[
  {
    "path": ".babelrc",
    "content": "{\n    \"presets\": [\"@babel/preset-env\"],\n    \"plugins\": [\n        \"@babel/plugin-transform-runtime\",\n        \"@babel/plugin-transform-object-assign\",\n        \"@babel/plugin-transform-modules-commonjs\",\n        \"@babel/plugin-syntax-dynamic-import\",\n        \"@babel/plugin-proposal-object-rest-spread\",\n        \"@babel/plugin-proposal-class-properties\",\n        \"@babel/plugin-proposal-private-methods\"\n    ],\n    \"env\": {\n        \"test\": {\n            \"plugins\": [\"dynamic-import-node\"]\n        }\n    }\n}\n"
  },
  {
    "path": ".eslintignore",
    "content": "src/playground/blocks/hardware/**/*.js\nextern\ntest\ntest_util\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n    \"parser\": \"@babel/eslint-parser\",\n    \"plugins\": [\"prettier\"],\n    \"extends\": [\"plugin:prettier/recommended\"],\n    \"overrides\": [\n        {\n            \"files\": [\"*.ts\"],\n            \"parser\": \"@typescript-eslint/parser\",\n            \"rules\": {\n                \"no-unused-vars\": \"off\",\n            },\n        },\n        {\n            \"files\": [\"*.d.ts\"],\n            \"parser\": \"@typescript-eslint/parser\",\n            \"rules\": {\n                \"no-unused-vars\": \"off\",\n                \"no-var\": \"off\",\n                \"no-useless-constructor\": \"off\",\n            },\n        },\n    ],\n    \"env\": {\n        \"es6\": true,\n        \"browser\": true,\n        \"jquery\": true,\n    },\n    \"parserOptions\": {\n        \"requireConfigFile\": false,\n        \"ecmaVersion\": 2020,\n        \"sourceType\": \"module\",\n        \"ecmaFeatures\": {\n            \"jsx\": true,\n        },\n    },\n    \"rules\": {\n        \"prefer-const\": \"warn\",\n        \"no-var\": \"warn\",\n        \"eqeqeq\": 0,\n        \"no-const-assign\": \"error\",\n        \"no-new-object\": \"warn\",\n        \"object-shorthand\": \"warn\",\n        \"no-prototype-builtins\": \"warn\",\n        \"no-array-constructor\": \"warn\",\n        \"prefer-template\": \"warn\",\n        \"no-useless-escape\": \"warn\",\n        \"wrap-iife\": [\"warn\", \"inside\"],\n        \"no-loop-func\": \"warn\",\n        \"no-new-func\": \"warn\",\n        \"prefer-rest-params\": \"warn\",\n        \"prefer-arrow-callback\": \"warn\",\n        \"template-curly-spacing\": \"warn\",\n        \"no-param-reassign\": [\"warn\", { \"props\": false }],\n        \"prefer-spread\": \"warn\",\n        \"arrow-spacing\": \"warn\",\n        \"arrow-body-style\": [\"warn\", \"as-needed\"],\n        \"no-useless-constructor\": \"warn\",\n        \"no-dupe-class-members\": \"warn\",\n        \"no-duplicate-imports\": \"warn\",\n        \"dot-notation\": \"warn\",\n        \"no-undef\": [\"warn\", { \"typeof\": true }],\n        \"one-var\": [\"warn\", \"never\"],\n        \"no-multi-assign\": \"warn\",\n        \"no-case-declarations\": \"warn\",\n        \"no-nested-ternary\": \"warn\",\n        \"no-unneeded-ternary\": \"warn\",\n        \"brace-style\": \"warn\",\n        \"space-before-blocks\": [\n            \"warn\",\n            { \"functions\": \"always\", \"keywords\": \"always\", \"classes\": \"always\" },\n        ],\n        \"space-infix-ops\": \"warn\",\n        \"eol-last\": [\"warn\", \"always\"],\n        \"no-whitespace-before-property\": \"warn\",\n        \"padded-blocks\": [\"warn\", \"never\"],\n        \"space-in-parens\": [\"warn\", \"never\"],\n        \"array-bracket-spacing\": [\"warn\", \"never\"],\n        \"object-curly-spacing\": [\"warn\", \"always\"],\n        \"max-len\": [\"warn\", { \"code\": 100 }],\n        \"comma-style\": [\"warn\", \"last\"],\n        \"semi\": [\"warn\"],\n        \"radix\": \"warn\",\n        \"camelcase\": [\"warn\", { \"properties\": \"never\" }],\n        \"new-cap\": [\"warn\", { \"capIsNewExceptionPattern\": \"^Entry.\" }],\n        \"curly\": \"warn\",\n        \"keyword-spacing\": \"warn\",\n    },\n    \"globals\": {\n        \"$\": true,\n        \"_\": true,\n        \"arcon\": true,\n        \"goog\": true,\n        \"acorn\": true,\n        \"createjs\": true,\n        \"Entry\": true,\n        \"filbert\": true,\n        \"Blockly\": true,\n        \"BigNumber\": true,\n        \"Lang\": true,\n        \"context\": true,\n        \"popup\": true,\n        \"WebFont\": true,\n        \"CanvasInput\": true,\n        \"EntryStatic\": true,\n        \"EaselHandle\": true,\n        \"ndgmr\": true,\n        \"Ntry\": true,\n        \"Snap\": true,\n        \"mina\": true,\n        \"Touch\": true,\n        \"io\": true,\n        \"LC\": true,\n        \"ActiveXObject\": true,\n        \"CodeMirror\": true,\n        \"entrylms\": true,\n        \"require\": true,\n        \"module\": true,\n        \"Symbol\": true,\n        \"process\": true,\n    },\n}\n"
  },
  {
    "path": ".github/pr-labeler.yml",
    "content": "feature: feature/*\nsecurity: security/*\nissue: [issue/*, Issue/*]\nhotfix: hotfix/*\n"
  },
  {
    "path": ".github/workflows/build-and-deploy.yml",
    "content": "name: 'build-and-deploy'\non:\n    push:\n        branches:\n            - 'deploy/**'\n            - master\n            - develop-hw\n            - develop2\n            - develop\n\njobs:\n    build-and-deploy:\n        runs-on: ubuntu-latest\n        steps:\n            - uses: actions/checkout@v4\n            - name: Use Node.js 20.x\n              uses: actions/setup-node@v4\n              env:\n                  NODE_OPTIONS: '--max-old-space-size=4096'\n                  TOOL_NODE_FLAGS: '--max-old-space-size=4096'\n              with:\n                  node-version: 20\n            - uses: pnpm/action-setup@v3\n              name: Install pnpm\n              with:\n                  version: 9\n                  run_install: true\n            - name: entry build\n              env:\n                  NODE_OPTIONS: '--max-old-space-size=4096'\n                  TOOL_NODE_FLAGS: '--max-old-space-size=4096'\n              run: pnpm prod\n            - name: Define branch name\n              id: target_branch\n              shell: bash\n              run: echo \"##[set-output name=branch;]$(echo ${GITHUB_REF##*/})\"\n            - uses: haya14busa/action-cond@v1\n              id: deploy_branch\n              with:\n                  cond: ${{ steps.target_branch.outputs.branch == 'master' }}\n                  if_true: 'build'\n                  if_false: dist/${{ steps.target_branch.outputs.branch }}\n            - name: Execute build.sh\n              run: |\n                  sh ./scripts/build.sh\n            - name: Execute deploy.sh\n              run: |\n                  sh ./scripts/deploy.sh\n            - name: Push Changes into build branch\n              uses: ad-m/github-push-action@master\n              with:\n                  github_token: ${{ secrets.GITHUB_TOKEN }}\n                  force: true\n                  directory: ./build\n                  branch: ${{ steps.deploy_branch.outputs.value }}\n"
  },
  {
    "path": ".github/workflows/pull-request-workflow.yml",
    "content": "name: PR Workflow\non:\n  pull_request:\n    types: [opened, edited, synchronize]\n\njobs:\n  pr-labeler:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: TimonVS/pr-labeler-action@v3\n        with:\n          configuration-path: .github/pr-labeler.yml # optional, .github/pr-labeler.yml is the default value\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n  eslint:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install pnpm\n        uses: pnpm/action-setup@v3\n        with:\n          version: 9\n      - run: pnpm install\n      - uses: reviewdog/action-eslint@v1\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          reporter: github-pr-review\n          eslint_flags: '--ignore-pattern .eslintignore src/'\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: 'release'\non:\n    release:\n        types: [created]\n\njobs:\n    release:\n        runs-on: ubuntu-latest\n        steps:\n            - uses: actions/checkout@v4\n            - name: Install pnpm\n              uses: pnpm/action-setup@v3\n              with:\n                  version: 9\n            - uses: actions/setup-node@v4\n              with:\n                  node-version: '20'\n                  cache: 'pnpm'\n            - run: pnpm install\n            - run: pnpm prod\n            - uses: JS-DevTools/npm-publish@v3\n              with:\n                  token: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\n\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\nreports\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directory\n# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git\nnode_modules\n\n# external libraries\nextern/closure-library\n\n.DS_Store\n\n*.map\n\n.vscode/*\n.idea/\ndist/\n\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n    \"printWidth\": 100,\n    \"tabWidth\": 4,\n    \"singleQuote\": true,\n    \"trailingComma\": \"es5\",\n    \"bracketSpacing\": true,\n    \"semi\": true,\n    \"arrowParens\": \"always\",\n    \"endOfLine\": \"auto\"\n}\n"
  },
  {
    "path": "COPYING",
    "content": "   Copyright 2015 Entry Labs\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n   "
  },
  {
    "path": "Gruntfile.js",
    "content": "module.exports = function(grunt) {\n    'use strict';\n\n    const ClosureCompiler = require('google-closure-compiler').compiler;\n\n    grunt.initConfig({\n        concurrent: {\n            tasks: ['watch'],\n            options: {\n                logConcurrentOutput: true,\n            },\n        },\n        watch: {\n            test: {\n                files: ['test/**/*.js'],\n                tasks: ['karma'],\n            },\n            js: {\n                files: ['src/**'],\n                tasks: ['closureCompiler:targetName', 'karma', 'jshint', 'less'],\n            },\n        },\n        less: {\n            options: {\n                compress: false,\n            },\n            development: {\n                files: {\n                    'dist/entry.css': 'src/css/*.less',\n                },\n            },\n        },\n        jshint: {\n            all: ['src/**/*.js'],\n            options: {\n                jshintrc: true,\n                ignores: ['src/blocks/*.js'],\n            },\n        },\n        karma: {\n            options: {\n                frameworks: ['mocha', 'chai'],\n                files: [\n                    'http://ajax.aspnetcdn.com/ajax/jshint/r07/jshint.js',\n                    'test_util/*.js',\n                    'extern/lang/ko.js',\n                    'extern/blockly/blockly_compressed.js',\n                    'extern/util/static.js',\n                    'extern/util/filbert.js',\n                    'extern/util/bignumber.min.js',\n                    'node_modules/jquery/jquery.js',\n                    'node_modules/createjs-easeljs/lib/easeljs-0.8.2.min.js',\n                    'node_modules/createjs-soundjs/lib/soundjs-0.6.2.min.js',\n                    'node_modules/createjs-preloadjs/lib/preloadjs-0.6.2.min.js',\n                    'dist/entry.js',\n                    'src/workspace/block_entry.js',\n                ],\n            },\n            unit: {\n                configFile: 'karma.conf.js',\n                files: [{ src: ['test/**/*.js'] }],\n            },\n        },\n        closureCompiler: {\n            options: {\n                compilerFile: ClosureCompiler.COMPILER_PATH,\n                checkModified: true,\n                compilerOpts: {\n                    create_source_map: 'entry.js.map',\n                    compilation_level: 'SIMPLE_OPTIMIZATIONS',\n                    language_in: 'ECMASCRIPT5',\n                    language_out: 'ECMASCRIPT5',\n                    formatting: 'pretty_print',\n                },\n            },\n            targetName: {\n                src: ['src/entry.js', 'src/**/*.js', '!src/workspace/block_entry.js'],\n                dest: 'dist/entry.js',\n            },\n            dist: {\n                options: {\n                    compilerOpts: {\n                        compilation_level: 'SIMPLE_OPTIMIZATIONS',\n                        language_in: 'ECMASCRIPT5',\n                        language_out: 'ECMASCRIPT5',\n                    },\n                },\n                expand: false,\n                src: ['src/entry.js', 'src/**/*.js'],\n                dest: 'dist/entry.min.js',\n                ext: '.min.js',\n            },\n        },\n    });\n\n    // Load NPM tasks\n    grunt.loadNpmTasks('grunt-closure-tools');\n    grunt.loadNpmTasks('grunt-contrib-jshint');\n    grunt.loadNpmTasks('grunt-concurrent');\n    grunt.loadNpmTasks('grunt-contrib-watch');\n    grunt.loadNpmTasks('grunt-karma');\n    grunt.loadNpmTasks('grunt-contrib-less');\n\n    grunt.option('force', true);\n\n    // Default tasks.\n    grunt.registerTask('default', ['closureCompiler', 'karma', 'jshint', 'less']);\n\n    grunt.registerTask('development', [\n        'watch',\n        'closureCompiler:targetName',\n        'karma',\n        'concurrent',\n    ]);\n\n    grunt.registerTask('test', ['karma']);\n\n    grunt.registerTask('closure', ['closureCompiler']);\n\n    grunt.registerTask('build', ['closureCompiler', 'less']);\n};\n"
  },
  {
    "path": "Jenkinsfile",
    "content": "pipeline {\n  agent none\n  stages {\n    stage('EntryJS Test') {\n      when {\n        beforeAgent true\n        expression {\n          return env.CHANGE_ID\n        }\n      }\n      agent {\n        docker {\n          image 'node:8.11.3'\n        }\n      }\n      steps {\n        script {\n          sh \"npm prune\"\n          sh \"npm install\"\n          sh \"yarn test\"\n        }\n      }\n      post {\n        always {\n          junit 'reports/*.xml'\n        }\n      }\n    }\n    stage('SonarQube Analysis') {\n      when { \n        beforeAgent true\n        expression {\n          return env.CHANGE_ID\n        }\n      }\n      agent {\n        docker {\n          image 'maven:3-alpine'\n        }\n      }\n      steps {\n        script {\n          def scannerHome = tool \"sonarqube-scanner\";\n          withSonarQubeEnv(\"sonar\") {\n            sh \"${scannerHome}/bin/sonar-scanner \" +\n            \"-Dsonar.projectKey=entry.entryjs \" +\n            \"-Dsonar.projectName=entryjs \" +\n            \"-Dsonar.sourceEncoding=UTF-8 \" +\n            \"-Dsonar.analysis.mode=preview \" +\n            \"-Dsonar.github.repository=entrylabs/entryjs \" +\n            \"-Dsonar.github.endpoint=https://api.github.com \" +\n            \"-Dsonar.github.oauth=${GH_TOKEN} \" +\n            \"-Dsonar.issuesReport.console.enable=true \" +\n            \"-Dsonar.github.disableInlineComments=true \" +\n            \"-Dsonar.github.pullRequest=${env.CHANGE_ID} \" +\n            \"-Dsonar.sources=src \"\n          }\n        }\n      }\n    }\n    stage('SonarQube Scan') {\n      when {\n        beforeAgent true\n        allOf {\n          expression { BRANCH_NAME ==~ /(^master$)/ }\n          not { changeRequest() }\n        }\n      }\n      agent {\n        docker {\n          image 'maven:3-alpine'\n        }\n      }\n      steps {\n        script {\n          def scannerHome = tool \"sonarqube-scanner\";\n          withSonarQubeEnv(\"sonar\") {\n            sh \"${scannerHome}/bin/sonar-scanner \" +\n            \"-Dsonar.projectKey=entry.entryjs \" +\n            \"-Dsonar.projectName=entryjs \" +\n            \"-Dsonar.sourceEncoding=UTF-8 \" +\n            \"-Dsonar.sources=src \"\n          }\n        }\n      }\n    }\n    stage('EntryJS Deploy') {\n      when {\n        beforeAgent true\n        allOf {\n          expression { BRANCH_NAME ==~ /(^master$|^deploy\\/.*$)/ }\n          not { changeRequest() }\n        }\n      }\n      agent {\n        docker {\n          image 'node:8.11.3'\n        }\n      }\n      steps {\n        script {\n          sh '''npm prune\nnpm install\nchmod +x ./scripts/build.sh\nchmod +x ./scripts/deploy.sh\n./scripts/build.sh\n./scripts/deploy.sh'''\n        }\n      }\n    }\n  }\n  environment {\n    GH_REPO = 'https://github.com/entrylabs/entryjs.git'\n    GH_REF = 'github.com/entrylabs/entryjs.git'\n  }\n}"
  },
  {
    "path": "LICENSE",
    "content": "\n                                Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "NOTICE",
    "content": "EntryJS\nCopyright 2015 Entry Labs\n\n\nEntryJS project contains subcomponents with separate copyright notices and license terms. \nYour use of the source code for the these subcomponents is subject to the terms and conditions of the following licenses.\n\n\n=======================================================================\nBlockly (https://github.com/google/blockly)\n=======================================================================\n\n/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://developers.google.com/blockly/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n\n=======================================================================\nCollision-Detection-for-EaselJS (https://github.com/olsn/Collision-Detection-for-EaselJS)\n=======================================================================\n\nCopyright (c) 2013 Olaf Horstmann\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n=======================================================================\nCanvasInput (https://github.com/goldfire/CanvasInput)\n=======================================================================\n\n/*!\n *  CanvasInput v1.2.1\n *  http://goldfirestudios.com/blog/108/CanvasInput-HTML5-Canvas-Text-Input\n *\n *  (c) 2013-2015, James Simpson of GoldFire Studios\n *  goldfirestudios.com\n *\n *  MIT License\n */\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n=======================================================================\nContext.js (https://github.com/jakiestfu/Context.js)\n=======================================================================\n\n/*\n * Context.js\n * Copyright Jacob Kelley\n * MIT License\n *\n * Modified by Joshua Christman\n */\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README-en.md",
    "content": "# entryjs \nentryjs is an HTML5-based block coding library developed by entry.\nIf you access the [Entry](https://playentry.org) site, you can check the block coding environment using entryjs.\n\n## get started\nentryjs uses several open source libraries to handle HTML Canvas, audio, and vector images.\nAfter these libraries are loaded in the web project, entryjs should be loaded.\n\n### 3rd party library\n * [jQuery](http://jquery.com/download/) - 1.9.1\n * [jquery-ui](https://github.com/jquery/jquery-ui) - 1.10.4\n * [Underscore](https://github.com/jashkenas/underscore) - 1.8.3\n * [CreateJS](http://createjs.com/downloads)\n   * EaselJS - 0.8.0\n   * PreloadJS - 0.6.0\n   * SoundJS - 0.6.0\n * [Lodash](https://lodash.com/docs/4.17.15) - 4.17.10\n * [Velocity](https://github.com/julianshapiro/velocity) - ~1.2.3\n * [CodeMirror](https://codemirror.net) - 5.12.0\n * [Fuzzy](https://github.com/mattyork/fuzzy) - ~0.1.1\n * [Literallycanvas](https://github.com/entrylabs/literallycanvas) - entry version\n * [EntryTool](https://github.com/entrylabs/entry-tool) - entry version\n  All of these libraries are distributed as open source, You can download it yourself or install it using [npm](http://npmjs.org) or [bower](http://bower.io).\n\n###  JavaScript library\n \n```html\n<!--  third party libraries -->\n<script type=\"text/javascript\" src=\"${LIBDIR}/PreloadJS/lib/preloadjs-0.6.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/EaselJS/lib/easeljs-0.8.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/SoundJS/lib/soundjs-0.6.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/SoundJS/lib/flashaudioplugin-0.6.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/lodash/dist/lodash.min.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/jquery/jquery.min.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/jquery-ui/ui/minified/jquery-ui.min.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/velocity/velocity.min.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/lib/codemirror.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/addon/hint/show-hint.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/addon/lint/lint.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/addon/selection/active-line.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/mode/javascript/javascript.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/addon/hint/javascript-hint.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/fuzzy/lib/fuzzy.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/socket.io-client/socket.io.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/react/react.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/react/react-dom.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/entry-lms/dist/assets/app.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/literallycanvas-mobile/lib/js/literallycanvas.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/entry-tool/dist/entry-tool.js\"></script>\n\n<!-- Code included in the playentry server -->\n<script type=\"text/javascript\" src=\"https://playentry.org/js/jshint.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/js/textmode/python/python.js\"></script>\n\n<!-- library included in entryjs and entryjs -->\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/filbert.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/CanvasInput.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/ndgmr.Collision.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/handle.js\"></script>\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/bignumber.min.js\"></script>\n\n<!-- entryjs core / contains language and global settings -->\n<script type='text/javascript' src='${LIBDIR}/entryjs/extern/lang/ko.js'></script>\n<script type='text/javascript' src='${LIBDIR}/entryjs/extern/util/static.js'></script>\n<script type='text/javascript' src='${LIBDIR}/entryjs/dist/entry.min.js'></script>\n```\n\n###  entryjs stylesheet\nBasic styles related to block design are defined.\n```html\n<link rel='stylesheet'  href='${LIBDIR}/entryjs/dist/entry.css'>\n```\n\n### Entry Initialization (Inject Options)\n\nOnce you have loaded the necessary libraries and entryjs, you can inject the entryjs workspace using Javascript at a specific location in the current DOM.\n\n * Entry.init(domElement, initOptions);\n    ```html\n       <div id=\"workspace\"></div>\n    ```\n\n    ```javascript\n       var workspace = document.getElementById(\"workspace\");\n       var initOptions = {\n        type: 'workspace',\n        libDir: '/lib',\n        fonts: [{\n          name: '나눔고딕',\n          family: 'Nanum Gothic',\n          url: '/css/nanumgothic.css'\n        }]\n       };\n       Entry.init(workspace, initOptions);\n    ```\n * domElement : The DOM node into which the entry will be injected.\n * initOptions : Option value of entryjs workspace.\n   \n### initOptions\n All options except Workspace type and font information are optional and Boolean type. \n   \n * Required\n   - type: Workspace type. (workspace: creation environment, minimize: viewing environment)\n   - libDir:Third-party library repository. Library location including entryjs. (default: '/lib')\n   - fonts: Web font information\n   \n * choice\n   - projectsaveable: Whether the project can be saved (true)\n   - objectaddable: Whether objects can be added (true)\n   - objectEditable: Whether the object can be modified (true). Setting this value to false also sets objectAddable to false.\n   - objectdeletable: Whether the object can be deleted (true)\n   - soundeditable: Whether sound can be modified (true)\n   - pictureeditable: Whether the shape can be modified (true)\n   - sceneEditable: Whether the scene can be modified (true)\n   - functionEnable: Whether the function is available (true)\n   - messageEnable: signal available (true)\n   - variableEnable: Whether the variable is available (true)\n   - listEnable: list available (true)\n   - isForLecture: Lecture project or not (false)\n   - textCodingEnable: Whether entry python is available (true)\n   - hardwareEnable: Hardware availability (true)\n   \n * Web font information 정보\n    You can add one or more arrays of fonts to be used in the entry textbox and paint.\n    ```javascript\n      [{\n        name: 'Font name to display on screen',\n        family: 'font-family name',\n        url: 'Font definition file path'\n      }]\n    ```\n    \n    ```javascript\n    // 예시\n    [{\n      name: 'Nanum Gothic',\n      family: 'Nanum Gothic',\n      url: '/css/nanumgothic.css'\n    },\n    {\n      name: 'Nanum handwriting',\n      family: 'Nanum Pen Script',\n      url: '/css/nanumpenscript.css'\n    }]\n    ```\n   Free Korean web fonts can be downloaded from https://www.google.com/fonts/earlyaccess.\n\n### Entry.playground.setBlockMenu();\n Block menu reset\n    \n### Entry.loadProject(project);\n Load project. If the project argument is omitted, the default project is returned..\n\n### event. (Event description)\n * event listening\n ```javascript\n Entry.addEventListener(eventName, function);\n ```\n  - eventName: The name of the custom event you want to catch\n  - function: Function to be executed when the corresponding custom event occurs\n\n * event dispatch\n ```javascript\n Entry.dispatchEvent(eventName,params);\n ```\n  - eventName: The name of the event you want to trigger\n  - params: Parameters to be passed to the callback function listening for events\n\n * representative event\n  - run\n  - stop\n\n * user interaction\n  - keyPressed\n  - keyUpped\n  - canvasClick\n  - canvasClickCanceled\n  - entityClick\n  - entityClickCanceled\n  - stageMouseMove\n  - stageMouseOut\n\n * screen\n  - windowResized\n\n### Entry.Toast\n* Display notification messages at the bottom of the workspace\n - Entry.Toast.warning(title, message, auto-dospose); // caution\n - Entry.Toast.success(title, message, auto-dospose); // success\n - Entry.Toast.alert(title, message, auto-dospose); // warning\n\n### Block shape definition and running script.\n```\n${entryjs}/src/blocks/**/*\n```\n\n### block shape definition\n\nPlease refer to [EntryDocs - Write block specification](https://entrylabs.github.io/docs/guide/entryjs/2016-05-22-add_new_blocks.html).\n\n### Project Schema\n\n### save\n   :You can save essential information in JSON format using the Entry function below.\n     A saved project can be reloaded using Entry.loadProject(project) .\n    \n```javascript\n    var project = Entry.exportProject();\n```\n\n### detailed schema\n \n```javascript\n/**\n * MongoDB schema example.\n */\nvar ProjectSchema = new Schema({\n    speed: { // Execution frames per second\n        type: Number,\n        default: 60\n    },\n    objects: [ // object list\n        {\n            id: String, // Object ID. Unique.\n            name: String, // The object (or textbox title) name.\n            text: String, // text box content. (If objectType is textBox)\n            order: Number, // TODO\n            objectType: String, // object type. (sprite, textBox)\n            scene: String, // Scene ID. Unique.\n            active: { // whether the object is active\n                type: Boolean,\n                default: true\n            },\n            lock: { // object lock\n                type: Boolean,\n                default: false\n            },\n            rotateMethod: String, // rotation method (free, vertical, none)\n            entity: { // entity information\n                rotation: Number, // rotation\n                direction: Number, // direction\n                x: Number, // x coordinate\n                y: Number, // y coordinate\n                regX: Number, // horizontal center point\n                regY: Number, // vertical center point\n                scaleX: Number, // horizontal scale\n                scaleY: Number, // vertical scale\n                width: Number, // area\n                height: Number, // height\n                imageIndex: Number, // TODO\n                visible: Boolean, // screen display\n                colour: String, // text box font color \n                font: String, // text box font\n                bgColor: String, // text box background color\n                textAlign: Number, // textbox alignment\n                lineBreak: Boolean, // Whether text box line breaks\n                underLine: Boolean, // text box\n                strike: Boolean // text box underline\n            },\n            script: String, // block script\n            sprite: { // sprite information\n                name: String, // sprite name\n                pictures: [{ // shape list\n                    id: String, // Shape ID. Unique/\n                    name: String, // shape name\n                    fileurl: String, // shape image\n                    dimension: { // shape size\n                        width: Number,\n                        height: Number,\n                        scaleX: Number,\n                        scaleY: Number\n                    },\n                    scale: { // Magnification, reduction ratio (based on 100%)\n                        type: Number,\n                        default: 100\n                    }\n                }],\n                sounds: [{ // list of sounds\n                    id: String, // Sound ID. Unique.\n                    name: String, // name\n                    fileurl: String, // Sound file URL\n                    duration: Number // play time. (in seconds)\n                }]\n            },\n            selectedPictureId: String, // ID of the currently active shape\n            selectedSoundId: String // ID of currently active sound\n\n        }\n    ],\n    variables: [ // project variable\n        {\n            name: String, // variable name\n            variableType: String, // variable type. (General variable: variable, timer: timer, answer: answer, slide: slide, list: list)\n            id: String, // variable ID. Unique.\n            value: String, // variable value\n            minValue: Number, // minimum\n            maxValue: Number, // max value\n            visible: Boolean, // visibility on canvas\n            x: Number, // Converse position x coordinate\n            y: Number, // canvas position y-coordinate\n            width: Number, // width\n            height: Number, // height\n            isCloud: { // Shared variable or not\n                type: Boolean,\n                default: false\n            },\n            object: { // If it is a local variable, the ID of the object it refers to\n                type: String,\n                default: null\n            },\n            array: [{ // A list of values if the variable type is list\n                data: String //  value data\n            }]\n        }\n    ],\n    messages: [ // signal list\n        {\n            name: String, // signal name\n            id: String // Signal ID. Unique.\n        }\n    ],\n    functions: [ // function list\n        {\n            id: String, // function ID. Unique.\n            block: String, // function block information\n            content: String, // function execution information\n                id: String,\n                name: String\n            }]\n        }\n    ],\n    scenes: { // scene information\n        type: [ // scene list\n            {\n                name: String, // scene name\n                id: String // Scene ID. Unique.\n            }\n        ]\n    },\n});\n```\n\n### Sprite, Picture, Sound schema\n\n### Sprites\n```javascript\n            var SpriteSchema = new Schema({\n                name: String, // sprite name\n                pictures: [{ // shape list\n                    name: String, // shape name\n                    fileurl: String, // shape image\n                    dimension: { // shape size\n                        width: Number,\n                        height: Number\n                    }\n                }],\n                sounds: [{ // list of sounds\n                    name: String, // name\n                    fileurl: String, // Sound file URL\n                    duration: Number // play time. (in seconds)\n                }]\n            })\n```\n\n#### Pictures\n```javascript\n\tvar PictureSchema = new Schema({\n                    name: String, // shape name\n                    fileurl: String, // shape image\n                    dimension: { // shape size\n                        width: Number,\n                        height: Number\n                    }\n\t})\n```\n\n#### Sounds\n```javascript\n\tvar SoundSchema = new Schema({\n                    name: String, // name\n                    fileurl: String, // Sound file URL\n                    duration: Number // play time. (in seconds)\n\t})\n```\n\n\n## Copyright and License\n\nEntryJS Copyright (c) 2015 Entry Labs.\n\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License.  You may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# entryjs\r\n\r\nentryjs는 엔트리에서 개발한 HTML5 기반의 블록코딩 라이브러리 입니다.\r\n[엔트리](https://playentry.org) 사이트에 접속하시면 entryjs를 사용한 블록코딩 환경을 확인해 볼 수 있습니다.\r\n\r\n## 시작하기\r\n\r\nentryjs는 HTML Canvas와 오디오, 벡터 이미지등을 다루기 위해 몇가지 오픈소스 라이브러리들을 사용합니다.\r\n이 라이브러리들이 웹프로젝트에 먼저 로딩된 후에 entryjs를 로딩하여야 합니다.\r\n\r\n### 써드파티 라이브러리\r\n\r\n-   [jQuery](http://jquery.com/download/) - 1.9.1\r\n-   [jquery-ui](https://github.com/jquery/jquery-ui) - 1.10.4\r\n-   [Underscore](https://github.com/jashkenas/underscore) - 1.8.3\r\n-   [CreateJS](http://createjs.com/downloads)\r\n    -   EaselJS - 0.8.0\r\n    -   PreloadJS - 0.6.0\r\n    -   SoundJS - 0.6.0\r\n-   [Lodash](https://lodash.com/docs/4.17.15) - 4.17.10\r\n-   [Velocity](https://github.com/julianshapiro/velocity) - ~1.2.3\r\n-   [CodeMirror](https://codemirror.net) - 5.12.0\r\n-   [Fuzzy](https://github.com/mattyork/fuzzy) - ~0.1.1\r\n-   [Literallycanvas](https://github.com/entrylabs/literallycanvas) - entry version\r\n-   [EntryTool](https://github.com/entrylabs/entry-tool) - entry version\r\n    위 라이브러리들은 모두 오픈소스로 배포되며, 직접 다운로드 받거나 [npm](http://npmjs.org), [bower](http://bower.io)등을 이용해 설치할 수 있습니다.\r\n\r\n### 자바스크립트 라이브러리\r\n\r\n```html\r\n<!-- 써드파티 라이브러리들 -->\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/PreloadJS/lib/preloadjs-0.6.0.min.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/EaselJS/lib/easeljs-0.8.0.min.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/SoundJS/lib/soundjs-0.6.0.min.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/SoundJS/lib/flashaudioplugin-0.6.0.min.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/lodash/dist/lodash.min.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/jquery/jquery.min.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/jquery-ui/ui/minified/jquery-ui.min.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/velocity/velocity.min.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/lib/codemirror.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/addon/hint/show-hint.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/addon/lint/lint.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/addon/selection/active-line.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/mode/javascript/javascript.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/codemirror/addon/hint/javascript-hint.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/fuzzy/lib/fuzzy.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/socket.io-client/socket.io.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/react/react.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/react/react-dom.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entry-lms/dist/assets/app.js\"></script>\r\n<script\r\n    type=\"text/javascript\"\r\n    src=\"${LIBDIR}/literallycanvas-mobile/lib/js/literallycanvas.js\"\r\n></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entry-tool/dist/entry-tool.js\"></script>\r\n\r\n<!-- playentry 서버에 포함된 코드 -->\r\n<script type=\"text/javascript\" src=\"https://playentry.org/js/jshint.js\"></script>\r\n<script type=\"text/javascript\" src=\"https://playentry.org/js/textmode/python/python.js\"></script>\r\n\r\n<!-- entryjs 및 entryjs 에 포함된 라이브러리들 -->\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/filbert.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/CanvasInput.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/ndgmr.Collision.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/handle.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/bignumber.min.js\"></script>\r\n\r\n<!-- entryjs core / 언어 및 글로벌 설정이 포함되어있습니다. -->\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/lang/ko.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/extern/util/static.js\"></script>\r\n<script type=\"text/javascript\" src=\"${LIBDIR}/entryjs/dist/entry.min.js\"></script>\r\n```\r\n\r\n### entryjs 스타일시트\r\n\r\n블록 디자인과 관련된 기본적인 스타일들이 정의되어 있습니다.\r\n\r\n```html\r\n<link rel=\"stylesheet\" href=\"${LIBDIR}/entryjs/dist/entry.css\" />\r\n```\r\n\r\n### 엔트리 초기화 (Inject Options)\r\n\r\n필요한 라이브러리와 entryjs를 로딩하였으면 현재 DOM의 특정 위치에 Javascript를 이용해 entryjs workspace를 주입할 수 있습니다.\r\n\r\n-   Entry.init(domElement, initOptions);\r\n\r\n    ```html\r\n    <div id=\"workspace\"></div>\r\n    ```\r\n\r\n    ```javascript\r\n    var workspace = document.getElementById('workspace');\r\n    var initOptions = {\r\n        type: 'workspace',\r\n        libDir: '/lib',\r\n        fonts: [\r\n            {\r\n                name: '나눔고딕',\r\n                family: 'Nanum Gothic',\r\n                url: '/css/nanumgothic.css',\r\n            },\r\n        ],\r\n    };\r\n    Entry.init(workspace, initOptions);\r\n    ```\r\n\r\n-   domElement : Entry가 Inject될 DOM 노드.\r\n-   initOptions : entryjs workspace의 옵션값.\r\n\r\n### initOptions\r\n\r\nWorkspace 타입과 폰트정보를 제외한 모든 옵션은 선택사항이며 Boolean 타입입니다.\r\n\r\n-   필수항목\r\n\r\n    -   type: 워크스페이스 타입. (workspace: 만들기 환경, minimize: 구경하기 환경)\r\n    -   libDir: 써드파티 라이브러리 저장소. entryjs를 포함한 Library 위치. (기본값: '/lib')\r\n    -   fonts: 웹폰트 정보\r\n\r\n-   선택항목\r\n\r\n    -   projectsaveable: 프로젝트 저장가능 여부 (true)\r\n    -   objectaddable: 오브젝트 추가가능 여부 (true)\r\n    -   objectEditable: 오브젝트 수정가능 여부 (true). 이값을 false로 세팅하면 objectAddable도 false가 된다.\r\n    -   objectdeletable: 오브젝트 삭제가능 여부 (true)\r\n    -   soundeditable: 소리 수정가능 여부 (true)\r\n    -   pictureeditable: 모양 수정가능 여부 (true)\r\n    -   sceneEditable: 장면 수정가능 여부 (true)\r\n    -   functionEnable: 함수 사용가능 여부 (true)\r\n    -   messageEnable: 신호 사용가능 여부 (true)\r\n    -   variableEnable: 변수 사용가능 여부 (true)\r\n    -   listEnable: 리스트 사용가능 여부 (true)\r\n    -   isForLecture: 강의용 프로젝트 여부 (false)\r\n    -   textCodingEnable: 엔트리 파이선 사용가능 여부 (true)\r\n    -   hardwareEnable: 하드웨어 사용가능 여부 (true)\r\n\r\n-   웹폰트 정보\r\n    엔트리 글상자와 그림판에서 사용할 폰트들을 하나 이상 배열로 추가할 수 있습니다.\r\n    ```javascript\r\n    [\r\n        {\r\n            name: '화면에 표시할 폰트 이름',\r\n            family: 'font-family 이름',\r\n            url: '폰트 정의파일 경로',\r\n        },\r\n    ];\r\n    ```\r\n    ```javascript\r\n    // 예시\r\n    [\r\n        {\r\n            name: '나눔고딕',\r\n            family: 'Nanum Gothic',\r\n            url: '/css/nanumgothic.css',\r\n        },\r\n        {\r\n            name: '나눔필기체',\r\n            family: 'Nanum Pen Script',\r\n            url: '/css/nanumpenscript.css',\r\n        },\r\n    ];\r\n    ```\r\n    무료 한글 웹폰트는 https://www.google.com/fonts/earlyaccess 에서 다운로드 하실 수 있습니다.\r\n\r\n### Entry.playground.setBlockMenu();\r\n\r\n블록메뉴 초기화\r\n\r\n### Entry.loadProject(project);\r\n\r\n프로젝트 불러오기. project 인자를 생략할 경우 기본 프로젝트를 리턴합니다.\r\n\r\n### 이벤트. (Event description)\r\n\r\n-   event listening\r\n\r\n```javascript\r\nEntry.addEventListener(eventName, function);\r\n```\r\n\r\n-   eventName: 캐치하고 싶은 커스텀 이벤트의 이름\r\n-   function: 해당 커스텀 이벤트가 발생했을 경우 실행 될 함수\r\n\r\n*   event dispatch\r\n\r\n```javascript\r\nEntry.dispatchEvent(eventName, params);\r\n```\r\n\r\n-   eventName: 발생 시키고 싶은 이벤트의 이름\r\n-   params: 이벤트를 리스닝 하고 있는 콜백함수에 넘겨줄 파라미터\r\n\r\n*   대표적인 이벤트\r\n\r\n-   run\r\n-   stop\r\n\r\n*   유저 인터랙션\r\n\r\n-   keyPressed\r\n-   keyUpped\r\n-   canvasClick\r\n-   canvasClickCanceled\r\n-   entityClick\r\n-   entityClickCanceled\r\n-   stageMouseMove\r\n-   stageMouseOut\r\n\r\n*   화면\r\n\r\n-   windowResized\r\n\r\n### Entry.Toast\r\n\r\n-   워크스페이스 하단에 알림 메시지 표시\r\n\r\n*   Entry.Toast.warning(title, message, auto-dospose); // 주의\r\n*   Entry.Toast.success(title, message, auto-dospose); // 성공\r\n*   Entry.Toast.alert(title, message, auto-dospose); // 경고\r\n\r\n### 블록 모양 정의와 실행 스크립트.\r\n\r\n```\r\n${entryjs}/src/blocks/**/*\r\n```\r\n\r\n### 블록 모양 정의\r\n\r\n[EntryDocs - 블록 명세 작성](https://entrylabs.github.io/docs/guide/entryjs/2016-05-22-add_new_blocks.html) 을 참고해주세요.\r\n\r\n### 프로젝트 (Project Schema)\r\n\r\n### 저장\r\n\r\n: 아래의 Entry 함수를 이용해 필수정보들을 JSON형태로 저장할 수 있습니다.\r\n저장된 프로젝트는 Entry.loadProject(project) 를 이용해 다시 로드할 수 있습니다.\r\n\r\n```javascript\r\nvar project = Entry.exportProject();\r\n```\r\n\r\n### 상세 스키마\r\n\r\n```javascript\r\n/**\r\n * MongoDB 스키마 예제.\r\n */\r\nvar ProjectSchema = new Schema({\r\n    speed: { // 초당 실행 프레임수\r\n        type: Number,\r\n        default: 60\r\n    },\r\n    objects: [ // 오브젝트 목록\r\n        {\r\n            id: String, // 오브젝트 ID. Unique.\r\n            name: String, // 오브젝트(또는 글상자 제목) 이름.\r\n            text: String, // 글상자 내용. (objectType이 textBox일 경우)\r\n            order: Number, // TODO\r\n            objectType: String, // 오브젝트 유형. (sprite, textBox)\r\n            scene: String, // 장면 ID. Unique.\r\n            active: { // 오브젝트 활성화 여부\r\n                type: Boolean,\r\n                default: true\r\n            },\r\n            lock: { // 오브젝트 잠금 여부\r\n                type: Boolean,\r\n                default: false\r\n            },\r\n            rotateMethod: String, // 회전방식. (free, vertical, none)\r\n            entity: { // 엔티티 정보\r\n                rotation: Number, // 회전\r\n                direction: Number, // 방향\r\n                x: Number, // x 좌표\r\n                y: Number, // y 좌표\r\n                regX: Number, // 가로 중심점\r\n                regY: Number, // 세로 중심점\r\n                scaleX: Number, // 가로 배율\r\n                scaleY: Number, // 세로 배율\r\n                width: Number, // 넓이\r\n                height: Number, // 높이\r\n                imageIndex: Number, // TODO\r\n                visible: Boolean, // 화면표시 여부\r\n                colour: String, // 글상자 폰트색깔\r\n                font: String, // 글상자 폰트\r\n                bgColor: String, // 글상자 배경색깔\r\n                textAlign: Number, // 글상자 정렬\r\n                lineBreak: Boolean, // 글상자 줄바꿈 여부\r\n                underLine: Boolean, // 글상자\r\n                strike: Boolean // 글상자 밑줄\r\n            },\r\n            script: String, // 블록 스크립트\r\n            sprite: { // 스프라이트 정보\r\n                name: String, // 스프라이트 이름\r\n                pictures: [{ // 모양 목록\r\n                    id: String, // 모양 ID. Unique/\r\n                    name: String, // 모양 이름\r\n                    fileurl: String, // 모양 이미지\r\n                    dimension: { // 모양 크기\r\n                        width: Number,\r\n                        height: Number,\r\n                        scaleX: Number,\r\n                        scaleY: Number\r\n                    },\r\n                    scale: { // 확대, 축소 비율(100% 기준)\r\n                        type: Number,\r\n                        default: 100\r\n                    }\r\n                }],\r\n                sounds: [{ // 소리 목록\r\n                    id: String, // 소리 ID. Unique.\r\n                    name: String, // 이름\r\n                    fileurl: String, // 사운드 파일 URL\r\n                    duration: Number // 재생시간. (초단위)\r\n                }]\r\n            },\r\n            selectedPictureId: String, // 현재 활성화된 모양의 ID\r\n            selectedSoundId: String // 현재 활성화된 소리의 ID\r\n\r\n        }\r\n    ],\r\n    variables: [ // 프로젝트 변수\r\n        {\r\n            name: String, // 변수명\r\n            variableType: String, // 변수형. (일반변수: variable, 타이머: timer, 대답: answer, 슬라이드: slide, 리스트: list)\r\n            id: String, // 변수ID. Unique.\r\n            value: String, // 변수 값\r\n            minValue: Number, // 최소값\r\n            maxValue: Number, // 최대값\r\n            visible: Boolean, // 캔버스에 표시여부\r\n            x: Number, // 컨버스 위치 x좌표\r\n            y: Number, // 캔버스 위치 y좌표\r\n            width: Number, // 넓이\r\n            height: Number, // 높이\r\n            isCloud: { // 공유 변수 여부\r\n                type: Boolean,\r\n                default: false\r\n            },\r\n            object: { // 지역변수일 경우 참조하는 오브젝트 ID\r\n                type: String,\r\n                default: null\r\n            },\r\n            array: [{ // 변수형이 list일 경우 값 목록\r\n                data: String // 값 데이터\r\n            }]\r\n        }\r\n    ],\r\n    messages: [ // 신호 목록\r\n        {\r\n            name: String, // 신호명\r\n            id: String // 신호 ID. Unique.\r\n        }\r\n    ],\r\n    functions: [ // 함수 목록\r\n        {\r\n            id: String, // 함수 ID. Unique.\r\n            block: String, // 함수 블록 정보\r\n            content: String, // 함수 실행 정보\r\n                id: String,\r\n                name: String\r\n            }]\r\n        }\r\n    ],\r\n    scenes: { // 장면 정보\r\n        type: [ // 장면 목록\r\n            {\r\n                name: String, // 장면 이름\r\n                id: String // 장면 ID. Unique.\r\n            }\r\n        ]\r\n    },\r\n});\r\n```\r\n\r\n### Sprite, Picture, Sound schema\r\n\r\n### 스프라이트\r\n\r\n```javascript\r\nvar SpriteSchema = new Schema({\r\n    name: String, // 스프라이트 이름\r\n    pictures: [\r\n        {\r\n            // 모양 목록\r\n            name: String, // 모양 이름\r\n            fileurl: String, // 모양 이미지\r\n            dimension: {\r\n                // 모양 크기\r\n                width: Number,\r\n                height: Number,\r\n            },\r\n        },\r\n    ],\r\n    sounds: [\r\n        {\r\n            // 소리 목록\r\n            name: String, // 이름\r\n            fileurl: String, // 사운드 파일 URL\r\n            duration: Number, // 재생시간. (초단위)\r\n        },\r\n    ],\r\n});\r\n```\r\n\r\n#### 모양\r\n\r\n```javascript\r\nvar PictureSchema = new Schema({\r\n    name: String, // 모양 이름\r\n    fileurl: String, // 모양 이미지\r\n    dimension: {\r\n        // 모양 크기\r\n        width: Number,\r\n        height: Number,\r\n    },\r\n});\r\n```\r\n\r\n#### 소리\r\n\r\n```javascript\r\nvar SoundSchema = new Schema({\r\n    name: String, // 이름\r\n    fileurl: String, // 사운드 파일 URL\r\n    duration: Number, // 재생시간. (초단위)\r\n});\r\n```\r\n\r\n## Copyright and License\r\n\r\nEntryJS Copyright (c) 2015 Entry Labs.\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at\r\n\r\n    http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.\r\n"
  },
  {
    "path": "contributing.md",
    "content": "#### 업체PR 가이드\n\n하드웨어 업체에서는\n\nentryjs 레포지토리에서 Pull Request를 보내실때 \n\ndevleop-hw브랜치로 보내주시기 바랍니다.\n\n기타 다른브랜치에 PR보내시면 Reject사유가 될수 있습니다.\n\n"
  },
  {
    "path": "example/example.ejs",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n        <meta charset=\"utf-8\" />\n        <meta\n            name=\"viewport\"\n            content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n        />\n        <title><%= htmlWebpackPlugin.options.title %></title>\n        <% for (var css in htmlWebpackPlugin.files.css) { %>\n        <link href=\"<%= htmlWebpackPlugin.files.css[css] %>\" rel=\"stylesheet\" />\n        <% } %>\n        <link href=\"https://playentry.org/lib/entry-tool/dist/entry-tool.css\" rel=\"stylesheet\" />\n        <link href=\"https://playentry.org/lib/entry-lms/dist/assets/app.css\" rel=\"stylesheet\" />\n    </head>\n\n    <body>\n        <section style=\"height: 42px;\">\n            <input type=\"file\" id=\"litemodule\" />\n            <input type=\"text\" id=\"litemodulename\" />\n            <button style=\"border: 1px solid black\" onclick=\"handleUpdate()\">\n                apply\n            </button>\n            <button style=\"border: 1px solid black\" onclick=\"changeWorkspaceMode('block')\">\n                Block Mode\n            </button>\n            <button style=\"border: 1px solid black\" onclick=\"changeWorkspaceMode('python')\">\n                Python Mode\n            </button>\n        </section>\n        <div id=\"workspace\"></div>\n\n        <!--language-->\n        <script src=\"../extern/lang/ko.js\"></script>\n\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/PreloadJS/lib/preloadjs-0.6.0.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/EaselJS/lib/easeljs-0.8.0.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/SoundJS/lib/soundjs-0.6.0.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/SoundJS/lib/flashaudioplugin-0.6.0.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/lodash/dist/lodash.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/jquery/jquery.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/jquery-ui/ui/minified/jquery-ui.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/velocity/velocity.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/codemirror/lib/codemirror.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/codemirror/addon/hint/show-hint.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/codemirror/addon/lint/lint.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/codemirror/addon/selection/active-line.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/codemirror/mode/javascript/javascript.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/codemirror/addon/hint/javascript-hint.js\"\n        ></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/js/jshint.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/fuzzy/lib/fuzzy.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/js/ws/python.js\"></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/entry-js/extern/util/filbert.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/entry-js/extern/util/CanvasInput.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/entry-js/extern/util/ndgmr.Collision.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/entry-js/extern/util/handle.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/entry-js/extern/util/bignumber.min.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/socket.io-client/socket.io.js\"\n        ></script>\n        <script type=\"text/javascript\" src=\"https://unpkg.com/react@18/umd/react.production.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://unpkg.com/react-dom@18/umd/react-dom.production.min.js\"></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/entry-lms/dist/assets/app.js\"\n        ></script>\n        <script src=\"../extern/util/static.js\"></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/entry-tool/dist/entry-tool.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://playentry.org/lib/entry-paint/dist/static/js/entry-paint.js\"\n        ></script>\n        <script\n            type=\"text/javascript\"\n            src=\"https://entry-cdn.pstatic.net/external/sound/sound-editor.js?v=240130-174210\"\n        ></script>\n        <script \n            type=\"text/javascript\" \n            src=\"https://entry-cdn.pstatic.net/module/legacy-video/index.js?v=241031-202112\"\n        ></script>\n\n\n        <% for (var chunk in htmlWebpackPlugin.files.js) { %>\n        <script src=\"<%= htmlWebpackPlugin.files.js[chunk] %>\"></script>\n        <% } %>\n\n        <script>\n            function handleUpdate() {\n                const file = document.getElementById('litemodule').files[0];\n                const name = document.getElementById('litemodulename').value;\n                Entry.loadLiteTestModule(file, name);\n            }\n\n            function changeWorkspaceMode(mode) {\n                const option = {};\n\n                if (mode === 'block') {\n                    option.boardType = Entry.Workspace.MODE_BOARD;\n                    option.textType = -1;\n                } else {\n                    option.boardType = Entry.Workspace.MODE_VIMBOARD;\n                    option.textType = Entry.Vim.TEXT_TYPE_PY;\n                    option.runType = Entry.Vim.WORKSPACE_MODE;\n                }\n\n                const workspace = Entry.getMainWS();\n\n                if (workspace) {\n                    workspace.setMode(option);\n                } else {\n                    console.error('entry workspace not found!');\n                }\n            }\n        </script>\n        <!--main script-->\n        <script>\n            window.PUBLIC_PATH_FOR_ENTRYJS = 'lib/entry-js/dist/';\n            $(document).ready(function() {\n                var initOption = {\n                    libDir: '',\n                    entryDir: '',\n                    type: 'workspace',\n                    textCodingEnable: true,\n                };\n                Entry.creationChangedEvent = new Entry.Event(window);\n                Entry.init(document.getElementById('workspace'), initOption);\n                Entry.loadProject();\n            });\n        </script>\n    </body>\n</html>\n"
  },
  {
    "path": "example/example_mini.ejs",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n    <head>\n        <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n        <meta charset=\"utf-8\" />\n        <meta\n            name=\"viewport\"\n            content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n        />\n        <title><%= htmlWebpackPlugin.options.title %></title>\n        <% for (var css in htmlWebpackPlugin.files.css) { %>\n        <link href=\"<%= htmlWebpackPlugin.files.css[css] %>\" rel=\"stylesheet\" />\n        <% } %>\n        <link href=\"https://playentry.org/lib/entry-tool/dist/entry-tool.css\" rel=\"stylesheet\"/>\n    </head>\n\n    <body>\n        <section class=\"wrapper\">\n            <div id=\"workspace\"></div>\n        </section>\n\n        <!--language-->\n        <script src=\"../extern/lang/ko.js\"></script>\n\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/PreloadJS/lib/preloadjs-0.6.0.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/EaselJS/lib/easeljs-0.8.0.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/SoundJS/lib/soundjs-0.6.0.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/SoundJS/lib/flashaudioplugin-0.6.0.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/lodash/dist/lodash.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/jquery/jquery.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/jquery-ui/ui/minified/jquery-ui.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/velocity/velocity.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/lib/codemirror.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/addon/hint/show-hint.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/addon/lint/lint.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/addon/selection/active-line.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/mode/javascript/javascript.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/addon/hint/javascript-hint.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/js/jshint.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/fuzzy/lib/fuzzy.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/js/textmode/python/python.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/filbert.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/CanvasInput.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/ndgmr.Collision.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/handle.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/bignumber.min.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/socket.io-client/socket.io.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/react/react.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/react/react-dom.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-lms/dist/assets/app.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/literallycanvas-mobile/lib/js/literallycanvas.js\"></script>\n        <script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-tool/dist/entry-tool.js\"></script>\n\n        <script src=\"../extern/util/static_mini.js\"></script>\n        <% for (var chunk in htmlWebpackPlugin.files.chunks) { %>\n        <script src=\"<%= htmlWebpackPlugin.files.chunks[chunk].entry %>\"></script>\n        <% } %>\n        <!--main script-->\n        <script>\n            window.PUBLIC_PATH_FOR_ENTRYJS = 'lib/entry-js/dist/';\n            $(document).ready(function() {\n                var isMiniMode = true;\n                var lastHwConnected = false;\n                var hwCategoryList = EntryStatic.hwCategoryList;\n                var initOption = {\n                    type: 'workspace',\n                };\n                initOption = $.extend(initOption, EntryStatic.initOptions);\n                Entry.init(document.getElementById('workspace'), initOption);\n                Entry.loadProject();\n\n                Entry.addEventListener('hwChanged', function() {\n                    if (\n                        (Entry.hw.programConnected && Entry.hw.hwModule && lastHwConnected) ||\n                        !isMiniMode\n                    ) {\n                        return;\n                    }\n                    if (Entry.hw.programConnected && Entry.hw.hwModule) {\n                        if (EntryStatic.hwMiniSupportList.indexOf(Entry.hw.hwModule.name) > -1) {\n                            hwCategoryList.forEach(function(categoryName) {\n                                Entry.playground.blockMenu.unbanCategory(categoryName);\n                            });\n                            Entry.playground.blockMenu.banCategory('arduino');\n                            Entry.playground.blockMenu.banCategory('hw_robot');\n                        } else {\n                            hwCategoryList.forEach(function(categoryName) {\n                                Entry.playground.blockMenu.banCategory(categoryName);\n                            });\n                            Entry.playground.blockMenu.banCategory('hw_robot');\n                            Entry.playground.blockMenu.unbanCategory('arduino');\n                        }\n                        lastHwConnected = true;\n                    } else {\n                        hwCategoryList.forEach(function(categoryName) {\n                            Entry.playground.blockMenu.banCategory(categoryName);\n                        });\n                        Entry.playground.blockMenu.banCategory('arduino');\n                        Entry.playground.blockMenu.unbanCategory('hw_robot');\n                        lastHwConnected = false;\n                    }\n                });\n            });\n        </script>\n    </body>\n</html>\n"
  },
  {
    "path": "example/example_webgl.ejs",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta charset=\"utf-8\" />\n    <meta\n            name=\"viewport\"\n            content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\"\n    />\n    <title><%= htmlWebpackPlugin.options.title %></title>\n    <% for (var css in htmlWebpackPlugin.files.css) { %>\n        <link href=\"<%= htmlWebpackPlugin.files.css[css] %>\" rel=\"stylesheet\" />\n    <% } %>\n    <link href=\"https://playentry.org/lib/entry-tool/dist/entry-tool.css\" rel=\"stylesheet\"/>\n</head>\n\n<body>\n<section class=\"wrapper\">\n    <div id=\"workspace\"></div>\n</section>\n\n<!--language-->\n<script src=\"../extern/lang/ko.js\"></script>\n\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/PreloadJS/lib/preloadjs-0.6.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/EaselJS/lib/easeljs-0.8.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/SoundJS/lib/soundjs-0.6.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/SoundJS/lib/flashaudioplugin-0.6.0.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/lodash/dist/lodash.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/jquery/jquery.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/jquery-ui/ui/minified/jquery-ui.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/velocity/velocity.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/lib/codemirror.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/addon/hint/show-hint.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/addon/lint/lint.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/addon/selection/active-line.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/mode/javascript/javascript.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/codemirror/addon/hint/javascript-hint.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/js/jshint.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/fuzzy/lib/fuzzy.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/js/textmode/python/python.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/filbert.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/CanvasInput.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/ndgmr.Collision.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/handle.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-js/extern/util/bignumber.min.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/socket.io-client/socket.io.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/react/react.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/react/react-dom.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-lms/dist/assets/app.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/literallycanvas-mobile/lib/js/literallycanvas.js\"></script>\n<script type=\"text/javascript\" src=\"https://playentry.org/lib/entry-tool/dist/entry-tool.js\"></script>\n<script type=\"text/javascript\" src=\"https://pixijs.download/v4.8.5/pixi.min.js\"></script>\n\n<script src=\"../extern/util/static.js\"></script>\n<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>\n    <script src=\"<%= htmlWebpackPlugin.files.chunks[chunk].entry %>\"></script>\n<% } %>\n<!--main script-->\n<script>\n    window.PUBLIC_PATH_FOR_ENTRYJS = 'lib/entry-js/dist/';\n    $(document).ready(function() {\n        var initOption = {\n            type: 'workspace',\n            useWebGL: '1',\n        };\n        Entry.init(document.getElementById('workspace'), initOption);\n        Entry.loadProject();\n    });\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "extern/blockly/.ropeproject/config.py",
    "content": "# The default ``config.py``\n\n\ndef set_prefs(prefs):\n    \"\"\"This function is called before opening the project\"\"\"\n\n    # Specify which files and folders to ignore in the project.\n    # Changes to ignored resources are not added to the history and\n    # VCSs.  Also they are not returned in `Project.get_files()`.\n    # Note that ``?`` and ``*`` match all characters but slashes.\n    # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'\n    # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'\n    # '.svn': matches 'pkg/.svn' and all of its children\n    # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'\n    # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'\n    prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',\n                                  '.hg', '.svn', '_svn', '.git']\n\n    # Specifies which files should be considered python files.  It is\n    # useful when you have scripts inside your project.  Only files\n    # ending with ``.py`` are considered to be python files by\n    # default.\n    #prefs['python_files'] = ['*.py']\n\n    # Custom source folders:  By default rope searches the project\n    # for finding source folders (folders that should be searched\n    # for finding modules).  You can add paths to that list.  Note\n    # that rope guesses project source folders correctly most of the\n    # time; use this if you have any problems.\n    # The folders should be relative to project root and use '/' for\n    # separating folders regardless of the platform rope is running on.\n    # 'src/my_source_folder' for instance.\n    #prefs.add('source_folders', 'src')\n\n    # You can extend python path for looking up modules\n    #prefs.add('python_path', '~/python/')\n\n    # Should rope save object information or not.\n    prefs['save_objectdb'] = True\n    prefs['compress_objectdb'] = False\n\n    # If `True`, rope analyzes each module when it is being saved.\n    prefs['automatic_soa'] = True\n    # The depth of calls to follow in static object analysis\n    prefs['soa_followed_calls'] = 0\n\n    # If `False` when running modules or unit tests \"dynamic object\n    # analysis\" is turned off.  This makes them much faster.\n    prefs['perform_doa'] = True\n\n    # Rope can check the validity of its object DB when running.\n    prefs['validate_objectdb'] = True\n\n    # How many undos to hold?\n    prefs['max_history_items'] = 32\n\n    # Shows whether to save history across sessions.\n    prefs['save_history'] = True\n    prefs['compress_history'] = False\n\n    # Set the number spaces used for indenting.  According to\n    # :PEP:`8`, it is best to use 4 spaces.  Since most of rope's\n    # unit-tests use 4 spaces it is more reliable, too.\n    prefs['indent_size'] = 4\n\n    # Builtin and c-extension modules that are allowed to be imported\n    # and inspected by rope.\n    prefs['extension_modules'] = []\n\n    # Add all standard c-extensions to extension_modules list.\n    prefs['import_dynload_stdmods'] = True\n\n    # If `True` modules with syntax errors are considered to be empty.\n    # The default value is `False`; When `False` syntax errors raise\n    # `rope.base.exceptions.ModuleSyntaxError` exception.\n    prefs['ignore_syntax_errors'] = False\n\n    # If `True`, rope ignores unresolvable imports.  Otherwise, they\n    # appear in the importing namespace.\n    prefs['ignore_bad_imports'] = False\n\n\ndef project_opened(project):\n    \"\"\"This function is called after opening the project\"\"\"\n    # Do whatever you like here!\n"
  },
  {
    "path": "extern/blockly/.ropeproject/globalnames",
    "content": "\u0002}q\u0001U\u0005build]q\u0002(U\u000eGen_compressedq\u0003U\u0006HEADERq\u0004U\fsearch_pathsq\u0005U\u000bimport_pathq\u0006U\bcalcdepsq\u0007U\u0010Gen_uncompressedq\bU\rGen_langfilesq\tes."
  },
  {
    "path": "extern/blockly/.ropeproject/history",
    "content": "\u0002]q\u0001(]q\u0002]q\u0003e."
  },
  {
    "path": "extern/blockly/.ropeproject/objectdb",
    "content": "\u0002}q\u0001."
  },
  {
    "path": "extern/blockly/blockly_compressed.js",
    "content": "// Do not edit this file; automatically generated by build.py.\n\"use strict\";\n\nvar COMPILED=!0,goog=goog||{};goog.global=this;goog.isDef=function(a){return void 0!==a};goog.exportPath_=function(a,b,c){a=a.split(\".\");c=c||goog.global;a[0]in c||!c.execScript||c.execScript(\"var \"+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&goog.isDef(b)?c[d]=b:c=c[d]?c[d]:c[d]={}};\ngoog.define=function(a,b){var c=b;COMPILED||(goog.global.CLOSURE_UNCOMPILED_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES,a)?c=goog.global.CLOSURE_UNCOMPILED_DEFINES[a]:goog.global.CLOSURE_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]));goog.exportPath_(a,c)};goog.DEBUG=!0;goog.LOCALE=\"en\";goog.TRUSTED_SITE=!0;goog.STRICT_MODE_COMPATIBLE=!1;goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG;\ngoog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING=!1;goog.provide=function(a){if(goog.isInModuleLoader_())throw Error(\"goog.provide can not be used within a goog.module.\");if(!COMPILED&&goog.isProvided_(a))throw Error('Namespace \"'+a+'\" already declared.');goog.constructNamespace_(a)};goog.constructNamespace_=function(a,b){if(!COMPILED){delete goog.implicitNamespaces_[a];for(var c=a;(c=c.substring(0,c.lastIndexOf(\".\")))&&!goog.getObjectByName(c);)goog.implicitNamespaces_[c]=!0}goog.exportPath_(a,b)};\ngoog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/;goog.module=function(a){if(!goog.isString(a)||!a||-1==a.search(goog.VALID_MODULE_RE_))throw Error(\"Invalid module identifier\");if(!goog.isInModuleLoader_())throw Error(\"Module \"+a+\" has been loaded incorrectly.\");if(goog.moduleLoaderState_.moduleName)throw Error(\"goog.module may only be called once per module.\");goog.moduleLoaderState_.moduleName=a;if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace \"'+a+'\" already declared.');delete goog.implicitNamespaces_[a]}};\ngoog.module.get=function(a){return goog.module.getInternal_(a)};goog.module.getInternal_=function(a){if(!COMPILED)return goog.isProvided_(a)?a in goog.loadedModules_?goog.loadedModules_[a]:goog.getObjectByName(a):null};goog.moduleLoaderState_=null;goog.isInModuleLoader_=function(){return null!=goog.moduleLoaderState_};\ngoog.module.declareLegacyNamespace=function(){if(!COMPILED&&!goog.isInModuleLoader_())throw Error(\"goog.module.declareLegacyNamespace must be called from within a goog.module\");if(!COMPILED&&!goog.moduleLoaderState_.moduleName)throw Error(\"goog.module must be called prior to goog.module.declareLegacyNamespace.\");goog.moduleLoaderState_.declareLegacyNamespace=!0};\ngoog.setTestOnly=function(a){if(goog.DISALLOW_TEST_ONLY_CODE)throw a=a||\"\",Error(\"Importing test-only code into non-debug environment\"+(a?\": \"+a:\".\"));};goog.forwardDeclare=function(a){};COMPILED||(goog.isProvided_=function(a){return a in goog.loadedModules_||!goog.implicitNamespaces_[a]&&goog.isDefAndNotNull(goog.getObjectByName(a))},goog.implicitNamespaces_={\"goog.module\":!0});\ngoog.getObjectByName=function(a,b){for(var c=a.split(\".\"),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]};\ngoog.addDependency=function(a,b,c,d){if(goog.DEPENDENCIES_ENABLED){var e;a=a.replace(/\\\\/g,\"/\");var f=goog.dependencies_;d&&\"boolean\"!==typeof d||(d=d?{module:\"goog\"}:{});for(var g=0;e=b[g];g++)f.nameToPath[e]=a,f.loadFlags[a]=d;for(d=0;b=c[d];d++)a in f.requires||(f.requires[a]={}),f.requires[a][b]=!0}};goog.ENABLE_DEBUG_LOADER=!0;goog.logToConsole_=function(a){goog.global.console&&goog.global.console.error(a)};\ngoog.require=function(a){if(!COMPILED){goog.ENABLE_DEBUG_LOADER&&goog.IS_OLD_IE_&&goog.maybeProcessDeferredDep_(a);if(goog.isProvided_(a))return goog.isInModuleLoader_()?goog.module.getInternal_(a):null;if(goog.ENABLE_DEBUG_LOADER){var b=goog.getPathFromDeps_(a);if(b)return goog.writeScripts_(b),null}a=\"goog.require could not find: \"+a;goog.logToConsole_(a);throw Error(a);}};goog.basePath=\"\";goog.nullFunction=function(){};\ngoog.abstractMethod=function(){throw Error(\"unimplemented abstract method\");};goog.addSingletonGetter=function(a){a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.LOAD_MODULE_USING_EVAL=!0;goog.SEAL_MODULE_EXPORTS=goog.DEBUG;goog.loadedModules_={};goog.DEPENDENCIES_ENABLED=!COMPILED&&goog.ENABLE_DEBUG_LOADER;goog.TRANSPILE=\"detect\";\ngoog.TRANSPILER=\"transpile.js\";\ngoog.DEPENDENCIES_ENABLED&&(goog.dependencies_={loadFlags:{},nameToPath:{},requires:{},visited:{},written:{},deferred:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return null!=a&&\"write\"in a},goog.findBasePath_=function(){if(goog.isDef(goog.global.CLOSURE_BASE_PATH))goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document.getElementsByTagName(\"SCRIPT\"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf(\"?\"),d=-1==d?c.length:d;if(\"base.js\"==\nc.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a,b){(goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_)(a,b)&&(goog.dependencies_.written[a]=!0)},goog.IS_OLD_IE_=!(goog.global.atob||!goog.global.document||!goog.global.document.all),goog.importProcessedScript_=function(a,b,c){goog.importScript_(\"\",'goog.retrieveAndExec_(\"'+a+'\", '+b+\", \"+c+\");\")},goog.queuedModules_=[],goog.wrapModule_=function(a,b){return goog.LOAD_MODULE_USING_EVAL&&goog.isDef(goog.global.JSON)?\n\"goog.loadModule(\"+goog.global.JSON.stringify(b+\"\\n//# sourceURL=\"+a+\"\\n\")+\");\":'goog.loadModule(function(exports) {\"use strict\";'+b+\"\\n;return exports});\\n//# sourceURL=\"+a+\"\\n\"},goog.loadQueuedModules_=function(){var a=goog.queuedModules_.length;if(0<a){var b=goog.queuedModules_;goog.queuedModules_=[];for(var c=0;c<a;c++)goog.maybeProcessDeferredPath_(b[c])}},goog.maybeProcessDeferredDep_=function(a){goog.isDeferredModule_(a)&&goog.allDepsAreAvailable_(a)&&(a=goog.getPathFromDeps_(a),goog.maybeProcessDeferredPath_(goog.basePath+\na))},goog.isDeferredModule_=function(a){var b=(a=goog.getPathFromDeps_(a))&&goog.dependencies_.loadFlags[a]||{};return a&&(\"goog\"==b.module||goog.needsTranspile_(b.lang))?goog.basePath+a in goog.dependencies_.deferred:!1},goog.allDepsAreAvailable_=function(a){if((a=goog.getPathFromDeps_(a))&&a in goog.dependencies_.requires)for(var b in goog.dependencies_.requires[a])if(!goog.isProvided_(b)&&!goog.isDeferredModule_(b))return!1;return!0},goog.maybeProcessDeferredPath_=function(a){if(a in goog.dependencies_.deferred){var b=\ngoog.dependencies_.deferred[a];delete goog.dependencies_.deferred[a];goog.globalEval(b)}},goog.loadModuleFromUrl=function(a){goog.retrieveAndExec_(a,!0,!1)},goog.writeScriptSrcNode_=function(a){goog.global.document.write('<script type=\"text/javascript\" src=\"'+a+'\">\\x3c/script>')},goog.appendScriptSrcNode_=function(a){var b=goog.global.document,c=b.createElement(\"script\");c.type=\"text/javascript\";c.src=a;c.defer=!1;c.async=!1;b.head.appendChild(c)},goog.writeScriptTag_=function(a,b){if(goog.inHtmlDocument_()){var c=\ngoog.global.document;if(!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING&&\"complete\"==c.readyState){if(/\\bdeps.js$/.test(a))return!1;throw Error('Cannot write \"'+a+'\" after document load');}if(void 0===b)if(goog.IS_OLD_IE_){var d=\" onreadystatechange='goog.onScriptLoad_(this, \"+ ++goog.lastNonModuleScriptIndex_+\")' \";c.write('<script type=\"text/javascript\" src=\"'+a+'\"'+d+\">\\x3c/script>\")}else goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING?goog.appendScriptSrcNode_(a):goog.writeScriptSrcNode_(a);else c.write('<script type=\"text/javascript\">'+\nb+\"\\x3c/script>\");return!0}return!1},goog.needsTranspile_=function(a){if(\"always\"==goog.TRANSPILE)return!0;if(\"never\"==goog.TRANSPILE)return!1;if(!goog.transpiledLanguages_){goog.transpiledLanguages_={es5:!0,es6:!0,\"es6-impl\":!0};try{goog.transpiledLanguages_.es5=eval(\"[1,].length!=1\"),eval('(()=>{\"use strict\";let a={};const X=class{constructor(){}x(z){return new Map([...arguments]).get(z[0])==3}};return new X().x([a,3])})()')&&(goog.transpiledLanguages_[\"es6-impl\"]=!1),eval('(()=>{\"use strict\";class X{constructor(){if(new.target!=String)throw 1;this.x=42}}let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof String))throw 1;for(const a of[2,3]){if(a==2)continue;function f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()==3}})()')&&\n(goog.transpiledLanguages_.es6=!1)}catch(b){}}return!!goog.transpiledLanguages_[a]},goog.transpiledLanguages_=null,goog.lastNonModuleScriptIndex_=0,goog.onScriptLoad_=function(a,b){\"complete\"==a.readyState&&goog.lastNonModuleScriptIndex_==b&&goog.loadQueuedModules_();return!0},goog.writeScripts_=function(a){function b(a){if(!(a in e.written||a in e.visited)){e.visited[a]=!0;if(a in e.requires)for(var f in e.requires[a])if(!goog.isProvided_(f))if(f in e.nameToPath)b(e.nameToPath[f]);else throw Error(\"Undefined nameToPath for \"+\nf);a in d||(d[a]=!0,c.push(a))}}var c=[],d={},e=goog.dependencies_;b(a);for(a=0;a<c.length;a++){var f=c[a];goog.dependencies_.written[f]=!0}var g=goog.moduleLoaderState_;goog.moduleLoaderState_=null;for(a=0;a<c.length;a++)if(f=c[a]){var h=e.loadFlags[f]||{},k=goog.needsTranspile_(h.lang);\"goog\"==h.module||k?goog.importProcessedScript_(goog.basePath+f,\"goog\"==h.module,k):goog.importScript_(goog.basePath+f)}else throw goog.moduleLoaderState_=g,Error(\"Undefined script input\");goog.moduleLoaderState_=\ng},goog.getPathFromDeps_=function(a){return a in goog.dependencies_.nameToPath?goog.dependencies_.nameToPath[a]:null},goog.findBasePath_(),goog.global.CLOSURE_NO_DEPS||goog.importScript_(goog.basePath+\"deps.js\"));\ngoog.loadModule=function(a){var b=goog.moduleLoaderState_;try{goog.moduleLoaderState_={moduleName:void 0,declareLegacyNamespace:!1};var c;if(goog.isFunction(a))c=a.call(void 0,{});else if(goog.isString(a))c=goog.loadModuleFromSource_.call(void 0,a);else throw Error(\"Invalid module definition\");var d=goog.moduleLoaderState_.moduleName;if(!goog.isString(d)||!d)throw Error('Invalid module name \"'+d+'\"');goog.moduleLoaderState_.declareLegacyNamespace?goog.constructNamespace_(d,c):goog.SEAL_MODULE_EXPORTS&&\nObject.seal&&Object.seal(c);goog.loadedModules_[d]=c}finally{goog.moduleLoaderState_=b}};goog.loadModuleFromSource_=function(a){eval(a);return{}};goog.normalizePath_=function(a){a=a.split(\"/\");for(var b=0;b<a.length;)\".\"==a[b]?a.splice(b,1):b&&\"..\"==a[b]&&a[b-1]&&\"..\"!=a[b-1]?a.splice(--b,2):b++;return a.join(\"/\")};\ngoog.loadFileSync_=function(a){if(goog.global.CLOSURE_LOAD_FILE_SYNC)return goog.global.CLOSURE_LOAD_FILE_SYNC(a);try{var b=new goog.global.XMLHttpRequest;b.open(\"get\",a,!1);b.send();return 0==b.status||200==b.status?b.responseText:null}catch(c){return null}};\ngoog.retrieveAndExec_=function(a,b,c){if(!COMPILED){var d=a;a=goog.normalizePath_(a);var e=goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_,f=goog.loadFileSync_(a);if(null==f)throw Error('Load of \"'+a+'\" failed');c&&(f=goog.transpile_.call(goog.global,f,a));f=b?goog.wrapModule_(a,f):f+(\"\\n//# sourceURL=\"+a);goog.IS_OLD_IE_?(goog.dependencies_.deferred[d]=f,goog.queuedModules_.push(d)):e(a,f)}};\ngoog.transpile_=function(a,b){var c=goog.global.$jscomp;c||(goog.global.$jscomp=c={});var d=c.transpile;if(!d){var e=goog.basePath+goog.TRANSPILER,f=goog.loadFileSync_(e);f&&(eval(f+\"\\n//# sourceURL=\"+e),c=goog.global.$jscomp,d=c.transpile)}d||(d=c.transpile=function(a,b){goog.logToConsole_(b+\" requires transpilation but no transpiler was found.\");return a});return d(a,b)};\ngoog.typeOf=function(a){var b=typeof a;if(\"object\"==b)if(a){if(a instanceof Array)return\"array\";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if(\"[object Window]\"==c)return\"object\";if(\"[object Array]\"==c||\"number\"==typeof a.length&&\"undefined\"!=typeof a.splice&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"splice\"))return\"array\";if(\"[object Function]\"==c||\"undefined\"!=typeof a.call&&\"undefined\"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable(\"call\"))return\"function\"}else return\"null\";\nelse if(\"function\"==b&&\"undefined\"==typeof a.call)return\"object\";return b};goog.isNull=function(a){return null===a};goog.isDefAndNotNull=function(a){return null!=a};goog.isArray=function(a){return\"array\"==goog.typeOf(a)};goog.isArrayLike=function(a){var b=goog.typeOf(a);return\"array\"==b||\"object\"==b&&\"number\"==typeof a.length};goog.isDateLike=function(a){return goog.isObject(a)&&\"function\"==typeof a.getFullYear};goog.isString=function(a){return\"string\"==typeof a};\ngoog.isBoolean=function(a){return\"boolean\"==typeof a};goog.isNumber=function(a){return\"number\"==typeof a};goog.isFunction=function(a){return\"function\"==goog.typeOf(a)};goog.isObject=function(a){var b=typeof a;return\"object\"==b&&null!=a||\"function\"==b};goog.getUid=function(a){return a[goog.UID_PROPERTY_]||(a[goog.UID_PROPERTY_]=++goog.uidCounter_)};goog.hasUid=function(a){return!!a[goog.UID_PROPERTY_]};\ngoog.removeUid=function(a){null!==a&&\"removeAttribute\"in a&&a.removeAttribute(goog.UID_PROPERTY_);try{delete a[goog.UID_PROPERTY_]}catch(b){}};goog.UID_PROPERTY_=\"closure_uid_\"+(1E9*Math.random()>>>0);goog.uidCounter_=0;goog.getHashCode=goog.getUid;goog.removeHashCode=goog.removeUid;goog.cloneObject=function(a){var b=goog.typeOf(a);if(\"object\"==b||\"array\"==b){if(a.clone)return a.clone();var b=\"array\"==b?[]:{},c;for(c in a)b[c]=goog.cloneObject(a[c]);return b}return a};\ngoog.bindNative_=function(a,b,c){return a.call.apply(a.bind,arguments)};goog.bindJs_=function(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}};\ngoog.bind=function(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf(\"native code\")?goog.bind=goog.bindNative_:goog.bind=goog.bindJs_;return goog.bind.apply(null,arguments)};goog.partial=function(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var b=c.slice();b.push.apply(b,arguments);return a.apply(this,b)}};goog.mixin=function(a,b){for(var c in b)a[c]=b[c]};goog.now=goog.TRUSTED_SITE&&Date.now||function(){return+new Date};\ngoog.globalEval=function(a){if(goog.global.execScript)goog.global.execScript(a,\"JavaScript\");else if(goog.global.eval){if(null==goog.evalWorksForGlobals_)if(goog.global.eval(\"var _evalTest_ = 1;\"),\"undefined\"!=typeof goog.global._evalTest_){try{delete goog.global._evalTest_}catch(d){}goog.evalWorksForGlobals_=!0}else goog.evalWorksForGlobals_=!1;if(goog.evalWorksForGlobals_)goog.global.eval(a);else{var b=goog.global.document,c=b.createElement(\"SCRIPT\");c.type=\"text/javascript\";c.defer=!1;c.appendChild(b.createTextNode(a));\nb.body.appendChild(c);b.body.removeChild(c)}}else throw Error(\"goog.globalEval not available\");};goog.evalWorksForGlobals_=null;goog.getCssName=function(a,b){var c=function(a){return goog.cssNameMapping_[a]||a},d=function(a){a=a.split(\"-\");for(var b=[],d=0;d<a.length;d++)b.push(c(a[d]));return b.join(\"-\")},d=goog.cssNameMapping_?\"BY_WHOLE\"==goog.cssNameMappingStyle_?c:d:function(a){return a};return b?a+\"-\"+d(b):d(a)};\ngoog.setCssNameMapping=function(a,b){goog.cssNameMapping_=a;goog.cssNameMappingStyle_=b};!COMPILED&&goog.global.CLOSURE_CSS_NAME_MAPPING&&(goog.cssNameMapping_=goog.global.CLOSURE_CSS_NAME_MAPPING);goog.getMsg=function(a,b){b&&(a=a.replace(/\\{\\$([^}]+)}/g,function(a,d){return null!=b&&d in b?b[d]:a}));return a};goog.getMsgWithFallback=function(a,b){return a};goog.exportSymbol=function(a,b,c){goog.exportPath_(a,b,c)};goog.exportProperty=function(a,b,c){a[b]=c};\ngoog.inherits=function(a,b){function c(){}c.prototype=b.prototype;a.superClass_=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.base=function(a,c,f){for(var g=Array(arguments.length-2),h=2;h<arguments.length;h++)g[h-2]=arguments[h];return b.prototype[c].apply(a,g)}};\ngoog.base=function(a,b,c){var d=arguments.callee.caller;if(goog.STRICT_MODE_COMPATIBLE||goog.DEBUG&&!d)throw Error(\"arguments.caller not defined.  goog.base() cannot be used with strict mode code. See http://www.ecma-international.org/ecma-262/5.1/#sec-C\");if(d.superClass_){for(var e=Array(arguments.length-1),f=1;f<arguments.length;f++)e[f-1]=arguments[f];return d.superClass_.constructor.apply(a,e)}e=Array(arguments.length-2);for(f=2;f<arguments.length;f++)e[f-2]=arguments[f];for(var f=!1,g=a.constructor;g;g=\ng.superClass_&&g.superClass_.constructor)if(g.prototype[b]===d)f=!0;else if(f)return g.prototype[b].apply(a,e);if(a[b]===d)return a.constructor.prototype[b].apply(a,e);throw Error(\"goog.base called from a method of one name to a method of a different name\");};goog.scope=function(a){if(goog.isInModuleLoader_())throw Error(\"goog.scope is not supported within a goog.module.\");a.call(goog.global)};COMPILED||(goog.global.COMPILED=COMPILED);\ngoog.defineClass=function(a,b){var c=b.constructor,d=b.statics;c&&c!=Object.prototype.constructor||(c=function(){throw Error(\"cannot instantiate an interface (no constructor defined).\");});c=goog.defineClass.createSealingConstructor_(c,a);a&&goog.inherits(c,a);delete b.constructor;delete b.statics;goog.defineClass.applyProperties_(c.prototype,b);null!=d&&(d instanceof Function?d(c):goog.defineClass.applyProperties_(c,d));return c};goog.defineClass.SEAL_CLASS_INSTANCES=goog.DEBUG;\ngoog.defineClass.createSealingConstructor_=function(a,b){if(!goog.defineClass.SEAL_CLASS_INSTANCES)return a;var c=!goog.defineClass.isUnsealable_(b),d=function(){var b=a.apply(this,arguments)||this;b[goog.UID_PROPERTY_]=b[goog.UID_PROPERTY_];this.constructor===d&&c&&Object.seal instanceof Function&&Object.seal(b);return b};return d};goog.defineClass.isUnsealable_=function(a){return a&&a.prototype&&a.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_]};goog.defineClass.OBJECT_PROTOTYPE_FIELDS_=\"constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf\".split(\" \");\ngoog.defineClass.applyProperties_=function(a,b){for(var c in b)Object.prototype.hasOwnProperty.call(b,c)&&(a[c]=b[c]);for(var d=0;d<goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length;d++)c=goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[d],Object.prototype.hasOwnProperty.call(b,c)&&(a[c]=b[c])};goog.tagUnsealableClass=function(a){!COMPILED&&goog.defineClass.SEAL_CLASS_INSTANCES&&(a.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_]=!0)};goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_=\"goog_defineClass_legacy_unsealable\";goog.debug={};goog.debug.Error=function(a){if(Error.captureStackTrace)Error.captureStackTrace(this,goog.debug.Error);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a));this.reportErrorToServer=!0};goog.inherits(goog.debug.Error,Error);goog.debug.Error.prototype.name=\"CustomError\";goog.dom={};goog.dom.NodeType={ELEMENT:1,ATTRIBUTE:2,TEXT:3,CDATA_SECTION:4,ENTITY_REFERENCE:5,ENTITY:6,PROCESSING_INSTRUCTION:7,COMMENT:8,DOCUMENT:9,DOCUMENT_TYPE:10,DOCUMENT_FRAGMENT:11,NOTATION:12};goog.string={};goog.string.DETECT_DOUBLE_ESCAPING=!1;goog.string.FORCE_NON_DOM_HTML_UNESCAPING=!1;goog.string.Unicode={NBSP:\"\\u00a0\"};goog.string.startsWith=function(a,b){return 0==a.lastIndexOf(b,0)};goog.string.endsWith=function(a,b){var c=a.length-b.length;return 0<=c&&a.indexOf(b,c)==c};goog.string.caseInsensitiveStartsWith=function(a,b){return 0==goog.string.caseInsensitiveCompare(b,a.substr(0,b.length))};\ngoog.string.caseInsensitiveEndsWith=function(a,b){return 0==goog.string.caseInsensitiveCompare(b,a.substr(a.length-b.length,b.length))};goog.string.caseInsensitiveEquals=function(a,b){return a.toLowerCase()==b.toLowerCase()};goog.string.subs=function(a,b){for(var c=a.split(\"%s\"),d=\"\",e=Array.prototype.slice.call(arguments,1);e.length&&1<c.length;)d+=c.shift()+e.shift();return d+c.join(\"%s\")};goog.string.collapseWhitespace=function(a){return a.replace(/[\\s\\xa0]+/g,\" \").replace(/^\\s+|\\s+$/g,\"\")};\ngoog.string.isEmptyOrWhitespace=function(a){return/^[\\s\\xa0]*$/.test(a)};goog.string.isEmptyString=function(a){return 0==a.length};goog.string.isEmpty=goog.string.isEmptyOrWhitespace;goog.string.isEmptyOrWhitespaceSafe=function(a){return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(a))};goog.string.isEmptySafe=goog.string.isEmptyOrWhitespaceSafe;goog.string.isBreakingWhitespace=function(a){return!/[^\\t\\n\\r ]/.test(a)};goog.string.isAlpha=function(a){return!/[^a-zA-Z]/.test(a)};\ngoog.string.isNumeric=function(a){return!/[^0-9]/.test(a)};goog.string.isAlphaNumeric=function(a){return!/[^a-zA-Z0-9]/.test(a)};goog.string.isSpace=function(a){return\" \"==a};goog.string.isUnicodeChar=function(a){return 1==a.length&&\" \"<=a&&\"~\">=a||\"\\u0080\"<=a&&\"\\ufffd\">=a};goog.string.stripNewlines=function(a){return a.replace(/(\\r\\n|\\r|\\n)+/g,\" \")};goog.string.canonicalizeNewlines=function(a){return a.replace(/(\\r\\n|\\r|\\n)/g,\"\\n\")};\ngoog.string.normalizeWhitespace=function(a){return a.replace(/\\xa0|\\s/g,\" \")};goog.string.normalizeSpaces=function(a){return a.replace(/\\xa0|[ \\t]+/g,\" \")};goog.string.collapseBreakingSpaces=function(a){return a.replace(/[\\t\\r\\n ]+/g,\" \").replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g,\"\")};goog.string.trim=goog.TRUSTED_SITE&&String.prototype.trim?function(a){return a.trim()}:function(a){return a.replace(/^[\\s\\xa0]+|[\\s\\xa0]+$/g,\"\")};goog.string.trimLeft=function(a){return a.replace(/^[\\s\\xa0]+/,\"\")};\ngoog.string.trimRight=function(a){return a.replace(/[\\s\\xa0]+$/,\"\")};goog.string.caseInsensitiveCompare=function(a,b){var c=String(a).toLowerCase(),d=String(b).toLowerCase();return c<d?-1:c==d?0:1};\ngoog.string.numberAwareCompare_=function(a,b,c){if(a==b)return 0;if(!a)return-1;if(!b)return 1;for(var d=a.toLowerCase().match(c),e=b.toLowerCase().match(c),f=Math.min(d.length,e.length),g=0;g<f;g++){c=d[g];var h=e[g];if(c!=h)return a=parseInt(c,10),!isNaN(a)&&(b=parseInt(h,10),!isNaN(b)&&a-b)?a-b:c<h?-1:1}return d.length!=e.length?d.length-e.length:a<b?-1:1};goog.string.intAwareCompare=function(a,b){return goog.string.numberAwareCompare_(a,b,/\\d+|\\D+/g)};\ngoog.string.floatAwareCompare=function(a,b){return goog.string.numberAwareCompare_(a,b,/\\d+|\\.\\d+|\\D+/g)};goog.string.numerateCompare=goog.string.floatAwareCompare;goog.string.urlEncode=function(a){return encodeURIComponent(String(a))};goog.string.urlDecode=function(a){return decodeURIComponent(a.replace(/\\+/g,\" \"))};goog.string.newLineToBr=function(a,b){return a.replace(/(\\r\\n|\\r|\\n)/g,b?\"<br />\":\"<br>\")};\ngoog.string.htmlEscape=function(a,b){if(b)a=a.replace(goog.string.AMP_RE_,\"&amp;\").replace(goog.string.LT_RE_,\"&lt;\").replace(goog.string.GT_RE_,\"&gt;\").replace(goog.string.QUOT_RE_,\"&quot;\").replace(goog.string.SINGLE_QUOTE_RE_,\"&#39;\").replace(goog.string.NULL_RE_,\"&#0;\"),goog.string.DETECT_DOUBLE_ESCAPING&&(a=a.replace(goog.string.E_RE_,\"&#101;\"));else{if(!goog.string.ALL_RE_.test(a))return a;-1!=a.indexOf(\"&\")&&(a=a.replace(goog.string.AMP_RE_,\"&amp;\"));-1!=a.indexOf(\"<\")&&(a=a.replace(goog.string.LT_RE_,\n\"&lt;\"));-1!=a.indexOf(\">\")&&(a=a.replace(goog.string.GT_RE_,\"&gt;\"));-1!=a.indexOf('\"')&&(a=a.replace(goog.string.QUOT_RE_,\"&quot;\"));-1!=a.indexOf(\"'\")&&(a=a.replace(goog.string.SINGLE_QUOTE_RE_,\"&#39;\"));-1!=a.indexOf(\"\\x00\")&&(a=a.replace(goog.string.NULL_RE_,\"&#0;\"));goog.string.DETECT_DOUBLE_ESCAPING&&-1!=a.indexOf(\"e\")&&(a=a.replace(goog.string.E_RE_,\"&#101;\"))}return a};goog.string.AMP_RE_=/&/g;goog.string.LT_RE_=/</g;goog.string.GT_RE_=/>/g;goog.string.QUOT_RE_=/\"/g;\ngoog.string.SINGLE_QUOTE_RE_=/'/g;goog.string.NULL_RE_=/\\x00/g;goog.string.E_RE_=/e/g;goog.string.ALL_RE_=goog.string.DETECT_DOUBLE_ESCAPING?/[\\x00&<>\"'e]/:/[\\x00&<>\"']/;goog.string.unescapeEntities=function(a){return goog.string.contains(a,\"&\")?!goog.string.FORCE_NON_DOM_HTML_UNESCAPING&&\"document\"in goog.global?goog.string.unescapeEntitiesUsingDom_(a):goog.string.unescapePureXmlEntities_(a):a};\ngoog.string.unescapeEntitiesWithDocument=function(a,b){return goog.string.contains(a,\"&\")?goog.string.unescapeEntitiesUsingDom_(a,b):a};\ngoog.string.unescapeEntitiesUsingDom_=function(a,b){var c={\"&amp;\":\"&\",\"&lt;\":\"<\",\"&gt;\":\">\",\"&quot;\":'\"'},d;d=b?b.createElement(\"div\"):goog.global.document.createElement(\"div\");return a.replace(goog.string.HTML_ENTITY_PATTERN_,function(a,b){var g=c[a];if(g)return g;if(\"#\"==b.charAt(0)){var h=Number(\"0\"+b.substr(1));isNaN(h)||(g=String.fromCharCode(h))}g||(d.innerHTML=a+\" \",g=d.firstChild.nodeValue.slice(0,-1));return c[a]=g})};\ngoog.string.unescapePureXmlEntities_=function(a){return a.replace(/&([^;]+);/g,function(a,c){switch(c){case \"amp\":return\"&\";case \"lt\":return\"<\";case \"gt\":return\">\";case \"quot\":return'\"';default:if(\"#\"==c.charAt(0)){var d=Number(\"0\"+c.substr(1));if(!isNaN(d))return String.fromCharCode(d)}return a}})};goog.string.HTML_ENTITY_PATTERN_=/&([^;\\s<&]+);?/g;goog.string.whitespaceEscape=function(a,b){return goog.string.newLineToBr(a.replace(/  /g,\" &#160;\"),b)};\ngoog.string.preserveSpaces=function(a){return a.replace(/(^|[\\n ]) /g,\"$1\"+goog.string.Unicode.NBSP)};goog.string.stripQuotes=function(a,b){for(var c=b.length,d=0;d<c;d++){var e=1==c?b:b.charAt(d);if(a.charAt(0)==e&&a.charAt(a.length-1)==e)return a.substring(1,a.length-1)}return a};goog.string.truncate=function(a,b,c){c&&(a=goog.string.unescapeEntities(a));a.length>b&&(a=a.substring(0,b-3)+\"...\");c&&(a=goog.string.htmlEscape(a));return a};\ngoog.string.truncateMiddle=function(a,b,c,d){c&&(a=goog.string.unescapeEntities(a));if(d&&a.length>b){d>b&&(d=b);var e=a.length-d;a=a.substring(0,b-d)+\"...\"+a.substring(e)}else a.length>b&&(d=Math.floor(b/2),e=a.length-d,a=a.substring(0,d+b%2)+\"...\"+a.substring(e));c&&(a=goog.string.htmlEscape(a));return a};goog.string.specialEscapeChars_={\"\\x00\":\"\\\\0\",\"\\b\":\"\\\\b\",\"\\f\":\"\\\\f\",\"\\n\":\"\\\\n\",\"\\r\":\"\\\\r\",\"\\t\":\"\\\\t\",\"\\x0B\":\"\\\\x0B\",'\"':'\\\\\"',\"\\\\\":\"\\\\\\\\\",\"<\":\"<\"};goog.string.jsEscapeCache_={\"'\":\"\\\\'\"};\ngoog.string.quote=function(a){a=String(a);for(var b=['\"'],c=0;c<a.length;c++){var d=a.charAt(c),e=d.charCodeAt(0);b[c+1]=goog.string.specialEscapeChars_[d]||(31<e&&127>e?d:goog.string.escapeChar(d))}b.push('\"');return b.join(\"\")};goog.string.escapeString=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=goog.string.escapeChar(a.charAt(c));return b.join(\"\")};\ngoog.string.escapeChar=function(a){if(a in goog.string.jsEscapeCache_)return goog.string.jsEscapeCache_[a];if(a in goog.string.specialEscapeChars_)return goog.string.jsEscapeCache_[a]=goog.string.specialEscapeChars_[a];var b,c=a.charCodeAt(0);if(31<c&&127>c)b=a;else{if(256>c){if(b=\"\\\\x\",16>c||256<c)b+=\"0\"}else b=\"\\\\u\",4096>c&&(b+=\"0\");b+=c.toString(16).toUpperCase()}return goog.string.jsEscapeCache_[a]=b};goog.string.contains=function(a,b){return-1!=a.indexOf(b)};\ngoog.string.caseInsensitiveContains=function(a,b){return goog.string.contains(a.toLowerCase(),b.toLowerCase())};goog.string.countOf=function(a,b){return a&&b?a.split(b).length-1:0};goog.string.removeAt=function(a,b,c){var d=a;0<=b&&b<a.length&&0<c&&(d=a.substr(0,b)+a.substr(b+c,a.length-b-c));return d};goog.string.remove=function(a,b){var c=new RegExp(goog.string.regExpEscape(b),\"\");return a.replace(c,\"\")};\ngoog.string.removeAll=function(a,b){var c=new RegExp(goog.string.regExpEscape(b),\"g\");return a.replace(c,\"\")};goog.string.regExpEscape=function(a){return String(a).replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g,\"\\\\$1\").replace(/\\x08/g,\"\\\\x08\")};goog.string.repeat=String.prototype.repeat?function(a,b){return a.repeat(b)}:function(a,b){return Array(b+1).join(a)};\ngoog.string.padNumber=function(a,b,c){a=goog.isDef(c)?a.toFixed(c):String(a);c=a.indexOf(\".\");-1==c&&(c=a.length);return goog.string.repeat(\"0\",Math.max(0,b-c))+a};goog.string.makeSafe=function(a){return null==a?\"\":String(a)};goog.string.buildString=function(a){return Array.prototype.join.call(arguments,\"\")};goog.string.getRandomString=function(){return Math.floor(2147483648*Math.random()).toString(36)+Math.abs(Math.floor(2147483648*Math.random())^goog.now()).toString(36)};\ngoog.string.compareVersions=function(a,b){for(var c=0,d=goog.string.trim(String(a)).split(\".\"),e=goog.string.trim(String(b)).split(\".\"),f=Math.max(d.length,e.length),g=0;0==c&&g<f;g++){var h=d[g]||\"\",k=e[g]||\"\",n=RegExp(\"(\\\\d*)(\\\\D*)\",\"g\"),p=RegExp(\"(\\\\d*)(\\\\D*)\",\"g\");do{var m=n.exec(h)||[\"\",\"\",\"\"],l=p.exec(k)||[\"\",\"\",\"\"];if(0==m[0].length&&0==l[0].length)break;var c=0==m[1].length?0:parseInt(m[1],10),q=0==l[1].length?0:parseInt(l[1],10),c=goog.string.compareElements_(c,q)||goog.string.compareElements_(0==\nm[2].length,0==l[2].length)||goog.string.compareElements_(m[2],l[2])}while(0==c)}return c};goog.string.compareElements_=function(a,b){return a<b?-1:a>b?1:0};goog.string.hashCode=function(a){for(var b=0,c=0;c<a.length;++c)b=31*b+a.charCodeAt(c)>>>0;return b};goog.string.uniqueStringCounter_=2147483648*Math.random()|0;goog.string.createUniqueString=function(){return\"goog_\"+goog.string.uniqueStringCounter_++};\ngoog.string.toNumber=function(a){var b=Number(a);return 0==b&&goog.string.isEmptyOrWhitespace(a)?NaN:b};goog.string.isLowerCamelCase=function(a){return/^[a-z]+([A-Z][a-z]*)*$/.test(a)};goog.string.isUpperCamelCase=function(a){return/^([A-Z][a-z]*)+$/.test(a)};goog.string.toCamelCase=function(a){return String(a).replace(/\\-([a-z])/g,function(a,c){return c.toUpperCase()})};goog.string.toSelectorCase=function(a){return String(a).replace(/([A-Z])/g,\"-$1\").toLowerCase()};\ngoog.string.toTitleCase=function(a,b){var c=goog.isString(b)?goog.string.regExpEscape(b):\"\\\\s\";return a.replace(new RegExp(\"(^\"+(c?\"|[\"+c+\"]+\":\"\")+\")([a-z])\",\"g\"),function(a,b,c){return b+c.toUpperCase()})};goog.string.capitalize=function(a){return String(a.charAt(0)).toUpperCase()+String(a.substr(1)).toLowerCase()};goog.string.parseInt=function(a){isFinite(a)&&(a=String(a));return goog.isString(a)?/^\\s*-?0x/i.test(a)?parseInt(a,16):parseInt(a,10):NaN};\ngoog.string.splitLimit=function(a,b,c){a=a.split(b);for(var d=[];0<c&&a.length;)d.push(a.shift()),c--;a.length&&d.push(a.join(b));return d};goog.string.lastComponent=function(a,b){if(b)\"string\"==typeof b&&(b=[b]);else return a;for(var c=-1,d=0;d<b.length;d++)if(\"\"!=b[d]){var e=a.lastIndexOf(b[d]);e>c&&(c=e)}return-1==c?a:a.slice(c+1)};\ngoog.string.editDistance=function(a,b){var c=[],d=[];if(a==b)return 0;if(!a.length||!b.length)return Math.max(a.length,b.length);for(var e=0;e<b.length+1;e++)c[e]=e;for(e=0;e<a.length;e++){d[0]=e+1;for(var f=0;f<b.length;f++)d[f+1]=Math.min(d[f]+1,c[f+1]+1,c[f]+Number(a[e]!=b[f]));for(f=0;f<c.length;f++)c[f]=d[f]}return d[b.length]};goog.asserts={};goog.asserts.ENABLE_ASSERTS=goog.DEBUG;goog.asserts.AssertionError=function(a,b){b.unshift(a);goog.debug.Error.call(this,goog.string.subs.apply(null,b));b.shift();this.messagePattern=a};goog.inherits(goog.asserts.AssertionError,goog.debug.Error);goog.asserts.AssertionError.prototype.name=\"AssertionError\";goog.asserts.DEFAULT_ERROR_HANDLER=function(a){throw a;};goog.asserts.errorHandler_=goog.asserts.DEFAULT_ERROR_HANDLER;\ngoog.asserts.doAssertFailure_=function(a,b,c,d){var e=\"Assertion failed\";if(c)var e=e+(\": \"+c),f=d;else a&&(e+=\": \"+a,f=b);a=new goog.asserts.AssertionError(\"\"+e,f||[]);goog.asserts.errorHandler_(a)};goog.asserts.setErrorHandler=function(a){goog.asserts.ENABLE_ASSERTS&&(goog.asserts.errorHandler_=a)};goog.asserts.assert=function(a,b,c){goog.asserts.ENABLE_ASSERTS&&!a&&goog.asserts.doAssertFailure_(\"\",null,b,Array.prototype.slice.call(arguments,2));return a};\ngoog.asserts.fail=function(a,b){goog.asserts.ENABLE_ASSERTS&&goog.asserts.errorHandler_(new goog.asserts.AssertionError(\"Failure\"+(a?\": \"+a:\"\"),Array.prototype.slice.call(arguments,1)))};goog.asserts.assertNumber=function(a,b,c){goog.asserts.ENABLE_ASSERTS&&!goog.isNumber(a)&&goog.asserts.doAssertFailure_(\"Expected number but got %s: %s.\",[goog.typeOf(a),a],b,Array.prototype.slice.call(arguments,2));return a};\ngoog.asserts.assertString=function(a,b,c){goog.asserts.ENABLE_ASSERTS&&!goog.isString(a)&&goog.asserts.doAssertFailure_(\"Expected string but got %s: %s.\",[goog.typeOf(a),a],b,Array.prototype.slice.call(arguments,2));return a};goog.asserts.assertFunction=function(a,b,c){goog.asserts.ENABLE_ASSERTS&&!goog.isFunction(a)&&goog.asserts.doAssertFailure_(\"Expected function but got %s: %s.\",[goog.typeOf(a),a],b,Array.prototype.slice.call(arguments,2));return a};\ngoog.asserts.assertObject=function(a,b,c){goog.asserts.ENABLE_ASSERTS&&!goog.isObject(a)&&goog.asserts.doAssertFailure_(\"Expected object but got %s: %s.\",[goog.typeOf(a),a],b,Array.prototype.slice.call(arguments,2));return a};goog.asserts.assertArray=function(a,b,c){goog.asserts.ENABLE_ASSERTS&&!goog.isArray(a)&&goog.asserts.doAssertFailure_(\"Expected array but got %s: %s.\",[goog.typeOf(a),a],b,Array.prototype.slice.call(arguments,2));return a};\ngoog.asserts.assertBoolean=function(a,b,c){goog.asserts.ENABLE_ASSERTS&&!goog.isBoolean(a)&&goog.asserts.doAssertFailure_(\"Expected boolean but got %s: %s.\",[goog.typeOf(a),a],b,Array.prototype.slice.call(arguments,2));return a};goog.asserts.assertElement=function(a,b,c){!goog.asserts.ENABLE_ASSERTS||goog.isObject(a)&&a.nodeType==goog.dom.NodeType.ELEMENT||goog.asserts.doAssertFailure_(\"Expected Element but got %s: %s.\",[goog.typeOf(a),a],b,Array.prototype.slice.call(arguments,2));return a};\ngoog.asserts.assertInstanceof=function(a,b,c,d){!goog.asserts.ENABLE_ASSERTS||a instanceof b||goog.asserts.doAssertFailure_(\"Expected instanceof %s but got %s.\",[goog.asserts.getType_(b),goog.asserts.getType_(a)],c,Array.prototype.slice.call(arguments,3));return a};goog.asserts.assertObjectPrototypeIsIntact=function(){for(var a in Object.prototype)goog.asserts.fail(a+\" should not be enumerable in Object.prototype.\")};\ngoog.asserts.getType_=function(a){return a instanceof Function?a.displayName||a.name||\"unknown type name\":a instanceof Object?a.constructor.displayName||a.constructor.name||Object.prototype.toString.call(a):null===a?\"null\":typeof a};goog.array={};goog.NATIVE_ARRAY_PROTOTYPES=goog.TRUSTED_SITE;goog.array.ASSUME_NATIVE_FUNCTIONS=!1;goog.array.peek=function(a){return a[a.length-1]};goog.array.last=goog.array.peek;\ngoog.array.indexOf=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.indexOf)?function(a,b,c){goog.asserts.assert(null!=a.length);return Array.prototype.indexOf.call(a,b,c)}:function(a,b,c){c=null==c?0:0>c?Math.max(0,a.length+c):c;if(goog.isString(a))return goog.isString(b)&&1==b.length?a.indexOf(b,c):-1;for(;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1};\ngoog.array.lastIndexOf=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.lastIndexOf)?function(a,b,c){goog.asserts.assert(null!=a.length);return Array.prototype.lastIndexOf.call(a,b,null==c?a.length-1:c)}:function(a,b,c){c=null==c?a.length-1:c;0>c&&(c=Math.max(0,a.length+c));if(goog.isString(a))return goog.isString(b)&&1==b.length?a.lastIndexOf(b,c):-1;for(;0<=c;c--)if(c in a&&a[c]===b)return c;return-1};\ngoog.array.forEach=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.forEach)?function(a,b,c){goog.asserts.assert(null!=a.length);Array.prototype.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=goog.isString(a)?a.split(\"\"):a,f=0;f<d;f++)f in e&&b.call(c,e[f],f,a)};goog.array.forEachRight=function(a,b,c){for(var d=a.length,e=goog.isString(a)?a.split(\"\"):a,d=d-1;0<=d;--d)d in e&&b.call(c,e[d],d,a)};\ngoog.array.filter=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.filter)?function(a,b,c){goog.asserts.assert(null!=a.length);return Array.prototype.filter.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=[],f=0,g=goog.isString(a)?a.split(\"\"):a,h=0;h<d;h++)if(h in g){var k=g[h];b.call(c,k,h,a)&&(e[f++]=k)}return e};\ngoog.array.map=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.map)?function(a,b,c){goog.asserts.assert(null!=a.length);return Array.prototype.map.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=Array(d),f=goog.isString(a)?a.split(\"\"):a,g=0;g<d;g++)g in f&&(e[g]=b.call(c,f[g],g,a));return e};\ngoog.array.reduce=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.reduce)?function(a,b,c,d){goog.asserts.assert(null!=a.length);d&&(b=goog.bind(b,d));return Array.prototype.reduce.call(a,b,c)}:function(a,b,c,d){var e=c;goog.array.forEach(a,function(c,g){e=b.call(d,e,c,g,a)});return e};\ngoog.array.reduceRight=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.reduceRight)?function(a,b,c,d){goog.asserts.assert(null!=a.length);goog.asserts.assert(null!=b);d&&(b=goog.bind(b,d));return Array.prototype.reduceRight.call(a,b,c)}:function(a,b,c,d){var e=c;goog.array.forEachRight(a,function(c,g){e=b.call(d,e,c,g,a)});return e};\ngoog.array.some=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.some)?function(a,b,c){goog.asserts.assert(null!=a.length);return Array.prototype.some.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=goog.isString(a)?a.split(\"\"):a,f=0;f<d;f++)if(f in e&&b.call(c,e[f],f,a))return!0;return!1};\ngoog.array.every=goog.NATIVE_ARRAY_PROTOTYPES&&(goog.array.ASSUME_NATIVE_FUNCTIONS||Array.prototype.every)?function(a,b,c){goog.asserts.assert(null!=a.length);return Array.prototype.every.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=goog.isString(a)?a.split(\"\"):a,f=0;f<d;f++)if(f in e&&!b.call(c,e[f],f,a))return!1;return!0};goog.array.count=function(a,b,c){var d=0;goog.array.forEach(a,function(a,f,g){b.call(c,a,f,g)&&++d},c);return d};\ngoog.array.find=function(a,b,c){b=goog.array.findIndex(a,b,c);return 0>b?null:goog.isString(a)?a.charAt(b):a[b]};goog.array.findIndex=function(a,b,c){for(var d=a.length,e=goog.isString(a)?a.split(\"\"):a,f=0;f<d;f++)if(f in e&&b.call(c,e[f],f,a))return f;return-1};goog.array.findRight=function(a,b,c){b=goog.array.findIndexRight(a,b,c);return 0>b?null:goog.isString(a)?a.charAt(b):a[b]};\ngoog.array.findIndexRight=function(a,b,c){for(var d=a.length,e=goog.isString(a)?a.split(\"\"):a,d=d-1;0<=d;d--)if(d in e&&b.call(c,e[d],d,a))return d;return-1};goog.array.contains=function(a,b){return 0<=goog.array.indexOf(a,b)};goog.array.isEmpty=function(a){return 0==a.length};goog.array.clear=function(a){if(!goog.isArray(a))for(var b=a.length-1;0<=b;b--)delete a[b];a.length=0};goog.array.insert=function(a,b){goog.array.contains(a,b)||a.push(b)};\ngoog.array.insertAt=function(a,b,c){goog.array.splice(a,c,0,b)};goog.array.insertArrayAt=function(a,b,c){goog.partial(goog.array.splice,a,c,0).apply(null,b)};goog.array.insertBefore=function(a,b,c){var d;2==arguments.length||0>(d=goog.array.indexOf(a,c))?a.push(b):goog.array.insertAt(a,b,d)};goog.array.remove=function(a,b){var c=goog.array.indexOf(a,b),d;(d=0<=c)&&goog.array.removeAt(a,c);return d};\ngoog.array.removeLast=function(a,b){var c=goog.array.lastIndexOf(a,b);return 0<=c?(goog.array.removeAt(a,c),!0):!1};goog.array.removeAt=function(a,b){goog.asserts.assert(null!=a.length);return 1==Array.prototype.splice.call(a,b,1).length};goog.array.removeIf=function(a,b,c){b=goog.array.findIndex(a,b,c);return 0<=b?(goog.array.removeAt(a,b),!0):!1};goog.array.removeAllIf=function(a,b,c){var d=0;goog.array.forEachRight(a,function(e,f){b.call(c,e,f,a)&&goog.array.removeAt(a,f)&&d++});return d};\ngoog.array.concat=function(a){return Array.prototype.concat.apply(Array.prototype,arguments)};goog.array.join=function(a){return Array.prototype.concat.apply(Array.prototype,arguments)};goog.array.toArray=function(a){var b=a.length;if(0<b){for(var c=Array(b),d=0;d<b;d++)c[d]=a[d];return c}return[]};goog.array.clone=goog.array.toArray;\ngoog.array.extend=function(a,b){for(var c=1;c<arguments.length;c++){var d=arguments[c];if(goog.isArrayLike(d)){var e=a.length||0,f=d.length||0;a.length=e+f;for(var g=0;g<f;g++)a[e+g]=d[g]}else a.push(d)}};goog.array.splice=function(a,b,c,d){goog.asserts.assert(null!=a.length);return Array.prototype.splice.apply(a,goog.array.slice(arguments,1))};\ngoog.array.slice=function(a,b,c){goog.asserts.assert(null!=a.length);return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)};goog.array.removeDuplicates=function(a,b,c){b=b||a;var d=function(a){return goog.isObject(a)?\"o\"+goog.getUid(a):(typeof a).charAt(0)+a};c=c||d;for(var d={},e=0,f=0;f<a.length;){var g=a[f++],h=c(g);Object.prototype.hasOwnProperty.call(d,h)||(d[h]=!0,b[e++]=g)}b.length=e};\ngoog.array.binarySearch=function(a,b,c){return goog.array.binarySearch_(a,c||goog.array.defaultCompare,!1,b)};goog.array.binarySelect=function(a,b,c){return goog.array.binarySearch_(a,b,!0,void 0,c)};goog.array.binarySearch_=function(a,b,c,d,e){for(var f=0,g=a.length,h;f<g;){var k=f+g>>1,n;n=c?b.call(e,a[k],k,a):b(d,a[k]);0<n?f=k+1:(g=k,h=!n)}return h?f:~f};goog.array.sort=function(a,b){a.sort(b||goog.array.defaultCompare)};\ngoog.array.stableSort=function(a,b){for(var c=Array(a.length),d=0;d<a.length;d++)c[d]={index:d,value:a[d]};var e=b||goog.array.defaultCompare;goog.array.sort(c,function(a,b){return e(a.value,b.value)||a.index-b.index});for(d=0;d<a.length;d++)a[d]=c[d].value};goog.array.sortByKey=function(a,b,c){var d=c||goog.array.defaultCompare;goog.array.sort(a,function(a,c){return d(b(a),b(c))})};goog.array.sortObjectsByKey=function(a,b,c){goog.array.sortByKey(a,function(a){return a[b]},c)};\ngoog.array.isSorted=function(a,b,c){b=b||goog.array.defaultCompare;for(var d=1;d<a.length;d++){var e=b(a[d-1],a[d]);if(0<e||0==e&&c)return!1}return!0};goog.array.equals=function(a,b,c){if(!goog.isArrayLike(a)||!goog.isArrayLike(b)||a.length!=b.length)return!1;var d=a.length;c=c||goog.array.defaultCompareEquality;for(var e=0;e<d;e++)if(!c(a[e],b[e]))return!1;return!0};\ngoog.array.compare3=function(a,b,c){c=c||goog.array.defaultCompare;for(var d=Math.min(a.length,b.length),e=0;e<d;e++){var f=c(a[e],b[e]);if(0!=f)return f}return goog.array.defaultCompare(a.length,b.length)};goog.array.defaultCompare=function(a,b){return a>b?1:a<b?-1:0};goog.array.inverseDefaultCompare=function(a,b){return-goog.array.defaultCompare(a,b)};goog.array.defaultCompareEquality=function(a,b){return a===b};\ngoog.array.binaryInsert=function(a,b,c){c=goog.array.binarySearch(a,b,c);return 0>c?(goog.array.insertAt(a,b,-(c+1)),!0):!1};goog.array.binaryRemove=function(a,b,c){b=goog.array.binarySearch(a,b,c);return 0<=b?goog.array.removeAt(a,b):!1};goog.array.bucket=function(a,b,c){for(var d={},e=0;e<a.length;e++){var f=a[e],g=b.call(c,f,e,a);goog.isDef(g)&&(d[g]||(d[g]=[])).push(f)}return d};goog.array.toObject=function(a,b,c){var d={};goog.array.forEach(a,function(e,f){d[b.call(c,e,f,a)]=e});return d};\ngoog.array.range=function(a,b,c){var d=[],e=0,f=a;c=c||1;void 0!==b&&(e=a,f=b);if(0>c*(f-e))return[];if(0<c)for(a=e;a<f;a+=c)d.push(a);else for(a=e;a>f;a+=c)d.push(a);return d};goog.array.repeat=function(a,b){for(var c=[],d=0;d<b;d++)c[d]=a;return c};goog.array.flatten=function(a){for(var b=[],c=0;c<arguments.length;c++){var d=arguments[c];if(goog.isArray(d))for(var e=0;e<d.length;e+=8192)for(var f=goog.array.slice(d,e,e+8192),f=goog.array.flatten.apply(null,f),g=0;g<f.length;g++)b.push(f[g]);else b.push(d)}return b};\ngoog.array.rotate=function(a,b){goog.asserts.assert(null!=a.length);a.length&&(b%=a.length,0<b?Array.prototype.unshift.apply(a,a.splice(-b,b)):0>b&&Array.prototype.push.apply(a,a.splice(0,-b)));return a};goog.array.moveItem=function(a,b,c){goog.asserts.assert(0<=b&&b<a.length);goog.asserts.assert(0<=c&&c<a.length);b=Array.prototype.splice.call(a,b,1);Array.prototype.splice.call(a,c,0,b[0])};\ngoog.array.zip=function(a){if(!arguments.length)return[];for(var b=[],c=arguments[0].length,d=1;d<arguments.length;d++)arguments[d].length<c&&(c=arguments[d].length);for(d=0;d<c;d++){for(var e=[],f=0;f<arguments.length;f++)e.push(arguments[f][d]);b.push(e)}return b};goog.array.shuffle=function(a,b){for(var c=b||Math.random,d=a.length-1;0<d;d--){var e=Math.floor(c()*(d+1)),f=a[d];a[d]=a[e];a[e]=f}};goog.array.copyByIndex=function(a,b){var c=[];goog.array.forEach(b,function(b){c.push(a[b])});return c};\ngoog.array.concatMap=function(a,b,c){return goog.array.concat.apply([],goog.array.map(a,b,c))};goog.labs={};goog.labs.userAgent={};goog.labs.userAgent.util={};goog.labs.userAgent.util.getNativeUserAgentString_=function(){var a=goog.labs.userAgent.util.getNavigator_();return a&&(a=a.userAgent)?a:\"\"};goog.labs.userAgent.util.getNavigator_=function(){return goog.global.navigator};goog.labs.userAgent.util.userAgent_=goog.labs.userAgent.util.getNativeUserAgentString_();goog.labs.userAgent.util.setUserAgent=function(a){goog.labs.userAgent.util.userAgent_=a||goog.labs.userAgent.util.getNativeUserAgentString_()};\ngoog.labs.userAgent.util.getUserAgent=function(){return goog.labs.userAgent.util.userAgent_};goog.labs.userAgent.util.matchUserAgent=function(a){var b=goog.labs.userAgent.util.getUserAgent();return goog.string.contains(b,a)};goog.labs.userAgent.util.matchUserAgentIgnoreCase=function(a){var b=goog.labs.userAgent.util.getUserAgent();return goog.string.caseInsensitiveContains(b,a)};\ngoog.labs.userAgent.util.extractVersionTuples=function(a){for(var b=RegExp(\"(\\\\w[\\\\w ]+)/([^\\\\s]+)\\\\s*(?:\\\\((.*?)\\\\))?\",\"g\"),c=[],d;d=b.exec(a);)c.push([d[1],d[2],d[3]||void 0]);return c};goog.object={};goog.object.is=function(a,b){return a===b?0!==a||1/a===1/b:a!==a&&b!==b};goog.object.forEach=function(a,b,c){for(var d in a)b.call(c,a[d],d,a)};goog.object.filter=function(a,b,c){var d={},e;for(e in a)b.call(c,a[e],e,a)&&(d[e]=a[e]);return d};goog.object.map=function(a,b,c){var d={},e;for(e in a)d[e]=b.call(c,a[e],e,a);return d};goog.object.some=function(a,b,c){for(var d in a)if(b.call(c,a[d],d,a))return!0;return!1};\ngoog.object.every=function(a,b,c){for(var d in a)if(!b.call(c,a[d],d,a))return!1;return!0};goog.object.getCount=function(a){var b=0,c;for(c in a)b++;return b};goog.object.getAnyKey=function(a){for(var b in a)return b};goog.object.getAnyValue=function(a){for(var b in a)return a[b]};goog.object.contains=function(a,b){return goog.object.containsValue(a,b)};goog.object.getValues=function(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b};\ngoog.object.getKeys=function(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b};goog.object.getValueByKeys=function(a,b){for(var c=goog.isArrayLike(b),d=c?b:arguments,c=c?0:1;c<d.length&&(a=a[d[c]],goog.isDef(a));c++);return a};goog.object.containsKey=function(a,b){return null!==a&&b in a};goog.object.containsValue=function(a,b){for(var c in a)if(a[c]==b)return!0;return!1};goog.object.findKey=function(a,b,c){for(var d in a)if(b.call(c,a[d],d,a))return d};\ngoog.object.findValue=function(a,b,c){return(b=goog.object.findKey(a,b,c))&&a[b]};goog.object.isEmpty=function(a){for(var b in a)return!1;return!0};goog.object.clear=function(a){for(var b in a)delete a[b]};goog.object.remove=function(a,b){var c;(c=b in a)&&delete a[b];return c};goog.object.add=function(a,b,c){if(null!==a&&b in a)throw Error('The object already contains the key \"'+b+'\"');goog.object.set(a,b,c)};goog.object.get=function(a,b,c){return null!==a&&b in a?a[b]:c};\ngoog.object.set=function(a,b,c){a[b]=c};goog.object.setIfUndefined=function(a,b,c){return b in a?a[b]:a[b]=c};goog.object.setWithReturnValueIfNotSet=function(a,b,c){if(b in a)return a[b];c=c();return a[b]=c};goog.object.equals=function(a,b){for(var c in a)if(!(c in b)||a[c]!==b[c])return!1;for(c in b)if(!(c in a))return!1;return!0};goog.object.clone=function(a){var b={},c;for(c in a)b[c]=a[c];return b};\ngoog.object.unsafeClone=function(a){var b=goog.typeOf(a);if(\"object\"==b||\"array\"==b){if(goog.isFunction(a.clone))return a.clone();var b=\"array\"==b?[]:{},c;for(c in a)b[c]=goog.object.unsafeClone(a[c]);return b}return a};goog.object.transpose=function(a){var b={},c;for(c in a)b[a[c]]=c;return b};goog.object.PROTOTYPE_FIELDS_=\"constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf\".split(\" \");\ngoog.object.extend=function(a,b){for(var c,d,e=1;e<arguments.length;e++){d=arguments[e];for(c in d)a[c]=d[c];for(var f=0;f<goog.object.PROTOTYPE_FIELDS_.length;f++)c=goog.object.PROTOTYPE_FIELDS_[f],Object.prototype.hasOwnProperty.call(d,c)&&(a[c]=d[c])}};\ngoog.object.create=function(a){var b=arguments.length;if(1==b&&goog.isArray(arguments[0]))return goog.object.create.apply(null,arguments[0]);if(b%2)throw Error(\"Uneven number of arguments\");for(var c={},d=0;d<b;d+=2)c[arguments[d]]=arguments[d+1];return c};goog.object.createSet=function(a){var b=arguments.length;if(1==b&&goog.isArray(arguments[0]))return goog.object.createSet.apply(null,arguments[0]);for(var c={},d=0;d<b;d++)c[arguments[d]]=!0;return c};\ngoog.object.createImmutableView=function(a){var b=a;Object.isFrozen&&!Object.isFrozen(a)&&(b=Object.create(a),Object.freeze(b));return b};goog.object.isImmutableView=function(a){return!!Object.isFrozen&&Object.isFrozen(a)};goog.labs.userAgent.browser={};goog.labs.userAgent.browser.matchOpera_=function(){return goog.labs.userAgent.util.matchUserAgent(\"Opera\")};goog.labs.userAgent.browser.matchIE_=function(){return goog.labs.userAgent.util.matchUserAgent(\"Trident\")||goog.labs.userAgent.util.matchUserAgent(\"MSIE\")};goog.labs.userAgent.browser.matchEdge_=function(){return goog.labs.userAgent.util.matchUserAgent(\"Edge\")};goog.labs.userAgent.browser.matchFirefox_=function(){return goog.labs.userAgent.util.matchUserAgent(\"Firefox\")};\ngoog.labs.userAgent.browser.matchSafari_=function(){return goog.labs.userAgent.util.matchUserAgent(\"Safari\")&&!(goog.labs.userAgent.browser.matchChrome_()||goog.labs.userAgent.browser.matchCoast_()||goog.labs.userAgent.browser.matchOpera_()||goog.labs.userAgent.browser.matchEdge_()||goog.labs.userAgent.browser.isSilk()||goog.labs.userAgent.util.matchUserAgent(\"Android\"))};goog.labs.userAgent.browser.matchCoast_=function(){return goog.labs.userAgent.util.matchUserAgent(\"Coast\")};\ngoog.labs.userAgent.browser.matchIosWebview_=function(){return(goog.labs.userAgent.util.matchUserAgent(\"iPad\")||goog.labs.userAgent.util.matchUserAgent(\"iPhone\"))&&!goog.labs.userAgent.browser.matchSafari_()&&!goog.labs.userAgent.browser.matchChrome_()&&!goog.labs.userAgent.browser.matchCoast_()&&goog.labs.userAgent.util.matchUserAgent(\"AppleWebKit\")};\ngoog.labs.userAgent.browser.matchChrome_=function(){return(goog.labs.userAgent.util.matchUserAgent(\"Chrome\")||goog.labs.userAgent.util.matchUserAgent(\"CriOS\"))&&!goog.labs.userAgent.browser.matchEdge_()};goog.labs.userAgent.browser.matchAndroidBrowser_=function(){return goog.labs.userAgent.util.matchUserAgent(\"Android\")&&!(goog.labs.userAgent.browser.isChrome()||goog.labs.userAgent.browser.isFirefox()||goog.labs.userAgent.browser.isOpera()||goog.labs.userAgent.browser.isSilk())};\ngoog.labs.userAgent.browser.isOpera=goog.labs.userAgent.browser.matchOpera_;goog.labs.userAgent.browser.isIE=goog.labs.userAgent.browser.matchIE_;goog.labs.userAgent.browser.isEdge=goog.labs.userAgent.browser.matchEdge_;goog.labs.userAgent.browser.isFirefox=goog.labs.userAgent.browser.matchFirefox_;goog.labs.userAgent.browser.isSafari=goog.labs.userAgent.browser.matchSafari_;goog.labs.userAgent.browser.isCoast=goog.labs.userAgent.browser.matchCoast_;goog.labs.userAgent.browser.isIosWebview=goog.labs.userAgent.browser.matchIosWebview_;\ngoog.labs.userAgent.browser.isChrome=goog.labs.userAgent.browser.matchChrome_;goog.labs.userAgent.browser.isAndroidBrowser=goog.labs.userAgent.browser.matchAndroidBrowser_;goog.labs.userAgent.browser.isSilk=function(){return goog.labs.userAgent.util.matchUserAgent(\"Silk\")};\ngoog.labs.userAgent.browser.getVersion=function(){function a(a){a=goog.array.find(a,d);return c[a]||\"\"}var b=goog.labs.userAgent.util.getUserAgent();if(goog.labs.userAgent.browser.isIE())return goog.labs.userAgent.browser.getIEVersion_(b);var b=goog.labs.userAgent.util.extractVersionTuples(b),c={};goog.array.forEach(b,function(a){c[a[0]]=a[1]});var d=goog.partial(goog.object.containsKey,c);return goog.labs.userAgent.browser.isOpera()?a([\"Version\",\"Opera\"]):goog.labs.userAgent.browser.isEdge()?a([\"Edge\"]):\ngoog.labs.userAgent.browser.isChrome()?a([\"Chrome\",\"CriOS\"]):(b=b[2])&&b[1]||\"\"};goog.labs.userAgent.browser.isVersionOrHigher=function(a){return 0<=goog.string.compareVersions(goog.labs.userAgent.browser.getVersion(),a)};\ngoog.labs.userAgent.browser.getIEVersion_=function(a){var b=/rv: *([\\d\\.]*)/.exec(a);if(b&&b[1])return b[1];var b=\"\",c=/MSIE +([\\d\\.]+)/.exec(a);if(c&&c[1])if(a=/Trident\\/(\\d.\\d)/.exec(a),\"7.0\"==c[1])if(a&&a[1])switch(a[1]){case \"4.0\":b=\"8.0\";break;case \"5.0\":b=\"9.0\";break;case \"6.0\":b=\"10.0\";break;case \"7.0\":b=\"11.0\"}else b=\"7.0\";else b=c[1];return b};goog.labs.userAgent.engine={};goog.labs.userAgent.engine.isPresto=function(){return goog.labs.userAgent.util.matchUserAgent(\"Presto\")};goog.labs.userAgent.engine.isTrident=function(){return goog.labs.userAgent.util.matchUserAgent(\"Trident\")||goog.labs.userAgent.util.matchUserAgent(\"MSIE\")};goog.labs.userAgent.engine.isEdge=function(){return goog.labs.userAgent.util.matchUserAgent(\"Edge\")};\ngoog.labs.userAgent.engine.isWebKit=function(){return goog.labs.userAgent.util.matchUserAgentIgnoreCase(\"WebKit\")&&!goog.labs.userAgent.engine.isEdge()};goog.labs.userAgent.engine.isGecko=function(){return goog.labs.userAgent.util.matchUserAgent(\"Gecko\")&&!goog.labs.userAgent.engine.isWebKit()&&!goog.labs.userAgent.engine.isTrident()&&!goog.labs.userAgent.engine.isEdge()};\ngoog.labs.userAgent.engine.getVersion=function(){var a=goog.labs.userAgent.util.getUserAgent();if(a){var a=goog.labs.userAgent.util.extractVersionTuples(a),b=goog.labs.userAgent.engine.getEngineTuple_(a);if(b)return\"Gecko\"==b[0]?goog.labs.userAgent.engine.getVersionForKey_(a,\"Firefox\"):b[1];var a=a[0],c;if(a&&(c=a[2])&&(c=/Trident\\/([^\\s;]+)/.exec(c)))return c[1]}return\"\"};\ngoog.labs.userAgent.engine.getEngineTuple_=function(a){if(!goog.labs.userAgent.engine.isEdge())return a[1];for(var b=0;b<a.length;b++){var c=a[b];if(\"Edge\"==c[0])return c}};goog.labs.userAgent.engine.isVersionOrHigher=function(a){return 0<=goog.string.compareVersions(goog.labs.userAgent.engine.getVersion(),a)};goog.labs.userAgent.engine.getVersionForKey_=function(a,b){var c=goog.array.find(a,function(a){return b==a[0]});return c&&c[1]||\"\"};goog.labs.userAgent.platform={};goog.labs.userAgent.platform.isAndroid=function(){return goog.labs.userAgent.util.matchUserAgent(\"Android\")};goog.labs.userAgent.platform.isIpod=function(){return goog.labs.userAgent.util.matchUserAgent(\"iPod\")};goog.labs.userAgent.platform.isIphone=function(){return goog.labs.userAgent.util.matchUserAgent(\"iPhone\")&&!goog.labs.userAgent.util.matchUserAgent(\"iPod\")&&!goog.labs.userAgent.util.matchUserAgent(\"iPad\")};goog.labs.userAgent.platform.isIpad=function(){return goog.labs.userAgent.util.matchUserAgent(\"iPad\")};\ngoog.labs.userAgent.platform.isIos=function(){return goog.labs.userAgent.platform.isIphone()||goog.labs.userAgent.platform.isIpad()||goog.labs.userAgent.platform.isIpod()};goog.labs.userAgent.platform.isMacintosh=function(){return goog.labs.userAgent.util.matchUserAgent(\"Macintosh\")};goog.labs.userAgent.platform.isLinux=function(){return goog.labs.userAgent.util.matchUserAgent(\"Linux\")};goog.labs.userAgent.platform.isWindows=function(){return goog.labs.userAgent.util.matchUserAgent(\"Windows\")};\ngoog.labs.userAgent.platform.isChromeOS=function(){return goog.labs.userAgent.util.matchUserAgent(\"CrOS\")};\ngoog.labs.userAgent.platform.getVersion=function(){var a=goog.labs.userAgent.util.getUserAgent(),b=\"\";goog.labs.userAgent.platform.isWindows()?(b=/Windows (?:NT|Phone) ([0-9.]+)/,b=(a=b.exec(a))?a[1]:\"0.0\"):goog.labs.userAgent.platform.isIos()?(b=/(?:iPhone|iPod|iPad|CPU)\\s+OS\\s+(\\S+)/,b=(a=b.exec(a))&&a[1].replace(/_/g,\".\")):goog.labs.userAgent.platform.isMacintosh()?(b=/Mac OS X ([0-9_.]+)/,b=(a=b.exec(a))?a[1].replace(/_/g,\".\"):\"10\"):goog.labs.userAgent.platform.isAndroid()?(b=/Android\\s+([^\\);]+)(\\)|;)/,\nb=(a=b.exec(a))&&a[1]):goog.labs.userAgent.platform.isChromeOS()&&(b=/(?:CrOS\\s+(?:i686|x86_64)\\s+([0-9.]+))/,b=(a=b.exec(a))&&a[1]);return b||\"\"};goog.labs.userAgent.platform.isVersionOrHigher=function(a){return 0<=goog.string.compareVersions(goog.labs.userAgent.platform.getVersion(),a)};goog.userAgent={};goog.userAgent.ASSUME_IE=!1;goog.userAgent.ASSUME_EDGE=!1;goog.userAgent.ASSUME_GECKO=!1;goog.userAgent.ASSUME_WEBKIT=!1;goog.userAgent.ASSUME_MOBILE_WEBKIT=!1;goog.userAgent.ASSUME_OPERA=!1;goog.userAgent.ASSUME_ANY_VERSION=!1;goog.userAgent.BROWSER_KNOWN_=goog.userAgent.ASSUME_IE||goog.userAgent.ASSUME_EDGE||goog.userAgent.ASSUME_GECKO||goog.userAgent.ASSUME_MOBILE_WEBKIT||goog.userAgent.ASSUME_WEBKIT||goog.userAgent.ASSUME_OPERA;goog.userAgent.getUserAgentString=function(){return goog.labs.userAgent.util.getUserAgent()};\ngoog.userAgent.getNavigator=function(){return goog.global.navigator||null};goog.userAgent.OPERA=goog.userAgent.BROWSER_KNOWN_?goog.userAgent.ASSUME_OPERA:goog.labs.userAgent.browser.isOpera();goog.userAgent.IE=goog.userAgent.BROWSER_KNOWN_?goog.userAgent.ASSUME_IE:goog.labs.userAgent.browser.isIE();goog.userAgent.EDGE=goog.userAgent.BROWSER_KNOWN_?goog.userAgent.ASSUME_EDGE:goog.labs.userAgent.engine.isEdge();goog.userAgent.EDGE_OR_IE=goog.userAgent.EDGE||goog.userAgent.IE;\ngoog.userAgent.GECKO=goog.userAgent.BROWSER_KNOWN_?goog.userAgent.ASSUME_GECKO:goog.labs.userAgent.engine.isGecko();goog.userAgent.WEBKIT=goog.userAgent.BROWSER_KNOWN_?goog.userAgent.ASSUME_WEBKIT||goog.userAgent.ASSUME_MOBILE_WEBKIT:goog.labs.userAgent.engine.isWebKit();goog.userAgent.isMobile_=function(){return goog.userAgent.WEBKIT&&goog.labs.userAgent.util.matchUserAgent(\"Mobile\")};goog.userAgent.MOBILE=goog.userAgent.ASSUME_MOBILE_WEBKIT||goog.userAgent.isMobile_();goog.userAgent.SAFARI=goog.userAgent.WEBKIT;\ngoog.userAgent.determinePlatform_=function(){var a=goog.userAgent.getNavigator();return a&&a.platform||\"\"};goog.userAgent.PLATFORM=goog.userAgent.determinePlatform_();goog.userAgent.ASSUME_MAC=!1;goog.userAgent.ASSUME_WINDOWS=!1;goog.userAgent.ASSUME_LINUX=!1;goog.userAgent.ASSUME_X11=!1;goog.userAgent.ASSUME_ANDROID=!1;goog.userAgent.ASSUME_IPHONE=!1;goog.userAgent.ASSUME_IPAD=!1;goog.userAgent.ASSUME_IPOD=!1;\ngoog.userAgent.PLATFORM_KNOWN_=goog.userAgent.ASSUME_MAC||goog.userAgent.ASSUME_WINDOWS||goog.userAgent.ASSUME_LINUX||goog.userAgent.ASSUME_X11||goog.userAgent.ASSUME_ANDROID||goog.userAgent.ASSUME_IPHONE||goog.userAgent.ASSUME_IPAD||goog.userAgent.ASSUME_IPOD;goog.userAgent.MAC=goog.userAgent.PLATFORM_KNOWN_?goog.userAgent.ASSUME_MAC:goog.labs.userAgent.platform.isMacintosh();goog.userAgent.WINDOWS=goog.userAgent.PLATFORM_KNOWN_?goog.userAgent.ASSUME_WINDOWS:goog.labs.userAgent.platform.isWindows();\ngoog.userAgent.isLegacyLinux_=function(){return goog.labs.userAgent.platform.isLinux()||goog.labs.userAgent.platform.isChromeOS()};goog.userAgent.LINUX=goog.userAgent.PLATFORM_KNOWN_?goog.userAgent.ASSUME_LINUX:goog.userAgent.isLegacyLinux_();goog.userAgent.isX11_=function(){var a=goog.userAgent.getNavigator();return!!a&&goog.string.contains(a.appVersion||\"\",\"X11\")};goog.userAgent.X11=goog.userAgent.PLATFORM_KNOWN_?goog.userAgent.ASSUME_X11:goog.userAgent.isX11_();\ngoog.userAgent.ANDROID=goog.userAgent.PLATFORM_KNOWN_?goog.userAgent.ASSUME_ANDROID:goog.labs.userAgent.platform.isAndroid();goog.userAgent.IPHONE=goog.userAgent.PLATFORM_KNOWN_?goog.userAgent.ASSUME_IPHONE:goog.labs.userAgent.platform.isIphone();goog.userAgent.IPAD=goog.userAgent.PLATFORM_KNOWN_?goog.userAgent.ASSUME_IPAD:goog.labs.userAgent.platform.isIpad();goog.userAgent.IPOD=goog.userAgent.PLATFORM_KNOWN_?goog.userAgent.ASSUME_IPOD:goog.labs.userAgent.platform.isIpod();\ngoog.userAgent.determineVersion_=function(){var a=\"\",b=goog.userAgent.getVersionRegexResult_();b&&(a=b?b[1]:\"\");return goog.userAgent.IE&&(b=goog.userAgent.getDocumentMode_(),null!=b&&b>parseFloat(a))?String(b):a};\ngoog.userAgent.getVersionRegexResult_=function(){var a=goog.userAgent.getUserAgentString();if(goog.userAgent.GECKO)return/rv\\:([^\\);]+)(\\)|;)/.exec(a);if(goog.userAgent.EDGE)return/Edge\\/([\\d\\.]+)/.exec(a);if(goog.userAgent.IE)return/\\b(?:MSIE|rv)[: ]([^\\);]+)(\\)|;)/.exec(a);if(goog.userAgent.WEBKIT)return/WebKit\\/(\\S+)/.exec(a);if(goog.userAgent.OPERA)return/(?:Version)[ \\/]?(\\S+)/.exec(a)};goog.userAgent.getDocumentMode_=function(){var a=goog.global.document;return a?a.documentMode:void 0};\ngoog.userAgent.VERSION=goog.userAgent.determineVersion_();goog.userAgent.compare=function(a,b){return goog.string.compareVersions(a,b)};goog.userAgent.isVersionOrHigherCache_={};goog.userAgent.isVersionOrHigher=function(a){return goog.userAgent.ASSUME_ANY_VERSION||goog.userAgent.isVersionOrHigherCache_[a]||(goog.userAgent.isVersionOrHigherCache_[a]=0<=goog.string.compareVersions(goog.userAgent.VERSION,a))};goog.userAgent.isVersion=goog.userAgent.isVersionOrHigher;\ngoog.userAgent.isDocumentModeOrHigher=function(a){return Number(goog.userAgent.DOCUMENT_MODE)>=a};goog.userAgent.isDocumentMode=goog.userAgent.isDocumentModeOrHigher;goog.userAgent.DOCUMENT_MODE=function(){var a=goog.global.document,b=goog.userAgent.getDocumentMode_();return a&&goog.userAgent.IE?b||(\"CSS1Compat\"==a.compatMode?parseInt(goog.userAgent.VERSION,10):5):void 0}();goog.Thenable=function(){};goog.Thenable.prototype.then=function(a,b,c){};goog.Thenable.IMPLEMENTED_BY_PROP=\"$goog_Thenable\";goog.Thenable.addImplementation=function(a){goog.exportProperty(a.prototype,\"then\",a.prototype.then);COMPILED?a.prototype[goog.Thenable.IMPLEMENTED_BY_PROP]=!0:a.prototype.$goog_Thenable=!0};goog.Thenable.isImplementedBy=function(a){if(!a)return!1;try{return COMPILED?!!a[goog.Thenable.IMPLEMENTED_BY_PROP]:!!a.$goog_Thenable}catch(b){return!1}};goog.async={};goog.async.FreeList=function(a,b,c){this.limit_=c;this.create_=a;this.reset_=b;this.occupants_=0;this.head_=null};goog.async.FreeList.prototype.get=function(){var a;0<this.occupants_?(this.occupants_--,a=this.head_,this.head_=a.next,a.next=null):a=this.create_();return a};goog.async.FreeList.prototype.put=function(a){this.reset_(a);this.occupants_<this.limit_&&(this.occupants_++,a.next=this.head_,this.head_=a)};goog.async.FreeList.prototype.occupants=function(){return this.occupants_};goog.async.WorkQueue=function(){this.workTail_=this.workHead_=null};goog.async.WorkQueue.DEFAULT_MAX_UNUSED=100;goog.async.WorkQueue.freelist_=new goog.async.FreeList(function(){return new goog.async.WorkItem},function(a){a.reset()},goog.async.WorkQueue.DEFAULT_MAX_UNUSED);goog.async.WorkQueue.prototype.add=function(a,b){var c=this.getUnusedItem_();c.set(a,b);this.workTail_?this.workTail_.next=c:(goog.asserts.assert(!this.workHead_),this.workHead_=c);this.workTail_=c};\ngoog.async.WorkQueue.prototype.remove=function(){var a=null;this.workHead_&&(a=this.workHead_,this.workHead_=this.workHead_.next,this.workHead_||(this.workTail_=null),a.next=null);return a};goog.async.WorkQueue.prototype.returnUnused=function(a){goog.async.WorkQueue.freelist_.put(a)};goog.async.WorkQueue.prototype.getUnusedItem_=function(){return goog.async.WorkQueue.freelist_.get()};goog.async.WorkItem=function(){this.next=this.scope=this.fn=null};\ngoog.async.WorkItem.prototype.set=function(a,b){this.fn=a;this.scope=b;this.next=null};goog.async.WorkItem.prototype.reset=function(){this.next=this.scope=this.fn=null};goog.debug.entryPointRegistry={};goog.debug.EntryPointMonitor=function(){};goog.debug.entryPointRegistry.refList_=[];goog.debug.entryPointRegistry.monitors_=[];goog.debug.entryPointRegistry.monitorsMayExist_=!1;goog.debug.entryPointRegistry.register=function(a){goog.debug.entryPointRegistry.refList_[goog.debug.entryPointRegistry.refList_.length]=a;if(goog.debug.entryPointRegistry.monitorsMayExist_)for(var b=goog.debug.entryPointRegistry.monitors_,c=0;c<b.length;c++)a(goog.bind(b[c].wrap,b[c]))};\ngoog.debug.entryPointRegistry.monitorAll=function(a){goog.debug.entryPointRegistry.monitorsMayExist_=!0;for(var b=goog.bind(a.wrap,a),c=0;c<goog.debug.entryPointRegistry.refList_.length;c++)goog.debug.entryPointRegistry.refList_[c](b);goog.debug.entryPointRegistry.monitors_.push(a)};\ngoog.debug.entryPointRegistry.unmonitorAllIfPossible=function(a){var b=goog.debug.entryPointRegistry.monitors_;goog.asserts.assert(a==b[b.length-1],\"Only the most recent monitor can be unwrapped.\");a=goog.bind(a.unwrap,a);for(var c=0;c<goog.debug.entryPointRegistry.refList_.length;c++)goog.debug.entryPointRegistry.refList_[c](a);b.length--};goog.dom.TagName={A:\"A\",ABBR:\"ABBR\",ACRONYM:\"ACRONYM\",ADDRESS:\"ADDRESS\",APPLET:\"APPLET\",AREA:\"AREA\",ARTICLE:\"ARTICLE\",ASIDE:\"ASIDE\",AUDIO:\"AUDIO\",B:\"B\",BASE:\"BASE\",BASEFONT:\"BASEFONT\",BDI:\"BDI\",BDO:\"BDO\",BIG:\"BIG\",BLOCKQUOTE:\"BLOCKQUOTE\",BODY:\"BODY\",BR:\"BR\",BUTTON:\"BUTTON\",CANVAS:\"CANVAS\",CAPTION:\"CAPTION\",CENTER:\"CENTER\",CITE:\"CITE\",CODE:\"CODE\",COL:\"COL\",COLGROUP:\"COLGROUP\",COMMAND:\"COMMAND\",DATA:\"DATA\",DATALIST:\"DATALIST\",DD:\"DD\",DEL:\"DEL\",DETAILS:\"DETAILS\",DFN:\"DFN\",DIALOG:\"DIALOG\",DIR:\"DIR\",DIV:\"DIV\",\nDL:\"DL\",DT:\"DT\",EM:\"EM\",EMBED:\"EMBED\",FIELDSET:\"FIELDSET\",FIGCAPTION:\"FIGCAPTION\",FIGURE:\"FIGURE\",FONT:\"FONT\",FOOTER:\"FOOTER\",FORM:\"FORM\",FRAME:\"FRAME\",FRAMESET:\"FRAMESET\",H1:\"H1\",H2:\"H2\",H3:\"H3\",H4:\"H4\",H5:\"H5\",H6:\"H6\",HEAD:\"HEAD\",HEADER:\"HEADER\",HGROUP:\"HGROUP\",HR:\"HR\",HTML:\"HTML\",I:\"I\",IFRAME:\"IFRAME\",IMG:\"IMG\",INPUT:\"INPUT\",INS:\"INS\",ISINDEX:\"ISINDEX\",KBD:\"KBD\",KEYGEN:\"KEYGEN\",LABEL:\"LABEL\",LEGEND:\"LEGEND\",LI:\"LI\",LINK:\"LINK\",MAP:\"MAP\",MARK:\"MARK\",MATH:\"MATH\",MENU:\"MENU\",META:\"META\",METER:\"METER\",\nNAV:\"NAV\",NOFRAMES:\"NOFRAMES\",NOSCRIPT:\"NOSCRIPT\",OBJECT:\"OBJECT\",OL:\"OL\",OPTGROUP:\"OPTGROUP\",OPTION:\"OPTION\",OUTPUT:\"OUTPUT\",P:\"P\",PARAM:\"PARAM\",PRE:\"PRE\",PROGRESS:\"PROGRESS\",Q:\"Q\",RP:\"RP\",RT:\"RT\",RUBY:\"RUBY\",S:\"S\",SAMP:\"SAMP\",SCRIPT:\"SCRIPT\",SECTION:\"SECTION\",SELECT:\"SELECT\",SMALL:\"SMALL\",SOURCE:\"SOURCE\",SPAN:\"SPAN\",STRIKE:\"STRIKE\",STRONG:\"STRONG\",STYLE:\"STYLE\",SUB:\"SUB\",SUMMARY:\"SUMMARY\",SUP:\"SUP\",SVG:\"SVG\",TABLE:\"TABLE\",TBODY:\"TBODY\",TD:\"TD\",TEMPLATE:\"TEMPLATE\",TEXTAREA:\"TEXTAREA\",TFOOT:\"TFOOT\",\nTH:\"TH\",THEAD:\"THEAD\",TIME:\"TIME\",TITLE:\"TITLE\",TR:\"TR\",TRACK:\"TRACK\",TT:\"TT\",U:\"U\",UL:\"UL\",VAR:\"VAR\",VIDEO:\"VIDEO\",WBR:\"WBR\"};goog.functions={};goog.functions.constant=function(a){return function(){return a}};goog.functions.FALSE=goog.functions.constant(!1);goog.functions.TRUE=goog.functions.constant(!0);goog.functions.NULL=goog.functions.constant(null);goog.functions.identity=function(a,b){return a};goog.functions.error=function(a){return function(){throw Error(a);}};goog.functions.fail=function(a){return function(){throw a;}};\ngoog.functions.lock=function(a,b){b=b||0;return function(){return a.apply(this,Array.prototype.slice.call(arguments,0,b))}};goog.functions.nth=function(a){return function(){return arguments[a]}};goog.functions.partialRight=function(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var b=Array.prototype.slice.call(arguments);b.push.apply(b,c);return a.apply(this,b)}};goog.functions.withReturnValue=function(a,b){return goog.functions.sequence(a,goog.functions.constant(b))};\ngoog.functions.equalTo=function(a,b){return function(c){return b?a==c:a===c}};goog.functions.compose=function(a,b){var c=arguments,d=c.length;return function(){var a;d&&(a=c[d-1].apply(this,arguments));for(var b=d-2;0<=b;b--)a=c[b].call(this,a);return a}};goog.functions.sequence=function(a){var b=arguments,c=b.length;return function(){for(var a,e=0;e<c;e++)a=b[e].apply(this,arguments);return a}};\ngoog.functions.and=function(a){var b=arguments,c=b.length;return function(){for(var a=0;a<c;a++)if(!b[a].apply(this,arguments))return!1;return!0}};goog.functions.or=function(a){var b=arguments,c=b.length;return function(){for(var a=0;a<c;a++)if(b[a].apply(this,arguments))return!0;return!1}};goog.functions.not=function(a){return function(){return!a.apply(this,arguments)}};\ngoog.functions.create=function(a,b){var c=function(){};c.prototype=a.prototype;c=new c;a.apply(c,Array.prototype.slice.call(arguments,1));return c};goog.functions.CACHE_RETURN_VALUE=!0;goog.functions.cacheReturnValue=function(a){var b=!1,c;return function(){if(!goog.functions.CACHE_RETURN_VALUE)return a();b||(c=a(),b=!0);return c}};goog.functions.once=function(a){var b=a;return function(){if(b){var a=b;b=null;a()}}};\ngoog.functions.debounce=function(a,b,c){c&&(a=goog.bind(a,c));var d=null;return function(c){goog.global.clearTimeout(d);var f=arguments;d=goog.global.setTimeout(function(){a.apply(null,f)},b)}};goog.functions.throttle=function(a,b,c){c&&(a=goog.bind(a,c));var d=null,e=!1,f=[],g=function(){d=null;e&&(e=!1,h())},h=function(){d=goog.global.setTimeout(g,b);a.apply(null,f)};return function(a){f=arguments;d?e=!0:h()}};goog.async.throwException=function(a){goog.global.setTimeout(function(){throw a;},0)};goog.async.nextTick=function(a,b,c){var d=a;b&&(d=goog.bind(a,b));d=goog.async.nextTick.wrapCallback_(d);goog.isFunction(goog.global.setImmediate)&&(c||goog.async.nextTick.useSetImmediate_())?goog.global.setImmediate(d):(goog.async.nextTick.setImmediate_||(goog.async.nextTick.setImmediate_=goog.async.nextTick.getSetImmediateEmulator_()),goog.async.nextTick.setImmediate_(d))};\ngoog.async.nextTick.useSetImmediate_=function(){return goog.global.Window&&goog.global.Window.prototype&&!goog.labs.userAgent.browser.isEdge()&&goog.global.Window.prototype.setImmediate==goog.global.setImmediate?!1:!0};\ngoog.async.nextTick.getSetImmediateEmulator_=function(){var a=goog.global.MessageChannel;\"undefined\"===typeof a&&\"undefined\"!==typeof window&&window.postMessage&&window.addEventListener&&!goog.labs.userAgent.engine.isPresto()&&(a=function(){var a=document.createElement(\"IFRAME\");a.style.display=\"none\";a.src=\"\";document.documentElement.appendChild(a);var b=a.contentWindow,a=b.document;a.open();a.write(\"\");a.close();var c=\"callImmediate\"+Math.random(),d=\"file:\"==b.location.protocol?\"*\":b.location.protocol+\n\"//\"+b.location.host,a=goog.bind(function(a){if((\"*\"==d||a.origin==d)&&a.data==c)this.port1.onmessage()},this);b.addEventListener(\"message\",a,!1);this.port1={};this.port2={postMessage:function(){b.postMessage(c,d)}}});if(\"undefined\"!==typeof a&&!goog.labs.userAgent.browser.isIE()){var b=new a,c={},d=c;b.port1.onmessage=function(){if(goog.isDef(c.next)){c=c.next;var a=c.cb;c.cb=null;a()}};return function(a){d.next={cb:a};d=d.next;b.port2.postMessage(0)}}return\"undefined\"!==typeof document&&\"onreadystatechange\"in\ndocument.createElement(\"SCRIPT\")?function(a){var b=document.createElement(\"SCRIPT\");b.onreadystatechange=function(){b.onreadystatechange=null;b.parentNode.removeChild(b);b=null;a();a=null};document.documentElement.appendChild(b)}:function(a){goog.global.setTimeout(a,0)}};goog.async.nextTick.wrapCallback_=goog.functions.identity;goog.debug.entryPointRegistry.register(function(a){goog.async.nextTick.wrapCallback_=a});goog.async.run=function(a,b){goog.async.run.schedule_||goog.async.run.initializeRunner_();goog.async.run.workQueueScheduled_||(goog.async.run.schedule_(),goog.async.run.workQueueScheduled_=!0);goog.async.run.workQueue_.add(a,b)};goog.async.run.initializeRunner_=function(){if(goog.global.Promise&&goog.global.Promise.resolve){var a=goog.global.Promise.resolve(void 0);goog.async.run.schedule_=function(){a.then(goog.async.run.processWorkQueue)}}else goog.async.run.schedule_=function(){goog.async.nextTick(goog.async.run.processWorkQueue)}};\ngoog.async.run.forceNextTick=function(a){goog.async.run.schedule_=function(){goog.async.nextTick(goog.async.run.processWorkQueue);a&&a(goog.async.run.processWorkQueue)}};goog.async.run.workQueueScheduled_=!1;goog.async.run.workQueue_=new goog.async.WorkQueue;goog.DEBUG&&(goog.async.run.resetQueue=function(){goog.async.run.workQueueScheduled_=!1;goog.async.run.workQueue_=new goog.async.WorkQueue});\ngoog.async.run.processWorkQueue=function(){for(var a;a=goog.async.run.workQueue_.remove();){try{a.fn.call(a.scope)}catch(b){goog.async.throwException(b)}goog.async.run.workQueue_.returnUnused(a)}goog.async.run.workQueueScheduled_=!1};goog.promise={};goog.promise.Resolver=function(){};goog.Promise=function(a,b){this.state_=goog.Promise.State_.PENDING;this.result_=void 0;this.callbackEntriesTail_=this.callbackEntries_=this.parent_=null;this.executing_=!1;0<goog.Promise.UNHANDLED_REJECTION_DELAY?this.unhandledRejectionId_=0:0==goog.Promise.UNHANDLED_REJECTION_DELAY&&(this.hadUnhandledRejection_=!1);goog.Promise.LONG_STACK_TRACES&&(this.stack_=[],this.addStackTrace_(Error(\"created\")),this.currentStep_=0);if(a!=goog.nullFunction)try{var c=this;a.call(b,function(a){c.resolve_(goog.Promise.State_.FULFILLED,\na)},function(a){if(goog.DEBUG&&!(a instanceof goog.Promise.CancellationError))try{if(a instanceof Error)throw a;throw Error(\"Promise rejected.\");}catch(b){}c.resolve_(goog.Promise.State_.REJECTED,a)})}catch(d){this.resolve_(goog.Promise.State_.REJECTED,d)}};goog.Promise.LONG_STACK_TRACES=!1;goog.Promise.UNHANDLED_REJECTION_DELAY=0;goog.Promise.State_={PENDING:0,BLOCKED:1,FULFILLED:2,REJECTED:3};\ngoog.Promise.CallbackEntry_=function(){this.next=this.context=this.onRejected=this.onFulfilled=this.child=null;this.always=!1};goog.Promise.CallbackEntry_.prototype.reset=function(){this.context=this.onRejected=this.onFulfilled=this.child=null;this.always=!1};goog.Promise.DEFAULT_MAX_UNUSED=100;goog.Promise.freelist_=new goog.async.FreeList(function(){return new goog.Promise.CallbackEntry_},function(a){a.reset()},goog.Promise.DEFAULT_MAX_UNUSED);\ngoog.Promise.getCallbackEntry_=function(a,b,c){var d=goog.Promise.freelist_.get();d.onFulfilled=a;d.onRejected=b;d.context=c;return d};goog.Promise.returnEntry_=function(a){goog.Promise.freelist_.put(a)};goog.Promise.resolve=function(a){if(a instanceof goog.Promise)return a;var b=new goog.Promise(goog.nullFunction);b.resolve_(goog.Promise.State_.FULFILLED,a);return b};goog.Promise.reject=function(a){return new goog.Promise(function(b,c){c(a)})};\ngoog.Promise.resolveThen_=function(a,b,c){goog.Promise.maybeThen_(a,b,c,null)||goog.async.run(goog.partial(b,a))};goog.Promise.race=function(a){return new goog.Promise(function(b,c){a.length||b(void 0);for(var d=0,e;d<a.length;d++)e=a[d],goog.Promise.resolveThen_(e,b,c)})};\ngoog.Promise.all=function(a){return new goog.Promise(function(b,c){var d=a.length,e=[];if(d)for(var f=function(a,c){d--;e[a]=c;0==d&&b(e)},g=function(a){c(a)},h=0,k;h<a.length;h++)k=a[h],goog.Promise.resolveThen_(k,goog.partial(f,h),g);else b(e)})};\ngoog.Promise.allSettled=function(a){return new goog.Promise(function(b,c){var d=a.length,e=[];if(d)for(var f=function(a,c,f){d--;e[a]=c?{fulfilled:!0,value:f}:{fulfilled:!1,reason:f};0==d&&b(e)},g=0,h;g<a.length;g++)h=a[g],goog.Promise.resolveThen_(h,goog.partial(f,g,!0),goog.partial(f,g,!1));else b(e)})};\ngoog.Promise.firstFulfilled=function(a){return new goog.Promise(function(b,c){var d=a.length,e=[];if(d)for(var f=function(a){b(a)},g=function(a,b){d--;e[a]=b;0==d&&c(e)},h=0,k;h<a.length;h++)k=a[h],goog.Promise.resolveThen_(k,f,goog.partial(g,h));else b(void 0)})};goog.Promise.withResolver=function(){var a,b,c=new goog.Promise(function(c,e){a=c;b=e});return new goog.Promise.Resolver_(c,a,b)};\ngoog.Promise.prototype.then=function(a,b,c){null!=a&&goog.asserts.assertFunction(a,\"opt_onFulfilled should be a function.\");null!=b&&goog.asserts.assertFunction(b,\"opt_onRejected should be a function. Did you pass opt_context as the second argument instead of the third?\");goog.Promise.LONG_STACK_TRACES&&this.addStackTrace_(Error(\"then\"));return this.addChildPromise_(goog.isFunction(a)?a:null,goog.isFunction(b)?b:null,c)};goog.Thenable.addImplementation(goog.Promise);\ngoog.Promise.prototype.thenVoid=function(a,b,c){null!=a&&goog.asserts.assertFunction(a,\"opt_onFulfilled should be a function.\");null!=b&&goog.asserts.assertFunction(b,\"opt_onRejected should be a function. Did you pass opt_context as the second argument instead of the third?\");goog.Promise.LONG_STACK_TRACES&&this.addStackTrace_(Error(\"then\"));this.addCallbackEntry_(goog.Promise.getCallbackEntry_(a||goog.nullFunction,b||null,c))};\ngoog.Promise.prototype.thenAlways=function(a,b){goog.Promise.LONG_STACK_TRACES&&this.addStackTrace_(Error(\"thenAlways\"));var c=goog.Promise.getCallbackEntry_(a,a,b);c.always=!0;this.addCallbackEntry_(c);return this};goog.Promise.prototype.thenCatch=function(a,b){goog.Promise.LONG_STACK_TRACES&&this.addStackTrace_(Error(\"thenCatch\"));return this.addChildPromise_(null,a,b)};\ngoog.Promise.prototype.cancel=function(a){this.state_==goog.Promise.State_.PENDING&&goog.async.run(function(){var b=new goog.Promise.CancellationError(a);this.cancelInternal_(b)},this)};goog.Promise.prototype.cancelInternal_=function(a){this.state_==goog.Promise.State_.PENDING&&(this.parent_?(this.parent_.cancelChild_(this,a),this.parent_=null):this.resolve_(goog.Promise.State_.REJECTED,a))};\ngoog.Promise.prototype.cancelChild_=function(a,b){if(this.callbackEntries_){for(var c=0,d=null,e=null,f=this.callbackEntries_;f&&(f.always||(c++,f.child==a&&(d=f),!(d&&1<c)));f=f.next)d||(e=f);d&&(this.state_==goog.Promise.State_.PENDING&&1==c?this.cancelInternal_(b):(e?this.removeEntryAfter_(e):this.popEntry_(),this.executeCallback_(d,goog.Promise.State_.REJECTED,b)))}};\ngoog.Promise.prototype.addCallbackEntry_=function(a){this.hasEntry_()||this.state_!=goog.Promise.State_.FULFILLED&&this.state_!=goog.Promise.State_.REJECTED||this.scheduleCallbacks_();this.queueEntry_(a)};\ngoog.Promise.prototype.addChildPromise_=function(a,b,c){var d=goog.Promise.getCallbackEntry_(null,null,null);d.child=new goog.Promise(function(e,f){d.onFulfilled=a?function(b){try{var d=a.call(c,b);e(d)}catch(k){f(k)}}:e;d.onRejected=b?function(a){try{var d=b.call(c,a);!goog.isDef(d)&&a instanceof goog.Promise.CancellationError?f(a):e(d)}catch(k){f(k)}}:f});d.child.parent_=this;this.addCallbackEntry_(d);return d.child};\ngoog.Promise.prototype.unblockAndFulfill_=function(a){goog.asserts.assert(this.state_==goog.Promise.State_.BLOCKED);this.state_=goog.Promise.State_.PENDING;this.resolve_(goog.Promise.State_.FULFILLED,a)};goog.Promise.prototype.unblockAndReject_=function(a){goog.asserts.assert(this.state_==goog.Promise.State_.BLOCKED);this.state_=goog.Promise.State_.PENDING;this.resolve_(goog.Promise.State_.REJECTED,a)};\ngoog.Promise.prototype.resolve_=function(a,b){this.state_==goog.Promise.State_.PENDING&&(this===b&&(a=goog.Promise.State_.REJECTED,b=new TypeError(\"Promise cannot resolve to itself\")),this.state_=goog.Promise.State_.BLOCKED,goog.Promise.maybeThen_(b,this.unblockAndFulfill_,this.unblockAndReject_,this)||(this.result_=b,this.state_=a,this.parent_=null,this.scheduleCallbacks_(),a!=goog.Promise.State_.REJECTED||b instanceof goog.Promise.CancellationError||goog.Promise.addUnhandledRejection_(this,b)))};\ngoog.Promise.maybeThen_=function(a,b,c,d){if(a instanceof goog.Promise)return a.thenVoid(b,c,d),!0;if(goog.Thenable.isImplementedBy(a))return a.then(b,c,d),!0;if(goog.isObject(a))try{var e=a.then;if(goog.isFunction(e))return goog.Promise.tryThen_(a,e,b,c,d),!0}catch(f){return c.call(d,f),!0}return!1};goog.Promise.tryThen_=function(a,b,c,d,e){var f=!1,g=function(a){f||(f=!0,c.call(e,a))},h=function(a){f||(f=!0,d.call(e,a))};try{b.call(a,g,h)}catch(k){h(k)}};\ngoog.Promise.prototype.scheduleCallbacks_=function(){this.executing_||(this.executing_=!0,goog.async.run(this.executeCallbacks_,this))};goog.Promise.prototype.hasEntry_=function(){return!!this.callbackEntries_};goog.Promise.prototype.queueEntry_=function(a){goog.asserts.assert(null!=a.onFulfilled);this.callbackEntriesTail_?this.callbackEntriesTail_.next=a:this.callbackEntries_=a;this.callbackEntriesTail_=a};\ngoog.Promise.prototype.popEntry_=function(){var a=null;this.callbackEntries_&&(a=this.callbackEntries_,this.callbackEntries_=a.next,a.next=null);this.callbackEntries_||(this.callbackEntriesTail_=null);null!=a&&goog.asserts.assert(null!=a.onFulfilled);return a};goog.Promise.prototype.removeEntryAfter_=function(a){goog.asserts.assert(this.callbackEntries_);goog.asserts.assert(null!=a);a.next==this.callbackEntriesTail_&&(this.callbackEntriesTail_=a);a.next=a.next.next};\ngoog.Promise.prototype.executeCallbacks_=function(){for(var a;a=this.popEntry_();)goog.Promise.LONG_STACK_TRACES&&this.currentStep_++,this.executeCallback_(a,this.state_,this.result_);this.executing_=!1};\ngoog.Promise.prototype.executeCallback_=function(a,b,c){b==goog.Promise.State_.REJECTED&&a.onRejected&&!a.always&&this.removeUnhandledRejection_();if(a.child)a.child.parent_=null,goog.Promise.invokeCallback_(a,b,c);else try{a.always?a.onFulfilled.call(a.context):goog.Promise.invokeCallback_(a,b,c)}catch(d){goog.Promise.handleRejection_.call(null,d)}goog.Promise.returnEntry_(a)};\ngoog.Promise.invokeCallback_=function(a,b,c){b==goog.Promise.State_.FULFILLED?a.onFulfilled.call(a.context,c):a.onRejected&&a.onRejected.call(a.context,c)};goog.Promise.prototype.addStackTrace_=function(a){if(goog.Promise.LONG_STACK_TRACES&&goog.isString(a.stack)){var b=a.stack.split(\"\\n\",4)[3];a=a.message;a+=Array(11-a.length).join(\" \");this.stack_.push(a+b)}};\ngoog.Promise.prototype.appendLongStack_=function(a){if(goog.Promise.LONG_STACK_TRACES&&a&&goog.isString(a.stack)&&this.stack_.length){for(var b=[\"Promise trace:\"],c=this;c;c=c.parent_){for(var d=this.currentStep_;0<=d;d--)b.push(c.stack_[d]);b.push(\"Value: [\"+(c.state_==goog.Promise.State_.REJECTED?\"REJECTED\":\"FULFILLED\")+\"] <\"+String(c.result_)+\">\")}a.stack+=\"\\n\\n\"+b.join(\"\\n\")}};\ngoog.Promise.prototype.removeUnhandledRejection_=function(){if(0<goog.Promise.UNHANDLED_REJECTION_DELAY)for(var a=this;a&&a.unhandledRejectionId_;a=a.parent_)goog.global.clearTimeout(a.unhandledRejectionId_),a.unhandledRejectionId_=0;else if(0==goog.Promise.UNHANDLED_REJECTION_DELAY)for(a=this;a&&a.hadUnhandledRejection_;a=a.parent_)a.hadUnhandledRejection_=!1};\ngoog.Promise.addUnhandledRejection_=function(a,b){0<goog.Promise.UNHANDLED_REJECTION_DELAY?a.unhandledRejectionId_=goog.global.setTimeout(function(){a.appendLongStack_(b);goog.Promise.handleRejection_.call(null,b)},goog.Promise.UNHANDLED_REJECTION_DELAY):0==goog.Promise.UNHANDLED_REJECTION_DELAY&&(a.hadUnhandledRejection_=!0,goog.async.run(function(){a.hadUnhandledRejection_&&(a.appendLongStack_(b),goog.Promise.handleRejection_.call(null,b))}))};goog.Promise.handleRejection_=goog.async.throwException;\ngoog.Promise.setUnhandledRejectionHandler=function(a){goog.Promise.handleRejection_=a};goog.Promise.CancellationError=function(a){goog.debug.Error.call(this,a)};goog.inherits(goog.Promise.CancellationError,goog.debug.Error);goog.Promise.CancellationError.prototype.name=\"cancel\";goog.Promise.Resolver_=function(a,b,c){this.promise=a;this.resolve=b;this.reject=c};goog.disposable={};goog.disposable.IDisposable=function(){};goog.Disposable=function(){goog.Disposable.MONITORING_MODE!=goog.Disposable.MonitoringMode.OFF&&(goog.Disposable.INCLUDE_STACK_ON_CREATION&&(this.creationStack=Error().stack),goog.Disposable.instances_[goog.getUid(this)]=this);this.disposed_=this.disposed_;this.onDisposeCallbacks_=this.onDisposeCallbacks_};goog.Disposable.MonitoringMode={OFF:0,PERMANENT:1,INTERACTIVE:2};goog.Disposable.MONITORING_MODE=0;goog.Disposable.INCLUDE_STACK_ON_CREATION=!0;goog.Disposable.instances_={};\ngoog.Disposable.getUndisposedObjects=function(){var a=[],b;for(b in goog.Disposable.instances_)goog.Disposable.instances_.hasOwnProperty(b)&&a.push(goog.Disposable.instances_[Number(b)]);return a};goog.Disposable.clearUndisposedObjects=function(){goog.Disposable.instances_={}};goog.Disposable.prototype.disposed_=!1;goog.Disposable.prototype.isDisposed=function(){return this.disposed_};goog.Disposable.prototype.getDisposed=goog.Disposable.prototype.isDisposed;\ngoog.Disposable.prototype.dispose=function(){if(!this.disposed_&&(this.disposed_=!0,this.disposeInternal(),goog.Disposable.MONITORING_MODE!=goog.Disposable.MonitoringMode.OFF)){var a=goog.getUid(this);if(goog.Disposable.MONITORING_MODE==goog.Disposable.MonitoringMode.PERMANENT&&!goog.Disposable.instances_.hasOwnProperty(a))throw Error(this+\" did not call the goog.Disposable base constructor or was disposed of after a clearUndisposedObjects call\");delete goog.Disposable.instances_[a]}};\ngoog.Disposable.prototype.registerDisposable=function(a){this.addOnDisposeCallback(goog.partial(goog.dispose,a))};goog.Disposable.prototype.addOnDisposeCallback=function(a,b){this.disposed_?goog.isDef(b)?a.call(b):a():(this.onDisposeCallbacks_||(this.onDisposeCallbacks_=[]),this.onDisposeCallbacks_.push(goog.isDef(b)?goog.bind(a,b):a))};goog.Disposable.prototype.disposeInternal=function(){if(this.onDisposeCallbacks_)for(;this.onDisposeCallbacks_.length;)this.onDisposeCallbacks_.shift()()};\ngoog.Disposable.isDisposed=function(a){return a&&\"function\"==typeof a.isDisposed?a.isDisposed():!1};goog.dispose=function(a){a&&\"function\"==typeof a.dispose&&a.dispose()};goog.disposeAll=function(a){for(var b=0,c=arguments.length;b<c;++b){var d=arguments[b];goog.isArrayLike(d)?goog.disposeAll.apply(null,d):goog.dispose(d)}};goog.events={};\ngoog.events.BrowserFeature={HAS_W3C_BUTTON:!goog.userAgent.IE||goog.userAgent.isDocumentModeOrHigher(9),HAS_W3C_EVENT_SUPPORT:!goog.userAgent.IE||goog.userAgent.isDocumentModeOrHigher(9),SET_KEY_CODE_TO_PREVENT_DEFAULT:goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"9\"),HAS_NAVIGATOR_ONLINE_PROPERTY:!goog.userAgent.WEBKIT||goog.userAgent.isVersionOrHigher(\"528\"),HAS_HTML5_NETWORK_EVENT_SUPPORT:goog.userAgent.GECKO&&goog.userAgent.isVersionOrHigher(\"1.9b\")||goog.userAgent.IE&&goog.userAgent.isVersionOrHigher(\"8\")||\ngoog.userAgent.OPERA&&goog.userAgent.isVersionOrHigher(\"9.5\")||goog.userAgent.WEBKIT&&goog.userAgent.isVersionOrHigher(\"528\"),HTML5_NETWORK_EVENTS_FIRE_ON_BODY:goog.userAgent.GECKO&&!goog.userAgent.isVersionOrHigher(\"8\")||goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"9\"),TOUCH_ENABLED:\"ontouchstart\"in goog.global||!!(goog.global.document&&document.documentElement&&\"ontouchstart\"in document.documentElement)||!(!goog.global.navigator||!goog.global.navigator.msMaxTouchPoints)};goog.events.EventId=function(a){this.id=a};goog.events.EventId.prototype.toString=function(){return this.id};goog.events.Event=function(a,b){this.type=a instanceof goog.events.EventId?String(a):a;this.currentTarget=this.target=b;this.defaultPrevented=this.propagationStopped_=!1;this.returnValue_=!0};goog.events.Event.prototype.stopPropagation=function(){this.propagationStopped_=!0};goog.events.Event.prototype.preventDefault=function(){this.defaultPrevented=!0;this.returnValue_=!1};goog.events.Event.stopPropagation=function(a){a.stopPropagation()};goog.events.Event.preventDefault=function(a){a.preventDefault()};goog.events.getVendorPrefixedName_=function(a){return goog.userAgent.WEBKIT?\"webkit\"+a:goog.userAgent.OPERA?\"o\"+a.toLowerCase():a.toLowerCase()};\ngoog.events.EventType={CLICK:\"click\",RIGHTCLICK:\"rightclick\",DBLCLICK:\"dblclick\",MOUSEDOWN:\"mousedown\",MOUSEUP:\"mouseup\",MOUSEOVER:\"mouseover\",MOUSEOUT:\"mouseout\",MOUSEMOVE:\"mousemove\",MOUSEENTER:\"mouseenter\",MOUSELEAVE:\"mouseleave\",SELECTSTART:\"selectstart\",WHEEL:\"wheel\",KEYPRESS:\"keypress\",KEYDOWN:\"keydown\",KEYUP:\"keyup\",BLUR:\"blur\",FOCUS:\"focus\",DEACTIVATE:\"deactivate\",FOCUSIN:goog.userAgent.IE?\"focusin\":\"DOMFocusIn\",FOCUSOUT:goog.userAgent.IE?\"focusout\":\"DOMFocusOut\",CHANGE:\"change\",RESET:\"reset\",\nSELECT:\"select\",SUBMIT:\"submit\",INPUT:\"input\",PROPERTYCHANGE:\"propertychange\",DRAGSTART:\"dragstart\",DRAG:\"drag\",DRAGENTER:\"dragenter\",DRAGOVER:\"dragover\",DRAGLEAVE:\"dragleave\",DROP:\"drop\",DRAGEND:\"dragend\",TOUCHSTART:\"touchstart\",TOUCHMOVE:\"touchmove\",TOUCHEND:\"touchend\",TOUCHCANCEL:\"touchcancel\",BEFOREUNLOAD:\"beforeunload\",CONSOLEMESSAGE:\"consolemessage\",CONTEXTMENU:\"contextmenu\",DOMCONTENTLOADED:\"DOMContentLoaded\",ERROR:\"error\",HELP:\"help\",LOAD:\"load\",LOSECAPTURE:\"losecapture\",ORIENTATIONCHANGE:\"orientationchange\",\nREADYSTATECHANGE:\"readystatechange\",RESIZE:\"resize\",SCROLL:\"scroll\",UNLOAD:\"unload\",CANPLAY:\"canplay\",CANPLAYTHROUGH:\"canplaythrough\",DURATIONCHANGE:\"durationchange\",EMPTIED:\"emptied\",ENDED:\"ended\",LOADEDDATA:\"loadeddata\",LOADEDMETADATA:\"loadedmetadata\",PAUSE:\"pause\",PLAY:\"play\",PLAYING:\"playing\",RATECHANGE:\"ratechange\",SEEKED:\"seeked\",SEEKING:\"seeking\",STALLED:\"stalled\",SUSPEND:\"suspend\",TIMEUPDATE:\"timeupdate\",VOLUMECHANGE:\"volumechange\",WAITING:\"waiting\",HASHCHANGE:\"hashchange\",PAGEHIDE:\"pagehide\",\nPAGESHOW:\"pageshow\",POPSTATE:\"popstate\",COPY:\"copy\",PASTE:\"paste\",CUT:\"cut\",BEFORECOPY:\"beforecopy\",BEFORECUT:\"beforecut\",BEFOREPASTE:\"beforepaste\",ONLINE:\"online\",OFFLINE:\"offline\",MESSAGE:\"message\",CONNECT:\"connect\",ANIMATIONSTART:goog.events.getVendorPrefixedName_(\"AnimationStart\"),ANIMATIONEND:goog.events.getVendorPrefixedName_(\"AnimationEnd\"),ANIMATIONITERATION:goog.events.getVendorPrefixedName_(\"AnimationIteration\"),TRANSITIONEND:goog.events.getVendorPrefixedName_(\"TransitionEnd\"),POINTERDOWN:\"pointerdown\",\nPOINTERUP:\"pointerup\",POINTERCANCEL:\"pointercancel\",POINTERMOVE:\"pointermove\",POINTEROVER:\"pointerover\",POINTEROUT:\"pointerout\",POINTERENTER:\"pointerenter\",POINTERLEAVE:\"pointerleave\",GOTPOINTERCAPTURE:\"gotpointercapture\",LOSTPOINTERCAPTURE:\"lostpointercapture\",MSGESTURECHANGE:\"MSGestureChange\",MSGESTUREEND:\"MSGestureEnd\",MSGESTUREHOLD:\"MSGestureHold\",MSGESTURESTART:\"MSGestureStart\",MSGESTURETAP:\"MSGestureTap\",MSGOTPOINTERCAPTURE:\"MSGotPointerCapture\",MSINERTIASTART:\"MSInertiaStart\",MSLOSTPOINTERCAPTURE:\"MSLostPointerCapture\",\nMSPOINTERCANCEL:\"MSPointerCancel\",MSPOINTERDOWN:\"MSPointerDown\",MSPOINTERENTER:\"MSPointerEnter\",MSPOINTERHOVER:\"MSPointerHover\",MSPOINTERLEAVE:\"MSPointerLeave\",MSPOINTERMOVE:\"MSPointerMove\",MSPOINTEROUT:\"MSPointerOut\",MSPOINTEROVER:\"MSPointerOver\",MSPOINTERUP:\"MSPointerUp\",TEXT:\"text\",TEXTINPUT:\"textInput\",COMPOSITIONSTART:\"compositionstart\",COMPOSITIONUPDATE:\"compositionupdate\",COMPOSITIONEND:\"compositionend\",EXIT:\"exit\",LOADABORT:\"loadabort\",LOADCOMMIT:\"loadcommit\",LOADREDIRECT:\"loadredirect\",LOADSTART:\"loadstart\",\nLOADSTOP:\"loadstop\",RESPONSIVE:\"responsive\",SIZECHANGED:\"sizechanged\",UNRESPONSIVE:\"unresponsive\",VISIBILITYCHANGE:\"visibilitychange\",STORAGE:\"storage\",DOMSUBTREEMODIFIED:\"DOMSubtreeModified\",DOMNODEINSERTED:\"DOMNodeInserted\",DOMNODEREMOVED:\"DOMNodeRemoved\",DOMNODEREMOVEDFROMDOCUMENT:\"DOMNodeRemovedFromDocument\",DOMNODEINSERTEDINTODOCUMENT:\"DOMNodeInsertedIntoDocument\",DOMATTRMODIFIED:\"DOMAttrModified\",DOMCHARACTERDATAMODIFIED:\"DOMCharacterDataModified\",BEFOREPRINT:\"beforeprint\",AFTERPRINT:\"afterprint\"};goog.reflect={};goog.reflect.object=function(a,b){return b};goog.reflect.objectProperty=function(a,b){return a};goog.reflect.sinkValue=function(a){goog.reflect.sinkValue[\" \"](a);return a};goog.reflect.sinkValue[\" \"]=goog.nullFunction;goog.reflect.canAccessProperty=function(a,b){try{return goog.reflect.sinkValue(a[b]),!0}catch(c){}return!1};goog.reflect.cache=function(a,b,c,d){d=d?d(b):b;return Object.prototype.hasOwnProperty.call(a,d)?a[d]:a[d]=c(b)};goog.events.BrowserEvent=function(a,b){goog.events.Event.call(this,a?a.type:\"\");this.relatedTarget=this.currentTarget=this.target=null;this.charCode=this.keyCode=this.button=this.screenY=this.screenX=this.clientY=this.clientX=this.offsetY=this.offsetX=0;this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.state=null;this.platformModifierKey=!1;this.event_=null;a&&this.init(a,b)};goog.inherits(goog.events.BrowserEvent,goog.events.Event);\ngoog.events.BrowserEvent.MouseButton={LEFT:0,MIDDLE:1,RIGHT:2};goog.events.BrowserEvent.IEButtonMap=[1,4,2];\ngoog.events.BrowserEvent.prototype.init=function(a,b){var c=this.type=a.type,d=a.changedTouches?a.changedTouches[0]:null;this.target=a.target||a.srcElement;this.currentTarget=b;var e=a.relatedTarget;e?goog.userAgent.GECKO&&(goog.reflect.canAccessProperty(e,\"nodeName\")||(e=null)):c==goog.events.EventType.MOUSEOVER?e=a.fromElement:c==goog.events.EventType.MOUSEOUT&&(e=a.toElement);this.relatedTarget=e;goog.isNull(d)?(this.offsetX=goog.userAgent.WEBKIT||void 0!==a.offsetX?a.offsetX:a.layerX,this.offsetY=\ngoog.userAgent.WEBKIT||void 0!==a.offsetY?a.offsetY:a.layerY,this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0):(this.clientX=void 0!==d.clientX?d.clientX:d.pageX,this.clientY=void 0!==d.clientY?d.clientY:d.pageY,this.screenX=d.screenX||0,this.screenY=d.screenY||0);this.button=a.button;this.keyCode=a.keyCode||0;this.charCode=a.charCode||(\"keypress\"==c?a.keyCode:0);this.ctrlKey=a.ctrlKey;this.altKey=\na.altKey;this.shiftKey=a.shiftKey;this.metaKey=a.metaKey;this.platformModifierKey=goog.userAgent.MAC?a.metaKey:a.ctrlKey;this.state=a.state;this.event_=a;a.defaultPrevented&&this.preventDefault()};goog.events.BrowserEvent.prototype.isButton=function(a){return goog.events.BrowserFeature.HAS_W3C_BUTTON?this.event_.button==a:\"click\"==this.type?a==goog.events.BrowserEvent.MouseButton.LEFT:!!(this.event_.button&goog.events.BrowserEvent.IEButtonMap[a])};\ngoog.events.BrowserEvent.prototype.isMouseActionButton=function(){return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT)&&!(goog.userAgent.WEBKIT&&goog.userAgent.MAC&&this.ctrlKey)};goog.events.BrowserEvent.prototype.stopPropagation=function(){goog.events.BrowserEvent.superClass_.stopPropagation.call(this);this.event_.stopPropagation?this.event_.stopPropagation():this.event_.cancelBubble=!0};\ngoog.events.BrowserEvent.prototype.preventDefault=function(){goog.events.BrowserEvent.superClass_.preventDefault.call(this);var a=this.event_;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,goog.events.BrowserFeature.SET_KEY_CODE_TO_PREVENT_DEFAULT)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};goog.events.BrowserEvent.prototype.getBrowserEvent=function(){return this.event_};goog.events.Listenable=function(){};goog.events.Listenable.IMPLEMENTED_BY_PROP=\"closure_listenable_\"+(1E6*Math.random()|0);goog.events.Listenable.addImplementation=function(a){a.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP]=!0};goog.events.Listenable.isImplementedBy=function(a){return!(!a||!a[goog.events.Listenable.IMPLEMENTED_BY_PROP])};goog.events.ListenableKey=function(){};goog.events.ListenableKey.counter_=0;goog.events.ListenableKey.reserveKey=function(){return++goog.events.ListenableKey.counter_};goog.events.Listener=function(a,b,c,d,e,f){goog.events.Listener.ENABLE_MONITORING&&(this.creationStack=Error().stack);this.listener=a;this.proxy=b;this.src=c;this.type=d;this.capture=!!e;this.handler=f;this.key=goog.events.ListenableKey.reserveKey();this.removed=this.callOnce=!1};goog.events.Listener.ENABLE_MONITORING=!1;goog.events.Listener.prototype.markAsRemoved=function(){this.removed=!0;this.handler=this.src=this.proxy=this.listener=null};goog.events.ListenerMap=function(a){this.src=a;this.listeners={};this.typeCount_=0};goog.events.ListenerMap.prototype.getTypeCount=function(){return this.typeCount_};goog.events.ListenerMap.prototype.getListenerCount=function(){var a=0,b;for(b in this.listeners)a+=this.listeners[b].length;return a};\ngoog.events.ListenerMap.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.listeners[f];a||(a=this.listeners[f]=[],this.typeCount_++);var g=goog.events.ListenerMap.findListenerIndex_(a,b,d,e);-1<g?(b=a[g],c||(b.callOnce=!1)):(b=new goog.events.Listener(b,null,this.src,f,!!d,e),b.callOnce=c,a.push(b));return b};\ngoog.events.ListenerMap.prototype.remove=function(a,b,c,d){a=a.toString();if(!(a in this.listeners))return!1;var e=this.listeners[a];b=goog.events.ListenerMap.findListenerIndex_(e,b,c,d);return-1<b?(e[b].markAsRemoved(),goog.array.removeAt(e,b),0==e.length&&(delete this.listeners[a],this.typeCount_--),!0):!1};\ngoog.events.ListenerMap.prototype.removeByKey=function(a){var b=a.type;if(!(b in this.listeners))return!1;var c=goog.array.remove(this.listeners[b],a);c&&(a.markAsRemoved(),0==this.listeners[b].length&&(delete this.listeners[b],this.typeCount_--));return c};goog.events.ListenerMap.prototype.removeAll=function(a){a=a&&a.toString();var b=0,c;for(c in this.listeners)if(!a||c==a){for(var d=this.listeners[c],e=0;e<d.length;e++)++b,d[e].markAsRemoved();delete this.listeners[c];this.typeCount_--}return b};\ngoog.events.ListenerMap.prototype.getListeners=function(a,b){var c=this.listeners[a.toString()],d=[];if(c)for(var e=0;e<c.length;++e){var f=c[e];f.capture==b&&d.push(f)}return d};goog.events.ListenerMap.prototype.getListener=function(a,b,c,d){a=this.listeners[a.toString()];var e=-1;a&&(e=goog.events.ListenerMap.findListenerIndex_(a,b,c,d));return-1<e?a[e]:null};\ngoog.events.ListenerMap.prototype.hasListener=function(a,b){var c=goog.isDef(a),d=c?a.toString():\"\",e=goog.isDef(b);return goog.object.some(this.listeners,function(a,g){for(var h=0;h<a.length;++h)if(!(c&&a[h].type!=d||e&&a[h].capture!=b))return!0;return!1})};goog.events.ListenerMap.findListenerIndex_=function(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e];if(!f.removed&&f.listener==b&&f.capture==!!c&&f.handler==d)return e}return-1};goog.events.LISTENER_MAP_PROP_=\"closure_lm_\"+(1E6*Math.random()|0);goog.events.onString_=\"on\";goog.events.onStringMap_={};goog.events.CaptureSimulationMode={OFF_AND_FAIL:0,OFF_AND_SILENT:1,ON:2};goog.events.CAPTURE_SIMULATION_MODE=2;goog.events.listenerCountEstimate_=0;\ngoog.events.listen=function(a,b,c,d,e){if(goog.isArray(b)){for(var f=0;f<b.length;f++)goog.events.listen(a,b[f],c,d,e);return null}c=goog.events.wrapListener(c);return goog.events.Listenable.isImplementedBy(a)?a.listen(b,c,d,e):goog.events.listen_(a,b,c,!1,d,e)};\ngoog.events.listen_=function(a,b,c,d,e,f){if(!b)throw Error(\"Invalid event type\");var g=!!e;if(g&&!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT){if(goog.events.CAPTURE_SIMULATION_MODE==goog.events.CaptureSimulationMode.OFF_AND_FAIL)return goog.asserts.fail(\"Can not register capture listener in IE8-.\"),null;if(goog.events.CAPTURE_SIMULATION_MODE==goog.events.CaptureSimulationMode.OFF_AND_SILENT)return null}var h=goog.events.getListenerMap_(a);h||(a[goog.events.LISTENER_MAP_PROP_]=h=new goog.events.ListenerMap(a));\nc=h.add(b,c,d,e,f);if(c.proxy)return c;d=goog.events.getProxy();c.proxy=d;d.src=a;d.listener=c;if(a.addEventListener)a.addEventListener(b.toString(),d,g);else if(a.attachEvent)a.attachEvent(goog.events.getOnString_(b.toString()),d);else throw Error(\"addEventListener and attachEvent are unavailable.\");goog.events.listenerCountEstimate_++;return c};\ngoog.events.getProxy=function(){var a=goog.events.handleBrowserEvent_,b=goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT?function(c){return a.call(b.src,b.listener,c)}:function(c){c=a.call(b.src,b.listener,c);if(!c)return c};return b};\ngoog.events.listenOnce=function(a,b,c,d,e){if(goog.isArray(b)){for(var f=0;f<b.length;f++)goog.events.listenOnce(a,b[f],c,d,e);return null}c=goog.events.wrapListener(c);return goog.events.Listenable.isImplementedBy(a)?a.listenOnce(b,c,d,e):goog.events.listen_(a,b,c,!0,d,e)};goog.events.listenWithWrapper=function(a,b,c,d,e){b.listen(a,c,d,e)};\ngoog.events.unlisten=function(a,b,c,d,e){if(goog.isArray(b)){for(var f=0;f<b.length;f++)goog.events.unlisten(a,b[f],c,d,e);return null}c=goog.events.wrapListener(c);if(goog.events.Listenable.isImplementedBy(a))return a.unlisten(b,c,d,e);if(!a)return!1;d=!!d;if(a=goog.events.getListenerMap_(a))if(b=a.getListener(b,c,d,e))return goog.events.unlistenByKey(b);return!1};\ngoog.events.unlistenByKey=function(a){if(goog.isNumber(a)||!a||a.removed)return!1;var b=a.src;if(goog.events.Listenable.isImplementedBy(b))return b.unlistenByKey(a);var c=a.type,d=a.proxy;b.removeEventListener?b.removeEventListener(c,d,a.capture):b.detachEvent&&b.detachEvent(goog.events.getOnString_(c),d);goog.events.listenerCountEstimate_--;(c=goog.events.getListenerMap_(b))?(c.removeByKey(a),0==c.getTypeCount()&&(c.src=null,b[goog.events.LISTENER_MAP_PROP_]=null)):a.markAsRemoved();return!0};\ngoog.events.unlistenWithWrapper=function(a,b,c,d,e){b.unlisten(a,c,d,e)};goog.events.removeAll=function(a,b){if(!a)return 0;if(goog.events.Listenable.isImplementedBy(a))return a.removeAllListeners(b);var c=goog.events.getListenerMap_(a);if(!c)return 0;var d=0,e=b&&b.toString(),f;for(f in c.listeners)if(!e||f==e)for(var g=c.listeners[f].concat(),h=0;h<g.length;++h)goog.events.unlistenByKey(g[h])&&++d;return d};\ngoog.events.getListeners=function(a,b,c){return goog.events.Listenable.isImplementedBy(a)?a.getListeners(b,c):a?(a=goog.events.getListenerMap_(a))?a.getListeners(b,c):[]:[]};goog.events.getListener=function(a,b,c,d,e){c=goog.events.wrapListener(c);d=!!d;return goog.events.Listenable.isImplementedBy(a)?a.getListener(b,c,d,e):a?(a=goog.events.getListenerMap_(a))?a.getListener(b,c,d,e):null:null};\ngoog.events.hasListener=function(a,b,c){if(goog.events.Listenable.isImplementedBy(a))return a.hasListener(b,c);a=goog.events.getListenerMap_(a);return!!a&&a.hasListener(b,c)};goog.events.expose=function(a){var b=[],c;for(c in a)a[c]&&a[c].id?b.push(c+\" = \"+a[c]+\" (\"+a[c].id+\")\"):b.push(c+\" = \"+a[c]);return b.join(\"\\n\")};goog.events.getOnString_=function(a){return a in goog.events.onStringMap_?goog.events.onStringMap_[a]:goog.events.onStringMap_[a]=goog.events.onString_+a};\ngoog.events.fireListeners=function(a,b,c,d){return goog.events.Listenable.isImplementedBy(a)?a.fireListeners(b,c,d):goog.events.fireListeners_(a,b,c,d)};goog.events.fireListeners_=function(a,b,c,d){var e=!0;if(a=goog.events.getListenerMap_(a))if(b=a.listeners[b.toString()])for(b=b.concat(),a=0;a<b.length;a++){var f=b[a];f&&f.capture==c&&!f.removed&&(f=goog.events.fireListener(f,d),e=e&&!1!==f)}return e};\ngoog.events.fireListener=function(a,b){var c=a.listener,d=a.handler||a.src;a.callOnce&&goog.events.unlistenByKey(a);return c.call(d,b)};goog.events.getTotalListenerCount=function(){return goog.events.listenerCountEstimate_};goog.events.dispatchEvent=function(a,b){goog.asserts.assert(goog.events.Listenable.isImplementedBy(a),\"Can not use goog.events.dispatchEvent with non-goog.events.Listenable instance.\");return a.dispatchEvent(b)};\ngoog.events.protectBrowserEventEntryPoint=function(a){goog.events.handleBrowserEvent_=a.protectEntryPoint(goog.events.handleBrowserEvent_)};\ngoog.events.handleBrowserEvent_=function(a,b){if(a.removed)return!0;if(!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT){var c=b||goog.getObjectByName(\"window.event\"),d=new goog.events.BrowserEvent(c,this),e=!0;if(goog.events.CAPTURE_SIMULATION_MODE==goog.events.CaptureSimulationMode.ON){if(!goog.events.isMarkedIeEvent_(c)){goog.events.markIeEvent_(c);for(var c=[],f=d.currentTarget;f;f=f.parentNode)c.push(f);for(var f=a.type,g=c.length-1;!d.propagationStopped_&&0<=g;g--){d.currentTarget=c[g];var h=\ngoog.events.fireListeners_(c[g],f,!0,d),e=e&&h}for(g=0;!d.propagationStopped_&&g<c.length;g++)d.currentTarget=c[g],h=goog.events.fireListeners_(c[g],f,!1,d),e=e&&h}}else e=goog.events.fireListener(a,d);return e}return goog.events.fireListener(a,new goog.events.BrowserEvent(b,this))};goog.events.markIeEvent_=function(a){var b=!1;if(0==a.keyCode)try{a.keyCode=-1;return}catch(c){b=!0}if(b||void 0==a.returnValue)a.returnValue=!0};goog.events.isMarkedIeEvent_=function(a){return 0>a.keyCode||void 0!=a.returnValue};\ngoog.events.uniqueIdCounter_=0;goog.events.getUniqueId=function(a){return a+\"_\"+goog.events.uniqueIdCounter_++};goog.events.getListenerMap_=function(a){a=a[goog.events.LISTENER_MAP_PROP_];return a instanceof goog.events.ListenerMap?a:null};goog.events.LISTENER_WRAPPER_PROP_=\"__closure_events_fn_\"+(1E9*Math.random()>>>0);\ngoog.events.wrapListener=function(a){goog.asserts.assert(a,\"Listener can not be null.\");if(goog.isFunction(a))return a;goog.asserts.assert(a.handleEvent,\"An object listener must have handleEvent method.\");a[goog.events.LISTENER_WRAPPER_PROP_]||(a[goog.events.LISTENER_WRAPPER_PROP_]=function(b){return a.handleEvent(b)});return a[goog.events.LISTENER_WRAPPER_PROP_]};goog.debug.entryPointRegistry.register(function(a){goog.events.handleBrowserEvent_=a(goog.events.handleBrowserEvent_)});goog.events.EventTarget=function(){goog.Disposable.call(this);this.eventTargetListeners_=new goog.events.ListenerMap(this);this.actualEventTarget_=this;this.parentEventTarget_=null};goog.inherits(goog.events.EventTarget,goog.Disposable);goog.events.Listenable.addImplementation(goog.events.EventTarget);goog.events.EventTarget.MAX_ANCESTORS_=1E3;goog.events.EventTarget.prototype.getParentEventTarget=function(){return this.parentEventTarget_};\ngoog.events.EventTarget.prototype.setParentEventTarget=function(a){this.parentEventTarget_=a};goog.events.EventTarget.prototype.addEventListener=function(a,b,c,d){goog.events.listen(this,a,b,c,d)};goog.events.EventTarget.prototype.removeEventListener=function(a,b,c,d){goog.events.unlisten(this,a,b,c,d)};\ngoog.events.EventTarget.prototype.dispatchEvent=function(a){this.assertInitialized_();var b,c=this.getParentEventTarget();if(c){b=[];for(var d=1;c;c=c.getParentEventTarget())b.push(c),goog.asserts.assert(++d<goog.events.EventTarget.MAX_ANCESTORS_,\"infinite loop\")}return goog.events.EventTarget.dispatchEventInternal_(this.actualEventTarget_,a,b)};\ngoog.events.EventTarget.prototype.disposeInternal=function(){goog.events.EventTarget.superClass_.disposeInternal.call(this);this.removeAllListeners();this.parentEventTarget_=null};goog.events.EventTarget.prototype.listen=function(a,b,c,d){this.assertInitialized_();return this.eventTargetListeners_.add(String(a),b,!1,c,d)};goog.events.EventTarget.prototype.listenOnce=function(a,b,c,d){return this.eventTargetListeners_.add(String(a),b,!0,c,d)};\ngoog.events.EventTarget.prototype.unlisten=function(a,b,c,d){return this.eventTargetListeners_.remove(String(a),b,c,d)};goog.events.EventTarget.prototype.unlistenByKey=function(a){return this.eventTargetListeners_.removeByKey(a)};goog.events.EventTarget.prototype.removeAllListeners=function(a){return this.eventTargetListeners_?this.eventTargetListeners_.removeAll(a):0};\ngoog.events.EventTarget.prototype.fireListeners=function(a,b,c){a=this.eventTargetListeners_.listeners[String(a)];if(!a)return!0;a=a.concat();for(var d=!0,e=0;e<a.length;++e){var f=a[e];if(f&&!f.removed&&f.capture==b){var g=f.listener,h=f.handler||f.src;f.callOnce&&this.unlistenByKey(f);d=!1!==g.call(h,c)&&d}}return d&&0!=c.returnValue_};goog.events.EventTarget.prototype.getListeners=function(a,b){return this.eventTargetListeners_.getListeners(String(a),b)};\ngoog.events.EventTarget.prototype.getListener=function(a,b,c,d){return this.eventTargetListeners_.getListener(String(a),b,c,d)};goog.events.EventTarget.prototype.hasListener=function(a,b){var c=goog.isDef(a)?String(a):void 0;return this.eventTargetListeners_.hasListener(c,b)};goog.events.EventTarget.prototype.setTargetForTesting=function(a){this.actualEventTarget_=a};goog.events.EventTarget.prototype.assertInitialized_=function(){goog.asserts.assert(this.eventTargetListeners_,\"Event target is not initialized. Did you call the superclass (goog.events.EventTarget) constructor?\")};\ngoog.events.EventTarget.dispatchEventInternal_=function(a,b,c){var d=b.type||b;if(goog.isString(b))b=new goog.events.Event(b,a);else if(b instanceof goog.events.Event)b.target=b.target||a;else{var e=b;b=new goog.events.Event(d,a);goog.object.extend(b,e)}var e=!0,f;if(c)for(var g=c.length-1;!b.propagationStopped_&&0<=g;g--)f=b.currentTarget=c[g],e=f.fireListeners(d,!0,b)&&e;b.propagationStopped_||(f=b.currentTarget=a,e=f.fireListeners(d,!0,b)&&e,b.propagationStopped_||(e=f.fireListeners(d,!1,b)&&e));\nif(c)for(g=0;!b.propagationStopped_&&g<c.length;g++)f=b.currentTarget=c[g],e=f.fireListeners(d,!1,b)&&e;return e};goog.Timer=function(a,b){goog.events.EventTarget.call(this);this.interval_=a||1;this.timerObject_=b||goog.Timer.defaultTimerObject;this.boundTick_=goog.bind(this.tick_,this);this.last_=goog.now()};goog.inherits(goog.Timer,goog.events.EventTarget);goog.Timer.MAX_TIMEOUT_=2147483647;goog.Timer.INVALID_TIMEOUT_ID_=-1;goog.Timer.prototype.enabled=!1;goog.Timer.defaultTimerObject=goog.global;goog.Timer.intervalScale=.8;goog.Timer.prototype.timer_=null;goog.Timer.prototype.getInterval=function(){return this.interval_};\ngoog.Timer.prototype.setInterval=function(a){this.interval_=a;this.timer_&&this.enabled?(this.stop(),this.start()):this.timer_&&this.stop()};\ngoog.Timer.prototype.tick_=function(){if(this.enabled){var a=goog.now()-this.last_;0<a&&a<this.interval_*goog.Timer.intervalScale?this.timer_=this.timerObject_.setTimeout(this.boundTick_,this.interval_-a):(this.timer_&&(this.timerObject_.clearTimeout(this.timer_),this.timer_=null),this.dispatchTick(),this.enabled&&(this.timer_=this.timerObject_.setTimeout(this.boundTick_,this.interval_),this.last_=goog.now()))}};goog.Timer.prototype.dispatchTick=function(){this.dispatchEvent(goog.Timer.TICK)};\ngoog.Timer.prototype.start=function(){this.enabled=!0;this.timer_||(this.timer_=this.timerObject_.setTimeout(this.boundTick_,this.interval_),this.last_=goog.now())};goog.Timer.prototype.stop=function(){this.enabled=!1;this.timer_&&(this.timerObject_.clearTimeout(this.timer_),this.timer_=null)};goog.Timer.prototype.disposeInternal=function(){goog.Timer.superClass_.disposeInternal.call(this);this.stop();delete this.timerObject_};goog.Timer.TICK=\"tick\";\ngoog.Timer.callOnce=function(a,b,c){if(goog.isFunction(a))c&&(a=goog.bind(a,c));else if(a&&\"function\"==typeof a.handleEvent)a=goog.bind(a.handleEvent,a);else throw Error(\"Invalid listener argument\");return Number(b)>goog.Timer.MAX_TIMEOUT_?goog.Timer.INVALID_TIMEOUT_ID_:goog.Timer.defaultTimerObject.setTimeout(a,b||0)};goog.Timer.clear=function(a){goog.Timer.defaultTimerObject.clearTimeout(a)};\ngoog.Timer.promise=function(a,b){var c=null;return(new goog.Promise(function(d,e){c=goog.Timer.callOnce(function(){d(b)},a);c==goog.Timer.INVALID_TIMEOUT_ID_&&e(Error(\"Failed to schedule timer.\"))})).thenCatch(function(a){goog.Timer.clear(c);throw a;})};goog.color={};\ngoog.color.names={aliceblue:\"#f0f8ff\",antiquewhite:\"#faebd7\",aqua:\"#00ffff\",aquamarine:\"#7fffd4\",azure:\"#f0ffff\",beige:\"#f5f5dc\",bisque:\"#ffe4c4\",black:\"#000000\",blanchedalmond:\"#ffebcd\",blue:\"#0000ff\",blueviolet:\"#8a2be2\",brown:\"#a52a2a\",burlywood:\"#deb887\",cadetblue:\"#5f9ea0\",chartreuse:\"#7fff00\",chocolate:\"#d2691e\",coral:\"#ff7f50\",cornflowerblue:\"#6495ed\",cornsilk:\"#fff8dc\",crimson:\"#dc143c\",cyan:\"#00ffff\",darkblue:\"#00008b\",darkcyan:\"#008b8b\",darkgoldenrod:\"#b8860b\",darkgray:\"#a9a9a9\",darkgreen:\"#006400\",\ndarkgrey:\"#a9a9a9\",darkkhaki:\"#bdb76b\",darkmagenta:\"#8b008b\",darkolivegreen:\"#556b2f\",darkorange:\"#ff8c00\",darkorchid:\"#9932cc\",darkred:\"#8b0000\",darksalmon:\"#e9967a\",darkseagreen:\"#8fbc8f\",darkslateblue:\"#483d8b\",darkslategray:\"#2f4f4f\",darkslategrey:\"#2f4f4f\",darkturquoise:\"#00ced1\",darkviolet:\"#9400d3\",deeppink:\"#ff1493\",deepskyblue:\"#00bfff\",dimgray:\"#696969\",dimgrey:\"#696969\",dodgerblue:\"#1e90ff\",firebrick:\"#b22222\",floralwhite:\"#fffaf0\",forestgreen:\"#228b22\",fuchsia:\"#ff00ff\",gainsboro:\"#dcdcdc\",\nghostwhite:\"#f8f8ff\",gold:\"#ffd700\",goldenrod:\"#daa520\",gray:\"#808080\",green:\"#008000\",greenyellow:\"#adff2f\",grey:\"#808080\",honeydew:\"#f0fff0\",hotpink:\"#ff69b4\",indianred:\"#cd5c5c\",indigo:\"#4b0082\",ivory:\"#fffff0\",khaki:\"#f0e68c\",lavender:\"#e6e6fa\",lavenderblush:\"#fff0f5\",lawngreen:\"#7cfc00\",lemonchiffon:\"#fffacd\",lightblue:\"#add8e6\",lightcoral:\"#f08080\",lightcyan:\"#e0ffff\",lightgoldenrodyellow:\"#fafad2\",lightgray:\"#d3d3d3\",lightgreen:\"#90ee90\",lightgrey:\"#d3d3d3\",lightpink:\"#ffb6c1\",lightsalmon:\"#ffa07a\",\nlightseagreen:\"#20b2aa\",lightskyblue:\"#87cefa\",lightslategray:\"#778899\",lightslategrey:\"#778899\",lightsteelblue:\"#b0c4de\",lightyellow:\"#ffffe0\",lime:\"#00ff00\",limegreen:\"#32cd32\",linen:\"#faf0e6\",magenta:\"#ff00ff\",maroon:\"#800000\",mediumaquamarine:\"#66cdaa\",mediumblue:\"#0000cd\",mediumorchid:\"#ba55d3\",mediumpurple:\"#9370db\",mediumseagreen:\"#3cb371\",mediumslateblue:\"#7b68ee\",mediumspringgreen:\"#00fa9a\",mediumturquoise:\"#48d1cc\",mediumvioletred:\"#c71585\",midnightblue:\"#191970\",mintcream:\"#f5fffa\",mistyrose:\"#ffe4e1\",\nmoccasin:\"#ffe4b5\",navajowhite:\"#ffdead\",navy:\"#000080\",oldlace:\"#fdf5e6\",olive:\"#808000\",olivedrab:\"#6b8e23\",orange:\"#ffa500\",orangered:\"#ff4500\",orchid:\"#da70d6\",palegoldenrod:\"#eee8aa\",palegreen:\"#98fb98\",paleturquoise:\"#afeeee\",palevioletred:\"#db7093\",papayawhip:\"#ffefd5\",peachpuff:\"#ffdab9\",peru:\"#cd853f\",pink:\"#ffc0cb\",plum:\"#dda0dd\",powderblue:\"#b0e0e6\",purple:\"#800080\",red:\"#ff0000\",rosybrown:\"#bc8f8f\",royalblue:\"#4169e1\",saddlebrown:\"#8b4513\",salmon:\"#fa8072\",sandybrown:\"#f4a460\",seagreen:\"#2e8b57\",\nseashell:\"#fff5ee\",sienna:\"#a0522d\",silver:\"#c0c0c0\",skyblue:\"#87ceeb\",slateblue:\"#6a5acd\",slategray:\"#708090\",slategrey:\"#708090\",snow:\"#fffafa\",springgreen:\"#00ff7f\",steelblue:\"#4682b4\",tan:\"#d2b48c\",teal:\"#008080\",thistle:\"#d8bfd8\",tomato:\"#ff6347\",turquoise:\"#40e0d0\",violet:\"#ee82ee\",wheat:\"#f5deb3\",white:\"#ffffff\",whitesmoke:\"#f5f5f5\",yellow:\"#ffff00\",yellowgreen:\"#9acd32\"};goog.math={};goog.math.randomInt=function(a){return Math.floor(Math.random()*a)};goog.math.uniformRandom=function(a,b){return a+Math.random()*(b-a)};goog.math.clamp=function(a,b,c){return Math.min(Math.max(a,b),c)};goog.math.modulo=function(a,b){var c=a%b;return 0>c*b?c+b:c};goog.math.lerp=function(a,b,c){return a+c*(b-a)};goog.math.nearlyEquals=function(a,b,c){return Math.abs(a-b)<=(c||1E-6)};goog.math.standardAngle=function(a){return goog.math.modulo(a,360)};\ngoog.math.standardAngleInRadians=function(a){return goog.math.modulo(a,2*Math.PI)};goog.math.toRadians=function(a){return a*Math.PI/180};goog.math.toDegrees=function(a){return 180*a/Math.PI};goog.math.angleDx=function(a,b){return b*Math.cos(goog.math.toRadians(a))};goog.math.angleDy=function(a,b){return b*Math.sin(goog.math.toRadians(a))};goog.math.angle=function(a,b,c,d){return goog.math.standardAngle(goog.math.toDegrees(Math.atan2(d-b,c-a)))};\ngoog.math.angleDifference=function(a,b){var c=goog.math.standardAngle(b)-goog.math.standardAngle(a);180<c?c-=360:-180>=c&&(c=360+c);return c};goog.math.sign=Math.sign||function(a){return 0<a?1:0>a?-1:a};\ngoog.math.longestCommonSubsequence=function(a,b,c,d){c=c||function(a,b){return a==b};d=d||function(b,c){return a[b]};for(var e=a.length,f=b.length,g=[],h=0;h<e+1;h++)g[h]=[],g[h][0]=0;for(var k=0;k<f+1;k++)g[0][k]=0;for(h=1;h<=e;h++)for(k=1;k<=f;k++)c(a[h-1],b[k-1])?g[h][k]=g[h-1][k-1]+1:g[h][k]=Math.max(g[h-1][k],g[h][k-1]);for(var n=[],h=e,k=f;0<h&&0<k;)c(a[h-1],b[k-1])?(n.unshift(d(h-1,k-1)),h--,k--):g[h-1][k]>g[h][k-1]?h--:k--;return n};\ngoog.math.sum=function(a){return goog.array.reduce(arguments,function(a,c){return a+c},0)};goog.math.average=function(a){return goog.math.sum.apply(null,arguments)/arguments.length};goog.math.sampleVariance=function(a){var b=arguments.length;if(2>b)return 0;var c=goog.math.average.apply(null,arguments);return goog.math.sum.apply(null,goog.array.map(arguments,function(a){return Math.pow(a-c,2)}))/(b-1)};goog.math.standardDeviation=function(a){return Math.sqrt(goog.math.sampleVariance.apply(null,arguments))};\ngoog.math.isInt=function(a){return isFinite(a)&&0==a%1};goog.math.isFiniteNumber=function(a){return isFinite(a)&&!isNaN(a)};goog.math.isNegativeZero=function(a){return 0==a&&0>1/a};goog.math.log10Floor=function(a){if(0<a){var b=Math.round(Math.log(a)*Math.LOG10E);return b-(parseFloat(\"1e\"+b)>a?1:0)}return 0==a?-Infinity:NaN};goog.math.safeFloor=function(a,b){goog.asserts.assert(!goog.isDef(b)||0<b);return Math.floor(a+(b||2E-15))};\ngoog.math.safeCeil=function(a,b){goog.asserts.assert(!goog.isDef(b)||0<b);return Math.ceil(a-(b||2E-15))};goog.color.parse=function(a){var b={};a=String(a);var c=goog.color.prependHashIfNecessaryHelper(a);if(goog.color.isValidHexColor_(c))return b.hex=goog.color.normalizeHex(c),b.type=\"hex\",b;c=goog.color.isValidRgbColor_(a);if(c.length)return b.hex=goog.color.rgbArrayToHex(c),b.type=\"rgb\",b;if(goog.color.names&&(c=goog.color.names[a.toLowerCase()]))return b.hex=c,b.type=\"named\",b;throw Error(a+\" is not a valid color string\");};\ngoog.color.isValidColor=function(a){var b=goog.color.prependHashIfNecessaryHelper(a);return!!(goog.color.isValidHexColor_(b)||goog.color.isValidRgbColor_(a).length||goog.color.names&&goog.color.names[a.toLowerCase()])};goog.color.parseRgb=function(a){var b=goog.color.isValidRgbColor_(a);if(!b.length)throw Error(a+\" is not a valid RGB color\");return b};goog.color.hexToRgbStyle=function(a){return goog.color.rgbStyle_(goog.color.hexToRgb(a))};goog.color.hexTripletRe_=/#(.)(.)(.)/;\ngoog.color.normalizeHex=function(a){if(!goog.color.isValidHexColor_(a))throw Error(\"'\"+a+\"' is not a valid hex color\");4==a.length&&(a=a.replace(goog.color.hexTripletRe_,\"#$1$1$2$2$3$3\"));return a.toLowerCase()};goog.color.hexToRgb=function(a){a=goog.color.normalizeHex(a);var b=parseInt(a.substr(1,2),16),c=parseInt(a.substr(3,2),16);a=parseInt(a.substr(5,2),16);return[b,c,a]};\ngoog.color.rgbToHex=function(a,b,c){a=Number(a);b=Number(b);c=Number(c);if(a!=(a&255)||b!=(b&255)||c!=(c&255))throw Error('\"('+a+\",\"+b+\",\"+c+'\") is not a valid RGB color');a=goog.color.prependZeroIfNecessaryHelper(a.toString(16));b=goog.color.prependZeroIfNecessaryHelper(b.toString(16));c=goog.color.prependZeroIfNecessaryHelper(c.toString(16));return\"#\"+a+b+c};goog.color.rgbArrayToHex=function(a){return goog.color.rgbToHex(a[0],a[1],a[2])};\ngoog.color.rgbToHsl=function(a,b,c){a/=255;b/=255;c/=255;var d=Math.max(a,b,c),e=Math.min(a,b,c),f=0,g=0,h=.5*(d+e);d!=e&&(d==a?f=60*(b-c)/(d-e):d==b?f=60*(c-a)/(d-e)+120:d==c&&(f=60*(a-b)/(d-e)+240),g=0<h&&.5>=h?(d-e)/(2*h):(d-e)/(2-2*h));return[Math.round(f+360)%360,g,h]};goog.color.rgbArrayToHsl=function(a){return goog.color.rgbToHsl(a[0],a[1],a[2])};goog.color.hueToRgb_=function(a,b,c){0>c?c+=1:1<c&&--c;return 1>6*c?a+6*(b-a)*c:1>2*c?b:2>3*c?a+(b-a)*(2/3-c)*6:a};\ngoog.color.hslToRgb=function(a,b,c){a/=360;if(0==b)c=b=a=255*c;else{var d,e;e=.5>c?c*(1+b):c+b-b*c;d=2*c-e;c=255*goog.color.hueToRgb_(d,e,a+1/3);b=255*goog.color.hueToRgb_(d,e,a);a=255*goog.color.hueToRgb_(d,e,a-1/3)}return[Math.round(c),Math.round(b),Math.round(a)]};goog.color.hslArrayToRgb=function(a){return goog.color.hslToRgb(a[0],a[1],a[2])};goog.color.validHexColorRe_=/^#(?:[0-9a-f]{3}){1,2}$/i;goog.color.isValidHexColor_=function(a){return goog.color.validHexColorRe_.test(a)};\ngoog.color.normalizedHexColorRe_=/^#[0-9a-f]{6}$/;goog.color.isNormalizedHexColor_=function(a){return goog.color.normalizedHexColorRe_.test(a)};goog.color.rgbColorRe_=/^(?:rgb)?\\((0|[1-9]\\d{0,2}),\\s?(0|[1-9]\\d{0,2}),\\s?(0|[1-9]\\d{0,2})\\)$/i;goog.color.isValidRgbColor_=function(a){var b=a.match(goog.color.rgbColorRe_);if(b){a=Number(b[1]);var c=Number(b[2]),b=Number(b[3]);if(0<=a&&255>=a&&0<=c&&255>=c&&0<=b&&255>=b)return[a,c,b]}return[]};\ngoog.color.prependZeroIfNecessaryHelper=function(a){return 1==a.length?\"0\"+a:a};goog.color.prependHashIfNecessaryHelper=function(a){return\"#\"==a.charAt(0)?a:\"#\"+a};goog.color.rgbStyle_=function(a){return\"rgb(\"+a.join(\",\")+\")\"};\ngoog.color.hsvToRgb=function(a,b,c){var d=0,e=0,f=0;if(0==b)f=e=d=c;else{var g=Math.floor(a/60),h=a/60-g;a=c*(1-b);var k=c*(1-b*h);b=c*(1-b*(1-h));switch(g){case 1:d=k;e=c;f=a;break;case 2:d=a;e=c;f=b;break;case 3:d=a;e=k;f=c;break;case 4:d=b;e=a;f=c;break;case 5:d=c;e=a;f=k;break;case 6:case 0:d=c,e=b,f=a}}return[Math.floor(d),Math.floor(e),Math.floor(f)]};\ngoog.color.rgbToHsv=function(a,b,c){var d=Math.max(Math.max(a,b),c),e=Math.min(Math.min(a,b),c);if(e==d)e=a=0;else{var f=d-e,e=f/d;a=60*(a==d?(b-c)/f:b==d?2+(c-a)/f:4+(a-b)/f);0>a&&(a+=360);360<a&&(a-=360)}return[a,e,d]};goog.color.rgbArrayToHsv=function(a){return goog.color.rgbToHsv(a[0],a[1],a[2])};goog.color.hsvArrayToRgb=function(a){return goog.color.hsvToRgb(a[0],a[1],a[2])};goog.color.hexToHsl=function(a){a=goog.color.hexToRgb(a);return goog.color.rgbToHsl(a[0],a[1],a[2])};\ngoog.color.hslToHex=function(a,b,c){return goog.color.rgbArrayToHex(goog.color.hslToRgb(a,b,c))};goog.color.hslArrayToHex=function(a){return goog.color.rgbArrayToHex(goog.color.hslToRgb(a[0],a[1],a[2]))};goog.color.hexToHsv=function(a){return goog.color.rgbArrayToHsv(goog.color.hexToRgb(a))};goog.color.hsvToHex=function(a,b,c){return goog.color.rgbArrayToHex(goog.color.hsvToRgb(a,b,c))};goog.color.hsvArrayToHex=function(a){return goog.color.hsvToHex(a[0],a[1],a[2])};\ngoog.color.hslDistance=function(a,b){var c,d;c=.5>=a[2]?a[1]*a[2]:a[1]*(1-a[2]);d=.5>=b[2]?b[1]*b[2]:b[1]*(1-b[2]);return(a[2]-b[2])*(a[2]-b[2])+c*c+d*d-2*c*d*Math.cos(2*(a[0]/360-b[0]/360)*Math.PI)};goog.color.blend=function(a,b,c){c=goog.math.clamp(c,0,1);return[Math.round(c*a[0]+(1-c)*b[0]),Math.round(c*a[1]+(1-c)*b[1]),Math.round(c*a[2]+(1-c)*b[2])]};goog.color.darken=function(a,b){return goog.color.blend([0,0,0],a,b)};goog.color.lighten=function(a,b){return goog.color.blend([255,255,255],a,b)};\ngoog.color.highContrast=function(a,b){for(var c=[],d=0;d<b.length;d++)c.push({color:b[d],diff:goog.color.yiqBrightnessDiff_(b[d],a)+goog.color.colorDiff_(b[d],a)});c.sort(function(a,b){return b.diff-a.diff});return c[0].color};goog.color.yiqBrightness_=function(a){return Math.round((299*a[0]+587*a[1]+114*a[2])/1E3)};goog.color.yiqBrightnessDiff_=function(a,b){return Math.abs(goog.color.yiqBrightness_(a)-goog.color.yiqBrightness_(b))};\ngoog.color.colorDiff_=function(a,b){return Math.abs(a[0]-b[0])+Math.abs(a[1]-b[1])+Math.abs(a[2]-b[2])};goog.dom.BrowserFeature={CAN_ADD_NAME_OR_TYPE_ATTRIBUTES:!goog.userAgent.IE||goog.userAgent.isDocumentModeOrHigher(9),CAN_USE_CHILDREN_ATTRIBUTE:!goog.userAgent.GECKO&&!goog.userAgent.IE||goog.userAgent.IE&&goog.userAgent.isDocumentModeOrHigher(9)||goog.userAgent.GECKO&&goog.userAgent.isVersionOrHigher(\"1.9.1\"),CAN_USE_INNER_TEXT:goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"9\"),CAN_USE_PARENT_ELEMENT_PROPERTY:goog.userAgent.IE||goog.userAgent.OPERA||goog.userAgent.WEBKIT,INNER_HTML_NEEDS_SCOPED_ELEMENT:goog.userAgent.IE,\nLEGACY_IE_RANGES:goog.userAgent.IE&&!goog.userAgent.isDocumentModeOrHigher(9)};goog.dom.tags={};goog.dom.tags.VOID_TAGS_={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0};goog.dom.tags.isVoidTag=function(a){return!0===goog.dom.tags.VOID_TAGS_[a]};goog.string.TypedString=function(){};goog.string.Const=function(){this.stringConstValueWithSecurityContract__googStringSecurityPrivate_=\"\";this.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_=goog.string.Const.TYPE_MARKER_};goog.string.Const.prototype.implementsGoogStringTypedString=!0;goog.string.Const.prototype.getTypedStringValue=function(){return this.stringConstValueWithSecurityContract__googStringSecurityPrivate_};\ngoog.string.Const.prototype.toString=function(){return\"Const{\"+this.stringConstValueWithSecurityContract__googStringSecurityPrivate_+\"}\"};goog.string.Const.unwrap=function(a){if(a instanceof goog.string.Const&&a.constructor===goog.string.Const&&a.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_===goog.string.Const.TYPE_MARKER_)return a.stringConstValueWithSecurityContract__googStringSecurityPrivate_;goog.asserts.fail(\"expected object of type Const, got '\"+a+\"'\");return\"type_error:Const\"};\ngoog.string.Const.from=function(a){return goog.string.Const.create__googStringSecurityPrivate_(a)};goog.string.Const.TYPE_MARKER_={};goog.string.Const.create__googStringSecurityPrivate_=function(a){var b=new goog.string.Const;b.stringConstValueWithSecurityContract__googStringSecurityPrivate_=a;return b};goog.html={};goog.html.SafeStyle=function(){this.privateDoNotAccessOrElseSafeStyleWrappedValue_=\"\";this.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_=goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_};goog.html.SafeStyle.prototype.implementsGoogStringTypedString=!0;goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_={};\ngoog.html.SafeStyle.fromConstant=function(a){a=goog.string.Const.unwrap(a);if(0===a.length)return goog.html.SafeStyle.EMPTY;goog.html.SafeStyle.checkStyle_(a);goog.asserts.assert(goog.string.endsWith(a,\";\"),\"Last character of style string is not ';': \"+a);goog.asserts.assert(goog.string.contains(a,\":\"),\"Style string must contain at least one ':', to specify a \\\"name: value\\\" pair: \"+a);return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(a)};\ngoog.html.SafeStyle.checkStyle_=function(a){goog.asserts.assert(!/[<>]/.test(a),\"Forbidden characters in style string: \"+a)};goog.html.SafeStyle.prototype.getTypedStringValue=function(){return this.privateDoNotAccessOrElseSafeStyleWrappedValue_};goog.DEBUG&&(goog.html.SafeStyle.prototype.toString=function(){return\"SafeStyle{\"+this.privateDoNotAccessOrElseSafeStyleWrappedValue_+\"}\"});\ngoog.html.SafeStyle.unwrap=function(a){if(a instanceof goog.html.SafeStyle&&a.constructor===goog.html.SafeStyle&&a.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_===goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_)return a.privateDoNotAccessOrElseSafeStyleWrappedValue_;goog.asserts.fail(\"expected object of type SafeStyle, got '\"+a+\"' of type \"+goog.typeOf(a));return\"type_error:SafeStyle\"};goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse=function(a){return(new goog.html.SafeStyle).initSecurityPrivateDoNotAccessOrElse_(a)};\ngoog.html.SafeStyle.prototype.initSecurityPrivateDoNotAccessOrElse_=function(a){this.privateDoNotAccessOrElseSafeStyleWrappedValue_=a;return this};goog.html.SafeStyle.EMPTY=goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(\"\");goog.html.SafeStyle.INNOCUOUS_STRING=\"zClosurez\";\ngoog.html.SafeStyle.create=function(a){var b=\"\",c;for(c in a){if(!/^[-_a-zA-Z0-9]+$/.test(c))throw Error(\"Name allows only [-_a-zA-Z0-9], got: \"+c);var d=a[c];null!=d&&(d instanceof goog.string.Const?(d=goog.string.Const.unwrap(d),goog.asserts.assert(!/[{;}]/.test(d),\"Value does not allow [{;}].\")):goog.html.SafeStyle.VALUE_RE_.test(d)?goog.html.SafeStyle.hasBalancedQuotes_(d)||(goog.asserts.fail(\"String value requires balanced quotes, got: \"+d),d=goog.html.SafeStyle.INNOCUOUS_STRING):(goog.asserts.fail(\"String value allows only [-,.\\\"'%_!# a-zA-Z0-9], rgb() and rgba(), got: \"+\nd),d=goog.html.SafeStyle.INNOCUOUS_STRING),b+=c+\":\"+d+\";\")}if(!b)return goog.html.SafeStyle.EMPTY;goog.html.SafeStyle.checkStyle_(b);return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(b)};goog.html.SafeStyle.hasBalancedQuotes_=function(a){for(var b=!0,c=!0,d=0;d<a.length;d++){var e=a.charAt(d);\"'\"==e&&c?b=!b:'\"'==e&&b&&(c=!c)}return b&&c};goog.html.SafeStyle.VALUE_RE_=/^([-,.\"'%_!# a-zA-Z0-9]+|(?:rgb|hsl)a?\\([0-9.%, ]+\\))$/;\ngoog.html.SafeStyle.concat=function(a){var b=\"\",c=function(a){goog.isArray(a)?goog.array.forEach(a,c):b+=goog.html.SafeStyle.unwrap(a)};goog.array.forEach(arguments,c);return b?goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(b):goog.html.SafeStyle.EMPTY};goog.html.SafeStyleSheet=function(){this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_=\"\";this.SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_=goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_};goog.html.SafeStyleSheet.prototype.implementsGoogStringTypedString=!0;goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_={};\ngoog.html.SafeStyleSheet.concat=function(a){var b=\"\",c=function(a){goog.isArray(a)?goog.array.forEach(a,c):b+=goog.html.SafeStyleSheet.unwrap(a)};goog.array.forEach(arguments,c);return goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(b)};\ngoog.html.SafeStyleSheet.fromConstant=function(a){a=goog.string.Const.unwrap(a);if(0===a.length)return goog.html.SafeStyleSheet.EMPTY;goog.asserts.assert(!goog.string.contains(a,\"<\"),\"Forbidden '<' character in style sheet string: \"+a);return goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(a)};goog.html.SafeStyleSheet.prototype.getTypedStringValue=function(){return this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_};\ngoog.DEBUG&&(goog.html.SafeStyleSheet.prototype.toString=function(){return\"SafeStyleSheet{\"+this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_+\"}\"});\ngoog.html.SafeStyleSheet.unwrap=function(a){if(a instanceof goog.html.SafeStyleSheet&&a.constructor===goog.html.SafeStyleSheet&&a.SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_===goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_)return a.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_;goog.asserts.fail(\"expected object of type SafeStyleSheet, got '\"+a+\"' of type \"+goog.typeOf(a));return\"type_error:SafeStyleSheet\"};\ngoog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse=function(a){return(new goog.html.SafeStyleSheet).initSecurityPrivateDoNotAccessOrElse_(a)};goog.html.SafeStyleSheet.prototype.initSecurityPrivateDoNotAccessOrElse_=function(a){this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_=a;return this};goog.html.SafeStyleSheet.EMPTY=goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(\"\");goog.fs={};goog.fs.url={};goog.fs.url.createObjectUrl=function(a){return goog.fs.url.getUrlObject_().createObjectURL(a)};goog.fs.url.revokeObjectUrl=function(a){goog.fs.url.getUrlObject_().revokeObjectURL(a)};goog.fs.url.getUrlObject_=function(){var a=goog.fs.url.findUrlObject_();if(null!=a)return a;throw Error(\"This browser doesn't seem to support blob URLs\");};\ngoog.fs.url.findUrlObject_=function(){return goog.isDef(goog.global.URL)&&goog.isDef(goog.global.URL.createObjectURL)?goog.global.URL:goog.isDef(goog.global.webkitURL)&&goog.isDef(goog.global.webkitURL.createObjectURL)?goog.global.webkitURL:goog.isDef(goog.global.createObjectURL)?goog.global:null};goog.fs.url.browserSupportsObjectUrls=function(){return null!=goog.fs.url.findUrlObject_()};goog.i18n={};goog.i18n.bidi={};goog.i18n.bidi.FORCE_RTL=!1;\ngoog.i18n.bidi.IS_RTL=goog.i18n.bidi.FORCE_RTL||(\"ar\"==goog.LOCALE.substring(0,2).toLowerCase()||\"fa\"==goog.LOCALE.substring(0,2).toLowerCase()||\"he\"==goog.LOCALE.substring(0,2).toLowerCase()||\"iw\"==goog.LOCALE.substring(0,2).toLowerCase()||\"ps\"==goog.LOCALE.substring(0,2).toLowerCase()||\"sd\"==goog.LOCALE.substring(0,2).toLowerCase()||\"ug\"==goog.LOCALE.substring(0,2).toLowerCase()||\"ur\"==goog.LOCALE.substring(0,2).toLowerCase()||\"yi\"==goog.LOCALE.substring(0,2).toLowerCase())&&(2==goog.LOCALE.length||\n\"-\"==goog.LOCALE.substring(2,3)||\"_\"==goog.LOCALE.substring(2,3))||3<=goog.LOCALE.length&&\"ckb\"==goog.LOCALE.substring(0,3).toLowerCase()&&(3==goog.LOCALE.length||\"-\"==goog.LOCALE.substring(3,4)||\"_\"==goog.LOCALE.substring(3,4));goog.i18n.bidi.Format={LRE:\"\\u202a\",RLE:\"\\u202b\",PDF:\"\\u202c\",LRM:\"\\u200e\",RLM:\"\\u200f\"};goog.i18n.bidi.Dir={LTR:1,RTL:-1,NEUTRAL:0};goog.i18n.bidi.RIGHT=\"right\";goog.i18n.bidi.LEFT=\"left\";goog.i18n.bidi.I18N_RIGHT=goog.i18n.bidi.IS_RTL?goog.i18n.bidi.LEFT:goog.i18n.bidi.RIGHT;\ngoog.i18n.bidi.I18N_LEFT=goog.i18n.bidi.IS_RTL?goog.i18n.bidi.RIGHT:goog.i18n.bidi.LEFT;goog.i18n.bidi.toDir=function(a,b){return\"number\"==typeof a?0<a?goog.i18n.bidi.Dir.LTR:0>a?goog.i18n.bidi.Dir.RTL:b?null:goog.i18n.bidi.Dir.NEUTRAL:null==a?null:a?goog.i18n.bidi.Dir.RTL:goog.i18n.bidi.Dir.LTR};goog.i18n.bidi.ltrChars_=\"A-Za-z\\u00c0-\\u00d6\\u00d8-\\u00f6\\u00f8-\\u02b8\\u0300-\\u0590\\u0800-\\u1fff\\u200e\\u2c00-\\ufb1c\\ufe00-\\ufe6f\\ufefd-\\uffff\";goog.i18n.bidi.rtlChars_=\"\\u0591-\\u06ef\\u06fa-\\u07ff\\u200f\\ufb1d-\\ufdff\\ufe70-\\ufefc\";\ngoog.i18n.bidi.htmlSkipReg_=/<[^>]*>|&[^;]+;/g;goog.i18n.bidi.stripHtmlIfNeeded_=function(a,b){return b?a.replace(goog.i18n.bidi.htmlSkipReg_,\"\"):a};goog.i18n.bidi.rtlCharReg_=new RegExp(\"[\"+goog.i18n.bidi.rtlChars_+\"]\");goog.i18n.bidi.ltrCharReg_=new RegExp(\"[\"+goog.i18n.bidi.ltrChars_+\"]\");goog.i18n.bidi.hasAnyRtl=function(a,b){return goog.i18n.bidi.rtlCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(a,b))};goog.i18n.bidi.hasRtlChar=goog.i18n.bidi.hasAnyRtl;\ngoog.i18n.bidi.hasAnyLtr=function(a,b){return goog.i18n.bidi.ltrCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(a,b))};goog.i18n.bidi.ltrRe_=new RegExp(\"^[\"+goog.i18n.bidi.ltrChars_+\"]\");goog.i18n.bidi.rtlRe_=new RegExp(\"^[\"+goog.i18n.bidi.rtlChars_+\"]\");goog.i18n.bidi.isRtlChar=function(a){return goog.i18n.bidi.rtlRe_.test(a)};goog.i18n.bidi.isLtrChar=function(a){return goog.i18n.bidi.ltrRe_.test(a)};goog.i18n.bidi.isNeutralChar=function(a){return!goog.i18n.bidi.isLtrChar(a)&&!goog.i18n.bidi.isRtlChar(a)};\ngoog.i18n.bidi.ltrDirCheckRe_=new RegExp(\"^[^\"+goog.i18n.bidi.rtlChars_+\"]*[\"+goog.i18n.bidi.ltrChars_+\"]\");goog.i18n.bidi.rtlDirCheckRe_=new RegExp(\"^[^\"+goog.i18n.bidi.ltrChars_+\"]*[\"+goog.i18n.bidi.rtlChars_+\"]\");goog.i18n.bidi.startsWithRtl=function(a,b){return goog.i18n.bidi.rtlDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(a,b))};goog.i18n.bidi.isRtlText=goog.i18n.bidi.startsWithRtl;\ngoog.i18n.bidi.startsWithLtr=function(a,b){return goog.i18n.bidi.ltrDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(a,b))};goog.i18n.bidi.isLtrText=goog.i18n.bidi.startsWithLtr;goog.i18n.bidi.isRequiredLtrRe_=/^http:\\/\\/.*/;goog.i18n.bidi.isNeutralText=function(a,b){a=goog.i18n.bidi.stripHtmlIfNeeded_(a,b);return goog.i18n.bidi.isRequiredLtrRe_.test(a)||!goog.i18n.bidi.hasAnyLtr(a)&&!goog.i18n.bidi.hasAnyRtl(a)};\ngoog.i18n.bidi.ltrExitDirCheckRe_=new RegExp(\"[\"+goog.i18n.bidi.ltrChars_+\"][^\"+goog.i18n.bidi.rtlChars_+\"]*$\");goog.i18n.bidi.rtlExitDirCheckRe_=new RegExp(\"[\"+goog.i18n.bidi.rtlChars_+\"][^\"+goog.i18n.bidi.ltrChars_+\"]*$\");goog.i18n.bidi.endsWithLtr=function(a,b){return goog.i18n.bidi.ltrExitDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(a,b))};goog.i18n.bidi.isLtrExitText=goog.i18n.bidi.endsWithLtr;\ngoog.i18n.bidi.endsWithRtl=function(a,b){return goog.i18n.bidi.rtlExitDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(a,b))};goog.i18n.bidi.isRtlExitText=goog.i18n.bidi.endsWithRtl;goog.i18n.bidi.rtlLocalesRe_=/^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)/i;goog.i18n.bidi.isRtlLanguage=function(a){return goog.i18n.bidi.rtlLocalesRe_.test(a)};goog.i18n.bidi.bracketGuardTextRe_=/(\\(.*?\\)+)|(\\[.*?\\]+)|(\\{.*?\\}+)|(<.*?>+)/g;\ngoog.i18n.bidi.guardBracketInText=function(a,b){var c=(void 0===b?goog.i18n.bidi.hasAnyRtl(a):b)?goog.i18n.bidi.Format.RLM:goog.i18n.bidi.Format.LRM;return a.replace(goog.i18n.bidi.bracketGuardTextRe_,c+\"$&\"+c)};goog.i18n.bidi.enforceRtlInHtml=function(a){return\"<\"==a.charAt(0)?a.replace(/<\\w+/,\"$& dir=rtl\"):\"\\n<span dir=rtl>\"+a+\"</span>\"};goog.i18n.bidi.enforceRtlInText=function(a){return goog.i18n.bidi.Format.RLE+a+goog.i18n.bidi.Format.PDF};\ngoog.i18n.bidi.enforceLtrInHtml=function(a){return\"<\"==a.charAt(0)?a.replace(/<\\w+/,\"$& dir=ltr\"):\"\\n<span dir=ltr>\"+a+\"</span>\"};goog.i18n.bidi.enforceLtrInText=function(a){return goog.i18n.bidi.Format.LRE+a+goog.i18n.bidi.Format.PDF};goog.i18n.bidi.dimensionsRe_=/:\\s*([.\\d][.\\w]*)\\s+([.\\d][.\\w]*)\\s+([.\\d][.\\w]*)\\s+([.\\d][.\\w]*)/g;goog.i18n.bidi.leftRe_=/left/gi;goog.i18n.bidi.rightRe_=/right/gi;goog.i18n.bidi.tempRe_=/%%%%/g;\ngoog.i18n.bidi.mirrorCSS=function(a){return a.replace(goog.i18n.bidi.dimensionsRe_,\":$1 $4 $3 $2\").replace(goog.i18n.bidi.leftRe_,\"%%%%\").replace(goog.i18n.bidi.rightRe_,goog.i18n.bidi.LEFT).replace(goog.i18n.bidi.tempRe_,goog.i18n.bidi.RIGHT)};goog.i18n.bidi.doubleQuoteSubstituteRe_=/([\\u0591-\\u05f2])\"/g;goog.i18n.bidi.singleQuoteSubstituteRe_=/([\\u0591-\\u05f2])'/g;\ngoog.i18n.bidi.normalizeHebrewQuote=function(a){return a.replace(goog.i18n.bidi.doubleQuoteSubstituteRe_,\"$1\\u05f4\").replace(goog.i18n.bidi.singleQuoteSubstituteRe_,\"$1\\u05f3\")};goog.i18n.bidi.wordSeparatorRe_=/\\s+/;goog.i18n.bidi.hasNumeralsRe_=/[\\d\\u06f0-\\u06f9]/;goog.i18n.bidi.rtlDetectionThreshold_=.4;\ngoog.i18n.bidi.estimateDirection=function(a,b){for(var c=0,d=0,e=!1,f=goog.i18n.bidi.stripHtmlIfNeeded_(a,b).split(goog.i18n.bidi.wordSeparatorRe_),g=0;g<f.length;g++){var h=f[g];goog.i18n.bidi.startsWithRtl(h)?(c++,d++):goog.i18n.bidi.isRequiredLtrRe_.test(h)?e=!0:goog.i18n.bidi.hasAnyLtr(h)?d++:goog.i18n.bidi.hasNumeralsRe_.test(h)&&(e=!0)}return 0==d?e?goog.i18n.bidi.Dir.LTR:goog.i18n.bidi.Dir.NEUTRAL:c/d>goog.i18n.bidi.rtlDetectionThreshold_?goog.i18n.bidi.Dir.RTL:goog.i18n.bidi.Dir.LTR};\ngoog.i18n.bidi.detectRtlDirectionality=function(a,b){return goog.i18n.bidi.estimateDirection(a,b)==goog.i18n.bidi.Dir.RTL};goog.i18n.bidi.setElementDirAndAlign=function(a,b){a&&(b=goog.i18n.bidi.toDir(b))&&(a.style.textAlign=b==goog.i18n.bidi.Dir.RTL?goog.i18n.bidi.RIGHT:goog.i18n.bidi.LEFT,a.dir=b==goog.i18n.bidi.Dir.RTL?\"rtl\":\"ltr\")};\ngoog.i18n.bidi.setElementDirByTextDirectionality=function(a,b){switch(goog.i18n.bidi.estimateDirection(b)){case goog.i18n.bidi.Dir.LTR:a.dir=\"ltr\";break;case goog.i18n.bidi.Dir.RTL:a.dir=\"rtl\";break;default:a.removeAttribute(\"dir\")}};goog.i18n.bidi.DirectionalString=function(){};goog.html.SafeUrl=function(){this.privateDoNotAccessOrElseSafeHtmlWrappedValue_=\"\";this.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_=goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_};goog.html.SafeUrl.INNOCUOUS_STRING=\"about:invalid#zClosurez\";goog.html.SafeUrl.prototype.implementsGoogStringTypedString=!0;goog.html.SafeUrl.prototype.getTypedStringValue=function(){return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_};\ngoog.html.SafeUrl.prototype.implementsGoogI18nBidiDirectionalString=!0;goog.html.SafeUrl.prototype.getDirection=function(){return goog.i18n.bidi.Dir.LTR};goog.DEBUG&&(goog.html.SafeUrl.prototype.toString=function(){return\"SafeUrl{\"+this.privateDoNotAccessOrElseSafeHtmlWrappedValue_+\"}\"});\ngoog.html.SafeUrl.unwrap=function(a){if(a instanceof goog.html.SafeUrl&&a.constructor===goog.html.SafeUrl&&a.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_===goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_)return a.privateDoNotAccessOrElseSafeHtmlWrappedValue_;goog.asserts.fail(\"expected object of type SafeUrl, got '\"+a+\"' of type \"+goog.typeOf(a));return\"type_error:SafeUrl\"};goog.html.SafeUrl.fromConstant=function(a){return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(goog.string.Const.unwrap(a))};\ngoog.html.SAFE_MIME_TYPE_PATTERN_=/^(?:image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\\/(?:mpeg|mp4|ogg|webm))$/i;goog.html.SafeUrl.fromBlob=function(a){a=goog.html.SAFE_MIME_TYPE_PATTERN_.test(a.type)?goog.fs.url.createObjectUrl(a):goog.html.SafeUrl.INNOCUOUS_STRING;return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(a)};goog.html.DATA_URL_PATTERN_=/^data:([^;,]*);base64,[a-z0-9+\\/]+=*$/i;\ngoog.html.SafeUrl.fromDataUrl=function(a){var b=a.match(goog.html.DATA_URL_PATTERN_),b=b&&goog.html.SAFE_MIME_TYPE_PATTERN_.test(b[1]);return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(b?a:goog.html.SafeUrl.INNOCUOUS_STRING)};goog.html.SafeUrl.fromTelUrl=function(a){goog.string.caseInsensitiveStartsWith(a,\"tel:\")||(a=goog.html.SafeUrl.INNOCUOUS_STRING);return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(a)};goog.html.SAFE_URL_PATTERN_=/^(?:(?:https?|mailto|ftp):|[^&:/?#]*(?:[/?#]|$))/i;\ngoog.html.SafeUrl.sanitize=function(a){if(a instanceof goog.html.SafeUrl)return a;a=a.implementsGoogStringTypedString?a.getTypedStringValue():String(a);goog.html.SAFE_URL_PATTERN_.test(a)||(a=goog.html.SafeUrl.INNOCUOUS_STRING);return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(a)};goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_={};\ngoog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse=function(a){var b=new goog.html.SafeUrl;b.privateDoNotAccessOrElseSafeHtmlWrappedValue_=a;return b};goog.html.SafeUrl.ABOUT_BLANK=goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(\"about:blank\");goog.html.TrustedResourceUrl=function(){this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_=\"\";this.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_=goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_};goog.html.TrustedResourceUrl.prototype.implementsGoogStringTypedString=!0;goog.html.TrustedResourceUrl.prototype.getTypedStringValue=function(){return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_};\ngoog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString=!0;goog.html.TrustedResourceUrl.prototype.getDirection=function(){return goog.i18n.bidi.Dir.LTR};goog.DEBUG&&(goog.html.TrustedResourceUrl.prototype.toString=function(){return\"TrustedResourceUrl{\"+this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_+\"}\"});\ngoog.html.TrustedResourceUrl.unwrap=function(a){if(a instanceof goog.html.TrustedResourceUrl&&a.constructor===goog.html.TrustedResourceUrl&&a.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_===goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_)return a.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;goog.asserts.fail(\"expected object of type TrustedResourceUrl, got '\"+a+\"' of type \"+goog.typeOf(a));return\"type_error:TrustedResourceUrl\"};\ngoog.html.TrustedResourceUrl.fromConstant=function(a){return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(goog.string.Const.unwrap(a))};goog.html.TrustedResourceUrl.fromConstants=function(a){for(var b=\"\",c=0;c<a.length;c++)b+=goog.string.Const.unwrap(a[c]);return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(b)};goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_={};\ngoog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse=function(a){var b=new goog.html.TrustedResourceUrl;b.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_=a;return b};goog.html.SafeHtml=function(){this.privateDoNotAccessOrElseSafeHtmlWrappedValue_=\"\";this.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_=goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;this.dir_=null};goog.html.SafeHtml.prototype.implementsGoogI18nBidiDirectionalString=!0;goog.html.SafeHtml.prototype.getDirection=function(){return this.dir_};goog.html.SafeHtml.prototype.implementsGoogStringTypedString=!0;goog.html.SafeHtml.prototype.getTypedStringValue=function(){return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_};\ngoog.DEBUG&&(goog.html.SafeHtml.prototype.toString=function(){return\"SafeHtml{\"+this.privateDoNotAccessOrElseSafeHtmlWrappedValue_+\"}\"});\ngoog.html.SafeHtml.unwrap=function(a){if(a instanceof goog.html.SafeHtml&&a.constructor===goog.html.SafeHtml&&a.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_===goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_)return a.privateDoNotAccessOrElseSafeHtmlWrappedValue_;goog.asserts.fail(\"expected object of type SafeHtml, got '\"+a+\"' of type \"+goog.typeOf(a));return\"type_error:SafeHtml\"};\ngoog.html.SafeHtml.htmlEscape=function(a){if(a instanceof goog.html.SafeHtml)return a;var b=null;a.implementsGoogI18nBidiDirectionalString&&(b=a.getDirection());a=a.implementsGoogStringTypedString?a.getTypedStringValue():String(a);return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(goog.string.htmlEscape(a),b)};\ngoog.html.SafeHtml.htmlEscapePreservingNewlines=function(a){if(a instanceof goog.html.SafeHtml)return a;a=goog.html.SafeHtml.htmlEscape(a);return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(goog.string.newLineToBr(goog.html.SafeHtml.unwrap(a)),a.getDirection())};\ngoog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces=function(a){if(a instanceof goog.html.SafeHtml)return a;a=goog.html.SafeHtml.htmlEscape(a);return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(goog.string.whitespaceEscape(goog.html.SafeHtml.unwrap(a)),a.getDirection())};goog.html.SafeHtml.from=goog.html.SafeHtml.htmlEscape;goog.html.SafeHtml.VALID_NAMES_IN_TAG_=/^[a-zA-Z0-9-]+$/;\ngoog.html.SafeHtml.URL_ATTRIBUTES_={action:!0,cite:!0,data:!0,formaction:!0,href:!0,manifest:!0,poster:!0,src:!0};goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_={APPLET:!0,BASE:!0,EMBED:!0,IFRAME:!0,LINK:!0,MATH:!0,META:!0,OBJECT:!0,SCRIPT:!0,STYLE:!0,SVG:!0,TEMPLATE:!0};goog.html.SafeHtml.create=function(a,b,c){goog.html.SafeHtml.verifyTagName(a);return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(a,b,c)};\ngoog.html.SafeHtml.verifyTagName=function(a){if(!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(a))throw Error(\"Invalid tag name <\"+a+\">.\");if(a.toUpperCase()in goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_)throw Error(\"Tag name <\"+a+\"> is not allowed for SafeHtml.\");};\ngoog.html.SafeHtml.createIframe=function(a,b,c,d){a&&goog.html.TrustedResourceUrl.unwrap(a);var e={};e.src=a||null;e.srcdoc=b&&goog.html.SafeHtml.unwrap(b);a=goog.html.SafeHtml.combineAttributes(e,{sandbox:\"\"},c);return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(\"iframe\",a,d)};\ngoog.html.SafeHtml.createSandboxIframe=function(a,b,c,d){if(!goog.html.SafeHtml.canUseSandboxIframe())throw Error(\"The browser does not support sandboxed iframes.\");var e={};e.src=a?goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(a)):null;e.srcdoc=b||null;e.sandbox=\"\";a=goog.html.SafeHtml.combineAttributes(e,{},c);return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(\"iframe\",a,d)};\ngoog.html.SafeHtml.canUseSandboxIframe=function(){return goog.global.HTMLIFrameElement&&\"sandbox\"in goog.global.HTMLIFrameElement.prototype};goog.html.SafeHtml.createScriptSrc=function(a,b){goog.html.TrustedResourceUrl.unwrap(a);var c=goog.html.SafeHtml.combineAttributes({src:a},{},b);return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(\"script\",c)};\ngoog.html.SafeHtml.createStyle=function(a,b){var c=goog.html.SafeHtml.combineAttributes({type:\"text/css\"},{},b),d=\"\";a=goog.array.concat(a);for(var e=0;e<a.length;e++)d+=goog.html.SafeStyleSheet.unwrap(a[e]);d=goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(d,goog.i18n.bidi.Dir.NEUTRAL);return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(\"style\",c,d)};\ngoog.html.SafeHtml.createMetaRefresh=function(a,b){var c=goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(a));(goog.labs.userAgent.browser.isIE()||goog.labs.userAgent.browser.isEdge())&&goog.string.contains(c,\";\")&&(c=\"'\"+c.replace(/'/g,\"%27\")+\"'\");return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(\"meta\",{\"http-equiv\":\"refresh\",content:(b||0)+\"; url=\"+c})};\ngoog.html.SafeHtml.getAttrNameAndValue_=function(a,b,c){if(c instanceof goog.string.Const)c=goog.string.Const.unwrap(c);else if(\"style\"==b.toLowerCase())c=goog.html.SafeHtml.getStyleValue_(c);else{if(/^on/i.test(b))throw Error('Attribute \"'+b+'\" requires goog.string.Const value, \"'+c+'\" given.');if(b.toLowerCase()in goog.html.SafeHtml.URL_ATTRIBUTES_)if(c instanceof goog.html.TrustedResourceUrl)c=goog.html.TrustedResourceUrl.unwrap(c);else if(c instanceof goog.html.SafeUrl)c=goog.html.SafeUrl.unwrap(c);\nelse if(goog.isString(c))c=goog.html.SafeUrl.sanitize(c).getTypedStringValue();else throw Error('Attribute \"'+b+'\" on tag \"'+a+'\" requires goog.html.SafeUrl, goog.string.Const, or string, value \"'+c+'\" given.');}c.implementsGoogStringTypedString&&(c=c.getTypedStringValue());goog.asserts.assert(goog.isString(c)||goog.isNumber(c),\"String or number value expected, got \"+typeof c+\" with value: \"+c);return b+'=\"'+goog.string.htmlEscape(String(c))+'\"'};\ngoog.html.SafeHtml.getStyleValue_=function(a){if(!goog.isObject(a))throw Error('The \"style\" attribute requires goog.html.SafeStyle or map of style properties, '+typeof a+\" given: \"+a);a instanceof goog.html.SafeStyle||(a=goog.html.SafeStyle.create(a));return goog.html.SafeStyle.unwrap(a)};goog.html.SafeHtml.createWithDir=function(a,b,c,d){b=goog.html.SafeHtml.create(b,c,d);b.dir_=a;return b};\ngoog.html.SafeHtml.concat=function(a){var b=goog.i18n.bidi.Dir.NEUTRAL,c=\"\",d=function(a){goog.isArray(a)?goog.array.forEach(a,d):(a=goog.html.SafeHtml.htmlEscape(a),c+=goog.html.SafeHtml.unwrap(a),a=a.getDirection(),b==goog.i18n.bidi.Dir.NEUTRAL?b=a:a!=goog.i18n.bidi.Dir.NEUTRAL&&b!=a&&(b=null))};goog.array.forEach(arguments,d);return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(c,b)};\ngoog.html.SafeHtml.concatWithDir=function(a,b){var c=goog.html.SafeHtml.concat(goog.array.slice(arguments,1));c.dir_=a;return c};goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_={};goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse=function(a,b){return(new goog.html.SafeHtml).initSecurityPrivateDoNotAccessOrElse_(a,b)};goog.html.SafeHtml.prototype.initSecurityPrivateDoNotAccessOrElse_=function(a,b){this.privateDoNotAccessOrElseSafeHtmlWrappedValue_=a;this.dir_=b;return this};\ngoog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse=function(a,b,c){var d=null,e;e=\"<\"+a+goog.html.SafeHtml.stringifyAttributes(a,b);goog.isDefAndNotNull(c)?goog.isArray(c)||(c=[c]):c=[];goog.dom.tags.isVoidTag(a.toLowerCase())?(goog.asserts.assert(!c.length,\"Void tag <\"+a+\"> does not allow content.\"),e+=\">\"):(d=goog.html.SafeHtml.concat(c),e+=\">\"+goog.html.SafeHtml.unwrap(d)+\"</\"+a+\">\",d=d.getDirection());(a=b&&b.dir)&&(d=/^(ltr|rtl|auto)$/i.test(a)?goog.i18n.bidi.Dir.NEUTRAL:null);\nreturn goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(e,d)};goog.html.SafeHtml.stringifyAttributes=function(a,b){var c=\"\";if(b)for(var d in b){if(!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(d))throw Error('Invalid attribute name \"'+d+'\".');var e=b[d];goog.isDefAndNotNull(e)&&(c+=\" \"+goog.html.SafeHtml.getAttrNameAndValue_(a,d,e))}return c};\ngoog.html.SafeHtml.combineAttributes=function(a,b,c){var d={},e;for(e in a)goog.asserts.assert(e.toLowerCase()==e,\"Must be lower case\"),d[e]=a[e];for(e in b)goog.asserts.assert(e.toLowerCase()==e,\"Must be lower case\"),d[e]=b[e];for(e in c){var f=e.toLowerCase();if(f in a)throw Error('Cannot override \"'+f+'\" attribute, got \"'+e+'\" with value \"'+c[e]+'\"');f in b&&delete d[f];d[e]=c[e]}return d};\ngoog.html.SafeHtml.DOCTYPE_HTML=goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\"<!DOCTYPE html>\",goog.i18n.bidi.Dir.NEUTRAL);goog.html.SafeHtml.EMPTY=goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\"\",goog.i18n.bidi.Dir.NEUTRAL);goog.html.SafeHtml.BR=goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\"<br>\",goog.i18n.bidi.Dir.NEUTRAL);goog.dom.safe={};goog.dom.safe.InsertAdjacentHtmlPosition={AFTERBEGIN:\"afterbegin\",AFTEREND:\"afterend\",BEFOREBEGIN:\"beforebegin\",BEFOREEND:\"beforeend\"};goog.dom.safe.insertAdjacentHtml=function(a,b,c){a.insertAdjacentHTML(b,goog.html.SafeHtml.unwrap(c))};goog.dom.safe.setInnerHtml=function(a,b){a.innerHTML=goog.html.SafeHtml.unwrap(b)};goog.dom.safe.setOuterHtml=function(a,b){a.outerHTML=goog.html.SafeHtml.unwrap(b)};goog.dom.safe.documentWrite=function(a,b){a.write(goog.html.SafeHtml.unwrap(b))};\ngoog.dom.safe.setAnchorHref=function(a,b){var c;c=b instanceof goog.html.SafeUrl?b:goog.html.SafeUrl.sanitize(b);a.href=goog.html.SafeUrl.unwrap(c)};goog.dom.safe.setImageSrc=function(a,b){var c;c=b instanceof goog.html.SafeUrl?b:goog.html.SafeUrl.sanitize(b);a.src=goog.html.SafeUrl.unwrap(c)};goog.dom.safe.setEmbedSrc=function(a,b){a.src=goog.html.TrustedResourceUrl.unwrap(b)};goog.dom.safe.setFrameSrc=function(a,b){a.src=goog.html.TrustedResourceUrl.unwrap(b)};\ngoog.dom.safe.setIframeSrc=function(a,b){a.src=goog.html.TrustedResourceUrl.unwrap(b)};\ngoog.dom.safe.setLinkHrefAndRel=function(a,b,c){a.rel=c;goog.string.caseInsensitiveContains(c,\"stylesheet\")?(goog.asserts.assert(b instanceof goog.html.TrustedResourceUrl,'URL must be TrustedResourceUrl because \"rel\" contains \"stylesheet\"'),a.href=goog.html.TrustedResourceUrl.unwrap(b)):a.href=b instanceof goog.html.TrustedResourceUrl?goog.html.TrustedResourceUrl.unwrap(b):b instanceof goog.html.SafeUrl?goog.html.SafeUrl.unwrap(b):goog.html.SafeUrl.sanitize(b).getTypedStringValue()};\ngoog.dom.safe.setObjectData=function(a,b){a.data=goog.html.TrustedResourceUrl.unwrap(b)};goog.dom.safe.setScriptSrc=function(a,b){a.src=goog.html.TrustedResourceUrl.unwrap(b)};goog.dom.safe.setLocationHref=function(a,b){var c;c=b instanceof goog.html.SafeUrl?b:goog.html.SafeUrl.sanitize(b);a.href=goog.html.SafeUrl.unwrap(c)};\ngoog.dom.safe.openInWindow=function(a,b,c,d,e){a=a instanceof goog.html.SafeUrl?a:goog.html.SafeUrl.sanitize(a);return(b||window).open(goog.html.SafeUrl.unwrap(a),c?goog.string.Const.unwrap(c):\"\",d,e)};goog.html.SafeScript=function(){this.privateDoNotAccessOrElseSafeScriptWrappedValue_=\"\";this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_=goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_};goog.html.SafeScript.prototype.implementsGoogStringTypedString=!0;goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_={};goog.html.SafeScript.fromConstant=function(a){a=goog.string.Const.unwrap(a);return 0===a.length?goog.html.SafeScript.EMPTY:goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(a)};\ngoog.html.SafeScript.prototype.getTypedStringValue=function(){return this.privateDoNotAccessOrElseSafeScriptWrappedValue_};goog.DEBUG&&(goog.html.SafeScript.prototype.toString=function(){return\"SafeScript{\"+this.privateDoNotAccessOrElseSafeScriptWrappedValue_+\"}\"});\ngoog.html.SafeScript.unwrap=function(a){if(a instanceof goog.html.SafeScript&&a.constructor===goog.html.SafeScript&&a.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_===goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_)return a.privateDoNotAccessOrElseSafeScriptWrappedValue_;goog.asserts.fail(\"expected object of type SafeScript, got '\"+a+\"' of type \"+goog.typeOf(a));return\"type_error:SafeScript\"};goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse=function(a){return(new goog.html.SafeScript).initSecurityPrivateDoNotAccessOrElse_(a)};\ngoog.html.SafeScript.prototype.initSecurityPrivateDoNotAccessOrElse_=function(a){this.privateDoNotAccessOrElseSafeScriptWrappedValue_=a;return this};goog.html.SafeScript.EMPTY=goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(\"\");goog.html.uncheckedconversions={};goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract=function(a,b,c){goog.asserts.assertString(goog.string.Const.unwrap(a),\"must provide justification\");goog.asserts.assert(!goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(a)),\"must provide non-empty justification\");return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(b,c||null)};\ngoog.html.uncheckedconversions.safeScriptFromStringKnownToSatisfyTypeContract=function(a,b){goog.asserts.assertString(goog.string.Const.unwrap(a),\"must provide justification\");goog.asserts.assert(!goog.string.isEmpty(goog.string.Const.unwrap(a)),\"must provide non-empty justification\");return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(b)};\ngoog.html.uncheckedconversions.safeStyleFromStringKnownToSatisfyTypeContract=function(a,b){goog.asserts.assertString(goog.string.Const.unwrap(a),\"must provide justification\");goog.asserts.assert(!goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(a)),\"must provide non-empty justification\");return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(b)};\ngoog.html.uncheckedconversions.safeStyleSheetFromStringKnownToSatisfyTypeContract=function(a,b){goog.asserts.assertString(goog.string.Const.unwrap(a),\"must provide justification\");goog.asserts.assert(!goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(a)),\"must provide non-empty justification\");return goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(b)};\ngoog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract=function(a,b){goog.asserts.assertString(goog.string.Const.unwrap(a),\"must provide justification\");goog.asserts.assert(!goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(a)),\"must provide non-empty justification\");return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(b)};\ngoog.html.uncheckedconversions.trustedResourceUrlFromStringKnownToSatisfyTypeContract=function(a,b){goog.asserts.assertString(goog.string.Const.unwrap(a),\"must provide justification\");goog.asserts.assert(!goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(a)),\"must provide non-empty justification\");return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(b)};goog.math.Coordinate=function(a,b){this.x=goog.isDef(a)?a:0;this.y=goog.isDef(b)?b:0};goog.math.Coordinate.prototype.clone=function(){return new goog.math.Coordinate(this.x,this.y)};goog.DEBUG&&(goog.math.Coordinate.prototype.toString=function(){return\"(\"+this.x+\", \"+this.y+\")\"});goog.math.Coordinate.equals=function(a,b){return a==b?!0:a&&b?a.x==b.x&&a.y==b.y:!1};goog.math.Coordinate.distance=function(a,b){var c=a.x-b.x,d=a.y-b.y;return Math.sqrt(c*c+d*d)};\ngoog.math.Coordinate.magnitude=function(a){return Math.sqrt(a.x*a.x+a.y*a.y)};goog.math.Coordinate.azimuth=function(a){return goog.math.angle(0,0,a.x,a.y)};goog.math.Coordinate.squaredDistance=function(a,b){var c=a.x-b.x,d=a.y-b.y;return c*c+d*d};goog.math.Coordinate.difference=function(a,b){return new goog.math.Coordinate(a.x-b.x,a.y-b.y)};goog.math.Coordinate.sum=function(a,b){return new goog.math.Coordinate(a.x+b.x,a.y+b.y)};\ngoog.math.Coordinate.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};goog.math.Coordinate.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};goog.math.Coordinate.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};\ngoog.math.Coordinate.prototype.translate=function(a,b){a instanceof goog.math.Coordinate?(this.x+=a.x,this.y+=a.y):(this.x+=Number(a),goog.isNumber(b)&&(this.y+=b));return this};goog.math.Coordinate.prototype.scale=function(a,b){var c=goog.isNumber(b)?b:a;this.x*=a;this.y*=c;return this};goog.math.Coordinate.prototype.rotateRadians=function(a,b){var c=b||new goog.math.Coordinate(0,0),d=this.x,e=this.y,f=Math.cos(a),g=Math.sin(a);this.x=(d-c.x)*f-(e-c.y)*g+c.x;this.y=(d-c.x)*g+(e-c.y)*f+c.y};\ngoog.math.Coordinate.prototype.rotateDegrees=function(a,b){this.rotateRadians(goog.math.toRadians(a),b)};goog.math.Size=function(a,b){this.width=a;this.height=b};goog.math.Size.equals=function(a,b){return a==b?!0:a&&b?a.width==b.width&&a.height==b.height:!1};goog.math.Size.prototype.clone=function(){return new goog.math.Size(this.width,this.height)};goog.DEBUG&&(goog.math.Size.prototype.toString=function(){return\"(\"+this.width+\" x \"+this.height+\")\"});goog.math.Size.prototype.getLongest=function(){return Math.max(this.width,this.height)};\ngoog.math.Size.prototype.getShortest=function(){return Math.min(this.width,this.height)};goog.math.Size.prototype.area=function(){return this.width*this.height};goog.math.Size.prototype.perimeter=function(){return 2*(this.width+this.height)};goog.math.Size.prototype.aspectRatio=function(){return this.width/this.height};goog.math.Size.prototype.isEmpty=function(){return!this.area()};goog.math.Size.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};\ngoog.math.Size.prototype.fitsInside=function(a){return this.width<=a.width&&this.height<=a.height};goog.math.Size.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};goog.math.Size.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};goog.math.Size.prototype.scale=function(a,b){var c=goog.isNumber(b)?b:a;this.width*=a;this.height*=c;return this};\ngoog.math.Size.prototype.scaleToCover=function(a){a=this.aspectRatio()<=a.aspectRatio()?a.width/this.width:a.height/this.height;return this.scale(a)};goog.math.Size.prototype.scaleToFit=function(a){a=this.aspectRatio()>a.aspectRatio()?a.width/this.width:a.height/this.height;return this.scale(a)};goog.dom.ASSUME_QUIRKS_MODE=!1;goog.dom.ASSUME_STANDARDS_MODE=!1;goog.dom.COMPAT_MODE_KNOWN_=goog.dom.ASSUME_QUIRKS_MODE||goog.dom.ASSUME_STANDARDS_MODE;goog.dom.getDomHelper=function(a){return a?new goog.dom.DomHelper(goog.dom.getOwnerDocument(a)):goog.dom.defaultDomHelper_||(goog.dom.defaultDomHelper_=new goog.dom.DomHelper)};goog.dom.getDocument=function(){return document};goog.dom.getElement=function(a){return goog.dom.getElementHelper_(document,a)};\ngoog.dom.getElementHelper_=function(a,b){return goog.isString(b)?a.getElementById(b):b};goog.dom.getRequiredElement=function(a){return goog.dom.getRequiredElementHelper_(document,a)};goog.dom.getRequiredElementHelper_=function(a,b){goog.asserts.assertString(b);var c=goog.dom.getElementHelper_(a,b);return c=goog.asserts.assertElement(c,\"No element found with id: \"+b)};goog.dom.$=goog.dom.getElement;\ngoog.dom.getElementsByTagNameAndClass=function(a,b,c){return goog.dom.getElementsByTagNameAndClass_(document,a,b,c)};goog.dom.getElementsByClass=function(a,b){var c=b||document;return goog.dom.canUseQuerySelector_(c)?c.querySelectorAll(\".\"+a):goog.dom.getElementsByTagNameAndClass_(document,\"*\",a,b)};\ngoog.dom.getElementByClass=function(a,b){var c=b||document;return(c.getElementsByClassName?c.getElementsByClassName(a)[0]:goog.dom.canUseQuerySelector_(c)?c.querySelector(\".\"+a):goog.dom.getElementsByTagNameAndClass_(document,\"*\",a,b)[0])||null};goog.dom.getRequiredElementByClass=function(a,b){var c=goog.dom.getElementByClass(a,b);return goog.asserts.assert(c,\"No element found with className: \"+a)};goog.dom.canUseQuerySelector_=function(a){return!(!a.querySelectorAll||!a.querySelector)};\ngoog.dom.getElementsByTagNameAndClass_=function(a,b,c,d){a=d||a;b=b&&\"*\"!=b?b.toUpperCase():\"\";if(goog.dom.canUseQuerySelector_(a)&&(b||c))return a.querySelectorAll(b+(c?\".\"+c:\"\"));if(c&&a.getElementsByClassName){a=a.getElementsByClassName(c);if(b){d={};for(var e=0,f=0,g;g=a[f];f++)b==g.nodeName&&(d[e++]=g);d.length=e;return d}return a}a=a.getElementsByTagName(b||\"*\");if(c){d={};for(f=e=0;g=a[f];f++)b=g.className,\"function\"==typeof b.split&&goog.array.contains(b.split(/\\s+/),c)&&(d[e++]=g);d.length=\ne;return d}return a};goog.dom.$$=goog.dom.getElementsByTagNameAndClass;goog.dom.setProperties=function(a,b){goog.object.forEach(b,function(b,d){\"style\"==d?a.style.cssText=b:\"class\"==d?a.className=b:\"for\"==d?a.htmlFor=b:goog.dom.DIRECT_ATTRIBUTE_MAP_.hasOwnProperty(d)?a.setAttribute(goog.dom.DIRECT_ATTRIBUTE_MAP_[d],b):goog.string.startsWith(d,\"aria-\")||goog.string.startsWith(d,\"data-\")?a.setAttribute(d,b):a[d]=b})};\ngoog.dom.DIRECT_ATTRIBUTE_MAP_={cellpadding:\"cellPadding\",cellspacing:\"cellSpacing\",colspan:\"colSpan\",frameborder:\"frameBorder\",height:\"height\",maxlength:\"maxLength\",nonce:\"nonce\",role:\"role\",rowspan:\"rowSpan\",type:\"type\",usemap:\"useMap\",valign:\"vAlign\",width:\"width\"};goog.dom.getViewportSize=function(a){return goog.dom.getViewportSize_(a||window)};goog.dom.getViewportSize_=function(a){a=a.document;a=goog.dom.isCss1CompatMode_(a)?a.documentElement:a.body;return new goog.math.Size(a.clientWidth,a.clientHeight)};\ngoog.dom.getDocumentHeight=function(){return goog.dom.getDocumentHeight_(window)};goog.dom.getDocumentHeightForWindow=function(a){return goog.dom.getDocumentHeight_(a)};\ngoog.dom.getDocumentHeight_=function(a){var b=a.document,c=0;if(b){var c=b.body,d=b.documentElement;if(!d||!c)return 0;a=goog.dom.getViewportSize_(a).height;if(goog.dom.isCss1CompatMode_(b)&&d.scrollHeight)c=d.scrollHeight!=a?d.scrollHeight:d.offsetHeight;else{var b=d.scrollHeight,e=d.offsetHeight;d.clientHeight!=e&&(b=c.scrollHeight,e=c.offsetHeight);c=b>a?b>e?b:e:b<e?b:e}}return c};goog.dom.getPageScroll=function(a){return goog.dom.getDomHelper((a||goog.global||window).document).getDocumentScroll()};\ngoog.dom.getDocumentScroll=function(){return goog.dom.getDocumentScroll_(document)};goog.dom.getDocumentScroll_=function(a){var b=goog.dom.getDocumentScrollElement_(a);a=goog.dom.getWindow_(a);return goog.userAgent.IE&&goog.userAgent.isVersionOrHigher(\"10\")&&a.pageYOffset!=b.scrollTop?new goog.math.Coordinate(b.scrollLeft,b.scrollTop):new goog.math.Coordinate(a.pageXOffset||b.scrollLeft,a.pageYOffset||b.scrollTop)};goog.dom.getDocumentScrollElement=function(){return goog.dom.getDocumentScrollElement_(document)};\ngoog.dom.getDocumentScrollElement_=function(a){return a.scrollingElement?a.scrollingElement:!goog.userAgent.WEBKIT&&goog.dom.isCss1CompatMode_(a)?a.documentElement:a.body||a.documentElement};goog.dom.getWindow=function(a){return a?goog.dom.getWindow_(a):window};goog.dom.getWindow_=function(a){return a.parentWindow||a.defaultView};goog.dom.createDom=function(a,b,c){return goog.dom.createDom_(document,arguments)};goog.dom.createUntypedDom=function(a,b,c){return goog.dom.createDom_(document,arguments)};\ngoog.dom.createDom_=function(a,b){var c=String(b[0]),d=b[1];if(!goog.dom.BrowserFeature.CAN_ADD_NAME_OR_TYPE_ATTRIBUTES&&d&&(d.name||d.type)){c=[\"<\",c];d.name&&c.push(' name=\"',goog.string.htmlEscape(d.name),'\"');if(d.type){c.push(' type=\"',goog.string.htmlEscape(d.type),'\"');var e={};goog.object.extend(e,d);delete e.type;d=e}c.push(\">\");c=c.join(\"\")}c=a.createElement(c);d&&(goog.isString(d)?c.className=d:goog.isArray(d)?c.className=d.join(\" \"):goog.dom.setProperties(c,d));2<b.length&&goog.dom.append_(a,\nc,b,2);return c};goog.dom.append_=function(a,b,c,d){function e(c){c&&b.appendChild(goog.isString(c)?a.createTextNode(c):c)}for(;d<c.length;d++){var f=c[d];goog.isArrayLike(f)&&!goog.dom.isNodeLike(f)?goog.array.forEach(goog.dom.isNodeList(f)?goog.array.toArray(f):f,e):e(f)}};goog.dom.$dom=goog.dom.createDom;goog.dom.createElement=function(a){return document.createElement(String(a))};goog.dom.createTextNode=function(a){return document.createTextNode(String(a))};\ngoog.dom.createTable=function(a,b,c){return goog.dom.createTable_(document,a,b,!!c)};goog.dom.createTable_=function(a,b,c,d){for(var e=a.createElement(\"TABLE\"),f=e.appendChild(a.createElement(\"TBODY\")),g=0;g<b;g++){for(var h=a.createElement(\"TR\"),k=0;k<c;k++){var n=a.createElement(\"TD\");d&&goog.dom.setTextContent(n,goog.string.Unicode.NBSP);h.appendChild(n)}f.appendChild(h)}return e};\ngoog.dom.constHtmlToNode=function(a){var b=goog.array.map(arguments,goog.string.Const.unwrap),b=goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract(goog.string.Const.from(\"Constant HTML string, that gets turned into a Node later, so it will be automatically balanced.\"),b.join(\"\"));return goog.dom.safeHtmlToNode(b)};goog.dom.safeHtmlToNode=function(a){return goog.dom.safeHtmlToNode_(document,a)};\ngoog.dom.safeHtmlToNode_=function(a,b){var c=a.createElement(\"DIV\");goog.dom.BrowserFeature.INNER_HTML_NEEDS_SCOPED_ELEMENT?(goog.dom.safe.setInnerHtml(c,goog.html.SafeHtml.concat(goog.html.SafeHtml.BR,b)),c.removeChild(c.firstChild)):goog.dom.safe.setInnerHtml(c,b);return goog.dom.childrenToNode_(a,c)};goog.dom.childrenToNode_=function(a,b){if(1==b.childNodes.length)return b.removeChild(b.firstChild);for(var c=a.createDocumentFragment();b.firstChild;)c.appendChild(b.firstChild);return c};\ngoog.dom.isCss1CompatMode=function(){return goog.dom.isCss1CompatMode_(document)};goog.dom.isCss1CompatMode_=function(a){return goog.dom.COMPAT_MODE_KNOWN_?goog.dom.ASSUME_STANDARDS_MODE:\"CSS1Compat\"==a.compatMode};goog.dom.canHaveChildren=function(a){if(a.nodeType!=goog.dom.NodeType.ELEMENT)return!1;switch(a.tagName){case \"APPLET\":case \"AREA\":case \"BASE\":case \"BR\":case \"COL\":case \"COMMAND\":case \"EMBED\":case \"FRAME\":case \"HR\":case \"IMG\":case \"INPUT\":case \"IFRAME\":case \"ISINDEX\":case \"KEYGEN\":case \"LINK\":case \"NOFRAMES\":case \"NOSCRIPT\":case \"META\":case \"OBJECT\":case \"PARAM\":case \"SCRIPT\":case \"SOURCE\":case \"STYLE\":case \"TRACK\":case \"WBR\":return!1}return!0};\ngoog.dom.appendChild=function(a,b){a.appendChild(b)};goog.dom.append=function(a,b){goog.dom.append_(goog.dom.getOwnerDocument(a),a,arguments,1)};goog.dom.removeChildren=function(a){for(var b;b=a.firstChild;)a.removeChild(b)};goog.dom.insertSiblingBefore=function(a,b){b.parentNode&&b.parentNode.insertBefore(a,b)};goog.dom.insertSiblingAfter=function(a,b){b.parentNode&&b.parentNode.insertBefore(a,b.nextSibling)};goog.dom.insertChildAt=function(a,b,c){a.insertBefore(b,a.childNodes[c]||null)};\ngoog.dom.removeNode=function(a){return a&&a.parentNode?a.parentNode.removeChild(a):null};goog.dom.replaceNode=function(a,b){var c=b.parentNode;c&&c.replaceChild(a,b)};goog.dom.flattenElement=function(a){var b,c=a.parentNode;if(c&&c.nodeType!=goog.dom.NodeType.DOCUMENT_FRAGMENT){if(a.removeNode)return a.removeNode(!1);for(;b=a.firstChild;)c.insertBefore(b,a);return goog.dom.removeNode(a)}};\ngoog.dom.getChildren=function(a){return goog.dom.BrowserFeature.CAN_USE_CHILDREN_ATTRIBUTE&&void 0!=a.children?a.children:goog.array.filter(a.childNodes,function(a){return a.nodeType==goog.dom.NodeType.ELEMENT})};goog.dom.getFirstElementChild=function(a){return goog.isDef(a.firstElementChild)?a.firstElementChild:goog.dom.getNextElementNode_(a.firstChild,!0)};goog.dom.getLastElementChild=function(a){return goog.isDef(a.lastElementChild)?a.lastElementChild:goog.dom.getNextElementNode_(a.lastChild,!1)};\ngoog.dom.getNextElementSibling=function(a){return goog.isDef(a.nextElementSibling)?a.nextElementSibling:goog.dom.getNextElementNode_(a.nextSibling,!0)};goog.dom.getPreviousElementSibling=function(a){return goog.isDef(a.previousElementSibling)?a.previousElementSibling:goog.dom.getNextElementNode_(a.previousSibling,!1)};goog.dom.getNextElementNode_=function(a,b){for(;a&&a.nodeType!=goog.dom.NodeType.ELEMENT;)a=b?a.nextSibling:a.previousSibling;return a};\ngoog.dom.getNextNode=function(a){if(!a)return null;if(a.firstChild)return a.firstChild;for(;a&&!a.nextSibling;)a=a.parentNode;return a?a.nextSibling:null};goog.dom.getPreviousNode=function(a){if(!a)return null;if(!a.previousSibling)return a.parentNode;for(a=a.previousSibling;a&&a.lastChild;)a=a.lastChild;return a};goog.dom.isNodeLike=function(a){return goog.isObject(a)&&0<a.nodeType};goog.dom.isElement=function(a){return goog.isObject(a)&&a.nodeType==goog.dom.NodeType.ELEMENT};\ngoog.dom.isWindow=function(a){return goog.isObject(a)&&a.window==a};goog.dom.getParentElement=function(a){var b;if(goog.dom.BrowserFeature.CAN_USE_PARENT_ELEMENT_PROPERTY&&!(goog.userAgent.IE&&goog.userAgent.isVersionOrHigher(\"9\")&&!goog.userAgent.isVersionOrHigher(\"10\")&&goog.global.SVGElement&&a instanceof goog.global.SVGElement)&&(b=a.parentElement))return b;b=a.parentNode;return goog.dom.isElement(b)?b:null};\ngoog.dom.contains=function(a,b){if(!a||!b)return!1;if(a.contains&&b.nodeType==goog.dom.NodeType.ELEMENT)return a==b||a.contains(b);if(\"undefined\"!=typeof a.compareDocumentPosition)return a==b||!!(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a};\ngoog.dom.compareNodeOrder=function(a,b){if(a==b)return 0;if(a.compareDocumentPosition)return a.compareDocumentPosition(b)&2?1:-1;if(goog.userAgent.IE&&!goog.userAgent.isDocumentModeOrHigher(9)){if(a.nodeType==goog.dom.NodeType.DOCUMENT)return-1;if(b.nodeType==goog.dom.NodeType.DOCUMENT)return 1}if(\"sourceIndex\"in a||a.parentNode&&\"sourceIndex\"in a.parentNode){var c=a.nodeType==goog.dom.NodeType.ELEMENT,d=b.nodeType==goog.dom.NodeType.ELEMENT;if(c&&d)return a.sourceIndex-b.sourceIndex;var e=a.parentNode,\nf=b.parentNode;return e==f?goog.dom.compareSiblingOrder_(a,b):!c&&goog.dom.contains(e,b)?-1*goog.dom.compareParentsDescendantNodeIe_(a,b):!d&&goog.dom.contains(f,a)?goog.dom.compareParentsDescendantNodeIe_(b,a):(c?a.sourceIndex:e.sourceIndex)-(d?b.sourceIndex:f.sourceIndex)}d=goog.dom.getOwnerDocument(a);c=d.createRange();c.selectNode(a);c.collapse(!0);d=d.createRange();d.selectNode(b);d.collapse(!0);return c.compareBoundaryPoints(goog.global.Range.START_TO_END,d)};\ngoog.dom.compareParentsDescendantNodeIe_=function(a,b){var c=a.parentNode;if(c==b)return-1;for(var d=b;d.parentNode!=c;)d=d.parentNode;return goog.dom.compareSiblingOrder_(d,a)};goog.dom.compareSiblingOrder_=function(a,b){for(var c=b;c=c.previousSibling;)if(c==a)return-1;return 1};\ngoog.dom.findCommonAncestor=function(a){var b,c=arguments.length;if(!c)return null;if(1==c)return arguments[0];var d=[],e=Infinity;for(b=0;b<c;b++){for(var f=[],g=arguments[b];g;)f.unshift(g),g=g.parentNode;d.push(f);e=Math.min(e,f.length)}f=null;for(b=0;b<e;b++){for(var g=d[0][b],h=1;h<c;h++)if(g!=d[h][b])return f;f=g}return f};goog.dom.getOwnerDocument=function(a){goog.asserts.assert(a,\"Node cannot be null or undefined.\");return a.nodeType==goog.dom.NodeType.DOCUMENT?a:a.ownerDocument||a.document};\ngoog.dom.getFrameContentDocument=function(a){return a.contentDocument||a.contentWindow.document};goog.dom.getFrameContentWindow=function(a){try{return a.contentWindow||(a.contentDocument?goog.dom.getWindow(a.contentDocument):null)}catch(b){}return null};\ngoog.dom.setTextContent=function(a,b){goog.asserts.assert(null!=a,\"goog.dom.setTextContent expects a non-null value for node\");if(\"textContent\"in a)a.textContent=b;else if(a.nodeType==goog.dom.NodeType.TEXT)a.data=b;else if(a.firstChild&&a.firstChild.nodeType==goog.dom.NodeType.TEXT){for(;a.lastChild!=a.firstChild;)a.removeChild(a.lastChild);a.firstChild.data=b}else{goog.dom.removeChildren(a);var c=goog.dom.getOwnerDocument(a);a.appendChild(c.createTextNode(String(b)))}};\ngoog.dom.getOuterHtml=function(a){goog.asserts.assert(null!==a,\"goog.dom.getOuterHtml expects a non-null value for element\");if(\"outerHTML\"in a)return a.outerHTML;var b=goog.dom.getOwnerDocument(a).createElement(\"DIV\");b.appendChild(a.cloneNode(!0));return b.innerHTML};goog.dom.findNode=function(a,b){var c=[];return goog.dom.findNodes_(a,b,c,!0)?c[0]:void 0};goog.dom.findNodes=function(a,b){var c=[];goog.dom.findNodes_(a,b,c,!1);return c};\ngoog.dom.findNodes_=function(a,b,c,d){if(null!=a)for(a=a.firstChild;a;){if(b(a)&&(c.push(a),d)||goog.dom.findNodes_(a,b,c,d))return!0;a=a.nextSibling}return!1};goog.dom.TAGS_TO_IGNORE_={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1};goog.dom.PREDEFINED_TAG_VALUES_={IMG:\" \",BR:\"\\n\"};goog.dom.isFocusableTabIndex=function(a){return goog.dom.hasSpecifiedTabIndex_(a)&&goog.dom.isTabIndexFocusable_(a)};goog.dom.setFocusableTabIndex=function(a,b){b?a.tabIndex=0:(a.tabIndex=-1,a.removeAttribute(\"tabIndex\"))};\ngoog.dom.isFocusable=function(a){var b;return(b=goog.dom.nativelySupportsFocus_(a)?!a.disabled&&(!goog.dom.hasSpecifiedTabIndex_(a)||goog.dom.isTabIndexFocusable_(a)):goog.dom.isFocusableTabIndex(a))&&goog.userAgent.IE?goog.dom.hasNonZeroBoundingRect_(a):b};goog.dom.hasSpecifiedTabIndex_=function(a){a=a.getAttributeNode(\"tabindex\");return goog.isDefAndNotNull(a)&&a.specified};goog.dom.isTabIndexFocusable_=function(a){a=a.tabIndex;return goog.isNumber(a)&&0<=a&&32768>a};\ngoog.dom.nativelySupportsFocus_=function(a){return\"A\"==a.tagName||\"INPUT\"==a.tagName||\"TEXTAREA\"==a.tagName||\"SELECT\"==a.tagName||\"BUTTON\"==a.tagName};goog.dom.hasNonZeroBoundingRect_=function(a){a=!goog.isFunction(a.getBoundingClientRect)||goog.userAgent.IE&&null==a.parentElement?{height:a.offsetHeight,width:a.offsetWidth}:a.getBoundingClientRect();return goog.isDefAndNotNull(a)&&0<a.height&&0<a.width};\ngoog.dom.getTextContent=function(a){if(goog.dom.BrowserFeature.CAN_USE_INNER_TEXT&&null!==a&&\"innerText\"in a)a=goog.string.canonicalizeNewlines(a.innerText);else{var b=[];goog.dom.getTextContent_(a,b,!0);a=b.join(\"\")}a=a.replace(/ \\xAD /g,\" \").replace(/\\xAD/g,\"\");a=a.replace(/\\u200B/g,\"\");goog.dom.BrowserFeature.CAN_USE_INNER_TEXT||(a=a.replace(/ +/g,\" \"));\" \"!=a&&(a=a.replace(/^\\s*/,\"\"));return a};goog.dom.getRawTextContent=function(a){var b=[];goog.dom.getTextContent_(a,b,!1);return b.join(\"\")};\ngoog.dom.getTextContent_=function(a,b,c){if(!(a.nodeName in goog.dom.TAGS_TO_IGNORE_))if(a.nodeType==goog.dom.NodeType.TEXT)c?b.push(String(a.nodeValue).replace(/(\\r\\n|\\r|\\n)/g,\"\")):b.push(a.nodeValue);else if(a.nodeName in goog.dom.PREDEFINED_TAG_VALUES_)b.push(goog.dom.PREDEFINED_TAG_VALUES_[a.nodeName]);else for(a=a.firstChild;a;)goog.dom.getTextContent_(a,b,c),a=a.nextSibling};goog.dom.getNodeTextLength=function(a){return goog.dom.getTextContent(a).length};\ngoog.dom.getNodeTextOffset=function(a,b){for(var c=b||goog.dom.getOwnerDocument(a).body,d=[];a&&a!=c;){for(var e=a;e=e.previousSibling;)d.unshift(goog.dom.getTextContent(e));a=a.parentNode}return goog.string.trimLeft(d.join(\"\")).replace(/ +/g,\" \").length};\ngoog.dom.getNodeAtOffset=function(a,b,c){a=[a];for(var d=0,e=null;0<a.length&&d<b;)if(e=a.pop(),!(e.nodeName in goog.dom.TAGS_TO_IGNORE_))if(e.nodeType==goog.dom.NodeType.TEXT)var f=e.nodeValue.replace(/(\\r\\n|\\r|\\n)/g,\"\").replace(/ +/g,\" \"),d=d+f.length;else if(e.nodeName in goog.dom.PREDEFINED_TAG_VALUES_)d+=goog.dom.PREDEFINED_TAG_VALUES_[e.nodeName].length;else for(f=e.childNodes.length-1;0<=f;f--)a.push(e.childNodes[f]);goog.isObject(c)&&(c.remainder=e?e.nodeValue.length+b-d-1:0,c.node=e);return e};\ngoog.dom.isNodeList=function(a){if(a&&\"number\"==typeof a.length){if(goog.isObject(a))return\"function\"==typeof a.item||\"string\"==typeof a.item;if(goog.isFunction(a))return\"function\"==typeof a.item}return!1};goog.dom.getAncestorByTagNameAndClass=function(a,b,c,d){if(!b&&!c)return null;var e=b?b.toUpperCase():null;return goog.dom.getAncestor(a,function(a){return(!e||a.nodeName==e)&&(!c||goog.isString(a.className)&&goog.array.contains(a.className.split(/\\s+/),c))},!0,d)};\ngoog.dom.getAncestorByClass=function(a,b,c){return goog.dom.getAncestorByTagNameAndClass(a,null,b,c)};goog.dom.getAncestor=function(a,b,c,d){c||(a=a.parentNode);for(c=0;a&&(null==d||c<=d);){goog.asserts.assert(\"parentNode\"!=a.name);if(b(a))return a;a=a.parentNode;c++}return null};goog.dom.getActiveElement=function(a){try{return a&&a.activeElement}catch(b){}return null};\ngoog.dom.getPixelRatio=function(){var a=goog.dom.getWindow();return goog.isDef(a.devicePixelRatio)?a.devicePixelRatio:a.matchMedia?goog.dom.matchesPixelRatio_(.75)||goog.dom.matchesPixelRatio_(1.5)||goog.dom.matchesPixelRatio_(2)||goog.dom.matchesPixelRatio_(3)||1:1};goog.dom.matchesPixelRatio_=function(a){return goog.dom.getWindow().matchMedia(\"(-webkit-min-device-pixel-ratio: \"+a+\"),(min--moz-device-pixel-ratio: \"+a+\"),(min-resolution: \"+a+\"dppx)\").matches?a:0};\ngoog.dom.DomHelper=function(a){this.document_=a||goog.global.document||document};goog.dom.DomHelper.prototype.getDomHelper=goog.dom.getDomHelper;goog.dom.DomHelper.prototype.setDocument=function(a){this.document_=a};goog.dom.DomHelper.prototype.getDocument=function(){return this.document_};goog.dom.DomHelper.prototype.getElement=function(a){return goog.dom.getElementHelper_(this.document_,a)};\ngoog.dom.DomHelper.prototype.getRequiredElement=function(a){return goog.dom.getRequiredElementHelper_(this.document_,a)};goog.dom.DomHelper.prototype.$=goog.dom.DomHelper.prototype.getElement;goog.dom.DomHelper.prototype.getElementsByTagNameAndClass=function(a,b,c){return goog.dom.getElementsByTagNameAndClass_(this.document_,a,b,c)};goog.dom.DomHelper.prototype.getElementsByClass=function(a,b){return goog.dom.getElementsByClass(a,b||this.document_)};\ngoog.dom.DomHelper.prototype.getElementByClass=function(a,b){return goog.dom.getElementByClass(a,b||this.document_)};goog.dom.DomHelper.prototype.getRequiredElementByClass=function(a,b){return goog.dom.getRequiredElementByClass(a,b||this.document_)};goog.dom.DomHelper.prototype.$$=goog.dom.DomHelper.prototype.getElementsByTagNameAndClass;goog.dom.DomHelper.prototype.setProperties=goog.dom.setProperties;goog.dom.DomHelper.prototype.getViewportSize=function(a){return goog.dom.getViewportSize(a||this.getWindow())};\ngoog.dom.DomHelper.prototype.getDocumentHeight=function(){return goog.dom.getDocumentHeight_(this.getWindow())};goog.dom.DomHelper.prototype.createDom=function(a,b,c){return goog.dom.createDom_(this.document_,arguments)};goog.dom.DomHelper.prototype.createUntypedDom=function(a,b,c){return goog.dom.createDom_(this.document_,arguments)};goog.dom.DomHelper.prototype.$dom=goog.dom.DomHelper.prototype.createDom;goog.dom.DomHelper.prototype.createElement=function(a){return this.document_.createElement(String(a))};\ngoog.dom.DomHelper.prototype.createTextNode=function(a){return this.document_.createTextNode(String(a))};goog.dom.DomHelper.prototype.createTable=function(a,b,c){return goog.dom.createTable_(this.document_,a,b,!!c)};goog.dom.DomHelper.prototype.safeHtmlToNode=function(a){return goog.dom.safeHtmlToNode_(this.document_,a)};goog.dom.DomHelper.prototype.isCss1CompatMode=function(){return goog.dom.isCss1CompatMode_(this.document_)};goog.dom.DomHelper.prototype.getWindow=function(){return goog.dom.getWindow_(this.document_)};\ngoog.dom.DomHelper.prototype.getDocumentScrollElement=function(){return goog.dom.getDocumentScrollElement_(this.document_)};goog.dom.DomHelper.prototype.getDocumentScroll=function(){return goog.dom.getDocumentScroll_(this.document_)};goog.dom.DomHelper.prototype.getActiveElement=function(a){return goog.dom.getActiveElement(a||this.document_)};goog.dom.DomHelper.prototype.appendChild=goog.dom.appendChild;goog.dom.DomHelper.prototype.append=goog.dom.append;\ngoog.dom.DomHelper.prototype.canHaveChildren=goog.dom.canHaveChildren;goog.dom.DomHelper.prototype.removeChildren=goog.dom.removeChildren;goog.dom.DomHelper.prototype.insertSiblingBefore=goog.dom.insertSiblingBefore;goog.dom.DomHelper.prototype.insertSiblingAfter=goog.dom.insertSiblingAfter;goog.dom.DomHelper.prototype.insertChildAt=goog.dom.insertChildAt;goog.dom.DomHelper.prototype.removeNode=goog.dom.removeNode;goog.dom.DomHelper.prototype.replaceNode=goog.dom.replaceNode;\ngoog.dom.DomHelper.prototype.flattenElement=goog.dom.flattenElement;goog.dom.DomHelper.prototype.getChildren=goog.dom.getChildren;goog.dom.DomHelper.prototype.getFirstElementChild=goog.dom.getFirstElementChild;goog.dom.DomHelper.prototype.getLastElementChild=goog.dom.getLastElementChild;goog.dom.DomHelper.prototype.getNextElementSibling=goog.dom.getNextElementSibling;goog.dom.DomHelper.prototype.getPreviousElementSibling=goog.dom.getPreviousElementSibling;\ngoog.dom.DomHelper.prototype.getNextNode=goog.dom.getNextNode;goog.dom.DomHelper.prototype.getPreviousNode=goog.dom.getPreviousNode;goog.dom.DomHelper.prototype.isNodeLike=goog.dom.isNodeLike;goog.dom.DomHelper.prototype.isElement=goog.dom.isElement;goog.dom.DomHelper.prototype.isWindow=goog.dom.isWindow;goog.dom.DomHelper.prototype.getParentElement=goog.dom.getParentElement;goog.dom.DomHelper.prototype.contains=goog.dom.contains;goog.dom.DomHelper.prototype.compareNodeOrder=goog.dom.compareNodeOrder;\ngoog.dom.DomHelper.prototype.findCommonAncestor=goog.dom.findCommonAncestor;goog.dom.DomHelper.prototype.getOwnerDocument=goog.dom.getOwnerDocument;goog.dom.DomHelper.prototype.getFrameContentDocument=goog.dom.getFrameContentDocument;goog.dom.DomHelper.prototype.getFrameContentWindow=goog.dom.getFrameContentWindow;goog.dom.DomHelper.prototype.setTextContent=goog.dom.setTextContent;goog.dom.DomHelper.prototype.getOuterHtml=goog.dom.getOuterHtml;goog.dom.DomHelper.prototype.findNode=goog.dom.findNode;\ngoog.dom.DomHelper.prototype.findNodes=goog.dom.findNodes;goog.dom.DomHelper.prototype.isFocusableTabIndex=goog.dom.isFocusableTabIndex;goog.dom.DomHelper.prototype.setFocusableTabIndex=goog.dom.setFocusableTabIndex;goog.dom.DomHelper.prototype.isFocusable=goog.dom.isFocusable;goog.dom.DomHelper.prototype.getTextContent=goog.dom.getTextContent;goog.dom.DomHelper.prototype.getNodeTextLength=goog.dom.getNodeTextLength;goog.dom.DomHelper.prototype.getNodeTextOffset=goog.dom.getNodeTextOffset;\ngoog.dom.DomHelper.prototype.getNodeAtOffset=goog.dom.getNodeAtOffset;goog.dom.DomHelper.prototype.isNodeList=goog.dom.isNodeList;goog.dom.DomHelper.prototype.getAncestorByTagNameAndClass=goog.dom.getAncestorByTagNameAndClass;goog.dom.DomHelper.prototype.getAncestorByClass=goog.dom.getAncestorByClass;goog.dom.DomHelper.prototype.getAncestor=goog.dom.getAncestor;goog.dom.vendor={};goog.dom.vendor.getVendorJsPrefix=function(){return goog.userAgent.WEBKIT?\"Webkit\":goog.userAgent.GECKO?\"Moz\":goog.userAgent.IE?\"ms\":goog.userAgent.OPERA?\"O\":null};goog.dom.vendor.getVendorPrefix=function(){return goog.userAgent.WEBKIT?\"-webkit\":goog.userAgent.GECKO?\"-moz\":goog.userAgent.IE?\"-ms\":goog.userAgent.OPERA?\"-o\":null};\ngoog.dom.vendor.getPrefixedPropertyName=function(a,b){if(b&&a in b)return a;var c=goog.dom.vendor.getVendorJsPrefix();return c?(c=c.toLowerCase(),c+=goog.string.toTitleCase(a),!goog.isDef(b)||c in b?c:null):null};goog.dom.vendor.getPrefixedEventType=function(a){return((goog.dom.vendor.getVendorJsPrefix()||\"\")+a).toLowerCase()};goog.html.legacyconversions={};goog.html.legacyconversions.safeHtmlFromString=function(a){goog.html.legacyconversions.reportCallback_();return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(a,null)};goog.html.legacyconversions.safeStyleFromString=function(a){goog.html.legacyconversions.reportCallback_();return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(a)};\ngoog.html.legacyconversions.safeStyleSheetFromString=function(a){goog.html.legacyconversions.reportCallback_();return goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(a)};goog.html.legacyconversions.safeUrlFromString=function(a){goog.html.legacyconversions.reportCallback_();return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(a)};goog.html.legacyconversions.trustedResourceUrlFromString=function(a){goog.html.legacyconversions.reportCallback_();return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(a)};\ngoog.html.legacyconversions.reportCallback_=goog.nullFunction;goog.html.legacyconversions.setReportCallback=function(a){goog.html.legacyconversions.reportCallback_=a};goog.math.Box=function(a,b,c,d){this.top=a;this.right=b;this.bottom=c;this.left=d};goog.math.Box.boundingBox=function(a){for(var b=new goog.math.Box(arguments[0].y,arguments[0].x,arguments[0].y,arguments[0].x),c=1;c<arguments.length;c++)b.expandToIncludeCoordinate(arguments[c]);return b};goog.math.Box.prototype.getWidth=function(){return this.right-this.left};goog.math.Box.prototype.getHeight=function(){return this.bottom-this.top};\ngoog.math.Box.prototype.clone=function(){return new goog.math.Box(this.top,this.right,this.bottom,this.left)};goog.DEBUG&&(goog.math.Box.prototype.toString=function(){return\"(\"+this.top+\"t, \"+this.right+\"r, \"+this.bottom+\"b, \"+this.left+\"l)\"});goog.math.Box.prototype.contains=function(a){return goog.math.Box.contains(this,a)};\ngoog.math.Box.prototype.expand=function(a,b,c,d){goog.isObject(a)?(this.top-=a.top,this.right+=a.right,this.bottom+=a.bottom,this.left-=a.left):(this.top-=a,this.right+=Number(b),this.bottom+=Number(c),this.left-=Number(d));return this};goog.math.Box.prototype.expandToInclude=function(a){this.left=Math.min(this.left,a.left);this.top=Math.min(this.top,a.top);this.right=Math.max(this.right,a.right);this.bottom=Math.max(this.bottom,a.bottom)};\ngoog.math.Box.prototype.expandToIncludeCoordinate=function(a){this.top=Math.min(this.top,a.y);this.right=Math.max(this.right,a.x);this.bottom=Math.max(this.bottom,a.y);this.left=Math.min(this.left,a.x)};goog.math.Box.equals=function(a,b){return a==b?!0:a&&b?a.top==b.top&&a.right==b.right&&a.bottom==b.bottom&&a.left==b.left:!1};\ngoog.math.Box.contains=function(a,b){return a&&b?b instanceof goog.math.Box?b.left>=a.left&&b.right<=a.right&&b.top>=a.top&&b.bottom<=a.bottom:b.x>=a.left&&b.x<=a.right&&b.y>=a.top&&b.y<=a.bottom:!1};goog.math.Box.relativePositionX=function(a,b){return b.x<a.left?b.x-a.left:b.x>a.right?b.x-a.right:0};goog.math.Box.relativePositionY=function(a,b){return b.y<a.top?b.y-a.top:b.y>a.bottom?b.y-a.bottom:0};\ngoog.math.Box.distance=function(a,b){var c=goog.math.Box.relativePositionX(a,b),d=goog.math.Box.relativePositionY(a,b);return Math.sqrt(c*c+d*d)};goog.math.Box.intersects=function(a,b){return a.left<=b.right&&b.left<=a.right&&a.top<=b.bottom&&b.top<=a.bottom};goog.math.Box.intersectsWithPadding=function(a,b,c){return a.left<=b.right+c&&b.left<=a.right+c&&a.top<=b.bottom+c&&b.top<=a.bottom+c};\ngoog.math.Box.prototype.ceil=function(){this.top=Math.ceil(this.top);this.right=Math.ceil(this.right);this.bottom=Math.ceil(this.bottom);this.left=Math.ceil(this.left);return this};goog.math.Box.prototype.floor=function(){this.top=Math.floor(this.top);this.right=Math.floor(this.right);this.bottom=Math.floor(this.bottom);this.left=Math.floor(this.left);return this};\ngoog.math.Box.prototype.round=function(){this.top=Math.round(this.top);this.right=Math.round(this.right);this.bottom=Math.round(this.bottom);this.left=Math.round(this.left);return this};goog.math.Box.prototype.translate=function(a,b){a instanceof goog.math.Coordinate?(this.left+=a.x,this.right+=a.x,this.top+=a.y,this.bottom+=a.y):(goog.asserts.assertNumber(a),this.left+=a,this.right+=a,goog.isNumber(b)&&(this.top+=b,this.bottom+=b));return this};\ngoog.math.Box.prototype.scale=function(a,b){var c=goog.isNumber(b)?b:a;this.left*=a;this.right*=a;this.top*=c;this.bottom*=c;return this};goog.math.IRect=function(){};goog.math.Rect=function(a,b,c,d){this.left=a;this.top=b;this.width=c;this.height=d};goog.math.Rect.prototype.clone=function(){return new goog.math.Rect(this.left,this.top,this.width,this.height)};goog.math.Rect.prototype.toBox=function(){return new goog.math.Box(this.top,this.left+this.width,this.top+this.height,this.left)};goog.math.Rect.createFromPositionAndSize=function(a,b){return new goog.math.Rect(a.x,a.y,b.width,b.height)};\ngoog.math.Rect.createFromBox=function(a){return new goog.math.Rect(a.left,a.top,a.right-a.left,a.bottom-a.top)};goog.DEBUG&&(goog.math.Rect.prototype.toString=function(){return\"(\"+this.left+\", \"+this.top+\" - \"+this.width+\"w x \"+this.height+\"h)\"});goog.math.Rect.equals=function(a,b){return a==b?!0:a&&b?a.left==b.left&&a.width==b.width&&a.top==b.top&&a.height==b.height:!1};\ngoog.math.Rect.prototype.intersection=function(a){var b=Math.max(this.left,a.left),c=Math.min(this.left+this.width,a.left+a.width);if(b<=c){var d=Math.max(this.top,a.top);a=Math.min(this.top+this.height,a.top+a.height);if(d<=a)return this.left=b,this.top=d,this.width=c-b,this.height=a-d,!0}return!1};\ngoog.math.Rect.intersection=function(a,b){var c=Math.max(a.left,b.left),d=Math.min(a.left+a.width,b.left+b.width);if(c<=d){var e=Math.max(a.top,b.top),f=Math.min(a.top+a.height,b.top+b.height);if(e<=f)return new goog.math.Rect(c,e,d-c,f-e)}return null};goog.math.Rect.intersects=function(a,b){return a.left<=b.left+b.width&&b.left<=a.left+a.width&&a.top<=b.top+b.height&&b.top<=a.top+a.height};goog.math.Rect.prototype.intersects=function(a){return goog.math.Rect.intersects(this,a)};\ngoog.math.Rect.difference=function(a,b){var c=goog.math.Rect.intersection(a,b);if(!c||!c.height||!c.width)return[a.clone()];var c=[],d=a.top,e=a.height,f=a.left+a.width,g=a.top+a.height,h=b.left+b.width,k=b.top+b.height;b.top>a.top&&(c.push(new goog.math.Rect(a.left,a.top,a.width,b.top-a.top)),d=b.top,e-=b.top-a.top);k<g&&(c.push(new goog.math.Rect(a.left,k,a.width,g-k)),e=k-d);b.left>a.left&&c.push(new goog.math.Rect(a.left,d,b.left-a.left,e));h<f&&c.push(new goog.math.Rect(h,d,f-h,e));return c};\ngoog.math.Rect.prototype.difference=function(a){return goog.math.Rect.difference(this,a)};goog.math.Rect.prototype.boundingRect=function(a){var b=Math.max(this.left+this.width,a.left+a.width),c=Math.max(this.top+this.height,a.top+a.height);this.left=Math.min(this.left,a.left);this.top=Math.min(this.top,a.top);this.width=b-this.left;this.height=c-this.top};goog.math.Rect.boundingRect=function(a,b){if(!a||!b)return null;var c=new goog.math.Rect(a.left,a.top,a.width,a.height);c.boundingRect(b);return c};\ngoog.math.Rect.prototype.contains=function(a){return a instanceof goog.math.Coordinate?a.x>=this.left&&a.x<=this.left+this.width&&a.y>=this.top&&a.y<=this.top+this.height:this.left<=a.left&&this.left+this.width>=a.left+a.width&&this.top<=a.top&&this.top+this.height>=a.top+a.height};goog.math.Rect.prototype.squaredDistance=function(a){var b=a.x<this.left?this.left-a.x:Math.max(a.x-(this.left+this.width),0);a=a.y<this.top?this.top-a.y:Math.max(a.y-(this.top+this.height),0);return b*b+a*a};\ngoog.math.Rect.prototype.distance=function(a){return Math.sqrt(this.squaredDistance(a))};goog.math.Rect.prototype.getSize=function(){return new goog.math.Size(this.width,this.height)};goog.math.Rect.prototype.getTopLeft=function(){return new goog.math.Coordinate(this.left,this.top)};goog.math.Rect.prototype.getCenter=function(){return new goog.math.Coordinate(this.left+this.width/2,this.top+this.height/2)};\ngoog.math.Rect.prototype.getBottomRight=function(){return new goog.math.Coordinate(this.left+this.width,this.top+this.height)};goog.math.Rect.prototype.ceil=function(){this.left=Math.ceil(this.left);this.top=Math.ceil(this.top);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};goog.math.Rect.prototype.floor=function(){this.left=Math.floor(this.left);this.top=Math.floor(this.top);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};\ngoog.math.Rect.prototype.round=function(){this.left=Math.round(this.left);this.top=Math.round(this.top);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};goog.math.Rect.prototype.translate=function(a,b){a instanceof goog.math.Coordinate?(this.left+=a.x,this.top+=a.y):(this.left+=goog.asserts.assertNumber(a),goog.isNumber(b)&&(this.top+=b));return this};\ngoog.math.Rect.prototype.scale=function(a,b){var c=goog.isNumber(b)?b:a;this.left*=a;this.width*=a;this.top*=c;this.height*=c;return this};goog.style={};goog.style.setStyle=function(a,b,c){if(goog.isString(b))goog.style.setStyle_(a,c,b);else for(var d in b)goog.style.setStyle_(a,b[d],d)};goog.style.setStyle_=function(a,b,c){(c=goog.style.getVendorJsStyleName_(a,c))&&(a.style[c]=b)};goog.style.styleNameCache_={};\ngoog.style.getVendorJsStyleName_=function(a,b){var c=goog.style.styleNameCache_[b];if(!c){var d=goog.string.toCamelCase(b),c=d;void 0===a.style[d]&&(d=goog.dom.vendor.getVendorJsPrefix()+goog.string.toTitleCase(d),void 0!==a.style[d]&&(c=d));goog.style.styleNameCache_[b]=c}return c};\ngoog.style.getVendorStyleName_=function(a,b){var c=goog.string.toCamelCase(b);return void 0===a.style[c]&&(c=goog.dom.vendor.getVendorJsPrefix()+goog.string.toTitleCase(c),void 0!==a.style[c])?goog.dom.vendor.getVendorPrefix()+\"-\"+b:b};goog.style.getStyle=function(a,b){var c=a.style[goog.string.toCamelCase(b)];return\"undefined\"!==typeof c?c:a.style[goog.style.getVendorJsStyleName_(a,b)]||\"\"};\ngoog.style.getComputedStyle=function(a,b){var c=goog.dom.getOwnerDocument(a);return c.defaultView&&c.defaultView.getComputedStyle&&(c=c.defaultView.getComputedStyle(a,null))?c[b]||c.getPropertyValue(b)||\"\":\"\"};goog.style.getCascadedStyle=function(a,b){return a.currentStyle?a.currentStyle[b]:null};goog.style.getStyle_=function(a,b){return goog.style.getComputedStyle(a,b)||goog.style.getCascadedStyle(a,b)||a.style&&a.style[b]};\ngoog.style.getComputedBoxSizing=function(a){return goog.style.getStyle_(a,\"boxSizing\")||goog.style.getStyle_(a,\"MozBoxSizing\")||goog.style.getStyle_(a,\"WebkitBoxSizing\")||null};goog.style.getComputedPosition=function(a){return goog.style.getStyle_(a,\"position\")};goog.style.getBackgroundColor=function(a){return goog.style.getStyle_(a,\"backgroundColor\")};goog.style.getComputedOverflowX=function(a){return goog.style.getStyle_(a,\"overflowX\")};\ngoog.style.getComputedOverflowY=function(a){return goog.style.getStyle_(a,\"overflowY\")};goog.style.getComputedZIndex=function(a){return goog.style.getStyle_(a,\"zIndex\")};goog.style.getComputedTextAlign=function(a){return goog.style.getStyle_(a,\"textAlign\")};goog.style.getComputedCursor=function(a){return goog.style.getStyle_(a,\"cursor\")};goog.style.getComputedTransform=function(a){var b=goog.style.getVendorStyleName_(a,\"transform\");return goog.style.getStyle_(a,b)||goog.style.getStyle_(a,\"transform\")};\ngoog.style.setPosition=function(a,b,c){var d;b instanceof goog.math.Coordinate?(d=b.x,b=b.y):(d=b,b=c);a.style.left=goog.style.getPixelStyleValue_(d,!1);a.style.top=goog.style.getPixelStyleValue_(b,!1)};goog.style.getPosition=function(a){return new goog.math.Coordinate(a.offsetLeft,a.offsetTop)};\ngoog.style.getClientViewportElement=function(a){a=a?goog.dom.getOwnerDocument(a):goog.dom.getDocument();return!goog.userAgent.IE||goog.userAgent.isDocumentModeOrHigher(9)||goog.dom.getDomHelper(a).isCss1CompatMode()?a.documentElement:a.body};goog.style.getViewportPageOffset=function(a){var b=a.body;a=a.documentElement;return new goog.math.Coordinate(b.scrollLeft||a.scrollLeft,b.scrollTop||a.scrollTop)};\ngoog.style.getBoundingClientRect_=function(a){var b;try{b=a.getBoundingClientRect()}catch(c){return{left:0,top:0,right:0,bottom:0}}goog.userAgent.IE&&a.ownerDocument.body&&(a=a.ownerDocument,b.left-=a.documentElement.clientLeft+a.body.clientLeft,b.top-=a.documentElement.clientTop+a.body.clientTop);return b};\ngoog.style.getOffsetParent=function(a){if(goog.userAgent.IE&&!goog.userAgent.isDocumentModeOrHigher(8))return goog.asserts.assert(a&&\"offsetParent\"in a),a.offsetParent;var b=goog.dom.getOwnerDocument(a),c=goog.style.getStyle_(a,\"position\"),d=\"fixed\"==c||\"absolute\"==c;for(a=a.parentNode;a&&a!=b;a=a.parentNode)if(a.nodeType==goog.dom.NodeType.DOCUMENT_FRAGMENT&&a.host&&(a=a.host),c=goog.style.getStyle_(a,\"position\"),d=d&&\"static\"==c&&a!=b.documentElement&&a!=b.body,!d&&(a.scrollWidth>a.clientWidth||\na.scrollHeight>a.clientHeight||\"fixed\"==c||\"absolute\"==c||\"relative\"==c))return a;return null};\ngoog.style.getVisibleRectForElement=function(a){for(var b=new goog.math.Box(0,Infinity,Infinity,0),c=goog.dom.getDomHelper(a),d=c.getDocument().body,e=c.getDocument().documentElement,f=c.getDocumentScrollElement();a=goog.style.getOffsetParent(a);)if(!(goog.userAgent.IE&&0==a.clientWidth||goog.userAgent.WEBKIT&&0==a.clientHeight&&a==d)&&a!=d&&a!=e&&\"visible\"!=goog.style.getStyle_(a,\"overflow\")){var g=goog.style.getPageOffset(a),h=goog.style.getClientLeftTop(a);g.x+=h.x;g.y+=h.y;b.top=Math.max(b.top,\ng.y);b.right=Math.min(b.right,g.x+a.clientWidth);b.bottom=Math.min(b.bottom,g.y+a.clientHeight);b.left=Math.max(b.left,g.x)}d=f.scrollLeft;f=f.scrollTop;b.left=Math.max(b.left,d);b.top=Math.max(b.top,f);c=c.getViewportSize();b.right=Math.min(b.right,d+c.width);b.bottom=Math.min(b.bottom,f+c.height);return 0<=b.top&&0<=b.left&&b.bottom>b.top&&b.right>b.left?b:null};\ngoog.style.getContainerOffsetToScrollInto=function(a,b,c){var d=b||goog.dom.getDocumentScrollElement(),e=goog.style.getPageOffset(a),f=goog.style.getPageOffset(d),g=goog.style.getBorderBox(d);d==goog.dom.getDocumentScrollElement()?(b=e.x-d.scrollLeft,e=e.y-d.scrollTop,goog.userAgent.IE&&!goog.userAgent.isDocumentModeOrHigher(10)&&(b+=g.left,e+=g.top)):(b=e.x-f.x-g.left,e=e.y-f.y-g.top);g=goog.style.getSizeWithDisplay_(a);a=d.clientWidth-g.width;g=d.clientHeight-g.height;f=d.scrollLeft;d=d.scrollTop;\nc?(f+=b-a/2,d+=e-g/2):(f+=Math.min(b,Math.max(b-a,0)),d+=Math.min(e,Math.max(e-g,0)));return new goog.math.Coordinate(f,d)};goog.style.scrollIntoContainerView=function(a,b,c){b=b||goog.dom.getDocumentScrollElement();a=goog.style.getContainerOffsetToScrollInto(a,b,c);b.scrollLeft=a.x;b.scrollTop=a.y};goog.style.getClientLeftTop=function(a){return new goog.math.Coordinate(a.clientLeft,a.clientTop)};\ngoog.style.getPageOffset=function(a){var b=goog.dom.getOwnerDocument(a);goog.asserts.assertObject(a,\"Parameter is required\");var c=new goog.math.Coordinate(0,0),d=goog.style.getClientViewportElement(b);if(a==d)return c;a=goog.style.getBoundingClientRect_(a);b=goog.dom.getDomHelper(b).getDocumentScroll();c.x=a.left+b.x;c.y=a.top+b.y;return c};goog.style.getPageOffsetLeft=function(a){return goog.style.getPageOffset(a).x};goog.style.getPageOffsetTop=function(a){return goog.style.getPageOffset(a).y};\ngoog.style.getFramedPageOffset=function(a,b){var c=new goog.math.Coordinate(0,0),d=goog.dom.getWindow(goog.dom.getOwnerDocument(a));if(!goog.reflect.canAccessProperty(d,\"parent\"))return c;var e=a;do{var f=d==b?goog.style.getPageOffset(e):goog.style.getClientPositionForElement_(goog.asserts.assert(e));c.x+=f.x;c.y+=f.y}while(d&&d!=b&&d!=d.parent&&(e=d.frameElement)&&(d=d.parent));return c};\ngoog.style.translateRectForAnotherFrame=function(a,b,c){if(b.getDocument()!=c.getDocument()){var d=b.getDocument().body;c=goog.style.getFramedPageOffset(d,c.getWindow());c=goog.math.Coordinate.difference(c,goog.style.getPageOffset(d));!goog.userAgent.IE||goog.userAgent.isDocumentModeOrHigher(9)||b.isCss1CompatMode()||(c=goog.math.Coordinate.difference(c,b.getDocumentScroll()));a.left+=c.x;a.top+=c.y}};\ngoog.style.getRelativePosition=function(a,b){var c=goog.style.getClientPosition(a),d=goog.style.getClientPosition(b);return new goog.math.Coordinate(c.x-d.x,c.y-d.y)};goog.style.getClientPositionForElement_=function(a){a=goog.style.getBoundingClientRect_(a);return new goog.math.Coordinate(a.left,a.top)};\ngoog.style.getClientPosition=function(a){goog.asserts.assert(a);if(a.nodeType==goog.dom.NodeType.ELEMENT)return goog.style.getClientPositionForElement_(a);a=a.changedTouches?a.changedTouches[0]:a;return new goog.math.Coordinate(a.clientX,a.clientY)};goog.style.setPageOffset=function(a,b,c){var d=goog.style.getPageOffset(a);b instanceof goog.math.Coordinate&&(c=b.y,b=b.x);b=goog.asserts.assertNumber(b)-d.x;goog.style.setPosition(a,a.offsetLeft+b,a.offsetTop+(Number(c)-d.y))};\ngoog.style.setSize=function(a,b,c){if(b instanceof goog.math.Size)c=b.height,b=b.width;else if(void 0==c)throw Error(\"missing height argument\");goog.style.setWidth(a,b);goog.style.setHeight(a,c)};goog.style.getPixelStyleValue_=function(a,b){\"number\"==typeof a&&(a=(b?Math.round(a):a)+\"px\");return a};goog.style.setHeight=function(a,b){a.style.height=goog.style.getPixelStyleValue_(b,!0)};goog.style.setWidth=function(a,b){a.style.width=goog.style.getPixelStyleValue_(b,!0)};\ngoog.style.getSize=function(a){return goog.style.evaluateWithTemporaryDisplay_(goog.style.getSizeWithDisplay_,a)};goog.style.evaluateWithTemporaryDisplay_=function(a,b){if(\"none\"!=goog.style.getStyle_(b,\"display\"))return a(b);var c=b.style,d=c.display,e=c.visibility,f=c.position;c.visibility=\"hidden\";c.position=\"absolute\";c.display=\"inline\";var g=a(b);c.display=d;c.position=f;c.visibility=e;return g};\ngoog.style.getSizeWithDisplay_=function(a){var b=a.offsetWidth,c=a.offsetHeight,d=goog.userAgent.WEBKIT&&!b&&!c;return goog.isDef(b)&&!d||!a.getBoundingClientRect?new goog.math.Size(b,c):(a=goog.style.getBoundingClientRect_(a),new goog.math.Size(a.right-a.left,a.bottom-a.top))};goog.style.getTransformedSize=function(a){if(!a.getBoundingClientRect)return null;a=goog.style.evaluateWithTemporaryDisplay_(goog.style.getBoundingClientRect_,a);return new goog.math.Size(a.right-a.left,a.bottom-a.top)};\ngoog.style.getBounds=function(a){var b=goog.style.getPageOffset(a);a=goog.style.getSize(a);return new goog.math.Rect(b.x,b.y,a.width,a.height)};goog.style.toCamelCase=function(a){return goog.string.toCamelCase(String(a))};goog.style.toSelectorCase=function(a){return goog.string.toSelectorCase(a)};\ngoog.style.getOpacity=function(a){goog.asserts.assert(a);var b=a.style;a=\"\";\"opacity\"in b?a=b.opacity:\"MozOpacity\"in b?a=b.MozOpacity:\"filter\"in b&&(b=b.filter.match(/alpha\\(opacity=([\\d.]+)\\)/))&&(a=String(b[1]/100));return\"\"==a?a:Number(a)};goog.style.setOpacity=function(a,b){goog.asserts.assert(a);var c=a.style;\"opacity\"in c?c.opacity=b:\"MozOpacity\"in c?c.MozOpacity=b:\"filter\"in c&&(c.filter=\"\"===b?\"\":\"alpha(opacity=\"+100*Number(b)+\")\")};\ngoog.style.setTransparentBackgroundImage=function(a,b){var c=a.style;goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"8\")?c.filter='progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\"'+b+'\", sizingMethod=\"crop\")':(c.backgroundImage=\"url(\"+b+\")\",c.backgroundPosition=\"top left\",c.backgroundRepeat=\"no-repeat\")};goog.style.clearTransparentBackgroundImage=function(a){a=a.style;\"filter\"in a?a.filter=\"\":a.backgroundImage=\"none\"};\ngoog.style.showElement=function(a,b){goog.style.setElementShown(a,b)};goog.style.setElementShown=function(a,b){a.style.display=b?\"\":\"none\"};goog.style.isElementShown=function(a){return\"none\"!=a.style.display};goog.style.installStyles=function(a,b){return goog.style.installSafeStyleSheet(goog.html.legacyconversions.safeStyleSheetFromString(a),b)};\ngoog.style.installSafeStyleSheet=function(a,b){var c=goog.dom.getDomHelper(b),d,e=c.getDocument();goog.userAgent.IE&&e.createStyleSheet?(d=e.createStyleSheet(),goog.style.setSafeStyleSheet(d,a)):(e=c.getElementsByTagNameAndClass(\"HEAD\")[0],e||(d=c.getElementsByTagNameAndClass(\"BODY\")[0],e=c.createDom(\"HEAD\"),d.parentNode.insertBefore(e,d)),d=c.createDom(\"STYLE\"),goog.style.setSafeStyleSheet(d,a),c.appendChild(e,d));return d};\ngoog.style.uninstallStyles=function(a){goog.dom.removeNode(a.ownerNode||a.owningElement||a)};goog.style.setStyles=function(a,b){goog.style.setSafeStyleSheet(a,goog.html.legacyconversions.safeStyleSheetFromString(b))};goog.style.setSafeStyleSheet=function(a,b){var c=goog.html.SafeStyleSheet.unwrap(b);goog.userAgent.IE&&goog.isDef(a.cssText)?a.cssText=c:a.innerHTML=c};\ngoog.style.setPreWrap=function(a){a=a.style;goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"8\")?(a.whiteSpace=\"pre\",a.wordWrap=\"break-word\"):a.whiteSpace=goog.userAgent.GECKO?\"-moz-pre-wrap\":\"pre-wrap\"};goog.style.setInlineBlock=function(a){a=a.style;a.position=\"relative\";goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"8\")?(a.zoom=\"1\",a.display=\"inline\"):a.display=\"inline-block\"};goog.style.isRightToLeft=function(a){return\"rtl\"==goog.style.getStyle_(a,\"direction\")};\ngoog.style.unselectableStyle_=goog.userAgent.GECKO?\"MozUserSelect\":goog.userAgent.WEBKIT||goog.userAgent.EDGE?\"WebkitUserSelect\":null;goog.style.isUnselectable=function(a){return goog.style.unselectableStyle_?\"none\"==a.style[goog.style.unselectableStyle_].toLowerCase():goog.userAgent.IE||goog.userAgent.OPERA?\"on\"==a.getAttribute(\"unselectable\"):!1};\ngoog.style.setUnselectable=function(a,b,c){c=c?null:a.getElementsByTagName(\"*\");var d=goog.style.unselectableStyle_;if(d){if(b=b?\"none\":\"\",a.style&&(a.style[d]=b),c){a=0;for(var e;e=c[a];a++)e.style&&(e.style[d]=b)}}else if(goog.userAgent.IE||goog.userAgent.OPERA)if(b=b?\"on\":\"\",a.setAttribute(\"unselectable\",b),c)for(a=0;e=c[a];a++)e.setAttribute(\"unselectable\",b)};goog.style.getBorderBoxSize=function(a){return new goog.math.Size(a.offsetWidth,a.offsetHeight)};\ngoog.style.setBorderBoxSize=function(a,b){var c=goog.dom.getOwnerDocument(a),d=goog.dom.getDomHelper(c).isCss1CompatMode();if(!goog.userAgent.IE||goog.userAgent.isVersionOrHigher(\"10\")||d&&goog.userAgent.isVersionOrHigher(\"8\"))goog.style.setBoxSizingSize_(a,b,\"border-box\");else if(c=a.style,d){var d=goog.style.getPaddingBox(a),e=goog.style.getBorderBox(a);c.pixelWidth=b.width-e.left-d.left-d.right-e.right;c.pixelHeight=b.height-e.top-d.top-d.bottom-e.bottom}else c.pixelWidth=b.width,c.pixelHeight=\nb.height};\ngoog.style.getContentBoxSize=function(a){var b=goog.dom.getOwnerDocument(a),c=goog.userAgent.IE&&a.currentStyle;if(c&&goog.dom.getDomHelper(b).isCss1CompatMode()&&\"auto\"!=c.width&&\"auto\"!=c.height&&!c.boxSizing)return b=goog.style.getIePixelValue_(a,c.width,\"width\",\"pixelWidth\"),a=goog.style.getIePixelValue_(a,c.height,\"height\",\"pixelHeight\"),new goog.math.Size(b,a);c=goog.style.getBorderBoxSize(a);b=goog.style.getPaddingBox(a);a=goog.style.getBorderBox(a);return new goog.math.Size(c.width-a.left-\nb.left-b.right-a.right,c.height-a.top-b.top-b.bottom-a.bottom)};\ngoog.style.setContentBoxSize=function(a,b){var c=goog.dom.getOwnerDocument(a),d=goog.dom.getDomHelper(c).isCss1CompatMode();if(!goog.userAgent.IE||goog.userAgent.isVersionOrHigher(\"10\")||d&&goog.userAgent.isVersionOrHigher(\"8\"))goog.style.setBoxSizingSize_(a,b,\"content-box\");else if(c=a.style,d)c.pixelWidth=b.width,c.pixelHeight=b.height;else{var d=goog.style.getPaddingBox(a),e=goog.style.getBorderBox(a);c.pixelWidth=b.width+e.left+d.left+d.right+e.right;c.pixelHeight=b.height+e.top+d.top+d.bottom+\ne.bottom}};goog.style.setBoxSizingSize_=function(a,b,c){a=a.style;goog.userAgent.GECKO?a.MozBoxSizing=c:goog.userAgent.WEBKIT?a.WebkitBoxSizing=c:a.boxSizing=c;a.width=Math.max(b.width,0)+\"px\";a.height=Math.max(b.height,0)+\"px\"};goog.style.getIePixelValue_=function(a,b,c,d){if(/^\\d+px?$/.test(b))return parseInt(b,10);var e=a.style[c],f=a.runtimeStyle[c];a.runtimeStyle[c]=a.currentStyle[c];a.style[c]=b;b=a.style[d];a.style[c]=e;a.runtimeStyle[c]=f;return b};\ngoog.style.getIePixelDistance_=function(a,b){var c=goog.style.getCascadedStyle(a,b);return c?goog.style.getIePixelValue_(a,c,\"left\",\"pixelLeft\"):0};\ngoog.style.getBox_=function(a,b){if(goog.userAgent.IE){var c=goog.style.getIePixelDistance_(a,b+\"Left\"),d=goog.style.getIePixelDistance_(a,b+\"Right\"),e=goog.style.getIePixelDistance_(a,b+\"Top\"),f=goog.style.getIePixelDistance_(a,b+\"Bottom\");return new goog.math.Box(e,d,f,c)}c=goog.style.getComputedStyle(a,b+\"Left\");d=goog.style.getComputedStyle(a,b+\"Right\");e=goog.style.getComputedStyle(a,b+\"Top\");f=goog.style.getComputedStyle(a,b+\"Bottom\");return new goog.math.Box(parseFloat(e),parseFloat(d),parseFloat(f),\nparseFloat(c))};goog.style.getPaddingBox=function(a){return goog.style.getBox_(a,\"padding\")};goog.style.getMarginBox=function(a){return goog.style.getBox_(a,\"margin\")};goog.style.ieBorderWidthKeywords_={thin:2,medium:4,thick:6};\ngoog.style.getIePixelBorder_=function(a,b){if(\"none\"==goog.style.getCascadedStyle(a,b+\"Style\"))return 0;var c=goog.style.getCascadedStyle(a,b+\"Width\");return c in goog.style.ieBorderWidthKeywords_?goog.style.ieBorderWidthKeywords_[c]:goog.style.getIePixelValue_(a,c,\"left\",\"pixelLeft\")};\ngoog.style.getBorderBox=function(a){if(goog.userAgent.IE&&!goog.userAgent.isDocumentModeOrHigher(9)){var b=goog.style.getIePixelBorder_(a,\"borderLeft\"),c=goog.style.getIePixelBorder_(a,\"borderRight\"),d=goog.style.getIePixelBorder_(a,\"borderTop\");a=goog.style.getIePixelBorder_(a,\"borderBottom\");return new goog.math.Box(d,c,a,b)}b=goog.style.getComputedStyle(a,\"borderLeftWidth\");c=goog.style.getComputedStyle(a,\"borderRightWidth\");d=goog.style.getComputedStyle(a,\"borderTopWidth\");a=goog.style.getComputedStyle(a,\n\"borderBottomWidth\");return new goog.math.Box(parseFloat(d),parseFloat(c),parseFloat(a),parseFloat(b))};goog.style.getFontFamily=function(a){var b=goog.dom.getOwnerDocument(a),c=\"\";if(b.body.createTextRange&&goog.dom.contains(b,a)){b=b.body.createTextRange();b.moveToElementText(a);try{c=b.queryCommandValue(\"FontName\")}catch(d){c=\"\"}}c||(c=goog.style.getStyle_(a,\"fontFamily\"));a=c.split(\",\");1<a.length&&(c=a[0]);return goog.string.stripQuotes(c,\"\\\"'\")};goog.style.lengthUnitRegex_=/[^\\d]+$/;\ngoog.style.getLengthUnits=function(a){return(a=a.match(goog.style.lengthUnitRegex_))&&a[0]||null};goog.style.ABSOLUTE_CSS_LENGTH_UNITS_={cm:1,\"in\":1,mm:1,pc:1,pt:1};goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_={em:1,ex:1};\ngoog.style.getFontSize=function(a){var b=goog.style.getStyle_(a,\"fontSize\"),c=goog.style.getLengthUnits(b);if(b&&\"px\"==c)return parseInt(b,10);if(goog.userAgent.IE){if(String(c)in goog.style.ABSOLUTE_CSS_LENGTH_UNITS_)return goog.style.getIePixelValue_(a,b,\"left\",\"pixelLeft\");if(a.parentNode&&a.parentNode.nodeType==goog.dom.NodeType.ELEMENT&&String(c)in goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_)return a=a.parentNode,c=goog.style.getStyle_(a,\"fontSize\"),goog.style.getIePixelValue_(a,b==c?\"1em\":b,\n\"left\",\"pixelLeft\")}c=goog.dom.createDom(\"SPAN\",{style:\"visibility:hidden;position:absolute;line-height:0;padding:0;margin:0;border:0;height:1em;\"});goog.dom.appendChild(a,c);b=c.offsetHeight;goog.dom.removeNode(c);return b};goog.style.parseStyleAttribute=function(a){var b={};goog.array.forEach(a.split(/\\s*;\\s*/),function(a){var d=a.match(/\\s*([\\w-]+)\\s*\\:(.+)/);d&&(a=d[1],d=goog.string.trim(d[2]),b[goog.string.toCamelCase(a.toLowerCase())]=d)});return b};\ngoog.style.toStyleAttribute=function(a){var b=[];goog.object.forEach(a,function(a,d){b.push(goog.string.toSelectorCase(d),\":\",a,\";\")});return b.join(\"\")};goog.style.setFloat=function(a,b){a.style[goog.userAgent.IE?\"styleFloat\":\"cssFloat\"]=b};goog.style.getFloat=function(a){return a.style[goog.userAgent.IE?\"styleFloat\":\"cssFloat\"]||\"\"};\ngoog.style.getScrollbarWidth=function(a){var b=goog.dom.createElement(\"DIV\");a&&(b.className=a);b.style.cssText=\"overflow:auto;position:absolute;top:0;width:100px;height:100px\";a=goog.dom.createElement(\"DIV\");goog.style.setSize(a,\"200px\",\"200px\");b.appendChild(a);goog.dom.appendChild(goog.dom.getDocument().body,b);a=b.offsetWidth-b.clientWidth;goog.dom.removeNode(b);return a};goog.style.MATRIX_TRANSLATION_REGEX_=/matrix\\([0-9\\.\\-]+, [0-9\\.\\-]+, [0-9\\.\\-]+, [0-9\\.\\-]+, ([0-9\\.\\-]+)p?x?, ([0-9\\.\\-]+)p?x?\\)/;\ngoog.style.getCssTranslation=function(a){a=goog.style.getComputedTransform(a);return a?(a=a.match(goog.style.MATRIX_TRANSLATION_REGEX_))?new goog.math.Coordinate(parseFloat(a[1]),parseFloat(a[2])):new goog.math.Coordinate(0,0):new goog.math.Coordinate(0,0)};goog.events.KeyCodes={WIN_KEY_FF_LINUX:0,MAC_ENTER:3,BACKSPACE:8,TAB:9,NUM_CENTER:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,PAUSE:19,CAPS_LOCK:20,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,PLUS_SIGN:43,PRINT_SCREEN:44,INSERT:45,DELETE:46,ZERO:48,ONE:49,TWO:50,THREE:51,FOUR:52,FIVE:53,SIX:54,SEVEN:55,EIGHT:56,NINE:57,FF_SEMICOLON:59,FF_EQUALS:61,FF_DASH:173,QUESTION_MARK:63,AT_SIGN:64,A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,\nQ:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,META:91,WIN_KEY_RIGHT:92,CONTEXT_MENU:93,NUM_ZERO:96,NUM_ONE:97,NUM_TWO:98,NUM_THREE:99,NUM_FOUR:100,NUM_FIVE:101,NUM_SIX:102,NUM_SEVEN:103,NUM_EIGHT:104,NUM_NINE:105,NUM_MULTIPLY:106,NUM_PLUS:107,NUM_MINUS:109,NUM_PERIOD:110,NUM_DIVISION:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,NUMLOCK:144,SCROLL_LOCK:145,FIRST_MEDIA_KEY:166,LAST_MEDIA_KEY:183,SEMICOLON:186,DASH:189,EQUALS:187,COMMA:188,PERIOD:190,\nSLASH:191,APOSTROPHE:192,TILDE:192,SINGLE_QUOTE:222,OPEN_SQUARE_BRACKET:219,BACKSLASH:220,CLOSE_SQUARE_BRACKET:221,WIN_KEY:224,MAC_FF_META:224,MAC_WK_CMD_LEFT:91,MAC_WK_CMD_RIGHT:93,WIN_IME:229,VK_NONAME:252,PHANTOM:255};\ngoog.events.KeyCodes.isTextModifyingKeyEvent=function(a){if(a.altKey&&!a.ctrlKey||a.metaKey||a.keyCode>=goog.events.KeyCodes.F1&&a.keyCode<=goog.events.KeyCodes.F12)return!1;switch(a.keyCode){case goog.events.KeyCodes.ALT:case goog.events.KeyCodes.CAPS_LOCK:case goog.events.KeyCodes.CONTEXT_MENU:case goog.events.KeyCodes.CTRL:case goog.events.KeyCodes.DOWN:case goog.events.KeyCodes.END:case goog.events.KeyCodes.ESC:case goog.events.KeyCodes.HOME:case goog.events.KeyCodes.INSERT:case goog.events.KeyCodes.LEFT:case goog.events.KeyCodes.MAC_FF_META:case goog.events.KeyCodes.META:case goog.events.KeyCodes.NUMLOCK:case goog.events.KeyCodes.NUM_CENTER:case goog.events.KeyCodes.PAGE_DOWN:case goog.events.KeyCodes.PAGE_UP:case goog.events.KeyCodes.PAUSE:case goog.events.KeyCodes.PHANTOM:case goog.events.KeyCodes.PRINT_SCREEN:case goog.events.KeyCodes.RIGHT:case goog.events.KeyCodes.SCROLL_LOCK:case goog.events.KeyCodes.SHIFT:case goog.events.KeyCodes.UP:case goog.events.KeyCodes.VK_NONAME:case goog.events.KeyCodes.WIN_KEY:case goog.events.KeyCodes.WIN_KEY_RIGHT:return!1;case goog.events.KeyCodes.WIN_KEY_FF_LINUX:return!goog.userAgent.GECKO;\ndefault:return a.keyCode<goog.events.KeyCodes.FIRST_MEDIA_KEY||a.keyCode>goog.events.KeyCodes.LAST_MEDIA_KEY}};\ngoog.events.KeyCodes.firesKeyPressEvent=function(a,b,c,d,e){if(!(goog.userAgent.IE||goog.userAgent.EDGE||goog.userAgent.WEBKIT&&goog.userAgent.isVersionOrHigher(\"525\")))return!0;if(goog.userAgent.MAC&&e)return goog.events.KeyCodes.isCharacterKey(a);if(e&&!d)return!1;goog.isNumber(b)&&(b=goog.events.KeyCodes.normalizeKeyCode(b));if(!c&&(b==goog.events.KeyCodes.CTRL||b==goog.events.KeyCodes.ALT||goog.userAgent.MAC&&b==goog.events.KeyCodes.META))return!1;if((goog.userAgent.WEBKIT||goog.userAgent.EDGE)&&\nd&&c)switch(a){case goog.events.KeyCodes.BACKSLASH:case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:case goog.events.KeyCodes.TILDE:case goog.events.KeyCodes.SEMICOLON:case goog.events.KeyCodes.DASH:case goog.events.KeyCodes.EQUALS:case goog.events.KeyCodes.COMMA:case goog.events.KeyCodes.PERIOD:case goog.events.KeyCodes.SLASH:case goog.events.KeyCodes.APOSTROPHE:case goog.events.KeyCodes.SINGLE_QUOTE:return!1}if(goog.userAgent.IE&&d&&b==a)return!1;switch(a){case goog.events.KeyCodes.ENTER:return!0;\ncase goog.events.KeyCodes.ESC:return!(goog.userAgent.WEBKIT||goog.userAgent.EDGE)}return goog.events.KeyCodes.isCharacterKey(a)};\ngoog.events.KeyCodes.isCharacterKey=function(a){if(a>=goog.events.KeyCodes.ZERO&&a<=goog.events.KeyCodes.NINE||a>=goog.events.KeyCodes.NUM_ZERO&&a<=goog.events.KeyCodes.NUM_MULTIPLY||a>=goog.events.KeyCodes.A&&a<=goog.events.KeyCodes.Z||(goog.userAgent.WEBKIT||goog.userAgent.EDGE)&&0==a)return!0;switch(a){case goog.events.KeyCodes.SPACE:case goog.events.KeyCodes.PLUS_SIGN:case goog.events.KeyCodes.QUESTION_MARK:case goog.events.KeyCodes.AT_SIGN:case goog.events.KeyCodes.NUM_PLUS:case goog.events.KeyCodes.NUM_MINUS:case goog.events.KeyCodes.NUM_PERIOD:case goog.events.KeyCodes.NUM_DIVISION:case goog.events.KeyCodes.SEMICOLON:case goog.events.KeyCodes.FF_SEMICOLON:case goog.events.KeyCodes.DASH:case goog.events.KeyCodes.EQUALS:case goog.events.KeyCodes.FF_EQUALS:case goog.events.KeyCodes.COMMA:case goog.events.KeyCodes.PERIOD:case goog.events.KeyCodes.SLASH:case goog.events.KeyCodes.APOSTROPHE:case goog.events.KeyCodes.SINGLE_QUOTE:case goog.events.KeyCodes.OPEN_SQUARE_BRACKET:case goog.events.KeyCodes.BACKSLASH:case goog.events.KeyCodes.CLOSE_SQUARE_BRACKET:return!0;default:return!1}};\ngoog.events.KeyCodes.normalizeKeyCode=function(a){return goog.userAgent.GECKO?goog.events.KeyCodes.normalizeGeckoKeyCode(a):goog.userAgent.MAC&&goog.userAgent.WEBKIT?goog.events.KeyCodes.normalizeMacWebKitKeyCode(a):a};\ngoog.events.KeyCodes.normalizeGeckoKeyCode=function(a){switch(a){case goog.events.KeyCodes.FF_EQUALS:return goog.events.KeyCodes.EQUALS;case goog.events.KeyCodes.FF_SEMICOLON:return goog.events.KeyCodes.SEMICOLON;case goog.events.KeyCodes.FF_DASH:return goog.events.KeyCodes.DASH;case goog.events.KeyCodes.MAC_FF_META:return goog.events.KeyCodes.META;case goog.events.KeyCodes.WIN_KEY_FF_LINUX:return goog.events.KeyCodes.WIN_KEY;default:return a}};\ngoog.events.KeyCodes.normalizeMacWebKitKeyCode=function(a){switch(a){case goog.events.KeyCodes.MAC_WK_CMD_RIGHT:return goog.events.KeyCodes.META;default:return a}};goog.events.EventHandler=function(a){goog.Disposable.call(this);this.handler_=a;this.keys_={}};goog.inherits(goog.events.EventHandler,goog.Disposable);goog.events.EventHandler.typeArray_=[];goog.events.EventHandler.prototype.listen=function(a,b,c,d){return this.listen_(a,b,c,d)};goog.events.EventHandler.prototype.listenWithScope=function(a,b,c,d,e){return this.listen_(a,b,c,d,e)};\ngoog.events.EventHandler.prototype.listen_=function(a,b,c,d,e){goog.isArray(b)||(b&&(goog.events.EventHandler.typeArray_[0]=b.toString()),b=goog.events.EventHandler.typeArray_);for(var f=0;f<b.length;f++){var g=goog.events.listen(a,b[f],c||this.handleEvent,d||!1,e||this.handler_||this);if(!g)break;this.keys_[g.key]=g}return this};goog.events.EventHandler.prototype.listenOnce=function(a,b,c,d){return this.listenOnce_(a,b,c,d)};\ngoog.events.EventHandler.prototype.listenOnceWithScope=function(a,b,c,d,e){return this.listenOnce_(a,b,c,d,e)};goog.events.EventHandler.prototype.listenOnce_=function(a,b,c,d,e){if(goog.isArray(b))for(var f=0;f<b.length;f++)this.listenOnce_(a,b[f],c,d,e);else{a=goog.events.listenOnce(a,b,c||this.handleEvent,d,e||this.handler_||this);if(!a)return this;this.keys_[a.key]=a}return this};goog.events.EventHandler.prototype.listenWithWrapper=function(a,b,c,d){return this.listenWithWrapper_(a,b,c,d)};\ngoog.events.EventHandler.prototype.listenWithWrapperAndScope=function(a,b,c,d,e){return this.listenWithWrapper_(a,b,c,d,e)};goog.events.EventHandler.prototype.listenWithWrapper_=function(a,b,c,d,e){b.listen(a,c,d,e||this.handler_||this,this);return this};goog.events.EventHandler.prototype.getListenerCount=function(){var a=0,b;for(b in this.keys_)Object.prototype.hasOwnProperty.call(this.keys_,b)&&a++;return a};\ngoog.events.EventHandler.prototype.unlisten=function(a,b,c,d,e){if(goog.isArray(b))for(var f=0;f<b.length;f++)this.unlisten(a,b[f],c,d,e);else if(a=goog.events.getListener(a,b,c||this.handleEvent,d,e||this.handler_||this))goog.events.unlistenByKey(a),delete this.keys_[a.key];return this};goog.events.EventHandler.prototype.unlistenWithWrapper=function(a,b,c,d,e){b.unlisten(a,c,d,e||this.handler_||this,this);return this};\ngoog.events.EventHandler.prototype.removeAll=function(){goog.object.forEach(this.keys_,function(a,b){this.keys_.hasOwnProperty(b)&&goog.events.unlistenByKey(a)},this);this.keys_={}};goog.events.EventHandler.prototype.disposeInternal=function(){goog.events.EventHandler.superClass_.disposeInternal.call(this);this.removeAll()};goog.events.EventHandler.prototype.handleEvent=function(a){throw Error(\"EventHandler.handleEvent not implemented\");};goog.ui={};goog.ui.IdGenerator=function(){};goog.addSingletonGetter(goog.ui.IdGenerator);goog.ui.IdGenerator.prototype.nextId_=0;goog.ui.IdGenerator.prototype.getNextUniqueId=function(){return\":\"+(this.nextId_++).toString(36)};goog.ui.Component=function(a){goog.events.EventTarget.call(this);this.dom_=a||goog.dom.getDomHelper();this.rightToLeft_=goog.ui.Component.defaultRightToLeft_;this.id_=null;this.inDocument_=!1;this.element_=null;this.googUiComponentHandler_=void 0;this.childIndex_=this.children_=this.parent_=this.model_=null;this.wasDecorated_=!1};goog.inherits(goog.ui.Component,goog.events.EventTarget);goog.ui.Component.ALLOW_DETACHED_DECORATION=!1;goog.ui.Component.prototype.idGenerator_=goog.ui.IdGenerator.getInstance();\ngoog.ui.Component.DEFAULT_BIDI_DIR=0;goog.ui.Component.defaultRightToLeft_=1==goog.ui.Component.DEFAULT_BIDI_DIR?!1:-1==goog.ui.Component.DEFAULT_BIDI_DIR?!0:null;\ngoog.ui.Component.EventType={BEFORE_SHOW:\"beforeshow\",SHOW:\"show\",HIDE:\"hide\",DISABLE:\"disable\",ENABLE:\"enable\",HIGHLIGHT:\"highlight\",UNHIGHLIGHT:\"unhighlight\",ACTIVATE:\"activate\",DEACTIVATE:\"deactivate\",SELECT:\"select\",UNSELECT:\"unselect\",CHECK:\"check\",UNCHECK:\"uncheck\",FOCUS:\"focus\",BLUR:\"blur\",OPEN:\"open\",CLOSE:\"close\",ENTER:\"enter\",LEAVE:\"leave\",ACTION:\"action\",CHANGE:\"change\"};\ngoog.ui.Component.Error={NOT_SUPPORTED:\"Method not supported\",DECORATE_INVALID:\"Invalid element to decorate\",ALREADY_RENDERED:\"Component already rendered\",PARENT_UNABLE_TO_BE_SET:\"Unable to set parent component\",CHILD_INDEX_OUT_OF_BOUNDS:\"Child component index out of bounds\",NOT_OUR_CHILD:\"Child is not in parent component\",NOT_IN_DOCUMENT:\"Operation not supported while component is not in document\",STATE_INVALID:\"Invalid component state\"};\ngoog.ui.Component.State={ALL:255,DISABLED:1,HOVER:2,ACTIVE:4,SELECTED:8,CHECKED:16,FOCUSED:32,OPENED:64};\ngoog.ui.Component.getStateTransitionEvent=function(a,b){switch(a){case goog.ui.Component.State.DISABLED:return b?goog.ui.Component.EventType.DISABLE:goog.ui.Component.EventType.ENABLE;case goog.ui.Component.State.HOVER:return b?goog.ui.Component.EventType.HIGHLIGHT:goog.ui.Component.EventType.UNHIGHLIGHT;case goog.ui.Component.State.ACTIVE:return b?goog.ui.Component.EventType.ACTIVATE:goog.ui.Component.EventType.DEACTIVATE;case goog.ui.Component.State.SELECTED:return b?goog.ui.Component.EventType.SELECT:\ngoog.ui.Component.EventType.UNSELECT;case goog.ui.Component.State.CHECKED:return b?goog.ui.Component.EventType.CHECK:goog.ui.Component.EventType.UNCHECK;case goog.ui.Component.State.FOCUSED:return b?goog.ui.Component.EventType.FOCUS:goog.ui.Component.EventType.BLUR;case goog.ui.Component.State.OPENED:return b?goog.ui.Component.EventType.OPEN:goog.ui.Component.EventType.CLOSE}throw Error(goog.ui.Component.Error.STATE_INVALID);};\ngoog.ui.Component.setDefaultRightToLeft=function(a){goog.ui.Component.defaultRightToLeft_=a};goog.ui.Component.prototype.getId=function(){return this.id_||(this.id_=this.idGenerator_.getNextUniqueId())};goog.ui.Component.prototype.setId=function(a){this.parent_&&this.parent_.childIndex_&&(goog.object.remove(this.parent_.childIndex_,this.id_),goog.object.add(this.parent_.childIndex_,a,this));this.id_=a};goog.ui.Component.prototype.getElement=function(){return this.element_};\ngoog.ui.Component.prototype.getElementStrict=function(){var a=this.element_;goog.asserts.assert(a,\"Can not call getElementStrict before rendering/decorating.\");return a};goog.ui.Component.prototype.setElementInternal=function(a){this.element_=a};goog.ui.Component.prototype.getElementsByClass=function(a){return this.element_?this.dom_.getElementsByClass(a,this.element_):[]};goog.ui.Component.prototype.getElementByClass=function(a){return this.element_?this.dom_.getElementByClass(a,this.element_):null};\ngoog.ui.Component.prototype.getRequiredElementByClass=function(a){var b=this.getElementByClass(a);goog.asserts.assert(b,\"Expected element in component with class: %s\",a);return b};goog.ui.Component.prototype.getHandler=function(){this.googUiComponentHandler_||(this.googUiComponentHandler_=new goog.events.EventHandler(this));return this.googUiComponentHandler_};\ngoog.ui.Component.prototype.setParent=function(a){if(this==a)throw Error(goog.ui.Component.Error.PARENT_UNABLE_TO_BE_SET);if(a&&this.parent_&&this.id_&&this.parent_.getChild(this.id_)&&this.parent_!=a)throw Error(goog.ui.Component.Error.PARENT_UNABLE_TO_BE_SET);this.parent_=a;goog.ui.Component.superClass_.setParentEventTarget.call(this,a)};goog.ui.Component.prototype.getParent=function(){return this.parent_};\ngoog.ui.Component.prototype.setParentEventTarget=function(a){if(this.parent_&&this.parent_!=a)throw Error(goog.ui.Component.Error.NOT_SUPPORTED);goog.ui.Component.superClass_.setParentEventTarget.call(this,a)};goog.ui.Component.prototype.getDomHelper=function(){return this.dom_};goog.ui.Component.prototype.isInDocument=function(){return this.inDocument_};goog.ui.Component.prototype.createDom=function(){this.element_=this.dom_.createElement(\"DIV\")};goog.ui.Component.prototype.render=function(a){this.render_(a)};\ngoog.ui.Component.prototype.renderBefore=function(a){this.render_(a.parentNode,a)};goog.ui.Component.prototype.render_=function(a,b){if(this.inDocument_)throw Error(goog.ui.Component.Error.ALREADY_RENDERED);this.element_||this.createDom();a?a.insertBefore(this.element_,b||null):this.dom_.getDocument().body.appendChild(this.element_);this.parent_&&!this.parent_.isInDocument()||this.enterDocument()};\ngoog.ui.Component.prototype.decorate=function(a){if(this.inDocument_)throw Error(goog.ui.Component.Error.ALREADY_RENDERED);if(a&&this.canDecorate(a)){this.wasDecorated_=!0;var b=goog.dom.getOwnerDocument(a);this.dom_&&this.dom_.getDocument()==b||(this.dom_=goog.dom.getDomHelper(a));this.decorateInternal(a);goog.ui.Component.ALLOW_DETACHED_DECORATION&&!goog.dom.contains(b,a)||this.enterDocument()}else throw Error(goog.ui.Component.Error.DECORATE_INVALID);};goog.ui.Component.prototype.canDecorate=function(a){return!0};\ngoog.ui.Component.prototype.wasDecorated=function(){return this.wasDecorated_};goog.ui.Component.prototype.decorateInternal=function(a){this.element_=a};goog.ui.Component.prototype.enterDocument=function(){this.inDocument_=!0;this.forEachChild(function(a){!a.isInDocument()&&a.getElement()&&a.enterDocument()})};\ngoog.ui.Component.prototype.exitDocument=function(){this.forEachChild(function(a){a.isInDocument()&&a.exitDocument()});this.googUiComponentHandler_&&this.googUiComponentHandler_.removeAll();this.inDocument_=!1};\ngoog.ui.Component.prototype.disposeInternal=function(){this.inDocument_&&this.exitDocument();this.googUiComponentHandler_&&(this.googUiComponentHandler_.dispose(),delete this.googUiComponentHandler_);this.forEachChild(function(a){a.dispose()});!this.wasDecorated_&&this.element_&&goog.dom.removeNode(this.element_);this.parent_=this.model_=this.element_=this.childIndex_=this.children_=null;goog.ui.Component.superClass_.disposeInternal.call(this)};\ngoog.ui.Component.prototype.makeId=function(a){return this.getId()+\".\"+a};goog.ui.Component.prototype.makeIds=function(a){var b={},c;for(c in a)b[c]=this.makeId(a[c]);return b};goog.ui.Component.prototype.getModel=function(){return this.model_};goog.ui.Component.prototype.setModel=function(a){this.model_=a};goog.ui.Component.prototype.getFragmentFromId=function(a){return a.substring(this.getId().length+1)};\ngoog.ui.Component.prototype.getElementByFragment=function(a){if(!this.inDocument_)throw Error(goog.ui.Component.Error.NOT_IN_DOCUMENT);return this.dom_.getElement(this.makeId(a))};goog.ui.Component.prototype.addChild=function(a,b){this.addChildAt(a,this.getChildCount(),b)};\ngoog.ui.Component.prototype.addChildAt=function(a,b,c){goog.asserts.assert(!!a,\"Provided element must not be null.\");if(a.inDocument_&&(c||!this.inDocument_))throw Error(goog.ui.Component.Error.ALREADY_RENDERED);if(0>b||b>this.getChildCount())throw Error(goog.ui.Component.Error.CHILD_INDEX_OUT_OF_BOUNDS);this.childIndex_&&this.children_||(this.childIndex_={},this.children_=[]);a.getParent()==this?(goog.object.set(this.childIndex_,a.getId(),a),goog.array.remove(this.children_,a)):goog.object.add(this.childIndex_,\na.getId(),a);a.setParent(this);goog.array.insertAt(this.children_,a,b);a.inDocument_&&this.inDocument_&&a.getParent()==this?(c=this.getContentElement(),b=c.childNodes[b]||null,b!=a.getElement()&&c.insertBefore(a.getElement(),b)):c?(this.element_||this.createDom(),b=this.getChildAt(b+1),a.render_(this.getContentElement(),b?b.element_:null)):this.inDocument_&&!a.inDocument_&&a.element_&&a.element_.parentNode&&a.element_.parentNode.nodeType==goog.dom.NodeType.ELEMENT&&a.enterDocument()};\ngoog.ui.Component.prototype.getContentElement=function(){return this.element_};goog.ui.Component.prototype.isRightToLeft=function(){null==this.rightToLeft_&&(this.rightToLeft_=goog.style.isRightToLeft(this.inDocument_?this.element_:this.dom_.getDocument().body));return this.rightToLeft_};goog.ui.Component.prototype.setRightToLeft=function(a){if(this.inDocument_)throw Error(goog.ui.Component.Error.ALREADY_RENDERED);this.rightToLeft_=a};\ngoog.ui.Component.prototype.hasChildren=function(){return!!this.children_&&0!=this.children_.length};goog.ui.Component.prototype.getChildCount=function(){return this.children_?this.children_.length:0};goog.ui.Component.prototype.getChildIds=function(){var a=[];this.forEachChild(function(b){a.push(b.getId())});return a};goog.ui.Component.prototype.getChild=function(a){return this.childIndex_&&a?goog.object.get(this.childIndex_,a)||null:null};\ngoog.ui.Component.prototype.getChildAt=function(a){return this.children_?this.children_[a]||null:null};goog.ui.Component.prototype.forEachChild=function(a,b){this.children_&&goog.array.forEach(this.children_,a,b)};goog.ui.Component.prototype.indexOfChild=function(a){return this.children_&&a?goog.array.indexOf(this.children_,a):-1};\ngoog.ui.Component.prototype.removeChild=function(a,b){if(a){var c=goog.isString(a)?a:a.getId();a=this.getChild(c);c&&a&&(goog.object.remove(this.childIndex_,c),goog.array.remove(this.children_,a),b&&(a.exitDocument(),a.element_&&goog.dom.removeNode(a.element_)),a.setParent(null))}if(!a)throw Error(goog.ui.Component.Error.NOT_OUR_CHILD);return a};goog.ui.Component.prototype.removeChildAt=function(a,b){return this.removeChild(this.getChildAt(a),b)};\ngoog.ui.Component.prototype.removeChildren=function(a){for(var b=[];this.hasChildren();)b.push(this.removeChildAt(0,a));return b};goog.events.KeyHandler=function(a,b){goog.events.EventTarget.call(this);a&&this.attach(a,b)};goog.inherits(goog.events.KeyHandler,goog.events.EventTarget);goog.events.KeyHandler.prototype.element_=null;goog.events.KeyHandler.prototype.keyPressKey_=null;goog.events.KeyHandler.prototype.keyDownKey_=null;goog.events.KeyHandler.prototype.keyUpKey_=null;goog.events.KeyHandler.prototype.lastKey_=-1;goog.events.KeyHandler.prototype.keyCode_=-1;goog.events.KeyHandler.prototype.altKey_=!1;\ngoog.events.KeyHandler.EventType={KEY:\"key\"};\ngoog.events.KeyHandler.safariKey_={3:goog.events.KeyCodes.ENTER,12:goog.events.KeyCodes.NUMLOCK,63232:goog.events.KeyCodes.UP,63233:goog.events.KeyCodes.DOWN,63234:goog.events.KeyCodes.LEFT,63235:goog.events.KeyCodes.RIGHT,63236:goog.events.KeyCodes.F1,63237:goog.events.KeyCodes.F2,63238:goog.events.KeyCodes.F3,63239:goog.events.KeyCodes.F4,63240:goog.events.KeyCodes.F5,63241:goog.events.KeyCodes.F6,63242:goog.events.KeyCodes.F7,63243:goog.events.KeyCodes.F8,63244:goog.events.KeyCodes.F9,63245:goog.events.KeyCodes.F10,\n63246:goog.events.KeyCodes.F11,63247:goog.events.KeyCodes.F12,63248:goog.events.KeyCodes.PRINT_SCREEN,63272:goog.events.KeyCodes.DELETE,63273:goog.events.KeyCodes.HOME,63275:goog.events.KeyCodes.END,63276:goog.events.KeyCodes.PAGE_UP,63277:goog.events.KeyCodes.PAGE_DOWN,63289:goog.events.KeyCodes.NUMLOCK,63302:goog.events.KeyCodes.INSERT};\ngoog.events.KeyHandler.keyIdentifier_={Up:goog.events.KeyCodes.UP,Down:goog.events.KeyCodes.DOWN,Left:goog.events.KeyCodes.LEFT,Right:goog.events.KeyCodes.RIGHT,Enter:goog.events.KeyCodes.ENTER,F1:goog.events.KeyCodes.F1,F2:goog.events.KeyCodes.F2,F3:goog.events.KeyCodes.F3,F4:goog.events.KeyCodes.F4,F5:goog.events.KeyCodes.F5,F6:goog.events.KeyCodes.F6,F7:goog.events.KeyCodes.F7,F8:goog.events.KeyCodes.F8,F9:goog.events.KeyCodes.F9,F10:goog.events.KeyCodes.F10,F11:goog.events.KeyCodes.F11,F12:goog.events.KeyCodes.F12,\n\"U+007F\":goog.events.KeyCodes.DELETE,Home:goog.events.KeyCodes.HOME,End:goog.events.KeyCodes.END,PageUp:goog.events.KeyCodes.PAGE_UP,PageDown:goog.events.KeyCodes.PAGE_DOWN,Insert:goog.events.KeyCodes.INSERT};goog.events.KeyHandler.USES_KEYDOWN_=goog.userAgent.IE||goog.userAgent.EDGE||goog.userAgent.WEBKIT&&goog.userAgent.isVersionOrHigher(\"525\");goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_=goog.userAgent.MAC&&goog.userAgent.GECKO;\ngoog.events.KeyHandler.prototype.handleKeyDown_=function(a){(goog.userAgent.WEBKIT||goog.userAgent.EDGE)&&(this.lastKey_==goog.events.KeyCodes.CTRL&&!a.ctrlKey||this.lastKey_==goog.events.KeyCodes.ALT&&!a.altKey||goog.userAgent.MAC&&this.lastKey_==goog.events.KeyCodes.META&&!a.metaKey)&&this.resetState();-1==this.lastKey_&&(a.ctrlKey&&a.keyCode!=goog.events.KeyCodes.CTRL?this.lastKey_=goog.events.KeyCodes.CTRL:a.altKey&&a.keyCode!=goog.events.KeyCodes.ALT?this.lastKey_=goog.events.KeyCodes.ALT:a.metaKey&&\na.keyCode!=goog.events.KeyCodes.META&&(this.lastKey_=goog.events.KeyCodes.META));goog.events.KeyHandler.USES_KEYDOWN_&&!goog.events.KeyCodes.firesKeyPressEvent(a.keyCode,this.lastKey_,a.shiftKey,a.ctrlKey,a.altKey)?this.handleEvent(a):(this.keyCode_=goog.events.KeyCodes.normalizeKeyCode(a.keyCode),goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_&&(this.altKey_=a.altKey))};goog.events.KeyHandler.prototype.resetState=function(){this.keyCode_=this.lastKey_=-1};\ngoog.events.KeyHandler.prototype.handleKeyup_=function(a){this.resetState();this.altKey_=a.altKey};\ngoog.events.KeyHandler.prototype.handleEvent=function(a){var b=a.getBrowserEvent(),c,d,e=b.altKey;goog.userAgent.IE&&a.type==goog.events.EventType.KEYPRESS?(c=this.keyCode_,d=c!=goog.events.KeyCodes.ENTER&&c!=goog.events.KeyCodes.ESC?b.keyCode:0):(goog.userAgent.WEBKIT||goog.userAgent.EDGE)&&a.type==goog.events.EventType.KEYPRESS?(c=this.keyCode_,d=0<=b.charCode&&63232>b.charCode&&goog.events.KeyCodes.isCharacterKey(c)?b.charCode:0):goog.userAgent.OPERA&&!goog.userAgent.WEBKIT?(c=this.keyCode_,d=\ngoog.events.KeyCodes.isCharacterKey(c)?b.keyCode:0):(c=b.keyCode||this.keyCode_,d=b.charCode||0,goog.events.KeyHandler.SAVE_ALT_FOR_KEYPRESS_&&(e=this.altKey_),goog.userAgent.MAC&&d==goog.events.KeyCodes.QUESTION_MARK&&c==goog.events.KeyCodes.WIN_KEY&&(c=goog.events.KeyCodes.SLASH));var f=c=goog.events.KeyCodes.normalizeKeyCode(c),g=b.keyIdentifier;c?63232<=c&&c in goog.events.KeyHandler.safariKey_?f=goog.events.KeyHandler.safariKey_[c]:25==c&&a.shiftKey&&(f=9):g&&g in goog.events.KeyHandler.keyIdentifier_&&\n(f=goog.events.KeyHandler.keyIdentifier_[g]);a=f==this.lastKey_;this.lastKey_=f;b=new goog.events.KeyEvent(f,d,a,b);b.altKey=e;this.dispatchEvent(b)};goog.events.KeyHandler.prototype.getElement=function(){return this.element_};\ngoog.events.KeyHandler.prototype.attach=function(a,b){this.keyUpKey_&&this.detach();this.element_=a;this.keyPressKey_=goog.events.listen(this.element_,goog.events.EventType.KEYPRESS,this,b);this.keyDownKey_=goog.events.listen(this.element_,goog.events.EventType.KEYDOWN,this.handleKeyDown_,b,this);this.keyUpKey_=goog.events.listen(this.element_,goog.events.EventType.KEYUP,this.handleKeyup_,b,this)};\ngoog.events.KeyHandler.prototype.detach=function(){this.keyPressKey_&&(goog.events.unlistenByKey(this.keyPressKey_),goog.events.unlistenByKey(this.keyDownKey_),goog.events.unlistenByKey(this.keyUpKey_),this.keyUpKey_=this.keyDownKey_=this.keyPressKey_=null);this.element_=null;this.keyCode_=this.lastKey_=-1};goog.events.KeyHandler.prototype.disposeInternal=function(){goog.events.KeyHandler.superClass_.disposeInternal.call(this);this.detach()};\ngoog.events.KeyEvent=function(a,b,c,d){goog.events.BrowserEvent.call(this,d);this.type=goog.events.KeyHandler.EventType.KEY;this.keyCode=a;this.charCode=b;this.repeat=c};goog.inherits(goog.events.KeyEvent,goog.events.BrowserEvent);goog.a11y={};goog.a11y.aria={};\ngoog.a11y.aria.Role={ALERT:\"alert\",ALERTDIALOG:\"alertdialog\",APPLICATION:\"application\",ARTICLE:\"article\",BANNER:\"banner\",BUTTON:\"button\",CHECKBOX:\"checkbox\",COLUMNHEADER:\"columnheader\",COMBOBOX:\"combobox\",COMPLEMENTARY:\"complementary\",CONTENTINFO:\"contentinfo\",DEFINITION:\"definition\",DIALOG:\"dialog\",DIRECTORY:\"directory\",DOCUMENT:\"document\",FORM:\"form\",GRID:\"grid\",GRIDCELL:\"gridcell\",GROUP:\"group\",HEADING:\"heading\",IMG:\"img\",LINK:\"link\",LIST:\"list\",LISTBOX:\"listbox\",LISTITEM:\"listitem\",LOG:\"log\",\nMAIN:\"main\",MARQUEE:\"marquee\",MATH:\"math\",MENU:\"menu\",MENUBAR:\"menubar\",MENU_ITEM:\"menuitem\",MENU_ITEM_CHECKBOX:\"menuitemcheckbox\",MENU_ITEM_RADIO:\"menuitemradio\",NAVIGATION:\"navigation\",NOTE:\"note\",OPTION:\"option\",PRESENTATION:\"presentation\",PROGRESSBAR:\"progressbar\",RADIO:\"radio\",RADIOGROUP:\"radiogroup\",REGION:\"region\",ROW:\"row\",ROWGROUP:\"rowgroup\",ROWHEADER:\"rowheader\",SCROLLBAR:\"scrollbar\",SEARCH:\"search\",SEPARATOR:\"separator\",SLIDER:\"slider\",SPINBUTTON:\"spinbutton\",STATUS:\"status\",TAB:\"tab\",\nTAB_LIST:\"tablist\",TAB_PANEL:\"tabpanel\",TEXTBOX:\"textbox\",TEXTINFO:\"textinfo\",TIMER:\"timer\",TOOLBAR:\"toolbar\",TOOLTIP:\"tooltip\",TREE:\"tree\",TREEGRID:\"treegrid\",TREEITEM:\"treeitem\"};goog.a11y.aria.State={ACTIVEDESCENDANT:\"activedescendant\",ATOMIC:\"atomic\",AUTOCOMPLETE:\"autocomplete\",BUSY:\"busy\",CHECKED:\"checked\",CONTROLS:\"controls\",DESCRIBEDBY:\"describedby\",DISABLED:\"disabled\",DROPEFFECT:\"dropeffect\",EXPANDED:\"expanded\",FLOWTO:\"flowto\",GRABBED:\"grabbed\",HASPOPUP:\"haspopup\",HIDDEN:\"hidden\",INVALID:\"invalid\",LABEL:\"label\",LABELLEDBY:\"labelledby\",LEVEL:\"level\",LIVE:\"live\",MULTILINE:\"multiline\",MULTISELECTABLE:\"multiselectable\",ORIENTATION:\"orientation\",OWNS:\"owns\",POSINSET:\"posinset\",\nPRESSED:\"pressed\",READONLY:\"readonly\",RELEVANT:\"relevant\",REQUIRED:\"required\",SELECTED:\"selected\",SETSIZE:\"setsize\",SORT:\"sort\",VALUEMAX:\"valuemax\",VALUEMIN:\"valuemin\",VALUENOW:\"valuenow\",VALUETEXT:\"valuetext\"};goog.a11y.aria.AutoCompleteValues={INLINE:\"inline\",LIST:\"list\",BOTH:\"both\",NONE:\"none\"};goog.a11y.aria.DropEffectValues={COPY:\"copy\",MOVE:\"move\",LINK:\"link\",EXECUTE:\"execute\",POPUP:\"popup\",NONE:\"none\"};goog.a11y.aria.LivePriority={OFF:\"off\",POLITE:\"polite\",ASSERTIVE:\"assertive\"};\ngoog.a11y.aria.OrientationValues={VERTICAL:\"vertical\",HORIZONTAL:\"horizontal\"};goog.a11y.aria.RelevantValues={ADDITIONS:\"additions\",REMOVALS:\"removals\",TEXT:\"text\",ALL:\"all\"};goog.a11y.aria.SortValues={ASCENDING:\"ascending\",DESCENDING:\"descending\",NONE:\"none\",OTHER:\"other\"};goog.a11y.aria.CheckedValues={TRUE:\"true\",FALSE:\"false\",MIXED:\"mixed\",UNDEFINED:\"undefined\"};goog.a11y.aria.ExpandedValues={TRUE:\"true\",FALSE:\"false\",UNDEFINED:\"undefined\"};\ngoog.a11y.aria.GrabbedValues={TRUE:\"true\",FALSE:\"false\",UNDEFINED:\"undefined\"};goog.a11y.aria.InvalidValues={FALSE:\"false\",TRUE:\"true\",GRAMMAR:\"grammar\",SPELLING:\"spelling\"};goog.a11y.aria.PressedValues={TRUE:\"true\",FALSE:\"false\",MIXED:\"mixed\",UNDEFINED:\"undefined\"};goog.a11y.aria.SelectedValues={TRUE:\"true\",FALSE:\"false\",UNDEFINED:\"undefined\"};goog.a11y.aria.datatables={};\ngoog.a11y.aria.datatables.getDefaultValuesMap=function(){goog.a11y.aria.DefaultStateValueMap_||(goog.a11y.aria.DefaultStateValueMap_=goog.object.create(goog.a11y.aria.State.ATOMIC,!1,goog.a11y.aria.State.AUTOCOMPLETE,\"none\",goog.a11y.aria.State.DROPEFFECT,\"none\",goog.a11y.aria.State.HASPOPUP,!1,goog.a11y.aria.State.LIVE,\"off\",goog.a11y.aria.State.MULTILINE,!1,goog.a11y.aria.State.MULTISELECTABLE,!1,goog.a11y.aria.State.ORIENTATION,\"vertical\",goog.a11y.aria.State.READONLY,!1,goog.a11y.aria.State.RELEVANT,\n\"additions text\",goog.a11y.aria.State.REQUIRED,!1,goog.a11y.aria.State.SORT,\"none\",goog.a11y.aria.State.BUSY,!1,goog.a11y.aria.State.DISABLED,!1,goog.a11y.aria.State.HIDDEN,!1,goog.a11y.aria.State.INVALID,\"false\"));return goog.a11y.aria.DefaultStateValueMap_};goog.a11y.aria.ARIA_PREFIX_=\"aria-\";goog.a11y.aria.ROLE_ATTRIBUTE_=\"role\";goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_=\"A AREA BUTTON HEAD INPUT LINK MENU META OPTGROUP OPTION PROGRESS STYLE SELECT SOURCE TEXTAREA TITLE TRACK\".split(\" \");\ngoog.a11y.aria.CONTAINER_ROLES_=[goog.a11y.aria.Role.COMBOBOX,goog.a11y.aria.Role.GRID,goog.a11y.aria.Role.GROUP,goog.a11y.aria.Role.LISTBOX,goog.a11y.aria.Role.MENU,goog.a11y.aria.Role.MENUBAR,goog.a11y.aria.Role.RADIOGROUP,goog.a11y.aria.Role.ROW,goog.a11y.aria.Role.ROWGROUP,goog.a11y.aria.Role.TAB_LIST,goog.a11y.aria.Role.TEXTBOX,goog.a11y.aria.Role.TOOLBAR,goog.a11y.aria.Role.TREE,goog.a11y.aria.Role.TREEGRID];\ngoog.a11y.aria.setRole=function(a,b){b?(goog.asserts.ENABLE_ASSERTS&&goog.asserts.assert(goog.object.containsValue(goog.a11y.aria.Role,b),\"No such ARIA role \"+b),a.setAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_,b)):goog.a11y.aria.removeRole(a)};goog.a11y.aria.getRole=function(a){return a.getAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_)||null};goog.a11y.aria.removeRole=function(a){a.removeAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_)};\ngoog.a11y.aria.setState=function(a,b,c){goog.isArray(c)&&(c=c.join(\" \"));var d=goog.a11y.aria.getAriaAttributeName_(b);\"\"===c||void 0==c?(c=goog.a11y.aria.datatables.getDefaultValuesMap(),b in c?a.setAttribute(d,c[b]):a.removeAttribute(d)):a.setAttribute(d,c)};goog.a11y.aria.toggleState=function(a,b){var c=goog.a11y.aria.getState(a,b);goog.string.isEmptyOrWhitespace(goog.string.makeSafe(c))||\"true\"==c||\"false\"==c?goog.a11y.aria.setState(a,b,\"true\"==c?\"false\":\"true\"):goog.a11y.aria.removeState(a,b)};\ngoog.a11y.aria.removeState=function(a,b){a.removeAttribute(goog.a11y.aria.getAriaAttributeName_(b))};goog.a11y.aria.getState=function(a,b){var c=a.getAttribute(goog.a11y.aria.getAriaAttributeName_(b));return null==c||void 0==c?\"\":String(c)};goog.a11y.aria.getActiveDescendant=function(a){var b=goog.a11y.aria.getState(a,goog.a11y.aria.State.ACTIVEDESCENDANT);return goog.dom.getOwnerDocument(a).getElementById(b)};\ngoog.a11y.aria.setActiveDescendant=function(a,b){var c=\"\";b&&(c=b.id,goog.asserts.assert(c,\"The active element should have an id.\"));goog.a11y.aria.setState(a,goog.a11y.aria.State.ACTIVEDESCENDANT,c)};goog.a11y.aria.getLabel=function(a){return goog.a11y.aria.getState(a,goog.a11y.aria.State.LABEL)};goog.a11y.aria.setLabel=function(a,b){goog.a11y.aria.setState(a,goog.a11y.aria.State.LABEL,b)};\ngoog.a11y.aria.assertRoleIsSetInternalUtil=function(a,b){if(!goog.array.contains(goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_,a.tagName)){var c=goog.a11y.aria.getRole(a);goog.asserts.assert(null!=c,\"The element ARIA role cannot be null.\");goog.asserts.assert(goog.array.contains(b,c),'Non existing or incorrect role set for element.The role set is \"'+c+'\". The role should be any of \"'+b+'\". Check the ARIA specification for more details http://www.w3.org/TR/wai-aria/roles.')}};\ngoog.a11y.aria.getStateBoolean=function(a,b){var c=a.getAttribute(goog.a11y.aria.getAriaAttributeName_(b));goog.asserts.assert(goog.isBoolean(c)||null==c||\"true\"==c||\"false\"==c);return null==c?c:goog.isBoolean(c)?c:\"true\"==c};goog.a11y.aria.getStateNumber=function(a,b){var c=a.getAttribute(goog.a11y.aria.getAriaAttributeName_(b));goog.asserts.assert((null==c||!isNaN(Number(c)))&&!goog.isBoolean(c));return null==c?null:Number(c)};\ngoog.a11y.aria.getStateString=function(a,b){var c=a.getAttribute(goog.a11y.aria.getAriaAttributeName_(b));goog.asserts.assert((null==c||goog.isString(c))&&(\"\"==c||isNaN(Number(c)))&&\"true\"!=c&&\"false\"!=c);return null==c||\"\"==c?null:c};goog.a11y.aria.getStringArrayStateInternalUtil=function(a,b){var c=a.getAttribute(goog.a11y.aria.getAriaAttributeName_(b));return goog.a11y.aria.splitStringOnWhitespace_(c)};goog.a11y.aria.hasState=function(a,b){return a.hasAttribute(goog.a11y.aria.getAriaAttributeName_(b))};\ngoog.a11y.aria.isContainerRole=function(a){a=goog.a11y.aria.getRole(a);return goog.array.contains(goog.a11y.aria.CONTAINER_ROLES_,a)};goog.a11y.aria.splitStringOnWhitespace_=function(a){return a?a.split(/\\s+/):[]};goog.a11y.aria.getAriaAttributeName_=function(a){goog.asserts.ENABLE_ASSERTS&&(goog.asserts.assert(a,\"ARIA attribute cannot be empty.\"),goog.asserts.assert(goog.object.containsValue(goog.a11y.aria.State,a),\"No such ARIA attribute \"+a));return goog.a11y.aria.ARIA_PREFIX_+a};goog.dom.classlist={};goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST=!1;goog.dom.classlist.get=function(a){if(goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST||a.classList)return a.classList;a=a.className;return goog.isString(a)&&a.match(/\\S+/g)||[]};goog.dom.classlist.set=function(a,b){a.className=b};goog.dom.classlist.contains=function(a,b){return goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST||a.classList?a.classList.contains(b):goog.array.contains(goog.dom.classlist.get(a),b)};\ngoog.dom.classlist.add=function(a,b){goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST||a.classList?a.classList.add(b):goog.dom.classlist.contains(a,b)||(a.className+=0<a.className.length?\" \"+b:b)};\ngoog.dom.classlist.addAll=function(a,b){if(goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST||a.classList)goog.array.forEach(b,function(b){goog.dom.classlist.add(a,b)});else{var c={};goog.array.forEach(goog.dom.classlist.get(a),function(a){c[a]=!0});goog.array.forEach(b,function(a){c[a]=!0});a.className=\"\";for(var d in c)a.className+=0<a.className.length?\" \"+d:d}};\ngoog.dom.classlist.remove=function(a,b){goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST||a.classList?a.classList.remove(b):goog.dom.classlist.contains(a,b)&&(a.className=goog.array.filter(goog.dom.classlist.get(a),function(a){return a!=b}).join(\" \"))};\ngoog.dom.classlist.removeAll=function(a,b){goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST||a.classList?goog.array.forEach(b,function(b){goog.dom.classlist.remove(a,b)}):a.className=goog.array.filter(goog.dom.classlist.get(a),function(a){return!goog.array.contains(b,a)}).join(\" \")};goog.dom.classlist.enable=function(a,b,c){c?goog.dom.classlist.add(a,b):goog.dom.classlist.remove(a,b)};goog.dom.classlist.enableAll=function(a,b,c){(c?goog.dom.classlist.addAll:goog.dom.classlist.removeAll)(a,b)};\ngoog.dom.classlist.swap=function(a,b,c){return goog.dom.classlist.contains(a,b)?(goog.dom.classlist.remove(a,b),goog.dom.classlist.add(a,c),!0):!1};goog.dom.classlist.toggle=function(a,b){var c=!goog.dom.classlist.contains(a,b);goog.dom.classlist.enable(a,b,c);return c};goog.dom.classlist.addRemove=function(a,b,c){goog.dom.classlist.remove(a,b);goog.dom.classlist.add(a,c)};goog.ui.ControlRenderer=function(){};goog.addSingletonGetter(goog.ui.ControlRenderer);goog.tagUnsealableClass(goog.ui.ControlRenderer);goog.ui.ControlRenderer.getCustomRenderer=function(a,b){var c=new a;c.getCssClass=function(){return b};return c};goog.ui.ControlRenderer.CSS_CLASS=\"goog-control\";goog.ui.ControlRenderer.IE6_CLASS_COMBINATIONS=[];\ngoog.ui.ControlRenderer.TOGGLE_ARIA_STATE_MAP_=goog.object.create(goog.a11y.aria.Role.BUTTON,goog.a11y.aria.State.PRESSED,goog.a11y.aria.Role.CHECKBOX,goog.a11y.aria.State.CHECKED,goog.a11y.aria.Role.MENU_ITEM,goog.a11y.aria.State.SELECTED,goog.a11y.aria.Role.MENU_ITEM_CHECKBOX,goog.a11y.aria.State.CHECKED,goog.a11y.aria.Role.MENU_ITEM_RADIO,goog.a11y.aria.State.CHECKED,goog.a11y.aria.Role.RADIO,goog.a11y.aria.State.CHECKED,goog.a11y.aria.Role.TAB,goog.a11y.aria.State.SELECTED,goog.a11y.aria.Role.TREEITEM,\ngoog.a11y.aria.State.SELECTED);goog.ui.ControlRenderer.prototype.getAriaRole=function(){};goog.ui.ControlRenderer.prototype.createDom=function(a){return a.getDomHelper().createDom(\"DIV\",this.getClassNames(a).join(\" \"),a.getContent())};goog.ui.ControlRenderer.prototype.getContentElement=function(a){return a};\ngoog.ui.ControlRenderer.prototype.enableClassName=function(a,b,c){if(a=a.getElement?a.getElement():a){var d=[b];goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"7\")&&(d=this.getAppliedCombinedClassNames_(goog.dom.classlist.get(a),b),d.push(b));goog.dom.classlist.enableAll(a,d,c)}};goog.ui.ControlRenderer.prototype.enableExtraClassName=function(a,b,c){this.enableClassName(a,b,c)};goog.ui.ControlRenderer.prototype.canDecorate=function(a){return!0};\ngoog.ui.ControlRenderer.prototype.decorate=function(a,b){b.id&&a.setId(b.id);var c=this.getContentElement(b);c&&c.firstChild?a.setContentInternal(c.firstChild.nextSibling?goog.array.clone(c.childNodes):c.firstChild):a.setContentInternal(null);var d=0,e=this.getCssClass(),f=this.getStructuralCssClass(),g=!1,h=!1,k=!1,n=goog.array.toArray(goog.dom.classlist.get(b));goog.array.forEach(n,function(a){g||a!=e?h||a!=f?d|=this.getStateFromClass(a):h=!0:(g=!0,f==e&&(h=!0));this.getStateFromClass(a)==goog.ui.Component.State.DISABLED&&\n(goog.asserts.assertElement(c),goog.dom.isFocusableTabIndex(c)&&goog.dom.setFocusableTabIndex(c,!1))},this);a.setStateInternal(d);g||(n.push(e),f==e&&(h=!0));h||n.push(f);var p=a.getExtraClassNames();p&&n.push.apply(n,p);if(goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"7\")){var m=this.getAppliedCombinedClassNames_(n);0<m.length&&(n.push.apply(n,m),k=!0)}g&&h&&!p&&!k||goog.dom.classlist.set(b,n.join(\" \"));return b};\ngoog.ui.ControlRenderer.prototype.initializeDom=function(a){a.isRightToLeft()&&this.setRightToLeft(a.getElement(),!0);a.isEnabled()&&this.setFocusable(a,a.isVisible())};goog.ui.ControlRenderer.prototype.setAriaRole=function(a,b){var c=b||this.getAriaRole();if(c){goog.asserts.assert(a,\"The element passed as a first parameter cannot be null.\");var d=goog.a11y.aria.getRole(a);c!=d&&goog.a11y.aria.setRole(a,c)}};\ngoog.ui.ControlRenderer.prototype.setAriaStates=function(a,b){goog.asserts.assert(a);goog.asserts.assert(b);var c=a.getAriaLabel();goog.isDefAndNotNull(c)&&this.setAriaLabel(b,c);a.isVisible()||goog.a11y.aria.setState(b,goog.a11y.aria.State.HIDDEN,!a.isVisible());a.isEnabled()||this.updateAriaState(b,goog.ui.Component.State.DISABLED,!a.isEnabled());a.isSupportedState(goog.ui.Component.State.SELECTED)&&this.updateAriaState(b,goog.ui.Component.State.SELECTED,a.isSelected());a.isSupportedState(goog.ui.Component.State.CHECKED)&&\nthis.updateAriaState(b,goog.ui.Component.State.CHECKED,a.isChecked());a.isSupportedState(goog.ui.Component.State.OPENED)&&this.updateAriaState(b,goog.ui.Component.State.OPENED,a.isOpen())};goog.ui.ControlRenderer.prototype.setAriaLabel=function(a,b){goog.a11y.aria.setLabel(a,b)};goog.ui.ControlRenderer.prototype.setAllowTextSelection=function(a,b){goog.style.setUnselectable(a,!b,!goog.userAgent.IE&&!goog.userAgent.OPERA)};\ngoog.ui.ControlRenderer.prototype.setRightToLeft=function(a,b){this.enableClassName(a,this.getStructuralCssClass()+\"-rtl\",b)};goog.ui.ControlRenderer.prototype.isFocusable=function(a){var b;return a.isSupportedState(goog.ui.Component.State.FOCUSED)&&(b=a.getKeyEventTarget())?goog.dom.isFocusableTabIndex(b):!1};\ngoog.ui.ControlRenderer.prototype.setFocusable=function(a,b){var c;if(a.isSupportedState(goog.ui.Component.State.FOCUSED)&&(c=a.getKeyEventTarget())){if(!b&&a.isFocused()){try{c.blur()}catch(d){}a.isFocused()&&a.handleBlur(null)}goog.dom.isFocusableTabIndex(c)!=b&&goog.dom.setFocusableTabIndex(c,b)}};goog.ui.ControlRenderer.prototype.setVisible=function(a,b){goog.style.setElementShown(a,b);a&&goog.a11y.aria.setState(a,goog.a11y.aria.State.HIDDEN,!b)};\ngoog.ui.ControlRenderer.prototype.setState=function(a,b,c){var d=a.getElement();if(d){var e=this.getClassForState(b);e&&this.enableClassName(a,e,c);this.updateAriaState(d,b,c)}};\ngoog.ui.ControlRenderer.prototype.updateAriaState=function(a,b,c){goog.ui.ControlRenderer.ariaAttributeMap_||(goog.ui.ControlRenderer.ariaAttributeMap_=goog.object.create(goog.ui.Component.State.DISABLED,goog.a11y.aria.State.DISABLED,goog.ui.Component.State.SELECTED,goog.a11y.aria.State.SELECTED,goog.ui.Component.State.CHECKED,goog.a11y.aria.State.CHECKED,goog.ui.Component.State.OPENED,goog.a11y.aria.State.EXPANDED));goog.asserts.assert(a,\"The element passed as a first parameter cannot be null.\");\n(b=goog.ui.ControlRenderer.getAriaStateForAriaRole_(a,goog.ui.ControlRenderer.ariaAttributeMap_[b]))&&goog.a11y.aria.setState(a,b,c)};goog.ui.ControlRenderer.getAriaStateForAriaRole_=function(a,b){var c=goog.a11y.aria.getRole(a);if(!c)return b;c=goog.ui.ControlRenderer.TOGGLE_ARIA_STATE_MAP_[c]||b;return goog.ui.ControlRenderer.isAriaState_(b)?c:b};goog.ui.ControlRenderer.isAriaState_=function(a){return a==goog.a11y.aria.State.CHECKED||a==goog.a11y.aria.State.SELECTED};\ngoog.ui.ControlRenderer.prototype.setContent=function(a,b){var c=this.getContentElement(a);if(c&&(goog.dom.removeChildren(c),b))if(goog.isString(b))goog.dom.setTextContent(c,b);else{var d=function(a){if(a){var b=goog.dom.getOwnerDocument(c);c.appendChild(goog.isString(a)?b.createTextNode(a):a)}};goog.isArray(b)?goog.array.forEach(b,d):!goog.isArrayLike(b)||\"nodeType\"in b?d(b):goog.array.forEach(goog.array.clone(b),d)}};goog.ui.ControlRenderer.prototype.getKeyEventTarget=function(a){return a.getElement()};\ngoog.ui.ControlRenderer.prototype.getCssClass=function(){return goog.ui.ControlRenderer.CSS_CLASS};goog.ui.ControlRenderer.prototype.getIe6ClassCombinations=function(){return[]};goog.ui.ControlRenderer.prototype.getStructuralCssClass=function(){return this.getCssClass()};\ngoog.ui.ControlRenderer.prototype.getClassNames=function(a){var b=this.getCssClass(),c=[b],d=this.getStructuralCssClass();d!=b&&c.push(d);b=this.getClassNamesForState(a.getState());c.push.apply(c,b);(a=a.getExtraClassNames())&&c.push.apply(c,a);goog.userAgent.IE&&!goog.userAgent.isVersionOrHigher(\"7\")&&c.push.apply(c,this.getAppliedCombinedClassNames_(c));return c};\ngoog.ui.ControlRenderer.prototype.getAppliedCombinedClassNames_=function(a,b){var c=[];b&&(a=goog.array.concat(a,[b]));goog.array.forEach(this.getIe6ClassCombinations(),function(d){!goog.array.every(d,goog.partial(goog.array.contains,a))||b&&!goog.array.contains(d,b)||c.push(d.join(\"_\"))});return c};goog.ui.ControlRenderer.prototype.getClassNamesForState=function(a){for(var b=[];a;){var c=a&-a;b.push(this.getClassForState(c));a&=~c}return b};\ngoog.ui.ControlRenderer.prototype.getClassForState=function(a){this.classByState_||this.createClassByStateMap_();return this.classByState_[a]};goog.ui.ControlRenderer.prototype.getStateFromClass=function(a){this.stateByClass_||this.createStateByClassMap_();a=parseInt(this.stateByClass_[a],10);return isNaN(a)?0:a};\ngoog.ui.ControlRenderer.prototype.createClassByStateMap_=function(){var a=this.getStructuralCssClass(),b=!goog.string.contains(goog.string.normalizeWhitespace(a),\" \");goog.asserts.assert(b,\"ControlRenderer has an invalid css class: '\"+a+\"'\");this.classByState_=goog.object.create(goog.ui.Component.State.DISABLED,a+\"-disabled\",goog.ui.Component.State.HOVER,a+\"-hover\",goog.ui.Component.State.ACTIVE,a+\"-active\",goog.ui.Component.State.SELECTED,a+\"-selected\",goog.ui.Component.State.CHECKED,a+\"-checked\",\ngoog.ui.Component.State.FOCUSED,a+\"-focused\",goog.ui.Component.State.OPENED,a+\"-open\")};goog.ui.ControlRenderer.prototype.createStateByClassMap_=function(){this.classByState_||this.createClassByStateMap_();this.stateByClass_=goog.object.transpose(this.classByState_)};goog.ui.registry={};goog.ui.registry.getDefaultRenderer=function(a){for(var b;a;){b=goog.getUid(a);if(b=goog.ui.registry.defaultRenderers_[b])break;a=a.superClass_?a.superClass_.constructor:null}return b?goog.isFunction(b.getInstance)?b.getInstance():new b:null};\ngoog.ui.registry.setDefaultRenderer=function(a,b){if(!goog.isFunction(a))throw Error(\"Invalid component class \"+a);if(!goog.isFunction(b))throw Error(\"Invalid renderer class \"+b);var c=goog.getUid(a);goog.ui.registry.defaultRenderers_[c]=b};goog.ui.registry.getDecoratorByClassName=function(a){return a in goog.ui.registry.decoratorFunctions_?goog.ui.registry.decoratorFunctions_[a]():null};\ngoog.ui.registry.setDecoratorByClassName=function(a,b){if(!a)throw Error(\"Invalid class name \"+a);if(!goog.isFunction(b))throw Error(\"Invalid decorator function \"+b);goog.ui.registry.decoratorFunctions_[a]=b};goog.ui.registry.getDecorator=function(a){goog.asserts.assert(a);for(var b=goog.dom.classlist.get(a),c=0,d=b.length;c<d;c++)if(a=goog.ui.registry.getDecoratorByClassName(b[c]))return a;return null};\ngoog.ui.registry.reset=function(){goog.ui.registry.defaultRenderers_={};goog.ui.registry.decoratorFunctions_={}};goog.ui.registry.defaultRenderers_={};goog.ui.registry.decoratorFunctions_={};goog.ui.Control=function(a,b,c){goog.ui.Component.call(this,c);this.renderer_=b||goog.ui.registry.getDefaultRenderer(this.constructor);this.setContentInternal(goog.isDef(a)?a:null);this.ariaLabel_=null};goog.inherits(goog.ui.Control,goog.ui.Component);goog.tagUnsealableClass(goog.ui.Control);goog.ui.Control.registerDecorator=goog.ui.registry.setDecoratorByClassName;goog.ui.Control.getDecorator=goog.ui.registry.getDecorator;goog.ui.Control.prototype.content_=null;goog.ui.Control.prototype.state_=0;\ngoog.ui.Control.prototype.supportedStates_=goog.ui.Component.State.DISABLED|goog.ui.Component.State.HOVER|goog.ui.Component.State.ACTIVE|goog.ui.Component.State.FOCUSED;goog.ui.Control.prototype.autoStates_=goog.ui.Component.State.ALL;goog.ui.Control.prototype.statesWithTransitionEvents_=0;goog.ui.Control.prototype.visible_=!0;goog.ui.Control.prototype.extraClassNames_=null;goog.ui.Control.prototype.handleMouseEvents_=!0;goog.ui.Control.prototype.allowTextSelection_=!1;\ngoog.ui.Control.prototype.preferredAriaRole_=null;goog.ui.Control.prototype.isHandleMouseEvents=function(){return this.handleMouseEvents_};goog.ui.Control.prototype.setHandleMouseEvents=function(a){this.isInDocument()&&a!=this.handleMouseEvents_&&this.enableMouseEventHandling_(a);this.handleMouseEvents_=a};goog.ui.Control.prototype.getKeyEventTarget=function(){return this.renderer_.getKeyEventTarget(this)};\ngoog.ui.Control.prototype.getKeyHandler=function(){return this.keyHandler_||(this.keyHandler_=new goog.events.KeyHandler)};goog.ui.Control.prototype.getRenderer=function(){return this.renderer_};goog.ui.Control.prototype.setRenderer=function(a){if(this.isInDocument())throw Error(goog.ui.Component.Error.ALREADY_RENDERED);this.getElement()&&this.setElementInternal(null);this.renderer_=a};goog.ui.Control.prototype.getExtraClassNames=function(){return this.extraClassNames_};\ngoog.ui.Control.prototype.addClassName=function(a){a&&(this.extraClassNames_?goog.array.contains(this.extraClassNames_,a)||this.extraClassNames_.push(a):this.extraClassNames_=[a],this.renderer_.enableExtraClassName(this,a,!0))};goog.ui.Control.prototype.removeClassName=function(a){a&&this.extraClassNames_&&goog.array.remove(this.extraClassNames_,a)&&(0==this.extraClassNames_.length&&(this.extraClassNames_=null),this.renderer_.enableExtraClassName(this,a,!1))};\ngoog.ui.Control.prototype.enableClassName=function(a,b){b?this.addClassName(a):this.removeClassName(a)};goog.ui.Control.prototype.createDom=function(){var a=this.renderer_.createDom(this);this.setElementInternal(a);this.renderer_.setAriaRole(a,this.getPreferredAriaRole());this.isAllowTextSelection()||this.renderer_.setAllowTextSelection(a,!1);this.isVisible()||this.renderer_.setVisible(a,!1)};goog.ui.Control.prototype.getPreferredAriaRole=function(){return this.preferredAriaRole_};\ngoog.ui.Control.prototype.setPreferredAriaRole=function(a){this.preferredAriaRole_=a};goog.ui.Control.prototype.getAriaLabel=function(){return this.ariaLabel_};goog.ui.Control.prototype.setAriaLabel=function(a){this.ariaLabel_=a;var b=this.getElement();b&&this.renderer_.setAriaLabel(b,a)};goog.ui.Control.prototype.getContentElement=function(){return this.renderer_.getContentElement(this.getElement())};goog.ui.Control.prototype.canDecorate=function(a){return this.renderer_.canDecorate(a)};\ngoog.ui.Control.prototype.decorateInternal=function(a){a=this.renderer_.decorate(this,a);this.setElementInternal(a);this.renderer_.setAriaRole(a,this.getPreferredAriaRole());this.isAllowTextSelection()||this.renderer_.setAllowTextSelection(a,!1);this.visible_=\"none\"!=a.style.display};\ngoog.ui.Control.prototype.enterDocument=function(){goog.ui.Control.superClass_.enterDocument.call(this);this.renderer_.setAriaStates(this,this.getElementStrict());this.renderer_.initializeDom(this);if(this.supportedStates_&~goog.ui.Component.State.DISABLED&&(this.isHandleMouseEvents()&&this.enableMouseEventHandling_(!0),this.isSupportedState(goog.ui.Component.State.FOCUSED))){var a=this.getKeyEventTarget();if(a){var b=this.getKeyHandler();b.attach(a);this.getHandler().listen(b,goog.events.KeyHandler.EventType.KEY,\nthis.handleKeyEvent).listen(a,goog.events.EventType.FOCUS,this.handleFocus).listen(a,goog.events.EventType.BLUR,this.handleBlur)}}};\ngoog.ui.Control.prototype.enableMouseEventHandling_=function(a){var b=this.getHandler(),c=this.getElement();a?(b.listen(c,goog.events.EventType.MOUSEOVER,this.handleMouseOver).listen(c,goog.events.EventType.MOUSEDOWN,this.handleMouseDown).listen(c,goog.events.EventType.MOUSEUP,this.handleMouseUp).listen(c,goog.events.EventType.MOUSEOUT,this.handleMouseOut),this.handleContextMenu!=goog.nullFunction&&b.listen(c,goog.events.EventType.CONTEXTMENU,this.handleContextMenu),goog.userAgent.IE&&(goog.userAgent.isVersionOrHigher(9)||\nb.listen(c,goog.events.EventType.DBLCLICK,this.handleDblClick),this.ieMouseEventSequenceSimulator_||(this.ieMouseEventSequenceSimulator_=new goog.ui.Control.IeMouseEventSequenceSimulator_(this),this.registerDisposable(this.ieMouseEventSequenceSimulator_)))):(b.unlisten(c,goog.events.EventType.MOUSEOVER,this.handleMouseOver).unlisten(c,goog.events.EventType.MOUSEDOWN,this.handleMouseDown).unlisten(c,goog.events.EventType.MOUSEUP,this.handleMouseUp).unlisten(c,goog.events.EventType.MOUSEOUT,this.handleMouseOut),\nthis.handleContextMenu!=goog.nullFunction&&b.unlisten(c,goog.events.EventType.CONTEXTMENU,this.handleContextMenu),goog.userAgent.IE&&(goog.userAgent.isVersionOrHigher(9)||b.unlisten(c,goog.events.EventType.DBLCLICK,this.handleDblClick),goog.dispose(this.ieMouseEventSequenceSimulator_),this.ieMouseEventSequenceSimulator_=null))};\ngoog.ui.Control.prototype.exitDocument=function(){goog.ui.Control.superClass_.exitDocument.call(this);this.keyHandler_&&this.keyHandler_.detach();this.isVisible()&&this.isEnabled()&&this.renderer_.setFocusable(this,!1)};goog.ui.Control.prototype.disposeInternal=function(){goog.ui.Control.superClass_.disposeInternal.call(this);this.keyHandler_&&(this.keyHandler_.dispose(),delete this.keyHandler_);delete this.renderer_;this.ieMouseEventSequenceSimulator_=this.extraClassNames_=this.content_=null};\ngoog.ui.Control.prototype.getContent=function(){return this.content_};goog.ui.Control.prototype.setContent=function(a){this.renderer_.setContent(this.getElement(),a);this.setContentInternal(a)};goog.ui.Control.prototype.setContentInternal=function(a){this.content_=a};goog.ui.Control.prototype.getCaption=function(){var a=this.getContent();if(!a)return\"\";a=goog.isString(a)?a:goog.isArray(a)?goog.array.map(a,goog.dom.getRawTextContent).join(\"\"):goog.dom.getTextContent(a);return goog.string.collapseBreakingSpaces(a)};\ngoog.ui.Control.prototype.setCaption=function(a){this.setContent(a)};goog.ui.Control.prototype.setRightToLeft=function(a){goog.ui.Control.superClass_.setRightToLeft.call(this,a);var b=this.getElement();b&&this.renderer_.setRightToLeft(b,a)};goog.ui.Control.prototype.isAllowTextSelection=function(){return this.allowTextSelection_};goog.ui.Control.prototype.setAllowTextSelection=function(a){this.allowTextSelection_=a;var b=this.getElement();b&&this.renderer_.setAllowTextSelection(b,a)};\ngoog.ui.Control.prototype.isVisible=function(){return this.visible_};goog.ui.Control.prototype.setVisible=function(a,b){if(b||this.visible_!=a&&this.dispatchEvent(a?goog.ui.Component.EventType.SHOW:goog.ui.Component.EventType.HIDE)){var c=this.getElement();c&&this.renderer_.setVisible(c,a);this.isEnabled()&&this.renderer_.setFocusable(this,a);this.visible_=a;return!0}return!1};goog.ui.Control.prototype.isEnabled=function(){return!this.hasState(goog.ui.Component.State.DISABLED)};\ngoog.ui.Control.prototype.isParentDisabled_=function(){var a=this.getParent();return!!a&&\"function\"==typeof a.isEnabled&&!a.isEnabled()};goog.ui.Control.prototype.setEnabled=function(a){!this.isParentDisabled_()&&this.isTransitionAllowed(goog.ui.Component.State.DISABLED,!a)&&(a||(this.setActive(!1),this.setHighlighted(!1)),this.isVisible()&&this.renderer_.setFocusable(this,a),this.setState(goog.ui.Component.State.DISABLED,!a,!0))};goog.ui.Control.prototype.isHighlighted=function(){return this.hasState(goog.ui.Component.State.HOVER)};\ngoog.ui.Control.prototype.setHighlighted=function(a){this.isTransitionAllowed(goog.ui.Component.State.HOVER,a)&&this.setState(goog.ui.Component.State.HOVER,a)};goog.ui.Control.prototype.isActive=function(){return this.hasState(goog.ui.Component.State.ACTIVE)};goog.ui.Control.prototype.setActive=function(a){this.isTransitionAllowed(goog.ui.Component.State.ACTIVE,a)&&this.setState(goog.ui.Component.State.ACTIVE,a)};goog.ui.Control.prototype.isSelected=function(){return this.hasState(goog.ui.Component.State.SELECTED)};\ngoog.ui.Control.prototype.setSelected=function(a){this.isTransitionAllowed(goog.ui.Component.State.SELECTED,a)&&this.setState(goog.ui.Component.State.SELECTED,a)};goog.ui.Control.prototype.isChecked=function(){return this.hasState(goog.ui.Component.State.CHECKED)};goog.ui.Control.prototype.setChecked=function(a){this.isTransitionAllowed(goog.ui.Component.State.CHECKED,a)&&this.setState(goog.ui.Component.State.CHECKED,a)};goog.ui.Control.prototype.isFocused=function(){return this.hasState(goog.ui.Component.State.FOCUSED)};\ngoog.ui.Control.prototype.setFocused=function(a){this.isTransitionAllowed(goog.ui.Component.State.FOCUSED,a)&&this.setState(goog.ui.Component.State.FOCUSED,a)};goog.ui.Control.prototype.isOpen=function(){return this.hasState(goog.ui.Component.State.OPENED)};goog.ui.Control.prototype.setOpen=function(a){this.isTransitionAllowed(goog.ui.Component.State.OPENED,a)&&this.setState(goog.ui.Component.State.OPENED,a)};goog.ui.Control.prototype.getState=function(){return this.state_};\ngoog.ui.Control.prototype.hasState=function(a){return!!(this.state_&a)};goog.ui.Control.prototype.setState=function(a,b,c){c||a!=goog.ui.Component.State.DISABLED?this.isSupportedState(a)&&b!=this.hasState(a)&&(this.renderer_.setState(this,a,b),this.state_=b?this.state_|a:this.state_&~a):this.setEnabled(!b)};goog.ui.Control.prototype.setStateInternal=function(a){this.state_=a};goog.ui.Control.prototype.isSupportedState=function(a){return!!(this.supportedStates_&a)};\ngoog.ui.Control.prototype.setSupportedState=function(a,b){if(this.isInDocument()&&this.hasState(a)&&!b)throw Error(goog.ui.Component.Error.ALREADY_RENDERED);!b&&this.hasState(a)&&this.setState(a,!1);this.supportedStates_=b?this.supportedStates_|a:this.supportedStates_&~a};goog.ui.Control.prototype.isAutoState=function(a){return!!(this.autoStates_&a)&&this.isSupportedState(a)};goog.ui.Control.prototype.setAutoStates=function(a,b){this.autoStates_=b?this.autoStates_|a:this.autoStates_&~a};\ngoog.ui.Control.prototype.isDispatchTransitionEvents=function(a){return!!(this.statesWithTransitionEvents_&a)&&this.isSupportedState(a)};goog.ui.Control.prototype.setDispatchTransitionEvents=function(a,b){this.statesWithTransitionEvents_=b?this.statesWithTransitionEvents_|a:this.statesWithTransitionEvents_&~a};\ngoog.ui.Control.prototype.isTransitionAllowed=function(a,b){return this.isSupportedState(a)&&this.hasState(a)!=b&&(!(this.statesWithTransitionEvents_&a)||this.dispatchEvent(goog.ui.Component.getStateTransitionEvent(a,b)))&&!this.isDisposed()};goog.ui.Control.prototype.handleMouseOver=function(a){!goog.ui.Control.isMouseEventWithinElement_(a,this.getElement())&&this.dispatchEvent(goog.ui.Component.EventType.ENTER)&&this.isEnabled()&&this.isAutoState(goog.ui.Component.State.HOVER)&&this.setHighlighted(!0)};\ngoog.ui.Control.prototype.handleMouseOut=function(a){!goog.ui.Control.isMouseEventWithinElement_(a,this.getElement())&&this.dispatchEvent(goog.ui.Component.EventType.LEAVE)&&(this.isAutoState(goog.ui.Component.State.ACTIVE)&&this.setActive(!1),this.isAutoState(goog.ui.Component.State.HOVER)&&this.setHighlighted(!1))};goog.ui.Control.prototype.handleContextMenu=goog.nullFunction;goog.ui.Control.isMouseEventWithinElement_=function(a,b){return!!a.relatedTarget&&goog.dom.contains(b,a.relatedTarget)};\ngoog.ui.Control.prototype.handleMouseDown=function(a){this.isEnabled()&&(this.isAutoState(goog.ui.Component.State.HOVER)&&this.setHighlighted(!0),a.isMouseActionButton()&&(this.isAutoState(goog.ui.Component.State.ACTIVE)&&this.setActive(!0),this.renderer_&&this.renderer_.isFocusable(this)&&this.getKeyEventTarget().focus()));!this.isAllowTextSelection()&&a.isMouseActionButton()&&a.preventDefault()};\ngoog.ui.Control.prototype.handleMouseUp=function(a){this.isEnabled()&&(this.isAutoState(goog.ui.Component.State.HOVER)&&this.setHighlighted(!0),this.isActive()&&this.performActionInternal(a)&&this.isAutoState(goog.ui.Component.State.ACTIVE)&&this.setActive(!1))};goog.ui.Control.prototype.handleDblClick=function(a){this.isEnabled()&&this.performActionInternal(a)};\ngoog.ui.Control.prototype.performActionInternal=function(a){this.isAutoState(goog.ui.Component.State.CHECKED)&&this.setChecked(!this.isChecked());this.isAutoState(goog.ui.Component.State.SELECTED)&&this.setSelected(!0);this.isAutoState(goog.ui.Component.State.OPENED)&&this.setOpen(!this.isOpen());var b=new goog.events.Event(goog.ui.Component.EventType.ACTION,this);a&&(b.altKey=a.altKey,b.ctrlKey=a.ctrlKey,b.metaKey=a.metaKey,b.shiftKey=a.shiftKey,b.platformModifierKey=a.platformModifierKey);return this.dispatchEvent(b)};\ngoog.ui.Control.prototype.handleFocus=function(a){this.isAutoState(goog.ui.Component.State.FOCUSED)&&this.setFocused(!0)};goog.ui.Control.prototype.handleBlur=function(a){this.isAutoState(goog.ui.Component.State.ACTIVE)&&this.setActive(!1);this.isAutoState(goog.ui.Component.State.FOCUSED)&&this.setFocused(!1)};goog.ui.Control.prototype.handleKeyEvent=function(a){return this.isVisible()&&this.isEnabled()&&this.handleKeyEventInternal(a)?(a.preventDefault(),a.stopPropagation(),!0):!1};\ngoog.ui.Control.prototype.handleKeyEventInternal=function(a){return a.keyCode==goog.events.KeyCodes.ENTER&&this.performActionInternal(a)};goog.ui.registry.setDefaultRenderer(goog.ui.Control,goog.ui.ControlRenderer);goog.ui.registry.setDecoratorByClassName(goog.ui.ControlRenderer.CSS_CLASS,function(){return new goog.ui.Control(null)});\ngoog.ui.Control.IeMouseEventSequenceSimulator_=function(a){goog.Disposable.call(this);this.control_=a;this.clickExpected_=!1;this.handler_=new goog.events.EventHandler(this);this.registerDisposable(this.handler_);a=this.control_.getElementStrict();this.handler_.listen(a,goog.events.EventType.MOUSEDOWN,this.handleMouseDown_).listen(a,goog.events.EventType.MOUSEUP,this.handleMouseUp_).listen(a,goog.events.EventType.CLICK,this.handleClick_)};\ngoog.inherits(goog.ui.Control.IeMouseEventSequenceSimulator_,goog.Disposable);goog.ui.Control.IeMouseEventSequenceSimulator_.SYNTHETIC_EVENTS_=!goog.userAgent.IE||goog.userAgent.isDocumentModeOrHigher(9);goog.ui.Control.IeMouseEventSequenceSimulator_.prototype.handleMouseDown_=function(){this.clickExpected_=!1};goog.ui.Control.IeMouseEventSequenceSimulator_.prototype.handleMouseUp_=function(){this.clickExpected_=!0};\ngoog.ui.Control.IeMouseEventSequenceSimulator_.makeLeftMouseEvent_=function(a,b){if(!goog.ui.Control.IeMouseEventSequenceSimulator_.SYNTHETIC_EVENTS_)return a.button=goog.events.BrowserEvent.MouseButton.LEFT,a.type=b,a;var c=document.createEvent(\"MouseEvents\");c.initMouseEvent(b,a.bubbles,a.cancelable,a.view||null,a.detail,a.screenX,a.screenY,a.clientX,a.clientY,a.ctrlKey,a.altKey,a.shiftKey,a.metaKey,goog.events.BrowserEvent.MouseButton.LEFT,a.relatedTarget||null);return c};\ngoog.ui.Control.IeMouseEventSequenceSimulator_.prototype.handleClick_=function(a){if(this.clickExpected_)this.clickExpected_=!1;else{var b=a.getBrowserEvent(),c=b.button,d=b.type,e=goog.ui.Control.IeMouseEventSequenceSimulator_.makeLeftMouseEvent_(b,goog.events.EventType.MOUSEDOWN);this.control_.handleMouseDown(new goog.events.BrowserEvent(e,a.currentTarget));e=goog.ui.Control.IeMouseEventSequenceSimulator_.makeLeftMouseEvent_(b,goog.events.EventType.MOUSEUP);this.control_.handleMouseUp(new goog.events.BrowserEvent(e,\na.currentTarget));goog.ui.Control.IeMouseEventSequenceSimulator_.SYNTHETIC_EVENTS_||(b.button=c,b.type=d)}};goog.ui.Control.IeMouseEventSequenceSimulator_.prototype.disposeInternal=function(){this.control_=null;goog.ui.Control.IeMouseEventSequenceSimulator_.superClass_.disposeInternal.call(this)};goog.iter={};goog.iter.StopIteration=\"StopIteration\"in goog.global?goog.global.StopIteration:{message:\"StopIteration\",stack:\"\"};goog.iter.Iterator=function(){};goog.iter.Iterator.prototype.next=function(){throw goog.iter.StopIteration;};goog.iter.Iterator.prototype.__iterator__=function(a){return this};\ngoog.iter.toIterator=function(a){if(a instanceof goog.iter.Iterator)return a;if(\"function\"==typeof a.__iterator__)return a.__iterator__(!1);if(goog.isArrayLike(a)){var b=0,c=new goog.iter.Iterator;c.next=function(){for(;;){if(b>=a.length)throw goog.iter.StopIteration;if(b in a)return a[b++];b++}};return c}throw Error(\"Not implemented\");};\ngoog.iter.forEach=function(a,b,c){if(goog.isArrayLike(a))try{goog.array.forEach(a,b,c)}catch(d){if(d!==goog.iter.StopIteration)throw d;}else{a=goog.iter.toIterator(a);try{for(;;)b.call(c,a.next(),void 0,a)}catch(d){if(d!==goog.iter.StopIteration)throw d;}}};goog.iter.filter=function(a,b,c){var d=goog.iter.toIterator(a);a=new goog.iter.Iterator;a.next=function(){for(;;){var a=d.next();if(b.call(c,a,void 0,d))return a}};return a};\ngoog.iter.filterFalse=function(a,b,c){return goog.iter.filter(a,goog.functions.not(b),c)};goog.iter.range=function(a,b,c){var d=0,e=a,f=c||1;1<arguments.length&&(d=a,e=b);if(0==f)throw Error(\"Range step argument must not be zero\");var g=new goog.iter.Iterator;g.next=function(){if(0<f&&d>=e||0>f&&d<=e)throw goog.iter.StopIteration;var a=d;d+=f;return a};return g};goog.iter.join=function(a,b){return goog.iter.toArray(a).join(b)};\ngoog.iter.map=function(a,b,c){var d=goog.iter.toIterator(a);a=new goog.iter.Iterator;a.next=function(){var a=d.next();return b.call(c,a,void 0,d)};return a};goog.iter.reduce=function(a,b,c,d){var e=c;goog.iter.forEach(a,function(a){e=b.call(d,e,a)});return e};goog.iter.some=function(a,b,c){a=goog.iter.toIterator(a);try{for(;;)if(b.call(c,a.next(),void 0,a))return!0}catch(d){if(d!==goog.iter.StopIteration)throw d;}return!1};\ngoog.iter.every=function(a,b,c){a=goog.iter.toIterator(a);try{for(;;)if(!b.call(c,a.next(),void 0,a))return!1}catch(d){if(d!==goog.iter.StopIteration)throw d;}return!0};goog.iter.chain=function(a){return goog.iter.chainFromIterable(arguments)};\ngoog.iter.chainFromIterable=function(a){var b=goog.iter.toIterator(a);a=new goog.iter.Iterator;var c=null;a.next=function(){for(;;){if(null==c){var a=b.next();c=goog.iter.toIterator(a)}try{return c.next()}catch(e){if(e!==goog.iter.StopIteration)throw e;c=null}}};return a};goog.iter.dropWhile=function(a,b,c){var d=goog.iter.toIterator(a);a=new goog.iter.Iterator;var e=!0;a.next=function(){for(;;){var a=d.next();if(!e||!b.call(c,a,void 0,d))return e=!1,a}};return a};\ngoog.iter.takeWhile=function(a,b,c){var d=goog.iter.toIterator(a);a=new goog.iter.Iterator;a.next=function(){var a=d.next();if(b.call(c,a,void 0,d))return a;throw goog.iter.StopIteration;};return a};goog.iter.toArray=function(a){if(goog.isArrayLike(a))return goog.array.toArray(a);a=goog.iter.toIterator(a);var b=[];goog.iter.forEach(a,function(a){b.push(a)});return b};\ngoog.iter.equals=function(a,b,c){a=goog.iter.zipLongest({},a,b);var d=c||goog.array.defaultCompareEquality;return goog.iter.every(a,function(a){return d(a[0],a[1])})};goog.iter.nextOrValue=function(a,b){try{return goog.iter.toIterator(a).next()}catch(c){if(c!=goog.iter.StopIteration)throw c;return b}};\ngoog.iter.product=function(a){if(goog.array.some(arguments,function(a){return!a.length})||!arguments.length)return new goog.iter.Iterator;var b=new goog.iter.Iterator,c=arguments,d=goog.array.repeat(0,c.length);b.next=function(){if(d){for(var a=goog.array.map(d,function(a,b){return c[b][a]}),b=d.length-1;0<=b;b--){goog.asserts.assert(d);if(d[b]<c[b].length-1){d[b]++;break}if(0==b){d=null;break}d[b]=0}return a}throw goog.iter.StopIteration;};return b};\ngoog.iter.cycle=function(a){var b=goog.iter.toIterator(a),c=[],d=0;a=new goog.iter.Iterator;var e=!1;a.next=function(){var a=null;if(!e)try{return a=b.next(),c.push(a),a}catch(g){if(g!=goog.iter.StopIteration||goog.array.isEmpty(c))throw g;e=!0}a=c[d];d=(d+1)%c.length;return a};return a};goog.iter.count=function(a,b){var c=a||0,d=goog.isDef(b)?b:1,e=new goog.iter.Iterator;e.next=function(){var a=c;c+=d;return a};return e};\ngoog.iter.repeat=function(a){var b=new goog.iter.Iterator;b.next=goog.functions.constant(a);return b};goog.iter.accumulate=function(a){var b=goog.iter.toIterator(a),c=0;a=new goog.iter.Iterator;a.next=function(){return c+=b.next()};return a};goog.iter.zip=function(a){var b=arguments,c=new goog.iter.Iterator;if(0<b.length){var d=goog.array.map(b,goog.iter.toIterator);c.next=function(){return goog.array.map(d,function(a){return a.next()})}}return c};\ngoog.iter.zipLongest=function(a,b){var c=goog.array.slice(arguments,1),d=new goog.iter.Iterator;if(0<c.length){var e=goog.array.map(c,goog.iter.toIterator);d.next=function(){var b=!1,c=goog.array.map(e,function(c){var d;try{d=c.next(),b=!0}catch(e){if(e!==goog.iter.StopIteration)throw e;d=a}return d});if(!b)throw goog.iter.StopIteration;return c}}return d};goog.iter.compress=function(a,b){var c=goog.iter.toIterator(b);return goog.iter.filter(a,function(){return!!c.next()})};\ngoog.iter.GroupByIterator_=function(a,b){this.iterator=goog.iter.toIterator(a);this.keyFunc=b||goog.functions.identity};goog.inherits(goog.iter.GroupByIterator_,goog.iter.Iterator);goog.iter.GroupByIterator_.prototype.next=function(){for(;this.currentKey==this.targetKey;)this.currentValue=this.iterator.next(),this.currentKey=this.keyFunc(this.currentValue);this.targetKey=this.currentKey;return[this.currentKey,this.groupItems_(this.targetKey)]};\ngoog.iter.GroupByIterator_.prototype.groupItems_=function(a){for(var b=[];this.currentKey==a;){b.push(this.currentValue);try{this.currentValue=this.iterator.next()}catch(c){if(c!==goog.iter.StopIteration)throw c;break}this.currentKey=this.keyFunc(this.currentValue)}return b};goog.iter.groupBy=function(a,b){return new goog.iter.GroupByIterator_(a,b)};\ngoog.iter.starMap=function(a,b,c){var d=goog.iter.toIterator(a);a=new goog.iter.Iterator;a.next=function(){var a=goog.iter.toArray(d.next());return b.apply(c,goog.array.concat(a,void 0,d))};return a};\ngoog.iter.tee=function(a,b){var c=goog.iter.toIterator(a),d=goog.isNumber(b)?b:2,e=goog.array.map(goog.array.range(d),function(){return[]}),f=function(){var a=c.next();goog.array.forEach(e,function(b){b.push(a)})};return goog.array.map(e,function(a){var b=new goog.iter.Iterator;b.next=function(){goog.array.isEmpty(a)&&f();goog.asserts.assert(!goog.array.isEmpty(a));return a.shift()};return b})};goog.iter.enumerate=function(a,b){return goog.iter.zip(goog.iter.count(b),a)};\ngoog.iter.limit=function(a,b){goog.asserts.assert(goog.math.isInt(b)&&0<=b);var c=goog.iter.toIterator(a),d=new goog.iter.Iterator,e=b;d.next=function(){if(0<e--)return c.next();throw goog.iter.StopIteration;};return d};goog.iter.consume=function(a,b){goog.asserts.assert(goog.math.isInt(b)&&0<=b);for(var c=goog.iter.toIterator(a);0<b--;)goog.iter.nextOrValue(c,null);return c};\ngoog.iter.slice=function(a,b,c){goog.asserts.assert(goog.math.isInt(b)&&0<=b);a=goog.iter.consume(a,b);goog.isNumber(c)&&(goog.asserts.assert(goog.math.isInt(c)&&c>=b),a=goog.iter.limit(a,c-b));return a};goog.iter.hasDuplicates_=function(a){var b=[];goog.array.removeDuplicates(a,b);return a.length!=b.length};goog.iter.permutations=function(a,b){var c=goog.iter.toArray(a),d=goog.isNumber(b)?b:c.length,c=goog.array.repeat(c,d),c=goog.iter.product.apply(void 0,c);return goog.iter.filter(c,function(a){return!goog.iter.hasDuplicates_(a)})};\ngoog.iter.combinations=function(a,b){function c(a){return d[a]}var d=goog.iter.toArray(a),e=goog.iter.range(d.length),e=goog.iter.permutations(e,b),f=goog.iter.filter(e,function(a){return goog.array.isSorted(a)}),e=new goog.iter.Iterator;e.next=function(){return goog.array.map(f.next(),c)};return e};\ngoog.iter.combinationsWithReplacement=function(a,b){function c(a){return d[a]}var d=goog.iter.toArray(a),e=goog.array.range(d.length),e=goog.array.repeat(e,b),e=goog.iter.product.apply(void 0,e),f=goog.iter.filter(e,function(a){return goog.array.isSorted(a)}),e=new goog.iter.Iterator;e.next=function(){return goog.array.map(f.next(),c)};return e};goog.dom.TagWalkType={START_TAG:1,OTHER:0,END_TAG:-1};goog.dom.TagIterator=function(a,b,c,d,e){this.reversed=!!b;this.node=null;this.tagType=goog.dom.TagWalkType.OTHER;this.started_=!1;this.constrained=!c;a&&this.setPosition(a,d);this.depth=void 0!=e?e:this.tagType||0;this.reversed&&(this.depth*=-1)};goog.inherits(goog.dom.TagIterator,goog.iter.Iterator);\ngoog.dom.TagIterator.prototype.setPosition=function(a,b,c){if(this.node=a)goog.isNumber(b)?this.tagType=b:this.tagType=this.node.nodeType!=goog.dom.NodeType.ELEMENT?goog.dom.TagWalkType.OTHER:this.reversed?goog.dom.TagWalkType.END_TAG:goog.dom.TagWalkType.START_TAG;goog.isNumber(c)&&(this.depth=c)};goog.dom.TagIterator.prototype.copyFrom=function(a){this.node=a.node;this.tagType=a.tagType;this.depth=a.depth;this.reversed=a.reversed;this.constrained=a.constrained};\ngoog.dom.TagIterator.prototype.clone=function(){return new goog.dom.TagIterator(this.node,this.reversed,!this.constrained,this.tagType,this.depth)};goog.dom.TagIterator.prototype.skipTag=function(){var a=this.reversed?goog.dom.TagWalkType.END_TAG:goog.dom.TagWalkType.START_TAG;this.tagType==a&&(this.tagType=-1*a,this.depth+=this.tagType*(this.reversed?-1:1))};\ngoog.dom.TagIterator.prototype.restartTag=function(){var a=this.reversed?goog.dom.TagWalkType.START_TAG:goog.dom.TagWalkType.END_TAG;this.tagType==a&&(this.tagType=-1*a,this.depth+=this.tagType*(this.reversed?-1:1))};\ngoog.dom.TagIterator.prototype.next=function(){var a;if(this.started_){if(!this.node||this.constrained&&0==this.depth)throw goog.iter.StopIteration;a=this.node;var b=this.reversed?goog.dom.TagWalkType.END_TAG:goog.dom.TagWalkType.START_TAG;if(this.tagType==b){var c=this.reversed?a.lastChild:a.firstChild;c?this.setPosition(c):this.setPosition(a,-1*b)}else(c=this.reversed?a.previousSibling:a.nextSibling)?this.setPosition(c):this.setPosition(a.parentNode,-1*b);this.depth+=this.tagType*(this.reversed?\n-1:1)}else this.started_=!0;a=this.node;if(!this.node)throw goog.iter.StopIteration;return a};goog.dom.TagIterator.prototype.isStarted=function(){return this.started_};goog.dom.TagIterator.prototype.isStartTag=function(){return this.tagType==goog.dom.TagWalkType.START_TAG};goog.dom.TagIterator.prototype.isEndTag=function(){return this.tagType==goog.dom.TagWalkType.END_TAG};goog.dom.TagIterator.prototype.isNonElement=function(){return this.tagType==goog.dom.TagWalkType.OTHER};\ngoog.dom.TagIterator.prototype.equals=function(a){return a.node==this.node&&(!this.node||a.tagType==this.tagType)};goog.dom.TagIterator.prototype.splice=function(a){var b=this.node;this.restartTag();this.reversed=!this.reversed;goog.dom.TagIterator.prototype.next.call(this);this.reversed=!this.reversed;for(var c=goog.isArrayLike(arguments[0])?arguments[0]:arguments,d=c.length-1;0<=d;d--)goog.dom.insertSiblingAfter(c[d],b);goog.dom.removeNode(b)};goog.dom.NodeIterator=function(a,b,c,d){goog.dom.TagIterator.call(this,a,b,c,null,d)};goog.inherits(goog.dom.NodeIterator,goog.dom.TagIterator);goog.dom.NodeIterator.prototype.next=function(){do goog.dom.NodeIterator.superClass_.next.call(this);while(this.isEndTag());return this.node};goog.ui.PaletteRenderer=function(){goog.ui.ControlRenderer.call(this)};goog.inherits(goog.ui.PaletteRenderer,goog.ui.ControlRenderer);goog.addSingletonGetter(goog.ui.PaletteRenderer);goog.ui.PaletteRenderer.cellId_=0;goog.ui.PaletteRenderer.CSS_CLASS=\"goog-palette\";\ngoog.ui.PaletteRenderer.prototype.createDom=function(a){var b=this.getClassNames(a);a=a.getDomHelper().createDom(\"DIV\",b?b.join(\" \"):null,this.createGrid(a.getContent(),a.getSize(),a.getDomHelper()));goog.a11y.aria.setRole(a,goog.a11y.aria.Role.GRID);return a};goog.ui.PaletteRenderer.prototype.createGrid=function(a,b,c){for(var d=[],e=0,f=0;e<b.height;e++){for(var g=[],h=0;h<b.width;h++){var k=a&&a[f++];g.push(this.createCell(k,c))}d.push(this.createRow(g,c))}return this.createTable(d,c)};\ngoog.ui.PaletteRenderer.prototype.createTable=function(a,b){var c=b.createDom(\"TABLE\",this.getCssClass()+\"-table\",b.createDom(\"TBODY\",this.getCssClass()+\"-body\",a));c.cellSpacing=0;c.cellPadding=0;return c};goog.ui.PaletteRenderer.prototype.createRow=function(a,b){var c=b.createDom(\"TR\",this.getCssClass()+\"-row\",a);goog.a11y.aria.setRole(c,goog.a11y.aria.Role.ROW);return c};\ngoog.ui.PaletteRenderer.prototype.createCell=function(a,b){var c=b.createDom(\"TD\",{\"class\":this.getCssClass()+\"-cell\",id:this.getCssClass()+\"-cell-\"+goog.ui.PaletteRenderer.cellId_++},a);goog.a11y.aria.setRole(c,goog.a11y.aria.Role.GRIDCELL);goog.a11y.aria.setState(c,goog.a11y.aria.State.SELECTED,!1);if(!goog.dom.getTextContent(c)&&!goog.a11y.aria.getLabel(c)){var d=this.findAriaLabelForCell_(c);d&&goog.a11y.aria.setLabel(c,d)}return c};\ngoog.ui.PaletteRenderer.prototype.findAriaLabelForCell_=function(a){a=new goog.dom.NodeIterator(a);for(var b=\"\",c;!b&&(c=goog.iter.nextOrValue(a,null));)c.nodeType==goog.dom.NodeType.ELEMENT&&(b=goog.a11y.aria.getLabel(c)||c.title);return b};goog.ui.PaletteRenderer.prototype.canDecorate=function(a){return!1};goog.ui.PaletteRenderer.prototype.decorate=function(a,b){return null};\ngoog.ui.PaletteRenderer.prototype.setContent=function(a,b){if(a){var c=goog.dom.getElementsByTagNameAndClass(\"TBODY\",this.getCssClass()+\"-body\",a)[0];if(c){var d=0;goog.array.forEach(c.rows,function(a){goog.array.forEach(a.cells,function(a){goog.dom.removeChildren(a);if(b){var c=b[d++];c&&goog.dom.appendChild(a,c)}})});if(d<b.length){for(var e=[],f=goog.dom.getDomHelper(a),g=c.rows[0].cells.length;d<b.length;){var h=b[d++];e.push(this.createCell(h,f));e.length==g&&(h=this.createRow(e,f),goog.dom.appendChild(c,\nh),e.length=0)}if(0<e.length){for(;e.length<g;)e.push(this.createCell(\"\",f));h=this.createRow(e,f);goog.dom.appendChild(c,h)}}}goog.style.setUnselectable(a,!0,goog.userAgent.GECKO)}};goog.ui.PaletteRenderer.prototype.getContainingItem=function(a,b){for(var c=a.getElement();b&&b.nodeType==goog.dom.NodeType.ELEMENT&&b!=c;){if(\"TD\"==b.tagName&&goog.dom.classlist.contains(b,this.getCssClass()+\"-cell\"))return b.firstChild;b=b.parentNode}return null};\ngoog.ui.PaletteRenderer.prototype.highlightCell=function(a,b,c){b&&(b=this.getCellForItem(b),goog.asserts.assert(b),goog.dom.classlist.enable(b,this.getCssClass()+\"-cell-hover\",c),c?goog.a11y.aria.setState(a.getElementStrict(),goog.a11y.aria.State.ACTIVEDESCENDANT,b.id):b.id==goog.a11y.aria.getState(a.getElementStrict(),goog.a11y.aria.State.ACTIVEDESCENDANT)&&goog.a11y.aria.removeState(a.getElementStrict(),goog.a11y.aria.State.ACTIVEDESCENDANT))};\ngoog.ui.PaletteRenderer.prototype.getCellForItem=function(a){return a?a.parentNode:null};goog.ui.PaletteRenderer.prototype.selectCell=function(a,b,c){b&&(a=b.parentNode,goog.dom.classlist.enable(a,this.getCssClass()+\"-cell-selected\",c),goog.a11y.aria.setState(a,goog.a11y.aria.State.SELECTED,c))};goog.ui.PaletteRenderer.prototype.getCssClass=function(){return goog.ui.PaletteRenderer.CSS_CLASS};goog.ui.SelectionModel=function(a){goog.events.EventTarget.call(this);this.items_=[];this.addItems(a)};goog.inherits(goog.ui.SelectionModel,goog.events.EventTarget);goog.tagUnsealableClass(goog.ui.SelectionModel);goog.ui.SelectionModel.prototype.selectedItem_=null;goog.ui.SelectionModel.prototype.selectionHandler_=null;goog.ui.SelectionModel.prototype.getSelectionHandler=function(){return this.selectionHandler_};\ngoog.ui.SelectionModel.prototype.setSelectionHandler=function(a){this.selectionHandler_=a};goog.ui.SelectionModel.prototype.getItemCount=function(){return this.items_.length};goog.ui.SelectionModel.prototype.indexOfItem=function(a){return a?goog.array.indexOf(this.items_,a):-1};goog.ui.SelectionModel.prototype.getFirst=function(){return this.items_[0]};goog.ui.SelectionModel.prototype.getLast=function(){return this.items_[this.items_.length-1]};\ngoog.ui.SelectionModel.prototype.getItemAt=function(a){return this.items_[a]||null};goog.ui.SelectionModel.prototype.addItems=function(a){a&&(goog.array.forEach(a,function(a){this.selectItem_(a,!1)},this),goog.array.extend(this.items_,a))};goog.ui.SelectionModel.prototype.addItem=function(a){this.addItemAt(a,this.getItemCount())};goog.ui.SelectionModel.prototype.addItemAt=function(a,b){a&&(this.selectItem_(a,!1),goog.array.insertAt(this.items_,a,b))};\ngoog.ui.SelectionModel.prototype.removeItem=function(a){a&&goog.array.remove(this.items_,a)&&a==this.selectedItem_&&(this.selectedItem_=null,this.dispatchEvent(goog.events.EventType.SELECT))};goog.ui.SelectionModel.prototype.removeItemAt=function(a){this.removeItem(this.getItemAt(a))};goog.ui.SelectionModel.prototype.getSelectedItem=function(){return this.selectedItem_};goog.ui.SelectionModel.prototype.getItems=function(){return goog.array.clone(this.items_)};\ngoog.ui.SelectionModel.prototype.setSelectedItem=function(a){a!=this.selectedItem_&&(this.selectItem_(this.selectedItem_,!1),this.selectedItem_=a,this.selectItem_(a,!0));this.dispatchEvent(goog.events.EventType.SELECT)};goog.ui.SelectionModel.prototype.getSelectedIndex=function(){return this.indexOfItem(this.selectedItem_)};goog.ui.SelectionModel.prototype.setSelectedIndex=function(a){this.setSelectedItem(this.getItemAt(a))};\ngoog.ui.SelectionModel.prototype.clear=function(){goog.array.clear(this.items_);this.selectedItem_=null};goog.ui.SelectionModel.prototype.disposeInternal=function(){goog.ui.SelectionModel.superClass_.disposeInternal.call(this);delete this.items_;this.selectedItem_=null};goog.ui.SelectionModel.prototype.selectItem_=function(a,b){a&&(\"function\"==typeof this.selectionHandler_?this.selectionHandler_(a,b):\"function\"==typeof a.setSelected&&a.setSelected(b))};goog.ui.Palette=function(a,b,c){goog.ui.Control.call(this,a,b||goog.ui.PaletteRenderer.getInstance(),c);this.setAutoStates(goog.ui.Component.State.CHECKED|goog.ui.Component.State.SELECTED|goog.ui.Component.State.OPENED,!1);this.currentCellControl_=new goog.ui.Palette.CurrentCell_;this.currentCellControl_.setParentEventTarget(this);this.lastHighlightedIndex_=-1};goog.inherits(goog.ui.Palette,goog.ui.Control);goog.tagUnsealableClass(goog.ui.Palette);goog.ui.Palette.EventType={AFTER_HIGHLIGHT:goog.events.getUniqueId(\"afterhighlight\")};\ngoog.ui.Palette.prototype.size_=null;goog.ui.Palette.prototype.highlightedIndex_=-1;goog.ui.Palette.prototype.selectionModel_=null;goog.ui.Palette.prototype.disposeInternal=function(){goog.ui.Palette.superClass_.disposeInternal.call(this);this.selectionModel_&&(this.selectionModel_.dispose(),this.selectionModel_=null);this.size_=null;this.currentCellControl_.dispose()};\ngoog.ui.Palette.prototype.setContentInternal=function(a){goog.ui.Palette.superClass_.setContentInternal.call(this,a);this.adjustSize_();this.selectionModel_?(this.selectionModel_.clear(),this.selectionModel_.addItems(a)):(this.selectionModel_=new goog.ui.SelectionModel(a),this.selectionModel_.setSelectionHandler(goog.bind(this.selectItem_,this)),this.getHandler().listen(this.selectionModel_,goog.events.EventType.SELECT,this.handleSelectionChange));this.highlightedIndex_=-1};\ngoog.ui.Palette.prototype.getCaption=function(){return\"\"};goog.ui.Palette.prototype.setCaption=function(a){};goog.ui.Palette.prototype.handleMouseOver=function(a){goog.ui.Palette.superClass_.handleMouseOver.call(this,a);var b=this.getRenderer().getContainingItem(this,a.target);b&&a.relatedTarget&&goog.dom.contains(b,a.relatedTarget)||b!=this.getHighlightedItem()&&this.setHighlightedItem(b)};\ngoog.ui.Palette.prototype.handleMouseDown=function(a){goog.ui.Palette.superClass_.handleMouseDown.call(this,a);this.isActive()&&(a=this.getRenderer().getContainingItem(this,a.target),a!=this.getHighlightedItem()&&this.setHighlightedItem(a))};goog.ui.Palette.prototype.performActionInternal=function(a){var b=this.getHighlightedItem();return b?(a&&this.shouldSelectHighlightedItem_(a)&&this.setSelectedItem(b),goog.ui.Palette.superClass_.performActionInternal.call(this,a)):!1};\ngoog.ui.Palette.prototype.shouldSelectHighlightedItem_=function(a){return this.getSelectedItem()?\"mouseup\"!=a.type?!0:!!this.getRenderer().getContainingItem(this,a.target):!0};\ngoog.ui.Palette.prototype.handleKeyEvent=function(a){var b=this.getContent(),b=b?b.length:0,c=this.size_.width;if(0==b||!this.isEnabled())return!1;if(a.keyCode==goog.events.KeyCodes.ENTER||a.keyCode==goog.events.KeyCodes.SPACE)return this.performActionInternal(a);if(a.keyCode==goog.events.KeyCodes.HOME)return this.setHighlightedIndex(0),!0;if(a.keyCode==goog.events.KeyCodes.END)return this.setHighlightedIndex(b-1),!0;var d=0>this.highlightedIndex_?this.getSelectedIndex():this.highlightedIndex_;switch(a.keyCode){case goog.events.KeyCodes.LEFT:if(-1==\nd||0==d)d=b;this.setHighlightedIndex(d-1);a.preventDefault();return!0;case goog.events.KeyCodes.RIGHT:return d==b-1&&(d=-1),this.setHighlightedIndex(d+1),a.preventDefault(),!0;case goog.events.KeyCodes.UP:-1==d&&(d=b+c-1);if(d>=c)return this.setHighlightedIndex(d-c),a.preventDefault(),!0;break;case goog.events.KeyCodes.DOWN:if(-1==d&&(d=-c),d<b-c)return this.setHighlightedIndex(d+c),a.preventDefault(),!0}return!1};goog.ui.Palette.prototype.handleSelectionChange=function(a){};\ngoog.ui.Palette.prototype.getSize=function(){return this.size_};goog.ui.Palette.prototype.setSize=function(a,b){if(this.getElement())throw Error(goog.ui.Component.Error.ALREADY_RENDERED);this.size_=goog.isNumber(a)?new goog.math.Size(a,b):a;this.adjustSize_()};goog.ui.Palette.prototype.getHighlightedIndex=function(){return this.highlightedIndex_};goog.ui.Palette.prototype.getHighlightedItem=function(){var a=this.getContent();return a&&a[this.highlightedIndex_]};\ngoog.ui.Palette.prototype.getHighlightedCellElement_=function(){return this.getRenderer().getCellForItem(this.getHighlightedItem())};goog.ui.Palette.prototype.setHighlightedIndex=function(a){a!=this.highlightedIndex_&&(this.highlightIndex_(this.highlightedIndex_,!1),this.lastHighlightedIndex_=this.highlightedIndex_,this.highlightedIndex_=a,this.highlightIndex_(a,!0),this.dispatchEvent(goog.ui.Palette.EventType.AFTER_HIGHLIGHT))};\ngoog.ui.Palette.prototype.setHighlightedItem=function(a){var b=this.getContent();this.setHighlightedIndex(b&&a?goog.array.indexOf(b,a):-1)};goog.ui.Palette.prototype.getSelectedIndex=function(){return this.selectionModel_?this.selectionModel_.getSelectedIndex():-1};goog.ui.Palette.prototype.getSelectedItem=function(){return this.selectionModel_?this.selectionModel_.getSelectedItem():null};goog.ui.Palette.prototype.setSelectedIndex=function(a){this.selectionModel_&&this.selectionModel_.setSelectedIndex(a)};\ngoog.ui.Palette.prototype.setSelectedItem=function(a){this.selectionModel_&&this.selectionModel_.setSelectedItem(a)};goog.ui.Palette.prototype.highlightIndex_=function(a,b){if(this.getElement()){var c=this.getContent();if(c&&0<=a&&a<c.length){var d=this.getHighlightedCellElement_();this.currentCellControl_.getElement()!=d&&this.currentCellControl_.setElementInternal(d);this.currentCellControl_.tryHighlight(b)&&this.getRenderer().highlightCell(this,c[a],b)}}};\ngoog.ui.Palette.prototype.setHighlighted=function(a){a&&-1==this.highlightedIndex_?this.setHighlightedIndex(-1<this.lastHighlightedIndex_?this.lastHighlightedIndex_:0):a||this.setHighlightedIndex(-1);goog.ui.Palette.superClass_.setHighlighted.call(this,a)};goog.ui.Palette.prototype.selectItem_=function(a,b){this.getElement()&&this.getRenderer().selectCell(this,a,b)};\ngoog.ui.Palette.prototype.adjustSize_=function(){var a=this.getContent();if(a)if(this.size_&&this.size_.width){if(a=Math.ceil(a.length/this.size_.width),!goog.isNumber(this.size_.height)||this.size_.height<a)this.size_.height=a}else a=Math.ceil(Math.sqrt(a.length)),this.size_=new goog.math.Size(a,a);else this.size_=new goog.math.Size(0,0)};goog.ui.Palette.CurrentCell_=function(){goog.ui.Control.call(this,null);this.setDispatchTransitionEvents(goog.ui.Component.State.HOVER,!0)};\ngoog.inherits(goog.ui.Palette.CurrentCell_,goog.ui.Control);goog.ui.Palette.CurrentCell_.prototype.tryHighlight=function(a){this.setHighlighted(a);return this.isHighlighted()==a};goog.ui.ColorPalette=function(a,b,c){this.colors_=a||[];goog.ui.Palette.call(this,null,b||goog.ui.PaletteRenderer.getInstance(),c);this.setColors(this.colors_)};goog.inherits(goog.ui.ColorPalette,goog.ui.Palette);goog.tagUnsealableClass(goog.ui.ColorPalette);goog.ui.ColorPalette.prototype.normalizedColors_=null;goog.ui.ColorPalette.prototype.labels_=null;goog.ui.ColorPalette.prototype.getColors=function(){return this.colors_};\ngoog.ui.ColorPalette.prototype.setColors=function(a,b){this.colors_=a;this.labels_=b||null;this.normalizedColors_=null;this.setContent(this.createColorNodes())};goog.ui.ColorPalette.prototype.getSelectedColor=function(){var a=this.getSelectedItem();return a?(a=goog.style.getStyle(a,\"background-color\"),goog.ui.ColorPalette.parseColor_(a)):null};\ngoog.ui.ColorPalette.prototype.setSelectedColor=function(a){a=goog.ui.ColorPalette.parseColor_(a);this.normalizedColors_||(this.normalizedColors_=goog.array.map(this.colors_,function(a){return goog.ui.ColorPalette.parseColor_(a)}));this.setSelectedIndex(a?goog.array.indexOf(this.normalizedColors_,a):-1)};\ngoog.ui.ColorPalette.prototype.createColorNodes=function(){return goog.array.map(this.colors_,function(a,b){var c=this.getDomHelper().createDom(\"DIV\",{\"class\":this.getRenderer().getCssClass()+\"-colorswatch\",style:\"background-color:\"+a});c.title=this.labels_&&this.labels_[b]?this.labels_[b]:\"#\"==a.charAt(0)?\"RGB (\"+goog.color.hexToRgb(a).join(\", \")+\")\":a;return c},this)};goog.ui.ColorPalette.parseColor_=function(a){if(a)try{return goog.color.parse(a).hex}catch(b){}return null};goog.ui.ColorPicker=function(a,b){goog.ui.Component.call(this,a);this.colorPalette_=b||null;this.getHandler().listen(this,goog.ui.Component.EventType.ACTION,this.onColorPaletteAction_)};goog.inherits(goog.ui.ColorPicker,goog.ui.Component);goog.ui.ColorPicker.DEFAULT_NUM_COLS=5;goog.ui.ColorPicker.EventType={CHANGE:\"change\"};goog.ui.ColorPicker.prototype.focusable_=!0;goog.ui.ColorPicker.prototype.getColors=function(){return this.colorPalette_?this.colorPalette_.getColors():null};\ngoog.ui.ColorPicker.prototype.setColors=function(a){this.colorPalette_?this.colorPalette_.setColors(a):this.createColorPalette_(a)};goog.ui.ColorPicker.prototype.addColors=function(a){this.setColors(a)};goog.ui.ColorPicker.prototype.setSize=function(a){this.colorPalette_||this.createColorPalette_([]);this.colorPalette_.setSize(a)};goog.ui.ColorPicker.prototype.getSize=function(){return this.colorPalette_?this.colorPalette_.getSize():null};goog.ui.ColorPicker.prototype.setColumnCount=function(a){this.setSize(a)};\ngoog.ui.ColorPicker.prototype.getSelectedIndex=function(){return this.colorPalette_?this.colorPalette_.getSelectedIndex():-1};goog.ui.ColorPicker.prototype.setSelectedIndex=function(a){this.colorPalette_&&this.colorPalette_.setSelectedIndex(a)};goog.ui.ColorPicker.prototype.getSelectedColor=function(){return this.colorPalette_?this.colorPalette_.getSelectedColor():null};goog.ui.ColorPicker.prototype.setSelectedColor=function(a){this.colorPalette_&&this.colorPalette_.setSelectedColor(a)};\ngoog.ui.ColorPicker.prototype.isFocusable=function(){return this.focusable_};goog.ui.ColorPicker.prototype.setFocusable=function(a){this.focusable_=a;this.colorPalette_&&this.colorPalette_.setSupportedState(goog.ui.Component.State.FOCUSED,a)};goog.ui.ColorPicker.prototype.canDecorate=function(a){return!1};\ngoog.ui.ColorPicker.prototype.enterDocument=function(){goog.ui.ColorPicker.superClass_.enterDocument.call(this);this.colorPalette_&&this.colorPalette_.render(this.getElement());this.getElement().unselectable=\"on\"};goog.ui.ColorPicker.prototype.disposeInternal=function(){goog.ui.ColorPicker.superClass_.disposeInternal.call(this);this.colorPalette_&&(this.colorPalette_.dispose(),this.colorPalette_=null)};goog.ui.ColorPicker.prototype.focus=function(){this.colorPalette_&&this.colorPalette_.getElement().focus()};\ngoog.ui.ColorPicker.prototype.onColorPaletteAction_=function(a){a.stopPropagation();this.dispatchEvent(goog.ui.ColorPicker.EventType.CHANGE)};goog.ui.ColorPicker.prototype.createColorPalette_=function(a){a=new goog.ui.ColorPalette(a,null,this.getDomHelper());a.setSize(goog.ui.ColorPicker.DEFAULT_NUM_COLS);a.setSupportedState(goog.ui.Component.State.FOCUSED,this.focusable_);this.addChild(a);this.colorPalette_=a;this.isInDocument()&&this.colorPalette_.render(this.getElement())};\ngoog.ui.ColorPicker.createSimpleColorGrid=function(a){a=new goog.ui.ColorPicker(a);a.setSize(7);a.setColors(goog.ui.ColorPicker.SIMPLE_GRID_COLORS);return a};goog.ui.ColorPicker.SIMPLE_GRID_COLORS=\"#ffffff #cccccc #c0c0c0 #999999 #666666 #333333 #000000 #ffcccc #ff6666 #ff0000 #cc0000 #990000 #660000 #330000 #ffcc99 #ff9966 #ff9900 #ff6600 #cc6600 #993300 #663300 #ffff99 #ffff66 #ffcc66 #ffcc33 #cc9933 #996633 #663333 #ffffcc #ffff33 #ffff00 #ffcc00 #999900 #666600 #333300 #99ff99 #66ff99 #33ff33 #33cc00 #009900 #006600 #003300 #99ffff #33ffff #66cccc #00cccc #339999 #336666 #003333 #ccffff #66ffff #33ccff #3366ff #3333ff #000099 #000066 #ccccff #9999ff #6666cc #6633ff #6600cc #333399 #330099 #ffccff #ff99ff #cc66cc #cc33cc #993399 #663366 #330033\".split(\" \");goog.events.FocusHandler=function(a){goog.events.EventTarget.call(this);this.element_=a;a=goog.userAgent.IE?\"focusout\":\"blur\";this.listenKeyIn_=goog.events.listen(this.element_,goog.userAgent.IE?\"focusin\":\"focus\",this,!goog.userAgent.IE);this.listenKeyOut_=goog.events.listen(this.element_,a,this,!goog.userAgent.IE)};goog.inherits(goog.events.FocusHandler,goog.events.EventTarget);goog.events.FocusHandler.EventType={FOCUSIN:\"focusin\",FOCUSOUT:\"focusout\"};\ngoog.events.FocusHandler.prototype.handleEvent=function(a){var b=a.getBrowserEvent(),b=new goog.events.BrowserEvent(b);b.type=\"focusin\"==a.type||\"focus\"==a.type?goog.events.FocusHandler.EventType.FOCUSIN:goog.events.FocusHandler.EventType.FOCUSOUT;this.dispatchEvent(b)};goog.events.FocusHandler.prototype.disposeInternal=function(){goog.events.FocusHandler.superClass_.disposeInternal.call(this);goog.events.unlistenByKey(this.listenKeyIn_);goog.events.unlistenByKey(this.listenKeyOut_);delete this.element_};goog.structs={};goog.structs.getCount=function(a){return a.getCount&&\"function\"==typeof a.getCount?a.getCount():goog.isArrayLike(a)||goog.isString(a)?a.length:goog.object.getCount(a)};goog.structs.getValues=function(a){if(a.getValues&&\"function\"==typeof a.getValues)return a.getValues();if(goog.isString(a))return a.split(\"\");if(goog.isArrayLike(a)){for(var b=[],c=a.length,d=0;d<c;d++)b.push(a[d]);return b}return goog.object.getValues(a)};\ngoog.structs.getKeys=function(a){if(a.getKeys&&\"function\"==typeof a.getKeys)return a.getKeys();if(!a.getValues||\"function\"!=typeof a.getValues){if(goog.isArrayLike(a)||goog.isString(a)){var b=[];a=a.length;for(var c=0;c<a;c++)b.push(c);return b}return goog.object.getKeys(a)}};\ngoog.structs.contains=function(a,b){return a.contains&&\"function\"==typeof a.contains?a.contains(b):a.containsValue&&\"function\"==typeof a.containsValue?a.containsValue(b):goog.isArrayLike(a)||goog.isString(a)?goog.array.contains(a,b):goog.object.containsValue(a,b)};goog.structs.isEmpty=function(a){return a.isEmpty&&\"function\"==typeof a.isEmpty?a.isEmpty():goog.isArrayLike(a)||goog.isString(a)?goog.array.isEmpty(a):goog.object.isEmpty(a)};\ngoog.structs.clear=function(a){a.clear&&\"function\"==typeof a.clear?a.clear():goog.isArrayLike(a)?goog.array.clear(a):goog.object.clear(a)};goog.structs.forEach=function(a,b,c){if(a.forEach&&\"function\"==typeof a.forEach)a.forEach(b,c);else if(goog.isArrayLike(a)||goog.isString(a))goog.array.forEach(a,b,c);else for(var d=goog.structs.getKeys(a),e=goog.structs.getValues(a),f=e.length,g=0;g<f;g++)b.call(c,e[g],d&&d[g],a)};\ngoog.structs.filter=function(a,b,c){if(\"function\"==typeof a.filter)return a.filter(b,c);if(goog.isArrayLike(a)||goog.isString(a))return goog.array.filter(a,b,c);var d,e=goog.structs.getKeys(a),f=goog.structs.getValues(a),g=f.length;if(e){d={};for(var h=0;h<g;h++)b.call(c,f[h],e[h],a)&&(d[e[h]]=f[h])}else for(d=[],h=0;h<g;h++)b.call(c,f[h],void 0,a)&&d.push(f[h]);return d};\ngoog.structs.map=function(a,b,c){if(\"function\"==typeof a.map)return a.map(b,c);if(goog.isArrayLike(a)||goog.isString(a))return goog.array.map(a,b,c);var d,e=goog.structs.getKeys(a),f=goog.structs.getValues(a),g=f.length;if(e){d={};for(var h=0;h<g;h++)d[e[h]]=b.call(c,f[h],e[h],a)}else for(d=[],h=0;h<g;h++)d[h]=b.call(c,f[h],void 0,a);return d};\ngoog.structs.some=function(a,b,c){if(\"function\"==typeof a.some)return a.some(b,c);if(goog.isArrayLike(a)||goog.isString(a))return goog.array.some(a,b,c);for(var d=goog.structs.getKeys(a),e=goog.structs.getValues(a),f=e.length,g=0;g<f;g++)if(b.call(c,e[g],d&&d[g],a))return!0;return!1};\ngoog.structs.every=function(a,b,c){if(\"function\"==typeof a.every)return a.every(b,c);if(goog.isArrayLike(a)||goog.isString(a))return goog.array.every(a,b,c);for(var d=goog.structs.getKeys(a),e=goog.structs.getValues(a),f=e.length,g=0;g<f;g++)if(!b.call(c,e[g],d&&d[g],a))return!1;return!0};goog.structs.Collection=function(){};goog.structs.Map=function(a,b){this.map_={};this.keys_=[];this.version_=this.count_=0;var c=arguments.length;if(1<c){if(c%2)throw Error(\"Uneven number of arguments\");for(var d=0;d<c;d+=2)this.set(arguments[d],arguments[d+1])}else a&&this.addAll(a)};goog.structs.Map.prototype.getCount=function(){return this.count_};goog.structs.Map.prototype.getValues=function(){this.cleanupKeysArray_();for(var a=[],b=0;b<this.keys_.length;b++)a.push(this.map_[this.keys_[b]]);return a};\ngoog.structs.Map.prototype.getKeys=function(){this.cleanupKeysArray_();return this.keys_.concat()};goog.structs.Map.prototype.containsKey=function(a){return goog.structs.Map.hasKey_(this.map_,a)};goog.structs.Map.prototype.containsValue=function(a){for(var b=0;b<this.keys_.length;b++){var c=this.keys_[b];if(goog.structs.Map.hasKey_(this.map_,c)&&this.map_[c]==a)return!0}return!1};\ngoog.structs.Map.prototype.equals=function(a,b){if(this===a)return!0;if(this.count_!=a.getCount())return!1;var c=b||goog.structs.Map.defaultEquals;this.cleanupKeysArray_();for(var d,e=0;d=this.keys_[e];e++)if(!c(this.get(d),a.get(d)))return!1;return!0};goog.structs.Map.defaultEquals=function(a,b){return a===b};goog.structs.Map.prototype.isEmpty=function(){return 0==this.count_};goog.structs.Map.prototype.clear=function(){this.map_={};this.version_=this.count_=this.keys_.length=0};\ngoog.structs.Map.prototype.remove=function(a){return goog.structs.Map.hasKey_(this.map_,a)?(delete this.map_[a],this.count_--,this.version_++,this.keys_.length>2*this.count_&&this.cleanupKeysArray_(),!0):!1};\ngoog.structs.Map.prototype.cleanupKeysArray_=function(){if(this.count_!=this.keys_.length){for(var a=0,b=0;a<this.keys_.length;){var c=this.keys_[a];goog.structs.Map.hasKey_(this.map_,c)&&(this.keys_[b++]=c);a++}this.keys_.length=b}if(this.count_!=this.keys_.length){for(var d={},b=a=0;a<this.keys_.length;)c=this.keys_[a],goog.structs.Map.hasKey_(d,c)||(this.keys_[b++]=c,d[c]=1),a++;this.keys_.length=b}};\ngoog.structs.Map.prototype.get=function(a,b){return goog.structs.Map.hasKey_(this.map_,a)?this.map_[a]:b};goog.structs.Map.prototype.set=function(a,b){goog.structs.Map.hasKey_(this.map_,a)||(this.count_++,this.keys_.push(a),this.version_++);this.map_[a]=b};goog.structs.Map.prototype.addAll=function(a){var b;a instanceof goog.structs.Map?(b=a.getKeys(),a=a.getValues()):(b=goog.object.getKeys(a),a=goog.object.getValues(a));for(var c=0;c<b.length;c++)this.set(b[c],a[c])};\ngoog.structs.Map.prototype.forEach=function(a,b){for(var c=this.getKeys(),d=0;d<c.length;d++){var e=c[d],f=this.get(e);a.call(b,f,e,this)}};goog.structs.Map.prototype.clone=function(){return new goog.structs.Map(this)};goog.structs.Map.prototype.transpose=function(){for(var a=new goog.structs.Map,b=0;b<this.keys_.length;b++){var c=this.keys_[b];a.set(this.map_[c],c)}return a};\ngoog.structs.Map.prototype.toObject=function(){this.cleanupKeysArray_();for(var a={},b=0;b<this.keys_.length;b++){var c=this.keys_[b];a[c]=this.map_[c]}return a};goog.structs.Map.prototype.getKeyIterator=function(){return this.__iterator__(!0)};goog.structs.Map.prototype.getValueIterator=function(){return this.__iterator__(!1)};\ngoog.structs.Map.prototype.__iterator__=function(a){this.cleanupKeysArray_();var b=0,c=this.version_,d=this,e=new goog.iter.Iterator;e.next=function(){if(c!=d.version_)throw Error(\"The map has changed since the iterator was created\");if(b>=d.keys_.length)throw goog.iter.StopIteration;var e=d.keys_[b++];return a?e:d.map_[e]};return e};goog.structs.Map.hasKey_=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};goog.structs.Set=function(a){this.map_=new goog.structs.Map;a&&this.addAll(a)};goog.structs.Set.getKey_=function(a){var b=typeof a;return\"object\"==b&&a||\"function\"==b?\"o\"+goog.getUid(a):b.substr(0,1)+a};goog.structs.Set.prototype.getCount=function(){return this.map_.getCount()};goog.structs.Set.prototype.add=function(a){this.map_.set(goog.structs.Set.getKey_(a),a)};goog.structs.Set.prototype.addAll=function(a){a=goog.structs.getValues(a);for(var b=a.length,c=0;c<b;c++)this.add(a[c])};\ngoog.structs.Set.prototype.removeAll=function(a){a=goog.structs.getValues(a);for(var b=a.length,c=0;c<b;c++)this.remove(a[c])};goog.structs.Set.prototype.remove=function(a){return this.map_.remove(goog.structs.Set.getKey_(a))};goog.structs.Set.prototype.clear=function(){this.map_.clear()};goog.structs.Set.prototype.isEmpty=function(){return this.map_.isEmpty()};goog.structs.Set.prototype.contains=function(a){return this.map_.containsKey(goog.structs.Set.getKey_(a))};\ngoog.structs.Set.prototype.containsAll=function(a){return goog.structs.every(a,this.contains,this)};goog.structs.Set.prototype.intersection=function(a){var b=new goog.structs.Set;a=goog.structs.getValues(a);for(var c=0;c<a.length;c++){var d=a[c];this.contains(d)&&b.add(d)}return b};goog.structs.Set.prototype.difference=function(a){var b=this.clone();b.removeAll(a);return b};goog.structs.Set.prototype.getValues=function(){return this.map_.getValues()};goog.structs.Set.prototype.clone=function(){return new goog.structs.Set(this)};\ngoog.structs.Set.prototype.equals=function(a){return this.getCount()==goog.structs.getCount(a)&&this.isSubsetOf(a)};goog.structs.Set.prototype.isSubsetOf=function(a){var b=goog.structs.getCount(a);if(this.getCount()>b)return!1;!(a instanceof goog.structs.Set)&&5<b&&(a=new goog.structs.Set(a));return goog.structs.every(this,function(b){return goog.structs.contains(a,b)})};goog.structs.Set.prototype.__iterator__=function(a){return this.map_.__iterator__(!1)};goog.debug.LOGGING_ENABLED=goog.DEBUG;goog.debug.FORCE_SLOPPY_STACKS=!1;goog.debug.catchErrors=function(a,b,c){c=c||goog.global;var d=c.onerror,e=!!b;goog.userAgent.WEBKIT&&!goog.userAgent.isVersionOrHigher(\"535.3\")&&(e=!e);c.onerror=function(b,c,h,k,n){d&&d(b,c,h,k,n);a({message:b,fileName:c,line:h,col:k,error:n});return e}};\ngoog.debug.expose=function(a,b){if(\"undefined\"==typeof a)return\"undefined\";if(null==a)return\"NULL\";var c=[],d;for(d in a)if(b||!goog.isFunction(a[d])){var e=d+\" = \";try{e+=a[d]}catch(f){e+=\"*** \"+f+\" ***\"}c.push(e)}return c.join(\"\\n\")};\ngoog.debug.deepExpose=function(a,b){var c=[],d=function(a,f,g){var h=f+\"  \";g=new goog.structs.Set(g);try{if(goog.isDef(a))if(goog.isNull(a))c.push(\"NULL\");else if(goog.isString(a))c.push('\"'+a.replace(/\\n/g,\"\\n\"+f)+'\"');else if(goog.isFunction(a))c.push(String(a).replace(/\\n/g,\"\\n\"+f));else if(goog.isObject(a))if(g.contains(a))c.push(\"*** reference loop detected ***\");else{g.add(a);c.push(\"{\");for(var k in a)if(b||!goog.isFunction(a[k]))c.push(\"\\n\"),c.push(h),c.push(k+\" = \"),d(a[k],h,g);c.push(\"\\n\"+\nf+\"}\")}else c.push(a);else c.push(\"undefined\")}catch(n){c.push(\"*** \"+n+\" ***\")}};d(a,\"\",new goog.structs.Set);return c.join(\"\")};goog.debug.exposeArray=function(a){for(var b=[],c=0;c<a.length;c++)goog.isArray(a[c])?b.push(goog.debug.exposeArray(a[c])):b.push(a[c]);return\"[ \"+b.join(\", \")+\" ]\"};goog.debug.exposeException=function(a,b){var c=goog.debug.exposeExceptionAsHtml(a,b);return goog.html.SafeHtml.unwrap(c)};\ngoog.debug.exposeExceptionAsHtml=function(a,b){try{var c=goog.debug.normalizeErrorObject(a),d=goog.debug.createViewSourceUrl_(c.fileName);return goog.html.SafeHtml.concat(goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(\"Message: \"+c.message+\"\\nUrl: \"),goog.html.SafeHtml.create(\"a\",{href:d,target:\"_new\"},c.fileName),goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(\"\\nLine: \"+c.lineNumber+\"\\n\\nBrowser stack:\\n\"+c.stack+\"-> [end]\\n\\nJS stack traversal:\\n\"+goog.debug.getStacktrace(b)+\n\"-> \"))}catch(e){return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(\"Exception trying to expose exception! You win, we lose. \"+e)}};\ngoog.debug.createViewSourceUrl_=function(a){goog.isDefAndNotNull(a)||(a=\"\");if(!/^https?:\\/\\//i.test(a))return goog.html.SafeUrl.fromConstant(goog.string.Const.from(\"sanitizedviewsrc\"));a=goog.html.SafeUrl.sanitize(a);return goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract(goog.string.Const.from(\"view-source scheme plus HTTP/HTTPS URL\"),\"view-source:\"+goog.html.SafeUrl.unwrap(a))};\ngoog.debug.normalizeErrorObject=function(a){var b=goog.getObjectByName(\"window.location.href\");if(goog.isString(a))return{message:a,name:\"Unknown error\",lineNumber:\"Not available\",fileName:b,stack:\"Not available\"};var c,d,e=!1;try{c=a.lineNumber||a.line||\"Not available\"}catch(f){c=\"Not available\",e=!0}try{d=a.fileName||a.filename||a.sourceURL||goog.global.$googDebugFname||b}catch(f){d=\"Not available\",e=!0}return!e&&a.lineNumber&&a.fileName&&a.stack&&a.message&&a.name?a:{message:a.message||\"Not available\",\nname:a.name||\"UnknownError\",lineNumber:c,fileName:d,stack:a.stack||\"Not available\"}};goog.debug.enhanceError=function(a,b){var c;\"string\"==typeof a?(c=Error(a),Error.captureStackTrace&&Error.captureStackTrace(c,goog.debug.enhanceError)):c=a;c.stack||(c.stack=goog.debug.getStacktrace(goog.debug.enhanceError));if(b){for(var d=0;c[\"message\"+d];)++d;c[\"message\"+d]=String(b)}return c};\ngoog.debug.getStacktraceSimple=function(a){if(!goog.debug.FORCE_SLOPPY_STACKS){var b=goog.debug.getNativeStackTrace_(goog.debug.getStacktraceSimple);if(b)return b}for(var b=[],c=arguments.callee.caller,d=0;c&&(!a||d<a);){b.push(goog.debug.getFunctionName(c));b.push(\"()\\n\");try{c=c.caller}catch(e){b.push(\"[exception trying to get caller]\\n\");break}d++;if(d>=goog.debug.MAX_STACK_DEPTH){b.push(\"[...long stack...]\");break}}a&&d>=a?b.push(\"[...reached max depth limit...]\"):b.push(\"[end]\");return b.join(\"\")};\ngoog.debug.MAX_STACK_DEPTH=50;goog.debug.getNativeStackTrace_=function(a){var b=Error();if(Error.captureStackTrace)return Error.captureStackTrace(b,a),String(b.stack);try{throw b;}catch(c){b=c}return(a=b.stack)?String(a):null};goog.debug.getStacktrace=function(a){var b;goog.debug.FORCE_SLOPPY_STACKS||(b=goog.debug.getNativeStackTrace_(a||goog.debug.getStacktrace));b||(b=goog.debug.getStacktraceHelper_(a||arguments.callee.caller,[]));return b};\ngoog.debug.getStacktraceHelper_=function(a,b){var c=[];if(goog.array.contains(b,a))c.push(\"[...circular reference...]\");else if(a&&b.length<goog.debug.MAX_STACK_DEPTH){c.push(goog.debug.getFunctionName(a)+\"(\");for(var d=a.arguments,e=0;d&&e<d.length;e++){0<e&&c.push(\", \");var f;f=d[e];switch(typeof f){case \"object\":f=f?\"object\":\"null\";break;case \"string\":break;case \"number\":f=String(f);break;case \"boolean\":f=f?\"true\":\"false\";break;case \"function\":f=(f=goog.debug.getFunctionName(f))?f:\"[fn]\";break;\ndefault:f=typeof f}40<f.length&&(f=f.substr(0,40)+\"...\");c.push(f)}b.push(a);c.push(\")\\n\");try{c.push(goog.debug.getStacktraceHelper_(a.caller,b))}catch(g){c.push(\"[exception trying to get caller]\\n\")}}else a?c.push(\"[...long stack...]\"):c.push(\"[end]\");return c.join(\"\")};goog.debug.setFunctionResolver=function(a){goog.debug.fnNameResolver_=a};\ngoog.debug.getFunctionName=function(a){if(goog.debug.fnNameCache_[a])return goog.debug.fnNameCache_[a];if(goog.debug.fnNameResolver_){var b=goog.debug.fnNameResolver_(a);if(b)return goog.debug.fnNameCache_[a]=b}a=String(a);goog.debug.fnNameCache_[a]||(b=/function ([^\\(]+)/.exec(a),goog.debug.fnNameCache_[a]=b?b[1]:\"[Anonymous]\");return goog.debug.fnNameCache_[a]};\ngoog.debug.makeWhitespaceVisible=function(a){return a.replace(/ /g,\"[_]\").replace(/\\f/g,\"[f]\").replace(/\\n/g,\"[n]\\n\").replace(/\\r/g,\"[r]\").replace(/\\t/g,\"[t]\")};goog.debug.runtimeType=function(a){return a instanceof Function?a.displayName||a.name||\"unknown type name\":a instanceof Object?a.constructor.displayName||a.constructor.name||Object.prototype.toString.call(a):null===a?\"null\":typeof a};goog.debug.fnNameCache_={};goog.debug.LogRecord=function(a,b,c,d,e){this.reset(a,b,c,d,e)};goog.debug.LogRecord.prototype.sequenceNumber_=0;goog.debug.LogRecord.prototype.exception_=null;goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS=!0;goog.debug.LogRecord.nextSequenceNumber_=0;\ngoog.debug.LogRecord.prototype.reset=function(a,b,c,d,e){goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS&&(this.sequenceNumber_=\"number\"==typeof e?e:goog.debug.LogRecord.nextSequenceNumber_++);this.time_=d||goog.now();this.level_=a;this.msg_=b;this.loggerName_=c;delete this.exception_};goog.debug.LogRecord.prototype.getLoggerName=function(){return this.loggerName_};goog.debug.LogRecord.prototype.getException=function(){return this.exception_};\ngoog.debug.LogRecord.prototype.setException=function(a){this.exception_=a};goog.debug.LogRecord.prototype.setLoggerName=function(a){this.loggerName_=a};goog.debug.LogRecord.prototype.getLevel=function(){return this.level_};goog.debug.LogRecord.prototype.setLevel=function(a){this.level_=a};goog.debug.LogRecord.prototype.getMessage=function(){return this.msg_};goog.debug.LogRecord.prototype.setMessage=function(a){this.msg_=a};goog.debug.LogRecord.prototype.getMillis=function(){return this.time_};\ngoog.debug.LogRecord.prototype.setMillis=function(a){this.time_=a};goog.debug.LogRecord.prototype.getSequenceNumber=function(){return this.sequenceNumber_};goog.debug.LogBuffer=function(){goog.asserts.assert(goog.debug.LogBuffer.isBufferingEnabled(),\"Cannot use goog.debug.LogBuffer without defining goog.debug.LogBuffer.CAPACITY.\");this.clear()};goog.debug.LogBuffer.getInstance=function(){goog.debug.LogBuffer.instance_||(goog.debug.LogBuffer.instance_=new goog.debug.LogBuffer);return goog.debug.LogBuffer.instance_};goog.debug.LogBuffer.CAPACITY=0;\ngoog.debug.LogBuffer.prototype.addRecord=function(a,b,c){var d=(this.curIndex_+1)%goog.debug.LogBuffer.CAPACITY;this.curIndex_=d;if(this.isFull_)return d=this.buffer_[d],d.reset(a,b,c),d;this.isFull_=d==goog.debug.LogBuffer.CAPACITY-1;return this.buffer_[d]=new goog.debug.LogRecord(a,b,c)};goog.debug.LogBuffer.isBufferingEnabled=function(){return 0<goog.debug.LogBuffer.CAPACITY};\ngoog.debug.LogBuffer.prototype.clear=function(){this.buffer_=Array(goog.debug.LogBuffer.CAPACITY);this.curIndex_=-1;this.isFull_=!1};goog.debug.LogBuffer.prototype.forEachRecord=function(a){var b=this.buffer_;if(b[0]){var c=this.curIndex_,d=this.isFull_?c:-1;do d=(d+1)%goog.debug.LogBuffer.CAPACITY,a(b[d]);while(d!=c)}};goog.debug.Logger=function(a){this.name_=a;this.handlers_=this.children_=this.level_=this.parent_=null};goog.debug.Logger.ROOT_LOGGER_NAME=\"\";goog.debug.Logger.ENABLE_HIERARCHY=!0;goog.debug.Logger.ENABLE_HIERARCHY||(goog.debug.Logger.rootHandlers_=[]);goog.debug.Logger.Level=function(a,b){this.name=a;this.value=b};goog.debug.Logger.Level.prototype.toString=function(){return this.name};goog.debug.Logger.Level.OFF=new goog.debug.Logger.Level(\"OFF\",Infinity);\ngoog.debug.Logger.Level.SHOUT=new goog.debug.Logger.Level(\"SHOUT\",1200);goog.debug.Logger.Level.SEVERE=new goog.debug.Logger.Level(\"SEVERE\",1E3);goog.debug.Logger.Level.WARNING=new goog.debug.Logger.Level(\"WARNING\",900);goog.debug.Logger.Level.INFO=new goog.debug.Logger.Level(\"INFO\",800);goog.debug.Logger.Level.CONFIG=new goog.debug.Logger.Level(\"CONFIG\",700);goog.debug.Logger.Level.FINE=new goog.debug.Logger.Level(\"FINE\",500);goog.debug.Logger.Level.FINER=new goog.debug.Logger.Level(\"FINER\",400);\ngoog.debug.Logger.Level.FINEST=new goog.debug.Logger.Level(\"FINEST\",300);goog.debug.Logger.Level.ALL=new goog.debug.Logger.Level(\"ALL\",0);goog.debug.Logger.Level.PREDEFINED_LEVELS=[goog.debug.Logger.Level.OFF,goog.debug.Logger.Level.SHOUT,goog.debug.Logger.Level.SEVERE,goog.debug.Logger.Level.WARNING,goog.debug.Logger.Level.INFO,goog.debug.Logger.Level.CONFIG,goog.debug.Logger.Level.FINE,goog.debug.Logger.Level.FINER,goog.debug.Logger.Level.FINEST,goog.debug.Logger.Level.ALL];\ngoog.debug.Logger.Level.predefinedLevelsCache_=null;goog.debug.Logger.Level.createPredefinedLevelsCache_=function(){goog.debug.Logger.Level.predefinedLevelsCache_={};for(var a=0,b;b=goog.debug.Logger.Level.PREDEFINED_LEVELS[a];a++)goog.debug.Logger.Level.predefinedLevelsCache_[b.value]=b,goog.debug.Logger.Level.predefinedLevelsCache_[b.name]=b};\ngoog.debug.Logger.Level.getPredefinedLevel=function(a){goog.debug.Logger.Level.predefinedLevelsCache_||goog.debug.Logger.Level.createPredefinedLevelsCache_();return goog.debug.Logger.Level.predefinedLevelsCache_[a]||null};\ngoog.debug.Logger.Level.getPredefinedLevelByValue=function(a){goog.debug.Logger.Level.predefinedLevelsCache_||goog.debug.Logger.Level.createPredefinedLevelsCache_();if(a in goog.debug.Logger.Level.predefinedLevelsCache_)return goog.debug.Logger.Level.predefinedLevelsCache_[a];for(var b=0;b<goog.debug.Logger.Level.PREDEFINED_LEVELS.length;++b){var c=goog.debug.Logger.Level.PREDEFINED_LEVELS[b];if(c.value<=a)return c}return null};goog.debug.Logger.getLogger=function(a){return goog.debug.LogManager.getLogger(a)};\ngoog.debug.Logger.logToProfilers=function(a){goog.global.console&&(goog.global.console.timeStamp?goog.global.console.timeStamp(a):goog.global.console.markTimeline&&goog.global.console.markTimeline(a));goog.global.msWriteProfilerMark&&goog.global.msWriteProfilerMark(a)};goog.debug.Logger.prototype.getName=function(){return this.name_};\ngoog.debug.Logger.prototype.addHandler=function(a){goog.debug.LOGGING_ENABLED&&(goog.debug.Logger.ENABLE_HIERARCHY?(this.handlers_||(this.handlers_=[]),this.handlers_.push(a)):(goog.asserts.assert(!this.name_,\"Cannot call addHandler on a non-root logger when goog.debug.Logger.ENABLE_HIERARCHY is false.\"),goog.debug.Logger.rootHandlers_.push(a)))};\ngoog.debug.Logger.prototype.removeHandler=function(a){if(goog.debug.LOGGING_ENABLED){var b=goog.debug.Logger.ENABLE_HIERARCHY?this.handlers_:goog.debug.Logger.rootHandlers_;return!!b&&goog.array.remove(b,a)}return!1};goog.debug.Logger.prototype.getParent=function(){return this.parent_};goog.debug.Logger.prototype.getChildren=function(){this.children_||(this.children_={});return this.children_};\ngoog.debug.Logger.prototype.setLevel=function(a){goog.debug.LOGGING_ENABLED&&(goog.debug.Logger.ENABLE_HIERARCHY?this.level_=a:(goog.asserts.assert(!this.name_,\"Cannot call setLevel() on a non-root logger when goog.debug.Logger.ENABLE_HIERARCHY is false.\"),goog.debug.Logger.rootLevel_=a))};goog.debug.Logger.prototype.getLevel=function(){return goog.debug.LOGGING_ENABLED?this.level_:goog.debug.Logger.Level.OFF};\ngoog.debug.Logger.prototype.getEffectiveLevel=function(){if(!goog.debug.LOGGING_ENABLED)return goog.debug.Logger.Level.OFF;if(!goog.debug.Logger.ENABLE_HIERARCHY)return goog.debug.Logger.rootLevel_;if(this.level_)return this.level_;if(this.parent_)return this.parent_.getEffectiveLevel();goog.asserts.fail(\"Root logger has no level set.\");return null};goog.debug.Logger.prototype.isLoggable=function(a){return goog.debug.LOGGING_ENABLED&&a.value>=this.getEffectiveLevel().value};\ngoog.debug.Logger.prototype.log=function(a,b,c){goog.debug.LOGGING_ENABLED&&this.isLoggable(a)&&(goog.isFunction(b)&&(b=b()),this.doLogRecord_(this.getLogRecord(a,b,c)))};goog.debug.Logger.prototype.getLogRecord=function(a,b,c){a=goog.debug.LogBuffer.isBufferingEnabled()?goog.debug.LogBuffer.getInstance().addRecord(a,b,this.name_):new goog.debug.LogRecord(a,String(b),this.name_);c&&a.setException(c);return a};\ngoog.debug.Logger.prototype.shout=function(a,b){goog.debug.LOGGING_ENABLED&&this.log(goog.debug.Logger.Level.SHOUT,a,b)};goog.debug.Logger.prototype.severe=function(a,b){goog.debug.LOGGING_ENABLED&&this.log(goog.debug.Logger.Level.SEVERE,a,b)};goog.debug.Logger.prototype.warning=function(a,b){goog.debug.LOGGING_ENABLED&&this.log(goog.debug.Logger.Level.WARNING,a,b)};goog.debug.Logger.prototype.info=function(a,b){goog.debug.LOGGING_ENABLED&&this.log(goog.debug.Logger.Level.INFO,a,b)};\ngoog.debug.Logger.prototype.config=function(a,b){goog.debug.LOGGING_ENABLED&&this.log(goog.debug.Logger.Level.CONFIG,a,b)};goog.debug.Logger.prototype.fine=function(a,b){goog.debug.LOGGING_ENABLED&&this.log(goog.debug.Logger.Level.FINE,a,b)};goog.debug.Logger.prototype.finer=function(a,b){goog.debug.LOGGING_ENABLED&&this.log(goog.debug.Logger.Level.FINER,a,b)};goog.debug.Logger.prototype.finest=function(a,b){goog.debug.LOGGING_ENABLED&&this.log(goog.debug.Logger.Level.FINEST,a,b)};\ngoog.debug.Logger.prototype.logRecord=function(a){goog.debug.LOGGING_ENABLED&&this.isLoggable(a.getLevel())&&this.doLogRecord_(a)};goog.debug.Logger.prototype.doLogRecord_=function(a){goog.debug.Logger.logToProfilers(\"log:\"+a.getMessage());if(goog.debug.Logger.ENABLE_HIERARCHY)for(var b=this;b;)b.callPublish_(a),b=b.getParent();else for(var b=0,c;c=goog.debug.Logger.rootHandlers_[b++];)c(a)};goog.debug.Logger.prototype.callPublish_=function(a){if(this.handlers_)for(var b=0,c;c=this.handlers_[b];b++)c(a)};\ngoog.debug.Logger.prototype.setParent_=function(a){this.parent_=a};goog.debug.Logger.prototype.addChild_=function(a,b){this.getChildren()[a]=b};goog.debug.LogManager={};goog.debug.LogManager.loggers_={};goog.debug.LogManager.rootLogger_=null;\ngoog.debug.LogManager.initialize=function(){goog.debug.LogManager.rootLogger_||(goog.debug.LogManager.rootLogger_=new goog.debug.Logger(goog.debug.Logger.ROOT_LOGGER_NAME),goog.debug.LogManager.loggers_[goog.debug.Logger.ROOT_LOGGER_NAME]=goog.debug.LogManager.rootLogger_,goog.debug.LogManager.rootLogger_.setLevel(goog.debug.Logger.Level.CONFIG))};goog.debug.LogManager.getLoggers=function(){return goog.debug.LogManager.loggers_};\ngoog.debug.LogManager.getRoot=function(){goog.debug.LogManager.initialize();return goog.debug.LogManager.rootLogger_};goog.debug.LogManager.getLogger=function(a){goog.debug.LogManager.initialize();return goog.debug.LogManager.loggers_[a]||goog.debug.LogManager.createLogger_(a)};goog.debug.LogManager.createFunctionForCatchErrors=function(a){return function(b){(a||goog.debug.LogManager.getRoot()).severe(\"Error: \"+b.message+\" (\"+b.fileName+\" @ Line: \"+b.line+\")\")}};\ngoog.debug.LogManager.createLogger_=function(a){var b=new goog.debug.Logger(a);if(goog.debug.Logger.ENABLE_HIERARCHY){var c=a.lastIndexOf(\".\"),d=a.substr(0,c),c=a.substr(c+1),d=goog.debug.LogManager.getLogger(d);d.addChild_(c,b);b.setParent_(d)}return goog.debug.LogManager.loggers_[a]=b};goog.log={};goog.log.ENABLED=goog.debug.LOGGING_ENABLED;goog.log.ROOT_LOGGER_NAME=goog.debug.Logger.ROOT_LOGGER_NAME;goog.log.Logger=goog.debug.Logger;goog.log.Level=goog.debug.Logger.Level;goog.log.LogRecord=goog.debug.LogRecord;goog.log.getLogger=function(a,b){if(goog.log.ENABLED){var c=goog.debug.LogManager.getLogger(a);b&&c&&c.setLevel(b);return c}return null};goog.log.addHandler=function(a,b){goog.log.ENABLED&&a&&a.addHandler(b)};\ngoog.log.removeHandler=function(a,b){return goog.log.ENABLED&&a?a.removeHandler(b):!1};goog.log.log=function(a,b,c,d){goog.log.ENABLED&&a&&a.log(b,c,d)};goog.log.error=function(a,b,c){goog.log.ENABLED&&a&&a.severe(b,c)};goog.log.warning=function(a,b,c){goog.log.ENABLED&&a&&a.warning(b,c)};goog.log.info=function(a,b,c){goog.log.ENABLED&&a&&a.info(b,c)};goog.log.fine=function(a,b,c){goog.log.ENABLED&&a&&a.fine(b,c)};goog.string.StringBuffer=function(a,b){null!=a&&this.append.apply(this,arguments)};goog.string.StringBuffer.prototype.buffer_=\"\";goog.string.StringBuffer.prototype.set=function(a){this.buffer_=\"\"+a};goog.string.StringBuffer.prototype.append=function(a,b,c){this.buffer_+=String(a);if(null!=b)for(var d=1;d<arguments.length;d++)this.buffer_+=arguments[d];return this};goog.string.StringBuffer.prototype.clear=function(){this.buffer_=\"\"};goog.string.StringBuffer.prototype.getLength=function(){return this.buffer_.length};\ngoog.string.StringBuffer.prototype.toString=function(){return this.buffer_};goog.ui.tree={};goog.ui.tree.BaseNode=function(a,b,c){goog.ui.Component.call(this,c);this.config_=b||goog.ui.tree.BaseNode.defaultConfig;this.html_=goog.html.SafeHtml.htmlEscapePreservingNewlines(a);this.expanded_=this.selected_=!1;this.toolTip_=null;this.afterLabelHtml_=goog.html.SafeHtml.EMPTY;this.isUserCollapsible_=!0;this.depth_=-1};goog.inherits(goog.ui.tree.BaseNode,goog.ui.Component);\ngoog.ui.tree.BaseNode.EventType={BEFORE_EXPAND:\"beforeexpand\",EXPAND:\"expand\",BEFORE_COLLAPSE:\"beforecollapse\",COLLAPSE:\"collapse\"};goog.ui.tree.BaseNode.allNodes={};goog.ui.tree.BaseNode.prototype.disposeInternal=function(){goog.ui.tree.BaseNode.superClass_.disposeInternal.call(this);this.tree&&(this.tree.removeNode(this),this.tree=null);this.setElementInternal(null)};\ngoog.ui.tree.BaseNode.prototype.initAccessibility=function(){var a=this.getElement();if(a){var b=this.getLabelElement();b&&!b.id&&(b.id=this.getId()+\".label\");goog.a11y.aria.setRole(a,\"treeitem\");goog.a11y.aria.setState(a,\"selected\",!1);goog.a11y.aria.setState(a,\"expanded\",!1);goog.a11y.aria.setState(a,\"level\",this.getDepth());b&&goog.a11y.aria.setState(a,\"labelledby\",b.id);(a=this.getIconElement())&&goog.a11y.aria.setRole(a,\"presentation\");(a=this.getExpandIconElement())&&goog.a11y.aria.setRole(a,\n\"presentation\");if(a=this.getChildrenElement())if(goog.a11y.aria.setRole(a,\"group\"),a.hasChildNodes())for(a=this.getChildCount(),b=1;b<=a;b++){var c=this.getChildAt(b-1).getElement();goog.asserts.assert(c,\"The child element cannot be null\");goog.a11y.aria.setState(c,\"setsize\",a);goog.a11y.aria.setState(c,\"posinset\",b)}}};goog.ui.tree.BaseNode.prototype.createDom=function(){var a=this.getDomHelper().safeHtmlToNode(this.toSafeHtml());this.setElementInternal(a)};\ngoog.ui.tree.BaseNode.prototype.enterDocument=function(){goog.ui.tree.BaseNode.superClass_.enterDocument.call(this);goog.ui.tree.BaseNode.allNodes[this.getId()]=this;this.initAccessibility()};goog.ui.tree.BaseNode.prototype.exitDocument=function(){goog.ui.tree.BaseNode.superClass_.exitDocument.call(this);delete goog.ui.tree.BaseNode.allNodes[this.getId()]};\ngoog.ui.tree.BaseNode.prototype.addChildAt=function(a,b,c){goog.asserts.assert(!a.getParent());goog.asserts.assertInstanceof(a,goog.ui.tree.BaseNode);c=this.getChildAt(b-1);var d=this.getChildAt(b);goog.ui.tree.BaseNode.superClass_.addChildAt.call(this,a,b);a.previousSibling_=c;a.nextSibling_=d;c?c.nextSibling_=a:this.firstChild_=a;d?d.previousSibling_=a:this.lastChild_=a;(b=this.getTree())&&a.setTreeInternal(b);a.setDepth_(this.getDepth()+1);if(this.getElement()&&(this.updateExpandIcon(),this.getExpanded())){b=\nthis.getChildrenElement();a.getElement()||a.createDom();var e=a.getElement(),f=d&&d.getElement();b.insertBefore(e,f);this.isInDocument()&&a.enterDocument();d||(c?c.updateExpandIcon():(goog.style.setElementShown(b,!0),this.setExpanded(this.getExpanded())))}};goog.ui.tree.BaseNode.prototype.add=function(a,b){goog.asserts.assert(!b||b.getParent()==this,\"Can only add nodes before siblings\");a.getParent()&&a.getParent().removeChild(a);this.addChildAt(a,b?this.indexOfChild(b):this.getChildCount());return a};\ngoog.ui.tree.BaseNode.prototype.removeChild=function(a,b){var c=this.getTree(),d=c?c.getSelectedItem():null;if(d==a||a.contains(d))c.hasFocus()?(this.select(),goog.Timer.callOnce(this.onTimeoutSelect_,10,this)):this.select();goog.ui.tree.BaseNode.superClass_.removeChild.call(this,a);this.lastChild_==a&&(this.lastChild_=a.previousSibling_);this.firstChild_==a&&(this.firstChild_=a.nextSibling_);a.previousSibling_&&(a.previousSibling_.nextSibling_=a.nextSibling_);a.nextSibling_&&(a.nextSibling_.previousSibling_=\na.previousSibling_);d=a.isLastSibling();a.tree=null;a.depth_=-1;if(c&&(c.removeNode(a),this.isInDocument())){c=this.getChildrenElement();if(a.isInDocument()){var e=a.getElement();c.removeChild(e);a.exitDocument()}d&&(d=this.getLastChild())&&d.updateExpandIcon();this.hasChildren()||(c.style.display=\"none\",this.updateExpandIcon(),this.updateIcon_())}return a};goog.ui.tree.BaseNode.prototype.remove=goog.ui.tree.BaseNode.prototype.removeChild;goog.ui.tree.BaseNode.prototype.onTimeoutSelect_=function(){this.select()};\ngoog.ui.tree.BaseNode.prototype.getDepth=function(){var a=this.depth_;0>a&&(a=this.computeDepth_(),this.setDepth_(a));return a};goog.ui.tree.BaseNode.prototype.computeDepth_=function(){var a=this.getParent();return a?a.getDepth()+1:0};goog.ui.tree.BaseNode.prototype.setDepth_=function(a){if(a!=this.depth_){this.depth_=a;var b=this.getRowElement();if(b){var c=this.getPixelIndent_()+\"px\";this.isRightToLeft()?b.style.paddingRight=c:b.style.paddingLeft=c}this.forEachChild(function(b){b.setDepth_(a+1)})}};\ngoog.ui.tree.BaseNode.prototype.contains=function(a){for(;a;){if(a==this)return!0;a=a.getParent()}return!1};goog.ui.tree.BaseNode.EMPTY_CHILDREN_=[];goog.ui.tree.BaseNode.prototype.getChildren=function(){var a=[];this.forEachChild(function(b){a.push(b)});return a};goog.ui.tree.BaseNode.prototype.getFirstChild=function(){return this.getChildAt(0)};goog.ui.tree.BaseNode.prototype.getLastChild=function(){return this.getChildAt(this.getChildCount()-1)};\ngoog.ui.tree.BaseNode.prototype.getPreviousSibling=function(){return this.previousSibling_};goog.ui.tree.BaseNode.prototype.getNextSibling=function(){return this.nextSibling_};goog.ui.tree.BaseNode.prototype.isLastSibling=function(){return!this.nextSibling_};goog.ui.tree.BaseNode.prototype.isSelected=function(){return this.selected_};goog.ui.tree.BaseNode.prototype.select=function(){var a=this.getTree();a&&a.setSelectedItem(this)};goog.ui.tree.BaseNode.prototype.deselect=goog.nullFunction;\ngoog.ui.tree.BaseNode.prototype.setSelectedInternal=function(a){if(this.selected_!=a){this.selected_=a;this.updateRow();var b=this.getElement();b&&(goog.a11y.aria.setState(b,\"selected\",a),a&&(a=this.getTree().getElement(),goog.asserts.assert(a,\"The DOM element for the tree cannot be null\"),goog.a11y.aria.setState(a,\"activedescendant\",this.getId())))}};goog.ui.tree.BaseNode.prototype.getExpanded=function(){return this.expanded_};\ngoog.ui.tree.BaseNode.prototype.setExpandedInternal=function(a){this.expanded_=a};\ngoog.ui.tree.BaseNode.prototype.setExpanded=function(a){var b=a!=this.expanded_;if(!b||this.dispatchEvent(a?goog.ui.tree.BaseNode.EventType.BEFORE_EXPAND:goog.ui.tree.BaseNode.EventType.BEFORE_COLLAPSE)){var c;this.expanded_=a;c=this.getTree();var d=this.getElement();if(this.hasChildren()){if(!a&&c&&this.contains(c.getSelectedItem())&&this.select(),d){if(c=this.getChildrenElement())if(goog.style.setElementShown(c,a),a&&this.isInDocument()&&!c.hasChildNodes()){var e=[];this.forEachChild(function(a){e.push(a.toSafeHtml())});\ngoog.dom.safe.setInnerHtml(c,goog.html.SafeHtml.concat(e));this.forEachChild(function(a){a.enterDocument()})}this.updateExpandIcon()}}else(c=this.getChildrenElement())&&goog.style.setElementShown(c,!1);d&&(this.updateIcon_(),goog.a11y.aria.setState(d,\"expanded\",a));b&&this.dispatchEvent(a?goog.ui.tree.BaseNode.EventType.EXPAND:goog.ui.tree.BaseNode.EventType.COLLAPSE)}};goog.ui.tree.BaseNode.prototype.toggle=function(){this.setExpanded(!this.getExpanded())};\ngoog.ui.tree.BaseNode.prototype.expand=function(){this.setExpanded(!0)};goog.ui.tree.BaseNode.prototype.collapse=function(){this.setExpanded(!1)};goog.ui.tree.BaseNode.prototype.collapseChildren=function(){this.forEachChild(function(a){a.collapseAll()})};goog.ui.tree.BaseNode.prototype.collapseAll=function(){this.collapseChildren();this.collapse()};goog.ui.tree.BaseNode.prototype.expandChildren=function(){this.forEachChild(function(a){a.expandAll()})};\ngoog.ui.tree.BaseNode.prototype.expandAll=function(){this.expandChildren();this.expand()};goog.ui.tree.BaseNode.prototype.reveal=function(){var a=this.getParent();a&&(a.setExpanded(!0),a.reveal())};goog.ui.tree.BaseNode.prototype.setIsUserCollapsible=function(a){(this.isUserCollapsible_=a)||this.expand();this.getElement()&&this.updateExpandIcon()};goog.ui.tree.BaseNode.prototype.isUserCollapsible=function(){return this.isUserCollapsible_};\ngoog.ui.tree.BaseNode.prototype.toSafeHtml=function(){var a=this.getTree(),b=!a.getShowLines()||a==this.getParent()&&!a.getShowRootLines()?this.config_.cssChildrenNoLines:this.config_.cssChildren,a=this.getExpanded()&&this.hasChildren(),b={\"class\":b,style:this.getLineStyle()},c=[];a&&this.forEachChild(function(a){c.push(a.toSafeHtml())});a=goog.html.SafeHtml.create(\"div\",b,c);return goog.html.SafeHtml.create(\"div\",{\"class\":this.config_.cssItem,id:this.getId()},[this.getRowSafeHtml(),a])};\ngoog.ui.tree.BaseNode.prototype.getPixelIndent_=function(){return Math.max(0,(this.getDepth()-1)*this.config_.indentWidth)};goog.ui.tree.BaseNode.prototype.getRowSafeHtml=function(){var a={};a[\"padding-\"+(this.isRightToLeft()?\"right\":\"left\")]=this.getPixelIndent_()+\"px\";var a={\"class\":this.getRowClassName(),style:a},b=[this.getExpandIconSafeHtml(),this.getIconSafeHtml(),this.getLabelSafeHtml()];return goog.html.SafeHtml.create(\"div\",a,b)};\ngoog.ui.tree.BaseNode.prototype.getRowClassName=function(){var a;a=this.isSelected()?\" \"+this.config_.cssSelectedRow:\"\";return this.config_.cssTreeRow+a};goog.ui.tree.BaseNode.prototype.getLabelSafeHtml=function(){var a=goog.html.SafeHtml.create(\"span\",{\"class\":this.config_.cssItemLabel,title:this.getToolTip()||null},this.getSafeHtml());return goog.html.SafeHtml.concat(a,goog.html.SafeHtml.create(\"span\",{},this.getAfterLabelSafeHtml()))};goog.ui.tree.BaseNode.prototype.getAfterLabelHtml=function(){return goog.html.SafeHtml.unwrap(this.getAfterLabelSafeHtml())};\ngoog.ui.tree.BaseNode.prototype.getAfterLabelSafeHtml=function(){return this.afterLabelHtml_};goog.ui.tree.BaseNode.prototype.setAfterLabelSafeHtml=function(a){this.afterLabelHtml_=a;var b=this.getAfterLabelElement();b&&goog.dom.safe.setInnerHtml(b,a)};goog.ui.tree.BaseNode.prototype.getIconSafeHtml=function(){return goog.html.SafeHtml.create(\"span\",{style:{display:\"inline-block\"},\"class\":this.getCalculatedIconClass()})};\ngoog.ui.tree.BaseNode.prototype.getExpandIconSafeHtml=function(){return goog.html.SafeHtml.create(\"span\",{type:\"expand\",style:{display:\"inline-block\"},\"class\":this.getExpandIconClass()})};\ngoog.ui.tree.BaseNode.prototype.getExpandIconClass=function(){var a=this.getTree(),b=!a.getShowLines()||a==this.getParent()&&!a.getShowRootLines(),c=this.config_,d=new goog.string.StringBuffer;d.append(c.cssTreeIcon,\" \",c.cssExpandTreeIcon,\" \");if(this.hasChildren()){var e=0;a.getShowExpandIcons()&&this.isUserCollapsible_&&(e=this.getExpanded()?2:1);b||(e=this.isLastSibling()?e+4:e+8);switch(e){case 1:d.append(c.cssExpandTreeIconPlus);break;case 2:d.append(c.cssExpandTreeIconMinus);break;case 4:d.append(c.cssExpandTreeIconL);\nbreak;case 5:d.append(c.cssExpandTreeIconLPlus);break;case 6:d.append(c.cssExpandTreeIconLMinus);break;case 8:d.append(c.cssExpandTreeIconT);break;case 9:d.append(c.cssExpandTreeIconTPlus);break;case 10:d.append(c.cssExpandTreeIconTMinus);break;default:d.append(c.cssExpandTreeIconBlank)}}else b?d.append(c.cssExpandTreeIconBlank):this.isLastSibling()?d.append(c.cssExpandTreeIconL):d.append(c.cssExpandTreeIconT);return d.toString()};\ngoog.ui.tree.BaseNode.prototype.getLineStyle=function(){var a=this.getExpanded()&&this.hasChildren();return goog.html.SafeStyle.create({\"background-position\":this.getBackgroundPosition(),display:a?null:\"none\"})};goog.ui.tree.BaseNode.prototype.getBackgroundPosition=function(){return(this.isLastSibling()?\"-100\":(this.getDepth()-1)*this.config_.indentWidth)+\"px 0\"};\ngoog.ui.tree.BaseNode.prototype.getElement=function(){var a=goog.ui.tree.BaseNode.superClass_.getElement.call(this);a||(a=this.getDomHelper().getElement(this.getId()),this.setElementInternal(a));return a};goog.ui.tree.BaseNode.prototype.getRowElement=function(){var a=this.getElement();return a?a.firstChild:null};goog.ui.tree.BaseNode.prototype.getExpandIconElement=function(){var a=this.getRowElement();return a?a.firstChild:null};\ngoog.ui.tree.BaseNode.prototype.getIconElement=function(){var a=this.getRowElement();return a?a.childNodes[1]:null};goog.ui.tree.BaseNode.prototype.getLabelElement=function(){var a=this.getRowElement();return a&&a.lastChild?a.lastChild.previousSibling:null};goog.ui.tree.BaseNode.prototype.getAfterLabelElement=function(){var a=this.getRowElement();return a?a.lastChild:null};goog.ui.tree.BaseNode.prototype.getChildrenElement=function(){var a=this.getElement();return a?a.lastChild:null};\ngoog.ui.tree.BaseNode.prototype.setIconClass=function(a){this.iconClass_=a;this.isInDocument()&&this.updateIcon_()};goog.ui.tree.BaseNode.prototype.getIconClass=function(){return this.iconClass_};goog.ui.tree.BaseNode.prototype.setExpandedIconClass=function(a){this.expandedIconClass_=a;this.isInDocument()&&this.updateIcon_()};goog.ui.tree.BaseNode.prototype.getExpandedIconClass=function(){return this.expandedIconClass_};goog.ui.tree.BaseNode.prototype.setText=function(a){this.setSafeHtml(goog.html.SafeHtml.htmlEscape(a))};\ngoog.ui.tree.BaseNode.prototype.getText=function(){return goog.string.unescapeEntities(goog.html.SafeHtml.unwrap(this.html_))};goog.ui.tree.BaseNode.prototype.setSafeHtml=function(a){this.html_=a;var b=this.getLabelElement();b&&goog.dom.safe.setInnerHtml(b,a);(a=this.getTree())&&a.setNode(this)};goog.ui.tree.BaseNode.prototype.getHtml=function(){return goog.html.SafeHtml.unwrap(this.getSafeHtml())};goog.ui.tree.BaseNode.prototype.getSafeHtml=function(){return this.html_};\ngoog.ui.tree.BaseNode.prototype.setToolTip=function(a){this.toolTip_=a;var b=this.getLabelElement();b&&(b.title=a)};goog.ui.tree.BaseNode.prototype.getToolTip=function(){return this.toolTip_};goog.ui.tree.BaseNode.prototype.updateRow=function(){var a=this.getRowElement();a&&(a.className=this.getRowClassName())};\ngoog.ui.tree.BaseNode.prototype.updateExpandIcon=function(){var a=this.getExpandIconElement();a&&(a.className=this.getExpandIconClass());if(a=this.getChildrenElement())a.style.backgroundPosition=this.getBackgroundPosition()};goog.ui.tree.BaseNode.prototype.updateIcon_=function(){this.getIconElement().className=this.getCalculatedIconClass()};\ngoog.ui.tree.BaseNode.prototype.onMouseDown=function(a){\"expand\"==a.target.getAttribute(\"type\")&&this.hasChildren()?this.isUserCollapsible_&&this.toggle():(this.select(),this.updateRow())};goog.ui.tree.BaseNode.prototype.onClick_=goog.events.Event.preventDefault;goog.ui.tree.BaseNode.prototype.onDoubleClick_=function(a){\"expand\"==a.target.getAttribute(\"type\")&&this.hasChildren()||this.isUserCollapsible_&&this.toggle()};\ngoog.ui.tree.BaseNode.prototype.onKeyDown=function(a){var b=!0;switch(a.keyCode){case goog.events.KeyCodes.RIGHT:if(a.altKey)break;this.hasChildren()&&(this.getExpanded()?this.getFirstChild().select():this.setExpanded(!0));break;case goog.events.KeyCodes.LEFT:if(a.altKey)break;if(this.hasChildren()&&this.getExpanded()&&this.isUserCollapsible_)this.setExpanded(!1);else{var c=this.getParent(),d=this.getTree();c&&(d.getShowRootNode()||c!=d)&&c.select()}break;case goog.events.KeyCodes.DOWN:(c=this.getNextShownNode())&&\nc.select();break;case goog.events.KeyCodes.UP:(c=this.getPreviousShownNode())&&c.select();break;default:b=!1}b&&(a.preventDefault(),(d=this.getTree())&&d.clearTypeAhead());return b};goog.ui.tree.BaseNode.prototype.getLastShownDescendant=function(){return this.getExpanded()&&this.hasChildren()?this.getLastChild().getLastShownDescendant():this};\ngoog.ui.tree.BaseNode.prototype.getNextShownNode=function(){if(this.hasChildren()&&this.getExpanded())return this.getFirstChild();for(var a=this,b;a!=this.getTree();){b=a.getNextSibling();if(null!=b)return b;a=a.getParent()}return null};goog.ui.tree.BaseNode.prototype.getPreviousShownNode=function(){var a=this.getPreviousSibling();if(null!=a)return a.getLastShownDescendant();var a=this.getParent(),b=this.getTree();return!b.getShowRootNode()&&a==b||this==b?null:a};\ngoog.ui.tree.BaseNode.prototype.getClientData=goog.ui.tree.BaseNode.prototype.getModel;goog.ui.tree.BaseNode.prototype.setClientData=goog.ui.tree.BaseNode.prototype.setModel;goog.ui.tree.BaseNode.prototype.getConfig=function(){return this.config_};goog.ui.tree.BaseNode.prototype.setTreeInternal=function(a){this.tree!=a&&(this.tree=a,a.setNode(this),this.forEachChild(function(b){b.setTreeInternal(a)}))};\ngoog.ui.tree.BaseNode.defaultConfig={indentWidth:19,cssRoot:\"goog-tree-root goog-tree-item\",cssHideRoot:\"goog-tree-hide-root\",cssItem:\"goog-tree-item\",cssChildren:\"goog-tree-children\",cssChildrenNoLines:\"goog-tree-children-nolines\",cssTreeRow:\"goog-tree-row\",cssItemLabel:\"goog-tree-item-label\",cssTreeIcon:\"goog-tree-icon\",cssExpandTreeIcon:\"goog-tree-expand-icon\",cssExpandTreeIconPlus:\"goog-tree-expand-icon-plus\",cssExpandTreeIconMinus:\"goog-tree-expand-icon-minus\",cssExpandTreeIconTPlus:\"goog-tree-expand-icon-tplus\",\ncssExpandTreeIconTMinus:\"goog-tree-expand-icon-tminus\",cssExpandTreeIconLPlus:\"goog-tree-expand-icon-lplus\",cssExpandTreeIconLMinus:\"goog-tree-expand-icon-lminus\",cssExpandTreeIconT:\"goog-tree-expand-icon-t\",cssExpandTreeIconL:\"goog-tree-expand-icon-l\",cssExpandTreeIconBlank:\"goog-tree-expand-icon-blank\",cssExpandedFolderIcon:\"goog-tree-expanded-folder-icon\",cssCollapsedFolderIcon:\"goog-tree-collapsed-folder-icon\",cssFileIcon:\"goog-tree-file-icon\",cssExpandedRootIcon:\"goog-tree-expanded-folder-icon\",\ncssCollapsedRootIcon:\"goog-tree-collapsed-folder-icon\",cssSelectedRow:\"selected\"};goog.ui.tree.TreeNode=function(a,b,c){goog.ui.tree.BaseNode.call(this,a,b,c)};goog.inherits(goog.ui.tree.TreeNode,goog.ui.tree.BaseNode);goog.ui.tree.TreeNode.prototype.getTree=function(){if(this.tree)return this.tree;var a=this.getParent();return a&&(a=a.getTree())?(this.setTreeInternal(a),a):null};\ngoog.ui.tree.TreeNode.prototype.getCalculatedIconClass=function(){var a=this.getExpanded(),b=this.getExpandedIconClass();if(a&&b)return b;b=this.getIconClass();if(!a&&b)return b;b=this.getConfig();if(this.hasChildren()){if(a&&b.cssExpandedFolderIcon)return b.cssTreeIcon+\" \"+b.cssExpandedFolderIcon;if(!a&&b.cssCollapsedFolderIcon)return b.cssTreeIcon+\" \"+b.cssCollapsedFolderIcon}else if(b.cssFileIcon)return b.cssTreeIcon+\" \"+b.cssFileIcon;return\"\"};goog.structs.Trie=function(a){this.value_=void 0;this.childNodes_={};a&&this.setAll(a)};goog.structs.Trie.prototype.set=function(a,b){this.setOrAdd_(a,b,!1)};goog.structs.Trie.prototype.add=function(a,b){this.setOrAdd_(a,b,!0)};\ngoog.structs.Trie.prototype.setOrAdd_=function(a,b,c){for(var d=this,e=0;e<a.length;e++){var f=a.charAt(e);d.childNodes_[f]||(d.childNodes_[f]=new goog.structs.Trie);d=d.childNodes_[f]}if(c&&void 0!==d.value_)throw Error('The collection already contains the key \"'+a+'\"');d.value_=b};goog.structs.Trie.prototype.setAll=function(a){var b=goog.structs.getKeys(a);a=goog.structs.getValues(a);for(var c=0;c<b.length;c++)this.set(b[c],a[c])};\ngoog.structs.Trie.prototype.getChildNode_=function(a){for(var b=this,c=0;c<a.length;c++){var d=a.charAt(c),b=b.childNodes_[d];if(!b)return}return b};goog.structs.Trie.prototype.get=function(a){return(a=this.getChildNode_(a))?a.value_:void 0};goog.structs.Trie.prototype.getKeyAndPrefixes=function(a,b){var c=this,d={},e=b||0;void 0!==c.value_&&(d[e]=c.value_);for(;e<a.length;e++){var f=a.charAt(e);if(!(f in c.childNodes_))break;c=c.childNodes_[f];void 0!==c.value_&&(d[e]=c.value_)}return d};\ngoog.structs.Trie.prototype.getValues=function(){var a=[];this.getValuesInternal_(a);return a};goog.structs.Trie.prototype.getValuesInternal_=function(a){void 0!==this.value_&&a.push(this.value_);for(var b in this.childNodes_)this.childNodes_[b].getValuesInternal_(a)};goog.structs.Trie.prototype.getKeys=function(a){var b=[];if(a){for(var c=this,d=0;d<a.length;d++){var e=a.charAt(d);if(!c.childNodes_[e])return[];c=c.childNodes_[e]}c.getKeysInternal_(a,b)}else this.getKeysInternal_(\"\",b);return b};\ngoog.structs.Trie.prototype.getKeysInternal_=function(a,b){void 0!==this.value_&&b.push(a);for(var c in this.childNodes_)this.childNodes_[c].getKeysInternal_(a+c,b)};goog.structs.Trie.prototype.containsKey=function(a){return void 0!==this.get(a)};goog.structs.Trie.prototype.containsPrefix=function(a){return 0==a.length?!this.isEmpty():!!this.getChildNode_(a)};\ngoog.structs.Trie.prototype.containsValue=function(a){if(this.value_===a)return!0;for(var b in this.childNodes_)if(this.childNodes_[b].containsValue(a))return!0;return!1};goog.structs.Trie.prototype.clear=function(){this.childNodes_={};this.value_=void 0};\ngoog.structs.Trie.prototype.remove=function(a){for(var b=this,c=[],d=0;d<a.length;d++){var e=a.charAt(d);if(!b.childNodes_[e])throw Error('The collection does not have the key \"'+a+'\"');c.push([b,e]);b=b.childNodes_[e]}a=b.value_;for(delete b.value_;0<c.length;)if(e=c.pop(),b=e[0],e=e[1],b.childNodes_[e].isEmpty())delete b.childNodes_[e];else break;return a};goog.structs.Trie.prototype.clone=function(){return new goog.structs.Trie(this)};goog.structs.Trie.prototype.getCount=function(){return goog.structs.getCount(this.getValues())};\ngoog.structs.Trie.prototype.isEmpty=function(){return void 0===this.value_&&goog.object.isEmpty(this.childNodes_)};goog.ui.tree.TypeAhead=function(){this.nodeMap_=new goog.structs.Trie;this.buffer_=\"\";this.matchingNodes_=this.matchingLabels_=null;this.matchingNodeIndex_=this.matchingLabelIndex_=0};goog.ui.tree.TypeAhead.Offset={DOWN:1,UP:-1};\ngoog.ui.tree.TypeAhead.prototype.handleNavigation=function(a){var b=!1;switch(a.keyCode){case goog.events.KeyCodes.DOWN:case goog.events.KeyCodes.UP:a.ctrlKey&&(this.jumpTo_(a.keyCode==goog.events.KeyCodes.DOWN?goog.ui.tree.TypeAhead.Offset.DOWN:goog.ui.tree.TypeAhead.Offset.UP),b=!0);break;case goog.events.KeyCodes.BACKSPACE:a=this.buffer_.length-1;b=!0;0<a?(this.buffer_=this.buffer_.substring(0,a),this.jumpToLabel_(this.buffer_)):0==a?this.buffer_=\"\":b=!1;break;case goog.events.KeyCodes.ESC:this.buffer_=\n\"\",b=!0}return b};goog.ui.tree.TypeAhead.prototype.handleTypeAheadChar=function(a){var b=!1;a.ctrlKey||a.altKey||(a=String.fromCharCode(a.charCode||a.keyCode).toLowerCase(),goog.string.isUnicodeChar(a)&&(\" \"!=a||this.buffer_)&&(this.buffer_+=a,b=this.jumpToLabel_(this.buffer_)));return b};\ngoog.ui.tree.TypeAhead.prototype.setNodeInMap=function(a){var b=a.getText();if(b&&!goog.string.isEmptyOrWhitespace(goog.string.makeSafe(b))){var b=b.toLowerCase(),c=this.nodeMap_.get(b);c?c.push(a):this.nodeMap_.set(b,[a])}};\ngoog.ui.tree.TypeAhead.prototype.removeNodeFromMap=function(a){var b=a.getText();if(b&&!goog.string.isEmptyOrWhitespace(goog.string.makeSafe(b))){var b=b.toLowerCase(),c=this.nodeMap_.get(b);if(c){for(var d=a.getChildCount(),e=0;e<d;e++)this.removeNodeFromMap(a.getChildAt(e));goog.array.remove(c,a);c.length||this.nodeMap_.remove(b)}}};\ngoog.ui.tree.TypeAhead.prototype.jumpToLabel_=function(a){var b=!1;(a=this.nodeMap_.getKeys(a))&&a.length&&(this.matchingLabelIndex_=this.matchingNodeIndex_=0,b=this.nodeMap_.get(a[0]),b=this.selectMatchingNode_(b))&&(this.matchingLabels_=a);return b};\ngoog.ui.tree.TypeAhead.prototype.jumpTo_=function(a){var b=!1,c=this.matchingLabels_;if(c){var b=null,d=!1;if(this.matchingNodes_){var e=this.matchingNodeIndex_+a;0<=e&&e<this.matchingNodes_.length?(this.matchingNodeIndex_=e,b=this.matchingNodes_):d=!0}b||(e=this.matchingLabelIndex_+a,0<=e&&e<c.length&&(this.matchingLabelIndex_=e),c.length>this.matchingLabelIndex_&&(b=this.nodeMap_.get(c[this.matchingLabelIndex_])),b&&b.length&&d&&(this.matchingNodeIndex_=a==goog.ui.tree.TypeAhead.Offset.UP?b.length-\n1:0));if(b=this.selectMatchingNode_(b))this.matchingLabels_=c}return b};goog.ui.tree.TypeAhead.prototype.selectMatchingNode_=function(a){var b;a&&(this.matchingNodeIndex_<a.length&&(b=a[this.matchingNodeIndex_],this.matchingNodes_=a),b&&(b.reveal(),b.select()));return!!b};goog.ui.tree.TypeAhead.prototype.clear=function(){this.buffer_=\"\"};goog.ui.tree.TreeControl=function(a,b,c){goog.ui.tree.BaseNode.call(this,a,b,c);this.setExpandedInternal(!0);this.setSelectedInternal(!0);this.selectedItem_=this;this.typeAhead_=new goog.ui.tree.TypeAhead;this.focusHandler_=this.keyHandler_=null;this.logger_=goog.log.getLogger(\"this\");this.focused_=!1;this.focusedNode_=null;this.showRootLines_=this.showRootNode_=this.showExpandIcons_=this.showLines_=!0;if(goog.userAgent.IE)try{document.execCommand(\"BackgroundImageCache\",!1,!0)}catch(d){goog.log.warning(this.logger_,\n\"Failed to enable background image cache\")}};goog.inherits(goog.ui.tree.TreeControl,goog.ui.tree.BaseNode);goog.ui.tree.TreeControl.prototype.getTree=function(){return this};goog.ui.tree.TreeControl.prototype.getDepth=function(){return 0};goog.ui.tree.TreeControl.prototype.reveal=function(){};goog.ui.tree.TreeControl.prototype.handleFocus_=function(a){this.focused_=!0;goog.dom.classlist.add(goog.asserts.assert(this.getElement()),\"focused\");this.selectedItem_&&this.selectedItem_.select()};\ngoog.ui.tree.TreeControl.prototype.handleBlur_=function(a){this.focused_=!1;goog.dom.classlist.remove(goog.asserts.assert(this.getElement()),\"focused\")};goog.ui.tree.TreeControl.prototype.hasFocus=function(){return this.focused_};goog.ui.tree.TreeControl.prototype.getExpanded=function(){return!this.showRootNode_||goog.ui.tree.TreeControl.superClass_.getExpanded.call(this)};\ngoog.ui.tree.TreeControl.prototype.setExpanded=function(a){this.showRootNode_?goog.ui.tree.TreeControl.superClass_.setExpanded.call(this,a):this.setExpandedInternal(a)};goog.ui.tree.TreeControl.prototype.getExpandIconSafeHtml=function(){return goog.html.SafeHtml.EMPTY};goog.ui.tree.TreeControl.prototype.getIconElement=function(){var a=this.getRowElement();return a?a.firstChild:null};goog.ui.tree.TreeControl.prototype.getExpandIconElement=function(){return null};\ngoog.ui.tree.TreeControl.prototype.updateExpandIcon=function(){};goog.ui.tree.TreeControl.prototype.getRowClassName=function(){return goog.ui.tree.TreeControl.superClass_.getRowClassName.call(this)+(this.showRootNode_?\"\":\" \"+this.getConfig().cssHideRoot)};\ngoog.ui.tree.TreeControl.prototype.getCalculatedIconClass=function(){var a=this.getExpanded(),b=this.getExpandedIconClass();if(a&&b)return b;b=this.getIconClass();if(!a&&b)return b;b=this.getConfig();return a&&b.cssExpandedRootIcon?b.cssTreeIcon+\" \"+b.cssExpandedRootIcon:!a&&b.cssCollapsedRootIcon?b.cssTreeIcon+\" \"+b.cssCollapsedRootIcon:\"\"};\ngoog.ui.tree.TreeControl.prototype.setSelectedItem=function(a){if(this.selectedItem_!=a){var b=!1;this.selectedItem_&&(b=this.selectedItem_==this.focusedNode_,this.selectedItem_.setSelectedInternal(!1));if(this.selectedItem_=a)a.setSelectedInternal(!0),b&&a.select();this.dispatchEvent(goog.events.EventType.CHANGE)}};goog.ui.tree.TreeControl.prototype.getSelectedItem=function(){return this.selectedItem_};\ngoog.ui.tree.TreeControl.prototype.setShowLines=function(a){this.showLines_!=a&&(this.showLines_=a,this.isInDocument()&&this.updateLinesAndExpandIcons_())};goog.ui.tree.TreeControl.prototype.getShowLines=function(){return this.showLines_};\ngoog.ui.tree.TreeControl.prototype.updateLinesAndExpandIcons_=function(){function a(e){var f=e.getChildrenElement();if(f){var g=!c||b==e.getParent()&&!d?e.getConfig().cssChildrenNoLines:e.getConfig().cssChildren;f.className=g;if(f=e.getExpandIconElement())f.className=e.getExpandIconClass()}e.forEachChild(a)}var b=this,c=b.getShowLines(),d=b.getShowRootLines();a(this)};\ngoog.ui.tree.TreeControl.prototype.setShowRootLines=function(a){this.showRootLines_!=a&&(this.showRootLines_=a,this.isInDocument()&&this.updateLinesAndExpandIcons_())};goog.ui.tree.TreeControl.prototype.getShowRootLines=function(){return this.showRootLines_};goog.ui.tree.TreeControl.prototype.setShowExpandIcons=function(a){this.showExpandIcons_!=a&&(this.showExpandIcons_=a,this.isInDocument()&&this.updateLinesAndExpandIcons_())};goog.ui.tree.TreeControl.prototype.getShowExpandIcons=function(){return this.showExpandIcons_};\ngoog.ui.tree.TreeControl.prototype.setShowRootNode=function(a){if(this.showRootNode_!=a){this.showRootNode_=a;if(this.isInDocument()){var b=this.getRowElement();b&&(b.className=this.getRowClassName())}!a&&this.getSelectedItem()==this&&this.getFirstChild()&&this.setSelectedItem(this.getFirstChild())}};goog.ui.tree.TreeControl.prototype.getShowRootNode=function(){return this.showRootNode_};\ngoog.ui.tree.TreeControl.prototype.initAccessibility=function(){goog.ui.tree.TreeControl.superClass_.initAccessibility.call(this);var a=this.getElement();goog.asserts.assert(a,\"The DOM element for the tree cannot be null.\");goog.a11y.aria.setRole(a,\"tree\");goog.a11y.aria.setState(a,\"labelledby\",this.getLabelElement().id)};\ngoog.ui.tree.TreeControl.prototype.enterDocument=function(){goog.ui.tree.TreeControl.superClass_.enterDocument.call(this);var a=this.getElement();a.className=this.getConfig().cssRoot;a.setAttribute(\"hideFocus\",\"true\");this.attachEvents_();this.initAccessibility()};goog.ui.tree.TreeControl.prototype.exitDocument=function(){goog.ui.tree.TreeControl.superClass_.exitDocument.call(this);this.detachEvents_()};\ngoog.ui.tree.TreeControl.prototype.attachEvents_=function(){var a=this.getElement();a.tabIndex=0;var b=this.keyHandler_=new goog.events.KeyHandler(a),c=this.focusHandler_=new goog.events.FocusHandler(a);this.getHandler().listen(c,goog.events.FocusHandler.EventType.FOCUSOUT,this.handleBlur_).listen(c,goog.events.FocusHandler.EventType.FOCUSIN,this.handleFocus_).listen(b,goog.events.KeyHandler.EventType.KEY,this.handleKeyEvent).listen(a,goog.events.EventType.MOUSEDOWN,this.handleMouseEvent_).listen(a,\ngoog.events.EventType.CLICK,this.handleMouseEvent_).listen(a,goog.events.EventType.DBLCLICK,this.handleMouseEvent_)};goog.ui.tree.TreeControl.prototype.detachEvents_=function(){this.keyHandler_.dispose();this.keyHandler_=null;this.focusHandler_.dispose();this.focusHandler_=null};\ngoog.ui.tree.TreeControl.prototype.handleMouseEvent_=function(a){goog.log.fine(this.logger_,\"Received event \"+a.type);var b=this.getNodeFromEvent_(a);if(b)switch(a.type){case goog.events.EventType.MOUSEDOWN:b.onMouseDown(a);break;case goog.events.EventType.CLICK:b.onClick_(a);break;case goog.events.EventType.DBLCLICK:b.onDoubleClick_(a)}};\ngoog.ui.tree.TreeControl.prototype.handleKeyEvent=function(a){var b;(b=this.typeAhead_.handleNavigation(a)||this.selectedItem_&&this.selectedItem_.onKeyDown(a)||this.typeAhead_.handleTypeAheadChar(a))&&a.preventDefault();return b};goog.ui.tree.TreeControl.prototype.getNodeFromEvent_=function(a){for(var b=a.target;null!=b;){if(a=goog.ui.tree.BaseNode.allNodes[b.id])return a;if(b==this.getElement())break;b=b.parentNode}return null};\ngoog.ui.tree.TreeControl.prototype.createNode=function(a){return new goog.ui.tree.TreeNode(a||goog.html.SafeHtml.EMPTY,this.getConfig(),this.getDomHelper())};goog.ui.tree.TreeControl.prototype.setNode=function(a){this.typeAhead_.setNodeInMap(a)};goog.ui.tree.TreeControl.prototype.removeNode=function(a){this.typeAhead_.removeNodeFromMap(a)};goog.ui.tree.TreeControl.prototype.clearTypeAhead=function(){this.typeAhead_.clear()};goog.ui.tree.TreeControl.defaultConfig=goog.ui.tree.BaseNode.defaultConfig;goog.cssom={};goog.cssom.CssRuleType={STYLE:1,IMPORT:3,MEDIA:4,FONT_FACE:5,PAGE:6,NAMESPACE:7};goog.cssom.getAllCssText=function(a){return goog.cssom.getAllCss_(a||document.styleSheets,!0)};goog.cssom.getAllCssStyleRules=function(a){return goog.cssom.getAllCss_(a||document.styleSheets,!1)};goog.cssom.getCssRulesFromStyleSheet=function(a){var b=null;try{b=a.cssRules||a.rules}catch(c){if(15==c.code)throw c.styleSheet=a,c;}return b};\ngoog.cssom.getAllCssStyleSheets=function(a,b){var c=[],d=a||document.styleSheets,e=goog.isDef(b)?b:!1;if(d.imports&&d.imports.length)for(var f=0,g=d.imports.length;f<g;f++)goog.array.extend(c,goog.cssom.getAllCssStyleSheets(d.imports[f]));else if(d.length)for(f=0,g=d.length;f<g;f++)goog.array.extend(c,goog.cssom.getAllCssStyleSheets(d[f]));else{var h=goog.cssom.getCssRulesFromStyleSheet(d);if(h&&h.length)for(var f=0,g=h.length,k;f<g;f++)k=h[f],k.styleSheet&&goog.array.extend(c,goog.cssom.getAllCssStyleSheets(k.styleSheet))}!(d.type||\nd.rules||d.cssRules)||d.disabled&&!e||c.push(d);return c};goog.cssom.getCssTextFromCssRule=function(a){var b=\"\";a.cssText?b=a.cssText:a.style&&a.style.cssText&&a.selectorText&&(b=a.style.cssText.replace(/\\s*-closure-parent-stylesheet:\\s*\\[object\\];?\\s*/gi,\"\").replace(/\\s*-closure-rule-index:\\s*[\\d]+;?\\s*/gi,\"\"),b=a.selectorText+\" { \"+b+\" }\");return b};\ngoog.cssom.getCssRuleIndexInParentStyleSheet=function(a,b){if(a.style&&a.style[\"-closure-rule-index\"])return a.style[\"-closure-rule-index\"];var c=b||goog.cssom.getParentStyleSheet(a);if(!c)throw Error(\"Cannot find a parentStyleSheet.\");if((c=goog.cssom.getCssRulesFromStyleSheet(c))&&c.length)for(var d=0,e=c.length,f;d<e;d++)if(f=c[d],f==a)return d;return-1};goog.cssom.getParentStyleSheet=function(a){return a.parentStyleSheet||a.style&&a.style[\"-closure-parent-stylesheet\"]};\ngoog.cssom.replaceCssRule=function(a,b,c,d){if(c=c||goog.cssom.getParentStyleSheet(a))if(a=0<=Number(d)?Number(d):goog.cssom.getCssRuleIndexInParentStyleSheet(a,c),0<=a)goog.cssom.removeCssRule(c,a),goog.cssom.addCssRule(c,b,a);else throw Error(\"Cannot proceed without the index of the cssRule.\");else throw Error(\"Cannot proceed without the parentStyleSheet.\");};\ngoog.cssom.addCssRule=function(a,b,c){if(void 0==c||0>c)c=goog.cssom.getCssRulesFromStyleSheet(a).length;if(a.insertRule)a.insertRule(b,c);else if(b=/^([^\\{]+)\\{([^\\{]+)\\}/.exec(b),3==b.length)a.addRule(b[1],b[2],c);else throw Error(\"Your CSSRule appears to be ill-formatted.\");};goog.cssom.removeCssRule=function(a,b){a.deleteRule?a.deleteRule(b):a.removeRule(b)};\ngoog.cssom.addCssText=function(a,b){var c=b?b.getDocument():goog.dom.getDocument(),d=c.createElement(\"STYLE\");d.type=\"text/css\";c.getElementsByTagName(\"HEAD\")[0].appendChild(d);d.styleSheet?d.styleSheet.cssText=a:(c=c.createTextNode(a),d.appendChild(c));return d};goog.cssom.getFileNameFromStyleSheet=function(a){return(a=a.href)?/([^\\/\\?]+)[^\\/]*$/.exec(a)[1]:null};\ngoog.cssom.getAllCss_=function(a,b){for(var c=[],d=goog.cssom.getAllCssStyleSheets(a),e=0;a=d[e];e++){var f=goog.cssom.getCssRulesFromStyleSheet(a);if(f&&f.length)for(var g=0,h=0,k=f.length,n;h<k;h++)n=f[h],b&&!n.href?(n=goog.cssom.getCssTextFromCssRule(n),c.push(n)):n.href||(n.style&&(n.parentStyleSheet||(n.style[\"-closure-parent-stylesheet\"]=a),n.style[\"-closure-rule-index\"]=b?void 0:g),c.push(n)),b||g++}return b?c.join(\" \"):c};\n// Copyright 2012 Google Inc.  Apache License 2.0\nvar Blockly={BlockSvg:function(a){this.block_=a;this.svgGroup_=Blockly.createSvgElement(\"g\",{},null);this.svgGroup_.block=this.block_;this.svgPathDark_=Blockly.createSvgElement(\"path\",{\"class\":\"blocklyPathDark\",transform:\"translate(0, 1)\"},this.svgGroup_);this.svgPath_=Blockly.createSvgElement(\"path\",{\"class\":\"blocklyPath\"},this.svgGroup_);Blockly.enableBlockAnimation&&(this.svgPathPatternA_=Blockly.createSvgElement(\"path\",{id:\"blocklyPathPattern1\",\"class\":\"blocklyPathPattern\"},this.svgGroup_),this.svgPathPatternB_=\nBlockly.createSvgElement(\"path\",{id:\"blocklyPathPattern2\",\"class\":\"blocklyPathPattern\"},this.svgGroup_),this.svgPathPatternC_=Blockly.createSvgElement(\"path\",{id:\"blocklyPathPattern3\",\"class\":\"blocklyPathPattern\"},this.svgGroup_),this.svgPathPatternD_=Blockly.createSvgElement(\"path\",{id:\"blocklyPathPattern4\",\"class\":\"blocklyPathPattern\"},this.svgGroup_));this.block_.outputConnection&&(this.svgPathLight_=Blockly.createSvgElement(\"path\",{\"class\":\"blocklyPathLight\"},this.svgGroup_));this.svgPath_.tooltip=\nthis.block_;Blockly.Tooltip&&Blockly.Tooltip.bindMouseEvents(this.svgPath_);this.updateMovable()}};Blockly.BlockSvg.INLINE=-1;Blockly.BlockSvg.prototype.init=function(){var a=this.block_;this.updateColour();for(var b=0,c;c=a.inputList[b];b++)c.init();a.mutator&&a.mutator.createIcon()};Blockly.BlockSvg.prototype.updateMovable=function(){this.block_.isMovable()?Blockly.addClass_(this.svgGroup_,\"blocklyDraggable\"):Blockly.removeClass_(this.svgGroup_,\"blocklyDraggable\")};\nBlockly.BlockSvg.prototype.toggleOnPattern=function(a){Blockly.addClass_(this.svgGroup_.parentNode,\"disablePattern\");Blockly.addClass_(this.svgGroup_,\"togglePattern\")};Blockly.BlockSvg.prototype.toggleOffPattern=function(a){Blockly.removeClass_(this.svgGroup_.parentNode,\"disablePattern\");Blockly.removeClass_(this.svgGroup_,\"togglePattern\")};Blockly.BlockSvg.prototype.getRootElement=function(){return this.svgGroup_};Blockly.BlockSvg.SEP_SPACE_X=4;Blockly.BlockSvg.SEP_SPACE_Y=10;\nBlockly.BlockSvg.INLINE_PADDING_Y=2;Blockly.BlockSvg.MIN_BLOCK_Y=30;Blockly.BlockSvg.MIN_INLINE_BLOCK_Y=20;Blockly.BlockSvg.TAB_HEIGHT=20;Blockly.BlockSvg.TAB_WIDTH=8;Blockly.BlockSvg.NOTCH_WIDTH=16;Blockly.BlockSvg.CORNER_RADIUS=0;Blockly.BlockSvg.FIELD_HEIGHT=0;Blockly.BlockSvg.DISTANCE_45_INSIDE=(1-Math.SQRT1_2)*(Blockly.BlockSvg.CORNER_RADIUS-1)+1;Blockly.BlockSvg.DISTANCE_45_OUTSIDE=(1-Math.SQRT1_2)*(Blockly.BlockSvg.CORNER_RADIUS+1)-1;Blockly.BlockSvg.NOTCH_PATH_LEFT=\"l 8,8 8,-8\";\nBlockly.BlockSvg.NOTCH_PATH_LEFT_HIGHLIGHT=\"l 6.5,4 2,0 6.5,-4\";Blockly.BlockSvg.NOTCH_PATH_RIGHT=\"l -8,8 -8,-8\";Blockly.BlockSvg.JAGGED_TEETH=\"l 8,0 0,4 8,4 -16,8 8,4\";Blockly.BlockSvg.JAGGED_TEETH_HEIGHT=20;Blockly.BlockSvg.TAB_PATH_DOWN=\"v 5 c 0,10 -\"+Blockly.BlockSvg.TAB_WIDTH+\",-8 -\"+Blockly.BlockSvg.TAB_WIDTH+\",7.5 s \"+Blockly.BlockSvg.TAB_WIDTH+\",-2.5 \"+Blockly.BlockSvg.TAB_WIDTH+\",7.5\";\nBlockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL=\"v 6.5 m -\"+.98*Blockly.BlockSvg.TAB_WIDTH+\",2.5 q -\"+.05*Blockly.BlockSvg.TAB_WIDTH+\",10 \"+.27*Blockly.BlockSvg.TAB_WIDTH+\",10 m \"+.71*Blockly.BlockSvg.TAB_WIDTH+\",-2.5 v 1.5\";Blockly.BlockSvg.TOP_LEFT_CORNER_START=\"m 0,\"+Blockly.BlockSvg.CORNER_RADIUS;Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_RTL=\"m \"+Blockly.BlockSvg.DISTANCE_45_INSIDE+\",\"+Blockly.BlockSvg.DISTANCE_45_INSIDE;\nBlockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_LTR=\"m 1,\"+(Blockly.BlockSvg.CORNER_RADIUS-1);Blockly.BlockSvg.TOP_LEFT_CORNER=\"A \"+Blockly.BlockSvg.CORNER_RADIUS+\",\"+Blockly.BlockSvg.CORNER_RADIUS+\" 0 0,1 \"+Blockly.BlockSvg.CORNER_RADIUS+\",0\";Blockly.BlockSvg.TOP_LEFT_CORNER_HIGHLIGHT=\"A \"+(Blockly.BlockSvg.CORNER_RADIUS-1)+\",\"+(Blockly.BlockSvg.CORNER_RADIUS-1)+\" 0 0,1 \"+Blockly.BlockSvg.CORNER_RADIUS+\",1\";\nBlockly.BlockSvg.INNER_TOP_LEFT_CORNER=Blockly.BlockSvg.NOTCH_PATH_RIGHT+\" h -0.6 h\"+Blockly.BlockSvg.CORNER_RADIUS+\" a \"+Blockly.BlockSvg.CORNER_RADIUS+\",\"+Blockly.BlockSvg.CORNER_RADIUS+\" 0 0,0 -\"+Blockly.BlockSvg.CORNER_RADIUS+\",\"+Blockly.BlockSvg.CORNER_RADIUS;Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER=\"a \"+Blockly.BlockSvg.CORNER_RADIUS+\",\"+Blockly.BlockSvg.CORNER_RADIUS+\" 0 0,0 \"+Blockly.BlockSvg.CORNER_RADIUS+\",\"+Blockly.BlockSvg.CORNER_RADIUS;\nBlockly.BlockSvg.INNER_TOP_LEFT_CORNER_HIGHLIGHT_RTL=\"a \"+(Blockly.BlockSvg.CORNER_RADIUS+1)+\",\"+(Blockly.BlockSvg.CORNER_RADIUS+1)+\" 0 0,0 \"+(-Blockly.BlockSvg.DISTANCE_45_OUTSIDE-1)+\",\"+(Blockly.BlockSvg.CORNER_RADIUS-Blockly.BlockSvg.DISTANCE_45_OUTSIDE);Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_RTL=\"a \"+(Blockly.BlockSvg.CORNER_RADIUS+1)+\",\"+(Blockly.BlockSvg.CORNER_RADIUS+1)+\" 0 0,0 \"+(Blockly.BlockSvg.CORNER_RADIUS+1)+\",\"+(Blockly.BlockSvg.CORNER_RADIUS+1);\nBlockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR=\"a \"+(Blockly.BlockSvg.CORNER_RADIUS+1)+\",\"+(Blockly.BlockSvg.CORNER_RADIUS+1)+\" 0 0,0 \"+(Blockly.BlockSvg.CORNER_RADIUS-Blockly.BlockSvg.DISTANCE_45_OUTSIDE)+\",\"+(Blockly.BlockSvg.DISTANCE_45_OUTSIDE+1);\nBlockly.BlockSvg.prototype.dispose=function(){goog.dom.removeNode(this.svgGroup_);this.svgPath_=this.svgGroup_=null;Blockly.enableBlockAnimation&&(this.svgPathPatternD_=this.svgPathPatternC_=this.svgPathPatternB_=this.svgPathPatternA_=null);this.block_=this.svgPathDark_=this.svgPathLight_=null};\nBlockly.BlockSvg.prototype.disposeUiEffect=function(){Blockly.playAudio(\"delete\");var a=Blockly.getSvgXY_(this.svgGroup_),b=this.svgGroup_.cloneNode(!0);b.translateX_=a.x;b.translateY_=a.y;b.setAttribute(\"transform\",\"translate(\"+b.translateX_+\",\"+b.translateY_+\")\");Blockly.svg.appendChild(b);b.bBox_=b.getBBox();b.startDate_=new Date;Blockly.BlockSvg.disposeUiStep_(b)};\nBlockly.BlockSvg.disposeUiStep_=function(a){var b=a.getElementsByTagName(\"text\");if(b)for(var c=0;c<b.length;c++)b[c].parentNode.removeChild(b[c]);b=(new Date-a.startDate_)/100;1<b?goog.dom.removeNode(a):(a.setAttribute(\"transform\",\"translate(\"+(a.translateX_+(Blockly.RTL?-1:1)*a.bBox_.width/2*b+\", \"+(a.translateY_+a.bBox_.height*b))+\") scale(\"+(1-b)+\")\"),window.setTimeout(function(){Blockly.BlockSvg.disposeUiStep_(a)},10))};\nBlockly.BlockSvg.prototype.connectionUiEffect=function(){Blockly.playAudio(\"click\");var a=Blockly.getSvgXY_(this.svgGroup_);this.block_.outputConnection?(a.x+=Blockly.RTL?3:-3,a.y+=13):this.block_.previousConnection&&(a.x+=Blockly.RTL?-23:23,a.y+=3);a=Blockly.createSvgElement(\"circle\",{cx:a.x,cy:a.y,r:0,fill:\"none\",stroke:\"#888\",\"stroke-width\":10},Blockly.svg);a.startDate_=new Date;Blockly.BlockSvg.connectionUiStep_(a)};\nBlockly.BlockSvg.connectionUiStep_=function(a){var b=(new Date-a.startDate_)/150;1<b?goog.dom.removeNode(a):(a.setAttribute(\"r\",25*b),a.style.opacity=1-b,window.setTimeout(function(){Blockly.BlockSvg.connectionUiStep_(a)},10))};\nBlockly.BlockSvg.prototype.updateColour=function(){if(!this.block_.disabled){var a=Blockly.makeColour(this.block_.getColour()),b=goog.color.hexToRgb(a),c=goog.color.darken(b,.1),b=goog.color.darken(b,.3);this.block_.outputConnection&&this.svgPathLight_.setAttribute(\"stroke\",goog.color.rgbArrayToHex(c));this.block_.outputConnection&&(this.block_.parentBlock_?this.svgPathDark_.setAttribute(\"opacity\",0):this.svgPathDark_.removeAttribute(\"opacity\"));this.svgPathDark_.setAttribute(\"fill\",goog.color.rgbArrayToHex(b));\nthis.svgPath_.setAttribute(\"fill\",a);Blockly.enableBlockAnimation&&(this.svgPathPatternA_.setAttribute(\"fill\",\"url(#blockPattern1)\"),Blockly.createSvgElement(\"animate\",{attributeName:\"opacity\",values:\"0;0.2;0;0\",repeatCount:\"indefinite\",begin:\"0\",dur:\"1.4s\"},this.svgPathPatternA_),this.svgPathPatternB_.setAttribute(\"fill\",\"url(#blockPattern2)\"),Blockly.createSvgElement(\"animate\",{attributeName:\"opacity\",values:\"0;0.2;0;0\",repeatCount:\"indefinite\",begin:\"0.33\",dur:\"1.4s\"},this.svgPathPatternB_),this.svgPathPatternC_.setAttribute(\"fill\",\n\"url(#blockPattern3)\"),Blockly.createSvgElement(\"animate\",{attributeName:\"opacity\",values:\"0;0.2;0;0\",repeatCount:\"indefinite\",begin:\"0.67\",dur:\"1.4s\"},this.svgPathPatternC_),this.svgPathPatternD_.setAttribute(\"fill\",\"url(#blockPattern4)\"));Blockly.createSvgElement(\"animate\",{attributeName:\"opacity\",values:\"0;0.2;0;0\",repeatCount:\"indefinite\",begin:\"1\",dur:\"1.4s\"},this.svgPathPatternD_)}};\nBlockly.BlockSvg.prototype.updateDisabled=function(){this.block_.disabled||this.block_.getInheritedDisabled()?(Blockly.addClass_(this.svgGroup_,\"blocklyDisabled\"),this.svgPath_.setAttribute(\"fill\",\"gray\")):(Blockly.removeClass_(this.svgGroup_,\"blocklyDisabled\"),this.updateColour());for(var a=this.block_.getChildren(),b=0,c;c=a[b];b++)c.svg_.updateDisabled()};Blockly.BlockSvg.prototype.addSelect=function(){Blockly.addClass_(this.svgGroup_,\"blocklySelected\");this.block_.isInBlockMenu||this.svgGroup_.parentNode.appendChild(this.svgGroup_)};\nBlockly.BlockSvg.prototype.removeSelect=function(){Blockly.removeClass_(this.svgGroup_,\"blocklySelected\");Blockly.removeClass_(this.svgGroup_,\"blocklyActivated\")};Blockly.BlockSvg.prototype.addActive=function(){Blockly.addClass_(this.svgGroup_,\"blocklyActivated\");this.svgGroup_.parentNode.appendChild(this.svgGroup_)};Blockly.BlockSvg.prototype.removeActive=function(){Blockly.removeClass_(this.svgGroup_,\"blocklyActivated\")};\nBlockly.BlockSvg.prototype.addDragging=function(){Blockly.addClass_(this.svgGroup_,\"blocklyDragging\")};Blockly.BlockSvg.prototype.removeDragging=function(){Blockly.removeClass_(this.svgGroup_,\"blocklyDragging\")};\nBlockly.BlockSvg.prototype.render=function(){this.block_.rendered=!0;for(var a=Blockly.BlockSvg.SEP_SPACE_X,b=this.block_.getIcons(),c=0;c<b.length;c++)a=b[c].renderIcon(a);a+=Blockly.RTL?Blockly.BlockSvg.SEP_SPACE_X:-Blockly.BlockSvg.SEP_SPACE_X;b=this.renderCompute_(a);this.renderDraw_(a,b);(a=this.block_.getParent())&&a.render()};\nBlockly.BlockSvg.prototype.renderFields_=function(a,b,c,d){for(var e=0,f;f=a[e];e++){f.isTextInput&&1==a.length&&(b-=4);var g=f.getSize(),h=g.width,g=c+(d-g.height)/2;f.getRootElement().setAttribute(\"transform\",\"translate(\"+b+\", \"+g+\")\");h&&(b+=h+Blockly.BlockSvg.SEP_SPACE_X);f.isTextInput&&1==a.length&&(b+=4)}return Blockly.RTL?-b:b};\nBlockly.BlockSvg.prototype.renderCompute_=function(a){var b=this.block_.inputList,c=[];c.rightEdge=a+2*Blockly.BlockSvg.SEP_SPACE_X;if(this.block_.previousConnection||this.block_.nextConnection)c.rightEdge=Math.max(c.rightEdge,Blockly.BlockSvg.NOTCH_WIDTH+Blockly.BlockSvg.SEP_SPACE_X);for(var d=0,e=0,f=!1,g=!1,h=!1,k=void 0,n=this.block_.inputsInline&&!this.block_.isCollapsed(),p=0,m;m=b[p];p++)if(m.isVisible()){var l;n&&k&&k!=Blockly.NEXT_STATEMENT&&m.type!=Blockly.NEXT_STATEMENT?l=c[c.length-1]:\n(k=m.type,l=[],l.type=n&&m.type!=Blockly.NEXT_STATEMENT?Blockly.BlockSvg.INLINE:m.type,l.height=0,c.push(l));l.push(m);m.renderHeight=m.sourceBlock_.outputConnection?Blockly.BlockSvg.MIN_INLINE_BLOCK_Y:Blockly.BlockSvg.MIN_BLOCK_Y;m.renderWidth=n&&m.type==Blockly.INPUT_VALUE?Blockly.BlockSvg.TAB_WIDTH+Blockly.BlockSvg.SEP_SPACE_X:0;if(m.connection&&m.connection.targetConnection){var q=m.connection.targetBlock().getHeightWidth();m.renderHeight=Blockly.BlockSvg.MIN_INLINE_BLOCK_Y;m.renderHeight=Math.max(m.renderHeight,\nq.height);m.renderWidth=Math.max(m.renderWidth,q.width)}l.height=Math.max(l.height,m.renderHeight);m.fieldWidth=0;1==c.length&&(m.fieldWidth+=Blockly.RTL?-a:a);for(var q=0,r;r=m.fieldRow[q];q++)0==q&&r instanceof Blockly.FieldIcon||(0!=q&&(m.fieldWidth+=Blockly.BlockSvg.SEP_SPACE_X),r=r.getSize(),m.fieldWidth+=r.width,l.height=Math.max(l.height,r.height));l.type!=Blockly.BlockSvg.INLINE&&(l.type==Blockly.NEXT_STATEMENT?(g=!0,e=Math.max(e,m.fieldWidth)):(l.type==Blockly.INPUT_VALUE?f=!0:l.type==Blockly.DUMMY_INPUT&&\n(h=!0),d=Math.max(d,m.fieldWidth)))}for(a=0;l=c[a];a++){l.thicker=!1;if(l.type==Blockly.BlockSvg.INLINE)for(b=0;m=l[b];b++)if(m.type==Blockly.INPUT_VALUE){this.block_.outputConnection&&(l.height+=2*Blockly.BlockSvg.INLINE_PADDING_Y,\"PARAM\"==this.block_.outputConnection.check_[0].toUpperCase()&&(l.height=Blockly.BlockSvg.MIN_BLOCK_Y-6));l.thicker=!0;break}this.height=l.height+10}c.statementEdge=2*Blockly.BlockSvg.SEP_SPACE_X+e;g&&(c.rightEdge=Math.max(c.rightEdge,c.statementEdge+Blockly.BlockSvg.NOTCH_WIDTH));\nf?c.rightEdge=Math.max(c.rightEdge,d+2*Blockly.BlockSvg.SEP_SPACE_X+Blockly.BlockSvg.TAB_WIDTH):h&&(c.rightEdge=Math.max(c.rightEdge,d+2*Blockly.BlockSvg.SEP_SPACE_X));c.hasValue=f;c.hasStatement=g;c.hasDummy=h;return c};\nBlockly.BlockSvg.prototype.renderDraw_=function(a,b){if(this.block_.outputConnection){this.squareBottomLeftCorner_=this.squareTopLeftCorner_=!1;if(this.block_.previousConnection){var c=this.block_.previousConnection.targetBlock();c&&c.nextConnection&&c.nextConnection.targetConnection==this.block_.previousConnection&&(this.squareTopLeftCorner_=!0)}this.block_.nextConnection&&(c=this.block_.nextConnection.targetBlock())&&c.previousConnection&&c.previousConnection.targetConnection==this.block_.nextConnection&&\n(this.squareBottomLeftCorner_=!0)}var c=this.block_.getRelativeToSurfaceXY(),d=[],e=[];this.renderDrawTop_(d,c,b);var f=this.renderDrawRight_(d,e,c,b,a);this.renderDrawBottom_(d,c,f);this.renderDrawLeft_(d,c,f,b);c=d.join(\" \")+\"\\n\"+e.join(\" \");this.svgPath_.setAttribute(\"d\",c);Blockly.enableBlockAnimation&&(this.svgPathPatternA_.setAttribute(\"d\",c),this.svgPathPatternB_.setAttribute(\"d\",c),this.svgPathPatternC_.setAttribute(\"d\",c),this.svgPathPatternD_.setAttribute(\"d\",c));this.svgPathDark_.setAttribute(\"d\",\nc);this.block_.outputConnection&&this.svgPathLight_.setAttribute(\"d\",c);c=this.block_;!c.previousConnection||c.nextConnection||c.outputConnection||c.dummySpace||(c.dummySpace=!0,Blockly.createSvgElement(\"rect\",{\"class\":\"BlockSpaceDummy\",height:\"9\",width:\"10\",y:this.height-10,opacity:\"0\"},c.svg_.svgGroup_))};\nBlockly.BlockSvg.prototype.renderDrawTop_=function(a,b,c){a.push(\"m 0,0\");Blockly.BROKEN_CONTROL_POINTS&&a.push(\"c 0,4 0,-4 0,0\");c=c[0][0].fieldRow;this.block_.previousConnection?(a.push(\"H\",0),a.push(Blockly.BlockSvg.NOTCH_PATH_LEFT),this.block_.previousConnection.moveTo(b.x+Blockly.BlockSvg.NOTCH_WIDTH,b.y)):c[0]instanceof Blockly.FieldIcon&&(a.push(\"m\",\"0,-5\"),a.push(\"a\",\"19.5,19.5 0, 0,1 16,0\"),a.push(\"c\",\"10,5 15,5 20,5\"))};\nBlockly.BlockSvg.prototype.renderDrawRight_=function(a,b,c,d,e){for(var f,g=0,h,k,n,p=0,m;m=d[p];p++){f=Blockly.BlockSvg.SEP_SPACE_X;0==p&&(f+=Blockly.RTL?-e:e);0==p&&this.block_.outputConnection?f=m[0].type==Blockly.INPUT_VALUE?f-(m.height/2+2):\"PARAM\"==this.block_.outputConnection.check_[0].toUpperCase()?f-8:f-(m.height/2-5):0!=p?(f+=33,g-=2):f=d[0][0].fieldRow[0]instanceof Blockly.FieldIcon?f-13:this.block_.previousConnection||this.block_.nextConnection?f+14:f-0;if(this.block_.isCollapsed()){var l=\nm[0];h=g+Blockly.BlockSvg.FIELD_HEIGHT;this.renderFields_(l.fieldRow,f,h,m.height);a.push(Blockly.BlockSvg.JAGGED_TEETH);a.push(\"v\",m.height-Blockly.BlockSvg.JAGGED_TEETH_HEIGHT)}else if(m.type==Blockly.BlockSvg.INLINE){for(n=0;l=m[n];n++)if(h=g+Blockly.BlockSvg.FIELD_HEIGHT,f=this.renderFields_(l.fieldRow,f,h,m.height),l.type!=Blockly.DUMMY_INPUT&&(f+=l.renderWidth+Blockly.BlockSvg.SEP_SPACE_X),l.type==Blockly.INPUT_VALUE){h=l.renderHeight/2;var q=l.renderWidth,r=0,q=q+1,t=l.connection.check_?l.connection.check_[0]:\n\"null\";k=g+(m.height-2*h)/2;\"BOOLEAN\"==t.toUpperCase()?(b.push(\"M\",f-Blockly.BlockSvg.SEP_SPACE_X-h+\",\"+(k+.5)),b.push(\"h\",-q+2*h),b.push(\"l\",\"-\"+h+\",\"+h+\" \"+h+\",\"+h),b.push(\"h\",q-2*h),b.push(\"l\",h+\",-\"+h+\" -\"+h+\",-\"+h),b.push(\"z\")):\"PARAM\"==t.toUpperCase()?(k+=1,this.block_.outputConnection?(f-=l.renderWidth+Blockly.BlockSvg.SEP_SPACE_X,r=l.renderWidth+Blockly.BlockSvg.SEP_SPACE_X+9):(r=8,b.push(\"M\",f-Blockly.BlockSvg.SEP_SPACE_X-6+\",3\"),b.push(\"h\",-q+9),b.push(\"l\",\"-2,2 0,3 3,0 1,1 0,11 -1,1 -3,0 0,4 2,2\"),\nb.push(\"h\",q-9),b.push(\"l\",\"2,-2 0,-3 3,0 1,-1 0,-13 -1,-1 -3,0 0,-2 -2,-2\"),b.push(\"z\"))):(b.push(\"M\",f-Blockly.BlockSvg.SEP_SPACE_X-h+\",\"+(k+.5)),b.push(\"h\",-q+2*h),b.push(\"a\",h+\",\"+h+\" 0 1,0 0,\"+2*h),b.push(\"h\",q-2*h),b.push(\"a\",h+\",\"+h+\" 0 1,0 0,-\"+2*h),b.push(\"z\"));h=c.x+f-Blockly.BlockSvg.SEP_SPACE_X-Blockly.BlockSvg.TAB_WIDTH-l.renderWidth+7.5+h+r;k=c.y+k;l.connection.moveTo(h,k);l.connection.targetConnection&&l.connection.tighten_()}n=f=Math.max(f,d.rightEdge);this.block_.outputConnection?\n(this.blockInlineWidth_=f,this.r_=h=m.height/2,l=m[m.length-1].fieldRow,l[l.length-1]instanceof Blockly.FieldLabel&&(f+=1),f+=2,\"PARAM\"==this.block_.outputConnection.check_[0].toUpperCase()?(a.push(\"H\",f),a.push(\"l\",\"-3,0 2,2 0,3 3,0 1,1 0,12 -1,1 -3,0 0,3 -2,2 3,0\")):\"BOOLEAN\"==this.block_.outputConnection.check_[0].toUpperCase()?(a.push(\"H\",f-h),a.push(\"l\",h+\",\"+h+\" -\"+h+\",\"+h)):(a.push(\"H\",f-h-4),a.push(\"a\",h+\",\"+h+\" 0 1,1 0,\"+2*h))):(0==p&&(this.blockInlineWidth_=f),this.blockInlineWidth_&&(f=\nthis.blockInlineWidth_),l=m[m.length-1].fieldRow,l[l.length-1]instanceof Blockly.FieldIcon||(f+=8),h=m.height/2,a.push(\"H\",f-h-1),a.push(\"a\",h+\",\"+h+\" 0 0,1 0,\"+2*h))}else m.type==Blockly.INPUT_VALUE?(l=m[0],h=g+Blockly.BlockSvg.FIELD_HEIGHT,l.align!=Blockly.ALIGN_LEFT&&(k=d.rightEdge-l.fieldWidth-Blockly.BlockSvg.TAB_WIDTH-2*Blockly.BlockSvg.SEP_SPACE_X,l.align==Blockly.ALIGN_RIGHT?f+=k:l.align==Blockly.ALIGN_CENTRE&&(f+=(k+f)/2)),this.renderFields_(l.fieldRow,f,h,m.height),a.push(Blockly.BlockSvg.TAB_PATH_DOWN),\na.push(\"v\",m.height-Blockly.BlockSvg.TAB_HEIGHT),h=c.x+(Blockly.RTL?-d.rightEdge-1:d.rightEdge+1),k=c.y+g+1,l.connection.moveTo(h,k),l.connection.targetConnection&&l.connection.tighten_()):m.type==Blockly.DUMMY_INPUT?(l=m[0],h=g+Blockly.BlockSvg.FIELD_HEIGHT,l.align!=Blockly.ALIGN_LEFT&&(k=d.rightEdge-l.fieldWidth-2*Blockly.BlockSvg.SEP_SPACE_X,d.hasValue&&(k-=Blockly.BlockSvg.TAB_WIDTH),l.align==Blockly.ALIGN_RIGHT?f+=k:l.align==Blockly.ALIGN_CENTRE&&(f+=(k+f)/2)),this.renderFields_(l.fieldRow,f,\nh,m.height),a.push(\"v\",m.height)):m.type==Blockly.NEXT_STATEMENT&&(l=m[0],0==p&&(a.push(\"v\",Blockly.BlockSvg.SEP_SPACE_Y),g+=Blockly.BlockSvg.SEP_SPACE_Y),h=g+Blockly.BlockSvg.FIELD_HEIGHT,l.align!=Blockly.ALIGN_LEFT&&(k=d.statementEdge-l.fieldWidth-2*Blockly.BlockSvg.SEP_SPACE_X,l.align==Blockly.ALIGN_RIGHT?f+=k:l.align==Blockly.ALIGN_CENTRE&&(f+=(k+f)/2)),this.renderFields_(l.fieldRow,f,h,m.height),f=d.statementEdge+Blockly.BlockSvg.NOTCH_WIDTH,a.push(\"H\",f+6),a.push(Blockly.BlockSvg.INNER_TOP_LEFT_CORNER),\na.push(\"v\",m.height-4.5),a.push(Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER),a.push(\"H\",14),a.push(Blockly.BlockSvg.NOTCH_PATH_LEFT),this.blockInlineWidth_?a.push(\"H\",this.blockInlineWidth_-12):a.push(\"H\",n),h=c.x+(Blockly.RTL?-f:f)+6,k=c.y+g+3,0!=p&&(k-=0),g-=0,l.connection.moveTo(h,k),l.connection.targetConnection&&l.connection.tighten_(),p==d.length-1||d[p+1].type==Blockly.NEXT_STATEMENT)&&(a.push(\"a\",\"8,8 0 0,1 0,16\"),g+=Blockly.BlockSvg.SEP_SPACE_Y+3);g+=m.height}d.length||(g=Blockly.BlockSvg.MIN_BLOCK_Y,\na.push(\"V\",g));return g};Blockly.BlockSvg.prototype.renderDrawBottom_=function(a,b,c){this.block_.nextConnection&&(a.push(\"l\",\"0,-0.5\"),a.push(\"H\",Blockly.BlockSvg.NOTCH_WIDTH+\" \"+Blockly.BlockSvg.NOTCH_PATH_RIGHT),a.push(\"l\",\"0,0.5\"),this.block_.nextConnection.moveTo(b.x+Blockly.BlockSvg.NOTCH_WIDTH,b.y+c+1),this.block_.nextConnection.targetConnection&&this.block_.nextConnection.tighten_());Blockly.BROKEN_CONTROL_POINTS&&a.push(\"c 0,4 0,-4 0,0\");a.push(\"H 0\")};\nBlockly.BlockSvg.prototype.renderDrawLeft_=function(a,b,c,d){this.block_.outputConnection&&(this.block_.outputConnection.moveTo(b.x,b.y),b=this.r_,\"PARAM\"==this.block_.outputConnection.check_[0].toUpperCase()?a.push(\"l\",\"-18,0 -2,-2 0,-3 3,0 1,-1 0,-12 -1,-1 -3,0 0,-3 2,-2 18,0\"):b&&\"BOOLEAN\"==this.block_.outputConnection.check_[0].toUpperCase()?a.push(\"l\",\"-\"+b+\",-\"+b+\" \"+b+\",-\"+b):b&&a.push(\"a\",b+\",\"+b+\" 0 1,1 0,-\"+2*b));d[0][0].fieldRow[0]instanceof Blockly.FieldIcon&&a.push(\"a\",\"19.5,19.5 0, 0,1 0,-35\");\na.push(\"z\")};\n// Copyright 2013 Google Inc.  Apache License 2.0\nBlockly.Blocks={};\nBlockly.Blocks.addTemplate=function(a){goog.asserts.assert(a.blockName);goog.asserts.assert(Blockly.Blocks[a.blockName],\"Blockly.Blocks already has a field named \",a.blockName);goog.asserts.assert(a.message);goog.asserts.assert(a.colour&&\"number\"==typeof a.colour&&0<=a.colour&&360>a.colour,\"details.colour must be a number from 0 to 360 (exclusive)\");\"undefined\"!=a.output&&(goog.asserts.assert(!a.previousStatement,\"When details.output is defined, details.previousStatement must not be true.\"),goog.asserts.assert(!a.nextStatement,\n\"When details.output is defined, details.nextStatement must not be true.\"));var b={init:function(){var b=this;this.setColour(a.colour);this.setHelpUrl(a.helpUrl);\"string\"==typeof a.tooltip?this.setTooltip(a.tooltip):\"function\"==typeof a.tooltip&&this.setTooltip(function(){return a.tooltip(b)});\"undefined\"!=a.output?this.setOutput(!0,a.output):(this.setPreviousStatement(\"undefined\"==typeof a.previousStatement?!0:a.previousStatement),this.setNextStatement(\"undefined\"==typeof a.nextStatement?!0:a.nextStatement));\nvar d=[];d.push(a.text);a.args&&a.args.forEach(function(a){goog.asserts.assert(a.name);goog.asserts.assert(\"undefined\"!=a.check);\"undefined\"==a.type||a.type==Blockly.INPUT_VALUE?d.push([a.name,a.check,\"undefined\"==typeof a.align?Blockly.ALIGN_RIGHT:a.align]):goog.asserts.fail(\"addTemplate() can only handle value inputs.\")});d.push(Blockly.ALIGN_RIGHT);a.inline&&this.setInlineInputs(a.inline);Blockly.Block.prototype.interpolateMsg.apply(this,d)}};b.mutationToDom=a.switchable?function(){var b=a.mutationToDomFunc?\na.mutatationToDomFunc():document.createElement(\"mutation\");b.setAttribute(\"is_statement\",this.isStatement||!1);return b}:a.mutationToDomFunc;Blockly.Blocks[a.blockName]=b};\n// Copyright 2011 Google Inc.  Apache License 2.0\nBlockly.ScrollbarPair=function(a){this.workspace_=a;this.oldHostMetrics_=null;this.hScroll=new Blockly.Scrollbar(a,!0,!0);this.vScroll=new Blockly.Scrollbar(a,!1,!0)};Blockly.ScrollbarPair.prototype.dispose=function(){Blockly.unbindEvent_(this.onResizeWrapper_);this.oldHostMetrics_=this.workspace_=this.onResizeWrapper_=null;this.hScroll.dispose();this.hScroll=null;this.vScroll.dispose();this.vScroll=null};\nBlockly.ScrollbarPair.prototype.resize=function(){if(!Blockly.scrollBarOff){var a=this.workspace_.getMetrics();if(a){var b=!1,c=!1;this.oldHostMetrics_&&this.oldHostMetrics_.viewWidth==a.viewWidth&&this.oldHostMetrics_.viewHeight==a.viewHeight&&this.oldHostMetrics_.absoluteTop==a.absoluteTop&&this.oldHostMetrics_.absoluteLeft==a.absoluteLeft?(this.oldHostMetrics_&&this.oldHostMetrics_.contentWidth==a.contentWidth&&this.oldHostMetrics_.viewLeft==a.viewLeft&&this.oldHostMetrics_.contentLeft==a.contentLeft||\n(b=!0),this.oldHostMetrics_&&this.oldHostMetrics_.contentHeight==a.contentHeight&&this.oldHostMetrics_.viewTop==a.viewTop&&this.oldHostMetrics_.contentTop==a.contentTop||(c=!0)):c=b=!0;b&&this.hScroll.resize(a);c&&this.vScroll.resize(a);this.oldHostMetrics_=a}}};\nBlockly.ScrollbarPair.prototype.set=function(a,b){if(Blockly.Scrollbar===Blockly.ScrollbarNative){this.hScroll.set(a,!1);this.vScroll.set(b,!1);var c={};c.x=this.hScroll.outerDiv_.scrollLeft/this.hScroll.innerImg_.offsetWidth||0;c.y=this.vScroll.outerDiv_.scrollTop/this.vScroll.innerImg_.offsetHeight||0;this.workspace_.setMetrics(c)}else this.hScroll.set(a,!0),this.vScroll.set(b,!0)};Blockly.ScrollbarInterface=function(){};Blockly.ScrollbarInterface.prototype.dispose=function(){};\nBlockly.ScrollbarInterface.prototype.resize=function(){};Blockly.ScrollbarInterface.prototype.isVisible=function(){};Blockly.ScrollbarInterface.prototype.setVisible=function(a){};Blockly.ScrollbarInterface.prototype.set=function(a,b){};\nBlockly.ScrollbarNative=function(a,b,c){this.workspace_=a;this.pair_=c||!1;this.horizontal_=b;this.createDom_();if(null!==b){Blockly.Scrollbar.scrollbarThickness||Blockly.ScrollbarNative.measureScrollbarThickness_(a);b?(this.foreignObject_.setAttribute(\"height\",Blockly.Scrollbar.scrollbarThickness),this.outerDiv_.style.height=Blockly.Scrollbar.scrollbarThickness+\"px\",this.outerDiv_.style.overflowX=\"scroll\",this.outerDiv_.style.overflowY=\"hidden\",this.innerImg_.style.height=\"1px\"):(this.foreignObject_.setAttribute(\"width\",\nBlockly.Scrollbar.scrollbarThickness),this.outerDiv_.style.width=Blockly.Scrollbar.scrollbarThickness+\"px\",this.outerDiv_.style.overflowX=\"hidden\",this.outerDiv_.style.overflowY=\"scroll\",this.innerImg_.style.width=\"1px\");var d=this;this.onScrollWrapper_=Blockly.bindEvent_(this.outerDiv_,\"scroll\",d,function(){d.onScroll_()});Blockly.bindEvent_(this.foreignObject_,\"mousedown\",null,function(a){Blockly.hideChaff(!0);Blockly.noEvent(a)})}};\nBlockly.ScrollbarNative.prototype.dispose=function(){Blockly.unbindEvent_(this.onResizeWrapper_);this.onResizeWrapper_=null;Blockly.unbindEvent_(this.onScrollWrapper_);this.onScrollWrapper_=null;goog.dom.removeNode(this.foreignObject_);this.innerImg_=this.outerDiv_=this.workspace_=this.foreignObject_=null};\nBlockly.ScrollbarNative.prototype.resize=function(a){if(!a&&(a=this.workspace_.getMetrics(),!a))return;if(this.horizontal_){var b=a.viewWidth;this.pair_?b-=Blockly.Scrollbar.scrollbarThickness:this.setVisible(b<a.contentWidth);this.ratio_=b/a.viewWidth;var c=this.ratio_*a.contentWidth,d=(a.viewLeft-a.contentLeft)*this.ratio_;this.outerDiv_.style.width=b+\"px\";this.innerImg_.style.width=c+\"px\";this.xCoordinate=a.absoluteLeft;this.pair_&&Blockly.RTL&&(this.xCoordinate+=Blockly.Scrollbar.scrollbarThickness);\nthis.yCoordinate=a.absoluteTop+a.viewHeight-Blockly.Scrollbar.scrollbarThickness;this.foreignObject_.setAttribute(\"x\",this.xCoordinate);this.foreignObject_.setAttribute(\"y\",this.yCoordinate);this.foreignObject_.setAttribute(\"width\",Math.max(0,b));this.outerDiv_.scrollLeft=Math.round(d)}else b=a.viewHeight,this.pair_?b-=Blockly.Scrollbar.scrollbarThickness:this.setVisible(b<a.contentHeight),this.ratio_=b/a.viewHeight,c=this.ratio_*a.contentHeight,d=(a.viewTop-a.contentTop)*this.ratio_,this.outerDiv_.style.height=\nb+\"px\",this.innerImg_.style.height=c+\"px\",this.xCoordinate=a.absoluteLeft,Blockly.RTL||(this.xCoordinate+=a.viewWidth-Blockly.Scrollbar.scrollbarThickness),this.yCoordinate=a.absoluteTop,this.foreignObject_.setAttribute(\"x\",this.xCoordinate),this.foreignObject_.setAttribute(\"y\",this.yCoordinate),this.foreignObject_.setAttribute(\"height\",Math.max(0,b)),this.outerDiv_.scrollTop=Math.round(d)};\nBlockly.ScrollbarNative.prototype.createDom_=function(){this.foreignObject_=Blockly.createSvgElement(\"foreignObject\",{},null);var a=document.createElementNS(Blockly.HTML_NS,\"body\");a.setAttribute(\"xmlns\",Blockly.HTML_NS);a.setAttribute(\"class\",\"blocklyMinimalBody\");var b=document.createElementNS(Blockly.HTML_NS,\"div\");this.outerDiv_=b;var c=document.createElementNS(Blockly.HTML_NS,\"img\");c.setAttribute(\"src\",Blockly.pathToBlockly+\"media/1x1.gif\");this.innerImg_=c;b.appendChild(c);a.appendChild(b);\nthis.foreignObject_.appendChild(a);Blockly.Scrollbar.insertAfter_(this.foreignObject_,this.workspace_.getBubbleCanvas())};Blockly.ScrollbarNative.prototype.isVisible=function(){return\"none\"!=this.foreignObject_.style.display};\nBlockly.ScrollbarNative.prototype.setVisible=function(a){if(a!=this.isVisible()){if(this.pair_)throw\"Unable to toggle visibility of paired scrollbars.\";a?(this.foreignObject_.style.display=\"block\",this.workspace_.getMetrics()):(this.workspace_.setMetrics({x:0,y:0}),this.foreignObject_.style.display=\"none\")}};\nBlockly.ScrollbarNative.prototype.onScroll_=function(){var a={};this.horizontal_?a.x=this.outerDiv_.scrollLeft/this.innerImg_.offsetWidth||0:a.y=this.outerDiv_.scrollTop/this.innerImg_.offsetHeight||0;this.workspace_.setMetrics(a)};\nBlockly.ScrollbarNative.prototype.set=function(a,b){if(!b&&this.onScrollWrapper_)var c=Blockly.unbindEvent_(this.onScrollWrapper_);this.horizontal_?this.outerDiv_.scrollLeft=a*this.ratio_:this.outerDiv_.scrollTop=a*this.ratio_;c&&(this.onScrollWrapper_=Blockly.bindEvent_(this.outerDiv_,\"scroll\",this,c))};\nBlockly.ScrollbarNative.measureScrollbarThickness_=function(a){a=new Blockly.ScrollbarNative(a,null,!1);a.outerDiv_.style.width=\"100px\";a.outerDiv_.style.height=\"100px\";a.innerImg_.style.width=\"100%\";a.innerImg_.style.height=\"200px\";a.foreignObject_.setAttribute(\"width\",1);a.foreignObject_.setAttribute(\"height\",1);a.outerDiv_.style.overflowY=\"scroll\";var b=a.innerImg_.offsetWidth;a.outerDiv_.style.overflowY=\"hidden\";var c=a.innerImg_.offsetWidth;goog.dom.removeNode(a.foreignObject_);a=c-b;0>=a&&(a=\n15);Blockly.Scrollbar.scrollbarThickness=a};\nBlockly.ScrollbarSvg=function(a,b,c){this.workspace_=a;this.pair_=c||!1;this.horizontal_=b;this.createDom_();b?(this.svgBackground_.setAttribute(\"height\",Blockly.Scrollbar.scrollbarThickness),this.svgKnob_.setAttribute(\"height\",Blockly.Scrollbar.scrollbarThickness-6),this.svgKnob_.setAttribute(\"y\",3)):(this.svgBackground_.setAttribute(\"width\",Blockly.Scrollbar.scrollbarThickness),this.svgKnob_.setAttribute(\"width\",Blockly.Scrollbar.scrollbarThickness-6),this.svgKnob_.setAttribute(\"x\",6));this.onMouseDownBarWrapper_=\nBlockly.bindEvent_(this.svgBackground_,\"mousedown\",this,this.onMouseDownBar_);this.onMouseDownKnobWrapper_=Blockly.bindEvent_(this.svgKnob_,\"mousedown\",this,this.onMouseDownKnob_)};Blockly.ScrollbarSvg.prototype.uiEffectInc_=function(a){this.svgGroup_.setAttribute(\"opacity\",\"1\")};Blockly.ScrollbarSvg.prototype.uiEffectDec_=function(a){};\nBlockly.ScrollbarSvg.prototype.dispose=function(){this.onMouseUpKnob_();this.onResizeWrapper_&&(Blockly.unbindEvent_(this.onResizeWrapper_),this.onResizeWrapper_=null);Blockly.unbindEvent_(this.onMouseDownBarWrapper_);this.onMouseDownBarWrapper_=null;Blockly.unbindEvent_(this.onMouseDownKnobWrapper_);this.onMouseDownKnobWrapper_=null;goog.dom.removeNode(this.svgGroup_);this.workspace_=this.svgKnob_=this.svgBackground_=this.svgGroup_=null};\nBlockly.ScrollbarSvg.prototype.resize=function(a){if(!a&&(a=this.workspace_.getMetrics(),!a))return;if(this.horizontal_){var b=a.viewWidth;this.pair_?b-=Blockly.Scrollbar.scrollbarThickness:this.setVisible(b<a.contentHeight);this.ratio_=b/a.contentWidth;if(-Infinity===this.ratio_||Infinity===this.ratio_||isNaN(this.ratio_))this.ratio_=0;var c=a.viewWidth*this.ratio_,d=(a.viewLeft-a.contentLeft)*this.ratio_;this.svgKnob_.setAttribute(\"width\",Math.max(0,c));this.xCoordinate=a.absoluteLeft;this.pair_&&\nBlockly.RTL&&(this.xCoordinate+=a.absoluteLeft+Blockly.Scrollbar.scrollbarThickness);this.yCoordinate=a.absoluteTop+a.viewHeight-Blockly.Scrollbar.scrollbarThickness;this.svgGroup_.setAttribute(\"transform\",\"translate(\"+this.xCoordinate+\", \"+this.yCoordinate+\")\");this.svgBackground_.setAttribute(\"width\",Math.max(0,b));this.svgKnob_.setAttribute(\"x\",this.constrainKnob_(d))}else{b=a.viewHeight;this.pair_?b-=Blockly.Scrollbar.scrollbarThickness:this.setVisible(b<a.contentHeight);this.ratio_=b/a.contentHeight;\nif(-Infinity===this.ratio_||Infinity===this.ratio_||isNaN(this.ratio_))this.ratio_=0;c=a.viewHeight*this.ratio_;d=(a.viewTop-a.contentTop)*this.ratio_;this.svgKnob_.setAttribute(\"height\",Math.max(0,c));this.xCoordinate=a.absoluteLeft;Blockly.RTL||(this.xCoordinate+=a.viewWidth-Blockly.Scrollbar.scrollbarThickness);this.yCoordinate=a.absoluteTop;this.svgGroup_.setAttribute(\"transform\",\"translate(\"+this.xCoordinate+\", \"+this.yCoordinate+\")\");this.svgBackground_.setAttribute(\"height\",Math.max(0,b));\nthis.svgKnob_.setAttribute(\"y\",this.constrainKnob_(d))}};Blockly.ScrollbarSvg.prototype.createDom_=function(){this.svgGroup_=Blockly.createSvgElement(\"g\",{},null);this.svgBackground_=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyScrollbarBackground\"},this.svgGroup_);var a=Math.floor((Blockly.Scrollbar.scrollbarThickness-6)/2);this.svgKnob_=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyScrollbarKnob\",rx:a,ry:a},this.svgGroup_);Blockly.Scrollbar.insertAfter_(this.svgGroup_,this.workspace_.getBubbleCanvas())};\nBlockly.ScrollbarSvg.prototype.isVisible=function(){return\"none\"!=this.svgGroup_.getAttribute(\"display\")};Blockly.ScrollbarSvg.prototype.setVisible=function(a){if(a!=this.isVisible()){if(this.pair_)throw\"Unable to toggle visibility of paired scrollbars.\";a?this.svgGroup_.setAttribute(\"display\",\"block\"):(this.workspace_.setMetrics({x:0,y:0}),this.svgGroup_.setAttribute(\"display\",\"none\"))}};\nBlockly.ScrollbarSvg.prototype.onMouseDownBar_=function(a){Blockly.hideChaff(!0);if(!Blockly.isRightButton(a)){var b=Blockly.mouseToSvg(a),b=this.horizontal_?b.x:b.y,c=Blockly.getSvgXY_(this.svgKnob_),c=this.horizontal_?c.x:c.y,d=parseFloat(this.svgKnob_.getAttribute(this.horizontal_?\"width\":\"height\")),e=parseFloat(this.svgKnob_.getAttribute(this.horizontal_?\"x\":\"y\")),f=.95*d;b<=c?e-=f:b>=c+d&&(e+=f);this.svgKnob_.setAttribute(this.horizontal_?\"x\":\"y\",this.constrainKnob_(e));this.onScroll_()}a.stopPropagation()};\nBlockly.ScrollbarSvg.prototype.onMouseDownKnob_=function(a){Blockly.hideChaff(!0);this.onMouseUpKnob_();Blockly.isRightButton(a)||(this.startDragKnob=parseFloat(this.svgKnob_.getAttribute(this.horizontal_?\"x\":\"y\")),this.startDragMouse=this.horizontal_?a.clientX:a.clientY,Blockly.ScrollbarSvg.onMouseUpWrapper_=Blockly.bindEvent_(document,\"mouseup\",this,this.onMouseUpKnob_),Blockly.ScrollbarSvg.onMouseMoveWrapper_=Blockly.bindEvent_(document,\"mousemove\",this,this.onMouseMoveKnob_));a.stopPropagation()};\nBlockly.ScrollbarSvg.prototype.onMouseMoveKnob_=function(a){this.svgKnob_.setAttribute(this.horizontal_?\"x\":\"y\",this.constrainKnob_(this.startDragKnob+((this.horizontal_?a.clientX:a.clientY)-this.startDragMouse)));this.onScroll_()};\nBlockly.ScrollbarSvg.prototype.onMouseUpKnob_=function(){Blockly.ScrollbarSvg.onMouseUpWrapper_&&(Blockly.unbindEvent_(Blockly.ScrollbarSvg.onMouseUpWrapper_),Blockly.ScrollbarSvg.onMouseUpWrapper_=null);Blockly.ScrollbarSvg.onMouseMoveWrapper_&&(Blockly.unbindEvent_(Blockly.ScrollbarSvg.onMouseMoveWrapper_),Blockly.ScrollbarSvg.onMouseMoveWrapper_=null)};\nBlockly.ScrollbarSvg.prototype.constrainKnob_=function(a){if(0>=a||isNaN(a))a=0;else{var b=this.horizontal_?\"width\":\"height\",c=parseFloat(this.svgBackground_.getAttribute(b)),b=parseFloat(this.svgKnob_.getAttribute(b));a=Math.min(a,c-b)}return a};\nBlockly.ScrollbarSvg.prototype.onScroll_=function(){var a=parseFloat(this.svgKnob_.getAttribute(this.horizontal_?\"x\":\"y\")),b=parseFloat(this.svgBackground_.getAttribute(this.horizontal_?\"width\":\"height\")),a=a/b;isNaN(a)&&(a=0);b={};this.horizontal_?b.x=a:b.y=a;this.workspace_.setMetrics(b);Blockly.hideChaff(!0)};Blockly.ScrollbarSvg.prototype.set=function(a,b){this.svgKnob_.setAttribute(this.horizontal_?\"x\":\"y\",a*this.ratio_);if(b)this.onScroll_()};Blockly.Scrollbar=Blockly.ScrollbarSvg;\nBlockly.Scrollbar.scrollbarThickness=15;Blockly.Scrollbar.insertAfter_=function(a,b){var c=b.nextSibling,d=b.parentNode;if(!d)throw\"Reference node has no parent.\";c?d.insertBefore(a,c):d.appendChild(a)};Blockly.Trashcan=function(a){this.workspace_=a};Blockly.Trashcan.prototype.BODY_URL_=\"/legacy_media/trashbody.png\";Blockly.Trashcan.prototype.LID_URL_=\"/legacy_media/trashlid.png\";Blockly.Trashcan.prototype.WIDTH_=57;Blockly.Trashcan.prototype.BODY_HEIGHT_=55;Blockly.Trashcan.prototype.LID_HEIGHT_=18;Blockly.Trashcan.prototype.MARGIN_BOTTOM_=55;Blockly.Trashcan.prototype.MARGIN_SIDE_=55;Blockly.Trashcan.prototype.isOpen=!1;Blockly.Trashcan.prototype.svgGroup_=null;Blockly.Trashcan.prototype.svgBody_=null;\nBlockly.Trashcan.prototype.svgLid_=null;Blockly.Trashcan.prototype.lidTask_=0;Blockly.Trashcan.prototype.lidAngle_=0;Blockly.Trashcan.prototype.left_=0;Blockly.Trashcan.prototype.top_=0;\nBlockly.Trashcan.prototype.createDom=function(){this.svgGroup_=Blockly.createSvgElement(\"g\",{filter:\"url(#blocklyTrashcanShadowFilter)\"},null);Blockly.bindEvent_(this.svgGroup_,\"mousedown\",this,function(a){Blockly.isRightButton(a)&&(console.log(\"hi\"),document.getElementById(\"entryBlockly\").style.background=\"white\")});this.svgBody_=Blockly.createSvgElement(\"image\",{width:this.WIDTH_,height:this.BODY_HEIGHT_},this.svgGroup_);this.svgBody_.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",\nthis.BODY_URL_);this.svgBody_.setAttribute(\"y\",this.LID_HEIGHT_);this.svgLid_=Blockly.createSvgElement(\"image\",{width:this.WIDTH_,height:this.LID_HEIGHT_},this.svgGroup_);this.svgLid_.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",this.LID_URL_);return this.svgGroup_};Blockly.Trashcan.prototype.init=function(){this.setOpen_(!1);this.position_();Blockly.bindEvent_(window,\"resize\",this,this.position_)};\nBlockly.Trashcan.prototype.dispose=function(){this.svgGroup_&&(goog.dom.removeNode(this.svgGroup_),this.svgGroup_=null);this.workspace_=this.svgLid_=this.svgBody_=null;goog.Timer.clear(this.lidTask_)};\nBlockly.Trashcan.prototype.position_=function(){var a=this.workspace_.getMetrics();a&&(this.left_=Blockly.RTL?this.MARGIN_SIDE_:a.viewWidth+a.absoluteLeft-this.WIDTH_-this.MARGIN_SIDE_,this.top_=a.viewHeight+a.absoluteTop-(this.BODY_HEIGHT_+this.LID_HEIGHT_)-this.MARGIN_BOTTOM_,this.svgGroup_.setAttribute(\"transform\",\"translate(\"+this.left_+\",\"+this.top_+\")\"))};\nBlockly.Trashcan.prototype.onMouseMove=function(a){if(this.svgGroup_){a=Blockly.mouseToSvg(a);var b=Blockly.getSvgXY_(this.svgGroup_);a=a.x+25>b.x&&a.x<b.x+this.WIDTH_+25&&a.y+25>b.y&&a.y<b.y+this.BODY_HEIGHT_+this.LID_HEIGHT_+25;this.isOpen!=a&&this.setOpen_(a)}};Blockly.Trashcan.prototype.setOpen_=function(a){this.isOpen!=a&&(goog.Timer.clear(this.lidTask_),this.isOpen=a,this.animateLid_())};\nBlockly.Trashcan.prototype.animateLid_=function(){this.lidAngle_+=this.isOpen?10:-10;this.lidAngle_=Math.max(0,this.lidAngle_);this.svgLid_.setAttribute(\"transform\",\"rotate(\"+(Blockly.RTL?-this.lidAngle_:this.lidAngle_)+\", \"+(Blockly.RTL?4:this.WIDTH_-4)+\", \"+(this.LID_HEIGHT_-2)+\")\");if(this.isOpen?45>this.lidAngle_:0<this.lidAngle_)this.lidTask_=goog.Timer.callOnce(this.animateLid_,5,this)};Blockly.Trashcan.prototype.close=function(){this.setOpen_(!1)};Blockly.Xml={};Blockly.Xml.workspaceToDom=function(a){var b=Blockly.svgSize().width,c=goog.dom.createDom(\"xml\");a=a.getTopBlocks(!0);for(var d=0,e;e=a[d];d++){var f=Blockly.Xml.blockToDom_(e);e=e.getRelativeToSurfaceXY();f.setAttribute(\"x\",Blockly.RTL?b-e.x:e.x);f.setAttribute(\"y\",e.y);c.appendChild(f)}return c};\nBlockly.Xml.blockToDom_=function(a){var b=goog.dom.createDom(\"block\");b.setAttribute(\"type\",a.type);a.outputConnection?b.setAttribute(\"class\",\"output \"+a.type):b.setAttribute(\"class\",\"inline \"+a.type);b.setAttribute(\"id\",a.id);if(a.mutationToDom){var c=a.mutationToDom();c&&b.appendChild(c)}for(var d=0;c=a.inputList[d];d++)for(var e=0,f;f=c.fieldRow[e];e++)if(f.name&&f.EDITABLE){var g=goog.dom.createDom(\"field\",null,f.getValue());g.setAttribute(\"name\",f.name);b.appendChild(g)}a.comment&&(c=goog.dom.createDom(\"comment\",\nnull,a.comment.getText()),c.setAttribute(\"pinned\",a.comment.isVisible()),d=a.comment.getBubbleSize(),c.setAttribute(\"h\",d.height),c.setAttribute(\"w\",d.width),b.appendChild(c));d=!1;for(e=0;c=a.inputList[e];e++){var h;f=!0;c.type!=Blockly.DUMMY_INPUT&&(g=c.connection.targetBlock(),c.type==Blockly.INPUT_VALUE?(h=goog.dom.createDom(\"value\"),d=!0):c.type==Blockly.NEXT_STATEMENT&&(h=goog.dom.createDom(\"statement\")),g&&(h.appendChild(Blockly.Xml.blockToDom_(g)),f=!1),h.setAttribute(\"name\",c.name),f||b.appendChild(h))}d&&\nb.setAttribute(\"inline\",a.inputsInline);a.isCollapsed()&&b.setAttribute(\"collapsed\",!0);a.disabled&&b.setAttribute(\"disabled\",!0);a.isDeletable()||b.setAttribute(\"deletable\",!1);a.isMovable()||b.setAttribute(\"movable\",!1);a.isAddable()||b.setAttribute(\"addable\",!1);a.isEditable()||b.setAttribute(\"editable\",!1);a.nextConnection&&(a=a.nextConnection.targetBlock())&&(h=goog.dom.createDom(\"next\",null,Blockly.Xml.blockToDom_(a)),b.appendChild(h));return b};Blockly.Xml.domToText=function(a){return(new XMLSerializer).serializeToString(a)};\nBlockly.Xml.domToPrettyText=function(a){a=Blockly.Xml.domToText(a).split(\"<\");for(var b=\"\",c=1;c<a.length;c++){var d=a[c];\"/\"==d[0]&&(b=b.substring(2));a[c]=b+\"<\"+d;\"/\"!=d[0]&&\"/>\"!=d.slice(-2)&&(b+=\"  \")}a=a.join(\"\\n\");a=a.replace(/(<(\\w+)\\b[^>]*>[^\\n]*)\\n *<\\/\\2>/g,\"$1</$2>\");return a.replace(/^\\n/,\"\")};\nBlockly.Xml.textToDom=function(a){a=(new DOMParser).parseFromString(a,\"text/xml\");if(!a||!a.firstChild||\"xml\"!=a.firstChild.nodeName.toLowerCase()||a.firstChild!==a.lastChild)throw\"Blockly.Xml.textToDom did not obtain a valid XML tree.\";return a.firstChild};\nBlockly.Xml.domToWorkspace=function(a,b){for(var c=Blockly.svgSize().width,d=0,e;e=b.childNodes[d];d++)if(\"block\"==e.nodeName.toLowerCase()){var f=Blockly.Xml.domToBlock(a,e),g=parseInt(e.getAttribute(\"x\"),10);e=parseInt(e.getAttribute(\"y\"),10);isNaN(g)||isNaN(e)||f.moveBy(Blockly.RTL?c-g:g,e)}Blockly.svgResize()};\nBlockly.Xml.domToBlock=function(a,b,c){var d,e=b.getAttribute(\"type\");if(!e)throw\"Block type unspecified: \\n\"+b.outerHTML;var f=b.getAttribute(\"id\");if(c&&f){d=Blockly.Block.getById(f,a);if(!d)throw\"Couldn't get Block with id: \"+f;f=d.getParent();d.workspace&&d.dispose(!0,!1,!0);d.fill(a,e);d.parent_=f}else d=Blockly.Block.obtain(a,e);d.previousId=b.getAttribute(\"id\");d.svg_||d.initSvg();(f=b.getAttribute(\"inline\"))&&d.setInputsInline(\"true\"==f);(f=b.getAttribute(\"disabled\"))&&d.setDisabled(\"true\"==\nf);(f=b.getAttribute(\"deletable\"))&&d.setDeletable(\"true\"==f);(f=b.getAttribute(\"movable\"))&&d.setMovable(\"true\"==f);(f=b.getAttribute(\"addable\"))&&d.setAddable(\"true\"==f);(f=b.getAttribute(\"editable\"))&&d.setEditable(\"true\"==f);for(var g,f=0,h;h=b.childNodes[f];f++)if(3!=h.nodeType||!h.data.match(/^\\s*$/)){g=null;for(var k=0,n;n=h.childNodes[k];k++)3==n.nodeType&&n.data.match(/^\\s*$/)||(g=n);k=h.getAttribute(\"name\");switch(h.nodeName.toLowerCase()){case \"mutation\":d.domToMutation&&d.domToMutation(h);\nbreak;case \"comment\":d.setCommentText(h.textContent);(g=h.getAttribute(\"pinned\"))&&d.comment.setVisible(\"true\"==g);g=parseInt(h.getAttribute(\"w\"),10);h=parseInt(h.getAttribute(\"h\"),10);isNaN(g)||isNaN(h)||d.comment.setBubbleSize(g,h);break;case \"title\":case \"field\":d.setFieldValue(h.textContent,k);break;case \"value\":case \"statement\":h=d.getInput(k);if(!h)throw\"Input \"+k+\" does not exist in block \"+e;if(g&&\"block\"==g.nodeName.toLowerCase())if(g=Blockly.Xml.domToBlock(a,g,c),g.outputConnection)h.connection.connect(g.outputConnection);\nelse if(g.previousConnection)h.connection.connect(g.previousConnection);else throw\"Child block does not have output or previous statement.\";break;case \"next\":if(g&&\"block\"==g.nodeName.toLowerCase()){if(!d.nextConnection)throw\"Next statement does not exist.\";if(d.nextConnection.targetConnection)throw\"Next statement is already connected.\";g=Blockly.Xml.domToBlock(a,g,c);if(!g.previousConnection)throw\"Next block does not have previous statement.\";d.nextConnection.connect(g.previousConnection)}}}(a=d.nextConnection&&\nd.nextConnection.targetBlock())?a.render():d.render();(b=b.getAttribute(\"collapsed\"))&&d.setCollapsed(\"true\"==b);return d};Blockly.Xml.deleteNext=function(a){for(var b=0,c;c=a.childNodes[b];b++)if(\"next\"==c.nodeName.toLowerCase()){a.removeChild(c);break}};Blockly.Xml=Blockly.Xml;Blockly.Xml.domToText=Blockly.Xml.domToText;Blockly.Xml.domToWorkspace=Blockly.Xml.domToWorkspace;Blockly.Xml.textToDom=Blockly.Xml.textToDom;Blockly.Xml.workspaceToDom=Blockly.Xml.workspaceToDom;Blockly.Workspace=function(a,b){a?(this.getMetrics=a,this.setMetrics=b):(this.getMetrics=Blockly.getGenralWorkspaceMetricsFunc_(this),this.setMetrics=Blockly.setGeneralWorkspaceMetricsFunc_(this));this.isFlyout=!1;this.topBlocks_=[];this.maxBlocks=Infinity;Blockly.ConnectionDB.init(this)};Blockly.Workspace.SCAN_ANGLE=3;Blockly.Workspace.prototype.dragMode=!1;Blockly.Workspace.prototype.scrollX=0;Blockly.Workspace.prototype.scrollY=0;Blockly.Workspace.prototype.trashcan=null;\nBlockly.Workspace.prototype.fireChangeEventPid_=null;Blockly.Workspace.prototype.scrollbar=null;Blockly.Workspace.prototype.createDom=function(){this.svgGroup_=Blockly.createSvgElement(\"g\",{},null);this.svgBlockCanvas_=Blockly.createSvgElement(\"g\",{},this.svgGroup_);this.svgBubbleCanvas_=Blockly.createSvgElement(\"g\",{},this.svgGroup_);this.fireChangeEvent();return this.svgGroup_};\nBlockly.Workspace.prototype.dispose=function(){this.svgGroup_&&(goog.dom.removeNode(this.svgGroup_),this.svgGroup_=null);this.svgBubbleCanvas_=this.svgBlockCanvas_=null;this.trashcan&&(this.trashcan.dispose(),this.trashcan=null)};Blockly.Workspace.prototype.addTrashcan=function(){if(Blockly.hasTrashcan&&!Blockly.readOnly){this.trashcan=new Blockly.Trashcan(this);var a=this.trashcan.createDom();this.svgGroup_.insertBefore(a,this.svgBlockCanvas_);this.trashcan.init()}};\nBlockly.Workspace.prototype.addConnectionAnimation=function(){this.connectionAnimation=new Blockly.ConnectionAnimation;var a=this.connectionAnimation.createDom();this.svgGroup_.insertBefore(a,this.svgBlockCanvas_);this.connectionAnimation.init()};Blockly.Workspace.prototype.getCanvas=function(){return this.svgBlockCanvas_};Blockly.Workspace.prototype.getBubbleCanvas=function(){return this.svgBubbleCanvas_};\nBlockly.Workspace.prototype.addTopBlock=function(a){this.topBlocks_.push(a);Blockly.Realtime.isEnabled()&&this==Blockly.mainWorkspace&&Blockly.Realtime.addTopBlock(a);this.fireChangeEvent()};\nBlockly.Workspace.prototype.removeTopBlock=function(a){for(var b=!1,c,d=0;c=this.topBlocks_[d];d++)if(c==a){this.topBlocks_.splice(d,1);b=!0;break}if(!b)throw\"Block not present in workspace's list of top-most blocks.\";Blockly.Realtime.isEnabled()&&this==Blockly.mainWorkspace&&Blockly.Realtime.removeTopBlock(a);this.fireChangeEvent()};\nBlockly.Workspace.prototype.getTopBlocks=function(a){var b=[].concat(this.topBlocks_);if(a&&1<b.length){var c=Math.sin(Blockly.Workspace.SCAN_ANGLE/180*Math.PI);Blockly.LTR&&(c*=-1);b.sort(function(a,b){var f=a.getRelativeToSurfaceXY(),g=b.getRelativeToSurfaceXY();return f.y+c*f.x-(g.y+c*g.x)})}return b};Blockly.Workspace.prototype.getAllBlocks=function(){for(var a=this.getTopBlocks(!1),b=0;b<a.length;b++)a=a.concat(a[b].getChildren());return a};Blockly.Workspace.prototype.clear=function(){for(Blockly.hideChaff();this.topBlocks_.length;)this.topBlocks_[0].dispose()};\nBlockly.Workspace.prototype.render=function(){for(var a=this.getAllBlocks(),b=0,c;c=a[b];b++)c.getChildren().length||c.render()};Blockly.Workspace.prototype.getBlockById=function(a){for(var b=this.getAllBlocks(),c=0,d;d=b[c];c++)if(d.id==a)return d;return null};Blockly.Workspace.prototype.getBlockByPreviousId=function(a){for(var b=this.getAllBlocks(),c=0,d;d=b[c];c++)if(d.previousId==a)return d;return null};\nBlockly.Workspace.prototype.getBlockByIdWithDeactivate=function(a){for(var b=this.getAllBlocks(),c=0,d;d=b[c];c++)if(d.svg_.removeActive(),d.id==a)return d;return null};Blockly.Workspace.prototype.setAllBlockDisable=function(){for(var a=this.getAllBlocks(),b=0,c;c=a[b];b++)c.setDisabled(!0);return null};Blockly.Workspace.prototype.setAllBlockAble=function(){for(var a=this.getAllBlocks(),b=0,c;c=a[b];b++)c.setDisabled(!1);return null};\nBlockly.Workspace.prototype.traceOn=function(a){this.traceOn_=a;this.traceWrapper_&&(Blockly.unbindEvent_(this.traceWrapper_),this.traceWrapper_=null);a&&(this.traceWrapper_=Blockly.bindEvent_(this.svgBlockCanvas_,\"blocklySelectChange\",this,function(){this.traceOn_=!1}))};Blockly.Workspace.prototype.activateBlock=function(a){this.traceOn(!0);var b=null;if(a&&(b=this.getBlockById(a),!b))return;this.traceOn(!1);b?b.activate():Blockly.selected&&Blockly.selected.unselect();this.traceOn(!0)};\nBlockly.Workspace.prototype.activatePreviousBlock=function(a){this.traceOn(!0);var b=null;if(a&&(b=this.getBlockByPreviousId(a),!b))return;this.traceOn(!1);b?b.activate():Blockly.selected&&Blockly.selected.unselect();this.traceOn(!0)};Blockly.Workspace.prototype.highlightBlock=function(a){if(this.traceOn_){var b=null;if(a&&(b=this.getBlockById(a),!b))return;this.traceOn(!1);b?b.select():Blockly.selected&&Blockly.selected.unselect();this.traceOn(!0)}};\nBlockly.Workspace.prototype.fireChangeEvent=function(){this.fireChangeEventPid_&&window.clearTimeout(this.fireChangeEventPid_);var a=this.svgBlockCanvas_;a&&(this.fireChangeEventPid_=window.setTimeout(function(){Blockly.fireUiEvent(a,\"blocklyWorkspaceChange\")},0))};\nBlockly.Workspace.prototype.paste=function(a){if(!(a.getElementsByTagName(\"block\").length>=this.remainingCapacity())){\"object\"===typeof Entry?a=Entry.changeXmlHashId(a):\"object\"===typeof Ntry&&(a=Ntry.changeXmlHashId(a));var b=Blockly.Xml.domToBlock(this,a),c=parseInt(a.getAttribute(\"x\"),10),d=parseInt(a.getAttribute(\"y\"),10);if(!isNaN(c)&&!isNaN(d)){Blockly.RTL&&(c=-c);do for(var e=!1,f=this.getAllBlocks(),g=0,h;h=f[g];g++)h=h.getRelativeToSurfaceXY(),1>=Math.abs(c-h.x)&&1>=Math.abs(d-h.y)&&(c=Blockly.RTL?\nc-Blockly.SNAP_RADIUS:c+Blockly.SNAP_RADIUS,d+=2*Blockly.SNAP_RADIUS,e=!0);while(e);b.moveBy(c,d)}b.select();a.getAttribute(\"isForFunc\")&&(Entry.Func.positionBlock_(b),a.removeAttribute(\"isForFunc\"))}};Blockly.Workspace.prototype.remainingCapacity=function(){return Infinity==this.maxBlocks?Infinity:this.maxBlocks-this.getAllBlocks().length};\nBlockly.Workspace.prototype.organizeBlocks=function(){var a=this.getMetrics();if(a){var b;Blockly.hasBlockMenu?b=Math.round(a.viewLeft+35):(b=Blockly.mainWorkspace.flyout_.svgGroup_.getBBox().width,b=Math.round(a.viewLeft+30+b));var c=0,d=0,e=a.viewTop+a.viewHeight-30,f=this.getTopBlocks(),g;for(g in f){var h=f[g].getHeightWidth(),k=c+a.viewTop+20;k>e&&(b=b+d+10,c=d=0);d=Math.max(d,h.width);k=c+a.viewTop+20;f[g].svg_.getRootElement().setAttribute(\"transform\",\"translate(\"+b+\",\"+k+\")\");c=c+h.height+\n20}a=Blockly.Xml.workspaceToDom(this);this.clear();Blockly.Xml.domToWorkspace(this,a)}};Blockly.Workspace.prototype.clear=Blockly.Workspace.prototype.clear;Blockly.Bubble=function(a,b,c,d,e,f,g){var h=Blockly.Bubble.ARROW_ANGLE;Blockly.RTL&&(h=-h);this.arrow_radians_=h/360*Math.PI*2;this.workspace_=a;this.content_=b;this.shape_=c;a.getBubbleCanvas().appendChild(this.createDom_(b,!(!f||!g)));this.setAnchorLocation(d,e);f&&g||(a=this.content_.getBBox(),f=a.width+2*Blockly.Bubble.BORDER_WIDTH,g=a.height+2*Blockly.Bubble.BORDER_WIDTH);this.setBubbleSize(f,g);this.positionBubble_();this.renderArrow_();this.rendered_=!0;Blockly.readOnly||(Blockly.bindEvent_(this.bubbleBack_,\n\"mousedown\",this,this.bubbleMouseDown_),this.resizeGroup_&&Blockly.bindEvent_(this.resizeGroup_,\"mousedown\",this,this.resizeMouseDown_))};Blockly.Bubble.BORDER_WIDTH=6;Blockly.Bubble.ARROW_THICKNESS=10;Blockly.Bubble.ARROW_ANGLE=20;Blockly.Bubble.ARROW_BEND=4;Blockly.Bubble.ANCHOR_RADIUS=8;Blockly.Bubble.onMouseUpWrapper_=null;Blockly.Bubble.onMouseMoveWrapper_=null;\nBlockly.Bubble.unbindDragEvents_=function(){Blockly.Bubble.onMouseUpWrapper_&&(Blockly.unbindEvent_(Blockly.Bubble.onMouseUpWrapper_),Blockly.Bubble.onMouseUpWrapper_=null);Blockly.Bubble.onMouseMoveWrapper_&&(Blockly.unbindEvent_(Blockly.Bubble.onMouseMoveWrapper_),Blockly.Bubble.onMouseMoveWrapper_=null)};Blockly.Bubble.prototype.rendered_=!1;Blockly.Bubble.prototype.anchorX_=0;Blockly.Bubble.prototype.anchorY_=0;Blockly.Bubble.prototype.relativeLeft_=0;Blockly.Bubble.prototype.relativeTop_=0;\nBlockly.Bubble.prototype.width_=0;Blockly.Bubble.prototype.height_=0;Blockly.Bubble.prototype.autoLayout_=!0;\nBlockly.Bubble.prototype.createDom_=function(a,b){this.bubbleGroup_=Blockly.createSvgElement(\"g\",{},null);var c=Blockly.createSvgElement(\"g\",{filter:\"url(#blocklyEmboss)\"},this.bubbleGroup_);this.bubbleArrow_=Blockly.createSvgElement(\"path\",{},c);this.bubbleBack_=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyDraggable\",x:0,y:0,rx:Blockly.Bubble.BORDER_WIDTH,ry:Blockly.Bubble.BORDER_WIDTH},c);b?(this.resizeGroup_=Blockly.createSvgElement(\"g\",{\"class\":Blockly.RTL?\"blocklyResizeSW\":\"blocklyResizeSE\"},\nthis.bubbleGroup_),c=2*Blockly.Bubble.BORDER_WIDTH,Blockly.createSvgElement(\"polygon\",{points:\"0,x x,x x,0\".replace(/x/g,c.toString())},this.resizeGroup_),Blockly.createSvgElement(\"line\",{\"class\":\"blocklyResizeLine\",x1:c/3,y1:c-1,x2:c-1,y2:c/3},this.resizeGroup_),Blockly.createSvgElement(\"line\",{\"class\":\"blocklyResizeLine\",x1:2*c/3,y1:c-1,x2:c-1,y2:2*c/3},this.resizeGroup_)):this.resizeGroup_=null;this.bubbleGroup_.appendChild(a);return this.bubbleGroup_};\nBlockly.Bubble.prototype.bubbleMouseDown_=function(a){this.promote_();Blockly.Bubble.unbindDragEvents_();Blockly.isRightButton(a)||Blockly.isTargetInput_(a)||(Blockly.setCursorHand_(!0),this.dragDeltaX=Blockly.RTL?this.relativeLeft_+a.clientX:this.relativeLeft_-a.clientX,this.dragDeltaY=this.relativeTop_-a.clientY,Blockly.Bubble.onMouseUpWrapper_=Blockly.bindEvent_(document,\"mouseup\",this,Blockly.Bubble.unbindDragEvents_),Blockly.Bubble.onMouseMoveWrapper_=Blockly.bindEvent_(document,\"mousemove\",\nthis,this.bubbleMouseMove_),Blockly.hideChaff(),a.stopPropagation())};Blockly.Bubble.prototype.bubbleMouseMove_=function(a){this.autoLayout_=!1;this.relativeLeft_=Blockly.RTL?this.dragDeltaX-a.clientX:this.dragDeltaX+a.clientX;this.relativeTop_=this.dragDeltaY+a.clientY;this.positionBubble_();this.renderArrow_()};\nBlockly.Bubble.prototype.resizeMouseDown_=function(a){this.promote_();Blockly.Bubble.unbindDragEvents_();Blockly.isRightButton(a)||(Blockly.setCursorHand_(!0),this.resizeDeltaWidth=Blockly.RTL?this.width_+a.clientX:this.width_-a.clientX,this.resizeDeltaHeight=this.height_-a.clientY,Blockly.Bubble.onMouseUpWrapper_=Blockly.bindEvent_(document,\"mouseup\",this,Blockly.Bubble.unbindDragEvents_),Blockly.Bubble.onMouseMoveWrapper_=Blockly.bindEvent_(document,\"mousemove\",this,this.resizeMouseMove_),Blockly.hideChaff(),\na.stopPropagation())};Blockly.Bubble.prototype.resizeMouseMove_=function(a){this.autoLayout_=!1;var b=this.resizeDeltaWidth,c=this.resizeDeltaHeight+a.clientY,b=Blockly.RTL?b-a.clientX:b+a.clientX;this.setBubbleSize(b,c);Blockly.RTL&&this.positionBubble_()};Blockly.Bubble.prototype.registerResizeEvent=function(a,b){Blockly.bindEvent_(this.bubbleGroup_,\"resize\",a,b)};Blockly.Bubble.prototype.promote_=function(){this.bubbleGroup_.parentNode.appendChild(this.bubbleGroup_)};\nBlockly.Bubble.prototype.setAnchorLocation=function(a,b){this.anchorX_=a;this.anchorY_=b;this.rendered_&&this.positionBubble_()};\nBlockly.Bubble.prototype.layoutBubble_=function(){var a=-this.width_/4,b=-this.height_-Blockly.BlockSvg.MIN_BLOCK_Y;if(this.workspace_.scrollbar){var c=this.workspace_.getMetrics();this.anchorX_+a<Blockly.BlockSvg.SEP_SPACE_X+c.viewLeft?a=Blockly.BlockSvg.SEP_SPACE_X+c.viewLeft-this.anchorX_:c.viewLeft+c.viewWidth<this.anchorX_+a+this.width_+Blockly.BlockSvg.SEP_SPACE_X+Blockly.Scrollbar.scrollbarThickness&&(a=c.viewLeft+c.viewWidth-this.anchorX_-this.width_-Blockly.BlockSvg.SEP_SPACE_X-Blockly.Scrollbar.scrollbarThickness);\nthis.anchorY_+b<Blockly.BlockSvg.SEP_SPACE_Y+c.viewTop&&(b=this.shape_.getBBox().height)}this.relativeLeft_=a;this.relativeTop_=b};Blockly.Bubble.prototype.positionBubble_=function(){this.bubbleGroup_.setAttribute(\"transform\",\"translate(\"+(Blockly.RTL?this.anchorX_-this.relativeLeft_-this.width_:this.anchorX_+this.relativeLeft_)+\", \"+(this.relativeTop_+this.anchorY_)+\")\")};Blockly.Bubble.prototype.getBubbleSize=function(){return{width:this.width_,height:this.height_}};\nBlockly.Bubble.prototype.setBubbleSize=function(a,b){var c=2*Blockly.Bubble.BORDER_WIDTH;a=Math.max(a,c+45);b=Math.max(b,c+Blockly.BlockSvg.FIELD_HEIGHT);this.width_=a;this.height_=b;this.bubbleBack_.setAttribute(\"width\",a);this.bubbleBack_.setAttribute(\"height\",b);this.resizeGroup_&&(Blockly.RTL?this.resizeGroup_.setAttribute(\"transform\",\"translate(\"+2*Blockly.Bubble.BORDER_WIDTH+\", \"+(b-c)+\") scale(-1 1)\"):this.resizeGroup_.setAttribute(\"transform\",\"translate(\"+(a-c)+\", \"+(b-c)+\")\"));this.rendered_&&\n(this.autoLayout_&&this.layoutBubble_(),this.positionBubble_(),this.renderArrow_());Blockly.fireUiEvent(this.bubbleGroup_,\"resize\")};\nBlockly.Bubble.prototype.renderArrow_=function(){var a=[],b=this.width_/2,c=this.height_/2,d=-this.relativeLeft_,e=-this.relativeTop_;if(b==d&&c==e)a.push(\"M \"+b+\",\"+c);else{e-=c;d-=b;Blockly.RTL&&(d*=-1);var f=Math.sqrt(e*e+d*d),g=Math.acos(d/f);0>e&&(g=2*Math.PI-g);var h=g+Math.PI/2;h>2*Math.PI&&(h-=2*Math.PI);var k=Math.sin(h),n=Math.cos(h),p=this.getBubbleSize(),h=(p.width+p.height)/Blockly.Bubble.ARROW_THICKNESS,h=Math.min(h,p.width,p.height)/2,p=1-Blockly.Bubble.ANCHOR_RADIUS/f,d=b+p*d,e=c+\np*e,p=b+h*n,m=c+h*k,b=b-h*n,c=c-h*k,k=g+this.arrow_radians_;k>2*Math.PI&&(k-=2*Math.PI);g=Math.sin(k)*f/Blockly.Bubble.ARROW_BEND;f=Math.cos(k)*f/Blockly.Bubble.ARROW_BEND;a.push(\"M\"+p+\",\"+m);a.push(\"C\"+(p+f)+\",\"+(m+g)+\" \"+d+\",\"+e+\" \"+d+\",\"+e);a.push(\"C\"+d+\",\"+e+\" \"+(b+f)+\",\"+(c+g)+\" \"+b+\",\"+c)}a.push(\"z\");this.bubbleArrow_.setAttribute(\"d\",a.join(\" \"))};Blockly.Bubble.prototype.setColour=function(a){this.bubbleBack_.setAttribute(\"fill\",a);this.bubbleArrow_.setAttribute(\"fill\",a)};\nBlockly.Bubble.prototype.dispose=function(){Blockly.Bubble.unbindDragEvents_();goog.dom.removeNode(this.bubbleGroup_);this.shape_=this.content_=this.workspace_=this.bubbleGroup_=null};Blockly.Icon=function(a){this.block_=a};Blockly.Icon.RADIUS=8;Blockly.Icon.prototype.bubble_=null;Blockly.Icon.prototype.iconX_=0;Blockly.Icon.prototype.iconY_=0;Blockly.Icon.prototype.createIcon_=function(){this.iconGroup_=Blockly.createSvgElement(\"g\",{},null);this.block_.getSvgRoot().appendChild(this.iconGroup_);Blockly.bindEvent_(this.iconGroup_,\"mouseup\",this,this.iconClick_);this.updateEditable()};\nBlockly.Icon.prototype.dispose=function(){goog.dom.removeNode(this.iconGroup_);this.iconGroup_=null;this.setVisible(!1);this.block_=null};Blockly.Icon.prototype.updateEditable=function(){this.block_.isInFlyout?Blockly.removeClass_(this.iconGroup_,\"blocklyIconGroup\"):Blockly.addClass_(this.iconGroup_,\"blocklyIconGroup\")};Blockly.Icon.prototype.isVisible=function(){return!!this.bubble_};Blockly.Icon.prototype.iconClick_=function(a){this.block_.isInFlyout||this.setVisible(!this.isVisible())};\nBlockly.Icon.prototype.updateColour=function(){if(this.isVisible()){var a=Blockly.makeColour(this.block_.getColour());this.bubble_.setColour(a)}};\nBlockly.Icon.prototype.renderIcon=function(a){if(this.block_.isCollapsed())return this.iconGroup_.setAttribute(\"display\",\"none\"),a;this.iconGroup_.setAttribute(\"display\",\"block\");var b=2*Blockly.Icon.RADIUS;Blockly.RTL&&(a-=b);this.iconGroup_.setAttribute(\"transform\",\"translate(\"+a+\", 5)\");this.computeIconLocation();return a=Blockly.RTL?a-Blockly.BlockSvg.SEP_SPACE_X:a+(b+Blockly.BlockSvg.SEP_SPACE_X)};\nBlockly.Icon.prototype.setIconLocation=function(a,b){this.iconX_=a;this.iconY_=b;this.isVisible()&&this.bubble_.setAnchorLocation(a,b)};Blockly.Icon.prototype.computeIconLocation=function(){var a=this.block_.getRelativeToSurfaceXY(),b=Blockly.getRelativeXY_(this.iconGroup_),c=a.x+b.x+Blockly.Icon.RADIUS,a=a.y+b.y+Blockly.Icon.RADIUS;c===this.iconX_&&a===this.iconY_||this.setIconLocation(c,a)};Blockly.Icon.prototype.getIconLocation=function(){return{x:this.iconX_,y:this.iconY_}};Blockly.Comment=function(a){Blockly.Comment.superClass_.constructor.call(this,a);this.createIcon_()};goog.inherits(Blockly.Comment,Blockly.Icon);Blockly.Comment.prototype.text_=\"\";Blockly.Comment.prototype.width_=160;Blockly.Comment.prototype.height_=80;\nBlockly.Comment.prototype.createIcon_=function(){Blockly.Icon.prototype.createIcon_.call(this);Blockly.createSvgElement(\"circle\",{\"class\":\"blocklyIconShield\",r:Blockly.Icon.RADIUS,cx:Blockly.Icon.RADIUS,cy:Blockly.Icon.RADIUS},this.iconGroup_);this.iconMark_=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyIconMark\",x:Blockly.Icon.RADIUS,y:2*Blockly.Icon.RADIUS-3},this.iconGroup_);this.iconMark_.appendChild(document.createTextNode(\"?\"))};\nBlockly.Comment.prototype.createEditor_=function(){this.foreignObject_=Blockly.createSvgElement(\"foreignObject\",{x:Blockly.Bubble.BORDER_WIDTH,y:Blockly.Bubble.BORDER_WIDTH},null);var a=document.createElementNS(Blockly.HTML_NS,\"body\");a.setAttribute(\"xmlns\",Blockly.HTML_NS);a.className=\"blocklyMinimalBody\";this.textarea_=document.createElementNS(Blockly.HTML_NS,\"textarea\");this.textarea_.className=\"blocklyCommentTextarea\";this.textarea_.setAttribute(\"dir\",Blockly.RTL?\"RTL\":\"LTR\");this.updateEditable();\na.appendChild(this.textarea_);this.foreignObject_.appendChild(a);Blockly.bindEvent_(this.textarea_,\"mouseup\",this,this.textareaFocus_);return this.foreignObject_};Blockly.Comment.prototype.updateEditable=function(){this.textarea_&&(this.block_.isEditable()?(this.textarea_.removeAttribute(\"disabled\"),this.textarea_.removeAttribute(\"readonly\")):(this.textarea_.setAttribute(\"disabled\",\"disabled\"),this.textarea_.setAttribute(\"readonly\",\"readonly\")));Blockly.Icon.prototype.updateEditable.call(this)};\nBlockly.Comment.prototype.resizeBubble_=function(){var a=this.bubble_.getBubbleSize(),b=2*Blockly.Bubble.BORDER_WIDTH;this.foreignObject_.setAttribute(\"width\",a.width-b);this.foreignObject_.setAttribute(\"height\",a.height-b);this.textarea_.style.width=a.width-b-4+\"px\";this.textarea_.style.height=a.height-b-4+\"px\"};\nBlockly.Comment.prototype.setVisible=function(a){if(a!=this.isVisible()){var b=this.getText(),c=this.getBubbleSize();a?(this.bubble_=new Blockly.Bubble(this.block_.workspace,this.createEditor_(),this.block_.svg_.svgGroup_,this.iconX_,this.iconY_,this.width_,this.height_),this.bubble_.registerResizeEvent(this,this.resizeBubble_),this.updateColour(),this.text_=null):(this.bubble_.dispose(),this.foreignObject_=this.textarea_=this.bubble_=null);this.setText(b);this.setBubbleSize(c.width,c.height)}};\nBlockly.Comment.prototype.textareaFocus_=function(a){this.bubble_.promote_();this.textarea_.focus()};Blockly.Comment.prototype.getBubbleSize=function(){return this.isVisible()?this.bubble_.getBubbleSize():{width:this.width_,height:this.height_}};Blockly.Comment.prototype.setBubbleSize=function(a,b){this.isVisible()?this.bubble_.setBubbleSize(a,b):(this.width_=a,this.height_=b)};Blockly.Comment.prototype.getText=function(){return this.isVisible()?this.textarea_.value:this.text_};\nBlockly.Comment.prototype.setText=function(a){this.isVisible()?this.textarea_.value=a:this.text_=a};Blockly.Comment.prototype.dispose=function(){this.block_.comment=null;Blockly.Icon.prototype.dispose.call(this)};Blockly.Connection=function(a,b){this.sourceBlock_=a;this.targetConnection=null;this.type=b;this.y_=this.x_=0;this.inDB_=!1;this.dbList_=this.sourceBlock_.workspace.connectionDBList};\nBlockly.Connection.prototype.dispose=function(){if(this.targetConnection)throw\"Disconnect connection before disposing of it.\";this.inDB_&&this.dbList_[this.type].removeConnection_(this);this.inDB_=!1;Blockly.highlightedConnection_==this&&(Blockly.highlightedConnection_=null);Blockly.localConnection_==this&&(Blockly.localConnection_=null)};Blockly.Connection.prototype.isSuperior=function(){return this.type==Blockly.INPUT_VALUE||this.type==Blockly.NEXT_STATEMENT};\nBlockly.Connection.prototype.connect=function(a){if(this.sourceBlock_==a.sourceBlock_)throw\"Attempted to connect a block to itself.\";if(this.sourceBlock_.workspace!==a.sourceBlock_.workspace)throw\"Blocks are on different workspaces.\";if(Blockly.OPPOSITE_TYPE[this.type]!=a.type)throw\"Attempt to connect incompatible types.\";if(this.type==Blockly.INPUT_VALUE||this.type==Blockly.OUTPUT_VALUE){if(this.targetConnection)throw\"Source connection already connected (value).\";if(a.targetConnection){var b=a.targetBlock();\nb.setParent(null);if(!b.outputConnection)throw\"Orphan block does not have an output connection.\";for(var c=this.sourceBlock_,d;d=Blockly.Connection.singleConnection_(c,b);)if(d.targetBlock())c=d.targetBlock();else{d.connect(b.outputConnection);b=null;break}b&&(d=b.type.toUpperCase(),-1<Blockly.primitiveTypes.indexOf(d)?b.dispose(!0,!1):window.setTimeout(function(){b.outputConnection.bumpAwayFrom_(a)},Blockly.BUMP_DELAY),c.previousConnection||c.nextConnection||window.setTimeout(function(){Blockly.mainWorkspace.render()},\n0))}}else{if(this.targetConnection)throw\"Source connection already connected (block).\";if(a.targetConnection){if(this.type!=Blockly.PREVIOUS_STATEMENT)throw\"Can only do a mid-stack connection with the top of a block.\";b=a.targetBlock();b.setParent(null);if(!b.previousConnection)throw\"Orphan block does not have a previous connection.\";for(c=this.sourceBlock_;c.nextConnection;)if(c.nextConnection.targetConnection)c=c.nextConnection.targetBlock();else{c.nextConnection.connect(b.previousConnection);b=\nnull;break}b&&window.setTimeout(function(){b.previousConnection.bumpAwayFrom_(a)},Blockly.BUMP_DELAY)}}this.isSuperior()?(c=this.sourceBlock_,d=a.sourceBlock_):(c=a.sourceBlock_,d=this.sourceBlock_);this.targetConnection=a;a.targetConnection=this;d.setParent(c);c.rendered&&c.svg_.updateDisabled();d.rendered&&d.svg_.updateDisabled();c.rendered&&d.rendered&&(this.type==Blockly.NEXT_STATEMENT||this.type==Blockly.PREVIOUS_STATEMENT?d.render():c.render())};\nBlockly.Connection.singleConnection_=function(a,b){for(var c=!1,d=0;d<a.inputList.length;d++){var e=a.inputList[d].connection;if(e&&e.type==Blockly.INPUT_VALUE&&b.outputConnection.checkType_(e)){if(c)return null;c=e}}return c};\nBlockly.Connection.prototype.disconnect=function(){var a=this.targetConnection;if(!a)throw\"Source connection not connected.\";if(a.targetConnection!=this)throw\"Target connection not connected to source connection.\";this.targetConnection=a.targetConnection=null;var b=this.sourceBlock_;if(!b.isInFlyout&&b.isEditing&&b.outputConnection instanceof Blockly.Connection){if(a.sourceBlock_.outputConnection&&\"PARAM\"==a.sourceBlock_.outputConnection.check_[0].toUpperCase()&&\"PARAM\"!=a.check_[0].toUpperCase()){var c=\nBlockly.Xml.blockToDom_(b),c=Blockly.Xml.domToBlock(b.workspace,c);a.connect(c.outputConnection)}else a.check_&&-1<a.check_.indexOf(\"Number\")?(c=Blockly.Xml.textToDom('<xml><block type=\"number\"><field name=\"NUM\">10</field></block></xml>'),c=Blockly.Xml.domToBlock(b.workspace,c.childNodes[0]),a.connect(c.outputConnection)):a.check_&&-1<a.check_.indexOf(\"String\")?(c=Blockly.Xml.textToDom('<xml><block type=\"text\"><field name=\"NAME\">\\ubb38\\uc790</field></block></xml>'),c=Blockly.Xml.domToBlock(b.workspace,\nc.childNodes[0]),a.connect(c.outputConnection)):a.check_&&-1<a.check_.indexOf(\"Boolean\")&&(c=Blockly.Xml.textToDom('<xml><block type=\"True\"></block></xml>'),c=Blockly.Xml.domToBlock(b.workspace,c.childNodes[0]),a.connect(c.outputConnection));b.isDrag=!1;a.sourceBlock_.isDrag=!1}this.isSuperior()?(b=this.sourceBlock_,a=a.sourceBlock_):(b=a.sourceBlock_,a=this.sourceBlock_);b.rendered&&b.render();a.rendered&&(a.svg_.updateDisabled(),a.render())};\nBlockly.Connection.prototype.targetBlock=function(){return this.targetConnection?this.targetConnection.sourceBlock_:null};\nBlockly.Connection.prototype.bumpAwayFrom_=function(a){if(0==Blockly.Block.dragMode_){var b=this.sourceBlock_.getRootBlock();if(!b.isInFlyout){var c=!1;if(!b.isMovable()){b=a.sourceBlock_.getRootBlock();if(!b.isMovable())return;a=this;c=!0}var d=b.getSvgRoot();d.parentNode.appendChild(d);d=a.x_+Blockly.SNAP_RADIUS-this.x_;a=a.y_+2*Blockly.SNAP_RADIUS-this.y_;c&&(a=-a);Blockly.RTL&&(d=-d);b.moveBy(d,a)}}};\nBlockly.Connection.prototype.moveTo=function(a,b){this.inDB_&&this.dbList_[this.type].removeConnection_(this);this.x_=a;this.y_=b;this.dbList_[this.type].addConnection_(this)};Blockly.Connection.prototype.moveBy=function(a,b){this.moveTo(this.x_+a,this.y_+b)};\nBlockly.Connection.prototype.highlight=function(){var a,b=this.sourceBlock_.getRelativeToSurfaceXY(),c=this.x_-b.x,b=this.y_-b.y;this.type==Blockly.INPUT_VALUE||this.type==Blockly.OUTPUT_VALUE?(a=this.check_?this.check_[0]:\"null\",\"PARAM\"==a.toUpperCase()?a=(a=this.sourceBlock_.outputConnection)?\"M -20,-2 l 2,2 0,3 4,0 0,12 -4,0 0,3 -2,2\":\"M -20,3 l -2,2 0,3 4,0 0,12 -4,0 0,3 2,2\":\"BOOLEAN\"==a.toUpperCase()?(a=this.targetConnection&&this.targetConnection.sourceBlock_)?(a=this.targetConnection.sourceBlock_.svg_.svgPathLight_.getAttribute(\"d\").split(\"z\")[0],\na+=\"z\"):a=\"M 16,0 h -20 l -11,11 11,11.5 h 20l 11,-11 -11,-11 z\":(a=this.targetConnection&&this.targetConnection.sourceBlock_)?(a=this.targetConnection.sourceBlock_.svg_.svgPathLight_.getAttribute(\"d\").split(\"z\")[0],a+=\"z\"):a=\"M 10,0 h -10 a 12,9.9 0 0,0 0,19.5 h 10a 11,9.9 0 0,0 0,-19.5 z\",Blockly.Connection.highlightedPath_=Blockly.createSvgElement(\"path\",{\"class\":\"blocklyHighlightedConnectionPathInline\",d:a,transform:\"translate(\"+c+\", \"+b+\")\"},this.sourceBlock_.getSvgRoot())):(a=Blockly.RTL?\"m 20,0 h -5 l -6,4 -3,0 -6,-4 h -5\":\n\"m -15,0 l 7,8 7,-8\",Blockly.Connection.highlightedPath_=Blockly.createSvgElement(\"path\",{\"class\":\"blocklyHighlightedConnectionPath\",d:a,transform:\"translate(\"+c+\", \"+b+\")\"},this.sourceBlock_.getSvgRoot()))};Blockly.Connection.prototype.unhighlight=function(){goog.dom.removeNode(Blockly.Connection.highlightedPath_);delete Blockly.Connection.highlightedPath_};\nBlockly.Connection.prototype.tighten_=function(){var a=Math.round(this.targetConnection.x_-this.x_),b=Math.round(this.targetConnection.y_-this.y_);if(0!=a||0!=b){var c=this.targetBlock(),d=c.getSvgRoot();if(!d)throw\"block is not rendered.\";d=Blockly.getRelativeXY_(d);c.getSvgRoot().setAttribute(\"transform\",\"translate(\"+(d.x-a)+\", \"+(d.y-b)+\")\");c.moveConnections_(-a,-b)}};\nBlockly.Connection.prototype.closest=function(a,b,c){function d(b){var c=e[b];if((c.type==Blockly.OUTPUT_VALUE||c.type==Blockly.PREVIOUS_STATEMENT)&&c.targetConnection||!p.checkType_(c))return!0;c=c.sourceBlock_;do{if(n==c)return!0;c=c.getParent()}while(c);var d=f-e[b].x_,c=g-e[b].y_,d=Math.sqrt(d*d+c*c);d<=a&&(k=e[b],a=d);return c<a}if(this.targetConnection)return{connection:null,radius:a};var e=this.dbList_[Blockly.OPPOSITE_TYPE[this.type]],f=this.x_+b,g=this.y_+c;b=0;for(var h=c=e.length-2;b<h;)e[h].y_<\ng?b=h:c=h,h=Math.floor((b+c)/2);c=b=h;var k=null,n=this.sourceBlock_,p=this;if(e.length){for(;0<=b&&d(b);)b--;do c++;while(c<e.length&&d(c))}return{connection:k,radius:a}};Blockly.Connection.prototype.checkType_=function(a){if(this.sourceBlock_.isInFlyout||a.sourceBlock_.isInFlyout)return!1;if(!this.check_||!a.check_)return!0;for(var b=0;b<this.check_.length;b++)if(-1!=a.check_.indexOf(this.check_[b]))return!0;return!1};\nBlockly.Connection.prototype.setCheck=function(a){a?(a instanceof Array||(a=[a]),this.check_=a,this.targetConnection&&!this.checkType_(this.targetConnection)&&(this.isSuperior()?this.targetBlock().setParent(null):this.sourceBlock_.setParent(null),this.sourceBlock_.bumpNeighbours_())):this.check_=null;return this};\nBlockly.Connection.prototype.neighbours_=function(a){function b(b){var f=d-c[b].x_,g=e-c[b].y_;Math.sqrt(f*f+g*g)<=a&&k.push(c[b]);return g<a}for(var c=this.dbList_[Blockly.OPPOSITE_TYPE[this.type]],d=this.x_,e=this.y_,f=0,g=c.length-2,h=g;f<h;)c[h].y_<e?f=h:g=h,h=Math.floor((f+g)/2);var g=f=h,k=[];if(c.length){for(;0<=f&&b(f);)f--;do g++;while(g<c.length&&b(g))}return k};\nBlockly.Connection.prototype.hideAll=function(){this.inDB_&&this.dbList_[this.type].removeConnection_(this);if(this.targetConnection)for(var a=this.targetBlock().getDescendants(),b=0;b<a.length;b++){for(var c=a[b],d=c.getConnections_(!0),e=0;e<d.length;e++){var f=d[e];f.inDB_&&this.dbList_[f.type].removeConnection_(f)}c=c.getIcons();for(d=0;d<c.length;d++)c[d].setVisible(!1)}};\nBlockly.Connection.prototype.unhideAll=function(){this.inDB_||this.dbList_[this.type].addConnection_(this);var a=[];if(this.type!=Blockly.INPUT_VALUE&&this.type!=Blockly.NEXT_STATEMENT)return a;var b=this.targetBlock();if(b){var c;b.isCollapsed()?(c=[],b.outputConnection&&c.push(b.outputConnection),b.nextConnection&&c.push(b.nextConnection),b.previousConnection&&c.push(b.previousConnection)):c=b.getConnections_(!0);for(var d=0;d<c.length;d++)a=a.concat(c[d].unhideAll());0==a.length&&(a[0]=b)}return a};\nBlockly.ConnectionDB=function(){};Blockly.ConnectionDB.prototype=[];Blockly.ConnectionDB.constructor=Blockly.ConnectionDB;Blockly.ConnectionDB.prototype.addConnection_=function(a){if(a.inDB_)throw\"Connection already in database.\";for(var b=0,c=this.length;b<c;){var d=Math.floor((b+c)/2);if(this[d].y_<a.y_)b=d+1;else if(this[d].y_>a.y_)c=d;else{b=d;break}}this.splice(b,0,a);a.inDB_=!0};\nBlockly.ConnectionDB.prototype.removeConnection_=function(a){if(!a.inDB_)throw\"Connection not in database.\";a.inDB_=!1;for(var b=0,c=this.length-2,d=c;b<d;)this[d].y_<a.y_?b=d:c=d,d=Math.floor((b+c)/2);for(c=b=d;0<=b&&this[b].y_==a.y_;){if(this[b]==a){this.splice(b,1);return}b--}do{if(this[c]==a){this.splice(c,1);return}c++}while(c<this.length&&this[c].y_==a.y_);throw\"Unable to find connection in connectionDB.\";};\nBlockly.ConnectionDB.init=function(a){var b=[];b[Blockly.INPUT_VALUE]=new Blockly.ConnectionDB;b[Blockly.OUTPUT_VALUE]=new Blockly.ConnectionDB;b[Blockly.NEXT_STATEMENT]=new Blockly.ConnectionDB;b[Blockly.PREVIOUS_STATEMENT]=new Blockly.ConnectionDB;a.connectionDBList=b};Blockly.ContextMenu={};Blockly.ContextMenu.X_PADDING=20;Blockly.ContextMenu.Y_HEIGHT=20;Blockly.ContextMenu.visible=!1;\nBlockly.ContextMenu.createDom=function(){var a=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyHidden\"},null);Blockly.ContextMenu.svgGroup=a;Blockly.ContextMenu.svgShadow=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyContextMenuShadow\",x:2,y:-2},a);Blockly.ContextMenu.svgBackground=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyContextMenuBackground\",y:-4},a);Blockly.ContextMenu.svgOptions=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyContextMenuOptions\"},a);return Blockly.contextMenu=a};\nBlockly.ContextMenu.show=function(a,b){if(b.length){goog.dom.removeChildren(Blockly.ContextMenu.svgOptions);Blockly.ContextMenu.svgGroup.style.display=\"block\";for(var c=0,d=[Blockly.ContextMenu.svgBackground,Blockly.ContextMenu.svgShadow],e=0,f;f=b[e];e++){var g=Blockly.ContextMenu.optionToDom(f.text),h=g.firstChild,k=g.lastChild;Blockly.ContextMenu.svgOptions.appendChild(g);g.setAttribute(\"transform\",\"translate(0, \"+e*Blockly.ContextMenu.Y_HEIGHT+\")\");d.push(h);Blockly.bindEvent_(g,\"mousedown\",null,\nBlockly.noEvent);f.enabled?(Blockly.bindEvent_(g,\"mouseup\",null,f.callback),Blockly.bindEvent_(g,\"mouseup\",null,Blockly.ContextMenu.hide)):g.setAttribute(\"class\",\"blocklyMenuDivDisabled\");c=Math.max(c,k.getComputedTextLength())}c+=2*Blockly.ContextMenu.X_PADDING;for(e=0;e<d.length;e++)d[e].setAttribute(\"width\",c);if(Blockly.RTL)for(e=0;g=Blockly.ContextMenu.svgOptions.childNodes[e];e++)k=g.lastChild,k.setAttribute(\"text-anchor\",\"end\"),k.setAttribute(\"x\",c-Blockly.ContextMenu.X_PADDING);Blockly.ContextMenu.svgBackground.setAttribute(\"height\",\nb.length*Blockly.ContextMenu.Y_HEIGHT+8);Blockly.ContextMenu.svgShadow.setAttribute(\"height\",b.length*Blockly.ContextMenu.Y_HEIGHT+10);c=a.x;d=a.y;e=Blockly.ContextMenu.svgGroup.getBBox();f=Blockly.svgSize();d+e.height>f.height&&(d-=e.height-10);Blockly.RTL?0>=c-e.width?c++:c-=e.width:c+e.width>f.width?c-=e.width:c++;Blockly.ContextMenu.svgGroup.setAttribute(\"transform\",\"translate(\"+c+\", \"+d+\")\");Blockly.ContextMenu.visible=!0}else Blockly.ContextMenu.hide()};\nBlockly.ContextMenu.optionToDom=function(a){var b=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyMenuDiv\"},null);Blockly.createSvgElement(\"rect\",{height:Blockly.ContextMenu.Y_HEIGHT},b);var c=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyMenuText\",x:Blockly.ContextMenu.X_PADDING,y:15},b);a=document.createTextNode(a);c.appendChild(a);return b};Blockly.ContextMenu.hide=function(){Blockly.ContextMenu.visible&&(Blockly.ContextMenu.svgGroup.style.display=\"none\",Blockly.ContextMenu.visible=!1)};\nBlockly.ContextMenu.callbackFactory=function(a,b){return function(){var c=Blockly.Xml.domToBlock(a.workspace,b),d=a.getRelativeToSurfaceXY();d.x=Blockly.RTL?d.x-Blockly.SNAP_RADIUS:d.x+Blockly.SNAP_RADIUS;d.y+=2*Blockly.SNAP_RADIUS;c.moveBy(d.x,d.y);c.select()}};Blockly.Field=function(a){this.sourceBlock_=null;this.fieldGroup_=Blockly.createSvgElement(\"g\",{},null);this.borderRect_=Blockly.createSvgElement(\"rect\",{rx:0,ry:0,x:-Blockly.BlockSvg.SEP_SPACE_X/3,y:0,height:16},this.fieldGroup_);this instanceof Blockly.FieldTextInput&&(this.borderRect_.setAttribute(\"x\",-Blockly.BlockSvg.SEP_SPACE_X/2),this.borderRect_.setAttribute(\"y\",\"-2\"));this.textElement_=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyText\",y:11},this.fieldGroup_);this.size_={height:14,width:0};\nthis.setText(a);this.visible_=!0};Blockly.Field.prototype.clone=function(){goog.asserts.fail(\"There should never be an instance of Field, only its derived classes.\")};Blockly.Field.NBSP=\"\\u00a0\";Blockly.Field.prototype.EDITABLE=!0;\nBlockly.Field.prototype.init=function(a){if(this.sourceBlock_)throw\"Field has already been initialized once.\";this.sourceBlock_=a;this.updateEditable();a.getSvgRoot().appendChild(this.fieldGroup_);this.mouseUpWrapper_=Blockly.bindEvent_(this.fieldGroup_,\"mouseup\",this,this.onMouseUp_);this.setText(null)};\nBlockly.Field.prototype.dispose=function(){this.mouseUpWrapper_&&(Blockly.unbindEvent_(this.mouseUpWrapper_),this.mouseUpWrapper_=null);this.sourceBlock_=null;goog.dom.removeNode(this.fieldGroup_);this.borderRect_=this.textElement_=this.fieldGroup_=null};\nBlockly.Field.prototype.updateEditable=function(){this.EDITABLE&&(this.sourceBlock_.isEditable()?(this.arrow_||this.symbol_?Blockly.addClass_(this.fieldGroup_,\"blocklyEditableField\"):Blockly.addClass_(this.fieldGroup_,\"blocklyEditableText\"),Blockly.removeClass_(this.fieldGroup_,\"blocklyNoNEditableText\"),this.fieldGroup_.style.cursor=this.CURSOR):(Blockly.addClass_(this.fieldGroup_,\"blocklyNonEditableText\"),Blockly.removeClass_(this.fieldGroup_,\"blocklyEditableText\"),this.fieldGroup_.style.cursor=\n\"\"))};Blockly.Field.prototype.isVisible=function(){return this.visible_};Blockly.Field.prototype.setVisible=function(a){this.visible_=a;this.getRootElement().style.display=a?\"block\":\"none\"};Blockly.Field.prototype.getRootElement=function(){return this.fieldGroup_};Blockly.Field.prototype.render_=function(){var a=this.textElement_.getComputedTextLength();this.borderRect_&&this.borderRect_.setAttribute(\"width\",a+Blockly.BlockSvg.SEP_SPACE_X);this.size_.width=a};\nBlockly.Field.prototype.getSize=function(){this.size_.width||this.render_();return this.size_};Blockly.Field.prototype.getText=function(){return this.text_};\nBlockly.Field.prototype.setText=function(a,b){if(null!==a&&a!==this.text_){this.text_=a;goog.dom.removeChildren(this.textElement_);a=a.replace(/\\s/g,Blockly.Field.NBSP);a||(a=Blockly.Field.NBSP);b&&a.length>Blockly.TEXT_INPUT_MAX_LENGTH&&(a=a.substr(0,Blockly.TEXT_INPUT_MAX_LENGTH-1)+\"...\");var c=document.createTextNode(a);this.textElement_.appendChild(c);this.size_.width=0;this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours_(),this.sourceBlock_.workspace.fireChangeEvent())}};\nBlockly.Field.prototype.getValue=function(){return this.getText()};Blockly.Field.prototype.setValue=function(a){this.setText(a)};Blockly.Field.prototype.onMouseUp_=function(a){!Blockly.isRightButton(a)&&2!=Blockly.Block.dragMode_&&this.sourceBlock_.isEditable()&&(this.sourceBlock_.isDrag=!0,this.showEditor_())};Blockly.Field.prototype.setTooltip=function(a){};Blockly.Tooltip={};Blockly.Tooltip.visible=!1;Blockly.Tooltip.mouseOutPid_=0;Blockly.Tooltip.showPid_=0;Blockly.Tooltip.lastXY_={x:0,y:0};Blockly.Tooltip.element_=null;Blockly.Tooltip.poisonedElement_=null;Blockly.Tooltip.svgGroup_=null;Blockly.Tooltip.svgText_=null;Blockly.Tooltip.svgBackground_=null;Blockly.Tooltip.svgShadow_=null;Blockly.Tooltip.OFFSET_X=0;Blockly.Tooltip.OFFSET_Y=10;Blockly.Tooltip.RADIUS_OK=10;Blockly.Tooltip.HOVER_MS=1E3;Blockly.Tooltip.MARGINS=5;\nBlockly.Tooltip.createDom=function(){var a=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyHidden\"},null);Blockly.Tooltip.svgGroup_=a;Blockly.Tooltip.svgShadow_=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyTooltipShadow\",x:2,y:2},a);Blockly.Tooltip.svgBackground_=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyTooltipBackground\"},a);Blockly.Tooltip.svgText_=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyTooltipText\"},a);return a};\nBlockly.Tooltip.bindMouseEvents=function(a){Blockly.bindEvent_(a,\"mouseover\",null,Blockly.Tooltip.onMouseOver_);Blockly.bindEvent_(a,\"mouseout\",null,Blockly.Tooltip.onMouseOut_);Blockly.bindEvent_(a,\"mousemove\",null,Blockly.Tooltip.onMouseMove_)};Blockly.Tooltip.onMouseOver_=function(a){for(a=a.target;!goog.isString(a.tooltip)&&!goog.isFunction(a.tooltip);)a=a.tooltip;Blockly.Tooltip.element_!=a&&(Blockly.Tooltip.hide(),Blockly.Tooltip.poisonedElement_=null,Blockly.Tooltip.element_=a);window.clearTimeout(Blockly.Tooltip.mouseOutPid_)};\nBlockly.Tooltip.onMouseOut_=function(a){Blockly.Tooltip.mouseOutPid_=window.setTimeout(function(){Blockly.Tooltip.element_=null;Blockly.Tooltip.poisonedElement_=null;Blockly.Tooltip.hide()},1);window.clearTimeout(Blockly.Tooltip.showPid_)};\nBlockly.Tooltip.onMouseMove_=function(a){!Blockly.Tooltip.element_||!Blockly.Tooltip.element_.tooltip||Blockly.ContextMenu&&Blockly.ContextMenu.visible||0!=Blockly.Block.dragMode_||(Blockly.Tooltip.visible?(a=Blockly.mouseToSvg(a),Math.sqrt(Math.pow(Blockly.Tooltip.lastXY_.x-a.x,2)+Math.pow(Blockly.Tooltip.lastXY_.y-a.y,2))>Blockly.Tooltip.RADIUS_OK&&Blockly.Tooltip.hide()):Blockly.Tooltip.poisonedElement_!=Blockly.Tooltip.element_&&(window.clearTimeout(Blockly.Tooltip.showPid_),Blockly.Tooltip.lastXY_=\nBlockly.mouseToSvg(a),Blockly.Tooltip.showPid_=window.setTimeout(Blockly.Tooltip.show_,Blockly.Tooltip.HOVER_MS)))};Blockly.Tooltip.hide=function(){Blockly.Tooltip.visible&&(Blockly.Tooltip.visible=!1,Blockly.Tooltip.svgGroup_&&(Blockly.Tooltip.svgGroup_.style.display=\"none\"));window.clearTimeout(Blockly.Tooltip.showPid_)};\nBlockly.Tooltip.show_=function(){Blockly.Tooltip.poisonedElement_=Blockly.Tooltip.element_;if(Blockly.Tooltip.svgGroup_){goog.dom.removeChildren(Blockly.Tooltip.svgText_);var a=Blockly.Tooltip.element_.tooltip;goog.isFunction(a)&&(a=a());for(var a=a.split(\"\\n\"),b=0;b<a.length;b++){var c=Blockly.createSvgElement(\"tspan\",{dy:\"1em\",x:Blockly.Tooltip.MARGINS},Blockly.Tooltip.svgText_),d=document.createTextNode(a[b]);c.appendChild(d)}Blockly.Tooltip.visible=!0;Blockly.Tooltip.svgGroup_.style.display=\"block\";\na=Blockly.Tooltip.svgText_.getBBox();b=2*Blockly.Tooltip.MARGINS+a.width;c=a.height;Blockly.Tooltip.svgBackground_.setAttribute(\"width\",b);Blockly.Tooltip.svgBackground_.setAttribute(\"height\",c);Blockly.Tooltip.svgShadow_.setAttribute(\"width\",b);Blockly.Tooltip.svgShadow_.setAttribute(\"height\",c);if(Blockly.RTL)for(var c=a.width,d=0,e;e=Blockly.Tooltip.svgText_.childNodes[d];d++)e.setAttribute(\"text-anchor\",\"end\"),e.setAttribute(\"x\",c+Blockly.Tooltip.MARGINS);c=Blockly.Tooltip.lastXY_.x;c=Blockly.RTL?\nc-(Blockly.Tooltip.OFFSET_X+b):c+Blockly.Tooltip.OFFSET_X;b=Blockly.Tooltip.lastXY_.y+Blockly.Tooltip.OFFSET_Y;d=Blockly.svgSize();b+a.height>d.height&&(b-=a.height+2*Blockly.Tooltip.OFFSET_Y);Blockly.RTL?c=Math.max(Blockly.Tooltip.MARGINS,c):c+a.width>d.width-2*Blockly.Tooltip.MARGINS&&(c=d.width-a.width-2*Blockly.Tooltip.MARGINS);Blockly.Tooltip.svgGroup_.setAttribute(\"transform\",\"translate(\"+c+\",\"+b+\")\")}};Blockly.FieldLabel=function(a,b){this.sourceBlock_=null;goog.isString(b)?this.textElement_=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyText\",style:\"fill:\"+b,y:12},null):this.textElement_=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyText\",y:12},null);this.size_={height:14,width:0};this.setText(a)};goog.inherits(Blockly.FieldLabel,Blockly.Field);Blockly.FieldLabel.prototype.clone=function(){return new Blockly.FieldLabel(this.getText())};Blockly.FieldLabel.prototype.EDITABLE=!1;\nBlockly.FieldLabel.prototype.init=function(a){if(this.sourceBlock_)throw\"Text has already been initialized once.\";this.sourceBlock_=a;a.getSvgRoot().appendChild(this.textElement_);this.textElement_.tooltip=this.sourceBlock_;Blockly.Tooltip&&Blockly.Tooltip.bindMouseEvents(this.textElement_)};Blockly.FieldLabel.prototype.dispose=function(){goog.dom.removeNode(this.textElement_);this.textElement_=null};Blockly.FieldLabel.prototype.getRootElement=function(){return this.textElement_};\nBlockly.FieldLabel.prototype.setTooltip=function(a){this.textElement_.tooltip=a};Blockly.Input=function(a,b,c,d){this.type=a;this.name=b;this.sourceBlock_=c;this.connection=d;this.fieldRow=[];this.align=Blockly.ALIGN_LEFT;this.visible_=!0};\nBlockly.Input.prototype.appendField=function(a,b){if(!a&&!b)return this;goog.isString(a)&&(a=new Blockly.FieldLabel(a,b));this.sourceBlock_.svg_&&a.init(this.sourceBlock_);a.name=b;a.prefixField&&this.appendField(a.prefixField);this.fieldRow.push(a);a.suffixField&&this.appendField(a.suffixField);this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours_());return this};\nBlockly.Input.prototype.appendTitle=function(a,b){console.log(\"Deprecated call to appendTitle, use appendField instead.\");return this.appendField(a,b)};Blockly.Input.prototype.removeField=function(a){for(var b=0,c;c=this.fieldRow[b];b++)if(c.name===a){c.dispose();this.fieldRow.splice(b,1);this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours_());return}goog.asserts.fail('Field \"%s\" not found.',a)};Blockly.Input.prototype.isVisible=function(){return this.visible_};\nBlockly.Input.prototype.setVisible=function(a){var b=[];if(this.visible_==a)return b;for(var c=(this.visible_=a)?\"block\":\"none\",d=0,e;e=this.fieldRow[d];d++)e.setVisible(a);this.connection&&(b=a?this.connection.unhideAll():this.connection.hideAll(),d=this.connection.targetBlock())&&(d.svg_.getRootElement().style.display=c,a||(d.rendered=!1));return b};Blockly.Input.prototype.setCheck=function(a){if(!this.connection)throw\"This input does not have a connection.\";this.connection.setCheck(a);return this};\nBlockly.Input.prototype.setAlign=function(a){this.align=a;this.sourceBlock_.rendered&&this.sourceBlock_.render();return this};Blockly.Input.prototype.init=function(){for(var a=0;a<this.fieldRow.length;a++)this.fieldRow[a].init(this.sourceBlock_)};Blockly.Input.prototype.dispose=function(){for(var a=0,b;b=this.fieldRow[a];a++)b.dispose();this.connection&&this.connection.dispose();this.sourceBlock_=null};Blockly.Msg={};Blockly.Mutator=function(a){Blockly.Mutator.superClass_.constructor.call(this,null);this.quarkXml_=[];for(var b=0;b<a.length;b++){var c=goog.dom.createDom(\"block\",{type:a[b]});this.quarkXml_[b]=c}};goog.inherits(Blockly.Mutator,Blockly.Icon);Blockly.Mutator.prototype.workspaceWidth_=0;Blockly.Mutator.prototype.workspaceHeight_=0;\nBlockly.Mutator.prototype.createIcon=function(){Blockly.Icon.prototype.createIcon_.call(this);var a=Blockly.Icon.RADIUS/2;Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyIconShield\",width:4*a,height:4*a,rx:a,ry:a},this.iconGroup_);this.iconMark_=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyIconMark\",x:Blockly.Icon.RADIUS,y:2*Blockly.Icon.RADIUS-4},this.iconGroup_);this.iconMark_.appendChild(document.createTextNode(\"\\u2605\"))};\nBlockly.Mutator.prototype.iconClick_=function(a){this.block_.isEditable()&&Blockly.Icon.prototype.iconClick_.call(this,a)};\nBlockly.Mutator.prototype.createEditor_=function(){this.svgDialog_=Blockly.createSvgElement(\"svg\",{x:Blockly.Bubble.BORDER_WIDTH,y:Blockly.Bubble.BORDER_WIDTH},null);this.svgBackground_=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyMutatorBackground\",height:\"100%\",width:\"100%\"},this.svgDialog_);var a=this;this.workspace_=new Blockly.Workspace(function(){return a.getFlyoutMetrics_()},null);this.flyout_=new Blockly.Flyout;this.flyout_.autoClose=!1;this.svgDialog_.appendChild(this.flyout_.createDom());\nthis.svgDialog_.appendChild(this.workspace_.createDom());return this.svgDialog_};Blockly.Mutator.prototype.updateEditable=function(){this.block_.isEditable()?Blockly.Icon.prototype.updateEditable.call(this):(this.setVisible(!1),Blockly.removeClass_(this.iconGroup_,\"blocklyIconGroup\"))};\nBlockly.Mutator.prototype.resizeBubble_=function(){var a=2*Blockly.Bubble.BORDER_WIDTH,b=this.workspace_.getCanvas().getBBox(),c=this.flyout_.getMetrics_(),d;d=Blockly.RTL?-b.x:b.width+b.x;b=Math.max(b.height+3*a,c.contentHeight+20);d+=3*a;if(Math.abs(this.workspaceWidth_-d)>a||Math.abs(this.workspaceHeight_-b)>a)this.workspaceWidth_=d,this.workspaceHeight_=b,this.bubble_.setBubbleSize(d+a,b+a),this.svgDialog_.setAttribute(\"width\",this.workspaceWidth_),this.svgDialog_.setAttribute(\"height\",this.workspaceHeight_);\nBlockly.RTL&&(a=\"translate(\"+this.workspaceWidth_+\",0)\",this.workspace_.getCanvas().setAttribute(\"transform\",a))};\nBlockly.Mutator.prototype.setVisible=function(a){if(a!=this.isVisible())if(a){this.bubble_=new Blockly.Bubble(this.block_.workspace,this.createEditor_(),this.block_.svg_.svgGroup_,this.iconX_,this.iconY_,null,null);var b=this;this.flyout_.init(this.workspace_,!1);this.flyout_.show(this.quarkXml_);this.rootBlock_=this.block_.decompose(this.workspace_);a=this.rootBlock_.getDescendants();for(var c=0,d;d=a[c];c++)d.render();this.rootBlock_.setMovable(!1);this.rootBlock_.setDeletable(!1);a=2*this.flyout_.CORNER_RADIUS;\nc=this.flyout_.width_+a;Blockly.RTL&&(c=-c);this.rootBlock_.moveBy(c,a);this.block_.saveConnections&&(this.block_.saveConnections(this.rootBlock_),this.sourceListener_=Blockly.bindEvent_(this.block_.workspace.getCanvas(),\"blocklyWorkspaceChange\",this.block_,function(){b.block_.saveConnections(b.rootBlock_)}));this.resizeBubble_();Blockly.bindEvent_(this.workspace_.getCanvas(),\"blocklyWorkspaceChange\",this.block_,function(){b.workspaceChanged_()});this.updateColour()}else this.svgBackground_=this.svgDialog_=\nnull,this.flyout_.dispose(),this.flyout_=null,this.workspace_.dispose(),this.rootBlock_=this.workspace_=null,this.bubble_.dispose(),this.bubble_=null,this.workspaceHeight_=this.workspaceWidth_=0,this.sourceListener_&&(Blockly.unbindEvent_(this.sourceListener_),this.sourceListener_=null)};\nBlockly.Mutator.prototype.workspaceChanged_=function(){if(0==Blockly.Block.dragMode_)for(var a=this.workspace_.getTopBlocks(!1),b=0,c;c=a[b];b++){var d=c.getRelativeToSurfaceXY(),e=c.getHeightWidth();(Blockly.RTL?d.x>-this.flyout_.width_+20:d.x<this.flyout_.width_-20)?c.dispose(!1,!0):20>d.y+e.height&&c.moveBy(0,20-e.height-d.y)}this.rootBlock_.workspace==this.workspace_&&(a=this.block_.rendered,this.block_.rendered=!1,this.block_.compose(this.rootBlock_),this.block_.rendered=a,this.block_.rendered&&\nthis.block_.render(),this.resizeBubble_(),this.block_.workspace.fireChangeEvent())};Blockly.Mutator.prototype.getFlyoutMetrics_=function(){var a=0;Blockly.RTL&&(a+=this.workspaceWidth_);return{viewHeight:this.workspaceHeight_,viewWidth:0,absoluteTop:0,absoluteLeft:a}};Blockly.Mutator.prototype.dispose=function(){this.block_.mutator=null;Blockly.Icon.prototype.dispose.call(this)};Blockly.Warning=function(a){Blockly.Warning.superClass_.constructor.call(this,a);this.createIcon_()};goog.inherits(Blockly.Warning,Blockly.Icon);Blockly.Warning.prototype.text_=\"\";\nBlockly.Warning.prototype.createIcon_=function(){Blockly.Icon.prototype.createIcon_.call(this);Blockly.createSvgElement(\"path\",{\"class\":\"blocklyIconShield\",d:\"M 2,15 Q -1,15 0.5,12 L 6.5,1.7 Q 8,-1 9.5,1.7 L 15.5,12 Q 17,15 14,15 z\"},this.iconGroup_);this.iconMark_=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyIconMark\",x:Blockly.Icon.RADIUS,y:2*Blockly.Icon.RADIUS-3},this.iconGroup_);this.iconMark_.appendChild(document.createTextNode(\"!\"))};\nBlockly.Warning.prototype.textToDom_=function(a){var b=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyText\",y:Blockly.Bubble.BORDER_WIDTH},null);a=a.split(\"\\n\");for(var c=0;c<a.length;c++){var d=Blockly.createSvgElement(\"tspan\",{dy:\"1em\",x:Blockly.Bubble.BORDER_WIDTH},b),e=document.createTextNode(a[c]);d.appendChild(e)}return b};\nBlockly.Warning.prototype.setVisible=function(a){if(a!=this.isVisible())if(a){a=this.textToDom_(this.text_);this.bubble_=new Blockly.Bubble(this.block_.workspace,a,this.block_.svg_.svgGroup_,this.iconX_,this.iconY_,null,null);if(Blockly.RTL)for(var b=a.getBBox().width,c=0,d;d=a.childNodes[c];c++)d.setAttribute(\"text-anchor\",\"end\"),d.setAttribute(\"x\",b+Blockly.Bubble.BORDER_WIDTH);this.updateColour();a=this.bubble_.getBubbleSize();this.bubble_.setBubbleSize(a.width,a.height)}else this.bubble_.dispose(),\nthis.foreignObject_=this.body_=this.bubble_=null};Blockly.Warning.prototype.bodyFocus_=function(a){this.bubble_.promote_()};Blockly.Warning.prototype.setText=function(a){this.text_=a;this.isVisible()&&(this.setVisible(!1),this.setVisible(!0))};Blockly.Warning.prototype.dispose=function(){this.block_.warning=null;Blockly.Icon.prototype.dispose.call(this)};Blockly.uidCounter_=0;Blockly.getUidCounter=function(){return Blockly.uidCounter_};Blockly.setUidCounter=function(a){Blockly.uidCounter_=a};Blockly.Block=function(){goog.asserts.assert(0==arguments.length,\"Please use Blockly.Block.obtain.\")};Blockly.Block.obtain=function(a,b){if(Blockly.Realtime.isEnabled())return Blockly.Realtime.obtainBlock(a,b);var c=new Blockly.Block;c.initialize(a,b);return c};\nBlockly.Block.prototype.initialize=function(a,b){this.id=++Blockly.uidCounter_;a.addTopBlock(this);this.fill(a,b);goog.isFunction(this.onchange)&&Blockly.bindEvent_(a.getCanvas(),\"blocklyWorkspaceChange\",this,this.onchange)};\nBlockly.Block.prototype.fill=function(a,b){this.previousConnection=this.nextConnection=this.outputConnection=null;this.inputList=[];this.disabled=this.rendered=this.inputsInline=!1;this.tooltip=\"\";this.contextMenu=!0;this.parentBlock_=null;this.childBlocks_=[];this.editable_=this.addable_=this.movable_=this.deletable_=!0;this.collapsed_=!1;this.workspace=a;this.isInFlyout=a.isFlyout;if(b){this.type=b;var c=Blockly.Blocks[b];goog.asserts.assertObject(c,'Error: \"%s\" is an unknown language block.',b);\ngoog.mixin(this,c)}goog.isFunction(this.init)&&this.init();goog.isFunction(this.whenAdd)&&this.workspace==Blockly.mainWorkspace&&this.whenAdd()};Blockly.Block.getById=function(a,b){return Blockly.Realtime.isEnabled()?Blockly.Realtime.getBlockById(a):b.getBlockById(a)};Blockly.Block.prototype.svg_=null;Blockly.Block.prototype.mutator=null;Blockly.Block.prototype.comment=null;Blockly.Block.prototype.warning=null;\nBlockly.Block.prototype.getIcons=function(){var a=[];this.mutator&&a.push(this.mutator);this.comment&&a.push(this.comment);this.warning&&a.push(this.warning);return a};\nBlockly.Block.prototype.initSvg=function(){this.svg_=new Blockly.BlockSvg(this);this.svg_.init();Blockly.readOnly||(this.mouseDownWrapper_&&Blockly.unbindEvent_(this.mouseDownWrapper_),this.mouseDownWrapper_=Blockly.bindEvent_(this.svg_.getRootElement(),\"mousedown\",this,this.onMouseDown_),\"function_general\"===this.type&&(this.dblClickWrapper_&&Blockly.unbindEvent_(this.dblClickWrapper_),this.dblClickWrapper_=Blockly.bindEvent_(this.svg_.getRootElement(),\"dblclick\",this,this.onDblClick_)));Blockly.enableBlockAnimation&&\n(Blockly.bindEvent_(this.svg_.svgGroup_,\"mouseover\",this.svg_,this.svg_.toggleOnPattern),Blockly.bindEvent_(this.svg_.svgGroup_,\"mouseout\",this.svg_,this.svg_.toggleOffPattern));this.workspace.getCanvas().appendChild(this.svg_.getRootElement())};Blockly.Block.prototype.getSvgRoot=function(){return this.svg_&&this.svg_.getRootElement()};Blockly.Block.dragMode_=0;Blockly.Block.onMouseUpWrapper_=null;Blockly.Block.onMouseMoveWrapper_=null;\nBlockly.Block.terminateDrag_=function(){Blockly.Block.onMouseUpWrapper_&&(Blockly.unbindEvent_(Blockly.Block.onMouseUpWrapper_),Blockly.Block.onMouseUpWrapper_=null);Blockly.Block.onMouseMoveWrapper_&&(Blockly.unbindEvent_(Blockly.Block.onMouseMoveWrapper_),Blockly.Block.onMouseMoveWrapper_=null);var a=Blockly.selected;if(2==Blockly.Block.dragMode_&&a){var b=a.getRelativeToSurfaceXY();a.moveConnections_(b.x-a.startDragX,b.y-a.startDragY);delete a.draggedBubbles_;a.setDragging_(!1);a.render();goog.Timer.callOnce(a.bumpNeighbours_,\nBlockly.BUMP_DELAY,a);Blockly.fireUiEvent(window,\"resize\")}a&&a.workspace.fireChangeEvent();Blockly.Block.dragMode_=0};Blockly.Block.prototype.select=function(){goog.asserts.assertObject(this.svg_,\"Block is not rendered.\");Blockly.selected&&Blockly.selected.unselect();Blockly.selected=this;this.svg_.addSelect();Blockly.fireUiEvent(this.workspace.getCanvas(),\"blocklySelectChange\")};\nBlockly.Block.prototype.activate=function(){goog.asserts.assertObject(this.svg_,\"Block is not rendered.\");Blockly.selected&&Blockly.selected.unselect();Blockly.selected=this;this.svg_.addActive();Blockly.fireUiEvent(this.workspace.getCanvas(),\"blocklySelectChange\")};Blockly.Block.prototype.unselect=function(){goog.asserts.assertObject(this.svg_,\"Block is not rendered.\");Blockly.selected=null;this.svg_.removeSelect();Blockly.fireUiEvent(this.workspace.getCanvas(),\"blocklySelectChange\")};\nBlockly.Block.prototype.dispose=function(a,b,c){goog.isFunction(this.whenRemove)&&this.workspace==Blockly.mainWorkspace&&this.isDrag&&this.whenRemove(Blockly.Xml.blockToDom_(this));this.rendered=!1;this.unplug(a);b&&this.svg_&&this.svg_.disposeUiEffect();this.workspace&&!c&&(this.workspace.removeTopBlock(this),this.workspace=null);Blockly.selected==this&&(Blockly.selected=null,Blockly.terminateDrag_());for(a=this.childBlocks_.length-1;0<=a;a--)this.childBlocks_[a].dispose(!1);b=this.getIcons();for(a=\n0;a<b.length;a++)b[a].dispose();for(a=0;b=this.inputList[a];a++)b.dispose();this.inputList=[];b=this.getConnections_(!0);for(a=0;a<b.length;a++)c=b[a],c.targetConnection&&c.disconnect(),b[a].dispose();this.svg_&&(this.svg_.dispose(),this.svg_=null);Blockly.Realtime.isEnabled()&&!Blockly.Realtime.withinSync&&Blockly.Realtime.removeBlock(this)};\nBlockly.Block.prototype.unplug=function(a,b){b=b&&!!this.getParent();if(this.outputConnection)this.outputConnection.targetConnection&&this.setParent(null);else{var c=null;this.previousConnection&&this.previousConnection.targetConnection&&(c=this.previousConnection.targetConnection,this.setParent(null));if(a&&this.nextConnection&&this.nextConnection.targetConnection){var d=this.nextConnection.targetConnection;this.nextConnection.targetBlock().setParent(null);c&&c.connect(d)}}b&&this.moveBy(Blockly.SNAP_RADIUS*\n(Blockly.RTL?-1:1),2*Blockly.SNAP_RADIUS)};Blockly.Block.prototype.getRelativeToSurfaceXY=function(){var a=0,b=0;if(this.svg_){var c=this.svg_.getRootElement();do var d=Blockly.getRelativeXY_(c),a=a+d.x,b=b+d.y,c=c.parentNode;while(c&&c!=this.workspace.getCanvas())}return{x:a,y:b}};\nBlockly.Block.prototype.moveBy=function(a,b){var c=this.getRelativeToSurfaceXY();this.svg_.getRootElement().setAttribute(\"transform\",\"translate(\"+(c.x+a)+\", \"+(c.y+b)+\")\");this.moveConnections_(a,b);Blockly.Realtime.isEnabled()&&!Blockly.Realtime.withinSync&&Blockly.Realtime.blockChanged(this)};\nBlockly.Block.prototype.getHeightWidth=function(){try{var a=this.getSvgRoot().getBBox(),b=a.height}catch(c){return{height:0,width:0}}Blockly.BROKEN_CONTROL_POINTS&&(b-=10,this.nextConnection&&(b+=4),this.nextConnection||this.outputConnection||!this.previousConnection||(b+=4));return{height:b-1,width:a.width}};Blockly.Block.prototype.onDblClick_=function(a){Entry.Func.isEdit||(a=Entry.variableContainer.functions_)&&0!==a.length&&Entry.Func.edit(a[this.hashId])};\nBlockly.Block.prototype.onMouseDown_=function(a){Entry.documentMousedown&&Entry.documentMousedown.notify(a);if(this.isInFlyout)this.select();else{Blockly.svgResize();Blockly.terminateDrag_();this.select();Blockly.hideChaff();if(Blockly.isRightButton(a)){if(this.isInBlockMenu&&0==Blockly.Block.dragMode_){this.stalkerBlock&&this.stalkerBlock.dispose();this.dispose();return}this.isDrag=!0;Blockly.ContextMenu&&this.showContextMenu_(Blockly.mouseToSvg(a))}else if(Blockly.isMiddleButton(a)){if(this.isInBlockMenu&&\n0==Blockly.Block.dragMode_){this.stalkerBlock&&this.stalkerBlock.dispose();this.dispose();return}}else if(this.isMovable()){\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\");this.isDrag=!1;Blockly.removeAllRanges();Blockly.setCursorHand_(!0);var b=this.getRelativeToSurfaceXY();this.startDragX=b.x;this.startDragY=b.y;this.startDragMouseX=a.clientX;this.startDragMouseY=a.clientY;Blockly.Block.dragMode_=1;Blockly.Block.onMouseUpWrapper_=Blockly.bindEvent_(document,\"mouseup\",this,this.onMouseUp_);\nBlockly.Block.onMouseMoveWrapper_=Blockly.bindEvent_(document,\"mousemove\",this,this.onMouseMove_);this.draggedBubbles_=[];for(var b=this.getDescendants(),c=0,d;d=b[c];c++){d=d.getIcons();for(var e=0;e<d.length;e++){var f=d[e].getIconLocation();f.bubble=d[e];this.draggedBubbles_.push(f)}}}else return;a.stopPropagation()}};\nBlockly.Block.prototype.onMouseUp_=function(a){if(this.isInBlockMenu){this.isInBlockMenu=!1;if((a=Blockly.selected)&&a.willBeDeleted){this.stalkerBlock.dispose(!1,!1);a.dispose(!1,!0);Blockly.terminateDrag_();return}this.stalkerBlock.dispose(!1,!1);delete a.willBeDeleted;this.stalkerBlock=null}Blockly.terminateDrag_();Blockly.selected&&Blockly.highlightedConnection_?(Blockly.localConnection_.connect(Blockly.highlightedConnection_),this.svg_&&(Blockly.localConnection_.isSuperior()?Blockly.highlightedConnection_:\nBlockly.localConnection_).sourceBlock_.svg_.connectionUiEffect(),this.workspace.trashcan&&this.workspace.trashcan.isOpen&&this.workspace.trashcan.close(),\"object\"==typeof Entry&&this.getParent()===this.isDisconnected&&Entry.dispatchEvent(\"cancelLastCommand\")):this.workspace.trashcan&&this.workspace.trashcan.isOpen?(a=this.workspace.trashcan,goog.Timer.callOnce(a.close,100,a),Blockly.selected.dispose(!1,!0),Blockly.fireUiEvent(window,\"resize\")):this.isDisconnected||\"object\"==typeof Entry&&Entry.dispatchEvent(\"cancelLastCommand\");\n\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyMouseUp\");Blockly.highlightedConnection_&&(Blockly.highlightedConnection_.unhighlight(),Blockly.highlightedConnection_=null)};Blockly.Block.prototype.showHelp_=function(){var a=goog.isFunction(this.helpUrl)?this.helpUrl():this.helpUrl;a&&window.open(a)};\nBlockly.Block.prototype.duplicate_=function(){var a=Blockly.Xml.blockToDom_(this);\"object\"===typeof Entry?a=Entry.changeXmlHashId(a):\"object\"===typeof Ntry&&(a=Ntry.changeXmlHashId(a));var a=Blockly.Xml.domToBlock(this.workspace,a),b=this.getRelativeToSurfaceXY();b.x=Blockly.RTL?b.x-Blockly.SNAP_RADIUS:b.x+Blockly.SNAP_RADIUS;b.y+=2*Blockly.SNAP_RADIUS;a.moveBy(b.x,b.y);return a};\nBlockly.Block.prototype.showContextMenu_=function(a){if(!Blockly.readOnly&&this.contextMenu){var b=this,c=[];if(this.isDeletable()&&!b.isInFlyout){var d={text:Lang.Blocks.Duplication_option,enabled:!0,callback:function(){b.duplicate_();\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\")}};this.getDescendants().length>this.workspace.remainingCapacity()&&(d.enabled=!1);c.push(d);d={text:Lang.Blocks.CONTEXT_COPY_option,enabled:!0,callback:function(){Blockly.copy_(Blockly.selected)}};this.getDescendants().length>\nthis.workspace.remainingCapacity()&&(d.enabled=!1);c.push(d);d=this.getDescendants().length;b.nextConnection&&b.nextConnection.targetConnection&&(d-=this.nextConnection.targetBlock().getDescendants().length);d={text:1==d?Lang.Blocks.Delete_Blocks:Lang.Blocks.Delete_Blocks.replace(\"%1\",d),enabled:!0,callback:function(){b.dispose(!0,!0);\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\")}};c.push(d)}this.customContextMenu&&!b.isInFlyout&&this.customContextMenu(c);Blockly.ContextMenu.show(a,\nc)}};Blockly.Block.prototype.getConnections_=function(a){var b=[];if(a||this.rendered)if(this.outputConnection&&b.push(this.outputConnection),this.nextConnection&&b.push(this.nextConnection),this.previousConnection&&b.push(this.previousConnection),a||!this.collapsed_){a=0;for(var c;c=this.inputList[a];a++)c.connection&&b.push(c.connection)}return b};\nBlockly.Block.prototype.moveConnections_=function(a,b){if(this.rendered){for(var c=this.getConnections_(!1),d=0;d<c.length;d++)c[d].moveBy(a,b);c=this.getIcons();for(d=0;d<c.length;d++)c[d].computeIconLocation();for(d=0;d<this.childBlocks_.length;d++)this.childBlocks_[d].moveConnections_(a,b)}};Blockly.Block.prototype.setDragging_=function(a){a?this.svg_.addDragging():this.svg_.removeDragging();for(var b=0;b<this.childBlocks_.length;b++)this.childBlocks_[b].setDragging_(a)};\nBlockly.Block.prototype.onMouseMove_=function(a){Blockly.scrollBarOff=!1;this.isDrag=!0;this.stalkerBlock&&(this.stalkerBlock.isDrag=!0,this.stalkerBlock.g=!0);this.isEditing=!0;if(!(\"mousemove\"==a.type&&1>=a.clientX&&0==a.clientY&&0==a.button)){Blockly.removeAllRanges();var b=a.clientX-this.startDragMouseX,c=a.clientY-this.startDragMouseY;1==Blockly.Block.dragMode_&&Math.sqrt(Math.pow(b,2)+Math.pow(c,2))>Blockly.DRAG_RADIUS&&(Blockly.Block.dragMode_=2,this.isDisconnected=this.getParent(),this.setParent(null),\nthis.setDragging_(!0));if(2==Blockly.Block.dragMode_){var d=this.startDragX+b,e=this.startDragY+c;this.svg_.getRootElement().setAttribute(\"transform\",\"translate(\"+d+\", \"+e+\")\");this.stalkerBlock&&(this.willBeDeleted=!0,d=this.stalkerBlock.startDragX+b,e=this.stalkerBlock.startDragY+c,200-d<this.svg_.blockInlineWidth_/2&&(this.willBeDeleted=!1),this.stalkerBlock.svg_.getRootElement().setAttribute(\"transform\",\"translate(\"+d+\", \"+e+\")\"));for(d=0;d<this.draggedBubbles_.length;d++)e=this.draggedBubbles_[d],\ne.bubble.setIconLocation(e.x+b,e.y+c);for(var e=this.getConnections_(!1),f=null,g=null,h=Blockly.SNAP_RADIUS_ENTRY,d=0;d<e.length;d++){var k=e[d],n=k.closest(h,b,c);n.connection&&(f=n.connection,g=k,h=n.radius)}Blockly.highlightedConnection_&&Blockly.highlightedConnection_!=f&&(Blockly.highlightedConnection_.unhighlight(),Blockly.highlightedConnection_=null,Blockly.localConnection_=null);f&&f!=Blockly.highlightedConnection_&&(f.highlight(),Blockly.highlightedConnection_=f,Blockly.localConnection_=\ng);if(this.workspace.trashcan&&this.isDeletable())this.workspace.trashcan.onMouseMove(a)}delete this.isEditing}a.stopPropagation()};\nBlockly.Block.prototype.bumpNeighbours_=function(){if(0==Blockly.Block.dragMode_){var a=this.getRootBlock();if(!a.isInFlyout)for(var b=this.getConnections_(!1),c=0;c<b.length;c++){var d=b[c];d.targetConnection&&d.isSuperior()&&d.targetBlock().bumpNeighbours_();for(var e=d.neighbours_(Blockly.SNAP_RADIUS),f=0;f<e.length;f++){var g=e[f];d.targetConnection&&g.targetConnection||g.sourceBlock_.getRootBlock()!=a&&(d.isSuperior()?g.bumpAwayFrom_(d):d.bumpAwayFrom_(g))}}}};\nBlockly.Block.prototype.getParent=function(){return this.parentBlock_};Blockly.Block.prototype.getSurroundParent=function(){for(var a=this;;){do{var b=a,a=a.getParent();if(!a)return null}while(a.nextConnection&&a.nextConnection.targetBlock()==b);return a}};Blockly.Block.prototype.getRootBlock=function(){var a,b=this;do a=b,b=a.parentBlock_;while(b);return a};Blockly.Block.prototype.getChildren=function(){return this.childBlocks_};\nBlockly.Block.prototype.setParent=function(a){if(this.parentBlock_){for(var b=this.parentBlock_.childBlocks_,c,d=0;c=b[d];d++)if(c==this){b.splice(d,1);break}b=this.getRelativeToSurfaceXY();this.workspace.getCanvas().appendChild(this.getSvgRoot());this.svg_.getRootElement().setAttribute(\"transform\",\"translate(\"+b.x+\", \"+b.y+\")\");this.parentBlock_=null;this.previousConnection&&this.previousConnection.targetConnection&&this.previousConnection.disconnect();this.outputConnection&&this.outputConnection.targetConnection&&\nthis.outputConnection.disconnect()}else goog.array.contains(this.workspace.getTopBlocks(!1),this)&&this.workspace.removeTopBlock(this);(this.parentBlock_=a)?(a.childBlocks_.push(this),b=this.getRelativeToSurfaceXY(),a.svg_&&this.svg_&&a.svg_.getRootElement().insertBefore(this.svg_.getRootElement(),a.svg_.svgPath_),a=this.getRelativeToSurfaceXY(),this.moveConnections_(a.x-b.x,a.y-b.y)):this.workspace.addTopBlock(this)};\nBlockly.Block.prototype.getDescendants=function(){for(var a=[this],b,c=0;b=this.childBlocks_[c];c++)a=a.concat(b.getDescendants());return a};Blockly.Block.prototype.isDeletable=function(){return this.deletable_&&!Blockly.readOnly};Blockly.Block.prototype.setDeletable=function(a){this.deletable_=a;this.svg_&&this.svg_.updateMovable()};Blockly.Block.prototype.isMovable=function(){return this.movable_&&!Blockly.readOnly};Blockly.Block.prototype.setMovable=function(a){this.movable_=a};\nBlockly.Block.prototype.setAddable=function(a){this.addable_=a};Blockly.Block.prototype.isAddable=function(){return this.addable_&&!Blockly.readOnly};Blockly.Block.prototype.isEditable=function(){return this.editable_&&!Blockly.readOnly};Blockly.Block.prototype.setEditable=function(a){this.editable_=a;a=0;for(var b;b=this.inputList[a];a++)for(var c=0,d;d=b.fieldRow[c];c++)d.updateEditable();b=this.getIcons();for(a=0;a<b.length;a++)b[a].updateEditable()};\nBlockly.Block.prototype.setHelpUrl=function(a){this.helpUrl=a};Blockly.Block.prototype.getColour=function(){return this.colourHue_};Blockly.Block.prototype.setColour=function(a){this.colourHue_=a;this.svg_&&this.svg_.updateColour();var b=this.getIcons();for(a=0;a<b.length;a++)b[a].updateColour();if(this.rendered){for(a=0;b=this.inputList[a];a++)for(var c=0,d;d=b.fieldRow[c];c++)d.setText(null);this.render()}};\nBlockly.Block.prototype.getField_=function(a){for(var b=0,c;c=this.inputList[b];b++)for(var d=0,e;e=c.fieldRow[d];d++)if(e.name===a)return e;return null};Blockly.Block.prototype.getFieldValue=function(a){return(a=this.getField_(a))?a.getValue():null};Blockly.Block.prototype.getTitleValue=function(a){console.log(\"Deprecated call to getTitleValue, use getFieldValue instead.\");return this.getFieldValue(a)};\nBlockly.Block.prototype.setFieldValue=function(a,b){var c=this.getField_(b);goog.asserts.assertObject(c,'Field \"%s\" not found.',b);c.setValue(a)};Blockly.Block.prototype.setTitleValue=function(a,b){console.log(\"Deprecated call to setTitleValue, use setFieldValue instead.\");this.setFieldValue(a,b)};Blockly.Block.prototype.setTooltip=function(a){this.tooltip=a};\nBlockly.Block.prototype.setPreviousStatement=function(a,b){this.previousConnection&&(goog.asserts.assert(!this.previousConnection.targetConnection,\"Must disconnect previous statement before removing connection.\"),this.previousConnection.dispose(),this.previousConnection=null);a&&(goog.asserts.assert(!this.outputConnection,\"Remove output connection prior to adding previous connection.\"),void 0===b&&(b=null),this.previousConnection=new Blockly.Connection(this,Blockly.PREVIOUS_STATEMENT),this.previousConnection.setCheck(b));\nthis.rendered&&(this.render(),this.bumpNeighbours_())};Blockly.Block.prototype.setNextStatement=function(a,b){this.nextConnection&&(goog.asserts.assert(!this.nextConnection.targetConnection,\"Must disconnect next statement before removing connection.\"),this.nextConnection.dispose(),this.nextConnection=null);a&&(void 0===b&&(b=null),this.nextConnection=new Blockly.Connection(this,Blockly.NEXT_STATEMENT),this.nextConnection.setCheck(b));this.rendered&&(this.render(),this.bumpNeighbours_())};\nBlockly.Block.prototype.setOutput=function(a,b){this.outputConnection&&(goog.asserts.assert(!this.outputConnection.targetConnection,\"Must disconnect output value before removing connection.\"),this.outputConnection.dispose(),this.outputConnection=null);a&&(goog.asserts.assert(!this.previousConnection,\"Remove previous connection prior to adding output connection.\"),void 0===b&&(b=null),this.outputConnection=new Blockly.Connection(this,Blockly.OUTPUT_VALUE),this.outputConnection.setCheck(b));this.rendered&&\n(this.render(),this.bumpNeighbours_())};Blockly.Block.prototype.changeOutput=function(a){goog.asserts.assert(this.outputConnection,\"Only use changeOutput() on blocks that already have an output.\");this.outputConnection.setCheck(a)};Blockly.Block.prototype.setInputsInline=function(a){this.inputsInline=a;this.rendered&&(this.render(),this.bumpNeighbours_(),this.workspace.fireChangeEvent())};\nBlockly.Block.prototype.setDisabled=function(a){this.disabled!=a&&(this.disabled=a,this.svg_.updateDisabled(),this.workspace.fireChangeEvent())};Blockly.Block.prototype.getInheritedDisabled=function(){for(var a=this;;){a=a.getSurroundParent();if(!a)return!1;if(a.disabled)return!0}};Blockly.Block.prototype.isCollapsed=function(){return this.collapsed_};\nBlockly.Block.prototype.setCollapsed=function(a){if(this.collapsed_!=a){this.collapsed_=a;for(var b=[],c=0,d;d=this.inputList[c];c++)b=b.concat(d.setVisible(!a));if(a){a=this.getIcons();for(c=0;c<a.length;c++)a[c].setVisible(!1);c=this.toString(Blockly.COLLAPSE_CHARS);this.appendDummyInput(\"_TEMP_COLLAPSED_INPUT\").appendField(c)}else this.removeInput(\"_TEMP_COLLAPSED_INPUT\");b.length||(b[0]=this);if(this.rendered){for(c=0;a=b[c];c++)a.render();this.bumpNeighbours_()}}};\nBlockly.Block.prototype.toString=function(a){for(var b=[],c=0,d;d=this.inputList[c];c++){for(var e=0,f;f=d.fieldRow[e];e++)b.push(f.getText());d.connection&&((d=d.connection.targetBlock())?b.push(d.toString()):b.push(\"?\"))}b=goog.string.trim(b.join(\" \"))||\"???\";a&&(b=goog.string.truncate(b,a));return b};Blockly.Block.prototype.appendValueInput=function(a){return this.appendInput_(Blockly.INPUT_VALUE,a)};\nBlockly.Block.prototype.appendStatementInput=function(a){return this.appendInput_(Blockly.NEXT_STATEMENT,a)};Blockly.Block.prototype.appendDummyInput=function(a){return this.appendInput_(Blockly.DUMMY_INPUT,a||\"\")};\nBlockly.Block.prototype.interpolateMsg=function(a,b){function c(a){a instanceof Blockly.Field?this.appendField(a):(goog.asserts.assert(a instanceof Array),this.appendField(a[1],a[0]))}goog.asserts.assertString(a);var d=arguments[arguments.length-1];goog.asserts.assert(d===Blockly.ALIGN_LEFT||d===Blockly.ALIGN_CENTRE||d===Blockly.ALIGN_RIGHT,'Illegal final argument \"%d\" is not an alignment.',d);--arguments.length;for(var e=a.split(this.interpolateMsg.SPLIT_REGEX_),f=[],g=0;g<e.length;g+=2){var h=goog.string.trim(e[g]),\nk=void 0;h&&f.push(new Blockly.FieldLabel(h));if((h=e[g+1])&&\"%\"==h.charAt(0)){var n=parseInt(h.substring(1),10),p=arguments[n];goog.asserts.assertArray(p,'Message symbol \"%s\" is out of range.',h);goog.asserts.assertArray(p,'Argument \"%s\" is not a tuple.',h);p[1]instanceof Blockly.Field?f.push([p[0],p[1]]):k=this.appendValueInput(p[0]).setCheck(p[1]).setAlign(p[2]);arguments[n]=null}else\"\\n\"==h&&f.length&&(k=this.appendDummyInput());k&&f.length&&(f.forEach(c,k),f=[])}f.length&&(k=this.appendDummyInput().setAlign(d),\nf.forEach(c,k));for(g=1;g<arguments.length-1;g++)goog.asserts.assert(null===arguments[g],'Input \"%%s\" not used in message: \"%s\"',g,a);this.setInputsInline(!a.match(this.interpolateMsg.INLINE_REGEX_))};Blockly.Block.prototype.interpolateMsg.SPLIT_REGEX_=/(%\\d+|\\n)/;Blockly.Block.prototype.interpolateMsg.INLINE_REGEX_=/%1\\s*$/;\nBlockly.Block.prototype.appendInput_=function(a,b){var c=null;if(a==Blockly.INPUT_VALUE||a==Blockly.NEXT_STATEMENT)c=new Blockly.Connection(this,a);c=new Blockly.Input(a,b,this,c);this.inputList.push(c);this.rendered&&(this.render(),this.bumpNeighbours_());return c};\nBlockly.Block.prototype.moveInputBefore=function(a,b){if(a!=b){for(var c=-1,d=b?-1:this.inputList.length,e=0,f;f=this.inputList[e];e++)if(f.name==a){if(c=e,-1!=d)break}else if(b&&f.name==b&&(d=e,-1!=c))break;goog.asserts.assert(-1!=c,'Named input \"%s\" not found.',a);goog.asserts.assert(-1!=d,'Reference input \"%s\" not found.',b);this.moveNumberedInputBefore(c,d)}};\nBlockly.Block.prototype.moveNumberedInputBefore=function(a,b){goog.asserts.assert(a!=b,\"Can't move input to itself.\");goog.asserts.assert(a<this.inputList.length,\"Input index \"+a+\" out of bounds.\");goog.asserts.assert(b<=this.inputList.length,\"Reference input \"+b+\" out of bounds.\");var c=this.inputList[a];this.inputList.splice(a,1);a<b&&b--;this.inputList.splice(b,0,c);this.rendered&&(this.render(),this.bumpNeighbours_())};\nBlockly.Block.prototype.removeInput=function(a,b){for(var c=0,d;d=this.inputList[c];c++)if(d.name==a){d.connection&&d.connection.targetConnection&&d.connection.targetBlock().setParent(null);d.dispose();this.inputList.splice(c,1);this.rendered&&(this.render(),this.bumpNeighbours_());return}b||goog.asserts.fail('Input \"%s\" not found.',a)};Blockly.Block.prototype.getInput=function(a){for(var b=0,c;c=this.inputList[b];b++)if(c.name==a)return c;return null};\nBlockly.Block.prototype.getInputTargetBlock=function(a){return(a=this.getInput(a))&&a.connection&&a.connection.targetBlock()};Blockly.Block.prototype.setMutator=function(a){this.mutator&&this.mutator!==a&&this.mutator.dispose();a&&(a.block_=this,this.mutator=a,this.svg_&&a.createIcon())};Blockly.Block.prototype.getCommentText=function(){return this.comment?this.comment.getText().replace(/\\s+$/,\"\").replace(/ +\\n/g,\"\\n\"):\"\"};\nBlockly.Block.prototype.setCommentText=function(a){var b=!1;goog.isString(a)?(this.comment||(this.comment=new Blockly.Comment(this),b=!0),this.comment.setText(a)):this.comment&&(this.comment.dispose(),b=!0);this.rendered&&(this.render(),b&&this.bumpNeighbours_())};\nBlockly.Block.prototype.setWarningText=function(a){this.isInFlyout&&(a=null);var b=!1;goog.isString(a)?(this.warning||(this.warning=new Blockly.Warning(this),b=!0),this.warning.setText(a)):this.warning&&(this.warning.dispose(),b=!0);b&&this.rendered&&(this.render(),this.bumpNeighbours_())};\nBlockly.Block.prototype.render=function(){goog.asserts.assertObject(this.svg_,\"Uninitialized block cannot be rendered.  Call block.initSvg()\");this.svg_.render();Blockly.Realtime.isEnabled()&&!Blockly.Realtime.withinSync&&Blockly.Realtime.blockChanged(this)};Blockly.Block.prototype.setStalkerBlock=function(a){this.isInBlockMenu&&(this.stalkerBlock=a)};Blockly.BlockMenu=function(a){this.buttons_=[];this.splitters_=[];this.buttons_=[];this.listeners_=[];this.isCenterAlign=this.isViewOnly=!1;this.targetWorkspace=Blockly.mainWorkspace;this.bannedClass=[];this.view_=a;this.menuView_=Blockly.createSvgElement(\"svg\",{xmlns:\"http://www.w3.org/2000/svg\",\"xmlns:html\":\"http://www.w3.org/1999/xhtml\",\"xmlns:xlink\":\"http://www.w3.org/1999/xlink\",version:\"1.1\",\"class\":\"blocklySvg\"},this.view_);var b=this;this.workspace_=new Blockly.Workspace(function(){return b.getMetrics_()},\nfunction(a){return b.setMetrics_(a)});this.menuView_.appendChild(this.workspace_.createDom());this.scrollbar_=new Blockly.Scrollbar(this.workspace_,!1,!1);this.onResizeWrapper_=Blockly.bindEvent_(window,goog.events.EventType.RESIZE,this,this.syncViewSize_);Blockly.bindEvent_(window,\"resize\",this,this.updateSplitters);a=Blockly.BlockMenu.BTN_WIDTH;var c=Blockly.BlockMenu.BTN_HEIGHT,d=Blockly.BlockMenu.BTN_ROUND,e=[];e.push(\"m \"+d+\",0\");e.push(\"h\",a-2*d);e.push(\"a\",d+\",\"+d+\" 0, 0,1 \"+d+\",\"+d);e.push(\"v\",\nc-2*d);e.push(\"a\",d+\",\"+d+\" 0, 0,1 -\"+d+\",\"+d);e.push(\"h\",-a+2*d);e.push(\"a\",d+\",\"+d+\" 0, 0,1 -\"+d+\",-\"+d);e.push(\"v\",-c+2*d);e.push(\"a\",d+\",\"+d+\" 0, 0,1 \"+d+\",-\"+d);e.push(\"z\");this.btnPath=e.join(\" \")};Blockly.BlockMenu.BTN_HEIGHT=30;Blockly.BlockMenu.BTN_WIDTH=140;Blockly.BlockMenu.BTN_ROUND=6;Blockly.BlockMenu.BTN_FONT_SIZE=\"9pt\";\nBlockly.BlockMenu.prototype.show=function(a){this.hide();this.menuView_.style.display=\"block\";var b=[],c=[];if(a==Blockly.Variables.NAME_TYPE)Blockly.Variables.blockMenuCategory(b,c,0,this.workspace_);else if(a==Blockly.Procedures.NAME_TYPE)Blockly.Procedures.blockMenuCategory(b,c,0,this.workspace_);else for(var d=0,e;e=a[d];d++)e.tagName&&\"BLOCK\"==e.tagName.toUpperCase()?(e=Blockly.Xml.domToBlock(this.workspace_,e),e.isInFlyout=!0,b.push(e),c.push(0)):e.tagName&&\"SPLITTER\"==e.tagName.toUpperCase()?\n(b.push(\"splitter\"),c.push(0)):e.tagName&&\"BTN\"==e.tagName.toUpperCase()&&(b.push(e),c.push(0));a=10;for(d=0;e=b[d];d++)if(\"splitter\"==e)e=this.createSplitter(64,b[d-1].outputConnection?a:a+5,this.view_.style.width.substr(0,3)),this.workspace_.svgBlockCanvas_.appendChild(e),this.splitters_.push(e),a+=10;else if(e.tagName&&\"BTN\"==e.tagName.toUpperCase()){var f=Number(e.getAttribute(\"height\")),g=Blockly.createSvgElement(\"g\",{transform:\"translate(10, \"+a+\")\",\"class\":\"blocklyBlockMenuBtn\"},null);if(f)Blockly.createSvgElement(\"image\",\n{x:0,y:0,width:e.getAttribute(\"width\")+\"px\",height:f+\"px\"},g).setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",e.getAttribute(\"src\")),Blockly.createSvgElement(\"image\",{x:0,y:0,width:e.getAttribute(\"width\")+\"px\",height:f+\"px\",\"class\":\"blocklyBlockMenuBtnHighlight\"},g).setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",e.getAttribute(\"highlightSrc\")),a+=f+15;else{var h=e.getAttribute(\"text\"),k=Blockly.BlockMenu.BTN_WIDTH,f=Blockly.BlockMenu.BTN_HEIGHT;Blockly.createSvgElement(\"path\",\n{transform:\"translate(1,1)\",d:this.btnPath,fill:\"#aaa\"},g);Blockly.createSvgElement(\"path\",{d:this.btnPath,fill:\"#eee\",\"class\":\"blocklyBlockMenuBtnPath\"},g);k=Blockly.createSvgElement(\"text\",{x:k/2+\"px\",y:f/2+4+\"px\",\"font-family\":\"ng\",\"font-size\":Blockly.BlockMenu.BTN_FONT_SIZE,\"text-anchor\":\"middle\"},g);h=document.createTextNode(eval(h));k.appendChild(h);a+=f+13}(e=e.getAttribute(\"onclick\"))&&!this.isViewOnly&&(g.onclick=function(a){return function(){eval(a)}}(e));this.workspace_.svgBlockCanvas_.appendChild(g);\nthis.buttons_.push(g)}else{g=e.getDescendants();for(f=0;h=g[f];f++)h.isInFlyout=!0,Blockly.Comment&&h.setCommentText(null);e.render();g=e.getSvgRoot();f=e.getHeightWidth();h=10;if(this.isCenterAlign)h=200-f.width/2;else if(e.outputConnection){h+=f.height/2;k=e.type;if(\"get_variable\"==k||\"get_canvas_input_value\"==k||\"value_of_index_from_list\"==k||\"length_of_list\"==k)a+=12;\"PARAM\"==e.outputConnection.check_[0].toUpperCase()&&(h+=9,a+=4)}else!e.previousConnection&&e.nextConnection?(h+=10,a+=10):a+=7;\ne.moveBy(h,a);e.previousConnection||e.nextConnection||(a+=10);a+=f.height+c[d];e.isAddable()&&!this.isViewOnly&&this.listeners_.push(Blockly.bindEvent_(g,\"mousedown\",null,this.blockMouseDown_(e)))}this.width_=0;this.reflow();Blockly.fireUiEvent(window,\"resize\");this.reflowWrapper_=Blockly.bindEvent_(this.workspace_.getCanvas(),\"blocklyWorkspaceChange\",this,this.reflow);this.workspace_.fireChangeEvent();return a};Blockly.BlockMenu.prototype.banClass=function(a){0>this.bannedClass.indexOf(a)&&this.bannedClass.push(a)};\nBlockly.BlockMenu.prototype.unbanClass=function(a){a=this.bannedClass.indexOf(a);-1<a&&this.bannedClass.splice(a,1)};Blockly.BlockMenu.prototype.checkBanClass=function(a){a=a.isNotFor;for(var b in this.bannedClass)if(a&&-1<a.indexOf(this.bannedClass[b]))return!0;return!1};\nBlockly.BlockMenu.prototype.showCategory=function(a){this.hide();this.menuView_.style.display=\"block\";var b=[],c=a.blocks;a=[];var d=\"\",e;for(e in c){var f=EntryStatic.blockInfo[c[e]];if(!this.checkBanClass(f)){d&&d!=f[\"class\"]&&(b.push(\"splitter\"),a.push(0));var d=f.xml,g=f.xmls?f.xmls:[f.xml],h;for(h in g)d=g[h],d=jQuery.parseXML(d).childNodes[0],d.tagName&&\"BTN\"==d.tagName.toUpperCase()||(d=Blockly.Xml.domToBlock(this.workspace_,d),d.isInFlyout=!0),b.push(d),a.push(0);d=f[\"class\"]}}c=10;for(e=\n0;d=b[e];e++)if(\"splitter\"==d)d=this.createSplitter(64,b[e-1].outputConnection?c:c+5,this.view_.style.width.substr(0,3)),this.workspace_.svgBlockCanvas_.appendChild(d),this.splitters_.push(d),c+=10;else if(d.tagName&&\"BTN\"==d.tagName.toUpperCase()){f=Number(d.getAttribute(\"height\"));h=Blockly.createSvgElement(\"g\",{transform:\"translate(10, \"+c+\")\",\"class\":\"blocklyBlockMenuBtn\"},null);if(f)Blockly.createSvgElement(\"image\",{x:0,y:0,width:d.getAttribute(\"width\")+\"px\",height:f+\"px\"},h).setAttributeNS(\"http://www.w3.org/1999/xlink\",\n\"xlink:href\",d.getAttribute(\"src\")),Blockly.createSvgElement(\"image\",{x:0,y:0,width:d.getAttribute(\"width\")+\"px\",height:f+\"px\",\"class\":\"blocklyBlockMenuBtnHighlight\"},h).setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",d.getAttribute(\"highlightSrc\")),c+=f+10;else{var g=d.getAttribute(\"text\"),k=Blockly.BlockMenu.BTN_WIDTH,f=Blockly.BlockMenu.BTN_HEIGHT;Blockly.createSvgElement(\"path\",{transform:\"translate(1,1)\",d:this.btnPath,fill:\"#aaa\"},h);Blockly.createSvgElement(\"path\",{d:this.btnPath,\nfill:\"#eee\",\"class\":\"blocklyBlockMenuBtnPath\"},h);k=Blockly.createSvgElement(\"text\",{x:k/2+\"px\",y:f/2+4+\"px\",\"font-family\":\"ng\",\"font-size\":Blockly.BlockMenu.BTN_FONT_SIZE,\"text-anchor\":\"middle\"},h);g=document.createTextNode(eval(g));k.appendChild(g);c+=f+13}if(d=d.getAttribute(\"onclick\"))h.onclick=function(a){return function(){eval(a)}}(d);this.workspace_.svgBlockCanvas_.appendChild(h);this.buttons_.push(h)}else{f=d.getDescendants();for(h=0;g=f[h];h++)g.isInFlyout=!0,Blockly.Comment&&g.setCommentText(null);\nd.render();h=d.getSvgRoot();f=d.getHeightWidth();g=10;if(this.isCenterAlign)g=200-f.width/2;else if(d.outputConnection){g+=f.height/2;k=d.type;if(\"get_variable\"==k||\"get_canvas_input_value\"==k||\"value_of_index_from_list\"==k||\"length_of_list\"==k)c+=12;\"PARAM\"==d.outputConnection.check_[0].toUpperCase()&&(g+=9,c+=4)}else!d.previousConnection&&d.nextConnection?(g+=10,c+=10):c+=7;d.moveBy(g,c);d.previousConnection||d.nextConnection||(c+=10);c+=f.height+a[e];d.isAddable()&&!this.isViewOnly&&this.listeners_.push(Blockly.bindEvent_(h,\n\"mousedown\",null,this.blockMouseDown_(d)))}this.width_=0;this.reflow();Blockly.fireUiEvent(window,\"resize\");this.reflowWrapper_=Blockly.bindEvent_(this.workspace_.getCanvas(),\"blocklyWorkspaceChange\",this,this.reflow);this.workspace_.fireChangeEvent();return c};\nBlockly.BlockMenu.prototype.hide=function(){for(var a=0,b;b=this.listeners_[a];a++)Blockly.unbindEvent_(b);this.listeners_.splice(0);this.reflowWrapper_&&(Blockly.unbindEvent_(this.reflowWrapper_),this.reflowWrapper_=null);b=this.workspace_.getTopBlocks(!1);for(var a=0,c;c=b[a];a++)c.workspace==this.workspace_&&c.dispose(!1,!1);for(var d in this.splitters_)goog.dom.removeNode(this.splitters_[d]);this.splitters_=[];for(d in this.buttons_)goog.dom.removeNode(this.buttons_[d]);this.buttons_=[]};\nBlockly.BlockMenu.prototype.hide=function(){for(var a=0,b;b=this.listeners_[a];a++)Blockly.unbindEvent_(b);this.listeners_.splice(0);this.reflowWrapper_&&(Blockly.unbindEvent_(this.reflowWrapper_),this.reflowWrapper_=null);b=this.workspace_.getTopBlocks(!1);for(var a=0,c;c=b[a];a++)c.workspace==this.workspace_&&c.dispose(!1,!1);for(var d in this.splitters_)goog.dom.removeNode(this.splitters_[d]);this.splitters_=[];for(d in this.buttons_)goog.dom.removeNode(this.buttons_[d]);this.buttons_=[]};\nBlockly.BlockMenu.prototype.createSplitter=function(a,b,c){c=Number(c)-119;a=Blockly.createSvgElement(\"g\",{transform:\"translate(\"+(a-34)+\", \"+b+\")\"},null);Blockly.createSvgElement(\"path\",{stroke:\"#b5b5b5\",transform:\"translate(0, 1)\",d:\"M0 0 l\"+c+\" 0\"},a);return a};Blockly.BlockMenu.prototype.updateSplitters=function(){var a=Number(this.view_.style.width.substr(0,3))-119+64,b;for(b in this.splitters_)this.splitters_[b].childNodes[0].setAttribute(\"d\",\"M0 0 l\"+a+\" 0\")};\nBlockly.BlockMenu.prototype.blockMouseDown_=function(a){var b=this;return function(c){Blockly.terminateDrag_();Blockly.hideChaff();Blockly.isRightButton(c)?Blockly.ContextMenu&&a.showContextMenu_(Blockly.mouseToSvg(c)):(Blockly.removeAllRanges(),Blockly.setCursorHand_(!0),Blockly.BlockMenu.startDownEvent_=c,Blockly.BlockMenu.startBlock_=a,Blockly.BlockMenu.startblockMenu_=b,Blockly.BlockMenu.onMouseUpWrapper_=Blockly.bindEvent_(document,\"mouseup\",this,Blockly.terminateDrag_),Blockly.BlockMenu.onMouseMoveWrapper_=\nBlockly.bindEvent_(document,\"mousemove\",this,b.onMouseMove_));c.stopPropagation()}};Blockly.BlockMenu.prototype.onMouseMove_=function(a){\"mousemove\"==a.type&&1>=a.clientX&&0==a.clientY&&0==a.button?a.stopPropagation():(Blockly.removeAllRanges(),Math.sqrt(Math.pow(a.clientX-Blockly.BlockMenu.startDownEvent_.clientX,2)+Math.pow(a.clientY-Blockly.BlockMenu.startDownEvent_.clientY,2))>Blockly.DRAG_RADIUS&&Blockly.BlockMenu.startblockMenu_.createBlockFunc_(Blockly.BlockMenu.startBlock_)(Blockly.BlockMenu.startDownEvent_))};\nBlockly.BlockMenu.prototype.createBlockFunc_=function(a){var b=this;return function(c){Blockly.scrollBarOff=!0;if(!Blockly.isRightButton(c)&&!a.disabled){\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\");var d=Blockly.Xml.blockToDom_(a),e=Blockly.Xml.domToBlock(b.workspace_,d);e.isInBlockMenu=!0;var f=a.getSvgRoot();if(!f)throw\"originBlock is not rendered.\";var f=Blockly.getSvgXY_(f),g=e.getSvgRoot();if(!g)throw\"block is not rendered.\";g=Blockly.getSvgXY_(g);e.setDragging_(!0);e.svg_.addSelect();\ne.moveBy(f.x-g.x,f.y-g.y);e.startDragX=f.x-g.x;e.startDragY=f.y-g.y;d=Blockly.Xml.domToBlock(b.targetWorkspace,d);g=d.getSvgRoot();if(!g)throw\"block is not rendered.\";var g=Blockly.getSvgXY_(g),h=Blockly.mainWorkspace,k=$(h.svgGroup_.parentNode.parentNode).css(\"border-width\"),k=k.substring(0,k.length-2),n=$(h.blockMenu.view_).position(),h=$(h.svgGroup_.parentNode.parentNode).eq(0).position();d.moveBy(f.x-g.x-h.left+n.left,f.y-g.y+n.top-h.top-k);d.isInBlockMenu=!0;d.setStalkerBlock(e);e.setStalkerBlock(d);\nd.onMouseDown_(c)}}};\nBlockly.BlockMenu.prototype.reflow=function(){for(var a=0,b=this.CORNER_RADIUS,c=this.workspace_.getTopBlocks(!1),d=0,e;e=c[d];d++)e.getSvgRoot(),e=e.getHeightWidth(),a=Math.max(a,e.width);this.blockMenuWidth=a;a+=b+Blockly.BlockSvg.TAB_WIDTH+b/2+Blockly.Scrollbar.scrollbarThickness;if(this.width_!=a){for(d=0;e=c[d];d++){e.getHeightWidth();var f=e.getRelativeToSurfaceXY();if(Blockly.RTL){var g=a-b-Blockly.BlockSvg.TAB_WIDTH-f.x;e.moveBy(g,0);f.x+=g}}this.width_=a;Blockly.fireUiEvent(window,\"resize\")}};\nBlockly.BlockMenu.prototype.getMetrics_=function(){var a=this.view_.getBoundingClientRect();try{var b=this.workspace_.getCanvas().getBBox()}catch(c){b={height:0,y:0}}return{viewHeight:a.height,viewWidth:a.width,contentHeight:b.height+b.y,viewTop:-this.workspace_.scrollY,contentTop:0,absoluteTop:0,absoluteLeft:0}};\nBlockly.BlockMenu.prototype.setMetrics_=function(a){var b=this.getMetrics_();b&&(goog.isNumber(a.y)&&(this.workspace_.scrollY=-b.contentHeight*a.y-b.contentTop),a=this.workspace_.scrollY+b.absoluteTop,this.workspace_.getCanvas().setAttribute(\"transform\",\"translate(0,\"+a+\")\"))};\nBlockly.BlockMenu.terminateDrag_=function(){Blockly.BlockMenu.onMouseUpWrapper_&&(Blockly.unbindEvent_(Blockly.BlockMenu.onMouseUpWrapper_),Blockly.BlockMenu.onMouseUpWrapper_=null);Blockly.BlockMenu.onMouseMoveWrapper_&&(Blockly.unbindEvent_(Blockly.BlockMenu.onMouseMoveWrapper_),Blockly.BlockMenu.onMouseMoveWrapper_=null);Blockly.BlockMenu.startDownEvent_=null;Blockly.BlockMenu.startBlock_=null;Blockly.BlockMenu.startFlyout_=null};\nBlockly.BlockMenu.prototype.syncViewSize_=function(){var a=this.view_.getBoundingClientRect();this.menuView_.style.width=a.width+\"px\";this.menuView_.style.height=a.height+\"px\";this.scrollbar_.resize()};Blockly.FieldIcon=function(a,b,c){this.sourceBlock_=null;this.type=c?c:\"endOrigin\";\"end\"==this.type?(this.height_=Number(24),this.width_=Number(24),this.iconSize=.7):\"endOrigin\"==this.type?(this.height_=Number(24),this.width_=Number(24)):\"start\"==this.type&&(this.height_=Number(34),this.width_=Number(34));this.size_={height:this.height_,width:this.width_};this.text_=b||\"\";\"end\"==this.type?(this.fieldGroup_=Blockly.createSvgElement(\"g\",{},null),this.circleElement_=Blockly.createSvgElement(\"circle\",\n{cx:this.width_/2,cy:this.height_/2,r:this.width_/2,y:0},this.fieldGroup_),this.imageElement_=Blockly.createSvgElement(\"image\",{height:this.height_*this.iconSize+\"px\",width:this.width_*this.iconSize+\"px\",x:this.width_*(1-this.iconSize)/2,y:this.height_*(1-this.iconSize)/2},this.fieldGroup_),this.setValue(a)):\"endOrigin\"==this.type?(this.fieldGroup_=Blockly.createSvgElement(\"g\",{},null),this.imageElement_=Blockly.createSvgElement(\"image\",{height:this.height_+\"px\",width:this.width_+\"px\",x:0,y:0},this.fieldGroup_),\nthis.setValue(a)):\"start\"==this.type&&(this.fieldGroup_=Blockly.createSvgElement(\"g\",{},null),this.imageElement_=Blockly.createSvgElement(\"image\",{height:this.height_+\"px\",width:this.width_+\"px\",x:0,y:-2},this.fieldGroup_),this.setValue(a));goog.userAgent.GECKO&&(this.rectElement_=Blockly.createSvgElement(\"rect\",{height:this.height_+\"px\",width:this.width_+\"px\",y:0,\"fill-opacity\":0},this.fieldGroup_))};goog.inherits(Blockly.FieldIcon,Blockly.Field);\nBlockly.FieldIcon.prototype.clone=function(){return new Blockly.FieldIcon(this.getSrc(),this.width_,this.height_,this.getText())};Blockly.FieldIcon.prototype.rectElement_=null;Blockly.FieldIcon.prototype.EDITABLE=!1;\nBlockly.FieldIcon.prototype.init=function(a){if(this.sourceBlock_)throw\"Image has already been initialized once.\";this.sourceBlock_=a;a.getSvgRoot().appendChild(this.fieldGroup_);if(this.type&&\"end\"!=this.type)\"endOrigin\"==this.type?(b=this.imageElement_,b.tooltip=this.sourceBlock_):\"start\"==this.type&&(b=this.imageElement_,b.tooltip=this.sourceBlock_);else{var b=this.rectElement_||this.imageElement_;b.tooltip=this.sourceBlock_;a=goog.color.hexToRgb(a.getColour());a=goog.color.darken(a,.2);a=goog.color.rgbToHex(a[0],\na[1],a[2]);this.circleElement_.style.fill=a}Blockly.Tooltip&&Blockly.Tooltip.bindMouseEvents(b)};Blockly.FieldIcon.prototype.dispose=function(){goog.dom.removeNode(this.fieldGroup_);this.rectElement_=this.imageElement_=this.fieldGroup_=null};Blockly.FieldIcon.prototype.setTooltip=function(a){(this.rectElement_||this.imageElement_).tooltip=a};Blockly.FieldIcon.prototype.getValue=function(){return this.src_};\nBlockly.FieldIcon.prototype.setValue=function(a){null!==a&&(this.src_=a,this.imageElement_.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",goog.isString(a)?a:\"\"))};Blockly.FieldIcon.prototype.setText=function(a){null!==a&&(this.text_=a)};Blockly.FieldTextInput=function(a,b){Blockly.FieldTextInput.superClass_.constructor.call(this,a);this.changeHandler_=b;this.isTextInput=!0};goog.inherits(Blockly.FieldTextInput,Blockly.Field);Blockly.FieldTextInput.prototype.clone=function(){return new Blockly.FieldTextInput(this.getText(),this.changeHandler_)};Blockly.FieldTextInput.prototype.CURSOR=\"text\";Blockly.FieldTextInput.prototype.dispose=function(){Blockly.WidgetDiv.hideIfField(this);Blockly.FieldTextInput.superClass_.dispose.call(this)};\nBlockly.FieldTextInput.prototype.setText=function(a){if(null!==a){if(this.changeHandler_){var b=this.changeHandler_(a);null!==b&&void 0!==b&&(a=b)}Blockly.Field.prototype.setText.call(this,a,!0)}};\nBlockly.FieldTextInput.prototype.showEditor_=function(){if(goog.userAgent.MOBILE){var a=window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE,this.text_);if(this.changeHandler_){var b=this.changeHandler_(a);void 0!==b&&(a=b)}null!==a&&this.setText(a)}else Blockly.WidgetDiv.show(this,this.dispose_()),b=Blockly.WidgetDiv.DIV,a=goog.dom.createDom(\"input\",\"blocklyHtmlInput\"),Blockly.FieldTextInput.htmlInput_=a,b.appendChild(a),a.value=a.defaultValue=this.text_,a.oldValue_=null,this.validate_(),this.resizeEditor_(),\na.focus(),a.select(),a.onKeyUpWrapper_=Blockly.bindEvent_(a,\"keyup\",this,this.onHtmlInputChange_),a.onKeyPressWrapper_=Blockly.bindEvent_(a,\"keypress\",this,this.onHtmlInputChange_),a.onBlurWrapper_=Blockly.bindEvent_(a,\"blur\",this,Blockly.WidgetDiv.hide),b=this.sourceBlock_.workspace.getCanvas(),a.onWorkspaceChangeWrapper_=Blockly.bindEvent_(b,\"blocklyWorkspaceChange\",this,this.resizeEditor_)};\nBlockly.FieldTextInput.prototype.onHtmlInputChange_=function(a){var b=Blockly.FieldTextInput.htmlInput_;13==a.keyCode?Blockly.WidgetDiv.hide():27==a.keyCode?(this.setText(b.defaultValue),Blockly.WidgetDiv.hide()):(a=b.value,a!==b.oldValue_?(b.oldValue_=a,this.setText(a),this.validate_()):goog.userAgent.WEBKIT&&this.sourceBlock_.render())};\nBlockly.FieldTextInput.prototype.validate_=function(){var a=!0;goog.asserts.assertObject(Blockly.FieldTextInput.htmlInput_);var b=Blockly.FieldTextInput.htmlInput_;this.changeHandler_&&(a=this.changeHandler_(b.value));null===a?Blockly.addClass_(b,\"blocklyInvalidInput\"):Blockly.removeClass_(b,\"blocklyInvalidInput\")};\nBlockly.FieldTextInput.prototype.resizeEditor_=function(){var a=Blockly.WidgetDiv.DIV,b=this.fieldGroup_.getBBox();a.style.width=b.width+\"px\";b=Blockly.getAbsoluteXY_(this.borderRect_,this.sourceBlock_.workspace.svgGroup_.parentNode);if(Blockly.RTL){var c=this.borderRect_.getBBox();b.x+=c.width;b.x-=a.offsetWidth}b.y+=1;goog.userAgent.WEBKIT&&(b.y-=3);a.style.left=b.x+\"px\";a.style.top=b.y+\"px\"};\nBlockly.FieldTextInput.prototype.dispose_=function(){var a=this;return function(){var b=Blockly.FieldTextInput.htmlInput_,c;c=b.value;a.changeHandler_&&(c=a.changeHandler_(c),null===c&&(c=b.defaultValue));a.setText(c);a.sourceBlock_.render();Blockly.unbindEvent_(b.onKeyUpWrapper_);Blockly.unbindEvent_(b.onKeyPressWrapper_);Blockly.unbindEvent_(b.onWorkspaceChangeWrapper_);Blockly.FieldTextInput.htmlInput_=null}};\nBlockly.FieldTextInput.numberValidator=function(a){a=a.replace(/O/ig,\"0\");a=a.replace(/,/g,\"\");a=parseFloat(a||0);return isNaN(a)?null:String(a)};Blockly.FieldTextInput.nonnegativeIntegerValidator=function(a){(a=Blockly.FieldTextInput.numberValidator(a))&&(a=String(Math.max(0,Math.floor(a))));return a};Blockly.FieldAngle=function(a,b){var c;if(b){var d=this;c=function(a){a=Blockly.FieldAngle.angleValidator.call(d,a);null!==a&&b.call(d,a);return a}}else c=Blockly.FieldAngle.angleValidator;this.symbol_=Blockly.createSvgElement(\"tspan\",{},null);this.symbol_.appendChild(document.createTextNode(\"\\u00b0\"));Blockly.FieldAngle.superClass_.constructor.call(this,a,c);this.borderRect_.setAttribute(\"x\",-Blockly.BlockSvg.SEP_SPACE_X/2)};goog.inherits(Blockly.FieldAngle,Blockly.FieldTextInput);\nBlockly.FieldAngle.prototype.clone=function(){return new Blockly.FieldAngle(this.getText(),this.changeHandler_)};Blockly.FieldAngle.ROUND=15;Blockly.FieldAngle.HALF=50;Blockly.FieldAngle.RADIUS=Blockly.FieldAngle.HALF-1;Blockly.FieldAngle.prototype.dispose_=function(){var a=this;return function(){Blockly.FieldAngle.superClass_.dispose_.call(a)();a.gauge_=null;a.clickWrapper_&&Blockly.unbindEvent_(a.clickWrapper_);a.moveWrapper1_&&Blockly.unbindEvent_(a.moveWrapper1_);a.moveWrapper2_&&Blockly.unbindEvent_(a.moveWrapper2_)}};\nBlockly.FieldAngle.prototype.showEditor_=function(){Blockly.FieldAngle.superClass_.showEditor_.call(this);var a=Blockly.WidgetDiv.DIV;if(a.firstChild){var a=Blockly.createSvgElement(\"svg\",{xmlns:\"http://www.w3.org/2000/svg\",\"xmlns:html\":\"http://www.w3.org/1999/xhtml\",\"xmlns:xlink\":\"http://www.w3.org/1999/xlink\",version:\"1.1\",height:2*Blockly.FieldAngle.HALF+\"px\",width:2*Blockly.FieldAngle.HALF+\"px\"},a),b=Blockly.createSvgElement(\"circle\",{cx:Blockly.FieldAngle.HALF,cy:Blockly.FieldAngle.HALF,r:Blockly.FieldAngle.RADIUS,\n\"class\":\"blocklyAngleCircle\"},a);this.gauge_=Blockly.createSvgElement(\"path\",{\"class\":\"blocklyAngleGauge\"},a);this.line_=Blockly.createSvgElement(\"line\",{x1:Blockly.FieldAngle.HALF,y1:Blockly.FieldAngle.HALF,\"class\":\"blocklyAngleLine\"},a);for(var c=0;360>c;c+=15)Blockly.createSvgElement(\"line\",{x1:Blockly.FieldAngle.HALF+Blockly.FieldAngle.RADIUS,y1:Blockly.FieldAngle.HALF,x2:Blockly.FieldAngle.HALF+Blockly.FieldAngle.RADIUS-(0==c%45?10:5),y2:Blockly.FieldAngle.HALF,\"class\":\"blocklyAngleMarks\",transform:\"rotate(\"+\nc+\", \"+Blockly.FieldAngle.HALF+\", \"+Blockly.FieldAngle.HALF+\")\"},a);a.style.marginLeft=\"-35px\";this.clickWrapper_=Blockly.bindEvent_(a,\"click\",this,Blockly.WidgetDiv.hide);this.moveWrapper1_=Blockly.bindEvent_(b,\"mousemove\",this,this.onMouseMove);this.moveWrapper2_=Blockly.bindEvent_(this.gauge_,\"mousemove\",this,this.onMouseMove);this.updateGraph()}};\nBlockly.FieldAngle.prototype.onMouseMove=function(a){var b=this.gauge_.ownerSVGElement.getBoundingClientRect(),c=a.clientX-b.left-Blockly.FieldAngle.HALF;a=a.clientY-b.top-Blockly.FieldAngle.HALF;b=Math.atan(-a/c);isNaN(b)||(b=b/Math.PI*180,b=90-b,0>c?b+=180:0<a&&(b+=360),Blockly.FieldAngle.ROUND&&(b=Math.round(b/Blockly.FieldAngle.ROUND)*Blockly.FieldAngle.ROUND),360<=b&&(b-=360),b=String(b),Blockly.FieldTextInput.htmlInput_.value=b,this.setText(b))};\nBlockly.FieldAngle.prototype.setText=function(a){Blockly.FieldAngle.superClass_.setText.call(this,a);this.updateGraph();Blockly.RTL?this.textElement_.insertBefore(this.symbol_,this.textElement_.firstChild):this.textElement_.appendChild(this.symbol_);this.size_.width=0};\nBlockly.FieldAngle.prototype.updateGraph=function(){if(this.gauge_){var a=Number(this.getText())/180*Math.PI;if(isNaN(a))this.gauge_.setAttribute(\"d\",\"M \"+Blockly.FieldAngle.HALF+\", \"+Blockly.FieldAngle.HALF),this.line_.setAttribute(\"x2\",Blockly.FieldAngle.HALF),this.line_.setAttribute(\"y2\",Blockly.FieldAngle.HALF);else{var b=Blockly.FieldAngle.HALF+Math.sin(a)*Blockly.FieldAngle.RADIUS,c=Blockly.FieldAngle.HALF+Math.cos(a)*-Blockly.FieldAngle.RADIUS;this.gauge_.setAttribute(\"d\",\"M \"+Blockly.FieldAngle.HALF+\n\", \"+Blockly.FieldAngle.HALF+\" v -\"+Blockly.FieldAngle.RADIUS+\" A \"+Blockly.FieldAngle.RADIUS+\",\"+Blockly.FieldAngle.RADIUS+\" 0 \"+(a>Math.PI?1:0)+\" 1 \"+b+\",\"+c+\" z\");this.line_.setAttribute(\"x2\",b);this.line_.setAttribute(\"y2\",c)}}};Blockly.FieldAngle.angleValidator=function(a){a=Blockly.FieldTextInput.numberValidator(a);null!==a&&(a=String(a));return a};Blockly.FieldCheckbox=function(a,b){Blockly.FieldCheckbox.superClass_.constructor.call(this,\"\");this.changeHandler_=b;this.checkElement_=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyText\",x:-3},this.fieldGroup_);var c=document.createTextNode(\"\\u2713\");this.checkElement_.appendChild(c);this.setValue(a)};goog.inherits(Blockly.FieldCheckbox,Blockly.Field);Blockly.FieldCheckbox.prototype.clone=function(){return new Blockly.FieldCheckbox(this.getValue(),this.changeHandler_)};\nBlockly.FieldCheckbox.prototype.CURSOR=\"default\";Blockly.FieldCheckbox.prototype.getValue=function(){return String(this.state_).toUpperCase()};Blockly.FieldCheckbox.prototype.setValue=function(a){a=\"TRUE\"==a;this.state_!==a&&(this.state_=a,this.checkElement_.style.display=a?\"block\":\"none\",this.sourceBlock_&&this.sourceBlock_.rendered&&this.sourceBlock_.workspace.fireChangeEvent())};\nBlockly.FieldCheckbox.prototype.showEditor_=function(){var a=!this.state_;if(this.changeHandler_){var b=this.changeHandler_(a);void 0!==b&&(a=b)}null!==a&&this.setValue(String(a).toUpperCase())};Blockly.FieldColour=function(a,b){Blockly.FieldColour.superClass_.constructor.call(this,\"\\u00a0\\u00a0\\u00a0\");this.changeHandler_=b;this.borderRect_.style.fillOpacity=1;this.setValue(a)};goog.inherits(Blockly.FieldColour,Blockly.Field);Blockly.FieldColour.prototype.clone=function(){return new Blockly.FieldColour(this.getValue(),this.changeHandler_)};Blockly.FieldColour.prototype.CURSOR=\"default\";Blockly.FieldColour.prototype.dispose=function(){Blockly.WidgetDiv.hideIfField(this);Blockly.FieldColour.superClass_.dispose.call(this)};\nBlockly.FieldColour.prototype.getValue=function(){return this.colour_};Blockly.FieldColour.prototype.setValue=function(a){this.colour_=a;this.borderRect_.style.fill=a;this.sourceBlock_&&this.sourceBlock_.rendered&&this.sourceBlock_.workspace.fireChangeEvent()};Blockly.FieldColour.COLOURS=goog.ui.ColorPicker.SIMPLE_GRID_COLORS;Blockly.FieldColour.COLUMNS=7;\nBlockly.FieldColour.prototype.showEditor_=function(){Blockly.WidgetDiv.show(this,Blockly.FieldColour.dispose_);var a=Blockly.WidgetDiv.DIV,b=new goog.ui.ColorPicker;b.setSize(Blockly.FieldColour.COLUMNS);b.setColors(Blockly.FieldColour.COLOURS);b.render(a);b.setSelectedColor(this.getValue());var c=Blockly.getAbsoluteXY_(this.borderRect_),d=this.borderRect_.getBBox();Blockly.RTL&&(c.x+=d.width);c.y+=d.height-1;Blockly.RTL&&(c.x-=a.offsetWidth);a.style.left=c.x+\"px\";a.style.top=c.y+\"px\";var e=this;\nBlockly.FieldColour.changeEventKey_=goog.events.listen(b,goog.ui.ColorPicker.EventType.CHANGE,function(a){a=a.target.getSelectedColor()||\"#000000\";Blockly.WidgetDiv.hide();if(e.changeHandler_){var b=e.changeHandler_(a);void 0!==b&&(a=b)}null!==a&&(\"object\"==typeof Entry&&e.getValue()!=a&&Entry.dispatchEvent(\"entryBlocklyChanged\"),e.setValue(a))})};Blockly.FieldColour.dispose_=function(){Blockly.FieldColour.changeEventKey_&&goog.events.unlistenByKey(Blockly.FieldColour.changeEventKey_)};Blockly.FieldDropdown=function(a,b,c,d){this.menuGenerator_=a;this.changeHandler_=b;this.trimOptions_();a=this.getOptions_()[0];this.value_=a[1];this.arrow_=Blockly.createSvgElement(\"tspan\",{},null);d&&(this.arrowColor_=d);0!=c&&this.arrow_.appendChild(document.createTextNode(Blockly.RTL?\"\\u25be \":\" \\u25be\"));Blockly.FieldDropdown.superClass_.constructor.call(this,a[0])};goog.inherits(Blockly.FieldDropdown,Blockly.Field);\nBlockly.FieldDropdown.prototype.clone=function(){return new Blockly.FieldDropdown(this.menuGenerator_,this.changeHandler_)};\nBlockly.FieldDropdown.createDom=function(){var a=\"/legacy_media/scroll_up.png\",b=\"/legacy_media/scroll_down.png\";Blockly.FieldDropdown.currentPosition=0;var c=Blockly.createSvgElement(\"svg\",{xmlns:\"http://www.w3.org/2000/svg\",version:\"1.1\",height:\"200\"},null);Blockly.FieldDropdown.svgWrapper_=c;var d=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyHidden blocklyFieldDropdown\"},c);Blockly.FieldDropdown.svgGroup_=d;Blockly.FieldDropdown.svgShadow_=Blockly.createSvgElement(\"rect\",\n{\"class\":\"blocklyDropdownMenuShadow\",x:0,y:1},d);Blockly.FieldDropdown.svgBackground_=Blockly.createSvgElement(\"rect\",{x:-2,y:-1,filter:\"url(#blocklyEmboss)\"},d);Blockly.FieldDropdown.svgOptions_=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyDropdownMenuOptions\"},d);Blockly.FieldDropdown.scrollbarWrapper_=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyDropdownScollWrapper blocklyHidden\"},c);Blockly.FieldDropdown.scrollbarUpWrapper_=Blockly.createSvgElement(\"g\",{transform:\"translate(0 0)\",cursor:\"pointer\"},\nBlockly.FieldDropdown.scrollbarWrapper_);Blockly.createSvgElement(\"rect\",{width:\"15\",height:\"40\",fill:\"none\",stroke:\"none\"},Blockly.FieldDropdown.scrollbarUpWrapper_);d=Blockly.createSvgElement(\"image\",{width:\"10\",height:\"40\",x:\"5\",opacity:\"0.5\"},Blockly.FieldDropdown.scrollbarUpWrapper_);d.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",a);Blockly.FieldDropdown.scrollbarDownWrapper_=Blockly.createSvgElement(\"g\",{transform:\"translate(0 160)\",cursor:\"pointer\"},Blockly.FieldDropdown.scrollbarWrapper_);\nBlockly.createSvgElement(\"rect\",{width:\"15\",height:\"40\",fill:\"none\",stroke:\"none\"},Blockly.FieldDropdown.scrollbarDownWrapper_);d=Blockly.createSvgElement(\"image\",{width:\"10\",height:\"40\",x:\"5\",opacity:\"0.5\"},Blockly.FieldDropdown.scrollbarDownWrapper_);d.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",b);return c};\nBlockly.FieldDropdown.moveUp=function(a){0!=Blockly.FieldDropdown.currentPosition&&(Blockly.FieldDropdown.currentPosition--,Blockly.FieldDropdown.moveScroll(Blockly.FieldDropdown.currentPosition),Blockly.FieldDropdown.timer=window.setTimeout(function(){Blockly.FieldDropdown.moveUp()},100))};Blockly.FieldDropdown.mouseLeave=function(a){Blockly.FieldDropdown.timer&&(window.clearInterval(Blockly.FieldDropdown.timer),Blockly.FieldDropdown.timer=null)};\nBlockly.FieldDropdown.moveDown=function(a){this.getOptions_&&(Blockly.FieldDropdown.optionLength=this.getOptions_().length);Blockly.FieldDropdown.currentPosition+10!=Blockly.FieldDropdown.optionLength&&(Blockly.FieldDropdown.currentPosition++,Blockly.FieldDropdown.moveScroll(Blockly.FieldDropdown.currentPosition),Blockly.FieldDropdown.timer=window.setTimeout(function(){Blockly.FieldDropdown.moveDown()},100))};\nBlockly.FieldDropdown.onMouseWheel=function(a){a.stopPropagation();a.preventDefault();Blockly.removeAllRanges();var b=Blockly.FieldDropdown.scrollbarWrapper_,c=this.getOptions_();10>=c.length?Blockly.addClass_(b,\"blocklyHidden\"):(a=a.wheelDeltaY||-a.deltaY,Blockly.removeClass_(b,\"blocklyHidden\"),b=Blockly.FieldDropdown.currentPosition,0==b&&0<a||b==c.length-10&&0>a||(0>a?Blockly.FieldDropdown.currentPosition++:Blockly.FieldDropdown.currentPosition--,Blockly.FieldDropdown.moveScroll(Blockly.FieldDropdown.currentPosition)))};\nBlockly.FieldDropdown.moveScroll=function(a){Blockly.FieldDropdown.svgGroup_.setAttribute(\"transform\",\"translate(0 \"+-20*a+\")\")};Blockly.FieldDropdown.prototype.dispose=function(){Blockly.FieldDropdown.openDropdown_==this&&Blockly.FieldDropdown.hide();Blockly.Field.prototype.dispose.call(this)};Blockly.FieldDropdown.CORNER_RADIUS=2;Blockly.FieldDropdown.prototype.CURSOR=\"default\";Blockly.FieldDropdown.openDropdown_=null;\nBlockly.FieldDropdown.prototype.showEditor_=function(){function a(a){return function(b){if(this.changeHandler_){var c=this.changeHandler_(a);void 0!==c&&(a=c)}null!==a&&(\"object\"==typeof Entry&&this.getValue()!=a&&Entry.dispatchEvent(\"entryBlocklyChanged\"),this.setValue(a));b.stopPropagation()}}if(Blockly.FieldDropdown.workspace!==this.sourceBlock_.workspace){goog.dom.removeChildren(Blockly.FieldDropdown.svgWrapper_);var b=Blockly.FieldDropdown.createDom();this.sourceBlock_.workspace.svgGroup_.appendChild(b);\nBlockly.FieldDropdown.workspace=this.sourceBlock_.workspace}var b=Blockly.FieldDropdown.svgWrapper_,c=Blockly.FieldDropdown.svgGroup_,d=Blockly.FieldDropdown.svgOptions_,e=Blockly.FieldDropdown.svgBackground_,f=Blockly.FieldDropdown.svgShadow_;goog.dom.removeChildren(d);Blockly.removeClass_(c,\"blocklyHidden\");Blockly.FieldDropdown.openDropdown_=this;for(var g=0,h=[],k=null,n=this.getOptions_(),p=0;p<n.length;p++){var m=n[p][1],l=Blockly.ContextMenu.optionToDom(n[p][0]),q=l.firstChild,r=l.lastChild;\nd.appendChild(l);k||m!=this.value_||(k=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyMenuText\",y:15},null),l.insertBefore(k,r),k.appendChild(document.createTextNode(\"\\u2713\")));l.setAttribute(\"transform\",\"translate(0, \"+p*Blockly.ContextMenu.Y_HEIGHT+\")\");h.push(q);Blockly.bindEvent_(l,\"mousedown\",null,Blockly.noEvent);Blockly.bindEvent_(l,\"mouseup\",this,a(m));Blockly.bindEvent_(l,\"mouseup\",null,Blockly.FieldDropdown.hide);g=Math.max(g,r.getComputedTextLength())}g+=2*Blockly.ContextMenu.X_PADDING;\nfor(p=0;p<h.length;p++)h[p].setAttribute(\"width\",g);if(Blockly.RTL)for(p=0;l=d.childNodes[p];p++)r=l.lastChild,r.setAttribute(\"text-anchor\",\"end\"),r.setAttribute(\"x\",g-Blockly.ContextMenu.X_PADDING);k&&(Blockly.RTL?(k.setAttribute(\"text-anchor\",\"end\"),k.setAttribute(\"x\",g-5)):k.setAttribute(\"x\",5));p=g+2*Blockly.FieldDropdown.CORNER_RADIUS;h=n.length*Blockly.ContextMenu.Y_HEIGHT+Blockly.FieldDropdown.CORNER_RADIUS+1;f.setAttribute(\"width\",p);f.setAttribute(\"height\",h);e.setAttribute(\"width\",p);e.setAttribute(\"height\",\nh);p=Blockly.makeColour(this.sourceBlock_.getColour());e.setAttribute(\"fill\",p);e=Blockly.getSvgXY_(this.borderRect_);f=this.borderRect_.getBBox();p=Blockly.RTL?e.x-g+Blockly.ContextMenu.X_PADDING+f.width-Blockly.BlockSvg.SEP_SPACE_X/2:e.x-Blockly.ContextMenu.X_PADDING+Blockly.BlockSvg.SEP_SPACE_X/2;g=Blockly.FieldDropdown.scrollbarWrapper_;10>=n.length?Blockly.addClass_(g,\"blocklyHidden\"):(d=d.getBBox(),Blockly.removeClass_(g,\"blocklyHidden\"),g.setAttribute(\"transform\",\"translate(\"+(Number(d.width)-\n15)+\" 0)\"));Blockly.FieldDropdown.wheelEvent_=Blockly.bindEvent_(c,\"wheel\",this,Blockly.FieldDropdown.onMouseWheel);Blockly.FieldDropdown.moveUpEvent_=Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarUpWrapper_,\"mouseover\",this,Blockly.FieldDropdown.moveUp);Blockly.FieldDropdown.moveUpLeaveEvent_=Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarUpWrapper_,\"mouseleave\",this,Blockly.FieldDropdown.mouseLeave);Blockly.FieldDropdown.moveDownEvent_=Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarDownWrapper_,\n\"mouseover\",this,Blockly.FieldDropdown.moveDown);Blockly.FieldDropdown.moveDownLeaveEvent_=Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarDownWrapper_,\"mouseleave\",this,Blockly.FieldDropdown.mouseLeave);b.setAttribute(\"x\",p);b.setAttribute(\"y\",e.y+f.height)};\nBlockly.FieldDropdown.prototype.trimOptions_=function(){this.suffixField=this.prefixField=null;var a=this.menuGenerator_;if(goog.isArray(a)&&!(2>a.length)){var b=a.map(function(a){return a[0]}),c=Blockly.shortestStringLength(b),d=Blockly.commonWordPrefix(b,c),e=Blockly.commonWordSuffix(b,c);if((d||e)&&!(c<=d+e)){d&&(this.prefixField=b[0].substring(0,d-1));e&&(this.suffixField=b[0].substr(1-e));b=[];for(c=0;c<a.length;c++){var f=a[c][0],g=a[c][1],f=f.substring(d,f.length-e);b[c]=[f,g]}this.menuGenerator_=\nb}}};Blockly.FieldDropdown.prototype.getOptions_=function(){return goog.isFunction(this.menuGenerator_)?this.menuGenerator_.call(this):this.menuGenerator_};Blockly.FieldDropdown.prototype.getValue=function(){return this.value_};Blockly.FieldDropdown.prototype.setValue=function(a){this.value_=a;for(var b=this.getOptions_(),c=0;c<b.length;c++)if(b[c][1]==a){this.setText(b[c][0]);return}this.setText(a)};\nBlockly.FieldDropdown.prototype.setText=function(a){this.sourceBlock_&&(this.arrow_.style.fill=this.arrowColor_?this.arrowColor_:Blockly.makeColour(this.sourceBlock_.getColour()));null!==a&&(this.text_=a,goog.dom.removeChildren(this.textElement_),a=a.replace(/\\s/g,Blockly.Field.NBSP),a||(a=Blockly.Field.NBSP),a=document.createTextNode(a),this.textElement_.appendChild(a),Blockly.RTL?this.textElement_.insertBefore(this.arrow_,this.textElement_.firstChild):this.textElement_.appendChild(this.arrow_),\nthis.size_.width=0,this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours_(),this.sourceBlock_.workspace.fireChangeEvent()))};\nBlockly.FieldDropdown.hide=function(){var a=Blockly.FieldDropdown.svgGroup_,b=Blockly.FieldDropdown.scrollbarWrapper_;a&&(Blockly.addClass_(a,\"blocklyHidden\"),a.removeAttribute(\"transform\"));b&&(Blockly.addClass_(b,\"blocklyHidden\"),b.removeAttribute(\"transform\"));Blockly.FieldDropdown.wheelEvent_&&Blockly.unbindEvent_(Blockly.FieldDropdown.wheelEvent_);Blockly.FieldDropdown.moveUpEvent_&&Blockly.unbindEvent_(Blockly.FieldDropdown.moveUpEvent_);Blockly.FieldDropdown.moveDownEvent_&&Blockly.unbindEvent_(Blockly.FieldDropdown.moveDownEvent_);\nBlockly.FieldDropdown.moveUpLeaveEvent_&&Blockly.unbindEvent_(Blockly.FieldDropdown.moveUpLeaveEvent_);Blockly.FieldDropdown.moveDownLaeveEvent_&&Blockly.unbindEvent_(Blockly.FieldDropdown.moveDownLeaveEvent_);Blockly.FieldDropdown.currentPosition=0;Blockly.FieldDropdown.openDropdown_=null};Blockly.FieldDropdownDynamic=function(a,b,c,d){\"function\"==typeof a?this.menuFunc_=a:this.menuName_=a;this.menuGenerator=this.getOptions_();this.changeHandler_=b;this.trimOptions_();a=this.getOptions_()[0];this.value_=a[1];this.arrow_=Blockly.createSvgElement(\"tspan\",{},null);d&&(this.arrowColor_=d);0!=c&&this.arrow_.appendChild(document.createTextNode(Blockly.RTL?\"\\u25be \":\" \\u25be\"));Blockly.FieldDropdownDynamic.superClass_.constructor.call(this,a[0])};\ngoog.inherits(Blockly.FieldDropdownDynamic,Blockly.Field);Blockly.FieldDropdownDynamic.prototype.clone=function(){return new Blockly.FieldDropdownDynamic(this.menuGenerator_,this.changeHandler_)};\nBlockly.FieldDropdownDynamic.createDom=function(){var a=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyHidden blocklyFieldDropdown\"},null);Blockly.FieldDropdownDynamic.svgGroup_=a;Blockly.FieldDropdownDynamic.svgShadow_=Blockly.createSvgElement(\"rect\",{\"class\":\"blocklyDropdownMenuShadow\",x:0,y:1},a);Blockly.FieldDropdownDynamic.svgBackground_=Blockly.createSvgElement(\"rect\",{x:-2,y:-1,filter:\"url(#blocklyEmboss)\"},a);Blockly.FieldDropdownDynamic.svgOptions_=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyDropdownMenuOptions\"},\na);return a};Blockly.FieldDropdownDynamic.prototype.dispose=function(){Blockly.FieldDropdownDynamic.openDropdown_==this&&Blockly.FieldDropdown.hide();Blockly.Field.prototype.dispose.call(this)};Blockly.FieldDropdownDynamic.CORNER_RADIUS=2;Blockly.FieldDropdownDynamic.prototype.CURSOR=\"default\";Blockly.FieldDropdownDynamic.openDropdown_=null;\nBlockly.FieldDropdownDynamic.prototype.showEditor_=function(){function a(a){return function(b){if(this.changeHandler_){var c=this.changeHandler_(a);void 0!==c&&(a=c)}null!==a&&(\"object\"==typeof Entry&&this.getValue()!=a&&Entry.dispatchEvent(\"entryBlocklyChanged\"),this.setValue(a));b.stopPropagation()}}if(Blockly.FieldDropdown.workspace!==this.sourceBlock_.workspace){goog.dom.removeChildren(Blockly.FieldDropdown.svgWrapper_);var b=Blockly.FieldDropdown.createDom();this.sourceBlock_.workspace.svgGroup_.appendChild(b);\nBlockly.FieldDropdown.workspace=this.sourceBlock_.workspace}var b=Blockly.FieldDropdown.svgWrapper_,c=Blockly.FieldDropdown.svgGroup_,d=Blockly.FieldDropdown.svgOptions_,e=Blockly.FieldDropdown.svgBackground_,f=Blockly.FieldDropdown.svgShadow_;goog.dom.removeChildren(d);Blockly.removeClass_(c,\"blocklyHidden\");Blockly.FieldDropdownDynamic.openDropdown_=this;for(var g=0,h=[],k=null,n=this.getOptions_(),p=0;p<n.length;p++){var m=n[p][1],l=Blockly.ContextMenu.optionToDom(n[p][0]),q=l.firstChild,r=l.lastChild;\nd.appendChild(l);k||m!=this.value_||(k=Blockly.createSvgElement(\"text\",{\"class\":\"blocklyMenuText\",y:15},null),l.insertBefore(k,r),k.appendChild(document.createTextNode(\"\\u2713\")));l.setAttribute(\"transform\",\"translate(0, \"+p*Blockly.ContextMenu.Y_HEIGHT+\")\");h.push(q);Blockly.bindEvent_(l,\"mousedown\",null,Blockly.noEvent);Blockly.bindEvent_(l,\"mouseup\",this,a(m));Blockly.bindEvent_(l,\"mouseup\",null,Blockly.FieldDropdown.hide);g=Math.max(g,r.getComputedTextLength())}g+=2*Blockly.ContextMenu.X_PADDING;\nfor(p=0;p<h.length;p++)h[p].setAttribute(\"width\",g);if(Blockly.RTL)for(p=0;l=d.childNodes[p];p++)r=l.lastChild,r.setAttribute(\"text-anchor\",\"end\"),r.setAttribute(\"x\",g-Blockly.ContextMenu.X_PADDING);k&&(Blockly.RTL?(k.setAttribute(\"text-anchor\",\"end\"),k.setAttribute(\"x\",g-5)):k.setAttribute(\"x\",5));p=g+2*Blockly.FieldDropdownDynamic.CORNER_RADIUS;h=n.length*Blockly.ContextMenu.Y_HEIGHT+Blockly.FieldDropdownDynamic.CORNER_RADIUS+1;f.setAttribute(\"width\",p);f.setAttribute(\"height\",h);e.setAttribute(\"width\",\np);e.setAttribute(\"height\",h);p=Blockly.makeColour(this.sourceBlock_.getColour());e.setAttribute(\"fill\",p);e=Blockly.getSvgXY_(this.borderRect_);f=this.borderRect_.getBBox();p=Blockly.RTL?e.x-g+Blockly.ContextMenu.X_PADDING+f.width-Blockly.BlockSvg.SEP_SPACE_X/2:e.x-Blockly.ContextMenu.X_PADDING+Blockly.BlockSvg.SEP_SPACE_X/2;g=Blockly.FieldDropdown.scrollbarWrapper_;10>=n.length?Blockly.addClass_(g,\"blocklyHidden\"):(d=d.getBBox(),Blockly.removeClass_(g,\"blocklyHidden\"),g.setAttribute(\"transform\",\n\"translate(\"+(Number(d.width)-15)+\" 0)\"));Blockly.FieldDropdown.wheelEvent_=Blockly.bindEvent_(c,\"wheel\",this,Blockly.FieldDropdown.onMouseWheel);Blockly.FieldDropdown.moveUpEvent_=Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarUpWrapper_,\"mouseover\",this,Blockly.FieldDropdown.moveUp);Blockly.FieldDropdown.moveUpLeaveEvent_=Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarUpWrapper_,\"mouseleave\",this,Blockly.FieldDropdown.mouseLeave);Blockly.FieldDropdown.moveDownEvent_=Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarDownWrapper_,\n\"mouseover\",this,Blockly.FieldDropdown.moveDown);Blockly.FieldDropdown.moveDownLeaveEvent_=Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarDownWrapper_,\"mouseleave\",this,Blockly.FieldDropdown.mouseLeave);b.setAttribute(\"x\",p);b.setAttribute(\"y\",e.y+f.height)};Blockly.FieldDropdownDynamic.prototype.trimOptions_=function(){};\nBlockly.FieldDropdownDynamic.prototype.getOptions_=function(){return\"object\"==typeof Entry.container?this.menuName_?Entry.container.getDropdownList(this.menuName_):this.menuFunc_.call(this):[[Lang.Blocks.no_target,\"null\"]]};Blockly.FieldDropdownDynamic.prototype.getValue=function(){return this.value_};Blockly.FieldDropdownDynamic.prototype.setValue=function(a){this.value_=a;for(var b=this.getOptions_(),c=0;c<b.length;c++)if(b[c][1]==a){this.setText(b[c][0]);return}this.setText(\"\\ub300\\uc0c1\\uc5c6\\uc74c\")};\nBlockly.FieldDropdownDynamic.prototype.setText=function(a){this.sourceBlock_&&(this.arrow_.style.fill=this.arrowColor_?this.arrowColor_:Blockly.makeColour(this.sourceBlock_.getColour()));a&&null!==a&&(this.text_=a,goog.dom.removeChildren(this.textElement_),a=a.replace(/\\s/g,Blockly.Field.NBSP),a||(a=Blockly.Field.NBSP),a=document.createTextNode(a),this.textElement_.appendChild(a),Blockly.RTL?this.textElement_.insertBefore(this.arrow_,this.textElement_.firstChild):this.textElement_.appendChild(this.arrow_),\nthis.size_.width=0,this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours_(),this.sourceBlock_.workspace.fireChangeEvent()))};Blockly.FieldDropdownDynamic.hide=function(){Blockly.FieldDropdown.hide()};Blockly.FieldImage=function(a,b,c,d){this.sourceBlock_=null;this.height_=Number(c);this.width_=Number(b);this.size_={height:this.height_+10,width:this.width_};this.text_=d||\"\";b=6-Blockly.BlockSvg.FIELD_HEIGHT;this.fieldGroup_=Blockly.createSvgElement(\"g\",{},null);this.imageElement_=Blockly.createSvgElement(\"image\",{height:this.height_+\"px\",width:this.width_+\"px\",y:b},this.fieldGroup_);this.setValue(a);goog.userAgent.GECKO&&(this.rectElement_=Blockly.createSvgElement(\"rect\",{height:this.height_+\"px\",\nwidth:this.width_+\"px\",y:b,\"fill-opacity\":0},this.fieldGroup_))};goog.inherits(Blockly.FieldImage,Blockly.Field);Blockly.FieldImage.prototype.clone=function(){return new Blockly.FieldImage(this.getSrc(),this.width_,this.height_,this.getText())};Blockly.FieldImage.prototype.rectElement_=null;Blockly.FieldImage.prototype.EDITABLE=!1;\nBlockly.FieldImage.prototype.init=function(a){if(this.sourceBlock_)throw\"Image has already been initialized once.\";this.sourceBlock_=a;a.getSvgRoot().appendChild(this.fieldGroup_);a=this.rectElement_||this.imageElement_;a.tooltip=this.sourceBlock_;Blockly.Tooltip&&Blockly.Tooltip.bindMouseEvents(a)};Blockly.FieldImage.prototype.dispose=function(){goog.dom.removeNode(this.fieldGroup_);this.rectElement_=this.imageElement_=this.fieldGroup_=null};\nBlockly.FieldImage.prototype.setTooltip=function(a){(this.rectElement_||this.imageElement_).tooltip=a};Blockly.FieldImage.prototype.getValue=function(){return this.src_};Blockly.FieldImage.prototype.setValue=function(a){null!==a&&(this.src_=a,this.imageElement_.setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",goog.isString(a)?a:\"\"))};Blockly.FieldImage.prototype.setText=function(a){null!==a&&(this.text_=a)};Blockly.FieldKeydownInput=function(a){this.arrow_=Blockly.createSvgElement(\"tspan\",{},null);var b=Entry.getKeyCodeMap();this.value_=a;Blockly.FieldKeydownInput.superClass_.constructor.call(this,b[a])};goog.inherits(Blockly.FieldKeydownInput,Blockly.Field);var fkip=Blockly.FieldKeydownInput.prototype;fkip.clone=function(){return new Blockly.FieldKeydownInput(this.getText(),this.changeHandler_)};\nBlockly.FieldKeydownInput.createDom=function(){var a=\"/legacy_media/keyboard_workspace.png\",b=Blockly.createSvgElement(\"g\",{\"class\":\"blocklyHelperDiv blocklyHidden\"},null);Blockly.createSvgElement(\"image\",{\"class\":\"blocklyHelperImg\",width:\"249\",height:\"106\"},b).setAttributeNS(\"http://www.w3.org/1999/xlink\",\"xlink:href\",a);return Blockly.FieldKeydownInput.helperSvgGroup_=b};fkip.CURSOR=\"pointer\";fkip.dispose=function(){Blockly.WidgetDiv.hideIfField(this);Blockly.FieldTextInput.superClass_.dispose.call(this)};\nfkip.setText=function(a){null!==a&&(a?Blockly.Field.prototype.setText.call(this,a):Blockly.Field.prototype.setText.call(this,\"   \"))};\nfkip.showEditor_=function(){Blockly.WidgetDiv.show(this,this.dispose_());var a=Blockly.WidgetDiv.DIV,b=goog.dom.createDom(\"input\",\"blocklyHtmlInput\");Blockly.FieldTextInput.htmlInput_=b;a.appendChild(b);b.value=b.defaultValue=this.text_;b.oldValue_=null;this.resizeEditor_();b.focus();b.select();b.onKeyUpWrapper_=Blockly.bindEvent_(b,\"keyup\",this,this.onHtmlInputChange_);b.onBlurWrapper_=Blockly.bindEvent_(b,\"blur\",this,Blockly.WidgetDiv.hide);b.onBlurWrapper_=Blockly.bindEvent_(b,\"blur\",this,Blockly.FieldKeydownInput.hide);\nthis.sourceBlock_.workspace.getCanvas();a=Blockly.FieldKeydownInput.helperSvgGroup_;Blockly.removeClass_(a,\"blocklyHidden\");var b=Blockly.getSvgXY_(this.borderRect_),c=this.borderRect_.getBBox();a.setAttribute(\"transform\",\"translate(\"+(b.x-15+c.width/2)+\", \"+(b.y+19)+\")\")};fkip.onHtmlInputChange_=function(a){Blockly.FieldTextInput.htmlInput_.value=\"\";a=a.keyCode;if(65<=a&&90>=a||37<=a&&40>=a||48<=a&&57>=a||32==a||13==a)Blockly.WidgetDiv.hide(),Blockly.FieldKeydownInput.hide(),this.setValue(a)};\nfkip.dispose_=function(){var a=this;return function(){var b=Blockly.FieldTextInput.htmlInput_;a.sourceBlock_.render();Blockly.unbindEvent_(b.onKeyUpWrapper_);Blockly.FieldTextInput.htmlInput_=null}};Blockly.FieldKeydownInput.hide=function(){var a=Blockly.FieldKeydownInput.helperSvgGroup_;a&&Blockly.addClass_(a,\"blocklyHidden\")};fkip.setValue=function(a){this.value_=a;(a=Entry.getKeyCodeMap()[a])?this.setText(String(a)):this.setText(Lang.Blocks.no_target)};fkip.getValue=function(){return String(this.value_)};\nfkip.resizeEditor_=function(){var a=Blockly.WidgetDiv.DIV,b=this.fieldGroup_.getBBox();a.style.width=b.width+\"px\";b=Blockly.getAbsoluteXY_(this.borderRect_,this.sourceBlock_.workspace.svgGroup_.parentNode);if(Blockly.RTL){var c=this.borderRect_.getBBox();b.x+=c.width;b.x-=a.offsetWidth}b.y+=1;goog.userAgent.WEBKIT&&(b.y-=3);a.style.left=b.x+\"px\";a.style.top=b.y+\"px\"};Blockly.Flyout=function(){var a=this;this.workspace_=new Blockly.Workspace(function(){return a.getMetrics_()},function(b){return a.setMetrics_(b)});this.workspace_.isFlyout=!0;this.changeWrapper_=null;this.height_=this.width_=0;this.buttons_=[];this.listeners_=[]};Blockly.Flyout.prototype.autoClose=!0;Blockly.Flyout.prototype.CORNER_RADIUS=8;Blockly.Flyout.prototype.onResizeWrapper_=null;\nBlockly.Flyout.prototype.createDom=function(){this.svgGroup_=Blockly.createSvgElement(\"g\",{},null);this.svgBackground_=Blockly.createSvgElement(\"path\",{\"class\":\"blocklyFlyoutBackground\"},this.svgGroup_);this.svgGroup_.appendChild(this.workspace_.createDom());return this.svgGroup_};\nBlockly.Flyout.prototype.dispose=function(){this.hide();this.onResizeWrapper_&&(Blockly.unbindEvent_(this.onResizeWrapper_),this.onResizeWrapper_=null);this.changeWrapper_&&(Blockly.unbindEvent_(this.changeWrapper_),this.changeWrapper_=null);this.scrollbar_&&(this.scrollbar_.dispose(),this.scrollbar_=null);this.workspace_=null;this.svgGroup_&&(goog.dom.removeNode(this.svgGroup_),this.svgGroup_=null);this.targetWorkspace_=this.svgBackground_=null};\nBlockly.Flyout.prototype.getMetrics_=function(){if(!this.isVisible())return null;var a=this.height_-2*this.CORNER_RADIUS,b=this.width_;try{var c=this.workspace_.getCanvas().getBBox()}catch(d){c={height:0,y:0}}return{viewHeight:a,viewWidth:b,contentHeight:c.height+c.y,viewTop:-this.workspace_.scrollY,contentTop:0,absoluteTop:this.CORNER_RADIUS,absoluteLeft:0}};\nBlockly.Flyout.prototype.setMetrics_=function(a){var b=this.getMetrics_();b&&(goog.isNumber(a.y)&&(this.workspace_.scrollY=-b.contentHeight*a.y-b.contentTop),a=this.workspace_.scrollY+b.absoluteTop,this.workspace_.getCanvas().setAttribute(\"transform\",\"translate(0,\"+a+\")\"))};\nBlockly.Flyout.prototype.init=function(a,b){this.targetWorkspace_=a;b&&(this.scrollbar_=new Blockly.Scrollbar(this.workspace_,!1,!1));this.hide();this.onResizeWrapper_=Blockly.bindEvent_(window,goog.events.EventType.RESIZE,this,this.position_);this.position_();this.changeWrapper_=Blockly.bindEvent_(this.targetWorkspace_.getCanvas(),\"blocklyWorkspaceChange\",this,this.filterForCapacity_)};\nBlockly.Flyout.prototype.position_=function(){if(this.isVisible()){var a=this.targetWorkspace_.getMetrics();if(a){var b=this.width_-this.CORNER_RADIUS;Blockly.RTL&&(b*=-1);var c=[\"M \"+(Blockly.RTL?this.width_:0)+\",0\"];c.push(\"h\",b);c.push(\"v\",Math.max(0,a.viewHeight));c.push(\"h\",-b);c.push(\"z\");this.svgBackground_.setAttribute(\"d\",c.join(\" \"));b=a.absoluteLeft;Blockly.RTL&&(b+=a.viewWidth,b-=this.width_);this.svgGroup_.setAttribute(\"transform\",\"translate(\"+b+\",\"+a.absoluteTop+\")\");this.height_=a.viewHeight;\nthis.scrollbar_&&this.scrollbar_.resize()}}};Blockly.Flyout.prototype.isVisible=function(){return\"block\"==this.svgGroup_.style.display};Blockly.Flyout.prototype.hide=function(){if(this.isVisible()){this.svgGroup_.style.display=\"none\";for(var a=0,b;b=this.listeners_[a];a++)Blockly.unbindEvent_(b);this.listeners_.splice(0);this.reflowWrapper_&&(Blockly.unbindEvent_(this.reflowWrapper_),this.reflowWrapper_=null)}};\nBlockly.Flyout.prototype.show=function(a){this.hide();for(var b=this.workspace_.getTopBlocks(!1),c=0,d;d=b[c];c++)d.workspace==this.workspace_&&d.dispose(!1,!1);for(var c=0,e;e=this.buttons_[c];c++)goog.dom.removeNode(e);this.buttons_.splice(0);var f=this.CORNER_RADIUS;this.svgGroup_.style.display=\"block\";var b=[],g=[];if(a==Blockly.Variables.NAME_TYPE)Blockly.Variables.flyoutCategory(b,g,f,this.workspace_);else if(a==Blockly.Procedures.NAME_TYPE)Blockly.Procedures.flyoutCategory(b,g,f,this.workspace_);\nelse for(var h=0;d=a[h];h++)d.tagName&&\"BLOCK\"==d.tagName.toUpperCase()&&(d=Blockly.Xml.domToBlock(this.workspace_,d),b.push(d),g.push(f));a=f;for(h=0;d=b[h];h++){c=d.getDescendants();e=0;for(var k;k=c[e];e++)k.isInFlyout=!0,Blockly.Comment&&k.setCommentText(null);d.render();k=d.getSvgRoot();e=d.getHeightWidth();c=Blockly.RTL?0:f+.5*Blockly.BlockSvg.TAB_WIDTH;d.outputConnection?c+=e.height/2:!d.previousConnection&&d.nextConnection&&(c+=10);d.moveBy(c,a);a+=e.height+g[h];e=Blockly.createSvgElement(\"rect\",\n{\"fill-opacity\":0},null);this.workspace_.getCanvas().insertBefore(e,d.getSvgRoot());d.flyoutRect_=e;this.buttons_[h]=e;this.autoClose&&d.isAddable()?this.listeners_.push(Blockly.bindEvent_(k,\"mousedown\",null,this.createBlockFunc_(d))):d.isAddable()&&this.listeners_.push(Blockly.bindEvent_(k,\"mousedown\",null,this.blockMouseDown_(d)));this.listeners_.push(Blockly.bindEvent_(k,\"mouseover\",d.svg_,d.svg_.addSelect));this.listeners_.push(Blockly.bindEvent_(k,\"mouseout\",d.svg_,d.svg_.removeSelect));this.listeners_.push(Blockly.bindEvent_(e,\n\"mousedown\",null,this.createBlockFunc_(d)));this.listeners_.push(Blockly.bindEvent_(e,\"mouseover\",d.svg_,d.svg_.addSelect));this.listeners_.push(Blockly.bindEvent_(e,\"mouseout\",d.svg_,d.svg_.removeSelect))}this.width_=0;this.reflow();this.filterForCapacity_();Blockly.fireUiEvent(window,\"resize\");this.reflowWrapper_=Blockly.bindEvent_(this.workspace_.getCanvas(),\"blocklyWorkspaceChange\",this,this.reflow);this.workspace_.fireChangeEvent()};\nBlockly.Flyout.prototype.reflow=function(){for(var a=0,b=this.CORNER_RADIUS,c=this.workspace_.getTopBlocks(!1),d=0,e;e=c[d];d++){e.getSvgRoot();var f=e.getHeightWidth(),a=Math.max(a,f.width)}a+=b+Blockly.BlockSvg.TAB_WIDTH+b/2+Blockly.Scrollbar.scrollbarThickness;if(this.width_!=a){for(d=0;e=c[d];d++){var f=e.getHeightWidth(),g=e.getRelativeToSurfaceXY();if(Blockly.RTL){var h=a-b-Blockly.BlockSvg.TAB_WIDTH-g.x;e.moveBy(h,0);g.x+=h}e.flyoutRect_&&(e.flyoutRect_.setAttribute(\"width\",f.width),e.flyoutRect_.setAttribute(\"height\",\nf.height),e.flyoutRect_.setAttribute(\"x\",Blockly.RTL?g.x-f.width:g.x),e.flyoutRect_.setAttribute(\"y\",g.y))}this.width_=a;Blockly.fireUiEvent(window,\"resize\")}};Blockly.Block.prototype.moveTo=function(a,b){var c=this.getRelativeToSurfaceXY();this.svg_.getRootElement().setAttribute(\"transform\",\"translate(\"+a+\", \"+b+\")\");this.moveConnections_(a-c.x,b-c.y)};\nBlockly.Flyout.prototype.blockMouseDown_=function(a){var b=this;return function(c){Blockly.terminateDrag_();Blockly.hideChaff();Blockly.isRightButton(c)?Blockly.ContextMenu&&a.showContextMenu_(Blockly.mouseToSvg(c)):(Blockly.removeAllRanges(),Blockly.setCursorHand_(!0),Blockly.Flyout.startDownEvent_=c,Blockly.Flyout.startBlock_=a,Blockly.Flyout.startFlyout_=b,Blockly.Flyout.onMouseUpWrapper_=Blockly.bindEvent_(document,\"mouseup\",this,Blockly.terminateDrag_),Blockly.Flyout.onMouseMoveWrapper_=Blockly.bindEvent_(document,\n\"mousemove\",this,b.onMouseMove_));c.stopPropagation()}};Blockly.Flyout.prototype.onMouseMove_=function(a){\"mousemove\"==a.type&&1>=a.clientX&&0==a.clientY&&0==a.button?a.stopPropagation():(Blockly.removeAllRanges(),Math.sqrt(Math.pow(a.clientX-Blockly.Flyout.startDownEvent_.clientX,2)+Math.pow(a.clientY-Blockly.Flyout.startDownEvent_.clientY,2))>Blockly.DRAG_RADIUS&&Blockly.Flyout.startFlyout_.createBlockFunc_(Blockly.Flyout.startBlock_)(Blockly.Flyout.startDownEvent_))};\nBlockly.Flyout.prototype.createBlockFunc_=function(a){var b=this;return function(c){if(!Blockly.isRightButton(c)&&!a.disabled){\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\");var d=Blockly.Xml.blockToDom_(a),d=Blockly.Xml.domToBlock(b.targetWorkspace_,d),e=a.getSvgRoot();if(!e)throw\"originBlock is not rendered.\";var e=Blockly.getSvgXY_(e),f=d.getSvgRoot();if(!f)throw\"block is not rendered.\";f=Blockly.getSvgXY_(f);d.moveBy(e.x-f.x,e.y-f.y);b.autoClose?b.hide():b.filterForCapacity_();\nd.onMouseDown_(c)}}};Blockly.Flyout.prototype.filterForCapacity_=function(){for(var a=this.targetWorkspace_.remainingCapacity(),b=this.workspace_.getTopBlocks(!1),c=0,d;d=b[c];c++){var e=d.getDescendants().length>a;d.setDisabled(e)}};\nBlockly.Flyout.terminateDrag_=function(){Blockly.Flyout.onMouseUpWrapper_&&(Blockly.unbindEvent_(Blockly.Flyout.onMouseUpWrapper_),Blockly.Flyout.onMouseUpWrapper_=null);Blockly.Flyout.onMouseMoveWrapper_&&(Blockly.unbindEvent_(Blockly.Flyout.onMouseMoveWrapper_),Blockly.Flyout.onMouseMoveWrapper_=null);Blockly.Flyout.startDownEvent_=null;Blockly.Flyout.startBlock_=null;Blockly.Flyout.startFlyout_=null};Blockly.Toolbox={};Blockly.Toolbox.width=0;Blockly.Toolbox.selectedOption_=null;Blockly.Toolbox.CONFIG_={indentWidth:19,cssRoot:\"blocklyTreeRoot\",cssHideRoot:\"blocklyHidden\",cssItem:\"\",cssTreeRow:\"blocklyTreeRow\",cssItemLabel:\"blocklyTreeLabel\",cssTreeIcon:\"blocklyTreeIcon\",cssExpandedFolderIcon:\"blocklyTreeIconOpen\",cssFileIcon:\"blocklyTreeIconNone\",cssSelectedRow:\"blocklyTreeSelected\"};\nBlockly.Toolbox.createDom=function(a,b){Blockly.Toolbox.HtmlDiv=goog.dom.createDom(\"div\",\"blocklyToolboxDiv\");Blockly.Toolbox.HtmlDiv.setAttribute(\"dir\",Blockly.RTL?\"RTL\":\"LTR\");b.appendChild(Blockly.Toolbox.HtmlDiv);Blockly.Toolbox.flyout_=new Blockly.Flyout;a.appendChild(Blockly.Toolbox.flyout_.createDom());Blockly.bindEvent_(Blockly.Toolbox.HtmlDiv,\"mousedown\",null,function(a){Blockly.isRightButton(a)||a.target==Blockly.Toolbox.HtmlDiv?Blockly.hideChaff(!1):Blockly.hideChaff(!0)})};\nBlockly.Toolbox.init=function(){Blockly.Toolbox.CONFIG_.cleardotPath=Blockly.pathToBlockly+\"media/1x1.gif\";Blockly.Toolbox.CONFIG_.cssCollapsedFolderIcon=\"blocklyTreeIconClosed\"+(Blockly.RTL?\"Rtl\":\"Ltr\");var a=new Blockly.Toolbox.TreeControl(\"root\",Blockly.Toolbox.CONFIG_);Blockly.Toolbox.tree_=a;a.setShowRootNode(!1);a.setShowLines(!1);a.setShowExpandIcons(!1);a.setSelectedItem(null);Blockly.Toolbox.HtmlDiv.style.display=\"block\";Blockly.Toolbox.flyout_.init(Blockly.mainWorkspace,!0);Blockly.Toolbox.populate_();\na.render(Blockly.Toolbox.HtmlDiv);goog.events.listen(window,goog.events.EventType.RESIZE,Blockly.Toolbox.position_);Blockly.Toolbox.position_()};Blockly.Toolbox.position_=function(){var a=Blockly.Toolbox.HtmlDiv,b=goog.style.getBorderBox(Blockly.svg),c=Blockly.svgSize();Blockly.RTL?(b=Blockly.convertCoordinates(0,0,!1),a.style.left=b.x+c.width-a.offsetWidth+\"px\"):a.style.marginLeft=b.left;a.style.height=c.height+1+\"px\";Blockly.Toolbox.width=a.offsetWidth;Blockly.RTL||--Blockly.Toolbox.width};\nBlockly.Toolbox.populate_=function(){function a(c,d){for(var e=0,f;f=c.childNodes[e];e++)if(f.tagName){var g=f.tagName.toUpperCase();if(\"CATEGORY\"==g){g=b.createNode(f.getAttribute(\"name\"));g.blocks=[];d.add(g);var h=f.getAttribute(\"custom\");h?g.blocks=h:a(f,g)}else\"BLOCK\"==g&&d.blocks.push(f)}}var b=Blockly.Toolbox.tree_;b.blocks=[];a(Blockly.languageTree,Blockly.Toolbox.tree_);if(b.blocks.length)throw\"Toolbox cannot have both blocks and categories in the root level.\";Blockly.fireUiEvent(window,\n\"resize\")};Blockly.Toolbox.clearSelection=function(){Blockly.Toolbox.tree_.setSelectedItem(null)};Blockly.Toolbox.TreeControl=function(a,b,c){goog.ui.tree.TreeControl.call(this,a,b,c)};goog.inherits(Blockly.Toolbox.TreeControl,goog.ui.tree.TreeControl);\nBlockly.Toolbox.TreeControl.prototype.enterDocument=function(){Blockly.Toolbox.TreeControl.superClass_.enterDocument.call(this);if(goog.events.BrowserFeature.TOUCH_ENABLED){var a=this.getElement();Blockly.bindEvent_(a,goog.events.EventType.TOUCHSTART,this,this.handleTouchEvent_)}};Blockly.Toolbox.TreeControl.prototype.handleTouchEvent_=function(a){a.preventDefault();var b=this.getNodeFromEvent_(a);b&&a.type===goog.events.EventType.TOUCHSTART&&window.setTimeout(function(){b.onMouseDown(a)},1)};\nBlockly.Toolbox.TreeControl.prototype.createNode=function(a){return new Blockly.Toolbox.TreeNode(a||\"\",this.getConfig(),this.getDomHelper())};Blockly.Toolbox.TreeControl.prototype.setSelectedItem=function(a){this.selectedItem_!=a&&(goog.ui.tree.TreeControl.prototype.setSelectedItem.call(this,a),a&&a.blocks&&a.blocks.length?Blockly.Toolbox.flyout_.show(a.blocks):Blockly.Toolbox.flyout_.hide())};\nBlockly.Toolbox.TreeNode=function(a,b,c){goog.ui.tree.TreeNode.call(this,a,b,c);a=function(){Blockly.fireUiEvent(window,\"resize\")};goog.events.listen(Blockly.Toolbox.tree_,goog.ui.tree.BaseNode.EventType.EXPAND,a);goog.events.listen(Blockly.Toolbox.tree_,goog.ui.tree.BaseNode.EventType.COLLAPSE,a)};goog.inherits(Blockly.Toolbox.TreeNode,goog.ui.tree.TreeNode);Blockly.Toolbox.TreeNode.prototype.getExpandIconHtml=function(){return\"<span></span>\"};\nBlockly.Toolbox.TreeNode.prototype.getExpandIconElement=function(){return null};Blockly.Toolbox.TreeNode.prototype.onMouseDown=function(a){this.hasChildren()&&this.isUserCollapsible_?(this.toggle(),this.select()):this.isSelected()?this.getTree().setSelectedItem(null):this.select();this.updateRow()};Blockly.Toolbox.TreeNode.prototype.onDoubleClick_=function(a){};Blockly.Variables={};Blockly.Variables.NAME_TYPE=\"VARIABLE\";Blockly.Variables.allVariables=function(a){var b;b=a?a.getDescendants():Blockly.mainWorkspace.getAllBlocks();a=Object.create(null);for(var c=0;c<b.length;c++){var d=b[c].getVars;if(d)for(var d=d.call(b[c]),e=0;e<d.length;e++){var f=d[e];f&&(a[f.toLowerCase()]=f)}}b=[];for(var g in a)b.push(a[g]);return b};\nBlockly.Variables.renameVariable=function(a,b){for(var c=Blockly.mainWorkspace.getAllBlocks(),d=0;d<c.length;d++){var e=c[d].renameVar;e&&e.call(c[d],a,b)}};\nBlockly.Variables.flyoutCategory=function(a,b,c,d){var e=Blockly.Variables.allVariables();e.sort(goog.string.caseInsensitiveCompare);e.unshift(null);for(var f=void 0,g=0;g<e.length;g++)if(e[g]!==f){var h=Blockly.Blocks.variables_get?Blockly.Block.obtain(d,\"variables_get\"):null;h&&h.initSvg();var k=Blockly.Blocks.variables_set?Blockly.Block.obtain(d,\"variables_set\"):null;k&&k.initSvg();null===e[g]?f=(h||k).getVars()[0]:(h&&h.setFieldValue(e[g],\"VAR\"),k&&k.setFieldValue(e[g],\"VAR\"));k&&a.push(k);h&&\na.push(h);h&&k?b.push(c,3*c):b.push(2*c)}};Blockly.Variables.generateUniqueName=function(){var a=Blockly.Variables.allVariables(),b=\"\";if(a.length){a.sort(goog.string.caseInsensitiveCompare);for(var c=0,d=\"i\",e,f;!b;){e=0;for(f=!1;e<a.length&&!f;)a[e].toLowerCase()==d&&(f=!0),e++;f?(\"z\"===d[0]?(c++,d=\"a\"):(d=String.fromCharCode(d.charCodeAt(0)+1),\"l\"==d[0]&&(d=String.fromCharCode(d.charCodeAt(0)+1))),0<c&&(d+=c)):b=d}}else b=\"i\";return b};Blockly.FieldVariable=function(a,b){var c;if(b){var d=this;c=function(a){var c=Blockly.FieldVariable.dropdownChange.call(d,a);a=void 0===c?a:null===c?d.getValue():c;b.call(d,a);return c}}else c=Blockly.FieldVariable.dropdownChange;Blockly.FieldVariable.superClass_.constructor.call(this,Blockly.FieldVariable.dropdownCreate,c);a?this.setValue(a):this.setValue(Blockly.Variables.generateUniqueName())};goog.inherits(Blockly.FieldVariable,Blockly.FieldDropdown);\nBlockly.FieldVariable.prototype.clone=function(){return new Blockly.FieldVariable(this.getValue(),this.changeHandler_)};Blockly.FieldVariable.prototype.getValue=function(){return this.getText()};Blockly.FieldVariable.prototype.setValue=function(a){this.value_=a;this.setText(a)};\nBlockly.FieldVariable.dropdownCreate=function(){var a=Blockly.Variables.allVariables(),b=this.getText();b&&-1==a.indexOf(b)&&a.push(b);a.sort(goog.string.caseInsensitiveCompare);a.push(Blockly.Msg.RENAME_VARIABLE);a.push(Blockly.Msg.NEW_VARIABLE);for(var b=[],c=0;c<a.length;c++)b[c]=[a[c],a[c]];return b};\nBlockly.FieldVariable.dropdownChange=function(a){function b(a,b){Blockly.hideChaff();var c=window.prompt(a,b);return c&&c.replace(/[\\s\\xa0]+/g,\" \").replace(/^ | $/g,\"\")}if(a==Blockly.Msg.RENAME_VARIABLE){var c=this.getText();(a=b(Blockly.Msg.RENAME_VARIABLE_TITLE.replace(\"%1\",c),c))&&Blockly.Variables.renameVariable(c,a);return null}if(a==Blockly.Msg.NEW_VARIABLE)return(a=b(Blockly.Msg.NEW_VARIABLE_TITLE,\"\"))?(Blockly.Variables.renameVariable(a,a),a):null};Blockly.Generator=function(a){this.name_=a;this.RESERVED_WORDS_=\"\"};Blockly.Generator.NAME_TYPE=\"generated_function\";\nBlockly.Generator.prototype.workspaceToCode=function(){var a=[];this.init();for(var b=Blockly.mainWorkspace.getTopBlocks(!0),c=0,d;d=b[c];c++){var e=this.blockToCode(d);e instanceof Array&&(e=e[0]);e&&(d.outputConnection&&this.scrubNakedValue&&(e=this.scrubNakedValue(e)),a.push(e))}a=a.join(\"\\n\");a=this.finish(a);a=a.replace(/^\\s+\\n/,\"\");a=a.replace(/\\n\\s+$/,\"\\n\");return a=a.replace(/[ \\t]+\\n/g,\"\\n\")};\nBlockly.Generator.prototype.tutorialWorkspaceToCode=function(){var a=[];this.init();for(var b=Blockly.mainWorkspace.getTopBlocks(!0),c=[],d=0;d<b.length;d++)\"when_start\"!=b[d].type&&\"declare_function\"!=b[d].type||c.push(b[d]);for(b=0;d=c[b];b++){var e=this.blockToCode(d);e instanceof Array&&(e=e[0]);e&&(d.outputConnection&&this.scrubNakedValue&&(e=this.scrubNakedValue(e)),a.push(e))}a=a.join(\"\\n\");a=this.finish(a);a=a.replace(/^\\s+\\n/,\"\");a=a.replace(/\\n\\s+$/,\"\\n\");return a=a.replace(/[ \\t]+\\n/g,\n\"\\n\")};Blockly.Generator.prototype.prefixLines=function(a,b){return b+a.replace(/\\n(.)/g,\"\\n\"+b+\"$1\")};Blockly.Generator.prototype.allNestedComments=function(a){var b=[];a=a.getDescendants();for(var c=0;c<a.length;c++){var d=a[c].getCommentText();d&&b.push(d)}b.length&&b.push(\"\");return b.join(\"\\n\")};\nBlockly.Generator.prototype.blockToCode=function(a){if(!a)return\"\";if(a.disabled)return a=a.nextConnection&&a.nextConnection.targetBlock(),this.blockToCode(a);var b=this[a.type];if(!b)throw'Language \"'+this.name_+'\" does not know how to generate code for block type \"'+a.type+'\".';b=b.call(a,a);return b instanceof Array?[this.scrub_(a,b[0]),b[1]]:this.scrub_(a,b)};\nBlockly.Generator.prototype.valueToCode=function(a,b,c){if(isNaN(c))throw'Expecting valid order from block \"'+a.type+'\".';a=a.getInputTargetBlock(b);if(!a)return\"\";var d=this.blockToCode(a);if(\"\"===d)return\"\";if(!(d instanceof Array))throw'Expecting tuple from value block \"'+a.type+'\".';b=d[0];d=d[1];if(isNaN(d))throw'Expecting valid order from value block \"'+a.type+'\".';b&&c<=d&&c!=d&&0!=c&&99!=c&&(b=\"(\"+b+\")\");return b};\nBlockly.Generator.prototype.statementToCode=function(a,b){var c=a.getInputTargetBlock(b),d=this.blockToCode(c);if(!goog.isString(d))throw'Expecting code from statement block \"'+c.type+'\".';d&&(d=this.prefixLines(d,\"  \"));return d};Blockly.Generator.prototype.addReservedWords=function(a){this.RESERVED_WORDS_+=a+\",\"};Blockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_=\"{leCUI8hutHZI4480Dc}\";\nBlockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_REGEXP_=new RegExp(Blockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_,\"g\");Blockly.Generator.prototype.provideFunction_=function(a,b){if(!this.definitions_[a]){var c=this.variableDB_.getDistinctName(a,this.NAME_TYPE);this.functionNames_[a]=c;this.definitions_[a]=b.join(\"\\n\").replace(this.FUNCTION_NAME_PLACEHOLDER_REGEXP_,c)}return this.functionNames_[a]};Blockly.Names=function(a){this.reservedDict_=Object.create(null);if(a){a=a.split(\",\");for(var b=0;b<a.length;b++)this.reservedDict_[a[b]]=!0}this.reset()};Blockly.Names.prototype.reset=function(){this.db_=Object.create(null);this.dbReverse_=Object.create(null)};Blockly.Names.prototype.getName=function(a,b){var c=a.toLowerCase()+\"_\"+b;if(c in this.db_)return this.db_[c];var d=this.getDistinctName(a,b);return this.db_[c]=d};\nBlockly.Names.prototype.getDistinctName=function(a,b){for(var c=this.safeName_(a),d=\"\";this.dbReverse_[c+d]||c+d in this.reservedDict_;)d=d?d+1:2;c+=d;this.dbReverse_[c]=!0;return c};Blockly.Names.prototype.safeName_=function(a){a?(a=encodeURI(a.replace(/ /g,\"_\")).replace(/[^\\w]/g,\"_\"),-1!=\"0123456789\".indexOf(a[0])&&(a=\"my_\"+a)):a=\"unnamed\";return a};Blockly.Names.equals=function(a,b){return a.toLowerCase()==b.toLowerCase()};Blockly.Procedures={};Blockly.Procedures.NAME_TYPE=\"PROCEDURE\";Blockly.Procedures.allProcedures=function(){for(var a=Blockly.mainWorkspace.getAllBlocks(),b=[],c=[],d=0;d<a.length;d++){var e=a[d].getProcedureDef;e&&(e=e.call(a[d]))&&(e[2]?b.push(e):c.push(e))}c.sort(Blockly.Procedures.procTupleComparator_);b.sort(Blockly.Procedures.procTupleComparator_);return[c,b]};Blockly.Procedures.procTupleComparator_=function(a,b){var c=a[0].toLowerCase(),d=b[0].toLowerCase();return c>d?1:c<d?-1:0};\nBlockly.Procedures.findLegalName=function(a,b){if(b.isInFlyout)return a;for(;!Blockly.Procedures.isLegalName(a,b.workspace,b);){var c=a.match(/^(.*?)(\\d+)$/);a=c?c[1]+(parseInt(c[2],10)+1):a+\"2\"}return a};Blockly.Procedures.isLegalName=function(a,b,c){b=b.getAllBlocks();for(var d=0;d<b.length;d++)if(b[d]!=c){var e=b[d].getProcedureDef;if(e&&(e=e.call(b[d]),Blockly.Names.equals(e[0],a)))return!1}return!0};\nBlockly.Procedures.rename=function(a){a=a.replace(/^[\\s\\xa0]+|[\\s\\xa0]+$/g,\"\");a=Blockly.Procedures.findLegalName(a,this.sourceBlock_);for(var b=this.sourceBlock_.workspace.getAllBlocks(),c=0;c<b.length;c++){var d=b[c].renameProcedure;d&&d.call(b[c],this.text_,a)}return a};\nBlockly.Procedures.flyoutCategory=function(a,b,c,d){function e(e,f){for(var k=0;k<e.length;k++){var n=Blockly.Block.obtain(d,f);n.setFieldValue(e[k][0],\"NAME\");for(var p=[],m=0;m<e[k][1].length;m++)p[m]=\"ARG\"+m;n.setProcedureParameters(e[k][1],p);n.initSvg();a.push(n);b.push(2*c)}}if(Blockly.Blocks.procedures_defnoreturn){var f=Blockly.Block.obtain(d,\"procedures_defnoreturn\");f.initSvg();a.push(f);b.push(2*c)}Blockly.Blocks.procedures_defreturn&&(f=Blockly.Block.obtain(d,\"procedures_defreturn\"),f.initSvg(),\na.push(f),b.push(2*c));Blockly.Blocks.procedures_ifreturn&&(f=Blockly.Block.obtain(d,\"procedures_ifreturn\"),f.initSvg(),a.push(f),b.push(2*c));b.length&&(b[b.length-1]=3*c);f=Blockly.Procedures.allProcedures();e(f[0],\"procedures_callnoreturn\");e(f[1],\"procedures_callreturn\")};Blockly.Procedures.getCallers=function(a,b){for(var c=[],d=b.getAllBlocks(),e=0;e<d.length;e++){var f=d[e].getProcedureCall;f&&(f=f.call(d[e]))&&Blockly.Names.equals(f,a)&&c.push(d[e])}return c};\nBlockly.Procedures.disposeCallers=function(a,b){for(var c=Blockly.Procedures.getCallers(a,b),d=0;d<c.length;d++)c[d].dispose(!0,!1)};Blockly.Procedures.mutateCallers=function(a,b,c,d){a=Blockly.Procedures.getCallers(a,b);for(b=0;b<a.length;b++)a[b].setProcedureParameters(c,d)};Blockly.Procedures.getDefinition=function(a,b){for(var c=b.getAllBlocks(),d=0;d<c.length;d++){var e=c[d].getProcedureDef;if(e&&(e=e.call(c[d]))&&Blockly.Names.equals(e[0],a))return c[d]}return null};\n// Copyright 2014 Google Inc.  Apache License 2.0\nBlockly.Realtime={};Blockly.Realtime.enabled_=!1;Blockly.Realtime.model_=null;Blockly.Realtime.initUi_=null;Blockly.Realtime.blocksMap_=null;Blockly.Realtime.withinSync=!1;Blockly.Realtime.realtimeLoader_=null;Blockly.Realtime.isEnabled=function(){return Blockly.Realtime.enabled_};\nBlockly.Realtime.initializeModel_=function(a){Blockly.Realtime.model_=a;var b=a.createMap();a.getRoot().set(\"blocks\",b);b=a.createList();a.getRoot().set(\"topBlocks\",b);b=a.createString(Blockly.Msg.CHAT);a.getRoot().set(\"text\",b)};Blockly.Realtime.removeBlock=function(a){Blockly.Realtime.blocksMap_[\"delete\"](a.id.toString())};Blockly.Realtime.addTopBlock=function(a){-1==Blockly.Realtime.topBlocks_.indexOf(a)&&Blockly.Realtime.topBlocks_.push(a)};Blockly.Realtime.removeTopBlock=function(a){Blockly.Realtime.topBlocks_.removeValue(a)};\nBlockly.Realtime.obtainBlock=function(a,b){return Blockly.Realtime.model_.create(Blockly.Block,a,b)};Blockly.Realtime.getBlockById=function(a){return Blockly.Realtime.blocksMap_.get(a)};\nBlockly.Realtime.onObjectChange_=function(a){var b=a.events;a=a.events.length;for(var c=0;c<a;c++){var d=b[c];if(!d.isLocal&&\"value_changed\"==d.type)if(\"xmlDom\"==d.property){var e=d.target;Blockly.Realtime.doWithinSync_(function(){Blockly.Realtime.placeBlockOnWorkspace_(e,!1);Blockly.Realtime.moveBlock_(e)})}else if(\"relativeX\"==d.property||\"relativeY\"==d.property){var f=d.target;Blockly.Realtime.doWithinSync_(function(){f.svg_||Blockly.Realtime.placeBlockOnWorkspace_(f,!1);Blockly.Realtime.moveBlock_(f)})}}};\nBlockly.Realtime.onBlocksMapChange_=function(a){console.log(\"Blocks Map event:\");console.log(\"  id: \"+a.property);if(!a.isLocal){var b=a.newValue;b?Blockly.Realtime.placeBlockOnWorkspace_(b,!a.oldValue):(b=a.oldValue,Blockly.Realtime.deleteBlock(b))}};Blockly.Realtime.doWithinSync_=function(a){if(Blockly.Realtime.withinSync)a();else try{Blockly.Realtime.withinSync=!0,a()}finally{Blockly.Realtime.withinSync=!1}};\nBlockly.Realtime.placeBlockOnWorkspace_=function(a,b){Blockly.Realtime.doWithinSync_(function(){var c=Blockly.Xml.textToDom(a.xmlDom).firstChild;if(c=Blockly.Xml.domToBlock(Blockly.mainWorkspace,c,!0))b&&c.workspace.addTopBlock(c),(b||goog.array.contains(Blockly.Realtime.topBlocks_,c))&&Blockly.Realtime.moveBlock_(c)})};\nBlockly.Realtime.moveBlock_=function(a){if(!isNaN(a.relativeX)&&!isNaN(a.relativeY)){var b=Blockly.svgSize().width,c=a.getRelativeToSurfaceXY(),d=a.relativeX-c.x;a.moveBy(Blockly.RTL?b-d:d,a.relativeY-c.y)}};Blockly.Realtime.deleteBlock=function(a){Blockly.Realtime.doWithinSync_(function(){a.dispose(!0,!0,!0)})};\nBlockly.Realtime.loadBlocks_=function(){for(var a=Blockly.Realtime.blocksMap_.values(),b=0;b<a.length;b++){var c=parseInt(a[b].id,10);c>Blockly.getUidCounter()&&Blockly.setUidCounter(c+1)}a=Blockly.Realtime.topBlocks_;for(b=0;b<a.length;b++)c=a.get(b),Blockly.Realtime.placeBlockOnWorkspace_(c,!0)};\nBlockly.Realtime.blockChanged=function(a){if(a.workspace==Blockly.mainWorkspace){a=a.getRootBlock();var b=a.getRelativeToSurfaceXY(),c=!1,d=Blockly.Xml.blockToDom_(a);d.setAttribute(\"id\",a.id);var e=goog.dom.createDom(\"xml\");e.appendChild(d);d=Blockly.Xml.domToText(e);d!=a.xmlDom&&(c=!0,a.xmlDom=d);if(a.relativeX!=b.x||a.relativeY!=b.y)a.relativeX=b.x,a.relativeY=b.y,c=!0;c&&Blockly.Realtime.blocksMap_.set(a.id.toString(),a)}};\nBlockly.Realtime.onFileLoaded_=function(a){Blockly.Realtime.model_=a.getModel();Blockly.Realtime.blocksMap_=Blockly.Realtime.model_.getRoot().get(\"blocks\");Blockly.Realtime.topBlocks_=Blockly.Realtime.model_.getRoot().get(\"topBlocks\");Blockly.Realtime.model_.getRoot().addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED,Blockly.Realtime.onObjectChange_);Blockly.Realtime.blocksMap_.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED,Blockly.Realtime.onBlocksMapChange_);a=Blockly.Realtime.model_.getRoot().get(\"text\");\nvar b=document.getElementById(\"chatbox\");gapi.drive.realtime.databinding.bindString(a,b);b.disabled=!1;Blockly.Realtime.initUi_();Blockly.Realtime.loadBlocks_()};\nBlockly.Realtime.registerTypes_=function(){var a=gapi.drive.realtime.custom;a.registerType(Blockly.Block,\"Block\");Blockly.Block.prototype.id=a.collaborativeField(\"id\");Blockly.Block.prototype.type=a.collaborativeField(\"type\");Blockly.Block.prototype.xmlDom=a.collaborativeField(\"xmlDom\");Blockly.Block.prototype.relativeX=a.collaborativeField(\"relativeX\");Blockly.Block.prototype.relativeY=a.collaborativeField(\"relativeY\");a.setInitializer(Blockly.Block,Blockly.Block.prototype.initialize)};\nBlockly.Realtime.REAUTH_INTERVAL_IN_MILLISECONDS_=18E5;Blockly.Realtime.afterAuth_=function(){window.setTimeout(function(){Blockly.Realtime.realtimeLoader_.authorizer.authorize(Blockly.Realtime.afterAuth_)},Blockly.Realtime.REAUTH_INTERVAL_IN_MILLISECONDS_)};\nBlockly.Realtime.afterCreate_=function(a){var b=gapi.client.drive.permissions.insert({fileId:a,resource:{type:\"anyone\",role:\"writer\",value:\"default\",withLink:!0}});b.execute(function(c){c.error&&Blockly.Realtime.getUserDomain(a,function(c){b=gapi.client.drive.permissions.insert({fileId:a,resource:{type:\"domain\",role:\"writer\",value:c,withLink:!0}});b.execute(function(a){})})})};\nBlockly.Realtime.getUserDomain=function(a,b){gapi.client.drive.permissions.list({fileId:a}).execute(function(a){for(var d=0;d<a.items.length;d++){var e=a.items[d];if(\"owner\"==e.role){b(e.domain);break}}})};\nBlockly.Realtime.realtimeOptions_={clientId:\"922110111899.apps.googleusercontent.com\",authButtonElementId:\"authorizeButton\",initializeModel:Blockly.Realtime.initializeModel_,autoCreate:!0,defaultTitle:\"New Realtime Blockly File\",newFileMimeType:null,onFileLoaded:Blockly.Realtime.onFileLoaded_,registerTypes:Blockly.Realtime.registerTypes_,afterAuth:Blockly.Realtime.afterAuth_,afterCreate:Blockly.Realtime.afterCreate_};\nBlockly.Realtime.startRealtime=function(a){Blockly.Realtime.enabled_=!0;Blockly.Realtime.initUi_=a;Blockly.Realtime.realtimeLoader_=new rtclient.RealtimeLoader(Blockly.Realtime.realtimeOptions_);Blockly.Realtime.realtimeLoader_.start()};Blockly.Css={};Blockly.Css.inject=function(){var a=Blockly.Css.CONTENT.join(\"\\n\"),a=a.replace(/<<<PATH>>>/g,Blockly.mediaFilePath);goog.cssom.addCssText(a)};\nBlockly.Css.CONTENT=[\".blocklySvg {\",\"  background-color: transparent;\",\"  position: absolute;\",\"  cursor: move\",\"}\",\".blocklyWidgetDiv {\",\"  position: absolute;\",\"  display: none;\",\"  z-index: 999;\",\"}\",\".blocklyDraggable {\",\"  /* Hotspot coordinates are baked into the CUR file, but they are still\",\"     required in the CSS due to a Chrome bug.\",\"     http://code.google.com/p/chromium/issues/detail?id=1446 */\",\"  cursor: url(/legacy_media/handopen.cur) 8 5, auto;\",\"}\",\".blocklyResizeSE {\",\"  fill: #aaa;\",\n\"  cursor: se-resize;\",\"}\",\".blocklyResizeSW {\",\"  fill: #aaa;\",\"  cursor: sw-resize;\",\"}\",\".blocklyResizeLine {\",\"  stroke-width: 1;\",\"  stroke: #888;\",\"}\",\".blocklyPathPattern {\",\"  opacity: 0;\",\"  display: none;\",\"}\",\".togglePattern>.blocklyPathPattern {\",\"    display: block;\",\"}\",\".disablePattern>.blocklyPathPattern {\",\"  opacity: 0;\",\"  display: none !important;\",\"}\",\".blocklyHighlightedConnectionPathInline {\",\"  stroke-width: 2px;\",\"  stroke: white;\",\"  stroke-opacity: 1;\",\"  fill: white;\",\n\"  fill-opacity: 0.5;\",\"}\",\".blocklyHighlightedConnectionPath {\",\"  stroke-width: 2px;\",\"  stroke: #3a3737;\",\"  fill: none;\",\"}\",\".blocklyPathLight {\",\"  fill: none;\",\"  stroke-width: 0.5;\",\"  stroke-linecap: square;\",\"}\",\".blocklySelected>.blocklyPath {\",\"  stroke-width: 3px;\",\"  stroke: #798EB1;\",\"}\",\".blocklyActivated>.blocklyPath {\",\"  stroke-width: 2px;\",\"  stroke: #FF3939;\",\"}\",\".blocklyActivated>.blocklyPathLight {\",\"  display: none;\",\"}\",\".blocklySelected>.blocklyPathLight {\",\"  display: none;\",\n\"}\",\".blocklyDragging>.blocklyPath,\",\".blocklyDragging>.blocklyPathLight {\",\"  fill-opacity: 0.8;\",\"  stroke-opacity: 0.8;\",\"}\",\".blocklyDragging>.blocklyPathDark {\",\"  display: none;\",\"}\",\".blocklyDisabled>.blocklyPath {\",\"  fill-opacity: 0.50;\",\"  stroke-opacity: 0.50;\",\"}\",\".blocklyDisabled>.blocklyPathLight,\",\".blocklyDisabled>.blocklyPathDark {\",\"  display: none;\",\"}\",\".blocklyText {\",\"  cursor: default;\",\"  font-family: ng;\",\"  font-size: 9pt;\",\"  fill: #fff;\",\"}\",\".blocklyEditableText>.blocklyText {\",\n\"  fill: #000;\",\"}\",\".blocklyNonEditableText>text {\",\"  pointer-events: none;\",\"}\",\".blocklyNonEditableText>rect,\",\".blocklyEditableText>rect {\",\"  fill: #fff;\",\"  fill-opacity: 0;\",\"}\",\".blocklyNonEditableField>rect,\",\".blocklyEditableField>rect {\",\"  fill: #fff;\",\"  fill-opacity: 0.4;\",\"}\",\".blocklyNonEditableField>text,\",\".blocklyEditableField>text {\",\"  fill: #000;\",\"}\",\".blocklyNonEditableText>text,\",\".blocklyEditableText>text {\",\"  fill: #000;\",\"}\",\".blocklyEditableText:hover>rect {\",\"  stroke-width: 2;\",\n\"  stroke: #fff;\",\"}\",\"/*\",\" * Don't allow users to select text.  It gets annoying when trying to\",\" * drag a block and selected text moves instead.\",\" */\",\".blocklySvg text {\",\"  -moz-user-select: none;\",\"  -webkit-user-select: none;\",\"  user-select: none;\",\"  cursor: inherit;\",\"}\",\"\",\".blocklyHidden {\",\"  display: none;\",\"}\",\".blocklyFieldDropdown:not(.blocklyHidden) {\",\"  display: block;\",\"}\",\".blocklyTooltipBackground {\",\"  fill: #ffffc7;\",\"  stroke-width: 1px;\",\"  stroke: #d8d8d8;\",\"}\",\".blocklyTooltipShadow,\",\n\".blocklyContextMenuShadow,\",\".blocklyDropdownMenuShadow {\",\"  fill: #bbb;\",\"  filter: url(#blocklyShadowFilter);\",\"}\",\".blocklyTooltipText {\",\"  font-family: sans-serif;\",\"  font-size: 9pt;\",\"  fill: #000;\",\"}\",\"\",\".blocklyIconShield {\",\"  cursor: default;\",\"  fill: #00c;\",\"  stroke-width: 1px;\",\"  stroke: #ccc;\",\"}\",\".blocklyIconGroup:hover>.blocklyIconShield {\",\"  fill: #00f;\",\"  stroke: #fff;\",\"}\",\".blocklyIconGroup:hover>.blocklyIconMark {\",\"  fill: #fff;\",\"}\",\".blocklyIconMark {\",\"  cursor: default !important;\",\n\"  font-family: sans-serif;\",\"  font-size: 9pt;\",\"  font-weight: bold;\",\"  fill: #ccc;\",\"  text-anchor: middle;\",\"}\",\".blocklyWarningBody {\",\"}\",\".blocklyMinimalBody {\",\"  margin: 0;\",\"  padding: 0;\",\"}\",\".blocklyCommentTextarea {\",\"  margin: 0;\",\"  padding: 2px;\",\"  border: 0;\",\"  resize: none;\",\"  background-color: #ffc;\",\"}\",\".blocklyHtmlInput {\",\"  font-family: ng;\",\"  font-size: 9pt;\",\"  border: none;\",\"  outline: none;\",\"  line-height: normal;\",\"  width: 100%;\",\"}\",\".blocklyContextMenuBackground,\",\n\".blocklyMutatorBackground {\",\"  fill: #fff;\",\"  stroke-width: 1;\",\"  stroke: #ddd;\",\"}\",\".blocklyContextMenuOptions>.blocklyMenuDiv,\",\".blocklyContextMenuOptions>.blocklyMenuDivDisabled,\",\".blocklyDropdownMenuOptions>.blocklyMenuDiv {\",\"  fill: #fff;\",\"}\",\".blocklyDropdownMenuOptions>.blocklyMenuDiv {\",\"  cursor: default;\",\"}\",\".blocklyContextMenuOptions>.blocklyMenuDiv:hover>rect,\",\".blocklyDropdownMenuOptions>.blocklyMenuDiv:hover>rect {\",\"  fill: #57e;\",\"}\",\".blocklyMenuSelected>rect {\",\"  fill: #57e;\",\n\"}\",\".blocklyMenuText {\",\"  cursor: default !important;\",\"  font-family: ng;\",\"  font-size: 9pt; /* All context menu sizes are based on pixels. */\",\"  fill: #000;\",\"}\",\".blocklyContextMenuOptions>.blocklyMenuDiv:hover>.blocklyMenuText,\",\".blocklyDropdownMenuOptions>.blocklyMenuDiv:hover>.blocklyMenuText {\",\"  fill: #fff;\",\"}\",\".blocklyMenuSelected>.blocklyMenuText {\",\"  fill: #fff;\",\"}\",\".blocklyMenuDivDisabled>.blocklyMenuText {\",\"  fill: #ccc;\",\"}\",\".blocklyFlyoutBackground {\",\"  fill: #ddd;\",\"  fill-opacity: 0.8;\",\n\"}\",\".blocklyColourBackground {\",\"  fill: #666;\",\"}\",\".blocklyScrollbarBackground {\",\"  opacity: 0\",\"}\",\".blocklyScrollbarKnob {\",\"  fill: #000;\",\"  opacity: 0.35\",\"}\",\".blocklyScrollbarBackground:hover+.blocklyScrollbarKnob,\",\".blocklyScrollbarKnob:hover {\",\"  fill: #000;\",\"  opacity: 0.6\",\"}\",\".blocklyInvalidInput {\",\"  background: #faa;\",\"}\",\".blocklyAngleCircle {\",\"  stroke: #444;\",\"  stroke-width: 1;\",\"  fill: #ddd;\",\"  fill-opacity: 0.8;\",\"}\",\".blocklyAngleMarks {\",\"  stroke: #444;\",\"  stroke-width: 1;\",\n\"}\",\".blocklyAngleGauge {\",\"  fill: #f88;\",\"  fill-opacity: 0.8;  \",\"}\",\".blocklyAngleLine {\",\"  stroke: #f00;\",\"  stroke-width: 2;\",\"  stroke-linecap: round;\",\"}\",\"\",\"/* Category tree in Toolbox. */\",\".blocklyToolboxDiv {\",\"  background-color: #ddd;\",\"  display: none;\",\"  overflow-x: visible;\",\"  overflow-y: auto;\",\"  position: absolute;\",\"}\",\".blocklyTreeRoot {\",\"  padding: 4px 0;\",\"}\",\".blocklyTreeRoot:focus {\",\"  outline: none;\",\"}\",\".blocklyTreeRow {\",\"  line-height: 22px;\",\"  height: 22px;\",\n\"  padding-right: 1em;\",\"  white-space: nowrap;\",\"}\",'.blocklyToolboxDiv[dir=\"RTL\"] .blocklyTreeRow {',\"  padding-right: 0;\",\"  padding-left: 1em !important;\",\"}\",\".blocklyTreeRow:hover {\",\"  background-color: #e4e4e4;\",\"}\",\".blocklyTreeIcon {\",\"  height: 16px;\",\"  width: 16px;\",\"  vertical-align: middle;\",\"  background-image: url(<<<PATH>>>/media/tree.png);\",\"}\",\".blocklyTreeIconClosedLtr {\",\"  background-position: -32px -1px;\",\"}\",\".blocklyTreeIconClosedRtl {\",\"  background-position: 0px -1px;\",\n\"}\",\".blocklyTreeIconOpen {\",\"  background-position: -16px -1px;\",\"}\",\".blocklyTreeIconNone {\",\"  background-position: -48px -1px;\",\"}\",\".blocklyTreeSelected>.blocklyTreeIconClosedLtr {\",\"  background-position: -32px -17px;\",\"}\",\".blocklyTreeSelected>.blocklyTreeIconClosedRtl {\",\"  background-position: 0px -17px;\",\"}\",\".blocklyTreeSelected>.blocklyTreeIconOpen {\",\"  background-position: -16px -17px;\",\"}\",\".blocklyTreeSelected>.blocklyTreeIconNone {\",\"  background-position: -48px -17px;\",\"}\",\".blocklyTreeLabel {\",\n\"  cursor: default;\",\"  font-family: sans-serif;\",\"  font-size: 16px;\",\"  padding: 0 3px;\",\"  vertical-align: middle;\",\"}\",\".blocklyTreeSelected  {\",\"  background-color: #57e !important;\",\"}\",\".blocklyTreeSelected .blocklyTreeLabel {\",\"  color: #fff;\",\"}\",\".blocklyBlockMenuBtn {\",\"  cursor: pointer\",\"}\",\".blocklyBlockMenuBtnHighlight {\",\"  opacity: 0\",\"}\",\".blocklyBlockMenuBtnHighlight:hover {\",\"  opacity: 1\",\"}\",\".blocklyBlockMenuBtnPath {\",\"  fill: #eee\",\"}\",\".blocklyBlockMenuBtnPath:hover {\",\"  fill: #f4f4f4\",\n\"}\",\"\",\"/*\",\" * Copyright 2007 The Closure Library Authors. All Rights Reserved.\",\" *\",\" * Use of this source code is governed by the Apache License, Version 2.0.\",\" * See the COPYING file for details.\",\" */\",\"\",\"/* Author: pupius@google.com (Daniel Pupius) */\",\"\",\"/*\",\" Styles to make the colorpicker look like the old gmail color picker\",\" NOTE: without CSS scoping this will override styles defined in palette.css\",\"*/\",\".goog-palette {\",\"  outline: none;\",\"  cursor: default;\",\"}\",\"\",\".goog-palette-table {\",\n\"  border: 1px solid #666;\",\"  border-collapse: collapse;\",\"}\",\"\",\".goog-palette-cell {\",\"  height: 13px;\",\"  width: 15px;\",\"  margin: 0;\",\"  border: 0;\",\"  text-align: center;\",\"  vertical-align: middle;\",\"  border-right: 1px solid #666;\",\"  font-size: 1px;\",\"}\",\"\",\".goog-palette-colorswatch {\",\"  position: relative;\",\"  height: 13px;\",\"  width: 15px;\",\"  border: 1px solid #666;\",\"}\",\"\",\".goog-palette-cell-hover .goog-palette-colorswatch {\",\"  border: 1px solid #FFF;\",\"}\",\"\",\".goog-palette-cell-selected .goog-palette-colorswatch {\",\n\"  border: 1px solid #000;\",\"  color: #fff;\",\"}\",\"\",\".entryFunctionButton {\",\"  stroke: #555;\",\"  stroke-width: 3;\",\"  fill: transparent;\",\"  cursor: pointer;\",\"}\",\"\",\".entryFunctionButton:hover {\",\"  stroke: black;\",\"}\",\"\",\".entryFunctionButtonText {\",\"  font-family: ng !important;\",\"  font-size: 13 !important;\",\"  text-anchor: middle;\",\"  fill: black;\",\"  cursor: pointer !important;\",\"}\",\"\"];Blockly.WidgetDiv={};Blockly.WidgetDiv.DIV=null;Blockly.WidgetDiv.field_=null;Blockly.WidgetDiv.dispose_=null;Blockly.WidgetDiv.show=function(a,b){\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\");Blockly.WidgetDiv.hide();Blockly.WidgetDiv.field_=a;Blockly.WidgetDiv.dispose_=b;Blockly.WidgetDiv.initialValue=Blockly.WidgetDiv.field_.text_;Blockly.WidgetDiv.DIV.style.display=\"block\"};\nBlockly.WidgetDiv.hide=function(){Blockly.WidgetDiv.field_&&(\"object\"==typeof Entry&&Blockly.WidgetDiv.initialValue!=Blockly.WidgetDiv.field_.text_&&Entry.dispatchEvent(\"cancelLastCommand\"),Blockly.WidgetDiv.DIV.style.display=\"none\",Blockly.WidgetDiv.dispose_&&Blockly.WidgetDiv.dispose_(),Blockly.WidgetDiv.field_=null,Blockly.WidgetDiv.dispose_=null,goog.dom.removeChildren(Blockly.WidgetDiv.DIV))};Blockly.WidgetDiv.hideIfField=function(a){Blockly.WidgetDiv.field_==a&&Blockly.WidgetDiv.hide()};Blockly.inject=function(a,b){if(!goog.dom.contains(document,a))throw\"Error: container is not in current document.\";b&&goog.mixin(Blockly,Blockly.parseOptions_(b));Blockly.createDom_(a);Blockly.init_()};\nBlockly.parseOptions_=function(a){var b=!!a.readOnly;if(b)var c=!1,d=!1,e=!1,f=null;else{if(f=a.toolbox){\"string\"!=typeof f&&\"undefined\"==typeof XSLTProcessor&&(f=f.outerHTML);\"string\"==typeof f&&(f=Blockly.Xml.textToDom(f));c=!1;try{c=!!f.getElementsByTagName(\"category\").length}catch(k){c=!1}}else f=null,c=!1;d=a.trashcan;void 0===d&&(d=c);var g=a.blockmenu;!g instanceof HTMLElement&&(g=!1);e=a.collapse;void 0===e&&(e=c)}var h=a.scrollbars;void 0===h&&(h=!0);return{RTL:!!a.rtl,collapse:e,readOnly:b,\nmaxBlocks:a.maxBlocks||Infinity,pathToBlockly:a.path||\"./\",hasCategories:c,hasScrollbars:h,hasTrashcan:d,hasBlockMenu:g,languageTree:f,mediaFilePath:a.mediaFilePath||\"./\"}};\nBlockly.createDom_=function(a){a.setAttribute(\"dir\",\"LTR\");goog.ui.Component.setDefaultRightToLeft(Blockly.RTL);Blockly.Css.inject();var b=Blockly.createSvgElement(\"svg\",{xmlns:\"http://www.w3.org/2000/svg\",\"xmlns:html\":\"http://www.w3.org/1999/xhtml\",\"xmlns:xlink\":\"http://www.w3.org/1999/xlink\",version:\"1.1\",\"class\":\"blocklySvg\"},null),c=Blockly.createSvgElement(\"defs\",{},b),d,e;d=Blockly.createSvgElement(\"filter\",{id:\"blocklyEmboss\"},c);Blockly.createSvgElement(\"feGaussianBlur\",{\"in\":\"SourceAlpha\",\nstdDeviation:1,result:\"blur\"},d);e=Blockly.createSvgElement(\"feSpecularLighting\",{\"in\":\"blur\",surfaceScale:1,specularConstant:.5,specularExponent:10,\"lighting-color\":\"white\",result:\"specOut\"},d);Blockly.createSvgElement(\"fePointLight\",{x:-5E3,y:-1E4,z:2E4},e);Blockly.createSvgElement(\"feComposite\",{\"in\":\"specOut\",in2:\"SourceAlpha\",operator:\"in\",result:\"specOut\"},d);Blockly.createSvgElement(\"feComposite\",{\"in\":\"SourceGraphic\",in2:\"specOut\",operator:\"arithmetic\",k1:0,k2:1,k3:1,k4:0},d);d=Blockly.createSvgElement(\"filter\",\n{id:\"blocklyTrashcanShadowFilter\"},c);Blockly.createSvgElement(\"feGaussianBlur\",{\"in\":\"SourceAlpha\",stdDeviation:2,result:\"blur\"},d);Blockly.createSvgElement(\"feOffset\",{\"in\":\"blur\",dx:1,dy:1,result:\"offsetBlur\"},d);d=Blockly.createSvgElement(\"feMerge\",{},d);Blockly.createSvgElement(\"feMergeNode\",{\"in\":\"offsetBlur\"},d);Blockly.createSvgElement(\"feMergeNode\",{\"in\":\"SourceGraphic\"},d);d=Blockly.createSvgElement(\"filter\",{id:\"blocklyShadowFilter\"},c);Blockly.createSvgElement(\"feGaussianBlur\",{stdDeviation:2},\nd);d=Blockly.createSvgElement(\"pattern\",{id:\"blocklyDisabledPattern\",patternUnits:\"userSpaceOnUse\",width:10,height:10},c);Blockly.createSvgElement(\"rect\",{width:10,height:10,fill:\"#aaa\"},d);Blockly.createSvgElement(\"path\",{d:\"M 0 0 L 10 10 M 10 0 L 0 10\",stroke:\"#cc0\"},d);for(d=1;5>d;d++)e=Blockly.createSvgElement(\"pattern\",{id:\"blockPattern\"+d,patternUnits:\"userSpaceOnUse\",width:125,height:33,x:0,y:0},c),e=Blockly.createSvgElement(\"image\",{width:125,height:33,x:0,y:0},e),e.setAttributeNS(\"http://www.w3.org/1999/xlink\",\n\"xlink:href\",Blockly.mediaFilePath+\"block_pattern_\"+d+\".png\");Blockly.mainWorkspace=new Blockly.Workspace(Blockly.getMainWorkspaceMetrics_,Blockly.setMainWorkspaceMetrics_);b.appendChild(Blockly.mainWorkspace.createDom());Blockly.mainWorkspace.maxBlocks=Blockly.maxBlocks;Blockly.readOnly||(Blockly.hasCategories?Blockly.Toolbox.createDom(b,a):(Blockly.hasBlockMenu&&(c=new Blockly.BlockMenu(Blockly.hasBlockMenu),Blockly.mainWorkspace.blockMenu=c,Blockly.bindEvent_(c.menuView_,\"wheel\",c,Blockly.onMouseWheelFlyout_)),\nBlockly.mainWorkspace.flyout_=new Blockly.Flyout,c=Blockly.mainWorkspace.flyout_,d=c.createDom(),c.init(Blockly.mainWorkspace,!0),Blockly.bindEvent_(d,\"wheel\",c,Blockly.onMouseWheelFlyout_),c.autoClose=!1,goog.dom.insertSiblingAfter(d,Blockly.mainWorkspace.svgGroup_),Blockly.addChangeListener(function(){})));Blockly.Tooltip&&b.appendChild(Blockly.Tooltip.createDom());!Blockly.readOnly&&Blockly.FieldDropdown&&(Blockly.fieldDropdownDom=Blockly.FieldDropdown.createDom(),b.appendChild(Blockly.fieldDropdownDom));\n!Blockly.readOnly&&Blockly.FieldKeydownInput&&(Blockly.fieldKeydownDom=Blockly.FieldKeydownInput.createDom(),b.appendChild(Blockly.fieldKeydownDom));Blockly.ContextMenu&&Blockly.ContextMenu&&b.appendChild(Blockly.ContextMenu.createDom());a.appendChild(b);Blockly.bindEvent_(b,\"mousedown\",this,Blockly.hideChaff);Blockly.bindEvent_(b,\"wheel\",this,Blockly.onMouseWheel_);Blockly.svg=b;Blockly.svgResize();Blockly.WidgetDiv.DIV=goog.dom.createDom(\"div\",\"blocklyWidgetDiv\");document.body.appendChild(Blockly.WidgetDiv.DIV)};\nBlockly.init_=function(){if(goog.userAgent.WEBKIT){var a=Blockly.createSvgElement(\"path\",{d:\"m 0,0 c 0,-5 0,-5 0,0 H 50 V 50 z\"},Blockly.svg);50<a.getBBox().height&&(Blockly.BROKEN_CONTROL_POINTS=!0);Blockly.svg.removeChild(a)}Blockly.bindEvent_(Blockly.svg,\"mousedown\",null,Blockly.onMouseDown_);Blockly.bindEvent_(Blockly.svg,\"mousemove\",null,Blockly.onMouseMove_);Blockly.bindEvent_(Blockly.svg,\"contextmenu\",null,Blockly.onContextMenu_);Blockly.documentEventsBound_||(Blockly.bindEvent_(window,\"resize\",\ndocument,Blockly.svgResize),Blockly.bindEvent_(document,\"mouseup\",null,Blockly.onMouseUp_),Blockly.bindEvent_(document,\"keydown\",null,Blockly.onKeyDown_),goog.userAgent.IPAD&&Blockly.bindEvent_(window,\"orientationchange\",document,function(){Blockly.fireUiEvent(window,\"resize\")},!1),Blockly.documentEventsBound_=!0);Blockly.languageTree&&(Blockly.hasCategories?Blockly.Toolbox.init():(Blockly.mainWorkspace.flyout_.init(Blockly.mainWorkspace,!0),Blockly.mainWorkspace.flyout_.show(Blockly.languageTree.childNodes),\nBlockly.mainWorkspace.scrollX=Blockly.mainWorkspace.flyout_.width_,a=\"translate(\"+Blockly.mainWorkspace.scrollX+\", 0)\",Blockly.mainWorkspace.getCanvas().setAttribute(\"transform\",a),Blockly.mainWorkspace.getBubbleCanvas().setAttribute(\"transform\",a)));Blockly.hasScrollbars&&(Blockly.mainWorkspace.scrollbar=new Blockly.ScrollbarPair(Blockly.mainWorkspace),Blockly.mainWorkspace.scrollbar.resize());Blockly.mainWorkspace.addTrashcan()};Blockly.utils={};Blockly.addClass_=function(a,b){var c=a.getAttribute(\"class\")||\"\";-1==(\" \"+c+\" \").indexOf(\" \"+b+\" \")&&(c&&(c+=\" \"),a.setAttribute(\"class\",c+b))};Blockly.removeClass_=function(a,b){var c=a.getAttribute(\"class\");if(-1!=(\" \"+c+\" \").indexOf(\" \"+b+\" \")){for(var c=c.split(/\\s+/),d=0;d<c.length;d++)c[d]&&c[d]!=b||(c.splice(d,1),d--);c.length?a.setAttribute(\"class\",c.join(\" \")):a.removeAttribute(\"class\")}};\nBlockly.bindEvent_=function(a,b,c,d){var e=[],f;if(!a.addEventListener)throw\"Element is not a DOM node with addEventListener.\";f=function(a){d.apply(c,arguments)};a.addEventListener(b,f,!1);e.push([a,b,f]);b in Blockly.bindEvent_.TOUCH_MAP&&(f=function(a){if(1==a.changedTouches.length){var b=a.changedTouches[0];a.clientX=b.clientX;a.clientY=b.clientY}d.apply(c,arguments);if(Entry&&\"phone\"==Entry.type){var b=$(window).scrollTop(),e=$(Entry.playground.blocklyView_),f=e.offset();a.clientY>f.top-b&&a.clientY<\nf.top-b+e.height()&&a.clientX>f.left&&a.clientX<f.left+e.width()&&a.preventDefault()}else a.preventDefault()},a.addEventListener(Blockly.bindEvent_.TOUCH_MAP[b],f,!1),e.push([a,Blockly.bindEvent_.TOUCH_MAP[b],f]));return e};Blockly.bindEvent_.TOUCH_MAP={};\"ontouchstart\"in document.documentElement&&(Blockly.bindEvent_.TOUCH_MAP={mousedown:\"touchstart\",mousemove:\"touchmove\",mouseup:\"touchend\"});Blockly.unbindEvent_=function(a){for(;a.length;){var b=a.pop(),c=b[2];b[0].removeEventListener(b[1],c,!1)}return c};\nBlockly.fireUiEvent=function(a,b){var c=document;if(c.createEvent)c=c.createEvent(\"UIEvents\"),c.initEvent(b,!0,!0),a.dispatchEvent(c);else if(c.createEventObject)c=c.createEventObject(),a.fireEvent(\"on\"+b,c);else throw\"FireEvent: No event creation mechanism.\";};Blockly.noEvent=function(a){a.preventDefault();a.stopPropagation()};\nBlockly.getRelativeXY_=function(a){var b={x:0,y:0},c=a.getAttribute(\"x\");c&&(b.x=parseInt(c,10));if(c=a.getAttribute(\"y\"))b.y=parseInt(c,10);if(a=(a=a.getAttribute(\"transform\"))&&a.match(/translate\\(\\s*([-\\d.]+)([ ,]\\s*([-\\d.]+)\\s*\\))?/))b.x+=parseInt(a[1],10),a[3]&&(b.y+=parseInt(a[3],10));return b};\nBlockly.getSvgXY_=function(a,b){var c=0,d=0;if(Blockly.mainWorkspace.blockMenu){do{var e=Blockly.getRelativeXY_(a),c=c+e.x,d=d+e.y;a=a.parentNode}while(a&&\"SVG\"!=a.tagName.toUpperCase())}else{do e=Blockly.getRelativeXY_(a),c+=e.x,d+=e.y,a=a.parentNode;while(a&&a!=Blockly.svg)}return{x:c,y:d}};Blockly.getAbsoluteXY_=function(a,b){var c=Blockly.getSvgXY_(a);return Blockly.convertCoordinates(c.x,c.y,!1,b)};\nBlockly.createSvgElement=function(a,b,c){a=document.createElementNS(Blockly.SVG_NS,a);for(var d in b)a.setAttribute(d,b[d]);document.body.runtimeStyle&&(a.runtimeStyle=a.currentStyle=a.style);c&&c.appendChild(a);return a};Blockly.isRightButton=function(a){return 2==a.button||a.ctrlKey};Blockly.isMiddleButton=function(a){return 1==a.button};\nBlockly.convertCoordinates=function(a,b,c,d){c&&(a-=window.scrollX||window.pageXOffset,b-=window.scrollY||window.pageYOffset);d=d?d:Blockly.svg;var e=d.createSVGPoint();e.x=a;e.y=b;a=d.getScreenCTM();c&&(a=a.inverse());e=e.matrixTransform(a);c||(e.x+=window.scrollX||window.pageXOffset,e.y+=window.scrollY||window.pageYOffset);return e};Blockly.mouseToSvg=function(a){return Blockly.convertCoordinates(a.clientX+(window.scrollX||window.pageXOffset),a.clientY+(window.scrollY||window.pageYOffset),!0)};\nBlockly.shortestStringLength=function(a){if(!a.length)return 0;for(var b=a[0].length,c=1;c<a.length;c++)b=Math.min(b,a[c].length);return b};Blockly.commonWordPrefix=function(a,b){if(!a.length)return 0;if(1==a.length)return a[0].length;for(var c=0,d=b||Blockly.shortestStringLength(a),e=0;e<d;e++){for(var f=a[0][e],g=1;g<a.length;g++)if(f!=a[g][e])return c;\" \"==f&&(c=e+1)}for(g=1;g<a.length;g++)if((f=a[g][e])&&\" \"!=f)return c;return d};\nBlockly.commonWordSuffix=function(a,b){if(!a.length)return 0;if(1==a.length)return a[0].length;for(var c=0,d=b||Blockly.shortestStringLength(a),e=0;e<d;e++){for(var f=a[0].substr(-e-1,1),g=1;g<a.length;g++)if(f!=a[g].substr(-e-1,1))return c;\" \"==f&&(c=e+1)}for(g=1;g<a.length;g++)if((f=a[g].charAt(a[g].length-e-1))&&\" \"!=f)return c;return d};Blockly.isNumber=function(a){return!!a.match(/^\\s*-?\\d+(\\.\\d+)?\\s*$/)};\nBlockly.getComputedTextLength=function(a){var b=a.innerHTML,c=Blockly.textLengthCache[b];c||(c=a.getComputedTextLength(),Blockly.textLengthCache[b]=c);return c};Blockly.isChild=function(a,b){if(null!=b)for(;b.parentNode;)if((b=b.parentNode)==a)return!0;return!1};Blockly.pathToBlockly=\"./\";Blockly.SVG_NS=\"http://www.w3.org/2000/svg\";Blockly.HTML_NS=\"http://www.w3.org/1999/xhtml\";Blockly.HSV_SATURATION=.45;Blockly.HSV_VALUE=.65;Blockly.makeColour=function(a){return\"number\"==typeof a?goog.color.hsvToHex(a,Blockly.HSV_SATURATION,256*Blockly.HSV_VALUE):a};Blockly.INPUT_VALUE=1;Blockly.OUTPUT_VALUE=2;Blockly.NEXT_STATEMENT=3;Blockly.PREVIOUS_STATEMENT=4;Blockly.DUMMY_INPUT=5;Blockly.ALIGN_LEFT=-1;Blockly.ALIGN_CENTRE=0;Blockly.ALIGN_RIGHT=1;\nBlockly.enableBlockAnimation=!(goog.userAgent.SAFARI&&!window.chrome);Blockly.OPPOSITE_TYPE=[];Blockly.OPPOSITE_TYPE[Blockly.INPUT_VALUE]=Blockly.OUTPUT_VALUE;Blockly.OPPOSITE_TYPE[Blockly.OUTPUT_VALUE]=Blockly.INPUT_VALUE;Blockly.OPPOSITE_TYPE[Blockly.NEXT_STATEMENT]=Blockly.PREVIOUS_STATEMENT;Blockly.OPPOSITE_TYPE[Blockly.PREVIOUS_STATEMENT]=Blockly.NEXT_STATEMENT;Blockly.SOUNDS_=Object.create(null);Blockly.activated=null;Blockly.selected=null;Blockly.readOnly=!1;\nBlockly.highlightedConnection_=null;Blockly.localConnection_=null;Blockly.DRAG_RADIUS=5;Blockly.SNAP_RADIUS=15;Blockly.SNAP_RADIUS_ENTRY=25;Blockly.BUMP_DELAY=250;Blockly.COLLAPSE_CHARS=30;Blockly.TEXT_INPUT_MAX_LENGTH=20;Blockly.primitiveTypes=\"NUMBER TRUE FALSE TEXT FUNCTION_PARAM_BOOLEAN FUNCTION_PARAM_STRING TRUE_UN\".split(\" \");Blockly.mainWorkspace=null;Blockly.clipboard_=null;Blockly.textLengthCache={};Blockly.svgSize=function(){return{width:Blockly.svg.cachedWidth_,height:Blockly.svg.cachedHeight_}};\nBlockly.svgResize=function(){var a=Blockly.svg,b=a.parentNode,c=b.offsetWidth-3,b=b.offsetHeight;a.cachedWidth_!=c&&(a.setAttribute(\"width\",c+\"px\"),a.cachedWidth_=c);a.cachedHeight_!=b&&(a.setAttribute(\"height\",b+\"px\"),a.cachedHeight_=b);Blockly.mainWorkspace.scrollbar&&Blockly.mainWorkspace.scrollbar.resize()};\nBlockly.onMouseDown_=function(a){Blockly.svgResize();Blockly.terminateDrag_();var b=a.target&&a.target.nodeName&&\"svg\"==a.target.nodeName.toLowerCase();!Blockly.readOnly&&Blockly.selected&&b&&Blockly.selected.unselect();Blockly.isRightButton(a)?Blockly.ContextMenu&&Blockly.showContextMenu_(Blockly.mouseToSvg(a)):(Blockly.readOnly||b)&&Blockly.mainWorkspace.scrollbar&&(Blockly.mainWorkspace.dragMode=!0,Blockly.mainWorkspace.startDragMouseX=a.clientX,Blockly.mainWorkspace.startDragMouseY=a.clientY,\nBlockly.mainWorkspace.startDragMetrics=Blockly.mainWorkspace.getMetrics(),Blockly.mainWorkspace.startScrollX=Blockly.mainWorkspace.scrollX,Blockly.mainWorkspace.startScrollY=Blockly.mainWorkspace.scrollY)};Blockly.onMouseUp_=function(a){Blockly.setCursorHand_(!1);Blockly.mainWorkspace.dragMode=!1};\nBlockly.onMouseMove_=function(a){var b=Blockly.mainWorkspace.scrollbar.vScroll;Blockly.mainWorkspace.scrollbar.hScroll.svgGroup_.setAttribute(\"opacity\",\"1\");b.svgGroup_.setAttribute(\"opacity\",\"1\");if(Blockly.mainWorkspace.dragMode){Blockly.removeAllRanges();var b=Blockly.mainWorkspace.startDragMetrics,c=Blockly.mainWorkspace.startScrollX+(a.clientX-Blockly.mainWorkspace.startDragMouseX);a=Blockly.mainWorkspace.startScrollY+(a.clientY-Blockly.mainWorkspace.startDragMouseY);c=Math.min(c,-b.contentLeft);\na=Math.min(a,-b.contentTop);c=Math.max(c,b.viewWidth-b.contentLeft-b.contentWidth);a=Math.max(a,b.viewHeight-b.contentTop-b.contentHeight);Blockly.mainWorkspace.scrollbar.set(-c-b.contentLeft,-a-b.contentTop)}};\nBlockly.onMouseWheel_=function(a){a.preventDefault();Blockly.removeAllRanges();Blockly.hideChaff();var b=a.wheelDeltaX||-a.deltaX,c=a.wheelDeltaY||-a.deltaY;a=Blockly.mainWorkspace.getMetrics();Blockly.mainWorkspace.startScrollX=Blockly.mainWorkspace.scrollX;Blockly.mainWorkspace.startScrollY=Blockly.mainWorkspace.scrollY;b=Blockly.mainWorkspace.startScrollX+b;c=Blockly.mainWorkspace.startScrollY+c;b=Math.min(b,-a.contentLeft);c=Math.min(c,-a.contentTop);b=Math.max(b,a.viewWidth-a.contentLeft-a.contentWidth);\nc=Math.max(c,a.viewHeight-a.contentTop-a.contentHeight);Blockly.mainWorkspace.scrollbar.set(-b-a.contentLeft,-c-a.contentTop)};\nBlockly.onMouseWheelFlyout_=function(a){a.stopPropagation();a.preventDefault();Blockly.removeAllRanges();var b=this.scrollbar_,c=a.wheelDeltaY||-a.deltaY;a=this.getMetrics_();b.startScrollY=parseFloat(this.scrollbar_.svgKnob_.getAttribute(\"y\"));c=parseFloat(-b.startScrollY)+c;c=Math.min(c,-a.contentTop);c=Math.max(c,a.viewHeight-a.contentTop-a.contentHeight);b.svgKnob_.setAttribute(this.horizontal_?\"x\":\"y\",b.constrainKnob_(-c-a.contentTop));b.onScroll_()};\nBlockly.onKeyDown_=function(a){var b=Blockly.selected;if(!Blockly.isTargetInput_(a)&&27!=a.keyCode)if(8==a.keyCode||46==a.keyCode)try{if(b&&b.isDeletable()&&!b.isInFlyout){Blockly.hideChaff();var c=b.type.toUpperCase();-1<Blockly.primitiveTypes.indexOf(c)&&b.getParent()||b.dispose(!0,!0);\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\")}}finally{a.preventDefault()}else if(a.altKey||a.ctrlKey||a.metaKey)b&&b.isDeletable()&&b.workspace==Blockly.mainWorkspace&&(Blockly.hideChaff(),67==\na.keyCode?Blockly.copy_(b):88==a.keyCode&&(Blockly.copy_(b),b.dispose(!0,!0))),\"object\"==typeof Entry&&Entry.Func&&Entry.Func.workspace&&b&&b.isDeletable()&&b.workspace==Entry.Func.workspace&&(Blockly.hideChaff(),67==a.keyCode?Blockly.copy_(b):88==a.keyCode&&(Blockly.copy_(b),b.dispose(!0,!0))),86==a.keyCode&&Blockly.clipboard_&&(Entry&&Entry.Func&&Entry.Func.workspace&&Entry.Func.workspace.visible?(a=Blockly.clipboard_,a.setAttribute(\"isForFunc\",\"true\"),Entry.Func.workspace.paste(a)):Blockly.mainWorkspace.paste(Blockly.clipboard_))};\nBlockly.terminateDrag_=function(){Blockly.Block.terminateDrag_();Blockly.Flyout.terminateDrag_();Blockly.mainWorkspace.blockMenu&&Blockly.BlockMenu.terminateDrag_()};Blockly.copy_=function(a){var b=Blockly.Xml.blockToDom_(a);a=a.getRelativeToSurfaceXY();b.setAttribute(\"x\",Blockly.RTL?-a.x:a.x);b.setAttribute(\"y\",a.y);Blockly.clipboard_=b};\nBlockly.showContextMenu_=function(a){if(!Blockly.readOnly){var b=[];if(Blockly.collapse){for(var c=!1,d=!1,e=Blockly.mainWorkspace.getTopBlocks(!1),f=0;f<e.length;f++)e[f].isCollapsed()?c=!0:d=!0;d={enabled:d};d.text=Blockly.Msg.COLLAPSE_ALL;d.callback=function(){for(var a=0;a<e.length;a++)e[a].setCollapsed(!0)};b.push(d);c={enabled:c};c.text=Blockly.Msg.EXPAND_ALL;c.callback=function(){for(var a=0;a<e.length;a++)e[a].setCollapsed(!1)};b.push(c)}c={text:Lang.Blocks.Paste_blocks,enabled:!0,callback:function(){var a=\nBlockly.clipboard_;\"object\"===typeof Entry&&Entry&&Entry.Func&&Entry.Func.workspace&&Entry.Func.workspace.visible?(a.setAttribute(\"isForFunc\",\"true\"),Entry.Func.workspace.paste(a)):\"object\"===typeof Ntry&&Ntry&&Ntry.Func&&Ntry.Func.workspace&&Ntry.Func.workspace.visible?a.setAttribute(\"isForFunc\",\"true\"):Blockly.mainWorkspace.paste(Blockly.clipboard_);\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\")}};d={text:Lang.Blocks.Clear_all_blocks,enabled:!0,callback:function(){var a;\"object\"===\ntypeof Entry&&Entry&&Entry.Func&&Entry.Func.workspace&&Entry.Func.workspace.visible?a=Entry.Func.workspace.getAllBlocks():\"object\"===typeof Ntry&&Ntry&&Ntry.Func&&Ntry.Func.workspace&&Ntry.Func.workspace.visible||(a=Blockly.mainWorkspace.getAllBlocks());for(var b=a.length-1;0<=b;b--)a[b].deletable_&&a[b].dispose();\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\")}};Blockly.clipboard_||(c.enabled=!1);b.push(c);b.push({text:\"\\ucf54\\ub4dc \\uc815\\ub9ac\\ud558\\uae30\",enabled:!0,callback:function(){Blockly.mainWorkspace.organizeBlocks();\n\"object\"==typeof Entry&&Entry.dispatchEvent(\"entryBlocklyChanged\");\"object\"==typeof Ntry&&Entry.dispatchEvent(\"ntryBlocklyChanged\")}});b.push(d);Blockly.ContextMenu.show(a,b)}};Blockly.onContextMenu_=function(a){!Blockly.isTargetInput_(a)&&Blockly.ContextMenu&&a.preventDefault()};\nBlockly.hideChaff=function(a){Blockly.Tooltip&&Blockly.Tooltip.hide();Blockly.ContextMenu&&Blockly.ContextMenu.hide();Blockly.FieldDropdown&&Blockly.FieldDropdown.hide();Blockly.FieldKeydownInput&&Blockly.FieldKeydownInput.hide();Blockly.WidgetDiv.hide();!a&&Blockly.Toolbox.flyout_&&Blockly.Toolbox.flyout_.autoClose&&Blockly.Toolbox.clearSelection()};\nBlockly.removeAllRanges=function(){if(window.getSelection){var a=window.getSelection();a&&a.removeAllRanges&&(a.removeAllRanges(),window.setTimeout(function(){window.getSelection().removeAllRanges()},0))}};Blockly.isTargetInput_=function(a){return\"textarea\"==a.target.type||\"text\"==a.target.type};Blockly.loadAudio_=function(a,b){if(window.Audio&&a.length)for(;0<a.length;){var c=a[0],d=Blockly.pathToBlockly+c,c=c.match(/\\/([^.]+)./)[1];createjs.Sound.registerSound(d,c,4);break}};\nBlockly.playAudio=function(a,b){createjs.Sound.play(a)};Blockly.setCursorHand_=function(a){if(!Blockly.readOnly){var b=\"\";a&&(b=\"url(\"+Blockly.pathToBlockly+\"media/handclosed.cur) 7 3, auto\");Blockly.selected&&(Blockly.selected.getSvgRoot().style.cursor=b);Blockly.svg.style.cursor=b}};\nBlockly.getMainWorkspaceMetrics_=function(){var a=Blockly.svgSize();a.width-=Blockly.Toolbox.width;var b=a.width-Blockly.Scrollbar.scrollbarThickness,c=a.height-Blockly.Scrollbar.scrollbarThickness;try{var d=Blockly.mainWorkspace.getCanvas().getBBox()}catch(g){return null}if(Blockly.mainWorkspace.scrollbar)var e=Math.min(d.x-b/2,d.x+d.width-b),b=Math.max(d.x+d.width+b/2,d.x+b),f=Math.min(d.y-c/2,d.y+d.height-c),c=Math.max(d.y+d.height+c/2,d.y+c);else e=d.x,b=e+d.width,f=d.y,c=f+d.height;return{viewHeight:a.height,\nviewWidth:a.width,contentHeight:c-f,contentWidth:b-e,viewTop:-Blockly.mainWorkspace.scrollY,viewLeft:-Blockly.mainWorkspace.scrollX,contentTop:f,contentLeft:e,absoluteTop:0,absoluteLeft:Blockly.RTL?0:Blockly.Toolbox.width}};\nBlockly.getGenralWorkspaceMetricsFunc_=function(a){return function(){var b=Blockly.svgSize();b.width-=Blockly.Toolbox.width;var c=b.width-Blockly.Scrollbar.scrollbarThickness,d=b.height-Blockly.Scrollbar.scrollbarThickness;try{var e=a.getCanvas().getBBox()}catch(h){return null}if(a.scrollbar)var f=Math.min(e.x-c/2,e.x+e.width-c),c=Math.max(e.x+e.width+c/2,e.x+c),g=Math.min(e.y-d/2,e.y+e.height-d),d=Math.max(e.y+e.height+d/2,e.y+d);else f=e.x,c=f+e.width,g=e.y,d=g+e.height;return{viewHeight:b.height,\nviewWidth:b.width,contentHeight:d-g,contentWidth:c-f,viewTop:-a.scrollY,viewLeft:-a.scrollX,contentTop:g,contentLeft:f,absoluteTop:0,absoluteLeft:Blockly.RTL?0:Blockly.Toolbox.width}}};\nBlockly.setMainWorkspaceMetrics_=function(a){if(!Blockly.mainWorkspace.scrollbar)throw\"Attempt to set main workspace scroll without scrollbars.\";var b=Blockly.getMainWorkspaceMetrics_();goog.isNumber(a.x)&&(Blockly.mainWorkspace.scrollX=-b.contentWidth*a.x-b.contentLeft);goog.isNumber(a.y)&&(Blockly.mainWorkspace.scrollY=-b.contentHeight*a.y-b.contentTop);a=\"translate(\"+(Blockly.mainWorkspace.scrollX+b.absoluteLeft)+\",\"+(Blockly.mainWorkspace.scrollY+b.absoluteTop)+\")\";Blockly.mainWorkspace.getCanvas().setAttribute(\"transform\",\na);Blockly.mainWorkspace.getBubbleCanvas().setAttribute(\"transform\",a)};\nBlockly.setGeneralWorkspaceMetricsFunc_=function(a){return function(b){if(!a.scrollbar)throw\"Attempt to set main workspace scroll without scrollbars.\";var c=Blockly.getGenralWorkspaceMetricsFunc_(a)();goog.isNumber(b.x)&&(a.scrollX=-c.contentWidth*b.x-c.contentLeft);goog.isNumber(b.y)&&(a.scrollY=-c.contentHeight*b.y-c.contentTop);b=\"translate(\"+(a.scrollX+c.absoluteLeft)+\",\"+(a.scrollY+c.absoluteTop)+\")\";a.getCanvas().setAttribute(\"transform\",b);a.getBubbleCanvas().setAttribute(\"transform\",b)}};\nBlockly.addChangeListener=function(a){return Blockly.bindEvent_(Blockly.mainWorkspace.getCanvas(),\"blocklyWorkspaceChange\",null,a)};Blockly.removeChangeListener=function(a){Blockly.unbindEvent_(a)};Blockly.getMainWorkspace=function(){return Blockly.mainWorkspace};window.Blockly=Blockly;Blockly.getMainWorkspace=Blockly.getMainWorkspace;Blockly.addChangeListener=Blockly.addChangeListener;Blockly.removeChangeListener=Blockly.removeChangeListener;\n"
  },
  {
    "path": "extern/blockly/blockly_uncompressed.js",
    "content": "// Do not edit this file; automatically generated by build.py.\n\"use strict\";\n\nwindow.BLOCKLY_DIR = (function() {\n  // Find name of current directory.\n  var scripts = document.getElementsByTagName('script');\n  var re = new RegExp('(.+)[\\/]blockly_uncompressed\\.js$');\n  for (var x = 0, script; script = scripts[x]; x++) {\n    var match = re.exec(script.src);\n    if (match) {\n      return match[1];\n    }\n  }\n  alert('Could not detect Blockly\\'s directory name.');\n  return '';\n})();\n\nwindow.BLOCKLY_BOOT = function() {\n// Execute after Closure has loaded.\nif (!window.goog) {\n  alert('Error: Closure not found.  Read this:\\n' +\n        'http://code.google.com/p/blockly/wiki/Closure\\n');\n}\n\n// Build map of all dependencies (used and unused).\nvar dir = window.BLOCKLY_DIR.match(/[^\\/]+$/)[0];\ngoog.addDependency(\"../../../\" + dir + \"/core/block.js\", ['Blockly.Block'], ['Blockly.BlockSvg', 'Blockly.Blocks', 'Blockly.Comment', 'Blockly.Connection', 'Blockly.ContextMenu', 'Blockly.Input', 'Blockly.Msg', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.Workspace', 'Blockly.Xml', 'goog.asserts', 'goog.string', 'goog.Timer', 'goog.array']);\ngoog.addDependency(\"../../../\" + dir + \"/core/block_menu.js\", ['Blockly.BlockMenu'], ['Blockly.Workspace']);\ngoog.addDependency(\"../../../\" + dir + \"/core/block_svg.js\", ['Blockly.BlockSvg'], ['goog.userAgent']);\ngoog.addDependency(\"../../../\" + dir + \"/core/blockly.js\", ['Blockly'], ['Blockly.Block', 'Blockly.BlockMenu', 'Blockly.FieldIcon', 'Blockly.Connection', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldDropdownDynamic', 'Blockly.FieldImage', 'Blockly.FieldIcon', 'Blockly.FieldTextInput', 'Blockly.FieldKeydownInput', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Realtime', 'Blockly.Toolbox', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.inject', 'Blockly.utils', 'goog.dom', 'goog.color', 'goog.events', 'goog.string', 'goog.ui.ColorPicker', 'goog.ui.tree.TreeControl', 'goog.userAgent', 'Blockly.FieldKeydownInput']);\ngoog.addDependency(\"../../../\" + dir + \"/core/blocks.js\", ['Blockly.Blocks'], ['goog.asserts']);\ngoog.addDependency(\"../../../\" + dir + \"/core/bubble.js\", ['Blockly.Bubble'], ['Blockly.Workspace']);\ngoog.addDependency(\"../../../\" + dir + \"/core/comment.js\", ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Icon']);\ngoog.addDependency(\"../../../\" + dir + \"/core/connection-animation.js\", ['Blockly.ConnectionAnimation'], ['Blockly.Connection', 'goog.Timer']);\ngoog.addDependency(\"../../../\" + dir + \"/core/connection.js\", ['Blockly.Connection', 'Blockly.ConnectionDB'], ['Blockly.Workspace']);\ngoog.addDependency(\"../../../\" + dir + \"/core/contextmenu.js\", ['Blockly.ContextMenu'], []);\ngoog.addDependency(\"../../../\" + dir + \"/core/css.js\", ['Blockly.Css'], ['goog.cssom']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field.js\", ['Blockly.Field'], ['Blockly.BlockSvg', 'goog.asserts']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_angle.js\", ['Blockly.FieldAngle'], ['Blockly.FieldTextInput']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_checkbox.js\", ['Blockly.FieldCheckbox'], ['Blockly.Field']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_colour.js\", ['Blockly.FieldColour'], ['Blockly.Field', 'goog.ui.ColorPicker']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_dropdown.js\", ['Blockly.FieldDropdown'], ['Blockly.Field']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_dropdowndynamic.js\", ['Blockly.FieldDropdownDynamic'], ['Blockly.Field']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_icon.js\", ['Blockly.FieldIcon'], ['Blockly.Field', 'goog.userAgent']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_image.js\", ['Blockly.FieldImage'], ['Blockly.Field', 'goog.userAgent']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_keydown_input.js\", ['Blockly.FieldKeydownInput'], ['Blockly.Field', 'Blockly.Msg', 'goog.asserts', 'goog.userAgent']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_label.js\", ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.Tooltip']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_textinput.js\", ['Blockly.FieldTextInput'], ['Blockly.Field', 'Blockly.Msg', 'goog.asserts', 'goog.userAgent']);\ngoog.addDependency(\"../../../\" + dir + \"/core/field_variable.js\", ['Blockly.FieldVariable'], ['Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.Variables']);\ngoog.addDependency(\"../../../\" + dir + \"/core/flyout.js\", ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.Comment']);\ngoog.addDependency(\"../../../\" + dir + \"/core/generator.js\", ['Blockly.Generator'], ['Blockly.Block']);\ngoog.addDependency(\"../../../\" + dir + \"/core/icon.js\", ['Blockly.Icon'], []);\ngoog.addDependency(\"../../../\" + dir + \"/core/inject.js\", ['Blockly.inject'], ['Blockly.Css', 'goog.dom']);\ngoog.addDependency(\"../../../\" + dir + \"/core/input.js\", ['Blockly.Input'], ['Blockly.Connection', 'Blockly.FieldLabel', 'goog.asserts']);\ngoog.addDependency(\"../../../\" + dir + \"/core/msg.js\", ['Blockly.Msg'], []);\ngoog.addDependency(\"../../../\" + dir + \"/core/mutator.js\", ['Blockly.Mutator'], ['Blockly.Bubble', 'Blockly.Icon']);\ngoog.addDependency(\"../../../\" + dir + \"/core/names.js\", ['Blockly.Names'], []);\ngoog.addDependency(\"../../../\" + dir + \"/core/procedures.js\", ['Blockly.Procedures'], ['Blockly.FieldVariable', 'Blockly.Names', 'Blockly.Workspace']);\ngoog.addDependency(\"../../../\" + dir + \"/core/realtime-client-utils.js\", [], []);\ngoog.addDependency(\"../../../\" + dir + \"/core/realtime.js\", ['Blockly.Realtime'], ['goog.array']);\ngoog.addDependency(\"../../../\" + dir + \"/core/scrollbar.js\", ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['goog.userAgent']);\ngoog.addDependency(\"../../../\" + dir + \"/core/toolbox.js\", ['Blockly.Toolbox'], ['Blockly.Flyout', 'goog.events.BrowserFeature', 'goog.style', 'goog.ui.tree.TreeControl', 'goog.ui.tree.TreeNode']);\ngoog.addDependency(\"../../../\" + dir + \"/core/tooltip.js\", ['Blockly.Tooltip'], []);\ngoog.addDependency(\"../../../\" + dir + \"/core/trashcan.js\", ['Blockly.Trashcan'], ['goog.Timer']);\ngoog.addDependency(\"../../../\" + dir + \"/core/utils.js\", ['Blockly.utils'], []);\ngoog.addDependency(\"../../../\" + dir + \"/core/variables.js\", ['Blockly.Variables'], ['Blockly.Toolbox', 'Blockly.Workspace']);\ngoog.addDependency(\"../../../\" + dir + \"/core/warning.js\", ['Blockly.Warning'], ['Blockly.Bubble', 'Blockly.Icon']);\ngoog.addDependency(\"../../../\" + dir + \"/core/widgetdiv.js\", ['Blockly.WidgetDiv'], ['Blockly.Css', 'goog.dom']);\ngoog.addDependency(\"../../../\" + dir + \"/core/workspace.js\", ['Blockly.Workspace'], ['Blockly.ScrollbarPair', 'Blockly.Trashcan', 'Blockly.Xml']);\ngoog.addDependency(\"../../../\" + dir + \"/core/xml.js\", ['Blockly.Xml'], []);\ngoog.addDependency(\"../../alltests.js\", [], []);\ngoog.addDependency(\"../../browser_capabilities.js\", [], []);\ngoog.addDependency(\"../../protractor.conf.js\", [], []);\ngoog.addDependency(\"../../protractor_spec.js\", [], []);\ngoog.addDependency(\"base.js\", [], []);\ngoog.addDependency(\"base_module_test.js\", [], []);\ngoog.addDependency(\"base_test.js\", ['goog.baseTest', 'ns', 'goog.test.name.space', 'goog.test', 'goog.test.name', 'goog.xy', 'goog.xy.z', 'goog.explicit', 'goog.implicit.explicit', 'an.existing.path', 'dup.base', 'testDep.bar', 'far.out'], ['goog.Promise', 'goog.Timer', 'goog.dom.TagName', 'goog.functions', 'goog.test_module', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"defineclass_test.js\", ['goog.defineClassTest'], ['goog.testing.jsunit']);\ngoog.addDependency(\"deps.js\", [], []);\ngoog.addDependency(\"test_module.js\", [], []);\ngoog.addDependency(\"test_module_dep.js\", [], []);\ngoog.addDependency(\"a11y/aria/announcer.js\", ['goog.a11y.aria.Announcer'], ['goog.Disposable', 'goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.object']);\ngoog.addDependency(\"a11y/aria/announcer_test.js\", ['goog.a11y.aria.AnnouncerTest'], ['goog.a11y.aria', 'goog.a11y.aria.Announcer', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.iframe', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"a11y/aria/aria.js\", ['goog.a11y.aria'], ['goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.a11y.aria.datatables', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.object', 'goog.string']);\ngoog.addDependency(\"a11y/aria/aria_test.js\", ['goog.a11y.ariaTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit']);\ngoog.addDependency(\"a11y/aria/attributes.js\", ['goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.CheckedValues', 'goog.a11y.aria.DropEffectValues', 'goog.a11y.aria.ExpandedValues', 'goog.a11y.aria.GrabbedValues', 'goog.a11y.aria.InvalidValues', 'goog.a11y.aria.LivePriority', 'goog.a11y.aria.OrientationValues', 'goog.a11y.aria.PressedValues', 'goog.a11y.aria.RelevantValues', 'goog.a11y.aria.SelectedValues', 'goog.a11y.aria.SortValues', 'goog.a11y.aria.State'], []);\ngoog.addDependency(\"a11y/aria/datatables.js\", ['goog.a11y.aria.datatables'], ['goog.a11y.aria.State', 'goog.object']);\ngoog.addDependency(\"a11y/aria/roles.js\", ['goog.a11y.aria.Role'], []);\ngoog.addDependency(\"array/array.js\", ['goog.array', 'goog.array.ArrayLike'], ['goog.asserts']);\ngoog.addDependency(\"array/array_test.js\", ['goog.arrayTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"asserts/asserts.js\", ['goog.asserts', 'goog.asserts.AssertionError'], ['goog.debug.Error', 'goog.dom.NodeType', 'goog.string']);\ngoog.addDependency(\"asserts/asserts_test.js\", ['goog.assertsTest'], ['goog.asserts', 'goog.asserts.AssertionError', 'goog.dom', 'goog.dom.TagName', 'goog.string', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"async/animationdelay.js\", ['goog.async.AnimationDelay'], ['goog.Disposable', 'goog.events', 'goog.functions']);\ngoog.addDependency(\"async/animationdelay_test.js\", [], []);\ngoog.addDependency(\"async/conditionaldelay.js\", ['goog.async.ConditionalDelay'], ['goog.Disposable', 'goog.async.Delay']);\ngoog.addDependency(\"async/conditionaldelay_test.js\", ['goog.async.ConditionalDelayTest'], ['goog.async.ConditionalDelay', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"async/debouncer.js\", ['goog.async.Debouncer'], ['goog.Disposable', 'goog.Timer']);\ngoog.addDependency(\"async/debouncer_test.js\", ['goog.async.DebouncerTest'], ['goog.array', 'goog.async.Debouncer', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"async/delay.js\", ['goog.Delay', 'goog.async.Delay'], ['goog.Disposable', 'goog.Timer']);\ngoog.addDependency(\"async/delay_test.js\", ['goog.async.DelayTest'], ['goog.async.Delay', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"async/freelist.js\", ['goog.async.FreeList'], []);\ngoog.addDependency(\"async/freelist_test.js\", ['goog.async.FreeListTest'], ['goog.async.FreeList', 'goog.testing.jsunit']);\ngoog.addDependency(\"async/nexttick.js\", ['goog.async.nextTick', 'goog.async.throwException'], ['goog.debug.entryPointRegistry', 'goog.dom.TagName', 'goog.functions', 'goog.labs.userAgent.browser', 'goog.labs.userAgent.engine']);\ngoog.addDependency(\"async/nexttick_test.js\", ['goog.async.nextTickTest'], ['goog.Promise', 'goog.Timer', 'goog.async.nextTick', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.dom', 'goog.dom.TagName', 'goog.labs.userAgent.browser', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"async/run.js\", ['goog.async.run'], ['goog.async.WorkQueue', 'goog.async.nextTick', 'goog.async.throwException']);\ngoog.addDependency(\"async/run_test.js\", ['goog.async.runTest'], ['goog.async.run', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"async/throttle.js\", ['goog.Throttle', 'goog.async.Throttle'], ['goog.Disposable', 'goog.Timer']);\ngoog.addDependency(\"async/throttle_test.js\", ['goog.async.ThrottleTest'], ['goog.async.Throttle', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"async/workqueue.js\", ['goog.async.WorkItem', 'goog.async.WorkQueue'], ['goog.asserts', 'goog.async.FreeList']);\ngoog.addDependency(\"async/workqueue_test.js\", ['goog.async.WorkQueueTest'], ['goog.async.WorkQueue', 'goog.testing.jsunit']);\ngoog.addDependency(\"bootstrap/nodejs.js\", [], []);\ngoog.addDependency(\"bootstrap/webworkers.js\", [], []);\ngoog.addDependency(\"color/alpha.js\", ['goog.color.alpha'], ['goog.color']);\ngoog.addDependency(\"color/alpha_test.js\", ['goog.color.alphaTest'], ['goog.array', 'goog.color', 'goog.color.alpha', 'goog.testing.jsunit']);\ngoog.addDependency(\"color/color.js\", ['goog.color', 'goog.color.Hsl', 'goog.color.Hsv', 'goog.color.Rgb'], ['goog.color.names', 'goog.math']);\ngoog.addDependency(\"color/color_test.js\", ['goog.colorTest'], ['goog.array', 'goog.color', 'goog.color.names', 'goog.testing.jsunit']);\ngoog.addDependency(\"color/names.js\", ['goog.color.names'], []);\ngoog.addDependency(\"crypt/aes.js\", ['goog.crypt.Aes'], ['goog.asserts', 'goog.crypt.BlockCipher']);\ngoog.addDependency(\"crypt/aes_test.js\", ['goog.crypt.AesTest'], ['goog.crypt', 'goog.crypt.Aes', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/arc4.js\", ['goog.crypt.Arc4'], ['goog.asserts']);\ngoog.addDependency(\"crypt/arc4_test.js\", ['goog.crypt.Arc4Test'], ['goog.array', 'goog.crypt.Arc4', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/base64.js\", ['goog.crypt.base64'], ['goog.asserts', 'goog.crypt', 'goog.string', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"crypt/base64_test.js\", ['goog.crypt.base64Test'], ['goog.crypt', 'goog.crypt.base64', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/basen.js\", ['goog.crypt.baseN'], []);\ngoog.addDependency(\"crypt/basen_test.js\", ['goog.crypt.baseNTest'], ['goog.crypt.baseN', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/blobhasher.js\", ['goog.crypt.BlobHasher', 'goog.crypt.BlobHasher.EventType'], ['goog.asserts', 'goog.events.EventTarget', 'goog.fs', 'goog.log']);\ngoog.addDependency(\"crypt/blobhasher_test.js\", ['goog.crypt.BlobHasherTest'], ['goog.crypt', 'goog.crypt.BlobHasher', 'goog.crypt.Md5', 'goog.events', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/blockcipher.js\", ['goog.crypt.BlockCipher'], []);\ngoog.addDependency(\"crypt/bytestring_perf.js\", ['goog.crypt.byteArrayToStringPerf'], ['goog.array', 'goog.dom', 'goog.testing.PerformanceTable']);\ngoog.addDependency(\"crypt/cbc.js\", ['goog.crypt.Cbc'], ['goog.array', 'goog.asserts', 'goog.crypt']);\ngoog.addDependency(\"crypt/cbc_test.js\", ['goog.crypt.CbcTest'], ['goog.crypt', 'goog.crypt.Aes', 'goog.crypt.Cbc', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/crypt.js\", ['goog.crypt'], ['goog.array', 'goog.asserts']);\ngoog.addDependency(\"crypt/crypt_test.js\", ['goog.cryptTest'], ['goog.crypt', 'goog.string', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/hash.js\", ['goog.crypt.Hash'], []);\ngoog.addDependency(\"crypt/hash32.js\", ['goog.crypt.hash32'], ['goog.crypt']);\ngoog.addDependency(\"crypt/hash32_test.js\", ['goog.crypt.hash32Test'], ['goog.crypt.hash32', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/hashtester.js\", ['goog.crypt.hashTester'], ['goog.array', 'goog.crypt', 'goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTable', 'goog.testing.PseudoRandom', 'goog.testing.asserts']);\ngoog.addDependency(\"crypt/hmac.js\", ['goog.crypt.Hmac'], ['goog.crypt.Hash']);\ngoog.addDependency(\"crypt/hmac_test.js\", ['goog.crypt.HmacTest'], ['goog.crypt.Hmac', 'goog.crypt.Sha1', 'goog.crypt.hashTester', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/md5.js\", ['goog.crypt.Md5'], ['goog.crypt.Hash']);\ngoog.addDependency(\"crypt/md5_test.js\", ['goog.crypt.Md5Test'], ['goog.crypt', 'goog.crypt.Md5', 'goog.crypt.hashTester', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/pbkdf2.js\", ['goog.crypt.pbkdf2'], ['goog.array', 'goog.asserts', 'goog.crypt', 'goog.crypt.Hmac', 'goog.crypt.Sha1']);\ngoog.addDependency(\"crypt/pbkdf2_test.js\", ['goog.crypt.pbkdf2Test'], ['goog.crypt', 'goog.crypt.pbkdf2', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"crypt/sha1.js\", ['goog.crypt.Sha1'], ['goog.crypt.Hash']);\ngoog.addDependency(\"crypt/sha1_test.js\", ['goog.crypt.Sha1Test'], ['goog.crypt', 'goog.crypt.Sha1', 'goog.crypt.hashTester', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"crypt/sha2.js\", ['goog.crypt.Sha2'], ['goog.array', 'goog.asserts', 'goog.crypt.Hash']);\ngoog.addDependency(\"crypt/sha224.js\", ['goog.crypt.Sha224'], ['goog.crypt.Sha2']);\ngoog.addDependency(\"crypt/sha224_test.js\", ['goog.crypt.Sha224Test'], ['goog.crypt', 'goog.crypt.Sha224', 'goog.crypt.hashTester', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/sha256.js\", ['goog.crypt.Sha256'], ['goog.crypt.Sha2']);\ngoog.addDependency(\"crypt/sha256_test.js\", ['goog.crypt.Sha256Test'], ['goog.crypt', 'goog.crypt.Sha256', 'goog.crypt.hashTester', 'goog.testing.jsunit']);\ngoog.addDependency(\"crypt/sha2_64bit.js\", ['goog.crypt.Sha2_64bit'], ['goog.array', 'goog.asserts', 'goog.crypt.Hash', 'goog.math.Long']);\ngoog.addDependency(\"crypt/sha2_64bit_test.js\", ['goog.crypt.Sha2_64bit_test'], ['goog.array', 'goog.crypt', 'goog.crypt.Sha384', 'goog.crypt.Sha512', 'goog.crypt.Sha512_256', 'goog.crypt.hashTester', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"crypt/sha384.js\", ['goog.crypt.Sha384'], ['goog.crypt.Sha2_64bit']);\ngoog.addDependency(\"crypt/sha512.js\", ['goog.crypt.Sha512'], ['goog.crypt.Sha2_64bit']);\ngoog.addDependency(\"crypt/sha512_256.js\", ['goog.crypt.Sha512_256'], ['goog.crypt.Sha2_64bit']);\ngoog.addDependency(\"cssom/cssom.js\", ['goog.cssom', 'goog.cssom.CssRuleType'], ['goog.array', 'goog.dom', 'goog.dom.TagName']);\ngoog.addDependency(\"cssom/cssom_test.js\", ['goog.cssomTest'], ['goog.array', 'goog.cssom', 'goog.cssom.CssRuleType', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"cssom/iframe/style.js\", ['goog.cssom.iframe.style'], ['goog.asserts', 'goog.cssom', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.string', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"cssom/iframe/style_test.js\", ['goog.cssom.iframe.styleTest'], ['goog.cssom', 'goog.cssom.iframe.style', 'goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"datasource/datamanager.js\", ['goog.ds.DataManager'], ['goog.ds.BasicNodeList', 'goog.ds.DataNode', 'goog.ds.Expr', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.Map']);\ngoog.addDependency(\"datasource/datasource.js\", ['goog.ds.BaseDataNode', 'goog.ds.BasicNodeList', 'goog.ds.DataNode', 'goog.ds.DataNodeList', 'goog.ds.EmptyNodeList', 'goog.ds.LoadState', 'goog.ds.SortedNodeList', 'goog.ds.Util', 'goog.ds.logger'], ['goog.array', 'goog.log']);\ngoog.addDependency(\"datasource/datasource_test.js\", ['goog.ds.JsDataSourceTest'], ['goog.dom.xml', 'goog.ds.DataManager', 'goog.ds.JsDataSource', 'goog.ds.SortedNodeList', 'goog.ds.XmlDataSource', 'goog.testing.jsunit']);\ngoog.addDependency(\"datasource/expr.js\", ['goog.ds.Expr'], ['goog.ds.BasicNodeList', 'goog.ds.EmptyNodeList', 'goog.string']);\ngoog.addDependency(\"datasource/expr_test.js\", ['goog.ds.ExprTest'], ['goog.ds.DataManager', 'goog.ds.Expr', 'goog.ds.JsDataSource', 'goog.testing.jsunit']);\ngoog.addDependency(\"datasource/fastdatanode.js\", ['goog.ds.AbstractFastDataNode', 'goog.ds.FastDataNode', 'goog.ds.FastListNode', 'goog.ds.PrimitiveFastDataNode'], ['goog.ds.DataManager', 'goog.ds.DataNodeList', 'goog.ds.EmptyNodeList', 'goog.string']);\ngoog.addDependency(\"datasource/fastdatanode_test.js\", ['goog.ds.FastDataNodeTest'], ['goog.array', 'goog.ds.DataManager', 'goog.ds.Expr', 'goog.ds.FastDataNode', 'goog.testing.jsunit']);\ngoog.addDependency(\"datasource/jsdatasource.js\", ['goog.ds.JsDataSource', 'goog.ds.JsPropertyDataSource'], ['goog.ds.BaseDataNode', 'goog.ds.BasicNodeList', 'goog.ds.DataManager', 'goog.ds.DataNode', 'goog.ds.EmptyNodeList', 'goog.ds.LoadState']);\ngoog.addDependency(\"datasource/jsondatasource.js\", ['goog.ds.JsonDataSource'], ['goog.Uri', 'goog.dom', 'goog.dom.TagName', 'goog.ds.DataManager', 'goog.ds.JsDataSource', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.log']);\ngoog.addDependency(\"datasource/jsxmlhttpdatasource.js\", ['goog.ds.JsXmlHttpDataSource'], ['goog.Uri', 'goog.ds.DataManager', 'goog.ds.FastDataNode', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.events', 'goog.log', 'goog.net.EventType', 'goog.net.XhrIo']);\ngoog.addDependency(\"datasource/jsxmlhttpdatasource_test.js\", ['goog.ds.JsXmlHttpDataSourceTest'], ['goog.ds.JsXmlHttpDataSource', 'goog.testing.TestQueue', 'goog.testing.jsunit', 'goog.testing.net.XhrIo']);\ngoog.addDependency(\"datasource/xmldatasource.js\", ['goog.ds.XmlDataSource', 'goog.ds.XmlHttpDataSource'], ['goog.Uri', 'goog.dom.NodeType', 'goog.dom.xml', 'goog.ds.BasicNodeList', 'goog.ds.DataManager', 'goog.ds.DataNode', 'goog.ds.LoadState', 'goog.ds.logger', 'goog.net.XhrIo', 'goog.string']);\ngoog.addDependency(\"date/date.js\", ['goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval', 'goog.date.month', 'goog.date.weekDay'], ['goog.asserts', 'goog.date.DateLike', 'goog.i18n.DateTimeSymbols', 'goog.string']);\ngoog.addDependency(\"date/date_test.js\", ['goog.dateTest'], ['goog.array', 'goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval', 'goog.date.month', 'goog.date.weekDay', 'goog.i18n.DateTimeSymbols', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.platform', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"date/datelike.js\", ['goog.date.DateLike'], []);\ngoog.addDependency(\"date/daterange.js\", ['goog.date.DateRange', 'goog.date.DateRange.Iterator', 'goog.date.DateRange.StandardDateRangeKeys'], ['goog.date.Date', 'goog.date.Interval', 'goog.iter.Iterator', 'goog.iter.StopIteration']);\ngoog.addDependency(\"date/daterange_test.js\", ['goog.date.DateRangeTest'], ['goog.date.Date', 'goog.date.DateRange', 'goog.date.Interval', 'goog.i18n.DateTimeSymbols', 'goog.testing.jsunit']);\ngoog.addDependency(\"date/duration.js\", ['goog.date.duration'], ['goog.i18n.DateTimeFormat', 'goog.i18n.MessageFormat']);\ngoog.addDependency(\"date/duration_test.js\", ['goog.date.durationTest'], ['goog.date.duration', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.testing.jsunit']);\ngoog.addDependency(\"date/relative.js\", ['goog.date.relative', 'goog.date.relative.TimeDeltaFormatter', 'goog.date.relative.Unit'], ['goog.i18n.DateTimeFormat', 'goog.i18n.DateTimePatterns']);\ngoog.addDependency(\"date/relative_test.js\", ['goog.date.relativeTest'], ['goog.date.DateTime', 'goog.date.relative', 'goog.i18n.DateTimeFormat', 'goog.testing.jsunit']);\ngoog.addDependency(\"date/relativewithplurals.js\", ['goog.date.relativeWithPlurals'], ['goog.date.relative', 'goog.date.relative.Unit', 'goog.i18n.MessageFormat']);\ngoog.addDependency(\"date/relativewithplurals_test.js\", ['goog.date.relativeWithPluralsTest'], ['goog.date.relative', 'goog.date.relativeTest', 'goog.date.relativeWithPlurals', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_bn', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_fa']);\ngoog.addDependency(\"date/utcdatetime.js\", ['goog.date.UtcDateTime'], ['goog.date', 'goog.date.Date', 'goog.date.DateTime', 'goog.date.Interval']);\ngoog.addDependency(\"date/utcdatetime_test.js\", ['goog.date.UtcDateTimeTest'], ['goog.date.Interval', 'goog.date.UtcDateTime', 'goog.date.month', 'goog.date.weekDay', 'goog.testing.jsunit']);\ngoog.addDependency(\"db/cursor.js\", ['goog.db.Cursor'], ['goog.async.Deferred', 'goog.db.Error', 'goog.debug', 'goog.events.EventTarget']);\ngoog.addDependency(\"db/db.js\", ['goog.db', 'goog.db.BlockedCallback', 'goog.db.UpgradeNeededCallback'], ['goog.asserts', 'goog.async.Deferred', 'goog.db.Error', 'goog.db.IndexedDb', 'goog.db.Transaction']);\ngoog.addDependency(\"db/db_test.js\", ['goog.dbTest'], ['goog.Disposable', 'goog.Promise', 'goog.array', 'goog.db', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.IndexedDb', 'goog.db.KeyRange', 'goog.db.Transaction', 'goog.events', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent.product']);\ngoog.addDependency(\"db/error.js\", ['goog.db.Error', 'goog.db.Error.ErrorCode', 'goog.db.Error.ErrorName', 'goog.db.Error.VersionChangeBlockedError'], ['goog.debug.Error']);\ngoog.addDependency(\"db/index.js\", ['goog.db.Index'], ['goog.async.Deferred', 'goog.db.Cursor', 'goog.db.Error', 'goog.debug']);\ngoog.addDependency(\"db/indexeddb.js\", ['goog.db.IndexedDb'], ['goog.db.Error', 'goog.db.ObjectStore', 'goog.db.Transaction', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget']);\ngoog.addDependency(\"db/keyrange.js\", ['goog.db.KeyRange'], []);\ngoog.addDependency(\"db/objectstore.js\", ['goog.db.ObjectStore'], ['goog.async.Deferred', 'goog.db.Cursor', 'goog.db.Error', 'goog.db.Index', 'goog.debug', 'goog.events']);\ngoog.addDependency(\"db/transaction.js\", ['goog.db.Transaction', 'goog.db.Transaction.TransactionMode'], ['goog.async.Deferred', 'goog.db.Error', 'goog.db.ObjectStore', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget']);\ngoog.addDependency(\"debug/console.js\", ['goog.debug.Console'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.debug.TextFormatter']);\ngoog.addDependency(\"debug/console_test.js\", ['goog.debug.ConsoleTest'], ['goog.debug.Console', 'goog.debug.LogRecord', 'goog.debug.Logger', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"debug/debug.js\", ['goog.debug'], ['goog.array', 'goog.html.SafeHtml', 'goog.html.SafeUrl', 'goog.html.uncheckedconversions', 'goog.string.Const', 'goog.structs.Set', 'goog.userAgent']);\ngoog.addDependency(\"debug/debug_test.js\", ['goog.debugTest'], ['goog.debug', 'goog.html.SafeHtml', 'goog.structs.Set', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/debugwindow.js\", ['goog.debug.DebugWindow'], ['goog.debug.HtmlFormatter', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyleSheet', 'goog.string.Const', 'goog.structs.CircularBuffer', 'goog.userAgent']);\ngoog.addDependency(\"debug/debugwindow_test.js\", ['goog.debug.DebugWindowTest'], ['goog.debug.DebugWindow', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/divconsole.js\", ['goog.debug.DivConsole'], ['goog.debug.HtmlFormatter', 'goog.debug.LogManager', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.style']);\ngoog.addDependency(\"debug/enhanceerror_test.js\", ['goog.debugEnhanceErrorTest'], ['goog.debug', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/entrypointregistry.js\", ['goog.debug.EntryPointMonitor', 'goog.debug.entryPointRegistry'], ['goog.asserts']);\ngoog.addDependency(\"debug/entrypointregistry_test.js\", ['goog.debug.entryPointRegistryTest'], ['goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/error.js\", ['goog.debug.Error'], []);\ngoog.addDependency(\"debug/error_test.js\", ['goog.debug.ErrorTest'], ['goog.debug.Error', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"debug/errorhandler.js\", ['goog.debug.ErrorHandler', 'goog.debug.ErrorHandler.ProtectedFunctionError'], ['goog.Disposable', 'goog.asserts', 'goog.debug', 'goog.debug.EntryPointMonitor', 'goog.debug.Error', 'goog.debug.Trace']);\ngoog.addDependency(\"debug/errorhandler_async_test.js\", ['goog.debug.ErrorHandlerAsyncTest'], ['goog.Promise', 'goog.debug.ErrorHandler', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"debug/errorhandler_test.js\", ['goog.debug.ErrorHandlerTest'], ['goog.debug.ErrorHandler', 'goog.testing.MockControl', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/errorhandlerweakdep.js\", ['goog.debug.errorHandlerWeakDep'], []);\ngoog.addDependency(\"debug/errorreporter.js\", ['goog.debug.ErrorReporter', 'goog.debug.ErrorReporter.ExceptionEvent'], ['goog.asserts', 'goog.debug', 'goog.debug.Error', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.log', 'goog.net.XhrIo', 'goog.object', 'goog.string', 'goog.uri.utils', 'goog.userAgent']);\ngoog.addDependency(\"debug/errorreporter_test.js\", ['goog.debug.ErrorReporterTest'], ['goog.debug.Error', 'goog.debug.ErrorReporter', 'goog.events', 'goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"debug/fancywindow.js\", ['goog.debug.FancyWindow'], ['goog.array', 'goog.debug.DebugWindow', 'goog.debug.LogManager', 'goog.debug.Logger', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyleSheet', 'goog.object', 'goog.string', 'goog.string.Const', 'goog.userAgent']);\ngoog.addDependency(\"debug/formatter.js\", ['goog.debug.Formatter', 'goog.debug.HtmlFormatter', 'goog.debug.TextFormatter'], ['goog.debug', 'goog.debug.Logger', 'goog.debug.RelativeTimeProvider', 'goog.html.SafeHtml']);\ngoog.addDependency(\"debug/formatter_test.js\", ['goog.debug.FormatterTest'], ['goog.debug.HtmlFormatter', 'goog.debug.LogRecord', 'goog.debug.Logger', 'goog.html.SafeHtml', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/fpsdisplay.js\", ['goog.debug.FpsDisplay'], ['goog.asserts', 'goog.async.AnimationDelay', 'goog.dom', 'goog.dom.TagName', 'goog.ui.Component']);\ngoog.addDependency(\"debug/fpsdisplay_test.js\", ['goog.debug.FpsDisplayTest'], ['goog.Timer', 'goog.debug.FpsDisplay', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/logbuffer.js\", ['goog.debug.LogBuffer'], ['goog.asserts', 'goog.debug.LogRecord']);\ngoog.addDependency(\"debug/logbuffer_test.js\", ['goog.debug.LogBufferTest'], ['goog.debug.LogBuffer', 'goog.debug.Logger', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/logger.js\", ['goog.debug.LogManager', 'goog.debug.Loggable', 'goog.debug.Logger', 'goog.debug.Logger.Level'], ['goog.array', 'goog.asserts', 'goog.debug', 'goog.debug.LogBuffer', 'goog.debug.LogRecord']);\ngoog.addDependency(\"debug/logger_test.js\", ['goog.debug.LoggerTest'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/logrecord.js\", ['goog.debug.LogRecord'], []);\ngoog.addDependency(\"debug/logrecordserializer.js\", ['goog.debug.logRecordSerializer'], ['goog.debug.LogRecord', 'goog.debug.Logger', 'goog.json', 'goog.object']);\ngoog.addDependency(\"debug/logrecordserializer_test.js\", ['goog.debug.logRecordSerializerTest'], ['goog.debug.LogRecord', 'goog.debug.Logger', 'goog.debug.logRecordSerializer', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/relativetimeprovider.js\", ['goog.debug.RelativeTimeProvider'], []);\ngoog.addDependency(\"debug/tracer.js\", ['goog.debug.Trace'], ['goog.array', 'goog.debug.Logger', 'goog.iter', 'goog.log', 'goog.structs.Map', 'goog.structs.SimplePool']);\ngoog.addDependency(\"debug/tracer_test.js\", ['goog.debug.TraceTest'], ['goog.debug.Trace', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/devcss/devcss.js\", ['goog.debug.DevCss', 'goog.debug.DevCss.UserAgent'], ['goog.asserts', 'goog.cssom', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"debug/devcss/devcss_test.js\", ['goog.debug.DevCssTest'], ['goog.debug.DevCss', 'goog.style', 'goog.testing.jsunit']);\ngoog.addDependency(\"debug/devcss/devcssrunner.js\", ['goog.debug.devCssRunner'], ['goog.debug.DevCss']);\ngoog.addDependency(\"demos/autocompleteremotedata.js\", [], []);\ngoog.addDependency(\"demos/autocompleterichremotedata.js\", [], []);\ngoog.addDependency(\"demos/samplecomponent.js\", ['goog.demos.SampleComponent'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.ui.Component']);\ngoog.addDependency(\"demos/editor/deps.js\", [], []);\ngoog.addDependency(\"demos/editor/helloworld.js\", ['goog.demos.editor.HelloWorld'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Plugin']);\ngoog.addDependency(\"demos/editor/helloworlddialog.js\", ['goog.demos.editor.HelloWorldDialog', 'goog.demos.editor.HelloWorldDialog.OkEvent'], ['goog.dom.TagName', 'goog.events.Event', 'goog.string', 'goog.ui.editor.AbstractDialog']);\ngoog.addDependency(\"demos/editor/helloworlddialogplugin.js\", ['goog.demos.editor.HelloWorldDialogPlugin', 'goog.demos.editor.HelloWorldDialogPlugin.Command'], ['goog.demos.editor.HelloWorldDialog', 'goog.dom.TagName', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.range', 'goog.functions', 'goog.ui.editor.AbstractDialog']);\ngoog.addDependency(\"demos/graphics/tigerdata.js\", [], []);\ngoog.addDependency(\"demos/tree/testdata.js\", [], []);\ngoog.addDependency(\"demos/xpc/xpcdemo.js\", ['xpcdemo'], ['goog.Uri', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.html.SafeHtml', 'goog.json', 'goog.log', 'goog.log.Level', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel']);\ngoog.addDependency(\"disposable/disposable.js\", ['goog.Disposable', 'goog.dispose', 'goog.disposeAll'], ['goog.disposable.IDisposable']);\ngoog.addDependency(\"disposable/disposable_test.js\", ['goog.DisposableTest'], ['goog.Disposable', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"disposable/idisposable.js\", ['goog.disposable.IDisposable'], []);\ngoog.addDependency(\"dom/abstractmultirange.js\", ['goog.dom.AbstractMultiRange'], ['goog.array', 'goog.dom', 'goog.dom.AbstractRange']);\ngoog.addDependency(\"dom/abstractrange.js\", ['goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.SavedCaretRange', 'goog.dom.TagIterator', 'goog.userAgent']);\ngoog.addDependency(\"dom/abstractrange_test.js\", ['goog.dom.AbstractRangeTest'], ['goog.dom', 'goog.dom.AbstractRange', 'goog.dom.Range', 'goog.dom.TagName', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/annotate.js\", ['goog.dom.annotate', 'goog.dom.annotate.AnnotateFn'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml']);\ngoog.addDependency(\"dom/annotate_test.js\", ['goog.dom.annotateTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.annotate', 'goog.html.SafeHtml', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/browserfeature.js\", ['goog.dom.BrowserFeature'], ['goog.userAgent']);\ngoog.addDependency(\"dom/bufferedviewportsizemonitor.js\", ['goog.dom.BufferedViewportSizeMonitor'], ['goog.asserts', 'goog.async.Delay', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType']);\ngoog.addDependency(\"dom/bufferedviewportsizemonitor_test.js\", ['goog.dom.BufferedViewportSizeMonitorTest'], ['goog.dom.BufferedViewportSizeMonitor', 'goog.dom.ViewportSizeMonitor', 'goog.events', 'goog.events.EventType', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/classes.js\", ['goog.dom.classes'], ['goog.array']);\ngoog.addDependency(\"dom/classes_test.js\", ['goog.dom.classes_test'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classes', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/classlist.js\", ['goog.dom.classlist'], ['goog.array']);\ngoog.addDependency(\"dom/classlist_test.js\", ['goog.dom.classlist_test'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/controlrange.js\", ['goog.dom.ControlRange', 'goog.dom.ControlRangeIterator'], ['goog.array', 'goog.dom', 'goog.dom.AbstractMultiRange', 'goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TagWalkType', 'goog.dom.TextRange', 'goog.iter.StopIteration', 'goog.userAgent']);\ngoog.addDependency(\"dom/controlrange_test.js\", ['goog.dom.ControlRangeTest'], ['goog.dom', 'goog.dom.ControlRange', 'goog.dom.RangeType', 'goog.dom.TagName', 'goog.dom.TextRange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"dom/dataset.js\", ['goog.dom.dataset'], ['goog.string', 'goog.userAgent.product']);\ngoog.addDependency(\"dom/dataset_test.js\", ['goog.dom.datasetTest'], ['goog.dom', 'goog.dom.dataset', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/dom.js\", ['goog.dom', 'goog.dom.Appendable', 'goog.dom.DomHelper'], ['goog.array', 'goog.asserts', 'goog.dom.BrowserFeature', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.math.Coordinate', 'goog.math.Size', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.userAgent']);\ngoog.addDependency(\"dom/dom_test.js\", ['goog.dom.dom_test'], ['goog.dom', 'goog.dom.BrowserFeature', 'goog.dom.DomHelper', 'goog.dom.InputType', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.functions', 'goog.html.testing', 'goog.object', 'goog.string.Unicode', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"dom/fontsizemonitor.js\", ['goog.dom.FontSizeMonitor', 'goog.dom.FontSizeMonitor.EventType'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.userAgent']);\ngoog.addDependency(\"dom/fontsizemonitor_test.js\", ['goog.dom.FontSizeMonitorTest'], ['goog.dom', 'goog.dom.FontSizeMonitor', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"dom/forms.js\", ['goog.dom.forms'], ['goog.dom.InputType', 'goog.dom.TagName', 'goog.structs.Map']);\ngoog.addDependency(\"dom/forms_test.js\", ['goog.dom.formsTest'], ['goog.dom', 'goog.dom.forms', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/fullscreen.js\", ['goog.dom.fullscreen', 'goog.dom.fullscreen.EventType'], ['goog.dom', 'goog.userAgent']);\ngoog.addDependency(\"dom/fullscreen_test.js\", ['goog.dom.fullscreen_test'], ['goog.dom.DomHelper', 'goog.dom.fullscreen', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/iframe.js\", ['goog.dom.iframe'], ['goog.dom', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.legacyconversions', 'goog.userAgent']);\ngoog.addDependency(\"dom/iframe_test.js\", ['goog.dom.iframeTest'], ['goog.dom', 'goog.dom.iframe', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/inputtype.js\", ['goog.dom.InputType'], []);\ngoog.addDependency(\"dom/inputtype_test.js\", ['goog.dom.InputTypeTest'], ['goog.dom.InputType', 'goog.object']);\ngoog.addDependency(\"dom/iter.js\", ['goog.dom.iter.AncestorIterator', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator'], ['goog.iter.Iterator', 'goog.iter.StopIteration']);\ngoog.addDependency(\"dom/iter_test.js\", ['goog.dom.iterTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.iter.AncestorIterator', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator', 'goog.testing.dom', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/multirange.js\", ['goog.dom.MultiRange', 'goog.dom.MultiRangeIterator'], ['goog.array', 'goog.dom.AbstractMultiRange', 'goog.dom.AbstractRange', 'goog.dom.RangeIterator', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TextRange', 'goog.iter.StopIteration', 'goog.log']);\ngoog.addDependency(\"dom/multirange_test.js\", ['goog.dom.MultiRangeTest'], ['goog.dom', 'goog.dom.MultiRange', 'goog.dom.Range', 'goog.iter', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/nodeiterator.js\", ['goog.dom.NodeIterator'], ['goog.dom.TagIterator']);\ngoog.addDependency(\"dom/nodeiterator_test.js\", ['goog.dom.NodeIteratorTest'], ['goog.dom', 'goog.dom.NodeIterator', 'goog.testing.dom', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/nodeoffset.js\", ['goog.dom.NodeOffset'], ['goog.Disposable', 'goog.dom.TagName']);\ngoog.addDependency(\"dom/nodeoffset_test.js\", ['goog.dom.NodeOffsetTest'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/nodetype.js\", ['goog.dom.NodeType'], []);\ngoog.addDependency(\"dom/range.js\", ['goog.dom.Range'], ['goog.dom', 'goog.dom.AbstractRange', 'goog.dom.BrowserFeature', 'goog.dom.ControlRange', 'goog.dom.MultiRange', 'goog.dom.NodeType', 'goog.dom.TextRange']);\ngoog.addDependency(\"dom/range_test.js\", ['goog.dom.RangeTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeType', 'goog.dom.TagName', 'goog.dom.TextRange', 'goog.dom.browserrange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"dom/rangeendpoint.js\", ['goog.dom.RangeEndpoint'], []);\ngoog.addDependency(\"dom/safe.js\", ['goog.dom.safe', 'goog.dom.safe.InsertAdjacentHtmlPosition'], ['goog.asserts', 'goog.html.SafeHtml', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.string', 'goog.string.Const']);\ngoog.addDependency(\"dom/safe_test.js\", ['goog.dom.safeTest'], ['goog.dom.safe', 'goog.dom.safe.InsertAdjacentHtmlPosition', 'goog.html.SafeHtml', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.testing', 'goog.string.Const', 'goog.testing', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/savedcaretrange.js\", ['goog.dom.SavedCaretRange'], ['goog.array', 'goog.dom', 'goog.dom.SavedRange', 'goog.dom.TagName', 'goog.string']);\ngoog.addDependency(\"dom/savedcaretrange_test.js\", ['goog.dom.SavedCaretRangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.SavedCaretRange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"dom/savedrange.js\", ['goog.dom.SavedRange'], ['goog.Disposable', 'goog.log']);\ngoog.addDependency(\"dom/savedrange_test.js\", ['goog.dom.SavedRangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"dom/selection.js\", ['goog.dom.selection'], ['goog.dom.InputType', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"dom/selection_test.js\", ['goog.dom.selectionTest'], ['goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.selection', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"dom/tagiterator.js\", ['goog.dom.TagIterator', 'goog.dom.TagWalkType'], ['goog.dom', 'goog.dom.NodeType', 'goog.iter.Iterator', 'goog.iter.StopIteration']);\ngoog.addDependency(\"dom/tagiterator_test.js\", ['goog.dom.TagIteratorTest'], ['goog.dom', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.dom.TagWalkType', 'goog.iter', 'goog.iter.StopIteration', 'goog.testing.dom', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/tagname.js\", ['goog.dom.TagName'], []);\ngoog.addDependency(\"dom/tagname_test.js\", ['goog.dom.TagNameTest'], ['goog.dom.TagName', 'goog.object', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/tags.js\", ['goog.dom.tags'], ['goog.object']);\ngoog.addDependency(\"dom/tags_test.js\", ['goog.dom.tagsTest'], ['goog.dom.tags', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/textrange.js\", ['goog.dom.TextRange'], ['goog.array', 'goog.dom', 'goog.dom.AbstractRange', 'goog.dom.RangeType', 'goog.dom.SavedRange', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.dom.browserrange', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"dom/textrange_test.js\", ['goog.dom.TextRangeTest'], ['goog.dom', 'goog.dom.ControlRange', 'goog.dom.Range', 'goog.dom.TextRange', 'goog.math.Coordinate', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"dom/textrangeiterator.js\", ['goog.dom.TextRangeIterator'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeIterator', 'goog.dom.TagName', 'goog.iter.StopIteration']);\ngoog.addDependency(\"dom/textrangeiterator_test.js\", ['goog.dom.TextRangeIteratorTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.iter.StopIteration', 'goog.testing.dom', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/vendor.js\", ['goog.dom.vendor'], ['goog.string', 'goog.userAgent']);\ngoog.addDependency(\"dom/vendor_test.js\", ['goog.dom.vendorTest'], ['goog.array', 'goog.dom.vendor', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgentTestUtil']);\ngoog.addDependency(\"dom/viewportsizemonitor.js\", ['goog.dom.ViewportSizeMonitor'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Size']);\ngoog.addDependency(\"dom/viewportsizemonitor_test.js\", ['goog.dom.ViewportSizeMonitorTest'], ['goog.dom.ViewportSizeMonitor', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/xml.js\", ['goog.dom.xml'], ['goog.dom', 'goog.dom.NodeType', 'goog.userAgent']);\ngoog.addDependency(\"dom/xml_test.js\", ['goog.dom.xmlTest'], ['goog.dom.TagName', 'goog.dom.xml', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"dom/animationframe/animationframe.js\", ['goog.dom.animationFrame', 'goog.dom.animationFrame.Spec', 'goog.dom.animationFrame.State'], ['goog.dom.animationFrame.polyfill']);\ngoog.addDependency(\"dom/animationframe/animationframe_test.js\", [], ['goog.dom.animationFrame', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/animationframe/polyfill.js\", ['goog.dom.animationFrame.polyfill'], []);\ngoog.addDependency(\"dom/browserrange/abstractrange.js\", ['goog.dom.browserrange.AbstractRange'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.TextRangeIterator', 'goog.iter', 'goog.math.Coordinate', 'goog.string', 'goog.string.StringBuffer', 'goog.userAgent']);\ngoog.addDependency(\"dom/browserrange/browserrange.js\", ['goog.dom.browserrange', 'goog.dom.browserrange.Error'], ['goog.dom', 'goog.dom.BrowserFeature', 'goog.dom.NodeType', 'goog.dom.browserrange.GeckoRange', 'goog.dom.browserrange.IeRange', 'goog.dom.browserrange.OperaRange', 'goog.dom.browserrange.W3cRange', 'goog.dom.browserrange.WebKitRange', 'goog.userAgent']);\ngoog.addDependency(\"dom/browserrange/browserrange_test.js\", ['goog.dom.browserrangeTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"dom/browserrange/geckorange.js\", ['goog.dom.browserrange.GeckoRange'], ['goog.dom.browserrange.W3cRange']);\ngoog.addDependency(\"dom/browserrange/ierange.js\", ['goog.dom.browserrange.IeRange'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange.AbstractRange', 'goog.log', 'goog.string']);\ngoog.addDependency(\"dom/browserrange/operarange.js\", ['goog.dom.browserrange.OperaRange'], ['goog.dom.browserrange.W3cRange']);\ngoog.addDependency(\"dom/browserrange/w3crange.js\", ['goog.dom.browserrange.W3cRange'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.RangeEndpoint', 'goog.dom.TagName', 'goog.dom.browserrange.AbstractRange', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"dom/browserrange/webkitrange.js\", ['goog.dom.browserrange.WebKitRange'], ['goog.dom.RangeEndpoint', 'goog.dom.browserrange.W3cRange', 'goog.userAgent']);\ngoog.addDependency(\"dom/pattern/abstractpattern.js\", ['goog.dom.pattern.AbstractPattern'], ['goog.dom.pattern.MatchType']);\ngoog.addDependency(\"dom/pattern/allchildren.js\", ['goog.dom.pattern.AllChildren'], ['goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']);\ngoog.addDependency(\"dom/pattern/childmatches.js\", ['goog.dom.pattern.ChildMatches'], ['goog.dom.pattern.AllChildren', 'goog.dom.pattern.MatchType']);\ngoog.addDependency(\"dom/pattern/endtag.js\", ['goog.dom.pattern.EndTag'], ['goog.dom.TagWalkType', 'goog.dom.pattern.Tag']);\ngoog.addDependency(\"dom/pattern/fulltag.js\", ['goog.dom.pattern.FullTag'], ['goog.dom.pattern.MatchType', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.Tag']);\ngoog.addDependency(\"dom/pattern/matcher.js\", ['goog.dom.pattern.Matcher'], ['goog.dom.TagIterator', 'goog.dom.pattern.MatchType', 'goog.iter']);\ngoog.addDependency(\"dom/pattern/matcher_test.js\", ['goog.dom.pattern.matcherTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.pattern.EndTag', 'goog.dom.pattern.FullTag', 'goog.dom.pattern.Matcher', 'goog.dom.pattern.Repeat', 'goog.dom.pattern.Sequence', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.callback.Counter', 'goog.dom.pattern.callback.Test', 'goog.iter.StopIteration', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/pattern/nodetype.js\", ['goog.dom.pattern.NodeType'], ['goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']);\ngoog.addDependency(\"dom/pattern/pattern.js\", ['goog.dom.pattern', 'goog.dom.pattern.MatchType'], []);\ngoog.addDependency(\"dom/pattern/pattern_test.js\", ['goog.dom.patternTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagWalkType', 'goog.dom.pattern.AllChildren', 'goog.dom.pattern.ChildMatches', 'goog.dom.pattern.EndTag', 'goog.dom.pattern.FullTag', 'goog.dom.pattern.MatchType', 'goog.dom.pattern.NodeType', 'goog.dom.pattern.Repeat', 'goog.dom.pattern.Sequence', 'goog.dom.pattern.StartTag', 'goog.dom.pattern.Text', 'goog.testing.jsunit']);\ngoog.addDependency(\"dom/pattern/repeat.js\", ['goog.dom.pattern.Repeat'], ['goog.dom.NodeType', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']);\ngoog.addDependency(\"dom/pattern/sequence.js\", ['goog.dom.pattern.Sequence'], ['goog.dom.NodeType', 'goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']);\ngoog.addDependency(\"dom/pattern/starttag.js\", ['goog.dom.pattern.StartTag'], ['goog.dom.TagWalkType', 'goog.dom.pattern.Tag']);\ngoog.addDependency(\"dom/pattern/tag.js\", ['goog.dom.pattern.Tag'], ['goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType', 'goog.object']);\ngoog.addDependency(\"dom/pattern/text.js\", ['goog.dom.pattern.Text'], ['goog.dom.NodeType', 'goog.dom.pattern', 'goog.dom.pattern.AbstractPattern', 'goog.dom.pattern.MatchType']);\ngoog.addDependency(\"dom/pattern/callback/callback.js\", ['goog.dom.pattern.callback'], ['goog.dom', 'goog.dom.TagWalkType', 'goog.iter']);\ngoog.addDependency(\"dom/pattern/callback/counter.js\", ['goog.dom.pattern.callback.Counter'], []);\ngoog.addDependency(\"dom/pattern/callback/test.js\", ['goog.dom.pattern.callback.Test'], ['goog.iter.StopIteration']);\ngoog.addDependency(\"editor/browserfeature.js\", ['goog.editor.BrowserFeature'], ['goog.editor.defines', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"editor/browserfeature_test.js\", ['goog.editor.BrowserFeatureTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/clicktoeditwrapper.js\", ['goog.editor.ClickToEditWrapper'], ['goog.Disposable', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.range', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventType']);\ngoog.addDependency(\"editor/clicktoeditwrapper_test.js\", ['goog.editor.ClickToEditWrapperTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.ClickToEditWrapper', 'goog.editor.SeamlessField', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"editor/command.js\", ['goog.editor.Command'], []);\ngoog.addDependency(\"editor/contenteditablefield.js\", ['goog.editor.ContentEditableField'], ['goog.asserts', 'goog.editor.Field', 'goog.log']);\ngoog.addDependency(\"editor/contenteditablefield_test.js\", ['goog.editor.ContentEditableFieldTest'], ['goog.dom', 'goog.editor.ContentEditableField', 'goog.editor.field_test', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/defines.js\", ['goog.editor.defines'], []);\ngoog.addDependency(\"editor/field.js\", ['goog.editor.Field', 'goog.editor.Field.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.array', 'goog.asserts', 'goog.async.Delay', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.editor.node', 'goog.editor.range', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.log', 'goog.log.Level', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"editor/field_test.js\", ['goog.editor.field_test'], ['goog.array', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.range', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.LooseMock', 'goog.testing.MockClock', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"editor/focus.js\", ['goog.editor.focus'], ['goog.dom.selection']);\ngoog.addDependency(\"editor/focus_test.js\", ['goog.editor.focusTest'], ['goog.dom.selection', 'goog.editor.BrowserFeature', 'goog.editor.focus', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/icontent.js\", ['goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo'], ['goog.dom', 'goog.editor.BrowserFeature', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"editor/icontent_test.js\", ['goog.editor.icontentTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/link.js\", ['goog.editor.Link'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.node', 'goog.editor.range', 'goog.string', 'goog.string.Unicode', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex']);\ngoog.addDependency(\"editor/link_test.js\", ['goog.editor.LinkTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Link', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/node.js\", ['goog.editor.node'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.iter.ChildIterator', 'goog.dom.iter.SiblingIterator', 'goog.iter', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.userAgent']);\ngoog.addDependency(\"editor/node_test.js\", ['goog.editor.nodeTest'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.node', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugin.js\", ['goog.editor.Plugin'], ['goog.events.EventTarget', 'goog.functions', 'goog.log', 'goog.object', 'goog.reflect', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugin_test.js\", ['goog.editor.PluginTest'], ['goog.editor.Field', 'goog.editor.Plugin', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/range.js\", ['goog.editor.range', 'goog.editor.range.Point'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.RangeEndpoint', 'goog.dom.SavedCaretRange', 'goog.editor.node', 'goog.editor.style', 'goog.iter', 'goog.userAgent']);\ngoog.addDependency(\"editor/range_test.js\", ['goog.editor.rangeTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.range', 'goog.editor.range.Point', 'goog.string', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/seamlessfield.js\", ['goog.editor.SeamlessField'], ['goog.cssom.iframe.style', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.safe', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.icontent', 'goog.editor.icontent.FieldFormatInfo', 'goog.editor.icontent.FieldStyleInfo', 'goog.editor.node', 'goog.events', 'goog.events.EventType', 'goog.html.uncheckedconversions', 'goog.log', 'goog.string.Const', 'goog.style']);\ngoog.addDependency(\"editor/seamlessfield_test.js\", ['goog.editor.seamlessfield_test'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.SeamlessField', 'goog.events', 'goog.functions', 'goog.style', 'goog.testing.MockClock', 'goog.testing.MockRange', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/style.js\", ['goog.editor.style'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.events.EventType', 'goog.object', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"editor/style_test.js\", ['goog.editor.styleTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.style', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.style', 'goog.testing.LooseMock', 'goog.testing.jsunit', 'goog.testing.mockmatchers']);\ngoog.addDependency(\"editor/table.js\", ['goog.editor.Table', 'goog.editor.TableCell', 'goog.editor.TableRow'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.log', 'goog.string.Unicode', 'goog.style']);\ngoog.addDependency(\"editor/table_test.js\", ['goog.editor.TableTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Table', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/abstractbubbleplugin.js\", ['goog.editor.plugins.AbstractBubblePlugin'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.Plugin', 'goog.editor.style', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.actionEventWrapper', 'goog.functions', 'goog.string.Unicode', 'goog.ui.Component', 'goog.ui.editor.Bubble', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/abstractbubbleplugin_test.js\", ['goog.editor.plugins.AbstractBubblePluginTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.functions', 'goog.style', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.editor.Bubble', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/abstractdialogplugin.js\", ['goog.editor.plugins.AbstractDialogPlugin', 'goog.editor.plugins.AbstractDialogPlugin.EventType'], ['goog.dom', 'goog.dom.Range', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.range', 'goog.events', 'goog.ui.editor.AbstractDialog']);\ngoog.addDependency(\"editor/plugins/abstractdialogplugin_test.js\", ['goog.editor.plugins.AbstractDialogPluginTest'], ['goog.dom.SavedRange', 'goog.dom.TagName', 'goog.editor.Field', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.events.Event', 'goog.events.EventHandler', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/abstracttabhandler.js\", ['goog.editor.plugins.AbstractTabHandler'], ['goog.editor.Plugin', 'goog.events.KeyCodes', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/abstracttabhandler_test.js\", ['goog.editor.plugins.AbstractTabHandlerTest'], ['goog.editor.Field', 'goog.editor.plugins.AbstractTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/basictextformatter.js\", ['goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.BasicTextFormatter.COMMAND'], ['goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.editor.style', 'goog.iter', 'goog.iter.StopIteration', 'goog.log', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.editor.messages', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/basictextformatter_test.js\", ['goog.editor.plugins.BasicTextFormatterTest'], ['goog.array', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.BasicTextFormatter', 'goog.object', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.LooseMock', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/blockquote.js\", ['goog.editor.plugins.Blockquote'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Plugin', 'goog.editor.node', 'goog.functions', 'goog.log']);\ngoog.addDependency(\"editor/plugins/blockquote_test.js\", ['goog.editor.plugins.BlockquoteTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.plugins.Blockquote', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/plugins/emoticons.js\", ['goog.editor.plugins.Emoticons'], ['goog.dom.TagName', 'goog.editor.Plugin', 'goog.editor.range', 'goog.functions', 'goog.ui.emoji.Emoji', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/emoticons_test.js\", ['goog.editor.plugins.EmoticonsTest'], ['goog.Uri', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.editor.Field', 'goog.editor.plugins.Emoticons', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/enterhandler.js\", ['goog.editor.plugins.EnterHandler'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.plugins.Blockquote', 'goog.editor.range', 'goog.editor.style', 'goog.events.KeyCodes', 'goog.functions', 'goog.object', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/enterhandler_test.js\", ['goog.editor.plugins.EnterHandlerTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.Blockquote', 'goog.editor.plugins.EnterHandler', 'goog.editor.range', 'goog.events', 'goog.events.KeyCodes', 'goog.testing.ExpectedFailures', 'goog.testing.MockClock', 'goog.testing.dom', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/firststrong.js\", ['goog.editor.plugins.FirstStrong'], ['goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.i18n.bidi', 'goog.i18n.uChar', 'goog.iter', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/firststrong_test.js\", ['goog.editor.plugins.FirstStrongTest'], ['goog.dom.Range', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.plugins.FirstStrong', 'goog.editor.range', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/headerformatter.js\", ['goog.editor.plugins.HeaderFormatter'], ['goog.editor.Command', 'goog.editor.Plugin', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/headerformatter_test.js\", ['goog.editor.plugins.HeaderFormatterTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.HeaderFormatter', 'goog.events.BrowserEvent', 'goog.testing.LooseMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/linkbubble.js\", ['goog.editor.plugins.LinkBubble', 'goog.editor.plugins.LinkBubble.Action'], ['goog.array', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.functions', 'goog.string', 'goog.style', 'goog.ui.editor.messages', 'goog.uri.utils', 'goog.window']);\ngoog.addDependency(\"editor/plugins/linkbubble_test.js\", ['goog.editor.plugins.LinkBubbleTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.Link', 'goog.editor.plugins.LinkBubble', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.string', 'goog.style', 'goog.testing.FunctionMock', 'goog.testing.PropertyReplacer', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/linkdialogplugin.js\", ['goog.editor.plugins.LinkDialogPlugin'], ['goog.array', 'goog.dom', 'goog.editor.Command', 'goog.editor.plugins.AbstractDialogPlugin', 'goog.events.EventHandler', 'goog.functions', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.uri.utils']);\ngoog.addDependency(\"editor/plugins/linkdialogplugin_test.js\", ['goog.ui.editor.plugins.LinkDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Link', 'goog.editor.plugins.LinkDialogPlugin', 'goog.string', 'goog.string.Unicode', 'goog.testing.MockControl', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.editor.dom', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/linkshortcutplugin.js\", ['goog.editor.plugins.LinkShortcutPlugin'], ['goog.editor.Command', 'goog.editor.Plugin']);\ngoog.addDependency(\"editor/plugins/linkshortcutplugin_test.js\", ['goog.editor.plugins.LinkShortcutPluginTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Field', 'goog.editor.plugins.BasicTextFormatter', 'goog.editor.plugins.LinkBubble', 'goog.editor.plugins.LinkShortcutPlugin', 'goog.events.KeyCodes', 'goog.testing.PropertyReplacer', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent.product']);\ngoog.addDependency(\"editor/plugins/listtabhandler.js\", ['goog.editor.plugins.ListTabHandler'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.plugins.AbstractTabHandler', 'goog.iter']);\ngoog.addDependency(\"editor/plugins/listtabhandler_test.js\", ['goog.editor.plugins.ListTabHandlerTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.plugins.ListTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/plugins/loremipsum.js\", ['goog.editor.plugins.LoremIpsum'], ['goog.asserts', 'goog.dom', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.functions', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/loremipsum_test.js\", ['goog.editor.plugins.LoremIpsumTest'], ['goog.dom', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.plugins.LoremIpsum', 'goog.string.Unicode', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/removeformatting.js\", ['goog.editor.plugins.RemoveFormatting'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.range', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/removeformatting_test.js\", ['goog.editor.plugins.RemoveFormattingTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.plugins.RemoveFormatting', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.dom', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/spacestabhandler.js\", ['goog.editor.plugins.SpacesTabHandler'], ['goog.dom.TagName', 'goog.editor.plugins.AbstractTabHandler', 'goog.editor.range']);\ngoog.addDependency(\"editor/plugins/spacestabhandler_test.js\", ['goog.editor.plugins.SpacesTabHandlerTest'], ['goog.dom', 'goog.dom.Range', 'goog.editor.plugins.SpacesTabHandler', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.functions', 'goog.testing.StrictMock', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/plugins/tableeditor.js\", ['goog.editor.plugins.TableEditor'], ['goog.array', 'goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Plugin', 'goog.editor.Table', 'goog.editor.node', 'goog.editor.range', 'goog.object', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/tableeditor_test.js\", ['goog.editor.plugins.TableEditorTest'], ['goog.dom', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.plugins.TableEditor', 'goog.object', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.JsUnitException', 'goog.testing.TestCase', 'goog.testing.editor.FieldMock', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/tagonenterhandler.js\", ['goog.editor.plugins.TagOnEnterHandler'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.Command', 'goog.editor.node', 'goog.editor.plugins.EnterHandler', 'goog.editor.range', 'goog.editor.style', 'goog.events.KeyCodes', 'goog.functions', 'goog.string.Unicode', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/tagonenterhandler_test.js\", ['goog.editor.plugins.TagOnEnterHandlerTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.plugins.TagOnEnterHandler', 'goog.events.KeyCodes', 'goog.string.Unicode', 'goog.testing.dom', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"editor/plugins/undoredo.js\", ['goog.editor.plugins.UndoRedo'], ['goog.dom', 'goog.dom.NodeOffset', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.Command', 'goog.editor.Field', 'goog.editor.Plugin', 'goog.editor.node', 'goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.events.EventHandler', 'goog.log', 'goog.object']);\ngoog.addDependency(\"editor/plugins/undoredo_test.js\", ['goog.editor.plugins.UndoRedoTest'], ['goog.array', 'goog.dom', 'goog.dom.browserrange', 'goog.editor.Field', 'goog.editor.plugins.LoremIpsum', 'goog.editor.plugins.UndoRedo', 'goog.events', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/plugins/undoredomanager.js\", ['goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoManager.EventType'], ['goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.events.EventTarget']);\ngoog.addDependency(\"editor/plugins/undoredomanager_test.js\", ['goog.editor.plugins.UndoRedoManagerTest'], ['goog.editor.plugins.UndoRedoManager', 'goog.editor.plugins.UndoRedoState', 'goog.events', 'goog.testing.StrictMock', 'goog.testing.jsunit']);\ngoog.addDependency(\"editor/plugins/undoredostate.js\", ['goog.editor.plugins.UndoRedoState'], ['goog.events.EventTarget']);\ngoog.addDependency(\"editor/plugins/undoredostate_test.js\", ['goog.editor.plugins.UndoRedoStateTest'], ['goog.editor.plugins.UndoRedoState', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/actioneventwrapper.js\", ['goog.events.actionEventWrapper'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.EventWrapper', 'goog.events.KeyCodes', 'goog.userAgent']);\ngoog.addDependency(\"events/actioneventwrapper_test.js\", ['goog.events.actionEventWrapperTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.events', 'goog.events.EventHandler', 'goog.events.KeyCodes', 'goog.events.actionEventWrapper', 'goog.testing.events', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/actionhandler.js\", ['goog.events.ActionEvent', 'goog.events.ActionHandler', 'goog.events.ActionHandler.EventType', 'goog.events.BeforeActionEvent'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent']);\ngoog.addDependency(\"events/actionhandler_test.js\", ['goog.events.ActionHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.ActionHandler', 'goog.testing.events', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/browserevent.js\", ['goog.events.BrowserEvent', 'goog.events.BrowserEvent.MouseButton'], ['goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventType', 'goog.reflect', 'goog.userAgent']);\ngoog.addDependency(\"events/browserevent_test.js\", ['goog.events.BrowserEventTest'], ['goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.math.Coordinate', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"events/browserfeature.js\", ['goog.events.BrowserFeature'], ['goog.userAgent']);\ngoog.addDependency(\"events/event.js\", ['goog.events.Event', 'goog.events.EventLike'], ['goog.Disposable', 'goog.events.EventId']);\ngoog.addDependency(\"events/event_test.js\", ['goog.events.EventTest'], ['goog.events.Event', 'goog.events.EventId', 'goog.events.EventTarget', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/eventhandler.js\", ['goog.events.EventHandler'], ['goog.Disposable', 'goog.events', 'goog.object']);\ngoog.addDependency(\"events/eventhandler_test.js\", ['goog.events.EventHandlerTest'], ['goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"events/eventid.js\", ['goog.events.EventId'], []);\ngoog.addDependency(\"events/events.js\", ['goog.events', 'goog.events.CaptureSimulationMode', 'goog.events.Key', 'goog.events.ListenableType'], ['goog.asserts', 'goog.debug.entryPointRegistry', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.Listenable', 'goog.events.ListenerMap']);\ngoog.addDependency(\"events/events_test.js\", ['goog.eventsTest'], ['goog.asserts.AssertionError', 'goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.BrowserFeature', 'goog.events.CaptureSimulationMode', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.Listener', 'goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"events/eventtarget.js\", ['goog.events.EventTarget'], ['goog.Disposable', 'goog.asserts', 'goog.events', 'goog.events.Event', 'goog.events.Listenable', 'goog.events.ListenerMap', 'goog.object']);\ngoog.addDependency(\"events/eventtarget_test.js\", ['goog.events.EventTargetTest'], ['goog.events.EventTarget', 'goog.events.Listenable', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/eventtarget_via_googevents_test.js\", ['goog.events.EventTargetGoogEventsTest'], ['goog.events', 'goog.events.EventTarget', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/eventtarget_via_w3cinterface_test.js\", ['goog.events.EventTargetW3CTest'], ['goog.events.EventTarget', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/eventtargettester.js\", ['goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType'], ['goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.testing.asserts', 'goog.testing.recordFunction']);\ngoog.addDependency(\"events/eventtype.js\", ['goog.events.EventType'], ['goog.userAgent']);\ngoog.addDependency(\"events/eventwrapper.js\", ['goog.events.EventWrapper'], []);\ngoog.addDependency(\"events/filedrophandler.js\", ['goog.events.FileDropHandler', 'goog.events.FileDropHandler.EventType'], ['goog.array', 'goog.dom', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.log', 'goog.log.Level']);\ngoog.addDependency(\"events/filedrophandler_test.js\", ['goog.events.FileDropHandlerTest'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.FileDropHandler', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"events/focushandler.js\", ['goog.events.FocusHandler', 'goog.events.FocusHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.userAgent']);\ngoog.addDependency(\"events/imehandler.js\", ['goog.events.ImeHandler', 'goog.events.ImeHandler.Event', 'goog.events.ImeHandler.EventType'], ['goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent']);\ngoog.addDependency(\"events/imehandler_test.js\", ['goog.events.ImeHandlerTest'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.ImeHandler', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"events/inputhandler.js\", ['goog.events.InputHandler', 'goog.events.InputHandler.EventType'], ['goog.Timer', 'goog.dom.TagName', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.KeyCodes', 'goog.userAgent']);\ngoog.addDependency(\"events/inputhandler_test.js\", ['goog.events.InputHandlerTest'], ['goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"events/keycodes.js\", ['goog.events.KeyCodes'], ['goog.userAgent']);\ngoog.addDependency(\"events/keycodes_test.js\", ['goog.events.KeyCodesTest'], ['goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"events/keyhandler.js\", ['goog.events.KeyEvent', 'goog.events.KeyHandler', 'goog.events.KeyHandler.EventType'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.userAgent']);\ngoog.addDependency(\"events/keyhandler_test.js\", ['goog.events.KeyEventTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"events/keynames.js\", ['goog.events.KeyNames'], []);\ngoog.addDependency(\"events/listenable.js\", ['goog.events.Listenable', 'goog.events.ListenableKey'], ['goog.events.EventId']);\ngoog.addDependency(\"events/listenable_test.js\", ['goog.events.ListenableTest'], ['goog.events.Listenable', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/listener.js\", ['goog.events.Listener'], ['goog.events.ListenableKey']);\ngoog.addDependency(\"events/listenermap.js\", ['goog.events.ListenerMap'], ['goog.array', 'goog.events.Listener', 'goog.object']);\ngoog.addDependency(\"events/listenermap_test.js\", ['goog.events.ListenerMapTest'], ['goog.dispose', 'goog.events', 'goog.events.EventId', 'goog.events.EventTarget', 'goog.events.ListenerMap', 'goog.testing.jsunit']);\ngoog.addDependency(\"events/mousewheelhandler.js\", ['goog.events.MouseWheelEvent', 'goog.events.MouseWheelHandler', 'goog.events.MouseWheelHandler.EventType'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.math', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"events/mousewheelhandler_test.js\", ['goog.events.MouseWheelHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.MouseWheelEvent', 'goog.events.MouseWheelHandler', 'goog.functions', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"events/onlinehandler.js\", ['goog.events.OnlineHandler', 'goog.events.OnlineHandler.EventType'], ['goog.Timer', 'goog.events.BrowserFeature', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.net.NetworkStatusMonitor']);\ngoog.addDependency(\"events/onlinelistener_test.js\", ['goog.events.OnlineHandlerTest'], ['goog.events', 'goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.OnlineHandler', 'goog.net.NetworkStatusMonitor', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"events/pastehandler.js\", ['goog.events.PasteHandler', 'goog.events.PasteHandler.EventType', 'goog.events.PasteHandler.State'], ['goog.Timer', 'goog.async.ConditionalDelay', 'goog.events.BrowserEvent', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.log', 'goog.userAgent']);\ngoog.addDependency(\"events/pastehandler_test.js\", ['goog.events.PasteHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.PasteHandler', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"events/wheelevent.js\", ['goog.events.WheelEvent'], ['goog.asserts', 'goog.events.BrowserEvent']);\ngoog.addDependency(\"events/wheelhandler.js\", ['goog.events.WheelHandler'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.WheelEvent', 'goog.style', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"events/wheelhandler_test.js\", ['goog.events.WheelHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.WheelEvent', 'goog.events.WheelHandler', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"format/emailaddress.js\", ['goog.format.EmailAddress'], ['goog.string']);\ngoog.addDependency(\"format/emailaddress_test.js\", ['goog.format.EmailAddressTest'], ['goog.array', 'goog.format.EmailAddress', 'goog.testing.jsunit']);\ngoog.addDependency(\"format/format.js\", ['goog.format'], ['goog.i18n.GraphemeBreak', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"format/format_test.js\", ['goog.formatTest'], ['goog.dom', 'goog.dom.TagName', 'goog.format', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"format/htmlprettyprinter.js\", ['goog.format.HtmlPrettyPrinter', 'goog.format.HtmlPrettyPrinter.Buffer'], ['goog.dom.TagName', 'goog.object', 'goog.string.StringBuffer']);\ngoog.addDependency(\"format/htmlprettyprinter_test.js\", ['goog.format.HtmlPrettyPrinterTest'], ['goog.format.HtmlPrettyPrinter', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"format/internationalizedemailaddress.js\", ['goog.format.InternationalizedEmailAddress'], ['goog.format.EmailAddress', 'goog.string']);\ngoog.addDependency(\"format/internationalizedemailaddress_test.js\", ['goog.format.InternationalizedEmailAddressTest'], ['goog.array', 'goog.format.InternationalizedEmailAddress', 'goog.testing.jsunit']);\ngoog.addDependency(\"format/jsonprettyprinter.js\", ['goog.format.JsonPrettyPrinter', 'goog.format.JsonPrettyPrinter.SafeHtmlDelimiters', 'goog.format.JsonPrettyPrinter.TextDelimiters'], ['goog.html.SafeHtml', 'goog.json', 'goog.json.Serializer', 'goog.string', 'goog.string.format']);\ngoog.addDependency(\"format/jsonprettyprinter_test.js\", ['goog.format.JsonPrettyPrinterTest'], ['goog.format.JsonPrettyPrinter', 'goog.testing.jsunit']);\ngoog.addDependency(\"fs/entry.js\", ['goog.fs.DirectoryEntry', 'goog.fs.DirectoryEntry.Behavior', 'goog.fs.Entry', 'goog.fs.FileEntry'], []);\ngoog.addDependency(\"fs/entryimpl.js\", ['goog.fs.DirectoryEntryImpl', 'goog.fs.EntryImpl', 'goog.fs.FileEntryImpl'], ['goog.array', 'goog.async.Deferred', 'goog.fs.DirectoryEntry', 'goog.fs.Entry', 'goog.fs.Error', 'goog.fs.FileEntry', 'goog.fs.FileWriter', 'goog.functions', 'goog.string']);\ngoog.addDependency(\"fs/error.js\", ['goog.fs.Error', 'goog.fs.Error.ErrorCode'], ['goog.debug.Error', 'goog.object', 'goog.string']);\ngoog.addDependency(\"fs/filereader.js\", ['goog.fs.FileReader', 'goog.fs.FileReader.EventType', 'goog.fs.FileReader.ReadyState'], ['goog.async.Deferred', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.ProgressEvent']);\ngoog.addDependency(\"fs/filesaver.js\", ['goog.fs.FileSaver', 'goog.fs.FileSaver.EventType', 'goog.fs.FileSaver.ReadyState'], ['goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.ProgressEvent']);\ngoog.addDependency(\"fs/filesystem.js\", ['goog.fs.FileSystem'], []);\ngoog.addDependency(\"fs/filesystemimpl.js\", ['goog.fs.FileSystemImpl'], ['goog.fs.DirectoryEntryImpl', 'goog.fs.FileSystem']);\ngoog.addDependency(\"fs/filewriter.js\", ['goog.fs.FileWriter'], ['goog.fs.Error', 'goog.fs.FileSaver']);\ngoog.addDependency(\"fs/fs.js\", ['goog.fs'], ['goog.array', 'goog.async.Deferred', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSystemImpl', 'goog.fs.url', 'goog.userAgent']);\ngoog.addDependency(\"fs/fs_test.js\", ['goog.fsTest'], ['goog.Promise', 'goog.array', 'goog.dom', 'goog.events', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.fs.FileSaver', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"fs/progressevent.js\", ['goog.fs.ProgressEvent'], ['goog.events.Event']);\ngoog.addDependency(\"fs/url.js\", ['goog.fs.url'], []);\ngoog.addDependency(\"fs/url_test.js\", ['goog.urlTest'], ['goog.fs.url', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"functions/functions.js\", ['goog.functions'], []);\ngoog.addDependency(\"functions/functions_test.js\", ['goog.functionsTest'], ['goog.array', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"fx/abstractdragdrop.js\", ['goog.fx.AbstractDragDrop', 'goog.fx.AbstractDragDrop.EventType', 'goog.fx.DragDropEvent', 'goog.fx.DragDropItem'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style']);\ngoog.addDependency(\"fx/abstractdragdrop_test.js\", ['goog.fx.AbstractDragDropTest'], ['goog.array', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.functions', 'goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/animation.js\", ['goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Animation.State', 'goog.fx.AnimationEvent'], ['goog.array', 'goog.events.Event', 'goog.fx.Transition', 'goog.fx.TransitionBase', 'goog.fx.anim', 'goog.fx.anim.Animated']);\ngoog.addDependency(\"fx/animation_test.js\", ['goog.fx.AnimationTest'], ['goog.events', 'goog.fx.Animation', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/animationqueue.js\", ['goog.fx.AnimationParallelQueue', 'goog.fx.AnimationQueue', 'goog.fx.AnimationSerialQueue'], ['goog.array', 'goog.asserts', 'goog.events', 'goog.fx.Transition', 'goog.fx.TransitionBase']);\ngoog.addDependency(\"fx/animationqueue_test.js\", ['goog.fx.AnimationQueueTest'], ['goog.events', 'goog.fx.Animation', 'goog.fx.AnimationParallelQueue', 'goog.fx.AnimationSerialQueue', 'goog.fx.Transition', 'goog.fx.anim', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/cssspriteanimation.js\", ['goog.fx.CssSpriteAnimation'], ['goog.fx.Animation']);\ngoog.addDependency(\"fx/cssspriteanimation_test.js\", ['goog.fx.CssSpriteAnimationTest'], ['goog.fx.CssSpriteAnimation', 'goog.math.Box', 'goog.math.Size', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/dom.js\", ['goog.fx.dom', 'goog.fx.dom.BgColorTransform', 'goog.fx.dom.ColorTransform', 'goog.fx.dom.Fade', 'goog.fx.dom.FadeIn', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOut', 'goog.fx.dom.FadeOutAndHide', 'goog.fx.dom.PredefinedEffect', 'goog.fx.dom.Resize', 'goog.fx.dom.ResizeHeight', 'goog.fx.dom.ResizeWidth', 'goog.fx.dom.Scroll', 'goog.fx.dom.Slide', 'goog.fx.dom.SlideFrom', 'goog.fx.dom.Swipe'], ['goog.color', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.style', 'goog.style.bidi']);\ngoog.addDependency(\"fx/dragdrop.js\", ['goog.fx.DragDrop'], ['goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem']);\ngoog.addDependency(\"fx/dragdropgroup.js\", ['goog.fx.DragDropGroup'], ['goog.dom', 'goog.fx.AbstractDragDrop', 'goog.fx.DragDropItem']);\ngoog.addDependency(\"fx/dragdropgroup_test.js\", ['goog.fx.DragDropGroupTest'], ['goog.events', 'goog.fx.DragDropGroup', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/dragger.js\", ['goog.fx.DragEvent', 'goog.fx.Dragger', 'goog.fx.Dragger.EventType'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.style', 'goog.style.bidi', 'goog.userAgent']);\ngoog.addDependency(\"fx/dragger_test.js\", ['goog.fx.DraggerTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Rect', 'goog.style.bidi', 'goog.testing.StrictMock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"fx/draglistgroup.js\", ['goog.fx.DragListDirection', 'goog.fx.DragListGroup', 'goog.fx.DragListGroup.EventType', 'goog.fx.DragListGroupEvent'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Coordinate', 'goog.string', 'goog.style']);\ngoog.addDependency(\"fx/draglistgroup_test.js\", ['goog.fx.DragListGroupTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.Event', 'goog.events.EventType', 'goog.fx.DragEvent', 'goog.fx.DragListDirection', 'goog.fx.DragListGroup', 'goog.fx.Dragger', 'goog.math.Coordinate', 'goog.object', 'goog.testing.events', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/dragscrollsupport.js\", ['goog.fx.DragScrollSupport'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.style']);\ngoog.addDependency(\"fx/dragscrollsupport_test.js\", ['goog.fx.DragScrollSupportTest'], ['goog.fx.DragScrollSupport', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/easing.js\", ['goog.fx.easing'], []);\ngoog.addDependency(\"fx/easing_test.js\", ['goog.fx.easingTest'], ['goog.fx.easing', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/fx.js\", ['goog.fx'], ['goog.asserts', 'goog.fx.Animation', 'goog.fx.Animation.EventType', 'goog.fx.Animation.State', 'goog.fx.AnimationEvent', 'goog.fx.Transition.EventType', 'goog.fx.easing']);\ngoog.addDependency(\"fx/fx_test.js\", ['goog.fxTest'], ['goog.fx.Animation', 'goog.object', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"fx/transition.js\", ['goog.fx.Transition', 'goog.fx.Transition.EventType'], []);\ngoog.addDependency(\"fx/transitionbase.js\", ['goog.fx.TransitionBase', 'goog.fx.TransitionBase.State'], ['goog.events.EventTarget', 'goog.fx.Transition']);\ngoog.addDependency(\"fx/anim/anim.js\", ['goog.fx.anim', 'goog.fx.anim.Animated'], ['goog.async.AnimationDelay', 'goog.async.Delay', 'goog.object']);\ngoog.addDependency(\"fx/anim/anim_test.js\", ['goog.fx.animTest'], ['goog.async.AnimationDelay', 'goog.async.Delay', 'goog.events', 'goog.functions', 'goog.fx.Animation', 'goog.fx.anim', 'goog.object', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"fx/css3/fx.js\", ['goog.fx.css3'], ['goog.fx.css3.Transition']);\ngoog.addDependency(\"fx/css3/transition.js\", ['goog.fx.css3.Transition'], ['goog.Timer', 'goog.asserts', 'goog.fx.TransitionBase', 'goog.style', 'goog.style.transition']);\ngoog.addDependency(\"fx/css3/transition_test.js\", ['goog.fx.css3.TransitionTest'], ['goog.dispose', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.fx.Transition', 'goog.fx.css3.Transition', 'goog.style.transition', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"graphics/abstractgraphics.js\", ['goog.graphics.AbstractGraphics'], ['goog.dom', 'goog.graphics.Path', 'goog.math.Coordinate', 'goog.math.Size', 'goog.style', 'goog.ui.Component']);\ngoog.addDependency(\"graphics/affinetransform.js\", ['goog.graphics.AffineTransform'], ['goog.math']);\ngoog.addDependency(\"graphics/canvaselement.js\", ['goog.graphics.CanvasEllipseElement', 'goog.graphics.CanvasGroupElement', 'goog.graphics.CanvasImageElement', 'goog.graphics.CanvasPathElement', 'goog.graphics.CanvasRectElement', 'goog.graphics.CanvasTextElement'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.Path', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement', 'goog.html.SafeHtml', 'goog.html.uncheckedconversions', 'goog.math', 'goog.string', 'goog.string.Const']);\ngoog.addDependency(\"graphics/canvasgraphics.js\", ['goog.graphics.CanvasGraphics'], ['goog.dom.TagName', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.CanvasEllipseElement', 'goog.graphics.CanvasGroupElement', 'goog.graphics.CanvasImageElement', 'goog.graphics.CanvasPathElement', 'goog.graphics.CanvasRectElement', 'goog.graphics.CanvasTextElement', 'goog.graphics.SolidFill', 'goog.math.Size', 'goog.style']);\ngoog.addDependency(\"graphics/canvasgraphics_test.js\", ['goog.graphics.CanvasGraphicsTest'], ['goog.dom', 'goog.graphics.CanvasGraphics', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.testing.jsunit']);\ngoog.addDependency(\"graphics/element.js\", ['goog.graphics.Element'], ['goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.events.Listenable', 'goog.graphics.AffineTransform', 'goog.math']);\ngoog.addDependency(\"graphics/ellipseelement.js\", ['goog.graphics.EllipseElement'], ['goog.graphics.StrokeAndFillElement']);\ngoog.addDependency(\"graphics/fill.js\", ['goog.graphics.Fill'], []);\ngoog.addDependency(\"graphics/font.js\", ['goog.graphics.Font'], []);\ngoog.addDependency(\"graphics/graphics.js\", ['goog.graphics'], ['goog.dom', 'goog.graphics.CanvasGraphics', 'goog.graphics.SvgGraphics', 'goog.graphics.VmlGraphics', 'goog.userAgent']);\ngoog.addDependency(\"graphics/groupelement.js\", ['goog.graphics.GroupElement'], ['goog.graphics.Element']);\ngoog.addDependency(\"graphics/imageelement.js\", ['goog.graphics.ImageElement'], ['goog.graphics.Element']);\ngoog.addDependency(\"graphics/lineargradient.js\", ['goog.graphics.LinearGradient'], ['goog.asserts', 'goog.graphics.Fill']);\ngoog.addDependency(\"graphics/path.js\", ['goog.graphics.Path', 'goog.graphics.Path.Segment'], ['goog.array', 'goog.math']);\ngoog.addDependency(\"graphics/pathelement.js\", ['goog.graphics.PathElement'], ['goog.graphics.StrokeAndFillElement']);\ngoog.addDependency(\"graphics/paths.js\", ['goog.graphics.paths'], ['goog.graphics.Path', 'goog.math.Coordinate']);\ngoog.addDependency(\"graphics/rectelement.js\", ['goog.graphics.RectElement'], ['goog.graphics.StrokeAndFillElement']);\ngoog.addDependency(\"graphics/solidfill.js\", ['goog.graphics.SolidFill'], ['goog.graphics.Fill']);\ngoog.addDependency(\"graphics/stroke.js\", ['goog.graphics.Stroke'], []);\ngoog.addDependency(\"graphics/strokeandfillelement.js\", ['goog.graphics.StrokeAndFillElement'], ['goog.graphics.Element']);\ngoog.addDependency(\"graphics/svgelement.js\", ['goog.graphics.SvgEllipseElement', 'goog.graphics.SvgGroupElement', 'goog.graphics.SvgImageElement', 'goog.graphics.SvgPathElement', 'goog.graphics.SvgRectElement', 'goog.graphics.SvgTextElement'], ['goog.dom', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement']);\ngoog.addDependency(\"graphics/svggraphics.js\", ['goog.graphics.SvgGraphics'], ['goog.Timer', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.LinearGradient', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.graphics.SvgEllipseElement', 'goog.graphics.SvgGroupElement', 'goog.graphics.SvgImageElement', 'goog.graphics.SvgPathElement', 'goog.graphics.SvgRectElement', 'goog.graphics.SvgTextElement', 'goog.math', 'goog.math.Size', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"graphics/textelement.js\", ['goog.graphics.TextElement'], ['goog.graphics.StrokeAndFillElement']);\ngoog.addDependency(\"graphics/vmlelement.js\", ['goog.graphics.VmlEllipseElement', 'goog.graphics.VmlGroupElement', 'goog.graphics.VmlImageElement', 'goog.graphics.VmlPathElement', 'goog.graphics.VmlRectElement', 'goog.graphics.VmlTextElement'], ['goog.dom', 'goog.graphics.EllipseElement', 'goog.graphics.GroupElement', 'goog.graphics.ImageElement', 'goog.graphics.PathElement', 'goog.graphics.RectElement', 'goog.graphics.TextElement']);\ngoog.addDependency(\"graphics/vmlgraphics.js\", ['goog.graphics.VmlGraphics'], ['goog.array', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.graphics.AbstractGraphics', 'goog.graphics.LinearGradient', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.VmlEllipseElement', 'goog.graphics.VmlGroupElement', 'goog.graphics.VmlImageElement', 'goog.graphics.VmlPathElement', 'goog.graphics.VmlRectElement', 'goog.graphics.VmlTextElement', 'goog.html.uncheckedconversions', 'goog.math', 'goog.math.Size', 'goog.reflect', 'goog.string', 'goog.string.Const', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"graphics/ext/coordinates.js\", ['goog.graphics.ext.coordinates'], ['goog.string']);\ngoog.addDependency(\"graphics/ext/element.js\", ['goog.graphics.ext.Element'], ['goog.events.EventTarget', 'goog.functions', 'goog.graphics.ext.coordinates']);\ngoog.addDependency(\"graphics/ext/ellipse.js\", ['goog.graphics.ext.Ellipse'], ['goog.graphics.ext.StrokeAndFillElement']);\ngoog.addDependency(\"graphics/ext/ext.js\", ['goog.graphics.ext'], ['goog.graphics.ext.Ellipse', 'goog.graphics.ext.Graphics', 'goog.graphics.ext.Group', 'goog.graphics.ext.Image', 'goog.graphics.ext.Rectangle', 'goog.graphics.ext.Shape', 'goog.graphics.ext.coordinates']);\ngoog.addDependency(\"graphics/ext/graphics.js\", ['goog.graphics.ext.Graphics'], ['goog.events', 'goog.events.EventType', 'goog.graphics', 'goog.graphics.ext.Group']);\ngoog.addDependency(\"graphics/ext/group.js\", ['goog.graphics.ext.Group'], ['goog.array', 'goog.graphics.ext.Element']);\ngoog.addDependency(\"graphics/ext/image.js\", ['goog.graphics.ext.Image'], ['goog.graphics.ext.Element']);\ngoog.addDependency(\"graphics/ext/path.js\", ['goog.graphics.ext.Path'], ['goog.graphics.AffineTransform', 'goog.graphics.Path', 'goog.math.Rect']);\ngoog.addDependency(\"graphics/ext/rectangle.js\", ['goog.graphics.ext.Rectangle'], ['goog.graphics.ext.StrokeAndFillElement']);\ngoog.addDependency(\"graphics/ext/shape.js\", ['goog.graphics.ext.Shape'], ['goog.graphics.ext.StrokeAndFillElement']);\ngoog.addDependency(\"graphics/ext/strokeandfillelement.js\", ['goog.graphics.ext.StrokeAndFillElement'], ['goog.graphics.ext.Element']);\ngoog.addDependency(\"history/event.js\", ['goog.history.Event'], ['goog.events.Event', 'goog.history.EventType']);\ngoog.addDependency(\"history/eventtype.js\", ['goog.history.EventType'], []);\ngoog.addDependency(\"history/history.js\", ['goog.History', 'goog.History.Event', 'goog.History.EventType'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.safe', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.history.Event', 'goog.history.EventType', 'goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.legacyconversions', 'goog.labs.userAgent.device', 'goog.memoize', 'goog.string', 'goog.string.Const', 'goog.userAgent']);\ngoog.addDependency(\"history/history_test.js\", ['goog.HistoryTest'], ['goog.History', 'goog.dispose', 'goog.dom', 'goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"history/html5history.js\", ['goog.history.Html5History', 'goog.history.Html5History.TokenTransformer'], ['goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.history.Event']);\ngoog.addDependency(\"history/html5history_test.js\", ['goog.history.Html5HistoryTest'], ['goog.Timer', 'goog.events', 'goog.events.EventType', 'goog.history.EventType', 'goog.history.Html5History', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.recordFunction']);\ngoog.addDependency(\"html/flash.js\", ['goog.html.flash'], ['goog.asserts', 'goog.html.SafeHtml']);\ngoog.addDependency(\"html/flash_test.js\", ['goog.html.flashTest'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/legacyconversions.js\", ['goog.html.legacyconversions'], ['goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl']);\ngoog.addDependency(\"html/legacyconversions_test.js\", ['goog.html.legacyconversionsTest'], ['goog.html.SafeHtml', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.legacyconversions', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/safehtml.js\", ['goog.html.SafeHtml'], ['goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.tags', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.labs.userAgent.browser', 'goog.object', 'goog.string', 'goog.string.Const', 'goog.string.TypedString']);\ngoog.addDependency(\"html/safehtml_test.js\", ['goog.html.safeHtmlTest'], ['goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.testing', 'goog.i18n.bidi.Dir', 'goog.object', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/safescript.js\", ['goog.html.SafeScript'], ['goog.asserts', 'goog.string.Const', 'goog.string.TypedString']);\ngoog.addDependency(\"html/safescript_test.js\", ['goog.html.safeScriptTest'], ['goog.html.SafeScript', 'goog.object', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/safestyle.js\", ['goog.html.SafeStyle'], ['goog.array', 'goog.asserts', 'goog.string', 'goog.string.Const', 'goog.string.TypedString']);\ngoog.addDependency(\"html/safestyle_test.js\", ['goog.html.safeStyleTest'], ['goog.html.SafeStyle', 'goog.object', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/safestylesheet.js\", ['goog.html.SafeStyleSheet'], ['goog.array', 'goog.asserts', 'goog.string', 'goog.string.Const', 'goog.string.TypedString']);\ngoog.addDependency(\"html/safestylesheet_test.js\", ['goog.html.safeStyleSheetTest'], ['goog.html.SafeStyleSheet', 'goog.object', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/safeurl.js\", ['goog.html.SafeUrl'], ['goog.asserts', 'goog.fs.url', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.string.Const', 'goog.string.TypedString']);\ngoog.addDependency(\"html/safeurl_test.js\", ['goog.html.safeUrlTest'], ['goog.html.SafeUrl', 'goog.i18n.bidi.Dir', 'goog.object', 'goog.string.Const', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"html/silverlight.js\", ['goog.html.silverlight'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.string.Const']);\ngoog.addDependency(\"html/silverlight_test.js\", ['goog.html.silverlightTest'], ['goog.html.SafeHtml', 'goog.html.TrustedResourceUrl', 'goog.html.silverlight', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/testing.js\", ['goog.html.testing'], ['goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl']);\ngoog.addDependency(\"html/trustedresourceurl.js\", ['goog.html.TrustedResourceUrl'], ['goog.asserts', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.string.Const', 'goog.string.TypedString']);\ngoog.addDependency(\"html/trustedresourceurl_test.js\", ['goog.html.trustedResourceUrlTest'], ['goog.html.TrustedResourceUrl', 'goog.i18n.bidi.Dir', 'goog.object', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/uncheckedconversions.js\", ['goog.html.uncheckedconversions'], ['goog.asserts', 'goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.string', 'goog.string.Const']);\ngoog.addDependency(\"html/uncheckedconversions_test.js\", ['goog.html.uncheckedconversionsTest'], ['goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.uncheckedconversions', 'goog.i18n.bidi.Dir', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"html/utils.js\", ['goog.html.utils'], ['goog.string']);\ngoog.addDependency(\"html/utils_test.js\", ['goog.html.UtilsTest'], ['goog.array', 'goog.dom.TagName', 'goog.html.utils', 'goog.object', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/bidi.js\", ['goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.DirectionalString', 'goog.i18n.bidi.Format'], []);\ngoog.addDependency(\"i18n/bidi_test.js\", ['goog.i18n.bidiTest'], ['goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/bidiformatter.js\", ['goog.i18n.BidiFormatter'], ['goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.i18n.bidi', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.Format']);\ngoog.addDependency(\"i18n/bidiformatter_test.js\", ['goog.i18n.BidiFormatterTest'], ['goog.html.SafeHtml', 'goog.i18n.BidiFormatter', 'goog.i18n.bidi.Dir', 'goog.i18n.bidi.Format', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/charlistdecompressor.js\", ['goog.i18n.CharListDecompressor'], ['goog.array', 'goog.i18n.uChar']);\ngoog.addDependency(\"i18n/charlistdecompressor_test.js\", ['goog.i18n.CharListDecompressorTest'], ['goog.i18n.CharListDecompressor', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/charpickerdata.js\", ['goog.i18n.CharPickerData'], []);\ngoog.addDependency(\"i18n/collation.js\", ['goog.i18n.collation'], []);\ngoog.addDependency(\"i18n/collation_test.js\", ['goog.i18n.collationTest'], ['goog.i18n.collation', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"i18n/compactnumberformatsymbols.js\", ['goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.CompactNumberFormatSymbols_af', 'goog.i18n.CompactNumberFormatSymbols_af_ZA', 'goog.i18n.CompactNumberFormatSymbols_am', 'goog.i18n.CompactNumberFormatSymbols_am_ET', 'goog.i18n.CompactNumberFormatSymbols_ar', 'goog.i18n.CompactNumberFormatSymbols_ar_001', 'goog.i18n.CompactNumberFormatSymbols_ar_EG', 'goog.i18n.CompactNumberFormatSymbols_ar_XB', 'goog.i18n.CompactNumberFormatSymbols_az', 'goog.i18n.CompactNumberFormatSymbols_az_Latn', 'goog.i18n.CompactNumberFormatSymbols_az_Latn_AZ', 'goog.i18n.CompactNumberFormatSymbols_be', 'goog.i18n.CompactNumberFormatSymbols_be_BY', 'goog.i18n.CompactNumberFormatSymbols_bg', 'goog.i18n.CompactNumberFormatSymbols_bg_BG', 'goog.i18n.CompactNumberFormatSymbols_bn', 'goog.i18n.CompactNumberFormatSymbols_bn_BD', 'goog.i18n.CompactNumberFormatSymbols_br', 'goog.i18n.CompactNumberFormatSymbols_br_FR', 'goog.i18n.CompactNumberFormatSymbols_bs', 'goog.i18n.CompactNumberFormatSymbols_bs_Latn', 'goog.i18n.CompactNumberFormatSymbols_bs_Latn_BA', 'goog.i18n.CompactNumberFormatSymbols_ca', 'goog.i18n.CompactNumberFormatSymbols_ca_AD', 'goog.i18n.CompactNumberFormatSymbols_ca_ES', 'goog.i18n.CompactNumberFormatSymbols_ca_ES_VALENCIA', 'goog.i18n.CompactNumberFormatSymbols_ca_FR', 'goog.i18n.CompactNumberFormatSymbols_ca_IT', 'goog.i18n.CompactNumberFormatSymbols_chr', 'goog.i18n.CompactNumberFormatSymbols_chr_US', 'goog.i18n.CompactNumberFormatSymbols_cs', 'goog.i18n.CompactNumberFormatSymbols_cs_CZ', 'goog.i18n.CompactNumberFormatSymbols_cy', 'goog.i18n.CompactNumberFormatSymbols_cy_GB', 'goog.i18n.CompactNumberFormatSymbols_da', 'goog.i18n.CompactNumberFormatSymbols_da_DK', 'goog.i18n.CompactNumberFormatSymbols_da_GL', 'goog.i18n.CompactNumberFormatSymbols_de', 'goog.i18n.CompactNumberFormatSymbols_de_AT', 'goog.i18n.CompactNumberFormatSymbols_de_BE', 'goog.i18n.CompactNumberFormatSymbols_de_CH', 'goog.i18n.CompactNumberFormatSymbols_de_DE', 'goog.i18n.CompactNumberFormatSymbols_de_LU', 'goog.i18n.CompactNumberFormatSymbols_el', 'goog.i18n.CompactNumberFormatSymbols_el_CY', 'goog.i18n.CompactNumberFormatSymbols_el_GR', 'goog.i18n.CompactNumberFormatSymbols_en', 'goog.i18n.CompactNumberFormatSymbols_en_001', 'goog.i18n.CompactNumberFormatSymbols_en_AS', 'goog.i18n.CompactNumberFormatSymbols_en_AU', 'goog.i18n.CompactNumberFormatSymbols_en_CA', 'goog.i18n.CompactNumberFormatSymbols_en_DG', 'goog.i18n.CompactNumberFormatSymbols_en_FM', 'goog.i18n.CompactNumberFormatSymbols_en_GB', 'goog.i18n.CompactNumberFormatSymbols_en_GU', 'goog.i18n.CompactNumberFormatSymbols_en_IE', 'goog.i18n.CompactNumberFormatSymbols_en_IN', 'goog.i18n.CompactNumberFormatSymbols_en_IO', 'goog.i18n.CompactNumberFormatSymbols_en_MH', 'goog.i18n.CompactNumberFormatSymbols_en_MP', 'goog.i18n.CompactNumberFormatSymbols_en_PR', 'goog.i18n.CompactNumberFormatSymbols_en_PW', 'goog.i18n.CompactNumberFormatSymbols_en_SG', 'goog.i18n.CompactNumberFormatSymbols_en_TC', 'goog.i18n.CompactNumberFormatSymbols_en_UM', 'goog.i18n.CompactNumberFormatSymbols_en_US', 'goog.i18n.CompactNumberFormatSymbols_en_VG', 'goog.i18n.CompactNumberFormatSymbols_en_VI', 'goog.i18n.CompactNumberFormatSymbols_en_XA', 'goog.i18n.CompactNumberFormatSymbols_en_ZA', 'goog.i18n.CompactNumberFormatSymbols_en_ZW', 'goog.i18n.CompactNumberFormatSymbols_es', 'goog.i18n.CompactNumberFormatSymbols_es_419', 'goog.i18n.CompactNumberFormatSymbols_es_EA', 'goog.i18n.CompactNumberFormatSymbols_es_ES', 'goog.i18n.CompactNumberFormatSymbols_es_IC', 'goog.i18n.CompactNumberFormatSymbols_es_MX', 'goog.i18n.CompactNumberFormatSymbols_es_US', 'goog.i18n.CompactNumberFormatSymbols_et', 'goog.i18n.CompactNumberFormatSymbols_et_EE', 'goog.i18n.CompactNumberFormatSymbols_eu', 'goog.i18n.CompactNumberFormatSymbols_eu_ES', 'goog.i18n.CompactNumberFormatSymbols_fa', 'goog.i18n.CompactNumberFormatSymbols_fa_IR', 'goog.i18n.CompactNumberFormatSymbols_fi', 'goog.i18n.CompactNumberFormatSymbols_fi_FI', 'goog.i18n.CompactNumberFormatSymbols_fil', 'goog.i18n.CompactNumberFormatSymbols_fil_PH', 'goog.i18n.CompactNumberFormatSymbols_fr', 'goog.i18n.CompactNumberFormatSymbols_fr_BL', 'goog.i18n.CompactNumberFormatSymbols_fr_CA', 'goog.i18n.CompactNumberFormatSymbols_fr_FR', 'goog.i18n.CompactNumberFormatSymbols_fr_GF', 'goog.i18n.CompactNumberFormatSymbols_fr_GP', 'goog.i18n.CompactNumberFormatSymbols_fr_MC', 'goog.i18n.CompactNumberFormatSymbols_fr_MF', 'goog.i18n.CompactNumberFormatSymbols_fr_MQ', 'goog.i18n.CompactNumberFormatSymbols_fr_PM', 'goog.i18n.CompactNumberFormatSymbols_fr_RE', 'goog.i18n.CompactNumberFormatSymbols_fr_YT', 'goog.i18n.CompactNumberFormatSymbols_ga', 'goog.i18n.CompactNumberFormatSymbols_ga_IE', 'goog.i18n.CompactNumberFormatSymbols_gl', 'goog.i18n.CompactNumberFormatSymbols_gl_ES', 'goog.i18n.CompactNumberFormatSymbols_gsw', 'goog.i18n.CompactNumberFormatSymbols_gsw_CH', 'goog.i18n.CompactNumberFormatSymbols_gsw_LI', 'goog.i18n.CompactNumberFormatSymbols_gu', 'goog.i18n.CompactNumberFormatSymbols_gu_IN', 'goog.i18n.CompactNumberFormatSymbols_haw', 'goog.i18n.CompactNumberFormatSymbols_haw_US', 'goog.i18n.CompactNumberFormatSymbols_he', 'goog.i18n.CompactNumberFormatSymbols_he_IL', 'goog.i18n.CompactNumberFormatSymbols_hi', 'goog.i18n.CompactNumberFormatSymbols_hi_IN', 'goog.i18n.CompactNumberFormatSymbols_hr', 'goog.i18n.CompactNumberFormatSymbols_hr_HR', 'goog.i18n.CompactNumberFormatSymbols_hu', 'goog.i18n.CompactNumberFormatSymbols_hu_HU', 'goog.i18n.CompactNumberFormatSymbols_hy', 'goog.i18n.CompactNumberFormatSymbols_hy_AM', 'goog.i18n.CompactNumberFormatSymbols_id', 'goog.i18n.CompactNumberFormatSymbols_id_ID', 'goog.i18n.CompactNumberFormatSymbols_in', 'goog.i18n.CompactNumberFormatSymbols_is', 'goog.i18n.CompactNumberFormatSymbols_is_IS', 'goog.i18n.CompactNumberFormatSymbols_it', 'goog.i18n.CompactNumberFormatSymbols_it_IT', 'goog.i18n.CompactNumberFormatSymbols_it_SM', 'goog.i18n.CompactNumberFormatSymbols_iw', 'goog.i18n.CompactNumberFormatSymbols_ja', 'goog.i18n.CompactNumberFormatSymbols_ja_JP', 'goog.i18n.CompactNumberFormatSymbols_ka', 'goog.i18n.CompactNumberFormatSymbols_ka_GE', 'goog.i18n.CompactNumberFormatSymbols_kk', 'goog.i18n.CompactNumberFormatSymbols_kk_KZ', 'goog.i18n.CompactNumberFormatSymbols_km', 'goog.i18n.CompactNumberFormatSymbols_km_KH', 'goog.i18n.CompactNumberFormatSymbols_kn', 'goog.i18n.CompactNumberFormatSymbols_kn_IN', 'goog.i18n.CompactNumberFormatSymbols_ko', 'goog.i18n.CompactNumberFormatSymbols_ko_KR', 'goog.i18n.CompactNumberFormatSymbols_ky', 'goog.i18n.CompactNumberFormatSymbols_ky_KG', 'goog.i18n.CompactNumberFormatSymbols_ln', 'goog.i18n.CompactNumberFormatSymbols_ln_CD', 'goog.i18n.CompactNumberFormatSymbols_lo', 'goog.i18n.CompactNumberFormatSymbols_lo_LA', 'goog.i18n.CompactNumberFormatSymbols_lt', 'goog.i18n.CompactNumberFormatSymbols_lt_LT', 'goog.i18n.CompactNumberFormatSymbols_lv', 'goog.i18n.CompactNumberFormatSymbols_lv_LV', 'goog.i18n.CompactNumberFormatSymbols_mk', 'goog.i18n.CompactNumberFormatSymbols_mk_MK', 'goog.i18n.CompactNumberFormatSymbols_ml', 'goog.i18n.CompactNumberFormatSymbols_ml_IN', 'goog.i18n.CompactNumberFormatSymbols_mn', 'goog.i18n.CompactNumberFormatSymbols_mn_MN', 'goog.i18n.CompactNumberFormatSymbols_mr', 'goog.i18n.CompactNumberFormatSymbols_mr_IN', 'goog.i18n.CompactNumberFormatSymbols_ms', 'goog.i18n.CompactNumberFormatSymbols_ms_MY', 'goog.i18n.CompactNumberFormatSymbols_mt', 'goog.i18n.CompactNumberFormatSymbols_mt_MT', 'goog.i18n.CompactNumberFormatSymbols_my', 'goog.i18n.CompactNumberFormatSymbols_my_MM', 'goog.i18n.CompactNumberFormatSymbols_nb', 'goog.i18n.CompactNumberFormatSymbols_nb_NO', 'goog.i18n.CompactNumberFormatSymbols_nb_SJ', 'goog.i18n.CompactNumberFormatSymbols_ne', 'goog.i18n.CompactNumberFormatSymbols_ne_NP', 'goog.i18n.CompactNumberFormatSymbols_nl', 'goog.i18n.CompactNumberFormatSymbols_nl_NL', 'goog.i18n.CompactNumberFormatSymbols_no', 'goog.i18n.CompactNumberFormatSymbols_no_NO', 'goog.i18n.CompactNumberFormatSymbols_or', 'goog.i18n.CompactNumberFormatSymbols_or_IN', 'goog.i18n.CompactNumberFormatSymbols_pa', 'goog.i18n.CompactNumberFormatSymbols_pa_Guru', 'goog.i18n.CompactNumberFormatSymbols_pa_Guru_IN', 'goog.i18n.CompactNumberFormatSymbols_pl', 'goog.i18n.CompactNumberFormatSymbols_pl_PL', 'goog.i18n.CompactNumberFormatSymbols_pt', 'goog.i18n.CompactNumberFormatSymbols_pt_BR', 'goog.i18n.CompactNumberFormatSymbols_pt_PT', 'goog.i18n.CompactNumberFormatSymbols_ro', 'goog.i18n.CompactNumberFormatSymbols_ro_RO', 'goog.i18n.CompactNumberFormatSymbols_ru', 'goog.i18n.CompactNumberFormatSymbols_ru_RU', 'goog.i18n.CompactNumberFormatSymbols_si', 'goog.i18n.CompactNumberFormatSymbols_si_LK', 'goog.i18n.CompactNumberFormatSymbols_sk', 'goog.i18n.CompactNumberFormatSymbols_sk_SK', 'goog.i18n.CompactNumberFormatSymbols_sl', 'goog.i18n.CompactNumberFormatSymbols_sl_SI', 'goog.i18n.CompactNumberFormatSymbols_sq', 'goog.i18n.CompactNumberFormatSymbols_sq_AL', 'goog.i18n.CompactNumberFormatSymbols_sr', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_RS', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_RS', 'goog.i18n.CompactNumberFormatSymbols_sv', 'goog.i18n.CompactNumberFormatSymbols_sv_SE', 'goog.i18n.CompactNumberFormatSymbols_sw', 'goog.i18n.CompactNumberFormatSymbols_sw_TZ', 'goog.i18n.CompactNumberFormatSymbols_ta', 'goog.i18n.CompactNumberFormatSymbols_ta_IN', 'goog.i18n.CompactNumberFormatSymbols_te', 'goog.i18n.CompactNumberFormatSymbols_te_IN', 'goog.i18n.CompactNumberFormatSymbols_th', 'goog.i18n.CompactNumberFormatSymbols_th_TH', 'goog.i18n.CompactNumberFormatSymbols_tl', 'goog.i18n.CompactNumberFormatSymbols_tr', 'goog.i18n.CompactNumberFormatSymbols_tr_TR', 'goog.i18n.CompactNumberFormatSymbols_uk', 'goog.i18n.CompactNumberFormatSymbols_uk_UA', 'goog.i18n.CompactNumberFormatSymbols_ur', 'goog.i18n.CompactNumberFormatSymbols_ur_PK', 'goog.i18n.CompactNumberFormatSymbols_uz', 'goog.i18n.CompactNumberFormatSymbols_uz_Latn', 'goog.i18n.CompactNumberFormatSymbols_uz_Latn_UZ', 'goog.i18n.CompactNumberFormatSymbols_vi', 'goog.i18n.CompactNumberFormatSymbols_vi_VN', 'goog.i18n.CompactNumberFormatSymbols_zh', 'goog.i18n.CompactNumberFormatSymbols_zh_CN', 'goog.i18n.CompactNumberFormatSymbols_zh_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_CN', 'goog.i18n.CompactNumberFormatSymbols_zh_TW', 'goog.i18n.CompactNumberFormatSymbols_zu', 'goog.i18n.CompactNumberFormatSymbols_zu_ZA'], []);\ngoog.addDependency(\"i18n/compactnumberformatsymbols_ext.js\", ['goog.i18n.CompactNumberFormatSymbolsExt', 'goog.i18n.CompactNumberFormatSymbols_af_NA', 'goog.i18n.CompactNumberFormatSymbols_agq', 'goog.i18n.CompactNumberFormatSymbols_agq_CM', 'goog.i18n.CompactNumberFormatSymbols_ak', 'goog.i18n.CompactNumberFormatSymbols_ak_GH', 'goog.i18n.CompactNumberFormatSymbols_ar_AE', 'goog.i18n.CompactNumberFormatSymbols_ar_BH', 'goog.i18n.CompactNumberFormatSymbols_ar_DJ', 'goog.i18n.CompactNumberFormatSymbols_ar_DZ', 'goog.i18n.CompactNumberFormatSymbols_ar_EH', 'goog.i18n.CompactNumberFormatSymbols_ar_ER', 'goog.i18n.CompactNumberFormatSymbols_ar_IL', 'goog.i18n.CompactNumberFormatSymbols_ar_IQ', 'goog.i18n.CompactNumberFormatSymbols_ar_JO', 'goog.i18n.CompactNumberFormatSymbols_ar_KM', 'goog.i18n.CompactNumberFormatSymbols_ar_KW', 'goog.i18n.CompactNumberFormatSymbols_ar_LB', 'goog.i18n.CompactNumberFormatSymbols_ar_LY', 'goog.i18n.CompactNumberFormatSymbols_ar_MA', 'goog.i18n.CompactNumberFormatSymbols_ar_MR', 'goog.i18n.CompactNumberFormatSymbols_ar_OM', 'goog.i18n.CompactNumberFormatSymbols_ar_PS', 'goog.i18n.CompactNumberFormatSymbols_ar_QA', 'goog.i18n.CompactNumberFormatSymbols_ar_SA', 'goog.i18n.CompactNumberFormatSymbols_ar_SD', 'goog.i18n.CompactNumberFormatSymbols_ar_SO', 'goog.i18n.CompactNumberFormatSymbols_ar_SS', 'goog.i18n.CompactNumberFormatSymbols_ar_SY', 'goog.i18n.CompactNumberFormatSymbols_ar_TD', 'goog.i18n.CompactNumberFormatSymbols_ar_TN', 'goog.i18n.CompactNumberFormatSymbols_ar_YE', 'goog.i18n.CompactNumberFormatSymbols_as', 'goog.i18n.CompactNumberFormatSymbols_as_IN', 'goog.i18n.CompactNumberFormatSymbols_asa', 'goog.i18n.CompactNumberFormatSymbols_asa_TZ', 'goog.i18n.CompactNumberFormatSymbols_ast', 'goog.i18n.CompactNumberFormatSymbols_ast_ES', 'goog.i18n.CompactNumberFormatSymbols_az_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_az_Cyrl_AZ', 'goog.i18n.CompactNumberFormatSymbols_bas', 'goog.i18n.CompactNumberFormatSymbols_bas_CM', 'goog.i18n.CompactNumberFormatSymbols_bem', 'goog.i18n.CompactNumberFormatSymbols_bem_ZM', 'goog.i18n.CompactNumberFormatSymbols_bez', 'goog.i18n.CompactNumberFormatSymbols_bez_TZ', 'goog.i18n.CompactNumberFormatSymbols_bm', 'goog.i18n.CompactNumberFormatSymbols_bm_ML', 'goog.i18n.CompactNumberFormatSymbols_bn_IN', 'goog.i18n.CompactNumberFormatSymbols_bo', 'goog.i18n.CompactNumberFormatSymbols_bo_CN', 'goog.i18n.CompactNumberFormatSymbols_bo_IN', 'goog.i18n.CompactNumberFormatSymbols_brx', 'goog.i18n.CompactNumberFormatSymbols_brx_IN', 'goog.i18n.CompactNumberFormatSymbols_bs_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_bs_Cyrl_BA', 'goog.i18n.CompactNumberFormatSymbols_ce', 'goog.i18n.CompactNumberFormatSymbols_ce_RU', 'goog.i18n.CompactNumberFormatSymbols_cgg', 'goog.i18n.CompactNumberFormatSymbols_cgg_UG', 'goog.i18n.CompactNumberFormatSymbols_ckb', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IQ', 'goog.i18n.CompactNumberFormatSymbols_ckb_Arab_IR', 'goog.i18n.CompactNumberFormatSymbols_ckb_IQ', 'goog.i18n.CompactNumberFormatSymbols_ckb_IR', 'goog.i18n.CompactNumberFormatSymbols_ckb_Latn', 'goog.i18n.CompactNumberFormatSymbols_ckb_Latn_IQ', 'goog.i18n.CompactNumberFormatSymbols_cu', 'goog.i18n.CompactNumberFormatSymbols_cu_RU', 'goog.i18n.CompactNumberFormatSymbols_dav', 'goog.i18n.CompactNumberFormatSymbols_dav_KE', 'goog.i18n.CompactNumberFormatSymbols_de_LI', 'goog.i18n.CompactNumberFormatSymbols_dje', 'goog.i18n.CompactNumberFormatSymbols_dje_NE', 'goog.i18n.CompactNumberFormatSymbols_dsb', 'goog.i18n.CompactNumberFormatSymbols_dsb_DE', 'goog.i18n.CompactNumberFormatSymbols_dua', 'goog.i18n.CompactNumberFormatSymbols_dua_CM', 'goog.i18n.CompactNumberFormatSymbols_dyo', 'goog.i18n.CompactNumberFormatSymbols_dyo_SN', 'goog.i18n.CompactNumberFormatSymbols_dz', 'goog.i18n.CompactNumberFormatSymbols_dz_BT', 'goog.i18n.CompactNumberFormatSymbols_ebu', 'goog.i18n.CompactNumberFormatSymbols_ebu_KE', 'goog.i18n.CompactNumberFormatSymbols_ee', 'goog.i18n.CompactNumberFormatSymbols_ee_GH', 'goog.i18n.CompactNumberFormatSymbols_ee_TG', 'goog.i18n.CompactNumberFormatSymbols_en_150', 'goog.i18n.CompactNumberFormatSymbols_en_AG', 'goog.i18n.CompactNumberFormatSymbols_en_AI', 'goog.i18n.CompactNumberFormatSymbols_en_AT', 'goog.i18n.CompactNumberFormatSymbols_en_BB', 'goog.i18n.CompactNumberFormatSymbols_en_BE', 'goog.i18n.CompactNumberFormatSymbols_en_BI', 'goog.i18n.CompactNumberFormatSymbols_en_BM', 'goog.i18n.CompactNumberFormatSymbols_en_BS', 'goog.i18n.CompactNumberFormatSymbols_en_BW', 'goog.i18n.CompactNumberFormatSymbols_en_BZ', 'goog.i18n.CompactNumberFormatSymbols_en_CC', 'goog.i18n.CompactNumberFormatSymbols_en_CH', 'goog.i18n.CompactNumberFormatSymbols_en_CK', 'goog.i18n.CompactNumberFormatSymbols_en_CM', 'goog.i18n.CompactNumberFormatSymbols_en_CX', 'goog.i18n.CompactNumberFormatSymbols_en_CY', 'goog.i18n.CompactNumberFormatSymbols_en_DE', 'goog.i18n.CompactNumberFormatSymbols_en_DK', 'goog.i18n.CompactNumberFormatSymbols_en_DM', 'goog.i18n.CompactNumberFormatSymbols_en_ER', 'goog.i18n.CompactNumberFormatSymbols_en_FI', 'goog.i18n.CompactNumberFormatSymbols_en_FJ', 'goog.i18n.CompactNumberFormatSymbols_en_FK', 'goog.i18n.CompactNumberFormatSymbols_en_GD', 'goog.i18n.CompactNumberFormatSymbols_en_GG', 'goog.i18n.CompactNumberFormatSymbols_en_GH', 'goog.i18n.CompactNumberFormatSymbols_en_GI', 'goog.i18n.CompactNumberFormatSymbols_en_GM', 'goog.i18n.CompactNumberFormatSymbols_en_GY', 'goog.i18n.CompactNumberFormatSymbols_en_HK', 'goog.i18n.CompactNumberFormatSymbols_en_IL', 'goog.i18n.CompactNumberFormatSymbols_en_IM', 'goog.i18n.CompactNumberFormatSymbols_en_JE', 'goog.i18n.CompactNumberFormatSymbols_en_JM', 'goog.i18n.CompactNumberFormatSymbols_en_KE', 'goog.i18n.CompactNumberFormatSymbols_en_KI', 'goog.i18n.CompactNumberFormatSymbols_en_KN', 'goog.i18n.CompactNumberFormatSymbols_en_KY', 'goog.i18n.CompactNumberFormatSymbols_en_LC', 'goog.i18n.CompactNumberFormatSymbols_en_LR', 'goog.i18n.CompactNumberFormatSymbols_en_LS', 'goog.i18n.CompactNumberFormatSymbols_en_MG', 'goog.i18n.CompactNumberFormatSymbols_en_MO', 'goog.i18n.CompactNumberFormatSymbols_en_MS', 'goog.i18n.CompactNumberFormatSymbols_en_MT', 'goog.i18n.CompactNumberFormatSymbols_en_MU', 'goog.i18n.CompactNumberFormatSymbols_en_MW', 'goog.i18n.CompactNumberFormatSymbols_en_MY', 'goog.i18n.CompactNumberFormatSymbols_en_NA', 'goog.i18n.CompactNumberFormatSymbols_en_NF', 'goog.i18n.CompactNumberFormatSymbols_en_NG', 'goog.i18n.CompactNumberFormatSymbols_en_NL', 'goog.i18n.CompactNumberFormatSymbols_en_NR', 'goog.i18n.CompactNumberFormatSymbols_en_NU', 'goog.i18n.CompactNumberFormatSymbols_en_NZ', 'goog.i18n.CompactNumberFormatSymbols_en_PG', 'goog.i18n.CompactNumberFormatSymbols_en_PH', 'goog.i18n.CompactNumberFormatSymbols_en_PK', 'goog.i18n.CompactNumberFormatSymbols_en_PN', 'goog.i18n.CompactNumberFormatSymbols_en_RW', 'goog.i18n.CompactNumberFormatSymbols_en_SB', 'goog.i18n.CompactNumberFormatSymbols_en_SC', 'goog.i18n.CompactNumberFormatSymbols_en_SD', 'goog.i18n.CompactNumberFormatSymbols_en_SE', 'goog.i18n.CompactNumberFormatSymbols_en_SH', 'goog.i18n.CompactNumberFormatSymbols_en_SI', 'goog.i18n.CompactNumberFormatSymbols_en_SL', 'goog.i18n.CompactNumberFormatSymbols_en_SS', 'goog.i18n.CompactNumberFormatSymbols_en_SX', 'goog.i18n.CompactNumberFormatSymbols_en_SZ', 'goog.i18n.CompactNumberFormatSymbols_en_TK', 'goog.i18n.CompactNumberFormatSymbols_en_TO', 'goog.i18n.CompactNumberFormatSymbols_en_TT', 'goog.i18n.CompactNumberFormatSymbols_en_TV', 'goog.i18n.CompactNumberFormatSymbols_en_TZ', 'goog.i18n.CompactNumberFormatSymbols_en_UG', 'goog.i18n.CompactNumberFormatSymbols_en_VC', 'goog.i18n.CompactNumberFormatSymbols_en_VU', 'goog.i18n.CompactNumberFormatSymbols_en_WS', 'goog.i18n.CompactNumberFormatSymbols_en_ZM', 'goog.i18n.CompactNumberFormatSymbols_eo', 'goog.i18n.CompactNumberFormatSymbols_eo_001', 'goog.i18n.CompactNumberFormatSymbols_es_AR', 'goog.i18n.CompactNumberFormatSymbols_es_BO', 'goog.i18n.CompactNumberFormatSymbols_es_CL', 'goog.i18n.CompactNumberFormatSymbols_es_CO', 'goog.i18n.CompactNumberFormatSymbols_es_CR', 'goog.i18n.CompactNumberFormatSymbols_es_CU', 'goog.i18n.CompactNumberFormatSymbols_es_DO', 'goog.i18n.CompactNumberFormatSymbols_es_EC', 'goog.i18n.CompactNumberFormatSymbols_es_GQ', 'goog.i18n.CompactNumberFormatSymbols_es_GT', 'goog.i18n.CompactNumberFormatSymbols_es_HN', 'goog.i18n.CompactNumberFormatSymbols_es_NI', 'goog.i18n.CompactNumberFormatSymbols_es_PA', 'goog.i18n.CompactNumberFormatSymbols_es_PE', 'goog.i18n.CompactNumberFormatSymbols_es_PH', 'goog.i18n.CompactNumberFormatSymbols_es_PR', 'goog.i18n.CompactNumberFormatSymbols_es_PY', 'goog.i18n.CompactNumberFormatSymbols_es_SV', 'goog.i18n.CompactNumberFormatSymbols_es_UY', 'goog.i18n.CompactNumberFormatSymbols_es_VE', 'goog.i18n.CompactNumberFormatSymbols_ewo', 'goog.i18n.CompactNumberFormatSymbols_ewo_CM', 'goog.i18n.CompactNumberFormatSymbols_fa_AF', 'goog.i18n.CompactNumberFormatSymbols_ff', 'goog.i18n.CompactNumberFormatSymbols_ff_CM', 'goog.i18n.CompactNumberFormatSymbols_ff_GN', 'goog.i18n.CompactNumberFormatSymbols_ff_MR', 'goog.i18n.CompactNumberFormatSymbols_ff_SN', 'goog.i18n.CompactNumberFormatSymbols_fo', 'goog.i18n.CompactNumberFormatSymbols_fo_DK', 'goog.i18n.CompactNumberFormatSymbols_fo_FO', 'goog.i18n.CompactNumberFormatSymbols_fr_BE', 'goog.i18n.CompactNumberFormatSymbols_fr_BF', 'goog.i18n.CompactNumberFormatSymbols_fr_BI', 'goog.i18n.CompactNumberFormatSymbols_fr_BJ', 'goog.i18n.CompactNumberFormatSymbols_fr_CD', 'goog.i18n.CompactNumberFormatSymbols_fr_CF', 'goog.i18n.CompactNumberFormatSymbols_fr_CG', 'goog.i18n.CompactNumberFormatSymbols_fr_CH', 'goog.i18n.CompactNumberFormatSymbols_fr_CI', 'goog.i18n.CompactNumberFormatSymbols_fr_CM', 'goog.i18n.CompactNumberFormatSymbols_fr_DJ', 'goog.i18n.CompactNumberFormatSymbols_fr_DZ', 'goog.i18n.CompactNumberFormatSymbols_fr_GA', 'goog.i18n.CompactNumberFormatSymbols_fr_GN', 'goog.i18n.CompactNumberFormatSymbols_fr_GQ', 'goog.i18n.CompactNumberFormatSymbols_fr_HT', 'goog.i18n.CompactNumberFormatSymbols_fr_KM', 'goog.i18n.CompactNumberFormatSymbols_fr_LU', 'goog.i18n.CompactNumberFormatSymbols_fr_MA', 'goog.i18n.CompactNumberFormatSymbols_fr_MG', 'goog.i18n.CompactNumberFormatSymbols_fr_ML', 'goog.i18n.CompactNumberFormatSymbols_fr_MR', 'goog.i18n.CompactNumberFormatSymbols_fr_MU', 'goog.i18n.CompactNumberFormatSymbols_fr_NC', 'goog.i18n.CompactNumberFormatSymbols_fr_NE', 'goog.i18n.CompactNumberFormatSymbols_fr_PF', 'goog.i18n.CompactNumberFormatSymbols_fr_RW', 'goog.i18n.CompactNumberFormatSymbols_fr_SC', 'goog.i18n.CompactNumberFormatSymbols_fr_SN', 'goog.i18n.CompactNumberFormatSymbols_fr_SY', 'goog.i18n.CompactNumberFormatSymbols_fr_TD', 'goog.i18n.CompactNumberFormatSymbols_fr_TG', 'goog.i18n.CompactNumberFormatSymbols_fr_TN', 'goog.i18n.CompactNumberFormatSymbols_fr_VU', 'goog.i18n.CompactNumberFormatSymbols_fr_WF', 'goog.i18n.CompactNumberFormatSymbols_fur', 'goog.i18n.CompactNumberFormatSymbols_fur_IT', 'goog.i18n.CompactNumberFormatSymbols_fy', 'goog.i18n.CompactNumberFormatSymbols_fy_NL', 'goog.i18n.CompactNumberFormatSymbols_gd', 'goog.i18n.CompactNumberFormatSymbols_gd_GB', 'goog.i18n.CompactNumberFormatSymbols_gsw_FR', 'goog.i18n.CompactNumberFormatSymbols_guz', 'goog.i18n.CompactNumberFormatSymbols_guz_KE', 'goog.i18n.CompactNumberFormatSymbols_gv', 'goog.i18n.CompactNumberFormatSymbols_gv_IM', 'goog.i18n.CompactNumberFormatSymbols_ha', 'goog.i18n.CompactNumberFormatSymbols_ha_GH', 'goog.i18n.CompactNumberFormatSymbols_ha_NE', 'goog.i18n.CompactNumberFormatSymbols_ha_NG', 'goog.i18n.CompactNumberFormatSymbols_hr_BA', 'goog.i18n.CompactNumberFormatSymbols_hsb', 'goog.i18n.CompactNumberFormatSymbols_hsb_DE', 'goog.i18n.CompactNumberFormatSymbols_ig', 'goog.i18n.CompactNumberFormatSymbols_ig_NG', 'goog.i18n.CompactNumberFormatSymbols_ii', 'goog.i18n.CompactNumberFormatSymbols_ii_CN', 'goog.i18n.CompactNumberFormatSymbols_it_CH', 'goog.i18n.CompactNumberFormatSymbols_jgo', 'goog.i18n.CompactNumberFormatSymbols_jgo_CM', 'goog.i18n.CompactNumberFormatSymbols_jmc', 'goog.i18n.CompactNumberFormatSymbols_jmc_TZ', 'goog.i18n.CompactNumberFormatSymbols_kab', 'goog.i18n.CompactNumberFormatSymbols_kab_DZ', 'goog.i18n.CompactNumberFormatSymbols_kam', 'goog.i18n.CompactNumberFormatSymbols_kam_KE', 'goog.i18n.CompactNumberFormatSymbols_kde', 'goog.i18n.CompactNumberFormatSymbols_kde_TZ', 'goog.i18n.CompactNumberFormatSymbols_kea', 'goog.i18n.CompactNumberFormatSymbols_kea_CV', 'goog.i18n.CompactNumberFormatSymbols_khq', 'goog.i18n.CompactNumberFormatSymbols_khq_ML', 'goog.i18n.CompactNumberFormatSymbols_ki', 'goog.i18n.CompactNumberFormatSymbols_ki_KE', 'goog.i18n.CompactNumberFormatSymbols_kkj', 'goog.i18n.CompactNumberFormatSymbols_kkj_CM', 'goog.i18n.CompactNumberFormatSymbols_kl', 'goog.i18n.CompactNumberFormatSymbols_kl_GL', 'goog.i18n.CompactNumberFormatSymbols_kln', 'goog.i18n.CompactNumberFormatSymbols_kln_KE', 'goog.i18n.CompactNumberFormatSymbols_ko_KP', 'goog.i18n.CompactNumberFormatSymbols_kok', 'goog.i18n.CompactNumberFormatSymbols_kok_IN', 'goog.i18n.CompactNumberFormatSymbols_ks', 'goog.i18n.CompactNumberFormatSymbols_ks_IN', 'goog.i18n.CompactNumberFormatSymbols_ksb', 'goog.i18n.CompactNumberFormatSymbols_ksb_TZ', 'goog.i18n.CompactNumberFormatSymbols_ksf', 'goog.i18n.CompactNumberFormatSymbols_ksf_CM', 'goog.i18n.CompactNumberFormatSymbols_ksh', 'goog.i18n.CompactNumberFormatSymbols_ksh_DE', 'goog.i18n.CompactNumberFormatSymbols_kw', 'goog.i18n.CompactNumberFormatSymbols_kw_GB', 'goog.i18n.CompactNumberFormatSymbols_lag', 'goog.i18n.CompactNumberFormatSymbols_lag_TZ', 'goog.i18n.CompactNumberFormatSymbols_lb', 'goog.i18n.CompactNumberFormatSymbols_lb_LU', 'goog.i18n.CompactNumberFormatSymbols_lg', 'goog.i18n.CompactNumberFormatSymbols_lg_UG', 'goog.i18n.CompactNumberFormatSymbols_lkt', 'goog.i18n.CompactNumberFormatSymbols_lkt_US', 'goog.i18n.CompactNumberFormatSymbols_ln_AO', 'goog.i18n.CompactNumberFormatSymbols_ln_CF', 'goog.i18n.CompactNumberFormatSymbols_ln_CG', 'goog.i18n.CompactNumberFormatSymbols_lrc', 'goog.i18n.CompactNumberFormatSymbols_lrc_IQ', 'goog.i18n.CompactNumberFormatSymbols_lrc_IR', 'goog.i18n.CompactNumberFormatSymbols_lu', 'goog.i18n.CompactNumberFormatSymbols_lu_CD', 'goog.i18n.CompactNumberFormatSymbols_luo', 'goog.i18n.CompactNumberFormatSymbols_luo_KE', 'goog.i18n.CompactNumberFormatSymbols_luy', 'goog.i18n.CompactNumberFormatSymbols_luy_KE', 'goog.i18n.CompactNumberFormatSymbols_mas', 'goog.i18n.CompactNumberFormatSymbols_mas_KE', 'goog.i18n.CompactNumberFormatSymbols_mas_TZ', 'goog.i18n.CompactNumberFormatSymbols_mer', 'goog.i18n.CompactNumberFormatSymbols_mer_KE', 'goog.i18n.CompactNumberFormatSymbols_mfe', 'goog.i18n.CompactNumberFormatSymbols_mfe_MU', 'goog.i18n.CompactNumberFormatSymbols_mg', 'goog.i18n.CompactNumberFormatSymbols_mg_MG', 'goog.i18n.CompactNumberFormatSymbols_mgh', 'goog.i18n.CompactNumberFormatSymbols_mgh_MZ', 'goog.i18n.CompactNumberFormatSymbols_mgo', 'goog.i18n.CompactNumberFormatSymbols_mgo_CM', 'goog.i18n.CompactNumberFormatSymbols_ms_BN', 'goog.i18n.CompactNumberFormatSymbols_ms_SG', 'goog.i18n.CompactNumberFormatSymbols_mua', 'goog.i18n.CompactNumberFormatSymbols_mua_CM', 'goog.i18n.CompactNumberFormatSymbols_mzn', 'goog.i18n.CompactNumberFormatSymbols_mzn_IR', 'goog.i18n.CompactNumberFormatSymbols_naq', 'goog.i18n.CompactNumberFormatSymbols_naq_NA', 'goog.i18n.CompactNumberFormatSymbols_nd', 'goog.i18n.CompactNumberFormatSymbols_nd_ZW', 'goog.i18n.CompactNumberFormatSymbols_ne_IN', 'goog.i18n.CompactNumberFormatSymbols_nl_AW', 'goog.i18n.CompactNumberFormatSymbols_nl_BE', 'goog.i18n.CompactNumberFormatSymbols_nl_BQ', 'goog.i18n.CompactNumberFormatSymbols_nl_CW', 'goog.i18n.CompactNumberFormatSymbols_nl_SR', 'goog.i18n.CompactNumberFormatSymbols_nl_SX', 'goog.i18n.CompactNumberFormatSymbols_nmg', 'goog.i18n.CompactNumberFormatSymbols_nmg_CM', 'goog.i18n.CompactNumberFormatSymbols_nn', 'goog.i18n.CompactNumberFormatSymbols_nn_NO', 'goog.i18n.CompactNumberFormatSymbols_nnh', 'goog.i18n.CompactNumberFormatSymbols_nnh_CM', 'goog.i18n.CompactNumberFormatSymbols_nus', 'goog.i18n.CompactNumberFormatSymbols_nus_SS', 'goog.i18n.CompactNumberFormatSymbols_nyn', 'goog.i18n.CompactNumberFormatSymbols_nyn_UG', 'goog.i18n.CompactNumberFormatSymbols_om', 'goog.i18n.CompactNumberFormatSymbols_om_ET', 'goog.i18n.CompactNumberFormatSymbols_om_KE', 'goog.i18n.CompactNumberFormatSymbols_os', 'goog.i18n.CompactNumberFormatSymbols_os_GE', 'goog.i18n.CompactNumberFormatSymbols_os_RU', 'goog.i18n.CompactNumberFormatSymbols_pa_Arab', 'goog.i18n.CompactNumberFormatSymbols_pa_Arab_PK', 'goog.i18n.CompactNumberFormatSymbols_prg', 'goog.i18n.CompactNumberFormatSymbols_prg_001', 'goog.i18n.CompactNumberFormatSymbols_ps', 'goog.i18n.CompactNumberFormatSymbols_ps_AF', 'goog.i18n.CompactNumberFormatSymbols_pt_AO', 'goog.i18n.CompactNumberFormatSymbols_pt_CV', 'goog.i18n.CompactNumberFormatSymbols_pt_GW', 'goog.i18n.CompactNumberFormatSymbols_pt_MO', 'goog.i18n.CompactNumberFormatSymbols_pt_MZ', 'goog.i18n.CompactNumberFormatSymbols_pt_ST', 'goog.i18n.CompactNumberFormatSymbols_pt_TL', 'goog.i18n.CompactNumberFormatSymbols_qu', 'goog.i18n.CompactNumberFormatSymbols_qu_BO', 'goog.i18n.CompactNumberFormatSymbols_qu_EC', 'goog.i18n.CompactNumberFormatSymbols_qu_PE', 'goog.i18n.CompactNumberFormatSymbols_rm', 'goog.i18n.CompactNumberFormatSymbols_rm_CH', 'goog.i18n.CompactNumberFormatSymbols_rn', 'goog.i18n.CompactNumberFormatSymbols_rn_BI', 'goog.i18n.CompactNumberFormatSymbols_ro_MD', 'goog.i18n.CompactNumberFormatSymbols_rof', 'goog.i18n.CompactNumberFormatSymbols_rof_TZ', 'goog.i18n.CompactNumberFormatSymbols_ru_BY', 'goog.i18n.CompactNumberFormatSymbols_ru_KG', 'goog.i18n.CompactNumberFormatSymbols_ru_KZ', 'goog.i18n.CompactNumberFormatSymbols_ru_MD', 'goog.i18n.CompactNumberFormatSymbols_ru_UA', 'goog.i18n.CompactNumberFormatSymbols_rw', 'goog.i18n.CompactNumberFormatSymbols_rw_RW', 'goog.i18n.CompactNumberFormatSymbols_rwk', 'goog.i18n.CompactNumberFormatSymbols_rwk_TZ', 'goog.i18n.CompactNumberFormatSymbols_sah', 'goog.i18n.CompactNumberFormatSymbols_sah_RU', 'goog.i18n.CompactNumberFormatSymbols_saq', 'goog.i18n.CompactNumberFormatSymbols_saq_KE', 'goog.i18n.CompactNumberFormatSymbols_sbp', 'goog.i18n.CompactNumberFormatSymbols_sbp_TZ', 'goog.i18n.CompactNumberFormatSymbols_se', 'goog.i18n.CompactNumberFormatSymbols_se_FI', 'goog.i18n.CompactNumberFormatSymbols_se_NO', 'goog.i18n.CompactNumberFormatSymbols_se_SE', 'goog.i18n.CompactNumberFormatSymbols_seh', 'goog.i18n.CompactNumberFormatSymbols_seh_MZ', 'goog.i18n.CompactNumberFormatSymbols_ses', 'goog.i18n.CompactNumberFormatSymbols_ses_ML', 'goog.i18n.CompactNumberFormatSymbols_sg', 'goog.i18n.CompactNumberFormatSymbols_sg_CF', 'goog.i18n.CompactNumberFormatSymbols_shi', 'goog.i18n.CompactNumberFormatSymbols_shi_Latn', 'goog.i18n.CompactNumberFormatSymbols_shi_Latn_MA', 'goog.i18n.CompactNumberFormatSymbols_shi_Tfng', 'goog.i18n.CompactNumberFormatSymbols_shi_Tfng_MA', 'goog.i18n.CompactNumberFormatSymbols_smn', 'goog.i18n.CompactNumberFormatSymbols_smn_FI', 'goog.i18n.CompactNumberFormatSymbols_sn', 'goog.i18n.CompactNumberFormatSymbols_sn_ZW', 'goog.i18n.CompactNumberFormatSymbols_so', 'goog.i18n.CompactNumberFormatSymbols_so_DJ', 'goog.i18n.CompactNumberFormatSymbols_so_ET', 'goog.i18n.CompactNumberFormatSymbols_so_KE', 'goog.i18n.CompactNumberFormatSymbols_so_SO', 'goog.i18n.CompactNumberFormatSymbols_sq_MK', 'goog.i18n.CompactNumberFormatSymbols_sq_XK', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_BA', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_ME', 'goog.i18n.CompactNumberFormatSymbols_sr_Cyrl_XK', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_BA', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_ME', 'goog.i18n.CompactNumberFormatSymbols_sr_Latn_XK', 'goog.i18n.CompactNumberFormatSymbols_sv_AX', 'goog.i18n.CompactNumberFormatSymbols_sv_FI', 'goog.i18n.CompactNumberFormatSymbols_sw_CD', 'goog.i18n.CompactNumberFormatSymbols_sw_KE', 'goog.i18n.CompactNumberFormatSymbols_sw_UG', 'goog.i18n.CompactNumberFormatSymbols_ta_LK', 'goog.i18n.CompactNumberFormatSymbols_ta_MY', 'goog.i18n.CompactNumberFormatSymbols_ta_SG', 'goog.i18n.CompactNumberFormatSymbols_teo', 'goog.i18n.CompactNumberFormatSymbols_teo_KE', 'goog.i18n.CompactNumberFormatSymbols_teo_UG', 'goog.i18n.CompactNumberFormatSymbols_ti', 'goog.i18n.CompactNumberFormatSymbols_ti_ER', 'goog.i18n.CompactNumberFormatSymbols_ti_ET', 'goog.i18n.CompactNumberFormatSymbols_tk', 'goog.i18n.CompactNumberFormatSymbols_tk_TM', 'goog.i18n.CompactNumberFormatSymbols_to', 'goog.i18n.CompactNumberFormatSymbols_to_TO', 'goog.i18n.CompactNumberFormatSymbols_tr_CY', 'goog.i18n.CompactNumberFormatSymbols_twq', 'goog.i18n.CompactNumberFormatSymbols_twq_NE', 'goog.i18n.CompactNumberFormatSymbols_tzm', 'goog.i18n.CompactNumberFormatSymbols_tzm_MA', 'goog.i18n.CompactNumberFormatSymbols_ug', 'goog.i18n.CompactNumberFormatSymbols_ug_CN', 'goog.i18n.CompactNumberFormatSymbols_ur_IN', 'goog.i18n.CompactNumberFormatSymbols_uz_Arab', 'goog.i18n.CompactNumberFormatSymbols_uz_Arab_AF', 'goog.i18n.CompactNumberFormatSymbols_uz_Cyrl', 'goog.i18n.CompactNumberFormatSymbols_uz_Cyrl_UZ', 'goog.i18n.CompactNumberFormatSymbols_vai', 'goog.i18n.CompactNumberFormatSymbols_vai_Latn', 'goog.i18n.CompactNumberFormatSymbols_vai_Latn_LR', 'goog.i18n.CompactNumberFormatSymbols_vai_Vaii', 'goog.i18n.CompactNumberFormatSymbols_vai_Vaii_LR', 'goog.i18n.CompactNumberFormatSymbols_vo', 'goog.i18n.CompactNumberFormatSymbols_vo_001', 'goog.i18n.CompactNumberFormatSymbols_vun', 'goog.i18n.CompactNumberFormatSymbols_vun_TZ', 'goog.i18n.CompactNumberFormatSymbols_wae', 'goog.i18n.CompactNumberFormatSymbols_wae_CH', 'goog.i18n.CompactNumberFormatSymbols_xog', 'goog.i18n.CompactNumberFormatSymbols_xog_UG', 'goog.i18n.CompactNumberFormatSymbols_yav', 'goog.i18n.CompactNumberFormatSymbols_yav_CM', 'goog.i18n.CompactNumberFormatSymbols_yi', 'goog.i18n.CompactNumberFormatSymbols_yi_001', 'goog.i18n.CompactNumberFormatSymbols_yo', 'goog.i18n.CompactNumberFormatSymbols_yo_BJ', 'goog.i18n.CompactNumberFormatSymbols_yo_NG', 'goog.i18n.CompactNumberFormatSymbols_zgh', 'goog.i18n.CompactNumberFormatSymbols_zgh_MA', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_MO', 'goog.i18n.CompactNumberFormatSymbols_zh_Hans_SG', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_HK', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_MO', 'goog.i18n.CompactNumberFormatSymbols_zh_Hant_TW'], []);\ngoog.addDependency(\"i18n/currency.js\", ['goog.i18n.currency', 'goog.i18n.currency.CurrencyInfo', 'goog.i18n.currency.CurrencyInfoTier2'], []);\ngoog.addDependency(\"i18n/currency_test.js\", ['goog.i18n.currencyTest'], ['goog.i18n.NumberFormat', 'goog.i18n.currency', 'goog.i18n.currency.CurrencyInfo', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/currencycodemap.js\", ['goog.i18n.currencyCodeMap', 'goog.i18n.currencyCodeMapTier2'], []);\ngoog.addDependency(\"i18n/datetimeformat.js\", ['goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeFormat.Format'], ['goog.asserts', 'goog.date', 'goog.i18n.DateTimeSymbols', 'goog.i18n.TimeZone', 'goog.string']);\ngoog.addDependency(\"i18n/datetimeformat_test.js\", ['goog.i18n.DateTimeFormatTest'], ['goog.date.Date', 'goog.date.DateTime', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimePatterns', 'goog.i18n.DateTimePatterns_ar', 'goog.i18n.DateTimePatterns_de', 'goog.i18n.DateTimePatterns_en', 'goog.i18n.DateTimePatterns_fa', 'goog.i18n.DateTimePatterns_fr', 'goog.i18n.DateTimePatterns_ja', 'goog.i18n.DateTimePatterns_sv', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_ar', 'goog.i18n.DateTimeSymbols_ar_AE', 'goog.i18n.DateTimeSymbols_ar_SA', 'goog.i18n.DateTimeSymbols_bn_BD', 'goog.i18n.DateTimeSymbols_de', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_en_GB', 'goog.i18n.DateTimeSymbols_en_IE', 'goog.i18n.DateTimeSymbols_en_IN', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_fr_DJ', 'goog.i18n.DateTimeSymbols_he_IL', 'goog.i18n.DateTimeSymbols_ja', 'goog.i18n.DateTimeSymbols_ro_RO', 'goog.i18n.DateTimeSymbols_sv', 'goog.i18n.TimeZone', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/datetimeparse.js\", ['goog.i18n.DateTimeParse'], ['goog.asserts', 'goog.date', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeSymbols']);\ngoog.addDependency(\"i18n/datetimeparse_test.js\", ['goog.i18n.DateTimeParseTest'], ['goog.date.Date', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeParse', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_pl', 'goog.i18n.DateTimeSymbols_zh', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"i18n/datetimepatterns.js\", ['goog.i18n.DateTimePatterns', 'goog.i18n.DateTimePatterns_af', 'goog.i18n.DateTimePatterns_am', 'goog.i18n.DateTimePatterns_ar', 'goog.i18n.DateTimePatterns_az', 'goog.i18n.DateTimePatterns_be', 'goog.i18n.DateTimePatterns_bg', 'goog.i18n.DateTimePatterns_bn', 'goog.i18n.DateTimePatterns_br', 'goog.i18n.DateTimePatterns_bs', 'goog.i18n.DateTimePatterns_ca', 'goog.i18n.DateTimePatterns_chr', 'goog.i18n.DateTimePatterns_cs', 'goog.i18n.DateTimePatterns_cy', 'goog.i18n.DateTimePatterns_da', 'goog.i18n.DateTimePatterns_de', 'goog.i18n.DateTimePatterns_de_AT', 'goog.i18n.DateTimePatterns_de_CH', 'goog.i18n.DateTimePatterns_el', 'goog.i18n.DateTimePatterns_en', 'goog.i18n.DateTimePatterns_en_AU', 'goog.i18n.DateTimePatterns_en_CA', 'goog.i18n.DateTimePatterns_en_GB', 'goog.i18n.DateTimePatterns_en_IE', 'goog.i18n.DateTimePatterns_en_IN', 'goog.i18n.DateTimePatterns_en_SG', 'goog.i18n.DateTimePatterns_en_US', 'goog.i18n.DateTimePatterns_en_ZA', 'goog.i18n.DateTimePatterns_es', 'goog.i18n.DateTimePatterns_es_419', 'goog.i18n.DateTimePatterns_es_ES', 'goog.i18n.DateTimePatterns_es_MX', 'goog.i18n.DateTimePatterns_es_US', 'goog.i18n.DateTimePatterns_et', 'goog.i18n.DateTimePatterns_eu', 'goog.i18n.DateTimePatterns_fa', 'goog.i18n.DateTimePatterns_fi', 'goog.i18n.DateTimePatterns_fil', 'goog.i18n.DateTimePatterns_fr', 'goog.i18n.DateTimePatterns_fr_CA', 'goog.i18n.DateTimePatterns_ga', 'goog.i18n.DateTimePatterns_gl', 'goog.i18n.DateTimePatterns_gsw', 'goog.i18n.DateTimePatterns_gu', 'goog.i18n.DateTimePatterns_haw', 'goog.i18n.DateTimePatterns_he', 'goog.i18n.DateTimePatterns_hi', 'goog.i18n.DateTimePatterns_hr', 'goog.i18n.DateTimePatterns_hu', 'goog.i18n.DateTimePatterns_hy', 'goog.i18n.DateTimePatterns_id', 'goog.i18n.DateTimePatterns_in', 'goog.i18n.DateTimePatterns_is', 'goog.i18n.DateTimePatterns_it', 'goog.i18n.DateTimePatterns_iw', 'goog.i18n.DateTimePatterns_ja', 'goog.i18n.DateTimePatterns_ka', 'goog.i18n.DateTimePatterns_kk', 'goog.i18n.DateTimePatterns_km', 'goog.i18n.DateTimePatterns_kn', 'goog.i18n.DateTimePatterns_ko', 'goog.i18n.DateTimePatterns_ky', 'goog.i18n.DateTimePatterns_ln', 'goog.i18n.DateTimePatterns_lo', 'goog.i18n.DateTimePatterns_lt', 'goog.i18n.DateTimePatterns_lv', 'goog.i18n.DateTimePatterns_mk', 'goog.i18n.DateTimePatterns_ml', 'goog.i18n.DateTimePatterns_mn', 'goog.i18n.DateTimePatterns_mo', 'goog.i18n.DateTimePatterns_mr', 'goog.i18n.DateTimePatterns_ms', 'goog.i18n.DateTimePatterns_mt', 'goog.i18n.DateTimePatterns_my', 'goog.i18n.DateTimePatterns_nb', 'goog.i18n.DateTimePatterns_ne', 'goog.i18n.DateTimePatterns_nl', 'goog.i18n.DateTimePatterns_no', 'goog.i18n.DateTimePatterns_no_NO', 'goog.i18n.DateTimePatterns_or', 'goog.i18n.DateTimePatterns_pa', 'goog.i18n.DateTimePatterns_pl', 'goog.i18n.DateTimePatterns_pt', 'goog.i18n.DateTimePatterns_pt_BR', 'goog.i18n.DateTimePatterns_pt_PT', 'goog.i18n.DateTimePatterns_ro', 'goog.i18n.DateTimePatterns_ru', 'goog.i18n.DateTimePatterns_sh', 'goog.i18n.DateTimePatterns_si', 'goog.i18n.DateTimePatterns_sk', 'goog.i18n.DateTimePatterns_sl', 'goog.i18n.DateTimePatterns_sq', 'goog.i18n.DateTimePatterns_sr', 'goog.i18n.DateTimePatterns_sr_Latn', 'goog.i18n.DateTimePatterns_sv', 'goog.i18n.DateTimePatterns_sw', 'goog.i18n.DateTimePatterns_ta', 'goog.i18n.DateTimePatterns_te', 'goog.i18n.DateTimePatterns_th', 'goog.i18n.DateTimePatterns_tl', 'goog.i18n.DateTimePatterns_tr', 'goog.i18n.DateTimePatterns_uk', 'goog.i18n.DateTimePatterns_ur', 'goog.i18n.DateTimePatterns_uz', 'goog.i18n.DateTimePatterns_vi', 'goog.i18n.DateTimePatterns_zh', 'goog.i18n.DateTimePatterns_zh_CN', 'goog.i18n.DateTimePatterns_zh_HK', 'goog.i18n.DateTimePatterns_zh_TW', 'goog.i18n.DateTimePatterns_zu'], []);\ngoog.addDependency(\"i18n/datetimepatternsext.js\", ['goog.i18n.DateTimePatternsExt', 'goog.i18n.DateTimePatterns_af_NA', 'goog.i18n.DateTimePatterns_af_ZA', 'goog.i18n.DateTimePatterns_agq', 'goog.i18n.DateTimePatterns_agq_CM', 'goog.i18n.DateTimePatterns_ak', 'goog.i18n.DateTimePatterns_ak_GH', 'goog.i18n.DateTimePatterns_am_ET', 'goog.i18n.DateTimePatterns_ar_001', 'goog.i18n.DateTimePatterns_ar_AE', 'goog.i18n.DateTimePatterns_ar_BH', 'goog.i18n.DateTimePatterns_ar_DJ', 'goog.i18n.DateTimePatterns_ar_DZ', 'goog.i18n.DateTimePatterns_ar_EG', 'goog.i18n.DateTimePatterns_ar_EH', 'goog.i18n.DateTimePatterns_ar_ER', 'goog.i18n.DateTimePatterns_ar_IL', 'goog.i18n.DateTimePatterns_ar_IQ', 'goog.i18n.DateTimePatterns_ar_JO', 'goog.i18n.DateTimePatterns_ar_KM', 'goog.i18n.DateTimePatterns_ar_KW', 'goog.i18n.DateTimePatterns_ar_LB', 'goog.i18n.DateTimePatterns_ar_LY', 'goog.i18n.DateTimePatterns_ar_MA', 'goog.i18n.DateTimePatterns_ar_MR', 'goog.i18n.DateTimePatterns_ar_OM', 'goog.i18n.DateTimePatterns_ar_PS', 'goog.i18n.DateTimePatterns_ar_QA', 'goog.i18n.DateTimePatterns_ar_SA', 'goog.i18n.DateTimePatterns_ar_SD', 'goog.i18n.DateTimePatterns_ar_SO', 'goog.i18n.DateTimePatterns_ar_SS', 'goog.i18n.DateTimePatterns_ar_SY', 'goog.i18n.DateTimePatterns_ar_TD', 'goog.i18n.DateTimePatterns_ar_TN', 'goog.i18n.DateTimePatterns_ar_XB', 'goog.i18n.DateTimePatterns_ar_YE', 'goog.i18n.DateTimePatterns_as', 'goog.i18n.DateTimePatterns_as_IN', 'goog.i18n.DateTimePatterns_asa', 'goog.i18n.DateTimePatterns_asa_TZ', 'goog.i18n.DateTimePatterns_az_Cyrl', 'goog.i18n.DateTimePatterns_az_Cyrl_AZ', 'goog.i18n.DateTimePatterns_az_Latn', 'goog.i18n.DateTimePatterns_az_Latn_AZ', 'goog.i18n.DateTimePatterns_bas', 'goog.i18n.DateTimePatterns_bas_CM', 'goog.i18n.DateTimePatterns_be_BY', 'goog.i18n.DateTimePatterns_bem', 'goog.i18n.DateTimePatterns_bem_ZM', 'goog.i18n.DateTimePatterns_bez', 'goog.i18n.DateTimePatterns_bez_TZ', 'goog.i18n.DateTimePatterns_bg_BG', 'goog.i18n.DateTimePatterns_bm', 'goog.i18n.DateTimePatterns_bm_ML', 'goog.i18n.DateTimePatterns_bn_BD', 'goog.i18n.DateTimePatterns_bn_IN', 'goog.i18n.DateTimePatterns_bo', 'goog.i18n.DateTimePatterns_bo_CN', 'goog.i18n.DateTimePatterns_bo_IN', 'goog.i18n.DateTimePatterns_br_FR', 'goog.i18n.DateTimePatterns_brx', 'goog.i18n.DateTimePatterns_brx_IN', 'goog.i18n.DateTimePatterns_bs_Cyrl', 'goog.i18n.DateTimePatterns_bs_Cyrl_BA', 'goog.i18n.DateTimePatterns_bs_Latn', 'goog.i18n.DateTimePatterns_bs_Latn_BA', 'goog.i18n.DateTimePatterns_ca_AD', 'goog.i18n.DateTimePatterns_ca_ES', 'goog.i18n.DateTimePatterns_ca_FR', 'goog.i18n.DateTimePatterns_ca_IT', 'goog.i18n.DateTimePatterns_ce', 'goog.i18n.DateTimePatterns_ce_RU', 'goog.i18n.DateTimePatterns_cgg', 'goog.i18n.DateTimePatterns_cgg_UG', 'goog.i18n.DateTimePatterns_chr_US', 'goog.i18n.DateTimePatterns_cs_CZ', 'goog.i18n.DateTimePatterns_cy_GB', 'goog.i18n.DateTimePatterns_da_DK', 'goog.i18n.DateTimePatterns_da_GL', 'goog.i18n.DateTimePatterns_dav', 'goog.i18n.DateTimePatterns_dav_KE', 'goog.i18n.DateTimePatterns_de_BE', 'goog.i18n.DateTimePatterns_de_DE', 'goog.i18n.DateTimePatterns_de_LI', 'goog.i18n.DateTimePatterns_de_LU', 'goog.i18n.DateTimePatterns_dje', 'goog.i18n.DateTimePatterns_dje_NE', 'goog.i18n.DateTimePatterns_dsb', 'goog.i18n.DateTimePatterns_dsb_DE', 'goog.i18n.DateTimePatterns_dua', 'goog.i18n.DateTimePatterns_dua_CM', 'goog.i18n.DateTimePatterns_dyo', 'goog.i18n.DateTimePatterns_dyo_SN', 'goog.i18n.DateTimePatterns_dz', 'goog.i18n.DateTimePatterns_dz_BT', 'goog.i18n.DateTimePatterns_ebu', 'goog.i18n.DateTimePatterns_ebu_KE', 'goog.i18n.DateTimePatterns_ee', 'goog.i18n.DateTimePatterns_ee_GH', 'goog.i18n.DateTimePatterns_ee_TG', 'goog.i18n.DateTimePatterns_el_CY', 'goog.i18n.DateTimePatterns_el_GR', 'goog.i18n.DateTimePatterns_en_001', 'goog.i18n.DateTimePatterns_en_150', 'goog.i18n.DateTimePatterns_en_AG', 'goog.i18n.DateTimePatterns_en_AI', 'goog.i18n.DateTimePatterns_en_AS', 'goog.i18n.DateTimePatterns_en_AT', 'goog.i18n.DateTimePatterns_en_BB', 'goog.i18n.DateTimePatterns_en_BE', 'goog.i18n.DateTimePatterns_en_BI', 'goog.i18n.DateTimePatterns_en_BM', 'goog.i18n.DateTimePatterns_en_BS', 'goog.i18n.DateTimePatterns_en_BW', 'goog.i18n.DateTimePatterns_en_BZ', 'goog.i18n.DateTimePatterns_en_CC', 'goog.i18n.DateTimePatterns_en_CH', 'goog.i18n.DateTimePatterns_en_CK', 'goog.i18n.DateTimePatterns_en_CM', 'goog.i18n.DateTimePatterns_en_CX', 'goog.i18n.DateTimePatterns_en_CY', 'goog.i18n.DateTimePatterns_en_DE', 'goog.i18n.DateTimePatterns_en_DG', 'goog.i18n.DateTimePatterns_en_DK', 'goog.i18n.DateTimePatterns_en_DM', 'goog.i18n.DateTimePatterns_en_ER', 'goog.i18n.DateTimePatterns_en_FI', 'goog.i18n.DateTimePatterns_en_FJ', 'goog.i18n.DateTimePatterns_en_FK', 'goog.i18n.DateTimePatterns_en_FM', 'goog.i18n.DateTimePatterns_en_GD', 'goog.i18n.DateTimePatterns_en_GG', 'goog.i18n.DateTimePatterns_en_GH', 'goog.i18n.DateTimePatterns_en_GI', 'goog.i18n.DateTimePatterns_en_GM', 'goog.i18n.DateTimePatterns_en_GU', 'goog.i18n.DateTimePatterns_en_GY', 'goog.i18n.DateTimePatterns_en_HK', 'goog.i18n.DateTimePatterns_en_IL', 'goog.i18n.DateTimePatterns_en_IM', 'goog.i18n.DateTimePatterns_en_IO', 'goog.i18n.DateTimePatterns_en_JE', 'goog.i18n.DateTimePatterns_en_JM', 'goog.i18n.DateTimePatterns_en_KE', 'goog.i18n.DateTimePatterns_en_KI', 'goog.i18n.DateTimePatterns_en_KN', 'goog.i18n.DateTimePatterns_en_KY', 'goog.i18n.DateTimePatterns_en_LC', 'goog.i18n.DateTimePatterns_en_LR', 'goog.i18n.DateTimePatterns_en_LS', 'goog.i18n.DateTimePatterns_en_MG', 'goog.i18n.DateTimePatterns_en_MH', 'goog.i18n.DateTimePatterns_en_MO', 'goog.i18n.DateTimePatterns_en_MP', 'goog.i18n.DateTimePatterns_en_MS', 'goog.i18n.DateTimePatterns_en_MT', 'goog.i18n.DateTimePatterns_en_MU', 'goog.i18n.DateTimePatterns_en_MW', 'goog.i18n.DateTimePatterns_en_MY', 'goog.i18n.DateTimePatterns_en_NA', 'goog.i18n.DateTimePatterns_en_NF', 'goog.i18n.DateTimePatterns_en_NG', 'goog.i18n.DateTimePatterns_en_NL', 'goog.i18n.DateTimePatterns_en_NR', 'goog.i18n.DateTimePatterns_en_NU', 'goog.i18n.DateTimePatterns_en_NZ', 'goog.i18n.DateTimePatterns_en_PG', 'goog.i18n.DateTimePatterns_en_PH', 'goog.i18n.DateTimePatterns_en_PK', 'goog.i18n.DateTimePatterns_en_PN', 'goog.i18n.DateTimePatterns_en_PR', 'goog.i18n.DateTimePatterns_en_PW', 'goog.i18n.DateTimePatterns_en_RW', 'goog.i18n.DateTimePatterns_en_SB', 'goog.i18n.DateTimePatterns_en_SC', 'goog.i18n.DateTimePatterns_en_SD', 'goog.i18n.DateTimePatterns_en_SE', 'goog.i18n.DateTimePatterns_en_SH', 'goog.i18n.DateTimePatterns_en_SI', 'goog.i18n.DateTimePatterns_en_SL', 'goog.i18n.DateTimePatterns_en_SS', 'goog.i18n.DateTimePatterns_en_SX', 'goog.i18n.DateTimePatterns_en_SZ', 'goog.i18n.DateTimePatterns_en_TC', 'goog.i18n.DateTimePatterns_en_TK', 'goog.i18n.DateTimePatterns_en_TO', 'goog.i18n.DateTimePatterns_en_TT', 'goog.i18n.DateTimePatterns_en_TV', 'goog.i18n.DateTimePatterns_en_TZ', 'goog.i18n.DateTimePatterns_en_UG', 'goog.i18n.DateTimePatterns_en_UM', 'goog.i18n.DateTimePatterns_en_US_POSIX', 'goog.i18n.DateTimePatterns_en_VC', 'goog.i18n.DateTimePatterns_en_VG', 'goog.i18n.DateTimePatterns_en_VI', 'goog.i18n.DateTimePatterns_en_VU', 'goog.i18n.DateTimePatterns_en_WS', 'goog.i18n.DateTimePatterns_en_XA', 'goog.i18n.DateTimePatterns_en_ZM', 'goog.i18n.DateTimePatterns_en_ZW', 'goog.i18n.DateTimePatterns_eo', 'goog.i18n.DateTimePatterns_es_AR', 'goog.i18n.DateTimePatterns_es_BO', 'goog.i18n.DateTimePatterns_es_CL', 'goog.i18n.DateTimePatterns_es_CO', 'goog.i18n.DateTimePatterns_es_CR', 'goog.i18n.DateTimePatterns_es_CU', 'goog.i18n.DateTimePatterns_es_DO', 'goog.i18n.DateTimePatterns_es_EA', 'goog.i18n.DateTimePatterns_es_EC', 'goog.i18n.DateTimePatterns_es_GQ', 'goog.i18n.DateTimePatterns_es_GT', 'goog.i18n.DateTimePatterns_es_HN', 'goog.i18n.DateTimePatterns_es_IC', 'goog.i18n.DateTimePatterns_es_NI', 'goog.i18n.DateTimePatterns_es_PA', 'goog.i18n.DateTimePatterns_es_PE', 'goog.i18n.DateTimePatterns_es_PH', 'goog.i18n.DateTimePatterns_es_PR', 'goog.i18n.DateTimePatterns_es_PY', 'goog.i18n.DateTimePatterns_es_SV', 'goog.i18n.DateTimePatterns_es_UY', 'goog.i18n.DateTimePatterns_es_VE', 'goog.i18n.DateTimePatterns_et_EE', 'goog.i18n.DateTimePatterns_eu_ES', 'goog.i18n.DateTimePatterns_ewo', 'goog.i18n.DateTimePatterns_ewo_CM', 'goog.i18n.DateTimePatterns_fa_AF', 'goog.i18n.DateTimePatterns_fa_IR', 'goog.i18n.DateTimePatterns_ff', 'goog.i18n.DateTimePatterns_ff_CM', 'goog.i18n.DateTimePatterns_ff_GN', 'goog.i18n.DateTimePatterns_ff_MR', 'goog.i18n.DateTimePatterns_ff_SN', 'goog.i18n.DateTimePatterns_fi_FI', 'goog.i18n.DateTimePatterns_fil_PH', 'goog.i18n.DateTimePatterns_fo', 'goog.i18n.DateTimePatterns_fo_DK', 'goog.i18n.DateTimePatterns_fo_FO', 'goog.i18n.DateTimePatterns_fr_BE', 'goog.i18n.DateTimePatterns_fr_BF', 'goog.i18n.DateTimePatterns_fr_BI', 'goog.i18n.DateTimePatterns_fr_BJ', 'goog.i18n.DateTimePatterns_fr_BL', 'goog.i18n.DateTimePatterns_fr_CD', 'goog.i18n.DateTimePatterns_fr_CF', 'goog.i18n.DateTimePatterns_fr_CG', 'goog.i18n.DateTimePatterns_fr_CH', 'goog.i18n.DateTimePatterns_fr_CI', 'goog.i18n.DateTimePatterns_fr_CM', 'goog.i18n.DateTimePatterns_fr_DJ', 'goog.i18n.DateTimePatterns_fr_DZ', 'goog.i18n.DateTimePatterns_fr_FR', 'goog.i18n.DateTimePatterns_fr_GA', 'goog.i18n.DateTimePatterns_fr_GF', 'goog.i18n.DateTimePatterns_fr_GN', 'goog.i18n.DateTimePatterns_fr_GP', 'goog.i18n.DateTimePatterns_fr_GQ', 'goog.i18n.DateTimePatterns_fr_HT', 'goog.i18n.DateTimePatterns_fr_KM', 'goog.i18n.DateTimePatterns_fr_LU', 'goog.i18n.DateTimePatterns_fr_MA', 'goog.i18n.DateTimePatterns_fr_MC', 'goog.i18n.DateTimePatterns_fr_MF', 'goog.i18n.DateTimePatterns_fr_MG', 'goog.i18n.DateTimePatterns_fr_ML', 'goog.i18n.DateTimePatterns_fr_MQ', 'goog.i18n.DateTimePatterns_fr_MR', 'goog.i18n.DateTimePatterns_fr_MU', 'goog.i18n.DateTimePatterns_fr_NC', 'goog.i18n.DateTimePatterns_fr_NE', 'goog.i18n.DateTimePatterns_fr_PF', 'goog.i18n.DateTimePatterns_fr_PM', 'goog.i18n.DateTimePatterns_fr_RE', 'goog.i18n.DateTimePatterns_fr_RW', 'goog.i18n.DateTimePatterns_fr_SC', 'goog.i18n.DateTimePatterns_fr_SN', 'goog.i18n.DateTimePatterns_fr_SY', 'goog.i18n.DateTimePatterns_fr_TD', 'goog.i18n.DateTimePatterns_fr_TG', 'goog.i18n.DateTimePatterns_fr_TN', 'goog.i18n.DateTimePatterns_fr_VU', 'goog.i18n.DateTimePatterns_fr_WF', 'goog.i18n.DateTimePatterns_fr_YT', 'goog.i18n.DateTimePatterns_fur', 'goog.i18n.DateTimePatterns_fur_IT', 'goog.i18n.DateTimePatterns_fy', 'goog.i18n.DateTimePatterns_fy_NL', 'goog.i18n.DateTimePatterns_ga_IE', 'goog.i18n.DateTimePatterns_gd', 'goog.i18n.DateTimePatterns_gd_GB', 'goog.i18n.DateTimePatterns_gl_ES', 'goog.i18n.DateTimePatterns_gsw_CH', 'goog.i18n.DateTimePatterns_gsw_FR', 'goog.i18n.DateTimePatterns_gsw_LI', 'goog.i18n.DateTimePatterns_gu_IN', 'goog.i18n.DateTimePatterns_guz', 'goog.i18n.DateTimePatterns_guz_KE', 'goog.i18n.DateTimePatterns_gv', 'goog.i18n.DateTimePatterns_gv_IM', 'goog.i18n.DateTimePatterns_ha', 'goog.i18n.DateTimePatterns_ha_GH', 'goog.i18n.DateTimePatterns_ha_NE', 'goog.i18n.DateTimePatterns_ha_NG', 'goog.i18n.DateTimePatterns_haw_US', 'goog.i18n.DateTimePatterns_he_IL', 'goog.i18n.DateTimePatterns_hi_IN', 'goog.i18n.DateTimePatterns_hr_BA', 'goog.i18n.DateTimePatterns_hr_HR', 'goog.i18n.DateTimePatterns_hsb', 'goog.i18n.DateTimePatterns_hsb_DE', 'goog.i18n.DateTimePatterns_hu_HU', 'goog.i18n.DateTimePatterns_hy_AM', 'goog.i18n.DateTimePatterns_id_ID', 'goog.i18n.DateTimePatterns_ig', 'goog.i18n.DateTimePatterns_ig_NG', 'goog.i18n.DateTimePatterns_ii', 'goog.i18n.DateTimePatterns_ii_CN', 'goog.i18n.DateTimePatterns_is_IS', 'goog.i18n.DateTimePatterns_it_CH', 'goog.i18n.DateTimePatterns_it_IT', 'goog.i18n.DateTimePatterns_it_SM', 'goog.i18n.DateTimePatterns_ja_JP', 'goog.i18n.DateTimePatterns_jgo', 'goog.i18n.DateTimePatterns_jgo_CM', 'goog.i18n.DateTimePatterns_jmc', 'goog.i18n.DateTimePatterns_jmc_TZ', 'goog.i18n.DateTimePatterns_ka_GE', 'goog.i18n.DateTimePatterns_kab', 'goog.i18n.DateTimePatterns_kab_DZ', 'goog.i18n.DateTimePatterns_kam', 'goog.i18n.DateTimePatterns_kam_KE', 'goog.i18n.DateTimePatterns_kde', 'goog.i18n.DateTimePatterns_kde_TZ', 'goog.i18n.DateTimePatterns_kea', 'goog.i18n.DateTimePatterns_kea_CV', 'goog.i18n.DateTimePatterns_khq', 'goog.i18n.DateTimePatterns_khq_ML', 'goog.i18n.DateTimePatterns_ki', 'goog.i18n.DateTimePatterns_ki_KE', 'goog.i18n.DateTimePatterns_kk_KZ', 'goog.i18n.DateTimePatterns_kkj', 'goog.i18n.DateTimePatterns_kkj_CM', 'goog.i18n.DateTimePatterns_kl', 'goog.i18n.DateTimePatterns_kl_GL', 'goog.i18n.DateTimePatterns_kln', 'goog.i18n.DateTimePatterns_kln_KE', 'goog.i18n.DateTimePatterns_km_KH', 'goog.i18n.DateTimePatterns_kn_IN', 'goog.i18n.DateTimePatterns_ko_KP', 'goog.i18n.DateTimePatterns_ko_KR', 'goog.i18n.DateTimePatterns_kok', 'goog.i18n.DateTimePatterns_kok_IN', 'goog.i18n.DateTimePatterns_ks', 'goog.i18n.DateTimePatterns_ks_IN', 'goog.i18n.DateTimePatterns_ksb', 'goog.i18n.DateTimePatterns_ksb_TZ', 'goog.i18n.DateTimePatterns_ksf', 'goog.i18n.DateTimePatterns_ksf_CM', 'goog.i18n.DateTimePatterns_ksh', 'goog.i18n.DateTimePatterns_ksh_DE', 'goog.i18n.DateTimePatterns_kw', 'goog.i18n.DateTimePatterns_kw_GB', 'goog.i18n.DateTimePatterns_ky_KG', 'goog.i18n.DateTimePatterns_lag', 'goog.i18n.DateTimePatterns_lag_TZ', 'goog.i18n.DateTimePatterns_lb', 'goog.i18n.DateTimePatterns_lb_LU', 'goog.i18n.DateTimePatterns_lg', 'goog.i18n.DateTimePatterns_lg_UG', 'goog.i18n.DateTimePatterns_lkt', 'goog.i18n.DateTimePatterns_lkt_US', 'goog.i18n.DateTimePatterns_ln_AO', 'goog.i18n.DateTimePatterns_ln_CD', 'goog.i18n.DateTimePatterns_ln_CF', 'goog.i18n.DateTimePatterns_ln_CG', 'goog.i18n.DateTimePatterns_lo_LA', 'goog.i18n.DateTimePatterns_lrc', 'goog.i18n.DateTimePatterns_lrc_IQ', 'goog.i18n.DateTimePatterns_lrc_IR', 'goog.i18n.DateTimePatterns_lt_LT', 'goog.i18n.DateTimePatterns_lu', 'goog.i18n.DateTimePatterns_lu_CD', 'goog.i18n.DateTimePatterns_luo', 'goog.i18n.DateTimePatterns_luo_KE', 'goog.i18n.DateTimePatterns_luy', 'goog.i18n.DateTimePatterns_luy_KE', 'goog.i18n.DateTimePatterns_lv_LV', 'goog.i18n.DateTimePatterns_mas', 'goog.i18n.DateTimePatterns_mas_KE', 'goog.i18n.DateTimePatterns_mas_TZ', 'goog.i18n.DateTimePatterns_mer', 'goog.i18n.DateTimePatterns_mer_KE', 'goog.i18n.DateTimePatterns_mfe', 'goog.i18n.DateTimePatterns_mfe_MU', 'goog.i18n.DateTimePatterns_mg', 'goog.i18n.DateTimePatterns_mg_MG', 'goog.i18n.DateTimePatterns_mgh', 'goog.i18n.DateTimePatterns_mgh_MZ', 'goog.i18n.DateTimePatterns_mgo', 'goog.i18n.DateTimePatterns_mgo_CM', 'goog.i18n.DateTimePatterns_mk_MK', 'goog.i18n.DateTimePatterns_ml_IN', 'goog.i18n.DateTimePatterns_mn_MN', 'goog.i18n.DateTimePatterns_mr_IN', 'goog.i18n.DateTimePatterns_ms_BN', 'goog.i18n.DateTimePatterns_ms_MY', 'goog.i18n.DateTimePatterns_ms_SG', 'goog.i18n.DateTimePatterns_mt_MT', 'goog.i18n.DateTimePatterns_mua', 'goog.i18n.DateTimePatterns_mua_CM', 'goog.i18n.DateTimePatterns_my_MM', 'goog.i18n.DateTimePatterns_mzn', 'goog.i18n.DateTimePatterns_mzn_IR', 'goog.i18n.DateTimePatterns_naq', 'goog.i18n.DateTimePatterns_naq_NA', 'goog.i18n.DateTimePatterns_nb_NO', 'goog.i18n.DateTimePatterns_nb_SJ', 'goog.i18n.DateTimePatterns_nd', 'goog.i18n.DateTimePatterns_nd_ZW', 'goog.i18n.DateTimePatterns_ne_IN', 'goog.i18n.DateTimePatterns_ne_NP', 'goog.i18n.DateTimePatterns_nl_AW', 'goog.i18n.DateTimePatterns_nl_BE', 'goog.i18n.DateTimePatterns_nl_BQ', 'goog.i18n.DateTimePatterns_nl_CW', 'goog.i18n.DateTimePatterns_nl_NL', 'goog.i18n.DateTimePatterns_nl_SR', 'goog.i18n.DateTimePatterns_nl_SX', 'goog.i18n.DateTimePatterns_nmg', 'goog.i18n.DateTimePatterns_nmg_CM', 'goog.i18n.DateTimePatterns_nn', 'goog.i18n.DateTimePatterns_nn_NO', 'goog.i18n.DateTimePatterns_nnh', 'goog.i18n.DateTimePatterns_nnh_CM', 'goog.i18n.DateTimePatterns_nus', 'goog.i18n.DateTimePatterns_nus_SS', 'goog.i18n.DateTimePatterns_nyn', 'goog.i18n.DateTimePatterns_nyn_UG', 'goog.i18n.DateTimePatterns_om', 'goog.i18n.DateTimePatterns_om_ET', 'goog.i18n.DateTimePatterns_om_KE', 'goog.i18n.DateTimePatterns_or_IN', 'goog.i18n.DateTimePatterns_os', 'goog.i18n.DateTimePatterns_os_GE', 'goog.i18n.DateTimePatterns_os_RU', 'goog.i18n.DateTimePatterns_pa_Arab', 'goog.i18n.DateTimePatterns_pa_Arab_PK', 'goog.i18n.DateTimePatterns_pa_Guru', 'goog.i18n.DateTimePatterns_pa_Guru_IN', 'goog.i18n.DateTimePatterns_pl_PL', 'goog.i18n.DateTimePatterns_ps', 'goog.i18n.DateTimePatterns_ps_AF', 'goog.i18n.DateTimePatterns_pt_AO', 'goog.i18n.DateTimePatterns_pt_CV', 'goog.i18n.DateTimePatterns_pt_GW', 'goog.i18n.DateTimePatterns_pt_MO', 'goog.i18n.DateTimePatterns_pt_MZ', 'goog.i18n.DateTimePatterns_pt_ST', 'goog.i18n.DateTimePatterns_pt_TL', 'goog.i18n.DateTimePatterns_qu', 'goog.i18n.DateTimePatterns_qu_BO', 'goog.i18n.DateTimePatterns_qu_EC', 'goog.i18n.DateTimePatterns_qu_PE', 'goog.i18n.DateTimePatterns_rm', 'goog.i18n.DateTimePatterns_rm_CH', 'goog.i18n.DateTimePatterns_rn', 'goog.i18n.DateTimePatterns_rn_BI', 'goog.i18n.DateTimePatterns_ro_MD', 'goog.i18n.DateTimePatterns_ro_RO', 'goog.i18n.DateTimePatterns_rof', 'goog.i18n.DateTimePatterns_rof_TZ', 'goog.i18n.DateTimePatterns_ru_BY', 'goog.i18n.DateTimePatterns_ru_KG', 'goog.i18n.DateTimePatterns_ru_KZ', 'goog.i18n.DateTimePatterns_ru_MD', 'goog.i18n.DateTimePatterns_ru_RU', 'goog.i18n.DateTimePatterns_ru_UA', 'goog.i18n.DateTimePatterns_rw', 'goog.i18n.DateTimePatterns_rw_RW', 'goog.i18n.DateTimePatterns_rwk', 'goog.i18n.DateTimePatterns_rwk_TZ', 'goog.i18n.DateTimePatterns_sah', 'goog.i18n.DateTimePatterns_sah_RU', 'goog.i18n.DateTimePatterns_saq', 'goog.i18n.DateTimePatterns_saq_KE', 'goog.i18n.DateTimePatterns_sbp', 'goog.i18n.DateTimePatterns_sbp_TZ', 'goog.i18n.DateTimePatterns_se', 'goog.i18n.DateTimePatterns_se_FI', 'goog.i18n.DateTimePatterns_se_NO', 'goog.i18n.DateTimePatterns_se_SE', 'goog.i18n.DateTimePatterns_seh', 'goog.i18n.DateTimePatterns_seh_MZ', 'goog.i18n.DateTimePatterns_ses', 'goog.i18n.DateTimePatterns_ses_ML', 'goog.i18n.DateTimePatterns_sg', 'goog.i18n.DateTimePatterns_sg_CF', 'goog.i18n.DateTimePatterns_shi', 'goog.i18n.DateTimePatterns_shi_Latn', 'goog.i18n.DateTimePatterns_shi_Latn_MA', 'goog.i18n.DateTimePatterns_shi_Tfng', 'goog.i18n.DateTimePatterns_shi_Tfng_MA', 'goog.i18n.DateTimePatterns_si_LK', 'goog.i18n.DateTimePatterns_sk_SK', 'goog.i18n.DateTimePatterns_sl_SI', 'goog.i18n.DateTimePatterns_smn', 'goog.i18n.DateTimePatterns_smn_FI', 'goog.i18n.DateTimePatterns_sn', 'goog.i18n.DateTimePatterns_sn_ZW', 'goog.i18n.DateTimePatterns_so', 'goog.i18n.DateTimePatterns_so_DJ', 'goog.i18n.DateTimePatterns_so_ET', 'goog.i18n.DateTimePatterns_so_KE', 'goog.i18n.DateTimePatterns_so_SO', 'goog.i18n.DateTimePatterns_sq_AL', 'goog.i18n.DateTimePatterns_sq_MK', 'goog.i18n.DateTimePatterns_sq_XK', 'goog.i18n.DateTimePatterns_sr_Cyrl', 'goog.i18n.DateTimePatterns_sr_Cyrl_BA', 'goog.i18n.DateTimePatterns_sr_Cyrl_ME', 'goog.i18n.DateTimePatterns_sr_Cyrl_RS', 'goog.i18n.DateTimePatterns_sr_Cyrl_XK', 'goog.i18n.DateTimePatterns_sr_Latn_BA', 'goog.i18n.DateTimePatterns_sr_Latn_ME', 'goog.i18n.DateTimePatterns_sr_Latn_RS', 'goog.i18n.DateTimePatterns_sr_Latn_XK', 'goog.i18n.DateTimePatterns_sv_AX', 'goog.i18n.DateTimePatterns_sv_FI', 'goog.i18n.DateTimePatterns_sv_SE', 'goog.i18n.DateTimePatterns_sw_CD', 'goog.i18n.DateTimePatterns_sw_KE', 'goog.i18n.DateTimePatterns_sw_TZ', 'goog.i18n.DateTimePatterns_sw_UG', 'goog.i18n.DateTimePatterns_ta_IN', 'goog.i18n.DateTimePatterns_ta_LK', 'goog.i18n.DateTimePatterns_ta_MY', 'goog.i18n.DateTimePatterns_ta_SG', 'goog.i18n.DateTimePatterns_te_IN', 'goog.i18n.DateTimePatterns_teo', 'goog.i18n.DateTimePatterns_teo_KE', 'goog.i18n.DateTimePatterns_teo_UG', 'goog.i18n.DateTimePatterns_th_TH', 'goog.i18n.DateTimePatterns_ti', 'goog.i18n.DateTimePatterns_ti_ER', 'goog.i18n.DateTimePatterns_ti_ET', 'goog.i18n.DateTimePatterns_to', 'goog.i18n.DateTimePatterns_to_TO', 'goog.i18n.DateTimePatterns_tr_CY', 'goog.i18n.DateTimePatterns_tr_TR', 'goog.i18n.DateTimePatterns_twq', 'goog.i18n.DateTimePatterns_twq_NE', 'goog.i18n.DateTimePatterns_tzm', 'goog.i18n.DateTimePatterns_tzm_MA', 'goog.i18n.DateTimePatterns_ug', 'goog.i18n.DateTimePatterns_ug_CN', 'goog.i18n.DateTimePatterns_uk_UA', 'goog.i18n.DateTimePatterns_ur_IN', 'goog.i18n.DateTimePatterns_ur_PK', 'goog.i18n.DateTimePatterns_uz_Arab', 'goog.i18n.DateTimePatterns_uz_Arab_AF', 'goog.i18n.DateTimePatterns_uz_Cyrl', 'goog.i18n.DateTimePatterns_uz_Cyrl_UZ', 'goog.i18n.DateTimePatterns_uz_Latn', 'goog.i18n.DateTimePatterns_uz_Latn_UZ', 'goog.i18n.DateTimePatterns_vai', 'goog.i18n.DateTimePatterns_vai_Latn', 'goog.i18n.DateTimePatterns_vai_Latn_LR', 'goog.i18n.DateTimePatterns_vai_Vaii', 'goog.i18n.DateTimePatterns_vai_Vaii_LR', 'goog.i18n.DateTimePatterns_vi_VN', 'goog.i18n.DateTimePatterns_vun', 'goog.i18n.DateTimePatterns_vun_TZ', 'goog.i18n.DateTimePatterns_wae', 'goog.i18n.DateTimePatterns_wae_CH', 'goog.i18n.DateTimePatterns_xog', 'goog.i18n.DateTimePatterns_xog_UG', 'goog.i18n.DateTimePatterns_yav', 'goog.i18n.DateTimePatterns_yav_CM', 'goog.i18n.DateTimePatterns_yi', 'goog.i18n.DateTimePatterns_yi_001', 'goog.i18n.DateTimePatterns_yo', 'goog.i18n.DateTimePatterns_yo_BJ', 'goog.i18n.DateTimePatterns_yo_NG', 'goog.i18n.DateTimePatterns_zgh', 'goog.i18n.DateTimePatterns_zgh_MA', 'goog.i18n.DateTimePatterns_zh_Hans', 'goog.i18n.DateTimePatterns_zh_Hans_CN', 'goog.i18n.DateTimePatterns_zh_Hans_HK', 'goog.i18n.DateTimePatterns_zh_Hans_MO', 'goog.i18n.DateTimePatterns_zh_Hans_SG', 'goog.i18n.DateTimePatterns_zh_Hant', 'goog.i18n.DateTimePatterns_zh_Hant_HK', 'goog.i18n.DateTimePatterns_zh_Hant_MO', 'goog.i18n.DateTimePatterns_zh_Hant_TW', 'goog.i18n.DateTimePatterns_zu_ZA'], ['goog.i18n.DateTimePatterns']);\ngoog.addDependency(\"i18n/datetimesymbols.js\", ['goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_af', 'goog.i18n.DateTimeSymbols_am', 'goog.i18n.DateTimeSymbols_ar', 'goog.i18n.DateTimeSymbols_az', 'goog.i18n.DateTimeSymbols_be', 'goog.i18n.DateTimeSymbols_bg', 'goog.i18n.DateTimeSymbols_bn', 'goog.i18n.DateTimeSymbols_br', 'goog.i18n.DateTimeSymbols_bs', 'goog.i18n.DateTimeSymbols_ca', 'goog.i18n.DateTimeSymbols_chr', 'goog.i18n.DateTimeSymbols_cs', 'goog.i18n.DateTimeSymbols_cy', 'goog.i18n.DateTimeSymbols_da', 'goog.i18n.DateTimeSymbols_de', 'goog.i18n.DateTimeSymbols_de_AT', 'goog.i18n.DateTimeSymbols_de_CH', 'goog.i18n.DateTimeSymbols_el', 'goog.i18n.DateTimeSymbols_en', 'goog.i18n.DateTimeSymbols_en_AU', 'goog.i18n.DateTimeSymbols_en_CA', 'goog.i18n.DateTimeSymbols_en_GB', 'goog.i18n.DateTimeSymbols_en_IE', 'goog.i18n.DateTimeSymbols_en_IN', 'goog.i18n.DateTimeSymbols_en_ISO', 'goog.i18n.DateTimeSymbols_en_SG', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_en_ZA', 'goog.i18n.DateTimeSymbols_es', 'goog.i18n.DateTimeSymbols_es_419', 'goog.i18n.DateTimeSymbols_es_ES', 'goog.i18n.DateTimeSymbols_es_MX', 'goog.i18n.DateTimeSymbols_es_US', 'goog.i18n.DateTimeSymbols_et', 'goog.i18n.DateTimeSymbols_eu', 'goog.i18n.DateTimeSymbols_fa', 'goog.i18n.DateTimeSymbols_fi', 'goog.i18n.DateTimeSymbols_fil', 'goog.i18n.DateTimeSymbols_fr', 'goog.i18n.DateTimeSymbols_fr_CA', 'goog.i18n.DateTimeSymbols_ga', 'goog.i18n.DateTimeSymbols_gl', 'goog.i18n.DateTimeSymbols_gsw', 'goog.i18n.DateTimeSymbols_gu', 'goog.i18n.DateTimeSymbols_haw', 'goog.i18n.DateTimeSymbols_he', 'goog.i18n.DateTimeSymbols_hi', 'goog.i18n.DateTimeSymbols_hr', 'goog.i18n.DateTimeSymbols_hu', 'goog.i18n.DateTimeSymbols_hy', 'goog.i18n.DateTimeSymbols_id', 'goog.i18n.DateTimeSymbols_in', 'goog.i18n.DateTimeSymbols_is', 'goog.i18n.DateTimeSymbols_it', 'goog.i18n.DateTimeSymbols_iw', 'goog.i18n.DateTimeSymbols_ja', 'goog.i18n.DateTimeSymbols_ka', 'goog.i18n.DateTimeSymbols_kk', 'goog.i18n.DateTimeSymbols_km', 'goog.i18n.DateTimeSymbols_kn', 'goog.i18n.DateTimeSymbols_ko', 'goog.i18n.DateTimeSymbols_ky', 'goog.i18n.DateTimeSymbols_ln', 'goog.i18n.DateTimeSymbols_lo', 'goog.i18n.DateTimeSymbols_lt', 'goog.i18n.DateTimeSymbols_lv', 'goog.i18n.DateTimeSymbols_mk', 'goog.i18n.DateTimeSymbols_ml', 'goog.i18n.DateTimeSymbols_mn', 'goog.i18n.DateTimeSymbols_mr', 'goog.i18n.DateTimeSymbols_ms', 'goog.i18n.DateTimeSymbols_mt', 'goog.i18n.DateTimeSymbols_my', 'goog.i18n.DateTimeSymbols_nb', 'goog.i18n.DateTimeSymbols_ne', 'goog.i18n.DateTimeSymbols_nl', 'goog.i18n.DateTimeSymbols_no', 'goog.i18n.DateTimeSymbols_no_NO', 'goog.i18n.DateTimeSymbols_or', 'goog.i18n.DateTimeSymbols_pa', 'goog.i18n.DateTimeSymbols_pl', 'goog.i18n.DateTimeSymbols_pt', 'goog.i18n.DateTimeSymbols_pt_BR', 'goog.i18n.DateTimeSymbols_pt_PT', 'goog.i18n.DateTimeSymbols_ro', 'goog.i18n.DateTimeSymbols_ru', 'goog.i18n.DateTimeSymbols_si', 'goog.i18n.DateTimeSymbols_sk', 'goog.i18n.DateTimeSymbols_sl', 'goog.i18n.DateTimeSymbols_sq', 'goog.i18n.DateTimeSymbols_sr', 'goog.i18n.DateTimeSymbols_sr_Latn', 'goog.i18n.DateTimeSymbols_sv', 'goog.i18n.DateTimeSymbols_sw', 'goog.i18n.DateTimeSymbols_ta', 'goog.i18n.DateTimeSymbols_te', 'goog.i18n.DateTimeSymbols_th', 'goog.i18n.DateTimeSymbols_tl', 'goog.i18n.DateTimeSymbols_tr', 'goog.i18n.DateTimeSymbols_uk', 'goog.i18n.DateTimeSymbols_ur', 'goog.i18n.DateTimeSymbols_uz', 'goog.i18n.DateTimeSymbols_vi', 'goog.i18n.DateTimeSymbols_zh', 'goog.i18n.DateTimeSymbols_zh_CN', 'goog.i18n.DateTimeSymbols_zh_HK', 'goog.i18n.DateTimeSymbols_zh_TW', 'goog.i18n.DateTimeSymbols_zu'], []);\ngoog.addDependency(\"i18n/datetimesymbolsext.js\", ['goog.i18n.DateTimeSymbolsExt', 'goog.i18n.DateTimeSymbols_af_NA', 'goog.i18n.DateTimeSymbols_af_ZA', 'goog.i18n.DateTimeSymbols_agq', 'goog.i18n.DateTimeSymbols_agq_CM', 'goog.i18n.DateTimeSymbols_ak', 'goog.i18n.DateTimeSymbols_ak_GH', 'goog.i18n.DateTimeSymbols_am_ET', 'goog.i18n.DateTimeSymbols_ar_001', 'goog.i18n.DateTimeSymbols_ar_AE', 'goog.i18n.DateTimeSymbols_ar_BH', 'goog.i18n.DateTimeSymbols_ar_DJ', 'goog.i18n.DateTimeSymbols_ar_DZ', 'goog.i18n.DateTimeSymbols_ar_EG', 'goog.i18n.DateTimeSymbols_ar_EH', 'goog.i18n.DateTimeSymbols_ar_ER', 'goog.i18n.DateTimeSymbols_ar_IL', 'goog.i18n.DateTimeSymbols_ar_IQ', 'goog.i18n.DateTimeSymbols_ar_JO', 'goog.i18n.DateTimeSymbols_ar_KM', 'goog.i18n.DateTimeSymbols_ar_KW', 'goog.i18n.DateTimeSymbols_ar_LB', 'goog.i18n.DateTimeSymbols_ar_LY', 'goog.i18n.DateTimeSymbols_ar_MA', 'goog.i18n.DateTimeSymbols_ar_MR', 'goog.i18n.DateTimeSymbols_ar_OM', 'goog.i18n.DateTimeSymbols_ar_PS', 'goog.i18n.DateTimeSymbols_ar_QA', 'goog.i18n.DateTimeSymbols_ar_SA', 'goog.i18n.DateTimeSymbols_ar_SD', 'goog.i18n.DateTimeSymbols_ar_SO', 'goog.i18n.DateTimeSymbols_ar_SS', 'goog.i18n.DateTimeSymbols_ar_SY', 'goog.i18n.DateTimeSymbols_ar_TD', 'goog.i18n.DateTimeSymbols_ar_TN', 'goog.i18n.DateTimeSymbols_ar_XB', 'goog.i18n.DateTimeSymbols_ar_YE', 'goog.i18n.DateTimeSymbols_as', 'goog.i18n.DateTimeSymbols_as_IN', 'goog.i18n.DateTimeSymbols_asa', 'goog.i18n.DateTimeSymbols_asa_TZ', 'goog.i18n.DateTimeSymbols_ast', 'goog.i18n.DateTimeSymbols_ast_ES', 'goog.i18n.DateTimeSymbols_az_Cyrl', 'goog.i18n.DateTimeSymbols_az_Cyrl_AZ', 'goog.i18n.DateTimeSymbols_az_Latn', 'goog.i18n.DateTimeSymbols_az_Latn_AZ', 'goog.i18n.DateTimeSymbols_bas', 'goog.i18n.DateTimeSymbols_bas_CM', 'goog.i18n.DateTimeSymbols_be_BY', 'goog.i18n.DateTimeSymbols_bem', 'goog.i18n.DateTimeSymbols_bem_ZM', 'goog.i18n.DateTimeSymbols_bez', 'goog.i18n.DateTimeSymbols_bez_TZ', 'goog.i18n.DateTimeSymbols_bg_BG', 'goog.i18n.DateTimeSymbols_bm', 'goog.i18n.DateTimeSymbols_bm_ML', 'goog.i18n.DateTimeSymbols_bn_BD', 'goog.i18n.DateTimeSymbols_bn_IN', 'goog.i18n.DateTimeSymbols_bo', 'goog.i18n.DateTimeSymbols_bo_CN', 'goog.i18n.DateTimeSymbols_bo_IN', 'goog.i18n.DateTimeSymbols_br_FR', 'goog.i18n.DateTimeSymbols_brx', 'goog.i18n.DateTimeSymbols_brx_IN', 'goog.i18n.DateTimeSymbols_bs_Cyrl', 'goog.i18n.DateTimeSymbols_bs_Cyrl_BA', 'goog.i18n.DateTimeSymbols_bs_Latn', 'goog.i18n.DateTimeSymbols_bs_Latn_BA', 'goog.i18n.DateTimeSymbols_ca_AD', 'goog.i18n.DateTimeSymbols_ca_ES', 'goog.i18n.DateTimeSymbols_ca_ES_VALENCIA', 'goog.i18n.DateTimeSymbols_ca_FR', 'goog.i18n.DateTimeSymbols_ca_IT', 'goog.i18n.DateTimeSymbols_ce', 'goog.i18n.DateTimeSymbols_ce_RU', 'goog.i18n.DateTimeSymbols_cgg', 'goog.i18n.DateTimeSymbols_cgg_UG', 'goog.i18n.DateTimeSymbols_chr_US', 'goog.i18n.DateTimeSymbols_ckb', 'goog.i18n.DateTimeSymbols_ckb_Arab', 'goog.i18n.DateTimeSymbols_ckb_Arab_IQ', 'goog.i18n.DateTimeSymbols_ckb_Arab_IR', 'goog.i18n.DateTimeSymbols_ckb_IQ', 'goog.i18n.DateTimeSymbols_ckb_IR', 'goog.i18n.DateTimeSymbols_ckb_Latn', 'goog.i18n.DateTimeSymbols_ckb_Latn_IQ', 'goog.i18n.DateTimeSymbols_cs_CZ', 'goog.i18n.DateTimeSymbols_cu', 'goog.i18n.DateTimeSymbols_cu_RU', 'goog.i18n.DateTimeSymbols_cy_GB', 'goog.i18n.DateTimeSymbols_da_DK', 'goog.i18n.DateTimeSymbols_da_GL', 'goog.i18n.DateTimeSymbols_dav', 'goog.i18n.DateTimeSymbols_dav_KE', 'goog.i18n.DateTimeSymbols_de_BE', 'goog.i18n.DateTimeSymbols_de_DE', 'goog.i18n.DateTimeSymbols_de_LI', 'goog.i18n.DateTimeSymbols_de_LU', 'goog.i18n.DateTimeSymbols_dje', 'goog.i18n.DateTimeSymbols_dje_NE', 'goog.i18n.DateTimeSymbols_dsb', 'goog.i18n.DateTimeSymbols_dsb_DE', 'goog.i18n.DateTimeSymbols_dua', 'goog.i18n.DateTimeSymbols_dua_CM', 'goog.i18n.DateTimeSymbols_dyo', 'goog.i18n.DateTimeSymbols_dyo_SN', 'goog.i18n.DateTimeSymbols_dz', 'goog.i18n.DateTimeSymbols_dz_BT', 'goog.i18n.DateTimeSymbols_ebu', 'goog.i18n.DateTimeSymbols_ebu_KE', 'goog.i18n.DateTimeSymbols_ee', 'goog.i18n.DateTimeSymbols_ee_GH', 'goog.i18n.DateTimeSymbols_ee_TG', 'goog.i18n.DateTimeSymbols_el_CY', 'goog.i18n.DateTimeSymbols_el_GR', 'goog.i18n.DateTimeSymbols_en_001', 'goog.i18n.DateTimeSymbols_en_150', 'goog.i18n.DateTimeSymbols_en_AG', 'goog.i18n.DateTimeSymbols_en_AI', 'goog.i18n.DateTimeSymbols_en_AS', 'goog.i18n.DateTimeSymbols_en_AT', 'goog.i18n.DateTimeSymbols_en_BB', 'goog.i18n.DateTimeSymbols_en_BE', 'goog.i18n.DateTimeSymbols_en_BI', 'goog.i18n.DateTimeSymbols_en_BM', 'goog.i18n.DateTimeSymbols_en_BS', 'goog.i18n.DateTimeSymbols_en_BW', 'goog.i18n.DateTimeSymbols_en_BZ', 'goog.i18n.DateTimeSymbols_en_CC', 'goog.i18n.DateTimeSymbols_en_CH', 'goog.i18n.DateTimeSymbols_en_CK', 'goog.i18n.DateTimeSymbols_en_CM', 'goog.i18n.DateTimeSymbols_en_CX', 'goog.i18n.DateTimeSymbols_en_CY', 'goog.i18n.DateTimeSymbols_en_DE', 'goog.i18n.DateTimeSymbols_en_DG', 'goog.i18n.DateTimeSymbols_en_DK', 'goog.i18n.DateTimeSymbols_en_DM', 'goog.i18n.DateTimeSymbols_en_ER', 'goog.i18n.DateTimeSymbols_en_FI', 'goog.i18n.DateTimeSymbols_en_FJ', 'goog.i18n.DateTimeSymbols_en_FK', 'goog.i18n.DateTimeSymbols_en_FM', 'goog.i18n.DateTimeSymbols_en_GD', 'goog.i18n.DateTimeSymbols_en_GG', 'goog.i18n.DateTimeSymbols_en_GH', 'goog.i18n.DateTimeSymbols_en_GI', 'goog.i18n.DateTimeSymbols_en_GM', 'goog.i18n.DateTimeSymbols_en_GU', 'goog.i18n.DateTimeSymbols_en_GY', 'goog.i18n.DateTimeSymbols_en_HK', 'goog.i18n.DateTimeSymbols_en_IL', 'goog.i18n.DateTimeSymbols_en_IM', 'goog.i18n.DateTimeSymbols_en_IO', 'goog.i18n.DateTimeSymbols_en_JE', 'goog.i18n.DateTimeSymbols_en_JM', 'goog.i18n.DateTimeSymbols_en_KE', 'goog.i18n.DateTimeSymbols_en_KI', 'goog.i18n.DateTimeSymbols_en_KN', 'goog.i18n.DateTimeSymbols_en_KY', 'goog.i18n.DateTimeSymbols_en_LC', 'goog.i18n.DateTimeSymbols_en_LR', 'goog.i18n.DateTimeSymbols_en_LS', 'goog.i18n.DateTimeSymbols_en_MG', 'goog.i18n.DateTimeSymbols_en_MH', 'goog.i18n.DateTimeSymbols_en_MO', 'goog.i18n.DateTimeSymbols_en_MP', 'goog.i18n.DateTimeSymbols_en_MS', 'goog.i18n.DateTimeSymbols_en_MT', 'goog.i18n.DateTimeSymbols_en_MU', 'goog.i18n.DateTimeSymbols_en_MW', 'goog.i18n.DateTimeSymbols_en_MY', 'goog.i18n.DateTimeSymbols_en_NA', 'goog.i18n.DateTimeSymbols_en_NF', 'goog.i18n.DateTimeSymbols_en_NG', 'goog.i18n.DateTimeSymbols_en_NL', 'goog.i18n.DateTimeSymbols_en_NR', 'goog.i18n.DateTimeSymbols_en_NU', 'goog.i18n.DateTimeSymbols_en_NZ', 'goog.i18n.DateTimeSymbols_en_PG', 'goog.i18n.DateTimeSymbols_en_PH', 'goog.i18n.DateTimeSymbols_en_PK', 'goog.i18n.DateTimeSymbols_en_PN', 'goog.i18n.DateTimeSymbols_en_PR', 'goog.i18n.DateTimeSymbols_en_PW', 'goog.i18n.DateTimeSymbols_en_RW', 'goog.i18n.DateTimeSymbols_en_SB', 'goog.i18n.DateTimeSymbols_en_SC', 'goog.i18n.DateTimeSymbols_en_SD', 'goog.i18n.DateTimeSymbols_en_SE', 'goog.i18n.DateTimeSymbols_en_SH', 'goog.i18n.DateTimeSymbols_en_SI', 'goog.i18n.DateTimeSymbols_en_SL', 'goog.i18n.DateTimeSymbols_en_SS', 'goog.i18n.DateTimeSymbols_en_SX', 'goog.i18n.DateTimeSymbols_en_SZ', 'goog.i18n.DateTimeSymbols_en_TC', 'goog.i18n.DateTimeSymbols_en_TK', 'goog.i18n.DateTimeSymbols_en_TO', 'goog.i18n.DateTimeSymbols_en_TT', 'goog.i18n.DateTimeSymbols_en_TV', 'goog.i18n.DateTimeSymbols_en_TZ', 'goog.i18n.DateTimeSymbols_en_UG', 'goog.i18n.DateTimeSymbols_en_UM', 'goog.i18n.DateTimeSymbols_en_VC', 'goog.i18n.DateTimeSymbols_en_VG', 'goog.i18n.DateTimeSymbols_en_VI', 'goog.i18n.DateTimeSymbols_en_VU', 'goog.i18n.DateTimeSymbols_en_WS', 'goog.i18n.DateTimeSymbols_en_XA', 'goog.i18n.DateTimeSymbols_en_ZM', 'goog.i18n.DateTimeSymbols_en_ZW', 'goog.i18n.DateTimeSymbols_eo', 'goog.i18n.DateTimeSymbols_eo_001', 'goog.i18n.DateTimeSymbols_es_AR', 'goog.i18n.DateTimeSymbols_es_BO', 'goog.i18n.DateTimeSymbols_es_CL', 'goog.i18n.DateTimeSymbols_es_CO', 'goog.i18n.DateTimeSymbols_es_CR', 'goog.i18n.DateTimeSymbols_es_CU', 'goog.i18n.DateTimeSymbols_es_DO', 'goog.i18n.DateTimeSymbols_es_EA', 'goog.i18n.DateTimeSymbols_es_EC', 'goog.i18n.DateTimeSymbols_es_GQ', 'goog.i18n.DateTimeSymbols_es_GT', 'goog.i18n.DateTimeSymbols_es_HN', 'goog.i18n.DateTimeSymbols_es_IC', 'goog.i18n.DateTimeSymbols_es_NI', 'goog.i18n.DateTimeSymbols_es_PA', 'goog.i18n.DateTimeSymbols_es_PE', 'goog.i18n.DateTimeSymbols_es_PH', 'goog.i18n.DateTimeSymbols_es_PR', 'goog.i18n.DateTimeSymbols_es_PY', 'goog.i18n.DateTimeSymbols_es_SV', 'goog.i18n.DateTimeSymbols_es_UY', 'goog.i18n.DateTimeSymbols_es_VE', 'goog.i18n.DateTimeSymbols_et_EE', 'goog.i18n.DateTimeSymbols_eu_ES', 'goog.i18n.DateTimeSymbols_ewo', 'goog.i18n.DateTimeSymbols_ewo_CM', 'goog.i18n.DateTimeSymbols_fa_AF', 'goog.i18n.DateTimeSymbols_fa_IR', 'goog.i18n.DateTimeSymbols_ff', 'goog.i18n.DateTimeSymbols_ff_CM', 'goog.i18n.DateTimeSymbols_ff_GN', 'goog.i18n.DateTimeSymbols_ff_MR', 'goog.i18n.DateTimeSymbols_ff_SN', 'goog.i18n.DateTimeSymbols_fi_FI', 'goog.i18n.DateTimeSymbols_fil_PH', 'goog.i18n.DateTimeSymbols_fo', 'goog.i18n.DateTimeSymbols_fo_DK', 'goog.i18n.DateTimeSymbols_fo_FO', 'goog.i18n.DateTimeSymbols_fr_BE', 'goog.i18n.DateTimeSymbols_fr_BF', 'goog.i18n.DateTimeSymbols_fr_BI', 'goog.i18n.DateTimeSymbols_fr_BJ', 'goog.i18n.DateTimeSymbols_fr_BL', 'goog.i18n.DateTimeSymbols_fr_CD', 'goog.i18n.DateTimeSymbols_fr_CF', 'goog.i18n.DateTimeSymbols_fr_CG', 'goog.i18n.DateTimeSymbols_fr_CH', 'goog.i18n.DateTimeSymbols_fr_CI', 'goog.i18n.DateTimeSymbols_fr_CM', 'goog.i18n.DateTimeSymbols_fr_DJ', 'goog.i18n.DateTimeSymbols_fr_DZ', 'goog.i18n.DateTimeSymbols_fr_FR', 'goog.i18n.DateTimeSymbols_fr_GA', 'goog.i18n.DateTimeSymbols_fr_GF', 'goog.i18n.DateTimeSymbols_fr_GN', 'goog.i18n.DateTimeSymbols_fr_GP', 'goog.i18n.DateTimeSymbols_fr_GQ', 'goog.i18n.DateTimeSymbols_fr_HT', 'goog.i18n.DateTimeSymbols_fr_KM', 'goog.i18n.DateTimeSymbols_fr_LU', 'goog.i18n.DateTimeSymbols_fr_MA', 'goog.i18n.DateTimeSymbols_fr_MC', 'goog.i18n.DateTimeSymbols_fr_MF', 'goog.i18n.DateTimeSymbols_fr_MG', 'goog.i18n.DateTimeSymbols_fr_ML', 'goog.i18n.DateTimeSymbols_fr_MQ', 'goog.i18n.DateTimeSymbols_fr_MR', 'goog.i18n.DateTimeSymbols_fr_MU', 'goog.i18n.DateTimeSymbols_fr_NC', 'goog.i18n.DateTimeSymbols_fr_NE', 'goog.i18n.DateTimeSymbols_fr_PF', 'goog.i18n.DateTimeSymbols_fr_PM', 'goog.i18n.DateTimeSymbols_fr_RE', 'goog.i18n.DateTimeSymbols_fr_RW', 'goog.i18n.DateTimeSymbols_fr_SC', 'goog.i18n.DateTimeSymbols_fr_SN', 'goog.i18n.DateTimeSymbols_fr_SY', 'goog.i18n.DateTimeSymbols_fr_TD', 'goog.i18n.DateTimeSymbols_fr_TG', 'goog.i18n.DateTimeSymbols_fr_TN', 'goog.i18n.DateTimeSymbols_fr_VU', 'goog.i18n.DateTimeSymbols_fr_WF', 'goog.i18n.DateTimeSymbols_fr_YT', 'goog.i18n.DateTimeSymbols_fur', 'goog.i18n.DateTimeSymbols_fur_IT', 'goog.i18n.DateTimeSymbols_fy', 'goog.i18n.DateTimeSymbols_fy_NL', 'goog.i18n.DateTimeSymbols_ga_IE', 'goog.i18n.DateTimeSymbols_gd', 'goog.i18n.DateTimeSymbols_gd_GB', 'goog.i18n.DateTimeSymbols_gl_ES', 'goog.i18n.DateTimeSymbols_gsw_CH', 'goog.i18n.DateTimeSymbols_gsw_FR', 'goog.i18n.DateTimeSymbols_gsw_LI', 'goog.i18n.DateTimeSymbols_gu_IN', 'goog.i18n.DateTimeSymbols_guz', 'goog.i18n.DateTimeSymbols_guz_KE', 'goog.i18n.DateTimeSymbols_gv', 'goog.i18n.DateTimeSymbols_gv_IM', 'goog.i18n.DateTimeSymbols_ha', 'goog.i18n.DateTimeSymbols_ha_GH', 'goog.i18n.DateTimeSymbols_ha_NE', 'goog.i18n.DateTimeSymbols_ha_NG', 'goog.i18n.DateTimeSymbols_haw_US', 'goog.i18n.DateTimeSymbols_he_IL', 'goog.i18n.DateTimeSymbols_hi_IN', 'goog.i18n.DateTimeSymbols_hr_BA', 'goog.i18n.DateTimeSymbols_hr_HR', 'goog.i18n.DateTimeSymbols_hsb', 'goog.i18n.DateTimeSymbols_hsb_DE', 'goog.i18n.DateTimeSymbols_hu_HU', 'goog.i18n.DateTimeSymbols_hy_AM', 'goog.i18n.DateTimeSymbols_id_ID', 'goog.i18n.DateTimeSymbols_ig', 'goog.i18n.DateTimeSymbols_ig_NG', 'goog.i18n.DateTimeSymbols_ii', 'goog.i18n.DateTimeSymbols_ii_CN', 'goog.i18n.DateTimeSymbols_is_IS', 'goog.i18n.DateTimeSymbols_it_CH', 'goog.i18n.DateTimeSymbols_it_IT', 'goog.i18n.DateTimeSymbols_it_SM', 'goog.i18n.DateTimeSymbols_ja_JP', 'goog.i18n.DateTimeSymbols_jgo', 'goog.i18n.DateTimeSymbols_jgo_CM', 'goog.i18n.DateTimeSymbols_jmc', 'goog.i18n.DateTimeSymbols_jmc_TZ', 'goog.i18n.DateTimeSymbols_ka_GE', 'goog.i18n.DateTimeSymbols_kab', 'goog.i18n.DateTimeSymbols_kab_DZ', 'goog.i18n.DateTimeSymbols_kam', 'goog.i18n.DateTimeSymbols_kam_KE', 'goog.i18n.DateTimeSymbols_kde', 'goog.i18n.DateTimeSymbols_kde_TZ', 'goog.i18n.DateTimeSymbols_kea', 'goog.i18n.DateTimeSymbols_kea_CV', 'goog.i18n.DateTimeSymbols_khq', 'goog.i18n.DateTimeSymbols_khq_ML', 'goog.i18n.DateTimeSymbols_ki', 'goog.i18n.DateTimeSymbols_ki_KE', 'goog.i18n.DateTimeSymbols_kk_KZ', 'goog.i18n.DateTimeSymbols_kkj', 'goog.i18n.DateTimeSymbols_kkj_CM', 'goog.i18n.DateTimeSymbols_kl', 'goog.i18n.DateTimeSymbols_kl_GL', 'goog.i18n.DateTimeSymbols_kln', 'goog.i18n.DateTimeSymbols_kln_KE', 'goog.i18n.DateTimeSymbols_km_KH', 'goog.i18n.DateTimeSymbols_kn_IN', 'goog.i18n.DateTimeSymbols_ko_KP', 'goog.i18n.DateTimeSymbols_ko_KR', 'goog.i18n.DateTimeSymbols_kok', 'goog.i18n.DateTimeSymbols_kok_IN', 'goog.i18n.DateTimeSymbols_ks', 'goog.i18n.DateTimeSymbols_ks_IN', 'goog.i18n.DateTimeSymbols_ksb', 'goog.i18n.DateTimeSymbols_ksb_TZ', 'goog.i18n.DateTimeSymbols_ksf', 'goog.i18n.DateTimeSymbols_ksf_CM', 'goog.i18n.DateTimeSymbols_ksh', 'goog.i18n.DateTimeSymbols_ksh_DE', 'goog.i18n.DateTimeSymbols_kw', 'goog.i18n.DateTimeSymbols_kw_GB', 'goog.i18n.DateTimeSymbols_ky_KG', 'goog.i18n.DateTimeSymbols_lag', 'goog.i18n.DateTimeSymbols_lag_TZ', 'goog.i18n.DateTimeSymbols_lb', 'goog.i18n.DateTimeSymbols_lb_LU', 'goog.i18n.DateTimeSymbols_lg', 'goog.i18n.DateTimeSymbols_lg_UG', 'goog.i18n.DateTimeSymbols_lkt', 'goog.i18n.DateTimeSymbols_lkt_US', 'goog.i18n.DateTimeSymbols_ln_AO', 'goog.i18n.DateTimeSymbols_ln_CD', 'goog.i18n.DateTimeSymbols_ln_CF', 'goog.i18n.DateTimeSymbols_ln_CG', 'goog.i18n.DateTimeSymbols_lo_LA', 'goog.i18n.DateTimeSymbols_lrc', 'goog.i18n.DateTimeSymbols_lrc_IQ', 'goog.i18n.DateTimeSymbols_lrc_IR', 'goog.i18n.DateTimeSymbols_lt_LT', 'goog.i18n.DateTimeSymbols_lu', 'goog.i18n.DateTimeSymbols_lu_CD', 'goog.i18n.DateTimeSymbols_luo', 'goog.i18n.DateTimeSymbols_luo_KE', 'goog.i18n.DateTimeSymbols_luy', 'goog.i18n.DateTimeSymbols_luy_KE', 'goog.i18n.DateTimeSymbols_lv_LV', 'goog.i18n.DateTimeSymbols_mas', 'goog.i18n.DateTimeSymbols_mas_KE', 'goog.i18n.DateTimeSymbols_mas_TZ', 'goog.i18n.DateTimeSymbols_mer', 'goog.i18n.DateTimeSymbols_mer_KE', 'goog.i18n.DateTimeSymbols_mfe', 'goog.i18n.DateTimeSymbols_mfe_MU', 'goog.i18n.DateTimeSymbols_mg', 'goog.i18n.DateTimeSymbols_mg_MG', 'goog.i18n.DateTimeSymbols_mgh', 'goog.i18n.DateTimeSymbols_mgh_MZ', 'goog.i18n.DateTimeSymbols_mgo', 'goog.i18n.DateTimeSymbols_mgo_CM', 'goog.i18n.DateTimeSymbols_mk_MK', 'goog.i18n.DateTimeSymbols_ml_IN', 'goog.i18n.DateTimeSymbols_mn_MN', 'goog.i18n.DateTimeSymbols_mr_IN', 'goog.i18n.DateTimeSymbols_ms_BN', 'goog.i18n.DateTimeSymbols_ms_MY', 'goog.i18n.DateTimeSymbols_ms_SG', 'goog.i18n.DateTimeSymbols_mt_MT', 'goog.i18n.DateTimeSymbols_mua', 'goog.i18n.DateTimeSymbols_mua_CM', 'goog.i18n.DateTimeSymbols_my_MM', 'goog.i18n.DateTimeSymbols_mzn', 'goog.i18n.DateTimeSymbols_mzn_IR', 'goog.i18n.DateTimeSymbols_naq', 'goog.i18n.DateTimeSymbols_naq_NA', 'goog.i18n.DateTimeSymbols_nb_NO', 'goog.i18n.DateTimeSymbols_nb_SJ', 'goog.i18n.DateTimeSymbols_nd', 'goog.i18n.DateTimeSymbols_nd_ZW', 'goog.i18n.DateTimeSymbols_ne_IN', 'goog.i18n.DateTimeSymbols_ne_NP', 'goog.i18n.DateTimeSymbols_nl_AW', 'goog.i18n.DateTimeSymbols_nl_BE', 'goog.i18n.DateTimeSymbols_nl_BQ', 'goog.i18n.DateTimeSymbols_nl_CW', 'goog.i18n.DateTimeSymbols_nl_NL', 'goog.i18n.DateTimeSymbols_nl_SR', 'goog.i18n.DateTimeSymbols_nl_SX', 'goog.i18n.DateTimeSymbols_nmg', 'goog.i18n.DateTimeSymbols_nmg_CM', 'goog.i18n.DateTimeSymbols_nn', 'goog.i18n.DateTimeSymbols_nn_NO', 'goog.i18n.DateTimeSymbols_nnh', 'goog.i18n.DateTimeSymbols_nnh_CM', 'goog.i18n.DateTimeSymbols_nus', 'goog.i18n.DateTimeSymbols_nus_SS', 'goog.i18n.DateTimeSymbols_nyn', 'goog.i18n.DateTimeSymbols_nyn_UG', 'goog.i18n.DateTimeSymbols_om', 'goog.i18n.DateTimeSymbols_om_ET', 'goog.i18n.DateTimeSymbols_om_KE', 'goog.i18n.DateTimeSymbols_or_IN', 'goog.i18n.DateTimeSymbols_os', 'goog.i18n.DateTimeSymbols_os_GE', 'goog.i18n.DateTimeSymbols_os_RU', 'goog.i18n.DateTimeSymbols_pa_Arab', 'goog.i18n.DateTimeSymbols_pa_Arab_PK', 'goog.i18n.DateTimeSymbols_pa_Guru', 'goog.i18n.DateTimeSymbols_pa_Guru_IN', 'goog.i18n.DateTimeSymbols_pl_PL', 'goog.i18n.DateTimeSymbols_prg', 'goog.i18n.DateTimeSymbols_prg_001', 'goog.i18n.DateTimeSymbols_ps', 'goog.i18n.DateTimeSymbols_ps_AF', 'goog.i18n.DateTimeSymbols_pt_AO', 'goog.i18n.DateTimeSymbols_pt_CV', 'goog.i18n.DateTimeSymbols_pt_GW', 'goog.i18n.DateTimeSymbols_pt_MO', 'goog.i18n.DateTimeSymbols_pt_MZ', 'goog.i18n.DateTimeSymbols_pt_ST', 'goog.i18n.DateTimeSymbols_pt_TL', 'goog.i18n.DateTimeSymbols_qu', 'goog.i18n.DateTimeSymbols_qu_BO', 'goog.i18n.DateTimeSymbols_qu_EC', 'goog.i18n.DateTimeSymbols_qu_PE', 'goog.i18n.DateTimeSymbols_rm', 'goog.i18n.DateTimeSymbols_rm_CH', 'goog.i18n.DateTimeSymbols_rn', 'goog.i18n.DateTimeSymbols_rn_BI', 'goog.i18n.DateTimeSymbols_ro_MD', 'goog.i18n.DateTimeSymbols_ro_RO', 'goog.i18n.DateTimeSymbols_rof', 'goog.i18n.DateTimeSymbols_rof_TZ', 'goog.i18n.DateTimeSymbols_ru_BY', 'goog.i18n.DateTimeSymbols_ru_KG', 'goog.i18n.DateTimeSymbols_ru_KZ', 'goog.i18n.DateTimeSymbols_ru_MD', 'goog.i18n.DateTimeSymbols_ru_RU', 'goog.i18n.DateTimeSymbols_ru_UA', 'goog.i18n.DateTimeSymbols_rw', 'goog.i18n.DateTimeSymbols_rw_RW', 'goog.i18n.DateTimeSymbols_rwk', 'goog.i18n.DateTimeSymbols_rwk_TZ', 'goog.i18n.DateTimeSymbols_sah', 'goog.i18n.DateTimeSymbols_sah_RU', 'goog.i18n.DateTimeSymbols_saq', 'goog.i18n.DateTimeSymbols_saq_KE', 'goog.i18n.DateTimeSymbols_sbp', 'goog.i18n.DateTimeSymbols_sbp_TZ', 'goog.i18n.DateTimeSymbols_se', 'goog.i18n.DateTimeSymbols_se_FI', 'goog.i18n.DateTimeSymbols_se_NO', 'goog.i18n.DateTimeSymbols_se_SE', 'goog.i18n.DateTimeSymbols_seh', 'goog.i18n.DateTimeSymbols_seh_MZ', 'goog.i18n.DateTimeSymbols_ses', 'goog.i18n.DateTimeSymbols_ses_ML', 'goog.i18n.DateTimeSymbols_sg', 'goog.i18n.DateTimeSymbols_sg_CF', 'goog.i18n.DateTimeSymbols_shi', 'goog.i18n.DateTimeSymbols_shi_Latn', 'goog.i18n.DateTimeSymbols_shi_Latn_MA', 'goog.i18n.DateTimeSymbols_shi_Tfng', 'goog.i18n.DateTimeSymbols_shi_Tfng_MA', 'goog.i18n.DateTimeSymbols_si_LK', 'goog.i18n.DateTimeSymbols_sk_SK', 'goog.i18n.DateTimeSymbols_sl_SI', 'goog.i18n.DateTimeSymbols_smn', 'goog.i18n.DateTimeSymbols_smn_FI', 'goog.i18n.DateTimeSymbols_sn', 'goog.i18n.DateTimeSymbols_sn_ZW', 'goog.i18n.DateTimeSymbols_so', 'goog.i18n.DateTimeSymbols_so_DJ', 'goog.i18n.DateTimeSymbols_so_ET', 'goog.i18n.DateTimeSymbols_so_KE', 'goog.i18n.DateTimeSymbols_so_SO', 'goog.i18n.DateTimeSymbols_sq_AL', 'goog.i18n.DateTimeSymbols_sq_MK', 'goog.i18n.DateTimeSymbols_sq_XK', 'goog.i18n.DateTimeSymbols_sr_Cyrl', 'goog.i18n.DateTimeSymbols_sr_Cyrl_BA', 'goog.i18n.DateTimeSymbols_sr_Cyrl_ME', 'goog.i18n.DateTimeSymbols_sr_Cyrl_RS', 'goog.i18n.DateTimeSymbols_sr_Cyrl_XK', 'goog.i18n.DateTimeSymbols_sr_Latn_BA', 'goog.i18n.DateTimeSymbols_sr_Latn_ME', 'goog.i18n.DateTimeSymbols_sr_Latn_RS', 'goog.i18n.DateTimeSymbols_sr_Latn_XK', 'goog.i18n.DateTimeSymbols_sv_AX', 'goog.i18n.DateTimeSymbols_sv_FI', 'goog.i18n.DateTimeSymbols_sv_SE', 'goog.i18n.DateTimeSymbols_sw_CD', 'goog.i18n.DateTimeSymbols_sw_KE', 'goog.i18n.DateTimeSymbols_sw_TZ', 'goog.i18n.DateTimeSymbols_sw_UG', 'goog.i18n.DateTimeSymbols_ta_IN', 'goog.i18n.DateTimeSymbols_ta_LK', 'goog.i18n.DateTimeSymbols_ta_MY', 'goog.i18n.DateTimeSymbols_ta_SG', 'goog.i18n.DateTimeSymbols_te_IN', 'goog.i18n.DateTimeSymbols_teo', 'goog.i18n.DateTimeSymbols_teo_KE', 'goog.i18n.DateTimeSymbols_teo_UG', 'goog.i18n.DateTimeSymbols_th_TH', 'goog.i18n.DateTimeSymbols_ti', 'goog.i18n.DateTimeSymbols_ti_ER', 'goog.i18n.DateTimeSymbols_ti_ET', 'goog.i18n.DateTimeSymbols_tk', 'goog.i18n.DateTimeSymbols_tk_TM', 'goog.i18n.DateTimeSymbols_to', 'goog.i18n.DateTimeSymbols_to_TO', 'goog.i18n.DateTimeSymbols_tr_CY', 'goog.i18n.DateTimeSymbols_tr_TR', 'goog.i18n.DateTimeSymbols_twq', 'goog.i18n.DateTimeSymbols_twq_NE', 'goog.i18n.DateTimeSymbols_tzm', 'goog.i18n.DateTimeSymbols_tzm_MA', 'goog.i18n.DateTimeSymbols_ug', 'goog.i18n.DateTimeSymbols_ug_CN', 'goog.i18n.DateTimeSymbols_uk_UA', 'goog.i18n.DateTimeSymbols_ur_IN', 'goog.i18n.DateTimeSymbols_ur_PK', 'goog.i18n.DateTimeSymbols_uz_Arab', 'goog.i18n.DateTimeSymbols_uz_Arab_AF', 'goog.i18n.DateTimeSymbols_uz_Cyrl', 'goog.i18n.DateTimeSymbols_uz_Cyrl_UZ', 'goog.i18n.DateTimeSymbols_uz_Latn', 'goog.i18n.DateTimeSymbols_uz_Latn_UZ', 'goog.i18n.DateTimeSymbols_vai', 'goog.i18n.DateTimeSymbols_vai_Latn', 'goog.i18n.DateTimeSymbols_vai_Latn_LR', 'goog.i18n.DateTimeSymbols_vai_Vaii', 'goog.i18n.DateTimeSymbols_vai_Vaii_LR', 'goog.i18n.DateTimeSymbols_vi_VN', 'goog.i18n.DateTimeSymbols_vo', 'goog.i18n.DateTimeSymbols_vo_001', 'goog.i18n.DateTimeSymbols_vun', 'goog.i18n.DateTimeSymbols_vun_TZ', 'goog.i18n.DateTimeSymbols_wae', 'goog.i18n.DateTimeSymbols_wae_CH', 'goog.i18n.DateTimeSymbols_xog', 'goog.i18n.DateTimeSymbols_xog_UG', 'goog.i18n.DateTimeSymbols_yav', 'goog.i18n.DateTimeSymbols_yav_CM', 'goog.i18n.DateTimeSymbols_yi', 'goog.i18n.DateTimeSymbols_yi_001', 'goog.i18n.DateTimeSymbols_yo', 'goog.i18n.DateTimeSymbols_yo_BJ', 'goog.i18n.DateTimeSymbols_yo_NG', 'goog.i18n.DateTimeSymbols_zgh', 'goog.i18n.DateTimeSymbols_zgh_MA', 'goog.i18n.DateTimeSymbols_zh_Hans', 'goog.i18n.DateTimeSymbols_zh_Hans_CN', 'goog.i18n.DateTimeSymbols_zh_Hans_HK', 'goog.i18n.DateTimeSymbols_zh_Hans_MO', 'goog.i18n.DateTimeSymbols_zh_Hans_SG', 'goog.i18n.DateTimeSymbols_zh_Hant', 'goog.i18n.DateTimeSymbols_zh_Hant_HK', 'goog.i18n.DateTimeSymbols_zh_Hant_MO', 'goog.i18n.DateTimeSymbols_zh_Hant_TW', 'goog.i18n.DateTimeSymbols_zu_ZA'], ['goog.i18n.DateTimeSymbols']);\ngoog.addDependency(\"i18n/graphemebreak.js\", ['goog.i18n.GraphemeBreak'], ['goog.structs.InversionMap']);\ngoog.addDependency(\"i18n/graphemebreak_test.js\", ['goog.i18n.GraphemeBreakTest'], ['goog.i18n.GraphemeBreak', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/messageformat.js\", ['goog.i18n.MessageFormat'], ['goog.asserts', 'goog.i18n.NumberFormat', 'goog.i18n.ordinalRules', 'goog.i18n.pluralRules']);\ngoog.addDependency(\"i18n/messageformat_test.js\", ['goog.i18n.MessageFormatTest'], ['goog.i18n.MessageFormat', 'goog.i18n.NumberFormatSymbols_hr', 'goog.i18n.pluralRules', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/mime.js\", ['goog.i18n.mime', 'goog.i18n.mime.encode'], ['goog.array']);\ngoog.addDependency(\"i18n/mime_test.js\", ['goog.i18n.mime.encodeTest'], ['goog.i18n.mime.encode', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/numberformat.js\", ['goog.i18n.NumberFormat', 'goog.i18n.NumberFormat.CurrencyStyle', 'goog.i18n.NumberFormat.Format'], ['goog.asserts', 'goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.currency', 'goog.math']);\ngoog.addDependency(\"i18n/numberformat_test.js\", ['goog.i18n.NumberFormatTest'], ['goog.i18n.CompactNumberFormatSymbols', 'goog.i18n.CompactNumberFormatSymbols_de', 'goog.i18n.CompactNumberFormatSymbols_en', 'goog.i18n.CompactNumberFormatSymbols_fr', 'goog.i18n.NumberFormat', 'goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_de', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_fr', 'goog.i18n.NumberFormatSymbols_pl', 'goog.i18n.NumberFormatSymbols_ro', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"i18n/numberformatsymbols.js\", ['goog.i18n.NumberFormatSymbols', 'goog.i18n.NumberFormatSymbols_af', 'goog.i18n.NumberFormatSymbols_af_ZA', 'goog.i18n.NumberFormatSymbols_am', 'goog.i18n.NumberFormatSymbols_am_ET', 'goog.i18n.NumberFormatSymbols_ar', 'goog.i18n.NumberFormatSymbols_ar_001', 'goog.i18n.NumberFormatSymbols_ar_EG', 'goog.i18n.NumberFormatSymbols_ar_XB', 'goog.i18n.NumberFormatSymbols_az', 'goog.i18n.NumberFormatSymbols_az_Latn', 'goog.i18n.NumberFormatSymbols_az_Latn_AZ', 'goog.i18n.NumberFormatSymbols_be', 'goog.i18n.NumberFormatSymbols_be_BY', 'goog.i18n.NumberFormatSymbols_bg', 'goog.i18n.NumberFormatSymbols_bg_BG', 'goog.i18n.NumberFormatSymbols_bn', 'goog.i18n.NumberFormatSymbols_bn_BD', 'goog.i18n.NumberFormatSymbols_br', 'goog.i18n.NumberFormatSymbols_br_FR', 'goog.i18n.NumberFormatSymbols_bs', 'goog.i18n.NumberFormatSymbols_bs_Latn', 'goog.i18n.NumberFormatSymbols_bs_Latn_BA', 'goog.i18n.NumberFormatSymbols_ca', 'goog.i18n.NumberFormatSymbols_ca_AD', 'goog.i18n.NumberFormatSymbols_ca_ES', 'goog.i18n.NumberFormatSymbols_ca_ES_VALENCIA', 'goog.i18n.NumberFormatSymbols_ca_FR', 'goog.i18n.NumberFormatSymbols_ca_IT', 'goog.i18n.NumberFormatSymbols_chr', 'goog.i18n.NumberFormatSymbols_chr_US', 'goog.i18n.NumberFormatSymbols_cs', 'goog.i18n.NumberFormatSymbols_cs_CZ', 'goog.i18n.NumberFormatSymbols_cy', 'goog.i18n.NumberFormatSymbols_cy_GB', 'goog.i18n.NumberFormatSymbols_da', 'goog.i18n.NumberFormatSymbols_da_DK', 'goog.i18n.NumberFormatSymbols_da_GL', 'goog.i18n.NumberFormatSymbols_de', 'goog.i18n.NumberFormatSymbols_de_AT', 'goog.i18n.NumberFormatSymbols_de_BE', 'goog.i18n.NumberFormatSymbols_de_CH', 'goog.i18n.NumberFormatSymbols_de_DE', 'goog.i18n.NumberFormatSymbols_de_LU', 'goog.i18n.NumberFormatSymbols_el', 'goog.i18n.NumberFormatSymbols_el_CY', 'goog.i18n.NumberFormatSymbols_el_GR', 'goog.i18n.NumberFormatSymbols_en', 'goog.i18n.NumberFormatSymbols_en_001', 'goog.i18n.NumberFormatSymbols_en_AS', 'goog.i18n.NumberFormatSymbols_en_AU', 'goog.i18n.NumberFormatSymbols_en_CA', 'goog.i18n.NumberFormatSymbols_en_DG', 'goog.i18n.NumberFormatSymbols_en_FM', 'goog.i18n.NumberFormatSymbols_en_GB', 'goog.i18n.NumberFormatSymbols_en_GU', 'goog.i18n.NumberFormatSymbols_en_IE', 'goog.i18n.NumberFormatSymbols_en_IN', 'goog.i18n.NumberFormatSymbols_en_IO', 'goog.i18n.NumberFormatSymbols_en_MH', 'goog.i18n.NumberFormatSymbols_en_MP', 'goog.i18n.NumberFormatSymbols_en_PR', 'goog.i18n.NumberFormatSymbols_en_PW', 'goog.i18n.NumberFormatSymbols_en_SG', 'goog.i18n.NumberFormatSymbols_en_TC', 'goog.i18n.NumberFormatSymbols_en_UM', 'goog.i18n.NumberFormatSymbols_en_US', 'goog.i18n.NumberFormatSymbols_en_VG', 'goog.i18n.NumberFormatSymbols_en_VI', 'goog.i18n.NumberFormatSymbols_en_XA', 'goog.i18n.NumberFormatSymbols_en_ZA', 'goog.i18n.NumberFormatSymbols_en_ZW', 'goog.i18n.NumberFormatSymbols_es', 'goog.i18n.NumberFormatSymbols_es_419', 'goog.i18n.NumberFormatSymbols_es_EA', 'goog.i18n.NumberFormatSymbols_es_ES', 'goog.i18n.NumberFormatSymbols_es_IC', 'goog.i18n.NumberFormatSymbols_es_MX', 'goog.i18n.NumberFormatSymbols_es_US', 'goog.i18n.NumberFormatSymbols_et', 'goog.i18n.NumberFormatSymbols_et_EE', 'goog.i18n.NumberFormatSymbols_eu', 'goog.i18n.NumberFormatSymbols_eu_ES', 'goog.i18n.NumberFormatSymbols_fa', 'goog.i18n.NumberFormatSymbols_fa_IR', 'goog.i18n.NumberFormatSymbols_fi', 'goog.i18n.NumberFormatSymbols_fi_FI', 'goog.i18n.NumberFormatSymbols_fil', 'goog.i18n.NumberFormatSymbols_fil_PH', 'goog.i18n.NumberFormatSymbols_fr', 'goog.i18n.NumberFormatSymbols_fr_BL', 'goog.i18n.NumberFormatSymbols_fr_CA', 'goog.i18n.NumberFormatSymbols_fr_FR', 'goog.i18n.NumberFormatSymbols_fr_GF', 'goog.i18n.NumberFormatSymbols_fr_GP', 'goog.i18n.NumberFormatSymbols_fr_MC', 'goog.i18n.NumberFormatSymbols_fr_MF', 'goog.i18n.NumberFormatSymbols_fr_MQ', 'goog.i18n.NumberFormatSymbols_fr_PM', 'goog.i18n.NumberFormatSymbols_fr_RE', 'goog.i18n.NumberFormatSymbols_fr_YT', 'goog.i18n.NumberFormatSymbols_ga', 'goog.i18n.NumberFormatSymbols_ga_IE', 'goog.i18n.NumberFormatSymbols_gl', 'goog.i18n.NumberFormatSymbols_gl_ES', 'goog.i18n.NumberFormatSymbols_gsw', 'goog.i18n.NumberFormatSymbols_gsw_CH', 'goog.i18n.NumberFormatSymbols_gsw_LI', 'goog.i18n.NumberFormatSymbols_gu', 'goog.i18n.NumberFormatSymbols_gu_IN', 'goog.i18n.NumberFormatSymbols_haw', 'goog.i18n.NumberFormatSymbols_haw_US', 'goog.i18n.NumberFormatSymbols_he', 'goog.i18n.NumberFormatSymbols_he_IL', 'goog.i18n.NumberFormatSymbols_hi', 'goog.i18n.NumberFormatSymbols_hi_IN', 'goog.i18n.NumberFormatSymbols_hr', 'goog.i18n.NumberFormatSymbols_hr_HR', 'goog.i18n.NumberFormatSymbols_hu', 'goog.i18n.NumberFormatSymbols_hu_HU', 'goog.i18n.NumberFormatSymbols_hy', 'goog.i18n.NumberFormatSymbols_hy_AM', 'goog.i18n.NumberFormatSymbols_id', 'goog.i18n.NumberFormatSymbols_id_ID', 'goog.i18n.NumberFormatSymbols_in', 'goog.i18n.NumberFormatSymbols_is', 'goog.i18n.NumberFormatSymbols_is_IS', 'goog.i18n.NumberFormatSymbols_it', 'goog.i18n.NumberFormatSymbols_it_IT', 'goog.i18n.NumberFormatSymbols_it_SM', 'goog.i18n.NumberFormatSymbols_iw', 'goog.i18n.NumberFormatSymbols_ja', 'goog.i18n.NumberFormatSymbols_ja_JP', 'goog.i18n.NumberFormatSymbols_ka', 'goog.i18n.NumberFormatSymbols_ka_GE', 'goog.i18n.NumberFormatSymbols_kk', 'goog.i18n.NumberFormatSymbols_kk_KZ', 'goog.i18n.NumberFormatSymbols_km', 'goog.i18n.NumberFormatSymbols_km_KH', 'goog.i18n.NumberFormatSymbols_kn', 'goog.i18n.NumberFormatSymbols_kn_IN', 'goog.i18n.NumberFormatSymbols_ko', 'goog.i18n.NumberFormatSymbols_ko_KR', 'goog.i18n.NumberFormatSymbols_ky', 'goog.i18n.NumberFormatSymbols_ky_KG', 'goog.i18n.NumberFormatSymbols_ln', 'goog.i18n.NumberFormatSymbols_ln_CD', 'goog.i18n.NumberFormatSymbols_lo', 'goog.i18n.NumberFormatSymbols_lo_LA', 'goog.i18n.NumberFormatSymbols_lt', 'goog.i18n.NumberFormatSymbols_lt_LT', 'goog.i18n.NumberFormatSymbols_lv', 'goog.i18n.NumberFormatSymbols_lv_LV', 'goog.i18n.NumberFormatSymbols_mk', 'goog.i18n.NumberFormatSymbols_mk_MK', 'goog.i18n.NumberFormatSymbols_ml', 'goog.i18n.NumberFormatSymbols_ml_IN', 'goog.i18n.NumberFormatSymbols_mn', 'goog.i18n.NumberFormatSymbols_mn_MN', 'goog.i18n.NumberFormatSymbols_mr', 'goog.i18n.NumberFormatSymbols_mr_IN', 'goog.i18n.NumberFormatSymbols_ms', 'goog.i18n.NumberFormatSymbols_ms_MY', 'goog.i18n.NumberFormatSymbols_mt', 'goog.i18n.NumberFormatSymbols_mt_MT', 'goog.i18n.NumberFormatSymbols_my', 'goog.i18n.NumberFormatSymbols_my_MM', 'goog.i18n.NumberFormatSymbols_nb', 'goog.i18n.NumberFormatSymbols_nb_NO', 'goog.i18n.NumberFormatSymbols_nb_SJ', 'goog.i18n.NumberFormatSymbols_ne', 'goog.i18n.NumberFormatSymbols_ne_NP', 'goog.i18n.NumberFormatSymbols_nl', 'goog.i18n.NumberFormatSymbols_nl_NL', 'goog.i18n.NumberFormatSymbols_no', 'goog.i18n.NumberFormatSymbols_no_NO', 'goog.i18n.NumberFormatSymbols_or', 'goog.i18n.NumberFormatSymbols_or_IN', 'goog.i18n.NumberFormatSymbols_pa', 'goog.i18n.NumberFormatSymbols_pa_Guru', 'goog.i18n.NumberFormatSymbols_pa_Guru_IN', 'goog.i18n.NumberFormatSymbols_pl', 'goog.i18n.NumberFormatSymbols_pl_PL', 'goog.i18n.NumberFormatSymbols_pt', 'goog.i18n.NumberFormatSymbols_pt_BR', 'goog.i18n.NumberFormatSymbols_pt_PT', 'goog.i18n.NumberFormatSymbols_ro', 'goog.i18n.NumberFormatSymbols_ro_RO', 'goog.i18n.NumberFormatSymbols_ru', 'goog.i18n.NumberFormatSymbols_ru_RU', 'goog.i18n.NumberFormatSymbols_si', 'goog.i18n.NumberFormatSymbols_si_LK', 'goog.i18n.NumberFormatSymbols_sk', 'goog.i18n.NumberFormatSymbols_sk_SK', 'goog.i18n.NumberFormatSymbols_sl', 'goog.i18n.NumberFormatSymbols_sl_SI', 'goog.i18n.NumberFormatSymbols_sq', 'goog.i18n.NumberFormatSymbols_sq_AL', 'goog.i18n.NumberFormatSymbols_sr', 'goog.i18n.NumberFormatSymbols_sr_Cyrl', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_RS', 'goog.i18n.NumberFormatSymbols_sr_Latn', 'goog.i18n.NumberFormatSymbols_sr_Latn_RS', 'goog.i18n.NumberFormatSymbols_sv', 'goog.i18n.NumberFormatSymbols_sv_SE', 'goog.i18n.NumberFormatSymbols_sw', 'goog.i18n.NumberFormatSymbols_sw_TZ', 'goog.i18n.NumberFormatSymbols_ta', 'goog.i18n.NumberFormatSymbols_ta_IN', 'goog.i18n.NumberFormatSymbols_te', 'goog.i18n.NumberFormatSymbols_te_IN', 'goog.i18n.NumberFormatSymbols_th', 'goog.i18n.NumberFormatSymbols_th_TH', 'goog.i18n.NumberFormatSymbols_tl', 'goog.i18n.NumberFormatSymbols_tr', 'goog.i18n.NumberFormatSymbols_tr_TR', 'goog.i18n.NumberFormatSymbols_uk', 'goog.i18n.NumberFormatSymbols_uk_UA', 'goog.i18n.NumberFormatSymbols_ur', 'goog.i18n.NumberFormatSymbols_ur_PK', 'goog.i18n.NumberFormatSymbols_uz', 'goog.i18n.NumberFormatSymbols_uz_Latn', 'goog.i18n.NumberFormatSymbols_uz_Latn_UZ', 'goog.i18n.NumberFormatSymbols_vi', 'goog.i18n.NumberFormatSymbols_vi_VN', 'goog.i18n.NumberFormatSymbols_zh', 'goog.i18n.NumberFormatSymbols_zh_CN', 'goog.i18n.NumberFormatSymbols_zh_HK', 'goog.i18n.NumberFormatSymbols_zh_Hans', 'goog.i18n.NumberFormatSymbols_zh_Hans_CN', 'goog.i18n.NumberFormatSymbols_zh_TW', 'goog.i18n.NumberFormatSymbols_zu', 'goog.i18n.NumberFormatSymbols_zu_ZA'], []);\ngoog.addDependency(\"i18n/numberformatsymbolsext.js\", ['goog.i18n.NumberFormatSymbolsExt', 'goog.i18n.NumberFormatSymbols_af_NA', 'goog.i18n.NumberFormatSymbols_agq', 'goog.i18n.NumberFormatSymbols_agq_CM', 'goog.i18n.NumberFormatSymbols_ak', 'goog.i18n.NumberFormatSymbols_ak_GH', 'goog.i18n.NumberFormatSymbols_ar_AE', 'goog.i18n.NumberFormatSymbols_ar_BH', 'goog.i18n.NumberFormatSymbols_ar_DJ', 'goog.i18n.NumberFormatSymbols_ar_DZ', 'goog.i18n.NumberFormatSymbols_ar_EH', 'goog.i18n.NumberFormatSymbols_ar_ER', 'goog.i18n.NumberFormatSymbols_ar_IL', 'goog.i18n.NumberFormatSymbols_ar_IQ', 'goog.i18n.NumberFormatSymbols_ar_JO', 'goog.i18n.NumberFormatSymbols_ar_KM', 'goog.i18n.NumberFormatSymbols_ar_KW', 'goog.i18n.NumberFormatSymbols_ar_LB', 'goog.i18n.NumberFormatSymbols_ar_LY', 'goog.i18n.NumberFormatSymbols_ar_MA', 'goog.i18n.NumberFormatSymbols_ar_MR', 'goog.i18n.NumberFormatSymbols_ar_OM', 'goog.i18n.NumberFormatSymbols_ar_PS', 'goog.i18n.NumberFormatSymbols_ar_QA', 'goog.i18n.NumberFormatSymbols_ar_SA', 'goog.i18n.NumberFormatSymbols_ar_SD', 'goog.i18n.NumberFormatSymbols_ar_SO', 'goog.i18n.NumberFormatSymbols_ar_SS', 'goog.i18n.NumberFormatSymbols_ar_SY', 'goog.i18n.NumberFormatSymbols_ar_TD', 'goog.i18n.NumberFormatSymbols_ar_TN', 'goog.i18n.NumberFormatSymbols_ar_YE', 'goog.i18n.NumberFormatSymbols_as', 'goog.i18n.NumberFormatSymbols_as_IN', 'goog.i18n.NumberFormatSymbols_asa', 'goog.i18n.NumberFormatSymbols_asa_TZ', 'goog.i18n.NumberFormatSymbols_ast', 'goog.i18n.NumberFormatSymbols_ast_ES', 'goog.i18n.NumberFormatSymbols_az_Cyrl', 'goog.i18n.NumberFormatSymbols_az_Cyrl_AZ', 'goog.i18n.NumberFormatSymbols_bas', 'goog.i18n.NumberFormatSymbols_bas_CM', 'goog.i18n.NumberFormatSymbols_bem', 'goog.i18n.NumberFormatSymbols_bem_ZM', 'goog.i18n.NumberFormatSymbols_bez', 'goog.i18n.NumberFormatSymbols_bez_TZ', 'goog.i18n.NumberFormatSymbols_bm', 'goog.i18n.NumberFormatSymbols_bm_ML', 'goog.i18n.NumberFormatSymbols_bn_IN', 'goog.i18n.NumberFormatSymbols_bo', 'goog.i18n.NumberFormatSymbols_bo_CN', 'goog.i18n.NumberFormatSymbols_bo_IN', 'goog.i18n.NumberFormatSymbols_brx', 'goog.i18n.NumberFormatSymbols_brx_IN', 'goog.i18n.NumberFormatSymbols_bs_Cyrl', 'goog.i18n.NumberFormatSymbols_bs_Cyrl_BA', 'goog.i18n.NumberFormatSymbols_ce', 'goog.i18n.NumberFormatSymbols_ce_RU', 'goog.i18n.NumberFormatSymbols_cgg', 'goog.i18n.NumberFormatSymbols_cgg_UG', 'goog.i18n.NumberFormatSymbols_ckb', 'goog.i18n.NumberFormatSymbols_ckb_Arab', 'goog.i18n.NumberFormatSymbols_ckb_Arab_IQ', 'goog.i18n.NumberFormatSymbols_ckb_Arab_IR', 'goog.i18n.NumberFormatSymbols_ckb_IQ', 'goog.i18n.NumberFormatSymbols_ckb_IR', 'goog.i18n.NumberFormatSymbols_ckb_Latn', 'goog.i18n.NumberFormatSymbols_ckb_Latn_IQ', 'goog.i18n.NumberFormatSymbols_cu', 'goog.i18n.NumberFormatSymbols_cu_RU', 'goog.i18n.NumberFormatSymbols_dav', 'goog.i18n.NumberFormatSymbols_dav_KE', 'goog.i18n.NumberFormatSymbols_de_LI', 'goog.i18n.NumberFormatSymbols_dje', 'goog.i18n.NumberFormatSymbols_dje_NE', 'goog.i18n.NumberFormatSymbols_dsb', 'goog.i18n.NumberFormatSymbols_dsb_DE', 'goog.i18n.NumberFormatSymbols_dua', 'goog.i18n.NumberFormatSymbols_dua_CM', 'goog.i18n.NumberFormatSymbols_dyo', 'goog.i18n.NumberFormatSymbols_dyo_SN', 'goog.i18n.NumberFormatSymbols_dz', 'goog.i18n.NumberFormatSymbols_dz_BT', 'goog.i18n.NumberFormatSymbols_ebu', 'goog.i18n.NumberFormatSymbols_ebu_KE', 'goog.i18n.NumberFormatSymbols_ee', 'goog.i18n.NumberFormatSymbols_ee_GH', 'goog.i18n.NumberFormatSymbols_ee_TG', 'goog.i18n.NumberFormatSymbols_en_150', 'goog.i18n.NumberFormatSymbols_en_AG', 'goog.i18n.NumberFormatSymbols_en_AI', 'goog.i18n.NumberFormatSymbols_en_AT', 'goog.i18n.NumberFormatSymbols_en_BB', 'goog.i18n.NumberFormatSymbols_en_BE', 'goog.i18n.NumberFormatSymbols_en_BI', 'goog.i18n.NumberFormatSymbols_en_BM', 'goog.i18n.NumberFormatSymbols_en_BS', 'goog.i18n.NumberFormatSymbols_en_BW', 'goog.i18n.NumberFormatSymbols_en_BZ', 'goog.i18n.NumberFormatSymbols_en_CC', 'goog.i18n.NumberFormatSymbols_en_CH', 'goog.i18n.NumberFormatSymbols_en_CK', 'goog.i18n.NumberFormatSymbols_en_CM', 'goog.i18n.NumberFormatSymbols_en_CX', 'goog.i18n.NumberFormatSymbols_en_CY', 'goog.i18n.NumberFormatSymbols_en_DE', 'goog.i18n.NumberFormatSymbols_en_DK', 'goog.i18n.NumberFormatSymbols_en_DM', 'goog.i18n.NumberFormatSymbols_en_ER', 'goog.i18n.NumberFormatSymbols_en_FI', 'goog.i18n.NumberFormatSymbols_en_FJ', 'goog.i18n.NumberFormatSymbols_en_FK', 'goog.i18n.NumberFormatSymbols_en_GD', 'goog.i18n.NumberFormatSymbols_en_GG', 'goog.i18n.NumberFormatSymbols_en_GH', 'goog.i18n.NumberFormatSymbols_en_GI', 'goog.i18n.NumberFormatSymbols_en_GM', 'goog.i18n.NumberFormatSymbols_en_GY', 'goog.i18n.NumberFormatSymbols_en_HK', 'goog.i18n.NumberFormatSymbols_en_IL', 'goog.i18n.NumberFormatSymbols_en_IM', 'goog.i18n.NumberFormatSymbols_en_JE', 'goog.i18n.NumberFormatSymbols_en_JM', 'goog.i18n.NumberFormatSymbols_en_KE', 'goog.i18n.NumberFormatSymbols_en_KI', 'goog.i18n.NumberFormatSymbols_en_KN', 'goog.i18n.NumberFormatSymbols_en_KY', 'goog.i18n.NumberFormatSymbols_en_LC', 'goog.i18n.NumberFormatSymbols_en_LR', 'goog.i18n.NumberFormatSymbols_en_LS', 'goog.i18n.NumberFormatSymbols_en_MG', 'goog.i18n.NumberFormatSymbols_en_MO', 'goog.i18n.NumberFormatSymbols_en_MS', 'goog.i18n.NumberFormatSymbols_en_MT', 'goog.i18n.NumberFormatSymbols_en_MU', 'goog.i18n.NumberFormatSymbols_en_MW', 'goog.i18n.NumberFormatSymbols_en_MY', 'goog.i18n.NumberFormatSymbols_en_NA', 'goog.i18n.NumberFormatSymbols_en_NF', 'goog.i18n.NumberFormatSymbols_en_NG', 'goog.i18n.NumberFormatSymbols_en_NL', 'goog.i18n.NumberFormatSymbols_en_NR', 'goog.i18n.NumberFormatSymbols_en_NU', 'goog.i18n.NumberFormatSymbols_en_NZ', 'goog.i18n.NumberFormatSymbols_en_PG', 'goog.i18n.NumberFormatSymbols_en_PH', 'goog.i18n.NumberFormatSymbols_en_PK', 'goog.i18n.NumberFormatSymbols_en_PN', 'goog.i18n.NumberFormatSymbols_en_RW', 'goog.i18n.NumberFormatSymbols_en_SB', 'goog.i18n.NumberFormatSymbols_en_SC', 'goog.i18n.NumberFormatSymbols_en_SD', 'goog.i18n.NumberFormatSymbols_en_SE', 'goog.i18n.NumberFormatSymbols_en_SH', 'goog.i18n.NumberFormatSymbols_en_SI', 'goog.i18n.NumberFormatSymbols_en_SL', 'goog.i18n.NumberFormatSymbols_en_SS', 'goog.i18n.NumberFormatSymbols_en_SX', 'goog.i18n.NumberFormatSymbols_en_SZ', 'goog.i18n.NumberFormatSymbols_en_TK', 'goog.i18n.NumberFormatSymbols_en_TO', 'goog.i18n.NumberFormatSymbols_en_TT', 'goog.i18n.NumberFormatSymbols_en_TV', 'goog.i18n.NumberFormatSymbols_en_TZ', 'goog.i18n.NumberFormatSymbols_en_UG', 'goog.i18n.NumberFormatSymbols_en_VC', 'goog.i18n.NumberFormatSymbols_en_VU', 'goog.i18n.NumberFormatSymbols_en_WS', 'goog.i18n.NumberFormatSymbols_en_ZM', 'goog.i18n.NumberFormatSymbols_eo', 'goog.i18n.NumberFormatSymbols_eo_001', 'goog.i18n.NumberFormatSymbols_es_AR', 'goog.i18n.NumberFormatSymbols_es_BO', 'goog.i18n.NumberFormatSymbols_es_CL', 'goog.i18n.NumberFormatSymbols_es_CO', 'goog.i18n.NumberFormatSymbols_es_CR', 'goog.i18n.NumberFormatSymbols_es_CU', 'goog.i18n.NumberFormatSymbols_es_DO', 'goog.i18n.NumberFormatSymbols_es_EC', 'goog.i18n.NumberFormatSymbols_es_GQ', 'goog.i18n.NumberFormatSymbols_es_GT', 'goog.i18n.NumberFormatSymbols_es_HN', 'goog.i18n.NumberFormatSymbols_es_NI', 'goog.i18n.NumberFormatSymbols_es_PA', 'goog.i18n.NumberFormatSymbols_es_PE', 'goog.i18n.NumberFormatSymbols_es_PH', 'goog.i18n.NumberFormatSymbols_es_PR', 'goog.i18n.NumberFormatSymbols_es_PY', 'goog.i18n.NumberFormatSymbols_es_SV', 'goog.i18n.NumberFormatSymbols_es_UY', 'goog.i18n.NumberFormatSymbols_es_VE', 'goog.i18n.NumberFormatSymbols_ewo', 'goog.i18n.NumberFormatSymbols_ewo_CM', 'goog.i18n.NumberFormatSymbols_fa_AF', 'goog.i18n.NumberFormatSymbols_ff', 'goog.i18n.NumberFormatSymbols_ff_CM', 'goog.i18n.NumberFormatSymbols_ff_GN', 'goog.i18n.NumberFormatSymbols_ff_MR', 'goog.i18n.NumberFormatSymbols_ff_SN', 'goog.i18n.NumberFormatSymbols_fo', 'goog.i18n.NumberFormatSymbols_fo_DK', 'goog.i18n.NumberFormatSymbols_fo_FO', 'goog.i18n.NumberFormatSymbols_fr_BE', 'goog.i18n.NumberFormatSymbols_fr_BF', 'goog.i18n.NumberFormatSymbols_fr_BI', 'goog.i18n.NumberFormatSymbols_fr_BJ', 'goog.i18n.NumberFormatSymbols_fr_CD', 'goog.i18n.NumberFormatSymbols_fr_CF', 'goog.i18n.NumberFormatSymbols_fr_CG', 'goog.i18n.NumberFormatSymbols_fr_CH', 'goog.i18n.NumberFormatSymbols_fr_CI', 'goog.i18n.NumberFormatSymbols_fr_CM', 'goog.i18n.NumberFormatSymbols_fr_DJ', 'goog.i18n.NumberFormatSymbols_fr_DZ', 'goog.i18n.NumberFormatSymbols_fr_GA', 'goog.i18n.NumberFormatSymbols_fr_GN', 'goog.i18n.NumberFormatSymbols_fr_GQ', 'goog.i18n.NumberFormatSymbols_fr_HT', 'goog.i18n.NumberFormatSymbols_fr_KM', 'goog.i18n.NumberFormatSymbols_fr_LU', 'goog.i18n.NumberFormatSymbols_fr_MA', 'goog.i18n.NumberFormatSymbols_fr_MG', 'goog.i18n.NumberFormatSymbols_fr_ML', 'goog.i18n.NumberFormatSymbols_fr_MR', 'goog.i18n.NumberFormatSymbols_fr_MU', 'goog.i18n.NumberFormatSymbols_fr_NC', 'goog.i18n.NumberFormatSymbols_fr_NE', 'goog.i18n.NumberFormatSymbols_fr_PF', 'goog.i18n.NumberFormatSymbols_fr_RW', 'goog.i18n.NumberFormatSymbols_fr_SC', 'goog.i18n.NumberFormatSymbols_fr_SN', 'goog.i18n.NumberFormatSymbols_fr_SY', 'goog.i18n.NumberFormatSymbols_fr_TD', 'goog.i18n.NumberFormatSymbols_fr_TG', 'goog.i18n.NumberFormatSymbols_fr_TN', 'goog.i18n.NumberFormatSymbols_fr_VU', 'goog.i18n.NumberFormatSymbols_fr_WF', 'goog.i18n.NumberFormatSymbols_fur', 'goog.i18n.NumberFormatSymbols_fur_IT', 'goog.i18n.NumberFormatSymbols_fy', 'goog.i18n.NumberFormatSymbols_fy_NL', 'goog.i18n.NumberFormatSymbols_gd', 'goog.i18n.NumberFormatSymbols_gd_GB', 'goog.i18n.NumberFormatSymbols_gsw_FR', 'goog.i18n.NumberFormatSymbols_guz', 'goog.i18n.NumberFormatSymbols_guz_KE', 'goog.i18n.NumberFormatSymbols_gv', 'goog.i18n.NumberFormatSymbols_gv_IM', 'goog.i18n.NumberFormatSymbols_ha', 'goog.i18n.NumberFormatSymbols_ha_GH', 'goog.i18n.NumberFormatSymbols_ha_NE', 'goog.i18n.NumberFormatSymbols_ha_NG', 'goog.i18n.NumberFormatSymbols_hr_BA', 'goog.i18n.NumberFormatSymbols_hsb', 'goog.i18n.NumberFormatSymbols_hsb_DE', 'goog.i18n.NumberFormatSymbols_ig', 'goog.i18n.NumberFormatSymbols_ig_NG', 'goog.i18n.NumberFormatSymbols_ii', 'goog.i18n.NumberFormatSymbols_ii_CN', 'goog.i18n.NumberFormatSymbols_it_CH', 'goog.i18n.NumberFormatSymbols_jgo', 'goog.i18n.NumberFormatSymbols_jgo_CM', 'goog.i18n.NumberFormatSymbols_jmc', 'goog.i18n.NumberFormatSymbols_jmc_TZ', 'goog.i18n.NumberFormatSymbols_kab', 'goog.i18n.NumberFormatSymbols_kab_DZ', 'goog.i18n.NumberFormatSymbols_kam', 'goog.i18n.NumberFormatSymbols_kam_KE', 'goog.i18n.NumberFormatSymbols_kde', 'goog.i18n.NumberFormatSymbols_kde_TZ', 'goog.i18n.NumberFormatSymbols_kea', 'goog.i18n.NumberFormatSymbols_kea_CV', 'goog.i18n.NumberFormatSymbols_khq', 'goog.i18n.NumberFormatSymbols_khq_ML', 'goog.i18n.NumberFormatSymbols_ki', 'goog.i18n.NumberFormatSymbols_ki_KE', 'goog.i18n.NumberFormatSymbols_kkj', 'goog.i18n.NumberFormatSymbols_kkj_CM', 'goog.i18n.NumberFormatSymbols_kl', 'goog.i18n.NumberFormatSymbols_kl_GL', 'goog.i18n.NumberFormatSymbols_kln', 'goog.i18n.NumberFormatSymbols_kln_KE', 'goog.i18n.NumberFormatSymbols_ko_KP', 'goog.i18n.NumberFormatSymbols_kok', 'goog.i18n.NumberFormatSymbols_kok_IN', 'goog.i18n.NumberFormatSymbols_ks', 'goog.i18n.NumberFormatSymbols_ks_IN', 'goog.i18n.NumberFormatSymbols_ksb', 'goog.i18n.NumberFormatSymbols_ksb_TZ', 'goog.i18n.NumberFormatSymbols_ksf', 'goog.i18n.NumberFormatSymbols_ksf_CM', 'goog.i18n.NumberFormatSymbols_ksh', 'goog.i18n.NumberFormatSymbols_ksh_DE', 'goog.i18n.NumberFormatSymbols_kw', 'goog.i18n.NumberFormatSymbols_kw_GB', 'goog.i18n.NumberFormatSymbols_lag', 'goog.i18n.NumberFormatSymbols_lag_TZ', 'goog.i18n.NumberFormatSymbols_lb', 'goog.i18n.NumberFormatSymbols_lb_LU', 'goog.i18n.NumberFormatSymbols_lg', 'goog.i18n.NumberFormatSymbols_lg_UG', 'goog.i18n.NumberFormatSymbols_lkt', 'goog.i18n.NumberFormatSymbols_lkt_US', 'goog.i18n.NumberFormatSymbols_ln_AO', 'goog.i18n.NumberFormatSymbols_ln_CF', 'goog.i18n.NumberFormatSymbols_ln_CG', 'goog.i18n.NumberFormatSymbols_lrc', 'goog.i18n.NumberFormatSymbols_lrc_IQ', 'goog.i18n.NumberFormatSymbols_lrc_IR', 'goog.i18n.NumberFormatSymbols_lu', 'goog.i18n.NumberFormatSymbols_lu_CD', 'goog.i18n.NumberFormatSymbols_luo', 'goog.i18n.NumberFormatSymbols_luo_KE', 'goog.i18n.NumberFormatSymbols_luy', 'goog.i18n.NumberFormatSymbols_luy_KE', 'goog.i18n.NumberFormatSymbols_mas', 'goog.i18n.NumberFormatSymbols_mas_KE', 'goog.i18n.NumberFormatSymbols_mas_TZ', 'goog.i18n.NumberFormatSymbols_mer', 'goog.i18n.NumberFormatSymbols_mer_KE', 'goog.i18n.NumberFormatSymbols_mfe', 'goog.i18n.NumberFormatSymbols_mfe_MU', 'goog.i18n.NumberFormatSymbols_mg', 'goog.i18n.NumberFormatSymbols_mg_MG', 'goog.i18n.NumberFormatSymbols_mgh', 'goog.i18n.NumberFormatSymbols_mgh_MZ', 'goog.i18n.NumberFormatSymbols_mgo', 'goog.i18n.NumberFormatSymbols_mgo_CM', 'goog.i18n.NumberFormatSymbols_ms_BN', 'goog.i18n.NumberFormatSymbols_ms_SG', 'goog.i18n.NumberFormatSymbols_mua', 'goog.i18n.NumberFormatSymbols_mua_CM', 'goog.i18n.NumberFormatSymbols_mzn', 'goog.i18n.NumberFormatSymbols_mzn_IR', 'goog.i18n.NumberFormatSymbols_naq', 'goog.i18n.NumberFormatSymbols_naq_NA', 'goog.i18n.NumberFormatSymbols_nd', 'goog.i18n.NumberFormatSymbols_nd_ZW', 'goog.i18n.NumberFormatSymbols_ne_IN', 'goog.i18n.NumberFormatSymbols_nl_AW', 'goog.i18n.NumberFormatSymbols_nl_BE', 'goog.i18n.NumberFormatSymbols_nl_BQ', 'goog.i18n.NumberFormatSymbols_nl_CW', 'goog.i18n.NumberFormatSymbols_nl_SR', 'goog.i18n.NumberFormatSymbols_nl_SX', 'goog.i18n.NumberFormatSymbols_nmg', 'goog.i18n.NumberFormatSymbols_nmg_CM', 'goog.i18n.NumberFormatSymbols_nn', 'goog.i18n.NumberFormatSymbols_nn_NO', 'goog.i18n.NumberFormatSymbols_nnh', 'goog.i18n.NumberFormatSymbols_nnh_CM', 'goog.i18n.NumberFormatSymbols_nus', 'goog.i18n.NumberFormatSymbols_nus_SS', 'goog.i18n.NumberFormatSymbols_nyn', 'goog.i18n.NumberFormatSymbols_nyn_UG', 'goog.i18n.NumberFormatSymbols_om', 'goog.i18n.NumberFormatSymbols_om_ET', 'goog.i18n.NumberFormatSymbols_om_KE', 'goog.i18n.NumberFormatSymbols_os', 'goog.i18n.NumberFormatSymbols_os_GE', 'goog.i18n.NumberFormatSymbols_os_RU', 'goog.i18n.NumberFormatSymbols_pa_Arab', 'goog.i18n.NumberFormatSymbols_pa_Arab_PK', 'goog.i18n.NumberFormatSymbols_prg', 'goog.i18n.NumberFormatSymbols_prg_001', 'goog.i18n.NumberFormatSymbols_ps', 'goog.i18n.NumberFormatSymbols_ps_AF', 'goog.i18n.NumberFormatSymbols_pt_AO', 'goog.i18n.NumberFormatSymbols_pt_CV', 'goog.i18n.NumberFormatSymbols_pt_GW', 'goog.i18n.NumberFormatSymbols_pt_MO', 'goog.i18n.NumberFormatSymbols_pt_MZ', 'goog.i18n.NumberFormatSymbols_pt_ST', 'goog.i18n.NumberFormatSymbols_pt_TL', 'goog.i18n.NumberFormatSymbols_qu', 'goog.i18n.NumberFormatSymbols_qu_BO', 'goog.i18n.NumberFormatSymbols_qu_EC', 'goog.i18n.NumberFormatSymbols_qu_PE', 'goog.i18n.NumberFormatSymbols_rm', 'goog.i18n.NumberFormatSymbols_rm_CH', 'goog.i18n.NumberFormatSymbols_rn', 'goog.i18n.NumberFormatSymbols_rn_BI', 'goog.i18n.NumberFormatSymbols_ro_MD', 'goog.i18n.NumberFormatSymbols_rof', 'goog.i18n.NumberFormatSymbols_rof_TZ', 'goog.i18n.NumberFormatSymbols_ru_BY', 'goog.i18n.NumberFormatSymbols_ru_KG', 'goog.i18n.NumberFormatSymbols_ru_KZ', 'goog.i18n.NumberFormatSymbols_ru_MD', 'goog.i18n.NumberFormatSymbols_ru_UA', 'goog.i18n.NumberFormatSymbols_rw', 'goog.i18n.NumberFormatSymbols_rw_RW', 'goog.i18n.NumberFormatSymbols_rwk', 'goog.i18n.NumberFormatSymbols_rwk_TZ', 'goog.i18n.NumberFormatSymbols_sah', 'goog.i18n.NumberFormatSymbols_sah_RU', 'goog.i18n.NumberFormatSymbols_saq', 'goog.i18n.NumberFormatSymbols_saq_KE', 'goog.i18n.NumberFormatSymbols_sbp', 'goog.i18n.NumberFormatSymbols_sbp_TZ', 'goog.i18n.NumberFormatSymbols_se', 'goog.i18n.NumberFormatSymbols_se_FI', 'goog.i18n.NumberFormatSymbols_se_NO', 'goog.i18n.NumberFormatSymbols_se_SE', 'goog.i18n.NumberFormatSymbols_seh', 'goog.i18n.NumberFormatSymbols_seh_MZ', 'goog.i18n.NumberFormatSymbols_ses', 'goog.i18n.NumberFormatSymbols_ses_ML', 'goog.i18n.NumberFormatSymbols_sg', 'goog.i18n.NumberFormatSymbols_sg_CF', 'goog.i18n.NumberFormatSymbols_shi', 'goog.i18n.NumberFormatSymbols_shi_Latn', 'goog.i18n.NumberFormatSymbols_shi_Latn_MA', 'goog.i18n.NumberFormatSymbols_shi_Tfng', 'goog.i18n.NumberFormatSymbols_shi_Tfng_MA', 'goog.i18n.NumberFormatSymbols_smn', 'goog.i18n.NumberFormatSymbols_smn_FI', 'goog.i18n.NumberFormatSymbols_sn', 'goog.i18n.NumberFormatSymbols_sn_ZW', 'goog.i18n.NumberFormatSymbols_so', 'goog.i18n.NumberFormatSymbols_so_DJ', 'goog.i18n.NumberFormatSymbols_so_ET', 'goog.i18n.NumberFormatSymbols_so_KE', 'goog.i18n.NumberFormatSymbols_so_SO', 'goog.i18n.NumberFormatSymbols_sq_MK', 'goog.i18n.NumberFormatSymbols_sq_XK', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_BA', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_ME', 'goog.i18n.NumberFormatSymbols_sr_Cyrl_XK', 'goog.i18n.NumberFormatSymbols_sr_Latn_BA', 'goog.i18n.NumberFormatSymbols_sr_Latn_ME', 'goog.i18n.NumberFormatSymbols_sr_Latn_XK', 'goog.i18n.NumberFormatSymbols_sv_AX', 'goog.i18n.NumberFormatSymbols_sv_FI', 'goog.i18n.NumberFormatSymbols_sw_CD', 'goog.i18n.NumberFormatSymbols_sw_KE', 'goog.i18n.NumberFormatSymbols_sw_UG', 'goog.i18n.NumberFormatSymbols_ta_LK', 'goog.i18n.NumberFormatSymbols_ta_MY', 'goog.i18n.NumberFormatSymbols_ta_SG', 'goog.i18n.NumberFormatSymbols_teo', 'goog.i18n.NumberFormatSymbols_teo_KE', 'goog.i18n.NumberFormatSymbols_teo_UG', 'goog.i18n.NumberFormatSymbols_ti', 'goog.i18n.NumberFormatSymbols_ti_ER', 'goog.i18n.NumberFormatSymbols_ti_ET', 'goog.i18n.NumberFormatSymbols_tk', 'goog.i18n.NumberFormatSymbols_tk_TM', 'goog.i18n.NumberFormatSymbols_to', 'goog.i18n.NumberFormatSymbols_to_TO', 'goog.i18n.NumberFormatSymbols_tr_CY', 'goog.i18n.NumberFormatSymbols_twq', 'goog.i18n.NumberFormatSymbols_twq_NE', 'goog.i18n.NumberFormatSymbols_tzm', 'goog.i18n.NumberFormatSymbols_tzm_MA', 'goog.i18n.NumberFormatSymbols_ug', 'goog.i18n.NumberFormatSymbols_ug_CN', 'goog.i18n.NumberFormatSymbols_ur_IN', 'goog.i18n.NumberFormatSymbols_uz_Arab', 'goog.i18n.NumberFormatSymbols_uz_Arab_AF', 'goog.i18n.NumberFormatSymbols_uz_Cyrl', 'goog.i18n.NumberFormatSymbols_uz_Cyrl_UZ', 'goog.i18n.NumberFormatSymbols_vai', 'goog.i18n.NumberFormatSymbols_vai_Latn', 'goog.i18n.NumberFormatSymbols_vai_Latn_LR', 'goog.i18n.NumberFormatSymbols_vai_Vaii', 'goog.i18n.NumberFormatSymbols_vai_Vaii_LR', 'goog.i18n.NumberFormatSymbols_vo', 'goog.i18n.NumberFormatSymbols_vo_001', 'goog.i18n.NumberFormatSymbols_vun', 'goog.i18n.NumberFormatSymbols_vun_TZ', 'goog.i18n.NumberFormatSymbols_wae', 'goog.i18n.NumberFormatSymbols_wae_CH', 'goog.i18n.NumberFormatSymbols_xog', 'goog.i18n.NumberFormatSymbols_xog_UG', 'goog.i18n.NumberFormatSymbols_yav', 'goog.i18n.NumberFormatSymbols_yav_CM', 'goog.i18n.NumberFormatSymbols_yi', 'goog.i18n.NumberFormatSymbols_yi_001', 'goog.i18n.NumberFormatSymbols_yo', 'goog.i18n.NumberFormatSymbols_yo_BJ', 'goog.i18n.NumberFormatSymbols_yo_NG', 'goog.i18n.NumberFormatSymbols_zgh', 'goog.i18n.NumberFormatSymbols_zgh_MA', 'goog.i18n.NumberFormatSymbols_zh_Hans_HK', 'goog.i18n.NumberFormatSymbols_zh_Hans_MO', 'goog.i18n.NumberFormatSymbols_zh_Hans_SG', 'goog.i18n.NumberFormatSymbols_zh_Hant', 'goog.i18n.NumberFormatSymbols_zh_Hant_HK', 'goog.i18n.NumberFormatSymbols_zh_Hant_MO', 'goog.i18n.NumberFormatSymbols_zh_Hant_TW'], ['goog.i18n.NumberFormatSymbols']);\ngoog.addDependency(\"i18n/ordinalrules.js\", ['goog.i18n.ordinalRules'], []);\ngoog.addDependency(\"i18n/pluralrules.js\", ['goog.i18n.pluralRules'], []);\ngoog.addDependency(\"i18n/pluralrules_test.js\", ['goog.i18n.pluralRulesTest'], ['goog.i18n.pluralRules', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/timezone.js\", ['goog.i18n.TimeZone'], ['goog.array', 'goog.date.DateLike', 'goog.object', 'goog.string']);\ngoog.addDependency(\"i18n/timezone_test.js\", ['goog.i18n.TimeZoneTest'], ['goog.i18n.TimeZone', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/uchar.js\", ['goog.i18n.uChar'], []);\ngoog.addDependency(\"i18n/uchar_test.js\", ['goog.i18n.uCharTest'], ['goog.i18n.uChar', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/ucharnames.js\", ['goog.i18n.uCharNames'], ['goog.i18n.uChar']);\ngoog.addDependency(\"i18n/ucharnames_test.js\", ['goog.i18n.uCharNamesTest'], ['goog.i18n.uCharNames', 'goog.testing.jsunit']);\ngoog.addDependency(\"i18n/uchar/localnamefetcher.js\", ['goog.i18n.uChar.LocalNameFetcher'], ['goog.i18n.uChar.NameFetcher', 'goog.i18n.uCharNames', 'goog.log']);\ngoog.addDependency(\"i18n/uchar/localnamefetcher_test.js\", ['goog.i18n.uChar.LocalNameFetcherTest'], ['goog.i18n.uChar.LocalNameFetcher', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"i18n/uchar/namefetcher.js\", ['goog.i18n.uChar.NameFetcher'], []);\ngoog.addDependency(\"i18n/uchar/remotenamefetcher.js\", ['goog.i18n.uChar.RemoteNameFetcher'], ['goog.Disposable', 'goog.Uri', 'goog.i18n.uChar', 'goog.i18n.uChar.NameFetcher', 'goog.log', 'goog.net.XhrIo', 'goog.structs.Map']);\ngoog.addDependency(\"i18n/uchar/remotenamefetcher_test.js\", ['goog.i18n.uChar.RemoteNameFetcherTest'], ['goog.i18n.uChar.RemoteNameFetcher', 'goog.net.XhrIo', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction']);\ngoog.addDependency(\"iter/iter.js\", ['goog.iter', 'goog.iter.Iterable', 'goog.iter.Iterator', 'goog.iter.StopIteration'], ['goog.array', 'goog.asserts', 'goog.functions', 'goog.math']);\ngoog.addDependency(\"iter/iter_test.js\", ['goog.iterTest'], ['goog.iter', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.testing.jsunit']);\ngoog.addDependency(\"json/evaljsonprocessor.js\", ['goog.json.EvalJsonProcessor'], ['goog.json', 'goog.json.Processor', 'goog.json.Serializer']);\ngoog.addDependency(\"json/hybrid.js\", ['goog.json.hybrid'], ['goog.asserts', 'goog.json']);\ngoog.addDependency(\"json/hybrid_test.js\", ['goog.json.hybridTest'], ['goog.json', 'goog.json.hybrid', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"json/hybridjsonprocessor.js\", ['goog.json.HybridJsonProcessor'], ['goog.json.Processor', 'goog.json.hybrid']);\ngoog.addDependency(\"json/hybridjsonprocessor_test.js\", ['goog.json.HybridJsonProcessorTest'], ['goog.json.HybridJsonProcessor', 'goog.json.hybrid', 'goog.testing.jsunit']);\ngoog.addDependency(\"json/json.js\", ['goog.json', 'goog.json.Replacer', 'goog.json.Reviver', 'goog.json.Serializer'], []);\ngoog.addDependency(\"json/json_perf.js\", ['goog.jsonPerf'], ['goog.dom', 'goog.json', 'goog.math', 'goog.string', 'goog.testing.PerformanceTable', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"json/json_test.js\", ['goog.jsonTest'], ['goog.functions', 'goog.json', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"json/nativejsonprocessor.js\", ['goog.json.NativeJsonProcessor'], ['goog.asserts', 'goog.json.Processor']);\ngoog.addDependency(\"json/processor.js\", ['goog.json.Processor'], ['goog.string.Parser', 'goog.string.Stringifier']);\ngoog.addDependency(\"json/processor_test.js\", ['goog.json.processorTest'], ['goog.json.EvalJsonProcessor', 'goog.json.NativeJsonProcessor', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"labs/dom/pagevisibilitymonitor.js\", ['goog.labs.dom.PageVisibilityEvent', 'goog.labs.dom.PageVisibilityMonitor', 'goog.labs.dom.PageVisibilityState'], ['goog.dom', 'goog.dom.vendor', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.memoize']);\ngoog.addDependency(\"labs/dom/pagevisibilitymonitor_test.js\", ['goog.labs.dom.PageVisibilityMonitorTest'], ['goog.events', 'goog.functions', 'goog.labs.dom.PageVisibilityMonitor', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"labs/events/nondisposableeventtarget.js\", ['goog.labs.events.NonDisposableEventTarget'], ['goog.array', 'goog.asserts', 'goog.events.Event', 'goog.events.Listenable', 'goog.events.ListenerMap', 'goog.object']);\ngoog.addDependency(\"labs/events/nondisposableeventtarget_test.js\", ['goog.labs.events.NonDisposableEventTargetTest'], ['goog.events.Listenable', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.labs.events.NonDisposableEventTarget', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/events/nondisposableeventtarget_via_googevents_test.js\", ['goog.labs.events.NonDisposableEventTargetGoogEventsTest'], ['goog.events', 'goog.events.eventTargetTester', 'goog.events.eventTargetTester.KeyType', 'goog.events.eventTargetTester.UnlistenReturnType', 'goog.labs.events.NonDisposableEventTarget', 'goog.testing', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/events/touch.js\", ['goog.labs.events.touch', 'goog.labs.events.touch.TouchData'], ['goog.array', 'goog.asserts', 'goog.events.EventType', 'goog.string']);\ngoog.addDependency(\"labs/events/touch_test.js\", ['goog.labs.events.touchTest'], ['goog.labs.events.touch', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/format/csv.js\", ['goog.labs.format.csv', 'goog.labs.format.csv.ParseError', 'goog.labs.format.csv.Token'], ['goog.array', 'goog.asserts', 'goog.debug.Error', 'goog.object', 'goog.string', 'goog.string.newlines']);\ngoog.addDependency(\"labs/format/csv_test.js\", ['goog.labs.format.csvTest'], ['goog.labs.format.csv', 'goog.labs.format.csv.ParseError', 'goog.object', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/html/attribute_rewriter.js\", ['goog.labs.html.AttributeRewriter', 'goog.labs.html.AttributeValue', 'goog.labs.html.attributeRewriterPresubmitWorkaround'], []);\ngoog.addDependency(\"labs/html/sanitizer.js\", ['goog.labs.html.Sanitizer'], ['goog.asserts', 'goog.html.SafeUrl', 'goog.labs.html.attributeRewriterPresubmitWorkaround', 'goog.labs.html.scrubber', 'goog.object', 'goog.string']);\ngoog.addDependency(\"labs/html/sanitizer_test.js\", ['goog.labs.html.SanitizerTest'], ['goog.html.SafeUrl', 'goog.labs.html.Sanitizer', 'goog.string', 'goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/html/scrubber.js\", ['goog.labs.html.scrubber'], ['goog.array', 'goog.dom.tags', 'goog.labs.html.attributeRewriterPresubmitWorkaround', 'goog.string']);\ngoog.addDependency(\"labs/html/scrubber_test.js\", ['goog.html.ScrubberTest'], ['goog.labs.html.scrubber', 'goog.object', 'goog.string', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/i18n/listformat.js\", ['goog.labs.i18n.GenderInfo', 'goog.labs.i18n.GenderInfo.Gender', 'goog.labs.i18n.ListFormat'], ['goog.asserts', 'goog.labs.i18n.ListFormatSymbols']);\ngoog.addDependency(\"labs/i18n/listformat_test.js\", ['goog.labs.i18n.ListFormatTest'], ['goog.labs.i18n.GenderInfo', 'goog.labs.i18n.ListFormat', 'goog.labs.i18n.ListFormatSymbols', 'goog.labs.i18n.ListFormatSymbols_el', 'goog.labs.i18n.ListFormatSymbols_en', 'goog.labs.i18n.ListFormatSymbols_fr', 'goog.labs.i18n.ListFormatSymbols_ml', 'goog.labs.i18n.ListFormatSymbols_zu', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/i18n/listsymbols.js\", ['goog.labs.i18n.ListFormatSymbols', 'goog.labs.i18n.ListFormatSymbols_af', 'goog.labs.i18n.ListFormatSymbols_am', 'goog.labs.i18n.ListFormatSymbols_ar', 'goog.labs.i18n.ListFormatSymbols_az', 'goog.labs.i18n.ListFormatSymbols_be', 'goog.labs.i18n.ListFormatSymbols_bg', 'goog.labs.i18n.ListFormatSymbols_bn', 'goog.labs.i18n.ListFormatSymbols_br', 'goog.labs.i18n.ListFormatSymbols_bs', 'goog.labs.i18n.ListFormatSymbols_ca', 'goog.labs.i18n.ListFormatSymbols_chr', 'goog.labs.i18n.ListFormatSymbols_cs', 'goog.labs.i18n.ListFormatSymbols_cy', 'goog.labs.i18n.ListFormatSymbols_da', 'goog.labs.i18n.ListFormatSymbols_de', 'goog.labs.i18n.ListFormatSymbols_de_AT', 'goog.labs.i18n.ListFormatSymbols_de_CH', 'goog.labs.i18n.ListFormatSymbols_el', 'goog.labs.i18n.ListFormatSymbols_en', 'goog.labs.i18n.ListFormatSymbols_en_AU', 'goog.labs.i18n.ListFormatSymbols_en_CA', 'goog.labs.i18n.ListFormatSymbols_en_GB', 'goog.labs.i18n.ListFormatSymbols_en_IE', 'goog.labs.i18n.ListFormatSymbols_en_IN', 'goog.labs.i18n.ListFormatSymbols_en_SG', 'goog.labs.i18n.ListFormatSymbols_en_US', 'goog.labs.i18n.ListFormatSymbols_en_ZA', 'goog.labs.i18n.ListFormatSymbols_es', 'goog.labs.i18n.ListFormatSymbols_es_419', 'goog.labs.i18n.ListFormatSymbols_es_ES', 'goog.labs.i18n.ListFormatSymbols_es_MX', 'goog.labs.i18n.ListFormatSymbols_es_US', 'goog.labs.i18n.ListFormatSymbols_et', 'goog.labs.i18n.ListFormatSymbols_eu', 'goog.labs.i18n.ListFormatSymbols_fa', 'goog.labs.i18n.ListFormatSymbols_fi', 'goog.labs.i18n.ListFormatSymbols_fil', 'goog.labs.i18n.ListFormatSymbols_fr', 'goog.labs.i18n.ListFormatSymbols_fr_CA', 'goog.labs.i18n.ListFormatSymbols_ga', 'goog.labs.i18n.ListFormatSymbols_gl', 'goog.labs.i18n.ListFormatSymbols_gsw', 'goog.labs.i18n.ListFormatSymbols_gu', 'goog.labs.i18n.ListFormatSymbols_haw', 'goog.labs.i18n.ListFormatSymbols_he', 'goog.labs.i18n.ListFormatSymbols_hi', 'goog.labs.i18n.ListFormatSymbols_hr', 'goog.labs.i18n.ListFormatSymbols_hu', 'goog.labs.i18n.ListFormatSymbols_hy', 'goog.labs.i18n.ListFormatSymbols_id', 'goog.labs.i18n.ListFormatSymbols_in', 'goog.labs.i18n.ListFormatSymbols_is', 'goog.labs.i18n.ListFormatSymbols_it', 'goog.labs.i18n.ListFormatSymbols_iw', 'goog.labs.i18n.ListFormatSymbols_ja', 'goog.labs.i18n.ListFormatSymbols_ka', 'goog.labs.i18n.ListFormatSymbols_kk', 'goog.labs.i18n.ListFormatSymbols_km', 'goog.labs.i18n.ListFormatSymbols_kn', 'goog.labs.i18n.ListFormatSymbols_ko', 'goog.labs.i18n.ListFormatSymbols_ky', 'goog.labs.i18n.ListFormatSymbols_ln', 'goog.labs.i18n.ListFormatSymbols_lo', 'goog.labs.i18n.ListFormatSymbols_lt', 'goog.labs.i18n.ListFormatSymbols_lv', 'goog.labs.i18n.ListFormatSymbols_mk', 'goog.labs.i18n.ListFormatSymbols_ml', 'goog.labs.i18n.ListFormatSymbols_mn', 'goog.labs.i18n.ListFormatSymbols_mo', 'goog.labs.i18n.ListFormatSymbols_mr', 'goog.labs.i18n.ListFormatSymbols_ms', 'goog.labs.i18n.ListFormatSymbols_mt', 'goog.labs.i18n.ListFormatSymbols_my', 'goog.labs.i18n.ListFormatSymbols_nb', 'goog.labs.i18n.ListFormatSymbols_ne', 'goog.labs.i18n.ListFormatSymbols_nl', 'goog.labs.i18n.ListFormatSymbols_no', 'goog.labs.i18n.ListFormatSymbols_no_NO', 'goog.labs.i18n.ListFormatSymbols_or', 'goog.labs.i18n.ListFormatSymbols_pa', 'goog.labs.i18n.ListFormatSymbols_pl', 'goog.labs.i18n.ListFormatSymbols_pt', 'goog.labs.i18n.ListFormatSymbols_pt_BR', 'goog.labs.i18n.ListFormatSymbols_pt_PT', 'goog.labs.i18n.ListFormatSymbols_ro', 'goog.labs.i18n.ListFormatSymbols_ru', 'goog.labs.i18n.ListFormatSymbols_sh', 'goog.labs.i18n.ListFormatSymbols_si', 'goog.labs.i18n.ListFormatSymbols_sk', 'goog.labs.i18n.ListFormatSymbols_sl', 'goog.labs.i18n.ListFormatSymbols_sq', 'goog.labs.i18n.ListFormatSymbols_sr', 'goog.labs.i18n.ListFormatSymbols_sr_Latn', 'goog.labs.i18n.ListFormatSymbols_sv', 'goog.labs.i18n.ListFormatSymbols_sw', 'goog.labs.i18n.ListFormatSymbols_ta', 'goog.labs.i18n.ListFormatSymbols_te', 'goog.labs.i18n.ListFormatSymbols_th', 'goog.labs.i18n.ListFormatSymbols_tl', 'goog.labs.i18n.ListFormatSymbols_tr', 'goog.labs.i18n.ListFormatSymbols_uk', 'goog.labs.i18n.ListFormatSymbols_ur', 'goog.labs.i18n.ListFormatSymbols_uz', 'goog.labs.i18n.ListFormatSymbols_vi', 'goog.labs.i18n.ListFormatSymbols_zh', 'goog.labs.i18n.ListFormatSymbols_zh_CN', 'goog.labs.i18n.ListFormatSymbols_zh_HK', 'goog.labs.i18n.ListFormatSymbols_zh_TW', 'goog.labs.i18n.ListFormatSymbols_zu'], []);\ngoog.addDependency(\"labs/i18n/listsymbolsext.js\", ['goog.labs.i18n.ListFormatSymbolsExt', 'goog.labs.i18n.ListFormatSymbols_af_NA', 'goog.labs.i18n.ListFormatSymbols_af_ZA', 'goog.labs.i18n.ListFormatSymbols_agq', 'goog.labs.i18n.ListFormatSymbols_agq_CM', 'goog.labs.i18n.ListFormatSymbols_ak', 'goog.labs.i18n.ListFormatSymbols_ak_GH', 'goog.labs.i18n.ListFormatSymbols_am_ET', 'goog.labs.i18n.ListFormatSymbols_ar_001', 'goog.labs.i18n.ListFormatSymbols_ar_AE', 'goog.labs.i18n.ListFormatSymbols_ar_BH', 'goog.labs.i18n.ListFormatSymbols_ar_DJ', 'goog.labs.i18n.ListFormatSymbols_ar_DZ', 'goog.labs.i18n.ListFormatSymbols_ar_EG', 'goog.labs.i18n.ListFormatSymbols_ar_EH', 'goog.labs.i18n.ListFormatSymbols_ar_ER', 'goog.labs.i18n.ListFormatSymbols_ar_IL', 'goog.labs.i18n.ListFormatSymbols_ar_IQ', 'goog.labs.i18n.ListFormatSymbols_ar_JO', 'goog.labs.i18n.ListFormatSymbols_ar_KM', 'goog.labs.i18n.ListFormatSymbols_ar_KW', 'goog.labs.i18n.ListFormatSymbols_ar_LB', 'goog.labs.i18n.ListFormatSymbols_ar_LY', 'goog.labs.i18n.ListFormatSymbols_ar_MA', 'goog.labs.i18n.ListFormatSymbols_ar_MR', 'goog.labs.i18n.ListFormatSymbols_ar_OM', 'goog.labs.i18n.ListFormatSymbols_ar_PS', 'goog.labs.i18n.ListFormatSymbols_ar_QA', 'goog.labs.i18n.ListFormatSymbols_ar_SA', 'goog.labs.i18n.ListFormatSymbols_ar_SD', 'goog.labs.i18n.ListFormatSymbols_ar_SO', 'goog.labs.i18n.ListFormatSymbols_ar_SS', 'goog.labs.i18n.ListFormatSymbols_ar_SY', 'goog.labs.i18n.ListFormatSymbols_ar_TD', 'goog.labs.i18n.ListFormatSymbols_ar_TN', 'goog.labs.i18n.ListFormatSymbols_ar_XB', 'goog.labs.i18n.ListFormatSymbols_ar_YE', 'goog.labs.i18n.ListFormatSymbols_as', 'goog.labs.i18n.ListFormatSymbols_as_IN', 'goog.labs.i18n.ListFormatSymbols_asa', 'goog.labs.i18n.ListFormatSymbols_asa_TZ', 'goog.labs.i18n.ListFormatSymbols_az_Cyrl', 'goog.labs.i18n.ListFormatSymbols_az_Cyrl_AZ', 'goog.labs.i18n.ListFormatSymbols_az_Latn', 'goog.labs.i18n.ListFormatSymbols_az_Latn_AZ', 'goog.labs.i18n.ListFormatSymbols_bas', 'goog.labs.i18n.ListFormatSymbols_bas_CM', 'goog.labs.i18n.ListFormatSymbols_be_BY', 'goog.labs.i18n.ListFormatSymbols_bem', 'goog.labs.i18n.ListFormatSymbols_bem_ZM', 'goog.labs.i18n.ListFormatSymbols_bez', 'goog.labs.i18n.ListFormatSymbols_bez_TZ', 'goog.labs.i18n.ListFormatSymbols_bg_BG', 'goog.labs.i18n.ListFormatSymbols_bm', 'goog.labs.i18n.ListFormatSymbols_bm_ML', 'goog.labs.i18n.ListFormatSymbols_bn_BD', 'goog.labs.i18n.ListFormatSymbols_bn_IN', 'goog.labs.i18n.ListFormatSymbols_bo', 'goog.labs.i18n.ListFormatSymbols_bo_CN', 'goog.labs.i18n.ListFormatSymbols_bo_IN', 'goog.labs.i18n.ListFormatSymbols_br_FR', 'goog.labs.i18n.ListFormatSymbols_brx', 'goog.labs.i18n.ListFormatSymbols_brx_IN', 'goog.labs.i18n.ListFormatSymbols_bs_Cyrl', 'goog.labs.i18n.ListFormatSymbols_bs_Cyrl_BA', 'goog.labs.i18n.ListFormatSymbols_bs_Latn', 'goog.labs.i18n.ListFormatSymbols_bs_Latn_BA', 'goog.labs.i18n.ListFormatSymbols_ca_AD', 'goog.labs.i18n.ListFormatSymbols_ca_ES', 'goog.labs.i18n.ListFormatSymbols_ca_FR', 'goog.labs.i18n.ListFormatSymbols_ca_IT', 'goog.labs.i18n.ListFormatSymbols_ce', 'goog.labs.i18n.ListFormatSymbols_ce_RU', 'goog.labs.i18n.ListFormatSymbols_cgg', 'goog.labs.i18n.ListFormatSymbols_cgg_UG', 'goog.labs.i18n.ListFormatSymbols_chr_US', 'goog.labs.i18n.ListFormatSymbols_cs_CZ', 'goog.labs.i18n.ListFormatSymbols_cy_GB', 'goog.labs.i18n.ListFormatSymbols_da_DK', 'goog.labs.i18n.ListFormatSymbols_da_GL', 'goog.labs.i18n.ListFormatSymbols_dav', 'goog.labs.i18n.ListFormatSymbols_dav_KE', 'goog.labs.i18n.ListFormatSymbols_de_BE', 'goog.labs.i18n.ListFormatSymbols_de_DE', 'goog.labs.i18n.ListFormatSymbols_de_LI', 'goog.labs.i18n.ListFormatSymbols_de_LU', 'goog.labs.i18n.ListFormatSymbols_dje', 'goog.labs.i18n.ListFormatSymbols_dje_NE', 'goog.labs.i18n.ListFormatSymbols_dsb', 'goog.labs.i18n.ListFormatSymbols_dsb_DE', 'goog.labs.i18n.ListFormatSymbols_dua', 'goog.labs.i18n.ListFormatSymbols_dua_CM', 'goog.labs.i18n.ListFormatSymbols_dyo', 'goog.labs.i18n.ListFormatSymbols_dyo_SN', 'goog.labs.i18n.ListFormatSymbols_dz', 'goog.labs.i18n.ListFormatSymbols_dz_BT', 'goog.labs.i18n.ListFormatSymbols_ebu', 'goog.labs.i18n.ListFormatSymbols_ebu_KE', 'goog.labs.i18n.ListFormatSymbols_ee', 'goog.labs.i18n.ListFormatSymbols_ee_GH', 'goog.labs.i18n.ListFormatSymbols_ee_TG', 'goog.labs.i18n.ListFormatSymbols_el_CY', 'goog.labs.i18n.ListFormatSymbols_el_GR', 'goog.labs.i18n.ListFormatSymbols_en_001', 'goog.labs.i18n.ListFormatSymbols_en_150', 'goog.labs.i18n.ListFormatSymbols_en_AG', 'goog.labs.i18n.ListFormatSymbols_en_AI', 'goog.labs.i18n.ListFormatSymbols_en_AS', 'goog.labs.i18n.ListFormatSymbols_en_AT', 'goog.labs.i18n.ListFormatSymbols_en_BB', 'goog.labs.i18n.ListFormatSymbols_en_BE', 'goog.labs.i18n.ListFormatSymbols_en_BI', 'goog.labs.i18n.ListFormatSymbols_en_BM', 'goog.labs.i18n.ListFormatSymbols_en_BS', 'goog.labs.i18n.ListFormatSymbols_en_BW', 'goog.labs.i18n.ListFormatSymbols_en_BZ', 'goog.labs.i18n.ListFormatSymbols_en_CC', 'goog.labs.i18n.ListFormatSymbols_en_CH', 'goog.labs.i18n.ListFormatSymbols_en_CK', 'goog.labs.i18n.ListFormatSymbols_en_CM', 'goog.labs.i18n.ListFormatSymbols_en_CX', 'goog.labs.i18n.ListFormatSymbols_en_CY', 'goog.labs.i18n.ListFormatSymbols_en_DE', 'goog.labs.i18n.ListFormatSymbols_en_DG', 'goog.labs.i18n.ListFormatSymbols_en_DK', 'goog.labs.i18n.ListFormatSymbols_en_DM', 'goog.labs.i18n.ListFormatSymbols_en_ER', 'goog.labs.i18n.ListFormatSymbols_en_FI', 'goog.labs.i18n.ListFormatSymbols_en_FJ', 'goog.labs.i18n.ListFormatSymbols_en_FK', 'goog.labs.i18n.ListFormatSymbols_en_FM', 'goog.labs.i18n.ListFormatSymbols_en_GD', 'goog.labs.i18n.ListFormatSymbols_en_GG', 'goog.labs.i18n.ListFormatSymbols_en_GH', 'goog.labs.i18n.ListFormatSymbols_en_GI', 'goog.labs.i18n.ListFormatSymbols_en_GM', 'goog.labs.i18n.ListFormatSymbols_en_GU', 'goog.labs.i18n.ListFormatSymbols_en_GY', 'goog.labs.i18n.ListFormatSymbols_en_HK', 'goog.labs.i18n.ListFormatSymbols_en_IL', 'goog.labs.i18n.ListFormatSymbols_en_IM', 'goog.labs.i18n.ListFormatSymbols_en_IO', 'goog.labs.i18n.ListFormatSymbols_en_JE', 'goog.labs.i18n.ListFormatSymbols_en_JM', 'goog.labs.i18n.ListFormatSymbols_en_KE', 'goog.labs.i18n.ListFormatSymbols_en_KI', 'goog.labs.i18n.ListFormatSymbols_en_KN', 'goog.labs.i18n.ListFormatSymbols_en_KY', 'goog.labs.i18n.ListFormatSymbols_en_LC', 'goog.labs.i18n.ListFormatSymbols_en_LR', 'goog.labs.i18n.ListFormatSymbols_en_LS', 'goog.labs.i18n.ListFormatSymbols_en_MG', 'goog.labs.i18n.ListFormatSymbols_en_MH', 'goog.labs.i18n.ListFormatSymbols_en_MO', 'goog.labs.i18n.ListFormatSymbols_en_MP', 'goog.labs.i18n.ListFormatSymbols_en_MS', 'goog.labs.i18n.ListFormatSymbols_en_MT', 'goog.labs.i18n.ListFormatSymbols_en_MU', 'goog.labs.i18n.ListFormatSymbols_en_MW', 'goog.labs.i18n.ListFormatSymbols_en_MY', 'goog.labs.i18n.ListFormatSymbols_en_NA', 'goog.labs.i18n.ListFormatSymbols_en_NF', 'goog.labs.i18n.ListFormatSymbols_en_NG', 'goog.labs.i18n.ListFormatSymbols_en_NL', 'goog.labs.i18n.ListFormatSymbols_en_NR', 'goog.labs.i18n.ListFormatSymbols_en_NU', 'goog.labs.i18n.ListFormatSymbols_en_NZ', 'goog.labs.i18n.ListFormatSymbols_en_PG', 'goog.labs.i18n.ListFormatSymbols_en_PH', 'goog.labs.i18n.ListFormatSymbols_en_PK', 'goog.labs.i18n.ListFormatSymbols_en_PN', 'goog.labs.i18n.ListFormatSymbols_en_PR', 'goog.labs.i18n.ListFormatSymbols_en_PW', 'goog.labs.i18n.ListFormatSymbols_en_RW', 'goog.labs.i18n.ListFormatSymbols_en_SB', 'goog.labs.i18n.ListFormatSymbols_en_SC', 'goog.labs.i18n.ListFormatSymbols_en_SD', 'goog.labs.i18n.ListFormatSymbols_en_SE', 'goog.labs.i18n.ListFormatSymbols_en_SH', 'goog.labs.i18n.ListFormatSymbols_en_SI', 'goog.labs.i18n.ListFormatSymbols_en_SL', 'goog.labs.i18n.ListFormatSymbols_en_SS', 'goog.labs.i18n.ListFormatSymbols_en_SX', 'goog.labs.i18n.ListFormatSymbols_en_SZ', 'goog.labs.i18n.ListFormatSymbols_en_TC', 'goog.labs.i18n.ListFormatSymbols_en_TK', 'goog.labs.i18n.ListFormatSymbols_en_TO', 'goog.labs.i18n.ListFormatSymbols_en_TT', 'goog.labs.i18n.ListFormatSymbols_en_TV', 'goog.labs.i18n.ListFormatSymbols_en_TZ', 'goog.labs.i18n.ListFormatSymbols_en_UG', 'goog.labs.i18n.ListFormatSymbols_en_UM', 'goog.labs.i18n.ListFormatSymbols_en_US_POSIX', 'goog.labs.i18n.ListFormatSymbols_en_VC', 'goog.labs.i18n.ListFormatSymbols_en_VG', 'goog.labs.i18n.ListFormatSymbols_en_VI', 'goog.labs.i18n.ListFormatSymbols_en_VU', 'goog.labs.i18n.ListFormatSymbols_en_WS', 'goog.labs.i18n.ListFormatSymbols_en_XA', 'goog.labs.i18n.ListFormatSymbols_en_ZM', 'goog.labs.i18n.ListFormatSymbols_en_ZW', 'goog.labs.i18n.ListFormatSymbols_eo', 'goog.labs.i18n.ListFormatSymbols_es_AR', 'goog.labs.i18n.ListFormatSymbols_es_BO', 'goog.labs.i18n.ListFormatSymbols_es_CL', 'goog.labs.i18n.ListFormatSymbols_es_CO', 'goog.labs.i18n.ListFormatSymbols_es_CR', 'goog.labs.i18n.ListFormatSymbols_es_CU', 'goog.labs.i18n.ListFormatSymbols_es_DO', 'goog.labs.i18n.ListFormatSymbols_es_EA', 'goog.labs.i18n.ListFormatSymbols_es_EC', 'goog.labs.i18n.ListFormatSymbols_es_GQ', 'goog.labs.i18n.ListFormatSymbols_es_GT', 'goog.labs.i18n.ListFormatSymbols_es_HN', 'goog.labs.i18n.ListFormatSymbols_es_IC', 'goog.labs.i18n.ListFormatSymbols_es_NI', 'goog.labs.i18n.ListFormatSymbols_es_PA', 'goog.labs.i18n.ListFormatSymbols_es_PE', 'goog.labs.i18n.ListFormatSymbols_es_PH', 'goog.labs.i18n.ListFormatSymbols_es_PR', 'goog.labs.i18n.ListFormatSymbols_es_PY', 'goog.labs.i18n.ListFormatSymbols_es_SV', 'goog.labs.i18n.ListFormatSymbols_es_UY', 'goog.labs.i18n.ListFormatSymbols_es_VE', 'goog.labs.i18n.ListFormatSymbols_et_EE', 'goog.labs.i18n.ListFormatSymbols_eu_ES', 'goog.labs.i18n.ListFormatSymbols_ewo', 'goog.labs.i18n.ListFormatSymbols_ewo_CM', 'goog.labs.i18n.ListFormatSymbols_fa_AF', 'goog.labs.i18n.ListFormatSymbols_fa_IR', 'goog.labs.i18n.ListFormatSymbols_ff', 'goog.labs.i18n.ListFormatSymbols_ff_CM', 'goog.labs.i18n.ListFormatSymbols_ff_GN', 'goog.labs.i18n.ListFormatSymbols_ff_MR', 'goog.labs.i18n.ListFormatSymbols_ff_SN', 'goog.labs.i18n.ListFormatSymbols_fi_FI', 'goog.labs.i18n.ListFormatSymbols_fil_PH', 'goog.labs.i18n.ListFormatSymbols_fo', 'goog.labs.i18n.ListFormatSymbols_fo_DK', 'goog.labs.i18n.ListFormatSymbols_fo_FO', 'goog.labs.i18n.ListFormatSymbols_fr_BE', 'goog.labs.i18n.ListFormatSymbols_fr_BF', 'goog.labs.i18n.ListFormatSymbols_fr_BI', 'goog.labs.i18n.ListFormatSymbols_fr_BJ', 'goog.labs.i18n.ListFormatSymbols_fr_BL', 'goog.labs.i18n.ListFormatSymbols_fr_CD', 'goog.labs.i18n.ListFormatSymbols_fr_CF', 'goog.labs.i18n.ListFormatSymbols_fr_CG', 'goog.labs.i18n.ListFormatSymbols_fr_CH', 'goog.labs.i18n.ListFormatSymbols_fr_CI', 'goog.labs.i18n.ListFormatSymbols_fr_CM', 'goog.labs.i18n.ListFormatSymbols_fr_DJ', 'goog.labs.i18n.ListFormatSymbols_fr_DZ', 'goog.labs.i18n.ListFormatSymbols_fr_FR', 'goog.labs.i18n.ListFormatSymbols_fr_GA', 'goog.labs.i18n.ListFormatSymbols_fr_GF', 'goog.labs.i18n.ListFormatSymbols_fr_GN', 'goog.labs.i18n.ListFormatSymbols_fr_GP', 'goog.labs.i18n.ListFormatSymbols_fr_GQ', 'goog.labs.i18n.ListFormatSymbols_fr_HT', 'goog.labs.i18n.ListFormatSymbols_fr_KM', 'goog.labs.i18n.ListFormatSymbols_fr_LU', 'goog.labs.i18n.ListFormatSymbols_fr_MA', 'goog.labs.i18n.ListFormatSymbols_fr_MC', 'goog.labs.i18n.ListFormatSymbols_fr_MF', 'goog.labs.i18n.ListFormatSymbols_fr_MG', 'goog.labs.i18n.ListFormatSymbols_fr_ML', 'goog.labs.i18n.ListFormatSymbols_fr_MQ', 'goog.labs.i18n.ListFormatSymbols_fr_MR', 'goog.labs.i18n.ListFormatSymbols_fr_MU', 'goog.labs.i18n.ListFormatSymbols_fr_NC', 'goog.labs.i18n.ListFormatSymbols_fr_NE', 'goog.labs.i18n.ListFormatSymbols_fr_PF', 'goog.labs.i18n.ListFormatSymbols_fr_PM', 'goog.labs.i18n.ListFormatSymbols_fr_RE', 'goog.labs.i18n.ListFormatSymbols_fr_RW', 'goog.labs.i18n.ListFormatSymbols_fr_SC', 'goog.labs.i18n.ListFormatSymbols_fr_SN', 'goog.labs.i18n.ListFormatSymbols_fr_SY', 'goog.labs.i18n.ListFormatSymbols_fr_TD', 'goog.labs.i18n.ListFormatSymbols_fr_TG', 'goog.labs.i18n.ListFormatSymbols_fr_TN', 'goog.labs.i18n.ListFormatSymbols_fr_VU', 'goog.labs.i18n.ListFormatSymbols_fr_WF', 'goog.labs.i18n.ListFormatSymbols_fr_YT', 'goog.labs.i18n.ListFormatSymbols_fur', 'goog.labs.i18n.ListFormatSymbols_fur_IT', 'goog.labs.i18n.ListFormatSymbols_fy', 'goog.labs.i18n.ListFormatSymbols_fy_NL', 'goog.labs.i18n.ListFormatSymbols_ga_IE', 'goog.labs.i18n.ListFormatSymbols_gd', 'goog.labs.i18n.ListFormatSymbols_gd_GB', 'goog.labs.i18n.ListFormatSymbols_gl_ES', 'goog.labs.i18n.ListFormatSymbols_gsw_CH', 'goog.labs.i18n.ListFormatSymbols_gsw_FR', 'goog.labs.i18n.ListFormatSymbols_gsw_LI', 'goog.labs.i18n.ListFormatSymbols_gu_IN', 'goog.labs.i18n.ListFormatSymbols_guz', 'goog.labs.i18n.ListFormatSymbols_guz_KE', 'goog.labs.i18n.ListFormatSymbols_gv', 'goog.labs.i18n.ListFormatSymbols_gv_IM', 'goog.labs.i18n.ListFormatSymbols_ha', 'goog.labs.i18n.ListFormatSymbols_ha_GH', 'goog.labs.i18n.ListFormatSymbols_ha_NE', 'goog.labs.i18n.ListFormatSymbols_ha_NG', 'goog.labs.i18n.ListFormatSymbols_haw_US', 'goog.labs.i18n.ListFormatSymbols_he_IL', 'goog.labs.i18n.ListFormatSymbols_hi_IN', 'goog.labs.i18n.ListFormatSymbols_hr_BA', 'goog.labs.i18n.ListFormatSymbols_hr_HR', 'goog.labs.i18n.ListFormatSymbols_hsb', 'goog.labs.i18n.ListFormatSymbols_hsb_DE', 'goog.labs.i18n.ListFormatSymbols_hu_HU', 'goog.labs.i18n.ListFormatSymbols_hy_AM', 'goog.labs.i18n.ListFormatSymbols_id_ID', 'goog.labs.i18n.ListFormatSymbols_ig', 'goog.labs.i18n.ListFormatSymbols_ig_NG', 'goog.labs.i18n.ListFormatSymbols_ii', 'goog.labs.i18n.ListFormatSymbols_ii_CN', 'goog.labs.i18n.ListFormatSymbols_is_IS', 'goog.labs.i18n.ListFormatSymbols_it_CH', 'goog.labs.i18n.ListFormatSymbols_it_IT', 'goog.labs.i18n.ListFormatSymbols_it_SM', 'goog.labs.i18n.ListFormatSymbols_ja_JP', 'goog.labs.i18n.ListFormatSymbols_jgo', 'goog.labs.i18n.ListFormatSymbols_jgo_CM', 'goog.labs.i18n.ListFormatSymbols_jmc', 'goog.labs.i18n.ListFormatSymbols_jmc_TZ', 'goog.labs.i18n.ListFormatSymbols_ka_GE', 'goog.labs.i18n.ListFormatSymbols_kab', 'goog.labs.i18n.ListFormatSymbols_kab_DZ', 'goog.labs.i18n.ListFormatSymbols_kam', 'goog.labs.i18n.ListFormatSymbols_kam_KE', 'goog.labs.i18n.ListFormatSymbols_kde', 'goog.labs.i18n.ListFormatSymbols_kde_TZ', 'goog.labs.i18n.ListFormatSymbols_kea', 'goog.labs.i18n.ListFormatSymbols_kea_CV', 'goog.labs.i18n.ListFormatSymbols_khq', 'goog.labs.i18n.ListFormatSymbols_khq_ML', 'goog.labs.i18n.ListFormatSymbols_ki', 'goog.labs.i18n.ListFormatSymbols_ki_KE', 'goog.labs.i18n.ListFormatSymbols_kk_KZ', 'goog.labs.i18n.ListFormatSymbols_kkj', 'goog.labs.i18n.ListFormatSymbols_kkj_CM', 'goog.labs.i18n.ListFormatSymbols_kl', 'goog.labs.i18n.ListFormatSymbols_kl_GL', 'goog.labs.i18n.ListFormatSymbols_kln', 'goog.labs.i18n.ListFormatSymbols_kln_KE', 'goog.labs.i18n.ListFormatSymbols_km_KH', 'goog.labs.i18n.ListFormatSymbols_kn_IN', 'goog.labs.i18n.ListFormatSymbols_ko_KP', 'goog.labs.i18n.ListFormatSymbols_ko_KR', 'goog.labs.i18n.ListFormatSymbols_kok', 'goog.labs.i18n.ListFormatSymbols_kok_IN', 'goog.labs.i18n.ListFormatSymbols_ks', 'goog.labs.i18n.ListFormatSymbols_ks_IN', 'goog.labs.i18n.ListFormatSymbols_ksb', 'goog.labs.i18n.ListFormatSymbols_ksb_TZ', 'goog.labs.i18n.ListFormatSymbols_ksf', 'goog.labs.i18n.ListFormatSymbols_ksf_CM', 'goog.labs.i18n.ListFormatSymbols_ksh', 'goog.labs.i18n.ListFormatSymbols_ksh_DE', 'goog.labs.i18n.ListFormatSymbols_kw', 'goog.labs.i18n.ListFormatSymbols_kw_GB', 'goog.labs.i18n.ListFormatSymbols_ky_KG', 'goog.labs.i18n.ListFormatSymbols_lag', 'goog.labs.i18n.ListFormatSymbols_lag_TZ', 'goog.labs.i18n.ListFormatSymbols_lb', 'goog.labs.i18n.ListFormatSymbols_lb_LU', 'goog.labs.i18n.ListFormatSymbols_lg', 'goog.labs.i18n.ListFormatSymbols_lg_UG', 'goog.labs.i18n.ListFormatSymbols_lkt', 'goog.labs.i18n.ListFormatSymbols_lkt_US', 'goog.labs.i18n.ListFormatSymbols_ln_AO', 'goog.labs.i18n.ListFormatSymbols_ln_CD', 'goog.labs.i18n.ListFormatSymbols_ln_CF', 'goog.labs.i18n.ListFormatSymbols_ln_CG', 'goog.labs.i18n.ListFormatSymbols_lo_LA', 'goog.labs.i18n.ListFormatSymbols_lrc', 'goog.labs.i18n.ListFormatSymbols_lrc_IQ', 'goog.labs.i18n.ListFormatSymbols_lrc_IR', 'goog.labs.i18n.ListFormatSymbols_lt_LT', 'goog.labs.i18n.ListFormatSymbols_lu', 'goog.labs.i18n.ListFormatSymbols_lu_CD', 'goog.labs.i18n.ListFormatSymbols_luo', 'goog.labs.i18n.ListFormatSymbols_luo_KE', 'goog.labs.i18n.ListFormatSymbols_luy', 'goog.labs.i18n.ListFormatSymbols_luy_KE', 'goog.labs.i18n.ListFormatSymbols_lv_LV', 'goog.labs.i18n.ListFormatSymbols_mas', 'goog.labs.i18n.ListFormatSymbols_mas_KE', 'goog.labs.i18n.ListFormatSymbols_mas_TZ', 'goog.labs.i18n.ListFormatSymbols_mer', 'goog.labs.i18n.ListFormatSymbols_mer_KE', 'goog.labs.i18n.ListFormatSymbols_mfe', 'goog.labs.i18n.ListFormatSymbols_mfe_MU', 'goog.labs.i18n.ListFormatSymbols_mg', 'goog.labs.i18n.ListFormatSymbols_mg_MG', 'goog.labs.i18n.ListFormatSymbols_mgh', 'goog.labs.i18n.ListFormatSymbols_mgh_MZ', 'goog.labs.i18n.ListFormatSymbols_mgo', 'goog.labs.i18n.ListFormatSymbols_mgo_CM', 'goog.labs.i18n.ListFormatSymbols_mk_MK', 'goog.labs.i18n.ListFormatSymbols_ml_IN', 'goog.labs.i18n.ListFormatSymbols_mn_MN', 'goog.labs.i18n.ListFormatSymbols_mr_IN', 'goog.labs.i18n.ListFormatSymbols_ms_BN', 'goog.labs.i18n.ListFormatSymbols_ms_MY', 'goog.labs.i18n.ListFormatSymbols_ms_SG', 'goog.labs.i18n.ListFormatSymbols_mt_MT', 'goog.labs.i18n.ListFormatSymbols_mua', 'goog.labs.i18n.ListFormatSymbols_mua_CM', 'goog.labs.i18n.ListFormatSymbols_my_MM', 'goog.labs.i18n.ListFormatSymbols_mzn', 'goog.labs.i18n.ListFormatSymbols_mzn_IR', 'goog.labs.i18n.ListFormatSymbols_naq', 'goog.labs.i18n.ListFormatSymbols_naq_NA', 'goog.labs.i18n.ListFormatSymbols_nb_NO', 'goog.labs.i18n.ListFormatSymbols_nb_SJ', 'goog.labs.i18n.ListFormatSymbols_nd', 'goog.labs.i18n.ListFormatSymbols_nd_ZW', 'goog.labs.i18n.ListFormatSymbols_ne_IN', 'goog.labs.i18n.ListFormatSymbols_ne_NP', 'goog.labs.i18n.ListFormatSymbols_nl_AW', 'goog.labs.i18n.ListFormatSymbols_nl_BE', 'goog.labs.i18n.ListFormatSymbols_nl_BQ', 'goog.labs.i18n.ListFormatSymbols_nl_CW', 'goog.labs.i18n.ListFormatSymbols_nl_NL', 'goog.labs.i18n.ListFormatSymbols_nl_SR', 'goog.labs.i18n.ListFormatSymbols_nl_SX', 'goog.labs.i18n.ListFormatSymbols_nmg', 'goog.labs.i18n.ListFormatSymbols_nmg_CM', 'goog.labs.i18n.ListFormatSymbols_nn', 'goog.labs.i18n.ListFormatSymbols_nn_NO', 'goog.labs.i18n.ListFormatSymbols_nnh', 'goog.labs.i18n.ListFormatSymbols_nnh_CM', 'goog.labs.i18n.ListFormatSymbols_nus', 'goog.labs.i18n.ListFormatSymbols_nus_SS', 'goog.labs.i18n.ListFormatSymbols_nyn', 'goog.labs.i18n.ListFormatSymbols_nyn_UG', 'goog.labs.i18n.ListFormatSymbols_om', 'goog.labs.i18n.ListFormatSymbols_om_ET', 'goog.labs.i18n.ListFormatSymbols_om_KE', 'goog.labs.i18n.ListFormatSymbols_or_IN', 'goog.labs.i18n.ListFormatSymbols_os', 'goog.labs.i18n.ListFormatSymbols_os_GE', 'goog.labs.i18n.ListFormatSymbols_os_RU', 'goog.labs.i18n.ListFormatSymbols_pa_Arab', 'goog.labs.i18n.ListFormatSymbols_pa_Arab_PK', 'goog.labs.i18n.ListFormatSymbols_pa_Guru', 'goog.labs.i18n.ListFormatSymbols_pa_Guru_IN', 'goog.labs.i18n.ListFormatSymbols_pl_PL', 'goog.labs.i18n.ListFormatSymbols_ps', 'goog.labs.i18n.ListFormatSymbols_ps_AF', 'goog.labs.i18n.ListFormatSymbols_pt_AO', 'goog.labs.i18n.ListFormatSymbols_pt_CV', 'goog.labs.i18n.ListFormatSymbols_pt_GW', 'goog.labs.i18n.ListFormatSymbols_pt_MO', 'goog.labs.i18n.ListFormatSymbols_pt_MZ', 'goog.labs.i18n.ListFormatSymbols_pt_ST', 'goog.labs.i18n.ListFormatSymbols_pt_TL', 'goog.labs.i18n.ListFormatSymbols_qu', 'goog.labs.i18n.ListFormatSymbols_qu_BO', 'goog.labs.i18n.ListFormatSymbols_qu_EC', 'goog.labs.i18n.ListFormatSymbols_qu_PE', 'goog.labs.i18n.ListFormatSymbols_rm', 'goog.labs.i18n.ListFormatSymbols_rm_CH', 'goog.labs.i18n.ListFormatSymbols_rn', 'goog.labs.i18n.ListFormatSymbols_rn_BI', 'goog.labs.i18n.ListFormatSymbols_ro_MD', 'goog.labs.i18n.ListFormatSymbols_ro_RO', 'goog.labs.i18n.ListFormatSymbols_rof', 'goog.labs.i18n.ListFormatSymbols_rof_TZ', 'goog.labs.i18n.ListFormatSymbols_ru_BY', 'goog.labs.i18n.ListFormatSymbols_ru_KG', 'goog.labs.i18n.ListFormatSymbols_ru_KZ', 'goog.labs.i18n.ListFormatSymbols_ru_MD', 'goog.labs.i18n.ListFormatSymbols_ru_RU', 'goog.labs.i18n.ListFormatSymbols_ru_UA', 'goog.labs.i18n.ListFormatSymbols_rw', 'goog.labs.i18n.ListFormatSymbols_rw_RW', 'goog.labs.i18n.ListFormatSymbols_rwk', 'goog.labs.i18n.ListFormatSymbols_rwk_TZ', 'goog.labs.i18n.ListFormatSymbols_sah', 'goog.labs.i18n.ListFormatSymbols_sah_RU', 'goog.labs.i18n.ListFormatSymbols_saq', 'goog.labs.i18n.ListFormatSymbols_saq_KE', 'goog.labs.i18n.ListFormatSymbols_sbp', 'goog.labs.i18n.ListFormatSymbols_sbp_TZ', 'goog.labs.i18n.ListFormatSymbols_se', 'goog.labs.i18n.ListFormatSymbols_se_FI', 'goog.labs.i18n.ListFormatSymbols_se_NO', 'goog.labs.i18n.ListFormatSymbols_se_SE', 'goog.labs.i18n.ListFormatSymbols_seh', 'goog.labs.i18n.ListFormatSymbols_seh_MZ', 'goog.labs.i18n.ListFormatSymbols_ses', 'goog.labs.i18n.ListFormatSymbols_ses_ML', 'goog.labs.i18n.ListFormatSymbols_sg', 'goog.labs.i18n.ListFormatSymbols_sg_CF', 'goog.labs.i18n.ListFormatSymbols_shi', 'goog.labs.i18n.ListFormatSymbols_shi_Latn', 'goog.labs.i18n.ListFormatSymbols_shi_Latn_MA', 'goog.labs.i18n.ListFormatSymbols_shi_Tfng', 'goog.labs.i18n.ListFormatSymbols_shi_Tfng_MA', 'goog.labs.i18n.ListFormatSymbols_si_LK', 'goog.labs.i18n.ListFormatSymbols_sk_SK', 'goog.labs.i18n.ListFormatSymbols_sl_SI', 'goog.labs.i18n.ListFormatSymbols_smn', 'goog.labs.i18n.ListFormatSymbols_smn_FI', 'goog.labs.i18n.ListFormatSymbols_sn', 'goog.labs.i18n.ListFormatSymbols_sn_ZW', 'goog.labs.i18n.ListFormatSymbols_so', 'goog.labs.i18n.ListFormatSymbols_so_DJ', 'goog.labs.i18n.ListFormatSymbols_so_ET', 'goog.labs.i18n.ListFormatSymbols_so_KE', 'goog.labs.i18n.ListFormatSymbols_so_SO', 'goog.labs.i18n.ListFormatSymbols_sq_AL', 'goog.labs.i18n.ListFormatSymbols_sq_MK', 'goog.labs.i18n.ListFormatSymbols_sq_XK', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_BA', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_ME', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_RS', 'goog.labs.i18n.ListFormatSymbols_sr_Cyrl_XK', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_BA', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_ME', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_RS', 'goog.labs.i18n.ListFormatSymbols_sr_Latn_XK', 'goog.labs.i18n.ListFormatSymbols_sv_AX', 'goog.labs.i18n.ListFormatSymbols_sv_FI', 'goog.labs.i18n.ListFormatSymbols_sv_SE', 'goog.labs.i18n.ListFormatSymbols_sw_CD', 'goog.labs.i18n.ListFormatSymbols_sw_KE', 'goog.labs.i18n.ListFormatSymbols_sw_TZ', 'goog.labs.i18n.ListFormatSymbols_sw_UG', 'goog.labs.i18n.ListFormatSymbols_ta_IN', 'goog.labs.i18n.ListFormatSymbols_ta_LK', 'goog.labs.i18n.ListFormatSymbols_ta_MY', 'goog.labs.i18n.ListFormatSymbols_ta_SG', 'goog.labs.i18n.ListFormatSymbols_te_IN', 'goog.labs.i18n.ListFormatSymbols_teo', 'goog.labs.i18n.ListFormatSymbols_teo_KE', 'goog.labs.i18n.ListFormatSymbols_teo_UG', 'goog.labs.i18n.ListFormatSymbols_th_TH', 'goog.labs.i18n.ListFormatSymbols_ti', 'goog.labs.i18n.ListFormatSymbols_ti_ER', 'goog.labs.i18n.ListFormatSymbols_ti_ET', 'goog.labs.i18n.ListFormatSymbols_to', 'goog.labs.i18n.ListFormatSymbols_to_TO', 'goog.labs.i18n.ListFormatSymbols_tr_CY', 'goog.labs.i18n.ListFormatSymbols_tr_TR', 'goog.labs.i18n.ListFormatSymbols_twq', 'goog.labs.i18n.ListFormatSymbols_twq_NE', 'goog.labs.i18n.ListFormatSymbols_tzm', 'goog.labs.i18n.ListFormatSymbols_tzm_MA', 'goog.labs.i18n.ListFormatSymbols_ug', 'goog.labs.i18n.ListFormatSymbols_ug_CN', 'goog.labs.i18n.ListFormatSymbols_uk_UA', 'goog.labs.i18n.ListFormatSymbols_ur_IN', 'goog.labs.i18n.ListFormatSymbols_ur_PK', 'goog.labs.i18n.ListFormatSymbols_uz_Arab', 'goog.labs.i18n.ListFormatSymbols_uz_Arab_AF', 'goog.labs.i18n.ListFormatSymbols_uz_Cyrl', 'goog.labs.i18n.ListFormatSymbols_uz_Cyrl_UZ', 'goog.labs.i18n.ListFormatSymbols_uz_Latn', 'goog.labs.i18n.ListFormatSymbols_uz_Latn_UZ', 'goog.labs.i18n.ListFormatSymbols_vai', 'goog.labs.i18n.ListFormatSymbols_vai_Latn', 'goog.labs.i18n.ListFormatSymbols_vai_Latn_LR', 'goog.labs.i18n.ListFormatSymbols_vai_Vaii', 'goog.labs.i18n.ListFormatSymbols_vai_Vaii_LR', 'goog.labs.i18n.ListFormatSymbols_vi_VN', 'goog.labs.i18n.ListFormatSymbols_vun', 'goog.labs.i18n.ListFormatSymbols_vun_TZ', 'goog.labs.i18n.ListFormatSymbols_wae', 'goog.labs.i18n.ListFormatSymbols_wae_CH', 'goog.labs.i18n.ListFormatSymbols_xog', 'goog.labs.i18n.ListFormatSymbols_xog_UG', 'goog.labs.i18n.ListFormatSymbols_yav', 'goog.labs.i18n.ListFormatSymbols_yav_CM', 'goog.labs.i18n.ListFormatSymbols_yi', 'goog.labs.i18n.ListFormatSymbols_yi_001', 'goog.labs.i18n.ListFormatSymbols_yo', 'goog.labs.i18n.ListFormatSymbols_yo_BJ', 'goog.labs.i18n.ListFormatSymbols_yo_NG', 'goog.labs.i18n.ListFormatSymbols_zgh', 'goog.labs.i18n.ListFormatSymbols_zgh_MA', 'goog.labs.i18n.ListFormatSymbols_zh_Hans', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_CN', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_HK', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_MO', 'goog.labs.i18n.ListFormatSymbols_zh_Hans_SG', 'goog.labs.i18n.ListFormatSymbols_zh_Hant', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_HK', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_MO', 'goog.labs.i18n.ListFormatSymbols_zh_Hant_TW', 'goog.labs.i18n.ListFormatSymbols_zu_ZA'], ['goog.labs.i18n.ListFormatSymbols']);\ngoog.addDependency(\"labs/iterable/iterable.js\", [], []);\ngoog.addDependency(\"labs/iterable/iterable_test.js\", [], ['goog.testing.jsunit']);\ngoog.addDependency(\"labs/mock/mock.js\", ['goog.labs.mock', 'goog.labs.mock.VerificationError'], ['goog.array', 'goog.asserts', 'goog.debug', 'goog.debug.Error', 'goog.functions', 'goog.object']);\ngoog.addDependency(\"labs/mock/mock_test.js\", ['goog.labs.mockTest'], ['goog.array', 'goog.labs.mock', 'goog.labs.mock.VerificationError', 'goog.labs.testing.AnythingMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.string', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/net/image.js\", ['goog.labs.net.image'], ['goog.Promise', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.net.EventType', 'goog.userAgent']);\ngoog.addDependency(\"labs/net/image_test.js\", ['goog.labs.net.imageTest'], ['goog.labs.net.image', 'goog.string', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"labs/net/webchannel.js\", ['goog.net.WebChannel'], ['goog.events', 'goog.events.Event']);\ngoog.addDependency(\"labs/net/webchanneltransport.js\", ['goog.net.WebChannelTransport'], []);\ngoog.addDependency(\"labs/net/webchanneltransportfactory.js\", ['goog.net.createWebChannelTransport'], ['goog.functions', 'goog.labs.net.webChannel.WebChannelBaseTransport']);\ngoog.addDependency(\"labs/net/xhr.js\", ['goog.labs.net.xhr', 'goog.labs.net.xhr.Error', 'goog.labs.net.xhr.HttpError', 'goog.labs.net.xhr.Options', 'goog.labs.net.xhr.PostData', 'goog.labs.net.xhr.ResponseType', 'goog.labs.net.xhr.TimeoutError'], ['goog.Promise', 'goog.asserts', 'goog.debug.Error', 'goog.json', 'goog.net.HttpStatus', 'goog.net.XmlHttp', 'goog.string', 'goog.uri.utils', 'goog.userAgent']);\ngoog.addDependency(\"labs/net/xhr_test.js\", ['goog.labs.net.xhrTest'], ['goog.Promise', 'goog.events', 'goog.events.EventType', 'goog.labs.net.xhr', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XmlHttp', 'goog.testing.MockClock', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"labs/net/webchannel/basetestchannel.js\", ['goog.labs.net.webChannel.BaseTestChannel'], ['goog.labs.net.webChannel.Channel', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat']);\ngoog.addDependency(\"labs/net/webchannel/channel.js\", ['goog.labs.net.webChannel.Channel'], []);\ngoog.addDependency(\"labs/net/webchannel/channelrequest.js\", ['goog.labs.net.webChannel.ChannelRequest'], ['goog.Timer', 'goog.async.Throttle', 'goog.events.EventHandler', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.userAgent']);\ngoog.addDependency(\"labs/net/webchannel/channelrequest_test.js\", ['goog.labs.net.webChannel.channelRequestTest'], ['goog.Uri', 'goog.functions', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction']);\ngoog.addDependency(\"labs/net/webchannel/connectionstate.js\", ['goog.labs.net.webChannel.ConnectionState'], []);\ngoog.addDependency(\"labs/net/webchannel/forwardchannelrequestpool.js\", ['goog.labs.net.webChannel.ForwardChannelRequestPool'], ['goog.array', 'goog.string', 'goog.structs.Set']);\ngoog.addDependency(\"labs/net/webchannel/forwardchannelrequestpool_test.js\", ['goog.labs.net.webChannel.forwardChannelRequestPoolTest'], ['goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/net/webchannel/netutils.js\", ['goog.labs.net.webChannel.netUtils'], ['goog.Uri', 'goog.labs.net.webChannel.WebChannelDebug']);\ngoog.addDependency(\"labs/net/webchannel/requeststats.js\", ['goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Event', 'goog.labs.net.webChannel.requestStats.ServerReachability', 'goog.labs.net.webChannel.requestStats.ServerReachabilityEvent', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.labs.net.webChannel.requestStats.StatEvent', 'goog.labs.net.webChannel.requestStats.TimingEvent'], ['goog.events.Event', 'goog.events.EventTarget']);\ngoog.addDependency(\"labs/net/webchannel/webchannelbase.js\", ['goog.labs.net.webChannel.WebChannelBase'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.debug.TextFormatter', 'goog.json', 'goog.labs.net.webChannel.BaseTestChannel', 'goog.labs.net.webChannel.Channel', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ConnectionState', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.Wire', 'goog.labs.net.webChannel.WireV8', 'goog.labs.net.webChannel.netUtils', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.log', 'goog.net.XhrIo', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.CircularBuffer']);\ngoog.addDependency(\"labs/net/webchannel/webchannelbase_test.js\", ['goog.labs.net.webChannel.webChannelBaseTest'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.functions', 'goog.json', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.ForwardChannelRequestPool', 'goog.labs.net.webChannel.WebChannelBase', 'goog.labs.net.webChannel.WebChannelBaseTransport', 'goog.labs.net.webChannel.WebChannelDebug', 'goog.labs.net.webChannel.Wire', 'goog.labs.net.webChannel.netUtils', 'goog.labs.net.webChannel.requestStats', 'goog.labs.net.webChannel.requestStats.Stat', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/net/webchannel/webchannelbasetransport.js\", ['goog.labs.net.webChannel.WebChannelBaseTransport'], ['goog.asserts', 'goog.events.EventTarget', 'goog.json', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelBase', 'goog.log', 'goog.net.WebChannel', 'goog.net.WebChannelTransport', 'goog.object', 'goog.string.path']);\ngoog.addDependency(\"labs/net/webchannel/webchannelbasetransport_test.js\", ['goog.labs.net.webChannel.webChannelBaseTransportTest'], ['goog.events', 'goog.functions', 'goog.json', 'goog.labs.net.webChannel.ChannelRequest', 'goog.labs.net.webChannel.WebChannelBase', 'goog.labs.net.webChannel.WebChannelBaseTransport', 'goog.net.WebChannel', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/net/webchannel/webchanneldebug.js\", ['goog.labs.net.webChannel.WebChannelDebug'], ['goog.json', 'goog.log']);\ngoog.addDependency(\"labs/net/webchannel/wire.js\", ['goog.labs.net.webChannel.Wire'], []);\ngoog.addDependency(\"labs/net/webchannel/wirev8.js\", ['goog.labs.net.webChannel.WireV8'], ['goog.asserts', 'goog.json', 'goog.json.NativeJsonProcessor', 'goog.structs']);\ngoog.addDependency(\"labs/net/webchannel/wirev8_test.js\", ['goog.labs.net.webChannel.WireV8Test'], ['goog.labs.net.webChannel.WireV8', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/object/object.js\", ['goog.labs.object'], []);\ngoog.addDependency(\"labs/object/object_test.js\", ['goog.labs.objectTest'], ['goog.labs.object', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/promise/promise.js\", [], []);\ngoog.addDependency(\"labs/promise/promise_test.js\", [], ['goog.testing.jsunit']);\ngoog.addDependency(\"labs/pubsub/broadcastpubsub.js\", ['goog.labs.pubsub.BroadcastPubSub'], ['goog.Disposable', 'goog.Timer', 'goog.array', 'goog.async.run', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.math', 'goog.pubsub.PubSub', 'goog.storage.Storage', 'goog.storage.mechanism.HTML5LocalStorage', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"labs/pubsub/broadcastpubsub_test.js\", ['goog.labs.pubsub.BroadcastPubSubTest'], ['goog.array', 'goog.debug.Logger', 'goog.json', 'goog.labs.pubsub.BroadcastPubSub', 'goog.storage.Storage', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"labs/storage/boundedcollectablestorage.js\", ['goog.labs.storage.BoundedCollectableStorage'], ['goog.array', 'goog.asserts', 'goog.iter', 'goog.storage.CollectableStorage', 'goog.storage.ErrorCode', 'goog.storage.ExpiringStorage']);\ngoog.addDependency(\"labs/storage/boundedcollectablestorage_test.js\", ['goog.labs.storage.BoundedCollectableStorageTest'], ['goog.labs.storage.BoundedCollectableStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism']);\ngoog.addDependency(\"labs/structs/map.js\", ['goog.labs.structs.Map'], ['goog.array', 'goog.asserts', 'goog.labs.object', 'goog.object']);\ngoog.addDependency(\"labs/structs/map_perf.js\", ['goog.labs.structs.MapPerf'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.labs.structs.Map', 'goog.structs.Map', 'goog.testing.PerformanceTable', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/structs/map_test.js\", ['goog.labs.structs.MapTest'], ['goog.labs.structs.Map', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/structs/multimap.js\", ['goog.labs.structs.Multimap'], ['goog.array', 'goog.labs.object', 'goog.labs.structs.Map']);\ngoog.addDependency(\"labs/structs/multimap_test.js\", ['goog.labs.structs.MultimapTest'], ['goog.labs.structs.Map', 'goog.labs.structs.Multimap', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/style/pixeldensitymonitor.js\", ['goog.labs.style.PixelDensityMonitor', 'goog.labs.style.PixelDensityMonitor.Density', 'goog.labs.style.PixelDensityMonitor.EventType'], ['goog.events', 'goog.events.EventTarget']);\ngoog.addDependency(\"labs/style/pixeldensitymonitor_test.js\", ['goog.labs.style.PixelDensityMonitorTest'], ['goog.array', 'goog.dom.DomHelper', 'goog.events', 'goog.labs.style.PixelDensityMonitor', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"labs/testing/assertthat.js\", ['goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat'], ['goog.debug.Error']);\ngoog.addDependency(\"labs/testing/assertthat_test.js\", ['goog.labs.testing.assertThatTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"labs/testing/decoratormatcher.js\", ['goog.labs.testing.AnythingMatcher'], ['goog.labs.testing.Matcher']);\ngoog.addDependency(\"labs/testing/decoratormatcher_test.js\", ['goog.labs.testing.decoratorMatcherTest'], ['goog.labs.testing.AnythingMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/testing/dictionarymatcher.js\", ['goog.labs.testing.HasEntriesMatcher', 'goog.labs.testing.HasEntryMatcher', 'goog.labs.testing.HasKeyMatcher', 'goog.labs.testing.HasValueMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher', 'goog.object']);\ngoog.addDependency(\"labs/testing/dictionarymatcher_test.js\", ['goog.labs.testing.dictionaryMatcherTest'], ['goog.labs.testing.HasEntryMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/testing/environment.js\", ['goog.labs.testing.Environment'], ['goog.array', 'goog.asserts', 'goog.debug.Console', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/testing/environment_test.js\", ['goog.labs.testing.environmentTest'], ['goog.labs.testing.Environment', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.testSuite']);\ngoog.addDependency(\"labs/testing/environment_usage_test.js\", ['goog.labs.testing.environmentUsageTest'], ['goog.labs.testing.Environment']);\ngoog.addDependency(\"labs/testing/json_fuzzing.js\", ['goog.labs.testing.JsonFuzzing'], ['goog.string', 'goog.testing.PseudoRandom']);\ngoog.addDependency(\"labs/testing/json_fuzzing_test.js\", ['goog.labs.testing.JsonFuzzingTest'], ['goog.json', 'goog.labs.testing.JsonFuzzing', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/testing/logicmatcher.js\", ['goog.labs.testing.AllOfMatcher', 'goog.labs.testing.AnyOfMatcher', 'goog.labs.testing.IsNotMatcher'], ['goog.array', 'goog.labs.testing.Matcher']);\ngoog.addDependency(\"labs/testing/logicmatcher_test.js\", ['goog.labs.testing.logicMatcherTest'], ['goog.labs.testing.AllOfMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/testing/matcher.js\", ['goog.labs.testing.Matcher'], []);\ngoog.addDependency(\"labs/testing/numbermatcher.js\", ['goog.labs.testing.CloseToMatcher', 'goog.labs.testing.EqualToMatcher', 'goog.labs.testing.GreaterThanEqualToMatcher', 'goog.labs.testing.GreaterThanMatcher', 'goog.labs.testing.LessThanEqualToMatcher', 'goog.labs.testing.LessThanMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher']);\ngoog.addDependency(\"labs/testing/numbermatcher_test.js\", ['goog.labs.testing.numberMatcherTest'], ['goog.labs.testing.LessThanMatcher', 'goog.labs.testing.MatcherError', 'goog.labs.testing.assertThat', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/testing/objectmatcher.js\", ['goog.labs.testing.HasPropertyMatcher', 'goog.labs.testing.InstanceOfMatcher', 'goog.labs.testing.IsNullMatcher', 'goog.labs.testing.IsNullOrUndefinedMatcher', 'goog.labs.testing.IsUndefinedMatcher', 'goog.labs.testing.ObjectEqualsMatcher'], ['goog.labs.testing.Matcher']);\ngoog.addDependency(\"labs/testing/objectmatcher_test.js\", ['goog.labs.testing.objectMatcherTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.ObjectEqualsMatcher', 'goog.labs.testing.assertThat', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/testing/stringmatcher.js\", ['goog.labs.testing.ContainsStringMatcher', 'goog.labs.testing.EndsWithMatcher', 'goog.labs.testing.EqualToIgnoringWhitespaceMatcher', 'goog.labs.testing.EqualsMatcher', 'goog.labs.testing.RegexMatcher', 'goog.labs.testing.StartsWithMatcher', 'goog.labs.testing.StringContainsInOrderMatcher'], ['goog.asserts', 'goog.labs.testing.Matcher', 'goog.string']);\ngoog.addDependency(\"labs/testing/stringmatcher_test.js\", ['goog.labs.testing.stringMatcherTest'], ['goog.labs.testing.MatcherError', 'goog.labs.testing.StringContainsInOrderMatcher', 'goog.labs.testing.assertThat', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/useragent/browser.js\", ['goog.labs.userAgent.browser'], ['goog.array', 'goog.labs.userAgent.util', 'goog.object', 'goog.string']);\ngoog.addDependency(\"labs/useragent/browser_test.js\", ['goog.labs.userAgent.browserTest'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.object', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/useragent/device.js\", ['goog.labs.userAgent.device'], ['goog.labs.userAgent.util']);\ngoog.addDependency(\"labs/useragent/device_test.js\", ['goog.labs.userAgent.deviceTest'], ['goog.labs.userAgent.device', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/useragent/engine.js\", ['goog.labs.userAgent.engine'], ['goog.array', 'goog.labs.userAgent.util', 'goog.string']);\ngoog.addDependency(\"labs/useragent/engine_test.js\", ['goog.labs.userAgent.engineTest'], ['goog.labs.userAgent.engine', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/useragent/platform.js\", ['goog.labs.userAgent.platform'], ['goog.labs.userAgent.util', 'goog.string']);\ngoog.addDependency(\"labs/useragent/platform_test.js\", ['goog.labs.userAgent.platformTest'], ['goog.labs.userAgent.platform', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.jsunit']);\ngoog.addDependency(\"labs/useragent/test_agents.js\", ['goog.labs.userAgent.testAgents'], []);\ngoog.addDependency(\"labs/useragent/util.js\", ['goog.labs.userAgent.util'], ['goog.string']);\ngoog.addDependency(\"labs/useragent/util_test.js\", ['goog.labs.userAgent.utilTest'], ['goog.functions', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"locale/countries.js\", ['goog.locale.countries'], []);\ngoog.addDependency(\"locale/countrylanguagenames_test.js\", ['goog.locale.countryLanguageNamesTest'], ['goog.locale', 'goog.testing.jsunit']);\ngoog.addDependency(\"locale/defaultlocalenameconstants.js\", ['goog.locale.defaultLocaleNameConstants'], []);\ngoog.addDependency(\"locale/genericfontnames.js\", ['goog.locale.genericFontNames'], []);\ngoog.addDependency(\"locale/genericfontnames_test.js\", ['goog.locale.genericFontNamesTest'], ['goog.locale.genericFontNames', 'goog.testing.jsunit']);\ngoog.addDependency(\"locale/genericfontnamesdata.js\", ['goog.locale.genericFontNamesData'], []);\ngoog.addDependency(\"locale/locale.js\", ['goog.locale'], ['goog.locale.nativeNameConstants']);\ngoog.addDependency(\"locale/nativenameconstants.js\", ['goog.locale.nativeNameConstants'], []);\ngoog.addDependency(\"locale/scriptToLanguages.js\", ['goog.locale.scriptToLanguages'], ['goog.locale']);\ngoog.addDependency(\"locale/timezonedetection.js\", ['goog.locale.timeZoneDetection'], ['goog.locale.TimeZoneFingerprint']);\ngoog.addDependency(\"locale/timezonedetection_test.js\", ['goog.locale.timeZoneDetectionTest'], ['goog.locale.timeZoneDetection', 'goog.testing.jsunit']);\ngoog.addDependency(\"locale/timezonefingerprint.js\", ['goog.locale.TimeZoneFingerprint'], []);\ngoog.addDependency(\"locale/timezonelist.js\", ['goog.locale.TimeZoneList'], ['goog.locale']);\ngoog.addDependency(\"locale/timezonelist_test.js\", ['goog.locale.TimeZoneListTest'], ['goog.locale', 'goog.locale.TimeZoneList', 'goog.testing.jsunit']);\ngoog.addDependency(\"log/log.js\", ['goog.log', 'goog.log.Level', 'goog.log.LogRecord', 'goog.log.Logger'], ['goog.debug', 'goog.debug.LogManager', 'goog.debug.LogRecord', 'goog.debug.Logger']);\ngoog.addDependency(\"log/log_test.js\", ['goog.logTest'], ['goog.debug.LogManager', 'goog.log', 'goog.log.Level', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/affinetransform.js\", ['goog.math.AffineTransform'], ['goog.math']);\ngoog.addDependency(\"math/affinetransform_test.js\", ['goog.math.AffineTransformTest'], ['goog.array', 'goog.math', 'goog.math.AffineTransform', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/bezier.js\", ['goog.math.Bezier'], ['goog.math', 'goog.math.Coordinate']);\ngoog.addDependency(\"math/bezier_test.js\", ['goog.math.BezierTest'], ['goog.math', 'goog.math.Bezier', 'goog.math.Coordinate', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/box.js\", ['goog.math.Box'], ['goog.asserts', 'goog.math.Coordinate']);\ngoog.addDependency(\"math/box_test.js\", ['goog.math.BoxTest'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/coordinate.js\", ['goog.math.Coordinate'], ['goog.math']);\ngoog.addDependency(\"math/coordinate3.js\", ['goog.math.Coordinate3'], []);\ngoog.addDependency(\"math/coordinate3_test.js\", ['goog.math.Coordinate3Test'], ['goog.math.Coordinate3', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/coordinate_test.js\", ['goog.math.CoordinateTest'], ['goog.math.Coordinate', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/exponentialbackoff.js\", ['goog.math.ExponentialBackoff'], ['goog.asserts']);\ngoog.addDependency(\"math/exponentialbackoff_test.js\", ['goog.math.ExponentialBackoffTest'], ['goog.math.ExponentialBackoff', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/integer.js\", ['goog.math.Integer'], []);\ngoog.addDependency(\"math/integer_test.js\", ['goog.math.IntegerTest'], ['goog.math.Integer', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/line.js\", ['goog.math.Line'], ['goog.math', 'goog.math.Coordinate']);\ngoog.addDependency(\"math/line_test.js\", ['goog.math.LineTest'], ['goog.math.Coordinate', 'goog.math.Line', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/long.js\", ['goog.math.Long'], []);\ngoog.addDependency(\"math/long_test.js\", ['goog.math.LongTest'], ['goog.math.Long', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/math.js\", ['goog.math'], ['goog.array', 'goog.asserts']);\ngoog.addDependency(\"math/math_test.js\", ['goog.mathTest'], ['goog.math', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/matrix.js\", ['goog.math.Matrix'], ['goog.array', 'goog.asserts', 'goog.math', 'goog.math.Size', 'goog.string']);\ngoog.addDependency(\"math/matrix_test.js\", ['goog.math.MatrixTest'], ['goog.math.Matrix', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/path.js\", ['goog.math.Path', 'goog.math.Path.Segment'], ['goog.array', 'goog.math']);\ngoog.addDependency(\"math/path_test.js\", ['goog.math.PathTest'], ['goog.array', 'goog.math.AffineTransform', 'goog.math.Path', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/paths.js\", ['goog.math.paths'], ['goog.math.Coordinate', 'goog.math.Path']);\ngoog.addDependency(\"math/paths_test.js\", ['goog.math.pathsTest'], ['goog.math.Coordinate', 'goog.math.paths', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/range.js\", ['goog.math.Range'], ['goog.asserts']);\ngoog.addDependency(\"math/range_test.js\", ['goog.math.RangeTest'], ['goog.math.Range', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/rangeset.js\", ['goog.math.RangeSet'], ['goog.array', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.math.Range']);\ngoog.addDependency(\"math/rangeset_test.js\", ['goog.math.RangeSetTest'], ['goog.iter', 'goog.math.Range', 'goog.math.RangeSet', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/rect.js\", ['goog.math.Rect'], ['goog.asserts', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size']);\ngoog.addDependency(\"math/rect_test.js\", ['goog.math.RectTest'], ['goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/size.js\", ['goog.math.Size'], []);\ngoog.addDependency(\"math/size_test.js\", ['goog.math.SizeTest'], ['goog.math.Size', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/tdma.js\", ['goog.math.tdma'], []);\ngoog.addDependency(\"math/tdma_test.js\", ['goog.math.tdmaTest'], ['goog.math.tdma', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/vec2.js\", ['goog.math.Vec2'], ['goog.math', 'goog.math.Coordinate']);\ngoog.addDependency(\"math/vec2_test.js\", ['goog.math.Vec2Test'], ['goog.math.Vec2', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/vec3.js\", ['goog.math.Vec3'], ['goog.math', 'goog.math.Coordinate3']);\ngoog.addDependency(\"math/vec3_test.js\", ['goog.math.Vec3Test'], ['goog.math.Coordinate3', 'goog.math.Vec3', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/interpolator/interpolator1.js\", ['goog.math.interpolator.Interpolator1'], []);\ngoog.addDependency(\"math/interpolator/linear1.js\", ['goog.math.interpolator.Linear1'], ['goog.array', 'goog.asserts', 'goog.math', 'goog.math.interpolator.Interpolator1']);\ngoog.addDependency(\"math/interpolator/linear1_test.js\", ['goog.math.interpolator.Linear1Test'], ['goog.math.interpolator.Linear1', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/interpolator/pchip1.js\", ['goog.math.interpolator.Pchip1'], ['goog.math', 'goog.math.interpolator.Spline1']);\ngoog.addDependency(\"math/interpolator/pchip1_test.js\", ['goog.math.interpolator.Pchip1Test'], ['goog.math.interpolator.Pchip1', 'goog.testing.jsunit']);\ngoog.addDependency(\"math/interpolator/spline1.js\", ['goog.math.interpolator.Spline1'], ['goog.array', 'goog.asserts', 'goog.math', 'goog.math.interpolator.Interpolator1', 'goog.math.tdma']);\ngoog.addDependency(\"math/interpolator/spline1_test.js\", ['goog.math.interpolator.Spline1Test'], ['goog.math.interpolator.Spline1', 'goog.testing.jsunit']);\ngoog.addDependency(\"memoize/memoize.js\", ['goog.memoize'], []);\ngoog.addDependency(\"memoize/memoize_test.js\", ['goog.memoizeTest'], ['goog.memoize', 'goog.testing.jsunit']);\ngoog.addDependency(\"messaging/abstractchannel.js\", ['goog.messaging.AbstractChannel'], ['goog.Disposable', 'goog.json', 'goog.log', 'goog.messaging.MessageChannel']);\ngoog.addDependency(\"messaging/abstractchannel_test.js\", ['goog.messaging.AbstractChannelTest'], ['goog.messaging.AbstractChannel', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit']);\ngoog.addDependency(\"messaging/bufferedchannel.js\", ['goog.messaging.BufferedChannel'], ['goog.Disposable', 'goog.Timer', 'goog.events', 'goog.log', 'goog.messaging.MessageChannel', 'goog.messaging.MultiChannel']);\ngoog.addDependency(\"messaging/bufferedchannel_test.js\", ['goog.messaging.BufferedChannelTest'], ['goog.debug.Console', 'goog.dom', 'goog.dom.TagName', 'goog.log', 'goog.log.Level', 'goog.messaging.BufferedChannel', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel']);\ngoog.addDependency(\"messaging/deferredchannel.js\", ['goog.messaging.DeferredChannel'], ['goog.Disposable', 'goog.messaging.MessageChannel']);\ngoog.addDependency(\"messaging/deferredchannel_test.js\", ['goog.messaging.DeferredChannelTest'], ['goog.async.Deferred', 'goog.messaging.DeferredChannel', 'goog.testing.MockControl', 'goog.testing.async.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel']);\ngoog.addDependency(\"messaging/loggerclient.js\", ['goog.messaging.LoggerClient'], ['goog.Disposable', 'goog.debug', 'goog.debug.LogManager', 'goog.debug.Logger']);\ngoog.addDependency(\"messaging/loggerclient_test.js\", ['goog.messaging.LoggerClientTest'], ['goog.debug', 'goog.debug.Logger', 'goog.messaging.LoggerClient', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel']);\ngoog.addDependency(\"messaging/loggerserver.js\", ['goog.messaging.LoggerServer'], ['goog.Disposable', 'goog.log', 'goog.log.Level']);\ngoog.addDependency(\"messaging/loggerserver_test.js\", ['goog.messaging.LoggerServerTest'], ['goog.debug.LogManager', 'goog.debug.Logger', 'goog.log', 'goog.log.Level', 'goog.messaging.LoggerServer', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel']);\ngoog.addDependency(\"messaging/messagechannel.js\", ['goog.messaging.MessageChannel'], []);\ngoog.addDependency(\"messaging/messaging.js\", ['goog.messaging'], []);\ngoog.addDependency(\"messaging/messaging_test.js\", ['goog.testing.messaging.MockMessageChannelTest'], ['goog.messaging', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel']);\ngoog.addDependency(\"messaging/multichannel.js\", ['goog.messaging.MultiChannel', 'goog.messaging.MultiChannel.VirtualChannel'], ['goog.Disposable', 'goog.log', 'goog.messaging.MessageChannel', 'goog.object']);\ngoog.addDependency(\"messaging/multichannel_test.js\", ['goog.messaging.MultiChannelTest'], ['goog.messaging.MultiChannel', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel', 'goog.testing.mockmatchers.IgnoreArgument']);\ngoog.addDependency(\"messaging/portcaller.js\", ['goog.messaging.PortCaller'], ['goog.Disposable', 'goog.async.Deferred', 'goog.messaging.DeferredChannel', 'goog.messaging.PortChannel', 'goog.messaging.PortNetwork', 'goog.object']);\ngoog.addDependency(\"messaging/portcaller_test.js\", ['goog.messaging.PortCallerTest'], ['goog.events.EventTarget', 'goog.messaging.PortCaller', 'goog.messaging.PortNetwork', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel']);\ngoog.addDependency(\"messaging/portchannel.js\", ['goog.messaging.PortChannel'], ['goog.Timer', 'goog.array', 'goog.async.Deferred', 'goog.debug', 'goog.events', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.messaging.AbstractChannel', 'goog.messaging.DeferredChannel', 'goog.object', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"messaging/portchannel_test.js\", ['goog.messaging.PortChannelTest'], ['goog.Promise', 'goog.Timer', 'goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.json', 'goog.messaging.PortChannel', 'goog.testing.MockControl', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageEvent']);\ngoog.addDependency(\"messaging/portnetwork.js\", ['goog.messaging.PortNetwork'], []);\ngoog.addDependency(\"messaging/portnetwork_test.js\", ['goog.messaging.PortNetworkTest'], ['goog.Promise', 'goog.Timer', 'goog.labs.userAgent.browser', 'goog.messaging.PortChannel', 'goog.messaging.PortOperator', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"messaging/portoperator.js\", ['goog.messaging.PortOperator'], ['goog.Disposable', 'goog.asserts', 'goog.log', 'goog.messaging.PortChannel', 'goog.messaging.PortNetwork', 'goog.object']);\ngoog.addDependency(\"messaging/portoperator_test.js\", ['goog.messaging.PortOperatorTest'], ['goog.messaging.PortNetwork', 'goog.messaging.PortOperator', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel', 'goog.testing.messaging.MockMessagePort']);\ngoog.addDependency(\"messaging/respondingchannel.js\", ['goog.messaging.RespondingChannel'], ['goog.Disposable', 'goog.log', 'goog.messaging.MultiChannel']);\ngoog.addDependency(\"messaging/respondingchannel_test.js\", ['goog.messaging.RespondingChannelTest'], ['goog.messaging.RespondingChannel', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.messaging.MockMessageChannel']);\ngoog.addDependency(\"messaging/testdata/portchannel_worker.js\", ['goog.messaging.testdata.portchannel_worker'], ['goog.messaging.PortChannel']);\ngoog.addDependency(\"messaging/testdata/portnetwork_worker1.js\", ['goog.messaging.testdata.portnetwork_worker1'], ['goog.messaging.PortCaller', 'goog.messaging.PortChannel']);\ngoog.addDependency(\"messaging/testdata/portnetwork_worker2.js\", ['goog.messaging.testdata.portnetwork_worker2'], ['goog.messaging.PortCaller', 'goog.messaging.PortChannel']);\ngoog.addDependency(\"module/abstractmoduleloader.js\", ['goog.module.AbstractModuleLoader'], ['goog.module']);\ngoog.addDependency(\"module/basemodule.js\", ['goog.module.BaseModule'], ['goog.Disposable', 'goog.module']);\ngoog.addDependency(\"module/loader.js\", ['goog.module.Loader'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.module', 'goog.object']);\ngoog.addDependency(\"module/module.js\", ['goog.module'], []);\ngoog.addDependency(\"module/moduleinfo.js\", ['goog.module.ModuleInfo'], ['goog.Disposable', 'goog.async.throwException', 'goog.functions', 'goog.module', 'goog.module.BaseModule', 'goog.module.ModuleLoadCallback']);\ngoog.addDependency(\"module/moduleinfo_test.js\", ['goog.module.ModuleInfoTest'], ['goog.module.BaseModule', 'goog.module.ModuleInfo', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"module/moduleloadcallback.js\", ['goog.module.ModuleLoadCallback'], ['goog.debug.entryPointRegistry', 'goog.module']);\ngoog.addDependency(\"module/moduleloadcallback_test.js\", ['goog.module.ModuleLoadCallbackTest'], ['goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.functions', 'goog.module.ModuleLoadCallback', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"module/moduleloader.js\", ['goog.module.ModuleLoader'], ['goog.Timer', 'goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventId', 'goog.events.EventTarget', 'goog.labs.userAgent.browser', 'goog.log', 'goog.module.AbstractModuleLoader', 'goog.net.BulkLoader', 'goog.net.EventType', 'goog.net.jsloader', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"module/moduleloader_test.js\", ['goog.module.ModuleLoaderTest'], ['goog.Promise', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.functions', 'goog.module.ModuleLoader', 'goog.module.ModuleManager', 'goog.net.BulkLoader', 'goog.net.XmlHttp', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.events.EventObserver', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"module/modulemanager.js\", ['goog.module.ModuleManager', 'goog.module.ModuleManager.CallbackType', 'goog.module.ModuleManager.FailureType'], ['goog.Disposable', 'goog.array', 'goog.asserts', 'goog.async.Deferred', 'goog.debug.Trace', 'goog.dispose', 'goog.log', 'goog.module', 'goog.module.ModuleInfo', 'goog.module.ModuleLoadCallback', 'goog.object']);\ngoog.addDependency(\"module/modulemanager_test.js\", ['goog.module.ModuleManagerTest'], ['goog.array', 'goog.functions', 'goog.module.BaseModule', 'goog.module.ModuleManager', 'goog.testing', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"module/testdata/modA_1.js\", ['goog.module.testdata.modA_1'], []);\ngoog.addDependency(\"module/testdata/modA_2.js\", ['goog.module.testdata.modA_2'], ['goog.module.ModuleManager']);\ngoog.addDependency(\"module/testdata/modB_1.js\", ['goog.module.testdata.modB_1'], ['goog.module.ModuleManager']);\ngoog.addDependency(\"net/browserchannel.js\", ['goog.net.BrowserChannel', 'goog.net.BrowserChannel.Error', 'goog.net.BrowserChannel.Event', 'goog.net.BrowserChannel.Handler', 'goog.net.BrowserChannel.LogSaver', 'goog.net.BrowserChannel.QueuedMap', 'goog.net.BrowserChannel.ServerReachability', 'goog.net.BrowserChannel.ServerReachabilityEvent', 'goog.net.BrowserChannel.Stat', 'goog.net.BrowserChannel.StatEvent', 'goog.net.BrowserChannel.State', 'goog.net.BrowserChannel.TimingEvent'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.debug.TextFormatter', 'goog.events.Event', 'goog.events.EventTarget', 'goog.json', 'goog.json.EvalJsonProcessor', 'goog.log', 'goog.net.BrowserTestChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.net.XhrIo', 'goog.net.tmpnetwork', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.CircularBuffer']);\ngoog.addDependency(\"net/browserchannel_test.js\", ['goog.net.BrowserChannelTest'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.functions', 'goog.json', 'goog.net.BrowserChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.net.tmpnetwork', 'goog.structs.Map', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"net/browsertestchannel.js\", ['goog.net.BrowserTestChannel'], ['goog.json.EvalJsonProcessor', 'goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error', 'goog.net.tmpnetwork', 'goog.string.Parser']);\ngoog.addDependency(\"net/bulkloader.js\", ['goog.net.BulkLoader'], ['goog.events.EventHandler', 'goog.events.EventTarget', 'goog.log', 'goog.net.BulkLoaderHelper', 'goog.net.EventType', 'goog.net.XhrIo']);\ngoog.addDependency(\"net/bulkloader_test.js\", ['goog.net.BulkLoaderTest'], ['goog.events.Event', 'goog.events.EventHandler', 'goog.net.BulkLoader', 'goog.net.EventType', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/bulkloaderhelper.js\", ['goog.net.BulkLoaderHelper'], ['goog.Disposable']);\ngoog.addDependency(\"net/channeldebug.js\", ['goog.net.ChannelDebug'], ['goog.json', 'goog.log']);\ngoog.addDependency(\"net/channelrequest.js\", ['goog.net.ChannelRequest', 'goog.net.ChannelRequest.Error'], ['goog.Timer', 'goog.async.Throttle', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events.EventHandler', 'goog.html.SafeUrl', 'goog.html.uncheckedconversions', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.string', 'goog.string.Const', 'goog.userAgent']);\ngoog.addDependency(\"net/channelrequest_test.js\", ['goog.net.ChannelRequestTest'], ['goog.Uri', 'goog.functions', 'goog.net.BrowserChannel', 'goog.net.ChannelDebug', 'goog.net.ChannelRequest', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction']);\ngoog.addDependency(\"net/cookies.js\", ['goog.net.Cookies', 'goog.net.cookies'], []);\ngoog.addDependency(\"net/cookies_test.js\", ['goog.net.cookiesTest'], ['goog.array', 'goog.net.cookies', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/corsxmlhttpfactory.js\", ['goog.net.CorsXmlHttpFactory', 'goog.net.IeCorsXhrAdapter'], ['goog.net.HttpStatus', 'goog.net.XhrLike', 'goog.net.XmlHttp', 'goog.net.XmlHttpFactory']);\ngoog.addDependency(\"net/corsxmlhttpfactory_test.js\", ['goog.net.CorsXmlHttpFactoryTest'], ['goog.net.CorsXmlHttpFactory', 'goog.net.IeCorsXhrAdapter', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"net/crossdomainrpc.js\", ['goog.net.CrossDomainRpc'], ['goog.Uri', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.html.SafeHtml', 'goog.json', 'goog.log', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"net/crossdomainrpc_test.js\", ['goog.net.CrossDomainRpcTest'], ['goog.Promise', 'goog.log', 'goog.net.CrossDomainRpc', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"net/errorcode.js\", ['goog.net.ErrorCode'], []);\ngoog.addDependency(\"net/eventtype.js\", ['goog.net.EventType'], []);\ngoog.addDependency(\"net/fetchxmlhttpfactory.js\", ['goog.net.FetchXmlHttp', 'goog.net.FetchXmlHttpFactory'], ['goog.asserts', 'goog.events.EventTarget', 'goog.functions', 'goog.log', 'goog.net.XhrLike', 'goog.net.XmlHttpFactory']);\ngoog.addDependency(\"net/fetchxmlhttpfactory_test.js\", ['goog.net.FetchXmlHttpFactoryTest'], ['goog.net.FetchXmlHttp', 'goog.net.FetchXmlHttpFactory', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"net/filedownloader.js\", ['goog.net.FileDownloader', 'goog.net.FileDownloader.Error'], ['goog.Disposable', 'goog.asserts', 'goog.async.Deferred', 'goog.crypt.hash32', 'goog.debug.Error', 'goog.events', 'goog.events.EventHandler', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrIoPool', 'goog.object']);\ngoog.addDependency(\"net/filedownloader_test.js\", ['goog.net.FileDownloaderTest'], ['goog.fs.Error', 'goog.net.ErrorCode', 'goog.net.FileDownloader', 'goog.net.XhrIo', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.fs', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit', 'goog.testing.net.XhrIoPool']);\ngoog.addDependency(\"net/httpstatus.js\", ['goog.net.HttpStatus'], []);\ngoog.addDependency(\"net/iframeio.js\", ['goog.net.IframeIo', 'goog.net.IframeIo.IncrementalDataEvent'], ['goog.Timer', 'goog.Uri', 'goog.array', 'goog.asserts', 'goog.debug', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.html.uncheckedconversions', 'goog.json', 'goog.log', 'goog.log.Level', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.reflect', 'goog.string', 'goog.string.Const', 'goog.structs', 'goog.userAgent']);\ngoog.addDependency(\"net/iframeio_different_base_test.js\", ['goog.net.iframeIoDifferentBaseTest'], ['goog.Promise', 'goog.events', 'goog.net.EventType', 'goog.net.IframeIo', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/iframeio_test.js\", ['goog.net.IframeIoTest'], ['goog.debug', 'goog.debug.DivConsole', 'goog.debug.LogManager', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.log', 'goog.log.Level', 'goog.net.IframeIo', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"net/iframeloadmonitor.js\", ['goog.net.IframeLoadMonitor'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.userAgent']);\ngoog.addDependency(\"net/iframeloadmonitor_test.js\", [], []);\ngoog.addDependency(\"net/imageloader.js\", ['goog.net.ImageLoader'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.net.EventType', 'goog.object', 'goog.userAgent']);\ngoog.addDependency(\"net/imageloader_test.js\", ['goog.net.ImageLoaderTest'], ['goog.Promise', 'goog.Timer', 'goog.array', 'goog.dispose', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.net.EventType', 'goog.net.ImageLoader', 'goog.object', 'goog.string', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"net/ipaddress.js\", ['goog.net.IpAddress', 'goog.net.Ipv4Address', 'goog.net.Ipv6Address'], ['goog.array', 'goog.math.Integer', 'goog.object', 'goog.string']);\ngoog.addDependency(\"net/ipaddress_test.js\", ['goog.net.IpAddressTest'], ['goog.math.Integer', 'goog.net.IpAddress', 'goog.net.Ipv4Address', 'goog.net.Ipv6Address', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/jsloader.js\", ['goog.net.jsloader', 'goog.net.jsloader.Error', 'goog.net.jsloader.ErrorCode', 'goog.net.jsloader.Options'], ['goog.array', 'goog.async.Deferred', 'goog.debug.Error', 'goog.dom', 'goog.dom.TagName', 'goog.object']);\ngoog.addDependency(\"net/jsloader_test.js\", ['goog.net.jsloaderTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.net.jsloader', 'goog.net.jsloader.ErrorCode', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/jsonp.js\", ['goog.net.Jsonp'], ['goog.Uri', 'goog.net.jsloader']);\ngoog.addDependency(\"net/jsonp_test.js\", ['goog.net.JsonpTest'], ['goog.net.Jsonp', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"net/mockiframeio.js\", ['goog.net.MockIFrameIo'], ['goog.events.EventTarget', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.IframeIo']);\ngoog.addDependency(\"net/multiiframeloadmonitor.js\", ['goog.net.MultiIframeLoadMonitor'], ['goog.events', 'goog.net.IframeLoadMonitor']);\ngoog.addDependency(\"net/multiiframeloadmonitor_test.js\", [], []);\ngoog.addDependency(\"net/networkstatusmonitor.js\", ['goog.net.NetworkStatusMonitor'], ['goog.events.Listenable']);\ngoog.addDependency(\"net/networktester.js\", ['goog.net.NetworkTester'], ['goog.Timer', 'goog.Uri', 'goog.log']);\ngoog.addDependency(\"net/networktester_test.js\", ['goog.net.NetworkTesterTest'], ['goog.Uri', 'goog.net.NetworkTester', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/tmpnetwork.js\", ['goog.net.tmpnetwork'], ['goog.Uri', 'goog.net.ChannelDebug']);\ngoog.addDependency(\"net/websocket.js\", ['goog.net.WebSocket', 'goog.net.WebSocket.ErrorEvent', 'goog.net.WebSocket.EventType', 'goog.net.WebSocket.MessageEvent'], ['goog.Timer', 'goog.asserts', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.log']);\ngoog.addDependency(\"net/websocket_test.js\", ['goog.net.WebSocketTest'], ['goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.functions', 'goog.net.WebSocket', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"net/wrapperxmlhttpfactory.js\", ['goog.net.WrapperXmlHttpFactory'], ['goog.net.XhrLike', 'goog.net.XmlHttpFactory']);\ngoog.addDependency(\"net/xhrio.js\", ['goog.net.XhrIo', 'goog.net.XhrIo.ResponseType'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.debug.entryPointRegistry', 'goog.events.EventTarget', 'goog.json', 'goog.log', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XmlHttp', 'goog.object', 'goog.string', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils', 'goog.userAgent']);\ngoog.addDependency(\"net/xhrio_test.js\", ['goog.net.XhrIoTest'], ['goog.Uri', 'goog.debug.EntryPointMonitor', 'goog.debug.ErrorHandler', 'goog.debug.entryPointRegistry', 'goog.events', 'goog.functions', 'goog.net.EventType', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XhrIo', 'goog.net.XmlHttp', 'goog.object', 'goog.string', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.testing.recordFunction', 'goog.userAgent.product']);\ngoog.addDependency(\"net/xhriopool.js\", ['goog.net.XhrIoPool'], ['goog.net.XhrIo', 'goog.structs.PriorityPool']);\ngoog.addDependency(\"net/xhriopool_test.js\", ['goog.net.XhrIoPoolTest'], ['goog.net.XhrIoPool', 'goog.structs.Map', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/xhrlike.js\", ['goog.net.XhrLike'], []);\ngoog.addDependency(\"net/xhrmanager.js\", ['goog.net.XhrManager', 'goog.net.XhrManager.Event', 'goog.net.XhrManager.Request'], ['goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrIoPool', 'goog.structs.Map']);\ngoog.addDependency(\"net/xhrmanager_test.js\", ['goog.net.XhrManagerTest'], ['goog.events', 'goog.net.EventType', 'goog.net.XhrIo', 'goog.net.XhrManager', 'goog.testing.jsunit', 'goog.testing.net.XhrIoPool', 'goog.testing.recordFunction']);\ngoog.addDependency(\"net/xmlhttp.js\", ['goog.net.DefaultXmlHttpFactory', 'goog.net.XmlHttp', 'goog.net.XmlHttp.OptionType', 'goog.net.XmlHttp.ReadyState', 'goog.net.XmlHttpDefines'], ['goog.asserts', 'goog.net.WrapperXmlHttpFactory', 'goog.net.XmlHttpFactory']);\ngoog.addDependency(\"net/xmlhttpfactory.js\", ['goog.net.XmlHttpFactory'], ['goog.net.XhrLike']);\ngoog.addDependency(\"net/streams/jsonstreamparser.js\", ['goog.net.streams.JsonStreamParser'], ['goog.asserts', 'goog.json', 'goog.net.streams.StreamParser']);\ngoog.addDependency(\"net/streams/jsonstreamparser_test.js\", ['goog.net.streams.JsonStreamParserTest'], ['goog.array', 'goog.json', 'goog.labs.testing.JsonFuzzing', 'goog.net.streams.JsonStreamParser', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.uri.utils']);\ngoog.addDependency(\"net/streams/nodereadablestream.js\", ['goog.net.streams.NodeReadableStream'], []);\ngoog.addDependency(\"net/streams/pbstreamparser.js\", ['goog.net.streams.PbStreamParser'], ['goog.asserts', 'goog.net.streams.StreamParser']);\ngoog.addDependency(\"net/streams/streamfactory.js\", ['goog.net.streams.createXhrNodeReadableStream'], ['goog.asserts', 'goog.net.streams.XhrNodeReadableStream', 'goog.net.streams.XhrStreamReader']);\ngoog.addDependency(\"net/streams/streamparser.js\", ['goog.net.streams.StreamParser'], []);\ngoog.addDependency(\"net/streams/xhrnodereadablestream.js\", ['goog.net.streams.XhrNodeReadableStream'], ['goog.array', 'goog.log', 'goog.net.streams.NodeReadableStream', 'goog.net.streams.XhrStreamReader']);\ngoog.addDependency(\"net/streams/xhrnodereadablestream_test.js\", ['goog.net.streams.XhrNodeReadableStreamTest'], ['goog.net.streams.NodeReadableStream', 'goog.net.streams.XhrNodeReadableStream', 'goog.net.streams.XhrStreamReader', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/streams/xhrstreamreader.js\", ['goog.net.streams.XhrStreamReader'], ['goog.events.EventHandler', 'goog.log', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XhrIo', 'goog.net.XmlHttp', 'goog.net.streams.JsonStreamParser', 'goog.userAgent']);\ngoog.addDependency(\"net/streams/xhrstreamreader_test.js\", ['goog.net.streams.XhrStreamReaderTest'], ['goog.net.ErrorCode', 'goog.net.XmlHttp', 'goog.net.streams.XhrStreamReader', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.net.XhrIo']);\ngoog.addDependency(\"net/testdata/jsloader_test1.js\", ['goog.net.testdata.jsloader_test1'], []);\ngoog.addDependency(\"net/testdata/jsloader_test2.js\", ['goog.net.testdata.jsloader_test2'], []);\ngoog.addDependency(\"net/testdata/jsloader_test3.js\", ['goog.net.testdata.jsloader_test3'], []);\ngoog.addDependency(\"net/testdata/jsloader_test4.js\", ['goog.net.testdata.jsloader_test4'], []);\ngoog.addDependency(\"net/xpc/crosspagechannel.js\", ['goog.net.xpc.CrossPageChannel'], ['goog.Uri', 'goog.async.Deferred', 'goog.async.Delay', 'goog.dispose', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.json', 'goog.log', 'goog.messaging.AbstractChannel', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.ChannelStates', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.DirectTransport', 'goog.net.xpc.FrameElementMethodTransport', 'goog.net.xpc.IframePollingTransport', 'goog.net.xpc.IframeRelayTransport', 'goog.net.xpc.NativeMessagingTransport', 'goog.net.xpc.NixTransport', 'goog.net.xpc.TransportTypes', 'goog.net.xpc.UriCfgFields', 'goog.string', 'goog.uri.utils', 'goog.userAgent']);\ngoog.addDependency(\"net/xpc/crosspagechannel_test.js\", ['goog.net.xpc.CrossPageChannelTest'], ['goog.Disposable', 'goog.Promise', 'goog.Timer', 'goog.Uri', 'goog.dom', 'goog.dom.TagName', 'goog.labs.userAgent.browser', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.object', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/xpc/crosspagechannelrole.js\", ['goog.net.xpc.CrossPageChannelRole'], []);\ngoog.addDependency(\"net/xpc/directtransport.js\", ['goog.net.xpc.DirectTransport'], ['goog.Timer', 'goog.async.Deferred', 'goog.events.EventHandler', 'goog.log', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.object']);\ngoog.addDependency(\"net/xpc/directtransport_test.js\", ['goog.net.xpc.DirectTransportTest'], ['goog.Promise', 'goog.dom', 'goog.dom.TagName', 'goog.labs.userAgent.browser', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/xpc/frameelementmethodtransport.js\", ['goog.net.xpc.FrameElementMethodTransport'], ['goog.log', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes']);\ngoog.addDependency(\"net/xpc/iframepollingtransport.js\", ['goog.net.xpc.IframePollingTransport', 'goog.net.xpc.IframePollingTransport.Receiver', 'goog.net.xpc.IframePollingTransport.Sender'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.userAgent']);\ngoog.addDependency(\"net/xpc/iframepollingtransport_test.js\", ['goog.net.xpc.IframePollingTransportTest'], ['goog.Timer', 'goog.dom', 'goog.dom.TagName', 'goog.functions', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.TransportTypes', 'goog.object', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"net/xpc/iframerelaytransport.js\", ['goog.net.xpc.IframeRelayTransport'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.html.SafeHtml', 'goog.log', 'goog.log.Level', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.string', 'goog.string.Const', 'goog.userAgent']);\ngoog.addDependency(\"net/xpc/nativemessagingtransport.js\", ['goog.net.xpc.NativeMessagingTransport'], ['goog.Timer', 'goog.asserts', 'goog.async.Deferred', 'goog.events', 'goog.events.EventHandler', 'goog.log', 'goog.net.xpc', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes']);\ngoog.addDependency(\"net/xpc/nativemessagingtransport_test.js\", ['goog.net.xpc.NativeMessagingTransportTest'], ['goog.dom', 'goog.events', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannel', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.NativeMessagingTransport', 'goog.testing.jsunit']);\ngoog.addDependency(\"net/xpc/nixtransport.js\", ['goog.net.xpc.NixTransport'], ['goog.log', 'goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.CrossPageChannelRole', 'goog.net.xpc.Transport', 'goog.net.xpc.TransportTypes', 'goog.reflect']);\ngoog.addDependency(\"net/xpc/relay.js\", ['goog.net.xpc.relay'], []);\ngoog.addDependency(\"net/xpc/transport.js\", ['goog.net.xpc.Transport'], ['goog.Disposable', 'goog.dom', 'goog.net.xpc.TransportNames']);\ngoog.addDependency(\"net/xpc/xpc.js\", ['goog.net.xpc', 'goog.net.xpc.CfgFields', 'goog.net.xpc.ChannelStates', 'goog.net.xpc.TransportNames', 'goog.net.xpc.TransportTypes', 'goog.net.xpc.UriCfgFields'], ['goog.log']);\ngoog.addDependency(\"object/object.js\", ['goog.object'], []);\ngoog.addDependency(\"object/object_test.js\", ['goog.objectTest'], ['goog.functions', 'goog.object', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"positioning/absoluteposition.js\", ['goog.positioning.AbsolutePosition'], ['goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition']);\ngoog.addDependency(\"positioning/abstractposition.js\", ['goog.positioning.AbstractPosition'], []);\ngoog.addDependency(\"positioning/anchoredposition.js\", ['goog.positioning.AnchoredPosition'], ['goog.positioning', 'goog.positioning.AbstractPosition']);\ngoog.addDependency(\"positioning/anchoredposition_test.js\", ['goog.positioning.AnchoredPositionTest'], ['goog.dom', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.jsunit']);\ngoog.addDependency(\"positioning/anchoredviewportposition.js\", ['goog.positioning.AnchoredViewportPosition'], ['goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus']);\ngoog.addDependency(\"positioning/anchoredviewportposition_test.js\", ['goog.positioning.AnchoredViewportPositionTest'], ['goog.dom', 'goog.math.Box', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.positioning.OverflowStatus', 'goog.style', 'goog.testing.jsunit']);\ngoog.addDependency(\"positioning/clientposition.js\", ['goog.positioning.ClientPosition'], ['goog.asserts', 'goog.dom', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition', 'goog.style']);\ngoog.addDependency(\"positioning/clientposition_test.js\", ['goog.positioning.clientPositionTest'], ['goog.dom', 'goog.dom.TagName', 'goog.positioning.ClientPosition', 'goog.positioning.Corner', 'goog.style', 'goog.testing.jsunit']);\ngoog.addDependency(\"positioning/menuanchoredposition.js\", ['goog.positioning.MenuAnchoredPosition'], ['goog.positioning.AnchoredViewportPosition', 'goog.positioning.Overflow']);\ngoog.addDependency(\"positioning/menuanchoredposition_test.js\", ['goog.positioning.MenuAnchoredPositionTest'], ['goog.dom', 'goog.dom.TagName', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.testing.jsunit']);\ngoog.addDependency(\"positioning/positioning.js\", ['goog.positioning', 'goog.positioning.Corner', 'goog.positioning.CornerBit', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.style', 'goog.style.bidi']);\ngoog.addDependency(\"positioning/positioning_test.js\", ['goog.positioningTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.labs.userAgent.browser', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Size', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"positioning/viewportclientposition.js\", ['goog.positioning.ViewportClientPosition'], ['goog.dom', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.ClientPosition', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.style']);\ngoog.addDependency(\"positioning/viewportclientposition_test.js\", ['goog.positioning.ViewportClientPositionTest'], ['goog.dom', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.ViewportClientPosition', 'goog.style', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"positioning/viewportposition.js\", ['goog.positioning.ViewportPosition'], ['goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AbstractPosition', 'goog.positioning.Corner', 'goog.style']);\ngoog.addDependency(\"promise/promise.js\", ['goog.Promise'], ['goog.Thenable', 'goog.asserts', 'goog.async.FreeList', 'goog.async.run', 'goog.async.throwException', 'goog.debug.Error', 'goog.promise.Resolver']);\ngoog.addDependency(\"promise/promise_test.js\", ['goog.PromiseTest'], ['goog.Promise', 'goog.Thenable', 'goog.Timer', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"promise/resolver.js\", ['goog.promise.Resolver'], []);\ngoog.addDependency(\"promise/testsuiteadapter.js\", ['goog.promise.testSuiteAdapter'], ['goog.Promise']);\ngoog.addDependency(\"promise/thenable.js\", ['goog.Thenable'], []);\ngoog.addDependency(\"proto/proto.js\", ['goog.proto'], ['goog.proto.Serializer']);\ngoog.addDependency(\"proto/serializer.js\", ['goog.proto.Serializer'], ['goog.json.Serializer', 'goog.string']);\ngoog.addDependency(\"proto/serializer_test.js\", ['goog.protoTest'], ['goog.proto', 'goog.testing.jsunit']);\ngoog.addDependency(\"proto2/descriptor.js\", ['goog.proto2.Descriptor', 'goog.proto2.Metadata'], ['goog.array', 'goog.asserts', 'goog.object', 'goog.string']);\ngoog.addDependency(\"proto2/descriptor_test.js\", ['goog.proto2.DescriptorTest'], ['goog.proto2.Descriptor', 'goog.proto2.Message', 'goog.testing.jsunit']);\ngoog.addDependency(\"proto2/fielddescriptor.js\", ['goog.proto2.FieldDescriptor'], ['goog.asserts', 'goog.string']);\ngoog.addDependency(\"proto2/fielddescriptor_test.js\", ['goog.proto2.FieldDescriptorTest'], ['goog.proto2.FieldDescriptor', 'goog.proto2.Message', 'goog.testing.jsunit']);\ngoog.addDependency(\"proto2/lazydeserializer.js\", ['goog.proto2.LazyDeserializer'], ['goog.asserts', 'goog.proto2.Message', 'goog.proto2.Serializer']);\ngoog.addDependency(\"proto2/message.js\", ['goog.proto2.Message'], ['goog.asserts', 'goog.proto2.Descriptor', 'goog.proto2.FieldDescriptor']);\ngoog.addDependency(\"proto2/message_test.js\", ['goog.proto2.MessageTest'], ['goog.testing.TestCase', 'goog.testing.jsunit', 'proto2.TestAllTypes', 'proto2.TestAllTypes.NestedEnum', 'proto2.TestAllTypes.NestedMessage', 'proto2.TestAllTypes.OptionalGroup', 'proto2.TestAllTypes.RepeatedGroup']);\ngoog.addDependency(\"proto2/objectserializer.js\", ['goog.proto2.ObjectSerializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.Serializer', 'goog.string']);\ngoog.addDependency(\"proto2/objectserializer_test.js\", ['goog.proto2.ObjectSerializerTest'], ['goog.proto2.ObjectSerializer', 'goog.proto2.Serializer', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'proto2.TestAllTypes']);\ngoog.addDependency(\"proto2/package_test.pb.js\", ['someprotopackage.TestPackageTypes'], ['goog.proto2.Message', 'proto2.TestAllTypes']);\ngoog.addDependency(\"proto2/pbliteserializer.js\", ['goog.proto2.PbLiteSerializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.LazyDeserializer', 'goog.proto2.Serializer']);\ngoog.addDependency(\"proto2/pbliteserializer_test.js\", ['goog.proto2.PbLiteSerializerTest'], ['goog.proto2.PbLiteSerializer', 'goog.testing.jsunit', 'proto2.TestAllTypes']);\ngoog.addDependency(\"proto2/proto_test.js\", ['goog.proto2.messageTest'], ['goog.proto2.FieldDescriptor', 'goog.testing.jsunit', 'proto2.TestAllTypes', 'proto2.TestDefaultParent', 'someprotopackage.TestPackageTypes']);\ngoog.addDependency(\"proto2/serializer.js\", ['goog.proto2.Serializer'], ['goog.asserts', 'goog.proto2.FieldDescriptor', 'goog.proto2.Message']);\ngoog.addDependency(\"proto2/test.pb.js\", ['proto2.TestAllTypes', 'proto2.TestAllTypes.NestedMessage', 'proto2.TestAllTypes.OptionalGroup', 'proto2.TestAllTypes.RepeatedGroup', 'proto2.TestAllTypes.NestedEnum', 'proto2.TestDefaultParent', 'proto2.TestDefaultChild'], ['goog.proto2.Message']);\ngoog.addDependency(\"proto2/textformatserializer.js\", ['goog.proto2.TextFormatSerializer'], ['goog.array', 'goog.asserts', 'goog.json', 'goog.math', 'goog.object', 'goog.proto2.FieldDescriptor', 'goog.proto2.Message', 'goog.proto2.Serializer', 'goog.string']);\ngoog.addDependency(\"proto2/textformatserializer_test.js\", ['goog.proto2.TextFormatSerializerTest'], ['goog.proto2.ObjectSerializer', 'goog.proto2.TextFormatSerializer', 'goog.testing.jsunit', 'proto2.TestAllTypes']);\ngoog.addDependency(\"proto2/util.js\", ['goog.proto2.Util'], ['goog.asserts']);\ngoog.addDependency(\"pubsub/pubsub.js\", ['goog.pubsub.PubSub'], ['goog.Disposable', 'goog.array', 'goog.async.run']);\ngoog.addDependency(\"pubsub/pubsub_test.js\", ['goog.pubsub.PubSubTest'], ['goog.array', 'goog.pubsub.PubSub', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"pubsub/topicid.js\", ['goog.pubsub.TopicId'], []);\ngoog.addDependency(\"pubsub/typedpubsub.js\", ['goog.pubsub.TypedPubSub'], ['goog.Disposable', 'goog.pubsub.PubSub']);\ngoog.addDependency(\"pubsub/typedpubsub_test.js\", ['goog.pubsub.TypedPubSubTest'], ['goog.array', 'goog.pubsub.TopicId', 'goog.pubsub.TypedPubSub', 'goog.testing.jsunit']);\ngoog.addDependency(\"reflect/reflect.js\", ['goog.reflect'], []);\ngoog.addDependency(\"result/deferredadaptor.js\", ['goog.result.DeferredAdaptor'], ['goog.async.Deferred', 'goog.result', 'goog.result.Result']);\ngoog.addDependency(\"result/dependentresult.js\", ['goog.result.DependentResult'], ['goog.result.Result']);\ngoog.addDependency(\"result/result_interface.js\", ['goog.result.Result'], ['goog.Thenable']);\ngoog.addDependency(\"result/resultutil.js\", ['goog.result'], ['goog.array', 'goog.result.DependentResult', 'goog.result.Result', 'goog.result.SimpleResult']);\ngoog.addDependency(\"result/simpleresult.js\", ['goog.result.SimpleResult', 'goog.result.SimpleResult.StateError'], ['goog.Promise', 'goog.Thenable', 'goog.debug.Error', 'goog.result.Result']);\ngoog.addDependency(\"soy/data.js\", ['goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind', 'goog.soy.data.UnsanitizedText'], ['goog.html.SafeHtml', 'goog.html.uncheckedconversions', 'goog.string.Const']);\ngoog.addDependency(\"soy/data_test.js\", ['goog.soy.dataTest'], ['goog.html.SafeHtml', 'goog.soy.testHelper', 'goog.testing.jsunit']);\ngoog.addDependency(\"soy/renderer.js\", ['goog.soy.InjectedDataSupplier', 'goog.soy.Renderer'], ['goog.asserts', 'goog.dom', 'goog.soy', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind']);\ngoog.addDependency(\"soy/renderer_test.js\", ['goog.soy.RendererTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.html.SafeHtml', 'goog.i18n.bidi.Dir', 'goog.soy.Renderer', 'goog.soy.data.SanitizedContentKind', 'goog.soy.testHelper', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"soy/soy.js\", ['goog.soy'], ['goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind', 'goog.string']);\ngoog.addDependency(\"soy/soy_test.js\", ['goog.soyTest'], ['goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.functions', 'goog.soy', 'goog.soy.testHelper', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"soy/soy_testhelper.js\", ['goog.soy.testHelper'], ['goog.dom', 'goog.dom.TagName', 'goog.i18n.bidi.Dir', 'goog.soy.data.SanitizedContent', 'goog.soy.data.SanitizedContentKind', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"spell/spellcheck.js\", ['goog.spell.SpellCheck', 'goog.spell.SpellCheck.WordChangedEvent'], ['goog.Timer', 'goog.events.Event', 'goog.events.EventTarget', 'goog.structs.Set']);\ngoog.addDependency(\"spell/spellcheck_test.js\", ['goog.spell.SpellCheckTest'], ['goog.spell.SpellCheck', 'goog.testing.jsunit']);\ngoog.addDependency(\"stats/basicstat.js\", ['goog.stats.BasicStat'], ['goog.asserts', 'goog.log', 'goog.string.format', 'goog.structs.CircularBuffer']);\ngoog.addDependency(\"stats/basicstat_test.js\", ['goog.stats.BasicStatTest'], ['goog.array', 'goog.stats.BasicStat', 'goog.string.format', 'goog.testing.PseudoRandom', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"storage/collectablestorage.js\", ['goog.storage.CollectableStorage'], ['goog.array', 'goog.iter', 'goog.storage.ErrorCode', 'goog.storage.ExpiringStorage', 'goog.storage.RichStorage']);\ngoog.addDependency(\"storage/collectablestorage_test.js\", ['goog.storage.CollectableStorageTest'], ['goog.storage.CollectableStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism']);\ngoog.addDependency(\"storage/collectablestoragetester.js\", ['goog.storage.collectableStorageTester'], ['goog.testing.asserts']);\ngoog.addDependency(\"storage/encryptedstorage.js\", ['goog.storage.EncryptedStorage'], ['goog.crypt', 'goog.crypt.Arc4', 'goog.crypt.Sha1', 'goog.crypt.base64', 'goog.json', 'goog.json.Serializer', 'goog.storage.CollectableStorage', 'goog.storage.ErrorCode', 'goog.storage.RichStorage']);\ngoog.addDependency(\"storage/encryptedstorage_test.js\", ['goog.storage.EncryptedStorageTest'], ['goog.json', 'goog.storage.EncryptedStorage', 'goog.storage.ErrorCode', 'goog.storage.RichStorage', 'goog.storage.collectableStorageTester', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.PseudoRandom', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism']);\ngoog.addDependency(\"storage/errorcode.js\", ['goog.storage.ErrorCode'], []);\ngoog.addDependency(\"storage/expiringstorage.js\", ['goog.storage.ExpiringStorage'], ['goog.storage.RichStorage']);\ngoog.addDependency(\"storage/expiringstorage_test.js\", ['goog.storage.ExpiringStorageTest'], ['goog.storage.ExpiringStorage', 'goog.storage.storage_test', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism']);\ngoog.addDependency(\"storage/richstorage.js\", ['goog.storage.RichStorage', 'goog.storage.RichStorage.Wrapper'], ['goog.storage.ErrorCode', 'goog.storage.Storage']);\ngoog.addDependency(\"storage/richstorage_test.js\", ['goog.storage.RichStorageTest'], ['goog.storage.ErrorCode', 'goog.storage.RichStorage', 'goog.storage.storage_test', 'goog.testing.jsunit', 'goog.testing.storage.FakeMechanism']);\ngoog.addDependency(\"storage/storage.js\", ['goog.storage.Storage'], ['goog.json', 'goog.storage.ErrorCode']);\ngoog.addDependency(\"storage/storage_test.js\", ['goog.storage.storage_test'], ['goog.structs.Map', 'goog.testing.asserts']);\ngoog.addDependency(\"storage/mechanism/errorcode.js\", ['goog.storage.mechanism.ErrorCode'], []);\ngoog.addDependency(\"storage/mechanism/errorhandlingmechanism.js\", ['goog.storage.mechanism.ErrorHandlingMechanism'], ['goog.storage.mechanism.Mechanism']);\ngoog.addDependency(\"storage/mechanism/errorhandlingmechanism_test.js\", ['goog.storage.mechanism.ErrorHandlingMechanismTest'], ['goog.storage.mechanism.ErrorHandlingMechanism', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"storage/mechanism/html5localstorage.js\", ['goog.storage.mechanism.HTML5LocalStorage'], ['goog.storage.mechanism.HTML5WebStorage']);\ngoog.addDependency(\"storage/mechanism/html5localstorage_test.js\", ['goog.storage.mechanism.HTML5LocalStorageTest'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"storage/mechanism/html5sessionstorage.js\", ['goog.storage.mechanism.HTML5SessionStorage'], ['goog.storage.mechanism.HTML5WebStorage']);\ngoog.addDependency(\"storage/mechanism/html5sessionstorage_test.js\", ['goog.storage.mechanism.HTML5SessionStorageTest'], ['goog.storage.mechanism.HTML5SessionStorage', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"storage/mechanism/html5webstorage.js\", ['goog.storage.mechanism.HTML5WebStorage'], ['goog.asserts', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.IterableMechanism']);\ngoog.addDependency(\"storage/mechanism/html5webstorage_test.js\", ['goog.storage.mechanism.HTML5MockStorage', 'goog.storage.mechanism.HTML5WebStorageTest', 'goog.storage.mechanism.MockThrowableStorage'], ['goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.HTML5WebStorage', 'goog.testing.jsunit']);\ngoog.addDependency(\"storage/mechanism/ieuserdata.js\", ['goog.storage.mechanism.IEUserData'], ['goog.asserts', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.storage.mechanism.ErrorCode', 'goog.storage.mechanism.IterableMechanism', 'goog.structs.Map', 'goog.userAgent']);\ngoog.addDependency(\"storage/mechanism/ieuserdata_test.js\", ['goog.storage.mechanism.IEUserDataTest'], ['goog.storage.mechanism.IEUserData', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"storage/mechanism/iterablemechanism.js\", ['goog.storage.mechanism.IterableMechanism'], ['goog.array', 'goog.asserts', 'goog.iter', 'goog.storage.mechanism.Mechanism']);\ngoog.addDependency(\"storage/mechanism/iterablemechanismtester.js\", ['goog.storage.mechanism.iterableMechanismTester'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism', 'goog.testing.asserts']);\ngoog.addDependency(\"storage/mechanism/mechanism.js\", ['goog.storage.mechanism.Mechanism'], []);\ngoog.addDependency(\"storage/mechanism/mechanismfactory.js\", ['goog.storage.mechanism.mechanismfactory'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.HTML5SessionStorage', 'goog.storage.mechanism.IEUserData', 'goog.storage.mechanism.PrefixedMechanism']);\ngoog.addDependency(\"storage/mechanism/mechanismfactory_test.js\", ['goog.storage.mechanism.mechanismfactoryTest'], ['goog.storage.mechanism.mechanismfactory', 'goog.testing.jsunit']);\ngoog.addDependency(\"storage/mechanism/mechanismseparationtester.js\", ['goog.storage.mechanism.mechanismSeparationTester'], ['goog.iter.StopIteration', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.asserts']);\ngoog.addDependency(\"storage/mechanism/mechanismsharingtester.js\", ['goog.storage.mechanism.mechanismSharingTester'], ['goog.iter.StopIteration', 'goog.storage.mechanism.mechanismTestDefinition', 'goog.testing.asserts']);\ngoog.addDependency(\"storage/mechanism/mechanismtestdefinition.js\", ['goog.storage.mechanism.mechanismTestDefinition'], []);\ngoog.addDependency(\"storage/mechanism/mechanismtester.js\", ['goog.storage.mechanism.mechanismTester'], ['goog.storage.mechanism.ErrorCode', 'goog.testing.asserts', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"storage/mechanism/prefixedmechanism.js\", ['goog.storage.mechanism.PrefixedMechanism'], ['goog.iter.Iterator', 'goog.storage.mechanism.IterableMechanism']);\ngoog.addDependency(\"storage/mechanism/prefixedmechanism_test.js\", ['goog.storage.mechanism.PrefixedMechanismTest'], ['goog.storage.mechanism.HTML5LocalStorage', 'goog.storage.mechanism.PrefixedMechanism', 'goog.storage.mechanism.mechanismSeparationTester', 'goog.storage.mechanism.mechanismSharingTester', 'goog.testing.jsunit']);\ngoog.addDependency(\"string/const.js\", ['goog.string.Const'], ['goog.asserts', 'goog.string.TypedString']);\ngoog.addDependency(\"string/const_test.js\", ['goog.string.constTest'], ['goog.string.Const', 'goog.testing.jsunit']);\ngoog.addDependency(\"string/linkify.js\", ['goog.string.linkify'], ['goog.html.SafeHtml', 'goog.string']);\ngoog.addDependency(\"string/linkify_test.js\", ['goog.string.linkifyTest'], ['goog.dom.TagName', 'goog.html.SafeHtml', 'goog.string', 'goog.string.linkify', 'goog.testing.dom', 'goog.testing.jsunit']);\ngoog.addDependency(\"string/newlines.js\", ['goog.string.newlines', 'goog.string.newlines.Line'], ['goog.array']);\ngoog.addDependency(\"string/newlines_test.js\", ['goog.string.newlinesTest'], ['goog.string.newlines', 'goog.testing.jsunit']);\ngoog.addDependency(\"string/parser.js\", ['goog.string.Parser'], []);\ngoog.addDependency(\"string/path.js\", ['goog.string.path'], ['goog.array', 'goog.string']);\ngoog.addDependency(\"string/path_test.js\", ['goog.string.pathTest'], ['goog.string.path', 'goog.testing.jsunit']);\ngoog.addDependency(\"string/string.js\", ['goog.string', 'goog.string.Unicode'], []);\ngoog.addDependency(\"string/string_test.js\", ['goog.stringTest'], ['goog.dom.TagName', 'goog.functions', 'goog.object', 'goog.string', 'goog.string.Unicode', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit']);\ngoog.addDependency(\"string/stringbuffer.js\", ['goog.string.StringBuffer'], []);\ngoog.addDependency(\"string/stringbuffer_test.js\", ['goog.string.StringBufferTest'], ['goog.string.StringBuffer', 'goog.testing.jsunit']);\ngoog.addDependency(\"string/stringformat.js\", ['goog.string.format'], ['goog.string']);\ngoog.addDependency(\"string/stringformat_test.js\", ['goog.string.formatTest'], ['goog.string.format', 'goog.testing.jsunit']);\ngoog.addDependency(\"string/stringifier.js\", ['goog.string.Stringifier'], []);\ngoog.addDependency(\"string/typedstring.js\", ['goog.string.TypedString'], []);\ngoog.addDependency(\"structs/avltree.js\", ['goog.structs.AvlTree', 'goog.structs.AvlTree.Node'], ['goog.structs.Collection']);\ngoog.addDependency(\"structs/avltree_test.js\", ['goog.structs.AvlTreeTest'], ['goog.array', 'goog.structs.AvlTree', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/circularbuffer.js\", ['goog.structs.CircularBuffer'], []);\ngoog.addDependency(\"structs/circularbuffer_test.js\", ['goog.structs.CircularBufferTest'], ['goog.structs.CircularBuffer', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/collection.js\", ['goog.structs.Collection'], []);\ngoog.addDependency(\"structs/collection_test.js\", ['goog.structs.CollectionTest'], ['goog.structs.AvlTree', 'goog.structs.Set', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/heap.js\", ['goog.structs.Heap'], ['goog.array', 'goog.object', 'goog.structs.Node']);\ngoog.addDependency(\"structs/heap_test.js\", ['goog.structs.HeapTest'], ['goog.structs', 'goog.structs.Heap', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/inversionmap.js\", ['goog.structs.InversionMap'], ['goog.array']);\ngoog.addDependency(\"structs/inversionmap_test.js\", ['goog.structs.InversionMapTest'], ['goog.structs.InversionMap', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/linkedmap.js\", ['goog.structs.LinkedMap'], ['goog.structs.Map']);\ngoog.addDependency(\"structs/linkedmap_test.js\", ['goog.structs.LinkedMapTest'], ['goog.structs.LinkedMap', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"structs/map.js\", ['goog.structs.Map'], ['goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.object']);\ngoog.addDependency(\"structs/map_test.js\", ['goog.structs.MapTest'], ['goog.iter', 'goog.structs', 'goog.structs.Map', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/node.js\", ['goog.structs.Node'], []);\ngoog.addDependency(\"structs/pool.js\", ['goog.structs.Pool'], ['goog.Disposable', 'goog.structs.Queue', 'goog.structs.Set']);\ngoog.addDependency(\"structs/pool_test.js\", ['goog.structs.PoolTest'], ['goog.structs.Pool', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/prioritypool.js\", ['goog.structs.PriorityPool'], ['goog.structs.Pool', 'goog.structs.PriorityQueue']);\ngoog.addDependency(\"structs/prioritypool_test.js\", ['goog.structs.PriorityPoolTest'], ['goog.structs.PriorityPool', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/priorityqueue.js\", ['goog.structs.PriorityQueue'], ['goog.structs.Heap']);\ngoog.addDependency(\"structs/priorityqueue_test.js\", ['goog.structs.PriorityQueueTest'], ['goog.structs', 'goog.structs.PriorityQueue', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/quadtree.js\", ['goog.structs.QuadTree', 'goog.structs.QuadTree.Node', 'goog.structs.QuadTree.Point'], ['goog.math.Coordinate']);\ngoog.addDependency(\"structs/quadtree_test.js\", ['goog.structs.QuadTreeTest'], ['goog.structs', 'goog.structs.QuadTree', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/queue.js\", ['goog.structs.Queue'], ['goog.array']);\ngoog.addDependency(\"structs/queue_test.js\", ['goog.structs.QueueTest'], ['goog.structs.Queue', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/set.js\", ['goog.structs.Set'], ['goog.structs', 'goog.structs.Collection', 'goog.structs.Map']);\ngoog.addDependency(\"structs/set_test.js\", ['goog.structs.SetTest'], ['goog.iter', 'goog.structs', 'goog.structs.Set', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/simplepool.js\", ['goog.structs.SimplePool'], ['goog.Disposable']);\ngoog.addDependency(\"structs/stringset.js\", ['goog.structs.StringSet'], ['goog.asserts', 'goog.iter']);\ngoog.addDependency(\"structs/stringset_test.js\", ['goog.structs.StringSetTest'], ['goog.array', 'goog.iter', 'goog.structs.StringSet', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/structs.js\", ['goog.structs'], ['goog.array', 'goog.object']);\ngoog.addDependency(\"structs/structs_test.js\", ['goog.structsTest'], ['goog.array', 'goog.dom.TagName', 'goog.structs', 'goog.structs.Map', 'goog.structs.Set', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/treenode.js\", ['goog.structs.TreeNode'], ['goog.array', 'goog.asserts', 'goog.structs.Node']);\ngoog.addDependency(\"structs/treenode_test.js\", ['goog.structs.TreeNodeTest'], ['goog.structs.TreeNode', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/trie.js\", ['goog.structs.Trie'], ['goog.object', 'goog.structs']);\ngoog.addDependency(\"structs/trie_test.js\", ['goog.structs.TrieTest'], ['goog.object', 'goog.structs', 'goog.structs.Trie', 'goog.testing.jsunit']);\ngoog.addDependency(\"structs/weak/weak.js\", ['goog.structs.weak'], ['goog.userAgent']);\ngoog.addDependency(\"structs/weak/weak_test.js\", ['goog.structs.weakTest'], ['goog.array', 'goog.structs.weak', 'goog.testing.jsunit']);\ngoog.addDependency(\"style/bidi.js\", ['goog.style.bidi'], ['goog.dom', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"style/bidi_test.js\", ['goog.style.bidiTest'], ['goog.dom', 'goog.style', 'goog.style.bidi', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"style/cursor.js\", ['goog.style.cursor'], ['goog.userAgent']);\ngoog.addDependency(\"style/cursor_test.js\", ['goog.style.cursorTest'], ['goog.style.cursor', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"style/style.js\", ['goog.style'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.vendor', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.object', 'goog.reflect', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"style/style_document_scroll_test.js\", ['goog.style.style_document_scroll_test'], ['goog.dom', 'goog.style', 'goog.testing.jsunit']);\ngoog.addDependency(\"style/style_test.js\", ['goog.style_test'], ['goog.array', 'goog.color', 'goog.dom', 'goog.dom.TagName', 'goog.events.BrowserEvent', 'goog.labs.userAgent.util', 'goog.math.Box', 'goog.math.Coordinate', 'goog.math.Rect', 'goog.math.Size', 'goog.object', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.MockUserAgent', 'goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgentTestUtil', 'goog.userAgentTestUtil.UserAgents']);\ngoog.addDependency(\"style/style_webkit_scrollbars_test.js\", ['goog.style.webkitScrollbarsTest'], ['goog.asserts', 'goog.style', 'goog.styleScrollbarTester', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"style/stylescrollbartester.js\", ['goog.styleScrollbarTester'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.testing.asserts']);\ngoog.addDependency(\"style/transform.js\", ['goog.style.transform'], ['goog.functions', 'goog.math.Coordinate', 'goog.math.Coordinate3', 'goog.style', 'goog.userAgent', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"style/transform_test.js\", ['goog.style.transformTest'], ['goog.dom', 'goog.dom.TagName', 'goog.style.transform', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"style/transition.js\", ['goog.style.transition', 'goog.style.transition.Css3Property'], ['goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.safe', 'goog.dom.vendor', 'goog.functions', 'goog.html.SafeHtml', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"style/transition_test.js\", ['goog.style.transitionTest'], ['goog.style', 'goog.style.transition', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"testing/asserts.js\", ['goog.testing.JsUnitException', 'goog.testing.asserts', 'goog.testing.asserts.ArrayLike'], ['goog.testing.stacktrace']);\ngoog.addDependency(\"testing/asserts_test.js\", ['goog.testing.assertsTest'], ['goog.array', 'goog.dom', 'goog.iter.Iterator', 'goog.iter.StopIteration', 'goog.labs.userAgent.browser', 'goog.string', 'goog.structs.Map', 'goog.structs.Set', 'goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"testing/asynctestcase.js\", ['goog.testing.AsyncTestCase', 'goog.testing.AsyncTestCase.ControlBreakingException'], ['goog.testing.TestCase', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/asynctestcase_async_test.js\", ['goog.testing.AsyncTestCaseAsyncTest'], ['goog.testing.AsyncTestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/asynctestcase_noasync_test.js\", ['goog.testing.AsyncTestCaseSyncTest'], ['goog.testing.AsyncTestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/asynctestcase_test.js\", ['goog.testing.AsyncTestCaseTest'], ['goog.debug.Error', 'goog.testing.AsyncTestCase', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/benchmark.js\", ['goog.testing.benchmark'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTable', 'goog.testing.PerformanceTimer', 'goog.testing.TestCase']);\ngoog.addDependency(\"testing/continuationtestcase.js\", ['goog.testing.ContinuationTestCase', 'goog.testing.ContinuationTestCase.ContinuationTest', 'goog.testing.ContinuationTestCase.Step'], ['goog.array', 'goog.events.EventHandler', 'goog.testing.TestCase', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/continuationtestcase_test.js\", ['goog.testing.ContinuationTestCaseTest'], ['goog.events', 'goog.events.EventTarget', 'goog.testing.ContinuationTestCase', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/deferredtestcase.js\", ['goog.testing.DeferredTestCase'], ['goog.testing.AsyncTestCase', 'goog.testing.TestCase']);\ngoog.addDependency(\"testing/deferredtestcase_test.js\", ['goog.testing.DeferredTestCaseTest'], ['goog.async.Deferred', 'goog.testing.DeferredTestCase', 'goog.testing.TestCase', 'goog.testing.TestRunner', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"testing/dom.js\", ['goog.testing.dom'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.NodeIterator', 'goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.iter', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.asserts', 'goog.userAgent']);\ngoog.addDependency(\"testing/dom_test.js\", ['goog.testing.domTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.TestCase', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"testing/expectedfailures.js\", ['goog.testing.ExpectedFailures'], ['goog.asserts', 'goog.debug.DivConsole', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.log', 'goog.style', 'goog.testing.JsUnitException', 'goog.testing.TestCase', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/expectedfailures_test.js\", ['goog.testing.ExpectedFailuresTest'], ['goog.debug.Logger', 'goog.testing.ExpectedFailures', 'goog.testing.JsUnitException', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/functionmock.js\", ['goog.testing', 'goog.testing.FunctionMock', 'goog.testing.GlobalFunctionMock', 'goog.testing.MethodMock'], ['goog.object', 'goog.testing.LooseMock', 'goog.testing.Mock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock']);\ngoog.addDependency(\"testing/functionmock_test.js\", ['goog.testing.FunctionMockTest'], ['goog.array', 'goog.string', 'goog.testing', 'goog.testing.FunctionMock', 'goog.testing.Mock', 'goog.testing.StrictMock', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.mockmatchers']);\ngoog.addDependency(\"testing/graphics.js\", ['goog.testing.graphics'], ['goog.graphics.Path', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/jstdtestcaseadapter.js\", ['goog.testing.JsTdTestCaseAdapter'], ['goog.async.run', 'goog.testing.TestCase', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/jsunit.js\", ['goog.testing.jsunit'], ['goog.dom.TagName', 'goog.testing.TestCase', 'goog.testing.TestRunner']);\ngoog.addDependency(\"testing/loosemock.js\", ['goog.testing.LooseExpectationCollection', 'goog.testing.LooseMock'], ['goog.array', 'goog.structs.Map', 'goog.testing.Mock']);\ngoog.addDependency(\"testing/loosemock_test.js\", ['goog.testing.LooseMockTest'], ['goog.testing.LooseMock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.mockmatchers']);\ngoog.addDependency(\"testing/mock.js\", ['goog.testing.Mock', 'goog.testing.MockExpectation'], ['goog.array', 'goog.object', 'goog.testing.JsUnitException', 'goog.testing.MockInterface', 'goog.testing.mockmatchers']);\ngoog.addDependency(\"testing/mock_test.js\", ['goog.testing.MockTest'], ['goog.array', 'goog.testing', 'goog.testing.Mock', 'goog.testing.MockControl', 'goog.testing.MockExpectation', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/mockclassfactory.js\", ['goog.testing.MockClassFactory', 'goog.testing.MockClassRecord'], ['goog.array', 'goog.object', 'goog.testing.LooseMock', 'goog.testing.StrictMock', 'goog.testing.TestCase', 'goog.testing.mockmatchers']);\ngoog.addDependency(\"testing/mockclassfactory_test.js\", ['fake.BaseClass', 'fake.ChildClass', 'goog.testing.MockClassFactoryTest'], ['goog.testing', 'goog.testing.MockClassFactory', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/mockclock.js\", ['goog.testing.MockClock'], ['goog.Disposable', 'goog.async.run', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.events.Event']);\ngoog.addDependency(\"testing/mockclock_test.js\", ['goog.testing.MockClockTest'], ['goog.Promise', 'goog.Timer', 'goog.events', 'goog.functions', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.recordFunction']);\ngoog.addDependency(\"testing/mockcontrol.js\", ['goog.testing.MockControl'], ['goog.array', 'goog.testing', 'goog.testing.LooseMock', 'goog.testing.StrictMock']);\ngoog.addDependency(\"testing/mockcontrol_test.js\", ['goog.testing.MockControlTest'], ['goog.testing.Mock', 'goog.testing.MockControl', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/mockinterface.js\", ['goog.testing.MockInterface'], []);\ngoog.addDependency(\"testing/mockmatchers.js\", ['goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.testing.mockmatchers.IgnoreArgument', 'goog.testing.mockmatchers.InstanceOf', 'goog.testing.mockmatchers.ObjectEquals', 'goog.testing.mockmatchers.RegexpMatch', 'goog.testing.mockmatchers.SaveArgument', 'goog.testing.mockmatchers.TypeOf'], ['goog.array', 'goog.dom', 'goog.testing.TestCase', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/mockmatchers_test.js\", ['goog.testing.mockmatchersTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher']);\ngoog.addDependency(\"testing/mockrandom.js\", ['goog.testing.MockRandom'], ['goog.Disposable']);\ngoog.addDependency(\"testing/mockrandom_test.js\", ['goog.testing.MockRandomTest'], ['goog.testing.MockRandom', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/mockrange.js\", ['goog.testing.MockRange'], ['goog.dom.AbstractRange', 'goog.testing.LooseMock']);\ngoog.addDependency(\"testing/mockrange_test.js\", ['goog.testing.MockRangeTest'], ['goog.testing.MockRange', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/mockstorage.js\", ['goog.testing.MockStorage'], ['goog.structs.Map']);\ngoog.addDependency(\"testing/mockstorage_test.js\", ['goog.testing.MockStorageTest'], ['goog.testing.MockStorage', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/mockuseragent.js\", ['goog.testing.MockUserAgent'], ['goog.Disposable', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.userAgent']);\ngoog.addDependency(\"testing/mockuseragent_test.js\", ['goog.testing.MockUserAgentTest'], ['goog.dispose', 'goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"testing/multitestrunner.js\", ['goog.testing.MultiTestRunner', 'goog.testing.MultiTestRunner.TestFrame'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.functions', 'goog.object', 'goog.string', 'goog.ui.Component', 'goog.ui.ServerChart', 'goog.ui.TableSorter']);\ngoog.addDependency(\"testing/multitestrunner_test.js\", [], []);\ngoog.addDependency(\"testing/objectpropertystring.js\", ['goog.testing.ObjectPropertyString'], []);\ngoog.addDependency(\"testing/parallel_closure_test_suite.js\", [], []);\ngoog.addDependency(\"testing/parallel_closure_test_suite_test.js\", [], []);\ngoog.addDependency(\"testing/performancetable.js\", ['goog.testing.PerformanceTable'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.PerformanceTimer']);\ngoog.addDependency(\"testing/performancetimer.js\", ['goog.testing.PerformanceTimer', 'goog.testing.PerformanceTimer.Task'], ['goog.array', 'goog.async.Deferred', 'goog.math']);\ngoog.addDependency(\"testing/performancetimer_test.js\", ['goog.testing.PerformanceTimerTest'], ['goog.async.Deferred', 'goog.dom', 'goog.math', 'goog.testing.MockClock', 'goog.testing.PerformanceTimer', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/propertyreplacer.js\", ['goog.testing.PropertyReplacer'], ['goog.testing.ObjectPropertyString', 'goog.userAgent']);\ngoog.addDependency(\"testing/propertyreplacer_test.js\", ['goog.testing.PropertyReplacerTest'], ['goog.dom.TagName', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"testing/pseudorandom.js\", ['goog.testing.PseudoRandom'], ['goog.Disposable']);\ngoog.addDependency(\"testing/pseudorandom_test.js\", ['goog.testing.PseudoRandomTest'], ['goog.testing.PseudoRandom', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/recordfunction.js\", ['goog.testing.FunctionCall', 'goog.testing.recordConstructor', 'goog.testing.recordFunction'], ['goog.testing.asserts']);\ngoog.addDependency(\"testing/recordfunction_test.js\", ['goog.testing.recordFunctionTest'], ['goog.functions', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.recordConstructor', 'goog.testing.recordFunction']);\ngoog.addDependency(\"testing/shardingtestcase.js\", ['goog.testing.ShardingTestCase'], ['goog.asserts', 'goog.testing.TestCase']);\ngoog.addDependency(\"testing/shardingtestcase_test.js\", ['goog.testing.ShardingTestCaseTest'], ['goog.testing.ShardingTestCase', 'goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/singleton.js\", ['goog.testing.singleton'], []);\ngoog.addDependency(\"testing/singleton_test.js\", ['goog.testing.singletonTest'], ['goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.singleton']);\ngoog.addDependency(\"testing/stacktrace.js\", ['goog.testing.stacktrace', 'goog.testing.stacktrace.Frame'], []);\ngoog.addDependency(\"testing/stacktrace_test.js\", ['goog.testing.stacktraceTest'], ['goog.functions', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.stacktrace', 'goog.testing.stacktrace.Frame', 'goog.userAgent']);\ngoog.addDependency(\"testing/strictmock.js\", ['goog.testing.StrictMock'], ['goog.array', 'goog.testing.Mock']);\ngoog.addDependency(\"testing/strictmock_test.js\", ['goog.testing.StrictMockTest'], ['goog.testing.StrictMock', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/testcase.js\", ['goog.testing.TestCase', 'goog.testing.TestCase.Error', 'goog.testing.TestCase.Order', 'goog.testing.TestCase.Result', 'goog.testing.TestCase.Test'], ['goog.Promise', 'goog.Thenable', 'goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.object', 'goog.testing.JsUnitException', 'goog.testing.asserts', 'goog.testing.stacktrace']);\ngoog.addDependency(\"testing/testcase_test.js\", ['goog.testing.TestCaseTest'], ['goog.Promise', 'goog.functions', 'goog.string', 'goog.testing.ExpectedFailures', 'goog.testing.JsUnitException', 'goog.testing.MethodMock', 'goog.testing.MockRandom', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.mockmatchers.ObjectEquals']);\ngoog.addDependency(\"testing/testqueue.js\", ['goog.testing.TestQueue'], []);\ngoog.addDependency(\"testing/testrunner.js\", ['goog.testing.TestRunner'], ['goog.dom.TagName', 'goog.testing.TestCase']);\ngoog.addDependency(\"testing/testsuite.js\", ['goog.testing.testSuite'], ['goog.labs.testing.Environment', 'goog.testing.TestCase']);\ngoog.addDependency(\"testing/async/mockcontrol.js\", ['goog.testing.async.MockControl'], ['goog.asserts', 'goog.async.Deferred', 'goog.debug', 'goog.testing.asserts', 'goog.testing.mockmatchers.IgnoreArgument']);\ngoog.addDependency(\"testing/async/mockcontrol_test.js\", ['goog.testing.async.MockControlTest'], ['goog.async.Deferred', 'goog.testing.MockControl', 'goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.async.MockControl', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/editor/dom.js\", ['goog.testing.editor.dom'], ['goog.dom.NodeType', 'goog.dom.TagIterator', 'goog.dom.TagWalkType', 'goog.iter', 'goog.string', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/editor/dom_test.js\", ['goog.testing.editor.domTest'], ['goog.dom', 'goog.dom.TagName', 'goog.functions', 'goog.testing.TestCase', 'goog.testing.editor.dom', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/editor/fieldmock.js\", ['goog.testing.editor.FieldMock'], ['goog.dom', 'goog.dom.Range', 'goog.editor.Field', 'goog.testing.LooseMock', 'goog.testing.mockmatchers']);\ngoog.addDependency(\"testing/editor/testhelper.js\", ['goog.testing.editor.TestHelper'], ['goog.Disposable', 'goog.dom', 'goog.dom.Range', 'goog.editor.BrowserFeature', 'goog.editor.node', 'goog.editor.plugins.AbstractBubblePlugin', 'goog.testing.dom']);\ngoog.addDependency(\"testing/editor/testhelper_test.js\", ['goog.testing.editor.TestHelperTest'], ['goog.dom', 'goog.dom.TagName', 'goog.editor.node', 'goog.testing.TestCase', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"testing/events/eventobserver.js\", ['goog.testing.events.EventObserver'], ['goog.array']);\ngoog.addDependency(\"testing/events/eventobserver_test.js\", ['goog.testing.events.EventObserverTest'], ['goog.array', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.testing.events.EventObserver', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/events/events.js\", ['goog.testing.events', 'goog.testing.events.Event'], ['goog.Disposable', 'goog.asserts', 'goog.dom.NodeType', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.BrowserFeature', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.object', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"testing/events/events_test.js\", ['goog.testing.eventsTest'], ['goog.array', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.userAgent']);\ngoog.addDependency(\"testing/events/matchers.js\", ['goog.testing.events.EventMatcher'], ['goog.events.Event', 'goog.testing.mockmatchers.ArgumentMatcher']);\ngoog.addDependency(\"testing/events/matchers_test.js\", ['goog.testing.events.EventMatcherTest'], ['goog.events.Event', 'goog.testing.events.EventMatcher', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/events/onlinehandler.js\", ['goog.testing.events.OnlineHandler'], ['goog.events.EventTarget', 'goog.net.NetworkStatusMonitor']);\ngoog.addDependency(\"testing/events/onlinehandler_test.js\", ['goog.testing.events.OnlineHandlerTest'], ['goog.events', 'goog.net.NetworkStatusMonitor', 'goog.testing.events.EventObserver', 'goog.testing.events.OnlineHandler', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/blob.js\", ['goog.testing.fs.Blob'], ['goog.crypt.base64']);\ngoog.addDependency(\"testing/fs/blob_test.js\", ['goog.testing.fs.BlobTest'], ['goog.testing.fs.Blob', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/directoryentry_test.js\", ['goog.testing.fs.DirectoryEntryTest'], ['goog.array', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.testing.MockClock', 'goog.testing.TestCase', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/entry.js\", ['goog.testing.fs.DirectoryEntry', 'goog.testing.fs.Entry', 'goog.testing.fs.FileEntry'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.async.Deferred', 'goog.fs.DirectoryEntry', 'goog.fs.DirectoryEntryImpl', 'goog.fs.Entry', 'goog.fs.Error', 'goog.fs.FileEntry', 'goog.functions', 'goog.object', 'goog.string', 'goog.testing.fs.File', 'goog.testing.fs.FileWriter']);\ngoog.addDependency(\"testing/fs/entry_test.js\", ['goog.testing.fs.EntryTest'], ['goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.testing.MockClock', 'goog.testing.TestCase', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/file.js\", ['goog.testing.fs.File'], ['goog.testing.fs.Blob']);\ngoog.addDependency(\"testing/fs/fileentry_test.js\", ['goog.testing.fs.FileEntryTest'], ['goog.testing.MockClock', 'goog.testing.fs.FileEntry', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/filereader.js\", ['goog.testing.fs.FileReader'], ['goog.Timer', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.testing.fs.ProgressEvent']);\ngoog.addDependency(\"testing/fs/filereader_test.js\", ['goog.testing.fs.FileReaderTest'], ['goog.Promise', 'goog.array', 'goog.events', 'goog.fs.Error', 'goog.fs.FileReader', 'goog.object', 'goog.testing.events.EventObserver', 'goog.testing.fs.FileReader', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/filesystem.js\", ['goog.testing.fs.FileSystem'], ['goog.fs.FileSystem', 'goog.testing.fs.DirectoryEntry']);\ngoog.addDependency(\"testing/fs/filewriter.js\", ['goog.testing.fs.FileWriter'], ['goog.Timer', 'goog.events.EventTarget', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.string', 'goog.testing.fs.ProgressEvent']);\ngoog.addDependency(\"testing/fs/filewriter_test.js\", ['goog.testing.fs.FileWriterTest'], ['goog.Promise', 'goog.array', 'goog.events', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.object', 'goog.testing.MockClock', 'goog.testing.events.EventObserver', 'goog.testing.fs.Blob', 'goog.testing.fs.FileSystem', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/fs.js\", ['goog.testing.fs'], ['goog.Timer', 'goog.array', 'goog.async.Deferred', 'goog.fs', 'goog.testing.fs.Blob', 'goog.testing.fs.FileSystem']);\ngoog.addDependency(\"testing/fs/fs_test.js\", ['goog.testing.fsTest'], ['goog.testing.fs', 'goog.testing.fs.Blob', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/integration_test.js\", ['goog.testing.fs.integrationTest'], ['goog.Promise', 'goog.events', 'goog.fs', 'goog.fs.DirectoryEntry', 'goog.fs.Error', 'goog.fs.FileSaver', 'goog.testing.PropertyReplacer', 'goog.testing.fs', 'goog.testing.jsunit']);\ngoog.addDependency(\"testing/fs/progressevent.js\", ['goog.testing.fs.ProgressEvent'], ['goog.events.Event']);\ngoog.addDependency(\"testing/i18n/asserts.js\", ['goog.testing.i18n.asserts'], ['goog.testing.jsunit']);\ngoog.addDependency(\"testing/i18n/asserts_test.js\", ['goog.testing.i18n.assertsTest'], ['goog.testing.ExpectedFailures', 'goog.testing.i18n.asserts']);\ngoog.addDependency(\"testing/messaging/mockmessagechannel.js\", ['goog.testing.messaging.MockMessageChannel'], ['goog.messaging.AbstractChannel', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/messaging/mockmessageevent.js\", ['goog.testing.messaging.MockMessageEvent'], ['goog.events.BrowserEvent', 'goog.events.EventType', 'goog.testing.events.Event']);\ngoog.addDependency(\"testing/messaging/mockmessageport.js\", ['goog.testing.messaging.MockMessagePort'], ['goog.events.EventTarget']);\ngoog.addDependency(\"testing/messaging/mockportnetwork.js\", ['goog.testing.messaging.MockPortNetwork'], ['goog.messaging.PortNetwork', 'goog.testing.messaging.MockMessageChannel']);\ngoog.addDependency(\"testing/net/xhrio.js\", ['goog.testing.net.XhrIo'], ['goog.array', 'goog.dom.xml', 'goog.events', 'goog.events.EventTarget', 'goog.json', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.HttpStatus', 'goog.net.XhrIo', 'goog.net.XmlHttp', 'goog.object', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils']);\ngoog.addDependency(\"testing/net/xhrio_test.js\", ['goog.testing.net.XhrIoTest'], ['goog.dom.xml', 'goog.events', 'goog.events.Event', 'goog.net.ErrorCode', 'goog.net.EventType', 'goog.net.XmlHttp', 'goog.object', 'goog.testing.MockControl', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.mockmatchers.InstanceOf', 'goog.testing.net.XhrIo']);\ngoog.addDependency(\"testing/net/xhriopool.js\", ['goog.testing.net.XhrIoPool'], ['goog.net.XhrIoPool', 'goog.testing.net.XhrIo']);\ngoog.addDependency(\"testing/proto2/proto2.js\", ['goog.testing.proto2'], ['goog.proto2.Message', 'goog.proto2.ObjectSerializer', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/proto2/proto2_test.js\", ['goog.testing.proto2Test'], ['goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.proto2', 'proto2.TestAllTypes']);\ngoog.addDependency(\"testing/storage/fakemechanism.js\", ['goog.testing.storage.FakeMechanism'], ['goog.storage.mechanism.IterableMechanism', 'goog.structs.Map']);\ngoog.addDependency(\"testing/style/layoutasserts.js\", ['goog.testing.style.layoutasserts'], ['goog.style', 'goog.testing.asserts', 'goog.testing.style']);\ngoog.addDependency(\"testing/style/layoutasserts_test.js\", ['goog.testing.style.layoutassertsTest'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.style.layoutasserts']);\ngoog.addDependency(\"testing/style/style.js\", ['goog.testing.style'], ['goog.dom', 'goog.math.Rect', 'goog.style']);\ngoog.addDependency(\"testing/style/style_test.js\", ['goog.testing.styleTest'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.testing.jsunit', 'goog.testing.style']);\ngoog.addDependency(\"testing/ui/rendererasserts.js\", ['goog.testing.ui.rendererasserts'], ['goog.testing.asserts', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"testing/ui/rendererasserts_test.js\", ['goog.testing.ui.rendererassertsTest'], ['goog.testing.TestCase', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"testing/ui/rendererharness.js\", ['goog.testing.ui.RendererHarness'], ['goog.Disposable', 'goog.dom.NodeType', 'goog.testing.asserts', 'goog.testing.dom']);\ngoog.addDependency(\"testing/ui/style.js\", ['goog.testing.ui.style'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.testing.asserts']);\ngoog.addDependency(\"testing/ui/style_test.js\", ['goog.testing.ui.styleTest'], ['goog.dom', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.testing.ui.style']);\ngoog.addDependency(\"timer/timer.js\", ['goog.Timer'], ['goog.Promise', 'goog.events.EventTarget']);\ngoog.addDependency(\"timer/timer_test.js\", ['goog.TimerTest'], ['goog.Promise', 'goog.Timer', 'goog.events', 'goog.testing.MockClock', 'goog.testing.jsunit']);\ngoog.addDependency(\"tweak/entries.js\", ['goog.tweak.BaseEntry', 'goog.tweak.BasePrimitiveSetting', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting'], ['goog.array', 'goog.asserts', 'goog.log', 'goog.object']);\ngoog.addDependency(\"tweak/entries_test.js\", ['goog.tweak.BaseEntryTest'], ['goog.testing.MockControl', 'goog.testing.jsunit', 'goog.tweak.testhelpers']);\ngoog.addDependency(\"tweak/registry.js\", ['goog.tweak.Registry'], ['goog.array', 'goog.asserts', 'goog.log', 'goog.string', 'goog.tweak.BasePrimitiveSetting', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting', 'goog.uri.utils']);\ngoog.addDependency(\"tweak/registry_test.js\", ['goog.tweak.RegistryTest'], ['goog.asserts.AssertionError', 'goog.testing.jsunit', 'goog.tweak', 'goog.tweak.testhelpers']);\ngoog.addDependency(\"tweak/testhelpers.js\", ['goog.tweak.testhelpers'], ['goog.tweak', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.Registry', 'goog.tweak.StringSetting']);\ngoog.addDependency(\"tweak/tweak.js\", ['goog.tweak', 'goog.tweak.ConfigParams'], ['goog.asserts', 'goog.tweak.BaseSetting', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.Registry', 'goog.tweak.StringSetting']);\ngoog.addDependency(\"tweak/tweakui.js\", ['goog.tweak.EntriesPanel', 'goog.tweak.TweakUi'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.object', 'goog.string.Const', 'goog.style', 'goog.tweak', 'goog.tweak.BaseEntry', 'goog.tweak.BooleanGroup', 'goog.tweak.BooleanInGroupSetting', 'goog.tweak.BooleanSetting', 'goog.tweak.ButtonAction', 'goog.tweak.NumericSetting', 'goog.tweak.StringSetting', 'goog.ui.Zippy', 'goog.userAgent']);\ngoog.addDependency(\"tweak/tweakui_test.js\", ['goog.tweak.TweakUiTest'], ['goog.dom', 'goog.dom.TagName', 'goog.string', 'goog.testing.jsunit', 'goog.tweak', 'goog.tweak.TweakUi', 'goog.tweak.testhelpers']);\ngoog.addDependency(\"ui/abstractspellchecker.js\", ['goog.ui.AbstractSpellChecker', 'goog.ui.AbstractSpellChecker.AsyncResult'], ['goog.a11y.aria', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.selection', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.spell.SpellCheck', 'goog.structs.Set', 'goog.style', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuSeparator', 'goog.ui.PopupMenu']);\ngoog.addDependency(\"ui/activitymonitor.js\", ['goog.ui.ActivityMonitor'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType']);\ngoog.addDependency(\"ui/activitymonitor_test.js\", ['goog.ui.ActivityMonitorTest'], ['goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.ActivityMonitor']);\ngoog.addDependency(\"ui/advancedtooltip.js\", ['goog.ui.AdvancedTooltip'], ['goog.events', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.ui.Tooltip', 'goog.userAgent']);\ngoog.addDependency(\"ui/advancedtooltip_test.js\", ['goog.ui.AdvancedTooltipTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events.Event', 'goog.events.EventType', 'goog.math.Box', 'goog.math.Coordinate', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.AdvancedTooltip', 'goog.ui.Tooltip', 'goog.userAgent']);\ngoog.addDependency(\"ui/animatedzippy.js\", ['goog.ui.AnimatedZippy'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.fx.easing', 'goog.ui.Zippy', 'goog.ui.ZippyEvent']);\ngoog.addDependency(\"ui/animatedzippy_test.js\", ['goog.ui.AnimatedZippyTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events', 'goog.functions', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.testing.PropertyReplacer', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.ui.AnimatedZippy', 'goog.ui.Zippy']);\ngoog.addDependency(\"ui/attachablemenu.js\", ['goog.ui.AttachableMenu'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.string', 'goog.style', 'goog.ui.ItemEvent', 'goog.ui.MenuBase', 'goog.ui.PopupBase', 'goog.userAgent']);\ngoog.addDependency(\"ui/bidiinput.js\", ['goog.ui.BidiInput'], ['goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.InputHandler', 'goog.i18n.bidi', 'goog.ui.Component']);\ngoog.addDependency(\"ui/bidiinput_test.js\", ['goog.ui.BidiInputTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.BidiInput']);\ngoog.addDependency(\"ui/bubble.js\", ['goog.ui.Bubble'], ['goog.Timer', 'goog.dom.safe', 'goog.events', 'goog.events.EventType', 'goog.html.SafeHtml', 'goog.math.Box', 'goog.positioning', 'goog.positioning.AbsolutePosition', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.CornerBit', 'goog.string.Const', 'goog.style', 'goog.ui.Component', 'goog.ui.Popup']);\ngoog.addDependency(\"ui/button.js\", ['goog.ui.Button', 'goog.ui.Button.Side'], ['goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.NativeButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/button_test.js\", ['goog.ui.ButtonTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.NativeButtonRenderer']);\ngoog.addDependency(\"ui/buttonrenderer.js\", ['goog.ui.ButtonRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"ui/buttonrenderer_test.js\", ['goog.ui.ButtonRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.ExpectedFailures', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.ButtonSide', 'goog.ui.Component']);\ngoog.addDependency(\"ui/buttonside.js\", ['goog.ui.ButtonSide'], []);\ngoog.addDependency(\"ui/charcounter.js\", ['goog.ui.CharCounter', 'goog.ui.CharCounter.Display'], ['goog.dom', 'goog.events', 'goog.events.EventTarget', 'goog.events.InputHandler']);\ngoog.addDependency(\"ui/charcounter_test.js\", ['goog.ui.CharCounterTest'], ['goog.dom', 'goog.testing.asserts', 'goog.testing.jsunit', 'goog.ui.CharCounter', 'goog.userAgent']);\ngoog.addDependency(\"ui/charpicker.js\", ['goog.ui.CharPicker'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.i18n.CharListDecompressor', 'goog.i18n.uChar', 'goog.structs.Set', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.ContainerScroller', 'goog.ui.FlatButtonRenderer', 'goog.ui.HoverCard', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.Tooltip']);\ngoog.addDependency(\"ui/charpicker_test.js\", ['goog.ui.CharPickerTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dispose', 'goog.dom', 'goog.events.Event', 'goog.events.EventType', 'goog.i18n.CharPickerData', 'goog.i18n.uChar.NameFetcher', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.CharPicker', 'goog.ui.FlatButtonRenderer']);\ngoog.addDependency(\"ui/checkbox.js\", ['goog.ui.Checkbox', 'goog.ui.Checkbox.State'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.string', 'goog.ui.CheckboxRenderer', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.registry']);\ngoog.addDependency(\"ui/checkbox_test.js\", ['goog.ui.CheckboxTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.KeyCodes', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Checkbox', 'goog.ui.CheckboxRenderer', 'goog.ui.Component', 'goog.ui.ControlRenderer', 'goog.ui.decorate']);\ngoog.addDependency(\"ui/checkboxmenuitem.js\", ['goog.ui.CheckBoxMenuItem'], ['goog.ui.MenuItem', 'goog.ui.registry']);\ngoog.addDependency(\"ui/checkboxrenderer.js\", ['goog.ui.CheckboxRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.object', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"ui/colorbutton.js\", ['goog.ui.ColorButton'], ['goog.ui.Button', 'goog.ui.ColorButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/colorbutton_test.js\", ['goog.ui.ColorButtonTest'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.ColorButton', 'goog.ui.decorate']);\ngoog.addDependency(\"ui/colorbuttonrenderer.js\", ['goog.ui.ColorButtonRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.functions', 'goog.ui.ColorMenuButtonRenderer']);\ngoog.addDependency(\"ui/colormenubutton.js\", ['goog.ui.ColorMenuButton'], ['goog.array', 'goog.object', 'goog.ui.ColorMenuButtonRenderer', 'goog.ui.ColorPalette', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.registry']);\ngoog.addDependency(\"ui/colormenubuttonrenderer.js\", ['goog.ui.ColorMenuButtonRenderer'], ['goog.asserts', 'goog.color', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.MenuButtonRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/colormenubuttonrenderer_test.js\", ['goog.ui.ColorMenuButtonTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.testing.ui.RendererHarness', 'goog.testing.ui.rendererasserts', 'goog.ui.ColorMenuButton', 'goog.ui.ColorMenuButtonRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/colorpalette.js\", ['goog.ui.ColorPalette'], ['goog.array', 'goog.color', 'goog.dom.TagName', 'goog.style', 'goog.ui.Palette', 'goog.ui.PaletteRenderer']);\ngoog.addDependency(\"ui/colorpalette_test.js\", ['goog.ui.ColorPaletteTest'], ['goog.color', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.ColorPalette']);\ngoog.addDependency(\"ui/colorpicker.js\", ['goog.ui.ColorPicker', 'goog.ui.ColorPicker.EventType'], ['goog.ui.ColorPalette', 'goog.ui.Component']);\ngoog.addDependency(\"ui/colorsplitbehavior.js\", ['goog.ui.ColorSplitBehavior'], ['goog.ui.ColorMenuButton', 'goog.ui.SplitBehavior']);\ngoog.addDependency(\"ui/combobox.js\", ['goog.ui.ComboBox', 'goog.ui.ComboBoxItem'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.log', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.ItemEvent', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.MenuSeparator', 'goog.ui.registry', 'goog.userAgent']);\ngoog.addDependency(\"ui/combobox_test.js\", ['goog.ui.ComboBoxTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.ComboBox', 'goog.ui.ComboBoxItem', 'goog.ui.Component', 'goog.ui.ControlRenderer', 'goog.ui.LabelInput', 'goog.ui.Menu', 'goog.ui.MenuItem']);\ngoog.addDependency(\"ui/component.js\", ['goog.ui.Component', 'goog.ui.Component.Error', 'goog.ui.Component.EventType', 'goog.ui.Component.State'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.object', 'goog.style', 'goog.ui.IdGenerator']);\ngoog.addDependency(\"ui/component_test.js\", ['goog.ui.ComponentTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.events.EventTarget', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component']);\ngoog.addDependency(\"ui/container.js\", ['goog.ui.Container', 'goog.ui.Container.EventType', 'goog.ui.Container.Orientation'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.object', 'goog.style', 'goog.ui.Component', 'goog.ui.ContainerRenderer', 'goog.ui.Control']);\ngoog.addDependency(\"ui/container_test.js\", ['goog.ui.ContainerTest'], ['goog.a11y.aria', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.events.KeyEvent', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Control']);\ngoog.addDependency(\"ui/containerrenderer.js\", ['goog.ui.ContainerRenderer'], ['goog.a11y.aria', 'goog.array', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.string', 'goog.style', 'goog.ui.registry', 'goog.userAgent']);\ngoog.addDependency(\"ui/containerrenderer_test.js\", ['goog.ui.ContainerRendererTest'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Container', 'goog.ui.ContainerRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/containerscroller.js\", ['goog.ui.ContainerScroller'], ['goog.Disposable', 'goog.Timer', 'goog.events.EventHandler', 'goog.style', 'goog.ui.Component', 'goog.ui.Container']);\ngoog.addDependency(\"ui/containerscroller_test.js\", ['goog.ui.ContainerScrollerTest'], ['goog.dom', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Container', 'goog.ui.ContainerScroller']);\ngoog.addDependency(\"ui/control.js\", ['goog.ui.Control'], ['goog.Disposable', 'goog.array', 'goog.dom', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.string', 'goog.ui.Component', 'goog.ui.ControlContent', 'goog.ui.ControlRenderer', 'goog.ui.decorate', 'goog.ui.registry', 'goog.userAgent']);\ngoog.addDependency(\"ui/control_test.js\", ['goog.ui.ControlTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer', 'goog.ui.registry', 'goog.userAgent']);\ngoog.addDependency(\"ui/controlcontent.js\", ['goog.ui.ControlContent'], []);\ngoog.addDependency(\"ui/controlrenderer.js\", ['goog.ui.ControlRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.object', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.userAgent']);\ngoog.addDependency(\"ui/controlrenderer_test.js\", ['goog.ui.ControlRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.object', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/cookieeditor.js\", ['goog.ui.CookieEditor'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.events.EventType', 'goog.net.cookies', 'goog.string', 'goog.style', 'goog.ui.Component']);\ngoog.addDependency(\"ui/cookieeditor_test.js\", ['goog.ui.CookieEditorTest'], ['goog.dom', 'goog.events.Event', 'goog.events.EventType', 'goog.net.cookies', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.CookieEditor']);\ngoog.addDependency(\"ui/css3buttonrenderer.js\", ['goog.ui.Css3ButtonRenderer'], ['goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.Component', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry']);\ngoog.addDependency(\"ui/css3menubuttonrenderer.js\", ['goog.ui.Css3MenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/cssnames.js\", ['goog.ui.INLINE_BLOCK_CLASSNAME'], []);\ngoog.addDependency(\"ui/custombutton.js\", ['goog.ui.CustomButton'], ['goog.ui.Button', 'goog.ui.CustomButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/custombuttonrenderer.js\", ['goog.ui.CustomButtonRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.string', 'goog.ui.ButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME']);\ngoog.addDependency(\"ui/customcolorpalette.js\", ['goog.ui.CustomColorPalette'], ['goog.color', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.ColorPalette', 'goog.ui.Component']);\ngoog.addDependency(\"ui/customcolorpalette_test.js\", ['goog.ui.CustomColorPaletteTest'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.CustomColorPalette']);\ngoog.addDependency(\"ui/datepicker.js\", ['goog.ui.DatePicker', 'goog.ui.DatePicker.Events', 'goog.ui.DatePickerEvent'], ['goog.a11y.aria', 'goog.asserts', 'goog.date.Date', 'goog.date.DateRange', 'goog.date.Interval', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimePatterns', 'goog.i18n.DateTimeSymbols', 'goog.style', 'goog.ui.Component', 'goog.ui.DefaultDatePickerRenderer', 'goog.ui.IdGenerator']);\ngoog.addDependency(\"ui/datepicker_test.js\", ['goog.ui.DatePickerTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.date.Date', 'goog.date.DateRange', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.KeyCodes', 'goog.i18n.DateTimeSymbols', 'goog.i18n.DateTimeSymbols_en_US', 'goog.i18n.DateTimeSymbols_zh_HK', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.DatePicker']);\ngoog.addDependency(\"ui/datepickerrenderer.js\", ['goog.ui.DatePickerRenderer'], []);\ngoog.addDependency(\"ui/decorate.js\", ['goog.ui.decorate'], ['goog.ui.registry']);\ngoog.addDependency(\"ui/decorate_test.js\", ['goog.ui.decorateTest'], ['goog.testing.jsunit', 'goog.ui.decorate', 'goog.ui.registry']);\ngoog.addDependency(\"ui/defaultdatepickerrenderer.js\", ['goog.ui.DefaultDatePickerRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.DatePickerRenderer']);\ngoog.addDependency(\"ui/dialog.js\", ['goog.ui.Dialog', 'goog.ui.Dialog.ButtonSet', 'goog.ui.Dialog.ButtonSet.DefaultButtons', 'goog.ui.Dialog.DefaultButtonCaptions', 'goog.ui.Dialog.DefaultButtonKeys', 'goog.ui.Dialog.Event', 'goog.ui.Dialog.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.safe', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Dragger', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.math.Rect', 'goog.string', 'goog.structs.Map', 'goog.style', 'goog.ui.ModalPopup']);\ngoog.addDependency(\"ui/dialog_test.js\", ['goog.ui.DialogTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.css3', 'goog.html.SafeHtml', 'goog.html.testing', 'goog.style', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Dialog', 'goog.userAgent']);\ngoog.addDependency(\"ui/dimensionpicker.js\", ['goog.ui.DimensionPicker'], ['goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.DimensionPickerRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/dimensionpicker_test.js\", ['goog.ui.DimensionPickerTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.DimensionPicker', 'goog.ui.DimensionPickerRenderer']);\ngoog.addDependency(\"ui/dimensionpickerrenderer.js\", ['goog.ui.DimensionPickerRenderer'], ['goog.a11y.aria.Announcer', 'goog.a11y.aria.LivePriority', 'goog.dom', 'goog.dom.TagName', 'goog.i18n.bidi', 'goog.style', 'goog.ui.ControlRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/dimensionpickerrenderer_test.js\", ['goog.ui.DimensionPickerRendererTest'], ['goog.a11y.aria.LivePriority', 'goog.array', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.DimensionPicker', 'goog.ui.DimensionPickerRenderer']);\ngoog.addDependency(\"ui/dragdropdetector.js\", ['goog.ui.DragDropDetector', 'goog.ui.DragDropDetector.EventType', 'goog.ui.DragDropDetector.ImageDropEvent', 'goog.ui.DragDropDetector.LinkDropEvent'], ['goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"ui/drilldownrow.js\", ['goog.ui.DrilldownRow'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.string.Unicode', 'goog.ui.Component']);\ngoog.addDependency(\"ui/drilldownrow_test.js\", ['goog.ui.DrilldownRowTest'], ['goog.dom', 'goog.dom.TagName', 'goog.html.SafeHtml', 'goog.testing.jsunit', 'goog.ui.DrilldownRow']);\ngoog.addDependency(\"ui/filteredmenu.js\", ['goog.ui.FilteredMenu'], ['goog.a11y.aria', 'goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.object', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.FilterObservingMenuItem', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.userAgent']);\ngoog.addDependency(\"ui/filteredmenu_test.js\", ['goog.ui.FilteredMenuTest'], ['goog.a11y.aria', 'goog.a11y.aria.AutoCompleteValues', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Rect', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.FilteredMenu', 'goog.ui.MenuItem']);\ngoog.addDependency(\"ui/filterobservingmenuitem.js\", ['goog.ui.FilterObservingMenuItem'], ['goog.ui.FilterObservingMenuItemRenderer', 'goog.ui.MenuItem', 'goog.ui.registry']);\ngoog.addDependency(\"ui/filterobservingmenuitemrenderer.js\", ['goog.ui.FilterObservingMenuItemRenderer'], ['goog.ui.MenuItemRenderer']);\ngoog.addDependency(\"ui/flatbuttonrenderer.js\", ['goog.ui.FlatButtonRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.ButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry']);\ngoog.addDependency(\"ui/flatmenubuttonrenderer.js\", ['goog.ui.FlatMenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.ui.FlatButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/formpost.js\", ['goog.ui.FormPost'], ['goog.array', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeHtml', 'goog.ui.Component']);\ngoog.addDependency(\"ui/formpost_test.js\", ['goog.ui.FormPostTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.object', 'goog.testing.jsunit', 'goog.ui.FormPost', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"ui/gauge.js\", ['goog.ui.Gauge', 'goog.ui.GaugeColoredRange'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom.TagName', 'goog.events', 'goog.fx.Animation', 'goog.fx.Transition', 'goog.fx.easing', 'goog.graphics', 'goog.graphics.Font', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.math', 'goog.ui.Component', 'goog.ui.GaugeTheme']);\ngoog.addDependency(\"ui/gaugetheme.js\", ['goog.ui.GaugeTheme'], ['goog.graphics.LinearGradient', 'goog.graphics.SolidFill', 'goog.graphics.Stroke']);\ngoog.addDependency(\"ui/hovercard.js\", ['goog.ui.HoverCard', 'goog.ui.HoverCard.EventType', 'goog.ui.HoverCard.TriggerEvent'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.ui.AdvancedTooltip', 'goog.ui.PopupBase', 'goog.ui.Tooltip']);\ngoog.addDependency(\"ui/hovercard_test.js\", ['goog.ui.HoverCardTest'], ['goog.dom', 'goog.events', 'goog.math.Coordinate', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.HoverCard']);\ngoog.addDependency(\"ui/hsvapalette.js\", ['goog.ui.HsvaPalette'], ['goog.array', 'goog.color.alpha', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.HsvPalette']);\ngoog.addDependency(\"ui/hsvapalette_test.js\", ['goog.ui.HsvaPaletteTest'], ['goog.color.alpha', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.Event', 'goog.math.Coordinate', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.HsvaPalette', 'goog.userAgent']);\ngoog.addDependency(\"ui/hsvpalette.js\", ['goog.ui.HsvPalette'], ['goog.color', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.events.InputHandler', 'goog.style', 'goog.style.bidi', 'goog.ui.Component', 'goog.userAgent']);\ngoog.addDependency(\"ui/hsvpalette_test.js\", ['goog.ui.HsvPaletteTest'], ['goog.color', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.math.Coordinate', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.HsvPalette', 'goog.userAgent']);\ngoog.addDependency(\"ui/idgenerator.js\", ['goog.ui.IdGenerator'], []);\ngoog.addDependency(\"ui/idletimer.js\", ['goog.ui.IdleTimer'], ['goog.Timer', 'goog.events', 'goog.events.EventTarget', 'goog.structs.Set', 'goog.ui.ActivityMonitor']);\ngoog.addDependency(\"ui/idletimer_test.js\", ['goog.ui.IdleTimerTest'], ['goog.events', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.IdleTimer', 'goog.ui.MockActivityMonitor']);\ngoog.addDependency(\"ui/iframemask.js\", ['goog.ui.IframeMask'], ['goog.Disposable', 'goog.Timer', 'goog.dom', 'goog.dom.iframe', 'goog.events.EventHandler', 'goog.style']);\ngoog.addDependency(\"ui/iframemask_test.js\", ['goog.ui.IframeMaskTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.iframe', 'goog.structs.Pool', 'goog.style', 'goog.testing.MockClock', 'goog.testing.StrictMock', 'goog.testing.jsunit', 'goog.ui.IframeMask', 'goog.ui.Popup', 'goog.ui.PopupBase', 'goog.userAgent']);\ngoog.addDependency(\"ui/imagelessbuttonrenderer.js\", ['goog.ui.ImagelessButtonRenderer'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry']);\ngoog.addDependency(\"ui/imagelessmenubuttonrenderer.js\", ['goog.ui.ImagelessMenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/inputdatepicker.js\", ['goog.ui.InputDatePicker'], ['goog.date.DateTime', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.string', 'goog.ui.Component', 'goog.ui.DatePicker', 'goog.ui.LabelInput', 'goog.ui.PopupBase', 'goog.ui.PopupDatePicker']);\ngoog.addDependency(\"ui/inputdatepicker_test.js\", ['goog.ui.InputDatePickerTest'], ['goog.dom', 'goog.i18n.DateTimeFormat', 'goog.i18n.DateTimeParse', 'goog.testing.jsunit', 'goog.ui.InputDatePicker']);\ngoog.addDependency(\"ui/itemevent.js\", ['goog.ui.ItemEvent'], ['goog.events.Event']);\ngoog.addDependency(\"ui/keyboardshortcuthandler.js\", ['goog.ui.KeyboardShortcutEvent', 'goog.ui.KeyboardShortcutHandler', 'goog.ui.KeyboardShortcutHandler.EventType'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyNames', 'goog.object', 'goog.userAgent']);\ngoog.addDependency(\"ui/keyboardshortcuthandler_test.js\", ['goog.ui.KeyboardShortcutHandlerTest'], ['goog.dom', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.KeyCodes', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.StrictMock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.KeyboardShortcutHandler', 'goog.userAgent']);\ngoog.addDependency(\"ui/labelinput.js\", ['goog.ui.LabelInput'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.ui.Component', 'goog.userAgent']);\ngoog.addDependency(\"ui/labelinput_test.js\", ['goog.ui.LabelInputTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.LabelInput', 'goog.userAgent']);\ngoog.addDependency(\"ui/linkbuttonrenderer.js\", ['goog.ui.LinkButtonRenderer'], ['goog.ui.Button', 'goog.ui.FlatButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/menu.js\", ['goog.ui.Menu', 'goog.ui.Menu.EventType'], ['goog.dom.TagName', 'goog.math.Coordinate', 'goog.string', 'goog.style', 'goog.ui.Component.EventType', 'goog.ui.Component.State', 'goog.ui.Container', 'goog.ui.Container.Orientation', 'goog.ui.MenuHeader', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.MenuSeparator']);\ngoog.addDependency(\"ui/menu_test.js\", ['goog.ui.MenuTest'], ['goog.dom', 'goog.events', 'goog.math.Coordinate', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Menu']);\ngoog.addDependency(\"ui/menubar.js\", ['goog.ui.menuBar'], ['goog.ui.Container', 'goog.ui.MenuBarRenderer']);\ngoog.addDependency(\"ui/menubardecorator.js\", ['goog.ui.menuBarDecorator'], ['goog.ui.MenuBarRenderer', 'goog.ui.menuBar', 'goog.ui.registry']);\ngoog.addDependency(\"ui/menubarrenderer.js\", ['goog.ui.MenuBarRenderer'], ['goog.a11y.aria.Role', 'goog.ui.Container', 'goog.ui.ContainerRenderer']);\ngoog.addDependency(\"ui/menubase.js\", ['goog.ui.MenuBase'], ['goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyHandler', 'goog.ui.Popup']);\ngoog.addDependency(\"ui/menubutton.js\", ['goog.ui.MenuButton'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.math.Box', 'goog.math.Rect', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.IdGenerator', 'goog.ui.Menu', 'goog.ui.MenuButtonRenderer', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.registry', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"ui/menubutton_test.js\", ['goog.ui.MenuButtonTest'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.PropertyReplacer', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.SubMenu', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"ui/menubuttonrenderer.js\", ['goog.ui.MenuButtonRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.Menu', 'goog.ui.MenuRenderer']);\ngoog.addDependency(\"ui/menubuttonrenderer_test.js\", ['goog.ui.MenuButtonRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.MenuButton', 'goog.ui.MenuButtonRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/menuheader.js\", ['goog.ui.MenuHeader'], ['goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuHeaderRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/menuheaderrenderer.js\", ['goog.ui.MenuHeaderRenderer'], ['goog.ui.ControlRenderer']);\ngoog.addDependency(\"ui/menuitem.js\", ['goog.ui.MenuItem'], ['goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.dom.classlist', 'goog.math.Coordinate', 'goog.string', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuItemRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/menuitem_test.js\", ['goog.ui.MenuItemTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.math.Coordinate', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuItemRenderer']);\ngoog.addDependency(\"ui/menuitemrenderer.js\", ['goog.ui.MenuItemRenderer'], ['goog.a11y.aria.Role', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Component', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"ui/menuitemrenderer_test.js\", ['goog.ui.MenuItemRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.MenuItemRenderer']);\ngoog.addDependency(\"ui/menurenderer.js\", ['goog.ui.MenuRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.ui.ContainerRenderer', 'goog.ui.Separator']);\ngoog.addDependency(\"ui/menuseparator.js\", ['goog.ui.MenuSeparator'], ['goog.ui.MenuSeparatorRenderer', 'goog.ui.Separator', 'goog.ui.registry']);\ngoog.addDependency(\"ui/menuseparatorrenderer.js\", ['goog.ui.MenuSeparatorRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"ui/menuseparatorrenderer_test.js\", ['goog.ui.MenuSeparatorRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.MenuSeparator', 'goog.ui.MenuSeparatorRenderer']);\ngoog.addDependency(\"ui/mockactivitymonitor.js\", ['goog.ui.MockActivityMonitor'], ['goog.events.EventType', 'goog.ui.ActivityMonitor']);\ngoog.addDependency(\"ui/mockactivitymonitor_test.js\", ['goog.ui.MockActivityMonitorTest'], ['goog.events', 'goog.functions', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.ActivityMonitor', 'goog.ui.MockActivityMonitor']);\ngoog.addDependency(\"ui/modalariavisibilityhelper.js\", ['goog.ui.ModalAriaVisibilityHelper'], ['goog.a11y.aria', 'goog.a11y.aria.State']);\ngoog.addDependency(\"ui/modalariavisibilityhelper_test.js\", ['goog.ui.ModalAriaVisibilityHelperTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.string', 'goog.testing.jsunit', 'goog.ui.ModalAriaVisibilityHelper']);\ngoog.addDependency(\"ui/modalpopup.js\", ['goog.ui.ModalPopup'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.dom.iframe', 'goog.events', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.fx.Transition', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.ModalAriaVisibilityHelper', 'goog.ui.PopupBase', 'goog.userAgent']);\ngoog.addDependency(\"ui/modalpopup_test.js\", ['goog.ui.ModalPopupTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dispose', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventTarget', 'goog.fx.Transition', 'goog.fx.css3', 'goog.string', 'goog.style', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ModalPopup', 'goog.ui.PopupBase']);\ngoog.addDependency(\"ui/nativebuttonrenderer.js\", ['goog.ui.NativeButtonRenderer'], ['goog.asserts', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.ui.ButtonRenderer', 'goog.ui.Component']);\ngoog.addDependency(\"ui/nativebuttonrenderer_test.js\", ['goog.ui.NativeButtonRendererTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.testing.ExpectedFailures', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.NativeButtonRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/option.js\", ['goog.ui.Option'], ['goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.registry']);\ngoog.addDependency(\"ui/palette.js\", ['goog.ui.Palette'], ['goog.array', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Size', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.PaletteRenderer', 'goog.ui.SelectionModel']);\ngoog.addDependency(\"ui/palette_test.js\", ['goog.ui.PaletteTest'], ['goog.a11y.aria', 'goog.dom', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyEvent', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Palette']);\ngoog.addDependency(\"ui/paletterenderer.js\", ['goog.ui.PaletteRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeIterator', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.iter', 'goog.style', 'goog.ui.ControlRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/paletterenderer_test.js\", ['goog.ui.PaletteRendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.Palette', 'goog.ui.PaletteRenderer']);\ngoog.addDependency(\"ui/plaintextspellchecker.js\", ['goog.ui.PlainTextSpellChecker'], ['goog.Timer', 'goog.a11y.aria', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.spell.SpellCheck', 'goog.style', 'goog.ui.AbstractSpellChecker', 'goog.ui.Component', 'goog.userAgent']);\ngoog.addDependency(\"ui/plaintextspellchecker_test.js\", ['goog.ui.PlainTextSpellCheckerTest'], ['goog.Timer', 'goog.dom', 'goog.events.KeyCodes', 'goog.spell.SpellCheck', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.PlainTextSpellChecker']);\ngoog.addDependency(\"ui/popup.js\", ['goog.ui.Popup'], ['goog.math.Box', 'goog.positioning.Corner', 'goog.style', 'goog.ui.PopupBase']);\ngoog.addDependency(\"ui/popup_test.js\", ['goog.ui.PopupTest'], ['goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.style', 'goog.testing.jsunit', 'goog.ui.Popup', 'goog.userAgent']);\ngoog.addDependency(\"ui/popupbase.js\", ['goog.ui.PopupBase', 'goog.ui.PopupBase.EventType', 'goog.ui.PopupBase.Type'], ['goog.Timer', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Transition', 'goog.style', 'goog.userAgent']);\ngoog.addDependency(\"ui/popupbase_test.js\", ['goog.ui.PopupBaseTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Transition', 'goog.fx.css3', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.PopupBase']);\ngoog.addDependency(\"ui/popupcolorpicker.js\", ['goog.ui.PopupColorPicker'], ['goog.asserts', 'goog.dom.classlist', 'goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.ui.ColorPicker', 'goog.ui.Component', 'goog.ui.Popup']);\ngoog.addDependency(\"ui/popupcolorpicker_test.js\", ['goog.ui.PopupColorPickerTest'], ['goog.dom', 'goog.events', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.ColorPicker', 'goog.ui.PopupColorPicker']);\ngoog.addDependency(\"ui/popupdatepicker.js\", ['goog.ui.PopupDatePicker'], ['goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.style', 'goog.ui.Component', 'goog.ui.DatePicker', 'goog.ui.Popup', 'goog.ui.PopupBase']);\ngoog.addDependency(\"ui/popupdatepicker_test.js\", ['goog.ui.PopupDatePickerTest'], ['goog.date.Date', 'goog.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.PopupBase', 'goog.ui.PopupDatePicker']);\ngoog.addDependency(\"ui/popupmenu.js\", ['goog.ui.PopupMenu'], ['goog.events', 'goog.events.BrowserEvent', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.positioning.MenuAnchoredPosition', 'goog.positioning.Overflow', 'goog.positioning.ViewportClientPosition', 'goog.structs.Map', 'goog.style', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.PopupBase', 'goog.userAgent']);\ngoog.addDependency(\"ui/popupmenu_test.js\", ['goog.ui.PopupMenuTest'], ['goog.dom', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.math.Box', 'goog.math.Coordinate', 'goog.positioning.Corner', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.PopupMenu']);\ngoog.addDependency(\"ui/progressbar.js\", ['goog.ui.ProgressBar', 'goog.ui.ProgressBar.Orientation'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.ui.Component', 'goog.ui.RangeModel', 'goog.userAgent']);\ngoog.addDependency(\"ui/prompt.js\", ['goog.ui.Prompt'], ['goog.Timer', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.functions', 'goog.html.SafeHtml', 'goog.html.legacyconversions', 'goog.ui.Component', 'goog.ui.Dialog', 'goog.userAgent']);\ngoog.addDependency(\"ui/prompt_test.js\", ['goog.ui.PromptTest'], ['goog.dom.selection', 'goog.events.InputHandler', 'goog.events.KeyCodes', 'goog.functions', 'goog.string', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.BidiInput', 'goog.ui.Dialog', 'goog.ui.Prompt', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"ui/rangemodel.js\", ['goog.ui.RangeModel'], ['goog.events.EventTarget', 'goog.ui.Component']);\ngoog.addDependency(\"ui/rangemodel_test.js\", ['goog.ui.RangeModelTest'], ['goog.testing.jsunit', 'goog.ui.RangeModel']);\ngoog.addDependency(\"ui/ratings.js\", ['goog.ui.Ratings', 'goog.ui.Ratings.EventType'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.ui.Component']);\ngoog.addDependency(\"ui/registry.js\", ['goog.ui.registry'], ['goog.asserts', 'goog.dom.classlist']);\ngoog.addDependency(\"ui/registry_test.js\", ['goog.ui.registryTest'], ['goog.object', 'goog.testing.jsunit', 'goog.ui.registry']);\ngoog.addDependency(\"ui/richtextspellchecker.js\", ['goog.ui.RichTextSpellChecker'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.Range', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.math.Coordinate', 'goog.spell.SpellCheck', 'goog.string.StringBuffer', 'goog.style', 'goog.ui.AbstractSpellChecker', 'goog.ui.Component', 'goog.ui.PopupMenu']);\ngoog.addDependency(\"ui/richtextspellchecker_test.js\", ['goog.ui.RichTextSpellCheckerTest'], ['goog.dom.Range', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.object', 'goog.spell.SpellCheck', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.RichTextSpellChecker']);\ngoog.addDependency(\"ui/roundedpanel.js\", ['goog.ui.BaseRoundedPanel', 'goog.ui.CssRoundedPanel', 'goog.ui.GraphicsRoundedPanel', 'goog.ui.RoundedPanel', 'goog.ui.RoundedPanel.Corner'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.graphics', 'goog.graphics.Path', 'goog.graphics.SolidFill', 'goog.graphics.Stroke', 'goog.math', 'goog.math.Coordinate', 'goog.style', 'goog.ui.Component', 'goog.userAgent']);\ngoog.addDependency(\"ui/roundedpanel_test.js\", ['goog.ui.RoundedPanelTest'], ['goog.testing.jsunit', 'goog.ui.CssRoundedPanel', 'goog.ui.GraphicsRoundedPanel', 'goog.ui.RoundedPanel', 'goog.userAgent']);\ngoog.addDependency(\"ui/roundedtabrenderer.js\", ['goog.ui.RoundedTabRenderer'], ['goog.dom', 'goog.dom.TagName', 'goog.ui.Tab', 'goog.ui.TabBar', 'goog.ui.TabRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/scrollfloater.js\", ['goog.ui.ScrollFloater', 'goog.ui.ScrollFloater.EventType'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.userAgent']);\ngoog.addDependency(\"ui/scrollfloater_test.js\", ['goog.ui.ScrollFloaterTest'], ['goog.dom', 'goog.events', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.ScrollFloater']);\ngoog.addDependency(\"ui/select.js\", ['goog.ui.Select'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.events.EventType', 'goog.ui.Component', 'goog.ui.IdGenerator', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.MenuRenderer', 'goog.ui.SelectionModel', 'goog.ui.registry']);\ngoog.addDependency(\"ui/select_test.js\", ['goog.ui.SelectTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.Select', 'goog.ui.Separator']);\ngoog.addDependency(\"ui/selectionmenubutton.js\", ['goog.ui.SelectionMenuButton', 'goog.ui.SelectionMenuButton.SelectionState'], ['goog.dom.InputType', 'goog.dom.TagName', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.registry']);\ngoog.addDependency(\"ui/selectionmenubutton_test.js\", ['goog.ui.SelectionMenuButtonTest'], ['goog.dom', 'goog.events', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.SelectionMenuButton']);\ngoog.addDependency(\"ui/selectionmodel.js\", ['goog.ui.SelectionModel'], ['goog.array', 'goog.events.EventTarget', 'goog.events.EventType']);\ngoog.addDependency(\"ui/selectionmodel_test.js\", ['goog.ui.SelectionModelTest'], ['goog.array', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.SelectionModel']);\ngoog.addDependency(\"ui/separator.js\", ['goog.ui.Separator'], ['goog.a11y.aria', 'goog.asserts', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.MenuSeparatorRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/serverchart.js\", ['goog.ui.ServerChart', 'goog.ui.ServerChart.AxisDisplayType', 'goog.ui.ServerChart.ChartType', 'goog.ui.ServerChart.EncodingType', 'goog.ui.ServerChart.Event', 'goog.ui.ServerChart.LegendPosition', 'goog.ui.ServerChart.MaximumValue', 'goog.ui.ServerChart.MultiAxisAlignment', 'goog.ui.ServerChart.MultiAxisType', 'goog.ui.ServerChart.UriParam', 'goog.ui.ServerChart.UriTooLongEvent'], ['goog.Uri', 'goog.array', 'goog.asserts', 'goog.dom.TagName', 'goog.events.Event', 'goog.string', 'goog.ui.Component']);\ngoog.addDependency(\"ui/serverchart_test.js\", ['goog.ui.ServerChartTest'], ['goog.Uri', 'goog.events', 'goog.testing.jsunit', 'goog.ui.ServerChart']);\ngoog.addDependency(\"ui/slider.js\", ['goog.ui.Slider', 'goog.ui.Slider.Orientation'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.dom.TagName', 'goog.ui.SliderBase']);\ngoog.addDependency(\"ui/sliderbase.js\", ['goog.ui.SliderBase', 'goog.ui.SliderBase.AnimationFactory', 'goog.ui.SliderBase.Orientation'], ['goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.events.MouseWheelHandler', 'goog.functions', 'goog.fx.AnimationParallelQueue', 'goog.fx.Dragger', 'goog.fx.Transition', 'goog.fx.dom.ResizeHeight', 'goog.fx.dom.ResizeWidth', 'goog.fx.dom.Slide', 'goog.math', 'goog.math.Coordinate', 'goog.style', 'goog.style.bidi', 'goog.ui.Component', 'goog.ui.RangeModel']);\ngoog.addDependency(\"ui/sliderbase_test.js\", ['goog.ui.SliderBaseTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.fx.Animation', 'goog.math.Coordinate', 'goog.style', 'goog.style.bidi', 'goog.testing.MockClock', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.SliderBase', 'goog.userAgent']);\ngoog.addDependency(\"ui/splitbehavior.js\", ['goog.ui.SplitBehavior', 'goog.ui.SplitBehavior.DefaultHandlers'], ['goog.Disposable', 'goog.asserts', 'goog.dispose', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.ui.ButtonSide', 'goog.ui.Component', 'goog.ui.decorate', 'goog.ui.registry']);\ngoog.addDependency(\"ui/splitbehavior_test.js\", ['goog.ui.SplitBehaviorTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.CustomButton', 'goog.ui.Menu', 'goog.ui.MenuButton', 'goog.ui.MenuItem', 'goog.ui.SplitBehavior', 'goog.ui.decorate']);\ngoog.addDependency(\"ui/splitpane.js\", ['goog.ui.SplitPane', 'goog.ui.SplitPane.Orientation'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.fx.Dragger', 'goog.math.Rect', 'goog.math.Size', 'goog.style', 'goog.ui.Component', 'goog.userAgent']);\ngoog.addDependency(\"ui/splitpane_test.js\", ['goog.ui.SplitPaneTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.math.Size', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.recordFunction', 'goog.ui.Component', 'goog.ui.SplitPane']);\ngoog.addDependency(\"ui/submenu.js\", ['goog.ui.SubMenu'], ['goog.Timer', 'goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.KeyCodes', 'goog.positioning.AnchoredViewportPosition', 'goog.positioning.Corner', 'goog.style', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.SubMenuRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/submenu_test.js\", ['goog.ui.SubMenuTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.functions', 'goog.positioning', 'goog.positioning.Overflow', 'goog.style', 'goog.testing.MockClock', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Menu', 'goog.ui.MenuItem', 'goog.ui.SubMenu', 'goog.ui.SubMenuRenderer']);\ngoog.addDependency(\"ui/submenurenderer.js\", ['goog.ui.SubMenuRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuItemRenderer']);\ngoog.addDependency(\"ui/tab.js\", ['goog.ui.Tab'], ['goog.ui.Component', 'goog.ui.Control', 'goog.ui.TabRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/tab_test.js\", ['goog.ui.TabTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Tab', 'goog.ui.TabRenderer']);\ngoog.addDependency(\"ui/tabbar.js\", ['goog.ui.TabBar', 'goog.ui.TabBar.Location'], ['goog.ui.Component.EventType', 'goog.ui.Container', 'goog.ui.Container.Orientation', 'goog.ui.Tab', 'goog.ui.TabBarRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/tabbar_test.js\", ['goog.ui.TabBarTest'], ['goog.dom', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Tab', 'goog.ui.TabBar', 'goog.ui.TabBarRenderer']);\ngoog.addDependency(\"ui/tabbarrenderer.js\", ['goog.ui.TabBarRenderer'], ['goog.a11y.aria.Role', 'goog.object', 'goog.ui.ContainerRenderer']);\ngoog.addDependency(\"ui/tabbarrenderer_test.js\", ['goog.ui.TabBarRendererTest'], ['goog.a11y.aria.Role', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Container', 'goog.ui.TabBar', 'goog.ui.TabBarRenderer']);\ngoog.addDependency(\"ui/tablesorter.js\", ['goog.ui.TableSorter', 'goog.ui.TableSorter.EventType'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventType', 'goog.functions', 'goog.ui.Component']);\ngoog.addDependency(\"ui/tablesorter_test.js\", ['goog.ui.TableSorterTest'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.TableSorter']);\ngoog.addDependency(\"ui/tabpane.js\", ['goog.ui.TabPane', 'goog.ui.TabPane.Events', 'goog.ui.TabPane.TabLocation', 'goog.ui.TabPane.TabPage', 'goog.ui.TabPaneEvent'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style']);\ngoog.addDependency(\"ui/tabpane_test.js\", ['goog.ui.TabPaneTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.TabPane']);\ngoog.addDependency(\"ui/tabrenderer.js\", ['goog.ui.TabRenderer'], ['goog.a11y.aria.Role', 'goog.ui.Component', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"ui/tabrenderer_test.js\", ['goog.ui.TabRendererTest'], ['goog.a11y.aria.Role', 'goog.dom', 'goog.dom.classlist', 'goog.testing.dom', 'goog.testing.jsunit', 'goog.testing.ui.rendererasserts', 'goog.ui.Tab', 'goog.ui.TabRenderer']);\ngoog.addDependency(\"ui/textarea.js\", ['goog.ui.Textarea', 'goog.ui.Textarea.EventType'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventType', 'goog.style', 'goog.ui.Control', 'goog.ui.TextareaRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/textarea_test.js\", ['goog.ui.TextareaTest'], ['goog.dom', 'goog.dom.classlist', 'goog.events', 'goog.style', 'goog.testing.ExpectedFailures', 'goog.testing.events.EventObserver', 'goog.testing.jsunit', 'goog.ui.Textarea', 'goog.ui.TextareaRenderer', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"ui/textarearenderer.js\", ['goog.ui.TextareaRenderer'], ['goog.dom.TagName', 'goog.ui.Component', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"ui/togglebutton.js\", ['goog.ui.ToggleButton'], ['goog.ui.Button', 'goog.ui.Component', 'goog.ui.CustomButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/toolbar.js\", ['goog.ui.Toolbar'], ['goog.ui.Container', 'goog.ui.ToolbarRenderer']);\ngoog.addDependency(\"ui/toolbar_test.js\", ['goog.ui.ToolbarTest'], ['goog.a11y.aria', 'goog.dom', 'goog.events.EventType', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.ui.Toolbar', 'goog.ui.ToolbarMenuButton']);\ngoog.addDependency(\"ui/toolbarbutton.js\", ['goog.ui.ToolbarButton'], ['goog.ui.Button', 'goog.ui.ToolbarButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/toolbarbuttonrenderer.js\", ['goog.ui.ToolbarButtonRenderer'], ['goog.ui.CustomButtonRenderer']);\ngoog.addDependency(\"ui/toolbarcolormenubutton.js\", ['goog.ui.ToolbarColorMenuButton'], ['goog.ui.ColorMenuButton', 'goog.ui.ToolbarColorMenuButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/toolbarcolormenubuttonrenderer.js\", ['goog.ui.ToolbarColorMenuButtonRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.ui.ColorMenuButtonRenderer', 'goog.ui.MenuButtonRenderer', 'goog.ui.ToolbarMenuButtonRenderer']);\ngoog.addDependency(\"ui/toolbarcolormenubuttonrenderer_test.js\", ['goog.ui.ToolbarColorMenuButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.RendererHarness', 'goog.testing.ui.rendererasserts', 'goog.ui.ToolbarColorMenuButton', 'goog.ui.ToolbarColorMenuButtonRenderer']);\ngoog.addDependency(\"ui/toolbarmenubutton.js\", ['goog.ui.ToolbarMenuButton'], ['goog.ui.MenuButton', 'goog.ui.ToolbarMenuButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/toolbarmenubuttonrenderer.js\", ['goog.ui.ToolbarMenuButtonRenderer'], ['goog.ui.MenuButtonRenderer']);\ngoog.addDependency(\"ui/toolbarrenderer.js\", ['goog.ui.ToolbarRenderer'], ['goog.a11y.aria.Role', 'goog.dom.TagName', 'goog.ui.Container', 'goog.ui.ContainerRenderer', 'goog.ui.Separator', 'goog.ui.ToolbarSeparatorRenderer']);\ngoog.addDependency(\"ui/toolbarselect.js\", ['goog.ui.ToolbarSelect'], ['goog.ui.Select', 'goog.ui.ToolbarMenuButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/toolbarseparator.js\", ['goog.ui.ToolbarSeparator'], ['goog.ui.Separator', 'goog.ui.ToolbarSeparatorRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/toolbarseparatorrenderer.js\", ['goog.ui.ToolbarSeparatorRenderer'], ['goog.asserts', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.MenuSeparatorRenderer']);\ngoog.addDependency(\"ui/toolbarseparatorrenderer_test.js\", ['goog.ui.ToolbarSeparatorRendererTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.ToolbarSeparator', 'goog.ui.ToolbarSeparatorRenderer']);\ngoog.addDependency(\"ui/toolbartogglebutton.js\", ['goog.ui.ToolbarToggleButton'], ['goog.ui.ToggleButton', 'goog.ui.ToolbarButtonRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/tooltip.js\", ['goog.ui.Tooltip', 'goog.ui.Tooltip.CursorTooltipPosition', 'goog.ui.Tooltip.ElementTooltipPosition', 'goog.ui.Tooltip.State'], ['goog.Timer', 'goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.html.legacyconversions', 'goog.math.Box', 'goog.math.Coordinate', 'goog.positioning', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.positioning.ViewportPosition', 'goog.structs.Set', 'goog.style', 'goog.ui.Popup', 'goog.ui.PopupBase']);\ngoog.addDependency(\"ui/tooltip_test.js\", ['goog.ui.TooltipTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.html.testing', 'goog.math.Coordinate', 'goog.positioning.AbsolutePosition', 'goog.style', 'goog.testing.MockClock', 'goog.testing.PropertyReplacer', 'goog.testing.TestQueue', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.PopupBase', 'goog.ui.Tooltip', 'goog.userAgent']);\ngoog.addDependency(\"ui/tristatemenuitem.js\", ['goog.ui.TriStateMenuItem', 'goog.ui.TriStateMenuItem.State'], ['goog.dom.classlist', 'goog.ui.Component', 'goog.ui.MenuItem', 'goog.ui.TriStateMenuItemRenderer', 'goog.ui.registry']);\ngoog.addDependency(\"ui/tristatemenuitemrenderer.js\", ['goog.ui.TriStateMenuItemRenderer'], ['goog.asserts', 'goog.dom.classlist', 'goog.ui.MenuItemRenderer']);\ngoog.addDependency(\"ui/twothumbslider.js\", ['goog.ui.TwoThumbSlider'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.dom.TagName', 'goog.ui.SliderBase']);\ngoog.addDependency(\"ui/twothumbslider_test.js\", ['goog.ui.TwoThumbSliderTest'], ['goog.testing.jsunit', 'goog.ui.SliderBase', 'goog.ui.TwoThumbSlider']);\ngoog.addDependency(\"ui/zippy.js\", ['goog.ui.Zippy', 'goog.ui.Zippy.Events', 'goog.ui.ZippyEvent'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style']);\ngoog.addDependency(\"ui/zippy_test.js\", ['goog.ui.ZippyTest'], ['goog.a11y.aria', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.object', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Zippy']);\ngoog.addDependency(\"ui/ac/ac.js\", ['goog.ui.ac'], ['goog.ui.ac.ArrayMatcher', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.Renderer']);\ngoog.addDependency(\"ui/ac/ac_test.js\", ['goog.ui.acTest'], ['goog.array', 'goog.asserts', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.classlist', 'goog.dom.selection', 'goog.events', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ac', 'goog.userAgent']);\ngoog.addDependency(\"ui/ac/arraymatcher.js\", ['goog.ui.ac.ArrayMatcher'], ['goog.string']);\ngoog.addDependency(\"ui/ac/arraymatcher_test.js\", ['goog.ui.ac.ArrayMatcherTest'], ['goog.testing.jsunit', 'goog.ui.ac.ArrayMatcher']);\ngoog.addDependency(\"ui/ac/autocomplete.js\", ['goog.ui.ac.AutoComplete', 'goog.ui.ac.AutoComplete.EventType'], ['goog.array', 'goog.asserts', 'goog.events', 'goog.events.EventTarget', 'goog.object']);\ngoog.addDependency(\"ui/ac/autocomplete_test.js\", ['goog.ui.ac.AutoCompleteTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.string', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.RenderOptions', 'goog.ui.ac.Renderer']);\ngoog.addDependency(\"ui/ac/cachingmatcher.js\", ['goog.ui.ac.CachingMatcher'], ['goog.array', 'goog.async.Throttle', 'goog.ui.ac.ArrayMatcher', 'goog.ui.ac.RenderOptions']);\ngoog.addDependency(\"ui/ac/cachingmatcher_test.js\", ['goog.ui.ac.CachingMatcherTest'], ['goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.ui.ac.CachingMatcher']);\ngoog.addDependency(\"ui/ac/inputhandler.js\", ['goog.ui.ac.InputHandler'], ['goog.Disposable', 'goog.Timer', 'goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.selection', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.events.KeyHandler', 'goog.string', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"ui/ac/inputhandler_test.js\", ['goog.ui.ac.InputHandlerTest'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.selection', 'goog.events.BrowserEvent', 'goog.events.Event', 'goog.events.EventTarget', 'goog.events.KeyCodes', 'goog.functions', 'goog.object', 'goog.testing.MockClock', 'goog.testing.jsunit', 'goog.ui.ac.InputHandler', 'goog.userAgent']);\ngoog.addDependency(\"ui/ac/remote.js\", ['goog.ui.ac.Remote'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.InputHandler', 'goog.ui.ac.RemoteArrayMatcher', 'goog.ui.ac.Renderer']);\ngoog.addDependency(\"ui/ac/remotearraymatcher.js\", ['goog.ui.ac.RemoteArrayMatcher'], ['goog.Disposable', 'goog.Uri', 'goog.events', 'goog.json', 'goog.net.EventType', 'goog.net.XhrIo']);\ngoog.addDependency(\"ui/ac/remotearraymatcher_test.js\", ['goog.ui.ac.RemoteArrayMatcherTest'], ['goog.json', 'goog.net.XhrIo', 'goog.testing.MockControl', 'goog.testing.jsunit', 'goog.testing.net.XhrIo', 'goog.ui.ac.RemoteArrayMatcher']);\ngoog.addDependency(\"ui/ac/renderer.js\", ['goog.ui.ac.Renderer', 'goog.ui.ac.Renderer.CustomRenderer'], ['goog.a11y.aria', 'goog.a11y.aria.Role', 'goog.a11y.aria.State', 'goog.array', 'goog.asserts', 'goog.dispose', 'goog.dom', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOutAndHide', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.string', 'goog.style', 'goog.ui.IdGenerator', 'goog.ui.ac.AutoComplete']);\ngoog.addDependency(\"ui/ac/renderer_test.js\", ['goog.ui.ac.RendererTest'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events', 'goog.fx.dom.FadeInAndShow', 'goog.fx.dom.FadeOutAndHide', 'goog.string', 'goog.style', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.ac.AutoComplete', 'goog.ui.ac.Renderer']);\ngoog.addDependency(\"ui/ac/renderoptions.js\", ['goog.ui.ac.RenderOptions'], []);\ngoog.addDependency(\"ui/ac/richinputhandler.js\", ['goog.ui.ac.RichInputHandler'], ['goog.ui.ac.InputHandler']);\ngoog.addDependency(\"ui/ac/richremote.js\", ['goog.ui.ac.RichRemote'], ['goog.ui.ac.AutoComplete', 'goog.ui.ac.Remote', 'goog.ui.ac.Renderer', 'goog.ui.ac.RichInputHandler', 'goog.ui.ac.RichRemoteArrayMatcher']);\ngoog.addDependency(\"ui/ac/richremotearraymatcher.js\", ['goog.ui.ac.RichRemoteArrayMatcher'], ['goog.dom.safe', 'goog.html.legacyconversions', 'goog.json', 'goog.ui.ac.RemoteArrayMatcher']);\ngoog.addDependency(\"ui/editor/abstractdialog.js\", ['goog.ui.editor.AbstractDialog', 'goog.ui.editor.AbstractDialog.Builder', 'goog.ui.editor.AbstractDialog.EventType'], ['goog.asserts', 'goog.dom', 'goog.dom.classlist', 'goog.events.EventTarget', 'goog.string', 'goog.ui.Dialog', 'goog.ui.PopupBase']);\ngoog.addDependency(\"ui/editor/abstractdialog_test.js\", ['goog.ui.editor.AbstractDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.KeyCodes', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.userAgent']);\ngoog.addDependency(\"ui/editor/bubble.js\", ['goog.ui.editor.Bubble'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.ViewportSizeMonitor', 'goog.dom.classlist', 'goog.editor.style', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.events.EventType', 'goog.functions', 'goog.log', 'goog.math.Box', 'goog.object', 'goog.positioning', 'goog.positioning.Corner', 'goog.positioning.Overflow', 'goog.positioning.OverflowStatus', 'goog.string', 'goog.style', 'goog.ui.Component', 'goog.ui.PopupBase', 'goog.userAgent']);\ngoog.addDependency(\"ui/editor/bubble_test.js\", ['goog.ui.editor.BubbleTest'], ['goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.events.EventType', 'goog.positioning.Corner', 'goog.positioning.OverflowStatus', 'goog.string', 'goog.style', 'goog.testing.editor.TestHelper', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.editor.Bubble', 'goog.userAgent.product']);\ngoog.addDependency(\"ui/editor/defaulttoolbar.js\", ['goog.ui.editor.ButtonDescriptor', 'goog.ui.editor.DefaultToolbar'], ['goog.asserts', 'goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.editor.Command', 'goog.style', 'goog.ui.editor.ToolbarFactory', 'goog.ui.editor.messages', 'goog.userAgent']);\ngoog.addDependency(\"ui/editor/linkdialog.js\", ['goog.ui.editor.LinkDialog', 'goog.ui.editor.LinkDialog.BeforeTestLinkEvent', 'goog.ui.editor.LinkDialog.EventType', 'goog.ui.editor.LinkDialog.OkEvent'], ['goog.a11y.aria', 'goog.a11y.aria.State', 'goog.dom', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.safe', 'goog.editor.BrowserFeature', 'goog.editor.Link', 'goog.editor.focus', 'goog.editor.node', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.InputHandler', 'goog.html.SafeHtml', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.LinkButtonRenderer', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.TabPane', 'goog.ui.editor.messages', 'goog.userAgent', 'goog.window']);\ngoog.addDependency(\"ui/editor/linkdialog_test.js\", ['goog.ui.editor.LinkDialogTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.editor.BrowserFeature', 'goog.editor.Link', 'goog.events', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.events.KeyCodes', 'goog.style', 'goog.testing.MockControl', 'goog.testing.PropertyReplacer', 'goog.testing.dom', 'goog.testing.events', 'goog.testing.events.Event', 'goog.testing.jsunit', 'goog.testing.mockmatchers', 'goog.testing.mockmatchers.ArgumentMatcher', 'goog.ui.editor.AbstractDialog', 'goog.ui.editor.LinkDialog', 'goog.ui.editor.messages', 'goog.userAgent']);\ngoog.addDependency(\"ui/editor/messages.js\", ['goog.ui.editor.messages'], ['goog.html.uncheckedconversions', 'goog.string.Const']);\ngoog.addDependency(\"ui/editor/tabpane.js\", ['goog.ui.editor.TabPane'], ['goog.asserts', 'goog.dom.InputType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.style', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.Tab', 'goog.ui.TabBar']);\ngoog.addDependency(\"ui/editor/toolbarcontroller.js\", ['goog.ui.editor.ToolbarController'], ['goog.editor.Field', 'goog.events.EventHandler', 'goog.events.EventTarget', 'goog.ui.Component']);\ngoog.addDependency(\"ui/editor/toolbarfactory.js\", ['goog.ui.editor.ToolbarFactory'], ['goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.string', 'goog.string.Unicode', 'goog.style', 'goog.ui.Component', 'goog.ui.Container', 'goog.ui.Option', 'goog.ui.Toolbar', 'goog.ui.ToolbarButton', 'goog.ui.ToolbarColorMenuButton', 'goog.ui.ToolbarMenuButton', 'goog.ui.ToolbarRenderer', 'goog.ui.ToolbarSelect', 'goog.userAgent']);\ngoog.addDependency(\"ui/editor/toolbarfactory_test.js\", ['goog.ui.editor.ToolbarFactoryTest'], ['goog.dom', 'goog.testing.ExpectedFailures', 'goog.testing.editor.TestHelper', 'goog.testing.jsunit', 'goog.ui.editor.ToolbarFactory', 'goog.userAgent']);\ngoog.addDependency(\"ui/emoji/emoji.js\", ['goog.ui.emoji.Emoji'], []);\ngoog.addDependency(\"ui/emoji/emojipalette.js\", ['goog.ui.emoji.EmojiPalette'], ['goog.events.EventType', 'goog.net.ImageLoader', 'goog.ui.Palette', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPaletteRenderer']);\ngoog.addDependency(\"ui/emoji/emojipaletterenderer.js\", ['goog.ui.emoji.EmojiPaletteRenderer'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom.NodeType', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.style', 'goog.ui.PaletteRenderer', 'goog.ui.emoji.Emoji']);\ngoog.addDependency(\"ui/emoji/emojipicker.js\", ['goog.ui.emoji.EmojiPicker'], ['goog.dom.TagName', 'goog.style', 'goog.ui.Component', 'goog.ui.TabPane', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPalette', 'goog.ui.emoji.EmojiPaletteRenderer', 'goog.ui.emoji.ProgressiveEmojiPaletteRenderer']);\ngoog.addDependency(\"ui/emoji/emojipicker_test.js\", ['goog.ui.emoji.EmojiPickerTest'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.events.EventHandler', 'goog.style', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo']);\ngoog.addDependency(\"ui/emoji/fast_nonprogressive_emojipicker_test.js\", ['goog.ui.emoji.FastNonProgressiveEmojiPickerTest'], ['goog.Promise', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.net.EventType', 'goog.style', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo']);\ngoog.addDependency(\"ui/emoji/fast_progressive_emojipicker_test.js\", ['goog.ui.emoji.FastProgressiveEmojiPickerTest'], ['goog.Promise', 'goog.dom.classlist', 'goog.events', 'goog.events.EventType', 'goog.net.EventType', 'goog.style', 'goog.testing.jsunit', 'goog.ui.emoji.Emoji', 'goog.ui.emoji.EmojiPicker', 'goog.ui.emoji.SpriteInfo']);\ngoog.addDependency(\"ui/emoji/popupemojipicker.js\", ['goog.ui.emoji.PopupEmojiPicker'], ['goog.events.EventType', 'goog.positioning.AnchoredPosition', 'goog.positioning.Corner', 'goog.ui.Component', 'goog.ui.Popup', 'goog.ui.emoji.EmojiPicker']);\ngoog.addDependency(\"ui/emoji/popupemojipicker_test.js\", ['goog.ui.emoji.PopupEmojiPickerTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.emoji.PopupEmojiPicker']);\ngoog.addDependency(\"ui/emoji/progressiveemojipaletterenderer.js\", ['goog.ui.emoji.ProgressiveEmojiPaletteRenderer'], ['goog.dom.TagName', 'goog.style', 'goog.ui.emoji.EmojiPaletteRenderer']);\ngoog.addDependency(\"ui/emoji/spriteinfo.js\", ['goog.ui.emoji.SpriteInfo'], []);\ngoog.addDependency(\"ui/emoji/spriteinfo_test.js\", ['goog.ui.emoji.SpriteInfoTest'], ['goog.testing.jsunit', 'goog.ui.emoji.SpriteInfo']);\ngoog.addDependency(\"ui/media/flashobject.js\", ['goog.ui.media.FlashObject', 'goog.ui.media.FlashObject.ScriptAccessLevel', 'goog.ui.media.FlashObject.Wmodes'], ['goog.asserts', 'goog.dom.TagName', 'goog.dom.safe', 'goog.events.Event', 'goog.events.EventHandler', 'goog.events.EventType', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.flash', 'goog.html.legacyconversions', 'goog.log', 'goog.object', 'goog.string', 'goog.structs.Map', 'goog.style', 'goog.ui.Component', 'goog.userAgent', 'goog.userAgent.flash']);\ngoog.addDependency(\"ui/media/flashobject_test.js\", ['goog.ui.media.FlashObjectTest'], ['goog.dom', 'goog.dom.DomHelper', 'goog.dom.TagName', 'goog.events', 'goog.events.Event', 'goog.events.EventType', 'goog.html.SafeUrl', 'goog.testing.MockControl', 'goog.testing.events', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.userAgent']);\ngoog.addDependency(\"ui/media/flickr.js\", ['goog.ui.media.FlickrSet', 'goog.ui.media.FlickrSetModel'], ['goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer']);\ngoog.addDependency(\"ui/media/flickr_test.js\", ['goog.ui.media.FlickrSetTest'], ['goog.dom', 'goog.dom.TagName', 'goog.html.testing', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.FlickrSet', 'goog.ui.media.FlickrSetModel', 'goog.ui.media.Media']);\ngoog.addDependency(\"ui/media/googlevideo.js\", ['goog.ui.media.GoogleVideo', 'goog.ui.media.GoogleVideoModel'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer']);\ngoog.addDependency(\"ui/media/googlevideo_test.js\", ['goog.ui.media.GoogleVideoTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.GoogleVideo', 'goog.ui.media.GoogleVideoModel', 'goog.ui.media.Media']);\ngoog.addDependency(\"ui/media/media.js\", ['goog.ui.media.Media', 'goog.ui.media.MediaRenderer'], ['goog.asserts', 'goog.dom.TagName', 'goog.style', 'goog.ui.Component', 'goog.ui.Control', 'goog.ui.ControlRenderer']);\ngoog.addDependency(\"ui/media/media_test.js\", ['goog.ui.media.MediaTest'], ['goog.dom', 'goog.dom.TagName', 'goog.math.Size', 'goog.testing.jsunit', 'goog.ui.ControlRenderer', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer']);\ngoog.addDependency(\"ui/media/mediamodel.js\", ['goog.ui.media.MediaModel', 'goog.ui.media.MediaModel.Category', 'goog.ui.media.MediaModel.Credit', 'goog.ui.media.MediaModel.Credit.Role', 'goog.ui.media.MediaModel.Credit.Scheme', 'goog.ui.media.MediaModel.Medium', 'goog.ui.media.MediaModel.MimeType', 'goog.ui.media.MediaModel.Player', 'goog.ui.media.MediaModel.SubTitle', 'goog.ui.media.MediaModel.Thumbnail'], ['goog.array', 'goog.html.TrustedResourceUrl', 'goog.html.legacyconversions']);\ngoog.addDependency(\"ui/media/mediamodel_test.js\", ['goog.ui.media.MediaModelTest'], ['goog.testing.jsunit', 'goog.ui.media.MediaModel']);\ngoog.addDependency(\"ui/media/mp3.js\", ['goog.ui.media.Mp3'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaRenderer']);\ngoog.addDependency(\"ui/media/mp3_test.js\", ['goog.ui.media.Mp3Test'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.Mp3']);\ngoog.addDependency(\"ui/media/photo.js\", ['goog.ui.media.Photo'], ['goog.dom.TagName', 'goog.ui.media.Media', 'goog.ui.media.MediaRenderer']);\ngoog.addDependency(\"ui/media/photo_test.js\", ['goog.ui.media.PhotoTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.MediaModel', 'goog.ui.media.Photo']);\ngoog.addDependency(\"ui/media/picasa.js\", ['goog.ui.media.PicasaAlbum', 'goog.ui.media.PicasaAlbumModel'], ['goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer']);\ngoog.addDependency(\"ui/media/picasa_test.js\", ['goog.ui.media.PicasaTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.PicasaAlbum', 'goog.ui.media.PicasaAlbumModel']);\ngoog.addDependency(\"ui/media/vimeo.js\", ['goog.ui.media.Vimeo', 'goog.ui.media.VimeoModel'], ['goog.string', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer']);\ngoog.addDependency(\"ui/media/vimeo_test.js\", ['goog.ui.media.VimeoTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.Vimeo', 'goog.ui.media.VimeoModel']);\ngoog.addDependency(\"ui/media/youtube.js\", ['goog.ui.media.Youtube', 'goog.ui.media.YoutubeModel'], ['goog.dom.TagName', 'goog.string', 'goog.ui.Component', 'goog.ui.media.FlashObject', 'goog.ui.media.Media', 'goog.ui.media.MediaModel', 'goog.ui.media.MediaRenderer']);\ngoog.addDependency(\"ui/media/youtube_test.js\", ['goog.ui.media.YoutubeTest'], ['goog.dom', 'goog.dom.TagName', 'goog.testing.jsunit', 'goog.ui.media.FlashObject', 'goog.ui.media.Youtube', 'goog.ui.media.YoutubeModel']);\ngoog.addDependency(\"ui/style/app/buttonrenderer.js\", ['goog.ui.style.app.ButtonRenderer'], ['goog.dom.TagName', 'goog.dom.classlist', 'goog.ui.Button', 'goog.ui.CustomButtonRenderer', 'goog.ui.INLINE_BLOCK_CLASSNAME', 'goog.ui.registry']);\ngoog.addDependency(\"ui/style/app/buttonrenderer_test.js\", ['goog.ui.style.app.ButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.style.app.ButtonRenderer', 'goog.userAgent']);\ngoog.addDependency(\"ui/style/app/menubuttonrenderer.js\", ['goog.ui.style.app.MenuButtonRenderer'], ['goog.a11y.aria.Role', 'goog.array', 'goog.dom', 'goog.dom.TagName', 'goog.style', 'goog.ui.Menu', 'goog.ui.MenuRenderer', 'goog.ui.style.app.ButtonRenderer']);\ngoog.addDependency(\"ui/style/app/menubuttonrenderer_test.js\", ['goog.ui.style.app.MenuButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Component', 'goog.ui.MenuButton', 'goog.ui.style.app.MenuButtonRenderer']);\ngoog.addDependency(\"ui/style/app/primaryactionbuttonrenderer.js\", ['goog.ui.style.app.PrimaryActionButtonRenderer'], ['goog.ui.Button', 'goog.ui.registry', 'goog.ui.style.app.ButtonRenderer']);\ngoog.addDependency(\"ui/style/app/primaryactionbuttonrenderer_test.js\", ['goog.ui.style.app.PrimaryActionButtonRendererTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.testing.ui.style', 'goog.ui.Button', 'goog.ui.Component', 'goog.ui.style.app.PrimaryActionButtonRenderer']);\ngoog.addDependency(\"ui/tree/basenode.js\", ['goog.ui.tree.BaseNode', 'goog.ui.tree.BaseNode.EventType'], ['goog.Timer', 'goog.a11y.aria', 'goog.asserts', 'goog.dom.safe', 'goog.events.Event', 'goog.events.KeyCodes', 'goog.html.SafeHtml', 'goog.html.SafeStyle', 'goog.html.legacyconversions', 'goog.string', 'goog.string.StringBuffer', 'goog.style', 'goog.ui.Component']);\ngoog.addDependency(\"ui/tree/basenode_test.js\", ['goog.ui.tree.BaseNodeTest'], ['goog.dom', 'goog.dom.TagName', 'goog.dom.classlist', 'goog.html.legacyconversions', 'goog.html.testing', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.ui.Component', 'goog.ui.tree.BaseNode', 'goog.ui.tree.TreeControl', 'goog.ui.tree.TreeNode']);\ngoog.addDependency(\"ui/tree/treecontrol.js\", ['goog.ui.tree.TreeControl'], ['goog.a11y.aria', 'goog.asserts', 'goog.dom.classlist', 'goog.events.EventType', 'goog.events.FocusHandler', 'goog.events.KeyHandler', 'goog.html.SafeHtml', 'goog.log', 'goog.ui.tree.BaseNode', 'goog.ui.tree.TreeNode', 'goog.ui.tree.TypeAhead', 'goog.userAgent']);\ngoog.addDependency(\"ui/tree/treecontrol_test.js\", ['goog.ui.tree.TreeControlTest'], ['goog.dom', 'goog.testing.jsunit', 'goog.ui.tree.TreeControl']);\ngoog.addDependency(\"ui/tree/treenode.js\", ['goog.ui.tree.TreeNode'], ['goog.ui.tree.BaseNode']);\ngoog.addDependency(\"ui/tree/typeahead.js\", ['goog.ui.tree.TypeAhead', 'goog.ui.tree.TypeAhead.Offset'], ['goog.array', 'goog.events.KeyCodes', 'goog.string', 'goog.structs.Trie']);\ngoog.addDependency(\"ui/tree/typeahead_test.js\", ['goog.ui.tree.TypeAheadTest'], ['goog.dom', 'goog.events.KeyCodes', 'goog.testing.jsunit', 'goog.ui.tree.TreeControl', 'goog.ui.tree.TypeAhead']);\ngoog.addDependency(\"uri/uri.js\", ['goog.Uri', 'goog.Uri.QueryData'], ['goog.array', 'goog.asserts', 'goog.string', 'goog.structs', 'goog.structs.Map', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.StandardQueryParam']);\ngoog.addDependency(\"uri/uri_test.js\", ['goog.UriTest'], ['goog.Uri', 'goog.testing.jsunit']);\ngoog.addDependency(\"uri/utils.js\", ['goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.QueryArray', 'goog.uri.utils.QueryValue', 'goog.uri.utils.StandardQueryParam'], ['goog.asserts', 'goog.string']);\ngoog.addDependency(\"uri/utils_test.js\", ['goog.uri.utilsTest'], ['goog.functions', 'goog.string', 'goog.testing.jsunit', 'goog.uri.utils']);\ngoog.addDependency(\"useragent/adobereader.js\", ['goog.userAgent.adobeReader'], ['goog.string', 'goog.userAgent']);\ngoog.addDependency(\"useragent/adobereader_test.js\", ['goog.userAgent.adobeReaderTest'], ['goog.testing.jsunit', 'goog.userAgent.adobeReader']);\ngoog.addDependency(\"useragent/flash.js\", ['goog.userAgent.flash'], ['goog.string']);\ngoog.addDependency(\"useragent/flash_test.js\", ['goog.userAgent.flashTest'], ['goog.testing.jsunit', 'goog.userAgent.flash']);\ngoog.addDependency(\"useragent/iphoto.js\", ['goog.userAgent.iphoto'], ['goog.string', 'goog.userAgent']);\ngoog.addDependency(\"useragent/jscript.js\", ['goog.userAgent.jscript'], ['goog.string']);\ngoog.addDependency(\"useragent/jscript_test.js\", ['goog.userAgent.jscriptTest'], ['goog.testing.jsunit', 'goog.userAgent.jscript']);\ngoog.addDependency(\"useragent/keyboard.js\", ['goog.userAgent.keyboard'], ['goog.labs.userAgent.platform']);\ngoog.addDependency(\"useragent/keyboard_test.js\", ['goog.userAgent.keyboardTest'], ['goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent.keyboard', 'goog.userAgentTestUtil']);\ngoog.addDependency(\"useragent/platform.js\", ['goog.userAgent.platform'], ['goog.string', 'goog.userAgent']);\ngoog.addDependency(\"useragent/platform_test.js\", ['goog.userAgent.platformTest'], ['goog.testing.MockUserAgent', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.platform', 'goog.userAgentTestUtil']);\ngoog.addDependency(\"useragent/product.js\", ['goog.userAgent.product'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.platform', 'goog.userAgent']);\ngoog.addDependency(\"useragent/product_isversion.js\", ['goog.userAgent.product.isVersion'], ['goog.labs.userAgent.platform', 'goog.string', 'goog.userAgent', 'goog.userAgent.product']);\ngoog.addDependency(\"useragent/product_test.js\", ['goog.userAgent.productTest'], ['goog.array', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.MockUserAgent', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgent.product', 'goog.userAgent.product.isVersion', 'goog.userAgentTestUtil']);\ngoog.addDependency(\"useragent/useragent.js\", ['goog.userAgent'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.engine', 'goog.labs.userAgent.platform', 'goog.labs.userAgent.util', 'goog.string']);\ngoog.addDependency(\"useragent/useragent_quirks_test.js\", ['goog.userAgentQuirksTest'], ['goog.testing.jsunit', 'goog.userAgent']);\ngoog.addDependency(\"useragent/useragent_test.js\", ['goog.userAgentTest'], ['goog.array', 'goog.labs.userAgent.platform', 'goog.labs.userAgent.testAgents', 'goog.labs.userAgent.util', 'goog.testing.PropertyReplacer', 'goog.testing.jsunit', 'goog.userAgent', 'goog.userAgentTestUtil']);\ngoog.addDependency(\"useragent/useragenttestutil.js\", ['goog.userAgentTestUtil', 'goog.userAgentTestUtil.UserAgents'], ['goog.labs.userAgent.browser', 'goog.labs.userAgent.engine', 'goog.labs.userAgent.platform', 'goog.userAgent', 'goog.userAgent.keyboard', 'goog.userAgent.platform', 'goog.userAgent.product', 'goog.userAgent.product.isVersion']);\ngoog.addDependency(\"vec/float32array.js\", ['goog.vec.Float32Array'], []);\ngoog.addDependency(\"vec/float64array.js\", ['goog.vec.Float64Array'], []);\ngoog.addDependency(\"vec/mat3.js\", ['goog.vec.Mat3'], ['goog.vec']);\ngoog.addDependency(\"vec/mat3d.js\", ['goog.vec.mat3d', 'goog.vec.mat3d.Type'], ['goog.vec']);\ngoog.addDependency(\"vec/mat3f.js\", ['goog.vec.mat3f', 'goog.vec.mat3f.Type'], ['goog.vec']);\ngoog.addDependency(\"vec/mat4.js\", ['goog.vec.Mat4'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4']);\ngoog.addDependency(\"vec/mat4d.js\", ['goog.vec.mat4d', 'goog.vec.mat4d.Type'], ['goog.vec', 'goog.vec.Quaternion', 'goog.vec.vec3d', 'goog.vec.vec4d']);\ngoog.addDependency(\"vec/mat4f.js\", ['goog.vec.mat4f', 'goog.vec.mat4f.Type'], ['goog.vec', 'goog.vec.Quaternion', 'goog.vec.vec3f', 'goog.vec.vec4f']);\ngoog.addDependency(\"vec/matrix3.js\", ['goog.vec.Matrix3'], []);\ngoog.addDependency(\"vec/matrix4.js\", ['goog.vec.Matrix4'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4']);\ngoog.addDependency(\"vec/quaternion.js\", ['goog.vec.Quaternion', 'goog.vec.Quaternion.AnyType'], ['goog.vec', 'goog.vec.Vec3', 'goog.vec.Vec4']);\ngoog.addDependency(\"vec/ray.js\", ['goog.vec.Ray'], ['goog.vec.Vec3']);\ngoog.addDependency(\"vec/vec.js\", ['goog.vec', 'goog.vec.AnyType', 'goog.vec.ArrayType', 'goog.vec.Float32', 'goog.vec.Float64', 'goog.vec.Number'], ['goog.vec.Float32Array', 'goog.vec.Float64Array']);\ngoog.addDependency(\"vec/vec2.js\", ['goog.vec.Vec2'], ['goog.vec']);\ngoog.addDependency(\"vec/vec2d.js\", ['goog.vec.vec2d', 'goog.vec.vec2d.Type'], ['goog.vec']);\ngoog.addDependency(\"vec/vec2f.js\", ['goog.vec.vec2f', 'goog.vec.vec2f.Type'], ['goog.vec']);\ngoog.addDependency(\"vec/vec3.js\", ['goog.vec.Vec3'], ['goog.vec']);\ngoog.addDependency(\"vec/vec3d.js\", ['goog.vec.vec3d', 'goog.vec.vec3d.Type'], ['goog.vec']);\ngoog.addDependency(\"vec/vec3f.js\", ['goog.vec.vec3f', 'goog.vec.vec3f.Type'], ['goog.vec']);\ngoog.addDependency(\"vec/vec4.js\", ['goog.vec.Vec4'], ['goog.vec']);\ngoog.addDependency(\"vec/vec4d.js\", ['goog.vec.vec4d', 'goog.vec.vec4d.Type'], ['goog.vec']);\ngoog.addDependency(\"vec/vec4f.js\", ['goog.vec.vec4f', 'goog.vec.vec4f.Type'], ['goog.vec']);\ngoog.addDependency(\"webgl/webgl.js\", ['goog.webgl'], []);\ngoog.addDependency(\"window/window.js\", ['goog.window'], ['goog.dom.TagName', 'goog.dom.safe', 'goog.html.SafeUrl', 'goog.html.uncheckedconversions', 'goog.labs.userAgent.platform', 'goog.string', 'goog.string.Const', 'goog.userAgent']);\ngoog.addDependency(\"window/window_test.js\", ['goog.windowTest'], ['goog.Promise', 'goog.dom', 'goog.dom.TagName', 'goog.events', 'goog.functions', 'goog.labs.userAgent.browser', 'goog.labs.userAgent.engine', 'goog.labs.userAgent.platform', 'goog.string', 'goog.testing.PropertyReplacer', 'goog.testing.TestCase', 'goog.testing.jsunit', 'goog.window']);\ngoog.addDependency(\"../../third_party/closure/goog/base.js\", [], []);\ngoog.addDependency(\"../../third_party/closure/goog/deps.js\", [], []);\ngoog.addDependency(\"../../third_party/closure/goog/caja/string/html/htmlparser.js\", ['goog.string.html', 'goog.string.html.HtmlParser', 'goog.string.html.HtmlParser.EFlags', 'goog.string.html.HtmlParser.Elements', 'goog.string.html.HtmlParser.Entities', 'goog.string.html.HtmlSaxHandler'], []);\ngoog.addDependency(\"../../third_party/closure/goog/caja/string/html/htmlsanitizer.js\", ['goog.string.html.HtmlSanitizer', 'goog.string.html.HtmlSanitizer.AttributeType', 'goog.string.html.HtmlSanitizer.Attributes', 'goog.string.html.htmlSanitize'], ['goog.string.StringBuffer', 'goog.string.html.HtmlParser', 'goog.string.html.HtmlSaxHandler']);\ngoog.addDependency(\"../../third_party/closure/goog/dojo/dom/query.js\", ['goog.dom.query'], ['goog.array', 'goog.dom', 'goog.functions', 'goog.string', 'goog.userAgent']);\ngoog.addDependency(\"../../third_party/closure/goog/dojo/dom/query_test.js\", [], ['goog.dom', 'goog.userAgent']);\ngoog.addDependency(\"../../third_party/closure/goog/jpeg_encoder/jpeg_encoder_basic.js\", ['goog.crypt.JpegEncoder'], ['goog.crypt.base64']);\ngoog.addDependency(\"../../third_party/closure/goog/loremipsum/text/loremipsum.js\", ['goog.text.LoremIpsum'], ['goog.array', 'goog.math', 'goog.string', 'goog.structs.Map', 'goog.structs.Set']);\ngoog.addDependency(\"../../third_party/closure/goog/mochikit/async/deferred.js\", ['goog.async.Deferred', 'goog.async.Deferred.AlreadyCalledError', 'goog.async.Deferred.CanceledError'], ['goog.Promise', 'goog.Thenable', 'goog.array', 'goog.asserts', 'goog.debug.Error']);\ngoog.addDependency(\"../../third_party/closure/goog/mochikit/async/deferredlist.js\", ['goog.async.DeferredList'], ['goog.async.Deferred']);\ngoog.addDependency(\"../../third_party/closure/goog/osapi/osapi.js\", ['goog.osapi'], []);\ngoog.addDependency(\"../../third_party/closure/goog/svgpan/svgpan.js\", ['svgpan.SvgPan'], ['goog.Disposable', 'goog.events', 'goog.events.EventType', 'goog.events.MouseWheelHandler']);\n\n// Load Blockly.\ngoog.require('Blockly');\ngoog.require('Blockly.Block');\ngoog.require('Blockly.BlockMenu');\ngoog.require('Blockly.BlockSvg');\ngoog.require('Blockly.Blocks');\ngoog.require('Blockly.Bubble');\ngoog.require('Blockly.Comment');\ngoog.require('Blockly.Connection');\ngoog.require('Blockly.ConnectionAnimation');\ngoog.require('Blockly.ConnectionDB');\ngoog.require('Blockly.ContextMenu');\ngoog.require('Blockly.Css');\ngoog.require('Blockly.Field');\ngoog.require('Blockly.FieldAngle');\ngoog.require('Blockly.FieldCheckbox');\ngoog.require('Blockly.FieldColour');\ngoog.require('Blockly.FieldDropdown');\ngoog.require('Blockly.FieldDropdownDynamic');\ngoog.require('Blockly.FieldIcon');\ngoog.require('Blockly.FieldImage');\ngoog.require('Blockly.FieldKeydownInput');\ngoog.require('Blockly.FieldLabel');\ngoog.require('Blockly.FieldTextInput');\ngoog.require('Blockly.FieldVariable');\ngoog.require('Blockly.Flyout');\ngoog.require('Blockly.Generator');\ngoog.require('Blockly.Icon');\ngoog.require('Blockly.Input');\ngoog.require('Blockly.Msg');\ngoog.require('Blockly.Mutator');\ngoog.require('Blockly.Names');\ngoog.require('Blockly.Procedures');\ngoog.require('Blockly.Realtime');\ngoog.require('Blockly.Scrollbar');\ngoog.require('Blockly.ScrollbarPair');\ngoog.require('Blockly.Toolbox');\ngoog.require('Blockly.Tooltip');\ngoog.require('Blockly.Trashcan');\ngoog.require('Blockly.Variables');\ngoog.require('Blockly.Warning');\ngoog.require('Blockly.WidgetDiv');\ngoog.require('Blockly.Workspace');\ngoog.require('Blockly.Xml');\ngoog.require('Blockly.inject');\ngoog.require('Blockly.utils');\n\ndelete window.BLOCKLY_DIR;\ndelete window.BLOCKLY_BOOT;\n};\n\n// Delete any existing Closure (e.g. Soy's nogoog_shim).\ndocument.write('<script type=\"text/javascript\">var goog = undefined;</script>');\n// Load fresh Closure Library.\ndocument.write('<script type=\"text/javascript\" src=\"' + window.BLOCKLY_DIR +\n    '/../../closure-library/closure/goog/base.js\"></script>');\ndocument.write('<script type=\"text/javascript\">window.BLOCKLY_BOOT()</script>');\n"
  },
  {
    "path": "extern/blockly/blocks/colour.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Colour blocks for Blockly.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Blocks.colour');\n\ngoog.require('Blockly.Blocks');\n\n\nBlockly.Blocks['colour_picker'] = {\n  // Colour picker.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.COLOUR_PICKER_HELPURL);\n    this.setColour(20);\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldColour('#ff0000'), 'COLOUR');\n    this.setOutput(true, 'Colour');\n    this.setTooltip(Blockly.Msg.COLOUR_PICKER_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['colour_random'] = {\n  // Random colour.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.COLOUR_RANDOM_HELPURL);\n    this.setColour(20);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.COLOUR_RANDOM_TITLE);\n    this.setOutput(true, 'Colour');\n    this.setTooltip(Blockly.Msg.COLOUR_RANDOM_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['colour_rgb'] = {\n  // Compose a colour from RGB components.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.COLOUR_RGB_HELPURL);\n    this.setColour(20);\n    this.appendValueInput('RED')\n        .setCheck('Number')\n        .setAlign(Blockly.ALIGN_RIGHT)\n        .appendField(Blockly.Msg.COLOUR_RGB_TITLE)\n        .appendField(Blockly.Msg.COLOUR_RGB_RED);\n    this.appendValueInput('GREEN')\n        .setCheck('Number')\n        .setAlign(Blockly.ALIGN_RIGHT)\n        .appendField(Blockly.Msg.COLOUR_RGB_GREEN);\n    this.appendValueInput('BLUE')\n        .setCheck('Number')\n        .setAlign(Blockly.ALIGN_RIGHT)\n        .appendField(Blockly.Msg.COLOUR_RGB_BLUE);\n    this.setOutput(true, 'Colour');\n    this.setTooltip(Blockly.Msg.COLOUR_RGB_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['colour_blend'] = {\n  // Blend two colours together.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.COLOUR_BLEND_HELPURL);\n    this.setColour(20);\n    this.appendValueInput('COLOUR1')\n        .setCheck('Colour')\n        .setAlign(Blockly.ALIGN_RIGHT)\n        .appendField(Blockly.Msg.COLOUR_BLEND_TITLE)\n        .appendField(Blockly.Msg.COLOUR_BLEND_COLOUR1);\n    this.appendValueInput('COLOUR2')\n        .setCheck('Colour')\n        .setAlign(Blockly.ALIGN_RIGHT)\n        .appendField(Blockly.Msg.COLOUR_BLEND_COLOUR2);\n    this.appendValueInput('RATIO')\n        .setCheck('Number')\n        .setAlign(Blockly.ALIGN_RIGHT)\n        .appendField(Blockly.Msg.COLOUR_BLEND_RATIO);\n    this.setOutput(true, 'Colour');\n    this.setTooltip(Blockly.Msg.COLOUR_BLEND_TOOLTIP);\n  }\n};\n"
  },
  {
    "path": "extern/blockly/blocks/lists.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview List blocks for Blockly.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Blocks.lists');\n\ngoog.require('Blockly.Blocks');\n\n\nBlockly.Blocks['lists_create_empty'] = {\n  // Create an empty list.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL);\n    this.setColour(260);\n    this.setOutput(true, 'Array');\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);\n    this.setTooltip(Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['lists_create_with'] = {\n  // Create a list with any number of elements of any type.\n  init: function() {\n    this.setColour(260);\n    this.appendValueInput('ADD0')\n        .appendField(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);\n    this.appendValueInput('ADD1');\n    this.appendValueInput('ADD2');\n    this.setOutput(true, 'Array');\n    this.setMutator(new Blockly.Mutator(['lists_create_with_item']));\n    this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP);\n    this.itemCount_ = 3;\n  },\n  mutationToDom: function(workspace) {\n    var container = document.createElement('mutation');\n    container.setAttribute('items', this.itemCount_);\n    return container;\n  },\n  domToMutation: function(container) {\n    for (var x = 0; x < this.itemCount_; x++) {\n      this.removeInput('ADD' + x);\n    }\n    this.itemCount_ = parseInt(container.getAttribute('items'), 10);\n    for (var x = 0; x < this.itemCount_; x++) {\n      var input = this.appendValueInput('ADD' + x);\n      if (x == 0) {\n        input.appendField(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);\n      }\n    }\n    if (this.itemCount_ == 0) {\n      this.appendDummyInput('EMPTY')\n          .appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);\n    }\n  },\n  decompose: function(workspace) {\n    var containerBlock =\n        Blockly.Block.obtain(workspace, 'lists_create_with_container');\n    containerBlock.initSvg();\n    var connection = containerBlock.getInput('STACK').connection;\n    for (var x = 0; x < this.itemCount_; x++) {\n      var itemBlock = Blockly.Block.obtain(workspace, 'lists_create_with_item');\n      itemBlock.initSvg();\n      connection.connect(itemBlock.previousConnection);\n      connection = itemBlock.nextConnection;\n    }\n    return containerBlock;\n  },\n  compose: function(containerBlock) {\n    // Disconnect all input blocks and remove all inputs.\n    if (this.itemCount_ == 0) {\n      this.removeInput('EMPTY');\n    } else {\n      for (var x = this.itemCount_ - 1; x >= 0; x--) {\n        this.removeInput('ADD' + x);\n      }\n    }\n    this.itemCount_ = 0;\n    // Rebuild the block's inputs.\n    var itemBlock = containerBlock.getInputTargetBlock('STACK');\n    while (itemBlock) {\n      var input = this.appendValueInput('ADD' + this.itemCount_);\n      if (this.itemCount_ == 0) {\n        input.appendField(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);\n      }\n      // Reconnect any child blocks.\n      if (itemBlock.valueConnection_) {\n        input.connection.connect(itemBlock.valueConnection_);\n      }\n      this.itemCount_++;\n      itemBlock = itemBlock.nextConnection &&\n          itemBlock.nextConnection.targetBlock();\n    }\n    if (this.itemCount_ == 0) {\n      this.appendDummyInput('EMPTY')\n          .appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);\n    }\n  },\n  saveConnections: function(containerBlock) {\n    // Store a pointer to any connected child blocks.\n    var itemBlock = containerBlock.getInputTargetBlock('STACK');\n    var x = 0;\n    while (itemBlock) {\n      var input = this.getInput('ADD' + x);\n      itemBlock.valueConnection_ = input && input.connection.targetConnection;\n      x++;\n      itemBlock = itemBlock.nextConnection &&\n          itemBlock.nextConnection.targetBlock();\n    }\n  }\n};\n\nBlockly.Blocks['lists_create_with_container'] = {\n  // Container.\n  init: function() {\n    this.setColour(260);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD);\n    this.appendStatementInput('STACK');\n    this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP);\n    this.contextMenu = false;\n  }\n};\n\nBlockly.Blocks['lists_create_with_item'] = {\n  // Add items.\n  init: function() {\n    this.setColour(260);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP);\n    this.contextMenu = false;\n  }\n};\n\nBlockly.Blocks['lists_repeat'] = {\n  // Create a list with one element repeated.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.LISTS_REPEAT_HELPURL);\n    this.setColour(260);\n    this.setOutput(true, 'Array');\n    this.interpolateMsg(Blockly.Msg.LISTS_REPEAT_TITLE,\n                        ['ITEM', null, Blockly.ALIGN_RIGHT],\n                        ['NUM', 'Number', Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT);\n    this.setTooltip(Blockly.Msg.LISTS_REPEAT_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['lists_length'] = {\n  // List length.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.LISTS_LENGTH_HELPURL);\n    this.setColour(260);\n    this.interpolateMsg(Blockly.Msg.LISTS_LENGTH_TITLE,\n                        ['VALUE', ['Array', 'String'], Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT);\n    this.setOutput(true, 'Number');\n    this.setTooltip(Blockly.Msg.LISTS_LENGTH_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['lists_isEmpty'] = {\n  // Is the list empty?\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.LISTS_IS_EMPTY_HELPURL);\n    this.setColour(260);\n    this.interpolateMsg(Blockly.Msg.LISTS_IS_EMPTY_TITLE,\n                        ['VALUE', ['Array', 'String'], Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT)\n    this.setInputsInline(true);\n    this.setOutput(true, 'Boolean');\n    this.setTooltip(Blockly.Msg.LISTS_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['lists_indexOf'] = {\n  // Find an item in the list.\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.LISTS_INDEX_OF_FIRST, 'FIRST'],\n         [Blockly.Msg.LISTS_INDEX_OF_LAST, 'LAST']];\n    this.setHelpUrl(Blockly.Msg.LISTS_INDEX_OF_HELPURL);\n    this.setColour(260);\n    this.setOutput(true, 'Number');\n    this.appendValueInput('VALUE')\n        .setCheck('Array')\n        .appendField(Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST);\n    this.appendValueInput('FIND')\n        .appendField(new Blockly.FieldDropdown(OPERATORS), 'END');\n    this.setInputsInline(true);\n    this.setTooltip(Blockly.Msg.LISTS_INDEX_OF_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['lists_getIndex'] = {\n  // Get element at index.\n  init: function() {\n    var MODE =\n        [[Blockly.Msg.LISTS_GET_INDEX_GET, 'GET'],\n         [Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE, 'GET_REMOVE'],\n         [Blockly.Msg.LISTS_GET_INDEX_REMOVE, 'REMOVE']];\n    this.WHERE_OPTIONS =\n        [[Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'],\n         [Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'],\n         [Blockly.Msg.LISTS_GET_INDEX_FIRST, 'FIRST'],\n         [Blockly.Msg.LISTS_GET_INDEX_LAST, 'LAST'],\n         [Blockly.Msg.LISTS_GET_INDEX_RANDOM, 'RANDOM']];\n    this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL);\n    this.setColour(260);\n    var modeMenu = new Blockly.FieldDropdown(MODE, function(value) {\n      var isStatement = (value == 'REMOVE');\n      this.sourceBlock_.updateStatement(isStatement);\n    });\n    this.appendValueInput('VALUE')\n        .setCheck('Array')\n        .appendField(Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST);\n    this.appendDummyInput()\n        .appendField(modeMenu, 'MODE')\n        .appendField('', 'SPACE');\n    this.appendDummyInput('AT');\n    if (Blockly.Msg.LISTS_GET_INDEX_TAIL) {\n      this.appendDummyInput('TAIL')\n          .appendField(Blockly.Msg.LISTS_GET_INDEX_TAIL);\n    }\n    this.setInputsInline(true);\n    this.setOutput(true);\n    this.updateAt(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var combo = thisBlock.getFieldValue('MODE') + '_' +\n          thisBlock.getFieldValue('WHERE');\n      return Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_' + combo];\n    });\n  },\n  mutationToDom: function() {\n    // Save whether the block is a statement or a value.\n    // Save whether there is an 'AT' input.\n    var container = document.createElement('mutation');\n    var isStatement = !this.outputConnection;\n    container.setAttribute('statement', isStatement);\n    var isAt = this.getInput('AT').type == Blockly.INPUT_VALUE;\n    container.setAttribute('at', isAt);\n    return container;\n  },\n  domToMutation: function(xmlElement) {\n    // Restore the block shape.\n    // Note: Until January 2013 this block did not have mutations,\n    // so 'statement' defaults to false and 'at' defaults to true.\n    var isStatement = (xmlElement.getAttribute('statement') == 'true');\n    this.updateStatement(isStatement);\n    var isAt = (xmlElement.getAttribute('at') != 'false');\n    this.updateAt(isAt);\n  },\n  updateStatement: function(newStatement) {\n    // Switch between a value block and a statement block.\n    var oldStatement = !this.outputConnection;\n    if (newStatement != oldStatement) {\n      this.unplug(true, true);\n      if (newStatement) {\n        this.setOutput(false);\n        this.setPreviousStatement(true);\n        this.setNextStatement(true);\n      } else {\n        this.setPreviousStatement(false);\n        this.setNextStatement(false);\n        this.setOutput(true);\n      }\n    }\n  },\n  updateAt: function(isAt) {\n    // Create or delete an input for the numeric index.\n    // Destroy old 'AT' and 'ORDINAL' inputs.\n    this.removeInput('AT');\n    this.removeInput('ORDINAL', true);\n    // Create either a value 'AT' input or a dummy input.\n    if (isAt) {\n      this.appendValueInput('AT').setCheck('Number');\n      if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {\n        this.appendDummyInput('ORDINAL')\n            .appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);\n      }\n    } else {\n      this.appendDummyInput('AT');\n    }\n    var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) {\n      var newAt = (value == 'FROM_START') || (value == 'FROM_END');\n      // The 'isAt' variable is available due to this function being a closure.\n      if (newAt != isAt) {\n        var block = this.sourceBlock_;\n        block.updateAt(newAt);\n        // This menu has been destroyed and replaced.  Update the replacement.\n        block.setFieldValue(value, 'WHERE');\n        return null;\n      }\n      return undefined;\n    });\n    this.getInput('AT').appendField(menu, 'WHERE');\n    if (Blockly.Msg.LISTS_GET_INDEX_TAIL) {\n      this.moveInputBefore('TAIL', null);\n    }\n  }\n};\n\nBlockly.Blocks['lists_setIndex'] = {\n  // Set element at index.\n  init: function() {\n    var MODE =\n        [[Blockly.Msg.LISTS_SET_INDEX_SET, 'SET'],\n         [Blockly.Msg.LISTS_SET_INDEX_INSERT, 'INSERT']];\n    this.WHERE_OPTIONS =\n        [[Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'],\n         [Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'],\n         [Blockly.Msg.LISTS_GET_INDEX_FIRST, 'FIRST'],\n         [Blockly.Msg.LISTS_GET_INDEX_LAST, 'LAST'],\n         [Blockly.Msg.LISTS_GET_INDEX_RANDOM, 'RANDOM']];\n    this.setHelpUrl(Blockly.Msg.LISTS_SET_INDEX_HELPURL);\n    this.setColour(260);\n    this.appendValueInput('LIST')\n        .setCheck('Array')\n        .appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST);\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldDropdown(MODE), 'MODE')\n        .appendField('', 'SPACE');\n    this.appendDummyInput('AT');\n    this.appendValueInput('TO')\n        .appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_TO);\n    this.setInputsInline(true);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_TOOLTIP);\n    this.updateAt(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var combo = thisBlock.getFieldValue('MODE') + '_' +\n          thisBlock.getFieldValue('WHERE');\n      return Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_' + combo];\n    });\n  },\n  mutationToDom: function() {\n    // Save whether there is an 'AT' input.\n    var container = document.createElement('mutation');\n    var isAt = this.getInput('AT').type == Blockly.INPUT_VALUE;\n    container.setAttribute('at', isAt);\n    return container;\n  },\n  domToMutation: function(xmlElement) {\n    // Restore the block shape.\n    // Note: Until January 2013 this block did not have mutations,\n    // so 'at' defaults to true.\n    var isAt = (xmlElement.getAttribute('at') != 'false');\n    this.updateAt(isAt);\n  },\n  updateAt: function(isAt) {\n    // Create or delete an input for the numeric index.\n    // Destroy old 'AT' and 'ORDINAL' input.\n    this.removeInput('AT');\n    this.removeInput('ORDINAL', true);\n    // Create either a value 'AT' input or a dummy input.\n    if (isAt) {\n      this.appendValueInput('AT').setCheck('Number');\n      if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {\n        this.appendDummyInput('ORDINAL')\n            .appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);\n      }\n    } else {\n      this.appendDummyInput('AT');\n    }\n    var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) {\n      var newAt = (value == 'FROM_START') || (value == 'FROM_END');\n      // The 'isAt' variable is available due to this function being a closure.\n      if (newAt != isAt) {\n        var block = this.sourceBlock_;\n        block.updateAt(newAt);\n        // This menu has been destroyed and replaced.  Update the replacement.\n        block.setFieldValue(value, 'WHERE');\n        return null;\n      }\n      return undefined;\n    });\n    this.moveInputBefore('AT', 'TO');\n    if (this.getInput('ORDINAL')) {\n      this.moveInputBefore('ORDINAL', 'TO');\n    }\n\n    this.getInput('AT').appendField(menu, 'WHERE');\n  }\n};\n\nBlockly.Blocks['lists_getSublist'] = {\n  // Get sublist.\n  init: function() {\n    this.WHERE_OPTIONS_1 =\n        [[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START, 'FROM_START'],\n         [Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END, 'FROM_END'],\n         [Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST, 'FIRST']];\n    this.WHERE_OPTIONS_2 =\n        [[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START, 'FROM_START'],\n         [Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END, 'FROM_END'],\n         [Blockly.Msg.LISTS_GET_SUBLIST_END_LAST, 'LAST']];\n    this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL);\n    this.setColour(260);\n    this.appendValueInput('LIST')\n        .setCheck('Array')\n        .appendField(Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST);\n    this.appendDummyInput('AT1');\n    this.appendDummyInput('AT2');\n    if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) {\n      this.appendDummyInput('TAIL')\n          .appendField(Blockly.Msg.LISTS_GET_SUBLIST_TAIL);\n    }\n    this.setInputsInline(true);\n    this.setOutput(true, 'Array');\n    this.updateAt(1, true);\n    this.updateAt(2, true);\n    this.setTooltip(Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP);\n  },\n  mutationToDom: function() {\n    // Save whether there are 'AT' inputs.\n    var container = document.createElement('mutation');\n    var isAt1 = this.getInput('AT1').type == Blockly.INPUT_VALUE;\n    container.setAttribute('at1', isAt1);\n    var isAt2 = this.getInput('AT2').type == Blockly.INPUT_VALUE;\n    container.setAttribute('at2', isAt2);\n    return container;\n  },\n  domToMutation: function(xmlElement) {\n    // Restore the block shape.\n    var isAt1 = (xmlElement.getAttribute('at1') == 'true');\n    var isAt2 = (xmlElement.getAttribute('at2') == 'true');\n    this.updateAt(1, isAt1);\n    this.updateAt(2, isAt2);\n  },\n  updateAt: function(n, isAt) {\n    // Create or delete an input for the numeric index.\n    // Destroy old 'AT' and 'ORDINAL' inputs.\n    this.removeInput('AT' + n);\n    this.removeInput('ORDINAL' + n, true);\n    // Create either a value 'AT' input or a dummy input.\n    if (isAt) {\n      this.appendValueInput('AT' + n).setCheck('Number');\n      if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {\n        this.appendDummyInput('ORDINAL' + n)\n            .appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);\n      }\n    } else {\n      this.appendDummyInput('AT' + n);\n    }\n    var menu = new Blockly.FieldDropdown(this['WHERE_OPTIONS_' + n],\n        function(value) {\n      var newAt = (value == 'FROM_START') || (value == 'FROM_END');\n      // The 'isAt' variable is available due to this function being a closure.\n      if (newAt != isAt) {\n        var block = this.sourceBlock_;\n        block.updateAt(n, newAt);\n        // This menu has been destroyed and replaced.  Update the replacement.\n        block.setFieldValue(value, 'WHERE' + n);\n        return null;\n      }\n      return undefined;\n    });\n    this.getInput('AT' + n)\n        .appendField(menu, 'WHERE' + n);\n    if (n == 1) {\n      this.moveInputBefore('AT1', 'AT2');\n      if (this.getInput('ORDINAL1')) {\n        this.moveInputBefore('ORDINAL1', 'AT2');\n      }\n    }\n    if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) {\n      this.moveInputBefore('TAIL', null);\n    }\n  }\n};\n"
  },
  {
    "path": "extern/blockly/blocks/logic.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Logic blocks for Blockly.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Blocks.logic');\n\ngoog.require('Blockly.Blocks');\n\n\nBlockly.Blocks['controls_if'] = {\n  // If/elseif/else condition.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL);\n    this.setColour(210);\n    this.appendValueInput('IF0')\n        .setCheck('Boolean')\n        .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF);\n    this.appendStatementInput('DO0')\n        .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setMutator(new Blockly.Mutator(['controls_if_elseif',\n                                         'controls_if_else']));\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      if (!thisBlock.elseifCount_ && !thisBlock.elseCount_) {\n        return Blockly.Msg.CONTROLS_IF_TOOLTIP_1;\n      } else if (!thisBlock.elseifCount_ && thisBlock.elseCount_) {\n        return Blockly.Msg.CONTROLS_IF_TOOLTIP_2;\n      } else if (thisBlock.elseifCount_ && !thisBlock.elseCount_) {\n        return Blockly.Msg.CONTROLS_IF_TOOLTIP_3;\n      } else if (thisBlock.elseifCount_ && thisBlock.elseCount_) {\n        return Blockly.Msg.CONTROLS_IF_TOOLTIP_4;\n      }\n      return '';\n    });\n    this.elseifCount_ = 0;\n    this.elseCount_ = 0;\n  },\n  mutationToDom: function() {\n    if (!this.elseifCount_ && !this.elseCount_) {\n      return null;\n    }\n    var container = document.createElement('mutation');\n    if (this.elseifCount_) {\n      container.setAttribute('elseif', this.elseifCount_);\n    }\n    if (this.elseCount_) {\n      container.setAttribute('else', 1);\n    }\n    return container;\n  },\n  domToMutation: function(xmlElement) {\n    this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10);\n    this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10);\n    for (var x = 1; x <= this.elseifCount_; x++) {\n      this.appendValueInput('IF' + x)\n          .setCheck('Boolean')\n          .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF);\n      this.appendStatementInput('DO' + x)\n          .appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);\n    }\n    if (this.elseCount_) {\n      this.appendStatementInput('ELSE')\n          .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE);\n    }\n  },\n  decompose: function(workspace) {\n    var containerBlock = Blockly.Block.obtain(workspace, 'controls_if_if');\n    containerBlock.initSvg();\n    var connection = containerBlock.getInput('STACK').connection;\n    for (var x = 1; x <= this.elseifCount_; x++) {\n      var elseifBlock = Blockly.Block.obtain(workspace, 'controls_if_elseif');\n      elseifBlock.initSvg();\n      connection.connect(elseifBlock.previousConnection);\n      connection = elseifBlock.nextConnection;\n    }\n    if (this.elseCount_) {\n      var elseBlock = Blockly.Block.obtain(workspace, 'controls_if_else');\n      elseBlock.initSvg();\n      connection.connect(elseBlock.previousConnection);\n    }\n    return containerBlock;\n  },\n  compose: function(containerBlock) {\n    // Disconnect the else input blocks and remove the inputs.\n    if (this.elseCount_) {\n      this.removeInput('ELSE');\n    }\n    this.elseCount_ = 0;\n    // Disconnect all the elseif input blocks and remove the inputs.\n    for (var x = this.elseifCount_; x > 0; x--) {\n      this.removeInput('IF' + x);\n      this.removeInput('DO' + x);\n    }\n    this.elseifCount_ = 0;\n    // Rebuild the block's optional inputs.\n    var clauseBlock = containerBlock.getInputTargetBlock('STACK');\n    while (clauseBlock) {\n      switch (clauseBlock.type) {\n        case 'controls_if_elseif':\n          this.elseifCount_++;\n          var ifInput = this.appendValueInput('IF' + this.elseifCount_)\n              .setCheck('Boolean')\n              .appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF);\n          var doInput = this.appendStatementInput('DO' + this.elseifCount_);\n          doInput.appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);\n          // Reconnect any child blocks.\n          if (clauseBlock.valueConnection_) {\n            ifInput.connection.connect(clauseBlock.valueConnection_);\n          }\n          if (clauseBlock.statementConnection_) {\n            doInput.connection.connect(clauseBlock.statementConnection_);\n          }\n          break;\n        case 'controls_if_else':\n          this.elseCount_++;\n          var elseInput = this.appendStatementInput('ELSE');\n          elseInput.appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE);\n          // Reconnect any child blocks.\n          if (clauseBlock.statementConnection_) {\n            elseInput.connection.connect(clauseBlock.statementConnection_);\n          }\n          break;\n        default:\n          throw 'Unknown block type.';\n      }\n      clauseBlock = clauseBlock.nextConnection &&\n          clauseBlock.nextConnection.targetBlock();\n    }\n  },\n  saveConnections: function(containerBlock) {\n    // Store a pointer to any connected child blocks.\n    var clauseBlock = containerBlock.getInputTargetBlock('STACK');\n    var x = 1;\n    while (clauseBlock) {\n      switch (clauseBlock.type) {\n        case 'controls_if_elseif':\n          var inputIf = this.getInput('IF' + x);\n          var inputDo = this.getInput('DO' + x);\n          clauseBlock.valueConnection_ =\n              inputIf && inputIf.connection.targetConnection;\n          clauseBlock.statementConnection_ =\n              inputDo && inputDo.connection.targetConnection;\n          x++;\n          break;\n        case 'controls_if_else':\n          var inputDo = this.getInput('ELSE');\n          clauseBlock.statementConnection_ =\n              inputDo && inputDo.connection.targetConnection;\n          break;\n        default:\n          throw 'Unknown block type.';\n      }\n      clauseBlock = clauseBlock.nextConnection &&\n          clauseBlock.nextConnection.targetBlock();\n    }\n  }\n};\n\nBlockly.Blocks['controls_if_if'] = {\n  // If condition.\n  init: function() {\n    this.setColour(210);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF);\n    this.appendStatementInput('STACK');\n    this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP);\n    this.contextMenu = false;\n  }\n};\n\nBlockly.Blocks['controls_if_elseif'] = {\n  // Else-If condition.\n  init: function() {\n    this.setColour(210);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP);\n    this.contextMenu = false;\n  }\n};\n\nBlockly.Blocks['controls_if_else'] = {\n  // Else condition.\n  init: function() {\n    this.setColour(210);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE);\n    this.setPreviousStatement(true);\n    this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP);\n    this.contextMenu = false;\n  }\n};\n\nBlockly.Blocks['logic_compare'] = {\n  // Comparison operator.\n  init: function() {\n    var OPERATORS = Blockly.RTL ? [\n          ['=', 'EQ'],\n          ['\\u2260', 'NEQ'],\n          ['>', 'LT'],\n          ['\\u2265', 'LTE'],\n          ['<', 'GT'],\n          ['\\u2264', 'GTE']\n        ] : [\n          ['=', 'EQ'],\n          ['\\u2260', 'NEQ'],\n          ['<', 'LT'],\n          ['\\u2264', 'LTE'],\n          ['>', 'GT'],\n          ['\\u2265', 'GTE']\n        ];\n    this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL);\n    this.setColour(210);\n    this.setOutput(true, 'Boolean');\n    this.appendValueInput('A');\n    this.appendValueInput('B')\n        .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP');\n    this.setInputsInline(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var op = thisBlock.getFieldValue('OP');\n      var TOOLTIPS = {\n        EQ: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ,\n        NEQ: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ,\n        LT: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT,\n        LTE: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE,\n        GT: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT,\n        GTE: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE\n      };\n      return TOOLTIPS[op];\n    });\n  }\n};\n\nBlockly.Blocks['logic_operation'] = {\n  // Logical operations: 'and', 'or'.\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.LOGIC_OPERATION_AND, 'AND'],\n         [Blockly.Msg.LOGIC_OPERATION_OR, 'OR']];\n    this.setHelpUrl(Blockly.Msg.LOGIC_OPERATION_HELPURL);\n    this.setColour(210);\n    this.setOutput(true, 'Boolean');\n    this.appendValueInput('A')\n        .setCheck('Boolean');\n    this.appendValueInput('B')\n        .setCheck('Boolean')\n        .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP');\n    this.setInputsInline(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var op = thisBlock.getFieldValue('OP');\n      var TOOLTIPS = {\n        AND: Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND,\n        OR: Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR\n      };\n      return TOOLTIPS[op];\n    });\n  }\n};\n\n\nBlockly.Blocks['logic_negate'] = {\n  // Negation.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.LOGIC_NEGATE_HELPURL);\n    this.setColour(210);\n    this.setOutput(true, 'Boolean');\n    this.interpolateMsg(Blockly.Msg.LOGIC_NEGATE_TITLE,\n                        ['BOOL', 'Boolean', Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT);\n    this.setTooltip(Blockly.Msg.LOGIC_NEGATE_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['logic_boolean'] = {\n  // Boolean data type: true and false.\n  init: function() {\n    var BOOLEANS =\n        [[Blockly.Msg.LOGIC_BOOLEAN_TRUE, 'TRUE'],\n         [Blockly.Msg.LOGIC_BOOLEAN_FALSE, 'FALSE']];\n    this.setHelpUrl(Blockly.Msg.LOGIC_BOOLEAN_HELPURL);\n    this.setColour(210);\n    this.setOutput(true, 'Boolean');\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldDropdown(BOOLEANS), 'BOOL');\n    this.setTooltip(Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['logic_null'] = {\n  // Null data type.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.LOGIC_NULL_HELPURL);\n    this.setColour(210);\n    this.setOutput(true);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.LOGIC_NULL);\n    this.setTooltip(Blockly.Msg.LOGIC_NULL_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['logic_ternary'] = {\n  // Ternary operator.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.LOGIC_TERNARY_HELPURL);\n    this.setColour(210);\n    this.appendValueInput('IF')\n        .setCheck('Boolean')\n        .appendField(Blockly.Msg.LOGIC_TERNARY_CONDITION);\n    this.appendValueInput('THEN')\n        .appendField(Blockly.Msg.LOGIC_TERNARY_IF_TRUE);\n    this.appendValueInput('ELSE')\n        .appendField(Blockly.Msg.LOGIC_TERNARY_IF_FALSE);\n    this.setOutput(true);\n    this.setTooltip(Blockly.Msg.LOGIC_TERNARY_TOOLTIP);\n  }\n};\n"
  },
  {
    "path": "extern/blockly/blocks/loops.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Loop blocks for Blockly.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Blocks.loops');\n\ngoog.require('Blockly.Blocks');\n\n\nBlockly.Blocks['controls_repeat'] = {\n  // Repeat n times (internal number).\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL);\n    this.setColour(120);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT)\n        .appendField(new Blockly.FieldTextInput('10',\n            Blockly.FieldTextInput.nonnegativeIntegerValidator), 'TIMES')\n        .appendField(Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES);\n    this.appendStatementInput('DO')\n        .appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['controls_repeat_ext'] = {\n  // Repeat n times (external number).\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL);\n    this.setColour(120);\n    this.interpolateMsg(Blockly.Msg.CONTROLS_REPEAT_TITLE,\n                        ['TIMES', 'Number', Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT);\n    this.appendStatementInput('DO')\n        .appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setInputsInline(true);\n    this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['controls_whileUntil'] = {\n  // Do while/until loop.\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE, 'WHILE'],\n         [Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL, 'UNTIL']];\n    this.setHelpUrl(Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL);\n    this.setColour(120);\n    this.appendValueInput('BOOL')\n        .setCheck('Boolean')\n        .appendField(new Blockly.FieldDropdown(OPERATORS), 'MODE');\n    this.appendStatementInput('DO')\n        .appendField(Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var op = thisBlock.getFieldValue('MODE');\n      var TOOLTIPS = {\n        WHILE: Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE,\n        UNTIL: Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\n      };\n      return TOOLTIPS[op];\n    });\n  }\n};\n\nBlockly.Blocks['controls_for'] = {\n  // For loop.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.CONTROLS_FOR_HELPURL);\n    this.setColour(120);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH)\n        .appendField(new Blockly.FieldVariable(null), 'VAR');\n    this.interpolateMsg(Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY,\n                        ['FROM', 'Number', Blockly.ALIGN_RIGHT],\n                        ['TO', 'Number', Blockly.ALIGN_RIGHT],\n                        ['BY', 'Number', Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT);\n    this.appendStatementInput('DO')\n        .appendField(Blockly.Msg.CONTROLS_FOR_INPUT_DO);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setInputsInline(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1',\n          thisBlock.getFieldValue('VAR'));\n    });\n  },\n  getVars: function() {\n    return [this.getFieldValue('VAR')];\n  },\n  renameVar: function(oldName, newName) {\n    if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {\n      this.setFieldValue(newName, 'VAR');\n    }\n  },\n  customContextMenu: function(options) {\n    var option = {enabled: true};\n    var name = this.getFieldValue('VAR');\n    option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name);\n    var xmlField = goog.dom.createDom('field', null, name);\n    xmlField.setAttribute('name', 'VAR');\n    var xmlBlock = goog.dom.createDom('block', null, xmlField);\n    xmlBlock.setAttribute('type', 'variables_get');\n    option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);\n    options.push(option);\n  }\n};\n\nBlockly.Blocks['controls_forEach'] = {\n  // For each loop.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.CONTROLS_FOREACH_HELPURL);\n    this.setColour(120);\n    this.appendValueInput('LIST')\n        .setCheck('Array')\n        .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM)\n        .appendField(new Blockly.FieldVariable(null), 'VAR')\n        .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST);\n    if (Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL) {\n      this.appendDummyInput()\n          .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL);\n      this.setInputsInline(true);\n    }\n    this.appendStatementInput('DO')\n        .appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_DO);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      return Blockly.Msg.CONTROLS_FOREACH_TOOLTIP.replace('%1',\n          thisBlock.getFieldValue('VAR'));\n    });\n  },\n  getVars: function() {\n    return [this.getFieldValue('VAR')];\n  },\n  renameVar: function(oldName, newName) {\n    if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {\n      this.setFieldValue(newName, 'VAR');\n    }\n  },\n  customContextMenu: Blockly.Blocks['controls_for'].customContextMenu\n};\n\nBlockly.Blocks['controls_flow_statements'] = {\n  // Flow statements: continue, break.\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK, 'BREAK'],\n         [Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE, 'CONTINUE']];\n    this.setHelpUrl(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL);\n    this.setColour(120);\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldDropdown(OPERATORS), 'FLOW');\n    this.setPreviousStatement(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var op = thisBlock.getFieldValue('FLOW');\n      var TOOLTIPS = {\n        BREAK: Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK,\n        CONTINUE: Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\n      };\n      return thisBlock.TOOLTIPS[op];\n    });\n  },\n  onchange: function() {\n    if (!this.workspace) {\n      // Block has been deleted.\n      return;\n    }\n    var legal = false;\n    // Is the block nested in a control statement?\n    var block = this;\n    do {\n      if (block.type == 'controls_repeat' ||\n          block.type == 'controls_repeat_ext' ||\n          block.type == 'controls_forEach' ||\n          block.type == 'controls_for' ||\n          block.type == 'controls_whileUntil') {\n        legal = true;\n        break;\n      }\n      block = block.getSurroundParent();\n    } while (block);\n    if (legal) {\n      this.setWarningText(null);\n    } else {\n      this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING);\n    }\n  }\n};\n"
  },
  {
    "path": "extern/blockly/blocks/math.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Math blocks for Blockly.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Blocks.math');\n\ngoog.require('Blockly.Blocks');\n\n\nBlockly.Blocks['math_number'] = {\n  // Numeric value.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL);\n    this.setColour(230);\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldTextInput('0',\n        Blockly.FieldTextInput.numberValidator), 'NUM');\n    this.setOutput(true, 'Number');\n    this.setTooltip(Blockly.Msg.MATH_NUMBER_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['math_arithmetic'] = {\n  // Basic arithmetic operator.\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.MATH_ADDITION_SYMBOL, 'ADD'],\n         [Blockly.Msg.MATH_SUBTRACTION_SYMBOL, 'MINUS'],\n         [Blockly.Msg.MATH_MULTIPLICATION_SYMBOL, 'MULTIPLY'],\n         [Blockly.Msg.MATH_DIVISION_SYMBOL, 'DIVIDE'],\n         [Blockly.Msg.MATH_POWER_SYMBOL, 'POWER']];\n    this.setHelpUrl(Blockly.Msg.MATH_ARITHMETIC_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.appendValueInput('A')\n        .setCheck('Number');\n    this.appendValueInput('B')\n        .setCheck('Number')\n        .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP');\n    this.setInputsInline(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var mode = thisBlock.getFieldValue('OP');\n      var TOOLTIPS = {\n        ADD: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,\n        MINUS: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,\n        MULTIPLY: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,\n        DIVIDE: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,\n        POWER: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER\n      };\n      return TOOLTIPS[mode];\n    });\n  }\n};\n\nBlockly.Blocks['math_single'] = {\n  // Advanced math operators with single operand.\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.MATH_SINGLE_OP_ROOT, 'ROOT'],\n         [Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE, 'ABS'],\n         ['-', 'NEG'],\n         ['ln', 'LN'],\n         ['log10', 'LOG10'],\n         ['e^', 'EXP'],\n         ['10^', 'POW10']];\n    this.setHelpUrl(Blockly.Msg.MATH_SINGLE_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.interpolateMsg('%1 %2',\n        ['OP', new Blockly.FieldDropdown(OPERATORS)],\n        ['NUM', 'Number', Blockly.ALIGN_RIGHT],\n        Blockly.ALIGN_RIGHT);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var mode = thisBlock.getFieldValue('OP');\n      var TOOLTIPS = {\n        ROOT: Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT,\n        ABS: Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS,\n        NEG: Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG,\n        LN: Blockly.Msg.MATH_SINGLE_TOOLTIP_LN,\n        LOG10: Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10,\n        EXP: Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP,\n        POW10: Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10\n      };\n      return TOOLTIPS[mode];\n    });\n  }\n};\n\nBlockly.Blocks['math_trig'] = {\n  // Trigonometry operators.\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.MATH_TRIG_SIN, 'SIN'],\n         [Blockly.Msg.MATH_TRIG_COS, 'COS'],\n         [Blockly.Msg.MATH_TRIG_TAN, 'TAN'],\n         [Blockly.Msg.MATH_TRIG_ASIN, 'ASIN'],\n         [Blockly.Msg.MATH_TRIG_ACOS, 'ACOS'],\n         [Blockly.Msg.MATH_TRIG_ATAN, 'ATAN']];\n    this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.appendValueInput('NUM')\n        .setCheck('Number')\n        .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP');\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      var mode = thisBlock.getFieldValue('OP');\n      var TOOLTIPS = {\n        SIN: Blockly.Msg.MATH_TRIG_TOOLTIP_SIN,\n        COS: Blockly.Msg.MATH_TRIG_TOOLTIP_COS,\n        TAN: Blockly.Msg.MATH_TRIG_TOOLTIP_TAN,\n        ASIN: Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN,\n        ACOS: Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS,\n        ATAN: Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN\n      };\n      return TOOLTIPS[mode];\n    });\n  }\n};\n\nBlockly.Blocks['math_constant'] = {\n  // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.\n  init: function() {\n    var CONSTANTS =\n        [['\\u03c0', 'PI'],\n         ['e', 'E'],\n         ['\\u03c6', 'GOLDEN_RATIO'],\n         ['sqrt(2)', 'SQRT2'],\n         ['sqrt(\\u00bd)', 'SQRT1_2'],\n         ['\\u221e', 'INFINITY']];\n    this.setHelpUrl(Blockly.Msg.MATH_CONSTANT_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldDropdown(CONSTANTS), 'CONSTANT');\n    this.setTooltip(Blockly.Msg.MATH_CONSTANT_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['math_number_property'] = {\n  // Check if a number is even, odd, prime, whole, positive, or negative\n  // or if it is divisible by certain number. Returns true or false.\n  init: function() {\n    var PROPERTIES =\n        [[Blockly.Msg.MATH_IS_EVEN, 'EVEN'],\n         [Blockly.Msg.MATH_IS_ODD, 'ODD'],\n         [Blockly.Msg.MATH_IS_PRIME, 'PRIME'],\n         [Blockly.Msg.MATH_IS_WHOLE, 'WHOLE'],\n         [Blockly.Msg.MATH_IS_POSITIVE, 'POSITIVE'],\n         [Blockly.Msg.MATH_IS_NEGATIVE, 'NEGATIVE'],\n         [Blockly.Msg.MATH_IS_DIVISIBLE_BY, 'DIVISIBLE_BY']];\n    this.setColour(230);\n    this.appendValueInput('NUMBER_TO_CHECK')\n        .setCheck('Number');\n    var dropdown = new Blockly.FieldDropdown(PROPERTIES, function(option) {\n      var divisorInput = (option == 'DIVISIBLE_BY');\n      this.sourceBlock_.updateShape(divisorInput);\n    });\n    this.appendDummyInput()\n        .appendField(dropdown, 'PROPERTY');\n    this.setInputsInline(true);\n    this.setOutput(true, 'Boolean');\n    this.setTooltip(Blockly.Msg.MATH_IS_TOOLTIP);\n  },\n  mutationToDom: function() {\n    // Save whether the 'divisorInput' should be true of false (present or not).\n    var container = document.createElement('mutation');\n    var divisorInput = (this.getFieldValue('PROPERTY') == 'DIVISIBLE_BY');\n    container.setAttribute('divisor_input', divisorInput);\n    return container;\n  },\n  domToMutation: function(xmlElement) {\n    // Restore the 'divisorInput'.\n    var divisorInput = (xmlElement.getAttribute('divisor_input') == 'true');\n    this.updateShape(divisorInput);\n  },\n  updateShape: function(divisorInput) {\n    // Add or remove a Value Input.\n    var inputExists = this.getInput('DIVISOR');\n    if (divisorInput) {\n      if (!inputExists) {\n        this.appendValueInput('DIVISOR')\n                 .setCheck('Number');\n      }\n    } else if (inputExists) {\n      this.removeInput('DIVISOR');\n    }\n  }\n};\n\nBlockly.Blocks['math_change'] = {\n  // Add to a variable in place.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.MATH_CHANGE_HELPURL);\n    this.setColour(230);\n    this.interpolateMsg(\n        // TODO: Combine these messages instead of using concatenation.\n        Blockly.Msg.MATH_CHANGE_TITLE_CHANGE + ' %1 ' +\n        Blockly.Msg.MATH_CHANGE_INPUT_BY + ' %2',\n        ['VAR', new Blockly.FieldVariable(Blockly.Msg.MATH_CHANGE_TITLE_ITEM)],\n        ['DELTA', 'Number', Blockly.ALIGN_RIGHT],\n        Blockly.ALIGN_RIGHT);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    // Assign 'this' to a variable for use in the tooltip closure below.\n    var thisBlock = this;\n    this.setTooltip(function() {\n      return Blockly.Msg.MATH_CHANGE_TOOLTIP.replace('%1',\n          thisBlock.getFieldValue('VAR'));\n    });\n  },\n  getVars: function() {\n    return [this.getFieldValue('VAR')];\n  },\n  renameVar: function(oldName, newName) {\n    if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {\n      this.setFieldValue(newName, 'VAR');\n    }\n  }\n};\n\nBlockly.Blocks['math_round'] = {\n  // Rounding functions.\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.MATH_ROUND_OPERATOR_ROUND, 'ROUND'],\n         [Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP, 'ROUNDUP'],\n         [Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN, 'ROUNDDOWN']];\n    this.setHelpUrl(Blockly.Msg.MATH_ROUND_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.appendValueInput('NUM')\n        .setCheck('Number')\n        .appendField(new Blockly.FieldDropdown(OPERATORS), 'OP');\n    this.setTooltip(Blockly.Msg.MATH_ROUND_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['math_on_list'] = {\n  // Evaluate a list of numbers to return sum, average, min, max, etc.\n  // Some functions also work on text (min, max, mode, median).\n  init: function() {\n    var OPERATORS =\n        [[Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'SUM'],\n         [Blockly.Msg.MATH_ONLIST_OPERATOR_MIN, 'MIN'],\n         [Blockly.Msg.MATH_ONLIST_OPERATOR_MAX, 'MAX'],\n         [Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE, 'AVERAGE'],\n         [Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN, 'MEDIAN'],\n         [Blockly.Msg.MATH_ONLIST_OPERATOR_MODE, 'MODE'],\n         [Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV, 'STD_DEV'],\n         [Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM, 'RANDOM']];\n    // Assign 'this' to a variable for use in the closure below.\n    var thisBlock = this;\n    this.setHelpUrl(Blockly.Msg.MATH_ONLIST_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    var dropdown = new Blockly.FieldDropdown(OPERATORS, function(newOp) {\n      if (newOp == 'MODE') {\n        thisBlock.outputConnection.setCheck('Array');\n      } else {\n        thisBlock.outputConnection.setCheck('Number');\n      }\n    });\n    this.appendValueInput('LIST')\n        .setCheck('Array')\n        .appendField(dropdown, 'OP');\n    this.setTooltip(function() {\n      var mode = thisBlock.getFieldValue('OP');\n      var TOOLTIPS = {\n        SUM: Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM,\n        MIN: Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN,\n        MAX: Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX,\n        AVERAGE: Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE,\n        MEDIAN: Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN,\n        MODE: Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE,\n        STD_DEV: Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV,\n        RANDOM: Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM\n      };\n      return TOOLTIPS[mode];\n    });\n  }\n};\n\nBlockly.Blocks['math_modulo'] = {\n  // Remainder of a division.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.MATH_MODULO_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.interpolateMsg(Blockly.Msg.MATH_MODULO_TITLE,\n                        ['DIVIDEND', 'Number', Blockly.ALIGN_RIGHT],\n                        ['DIVISOR', 'Number', Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT);\n    this.setInputsInline(true);\n    this.setTooltip(Blockly.Msg.MATH_MODULO_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['math_constrain'] = {\n  // Constrain a number between two limits.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.MATH_CONSTRAIN_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.interpolateMsg(Blockly.Msg.MATH_CONSTRAIN_TITLE,\n                        ['VALUE', 'Number', Blockly.ALIGN_RIGHT],\n                        ['LOW', 'Number', Blockly.ALIGN_RIGHT],\n                        ['HIGH', 'Number', Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT)\n    this.setInputsInline(true);\n    this.setTooltip(Blockly.Msg.MATH_CONSTRAIN_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['math_random_int'] = {\n  // Random integer between [X] and [Y].\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.MATH_RANDOM_INT_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.interpolateMsg(Blockly.Msg.MATH_RANDOM_INT_TITLE,\n                        ['FROM', 'Number', Blockly.ALIGN_RIGHT],\n                        ['TO', 'Number', Blockly.ALIGN_RIGHT],\n                        Blockly.ALIGN_RIGHT);\n    this.setInputsInline(true);\n    this.setTooltip(Blockly.Msg.MATH_RANDOM_INT_TOOLTIP);\n  }\n};\n\nBlockly.Blocks['math_random_float'] = {\n  // Random fraction between 0 and 1.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL);\n    this.setColour(230);\n    this.setOutput(true, 'Number');\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM);\n    this.setTooltip(Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP);\n  }\n};\n"
  },
  {
    "path": "extern/blockly/blocks/procedures.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Procedure blocks for Blockly.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Blocks.procedures');\n\ngoog.require('Blockly.Blocks');\n\n\nBlockly.Blocks['procedures_defnoreturn'] = {\n  // Define a procedure with no return value.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL);\n    this.setColour(290);\n    var name = Blockly.Procedures.findLegalName(\n        Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE, this);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE)\n        .appendField(new Blockly.FieldTextInput(name,\n        Blockly.Procedures.rename), 'NAME')\n        .appendField('', 'PARAMS');\n    this.appendStatementInput('STACK')\n        .appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_DO);\n    this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));\n    this.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP);\n    this.arguments_ = [];\n  },\n  updateParams_: function() {\n    // Check for duplicated arguments.\n    var badArg = false;\n    var hash = {};\n    for (var x = 0; x < this.arguments_.length; x++) {\n      if (hash['arg_' + this.arguments_[x].toLowerCase()]) {\n        badArg = true;\n        break;\n      }\n      hash['arg_' + this.arguments_[x].toLowerCase()] = true;\n    }\n    if (badArg) {\n      this.setWarningText(Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING);\n    } else {\n      this.setWarningText(null);\n    }\n    // Merge the arguments into a human-readable list.\n    var paramString = '';\n    if (this.arguments_.length) {\n      paramString = Blockly.Msg.PROCEDURES_BEFORE_PARAMS +\n          ' ' + this.arguments_.join(', ');\n    }\n    this.setFieldValue(paramString, 'PARAMS');\n  },\n  mutationToDom: function() {\n    var container = document.createElement('mutation');\n    for (var x = 0; x < this.arguments_.length; x++) {\n      var parameter = document.createElement('arg');\n      parameter.setAttribute('name', this.arguments_[x]);\n      container.appendChild(parameter);\n    }\n    return container;\n  },\n  domToMutation: function(xmlElement) {\n    this.arguments_ = [];\n    for (var x = 0, childNode; childNode = xmlElement.childNodes[x]; x++) {\n      if (childNode.nodeName.toLowerCase() == 'arg') {\n        this.arguments_.push(childNode.getAttribute('name'));\n      }\n    }\n    this.updateParams_();\n  },\n  decompose: function(workspace) {\n    var containerBlock = Blockly.Block.obtain(workspace,\n                                           'procedures_mutatorcontainer');\n    containerBlock.initSvg();\n    var connection = containerBlock.getInput('STACK').connection;\n    for (var x = 0; x < this.arguments_.length; x++) {\n      var paramBlock = Blockly.Block.obtain(workspace, 'procedures_mutatorarg');\n      paramBlock.initSvg();\n      paramBlock.setFieldValue(this.arguments_[x], 'NAME');\n      // Store the old location.\n      paramBlock.oldLocation = x;\n      connection.connect(paramBlock.previousConnection);\n      connection = paramBlock.nextConnection;\n    }\n    // Initialize procedure's callers with blank IDs.\n    Blockly.Procedures.mutateCallers(this.getFieldValue('NAME'),\n                                     this.workspace, this.arguments_, null);\n    return containerBlock;\n  },\n  compose: function(containerBlock) {\n    this.arguments_ = [];\n    this.paramIds_ = [];\n    var paramBlock = containerBlock.getInputTargetBlock('STACK');\n    while (paramBlock) {\n      this.arguments_.push(paramBlock.getFieldValue('NAME'));\n      this.paramIds_.push(paramBlock.id);\n      paramBlock = paramBlock.nextConnection &&\n          paramBlock.nextConnection.targetBlock();\n    }\n    this.updateParams_();\n    Blockly.Procedures.mutateCallers(this.getFieldValue('NAME'),\n        this.workspace, this.arguments_, this.paramIds_);\n  },\n  dispose: function() {\n    // Dispose of any callers.\n    var name = this.getFieldValue('NAME');\n    Blockly.Procedures.disposeCallers(name, this.workspace);\n    // Call parent's destructor.\n    Blockly.Block.prototype.dispose.apply(this, arguments);\n  },\n  getProcedureDef: function() {\n    // Return the name of the defined procedure,\n    // a list of all its arguments,\n    // and that it DOES NOT have a return value.\n    return [this.getFieldValue('NAME'), this.arguments_, false];\n  },\n  getVars: function() {\n    return this.arguments_;\n  },\n  renameVar: function(oldName, newName) {\n    var change = false;\n    for (var x = 0; x < this.arguments_.length; x++) {\n      if (Blockly.Names.equals(oldName, this.arguments_[x])) {\n        this.arguments_[x] = newName;\n        change = true;\n      }\n    }\n    if (change) {\n      this.updateParams_();\n      // Update the mutator's variables if the mutator is open.\n      if (this.mutator.isVisible_()) {\n        var blocks = this.mutator.workspace_.getAllBlocks();\n        for (var x = 0, block; block = blocks[x]; x++) {\n          if (block.type == 'procedures_mutatorarg' &&\n              Blockly.Names.equals(oldName, block.getFieldValue('NAME'))) {\n            block.setFieldValue(newName, 'NAME');\n          }\n        }\n      }\n    }\n  },\n  customContextMenu: function(options) {\n    // Add option to create caller.\n    var option = {enabled: true};\n    var name = this.getFieldValue('NAME');\n    option.text = Blockly.Msg.PROCEDURES_CREATE_DO.replace('%1', name);\n\n    var xmlMutation = goog.dom.createDom('mutation');\n    xmlMutation.setAttribute('name', name);\n    for (var x = 0; x < this.arguments_.length; x++) {\n      var xmlArg = goog.dom.createDom('arg');\n      xmlArg.setAttribute('name', this.arguments_[x]);\n      xmlMutation.appendChild(xmlArg);\n    }\n    var xmlBlock = goog.dom.createDom('block', null, xmlMutation);\n    xmlBlock.setAttribute('type', this.callType_);\n    option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);\n\n    options.push(option);\n    // Add options to create getters for each parameter.\n    for (var x = 0; x < this.arguments_.length; x++) {\n      var option = {enabled: true};\n      var name = this.arguments_[x];\n      option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name);\n      var xmlField = goog.dom.createDom('field', null, name);\n      xmlField.setAttribute('name', 'VAR');\n      var xmlBlock = goog.dom.createDom('block', null, xmlField);\n      xmlBlock.setAttribute('type', 'variables_get');\n      option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);\n      options.push(option);\n    }\n  },\n  callType_: 'procedures_callnoreturn'\n};\n\nBlockly.Blocks['procedures_defreturn'] = {\n  // Define a procedure with a return value.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL);\n    this.setColour(290);\n    var name = Blockly.Procedures.findLegalName(\n        Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE, this);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_TITLE)\n        .appendField(new Blockly.FieldTextInput(name,\n        Blockly.Procedures.rename), 'NAME')\n        .appendField('', 'PARAMS');\n    this.appendStatementInput('STACK')\n        .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_DO);\n    this.appendValueInput('RETURN')\n        .setAlign(Blockly.ALIGN_RIGHT)\n        .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);\n    this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));\n    this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP);\n    this.arguments_ = [];\n  },\n  updateParams_: Blockly.Blocks['procedures_defnoreturn'].updateParams_,\n  mutationToDom: Blockly.Blocks['procedures_defnoreturn'].mutationToDom,\n  domToMutation: Blockly.Blocks['procedures_defnoreturn'].domToMutation,\n  decompose: Blockly.Blocks['procedures_defnoreturn'].decompose,\n  compose: Blockly.Blocks['procedures_defnoreturn'].compose,\n  dispose: Blockly.Blocks['procedures_defnoreturn'].dispose,\n  getProcedureDef: function() {\n    // Return the name of the defined procedure,\n    // a list of all its arguments,\n    // and that it DOES have a return value.\n    return [this.getFieldValue('NAME'), this.arguments_, true];\n  },\n  getVars: Blockly.Blocks['procedures_defnoreturn'].getVars,\n  renameVar: Blockly.Blocks['procedures_defnoreturn'].renameVar,\n  customContextMenu: Blockly.Blocks['procedures_defnoreturn'].customContextMenu,\n  callType_: 'procedures_callreturn'\n};\n\nBlockly.Blocks['procedures_mutatorcontainer'] = {\n  // Procedure container (for mutator dialog).\n  init: function() {\n    this.setColour(290);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE);\n    this.appendStatementInput('STACK');\n    this.setTooltip('');\n    this.contextMenu = false;\n  }\n};\n\nBlockly.Blocks['procedures_mutatorarg'] = {\n  // Procedure argument (for mutator dialog).\n  init: function() {\n    this.setColour(290);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.PROCEDURES_MUTATORARG_TITLE)\n        .appendField(new Blockly.FieldTextInput('x', this.validator), 'NAME');\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setTooltip('');\n    this.contextMenu = false;\n  },\n  validator: function(newVar) {\n    // Merge runs of whitespace.  Strip leading and trailing whitespace.\n    // Beyond this, all names are legal.\n    newVar = newVar.replace(/[\\s\\xa0]+/g, ' ').replace(/^ | $/g, '');\n    return newVar || null;\n  }\n};\n\nBlockly.Blocks['procedures_callnoreturn'] = {\n  // Call a procedure with no return value.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL);\n    this.setColour(290);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.PROCEDURES_CALLNORETURN_CALL)\n        .appendField('', 'NAME');\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setTooltip(Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP);\n    this.arguments_ = [];\n    this.quarkConnections_ = null;\n    this.quarkArguments_ = null;\n  },\n  getProcedureCall: function() {\n    return this.getFieldValue('NAME');\n  },\n  renameProcedure: function(oldName, newName) {\n    if (Blockly.Names.equals(oldName, this.getFieldValue('NAME'))) {\n      this.setFieldValue(newName, 'NAME');\n      this.setTooltip(\n          (this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP\n           : Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP)\n          .replace('%1', newName));\n    }\n  },\n  setProcedureParameters: function(paramNames, paramIds) {\n    // Data structures for parameters on each call block:\n    // this.arguments = ['x', 'y']\n    //     Existing param names.\n    // paramNames = ['x', 'y', 'z']\n    //     New param names.\n    // paramIds = ['piua', 'f8b_', 'oi.o']\n    //     IDs of params (consistent for each parameter through the life of a\n    //     mutator, regardless of param renaming).\n    // this.quarkConnections_ {piua: null, f8b_: Blockly.Connection}\n    //     Look-up of paramIds to connections plugged into the call block.\n    // this.quarkArguments_ = ['piua', 'f8b_']\n    //     Existing param IDs.\n    // Note that quarkConnections_ may include IDs that no longer exist, but\n    // which might reappear if a param is reattached in the mutator.\n    if (!paramIds) {\n      // Reset the quarks (a mutator is about to open).\n      this.quarkConnections_ = {};\n      this.quarkArguments_ = null;\n      return;\n    }\n    if (paramIds.length != paramNames.length) {\n      throw 'Error: paramNames and paramIds must be the same length.';\n    }\n    if (!this.quarkArguments_) {\n      // Initialize tracking for this block.\n      this.quarkConnections_ = {};\n      if (paramNames.join('\\n') == this.arguments_.join('\\n')) {\n        // No change to the parameters, allow quarkConnections_ to be\n        // populated with the existing connections.\n        this.quarkArguments_ = paramIds;\n      } else {\n        this.quarkArguments_ = [];\n      }\n    }\n    // Switch off rendering while the block is rebuilt.\n    var savedRendered = this.rendered;\n    this.rendered = false;\n    // Update the quarkConnections_ with existing connections.\n    for (var x = this.arguments_.length - 1; x >= 0; x--) {\n      var input = this.getInput('ARG' + x);\n      if (input) {\n        var connection = input.connection.targetConnection;\n        this.quarkConnections_[this.quarkArguments_[x]] = connection;\n        // Disconnect all argument blocks and remove all inputs.\n        this.removeInput('ARG' + x);\n      }\n    }\n    // Rebuild the block's arguments.\n    this.arguments_ = [].concat(paramNames);\n    this.quarkArguments_ = paramIds;\n    for (var x = 0; x < this.arguments_.length; x++) {\n      var input = this.appendValueInput('ARG' + x)\n          .setAlign(Blockly.ALIGN_RIGHT)\n          .appendField(this.arguments_[x]);\n      if (this.quarkArguments_) {\n        // Reconnect any child blocks.\n        var quarkName = this.quarkArguments_[x];\n        if (quarkName in this.quarkConnections_) {\n          var connection = this.quarkConnections_[quarkName];\n          if (!connection || connection.targetConnection ||\n              connection.sourceBlock_.workspace != this.workspace) {\n            // Block no longer exists or has been attached elsewhere.\n            delete this.quarkConnections_[quarkName];\n          } else {\n            input.connection.connect(connection);\n          }\n        }\n      }\n    }\n    // Restore rendering and show the changes.\n    this.rendered = savedRendered;\n    if (this.rendered) {\n      this.render();\n    }\n  },\n  mutationToDom: function() {\n    // Save the name and arguments (none of which are editable).\n    var container = document.createElement('mutation');\n    container.setAttribute('name', this.getFieldValue('NAME'));\n    for (var x = 0; x < this.arguments_.length; x++) {\n      var parameter = document.createElement('arg');\n      parameter.setAttribute('name', this.arguments_[x]);\n      container.appendChild(parameter);\n    }\n    return container;\n  },\n  domToMutation: function(xmlElement) {\n    // Restore the name and parameters.\n    var name = xmlElement.getAttribute('name');\n    this.setFieldValue(name, 'NAME');\n    this.setTooltip(\n        (this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP\n         : Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP).replace('%1', name));\n    var def = Blockly.Procedures.getDefinition(name, this.workspace);\n    if (def && def.mutator.isVisible()) {\n      // Initialize caller with the mutator's IDs.\n      this.setProcedureParameters(def.arguments_, def.paramIds_);\n    } else {\n      this.arguments_ = [];\n      for (var x = 0, childNode; childNode = xmlElement.childNodes[x]; x++) {\n        if (childNode.nodeName.toLowerCase() == 'arg') {\n          this.arguments_.push(childNode.getAttribute('name'));\n        }\n      }\n      // For the second argument (paramIds) use the arguments list as a dummy\n      // list.\n      this.setProcedureParameters(this.arguments_, this.arguments_);\n    }\n  },\n  renameVar: function(oldName, newName) {\n    for (var x = 0; x < this.arguments_.length; x++) {\n      if (Blockly.Names.equals(oldName, this.arguments_[x])) {\n        this.arguments_[x] = newName;\n        this.getInput('ARG' + x).fieldRow[0].setText(newName);\n      }\n    }\n  },\n  customContextMenu: function(options) {\n    // Add option to find caller.\n    var option = {enabled: true};\n    option.text = Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF;\n    var name = this.getFieldValue('NAME');\n    var workspace = this.workspace;\n    option.callback = function() {\n      var def = Blockly.Procedures.getDefinition(name, workspace);\n      def && def.select();\n    };\n    options.push(option);\n  }\n};\n\nBlockly.Blocks['procedures_callreturn'] = {\n  // Call a procedure with a return value.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL);\n    this.setColour(290);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.PROCEDURES_CALLRETURN_CALL)\n        .appendField('', 'NAME');\n    this.setOutput(true);\n    this.setTooltip(Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP);\n    this.arguments_ = [];\n    this.quarkConnections_ = null;\n    this.quarkArguments_ = null;\n  },\n  getProcedureCall: Blockly.Blocks['procedures_callnoreturn'].getProcedureCall,\n  renameProcedure: Blockly.Blocks['procedures_callnoreturn'].renameProcedure,\n  setProcedureParameters:\n      Blockly.Blocks['procedures_callnoreturn'].setProcedureParameters,\n  mutationToDom: Blockly.Blocks['procedures_callnoreturn'].mutationToDom,\n  domToMutation: Blockly.Blocks['procedures_callnoreturn'].domToMutation,\n  renameVar: Blockly.Blocks['procedures_callnoreturn'].renameVar,\n  customContextMenu: Blockly.Blocks['procedures_callnoreturn'].customContextMenu\n};\n\nBlockly.Blocks['procedures_ifreturn'] = {\n  // Conditionally return value from a procedure.\n  init: function() {\n    this.setHelpUrl('http://c2.com/cgi/wiki?GuardClause');\n    this.setColour(290);\n    this.appendValueInput('CONDITION')\n        .setCheck('Boolean')\n        .appendField(Blockly.Msg.CONTROLS_IF_MSG_IF);\n    this.appendValueInput('VALUE')\n        .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);\n    this.setInputsInline(true);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP);\n    this.hasReturnValue_ = true;\n  },\n  mutationToDom: function() {\n    // Save whether this block has a return value.\n    var container = document.createElement('mutation');\n    container.setAttribute('value', Number(this.hasReturnValue_));\n    return container;\n  },\n  domToMutation: function(xmlElement) {\n    // Restore whether this block has a return value.\n    var value = xmlElement.getAttribute('value');\n    this.hasReturnValue_ = (value == 1);\n    if (!this.hasReturnValue_) {\n      this.removeInput('VALUE');\n      this.appendDummyInput('VALUE')\n        .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);\n    }\n  },\n  onchange: function() {\n    if (!this.workspace) {\n      // Block has been deleted.\n      return;\n    }\n    var legal = false;\n    // Is the block nested in a procedure?\n    var block = this;\n    do {\n      if (block.type == 'procedures_defnoreturn' ||\n          block.type == 'procedures_defreturn') {\n        legal = true;\n        break;\n      }\n      block = block.getSurroundParent();\n    } while (block);\n    if (legal) {\n      // If needed, toggle whether this block has a return value.\n      if (block.type == 'procedures_defnoreturn' && this.hasReturnValue_) {\n        this.removeInput('VALUE');\n        this.appendDummyInput('VALUE')\n          .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);\n        this.hasReturnValue_ = false;\n      } else if (block.type == 'procedures_defreturn' &&\n                 !this.hasReturnValue_) {\n        this.removeInput('VALUE');\n        this.appendValueInput('VALUE')\n          .appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);\n        this.hasReturnValue_ = true;\n      }\n      this.setWarningText(null);\n    } else {\n      this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING);\n    }\n  }\n};\n"
  },
  {
    "path": "extern/blockly/blocks/text.js",
    "content": ""
  },
  {
    "path": "extern/blockly/blocks/variables.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Variable blocks for Blockly.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Blocks.variables');\n\ngoog.require('Blockly.Blocks');\n\n\nBlockly.Blocks['variables_get'] = {\n  // Variable getter.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL);\n    this.setColour(330);\n    this.appendDummyInput()\n        .appendField(Blockly.Msg.VARIABLES_GET_TITLE)\n        .appendField(new Blockly.FieldVariable(\n        Blockly.Msg.VARIABLES_GET_ITEM), 'VAR')\n        .appendField(Blockly.Msg.VARIABLES_GET_TAIL);\n    this.setOutput(true);\n    this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP);\n    this.contextMenuMsg_ = Blockly.Msg.VARIABLES_GET_CREATE_SET;\n    this.contextMenuType_ = 'variables_set';\n  },\n  getVars: function() {\n    return [this.getFieldValue('VAR')];\n  },\n  renameVar: function(oldName, newName) {\n    if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {\n      this.setFieldValue(newName, 'VAR');\n    }\n  },\n  customContextMenu: function(options) {\n    var option = {enabled: true};\n    var name = this.getFieldValue('VAR');\n    option.text = this.contextMenuMsg_.replace('%1', name);\n    var xmlField = goog.dom.createDom('field', null, name);\n    xmlField.setAttribute('name', 'VAR');\n    var xmlBlock = goog.dom.createDom('block', null, xmlField);\n    xmlBlock.setAttribute('type', this.contextMenuType_);\n    option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);\n    options.push(option);\n  }\n};\n\nBlockly.Blocks['variables_set'] = {\n  // Variable setter.\n  init: function() {\n    this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL);\n    this.setColour(330);\n    this.interpolateMsg(\n        // TODO: Combine these messages instead of using concatenation.\n        Blockly.Msg.VARIABLES_SET_TITLE + ' %1 ' +\n        Blockly.Msg.VARIABLES_SET_TAIL + ' %2',\n        ['VAR', new Blockly.FieldVariable(Blockly.Msg.VARIABLES_SET_ITEM)],\n        ['VALUE', null, Blockly.ALIGN_RIGHT],\n        Blockly.ALIGN_RIGHT);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP);\n    this.contextMenuMsg_ = Blockly.Msg.VARIABLES_SET_CREATE_GET;\n    this.contextMenuType_ = 'variables_get';\n  },\n  getVars: function() {\n    return [this.getFieldValue('VAR')];\n  },\n  renameVar: function(oldName, newName) {\n    if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {\n      this.setFieldValue(newName, 'VAR');\n    }\n  },\n  customContextMenu: Blockly.Blocks['variables_get'].customContextMenu\n};\n"
  },
  {
    "path": "extern/blockly/blocks_compressed.js",
    "content": "// Do not edit this file; automatically generated by build.py.\n\"use strict\";\n\n\n// Copyright 2012 Google Inc.  Apache License 2.0\nBlockly.Blocks.colour={};Blockly.Blocks.colour_picker={init:function(){this.setHelpUrl(Blockly.Msg.COLOUR_PICKER_HELPURL);this.setColour(20);this.appendDummyInput().appendField(new Blockly.FieldColour(\"#ff0000\"),\"COLOUR\");this.setOutput(!0,\"Colour\");this.setTooltip(Blockly.Msg.COLOUR_PICKER_TOOLTIP)}};\nBlockly.Blocks.colour_random={init:function(){this.setHelpUrl(Blockly.Msg.COLOUR_RANDOM_HELPURL);this.setColour(20);this.appendDummyInput().appendField(Blockly.Msg.COLOUR_RANDOM_TITLE);this.setOutput(!0,\"Colour\");this.setTooltip(Blockly.Msg.COLOUR_RANDOM_TOOLTIP)}};\nBlockly.Blocks.colour_rgb={init:function(){this.setHelpUrl(Blockly.Msg.COLOUR_RGB_HELPURL);this.setColour(20);this.appendValueInput(\"RED\").setCheck(\"Number\").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.COLOUR_RGB_TITLE).appendField(Blockly.Msg.COLOUR_RGB_RED);this.appendValueInput(\"GREEN\").setCheck(\"Number\").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.COLOUR_RGB_GREEN);this.appendValueInput(\"BLUE\").setCheck(\"Number\").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.COLOUR_RGB_BLUE);\nthis.setOutput(!0,\"Colour\");this.setTooltip(Blockly.Msg.COLOUR_RGB_TOOLTIP)}};\nBlockly.Blocks.colour_blend={init:function(){this.setHelpUrl(Blockly.Msg.COLOUR_BLEND_HELPURL);this.setColour(20);this.appendValueInput(\"COLOUR1\").setCheck(\"Colour\").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.COLOUR_BLEND_TITLE).appendField(Blockly.Msg.COLOUR_BLEND_COLOUR1);this.appendValueInput(\"COLOUR2\").setCheck(\"Colour\").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.COLOUR_BLEND_COLOUR2);this.appendValueInput(\"RATIO\").setCheck(\"Number\").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.COLOUR_BLEND_RATIO);this.setOutput(!0,\n\"Colour\");this.setTooltip(Blockly.Msg.COLOUR_BLEND_TOOLTIP)}};Blockly.Blocks.lists={};Blockly.Blocks.lists_create_empty={init:function(){this.setHelpUrl(Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL);this.setColour(260);this.setOutput(!0,\"Array\");this.appendDummyInput().appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);this.setTooltip(Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP)}};\nBlockly.Blocks.lists_create_with={init:function(){this.setColour(260);this.appendValueInput(\"ADD0\").appendField(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);this.appendValueInput(\"ADD1\");this.appendValueInput(\"ADD2\");this.setOutput(!0,\"Array\");this.setMutator(new Blockly.Mutator([\"lists_create_with_item\"]));this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP);this.itemCount_=3},mutationToDom:function(a){a=document.createElement(\"mutation\");a.setAttribute(\"items\",this.itemCount_);return a},domToMutation:function(a){for(var b=\n0;b<this.itemCount_;b++)this.removeInput(\"ADD\"+b);this.itemCount_=parseInt(a.getAttribute(\"items\"),10);for(b=0;b<this.itemCount_;b++)a=this.appendValueInput(\"ADD\"+b),0==b&&a.appendField(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);0==this.itemCount_&&this.appendDummyInput(\"EMPTY\").appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE)},decompose:function(a){var b=Blockly.Block.obtain(a,\"lists_create_with_container\");b.initSvg();for(var c=b.getInput(\"STACK\").connection,d=0;d<this.itemCount_;d++){var e=Blockly.Block.obtain(a,\n\"lists_create_with_item\");e.initSvg();c.connect(e.previousConnection);c=e.nextConnection}return b},compose:function(a){if(0==this.itemCount_)this.removeInput(\"EMPTY\");else for(var b=this.itemCount_-1;0<=b;b--)this.removeInput(\"ADD\"+b);this.itemCount_=0;for(a=a.getInputTargetBlock(\"STACK\");a;)b=this.appendValueInput(\"ADD\"+this.itemCount_),0==this.itemCount_&&b.appendField(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH),a.valueConnection_&&b.connection.connect(a.valueConnection_),this.itemCount_++,a=a.nextConnection&&\na.nextConnection.targetBlock();0==this.itemCount_&&this.appendDummyInput(\"EMPTY\").appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE)},saveConnections:function(a){a=a.getInputTargetBlock(\"STACK\");for(var b=0;a;){var c=this.getInput(\"ADD\"+b);a.valueConnection_=c&&c.connection.targetConnection;b++;a=a.nextConnection&&a.nextConnection.targetBlock()}}};\nBlockly.Blocks.lists_create_with_container={init:function(){this.setColour(260);this.appendDummyInput().appendField(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD);this.appendStatementInput(\"STACK\");this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP);this.contextMenu=!1}};\nBlockly.Blocks.lists_create_with_item={init:function(){this.setColour(260);this.appendDummyInput().appendField(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP);this.contextMenu=!1}};\nBlockly.Blocks.lists_repeat={init:function(){this.setHelpUrl(Blockly.Msg.LISTS_REPEAT_HELPURL);this.setColour(260);this.setOutput(!0,\"Array\");this.interpolateMsg(Blockly.Msg.LISTS_REPEAT_TITLE,[\"ITEM\",null,Blockly.ALIGN_RIGHT],[\"NUM\",\"Number\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setTooltip(Blockly.Msg.LISTS_REPEAT_TOOLTIP)}};\nBlockly.Blocks.lists_length={init:function(){this.setHelpUrl(Blockly.Msg.LISTS_LENGTH_HELPURL);this.setColour(260);this.interpolateMsg(Blockly.Msg.LISTS_LENGTH_TITLE,[\"VALUE\",[\"Array\",\"String\"],Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setOutput(!0,\"Number\");this.setTooltip(Blockly.Msg.LISTS_LENGTH_TOOLTIP)}};\nBlockly.Blocks.lists_isEmpty={init:function(){this.setHelpUrl(Blockly.Msg.LISTS_IS_EMPTY_HELPURL);this.setColour(260);this.interpolateMsg(Blockly.Msg.LISTS_IS_EMPTY_TITLE,[\"VALUE\",[\"Array\",\"String\"],Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setInputsInline(!0);this.setOutput(!0,\"Boolean\");this.setTooltip(Blockly.Msg.LISTS_TOOLTIP)}};\nBlockly.Blocks.lists_indexOf={init:function(){var a=[[Blockly.Msg.LISTS_INDEX_OF_FIRST,\"FIRST\"],[Blockly.Msg.LISTS_INDEX_OF_LAST,\"LAST\"]];this.setHelpUrl(Blockly.Msg.LISTS_INDEX_OF_HELPURL);this.setColour(260);this.setOutput(!0,\"Number\");this.appendValueInput(\"VALUE\").setCheck(\"Array\").appendField(Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST);this.appendValueInput(\"FIND\").appendField(new Blockly.FieldDropdown(a),\"END\");this.setInputsInline(!0);this.setTooltip(Blockly.Msg.LISTS_INDEX_OF_TOOLTIP)}};\nBlockly.Blocks.lists_getIndex={init:function(){var a=[[Blockly.Msg.LISTS_GET_INDEX_GET,\"GET\"],[Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE,\"GET_REMOVE\"],[Blockly.Msg.LISTS_GET_INDEX_REMOVE,\"REMOVE\"]];this.WHERE_OPTIONS=[[Blockly.Msg.LISTS_GET_INDEX_FROM_START,\"FROM_START\"],[Blockly.Msg.LISTS_GET_INDEX_FROM_END,\"FROM_END\"],[Blockly.Msg.LISTS_GET_INDEX_FIRST,\"FIRST\"],[Blockly.Msg.LISTS_GET_INDEX_LAST,\"LAST\"],[Blockly.Msg.LISTS_GET_INDEX_RANDOM,\"RANDOM\"]];this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL);\nthis.setColour(260);a=new Blockly.FieldDropdown(a,function(a){this.sourceBlock_.updateStatement(\"REMOVE\"==a)});this.appendValueInput(\"VALUE\").setCheck(\"Array\").appendField(Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST);this.appendDummyInput().appendField(a,\"MODE\").appendField(\"\",\"SPACE\");this.appendDummyInput(\"AT\");Blockly.Msg.LISTS_GET_INDEX_TAIL&&this.appendDummyInput(\"TAIL\").appendField(Blockly.Msg.LISTS_GET_INDEX_TAIL);this.setInputsInline(!0);this.setOutput(!0);this.updateAt(!0);var b=this;this.setTooltip(function(){var a=\nb.getFieldValue(\"MODE\")+\"_\"+b.getFieldValue(\"WHERE\");return Blockly.Msg[\"LISTS_GET_INDEX_TOOLTIP_\"+a]})},mutationToDom:function(){var a=document.createElement(\"mutation\");a.setAttribute(\"statement\",!this.outputConnection);var b=this.getInput(\"AT\").type==Blockly.INPUT_VALUE;a.setAttribute(\"at\",b);return a},domToMutation:function(a){var b=\"true\"==a.getAttribute(\"statement\");this.updateStatement(b);a=\"false\"!=a.getAttribute(\"at\");this.updateAt(a)},updateStatement:function(a){a!=!this.outputConnection&&\n(this.unplug(!0,!0),a?(this.setOutput(!1),this.setPreviousStatement(!0),this.setNextStatement(!0)):(this.setPreviousStatement(!1),this.setNextStatement(!1),this.setOutput(!0)))},updateAt:function(a){this.removeInput(\"AT\");this.removeInput(\"ORDINAL\",!0);a?(this.appendValueInput(\"AT\").setCheck(\"Number\"),Blockly.Msg.ORDINAL_NUMBER_SUFFIX&&this.appendDummyInput(\"ORDINAL\").appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX)):this.appendDummyInput(\"AT\");var b=new Blockly.FieldDropdown(this.WHERE_OPTIONS,function(b){var d=\n\"FROM_START\"==b||\"FROM_END\"==b;if(d!=a){var e=this.sourceBlock_;e.updateAt(d);e.setFieldValue(b,\"WHERE\");return null}});this.getInput(\"AT\").appendField(b,\"WHERE\");Blockly.Msg.LISTS_GET_INDEX_TAIL&&this.moveInputBefore(\"TAIL\",null)}};\nBlockly.Blocks.lists_setIndex={init:function(){var a=[[Blockly.Msg.LISTS_SET_INDEX_SET,\"SET\"],[Blockly.Msg.LISTS_SET_INDEX_INSERT,\"INSERT\"]];this.WHERE_OPTIONS=[[Blockly.Msg.LISTS_GET_INDEX_FROM_START,\"FROM_START\"],[Blockly.Msg.LISTS_GET_INDEX_FROM_END,\"FROM_END\"],[Blockly.Msg.LISTS_GET_INDEX_FIRST,\"FIRST\"],[Blockly.Msg.LISTS_GET_INDEX_LAST,\"LAST\"],[Blockly.Msg.LISTS_GET_INDEX_RANDOM,\"RANDOM\"]];this.setHelpUrl(Blockly.Msg.LISTS_SET_INDEX_HELPURL);this.setColour(260);this.appendValueInput(\"LIST\").setCheck(\"Array\").appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST);\nthis.appendDummyInput().appendField(new Blockly.FieldDropdown(a),\"MODE\").appendField(\"\",\"SPACE\");this.appendDummyInput(\"AT\");this.appendValueInput(\"TO\").appendField(Blockly.Msg.LISTS_SET_INDEX_INPUT_TO);this.setInputsInline(!0);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_TOOLTIP);this.updateAt(!0);var b=this;this.setTooltip(function(){var a=b.getFieldValue(\"MODE\")+\"_\"+b.getFieldValue(\"WHERE\");return Blockly.Msg[\"LISTS_SET_INDEX_TOOLTIP_\"+a]})},\nmutationToDom:function(){var a=document.createElement(\"mutation\"),b=this.getInput(\"AT\").type==Blockly.INPUT_VALUE;a.setAttribute(\"at\",b);return a},domToMutation:function(a){a=\"false\"!=a.getAttribute(\"at\");this.updateAt(a)},updateAt:function(a){this.removeInput(\"AT\");this.removeInput(\"ORDINAL\",!0);a?(this.appendValueInput(\"AT\").setCheck(\"Number\"),Blockly.Msg.ORDINAL_NUMBER_SUFFIX&&this.appendDummyInput(\"ORDINAL\").appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX)):this.appendDummyInput(\"AT\");var b=new Blockly.FieldDropdown(this.WHERE_OPTIONS,\nfunction(b){var d=\"FROM_START\"==b||\"FROM_END\"==b;if(d!=a){var e=this.sourceBlock_;e.updateAt(d);e.setFieldValue(b,\"WHERE\");return null}});this.moveInputBefore(\"AT\",\"TO\");this.getInput(\"ORDINAL\")&&this.moveInputBefore(\"ORDINAL\",\"TO\");this.getInput(\"AT\").appendField(b,\"WHERE\")}};\nBlockly.Blocks.lists_getSublist={init:function(){this.WHERE_OPTIONS_1=[[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START,\"FROM_START\"],[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END,\"FROM_END\"],[Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST,\"FIRST\"]];this.WHERE_OPTIONS_2=[[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START,\"FROM_START\"],[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END,\"FROM_END\"],[Blockly.Msg.LISTS_GET_SUBLIST_END_LAST,\"LAST\"]];this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL);this.setColour(260);\nthis.appendValueInput(\"LIST\").setCheck(\"Array\").appendField(Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST);this.appendDummyInput(\"AT1\");this.appendDummyInput(\"AT2\");Blockly.Msg.LISTS_GET_SUBLIST_TAIL&&this.appendDummyInput(\"TAIL\").appendField(Blockly.Msg.LISTS_GET_SUBLIST_TAIL);this.setInputsInline(!0);this.setOutput(!0,\"Array\");this.updateAt(1,!0);this.updateAt(2,!0);this.setTooltip(Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP)},mutationToDom:function(){var a=document.createElement(\"mutation\"),b=this.getInput(\"AT1\").type==\nBlockly.INPUT_VALUE;a.setAttribute(\"at1\",b);b=this.getInput(\"AT2\").type==Blockly.INPUT_VALUE;a.setAttribute(\"at2\",b);return a},domToMutation:function(a){var b=\"true\"==a.getAttribute(\"at1\");a=\"true\"==a.getAttribute(\"at2\");this.updateAt(1,b);this.updateAt(2,a)},updateAt:function(a,b){this.removeInput(\"AT\"+a);this.removeInput(\"ORDINAL\"+a,!0);b?(this.appendValueInput(\"AT\"+a).setCheck(\"Number\"),Blockly.Msg.ORDINAL_NUMBER_SUFFIX&&this.appendDummyInput(\"ORDINAL\"+a).appendField(Blockly.Msg.ORDINAL_NUMBER_SUFFIX)):\nthis.appendDummyInput(\"AT\"+a);var c=new Blockly.FieldDropdown(this[\"WHERE_OPTIONS_\"+a],function(c){var e=\"FROM_START\"==c||\"FROM_END\"==c;if(e!=b){var f=this.sourceBlock_;f.updateAt(a,e);f.setFieldValue(c,\"WHERE\"+a);return null}});this.getInput(\"AT\"+a).appendField(c,\"WHERE\"+a);1==a&&(this.moveInputBefore(\"AT1\",\"AT2\"),this.getInput(\"ORDINAL1\")&&this.moveInputBefore(\"ORDINAL1\",\"AT2\"));Blockly.Msg.LISTS_GET_SUBLIST_TAIL&&this.moveInputBefore(\"TAIL\",null)}};Blockly.Blocks.logic={};\nBlockly.Blocks.controls_if={init:function(){this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL);this.setColour(210);this.appendValueInput(\"IF0\").setCheck(\"Boolean\").appendField(Blockly.Msg.CONTROLS_IF_MSG_IF);this.appendStatementInput(\"DO0\").appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setMutator(new Blockly.Mutator([\"controls_if_elseif\",\"controls_if_else\"]));var a=this;this.setTooltip(function(){if(a.elseifCount_||a.elseCount_){if(!a.elseifCount_&&\na.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_2;if(a.elseifCount_&&!a.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_3;if(a.elseifCount_&&a.elseCount_)return Blockly.Msg.CONTROLS_IF_TOOLTIP_4}else return Blockly.Msg.CONTROLS_IF_TOOLTIP_1;return\"\"});this.elseCount_=this.elseifCount_=0},mutationToDom:function(){if(!this.elseifCount_&&!this.elseCount_)return null;var a=document.createElement(\"mutation\");this.elseifCount_&&a.setAttribute(\"elseif\",this.elseifCount_);this.elseCount_&&a.setAttribute(\"else\",\n1);return a},domToMutation:function(a){this.elseifCount_=parseInt(a.getAttribute(\"elseif\"),10);this.elseCount_=parseInt(a.getAttribute(\"else\"),10);for(a=1;a<=this.elseifCount_;a++)this.appendValueInput(\"IF\"+a).setCheck(\"Boolean\").appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF),this.appendStatementInput(\"DO\"+a).appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);this.elseCount_&&this.appendStatementInput(\"ELSE\").appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE)},decompose:function(a){var b=Blockly.Block.obtain(a,\n\"controls_if_if\");b.initSvg();for(var c=b.getInput(\"STACK\").connection,d=1;d<=this.elseifCount_;d++){var e=Blockly.Block.obtain(a,\"controls_if_elseif\");e.initSvg();c.connect(e.previousConnection);c=e.nextConnection}this.elseCount_&&(a=Blockly.Block.obtain(a,\"controls_if_else\"),a.initSvg(),c.connect(a.previousConnection));return b},compose:function(a){this.elseCount_&&this.removeInput(\"ELSE\");this.elseCount_=0;for(var b=this.elseifCount_;0<b;b--)this.removeInput(\"IF\"+b),this.removeInput(\"DO\"+b);this.elseifCount_=\n0;for(a=a.getInputTargetBlock(\"STACK\");a;){switch(a.type){case \"controls_if_elseif\":this.elseifCount_++;var b=this.appendValueInput(\"IF\"+this.elseifCount_).setCheck(\"Boolean\").appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF),c=this.appendStatementInput(\"DO\"+this.elseifCount_);c.appendField(Blockly.Msg.CONTROLS_IF_MSG_THEN);a.valueConnection_&&b.connection.connect(a.valueConnection_);a.statementConnection_&&c.connection.connect(a.statementConnection_);break;case \"controls_if_else\":this.elseCount_++;\nb=this.appendStatementInput(\"ELSE\");b.appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE);a.statementConnection_&&b.connection.connect(a.statementConnection_);break;default:throw\"Unknown block type.\";}a=a.nextConnection&&a.nextConnection.targetBlock()}},saveConnections:function(a){a=a.getInputTargetBlock(\"STACK\");for(var b=1;a;){switch(a.type){case \"controls_if_elseif\":var c=this.getInput(\"IF\"+b),d=this.getInput(\"DO\"+b);a.valueConnection_=c&&c.connection.targetConnection;a.statementConnection_=d&&d.connection.targetConnection;\nb++;break;case \"controls_if_else\":d=this.getInput(\"ELSE\");a.statementConnection_=d&&d.connection.targetConnection;break;default:throw\"Unknown block type.\";}a=a.nextConnection&&a.nextConnection.targetBlock()}}};Blockly.Blocks.controls_if_if={init:function(){this.setColour(210);this.appendDummyInput().appendField(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF);this.appendStatementInput(\"STACK\");this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP);this.contextMenu=!1}};\nBlockly.Blocks.controls_if_elseif={init:function(){this.setColour(210);this.appendDummyInput().appendField(Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP);this.contextMenu=!1}};\nBlockly.Blocks.controls_if_else={init:function(){this.setColour(210);this.appendDummyInput().appendField(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE);this.setPreviousStatement(!0);this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP);this.contextMenu=!1}};\nBlockly.Blocks.logic_compare={init:function(){var a=Blockly.RTL?[[\"=\",\"EQ\"],[\"\\u2260\",\"NEQ\"],[\">\",\"LT\"],[\"\\u2265\",\"LTE\"],[\"<\",\"GT\"],[\"\\u2264\",\"GTE\"]]:[[\"=\",\"EQ\"],[\"\\u2260\",\"NEQ\"],[\"<\",\"LT\"],[\"\\u2264\",\"LTE\"],[\">\",\"GT\"],[\"\\u2265\",\"GTE\"]];this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL);this.setColour(210);this.setOutput(!0,\"Boolean\");this.appendValueInput(\"A\");this.appendValueInput(\"B\").appendField(new Blockly.FieldDropdown(a),\"OP\");this.setInputsInline(!0);var b=this;this.setTooltip(function(){var a=\nb.getFieldValue(\"OP\");return{EQ:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ,NEQ:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ,LT:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT,LTE:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE,GT:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT,GTE:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE}[a]})}};\nBlockly.Blocks.logic_operation={init:function(){var a=[[Blockly.Msg.LOGIC_OPERATION_AND,\"AND\"],[Blockly.Msg.LOGIC_OPERATION_OR,\"OR\"]];this.setHelpUrl(Blockly.Msg.LOGIC_OPERATION_HELPURL);this.setColour(210);this.setOutput(!0,\"Boolean\");this.appendValueInput(\"A\").setCheck(\"Boolean\");this.appendValueInput(\"B\").setCheck(\"Boolean\").appendField(new Blockly.FieldDropdown(a),\"OP\");this.setInputsInline(!0);var b=this;this.setTooltip(function(){var a=b.getFieldValue(\"OP\");return{AND:Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND,\nOR:Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR}[a]})}};Blockly.Blocks.logic_negate={init:function(){this.setHelpUrl(Blockly.Msg.LOGIC_NEGATE_HELPURL);this.setColour(210);this.setOutput(!0,\"Boolean\");this.interpolateMsg(Blockly.Msg.LOGIC_NEGATE_TITLE,[\"BOOL\",\"Boolean\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setTooltip(Blockly.Msg.LOGIC_NEGATE_TOOLTIP)}};\nBlockly.Blocks.logic_boolean={init:function(){var a=[[Blockly.Msg.LOGIC_BOOLEAN_TRUE,\"TRUE\"],[Blockly.Msg.LOGIC_BOOLEAN_FALSE,\"FALSE\"]];this.setHelpUrl(Blockly.Msg.LOGIC_BOOLEAN_HELPURL);this.setColour(210);this.setOutput(!0,\"Boolean\");this.appendDummyInput().appendField(new Blockly.FieldDropdown(a),\"BOOL\");this.setTooltip(Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP)}};\nBlockly.Blocks.logic_null={init:function(){this.setHelpUrl(Blockly.Msg.LOGIC_NULL_HELPURL);this.setColour(210);this.setOutput(!0);this.appendDummyInput().appendField(Blockly.Msg.LOGIC_NULL);this.setTooltip(Blockly.Msg.LOGIC_NULL_TOOLTIP)}};\nBlockly.Blocks.logic_ternary={init:function(){this.setHelpUrl(Blockly.Msg.LOGIC_TERNARY_HELPURL);this.setColour(210);this.appendValueInput(\"IF\").setCheck(\"Boolean\").appendField(Blockly.Msg.LOGIC_TERNARY_CONDITION);this.appendValueInput(\"THEN\").appendField(Blockly.Msg.LOGIC_TERNARY_IF_TRUE);this.appendValueInput(\"ELSE\").appendField(Blockly.Msg.LOGIC_TERNARY_IF_FALSE);this.setOutput(!0);this.setTooltip(Blockly.Msg.LOGIC_TERNARY_TOOLTIP)}};Blockly.Blocks.loops={};\nBlockly.Blocks.controls_repeat={init:function(){this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL);this.setColour(120);this.appendDummyInput().appendField(Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT).appendField(new Blockly.FieldTextInput(\"10\",Blockly.FieldTextInput.nonnegativeIntegerValidator),\"TIMES\").appendField(Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES);this.appendStatementInput(\"DO\").appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_TOOLTIP)}};\nBlockly.Blocks.controls_repeat_ext={init:function(){this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL);this.setColour(120);this.interpolateMsg(Blockly.Msg.CONTROLS_REPEAT_TITLE,[\"TIMES\",\"Number\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.appendStatementInput(\"DO\").appendField(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setInputsInline(!0);this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_TOOLTIP)}};\nBlockly.Blocks.controls_whileUntil={init:function(){var a=[[Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE,\"WHILE\"],[Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL,\"UNTIL\"]];this.setHelpUrl(Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL);this.setColour(120);this.appendValueInput(\"BOOL\").setCheck(\"Boolean\").appendField(new Blockly.FieldDropdown(a),\"MODE\");this.appendStatementInput(\"DO\").appendField(Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO);this.setPreviousStatement(!0);this.setNextStatement(!0);var b=this;\nthis.setTooltip(function(){var a=b.getFieldValue(\"MODE\");return{WHILE:Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE,UNTIL:Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL}[a]})}};\nBlockly.Blocks.controls_for={init:function(){this.setHelpUrl(Blockly.Msg.CONTROLS_FOR_HELPURL);this.setColour(120);this.appendDummyInput().appendField(Blockly.Msg.CONTROLS_FOR_INPUT_WITH).appendField(new Blockly.FieldVariable(null),\"VAR\");this.interpolateMsg(Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY,[\"FROM\",\"Number\",Blockly.ALIGN_RIGHT],[\"TO\",\"Number\",Blockly.ALIGN_RIGHT],[\"BY\",\"Number\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.appendStatementInput(\"DO\").appendField(Blockly.Msg.CONTROLS_FOR_INPUT_DO);\nthis.setPreviousStatement(!0);this.setNextStatement(!0);this.setInputsInline(!0);var a=this;this.setTooltip(function(){return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace(\"%1\",a.getFieldValue(\"VAR\"))})},getVars:function(){return[this.getFieldValue(\"VAR\")]},renameVar:function(a,b){Blockly.Names.equals(a,this.getFieldValue(\"VAR\"))&&this.setFieldValue(b,\"VAR\")},customContextMenu:function(a){var b={enabled:!0},c=this.getFieldValue(\"VAR\");b.text=Blockly.Msg.VARIABLES_SET_CREATE_GET.replace(\"%1\",c);c=goog.dom.createDom(\"field\",\nnull,c);c.setAttribute(\"name\",\"VAR\");c=goog.dom.createDom(\"block\",null,c);c.setAttribute(\"type\",\"variables_get\");b.callback=Blockly.ContextMenu.callbackFactory(this,c);a.push(b)}};\nBlockly.Blocks.controls_forEach={init:function(){this.setHelpUrl(Blockly.Msg.CONTROLS_FOREACH_HELPURL);this.setColour(120);this.appendValueInput(\"LIST\").setCheck(\"Array\").appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM).appendField(new Blockly.FieldVariable(null),\"VAR\").appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST);Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL&&(this.appendDummyInput().appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL),this.setInputsInline(!0));this.appendStatementInput(\"DO\").appendField(Blockly.Msg.CONTROLS_FOREACH_INPUT_DO);\nthis.setPreviousStatement(!0);this.setNextStatement(!0);var a=this;this.setTooltip(function(){return Blockly.Msg.CONTROLS_FOREACH_TOOLTIP.replace(\"%1\",a.getFieldValue(\"VAR\"))})},getVars:function(){return[this.getFieldValue(\"VAR\")]},renameVar:function(a,b){Blockly.Names.equals(a,this.getFieldValue(\"VAR\"))&&this.setFieldValue(b,\"VAR\")},customContextMenu:Blockly.Blocks.controls_for.customContextMenu};\nBlockly.Blocks.controls_flow_statements={init:function(){var a=[[Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK,\"BREAK\"],[Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE,\"CONTINUE\"]];this.setHelpUrl(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL);this.setColour(120);this.appendDummyInput().appendField(new Blockly.FieldDropdown(a),\"FLOW\");this.setPreviousStatement(!0);var b=this;this.setTooltip(function(){var a=b.getFieldValue(\"FLOW\");return b.TOOLTIPS[a]})},onchange:function(){if(this.workspace){var a=\n!1,b=this;do{if(\"controls_repeat\"==b.type||\"controls_repeat_ext\"==b.type||\"controls_forEach\"==b.type||\"controls_for\"==b.type||\"controls_whileUntil\"==b.type){a=!0;break}b=b.getSurroundParent()}while(b);a?this.setWarningText(null):this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING)}}};Blockly.Blocks.math={};Blockly.Blocks.math_number={init:function(){this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL);this.setColour(230);this.appendDummyInput().appendField(new Blockly.FieldTextInput(\"0\",Blockly.FieldTextInput.numberValidator),\"NUM\");this.setOutput(!0,\"Number\");this.setTooltip(Blockly.Msg.MATH_NUMBER_TOOLTIP)}};\nBlockly.Blocks.math_arithmetic={init:function(){var a=[[Blockly.Msg.MATH_ADDITION_SYMBOL,\"ADD\"],[Blockly.Msg.MATH_SUBTRACTION_SYMBOL,\"MINUS\"],[Blockly.Msg.MATH_MULTIPLICATION_SYMBOL,\"MULTIPLY\"],[Blockly.Msg.MATH_DIVISION_SYMBOL,\"DIVIDE\"],[Blockly.Msg.MATH_POWER_SYMBOL,\"POWER\"]];this.setHelpUrl(Blockly.Msg.MATH_ARITHMETIC_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.appendValueInput(\"A\").setCheck(\"Number\");this.appendValueInput(\"B\").setCheck(\"Number\").appendField(new Blockly.FieldDropdown(a),\n\"OP\");this.setInputsInline(!0);var b=this;this.setTooltip(function(){var a=b.getFieldValue(\"OP\");return{ADD:Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,MINUS:Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,MULTIPLY:Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,DIVIDE:Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,POWER:Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER}[a]})}};\nBlockly.Blocks.math_single={init:function(){var a=[[Blockly.Msg.MATH_SINGLE_OP_ROOT,\"ROOT\"],[Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE,\"ABS\"],[\"-\",\"NEG\"],[\"ln\",\"LN\"],[\"log10\",\"LOG10\"],[\"e^\",\"EXP\"],[\"10^\",\"POW10\"]];this.setHelpUrl(Blockly.Msg.MATH_SINGLE_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.interpolateMsg(\"%1 %2\",[\"OP\",new Blockly.FieldDropdown(a)],[\"NUM\",\"Number\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);var b=this;this.setTooltip(function(){var a=b.getFieldValue(\"OP\");return{ROOT:Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT,\nABS:Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS,NEG:Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG,LN:Blockly.Msg.MATH_SINGLE_TOOLTIP_LN,LOG10:Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10,EXP:Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP,POW10:Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10}[a]})}};\nBlockly.Blocks.math_trig={init:function(){var a=[[Blockly.Msg.MATH_TRIG_SIN,\"SIN\"],[Blockly.Msg.MATH_TRIG_COS,\"COS\"],[Blockly.Msg.MATH_TRIG_TAN,\"TAN\"],[Blockly.Msg.MATH_TRIG_ASIN,\"ASIN\"],[Blockly.Msg.MATH_TRIG_ACOS,\"ACOS\"],[Blockly.Msg.MATH_TRIG_ATAN,\"ATAN\"]];this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.appendValueInput(\"NUM\").setCheck(\"Number\").appendField(new Blockly.FieldDropdown(a),\"OP\");var b=this;this.setTooltip(function(){var a=b.getFieldValue(\"OP\");\nreturn{SIN:Blockly.Msg.MATH_TRIG_TOOLTIP_SIN,COS:Blockly.Msg.MATH_TRIG_TOOLTIP_COS,TAN:Blockly.Msg.MATH_TRIG_TOOLTIP_TAN,ASIN:Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN,ACOS:Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS,ATAN:Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN}[a]})}};\nBlockly.Blocks.math_constant={init:function(){this.setHelpUrl(Blockly.Msg.MATH_CONSTANT_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.appendDummyInput().appendField(new Blockly.FieldDropdown([[\"\\u03c0\",\"PI\"],[\"e\",\"E\"],[\"\\u03c6\",\"GOLDEN_RATIO\"],[\"sqrt(2)\",\"SQRT2\"],[\"sqrt(\\u00bd)\",\"SQRT1_2\"],[\"\\u221e\",\"INFINITY\"]]),\"CONSTANT\");this.setTooltip(Blockly.Msg.MATH_CONSTANT_TOOLTIP)}};\nBlockly.Blocks.math_number_property={init:function(){var a=[[Blockly.Msg.MATH_IS_EVEN,\"EVEN\"],[Blockly.Msg.MATH_IS_ODD,\"ODD\"],[Blockly.Msg.MATH_IS_PRIME,\"PRIME\"],[Blockly.Msg.MATH_IS_WHOLE,\"WHOLE\"],[Blockly.Msg.MATH_IS_POSITIVE,\"POSITIVE\"],[Blockly.Msg.MATH_IS_NEGATIVE,\"NEGATIVE\"],[Blockly.Msg.MATH_IS_DIVISIBLE_BY,\"DIVISIBLE_BY\"]];this.setColour(230);this.appendValueInput(\"NUMBER_TO_CHECK\").setCheck(\"Number\");a=new Blockly.FieldDropdown(a,function(a){this.sourceBlock_.updateShape(\"DIVISIBLE_BY\"==\na)});this.appendDummyInput().appendField(a,\"PROPERTY\");this.setInputsInline(!0);this.setOutput(!0,\"Boolean\");this.setTooltip(Blockly.Msg.MATH_IS_TOOLTIP)},mutationToDom:function(){var a=document.createElement(\"mutation\"),b=\"DIVISIBLE_BY\"==this.getFieldValue(\"PROPERTY\");a.setAttribute(\"divisor_input\",b);return a},domToMutation:function(a){a=\"true\"==a.getAttribute(\"divisor_input\");this.updateShape(a)},updateShape:function(a){var b=this.getInput(\"DIVISOR\");a?b||this.appendValueInput(\"DIVISOR\").setCheck(\"Number\"):\nb&&this.removeInput(\"DIVISOR\")}};\nBlockly.Blocks.math_change={init:function(){this.setHelpUrl(Blockly.Msg.MATH_CHANGE_HELPURL);this.setColour(230);this.interpolateMsg(Blockly.Msg.MATH_CHANGE_TITLE_CHANGE+\" %1 \"+Blockly.Msg.MATH_CHANGE_INPUT_BY+\" %2\",[\"VAR\",new Blockly.FieldVariable(Blockly.Msg.MATH_CHANGE_TITLE_ITEM)],[\"DELTA\",\"Number\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setPreviousStatement(!0);this.setNextStatement(!0);var a=this;this.setTooltip(function(){return Blockly.Msg.MATH_CHANGE_TOOLTIP.replace(\"%1\",a.getFieldValue(\"VAR\"))})},\ngetVars:function(){return[this.getFieldValue(\"VAR\")]},renameVar:function(a,b){Blockly.Names.equals(a,this.getFieldValue(\"VAR\"))&&this.setFieldValue(b,\"VAR\")}};\nBlockly.Blocks.math_round={init:function(){var a=[[Blockly.Msg.MATH_ROUND_OPERATOR_ROUND,\"ROUND\"],[Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP,\"ROUNDUP\"],[Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN,\"ROUNDDOWN\"]];this.setHelpUrl(Blockly.Msg.MATH_ROUND_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.appendValueInput(\"NUM\").setCheck(\"Number\").appendField(new Blockly.FieldDropdown(a),\"OP\");this.setTooltip(Blockly.Msg.MATH_ROUND_TOOLTIP)}};\nBlockly.Blocks.math_on_list={init:function(){var a=[[Blockly.Msg.MATH_ONLIST_OPERATOR_SUM,\"SUM\"],[Blockly.Msg.MATH_ONLIST_OPERATOR_MIN,\"MIN\"],[Blockly.Msg.MATH_ONLIST_OPERATOR_MAX,\"MAX\"],[Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE,\"AVERAGE\"],[Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN,\"MEDIAN\"],[Blockly.Msg.MATH_ONLIST_OPERATOR_MODE,\"MODE\"],[Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV,\"STD_DEV\"],[Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM,\"RANDOM\"]],b=this;this.setHelpUrl(Blockly.Msg.MATH_ONLIST_HELPURL);this.setColour(230);\nthis.setOutput(!0,\"Number\");a=new Blockly.FieldDropdown(a,function(a){\"MODE\"==a?b.outputConnection.setCheck(\"Array\"):b.outputConnection.setCheck(\"Number\")});this.appendValueInput(\"LIST\").setCheck(\"Array\").appendField(a,\"OP\");this.setTooltip(function(){var a=b.getFieldValue(\"OP\");return{SUM:Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM,MIN:Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN,MAX:Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX,AVERAGE:Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE,MEDIAN:Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN,\nMODE:Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE,STD_DEV:Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV,RANDOM:Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM}[a]})}};Blockly.Blocks.math_modulo={init:function(){this.setHelpUrl(Blockly.Msg.MATH_MODULO_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.interpolateMsg(Blockly.Msg.MATH_MODULO_TITLE,[\"DIVIDEND\",\"Number\",Blockly.ALIGN_RIGHT],[\"DIVISOR\",\"Number\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setInputsInline(!0);this.setTooltip(Blockly.Msg.MATH_MODULO_TOOLTIP)}};\nBlockly.Blocks.math_constrain={init:function(){this.setHelpUrl(Blockly.Msg.MATH_CONSTRAIN_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.interpolateMsg(Blockly.Msg.MATH_CONSTRAIN_TITLE,[\"VALUE\",\"Number\",Blockly.ALIGN_RIGHT],[\"LOW\",\"Number\",Blockly.ALIGN_RIGHT],[\"HIGH\",\"Number\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setInputsInline(!0);this.setTooltip(Blockly.Msg.MATH_CONSTRAIN_TOOLTIP)}};\nBlockly.Blocks.math_random_int={init:function(){this.setHelpUrl(Blockly.Msg.MATH_RANDOM_INT_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.interpolateMsg(Blockly.Msg.MATH_RANDOM_INT_TITLE,[\"FROM\",\"Number\",Blockly.ALIGN_RIGHT],[\"TO\",\"Number\",Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setInputsInline(!0);this.setTooltip(Blockly.Msg.MATH_RANDOM_INT_TOOLTIP)}};\nBlockly.Blocks.math_random_float={init:function(){this.setHelpUrl(Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL);this.setColour(230);this.setOutput(!0,\"Number\");this.appendDummyInput().appendField(Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM);this.setTooltip(Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP)}};Blockly.Blocks.procedures={};\nBlockly.Blocks.procedures_defnoreturn={init:function(){this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL);this.setColour(290);var a=Blockly.Procedures.findLegalName(Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE,this);this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE).appendField(new Blockly.FieldTextInput(a,Blockly.Procedures.rename),\"NAME\").appendField(\"\",\"PARAMS\");this.appendStatementInput(\"STACK\").appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_DO);this.setMutator(new Blockly.Mutator([\"procedures_mutatorarg\"]));\nthis.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP);this.arguments_=[]},updateParams_:function(){for(var a=!1,b={},c=0;c<this.arguments_.length;c++){if(b[\"arg_\"+this.arguments_[c].toLowerCase()]){a=!0;break}b[\"arg_\"+this.arguments_[c].toLowerCase()]=!0}a?this.setWarningText(Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING):this.setWarningText(null);a=\"\";this.arguments_.length&&(a=Blockly.Msg.PROCEDURES_BEFORE_PARAMS+\" \"+this.arguments_.join(\", \"));this.setFieldValue(a,\"PARAMS\")},mutationToDom:function(){for(var a=\ndocument.createElement(\"mutation\"),b=0;b<this.arguments_.length;b++){var c=document.createElement(\"arg\");c.setAttribute(\"name\",this.arguments_[b]);a.appendChild(c)}return a},domToMutation:function(a){this.arguments_=[];for(var b=0,c;c=a.childNodes[b];b++)\"arg\"==c.nodeName.toLowerCase()&&this.arguments_.push(c.getAttribute(\"name\"));this.updateParams_()},decompose:function(a){var b=Blockly.Block.obtain(a,\"procedures_mutatorcontainer\");b.initSvg();for(var c=b.getInput(\"STACK\").connection,d=0;d<this.arguments_.length;d++){var e=\nBlockly.Block.obtain(a,\"procedures_mutatorarg\");e.initSvg();e.setFieldValue(this.arguments_[d],\"NAME\");e.oldLocation=d;c.connect(e.previousConnection);c=e.nextConnection}Blockly.Procedures.mutateCallers(this.getFieldValue(\"NAME\"),this.workspace,this.arguments_,null);return b},compose:function(a){this.arguments_=[];this.paramIds_=[];for(a=a.getInputTargetBlock(\"STACK\");a;)this.arguments_.push(a.getFieldValue(\"NAME\")),this.paramIds_.push(a.id),a=a.nextConnection&&a.nextConnection.targetBlock();this.updateParams_();\nBlockly.Procedures.mutateCallers(this.getFieldValue(\"NAME\"),this.workspace,this.arguments_,this.paramIds_)},dispose:function(){var a=this.getFieldValue(\"NAME\");Blockly.Procedures.disposeCallers(a,this.workspace);Blockly.Block.prototype.dispose.apply(this,arguments)},getProcedureDef:function(){return[this.getFieldValue(\"NAME\"),this.arguments_,!1]},getVars:function(){return this.arguments_},renameVar:function(a,b){for(var c=!1,d=0;d<this.arguments_.length;d++)Blockly.Names.equals(a,this.arguments_[d])&&\n(this.arguments_[d]=b,c=!0);if(c&&(this.updateParams_(),this.mutator.isVisible_()))for(var c=this.mutator.workspace_.getAllBlocks(),d=0,e;e=c[d];d++)\"procedures_mutatorarg\"==e.type&&Blockly.Names.equals(a,e.getFieldValue(\"NAME\"))&&e.setFieldValue(b,\"NAME\")},customContextMenu:function(a){var b={enabled:!0},c=this.getFieldValue(\"NAME\");b.text=Blockly.Msg.PROCEDURES_CREATE_DO.replace(\"%1\",c);var d=goog.dom.createDom(\"mutation\");d.setAttribute(\"name\",c);for(var e=0;e<this.arguments_.length;e++)c=goog.dom.createDom(\"arg\"),\nc.setAttribute(\"name\",this.arguments_[e]),d.appendChild(c);d=goog.dom.createDom(\"block\",null,d);d.setAttribute(\"type\",this.callType_);b.callback=Blockly.ContextMenu.callbackFactory(this,d);a.push(b);for(e=0;e<this.arguments_.length;e++)b={enabled:!0},c=this.arguments_[e],b.text=Blockly.Msg.VARIABLES_SET_CREATE_GET.replace(\"%1\",c),d=goog.dom.createDom(\"field\",null,c),d.setAttribute(\"name\",\"VAR\"),d=goog.dom.createDom(\"block\",null,d),d.setAttribute(\"type\",\"variables_get\"),b.callback=Blockly.ContextMenu.callbackFactory(this,\nd),a.push(b)},callType_:\"procedures_callnoreturn\"};\nBlockly.Blocks.procedures_defreturn={init:function(){this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL);this.setColour(290);var a=Blockly.Procedures.findLegalName(Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE,this);this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_DEFRETURN_TITLE).appendField(new Blockly.FieldTextInput(a,Blockly.Procedures.rename),\"NAME\").appendField(\"\",\"PARAMS\");this.appendStatementInput(\"STACK\").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_DO);this.appendValueInput(\"RETURN\").setAlign(Blockly.ALIGN_RIGHT).appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);\nthis.setMutator(new Blockly.Mutator([\"procedures_mutatorarg\"]));this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP);this.arguments_=[]},updateParams_:Blockly.Blocks.procedures_defnoreturn.updateParams_,mutationToDom:Blockly.Blocks.procedures_defnoreturn.mutationToDom,domToMutation:Blockly.Blocks.procedures_defnoreturn.domToMutation,decompose:Blockly.Blocks.procedures_defnoreturn.decompose,compose:Blockly.Blocks.procedures_defnoreturn.compose,dispose:Blockly.Blocks.procedures_defnoreturn.dispose,\ngetProcedureDef:function(){return[this.getFieldValue(\"NAME\"),this.arguments_,!0]},getVars:Blockly.Blocks.procedures_defnoreturn.getVars,renameVar:Blockly.Blocks.procedures_defnoreturn.renameVar,customContextMenu:Blockly.Blocks.procedures_defnoreturn.customContextMenu,callType_:\"procedures_callreturn\"};\nBlockly.Blocks.procedures_mutatorcontainer={init:function(){this.setColour(290);this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE);this.appendStatementInput(\"STACK\");this.setTooltip(\"\");this.contextMenu=!1}};\nBlockly.Blocks.procedures_mutatorarg={init:function(){this.setColour(290);this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_MUTATORARG_TITLE).appendField(new Blockly.FieldTextInput(\"x\",this.validator),\"NAME\");this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(\"\");this.contextMenu=!1},validator:function(a){return(a=a.replace(/[\\s\\xa0]+/g,\" \").replace(/^ | $/g,\"\"))||null}};\nBlockly.Blocks.procedures_callnoreturn={init:function(){this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL);this.setColour(290);this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_CALLNORETURN_CALL).appendField(\"\",\"NAME\");this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP);this.arguments_=[];this.quarkArguments_=this.quarkConnections_=null},getProcedureCall:function(){return this.getFieldValue(\"NAME\")},renameProcedure:function(a,\nb){Blockly.Names.equals(a,this.getFieldValue(\"NAME\"))&&(this.setFieldValue(b,\"NAME\"),this.setTooltip((this.outputConnection?Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP:Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP).replace(\"%1\",b)))},setProcedureParameters:function(a,b){if(b){if(b.length!=a.length)throw\"Error: paramNames and paramIds must be the same length.\";this.quarkArguments_||(this.quarkConnections_={},a.join(\"\\n\")==this.arguments_.join(\"\\n\")?this.quarkArguments_=b:this.quarkArguments_=[]);var c=\nthis.rendered;this.rendered=!1;for(var d=this.arguments_.length-1;0<=d;d--){var e=this.getInput(\"ARG\"+d);if(e){var f=e.connection.targetConnection;this.quarkConnections_[this.quarkArguments_[d]]=f;this.removeInput(\"ARG\"+d)}}this.arguments_=[].concat(a);this.quarkArguments_=b;for(d=0;d<this.arguments_.length;d++)if(e=this.appendValueInput(\"ARG\"+d).setAlign(Blockly.ALIGN_RIGHT).appendField(this.arguments_[d]),this.quarkArguments_){var g=this.quarkArguments_[d];g in this.quarkConnections_&&(f=this.quarkConnections_[g],\n!f||f.targetConnection||f.sourceBlock_.workspace!=this.workspace?delete this.quarkConnections_[g]:e.connection.connect(f))}(this.rendered=c)&&this.render()}else this.quarkConnections_={},this.quarkArguments_=null},mutationToDom:function(){var a=document.createElement(\"mutation\");a.setAttribute(\"name\",this.getFieldValue(\"NAME\"));for(var b=0;b<this.arguments_.length;b++){var c=document.createElement(\"arg\");c.setAttribute(\"name\",this.arguments_[b]);a.appendChild(c)}return a},domToMutation:function(a){var b=\na.getAttribute(\"name\");this.setFieldValue(b,\"NAME\");this.setTooltip((this.outputConnection?Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP:Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP).replace(\"%1\",b));if((b=Blockly.Procedures.getDefinition(b,this.workspace))&&b.mutator.isVisible())this.setProcedureParameters(b.arguments_,b.paramIds_);else{this.arguments_=[];for(var b=0,c;c=a.childNodes[b];b++)\"arg\"==c.nodeName.toLowerCase()&&this.arguments_.push(c.getAttribute(\"name\"));this.setProcedureParameters(this.arguments_,\nthis.arguments_)}},renameVar:function(a,b){for(var c=0;c<this.arguments_.length;c++)Blockly.Names.equals(a,this.arguments_[c])&&(this.arguments_[c]=b,this.getInput(\"ARG\"+c).fieldRow[0].setText(b))},customContextMenu:function(a){var b={enabled:!0};b.text=Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF;var c=this.getFieldValue(\"NAME\"),d=this.workspace;b.callback=function(){var a=Blockly.Procedures.getDefinition(c,d);a&&a.select()};a.push(b)}};\nBlockly.Blocks.procedures_callreturn={init:function(){this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL);this.setColour(290);this.appendDummyInput().appendField(Blockly.Msg.PROCEDURES_CALLRETURN_CALL).appendField(\"\",\"NAME\");this.setOutput(!0);this.setTooltip(Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP);this.arguments_=[];this.quarkArguments_=this.quarkConnections_=null},getProcedureCall:Blockly.Blocks.procedures_callnoreturn.getProcedureCall,renameProcedure:Blockly.Blocks.procedures_callnoreturn.renameProcedure,\nsetProcedureParameters:Blockly.Blocks.procedures_callnoreturn.setProcedureParameters,mutationToDom:Blockly.Blocks.procedures_callnoreturn.mutationToDom,domToMutation:Blockly.Blocks.procedures_callnoreturn.domToMutation,renameVar:Blockly.Blocks.procedures_callnoreturn.renameVar,customContextMenu:Blockly.Blocks.procedures_callnoreturn.customContextMenu};\nBlockly.Blocks.procedures_ifreturn={init:function(){this.setHelpUrl(\"http://c2.com/cgi/wiki?GuardClause\");this.setColour(290);this.appendValueInput(\"CONDITION\").setCheck(\"Boolean\").appendField(Blockly.Msg.CONTROLS_IF_MSG_IF);this.appendValueInput(\"VALUE\").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);this.setInputsInline(!0);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP);this.hasReturnValue_=!0},mutationToDom:function(){var a=\ndocument.createElement(\"mutation\");a.setAttribute(\"value\",Number(this.hasReturnValue_));return a},domToMutation:function(a){this.hasReturnValue_=1==a.getAttribute(\"value\");this.hasReturnValue_||(this.removeInput(\"VALUE\"),this.appendDummyInput(\"VALUE\").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN))},onchange:function(){if(this.workspace){var a=!1,b=this;do{if(\"procedures_defnoreturn\"==b.type||\"procedures_defreturn\"==b.type){a=!0;break}b=b.getSurroundParent()}while(b);a?(\"procedures_defnoreturn\"==\nb.type&&this.hasReturnValue_?(this.removeInput(\"VALUE\"),this.appendDummyInput(\"VALUE\").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN),this.hasReturnValue_=!1):\"procedures_defreturn\"!=b.type||this.hasReturnValue_||(this.removeInput(\"VALUE\"),this.appendValueInput(\"VALUE\").appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN),this.hasReturnValue_=!0),this.setWarningText(null)):this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING)}}};Blockly.Blocks.variables={};\nBlockly.Blocks.variables_get={init:function(){this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL);this.setColour(330);this.appendDummyInput().appendField(Blockly.Msg.VARIABLES_GET_TITLE).appendField(new Blockly.FieldVariable(Blockly.Msg.VARIABLES_GET_ITEM),\"VAR\").appendField(Blockly.Msg.VARIABLES_GET_TAIL);this.setOutput(!0);this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP);this.contextMenuMsg_=Blockly.Msg.VARIABLES_GET_CREATE_SET;this.contextMenuType_=\"variables_set\"},getVars:function(){return[this.getFieldValue(\"VAR\")]},\nrenameVar:function(a,b){Blockly.Names.equals(a,this.getFieldValue(\"VAR\"))&&this.setFieldValue(b,\"VAR\")},customContextMenu:function(a){var b={enabled:!0},c=this.getFieldValue(\"VAR\");b.text=this.contextMenuMsg_.replace(\"%1\",c);c=goog.dom.createDom(\"field\",null,c);c.setAttribute(\"name\",\"VAR\");c=goog.dom.createDom(\"block\",null,c);c.setAttribute(\"type\",this.contextMenuType_);b.callback=Blockly.ContextMenu.callbackFactory(this,c);a.push(b)}};\nBlockly.Blocks.variables_set={init:function(){this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL);this.setColour(330);this.interpolateMsg(Blockly.Msg.VARIABLES_SET_TITLE+\" %1 \"+Blockly.Msg.VARIABLES_SET_TAIL+\" %2\",[\"VAR\",new Blockly.FieldVariable(Blockly.Msg.VARIABLES_SET_ITEM)],[\"VALUE\",null,Blockly.ALIGN_RIGHT],Blockly.ALIGN_RIGHT);this.setPreviousStatement(!0);this.setNextStatement(!0);this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP);this.contextMenuMsg_=Blockly.Msg.VARIABLES_SET_CREATE_GET;this.contextMenuType_=\n\"variables_get\"},getVars:function(){return[this.getFieldValue(\"VAR\")]},renameVar:function(a,b){Blockly.Names.equals(a,this.getFieldValue(\"VAR\"))&&this.setFieldValue(b,\"VAR\")},customContextMenu:Blockly.Blocks.variables_get.customContextMenu};"
  },
  {
    "path": "extern/blockly/build.py",
    "content": "#!/usr/bin/python\n# Compresses the core Blockly files into a single JavaScript file.\n#\n# Copyright 2012 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n# This script generates two versions of Blockly's core files:\n#   blockly_compressed.js\n#   blockly_uncompressed.js\n# The compressed file is a concatenation of all of Blockly's core files which\n# have been run through Google's Closure Compiler.  This is done using the\n# online API (which takes a few seconds and requires an Internet connection).\n# The uncompressed file is a script that loads in each of Blockly's core files\n# one by one.  This takes much longer for a browser to load, but is useful\n# when debugging code since line numbers are meaningful and variables haven't\n# been renamed.  The uncompressed file also allows for a faster developement\n# cycle since there is no need to rebuild or recompile, just reload.\n#\n# This script also generates:\n#   blocks_compressed.js: The compressed Blockly language blocks.\n#   javascript_compressed.js: The compressed Javascript generator.\n#   python_compressed.js: The compressed Python generator.\n#   dart_compressed.js: The compressed Dart generator.\n#   msg/js/<LANG>.js for every language <LANG> defined in msg/js/<LANG>.json.\n\nimport errno, glob, httplib, json, os, re, subprocess, sys, threading, urllib\n\ndef import_path(fullpath):\n  \"\"\"Import a file with full path specification.\n  Allows one to import from any directory, something __import__ does not do.\n\n  Args:\n      fullpath:  Path and filename of import.\n\n  Returns:\n      An imported module.\n  \"\"\"\n  path, filename = os.path.split(fullpath)\n  filename, ext = os.path.splitext(filename)\n  sys.path.append(path)\n  module = __import__(filename)\n  reload(module) # Might be out of date\n  del sys.path[-1]\n  return module\n\n\nHEADER = ('// Do not edit this file; automatically generated by build.py.\\n'\n          '\"use strict\";\\n')\n\n\nclass Gen_uncompressed(threading.Thread):\n  \"\"\"Generate a JavaScript file that loads Blockly's raw files.\n  Runs in a separate thread.\n  \"\"\"\n  def __init__(self, search_paths):\n    threading.Thread.__init__(self)\n    self.search_paths = search_paths\n\n  def run(self):\n    target_filename = 'blockly_uncompressed.js'\n    f = open(target_filename, 'w')\n    f.write(HEADER)\n    f.write(\"\"\"\nwindow.BLOCKLY_DIR = (function() {\n  // Find name of current directory.\n  var scripts = document.getElementsByTagName('script');\n  var re = new RegExp('(.+)[\\/]blockly_uncompressed\\.js$');\n  for (var x = 0, script; script = scripts[x]; x++) {\n    var match = re.exec(script.src);\n    if (match) {\n      return match[1];\n    }\n  }\n  alert('Could not detect Blockly\\\\'s directory name.');\n  return '';\n})();\n\nwindow.BLOCKLY_BOOT = function() {\n// Execute after Closure has loaded.\nif (!window.goog) {\n  alert('Error: Closure not found.  Read this:\\\\n' +\n        'http://code.google.com/p/blockly/wiki/Closure\\\\n');\n}\n\n// Build map of all dependencies (used and unused).\nvar dir = window.BLOCKLY_DIR.match(/[^\\\\/]+$/)[0];\n\"\"\")\n    add_dependency = []\n    base_path = calcdeps.FindClosureBasePath(self.search_paths)\n    for dep in calcdeps.BuildDependenciesFromFiles(self.search_paths):\n      add_dependency.append(calcdeps.GetDepsLine(dep, base_path))\n    add_dependency = '\\n'.join(add_dependency)\n    # Find the Blockly directory name and replace it with a JS variable.\n    # This allows blockly_uncompressed.js to be compiled on one computer and be\n    # used on another, even if the directory name differs.\n    m = re.search('[\\\\/]([^\\\\/]+)[\\\\/]core[\\\\/]blockly.js', add_dependency)\n    add_dependency = re.sub('([\\\\/])' + re.escape(m.group(1)) +\n        '([\\\\/]core[\\\\/])', '\\\\1\" + dir + \"\\\\2', add_dependency)\n    f.write(add_dependency + '\\n')\n\n    provides = []\n    for dep in calcdeps.BuildDependenciesFromFiles(self.search_paths):\n      if not dep.filename.startswith(os.pardir + os.sep):  # '../'\n        provides.extend(dep.provides)\n    provides.sort()\n    f.write('\\n')\n    f.write('// Load Blockly.\\n')\n    for provide in provides:\n      f.write('goog.require(\\'%s\\');\\n' % provide)\n\n    f.write(\"\"\"\ndelete window.BLOCKLY_DIR;\ndelete window.BLOCKLY_BOOT;\n};\n\n// Delete any existing Closure (e.g. Soy's nogoog_shim).\ndocument.write('<script type=\"text/javascript\">var goog = undefined;</script>');\n// Load fresh Closure Library.\ndocument.write('<script type=\"text/javascript\" src=\"' + window.BLOCKLY_DIR +\n    '/../../closure-library/closure/goog/base.js\"></script>');\ndocument.write('<script type=\"text/javascript\">window.BLOCKLY_BOOT()</script>');\n\"\"\")\n    f.close()\n    print('SUCCESS: ' + target_filename)\n\n\nclass Gen_compressed(threading.Thread):\n  \"\"\"Generate a JavaScript file that contains all of Blockly's core and all\n  required parts of Closure, compiled together.\n  Uses the Closure Compiler's online API.\n  Runs in a separate thread.\n  \"\"\"\n  def __init__(self, search_paths):\n    threading.Thread.__init__(self)\n    self.search_paths = search_paths\n\n  def run(self):\n    self.gen_core()\n    self.gen_blocks()\n    self.gen_generator('javascript')\n    self.gen_generator('python')\n    self.gen_generator('dart')\n\n  def gen_core(self):\n    target_filename = 'blockly_compressed.js'\n    # Define the parameters for the POST request.\n    params = [\n        ('compilation_level', 'SIMPLE_OPTIMIZATIONS'),\n        ('use_closure_library', 'true'),\n        ('output_format', 'json'),\n        ('output_info', 'compiled_code'),\n        ('output_info', 'warnings'),\n        ('output_info', 'errors'),\n        ('output_info', 'statistics'),\n        ('language', 'ECMASCRIPT5'),\n      ]\n\n    # Read in all the source files.\n    filenames = calcdeps.CalculateDependencies(self.search_paths,\n        [os.path.join('core', 'blockly.js')])\n    for filename in filenames:\n      # Filter out the Closure files (the compiler will add them).\n      if filename.startswith(os.pardir + os.sep):  # '../'\n        continue\n      f = open(filename)\n      params.append(('js_code', ''.join(f.readlines())))\n      f.close()\n\n    self.do_compile(params, target_filename, filenames, '')\n\n  def gen_blocks(self):\n    target_filename = 'blocks_compressed.js'\n    # Define the parameters for the POST request.\n    params = [\n        ('compilation_level', 'SIMPLE_OPTIMIZATIONS'),\n        ('output_format', 'json'),\n        ('output_info', 'compiled_code'),\n        ('output_info', 'warnings'),\n        ('output_info', 'errors'),\n        ('output_info', 'statistics'),\n        ('language', 'ECMASCRIPT5'),\n      ]\n\n    # Read in all the source files.\n    # Add Blockly.Blocks to be compatible with the compiler.\n    params.append(('js_code', \"goog.provide('Blockly.Blocks');\"))\n    filenames = glob.glob(os.path.join('blocks', '*.js'))\n    for filename in filenames:\n      f = open(filename)\n      params.append(('js_code', ''.join(f.readlines())))\n      f.close()\n\n    # Remove Blockly.Blocks to be compatible with Blockly.\n    remove = \"var Blockly={Blocks:{}};\"\n    self.do_compile(params, target_filename, filenames, remove)\n\n  def gen_generator(self, language):\n    target_filename = language + '_compressed.js'\n    # Define the parameters for the POST request.\n    params = [\n        ('compilation_level', 'SIMPLE_OPTIMIZATIONS'),\n        ('output_format', 'json'),\n        ('output_info', 'compiled_code'),\n        ('output_info', 'warnings'),\n        ('output_info', 'errors'),\n        ('output_info', 'statistics'),\n        ('language', 'ECMASCRIPT5'),\n      ]\n\n    # Read in all the source files.\n    # Add Blockly.Generator to be compatible with the compiler.\n    params.append(('js_code', \"goog.provide('Blockly.Generator');\"))\n    filenames = glob.glob(\n        os.path.join('generators', language, '*.js'))\n    filenames.insert(0, os.path.join('generators', language + '.js'))\n    for filename in filenames:\n      f = open(filename)\n      params.append(('js_code', ''.join(f.readlines())))\n      f.close()\n    filenames.insert(0, '[goog.provide]')\n\n    # Remove Blockly.Generator to be compatible with Blockly.\n    remove = \"var Blockly={Generator:{}};\"\n    self.do_compile(params, target_filename, filenames, remove)\n\n  def do_compile(self, params, target_filename, filenames, remove):\n    # Send the request to Google.\n    headers = { \"Content-type\": \"application/x-www-form-urlencoded\" }\n    conn = httplib.HTTPConnection('closure-compiler.appspot.com')\n    conn.request('POST', '/compile', urllib.urlencode(params), headers)\n    response = conn.getresponse()\n    json_str = response.read()\n    conn.close()\n\n    # Parse the JSON response.\n    json_data = json.loads(json_str)\n\n    def file_lookup(name):\n      if not name.startswith('Input_'):\n        return '???'\n      n = int(name[6:])\n      return filenames[n]\n\n    if json_data.has_key('serverErrors'):\n      errors = json_data['serverErrors']\n      for error in errors:\n        print 'SERVER ERROR: %s' % target_filename\n        print error['error']\n    elif json_data.has_key('errors'):\n      errors = json_data['errors']\n      for error in errors:\n        print('FATAL ERROR')\n        print(error['error'])\n        print('%s at line %d:' % (\n            file_lookup(error['file']), error['lineno']))\n        print(error['line'])\n        print((' ' * error['charno']) + '^')\n        sys.exit(1)\n    else:\n      if json_data.has_key('warnings'):\n        warnings = json_data['warnings']\n        for warning in warnings:\n          print('WARNING')\n          print(warning['warning'])\n          print('%s at line %d:' % (\n              file_lookup(warning['file']), warning['lineno']))\n          print(warning['line'])\n          print((' ' * warning['charno']) + '^')\n        print()\n\n      if not json_data.has_key('compiledCode'):\n        print('FATAL ERROR: Compiler did not return compiledCode.')\n        sys.exit(1)\n\n      code = HEADER + '\\n' + json_data['compiledCode']\n      code = code.replace(remove, '')\n\n      # Trim down Google's Apache licences.\n      LICENSE = re.compile(\"\"\"/\\\\*\n\n [\\w ]+\n\n (Copyright \\\\d+ Google Inc.)\n https://blockly.googlecode.com/\n\n Licensed under the Apache License, Version 2.0 \\(the \"License\"\\);\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\\\\*/\"\"\")\n      code = re.sub(LICENSE, r\"\\n// \\1  Apache License 2.0\", code)\n\n      stats = json_data['statistics']\n      original_b = stats['originalSize']\n      compressed_b = stats['compressedSize']\n      if original_b > 0 and compressed_b > 0:\n        f = open(target_filename, 'w')\n        f.write(code)\n        f.close()\n\n        original_kb = int(original_b / 1024 + 0.5)\n        compressed_kb = int(compressed_b / 1024 + 0.5)\n        ratio = int(float(compressed_b) / float(original_b) * 100 + 0.5)\n        print('SUCCESS: ' + target_filename)\n        print('Size changed from %d KB to %d KB (%d%%).' % (\n            original_kb, compressed_kb, ratio))\n      else:\n        print 'UNKNOWN ERROR'\n\n\nclass Gen_langfiles(threading.Thread):\n  \"\"\"Generate JavaScript file for each natural language supported.\n\n  Runs in a separate thread.\n  \"\"\"\n\n  def __init__(self):\n    threading.Thread.__init__(self)\n\n  def _rebuild(self, srcs, dests):\n    # Determine whether any of the files in srcs is newer than any in dests.\n    try:\n      return (max(os.path.getmtime(src) for src in srcs) >\n              min(os.path.getmtime(dest) for dest in dests))\n    except OSError, e:\n      # Was a file not found?\n      if e.errno == errno.ENOENT:\n        # If it was a source file, we can't proceed.\n        if e.filename in srcs:\n          print('Source file missing: ' + e.filename)\n          sys.exit(1)\n        else:\n          # If a destination file was missing, rebuild.\n          return True\n      else:\n        print('Error checking file creation times: ' + e)\n\n  def run(self):\n    # The files msg/json/{en,qqq,synonyms}.json depend on msg/messages.js.\n    if self._rebuild([os.path.join('msg', 'messages.js')],\n                     [os.path.join('msg', 'json', f) for f in\n                      ['en.json', 'qqq.json', 'synonyms.json']]):\n      try:\n        subprocess.check_call([\n            os.path.join('i18n', 'js_to_json.py'),\n            '--input_file', 'msg/messages.js',\n            '--output_dir', 'msg/json/',\n            '--quiet'])\n      except (subprocess.CalledProcessError, OSError), e:\n        # Documentation for subprocess.check_call says that CalledProcessError\n        # will be raised on failure, but I found that OSError is also possible.\n        print('Error running i18n/js_to_json.py: ', e)\n        sys.exit(1)\n\n    # Checking whether it is necessary to rebuild the js files would be a lot of\n    # work since we would have to compare each <lang>.json file with each\n    # <lang>.js file.  Rebuilding is easy and cheap, so just go ahead and do it.\n    try:\n      # Use create_messages.py to create .js files from .json files.\n      cmd = [\n          os.path.join('i18n', 'create_messages.py'),\n          '--source_lang_file', os.path.join('msg', 'json', 'en.json'),\n          '--source_synonym_file', os.path.join('msg', 'json', 'synonyms.json'),\n          '--key_file', os.path.join('msg', 'json', 'keys.json'),\n          '--output_dir', os.path.join('msg', 'js'),\n          '--quiet']\n      json_files = glob.glob(os.path.join('msg', 'json', '*.json'))\n      json_files = [file for file in json_files if not\n                    (file.endswith(('keys.json', 'synonyms.json', 'qqq.json')))]\n      cmd.extend(json_files)\n      subprocess.check_call(cmd)\n    except (subprocess.CalledProcessError, OSError), e:\n      print('Error running i18n/create_messages.py: ', e)\n      sys.exit(1)\n\n    # Output list of .js files created.\n    for f in json_files:\n      # This assumes the path to the current directory does not contain 'json'.\n      f = f.replace('json', 'js')\n      if os.path.isfile(f):\n        print('SUCCESS: ' + f)\n      else:\n        print('FAILED to create ' + f)\n\n\nif __name__ == '__main__':\n  try:\n    # os.chdir(os.path.join('extern','blockly'));\n    # calcdeps = import_path(os.path.join(os.path.pardir, os.path.pardir, 'lib',\n    #       'closure-library', 'closure', 'bin', 'calcdeps.py'))\n    calcdeps = import_path(os.path.join(os.path.pardir,\n          'closure-library', 'closure', 'bin', 'calcdeps.py'))\n    print calcdeps\n  except ImportError:\n    print(\"\"\"Error: Closure not found.  Read this:\nhttp://code.google.com/p/blockly/wiki/Closure\"\"\")\n    sys.exit(1)\n  search_paths = calcdeps.ExpandDirectories(\n      ['core', os.path.join(os.path.pardir, 'closure-library')])\n  #    ['core', os.path.join(os.path.pardir, os.path.pardir, 'lib', 'closure-library')])\n\n  # Run both tasks in parallel threads.\n  # Uncompressed is limited by processor speed.\n  # Compressed is limited by network and server speed.\n  Gen_uncompressed(search_paths).start()\n  Gen_compressed(search_paths).start()\n\n  # This is run locally in a separate thread.\n  Gen_langfiles().start()\n"
  },
  {
    "path": "extern/blockly/core/block.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview The class representing one block.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Block');\n\ngoog.require('Blockly.BlockSvg');\ngoog.require('Blockly.Blocks');\ngoog.require('Blockly.Comment');\ngoog.require('Blockly.Connection');\ngoog.require('Blockly.ContextMenu');\ngoog.require('Blockly.Input');\ngoog.require('Blockly.Msg');\ngoog.require('Blockly.Mutator');\ngoog.require('Blockly.Warning');\ngoog.require('Blockly.Workspace');\ngoog.require('Blockly.Xml');\ngoog.require('goog.asserts');\ngoog.require('goog.string');\ngoog.require('goog.Timer');\ngoog.require('goog.array');\n\n\n/**\n * Unique ID counter for created blocks.\n * @private\n */\nBlockly.uidCounter_ = 0;\n\n/**\n * Get the Blockly.uidCounter_\n * @returns {number}\n */\nBlockly.getUidCounter = function() {\n  return Blockly.uidCounter_;\n}\n\n/**\n * Set the Blockly.uidCounter_\n * @param {number} val The value to set the counter to.\n */\nBlockly.setUidCounter = function(val) {\n  Blockly.uidCounter_ = val;\n}\n\n/**\n* Class for one block.\n* @constructor\n*/\nBlockly.Block = function() {\n  // We assert this here because there may be users of the previous form of\n  // this constructor, which took arguments.\n  goog.asserts.assert(arguments.length == 0,\n      'Please use Blockly.Block.obtain.');\n};\n\n/**\n * Obtain a newly created block.\n * @param {!Blockly.Workspace} workspace The block's workspace.\n * @param {?string} prototypeName Name of the language object containing\n *     type-specific functions for this block.\n * @return {!Blockly.Block} The created block\n */\nBlockly.Block.obtain = function(workspace, prototypeName) {\n  if (Blockly.Realtime.isEnabled()) {\n    return Blockly.Realtime.obtainBlock(workspace, prototypeName);\n  } else {\n    var newBlock = new Blockly.Block();\n    newBlock.initialize(workspace, prototypeName);\n    return newBlock;\n  }\n};\n\n/**\n * Initialization for one block.\n * @param {!Blockly.Workspace} workspace The new block's workspace.\n * @param {?string} prototypeName Name of the language object containing\n *     type-specific functions for this block.\n */\nBlockly.Block.prototype.initialize = function(workspace, prototypeName) {\n  this.id = ++Blockly.uidCounter_;\n  workspace.addTopBlock(this);\n  this.fill(workspace, prototypeName);\n  // Bind an onchange function, if it exists.\n  if (goog.isFunction(this.onchange)) {\n    Blockly.bindEvent_(workspace.getCanvas(), 'blocklyWorkspaceChange', this,\n        this.onchange);\n  }\n};\n\n/**\n * Fill a block with initial values.\n * @param {!Blockly.Workspace} workspace The workspace to use.\n * @param {string} prototypeName The typename of the block.\n */\nBlockly.Block.prototype.fill = function(workspace, prototypeName) {\n  this.outputConnection = null;\n  this.nextConnection = null;\n  this.previousConnection = null;\n  this.inputList = [];\n  this.inputsInline = false;\n  this.rendered = false;\n  this.disabled = false;\n  this.tooltip = '';\n  this.contextMenu = true;\n\n  this.parentBlock_ = null;\n  this.childBlocks_ = [];\n  this.deletable_ = true;\n  this.movable_ = true;\n  this.addable_ = true;\n  this.editable_ = true;\n  this.collapsed_ = false;\n\n  this.workspace = workspace;\n  this.isInFlyout = workspace.isFlyout;\n\n  // Copy the type-specific functions and data from the prototype.\n  if (prototypeName) {\n    this.type = prototypeName;\n    var prototype = Blockly.Blocks[prototypeName];\n    goog.asserts.assertObject(prototype,\n        'Error: \"%s\" is an unknown language block.', prototypeName);\n    goog.mixin(this, prototype);\n  }\n  // Call an initialization function, if it exists.\n  if (goog.isFunction(this.init)) {\n    this.init();\n  }\n  if (goog.isFunction(this.whenAdd)) {\n      if (this.workspace == Blockly.mainWorkspace)\n          this.whenAdd();\n  }\n};\n\n/**\n * Get an existing block.\n * @param {string} id The block's id.\n * @param {!Blockly.Workspace} workspace The block's workspace.\n * @return {Blockly.Block} The found block, or null if not found.\n */\nBlockly.Block.getById = function(id, workspace) {\n  if (Blockly.Realtime.isEnabled()) {\n    return Blockly.Realtime.getBlockById(id);\n  } else {\n    return workspace.getBlockById(id);\n  }\n};\n\n/**\n * Pointer to SVG representation of the block.\n * @type {Blockly.BlockSvg}\n * @private\n */\nBlockly.Block.prototype.svg_ = null;\n\n/**\n * Block's mutator icon (if any).\n * @type {Blockly.Mutator}\n */\nBlockly.Block.prototype.mutator = null;\n\n/**\n * Block's comment icon (if any).\n * @type {Blockly.Comment}\n */\nBlockly.Block.prototype.comment = null;\n\n/**\n * Block's warning icon (if any).\n * @type {Blockly.Warning}\n */\nBlockly.Block.prototype.warning = null;\n\n/**\n * Returns a list of mutator, comment, and warning icons.\n * @return {!Array} List of icons.\n */\nBlockly.Block.prototype.getIcons = function() {\n  var icons = [];\n  if (this.mutator) {\n    icons.push(this.mutator);\n  }\n  if (this.comment) {\n    icons.push(this.comment);\n  }\n  if (this.warning) {\n    icons.push(this.warning);\n  }\n  return icons;\n};\n\n/**\n * Create and initialize the SVG representation of the block.\n */\nBlockly.Block.prototype.initSvg = function() {\n  this.svg_ = new Blockly.BlockSvg(this);\n  this.svg_.init();\n  if (!Blockly.readOnly) {\n    if (this.mouseDownWrapper_)\n        Blockly.unbindEvent_(this.mouseDownWrapper_);\n    this.mouseDownWrapper_ =\n        Blockly.bindEvent_(this.svg_.getRootElement(), 'mousedown', this,\n                       this.onMouseDown_);\n\n    if(this.type === \"function_general\") {\n      if (this.dblClickWrapper_)\n          Blockly.unbindEvent_(this.dblClickWrapper_);\n      this.dblClickWrapper_ =\n          Blockly.bindEvent_(this.svg_.getRootElement(), 'dblclick', this,\n                         this.onDblClick_);\n    }\n  }\n  if (Blockly.enableBlockAnimation) {\n      Blockly.bindEvent_(this.svg_.svgGroup_,\n        'mouseover', this.svg_, this.svg_.toggleOnPattern);\n      Blockly.bindEvent_(this.svg_.svgGroup_,\n        'mouseout', this.svg_, this.svg_.toggleOffPattern);\n  }\n  this.workspace.getCanvas().appendChild(this.svg_.getRootElement());\n};\n\n/**\n * Return the root node of the SVG or null if none exists.\n * @return {Element} The root SVG node (probably a group).\n */\nBlockly.Block.prototype.getSvgRoot = function() {\n  return this.svg_ && this.svg_.getRootElement();\n};\n\n/**\n * Is the mouse dragging a block?\n * 0 - No drag operation.\n * 1 - Still inside the sticky DRAG_RADIUS.\n * 2 - Freely draggable.\n * @private\n */\nBlockly.Block.dragMode_ = 0;\n\n/**\n * Wrapper function called when a mouseUp occurs during a drag operation.\n * @type {Array.<!Array>}\n * @private\n */\nBlockly.Block.onMouseUpWrapper_ = null;\n\n/**\n * Wrapper function called when a mouseMove occurs during a drag operation.\n * @type {Array.<!Array>}\n * @private\n */\nBlockly.Block.onMouseMoveWrapper_ = null;\n\n/**\n * Stop binding to the global mouseup and mousemove events.\n * @private\n */\nBlockly.Block.terminateDrag_ = function() {\n  if (Blockly.Block.onMouseUpWrapper_) {\n    Blockly.unbindEvent_(Blockly.Block.onMouseUpWrapper_);\n    Blockly.Block.onMouseUpWrapper_ = null;\n  }\n  if (Blockly.Block.onMouseMoveWrapper_) {\n    Blockly.unbindEvent_(Blockly.Block.onMouseMoveWrapper_);\n    Blockly.Block.onMouseMoveWrapper_ = null;\n  }\n\n\n  var selected = Blockly.selected;\n  if (Blockly.Block.dragMode_ == 2) {\n    // Terminate a drag operation.\n    if (selected) {\n      // Update the connection locations.\n      var xy = selected.getRelativeToSurfaceXY();\n      var dx = xy.x - selected.startDragX;\n      var dy = xy.y - selected.startDragY;\n      selected.moveConnections_(dx, dy);\n      delete selected.draggedBubbles_;\n      selected.setDragging_(false);\n      selected.render();\n      goog.Timer.callOnce(\n          selected.bumpNeighbours_, Blockly.BUMP_DELAY, selected);\n      // Fire an event to allow scrollbars to resize.\n\n      Blockly.fireUiEvent(window, 'resize');\n    }\n  }\n\n  if (selected) {\n    selected.workspace.fireChangeEvent();\n  }\n  Blockly.Block.dragMode_ = 0;\n};\n\n/**\n * Select this block.  Highlight it visually.\n */\nBlockly.Block.prototype.select = function() {\n  goog.asserts.assertObject(this.svg_, 'Block is not rendered.');\n  if (Blockly.selected) {\n    // Unselect any previously selected block.\n    Blockly.selected.unselect();\n  }\n  Blockly.selected = this;\n  this.svg_.addSelect();\n  Blockly.fireUiEvent(this.workspace.getCanvas(), 'blocklySelectChange');\n};\n\n/**\n * Activate this block.  Highlight it visually.\n */\nBlockly.Block.prototype.activate = function() {\n  goog.asserts.assertObject(this.svg_, 'Block is not rendered.');\n  if (Blockly.selected) {\n    // Unselect any previously selected block.\n    Blockly.selected.unselect();\n  }\n  Blockly.selected = this;\n  this.svg_.addActive();\n  Blockly.fireUiEvent(this.workspace.getCanvas(), 'blocklySelectChange');\n};\n\n/**\n * Unselect this block.  Remove its highlighting.\n */\nBlockly.Block.prototype.unselect = function() {\n  goog.asserts.assertObject(this.svg_, 'Block is not rendered.');\n  Blockly.selected = null;\n  this.svg_.removeSelect();\n  Blockly.fireUiEvent(this.workspace.getCanvas(), 'blocklySelectChange');\n};\n\n/**\n * Dispose of this block.\n * @param {boolean} healStack If true, then try to heal any gap by connecting\n *     the next statement with the previous statement.  Otherwise, dispose of\n *     all children of this block.\n * @param {boolean} animate If true, show a disposal animation and sound.\n * @param {boolean} dontRemoveFromWorkspace If true, don't remove this block\n *     from the workspace's list of top blocks.\n */\nBlockly.Block.prototype.dispose = function(healStack, animate,\n                                           dontRemoveFromWorkspace) {\n  // Switch off rerendering.\n  //this.isEditing = true;\n  if (goog.isFunction(this.whenRemove)) {\n      if (this.workspace == Blockly.mainWorkspace\n          && this.isDrag) {\n        this.whenRemove(Blockly.Xml.blockToDom_(this));\n      }\n  }\n  this.rendered = false;\n  this.unplug(healStack);\n  if (animate && this.svg_) {\n    this.svg_.disposeUiEffect();\n  }\n\n  // This block is now at the top of the workspace.\n  // Remove this block from the workspace's list of top-most blocks.\n  if (this.workspace && !dontRemoveFromWorkspace) {\n    this.workspace.removeTopBlock(this);\n    this.workspace = null;\n  }\n\n  // Just deleting this block from the DOM would result in a memory leak as\n  // well as corruption of the connection database.  Therefore we must\n  // methodically step through the blocks and carefully disassemble them.\n\n  if (Blockly.selected == this) {\n    Blockly.selected = null;\n    // If there's a drag in-progress, unlink the mouse events.\n    Blockly.terminateDrag_();\n  }\n\n  // First, dispose of all my children.\n  for (var x = this.childBlocks_.length - 1; x >= 0; x--) {\n    this.childBlocks_[x].dispose(false);\n  }\n  // Then dispose of myself.\n  var icons = this.getIcons();\n  for (var x = 0; x < icons.length; x++) {\n    icons[x].dispose();\n  }\n  // Dispose of all inputs and their fields.\n  for (var x = 0, input; input = this.inputList[x]; x++) {\n    input.dispose();\n  }\n  this.inputList = [];\n  // Dispose of any remaining connections (next/previous/output).\n  var connections = this.getConnections_(true);\n  for (var x = 0; x < connections.length; x++) {\n    var connection = connections[x];\n    if (connection.targetConnection) {\n      connection.disconnect();\n    }\n    connections[x].dispose();\n  }\n  // Dispose of the SVG and break circular references.\n  if (this.svg_) {\n    this.svg_.dispose();\n    this.svg_ = null;\n  }\n  // Remove from Realtime set of blocks.\n  if (Blockly.Realtime.isEnabled() && !Blockly.Realtime.withinSync) {\n    Blockly.Realtime.removeBlock(this);\n  }\n};\n\n/**\n * Unplug this block from its superior block.  If this block is a statement,\n * optionally reconnect the block underneath with the block on top.\n * @param {boolean} healStack Disconnect child statement and reconnect stack.\n * @param {boolean} bump Move the unplugged block sideways a short distance.\n */\nBlockly.Block.prototype.unplug = function(healStack, bump) {\n  bump = bump && !!this.getParent();\n  if (this.outputConnection) {\n    if (this.outputConnection.targetConnection) {\n      // Disconnect from any superior block.\n      this.setParent(null);\n    }\n  } else {\n    var previousTarget = null;\n    if (this.previousConnection && this.previousConnection.targetConnection) {\n      // Remember the connection that any next statements need to connect to.\n      previousTarget = this.previousConnection.targetConnection;\n      // Detach this block from the parent's tree.\n      this.setParent(null);\n    }\n    if (healStack && this.nextConnection &&\n        this.nextConnection.targetConnection) {\n      // Disconnect the next statement.\n      var nextTarget = this.nextConnection.targetConnection;\n      var nextBlock = this.nextConnection.targetBlock();\n      nextBlock.setParent(null);\n      if (previousTarget) {\n        // Attach the next statement to the previous statement.\n        previousTarget.connect(nextTarget);\n      }\n    }\n  }\n  if (bump) {\n    // Bump the block sideways.\n    var dx = Blockly.SNAP_RADIUS * (Blockly.RTL ? -1 : 1);\n    var dy = Blockly.SNAP_RADIUS * 2;\n    this.moveBy(dx, dy);\n  }\n};\n\n/**\n * Return the coordinates of the top-left corner of this block relative to the\n * drawing surface's origin (0,0).\n * @return {!Object} Object with .x and .y properties.\n */\nBlockly.Block.prototype.getRelativeToSurfaceXY = function() {\n  var x = 0;\n  var y = 0;\n  if (this.svg_) {\n    var element = this.svg_.getRootElement();\n    do {\n      // Loop through this block and every parent.\n      var xy = Blockly.getRelativeXY_(element);\n      x += xy.x;\n      y += xy.y;\n      element = element.parentNode;\n    } while (element && element != this.workspace.getCanvas());\n  }\n  return {x: x, y: y};\n};\n\n/**\n * Move a block by a relative offset.\n * @param {number} dx Horizontal offset.\n * @param {number} dy Vertical offset.\n */\nBlockly.Block.prototype.moveBy = function(dx, dy) {\n  var xy = this.getRelativeToSurfaceXY();\n  this.svg_.getRootElement().setAttribute('transform',\n      'translate(' + (xy.x + dx) + ', ' + (xy.y + dy) + ')');\n  this.moveConnections_(dx, dy);\n  if (Blockly.Realtime.isEnabled() && !Blockly.Realtime.withinSync) {\n    Blockly.Realtime.blockChanged(this);\n  }\n};\n\n/**\n * Returns a bounding box describing the dimensions of this block.\n * @return {!Object} Object with height and width properties.\n */\nBlockly.Block.prototype.getHeightWidth = function() {\n  try {\n    var bBox = this.getSvgRoot().getBBox();\n    var height = bBox.height;\n  } catch (e) {\n    // Firefox has trouble with hidden elements (Bug 528969).\n    return {height: 0, width: 0};\n  }\n  if (Blockly.BROKEN_CONTROL_POINTS) {\n    /* HACK:\n     WebKit bug 67298 causes control points to be included in the reported\n     bounding box.  The render functions (below) add two 5px spacer control\n     points that we need to subtract.\n    */\n    height -= 10;\n    if (this.nextConnection) {\n      // Bottom control point partially masked by lower tab.\n      height += 4;\n    }\n    if (!this.nextConnection && !this.outputConnection && this.previousConnection) {\n      height += 4;\n    }\n  }\n  // Subtract one from the height due to the shadow.\n  height -= 1;\n  return {height: height, width: bBox.width};\n};\n\nBlockly.Block.prototype.onDblClick_ = function(e) {\n  if (Entry.Func.isEdit)\n    return;\n\n   var funcs = Entry.variableContainer.functions_;\n   if(funcs && funcs.length !== 0)\n      Entry.Func.edit(funcs[this.hashId]);\n};\n\n/**\n * Handle a mouse-down on an SVG block.\n * @param {!Event} e Mouse down event.\n * @private\n */\nBlockly.Block.prototype.onMouseDown_ = function(e) {\n  if (Entry.documentMousedown)\n      Entry.documentMousedown.notify(e);\n\n  if (this.isInFlyout) {\n    this.select();\n    return;\n  }\n  // Update Blockly's knowledge of its own location.\n  Blockly.svgResize();\n  Blockly.terminateDrag_();\n  this.select();\n  Blockly.hideChaff();\n  if (Blockly.isRightButton(e)) {\n    // Right-click.\n     if (this.isInBlockMenu && Blockly.Block.dragMode_ == 0) {\n      if (this.stalkerBlock)\n        this.stalkerBlock.dispose();\n      this.dispose();\n      return;\n    }\n    this.isDrag = true;\n    if (Blockly.ContextMenu) {\n      this.showContextMenu_(Blockly.mouseToSvg(e));\n    }\n  } else if (Blockly.isMiddleButton(e)) {\n    // middle-click.\n     if (this.isInBlockMenu && Blockly.Block.dragMode_ == 0) {\n      if (this.stalkerBlock)\n        this.stalkerBlock.dispose();\n      this.dispose();\n      return;\n    }\n  } else if (!this.isMovable()) {\n    // Allow unmovable blocks to be selected and context menued, but not\n    // dragged.  Let this event bubble up to document, so the workspace may be\n    // dragged instead.\n    return;\n  } else {\n    // Left-click\n    if (typeof(Entry) == \"object\") {\n      Entry.dispatchEvent(\"entryBlocklyChanged\");\n    }\n    this.isDrag = false;\n    Blockly.removeAllRanges();\n    Blockly.setCursorHand_(true);\n    // Look up the current translation and record it.\n    var xy = this.getRelativeToSurfaceXY();\n    this.startDragX = xy.x;\n    this.startDragY = xy.y;\n    // Record the current mouse position.\n    this.startDragMouseX = e.clientX;\n    this.startDragMouseY = e.clientY;\n    Blockly.Block.dragMode_ = 1;\n    Blockly.Block.onMouseUpWrapper_ = Blockly.bindEvent_(document,\n        'mouseup', this, this.onMouseUp_);\n    Blockly.Block.onMouseMoveWrapper_ = Blockly.bindEvent_(document,\n        'mousemove', this, this.onMouseMove_);\n    // Build a list of bubbles that need to be moved and where they started.\n    this.draggedBubbles_ = [];\n    var descendants = this.getDescendants();\n    for (var x = 0, descendant; descendant = descendants[x]; x++) {\n      var icons = descendant.getIcons();\n      for (var y = 0; y < icons.length; y++) {\n        var data = icons[y].getIconLocation();\n        data.bubble = icons[y];\n        this.draggedBubbles_.push(data);\n      }\n    }\n  }\n  // This event has been handled.  No need to bubble up to the document.\n  e.stopPropagation();\n};\n\n/**\n * Handle a mouse-up anywhere in the SVG pane.  Is only registered when a\n * block is clicked.  We can't use mouseUp on the block since a fast-moving\n * cursor can briefly escape the block before it catches up.\n * @param {!Event} e Mouse up event.\n * @private\n */\nBlockly.Block.prototype.onMouseUp_ = function(e) {\n\n  if (this.isInBlockMenu) {\n    this.isInBlockMenu = false;\n    var selected = Blockly.selected;\n    if (selected && selected.willBeDeleted) {\n        this.stalkerBlock.dispose(false, false);\n        selected.dispose(false, true);\n        Blockly.terminateDrag_();\n        return;\n    } else {\n        this.stalkerBlock.dispose(false, false);\n        delete selected.willBeDeleted;\n    }\n\n    this.stalkerBlock = null;\n  }\n\n  if (!this.isDrag && typeof(Entry) == \"object\") {\n    //fire instant event\n    //Entry.fireInstantEvent(this.id);\n  };\n  Blockly.terminateDrag_();\n  if (Blockly.selected && Blockly.highlightedConnection_) {\n    // Connect two blocks together.\n    Blockly.localConnection_.connect(Blockly.highlightedConnection_);\n    if (this.svg_) {\n      // Trigger a connection animation.\n      // Determine which connection is inferior (lower in the source stack).\n      var inferiorConnection;\n      if (Blockly.localConnection_.isSuperior()) {\n        inferiorConnection = Blockly.highlightedConnection_;\n      } else {\n        inferiorConnection = Blockly.localConnection_;\n      }\n      inferiorConnection.sourceBlock_.svg_.connectionUiEffect();\n    }\n    if (this.workspace.trashcan && this.workspace.trashcan.isOpen) {\n      // Don't throw an object in the trash can if it just got connected.\n      this.workspace.trashcan.close();\n    }\n    if (typeof(Entry) == \"object\" && this.getParent() === this.isDisconnected) {\n      Entry.dispatchEvent(\"cancelLastCommand\");\n    }\n  } else if (this.workspace.trashcan && this.workspace.trashcan.isOpen) {\n    var trashcan = this.workspace.trashcan;\n    goog.Timer.callOnce(trashcan.close, 100, trashcan);\n\n    Blockly.selected.dispose(false, true);\n    // Dropping a block on the trash can will usually cause the workspace to\n    // resize to contain the newly positioned block.  Force a second resize now\n    // that the block has been deleted.\n    Blockly.fireUiEvent(window, 'resize');\n  } else if (this.isDisconnected) {\n  } else {\n    if (typeof(Entry) == \"object\") {\n      Entry.dispatchEvent(\"cancelLastCommand\");\n    }\n  }\n  if (typeof(Entry) == \"object\")\n    Entry.dispatchEvent(\"entryBlocklyMouseUp\");\n\n  if (Blockly.highlightedConnection_) {\n    Blockly.highlightedConnection_.unhighlight();\n    Blockly.highlightedConnection_ = null;\n  }\n};\n\n/**\n * Load the block's help page in a new window.\n * @private\n */\nBlockly.Block.prototype.showHelp_ = function() {\n  var url = goog.isFunction(this.helpUrl) ? this.helpUrl() : this.helpUrl;\n  if (url) {\n    window.open(url);\n  }\n};\n\n/**\n * Duplicate this block and its children.\n * @return {!Blockly.Block} The duplicate.\n * @private\n */\nBlockly.Block.prototype.duplicate_ = function() {\n  // Create a duplicate via XML.\n  var xmlBlock = Blockly.Xml.blockToDom_(this);\n  if (typeof(Entry) === \"object\") {\n      xmlBlock = Entry.changeXmlHashId(xmlBlock);\n  } else if (typeof(Ntry) === \"object\") {\n      xmlBlock = Ntry.changeXmlHashId(xmlBlock);\n  }\n  // Blockly.Xml.deleteNext(xmlBlock);\n  var newBlock = Blockly.Xml.domToBlock(\n      /** @type {!Blockly.Workspace} */ (this.workspace), xmlBlock);\n  // Move the duplicate next to the old block.\n  var xy = this.getRelativeToSurfaceXY();\n  if (Blockly.RTL) {\n    xy.x -= Blockly.SNAP_RADIUS;\n  } else {\n    xy.x += Blockly.SNAP_RADIUS;\n  }\n  xy.y += Blockly.SNAP_RADIUS * 2;\n  newBlock.moveBy(xy.x, xy.y);\n  return newBlock;\n};\n\n/**\n * Show the context menu for this block.\n * @param {!Object} xy Coordinates of mouse click, contains x and y properties.\n * @private\n */\nBlockly.Block.prototype.showContextMenu_ = function(xy) {\n  if (Blockly.readOnly || !this.contextMenu) {\n    return;\n  }\n  // Save the current block in a variable for use in closures.\n  var block = this;\n  var options = [];\n\n  if (this.isDeletable() && !block.isInFlyout) {\n    // Option to duplicate this block.\n    var duplicateOption = {\n      text: Lang.Blocks.Duplication_option,\n      enabled: true,\n      callback: function() {\n        block.duplicate_();\n        if (typeof(Entry) == \"object\") {\n          Entry.dispatchEvent(\"entryBlocklyChanged\");\n        }\n      }\n    };\n    if (this.getDescendants().length > this.workspace.remainingCapacity()) {\n      duplicateOption.enabled = false;\n    }\n    options.push(duplicateOption);\n\n    var copyOption = {\n        text: Lang.Blocks.CONTEXT_COPY_option,\n        enabled: true,\n        callback: function() {\n            Blockly.copy_(Blockly.selected);\n        }\n    };\n    if (this.getDescendants().length > this.workspace.remainingCapacity()) {\n      copyOption.enabled = false;\n    }\n    options.push(copyOption);\n\n    // Option to delete this block.\n    // Count the number of blocks that are nested in this block.\n    var descendantCount = this.getDescendants().length;\n    if (block.nextConnection && block.nextConnection.targetConnection) {\n      // Blocks in the current stack would survive this block's deletion.\n      descendantCount -= this.nextConnection.targetBlock().\n          getDescendants().length;\n    }\n    var deleteOption = {\n      text: descendantCount == 1 ? Lang.Blocks.Delete_Blocks :\n          Lang.Blocks.Delete_Blocks.replace('%1', descendantCount),\n      enabled: true,\n      callback: function() {\n        block.dispose(true, true);\n        if (typeof(Entry) == \"object\") {\n          Entry.dispatchEvent(\"entryBlocklyChanged\");\n        }\n      }\n    };\n    options.push(deleteOption);\n  }\n\n  // Allow the block to add or modify options.\n  if (this.customContextMenu && !block.isInFlyout) {\n    this.customContextMenu(options);\n  }\n\n  Blockly.ContextMenu.show(xy, options);\n};\n\n/**\n * Returns all connections originating from this block.\n * @param {boolean} all If true, return all connections even hidden ones.\n *     Otherwise return those that are visible.\n * @return {!Array.<!Blockly.Connection>} Array of connections.\n * @private\n */\nBlockly.Block.prototype.getConnections_ = function(all) {\n  var myConnections = [];\n  if (all || this.rendered) {\n    if (this.outputConnection) {\n      myConnections.push(this.outputConnection);\n    }\n    if (this.nextConnection) {\n      myConnections.push(this.nextConnection);\n    }\n    if (this.previousConnection) {\n      myConnections.push(this.previousConnection);\n    }\n    if (all || !this.collapsed_) {\n      for (var x = 0, input; input = this.inputList[x]; x++) {\n        if (input.connection) {\n          myConnections.push(input.connection);\n        }\n      }\n    }\n  }\n  return myConnections;\n};\n\n/**\n * Move the connections for this block and all blocks attached under it.\n * Also update any attached bubbles.\n * @param {number} dx Horizontal offset from current location.\n * @param {number} dy Vertical offset from current location.\n * @private\n */\nBlockly.Block.prototype.moveConnections_ = function(dx, dy) {\n  if (!this.rendered) {\n    // Rendering is required to lay out the blocks.\n    // This is probably an invisible block attached to a collapsed block.\n    return;\n  }\n  var myConnections = this.getConnections_(false);\n  for (var x = 0; x < myConnections.length; x++) {\n    myConnections[x].moveBy(dx, dy);\n  }\n  var icons = this.getIcons();\n  for (var x = 0; x < icons.length; x++) {\n    icons[x].computeIconLocation();\n  }\n\n  // Recurse through all blocks attached under this one.\n  for (var x = 0; x < this.childBlocks_.length; x++) {\n    this.childBlocks_[x].moveConnections_(dx, dy);\n  }\n};\n\n/**\n * Recursively adds or removes the dragging class to this node and its children.\n * @param {boolean} adding True if adding, false if removing.\n * @private\n */\nBlockly.Block.prototype.setDragging_ = function(adding) {\n  if (adding) {\n    this.svg_.addDragging();\n  } else {\n    this.svg_.removeDragging();\n  }\n  // Recurse through all blocks attached under this one.\n  for (var x = 0; x < this.childBlocks_.length; x++) {\n    this.childBlocks_[x].setDragging_(adding);\n  }\n};\n\n/**\n * Drag this block to follow the mouse.\n * @param {!Event} e Mouse move event.\n * @private\n */\nBlockly.Block.prototype.onMouseMove_ = function(e) {\n  Blockly.scrollBarOff = false;\n  this.isDrag = true;\n  if (this.stalkerBlock) {\n    this.stalkerBlock.isDrag = true;\n    this.stalkerBlock.g = true;\n  }\n  this.isEditing = true;\n  if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 &&\n      e.button == 0) {\n    /* HACK:\n     Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove events\n     on certain touch actions. Ignore events with these signatures.\n     This may result in a one-pixel blind spot in other browsers,\n     but this shouldn't be noticable. */\n    e.stopPropagation();\n    return;\n  }\n  Blockly.removeAllRanges();\n  var dx = e.clientX - this.startDragMouseX;\n  var dy = e.clientY - this.startDragMouseY;\n  if (Blockly.Block.dragMode_ == 1) {\n    // Still dragging within the sticky DRAG_RADIUS.\n    var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));\n    if (dr > Blockly.DRAG_RADIUS) {\n      // Switch to unrestricted dragging.\n      Blockly.Block.dragMode_ = 2;\n      // Push this block to the very top of the stack.\n      this.isDisconnected = this.getParent();\n      this.setParent(null);\n      this.setDragging_(true);\n    }\n  }\n  if (Blockly.Block.dragMode_ == 2) {\n    // Unrestricted dragging.\n    var x = this.startDragX + dx;\n    var y = this.startDragY + dy;\n    this.svg_.getRootElement().setAttribute('transform',\n        'translate(' + x + ', ' + y + ')');\n    if (this.stalkerBlock) {\n      this.willBeDeleted = true;\n      var sx = this.stalkerBlock.startDragX + dx;\n      var sy = this.stalkerBlock.startDragY + dy;\n      if (200 - sx < this.svg_.blockInlineWidth_ / 2)\n          this.willBeDeleted = false;\n\n      this.stalkerBlock.svg_.getRootElement().setAttribute('transform',\n          'translate(' + sx + ', ' + sy + ')');\n    }\n    // Drag all the nested bubbles.\n    for (var i = 0; i < this.draggedBubbles_.length; i++) {\n      var commentData = this.draggedBubbles_[i];\n      commentData.bubble.setIconLocation(commentData.x + dx,\n                                         commentData.y + dy);\n    }\n\n    // Check to see if any of this block's connections are within range of\n    // another block's connection.\n    var myConnections = this.getConnections_(false);\n    var closestConnection = null;\n    var localConnection = null;\n    var radiusConnection = Blockly.SNAP_RADIUS_ENTRY;\n    //var radiusConnection = Blockly.SNAP_RADIUS;\n    for (var i = 0; i < myConnections.length; i++) {\n      var myConnection = myConnections[i];\n      var neighbour = myConnection.closest(radiusConnection, dx, dy);\n      if (neighbour.connection) {\n        closestConnection = neighbour.connection;\n        localConnection = myConnection;\n        radiusConnection = neighbour.radius;\n      }\n    }\n\n    // Remove connection highlighting if needed.\n    if (Blockly.highlightedConnection_ &&\n        Blockly.highlightedConnection_ != closestConnection) {\n      Blockly.highlightedConnection_.unhighlight();\n      Blockly.highlightedConnection_ = null;\n      Blockly.localConnection_ = null;\n    }\n    // Add connection highlighting if needed.\n    if (closestConnection &&\n        closestConnection != Blockly.highlightedConnection_) {\n      closestConnection.highlight();\n      Blockly.highlightedConnection_ = closestConnection;\n      Blockly.localConnection_ = localConnection;\n    }\n    // Flip the trash can lid if needed.\n    if (this.workspace.trashcan && this.isDeletable()) {\n      this.workspace.trashcan.onMouseMove(e);\n    }\n  }\n  delete this.isEditing;\n  // This event has been handled.  No need to bubble up to the document.\n  e.stopPropagation();\n};\n\n/**\n * Bump unconnected blocks out of alignment.  Two blocks which aren't actually\n * connected should not coincidentally line up on screen.\n * @private\n */\nBlockly.Block.prototype.bumpNeighbours_ = function() {\n  if (Blockly.Block.dragMode_ != 0) {\n    // Don't bump blocks during a drag.\n    return;\n  }\n  var rootBlock = this.getRootBlock();\n  if (rootBlock.isInFlyout) {\n    // Don't move blocks around in a flyout.\n    return;\n  }\n  // Loop though every connection on this block.\n  var myConnections = this.getConnections_(false);\n  for (var x = 0; x < myConnections.length; x++) {\n    var connection = myConnections[x];\n    // Spider down from this block bumping all sub-blocks.\n    if (connection.targetConnection && connection.isSuperior()) {\n      connection.targetBlock().bumpNeighbours_();\n    }\n\n    var neighbours = connection.neighbours_(Blockly.SNAP_RADIUS);\n    for (var y = 0; y < neighbours.length; y++) {\n      var otherConnection = neighbours[y];\n      // If both connections are connected, that's probably fine.  But if\n      // either one of them is unconnected, then there could be confusion.\n      if (!connection.targetConnection || !otherConnection.targetConnection) {\n        // Only bump blocks if they are from different tree structures.\n        if (otherConnection.sourceBlock_.getRootBlock() != rootBlock) {\n          // Always bump the inferior block.\n          if (connection.isSuperior()) {\n            otherConnection.bumpAwayFrom_(connection);\n          } else {\n            connection.bumpAwayFrom_(otherConnection);\n          }\n        }\n      }\n    }\n  }\n};\n\n/**\n * Return the parent block or null if this block is at the top level.\n * @return {Blockly.Block} The block that holds the current block.\n */\nBlockly.Block.prototype.getParent = function() {\n  // Look at the DOM to see if we are nested in another block.\n  return this.parentBlock_;\n};\n\n/**\n * Return the parent block that surrounds the current block, or null if this\n * block has no surrounding block.  A parent block might just be the previous\n * statement, whereas the surrounding block is an if statement, while loop, etc.\n * @return {Blockly.Block} The block that surrounds the current block.\n */\nBlockly.Block.prototype.getSurroundParent = function() {\n  var block = this;\n  while (true) {\n    do {\n      var prevBlock = block;\n      block = block.getParent();\n      if (!block) {\n        // Ran off the top.\n        return null;\n      }\n    } while (block.nextConnection &&\n             block.nextConnection.targetBlock() == prevBlock);\n    // This block is an enclosing parent, not just a statement in a stack.\n    return block;\n  }\n};\n\n/**\n * Return the top-most block in this block's tree.\n * This will return itself if this block is at the top level.\n * @return {!Blockly.Block} The root block.\n */\nBlockly.Block.prototype.getRootBlock = function() {\n  var rootBlock;\n  var block = this;\n  do {\n    rootBlock = block;\n    block = rootBlock.parentBlock_;\n  } while (block);\n  return rootBlock;\n};\n\n/**\n * Find all the blocks that are directly nested inside this one.\n * Includes value and block inputs, as well as any following statement.\n * Excludes any connection on an output tab or any preceding statement.\n * @return {!Array.<!Blockly.Block>} Array of blocks.\n */\nBlockly.Block.prototype.getChildren = function() {\n  return this.childBlocks_;\n};\n\n/**\n * Set parent of this block to be a new block or null.\n * @param {Blockly.Block} newParent New parent block.\n */\nBlockly.Block.prototype.setParent = function(newParent) {\n  if (this.parentBlock_) {\n    // Remove this block from the old parent's child list.\n    var children = this.parentBlock_.childBlocks_;\n    for (var child, x = 0; child = children[x]; x++) {\n      if (child == this) {\n        children.splice(x, 1);\n        break;\n      }\n    }\n    // Move this block up the DOM.  Keep track of x/y translations.\n    var xy = this.getRelativeToSurfaceXY();\n    this.workspace.getCanvas().appendChild(this.getSvgRoot());\n    this.svg_.getRootElement().setAttribute('transform',\n        'translate(' + xy.x + ', ' + xy.y + ')');\n\n    // Disconnect from superior blocks.\n    this.parentBlock_ = null;\n    if (this.previousConnection && this.previousConnection.targetConnection) {\n      this.previousConnection.disconnect();\n    }\n    if (this.outputConnection && this.outputConnection.targetConnection) {\n      this.outputConnection.disconnect();\n    }\n    // This block hasn't actually moved on-screen, so there's no need to update\n    // its connection locations.\n  } else {\n    // Remove this block from the workspace's list of top-most blocks.\n    // Note that during realtime sync we sometimes create child blocks that are\n    // not top level so we check first before removing.\n    if (goog.array.contains(this.workspace.getTopBlocks(false), this)) {\n      this.workspace.removeTopBlock(this);\n    }\n  }\n\n  this.parentBlock_ = newParent;\n  if (newParent) {\n    // Add this block to the new parent's child list.\n    newParent.childBlocks_.push(this);\n\n    var oldXY = this.getRelativeToSurfaceXY();\n    if (newParent.svg_ && this.svg_) {\n        newParent.svg_.getRootElement().insertBefore(this.svg_.getRootElement(),\n            newParent.svg_.svgPath_);\n    }\n    var newXY = this.getRelativeToSurfaceXY();\n    // Move the connections to match the child's new position.\n    this.moveConnections_(newXY.x - oldXY.x, newXY.y - oldXY.y);\n  } else {\n    this.workspace.addTopBlock(this);\n  }\n};\n\n/**\n * Find all the blocks that are directly or indirectly nested inside this one.\n * Includes this block in the list.\n * Includes value and block inputs, as well as any following statements.\n * Excludes any connection on an output tab or any preceding statements.\n * @return {!Array.<!Blockly.Block>} Flattened array of blocks.\n */\nBlockly.Block.prototype.getDescendants = function() {\n  var blocks = [this];\n  for (var child, x = 0; child = this.childBlocks_[x]; x++) {\n    blocks = blocks.concat(child.getDescendants());\n  }\n  return blocks;\n};\n\n/**\n * Get whether this block is deletable or not.\n * @return {boolean} True if deletable.\n */\nBlockly.Block.prototype.isDeletable = function() {\n  return this.deletable_ && !Blockly.readOnly;\n};\n\n/**\n * Set whether this block is deletable or not.\n * @param {boolean} deletable True if deletable.\n */\nBlockly.Block.prototype.setDeletable = function(deletable) {\n  this.deletable_ = deletable;\n  this.svg_ && this.svg_.updateMovable();\n};\n\n/**\n * Get whether this block is movable or not.\n * @return {boolean} True if movable.\n */\nBlockly.Block.prototype.isMovable = function() {\n  return this.movable_ && !Blockly.readOnly;\n};\n\n/**\n * Set whether this block is movable or not.\n * @param {boolean} movable True if movable.\n */\nBlockly.Block.prototype.setMovable = function(movable) {\n  this.movable_ = movable;\n};\n\n/**\n * Set whether this block is addable or not.\n * @param {boolean} addable True if addable.\n */\nBlockly.Block.prototype.setAddable = function(addable) {\n  this.addable_ = addable;\n};\n/**\n * Get whether this block is addable or not.\n * @return {boolean} True if addable.\n */\nBlockly.Block.prototype.isAddable = function() {\n  return this.addable_ && !Blockly.readOnly;\n};\n\n/**\n * Get whether this block is editable or not.\n * @return {boolean} True if editable.\n */\nBlockly.Block.prototype.isEditable = function() {\n  return this.editable_ && !Blockly.readOnly;\n};\n\n/**\n * Set whether this block is editable or not.\n * @param {boolean} editable True if editable.\n */\nBlockly.Block.prototype.setEditable = function(editable) {\n  this.editable_ = editable;\n  for (var x = 0, input; input = this.inputList[x]; x++) {\n    for (var y = 0, field; field = input.fieldRow[y]; y++) {\n      field.updateEditable();\n    }\n  }\n  var icons = this.getIcons();\n  for (var x = 0; x < icons.length; x++) {\n    icons[x].updateEditable();\n  }\n};\n\n/**\n * Set the URL of this block's help page.\n * @param {string|Function} url URL string for block help, or function that\n *     returns a URL.  Null for no help.\n */\nBlockly.Block.prototype.setHelpUrl = function(url) {\n  this.helpUrl = url;\n};\n\n/**\n * Get the colour of a block.\n * @return {number} HSV hue value.\n */\nBlockly.Block.prototype.getColour = function() {\n  return this.colourHue_;\n};\n\n/**\n * Change the colour of a block.\n * @param {number} colourHue HSV hue value.\n */\nBlockly.Block.prototype.setColour = function(colourHue) {\n  this.colourHue_ = colourHue;\n  if (this.svg_) {\n    this.svg_.updateColour();\n  }\n  var icons = this.getIcons();\n  for (var x = 0; x < icons.length; x++) {\n    icons[x].updateColour();\n  }\n  if (this.rendered) {\n    // Bump every dropdown to change its colour.\n    for (var x = 0, input; input = this.inputList[x]; x++) {\n      for (var y = 0, field; field = input.fieldRow[y]; y++) {\n        field.setText(null);\n      }\n    }\n    this.render();\n  }\n};\n\n/**\n * Returns the named field from a block.\n * @param {string} name The name of the field.\n * @return {Blockly.Field} Named field, or null if field does not exist.\n * @private\n */\nBlockly.Block.prototype.getField_ = function(name) {\n  for (var x = 0, input; input = this.inputList[x]; x++) {\n    for (var y = 0, field; field = input.fieldRow[y]; y++) {\n      if (field.name === name) {\n        return field;\n      }\n    }\n  }\n  return null;\n};\n\n/**\n * Returns the language-neutral value from the field of a block.\n * @param {string} name The name of the field.\n * @return {?string} Value from the field or null if field does not exist.\n */\nBlockly.Block.prototype.getFieldValue = function(name) {\n  var field = this.getField_(name);\n  if (field) {\n    return field.getValue();\n  }\n  return null;\n};\n\n/**\n * Returns the language-neutral value from the field of a block.\n * @param {string} name The name of the field.\n * @return {?string} Value from the field or null if field does not exist.\n * @deprecated December 2013\n */\nBlockly.Block.prototype.getTitleValue = function(name) {\n  console.log('Deprecated call to getTitleValue, use getFieldValue instead.');\n  return this.getFieldValue(name);\n};\n\n/**\n * Change the field value for a block (e.g. 'CHOOSE' or 'REMOVE').\n * @param {string} newValue Value to be the new field.\n * @param {string} name The name of the field.\n */\nBlockly.Block.prototype.setFieldValue = function(newValue, name) {\n  var field = this.getField_(name);\n  goog.asserts.assertObject(field, 'Field \"%s\" not found.', name);\n  field.setValue(newValue);\n};\n\n/**\n * Change the field value for a block (e.g. 'CHOOSE' or 'REMOVE').\n * @param {string} newValue Value to be the new field.\n * @param {string} name The name of the field.\n * @deprecated December 2013\n */\nBlockly.Block.prototype.setTitleValue = function(newValue, name) {\n  console.log('Deprecated call to setTitleValue, use setFieldValue instead.');\n  this.setFieldValue(newValue, name);\n};\n\n/**\n * Change the tooltip text for a block.\n * @param {string|!Element} newTip Text for tooltip or a parent element to\n *     link to for its tooltip.\n */\nBlockly.Block.prototype.setTooltip = function(newTip) {\n  this.tooltip = newTip;\n};\n\n/**\n * Set whether this block can chain onto the bottom of another block.\n * @param {boolean} newBoolean True if there can be a previous statement.\n * @param {string|Array.<string>|null} opt_check Statement type or list of\n *     statement types.  Null or undefined if any type could be connected.\n */\nBlockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) {\n  if (this.previousConnection) {\n    goog.asserts.assert(!this.previousConnection.targetConnection,\n        'Must disconnect previous statement before removing connection.');\n    this.previousConnection.dispose();\n    this.previousConnection = null;\n  }\n  if (newBoolean) {\n    goog.asserts.assert(!this.outputConnection,\n        'Remove output connection prior to adding previous connection.');\n    if (opt_check === undefined) {\n      opt_check = null;\n    }\n    this.previousConnection =\n        new Blockly.Connection(this, Blockly.PREVIOUS_STATEMENT);\n    this.previousConnection.setCheck(opt_check);\n  }\n  if (this.rendered) {\n    this.render();\n    this.bumpNeighbours_();\n  }\n};\n\n/**\n * Set whether another block can chain onto the bottom of this block.\n * @param {boolean} newBoolean True if there can be a next statement.\n * @param {string|Array.<string>|null} opt_check Statement type or list of\n *     statement types.  Null or undefined if any type could be connected.\n */\nBlockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) {\n  if (this.nextConnection) {\n    goog.asserts.assert(!this.nextConnection.targetConnection,\n        'Must disconnect next statement before removing connection.');\n    this.nextConnection.dispose();\n    this.nextConnection = null;\n  }\n  if (newBoolean) {\n    if (opt_check === undefined) {\n      opt_check = null;\n    }\n    this.nextConnection =\n        new Blockly.Connection(this, Blockly.NEXT_STATEMENT);\n    this.nextConnection.setCheck(opt_check);\n  }\n  if (this.rendered) {\n    this.render();\n    this.bumpNeighbours_();\n  }\n};\n\n/**\n * Set whether this block returns a value.\n * @param {boolean} newBoolean True if there is an output.\n * @param {string|Array.<string>|null} opt_check Returned type or list of\n *     returned types.  Null or undefined if any type could be returned\n *     (e.g. variable get).\n */\nBlockly.Block.prototype.setOutput = function(newBoolean, opt_check) {\n  if (this.outputConnection) {\n    goog.asserts.assert(!this.outputConnection.targetConnection,\n        'Must disconnect output value before removing connection.');\n    this.outputConnection.dispose();\n    this.outputConnection = null;\n  }\n  if (newBoolean) {\n    goog.asserts.assert(!this.previousConnection,\n        'Remove previous connection prior to adding output connection.');\n    if (opt_check === undefined) {\n      opt_check = null;\n    }\n    this.outputConnection =\n        new Blockly.Connection(this, Blockly.OUTPUT_VALUE);\n    this.outputConnection.setCheck(opt_check);\n  }\n  if (this.rendered) {\n    this.render();\n    this.bumpNeighbours_();\n  }\n};\n\n/**\n * Change the output type on a block.\n * @param {string|Array.<string>|null} check Returned type or list of\n *     returned types.  Null or undefined if any type could be returned\n *     (e.g. variable get).  It is fine if this is the same as the old type.\n * @throws {goog.asserts.AssertionError} if the block did not already have an\n *     output.\n */\nBlockly.Block.prototype.changeOutput = function(check) {\n  goog.asserts.assert(this.outputConnection,\n      'Only use changeOutput() on blocks that already have an output.');\n  this.outputConnection.setCheck(check);\n};\n\n/**\n * Set whether value inputs are arranged horizontally or vertically.\n * @param {boolean} newBoolean True if inputs are horizontal.\n */\nBlockly.Block.prototype.setInputsInline = function(newBoolean) {\n  this.inputsInline = newBoolean;\n  if (this.rendered) {\n    this.render();\n    this.bumpNeighbours_();\n    this.workspace.fireChangeEvent();\n  }\n};\n\n/**\n * Set whether the block is disabled or not.\n * @param {boolean} disabled True if disabled.\n */\nBlockly.Block.prototype.setDisabled = function(disabled) {\n  if (this.disabled == disabled) {\n    return;\n  }\n  this.disabled = disabled;\n  this.svg_.updateDisabled();\n  this.workspace.fireChangeEvent();\n};\n\n/**\n * Get whether the block is disabled or not due to parents.\n * The block's own disabled property is not considered.\n * @return {boolean} True if disabled.\n */\nBlockly.Block.prototype.getInheritedDisabled = function() {\n  var block = this;\n  while (true) {\n    block = block.getSurroundParent();\n    if (!block) {\n      // Ran off the top.\n      return false;\n    } else if (block.disabled) {\n      return true;\n    }\n  }\n};\n\n/**\n * Get whether the block is collapsed or not.\n * @return {boolean} True if collapsed.\n */\nBlockly.Block.prototype.isCollapsed = function() {\n  return this.collapsed_;\n};\n\n/**\n * Set whether the block is collapsed or not.\n * @param {boolean} collapsed True if collapsed.\n */\nBlockly.Block.prototype.setCollapsed = function(collapsed) {\n  if (this.collapsed_ == collapsed) {\n    return;\n  }\n  this.collapsed_ = collapsed;\n  var renderList = [];\n  // Show/hide the inputs.\n  for (var x = 0, input; input = this.inputList[x]; x++) {\n    renderList = renderList.concat(input.setVisible(!collapsed));\n  }\n\n  var COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT';\n  if (collapsed) {\n    var icons = this.getIcons();\n    for (var x = 0; x < icons.length; x++) {\n      icons[x].setVisible(false);\n    }\n    var text = this.toString(Blockly.COLLAPSE_CHARS);\n    this.appendDummyInput(COLLAPSED_INPUT_NAME).appendField(text);\n  } else {\n    this.removeInput(COLLAPSED_INPUT_NAME)\n  }\n\n  if (!renderList.length) {\n    // No child blocks, just render this block.\n    renderList[0] = this;\n  }\n  if (this.rendered) {\n    for (var x = 0, block; block = renderList[x]; x++) {\n      block.render();\n    }\n    this.bumpNeighbours_();\n  }\n};\n\n/**\n * Create a human-readable text representation of this block and any children.\n * @param {?number} opt_maxLength Truncate the string to this length.\n * @return {string} Text of block.\n */\nBlockly.Block.prototype.toString = function(opt_maxLength) {\n  var text = [];\n  for (var x = 0, input; input = this.inputList[x]; x++) {\n    for (var y = 0, field; field = input.fieldRow[y]; y++) {\n      text.push(field.getText());\n    }\n    if (input.connection) {\n      var child = input.connection.targetBlock();\n      if (child) {\n        text.push(child.toString());\n      } else {\n        text.push('?');\n      }\n    }\n  }\n  text = goog.string.trim(text.join(' ')) || '???';\n  if (opt_maxLength) {\n    // TODO: Improve truncation so that text from this block is given priority.\n    // TODO: Handle FieldImage better.\n    text = goog.string.truncate(text, opt_maxLength);\n  }\n  return text;\n}\n\n/**\n * Shortcut for appending a value input row.\n * @param {string} name Language-neutral identifier which may used to find this\n *     input again.  Should be unique to this block.\n * @return {!Blockly.Input} The input object created.\n */\nBlockly.Block.prototype.appendValueInput = function(name) {\n  return this.appendInput_(Blockly.INPUT_VALUE, name);\n};\n\n/**\n * Shortcut for appending a statement input row.\n * @param {string} name Language-neutral identifier which may used to find this\n *     input again.  Should be unique to this block.\n * @return {!Blockly.Input} The input object created.\n */\nBlockly.Block.prototype.appendStatementInput = function(name) {\n  return this.appendInput_(Blockly.NEXT_STATEMENT, name);\n};\n\n/**\n * Shortcut for appending a dummy input row.\n * @param {string} opt_name Language-neutral identifier which may used to find\n *     this input again.  Should be unique to this block.\n * @return {!Blockly.Input} The input object created.\n */\nBlockly.Block.prototype.appendDummyInput = function(opt_name) {\n  return this.appendInput_(Blockly.DUMMY_INPUT, opt_name || '');\n};\n\n/**\n * Interpolate a message string, creating fields and inputs.\n * @param {string} msg The message string to parse.  %1, %2, etc. are symbols\n *     for value inputs or for Fields, such as an instance of\n *     Blockly.FieldDropdown, which would be placed as a field in either the\n *     following value input or a dummy input.  The newline character forces\n *     the creation of an unnamed dummy input if any fields need placement.\n *     Note that '%10' would be interpreted as a reference to the tenth\n *     argument.  To show the first argument followed by a zero, use '%1 0'.\n *     (Spaces around tokens are stripped.)  To display a percentage sign\n *     followed by a number (e.g., \"%123\"), put that text in a\n *     Blockly.FieldLabel (as described below).\n * @param {!Array.<?string|number|Array.<string>|Blockly.Field>|number} var_args\n *     A series of tuples that each specify the value inputs to create.  Each\n *     tuple has at least two elements.  The first is its name; the second is\n *     its type, which can be any of:\n *     - A string (such as 'Number'), denoting the one type allowed in the\n *       corresponding socket.\n *     - An array of strings (such as ['Number', 'List']), denoting the\n *       different types allowed in the corresponding socket.\n *     - null, denoting that any type is allowed in the corresponding socket.\n *     - Blockly.Field, in which case that field instance, such as an\n *       instance of Blockly.FieldDropdown, appears (instead of a socket).\n *     If the type is any of the first three options (which are legal arguments\n *     to setCheck()), there should be a third element in the tuple, giving its\n *     alignment.\n *     The final parameter is not a tuple, but just an alignment for any\n *     trailing dummy inputs.  This last parameter is mandatory; there may be\n *     any number of tuples (though the number of tuples must match the symbols\n *     in msg).\n */\nBlockly.Block.prototype.interpolateMsg = function(msg, var_args) {\n  /**\n   * Add a field to this input.\n   * @this !Blockly.input\n   * @param {Blockly.Field|Array.<string|Blockly.Field>} field\n   *     This is either a Field or a tuple of a name and a Field.\n   */\n  function addFieldToInput(field) {\n    if (field instanceof Blockly.Field) {\n      this.appendField(field);\n    } else {\n      goog.asserts.assert(field instanceof Array);\n      this.appendField(field[1], field[0]);\n    }\n  }\n\n  // Validate the msg at the start and the dummy alignment at the end,\n  // and remove the latter.\n  goog.asserts.assertString(msg);\n  var dummyAlign = arguments[arguments.length - 1];\n  goog.asserts.assert(\n      dummyAlign === Blockly.ALIGN_LEFT ||\n      dummyAlign === Blockly.ALIGN_CENTRE ||\n      dummyAlign === Blockly.ALIGN_RIGHT,\n      'Illegal final argument \"%d\" is not an alignment.', dummyAlign);\n  arguments.length = arguments.length - 1;\n\n  var tokens = msg.split(this.interpolateMsg.SPLIT_REGEX_);\n  var fields = [];\n  for (var i = 0; i < tokens.length; i += 2) {\n    var text = goog.string.trim(tokens[i]);\n    var input = undefined;\n    if (text) {\n      fields.push(new Blockly.FieldLabel(text));\n    }\n    var symbol = tokens[i + 1];\n    if (symbol && symbol.charAt(0) == '%') {\n      // Numeric field.\n      var number = parseInt(symbol.substring(1), 10);\n      var tuple = arguments[number];\n      goog.asserts.assertArray(tuple,\n          'Message symbol \"%s\" is out of range.', symbol);\n      goog.asserts.assertArray(tuple,\n          'Argument \"%s\" is not a tuple.', symbol);\n      if (tuple[1] instanceof Blockly.Field) {\n        fields.push([tuple[0], tuple[1]]);\n      } else {\n        input = this.appendValueInput(tuple[0])\n            .setCheck(tuple[1])\n            .setAlign(tuple[2]);\n      }\n      arguments[number] = null;  // Inputs may not be reused.\n    } else if (symbol == '\\n' && fields.length) {\n      // Create a dummy input.\n      input = this.appendDummyInput();\n    }\n    // If we just added an input, hang any pending fields on it.\n    if (input && fields.length) {\n      fields.forEach(addFieldToInput, input);\n      fields = [];\n    }\n  }\n  // If any fields remain, create a trailing dummy input.\n  if (fields.length) {\n    var input = this.appendDummyInput()\n        .setAlign(dummyAlign);\n    fields.forEach(addFieldToInput, input);\n  }\n\n  // Verify that all inputs were used.\n  for (var i = 1; i < arguments.length - 1; i++) {\n    goog.asserts.assert(arguments[i] === null,\n        'Input \"%%s\" not used in message: \"%s\"', i, msg);\n  }\n  // Make the inputs inline unless there is only one input and\n  // no text follows it.\n  this.setInputsInline(!msg.match(this.interpolateMsg.INLINE_REGEX_));\n};\n\nBlockly.Block.prototype.interpolateMsg.SPLIT_REGEX_ = /(%\\d+|\\n)/;\nBlockly.Block.prototype.interpolateMsg.INLINE_REGEX_ = /%1\\s*$/;\n\n\n/**\n * Add a value input, statement input or local variable to this block.\n * @param {number} type Either Blockly.INPUT_VALUE or Blockly.NEXT_STATEMENT or\n *     Blockly.DUMMY_INPUT.\n * @param {string} name Language-neutral identifier which may used to find this\n *     input again.  Should be unique to this block.\n * @return {!Blockly.Input} The input object created.\n * @private\n */\nBlockly.Block.prototype.appendInput_ = function(type, name) {\n  var connection = null;\n  if (type == Blockly.INPUT_VALUE || type == Blockly.NEXT_STATEMENT) {\n    connection = new Blockly.Connection(this, type);\n  }\n  var input = new Blockly.Input(type, name, this, connection);\n  // Append input to list.\n  this.inputList.push(input);\n  if (this.rendered) {\n    this.render();\n    // Adding an input will cause the block to change shape.\n    this.bumpNeighbours_();\n  }\n  return input;\n};\n\n/**\n * Move a named input to a different location on this block.\n * @param {string} name The name of the input to move.\n * @param {?string} refName Name of input that should be after the moved input,\n *   or null to be the input at the end.\n */\nBlockly.Block.prototype.moveInputBefore = function(name, refName) {\n  if (name == refName) {\n    return;\n  }\n  // Find both inputs.\n  var inputIndex = -1;\n  var refIndex = refName ? -1 : this.inputList.length;\n  for (var x = 0, input; input = this.inputList[x]; x++) {\n    if (input.name == name) {\n      inputIndex = x;\n      if (refIndex != -1) {\n        break;\n      }\n    } else if (refName && input.name == refName) {\n      refIndex = x;\n      if (inputIndex != -1) {\n        break;\n      }\n    }\n  }\n  goog.asserts.assert(inputIndex != -1, 'Named input \"%s\" not found.', name);\n  goog.asserts.assert(refIndex != -1, 'Reference input \"%s\" not found.',\n                      refName);\n  this.moveNumberedInputBefore(inputIndex, refIndex);\n};\n\n/**\n * Move a numbered input to a different location on this block.\n * @param {number} inputIndex Index of the input to move.\n * @param {number} refIndex Index of input that should be after the moved input.\n */\nBlockly.Block.prototype.moveNumberedInputBefore = function(\n    inputIndex, refIndex) {\n  // Validate arguments.\n  goog.asserts.assert(inputIndex != refIndex, 'Can\\'t move input to itself.');\n  goog.asserts.assert(inputIndex < this.inputList.length,\n                      'Input index ' + inputIndex + ' out of bounds.')\n  goog.asserts.assert(refIndex <= this.inputList.length,\n                      'Reference input ' + refIndex + ' out of bounds.')\n  // Remove input.\n  var input = this.inputList[inputIndex];\n  this.inputList.splice(inputIndex, 1);\n  if (inputIndex < refIndex) {\n    refIndex--;\n  }\n  // Reinsert input.\n  this.inputList.splice(refIndex, 0, input);\n  if (this.rendered) {\n    this.render();\n    // Moving an input will cause the block to change shape.\n    this.bumpNeighbours_();\n  }\n};\n\n/**\n * Remove an input from this block.\n * @param {string} name The name of the input.\n * @param {boolean} opt_quiet True to prevent error if input is not present.\n * @throws {goog.asserts.AssertionError} if the input is not present and\n *     opt_quiet is not true.\n */\nBlockly.Block.prototype.removeInput = function(name, opt_quiet) {\n  for (var x = 0, input; input = this.inputList[x]; x++) {\n    if (input.name == name) {\n      if (input.connection && input.connection.targetConnection) {\n        // Disconnect any attached block.\n        input.connection.targetBlock().setParent(null);\n      }\n      input.dispose();\n      this.inputList.splice(x, 1);\n      if (this.rendered) {\n        this.render();\n        // Removing an input will cause the block to change shape.\n        this.bumpNeighbours_();\n      }\n      return;\n    }\n  }\n  if (!opt_quiet) {\n    goog.asserts.fail('Input \"%s\" not found.', name);\n  }\n};\n\n/**\n * Fetches the named input object.\n * @param {string} name The name of the input.\n * @return {Object} The input object, or null of the input does not exist.\n */\nBlockly.Block.prototype.getInput = function(name) {\n  for (var x = 0, input; input = this.inputList[x]; x++) {\n    if (input.name == name) {\n      return input;\n    }\n  }\n  // This input does not exist.\n  return null;\n};\n\n/**\n * Fetches the block attached to the named input.\n * @param {string} name The name of the input.\n * @return {Blockly.Block} The attached value block, or null if the input is\n *     either disconnected or if the input does not exist.\n */\nBlockly.Block.prototype.getInputTargetBlock = function(name) {\n  var input = this.getInput(name);\n  return input && input.connection && input.connection.targetBlock();\n};\n\n/**\n * Give this block a mutator dialog.\n * @param {Blockly.Mutator} mutator A mutator dialog instance or null to remove.\n */\nBlockly.Block.prototype.setMutator = function(mutator) {\n  if (this.mutator && this.mutator !== mutator) {\n    this.mutator.dispose();\n  }\n  if (mutator) {\n    mutator.block_ = this;\n    this.mutator = mutator;\n    if (this.svg_) {\n      mutator.createIcon();\n    }\n  }\n};\n\n/**\n * Returns the comment on this block (or '' if none).\n * @return {string} Block's comment.\n */\nBlockly.Block.prototype.getCommentText = function() {\n  if (this.comment) {\n    var comment = this.comment.getText();\n    // Trim off trailing whitespace.\n    return comment.replace(/\\s+$/, '').replace(/ +\\n/g, '\\n');\n  }\n  return '';\n};\n\n/**\n * Set this block's comment text.\n * @param {?string} text The text, or null to delete.\n */\nBlockly.Block.prototype.setCommentText = function(text) {\n  var changedState = false;\n  if (goog.isString(text)) {\n    if (!this.comment) {\n      this.comment = new Blockly.Comment(this);\n      changedState = true;\n    }\n    this.comment.setText(/** @type {string} */ (text));\n  } else {\n    if (this.comment) {\n      this.comment.dispose();\n      changedState = true;\n    }\n  }\n  if (this.rendered) {\n    this.render();\n    if (changedState) {\n      // Adding or removing a comment icon will cause the block to change shape.\n      this.bumpNeighbours_();\n    }\n  }\n};\n\n/**\n * Set this block's warning text.\n * @param {?string} text The text, or null to delete.\n */\nBlockly.Block.prototype.setWarningText = function(text) {\n  if (this.isInFlyout) {\n    text = null;\n  }\n  var changedState = false;\n  if (goog.isString(text)) {\n    if (!this.warning) {\n      this.warning = new Blockly.Warning(this);\n      changedState = true;\n    }\n    this.warning.setText(/** @type {string} */ (text));\n  } else {\n    if (this.warning) {\n      this.warning.dispose();\n      changedState = true;\n    }\n  }\n  if (changedState && this.rendered) {\n    this.render();\n    // Adding or removing a warning icon will cause the block to change shape.\n    this.bumpNeighbours_();\n  }\n};\n\n/**\n * Render the block.\n * Lays out and reflows a block based on its contents and settings.\n */\nBlockly.Block.prototype.render = function() {\n  goog.asserts.assertObject(this.svg_,\n      'Uninitialized block cannot be rendered.  Call block.initSvg()');\n  this.svg_.render();\n  if (Blockly.Realtime.isEnabled() && !Blockly.Realtime.withinSync) {\n    Blockly.Realtime.blockChanged(this);\n  }\n};\n\n/**\n * Set stalker block. Stalker block is only for BlockMenu block.\n * It provide graphical effect when adding blocks on block menu.\n * @param {Blockly.Block} targetBlock\n */\nBlockly.Block.prototype.setStalkerBlock = function(targetBlock) {\n  if (!this.isInBlockMenu)\n    return;\n  this.stalkerBlock = targetBlock;\n};\n"
  },
  {
    "path": "extern/blockly/core/block_menu.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing a UI block menu.\n * @author kyumin92@gmail.com\n */\n'use strict';\n\ngoog.provide('Blockly.BlockMenu');\n\ngoog.require('Blockly.Workspace');\n\n\n/**\n * Class for UI Block Menu\n * @param {!Element} element HTML div for block menu.\n * @constructor\n */\nBlockly.BlockMenu = function(element) {\n\n  /**\n   * List of background buttons that lurk behind each block to catch clicks\n   * landing in the blocks' lakes and bays.\n   * @type {!Array.<!Element>}\n   * @private\n   */\n  this.buttons_ = [];\n\n  /**\n   * List of split line.\n   */\n  this.splitters_ = [];\n\n  /**\n   * List of buttons.\n   */\n  this.buttons_ = [];\n\n  /**\n   * List of event listeners.\n   * @type {!Array.<!Array>}\n   * @private\n   */\n  this.listeners_ = [];\n\n  this.isViewOnly = false;\n\n  this.isCenterAlign = false;\n\n  this.targetWorkspace = Blockly.mainWorkspace;\n\n  this.bannedClass = [];\n\n  this.view_ = element;\n  this.menuView_ = Blockly.createSvgElement('svg', {\n    'xmlns': 'http://www.w3.org/2000/svg',\n    'xmlns:html': 'http://www.w3.org/1999/xhtml',\n    'xmlns:xlink': 'http://www.w3.org/1999/xlink',\n    'version': '1.1',\n    'class': 'blocklySvg'\n  }, this.view_);\n  var blockMenu = this;\n  this.workspace_ = new Blockly.Workspace(\n      function() {return blockMenu.getMetrics_();},\n      function(ratio) {return blockMenu.setMetrics_(ratio);});\n  this.menuView_.appendChild(this.workspace_.createDom());\n  this.scrollbar_ = new Blockly.Scrollbar(this.workspace_, false, false);\n  this.onResizeWrapper_ = Blockly.bindEvent_(window,\n      goog.events.EventType.RESIZE, this, this.syncViewSize_);\n\n  Blockly.bindEvent_(window, 'resize', this, this.updateSplitters);\n\n  var width = Blockly.BlockMenu.BTN_WIDTH;\n  var height = Blockly.BlockMenu.BTN_HEIGHT;\n  var round = Blockly.BlockMenu.BTN_ROUND;\n  var paths = [];\n  paths.push('m ' + round + ',0');\n  paths.push('h', width - 2 * round);\n  paths.push('a', round + ',' + round + ' 0, 0,1 ' + round + ',' + round);\n  paths.push('v', height - 2 * round);\n  paths.push('a', round + ',' + round + ' 0, 0,1 -' + round + ',' + round);\n  paths.push('h', - width + 2 * round);\n  paths.push('a', round + ',' + round + ' 0, 0,1 -' + round + ',-' + round);\n  paths.push('v', - height + 2 * round);\n  paths.push('a', round + ',' + round + ' 0, 0,1 ' + round + ',-' + round);\n  paths.push('z');\n  this.btnPath = paths.join(' ');\n};\n\nBlockly.BlockMenu.BTN_HEIGHT = 30;\nBlockly.BlockMenu.BTN_WIDTH = 140;\nBlockly.BlockMenu.BTN_ROUND = 6;\nBlockly.BlockMenu.BTN_FONT_SIZE = '9pt';\n\n/**\n * how and populate the blockmenu.\n * @param {!Array|string} xmlList List of blocks to show.\n *     Variables and procedures have a custom set of blocks.\n */\nBlockly.BlockMenu.prototype.show = function(xmlList) {\n  this.hide();\n  var margin = 0;\n  this.menuView_.style.display = 'block';\n\n  // Create the blocks to be shown in this blockMenu.\n  var blocks = [];\n  var gaps = [];\n  if (xmlList == Blockly.Variables.NAME_TYPE) {\n    // Special category for variables.\n    Blockly.Variables.blockMenuCategory(blocks, gaps, margin,\n        /** @type {!Blockly.Workspace} */ (this.workspace_));\n  } else if (xmlList == Blockly.Procedures.NAME_TYPE) {\n    // Special category for procedures.\n    Blockly.Procedures.blockMenuCategory(blocks, gaps, margin,\n        /** @type {!Blockly.Workspace} */ (this.workspace_));\n  } else {\n    for (var i = 0, xml; xml = xmlList[i]; i++) {\n      if (xml.tagName && xml.tagName.toUpperCase() == 'BLOCK') {\n        var block = Blockly.Xml.domToBlock(\n            /** @type {!Blockly.Workspace} */ (this.workspace_), xml);\n        block.isInFlyout = true;\n        blocks.push(block);\n        gaps.push(margin);\n      } else if (xml.tagName && xml.tagName.toUpperCase() == 'SPLITTER') {\n        blocks.push('splitter');\n        gaps.push(0);\n      } else if (xml.tagName && xml.tagName.toUpperCase() == 'BTN') {\n        blocks.push(xml);\n        gaps.push(margin);\n      }\n    }\n  }\n\n  // Lay out the blocks vertically.\n  var cursorY = 10;\n  for (var i = 0, block; block = blocks[i]; i++) {\n    if (block == 'splitter') {\n      var previousBlock = blocks[i - 1];\n      var y = previousBlock.outputConnection ? cursorY : cursorY + 5;\n      var splitter = this.createSplitter(64, y,\n        this.view_.style.width.substr(0,3));\n      this.workspace_.svgBlockCanvas_.appendChild(splitter);\n      this.splitters_.push(splitter);\n      cursorY += 10;\n      continue;\n    } else if (block.tagName && block.tagName.toUpperCase() == 'BTN') {\n      var height = Number(block.getAttribute('height'));\n      var button = Blockly.createSvgElement('g', {\n                      'transform': 'translate(' + (10) + ', ' + cursorY + ')',\n                      'class': 'blocklyBlockMenuBtn'\n                    }, null);\n      if (height) {\n        var image = Blockly.createSvgElement('image',\n            {'x': 0, 'y': 0,\n            'width': block.getAttribute('width') + 'px',\n            'height': height + 'px'\n            }, button);\n        image.setAttributeNS(\"http://www.w3.org/1999/xlink\",\n          'xlink:href', block.getAttribute('src'));\n        var highlightImage = Blockly.createSvgElement('image',\n            {'x': 0, 'y': 0,\n            'width': block.getAttribute('width') + 'px',\n            'height': height + 'px',\n            'class': 'blocklyBlockMenuBtnHighlight'\n            }, button);\n        highlightImage.setAttributeNS(\"http://www.w3.org/1999/xlink\",\n          'xlink:href', block.getAttribute('highlightSrc'));\n        cursorY += height + 15;\n      } else {\n        var text = block.getAttribute('text');\n        var width = Blockly.BlockMenu.BTN_WIDTH;\n        var height = Blockly.BlockMenu.BTN_HEIGHT;\n        Blockly.createSvgElement('path', {\n          'transform': 'translate(1,1)', 'd': this.btnPath, 'fill': '#aaa'\n        }, button);\n        Blockly.createSvgElement('path', {\n          'd': this.btnPath, 'fill': '#eee',\n          'class': 'blocklyBlockMenuBtnPath'\n        }, button);\n        var textElement = Blockly.createSvgElement('text', {\n          'x': width/2 + 'px', 'y': (height/2 + 4) + 'px',\n          'font-family': 'ng',\n          'font-size': Blockly.BlockMenu.BTN_FONT_SIZE,\n          'text-anchor': 'middle'\n          }, button);\n        var textNode = document.createTextNode(eval(text));\n        textElement.appendChild(textNode);\n        cursorY += height + 13;\n      }\n      var onclickFunc = block.getAttribute('onclick');\n      if (onclickFunc && !this.isViewOnly) {\n          button.onclick = (function (func){\n            return function () {eval(func)};\n          })(onclickFunc);\n      }\n      this.workspace_.svgBlockCanvas_.appendChild(button);\n      this.buttons_.push(button);\n      continue;\n    } else {\n      var allBlocks = block.getDescendants();\n      for (var j = 0, child; child = allBlocks[j]; j++) {\n        // Mark blocks as being inside a blockMenu.  This is used to detect and\n        // prevent the closure of the blockMenu if the user right-clicks on such a\n        // block.\n        child.isInFlyout = true;\n        // There is no good way to handle comment bubbles inside the blockMenu.\n        // Blocks shouldn't come with predefined comments, but someone will\n        // try this, I'm sure.  Kill the comment.\n        Blockly.Comment && child.setCommentText(null);\n      }\n      block.render();\n      var root = block.getSvgRoot();\n      var blockHW = block.getHeightWidth();\n      var x = 10;\n      if (this.isCenterAlign) {\n        x = 200 - blockHW.width/2;\n      } else if (block.outputConnection) {\n        x += blockHW.height/2;\n        var bType = block.type;\n          if (bType == 'get_variable' || bType == 'get_canvas_input_value'\n             || bType == 'value_of_index_from_list' || bType == 'length_of_list') {\n              cursorY += 12;\n          }\n        if (block.outputConnection.check_[0].toUpperCase() == \"PARAM\") {\n          x += 9;\n          cursorY += 4;\n        }\n      } else if (!block.previousConnection && block.nextConnection){\n        x += 10;\n        cursorY += 10;\n      } else {\n        cursorY += 7;\n      }\n      block.moveBy(x, cursorY);\n      if (!block.previousConnection && !block.nextConnection){\n        cursorY += 10;\n      }\n\n      cursorY += blockHW.height + gaps[i];\n\n      if (block.isAddable() && !this.isViewOnly) {\n        this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null,\n            this.blockMouseDown_(block)));\n      }\n    }\n  }\n  this.width_ = 0;\n  //if (block && block.svg_ && block.svg_.svgGroup_)\n      //console.log(block.svg_.svgGroup_);\n\n  this.reflow();\n\n  //this.filterForCapacity_();\n\n  // Fire a resize event to update the blockMenu's scrollbar.\n  Blockly.fireUiEvent(window, 'resize');\n  this.reflowWrapper_ = Blockly.bindEvent_(this.workspace_.getCanvas(),\n      'blocklyWorkspaceChange', this, this.reflow);\n  this.workspace_.fireChangeEvent();\n  return cursorY;\n};\n\nBlockly.BlockMenu.prototype.banClass = function(className) {\n    var index = this.bannedClass.indexOf(className);\n    if (index < 0)\n        this.bannedClass.push(className);\n}\n\nBlockly.BlockMenu.prototype.unbanClass = function(className) {\n    var index = this.bannedClass.indexOf(className);\n    if (index > -1)\n        this.bannedClass.splice(index, 1);\n}\n\nBlockly.BlockMenu.prototype.checkBanClass = function(blockInfo) {\n    var isNotFor = blockInfo.isNotFor;\n    for (var i in this.bannedClass) {\n        if (isNotFor && isNotFor.indexOf(this.bannedClass[i]) > -1)\n            return true;\n    }\n    return false;\n}\n\n\n/**\n * Show category and populate the blockmenu.\n * @param {object} categoryObject to show.\n */\nBlockly.BlockMenu.prototype.showCategory = function(categoryObject) {\n  this.hide();\n  var margin = 0;\n  this.menuView_.style.display = 'block';\n\n  var objectType = Entry.playground.object.objectType;\n\n  // Create the blocks to be shown in this blockMenu.\n  var blocks = [];\n  var blockNames = categoryObject.blocks;\n  var gaps = [];\n  var blockClass = \"\";\n  for (var i in blockNames) {\n    var blockInfo = EntryStatic.blockInfo[blockNames[i]];\n    if (this.checkBanClass(blockInfo))\n      continue;\n    if (blockClass && blockClass != blockInfo.class) {\n      blocks.push('splitter');\n      gaps.push(0);\n    }\n\n    var xmlText = blockInfo.xml;\n    if (blockInfo.xmls)\n      var xmls = blockInfo.xmls;\n    else\n      var xmls = [blockInfo.xml];\n    for (var j in xmls) {\n      xmlText = xmls[j];\n      var xml = jQuery.parseXML(xmlText).childNodes[0];\n      if (xml.tagName && xml.tagName.toUpperCase() == 'BTN') {\n          blocks.push(xml);\n      } else {\n          var block = Blockly.Xml.domToBlock(\n              /** @type {!Blockly.Workspace} */ (this.workspace_), xml);\n          block.isInFlyout = true;\n          blocks.push(block);\n      }\n      gaps.push(margin);\n    }\n    blockClass = blockInfo.class;\n  }\n\n  // Lay out the blocks vertically.\n  var cursorY = 10;\n  for (var i = 0, block; block = blocks[i]; i++) {\n    if (block == 'splitter') {\n      var previousBlock = blocks[i - 1];\n      var y = previousBlock.outputConnection ? cursorY : cursorY + 5;\n      var splitter = this.createSplitter(64, y,\n        this.view_.style.width.substr(0,3));\n      this.workspace_.svgBlockCanvas_.appendChild(splitter);\n      this.splitters_.push(splitter);\n      cursorY += 10;\n      continue;\n    } else if (block.tagName && block.tagName.toUpperCase() == 'BTN') {\n      var height = Number(block.getAttribute('height'));\n      var button = Blockly.createSvgElement('g', {\n                      'transform': 'translate(' + (10) + ', ' + cursorY + ')',\n                      'class': 'blocklyBlockMenuBtn'\n                    }, null);\n      if (height) {\n        var image = Blockly.createSvgElement('image',\n            {'x': 0, 'y': 0,\n            'width': block.getAttribute('width') + 'px',\n            'height': height + 'px'\n            }, button);\n        image.setAttributeNS(\"http://www.w3.org/1999/xlink\",\n          'xlink:href', block.getAttribute('src'));\n        var highlightImage = Blockly.createSvgElement('image',\n            {'x': 0, 'y': 0,\n            'width': block.getAttribute('width') + 'px',\n            'height': height + 'px',\n            'class': 'blocklyBlockMenuBtnHighlight'\n            }, button);\n        highlightImage.setAttributeNS(\"http://www.w3.org/1999/xlink\",\n          'xlink:href', block.getAttribute('highlightSrc'));\n        cursorY += height + 10;\n      } else {\n        var text = block.getAttribute('text');\n        var width = Blockly.BlockMenu.BTN_WIDTH;\n        var height = Blockly.BlockMenu.BTN_HEIGHT;\n        Blockly.createSvgElement('path', {\n          'transform': 'translate(1,1)', 'd': this.btnPath, 'fill': '#aaa'\n        }, button);\n        Blockly.createSvgElement('path', {\n          'd': this.btnPath, 'fill': '#eee',\n          'class': 'blocklyBlockMenuBtnPath'\n        }, button);\n        var textElement = Blockly.createSvgElement('text', {\n          'x': width/2 + 'px', 'y': (height/2 + 4) + 'px',\n          'font-family': 'ng',\n          'font-size': Blockly.BlockMenu.BTN_FONT_SIZE,\n          'text-anchor': 'middle'\n          }, button);\n        var textNode = document.createTextNode(eval(text));\n        textElement.appendChild(textNode);\n        cursorY += height + 13;\n      }\n      var onclickFunc = block.getAttribute('onclick');\n      if (onclickFunc) {\n          button.onclick = (function (func){\n            return function () {eval(func)};\n          })(onclickFunc);\n      }\n      this.workspace_.svgBlockCanvas_.appendChild(button);\n      this.buttons_.push(button);\n      continue;\n    } else {\n      var allBlocks = block.getDescendants();\n      for (var j = 0, child; child = allBlocks[j]; j++) {\n        // Mark blocks as being inside a blockMenu.  This is used to detect and\n        // prevent the closure of the blockMenu if the user right-clicks on such a\n        // block.\n        child.isInFlyout = true;\n        // There is no good way to handle comment bubbles inside the blockMenu.\n        // Blocks shouldn't come with predefined comments, but someone will\n        // try this, I'm sure.  Kill the comment.\n        Blockly.Comment && child.setCommentText(null);\n      }\n      block.render();\n      var root = block.getSvgRoot();\n      var blockHW = block.getHeightWidth();\n      var x = 10;\n      if (this.isCenterAlign) {\n        x = 200 - blockHW.width/2;\n      } else if (block.outputConnection) {\n        x += blockHW.height/2;\n        var bType = block.type;\n          if (bType == 'get_variable' || bType == 'get_canvas_input_value'\n             || bType == 'value_of_index_from_list' || bType == 'length_of_list') {\n              cursorY += 12;\n          }\n        if (block.outputConnection.check_[0].toUpperCase() == \"PARAM\") {\n          x += 9;\n          cursorY += 4;\n        }\n      } else if (!block.previousConnection && block.nextConnection){\n        x += 10;\n        cursorY += 10;\n      } else {\n        cursorY += 7;\n      }\n      block.moveBy(x, cursorY);\n      if (!block.previousConnection && !block.nextConnection){\n        cursorY += 10;\n      }\n\n      cursorY += blockHW.height + gaps[i];\n\n      if (block.isAddable() && !this.isViewOnly) {\n        this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null,\n            this.blockMouseDown_(block)));\n      }\n    }\n  }\n  this.width_ = 0;\n  //if (block && block.svg_ && block.svg_.svgGroup_)\n      //console.log(block.svg_.svgGroup_);\n\n  this.reflow();\n\n  //this.filterForCapacity_();\n\n  // Fire a resize event to update the blockMenu's scrollbar.\n  Blockly.fireUiEvent(window, 'resize');\n  this.reflowWrapper_ = Blockly.bindEvent_(this.workspace_.getCanvas(),\n      'blocklyWorkspaceChange', this, this.reflow);\n  this.workspace_.fireChangeEvent();\n  return cursorY;\n};\n\n/**\n * Hide and empty the blockMenu.\n */\nBlockly.BlockMenu.prototype.hide = function() {\n  // Delete all the event listeners.\n  for (var x = 0, listen; listen = this.listeners_[x]; x++) {\n    Blockly.unbindEvent_(listen);\n  }\n  this.listeners_.splice(0);\n  if (this.reflowWrapper_) {\n    Blockly.unbindEvent_(this.reflowWrapper_);\n    this.reflowWrapper_ = null;\n  }\n  // Delete all the blocks.\n  var blocks = this.workspace_.getTopBlocks(false);\n  for (var x = 0, block; block = blocks[x]; x++) {\n    if (block.workspace == this.workspace_) {\n      block.dispose(false, false);\n    }\n  }\n  for (var i in this.splitters_) {\n    goog.dom.removeNode(this.splitters_[i]);\n  }\n  this.splitters_ = [];\n  for (var i in this.buttons_) {\n    goog.dom.removeNode(this.buttons_[i]);\n  }\n  this.buttons_ = [];\n  // Delete all the background buttons.\n  //for (var x = 0, rect; rect = this.buttons_[x]; x++) {\n    //goog.dom.removeNode(rect);\n  //}\n  //this.buttons_.splice(0);\n};\n\n/**\n * Hide and empty the blockMenu.\n */\nBlockly.BlockMenu.prototype.hide = function() {\n  // Delete all the event listeners.\n  for (var x = 0, listen; listen = this.listeners_[x]; x++) {\n    Blockly.unbindEvent_(listen);\n  }\n  this.listeners_.splice(0);\n  if (this.reflowWrapper_) {\n    Blockly.unbindEvent_(this.reflowWrapper_);\n    this.reflowWrapper_ = null;\n  }\n  // Delete all the blocks.\n  var blocks = this.workspace_.getTopBlocks(false);\n  for (var x = 0, block; block = blocks[x]; x++) {\n    if (block.workspace == this.workspace_) {\n      block.dispose(false, false);\n    }\n  }\n  for (var i in this.splitters_) {\n    goog.dom.removeNode(this.splitters_[i]);\n  }\n  this.splitters_ = [];\n  for (var i in this.buttons_) {\n    goog.dom.removeNode(this.buttons_[i]);\n  }\n  this.buttons_ = [];\n  // Delete all the background buttons.\n  //for (var x = 0, rect; rect = this.buttons_[x]; x++) {\n    //goog.dom.removeNode(rect);\n  //}\n  //this.buttons_.splice(0);\n};\n\n/**\n */\nBlockly.BlockMenu.prototype.createSplitter = function(x, y, width) {\n  var width = Number(width) - 119;\n  var svgGroup = Blockly.createSvgElement('g', {\n    'transform': 'translate(' + (x-34) + ', ' + y + ')'\n  }, null);\n  Blockly.createSvgElement('path',\n      {'stroke': '#b5b5b5', 'transform': 'translate(0, 1)',\n      'd': 'M0 0 l' + width + ' 0'},\n      svgGroup);\n  return svgGroup;\n};\n\nBlockly.BlockMenu.prototype.updateSplitters = function() {\n  var width = Number(this.view_.style.width.substr(0,3)) - 119 + 64;\n  for (var i in this.splitters_) {\n    var splitter = this.splitters_[i];\n    splitter.childNodes[0].setAttribute('d', 'M0 0 l' + width + ' 0');\n  }\n}\n\n/**\n * Handle a mouse-down on an SVG block in a non-closing blockMenu.\n * @param {!Blockly.Block} originBlock The blockMenu block to copy.\n * @return {!Function} Function to call when block is clicked.\n * @private\n */\nBlockly.BlockMenu.prototype.blockMouseDown_ = function(block) {\n  var blockMenu = this;\n  return function(e) {\n    Blockly.terminateDrag_();\n    Blockly.hideChaff();\n    if (Blockly.isRightButton(e)) {\n      // Right-click.\n      if (Blockly.ContextMenu) {\n        block.showContextMenu_(Blockly.mouseToSvg(e));\n      }\n    } else {\n      // Left-click (or middle click)\n      Blockly.removeAllRanges();\n      Blockly.setCursorHand_(true);\n      // Record the current mouse position.\n      Blockly.BlockMenu.startDownEvent_ = e;\n      Blockly.BlockMenu.startBlock_ = block;\n      Blockly.BlockMenu.startblockMenu_ = blockMenu;\n      Blockly.BlockMenu.onMouseUpWrapper_ = Blockly.bindEvent_(document,\n          'mouseup', this, Blockly.terminateDrag_);\n      Blockly.BlockMenu.onMouseMoveWrapper_ = Blockly.bindEvent_(document,\n          'mousemove', this, blockMenu.onMouseMove_);\n    }\n    // This event has been handled.  No need to bubble up to the document.\n    e.stopPropagation();\n  };\n};\n\n/**\n * Mouse button is down on a block in a non-closing blockMenu.  Create the block\n * if the mouse moves beyond a small radius.  This allows one to play with\n * fields without instantiating blocks that instantly self-destruct.\n * @param {!Event} e Mouse move event.\n * @private\n */\nBlockly.BlockMenu.prototype.onMouseMove_ = function(e) {\n  if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 &&\n      e.button == 0) {\n    /* HACK:\n     Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove events\n     on certain touch actions. Ignore events with these signatures.\n     This may result in a one-pixel blind spot in other browsers,\n     but this shouldn't be noticable. */\n    e.stopPropagation();\n    return;\n  }\n  Blockly.removeAllRanges();\n  var dx = e.clientX - Blockly.BlockMenu.startDownEvent_.clientX;\n  var dy = e.clientY - Blockly.BlockMenu.startDownEvent_.clientY;\n  // Still dragging within the sticky DRAG_RADIUS.\n  var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));\n  if (dr > Blockly.DRAG_RADIUS) {\n    // Create the block.\n    Blockly.BlockMenu.startblockMenu_.createBlockFunc_(Blockly.BlockMenu.startBlock_)\n        (Blockly.BlockMenu.startDownEvent_);\n  }\n};\n\n/**\n * Create a copy of this block on the workspace.\n * @param {!Blockly.Block} originBlock The blockMenu block to copy.\n * @return {!Function} Function to call when block is clicked.\n * @private\n */\nBlockly.BlockMenu.prototype.createBlockFunc_ = function(originBlock) {\n  var blockMenu = this;\n  return function(e) {\n    Blockly.scrollBarOff = true;\n    if (Blockly.isRightButton(e)) {\n      // Right-click.  Don't create a block, let the context menu show.\n      return;\n    }\n    if (originBlock.disabled) {\n      // Beyond capacity.\n      return;\n    }\n\n    // Create the new block by cloning the block in the blockMenu (via XML).\n    if (typeof(Entry) == \"object\") {\n        Entry.dispatchEvent(\"entryBlocklyChanged\");\n    }\n    var xml = Blockly.Xml.blockToDom_(originBlock);\n    var block = Blockly.Xml.domToBlock(blockMenu.workspace_, xml);\n    block.isInBlockMenu = true;\n    // Place it in the same spot as the blockMenu copy.\n    var svgRootOld = originBlock.getSvgRoot();\n    if (!svgRootOld) {\n      throw 'originBlock is not rendered.';\n    }\n    var xyOld = Blockly.getSvgXY_(svgRootOld);\n    var svgRootNew = block.getSvgRoot();\n    if (!svgRootNew) {\n      throw 'block is not rendered.';\n    }\n    var xyNew = Blockly.getSvgXY_(svgRootNew);\n    block.setDragging_(true);\n    block.svg_.addSelect();\n    block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y);\n    block.startDragX = xyOld.x - xyNew.x;\n    block.startDragY = xyOld.y - xyNew.y;\n\n    var workspaceBlock = Blockly.Xml.domToBlock(blockMenu.targetWorkspace, xml);\n\n    var svgRootNewWorkspace = workspaceBlock.getSvgRoot();\n    if (!svgRootNewWorkspace) {\n      throw 'block is not rendered.';\n    }\n    var xyNewWorkspace = Blockly.getSvgXY_(svgRootNewWorkspace);\n\n    var workspace = Blockly.mainWorkspace;\n    var borderWidth = $(workspace.svgGroup_.parentNode.parentNode).css('border-width');\n    borderWidth = borderWidth.substring(0, borderWidth.length-2);\n    var blockMenuWorkspace = $(workspace.blockMenu.view_).position();\n    var playgroundBlockly = $(workspace.svgGroup_.parentNode.parentNode).eq(0).position();\n    var stalkerX = xyOld.x - xyNewWorkspace.x\n                   - playgroundBlockly.left\n                   + blockMenuWorkspace.left;\n    var stalkerY = xyOld.y - xyNewWorkspace.y + blockMenuWorkspace.top\n        - playgroundBlockly.top - borderWidth;\n    workspaceBlock.moveBy(stalkerX, stalkerY);\n\n    // Start a dragging operation on the new block.\n    workspaceBlock.isInBlockMenu = true;\n    workspaceBlock.setStalkerBlock(block);\n    block.setStalkerBlock(workspaceBlock);\n    workspaceBlock.onMouseDown_(e);\n  };\n};\n\n/**\n * Compute width of flyout.  Position button under each block.\n */\nBlockly.BlockMenu.prototype.reflow = function() {\n  var blockMenuWidth = 0;\n  var margin = this.CORNER_RADIUS;\n  var blocks = this.workspace_.getTopBlocks(false);\n  for (var x = 0, block; block = blocks[x]; x++) {\n    var root = block.getSvgRoot();\n    var blockHW = block.getHeightWidth();\n    blockMenuWidth = Math.max(blockMenuWidth, blockHW.width);\n  }\n  this.blockMenuWidth = blockMenuWidth;\n  blockMenuWidth += margin + Blockly.BlockSvg.TAB_WIDTH + margin / 2 +\n                 Blockly.Scrollbar.scrollbarThickness;\n  if (this.width_ != blockMenuWidth) {\n    for (var x = 0, block; block = blocks[x]; x++) {\n      var blockHW = block.getHeightWidth();\n      var blockXY = block.getRelativeToSurfaceXY();\n      if (Blockly.RTL) {\n        // With the blockMenuWidth known, right-align the blocks.\n        var dx = blockMenuWidth - margin - Blockly.BlockSvg.TAB_WIDTH - blockXY.x;\n        block.moveBy(dx, 0);\n        blockXY.x += dx;\n      }\n      //if (block.blockMenuRect_) {\n        //block.blockMenuRect_.setAttribute('width', blockHW.width);\n        //block.blockMenuRect_.setAttribute('height', blockHW.height);\n        //block.blockMenuRect_.setAttribute('x',\n            //Blockly.RTL ? blockXY.x - blockHW.width : blockXY.x);\n        //block.blockMenuRect_.setAttribute('y', blockXY.y);\n      //}\n    }\n    // Record the width for .getMetrics_ and .position_.\n    this.width_ = blockMenuWidth;\n    // Fire a resize event to update the blockMenu's scrollbar.\n    Blockly.fireUiEvent(window, 'resize');\n  }\n};\n\n/**\n * return metrices for workspace\n * @private\n */\nBlockly.BlockMenu.prototype.getMetrics_ = function() {\n  var rect = this.view_.getBoundingClientRect();\n  try {\n    var optionBox = this.workspace_.getCanvas().getBBox();\n  } catch (e) {\n    // Firefox has trouble with hidden elements (Bug 528969).\n    var optionBox = {height: 0, y: 0};\n  }\n  var metrics = {\n    viewHeight: rect.height,\n    viewWidth: rect.width,\n    contentHeight: optionBox.height + optionBox.y,\n    viewTop: -this.workspace_.scrollY,\n    contentTop: 0,\n    absoluteTop: 0,\n    absoluteLeft: 0\n  };\n  return metrics;\n};\n\n/**\n * Sets the Y translation of the flyout to match the scrollbars.\n * @param {!Object} yRatio Contains a y property which is a float\n *     between 0 and 1 specifying the degree of scrolling.\n * @private\n */\nBlockly.BlockMenu.prototype.setMetrics_ = function(yRatio) {\n  var metrics = this.getMetrics_();\n  // This is a fix to an apparent race condition.\n  if (!metrics) {\n    return;\n  }\n  if (goog.isNumber(yRatio.y)) {\n    this.workspace_.scrollY =\n        -metrics.contentHeight * yRatio.y - metrics.contentTop;\n  }\n  var y = this.workspace_.scrollY + metrics.absoluteTop;\n  this.workspace_.getCanvas().setAttribute('transform',\n                                           'translate(0,' + y + ')');\n};\n\n/**\n * Stop binding to the global mouseup and mousemove events.\n * @private\n */\nBlockly.BlockMenu.terminateDrag_ = function() {\n  if (Blockly.BlockMenu.onMouseUpWrapper_) {\n    Blockly.unbindEvent_(Blockly.BlockMenu.onMouseUpWrapper_);\n    Blockly.BlockMenu.onMouseUpWrapper_ = null;\n  }\n  if (Blockly.BlockMenu.onMouseMoveWrapper_) {\n    Blockly.unbindEvent_(Blockly.BlockMenu.onMouseMoveWrapper_);\n    Blockly.BlockMenu.onMouseMoveWrapper_ = null;\n  }\n  Blockly.BlockMenu.startDownEvent_ = null;\n  Blockly.BlockMenu.startBlock_ = null;\n  Blockly.BlockMenu.startFlyout_ = null;\n};\n\n/**\n * Update view when window resizing\n * @private\n */\nBlockly.BlockMenu.prototype.syncViewSize_ = function() {\n  var rect = this.view_.getBoundingClientRect();\n  this.menuView_.style.width = rect.width + 'px';\n  this.menuView_.style.height = rect.height + 'px';\n  this.scrollbar_.resize();\n};\n"
  },
  {
    "path": "extern/blockly/core/block_svg.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Methods for graphically rendering a block as SVG.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\ngoog.provide('Blockly.BlockSvg');\n\ngoog.require('goog.userAgent');\n\n\n/**\n * Class for a block's SVG representation.\n * @param {!Blockly.Block} block The underlying block object.\n * @constructor\n */\nBlockly.BlockSvg = function(block) {\n  this.block_ = block;\n  // Create core elements for the block.\n  this.svgGroup_ = Blockly.createSvgElement('g', {}, null);\n  this.svgGroup_.block = this.block_;\n  this.svgPathDark_ = Blockly.createSvgElement('path',\n      {'class': 'blocklyPathDark', 'transform': 'translate(0, 1)'},\n      this.svgGroup_);\n  this.svgPath_ = Blockly.createSvgElement('path', {'class': 'blocklyPath'},\n      this.svgGroup_);\n  if (Blockly.enableBlockAnimation) {\n      this.svgPathPatternA_ = Blockly.createSvgElement('path', {\n        'id': 'blocklyPathPattern1',\n        'class': 'blocklyPathPattern'}, this.svgGroup_);\n      this.svgPathPatternB_ = Blockly.createSvgElement('path', {\n        'id': 'blocklyPathPattern2',\n        'class': 'blocklyPathPattern'}, this.svgGroup_);\n      this.svgPathPatternC_ = Blockly.createSvgElement('path', {\n        'id': 'blocklyPathPattern3',\n        'class': 'blocklyPathPattern'}, this.svgGroup_);\n      this.svgPathPatternD_ = Blockly.createSvgElement('path', {\n        'id': 'blocklyPathPattern4',\n        'class': 'blocklyPathPattern'}, this.svgGroup_);\n  }\n  if (this.block_.outputConnection)\n    this.svgPathLight_ = Blockly.createSvgElement('path',\n        {'class': 'blocklyPathLight'}, this.svgGroup_);\n  this.svgPath_.tooltip = this.block_;\n  Blockly.Tooltip && Blockly.Tooltip.bindMouseEvents(this.svgPath_);\n  this.updateMovable();\n};\n\n/**\n * Constant for identifying rows that are to be rendered inline.\n * Don't collide with Blockly.INPUT_VALUE and friends.\n * @const\n */\nBlockly.BlockSvg.INLINE = -1;\n\n/**\n * Initialize the SVG representation with any block attributes which have\n * already been defined.\n */\nBlockly.BlockSvg.prototype.init = function() {\n  var block = this.block_;\n  this.updateColour();\n  for (var x = 0, input; input = block.inputList[x]; x++) {\n    input.init();\n  }\n  if (block.mutator) {\n    block.mutator.createIcon();\n  }\n};\n\n/**\n * Add or remove the UI indicating if this block is movable or not.\n */\nBlockly.BlockSvg.prototype.updateMovable = function() {\n  if (this.block_.isMovable()) {\n    Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_),\n                      'blocklyDraggable');\n  } else {\n    Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),\n                         'blocklyDraggable');\n  }\n};\n\nBlockly.BlockSvg.prototype.toggleOnPattern = function(e) {\n  Blockly.addClass_(this.svgGroup_.parentNode, 'disablePattern');\n  Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_),\n                'togglePattern');\n\n};\n\nBlockly.BlockSvg.prototype.toggleOffPattern = function(e) {\n  Blockly.removeClass_(this.svgGroup_.parentNode, 'disablePattern');\n  Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),\n                       'togglePattern');\n};\n\n/**\n * Get the root SVG element.\n * @return {!Element} The root SVG element.\n */\nBlockly.BlockSvg.prototype.getRootElement = function() {\n  return this.svgGroup_;\n};\n\n// UI constants for rendering blocks.\n/**\n * Horizontal space between elements.\n * @const\n */\nBlockly.BlockSvg.SEP_SPACE_X = 4;\n/**\n * Vertical space between elements.\n * @const\n */\nBlockly.BlockSvg.SEP_SPACE_Y = 10;\n/**\n * Vertical padding around inline elements.\n * @const\n */\nBlockly.BlockSvg.INLINE_PADDING_Y = 2;\n/**\n * Minimum height of a block.\n * @const\n */\nBlockly.BlockSvg.MIN_BLOCK_Y = 30;\n/**\n * Minimum height of a block.\n * @const\n */\nBlockly.BlockSvg.MIN_INLINE_BLOCK_Y = 20;\n/**\n * Height of horizontal puzzle tab.\n * @const\n */\nBlockly.BlockSvg.TAB_HEIGHT = 20;\n/**\n * Width of horizontal puzzle tab.\n * @const\n */\nBlockly.BlockSvg.TAB_WIDTH = 8;\n/**\n * Width of vertical tab (inc left margin).\n * @const\n */\nBlockly.BlockSvg.NOTCH_WIDTH = 16;\n/**\n * Rounded corner radius.\n * @const\n */\nBlockly.BlockSvg.CORNER_RADIUS = 0;\n/**\n * Minimum height of field rows.\n * @const\n */\nBlockly.BlockSvg.FIELD_HEIGHT = 0;\n/**\n * Distance from shape edge to intersect with a curved corner at 45 degrees.\n * Applies to highlighting on around the inside of a curve.\n * @const\n */\nBlockly.BlockSvg.DISTANCE_45_INSIDE = (1 - Math.SQRT1_2) *\n      (Blockly.BlockSvg.CORNER_RADIUS - 1) + 1;\n/**\n * Distance from shape edge to intersect with a curved corner at 45 degrees.\n * Applies to highlighting on around the outside of a curve.\n * @const\n */\nBlockly.BlockSvg.DISTANCE_45_OUTSIDE = (1 - Math.SQRT1_2) *\n      (Blockly.BlockSvg.CORNER_RADIUS + 1) - 1;\n/**\n * SVG path for drawing next/previous notch from left to right.\n * @const\n */\n//Blockly.BlockSvg.NOTCH_PATH_LEFT = 'l 6,4 3,0 6,-4';\nBlockly.BlockSvg.NOTCH_PATH_LEFT = 'l 8,8 8,-8';\n/**\n * SVG path for drawing next/previous notch from left to right with\n * highlighting.\n * @const\n */\nBlockly.BlockSvg.NOTCH_PATH_LEFT_HIGHLIGHT = 'l 6.5,4 2,0 6.5,-4';\n/**\n * SVG path for drawing next/previous notch from right to left.\n * @const\n */\n//Blockly.BlockSvg.NOTCH_PATH_RIGHT = 'l -6,4 -3,0 -6,-4';\nBlockly.BlockSvg.NOTCH_PATH_RIGHT = 'l -8,8 -8,-8';\n/**\n * SVG path for drawing jagged teeth at the end of collapsed blocks.\n * @const\n */\nBlockly.BlockSvg.JAGGED_TEETH = 'l 8,0 0,4 8,4 -16,8 8,4';\n/**\n * SVG path for drawing jagged teeth at the end of collapsed blocks.\n * @const\n */\nBlockly.BlockSvg.JAGGED_TEETH_HEIGHT = 20;\n/**\n * SVG path for drawing a horizontal puzzle tab from top to bottom.\n * @const\n */\nBlockly.BlockSvg.TAB_PATH_DOWN = 'v 5 c 0,10 -' + Blockly.BlockSvg.TAB_WIDTH +\n    ',-8 -' + Blockly.BlockSvg.TAB_WIDTH + ',7.5 s ' +\n    Blockly.BlockSvg.TAB_WIDTH + ',-2.5 ' + Blockly.BlockSvg.TAB_WIDTH + ',7.5';\n/**\n * SVG path for drawing a horizontal puzzle tab from top to bottom with\n * highlighting from the upper-right.\n * @const\n */\nBlockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL = 'v 6.5 m -' +\n    (Blockly.BlockSvg.TAB_WIDTH * 0.98) + ',2.5 q -' +\n    (Blockly.BlockSvg.TAB_WIDTH * .05) + ',10 ' +\n    (Blockly.BlockSvg.TAB_WIDTH * .27) + ',10 m ' +\n    (Blockly.BlockSvg.TAB_WIDTH * .71) + ',-2.5 v 1.5';\n\n/**\n * SVG start point for drawing the top-left corner.\n * @const\n */\nBlockly.BlockSvg.TOP_LEFT_CORNER_START =\n    'm 0,' + Blockly.BlockSvg.CORNER_RADIUS;\n/**\n * SVG start point for drawing the top-left corner's highlight in RTL.\n * @const\n */\nBlockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_RTL =\n    'm ' + Blockly.BlockSvg.DISTANCE_45_INSIDE + ',' +\n    Blockly.BlockSvg.DISTANCE_45_INSIDE;\n/**\n * SVG start point for drawing the top-left corner's highlight in LTR.\n * @const\n */\nBlockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_LTR =\n    'm 1,' + (Blockly.BlockSvg.CORNER_RADIUS - 1);\n/**\n * SVG path for drawing the rounded top-left corner.\n * @const\n */\nBlockly.BlockSvg.TOP_LEFT_CORNER =\n    'A ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +\n    Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 ' +\n    Blockly.BlockSvg.CORNER_RADIUS + ',0';\n/**\n * SVG path for drawing the highlight on the rounded top-left corner.\n * @const\n */\nBlockly.BlockSvg.TOP_LEFT_CORNER_HIGHLIGHT =\n    'A ' + (Blockly.BlockSvg.CORNER_RADIUS - 1) + ',' +\n    (Blockly.BlockSvg.CORNER_RADIUS - 1) + ' 0 0,1 ' +\n    Blockly.BlockSvg.CORNER_RADIUS + ',1';\n/**\n * SVG path for drawing the top-left corner of a statement input.\n * Includes the top notch, a horizontal space, and the rounded inside corner.\n * @const\n */\nBlockly.BlockSvg.INNER_TOP_LEFT_CORNER =\n    Blockly.BlockSvg.NOTCH_PATH_RIGHT + ' h -0.6 h' +\n    (Blockly.BlockSvg.CORNER_RADIUS) +\n    ' a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +\n    Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 -' +\n    Blockly.BlockSvg.CORNER_RADIUS + ',' +\n    Blockly.BlockSvg.CORNER_RADIUS;\n/**\n * SVG path for drawing the bottom-left corner of a statement input.\n * Includes the rounded inside corner.\n * @const\n */\nBlockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER =\n    'a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' +\n    Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' +\n    Blockly.BlockSvg.CORNER_RADIUS + ',' +\n    Blockly.BlockSvg.CORNER_RADIUS;\n/**\n * SVG path for drawing highlight on the top-left corner of a statement\n * input in RTL.\n * @const\n */\nBlockly.BlockSvg.INNER_TOP_LEFT_CORNER_HIGHLIGHT_RTL =\n    'a ' + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ',' +\n    (Blockly.BlockSvg.CORNER_RADIUS + 1) + ' 0 0,0 ' +\n    (-Blockly.BlockSvg.DISTANCE_45_OUTSIDE - 1) + ',' +\n    (Blockly.BlockSvg.CORNER_RADIUS -\n    Blockly.BlockSvg.DISTANCE_45_OUTSIDE);\n/**\n * SVG path for drawing highlight on the bottom-left corner of a statement\n * input in RTL.\n * @const\n */\nBlockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_RTL =\n    'a ' + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ',' +\n    (Blockly.BlockSvg.CORNER_RADIUS + 1) + ' 0 0,0 ' +\n    (Blockly.BlockSvg.CORNER_RADIUS + 1) + ',' +\n    (Blockly.BlockSvg.CORNER_RADIUS + 1);\n/**\n * SVG path for drawing highlight on the bottom-left corner of a statement\n * input in LTR.\n * @const\n */\nBlockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR =\n    'a ' + (Blockly.BlockSvg.CORNER_RADIUS + 1) + ',' +\n    (Blockly.BlockSvg.CORNER_RADIUS + 1) + ' 0 0,0 ' +\n    (Blockly.BlockSvg.CORNER_RADIUS -\n    Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + ',' +\n    (Blockly.BlockSvg.DISTANCE_45_OUTSIDE + 1);\n\n/**\n * Dispose of this SVG block.\n */\nBlockly.BlockSvg.prototype.dispose = function() {\n  goog.dom.removeNode(this.svgGroup_);\n  // Sever JavaScript to DOM connections.\n  this.svgGroup_ = null;\n  this.svgPath_ = null;\n  if (Blockly.enableBlockAnimation) {\n      this.svgPathPatternA_ = null;\n      this.svgPathPatternB_ = null;\n      this.svgPathPatternC_ = null;\n      this.svgPathPatternD_ = null;\n  }\n  this.svgPathLight_ = null;\n  this.svgPathDark_ = null;\n  // Break circular references.\n  this.block_ = null;\n};\n\n/**\n * Play some UI effects (sound, animation) when disposing of a block.\n */\nBlockly.BlockSvg.prototype.disposeUiEffect = function() {\n  Blockly.playAudio('delete');\n\n  var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_));\n  // Deeply clone the current block.\n  var clone = this.svgGroup_.cloneNode(true);\n  clone.translateX_ = xy.x;\n  clone.translateY_ = xy.y;\n  clone.setAttribute('transform',\n      'translate(' + clone.translateX_ + ',' + clone.translateY_ + ')');\n  Blockly.svg.appendChild(clone);\n  clone.bBox_ = clone.getBBox();\n  // Start the animation.\n  clone.startDate_ = new Date();\n  Blockly.BlockSvg.disposeUiStep_(clone);\n};\n\n/**\n * Animate a cloned block and eventually dispose of it.\n * @param {!Element} clone SVG element to animate and dispose of.\n * @private\n */\nBlockly.BlockSvg.disposeUiStep_ = function(clone) {\n  var textNodes = clone.getElementsByTagName('text');\n\n  if (textNodes) {\n      for (var i=0; i<textNodes.length; i++)\n        textNodes[i].parentNode.removeChild(textNodes[i]);\n  }\n\n  var ms = (new Date()) - clone.startDate_;\n  var percent = ms / 100;\n  if (percent > 1) {\n    goog.dom.removeNode(clone);\n  } else {\n    var x = clone.translateX_ +\n        (Blockly.RTL ? -1 : 1) * clone.bBox_.width / 2 * percent;\n    var y = clone.translateY_ + clone.bBox_.height * percent;\n    var translate = x + ', ' + y;\n    var scale = 1 - percent;\n    clone.setAttribute('transform', 'translate(' + translate + ')' +\n        ' scale(' + scale + ')');\n    var closure = function() {\n      Blockly.BlockSvg.disposeUiStep_(clone);\n    };\n    window.setTimeout(closure, 10);\n  }\n};\n\n/**\n * Play some UI effects (sound, ripple) after a connection has been established.\n */\nBlockly.BlockSvg.prototype.connectionUiEffect = function() {\n  Blockly.playAudio('click');\n\n  // Determine the absolute coordinates of the inferior block.\n  var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_));\n  // Offset the coordinates based on the two connection types.\n  if (this.block_.outputConnection) {\n    xy.x += Blockly.RTL ? 3 : -3;\n    xy.y += 13;\n  } else if (this.block_.previousConnection) {\n    xy.x += Blockly.RTL ? -23 : 23;\n    xy.y += 3;\n  }\n  var ripple = Blockly.createSvgElement('circle',\n      {'cx': xy.x, 'cy': xy.y, 'r': 0, 'fill': 'none',\n       'stroke': '#888', 'stroke-width': 10},\n      Blockly.svg);\n  // Start the animation.\n  ripple.startDate_ = new Date();\n  Blockly.BlockSvg.connectionUiStep_(ripple);\n};\n\n/**\n * Expand a ripple around a connection.\n * @param {!Element} ripple Element to animate.\n * @private\n */\nBlockly.BlockSvg.connectionUiStep_ = function(ripple) {\n  var ms = (new Date()) - ripple.startDate_;\n  var percent = ms / 150;\n  if (percent > 1) {\n    goog.dom.removeNode(ripple);\n  } else {\n    ripple.setAttribute('r', percent * 25);\n    ripple.style.opacity = 1 - percent;\n    var closure = function() {\n      Blockly.BlockSvg.connectionUiStep_(ripple);\n    };\n    window.setTimeout(closure, 10);\n  }\n};\n\n/**\n * Change the colour of a block.\n */\nBlockly.BlockSvg.prototype.updateColour = function() {\n  if (this.block_.disabled) {\n    // Disabled blocks don't have colour.\n    return;\n  }\n  var hexColour = Blockly.makeColour(this.block_.getColour());\n  var rgb = goog.color.hexToRgb(hexColour);\n  var rgbLight = goog.color.darken(rgb, 0.1);\n  var rgbDark = goog.color.darken(rgb, 0.3);\n  if (this.block_.outputConnection)\n    this.svgPathLight_.setAttribute('stroke', goog.color.rgbArrayToHex(rgbLight));\n  if (this.block_.outputConnection)\n    if (this.block_.parentBlock_)\n      this.svgPathDark_.setAttribute('opacity', 0);\n    else\n      this.svgPathDark_.removeAttribute('opacity');\n  this.svgPathDark_.setAttribute('fill', goog.color.rgbArrayToHex(rgbDark));\n  this.svgPath_.setAttribute('fill', hexColour);\n  if (Blockly.enableBlockAnimation) {\n      this.svgPathPatternA_.setAttribute('fill', 'url(#blockPattern1)');\n      Blockly.createSvgElement('animate', {\n        'attributeName': 'opacity',\n        'values': '0;0.2;0;0',\n        'repeatCount': 'indefinite',\n        'begin': '0',\n        'dur': '1.4s'\n      }, this.svgPathPatternA_);\n      this.svgPathPatternB_.setAttribute('fill', 'url(#blockPattern2)');\n      Blockly.createSvgElement('animate', {\n        'attributeName': 'opacity',\n        'values': '0;0.2;0;0',\n        'repeatCount': 'indefinite',\n        'begin': '0.33',\n        'dur': '1.4s'\n      }, this.svgPathPatternB_);\n      this.svgPathPatternC_.setAttribute('fill', 'url(#blockPattern3)');\n      Blockly.createSvgElement('animate', {\n        'attributeName': 'opacity',\n        'values': '0;0.2;0;0',\n        'repeatCount': 'indefinite',\n        'begin': '0.67',\n        'dur': '1.4s'\n      }, this.svgPathPatternC_);\n      this.svgPathPatternD_.setAttribute('fill', 'url(#blockPattern4)');\n  }\n  Blockly.createSvgElement('animate', {\n    'attributeName': 'opacity',\n    'values': '0;0.2;0;0',\n    'repeatCount': 'indefinite',\n    'begin': '1',\n    'dur': '1.4s'\n  }, this.svgPathPatternD_);\n};\n\n/**\n * Enable or disable a block.\n */\nBlockly.BlockSvg.prototype.updateDisabled = function() {\n  if (this.block_.disabled || this.block_.getInheritedDisabled()) {\n    Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_),\n                      'blocklyDisabled');\n    this.svgPath_.setAttribute('fill', 'gray');\n  } else {\n    Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),\n                         'blocklyDisabled');\n    this.updateColour();\n  }\n  var children = this.block_.getChildren();\n  for (var x = 0, child; child = children[x]; x++) {\n    child.svg_.updateDisabled();\n  }\n};\n\n/**\n * Select this block.  Highlight it visually.\n */\nBlockly.BlockSvg.prototype.addSelect = function() {\n  Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_),\n                    'blocklySelected');\n  // Move the selected block to the top of the stack.\n  if (this.block_.isInBlockMenu)\n    return;\n  this.svgGroup_.parentNode.appendChild(this.svgGroup_);\n};\n\n/**\n * Unselect this block.  Remove its highlighting.\n */\nBlockly.BlockSvg.prototype.removeSelect = function() {\n  Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),\n                       'blocklySelected');\n  Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),\n                       'blocklyActivated');\n};\n\n/**\n * Activate this block.  Highlight it visually.\n */\nBlockly.BlockSvg.prototype.addActive = function() {\n  Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_),\n                    'blocklyActivated');\n  // Move the selected block to the top of the stack.\n  this.svgGroup_.parentNode.appendChild(this.svgGroup_);\n};\n\n/**\n * Activate this block.  Remove its highlighting.\n */\nBlockly.BlockSvg.prototype.removeActive = function() {\n  Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),\n                       'blocklyActivated');\n};\n\n/**\n * Adds the dragging class to this block.\n * Also disables the highlights/shadows to improve performance.\n */\nBlockly.BlockSvg.prototype.addDragging = function() {\n  Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_),\n                    'blocklyDragging');\n};\n\n/**\n * Removes the dragging class from this block.\n */\nBlockly.BlockSvg.prototype.removeDragging = function() {\n  Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_),\n                       'blocklyDragging');\n};\n\n/**\n * Render the block.\n * Lays out and reflows a block based on its contents and settings.\n */\nBlockly.BlockSvg.prototype.render = function() {\n  this.block_.rendered = true;\n\n  var cursorX = Blockly.BlockSvg.SEP_SPACE_X;\n  // Move the icons into position.\n  var icons = this.block_.getIcons();\n  for (var x = 0; x < icons.length; x++) {\n    cursorX = icons[x].renderIcon(cursorX);\n  }\n  cursorX += Blockly.RTL ?\n      Blockly.BlockSvg.SEP_SPACE_X : -Blockly.BlockSvg.SEP_SPACE_X;\n  // If there are no icons, cursorX will be 0, otherwise it will be the\n  // width that the first label needs to move over by.\n\n  var inputRows = this.renderCompute_(cursorX);\n  this.renderDraw_(cursorX, inputRows);\n\n  // Render all blocks above this one (propagate a reflow).\n  var parentBlock = this.block_.getParent();\n  if (parentBlock) {\n    parentBlock.render();\n  } else {\n    // Top-most block.  Fire an event to allow scrollbars to resize.\n    //Blockly.fireUiEvent(window, 'resize');\n    // Remove. It's too heavy.\n  }\n};\n\n/**\n * Render a list of fields starting at the specified location.\n * @param {!Array.<!Blockly.Field>} fieldList List of fields.\n * @param {number} cursorX X-coordinate to start the fields.\n * @param {number} cursorY Y-coordinate to start the fields.\n * @param {number} rowHeight row height.\n * @return {number} X-coordinate of the end of the field row (plus a gap).\n * @private\n */\nBlockly.BlockSvg.prototype.renderFields_ = function(fieldList,\n                                                    cursorX, cursorY, rowHeight) {\n  for (var t = 0, field; field = fieldList[t]; t++) {\n    // Get the dimensions of the field.\n    if (field.isTextInput && fieldList.length ==1)\n      cursorX -= 4;\n    var fieldSize = field.getSize();\n    var fieldWidth = fieldSize.width;\n    var fieldY = cursorY + (rowHeight - fieldSize.height)/ 2;\n\n    field.getRootElement().setAttribute('transform',\n        'translate(' + cursorX + ', ' + fieldY + ')');\n    if (fieldWidth) {\n      cursorX += fieldWidth + Blockly.BlockSvg.SEP_SPACE_X;\n    }\n    if (field.isTextInput && fieldList.length ==1)\n      cursorX += 4;\n  }\n  return Blockly.RTL ? -cursorX : cursorX;\n};\n\n/**\n * Computes the height and widths for each row and field.\n * @param {number} iconWidth Offset of first row due to icons.\n * @return {!Array.<!Array.<!Object>>} 2D array of objects, each containing\n *     position information.\n * @private\n */\nBlockly.BlockSvg.prototype.renderCompute_ = function(iconWidth) {\n  var inputList = this.block_.inputList;\n  var inputRows = [];\n  inputRows.rightEdge = iconWidth + Blockly.BlockSvg.SEP_SPACE_X * 2;\n  if (this.block_.previousConnection || this.block_.nextConnection) {\n    inputRows.rightEdge = Math.max(inputRows.rightEdge,\n        Blockly.BlockSvg.NOTCH_WIDTH + Blockly.BlockSvg.SEP_SPACE_X);\n  }\n  var fieldValueWidth = 0;  // Width of longest external value field.\n  var fieldStatementWidth = 0;  // Width of longest statement field.\n  var hasValue = false;\n  var hasStatement = false;\n  var hasDummy = false;\n  var lastType = undefined;\n  var isInline = this.block_.inputsInline && !this.block_.isCollapsed();\n  for (var i = 0, input; input = inputList[i]; i++) {\n    if (!input.isVisible()) {\n      continue;\n    }\n    var row;\n    if (!isInline || !lastType ||\n        lastType == Blockly.NEXT_STATEMENT ||\n        input.type == Blockly.NEXT_STATEMENT) {\n      // Create new row.\n      lastType = input.type;\n      row = [];\n      if (isInline && input.type != Blockly.NEXT_STATEMENT) {\n        row.type = Blockly.BlockSvg.INLINE;\n      } else {\n        row.type = input.type;\n      }\n      row.height = 0;\n      inputRows.push(row);\n    } else {\n      row = inputRows[inputRows.length - 1];\n    }\n    row.push(input);\n\n    // Compute minimum input size.\n    if (input.sourceBlock_.outputConnection)\n      input.renderHeight = Blockly.BlockSvg.MIN_INLINE_BLOCK_Y;\n    else\n      input.renderHeight = Blockly.BlockSvg.MIN_BLOCK_Y;\n    // The width is currently only needed for inline value inputs.\n    if (isInline && input.type == Blockly.INPUT_VALUE) {\n      input.renderWidth = Blockly.BlockSvg.TAB_WIDTH +\n          Blockly.BlockSvg.SEP_SPACE_X;\n    } else {\n      input.renderWidth = 0;\n    }\n    // Expand input size if there is a connection.\n    if (input.connection && input.connection.targetConnection) {\n      var linkedBlock = input.connection.targetBlock();\n      var bBox = linkedBlock.getHeightWidth();\n      input.renderHeight = Blockly.BlockSvg.MIN_INLINE_BLOCK_Y;\n      input.renderHeight = Math.max(input.renderHeight, bBox.height);\n      input.renderWidth = Math.max(input.renderWidth, bBox.width);\n    }\n\n    row.height = Math.max(row.height, input.renderHeight);\n    input.fieldWidth = 0;\n    if (inputRows.length == 1) {\n      // The first row gets shifted to accommodate any icons.\n      input.fieldWidth += Blockly.RTL ? -iconWidth : iconWidth;\n    }\n    for (var j = 0, field; field = input.fieldRow[j]; j++) {\n      if (j == 0 && field instanceof Blockly.FieldIcon)\n        continue;\n      if (j != 0) {\n        input.fieldWidth += Blockly.BlockSvg.SEP_SPACE_X;\n      }\n      // Get the dimensions of the field.\n      var fieldSize = field.getSize();\n      input.fieldWidth += fieldSize.width;\n      row.height = Math.max(row.height, fieldSize.height);\n    }\n\n    if (row.type != Blockly.BlockSvg.INLINE) {\n      if (row.type == Blockly.NEXT_STATEMENT) {\n        hasStatement = true;\n        fieldStatementWidth = Math.max(fieldStatementWidth, input.fieldWidth);\n      } else {\n        if (row.type == Blockly.INPUT_VALUE) {\n          hasValue = true;\n        } else if (row.type == Blockly.DUMMY_INPUT) {\n          hasDummy = true;\n        }\n        fieldValueWidth = Math.max(fieldValueWidth, input.fieldWidth);\n      }\n    }\n  }\n\n  // Make inline rows a bit thicker in order to enclose the values.\n  for (var y = 0, row; row = inputRows[y]; y++) {\n    row.thicker = false;\n    if (row.type == Blockly.BlockSvg.INLINE) {\n      for (var z = 0, input; input = row[z]; z++) {\n        if (input.type == Blockly.INPUT_VALUE) {\n          if (this.block_.outputConnection) {\n            row.height += 2 * Blockly.BlockSvg.INLINE_PADDING_Y;\n            if (this.block_.outputConnection.check_[0].toUpperCase() == \"PARAM\")\n              row.height = Blockly.BlockSvg.MIN_BLOCK_Y - 6;\n          }\n          row.thicker = true;\n          break;\n        }\n      }\n    }\n    this.height = row.height+10;\n  }\n\n  // Compute the statement edge.\n  // This is the width of a block where statements are nested.\n  inputRows.statementEdge = 2 * Blockly.BlockSvg.SEP_SPACE_X +\n      fieldStatementWidth;\n  // Compute the preferred right edge.  Inline blocks may extend beyond.\n  // This is the width of the block where external inputs connect.\n  if (hasStatement) {\n    inputRows.rightEdge = Math.max(inputRows.rightEdge,\n        inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH);\n  }\n  if (hasValue) {\n    inputRows.rightEdge = Math.max(inputRows.rightEdge, fieldValueWidth +\n        Blockly.BlockSvg.SEP_SPACE_X * 2 + Blockly.BlockSvg.TAB_WIDTH);\n  } else if (hasDummy) {\n    inputRows.rightEdge = Math.max(inputRows.rightEdge, fieldValueWidth +\n        Blockly.BlockSvg.SEP_SPACE_X * 2);\n  }\n\n  inputRows.hasValue = hasValue;\n  inputRows.hasStatement = hasStatement;\n  inputRows.hasDummy = hasDummy;\n  return inputRows;\n};\n\n\n/**\n * Draw the path of the block.\n * Move the fields to the correct locations.\n * @param {number} iconWidth Offset of first row due to icons.\n * @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each\n *     containing position information.\n * @private\n */\nBlockly.BlockSvg.prototype.renderDraw_ = function(iconWidth, inputRows) {\n  // Should the top and bottom left corners be rounded or square?\n  if (this.block_.outputConnection) {\n    this.squareTopLeftCorner_ = true;\n    this.squareBottomLeftCorner_ = true;\n    this.squareTopLeftCorner_ = false;\n    this.squareBottomLeftCorner_ = false;\n    // If this block is in the middle of a stack, square the corners.\n    if (this.block_.previousConnection) {\n      var prevBlock = this.block_.previousConnection.targetBlock();\n      if (prevBlock && prevBlock.nextConnection &&\n          prevBlock.nextConnection.targetConnection ==\n          this.block_.previousConnection) {\n        this.squareTopLeftCorner_ = true;\n       }\n    }\n    if (this.block_.nextConnection) {\n      var nextBlock = this.block_.nextConnection.targetBlock();\n      if (nextBlock && nextBlock.previousConnection &&\n          nextBlock.previousConnection.targetConnection ==\n          this.block_.nextConnection) {\n        this.squareBottomLeftCorner_ = true;\n      }\n    }\n  }\n\n  // Fetch the block's coordinates on the surface for use in anchoring\n  // the connections.\n  var connectionsXY = this.block_.getRelativeToSurfaceXY();\n\n  // Assemble the block's path.\n  var steps = [];\n  var inlineSteps = [];\n  // The highlighting applies to edges facing the upper-left corner.\n  // Since highlighting is a two-pixel wide border, it would normally overhang\n  // the edge of the block by a pixel. So undersize all measurements by a pixel.\n\n  this.renderDrawTop_(steps, connectionsXY,\n      inputRows);\n  var cursorY = this.renderDrawRight_(steps, inlineSteps,\n      connectionsXY, inputRows, iconWidth);\n  this.renderDrawBottom_(steps, connectionsXY, cursorY);\n  this.renderDrawLeft_(steps, connectionsXY, cursorY, inputRows);\n\n  var pathString = steps.join(' ') + '\\n' + inlineSteps.join(' ');\n  this.svgPath_.setAttribute('d', pathString);\n  if (Blockly.enableBlockAnimation) {\n      this.svgPathPatternA_.setAttribute('d', pathString);\n      this.svgPathPatternB_.setAttribute('d', pathString);\n      this.svgPathPatternC_.setAttribute('d', pathString);\n      this.svgPathPatternD_.setAttribute('d', pathString);\n  }\n  this.svgPathDark_.setAttribute('d', pathString);\n  if (this.block_.outputConnection)\n    this.svgPathLight_.setAttribute('d', pathString);\n  var block = this.block_;\n  if (block.previousConnection && !block.nextConnection\n      && !block.outputConnection && !block.dummySpace ) {\n    block.dummySpace = true;\n    var rect = Blockly.createSvgElement('rect', {'class':'BlockSpaceDummy',\n    'height': '9', 'width':'10', 'y':(this.height - 10), 'opacity': '0'}, block.svg_.svgGroup_);\n  }\n};\n\n/**\n * Render the top edge of the block.\n * @param {!Array.<string>} steps Path of block outline.\n * @param {!Object} connectionsXY Location of block.\n * @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each\n *     containing position information.\n * @private\n */\nBlockly.BlockSvg.prototype.renderDrawTop_ =\n    function(steps, connectionsXY, inputRows) {\n  // Position the cursor at the top-left starting point.\n//if (this.squareTopLeftCorner_) {\n  var rightEdge = inputRows.rightEdge;\n  if (true) {\n    steps.push('m 0,0');\n  } else {\n    steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER_START);\n    // Top-left rounded corner.\n    steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER);\n  }\n  if (Blockly.BROKEN_CONTROL_POINTS) {\n    /* HACK:\n     WebKit bug 67298 causes control points to be included in the reported\n     bounding box.  Add 5px control point to the top of the path.\n    */\n   steps.push('c 0,4 0,-4 0,0');\n  }\n\n  var firstRow = inputRows[0][0].fieldRow;\n\n  // Top edge.\n  if (this.block_.previousConnection) {\n    steps.push('H', 0);\n    steps.push(Blockly.BlockSvg.NOTCH_PATH_LEFT);\n    // Create previous block connection.\n    var connectionX = connectionsXY.x + Blockly.BlockSvg.NOTCH_WIDTH;\n    var connectionY = connectionsXY.y;\n    this.block_.previousConnection.moveTo(connectionX, connectionY);\n    // This connection will be tightened when the parent renders.\n  } else if (firstRow[0] instanceof Blockly.FieldIcon) {\n    steps.push('m', '0,-5');\n    steps.push('a', '19.5,19.5 0, 0,1 16,0');\n    steps.push('c', '10,5 15,5 20,5');\n  }\n  //steps.push('H', rightEdge);\n};\n\n/**\n * Render the right edge of the block.\n * @param {!Array.<string>} steps Path of block outline.\n * @param {!Array.<string>} inlineSteps Inline block outlines.\n * @param {!Object} connectionsXY Location of block.\n * @param {!Array.<!Array.<!Object>>} inputRows 2D array of objects, each\n *     containing position information.\n * @param {number} iconWidth Offset of first row due to icons.\n * @return {number} Height of block.\n * @private\n */\nBlockly.BlockSvg.prototype.renderDrawRight_ = function(steps,\n    inlineSteps, connectionsXY, inputRows, iconWidth) {\n  var cursorX;\n  var cursorY = 0;\n  var connectionX, connectionY;\n  var blockWidth;\n  for (var y = 0, row; row = inputRows[y]; y++) {\n    cursorX = Blockly.BlockSvg.SEP_SPACE_X;\n    if (y == 0) {\n      cursorX += Blockly.RTL ? -iconWidth : iconWidth;\n    }\n    if (y == 0 && this.block_.outputConnection) {\n      if (row[0].type == Blockly.INPUT_VALUE)\n        cursorX -= row.height/2 + 2;\n      else if (this.block_.outputConnection.check_[0].toUpperCase() == \"PARAM\")\n        cursorX -= 8;\n      else\n        cursorX -= row.height/2 - 5;\n    } else if (y != 0) {\n      cursorX += 33;\n      cursorY -=2;\n    } else if (inputRows[0][0].fieldRow[0] instanceof Blockly.FieldIcon) {\n      cursorX -= 13;\n    } else if (!this.block_.previousConnection &&\n      !this.block_.nextConnection) {\n      cursorX -= 0;\n    } else {\n      cursorX += 14;\n    };\n    if (this.block_.isCollapsed()) {\n      // Jagged right edge.\n      var input = row[0];\n      var fieldX = cursorX;\n      var fieldY = cursorY + Blockly.BlockSvg.FIELD_HEIGHT;\n      this.renderFields_(input.fieldRow, fieldX, fieldY, row.height);\n      steps.push(Blockly.BlockSvg.JAGGED_TEETH);\n      var remainder = row.height - Blockly.BlockSvg.JAGGED_TEETH_HEIGHT;\n      steps.push('v', remainder);\n    } else if (row.type == Blockly.BlockSvg.INLINE) {\n      // Inline inputs.\n      for (var x = 0, input; input = row[x]; x++) {\n        var fieldX = cursorX;\n        var fieldY = cursorY + Blockly.BlockSvg.FIELD_HEIGHT;\n        // TODO: Align inline field rows (left/right/centre).\n        cursorX = this.renderFields_(input.fieldRow, fieldX, fieldY, row.height);\n        if (input.type != Blockly.DUMMY_INPUT) {\n          cursorX += input.renderWidth + Blockly.BlockSvg.SEP_SPACE_X;\n        }\n        if (input.type == Blockly.INPUT_VALUE) {\n          var r = input.renderHeight/2;\n          var l = input.renderWidth;\n          var param = 0;\n          l += 1;\n          var inputType = input.connection.check_ ? input.connection.check_[0] : \"null\";\n          var inlineCursorY = cursorY + (row.height - 2*r)/2;\n          if (inputType.toUpperCase() == \"BOOLEAN\") {\n            inlineSteps.push('M', (cursorX - Blockly.BlockSvg.SEP_SPACE_X - r) +\n                             ',' + (inlineCursorY + 0.5));\n            inlineSteps.push('h', -l + 2*r);\n            inlineSteps.push('l', '-' + r + ',' + r + ' ' + r + ',' + r);\n            inlineSteps.push('h', l - 2*r);\n            inlineSteps.push('l', r + ',-' + r + ' -' + r + ',-' + r);\n            inlineSteps.push('z');\n          } else if (inputType.toUpperCase() == \"PARAM\") {\n            inlineCursorY += 1;\n            if (this.block_.outputConnection) {\n              cursorX -= input.renderWidth + Blockly.BlockSvg.SEP_SPACE_X;\n              param = input.renderWidth + Blockly.BlockSvg.SEP_SPACE_X + 9;\n            } else {\n              param = 8;\n              inlineSteps.push('M', (cursorX - Blockly.BlockSvg.SEP_SPACE_X - 6) +\n                               ',' + (3));\n              inlineSteps.push('h', -l + 9);\n              inlineSteps.push('l', '-2,2 0,3 3,0 1,1 0,11 -1,1 -3,0 0,4 2,2');\n              inlineSteps.push('h', l - 9);\n              inlineSteps.push('l', '2,-2 0,-3 3,0 1,-1 0,-13 -1,-1 -3,0 0,-2 -2,-2');\n              inlineSteps.push('z');\n            }\n          } else {\n            inlineSteps.push('M', (cursorX - Blockly.BlockSvg.SEP_SPACE_X - r) +\n                             ',' +( inlineCursorY + 0.5));\n            inlineSteps.push('h', -l + 2*r);\n            inlineSteps.push('a', r + ',' + r + ' 0 1,0 0,' + 2*r);\n            inlineSteps.push('h', l - 2*r);\n            inlineSteps.push('a', r + ',' + r + ' 0 1,0 0,-' + 2*r);\n            inlineSteps.push('z');\n          }\n          // Create inline input connection.\n          connectionX = connectionsXY.x + cursorX - Blockly.BlockSvg.SEP_SPACE_X\n              -Blockly.BlockSvg.TAB_WIDTH-input.renderWidth +7.5+ r + param;\n          connectionY = connectionsXY.y + inlineCursorY;\n          input.connection.moveTo(connectionX, connectionY);\n          if (input.connection.targetConnection) {\n            input.connection.tighten_();\n          }\n        }\n      }\n\n      cursorX = Math.max(cursorX, inputRows.rightEdge);\n      blockWidth = cursorX;\n      if (this.block_.outputConnection) {\n        this.blockInlineWidth_ = cursorX;\n        var r = row.height/2;\n        this.r_ = r;\n        var lastRow = row[row.length-1].fieldRow;\n        if (lastRow[lastRow.length-1] instanceof Blockly.FieldLabel)\n          cursorX += 1;\n        cursorX += 2;\n        if (this.block_.outputConnection.check_[0].toUpperCase() == \"PARAM\") {\n          steps.push('H', cursorX);\n          steps.push('l', '-3,0 2,2 0,3 3,0 1,1 0,12 -1,1 -3,0 0,3 -2,2 3,0');\n        } else if (this.block_.outputConnection.check_[0].toUpperCase() == \"BOOLEAN\") {\n          steps.push('H', cursorX - r);\n          steps.push('l', r + ',' + r + ' -' + r + ',' + r);\n        } else {\n          steps.push('H', cursorX - r - 4);\n          steps.push('a', r + ',' + r + ' 0 1,1 0,' + 2*r);\n        }\n      } else {\n        if (y==0)\n          this.blockInlineWidth_ = cursorX;\n        if (this.blockInlineWidth_)\n          cursorX = this.blockInlineWidth_;\n        var lastRow = row[row.length-1].fieldRow;\n        if (!(lastRow[lastRow.length-1] instanceof Blockly.FieldIcon))\n          cursorX += 8;\n         var r = row.height/2;\n        steps.push('H', cursorX - r - 1);\n        steps.push('a', r + ',' + r + ' 0 0,1 0,' + 2*r);\n      }\n    } else if (row.type == Blockly.INPUT_VALUE) {\n      // External input.\n      var input = row[0];\n      var fieldX = cursorX;\n      var fieldY = cursorY + Blockly.BlockSvg.FIELD_HEIGHT;\n      if (input.align != Blockly.ALIGN_LEFT) {\n        var fieldRightX = inputRows.rightEdge - input.fieldWidth -\n            Blockly.BlockSvg.TAB_WIDTH - 2 * Blockly.BlockSvg.SEP_SPACE_X;\n        if (input.align == Blockly.ALIGN_RIGHT) {\n          fieldX += fieldRightX;\n        } else if (input.align == Blockly.ALIGN_CENTRE) {\n          fieldX += (fieldRightX + fieldX) / 2;\n        }\n      }\n      this.renderFields_(input.fieldRow, fieldX, fieldY, row.height);\n      steps.push(Blockly.BlockSvg.TAB_PATH_DOWN);\n      steps.push('v', row.height - Blockly.BlockSvg.TAB_HEIGHT);\n      // Create external input connection.\n      connectionX = connectionsXY.x +\n          (Blockly.RTL ? -inputRows.rightEdge - 1 : inputRows.rightEdge + 1);\n      connectionY = connectionsXY.y + cursorY + 1;\n      input.connection.moveTo(connectionX, connectionY);\n      if (input.connection.targetConnection) {\n        input.connection.tighten_();\n      }\n    } else if (row.type == Blockly.DUMMY_INPUT) {\n      // External naked field.\n      var input = row[0];\n      var fieldX = cursorX;\n      var fieldY = cursorY + Blockly.BlockSvg.FIELD_HEIGHT;\n      if (input.align != Blockly.ALIGN_LEFT) {\n        var fieldRightX = inputRows.rightEdge - input.fieldWidth -\n            2 * Blockly.BlockSvg.SEP_SPACE_X;\n        if (inputRows.hasValue) {\n          fieldRightX -= Blockly.BlockSvg.TAB_WIDTH;\n        }\n        if (input.align == Blockly.ALIGN_RIGHT) {\n          fieldX += fieldRightX;\n        } else if (input.align == Blockly.ALIGN_CENTRE) {\n          fieldX += (fieldRightX + fieldX) / 2;\n        }\n      }\n      this.renderFields_(input.fieldRow, fieldX, fieldY, row.height);\n      steps.push('v', row.height);\n    } else if (row.type == Blockly.NEXT_STATEMENT) {\n      // Nested statement.\n      var input = row[0];\n      if (y == 0) {\n        // If the first input is a statement stack, add a small row on top.\n        steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y);\n        cursorY += Blockly.BlockSvg.SEP_SPACE_Y;\n      }\n      var fieldX = cursorX;\n      var fieldY = cursorY + Blockly.BlockSvg.FIELD_HEIGHT;\n      if (input.align != Blockly.ALIGN_LEFT) {\n        var fieldRightX = inputRows.statementEdge - input.fieldWidth -\n            2 * Blockly.BlockSvg.SEP_SPACE_X;\n        if (input.align == Blockly.ALIGN_RIGHT) {\n          fieldX += fieldRightX;\n        } else if (input.align == Blockly.ALIGN_CENTRE) {\n          fieldX += (fieldRightX + fieldX) / 2;\n        }\n      }\n      this.renderFields_(input.fieldRow, fieldX, fieldY, row.height);\n      cursorX = inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH;\n\n        var r = row.height/2;\n      steps.push('H', cursorX + 6);\n      steps.push(Blockly.BlockSvg.INNER_TOP_LEFT_CORNER);\n      steps.push('v', row.height- 4.5);\n      steps.push(Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER);\n      steps.push('H', 14);\n      steps.push(Blockly.BlockSvg.NOTCH_PATH_LEFT);\n      if (this.blockInlineWidth_)\n        steps.push('H', this.blockInlineWidth_ -12);\n      else\n        steps.push('H', blockWidth);\n      // Create statement connection.\n      connectionX = connectionsXY.x + (Blockly.RTL ? -cursorX : cursorX) + 6;\n      connectionY = connectionsXY.y + cursorY + 3;\n      if (y != 0)\n        connectionY -= 0;\n      cursorY -= 0;\n      input.connection.moveTo(connectionX, connectionY);\n      if (input.connection.targetConnection) {\n        input.connection.tighten_();\n      }\n      if (y == inputRows.length - 1 ||\n          inputRows[y + 1].type == Blockly.NEXT_STATEMENT) {\n        // If the final input is a statement stack, add a small row underneath.\n        // Consecutive statement stacks are also separated by a small divider.\n        steps.push('a', 8 + ',' + 8 + ' 0 0,1 0,' + 2*8);\n        cursorY += Blockly.BlockSvg.SEP_SPACE_Y + 3;\n      }\n    }\n    cursorY += row.height;\n  }\n  if (!inputRows.length) {\n    cursorY = Blockly.BlockSvg.MIN_BLOCK_Y;\n    steps.push('V', cursorY);\n  }\n  return cursorY;\n};\n\n/**\n * Render the bottom edge of the block.\n * @param {!Array.<string>} steps Path of block outline.\n * @param {!Object} connectionsXY Location of block.\n * @param {number} cursorY Height of block.\n * @private\n */\nBlockly.BlockSvg.prototype.renderDrawBottom_ = function(steps,\n                                                     connectionsXY, cursorY) {\n  if (this.block_.nextConnection) {\n    steps.push('l', '0,-0.5');\n    steps.push('H', Blockly.BlockSvg.NOTCH_WIDTH + ' ' +\n        Blockly.BlockSvg.NOTCH_PATH_RIGHT);\n    steps.push('l', '0,0.5');\n    // Create next block connection.\n    var connectionX;\n    connectionX = connectionsXY.x + Blockly.BlockSvg.NOTCH_WIDTH;\n    var connectionY = connectionsXY.y + cursorY + 1;\n    this.block_.nextConnection.moveTo(connectionX, connectionY);\n    if (this.block_.nextConnection.targetConnection) {\n      this.block_.nextConnection.tighten_();\n    }\n  }\n\n  if (Blockly.BROKEN_CONTROL_POINTS) {\n    /* HACK:\n     WebKit bug 67298 causes control points to be included in the reported\n     bounding box.  Add 5px control point to the bottom of the path.\n    */\n   steps.push('c 0,4 0,-4 0,0');\n  }\n  // Should the bottom-left corner be rounded or square?\n//if (this.squareBottomLeftCorner_) {\n  if (true) {\n    steps.push('H 0');\n  } else {\n    steps.push('H', Blockly.BlockSvg.CORNER_RADIUS);\n    steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' +\n               Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 -' +\n               Blockly.BlockSvg.CORNER_RADIUS + ',-' +\n               Blockly.BlockSvg.CORNER_RADIUS);\n  }\n};\n\n/**\n * Render the left edge of the block.\n * @param {!Array.<string>} steps Path of block outline.\n * @param {!Object} connectionsXY Location of block.\n * @param {number} cursorY Height of block.\n * @private\n */\nBlockly.BlockSvg.prototype.renderDrawLeft_ = function(steps,\n                                                      connectionsXY, cursorY,\n                                                      inputRows) {\n  if (this.block_.outputConnection) {\n    // Create output connection.\n    this.block_.outputConnection.moveTo(connectionsXY.x, connectionsXY.y);\n    // This connection will be tightened when the parent renders.\n    var r = this.r_;\n    if (this.block_.outputConnection.check_[0].toUpperCase() == \"PARAM\") {\n      steps.push('l', '-18,0 -2,-2 0,-3 3,0 1,-1 0,-12 -1,-1 -3,0 0,-3 2,-2 18,0');\n    } else if (r && this.block_.outputConnection.check_[0].toUpperCase() == \"BOOLEAN\") {\n      steps.push('l', '-' + r + ',-' + r + ' ' + r + ',-' + r);\n    } else if (r) {\n      steps.push('a', r + ',' + r + ' 0 1,1 0,-' + 2*r);\n    }\n  }\n\n  var firstRow = inputRows[0][0].fieldRow;\n  if (firstRow[0] instanceof Blockly.FieldIcon) {\n    steps.push('a', '19.5,19.5 0, 0,1 0,-35');\n    steps.push('z');\n  } else steps.push('z');\n};\n"
  },
  {
    "path": "extern/blockly/core/blockly.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Core JavaScript library for Blockly.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\n// Top level object for Blockly.\ngoog.provide('Blockly');\n\n// Blockly core dependencies.\ngoog.require('Blockly.Block');\ngoog.require('Blockly.BlockMenu');\ngoog.require('Blockly.FieldIcon');\ngoog.require('Blockly.Connection');\ngoog.require('Blockly.FieldAngle');\ngoog.require('Blockly.FieldCheckbox');\ngoog.require('Blockly.FieldColour');\ngoog.require('Blockly.FieldDropdown');\ngoog.require('Blockly.FieldDropdownDynamic');\ngoog.require('Blockly.FieldImage');\ngoog.require('Blockly.FieldIcon');\ngoog.require('Blockly.FieldTextInput');\ngoog.require('Blockly.FieldKeydownInput');\ngoog.require('Blockly.FieldVariable');\ngoog.require('Blockly.Generator');\ngoog.require('Blockly.Msg');\ngoog.require('Blockly.Procedures');\ngoog.require('Blockly.Realtime');\ngoog.require('Blockly.Toolbox');\ngoog.require('Blockly.WidgetDiv');\ngoog.require('Blockly.Workspace');\ngoog.require('Blockly.inject');\ngoog.require('Blockly.utils');\n\n// Closure dependencies.\ngoog.require('goog.dom');\ngoog.require('goog.color');\ngoog.require('goog.events');\ngoog.require('goog.string');\ngoog.require('goog.ui.ColorPicker');\ngoog.require('goog.ui.tree.TreeControl');\ngoog.require('goog.userAgent');\n\n\n/**\n * Path to Blockly's directory.  Can be relative, absolute, or remote.\n * Used for loading additional resources.\n */\nBlockly.pathToBlockly = './';\n\n/**\n * Required name space for SVG elements.\n * @const\n */\nBlockly.SVG_NS = 'http://www.w3.org/2000/svg';\n/**\n * Required name space for HTML elements.\n * @const\n */\nBlockly.HTML_NS = 'http://www.w3.org/1999/xhtml';\n\n/**\n * The richness of block colours, regardless of the hue.\n * Must be in the range of 0 (inclusive) to 1 (exclusive).\n */\nBlockly.HSV_SATURATION = 0.45;\n/**\ngoog.require('Blockly.FieldKeydownInput');\n * The intensity of block colours, regardless of the hue.\n * Must be in the range of 0 (inclusive) to 1 (exclusive).\n */\nBlockly.HSV_VALUE = 0.65;\n\n/**\n * Convert a hue (HSV model) into an RGB hex triplet.\n * @param {number} hue Hue on a colour wheel (0-360).\n * @return {string} RGB code, e.g. '#5ba65b'.\n */\nBlockly.makeColour = function(colorCode) {\n  if (typeof(colorCode) == \"number\")\n    return goog.color.hsvToHex(colorCode, Blockly.HSV_SATURATION,\n        Blockly.HSV_VALUE * 256);\n  else\n    return colorCode;\n};\n\n/**\n * ENUM for a right-facing value input.  E.g. 'test' or 'return'.\n * @const\n */\nBlockly.INPUT_VALUE = 1;\n/**\n * ENUM for a left-facing value output.  E.g. 'call random'.\n * @const\n */\nBlockly.OUTPUT_VALUE = 2;\n/**\n * ENUM for a down-facing block stack.  E.g. 'then-do' or 'else-do'.\n * @const\n */\nBlockly.NEXT_STATEMENT = 3;\n/**\n * ENUM for an up-facing block stack.  E.g. 'close screen'.\n * @const\n */\nBlockly.PREVIOUS_STATEMENT = 4;\n/**\n * ENUM for an dummy input.  Used to add field(s) with no input.\n * @const\n */\nBlockly.DUMMY_INPUT = 5;\n\n/**\n * ENUM for left alignment.\n * @const\n */\nBlockly.ALIGN_LEFT = -1;\n/**\n * ENUM for centre alignment.\n * @const\n */\nBlockly.ALIGN_CENTRE = 0;\n/**\n * ENUM for right alignment.\n * @const\n */\nBlockly.ALIGN_RIGHT = 1;\n\nBlockly.enableBlockAnimation = !(goog.userAgent.SAFARI && !window.chrome);\n\n/**\n * Lookup table for determining the opposite type of a connection.\n * @const\n */\nBlockly.OPPOSITE_TYPE = [];\nBlockly.OPPOSITE_TYPE[Blockly.INPUT_VALUE] = Blockly.OUTPUT_VALUE;\nBlockly.OPPOSITE_TYPE[Blockly.OUTPUT_VALUE] = Blockly.INPUT_VALUE;\nBlockly.OPPOSITE_TYPE[Blockly.NEXT_STATEMENT] = Blockly.PREVIOUS_STATEMENT;\nBlockly.OPPOSITE_TYPE[Blockly.PREVIOUS_STATEMENT] = Blockly.NEXT_STATEMENT;\n\n/**\n * Database of pre-loaded sounds.\n * @private\n * @const\n */\nBlockly.SOUNDS_ = Object.create(null);\n\n/**\n * Currently activated block.\n * @type {Blockly.Block}\n */\nBlockly.activated = null;\n\n/**\n * Currently selected block.\n * @type {Blockly.Block}\n */\nBlockly.selected = null;\n\n/**\n * Is Blockly in a read-only, non-editable mode?\n * Note that this property may only be set before init is called.\n * It can't be used to dynamically toggle editability on and off.\n */\nBlockly.readOnly = false;\n\n/**\n * Currently highlighted connection (during a drag).\n * @type {Blockly.Connection}\n * @private\n */\nBlockly.highlightedConnection_ = null;\n\n/**\n * Connection on dragged block that matches the highlighted connection.\n * @type {Blockly.Connection}\n * @private\n */\nBlockly.localConnection_ = null;\n\n/**\n * Number of pixels the mouse must move before a drag starts.\n * @const\n */\nBlockly.DRAG_RADIUS = 5;\n\n/**\n * Maximum misalignment between connections for them to snap together.\n * @const\n */\nBlockly.SNAP_RADIUS = 15;\n\n/**\n * Maximum misalignment between connections for them to snap together for Entry workspace.\n * @const\n */\nBlockly.SNAP_RADIUS_ENTRY = 25;\n\n/**\n * Delay in ms between trigger and bumping unconnected block out of alignment.\n * @const\n */\nBlockly.BUMP_DELAY = 250;\n\n/**\n * Number of characters to truncate a collapsed block to.\n * @const\n */\nBlockly.COLLAPSE_CHARS = 30;\n\n/**\n * Length limit of blockly text input view.\n * @const\n */\nBlockly.TEXT_INPUT_MAX_LENGTH = 20;\n\nBlockly.primitiveTypes = ['NUMBER', 'TRUE', 'FALSE',\n  'TEXT', 'FUNCTION_PARAM_BOOLEAN', 'FUNCTION_PARAM_STRING', 'TRUE_UN'];\n\n/**\n * The main workspace (defined by inject.js).\n * @type {Blockly.Workspace}\n */\nBlockly.mainWorkspace = null;\n\n/**\n * Contents of the local clipboard.\n * @type {Element}\n * @private\n */\nBlockly.clipboard_ = null;\n\nBlockly.textLengthCache = {};\n\n/**\n * Returns the dimensions of the current SVG image.\n * @return {!Object} Contains width and height properties.\n */\nBlockly.svgSize = function() {\n  return {width: Blockly.svg.cachedWidth_,\n          height: Blockly.svg.cachedHeight_};\n};\n\n/**\n * Size the SVG image to completely fill its container.  Record both\n * the height/width and the absolute position of the SVG image.\n */\nBlockly.svgResize = function() {\n  var svg = Blockly.svg;\n  var div = svg.parentNode;\n  var width = div.offsetWidth-3;\n  var height = div.offsetHeight;\n  if (svg.cachedWidth_ != width) {\n    svg.setAttribute('width', width + 'px');\n    svg.cachedWidth_ = width;\n  }\n  if (svg.cachedHeight_ != height) {\n    svg.setAttribute('height', height + 'px');\n    svg.cachedHeight_ = height;\n  }\n  // Update the scrollbars (if they exist).\n  if (Blockly.mainWorkspace.scrollbar) {\n    Blockly.mainWorkspace.scrollbar.resize();\n  }\n};\n\n/**\n * Handle a mouse-down on SVG drawing surface.\n * @param {!Event} e Mouse down event.\n * @private\n */\nBlockly.onMouseDown_ = function(e) {\n  Blockly.svgResize();\n  Blockly.terminateDrag_(); // In case mouse-up event was lost.\n  //Blockly.hideChaff();\n  var isTargetSvg = e.target && e.target.nodeName &&\n      e.target.nodeName.toLowerCase() == 'svg';\n  if (!Blockly.readOnly && Blockly.selected && isTargetSvg) {\n    // Clicking on the document clears the selection.\n    Blockly.selected.unselect();\n  }\n  if (Blockly.isRightButton(e)) {\n    // Right-click.\n    if (Blockly.ContextMenu) {\n      Blockly.showContextMenu_(Blockly.mouseToSvg(e));\n    }\n  } else if ((Blockly.readOnly || isTargetSvg) &&\n             Blockly.mainWorkspace.scrollbar) {\n    // If the workspace is editable, only allow dragging when gripping empty\n    // space.  Otherwise, allow dragging when gripping anywhere.\n    Blockly.mainWorkspace.dragMode = true;\n    // Record the current mouse position.\n    Blockly.mainWorkspace.startDragMouseX = e.clientX;\n    Blockly.mainWorkspace.startDragMouseY = e.clientY;\n    Blockly.mainWorkspace.startDragMetrics =\n        Blockly.mainWorkspace.getMetrics();\n    Blockly.mainWorkspace.startScrollX = Blockly.mainWorkspace.scrollX;\n    Blockly.mainWorkspace.startScrollY = Blockly.mainWorkspace.scrollY;\n  }\n};\n\n/**\n * Handle a mouse-up on SVG drawing surface.\n * @param {!Event} e Mouse up event.\n * @private\n */\nBlockly.onMouseUp_ = function(e) {\n  Blockly.setCursorHand_(false);\n  Blockly.mainWorkspace.dragMode = false;\n};\n\n/**\n * Handle a mouse-move on SVG surface.\n * @param {!Event} e Mouse move event.\n * @private\n */\nBlockly.onMouseMove_ = function(e) {\n  var hScroll = Blockly.mainWorkspace.scrollbar.hScroll;\n  var vScroll = Blockly.mainWorkspace.scrollbar.vScroll;\n  hScroll.svgGroup_.setAttribute('opacity', '1');\n  vScroll.svgGroup_.setAttribute('opacity', '1');\n  if (Blockly.mainWorkspace.dragMode) {\n    Blockly.removeAllRanges();\n    var dx = e.clientX - Blockly.mainWorkspace.startDragMouseX;\n    var dy = e.clientY - Blockly.mainWorkspace.startDragMouseY;\n    var metrics = Blockly.mainWorkspace.startDragMetrics;\n    var x = Blockly.mainWorkspace.startScrollX + dx;\n    var y = Blockly.mainWorkspace.startScrollY + dy;\n    x = Math.min(x, -metrics.contentLeft);\n    y = Math.min(y, -metrics.contentTop);\n    x = Math.max(x, metrics.viewWidth - metrics.contentLeft -\n                 metrics.contentWidth);\n    y = Math.max(y, metrics.viewHeight - metrics.contentTop -\n                 metrics.contentHeight);\n\n    // Move the scrollbars and the page will scroll automatically.\n    Blockly.mainWorkspace.scrollbar.set(-x - metrics.contentLeft,\n                                        -y - metrics.contentTop);\n  }\n};\n\n/**\n * Handle a mouse-wheel on SVG drawing surface.\n * @param {!Event} e Mouse move event.\n * @private\n */\nBlockly.onMouseWheel_ = function (e) {\n    e.preventDefault();\n    Blockly.removeAllRanges();\n    Blockly.hideChaff();\n\n    var dx = e.wheelDeltaX || -e.deltaX;\n    var dy = e.wheelDeltaY || -e.deltaY;\n    var metrics = Blockly.mainWorkspace.getMetrics();\n    Blockly.mainWorkspace.startScrollX = Blockly.mainWorkspace.scrollX;\n    Blockly.mainWorkspace.startScrollY = Blockly.mainWorkspace.scrollY;\n    var x = Blockly.mainWorkspace.startScrollX + dx;\n    var y = Blockly.mainWorkspace.startScrollY + dy;\n    x = Math.min(x, -metrics.contentLeft);\n    y = Math.min(y, -metrics.contentTop);\n    x = Math.max(x, metrics.viewWidth - metrics.contentLeft -\n                 metrics.contentWidth);\n    y = Math.max(y, metrics.viewHeight - metrics.contentTop -\n                 metrics.contentHeight);\n\n    // Move the scrollbars and the page will scroll automatically.\n    Blockly.mainWorkspace.scrollbar.set(-x - metrics.contentLeft,\n                                        -y - metrics.contentTop);\n}\n\n/**\n * Handle a mouse-wheel on flyout SVG drawing surface.\n * @param {!Event} e Mouse move event.\n * @private\n */\nBlockly.onMouseWheelFlyout_ = function (e) {\n    e.stopPropagation();\n    e.preventDefault();\n    Blockly.removeAllRanges();\n\n    var scroll = this.scrollbar_;\n    var dy = e.wheelDeltaY || -e.deltaY;\n    var metrics = this.getMetrics_();\n    scroll.startScrollY = parseFloat(this.scrollbar_.svgKnob_.getAttribute('y'));\n\n    var y = parseFloat(-scroll.startScrollY) + dy;\n    y = Math.min(y, -metrics.contentTop);\n    y = Math.max(y, metrics.viewHeight - metrics.contentTop -\n                 metrics.contentHeight);\n\n    scroll.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y',\n                                scroll.constrainKnob_(-y- metrics.contentTop));\n    scroll.onScroll_();\n}\n\n/**\n * Handle a key-down on SVG drawing surface.\n * @param {!Event} e Key down event.\n * @private\n */\nBlockly.onKeyDown_ = function(e) {\n  var block = Blockly.selected;\n  if (Blockly.isTargetInput_(e)) {\n    // When focused on an HTML text input widget, don't trap any keys.\n    return;\n  }\n  // TODO: Add keyboard support for cursoring around the context menu.\n  if (e.keyCode == 27) {\n    // Pressing esc closes the context menu.\n    //Blockly.hideChaff();\n  } else if (e.keyCode == 8 || e.keyCode == 46) {\n    // Delete or backspace.\n    try {\n      if (block && block.isDeletable() && !block.isInFlyout) {\n        Blockly.hideChaff();\n        var blockType = block.type.toUpperCase();\n        if (!(Blockly.primitiveTypes.indexOf(blockType) > -1 &&\n              block.getParent()))\n            block.dispose(true, true);\n            if (typeof(Entry) == \"object\")\n                Entry.dispatchEvent(\"entryBlocklyChanged\");\n      }\n    } finally {\n      // Stop the browser from going back to the previous page.\n      // Use a finally so that any error in delete code above doesn't disappear\n      // from the console when the page rolls back.\n      e.preventDefault();\n    }\n  } else if (e.altKey || e.ctrlKey || e.metaKey) {\n    //target is Blockly mainWorkspace\n    if (block && block.isDeletable() &&\n        (block.workspace == Blockly.mainWorkspace)) {\n      Blockly.hideChaff();\n      if (e.keyCode == 67) {\n        // 'c' for copy.\n        Blockly.copy_(block);\n      } else if (e.keyCode == 88) {\n        // 'x' for cut.\n        Blockly.copy_(block);\n        block.dispose(true, true);\n      }\n    }\n    //target is Entry.Func workspace\n    if (typeof(Entry) == 'object' && Entry.Func && Entry.Func.workspace &&\n        block && block.isDeletable() &&\n        (block.workspace == Entry.Func.workspace)) {\n        Blockly.hideChaff();\n        if (e.keyCode == 67) {\n            // 'c' for copy.\n            Blockly.copy_(block);\n        } else if (e.keyCode == 88) {\n            // 'x' for cut.\n            Blockly.copy_(block);\n            block.dispose(true, true);\n        }\n    }\n    if (e.keyCode == 86) {\n      // 'v' for paste.\n      if (Blockly.clipboard_) {\n          if (!Entry || !Entry.Func || !Entry.Func.workspace || !Entry.Func.workspace.visible ) {\n            Blockly.mainWorkspace.paste(Blockly.clipboard_);\n          }\n          else {\n            var xmlBlock = Blockly.clipboard_;\n            xmlBlock.setAttribute('isForFunc', 'true');\n            Entry.Func.workspace.paste(xmlBlock);\n          }\n      }\n    }\n  }\n};\n\n/**\n * Stop binding to the global mouseup and mousemove events.\n * @private\n */\nBlockly.terminateDrag_ = function() {\n  Blockly.Block.terminateDrag_();\n  Blockly.Flyout.terminateDrag_();\n  if (Blockly.mainWorkspace.blockMenu)\n    Blockly.BlockMenu.terminateDrag_();\n};\n\n/**\n * Copy a block onto the local clipboard.\n * @param {!Blockly.Block} block Block to be copied.\n * @private\n */\nBlockly.copy_ = function(block) {\n  var xmlBlock = Blockly.Xml.blockToDom_(block);\n  //Blockly.Xml.deleteNext(xmlBlock);\n  // Encode start position in XML.\n  var xy = block.getRelativeToSurfaceXY();\n  xmlBlock.setAttribute('x', Blockly.RTL ? -xy.x : xy.x);\n  xmlBlock.setAttribute('y', xy.y);\n  Blockly.clipboard_ = xmlBlock;\n};\n\n/**\n * Show the context menu for the workspace.\n * @param {!Object} xy Coordinates of mouse click, contains x and y properties.\n * @private\n */\nBlockly.showContextMenu_ = function(xy) {\n  if (Blockly.readOnly) {\n    return;\n  }\n  var options = [];\n\n  if (Blockly.collapse) {\n    var hasCollapsedBlocks = false;\n    var hasExpandedBlocks = false;\n    var topBlocks = Blockly.mainWorkspace.getTopBlocks(false);\n    for (var i = 0; i < topBlocks.length; i++) {\n      if (topBlocks[i].isCollapsed()) {\n        hasCollapsedBlocks = true;\n      } else {\n        hasExpandedBlocks = true;\n      }\n    }\n\n    // Option to collapse top blocks.\n    var collapseOption = {enabled: hasExpandedBlocks};\n    collapseOption.text = Blockly.Msg.COLLAPSE_ALL;\n    collapseOption.callback = function() {\n      for (var i = 0; i < topBlocks.length; i++) {\n        topBlocks[i].setCollapsed(true);\n      }\n    };\n    options.push(collapseOption);\n\n    // Option to expand top blocks.\n    var expandOption = {enabled: hasCollapsedBlocks};\n    expandOption.text = Blockly.Msg.EXPAND_ALL;\n    expandOption.callback = function() {\n      for (var i = 0; i < topBlocks.length; i++) {\n        topBlocks[i].setCollapsed(false);\n      }\n    };\n    options.push(expandOption);\n  }\n\n    var pasteOption = {\n        text: Lang.Blocks.Paste_blocks,\n        enabled: true,\n        callback: function() {\n            var xmlBlock = Blockly.clipboard_;\n            if (typeof(Entry) === \"object\" && Entry && Entry.Func && Entry.Func.workspace && Entry.Func.workspace.visible) {\n                xmlBlock.setAttribute('isForFunc', 'true');\n                Entry.Func.workspace.paste(xmlBlock);\n            } else if (typeof(Ntry) === \"object\" && Ntry && Ntry.Func && Ntry.Func.workspace && Ntry.Func.workspace.visible) {\n                xmlBlock.setAttribute('isForFunc', 'true');\n                //Ntry.Func.workspace.paste(xmlBlock);\n            } else {\n                Blockly.mainWorkspace.paste(Blockly.clipboard_);\n            }\n\n            if (typeof(Entry) == \"object\") {\n                Entry.dispatchEvent(\"entryBlocklyChanged\");\n            }\n            /*\n            if (typeof(Ntry) == \"object\") {\n                Ntry.dispatchEvent(\"ntryBlocklyChanged\");\n            }\n            */\n        }\n    }\n    var clearOption = {\n        text: Lang.Blocks.Clear_all_blocks,\n        enabled: true,\n        callback: function() {\n            var total;\n\n            if (typeof(Entry) === \"object\" && Entry && Entry.Func && Entry.Func.workspace && Entry.Func.workspace.visible) {\n                total = Entry.Func.workspace.getAllBlocks();\n            } else if (typeof(Ntry) === \"object\" && Ntry && Ntry.Func && Ntry.Func.workspace && Ntry.Func.workspace.visible) {\n                //total = Ntry.Func.workspace.getAllBlocks();\n            } else {\n                total = Blockly.mainWorkspace.getAllBlocks();\n            }\n\n            for (var i = total.length-1; i >= 0; i--) {\n                if (total[i].deletable_)\n                    total[i].dispose();\n            }\n\n            if (typeof(Entry) == \"object\") {\n              Entry.dispatchEvent(\"entryBlocklyChanged\");\n            }\n            /*\n            if (typeof(Ntry) == \"object\") {\n                Ntry.dispatchEvent(\"ntryBlocklyChanged\");\n            }\n            */\n        }\n    }\n\n    if (!Blockly.clipboard_) {\n        pasteOption.enabled = false;\n    }\n    var cleanUpOption = {\n        text: '코드 정리하기',\n        enabled: true,\n        callback: function() {\n            Blockly.mainWorkspace.organizeBlocks();\n            if (typeof(Entry) == \"object\")\n              Entry.dispatchEvent(\"entryBlocklyChanged\");\n            if (typeof(Ntry) == \"object\")\n              Entry.dispatchEvent(\"ntryBlocklyChanged\");\n        }\n    }\n\n    options.push(pasteOption);\n    options.push(cleanUpOption);\n    options.push(clearOption);\n\n  // Option to get help.\n/*\n  var helpOption = {enabled: false};\n  helpOption.text = Blockly.Msg.HELP;\n  helpOption.callback = function() {};\n  options.push(helpOption);\n*/\n\n  Blockly.ContextMenu.show(xy, options);\n};\n\n/**\n * Cancel the native context menu, unless the focus is on an HTML input widget.\n * @param {!Event} e Mouse down event.\n * @private\n */\nBlockly.onContextMenu_ = function(e) {\n  if (!Blockly.isTargetInput_(e) && Blockly.ContextMenu) {\n    // When focused on an HTML text input widget, don't cancel the context menu.\n    e.preventDefault();\n  }\n};\n\n/**\n * Close tooltips, context menus, dropdown selections, etc.\n * @param {boolean=} opt_allowToolbox If true, don't close the toolbox.\n */\nBlockly.hideChaff = function(opt_allowToolbox) {\n  Blockly.Tooltip && Blockly.Tooltip.hide();\n  Blockly.ContextMenu && Blockly.ContextMenu.hide();\n  Blockly.FieldDropdown && Blockly.FieldDropdown.hide();\n  Blockly.FieldKeydownInput && Blockly.FieldKeydownInput.hide();\n  Blockly.WidgetDiv.hide();\n  if (!opt_allowToolbox &&\n      Blockly.Toolbox.flyout_ && Blockly.Toolbox.flyout_.autoClose) {\n    Blockly.Toolbox.clearSelection();\n  }\n};\n\n/**\n * Deselect any selections on the webpage.\n * Chrome will select text outside the SVG when double-clicking.\n * Deselect this text, so that it doesn't mess up any subsequent drag.\n */\nBlockly.removeAllRanges = function() {\n  if (window.getSelection) {  // W3\n    var sel = window.getSelection();\n    if (sel && sel.removeAllRanges) {\n      sel.removeAllRanges();\n      window.setTimeout(function() {\n          window.getSelection().removeAllRanges();\n        }, 0);\n    }\n  }\n};\n\n/**\n * Is this event targeting a text input widget?\n * @param {!Event} e An event.\n * @return {boolean} True if text input.\n * @private\n */\nBlockly.isTargetInput_ = function(e) {\n  return e.target.type == 'textarea' || e.target.type == 'text';\n};\n\n/**\n * Load an audio file.  Cache it, ready for instantaneous playing.\n * @param {!Array.<string>} filenames List of file types in decreasing order of\n *   preference (i.e. increasing size).  E.g. ['media/go.mp3', 'media/go.wav']\n *   Filenames include path from Blockly's root.  File extensions matter.\n * @param {string} name Name of sound.\n * @private\n */\nBlockly.loadAudio_ = function(filenames, name) {\n  if (!window['Audio'] || !filenames.length) {\n    // No browser support for Audio.\n    return;\n  }\n\n  for (var i = 0; i < filenames.length; i++) {\n    var filename = filenames[i];\n    var path = Blockly.pathToBlockly + filename;\n    var id = filename.match(/\\/([^.]+)./)[1];\n    createjs.Sound.registerSound(path, id, 4);\n    break;\n  }\n  //var sound;\n  //var audioTest = new window['Audio']();\n  //for (var i = 0; i < filenames.length; i++) {\n    //var filename = filenames[i];\n    //var ext = filename.match(/\\.(\\w+)$/);\n    //if (ext && audioTest.canPlayType('audio/' + ext[1])) {\n      //// Found an audio format we can play.\n      //sound = new window['Audio'](Blockly.pathToBlockly + filename);\n      //break;\n    //}\n  //}\n  //// To force the browser to load the sound, play it, but at nearly zero volume.\n  //if (sound && sound.play) {\n    //sound.volume = 0.01;\n    //sound.play();\n    //Blockly.SOUNDS_[name] = sound;\n  //}\n  // To force the browser to load the sound, play it, but at nearly zero volume.\n  //if (sound && sound.play) {\n    //sound.volume = 0.01;\n    //sound.play();\n    //Blockly.SOUNDS_[name] = sound;\n  //}\n};\n\n/**\n * Play an audio file at specified value.  If volume is not specified,\n * use full volume (1).\n * @param {string} name Name of sound.\n * @param {?number} opt_volume Volume of sound (0-1).\n */\nBlockly.playAudio = function(name, opt_volume) {\n  createjs.Sound.play(name);\n  //var sound = Blockly.SOUNDS_[name];\n  //if (sound) {\n    //var mySound;\n    //var ie9 = goog.userAgent.DOCUMENT_MODE &&\n              //goog.userAgent.DOCUMENT_MODE === 9;\n    //if (ie9 || goog.userAgent.IPAD || goog.userAgent.ANDROID) {\n      //// Creating a new audio node causes lag in IE9, Android and iPad. Android\n      //// and IE9 refetch the file from the server, iPad uses a singleton audio\n      //// node which must be deleted and recreated for each new audio tag.\n      //mySound = sound;\n    //} else {\n      //mySound = sound.cloneNode();\n    //}\n    //mySound.volume = (opt_volume === undefined ? 1 : opt_volume);\n    //mySound.play();\n  //}\n};\n\n/**\n * Set the mouse cursor to be either a closed hand or the default.\n * @param {boolean} closed True for closed hand.\n * @private\n */\nBlockly.setCursorHand_ = function(closed) {\n  if (Blockly.readOnly) {\n    return;\n  }\n  /* Hotspot coordinates are baked into the CUR file, but they are still\n     required due to a Chrome bug.\n     http://code.google.com/p/chromium/issues/detail?id=1446 */\n  var cursor = '';\n  if (closed) {\n    cursor = 'url(' + Blockly.pathToBlockly + 'media/handclosed.cur) 7 3, auto';\n  }\n  if (Blockly.selected) {\n    Blockly.selected.getSvgRoot().style.cursor = cursor;\n  }\n  // Set cursor on the SVG surface as well as block so that rapid movements\n  // don't result in cursor changing to an arrow momentarily.\n  Blockly.svg.style.cursor = cursor;\n};\n\n/**\n * Return an object with all the metrics required to size scrollbars for the\n * main workspace.  The following properties are computed:\n * .viewHeight: Height of the visible rectangle,\n * .viewWidth: Width of the visible rectangle,\n * .contentHeight: Height of the contents,\n * .contentWidth: Width of the content,\n * .viewTop: Offset of top edge of visible rectangle from parent,\n * .viewLeft: Offset of left edge of visible rectangle from parent,\n * .contentTop: Offset of the top-most content from the y=0 coordinate,\n * .contentLeft: Offset of the left-most content from the x=0 coordinate.\n * .absoluteTop: Top-edge of view.\n * .absoluteLeft: Left-edge of view.\n * @return {Object} Contains size and position metrics of main workspace.\n * @private\n */\nBlockly.getMainWorkspaceMetrics_ = function() {\n  var svgSize = Blockly.svgSize();\n  svgSize.width -= Blockly.Toolbox.width;  // Zero if no Toolbox.\n  var viewWidth = svgSize.width - Blockly.Scrollbar.scrollbarThickness;\n  var viewHeight = svgSize.height - Blockly.Scrollbar.scrollbarThickness;\n  try {\n    var blockBox = Blockly.mainWorkspace.getCanvas().getBBox();\n  } catch (e) {\n    // Firefox has trouble with hidden elements (Bug 528969).\n    return null;\n  }\n  if (Blockly.mainWorkspace.scrollbar) {\n    // Add a border around the content that is at least half a screenful wide.\n    // Ensure border is wide enough that blocks can scroll over entire screen.\n    var leftEdge = Math.min(blockBox.x - viewWidth / 2,\n                            blockBox.x + blockBox.width - viewWidth);\n    var rightEdge = Math.max(blockBox.x + blockBox.width + viewWidth / 2,\n                             blockBox.x + viewWidth);\n    var topEdge = Math.min(blockBox.y - viewHeight / 2,\n                           blockBox.y + blockBox.height - viewHeight);\n    var bottomEdge = Math.max(blockBox.y + blockBox.height + viewHeight / 2,\n                              blockBox.y + viewHeight);\n  } else {\n    var leftEdge = blockBox.x;\n    var rightEdge = leftEdge + blockBox.width;\n    var topEdge = blockBox.y;\n    var bottomEdge = topEdge + blockBox.height;\n  }\n  var absoluteLeft = Blockly.RTL ? 0 : Blockly.Toolbox.width;\n  var metrics = {\n    viewHeight: svgSize.height,\n    viewWidth: svgSize.width,\n    contentHeight: bottomEdge - topEdge,\n    contentWidth: rightEdge - leftEdge,\n    viewTop: -Blockly.mainWorkspace.scrollY,\n    viewLeft: -Blockly.mainWorkspace.scrollX,\n    contentTop: topEdge,\n    contentLeft: leftEdge,\n    absoluteTop: 0,\n    absoluteLeft: absoluteLeft\n  };\n  return metrics;\n};\n\nBlockly.getGenralWorkspaceMetricsFunc_ = function(workspace) {\n  return function() {\n    var svgSize = Blockly.svgSize();\n    svgSize.width -= Blockly.Toolbox.width;  // Zero if no Toolbox.\n    var viewWidth = svgSize.width - Blockly.Scrollbar.scrollbarThickness;\n    var viewHeight = svgSize.height - Blockly.Scrollbar.scrollbarThickness;\n    try {\n      var blockBox = workspace.getCanvas().getBBox();\n    } catch (e) {\n      // Firefox has trouble with hidden elements (Bug 528969).\n      return null;\n    }\n    if (workspace.scrollbar) {\n      // Add a border around the content that is at least half a screenful wide.\n      // Ensure border is wide enough that blocks can scroll over entire screen.\n      var leftEdge = Math.min(blockBox.x - viewWidth / 2,\n                              blockBox.x + blockBox.width - viewWidth);\n      var rightEdge = Math.max(blockBox.x + blockBox.width + viewWidth / 2,\n                               blockBox.x + viewWidth);\n      var topEdge = Math.min(blockBox.y - viewHeight / 2,\n                             blockBox.y + blockBox.height - viewHeight);\n      var bottomEdge = Math.max(blockBox.y + blockBox.height + viewHeight / 2,\n                                blockBox.y + viewHeight);\n    } else {\n      var leftEdge = blockBox.x;\n      var rightEdge = leftEdge + blockBox.width;\n      var topEdge = blockBox.y;\n      var bottomEdge = topEdge + blockBox.height;\n    }\n    var absoluteLeft = Blockly.RTL ? 0 : Blockly.Toolbox.width;\n    var metrics = {\n      viewHeight: svgSize.height,\n      viewWidth: svgSize.width,\n      contentHeight: bottomEdge - topEdge,\n      contentWidth: rightEdge - leftEdge,\n      viewTop: -workspace.scrollY,\n      viewLeft: -workspace.scrollX,\n      contentTop: topEdge,\n      contentLeft: leftEdge,\n      absoluteTop: 0,\n      absoluteLeft: absoluteLeft\n    };\n    return metrics;\n  }\n};\n\n/**\n * Sets the X/Y translations of the main workspace to match the scrollbars.\n * @param {!Object} xyRatio Contains an x and/or y property which is a float\n *     between 0 and 1 specifying the degree of scrolling.\n * @private\n */\nBlockly.setMainWorkspaceMetrics_ = function(xyRatio) {\n  if (!Blockly.mainWorkspace.scrollbar) {\n    throw 'Attempt to set main workspace scroll without scrollbars.';\n  }\n  var metrics = Blockly.getMainWorkspaceMetrics_();\n  if (goog.isNumber(xyRatio.x)) {\n    Blockly.mainWorkspace.scrollX = -metrics.contentWidth * xyRatio.x -\n        metrics.contentLeft;\n  }\n  if (goog.isNumber(xyRatio.y)) {\n    Blockly.mainWorkspace.scrollY = -metrics.contentHeight * xyRatio.y -\n        metrics.contentTop;\n  }\n  var translation = 'translate(' +\n      (Blockly.mainWorkspace.scrollX + metrics.absoluteLeft) + ',' +\n      (Blockly.mainWorkspace.scrollY + metrics.absoluteTop) + ')';\n  Blockly.mainWorkspace.getCanvas().setAttribute('transform', translation);\n  Blockly.mainWorkspace.getBubbleCanvas().setAttribute('transform',\n                                                       translation);\n};\n\nBlockly.setGeneralWorkspaceMetricsFunc_ = function(workspace) {\n  return function(xyRatio) {\n    if (!workspace.scrollbar) {\n      throw 'Attempt to set main workspace scroll without scrollbars.';\n    }\n    var metrics = Blockly.getGenralWorkspaceMetricsFunc_(workspace)();\n    if (goog.isNumber(xyRatio.x)) {\n      workspace.scrollX = -metrics.contentWidth * xyRatio.x -\n          metrics.contentLeft;\n    }\n    if (goog.isNumber(xyRatio.y)) {\n      workspace.scrollY = -metrics.contentHeight * xyRatio.y -\n          metrics.contentTop;\n    }\n    var translation = 'translate(' +\n        (workspace.scrollX + metrics.absoluteLeft) + ',' +\n        (workspace.scrollY + metrics.absoluteTop) + ')';\n    workspace.getCanvas().setAttribute('transform', translation);\n    workspace.getBubbleCanvas().setAttribute('transform', translation);\n  }\n};\n\n\n/**\n * When something in Blockly's workspace changes, call a function.\n * @param {!Function} func Function to call.\n * @return {!Array.<!Array>} Opaque data that can be passed to\n *     removeChangeListener.\n */\nBlockly.addChangeListener = function(func) {\n  return Blockly.bindEvent_(Blockly.mainWorkspace.getCanvas(),\n                            'blocklyWorkspaceChange', null, func);\n};\n\n/**\n * Stop listening for Blockly's workspace changes.\n * @param {!Array.<!Array>} bindData Opaque data from addChangeListener.\n */\nBlockly.removeChangeListener = function(bindData) {\n  Blockly.unbindEvent_(bindData);\n};\n\n/**\n * Returns the main workspace.\n * @return {!Blockly.Workspace} The main workspace.\n */\nBlockly.getMainWorkspace = function() {\n  return Blockly.mainWorkspace;\n};\n\n// Export symbols that would otherwise be renamed by Closure compiler.\nwindow['Blockly'] = Blockly;\nBlockly['getMainWorkspace'] = Blockly.getMainWorkspace;\nBlockly['addChangeListener'] = Blockly.addChangeListener;\nBlockly['removeChangeListener'] = Blockly.removeChangeListener;\n"
  },
  {
    "path": "extern/blockly/core/blocks.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2013 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Core JavaScript library for Blockly.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\ngoog.require('goog.asserts');\n\n/**\n * Name space for the Blocks singleton.\n * Blocks gets populated in the blocks files, possibly through calls to\n * Blocks.addTemplate().\n */\ngoog.provide('Blockly.Blocks');\n\n/**\n * Create a block template and add it as a field to Blockly.Blocks with the\n * name details.blockName.\n * @param {!Object} details Details about the block that should be created.\n *     The following fields are used:\n *     - blockName {string} The name of the block, which should be unique.\n *     - colour {number} The hue value of the colour to use for the block.\n *       (Blockly.HSV_SATURATION and Blockly.HSV_VALUE are used for saturation\n *       and value, respectively.)\n *     - output {?string|Array.<string>} Output type.  If undefined, there are\n *       assumed to be no outputs.  Otherwise, this is interpreted the same way\n *       as arguments to Blockly.Block.setCheck():\n *       - null: Any type can be produced.\n *       - String: Only the specified type (e.g., 'Number') can be produced.\n *       - Array.<string>: Any of the specified types can be produced.\n *     - message {string} A message suitable for passing as a first argument to\n *       Blockly.Block.interpolateMsg().  Specifically, it should consist of\n *       text to be displayed on the block, optionally interspersed with\n *       references to inputs (one-based indices into the args array) or fields,\n *       such as '%1' for the first element of args.  The creation of dummy\n *       inputs can be forced with a newline (\\n).\n *     - args {Array.<Object>} One or more descriptions of value inputs.\n *       TODO: Add Fields and statement stacks.\n *       Each object in the array can have the following fields:\n *       - name {string} The name of the input.\n *       - type {?number} One of Blockly.INPUT_VALUE, Blockly.NEXT_STATEMENT, or\n *         ??.   If not provided, it is assumed to be Blockly.INPUT_VALUE.\n *       - check {?string|Array.<string>} Input type.  See description of the\n *         output field above.\n *       - align {?number} One of Blockly.ALIGN_LEFT, Blockly.ALIGN_CENTRE, or\n *         Blockly.ALIGN_RIGHT (the default value, if not explicitly provided).\n *     - inline {?boolean}: Whether inputs should be inline (true) or external\n *       (false).  If not explicitly specified, inputs will be inline if message\n *       references, and ends with, a single value input.\n *     - previousStatement {?boolean} Whether there should be a statement\n *       connector on the top of the block.  If not specified, the default\n *       value will be !output.\n *     - nextStatement {?boolean} Whether there should be a statement\n *       connector on the bottom of the block.  If not specified, the default\n *       value will be !output.\n *     - tooltip {?string|Function} Tooltip text or a function on this block\n *       that returns a tooltip string.\n *     - helpUrl {?string|Function} The help URL, or a function on this block\n *       that returns the help URL.\n *     - switchable {?boolean} Whether the block should be switchable between\n *       an expression and statement.  Specifically, if true, the block will\n *       begin as an expression (having an output).  There will be a context\n *       menu option 'Remove output'.  If selected, the output will disappear,\n *       and previous and next statement connectors will appear.  The context\n *       menu option 'Remove output' will be replaced by 'Add Output'.  If\n *       selected, the output will reappear and the statement connectors will\n *       disappear.\n *     - mutationToDomFunc {Function} TODO desc.\n *     - domToMutationFunc {Function} TODO desc.\n *     - customContextMenuFunc {Function} TODO desc.\n *     Additional fields will be ignored.\n */\nBlockly.Blocks.addTemplate = function(details) {\n  // Validate inputs.  TODO: Add more.\n  goog.asserts.assert(details.blockName);\n  goog.asserts.assert(Blockly.Blocks[details.blockName],\n      'Blockly.Blocks already has a field named ', details.blockName);\n  goog.asserts.assert(details.message);\n  goog.asserts.assert(details.colour && typeof details.colour == 'number' &&\n      details.colour >= 0 && details.colour < 360,\n     'details.colour must be a number from 0 to 360 (exclusive)');\n  if (details.output != 'undefined') {\n    goog.asserts.assert(!details.previousStatement,\n        'When details.output is defined, ' +\n        'details.previousStatement must not be true.');\n    goog.asserts.assert(!details.nextStatement,\n        'When details.output is defined, ' +\n        'details.nextStatement must not be true.');\n  }\n\n  // Build up template.\n  var block = {};\n  block.init = function() {\n    var thisBlock = this;\n    // Set basic properties of block.\n    this.setColour(details.colour);\n    this.setHelpUrl(details.helpUrl);\n    if (typeof details.tooltip == 'string') {\n      this.setTooltip(details.tooltip);\n    } else if (typeof details.tooltip == 'function') {\n      this.setTooltip(function() {\n        return details.tooltip(thisBlock);\n      });\n    }\n    // Set output and previous/next connections.\n    if (details.output != 'undefined') {\n      this.setOutput(true, details.output);\n    } else {\n      this.setPreviousStatement(\n          typeof details.previousStatement == 'undefined' ?\n              true : details.previousStatement);\n      this.setNextStatement(\n          typeof details.nextStatement == 'undefined' ?\n              true : details.nextStatement);\n    }\n    // Build up arguments in the format expected by interpolateMsg.\n    var interpArgs = [];\n    interpArgs.push(details.text);\n    if (details.args) {\n      details.args.forEach(function(arg) {\n        goog.asserts.assert(arg.name);\n        goog.asserts.assert(arg.check != 'undefined');\n        if (arg.type == 'undefined' || arg.type == Blockly.INPUT_VALUE) {\n          interpArgs.push([arg.name,\n                           arg.check,\n                           typeof arg.align == 'undefined' ? Blockly.ALIGN_RIGHT\n                               : arg.align]);\n        } else {\n          // TODO: Write code for other input types.\n          goog.asserts.fail('addTemplate() can only handle value inputs.');\n        }\n      });\n    }\n    // Neil, how would you recommend specifying the final dummy alignment?\n    // Should it be a top-level field in details?\n    interpArgs.push(Blockly.ALIGN_RIGHT);\n    if (details.inline) {\n      this.setInlineInputs(details.inline);\n    }\n    Blockly.Block.prototype.interpolateMsg.apply(this, interpArgs);\n  };\n\n  // Create mutationToDom if needed.\n  if (details.switchable) {\n    block.mutationToDom = function() {\n      var container = details.mutationToDomFunc ? details.mutatationToDomFunc()\n          : document.createElement('mutation');\n      container.setAttribute('is_statement', this['isStatement'] || false);\n      return container;\n    };\n  } else {\n    block.mutationToDom = details.mutationToDomFunc;\n  }\n  // TODO: Add domToMutation and customContextMenu.\n\n  // Add new block to Blockly.Blocks.\n  Blockly.Blocks[details.blockName] = block;\n};\n"
  },
  {
    "path": "extern/blockly/core/bubble.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing a UI bubble.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Bubble');\n\ngoog.require('Blockly.Workspace');\n\n\n/**\n * Class for UI bubble.\n * @param {!Blockly.Workspace} workspace The workspace on which to draw the\n *     bubble.\n * @param {!Element} content SVG content for the bubble.\n * @param {Element} shape SVG element to avoid eclipsing.\n * @param {number} anchorX Absolute horizontal position of bubbles anchor point.\n * @param {number} anchorY Absolute vertical position of bubbles anchor point.\n * @param {?number} bubbleWidth Width of bubble, or null if not resizable.\n * @param {?number} bubbleHeight Height of bubble, or null if not resizable.\n * @constructor\n */\nBlockly.Bubble = function(workspace, content, shape,\n                          anchorX, anchorY,\n                          bubbleWidth, bubbleHeight) {\n  var angle = Blockly.Bubble.ARROW_ANGLE;\n  if (Blockly.RTL) {\n    angle = -angle;\n  }\n  this.arrow_radians_ = angle / 360 * Math.PI * 2;\n\n  this.workspace_ = workspace;\n  this.content_ = content;\n  this.shape_ = shape;\n  var canvas = workspace.getBubbleCanvas();\n  canvas.appendChild(this.createDom_(content, !!(bubbleWidth && bubbleHeight)));\n\n  this.setAnchorLocation(anchorX, anchorY);\n  if (!bubbleWidth || !bubbleHeight) {\n    var bBox = /** @type {SVGLocatable} */ (this.content_).getBBox();\n    bubbleWidth = bBox.width + 2 * Blockly.Bubble.BORDER_WIDTH;\n    bubbleHeight = bBox.height + 2 * Blockly.Bubble.BORDER_WIDTH;\n  }\n  this.setBubbleSize(bubbleWidth, bubbleHeight);\n\n  // Render the bubble.\n  this.positionBubble_();\n  this.renderArrow_();\n  this.rendered_ = true;\n\n  if (!Blockly.readOnly) {\n    Blockly.bindEvent_(this.bubbleBack_, 'mousedown', this,\n                       this.bubbleMouseDown_);\n    if (this.resizeGroup_) {\n      Blockly.bindEvent_(this.resizeGroup_, 'mousedown', this,\n                         this.resizeMouseDown_);\n    }\n  }\n};\n\n/**\n * Width of the border around the bubble.\n */\nBlockly.Bubble.BORDER_WIDTH = 6;\n\n/**\n * Determines the thickness of the base of the arrow in relation to the size\n * of the bubble.  Higher numbers result in thinner arrows.\n */\nBlockly.Bubble.ARROW_THICKNESS = 10;\n\n/**\n * The number of degrees that the arrow bends counter-clockwise.\n */\nBlockly.Bubble.ARROW_ANGLE = 20;\n\n/**\n * The sharpness of the arrow's bend.  Higher numbers result in smoother arrows.\n */\nBlockly.Bubble.ARROW_BEND = 4;\n\n/**\n * Distance between arrow point and anchor point.\n */\nBlockly.Bubble.ANCHOR_RADIUS = 8;\n\n/**\n * Wrapper function called when a mouseUp occurs during a drag operation.\n * @type {Array.<!Array>}\n * @private\n */\nBlockly.Bubble.onMouseUpWrapper_ = null;\n\n/**\n * Wrapper function called when a mouseMove occurs during a drag operation.\n * @type {Array.<!Array>}\n * @private\n */\nBlockly.Bubble.onMouseMoveWrapper_ = null;\n\n/**\n * Stop binding to the global mouseup and mousemove events.\n * @private\n */\nBlockly.Bubble.unbindDragEvents_ = function() {\n  if (Blockly.Bubble.onMouseUpWrapper_) {\n    Blockly.unbindEvent_(Blockly.Bubble.onMouseUpWrapper_);\n    Blockly.Bubble.onMouseUpWrapper_ = null;\n  }\n  if (Blockly.Bubble.onMouseMoveWrapper_) {\n    Blockly.unbindEvent_(Blockly.Bubble.onMouseMoveWrapper_);\n    Blockly.Bubble.onMouseMoveWrapper_ = null;\n  }\n};\n\n/**\n * Flag to stop incremental rendering during construction.\n * @private\n */\nBlockly.Bubble.prototype.rendered_ = false;\n\n/**\n * Absolute X coordinate of anchor point.\n * @private\n */\nBlockly.Bubble.prototype.anchorX_ = 0;\n\n/**\n * Absolute Y coordinate of anchor point.\n * @private\n */\nBlockly.Bubble.prototype.anchorY_ = 0;\n\n/**\n * Relative X coordinate of bubble with respect to the anchor's centre.\n * In RTL mode the initial value is negated.\n * @private\n */\nBlockly.Bubble.prototype.relativeLeft_ = 0;\n\n/**\n * Relative Y coordinate of bubble with respect to the anchor's centre.\n * @private\n */\nBlockly.Bubble.prototype.relativeTop_ = 0;\n\n/**\n * Width of bubble.\n * @private\n */\nBlockly.Bubble.prototype.width_ = 0;\n\n/**\n * Height of bubble.\n * @private\n */\nBlockly.Bubble.prototype.height_ = 0;\n\n/**\n * Automatically position and reposition the bubble.\n * @private\n */\nBlockly.Bubble.prototype.autoLayout_ = true;\n\n/**\n * Create the bubble's DOM.\n * @param {!Element} content SVG content for the bubble.\n * @param {boolean} hasResize Add diagonal resize gripper if true.\n * @return {!Element} The bubble's SVG group.\n * @private\n */\nBlockly.Bubble.prototype.createDom_ = function(content, hasResize) {\n  /* Create the bubble.  Here's the markup that will be generated:\n  <g>\n    <g filter=\"url(#blocklyEmboss)\">\n      <path d=\"... Z\" />\n      <rect class=\"blocklyDraggable\" rx=\"8\" ry=\"8\" width=\"180\" height=\"180\"/>\n    </g>\n    <g transform=\"translate(165, 165)\" class=\"blocklyResizeSE\">\n      <polygon points=\"0,15 15,15 15,0\"/>\n      <line class=\"blocklyResizeLine\" x1=\"5\" y1=\"14\" x2=\"14\" y2=\"5\"/>\n      <line class=\"blocklyResizeLine\" x1=\"10\" y1=\"14\" x2=\"14\" y2=\"10\"/>\n    </g>\n    [...content goes here...]\n  </g>\n  */\n  this.bubbleGroup_ = Blockly.createSvgElement('g', {}, null);\n  var bubbleEmboss = Blockly.createSvgElement('g',\n      {'filter': 'url(#blocklyEmboss)'}, this.bubbleGroup_);\n  this.bubbleArrow_ = Blockly.createSvgElement('path', {}, bubbleEmboss);\n  this.bubbleBack_ = Blockly.createSvgElement('rect',\n      {'class': 'blocklyDraggable', 'x': 0, 'y': 0,\n      'rx': Blockly.Bubble.BORDER_WIDTH, 'ry': Blockly.Bubble.BORDER_WIDTH},\n      bubbleEmboss);\n  if (hasResize) {\n    this.resizeGroup_ = Blockly.createSvgElement('g',\n        {'class': Blockly.RTL ? 'blocklyResizeSW' : 'blocklyResizeSE'},\n        this.bubbleGroup_);\n    var resizeSize = 2 * Blockly.Bubble.BORDER_WIDTH;\n    Blockly.createSvgElement('polygon',\n        {'points': '0,x x,x x,0'.replace(/x/g, resizeSize.toString())},\n        this.resizeGroup_);\n    Blockly.createSvgElement('line',\n        {'class': 'blocklyResizeLine',\n        'x1': resizeSize / 3, 'y1': resizeSize - 1,\n        'x2': resizeSize - 1, 'y2': resizeSize / 3}, this.resizeGroup_);\n    Blockly.createSvgElement('line',\n        {'class': 'blocklyResizeLine',\n        'x1': resizeSize * 2 / 3, 'y1': resizeSize - 1,\n        'x2': resizeSize - 1, 'y2': resizeSize * 2 / 3}, this.resizeGroup_);\n  } else {\n    this.resizeGroup_ = null;\n  }\n  this.bubbleGroup_.appendChild(content);\n  return this.bubbleGroup_;\n};\n\n/**\n * Handle a mouse-down on bubble's border.\n * @param {!Event} e Mouse down event.\n * @private\n */\nBlockly.Bubble.prototype.bubbleMouseDown_ = function(e) {\n  this.promote_();\n  Blockly.Bubble.unbindDragEvents_();\n  if (Blockly.isRightButton(e)) {\n    // Right-click.\n    return;\n  } else if (Blockly.isTargetInput_(e)) {\n    // When focused on an HTML text input widget, don't trap any events.\n    return;\n  }\n  // Left-click (or middle click)\n  Blockly.setCursorHand_(true);\n  // Record the starting offset between the current location and the mouse.\n  if (Blockly.RTL) {\n    this.dragDeltaX = this.relativeLeft_ + e.clientX;\n  } else {\n    this.dragDeltaX = this.relativeLeft_ - e.clientX;\n  }\n  this.dragDeltaY = this.relativeTop_ - e.clientY;\n\n  Blockly.Bubble.onMouseUpWrapper_ = Blockly.bindEvent_(document,\n      'mouseup', this, Blockly.Bubble.unbindDragEvents_);\n  Blockly.Bubble.onMouseMoveWrapper_ = Blockly.bindEvent_(document,\n      'mousemove', this, this.bubbleMouseMove_);\n  Blockly.hideChaff();\n  // This event has been handled.  No need to bubble up to the document.\n  e.stopPropagation();\n};\n\n/**\n * Drag this bubble to follow the mouse.\n * @param {!Event} e Mouse move event.\n * @private\n */\nBlockly.Bubble.prototype.bubbleMouseMove_ = function(e) {\n  this.autoLayout_ = false;\n  if (Blockly.RTL) {\n    this.relativeLeft_ = this.dragDeltaX - e.clientX;\n  } else {\n    this.relativeLeft_ = this.dragDeltaX + e.clientX;\n  }\n  this.relativeTop_ = this.dragDeltaY + e.clientY;\n  this.positionBubble_();\n  this.renderArrow_();\n};\n\n/**\n * Handle a mouse-down on bubble's resize corner.\n * @param {!Event} e Mouse down event.\n * @private\n */\nBlockly.Bubble.prototype.resizeMouseDown_ = function(e) {\n  this.promote_();\n  Blockly.Bubble.unbindDragEvents_();\n  if (Blockly.isRightButton(e)) {\n    // Right-click.\n    return;\n  }\n  // Left-click (or middle click)\n  Blockly.setCursorHand_(true);\n  // Record the starting offset between the current location and the mouse.\n  if (Blockly.RTL) {\n    this.resizeDeltaWidth = this.width_ + e.clientX;\n  } else {\n    this.resizeDeltaWidth = this.width_ - e.clientX;\n  }\n  this.resizeDeltaHeight = this.height_ - e.clientY;\n\n  Blockly.Bubble.onMouseUpWrapper_ = Blockly.bindEvent_(document,\n      'mouseup', this, Blockly.Bubble.unbindDragEvents_);\n  Blockly.Bubble.onMouseMoveWrapper_ = Blockly.bindEvent_(document,\n      'mousemove', this, this.resizeMouseMove_);\n  Blockly.hideChaff();\n  // This event has been handled.  No need to bubble up to the document.\n  e.stopPropagation();\n};\n\n/**\n * Resize this bubble to follow the mouse.\n * @param {!Event} e Mouse move event.\n * @private\n */\nBlockly.Bubble.prototype.resizeMouseMove_ = function(e) {\n  this.autoLayout_ = false;\n  var w = this.resizeDeltaWidth;\n  var h = this.resizeDeltaHeight + e.clientY;\n  if (Blockly.RTL) {\n    // RTL drags the bottom-left corner.\n    w -= e.clientX;\n  } else {\n    // LTR drags the bottom-right corner.\n    w += e.clientX;\n  }\n  this.setBubbleSize(w, h);\n  if (Blockly.RTL) {\n    // RTL requires the bubble to move its left edge.\n    this.positionBubble_();\n  }\n};\n\n/**\n * Register a function as a callback event for when the bubble is resized.\n * @param {Object} thisObject The value of 'this' in the callback.\n * @param {!Function} callback The function to call on resize.\n */\nBlockly.Bubble.prototype.registerResizeEvent = function(thisObject, callback) {\n  Blockly.bindEvent_(this.bubbleGroup_, 'resize', thisObject, callback);\n};\n\n/**\n * Move this bubble to the top of the stack.\n * @private\n */\nBlockly.Bubble.prototype.promote_ = function() {\n  var svgGroup = this.bubbleGroup_.parentNode;\n  svgGroup.appendChild(this.bubbleGroup_);\n};\n\n/**\n * Notification that the anchor has moved.\n * Update the arrow and bubble accordingly.\n * @param {number} x Absolute horizontal location.\n * @param {number} y Absolute vertical location.\n */\nBlockly.Bubble.prototype.setAnchorLocation = function(x, y) {\n  this.anchorX_ = x;\n  this.anchorY_ = y;\n  if (this.rendered_) {\n    this.positionBubble_();\n  }\n};\n\n/**\n * Position the bubble so that it does not fall offscreen.\n * @private\n */\nBlockly.Bubble.prototype.layoutBubble_ = function() {\n  // Compute the preferred bubble location.\n  var relativeLeft = -this.width_ / 4;\n  var relativeTop = -this.height_ - Blockly.BlockSvg.MIN_BLOCK_Y;\n  // Prevent the bubble from being offscreen.\n  if (this.workspace_.scrollbar) {\n    // Fetch the workspace's metrics, if they exist.\n    var metrics = this.workspace_.getMetrics();\n    if (this.anchorX_ + relativeLeft <\n        Blockly.BlockSvg.SEP_SPACE_X + metrics.viewLeft) {\n      // Slide the bubble right until it is onscreen.\n      relativeLeft = Blockly.BlockSvg.SEP_SPACE_X + metrics.viewLeft -\n          this.anchorX_;\n    } else if (metrics.viewLeft + metrics.viewWidth <\n        this.anchorX_ + relativeLeft + this.width_ +\n        Blockly.BlockSvg.SEP_SPACE_X +\n        Blockly.Scrollbar.scrollbarThickness) {\n      // Slide the bubble left until it is onscreen.\n      relativeLeft = metrics.viewLeft + metrics.viewWidth - this.anchorX_ -\n          this.width_ - Blockly.BlockSvg.SEP_SPACE_X -\n          Blockly.Scrollbar.scrollbarThickness;\n    }\n    if (this.anchorY_ + relativeTop <\n        Blockly.BlockSvg.SEP_SPACE_Y + metrics.viewTop) {\n      // Slide the bubble below the block.\n      var bBox = /** @type {SVGLocatable} */ (this.shape_).getBBox();\n      relativeTop = bBox.height;\n    }\n  }\n  this.relativeLeft_ = relativeLeft;\n  this.relativeTop_ = relativeTop;\n};\n\n/**\n * Move the bubble to a location relative to the anchor's centre.\n * @private\n */\nBlockly.Bubble.prototype.positionBubble_ = function() {\n  var left;\n  if (Blockly.RTL) {\n    left = this.anchorX_ - this.relativeLeft_ - this.width_;\n  } else {\n    left = this.anchorX_ + this.relativeLeft_;\n  }\n  var top = this.relativeTop_ + this.anchorY_;\n  this.bubbleGroup_.setAttribute('transform',\n      'translate(' + left + ', ' + top + ')');\n};\n\n/**\n * Get the dimensions of this bubble.\n * @return {!Object} Object with width and height properties.\n */\nBlockly.Bubble.prototype.getBubbleSize = function() {\n  return {width: this.width_, height: this.height_};\n};\n\n/**\n * Size this bubble.\n * @param {number} width Width of the bubble.\n * @param {number} height Height of the bubble.\n */\nBlockly.Bubble.prototype.setBubbleSize = function(width, height) {\n  var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH;\n  // Minimum size of a bubble.\n  width = Math.max(width, doubleBorderWidth + 45);\n  height = Math.max(height, doubleBorderWidth + Blockly.BlockSvg.FIELD_HEIGHT);\n  this.width_ = width;\n  this.height_ = height;\n  this.bubbleBack_.setAttribute('width', width);\n  this.bubbleBack_.setAttribute('height', height);\n  if (this.resizeGroup_) {\n    if (Blockly.RTL) {\n      // Mirror the resize group.\n      var resizeSize = 2 * Blockly.Bubble.BORDER_WIDTH;\n      this.resizeGroup_.setAttribute('transform', 'translate(' +\n          resizeSize + ', ' +\n          (height - doubleBorderWidth) + ') scale(-1 1)');\n    } else {\n      this.resizeGroup_.setAttribute('transform', 'translate(' +\n          (width - doubleBorderWidth) + ', ' +\n          (height - doubleBorderWidth) + ')');\n    }\n  }\n  if (this.rendered_) {\n    if (this.autoLayout_) {\n      this.layoutBubble_();\n    }\n    this.positionBubble_();\n    this.renderArrow_();\n  }\n  // Fire an event to allow the contents to resize.\n  Blockly.fireUiEvent(this.bubbleGroup_, 'resize');\n};\n\n/**\n * Draw the arrow between the bubble and the origin.\n * @private\n */\nBlockly.Bubble.prototype.renderArrow_ = function() {\n  var steps = [];\n  // Find the relative coordinates of the center of the bubble.\n  var relBubbleX = this.width_ / 2;\n  var relBubbleY = this.height_ / 2;\n  // Find the relative coordinates of the center of the anchor.\n  var relAnchorX = -this.relativeLeft_;\n  var relAnchorY = -this.relativeTop_;\n  if (relBubbleX == relAnchorX && relBubbleY == relAnchorY) {\n    // Null case.  Bubble is directly on top of the anchor.\n    // Short circuit this rather than wade through divide by zeros.\n    steps.push('M ' + relBubbleX + ',' + relBubbleY);\n  } else {\n    // Compute the angle of the arrow's line.\n    var rise = relAnchorY - relBubbleY;\n    var run = relAnchorX - relBubbleX;\n    if (Blockly.RTL) {\n      run *= -1;\n    }\n    var hypotenuse = Math.sqrt(rise * rise + run * run);\n    var angle = Math.acos(run / hypotenuse);\n    if (rise < 0) {\n      angle = 2 * Math.PI - angle;\n    }\n    // Compute a line perpendicular to the arrow.\n    var rightAngle = angle + Math.PI / 2;\n    if (rightAngle > Math.PI * 2) {\n      rightAngle -= Math.PI * 2;\n    }\n    var rightRise = Math.sin(rightAngle);\n    var rightRun = Math.cos(rightAngle);\n\n    // Calculate the thickness of the base of the arrow.\n    var bubbleSize = this.getBubbleSize();\n    var thickness = (bubbleSize.width + bubbleSize.height) /\n                    Blockly.Bubble.ARROW_THICKNESS;\n    thickness = Math.min(thickness, bubbleSize.width, bubbleSize.height) / 2;\n\n    // Back the tip of the arrow off of the anchor.\n    var backoffRatio = 1 - Blockly.Bubble.ANCHOR_RADIUS / hypotenuse;\n    relAnchorX = relBubbleX + backoffRatio * run;\n    relAnchorY = relBubbleY + backoffRatio * rise;\n\n    // Coordinates for the base of the arrow.\n    var baseX1 = relBubbleX + thickness * rightRun;\n    var baseY1 = relBubbleY + thickness * rightRise;\n    var baseX2 = relBubbleX - thickness * rightRun;\n    var baseY2 = relBubbleY - thickness * rightRise;\n\n    // Distortion to curve the arrow.\n    var swirlAngle = angle + this.arrow_radians_;\n    if (swirlAngle > Math.PI * 2) {\n      swirlAngle -= Math.PI * 2;\n    }\n    var swirlRise = Math.sin(swirlAngle) *\n        hypotenuse / Blockly.Bubble.ARROW_BEND;\n    var swirlRun = Math.cos(swirlAngle) *\n        hypotenuse / Blockly.Bubble.ARROW_BEND;\n\n    steps.push('M' + baseX1 + ',' + baseY1);\n    steps.push('C' + (baseX1 + swirlRun) + ',' + (baseY1 + swirlRise) +\n               ' ' + relAnchorX + ',' + relAnchorY +\n               ' ' + relAnchorX + ',' + relAnchorY);\n    steps.push('C' + relAnchorX + ',' + relAnchorY +\n               ' ' + (baseX2 + swirlRun) + ',' + (baseY2 + swirlRise) +\n               ' ' + baseX2 + ',' + baseY2);\n  }\n  steps.push('z');\n  this.bubbleArrow_.setAttribute('d', steps.join(' '));\n};\n\n/**\n * Change the colour of a bubble.\n * @param {string} hexColour Hex code of colour.\n */\nBlockly.Bubble.prototype.setColour = function(hexColour) {\n  this.bubbleBack_.setAttribute('fill', hexColour);\n  this.bubbleArrow_.setAttribute('fill', hexColour);\n};\n\n/**\n * Dispose of this bubble.\n */\nBlockly.Bubble.prototype.dispose = function() {\n  Blockly.Bubble.unbindDragEvents_();\n  // Dispose of and unlink the bubble.\n  goog.dom.removeNode(this.bubbleGroup_);\n  this.bubbleGroup_ = null;\n  this.workspace_ = null;\n  this.content_ = null;\n  this.shape_ = null;\n};\n"
  },
  {
    "path": "extern/blockly/core/comment.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing a code comment.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Comment');\n\ngoog.require('Blockly.Bubble');\ngoog.require('Blockly.Icon');\n\n\n/**\n * Class for a comment.\n * @param {!Blockly.Block} block The block associated with this comment.\n * @extends {Blockly.Icon}\n * @constructor\n */\nBlockly.Comment = function(block) {\n  Blockly.Comment.superClass_.constructor.call(this, block);\n  this.createIcon_();\n};\ngoog.inherits(Blockly.Comment, Blockly.Icon);\n\n/**\n * Comment text (if bubble is not visible).\n * @private\n */\nBlockly.Comment.prototype.text_ = '';\n\n/**\n * Width of bubble.\n * @private\n */\nBlockly.Comment.prototype.width_ = 160;\n\n/**\n * Height of bubble.\n * @private\n */\nBlockly.Comment.prototype.height_ = 80;\n\n/**\n * Create the icon on the block.\n * @private\n */\nBlockly.Comment.prototype.createIcon_ = function() {\n  Blockly.Icon.prototype.createIcon_.call(this);\n  /* Here's the markup that will be generated:\n  <circle class=\"blocklyIconShield\" r=\"8\" cx=\"8\" cy=\"8\"/>\n  <text class=\"blocklyIconMark\" x=\"8\" y=\"13\">?</text>\n  */\n  var iconShield = Blockly.createSvgElement('circle',\n      {'class': 'blocklyIconShield',\n       'r': Blockly.Icon.RADIUS,\n       'cx': Blockly.Icon.RADIUS,\n       'cy': Blockly.Icon.RADIUS}, this.iconGroup_);\n  this.iconMark_ = Blockly.createSvgElement('text',\n      {'class': 'blocklyIconMark',\n       'x': Blockly.Icon.RADIUS,\n       'y': 2 * Blockly.Icon.RADIUS - 3}, this.iconGroup_);\n  this.iconMark_.appendChild(document.createTextNode('?'));\n};\n\n/**\n * Create the editor for the comment's bubble.\n * @return {!Element} The top-level node of the editor.\n * @private\n */\nBlockly.Comment.prototype.createEditor_ = function() {\n  /* Create the editor.  Here's the markup that will be generated:\n    <foreignObject x=\"8\" y=\"8\" width=\"164\" height=\"164\">\n      <body xmlns=\"http://www.w3.org/1999/xhtml\" class=\"blocklyMinimalBody\">\n        <textarea xmlns=\"http://www.w3.org/1999/xhtml\"\n            class=\"blocklyCommentTextarea\"\n            style=\"height: 164px; width: 164px;\"></textarea>\n      </body>\n    </foreignObject>\n  */\n  this.foreignObject_ = Blockly.createSvgElement('foreignObject',\n      {'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH},\n      null);\n  var body = document.createElementNS(Blockly.HTML_NS, 'body');\n  body.setAttribute('xmlns', Blockly.HTML_NS);\n  body.className = 'blocklyMinimalBody';\n  this.textarea_ = document.createElementNS(Blockly.HTML_NS, 'textarea');\n  this.textarea_.className = 'blocklyCommentTextarea';\n  this.textarea_.setAttribute('dir', Blockly.RTL ? 'RTL' : 'LTR');\n  this.updateEditable();\n  body.appendChild(this.textarea_);\n  this.foreignObject_.appendChild(body);\n  Blockly.bindEvent_(this.textarea_, 'mouseup', this, this.textareaFocus_);\n  return this.foreignObject_;\n};\n\n/**\n * Add or remove editability of the textarea.\n * @override\n */\nBlockly.Comment.prototype.updateEditable = function() {\n  if (this.textarea_) {\n    if (!this.block_.isEditable()) {\n      this.textarea_.setAttribute('disabled', 'disabled');\n      this.textarea_.setAttribute('readonly', 'readonly');\n    } else {\n      this.textarea_.removeAttribute('disabled');\n      this.textarea_.removeAttribute('readonly');\n    }\n  }\n  // Allow the icon to update.\n  Blockly.Icon.prototype.updateEditable.call(this);\n};\n\n/**\n * Callback function triggered when the bubble has resized.\n * Resize the text area accordingly.\n * @private\n */\nBlockly.Comment.prototype.resizeBubble_ = function() {\n  var size = this.bubble_.getBubbleSize();\n  var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH;\n  this.foreignObject_.setAttribute('width', size.width - doubleBorderWidth);\n  this.foreignObject_.setAttribute('height', size.height - doubleBorderWidth);\n  this.textarea_.style.width = (size.width - doubleBorderWidth - 4) + 'px';\n  this.textarea_.style.height = (size.height - doubleBorderWidth - 4) + 'px';\n};\n\n/**\n * Show or hide the comment bubble.\n * @param {boolean} visible True if the bubble should be visible.\n */\nBlockly.Comment.prototype.setVisible = function(visible) {\n  if (visible == this.isVisible()) {\n    // No change.\n    return;\n  }\n  // Save the bubble stats before the visibility switch.\n  var text = this.getText();\n  var size = this.getBubbleSize();\n  if (visible) {\n    // Create the bubble.\n    this.bubble_ = new Blockly.Bubble(\n        /** @type {!Blockly.Workspace} */ (this.block_.workspace),\n        this.createEditor_(), this.block_.svg_.svgGroup_,\n        this.iconX_, this.iconY_,\n        this.width_, this.height_);\n    this.bubble_.registerResizeEvent(this, this.resizeBubble_);\n    this.updateColour();\n    this.text_ = null;\n  } else {\n    // Dispose of the bubble.\n    this.bubble_.dispose();\n    this.bubble_ = null;\n    this.textarea_ = null;\n    this.foreignObject_ = null;\n  }\n  // Restore the bubble stats after the visibility switch.\n  this.setText(text);\n  this.setBubbleSize(size.width, size.height);\n};\n\n/**\n * Bring the comment to the top of the stack when clicked on.\n * @param {!Event} e Mouse up event.\n * @private\n */\nBlockly.Comment.prototype.textareaFocus_ = function(e) {\n  // Ideally this would be hooked to the focus event for the comment.\n  // However doing so in Firefox swallows the cursor for unknown reasons.\n  // So this is hooked to mouseup instead.  No big deal.\n  this.bubble_.promote_();\n  // Since the act of moving this node within the DOM causes a loss of focus,\n  // we need to reapply the focus.\n  this.textarea_.focus();\n};\n\n/**\n * Get the dimensions of this comment's bubble.\n * @return {!Object} Object with width and height properties.\n */\nBlockly.Comment.prototype.getBubbleSize = function() {\n  if (this.isVisible()) {\n    return this.bubble_.getBubbleSize();\n  } else {\n    return {width: this.width_, height: this.height_};\n  }\n};\n\n/**\n * Size this comment's bubble.\n * @param {number} width Width of the bubble.\n * @param {number} height Height of the bubble.\n */\nBlockly.Comment.prototype.setBubbleSize = function(width, height) {\n  if (this.isVisible()) {\n    this.bubble_.setBubbleSize(width, height);\n  } else {\n    this.width_ = width;\n    this.height_ = height;\n  }\n};\n\n/**\n * Returns this comment's text.\n * @return {string} Comment text.\n */\nBlockly.Comment.prototype.getText = function() {\n  return this.isVisible() ? this.textarea_.value : this.text_;\n};\n\n/**\n * Set this comment's text.\n * @param {string} text Comment text.\n */\nBlockly.Comment.prototype.setText = function(text) {\n  if (this.isVisible()) {\n    this.textarea_.value = text;\n  } else {\n    this.text_ = text;\n  }\n};\n\n/**\n * Dispose of this comment.\n */\nBlockly.Comment.prototype.dispose = function() {\n  this.block_.comment = null;\n  Blockly.Icon.prototype.dispose.call(this);\n};\n"
  },
  {
    "path": "extern/blockly/core/connection-animation.js",
    "content": "'use strict';\n\ngoog.provide('Blockly.ConnectionAnimation');\n\ngoog.require('Blockly.Connection');\ngoog.require('goog.Timer');\n\n/**\n * Class for a connection animation between blocks.\n * @param {!Blockly.Block} source The block establishing this connection.\n * @param {number} type The type of the connection.\n * @constructor\n */\nBlockly.ConnectionAnimation = function() {\n};\n\n/**\n * URL of the connection image\n * @type {string}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.IMG_URL_ = 'media/ani.png';\n\n/**\n * Width connection image\n * @type {number}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.IMG_WIDTH_ = 23;\n\n/**\n * Height of the connection image\n * @type {number}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.IMG_HEIGHT_ = 23;\n\n/**\n * The SVG group containing the connection animation\n * @type {Element}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.svgGroup_ = null;\n\n/**\n * The SVG group containing the connection animation\n * @type {Element}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.svgBody_ = null;\n\n\n/**\n * Current scale of the img.\n * @type {number}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.scale_ = 0;\n\n/**\n * Current scale of the img.\n * @type {number}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.current_x_ = 0;\n\n/**\n * Current scale of the img.\n * @type {number}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.current_y_ = 0;\n/**\n * Target scale of the img.\n * @type {number}\n * @private\n */\nBlockly.ConnectionAnimation.prototype.target_scale_ = 0.95;\n\n/**\n * Create the animation img elements.\n * @return {!Element} The anmimation SVG group\n */\nBlockly.ConnectionAnimation.prototype.createDom = function() {\n  this.svgGroup_ = Blockly.createSvgElement('g',\n      {}, null);\n  this.svgBody_ = Blockly.createSvgElement('image',\n      {'width': this.IMG_WIDTH_, 'height': this.IMG_HEIGHT_},\n      this.svgGroup_);\n  this.svgBody_.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',\n      Blockly.pathToBlockly + this.IMG_URL_);\n  this.svgBody_.setAttribute('transform', 'scale(' +\n    this.scale_\n  + ')');\n\n  return this.svgGroup_;\n};\n\n\n/**\n * Initialize the animation image.\n */\nBlockly.ConnectionAnimation.prototype.init = function() {\n    this.hide_();\n};\n\n\n/**\n * Initialize the animation image.\n */\nBlockly.ConnectionAnimation.prototype.hide_ = function () {\n    if (this.scale_ <= 0)\n        return;\n\n    this.scale_ -= 0.1;\n    this.svgBody_.setAttribute('transform', 'scale(' +\n        this.scale_\n    + ')');\n    goog.Timer.callOnce(this.hide_, 5, this);\n};\n\n/**\n * Initialize the animation image.\n */\nBlockly.ConnectionAnimation.prototype.show_ = function (sourceBlock, connection) {\n    if ( sourceBlock ) {\n        var svg = sourceBlock.svg_.getRootElement();\n        this.bbox = svg.getBBox();\n        var xy = Blockly.getSvgXY_(svg);\n        this.blockHeight = sourceBlock.svg_.height + 15;\n        this.current_x_ = xy.x;\n        this.current_y_ = xy.y;\n    }\n    if (connection)\n        this.connection_ = connection;\n    if (this.connection_ != this.connection_.sourceBlock_.outputConnection &&\n        this.connection_ != this.connection_.sourceBlock_.previousConnection &&\n        this.connection_ != this.connection_.sourceBlock_.nextConnection)\n        this.svgGroup_.setAttribute('transform', 'translate(' + (this.current_x_ + Blockly.BlockSvg.NOTCH_WIDTH) + ',' + (this.current_y_ + this.blockHeight) + ')');\n    else\n        this.svgGroup_.setAttribute('transform', 'translate(' + (this.current_x_) + ',' + (this.current_y_ + this.bbox.height) + ')');\n\n    if (this.scale_ >= 1) {\n        this.svgBody_.setAttribute('transform',\n            //'translate(' + (1 - this.target_scale_) * this.current_x_+12 + ','+ (1 - this.target_scale_) + this.current_y_+12 + ') ' +\n            'scale(' + this.target_scale_ + ')'\n        );\n        return;\n    }\n\n    this.scale_ += 0.02;\n    this.svgBody_.setAttribute('transform',\n        //'translate(' + (1 - this.scale_) * this.current_x_ + 12 + ','+ (1 - this.scale_) + this.current_y_ + 12 + ') ' +\n        'scale(' + this.scale_ + ')'\n    );\n    goog.Timer.callOnce(this.show_, 5, this);\n\n};\n\n"
  },
  {
    "path": "extern/blockly/core/connection.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Components for creating connections between blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Connection');\ngoog.provide('Blockly.ConnectionDB');\n\ngoog.require('Blockly.Workspace');\n\n\n/**\n * Class for a connection between blocks.\n * @param {!Blockly.Block} source The block establishing this connection.\n * @param {number} type The type of the connection.\n * @constructor\n */\nBlockly.Connection = function(source, type) {\n  this.sourceBlock_ = source;\n  this.targetConnection = null;\n  this.type = type;\n  this.x_ = 0;\n  this.y_ = 0;\n  this.inDB_ = false;\n  // Shortcut for the databases for this connection's workspace.\n  this.dbList_ = this.sourceBlock_.workspace.connectionDBList;\n};\n\n/**\n * Sever all links to this connection (not including from the source object).\n */\nBlockly.Connection.prototype.dispose = function() {\n  if (this.targetConnection) {\n    throw 'Disconnect connection before disposing of it.';\n  }\n  if (this.inDB_) {\n    this.dbList_[this.type].removeConnection_(this);\n  }\n  this.inDB_ = false;\n  if (Blockly.highlightedConnection_ == this) {\n    Blockly.highlightedConnection_ = null;\n  }\n  if (Blockly.localConnection_ == this) {\n    Blockly.localConnection_ = null;\n  }\n};\n\n/**\n * Does the connection belong to a superior block (higher in the source stack)?\n * @return {boolean} True if connection faces down or right.\n */\nBlockly.Connection.prototype.isSuperior = function() {\n  return this.type == Blockly.INPUT_VALUE ||\n      this.type == Blockly.NEXT_STATEMENT;\n};\n\n/**\n * Connect this connection to another connection.\n * @param {!Blockly.Connection} otherConnection Connection to connect to.\n */\nBlockly.Connection.prototype.connect = function(otherConnection) {\n  if (this.sourceBlock_ == otherConnection.sourceBlock_) {\n    throw 'Attempted to connect a block to itself.';\n  }\n  if (this.sourceBlock_.workspace !== otherConnection.sourceBlock_.workspace) {\n    throw 'Blocks are on different workspaces.';\n  }\n  if (Blockly.OPPOSITE_TYPE[this.type] != otherConnection.type) {\n    throw 'Attempt to connect incompatible types.';\n  }\n  if (this.type == Blockly.INPUT_VALUE || this.type == Blockly.OUTPUT_VALUE) {\n    if (this.targetConnection) {\n      // Can't make a value connection if male block is already connected.\n      throw 'Source connection already connected (value).';\n    } else if (otherConnection.targetConnection) {\n      // Statement blocks may be inserted into the middle of a stack.\n      // If female block is already connected, disconnect and bump the male.\n      var orphanBlock = otherConnection.targetBlock();\n      orphanBlock.setParent(null);\n      if (!orphanBlock.outputConnection) {\n        throw 'Orphan block does not have an output connection.';\n      }\n      // Attempt to reattach the orphan at the end of the newly inserted\n      // block.  Since this block may be a row, walk down to the end.\n      var newBlock = this.sourceBlock_;\n      var connection;\n      while (connection =\n          Blockly.Connection.singleConnection_(\n          /** @type {!Blockly.Block} */ (newBlock), orphanBlock)) {\n        // '=' is intentional in line above.\n        if (connection.targetBlock()) {\n          newBlock = connection.targetBlock();\n        } else {\n          connection.connect(orphanBlock.outputConnection);\n          orphanBlock = null;\n          break;\n        }\n      }\n      if (orphanBlock) {\n        // Unable to reattach orphan.  Bump it off to the side.\n        var blockType = orphanBlock.type.toUpperCase();\n        if (Blockly.primitiveTypes.indexOf(blockType) > -1)\n            orphanBlock.dispose(true, false);\n        else {\n          window.setTimeout(function() {\n                orphanBlock.outputConnection.bumpAwayFrom_(otherConnection);\n              }, Blockly.BUMP_DELAY);\n        }\n        //render whole workspace in order to prevent too much space error\n        if (!newBlock.previousConnection && !newBlock.nextConnection) {\n            window.setTimeout(function() {\n                Blockly.mainWorkspace.render();\n            }, 0);\n        }\n      }\n    }\n  } else {\n    if (this.targetConnection) {\n      throw 'Source connection already connected (block).';\n    } else if (otherConnection.targetConnection) {\n      // Statement blocks may be inserted into the middle of a stack.\n      if (this.type != Blockly.PREVIOUS_STATEMENT) {\n        throw 'Can only do a mid-stack connection with the top of a block.';\n      }\n      // Split the stack.\n      var orphanBlock = otherConnection.targetBlock();\n      orphanBlock.setParent(null);\n      if (!orphanBlock.previousConnection) {\n        throw 'Orphan block does not have a previous connection.';\n      }\n      // Attempt to reattach the orphan at the bottom of the newly inserted\n      // block.  Since this block may be a stack, walk down to the end.\n      var newBlock = this.sourceBlock_;\n      while (newBlock.nextConnection) {\n        if (newBlock.nextConnection.targetConnection) {\n          newBlock = newBlock.nextConnection.targetBlock();\n        } else {\n          newBlock.nextConnection.connect(orphanBlock.previousConnection);\n          orphanBlock = null;\n          break;\n        }\n      }\n      if (orphanBlock) {\n        // Unable to reattach orphan.  Bump it off to the side.\n        window.setTimeout(function() {\n              orphanBlock.previousConnection.bumpAwayFrom_(otherConnection);\n            }, Blockly.BUMP_DELAY);\n      }\n    }\n  }\n\n  // Determine which block is superior (higher in the source stack).\n  var parentBlock, childBlock;\n  if (this.isSuperior()) {\n    // Superior block.\n    parentBlock = this.sourceBlock_;\n    childBlock = otherConnection.sourceBlock_;\n  } else {\n    // Inferior block.\n    parentBlock = otherConnection.sourceBlock_;\n    childBlock = this.sourceBlock_;\n  }\n\n  // Establish the connections.\n  this.targetConnection = otherConnection;\n  otherConnection.targetConnection = this;\n\n  // Demote the inferior block so that one is a child of the superior one.\n  childBlock.setParent(parentBlock);\n\n  if (parentBlock.rendered) {\n    parentBlock.svg_.updateDisabled();\n  }\n  if (childBlock.rendered) {\n    childBlock.svg_.updateDisabled();\n  }\n  if (parentBlock.rendered && childBlock.rendered) {\n    if (this.type == Blockly.NEXT_STATEMENT ||\n        this.type == Blockly.PREVIOUS_STATEMENT) {\n      // Child block may need to square off its corners if it is in a stack.\n      // Rendering a child will render its parent.\n      childBlock.render();\n\n    } else {\n      // Child block does not change shape.  Rendering the parent node will\n      // move its connected children into position.\n      parentBlock.render();\n    }\n  }\n};\n\n/**\n * Does the given block have one and only one connection point that will accept\n * the orphaned block?\n * @param {!Blockly.Block} block The superior block.\n * @param {!Blockly.Block} orphanBlock The inferior block.\n * @return {Blockly.Connection} The suitable connection point on 'block',\n *     or null.\n * @private\n */\nBlockly.Connection.singleConnection_ = function(block, orphanBlock) {\n  var connection = false;\n  for (var x = 0; x < block.inputList.length; x++) {\n    var thisConnection = block.inputList[x].connection;\n    if (thisConnection && thisConnection.type == Blockly.INPUT_VALUE &&\n        orphanBlock.outputConnection.checkType_(thisConnection)) {\n      if (connection) {\n        return null;  // More than one connection.\n      }\n      connection = thisConnection;\n    }\n  }\n  return connection;\n};\n\n/**\n * Disconnect this connection.\n */\nBlockly.Connection.prototype.disconnect = function() {\n  var otherConnection = this.targetConnection;\n  if (!otherConnection) {\n    throw 'Source connection not connected.';\n  } else if (otherConnection.targetConnection != this) {\n    throw 'Target connection not connected to source connection.';\n  }\n  otherConnection.targetConnection = null;\n  this.targetConnection = null;\n\n  var sourceBlock = this.sourceBlock_;\n  if (!sourceBlock.isInFlyout && sourceBlock.isEditing &&\n      //sourceBlock == Blockly.selected  &&\n      sourceBlock.outputConnection instanceof Blockly.Connection) {\n    if (otherConnection.sourceBlock_.outputConnection &&\n      otherConnection.sourceBlock_.outputConnection.check_[0].toUpperCase() == \"PARAM\" &&\n      otherConnection.check_[0].toUpperCase() != \"PARAM\") {\n      var xml = Blockly.Xml.blockToDom_(sourceBlock);\n      var newblock = Blockly.Xml.domToBlock(sourceBlock.workspace, xml);\n      otherConnection.connect(newblock.outputConnection);\n    } else if (otherConnection.check_ &&\n        otherConnection.check_.indexOf('Number') > -1) {\n      var xml = Blockly.Xml.textToDom('<xml><block type=\"number\">' +\n                                      '<field name=\"NUM\">10</field>' +\n                                      '</block></xml>');\n      var newblock = Blockly.Xml.domToBlock(sourceBlock.workspace, xml.childNodes[0]);\n      otherConnection.connect(newblock.outputConnection);\n    } else if (otherConnection.check_ &&\n        otherConnection.check_.indexOf('String') > -1) {\n      var xml = Blockly.Xml.textToDom('<xml><block type=\"text\">' +\n                                      '<field name=\"NAME\">문자</field>' +\n                                      '</block></xml>');\n      var newblock = Blockly.Xml.domToBlock(sourceBlock.workspace, xml.childNodes[0]);\n      otherConnection.connect(newblock.outputConnection);\n    } else if (otherConnection.check_ &&\n        otherConnection.check_.indexOf('Boolean') > -1) {\n      var xml = Blockly.Xml.textToDom('<xml><block type=\"True\">' +\n                                      '</block></xml>');\n      var newblock = Blockly.Xml.domToBlock(sourceBlock.workspace, xml.childNodes[0]);\n      otherConnection.connect(newblock.outputConnection);\n    }\n    sourceBlock.isDrag = false;\n    otherConnection.sourceBlock_.isDrag = false;\n  }\n\n  // Rerender the parent so that it may reflow.\n  var parentBlock, childBlock;\n  if (this.isSuperior()) {\n    // Superior block.\n    parentBlock = this.sourceBlock_;\n    childBlock = otherConnection.sourceBlock_;\n  } else {\n    // Inferior block.\n    parentBlock = otherConnection.sourceBlock_;\n    childBlock = this.sourceBlock_;\n  }\n  if (parentBlock.rendered) {\n    parentBlock.render();\n  }\n  if (childBlock.rendered) {\n    childBlock.svg_.updateDisabled();\n    childBlock.render();\n  }\n};\n\n/**\n * Returns the block that this connection connects to.\n * @return {Blockly.Block} The connected block or null if none is connected.\n */\nBlockly.Connection.prototype.targetBlock = function() {\n  if (this.targetConnection) {\n    return this.targetConnection.sourceBlock_;\n  }\n  return null;\n};\n\n/**\n * Move the block(s) belonging to the connection to a point where they don't\n * visually interfere with the specified connection.\n * @param {!Blockly.Connection} staticConnection The connection to move away\n *     from.\n * @private\n */\nBlockly.Connection.prototype.bumpAwayFrom_ = function(staticConnection) {\n  if (Blockly.Block.dragMode_ != 0) {\n    // Don't move blocks around while the user is doing the same.\n    return;\n  }\n  // Move the root block.\n  var rootBlock = this.sourceBlock_.getRootBlock();\n  if (rootBlock.isInFlyout) {\n    // Don't move blocks around in a flyout.\n    return;\n  }\n  var reverse = false;\n  if (!rootBlock.isMovable()) {\n    // Can't bump an uneditable block away.\n    // Check to see if the other block is movable.\n    rootBlock = staticConnection.sourceBlock_.getRootBlock();\n    if (!rootBlock.isMovable()) {\n      return;\n    }\n    // Swap the connections and move the 'static' connection instead.\n    staticConnection = this;\n    reverse = true;\n  }\n  // Raise it to the top for extra visibility.\n  var rootSvg = rootBlock.getSvgRoot();\n  rootSvg.parentNode.appendChild(rootSvg);\n  var dx = (staticConnection.x_ + Blockly.SNAP_RADIUS) - this.x_;\n  var dy = (staticConnection.y_ + Blockly.SNAP_RADIUS * 2) - this.y_;\n  if (reverse) {\n    // When reversing a bump due to an uneditable block, bump up.\n    dy = -dy;\n  }\n  if (Blockly.RTL) {\n    dx = -dx;\n  }\n  rootBlock.moveBy(dx, dy);\n};\n\n/**\n * Change the connection's coordinates.\n * @param {number} x New absolute x coordinate.\n * @param {number} y New absolute y coordinate.\n */\nBlockly.Connection.prototype.moveTo = function(x, y) {\n  // Remove it from its old location in the database (if already present)\n  if (this.inDB_) {\n    this.dbList_[this.type].removeConnection_(this);\n  }\n  this.x_ = x;\n  this.y_ = y;\n  // Insert it into its new location in the database.\n  this.dbList_[this.type].addConnection_(this);\n};\n\n/**\n * Change the connection's coordinates.\n * @param {number} dx Change to x coordinate.\n * @param {number} dy Change to y coordinate.\n */\nBlockly.Connection.prototype.moveBy = function(dx, dy) {\n  this.moveTo(this.x_ + dx, this.y_ + dy);\n};\n\n/**\n * Add highlighting around this connection.\n */\nBlockly.Connection.prototype.highlight = function() {\n  var steps;\n  var xy = this.sourceBlock_.getRelativeToSurfaceXY();\n  var x = this.x_ - xy.x;\n  var y = this.y_ - xy.y;\n  if (this.type == Blockly.INPUT_VALUE || this.type == Blockly.OUTPUT_VALUE) {\n    var inputType = this.check_ ? this.check_[0] : \"null\";\n    if (inputType.toUpperCase() == \"PARAM\") {\n      var targetChecker = this.sourceBlock_.outputConnection;\n      if (targetChecker) {\n        steps = 'M -20,-2 l 2,2 0,3 4,0 0,12 -4,0 0,3 -2,2';\n      } else\n        steps = 'M -20,3 l -2,2 0,3 4,0 0,12 -4,0 0,3 2,2';\n    } else if (inputType.toUpperCase() == \"BOOLEAN\") {\n      var targetChecker = this.targetConnection && this.targetConnection.sourceBlock_;\n      if (targetChecker) {\n        var targetSvg = this.targetConnection.sourceBlock_.svg_.\n          svgPathLight_.getAttribute('d').split('z')[0];\n        steps = targetSvg + 'z';\n      } else\n        steps = 'M 16,0 h -20 l -11,11 11,11.5 h 20' +\n                'l 11,-11 -11,-11 z';\n    } else {\n      var targetChecker = this.targetConnection && this.targetConnection.sourceBlock_;\n      if (targetChecker) {\n        var targetSvg = this.targetConnection.sourceBlock_.svg_.\n          svgPathLight_.getAttribute('d').split('z')[0];\n\n        steps = targetSvg + 'z';\n      } else\n        steps = 'M 10,0 h -10 a 12,9.9 0 0,0 0,19.5 h 10' +\n                'a 11,9.9 0 0,0 0,-19.5 z';\n    }\n    Blockly.Connection.highlightedPath_ = Blockly.createSvgElement('path',\n        {'class': 'blocklyHighlightedConnectionPathInline',\n         'd': steps,\n         transform: 'translate(' + x + ', ' + y + ')'},\n        this.sourceBlock_.getSvgRoot());\n  } else {\n    if (Blockly.RTL) {\n      steps = 'm 20,0 h -5 l -6,4 -3,0 -6,-4 h -5';\n    } else {\n      steps = 'm -15,0 l 7,8 7,-8';\n    }\n\n    Blockly.Connection.highlightedPath_ = Blockly.createSvgElement('path',\n        {'class': 'blocklyHighlightedConnectionPath',\n         'd': steps,\n         transform: 'translate(' + x + ', ' + y + ')'},\n        this.sourceBlock_.getSvgRoot());\n\n  }\n};\n\n/**\n * Remove the highlighting around this connection.\n */\nBlockly.Connection.prototype.unhighlight = function() {\n  goog.dom.removeNode(Blockly.Connection.highlightedPath_);\n  delete Blockly.Connection.highlightedPath_;\n};\n\n/**\n * Move the blocks on either side of this connection right next to each other.\n * @private\n */\nBlockly.Connection.prototype.tighten_ = function() {\n  var dx = Math.round(this.targetConnection.x_ - this.x_);\n  var dy = Math.round(this.targetConnection.y_ - this.y_);\n  if (dx != 0 || dy != 0) {\n    var block = this.targetBlock();\n    var svgRoot = block.getSvgRoot();\n    if (!svgRoot) {\n      throw 'block is not rendered.';\n    }\n    var xy = Blockly.getRelativeXY_(svgRoot);\n    block.getSvgRoot().setAttribute('transform',\n        'translate(' + (xy.x - dx) + ', ' + (xy.y - dy) + ')');\n    block.moveConnections_(-dx, -dy);\n  }\n};\n\n/**\n * Find the closest compatible connection to this connection.\n * @param {number} maxLimit The maximum radius to another connection.\n * @param {number} dx Horizontal offset between this connection's location\n *     in the database and the current location (as a result of dragging).\n * @param {number} dy Vertical offset between this connection's location\n *     in the database and the current location (as a result of dragging).\n * @return {!Object} Contains two properties: 'connection' which is either\n *     another connection or null, and 'radius' which is the distance.\n */\nBlockly.Connection.prototype.closest = function(maxLimit, dx, dy) {\n  if (this.targetConnection) {\n    // Don't offer to connect to a connection that's already connected.\n    return {connection: null, radius: maxLimit};\n  }\n  // Determine the opposite type of connection.\n  var oppositeType = Blockly.OPPOSITE_TYPE[this.type];\n  var db = this.dbList_[oppositeType];\n\n  // Since this connection is probably being dragged, add the delta.\n  var currentX = this.x_ + dx;\n  var currentY = this.y_ + dy;\n\n  // Binary search to find the closest y location.\n  var pointerMin = 0;\n  var pointerMax = db.length - 2;\n  var pointerMid = pointerMax;\n  while (pointerMin < pointerMid) {\n    if (db[pointerMid].y_ < currentY) {\n      pointerMin = pointerMid;\n    } else {\n      pointerMax = pointerMid;\n    }\n    pointerMid = Math.floor((pointerMin + pointerMax) / 2);\n  }\n\n  // Walk forward and back on the y axis looking for the closest x,y point.\n  pointerMin = pointerMid;\n  pointerMax = pointerMid;\n  var closestConnection = null;\n  var sourceBlock = this.sourceBlock_;\n  var thisConnection = this;\n  if (db.length) {\n    while (pointerMin >= 0 && checkConnection_(pointerMin)) {\n      pointerMin--;\n    }\n    do {\n      pointerMax++;\n    } while (pointerMax < db.length && checkConnection_(pointerMax));\n  }\n\n  /**\n   * Computes if the current connection is within the allowed radius of another\n   * connection.\n   * This function is a closure and has access to outside variables.\n   * @param {number} yIndex The other connection's index in the database.\n   * @return {boolean} True if the search needs to continue: either the current\n   *     connection's vertical distance from the other connection is less than\n   *     the allowed radius, or if the connection is not compatible.\n   */\n  function checkConnection_(yIndex) {\n    var connection = db[yIndex];\n    if (connection.type == Blockly.OUTPUT_VALUE ||\n        connection.type == Blockly.PREVIOUS_STATEMENT) {\n      // Don't offer to connect an already connected left (male) value plug to\n      // an available right (female) value plug.  Don't offer to connect the\n      // bottom of a statement block to one that's already connected.\n      if (connection.targetConnection) {\n        return true;\n      }\n    }\n    // Offering to connect the top of a statement block to an already connected\n    // connection is ok, we'll just insert it into the stack.\n    // Offering to connect the left (male) of a value block to an already\n    // connected value pair is ok, we'll splice it in.\n\n    // Do type checking.\n    if (!thisConnection.checkType_(connection)) {\n      return true;\n    }\n\n    // Don't let blocks try to connect to themselves or ones they nest.\n    var targetSourceBlock = connection.sourceBlock_;\n    do {\n      if (sourceBlock == targetSourceBlock) {\n        return true;\n      }\n      targetSourceBlock = targetSourceBlock.getParent();\n    } while (targetSourceBlock);\n\n    var dx = currentX - db[yIndex].x_;\n    var dy = currentY - db[yIndex].y_;\n    var r = Math.sqrt(dx * dx + dy * dy);\n    if (r <= maxLimit) {\n      closestConnection = db[yIndex];\n      maxLimit = r;\n    }\n    return dy < maxLimit;\n  }\n  return {connection: closestConnection, radius: maxLimit};\n};\n\n/**\n * Is this connection compatible with another connection with respect to the\n * value type system.  E.g. square_root(\"Hello\") is not compatible.\n * @param {!Blockly.Connection} otherConnection Connection to compare against.\n * @return {boolean} True if the connections share a type.\n * @private\n */\nBlockly.Connection.prototype.checkType_ = function(otherConnection) {\n  if (this.sourceBlock_.isInFlyout || otherConnection.sourceBlock_.isInFlyout)\n    return false;\n  if (!this.check_ || !otherConnection.check_) {\n    // One or both sides are promiscuous enough that anything will fit.\n    return true;\n  }\n  // Find any intersection in the check lists.\n  for (var x = 0; x < this.check_.length; x++) {\n    if (otherConnection.check_.indexOf(this.check_[x]) != -1) {\n      return true;\n    }\n  }\n  // No intersection.\n  return false;\n};\n\n/**\n * Change a connection's compatibility.\n * @param {*} check Compatible value type or list of value types.\n *     Null if all types are compatible.\n * @return {!Blockly.Connection} The connection being modified\n *     (to allow chaining).\n */\nBlockly.Connection.prototype.setCheck = function(check) {\n  if (check) {\n    // Ensure that check is in an array.\n    if (!(check instanceof Array)) {\n      check = [check];\n    }\n    this.check_ = check;\n    // The new value type may not be compatible with the existing connection.\n    if (this.targetConnection && !this.checkType_(this.targetConnection)) {\n      if (this.isSuperior()) {\n        this.targetBlock().setParent(null);\n      } else {\n        this.sourceBlock_.setParent(null);\n      }\n      // Bump away.\n      this.sourceBlock_.bumpNeighbours_();\n    }\n  } else {\n    this.check_ = null;\n  }\n  return this;\n};\n\n/**\n * Find all nearby compatible connections to this connection.\n * Type checking does not apply, since this function is used for bumping.\n * @param {number} maxLimit The maximum radius to another connection.\n * @return {!Array.<Blockly.Connection>} List of connections.\n * @private\n */\nBlockly.Connection.prototype.neighbours_ = function(maxLimit) {\n  // Determine the opposite type of connection.\n  var oppositeType = Blockly.OPPOSITE_TYPE[this.type];\n  var db = this.dbList_[oppositeType];\n\n  var currentX = this.x_;\n  var currentY = this.y_;\n\n  // Binary search to find the closest y location.\n  var pointerMin = 0;\n  var pointerMax = db.length - 2;\n  var pointerMid = pointerMax;\n  while (pointerMin < pointerMid) {\n    if (db[pointerMid].y_ < currentY) {\n      pointerMin = pointerMid;\n    } else {\n      pointerMax = pointerMid;\n    }\n    pointerMid = Math.floor((pointerMin + pointerMax) / 2);\n  }\n\n  // Walk forward and back on the y axis looking for the closest x,y point.\n  pointerMin = pointerMid;\n  pointerMax = pointerMid;\n  var neighbours = [];\n  var sourceBlock = this.sourceBlock_;\n  if (db.length) {\n    while (pointerMin >= 0 && checkConnection_(pointerMin)) {\n      pointerMin--;\n    }\n    do {\n      pointerMax++;\n    } while (pointerMax < db.length && checkConnection_(pointerMax));\n  }\n\n  /**\n   * Computes if the current connection is within the allowed radius of another\n   * connection.\n   * This function is a closure and has access to outside variables.\n   * @param {number} yIndex The other connection's index in the database.\n   * @return {boolean} True if the current connection's vertical distance from\n   *     the other connection is less than the allowed radius.\n   */\n  function checkConnection_(yIndex) {\n    var dx = currentX - db[yIndex].x_;\n    var dy = currentY - db[yIndex].y_;\n    var r = Math.sqrt(dx * dx + dy * dy);\n    if (r <= maxLimit) {\n      neighbours.push(db[yIndex]);\n    }\n    return dy < maxLimit;\n  }\n  return neighbours;\n};\n\n/**\n * Hide this connection, as well as all down-stream connections on any block\n * attached to this connection.  This happens when a block is collapsed.\n * Also hides down-stream comments.\n */\nBlockly.Connection.prototype.hideAll = function() {\n  if (this.inDB_) {\n    this.dbList_[this.type].removeConnection_(this);\n  }\n  if (this.targetConnection) {\n    var blocks = this.targetBlock().getDescendants();\n    for (var b = 0; b < blocks.length; b++) {\n      var block = blocks[b];\n      // Hide all connections of all children.\n      var connections = block.getConnections_(true);\n      for (var c = 0; c < connections.length; c++) {\n        var connection = connections[c];\n        if (connection.inDB_) {\n          this.dbList_[connection.type].removeConnection_(connection);\n        }\n      }\n      // Close all bubbles of all children.\n      var icons = block.getIcons();\n      for (var x = 0; x < icons.length; x++) {\n        icons[x].setVisible(false);\n      }\n    }\n  }\n};\n\n/**\n * Unhide this connection, as well as all down-stream connections on any block\n * attached to this connection.  This happens when a block is expanded.\n * Also unhides down-stream comments.\n * @return {!Array.<!Blockly.Block>} List of blocks to render.\n */\nBlockly.Connection.prototype.unhideAll = function() {\n  if (!this.inDB_) {\n    this.dbList_[this.type].addConnection_(this);\n  }\n  // All blocks that need unhiding must be unhidden before any rendering takes\n  // place, since rendering requires knowing the dimensions of lower blocks.\n  // Also, since rendering a block renders all its parents, we only need to\n  // render the leaf nodes.\n  var renderList = [];\n  if (this.type != Blockly.INPUT_VALUE && this.type != Blockly.NEXT_STATEMENT) {\n    // Only spider down.\n    return renderList;\n  }\n  var block = this.targetBlock();\n  if (block) {\n    var connections;\n    if (block.isCollapsed()) {\n      // This block should only be partially revealed since it is collapsed.\n      connections = [];\n      block.outputConnection && connections.push(block.outputConnection);\n      block.nextConnection && connections.push(block.nextConnection);\n      block.previousConnection && connections.push(block.previousConnection);\n    } else {\n      // Show all connections of this block.\n      connections = block.getConnections_(true);\n    }\n    for (var c = 0; c < connections.length; c++) {\n      renderList = renderList.concat(connections[c].unhideAll());\n    }\n    if (renderList.length == 0) {\n      // Leaf block.\n      renderList[0] = block;\n    }\n  }\n  return renderList;\n};\n\n\n/**\n * Database of connections.\n * Connections are stored in order of their vertical component.  This way\n * connections in an area may be looked up quickly using a binary search.\n * @constructor\n */\nBlockly.ConnectionDB = function() {\n};\n\nBlockly.ConnectionDB.prototype = new Array();\n/**\n * Don't inherit the constructor from Array.\n * @type {!Function}\n */\nBlockly.ConnectionDB.constructor = Blockly.ConnectionDB;\n\n/**\n * Add a connection to the database.  Must not already exist in DB.\n * @param {!Blockly.Connection} connection The connection to be added.\n * @private\n */\nBlockly.ConnectionDB.prototype.addConnection_ = function(connection) {\n  if (connection.inDB_) {\n    throw 'Connection already in database.';\n  }\n  // Insert connection using binary search.\n  var pointerMin = 0;\n  var pointerMax = this.length;\n  while (pointerMin < pointerMax) {\n    var pointerMid = Math.floor((pointerMin + pointerMax) / 2);\n    if (this[pointerMid].y_ < connection.y_) {\n      pointerMin = pointerMid + 1;\n    } else if (this[pointerMid].y_ > connection.y_) {\n      pointerMax = pointerMid;\n    } else {\n      pointerMin = pointerMid;\n      break;\n    }\n  }\n  this.splice(pointerMin, 0, connection);\n  connection.inDB_ = true;\n};\n\n/**\n * Remove a connection from the database.  Must already exist in DB.\n * @param {!Blockly.Connection} connection The connection to be removed.\n * @private\n */\nBlockly.ConnectionDB.prototype.removeConnection_ = function(connection) {\n  if (!connection.inDB_) {\n    throw 'Connection not in database.';\n  }\n  connection.inDB_ = false;\n  // Find the connection using a binary search.\n  var pointerMin = 0;\n  var pointerMax = this.length - 2;\n  var pointerMid = pointerMax;\n  while (pointerMin < pointerMid) {\n    if (this[pointerMid].y_ < connection.y_) {\n      pointerMin = pointerMid;\n    } else {\n      pointerMax = pointerMid;\n    }\n    pointerMid = Math.floor((pointerMin + pointerMax) / 2);\n  }\n\n  // Walk forward and back on the y axis looking for the connection.\n  // When found, splice it out of the array.\n  pointerMin = pointerMid;\n  pointerMax = pointerMid;\n  while (pointerMin >= 0 && this[pointerMin].y_ == connection.y_) {\n    if (this[pointerMin] == connection) {\n      this.splice(pointerMin, 1);\n      return;\n    }\n    pointerMin--;\n  }\n  do {\n    if (this[pointerMax] == connection) {\n      this.splice(pointerMax, 1);\n      return;\n    }\n    pointerMax++;\n  } while (pointerMax < this.length &&\n           this[pointerMax].y_ == connection.y_);\n  throw 'Unable to find connection in connectionDB.';\n};\n\n/**\n * Initialize a set of connection DBs for a specified workspace.\n * @param {!Blockly.Workspace} workspace The workspace this DB is for.\n */\nBlockly.ConnectionDB.init = function(workspace) {\n  // Create four databases, one for each connection type.\n  var dbList = [];\n  dbList[Blockly.INPUT_VALUE] = new Blockly.ConnectionDB();\n  dbList[Blockly.OUTPUT_VALUE] = new Blockly.ConnectionDB();\n  dbList[Blockly.NEXT_STATEMENT] = new Blockly.ConnectionDB();\n  dbList[Blockly.PREVIOUS_STATEMENT] = new Blockly.ConnectionDB();\n  workspace.connectionDBList = dbList;\n};\n"
  },
  {
    "path": "extern/blockly/core/contextmenu.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Functionality for the right-click context menus.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.ContextMenu');\n\n\n/**\n * Horizontal padding on either side of each option.\n */\nBlockly.ContextMenu.X_PADDING = 20;\n\n/**\n * Vertical height of each option.\n */\nBlockly.ContextMenu.Y_HEIGHT = 20;\n\n/**\n * Is a context menu currently showing?\n */\nBlockly.ContextMenu.visible = false;\n\n/**\n * Creates the context menu's DOM.  Only needs to be called once.\n * @return {!SVGGElement} The context menu's SVG group.\n */\nBlockly.ContextMenu.createDom = function() {\n  /*\n  <g class=\"blocklyHidden\">\n    <rect class=\"blocklyContextMenuShadow\" x=\"2\" y=\"-2\" rx=\"4\" ry=\"4\"/>\n    <rect class=\"blocklyContextMenuBackground\" y=\"-4\" rx=\"4\" ry=\"4\"/>\n    <g class=\"blocklyContextMenuOptions\">\n    </g>\n  </g>\n  */\n  var svgGroup = /** @type {!SVGGElement} */ (\n      Blockly.createSvgElement('g', {'class': 'blocklyHidden'}, null));\n  Blockly.ContextMenu.svgGroup = svgGroup;\n  Blockly.ContextMenu.svgShadow = Blockly.createSvgElement('rect',\n      {'class': 'blocklyContextMenuShadow',\n      'x': 2, 'y': -2}, svgGroup);\n  Blockly.ContextMenu.svgBackground = Blockly.createSvgElement('rect',\n      {'class': 'blocklyContextMenuBackground',\n      'y': -4}, svgGroup);\n  Blockly.ContextMenu.svgOptions = Blockly.createSvgElement('g',\n      {'class': 'blocklyContextMenuOptions'}, svgGroup);\n  Blockly.contextMenu = svgGroup;\n  return svgGroup;\n};\n\n/**\n * Construct the menu based on the list of options and show the menu.\n * @param {!Object} xy Coordinates of anchor point, contains x and y properties.\n * @param {!Array.<Object>} options Array of menu options.\n */\nBlockly.ContextMenu.show = function(xy, options) {\n  if (!options.length) {\n    Blockly.ContextMenu.hide();\n    return;\n  }\n  /* Here's what one option object looks like:\n    {text: 'Make It So',\n     enabled: true,\n     callback: Blockly.MakeItSo}\n  */\n  // Erase all existing options.\n  goog.dom.removeChildren(Blockly.ContextMenu.svgOptions);\n  /* Here's the SVG we want for each option:\n    <g class=\"blocklyMenuDiv\" transform=\"translate(0, 0)\">\n      <rect width=\"100\" height=\"20\"/>\n      <text class=\"blocklyMenuText\" x=\"20\" y=\"15\">Make It So</text>\n    </g>\n  */\n  // The menu must be made visible early since otherwise BBox and\n  // getComputedTextLength will return 0.\n  Blockly.ContextMenu.svgGroup.style.display = 'block';\n  var maxWidth = 0;\n  var resizeList = [Blockly.ContextMenu.svgBackground,\n                    Blockly.ContextMenu.svgShadow];\n  for (var x = 0, option; option = options[x]; x++) {\n    var gElement = Blockly.ContextMenu.optionToDom(option.text);\n    var rectElement = /** @type {SVGRectElement} */ (gElement.firstChild);\n    var textElement = /** @type {SVGTextElement} */ (gElement.lastChild);\n    Blockly.ContextMenu.svgOptions.appendChild(gElement);\n\n    gElement.setAttribute('transform',\n        'translate(0, ' + (x * Blockly.ContextMenu.Y_HEIGHT) + ')');\n    resizeList.push(rectElement);\n    Blockly.bindEvent_(gElement, 'mousedown', null, Blockly.noEvent);\n    if (option.enabled) {\n      Blockly.bindEvent_(gElement, 'mouseup', null, option.callback);\n      Blockly.bindEvent_(gElement, 'mouseup', null, Blockly.ContextMenu.hide);\n    } else {\n      gElement.setAttribute('class', 'blocklyMenuDivDisabled');\n    }\n    // Compute the length of the longest text length.\n    maxWidth = Math.max(maxWidth, textElement.getComputedTextLength());\n  }\n  // Run a second pass to resize all options to the required width.\n  maxWidth += Blockly.ContextMenu.X_PADDING * 2;\n  for (var x = 0; x < resizeList.length; x++) {\n    resizeList[x].setAttribute('width', maxWidth);\n  }\n  if (Blockly.RTL) {\n    // Right-align the text.\n    for (var x = 0, gElement;\n         gElement = Blockly.ContextMenu.svgOptions.childNodes[x]; x++) {\n      var textElement = gElement.lastChild;\n      textElement.setAttribute('text-anchor', 'end');\n      textElement.setAttribute('x', maxWidth - Blockly.ContextMenu.X_PADDING);\n    }\n  }\n  Blockly.ContextMenu.svgBackground.setAttribute('height',\n      options.length * Blockly.ContextMenu.Y_HEIGHT + 8);\n  Blockly.ContextMenu.svgShadow.setAttribute('height',\n      options.length * Blockly.ContextMenu.Y_HEIGHT + 10);\n\n  // Convert the mouse coordinates into SVG coordinates.\n  var anchorX = xy.x;\n  var anchorY = xy.y;\n\n  // Measure the menu's size and position it so that it does not go off-screen.\n  var bBox = Blockly.ContextMenu.svgGroup.getBBox();\n  var svgSize = Blockly.svgSize();\n  if (anchorY + bBox.height > svgSize.height) {\n    // Falling off the bottom of the screen; flip the menu up.\n    anchorY -= bBox.height - 10;\n  }\n  if (Blockly.RTL) {\n    if (anchorX - bBox.width <= 0) {\n      anchorX++;\n    } else {\n      // Falling off the left edge in RTL mode; flip menu to right.\n      anchorX -= bBox.width;\n    }\n  } else {\n    if (anchorX + bBox.width > svgSize.width) {\n      // Falling off the right edge in LTR mode; flip the menu to left.\n      anchorX -= bBox.width;\n    } else {\n      anchorX++;\n    }\n  }\n  Blockly.ContextMenu.svgGroup.setAttribute('transform',\n      'translate(' + anchorX + ', ' + anchorY + ')');\n  Blockly.ContextMenu.visible = true;\n};\n\n/**\n * Create the DOM nodes for a menu option.\n * @param {string} text The option's text.\n * @return {!Element} <g> node containing the menu option.\n */\nBlockly.ContextMenu.optionToDom = function(text) {\n  /* Here's the SVG we create:\n    <g class=\"blocklyMenuDiv\">\n      <rect height=\"20\"/>\n      <text class=\"blocklyMenuText\" x=\"20\" y=\"15\">Make It So</text>\n    </g>\n  */\n  var gElement = Blockly.createSvgElement('g', {'class': 'blocklyMenuDiv'},\n                                          null);\n  var rectElement = Blockly.createSvgElement('rect',\n      {'height': Blockly.ContextMenu.Y_HEIGHT}, gElement);\n  var textElement = Blockly.createSvgElement('text',\n      {'class': 'blocklyMenuText',\n      'x': Blockly.ContextMenu.X_PADDING,\n      'y': 15}, gElement);\n  var textNode = document.createTextNode(text);\n  textElement.appendChild(textNode);\n  return gElement;\n};\n\n/**\n * Hide the context menu.\n */\nBlockly.ContextMenu.hide = function() {\n  if (Blockly.ContextMenu.visible) {\n    Blockly.ContextMenu.svgGroup.style.display = 'none';\n    Blockly.ContextMenu.visible = false;\n  }\n};\n\n/**\n * Create a callback function that creates and configures a block,\n *   then places the new block next to the original.\n * @param {!Blockly.Block} block Original block.\n * @param {!Element} xml XML representation of new block.\n * @return {!Function} Function that creates a block.\n */\nBlockly.ContextMenu.callbackFactory = function(block, xml) {\n  return function() {\n    var newBlock = Blockly.Xml.domToBlock(block.workspace, xml);\n    // Move the new block next to the old block.\n    var xy = block.getRelativeToSurfaceXY();\n    if (Blockly.RTL) {\n      xy.x -= Blockly.SNAP_RADIUS;\n    } else {\n      xy.x += Blockly.SNAP_RADIUS;\n    }\n    xy.y += Blockly.SNAP_RADIUS * 2;\n    newBlock.moveBy(xy.x, xy.y);\n    newBlock.select();\n  };\n};\n"
  },
  {
    "path": "extern/blockly/core/css.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2013 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Inject Blockly's CSS synchronously.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Css');\n\ngoog.require('goog.cssom');\n\n\n/**\n * Inject the CSS into the DOM.  This is preferable over using a regular CSS\n * file since:\n * a) It loads synchronously and doesn't force a redraw later.\n * b) It speeds up loading by not blocking on a separate HTTP transfer.\n * c) The CSS content may be made dynamic depending on init options.\n */\nBlockly.Css.inject = function() {\n  var text = Blockly.Css.CONTENT.join('\\n');\n  // Strip off any trailing slash (either Unix or Windows).\n  //var path = Blockly.pathToBlockly.replace(/[\\\\\\/]$/, '') + Blockly.mediaFilePath;\n  //text = text.replace(/<<<PATH>>>/g, path);\n  text = text.replace(/<<<PATH>>>/g, Blockly.mediaFilePath);\n  goog.cssom.addCssText(text);\n};\n\n/**\n * Array making up the CSS content for Blockly.\n */\nBlockly.Css.CONTENT = [\n  '.blocklySvg {',\n  '  background-color: transparent;',\n  '  position: absolute;',\n  '  cursor: move',\n  '}',\n  '.blocklyWidgetDiv {',\n  '  position: absolute;',\n  '  display: none;',\n  '  z-index: 999;',\n  '}',\n  '.blocklyDraggable {',\n  '  /* Hotspot coordinates are baked into the CUR file, but they are still',\n  '     required in the CSS due to a Chrome bug.',\n  '     http://code.google.com/p/chromium/issues/detail?id=1446 */',\n  '  cursor: url(<<<PATH>>>/media/handopen.cur) 8 5, auto;',\n  '}',\n  '.blocklyResizeSE {',\n  '  fill: #aaa;',\n  '  cursor: se-resize;',\n  '}',\n  '.blocklyResizeSW {',\n  '  fill: #aaa;',\n  '  cursor: sw-resize;',\n  '}',\n  '.blocklyResizeLine {',\n  '  stroke-width: 1;',\n  '  stroke: #888;',\n  '}',\n  '.blocklyPathPattern {',\n  '  opacity: 0;',\n  '  display: none;',\n  '}',\n  '.togglePattern>.blocklyPathPattern {',\n  '    display: block;',\n  '}',\n  '.disablePattern>.blocklyPathPattern {',\n  '  opacity: 0;',\n  '  display: none !important;',\n  '}',\n  '.blocklyHighlightedConnectionPathInline {',\n  '  stroke-width: 2px;',\n  //'  stroke: #1D55B4;',\n  //'  fill: #1D55B4;',\n  '  stroke: white;',\n  '  stroke-opacity: 1;',\n  '  fill: white;',\n  '  fill-opacity: 0.5;',\n  '}',\n  '.blocklyHighlightedConnectionPath {',\n  '  stroke-width: 2px;',\n  '  stroke: #3a3737;',\n  '  fill: none;',\n  '}',\n  '.blocklyPathLight {',\n  '  fill: none;',\n  '  stroke-width: 0.5;',\n  '  stroke-linecap: square;',\n  '}',\n  '.blocklySelected>.blocklyPath {',\n  '  stroke-width: 3px;',\n  '  stroke: #798EB1;',\n  '}',\n  '.blocklyActivated>.blocklyPath {',\n  '  stroke-width: 2px;',\n  '  stroke: #FF3939;',\n  '}',\n  '.blocklyActivated>.blocklyPathLight {',\n  '  display: none;',\n  '}',\n  '.blocklySelected>.blocklyPathLight {',\n  '  display: none;',\n  '}',\n  '.blocklyDragging>.blocklyPath,',\n  '.blocklyDragging>.blocklyPathLight {',\n  '  fill-opacity: 0.8;',\n  '  stroke-opacity: 0.8;',\n  '}',\n  '.blocklyDragging>.blocklyPathDark {',\n  '  display: none;',\n  '}',\n  '.blocklyDisabled>.blocklyPath {',\n  '  fill-opacity: 0.50;',\n  '  stroke-opacity: 0.50;',\n  '}',\n  '.blocklyDisabled>.blocklyPathLight,',\n  '.blocklyDisabled>.blocklyPathDark {',\n  '  display: none;',\n  '}',\n  '.blocklyText {',\n  '  cursor: default;',\n  '  font-family: ng;',\n  '  font-size: 9pt;',\n  '  fill: #fff;',\n  '}',\n  '.blocklyEditableText>.blocklyText {',\n  '  fill: #000;',\n  '}',\n  '.blocklyNonEditableText>text {',\n  '  pointer-events: none;',\n  '}',\n  '.blocklyNonEditableText>rect,',\n  '.blocklyEditableText>rect {',\n  '  fill: #fff;',\n  '  fill-opacity: 0;',\n  '}',\n  '.blocklyNonEditableField>rect,',\n  '.blocklyEditableField>rect {',\n  '  fill: #fff;',\n  '  fill-opacity: 0.4;',\n  '}',\n  '.blocklyNonEditableField>text,',\n  '.blocklyEditableField>text {',\n  '  fill: #000;',\n  '}',\n  '.blocklyNonEditableText>text,',\n  '.blocklyEditableText>text {',\n  '  fill: #000;',\n  '}',\n  '.blocklyEditableText:hover>rect {',\n  '  stroke-width: 2;',\n  '  stroke: #fff;',\n  '}',\n  '/*',\n  ' * Don\\'t allow users to select text.  It gets annoying when trying to',\n  ' * drag a block and selected text moves instead.',\n  ' */',\n  '.blocklySvg text {',\n  '  -moz-user-select: none;',\n  '  -webkit-user-select: none;',\n  '  user-select: none;',\n  '  cursor: inherit;',\n  '}',\n  '',\n  '.blocklyHidden {',\n  '  display: none;',\n  '}',\n  '.blocklyFieldDropdown:not(.blocklyHidden) {',\n  '  display: block;',\n  '}',\n  '.blocklyTooltipBackground {',\n  '  fill: #ffffc7;',\n  '  stroke-width: 1px;',\n  '  stroke: #d8d8d8;',\n  '}',\n  '.blocklyTooltipShadow,',\n  '.blocklyContextMenuShadow,',\n  '.blocklyDropdownMenuShadow {',\n  '  fill: #bbb;',\n  '  filter: url(#blocklyShadowFilter);',\n  '}',\n  '.blocklyTooltipText {',\n  '  font-family: sans-serif;',\n  '  font-size: 9pt;',\n  '  fill: #000;',\n  '}',\n  '',\n  '.blocklyIconShield {',\n  '  cursor: default;',\n  '  fill: #00c;',\n  '  stroke-width: 1px;',\n  '  stroke: #ccc;',\n  '}',\n  '.blocklyIconGroup:hover>.blocklyIconShield {',\n  '  fill: #00f;',\n  '  stroke: #fff;',\n  '}',\n  '.blocklyIconGroup:hover>.blocklyIconMark {',\n  '  fill: #fff;',\n  '}',\n  '.blocklyIconMark {',\n  '  cursor: default !important;',\n  '  font-family: sans-serif;',\n  '  font-size: 9pt;',\n  '  font-weight: bold;',\n  '  fill: #ccc;',\n  '  text-anchor: middle;',\n  '}',\n  '.blocklyWarningBody {',\n  '}',\n  '.blocklyMinimalBody {',\n  '  margin: 0;',\n  '  padding: 0;',\n  '}',\n  '.blocklyCommentTextarea {',\n  '  margin: 0;',\n  '  padding: 2px;',\n  '  border: 0;',\n  '  resize: none;',\n  '  background-color: #ffc;',\n  '}',\n  '.blocklyHtmlInput {',\n  '  font-family: ng;',\n  '  font-size: 9pt;',\n  '  border: none;',\n  '  outline: none;',\n  '  line-height: normal;',\n  '  width: 100%;',\n  '}',\n  '.blocklyContextMenuBackground,',\n  '.blocklyMutatorBackground {',\n  '  fill: #fff;',\n  '  stroke-width: 1;',\n  '  stroke: #ddd;',\n  '}',\n  '.blocklyContextMenuOptions>.blocklyMenuDiv,',\n  '.blocklyContextMenuOptions>.blocklyMenuDivDisabled,',\n  '.blocklyDropdownMenuOptions>.blocklyMenuDiv {',\n  '  fill: #fff;',\n  '}',\n  '.blocklyDropdownMenuOptions>.blocklyMenuDiv {',\n  '  cursor: default;',\n  '}',\n  '.blocklyContextMenuOptions>.blocklyMenuDiv:hover>rect,',\n  '.blocklyDropdownMenuOptions>.blocklyMenuDiv:hover>rect {',\n  '  fill: #57e;',\n  '}',\n  '.blocklyMenuSelected>rect {',\n  '  fill: #57e;',\n  '}',\n  '.blocklyMenuText {',\n  '  cursor: default !important;',\n  '  font-family: ng;',\n  '  font-size: 9pt; /* All context menu sizes are based on pixels. */',\n  '  fill: #000;',\n  '}',\n  '.blocklyContextMenuOptions>.blocklyMenuDiv:hover>.blocklyMenuText,',\n  '.blocklyDropdownMenuOptions>.blocklyMenuDiv:hover>.blocklyMenuText {',\n  '  fill: #fff;',\n  '}',\n  '.blocklyMenuSelected>.blocklyMenuText {',\n  '  fill: #fff;',\n  '}',\n  '.blocklyMenuDivDisabled>.blocklyMenuText {',\n  '  fill: #ccc;',\n  '}',\n  '.blocklyFlyoutBackground {',\n  '  fill: #ddd;',\n  '  fill-opacity: 0.8;',\n  '}',\n  '.blocklyColourBackground {',\n  '  fill: #666;',\n  '}',\n  '.blocklyScrollbarBackground {',\n  '  opacity: 0',\n  '}',\n  '.blocklyScrollbarKnob {',\n  '  fill: #000;',\n  '  opacity: 0.35',\n  '}',\n  '.blocklyScrollbarBackground:hover+.blocklyScrollbarKnob,',\n  '.blocklyScrollbarKnob:hover {',\n  '  fill: #000;',\n  '  opacity: 0.6',\n  '}',\n  '.blocklyInvalidInput {',\n  '  background: #faa;',\n  '}',\n  '.blocklyAngleCircle {',\n  '  stroke: #444;',\n  '  stroke-width: 1;',\n  '  fill: #ddd;',\n  '  fill-opacity: 0.8;',\n  '}',\n  '.blocklyAngleMarks {',\n  '  stroke: #444;',\n  '  stroke-width: 1;',\n  '}',\n  '.blocklyAngleGauge {',\n  '  fill: #f88;',\n  '  fill-opacity: 0.8;  ',\n  '}',\n  '.blocklyAngleLine {',\n  '  stroke: #f00;',\n  '  stroke-width: 2;',\n  '  stroke-linecap: round;',\n  '}',\n  '',\n  '/* Category tree in Toolbox. */',\n  '.blocklyToolboxDiv {',\n  '  background-color: #ddd;',\n  '  display: none;',\n  '  overflow-x: visible;',\n  '  overflow-y: auto;',\n  '  position: absolute;',\n  '}',\n  '.blocklyTreeRoot {',\n  '  padding: 4px 0;',\n  '}',\n  '.blocklyTreeRoot:focus {',\n  '  outline: none;',\n  '}',\n  '.blocklyTreeRow {',\n  '  line-height: 22px;',\n  '  height: 22px;',\n  '  padding-right: 1em;',\n  '  white-space: nowrap;',\n  '}',\n  '.blocklyToolboxDiv[dir=\"RTL\"] .blocklyTreeRow {',\n  '  padding-right: 0;',\n  '  padding-left: 1em !important;',\n  '}',\n  '.blocklyTreeRow:hover {',\n  '  background-color: #e4e4e4;',\n  '}',\n  '.blocklyTreeIcon {',\n  '  height: 16px;',\n  '  width: 16px;',\n  '  vertical-align: middle;',\n  '  background-image: url(<<<PATH>>>/media/tree.png);',\n  '}',\n  '.blocklyTreeIconClosedLtr {',\n  '  background-position: -32px -1px;',\n  '}',\n  '.blocklyTreeIconClosedRtl {',\n  '  background-position: 0px -1px;',\n  '}',\n  '.blocklyTreeIconOpen {',\n  '  background-position: -16px -1px;',\n  '}',\n  '.blocklyTreeIconNone {',\n  '  background-position: -48px -1px;',\n  '}',\n  '.blocklyTreeSelected>.blocklyTreeIconClosedLtr {',\n  '  background-position: -32px -17px;',\n  '}',\n  '.blocklyTreeSelected>.blocklyTreeIconClosedRtl {',\n  '  background-position: 0px -17px;',\n  '}',\n  '.blocklyTreeSelected>.blocklyTreeIconOpen {',\n  '  background-position: -16px -17px;',\n  '}',\n  '.blocklyTreeSelected>.blocklyTreeIconNone {',\n  '  background-position: -48px -17px;',\n  '}',\n  '.blocklyTreeLabel {',\n  '  cursor: default;',\n  '  font-family: sans-serif;',\n  '  font-size: 16px;',\n  '  padding: 0 3px;',\n  '  vertical-align: middle;',\n  '}',\n  '.blocklyTreeSelected  {',\n  '  background-color: #57e !important;',\n  '}',\n  '.blocklyTreeSelected .blocklyTreeLabel {',\n  '  color: #fff;',\n  '}',\n  '.blocklyBlockMenuBtn {',\n  '  cursor: pointer',\n  '}',\n  '.blocklyBlockMenuBtnHighlight {',\n  '  opacity: 0',\n  '}',\n  '.blocklyBlockMenuBtnHighlight:hover {',\n  '  opacity: 1',\n  '}',\n  '.blocklyBlockMenuBtnPath {',\n  '  fill: #eee',\n  '}',\n  '.blocklyBlockMenuBtnPath:hover {',\n  '  fill: #f4f4f4',\n  '}',\n  '',\n  '/*',\n  ' * Copyright 2007 The Closure Library Authors. All Rights Reserved.',\n  ' *',\n  ' * Use of this source code is governed by the Apache License, Version 2.0.',\n  ' * See the COPYING file for details.',\n  ' */',\n  '',\n  '/* Author: pupius@google.com (Daniel Pupius) */',\n  '',\n  '/*',\n  ' Styles to make the colorpicker look like the old gmail color picker',\n  ' NOTE: without CSS scoping this will override styles defined in palette.css',\n  '*/',\n  '.goog-palette {',\n  '  outline: none;',\n  '  cursor: default;',\n  '}',\n  '',\n  '.goog-palette-table {',\n  '  border: 1px solid #666;',\n  '  border-collapse: collapse;',\n  '}',\n  '',\n  '.goog-palette-cell {',\n  '  height: 13px;',\n  '  width: 15px;',\n  '  margin: 0;',\n  '  border: 0;',\n  '  text-align: center;',\n  '  vertical-align: middle;',\n  '  border-right: 1px solid #666;',\n  '  font-size: 1px;',\n  '}',\n  '',\n  '.goog-palette-colorswatch {',\n  '  position: relative;',\n  '  height: 13px;',\n  '  width: 15px;',\n  '  border: 1px solid #666;',\n  '}',\n  '',\n  '.goog-palette-cell-hover .goog-palette-colorswatch {',\n  '  border: 1px solid #FFF;',\n  '}',\n  '',\n  '.goog-palette-cell-selected .goog-palette-colorswatch {',\n  '  border: 1px solid #000;',\n  '  color: #fff;',\n  '}',\n  '',\n  '.entryFunctionButton {',\n  '  stroke: #555;',\n  '  stroke-width: 3;',\n  '  fill: transparent;',\n  '  cursor: pointer;',\n  '}',\n  '',\n  '.entryFunctionButton:hover {',\n  '  stroke: black;',\n  '}',\n  '',\n  '.entryFunctionButtonText {',\n  '  font-family: ng !important;',\n  '  font-size: 13 !important;',\n  '  text-anchor: middle;',\n  '  fill: black;',\n  '  cursor: pointer !important;',\n  '}',\n  ''\n];\n"
  },
  {
    "path": "extern/blockly/core/field.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Input field.  Used for editable titles, variables, etc.\n * This is an abstract class that defines the UI on the block.  Actual\n * instances would be Blockly.FieldTextInput, Blockly.FieldDropdown, etc.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Field');\n\n// TODO(scr): Fix circular dependencies\n// goog.require('Blockly.Block');\ngoog.require('Blockly.BlockSvg');\ngoog.require('goog.asserts');\n\n\n/**\n * Class for an editable field.\n * @param {string} text The initial content of the field.\n * @constructor\n */\nBlockly.Field = function(text) {\n  this.sourceBlock_ = null;\n  // Build the DOM.\n  this.fieldGroup_ = Blockly.createSvgElement('g', {}, null);\n  this.borderRect_ = Blockly.createSvgElement('rect',\n      {'rx': 0,\n       'ry': 0,\n       'x': -Blockly.BlockSvg.SEP_SPACE_X / 3 ,\n       'y': 0,\n       'height': 16}, this.fieldGroup_);\n  if (this instanceof Blockly.FieldTextInput) {\n      this.borderRect_.setAttribute('x', -Blockly.BlockSvg.SEP_SPACE_X / 2);\n      this.borderRect_.setAttribute('y', '-2');\n  }\n  this.textElement_ = Blockly.createSvgElement('text',\n      {'class': 'blocklyText', 'y': 11}, this.fieldGroup_);\n  this.size_ = {height: 14, width: 0};\n  this.setText(text);\n  this.visible_ = true;\n};\n\n/**\n * Clone this Field.  This must be implemented by all classes derived from\n * Field.  Since this class should not be instantiated, calling this method\n * throws an exception.\n * @throws {goog.assert.AssertionError}\n */\nBlockly.Field.prototype.clone = function() {\n  goog.asserts.fail('There should never be an instance of Field, ' +\n      'only its derived classes.');\n};\n\n/**\n * Non-breaking space.\n */\nBlockly.Field.NBSP = '\\u00A0';\n\n/**\n * Editable fields are saved by the XML renderer, non-editable fields are not.\n */\nBlockly.Field.prototype.EDITABLE = true;\n\n/**\n * Install this field on a block.\n * @param {!Blockly.Block} block The block containing this field.\n */\nBlockly.Field.prototype.init = function(block) {\n  if (this.sourceBlock_) {\n    throw 'Field has already been initialized once.';\n  }\n  this.sourceBlock_ = block;\n  this.updateEditable();\n  block.getSvgRoot().appendChild(this.fieldGroup_);\n  this.mouseUpWrapper_ =\n      Blockly.bindEvent_(this.fieldGroup_, 'mouseup', this, this.onMouseUp_);\n  // Bump to set the colours for dropdown arrows.\n  this.setText(null);\n};\n\n/**\n * Dispose of all DOM objects belonging to this editable field.\n */\nBlockly.Field.prototype.dispose = function() {\n  if (this.mouseUpWrapper_) {\n    Blockly.unbindEvent_(this.mouseUpWrapper_);\n    this.mouseUpWrapper_ = null;\n  }\n  this.sourceBlock_ = null;\n  goog.dom.removeNode(this.fieldGroup_);\n  this.fieldGroup_ = null;\n  this.textElement_ = null;\n  this.borderRect_ = null;\n};\n\n/**\n * Add or remove the UI indicating if this field is editable or not.\n */\nBlockly.Field.prototype.updateEditable = function() {\n  if (!this.EDITABLE) {\n    return;\n  }\n  if (this.sourceBlock_.isEditable()) {\n    if (this.arrow_ || this.symbol_)\n      Blockly.addClass_(/** @type {!Element} */ (this.fieldGroup_),\n                  'blocklyEditableField');\n    else\n      Blockly.addClass_(/** @type {!Element} */ (this.fieldGroup_),\n                  'blocklyEditableText');\n    Blockly.removeClass_(/** @type {!Element} */ (this.fieldGroup_),\n                         'blocklyNoNEditableText');\n    this.fieldGroup_.style.cursor = this.CURSOR;\n\n  } else {\n    Blockly.addClass_(/** @type {!Element} */ (this.fieldGroup_),\n                      'blocklyNonEditableText');\n    Blockly.removeClass_(/** @type {!Element} */ (this.fieldGroup_),\n                         'blocklyEditableText');\n    this.fieldGroup_.style.cursor = '';\n  }\n};\n\n/**\n * Gets whether this editable field is visible or not.\n * @return {boolean} True if visible.\n */\nBlockly.Field.prototype.isVisible = function() {\n  return this.visible_;\n};\n\n/**\n * Sets whether this editable field is visible or not.\n * @param {boolean} visible True if visible.\n */\nBlockly.Field.prototype.setVisible = function(visible) {\n  this.visible_ = visible;\n  this.getRootElement().style.display = visible ? 'block' : 'none';\n};\n\n/**\n * Gets the group element for this editable field.\n * Used for measuring the size and for positioning.\n * @return {!Element} The group element.\n */\nBlockly.Field.prototype.getRootElement = function() {\n  return /** @type {!Element} */ (this.fieldGroup_);\n};\n\n/**\n * Draws the border with the correct width.\n * Saves the computed width in a property.\n * @private\n */\nBlockly.Field.prototype.render_ = function() {\n  var width = this.textElement_.getComputedTextLength();\n  if (this.borderRect_) {\n    this.borderRect_.setAttribute('width',\n        width + Blockly.BlockSvg.SEP_SPACE_X);\n  }\n  this.size_.width = width;\n};\n\n/**\n * Returns the height and width of the field.\n * @return {!Object} Height and width.\n */\nBlockly.Field.prototype.getSize = function() {\n  if (!this.size_.width) {\n    this.render_();\n  }\n  return this.size_;\n};\n\n/**\n * Get the text from this field.\n * @return {string} Current text.\n */\nBlockly.Field.prototype.getText = function() {\n  return this.text_;\n};\n\n/**\n * Set the text in this field.  Trigger a rerender of the source block.\n * @param {?string} text New text.\n * @param {?boolean} isTrim Trim shown text.\n */\nBlockly.Field.prototype.setText = function(text, isTrim) {\n  if (text === null || text === this.text_) {\n    // No change if null.\n    return;\n  }\n  this.text_ = text;\n  // Empty the text element.\n  goog.dom.removeChildren(/** @type {!Element} */ (this.textElement_));\n  // Replace whitespace with non-breaking spaces so the text doesn't collapse.\n  text = text.replace(/\\s/g, Blockly.Field.NBSP);\n  if (!text) {\n    // Prevent the field from disappearing if empty.\n    text = Blockly.Field.NBSP;\n  }\n  if (isTrim && (text.length > Blockly.TEXT_INPUT_MAX_LENGTH))\n    text = text.substr(0, Blockly.TEXT_INPUT_MAX_LENGTH - 1) + '...';\n  var textNode = document.createTextNode(text);\n  this.textElement_.appendChild(textNode);\n\n  // Cached width is obsolete.  Clear it.\n  this.size_.width = 0;\n\n  if (this.sourceBlock_ && this.sourceBlock_.rendered) {\n    this.sourceBlock_.render();\n    this.sourceBlock_.bumpNeighbours_();\n    this.sourceBlock_.workspace.fireChangeEvent();\n  }\n};\n\n/**\n * By default there is no difference between the human-readable text and\n * the language-neutral values.  Subclasses (such as dropdown) may define this.\n * @return {string} Current text.\n */\nBlockly.Field.prototype.getValue = function() {\n  return this.getText();\n};\n\n/**\n * By default there is no difference between the human-readable text and\n * the language-neutral values.  Subclasses (such as dropdown) may define this.\n * @param {string} text New text.\n */\nBlockly.Field.prototype.setValue = function(text) {\n  this.setText(text);\n};\n\n/**\n * Handle a mouse up event on an editable field.\n * @param {!Event} e Mouse up event.\n * @private\n */\nBlockly.Field.prototype.onMouseUp_ = function(e) {\n  if (Blockly.isRightButton(e)) {\n    // Right-click.\n    return;\n  } else if (Blockly.Block.dragMode_ == 2) {\n    // Drag operation is concluding.  Don't open the editor.\n    return;\n  } else if (this.sourceBlock_.isEditable()) {\n    // Non-abstract sub-classes must define a showEditor_ method.\n    this.sourceBlock_.isDrag = true;\n    this.showEditor_();\n  }\n};\n\n/**\n * Change the tooltip text for this field.\n * @param {string|!Element} newTip Text for tooltip or a parent element to\n *     link to for its tooltip.\n */\nBlockly.Field.prototype.setTooltip = function(newTip) {\n  // Non-abstract sub-classes may wish to implement this.  See FieldLabel.\n};\n"
  },
  {
    "path": "extern/blockly/core/field_angle.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2013 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Angle input field.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldAngle');\n\ngoog.require('Blockly.FieldTextInput');\n\n\n/**\n * Class for an editable angle field.\n * @param {string} text The initial content of the field.\n * @param {Function} opt_changeHandler An optional function that is called\n *     to validate any constraints on what the user entered.  Takes the new\n *     text as an argument and returns the accepted text or null to abort\n *     the change.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldAngle = function(text, opt_changeHandler) {\n  var changeHandler;\n  if (opt_changeHandler) {\n    // Wrap the user's change handler together with the angle validator.\n    var thisObj = this;\n    changeHandler = function(value) {\n      value = Blockly.FieldAngle.angleValidator.call(thisObj, value);\n      if (value !== null) {\n        opt_changeHandler.call(thisObj, value);\n      }\n      return value;\n    };\n  } else {\n    changeHandler = Blockly.FieldAngle.angleValidator;\n  }\n\n  // Add degree symbol: \"360°\" (LTR) or \"°360\" (RTL)\n  this.symbol_ = Blockly.createSvgElement('tspan', {}, null);\n  this.symbol_.appendChild(document.createTextNode('\\u00B0'));\n\n  Blockly.FieldAngle.superClass_.constructor.call(this,\n      text, changeHandler);\n  this.borderRect_.setAttribute('x', -Blockly.BlockSvg.SEP_SPACE_X/2);\n};\ngoog.inherits(Blockly.FieldAngle, Blockly.FieldTextInput);\n\n/**\n * Clone this FieldAngle.\n * @return {!Blockly.FieldAngle} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldAngle.prototype.clone = function() {\n  return new Blockly.FieldAngle(this.getText(), this.changeHandler_);\n};\n\n/**\n * Round angles to the nearest 15 degrees when using mouse.\n * Set to 0 to disable rounding.\n */\nBlockly.FieldAngle.ROUND = 15;\n\n/**\n * Half the width of protractor image.\n */\nBlockly.FieldAngle.HALF = 100 / 2;\n\n/**\n * Radius of protractor circle.  Slightly smaller than protractor size since\n * otherwise SVG crops off half the border at the edges.\n */\nBlockly.FieldAngle.RADIUS = Blockly.FieldAngle.HALF - 1;\n\n/**\n * Clean up this FieldAngle, as well as the inherited FieldTextInput.\n * @return {!Function} Closure to call on destruction of the WidgetDiv.\n * @private\n */\nBlockly.FieldAngle.prototype.dispose_ = function() {\n  var thisField = this;\n  return function() {\n    Blockly.FieldAngle.superClass_.dispose_.call(thisField)();\n    thisField.gauge_ = null;\n    if (thisField.clickWrapper_) {\n      Blockly.unbindEvent_(thisField.clickWrapper_);\n    }\n    if (thisField.moveWrapper1_) {\n      Blockly.unbindEvent_(thisField.moveWrapper1_);\n    }\n    if (thisField.moveWrapper2_) {\n      Blockly.unbindEvent_(thisField.moveWrapper2_);\n    }\n  };\n};\n\n/**\n * Show the inline free-text editor on top of the text.\n * @private\n */\nBlockly.FieldAngle.prototype.showEditor_ = function() {\n  Blockly.FieldAngle.superClass_.showEditor_.call(this);\n  var div = Blockly.WidgetDiv.DIV;\n  if (!div.firstChild) {\n    // Mobile interface uses window.prompt.\n    return;\n  }\n  // Build the SVG DOM.\n  var svg = Blockly.createSvgElement('svg', {\n    'xmlns': 'http://www.w3.org/2000/svg',\n    'xmlns:html': 'http://www.w3.org/1999/xhtml',\n    'xmlns:xlink': 'http://www.w3.org/1999/xlink',\n    'version': '1.1',\n    'height': (Blockly.FieldAngle.HALF * 2) + 'px',\n    'width': (Blockly.FieldAngle.HALF * 2) + 'px'\n  }, div);\n  var circle = Blockly.createSvgElement('circle', {\n    'cx': Blockly.FieldAngle.HALF, 'cy': Blockly.FieldAngle.HALF,\n    'r': Blockly.FieldAngle.RADIUS,\n    'class': 'blocklyAngleCircle'\n  }, svg);\n  this.gauge_ = Blockly.createSvgElement('path',\n      {'class': 'blocklyAngleGauge'}, svg);\n  this.line_ = Blockly.createSvgElement('line',\n      {'x1': Blockly.FieldAngle.HALF,\n      'y1': Blockly.FieldAngle.HALF,\n      'class': 'blocklyAngleLine'}, svg);\n  // Draw markers around the edge.\n  for (var a = 0; a < 360; a += 15) {\n    Blockly.createSvgElement('line', {\n      'x1': Blockly.FieldAngle.HALF + Blockly.FieldAngle.RADIUS,\n      'y1': Blockly.FieldAngle.HALF,\n      'x2': Blockly.FieldAngle.HALF + Blockly.FieldAngle.RADIUS -\n          (a % 45 == 0 ? 10 : 5),\n      'y2': Blockly.FieldAngle.HALF,\n      'class': 'blocklyAngleMarks',\n      'transform': 'rotate(' + a + ', ' +\n          Blockly.FieldAngle.HALF + ', ' + Blockly.FieldAngle.HALF + ')'\n    }, svg);\n  }\n  svg.style.marginLeft = '-35px';\n  this.clickWrapper_ =\n      Blockly.bindEvent_(svg, 'click', this, Blockly.WidgetDiv.hide);\n  this.moveWrapper1_ =\n      Blockly.bindEvent_(circle, 'mousemove', this, this.onMouseMove);\n  this.moveWrapper2_ =\n      Blockly.bindEvent_(this.gauge_, 'mousemove', this, this.onMouseMove);\n  this.updateGraph();\n};\n\n/**\n * Set the angle to match the mouse's position.\n * @param {!Event} e Mouse move event.\n */\nBlockly.FieldAngle.prototype.onMouseMove = function(e) {\n  var bBox = this.gauge_.ownerSVGElement.getBoundingClientRect();\n  var dx = e.clientX - bBox.left - Blockly.FieldAngle.HALF;\n  var dy = e.clientY - bBox.top - Blockly.FieldAngle.HALF;\n  var angle = Math.atan(-dy / dx);\n  if (isNaN(angle)) {\n    // This shouldn't happen, but let's not let this error propogate further.\n    return;\n  }\n  angle = angle / Math.PI * 180;\n  angle = 90 - angle;\n  // 0: East, 90: North, 180: West, 270: South.\n  if (dx < 0) {\n    angle += 180;\n  } else if (dy > 0) {\n    angle += 360;\n  }\n  if (Blockly.FieldAngle.ROUND) {\n    angle = Math.round(angle / Blockly.FieldAngle.ROUND) *\n        Blockly.FieldAngle.ROUND;\n  }\n  if (angle >= 360) {\n    // Rounding may have rounded up to 360.\n    angle -= 360;\n  }\n  angle = String(angle);\n  Blockly.FieldTextInput.htmlInput_.value = angle;\n  this.setText(angle);\n};\n\n/**\n * Insert a degree symbol.\n * @param {?string} text New text.\n */\nBlockly.FieldAngle.prototype.setText = function(text) {\n  Blockly.FieldAngle.superClass_.setText.call(this, text);\n  this.updateGraph();\n  // Insert degree symbol.\n  if (Blockly.RTL) {\n    this.textElement_.insertBefore(this.symbol_, this.textElement_.firstChild);\n  } else {\n    this.textElement_.appendChild(this.symbol_);\n  }\n  // Cached width is obsolete.  Clear it.\n  this.size_.width = 0;\n};\n\n/**\n * Ensure that only an angle may be entered.\n * @param {string} text The user's text.\n * @return {?string} A string representing a valid angle, or null if invalid.\n */\nBlockly.FieldAngle.prototype.updateGraph = function() {\n  if (this.gauge_) {\n    var angleRadians = Number(this.getText()) / 180 * Math.PI;\n    if (isNaN(angleRadians)) {\n      this.gauge_.setAttribute('d',\n          'M ' + Blockly.FieldAngle.HALF + ', ' + Blockly.FieldAngle.HALF);\n      this.line_.setAttribute('x2', Blockly.FieldAngle.HALF);\n      this.line_.setAttribute('y2', Blockly.FieldAngle.HALF);\n    } else {\n      var x = Blockly.FieldAngle.HALF + Math.sin(angleRadians) *\n          Blockly.FieldAngle.RADIUS;\n      var y = Blockly.FieldAngle.HALF + Math.cos(angleRadians) *\n          -Blockly.FieldAngle.RADIUS;\n      var largeFlag = (angleRadians > Math.PI) ? 1 : 0;\n      this.gauge_.setAttribute('d',\n          'M ' + Blockly.FieldAngle.HALF + ', ' + Blockly.FieldAngle.HALF +\n          ' v -' + Blockly.FieldAngle.RADIUS +\n          ' A ' + Blockly.FieldAngle.RADIUS + ',' + Blockly.FieldAngle.RADIUS +\n          ' 0 ' + largeFlag + ' 1 ' + x + ',' + y + ' z');\n      this.line_.setAttribute('x2', x);\n      this.line_.setAttribute('y2', y);\n    }\n  }\n};\n\n/**\n * Ensure that only an angle may be entered.\n * @param {string} text The user's text.\n * @return {?string} A string representing a valid angle, or null if invalid.\n */\nBlockly.FieldAngle.angleValidator = function(text) {\n  var n = Blockly.FieldTextInput.numberValidator(text);\n  if (n !== null) {\n    //n = n % 360;\n    //if (n < 0) {\n      //n += 360;\n    //}\n    n = String(n);\n   }\n  return n;\n};\n"
  },
  {
    "path": "extern/blockly/core/field_checkbox.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Checkbox field.  Checked or not checked.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldCheckbox');\n\ngoog.require('Blockly.Field');\n\n\n/**\n * Class for a checkbox field.\n * @param {string} state The initial state of the field ('TRUE' or 'FALSE').\n * @param {Function} opt_changeHandler A function that is executed when a new\n *     option is selected.  Its sole argument is the new checkbox state.  If\n *     it returns a value, this becomes the new checkbox state, unless the\n *     value is null, in which case the change is aborted.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldCheckbox = function(state, opt_changeHandler) {\n  Blockly.FieldCheckbox.superClass_.constructor.call(this, '');\n\n  this.changeHandler_ = opt_changeHandler;\n  // The checkbox doesn't use the inherited text element.\n  // Instead it uses a custom checkmark element that is either visible or not.\n  this.checkElement_ = Blockly.createSvgElement('text',\n      {'class': 'blocklyText', 'x': -3}, this.fieldGroup_);\n  var textNode = document.createTextNode('\\u2713');\n  this.checkElement_.appendChild(textNode);\n  // Set the initial state.\n  this.setValue(state);\n};\ngoog.inherits(Blockly.FieldCheckbox, Blockly.Field);\n\n/**\n * Clone this FieldCheckbox.\n * @return {!Blockly.FieldCheckbox} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldCheckbox.prototype.clone = function() {\n  return new Blockly.FieldCheckbox(this.getValue(), this.changeHandler_);\n};\n\n/**\n * Mouse cursor style when over the hotspot that initiates editability.\n */\nBlockly.FieldCheckbox.prototype.CURSOR = 'default';\n\n/**\n * Return 'TRUE' if the checkbox is checked, 'FALSE' otherwise.\n * @return {string} Current state.\n */\nBlockly.FieldCheckbox.prototype.getValue = function() {\n  return String(this.state_).toUpperCase();\n};\n\n/**\n * Set the checkbox to be checked if strBool is 'TRUE', unchecks otherwise.\n * @param {string} strBool New state.\n */\nBlockly.FieldCheckbox.prototype.setValue = function(strBool) {\n  var newState = (strBool == 'TRUE');\n  if (this.state_ !== newState) {\n    this.state_ = newState;\n    this.checkElement_.style.display = newState ? 'block' : 'none';\n    if (this.sourceBlock_ && this.sourceBlock_.rendered) {\n      this.sourceBlock_.workspace.fireChangeEvent();\n    }\n  }\n};\n\n/**\n * Toggle the state of the checkbox.\n * @private\n */\nBlockly.FieldCheckbox.prototype.showEditor_ = function() {\n  var newState = !this.state_;\n  if (this.changeHandler_) {\n    // Call any change handler, and allow it to override.\n    var override = this.changeHandler_(newState);\n    if (override !== undefined) {\n      newState = override;\n    }\n  }\n  if (newState !== null) {\n    this.setValue(String(newState).toUpperCase());\n  }\n};\n"
  },
  {
    "path": "extern/blockly/core/field_colour.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Colour input field.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldColour');\n\ngoog.require('Blockly.Field');\ngoog.require('goog.ui.ColorPicker');\n\n\n/**\n * Class for a colour input field.\n * @param {string} colour The initial colour in '#rrggbb' format.\n * @param {Function} opt_changeHandler A function that is executed when a new\n *     colour is selected.  Its sole argument is the new colour value.  Its\n *     return value becomes the selected colour, unless it is undefined, in\n *     which case the new colour stands, or it is null, in which case the change\n *     is aborted.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldColour = function(colour, opt_changeHandler) {\n  Blockly.FieldColour.superClass_.constructor.call(this, '\\u00A0\\u00A0\\u00A0');\n\n  this.changeHandler_ = opt_changeHandler;\n  this.borderRect_.style.fillOpacity = 1;\n  // Set the initial state.\n  this.setValue(colour);\n};\ngoog.inherits(Blockly.FieldColour, Blockly.Field);\n\n/**\n * Clone this FieldColour.\n * @return {!Blockly.FieldColour} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldColour.prototype.clone = function() {\n  return new Blockly.FieldColour(this.getValue(), this.changeHandler_);\n};\n\n/**\n * Mouse cursor style when over the hotspot that initiates the editor.\n */\nBlockly.FieldColour.prototype.CURSOR = 'default';\n\n/**\n * Dispose of all DOM objects belonging to this editable field.\n */\nBlockly.FieldColour.prototype.dispose = function() {\n  Blockly.WidgetDiv.hideIfField(this);\n  Blockly.FieldColour.superClass_.dispose.call(this);\n};\n\n/**\n * Return the current colour.\n * @return {string} Current colour in '#rrggbb' format.\n */\nBlockly.FieldColour.prototype.getValue = function() {\n  return this.colour_;\n};\n\n/**\n * Set the colour.\n * @param {string} colour The new colour in '#rrggbb' format.\n */\nBlockly.FieldColour.prototype.setValue = function(colour) {\n  this.colour_ = colour;\n  this.borderRect_.style.fill = colour;\n  if (this.sourceBlock_ && this.sourceBlock_.rendered) {\n    this.sourceBlock_.workspace.fireChangeEvent();\n  }\n};\n\n/**\n * An array of colour strings for the palette.\n * See bottom of this page for the default:\n * http://docs.closure-library.googlecode.com/git/closure_goog_ui_colorpicker.js.source.html\n * @type {!Array.<string>}\n */\nBlockly.FieldColour.COLOURS = goog.ui.ColorPicker.SIMPLE_GRID_COLORS;\n\n/**\n * Number of columns in the palette.\n */\nBlockly.FieldColour.COLUMNS = 7;\n\n/**\n * Create a palette under the colour field.\n * @private\n */\nBlockly.FieldColour.prototype.showEditor_ = function() {\n  Blockly.WidgetDiv.show(this, Blockly.FieldColour.dispose_);\n  var div = Blockly.WidgetDiv.DIV;\n  // Create the palette using Closure.\n  var picker = new goog.ui.ColorPicker();\n  picker.setSize(Blockly.FieldColour.COLUMNS);\n  picker.setColors(Blockly.FieldColour.COLOURS);\n  picker.render(div);\n  picker.setSelectedColor(this.getValue());\n\n  // Position the palette to line up with the field.\n  var xy = Blockly.getAbsoluteXY_(/** @type {!Element} */ (this.borderRect_));\n  var borderBBox = this.borderRect_.getBBox();\n  if (Blockly.RTL) {\n    xy.x += borderBBox.width;\n  }\n  xy.y += borderBBox.height - 1;\n  if (Blockly.RTL) {\n    xy.x -= div.offsetWidth;\n  }\n  div.style.left = xy.x + 'px';\n  div.style.top = xy.y + 'px';\n\n  // Configure event handler.\n  var thisObj = this;\n  Blockly.FieldColour.changeEventKey_ = goog.events.listen(picker,\n      goog.ui.ColorPicker.EventType.CHANGE,\n      function(event) {\n        var colour = event.target.getSelectedColor() || '#000000';\n        Blockly.WidgetDiv.hide();\n        if (thisObj.changeHandler_) {\n          // Call any change handler, and allow it to override.\n          var override = thisObj.changeHandler_(colour);\n          if (override !== undefined) {\n            colour = override;\n          }\n        }\n        if (colour !== null) {\n          if (typeof(Entry) == \"object\" && thisObj.getValue() != colour) {\n            Entry.dispatchEvent(\"entryBlocklyChanged\");\n          }\n          thisObj.setValue(colour);\n        }\n      });\n};\n\n/**\n * Hide the colour palette.\n * @private\n */\nBlockly.FieldColour.dispose_ = function() {\n  if (Blockly.FieldColour.changeEventKey_) {\n    goog.events.unlistenByKey(Blockly.FieldColour.changeEventKey_);\n  }\n};\n"
  },
  {
    "path": "extern/blockly/core/field_dropdown.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Dropdown input field.  Used for editable titles and variables.\n * In the interests of a consistent UI, the toolbox shares some functions and\n * properties with the context menu.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldDropdown');\n\ngoog.require('Blockly.Field');\n\n/**\n * Class for an editable dropdown field.\n * @param {(!Array.<string>|!Function)} menuGenerator An array of options\n *     for a dropdown list, or a function which generates these options.\n * @param {Function} opt_changeHandler A function that is executed when a new\n *     option is selected, with the newly selected value as its sole argument.\n *     If it returns a value, that value (which must be one of the options) will\n *     become selected in place of the newly selected option, unless the return\n *     value is null, in which case the change is aborted.\n * @param {?Boolean} arrowOption If arrowOption is true or null, arrow will be\n *     shown. If arrowOption is false, arrow will not be shown.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldDropdown = function(menuGenerator, opt_changeHandler,\n                                 arrowOption, arrowColor) {\n  this.menuGenerator_ = menuGenerator;\n  this.changeHandler_ = opt_changeHandler;\n  this.trimOptions_();\n  var firstTuple = this.getOptions_()[0];\n  this.value_ = firstTuple[1];\n\n  // Add dropdown arrow: \"option ▾\" (LTR) or \"▾ אופציה\" (RTL)\n  this.arrow_ = Blockly.createSvgElement('tspan', {}, null);\n  if (arrowColor) this.arrowColor_ = arrowColor;\n  if (arrowOption != false) {\n    this.arrow_.appendChild(document.createTextNode(\n        Blockly.RTL ? '\\u25BE ' : ' \\u25BE'));\n  }\n\n  // Call parent's constructor.\n  Blockly.FieldDropdown.superClass_.constructor.call(this, firstTuple[0]);\n};\ngoog.inherits(Blockly.FieldDropdown, Blockly.Field);\n\n/**\n * Clone this FieldDropdown.\n * @return {!Blockly.FieldDropdown} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldDropdown.prototype.clone = function() {\n  return new Blockly.FieldDropdown(this.menuGenerator_, this.changeHandler_);\n};\n\n/**\n * Create the dropdown field's elements.  Only needs to be called once.\n * @return {!Element} The field's SVG group.\n */\nBlockly.FieldDropdown.createDom = function() {\n  var url_up = Blockly.mediaFilePath + 'media/scroll_up.png';\n  var url_down = Blockly.mediaFilePath + 'media/scroll_down.png';\n  Blockly.FieldDropdown.currentPosition = 0;\n  var svg = Blockly.createSvgElement('svg', {\n    'xmlns': 'http://www.w3.org/2000/svg',\n    'version': '1.1',\n    'height' : '200'\n  }, null);\n  Blockly.FieldDropdown.svgWrapper_ = svg;\n  var svgGroup = Blockly.createSvgElement('g',\n      {'class': 'blocklyHidden blocklyFieldDropdown'}, svg);\n  Blockly.FieldDropdown.svgGroup_ = svgGroup;\n  Blockly.FieldDropdown.svgShadow_ = Blockly.createSvgElement('rect',\n      {'class': 'blocklyDropdownMenuShadow',\n      'x': 0, 'y': 1}, svgGroup);\n  Blockly.FieldDropdown.svgBackground_ = Blockly.createSvgElement('rect',\n      {'x': -2, 'y': -1,\n      'filter': 'url(#blocklyEmboss)'}, svgGroup);\n  Blockly.FieldDropdown.svgOptions_ = Blockly.createSvgElement('g',\n      {'class': 'blocklyDropdownMenuOptions'}, svgGroup);\n\n  Blockly.FieldDropdown.scrollbarWrapper_ = Blockly.createSvgElement('g',\n      {'class': 'blocklyDropdownScollWrapper blocklyHidden'}, svg);\n\n  Blockly.FieldDropdown.scrollbarUpWrapper_ = Blockly.createSvgElement('g',\n      {'transform':'translate(0 0)','cursor':'pointer'}, Blockly.FieldDropdown.scrollbarWrapper_);\n  Blockly.createSvgElement('rect', {'width':'15','height':'40','fill':'none','stroke':'none'},\n                           Blockly.FieldDropdown.scrollbarUpWrapper_);\n  var upperImg = Blockly.createSvgElement('image', {'width':'10','height':'40', 'x':'5','opacity':'0.5'},\n                           Blockly.FieldDropdown.scrollbarUpWrapper_);\n  upperImg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',\n      url_up);\n\n  Blockly.FieldDropdown.scrollbarDownWrapper_ = Blockly.createSvgElement('g',\n      {'transform':'translate(0 160)', 'cursor':'pointer'}, Blockly.FieldDropdown.scrollbarWrapper_);\n  Blockly.createSvgElement('rect', {'width':'15','height':'40','fill':'none','stroke':'none'},\n                           Blockly.FieldDropdown.scrollbarDownWrapper_);\n  var upperImg = Blockly.createSvgElement('image', {'width':'10','height':'40', 'x':'5','opacity':'0.5'},\n                           Blockly.FieldDropdown.scrollbarDownWrapper_);\n  upperImg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',\n      url_down);;\n\n\n  return svg;\n};\n\n/**\n * handle mouse over event\n */\nBlockly.FieldDropdown.moveUp = function(e) {\n    var current = Blockly.FieldDropdown.currentPosition\n    if (current == 0)\n        return;\n    else\n        Blockly.FieldDropdown.currentPosition--;\n    Blockly.FieldDropdown.moveScroll(Blockly.FieldDropdown.currentPosition);\n    Blockly.FieldDropdown.timer = window.setTimeout(function(){\n       Blockly.FieldDropdown.moveUp();\n    },100);\n};\n\nBlockly.FieldDropdown.mouseLeave = function(e) {\n    if (Blockly.FieldDropdown.timer) {\n        window.clearInterval(Blockly.FieldDropdown.timer);\n        Blockly.FieldDropdown.timer = null;\n    }\n};\n\n/**\n * handle mouse over event\n */\nBlockly.FieldDropdown.moveDown = function(e) {\n    if (this.getOptions_)\n        Blockly.FieldDropdown.optionLength = this.getOptions_().length;\n\n    var current = Blockly.FieldDropdown.currentPosition\n    if (current + 10 ==  Blockly.FieldDropdown.optionLength)\n        return;\n    else\n        Blockly.FieldDropdown.currentPosition++;\n    Blockly.FieldDropdown.moveScroll(Blockly.FieldDropdown.currentPosition);\n    Blockly.FieldDropdown.timer = window.setTimeout(function(){\n       Blockly.FieldDropdown.moveDown();\n    },100);\n};\n\n/**\n * handle mouse wheel event\n */\nBlockly.FieldDropdown.onMouseWheel = function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n    Blockly.removeAllRanges();\n    var svgScroll = Blockly.FieldDropdown.scrollbar_;\n    var svgScrollWrapper = Blockly.FieldDropdown.scrollbarWrapper_;\n\n    var options = this.getOptions_();\n\n    if (options.length <= 10) {\n        Blockly.addClass_(svgScrollWrapper, 'blocklyHidden');\n        return;\n    } else {\n        var dy = e.wheelDeltaY || -e.deltaY;\n        Blockly.removeClass_(svgScrollWrapper, 'blocklyHidden');\n        var current = Blockly.FieldDropdown.currentPosition\n        if (current == 0 && dy > 0)\n            return;\n        if (current == (options.length - 10) && dy < 0)\n            return;\n        if (dy < 0)\n            Blockly.FieldDropdown.currentPosition++;\n        else\n            Blockly.FieldDropdown.currentPosition--;\n        Blockly.FieldDropdown.moveScroll(Blockly.FieldDropdown.currentPosition);\n    }\n};\n\n/**\n * translate svgGroup and scrollbar by currentposition\n */\nBlockly.FieldDropdown.moveScroll = function(position) {\n    var svgGroup = Blockly.FieldDropdown.svgGroup_;\n    svgGroup.setAttribute('transform', 'translate(0 '+ (position * -20)+')');\n};\n\n/**\n * Close the dropdown and dispose of all UI.\n */\nBlockly.FieldDropdown.prototype.dispose = function() {\n  if (Blockly.FieldDropdown.openDropdown_ == this) {\n    Blockly.FieldDropdown.hide();\n  }\n  // Call parent's destructor.\n  Blockly.Field.prototype.dispose.call(this);\n};\n\n/**\n * Corner radius of the dropdown background.\n */\nBlockly.FieldDropdown.CORNER_RADIUS = 2;\n\n/**\n * Mouse cursor style when over the hotspot that initiates the editor.\n */\nBlockly.FieldDropdown.prototype.CURSOR = 'default';\n\n/**\n * Which block is the dropdown attached to?\n * @type {Blockly.FieldDropdown}\n * @private\n */\nBlockly.FieldDropdown.openDropdown_ = null;\n\n/**\n * Create a dropdown menu under the text.\n * @private\n */\nBlockly.FieldDropdown.prototype.showEditor_ = function() {\n  if (Blockly.FieldDropdown.workspace !== this.sourceBlock_.workspace) {\n    goog.dom.removeChildren(/** @type {!Element} */ (Blockly.FieldDropdown.svgWrapper_));\n    var svg = Blockly.FieldDropdown.createDom();\n    this.sourceBlock_.workspace.svgGroup_.appendChild(svg);\n    Blockly.FieldDropdown.workspace = this.sourceBlock_.workspace\n  }\n\n  var svgWrapper = Blockly.FieldDropdown.svgWrapper_;\n  var svgGroup = Blockly.FieldDropdown.svgGroup_;\n  var svgOptions = Blockly.FieldDropdown.svgOptions_;\n  var svgBackground = Blockly.FieldDropdown.svgBackground_;\n  var svgShadow = Blockly.FieldDropdown.svgShadow_;\n  // Erase all existing options.\n  goog.dom.removeChildren(svgOptions);\n  // The menu must be made visible early since otherwise BBox and\n  // getComputedTextLength will return 0.\n  Blockly.removeClass_(svgGroup, 'blocklyHidden');\n  Blockly.FieldDropdown.openDropdown_ = this;\n\n  function callbackFactory(value) {\n    return function(e) {\n      if (this.changeHandler_) {\n        // Call any change handler, and allow it to override.\n        var override = this.changeHandler_(value);\n        if (override !== undefined) {\n          value = override;\n        }\n      }\n      if (value !== null) {\n        if (typeof(Entry) == \"object\" && this.getValue() != value) {\n          Entry.dispatchEvent(\"entryBlocklyChanged\");\n        }\n        this.setValue(value);\n      }\n      // This mouse click has been handled, don't bubble up to document.\n      e.stopPropagation();\n    };\n  }\n\n  var maxWidth = 0;\n  var resizeList = [];\n  var checkElement = null;\n  var options = this.getOptions_();\n  for (var x = 0; x < options.length; x++) {\n    var text = options[x][0];  // Human-readable text.\n    var value = options[x][1]; // Language-neutral value.\n    var gElement = Blockly.ContextMenu.optionToDom(text);\n    var rectElement = /** @type {SVGRectElement} */ (gElement.firstChild);\n    var textElement = /** @type {SVGTextElement} */ (gElement.lastChild);\n    svgOptions.appendChild(gElement);\n    // Add a checkmark next to the current item.\n    if (!checkElement && value == this.value_) {\n      checkElement = Blockly.createSvgElement('text',\n          {'class': 'blocklyMenuText', 'y': 15}, null);\n      // Insert the checkmark between the rect and text, thus preserving the\n      // ability to reference them as firstChild and lastChild respectively.\n      gElement.insertBefore(checkElement, textElement);\n      checkElement.appendChild(document.createTextNode('\\u2713'));\n    }\n\n    gElement.setAttribute('transform',\n        'translate(0, ' + (x * Blockly.ContextMenu.Y_HEIGHT) + ')');\n    resizeList.push(rectElement);\n    Blockly.bindEvent_(gElement, 'mousedown', null, Blockly.noEvent);\n    Blockly.bindEvent_(gElement, 'mouseup', this, callbackFactory(value));\n    Blockly.bindEvent_(gElement, 'mouseup', null,\n                       Blockly.FieldDropdown.hide);\n    // Compute the length of the longest text length.\n    maxWidth = Math.max(maxWidth, textElement.getComputedTextLength());\n  }\n  // Run a second pass to resize all options to the required width.\n  maxWidth += Blockly.ContextMenu.X_PADDING * 2;\n  for (var x = 0; x < resizeList.length; x++) {\n    resizeList[x].setAttribute('width', maxWidth);\n  }\n  if (Blockly.RTL) {\n    // Right-align the text.\n    for (var x = 0, gElement; gElement = svgOptions.childNodes[x]; x++) {\n      var textElement = gElement.lastChild;\n      textElement.setAttribute('text-anchor', 'end');\n      textElement.setAttribute('x', maxWidth - Blockly.ContextMenu.X_PADDING);\n    }\n  }\n  if (checkElement) {\n    if (Blockly.RTL) {\n      // Research indicates that RTL checkmarks are supposed to be drawn the\n      // same in the same direction as LTR checkmarks.  It's only the alignment\n      // that needs to change.\n      checkElement.setAttribute('text-anchor', 'end');\n      checkElement.setAttribute('x', maxWidth - 5);\n    } else {\n      checkElement.setAttribute('x', 5);\n    }\n  }\n  var width = maxWidth + Blockly.FieldDropdown.CORNER_RADIUS * 2;\n  var height = options.length * Blockly.ContextMenu.Y_HEIGHT +\n               Blockly.FieldDropdown.CORNER_RADIUS + 1;\n  svgShadow.setAttribute('width', width);\n  svgShadow.setAttribute('height', height);\n  svgBackground.setAttribute('width', width);\n  svgBackground.setAttribute('height', height);\n  var hexColour = Blockly.makeColour(this.sourceBlock_.getColour());\n  svgBackground.setAttribute('fill', hexColour);\n  // Position the dropdown to line up with the field.\n  var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.borderRect_));\n  var borderBBox = this.borderRect_.getBBox();\n  var x;\n  if (Blockly.RTL) {\n    x = xy.x - maxWidth + Blockly.ContextMenu.X_PADDING + borderBBox.width -\n        Blockly.BlockSvg.SEP_SPACE_X / 2;\n  } else {\n    x = xy.x - Blockly.ContextMenu.X_PADDING + Blockly.BlockSvg.SEP_SPACE_X / 2;\n  }\n  var scrollWrapper = Blockly.FieldDropdown.scrollbarWrapper_;\n  if (options.length <= 10) {\n      Blockly.addClass_(scrollWrapper, 'blocklyHidden');\n  } else {\n      var hw = svgOptions.getBBox();\n      Blockly.removeClass_(scrollWrapper, 'blocklyHidden');\n      scrollWrapper.setAttribute('transform', 'translate('+ (Number(hw.width)-15) + ' 0)');\n  }\n  Blockly.FieldDropdown.wheelEvent_ = Blockly.bindEvent_(\n                                      svgGroup, 'wheel', this, Blockly.FieldDropdown.onMouseWheel);\n  Blockly.FieldDropdown.moveUpEvent_ = Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarUpWrapper_,'mouseover',\n                     this, Blockly.FieldDropdown.moveUp);\n  Blockly.FieldDropdown.moveUpLeaveEvent_ = Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarUpWrapper_,'mouseleave',\n                     this, Blockly.FieldDropdown.mouseLeave);\n  Blockly.FieldDropdown.moveDownEvent_ = Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarDownWrapper_,'mouseover',\n                     this, Blockly.FieldDropdown.moveDown);\n  Blockly.FieldDropdown.moveDownLeaveEvent_ = Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarDownWrapper_,'mouseleave',\n                     this, Blockly.FieldDropdown.mouseLeave);\n  svgWrapper.setAttribute('x',  x);\n  svgWrapper.setAttribute('y',  xy.y + borderBBox.height);\n};\n\n/**\n * Factor out common words in statically defined options.\n * Create prefix and/or suffix labels.\n * @private\n */\nBlockly.FieldDropdown.prototype.trimOptions_ = function() {\n  this.prefixField = null;\n  this.suffixField = null;\n  var options = this.menuGenerator_;\n  if (!goog.isArray(options) || options.length < 2) {\n    return;\n  }\n  var strings = options.map(function(t) {return t[0];});\n  var shortest = Blockly.shortestStringLength(strings);\n  var prefixLength = Blockly.commonWordPrefix(strings, shortest);\n  var suffixLength = Blockly.commonWordSuffix(strings, shortest);\n  if (!prefixLength && !suffixLength) {\n    return;\n  }\n  if (shortest <= prefixLength + suffixLength) {\n    // One or more strings will entirely vanish if we proceed.  Abort.\n    return;\n  }\n  if (prefixLength) {\n    this.prefixField = strings[0].substring(0, prefixLength - 1);\n  }\n  if (suffixLength) {\n    this.suffixField = strings[0].substr(1 - suffixLength);\n  }\n  // Remove the prefix and suffix from the options.\n  var newOptions = [];\n  for (var x = 0; x < options.length; x++) {\n    var text = options[x][0];\n    var value = options[x][1];\n    text = text.substring(prefixLength, text.length - suffixLength);\n    newOptions[x] = [text, value];\n  }\n  this.menuGenerator_ = newOptions;\n};\n\n/**\n * Return a list of the options for this dropdown.\n * @return {!Array.<!Array.<string>>} Array of option tuples:\n *     (human-readable text, language-neutral name).\n * @private\n */\nBlockly.FieldDropdown.prototype.getOptions_ = function() {\n  if (goog.isFunction(this.menuGenerator_)) {\n    return this.menuGenerator_.call(this);\n  }\n  return /** @type {!Array.<!Array.<string>>} */ (this.menuGenerator_);\n};\n\n/**\n * Get the language-neutral value from this dropdown menu.\n * @return {string} Current text.\n */\nBlockly.FieldDropdown.prototype.getValue = function() {\n  return this.value_;\n};\n\n/**\n * Set the language-neutral value for this dropdown menu.\n * @param {string} newValue New value to set.\n */\nBlockly.FieldDropdown.prototype.setValue = function(newValue) {\n  this.value_ = newValue;\n  // Look up and display the human-readable text.\n  var options = this.getOptions_();\n  for (var x = 0; x < options.length; x++) {\n    // Options are tuples of human-readable text and language-neutral values.\n    if (options[x][1] == newValue) {\n      this.setText(options[x][0]);\n      return;\n    }\n  }\n  // Value not found.  Add it, maybe it will become valid once set\n  // (like variable names).\n  this.setText(newValue);\n};\n\n/**\n * Set the text in this field.  Trigger a rerender of the source block.\n * @param {?string} text New text.\n */\nBlockly.FieldDropdown.prototype.setText = function(text) {\n  if (this.sourceBlock_) {\n    // Update arrow's colour.\n    if (this.arrowColor_) this.arrow_.style.fill = this.arrowColor_;\n    else\n        this.arrow_.style.fill = Blockly.makeColour(this.sourceBlock_.getColour());\n  }\n  if (text === null) {\n    // No change if null.\n    return;\n  }\n  this.text_ = text;\n  // Empty the text element.\n  goog.dom.removeChildren(/** @type {!Element} */ (this.textElement_));\n  // Replace whitespace with non-breaking spaces so the text doesn't collapse.\n  text = text.replace(/\\s/g, Blockly.Field.NBSP);\n  if (!text) {\n    // Prevent the field from disappearing if empty.\n    text = Blockly.Field.NBSP;\n  }\n  var textNode = document.createTextNode(text);\n  this.textElement_.appendChild(textNode);\n\n  // Insert dropdown arrow.\n  if (Blockly.RTL) {\n    this.textElement_.insertBefore(this.arrow_, this.textElement_.firstChild);\n  } else {\n    this.textElement_.appendChild(this.arrow_);\n  }\n\n  // Cached width is obsolete.  Clear it.\n  this.size_.width = 0;\n\n  if (this.sourceBlock_ && this.sourceBlock_.rendered) {\n    this.sourceBlock_.render();\n    this.sourceBlock_.bumpNeighbours_();\n    this.sourceBlock_.workspace.fireChangeEvent();\n  }\n};\n\n/**\n * Hide the dropdown menu.\n */\nBlockly.FieldDropdown.hide = function() {\n  var svgGroup = Blockly.FieldDropdown.svgGroup_;\n  var svgScrollWrapper = Blockly.FieldDropdown.scrollbarWrapper_;\n  if (svgGroup) {\n    Blockly.addClass_(svgGroup, 'blocklyHidden');\n    svgGroup.removeAttribute('transform');\n  }\n  if (svgScrollWrapper) {\n        Blockly.addClass_(svgScrollWrapper, 'blocklyHidden');\n        svgScrollWrapper.removeAttribute('transform');\n  }\n  if (Blockly.FieldDropdown.wheelEvent_)\n      Blockly.unbindEvent_(Blockly.FieldDropdown.wheelEvent_);\n  if (Blockly.FieldDropdown.moveUpEvent_)\n      Blockly.unbindEvent_(Blockly.FieldDropdown.moveUpEvent_);\n  if (Blockly.FieldDropdown.moveDownEvent_)\n      Blockly.unbindEvent_(Blockly.FieldDropdown.moveDownEvent_);\n  if (Blockly.FieldDropdown.moveUpLeaveEvent_)\n      Blockly.unbindEvent_(Blockly.FieldDropdown.moveUpLeaveEvent_);\n  if (Blockly.FieldDropdown.moveDownLaeveEvent_)\n      Blockly.unbindEvent_(Blockly.FieldDropdown.moveDownLeaveEvent_);\n  Blockly.FieldDropdown.currentPosition = 0;\n  Blockly.FieldDropdown.openDropdown_ = null;\n};\n"
  },
  {
    "path": "extern/blockly/core/field_dropdowndynamic.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Dropdown input field.  Used for editable titles and variables.\n * In the interests of a consistent UI, the toolbox shares some functions and\n * properties with the context menu.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldDropdownDynamic');\n\ngoog.require('Blockly.Field');\n\n\n/**\n * Class for an editable dropdown field.\n * @param {(!Array.<string>|!Function)} menuGenerator An array of options\n *     for a dropdown list, or a function which generates these options.\n * @param {Function} opt_changeHandler A function that is executed when a new\n *     option is selected, with the newly selected value as its sole argument.\n *     If it returns a value, that value (which must be one of the options) will\n *     become selected in place of the newly selected option, unless the return\n *     value is null, in which case the change is aborted.\n * @param {?Boolean} arrowOption If arrowOption is true or null, arrow will be\n *     shown. If arrowOption is false, arrow will not be shown.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldDropdownDynamic = function(menuInfo, opt_changeHandler,\n                                       arrowOption, arrowColor) {\n  //document.addEventListener(\"cust\", this.updateMenu_, false);\n  //this.menuGenerator_ = menuGenerator;\n  if (typeof menuInfo == \"function\")\n    this.menuFunc_ = menuInfo\n  else\n    this.menuName_ = menuInfo;\n  this.menuGenerator = this.getOptions_();\n  this.changeHandler_ = opt_changeHandler;\n  this.trimOptions_();\n  var firstTuple = this.getOptions_()[0];\n  this.value_ = firstTuple[1];\n  // Add dropdown arrow: \"option ▾\" (LTR) or \"▾ אופציה\" (RTL)\n  this.arrow_ = Blockly.createSvgElement('tspan', {}, null);\n  if (arrowColor) this.arrowColor_ = arrowColor;\n  if (arrowOption != false) {\n      this.arrow_.appendChild(document.createTextNode(\n          Blockly.RTL ? '\\u25BE ' : ' \\u25BE'));\n  }\n\n  // Call parent's constructor.\n  Blockly.FieldDropdownDynamic.superClass_.constructor.call(this, firstTuple[0]);\n};\ngoog.inherits(Blockly.FieldDropdownDynamic, Blockly.Field);\n\n/*\nBlockly.FieldDropdownDynamic.prototype.updateMenu_ = function(e) {\n    console.log(\"updated!\");\n  this.menuGenerator_ = [['gamja','tiggem'], ['da','naggeoya'], ['grigo', 'igeotto']];\n    return true;\n};\n*/\n\n/**\n * Clone this FieldDropdownDynamic.\n * @return {!Blockly.FieldDropdownDynamic} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldDropdownDynamic.prototype.clone = function() {\n  return new Blockly.FieldDropdownDynamic(this.menuGenerator_, this.changeHandler_);\n};\n\n/**\n * Create the dropdown field's elements.  Only needs to be called once.\n * @return {!Element} The field's SVG group.\n */\nBlockly.FieldDropdownDynamic.createDom = function() {\n  /*\n  <g class=\"blocklyHidden blocklyFieldDropdownDynamic\">\n    <rect class=\"blocklyDropdownMenuShadow\" x=\"0\" y=\"1\" rx=\"2\" ry=\"2\"/>\n    <rect x=\"-2\" y=\"-1\" rx=\"2\" ry=\"2\"/>\n    <g class=\"blocklyDropdownMenuOptions\">\n    </g>\n  </g>\n  */\n  var svgGroup = Blockly.createSvgElement('g',\n      {'class': 'blocklyHidden blocklyFieldDropdown'}, null);\n  Blockly.FieldDropdownDynamic.svgGroup_ = svgGroup;\n  Blockly.FieldDropdownDynamic.svgShadow_ = Blockly.createSvgElement('rect',\n      {'class': 'blocklyDropdownMenuShadow',\n      'x': 0, 'y': 1}, svgGroup);\n  Blockly.FieldDropdownDynamic.svgBackground_ = Blockly.createSvgElement('rect',\n      {'x': -2, 'y': -1,\n      'filter': 'url(#blocklyEmboss)'}, svgGroup);\n  Blockly.FieldDropdownDynamic.svgOptions_ = Blockly.createSvgElement('g',\n      {'class': 'blocklyDropdownMenuOptions'}, svgGroup);\n  return svgGroup;\n};\n\n/**\n * Close the dropdown and dispose of all UI.\n */\nBlockly.FieldDropdownDynamic.prototype.dispose = function() {\n  if (Blockly.FieldDropdownDynamic.openDropdown_ == this) {\n    Blockly.FieldDropdown.hide();\n  }\n  // Call parent's destructor.\n  Blockly.Field.prototype.dispose.call(this);\n};\n\n/**\n * Corner radius of the dropdown background.\n */\nBlockly.FieldDropdownDynamic.CORNER_RADIUS = 2;\n\n/**\n * Mouse cursor style when over the hotspot that initiates the editor.\n */\nBlockly.FieldDropdownDynamic.prototype.CURSOR = 'default';\n\n/**\n * Which block is the dropdown attached to?\n * @type {Blockly.FieldDropdownDynamic}\n * @private\n */\nBlockly.FieldDropdownDynamic.openDropdown_ = null;\n\n/**\n * Create a dropdown menu under the text.\n * @private\n */\nBlockly.FieldDropdownDynamic.prototype.showEditor_ = function() {\n  if (Blockly.FieldDropdown.workspace !== this.sourceBlock_.workspace) {\n    goog.dom.removeChildren(/** @type {!Element} */ (Blockly.FieldDropdown.svgWrapper_));\n    var svg = Blockly.FieldDropdown.createDom();\n    this.sourceBlock_.workspace.svgGroup_.appendChild(svg);\n    Blockly.FieldDropdown.workspace = this.sourceBlock_.workspace\n  }\n\n  var svgWrapper = Blockly.FieldDropdown.svgWrapper_;\n  var svgGroup = Blockly.FieldDropdown.svgGroup_;\n  var svgOptions = Blockly.FieldDropdown.svgOptions_;\n  var svgBackground = Blockly.FieldDropdown.svgBackground_;\n  var svgShadow = Blockly.FieldDropdown.svgShadow_;\n  // Erase all existing options.\n  goog.dom.removeChildren(svgOptions);\n  // The menu must be made visible early since otherwise BBox and\n  // getComputedTextLength will return 0.\n  Blockly.removeClass_(svgGroup, 'blocklyHidden');\n  Blockly.FieldDropdownDynamic.openDropdown_ = this;\n\n  function callbackFactory(value) {\n    return function(e) {\n      if (this.changeHandler_) {\n        // Call any change handler, and allow it to override.\n        var override = this.changeHandler_(value);\n        if (override !== undefined) {\n          value = override;\n        }\n      }\n      if (value !== null) {\n        if (typeof(Entry) == \"object\" && this.getValue() != value) {\n          Entry.dispatchEvent(\"entryBlocklyChanged\");\n        }\n        this.setValue(value);\n      }\n      // This mouse click has been handled, don't bubble up to document.\n      e.stopPropagation();\n    };\n  }\n\n  var maxWidth = 0;\n  var resizeList = [];\n  var checkElement = null;\n  var options = this.getOptions_();\n  for (var x = 0; x < options.length; x++) {\n    var text = options[x][0];  // Human-readable text.\n    var value = options[x][1]; // Language-neutral value.\n    var gElement = Blockly.ContextMenu.optionToDom(text);\n    var rectElement = /** @type {SVGRectElement} */ (gElement.firstChild);\n    var textElement = /** @type {SVGTextElement} */ (gElement.lastChild);\n    svgOptions.appendChild(gElement);\n\n    // Add a checkmark next to the current item.\n    if (!checkElement && value == this.value_) {\n      checkElement = Blockly.createSvgElement('text',\n          {'class': 'blocklyMenuText', 'y': 15}, null);\n      // Insert the checkmark between the rect and text, thus preserving the\n      // ability to reference them as firstChild and lastChild respectively.\n      gElement.insertBefore(checkElement, textElement);\n      checkElement.appendChild(document.createTextNode('\\u2713'));\n    }\n\n    gElement.setAttribute('transform',\n        'translate(0, ' + (x * Blockly.ContextMenu.Y_HEIGHT) + ')');\n    resizeList.push(rectElement);\n    Blockly.bindEvent_(gElement, 'mousedown', null, Blockly.noEvent);\n    Blockly.bindEvent_(gElement, 'mouseup', this, callbackFactory(value));\n    Blockly.bindEvent_(gElement, 'mouseup', null,\n                       Blockly.FieldDropdown.hide);\n    // Compute the length of the longest text length.\n    maxWidth = Math.max(maxWidth, textElement.getComputedTextLength());\n  }\n  // Run a second pass to resize all options to the required width.\n  maxWidth += Blockly.ContextMenu.X_PADDING * 2;\n  for (var x = 0; x < resizeList.length; x++) {\n    resizeList[x].setAttribute('width', maxWidth);\n  }\n  if (Blockly.RTL) {\n    // Right-align the text.\n    for (var x = 0, gElement; gElement = svgOptions.childNodes[x]; x++) {\n      var textElement = gElement.lastChild;\n      textElement.setAttribute('text-anchor', 'end');\n      textElement.setAttribute('x', maxWidth - Blockly.ContextMenu.X_PADDING);\n    }\n  }\n  if (checkElement) {\n    if (Blockly.RTL) {\n      // Research indicates that RTL checkmarks are supposed to be drawn the\n      // same in the same direction as LTR checkmarks.  It's only the alignment\n      // that needs to change.\n      checkElement.setAttribute('text-anchor', 'end');\n      checkElement.setAttribute('x', maxWidth - 5);\n    } else {\n      checkElement.setAttribute('x', 5);\n    }\n  }\n  var width = maxWidth + Blockly.FieldDropdownDynamic.CORNER_RADIUS * 2;\n  var height = options.length * Blockly.ContextMenu.Y_HEIGHT +\n               Blockly.FieldDropdownDynamic.CORNER_RADIUS + 1;\n  svgShadow.setAttribute('width', width);\n  svgShadow.setAttribute('height', height);\n  svgBackground.setAttribute('width', width);\n  svgBackground.setAttribute('height', height);\n  var hexColour = Blockly.makeColour(this.sourceBlock_.getColour());\n  svgBackground.setAttribute('fill', hexColour);\n  // Position the dropdown to line up with the field.\n  var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.borderRect_));\n  var borderBBox = this.borderRect_.getBBox();\n  var x;\n  if (Blockly.RTL) {\n    x = xy.x - maxWidth + Blockly.ContextMenu.X_PADDING + borderBBox.width -\n        Blockly.BlockSvg.SEP_SPACE_X / 2;\n  } else {\n    x = xy.x - Blockly.ContextMenu.X_PADDING + Blockly.BlockSvg.SEP_SPACE_X / 2;\n  }\n  var scrollWrapper = Blockly.FieldDropdown.scrollbarWrapper_\n  if (options.length <= 10) {\n      Blockly.addClass_(scrollWrapper, 'blocklyHidden');\n  } else {\n      var hw = svgOptions.getBBox();\n      Blockly.removeClass_(scrollWrapper, 'blocklyHidden');\n      scrollWrapper.setAttribute('transform', 'translate('+ (Number(hw.width)-15) + ' 0)');\n  }\n  Blockly.FieldDropdown.wheelEvent_ = Blockly.bindEvent_(\n                                      svgGroup, 'wheel', this, Blockly.FieldDropdown.onMouseWheel);\n  Blockly.FieldDropdown.moveUpEvent_ = Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarUpWrapper_,'mouseover',\n                     this, Blockly.FieldDropdown.moveUp);\n  Blockly.FieldDropdown.moveUpLeaveEvent_ = Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarUpWrapper_,'mouseleave',\n                     this, Blockly.FieldDropdown.mouseLeave);\n  Blockly.FieldDropdown.moveDownEvent_ = Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarDownWrapper_,'mouseover',\n                     this, Blockly.FieldDropdown.moveDown);\n  Blockly.FieldDropdown.moveDownLeaveEvent_ = Blockly.bindEvent_(Blockly.FieldDropdown.scrollbarDownWrapper_,'mouseleave',\n                     this, Blockly.FieldDropdown.mouseLeave);\n  svgWrapper.setAttribute('x',  x);\n  svgWrapper.setAttribute('y',  xy.y + borderBBox.height);\n};\n\n/**\n * Factor out common words in statically defined options.\n * Create prefix and/or suffix labels.\n * @private\n */\nBlockly.FieldDropdownDynamic.prototype.trimOptions_ = function() {\n  return; //ignore trim feature\n  this.prefixField = null;\n  this.suffixField = null;\n  var options = this.menuGenerator_;\n  if (!goog.isArray(options) || options.length < 2) {\n    return;\n  }\n  var strings = options.map(function(t) {return t[0];});\n  var shortest = Blockly.shortestStringLength(strings);\n  var prefixLength = Blockly.commonWordPrefix(strings, shortest);\n  var suffixLength = Blockly.commonWordSuffix(strings, shortest);\n  if (!prefixLength && !suffixLength) {\n    return;\n  }\n  if (shortest <= prefixLength + suffixLength) {\n    // One or more strings will entirely vanish if we proceed.  Abort.\n    return;\n  }\n  if (prefixLength) {\n    this.prefixField = strings[0].substring(0, prefixLength - 1);\n  }\n  if (suffixLength) {\n    this.suffixField = strings[0].substr(1 - suffixLength);\n  }\n  // Remove the prefix and suffix from the options.\n  var newOptions = [];\n  for (var x = 0; x < options.length; x++) {\n    var text = options[x][0];\n    var value = options[x][1];\n    text = text.substring(prefixLength, text.length - suffixLength);\n    newOptions[x] = [text, value];\n  }\n  this.menuGenerator_ = newOptions;\n};\n\n/**\n * Return a list of the options for this dropdown.\n * @return {!Array.<!Array.<string>>} Array of option tuples:\n *     (human-readable text, language-neutral name).\n * @private\n */\nBlockly.FieldDropdownDynamic.prototype.getOptions_ = function() {\n  if (typeof(Entry.container) == \"object\") {\n    if (this.menuName_)\n      return Entry.container.getDropdownList(this.menuName_);\n    else {\n      return this.menuFunc_.call(this);\n    }\n  } else {\n    return [[Lang.Blocks.no_target, 'null']];\n  }\n  return /** @type {!Array.<!Array.<string>>} */ (this.menuGenerator_);\n};\n\n/**\n * Get the language-neutral value from this dropdown menu.\n * @return {string} Current text.\n */\nBlockly.FieldDropdownDynamic.prototype.getValue = function() {\n  return this.value_;\n};\n\n/**\n * Set the language-neutral value for this dropdown menu.\n * @param {string} newValue New value to set.\n */\nBlockly.FieldDropdownDynamic.prototype.setValue = function(newValue) {\n  this.value_ = newValue;\n  // Look up and display the human-readable text.\n  var options = this.getOptions_();\n  for (var x = 0; x < options.length; x++) {\n    // Options are tuples of human-readable text and language-neutral values.\n    if (options[x][1] == newValue) {\n      this.setText(options[x][0]);\n      return;\n    }\n  }\n  // Value not found.  Add it, maybe it will become valid once set\n  // (like variable names).\n  this.setText('대상없음');\n};\n\n/**\n * Set the text in this field.  Trigger a rerender of the source block.\n * @param {?string} text New text.\n */\nBlockly.FieldDropdownDynamic.prototype.setText = function(text) {\n  if (this.sourceBlock_) {\n    // Update arrow's colour.\n    if (this.arrowColor_) this.arrow_.style.fill = this.arrowColor_;\n    else\n        this.arrow_.style.fill = Blockly.makeColour(this.sourceBlock_.getColour());\n  }\n  if (!text || text === null) {\n    // No change if null.\n    return;\n  }\n  this.text_ = text;\n  // Empty the text element.\n  goog.dom.removeChildren(/** @type {!Element} */ (this.textElement_));\n  // Replace whitespace with non-breaking spaces so the text doesn't collapse.\n  text = text.replace(/\\s/g, Blockly.Field.NBSP);\n  if (!text) {\n    // Prevent the field from disappearing if empty.\n    text = Blockly.Field.NBSP;\n  }\n  var textNode = document.createTextNode(text);\n  this.textElement_.appendChild(textNode);\n\n  // Insert dropdown arrow.\n  if (Blockly.RTL) {\n    this.textElement_.insertBefore(this.arrow_, this.textElement_.firstChild);\n  } else {\n    this.textElement_.appendChild(this.arrow_);\n  }\n\n  // Cached width is obsolete.  Clear it.\n  this.size_.width = 0;\n\n  if (this.sourceBlock_ && this.sourceBlock_.rendered) {\n    this.sourceBlock_.render();\n    this.sourceBlock_.bumpNeighbours_();\n    this.sourceBlock_.workspace.fireChangeEvent();\n  }\n};\n\n/**\n * Hide the dropdown menu.\n */\nBlockly.FieldDropdownDynamic.hide = function() {\n    //this function should not be called but in order to prevent unexpected error,\n    //remain this function\n    Blockly.FieldDropdown.hide();\n};\n"
  },
  {
    "path": "extern/blockly/core/field_icon.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Image field.  Used for titles, labels, etc.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldIcon');\n\ngoog.require('Blockly.Field');\ngoog.require('goog.userAgent');\n\n\n/**\n * Class for an image.\n * @param {string} src The URL of the image.\n * @param {?string} opt_alt Optional alt text for when block is collapsed.\n * @param {?string} type type of icon.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldIcon = function(src, opt_alt, type) {\n  this.sourceBlock_ = null;\n  this.type = type ? type : \"endOrigin\";\n  if (this.type == \"end\") {\n    // Ensure height and width are numbers.  Strings are bad at math.\n    var height = 24;\n    var width = 24;\n    this.height_ = Number(height);\n    this.width_ = Number(width);\n    this.iconSize = 0.7;\n  } else if ( this.type == \"endOrigin\" ) {\n    var height = 24;\n    var width = 24;\n    this.height_ = Number(height);\n    this.width_ = Number(width);\n  } else if ( this.type == \"start\" ) {\n    var height = 34;\n    var width = 34;\n    this.height_ = Number(height);\n    this.width_ = Number(width);\n  }\n  this.size_ = {height: this.height_, width: this.width_};\n  this.text_ = opt_alt || '';\n  // Build the DOM.\n  var offsetY = 0;\n  if (this.type == \"end\") {\n    this.fieldGroup_ = Blockly.createSvgElement('g', {}, null);\n    this.circleElement_ = Blockly.createSvgElement('circle',\n        {'cx': this.width_/2, 'cy': this.height_/2,\n         'r': this.width_/2,\n         'y': offsetY}, this.fieldGroup_);\n    this.imageElement_ = Blockly.createSvgElement('image',\n        {'height': this.height_*this.iconSize + 'px',\n         'width': this.width_*this.iconSize + 'px',\n         'x': this.width_ * (1 - this.iconSize) / 2,\n         'y': this.height_ * (1 - this.iconSize) / 2}, this.fieldGroup_);\n    this.setValue(src);\n  } else if ( this.type == \"endOrigin\" ) {\n    this.fieldGroup_ = Blockly.createSvgElement('g', {}, null);\n    this.imageElement_ = Blockly.createSvgElement('image',\n        {'height': this.height_ + 'px',\n         'width': this.width_ + 'px',\n         'x': 0,\n         'y': 0}, this.fieldGroup_);\n    this.setValue(src);\n  } else if ( this.type == \"start\" ) {\n    this.fieldGroup_ = Blockly.createSvgElement('g', {}, null);\n    this.imageElement_ = Blockly.createSvgElement('image',\n        {'height': this.height_ + 'px',\n         'width': this.width_ + 'px',\n         'x': 0,\n         'y': -2}, this.fieldGroup_);\n    this.setValue(src);\n  }\n    if (goog.userAgent.GECKO) {\n    // Due to a Firefox bug which eats mouse events on image elements,\n    // a transparent rectangle needs to be placed on top of the image.\n    this.rectElement_ = Blockly.createSvgElement('rect',\n        {'height': this.height_ + 'px',\n         'width': this.width_ + 'px',\n         'y': offsetY,\n         'fill-opacity': 0}, this.fieldGroup_);\n  }\n};\ngoog.inherits(Blockly.FieldIcon, Blockly.Field);\n\n/**\n * Clone this FieldIcon.\n * @return {!Blockly.FieldIcon} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldIcon.prototype.clone = function() {\n  return new Blockly.FieldIcon(this.getSrc(), this.width_, this.height_,\n      this.getText());\n};\n\n/**\n * Rectangular mask used by Firefox.\n * @type {Element}\n * @private\n */\nBlockly.FieldIcon.prototype.rectElement_ = null;\n\n/**\n * Editable fields are saved by the XML renderer, non-editable fields are not.\n */\nBlockly.FieldIcon.prototype.EDITABLE = false;\n\n/**\n * Install this text on a block.\n * @param {!Blockly.Block} block The block containing this text.\n */\nBlockly.FieldIcon.prototype.init = function(block) {\n  if (this.sourceBlock_) {\n    throw 'Image has already been initialized once.';\n  }\n  this.sourceBlock_ = block;\n  block.getSvgRoot().appendChild(this.fieldGroup_);\n\n  // Configure the field to be transparent with respect to tooltips.\n  if (!this.type || this.type == \"end\") {\n    var topElement = this.rectElement_ || this.imageElement_;\n    topElement.tooltip = this.sourceBlock_;\n    var rgb = goog.color.hexToRgb(block.getColour());\n    var c = goog.color.darken(rgb, 0.2);\n    c = goog.color.rgbToHex(c[0], c[1], c[2]);\n    this.circleElement_.style.fill = c;\n  } else if ( this.type == \"endOrigin\" ) {\n    var topElement = this.imageElement_;\n    topElement.tooltip = this.sourceBlock_;\n  } else if ( this.type == \"start\" ) {\n    var topElement = this.imageElement_;\n    topElement.tooltip = this.sourceBlock_;\n  }\n\n  Blockly.Tooltip && Blockly.Tooltip.bindMouseEvents(topElement);\n};\n\n/**\n * Dispose of all DOM objects belonging to this text.\n */\nBlockly.FieldIcon.prototype.dispose = function() {\n  goog.dom.removeNode(this.fieldGroup_);\n  this.fieldGroup_ = null;\n  this.imageElement_ = null;\n  this.rectElement_ = null;\n};\n\n/**\n * Change the tooltip text for this field.\n * @param {string|!Element} newTip Text for tooltip or a parent element to\n *     link to for its tooltip.\n */\nBlockly.FieldIcon.prototype.setTooltip = function(newTip) {\n  var topElement = this.rectElement_ || this.imageElement_;\n  topElement.tooltip = newTip;\n};\n\n/**\n * Get the source URL of this image.\n * @return {string} Current text.\n * @override\n */\nBlockly.FieldIcon.prototype.getValue = function() {\n  return this.src_;\n};\n\n/**\n * Set the source URL of this image.\n * @param {?string} src New source.\n * @override\n */\nBlockly.FieldIcon.prototype.setValue = function(src) {\n  if (src === null) {\n    // No change if null.\n    return;\n  }\n  this.src_ = src;\n  this.imageElement_.setAttributeNS('http://www.w3.org/1999/xlink',\n      'xlink:href', goog.isString(src) ? src : '');\n};\n\n/**\n * Set the alt text of this image.\n * @param {?string} alt New alt text.\n * @override\n */\nBlockly.FieldIcon.prototype.setText = function(alt) {\n  if (alt === null) {\n    // No change if null.\n    return;\n  }\n  this.text_ = alt;\n};\n"
  },
  {
    "path": "extern/blockly/core/field_image.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Image field.  Used for titles, labels, etc.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldImage');\n\ngoog.require('Blockly.Field');\ngoog.require('goog.userAgent');\n\n\n/**\n * Class for an image.\n * @param {string} src The URL of the image.\n * @param {number} width Width of the image.\n * @param {number} height Height of the image.\n * @param {?string} opt_alt Optional alt text for when block is collapsed.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldImage = function(src, width, height, opt_alt) {\n  this.sourceBlock_ = null;\n  // Ensure height and width are numbers.  Strings are bad at math.\n  this.height_ = Number(height);\n  this.width_ = Number(width);\n  this.size_ = {height: this.height_ + 10, width: this.width_};\n  this.text_ = opt_alt || '';\n  // Build the DOM.\n  var offsetY = 6 - Blockly.BlockSvg.FIELD_HEIGHT;\n  this.fieldGroup_ = Blockly.createSvgElement('g', {}, null);\n  this.imageElement_ = Blockly.createSvgElement('image',\n      {'height': this.height_ + 'px',\n       'width': this.width_ + 'px',\n       'y': offsetY}, this.fieldGroup_);\n  this.setValue(src);\n  if (goog.userAgent.GECKO) {\n    // Due to a Firefox bug which eats mouse events on image elements,\n    // a transparent rectangle needs to be placed on top of the image.\n    this.rectElement_ = Blockly.createSvgElement('rect',\n        {'height': this.height_ + 'px',\n         'width': this.width_ + 'px',\n         'y': offsetY,\n         'fill-opacity': 0}, this.fieldGroup_);\n  }\n};\ngoog.inherits(Blockly.FieldImage, Blockly.Field);\n\n/**\n * Clone this FieldImage.\n * @return {!Blockly.FieldImage} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldImage.prototype.clone = function() {\n  return new Blockly.FieldImage(this.getSrc(), this.width_, this.height_,\n      this.getText());\n};\n\n/**\n * Rectangular mask used by Firefox.\n * @type {Element}\n * @private\n */\nBlockly.FieldImage.prototype.rectElement_ = null;\n\n/**\n * Editable fields are saved by the XML renderer, non-editable fields are not.\n */\nBlockly.FieldImage.prototype.EDITABLE = false;\n\n/**\n * Install this text on a block.\n * @param {!Blockly.Block} block The block containing this text.\n */\nBlockly.FieldImage.prototype.init = function(block) {\n  if (this.sourceBlock_) {\n    throw 'Image has already been initialized once.';\n  }\n  this.sourceBlock_ = block;\n  block.getSvgRoot().appendChild(this.fieldGroup_);\n\n  // Configure the field to be transparent with respect to tooltips.\n  var topElement = this.rectElement_ || this.imageElement_;\n  topElement.tooltip = this.sourceBlock_;\n  Blockly.Tooltip && Blockly.Tooltip.bindMouseEvents(topElement);\n};\n\n/**\n * Dispose of all DOM objects belonging to this text.\n */\nBlockly.FieldImage.prototype.dispose = function() {\n  goog.dom.removeNode(this.fieldGroup_);\n  this.fieldGroup_ = null;\n  this.imageElement_ = null;\n  this.rectElement_ = null;\n};\n\n/**\n * Change the tooltip text for this field.\n * @param {string|!Element} newTip Text for tooltip or a parent element to\n *     link to for its tooltip.\n */\nBlockly.FieldImage.prototype.setTooltip = function(newTip) {\n  var topElement = this.rectElement_ || this.imageElement_;\n  topElement.tooltip = newTip;\n};\n\n/**\n * Get the source URL of this image.\n * @return {string} Current text.\n * @override\n */\nBlockly.FieldImage.prototype.getValue = function() {\n  return this.src_;\n};\n\n/**\n * Set the source URL of this image.\n * @param {?string} src New source.\n * @override\n */\nBlockly.FieldImage.prototype.setValue = function(src) {\n  if (src === null) {\n    // No change if null.\n    return;\n  }\n  this.src_ = src;\n  this.imageElement_.setAttributeNS('http://www.w3.org/1999/xlink',\n      'xlink:href', goog.isString(src) ? src : '');\n};\n\n/**\n * Set the alt text of this image.\n * @param {?string} alt New alt text.\n * @override\n */\nBlockly.FieldImage.prototype.setText = function(alt) {\n  if (alt === null) {\n    // No change if null.\n    return;\n  }\n  this.text_ = alt;\n};\n"
  },
  {
    "path": "extern/blockly/core/field_keydown_input.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Text input field.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldKeydownInput');\n\ngoog.require('Blockly.Field');\ngoog.require('Blockly.Msg');\ngoog.require('goog.asserts');\ngoog.require('goog.userAgent');\n\n\n/**\n * Class for an editable text field.\n * @param {string} text The initial content of the field.\n * @param {Function} opt_changeHandler An optional function that is called\n *     to validate any constraints on what the user entered.  Takes the new\n *     text as an argument and returns either the accepted text, a replacement\n *     text, or null to abort the change.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldKeydownInput = function(value) {\n  this.arrow_ = Blockly.createSvgElement('tspan', {}, null);\n  var keyMap = Entry.getKeyCodeMap();\n  this.value_ = value;\n  Blockly.FieldKeydownInput.superClass_.constructor.call(this, keyMap[value]);\n};\ngoog.inherits(Blockly.FieldKeydownInput, Blockly.Field);\n\nvar fkip = Blockly.FieldKeydownInput.prototype;\n\n\n/**\n * Clone this FieldKeydownInput.\n * @return {!Blockly.FieldTextInput} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nfkip.clone = function() {\n  return new Blockly.FieldKeydownInput(this.getText(), this.changeHandler_);\n};\n\n/**\n * Create the dropdown field's elements.  Only needs to be called once.\n * @return {!Element} The field's SVG group.\n */\nBlockly.FieldKeydownInput.createDom = function() {\n  var url = Blockly.mediaFilePath + 'media/keyboard_workspace.png';\n  var svgGroup = Blockly.createSvgElement('g',\n      {'class': 'blocklyHelperDiv blocklyHidden'}, null);\n  var helpImg = Blockly.createSvgElement('image',\n      {'class': 'blocklyHelperImg',\n       'width': '249',\n       'height': '106'\n      }, svgGroup);\n  helpImg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',\n      url);\n\n  Blockly.FieldKeydownInput.helperSvgGroup_ = svgGroup;\n  return svgGroup;\n};\n\n/**\n * Mouse cursor style when over the hotspot that initiates the editor.\n */\nfkip.CURSOR = 'pointer';\n\n/**\n * Dispose of all DOM objects belonging to this editable field.\n */\nfkip.dispose = function() {\n  Blockly.WidgetDiv.hideIfField(this);\n  Blockly.FieldTextInput.superClass_.dispose.call(this);\n};\n\n/**\n * Set the text in this field.\n * @param {?string} keycode New text.\n * @override\n */\nfkip.setText = function(text) {\n  if (text === null)\n    return;\n  if (!text)\n      Blockly.Field.prototype.setText.call(this, '   ');\n  else\n      Blockly.Field.prototype.setText.call(this, text);\n};\n\n\n/**\n * Show the inline free-text editor on top of the text.\n * @private\n */\nfkip.showEditor_ = function() {\n  Blockly.WidgetDiv.show(this, this.dispose_());\n  var div = Blockly.WidgetDiv.DIV;\n  // Create the input.\n  var htmlInput = goog.dom.createDom('input', 'blocklyHtmlInput');\n  Blockly.FieldTextInput.htmlInput_ = htmlInput;\n  div.appendChild(htmlInput);\n\n  htmlInput.value = htmlInput.defaultValue = this.text_;\n  htmlInput.oldValue_ = null;\n  this.resizeEditor_();\n  htmlInput.focus();\n  htmlInput.select();\n\n  // Bind to keyup -- trap Enter and Esc; resize after every keystroke.\n  htmlInput.onKeyUpWrapper_ =\n      Blockly.bindEvent_(htmlInput, 'keyup', this, this.onHtmlInputChange_);\n  // Bind to keyPress -- repeatedly resize when holding down a key.\n  //htmlInput.onKeyPressWrapper_ =\n      //Blockly.bindEvent_(htmlInput, 'keypress', this, this.onHtmlInputChange_);\n  htmlInput.onBlurWrapper_ =\n      Blockly.bindEvent_(htmlInput, 'blur', this, Blockly.WidgetDiv.hide);\n  htmlInput.onBlurWrapper_ =\n      Blockly.bindEvent_(htmlInput, 'blur', this, Blockly.FieldKeydownInput.hide);\n  var workspaceSvg = this.sourceBlock_.workspace.getCanvas();\n\n  var helperSvgGroup = Blockly.FieldKeydownInput.helperSvgGroup_;\n  Blockly.removeClass_(helperSvgGroup, 'blocklyHidden');\n  var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.borderRect_));\n  var borderBBox = this.borderRect_.getBBox();\n  helperSvgGroup.setAttribute('transform',\n      'translate(' + (xy.x - 15 + borderBBox.width/2) + ', ' + (xy.y + 19) + ')');\n};\n\n\n/**\n * Handle a change to the editor.\n * @param {!Event} e Keyboard event.\n * @private\n */\nfkip.onHtmlInputChange_ = function(e) {\n  var htmlInput = Blockly.FieldTextInput.htmlInput_;\n  htmlInput.value = '';\n  var c = e.keyCode;\n  if ((c>=65 && c<=90) || (c>=37 && c<=40) ||\n      (c>=48 && c<=57) ||  c == 32 || c == 13) {\n      Blockly.WidgetDiv.hide();\n   \t  Blockly.FieldKeydownInput.hide();\n      this.setValue(c);\n  }\n};\n\n/**\n * Close the editor, save the results, and dispose of the editable\n * text field's elements.\n * @return {!Function} Closure to call on destruction of the WidgetDiv.\n * @private\n */\nfkip.dispose_ = function() {\n  var thisField = this;\n  return function() {\n    var htmlInput = Blockly.FieldTextInput.htmlInput_;\n    var text;\n    // Save the edit (if it validates).\n    text = htmlInput.value;\n    // thisField.setText(text);\n    thisField.sourceBlock_.render();\n    Blockly.unbindEvent_(htmlInput.onKeyUpWrapper_);\n    //Blockly.unbindEvent_(htmlInput.onKeyPressWrapper_);\n    Blockly.FieldTextInput.htmlInput_ = null;\n  };\n};\n\n/**\n * Hide the dropdown menu.\n */\nBlockly.FieldKeydownInput.hide = function() {\n  var helperSvgGroup = Blockly.FieldKeydownInput.helperSvgGroup_;\n  if (helperSvgGroup) {\n    Blockly.addClass_(helperSvgGroup, 'blocklyHidden');\n  }\n};\n\n/**\n * Set the language-neutral value for this dropdown menu.\n * @param {string} value New value to set.\n */\nfkip.setValue = function(value) {\n  this.value_ = value;\n  var keyMap = Entry.getKeyCodeMap();\n  var text = keyMap[value];\n  if (text) {\n      this.setText(String(text));\n      return;\n  } else {\n      this.setText(Lang.Blocks.no_target);\n      return;\n  }\n};\n\n/**\n * Get the language-neutral value from this dropdown menu.\n * @return {string} Current text.\n */\nfkip.getValue = function() {\n  return String(this.value_);\n};\n\n/**\n * Resize the editor and the underlying block to fit the text.\n * @private\n */\nfkip.resizeEditor_ = function() {\n  var div = Blockly.WidgetDiv.DIV;\n  var bBox = this.fieldGroup_.getBBox();\n  div.style.width = bBox.width + 'px';\n  var xy = Blockly.getAbsoluteXY_(/** @type {!Element} */ (this.borderRect_),\n                                 this.sourceBlock_.workspace.svgGroup_.parentNode);\n  // In RTL mode block fields and LTR input fields the left edge moves,\n  // whereas the right edge is fixed.  Reposition the editor.\n  if (Blockly.RTL) {\n    var borderBBox = this.borderRect_.getBBox();\n    xy.x += borderBBox.width;\n    xy.x -= div.offsetWidth;\n  }\n  // Shift by a few pixels to line up exactly.\n  xy.y += 1;\n  if (goog.userAgent.WEBKIT) {\n    xy.y -= 3;\n  }\n  div.style.left = xy.x + 'px';\n  div.style.top = xy.y + 'px';\n};\n"
  },
  {
    "path": "extern/blockly/core/field_label.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Non-editable text field.  Used for titles, labels, etc.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldLabel');\n\ngoog.require('Blockly.Field');\ngoog.require('Blockly.Tooltip');\n\n\n/**\n * Class for a non-editable field.\n * @param {string} text The initial content of the field.\n * @param {string} color Color code of the field.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldLabel = function(text, color) {\n  this.sourceBlock_ = null;\n  // Build the DOM.\n  if (goog.isString(color))\n    this.textElement_ = Blockly.createSvgElement('text',\n        {'class': 'blocklyText', 'style': 'fill:' + color, 'y': 12}, null);\n  else\n    this.textElement_ = Blockly.createSvgElement('text',\n        {'class': 'blocklyText', 'y': 12}, null);\n  this.size_ = {height: 14, width: 0};\n  this.setText(text);\n};\ngoog.inherits(Blockly.FieldLabel, Blockly.Field);\n\n/**\n * Clone this FieldLabel.\n * @return {!Blockly.FieldLabel} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldLabel.prototype.clone = function() {\n  return new Blockly.FieldLabel(this.getText());\n};\n\n/**\n * Editable fields are saved by the XML renderer, non-editable fields are not.\n */\nBlockly.FieldLabel.prototype.EDITABLE = false;\n\n/**\n * Install this text on a block.\n * @param {!Blockly.Block} block The block containing this text.\n */\nBlockly.FieldLabel.prototype.init = function(block) {\n  if (this.sourceBlock_) {\n    throw 'Text has already been initialized once.';\n  }\n  this.sourceBlock_ = block;\n  block.getSvgRoot().appendChild(this.textElement_);\n\n  // Configure the field to be transparent with respect to tooltips.\n  this.textElement_.tooltip = this.sourceBlock_;\n  Blockly.Tooltip && Blockly.Tooltip.bindMouseEvents(this.textElement_);\n};\n\n/**\n * Dispose of all DOM objects belonging to this text.\n */\nBlockly.FieldLabel.prototype.dispose = function() {\n  goog.dom.removeNode(this.textElement_);\n  this.textElement_ = null;\n};\n\n/**\n * Gets the group element for this field.\n * Used for measuring the size and for positioning.\n * @return {!Element} The group element.\n */\nBlockly.FieldLabel.prototype.getRootElement = function() {\n  return /** @type {!Element} */ (this.textElement_);\n};\n\n/**\n * Change the tooltip text for this field.\n * @param {string|!Element} newTip Text for tooltip or a parent element to\n *     link to for its tooltip.\n */\nBlockly.FieldLabel.prototype.setTooltip = function(newTip) {\n  this.textElement_.tooltip = newTip;\n};\n"
  },
  {
    "path": "extern/blockly/core/field_textinput.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Text input field.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldTextInput');\n\ngoog.require('Blockly.Field');\ngoog.require('Blockly.Msg');\ngoog.require('goog.asserts');\ngoog.require('goog.userAgent');\n\n\n/**\n * Class for an editable text field.\n * @param {string} text The initial content of the field.\n * @param {Function} opt_changeHandler An optional function that is called\n *     to validate any constraints on what the user entered.  Takes the new\n *     text as an argument and returns either the accepted text, a replacement\n *     text, or null to abort the change.\n * @extends {Blockly.Field}\n * @constructor\n */\nBlockly.FieldTextInput = function(text, opt_changeHandler) {\n  Blockly.FieldTextInput.superClass_.constructor.call(this, text);\n\n  this.changeHandler_ = opt_changeHandler;\n  this.isTextInput = true;\n};\ngoog.inherits(Blockly.FieldTextInput, Blockly.Field);\n\n/**\n * Clone this FieldTextInput.\n * @return {!Blockly.FieldTextInput} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldTextInput.prototype.clone = function() {\n  return new Blockly.FieldTextInput(this.getText(), this.changeHandler_);\n};\n\n/**\n * Mouse cursor style when over the hotspot that initiates the editor.\n */\nBlockly.FieldTextInput.prototype.CURSOR = 'text';\n\n/**\n * Dispose of all DOM objects belonging to this editable field.\n */\nBlockly.FieldTextInput.prototype.dispose = function() {\n  Blockly.WidgetDiv.hideIfField(this);\n  Blockly.FieldTextInput.superClass_.dispose.call(this);\n};\n\n/**\n * Set the text in this field.\n * @param {?string} text New text.\n * @override\n */\nBlockly.FieldTextInput.prototype.setText = function(text) {\n  if (text === null) {\n    // No change if null.\n    return;\n  }\n  if (this.changeHandler_) {\n    var validated = this.changeHandler_(text);\n    // If the new text is invalid, validation returns null.\n    // In this case we still want to display the illegal result.\n    if (validated !== null && validated !== undefined) {\n      text = validated;\n    }\n  }\n  Blockly.Field.prototype.setText.call(this, text, true);\n};\n\n/**\n * Show the inline free-text editor on top of the text.\n * @private\n */\nBlockly.FieldTextInput.prototype.showEditor_ = function() {\n  if (goog.userAgent.MOBILE) {\n    // Mobile browsers have issues with in-line textareas (focus & keyboards).\n    var newValue = window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_);\n    if (this.changeHandler_) {\n      var override = this.changeHandler_(newValue);\n      if (override !== undefined) {\n        newValue = override;\n      }\n    }\n    if (newValue !== null) {\n      this.setText(newValue);\n    }\n    return;\n  }\n\n  Blockly.WidgetDiv.show(this, this.dispose_());\n  var div = Blockly.WidgetDiv.DIV;\n  // Create the input.\n  var htmlInput = goog.dom.createDom('input', 'blocklyHtmlInput');\n  Blockly.FieldTextInput.htmlInput_ = htmlInput;\n  div.appendChild(htmlInput);\n\n  htmlInput.value = htmlInput.defaultValue = this.text_;\n  htmlInput.oldValue_ = null;\n  this.validate_();\n  this.resizeEditor_();\n  htmlInput.focus();\n  htmlInput.select();\n\n  // Bind to keyup -- trap Enter and Esc; resize after every keystroke.\n  htmlInput.onKeyUpWrapper_ =\n      Blockly.bindEvent_(htmlInput, 'keyup', this, this.onHtmlInputChange_);\n  // Bind to keyPress -- repeatedly resize when holding down a key.\n  htmlInput.onKeyPressWrapper_ =\n      Blockly.bindEvent_(htmlInput, 'keypress', this, this.onHtmlInputChange_);\n  htmlInput.onBlurWrapper_ =\n      Blockly.bindEvent_(htmlInput, 'blur', this, Blockly.WidgetDiv.hide);\n  var workspaceSvg = this.sourceBlock_.workspace.getCanvas();\n  htmlInput.onWorkspaceChangeWrapper_ =\n      Blockly.bindEvent_(workspaceSvg, 'blocklyWorkspaceChange', this,\n      this.resizeEditor_);\n};\n\n/**\n * Handle a change to the editor.\n * @param {!Event} e Keyboard event.\n * @private\n */\nBlockly.FieldTextInput.prototype.onHtmlInputChange_ = function(e) {\n  var htmlInput = Blockly.FieldTextInput.htmlInput_;\n  if (e.keyCode == 13) {\n    // Enter\n    Blockly.WidgetDiv.hide();\n  } else if (e.keyCode == 27) {\n    // Esc\n    this.setText(htmlInput.defaultValue);\n    Blockly.WidgetDiv.hide();\n  } else {\n    // Update source block.\n    var text = htmlInput.value;\n    if (text !== htmlInput.oldValue_) {\n      htmlInput.oldValue_ = text;\n      this.setText(text);\n      this.validate_();\n    } else if (goog.userAgent.WEBKIT) {\n      // Cursor key.  Render the source block to show the caret moving.\n      // Chrome only (version 26, OS X).\n      this.sourceBlock_.render();\n    }\n  }\n};\n\n/**\n * Check to see if the contents of the editor validates.\n * Style the editor accordingly.\n * @private\n */\nBlockly.FieldTextInput.prototype.validate_ = function() {\n  var valid = true;\n  goog.asserts.assertObject(Blockly.FieldTextInput.htmlInput_);\n  var htmlInput = /** @type {!Element} */ (Blockly.FieldTextInput.htmlInput_);\n  if (this.changeHandler_) {\n    valid = this.changeHandler_(htmlInput.value);\n  }\n  if (valid === null) {\n    Blockly.addClass_(htmlInput, 'blocklyInvalidInput');\n  } else {\n    Blockly.removeClass_(htmlInput, 'blocklyInvalidInput');\n  }\n};\n\n/**\n * Resize the editor and the underlying block to fit the text.\n * @private\n */\nBlockly.FieldTextInput.prototype.resizeEditor_ = function() {\n  var div = Blockly.WidgetDiv.DIV;\n  var bBox = this.fieldGroup_.getBBox();\n  div.style.width = bBox.width + 'px';\n  var xy = Blockly.getAbsoluteXY_(/** @type {!Element} */ (this.borderRect_),\n                                 this.sourceBlock_.workspace.svgGroup_.parentNode);\n  // In RTL mode block fields and LTR input fields the left edge moves,\n  // whereas the right edge is fixed.  Reposition the editor.\n  if (Blockly.RTL) {\n    var borderBBox = this.borderRect_.getBBox();\n    xy.x += borderBBox.width;\n    xy.x -= div.offsetWidth;\n  }\n  // Shift by a few pixels to line up exactly.\n  xy.y += 1;\n  if (goog.userAgent.WEBKIT) {\n    xy.y -= 3;\n  }\n  div.style.left = xy.x + 'px';\n  div.style.top = xy.y + 'px';\n};\n\n/**\n * Close the editor, save the results, and dispose of the editable\n * text field's elements.\n * @return {!Function} Closure to call on destruction of the WidgetDiv.\n * @private\n */\nBlockly.FieldTextInput.prototype.dispose_ = function() {\n  var thisField = this;\n  return function() {\n    var htmlInput = Blockly.FieldTextInput.htmlInput_;\n    var text;\n    // Save the edit (if it validates).\n    text = htmlInput.value;\n    if (thisField.changeHandler_) {\n      text = thisField.changeHandler_(text);\n      if (text === null) {\n        // Invalid edit.\n        text = htmlInput.defaultValue;\n      }\n    }\n    thisField.setText(text);\n    thisField.sourceBlock_.render();\n    Blockly.unbindEvent_(htmlInput.onKeyUpWrapper_);\n    Blockly.unbindEvent_(htmlInput.onKeyPressWrapper_);\n    Blockly.unbindEvent_(htmlInput.onWorkspaceChangeWrapper_);\n    Blockly.FieldTextInput.htmlInput_ = null;\n  };\n};\n\n/**\n * Ensure that only a number may be entered.\n * @param {string} text The user's text.\n * @return {?string} A string representing a valid number, or null if invalid.\n */\nBlockly.FieldTextInput.numberValidator = function(text) {\n  // TODO: Handle cases like 'ten', '1.203,14', etc.\n  // 'O' is sometimes mistaken for '0' by inexperienced users.\n  text = text.replace(/O/ig, '0');\n  // Strip out thousands separators.\n  text = text.replace(/,/g, '');\n  var n = parseFloat(text || 0);\n  return isNaN(n) ? null : String(n);\n};\n\n/**\n * Ensure that only a nonnegative integer may be entered.\n * @param {string} text The user's text.\n * @return {?string} A string representing a valid int, or null if invalid.\n */\nBlockly.FieldTextInput.nonnegativeIntegerValidator = function(text) {\n  var n = Blockly.FieldTextInput.numberValidator(text);\n  if (n) {\n    n = String(Math.max(0, Math.floor(n)));\n  }\n  return n;\n};\n"
  },
  {
    "path": "extern/blockly/core/field_variable.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Variable input field.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.FieldVariable');\n\ngoog.require('Blockly.FieldDropdown');\ngoog.require('Blockly.Msg');\ngoog.require('Blockly.Variables');\n\n\n/**\n * Class for a variable's dropdown field.\n * @param {!string} varname The default name for the variable.  If null,\n *     a unique variable name will be generated.\n * @param {Function} opt_changeHandler A function that is executed when a new\n *     option is selected.  Its sole argument is the new option value.  Its\n *     return value is ignored.\n * @extends {Blockly.FieldDropdown}\n * @constructor\n */\nBlockly.FieldVariable = function(varname, opt_changeHandler) {\n  var changeHandler;\n  if (opt_changeHandler) {\n    // Wrap the user's change handler together with the variable rename handler.\n    var thisObj = this;\n    changeHandler = function(value) {\n      var retVal = Blockly.FieldVariable.dropdownChange.call(thisObj, value);\n      var newVal;\n      if (retVal === undefined) {\n        newVal = value;  // Existing variable selected.\n      } else if (retVal === null) {\n        newVal = thisObj.getValue();  // Abort, no change.\n      } else {\n        newVal = retVal;  // Variable name entered.\n      }\n      opt_changeHandler.call(thisObj, newVal);\n      return retVal;\n    };\n  } else {\n    changeHandler = Blockly.FieldVariable.dropdownChange;\n  }\n\n  Blockly.FieldVariable.superClass_.constructor.call(this,\n      Blockly.FieldVariable.dropdownCreate, changeHandler);\n\n  if (varname) {\n    this.setValue(varname);\n  } else {\n    this.setValue(Blockly.Variables.generateUniqueName());\n  }\n};\ngoog.inherits(Blockly.FieldVariable, Blockly.FieldDropdown);\n\n/**\n * Clone this FieldVariable.\n * @return {!Blockly.FieldVariable} The result of calling the constructor again\n *   with the current values of the arguments used during construction.\n */\nBlockly.FieldVariable.prototype.clone = function() {\n  return new Blockly.FieldVariable(this.getValue(), this.changeHandler_);\n};\n\n/**\n * Get the variable's name (use a variableDB to convert into a real name).\n * Unline a regular dropdown, variables are literal and have no neutral value.\n * @return {string} Current text.\n */\nBlockly.FieldVariable.prototype.getValue = function() {\n  return this.getText();\n};\n\n/**\n * Set the variable name.\n * @param {string} text New text.\n */\nBlockly.FieldVariable.prototype.setValue = function(text) {\n  this.value_ = text;\n  this.setText(text);\n};\n\n/**\n * Return a sorted list of variable names for variable dropdown menus.\n * Include a special option at the end for creating a new variable name.\n * @return {!Array.<string>} Array of variable names.\n * @this {!Blockly.FieldVariable}\n */\nBlockly.FieldVariable.dropdownCreate = function() {\n  var variableList = Blockly.Variables.allVariables();\n  // Ensure that the currently selected variable is an option.\n  var name = this.getText();\n  if (name && variableList.indexOf(name) == -1) {\n    variableList.push(name);\n  }\n  variableList.sort(goog.string.caseInsensitiveCompare);\n  variableList.push(Blockly.Msg.RENAME_VARIABLE);\n  variableList.push(Blockly.Msg.NEW_VARIABLE);\n  // Variables are not language-specific, use the name as both the user-facing\n  // text and the internal representation.\n  var options = [];\n  for (var x = 0; x < variableList.length; x++) {\n    options[x] = [variableList[x], variableList[x]];\n  }\n  return options;\n};\n\n/**\n * Event handler for a change in variable name.\n * Special case the 'New variable...' and 'Rename variable...' options.\n * In both of these special cases, prompt the user for a new name.\n * @param {string} text The selected dropdown menu option.\n * @return {null|undefined|string} An acceptable new variable name, or null if\n *     change is to be either aborted (cancel button) or has been already\n *     handled (rename), or undefined if an existing variable was chosen.\n * @this {!Blockly.FieldVariable}\n */\nBlockly.FieldVariable.dropdownChange = function(text) {\n  function promptName(promptText, defaultText) {\n    Blockly.hideChaff();\n    var newVar = window.prompt(promptText, defaultText);\n    // Merge runs of whitespace.  Strip leading and trailing whitespace.\n    // Beyond this, all names are legal.\n    return newVar && newVar.replace(/[\\s\\xa0]+/g, ' ').replace(/^ | $/g, '');\n  }\n  if (text == Blockly.Msg.RENAME_VARIABLE) {\n    var oldVar = this.getText();\n    text = promptName(Blockly.Msg.RENAME_VARIABLE_TITLE.replace('%1', oldVar),\n                      oldVar);\n    if (text) {\n      Blockly.Variables.renameVariable(oldVar, text);\n    }\n    return null;\n  } else if (text == Blockly.Msg.NEW_VARIABLE) {\n    text = promptName(Blockly.Msg.NEW_VARIABLE_TITLE, '');\n    // Since variables are case-insensitive, ensure that if the new variable\n    // matches with an existing variable, the new case prevails throughout.\n    if (text) {\n      Blockly.Variables.renameVariable(text, text);\n      return text;\n    }\n    return null;\n  }\n  return undefined;\n};\n"
  },
  {
    "path": "extern/blockly/core/flyout.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Flyout tray containing blocks which may be created.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Flyout');\n\ngoog.require('Blockly.Block');\ngoog.require('Blockly.Comment');\n\n\n/**\n * Class for a flyout.\n * @constructor\n */\nBlockly.Flyout = function() {\n  /**\n   * @type {!Blockly.Workspace}\n   * @private\n   */\n  var flyout = this;\n  this.workspace_ = new Blockly.Workspace(\n      function() {return flyout.getMetrics_();},\n      function(ratio) {return flyout.setMetrics_(ratio);});\n  this.workspace_.isFlyout = true;\n\n  /**\n   * Opaque data that can be passed to removeChangeListener.\n   * @type {Array.<!Array>}\n   * @private\n   */\n  this.changeWrapper_ = null;\n\n  /**\n   * @type {number}\n   * @private\n   */\n  this.width_ = 0;\n\n  /**\n   * @type {number}\n   * @private\n   */\n  this.height_ = 0;\n\n  /**\n   * List of background buttons that lurk behind each block to catch clicks\n   * landing in the blocks' lakes and bays.\n   * @type {!Array.<!Element>}\n   * @private\n   */\n  this.buttons_ = [];\n\n  /**\n   * List of event listeners.\n   * @type {!Array.<!Array>}\n   * @private\n   */\n  this.listeners_ = [];\n};\n\n/**\n * Does the flyout automatically close when a block is created?\n * @type {boolean}\n */\nBlockly.Flyout.prototype.autoClose = true;\n\n/**\n * Corner radius of the flyout background.\n * @type {number}\n * @const\n */\nBlockly.Flyout.prototype.CORNER_RADIUS = 8;\n\n/**\n * Wrapper function called when a resize occurs.\n * @type {Array.<!Array>}\n * @private\n */\nBlockly.Flyout.prototype.onResizeWrapper_ = null;\n\n/**\n * Creates the flyout's DOM.  Only needs to be called once.\n * @return {!Element} The flyout's SVG group.\n */\nBlockly.Flyout.prototype.createDom = function() {\n  /*\n  <g>\n    <path class=\"blocklyFlyoutBackground\"/>\n    <g></g>\n  </g>\n  */\n  this.svgGroup_ = Blockly.createSvgElement('g', {}, null);\n  this.svgBackground_ = Blockly.createSvgElement('path',\n      {'class': 'blocklyFlyoutBackground'}, this.svgGroup_);\n  this.svgGroup_.appendChild(this.workspace_.createDom());\n  return this.svgGroup_;\n};\n\n/**\n * Dispose of this flyout.\n * Unlink from all DOM elements to prevent memory leaks.\n */\nBlockly.Flyout.prototype.dispose = function() {\n  this.hide();\n  if (this.onResizeWrapper_) {\n    Blockly.unbindEvent_(this.onResizeWrapper_);\n    this.onResizeWrapper_ = null;\n  }\n  if (this.changeWrapper_) {\n    Blockly.unbindEvent_(this.changeWrapper_);\n    this.changeWrapper_ = null;\n  }\n  if (this.scrollbar_) {\n    this.scrollbar_.dispose();\n    this.scrollbar_ = null;\n  }\n  this.workspace_ = null;\n  if (this.svgGroup_) {\n    goog.dom.removeNode(this.svgGroup_);\n    this.svgGroup_ = null;\n  }\n  this.svgBackground_ = null;\n  this.targetWorkspace_ = null;\n};\n\n/**\n * Return an object with all the metrics required to size scrollbars for the\n * flyout.  The following properties are computed:\n * .viewHeight: Height of the visible rectangle,\n * .viewWidth: Width of the visible rectangle,\n * .contentHeight: Height of the contents,\n * .viewTop: Offset of top edge of visible rectangle from parent,\n * .contentTop: Offset of the top-most content from the y=0 coordinate,\n * .absoluteTop: Top-edge of view.\n * .absoluteLeft: Left-edge of view.\n * @return {Object} Contains size and position metrics of the flyout.\n * @private\n */\nBlockly.Flyout.prototype.getMetrics_ = function() {\n  if (!this.isVisible()) {\n    // Flyout is hidden.\n    return null;\n  }\n  var viewHeight = this.height_ - 2 * this.CORNER_RADIUS;\n  var viewWidth = this.width_;\n  try {\n    var optionBox = this.workspace_.getCanvas().getBBox();\n  } catch (e) {\n    // Firefox has trouble with hidden elements (Bug 528969).\n    var optionBox = {height: 0, y: 0};\n  }\n  return {\n    viewHeight: viewHeight,\n    viewWidth: viewWidth,\n    contentHeight: optionBox.height + optionBox.y,\n    viewTop: -this.workspace_.scrollY,\n    contentTop: 0,\n    absoluteTop: this.CORNER_RADIUS,\n    absoluteLeft: 0\n  };\n};\n\n/**\n * Sets the Y translation of the flyout to match the scrollbars.\n * @param {!Object} yRatio Contains a y property which is a float\n *     between 0 and 1 specifying the degree of scrolling.\n * @private\n */\nBlockly.Flyout.prototype.setMetrics_ = function(yRatio) {\n  var metrics = this.getMetrics_();\n  // This is a fix to an apparent race condition.\n  if (!metrics) {\n    return;\n  }\n  if (goog.isNumber(yRatio.y)) {\n    this.workspace_.scrollY =\n        -metrics.contentHeight * yRatio.y - metrics.contentTop;\n  }\n  var y = this.workspace_.scrollY + metrics.absoluteTop;\n  this.workspace_.getCanvas().setAttribute('transform',\n                                           'translate(0,' + y + ')');\n};\n\n/**\n * Initializes the flyout.\n * @param {!Blockly.Workspace} workspace The workspace in which to create new\n *     blocks.\n * @param {boolean} withScrollbar True if a scrollbar should be displayed.\n */\nBlockly.Flyout.prototype.init =\n    function(workspace, withScrollbar) {\n  this.targetWorkspace_ = workspace;\n  // Add scrollbars.\n  var flyout = this;\n  if (withScrollbar) {\n    this.scrollbar_ = new Blockly.Scrollbar(flyout.workspace_, false, false);\n  }\n\n  this.hide();\n\n  // If the document resizes, reposition the flyout.\n  this.onResizeWrapper_ = Blockly.bindEvent_(window,\n      goog.events.EventType.RESIZE, this, this.position_);\n  this.position_();\n  this.changeWrapper_ = Blockly.bindEvent_(this.targetWorkspace_.getCanvas(),\n      'blocklyWorkspaceChange', this, this.filterForCapacity_);\n};\n\n/**\n * Move the toolbox to the edge of the workspace.\n * @private\n */\nBlockly.Flyout.prototype.position_ = function() {\n  if (!this.isVisible()) {\n    return;\n  }\n  var metrics = this.targetWorkspace_.getMetrics();\n  if (!metrics) {\n    // Hidden components will return null.\n    return;\n  }\n  var edgeWidth = this.width_ - this.CORNER_RADIUS;\n  if (Blockly.RTL) {\n    edgeWidth *= -1;\n  }\n  // var path = ['M ' + (Blockly.RTL ? this.width_ : 0) + ',0'];\n  // path.push('h', edgeWidth);\n  // path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,\n  //     Blockly.RTL ? 0 : 1,\n  //     Blockly.RTL ? -this.CORNER_RADIUS : this.CORNER_RADIUS,\n  //     this.CORNER_RADIUS);\n  // path.push('v', Math.max(0, metrics.viewHeight - this.CORNER_RADIUS * 2));\n  // path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0,\n  //     Blockly.RTL ? 0 : 1,\n  //     Blockly.RTL ? this.CORNER_RADIUS : -this.CORNER_RADIUS,\n  //     this.CORNER_RADIUS);\n  // path.push('h', -edgeWidth);\n  // path.push('z');\n  var path = ['M ' + (Blockly.RTL ? this.width_ : 0) + ',0'];\n  path.push('h', edgeWidth);\n  path.push('v', Math.max(0, metrics.viewHeight));\n  path.push('h', -edgeWidth);\n  path.push('z');\n  this.svgBackground_.setAttribute('d', path.join(' '));\n\n  var x = metrics.absoluteLeft;\n  if (Blockly.RTL) {\n    x += metrics.viewWidth;\n    x -= this.width_;\n  }\n  this.svgGroup_.setAttribute('transform',\n      'translate(' + x + ',' + metrics.absoluteTop + ')');\n\n  // Record the height for Blockly.Flyout.getMetrics_.\n  this.height_ = metrics.viewHeight;\n\n  // Update the scrollbar (if one exists).\n  if (this.scrollbar_) {\n    this.scrollbar_.resize();\n  }\n};\n\n/**\n * Is the flyout visible?\n * @return {boolean} True if visible.\n */\nBlockly.Flyout.prototype.isVisible = function() {\n  return this.svgGroup_.style.display == 'block';\n};\n\n/**\n * Hide and empty the flyout.\n */\nBlockly.Flyout.prototype.hide = function() {\n  if (!this.isVisible()) {\n    return;\n  }\n  this.svgGroup_.style.display = 'none';\n  // Delete all the event listeners.\n  for (var x = 0, listen; listen = this.listeners_[x]; x++) {\n    Blockly.unbindEvent_(listen);\n  }\n  this.listeners_.splice(0);\n  if (this.reflowWrapper_) {\n    Blockly.unbindEvent_(this.reflowWrapper_);\n    this.reflowWrapper_ = null;\n  }\n};\n\n/**\n * Show and populate the flyout.\n * @param {!Array|string} xmlList List of blocks to show.\n *     Variables and procedures have a custom set of blocks.\n */\nBlockly.Flyout.prototype.show = function(xmlList) {\n  this.hide();\n  var blocks = this.workspace_.getTopBlocks(false);\n  for (var x = 0, block; block = blocks[x]; x++) {\n    if (block.workspace == this.workspace_) {\n      block.dispose(false, false);\n    }\n  }\n  // Delete all the blocks.\n  // Delete all the background buttons.\n  for (var x = 0, rect; rect = this.buttons_[x]; x++) {\n    goog.dom.removeNode(rect);\n  }\n  this.buttons_.splice(0);\n\n  var margin = this.CORNER_RADIUS;\n  this.svgGroup_.style.display = 'block';\n\n  // Create the blocks to be shown in this flyout.\n  var blocks = [];\n  var gaps = [];\n  if (xmlList == Blockly.Variables.NAME_TYPE) {\n    // Special category for variables.\n    Blockly.Variables.flyoutCategory(blocks, gaps, margin,\n        /** @type {!Blockly.Workspace} */ (this.workspace_));\n  } else if (xmlList == Blockly.Procedures.NAME_TYPE) {\n    // Special category for procedures.\n    Blockly.Procedures.flyoutCategory(blocks, gaps, margin,\n        /** @type {!Blockly.Workspace} */ (this.workspace_));\n  } else {\n    for (var i = 0, xml; xml = xmlList[i]; i++) {\n      if (xml.tagName && xml.tagName.toUpperCase() == 'BLOCK') {\n        var block = Blockly.Xml.domToBlock(\n            /** @type {!Blockly.Workspace} */ (this.workspace_), xml);\n        blocks.push(block);\n        gaps.push(margin);\n      }\n    }\n  }\n\n  // Lay out the blocks vertically.\n  var cursorY = margin;\n  for (var i = 0, block; block = blocks[i]; i++) {\n    var allBlocks = block.getDescendants();\n    for (var j = 0, child; child = allBlocks[j]; j++) {\n      // Mark blocks as being inside a flyout.  This is used to detect and\n      // prevent the closure of the flyout if the user right-clicks on such a\n      // block.\n      child.isInFlyout = true;\n      // There is no good way to handle comment bubbles inside the flyout.\n      // Blocks shouldn't come with predefined comments, but someone will\n      // try this, I'm sure.  Kill the comment.\n      Blockly.Comment && child.setCommentText(null);\n    }\n    block.render();\n    var root = block.getSvgRoot();\n    var blockHW = block.getHeightWidth();\n    var x = Blockly.RTL ? 0 : margin + Blockly.BlockSvg.TAB_WIDTH * 0.5;\n    if (block.outputConnection)\n      x += blockHW.height/2;\n    else if (!block.previousConnection && block.nextConnection)\n      x += 10;\n    block.moveBy(x, cursorY);\n    cursorY += blockHW.height + gaps[i];\n\n    // Create an invisible rectangle under the block to act as a button.  Just\n    // using the block as a button is poor, since blocks have holes in them.\n    var rect = Blockly.createSvgElement('rect', {'fill-opacity': 0}, null);\n    // Add the rectangles under the blocks, so that the blocks' tooltips work.\n    this.workspace_.getCanvas().insertBefore(rect, block.getSvgRoot());\n    block.flyoutRect_ = rect;\n    this.buttons_[i] = rect;\n\n    if (this.autoClose && block.isAddable()) {\n      this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null,\n          this.createBlockFunc_(block)));\n    } else if (block.isAddable()) {\n      this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null,\n          this.blockMouseDown_(block)));\n    }\n    this.listeners_.push(Blockly.bindEvent_(root, 'mouseover', block.svg_,\n        block.svg_.addSelect));\n    this.listeners_.push(Blockly.bindEvent_(root, 'mouseout', block.svg_,\n        block.svg_.removeSelect));\n    this.listeners_.push(Blockly.bindEvent_(rect, 'mousedown', null,\n        this.createBlockFunc_(block)));\n    this.listeners_.push(Blockly.bindEvent_(rect, 'mouseover', block.svg_,\n        block.svg_.addSelect));\n    this.listeners_.push(Blockly.bindEvent_(rect, 'mouseout', block.svg_,\n        block.svg_.removeSelect));\n  }\n  this.width_ = 0;\n  this.reflow();\n\n  this.filterForCapacity_();\n\n  // Fire a resize event to update the flyout's scrollbar.\n  Blockly.fireUiEvent(window, 'resize');\n  this.reflowWrapper_ = Blockly.bindEvent_(this.workspace_.getCanvas(),\n      'blocklyWorkspaceChange', this, this.reflow);\n  this.workspace_.fireChangeEvent();\n};\n\n/**\n * Compute width of flyout.  Position button under each block.\n * For RTL: Lay out the blocks right-aligned.\n */\nBlockly.Flyout.prototype.reflow = function() {\n  var flyoutWidth = 0;\n  var margin = this.CORNER_RADIUS;\n  var blocks = this.workspace_.getTopBlocks(false);\n  for (var x = 0, block; block = blocks[x]; x++) {\n    var root = block.getSvgRoot();\n    var blockHW = block.getHeightWidth();\n    flyoutWidth = Math.max(flyoutWidth, blockHW.width);\n  }\n  flyoutWidth += margin + Blockly.BlockSvg.TAB_WIDTH + margin / 2 +\n                 Blockly.Scrollbar.scrollbarThickness;\n  if (this.width_ != flyoutWidth) {\n    for (var x = 0, block; block = blocks[x]; x++) {\n      var blockHW = block.getHeightWidth();\n      var blockXY = block.getRelativeToSurfaceXY();\n      if (Blockly.RTL) {\n        // With the flyoutWidth known, right-align the blocks.\n        var dx = flyoutWidth - margin - Blockly.BlockSvg.TAB_WIDTH - blockXY.x;\n        block.moveBy(dx, 0);\n        blockXY.x += dx;\n      }\n      if (block.flyoutRect_) {\n        block.flyoutRect_.setAttribute('width', blockHW.width);\n        block.flyoutRect_.setAttribute('height', blockHW.height);\n        block.flyoutRect_.setAttribute('x',\n            Blockly.RTL ? blockXY.x - blockHW.width : blockXY.x);\n        block.flyoutRect_.setAttribute('y', blockXY.y);\n      }\n    }\n    // Record the width for .getMetrics_ and .position_.\n    this.width_ = flyoutWidth;\n    // Fire a resize event to update the flyout's scrollbar.\n    Blockly.fireUiEvent(window, 'resize');\n  }\n};\n\n/**\n * Move a block to a specific location on the drawing surface.\n * @param {number} dx Horizontal location.\n * @param {number} dy Vertical location.\n */\nBlockly.Block.prototype.moveTo = function(x, y) {\n  var oldXY = this.getRelativeToSurfaceXY();\n  this.svg_.getRootElement().setAttribute('transform',\n      'translate(' + x + ', ' + y + ')');\n  this.moveConnections_(x - oldXY.x, y - oldXY.y);\n};\n\n/**\n * Handle a mouse-down on an SVG block in a non-closing flyout.\n * @param {!Blockly.Block} originBlock The flyout block to copy.\n * @return {!Function} Function to call when block is clicked.\n * @private\n */\nBlockly.Flyout.prototype.blockMouseDown_ = function(block) {\n  var flyout = this;\n  return function(e) {\n    Blockly.terminateDrag_();\n    Blockly.hideChaff();\n    if (Blockly.isRightButton(e)) {\n      // Right-click.\n      if (Blockly.ContextMenu) {\n        block.showContextMenu_(Blockly.mouseToSvg(e));\n      }\n    } else {\n      // Left-click (or middle click)\n      Blockly.removeAllRanges();\n      Blockly.setCursorHand_(true);\n      // Record the current mouse position.\n      Blockly.Flyout.startDownEvent_ = e;\n      Blockly.Flyout.startBlock_ = block;\n      Blockly.Flyout.startFlyout_ = flyout;\n      Blockly.Flyout.onMouseUpWrapper_ = Blockly.bindEvent_(document,\n          'mouseup', this, Blockly.terminateDrag_);\n      Blockly.Flyout.onMouseMoveWrapper_ = Blockly.bindEvent_(document,\n          'mousemove', this, flyout.onMouseMove_);\n    }\n    // This event has been handled.  No need to bubble up to the document.\n    e.stopPropagation();\n  };\n};\n\n/**\n * Mouse button is down on a block in a non-closing flyout.  Create the block\n * if the mouse moves beyond a small radius.  This allows one to play with\n * fields without instantiating blocks that instantly self-destruct.\n * @param {!Event} e Mouse move event.\n * @private\n */\nBlockly.Flyout.prototype.onMouseMove_ = function(e) {\n  if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 &&\n      e.button == 0) {\n    /* HACK:\n     Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove events\n     on certain touch actions. Ignore events with these signatures.\n     This may result in a one-pixel blind spot in other browsers,\n     but this shouldn't be noticable. */\n    e.stopPropagation();\n    return;\n  }\n  Blockly.removeAllRanges();\n  var dx = e.clientX - Blockly.Flyout.startDownEvent_.clientX;\n  var dy = e.clientY - Blockly.Flyout.startDownEvent_.clientY;\n  // Still dragging within the sticky DRAG_RADIUS.\n  var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));\n  if (dr > Blockly.DRAG_RADIUS) {\n    // Create the block.\n    Blockly.Flyout.startFlyout_.createBlockFunc_(Blockly.Flyout.startBlock_)\n        (Blockly.Flyout.startDownEvent_);\n  }\n};\n\n/**\n * Create a copy of this block on the workspace.\n * @param {!Blockly.Block} originBlock The flyout block to copy.\n * @return {!Function} Function to call when block is clicked.\n * @private\n */\nBlockly.Flyout.prototype.createBlockFunc_ = function(originBlock) {\n  var flyout = this;\n  return function(e) {\n    if (Blockly.isRightButton(e)) {\n      // Right-click.  Don't create a block, let the context menu show.\n      return;\n    }\n    if (originBlock.disabled) {\n      // Beyond capacity.\n      return;\n    }\n    // Create the new block by cloning the block in the flyout (via XML).\n    if (typeof(Entry) == \"object\") {\n        Entry.dispatchEvent(\"entryBlocklyChanged\");\n    }\n    var xml = Blockly.Xml.blockToDom_(originBlock);\n    var block = Blockly.Xml.domToBlock(flyout.targetWorkspace_, xml);\n    // Place it in the same spot as the flyout copy.\n    var svgRootOld = originBlock.getSvgRoot();\n    if (!svgRootOld) {\n      throw 'originBlock is not rendered.';\n    }\n    var xyOld = Blockly.getSvgXY_(svgRootOld);\n    var svgRootNew = block.getSvgRoot();\n    if (!svgRootNew) {\n      throw 'block is not rendered.';\n    }\n    var xyNew = Blockly.getSvgXY_(svgRootNew);\n    block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y);\n    if (flyout.autoClose) {\n      flyout.hide();\n    } else {\n      flyout.filterForCapacity_();\n    }\n    // Start a dragging operation on the new block.\n    block.onMouseDown_(e);\n  };\n};\n\n/**\n * Filter the blocks on the flyout to disable the ones that are above the\n * capacity limit.\n * @private\n */\nBlockly.Flyout.prototype.filterForCapacity_ = function() {\n  var remainingCapacity = this.targetWorkspace_.remainingCapacity();\n  var blocks = this.workspace_.getTopBlocks(false);\n  for (var i = 0, block; block = blocks[i]; i++) {\n    var allBlocks = block.getDescendants();\n    var disabled = allBlocks.length > remainingCapacity;\n    block.setDisabled(disabled);\n  }\n};\n\n/**\n * Stop binding to the global mouseup and mousemove events.\n * @private\n */\nBlockly.Flyout.terminateDrag_ = function() {\n  if (Blockly.Flyout.onMouseUpWrapper_) {\n    Blockly.unbindEvent_(Blockly.Flyout.onMouseUpWrapper_);\n    Blockly.Flyout.onMouseUpWrapper_ = null;\n  }\n  if (Blockly.Flyout.onMouseMoveWrapper_) {\n    Blockly.unbindEvent_(Blockly.Flyout.onMouseMoveWrapper_);\n    Blockly.Flyout.onMouseMoveWrapper_ = null;\n  }\n  Blockly.Flyout.startDownEvent_ = null;\n  Blockly.Flyout.startBlock_ = null;\n  Blockly.Flyout.startFlyout_ = null;\n};\n"
  },
  {
    "path": "extern/blockly/core/generator.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Utility functions for generating executable code from\n * Blockly code.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Generator');\n\ngoog.require('Blockly.Block');\n\n\n/**\n * Class for a code generator that translates the blocks into a language.\n * @param {string} name Language name of this generator.\n * @constructor\n */\nBlockly.Generator = function(name) {\n  this.name_ = name;\n  this.RESERVED_WORDS_ = '';\n};\n\n/**\n * Category to separate generated function names from variables and procedures.\n */\nBlockly.Generator.NAME_TYPE = 'generated_function';\n\n/**\n * Generate code for all blocks in the workspace to the specified language.\n * @return {string} Generated code.\n */\nBlockly.Generator.prototype.workspaceToCode = function() {\n  var code = [];\n  this.init();\n  var blocks = Blockly.mainWorkspace.getTopBlocks(true);\n\n  for (var x = 0, block; block = blocks[x]; x++) {\n    var line = this.blockToCode(block);\n    if (line instanceof Array) {\n      // Value blocks return tuples of code and operator order.\n      // Top-level blocks don't care about operator order.\n      line = line[0];\n    }\n    if (line) {\n      if (block.outputConnection && this.scrubNakedValue) {\n        // This block is a naked value.  Ask the language's code generator if\n        // it wants to append a semicolon, or something.\n        line = this.scrubNakedValue(line);\n      }\n      code.push(line);\n    }\n  }\n  code = code.join('\\n');  // Blank line between each section.\n  code = this.finish(code);\n  // Final scrubbing of whitespace.\n  code = code.replace(/^\\s+\\n/, '');\n  code = code.replace(/\\n\\s+$/, '\\n');\n  code = code.replace(/[ \\t]+\\n/g, '\\n');\n  return code;\n};\n\n/**\n * Generate code for all blocks in the tutorial workspace only attached to 'when_start' to the specified language.\n * @return {string} Generated code.\n */\nBlockly.Generator.prototype.tutorialWorkspaceToCode = function() {\n  var code = [];\n  this.init();\n  var blocks = Blockly.mainWorkspace.getTopBlocks(true);\n  var targetBlocks = [];\n  for (var i=0; i<blocks.length; i++) {\n      if (blocks[i].type == 'when_start' || blocks[i].type == 'declare_function') {\n        targetBlocks.push(blocks[i]);\n      }\n  }\n\n  for (var x = 0, block; block = targetBlocks[x]; x++) {\n    var line = this.blockToCode(block);\n    if (line instanceof Array) {\n      // Value blocks return tuples of code and operator order.\n      // Top-level blocks don't care about operator order.\n      line = line[0];\n    }\n    if (line) {\n      if (block.outputConnection && this.scrubNakedValue) {\n        // This block is a naked value.  Ask the language's code generator if\n        // it wants to append a semicolon, or something.\n        line = this.scrubNakedValue(line);\n      }\n      code.push(line);\n    }\n  }\n  code = code.join('\\n');  // Blank line between each section.\n  code = this.finish(code);\n  // Final scrubbing of whitespace.\n  code = code.replace(/^\\s+\\n/, '');\n  code = code.replace(/\\n\\s+$/, '\\n');\n  code = code.replace(/[ \\t]+\\n/g, '\\n');\n  return code;\n};\n\n// The following are some helpful functions which can be used by multiple\n// languages.\n\n/**\n * Prepend a common prefix onto each line of code.\n * @param {string} text The lines of code.\n * @param {string} prefix The common prefix.\n * @return {string} The prefixed lines of code.\n */\nBlockly.Generator.prototype.prefixLines = function(text, prefix) {\n  return prefix + text.replace(/\\n(.)/g, '\\n' + prefix + '$1');\n};\n\n/**\n * Recursively spider a tree of blocks, returning all their comments.\n * @param {!Blockly.Block} block The block from which to start spidering.\n * @return {string} Concatenated list of comments.\n */\nBlockly.Generator.prototype.allNestedComments = function(block) {\n  var comments = [];\n  var blocks = block.getDescendants();\n  for (var x = 0; x < blocks.length; x++) {\n    var comment = blocks[x].getCommentText();\n    if (comment) {\n      comments.push(comment);\n    }\n  }\n  // Append an empty string to create a trailing line break when joined.\n  if (comments.length) {\n    comments.push('');\n  }\n  return comments.join('\\n');\n};\n\n/**\n * Generate code for the specified block (and attached blocks).\n * @param {Blockly.Block} block The block to generate code for.\n * @return {string|!Array} For statement blocks, the generated code.\n *     For value blocks, an array containing the generated code and an\n *     operator order value.  Returns '' if block is null.\n */\nBlockly.Generator.prototype.blockToCode = function(block) {\n  if (!block) {\n    return '';\n  }\n  if (block.disabled) {\n    // Skip past this block if it is disabled.\n    var nextBlock = block.nextConnection && block.nextConnection.targetBlock();\n    return this.blockToCode(nextBlock);\n  }\n\n  var func = this[block.type];\n  if (!func) {\n    throw 'Language \"' + this.name_ + '\" does not know how to generate code ' +\n        'for block type \"' + block.type + '\".';\n  }\n  // First argument to func.call is the value of 'this' in the generator.\n  // Prior to 24 September 2013 'this' was the only way to access the block.\n  // The current prefered method of accessing the block is through the second\n  // argument to func.call, which becomes the first parameter to the generator.\n  var code = func.call(block, block);\n  if (code instanceof Array) {\n    // Value blocks return tuples of code and operator order.\n    return [this.scrub_(block, code[0]), code[1]];\n  } else {\n    return this.scrub_(block, code);\n  }\n};\n\n/**\n * Generate code representing the specified value input.\n * @param {!Blockly.Block} block The block containing the input.\n * @param {string} name The name of the input.\n * @param {number} order The maximum binding strength (minimum order value)\n *     of any operators adjacent to \"block\".\n * @return {string} Generated code or '' if no blocks are connected or the\n *     specified input does not exist.\n */\nBlockly.Generator.prototype.valueToCode = function(block, name, order) {\n  if (isNaN(order)) {\n    throw 'Expecting valid order from block \"' + block.type + '\".';\n  }\n  var targetBlock = block.getInputTargetBlock(name);\n  if (!targetBlock) {\n    return '';\n  }\n  var tuple = this.blockToCode(targetBlock);\n  if (tuple === '') {\n    // Disabled block.\n    return '';\n  }\n  if (!(tuple instanceof Array)) {\n    // Value blocks must return code and order of operations info.\n    // Statement blocks must only return code.\n    throw 'Expecting tuple from value block \"' + targetBlock.type + '\".';\n  }\n  var code = tuple[0];\n  var innerOrder = tuple[1];\n  if (isNaN(innerOrder)) {\n    throw 'Expecting valid order from value block \"' + targetBlock.type + '\".';\n  }\n  if (code && order <= innerOrder) {\n    if (order == innerOrder || (order == 0 || order == 99)) {\n      // 0 is the atomic order, 99 is the none order.  No parentheses needed.\n      // In all known languages multiple such code blocks are not order\n      // sensitive.  In fact in Python ('a' 'b') 'c' would fail.\n    } else {\n      // The operators outside this code are stonger than the operators\n      // inside this code.  To prevent the code from being pulled apart,\n      // wrap the code in parentheses.\n      // Technically, this should be handled on a language-by-language basis.\n      // However all known (sane) languages use parentheses for grouping.\n      code = '(' + code + ')';\n    }\n  }\n  return code;\n};\n\n/**\n * Generate code representing the statement.  Indent the code.\n * @param {!Blockly.Block} block The block containing the input.\n * @param {string} name The name of the input.\n * @return {string} Generated code or '' if no blocks are connected.\n */\nBlockly.Generator.prototype.statementToCode = function(block, name) {\n  var targetBlock = block.getInputTargetBlock(name);\n  var code = this.blockToCode(targetBlock);\n  if (!goog.isString(code)) {\n    // Value blocks must return code and order of operations info.\n    // Statement blocks must only return code.\n    throw 'Expecting code from statement block \"' + targetBlock.type + '\".';\n  }\n  if (code) {\n    code = this.prefixLines(/** @type {string} */ (code), '  ');\n  }\n  return code;\n};\n\n/**\n * Add one or more words to the list of reserved words for this language.\n * @param {string} words Comma-separated list of words to add to the list.\n *     No spaces.  Duplicates are ok.\n */\nBlockly.Generator.prototype.addReservedWords = function(words) {\n  this.RESERVED_WORDS_ += words + ',';\n};\n\n/**\n * This is used as a placeholder in functions defined using\n * Blockly.Generator.provideFunction_.  It must not be legal code that could\n * legitimately appear in a function definition (or comment), and it must\n * not confuse the regular expression parser.\n */\nBlockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}';\nBlockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_REGEXP_ =\n    new RegExp(Blockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_, 'g');\n\n/**\n * Define a function to be included in the generated code.\n * The first time this is called with a given desiredName, the code is\n * saved and an actual name is generated.  Subsequent calls with the\n * same desiredName have no effect but have the same return value.\n *\n * It is up to the caller to make sure the same desiredName is not\n * used for different code values.\n *\n * The code gets output when Blockly.Generator.finish() is called.\n *\n * @param {string} desiredName The desired name of the function (e.g., isPrime).\n * @param {string} code A list of Python statements.\n * @return {string} The actual name of the new function.  This may differ\n *     from desiredName if the former has already been taken by the user.\n * @private\n */\nBlockly.Generator.prototype.provideFunction_ = function(desiredName, code) {\n  if (!this.definitions_[desiredName]) {\n    var functionName =\n        this.variableDB_.getDistinctName(desiredName, this.NAME_TYPE);\n    this.functionNames_[desiredName] = functionName;\n    this.definitions_[desiredName] = code.join('\\n').replace(\n        this.FUNCTION_NAME_PLACEHOLDER_REGEXP_, functionName);\n  }\n  return this.functionNames_[desiredName];\n};\n"
  },
  {
    "path": "extern/blockly/core/icon.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2013 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing an icon on a block.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Icon');\n\n/**\n * Class for an icon.\n * @param {Blockly.Block} block The block associated with this icon.\n * @constructor\n */\nBlockly.Icon = function(block) {\n  this.block_ = block;\n};\n\n/**\n * Radius of icons.\n */\nBlockly.Icon.RADIUS = 8;\n\n/**\n * Bubble UI (if visible).\n * @type {Blockly.Bubble}\n * @private\n */\nBlockly.Icon.prototype.bubble_ = null;\n\n/**\n * Absolute X coordinate of icon's center.\n * @private\n */\nBlockly.Icon.prototype.iconX_ = 0;\n\n/**\n * Absolute Y coordinate of icon's centre.\n * @private\n */\nBlockly.Icon.prototype.iconY_ = 0;\n\n/**\n * Create the icon on the block.\n * @private\n */\nBlockly.Icon.prototype.createIcon_ = function() {\n  /* Here's the markup that will be generated:\n  <g class=\"blocklyIconGroup\"></g>\n  */\n  this.iconGroup_ = Blockly.createSvgElement('g', {}, null);\n  this.block_.getSvgRoot().appendChild(this.iconGroup_);\n  Blockly.bindEvent_(this.iconGroup_, 'mouseup', this, this.iconClick_);\n  this.updateEditable();\n};\n\n/**\n * Dispose of this icon.\n */\nBlockly.Icon.prototype.dispose = function() {\n  // Dispose of and unlink the icon.\n  goog.dom.removeNode(this.iconGroup_);\n  this.iconGroup_ = null;\n  // Dispose of and unlink the bubble.\n  this.setVisible(false);\n  this.block_ = null;\n};\n\n/**\n * Add or remove the UI indicating if this icon may be clicked or not.\n */\nBlockly.Icon.prototype.updateEditable = function() {\n  if (!this.block_.isInFlyout) {\n    Blockly.addClass_(/** @type {!Element} */ (this.iconGroup_),\n                      'blocklyIconGroup');\n  } else {\n    Blockly.removeClass_(/** @type {!Element} */ (this.iconGroup_),\n                         'blocklyIconGroup');\n  }\n};\n\n/**\n * Is the associated bubble visible?\n * @return {boolean} True if the bubble is visible.\n */\nBlockly.Icon.prototype.isVisible = function() {\n  return !!this.bubble_;\n};\n\n/**\n * Clicking on the icon toggles if the bubble is visible.\n * @param {!Event} e Mouse click event.\n * @private\n */\nBlockly.Icon.prototype.iconClick_ = function(e) {\n  if (!this.block_.isInFlyout) {\n    this.setVisible(!this.isVisible());\n  }\n};\n\n/**\n * Change the colour of the associated bubble to match its block.\n */\nBlockly.Icon.prototype.updateColour = function() {\n  if (this.isVisible()) {\n    var hexColour = Blockly.makeColour(this.block_.getColour());\n    this.bubble_.setColour(hexColour);\n  }\n};\n\n/**\n * Render the icon.\n * @param {number} cursorX Horizontal offset at which to position the icon.\n * @return {number} Horizontal offset for next item to draw.\n */\nBlockly.Icon.prototype.renderIcon = function(cursorX) {\n  if (this.block_.isCollapsed()) {\n    this.iconGroup_.setAttribute('display', 'none');\n    return cursorX;\n  }\n  this.iconGroup_.setAttribute('display', 'block');\n\n  var TOP_MARGIN = 5;\n  var diameter = 2 * Blockly.Icon.RADIUS;\n  if (Blockly.RTL) {\n    cursorX -= diameter;\n  }\n  this.iconGroup_.setAttribute('transform',\n      'translate(' + cursorX + ', ' + TOP_MARGIN + ')');\n  this.computeIconLocation();\n  if (Blockly.RTL) {\n    cursorX -= Blockly.BlockSvg.SEP_SPACE_X;\n  } else {\n    cursorX += diameter + Blockly.BlockSvg.SEP_SPACE_X;\n  }\n  return cursorX;\n};\n\n/**\n * Notification that the icon has moved.  Update the arrow accordingly.\n * @param {number} x Absolute horizontal location.\n * @param {number} y Absolute vertical location.\n */\nBlockly.Icon.prototype.setIconLocation = function(x, y) {\n  this.iconX_ = x;\n  this.iconY_ = y;\n  if (this.isVisible()) {\n    this.bubble_.setAnchorLocation(x, y);\n  }\n};\n\n/**\n * Notification that the icon has moved, but we don't really know where.\n * Recompute the icon's location from scratch.\n */\nBlockly.Icon.prototype.computeIconLocation = function() {\n  // Find coordinates for the centre of the icon and update the arrow.\n  var blockXY = this.block_.getRelativeToSurfaceXY();\n  var iconXY = Blockly.getRelativeXY_(this.iconGroup_);\n  var newX = blockXY.x + iconXY.x + Blockly.Icon.RADIUS;\n  var newY = blockXY.y + iconXY.y + Blockly.Icon.RADIUS;\n  if (newX !== this.iconX_ || newY !== this.iconY_) {\n    this.setIconLocation(newX, newY);\n  }\n};\n\n/**\n * Returns the center of the block's icon relative to the surface.\n * @return {!Object} Object with x and y properties.\n */\nBlockly.Icon.prototype.getIconLocation = function() {\n  return {x: this.iconX_, y: this.iconY_};\n};\n"
  },
  {
    "path": "extern/blockly/core/inject.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Functions for injecting Blockly into a web page.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.inject');\n\ngoog.require('Blockly.Css');\ngoog.require('goog.dom');\n\n/**\n * Initialize the SVG document with various handlers.\n * @param {!Element} container Containing element.\n * @param {Object} opt_options Optional dictionary of options.\n */\nBlockly.inject = function(container, opt_options) {\n    // Verify that the container is in document.\n    if (!goog.dom.contains(document, container)) {\n        throw 'Error: container is not in current document.';\n    }\n    if (opt_options) {\n        // TODO(scr): don't mix this in to global variables.\n        goog.mixin(Blockly, Blockly.parseOptions_(opt_options));\n    }\n    Blockly.createDom_(container);\n    Blockly.init_();\n};\n\n/**\n * Configure Blockly to behave according to a set of options.\n * @param {!Object} options Dictionary of options.\n * @return {Object} Parsed options.\n * @private\n */\nBlockly.parseOptions_ = function(options) {\n    var readOnly = !!options['readOnly'];\n    if (readOnly) {\n        var hasCategories = false;\n        var hasTrashcan = false;\n        var hasCollapse = false;\n        var tree = null;\n    } else {\n        var tree = options['toolbox'];\n        if (tree) {\n            if (typeof tree != 'string' && typeof XSLTProcessor == 'undefined') {\n                // In this case the tree will not have been properly built by the\n                // browser. The HTML will be contained in the element, but it will\n                // not have the proper DOM structure since the browser doesn't support\n                // XSLTProcessor (XML -> HTML). This is the case in IE 9+.\n                tree = tree.outerHTML;\n            }\n            if (typeof tree == 'string') {\n                tree = Blockly.Xml.textToDom(tree);\n            }\n            //var hasCategories = !!tree.getElementsByTagName('category').length;\n            var hasCategories = false;\n            try {\n                hasCategories = !!tree.getElementsByTagName('category').length;\n            } catch (err) {\n                hasCategories = false;\n            }\n        } else {\n            tree = null;\n            var hasCategories = false;\n        }\n        var hasTrashcan = options['trashcan'];\n        if (hasTrashcan === undefined) {\n            hasTrashcan = hasCategories;\n        }\n        var hasBlockMenu = options['blockmenu'];\n        if (!hasBlockMenu instanceof HTMLElement) {\n            hasBlockMenu = false;\n        }\n        var hasCollapse = options['collapse'];\n        if (hasCollapse === undefined) {\n            hasCollapse = hasCategories;\n        }\n    }\n    var hasScrollbars = options['scrollbars'];\n    if (hasScrollbars === undefined) {\n        hasScrollbars = true;\n    }\n    return {\n        RTL: !!options['rtl'],\n        collapse: hasCollapse,\n        readOnly: readOnly,\n        maxBlocks: options['maxBlocks'] || Infinity,\n        pathToBlockly: options['path'] || './',\n        hasCategories: hasCategories,\n        hasScrollbars: hasScrollbars,\n        hasTrashcan: hasTrashcan,\n        hasBlockMenu: hasBlockMenu,\n        languageTree: tree,\n        mediaFilePath: options['mediaFilePath'] || './',\n    };\n};\n\n/**\n * Create the SVG image.\n * @param {!Element} container Containing element.\n * @private\n */\nBlockly.createDom_ = function(container) {\n    // Sadly browsers (Chrome vs Firefox) are currently inconsistent in laying\n    // out content in RTL mode.  Therefore Blockly forces the use of LTR,\n    // then manually positions content in RTL as needed.\n    container.setAttribute('dir', 'LTR');\n    // Closure can be trusted to create HTML widgets with the proper direction.\n    goog.ui.Component.setDefaultRightToLeft(Blockly.RTL);\n\n    // Load CSS.\n    Blockly.Css.inject();\n\n    // Build the SVG DOM.\n    /*\n  <svg\n    xmlns=\"http://www.w3.org/2000/svg\"\n    xmlns:html=\"http://www.w3.org/1999/xhtml\"\n    xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n    version=\"1.1\"\n    class=\"blocklySvg\">\n    ...\n  </svg>\n  */\n    var svg = Blockly.createSvgElement(\n        'svg',\n        {\n            xmlns: 'http://www.w3.org/2000/svg',\n            'xmlns:html': 'http://www.w3.org/1999/xhtml',\n            'xmlns:xlink': 'http://www.w3.org/1999/xlink',\n            version: '1.1',\n            class: 'blocklySvg',\n        },\n        null\n    );\n    /*\n  <defs>\n    ... filters go here ...\n  </defs>\n  */\n    var defs = Blockly.createSvgElement('defs', {}, svg);\n    var filter, feSpecularLighting, feMerge, pattern, blockPattern, blockImg;\n    /*\n    <filter id=\"blocklyEmboss\">\n      <feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"1\" result=\"blur\"/>\n      <feSpecularLighting in=\"blur\" surfaceScale=\"1\" specularConstant=\"0.5\"\n                          specularExponent=\"10\" lighting-color=\"white\"\n                          result=\"specOut\">\n        <fePointLight x=\"-5000\" y=\"-10000\" z=\"20000\"/>\n      </feSpecularLighting>\n      <feComposite in=\"specOut\" in2=\"SourceAlpha\" operator=\"in\"\n                   result=\"specOut\"/>\n      <feComposite in=\"SourceGraphic\" in2=\"specOut\" operator=\"arithmetic\"\n                   k1=\"0\" k2=\"1\" k3=\"1\" k4=\"0\"/>\n    </filter>\n  */\n    filter = Blockly.createSvgElement('filter', { id: 'blocklyEmboss' }, defs);\n    Blockly.createSvgElement(\n        'feGaussianBlur',\n        { in: 'SourceAlpha', stdDeviation: 1, result: 'blur' },\n        filter\n    );\n    feSpecularLighting = Blockly.createSvgElement(\n        'feSpecularLighting',\n        {\n            in: 'blur',\n            surfaceScale: 1,\n            specularConstant: 0.5,\n            specularExponent: 10,\n            'lighting-color': 'white',\n            result: 'specOut',\n        },\n        filter\n    );\n    Blockly.createSvgElement('fePointLight', { x: -5000, y: -10000, z: 20000 }, feSpecularLighting);\n    Blockly.createSvgElement(\n        'feComposite',\n        {\n            in: 'specOut',\n            in2: 'SourceAlpha',\n            operator: 'in',\n            result: 'specOut',\n        },\n        filter\n    );\n    Blockly.createSvgElement(\n        'feComposite',\n        {\n            in: 'SourceGraphic',\n            in2: 'specOut',\n            operator: 'arithmetic',\n            k1: 0,\n            k2: 1,\n            k3: 1,\n            k4: 0,\n        },\n        filter\n    );\n    /*\n    <filter id=\"blocklyTrashcanShadowFilter\">\n      <feGaussianBlur in=\"SourceAlpha\" stdDeviation=\"2\" result=\"blur\"/>\n      <feOffset in=\"blur\" dx=\"1\" dy=\"1\" result=\"offsetBlur\"/>\n      <feMerge>\n        <feMergeNode in=\"offsetBlur\"/>\n        <feMergeNode in=\"SourceGraphic\"/>\n      </feMerge>\n    </filter>\n  */\n    filter = Blockly.createSvgElement('filter', { id: 'blocklyTrashcanShadowFilter' }, defs);\n    Blockly.createSvgElement(\n        'feGaussianBlur',\n        { in: 'SourceAlpha', stdDeviation: 2, result: 'blur' },\n        filter\n    );\n    Blockly.createSvgElement(\n        'feOffset',\n        { in: 'blur', dx: 1, dy: 1, result: 'offsetBlur' },\n        filter\n    );\n    feMerge = Blockly.createSvgElement('feMerge', {}, filter);\n    Blockly.createSvgElement('feMergeNode', { in: 'offsetBlur' }, feMerge);\n    Blockly.createSvgElement('feMergeNode', { in: 'SourceGraphic' }, feMerge);\n    /*\n    <filter id=\"blocklyShadowFilter\">\n      <feGaussianBlur stdDeviation=\"2\"/>\n    </filter>\n  */\n    filter = Blockly.createSvgElement('filter', { id: 'blocklyShadowFilter' }, defs);\n    Blockly.createSvgElement('feGaussianBlur', { stdDeviation: 2 }, filter);\n    /*\n    <pattern id=\"blocklyDisabledPattern\" patternUnits=\"userSpaceOnUse\"\n             width=\"10\" height=\"10\">\n      <rect width=\"10\" height=\"10\" fill=\"#aaa\" />\n      <path d=\"M 0 0 L 10 10 M 10 0 L 0 10\" stroke=\"#cc0\" />\n    </pattern>\n  */\n    pattern = Blockly.createSvgElement(\n        'pattern',\n        {\n            id: 'blocklyDisabledPattern',\n            patternUnits: 'userSpaceOnUse',\n            width: 10,\n            height: 10,\n        },\n        defs\n    );\n    Blockly.createSvgElement('rect', { width: 10, height: 10, fill: '#aaa' }, pattern);\n    Blockly.createSvgElement('path', { d: 'M 0 0 L 10 10 M 10 0 L 0 10', stroke: '#cc0' }, pattern);\n    for (var i = 1; i < 5; i++) {\n        blockPattern = Blockly.createSvgElement(\n            'pattern',\n            {\n                id: 'blockPattern' + i,\n                patternUnits: 'userSpaceOnUse',\n                width: 125,\n                height: 33,\n                x: 0,\n                y: 0,\n            },\n            defs\n        );\n        blockImg = Blockly.createSvgElement(\n            'image',\n            {\n                width: 125,\n                height: 33,\n                x: 0,\n                y: 0,\n            },\n            blockPattern\n        );\n        blockImg.setAttributeNS(\n            'http://www.w3.org/1999/xlink',\n            'xlink:href',\n            Blockly.mediaFilePath + 'block_pattern_' + i + '.png'\n        );\n    }\n    Blockly.mainWorkspace = new Blockly.Workspace(\n        Blockly.getMainWorkspaceMetrics_,\n        Blockly.setMainWorkspaceMetrics_\n    );\n    svg.appendChild(Blockly.mainWorkspace.createDom());\n    Blockly.mainWorkspace.maxBlocks = Blockly.maxBlocks;\n\n    if (!Blockly.readOnly) {\n        // Determine if there needs to be a category tree, or a simple list of\n        // blocks.  This cannot be changed later, since the UI is very different.\n        if (Blockly.hasCategories) {\n            Blockly.Toolbox.createDom(svg, container);\n        } else {\n            if (Blockly.hasBlockMenu) {\n                var blockMenu = new Blockly.BlockMenu(Blockly.hasBlockMenu);\n                Blockly.mainWorkspace.blockMenu = blockMenu;\n                Blockly.bindEvent_(\n                    blockMenu.menuView_,\n                    'wheel',\n                    blockMenu,\n                    Blockly.onMouseWheelFlyout_\n                );\n                //Blockly.bindEvent_(blockMenu.workspace_.svgGroup_, 'wheel', blockMenu, Blockly.onMouseWheelFlyout_);\n            }\n            /**\n             * @type {!Blockly.Flyout}\n             * @private\n             */\n            Blockly.mainWorkspace.flyout_ = new Blockly.Flyout();\n            var flyout = Blockly.mainWorkspace.flyout_;\n            var flyoutSvg = flyout.createDom();\n            flyout.init(Blockly.mainWorkspace, true);\n            Blockly.bindEvent_(flyoutSvg, 'wheel', flyout, Blockly.onMouseWheelFlyout_);\n            flyout.autoClose = false;\n            // Insert the flyout behind the workspace so that blocks appear on top.\n            goog.dom.insertSiblingAfter(flyoutSvg, Blockly.mainWorkspace.svgGroup_);\n            var workspaceChanged = function() {\n                /*\n           * prevent unintended block moving by scrolls\n           */\n                //if (Blockly.Block.dragMode_ == 0) {\n                //var metrics = Blockly.mainWorkspace.getMetrics();\n                //if (metrics.contentTop < 0 ||\n                //metrics.contentTop + metrics.contentHeight >\n                //metrics.viewHeight + metrics.viewTop ||\n                //metrics.contentLeft < (Blockly.RTL ? metrics.viewLeft : 0) ||\n                //metrics.contentLeft + metrics.contentWidth >\n                //metrics.viewWidth + (Blockly.RTL ? 2 : 1) * metrics.viewLeft) {\n                //// One or more blocks is out of bounds.  Bump them back in.\n                //var MARGIN = 25;\n                //var blocks = Blockly.mainWorkspace.getTopBlocks(false);\n                //for (var b = 0, block; block = blocks[b]; b++) {\n                //var blockXY = block.getRelativeToSurfaceXY();\n                //var blockHW = block.getHeightWidth();\n                //// Bump any block that's above the top back inside.\n                //var overflow = metrics.viewTop + MARGIN - blockHW.height -\n                //blockXY.y;\n                //if (overflow > 0) {\n                //block.moveBy(0, overflow);\n                //}\n                //// Bump any block that's below the bottom back inside.\n                //var overflow = metrics.viewTop + metrics.viewHeight - MARGIN -\n                //blockXY.y;\n                //if (overflow < 0) {\n                //block.moveBy(0, overflow);\n                //}\n                //// Bump any block that's off the left back inside.\n                //var overflow = MARGIN + metrics.viewLeft - blockXY.x -\n                //(Blockly.RTL ? 0 : blockHW.width);\n                //if (overflow > 0) {\n                //block.moveBy(overflow, 0);\n                //}\n                //// Bump any block that's off the right back inside.\n                //var overflow = metrics.viewLeft + metrics.viewWidth - MARGIN -\n                //blockXY.x + (Blockly.RTL ? blockHW.width : 0);\n                //if (overflow < 0) {\n                //block.moveBy(overflow, 0);\n                //}\n                //// Delete any block that's sitting on top of the flyout.\n                //if (typeof(Entry) == \"object\" && block.isDeletable() && (Blockly.RTL ?\n                //blockXY.x - 2 * metrics.viewLeft - metrics.viewWidth :\n                //-blockXY.x) > + Blockly.mainWorkspace.scrollX) {\n                ////block.dispose(false, true);\n                //}\n                //if (typeof(Entry) != \"object\" && block.isDeletable() && (Blockly.RTL ?\n                //blockXY.x - 2 * metrics.viewLeft - metrics.viewWidth :\n                //-blockXY.x) > + Blockly.mainWorkspace.scrollX - 150) {\n                ////block.dispose(false, true);\n                //}\n                //}\n                //}\n                //}\n            };\n            Blockly.addChangeListener(workspaceChanged);\n        }\n    }\n\n    Blockly.Tooltip && svg.appendChild(Blockly.Tooltip.createDom());\n    if (!Blockly.readOnly && Blockly.FieldDropdown) {\n        Blockly.fieldDropdownDom = Blockly.FieldDropdown.createDom();\n        svg.appendChild(Blockly.fieldDropdownDom);\n    }\n\n    if (!Blockly.readOnly && Blockly.FieldKeydownInput) {\n        Blockly.fieldKeydownDom = Blockly.FieldKeydownInput.createDom();\n        svg.appendChild(Blockly.fieldKeydownDom);\n    }\n\n    if (Blockly.ContextMenu && Blockly.ContextMenu) {\n        svg.appendChild(Blockly.ContextMenu.createDom());\n    }\n\n    // The SVG is now fully assembled.  Add it to the container.\n    container.appendChild(svg);\n    Blockly.bindEvent_(svg, 'mousedown', this, Blockly.hideChaff);\n    //if (typeof(Entry) == \"object\")\n    //Blockly.bindEvent_(svg, 'mousedown', this, Entry.stopInstantRun);\n    Blockly.bindEvent_(svg, 'wheel', this, Blockly.onMouseWheel_);\n    Blockly.svg = svg;\n    Blockly.svgResize();\n\n    // Create an HTML container for popup overlays (e.g. editor widgets).\n    Blockly.WidgetDiv.DIV = goog.dom.createDom('div', 'blocklyWidgetDiv');\n    document.body.appendChild(Blockly.WidgetDiv.DIV);\n};\n\n/**\n * Initialize Blockly with various handlers.\n * @private\n */\nBlockly.init_ = function() {\n    if (goog.userAgent.WEBKIT) {\n        /* HACK:\n     WebKit bug 67298 causes control points to be included in the reported\n     bounding box.  Detect if this browser suffers from this bug by drawing a\n     shape that is 50px high, and has a control point that sticks up by 5px.\n     If the getBBox function returns a height of 55px instead of 50px, then\n     this browser has broken control points.\n    */\n        var path = Blockly.createSvgElement(\n            'path',\n            { d: 'm 0,0 c 0,-5 0,-5 0,0 H 50 V 50 z' },\n            Blockly.svg\n        );\n        if (path.getBBox().height > 50) {\n            // Chrome (v28) and Opera (v15) report 55, Safari (v6.0.5) reports 53.75.\n            Blockly.BROKEN_CONTROL_POINTS = true;\n        }\n        Blockly.svg.removeChild(path);\n    }\n\n    // Bind events for scrolling the workspace.\n    // Most of these events should be bound to the SVG's surface.\n    // However, 'mouseup' has to be on the whole document so that a block dragged\n    // out of bounds and released will know that it has been released.\n    // Also, 'keydown' has to be on the whole document since the browser doesn't\n    // understand a concept of focus on the SVG image.\n    Blockly.bindEvent_(Blockly.svg, 'mousedown', null, Blockly.onMouseDown_);\n    Blockly.bindEvent_(Blockly.svg, 'mousemove', null, Blockly.onMouseMove_);\n    Blockly.bindEvent_(Blockly.svg, 'contextmenu', null, Blockly.onContextMenu_);\n\n    if (!Blockly.documentEventsBound_) {\n        // Only bind the window/document events once.\n        // Destroying and reinjecting Blockly should not bind again.\n        Blockly.bindEvent_(window, 'resize', document, Blockly.svgResize);\n        Blockly.bindEvent_(document, 'mouseup', null, Blockly.onMouseUp_);\n        Blockly.bindEvent_(document, 'keydown', null, Blockly.onKeyDown_);\n        // Some iPad versions don't fire resize after portrait to landscape change.\n        if (goog.userAgent.IPAD) {\n            Blockly.bindEvent_(\n                window,\n                'orientationchange',\n                document,\n                function() {\n                    Blockly.fireUiEvent(window, 'resize');\n                },\n                false\n            );\n        }\n        Blockly.documentEventsBound_ = true;\n    }\n\n    if (Blockly.languageTree) {\n        if (Blockly.hasCategories) {\n            Blockly.Toolbox.init();\n        } else {\n            // Build a fixed flyout with the root blocks.\n            Blockly.mainWorkspace.flyout_.init(Blockly.mainWorkspace, true);\n            Blockly.mainWorkspace.flyout_.show(Blockly.languageTree.childNodes);\n            // Translate the workspace sideways to avoid the fixed flyout.\n            Blockly.mainWorkspace.scrollX = Blockly.mainWorkspace.flyout_.width_;\n            var translation = 'translate(' + Blockly.mainWorkspace.scrollX + ', 0)';\n            Blockly.mainWorkspace.getCanvas().setAttribute('transform', translation);\n            Blockly.mainWorkspace.getBubbleCanvas().setAttribute('transform', translation);\n        }\n    }\n    if (Blockly.hasScrollbars) {\n        Blockly.mainWorkspace.scrollbar = new Blockly.ScrollbarPair(Blockly.mainWorkspace);\n        Blockly.mainWorkspace.scrollbar.resize();\n    }\n\n    //Blockly.mainWorkspace.addConnectionAnimation();\n    Blockly.mainWorkspace.addTrashcan();\n\n    // Load the sounds.\n    /*\n  Blockly.loadAudio_(\n      ['media/click.mp3', 'media/click.wav', 'media/click.ogg'], 'click');\n  Blockly.loadAudio_(\n      ['media/delete.mp3', 'media/delete.ogg', 'media/delete.wav'], 'delete');\n  */\n};\n"
  },
  {
    "path": "extern/blockly/core/input.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing an input (value, statement, or dummy).\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Input');\n\n// TODO(scr): Fix circular dependencies\n// goog.require('Blockly.Block');\ngoog.require('Blockly.Connection');\ngoog.require('Blockly.FieldLabel');\ngoog.require('goog.asserts');\n\n\n/**\n * Class for an input with an optional field.\n * @param {number} type The type of the input.\n * @param {string} name Language-neutral identifier which may used to find this\n *     input again.\n * @param {!Blockly.Block} block The block containing this input.\n * @param {Blockly.Connection} connection Optional connection for this input.\n * @constructor\n */\nBlockly.Input = function(type, name, block, connection) {\n  this.type = type;\n  this.name = name;\n  this.sourceBlock_ = block;\n  this.connection = connection;\n  this.fieldRow = [];\n  this.align = Blockly.ALIGN_LEFT;\n\n  this.visible_ = true;\n};\n\n/**\n * Add an item to the end of the input's field row.\n * @param {string|!Blockly.Field} field Something to add as a field.\n * @param {string} opt_name Language-neutral identifier which may used to find\n *     this field again.  Should be unique to the host block.\n * @return {!Blockly.Input} The input being append to (to allow chaining).\n */\nBlockly.Input.prototype.appendField = function(field, opt_name) {\n  // Empty string, Null or undefined generates no field, unless field is named.\n  if (!field && !opt_name) {\n    return this;\n  }\n  // Generate a FieldLabel when given a plain text field.\n  if (goog.isString(field)) {\n    field = new Blockly.FieldLabel(/** @type {string} */ (field), opt_name);\n  }\n  if (this.sourceBlock_.svg_) {\n    field.init(this.sourceBlock_);\n  }\n  field.name = opt_name;\n\n  if (field.prefixField) {\n    // Add any prefix.\n    this.appendField(field.prefixField);\n  }\n  // Add the field to the field row.\n  this.fieldRow.push(field);\n  if (field.suffixField) {\n    // Add any suffix.\n    this.appendField(field.suffixField);\n  }\n\n  if (this.sourceBlock_.rendered) {\n    this.sourceBlock_.render();\n    // Adding a field will cause the block to change shape.\n    this.sourceBlock_.bumpNeighbours_();\n  }\n  return this;\n};\n\n/**\n * Add an item to the end of the input's field row.\n * @param {*} field Something to add as a field.\n * @param {string} opt_name Language-neutral identifier which may used to find\n *     this field again.  Should be unique to the host block.\n * @return {!Blockly.Input} The input being append to (to allow chaining).\n * @deprecated December 2013\n */\nBlockly.Input.prototype.appendTitle = function(field, opt_name) {\n  console.log('Deprecated call to appendTitle, use appendField instead.');\n  return this.appendField(field, opt_name);\n};\n\n/**\n * Remove a field from this input.\n * @param {string} name The name of the field.\n * @throws {goog.asserts.AssertionError} if the field is not present.\n */\nBlockly.Input.prototype.removeField = function(name) {\n  for (var i = 0, field; field = this.fieldRow[i]; i++) {\n    if (field.name === name) {\n      field.dispose();\n      this.fieldRow.splice(i, 1);\n      if (this.sourceBlock_.rendered) {\n        this.sourceBlock_.render();\n        // Removing a field will cause the block to change shape.\n        this.sourceBlock_.bumpNeighbours_();\n      }\n      return;\n    }\n  }\n  goog.asserts.fail('Field \"%s\" not found.', name);\n};\n\n/**\n * Gets whether this input is visible or not.\n * @return {boolean} True if visible.\n */\nBlockly.Input.prototype.isVisible = function() {\n  return this.visible_;\n};\n\n/**\n * Sets whether this input is visible or not.\n * @param {boolean} visible True if visible.\n * @return {!Array.<!Blockly.Block>} List of blocks to render.\n */\nBlockly.Input.prototype.setVisible = function(visible) {\n  var renderList = [];\n  if (this.visible_ == visible) {\n    return renderList;\n  }\n  this.visible_ = visible;\n\n  var display = visible ? 'block' : 'none';\n  for (var y = 0, field; field = this.fieldRow[y]; y++) {\n    field.setVisible(visible);\n  }\n  if (this.connection) {\n    // Has a connection.\n    if (visible) {\n      renderList = this.connection.unhideAll();\n    } else {\n      renderList = this.connection.hideAll();\n    }\n    var child = this.connection.targetBlock();\n    if (child) {\n      child.svg_.getRootElement().style.display = display;\n      if (!visible) {\n        child.rendered = false;\n      }\n    }\n  }\n  return renderList;\n};\n\n/**\n * Change a connection's compatibility.\n * @param {string|Array.<string>|null} check Compatible value type or\n *     list of value types.  Null if all types are compatible.\n * @return {!Blockly.Input} The input being modified (to allow chaining).\n */\nBlockly.Input.prototype.setCheck = function(check) {\n  if (!this.connection) {\n    throw 'This input does not have a connection.';\n  }\n  this.connection.setCheck(check);\n  return this;\n};\n\n/**\n * Change the alignment of the connection's field(s).\n * @param {number} align One of Blockly.ALIGN_LEFT, ALIGN_CENTRE, ALIGN_RIGHT.\n *   In RTL mode directions are reversed, and ALIGN_RIGHT aligns to the left.\n * @return {!Blockly.Input} The input being modified (to allow chaining).\n */\nBlockly.Input.prototype.setAlign = function(align) {\n  this.align = align;\n  if (this.sourceBlock_.rendered) {\n    this.sourceBlock_.render();\n  }\n  return this;\n};\n\n/**\n * Initialize the fields on this input.\n */\nBlockly.Input.prototype.init = function() {\n  for (var x = 0; x < this.fieldRow.length; x++) {\n    this.fieldRow[x].init(this.sourceBlock_);\n  }\n};\n\n/**\n * Sever all links to this input.\n */\nBlockly.Input.prototype.dispose = function() {\n  for (var i = 0, field; field = this.fieldRow[i]; i++) {\n    field.dispose();\n  }\n  if (this.connection) {\n    this.connection.dispose();\n  }\n  this.sourceBlock_ = null;\n};\n"
  },
  {
    "path": "extern/blockly/core/msg.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2013 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Core JavaScript library for Blockly.\n * @author scr@google.com (Sheridan Rawlins)\n */\n'use strict';\n\n/**\n * Name space for the Msg singleton.\n * Msg gets populated in the message files.\n */\ngoog.provide('Blockly.Msg');\n"
  },
  {
    "path": "extern/blockly/core/mutator.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing a mutator dialog.  A mutator allows the\n * user to change the shape of a block using a nested blocks editor.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Mutator');\n\ngoog.require('Blockly.Bubble');\ngoog.require('Blockly.Icon');\n\n\n/**\n * Class for a mutator dialog.\n * @param {!Array.<string>} quarkNames List of names of sub-blocks for flyout.\n * @extends {Blockly.Icon}\n * @constructor\n */\nBlockly.Mutator = function(quarkNames) {\n  Blockly.Mutator.superClass_.constructor.call(this, null);\n  this.quarkXml_ = [];\n  // Convert the list of names into a list of XML objects for the flyout.\n  for (var x = 0; x < quarkNames.length; x++) {\n    var element = goog.dom.createDom('block', {'type': quarkNames[x]});\n    this.quarkXml_[x] = element;\n  }\n};\ngoog.inherits(Blockly.Mutator, Blockly.Icon);\n\n/**\n * Width of workspace.\n * @private\n */\nBlockly.Mutator.prototype.workspaceWidth_ = 0;\n\n/**\n * Height of workspace.\n * @private\n */\nBlockly.Mutator.prototype.workspaceHeight_ = 0;\n\n/**\n * Create the icon on the block.\n */\nBlockly.Mutator.prototype.createIcon = function() {\n  Blockly.Icon.prototype.createIcon_.call(this);\n  /* Here's the markup that will be generated:\n  <rect class=\"blocklyIconShield\" width=\"16\" height=\"16\" rx=\"4\" ry=\"4\"/>\n  <text class=\"blocklyIconMark\" x=\"8\" y=\"12\">★</text>\n  */\n  var quantum = Blockly.Icon.RADIUS / 2;\n  var iconShield = Blockly.createSvgElement('rect',\n      {'class': 'blocklyIconShield',\n       'width': 4 * quantum,\n       'height': 4 * quantum,\n       'rx': quantum,\n       'ry': quantum}, this.iconGroup_);\n  this.iconMark_ = Blockly.createSvgElement('text',\n      {'class': 'blocklyIconMark',\n       'x': Blockly.Icon.RADIUS,\n       'y': 2 * Blockly.Icon.RADIUS - 4}, this.iconGroup_);\n  this.iconMark_.appendChild(document.createTextNode('\\u2605'));\n};\n\n/**\n * Clicking on the icon toggles if the mutator bubble is visible.\n * Disable if block is uneditable.\n * @param {!Event} e Mouse click event.\n * @private\n * @override\n */\nBlockly.Mutator.prototype.iconClick_ = function(e) {\n  if (this.block_.isEditable()) {\n    Blockly.Icon.prototype.iconClick_.call(this, e);\n  }\n};\n\n/**\n * Create the editor for the mutator's bubble.\n * @return {!Element} The top-level node of the editor.\n * @private\n */\nBlockly.Mutator.prototype.createEditor_ = function() {\n  /* Create the editor.  Here's the markup that will be generated:\n  <svg>\n    <rect class=\"blocklyMutatorBackground\" />\n    [Flyout]\n    [Workspace]\n  </svg>\n  */\n  this.svgDialog_ = Blockly.createSvgElement('svg',\n      {'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH},\n      null);\n  this.svgBackground_ = Blockly.createSvgElement('rect',\n      {'class': 'blocklyMutatorBackground',\n       'height': '100%', 'width': '100%'}, this.svgDialog_);\n\n  var mutator = this;\n  this.workspace_ = new Blockly.Workspace(\n      function() {return mutator.getFlyoutMetrics_();}, null);\n  this.flyout_ = new Blockly.Flyout();\n  this.flyout_.autoClose = false;\n  this.svgDialog_.appendChild(this.flyout_.createDom());\n  this.svgDialog_.appendChild(this.workspace_.createDom());\n  return this.svgDialog_;\n};\n\n/**\n * Add or remove the UI indicating if this icon may be clicked or not.\n */\nBlockly.Mutator.prototype.updateEditable = function() {\n  if (this.block_.isEditable()) {\n    // Default behaviour for an icon.\n    Blockly.Icon.prototype.updateEditable.call(this);\n  } else {\n    // Close any mutator bubble.  Icon is not clickable.\n    this.setVisible(false);\n    Blockly.removeClass_(/** @type {!Element} */ (this.iconGroup_),\n                         'blocklyIconGroup');\n  }\n};\n\n/**\n * Callback function triggered when the bubble has resized.\n * Resize the workspace accordingly.\n * @private\n */\nBlockly.Mutator.prototype.resizeBubble_ = function() {\n  var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH;\n  var workspaceSize = this.workspace_.getCanvas().getBBox();\n  var flyoutMetrics = this.flyout_.getMetrics_();\n  var width;\n  if (Blockly.RTL) {\n    width = -workspaceSize.x;\n  } else {\n    width = workspaceSize.width + workspaceSize.x;\n  }\n  var height = Math.max(workspaceSize.height + doubleBorderWidth * 3,\n                        flyoutMetrics.contentHeight + 20);\n  width += doubleBorderWidth * 3;\n  // Only resize if the size difference is significant.  Eliminates shuddering.\n  if (Math.abs(this.workspaceWidth_ - width) > doubleBorderWidth ||\n      Math.abs(this.workspaceHeight_ - height) > doubleBorderWidth) {\n    // Record some layout information for getFlyoutMetrics_.\n    this.workspaceWidth_ = width;\n    this.workspaceHeight_ = height;\n    // Resize the bubble.\n    this.bubble_.setBubbleSize(width + doubleBorderWidth,\n                               height + doubleBorderWidth);\n    this.svgDialog_.setAttribute('width', this.workspaceWidth_);\n    this.svgDialog_.setAttribute('height', this.workspaceHeight_);\n  }\n\n  if (Blockly.RTL) {\n    // Scroll the workspace to always left-align.\n    var translation = 'translate(' + this.workspaceWidth_ + ',0)';\n    this.workspace_.getCanvas().setAttribute('transform', translation);\n  }\n};\n\n/**\n * Show or hide the mutator bubble.\n * @param {boolean} visible True if the bubble should be visible.\n */\nBlockly.Mutator.prototype.setVisible = function(visible) {\n  if (visible == this.isVisible()) {\n    // No change.\n    return;\n  }\n  if (visible) {\n    // Create the bubble.\n    this.bubble_ = new Blockly.Bubble(this.block_.workspace,\n        this.createEditor_(), this.block_.svg_.svgGroup_,\n        this.iconX_, this.iconY_, null, null);\n    var thisObj = this;\n    this.flyout_.init(this.workspace_, false);\n    this.flyout_.show(this.quarkXml_);\n\n    this.rootBlock_ = this.block_.decompose(this.workspace_);\n    var blocks = this.rootBlock_.getDescendants();\n    for (var i = 0, child; child = blocks[i]; i++) {\n      child.render();\n    }\n    // The root block should not be dragable or deletable.\n    this.rootBlock_.setMovable(false);\n    this.rootBlock_.setDeletable(false);\n    var margin = this.flyout_.CORNER_RADIUS * 2;\n    var x = this.flyout_.width_ + margin;\n    if (Blockly.RTL) {\n      x = -x;\n    }\n    this.rootBlock_.moveBy(x, margin);\n    // Save the initial connections, then listen for further changes.\n    if (this.block_.saveConnections) {\n      this.block_.saveConnections(this.rootBlock_);\n      this.sourceListener_ = Blockly.bindEvent_(\n          this.block_.workspace.getCanvas(),\n          'blocklyWorkspaceChange', this.block_,\n          function() {thisObj.block_.saveConnections(thisObj.rootBlock_)});\n    }\n    this.resizeBubble_();\n    // When the mutator's workspace changes, update the source block.\n    Blockly.bindEvent_(this.workspace_.getCanvas(), 'blocklyWorkspaceChange',\n        this.block_, function() {thisObj.workspaceChanged_();});\n    this.updateColour();\n  } else {\n    // Dispose of the bubble.\n    this.svgDialog_ = null;\n    this.svgBackground_ = null;\n    this.flyout_.dispose();\n    this.flyout_ = null;\n    this.workspace_.dispose();\n    this.workspace_ = null;\n    this.rootBlock_ = null;\n    this.bubble_.dispose();\n    this.bubble_ = null;\n    this.workspaceWidth_ = 0;\n    this.workspaceHeight_ = 0;\n    if (this.sourceListener_) {\n      Blockly.unbindEvent_(this.sourceListener_);\n      this.sourceListener_ = null;\n    }\n  }\n};\n\n/**\n * Update the source block when the mutator's blocks are changed.\n * Delete or bump any block that's out of bounds.\n * Fired whenever a change is made to the mutator's workspace.\n * @private\n */\nBlockly.Mutator.prototype.workspaceChanged_ = function() {\n  if (Blockly.Block.dragMode_ == 0) {\n    var blocks = this.workspace_.getTopBlocks(false);\n    var MARGIN = 20;\n    for (var b = 0, block; block = blocks[b]; b++) {\n      var blockXY = block.getRelativeToSurfaceXY();\n      var blockHW = block.getHeightWidth();\n      if (Blockly.RTL ? blockXY.x > -this.flyout_.width_ + MARGIN :\n           blockXY.x < this.flyout_.width_ - MARGIN) {\n        // Delete any block that's sitting on top of the flyout.\n        block.dispose(false, true);\n      } else if (blockXY.y + blockHW.height < MARGIN) {\n        // Bump any block that's above the top back inside.\n        block.moveBy(0, MARGIN - blockHW.height - blockXY.y);\n      }\n    }\n  }\n\n  // When the mutator's workspace changes, update the source block.\n  if (this.rootBlock_.workspace == this.workspace_) {\n    // Switch off rendering while the source block is rebuilt.\n    var savedRendered = this.block_.rendered;\n    this.block_.rendered = false;\n    // Allow the source block to rebuild itself.\n    this.block_.compose(this.rootBlock_);\n    // Restore rendering and show the changes.\n    this.block_.rendered = savedRendered;\n    if (this.block_.rendered) {\n      this.block_.render();\n    }\n    this.resizeBubble_();\n    // The source block may have changed, notify its workspace.\n    this.block_.workspace.fireChangeEvent();\n  }\n};\n\n/**\n * Return an object with all the metrics required to size scrollbars for the\n * mutator flyout.  The following properties are computed:\n * .viewHeight: Height of the visible rectangle,\n * .absoluteTop: Top-edge of view.\n * .absoluteLeft: Left-edge of view.\n * @return {!Object} Contains size and position metrics of mutator dialog's\n *     workspace.\n * @private\n */\nBlockly.Mutator.prototype.getFlyoutMetrics_ = function() {\n  var left = 0;\n  if (Blockly.RTL) {\n    left += this.workspaceWidth_;\n  }\n  return {\n    viewHeight: this.workspaceHeight_,\n    viewWidth: 0,  // This seem wrong, but results in correct RTL layout.\n    absoluteTop: 0,\n    absoluteLeft: left\n  };\n};\n\n/**\n * Dispose of this mutator.\n */\nBlockly.Mutator.prototype.dispose = function() {\n  this.block_.mutator = null;\n  Blockly.Icon.prototype.dispose.call(this);\n};\n"
  },
  {
    "path": "extern/blockly/core/names.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Utility functions for handling variables and procedure names.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Names');\n\n\n/**\n * Class for a database of entity names (variables, functions, etc).\n * @param {string} reservedWords A comma-separated string of words that are\n *     illegal for use as names in a language (e.g. 'new,if,this,...').\n * @constructor\n */\nBlockly.Names = function(reservedWords) {\n  this.reservedDict_ = Object.create(null);\n  if (reservedWords) {\n    var splitWords = reservedWords.split(',');\n    for (var x = 0; x < splitWords.length; x++) {\n      this.reservedDict_[splitWords[x]] = true;\n    }\n  }\n  this.reset();\n};\n\n/**\n * When JavaScript (or most other languages) is generated, variable 'foo' and\n * procedure 'foo' would collide.  However, Blockly has no such problems since\n * variable get 'foo' and procedure call 'foo' are unambiguous.\n * Therefore, Blockly keeps a separate type name to disambiguate.\n * getName('foo', 'variable') -> 'foo'\n * getName('foo', 'procedure') -> 'foo2'\n */\n\n/**\n * Empty the database and start from scratch.  The reserved words are kept.\n */\nBlockly.Names.prototype.reset = function() {\n  this.db_ = Object.create(null);\n  this.dbReverse_ = Object.create(null);\n};\n\n/**\n * Convert a Blockly entity name to a legal exportable entity name.\n * @param {string} name The Blockly entity name (no constraints).\n * @param {string} type The type of entity in Blockly\n *     ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...).\n * @return {string} An entity name legal for the exported language.\n */\nBlockly.Names.prototype.getName = function(name, type) {\n  var normalized = name.toLowerCase() + '_' + type;\n  if (normalized in this.db_) {\n    return this.db_[normalized];\n  }\n  var safeName = this.getDistinctName(name, type);\n  this.db_[normalized] = safeName;\n  return safeName;\n};\n\n/**\n * Convert a Blockly entity name to a legal exportable entity name.\n * Ensure that this is a new name not overlapping any previously defined name.\n * Also check against list of reserved words for the current language and\n * ensure name doesn't collide.\n * @param {string} name The Blockly entity name (no constraints).\n * @param {string} type The type of entity in Blockly\n *     ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...).\n * @return {string} An entity name legal for the exported language.\n */\nBlockly.Names.prototype.getDistinctName = function(name, type) {\n  var safeName = this.safeName_(name);\n  var i = '';\n  while (this.dbReverse_[safeName + i] ||\n         (safeName + i) in this.reservedDict_) {\n    // Collision with existing name.  Create a unique name.\n    i = i ? i + 1 : 2;\n  }\n  safeName += i;\n  this.dbReverse_[safeName] = true;\n  return safeName;\n};\n\n/**\n * Given a proposed entity name, generate a name that conforms to the\n * [_A-Za-z][_A-Za-z0-9]* format that most languages consider legal for\n * variables.\n * @param {string} name Potentially illegal entity name.\n * @return {string} Safe entity name.\n * @private\n */\nBlockly.Names.prototype.safeName_ = function(name) {\n  if (!name) {\n    name = 'unnamed';\n  } else {\n    // Unfortunately names in non-latin characters will look like\n    // _E9_9F_B3_E4_B9_90 which is pretty meaningless.\n    name = encodeURI(name.replace(/ /g, '_')).replace(/[^\\w]/g, '_');\n    // Most languages don't allow names with leading numbers.\n    if ('0123456789'.indexOf(name[0]) != -1) {\n      name = 'my_' + name;\n    }\n  }\n  return name;\n};\n\n/**\n * Do the given two entity names refer to the same entity?\n * Blockly names are case-insensitive.\n * @param {string} name1 First name.\n * @param {string} name2 Second name.\n * @return {boolean} True if names are the same.\n */\nBlockly.Names.equals = function(name1, name2) {\n  return name1.toLowerCase() == name2.toLowerCase();\n};\n"
  },
  {
    "path": "extern/blockly/core/procedures.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Utility functions for handling procedures.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Procedures');\n\n// TODO(scr): Fix circular dependencies\n// goog.require('Blockly.Block');\ngoog.require('Blockly.FieldVariable');\ngoog.require('Blockly.Names');\ngoog.require('Blockly.Workspace');\n\n\n/**\n * Category to separate procedure names from variables and generated functions.\n */\nBlockly.Procedures.NAME_TYPE = 'PROCEDURE';\n\n/**\n * Find all user-created procedure definitions.\n * @return {!Array.<!Array.<!Array>>} Pair of arrays, the\n *     first contains procedures without return variables, the second with.\n *     Each procedure is defined by a three-element list of name, parameter\n *     list, and return value boolean.\n */\nBlockly.Procedures.allProcedures = function() {\n  var blocks = Blockly.mainWorkspace.getAllBlocks();\n  var proceduresReturn = [];\n  var proceduresNoReturn = [];\n  for (var x = 0; x < blocks.length; x++) {\n    var func = blocks[x].getProcedureDef;\n    if (func) {\n      var tuple = func.call(blocks[x]);\n      if (tuple) {\n        if (tuple[2]) {\n          proceduresReturn.push(tuple);\n        } else {\n          proceduresNoReturn.push(tuple);\n        }\n      }\n    }\n  }\n\n  proceduresNoReturn.sort(Blockly.Procedures.procTupleComparator_);\n  proceduresReturn.sort(Blockly.Procedures.procTupleComparator_);\n  return [proceduresNoReturn, proceduresReturn];\n};\n\n/**\n * Comparison function for case-insensitive sorting of the first element of\n * a tuple.\n * @param {!Array} ta First tuple.\n * @param {!Array} tb Second tuple.\n * @return {number} -1, 0, or 1 to signify greater than, equality, or less than.\n * @private\n */\nBlockly.Procedures.procTupleComparator_ = function(ta, tb) {\n  var a = ta[0].toLowerCase();\n  var b = tb[0].toLowerCase();\n  if (a > b) {\n    return 1;\n  }\n  if (a < b) {\n    return -1;\n  }\n  return 0;\n};\n\n/**\n * Ensure two identically-named procedures don't exist.\n * @param {string} name Proposed procedure name.\n * @param {!Blockly.Block} block Block to disambiguate.\n * @return {string} Non-colliding name.\n */\nBlockly.Procedures.findLegalName = function(name, block) {\n  if (block.isInFlyout) {\n    // Flyouts can have multiple procedures called 'procedure'.\n    return name;\n  }\n  while (!Blockly.Procedures.isLegalName(name, block.workspace, block)) {\n    // Collision with another procedure.\n    var r = name.match(/^(.*?)(\\d+)$/);\n    if (!r) {\n      name += '2';\n    } else {\n      name = r[1] + (parseInt(r[2], 10) + 1);\n    }\n  }\n  return name;\n};\n\n/**\n * Does this procedure have a legal name?  Illegal names include names of\n * procedures already defined.\n * @param {string} name The questionable name.\n * @param {!Blockly.Workspace} workspace The workspace to scan for collisions.\n * @param {Blockly.Block} opt_exclude Optional block to exclude from\n *     comparisons (one doesn't want to collide with oneself).\n * @return {boolean} True if the name is legal.\n */\nBlockly.Procedures.isLegalName = function(name, workspace, opt_exclude) {\n  var blocks = workspace.getAllBlocks();\n  // Iterate through every block and check the name.\n  for (var x = 0; x < blocks.length; x++) {\n    if (blocks[x] == opt_exclude) {\n      continue;\n    }\n    var func = blocks[x].getProcedureDef;\n    if (func) {\n      var procName = func.call(blocks[x]);\n      if (Blockly.Names.equals(procName[0], name)) {\n        return false;\n      }\n    }\n  }\n  return true;\n};\n\n/**\n * Rename a procedure.  Called by the editable field.\n * @param {string} text The proposed new name.\n * @return {string} The accepted name.\n * @this {!Blockly.FieldVariable}\n */\nBlockly.Procedures.rename = function(text) {\n  // Strip leading and trailing whitespace.  Beyond this, all names are legal.\n  text = text.replace(/^[\\s\\xa0]+|[\\s\\xa0]+$/g, '');\n\n  // Ensure two identically-named procedures don't exist.\n  text = Blockly.Procedures.findLegalName(text, this.sourceBlock_);\n  // Rename any callers.\n  var blocks = this.sourceBlock_.workspace.getAllBlocks();\n  for (var x = 0; x < blocks.length; x++) {\n    var func = blocks[x].renameProcedure;\n    if (func) {\n      func.call(blocks[x], this.text_, text);\n    }\n  }\n  return text;\n};\n\n/**\n * Construct the blocks required by the flyout for the procedure category.\n * @param {!Array.<!Blockly.Block>} blocks List of blocks to show.\n * @param {!Array.<number>} gaps List of widths between blocks.\n * @param {number} margin Standard margin width for calculating gaps.\n * @param {!Blockly.Workspace} workspace The flyout's workspace.\n */\nBlockly.Procedures.flyoutCategory = function(blocks, gaps, margin, workspace) {\n  if (Blockly.Blocks['procedures_defnoreturn']) {\n    var block = Blockly.Block.obtain(workspace, 'procedures_defnoreturn');\n    block.initSvg();\n    blocks.push(block);\n    gaps.push(margin * 2);\n  }\n  if (Blockly.Blocks['procedures_defreturn']) {\n    var block = Blockly.Block.obtain(workspace, 'procedures_defreturn');\n    block.initSvg();\n    blocks.push(block);\n    gaps.push(margin * 2);\n  }\n  if (Blockly.Blocks['procedures_ifreturn']) {\n    var block = Blockly.Block.obtain(workspace, 'procedures_ifreturn');\n    block.initSvg();\n    blocks.push(block);\n    gaps.push(margin * 2);\n  }\n  if (gaps.length) {\n    // Add slightly larger gap between system blocks and user calls.\n    gaps[gaps.length - 1] = margin * 3;\n  }\n\n  function populateProcedures(procedureList, templateName) {\n    for (var x = 0; x < procedureList.length; x++) {\n      var block = Blockly.Block.obtain(workspace, templateName);\n      block.setFieldValue(procedureList[x][0], 'NAME');\n      var tempIds = [];\n      for (var t = 0; t < procedureList[x][1].length; t++) {\n        tempIds[t] = 'ARG' + t;\n      }\n      block.setProcedureParameters(procedureList[x][1], tempIds);\n      block.initSvg();\n      blocks.push(block);\n      gaps.push(margin * 2);\n    }\n  }\n\n  var tuple = Blockly.Procedures.allProcedures();\n  populateProcedures(tuple[0], 'procedures_callnoreturn');\n  populateProcedures(tuple[1], 'procedures_callreturn');\n};\n\n/**\n * Find all the callers of a named procedure.\n * @param {string} name Name of procedure.\n * @param {!Blockly.Workspace} workspace The workspace to find callers in.\n * @return {!Array.<!Blockly.Block>} Array of caller blocks.\n */\nBlockly.Procedures.getCallers = function(name, workspace) {\n  var callers = [];\n  var blocks = workspace.getAllBlocks();\n  // Iterate through every block and check the name.\n  for (var x = 0; x < blocks.length; x++) {\n    var func = blocks[x].getProcedureCall;\n    if (func) {\n      var procName = func.call(blocks[x]);\n      // Procedure name may be null if the block is only half-built.\n      if (procName && Blockly.Names.equals(procName, name)) {\n        callers.push(blocks[x]);\n      }\n    }\n  }\n  return callers;\n};\n\n/**\n * When a procedure definition is disposed of, find and dispose of all its\n *     callers.\n * @param {string} name Name of deleted procedure definition.\n * @param {!Blockly.Workspace} workspace The workspace to delete callers from.\n */\nBlockly.Procedures.disposeCallers = function(name, workspace) {\n  var callers = Blockly.Procedures.getCallers(name, workspace);\n  for (var x = 0; x < callers.length; x++) {\n    callers[x].dispose(true, false);\n  }\n};\n\n/**\n * When a procedure definition changes its parameters, find and edit all its\n * callers.\n * @param {string} name Name of edited procedure definition.\n * @param {!Blockly.Workspace} workspace The workspace to delete callers from.\n * @param {!Array.<string>} paramNames Array of new parameter names.\n * @param {!Array.<string>} paramIds Array of unique parameter IDs.\n */\nBlockly.Procedures.mutateCallers = function(name, workspace,\n                                            paramNames, paramIds) {\n  var callers = Blockly.Procedures.getCallers(name, workspace);\n  for (var x = 0; x < callers.length; x++) {\n    callers[x].setProcedureParameters(paramNames, paramIds);\n  }\n};\n\n/**\n * Find the definition block for the named procedure.\n * @param {string} name Name of procedure.\n * @param {!Blockly.Workspace} workspace The workspace to search.\n * @return {Blockly.Block} The procedure definition block, or null not found.\n */\nBlockly.Procedures.getDefinition = function(name, workspace) {\n  var blocks = workspace.getAllBlocks();\n  for (var x = 0; x < blocks.length; x++) {\n    var func = blocks[x].getProcedureDef;\n    if (func) {\n      var tuple = func.call(blocks[x]);\n      if (tuple && Blockly.Names.equals(tuple[0], name)) {\n        return blocks[x];\n      }\n    }\n  }\n  return null;\n};\n"
  },
  {
    "path": "extern/blockly/core/realtime-client-utils.js",
    "content": "/**\n * @license\n * Copyright 2013 Google Inc. All Rights Reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use strict';\n\n/**\n * @fileoverview Common utility functionality for Google Drive Realtime API,\n * including authorization and file loading. This functionality should serve\n * mostly as a well-documented example, though is usable in its own right.\n *\n * You can find this code as part of the Google Drive Realtime API Quickstart at\n * https://developers.google.com/drive/realtime/realtime-quickstart and also as\n * part of the Google Drive Realtime Playground code at\n * https://github.com/googledrive/realtime-playground/blob/master/js/realtime-client-utils.js\n */\n\n/**\n * Realtime client utilities namespace.\n */\nvar rtclient = rtclient || {};\n\n/**\n * OAuth 2.0 scope for installing Drive Apps.\n * @const\n */\nrtclient.INSTALL_SCOPE = 'https://www.googleapis.com/auth/drive.install';\n\n/**\n * OAuth 2.0 scope for opening and creating files.\n * @const\n */\nrtclient.FILE_SCOPE = 'https://www.googleapis.com/auth/drive.file';\n\n/**\n * OAuth 2.0 scope for accessing the user's ID.\n * @const\n */\nrtclient.OPENID_SCOPE = 'openid';\n\n/**\n * MIME type for newly created Realtime files.\n * @const\n */\nrtclient.REALTIME_MIMETYPE = 'application/vnd.google-apps.drive-sdk';\n\n/**\n * Parses the hash parameters to this page and returns them as an object.\n * @return {!Object} Parameter object.\n */\nrtclient.getParams = function() {\n  var params = {};\n  var hashFragment = window.location.hash;\n  if (hashFragment) {\n    // split up the query string and store in an object\n    var paramStrs = hashFragment.slice(1).split('&');\n    for (var i = 0; i < paramStrs.length; i++) {\n      var paramStr = paramStrs[i].split('=');\n      params[paramStr[0]] = unescape(paramStr[1]);\n    }\n  }\n  // Opening from Drive will encode the state in a query search parameter\n  var searchFragment = window.location.search;\n  if (searchFragment) {\n    // split up the query string and store in an object\n    var paramStrs2 = searchFragment.slice(1).split(\"&\");\n    for (var j = 0; j < paramStrs2.length; j++) {\n      var paramStr2 = paramStrs2[j].split(\"=\");\n      params[paramStr2[0]] = unescape(paramStr2[1]);\n    }\n  }\n  console.log(params);\n  return params;\n};\n\n/**\n * Instance of the query parameters.\n */\nrtclient.params = rtclient.getParams();\n\n/**\n * Fetches an option from options or a default value, logging an error if\n *     neither is available.\n * @param {!Object} options Containing options.\n * @param {string} key Option key.\n * @param {*} defaultValue Default option value (optional).\n * @return {*} Option value.\n */\nrtclient.getOption = function(options, key, defaultValue) {\n  if (options.hasOwnProperty(key)) {\n    return options[key];\n  }\n  console.error(key + ' should be present in the options.');\n  return defaultValue;\n};\n\n/**\n * Creates a new Authorizer from the options.\n * @constructor\n * @param {!Object} options For authorizer. Two keys are required as mandatory,\n *     these are:\n *\n *    1. \"clientId\", the Client ID from the console\n *    2. \"authButtonElementId\", the is of the dom element to use for\n *       authorizing.\n */\nrtclient.Authorizer = function(options) {\n  this.clientId = rtclient.getOption(options, 'clientId');\n  // Get the user ID if it's available in the state query parameter.\n  this.userId = rtclient.params['userId'];\n  this.authButton = document.getElementById(rtclient.getOption(options,\n      'authButtonElementId'));\n};\n\n/**\n * Start the authorization process.\n * @param {Function} onAuthComplete To call once authorization has completed.\n */\nrtclient.Authorizer.prototype.start = function(onAuthComplete) {\n  var _this = this;\n  gapi.load('auth:client,drive-realtime,drive-share', function() {\n    _this.authorize(onAuthComplete);\n  });\n};\n\n/**\n * Reauthorize the client with no callback (used for authorization failure).\n * @param {Function} onAuthComplete To call once authorization has completed.\n */\nrtclient.Authorizer.prototype.authorize = function(onAuthComplete) {\n  var clientId = this.clientId;\n  var userId = this.userId;\n  var _this = this;\n  var handleAuthResult = function(authResult) {\n    if (authResult && !authResult.error) {\n      _this.authButton.disabled = true;\n      _this.fetchUserId(onAuthComplete);\n    } else {\n      _this.authButton.disabled = false;\n      _this.authButton.onclick = authorizeWithPopup;\n    }\n  };\n  var authorizeWithPopup = function() {\n    gapi.auth.authorize({\n      client_id: clientId,\n      scope: [\n        rtclient.INSTALL_SCOPE,\n        rtclient.FILE_SCOPE,\n        rtclient.OPENID_SCOPE\n      ],\n      user_id: userId,\n      immediate: false\n    }, handleAuthResult);\n  };\n  // Try with no popups first.\n  gapi.auth.authorize({\n    client_id: clientId,\n    scope: [\n      rtclient.INSTALL_SCOPE,\n      rtclient.FILE_SCOPE,\n      rtclient.OPENID_SCOPE\n    ],\n    user_id: userId,\n    immediate: true\n  }, handleAuthResult);\n};\n\n/**\n * Fetch the user ID using the UserInfo API and save it locally.\n * @param {Function} callback The callback to call after user ID has been\n *     fetched.\n */\nrtclient.Authorizer.prototype.fetchUserId = function(callback) {\n  var _this = this;\n  gapi.client.load('oauth2', 'v2', function() {\n    gapi.client.oauth2.userinfo.get().execute(function(resp) {\n      if (resp.id) {\n        _this.userId = resp.id;\n      }\n      if (callback) {\n        callback();\n      }\n    });\n  });\n};\n\n/**\n * Creates a new Realtime file.\n * @param {string} title Title of the newly created file.\n * @param {string} mimeType The MIME type of the new file.\n * @param {Function} callback The callback to call after creation.\n */\nrtclient.createRealtimeFile = function(title, mimeType, callback) {\n  gapi.client.load('drive', 'v2', function() {\n    gapi.client.drive.files.insert({\n      'resource': {\n        mimeType: mimeType,\n        title: title\n      }\n    }).execute(callback);\n  });\n};\n\n/**\n * Fetches the metadata for a Realtime file.\n * @param {string} fileId The file to load metadata for.\n * @param {Function} callback The callback to be called on completion,\n *     with signature:\n *\n *    function onGetFileMetadata(file) {}\n *\n * where the file parameter is a Google Drive API file resource instance.\n */\nrtclient.getFileMetadata = function(fileId, callback) {\n  gapi.client.load('drive', 'v2', function() {\n    gapi.client.drive.files.get({\n      'fileId' : fileId\n    }).execute(callback);\n  });\n};\n\n/**\n * Parses the state parameter passed from the Drive user interface after\n *     Open With operations.\n * @param {string} stateParam The state query parameter as a JSON string.\n * @return {Object} The state query parameter as an object or null if\n *     parsing failed.\n */\nrtclient.parseState = function(stateParam) {\n  try {\n    var stateObj = JSON.parse(stateParam);\n    return stateObj;\n  } catch (e) {\n    return null;\n  }\n};\n\n/**\n * Handles authorizing, parsing query parameters, loading and creating Realtime\n *     documents.\n * @constructor\n * @param {!Object} options Options for loader. Four keys are required as\n *     mandatory, these are:\n *\n *    1. \"clientId\", the Client ID from the console\n *    2. \"initializeModel\", the callback to call when the file is loaded.\n *    3. \"onFileLoaded\", the callback to call when the model is first created.\n *\n * and one key is optional:\n *\n *    1. \"defaultTitle\", the title of newly created Realtime files.\n */\nrtclient.RealtimeLoader = function(options) {\n  // Initialize configuration variables.\n  this.onFileLoaded = rtclient.getOption(options, 'onFileLoaded');\n  this.newFileMimeType = rtclient.getOption(options, 'newFileMimeType',\n      rtclient.REALTIME_MIMETYPE);\n  this.initializeModel = rtclient.getOption(options, 'initializeModel');\n  this.registerTypes = rtclient.getOption(options, 'registerTypes',\n      function() {});\n  this.afterAuth = rtclient.getOption(options, 'afterAuth', function() {});\n  // This tells us if need to we automatically create a file after auth.\n  this.autoCreate = rtclient.getOption(options, 'autoCreate', false);\n  this.defaultTitle = rtclient.getOption(options, 'defaultTitle',\n      'New Realtime File');\n  this.afterCreate = rtclient.getOption(options, 'afterCreate', function() {});\n  this.authorizer = new rtclient.Authorizer(options);\n};\n\n/**\n * Redirects the browser back to the current page with an appropriate file ID.\n * @param {Array.<string>} fileIds The IDs of the files to open.\n * @param {string} userId The ID of the user.\n */\nrtclient.RealtimeLoader.prototype.redirectTo = function(fileIds, userId) {\n  var params = [];\n  if (fileIds) {\n    params.push('fileIds=' + fileIds.join(','));\n  }\n  if (userId) {\n    params.push('userId=' + userId);\n  }\n  // Naive URL construction.\n  var newUrl = params.length == 0\n      ? window.location.pathname\n      : (window.location.pathname + '#' + params.join('&'));\n  // Using HTML URL re-write if available.\n  if (window.history && window.history.replaceState) {\n    window.history.replaceState('Google Drive Realtime API Playground',\n        'Google Drive Realtime API Playground', newUrl);\n  } else {\n    window.location.href = newUrl;\n  }\n  // We are still here that means the page didn't reload.\n  rtclient.params = rtclient.getParams();\n  for (var index in fileIds) {\n    gapi.drive.realtime.load(fileIds[index], this.onFileLoaded,\n        this.initializeModel, this.handleErrors);\n  }\n};\n\n/**\n * Starts the loader by authorizing.\n */\nrtclient.RealtimeLoader.prototype.start = function() {\n  // Bind to local context to make them suitable for callbacks.\n  var _this = this;\n  this.authorizer.start(function() {\n    if (_this.registerTypes) {\n      _this.registerTypes();\n    }\n    if (_this.afterAuth) {\n      _this.afterAuth();\n    }\n    _this.load();\n  });\n};\n\n/**\n * Handles errors thrown by the Realtime API.\n * @param {!Error} e Error.\n */\nrtclient.RealtimeLoader.prototype.handleErrors = function(e) {\n  if (e.type == gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED) {\n    this.authorizer.authorize();\n  } else if (e.type == gapi.drive.realtime.ErrorType.CLIENT_ERROR) {\n    alert('An Error happened: ' + e.message);\n    window.location.href = '/';\n  } else if (e.type == gapi.drive.realtime.ErrorType.NOT_FOUND) {\n    alert('The file was not found. It does not exist or you do not have ' +\n        'read access to the file.');\n    window.location.href = '/';\n  }\n};\n\n/**\n * Loads or creates a Realtime file depending on the fileId and state query\n * parameters.\n */\nrtclient.RealtimeLoader.prototype.load = function() {\n  var fileIds = rtclient.params['fileIds'];\n  if (fileIds) {\n    fileIds = fileIds.split(',');\n  }\n  var userId = this.authorizer.userId;\n  var state = rtclient.params['state'];\n  // Creating the error callback.\n  var authorizer = this.authorizer;\n  // We have file IDs in the query parameters, so we will use them to load a\n  // file.\n  if (fileIds) {\n    for (var index in fileIds) {\n      gapi.drive.realtime.load(fileIds[index], this.onFileLoaded,\n          this.initializeModel, this.handleErrors);\n    }\n    return;\n  }\n  // We have a state parameter being redirected from the Drive UI.\n  // We will parse it and redirect to the fileId contained.\n  else if (state) {\n    var stateObj = rtclient.parseState(state);\n    // If opening a file from Drive.\n    if (stateObj.action == 'open') {\n      fileIds = stateObj.ids;\n      userId = stateObj.userId;\n      this.redirectTo(fileIds, userId);\n      return;\n    }\n  }\n  if (this.autoCreate) {\n    this.createNewFileAndRedirect();\n  }\n};\n\n/**\n * Creates a new file and redirects to the URL to load it.\n */\nrtclient.RealtimeLoader.prototype.createNewFileAndRedirect = function() {\n  // No fileId or state have been passed. We create a new Realtime file and\n  // redirect to it.\n  var _this = this;\n  rtclient.createRealtimeFile(this.defaultTitle, this.newFileMimeType,\n      function(file) {\n        if (file.id) {\n          if (_this.afterCreate) {\n            _this.afterCreate(file.id);\n          }\n          _this.redirectTo([file.id], _this.authorizer.userId);\n        } else {\n          // File failed to be created, log why and do not attempt to redirect.\n          console.error('Error creating file.');\n          console.error(file);\n        }\n      });\n};\n"
  },
  {
    "path": "extern/blockly/core/realtime.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * This file contains functions used by any Blockly app that wants to provide\n * realtime collaboration functionality.\n *\n * Note that it depends on the existence of particularly named UI elements.\n *\n * TODO: Inject the UI element names\n */\n\n/**\n * @fileoverview Common support code for Blockly apps using realtime\n * collaboration.\n * Note that to use this you must set up a project via the Google Developers\n * Console. Instructions on how to do that can be found in the Blockly wiki page\n * at https://code.google.com/p/blockly/wiki/RealtimeCollaboration\n * Once you do that you can set the clientId in\n * Blockly.Realtime.realtimeOptions_\n * @author markf@google.com (Mark Friedman)\n */\n'use strict';\n\ngoog.provide('Blockly.Realtime');\n\ngoog.require('goog.array');\n\n/**\n * Is realtime collaboration enabled?\n * @type {boolean}\n * @private\n */\nBlockly.Realtime.enabled_ = false;\n\n/**\n * The Realtime model of this doc.\n * @type {gapi.drive.realtime.Model}\n * @private\n */\nBlockly.Realtime.model_ = null;\n\n/**\n * The function used to initialize the UI after realtime is initialized.\n * @type {Function}\n * @private\n */\nBlockly.Realtime.initUi_ = null;\n\n/**\n * A map from block id to blocks.\n * @type {gapi.drive.realtime.CollaborativeMap}\n * @private\n */\nBlockly.Realtime.blocksMap_ = null;\n\n/**\n * Are currently syncing from another instance of this realtime doc.\n * @type {boolean}\n */\nBlockly.Realtime.withinSync = false;\n\n/**\n * The current instance of the realtime loader client\n * @type {rtclient.RealtimeLoader}\n * @private\n */\nBlockly.Realtime.realtimeLoader_ = null;\n\n/**\n * Returns whether realtime collaboration is enabled.\n * @returns {boolean}\n */\nBlockly.Realtime.isEnabled = function() {\n  return Blockly.Realtime.enabled_;\n};\n\n/**\n * This function is called the first time that the Realtime model is created\n * for a file. This function should be used to initialize any values of the\n * model.\n * @param model {gapi.drive.realtime.Model} model The Realtime root model\n *     object.\n */\nBlockly.Realtime.initializeModel_ = function(model) {\n  Blockly.Realtime.model_ = model;\n  var blocksMap = model.createMap();\n  model.getRoot().set('blocks', blocksMap);\n  var topBlocks = model.createList();\n  model.getRoot().set('topBlocks', topBlocks);\n  var string = model.createString(Blockly.Msg.CHAT);\n  model.getRoot().set('text', string);\n};\n\n/**\n * Delete a block from the realtime blocks map.\n * @param {!Blockly.Block} block The block to remove.\n */\nBlockly.Realtime.removeBlock = function(block) {\n  Blockly.Realtime.blocksMap_.delete(block.id.toString());\n};\n\n/**\n * Add to the list of top-level blocks.\n * @param {!Blockly.Block} block The block to add.\n */\nBlockly.Realtime.addTopBlock = function(block) {\n  if (Blockly.Realtime.topBlocks_.indexOf(block) == -1) {\n    Blockly.Realtime.topBlocks_.push(block);\n  }\n};\n\n/**\n * Delete a block from the list of top-level blocks.\n * @param {!Blockly.Block} block The block to remove.\n */\nBlockly.Realtime.removeTopBlock = function(block) {\n  Blockly.Realtime.topBlocks_.removeValue(block);\n};\n\n/**\n * Obtain a newly created block known by the Realtime API.\n * @param {!Blockly.Workspace} workspace The workspace to put the block in.\n * @param {string} prototypeName The name of the prototype for the block\n * @return {!Blockly.Block}\n */\nBlockly.Realtime.obtainBlock = function(workspace, prototypeName) {\n  var newBlock =\n      Blockly.Realtime.model_.create(Blockly.Block, workspace, prototypeName);\n  return newBlock;\n};\n\n/**\n * Get an existing block by id.\n * @param {string} id The block's id.\n * @return {Blockly.Block} The found block.\n */\nBlockly.Realtime.getBlockById = function(id) {\n  return Blockly.Realtime.blocksMap_.get(id);\n};\n\n/**\n * Event handler to call when a block is changed.\n * @param {gapi.drive.realtime.ObjectChangedEvent} evt The event that occurred.\n * @private\n */\nBlockly.Realtime.onObjectChange_ = function(evt) {\n  var events = evt.events;\n  var eventCount = evt.events.length;\n  for (var i = 0; i < eventCount; i++) {\n    var event = events[i];\n    if (!event.isLocal) {\n      if (event.type == 'value_changed') {\n        if (event.property == 'xmlDom') {\n          var block = event.target;\n          Blockly.Realtime.doWithinSync_(function(){\n            Blockly.Realtime.placeBlockOnWorkspace_(block, false);\n            Blockly.Realtime.moveBlock_(block);\n          });\n        } else if (event.property == 'relativeX' ||\n                   event.property == 'relativeY') {\n          var block2 = event.target;\n          Blockly.Realtime.doWithinSync_(function () {\n            if (!block2.svg_) {\n              // If this is a move of a newly disconnected (i.e newly top level)\n              // block it will not have any svg (because it has been disposed of\n              // by it's parent), so we need to handle that here.\n              Blockly.Realtime.placeBlockOnWorkspace_(block2, false);\n            }\n            Blockly.Realtime.moveBlock_(block2);\n          });\n         }\n      }\n    }\n  }\n};\n\n/**\n * Event handler to call when there is a change to the realtime blocks map.\n * @param {gapi.drive.realtime.ValueChangedEvent} evt The event that occurred.\n * @private\n */\nBlockly.Realtime.onBlocksMapChange_ = function(evt) {\n  console.log('Blocks Map event:');\n  console.log('  id: ' + evt.property);\n  if (!evt.isLocal) {\n    var block = evt.newValue;\n    if (block) {\n      Blockly.Realtime.placeBlockOnWorkspace_(block, !(evt.oldValue));\n    } else {\n      block = evt.oldValue;\n      Blockly.Realtime.deleteBlock(block);\n    }\n  }\n};\n\n/**\n * A convenient wrapper around code that synchronizes the local model being\n * edited with changes from another non-local model.\n * @param {!Function} thunk A thunk of code to call.\n * @private\n */\nBlockly.Realtime.doWithinSync_ = function(thunk) {\n  if (Blockly.Realtime.withinSync) {\n    thunk();\n  } else {\n    try {\n      Blockly.Realtime.withinSync = true;\n      thunk();\n    } finally {\n      Blockly.Realtime.withinSync = false;\n    }\n  }\n};\n\n/**\n * Places a block to be synced on this docs main workspace.  The block might\n * already exist on this doc, in which case it is updated and/or moved.\n * @param {!Blockly.Block} block The block.\n * @param {boolean} addToTop Whether to add the block to the workspace/s list of\n *     top-level blocks.\n * @private\n */\nBlockly.Realtime.placeBlockOnWorkspace_ = function(block, addToTop) {\n  Blockly.Realtime.doWithinSync_(function() {\n    var blockDom = Blockly.Xml.textToDom(block.xmlDom).firstChild;\n    var newBlock =\n        Blockly.Xml.domToBlock(Blockly.mainWorkspace, blockDom, true);\n    // TODO: The following is for debugging.  It should never actually happen.\n    if (!newBlock) {\n      return;\n    }\n    // Since Blockly.Xml.blockDomToBlock() purposely won't add blocks to\n    // workspace.topBlocks_ we sometimes need to do it explicitly here.\n    if (addToTop) {\n      newBlock.workspace.addTopBlock(newBlock);\n    }\n    if (addToTop ||\n        goog.array.contains(Blockly.Realtime.topBlocks_, newBlock)) {\n      Blockly.Realtime.moveBlock_(newBlock);\n    }\n  });\n};\n\n/**\n * Move a block\n * @param {Blockly.Block} block The block to move.\n * @private\n */\nBlockly.Realtime.moveBlock_ = function(block) {\n  if (!isNaN(block.relativeX) && !isNaN(block.relativeY)) {\n    var width = Blockly.svgSize().width;\n    var curPos = block.getRelativeToSurfaceXY();\n    var dx = block.relativeX - curPos.x;\n    var dy = block.relativeY - curPos.y;\n    block.moveBy(Blockly.RTL ? width - dx : dx, dy);\n  }\n};\n\n/**\n * Delete a block.\n * @param {!Blockly.Block} block The block to delete.\n * @private\n */\nBlockly.Realtime.deleteBlock = function(block) {\n  Blockly.Realtime.doWithinSync_(function() {\n    block.dispose(true, true, true);\n  });\n};\n\n/**\n * Load all the blocks from the realtime model's blocks map and place them\n * appropriately on the main Blockly workspace.\n * @private\n */\nBlockly.Realtime.loadBlocks_ = function() {\n  var blocks = Blockly.Realtime.blocksMap_.values();\n  for (var i = 0; i < blocks.length; i++) {\n    var block = blocks[i];\n    // Since we now have blocks with already existing ids, we have to make sure\n    // that new blocks don't get any of the existing ids.\n    var blockIdNum = parseInt(block.id, 10);\n    if (blockIdNum > Blockly.getUidCounter()) {\n      Blockly.setUidCounter(blockIdNum + 1);\n    }\n  }\n  var topBlocks = Blockly.Realtime.topBlocks_;\n  for (var j = 0; j < topBlocks.length; j++) {\n    var topBlock = topBlocks.get(j);\n    Blockly.Realtime.placeBlockOnWorkspace_(topBlock, true);\n  }\n};\n\n/**\n * Cause a changed block to update the realtime model, and therefore to be\n * synced with other apps editing this same doc.\n * @param {!Blockly.Block} block The block that changed.\n */\nBlockly.Realtime.blockChanged = function(block) {\n  if (block.workspace == Blockly.mainWorkspace) {\n    var rootBlock = block.getRootBlock();\n    var xy = rootBlock.getRelativeToSurfaceXY();\n    var changed = false;\n    var xml = Blockly.Xml.blockToDom_(rootBlock);\n    xml.setAttribute('id', rootBlock.id);\n    var topXml = goog.dom.createDom('xml');\n    topXml.appendChild(xml);\n    var newXml = Blockly.Xml.domToText(topXml);\n    if (newXml != rootBlock.xmlDom) {\n      changed = true;\n      rootBlock.xmlDom = newXml;\n    }\n    if (rootBlock.relativeX != xy.x || rootBlock.relativeY != xy.y){\n      rootBlock.relativeX = xy.x;\n      rootBlock.relativeY = xy.y;\n      changed = true;\n    }\n    if (changed) {\n      var blockId = rootBlock.id.toString();\n      Blockly.Realtime.blocksMap_.set(blockId, rootBlock);\n    }\n  }\n};\n\n/**\n * This function is called when the Realtime file has been loaded. It should\n * be used to initialize any user interface components and event handlers\n * depending on the Realtime model. In this case, create a text control binder\n * and bind it to our string model that we created in initializeModel.\n * @param {!gapi.drive.realtime.Document} doc The Realtime document.\n * @private\n */\nBlockly.Realtime.onFileLoaded_ = function(doc) {\n  Blockly.Realtime.model_ = doc.getModel();\n  Blockly.Realtime.blocksMap_ =\n      Blockly.Realtime.model_.getRoot().get('blocks');\n  Blockly.Realtime.topBlocks_ =\n      Blockly.Realtime.model_.getRoot().get('topBlocks');\n\n  Blockly.Realtime.model_.getRoot().addEventListener(\n      gapi.drive.realtime.EventType.OBJECT_CHANGED,\n      Blockly.Realtime.onObjectChange_);\n  Blockly.Realtime.blocksMap_.addEventListener(\n      gapi.drive.realtime.EventType.VALUE_CHANGED,\n      Blockly.Realtime.onBlocksMapChange_);\n\n  var string = Blockly.Realtime.model_.getRoot().get('text');\n\n  // Keeping one box updated with a String binder.\n  var textArea1 = document.getElementById('chatbox');\n  gapi.drive.realtime.databinding.bindString(string, textArea1);\n\n  // Enabling UI Elements.\n  textArea1.disabled = false;\n  Blockly.Realtime.initUi_();\n\n  Blockly.Realtime.loadBlocks_();\n\n  // Add logic for undo button.\n  // TODO: Uncomment this when undo/redo are fixed.\n/*\n  var undoButton = document.getElementById('undoButton');\n  var redoButton = document.getElementById('redoButton');\n\n  undoButton.onclick = function(e) {\n    Blockly.Realtime.model_.undo();\n  };\n  redoButton.onclick = function(e) {\n    Blockly.Realtime.model_.redo();\n  };\n\n  // Add event handler for UndoRedoStateChanged events.\n  var onUndoRedoStateChanged = function(e) {\n    undoButton.disabled = !e.canUndo;\n    redoButton.disabled = !e.canRedo;\n  };\n  Blockly.Realtime.model_.addEventListener(\n      gapi.drive.realtime.EventType.UNDO_REDO_STATE_CHANGED,\n      onUndoRedoStateChanged);\n */\n};\n\n/**\n * Register the Blockly types and attributes that are reflected in the realtime\n * model.\n * @private\n */\nBlockly.Realtime.registerTypes_ = function() {\n  var custom = gapi.drive.realtime.custom;\n\n  custom.registerType(Blockly.Block, 'Block');\n  Blockly.Block.prototype.id = custom.collaborativeField('id');\n  Blockly.Block.prototype.type = custom.collaborativeField('type');\n  Blockly.Block.prototype.xmlDom = custom.collaborativeField('xmlDom');\n  Blockly.Block.prototype.relativeX = custom.collaborativeField('relativeX');\n  Blockly.Block.prototype.relativeY = custom.collaborativeField('relativeY');\n\n  custom.setInitializer(Blockly.Block, Blockly.Block.prototype.initialize);\n};\n\nBlockly.Realtime.REAUTH_INTERVAL_IN_MILLISECONDS_ = 30 * 60 * 1000;\n\n/**\n * What to do after Realtime authorization.\n * @private\n */\nBlockly.Realtime.afterAuth_ = function() {\n  // This is a workaround for the fact that the code in realtime-client-utils.js\n  // doesn't deal with auth timeouts correctly.  So we explicitly reauthorize at\n  // regular intervals.\n  window.setTimeout(\n      function() {\n        Blockly.Realtime.realtimeLoader_.authorizer.authorize(\n            Blockly.Realtime.afterAuth_);\n      },\n      Blockly.Realtime.REAUTH_INTERVAL_IN_MILLISECONDS_);\n};\n\n/**\n * Add \"Anyone with the link\" permissions to the file.\n * @param {string} fileId the file id\n */\nBlockly.Realtime.afterCreate_ = function(fileId) {\n  var resource = {\n    'type': 'anyone',\n    'role': 'writer',\n    'value': 'default',\n    'withLink': true\n  };\n  var request = gapi.client.drive.permissions.insert({\n    'fileId': fileId,\n    'resource': resource\n  });\n  request.execute(function(resp) {\n    // If we have an error try to just set the permission for all users\n    // of the domain.\n    if (resp.error) {\n      Blockly.Realtime.getUserDomain(fileId, function(domain) {\n        var resource = {\n          'type': 'domain',\n          'role': 'writer',\n          'value': domain,\n          'withLink': true\n        };\n        request = gapi.client.drive.permissions.insert({\n          'fileId': fileId,\n          'resource': resource\n        });\n        request.execute(function(resp) { });\n      });\n    }\n  });\n};\n\n/**\n * Get the domain (if it exists) associated with a realtime file.  The callback\n * will be called with the domain, if it exists.\n * @param fileId {string} the id of the file\n * @param callback {function(string)} a function to call back with the domain\n */\nBlockly.Realtime.getUserDomain = function (fileId, callback) {\n  /**\n   * Note that there may be a more direct way to get the domain by, for example,\n   * using the Google profile API but this way we don't need any additional\n   * APIs or scopes.  But if it turns out that the permissions API stops\n   * providing the domain this might have to change.\n   */\n  var request = gapi.client.drive.permissions.list({\n    'fileId': fileId\n  });\n  request.execute(function(resp) {\n    for (var i = 0; i < resp.items.length; i++) {\n      var item = resp.items[i];\n      if (item.role == 'owner') {\n        callback(item.domain);\n        return;\n      }\n    }\n  });\n};\n\n/**\n * Options for the Realtime loader.\n */\nBlockly.Realtime.realtimeOptions_ = {\n  /**\n   * Client ID from the console.\n   */\n//  clientId: 'INSERT YOUR CLIENT ID HERE',\n  clientId: '922110111899.apps.googleusercontent.com',\n\n  /**\n   * The ID of the button to click to authorize. Must be a DOM element ID.\n   */\n  authButtonElementId: 'authorizeButton',\n\n  /**\n   * Function to be called when a Realtime model is first created.\n   */\n  initializeModel: Blockly.Realtime.initializeModel_,\n\n  /**\n   * Autocreate files right after auth automatically.\n   */\n  autoCreate: true,\n\n  /**\n   * The name of newly created Drive files.\n   */\n  defaultTitle: 'New Realtime Blockly File',\n\n  /**\n   * The MIME type of newly created Drive Files. By default the application\n   * specific MIME type will be used:\n   *     application/vnd.google-apps.drive-sdk.\n   */\n  newFileMimeType: null, // Using default.\n\n  /**\n   * Function to be called every time a Realtime file is loaded.\n   */\n  onFileLoaded: Blockly.Realtime.onFileLoaded_,\n\n  /**\n   * Function to be called to initialize custom Collaborative Objects types.\n   */\n  registerTypes: Blockly.Realtime.registerTypes_,\n\n  /**\n   * Function to be called after authorization and before loading files.\n   */\n  afterAuth: Blockly.Realtime.afterAuth_,\n\n  /**\n   * Function to be called after file creation, if autoCreate is true.\n   */\n  afterCreate: Blockly.Realtime.afterCreate_\n};\n\n/**\n * Start the Realtime loader with the options.\n */\nBlockly.Realtime.startRealtime = function (uiInitialize) {\n  Blockly.Realtime.enabled_ = true;\n  Blockly.Realtime.initUi_ = uiInitialize;\n  Blockly.Realtime.realtimeLoader_ =\n      new rtclient.RealtimeLoader(Blockly.Realtime.realtimeOptions_);\n  Blockly.Realtime.realtimeLoader_.start();\n};\n"
  },
  {
    "path": "extern/blockly/core/scrollbar.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Library for creating scrollbars.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Scrollbar');\ngoog.provide('Blockly.ScrollbarPair');\n\ngoog.require('goog.userAgent');\n\n\n/**\n * Class for a pair of scrollbars.  Horizontal and vertical.\n * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbars to.\n * @constructor\n */\nBlockly.ScrollbarPair = function(workspace) {\n  this.workspace_ = workspace;\n  this.oldHostMetrics_ = null;\n  this.hScroll = new Blockly.Scrollbar(workspace, true, true);\n  this.vScroll = new Blockly.Scrollbar(workspace, false, true);\n};\n\n/**\n * Dispose of this pair of scrollbars.\n * Unlink from all DOM elements to prevent memory leaks.\n */\nBlockly.ScrollbarPair.prototype.dispose = function() {\n  Blockly.unbindEvent_(this.onResizeWrapper_);\n  this.onResizeWrapper_ = null;\n  this.workspace_ = null;\n  this.oldHostMetrics_ = null;\n  this.hScroll.dispose();\n  this.hScroll = null;\n  this.vScroll.dispose();\n  this.vScroll = null;\n};\n\n/**\n * Recalculate both of the scrollbars' locations and lengths.\n * Also reposition the corner rectangle.\n */\nBlockly.ScrollbarPair.prototype.resize = function() {\n  // Look up the host metrics once, and use for both scrollbars.\n  if (Blockly.scrollBarOff)\n      return;\n  var hostMetrics = this.workspace_.getMetrics();\n  if (!hostMetrics) {\n    // Host element is likely not visible.\n    return;\n  }\n\n  // Only change the scrollbars if there has been a change in metrics.\n  var resizeH = false;\n  var resizeV = false;\n  if (!this.oldHostMetrics_ ||\n      this.oldHostMetrics_.viewWidth != hostMetrics.viewWidth ||\n      this.oldHostMetrics_.viewHeight != hostMetrics.viewHeight ||\n      this.oldHostMetrics_.absoluteTop != hostMetrics.absoluteTop ||\n      this.oldHostMetrics_.absoluteLeft != hostMetrics.absoluteLeft) {\n    // The window has been resized or repositioned.\n    resizeH = true;\n    resizeV = true;\n  } else {\n    // Has the content been resized or moved?\n    if (!this.oldHostMetrics_ ||\n        this.oldHostMetrics_.contentWidth != hostMetrics.contentWidth ||\n        this.oldHostMetrics_.viewLeft != hostMetrics.viewLeft ||\n        this.oldHostMetrics_.contentLeft != hostMetrics.contentLeft) {\n      resizeH = true;\n    }\n    if (!this.oldHostMetrics_ ||\n        this.oldHostMetrics_.contentHeight != hostMetrics.contentHeight ||\n        this.oldHostMetrics_.viewTop != hostMetrics.viewTop ||\n        this.oldHostMetrics_.contentTop != hostMetrics.contentTop) {\n      resizeV = true;\n    }\n  }\n  if (resizeH) {\n    this.hScroll.resize(hostMetrics);\n  }\n  if (resizeV) {\n    this.vScroll.resize(hostMetrics);\n  }\n\n  // Cache the current metrics to potentially short-cut the next resize event.\n  this.oldHostMetrics_ = hostMetrics;\n};\n\n/**\n * Set the sliders of both scrollbars to be at a certain position.\n * @param {number} x Horizontal scroll value.\n * @param {number} y Vertical scroll value.\n */\nBlockly.ScrollbarPair.prototype.set = function(x, y) {\n  /* HACK:\n   Two scrollbars are about to have their sliders moved.  Moving a scrollbar\n   will normally result in its onScroll function being called.  That function\n   will update the contents.  At issue is what happens when two scrollbars are\n   moved.  Calling onScroll twice may result in two rerenderings of the content\n   and increase jerkiness during dragging.\n   In the case of native scrollbars (currently used only by Firefox), onScroll\n   is called as an event, which means two separate renderings of the content are\n   performed.  However in the case of SVG scrollbars (currently used by all\n   other browsers), onScroll is called as a function and the browser only\n   rerenders the contents once at the end of the thread.\n  */\n  if (Blockly.Scrollbar === Blockly.ScrollbarNative) {\n    // Native scrollbar mode.\n    // Set both scrollbars and suppress their two separate onScroll events.\n    this.hScroll.set(x, false);\n    this.vScroll.set(y, false);\n    // Redraw the surface once with the new settings for both scrollbars.\n    var xyRatio = {};\n    xyRatio.x = (this.hScroll.outerDiv_.scrollLeft /\n                 this.hScroll.innerImg_.offsetWidth) || 0;\n    xyRatio.y = (this.vScroll.outerDiv_.scrollTop /\n                 this.vScroll.innerImg_.offsetHeight) || 0;\n    this.workspace_.setMetrics(xyRatio);\n  } else {\n    // SVG scrollbars.\n    // Set both scrollbars and allow each to call a separate onScroll execution.\n    this.hScroll.set(x, true);\n    this.vScroll.set(y, true);\n  }\n};\n\n// --------------------------------------------------------------------\n\n/**\n * Common properties and methods for ScrollbarNative and ScrollbarSvg.\n * Prevents the compiler from choosing incompatible names for properties on\n * each.\n * @interface\n */\nBlockly.ScrollbarInterface = function() {};\n/**\n * Dispose of this scrollbar.\n */\nBlockly.ScrollbarInterface.prototype.dispose = function() {};\n/**\n * Recalculate the scrollbar's location and its length.\n */\nBlockly.ScrollbarInterface.prototype.resize = function() {};\n/**\n * Is the scrollbar visible.\n * @return {boolean} True if visible.\n */\nBlockly.ScrollbarInterface.prototype.isVisible = function() {};\n/**\n * Set whether the scrollbar is visible.\n * @param {boolean} visible True if visible.\n */\nBlockly.ScrollbarInterface.prototype.setVisible = function(visible) {};\n/**\n * Set the scrollbar slider's position.\n * @param {number} value The distance from the top/left end of the bar.\n * @param {boolean} fireEvents True if onScroll events should be fired.\n */\nBlockly.ScrollbarInterface.prototype.set = function(value, fireEvents) {};\n\n// --------------------------------------------------------------------\n\n/**\n * Class for a native widget scrollbar nested in a foreignObject element.\n * This technique offers a scrollbar that looks and behaves like the system's\n * scrollbars.  However it isn't well supported at the moment.\n * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to.\n * @param {?boolean} horizontal True if horizontal, false if vertical.\n *     Null is used to create a test scrollbar to measure thickness.\n * @param {boolean=} opt_pair True if the scrollbar is part of a\n *     horizontal/vertical pair.\n * @constructor\n * @implements {Blockly.ScrollbarInterface}\n */\nBlockly.ScrollbarNative = function(workspace, horizontal, opt_pair) {\n  this.workspace_ = workspace;\n  this.pair_ = opt_pair || false;\n  this.horizontal_ = horizontal;\n\n  this.createDom_();\n  if (horizontal === null) {\n    // Just return a bare-bones scrollbar DOM for thickness testing.\n    return;\n  }\n  if (!Blockly.Scrollbar.scrollbarThickness) {\n    // The first time a scrollbar is created, we need to measure the thickness.\n    Blockly.ScrollbarNative.measureScrollbarThickness_(workspace);\n  }\n\n  if (horizontal) {\n    this.foreignObject_.setAttribute('height',\n        Blockly.Scrollbar.scrollbarThickness);\n    this.outerDiv_.style.height =\n        Blockly.Scrollbar.scrollbarThickness + 'px';\n    this.outerDiv_.style.overflowX = 'scroll';\n    this.outerDiv_.style.overflowY = 'hidden';\n    this.innerImg_.style.height = '1px';\n  } else {\n    this.foreignObject_.setAttribute('width',\n        Blockly.Scrollbar.scrollbarThickness);\n    this.outerDiv_.style.width =\n        Blockly.Scrollbar.scrollbarThickness + 'px';\n    this.outerDiv_.style.overflowX = 'hidden';\n    this.outerDiv_.style.overflowY = 'scroll';\n    this.innerImg_.style.width = '1px';\n  }\n  var scrollbar = this;\n  this.onScrollWrapper_ = Blockly.bindEvent_(this.outerDiv_, 'scroll',\n      scrollbar, function() {scrollbar.onScroll_();});\n  Blockly.bindEvent_(this.foreignObject_, 'mousedown', null,\n      function(e) {Blockly.hideChaff(true); Blockly.noEvent(e);});\n};\n\n/**\n * Dispose of this scrollbar.\n * Unlink from all DOM elements to prevent memory leaks.\n */\nBlockly.ScrollbarNative.prototype.dispose = function() {\n  Blockly.unbindEvent_(this.onResizeWrapper_);\n  this.onResizeWrapper_ = null;\n  Blockly.unbindEvent_(this.onScrollWrapper_);\n  this.onScrollWrapper_ = null;\n  goog.dom.removeNode(this.foreignObject_);\n  this.foreignObject_ = null;\n  this.workspace_ = null;\n  this.outerDiv_ = null;\n  this.innerImg_ = null;\n};\n\n/**\n * Recalculate the scrollbar's location and its length.\n * @param {Object=} opt_metrics A data structure of from the describing all the\n * required dimensions.  If not provided, it will be fetched from the host\n * object.\n */\nBlockly.ScrollbarNative.prototype.resize = function(opt_metrics) {\n  // Determine the location, height and width of the host element.\n  var hostMetrics = opt_metrics;\n  if (!hostMetrics) {\n    hostMetrics = this.workspace_.getMetrics();\n    if (!hostMetrics) {\n      // Host element is likely not visible.\n      return;\n    }\n  }\n  /* hostMetrics is an object with the following properties.\n   * .viewHeight: Height of the visible rectangle,\n   * .viewWidth: Width of the visible rectangle,\n   * .contentHeight: Height of the contents,\n   * .contentWidth: Width of the content,\n   * .viewTop: Offset of top edge of visible rectangle from parent,\n   * .viewLeft: Offset of left edge of visible rectangle from parent,\n   * .contentTop: Offset of the top-most content from the y=0 coordinate,\n   * .contentLeft: Offset of the left-most content from the x=0 coordinate,\n   * .absoluteTop: Top-edge of view.\n   * .absoluteLeft: Left-edge of view.\n   */\n  if (this.horizontal_) {\n    var outerLength = hostMetrics.viewWidth;\n    if (this.pair_) {\n      // Shorten the scrollbar to make room for the corner square.\n      outerLength -= Blockly.Scrollbar.scrollbarThickness;\n    } else {\n      // Only show the scrollbar if needed.\n      // Ideally this would also apply to scrollbar pairs, but that's a bigger\n      // headache (due to interactions with the corner square).\n      this.setVisible(outerLength < hostMetrics.contentWidth);\n    }\n    this.ratio_ = outerLength / hostMetrics.viewWidth;\n    var innerLength = this.ratio_ * hostMetrics.contentWidth;\n    var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) *\n        this.ratio_;\n    this.outerDiv_.style.width = outerLength + 'px';\n    this.innerImg_.style.width = innerLength + 'px';\n    this.xCoordinate = hostMetrics.absoluteLeft;\n    if (this.pair_ && Blockly.RTL) {\n      this.xCoordinate += Blockly.Scrollbar.scrollbarThickness;\n    }\n    this.yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight -\n        Blockly.Scrollbar.scrollbarThickness;\n    this.foreignObject_.setAttribute('x', this.xCoordinate);\n    this.foreignObject_.setAttribute('y', this.yCoordinate);\n    this.foreignObject_.setAttribute('width', Math.max(0, outerLength));\n    this.outerDiv_.scrollLeft = Math.round(innerOffset);\n  } else {\n    var outerLength = hostMetrics.viewHeight;\n    if (this.pair_) {\n      // Shorten the scrollbar to make room for the corner square.\n      outerLength -= Blockly.Scrollbar.scrollbarThickness;\n    } else {\n      // Only show the scrollbar if needed.\n      this.setVisible(outerLength < hostMetrics.contentHeight);\n    }\n    this.ratio_ = outerLength / hostMetrics.viewHeight;\n    var innerLength = this.ratio_ * hostMetrics.contentHeight;\n    var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) *\n        this.ratio_;\n    this.outerDiv_.style.height = outerLength + 'px';\n    this.innerImg_.style.height = innerLength + 'px';\n    this.xCoordinate = hostMetrics.absoluteLeft;\n    if (!Blockly.RTL) {\n      this.xCoordinate += hostMetrics.viewWidth -\n          Blockly.Scrollbar.scrollbarThickness;\n    }\n    this.yCoordinate = hostMetrics.absoluteTop;\n    this.foreignObject_.setAttribute('x', this.xCoordinate);\n    this.foreignObject_.setAttribute('y', this.yCoordinate);\n    this.foreignObject_.setAttribute('height', Math.max(0, outerLength));\n    this.outerDiv_.scrollTop = Math.round(innerOffset);\n  }\n};\n\n/**\n * Create all the DOM elements required for a scrollbar.\n * The resulting widget is not sized.\n * @private\n */\nBlockly.ScrollbarNative.prototype.createDom_ = function() {\n  /* Create the following DOM:\n  <foreignObject xmlns=\"http://www.w3.org/2000/svg\">\n    <body xmlns=\"http://www.w3.org/1999/xhtml\" class=\"blocklyMinimalBody\">\n      <div>\n        <img src=\"media/1x1.gif\">\n      </div>\n    </body>\n  </foreignObject>\n  */\n  this.foreignObject_ = Blockly.createSvgElement('foreignObject', {}, null);\n  var body = document.createElementNS(Blockly.HTML_NS, 'body');\n  body.setAttribute('xmlns', Blockly.HTML_NS);\n  body.setAttribute('class', 'blocklyMinimalBody');\n  var outer = document.createElementNS(Blockly.HTML_NS, 'div');\n  this.outerDiv_ = outer;\n  var inner = document.createElementNS(Blockly.HTML_NS, 'img');\n  inner.setAttribute('src', Blockly.pathToBlockly + 'media/1x1.gif');\n  this.innerImg_ = inner;\n\n  outer.appendChild(inner);\n  body.appendChild(outer);\n  this.foreignObject_.appendChild(body);\n  Blockly.Scrollbar.insertAfter_(this.foreignObject_,\n                                 this.workspace_.getBubbleCanvas());\n};\n\n/**\n * Is the scrollbar visible.  Non-paired scrollbars disappear when they aren't\n * needed.\n * @return {boolean} True if visible.\n */\nBlockly.ScrollbarNative.prototype.isVisible = function() {\n  return this.foreignObject_.style.display != 'none';\n};\n\n/**\n * Set whether the scrollbar is visible.\n * Only applies to non-paired scrollbars.\n * @param {boolean} visible True if visible.\n */\nBlockly.ScrollbarNative.prototype.setVisible = function(visible) {\n  if (visible == this.isVisible()) {\n    return;\n  }\n  // Ideally this would also apply to scrollbar pairs, but that's a bigger\n  // headache (due to interactions with the corner square).\n  if (this.pair_) {\n    throw 'Unable to toggle visibility of paired scrollbars.';\n  }\n  if (visible) {\n    this.foreignObject_.style.display = 'block';\n    /* HACK:\n    For some reason Firefox requires the metrics to be recalculated after\n    displaying the scrollbar.  Even though the metrics are identical and\n    calculating these metrics has no side effects.  Failure to do so\n    results in a scrollbar that's crushed to 0 in an off-scale range.\n    */\n    this.workspace_.getMetrics();\n  } else {\n    // Hide the scrollbar.\n    this.workspace_.setMetrics({x: 0, y: 0});\n    this.foreignObject_.style.display = 'none';\n  }\n};\n\n/**\n * Called when scrollbar is dragged.\n * @private\n */\nBlockly.ScrollbarNative.prototype.onScroll_ = function() {\n  var xyRatio = {};\n  if (this.horizontal_) {\n    xyRatio.x = (this.outerDiv_.scrollLeft / this.innerImg_.offsetWidth) || 0;\n  } else {\n    xyRatio.y = (this.outerDiv_.scrollTop / this.innerImg_.offsetHeight) || 0;\n  }\n  this.workspace_.setMetrics(xyRatio);\n};\n\n/**\n * Set the scrollbar slider's position.\n * @param {number} value The distance from the top/left end of the bar.\n * @param {boolean} fireEvents True if onScroll events should be fired.\n */\nBlockly.ScrollbarNative.prototype.set = function(value, fireEvents) {\n  // If the scrollbar is part of a pair, it is slightly shorter than the view\n  // and the value needs to be scaled accordingly.\n  if (!fireEvents && this.onScrollWrapper_) {\n    // Temporarily suppress the onscroll event handler.\n    var scrollFunc = Blockly.unbindEvent_(this.onScrollWrapper_);\n  }\n  // Move the scrollbar slider.\n  if (this.horizontal_) {\n    this.outerDiv_.scrollLeft = value * this.ratio_;\n  } else {\n    this.outerDiv_.scrollTop = value * this.ratio_;\n  }\n  if (scrollFunc) {\n    // Re-enable the onscroll event handler.\n    var scrollbar = this;\n    this.onScrollWrapper_ = Blockly.bindEvent_(this.outerDiv_, 'scroll',\n        scrollbar, scrollFunc);\n  }\n};\n\n/**\n * Mutilate this scrollbar to measure the thickness of an HTML scrollbar.\n * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to.\n * @private\n */\nBlockly.ScrollbarNative.measureScrollbarThickness_ = function(workspace) {\n  var testBar = new Blockly.ScrollbarNative(workspace, null, false);\n\n  testBar.outerDiv_.style.width = '100px';\n  testBar.outerDiv_.style.height = '100px';\n  testBar.innerImg_.style.width = '100%';\n  testBar.innerImg_.style.height = '200px';\n  // Trivia: failure to set a height and width results in Firefox returning\n  // a scrollbar width of -85 instead of 15.\n  testBar.foreignObject_.setAttribute('width', 1);\n  testBar.foreignObject_.setAttribute('height', 1);\n\n  // Measure the width of the inner-most div.\n  testBar.outerDiv_.style.overflowY = 'scroll';\n  var w1 = testBar.innerImg_.offsetWidth;\n  // Turn off scrollbars and remeasure.\n  testBar.outerDiv_.style.overflowY = 'hidden';\n  var w2 = testBar.innerImg_.offsetWidth;\n\n  // Dispose of the test scrollbar.\n  goog.dom.removeNode(testBar.foreignObject_);\n\n  var thickness = w2 - w1;\n  if (thickness <= 0) {\n    // Chrome for OS X 10.7 (Lion) floats scrollbars over the content, meaning\n    // that there is no way to measure the thickness.  Pick a default.\n    thickness = 15;\n  }\n  Blockly.Scrollbar.scrollbarThickness = thickness;\n};\n\n// --------------------------------------------------------------------\n\n/**\n * Class for a pure SVG scrollbar.\n * This technique offers a scrollbar that is guaranteed to work, but may not\n * look or behave like the system's scrollbars.\n * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to.\n * @param {boolean} horizontal True if horizontal, false if vertical.\n * @param {boolean} opt_pair True if the scrollbar is part of a horiz/vert pair.\n * @constructor\n * @implements {Blockly.ScrollbarInterface}\n */\nBlockly.ScrollbarSvg = function(workspace, horizontal, opt_pair) {\n  this.workspace_ = workspace;\n  this.pair_ = opt_pair || false;\n  this.horizontal_ = horizontal;\n\n  this.createDom_();\n\n  if (horizontal) {\n    this.svgBackground_.setAttribute('height',\n        Blockly.Scrollbar.scrollbarThickness);\n    this.svgKnob_.setAttribute('height',\n        Blockly.Scrollbar.scrollbarThickness - 6);\n    this.svgKnob_.setAttribute('y', 3);\n  } else {\n    this.svgBackground_.setAttribute('width',\n        Blockly.Scrollbar.scrollbarThickness);\n    this.svgKnob_.setAttribute('width',\n        Blockly.Scrollbar.scrollbarThickness - 6);\n    this.svgKnob_.setAttribute('x', 6);\n  }\n  var scrollbar = this;\n\n  var pElement = this.workspace_.svgGroup_.parentElement ||\n                 this.workspace_.svgGroup_.parentNode;\n  //Blockly.bindEvent_(pElement, 'mouseenter', scrollbar, function(e){\n      //scrollbar.svgGroup_.setAttribute('opacity', '1');\n  //});\n  //Blockly.bindEvent_(pElement, 'mouseout', scrollbar, function(e) {\n      //var result = Blockly.isChild(pElement, e.toElement);\n      //if ( !(result || e.toElement == pElement)) {\n        //scrollbar.svgGroup_.setAttribute('opacity', '0');\n      //} else\n          //return;\n  //});\n  this.onMouseDownBarWrapper_ = Blockly.bindEvent_(this.svgBackground_,\n      'mousedown', scrollbar, scrollbar.onMouseDownBar_);\n  this.onMouseDownKnobWrapper_ = Blockly.bindEvent_(this.svgKnob_,\n      'mousedown', scrollbar, scrollbar.onMouseDownKnob_);\n};\n\n/**\n * set UI effect of this scrollbar.\n */\nBlockly.ScrollbarSvg.prototype.uiEffectInc_ = function(e) {\n    var pElement = this.workspace_.svgGroup_.parentElement;\n    var scrollbar = this.svgGroup_;\n    scrollbar.setAttribute('opacity', '1');\n    //var timerFunc= window.setInterval(function(){\n        //var currentOpacity = scrollbar.getAttribute('opacity');\n        //if (currentOpacity >= 1) {\n            //scrollbar.setAttribute('opacity', '1');\n            //clearInterval(timerFunc);\n        //} else {\n            //currentOpacity = Number(currentOpacity) + 0.05;\n            //scrollbar.setAttribute('opacity', currentOpacity);\n        //}\n    //}, 20);\n};\n\n/**\n * set UI effect of this scrollbar.\n */\nBlockly.ScrollbarSvg.prototype.uiEffectDec_ = function(e) {\n    return;\n    var pElement = this.workspace_.svgGroup_.parentElement;\n    var result = Entry.isChild(pElement, e.toElement);\n    var scrollbar = this.svgGroup_;\n    if ( !(result || e.toElement == pElement)) {\n        scrollbar.setAttribute('opacity', '0');\n    } else\n      return;\n};\n\n\n/**\n * Dispose of this scrollbar.\n * Unlink from all DOM elements to prevent memory leaks.\n */\nBlockly.ScrollbarSvg.prototype.dispose = function() {\n  this.onMouseUpKnob_();\n  if (this.onResizeWrapper_) {\n    Blockly.unbindEvent_(this.onResizeWrapper_);\n    this.onResizeWrapper_ = null;\n  }\n  Blockly.unbindEvent_(this.onMouseDownBarWrapper_);\n  this.onMouseDownBarWrapper_ = null;\n  Blockly.unbindEvent_(this.onMouseDownKnobWrapper_);\n  this.onMouseDownKnobWrapper_ = null;\n\n  goog.dom.removeNode(this.svgGroup_);\n  this.svgGroup_ = null;\n  this.svgBackground_ = null;\n  this.svgKnob_ = null;\n  this.workspace_ = null;\n};\n\n/**\n * Recalculate the scrollbar's location and its length.\n * @param {Object=} opt_metrics A data structure of from the describing all the\n * required dimensions.  If not provided, it will be fetched from the host\n * object.\n */\nBlockly.ScrollbarSvg.prototype.resize = function(opt_metrics) {\n  // Determine the location, height and width of the host element.\n  var hostMetrics = opt_metrics;\n  if (!hostMetrics) {\n    hostMetrics = this.workspace_.getMetrics();\n    if (!hostMetrics) {\n      // Host element is likely not visible.\n      return;\n    }\n  }\n  /* hostMetrics is an object with the following properties.\n   * .viewHeight: Height of the visible rectangle,\n   * .viewWidth: Width of the visible rectangle,\n   * .contentHeight: Height of the contents,\n   * .contentWidth: Width of the content,\n   * .viewTop: Offset of top edge of visible rectangle from parent,\n   * .viewLeft: Offset of left edge of visible rectangle from parent,\n   * .contentTop: Offset of the top-most content from the y=0 coordinate,\n   * .contentLeft: Offset of the left-most content from the x=0 coordinate,\n   * .absoluteTop: Top-edge of view.\n   * .absoluteLeft: Left-edge of view.\n   */\n  if (this.horizontal_) {\n    var outerLength = hostMetrics.viewWidth;\n    if (this.pair_) {\n      // Shorten the scrollbar to make room for the corner square.\n      outerLength -= Blockly.Scrollbar.scrollbarThickness;\n    } else {\n      // Only show the scrollbar if needed.\n      // Ideally this would also apply to scrollbar pairs, but that's a bigger\n      // headache (due to interactions with the corner square).\n      this.setVisible(outerLength < hostMetrics.contentHeight);\n    }\n    this.ratio_ = outerLength / hostMetrics.contentWidth;\n    if (this.ratio_ === -Infinity || this.ratio_ === Infinity ||\n        isNaN(this.ratio_)) {\n      this.ratio_ = 0;\n    }\n    var innerLength = hostMetrics.viewWidth * this.ratio_;\n    var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) *\n        this.ratio_;\n    this.svgKnob_.setAttribute('width', Math.max(0, innerLength));\n    this.xCoordinate = hostMetrics.absoluteLeft;\n    if (this.pair_ && Blockly.RTL) {\n      this.xCoordinate += hostMetrics.absoluteLeft +\n          Blockly.Scrollbar.scrollbarThickness;\n    }\n    this.yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight -\n        Blockly.Scrollbar.scrollbarThickness;\n    this.svgGroup_.setAttribute('transform',\n        'translate(' + this.xCoordinate + ', ' + this.yCoordinate + ')');\n    this.svgBackground_.setAttribute('width', Math.max(0, outerLength));\n    this.svgKnob_.setAttribute('x', this.constrainKnob_(innerOffset));\n  } else {\n    var outerLength = hostMetrics.viewHeight;\n    if (this.pair_) {\n      // Shorten the scrollbar to make room for the corner square.\n      outerLength -= Blockly.Scrollbar.scrollbarThickness;\n    } else {\n      // Only show the scrollbar if needed.\n      this.setVisible(outerLength < hostMetrics.contentHeight);\n    }\n    this.ratio_ = outerLength / hostMetrics.contentHeight;\n    if (this.ratio_ === -Infinity || this.ratio_ === Infinity ||\n        isNaN(this.ratio_)) {\n      this.ratio_ = 0;\n    }\n    var innerLength = hostMetrics.viewHeight * this.ratio_;\n    var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) *\n        this.ratio_;\n    this.svgKnob_.setAttribute('height', Math.max(0, innerLength));\n    this.xCoordinate = hostMetrics.absoluteLeft;\n    if (!Blockly.RTL) {\n      this.xCoordinate += hostMetrics.viewWidth -\n          Blockly.Scrollbar.scrollbarThickness;\n    }\n    this.yCoordinate = hostMetrics.absoluteTop;\n    this.svgGroup_.setAttribute('transform',\n        'translate(' + this.xCoordinate + ', ' + this.yCoordinate + ')');\n    this.svgBackground_.setAttribute('height', Math.max(0, outerLength));\n    this.svgKnob_.setAttribute('y', this.constrainKnob_(innerOffset));\n  }\n  // Resizing may have caused some scrolling.\n  //this.onScroll_();\n};\n\n/**\n * Create all the DOM elements required for a scrollbar.\n * The resulting widget is not sized.\n * @private\n */\nBlockly.ScrollbarSvg.prototype.createDom_ = function() {\n  /* Create the following DOM:\n  <g>\n    <rect class=\"blocklyScrollbarBackground\" />\n    <rect class=\"blocklyScrollbarKnob\" rx=\"7\" ry=\"7\" />\n  </g>\n  */\n  this.svgGroup_ = Blockly.createSvgElement('g', {}, null);\n  this.svgBackground_ = Blockly.createSvgElement('rect',\n      {'class': 'blocklyScrollbarBackground'}, this.svgGroup_);\n  var radius = Math.floor((Blockly.Scrollbar.scrollbarThickness - 6) / 2);\n  this.svgKnob_ = Blockly.createSvgElement('rect',\n      {'class': 'blocklyScrollbarKnob', 'rx': radius, 'ry': radius},\n      this.svgGroup_);\n  Blockly.Scrollbar.insertAfter_(this.svgGroup_,\n                                 this.workspace_.getBubbleCanvas());\n};\n\n/**\n * Is the scrollbar visible.  Non-paired scrollbars disappear when they aren't\n * needed.\n * @return {boolean} True if visible.\n */\nBlockly.ScrollbarSvg.prototype.isVisible = function() {\n  return this.svgGroup_.getAttribute('display') != 'none';\n};\n\n/**\n * Set whether the scrollbar is visible.\n * Only applies to non-paired scrollbars.\n * @param {boolean} visible True if visible.\n */\nBlockly.ScrollbarSvg.prototype.setVisible = function(visible) {\n  if (visible == this.isVisible()) {\n    return;\n  }\n  // Ideally this would also apply to scrollbar pairs, but that's a bigger\n  // headache (due to interactions with the corner square).\n  if (this.pair_) {\n    throw 'Unable to toggle visibility of paired scrollbars.';\n  }\n  if (visible) {\n    this.svgGroup_.setAttribute('display', 'block');\n  } else {\n    // Hide the scrollbar.\n    this.workspace_.setMetrics({x: 0, y: 0});\n    this.svgGroup_.setAttribute('display', 'none');\n  }\n};\n\n/**\n * Scroll by one pageful.\n * Called when scrollbar background is clicked.\n * @param {!Event} e Mouse down event.\n * @private\n */\nBlockly.ScrollbarSvg.prototype.onMouseDownBar_ = function(e) {\n  Blockly.hideChaff(true);\n  if (Blockly.isRightButton(e)) {\n    // Right-click.\n    // Scrollbars have no context menu.\n    e.stopPropagation();\n    return;\n  }\n  var mouseXY = Blockly.mouseToSvg(e);\n  var mouseLocation = this.horizontal_ ? mouseXY.x : mouseXY.y;\n\n  var knobXY = Blockly.getSvgXY_(this.svgKnob_);\n  var knobStart = this.horizontal_ ? knobXY.x : knobXY.y;\n  var knobLength = parseFloat(\n      this.svgKnob_.getAttribute(this.horizontal_ ? 'width' : 'height'));\n  var knobValue = parseFloat(\n      this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y'));\n\n  var pageLength = knobLength * 0.95;\n  if (mouseLocation <= knobStart) {\n    // Decrease the scrollbar's value by a page.\n    knobValue -= pageLength;\n  } else if (mouseLocation >= knobStart + knobLength) {\n    // Increase the scrollbar's value by a page.\n    knobValue += pageLength;\n  }\n  this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y',\n                             this.constrainKnob_(knobValue));\n  this.onScroll_();\n  e.stopPropagation();\n};\n\n/**\n * Start a dragging operation.\n * Called when scrollbar knob is clicked.\n * @param {!Event} e Mouse down event.\n * @private\n */\nBlockly.ScrollbarSvg.prototype.onMouseDownKnob_ = function(e) {\n  Blockly.hideChaff(true);\n  this.onMouseUpKnob_();\n  if (Blockly.isRightButton(e)) {\n    // Right-click.\n    // Scrollbars have no context menu.\n    e.stopPropagation();\n    return;\n  }\n  // Look up the current translation and record it.\n  this.startDragKnob = parseFloat(\n      this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y'));\n  // Record the current mouse position.\n  this.startDragMouse = this.horizontal_ ? e.clientX : e.clientY;\n  Blockly.ScrollbarSvg.onMouseUpWrapper_ = Blockly.bindEvent_(document,\n      'mouseup', this, this.onMouseUpKnob_);\n  Blockly.ScrollbarSvg.onMouseMoveWrapper_ = Blockly.bindEvent_(document,\n      'mousemove', this, this.onMouseMoveKnob_);\n  e.stopPropagation();\n};\n\n/**\n * Drag the scrollbar's knob.\n * @param {!Event} e Mouse up event.\n * @private\n */\nBlockly.ScrollbarSvg.prototype.onMouseMoveKnob_ = function(e) {\n  var currentMouse = this.horizontal_ ? e.clientX : e.clientY;\n  var mouseDelta = currentMouse - this.startDragMouse;\n  var knobValue = this.startDragKnob + mouseDelta;\n  // Position the bar.\n  this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y',\n                             this.constrainKnob_(knobValue));\n  this.onScroll_();\n};\n\n/**\n * Stop binding to the global mouseup and mousemove events.\n * @private\n */\nBlockly.ScrollbarSvg.prototype.onMouseUpKnob_ = function() {\n  if (Blockly.ScrollbarSvg.onMouseUpWrapper_) {\n    Blockly.unbindEvent_(Blockly.ScrollbarSvg.onMouseUpWrapper_);\n    Blockly.ScrollbarSvg.onMouseUpWrapper_ = null;\n  }\n  if (Blockly.ScrollbarSvg.onMouseMoveWrapper_) {\n    Blockly.unbindEvent_(Blockly.ScrollbarSvg.onMouseMoveWrapper_);\n    Blockly.ScrollbarSvg.onMouseMoveWrapper_ = null;\n  }\n};\n\n/**\n * Constrain the knob's position within the minimum (0) and maximum\n * (length of scrollbar) values allowed for the scrollbar.\n * @param {number} value Value that is potentially out of bounds.\n * @return {number} Constrained value.\n * @private\n */\nBlockly.ScrollbarSvg.prototype.constrainKnob_ = function(value) {\n  if (value <= 0 || isNaN(value)) {\n    value = 0;\n  } else {\n    var axis = this.horizontal_ ? 'width' : 'height';\n    var barLength = parseFloat(this.svgBackground_.getAttribute(axis));\n    var knobLength = parseFloat(this.svgKnob_.getAttribute(axis));\n    value = Math.min(value, barLength - knobLength);\n  }\n  return value;\n};\n\n/**\n * Called when scrollbar is moved.\n * @private\n */\nBlockly.ScrollbarSvg.prototype.onScroll_ = function() {\n  var knobValue = parseFloat(\n      this.svgKnob_.getAttribute(this.horizontal_ ? 'x' : 'y'));\n  var barLength = parseFloat(\n      this.svgBackground_.getAttribute(this.horizontal_ ? 'width' : 'height'));\n  var ratio = knobValue / barLength;\n  if (isNaN(ratio)) {\n    ratio = 0;\n  }\n  var xyRatio = {};\n  if (this.horizontal_) {\n    xyRatio.x = ratio;\n  } else {\n    xyRatio.y = ratio;\n  }\n  this.workspace_.setMetrics(xyRatio);\n  Blockly.hideChaff(true);\n};\n\n/**\n * Set the scrollbar slider's position.\n * @param {number} value The distance from the top/left end of the bar.\n * @param {boolean} fireEvents True if onScroll events should be fired.\n */\nBlockly.ScrollbarSvg.prototype.set = function(value, fireEvents) {\n  // Move the scrollbar slider.\n  this.svgKnob_.setAttribute(this.horizontal_ ? 'x' : 'y', value * this.ratio_);\n\n  if (fireEvents) {\n    this.onScroll_();\n  }\n};\n\n// --------------------------------------------------------------------\n\n/**\n * Choose between the native and the SVG implementations.  The native one is\n * preferred, provided that the browser supports it.\n * To test, see: tests/native_scrollbar_test.html\n * Known good user agents:\n * Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0.2)\n *     Gecko/20100101 Firefox/10.0.2\n * Mozilla/5.0 (Ubuntu; X11; Linux x86_64; rv:9.0.1)\n *     Gecko/20100101 Firefox/9.0.1\n */\n//if (goog.userAgent.GECKO &&\n    //(goog.userAgent.MAC || goog.userAgent.LINUX)) {\n  /**\n   * Class for a scrollbar.\n   */\n  Blockly.Scrollbar = Blockly.ScrollbarSvg;\n  /**\n   * Width of vertical scrollbar or height of horizontal scrollbar.\n   */\n  Blockly.Scrollbar.scrollbarThickness = 15;\n\n/**\n * Insert a node after a reference node.\n * Contrast with node.insertBefore function.\n * @param {!Element} newNode New element to insert.\n * @param {!Element} refNode Existing element to precede new node.\n * @private\n */\nBlockly.Scrollbar.insertAfter_ = function(newNode, refNode) {\n  var siblingNode = refNode.nextSibling;\n  var parentNode = refNode.parentNode;\n  if (!parentNode) {\n    throw 'Reference node has no parent.';\n  }\n  if (siblingNode) {\n    parentNode.insertBefore(newNode, siblingNode);\n  } else {\n    parentNode.appendChild(newNode);\n  }\n};\n"
  },
  {
    "path": "extern/blockly/core/toolbox.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Toolbox from whence to create blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Toolbox');\n\ngoog.require('Blockly.Flyout');\ngoog.require('goog.events.BrowserFeature');\ngoog.require('goog.style');\ngoog.require('goog.ui.tree.TreeControl');\ngoog.require('goog.ui.tree.TreeNode');\n\n\n/**\n * Width of the toolbox.\n * @type {number}\n */\nBlockly.Toolbox.width = 0;\n\n/**\n * The SVG group currently selected.\n * @type {SVGGElement}\n * @private\n */\nBlockly.Toolbox.selectedOption_ = null;\n\n/**\n * Configuration constants for Closure's tree UI.\n * @type {Object.<string,*>}\n * @const\n * @private\n */\nBlockly.Toolbox.CONFIG_ = {\n  indentWidth: 19,\n  cssRoot: 'blocklyTreeRoot',\n  cssHideRoot: 'blocklyHidden',\n  cssItem: '',\n  cssTreeRow: 'blocklyTreeRow',\n  cssItemLabel: 'blocklyTreeLabel',\n  cssTreeIcon: 'blocklyTreeIcon',\n  cssExpandedFolderIcon: 'blocklyTreeIconOpen',\n  cssFileIcon: 'blocklyTreeIconNone',\n  cssSelectedRow: 'blocklyTreeSelected'\n};\n\n/**\n * Creates the toolbox's DOM.  Only needs to be called once.\n * @param {!Element} svg The top-level SVG element.\n * @param {!Element} container The SVG's HTML parent element.\n */\nBlockly.Toolbox.createDom = function(svg, container) {\n  // Create an HTML container for the Toolbox menu.\n  Blockly.Toolbox.HtmlDiv = goog.dom.createDom('div', 'blocklyToolboxDiv');\n  Blockly.Toolbox.HtmlDiv.setAttribute('dir', Blockly.RTL ? 'RTL' : 'LTR');\n  container.appendChild(Blockly.Toolbox.HtmlDiv);\n\n  /**\n   * @type {!Blockly.Flyout}\n   * @private\n   */\n  Blockly.Toolbox.flyout_ = new Blockly.Flyout();\n  //Blockly.Toolbox.flyout_.hide = function() {};\n  svg.appendChild(Blockly.Toolbox.flyout_.createDom());\n\n  // Clicking on toolbar closes popups.\n  Blockly.bindEvent_(Blockly.Toolbox.HtmlDiv, 'mousedown', null,\n      function(e) {\n        if (Blockly.isRightButton(e) || e.target == Blockly.Toolbox.HtmlDiv) {\n          // Close flyout.\n          Blockly.hideChaff(false);\n        } else {\n          // Just close popups.\n          Blockly.hideChaff(true);\n        }\n      });\n};\n\n/**\n * Initializes the toolbox.\n */\nBlockly.Toolbox.init = function() {\n  Blockly.Toolbox.CONFIG_['cleardotPath'] =\n      Blockly.pathToBlockly + 'media/1x1.gif';\n  Blockly.Toolbox.CONFIG_['cssCollapsedFolderIcon'] =\n      'blocklyTreeIconClosed' + (Blockly.RTL ? 'Rtl' : 'Ltr');\n  var tree = new Blockly.Toolbox.TreeControl('root', Blockly.Toolbox.CONFIG_);\n  Blockly.Toolbox.tree_ = tree;\n  tree.setShowRootNode(false);\n  tree.setShowLines(false);\n  tree.setShowExpandIcons(false);\n  tree.setSelectedItem(null);\n\n  Blockly.Toolbox.HtmlDiv.style.display = 'block';\n  Blockly.Toolbox.flyout_.init(Blockly.mainWorkspace, true);\n  Blockly.Toolbox.populate_();\n  tree.render(Blockly.Toolbox.HtmlDiv);\n\n  // If the document resizes, reposition the toolbox.\n  goog.events.listen(window, goog.events.EventType.RESIZE,\n                     Blockly.Toolbox.position_);\n  Blockly.Toolbox.position_();\n};\n\n/**\n * Move the toolbox to the edge.\n * @private\n */\nBlockly.Toolbox.position_ = function() {\n  var treeDiv = Blockly.Toolbox.HtmlDiv;\n  var svgBox = goog.style.getBorderBox(Blockly.svg);\n  var svgSize = Blockly.svgSize();\n  if (Blockly.RTL) {\n    var xy = Blockly.convertCoordinates(0, 0, false);\n    treeDiv.style.left = (xy.x + svgSize.width - treeDiv.offsetWidth) + 'px';\n  } else {\n    treeDiv.style.marginLeft = svgBox.left;\n  }\n  treeDiv.style.height = (svgSize.height + 1) + 'px';\n  Blockly.Toolbox.width = treeDiv.offsetWidth;\n  if (!Blockly.RTL) {\n    // For some reason the LTR toolbox now reports as 1px too wide.\n    Blockly.Toolbox.width -= 1;\n  }\n};\n\n/**\n * Fill the toolbox with categories and blocks.\n * @private\n */\nBlockly.Toolbox.populate_ = function() {\n  var rootOut = Blockly.Toolbox.tree_;\n  rootOut.blocks = [];\n  function syncTrees(treeIn, treeOut) {\n    for (var i = 0, childIn; childIn = treeIn.childNodes[i]; i++) {\n      if (!childIn.tagName) {\n        // Skip over text.\n        continue;\n      }\n      var name = childIn.tagName.toUpperCase();\n      if (name == 'CATEGORY') {\n        var childOut = rootOut.createNode(childIn.getAttribute('name'));\n        childOut.blocks = [];\n        treeOut.add(childOut);\n        var custom = childIn.getAttribute('custom');\n        if (custom) {\n          // Variables and procedures have special categories that are dynamic.\n          childOut.blocks = custom;\n        } else {\n          syncTrees(childIn, childOut);\n        }\n      } else if (name == 'BLOCK') {\n        treeOut.blocks.push(childIn);\n      }\n    }\n  }\n  syncTrees(Blockly.languageTree, Blockly.Toolbox.tree_);\n\n  if (rootOut.blocks.length) {\n    throw 'Toolbox cannot have both blocks and categories in the root level.';\n  }\n\n  // Fire a resize event since the toolbox may have changed width and height.\n  Blockly.fireUiEvent(window, 'resize');\n};\n\n/**\n * Unhighlight any previously specified option.\n */\nBlockly.Toolbox.clearSelection = function() {\n  Blockly.Toolbox.tree_.setSelectedItem(null);\n};\n\n// Extending Closure's Tree UI.\n\n/**\n * Extention of a TreeControl object that uses a custom tree node.\n * @param {string} html The HTML content of the node label.\n * @param {Object=} opt_config The configuration for the tree. See\n *    goog.ui.tree.TreeControl.DefaultConfig. If not specified, a default config\n *    will be used.\n * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.\n * @constructor\n * @extends {goog.ui.tree.TreeControl}\n */\nBlockly.Toolbox.TreeControl = function(html, opt_config, opt_domHelper) {\n  goog.ui.tree.TreeControl.call(this, html, opt_config, opt_domHelper);\n};\ngoog.inherits(Blockly.Toolbox.TreeControl, goog.ui.tree.TreeControl);\n\n/**\n * Adds touch handling to TreeControl.\n * @override\n */\nBlockly.Toolbox.TreeControl.prototype.enterDocument = function() {\n  Blockly.Toolbox.TreeControl.superClass_.enterDocument.call(this);\n\n  // Add touch handler.\n  if (goog.events.BrowserFeature.TOUCH_ENABLED) {\n    var el = this.getElement();\n    Blockly.bindEvent_(el, goog.events.EventType.TOUCHSTART, this,\n        this.handleTouchEvent_);\n  }\n};\n/**\n * Handles touch events.\n * @param {!goog.events.BrowserEvent} e The browser event.\n * @private\n */\nBlockly.Toolbox.TreeControl.prototype.handleTouchEvent_ = function(e) {\n  e.preventDefault();\n  var node = this.getNodeFromEvent_(e);\n  if (node && e.type === goog.events.EventType.TOUCHSTART) {\n    // Fire asynchronously since onMouseDown takes long enough that the browser\n    // would fire the default mouse event before this method returns.\n    window.setTimeout(function() {\n      node.onMouseDown(e);  // Same behavior for click and touch.\n    }, 1);\n  }\n};\n\n/**\n * Creates a new tree node using a custom tree node.\n * @param {string} html The html content of the node label.\n * @return {goog.ui.tree.TreeNode} The new item.\n * @override\n */\nBlockly.Toolbox.TreeControl.prototype.createNode = function(html) {\n  return new Blockly.Toolbox.TreeNode(html || '', this.getConfig(),\n      this.getDomHelper());\n};\n\n/**\n * Display/hide the flyout when an item is selected.\n * @param {goog.ui.tree.BaseNode} node The item to select.\n * @override\n */\nBlockly.Toolbox.TreeControl.prototype.setSelectedItem = function(node) {\n  if (this.selectedItem_ == node) {\n    return;\n  }\n  goog.ui.tree.TreeControl.prototype.setSelectedItem.call(this, node);\n  if (node && node.blocks && node.blocks.length) {\n    Blockly.Toolbox.flyout_.show(node.blocks);\n  } else {\n    // Hide the flyout.\n    Blockly.Toolbox.flyout_.hide();\n  }\n};\n\n/**\n * An single node in the tree, customized for Blockly's UI.\n * @param {string} html The html content of the node label.\n * @param {Object=} opt_config The configuration for the tree. See\n *    goog.ui.tree.TreeControl.DefaultConfig. If not specified, a default config\n *    will be used.\n * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.\n * @constructor\n * @extends {goog.ui.tree.TreeNode}\n */\nBlockly.Toolbox.TreeNode = function(html, opt_config, opt_domHelper) {\n  goog.ui.tree.TreeNode.call(this, html, opt_config, opt_domHelper);\n  var resize = function() {\n    Blockly.fireUiEvent(window, 'resize');\n  };\n  // Fire a resize event since the toolbox may have changed width.\n  goog.events.listen(Blockly.Toolbox.tree_,\n      goog.ui.tree.BaseNode.EventType.EXPAND, resize);\n  goog.events.listen(Blockly.Toolbox.tree_,\n      goog.ui.tree.BaseNode.EventType.COLLAPSE, resize);\n};\ngoog.inherits(Blockly.Toolbox.TreeNode, goog.ui.tree.TreeNode);\n\n/**\n * Do not show the +/- icon.\n * @return {string} The source for the icon.\n * @override\n */\nBlockly.Toolbox.TreeNode.prototype.getExpandIconHtml = function() {\n  return '<span></span>';\n};\n\n/**\n * Supress population of the +/- icon.\n * @return {null} Null.\n * @protected\n * @override\n */\nBlockly.Toolbox.TreeNode.prototype.getExpandIconElement = function() {\n  return null;\n};\n\n/**\n * Expand or collapse the node on mouse click.\n * @param {!goog.events.BrowserEvent} e The browser event.\n * @override\n */\nBlockly.Toolbox.TreeNode.prototype.onMouseDown = function(e) {\n  // Expand icon.\n  if (this.hasChildren() && this.isUserCollapsible_) {\n    this.toggle();\n    this.select();\n  } else if (this.isSelected()) {\n    this.getTree().setSelectedItem(null);\n  } else {\n    this.select();\n  }\n  this.updateRow();\n};\n\n/**\n * Supress the inherited double-click behaviour.\n * @param {!goog.events.BrowserEvent} e The browser event.\n * @override\n * @private\n */\nBlockly.Toolbox.TreeNode.prototype.onDoubleClick_ = function(e) {\n  // NOP.\n};\n"
  },
  {
    "path": "extern/blockly/core/tooltip.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Library to create tooltips for Blockly.\n * First, call Blockly.Tooltip.init() after onload.\n * Second, set the 'tooltip' property on any SVG element that needs a tooltip.\n * If the tooltip is a string, then that message will be displayed.\n * If the tooltip is an SVG element, then that object's tooltip will be used.\n * Third, call Blockly.Tooltip.bindMouseEvents(e) passing the SVG element.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Tooltip');\n\n\n/**\n * Is a tooltip currently showing?\n */\nBlockly.Tooltip.visible = false;\n\n/**\n * PID of suspended thread to clear tooltip on mouse out.\n * @private\n */\nBlockly.Tooltip.mouseOutPid_ = 0;\n\n/**\n * PID of suspended thread to show the tooltip.\n * @private\n */\nBlockly.Tooltip.showPid_ = 0;\n\n/**\n * Last observed location of the mouse pointer (freezes when tooltip appears).\n * @private\n */\nBlockly.Tooltip.lastXY_ = {x: 0, y: 0};\n\n/**\n * Current element being pointed at.\n * @private\n */\nBlockly.Tooltip.element_ = null;\n\n/**\n * Once a tooltip has opened for an element, that element is 'poisoned' and\n * cannot respawn a tooltip until the pointer moves over a different element.\n * @private\n */\nBlockly.Tooltip.poisonedElement_ = null;\n\n/**\n * Tooltip's SVG group element.\n * @type {Element}\n * @private\n */\nBlockly.Tooltip.svgGroup_ = null;\n\n/**\n * Tooltip's SVG text element.\n * @type {SVGTextElement}\n * @private\n */\nBlockly.Tooltip.svgText_ = null;\n\n/**\n * Tooltip's SVG background rectangle.\n * @type {Element}\n * @private\n */\nBlockly.Tooltip.svgBackground_ = null;\n\n/**\n * Tooltip's SVG shadow rectangle.\n * @type {Element}\n * @private\n */\nBlockly.Tooltip.svgShadow_ = null;\n\n/**\n * Horizontal offset between mouse cursor and tooltip.\n */\nBlockly.Tooltip.OFFSET_X = 0;\n\n/**\n * Vertical offset between mouse cursor and tooltip.\n */\nBlockly.Tooltip.OFFSET_Y = 10;\n\n/**\n * Radius mouse can move before killing tooltip.\n */\nBlockly.Tooltip.RADIUS_OK = 10;\n\n/**\n * Delay before tooltip appears.\n */\nBlockly.Tooltip.HOVER_MS = 1000;\n\n/**\n * Horizontal padding between text and background.\n */\nBlockly.Tooltip.MARGINS = 5;\n\n/**\n * Create the tooltip elements.  Only needs to be called once.\n * @return {!SVGGElement} The tooltip's SVG group.\n */\nBlockly.Tooltip.createDom = function() {\n  /*\n  <g class=\"blocklyHidden\">\n    <rect class=\"blocklyTooltipShadow\" x=\"2\" y=\"2\"/>\n    <rect class=\"blocklyTooltipBackground\"/>\n    <text class=\"blocklyTooltipText\"></text>\n  </g>\n  */\n  var svgGroup = /** @type {!SVGGElement} */ (\n      Blockly.createSvgElement('g', {'class': 'blocklyHidden'}, null));\n  Blockly.Tooltip.svgGroup_ = svgGroup;\n  Blockly.Tooltip.svgShadow_ = /** @type {!SVGRectElement} */ (\n      Blockly.createSvgElement(\n          'rect', {'class': 'blocklyTooltipShadow', 'x': 2, 'y': 2}, svgGroup));\n  Blockly.Tooltip.svgBackground_ = /** @type {!SVGRectElement} */ (\n      Blockly.createSvgElement(\n          'rect', {'class': 'blocklyTooltipBackground'}, svgGroup));\n  Blockly.Tooltip.svgText_ = /** @type {!SVGTextElement} */ (\n      Blockly.createSvgElement(\n          'text', {'class': 'blocklyTooltipText'}, svgGroup));\n  return svgGroup;\n};\n\n/**\n * Binds the required mouse events onto an SVG element.\n * @param {!Element} element SVG element onto which tooltip is to be bound.\n */\nBlockly.Tooltip.bindMouseEvents = function(element) {\n  Blockly.bindEvent_(element, 'mouseover', null, Blockly.Tooltip.onMouseOver_);\n  Blockly.bindEvent_(element, 'mouseout', null, Blockly.Tooltip.onMouseOut_);\n  Blockly.bindEvent_(element, 'mousemove', null, Blockly.Tooltip.onMouseMove_);\n};\n\n/**\n * Hide the tooltip if the mouse is over a different object.\n * Initialize the tooltip to potentially appear for this object.\n * @param {!Event} e Mouse event.\n * @private\n */\nBlockly.Tooltip.onMouseOver_ = function(e) {\n  // If the tooltip is an object, treat it as a pointer to the next object in\n  // the chain to look at.  Terminate when a string or function is found.\n  var element = e.target;\n  while (!goog.isString(element.tooltip) && !goog.isFunction(element.tooltip)) {\n    element = element.tooltip;\n  }\n  if (Blockly.Tooltip.element_ != element) {\n    Blockly.Tooltip.hide();\n    Blockly.Tooltip.poisonedElement_ = null;\n    Blockly.Tooltip.element_ = element;\n  }\n  // Forget about any immediately preceeding mouseOut event.\n  window.clearTimeout(Blockly.Tooltip.mouseOutPid_);\n};\n\n/**\n * Hide the tooltip if the mouse leaves the object and enters the workspace.\n * @param {!Event} e Mouse event.\n * @private\n */\nBlockly.Tooltip.onMouseOut_ = function(e) {\n  // Moving from one element to another (overlapping or with no gap) generates\n  // a mouseOut followed instantly by a mouseOver.  Fork off the mouseOut\n  // event and kill it if a mouseOver is received immediately.\n  // This way the task only fully executes if mousing into the void.\n  Blockly.Tooltip.mouseOutPid_ = window.setTimeout(function() {\n        Blockly.Tooltip.element_ = null;\n        Blockly.Tooltip.poisonedElement_ = null;\n        Blockly.Tooltip.hide();\n      }, 1);\n  window.clearTimeout(Blockly.Tooltip.showPid_);\n};\n\n/**\n * When hovering over an element, schedule a tooltip to be shown.  If a tooltip\n * is already visible, hide it if the mouse strays out of a certain radius.\n * @param {!Event} e Mouse event.\n * @private\n */\nBlockly.Tooltip.onMouseMove_ = function(e) {\n  if (!Blockly.Tooltip.element_ || !Blockly.Tooltip.element_.tooltip) {\n    // No tooltip here to show.\n    return;\n  } else if ((Blockly.ContextMenu && Blockly.ContextMenu.visible) ||\n             Blockly.Block.dragMode_ != 0) {\n    // Don't display a tooltip when a context menu is active, or during a drag.\n    return;\n  }\n  if (Blockly.Tooltip.visible) {\n    // Compute the distance between the mouse position when the tooltip was\n    // shown and the current mouse position.  Pythagorean theorem.\n    var mouseXY = Blockly.mouseToSvg(e);\n    var dx = Blockly.Tooltip.lastXY_.x - mouseXY.x;\n    var dy = Blockly.Tooltip.lastXY_.y - mouseXY.y;\n    var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));\n    if (dr > Blockly.Tooltip.RADIUS_OK) {\n      Blockly.Tooltip.hide();\n    }\n  } else if (Blockly.Tooltip.poisonedElement_ != Blockly.Tooltip.element_) {\n    // The mouse moved, clear any previously scheduled tooltip.\n    window.clearTimeout(Blockly.Tooltip.showPid_);\n    // Maybe this time the mouse will stay put.  Schedule showing of tooltip.\n    Blockly.Tooltip.lastXY_ = Blockly.mouseToSvg(e);\n    Blockly.Tooltip.showPid_ =\n        window.setTimeout(Blockly.Tooltip.show_, Blockly.Tooltip.HOVER_MS);\n  }\n};\n\n/**\n * Hide the tooltip.\n */\nBlockly.Tooltip.hide = function() {\n  if (Blockly.Tooltip.visible) {\n    Blockly.Tooltip.visible = false;\n    if (Blockly.Tooltip.svgGroup_) {\n      Blockly.Tooltip.svgGroup_.style.display = 'none';\n    }\n  }\n  window.clearTimeout(Blockly.Tooltip.showPid_);\n};\n\n/**\n * Create the tooltip and show it.\n * @private\n */\nBlockly.Tooltip.show_ = function() {\n  Blockly.Tooltip.poisonedElement_ = Blockly.Tooltip.element_;\n  if (!Blockly.Tooltip.svgGroup_) {\n    return;\n  }\n  // Erase all existing text.\n  goog.dom.removeChildren(\n      /** @type {!Element} */ (Blockly.Tooltip.svgText_));\n  // Create new text, line by line.\n  var tip = Blockly.Tooltip.element_.tooltip;\n  if (goog.isFunction(tip)) {\n    tip = tip();\n  }\n  var lines = tip.split('\\n');\n  for (var i = 0; i < lines.length; i++) {\n    var tspanElement = Blockly.createSvgElement('tspan',\n        {'dy': '1em', 'x': Blockly.Tooltip.MARGINS}, Blockly.Tooltip.svgText_);\n    var textNode = document.createTextNode(lines[i]);\n    tspanElement.appendChild(textNode);\n  }\n  // Display the tooltip.\n  Blockly.Tooltip.visible = true;\n  Blockly.Tooltip.svgGroup_.style.display = 'block';\n  // Resize the background and shadow to fit.\n  var bBox = Blockly.Tooltip.svgText_.getBBox();\n  var width = 2 * Blockly.Tooltip.MARGINS + bBox.width;\n  var height = bBox.height;\n  Blockly.Tooltip.svgBackground_.setAttribute('width', width);\n  Blockly.Tooltip.svgBackground_.setAttribute('height', height);\n  Blockly.Tooltip.svgShadow_.setAttribute('width', width);\n  Blockly.Tooltip.svgShadow_.setAttribute('height', height);\n  if (Blockly.RTL) {\n    // Right-align the paragraph.\n    // This cannot be done until the tooltip is rendered on screen.\n    var maxWidth = bBox.width;\n    for (var x = 0, textElement;\n         textElement = Blockly.Tooltip.svgText_.childNodes[x]; x++) {\n      textElement.setAttribute('text-anchor', 'end');\n      textElement.setAttribute('x', maxWidth + Blockly.Tooltip.MARGINS);\n    }\n  }\n  // Move the tooltip to just below the cursor.\n  var anchorX = Blockly.Tooltip.lastXY_.x;\n  if (Blockly.RTL) {\n    anchorX -= Blockly.Tooltip.OFFSET_X + width;\n  } else {\n    anchorX += Blockly.Tooltip.OFFSET_X;\n  }\n  var anchorY = Blockly.Tooltip.lastXY_.y + Blockly.Tooltip.OFFSET_Y;\n\n  var svgSize = Blockly.svgSize();\n  if (anchorY + bBox.height > svgSize.height) {\n    // Falling off the bottom of the screen; shift the tooltip up.\n    anchorY -= bBox.height + 2 * Blockly.Tooltip.OFFSET_Y;\n  }\n  if (Blockly.RTL) {\n    // Prevent falling off left edge in RTL mode.\n    anchorX = Math.max(Blockly.Tooltip.MARGINS, anchorX);\n  } else {\n    if (anchorX + bBox.width > svgSize.width - 2 * Blockly.Tooltip.MARGINS) {\n      // Falling off the right edge of the screen;\n      // clamp the tooltip on the edge.\n      anchorX = svgSize.width - bBox.width - 2 * Blockly.Tooltip.MARGINS;\n    }\n  }\n  Blockly.Tooltip.svgGroup_.setAttribute('transform',\n      'translate(' + anchorX + ',' + anchorY + ')');\n};\n"
  },
  {
    "path": "extern/blockly/core/trashcan.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing a trash can icon.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Trashcan');\n\ngoog.require('goog.Timer');\n\n\n/**\n * Class for a trash can.\n * @param {!Blockly.Workspace} workspace The workspace to sit in.\n * @constructor\n */\nBlockly.Trashcan = function(workspace) {\n  this.workspace_ = workspace;\n};\n\n/**\n * URL of the trashcan image (minus lid).\n * @type {string}\n * @private\n */\nBlockly.Trashcan.prototype.BODY_URL_ = '/media/trashbody.png';\n\n/**\n * URL of the lid image.\n * @type {string}\n * @private\n */\nBlockly.Trashcan.prototype.LID_URL_ = '/media/trashlid.png';\n\n/**\n * Width of both the trash can and lid images.\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.WIDTH_ = 57;\n\n/**\n * Height of the trashcan image (minus lid).\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.BODY_HEIGHT_ = 55;\n\n/**\n * Height of the lid image.\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.LID_HEIGHT_ = 18;\n\n/**\n * Distance between trashcan and bottom edge of workspace.\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.MARGIN_BOTTOM_ = 55;\n\n/**\n * Distance between trashcan and right edge of workspace.\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.MARGIN_SIDE_ = 55;\n\n/**\n * Current open/close state of the lid.\n * @type {boolean}\n */\nBlockly.Trashcan.prototype.isOpen = false;\n\n/**\n * The SVG group containing the trash can.\n * @type {Element}\n * @private\n */\nBlockly.Trashcan.prototype.svgGroup_ = null;\n\n/**\n * The SVG image element of the trash can body.\n * @type {Element}\n * @private\n */\nBlockly.Trashcan.prototype.svgBody_ = null;\n\n/**\n * The SVG image element of the trash can lid.\n * @type {Element}\n * @private\n */\nBlockly.Trashcan.prototype.svgLid_ = null;\n\n/**\n * Task ID of opening/closing animation.\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.lidTask_ = 0;\n\n/**\n * Current angle of the lid.\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.lidAngle_ = 0;\n\n/**\n * Left coordinate of the trash can.\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.left_ = 0;\n\n/**\n * Top coordinate of the trash can.\n * @type {number}\n * @private\n */\nBlockly.Trashcan.prototype.top_ = 0;\n\n/**\n * Create the trash can elements.\n * @return {!Element} The trash can's SVG group.\n */\nBlockly.Trashcan.prototype.createDom = function() {\n  /*\n  <g filter=\"url(#blocklyTrashcanShadowFilter)\">\n    <image width=\"47\" height=\"45\" y=\"15\" href=\"media/trashbody.png\"></image>\n    <image width=\"47\" height=\"15\" href=\"media/trashlid.png\"></image>\n  </g>\n  */\n  this.svgGroup_ = Blockly.createSvgElement('g',\n      {'filter': 'url(#blocklyTrashcanShadowFilter)'}, null);\n    Blockly.bindEvent_(this.svgGroup_, 'mousedown', this,\n                       function(e) {\n  if (Blockly.isRightButton(e)) {\n                           console.log('hi');\n    document.getElementById('entryBlockly').style.background = 'white';\n  }\n                       });\n  this.svgBody_ = Blockly.createSvgElement('image',\n      {'width': this.WIDTH_, 'height': this.BODY_HEIGHT_},\n      this.svgGroup_);\n  this.svgBody_.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',\n      Blockly.mediaFilePath + this.BODY_URL_);\n  this.svgBody_.setAttribute('y', this.LID_HEIGHT_);\n  this.svgLid_ = Blockly.createSvgElement('image',\n      {'width': this.WIDTH_, 'height': this.LID_HEIGHT_},\n      this.svgGroup_);\n  this.svgLid_.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href',\n      Blockly.mediaFilePath + this.LID_URL_);\n  return this.svgGroup_;\n};\n\n/**\n * Initialize the trash can.\n */\nBlockly.Trashcan.prototype.init = function() {\n  this.setOpen_(false);\n  this.position_();\n  // If the document resizes, reposition the trash can.\n  Blockly.bindEvent_(window, 'resize', this, this.position_);\n};\n\n/**\n * Dispose of this trash can.\n * Unlink from all DOM elements to prevent memory leaks.\n */\nBlockly.Trashcan.prototype.dispose = function() {\n  if (this.svgGroup_) {\n    goog.dom.removeNode(this.svgGroup_);\n    this.svgGroup_ = null;\n  }\n  this.svgBody_ = null;\n  this.svgLid_ = null;\n  this.workspace_ = null;\n  goog.Timer.clear(this.lidTask_);\n};\n\n/**\n * Move the trash can to the bottom-right corner.\n * @private\n */\nBlockly.Trashcan.prototype.position_ = function() {\n  var metrics = this.workspace_.getMetrics();\n  if (!metrics) {\n    // There are no metrics available (workspace is probably not visible).\n    return;\n  }\n  if (Blockly.RTL) {\n    this.left_ = this.MARGIN_SIDE_;\n  } else {\n    this.left_ = metrics.viewWidth + metrics.absoluteLeft -\n        this.WIDTH_ - this.MARGIN_SIDE_;\n  }\n  this.top_ = metrics.viewHeight + metrics.absoluteTop -\n      (this.BODY_HEIGHT_ + this.LID_HEIGHT_) - this.MARGIN_BOTTOM_;\n  this.svgGroup_.setAttribute('transform',\n      'translate(' + this.left_ + ',' + this.top_ + ')');\n};\n\n/**\n * Determines if the mouse is currently over the trash can.\n * Opens/closes the lid and sets the isOpen flag.\n * @param {!Event} e Mouse move event.\n */\nBlockly.Trashcan.prototype.onMouseMove = function(e) {\n  /*\n  An alternative approach would be to use onMouseOver and onMouseOut events.\n  However the selected block will be between the mouse and the trash can,\n  thus these events won't fire.\n  Another approach is to use HTML5's drag & drop API, but it's widely hated.\n  Instead, we'll just have the block's drag_ function call us.\n  */\n  if (!this.svgGroup_) {\n    return;\n  }\n  var mouseXY = Blockly.mouseToSvg(e);\n  var trashXY = Blockly.getSvgXY_(this.svgGroup_);\n  var over = (mouseXY.x + 25 > trashXY.x) &&\n             (mouseXY.x < trashXY.x + this.WIDTH_ + 25 ) &&\n             (mouseXY.y + 25  > trashXY.y) &&\n             (mouseXY.y < trashXY.y + this.BODY_HEIGHT_ + this.LID_HEIGHT_ + 25 );\n  // For bonus points we might want to match the trapezoidal outline.\n  if (this.isOpen != over) {\n    this.setOpen_(over);\n  }\n};\n\n/**\n * Flip the lid open or shut.\n * @param {boolean} state True if open.\n * @private\n */\nBlockly.Trashcan.prototype.setOpen_ = function(state) {\n  if (this.isOpen == state) {\n    return;\n  }\n  goog.Timer.clear(this.lidTask_);\n  this.isOpen = state;\n  this.animateLid_();\n};\n\n/**\n * Rotate the lid open or closed by one step.  Then wait and recurse.\n * @private\n */\nBlockly.Trashcan.prototype.animateLid_ = function() {\n  this.lidAngle_ += this.isOpen ? 10 : -10;\n  this.lidAngle_ = Math.max(0, this.lidAngle_);\n  this.svgLid_.setAttribute('transform', 'rotate(' +\n      (Blockly.RTL ? -this.lidAngle_ : this.lidAngle_) + ', ' +\n      (Blockly.RTL ? 4 : this.WIDTH_ - 4) + ', ' +\n      (this.LID_HEIGHT_ - 2) + ')');\n  if (this.isOpen ? (this.lidAngle_ < 45) : (this.lidAngle_ > 0)) {\n    this.lidTask_ = goog.Timer.callOnce(this.animateLid_, 5, this);\n  }\n};\n\n/**\n * Flip the lid shut.\n * Called externally after a drag.\n */\nBlockly.Trashcan.prototype.close = function() {\n  this.setOpen_(false);\n};\n"
  },
  {
    "path": "extern/blockly/core/utils.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Utility methods.\n * These methods are not specific to Blockly, and could be factored out if\n * a JavaScript framework such as Closure were used.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.utils');\n\n\n/**\n * Add a CSS class to a element.\n * Similar to Closure's goog.dom.classes.add, except it handles SVG elements.\n * @param {!Element} element DOM element to add class to.\n * @param {string} className Name of class to add.\n * @private\n */\nBlockly.addClass_ = function(element, className) {\n  var classes = element.getAttribute('class') || '';\n  if ((' ' + classes + ' ').indexOf(' ' + className + ' ') == -1) {\n    if (classes) {\n      classes += ' ';\n    }\n    element.setAttribute('class', classes + className);\n  }\n};\n\n/**\n * Remove a CSS class from a element.\n * Similar to Closure's goog.dom.classes.remove, except it handles SVG elements.\n * @param {!Element} element DOM element to remove class from.\n * @param {string} className Name of class to remove.\n * @private\n */\nBlockly.removeClass_ = function(element, className) {\n  var classes = element.getAttribute('class');\n  if ((' ' + classes + ' ').indexOf(' ' + className + ' ') != -1) {\n    var classList = classes.split(/\\s+/);\n    for (var i = 0; i < classList.length; i++) {\n      if (!classList[i] || classList[i] == className) {\n        classList.splice(i, 1);\n        i--;\n      }\n    }\n    if (classList.length) {\n      element.setAttribute('class', classList.join(' '));\n    } else {\n      element.removeAttribute('class');\n    }\n  }\n};\n\n/**\n * Bind an event to a function call.\n * @param {!Element} element Element upon which to listen.\n * @param {string} name Event name to listen to (e.g. 'mousedown').\n * @param {Object} thisObject The value of 'this' in the function.\n * @param {!Function} func Function to call when event is triggered.\n * @return {!Array.<!Array>} Opaque data that can be passed to unbindEvent_.\n * @private\n */\nBlockly.bindEvent_ = function(element, name, thisObject, func) {\n  var bindData = [];\n  var wrapFunc;\n  if (!element.addEventListener) {\n    throw 'Element is not a DOM node with addEventListener.';\n  }\n  wrapFunc = function(e) {\n    func.apply(thisObject, arguments);\n  };\n  element.addEventListener(name, wrapFunc, false);\n  bindData.push([element, name, wrapFunc]);\n  // Add equivalent touch event.\n  if (name in Blockly.bindEvent_.TOUCH_MAP) {\n    wrapFunc = function(e) {\n      // Punt on multitouch events.\n      if (e.changedTouches.length == 1) {\n        // Map the touch event's properties to the event.\n        var touchPoint = e.changedTouches[0];\n        e.clientX = touchPoint.clientX;\n        e.clientY = touchPoint.clientY;\n      }\n      func.apply(thisObject, arguments);\n      // Stop the browser from scrolling/zooming the page\n      if (Entry && Entry.type == 'phone') {\n          var scroll = $(window).scrollTop();\n          var element = $(Entry.playground.blocklyView_);\n          var position = element.offset();\n          if (e.clientY > position.top - scroll &&\n             e.clientY < position.top - scroll + element.height() &&\n             e.clientX > position.left &&\n             e.clientX < position.left + element.width())\n            e.preventDefault();\n      } else {\n        e.preventDefault();\n      }\n    };\n    element.addEventListener(Blockly.bindEvent_.TOUCH_MAP[name],\n                             wrapFunc, false);\n    bindData.push([element, Blockly.bindEvent_.TOUCH_MAP[name], wrapFunc]);\n  }\n  return bindData;\n};\n\n/**\n * The TOUCH_MAP lookup dictionary specifies additional touch events to fire,\n * in conjunction with mouse events.\n * @type {Object}\n */\nBlockly.bindEvent_.TOUCH_MAP = {};\nif ('ontouchstart' in document.documentElement) {\n  Blockly.bindEvent_.TOUCH_MAP = {\n    mousedown: 'touchstart',\n    mousemove: 'touchmove',\n    mouseup: 'touchend'\n  };\n}\n\n/**\n * Unbind one or more events event from a function call.\n * @param {!Array.<!Array>} bindData Opaque data from bindEvent_.  This list is\n *     emptied during the course of calling this function.\n * @return {!Function} The function call.\n * @private\n */\nBlockly.unbindEvent_ = function(bindData) {\n  while (bindData.length) {\n    var bindDatum = bindData.pop();\n    var element = bindDatum[0];\n    var name = bindDatum[1];\n    var func = bindDatum[2];\n    element.removeEventListener(name, func, false);\n  }\n  return func;\n};\n\n/**\n * Fire a synthetic event.\n * @param {!Element} element The event's target element.\n * @param {string} eventName Name of event (e.g. 'click').\n */\nBlockly.fireUiEvent = function(element, eventName) {\n  var doc = document;\n  if (doc.createEvent) {\n    // W3\n    var evt = doc.createEvent('UIEvents');\n    evt.initEvent(eventName, true, true);  // event type, bubbling, cancelable\n    element.dispatchEvent(evt);\n  } else if (doc.createEventObject) {\n    // MSIE\n    var evt = doc.createEventObject();\n    element.fireEvent('on' + eventName, evt);\n  } else {\n    throw 'FireEvent: No event creation mechanism.';\n  }\n};\n\n/**\n * Don't do anything for this event, just halt propagation.\n * @param {!Event} e An event.\n */\nBlockly.noEvent = function(e) {\n  // This event has been handled.  No need to bubble up to the document.\n  e.preventDefault();\n  e.stopPropagation();\n};\n\n/**\n * Return the coordinates of the top-left corner of this element relative to\n * its parent.\n * @param {!Element} element Element to find the coordinates of.\n * @return {!Object} Object with .x and .y properties.\n * @private\n */\nBlockly.getRelativeXY_ = function(element) {\n  var xy = {x: 0, y: 0};\n  // First, check for x and y attributes.\n  var x = element.getAttribute('x');\n  if (x) {\n    xy.x = parseInt(x, 10);\n  }\n  var y = element.getAttribute('y');\n  if (y) {\n    xy.y = parseInt(y, 10);\n  }\n  // Second, check for transform=\"translate(...)\" attribute.\n  var transform = element.getAttribute('transform');\n  // Note that Firefox and IE (9,10) return 'translate(12)' instead of\n  // 'translate(12, 0)'.\n  // Note that IE (9,10) returns 'translate(16 8)' instead of\n  // 'translate(16, 8)'.\n  var r = transform &&\n          transform.match(/translate\\(\\s*([-\\d.]+)([ ,]\\s*([-\\d.]+)\\s*\\))?/);\n  if (r) {\n    xy.x += parseInt(r[1], 10);\n    if (r[3]) {\n      xy.y += parseInt(r[3], 10);\n    }\n  }\n  return xy;\n};\n\n/**\n * Return the absolute coordinates of the top-left corner of this element.\n * The origin (0,0) is the top-left corner of the Blockly svg.\n * @param {!Element} element Element to find the coordinates of.\n * @return {!Object} Object with .x and .y properties.\n * @private\n */\nBlockly.getSvgXY_ = function(element, workspace) {\n  var x = 0;\n  var y = 0;\n  if (Blockly.mainWorkspace.blockMenu) {\n    do {\n      // Loop through this block and every parent.\n      var xy = Blockly.getRelativeXY_(element);\n      x += xy.x;\n      y += xy.y;\n      element = element.parentNode;\n    } while (element && (element.tagName.toUpperCase() != 'SVG'));\n  } else {\n    do {\n      // Loop through this block and every parent.\n      var xy = Blockly.getRelativeXY_(element);\n      x += xy.x;\n      y += xy.y;\n      element = element.parentNode;\n    } while (element && (element != Blockly.svg));\n  }\n  return {x: x, y: y};\n};\n\n/**\n * Return the absolute coordinates of the top-left corner of this element.\n * The origin (0,0) is the top-left corner of the page body.\n * @param {!Element} element Element to find the coordinates of.\n * @return {!Object} Object with .x and .y properties.\n * @private\n */\nBlockly.getAbsoluteXY_ = function(element, svg) {\n  var xy = Blockly.getSvgXY_(element);\n  return Blockly.convertCoordinates(xy.x, xy.y, false, svg);\n};\n\n/**\n * Helper method for creating SVG elements.\n * @param {string} name Element's tag name.\n * @param {!Object} attrs Dictionary of attribute names and values.\n * @param {Element=} opt_parent Optional parent on which to append the element.\n * @return {!SVGElement} Newly created SVG element.\n */\nBlockly.createSvgElement = function(name, attrs, opt_parent) {\n  var e = /** @type {!SVGElement} */ (\n      document.createElementNS(Blockly.SVG_NS, name));\n  for (var key in attrs) {\n    e.setAttribute(key, attrs[key]);\n  }\n  // IE defines a unique attribute \"runtimeStyle\", it is NOT applied to\n  // elements created with createElementNS. However, Closure checks for IE\n  // and assumes the presence of the attribute and crashes.\n  if (document.body.runtimeStyle) {  // Indicates presence of IE-only attr.\n    e.runtimeStyle = e.currentStyle = e.style;\n  }\n  if (opt_parent) {\n    opt_parent.appendChild(e);\n  }\n  return e;\n};\n\n/**\n * Is this event a right-click?\n * @param {!Event} e Mouse event.\n * @return {boolean} True if right-click.\n */\nBlockly.isRightButton = function(e) {\n  // Control-clicking in WebKit on Mac OS X fails to change button to 2.\n  return e.button == 2 || e.ctrlKey;\n};\n\n/**\n * Is this event a middle-click?\n * @param {!Event} e Mouse event.\n * @return {boolean} True if middle-click.\n */\nBlockly.isMiddleButton = function(e) {\n  return e.button == 1;\n};\n\n/**\n * Convert between HTML coordinates and SVG coordinates.\n * @param {number} x X input coordinate.\n * @param {number} y Y input coordinate.\n * @param {boolean} toSvg True to convert to SVG coordinates.\n *     False to convert to mouse/HTML coordinates.\n * @param {?Object} svg Origin SVG.\n * @return {!Object} Object with x and y properties in output coordinates.\n */\nBlockly.convertCoordinates = function(x, y, toSvg, svg) {\n  if (toSvg) {\n    x -= window.scrollX || window.pageXOffset;\n    y -= window.scrollY || window.pageYOffset;\n  }\n  var svg = svg ? svg : Blockly.svg;\n  var svgPoint = svg.createSVGPoint();\n  svgPoint.x = x;\n  svgPoint.y = y;\n  var matrix = svg.getScreenCTM();\n  if (toSvg) {\n    matrix = matrix.inverse();\n  }\n  var xy = svgPoint.matrixTransform(matrix);\n  if (!toSvg) {\n    xy.x += window.scrollX || window.pageXOffset;\n    xy.y += window.scrollY || window.pageYOffset;\n  }\n  return xy;\n};\n\n/**\n * Return the converted coordinates of the given mouse event.\n * The origin (0,0) is the top-left corner of the Blockly svg.\n * @param {!Event} e Mouse event.\n * @return {!Object} Object with .x and .y properties.\n */\nBlockly.mouseToSvg = function(e) {\n  var scrollX = window.scrollX || window.pageXOffset;\n  var scrollY = window.scrollY || window.pageYOffset;\n  return Blockly.convertCoordinates(e.clientX + scrollX,\n                                    e.clientY + scrollY, true);\n};\n\n/**\n * Given an array of strings, return the length of the shortest one.\n * @param {!Array.<string>} array Array of strings.\n * @return {number} Length of shortest string.\n */\nBlockly.shortestStringLength = function(array) {\n  if (!array.length) {\n    return 0;\n  }\n  var len = array[0].length;\n  for (var i = 1; i < array.length; i++) {\n    len = Math.min(len, array[i].length);\n  }\n  return len;\n};\n\n/**\n * Given an array of strings, return the length of the common prefix.\n * Words may not be split.  Any space after a word is included in the length.\n * @param {!Array.<string>} array Array of strings.\n * @param {?number} opt_shortest Length of shortest string.\n * @return {number} Length of common prefix.\n */\nBlockly.commonWordPrefix = function(array, opt_shortest) {\n  if (!array.length) {\n    return 0;\n  } else if (array.length == 1) {\n    return array[0].length;\n  }\n  var wordPrefix = 0;\n  var max = opt_shortest || Blockly.shortestStringLength(array);\n  for (var len = 0; len < max; len++) {\n    var letter = array[0][len];\n    for (var i = 1; i < array.length; i++) {\n      if (letter != array[i][len]) {\n        return wordPrefix;\n      }\n    }\n    if (letter == ' ') {\n      wordPrefix = len + 1;\n    }\n  }\n  for (var i = 1; i < array.length; i++) {\n    var letter = array[i][len];\n    if (letter && letter != ' ') {\n      return wordPrefix;\n    }\n  }\n  return max;\n};\n\n/**\n * Given an array of strings, return the length of the common suffix.\n * Words may not be split.  Any space after a word is included in the length.\n * @param {!Array.<string>} array Array of strings.\n * @param {?number} opt_shortest Length of shortest string.\n * @return {number} Length of common suffix.\n */\nBlockly.commonWordSuffix = function(array, opt_shortest) {\n  if (!array.length) {\n    return 0;\n  } else if (array.length == 1) {\n    return array[0].length;\n  }\n  var wordPrefix = 0;\n  var max = opt_shortest || Blockly.shortestStringLength(array);\n  for (var len = 0; len < max; len++) {\n    var letter = array[0].substr(-len - 1, 1);\n    for (var i = 1; i < array.length; i++) {\n      if (letter != array[i].substr(-len - 1, 1)) {\n        return wordPrefix;\n      }\n    }\n    if (letter == ' ') {\n      wordPrefix = len + 1;\n    }\n  }\n  for (var i = 1; i < array.length; i++) {\n    var letter = array[i].charAt(array[i].length - len - 1);\n    if (letter && letter != ' ') {\n      return wordPrefix;\n    }\n  }\n  return max;\n};\n\n/**\n * Is the given string a number (includes negative and decimals).\n * @param {string} str Input string.\n * @return {boolean} True if number, false otherwise.\n */\nBlockly.isNumber = function(str) {\n  return !!str.match(/^\\s*-?\\d+(\\.\\d+)?\\s*$/);\n};\n\n\nBlockly.getComputedTextLength = function(textElement) {\n  var textContent = textElement.innerHTML;\n  var length = Blockly.textLengthCache[textContent];\n  if (length)\n    return length;\n  else {\n    length = textElement.getComputedTextLength();\n    Blockly.textLengthCache[textContent] = length;\n    return length;\n  }\n};\n\nBlockly.isChild = function(parent, child) {\n    if (child != null) {\n        while (child.parentNode) {\n            if ( (child = child.parentNode) == parent)\n                return true;\n        }\n    }\n    return false;\n}\n"
  },
  {
    "path": "extern/blockly/core/variables.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Utility functions for handling variables and procedure names.\n * Note that variables and procedures share the same name space, meaning that\n * one can't have a variable and a procedure of the same name.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Variables');\n\n// TODO(scr): Fix circular dependencies\n// goog.require('Blockly.Block');\ngoog.require('Blockly.Toolbox');\ngoog.require('Blockly.Workspace');\n\n\n/**\n * Category to separate variable names from procedures and generated functions.\n */\nBlockly.Variables.NAME_TYPE = 'VARIABLE';\n\n/**\n * Find all user-created variables.\n * @param {Blockly.Block=} opt_block Optional root block.\n * @return {!Array.<string>} Array of variable names.\n */\nBlockly.Variables.allVariables = function(opt_block) {\n  var blocks;\n  if (opt_block) {\n    blocks = opt_block.getDescendants();\n  } else {\n    blocks = Blockly.mainWorkspace.getAllBlocks();\n  }\n  var variableHash = Object.create(null);\n  // Iterate through every block and add each variable to the hash.\n  for (var x = 0; x < blocks.length; x++) {\n    var func = blocks[x].getVars;\n    if (func) {\n      var blockVariables = func.call(blocks[x]);\n      for (var y = 0; y < blockVariables.length; y++) {\n        var varName = blockVariables[y];\n        // Variable name may be null if the block is only half-built.\n        if (varName) {\n          variableHash[varName.toLowerCase()] = varName;\n        }\n      }\n    }\n  }\n  // Flatten the hash into a list.\n  var variableList = [];\n  for (var name in variableHash) {\n    variableList.push(variableHash[name]);\n  }\n  return variableList;\n};\n\n/**\n * Find all instances of the specified variable and rename them.\n * @param {string} oldName Variable to rename.\n * @param {string} newName New variable name.\n */\nBlockly.Variables.renameVariable = function(oldName, newName) {\n  var blocks = Blockly.mainWorkspace.getAllBlocks();\n  // Iterate through every block.\n  for (var x = 0; x < blocks.length; x++) {\n    var func = blocks[x].renameVar;\n    if (func) {\n      func.call(blocks[x], oldName, newName);\n    }\n  }\n};\n\n/**\n * Construct the blocks required by the flyout for the variable category.\n * @param {!Array.<!Blockly.Block>} blocks List of blocks to show.\n * @param {!Array.<number>} gaps List of widths between blocks.\n * @param {number} margin Standard margin width for calculating gaps.\n * @param {!Blockly.Workspace} workspace The flyout's workspace.\n */\nBlockly.Variables.flyoutCategory = function(blocks, gaps, margin, workspace) {\n  var variableList = Blockly.Variables.allVariables();\n  variableList.sort(goog.string.caseInsensitiveCompare);\n  // In addition to the user's variables, we also want to display the default\n  // variable name at the top.  We also don't want this duplicated if the\n  // user has created a variable of the same name.\n  variableList.unshift(null);\n  var defaultVariable = undefined;\n  for (var i = 0; i < variableList.length; i++) {\n    if (variableList[i] === defaultVariable) {\n      continue;\n    }\n    var getBlock = Blockly.Blocks['variables_get'] ?\n        Blockly.Block.obtain(workspace, 'variables_get') : null;\n    getBlock && getBlock.initSvg();\n    var setBlock = Blockly.Blocks['variables_set'] ?\n        Blockly.Block.obtain(workspace, 'variables_set') : null;\n    setBlock && setBlock.initSvg();\n    if (variableList[i] === null) {\n      defaultVariable = (getBlock || setBlock).getVars()[0];\n    } else {\n      getBlock && getBlock.setFieldValue(variableList[i], 'VAR');\n      setBlock && setBlock.setFieldValue(variableList[i], 'VAR');\n    }\n    setBlock && blocks.push(setBlock);\n    getBlock && blocks.push(getBlock);\n    if (getBlock && setBlock) {\n      gaps.push(margin, margin * 3);\n    } else {\n      gaps.push(margin * 2);\n    }\n  }\n};\n\n/**\n* Return a new variable name that is not yet being used. This will try to\n* generate single letter variable names in the range 'i' to 'z' to start with.\n* If no unique name is located it will try 'i1' to 'z1', then 'i2' to 'z2' etc.\n* @return {string} New variable name.\n*/\nBlockly.Variables.generateUniqueName = function() {\n  var variableList = Blockly.Variables.allVariables();\n  var newName = '';\n  if (variableList.length) {\n    variableList.sort(goog.string.caseInsensitiveCompare);\n    var nameSuffix = 0, potName = 'i', i = 0, inUse = false;\n    while (!newName) {\n      i = 0;\n      inUse = false;\n      while (i < variableList.length && !inUse) {\n        if (variableList[i].toLowerCase() == potName) {\n          // This potential name is already used.\n          inUse = true;\n        }\n        i++;\n      }\n      if (inUse) {\n        // Try the next potential name.\n        if (potName[0] === 'z') {\n          // Reached the end of the character sequence so back to 'a' but with\n          // a new suffix.\n          nameSuffix++;\n          potName = 'a';\n        } else {\n          potName = String.fromCharCode(potName.charCodeAt(0) + 1);\n          if (potName[0] == 'l') {\n            // Avoid using variable 'l' because of ambiguity with '1'.\n            potName = String.fromCharCode(potName.charCodeAt(0) + 1);\n          }\n        }\n        if (nameSuffix > 0) {\n          potName += nameSuffix;\n        }\n      } else {\n        // We can use the current potential name.\n        newName = potName;\n      }\n    }\n  } else {\n    newName = 'i';\n  }\n  return newName;\n};\n"
  },
  {
    "path": "extern/blockly/core/warning.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing a warning.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Warning');\n\ngoog.require('Blockly.Bubble');\ngoog.require('Blockly.Icon');\n\n\n/**\n * Class for a warning.\n * @param {!Blockly.Block} block The block associated with this warning.\n * @extends {Blockly.Icon}\n * @constructor\n */\nBlockly.Warning = function(block) {\n  Blockly.Warning.superClass_.constructor.call(this, block);\n  this.createIcon_();\n};\ngoog.inherits(Blockly.Warning, Blockly.Icon);\n\n/**\n * Warning text (if bubble is not visible).\n * @private\n */\nBlockly.Warning.prototype.text_ = '';\n\n/**\n * Create the icon on the block.\n * @private\n */\nBlockly.Warning.prototype.createIcon_ = function() {\n  Blockly.Icon.prototype.createIcon_.call(this);\n  /* Here's the markup that will be generated:\n  <path class=\"blocklyIconShield\" d=\"...\"/>\n  <text class=\"blocklyIconMark\" x=\"8\" y=\"13\">!</text>\n  */\n  var iconShield = Blockly.createSvgElement('path',\n      {'class': 'blocklyIconShield',\n       'd': 'M 2,15 Q -1,15 0.5,12 L 6.5,1.7 Q 8,-1 9.5,1.7 L 15.5,12 ' +\n       'Q 17,15 14,15 z'},\n      this.iconGroup_);\n  this.iconMark_ = Blockly.createSvgElement('text',\n      {'class': 'blocklyIconMark',\n       'x': Blockly.Icon.RADIUS,\n       'y': 2 * Blockly.Icon.RADIUS - 3}, this.iconGroup_);\n  this.iconMark_.appendChild(document.createTextNode('!'));\n};\n\n/**\n * Create the text for the warning's bubble.\n * @param {string} text The text to display.\n * @return {!SVGTextElement} The top-level node of the text.\n * @private\n */\nBlockly.Warning.prototype.textToDom_ = function(text) {\n  var paragraph = /** @type {!SVGTextElement} */ (\n      Blockly.createSvgElement(\n          'text', {'class': 'blocklyText', 'y': Blockly.Bubble.BORDER_WIDTH},\n          null));\n  var lines = text.split('\\n');\n  for (var i = 0; i < lines.length; i++) {\n    var tspanElement = Blockly.createSvgElement('tspan',\n        {'dy': '1em', 'x': Blockly.Bubble.BORDER_WIDTH}, paragraph);\n    var textNode = document.createTextNode(lines[i]);\n    tspanElement.appendChild(textNode);\n  }\n  return paragraph;\n};\n\n/**\n * Show or hide the warning bubble.\n * @param {boolean} visible True if the bubble should be visible.\n */\nBlockly.Warning.prototype.setVisible = function(visible) {\n  if (visible == this.isVisible()) {\n    // No change.\n    return;\n  }\n  if (visible) {\n    // Create the bubble.\n    var paragraph = this.textToDom_(this.text_);\n    this.bubble_ = new Blockly.Bubble(\n        /** @type {!Blockly.Workspace} */ (this.block_.workspace),\n        paragraph, this.block_.svg_.svgGroup_,\n        this.iconX_, this.iconY_, null, null);\n    if (Blockly.RTL) {\n      // Right-align the paragraph.\n      // This cannot be done until the bubble is rendered on screen.\n      var maxWidth = paragraph.getBBox().width;\n      for (var x = 0, textElement; textElement = paragraph.childNodes[x]; x++) {\n        textElement.setAttribute('text-anchor', 'end');\n        textElement.setAttribute('x', maxWidth + Blockly.Bubble.BORDER_WIDTH);\n      }\n    }\n    this.updateColour();\n    // Bump the warning into the right location.\n    var size = this.bubble_.getBubbleSize();\n    this.bubble_.setBubbleSize(size.width, size.height);\n  } else {\n    // Dispose of the bubble.\n    this.bubble_.dispose();\n    this.bubble_ = null;\n    this.body_ = null;\n    this.foreignObject_ = null;\n  }\n};\n\n/**\n * Bring the warning to the top of the stack when clicked on.\n * @param {!Event} e Mouse up event.\n * @private\n */\nBlockly.Warning.prototype.bodyFocus_ = function(e) {\n  this.bubble_.promote_();\n};\n\n/**\n * Set this warning's text.\n * @param {string} text Warning text.\n */\nBlockly.Warning.prototype.setText = function(text) {\n  this.text_ = text;\n  if (this.isVisible()) {\n    this.setVisible(false);\n    this.setVisible(true);\n  }\n};\n\n/**\n * Dispose of this warning.\n */\nBlockly.Warning.prototype.dispose = function() {\n  this.block_.warning = null;\n  Blockly.Icon.prototype.dispose.call(this);\n};\n"
  },
  {
    "path": "extern/blockly/core/widgetdiv.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2013 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview A div that floats on top of Blockly.  This singleton contains\n *     temporary HTML UI widgets that the user is currently interacting with.\n *     E.g. text input areas, colour pickers.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.WidgetDiv');\n\ngoog.require('Blockly.Css');\ngoog.require('goog.dom');\n\n\n/**\n * The HTML container.  Set once by inject.js's Blockly.createDom_.\n * @type Element\n */\nBlockly.WidgetDiv.DIV = null;\n\n/**\n * The field currently using this container.\n * @private\n * @type Blockly.Field\n */\nBlockly.WidgetDiv.field_ = null;\n\n/**\n * Optional cleanup function set by whichever field uses the widget.\n * @private\n * @type Function\n */\nBlockly.WidgetDiv.dispose_ = null;\n\n/**\n * Initialize and display the widget div.  Close the old one if needed.\n * @param {!Blockly.Field} newField The field that will be using this container.\n * @param {Function} dispose Optional cleanup function to be run when the widget\n *   is closed.\n */\nBlockly.WidgetDiv.show = function(newField, dispose) {\n  if (typeof(Entry) == \"object\")\n    Entry.dispatchEvent(\"entryBlocklyChanged\");\n  Blockly.WidgetDiv.hide();\n  Blockly.WidgetDiv.field_ = newField;\n  Blockly.WidgetDiv.dispose_ = dispose;\n  Blockly.WidgetDiv.initialValue = Blockly.WidgetDiv.field_.text_;\n  Blockly.WidgetDiv.DIV.style.display = 'block';\n};\n\n/**\n * Destroy the widget and hide the div.\n */\nBlockly.WidgetDiv.hide = function() {\n  if (Blockly.WidgetDiv.field_) {\n    if (typeof(Entry) == \"object\" &&\n        Blockly.WidgetDiv.initialValue != Blockly.WidgetDiv.field_.text_) {\n      Entry.dispatchEvent(\"cancelLastCommand\");\n    }\n    Blockly.WidgetDiv.DIV.style.display = 'none';\n    Blockly.WidgetDiv.dispose_ && Blockly.WidgetDiv.dispose_();\n    Blockly.WidgetDiv.field_ = null;\n    Blockly.WidgetDiv.dispose_ = null;\n    goog.dom.removeChildren(Blockly.WidgetDiv.DIV);\n  }\n};\n\n/**\n * Destroy the widget and hide the div if it is being used by the specified\n *   field.\n * @param {!Blockly.Field} oldField The field that was using this container.\n */\nBlockly.WidgetDiv.hideIfField = function(oldField) {\n  if (Blockly.WidgetDiv.field_ == oldField) {\n    Blockly.WidgetDiv.hide();\n  }\n};\n"
  },
  {
    "path": "extern/blockly/core/workspace.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Object representing a workspace.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Workspace');\n\n// TODO(scr): Fix circular dependencies\n// goog.require('Blockly.Block');\ngoog.require('Blockly.ScrollbarPair');\ngoog.require('Blockly.Trashcan');\ngoog.require('Blockly.Xml');\n\n\n/**\n * Class for a workspace.\n * @param {Function} getMetrics A function that returns size/scrolling metrics.\n * @param {Function} setMetrics A function that sets size/scrolling metrics.\n * @constructor\n */\nBlockly.Workspace = function(getMetrics, setMetrics) {\n  if (!getMetrics) {\n    this.getMetrics = Blockly.getGenralWorkspaceMetricsFunc_(this);\n    this.setMetrics = Blockly.setGeneralWorkspaceMetricsFunc_(this);\n  } else {\n    this.getMetrics = getMetrics;\n    this.setMetrics = setMetrics;\n  }\n\n  /** @type {boolean} */\n  this.isFlyout = false;\n  /**\n   * @type {!Array.<!Blockly.Block>}\n   * @private\n   */\n  this.topBlocks_ = [];\n\n  /** @type {number} */\n  this.maxBlocks = Infinity;\n\n  Blockly.ConnectionDB.init(this);\n};\n\n/**\n * Angle away from the horizontal to sweep for blocks.  Order of execution is\n * generally top to bottom, but a small angle changes the scan to give a bit of\n * a left to right bias (reversed in RTL).  Units are in degrees.\n * See: http://tvtropes.org/pmwiki/pmwiki.php/Main/DiagonalBilling.\n */\nBlockly.Workspace.SCAN_ANGLE = 3;\n\n/**\n * Can this workspace be dragged around (true) or is it fixed (false)?\n * @type {boolean}\n */\nBlockly.Workspace.prototype.dragMode = false;\n\n/**\n * Current horizontal scrolling offset.\n * @type {number}\n */\nBlockly.Workspace.prototype.scrollX = 0;\n\n/**\n * Current vertical scrolling offset.\n * @type {number}\n */\nBlockly.Workspace.prototype.scrollY = 0;\n\n/**\n * The workspace's trashcan (if any).\n * @type {Blockly.Trashcan}\n */\nBlockly.Workspace.prototype.trashcan = null;\n\n/**\n * PID of upcoming firing of a change event.  Used to fire only one event\n * after multiple changes.\n * @type {?number}\n * @private\n */\nBlockly.Workspace.prototype.fireChangeEventPid_ = null;\n\n/**\n * This workspace's scrollbars, if they exist.\n * @type {Blockly.ScrollbarPair}\n */\nBlockly.Workspace.prototype.scrollbar = null;\n\n/**\n * Create the trash can elements.\n * @return {!Element} The workspace's SVG group.\n */\nBlockly.Workspace.prototype.createDom = function() {\n  /*\n  <g>\n    [Trashcan may go here]\n    <g></g>\n    <g></g>\n  </g>\n  */\n  this.svgGroup_ = Blockly.createSvgElement('g', {}, null);\n  this.svgBlockCanvas_ = Blockly.createSvgElement('g', {}, this.svgGroup_);\n  this.svgBubbleCanvas_ = Blockly.createSvgElement('g', {}, this.svgGroup_);\n  this.fireChangeEvent();\n  return this.svgGroup_;\n};\n\n/**\n * Dispose of this workspace.\n * Unlink from all DOM elements to prevent memory leaks.\n */\nBlockly.Workspace.prototype.dispose = function() {\n  if (this.svgGroup_) {\n    goog.dom.removeNode(this.svgGroup_);\n    this.svgGroup_ = null;\n  }\n  this.svgBlockCanvas_ = null;\n  this.svgBubbleCanvas_ = null;\n  if (this.trashcan) {\n    this.trashcan.dispose();\n    this.trashcan = null;\n  }\n};\n\n/**\n * Add a trashcan.\n */\nBlockly.Workspace.prototype.addTrashcan = function() {\n  if (Blockly.hasTrashcan && !Blockly.readOnly) {\n    this.trashcan = new Blockly.Trashcan(this);\n    var svgTrashcan = this.trashcan.createDom();\n    this.svgGroup_.insertBefore(svgTrashcan, this.svgBlockCanvas_);\n    this.trashcan.init();\n  }\n};\n\n/**\n * Add a connection animation.\n */\nBlockly.Workspace.prototype.addConnectionAnimation = function() {\n    this.connectionAnimation = new Blockly.ConnectionAnimation();\n    var svgConnectionAnimation = this.connectionAnimation.createDom();\n    this.svgGroup_.insertBefore(svgConnectionAnimation, this.svgBlockCanvas_);\n    this.connectionAnimation.init();\n};\n\n/**\n * Get the SVG element that forms the drawing surface.\n * @return {!Element} SVG element.\n */\nBlockly.Workspace.prototype.getCanvas = function() {\n  return this.svgBlockCanvas_;\n};\n\n/**\n * Get the SVG element that forms the bubble surface.\n * @return {!SVGGElement} SVG element.\n */\nBlockly.Workspace.prototype.getBubbleCanvas = function() {\n  return this.svgBubbleCanvas_;\n};\n\n/**\n * Add a block to the list of top blocks.\n * @param {!Blockly.Block} block Block to remove.\n */\nBlockly.Workspace.prototype.addTopBlock = function(block) {\n  this.topBlocks_.push(block);\n  if (Blockly.Realtime.isEnabled() && this == Blockly.mainWorkspace) {\n    Blockly.Realtime.addTopBlock(block);\n  }\n  this.fireChangeEvent();\n};\n\n/**\n * Remove a block from the list of top blocks.\n * @param {!Blockly.Block} block Block to remove.\n */\nBlockly.Workspace.prototype.removeTopBlock = function(block) {\n  var found = false;\n  for (var child, x = 0; child = this.topBlocks_[x]; x++) {\n    if (child == block) {\n      this.topBlocks_.splice(x, 1);\n      found = true;\n      break;\n    }\n  }\n  if (!found) {\n    throw 'Block not present in workspace\\'s list of top-most blocks.';\n  }\n  if (Blockly.Realtime.isEnabled() && this == Blockly.mainWorkspace) {\n    Blockly.Realtime.removeTopBlock(block);\n  }\n  this.fireChangeEvent();\n};\n\n/**\n * Finds the top-level blocks and returns them.  Blocks are optionally sorted\n * by position; top to bottom (with slight LTR or RTL bias).\n * @param {boolean} ordered Sort the list if true.\n * @return {!Array.<!Blockly.Block>} The top-level block objects.\n */\nBlockly.Workspace.prototype.getTopBlocks = function(ordered) {\n  // Copy the topBlocks_ list.\n  var blocks = [].concat(this.topBlocks_);\n  if (ordered && blocks.length > 1) {\n    var offset = Math.sin(Blockly.Workspace.SCAN_ANGLE / 180 * Math.PI);\n    if (Blockly.LTR) {\n      offset *= -1;\n    }\n    blocks.sort(function(a, b) {\n      var aXY = a.getRelativeToSurfaceXY();\n      var bXY = b.getRelativeToSurfaceXY();\n      return (aXY.y + offset * aXY.x) - (bXY.y + offset * bXY.x);\n    });\n  }\n  return blocks;\n};\n\n/**\n * Find all blocks in workspace.  No particular order.\n * @return {!Array.<!Blockly.Block>} Array of blocks.\n */\nBlockly.Workspace.prototype.getAllBlocks = function() {\n  var blocks = this.getTopBlocks(false);\n  for (var x = 0; x < blocks.length; x++) {\n    blocks = blocks.concat(blocks[x].getChildren());\n  }\n  return blocks;\n};\n\n/**\n * Dispose of all blocks in workspace.\n */\nBlockly.Workspace.prototype.clear = function() {\n  Blockly.hideChaff();\n  while (this.topBlocks_.length) {\n    this.topBlocks_[0].dispose();\n  }\n};\n\n/**\n * Render all blocks in workspace.\n */\nBlockly.Workspace.prototype.render = function() {\n  var renderList = this.getAllBlocks();\n  for (var x = 0, block; block = renderList[x]; x++) {\n    if (!block.getChildren().length) {\n      block.render();\n    }\n  }\n};\n\n/**\n * Finds the block with the specified ID in this workspace.\n * @param {string} id ID of block to find.\n * @return {Blockly.Block} The matching block, or null if not found.\n */\nBlockly.Workspace.prototype.getBlockById = function(id) {\n  // If this O(n) function fails to scale well, maintain a hash table of IDs.\n  var blocks = this.getAllBlocks();\n  for (var x = 0, block; block = blocks[x]; x++) {\n    if (block.id == id) {\n      return block;\n    }\n  }\n  return null;\n};\n\n/**\n * Finds the block with the specified previous ID in this workspace.\n * @param {string} previous id ID of block to find.\n * @return {Blockly.Block} The matching block, or null if not found.\n */\nBlockly.Workspace.prototype.getBlockByPreviousId = function(previousId) {\n  // If this O(n) function fails to scale well, maintain a hash table of IDs.\n  var blocks = this.getAllBlocks();\n  for (var x = 0, block; block = blocks[x]; x++) {\n    if (block.previousId == previousId) {\n      return block;\n    }\n  }\n  return null;\n};\n\n\nBlockly.Workspace.prototype.getBlockByIdWithDeactivate = function(id) {\n  // If this O(n) function fails to scale well, maintain a hash table of IDs.\n  var blocks = this.getAllBlocks();\n  for (var x = 0, block; block = blocks[x]; x++) {\n    block.svg_.removeActive();\n    if (block.id == id) {\n      return block;\n    }\n  }\n  return null;\n};\n\nBlockly.Workspace.prototype.setAllBlockDisable = function() {\n  // If this O(n) function fails to scale well, maintain a hash table of IDs.\n  var blocks = this.getAllBlocks();\n  for (var x = 0, block; block = blocks[x]; x++) {\n    block.setDisabled(true);\n  }\n  return null;\n};\n\nBlockly.Workspace.prototype.setAllBlockAble = function() {\n  // If this O(n) function fails to scale well, maintain a hash table of IDs.\n  var blocks = this.getAllBlocks();\n  for (var x = 0, block; block = blocks[x]; x++) {\n    block.setDisabled(false);\n  }\n  return null;\n};\n\n/**\n * Turn the visual trace functionality on or off.\n * @param {boolean} armed True if the trace should be on.\n */\nBlockly.Workspace.prototype.traceOn = function(armed) {\n  this.traceOn_ = armed;\n  if (this.traceWrapper_) {\n    Blockly.unbindEvent_(this.traceWrapper_);\n    this.traceWrapper_ = null;\n  }\n  if (armed) {\n    this.traceWrapper_ = Blockly.bindEvent_(this.svgBlockCanvas_,\n        'blocklySelectChange', this, function() {this.traceOn_ = false});\n  }\n};\n\n/**\n * Activate a block in the workspace.\n * @param {?string} id ID of block to find.\n */\nBlockly.Workspace.prototype.activateBlock = function(id) {\n  this.traceOn(true);\n  var block = null;\n  if (id) {\n    block = this.getBlockById(id);\n    if (!block) {\n      return;\n    }\n  }\n  // Temporary turn off the listener for selection changes, so that we don't\n  // trip the monitor for detecting user activity.\n  this.traceOn(false);\n  // Select the current block.\n  if (block) {\n    block.activate();\n  } else if (Blockly.selected) {\n    Blockly.selected.unselect();\n  }\n  this.traceOn(true);\n};\n\n/**\n * Activate a block in the workspace.\n * @param {?string} id ID of block to find.\n */\nBlockly.Workspace.prototype.activatePreviousBlock = function(id) {\n  this.traceOn(true);\n  var block = null;\n  if (id) {\n    block = this.getBlockByPreviousId(id);\n    if (!block) {\n      return;\n    }\n  }\n  // Temporary turn off the listener for selection changes, so that we don't\n  // trip the monitor for detecting user activity.\n  this.traceOn(false);\n  // Select the current block.\n  if (block) {\n    block.activate();\n  } else if (Blockly.selected) {\n    Blockly.selected.unselect();\n  }\n  this.traceOn(true);\n};\n\n/**\n * Highlight a block in the workspace.\n * @param {?string} id ID of block to find.\n */\nBlockly.Workspace.prototype.highlightBlock = function(id) {\n  if (!this.traceOn_) {\n    return;\n  }\n  var block = null;\n  if (id) {\n    block = this.getBlockById(id);\n    if (!block) {\n      return;\n    }\n  }\n  // Temporary turn off the listener for selection changes, so that we don't\n  // trip the monitor for detecting user activity.\n  this.traceOn(false);\n  // Select the current block.\n  if (block) {\n    block.select();\n  } else if (Blockly.selected) {\n    Blockly.selected.unselect();\n  }\n  // Restore the monitor for user activity.\n  this.traceOn(true);\n};\n\n/**\n * Fire a change event for this workspace.  Changes include new block, dropdown\n * edits, mutations, connections, etc.  Groups of simultaneous changes (e.g.\n * a tree of blocks being deleted) are merged into one event.\n * Applications may hook workspace changes by listening for\n * 'blocklyWorkspaceChange' on Blockly.mainWorkspace.getCanvas().\n */\nBlockly.Workspace.prototype.fireChangeEvent = function() {\n  if (this.fireChangeEventPid_) {\n    window.clearTimeout(this.fireChangeEventPid_);\n  }\n  var canvas = this.svgBlockCanvas_;\n  if (canvas) {\n    this.fireChangeEventPid_ = window.setTimeout(function() {\n        Blockly.fireUiEvent(canvas, 'blocklyWorkspaceChange');\n      }, 0);\n  }\n};\n\n/**\n * Paste the provided block onto the workspace.\n * @param {!Element} xmlBlock XML block element.\n */\nBlockly.Workspace.prototype.paste = function(xmlBlock) {\n  if (xmlBlock.getElementsByTagName('block').length >=\n      this.remainingCapacity()) {\n    return;\n  }\n\n  if (typeof(Entry) === \"object\") {\n      xmlBlock = Entry.changeXmlHashId(xmlBlock);\n  } else if (typeof(Ntry) === \"object\") {\n      xmlBlock = Ntry.changeXmlHashId(xmlBlock);\n  }\n\n  var block = Blockly.Xml.domToBlock(this, xmlBlock);\n  // Move the duplicate to original position.\n  var blockX = parseInt(xmlBlock.getAttribute('x'), 10);\n  var blockY = parseInt(xmlBlock.getAttribute('y'), 10);\n  if (!isNaN(blockX) && !isNaN(blockY)) {\n    if (Blockly.RTL) {\n      blockX = -blockX;\n    }\n    // // Offset block until not clobbering another block.\n    do {\n      var collide = false;\n      var allBlocks = this.getAllBlocks();\n      for (var x = 0, otherBlock; otherBlock = allBlocks[x]; x++) {\n        var otherXY = otherBlock.getRelativeToSurfaceXY();\n        if (Math.abs(blockX - otherXY.x) <= 1 &&\n            Math.abs(blockY - otherXY.y) <= 1) {\n          if (Blockly.RTL) {\n            blockX -= Blockly.SNAP_RADIUS;\n          } else {\n            blockX += Blockly.SNAP_RADIUS;\n          }\n          blockY += Blockly.SNAP_RADIUS * 2;\n          collide = true;\n        }\n      }\n    } while (collide);\n    block.moveBy(blockX, blockY);\n  }\n  block.select();\n  if (xmlBlock.getAttribute('isForFunc')) {\n    Entry.Func.positionBlock_(block);\n    xmlBlock.removeAttribute('isForFunc');\n  }\n};\n\n/**\n * The number of blocks that may be added to the workspace before reaching\n *     the maxBlocks.\n * @return {number} Number of blocks left.\n */\nBlockly.Workspace.prototype.remainingCapacity = function() {\n  if (this.maxBlocks == Infinity) {\n    return Infinity;\n  }\n  return this.maxBlocks - this.getAllBlocks().length;\n};\n\nBlockly.Workspace.prototype.organizeBlocks = function() {\n    var metrics = this.getMetrics();\n    if (!metrics)\n        return;\n    var verticalGap = 20;\n    var targetLeftPosition;\n    if (Blockly.hasBlockMenu)\n        targetLeftPosition = Math.round(metrics.viewLeft + 35);\n    else {\n        var flyoutWidth = Blockly.mainWorkspace.flyout_.svgGroup_.getBBox().width;\n        targetLeftPosition = Math.round(metrics.viewLeft + 30 + flyoutWidth);\n    }\n\n\n    var acculmulatedTop = 0;\n    var columWidth = 0;\n    var limitTopPosition = metrics.viewTop + metrics.viewHeight - 30;\n\n    var topBlocks = this.getTopBlocks();\n    for (var i in topBlocks) {\n        var block = topBlocks[i];\n        var heightWidth = block.getHeightWidth();\n        var targetTopPosition = acculmulatedTop + metrics.viewTop + verticalGap;\n        if (targetTopPosition > limitTopPosition) {\n            targetLeftPosition = targetLeftPosition + columWidth + 10;\n            columWidth = 0;\n            acculmulatedTop = 0;\n        }\n        columWidth = Math.max(columWidth, heightWidth.width);\n        targetTopPosition = acculmulatedTop + metrics.viewTop + verticalGap;\n        topBlocks[i].svg_.getRootElement().setAttribute('transform', 'translate('\n            + targetLeftPosition + ','\n            + targetTopPosition + ')');\n        acculmulatedTop = acculmulatedTop + heightWidth.height + verticalGap;\n    }\n\n    var xmls = Blockly.Xml.workspaceToDom(this);\n    this.clear();\n    Blockly.Xml.domToWorkspace(this, xmls);\n};\n\n// Export symbols that would otherwise be renamed by Closure compiler.\nBlockly.Workspace.prototype['clear'] = Blockly.Workspace.prototype.clear;\n"
  },
  {
    "path": "extern/blockly/core/xml.js",
    "content": "/**\n * @license\n * Visual Blocks Editor\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview XML reader and writer.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Xml');\n\n// TODO(scr): Fix circular dependencies\n// goog.require('Blockly.Block');\n\n\n/**\n * Encode a block tree as XML.\n * @param {!Object} workspace The SVG workspace.\n * @return {!Element} XML document.\n */\nBlockly.Xml.workspaceToDom = function(workspace) {\n  var width = Blockly.svgSize().width;\n  var xml = goog.dom.createDom('xml');\n  var blocks = workspace.getTopBlocks(true);\n  for (var i = 0, block; block = blocks[i]; i++) {\n    var element = Blockly.Xml.blockToDom_(block);\n    var xy = block.getRelativeToSurfaceXY();\n    element.setAttribute('x', Blockly.RTL ? width - xy.x : xy.x);\n    element.setAttribute('y', xy.y);\n    xml.appendChild(element);\n  }\n  return xml;\n};\n\n/**\n * Encode a block subtree as XML.\n * @param {!Blockly.Block} block The root block to encode.\n * @return {!Element} Tree of XML elements.\n * @private\n */\nBlockly.Xml.blockToDom_ = function(block) {\n  var element = goog.dom.createDom('block');\n  element.setAttribute('type', block.type);\n  if (block.outputConnection)\n    element.setAttribute('class', \"output \" + block.type);\n  else\n    element.setAttribute('class', \"inline \" + block.type);\n  element.setAttribute('id', block.id);\n  if (block.mutationToDom) {\n    // Custom data for an advanced block.\n    var mutation = block.mutationToDom();\n    if (mutation) {\n      element.appendChild(mutation);\n    }\n  }\n  function fieldToDom(field) {\n    if (field.name && field.EDITABLE) {\n      var container = goog.dom.createDom('field', null, field.getValue());\n      container.setAttribute('name', field.name);\n      element.appendChild(container);\n    }\n  }\n  for (var x = 0, input; input = block.inputList[x]; x++) {\n    for (var y = 0, field; field = input.fieldRow[y]; y++) {\n      fieldToDom(field);\n    }\n  }\n\n  if (block.comment) {\n    var commentElement = goog.dom.createDom('comment', null,\n        block.comment.getText());\n    commentElement.setAttribute('pinned', block.comment.isVisible());\n    var hw = block.comment.getBubbleSize();\n    commentElement.setAttribute('h', hw.height);\n    commentElement.setAttribute('w', hw.width);\n    element.appendChild(commentElement);\n  }\n\n  var hasValues = false;\n  for (var i = 0, input; input = block.inputList[i]; i++) {\n    var container;\n    var empty = true;\n    if (input.type == Blockly.DUMMY_INPUT) {\n      continue;\n    } else {\n      var childBlock = input.connection.targetBlock();\n      if (input.type == Blockly.INPUT_VALUE) {\n        container = goog.dom.createDom('value');\n        hasValues = true;\n      } else if (input.type == Blockly.NEXT_STATEMENT) {\n        container = goog.dom.createDom('statement');\n      }\n      if (childBlock) {\n        container.appendChild(Blockly.Xml.blockToDom_(childBlock));\n        empty = false;\n      }\n    }\n    container.setAttribute('name', input.name);\n    if (!empty) {\n      element.appendChild(container);\n    }\n  }\n  if (hasValues) {\n    element.setAttribute('inline', block.inputsInline);\n  }\n  if (block.isCollapsed()) {\n    element.setAttribute('collapsed', true);\n  }\n  if (block.disabled) {\n    element.setAttribute('disabled', true);\n  }\n  if (!block.isDeletable()) {\n    element.setAttribute('deletable', false);\n  }\n  if (!block.isMovable()) {\n    element.setAttribute('movable', false);\n  }\n  if (!block.isAddable()) {\n    element.setAttribute('addable', false);\n  }\n  if (!block.isEditable()) {\n    element.setAttribute('editable', false);\n  }\n\n  if (block.nextConnection) {\n    var nextBlock = block.nextConnection.targetBlock();\n    if (nextBlock) {\n      var container = goog.dom.createDom('next', null,\n          Blockly.Xml.blockToDom_(nextBlock));\n      element.appendChild(container);\n    }\n  }\n\n  return element;\n};\n\n/**\n * Converts a DOM structure into plain text.\n * Currently the text format is fairly ugly: all one line with no whitespace.\n * @param {!Element} dom A tree of XML elements.\n * @return {string} Text representation.\n */\nBlockly.Xml.domToText = function(dom) {\n  var oSerializer = new XMLSerializer();\n  return oSerializer.serializeToString(dom);\n};\n\n/**\n * Converts a DOM structure into properly indented text.\n * @param {!Element} dom A tree of XML elements.\n * @return {string} Text representation.\n */\nBlockly.Xml.domToPrettyText = function(dom) {\n  // This function is not guaranteed to be correct for all XML.\n  // But it handles the XML that Blockly generates.\n  var blob = Blockly.Xml.domToText(dom);\n  // Place every open and close tag on its own line.\n  var lines = blob.split('<');\n  // Indent every line.\n  var indent = '';\n  for (var x = 1; x < lines.length; x++) {\n    var line = lines[x];\n    if (line[0] == '/') {\n      indent = indent.substring(2);\n    }\n    lines[x] = indent + '<' + line;\n    if (line[0] != '/' && line.slice(-2) != '/>') {\n      indent += '  ';\n    }\n  }\n  // Pull simple tags back together.\n  // E.g. <foo></foo>\n  var text = lines.join('\\n');\n  text = text.replace(/(<(\\w+)\\b[^>]*>[^\\n]*)\\n *<\\/\\2>/g, '$1</$2>');\n  // Trim leading blank line.\n  return text.replace(/^\\n/, '');\n};\n\n/**\n * Converts plain text into a DOM structure.\n * Throws an error if XML doesn't parse.\n * @param {string} text Text representation.\n * @return {!Element} A tree of XML elements.\n */\nBlockly.Xml.textToDom = function(text) {\n  var oParser = new DOMParser();\n  var dom = oParser.parseFromString(text, 'text/xml');\n  // The DOM should have one and only one top-level node, an XML tag.\n  if (!dom || !dom.firstChild ||\n      dom.firstChild.nodeName.toLowerCase() != 'xml' ||\n      dom.firstChild !== dom.lastChild) {\n    // Whatever we got back from the parser is not XML.\n    throw 'Blockly.Xml.textToDom did not obtain a valid XML tree.';\n  }\n  return dom.firstChild;\n};\n\n/**\n * Decode an XML DOM and create blocks on the workspace.\n * @param {!Blockly.Workspace} workspace The SVG workspace.\n * @param {!Element} xml XML DOM.\n */\nBlockly.Xml.domToWorkspace = function(workspace, xml) {\n  var width = Blockly.svgSize().width;\n  for (var x = 0, xmlChild; xmlChild = xml.childNodes[x]; x++) {\n    if (xmlChild.nodeName.toLowerCase() == 'block') {\n      var block = Blockly.Xml.domToBlock(workspace, xmlChild);\n      var blockX = parseInt(xmlChild.getAttribute('x'), 10);\n      var blockY = parseInt(xmlChild.getAttribute('y'), 10);\n      if (!isNaN(blockX) && !isNaN(blockY)) {\n        block.moveBy(Blockly.RTL ? width - blockX : blockX, blockY);\n      }\n    }\n  }\n  Blockly.svgResize();\n};\n\n/**\n * Decode an XML block tag and create a block (and possibly sub blocks) on the\n * workspace.\n * @param {!Blockly.Workspace} workspace The workspace.\n * @param {!Element} xmlBlock XML block element.\n * @param {boolean=} opt_reuseBlock Optional arg indicating whether to\n *     reinitialize an existing block.\n * @return {!Blockly.Block} The root block created.\n * @private\n */\nBlockly.Xml.domToBlock = function(workspace, xmlBlock, opt_reuseBlock) {\n  var block = null;\n  var prototypeName = xmlBlock.getAttribute('type');\n  if (!prototypeName) {\n    throw 'Block type unspecified: \\n' + xmlBlock.outerHTML;\n  }\n  var id = xmlBlock.getAttribute('id');\n  if (opt_reuseBlock && id) {\n    block = Blockly.Block.getById(id, workspace);\n    // TODO: The following is for debugging.  It should never actually happen.\n    if (!block) {\n      throw 'Couldn\\'t get Block with id: ' + id;\n    }\n    var parentBlock = block.getParent();\n    // If we've already filled this block then we will dispose of it and then\n    // re-fill it.\n    if (block.workspace) {\n      block.dispose(true, false, true);\n    }\n    block.fill(workspace, prototypeName);\n    block.parent_ = parentBlock;\n  } else {\n    block = Blockly.Block.obtain(workspace, prototypeName);\n//    if (id) {\n//      block.id = parseInt(id, 10);\n//    }\n  }\n  block.previousId = xmlBlock.getAttribute('id');\n  if (!block.svg_) {\n    block.initSvg();\n  }\n\n  var inline = xmlBlock.getAttribute('inline');\n  if (inline) {\n    block.setInputsInline(inline == 'true');\n  }\n  var disabled = xmlBlock.getAttribute('disabled');\n  if (disabled) {\n    block.setDisabled(disabled == 'true');\n  }\n  var deletable = xmlBlock.getAttribute('deletable');\n  if (deletable) {\n    block.setDeletable(deletable == 'true');\n  }\n  var movable = xmlBlock.getAttribute('movable');\n  if (movable) {\n    block.setMovable(movable == 'true');\n  }\n  var addable = xmlBlock.getAttribute('addable');\n  if (addable) {\n    block.setAddable(addable == 'true');\n  }\n  var editable = xmlBlock.getAttribute('editable');\n  if (editable) {\n    block.setEditable(editable == 'true');\n  }\n\n  var blockChild = null;\n  for (var x = 0, xmlChild; xmlChild = xmlBlock.childNodes[x]; x++) {\n    if (xmlChild.nodeType == 3 && xmlChild.data.match(/^\\s*$/)) {\n      // Extra whitespace between tags does not concern us.\n      continue;\n    }\n    var input;\n\n    // Find the first 'real' grandchild node (that isn't whitespace).\n    var firstRealGrandchild = null;\n    for (var y = 0, grandchildNode; grandchildNode = xmlChild.childNodes[y];\n         y++) {\n      if (grandchildNode.nodeType != 3 || !grandchildNode.data.match(/^\\s*$/)) {\n        firstRealGrandchild = grandchildNode;\n      }\n    }\n\n    var name = xmlChild.getAttribute('name');\n    switch (xmlChild.nodeName.toLowerCase()) {\n      case 'mutation':\n        // Custom data for an advanced block.\n        if (block.domToMutation) {\n          block.domToMutation(xmlChild);\n        }\n        break;\n      case 'comment':\n        block.setCommentText(xmlChild.textContent);\n        var visible = xmlChild.getAttribute('pinned');\n        if (visible) {\n          block.comment.setVisible(visible == 'true');\n        }\n        var bubbleW = parseInt(xmlChild.getAttribute('w'), 10);\n        var bubbleH = parseInt(xmlChild.getAttribute('h'), 10);\n        if (!isNaN(bubbleW) && !isNaN(bubbleH)) {\n          block.comment.setBubbleSize(bubbleW, bubbleH);\n        }\n        break;\n      case 'title':\n        // Titles were renamed to field in December 2013.\n        // Fall through.\n      case 'field':\n        block.setFieldValue(xmlChild.textContent, name);\n        break;\n      case 'value':\n      case 'statement':\n        input = block.getInput(name);\n        if (!input) {\n          throw 'Input ' + name + ' does not exist in block ' + prototypeName;\n        }\n        if (firstRealGrandchild &&\n            firstRealGrandchild.nodeName.toLowerCase() == 'block') {\n          blockChild = Blockly.Xml.domToBlock(workspace, firstRealGrandchild,\n              opt_reuseBlock);\n          if (blockChild.outputConnection) {\n            input.connection.connect(blockChild.outputConnection);\n          } else if (blockChild.previousConnection) {\n            input.connection.connect(blockChild.previousConnection);\n          } else {\n            throw 'Child block does not have output or previous statement.';\n          }\n        }\n        break;\n      case 'next':\n        if (firstRealGrandchild &&\n            firstRealGrandchild.nodeName.toLowerCase() == 'block') {\n          if (!block.nextConnection) {\n            throw 'Next statement does not exist.';\n          } else if (block.nextConnection.targetConnection) {\n            // This could happen if there is more than one XML 'next' tag.\n            throw 'Next statement is already connected.';\n          }\n          blockChild = Blockly.Xml.domToBlock(workspace, firstRealGrandchild,\n              opt_reuseBlock);\n          if (!blockChild.previousConnection) {\n            throw 'Next block does not have previous statement.';\n          }\n          block.nextConnection.connect(blockChild.previousConnection);\n        }\n        break;\n      default:\n        // Unknown tag; ignore.  Same principle as HTML parsers.\n    }\n  }\n\n  var next = block.nextConnection && block.nextConnection.targetBlock();\n  if (next) {\n    // Next block in a stack needs to square off its corners.\n    // Rendering a child will render its parent.\n    next.render();\n  } else {\n    block.render();\n  }\n  var collapsed = xmlBlock.getAttribute('collapsed');\n  if (collapsed) {\n    block.setCollapsed(collapsed == 'true');\n  }\n  return block;\n};\n\n/**\n * Remove any 'next' block (statements in a stack).\n * @param {!Element} xmlBlock XML block element.\n */\nBlockly.Xml.deleteNext = function(xmlBlock) {\n  for (var x = 0, child; child = xmlBlock.childNodes[x]; x++) {\n    if (child.nodeName.toLowerCase() == 'next') {\n      xmlBlock.removeChild(child);\n      break;\n    }\n  }\n};\n\n// Export symbols that would otherwise be renamed by Closure compiler.\nBlockly['Xml'] = Blockly.Xml;\nBlockly.Xml['domToText'] = Blockly.Xml.domToText;\nBlockly.Xml['domToWorkspace'] = Blockly.Xml.domToWorkspace;\nBlockly.Xml['textToDom'] = Blockly.Xml.textToDom;\nBlockly.Xml['workspaceToDom'] = Blockly.Xml.workspaceToDom;\n"
  },
  {
    "path": "extern/blockly/dart_compressed.js",
    "content": "// Do not edit this file; automatically generated by build.py.\n\"use strict\";\n\n\n// Copyright 2014 Google Inc.  Apache License 2.0\nBlockly.Dart=new Blockly.Generator(\"Dart\");Blockly.Dart.addReservedWords(\"assert,break,case,catch,class,const,continue,default,do,else,enum,extends,false,final,finally,for,if,in,is,new,null,rethrow,return,super,switch,this,throw,true,try,var,void,while,with,print,identityHashCode,identical,BidirectionalIterator,Comparable,double,Function,int,Invocation,Iterable,Iterator,List,Map,Match,num,Pattern,RegExp,Set,StackTrace,String,StringSink,Type,bool,DateTime,Deprecated,Duration,Expando,Null,Object,RuneIterator,Runes,Stopwatch,StringBuffer,Symbol,Uri,Comparator,AbstractClassInstantiationError,ArgumentError,AssertionError,CastError,ConcurrentModificationError,CyclicInitializationError,Error,Exception,FallThroughError,FormatException,IntegerDivisionByZeroException,NoSuchMethodError,NullThrownError,OutOfMemoryError,RangeError,StackOverflowError,StateError,TypeError,UnimplementedError,UnsupportedError\");\nBlockly.Dart.ORDER_ATOMIC=0;Blockly.Dart.ORDER_UNARY_POSTFIX=1;Blockly.Dart.ORDER_UNARY_PREFIX=2;Blockly.Dart.ORDER_MULTIPLICATIVE=3;Blockly.Dart.ORDER_ADDITIVE=4;Blockly.Dart.ORDER_SHIFT=5;Blockly.Dart.ORDER_BITWISE_AND=6;Blockly.Dart.ORDER_BITWISE_XOR=7;Blockly.Dart.ORDER_BITWISE_OR=8;Blockly.Dart.ORDER_RELATIONAL=9;Blockly.Dart.ORDER_EQUALITY=10;Blockly.Dart.ORDER_LOGICAL_AND=11;Blockly.Dart.ORDER_LOGICAL_OR=12;Blockly.Dart.ORDER_CONDITIONAL=13;Blockly.Dart.ORDER_CASCADE=14;\nBlockly.Dart.ORDER_ASSIGNMENT=15;Blockly.Dart.ORDER_NONE=99;Blockly.Dart.INFINITE_LOOP_TRAP=null;\nBlockly.Dart.init=function(){Blockly.Dart.definitions_=Object.create(null);Blockly.Dart.functionNames_=Object.create(null);if(Blockly.Variables){Blockly.Dart.variableDB_?Blockly.Dart.variableDB_.reset():Blockly.Dart.variableDB_=new Blockly.Names(Blockly.Dart.RESERVED_WORDS_);for(var a=[],b=Blockly.Variables.allVariables(),c=0;c<b.length;c++)a[c]=\"var \"+Blockly.Dart.variableDB_.getName(b[c],Blockly.Variables.NAME_TYPE)+\";\";Blockly.Dart.definitions_.variables=a.join(\"\\n\")}};\nBlockly.Dart.finish=function(a){a=\"  \"+a.replace(/\\n/g,\"\\n  \");a=a.replace(/\\n\\s+$/,\"\\n\");a=\"main() {\\n\"+a+\"}\";var b=[],c=[],d;for(d in Blockly.Dart.definitions_){var e=Blockly.Dart.definitions_[d];e.match(/^import\\s/)?b.push(e):c.push(e)}return(b.join(\"\\n\")+\"\\n\\n\"+c.join(\"\\n\\n\")).replace(/\\n\\n+/g,\"\\n\\n\").replace(/\\n*$/,\"\\n\\n\\n\")+a};Blockly.Dart.scrubNakedValue=function(a){return a+\";\\n\"};\nBlockly.Dart.quote_=function(a){a=a.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\n/g,\"\\\\\\n\").replace(/\\$/g,\"\\\\$\").replace(/'/g,\"\\\\'\");return\"'\"+a+\"'\"};\nBlockly.Dart.scrub_=function(a,b){if(null===b)return\"\";var c=\"\";if(!a.outputConnection||!a.outputConnection.targetConnection){var d=a.getCommentText();d&&(c+=this.prefixLines(d,\"// \")+\"\\n\");for(var e=0;e<a.inputList.length;e++)a.inputList[e].type==Blockly.INPUT_VALUE&&(d=a.inputList[e].connection.targetBlock())&&(d=this.allNestedComments(d))&&(c+=this.prefixLines(d,\"// \"))}e=a.nextConnection&&a.nextConnection.targetBlock();e=this.blockToCode(e);return c+b+e};Blockly.Dart.colour={};Blockly.Dart.addReservedWords(\"Math\");Blockly.Dart.colour_picker=function(a){return[\"'\"+a.getFieldValue(\"COLOUR\")+\"'\",Blockly.Dart.ORDER_ATOMIC]};\nBlockly.Dart.colour_random=function(a){Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";return[Blockly.Dart.provideFunction_(\"colour_random\",[\"String \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"() {\",\"  String hex = '0123456789abcdef';\",\"  var rnd = new Math.Random();\",\"  return '#${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}'\",\"      '${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}'\",\"      '${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}';\",\"}\"])+\"()\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.colour_rgb=function(a){var b=Blockly.Dart.valueToCode(a,\"RED\",Blockly.Dart.ORDER_NONE)||0,c=Blockly.Dart.valueToCode(a,\"GREEN\",Blockly.Dart.ORDER_NONE)||0;a=Blockly.Dart.valueToCode(a,\"BLUE\",Blockly.Dart.ORDER_NONE)||0;Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";return[Blockly.Dart.provideFunction_(\"colour_rgb\",[\"String \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(num r, num g, num b) {\",\"  num rn = (Math.max(Math.min(r, 1), 0) * 255).round();\",\"  String rs = rn.toInt().toRadixString(16);\",\n\"  rs = '0$rs';\",\"  rs = rs.substring(rs.length - 2);\",\"  num gn = (Math.max(Math.min(g, 1), 0) * 255).round();\",\"  String gs = gn.toInt().toRadixString(16);\",\"  gs = '0$gs';\",\"  gs = gs.substring(gs.length - 2);\",\"  num bn = (Math.max(Math.min(b, 1), 0) * 255).round();\",\"  String bs = bn.toInt().toRadixString(16);\",\"  bs = '0$bs';\",\"  bs = bs.substring(bs.length - 2);\",\"  return '#$rs$gs$bs';\",\"}\"])+\"(\"+b+\", \"+c+\", \"+a+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.colour_blend=function(a){var b=Blockly.Dart.valueToCode(a,\"COLOUR1\",Blockly.Dart.ORDER_NONE)||\"'#000000'\",c=Blockly.Dart.valueToCode(a,\"COLOUR2\",Blockly.Dart.ORDER_NONE)||\"'#000000'\";a=Blockly.Dart.valueToCode(a,\"RATIO\",Blockly.Dart.ORDER_NONE)||.5;Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";return[Blockly.Dart.provideFunction_(\"colour_blend\",[\"String \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(String c1, String c2, num ratio) {\",\"  ratio = Math.max(Math.min(ratio, 1), 0);\",\n\"  int r1 = int.parse('0x${c1.substring(1, 3)}');\",\"  int g1 = int.parse('0x${c1.substring(3, 5)}');\",\"  int b1 = int.parse('0x${c1.substring(5, 7)}');\",\"  int r2 = int.parse('0x${c2.substring(1, 3)}');\",\"  int g2 = int.parse('0x${c2.substring(3, 5)}');\",\"  int b2 = int.parse('0x${c2.substring(5, 7)}');\",\"  num rn = (r1 * (1 - ratio) + r2 * ratio).round();\",\"  String rs = rn.toInt().toRadixString(16);\",\"  num gn = (g1 * (1 - ratio) + g2 * ratio).round();\",\"  String gs = gn.toInt().toRadixString(16);\",\n\"  num bn = (b1 * (1 - ratio) + b2 * ratio).round();\",\"  String bs = bn.toInt().toRadixString(16);\",\"  rs = '0$rs';\",\"  rs = rs.substring(rs.length - 2);\",\"  gs = '0$gs';\",\"  gs = gs.substring(gs.length - 2);\",\"  bs = '0$bs';\",\"  bs = bs.substring(bs.length - 2);\",\"  return '#$rs$gs$bs';\",\"}\"])+\"(\"+b+\", \"+c+\", \"+a+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.lists={};Blockly.Dart.addReservedWords(\"Math\");Blockly.Dart.lists_create_empty=function(a){return[\"[]\",Blockly.Dart.ORDER_ATOMIC]};Blockly.Dart.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c<a.itemCount_;c++)b[c]=Blockly.Dart.valueToCode(a,\"ADD\"+c,Blockly.Dart.ORDER_NONE)||\"null\";b=\"[\"+b.join(\", \")+\"]\";return[b,Blockly.Dart.ORDER_ATOMIC]};\nBlockly.Dart.lists_repeat=function(a){var b=Blockly.Dart.valueToCode(a,\"ITEM\",Blockly.Dart.ORDER_NONE)||\"null\";return[\"new List.filled(\"+(Blockly.Dart.valueToCode(a,\"NUM\",Blockly.Dart.ORDER_NONE)||\"0\")+\", \"+b+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.lists_length=function(a){return[(Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"[]\")+\".length\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.lists_isEmpty=function(a){return[(Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"[]\")+\".isEmpty\",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.lists_indexOf=function(a){var b=\"FIRST\"==a.getFieldValue(\"END\")?\"indexOf\":\"lastIndexOf\",c=Blockly.Dart.valueToCode(a,\"FIND\",Blockly.Dart.ORDER_NONE)||\"''\";return[(Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"[]\")+\".\"+b+\"(\"+c+\") + 1\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.lists_getIndex=function(a){var b=a.getFieldValue(\"MODE\")||\"GET\",c=a.getFieldValue(\"WHERE\")||\"FROM_START\",d=Blockly.Dart.valueToCode(a,\"AT\",Blockly.Dart.ORDER_UNARY_PREFIX)||\"1\";a=Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"[]\";if(\"FIRST\"==c){if(\"GET\"==b)return[a+\".first\",Blockly.Dart.ORDER_UNARY_POSTFIX];if(\"GET_REMOVE\"==b)return[a+\".removeAt(0)\",Blockly.Dart.ORDER_UNARY_POSTFIX];if(\"REMOVE\"==b)return a+\".removeAt(0);\\n\"}else if(\"LAST\"==c){if(\"GET\"==b)return[a+\n\".last\",Blockly.Dart.ORDER_UNARY_POSTFIX];if(\"GET_REMOVE\"==b)return[a+\".removeLast()\",Blockly.Dart.ORDER_UNARY_POSTFIX];if(\"REMOVE\"==b)return a+\".removeLast();\\n\"}else if(\"FROM_START\"==c){d=Blockly.isNumber(d)?parseInt(d,10)-1:d+\" - 1\";if(\"GET\"==b)return[a+\"[\"+d+\"]\",Blockly.Dart.ORDER_UNARY_POSTFIX];if(\"GET_REMOVE\"==b)return[a+\".removeAt(\"+d+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX];if(\"REMOVE\"==b)return a+\".removeAt(\"+d+\");\\n\"}else if(\"FROM_END\"==c){if(\"GET\"==b)return c=Blockly.Dart.provideFunction_(\"lists_get_from_end\",\n[\"dynamic \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList, num x) {\",\"  x = myList.length - x;\",\"  return myList.removeAt(x);\",\"}\"]),[c+\"(\"+a+\", \"+d+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX];if(\"GET_REMOVE\"==b||\"REMOVE\"==b){c=Blockly.Dart.provideFunction_(\"lists_remove_from_end\",[\"dynamic \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList, num x) {\",\"  x = myList.length - x;\",\"  return myList.removeAt(x);\",\"}\"]);d=c+\"(\"+a+\", \"+d+\")\";if(\"GET_REMOVE\"==b)return[d,Blockly.Dart.ORDER_UNARY_POSTFIX];\nif(\"REMOVE\"==b)return d+\";\\n\"}}else if(\"RANDOM\"==c){Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";c=Blockly.Dart.provideFunction_(\"lists_get_random_item\",[\"dynamic \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList, bool remove) {\",\"  int x = new Math.Random().nextInt(myList.length);\",\"  if (remove) {\",\"    return myList.removeAt(x);\",\"  } else {\",\"    return myList[x];\",\"  }\",\"}\"]);d=c+\"(\"+a+\", \"+(\"GET\"!=b)+\")\";if(\"GET\"==b||\"GET_REMOVE\"==b)return[d,Blockly.Dart.ORDER_UNARY_POSTFIX];\nif(\"REMOVE\"==b)return d+\";\\n\"}throw\"Unhandled combination (lists_getIndex).\";};\nBlockly.Dart.lists_setIndex=function(a){function b(){if(c.match(/^\\w+$/))return\"\";var a=Blockly.Dart.variableDB_.getDistinctName(\"tmp_list\",Blockly.Variables.NAME_TYPE),b=\"List \"+a+\" = \"+c+\";\\n\";c=a;return b}var c=Blockly.Dart.valueToCode(a,\"LIST\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"[]\",d=a.getFieldValue(\"MODE\")||\"GET\",e=a.getFieldValue(\"WHERE\")||\"FROM_START\",f=Blockly.Dart.valueToCode(a,\"AT\",Blockly.Dart.ORDER_ADDITIVE)||\"1\";a=Blockly.Dart.valueToCode(a,\"TO\",Blockly.Dart.ORDER_ASSIGNMENT)||\"null\";\nif(\"FIRST\"==e){if(\"SET\"==d)return c+\"[0] = \"+a+\";\\n\";if(\"INSERT\"==d)return c+\".insert(0, \"+a+\");\\n\"}else if(\"LAST\"==e){if(\"SET\"==d)return e=b(),e+(c+\"[\"+c+\".length - 1] = \"+a+\";\\n\");if(\"INSERT\"==d)return c+\".add(\"+a+\");\\n\"}else if(\"FROM_START\"==e){f=Blockly.isNumber(f)?parseInt(f,10)-1:f+\" - 1\";if(\"SET\"==d)return c+\"[\"+f+\"] = \"+a+\";\\n\";if(\"INSERT\"==d)return c+\".insert(\"+f+\", \"+a+\");\\n\"}else if(\"FROM_END\"==e){e=b();if(\"SET\"==d)return e+(c+\"[\"+c+\".length - \"+f+\"] = \"+a+\";\\n\");if(\"INSERT\"==d)return e+\n(c+\".insert(\"+c+\".length - \"+f+\", \"+a+\");\\n\")}else if(\"RANDOM\"==e){Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";e=b();f=Blockly.Dart.variableDB_.getDistinctName(\"tmp_x\",Blockly.Variables.NAME_TYPE);e+=\"int \"+f+\" = new Math.Random().nextInt(\"+c+\".length);\";if(\"SET\"==d)return e+(c+\"[\"+f+\"] = \"+a+\";\\n\");if(\"INSERT\"==d)return e+(c+\".insert(\"+f+\", \"+a+\");\\n\")}throw\"Unhandled combination (lists_setIndex).\";};\nBlockly.Dart.lists_getSublist=function(a){var b=Blockly.Dart.valueToCode(a,\"LIST\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"[]\",c=a.getFieldValue(\"WHERE1\"),d=a.getFieldValue(\"WHERE2\"),e=Blockly.Dart.valueToCode(a,\"AT1\",Blockly.Dart.ORDER_NONE)||\"1\";a=Blockly.Dart.valueToCode(a,\"AT2\",Blockly.Dart.ORDER_NONE)||\"1\";(\"FIRST\"==c||\"FROM_START\"==c&&Blockly.isNumber(e))&&(\"LAST\"==d||\"FROM_START\"==d&&Blockly.isNumber(a))?(e=\"FIRST\"==c?0:parseInt(e,10)-1,\"LAST\"==d?b=b+\".sublist(\"+e+\")\":(a=parseInt(a,10),b=b+\".sublist(\"+\ne+\", \"+a+\")\")):b=Blockly.Dart.provideFunction_(\"lists_get_sublist\",[\"List \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(list, where1, at1, where2, at2) {\",\"  int getAt(where, at) {\",\"    if (where == 'FROM_START') {\",\"      at--;\",\"    } else if (where == 'FROM_END') {\",\"      at = list.length - at;\",\"    } else if (where == 'FIRST') {\",\"      at = 0;\",\"    } else if (where == 'LAST') {\",\"      at = list.length - 1;\",\"    } else {\",\"      throw 'Unhandled option (lists_getSublist).';\",\"    }\",\"    return at;\",\n\"  }\",\"  at1 = getAt(where1, at1);\",\"  at2 = getAt(where2, at2) + 1;\",\"  return list.sublist(at1, at2);\",\"}\"])+\"(\"+b+\", '\"+c+\"', \"+e+\", '\"+d+\"', \"+a+\")\";return[b,Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.logic={};Blockly.Dart.controls_if=function(a){for(var b=0,c=Blockly.Dart.valueToCode(a,\"IF\"+b,Blockly.Dart.ORDER_NONE)||\"false\",d=Blockly.Dart.statementToCode(a,\"DO\"+b),e=\"if (\"+c+\") {\\n\"+d+\"}\",b=1;b<=a.elseifCount_;b++)c=Blockly.Dart.valueToCode(a,\"IF\"+b,Blockly.Dart.ORDER_NONE)||\"false\",d=Blockly.Dart.statementToCode(a,\"DO\"+b),e+=\" else if (\"+c+\") {\\n\"+d+\"}\";a.elseCount_&&(d=Blockly.Dart.statementToCode(a,\"ELSE\"),e+=\" else {\\n\"+d+\"}\");return e+\"\\n\"};\nBlockly.Dart.logic_compare=function(a){var b={EQ:\"==\",NEQ:\"!=\",LT:\"<\",LTE:\"<=\",GT:\">\",GTE:\">=\"}[a.getFieldValue(\"OP\")],c=\"==\"==b||\"!=\"==b?Blockly.Dart.ORDER_EQUALITY:Blockly.Dart.ORDER_RELATIONAL,d=Blockly.Dart.valueToCode(a,\"A\",c)||\"0\";a=Blockly.Dart.valueToCode(a,\"B\",c)||\"0\";return[d+\" \"+b+\" \"+a,c]};\nBlockly.Dart.logic_operation=function(a){var b=\"AND\"==a.getFieldValue(\"OP\")?\"&&\":\"||\",c=\"&&\"==b?Blockly.Dart.ORDER_LOGICAL_AND:Blockly.Dart.ORDER_LOGICAL_OR,d=Blockly.Dart.valueToCode(a,\"A\",c);a=Blockly.Dart.valueToCode(a,\"B\",c);if(d||a){var e=\"&&\"==b?\"true\":\"false\";d||(d=e);a||(a=e)}else a=d=\"false\";return[d+\" \"+b+\" \"+a,c]};Blockly.Dart.logic_negate=function(a){var b=Blockly.Dart.ORDER_UNARY_PREFIX;return[\"!\"+(Blockly.Dart.valueToCode(a,\"BOOL\",b)||\"true\"),b]};\nBlockly.Dart.logic_boolean=function(a){return[\"TRUE\"==a.getFieldValue(\"BOOL\")?\"true\":\"false\",Blockly.Dart.ORDER_ATOMIC]};Blockly.Dart.logic_null=function(a){return[\"null\",Blockly.Dart.ORDER_ATOMIC]};Blockly.Dart.logic_ternary=function(a){var b=Blockly.Dart.valueToCode(a,\"IF\",Blockly.Dart.ORDER_CONDITIONAL)||\"false\",c=Blockly.Dart.valueToCode(a,\"THEN\",Blockly.Dart.ORDER_CONDITIONAL)||\"null\";a=Blockly.Dart.valueToCode(a,\"ELSE\",Blockly.Dart.ORDER_CONDITIONAL)||\"null\";return[b+\" ? \"+c+\" : \"+a,Blockly.Dart.ORDER_CONDITIONAL]};Blockly.Dart.loops={};Blockly.Dart.controls_repeat=function(a){var b=Number(a.getFieldValue(\"TIMES\")),c=Blockly.Dart.statementToCode(a,\"DO\");Blockly.Dart.INFINITE_LOOP_TRAP&&(c=Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+c);a=Blockly.Dart.variableDB_.getDistinctName(\"count\",Blockly.Variables.NAME_TYPE);return\"for (int \"+a+\" = 0; \"+a+\" < \"+b+\"; \"+a+\"++) {\\n\"+c+\"}\\n\"};\nBlockly.Dart.controls_repeat_ext=function(a){var b=Blockly.Dart.valueToCode(a,\"TIMES\",Blockly.Dart.ORDER_ASSIGNMENT)||\"0\",c=Blockly.Dart.statementToCode(a,\"DO\");Blockly.Dart.INFINITE_LOOP_TRAP&&(c=Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+c);a=\"\";var d=Blockly.Dart.variableDB_.getDistinctName(\"count\",Blockly.Variables.NAME_TYPE),e=b;b.match(/^\\w+$/)||Blockly.isNumber(b)||(e=Blockly.Dart.variableDB_.getDistinctName(\"repeat_end\",Blockly.Variables.NAME_TYPE),a+=\"var \"+e+\" = \"+b+\";\\n\");\nreturn a+(\"for (int \"+d+\" = 0; \"+d+\" < \"+e+\"; \"+d+\"++) {\\n\"+c+\"}\\n\")};Blockly.Dart.controls_whileUntil=function(a){var b=\"UNTIL\"==a.getFieldValue(\"MODE\"),c=Blockly.Dart.valueToCode(a,\"BOOL\",b?Blockly.Dart.ORDER_UNARY_PREFIX:Blockly.Dart.ORDER_NONE)||\"false\",d=Blockly.Dart.statementToCode(a,\"DO\");Blockly.Dart.INFINITE_LOOP_TRAP&&(d=Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+d);b&&(c=\"!\"+c);return\"while (\"+c+\") {\\n\"+d+\"}\\n\"};\nBlockly.Dart.controls_for=function(a){var b=Blockly.Dart.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),c=Blockly.Dart.valueToCode(a,\"FROM\",Blockly.Dart.ORDER_ASSIGNMENT)||\"0\",d=Blockly.Dart.valueToCode(a,\"TO\",Blockly.Dart.ORDER_ASSIGNMENT)||\"0\",e=Blockly.Dart.valueToCode(a,\"BY\",Blockly.Dart.ORDER_ASSIGNMENT)||\"1\",f=Blockly.Dart.statementToCode(a,\"DO\");Blockly.Dart.INFINITE_LOOP_TRAP&&(f=Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+f);if(Blockly.isNumber(c)&&\nBlockly.isNumber(d)&&Blockly.isNumber(e)){var g=parseFloat(c)<=parseFloat(d);a=\"for (\"+b+\" = \"+c+\"; \"+b+(g?\" <= \":\" >= \")+d+\"; \"+b;b=Math.abs(parseFloat(e));a=(1==b?a+(g?\"++\":\"--\"):a+((g?\" += \":\" -= \")+b))+(\") {\\n\"+f+\"}\\n\")}else a=\"\",g=c,c.match(/^\\w+$/)||Blockly.isNumber(c)||(g=Blockly.Dart.variableDB_.getDistinctName(b+\"_start\",Blockly.Variables.NAME_TYPE),a+=\"var \"+g+\" = \"+c+\";\\n\"),c=d,d.match(/^\\w+$/)||Blockly.isNumber(d)||(c=Blockly.Dart.variableDB_.getDistinctName(b+\"_end\",Blockly.Variables.NAME_TYPE),\na+=\"var \"+c+\" = \"+d+\";\\n\"),d=Blockly.Dart.variableDB_.getDistinctName(b+\"_inc\",Blockly.Variables.NAME_TYPE),a+=\"num \"+d+\" = \",a=Blockly.isNumber(e)?a+(Math.abs(e)+\";\\n\"):a+(\"(\"+e+\").abs();\\n\"),a=a+(\"if (\"+g+\" > \"+c+\") {\\n\")+(\"  \"+d+\" = -\"+d+\";\\n\"),a+=\"}\\n\",a+=\"for (\"+b+\" = \"+g+\";\\n     \"+d+\" >= 0 ? \"+b+\" <= \"+c+\" : \"+b+\" >= \"+c+\";\\n     \"+b+\" += \"+d+\") {\\n\"+f+\"}\\n\";return a};\nBlockly.Dart.controls_forEach=function(a){var b=Blockly.Dart.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),c=Blockly.Dart.valueToCode(a,\"LIST\",Blockly.Dart.ORDER_ASSIGNMENT)||\"[]\",d=Blockly.Dart.statementToCode(a,\"DO\");Blockly.Dart.INFINITE_LOOP_TRAP&&(d=Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+d);return\"for (var \"+b+\" in  \"+c+\") {\\n\"+d+\"}\\n\"};\nBlockly.Dart.controls_flow_statements=function(a){switch(a.getFieldValue(\"FLOW\")){case \"BREAK\":return\"break;\\n\";case \"CONTINUE\":return\"continue;\\n\"}throw\"Unknown flow statement.\";};Blockly.Dart.math={};Blockly.Dart.addReservedWords(\"Math\");Blockly.Dart.math_number=function(a){a=window.parseFloat(a.getFieldValue(\"NUM\"));return[a,0>a?Blockly.Dart.ORDER_UNARY_PREFIX:Blockly.Dart.ORDER_ATOMIC]};\nBlockly.Dart.math_arithmetic=function(a){var b={ADD:[\" + \",Blockly.Dart.ORDER_ADDITIVE],MINUS:[\" - \",Blockly.Dart.ORDER_ADDITIVE],MULTIPLY:[\" * \",Blockly.Dart.ORDER_MULTIPLICATIVE],DIVIDE:[\" / \",Blockly.Dart.ORDER_MULTIPLICATIVE],POWER:[null,Blockly.Dart.ORDER_NONE]}[a.getFieldValue(\"OP\")],c=b[0],b=b[1],d=Blockly.Dart.valueToCode(a,\"A\",b)||\"0\";a=Blockly.Dart.valueToCode(a,\"B\",b)||\"0\";return c?[d+c+a,b]:(Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\",[\"Math.pow(\"+d+\", \"+a+\n\")\",Blockly.Dart.ORDER_UNARY_POSTFIX])};\nBlockly.Dart.math_single=function(a){var b=a.getFieldValue(\"OP\"),c;if(\"NEG\"==b)return a=Blockly.Dart.valueToCode(a,\"NUM\",Blockly.Dart.ORDER_UNARY_PREFIX)||\"0\",\"-\"==a[0]&&(a=\" \"+a),[\"-\"+a,Blockly.Dart.ORDER_UNARY_PREFIX];Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";a=\"ABS\"==b||\"ROUND\"==b.substring(0,5)?Blockly.Dart.valueToCode(a,\"NUM\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"0\":\"SIN\"==b||\"COS\"==b||\"TAN\"==b?Blockly.Dart.valueToCode(a,\"NUM\",Blockly.Dart.ORDER_MULTIPLICATIVE)||\n\"0\":Blockly.Dart.valueToCode(a,\"NUM\",Blockly.Dart.ORDER_NONE)||\"0\";switch(b){case \"ABS\":c=a+\".abs()\";break;case \"ROOT\":c=\"Math.sqrt(\"+a+\")\";break;case \"LN\":c=\"Math.log(\"+a+\")\";break;case \"EXP\":c=\"Math.exp(\"+a+\")\";break;case \"POW10\":c=\"Math.pow(10,\"+a+\")\";break;case \"ROUND\":c=a+\".round()\";break;case \"ROUNDUP\":c=a+\".ceil()\";break;case \"ROUNDDOWN\":c=a+\".floor()\";break;case \"SIN\":c=\"Math.sin(\"+a+\" / 180 * Math.PI)\";break;case \"COS\":c=\"Math.cos(\"+a+\" / 180 * Math.PI)\";break;case \"TAN\":c=\"Math.tan(\"+a+\n\" / 180 * Math.PI)\"}if(c)return[c,Blockly.Dart.ORDER_UNARY_POSTFIX];switch(b){case \"LOG10\":c=\"Math.log(\"+a+\") / Math.log(10)\";break;case \"ASIN\":c=\"Math.asin(\"+a+\") / Math.PI * 180\";break;case \"ACOS\":c=\"Math.acos(\"+a+\") / Math.PI * 180\";break;case \"ATAN\":c=\"Math.atan(\"+a+\") / Math.PI * 180\";break;default:throw\"Unknown math operator: \"+b;}return[c,Blockly.Dart.ORDER_MULTIPLICATIVE]};\nBlockly.Dart.math_constant=function(a){var b={PI:[\"Math.PI\",Blockly.Dart.ORDER_UNARY_POSTFIX],E:[\"Math.E\",Blockly.Dart.ORDER_UNARY_POSTFIX],GOLDEN_RATIO:[\"(1 + Math.sqrt(5)) / 2\",Blockly.Dart.ORDER_MULTIPLICATIVE],SQRT2:[\"Math.SQRT2\",Blockly.Dart.ORDER_UNARY_POSTFIX],SQRT1_2:[\"Math.SQRT1_2\",Blockly.Dart.ORDER_UNARY_POSTFIX],INFINITY:[\"double.INFINITY\",Blockly.Dart.ORDER_ATOMIC]};a=a.getFieldValue(\"CONSTANT\");\"INFINITY\"!=a&&(Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\");\nreturn b[a]};\nBlockly.Dart.math_number_property=function(a){var b=Blockly.Dart.valueToCode(a,\"NUMBER_TO_CHECK\",Blockly.Dart.ORDER_MULTIPLICATIVE);if(!b)return[\"false\",Blockly.Python.ORDER_ATOMIC];var c=a.getFieldValue(\"PROPERTY\"),d;if(\"PRIME\"==c)return Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\",[Blockly.Dart.provideFunction_(\"math_isPrime\",[\"bool \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(n) {\",\"  // https://en.wikipedia.org/wiki/Primality_test#Naive_methods\",\"  if (n == 2 || n == 3) {\",\"    return true;\",\n\"  }\",\"  // False if n is null, negative, is 1, or not whole.\",\"  // And false if n is divisible by 2 or 3.\",\"  if (n == null || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {\",\"    return false;\",\"  }\",\"  // Check all the numbers of form 6k +/- 1, up to sqrt(n).\",\"  for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {\",\"    if (n % (x - 1) == 0 || n % (x + 1) == 0) {\",\"      return false;\",\"    }\",\"  }\",\"  return true;\",\"}\"])+\"(\"+b+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX];switch(c){case \"EVEN\":d=b+\n\" % 2 == 0\";break;case \"ODD\":d=b+\" % 2 == 1\";break;case \"WHOLE\":d=b+\" % 1 == 0\";break;case \"POSITIVE\":d=b+\" > 0\";break;case \"NEGATIVE\":d=b+\" < 0\";break;case \"DIVISIBLE_BY\":a=Blockly.Dart.valueToCode(a,\"DIVISOR\",Blockly.Dart.ORDER_MULTIPLICATIVE);if(!a)return[\"false\",Blockly.Python.ORDER_ATOMIC];d=b+\" % \"+a+\" == 0\"}return[d,Blockly.Dart.ORDER_EQUALITY]};\nBlockly.Dart.math_change=function(a){var b=Blockly.Dart.valueToCode(a,\"DELTA\",Blockly.Dart.ORDER_ADDITIVE)||\"0\";a=Blockly.Dart.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE);return a+\" = (\"+a+\" is num ? \"+a+\" : 0) + \"+b+\";\\n\"};Blockly.Dart.math_round=Blockly.Dart.math_single;Blockly.Dart.math_trig=Blockly.Dart.math_single;\nBlockly.Dart.math_on_list=function(a){var b=a.getFieldValue(\"OP\");a=Blockly.Dart.valueToCode(a,\"LIST\",Blockly.Dart.ORDER_NONE)||\"[]\";switch(b){case \"SUM\":b=Blockly.Dart.provideFunction_(\"math_sum\",[\"num \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList) {\",\"  num sumVal = 0;\",\"  myList.forEach((num entry) {sumVal += entry;});\",\"  return sumVal;\",\"}\"]);b=b+\"(\"+a+\")\";break;case \"MIN\":Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";b=Blockly.Dart.provideFunction_(\"math_min\",\n[\"num \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList) {\",\"  if (myList.isEmpty) return null;\",\"  num minVal = myList[0];\",\"  myList.forEach((num entry) {minVal = Math.min(minVal, entry);});\",\"  return minVal;\",\"}\"]);b=b+\"(\"+a+\")\";break;case \"MAX\":Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";b=Blockly.Dart.provideFunction_(\"math_max\",[\"num \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList) {\",\"  if (myList.isEmpty) return null;\",\"  num maxVal = myList[0];\",\n\"  myList.forEach((num entry) {maxVal = Math.max(maxVal, entry);});\",\"  return maxVal;\",\"}\"]);b=b+\"(\"+a+\")\";break;case \"AVERAGE\":b=Blockly.Dart.provideFunction_(\"math_average\",[\"num \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList) {\",\"  // First filter list for numbers only.\",\"  List localList = new List.from(myList);\",\"  localList.removeMatching((a) => a is! num);\",\"  if (localList.isEmpty) return null;\",\"  num sumVal = 0;\",\"  localList.forEach((num entry) {sumVal += entry;});\",\"  return sumVal / localList.length;\",\n\"}\"]);b=b+\"(\"+a+\")\";break;case \"MEDIAN\":b=Blockly.Dart.provideFunction_(\"math_median\",[\"num \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList) {\",\"  // First filter list for numbers only, then sort, then return middle value\",\"  // or the average of two middle values if list has an even number of elements.\",\"  List localList = new List.from(myList);\",\"  localList.removeMatching((a) => a is! num);\",\"  if (localList.isEmpty) return null;\",\"  localList.sort((a, b) => (a - b));\",\"  int index = localList.length ~/ 2;\",\n\"  if (localList.length % 2 == 1) {\",\"    return localList[index];\",\"  } else {\",\"    return (localList[index - 1] + localList[index]) / 2;\",\"  }\",\"}\"]);b=b+\"(\"+a+\")\";break;case \"MODE\":Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";b=Blockly.Dart.provideFunction_(\"math_modes\",[\"List \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List values) {\",\"  List modes = [];\",\"  List counts = [];\",\"  int maxCount = 0;\",\"  for (int i = 0; i < values.length; i++) {\",\"    var value = values[i];\",\n\"    bool found = false;\",\"    int thisCount;\",\"    for (int j = 0; j < counts.length; j++) {\",\"      if (counts[j][0] == value) {\",\"        thisCount = ++counts[j][1];\",\"        found = true;\",\"        break;\",\"      }\",\"    }\",\"    if (!found) {\",\"      counts.add([value, 1]);\",\"      thisCount = 1;\",\"    }\",\"    maxCount = Math.max(thisCount, maxCount);\",\"  }\",\"  for (int j = 0; j < counts.length; j++) {\",\"    if (counts[j][1] == maxCount) {\",\"        modes.add(counts[j][0]);\",\"    }\",\"  }\",\"  return modes;\",\n\"}\"]);b=b+\"(\"+a+\")\";break;case \"STD_DEV\":Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";b=Blockly.Dart.provideFunction_(\"math_standard_deviation\",[\"num \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList) {\",\"  // First filter list for numbers only.\",\"  List numbers = new List.from(myList);\",\"  numbers.removeMatching((a) => a is! num);\",\"  if (numbers.isEmpty) return null;\",\"  num n = numbers.length;\",\"  num sum = 0;\",\"  numbers.forEach((x) => sum += x);\",\"  num mean = sum / n;\",\n\"  num sumSquare = 0;\",\"  numbers.forEach((x) => sumSquare += Math.pow(x - mean, 2));\",\"  return Math.sqrt(sumSquare / n);\",\"}\"]);b=b+\"(\"+a+\")\";break;case \"RANDOM\":Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";b=Blockly.Dart.provideFunction_(\"math_random_item\",[\"dynamic \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(List myList) {\",\"  int x = new Math.Random().nextInt(myList.length);\",\"  return myList[x];\",\"}\"]);b=b+\"(\"+a+\")\";break;default:throw\"Unknown operator: \"+b;}return[b,\nBlockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.math_modulo=function(a){var b=Blockly.Dart.valueToCode(a,\"DIVIDEND\",Blockly.Dart.ORDER_MULTIPLICATIVE)||\"0\";a=Blockly.Dart.valueToCode(a,\"DIVISOR\",Blockly.Dart.ORDER_MULTIPLICATIVE)||\"0\";return[b+\" % \"+a,Blockly.Dart.ORDER_MULTIPLICATIVE]};\nBlockly.Dart.math_constrain=function(a){Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";var b=Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_NONE)||\"0\",c=Blockly.Dart.valueToCode(a,\"LOW\",Blockly.Dart.ORDER_NONE)||\"0\";a=Blockly.Dart.valueToCode(a,\"HIGH\",Blockly.Dart.ORDER_NONE)||\"double.INFINITY\";return[\"Math.min(Math.max(\"+b+\", \"+c+\"), \"+a+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.math_random_int=function(a){Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";var b=Blockly.Dart.valueToCode(a,\"FROM\",Blockly.Dart.ORDER_NONE)||\"0\";a=Blockly.Dart.valueToCode(a,\"TO\",Blockly.Dart.ORDER_NONE)||\"0\";return[Blockly.Dart.provideFunction_(\"math_random_int\",[\"int \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(num a, num b) {\",\"  if (a > b) {\",\"    // Swap a and b to ensure a is smaller.\",\"    num c = a;\",\"    a = b;\",\"    b = c;\",\"  }\",\"  return new Math.Random().nextInt(b - a + 1) + a;\",\n\"}\"])+\"(\"+b+\", \"+a+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.math_random_float=function(a){Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\";return[\"new Math.Random().nextDouble()\",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.procedures={};\nBlockly.Dart.procedures_defreturn=function(a){var b=Blockly.Dart.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE),c=Blockly.Dart.statementToCode(a,\"STACK\");Blockly.Dart.INFINITE_LOOP_TRAP&&(c=Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+c);var d=Blockly.Dart.valueToCode(a,\"RETURN\",Blockly.Dart.ORDER_NONE)||\"\";d&&(d=\"  return \"+d+\";\\n\");for(var e=d?\"dynamic\":\"void\",f=[],g=0;g<a.arguments_.length;g++)f[g]=Blockly.Dart.variableDB_.getName(a.arguments_[g],Blockly.Variables.NAME_TYPE);\nc=e+\" \"+b+\"(\"+f.join(\", \")+\") {\\n\"+c+d+\"}\";c=Blockly.Dart.scrub_(a,c);Blockly.Dart.definitions_[b]=c;return null};Blockly.Dart.procedures_defnoreturn=Blockly.Dart.procedures_defreturn;Blockly.Dart.procedures_callreturn=function(a){for(var b=Blockly.Dart.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE),c=[],d=0;d<a.arguments_.length;d++)c[d]=Blockly.Dart.valueToCode(a,\"ARG\"+d,Blockly.Dart.ORDER_NONE)||\"null\";return[b+\"(\"+c.join(\", \")+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.procedures_callnoreturn=function(a){for(var b=Blockly.Dart.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE),c=[],d=0;d<a.arguments_.length;d++)c[d]=Blockly.Dart.valueToCode(a,\"ARG\"+d,Blockly.Dart.ORDER_NONE)||\"null\";return b+\"(\"+c.join(\", \")+\");\\n\"};\nBlockly.Dart.procedures_ifreturn=function(a){var b=\"if (\"+(Blockly.Dart.valueToCode(a,\"CONDITION\",Blockly.Dart.ORDER_NONE)||\"false\")+\") {\\n\";a.hasReturnValue_?(a=Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_NONE)||\"null\",b+=\"  return \"+a+\";\\n\"):b+=\"  return;\\n\";return b+\"}\\n\"};Blockly.Dart.text={};Blockly.Dart.addReservedWords(\"Html,Math\");Blockly.Dart.text=function(a){return[Blockly.Dart.quote_(a.getFieldValue(\"TEXT\")),Blockly.Dart.ORDER_ATOMIC]};\nBlockly.Dart.text_join=function(a){var b;if(0==a.itemCount_)return[\"''\",Blockly.Dart.ORDER_ATOMIC];if(1==a.itemCount_)return[(Blockly.Dart.valueToCode(a,\"ADD0\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\")+\".toString()\",Blockly.Dart.ORDER_UNARY_POSTFIX];b=Array(a.itemCount_);for(var c=0;c<a.itemCount_;c++)b[c]=Blockly.Dart.valueToCode(a,\"ADD\"+c,Blockly.Dart.ORDER_NONE)||\"''\";b=\"[\"+b.join(\",\")+\"].join()\";return[b,Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.text_append=function(a){var b=Blockly.Dart.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE);a=Blockly.Dart.valueToCode(a,\"TEXT\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\";return b+\" = [\"+b+\", \"+a+\"].join();\\n\"};Blockly.Dart.text_length=function(a){return[(Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\")+\".length\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.text_isEmpty=function(a){return[(Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\")+\".isEmpty\",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.text_indexOf=function(a){var b=\"FIRST\"==a.getFieldValue(\"END\")?\"indexOf\":\"lastIndexOf\",c=Blockly.Dart.valueToCode(a,\"FIND\",Blockly.Dart.ORDER_NONE)||\"''\";return[(Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\")+\".\"+b+\"(\"+c+\") + 1\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.text_charAt=function(a){var b=a.getFieldValue(\"WHERE\")||\"FROM_START\",c=Blockly.Dart.valueToCode(a,\"AT\",Blockly.Dart.ORDER_NONE)||\"1\";a=Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\";switch(b){case \"FIRST\":return[a+\"[0]\",Blockly.Dart.ORDER_UNARY_POSTFIX];case \"FROM_START\":return c=c.match(/^-?\\d+$/)?parseInt(c,10)-1:c+\" - 1\",[a+\"[\"+c+\"]\",Blockly.Dart.ORDER_UNARY_POSTFIX];case \"LAST\":c=1;case \"FROM_END\":return b=Blockly.Dart.provideFunction_(\"text_get_from_end\",\n[\"String \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(String text, num x) {\",\"  return text[text.length - x];\",\"}\"]),[b+\"(\"+a+\", \"+c+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX];case \"RANDOM\":return Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\",b=Blockly.Dart.provideFunction_(\"text_random_letter\",[\"String \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(String text) {\",\"  int x = new Math.Random().nextInt(text.length);\",\"  return text[x];\",\"}\"]),[b+\"(\"+a+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX]}throw\"Unhandled option (text_charAt).\";\n};\nBlockly.Dart.text_getSubstring=function(a){var b=Blockly.Dart.valueToCode(a,\"STRING\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\",c=a.getFieldValue(\"WHERE1\"),d=a.getFieldValue(\"WHERE2\"),e=Blockly.Dart.valueToCode(a,\"AT1\",Blockly.Dart.ORDER_NONE)||\"1\";a=Blockly.Dart.valueToCode(a,\"AT2\",Blockly.Dart.ORDER_NONE)||\"1\";return[\"FIRST\"==c&&\"LAST\"==d?b:Blockly.Dart.provideFunction_(\"text_get_substring\",[\"function \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(text, where1, at1, where2, at2) {\",\"  function getAt(where, at) {\",\"    if (where == 'FROM_START') {\",\n\"      at--;\",\"    } else if (where == 'FROM_END') {\",\"      at = text.length - at;\",\"    } else if (where == 'FIRST') {\",\"      at = 0;\",\"    } else if (where == 'LAST') {\",\"      at = text.length - 1;\",\"    } else {\",\"      throw 'Unhandled option (text_getSubstring).';\",\"    }\",\"    return at;\",\"  }\",\"  at1 = getAt(where1, at1);\",\"  at2 = getAt(where2, at2) + 1;\",\"  return text.substring(at1, at2);\",\"}\"])+\"(\"+b+\", '\"+c+\"', \"+e+\", '\"+d+\"', \"+a+\")\",Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.text_changeCase=function(a){var b={UPPERCASE:\".toUpperCase()\",LOWERCASE:\".toLowerCase()\",TITLECASE:null}[a.getFieldValue(\"CASE\")];b?(a=Blockly.Dart.valueToCode(a,\"TEXT\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\",a+=b):(b=Blockly.Dart.provideFunction_(\"text_toTitleCase\",[\"String \"+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+\"(String str) {\",\"  RegExp exp = new RegExp(r'\\\\b');\",\"  List<String> list = str.split(exp);\",\"  final title = new StringBuffer();\",\"  for (String part in list) {\",\"    if (part.length > 0) {\",\n\"      title.write(part[0].toUpperCase());\",\"      if (part.length > 0) {\",\"        title.write(part.substring(1).toLowerCase());\",\"      }\",\"    }\",\"  }\",\"  return title.toString();\",\"}\"]),a=Blockly.Dart.valueToCode(a,\"TEXT\",Blockly.Dart.ORDER_NONE)||\"''\",a=b+\"(\"+a+\")\");return[a,Blockly.Dart.ORDER_UNARY_POSTFIX]};\nBlockly.Dart.text_trim=function(a){var b={LEFT:\".replaceFirst(new RegExp(r'^\\\\s+'), '')\",RIGHT:\".replaceFirst(new RegExp(r'\\\\s+$'), '')\",BOTH:\".trim()\"}[a.getFieldValue(\"MODE\")];return[(Blockly.Dart.valueToCode(a,\"TEXT\",Blockly.Dart.ORDER_UNARY_POSTFIX)||\"''\")+b,Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.text_print=function(a){return\"print(\"+(Blockly.Dart.valueToCode(a,\"TEXT\",Blockly.Dart.ORDER_NONE)||\"''\")+\");\\n\"};\nBlockly.Dart.text_prompt=function(a){Blockly.Dart.definitions_.import_dart_html=\"import 'dart:html' as Html;\";var b=\"Html.window.prompt(\"+Blockly.Dart.quote_(a.getFieldValue(\"TEXT\"))+\", '')\";\"NUMBER\"==a.getFieldValue(\"TYPE\")&&(Blockly.Dart.definitions_.import_dart_math=\"import 'dart:math' as Math;\",b=\"Math.parseDouble(\"+b+\")\");return[b,Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.variables={};Blockly.Dart.variables_get=function(a){return[Blockly.Dart.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),Blockly.Dart.ORDER_ATOMIC]};Blockly.Dart.variables_set=function(a){var b=Blockly.Dart.valueToCode(a,\"VALUE\",Blockly.Dart.ORDER_ASSIGNMENT)||\"0\";return Blockly.Dart.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE)+\" = \"+b+\";\\n\"};"
  },
  {
    "path": "extern/blockly/generators/dart/colour.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for colour blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart.colour');\n\ngoog.require('Blockly.Dart');\n\n\nBlockly.Dart.addReservedWords('Math');\n\nBlockly.Dart['colour_picker'] = function(block) {\n  // Colour picker.\n  var code = '\\'' + block.getFieldValue('COLOUR') + '\\'';\n  return [code, Blockly.Dart.ORDER_ATOMIC];\n};\n\nBlockly.Dart['colour_random'] = function(block) {\n  // Generate a random colour.\n  Blockly.Dart.definitions_['import_dart_math'] =\n      'import \\'dart:math\\' as Math;';\n  var functionName = Blockly.Dart.provideFunction_(\n      'colour_random',\n      [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '() {',\n        '  String hex = \\'0123456789abcdef\\';',\n        '  var rnd = new Math.Random();',\n        '  return \\'#${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\\'',\n        '      \\'${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\\'',\n        '      \\'${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\\';',\n        '}']);\n  var code = functionName + '()';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['colour_rgb'] = function(block) {\n  // Compose a colour from RGB components expressed as percentages.\n  var red = Blockly.Dart.valueToCode(block, 'RED',\n      Blockly.Dart.ORDER_NONE) || 0;\n  var green = Blockly.Dart.valueToCode(block, 'GREEN',\n      Blockly.Dart.ORDER_NONE) || 0;\n  var blue = Blockly.Dart.valueToCode(block, 'BLUE',\n      Blockly.Dart.ORDER_NONE) || 0;\n\n  Blockly.Dart.definitions_['import_dart_math'] =\n      'import \\'dart:math\\' as Math;';\n  var functionName = Blockly.Dart.provideFunction_(\n      'colour_rgb',\n      [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n          '(num r, num g, num b) {',\n        '  num rn = (Math.max(Math.min(r, 1), 0) * 255).round();',\n        '  String rs = rn.toInt().toRadixString(16);',\n        '  rs = \\'0$rs\\';',\n        '  rs = rs.substring(rs.length - 2);',\n        '  num gn = (Math.max(Math.min(g, 1), 0) * 255).round();',\n        '  String gs = gn.toInt().toRadixString(16);',\n        '  gs = \\'0$gs\\';',\n        '  gs = gs.substring(gs.length - 2);',\n        '  num bn = (Math.max(Math.min(b, 1), 0) * 255).round();',\n        '  String bs = bn.toInt().toRadixString(16);',\n        '  bs = \\'0$bs\\';',\n        '  bs = bs.substring(bs.length - 2);',\n        '  return \\'#$rs$gs$bs\\';',\n        '}']);\n  var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['colour_blend'] = function(block) {\n  // Blend two colours together.\n  var c1 = Blockly.Dart.valueToCode(block, 'COLOUR1',\n      Blockly.Dart.ORDER_NONE) || '\\'#000000\\'';\n  var c2 = Blockly.Dart.valueToCode(block, 'COLOUR2',\n      Blockly.Dart.ORDER_NONE) || '\\'#000000\\'';\n  var ratio = Blockly.Dart.valueToCode(block, 'RATIO',\n      Blockly.Dart.ORDER_NONE) || 0.5;\n\n  Blockly.Dart.definitions_['import_dart_math'] =\n      'import \\'dart:math\\' as Math;';\n  var functionName = Blockly.Dart.provideFunction_(\n      'colour_blend',\n      [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n          '(String c1, String c2, num ratio) {',\n        '  ratio = Math.max(Math.min(ratio, 1), 0);',\n        '  int r1 = int.parse(\\'0x${c1.substring(1, 3)}\\');',\n        '  int g1 = int.parse(\\'0x${c1.substring(3, 5)}\\');',\n        '  int b1 = int.parse(\\'0x${c1.substring(5, 7)}\\');',\n        '  int r2 = int.parse(\\'0x${c2.substring(1, 3)}\\');',\n        '  int g2 = int.parse(\\'0x${c2.substring(3, 5)}\\');',\n        '  int b2 = int.parse(\\'0x${c2.substring(5, 7)}\\');',\n        '  num rn = (r1 * (1 - ratio) + r2 * ratio).round();',\n        '  String rs = rn.toInt().toRadixString(16);',\n        '  num gn = (g1 * (1 - ratio) + g2 * ratio).round();',\n        '  String gs = gn.toInt().toRadixString(16);',\n        '  num bn = (b1 * (1 - ratio) + b2 * ratio).round();',\n        '  String bs = bn.toInt().toRadixString(16);',\n        '  rs = \\'0$rs\\';',\n        '  rs = rs.substring(rs.length - 2);',\n        '  gs = \\'0$gs\\';',\n        '  gs = gs.substring(gs.length - 2);',\n        '  bs = \\'0$bs\\';',\n        '  bs = bs.substring(bs.length - 2);',\n        '  return \\'#$rs$gs$bs\\';',\n        '}']);\n  var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n"
  },
  {
    "path": "extern/blockly/generators/dart/lists.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for list blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart.lists');\n\ngoog.require('Blockly.Dart');\n\n\nBlockly.Dart.addReservedWords('Math');\n\nBlockly.Dart['lists_create_empty'] = function(block) {\n  // Create an empty list.\n  return ['[]', Blockly.Dart.ORDER_ATOMIC];\n};\n\nBlockly.Dart['lists_create_with'] = function(block) {\n  // Create a list with any number of elements of any type.\n  var code = new Array(block.itemCount_);\n  for (var n = 0; n < block.itemCount_; n++) {\n    code[n] = Blockly.Dart.valueToCode(block, 'ADD' + n,\n        Blockly.Dart.ORDER_NONE) || 'null';\n  }\n  code = '[' + code.join(', ') + ']';\n  return [code, Blockly.Dart.ORDER_ATOMIC];\n};\n\nBlockly.Dart['lists_repeat'] = function(block) {\n  // Create a list with one element repeated.\n  var argument0 = Blockly.Dart.valueToCode(block, 'ITEM',\n    Blockly.Dart.ORDER_NONE) || 'null';\n  var argument1 = Blockly.Dart.valueToCode(block, 'NUM',\n    Blockly.Dart.ORDER_NONE) || '0';\n  var code = 'new List.filled(' + argument1 + ', ' + argument0 + ')';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['lists_length'] = function(block) {\n  // List length.\n  var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';\n  return [argument0 + '.length', Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['lists_isEmpty'] = function(block) {\n  // Is the list empty?\n  var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';\n  return [argument0 + '.isEmpty', Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['lists_indexOf'] = function(block) {\n  // Find an item in the list.\n  var operator = block.getFieldValue('END') == 'FIRST' ?\n      'indexOf' : 'lastIndexOf';\n  var argument0 = Blockly.Dart.valueToCode(block, 'FIND',\n      Blockly.Dart.ORDER_NONE) || '\\'\\'';\n  var argument1 = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';\n  var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['lists_getIndex'] = function(block) {\n  // Get element at index.\n  // Note: Until January 2013 this block did not have MODE or WHERE inputs.\n  var mode = block.getFieldValue('MODE') || 'GET';\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.Dart.valueToCode(block, 'AT',\n      Blockly.Dart.ORDER_UNARY_PREFIX) || '1';\n  var list = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';\n\n  if (where == 'FIRST') {\n    if (mode == 'GET') {\n      var code = list + '.first';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    } else if (mode == 'GET_REMOVE') {\n      var code = list + '.removeAt(0)';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    } else if (mode == 'REMOVE') {\n      return list + '.removeAt(0);\\n';\n    }\n  } else if (where == 'LAST') {\n    if (mode == 'GET') {\n      var code = list + '.last';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    } else if (mode == 'GET_REMOVE') {\n      var code = list + '.removeLast()';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    } else if (mode == 'REMOVE') {\n      return list + '.removeLast();\\n';\n    }\n  } else if (where == 'FROM_START') {\n    // Blockly uses one-based indicies.\n    if (Blockly.isNumber(at)) {\n      // If the index is a naked number, decrement it right now.\n      at = parseInt(at, 10) - 1;\n    } else {\n      // If the index is dynamic, decrement it in code.\n      at += ' - 1';\n    }\n    if (mode == 'GET') {\n      var code = list + '[' + at + ']';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    } else if (mode == 'GET_REMOVE') {\n      var code = list + '.removeAt(' + at + ')';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    } else if (mode == 'REMOVE') {\n      return list + '.removeAt(' + at + ');\\n';\n    }\n  } else if (where == 'FROM_END') {\n    if (mode == 'GET') {\n      var functionName = Blockly.Dart.provideFunction_(\n          'lists_get_from_end',\n          [ 'dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList, num x) {',\n            '  x = myList.length - x;',\n            '  return myList.removeAt(x);',\n            '}']);\n      code = functionName + '(' + list + ', ' + at + ')';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') {\n      var functionName = Blockly.Dart.provideFunction_(\n          'lists_remove_from_end',\n          [ 'dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList, num x) {',\n            '  x = myList.length - x;',\n            '  return myList.removeAt(x);',\n            '}']);\n      code = functionName + '(' + list + ', ' + at + ')';\n      if (mode == 'GET_REMOVE') {\n        return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n      } else if (mode == 'REMOVE') {\n        return code + ';\\n';\n      }\n    }\n  } else if (where == 'RANDOM') {\n    Blockly.Dart.definitions_['import_dart_math'] =\n        'import \\'dart:math\\' as Math;';\n    var functionName = Blockly.Dart.provideFunction_(\n        'lists_get_random_item',\n        [ 'dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n            '(List myList, bool remove) {',\n          '  int x = new Math.Random().nextInt(myList.length);',\n          '  if (remove) {',\n          '    return myList.removeAt(x);',\n          '  } else {',\n          '    return myList[x];',\n          '  }',\n          '}']);\n    code = functionName + '(' + list + ', ' + (mode != 'GET') + ')';\n    if (mode == 'GET' || mode == 'GET_REMOVE') {\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    } else if (mode == 'REMOVE') {\n      return code + ';\\n';\n    }\n  }\n  throw 'Unhandled combination (lists_getIndex).';\n};\n\nBlockly.Dart['lists_setIndex'] = function(block) {\n  // Set element at index.\n  // Note: Until February 2013 this block did not have MODE or WHERE inputs.\n  var list = Blockly.Dart.valueToCode(block, 'LIST',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';\n  var mode = block.getFieldValue('MODE') || 'GET';\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.Dart.valueToCode(block, 'AT',\n      Blockly.Dart.ORDER_ADDITIVE) || '1';\n  var value = Blockly.Dart.valueToCode(block, 'TO',\n      Blockly.Dart.ORDER_ASSIGNMENT) || 'null';\n  // Cache non-trivial values to variables to prevent repeated look-ups.\n  // Closure, which accesses and modifies 'list'.\n  function cacheList() {\n    if (list.match(/^\\w+$/)) {\n      return '';\n    }\n    var listVar = Blockly.Dart.variableDB_.getDistinctName(\n        'tmp_list', Blockly.Variables.NAME_TYPE);\n    var code = 'List ' + listVar + ' = ' + list + ';\\n';\n    list = listVar;\n    return code;\n  }\n  if (where == 'FIRST') {\n    if (mode == 'SET') {\n      return list + '[0] = ' + value + ';\\n';\n    } else if (mode == 'INSERT') {\n      return list + '.insert(0, ' + value + ');\\n';\n    }\n  } else if (where == 'LAST') {\n    if (mode == 'SET') {\n      var code = cacheList();\n      code += list + '[' + list + '.length - 1] = ' + value + ';\\n';\n      return code;\n    } else if (mode == 'INSERT') {\n      return list + '.add(' + value + ');\\n';\n    }\n  } else if (where == 'FROM_START') {\n    // Blockly uses one-based indicies.\n    if (Blockly.isNumber(at)) {\n      // If the index is a naked number, decrement it right now.\n      at = parseInt(at, 10) - 1;\n    } else {\n      // If the index is dynamic, decrement it in code.\n      at += ' - 1';\n    }\n    if (mode == 'SET') {\n      return list + '[' + at + '] = ' + value + ';\\n';\n    } else if (mode == 'INSERT') {\n      return list + '.insert(' + at + ', ' + value + ');\\n';\n    }\n  } else if (where == 'FROM_END') {\n    var code = cacheList();\n    if (mode == 'SET') {\n      code += list + '[' + list + '.length - ' + at + '] = ' + value + ';\\n';\n      return code;\n    } else if (mode == 'INSERT') {\n      code += list + '.insert(' + list + '.length - ' + at + ', ' +\n          value + ');\\n';\n      return code;\n    }\n  } else if (where == 'RANDOM') {\n    Blockly.Dart.definitions_['import_dart_math'] =\n        'import \\'dart:math\\' as Math;';\n    var code = cacheList();\n    var xVar = Blockly.Dart.variableDB_.getDistinctName(\n        'tmp_x', Blockly.Variables.NAME_TYPE);\n    code += 'int ' + xVar + ' = new Math.Random().nextInt(' + list + '.length);';\n    if (mode == 'SET') {\n      code += list + '[' + xVar + '] = ' + value + ';\\n';\n      return code;\n    } else if (mode == 'INSERT') {\n      code += list + '.insert(' + xVar + ', ' + value + ');\\n';\n      return code;\n    }\n  }\n  throw 'Unhandled combination (lists_setIndex).';\n};\n\nBlockly.Dart['lists_getSublist'] = function(block) {\n  // Get sublist.\n  var list = Blockly.Dart.valueToCode(block, 'LIST',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]';\n  var where1 = block.getFieldValue('WHERE1');\n  var where2 = block.getFieldValue('WHERE2');\n  var at1 = Blockly.Dart.valueToCode(block, 'AT1',\n      Blockly.Dart.ORDER_NONE) || '1';\n  var at2 = Blockly.Dart.valueToCode(block, 'AT2',\n      Blockly.Dart.ORDER_NONE) || '1';\n  if ((where1 == 'FIRST' || where1 == 'FROM_START' && Blockly.isNumber(at1)) &&\n      (where2 == 'LAST' || where2 == 'FROM_START' && Blockly.isNumber(at2))) {\n    // Simple case that can be done inline.\n    at1 = where1 == 'FIRST' ? 0 : parseInt(at1, 10) - 1;\n    if (where2 == 'LAST') {\n      code = list + '.sublist(' + at1 + ')';\n    } else {\n      at2 = parseInt(at2, 10);\n      code = list + '.sublist(' + at1 + ', ' + at2 + ')';\n    }\n  } else {\n    var functionName = Blockly.Dart.provideFunction_(\n        'lists_get_sublist',\n        [ 'List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n            '(list, where1, at1, where2, at2) {',\n          '  int getAt(where, at) {',\n          '    if (where == \\'FROM_START\\') {',\n          '      at--;',\n          '    } else if (where == \\'FROM_END\\') {',\n          '      at = list.length - at;',\n          '    } else if (where == \\'FIRST\\') {',\n          '      at = 0;',\n          '    } else if (where == \\'LAST\\') {',\n          '      at = list.length - 1;',\n          '    } else {',\n          '      throw \\'Unhandled option (lists_getSublist).\\';',\n          '    }',\n          '    return at;',\n          '  }',\n          '  at1 = getAt(where1, at1);',\n          '  at2 = getAt(where2, at2) + 1;',\n          '  return list.sublist(at1, at2);',\n          '}']);\n    var code = functionName + '(' + list + ', \\'' +\n        where1 + '\\', ' + at1 + ', \\'' + where2 + '\\', ' + at2 + ')';\n  }\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n"
  },
  {
    "path": "extern/blockly/generators/dart/logic.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for logic blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart.logic');\n\ngoog.require('Blockly.Dart');\n\n\nBlockly.Dart['controls_if'] = function(block) {\n  // If/elseif/else condition.\n  var n = 0;\n  var argument = Blockly.Dart.valueToCode(block, 'IF' + n,\n      Blockly.Dart.ORDER_NONE) || 'false';\n  var branch = Blockly.Dart.statementToCode(block, 'DO' + n);\n  var code = 'if (' + argument + ') {\\n' + branch + '}';\n  for (n = 1; n <= block.elseifCount_; n++) {\n    argument = Blockly.Dart.valueToCode(block, 'IF' + n,\n      Blockly.Dart.ORDER_NONE) || 'false';\n    branch = Blockly.Dart.statementToCode(block, 'DO' + n);\n    code += ' else if (' + argument + ') {\\n' + branch + '}';\n  }\n  if (block.elseCount_) {\n    branch = Blockly.Dart.statementToCode(block, 'ELSE');\n    code += ' else {\\n' + branch + '}';\n  }\n  return code + '\\n';\n};\n\nBlockly.Dart['logic_compare'] = function(block) {\n  // Comparison operator.\n  var OPERATORS = {\n    EQ: '==',\n    NEQ: '!=',\n    LT: '<',\n    LTE: '<=',\n    GT: '>',\n    GTE: '>='\n  };\n  var operator = OPERATORS[block.getFieldValue('OP')];\n  var order = (operator == '==' || operator == '!=') ?\n      Blockly.Dart.ORDER_EQUALITY : Blockly.Dart.ORDER_RELATIONAL;\n  var argument0 = Blockly.Dart.valueToCode(block, 'A', order) || '0';\n  var argument1 = Blockly.Dart.valueToCode(block, 'B', order) || '0';\n  var code = argument0 + ' ' + operator + ' ' + argument1;\n  return [code, order];\n};\n\nBlockly.Dart['logic_operation'] = function(block) {\n  // Operations 'and', 'or'.\n  var operator = (block.getFieldValue('OP') == 'AND') ? '&&' : '||';\n  var order = (operator == '&&') ? Blockly.Dart.ORDER_LOGICAL_AND :\n      Blockly.Dart.ORDER_LOGICAL_OR;\n  var argument0 = Blockly.Dart.valueToCode(block, 'A', order);\n  var argument1 = Blockly.Dart.valueToCode(block, 'B', order);\n  if (!argument0 && !argument1) {\n    // If there are no arguments, then the return value is false.\n    argument0 = 'false';\n    argument1 = 'false';\n  } else {\n    // Single missing arguments have no effect on the return value.\n    var defaultArgument = (operator == '&&') ? 'true' : 'false';\n    if (!argument0) {\n      argument0 = defaultArgument;\n    }\n    if (!argument1) {\n      argument1 = defaultArgument;\n    }\n  }\n  var code = argument0 + ' ' + operator + ' ' + argument1;\n  return [code, order];\n};\n\nBlockly.Dart['logic_negate'] = function(block) {\n  // Negation.\n  var order = Blockly.Dart.ORDER_UNARY_PREFIX;\n  var argument0 = Blockly.Dart.valueToCode(block, 'BOOL', order) || 'true';\n  var code = '!' + argument0;\n  return [code, order];\n};\n\nBlockly.Dart['logic_boolean'] = function(block) {\n  // Boolean values true and false.\n  var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'true' : 'false';\n  return [code, Blockly.Dart.ORDER_ATOMIC];\n};\n\nBlockly.Dart['logic_null'] = function(block) {\n  // Null data type.\n  return ['null', Blockly.Dart.ORDER_ATOMIC];\n};\n\nBlockly.Dart['logic_ternary'] = function(block) {\n  // Ternary operator.\n  var value_if = Blockly.Dart.valueToCode(block, 'IF',\n      Blockly.Dart.ORDER_CONDITIONAL) || 'false';\n  var value_then = Blockly.Dart.valueToCode(block, 'THEN',\n      Blockly.Dart.ORDER_CONDITIONAL) || 'null';\n  var value_else = Blockly.Dart.valueToCode(block, 'ELSE',\n      Blockly.Dart.ORDER_CONDITIONAL) || 'null';\n  var code = value_if + ' ? ' + value_then + ' : ' + value_else\n  return [code, Blockly.Dart.ORDER_CONDITIONAL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/dart/loops.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for loop blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart.loops');\n\ngoog.require('Blockly.Dart');\n\n\nBlockly.Dart['controls_repeat'] = function(block) {\n  // Repeat n times (internal number).\n  var repeats = Number(block.getFieldValue('TIMES'));\n  var branch = Blockly.Dart.statementToCode(block, 'DO');\n  if (Blockly.Dart.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var loopVar = Blockly.Dart.variableDB_.getDistinctName(\n      'count', Blockly.Variables.NAME_TYPE);\n  var code = 'for (int ' + loopVar + ' = 0; ' +\n      loopVar + ' < ' + repeats + '; ' +\n      loopVar + '++) {\\n' +\n      branch + '}\\n';\n  return code;\n};\n\nBlockly.Dart['controls_repeat_ext'] = function(block) {\n  // Repeat n times (external number).\n  var repeats = Blockly.Dart.valueToCode(block, 'TIMES',\n      Blockly.Dart.ORDER_ASSIGNMENT) || '0';\n  var branch = Blockly.Dart.statementToCode(block, 'DO');\n  if (Blockly.Dart.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var code = '';\n  var loopVar = Blockly.Dart.variableDB_.getDistinctName(\n      'count', Blockly.Variables.NAME_TYPE);\n  var endVar = repeats;\n  if (!repeats.match(/^\\w+$/) && !Blockly.isNumber(repeats)) {\n    var endVar = Blockly.Dart.variableDB_.getDistinctName(\n        'repeat_end', Blockly.Variables.NAME_TYPE);\n    code += 'var ' + endVar + ' = ' + repeats + ';\\n';\n  }\n  code += 'for (int ' + loopVar + ' = 0; ' +\n      loopVar + ' < ' + endVar + '; ' +\n      loopVar + '++) {\\n' +\n      branch + '}\\n';\n  return code;\n};\n\nBlockly.Dart['controls_whileUntil'] = function(block) {\n  // Do while/until loop.\n  var until = block.getFieldValue('MODE') == 'UNTIL';\n  var argument0 = Blockly.Dart.valueToCode(block, 'BOOL',\n      until ? Blockly.Dart.ORDER_UNARY_PREFIX :\n      Blockly.Dart.ORDER_NONE) || 'false';\n  var branch = Blockly.Dart.statementToCode(block, 'DO');\n  if (Blockly.Dart.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  if (until) {\n    argument0 = '!' + argument0;\n  }\n  return 'while (' + argument0 + ') {\\n' + branch + '}\\n';\n};\n\nBlockly.Dart['controls_for'] = function(block) {\n  // For loop.\n  var variable0 = Blockly.Dart.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.Dart.valueToCode(block, 'FROM',\n      Blockly.Dart.ORDER_ASSIGNMENT) || '0';\n  var argument1 = Blockly.Dart.valueToCode(block, 'TO',\n      Blockly.Dart.ORDER_ASSIGNMENT) || '0';\n  var increment = Blockly.Dart.valueToCode(block, 'BY',\n      Blockly.Dart.ORDER_ASSIGNMENT) || '1';\n  var branch = Blockly.Dart.statementToCode(block, 'DO');\n  if (Blockly.Dart.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var code;\n  if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) &&\n      Blockly.isNumber(increment)) {\n    // All arguments are simple numbers.\n    var up = parseFloat(argument0) <= parseFloat(argument1);\n    code = 'for (' + variable0 + ' = ' + argument0 + '; ' +\n        variable0 + (up ? ' <= ' : ' >= ') + argument1 + '; ' +\n        variable0;\n    var step = Math.abs(parseFloat(increment));\n    if (step == 1) {\n      code += up ? '++' : '--';\n    } else {\n      code += (up ? ' += ' : ' -= ') + step;\n    }\n    code += ') {\\n' + branch + '}\\n';\n  } else {\n    code = '';\n    // Cache non-trivial values to variables to prevent repeated look-ups.\n    var startVar = argument0;\n    if (!argument0.match(/^\\w+$/) && !Blockly.isNumber(argument0)) {\n      var startVar = Blockly.Dart.variableDB_.getDistinctName(\n          variable0 + '_start', Blockly.Variables.NAME_TYPE);\n      code += 'var ' + startVar + ' = ' + argument0 + ';\\n';\n    }\n    var endVar = argument1;\n    if (!argument1.match(/^\\w+$/) && !Blockly.isNumber(argument1)) {\n      var endVar = Blockly.Dart.variableDB_.getDistinctName(\n          variable0 + '_end', Blockly.Variables.NAME_TYPE);\n      code += 'var ' + endVar + ' = ' + argument1 + ';\\n';\n    }\n    // Determine loop direction at start, in case one of the bounds\n    // changes during loop execution.\n    var incVar = Blockly.Dart.variableDB_.getDistinctName(\n        variable0 + '_inc', Blockly.Variables.NAME_TYPE);\n    code += 'num ' + incVar + ' = ';\n    if (Blockly.isNumber(increment)) {\n      code += Math.abs(increment) + ';\\n';\n    } else {\n      code += '(' + increment + ').abs();\\n';\n    }\n    code += 'if (' + startVar + ' > ' + endVar + ') {\\n';\n    code += '  ' + incVar + ' = -' + incVar +';\\n';\n    code += '}\\n';\n    code += 'for (' + variable0 + ' = ' + startVar + ';\\n' +\n        '     '  + incVar + ' >= 0 ? ' +\n        variable0 + ' <= ' + endVar + ' : ' +\n        variable0 + ' >= ' + endVar + ';\\n' +\n        '     ' + variable0 + ' += ' + incVar + ') {\\n' +\n        branch + '}\\n';\n  }\n  return code;\n};\n\nBlockly.Dart['controls_forEach'] = function(block) {\n  // For each loop.\n  var variable0 = Blockly.Dart.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.Dart.valueToCode(block, 'LIST',\n      Blockly.Dart.ORDER_ASSIGNMENT) || '[]';\n  var branch = Blockly.Dart.statementToCode(block, 'DO');\n  if (Blockly.Dart.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var code = 'for (var ' + variable0 + ' in  ' + argument0 + ') {\\n' +\n      branch + '}\\n';\n  return code;\n};\n\nBlockly.Dart['controls_flow_statements'] = function(block) {\n  // Flow statements: continue, break.\n  switch (block.getFieldValue('FLOW')) {\n    case 'BREAK':\n      return 'break;\\n';\n    case 'CONTINUE':\n      return 'continue;\\n';\n  }\n  throw 'Unknown flow statement.';\n};\n"
  },
  {
    "path": "extern/blockly/generators/dart/math.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for math blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart.math');\n\ngoog.require('Blockly.Dart');\n\n\nBlockly.Dart.addReservedWords('Math');\n\nBlockly.Dart['math_number'] = function(block) {\n  // Numeric value.\n  var code = window.parseFloat(block.getFieldValue('NUM'));\n  // -4.abs() returns -4 in Dart due to strange order of operation choices.\n  // -4 is actually an operator and a number.  Reflect this in the order.\n  var order = code < 0 ?\n      Blockly.Dart.ORDER_UNARY_PREFIX : Blockly.Dart.ORDER_ATOMIC;\n  return [code, order];\n};\n\nBlockly.Dart['math_arithmetic'] = function(block) {\n  // Basic arithmetic operators, and power.\n  var OPERATORS = {\n    ADD: [' + ', Blockly.Dart.ORDER_ADDITIVE],\n    MINUS: [' - ', Blockly.Dart.ORDER_ADDITIVE],\n    MULTIPLY: [' * ', Blockly.Dart.ORDER_MULTIPLICATIVE],\n    DIVIDE: [' / ', Blockly.Dart.ORDER_MULTIPLICATIVE],\n    POWER: [null, Blockly.Dart.ORDER_NONE]  // Handle power separately.\n  };\n  var tuple = OPERATORS[block.getFieldValue('OP')];\n  var operator = tuple[0];\n  var order = tuple[1];\n  var argument0 = Blockly.Dart.valueToCode(block, 'A', order) || '0';\n  var argument1 = Blockly.Dart.valueToCode(block, 'B', order) || '0';\n  var code;\n  // Power in Dart requires a special case since it has no operator.\n  if (!operator) {\n    Blockly.Dart.definitions_['import_dart_math'] =\n        'import \\'dart:math\\' as Math;';\n    code = 'Math.pow(' + argument0 + ', ' + argument1 + ')';\n    return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n  }\n  code = argument0 + operator + argument1;\n  return [code, order];\n};\n\nBlockly.Dart['math_single'] = function(block) {\n  // Math operators with single operand.\n  var operator = block.getFieldValue('OP');\n  var code;\n  var arg;\n  if (operator == 'NEG') {\n    // Negation is a special case given its different operator precedence.\n    arg = Blockly.Dart.valueToCode(block, 'NUM',\n        Blockly.Dart.ORDER_UNARY_PREFIX) || '0';\n    if (arg[0] == '-') {\n      // --3 is not legal in Dart.\n      arg = ' ' + arg;\n    }\n    code = '-' + arg;\n    return [code, Blockly.Dart.ORDER_UNARY_PREFIX];\n  }\n  Blockly.Dart.definitions_['import_dart_math'] =\n      'import \\'dart:math\\' as Math;';\n  if (operator == 'ABS' || operator.substring(0, 5) == 'ROUND') {\n    arg = Blockly.Dart.valueToCode(block, 'NUM',\n        Blockly.Dart.ORDER_UNARY_POSTFIX) || '0';\n  } else if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') {\n    arg = Blockly.Dart.valueToCode(block, 'NUM',\n        Blockly.Dart.ORDER_MULTIPLICATIVE) || '0';\n  } else {\n    arg = Blockly.Dart.valueToCode(block, 'NUM',\n        Blockly.Dart.ORDER_NONE) || '0';\n  }\n  // First, handle cases which generate values that don't need parentheses\n  // wrapping the code.\n  switch (operator) {\n    case 'ABS':\n      code = arg + '.abs()';\n      break;\n    case 'ROOT':\n      code = 'Math.sqrt(' + arg + ')';\n      break;\n    case 'LN':\n      code = 'Math.log(' + arg + ')';\n      break;\n    case 'EXP':\n      code = 'Math.exp(' + arg + ')';\n      break;\n    case 'POW10':\n      code = 'Math.pow(10,' + arg + ')';\n      break;\n    case 'ROUND':\n      code = arg + '.round()';\n      break;\n    case 'ROUNDUP':\n      code = arg + '.ceil()';\n      break;\n    case 'ROUNDDOWN':\n      code = arg + '.floor()';\n      break;\n    case 'SIN':\n      code = 'Math.sin(' + arg + ' / 180 * Math.PI)';\n      break;\n    case 'COS':\n      code = 'Math.cos(' + arg + ' / 180 * Math.PI)';\n      break;\n    case 'TAN':\n      code = 'Math.tan(' + arg + ' / 180 * Math.PI)';\n      break;\n  }\n  if (code) {\n    return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n  }\n  // Second, handle cases which generate values that may need parentheses\n  // wrapping the code.\n  switch (operator) {\n    case 'LOG10':\n      code = 'Math.log(' + arg + ') / Math.log(10)';\n      break;\n    case 'ASIN':\n      code = 'Math.asin(' + arg + ') / Math.PI * 180';\n      break;\n    case 'ACOS':\n      code = 'Math.acos(' + arg + ') / Math.PI * 180';\n      break;\n    case 'ATAN':\n      code = 'Math.atan(' + arg + ') / Math.PI * 180';\n      break;\n    default:\n      throw 'Unknown math operator: ' + operator;\n  }\n  return [code, Blockly.Dart.ORDER_MULTIPLICATIVE];\n};\n\nBlockly.Dart['math_constant'] = function(block) {\n  // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.\n  var CONSTANTS = {\n    PI: ['Math.PI', Blockly.Dart.ORDER_UNARY_POSTFIX],\n    E: ['Math.E', Blockly.Dart.ORDER_UNARY_POSTFIX],\n    GOLDEN_RATIO: ['(1 + Math.sqrt(5)) / 2', Blockly.Dart.ORDER_MULTIPLICATIVE],\n    SQRT2: ['Math.SQRT2', Blockly.Dart.ORDER_UNARY_POSTFIX],\n    SQRT1_2: ['Math.SQRT1_2', Blockly.Dart.ORDER_UNARY_POSTFIX],\n    INFINITY: ['double.INFINITY', Blockly.Dart.ORDER_ATOMIC]\n  };\n  var constant = block.getFieldValue('CONSTANT');\n  if (constant != 'INFINITY') {\n    Blockly.Dart.definitions_['import_dart_math'] =\n        'import \\'dart:math\\' as Math;';\n  }\n  return CONSTANTS[constant];\n};\n\nBlockly.Dart['math_number_property'] = function(block) {\n  // Check if a number is even, odd, prime, whole, positive, or negative\n  // or if it is divisible by certain number. Returns true or false.\n  var number_to_check = Blockly.Dart.valueToCode(block, 'NUMBER_TO_CHECK',\n      Blockly.Dart.ORDER_MULTIPLICATIVE);\n  if (!number_to_check) {\n    return ['false', Blockly.Python.ORDER_ATOMIC];\n  }\n  var dropdown_property = block.getFieldValue('PROPERTY');\n  var code;\n  if (dropdown_property == 'PRIME') {\n    // Prime is a special case as it is not a one-liner test.\n    Blockly.Dart.definitions_['import_dart_math'] =\n        'import \\'dart:math\\' as Math;';\n    var functionName = Blockly.Dart.provideFunction_(\n        'math_isPrime',\n        [ 'bool ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '(n) {',\n          '  // https://en.wikipedia.org/wiki/Primality_test#Naive_methods',\n          '  if (n == 2 || n == 3) {',\n          '    return true;',\n          '  }',\n          '  // False if n is null, negative, is 1, or not whole.',\n          '  // And false if n is divisible by 2 or 3.',\n          '  if (n == null || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' +\n            ' n % 3 == 0) {',\n          '    return false;',\n          '  }',\n          '  // Check all the numbers of form 6k +/- 1, up to sqrt(n).',\n          '  for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {',\n          '    if (n % (x - 1) == 0 || n % (x + 1) == 0) {',\n          '      return false;',\n          '    }',\n          '  }',\n          '  return true;',\n          '}']);\n    code = functionName + '(' + number_to_check + ')';\n    return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n  }\n  switch (dropdown_property) {\n    case 'EVEN':\n      code = number_to_check + ' % 2 == 0';\n      break;\n    case 'ODD':\n      code = number_to_check + ' % 2 == 1';\n      break;\n    case 'WHOLE':\n      code = number_to_check + ' % 1 == 0';\n      break;\n    case 'POSITIVE':\n      code = number_to_check + ' > 0';\n      break;\n    case 'NEGATIVE':\n      code = number_to_check + ' < 0';\n      break;\n    case 'DIVISIBLE_BY':\n      var divisor = Blockly.Dart.valueToCode(block, 'DIVISOR',\n          Blockly.Dart.ORDER_MULTIPLICATIVE);\n      if (!divisor) {\n        return ['false', Blockly.Python.ORDER_ATOMIC];\n      }\n      code = number_to_check + ' % ' + divisor + ' == 0';\n      break;\n  }\n  return [code, Blockly.Dart.ORDER_EQUALITY];\n};\n\nBlockly.Dart['math_change'] = function(block) {\n  // Add to a variable in place.\n  var argument0 = Blockly.Dart.valueToCode(block, 'DELTA',\n      Blockly.Dart.ORDER_ADDITIVE) || '0';\n  var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  return varName + ' = (' + varName + ' is num ? ' + varName + ' : 0) + ' +\n      argument0 + ';\\n';\n};\n\n// Rounding functions have a single operand.\nBlockly.Dart['math_round'] = Blockly.Dart['math_single'];\n// Trigonometry functions have a single operand.\nBlockly.Dart['math_trig'] = Blockly.Dart['math_single'];\n\nBlockly.Dart['math_on_list'] = function(block) {\n  // Math functions for lists.\n  var func = block.getFieldValue('OP');\n  var list = Blockly.Dart.valueToCode(block, 'LIST',\n      Blockly.Dart.ORDER_NONE) || '[]';\n  var code;\n  switch (func) {\n    case 'SUM':\n      var functionName = Blockly.Dart.provideFunction_(\n          'math_sum',\n          [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList) {',\n            '  num sumVal = 0;',\n            '  myList.forEach((num entry) {sumVal += entry;});',\n            '  return sumVal;',\n            '}']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'MIN':\n      Blockly.Dart.definitions_['import_dart_math'] =\n          'import \\'dart:math\\' as Math;';\n      var functionName = Blockly.Dart.provideFunction_(\n          'math_min',\n          [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList) {',\n            '  if (myList.isEmpty) return null;',\n            '  num minVal = myList[0];',\n            '  myList.forEach((num entry) ' +\n              '{minVal = Math.min(minVal, entry);});',\n            '  return minVal;',\n            '}']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'MAX':\n      Blockly.Dart.definitions_['import_dart_math'] =\n          'import \\'dart:math\\' as Math;';\n      var functionName = Blockly.Dart.provideFunction_(\n          'math_max',\n          [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList) {',\n            '  if (myList.isEmpty) return null;',\n            '  num maxVal = myList[0];',\n            '  myList.forEach((num entry) ' +\n                  '{maxVal = Math.max(maxVal, entry);});',\n            '  return maxVal;',\n            '}']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'AVERAGE':\n      // This operation exclude null and values that are not int or float:\n      //   math_mean([null,null,\"aString\",1,9]) == 5.0.\n      var functionName = Blockly.Dart.provideFunction_(\n          'math_average',\n          [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList) {',\n            '  // First filter list for numbers only.',\n            '  List localList = new List.from(myList);',\n            '  localList.removeMatching((a) => a is! num);',\n            '  if (localList.isEmpty) return null;',\n            '  num sumVal = 0;',\n            '  localList.forEach((num entry) {sumVal += entry;});',\n            '  return sumVal / localList.length;',\n            '}']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'MEDIAN':\n      var functionName = Blockly.Dart.provideFunction_(\n          'math_median',\n          [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList) {',\n            '  // First filter list for numbers only, then sort, ' +\n              'then return middle value',\n            '  // or the average of two middle values if list has an ' +\n              'even number of elements.',\n            '  List localList = new List.from(myList);',\n            '  localList.removeMatching((a) => a is! num);',\n            '  if (localList.isEmpty) return null;',\n            '  localList.sort((a, b) => (a - b));',\n            '  int index = localList.length ~/ 2;',\n            '  if (localList.length % 2 == 1) {',\n            '    return localList[index];',\n            '  } else {',\n            '    return (localList[index - 1] + localList[index]) / 2;',\n            '  }',\n            '}']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'MODE':\n      Blockly.Dart.definitions_['import_dart_math'] =\n          'import \\'dart:math\\' as Math;';\n      // As a list of numbers can contain more than one mode,\n      // the returned result is provided as an array.\n      // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].\n      var functionName = Blockly.Dart.provideFunction_(\n          'math_modes',\n          [ 'List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List values) {',\n            '  List modes = [];',\n            '  List counts = [];',\n            '  int maxCount = 0;',\n            '  for (int i = 0; i < values.length; i++) {',\n            '    var value = values[i];',\n            '    bool found = false;',\n            '    int thisCount;',\n            '    for (int j = 0; j < counts.length; j++) {',\n            '      if (counts[j][0] == value) {',\n            '        thisCount = ++counts[j][1];',\n            '        found = true;',\n            '        break;',\n            '      }',\n            '    }',\n            '    if (!found) {',\n            '      counts.add([value, 1]);',\n            '      thisCount = 1;',\n            '    }',\n            '    maxCount = Math.max(thisCount, maxCount);',\n            '  }',\n            '  for (int j = 0; j < counts.length; j++) {',\n            '    if (counts[j][1] == maxCount) {',\n            '        modes.add(counts[j][0]);',\n            '    }',\n            '  }',\n            '  return modes;',\n            '}']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'STD_DEV':\n      Blockly.Dart.definitions_['import_dart_math'] =\n          'import \\'dart:math\\' as Math;';\n      var functionName = Blockly.Dart.provideFunction_(\n          'math_standard_deviation',\n          [ 'num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList) {',\n            '  // First filter list for numbers only.',\n            '  List numbers = new List.from(myList);',\n            '  numbers.removeMatching((a) => a is! num);',\n            '  if (numbers.isEmpty) return null;',\n            '  num n = numbers.length;',\n            '  num sum = 0;',\n            '  numbers.forEach((x) => sum += x);',\n            '  num mean = sum / n;',\n            '  num sumSquare = 0;',\n            '  numbers.forEach((x) => sumSquare += ' +\n                  'Math.pow(x - mean, 2));',\n            '  return Math.sqrt(sumSquare / n);',\n            '}']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'RANDOM':\n      Blockly.Dart.definitions_['import_dart_math'] =\n          'import \\'dart:math\\' as Math;';\n      var functionName = Blockly.Dart.provideFunction_(\n          'math_random_item',\n          [ 'dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(List myList) {',\n            '  int x = new Math.Random().nextInt(myList.length);',\n            '  return myList[x];',\n            '}']);\n      code = functionName + '(' + list + ')';\n      break;\n    default:\n      throw 'Unknown operator: ' + func;\n  }\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['math_modulo'] = function(block) {\n  // Remainder computation.\n  var argument0 = Blockly.Dart.valueToCode(block, 'DIVIDEND',\n      Blockly.Dart.ORDER_MULTIPLICATIVE) || '0';\n  var argument1 = Blockly.Dart.valueToCode(block, 'DIVISOR',\n      Blockly.Dart.ORDER_MULTIPLICATIVE) || '0';\n  var code = argument0 + ' % ' + argument1;\n  return [code, Blockly.Dart.ORDER_MULTIPLICATIVE];\n};\n\nBlockly.Dart['math_constrain'] = function(block) {\n  // Constrain a number between two limits.\n  Blockly.Dart.definitions_['import_dart_math'] =\n      'import \\'dart:math\\' as Math;';\n  var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_NONE) || '0';\n  var argument1 = Blockly.Dart.valueToCode(block, 'LOW',\n      Blockly.Dart.ORDER_NONE) || '0';\n  var argument2 = Blockly.Dart.valueToCode(block, 'HIGH',\n      Blockly.Dart.ORDER_NONE) || 'double.INFINITY';\n  var code = 'Math.min(Math.max(' + argument0 + ', ' + argument1 + '), ' +\n      argument2 + ')';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['math_random_int'] = function(block) {\n  // Random integer between [X] and [Y].\n  Blockly.Dart.definitions_['import_dart_math'] =\n      'import \\'dart:math\\' as Math;';\n  var argument0 = Blockly.Dart.valueToCode(block, 'FROM',\n      Blockly.Dart.ORDER_NONE) || '0';\n  var argument1 = Blockly.Dart.valueToCode(block, 'TO',\n      Blockly.Dart.ORDER_NONE) || '0';\n  var functionName = Blockly.Dart.provideFunction_(\n      'math_random_int',\n      [ 'int ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '(num a, num b) {',\n        '  if (a > b) {',\n        '    // Swap a and b to ensure a is smaller.',\n        '    num c = a;',\n        '    a = b;',\n        '    b = c;',\n        '  }',\n        '  return new Math.Random().nextInt(b - a + 1) + a;',\n        '}']);\n  var code = functionName + '(' + argument0 + ', ' + argument1 + ')';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['math_random_float'] = function(block) {\n  // Random fraction between 0 and 1.\n  Blockly.Dart.definitions_['import_dart_math'] =\n      'import \\'dart:math\\' as Math;';\n  return ['new Math.Random().nextDouble()', Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n"
  },
  {
    "path": "extern/blockly/generators/dart/procedures.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for procedure blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart.procedures');\n\ngoog.require('Blockly.Dart');\n\n\nBlockly.Dart['procedures_defreturn'] = function(block) {\n  // Define a procedure with a return value.\n  var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'),\n      Blockly.Procedures.NAME_TYPE);\n  var branch = Blockly.Dart.statementToCode(block, 'STACK');\n  if (Blockly.Dart.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var returnValue = Blockly.Dart.valueToCode(block, 'RETURN',\n      Blockly.Dart.ORDER_NONE) || '';\n  if (returnValue) {\n    returnValue = '  return ' + returnValue + ';\\n';\n  }\n  var returnType = returnValue ? 'dynamic' : 'void';\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.Dart.variableDB_.getName(block.arguments_[x],\n        Blockly.Variables.NAME_TYPE);\n  }\n  var code = returnType + ' ' + funcName + '(' + args.join(', ') + ') {\\n' +\n      branch + returnValue + '}';\n  code = Blockly.Dart.scrub_(block, code);\n  Blockly.Dart.definitions_[funcName] = code;\n  return null;\n};\n\n// Defining a procedure without a return value uses the same generator as\n// a procedure with a return value.\nBlockly.Dart['procedures_defnoreturn'] = Blockly.Dart['procedures_defreturn'];\n\nBlockly.Dart['procedures_callreturn'] = function(block) {\n  // Call a procedure with a return value.\n  var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'),\n      Blockly.Procedures.NAME_TYPE);\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.Dart.valueToCode(block, 'ARG' + x,\n        Blockly.Dart.ORDER_NONE) || 'null';\n  }\n  var code = funcName + '(' + args.join(', ') + ')';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['procedures_callnoreturn'] = function(block) {\n  // Call a procedure with no return value.\n  var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'),\n      Blockly.Procedures.NAME_TYPE);\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.Dart.valueToCode(block, 'ARG' + x,\n        Blockly.Dart.ORDER_NONE) || 'null';\n  }\n  var code = funcName + '(' + args.join(', ') + ');\\n';\n  return code;\n};\n\nBlockly.Dart['procedures_ifreturn'] = function(block) {\n  // Conditionally return value from a procedure.\n  var condition = Blockly.Dart.valueToCode(block, 'CONDITION',\n      Blockly.Dart.ORDER_NONE) || 'false';\n  var code = 'if (' + condition + ') {\\n';\n  if (block.hasReturnValue_) {\n    var value = Blockly.Dart.valueToCode(block, 'VALUE',\n        Blockly.Dart.ORDER_NONE) || 'null';\n    code += '  return ' + value + ';\\n';\n  } else {\n    code += '  return;\\n';\n  }\n  code += '}\\n';\n  return code;\n};\n"
  },
  {
    "path": "extern/blockly/generators/dart/text.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for text blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart.text');\n\ngoog.require('Blockly.Dart');\n\n\nBlockly.Dart.addReservedWords('Html,Math');\n\nBlockly.Dart['text'] = function(block) {\n  // Text value.\n  var code = Blockly.Dart.quote_(block.getFieldValue('TEXT'));\n  return [code, Blockly.Dart.ORDER_ATOMIC];\n};\n\nBlockly.Dart['text_join'] = function(block) {\n  // Create a string made up of any number of elements of any type.\n  var code;\n  if (block.itemCount_ == 0) {\n    return ['\\'\\'', Blockly.Dart.ORDER_ATOMIC];\n  } else if (block.itemCount_ == 1) {\n    var argument0 = Blockly.Dart.valueToCode(block, 'ADD0',\n        Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n    code = argument0 + '.toString()';\n    return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n  } else {\n    code = new Array(block.itemCount_);\n    for (var n = 0; n < block.itemCount_; n++) {\n      code[n] = Blockly.Dart.valueToCode(block, 'ADD' + n,\n          Blockly.Dart.ORDER_NONE) || '\\'\\'';\n    }\n    code = '[' + code.join(',') + '].join()';\n    return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n  }\n};\n\nBlockly.Dart['text_append'] = function(block) {\n  // Append to a variable in place.\n  var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n  return varName + ' = [' + varName + ', ' + argument0 + '].join();\\n';\n};\n\nBlockly.Dart['text_length'] = function(block) {\n  // String length.\n  var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n  return [argument0 + '.length', Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['text_isEmpty'] = function(block) {\n  // Is the string null?\n  var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n  return [argument0 + '.isEmpty', Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['text_indexOf'] = function(block) {\n  // Search the text for a substring.\n  var operator = block.getFieldValue('END') == 'FIRST' ?\n      'indexOf' : 'lastIndexOf';\n  var argument0 = Blockly.Dart.valueToCode(block, 'FIND',\n      Blockly.Dart.ORDER_NONE) || '\\'\\'';\n  var argument1 = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n  var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['text_charAt'] = function(block) {\n  // Get letter at index.\n  // Note: Until January 2013 this block did not have the WHERE input.\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.Dart.valueToCode(block, 'AT',\n      Blockly.Dart.ORDER_NONE) || '1';\n  var text = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n  switch (where) {\n    case 'FIRST':\n      var code = text + '[0]';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    case 'FROM_START':\n      // Blockly uses one-based indicies.\n      if (at.match(/^-?\\d+$/)) {\n        // If the index is a naked number, decrement it right now.\n        at = parseInt(at, 10) - 1;\n      } else {\n        // If the index is dynamic, decrement it in code.\n        at += ' - 1';\n      }\n      var code = text + '[' + at + ']';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    case 'LAST':\n      at = 1;\n      // Fall through.\n    case 'FROM_END':\n      var functionName = Blockly.Dart.provideFunction_(\n          'text_get_from_end',\n          [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(String text, num x) {',\n            '  return text[text.length - x];',\n            '}']);\n      code = functionName + '(' + text + ', ' + at + ')';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n    case 'RANDOM':\n      Blockly.Dart.definitions_['import_dart_math'] =\n          'import \\'dart:math\\' as Math;';\n      var functionName = Blockly.Dart.provideFunction_(\n          'text_random_letter',\n          [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n              '(String text) {',\n            '  int x = new Math.Random().nextInt(text.length);',\n            '  return text[x];',\n            '}']);\n      code = functionName + '(' + text + ')';\n      return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n  }\n  throw 'Unhandled option (text_charAt).';\n};\n\nBlockly.Dart['text_getSubstring'] = function(block) {\n  // Get substring.\n  var text = Blockly.Dart.valueToCode(block, 'STRING',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n  var where1 = block.getFieldValue('WHERE1');\n  var where2 = block.getFieldValue('WHERE2');\n  var at1 = Blockly.Dart.valueToCode(block, 'AT1',\n      Blockly.Dart.ORDER_NONE) || '1';\n  var at2 = Blockly.Dart.valueToCode(block, 'AT2',\n      Blockly.Dart.ORDER_NONE) || '1';\n  if (where1 == 'FIRST' && where2 == 'LAST') {\n    var code = text;\n  } else {\n    var functionName = Blockly.Dart.provideFunction_(\n        'text_get_substring',\n        [ 'function ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n            '(text, where1, at1, where2, at2) {',\n          '  function getAt(where, at) {',\n          '    if (where == \\'FROM_START\\') {',\n          '      at--;',\n          '    } else if (where == \\'FROM_END\\') {',\n          '      at = text.length - at;',\n          '    } else if (where == \\'FIRST\\') {',\n          '      at = 0;',\n          '    } else if (where == \\'LAST\\') {',\n          '      at = text.length - 1;',\n          '    } else {',\n          '      throw \\'Unhandled option (text_getSubstring).\\';',\n          '    }',\n          '    return at;',\n          '  }',\n          '  at1 = getAt(where1, at1);',\n          '  at2 = getAt(where2, at2) + 1;',\n          '  return text.substring(at1, at2);',\n          '}']);\n    var code = functionName + '(' + text + ', \\'' +\n        where1 + '\\', ' + at1 + ', \\'' + where2 + '\\', ' + at2 + ')';\n  }\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['text_changeCase'] = function(block) {\n  // Change capitalization.\n  var OPERATORS = {\n    UPPERCASE: '.toUpperCase()',\n    LOWERCASE: '.toLowerCase()',\n    TITLECASE: null\n  };\n  var operator = OPERATORS[block.getFieldValue('CASE')];\n  var code;\n  if (operator) {\n    // Upper and lower case are functions built into Dart.\n    var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',\n        Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n    code = argument0 + operator;\n  } else {\n    // Title case is not a native Dart function.  Define one.\n    var functionName = Blockly.Dart.provideFunction_(\n        'text_toTitleCase',\n        [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n            '(String str) {',\n          '  RegExp exp = new RegExp(r\\'\\\\b\\');',\n          '  List<String> list = str.split(exp);',\n          '  final title = new StringBuffer();',\n          '  for (String part in list) {',\n          '    if (part.length > 0) {',\n          '      title.write(part[0].toUpperCase());',\n          '      if (part.length > 0) {',\n          '        title.write(part.substring(1).toLowerCase());',\n          '      }',\n          '    }',\n          '  }',\n          '  return title.toString();',\n          '}']);\n    var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',\n        Blockly.Dart.ORDER_NONE) || '\\'\\'';\n    code = functionName + '(' + argument0 + ')';\n  }\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['text_trim'] = function(block) {\n  // Trim spaces.\n  var OPERATORS = {\n    LEFT: '.replaceFirst(new RegExp(r\\'^\\\\s+\\'), \\'\\')',\n    RIGHT: '.replaceFirst(new RegExp(r\\'\\\\s+$\\'), \\'\\')',\n    BOTH: '.trim()'\n  };\n  var operator = OPERATORS[block.getFieldValue('MODE')];\n  var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',\n      Blockly.Dart.ORDER_UNARY_POSTFIX) || '\\'\\'';\n  return [argument0 + operator, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n\nBlockly.Dart['text_print'] = function(block) {\n  // Print statement.\n  var argument0 = Blockly.Dart.valueToCode(block, 'TEXT',\n      Blockly.Dart.ORDER_NONE) || '\\'\\'';\n  return 'print(' + argument0 + ');\\n';\n};\n\nBlockly.Dart['text_prompt'] = function(block) {\n  // Prompt function.\n  Blockly.Dart.definitions_['import_dart_html'] =\n      'import \\'dart:html\\' as Html;';\n  var msg = Blockly.Dart.quote_(block.getFieldValue('TEXT'));\n  var code = 'Html.window.prompt(' + msg + ', \\'\\')';\n  var toNumber = block.getFieldValue('TYPE') == 'NUMBER';\n  if (toNumber) {\n    Blockly.Dart.definitions_['import_dart_math'] =\n        'import \\'dart:math\\' as Math;';\n    code = 'Math.parseDouble(' + code + ')';\n  }\n  return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];\n};\n"
  },
  {
    "path": "extern/blockly/generators/dart/variables.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for variable blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart.variables');\n\ngoog.require('Blockly.Dart');\n\n\nBlockly.Dart['variables_get'] = function(block) {\n  // Variable getter.\n  var code = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  return [code, Blockly.Dart.ORDER_ATOMIC];\n};\n\nBlockly.Dart['variables_set'] = function(block) {\n  // Variable setter.\n  var argument0 = Blockly.Dart.valueToCode(block, 'VALUE',\n      Blockly.Dart.ORDER_ASSIGNMENT) || '0';\n  var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  return varName + ' = ' + argument0 + ';\\n';\n};\n"
  },
  {
    "path": "extern/blockly/generators/dart.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Helper functions for generating Dart for blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Dart');\n\ngoog.require('Blockly.Generator');\n\n\nBlockly.Dart = new Blockly.Generator('Dart');\n\n/**\n * List of illegal variable names.\n * This is not intended to be a security feature.  Blockly is 100% client-side,\n * so bypassing this list is trivial.  This is intended to prevent users from\n * accidentally clobbering a built-in object or function.\n * @private\n */\nBlockly.Dart.addReservedWords(\n    // https://www.dartlang.org/docs/spec/latest/dart-language-specification.pdf\n    // Section 16.1.1\n    'assert,break,case,catch,class,const,continue,default,do,else,enum,extends,false,final,finally,for,if,in,is,new,null,rethrow,return,super,switch,this,throw,true,try,var,void,while,with,' +\n    // https://api.dartlang.org/dart_core.html\n    'print,identityHashCode,identical,BidirectionalIterator,Comparable,double,Function,int,Invocation,Iterable,Iterator,List,Map,Match,num,Pattern,RegExp,Set,StackTrace,String,StringSink,Type,bool,DateTime,Deprecated,Duration,Expando,Null,Object,RuneIterator,Runes,Stopwatch,StringBuffer,Symbol,Uri,Comparator,AbstractClassInstantiationError,ArgumentError,AssertionError,CastError,ConcurrentModificationError,CyclicInitializationError,Error,Exception,FallThroughError,FormatException,IntegerDivisionByZeroException,NoSuchMethodError,NullThrownError,OutOfMemoryError,RangeError,StackOverflowError,StateError,TypeError,UnimplementedError,UnsupportedError');\n\n/**\n * Order of operation ENUMs.\n * https://www.dartlang.org/docs/dart-up-and-running/ch02.html#operator_table\n */\nBlockly.Dart.ORDER_ATOMIC = 0;         // 0 \"\" ...\nBlockly.Dart.ORDER_UNARY_POSTFIX = 1;  // expr++ expr-- () [] .\nBlockly.Dart.ORDER_UNARY_PREFIX = 2;   // -expr !expr ~expr ++expr --expr\nBlockly.Dart.ORDER_MULTIPLICATIVE = 3; // * / % ~/\nBlockly.Dart.ORDER_ADDITIVE = 4;       // + -\nBlockly.Dart.ORDER_SHIFT = 5;          // << >>\nBlockly.Dart.ORDER_BITWISE_AND = 6;    // &\nBlockly.Dart.ORDER_BITWISE_XOR = 7;    // ^\nBlockly.Dart.ORDER_BITWISE_OR = 8;     // |\nBlockly.Dart.ORDER_RELATIONAL = 9;     // >= > <= < as is is!\nBlockly.Dart.ORDER_EQUALITY = 10;      // == !=\nBlockly.Dart.ORDER_LOGICAL_AND = 11;   // &&\nBlockly.Dart.ORDER_LOGICAL_OR = 12;    // ||\nBlockly.Dart.ORDER_CONDITIONAL = 13;   // expr ? expr : expr\nBlockly.Dart.ORDER_CASCADE = 14;       // ..\nBlockly.Dart.ORDER_ASSIGNMENT = 15;    // = *= /= ~/= %= += -= <<= >>= &= ^= |=\nBlockly.Dart.ORDER_NONE = 99;          // (...)\n\n/**\n * Arbitrary code to inject into locations that risk causing infinite loops.\n * Any instances of '%1' will be replaced by the block ID that failed.\n * E.g. '  checkTimeout(%1);\\n'\n * @type ?string\n */\nBlockly.Dart.INFINITE_LOOP_TRAP = null;\n\n/**\n * Initialise the database of variable names.\n */\nBlockly.Dart.init = function() {\n  // Create a dictionary of definitions to be printed before the code.\n  Blockly.Dart.definitions_ = Object.create(null);\n  // Create a dictionary mapping desired function names in definitions_\n  // to actual function names (to avoid collisions with user functions).\n  Blockly.Dart.functionNames_ = Object.create(null);\n\n  if (Blockly.Variables) {\n    if (!Blockly.Dart.variableDB_) {\n      Blockly.Dart.variableDB_ =\n          new Blockly.Names(Blockly.Dart.RESERVED_WORDS_);\n    } else {\n      Blockly.Dart.variableDB_.reset();\n    }\n\n    var defvars = [];\n    var variables = Blockly.Variables.allVariables();\n    for (var x = 0; x < variables.length; x++) {\n      defvars[x] = 'var ' +\n          Blockly.Dart.variableDB_.getName(variables[x],\n          Blockly.Variables.NAME_TYPE) + ';';\n    }\n    Blockly.Dart.definitions_['variables'] = defvars.join('\\n');\n  }\n};\n\n/**\n * Prepend the generated code with the variable definitions.\n * @param {string} code Generated code.\n * @return {string} Completed code.\n */\nBlockly.Dart.finish = function(code) {\n  // Indent every line.\n  code = '  ' + code.replace(/\\n/g, '\\n  ');\n  code = code.replace(/\\n\\s+$/, '\\n');\n  code = 'main() {\\n' + code + '}';\n\n  // Convert the definitions dictionary into a list.\n  var imports = [];\n  var definitions = [];\n  for (var name in Blockly.Dart.definitions_) {\n    var def = Blockly.Dart.definitions_[name];\n    if (def.match(/^import\\s/)) {\n      imports.push(def);\n    } else {\n      definitions.push(def);\n    }\n  }\n  var allDefs = imports.join('\\n') + '\\n\\n' + definitions.join('\\n\\n');\n  return allDefs.replace(/\\n\\n+/g, '\\n\\n').replace(/\\n*$/, '\\n\\n\\n') + code;\n};\n\n/**\n * Naked values are top-level blocks with outputs that aren't plugged into\n * anything.  A trailing semicolon is needed to make this legal.\n * @param {string} line Line of generated code.\n * @return {string} Legal line of code.\n */\nBlockly.Dart.scrubNakedValue = function(line) {\n  return line + ';\\n';\n};\n\n/**\n * Encode a string as a properly escaped Dart string, complete with quotes.\n * @param {string} string Text to encode.\n * @return {string} Dart string.\n * @private\n */\nBlockly.Dart.quote_ = function(string) {\n  // TODO: This is a quick hack.  Replace with goog.string.quote\n  string = string.replace(/\\\\/g, '\\\\\\\\')\n                 .replace(/\\n/g, '\\\\\\n')\n                 .replace(/\\$/g, '\\\\$')\n                 .replace(/'/g, '\\\\\\'');\n  return '\\'' + string + '\\'';\n};\n\n/**\n * Common tasks for generating Dart from blocks.\n * Handles comments for the specified block and any connected value blocks.\n * Calls any statements following this block.\n * @param {!Blockly.Block} block The current block.\n * @param {string} code The Dart code created for this block.\n * @return {string} Dart code with comments and subsequent blocks added.\n * @this {Blockly.CodeGenerator}\n * @private\n */\nBlockly.Dart.scrub_ = function(block, code) {\n  if (code === null) {\n    // Block has handled code generation itself.\n    return '';\n  }\n  var commentCode = '';\n  // Only collect comments for blocks that aren't inline.\n  if (!block.outputConnection || !block.outputConnection.targetConnection) {\n    // Collect comment for this block.\n    var comment = block.getCommentText();\n    if (comment) {\n      commentCode += this.prefixLines(comment, '// ') + '\\n';\n    }\n    // Collect comments for all value arguments.\n    // Don't collect comments for nested statements.\n    for (var x = 0; x < block.inputList.length; x++) {\n      if (block.inputList[x].type == Blockly.INPUT_VALUE) {\n        var childBlock = block.inputList[x].connection.targetBlock();\n        if (childBlock) {\n          var comment = this.allNestedComments(childBlock);\n          if (comment) {\n            commentCode += this.prefixLines(comment, '// ');\n          }\n        }\n      }\n    }\n  }\n  var nextBlock = block.nextConnection && block.nextConnection.targetBlock();\n  var nextCode = this.blockToCode(nextBlock);\n  return commentCode + code + nextCode;\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript/colour.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for colour blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript.colour');\n\ngoog.require('Blockly.JavaScript');\n\n\nBlockly.JavaScript['colour_picker'] = function(block) {\n  // Colour picker.\n  var code = '\\'' + block.getFieldValue('COLOUR') + '\\'';\n  return [code, Blockly.JavaScript.ORDER_ATOMIC];\n};\n\nBlockly.JavaScript['colour_random'] = function(block) {\n  // Generate a random colour.\n  var functionName = Blockly.JavaScript.provideFunction_(\n      'colour_random',\n      [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '() {',\n        '  var num = Math.floor(Math.random() * Math.pow(2, 24));',\n        '  return \\'#\\' + (\\'00000\\' + num.toString(16)).substr(-6);',\n        '}']);\n  var code = functionName + '()';\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['colour_rgb'] = function(block) {\n  // Compose a colour from RGB components expressed as percentages.\n  var red = Blockly.JavaScript.valueToCode(block, 'RED',\n      Blockly.JavaScript.ORDER_COMMA) || 0;\n  var green = Blockly.JavaScript.valueToCode(block, 'GREEN',\n      Blockly.JavaScript.ORDER_COMMA) || 0;\n  var blue = Blockly.JavaScript.valueToCode(block, 'BLUE',\n      Blockly.JavaScript.ORDER_COMMA) || 0;\n  var functionName = Blockly.JavaScript.provideFunction_(\n      'colour_rgb',\n      [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n          '(r, g, b) {',\n        '  r = Math.max(Math.min(Number(r), 100), 0) * 2.55;',\n        '  g = Math.max(Math.min(Number(g), 100), 0) * 2.55;',\n        '  b = Math.max(Math.min(Number(b), 100), 0) * 2.55;',\n        '  r = (\\'0\\' + (Math.round(r) || 0).toString(16)).slice(-2);',\n        '  g = (\\'0\\' + (Math.round(g) || 0).toString(16)).slice(-2);',\n        '  b = (\\'0\\' + (Math.round(b) || 0).toString(16)).slice(-2);',\n        '  return \\'#\\' + r + g + b;',\n        '}']);\n  var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')';\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['colour_blend'] = function(block) {\n  // Blend two colours together.\n  var c1 = Blockly.JavaScript.valueToCode(block, 'COLOUR1',\n      Blockly.JavaScript.ORDER_COMMA) || '\\'#000000\\'';\n  var c2 = Blockly.JavaScript.valueToCode(block, 'COLOUR2',\n      Blockly.JavaScript.ORDER_COMMA) || '\\'#000000\\'';\n  var ratio = Blockly.JavaScript.valueToCode(block, 'RATIO',\n      Blockly.JavaScript.ORDER_COMMA) || 0.5;\n  var functionName = Blockly.JavaScript.provideFunction_(\n      'colour_blend',\n      [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n          '(c1, c2, ratio) {',\n        '  ratio = Math.max(Math.min(Number(ratio), 1), 0);',\n        '  var r1 = parseInt(c1.substring(1, 3), 16);',\n        '  var g1 = parseInt(c1.substring(3, 5), 16);',\n        '  var b1 = parseInt(c1.substring(5, 7), 16);',\n        '  var r2 = parseInt(c2.substring(1, 3), 16);',\n        '  var g2 = parseInt(c2.substring(3, 5), 16);',\n        '  var b2 = parseInt(c2.substring(5, 7), 16);',\n        '  var r = Math.round(r1 * (1 - ratio) + r2 * ratio);',\n        '  var g = Math.round(g1 * (1 - ratio) + g2 * ratio);',\n        '  var b = Math.round(b1 * (1 - ratio) + b2 * ratio);',\n        '  r = (\\'0\\' + (r || 0).toString(16)).slice(-2);',\n        '  g = (\\'0\\' + (g || 0).toString(16)).slice(-2);',\n        '  b = (\\'0\\' + (b || 0).toString(16)).slice(-2);',\n        '  return \\'#\\' + r + g + b;',\n        '}']);\n  var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')';\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript/lists.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for list blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript.lists');\n\ngoog.require('Blockly.JavaScript');\n\n\nBlockly.JavaScript['lists_create_empty'] = function(block) {\n  // Create an empty list.\n  return ['[]', Blockly.JavaScript.ORDER_ATOMIC];\n};\n\nBlockly.JavaScript['lists_create_with'] = function(block) {\n  // Create a list with any number of elements of any type.\n  var code = new Array(block.itemCount_);\n  for (var n = 0; n < block.itemCount_; n++) {\n    code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n,\n        Blockly.JavaScript.ORDER_COMMA) || 'null';\n  }\n  code = '[' + code.join(', ') + ']';\n  return [code, Blockly.JavaScript.ORDER_ATOMIC];\n};\n\nBlockly.JavaScript['lists_repeat'] = function(block) {\n  // Create a list with one element repeated.\n  var functionName = Blockly.JavaScript.provideFunction_(\n      'lists_repeat',\n      [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n          '(value, n) {',\n        '  var array = [];',\n        '  for (var i = 0; i < n; i++) {',\n        '    array[i] = value;',\n        '  }',\n        '  return array;',\n        '}']);\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'ITEM',\n      Blockly.JavaScript.ORDER_COMMA) || 'null';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'NUM',\n      Blockly.JavaScript.ORDER_COMMA) || '0';\n  var code = functionName + '(' + argument0 + ', ' + argument1 + ')';\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['lists_length'] = function(block) {\n  // List length.\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_FUNCTION_CALL) || '[]';\n  return [argument0 + '.length', Blockly.JavaScript.ORDER_MEMBER];\n};\n\nBlockly.JavaScript['lists_isEmpty'] = function(block) {\n  // Is the list empty?\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_MEMBER) || '[]';\n  return ['!' + argument0 + '.length', Blockly.JavaScript.ORDER_LOGICAL_NOT];\n};\n\nBlockly.JavaScript['lists_indexOf'] = function(block) {\n  // Find an item in the list.\n  var operator = block.getFieldValue('END') == 'FIRST' ?\n      'indexOf' : 'lastIndexOf';\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'FIND',\n      Blockly.JavaScript.ORDER_NONE) || '\\'\\'';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_MEMBER) || '[]';\n  var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';\n  return [code, Blockly.JavaScript.ORDER_MEMBER];\n};\n\nBlockly.JavaScript['lists_getIndex'] = function(block) {\n  // Get element at index.\n  // Note: Until January 2013 this block did not have MODE or WHERE inputs.\n  var mode = block.getFieldValue('MODE') || 'GET';\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.JavaScript.valueToCode(block, 'AT',\n      Blockly.JavaScript.ORDER_UNARY_NEGATION) || '1';\n  var list = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_MEMBER) || '[]';\n\n  if (where == 'FIRST') {\n    if (mode == 'GET') {\n      var code = list + '[0]';\n      return [code, Blockly.JavaScript.ORDER_MEMBER];\n    } else if (mode == 'GET_REMOVE') {\n      var code = list + '.shift()';\n      return [code, Blockly.JavaScript.ORDER_MEMBER];\n    } else if (mode == 'REMOVE') {\n      return list + '.shift();\\n';\n    }\n  } else if (where == 'LAST') {\n    if (mode == 'GET') {\n      var code = list + '.slice(-1)[0]';\n      return [code, Blockly.JavaScript.ORDER_MEMBER];\n    } else if (mode == 'GET_REMOVE') {\n      var code = list + '.pop()';\n      return [code, Blockly.JavaScript.ORDER_MEMBER];\n    } else if (mode == 'REMOVE') {\n      return list + '.pop();\\n';\n    }\n  } else if (where == 'FROM_START') {\n    // Blockly uses one-based indicies.\n    if (Blockly.isNumber(at)) {\n      // If the index is a naked number, decrement it right now.\n      at = parseFloat(at) - 1;\n    } else {\n      // If the index is dynamic, decrement it in code.\n      at += ' - 1';\n    }\n    if (mode == 'GET') {\n      var code = list + '[' + at + ']';\n      return [code, Blockly.JavaScript.ORDER_MEMBER];\n    } else if (mode == 'GET_REMOVE') {\n      var code = list + '.splice(' + at + ', 1)[0]';\n      return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n    } else if (mode == 'REMOVE') {\n      return list + '.splice(' + at + ', 1);\\n';\n    }\n  } else if (where == 'FROM_END') {\n    if (mode == 'GET') {\n      var code = list + '.slice(-' + at + ')[0]';\n      return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n    } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') {\n      var functionName = Blockly.JavaScript.provideFunction_(\n          'lists_remove_from_end',\n          [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n              '(list, x) {',\n            '  x = list.length - x;',\n            '  return list.splice(x, 1)[0];',\n            '}']);\n      code = functionName + '(' + list + ', ' + at + ')';\n      if (mode == 'GET_REMOVE') {\n        return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n      } else if (mode == 'REMOVE') {\n        return code + ';\\n';\n      }\n    }\n  } else if (where == 'RANDOM') {\n    var functionName = Blockly.JavaScript.provideFunction_(\n        'lists_get_random_item',\n        [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n            '(list, remove) {',\n          '  var x = Math.floor(Math.random() * list.length);',\n          '  if (remove) {',\n          '    return list.splice(x, 1)[0];',\n          '  } else {',\n          '    return list[x];',\n          '  }',\n          '}']);\n    code = functionName + '(' + list + ', ' + (mode != 'GET') + ')';\n    if (mode == 'GET' || mode == 'GET_REMOVE') {\n      return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n    } else if (mode == 'REMOVE') {\n      return code + ';\\n';\n    }\n  }\n  throw 'Unhandled combination (lists_getIndex).';\n};\n\nBlockly.JavaScript['lists_setIndex'] = function(block) {\n  // Set element at index.\n  // Note: Until February 2013 this block did not have MODE or WHERE inputs.\n  var list = Blockly.JavaScript.valueToCode(block, 'LIST',\n      Blockly.JavaScript.ORDER_MEMBER) || '[]';\n  var mode = block.getFieldValue('MODE') || 'GET';\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.JavaScript.valueToCode(block, 'AT',\n      Blockly.JavaScript.ORDER_NONE) || '1';\n  var value = Blockly.JavaScript.valueToCode(block, 'TO',\n      Blockly.JavaScript.ORDER_ASSIGNMENT) || 'null';\n  // Cache non-trivial values to variables to prevent repeated look-ups.\n  // Closure, which accesses and modifies 'list'.\n  function cacheList() {\n    if (list.match(/^\\w+$/)) {\n      return '';\n    }\n    var listVar = Blockly.JavaScript.variableDB_.getDistinctName(\n        'tmp_list', Blockly.Variables.NAME_TYPE);\n    var code = 'var ' + listVar + ' = ' + list + ';\\n';\n    list = listVar;\n    return code;\n  }\n  if (where == 'FIRST') {\n    if (mode == 'SET') {\n      return list + '[0] = ' + value + ';\\n';\n    } else if (mode == 'INSERT') {\n      return list + '.unshift(' + value + ');\\n';\n    }\n  } else if (where == 'LAST') {\n    if (mode == 'SET') {\n      var code = cacheList();\n      code += list + '[' + list + '.length - 1] = ' + value + ';\\n';\n      return code;\n    } else if (mode == 'INSERT') {\n      return list + '.push(' + value + ');\\n';\n    }\n  } else if (where == 'FROM_START') {\n    // Blockly uses one-based indicies.\n    if (Blockly.isNumber(at)) {\n      // If the index is a naked number, decrement it right now.\n      at = parseFloat(at) - 1;\n    } else {\n      // If the index is dynamic, decrement it in code.\n      at += ' - 1';\n    }\n    if (mode == 'SET') {\n      return list + '[' + at + '] = ' + value + ';\\n';\n    } else if (mode == 'INSERT') {\n      return list + '.splice(' + at + ', 0, ' + value + ');\\n';\n    }\n  } else if (where == 'FROM_END') {\n    var code = cacheList();\n    if (mode == 'SET') {\n      code += list + '[' + list + '.length - ' + at + '] = ' + value + ';\\n';\n      return code;\n    } else if (mode == 'INSERT') {\n      code += list + '.splice(' + list + '.length - ' + at + ', 0, ' + value +\n          ');\\n';\n      return code;\n    }\n  } else if (where == 'RANDOM') {\n    var code = cacheList();\n    var xVar = Blockly.JavaScript.variableDB_.getDistinctName(\n        'tmp_x', Blockly.Variables.NAME_TYPE);\n    code += 'var ' + xVar + ' = Math.floor(Math.random() * ' + list +\n        '.length);\\n';\n    if (mode == 'SET') {\n      code += list + '[' + xVar + '] = ' + value + ';\\n';\n      return code;\n    } else if (mode == 'INSERT') {\n      code += list + '.splice(' + xVar + ', 0, ' + value + ');\\n';\n      return code;\n    }\n  }\n  throw 'Unhandled combination (lists_setIndex).';\n};\n\nBlockly.JavaScript['lists_getSublist'] = function(block) {\n  // Get sublist.\n  var list = Blockly.JavaScript.valueToCode(block, 'LIST',\n      Blockly.JavaScript.ORDER_MEMBER) || '[]';\n  var where1 = block.getFieldValue('WHERE1');\n  var where2 = block.getFieldValue('WHERE2');\n  var at1 = Blockly.JavaScript.valueToCode(block, 'AT1',\n      Blockly.JavaScript.ORDER_NONE) || '1';\n  var at2 = Blockly.JavaScript.valueToCode(block, 'AT2',\n      Blockly.JavaScript.ORDER_NONE) || '1';\n  if (where1 == 'FIRST' && where2 == 'LAST') {\n    var code = list + '.concat()';\n  } else {\n    var functionName = Blockly.JavaScript.provideFunction_(\n        'lists_get_sublist',\n        [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n            '(list, where1, at1, where2, at2) {',\n          '  function getAt(where, at) {',\n          '    if (where == \\'FROM_START\\') {',\n          '      at--;',\n          '    } else if (where == \\'FROM_END\\') {',\n          '      at = list.length - at;',\n          '    } else if (where == \\'FIRST\\') {',\n          '      at = 0;',\n          '    } else if (where == \\'LAST\\') {',\n          '      at = list.length - 1;',\n          '    } else {',\n          '      throw \\'Unhandled option (lists_getSublist).\\';',\n          '    }',\n          '    return at;',\n          '  }',\n          '  at1 = getAt(where1, at1);',\n          '  at2 = getAt(where2, at2) + 1;',\n          '  return list.slice(at1, at2);',\n          '}']);\n    var code = functionName + '(' + list + ', \\'' +\n        where1 + '\\', ' + at1 + ', \\'' + where2 + '\\', ' + at2 + ')';\n  }\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript/logic.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for logic blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript.logic');\n\ngoog.require('Blockly.JavaScript');\n\n\nBlockly.JavaScript['controls_if'] = function(block) {\n  // If/elseif/else condition.\n  var n = 0;\n  var argument = Blockly.JavaScript.valueToCode(block, 'IF' + n,\n      Blockly.JavaScript.ORDER_NONE) || 'false';\n  var branch = Blockly.JavaScript.statementToCode(block, 'DO' + n);\n  var code = 'if (' + argument + ') {\\n' + branch + '}';\n  for (n = 1; n <= block.elseifCount_; n++) {\n    argument = Blockly.JavaScript.valueToCode(block, 'IF' + n,\n        Blockly.JavaScript.ORDER_NONE) || 'false';\n    branch = Blockly.JavaScript.statementToCode(block, 'DO' + n);\n    code += ' else if (' + argument + ') {\\n' + branch + '}';\n  }\n  if (block.elseCount_) {\n    branch = Blockly.JavaScript.statementToCode(block, 'ELSE');\n    code += ' else {\\n' + branch + '}';\n  }\n  return code + '\\n';\n};\n\nBlockly.JavaScript['logic_compare'] = function(block) {\n  // Comparison operator.\n  var OPERATORS = {\n    EQ: '==',\n    NEQ: '!=',\n    LT: '<',\n    LTE: '<=',\n    GT: '>',\n    GTE: '>='\n  };\n  var operator = OPERATORS[block.getFieldValue('OP')];\n  var order = (operator == '==' || operator == '!=') ?\n      Blockly.JavaScript.ORDER_EQUALITY : Blockly.JavaScript.ORDER_RELATIONAL;\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order) || '0';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order) || '0';\n  var code = argument0 + ' ' + operator + ' ' + argument1;\n  return [code, order];\n};\n\nBlockly.JavaScript['logic_operation'] = function(block) {\n  // Operations 'and', 'or'.\n  var operator = (block.getFieldValue('OP') == 'AND') ? '&&' : '||';\n  var order = (operator == '&&') ? Blockly.JavaScript.ORDER_LOGICAL_AND :\n      Blockly.JavaScript.ORDER_LOGICAL_OR;\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order);\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order);\n  if (!argument0 && !argument1) {\n    // If there are no arguments, then the return value is false.\n    argument0 = 'false';\n    argument1 = 'false';\n  } else {\n    // Single missing arguments have no effect on the return value.\n    var defaultArgument = (operator == '&&') ? 'true' : 'false';\n    if (!argument0) {\n      argument0 = defaultArgument;\n    }\n    if (!argument1) {\n      argument1 = defaultArgument;\n    }\n  }\n  var code = argument0 + ' ' + operator + ' ' + argument1;\n  return [code, order];\n};\n\nBlockly.JavaScript['logic_negate'] = function(block) {\n  // Negation.\n  var order = Blockly.JavaScript.ORDER_LOGICAL_NOT;\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'BOOL', order) ||\n      'true';\n  var code = '!' + argument0;\n  return [code, order];\n};\n\nBlockly.JavaScript['logic_boolean'] = function(block) {\n  // Boolean values true and false.\n  var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'true' : 'false';\n  return [code, Blockly.JavaScript.ORDER_ATOMIC];\n};\n\nBlockly.JavaScript['logic_null'] = function(block) {\n  // Null data type.\n  return ['null', Blockly.JavaScript.ORDER_ATOMIC];\n};\n\nBlockly.JavaScript['logic_ternary'] = function(block) {\n  // Ternary operator.\n  var value_if = Blockly.JavaScript.valueToCode(block, 'IF',\n      Blockly.JavaScript.ORDER_CONDITIONAL) || 'false';\n  var value_then = Blockly.JavaScript.valueToCode(block, 'THEN',\n      Blockly.JavaScript.ORDER_CONDITIONAL) || 'null';\n  var value_else = Blockly.JavaScript.valueToCode(block, 'ELSE',\n      Blockly.JavaScript.ORDER_CONDITIONAL) || 'null';\n  var code = value_if + ' ? ' + value_then + ' : ' + value_else\n  return [code, Blockly.JavaScript.ORDER_CONDITIONAL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript/loops.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for loop blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript.loops');\n\ngoog.require('Blockly.JavaScript');\n\n\nBlockly.JavaScript['controls_repeat'] = function(block) {\n  // Repeat n times (internal number).\n  var repeats = Number(block.getFieldValue('TIMES'));\n  var branch = Blockly.JavaScript.statementToCode(block, 'DO');\n  if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {\n    branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var loopVar = Blockly.JavaScript.variableDB_.getDistinctName(\n      'count', Blockly.Variables.NAME_TYPE);\n  var code = 'for (var ' + loopVar + ' = 0; ' +\n      loopVar + ' < ' + repeats + '; ' +\n      loopVar + '++) {\\n' +\n      branch + '}\\n';\n  return code;\n};\n\nBlockly.JavaScript['controls_repeat_ext'] = function(block) {\n  // Repeat n times (external number).\n  var repeats = Blockly.JavaScript.valueToCode(block, 'TIMES',\n      Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';\n  var branch = Blockly.JavaScript.statementToCode(block, 'DO');\n  if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {\n    branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var code = '';\n  var loopVar = Blockly.JavaScript.variableDB_.getDistinctName(\n      'count', Blockly.Variables.NAME_TYPE);\n  var endVar = repeats;\n  if (!repeats.match(/^\\w+$/) && !Blockly.isNumber(repeats)) {\n    var endVar = Blockly.JavaScript.variableDB_.getDistinctName(\n        'repeat_end', Blockly.Variables.NAME_TYPE);\n    code += 'var ' + endVar + ' = ' + repeats + ';\\n';\n  }\n  code += 'for (var ' + loopVar + ' = 0; ' +\n      loopVar + ' < ' + endVar + '; ' +\n      loopVar + '++) {\\n' +\n      branch + '}\\n';\n  return code;\n};\n\nBlockly.JavaScript['controls_whileUntil'] = function(block) {\n  // Do while/until loop.\n  var until = block.getFieldValue('MODE') == 'UNTIL';\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'BOOL',\n      until ? Blockly.JavaScript.ORDER_LOGICAL_NOT :\n      Blockly.JavaScript.ORDER_NONE) || 'false';\n  var branch = Blockly.JavaScript.statementToCode(block, 'DO');\n  if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {\n    branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  if (until) {\n    argument0 = '!' + argument0;\n  }\n  return 'while (' + argument0 + ') {\\n' + branch + '}\\n';\n};\n\nBlockly.JavaScript['controls_for'] = function(block) {\n  // For loop.\n  var variable0 = Blockly.JavaScript.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'FROM',\n      Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'TO',\n      Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';\n  var increment = Blockly.JavaScript.valueToCode(block, 'BY',\n      Blockly.JavaScript.ORDER_ASSIGNMENT) || '1';\n  var branch = Blockly.JavaScript.statementToCode(block, 'DO');\n  if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {\n    branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var code;\n  if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) &&\n      Blockly.isNumber(increment)) {\n    // All arguments are simple numbers.\n    var up = parseFloat(argument0) <= parseFloat(argument1);\n    code = 'for (' + variable0 + ' = ' + argument0 + '; ' +\n        variable0 + (up ? ' <= ' : ' >= ') + argument1 + '; ' +\n        variable0;\n    var step = Math.abs(parseFloat(increment));\n    if (step == 1) {\n      code += up ? '++' : '--';\n    } else {\n      code += (up ? ' += ' : ' -= ') + step;\n    }\n    code += ') {\\n' + branch + '}\\n';\n  } else {\n    code = '';\n    // Cache non-trivial values to variables to prevent repeated look-ups.\n    var startVar = argument0;\n    if (!argument0.match(/^\\w+$/) && !Blockly.isNumber(argument0)) {\n      var startVar = Blockly.JavaScript.variableDB_.getDistinctName(\n          variable0 + '_start', Blockly.Variables.NAME_TYPE);\n      code += 'var ' + startVar + ' = ' + argument0 + ';\\n';\n    }\n    var endVar = argument1;\n    if (!argument1.match(/^\\w+$/) && !Blockly.isNumber(argument1)) {\n      var endVar = Blockly.JavaScript.variableDB_.getDistinctName(\n          variable0 + '_end', Blockly.Variables.NAME_TYPE);\n      code += 'var ' + endVar + ' = ' + argument1 + ';\\n';\n    }\n    // Determine loop direction at start, in case one of the bounds\n    // changes during loop execution.\n    var incVar = Blockly.JavaScript.variableDB_.getDistinctName(\n        variable0 + '_inc', Blockly.Variables.NAME_TYPE);\n    code += 'var ' + incVar + ' = ';\n    if (Blockly.isNumber(increment)) {\n      code += Math.abs(increment) + ';\\n';\n    } else {\n      code += 'Math.abs(' + increment + ');\\n';\n    }\n    code += 'if (' + startVar + ' > ' + endVar + ') {\\n';\n    code += '  ' + incVar + ' = -' + incVar +';\\n';\n    code += '}\\n';\n    code += 'for (' + variable0 + ' = ' + startVar + ';\\n' +\n        '     '  + incVar + ' >= 0 ? ' +\n        variable0 + ' <= ' + endVar + ' : ' +\n        variable0 + ' >= ' + endVar + ';\\n' +\n        '     ' + variable0 + ' += ' + incVar + ') {\\n' +\n        branch + '}\\n';\n  }\n  return code;\n};\n\nBlockly.JavaScript['controls_forEach'] = function(block) {\n  // For each loop.\n  var variable0 = Blockly.JavaScript.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'LIST',\n      Blockly.JavaScript.ORDER_ASSIGNMENT) || '[]';\n  var branch = Blockly.JavaScript.statementToCode(block, 'DO');\n  if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {\n    branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var indexVar = Blockly.JavaScript.variableDB_.getDistinctName(\n      variable0 + '_index', Blockly.Variables.NAME_TYPE);\n  branch = '  ' + variable0 + ' = ' + argument0 + '[' + indexVar + '];\\n' +\n      branch;\n  var code = 'for (var ' + indexVar + ' in  ' + argument0 + ') {\\n' +\n      branch + '}\\n';\n  return code;\n};\n\nBlockly.JavaScript['controls_flow_statements'] = function(block) {\n  // Flow statements: continue, break.\n  switch (block.getFieldValue('FLOW')) {\n    case 'BREAK':\n      return 'break;\\n';\n    case 'CONTINUE':\n      return 'continue;\\n';\n  }\n  throw 'Unknown flow statement.';\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript/math.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for math blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript.math');\n\ngoog.require('Blockly.JavaScript');\n\n\nBlockly.JavaScript['math_number'] = function(block) {\n  // Numeric value.\n  var code = parseFloat(block.getFieldValue('NUM'));\n  return [code, Blockly.JavaScript.ORDER_ATOMIC];\n};\n\nBlockly.JavaScript['math_arithmetic'] = function(block) {\n  // Basic arithmetic operators, and power.\n  var OPERATORS = {\n    ADD: [' + ', Blockly.JavaScript.ORDER_ADDITION],\n    MINUS: [' - ', Blockly.JavaScript.ORDER_SUBTRACTION],\n    MULTIPLY: [' * ', Blockly.JavaScript.ORDER_MULTIPLICATION],\n    DIVIDE: [' / ', Blockly.JavaScript.ORDER_DIVISION],\n    POWER: [null, Blockly.JavaScript.ORDER_COMMA]  // Handle power separately.\n  };\n  var tuple = OPERATORS[block.getFieldValue('OP')];\n  var operator = tuple[0];\n  var order = tuple[1];\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order) || '0';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order) || '0';\n  var code;\n  // Power in JavaScript requires a special case since it has no operator.\n  if (!operator) {\n    code = 'Math.pow(' + argument0 + ', ' + argument1 + ')';\n    return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n  }\n  code = argument0 + operator + argument1;\n  return [code, order];\n};\n\nBlockly.JavaScript['math_single'] = function(block) {\n  // Math operators with single operand.\n  var operator = block.getFieldValue('OP');\n  var code;\n  var arg;\n  if (operator == 'NEG') {\n    // Negation is a special case given its different operator precedence.\n    arg = Blockly.JavaScript.valueToCode(block, 'NUM',\n        Blockly.JavaScript.ORDER_UNARY_NEGATION) || '0';\n    if (arg[0] == '-') {\n      // --3 is not legal in JS.\n      arg = ' ' + arg;\n    }\n    code = '-' + arg;\n    return [code, Blockly.JavaScript.ORDER_UNARY_NEGATION];\n  }\n  if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') {\n    arg = Blockly.JavaScript.valueToCode(block, 'NUM',\n        Blockly.JavaScript.ORDER_DIVISION) || '0';\n  } else {\n    arg = Blockly.JavaScript.valueToCode(block, 'NUM',\n        Blockly.JavaScript.ORDER_NONE) || '0';\n  }\n  // First, handle cases which generate values that don't need parentheses\n  // wrapping the code.\n  switch (operator) {\n    case 'ABS':\n      code = 'Math.abs(' + arg + ')';\n      break;\n    case 'ROOT':\n      code = 'Math.sqrt(' + arg + ')';\n      break;\n    case 'LN':\n      code = 'Math.log(' + arg + ')';\n      break;\n    case 'EXP':\n      code = 'Math.exp(' + arg + ')';\n      break;\n    case 'POW10':\n      code = 'Math.pow(10,' + arg + ')';\n      break;\n    case 'ROUND':\n      code = 'Math.round(' + arg + ')';\n      break;\n    case 'ROUNDUP':\n      code = 'Math.ceil(' + arg + ')';\n      break;\n    case 'ROUNDDOWN':\n      code = 'Math.floor(' + arg + ')';\n      break;\n    case 'SIN':\n      code = 'Math.sin(' + arg + ' / 180 * Math.PI)';\n      break;\n    case 'COS':\n      code = 'Math.cos(' + arg + ' / 180 * Math.PI)';\n      break;\n    case 'TAN':\n      code = 'Math.tan(' + arg + ' / 180 * Math.PI)';\n      break;\n  }\n  if (code) {\n    return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n  }\n  // Second, handle cases which generate values that may need parentheses\n  // wrapping the code.\n  switch (operator) {\n    case 'LOG10':\n      code = 'Math.log(' + arg + ') / Math.log(10)';\n      break;\n    case 'ASIN':\n      code = 'Math.asin(' + arg + ') / Math.PI * 180';\n      break;\n    case 'ACOS':\n      code = 'Math.acos(' + arg + ') / Math.PI * 180';\n      break;\n    case 'ATAN':\n      code = 'Math.atan(' + arg + ') / Math.PI * 180';\n      break;\n    default:\n      throw 'Unknown math operator: ' + operator;\n  }\n  return [code, Blockly.JavaScript.ORDER_DIVISION];\n};\n\nBlockly.JavaScript['math_constant'] = function(block) {\n  // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.\n  var CONSTANTS = {\n    PI: ['Math.PI', Blockly.JavaScript.ORDER_MEMBER],\n    E: ['Math.E', Blockly.JavaScript.ORDER_MEMBER],\n    GOLDEN_RATIO: ['(1 + Math.sqrt(5)) / 2', Blockly.JavaScript.ORDER_DIVISION],\n    SQRT2: ['Math.SQRT2', Blockly.JavaScript.ORDER_MEMBER],\n    SQRT1_2: ['Math.SQRT1_2', Blockly.JavaScript.ORDER_MEMBER],\n    INFINITY: ['Infinity', Blockly.JavaScript.ORDER_ATOMIC]\n  };\n  return CONSTANTS[block.getFieldValue('CONSTANT')];\n};\n\nBlockly.JavaScript['math_number_property'] = function(block) {\n  // Check if a number is even, odd, prime, whole, positive, or negative\n  // or if it is divisible by certain number. Returns true or false.\n  var number_to_check = Blockly.JavaScript.valueToCode(block, 'NUMBER_TO_CHECK',\n      Blockly.JavaScript.ORDER_MODULUS) || '0';\n  var dropdown_property = block.getFieldValue('PROPERTY');\n  var code;\n  if (dropdown_property == 'PRIME') {\n    // Prime is a special case as it is not a one-liner test.\n    var functionName = Blockly.JavaScript.provideFunction_(\n        'math_isPrime',\n        [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '(n) {',\n          '  // https://en.wikipedia.org/wiki/Primality_test#Naive_methods',\n          '  if (n == 2 || n == 3) {',\n          '    return true;',\n          '  }',\n          '  // False if n is NaN, negative, is 1, or not whole.',\n          '  // And false if n is divisible by 2 or 3.',\n          '  if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' +\n            ' n % 3 == 0) {',\n          '    return false;',\n          '  }',\n          '  // Check all the numbers of form 6k +/- 1, up to sqrt(n).',\n          '  for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {',\n          '    if (n % (x - 1) == 0 || n % (x + 1) == 0) {',\n          '      return false;',\n          '    }',\n          '  }',\n          '  return true;',\n          '}']);\n    code = functionName + '(' + number_to_check + ')';\n    return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n  }\n  switch (dropdown_property) {\n    case 'EVEN':\n      code = number_to_check + ' % 2 == 0';\n      break;\n    case 'ODD':\n      code = number_to_check + ' % 2 == 1';\n      break;\n    case 'WHOLE':\n      code = number_to_check + ' % 1 == 0';\n      break;\n    case 'POSITIVE':\n      code = number_to_check + ' > 0';\n      break;\n    case 'NEGATIVE':\n      code = number_to_check + ' < 0';\n      break;\n    case 'DIVISIBLE_BY':\n      var divisor = Blockly.JavaScript.valueToCode(block, 'DIVISOR',\n          Blockly.JavaScript.ORDER_MODULUS) || '0';\n      code = number_to_check + ' % ' + divisor + ' == 0';\n      break;\n  }\n  return [code, Blockly.JavaScript.ORDER_EQUALITY];\n};\n\nBlockly.JavaScript['math_change'] = function(block) {\n  // Add to a variable in place.\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'DELTA',\n      Blockly.JavaScript.ORDER_ADDITION) || '0';\n  var varName = Blockly.JavaScript.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  return varName + ' = (typeof ' + varName + ' == \\'number\\' ? ' + varName +\n      ' : 0) + ' + argument0 + ';\\n';\n};\n\n// Rounding functions have a single operand.\nBlockly.JavaScript['math_round'] = Blockly.JavaScript['math_single'];\n// Trigonometry functions have a single operand.\nBlockly.JavaScript['math_trig'] = Blockly.JavaScript['math_single'];\n\nBlockly.JavaScript['math_on_list'] = function(block) {\n  // Math functions for lists.\n  var func = block.getFieldValue('OP');\n  var list, code;\n  switch (func) {\n    case 'SUM':\n      list = Blockly.JavaScript.valueToCode(block, 'LIST',\n          Blockly.JavaScript.ORDER_MEMBER) || '[]';\n      code = list + '.reduce(function(x, y) {return x + y;})';\n      break;\n    case 'MIN':\n      list = Blockly.JavaScript.valueToCode(block, 'LIST',\n          Blockly.JavaScript.ORDER_COMMA) || '[]';\n      code = 'Math.min.apply(null, ' + list + ')';\n      break;\n    case 'MAX':\n      list = Blockly.JavaScript.valueToCode(block, 'LIST',\n          Blockly.JavaScript.ORDER_COMMA) || '[]';\n      code = 'Math.max.apply(null, ' + list + ')';\n      break;\n    case 'AVERAGE':\n      // math_median([null,null,1,3]) == 2.0.\n      var functionName = Blockly.JavaScript.provideFunction_(\n          'math_mean',\n          [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n              '(myList) {',\n            '  return myList.reduce(function(x, y) {return x + y;}) / ' +\n                  'myList.length;',\n            '}']);\n      list = Blockly.JavaScript.valueToCode(block, 'LIST',\n          Blockly.JavaScript.ORDER_NONE) || '[]';\n      code = functionName + '(' + list + ')';\n      break;\n    case 'MEDIAN':\n      // math_median([null,null,1,3]) == 2.0.\n      var functionName = Blockly.JavaScript.provideFunction_(\n          'math_median',\n          [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n              '(myList) {',\n            '  var localList = myList.filter(function (x) ' +\n              '{return typeof x == \\'number\\';});',\n            '  if (!localList.length) return null;',\n            '  localList.sort(function(a, b) {return b - a;});',\n            '  if (localList.length % 2 == 0) {',\n            '    return (localList[localList.length / 2 - 1] + ' +\n              'localList[localList.length / 2]) / 2;',\n            '  } else {',\n            '    return localList[(localList.length - 1) / 2];',\n            '  }',\n            '}']);\n      list = Blockly.JavaScript.valueToCode(block, 'LIST',\n          Blockly.JavaScript.ORDER_NONE) || '[]';\n      code = functionName + '(' + list + ')';\n      break;\n    case 'MODE':\n      // As a list of numbers can contain more than one mode,\n      // the returned result is provided as an array.\n      // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].\n      var functionName = Blockly.JavaScript.provideFunction_(\n          'math_modes',\n          [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n              '(values) {',\n            '  var modes = [];',\n            '  var counts = [];',\n            '  var maxCount = 0;',\n            '  for (var i = 0; i < values.length; i++) {',\n            '    var value = values[i];',\n            '    var found = false;',\n            '    var thisCount;',\n            '    for (var j = 0; j < counts.length; j++) {',\n            '      if (counts[j][0] === value) {',\n            '        thisCount = ++counts[j][1];',\n            '        found = true;',\n            '        break;',\n            '      }',\n            '    }',\n            '    if (!found) {',\n            '      counts.push([value, 1]);',\n            '      thisCount = 1;',\n            '    }',\n            '    maxCount = Math.max(thisCount, maxCount);',\n            '  }',\n            '  for (var j = 0; j < counts.length; j++) {',\n            '    if (counts[j][1] == maxCount) {',\n            '        modes.push(counts[j][0]);',\n            '    }',\n            '  }',\n            '  return modes;',\n            '}']);\n      list = Blockly.JavaScript.valueToCode(block, 'LIST',\n          Blockly.JavaScript.ORDER_NONE) || '[]';\n      code = functionName + '(' + list + ')';\n      break;\n    case 'STD_DEV':\n      var functionName = Blockly.JavaScript.provideFunction_(\n          'math_standard_deviation',\n          [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n              '(numbers) {',\n            '  var n = numbers.length;',\n            '  if (!n) return null;',\n            '  var mean = numbers.reduce(function(x, y) {return x + y;}) / n;',\n            '  var variance = 0;',\n            '  for (var j = 0; j < n; j++) {',\n            '    variance += Math.pow(numbers[j] - mean, 2);',\n            '  }',\n            '  variance = variance / n;',\n            '  return Math.sqrt(variance);',\n            '}']);\n      list = Blockly.JavaScript.valueToCode(block, 'LIST',\n          Blockly.JavaScript.ORDER_NONE) || '[]';\n      code = functionName + '(' + list + ')';\n      break;\n    case 'RANDOM':\n      var functionName = Blockly.JavaScript.provideFunction_(\n          'math_random_list',\n          [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n              '(list) {',\n            '  var x = Math.floor(Math.random() * list.length);',\n            '  return list[x];',\n            '}']);\n      list = Blockly.JavaScript.valueToCode(block, 'LIST',\n          Blockly.JavaScript.ORDER_NONE) || '[]';\n      code = functionName + '(' + list + ')';\n      break;\n    default:\n      throw 'Unknown operator: ' + func;\n  }\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['math_modulo'] = function(block) {\n  // Remainder computation.\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'DIVIDEND',\n      Blockly.JavaScript.ORDER_MODULUS) || '0';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'DIVISOR',\n      Blockly.JavaScript.ORDER_MODULUS) || '0';\n  var code = argument0 + ' % ' + argument1;\n  return [code, Blockly.JavaScript.ORDER_MODULUS];\n};\n\nBlockly.JavaScript['math_constrain'] = function(block) {\n  // Constrain a number between two limits.\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_COMMA) || '0';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'LOW',\n      Blockly.JavaScript.ORDER_COMMA) || '0';\n  var argument2 = Blockly.JavaScript.valueToCode(block, 'HIGH',\n      Blockly.JavaScript.ORDER_COMMA) || 'Infinity';\n  var code = 'Math.min(Math.max(' + argument0 + ', ' + argument1 + '), ' +\n      argument2 + ')';\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['math_random_int'] = function(block) {\n  // Random integer between [X] and [Y].\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'FROM',\n      Blockly.JavaScript.ORDER_COMMA) || '0';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'TO',\n      Blockly.JavaScript.ORDER_COMMA) || '0';\n  var functionName = Blockly.JavaScript.provideFunction_(\n      'math_random_int',\n      [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n          '(a, b) {',\n        '  if (a > b) {',\n        '    // Swap a and b to ensure a is smaller.',\n        '    var c = a;',\n        '    a = b;',\n        '    b = c;',\n        '  }',\n        '  return Math.floor(Math.random() * (b - a + 1) + a);',\n        '}']);\n  var code = functionName + '(' + argument0 + ', ' + argument1 + ')';\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['math_random_float'] = function(block) {\n  // Random fraction between 0 and 1.\n  return ['Math.random()', Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript/procedures.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for procedure blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript.procedures');\n\ngoog.require('Blockly.JavaScript');\n\n\nBlockly.JavaScript['procedures_defreturn'] = function(block) {\n  // Define a procedure with a return value.\n  var funcName = Blockly.JavaScript.variableDB_.getName(\n      block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE);\n  var branch = Blockly.JavaScript.statementToCode(block, 'STACK');\n  if (Blockly.JavaScript.INFINITE_LOOP_TRAP) {\n    branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var returnValue = Blockly.JavaScript.valueToCode(block, 'RETURN',\n      Blockly.JavaScript.ORDER_NONE) || '';\n  if (returnValue) {\n    returnValue = '  return ' + returnValue + ';\\n';\n  }\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.JavaScript.variableDB_.getName(block.arguments_[x],\n        Blockly.Variables.NAME_TYPE);\n  }\n  var code = 'function ' + funcName + '(' + args.join(', ') + ') {\\n' +\n      branch + returnValue + '}';\n  code = Blockly.JavaScript.scrub_(block, code);\n  Blockly.JavaScript.definitions_[funcName] = code;\n  return null;\n};\n\n// Defining a procedure without a return value uses the same generator as\n// a procedure with a return value.\nBlockly.JavaScript['procedures_defnoreturn'] =\n    Blockly.JavaScript['procedures_defreturn'];\n\nBlockly.JavaScript['procedures_callreturn'] = function(block) {\n  // Call a procedure with a return value.\n  var funcName = Blockly.JavaScript.variableDB_.getName(\n      block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE);\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.JavaScript.valueToCode(block, 'ARG' + x,\n        Blockly.JavaScript.ORDER_COMMA) || 'null';\n  }\n  var code = funcName + '(' + args.join(', ') + ')';\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['procedures_callnoreturn'] = function(block) {\n  // Call a procedure with no return value.\n  var funcName = Blockly.JavaScript.variableDB_.getName(\n      block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE);\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.JavaScript.valueToCode(block, 'ARG' + x,\n        Blockly.JavaScript.ORDER_COMMA) || 'null';\n  }\n  var code = funcName + '(' + args.join(', ') + ');\\n';\n  return code;\n};\n\nBlockly.JavaScript['procedures_ifreturn'] = function(block) {\n  // Conditionally return value from a procedure.\n  var condition = Blockly.JavaScript.valueToCode(block, 'CONDITION',\n      Blockly.JavaScript.ORDER_NONE) || 'false';\n  var code = 'if (' + condition + ') {\\n';\n  if (block.hasReturnValue_) {\n    var value = Blockly.JavaScript.valueToCode(block, 'VALUE',\n        Blockly.JavaScript.ORDER_NONE) || 'null';\n    code += '  return ' + value + ';\\n';\n  } else {\n    code += '  return;\\n';\n  }\n  code += '}\\n';\n  return code;\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript/text.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for text blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript.text');\n\ngoog.require('Blockly.JavaScript');\n\n\nBlockly.JavaScript['text'] = function(block) {\n  // Text value.\n  var code = Blockly.JavaScript.quote_(block.getFieldValue('TEXT'));\n  return [code, Blockly.JavaScript.ORDER_ATOMIC];\n};\n\nBlockly.JavaScript['text_join'] = function(block) {\n  // Create a string made up of any number of elements of any type.\n  var code;\n  if (block.itemCount_ == 0) {\n    return ['\\'\\'', Blockly.JavaScript.ORDER_ATOMIC];\n  } else if (block.itemCount_ == 1) {\n    var argument0 = Blockly.JavaScript.valueToCode(block, 'ADD0',\n        Blockly.JavaScript.ORDER_NONE) || '\\'\\'';\n    code = 'String(' + argument0 + ')';\n    return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n  } else if (block.itemCount_ == 2) {\n    var argument0 = Blockly.JavaScript.valueToCode(block, 'ADD0',\n        Blockly.JavaScript.ORDER_NONE) || '\\'\\'';\n    var argument1 = Blockly.JavaScript.valueToCode(block, 'ADD1',\n        Blockly.JavaScript.ORDER_NONE) || '\\'\\'';\n    code = 'String(' + argument0 + ') + String(' + argument1 + ')';\n    return [code, Blockly.JavaScript.ORDER_ADDITION];\n  } else {\n    code = new Array(block.itemCount_);\n    for (var n = 0; n < block.itemCount_; n++) {\n      code[n] = Blockly.JavaScript.valueToCode(block, 'ADD' + n,\n          Blockly.JavaScript.ORDER_COMMA) || '\\'\\'';\n    }\n    code = '[' + code.join(',') + '].join(\\'\\')';\n    return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n  }\n};\n\nBlockly.JavaScript['text_append'] = function(block) {\n  // Append to a variable in place.\n  var varName = Blockly.JavaScript.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',\n      Blockly.JavaScript.ORDER_NONE) || '\\'\\'';\n  return varName + ' = String(' + varName + ') + String(' + argument0 + ');\\n';\n};\n\nBlockly.JavaScript['text_length'] = function(block) {\n  // String length.\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\\'\\'';\n  return [argument0 + '.length', Blockly.JavaScript.ORDER_MEMBER];\n};\n\nBlockly.JavaScript['text_isEmpty'] = function(block) {\n  // Is the string null?\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_MEMBER) || '\\'\\'';\n  return ['!' + argument0, Blockly.JavaScript.ORDER_LOGICAL_NOT];\n};\n\nBlockly.JavaScript['text_indexOf'] = function(block) {\n  // Search the text for a substring.\n  var operator = block.getFieldValue('END') == 'FIRST' ?\n      'indexOf' : 'lastIndexOf';\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'FIND',\n      Blockly.JavaScript.ORDER_NONE) || '\\'\\'';\n  var argument1 = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_MEMBER) || '\\'\\'';\n  var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';\n  return [code, Blockly.JavaScript.ORDER_MEMBER];\n};\n\nBlockly.JavaScript['text_charAt'] = function(block) {\n  // Get letter at index.\n  // Note: Until January 2013 this block did not have the WHERE input.\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.JavaScript.valueToCode(block, 'AT',\n      Blockly.JavaScript.ORDER_UNARY_NEGATION) || '1';\n  var text = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_MEMBER) || '\\'\\'';\n  switch (where) {\n    case 'FIRST':\n      var code = text + '.charAt(0)';\n      return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n    case 'LAST':\n      var code = text + '.slice(-1)';\n      return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n    case 'FROM_START':\n      // Blockly uses one-based indicies.\n      if (Blockly.isNumber(at)) {\n        // If the index is a naked number, decrement it right now.\n        at = parseFloat(at) - 1;\n      } else {\n        // If the index is dynamic, decrement it in code.\n        at += ' - 1';\n      }\n      var code = text + '.charAt(' + at + ')';\n      return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n    case 'FROM_END':\n      var code = text + '.slice(-' + at + ').charAt(0)';\n      return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n    case 'RANDOM':\n      var functionName = Blockly.JavaScript.provideFunction_(\n          'text_random_letter',\n          [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n              '(text) {',\n            '  var x = Math.floor(Math.random() * text.length);',\n            '  return text[x];',\n            '}']);\n      code = functionName + '(' + text + ')';\n      return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n  }\n  throw 'Unhandled option (text_charAt).';\n};\n\nBlockly.JavaScript['text_getSubstring'] = function(block) {\n  // Get substring.\n  var text = Blockly.JavaScript.valueToCode(block, 'STRING',\n      Blockly.JavaScript.ORDER_MEMBER) || '\\'\\'';\n  var where1 = block.getFieldValue('WHERE1');\n  var where2 = block.getFieldValue('WHERE2');\n  var at1 = Blockly.JavaScript.valueToCode(block, 'AT1',\n      Blockly.JavaScript.ORDER_NONE) || '1';\n  var at2 = Blockly.JavaScript.valueToCode(block, 'AT2',\n      Blockly.JavaScript.ORDER_NONE) || '1';\n  if (where1 == 'FIRST' && where2 == 'LAST') {\n    var code = text;\n  } else {\n    var functionName = Blockly.JavaScript.provideFunction_(\n        'text_get_substring',\n        [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n            '(text, where1, at1, where2, at2) {',\n          '  function getAt(where, at) {',\n          '    if (where == \\'FROM_START\\') {',\n          '      at--;',\n          '    } else if (where == \\'FROM_END\\') {',\n          '      at = text.length - at;',\n          '    } else if (where == \\'FIRST\\') {',\n          '      at = 0;',\n          '    } else if (where == \\'LAST\\') {',\n          '      at = text.length - 1;',\n          '    } else {',\n          '      throw \\'Unhandled option (text_getSubstring).\\';',\n          '    }',\n          '    return at;',\n          '  }',\n          '  at1 = getAt(where1, at1);',\n          '  at2 = getAt(where2, at2) + 1;',\n          '  return text.slice(at1, at2);',\n          '}']);\n    var code = functionName + '(' + text + ', \\'' +\n        where1 + '\\', ' + at1 + ', \\'' + where2 + '\\', ' + at2 + ')';\n  }\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['text_changeCase'] = function(block) {\n  // Change capitalization.\n  var OPERATORS = {\n    UPPERCASE: '.toUpperCase()',\n    LOWERCASE: '.toLowerCase()',\n    TITLECASE: null\n  };\n  var operator = OPERATORS[block.getFieldValue('CASE')];\n  var code;\n  if (operator) {\n    // Upper and lower case are functions built into JavaScript.\n    var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',\n        Blockly.JavaScript.ORDER_MEMBER) || '\\'\\'';\n    code = argument0 + operator;\n  } else {\n    // Title case is not a native JavaScript function.  Define one.\n    var functionName = Blockly.JavaScript.provideFunction_(\n        'text_toTitleCase',\n        [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '(str) {',\n          '  return str.replace(/\\\\S+/g,',\n          '      function(txt) {return txt[0].toUpperCase() + ' +\n              'txt.substring(1).toLowerCase();});',\n          '}']);\n    var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',\n        Blockly.JavaScript.ORDER_NONE) || '\\'\\'';\n    code = functionName + '(' + argument0 + ')';\n  }\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['text_trim'] = function(block) {\n  // Trim spaces.\n  var OPERATORS = {\n    LEFT: '.trimLeft()',\n    RIGHT: '.trimRight()',\n    BOTH: '.trim()'\n  };\n  var operator = OPERATORS[block.getFieldValue('MODE')];\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',\n      Blockly.JavaScript.ORDER_MEMBER) || '\\'\\'';\n  return [argument0 + operator, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n\nBlockly.JavaScript['text_print'] = function(block) {\n  // Print statement.\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'TEXT',\n      Blockly.JavaScript.ORDER_NONE) || '\\'\\'';\n  return 'window.alert(' + argument0 + ');\\n';\n};\n\nBlockly.JavaScript['text_prompt'] = function(block) {\n  // Prompt function.\n  var msg = Blockly.JavaScript.quote_(block.getFieldValue('TEXT'));\n  var code = 'window.prompt(' + msg + ')';\n  var toNumber = block.getFieldValue('TYPE') == 'NUMBER';\n  if (toNumber) {\n    code = 'parseFloat(' + code + ')';\n  }\n  return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript/variables.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for variable blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript.variables');\n\ngoog.require('Blockly.JavaScript');\n\n\nBlockly.JavaScript['variables_get'] = function(block) {\n  // Variable getter.\n  var code = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  return [code, Blockly.JavaScript.ORDER_ATOMIC];\n};\n\nBlockly.JavaScript['variables_set'] = function(block) {\n  // Variable setter.\n  var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',\n      Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';\n  var varName = Blockly.JavaScript.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  return varName + ' = ' + argument0 + ';\\n';\n};\n"
  },
  {
    "path": "extern/blockly/generators/javascript.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Helper functions for generating JavaScript for blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.JavaScript');\n\ngoog.require('Blockly.Generator');\n\n\nBlockly.JavaScript = new Blockly.Generator('JavaScript');\n\n/**\n * List of illegal variable names.\n * This is not intended to be a security feature.  Blockly is 100% client-side,\n * so bypassing this list is trivial.  This is intended to prevent users from\n * accidentally clobbering a built-in object or function.\n * @private\n */\nBlockly.JavaScript.addReservedWords(\n    'Blockly,' +  // In case JS is evaled in the current window.\n    // https://developer.mozilla.org/en/JavaScript/Reference/Reserved_Words\n    'break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,' +\n    'class,enum,export,extends,import,super,implements,interface,let,package,private,protected,public,static,yield,' +\n    'const,null,true,false,' +\n    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects\n    'Array,ArrayBuffer,Boolean,Date,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Error,eval,EvalError,Float32Array,Float64Array,Function,Infinity,Int16Array,Int32Array,Int8Array,isFinite,isNaN,Iterator,JSON,Math,NaN,Number,Object,parseFloat,parseInt,RangeError,ReferenceError,RegExp,StopIteration,String,SyntaxError,TypeError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,undefined,uneval,URIError,' +\n    // https://developer.mozilla.org/en/DOM/window\n    'applicationCache,closed,Components,content,_content,controllers,crypto,defaultStatus,dialogArguments,directories,document,frameElement,frames,fullScreen,globalStorage,history,innerHeight,innerWidth,length,location,locationbar,localStorage,menubar,messageManager,mozAnimationStartTime,mozInnerScreenX,mozInnerScreenY,mozPaintCount,name,navigator,opener,outerHeight,outerWidth,pageXOffset,pageYOffset,parent,performance,personalbar,pkcs11,returnValue,screen,screenX,screenY,scrollbars,scrollMaxX,scrollMaxY,scrollX,scrollY,self,sessionStorage,sidebar,status,statusbar,toolbar,top,URL,window,' +\n    'addEventListener,alert,atob,back,blur,btoa,captureEvents,clearImmediate,clearInterval,clearTimeout,close,confirm,disableExternalCapture,dispatchEvent,dump,enableExternalCapture,escape,find,focus,forward,GeckoActiveXObject,getAttention,getAttentionWithCycleCount,getComputedStyle,getSelection,home,matchMedia,maximize,minimize,moveBy,moveTo,mozRequestAnimationFrame,open,openDialog,postMessage,print,prompt,QueryInterface,releaseEvents,removeEventListener,resizeBy,resizeTo,restore,routeEvent,scroll,scrollBy,scrollByLines,scrollByPages,scrollTo,setCursor,setImmediate,setInterval,setResizable,setTimeout,showModalDialog,sizeToContent,stop,unescape,updateCommands,XPCNativeWrapper,XPCSafeJSObjectWrapper,' +\n    'onabort,onbeforeunload,onblur,onchange,onclick,onclose,oncontextmenu,ondevicemotion,ondeviceorientation,ondragdrop,onerror,onfocus,onhashchange,onkeydown,onkeypress,onkeyup,onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup,onmozbeforepaint,onpaint,onpopstate,onreset,onresize,onscroll,onselect,onsubmit,onunload,onpageshow,onpagehide,' +\n    'Image,Option,Worker,' +\n    // https://developer.mozilla.org/en/Gecko_DOM_Reference\n    'Event,Range,File,FileReader,Blob,BlobBuilder,' +\n    'Attr,CDATASection,CharacterData,Comment,console,DocumentFragment,DocumentType,DomConfiguration,DOMError,DOMErrorHandler,DOMException,DOMImplementation,DOMImplementationList,DOMImplementationRegistry,DOMImplementationSource,DOMLocator,DOMObject,DOMString,DOMStringList,DOMTimeStamp,DOMUserData,Entity,EntityReference,MediaQueryList,MediaQueryListListener,NameList,NamedNodeMap,Node,NodeFilter,NodeIterator,NodeList,Notation,Plugin,PluginArray,ProcessingInstruction,SharedWorker,Text,TimeRanges,Treewalker,TypeInfo,UserDataHandler,Worker,WorkerGlobalScope,' +\n    'HTMLDocument,HTMLElement,HTMLAnchorElement,HTMLAppletElement,HTMLAudioElement,HTMLAreaElement,HTMLBaseElement,HTMLBaseFontElement,HTMLBodyElement,HTMLBRElement,HTMLButtonElement,HTMLCanvasElement,HTMLDirectoryElement,HTMLDivElement,HTMLDListElement,HTMLEmbedElement,HTMLFieldSetElement,HTMLFontElement,HTMLFormElement,HTMLFrameElement,HTMLFrameSetElement,HTMLHeadElement,HTMLHeadingElement,HTMLHtmlElement,HTMLHRElement,HTMLIFrameElement,HTMLImageElement,HTMLInputElement,HTMLKeygenElement,HTMLLabelElement,HTMLLIElement,HTMLLinkElement,HTMLMapElement,HTMLMenuElement,HTMLMetaElement,HTMLModElement,HTMLObjectElement,HTMLOListElement,HTMLOptGroupElement,HTMLOptionElement,HTMLOutputElement,HTMLParagraphElement,HTMLParamElement,HTMLPreElement,HTMLQuoteElement,HTMLScriptElement,HTMLSelectElement,HTMLSourceElement,HTMLSpanElement,HTMLStyleElement,HTMLTableElement,HTMLTableCaptionElement,HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement,HTMLTableColElement,HTMLTableRowElement,HTMLTableSectionElement,HTMLTextAreaElement,HTMLTimeElement,HTMLTitleElement,HTMLTrackElement,HTMLUListElement,HTMLUnknownElement,HTMLVideoElement,' +\n    'HTMLCanvasElement,CanvasRenderingContext2D,CanvasGradient,CanvasPattern,TextMetrics,ImageData,CanvasPixelArray,HTMLAudioElement,HTMLVideoElement,NotifyAudioAvailableEvent,HTMLCollection,HTMLAllCollection,HTMLFormControlsCollection,HTMLOptionsCollection,HTMLPropertiesCollection,DOMTokenList,DOMSettableTokenList,DOMStringMap,RadioNodeList,' +\n    'SVGDocument,SVGElement,SVGAElement,SVGAltGlyphElement,SVGAltGlyphDefElement,SVGAltGlyphItemElement,SVGAnimationElement,SVGAnimateElement,SVGAnimateColorElement,SVGAnimateMotionElement,SVGAnimateTransformElement,SVGSetElement,SVGCircleElement,SVGClipPathElement,SVGColorProfileElement,SVGCursorElement,SVGDefsElement,SVGDescElement,SVGEllipseElement,SVGFilterElement,SVGFilterPrimitiveStandardAttributes,SVGFEBlendElement,SVGFEColorMatrixElement,SVGFEComponentTransferElement,SVGFECompositeElement,SVGFEConvolveMatrixElement,SVGFEDiffuseLightingElement,SVGFEDisplacementMapElement,SVGFEDistantLightElement,SVGFEFloodElement,SVGFEGaussianBlurElement,SVGFEImageElement,SVGFEMergeElement,SVGFEMergeNodeElement,SVGFEMorphologyElement,SVGFEOffsetElement,SVGFEPointLightElement,SVGFESpecularLightingElement,SVGFESpotLightElement,SVGFETileElement,SVGFETurbulenceElement,SVGComponentTransferFunctionElement,SVGFEFuncRElement,SVGFEFuncGElement,SVGFEFuncBElement,SVGFEFuncAElement,SVGFontElement,SVGFontFaceElement,SVGFontFaceFormatElement,SVGFontFaceNameElement,SVGFontFaceSrcElement,SVGFontFaceUriElement,SVGForeignObjectElement,SVGGElement,SVGGlyphElement,SVGGlyphRefElement,SVGGradientElement,SVGLinearGradientElement,SVGRadialGradientElement,SVGHKernElement,SVGImageElement,SVGLineElement,SVGMarkerElement,SVGMaskElement,SVGMetadataElement,SVGMissingGlyphElement,SVGMPathElement,SVGPathElement,SVGPatternElement,SVGPolylineElement,SVGPolygonElement,SVGRectElement,SVGScriptElement,SVGStopElement,SVGStyleElement,SVGSVGElement,SVGSwitchElement,SVGSymbolElement,SVGTextElement,SVGTextPathElement,SVGTitleElement,SVGTRefElement,SVGTSpanElement,SVGUseElement,SVGViewElement,SVGVKernElement,' +\n    'SVGAngle,SVGColor,SVGICCColor,SVGElementInstance,SVGElementInstanceList,SVGLength,SVGLengthList,SVGMatrix,SVGNumber,SVGNumberList,SVGPaint,SVGPoint,SVGPointList,SVGPreserveAspectRatio,SVGRect,SVGStringList,SVGTransform,SVGTransformList,' +\n    'SVGAnimatedAngle,SVGAnimatedBoolean,SVGAnimatedEnumeration,SVGAnimatedInteger,SVGAnimatedLength,SVGAnimatedLengthList,SVGAnimatedNumber,SVGAnimatedNumberList,SVGAnimatedPreserveAspectRatio,SVGAnimatedRect,SVGAnimatedString,SVGAnimatedTransformList,' +\n    'SVGPathSegList,SVGPathSeg,SVGPathSegArcAbs,SVGPathSegArcRel,SVGPathSegClosePath,SVGPathSegCurvetoCubicAbs,SVGPathSegCurvetoCubicRel,SVGPathSegCurvetoCubicSmoothAbs,SVGPathSegCurvetoCubicSmoothRel,SVGPathSegCurvetoQuadraticAbs,SVGPathSegCurvetoQuadraticRel,SVGPathSegCurvetoQuadraticSmoothAbs,SVGPathSegCurvetoQuadraticSmoothRel,SVGPathSegLinetoAbs,SVGPathSegLinetoHorizontalAbs,SVGPathSegLinetoHorizontalRel,SVGPathSegLinetoRel,SVGPathSegLinetoVerticalAbs,SVGPathSegLinetoVerticalRel,SVGPathSegMovetoAbs,SVGPathSegMovetoRel,ElementTimeControl,TimeEvent,SVGAnimatedPathData,' +\n    'SVGAnimatedPoints,SVGColorProfileRule,SVGCSSRule,SVGExternalResourcesRequired,SVGFitToViewBox,SVGLangSpace,SVGLocatable,SVGRenderingIntent,SVGStylable,SVGTests,SVGTextContentElement,SVGTextPositioningElement,SVGTransformable,SVGUnitTypes,SVGURIReference,SVGViewSpec,SVGZoomAndPan');\n\n/**\n * Order of operation ENUMs.\n * https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence\n */\nBlockly.JavaScript.ORDER_ATOMIC = 0;         // 0 \"\" ...\nBlockly.JavaScript.ORDER_MEMBER = 1;         // . []\nBlockly.JavaScript.ORDER_NEW = 1;            // new\nBlockly.JavaScript.ORDER_FUNCTION_CALL = 2;  // ()\nBlockly.JavaScript.ORDER_INCREMENT = 3;      // ++\nBlockly.JavaScript.ORDER_DECREMENT = 3;      // --\nBlockly.JavaScript.ORDER_LOGICAL_NOT = 4;    // !\nBlockly.JavaScript.ORDER_BITWISE_NOT = 4;    // ~\nBlockly.JavaScript.ORDER_UNARY_PLUS = 4;     // +\nBlockly.JavaScript.ORDER_UNARY_NEGATION = 4; // -\nBlockly.JavaScript.ORDER_TYPEOF = 4;         // typeof\nBlockly.JavaScript.ORDER_VOID = 4;           // void\nBlockly.JavaScript.ORDER_DELETE = 4;         // delete\nBlockly.JavaScript.ORDER_MULTIPLICATION = 5; // *\nBlockly.JavaScript.ORDER_DIVISION = 5;       // /\nBlockly.JavaScript.ORDER_MODULUS = 5;        // %\nBlockly.JavaScript.ORDER_ADDITION = 6;       // +\nBlockly.JavaScript.ORDER_SUBTRACTION = 6;    // -\nBlockly.JavaScript.ORDER_BITWISE_SHIFT = 7;  // << >> >>>\nBlockly.JavaScript.ORDER_RELATIONAL = 8;     // < <= > >=\nBlockly.JavaScript.ORDER_IN = 8;             // in\nBlockly.JavaScript.ORDER_INSTANCEOF = 8;     // instanceof\nBlockly.JavaScript.ORDER_EQUALITY = 9;       // == != === !==\nBlockly.JavaScript.ORDER_BITWISE_AND = 10;   // &\nBlockly.JavaScript.ORDER_BITWISE_XOR = 11;   // ^\nBlockly.JavaScript.ORDER_BITWISE_OR = 12;    // |\nBlockly.JavaScript.ORDER_LOGICAL_AND = 13;   // &&\nBlockly.JavaScript.ORDER_LOGICAL_OR = 14;    // ||\nBlockly.JavaScript.ORDER_CONDITIONAL = 15;   // ?:\nBlockly.JavaScript.ORDER_ASSIGNMENT = 16;    // = += -= *= /= %= <<= >>= ...\nBlockly.JavaScript.ORDER_COMMA = 17;         // ,\nBlockly.JavaScript.ORDER_NONE = 99;          // (...)\n\n/**\n * Arbitrary code to inject into locations that risk causing infinite loops.\n * Any instances of '%1' will be replaced by the block ID that failed.\n * E.g. '  checkTimeout(%1);\\n'\n * @type ?string\n */\nBlockly.JavaScript.INFINITE_LOOP_TRAP = null;\n\n/**\n * Initialise the database of variable names.\n */\nBlockly.JavaScript.init = function() {\n  // Create a dictionary of definitions to be printed before the code.\n  Blockly.JavaScript.definitions_ = Object.create(null);\n  // Create a dictionary mapping desired function names in definitions_\n  // to actual function names (to avoid collisions with user functions).\n  Blockly.JavaScript.functionNames_ = Object.create(null);\n\n  if (Blockly.Variables) {\n    if (!Blockly.JavaScript.variableDB_) {\n      Blockly.JavaScript.variableDB_ =\n          new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_);\n    } else {\n      Blockly.JavaScript.variableDB_.reset();\n    }\n\n    var defvars = [];\n    var variables = Blockly.Variables.allVariables();\n    for (var x = 0; x < variables.length; x++) {\n      defvars[x] = 'var ' +\n          Blockly.JavaScript.variableDB_.getName(variables[x],\n          Blockly.Variables.NAME_TYPE) + ';';\n    }\n    Blockly.JavaScript.definitions_['variables'] = defvars.join('\\n');\n  }\n};\n\n/**\n * Prepend the generated code with the variable definitions.\n * @param {string} code Generated code.\n * @return {string} Completed code.\n */\nBlockly.JavaScript.finish = function(code) {\n  // Convert the definitions dictionary into a list.\n  var definitions = [];\n  for (var name in Blockly.JavaScript.definitions_) {\n    definitions.push(Blockly.JavaScript.definitions_[name]);\n  }\n  return definitions.join('\\n\\n') + '\\n\\n\\n' + code;\n};\n\n/**\n * Naked values are top-level blocks with outputs that aren't plugged into\n * anything.  A trailing semicolon is needed to make this legal.\n * @param {string} line Line of generated code.\n * @return {string} Legal line of code.\n */\nBlockly.JavaScript.scrubNakedValue = function(line) {\n  return line + ';\\n';\n};\n\n/**\n * Encode a string as a properly escaped JavaScript string, complete with\n * quotes.\n * @param {string} string Text to encode.\n * @return {string} JavaScript string.\n * @private\n */\nBlockly.JavaScript.quote_ = function(string) {\n  // TODO: This is a quick hack.  Replace with goog.string.quote\n  string = string.replace(/\\\\/g, '\\\\\\\\')\n                 .replace(/\\n/g, '\\\\\\n')\n                 .replace(/'/g, '\\\\\\'');\n  return '\\'' + string + '\\'';\n};\n\n/**\n * Common tasks for generating JavaScript from blocks.\n * Handles comments for the specified block and any connected value blocks.\n * Calls any statements following this block.\n * @param {!Blockly.Block} block The current block.\n * @param {string} code The JavaScript code created for this block.\n * @return {string} JavaScript code with comments and subsequent blocks added.\n * @this {Blockly.CodeGenerator}\n * @private\n */\nBlockly.JavaScript.scrub_ = function(block, code) {\n  if (code === null) {\n    // Block has handled code generation itself.\n    return '';\n  }\n  var commentCode = '';\n  // Only collect comments for blocks that aren't inline.\n  if (!block.outputConnection || !block.outputConnection.targetConnection) {\n    // Collect comment for this block.\n    var comment = block.getCommentText();\n    if (comment) {\n      commentCode += this.prefixLines(comment, '// ') + '\\n';\n    }\n    // Collect comments for all value arguments.\n    // Don't collect comments for nested statements.\n    for (var x = 0; x < block.inputList.length; x++) {\n      if (block.inputList[x].type == Blockly.INPUT_VALUE) {\n        var childBlock = block.inputList[x].connection.targetBlock();\n        if (childBlock) {\n          var comment = this.allNestedComments(childBlock);\n          if (comment) {\n            commentCode += this.prefixLines(comment, '// ');\n          }\n        }\n      }\n    }\n  }\n  var nextBlock = block.nextConnection && block.nextConnection.targetBlock();\n  var nextCode = this.blockToCode(nextBlock);\n  return commentCode + code + nextCode;\n};\n"
  },
  {
    "path": "extern/blockly/generators/python/colour.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for colour blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Python.colour');\n\ngoog.require('Blockly.Python');\n\n\nBlockly.Python['colour_picker'] = function(block) {\n  // Colour picker.\n  var code = '\\'' + block.getFieldValue('COLOUR') + '\\'';\n  return [code, Blockly.Python.ORDER_ATOMIC];\n};\n\nBlockly.Python['colour_random'] = function(block) {\n  // Generate a random colour.\n  Blockly.Python.definitions_['import_random'] = 'import random';\n  var code = '\\'#%06x\\' % random.randint(0, 2**24 - 1)';\n  return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n};\n\nBlockly.Python['colour_rgb'] = function(block) {\n  // Compose a colour from RGB components expressed as percentages.\n  var functionName = Blockly.Python.provideFunction_(\n      'colour_rgb',\n      [ 'def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b):',\n        '  r = round(min(100, max(0, r)) * 2.55)',\n        '  g = round(min(100, max(0, g)) * 2.55)',\n        '  b = round(min(100, max(0, b)) * 2.55)',\n        '  return \\'#%02x%02x%02x\\' % (r, g, b)']);\n  var r = Blockly.Python.valueToCode(block, 'RED',\n                                     Blockly.Python.ORDER_NONE) || 0;\n  var g = Blockly.Python.valueToCode(block, 'GREEN',\n                                     Blockly.Python.ORDER_NONE) || 0;\n  var b = Blockly.Python.valueToCode(block, 'BLUE',\n                                     Blockly.Python.ORDER_NONE) || 0;\n  var code = functionName + '(' + r + ', ' + g + ', ' + b + ')';\n  return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n};\n\nBlockly.Python['colour_blend'] = function(block) {\n  // Blend two colours together.\n  var functionName = Blockly.Python.provideFunction_(\n      'colour_blend',\n      ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ +\n          '(colour1, colour2, ratio):',\n       '  r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)',\n       '  g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)',\n       '  b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)',\n       '  ratio = min(1, max(0, ratio))',\n       '  r = round(r1 * (1 - ratio) + r2 * ratio)',\n       '  g = round(g1 * (1 - ratio) + g2 * ratio)',\n       '  b = round(b1 * (1 - ratio) + b2 * ratio)',\n       '  return \\'#%02x%02x%02x\\' % (r, g, b)']);\n  var colour1 = Blockly.Python.valueToCode(block, 'COLOUR1',\n      Blockly.Python.ORDER_NONE) || '\\'#000000\\'';\n  var colour2 = Blockly.Python.valueToCode(block, 'COLOUR2',\n      Blockly.Python.ORDER_NONE) || '\\'#000000\\'';\n  var ratio = Blockly.Python.valueToCode(block, 'RATIO',\n      Blockly.Python.ORDER_NONE) || 0;\n  var code = functionName + '(' + colour1 + ', ' + colour2 + ', ' + ratio + ')';\n  return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/python/lists.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for list blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Python.lists');\n\ngoog.require('Blockly.Python');\n\n\nBlockly.Python['lists_create_empty'] = function(block) {\n  // Create an empty list.\n  return ['[]', Blockly.Python.ORDER_ATOMIC];\n};\n\nBlockly.Python['lists_create_with'] = function(block) {\n  // Create a list with any number of elements of any type.\n  var code = new Array(block.itemCount_);\n  for (var n = 0; n < block.itemCount_; n++) {\n    code[n] = Blockly.Python.valueToCode(block, 'ADD' + n,\n        Blockly.Python.ORDER_NONE) || 'None';\n  }\n  code = '[' + code.join(', ') + ']';\n  return [code, Blockly.Python.ORDER_ATOMIC];\n};\n\nBlockly.Python['lists_repeat'] = function(block) {\n  // Create a list with one element repeated.\n  var argument0 = Blockly.Python.valueToCode(block, 'ITEM',\n      Blockly.Python.ORDER_NONE) || 'None';\n  var argument1 = Blockly.Python.valueToCode(block, 'NUM',\n      Blockly.Python.ORDER_MULTIPLICATIVE) || '0';\n  var code = '[' + argument0 + '] * ' + argument1;\n  return [code, Blockly.Python.ORDER_MULTIPLICATIVE];\n};\n\nBlockly.Python['lists_length'] = function(block) {\n  // List length.\n  var argument0 = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_NONE) || '[]';\n  return ['len(' + argument0 + ')', Blockly.Python.ORDER_FUNCTION_CALL];\n};\n\nBlockly.Python['lists_isEmpty'] = function(block) {\n  // Is the list empty?\n  var argument0 = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_NONE) || '[]';\n  var code = 'not len(' + argument0 + ')';\n  return [code, Blockly.Python.ORDER_LOGICAL_NOT];\n};\n\nBlockly.Python['lists_indexOf'] = function(block) {\n  // Find an item in the list.\n  var argument0 = Blockly.Python.valueToCode(block, 'FIND',\n      Blockly.Python.ORDER_NONE) || '[]';\n  var argument1 = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_MEMBER) || '\\'\\'';\n  var code;\n  if (block.getFieldValue('END') == 'FIRST') {\n    var functionName = Blockly.Python.provideFunction_(\n        'first_index',\n        ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList, elem):',\n         '  try: theIndex = myList.index(elem) + 1',\n         '  except: theIndex = 0',\n         '  return theIndex']);\n    code = functionName + '(' + argument1 + ', ' + argument0 + ')';\n    return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n  } else {\n    var functionName = Blockly.Python.provideFunction_(\n        'last_index',\n        ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList, elem):',\n         '  try: theIndex = len(myList) - myList[::-1].index(elem)',\n         '  except: theIndex = 0',\n         '  return theIndex']);\n    code = functionName + '(' + argument1 + ', ' + argument0 + ')';\n    return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n  }\n};\n\nBlockly.Python['lists_getIndex'] = function(block) {\n  // Get element at index.\n  // Note: Until January 2013 this block did not have MODE or WHERE inputs.\n  var mode = block.getFieldValue('MODE') || 'GET';\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.Python.valueToCode(block, 'AT',\n      Blockly.Python.ORDER_UNARY_SIGN) || '1';\n  var list = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_MEMBER) || '[]';\n\n  if (where == 'FIRST') {\n    if (mode == 'GET') {\n      var code = list + '[0]';\n      return [code, Blockly.Python.ORDER_MEMBER];\n    } else {\n      var code = list + '.pop(0)';\n      if (mode == 'GET_REMOVE') {\n        return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n      } else if (mode == 'REMOVE') {\n        return code + '\\n';\n      }\n    }\n  } else if (where == 'LAST') {\n    if (mode == 'GET') {\n      var code = list + '[-1]';\n      return [code, Blockly.Python.ORDER_MEMBER];\n    } else {\n      var code = list + '.pop()';\n      if (mode == 'GET_REMOVE') {\n        return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n      } else if (mode == 'REMOVE') {\n        return code + '\\n';\n      }\n    }\n  } else if (where == 'FROM_START') {\n    // Blockly uses one-based indicies.\n    if (Blockly.isNumber(at)) {\n      // If the index is a naked number, decrement it right now.\n      at = parseInt(at, 10) - 1;\n    } else {\n      // If the index is dynamic, decrement it in code.\n      at = 'int(' + at + ' - 1)';\n    }\n    if (mode == 'GET') {\n      var code = list + '[' + at + ']';\n      return [code, Blockly.Python.ORDER_MEMBER];\n    } else {\n      var code = list + '.pop(' + at + ')';\n      if (mode == 'GET_REMOVE') {\n        return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n      } else if (mode == 'REMOVE') {\n        return code + '\\n';\n      }\n    }\n  } else if (where == 'FROM_END') {\n    if (mode == 'GET') {\n      var code = list + '[-' + at + ']';\n      return [code, Blockly.Python.ORDER_MEMBER];\n    } else {\n      var code = list + '.pop(-' + at + ')';\n      if (mode == 'GET_REMOVE') {\n        return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n      } else if (mode == 'REMOVE') {\n        return code + '\\n';\n      }\n    }\n  } else if (where == 'RANDOM') {\n    Blockly.Python.definitions_['import_random'] = 'import random';\n    if (mode == 'GET') {\n      code = 'random.choice(' + list + ')';\n      return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n    } else {\n      var functionName = Blockly.Python.provideFunction_(\n          'lists_remove_random_item',\n          ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):',\n           '  x = int(random.random() * len(myList))',\n           '  return myList.pop(x)']);\n      code = functionName + '(' + list + ')';\n      if (mode == 'GET_REMOVE') {\n        return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n      } else if (mode == 'REMOVE') {\n        return code + '\\n';\n      }\n    }\n  }\n  throw 'Unhandled combination (lists_getIndex).';\n};\n\nBlockly.Python['lists_setIndex'] = function(block) {\n  // Set element at index.\n  // Note: Until February 2013 this block did not have MODE or WHERE inputs.\n  var list = Blockly.Python.valueToCode(block, 'LIST',\n      Blockly.Python.ORDER_MEMBER) || '[]';\n  var mode = block.getFieldValue('MODE') || 'GET';\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.Python.valueToCode(block, 'AT',\n      Blockly.Python.ORDER_NONE) || '1';\n  var value = Blockly.Python.valueToCode(block, 'TO',\n      Blockly.Python.ORDER_NONE) || 'None';\n  // Cache non-trivial values to variables to prevent repeated look-ups.\n  // Closure, which accesses and modifies 'list'.\n  function cacheList() {\n    if (list.match(/^\\w+$/)) {\n      return '';\n    }\n    var listVar = Blockly.Python.variableDB_.getDistinctName(\n        'tmp_list', Blockly.Variables.NAME_TYPE);\n    var code = listVar + ' = ' + list + '\\n';\n    list = listVar;\n    return code;\n  }\n  if (where == 'FIRST') {\n    if (mode == 'SET') {\n      return list + '[0] = ' + value + '\\n';\n    } else if (mode == 'INSERT') {\n      return list + '.insert(0, ' + value + ')\\n';\n    }\n  } else if (where == 'LAST') {\n    if (mode == 'SET') {\n      return list + '[-1] = ' + value + '\\n';\n    } else if (mode == 'INSERT') {\n      return list + '.append(' + value + ')\\n';\n    }\n  } else if (where == 'FROM_START') {\n    // Blockly uses one-based indicies.\n    if (Blockly.isNumber(at)) {\n      // If the index is a naked number, decrement it right now.\n      at = parseInt(at, 10) - 1;\n    } else {\n      // If the index is dynamic, decrement it in code.\n      at = 'int(' + at + ' - 1)';\n    }\n    if (mode == 'SET') {\n      return list + '[' + at + '] = ' + value + '\\n';\n    } else if (mode == 'INSERT') {\n      return list + '.insert(' + at + ', ' + value + ')\\n';\n    }\n  } else if (where == 'FROM_END') {\n    if (mode == 'SET') {\n      return list + '[-' + at + '] = ' + value + '\\n';\n    } else if (mode == 'INSERT') {\n      return list + '.insert(-' + at + ', ' + value + ')\\n';\n    }\n  } else if (where == 'RANDOM') {\n    Blockly.Python.definitions_['import_random'] = 'import random';\n    var code = cacheList();\n    var xVar = Blockly.Python.variableDB_.getDistinctName(\n        'tmp_x', Blockly.Variables.NAME_TYPE);\n    code += xVar + ' = int(random.random() * len(' + list + '))\\n';\n    if (mode == 'SET') {\n      code += list + '[' + xVar + '] = ' + value + '\\n';\n      return code;\n    } else if (mode == 'INSERT') {\n      code += list + '.insert(' + xVar + ', ' + value + ')\\n';\n      return code;\n    }\n  }\n  throw 'Unhandled combination (lists_setIndex).';\n};\n\nBlockly.Python['lists_getSublist'] = function(block) {\n  // Get sublist.\n  var list = Blockly.Python.valueToCode(block, 'LIST',\n      Blockly.Python.ORDER_MEMBER) || '[]';\n  var where1 = block.getFieldValue('WHERE1');\n  var where2 = block.getFieldValue('WHERE2');\n  var at1 = Blockly.Python.valueToCode(block, 'AT1',\n      Blockly.Python.ORDER_ADDITIVE) || '1';\n  var at2 = Blockly.Python.valueToCode(block, 'AT2',\n      Blockly.Python.ORDER_ADDITIVE) || '1';\n  if (where1 == 'FIRST' || (where1 == 'FROM_START' && at1 == '1')) {\n    at1 = '';\n  } else if (where1 == 'FROM_START') {\n    // Blockly uses one-based indicies.\n    if (Blockly.isNumber(at1)) {\n      // If the index is a naked number, decrement it right now.\n      at1 = parseInt(at1, 10) - 1;\n    } else {\n      // If the index is dynamic, decrement it in code.\n      at1 = 'int(' + at1 + ' - 1)';\n    }\n  } else if (where1 == 'FROM_END') {\n    if (Blockly.isNumber(at1)) {\n      at1 = -parseInt(at1, 10);\n    } else {\n      at1 = '-int(' + at1 + ')';\n    }\n  }\n  if (where2 == 'LAST' || (where2 == 'FROM_END' && at2 == '1')) {\n    at2 = '';\n  } else if (where1 == 'FROM_START') {\n    if (Blockly.isNumber(at2)) {\n      at2 = parseInt(at2, 10);\n    } else {\n      at2 = 'int(' + at2 + ')';\n    }\n  } else if (where1 == 'FROM_END') {\n    if (Blockly.isNumber(at2)) {\n      // If the index is a naked number, increment it right now.\n      // Add special case for -0.\n      at2 = 1 - parseInt(at2, 10);\n      if (at2 == 0) {\n        at2 = '';\n      }\n    } else {\n      // If the index is dynamic, increment it in code.\n      Blockly.Python.definitions_['import_sys'] = 'import sys';\n      at2 = 'int(1 - ' + at2 + ') or sys.maxsize';\n    }\n  }\n  var code = list + '[' + at1 + ' : ' + at2 + ']';\n  return [code, Blockly.Python.ORDER_MEMBER];\n};\n"
  },
  {
    "path": "extern/blockly/generators/python/logic.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for logic blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Python.logic');\n\ngoog.require('Blockly.Python');\n\n\nBlockly.Python['controls_if'] = function(block) {\n  // If/elseif/else condition.\n  var n = 0;\n  var argument = Blockly.Python.valueToCode(block, 'IF' + n,\n      Blockly.Python.ORDER_NONE) || 'False';\n  var branch = Blockly.Python.statementToCode(block, 'DO' + n) || '  pass\\n';\n  var code = 'if ' + argument + ':\\n' + branch;\n  for (n = 1; n <= block.elseifCount_; n++) {\n    argument = Blockly.Python.valueToCode(block, 'IF' + n,\n        Blockly.Python.ORDER_NONE) || 'False';\n    branch = Blockly.Python.statementToCode(block, 'DO' + n) || '  pass\\n';\n    code += 'elif ' + argument + ':\\n' + branch;\n  }\n  if (block.elseCount_) {\n    branch = Blockly.Python.statementToCode(block, 'ELSE') || '  pass\\n';\n    code += 'else:\\n' + branch;\n  }\n  return code;\n};\n\nBlockly.Python['logic_compare'] = function(block) {\n  // Comparison operator.\n  var OPERATORS = {\n    EQ: '==',\n    NEQ: '!=',\n    LT: '<',\n    LTE: '<=',\n    GT: '>',\n    GTE: '>='\n  };\n  var operator = OPERATORS[block.getFieldValue('OP')];\n  var order = Blockly.Python.ORDER_RELATIONAL;\n  var argument0 = Blockly.Python.valueToCode(block, 'A', order) || '0';\n  var argument1 = Blockly.Python.valueToCode(block, 'B', order) || '0';\n  var code = argument0 + ' ' + operator + ' ' + argument1;\n  return [code, order];\n};\n\nBlockly.Python['logic_operation'] = function(block) {\n  // Operations 'and', 'or'.\n  var operator = (block.getFieldValue('OP') == 'AND') ? 'and' : 'or';\n  var order = (operator == 'and') ? Blockly.Python.ORDER_LOGICAL_AND :\n      Blockly.Python.ORDER_LOGICAL_OR;\n  var argument0 = Blockly.Python.valueToCode(block, 'A', order);\n  var argument1 = Blockly.Python.valueToCode(block, 'B', order);\n  if (!argument0 && !argument1) {\n    // If there are no arguments, then the return value is false.\n    argument0 = 'False';\n    argument1 = 'False';\n  } else {\n    // Single missing arguments have no effect on the return value.\n    var defaultArgument = (operator == 'and') ? 'True' : 'False';\n    if (!argument0) {\n      argument0 = defaultArgument;\n    }\n    if (!argument1) {\n      argument1 = defaultArgument;\n    }\n  }\n  var code = argument0 + ' ' + operator + ' ' + argument1;\n  return [code, order];\n};\n\nBlockly.Python['logic_negate'] = function(block) {\n  // Negation.\n  var argument0 = Blockly.Python.valueToCode(block, 'BOOL',\n      Blockly.Python.ORDER_LOGICAL_NOT) || 'True';\n  var code = 'not ' + argument0;\n  return [code, Blockly.Python.ORDER_LOGICAL_NOT];\n};\n\nBlockly.Python['logic_boolean'] = function(block) {\n  // Boolean values true and false.\n  var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'True' : 'False';\n  return [code, Blockly.Python.ORDER_ATOMIC];\n};\n\nBlockly.Python['logic_null'] = function(block) {\n  // Null data type.\n  return ['None', Blockly.Python.ORDER_ATOMIC];\n};\n\nBlockly.Python['logic_ternary'] = function(block) {\n  // Ternary operator.\n  var value_if = Blockly.Python.valueToCode(block, 'IF',\n      Blockly.Python.ORDER_CONDITIONAL) || 'False';\n  var value_then = Blockly.Python.valueToCode(block, 'THEN',\n      Blockly.Python.ORDER_CONDITIONAL) || 'None';\n  var value_else = Blockly.Python.valueToCode(block, 'ELSE',\n      Blockly.Python.ORDER_CONDITIONAL) || 'None';\n  var code = value_then + ' if ' + value_if + ' else ' + value_else\n  return [code, Blockly.Python.ORDER_CONDITIONAL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/python/loops.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for loop blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Python.loops');\n\ngoog.require('Blockly.Python');\n\n\nBlockly.Python['controls_repeat'] = function(block) {\n  // Repeat n times (internal number).\n  var repeats = parseInt(block.getFieldValue('TIMES'), 10);\n  var branch = Blockly.Python.statementToCode(block, 'DO') || '  pass\\n';\n  if (Blockly.Python.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var loopVar = Blockly.Python.variableDB_.getDistinctName(\n      'count', Blockly.Variables.NAME_TYPE);\n  var code = 'for ' + loopVar + ' in range(' + repeats + '):\\n' + branch;\n  return code;\n};\n\nBlockly.Python['controls_repeat_ext'] = function(block) {\n  // Repeat n times (external number).\n  var repeats = Blockly.Python.valueToCode(block, 'TIMES',\n      Blockly.Python.ORDER_NONE) || '0';\n  if (Blockly.isNumber(repeats)) {\n    repeats = parseInt(repeats, 10);\n  } else {\n    repeats = 'int(' + repeats + ')';\n  }\n  var branch = Blockly.Python.statementToCode(block, 'DO') || '  pass\\n';\n  if (Blockly.Python.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\\'' + block.id + '\\'') + branch;\n  }\n  var loopVar = Blockly.Python.variableDB_.getDistinctName(\n      'count', Blockly.Variables.NAME_TYPE);\n  var code = 'for ' + loopVar + ' in range(' + repeats + '):\\n' + branch;\n  return code;\n};\n\nBlockly.Python['controls_whileUntil'] = function(block) {\n  // Do while/until loop.\n  var until = block.getFieldValue('MODE') == 'UNTIL';\n  var argument0 = Blockly.Python.valueToCode(block, 'BOOL',\n      until ? Blockly.Python.ORDER_LOGICAL_NOT :\n      Blockly.Python.ORDER_NONE) || 'False';\n  var branch = Blockly.Python.statementToCode(block, 'DO') || '  pass\\n';\n  if (Blockly.Python.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\"' + block.id + '\"') + branch;\n  }\n  if (until) {\n    argument0 = 'not ' + argument0;\n  }\n  return 'while ' + argument0 + ':\\n' + branch;\n};\n\nBlockly.Python['controls_for'] = function(block) {\n  // For loop.\n  var variable0 = Blockly.Python.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.Python.valueToCode(block, 'FROM',\n      Blockly.Python.ORDER_NONE) || '0';\n  var argument1 = Blockly.Python.valueToCode(block, 'TO',\n      Blockly.Python.ORDER_NONE) || '0';\n  var increment = Blockly.Python.valueToCode(block, 'BY',\n      Blockly.Python.ORDER_NONE) || '1';\n  var branch = Blockly.Python.statementToCode(block, 'DO') || '  pass\\n';\n  if (Blockly.Python.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\"' + block.id + '\"') + branch;\n  }\n\n  var code = '';\n  var range;\n\n  // Helper functions.\n  var defineUpRange = function() {\n    return Blockly.Python.provideFunction_(\n        'upRange',\n        ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ +\n            '(start, stop, step):',\n         '  while start <= stop:',\n         '    yield start',\n         '    start += abs(step)']);\n  };\n  var defineDownRange = function() {\n    return Blockly.Python.provideFunction_(\n        'downRange',\n        ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ +\n            '(start, stop, step):',\n         '  while start >= stop:',\n         '    yield start',\n         '    start -= abs(step)']);\n  };\n  // Arguments are legal Python code (numbers or strings returned by scrub()).\n  var generateUpDownRange = function(start, end, inc) {\n    return '(' + start + ' <= ' + end + ') and ' +\n        defineUpRange() + '(' + start + ', ' + end + ', ' + inc + ') or ' +\n        defineDownRange() + '(' + start + ', ' + end + ', ' + inc + ')';\n  };\n\n  if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) &&\n      Blockly.isNumber(increment)) {\n    // All parameters are simple numbers.\n    argument0 = parseFloat(argument0);\n    argument1 = parseFloat(argument1);\n    increment = Math.abs(parseFloat(increment));\n    if (argument0 % 1 === 0 && argument1 % 1 === 0 && increment % 1 === 0) {\n      // All parameters are integers.\n      if (argument0 <= argument1) {\n        // Count up.\n        argument1++;\n        if (argument0 == 0 && increment == 1) {\n          // If starting index is 0, omit it.\n          range = argument1;\n        } else {\n          range = argument0 + ', ' + argument1;\n        }\n        // If increment isn't 1, it must be explicit.\n        if (increment != 1) {\n          range += ', ' + increment;\n        }\n      } else {\n        // Count down.\n        argument1--;\n        range = argument0 + ', ' + argument1 + ', -' + increment;\n      }\n      range = 'range(' + range + ')';\n    } else {\n      // At least one of the parameters is not an integer.\n      if (argument0 < argument1) {\n        range = defineUpRange();\n      } else {\n        range = defineDownRange();\n      }\n      range += '(' + argument0 + ', ' +  argument1 + ', ' + increment + ')';\n    }\n  } else {\n    // Cache non-trivial values to variables to prevent repeated look-ups.\n    var scrub = function(arg, suffix) {\n      if (Blockly.isNumber(arg)) {\n        // Simple number.\n        arg = parseFloat(arg);\n      } else if (arg.match(/^\\w+$/)) {\n        // Variable.\n        arg = 'float(' + arg + ')';\n      } else {\n        // It's complicated.\n        var varName = Blockly.Python.variableDB_.getDistinctName(\n            variable0 + suffix, Blockly.Variables.NAME_TYPE);\n        code += varName + ' = float(' + arg + ')\\n';\n        arg = varName;\n      }\n      return arg;\n    };\n    var startVar = scrub(argument0, '_start');\n    var endVar = scrub(argument1, '_end');\n    var incVar = scrub(increment, '_inc');\n\n    if (typeof startVar == 'number' && typeof endVar == 'number') {\n      if (startVar < endVar) {\n        range = defineUpRange(startVar, endVar, increment);\n      } else {\n        range = defineDownRange(startVar, endVar, increment);\n      }\n    } else {\n      // We cannot determine direction statically.\n      range = generateUpDownRange(startVar, endVar, increment);\n    }\n  }\n  code += 'for ' + variable0 + ' in ' + range + ':\\n' + branch;\n  return code;\n};\n\nBlockly.Python['controls_forEach'] = function(block) {\n  // For each loop.\n  var variable0 = Blockly.Python.variableDB_.getName(\n      block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.Python.valueToCode(block, 'LIST',\n      Blockly.Python.ORDER_RELATIONAL) || '[]';\n  var branch = Blockly.Python.statementToCode(block, 'DO') || '  pass\\n';\n  if (Blockly.Python.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\"' + block.id + '\"') + branch;\n  }\n  var code = 'for ' + variable0 + ' in ' + argument0 + ':\\n' + branch;\n  return code;\n};\n\nBlockly.Python['controls_flow_statements'] = function(block) {\n  // Flow statements: continue, break.\n  switch (block.getFieldValue('FLOW')) {\n    case 'BREAK':\n      return 'break\\n';\n    case 'CONTINUE':\n      return 'continue\\n';\n  }\n  throw 'Unknown flow statement.';\n};\n"
  },
  {
    "path": "extern/blockly/generators/python/math.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for math blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Python.math');\n\ngoog.require('Blockly.Python');\n\n\n// If any new block imports any library, add that library name here.\nBlockly.Python.addReservedWords('math,random');\n\nBlockly.Python['math_number'] = function(block) {\n  // Numeric value.\n  var code = parseFloat(block.getFieldValue('NUM'));\n  var order = code < 0 ? Blockly.Python.ORDER_UNARY_SIGN :\n              Blockly.Python.ORDER_ATOMIC;\n  return [code, order];\n};\n\nBlockly.Python['math_arithmetic'] = function(block) {\n  // Basic arithmetic operators, and power.\n  var OPERATORS = {\n    ADD: [' + ', Blockly.Python.ORDER_ADDITIVE],\n    MINUS: [' - ', Blockly.Python.ORDER_ADDITIVE],\n    MULTIPLY: [' * ', Blockly.Python.ORDER_MULTIPLICATIVE],\n    DIVIDE: [' / ', Blockly.Python.ORDER_MULTIPLICATIVE],\n    POWER: [' ** ', Blockly.Python.ORDER_EXPONENTIATION]\n  };\n  var tuple = OPERATORS[block.getFieldValue('OP')];\n  var operator = tuple[0];\n  var order = tuple[1];\n  var argument0 = Blockly.Python.valueToCode(block, 'A', order) || '0';\n  var argument1 = Blockly.Python.valueToCode(block, 'B', order) || '0';\n  var code = argument0 + operator + argument1;\n  return [code, order];\n  // In case of 'DIVIDE', division between integers returns different results\n  // in Python 2 and 3. However, is not an issue since Blockly does not\n  // guarantee identical results in all languages.  To do otherwise would\n  // require every operator to be wrapped in a function call.  This would kill\n  // legibility of the generated code.  See:\n  // http://code.google.com/p/blockly/wiki/Language\n};\n\nBlockly.Python['math_single'] = function(block) {\n  // Math operators with single operand.\n  var operator = block.getFieldValue('OP');\n  var code;\n  var arg;\n  if (operator == 'NEG') {\n    // Negation is a special case given its different operator precedence.\n    var code = Blockly.Python.valueToCode(block, 'NUM',\n        Blockly.Python.ORDER_UNARY_SIGN) || '0';\n    return ['-' + code, Blockly.Python.ORDER_UNARY_SIGN];\n  }\n  Blockly.Python.definitions_['import_math'] = 'import math';\n  if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') {\n    arg = Blockly.Python.valueToCode(block, 'NUM',\n        Blockly.Python.ORDER_MULTIPLICATIVE) || '0';\n  } else {\n    arg = Blockly.Python.valueToCode(block, 'NUM',\n        Blockly.Python.ORDER_NONE) || '0';\n  }\n  // First, handle cases which generate values that don't need parentheses\n  // wrapping the code.\n  switch (operator) {\n    case 'ABS':\n      code = 'math.fabs(' + arg + ')';\n      break;\n    case 'ROOT':\n      code = 'math.sqrt(' + arg + ')';\n      break;\n    case 'LN':\n      code = 'math.log(' + arg + ')';\n      break;\n    case 'LOG10':\n      code = 'math.log10(' + arg + ')';\n      break;\n    case 'EXP':\n      code = 'math.exp(' + arg + ')';\n      break;\n    case 'POW10':\n      code = 'math.pow(10,' + arg + ')';\n      break;\n    case 'ROUND':\n      code = 'round(' + arg + ')';\n      break;\n    case 'ROUNDUP':\n      code = 'math.ceil(' + arg + ')';\n      break;\n    case 'ROUNDDOWN':\n      code = 'math.floor(' + arg + ')';\n      break;\n    case 'SIN':\n      code = 'math.sin(' + arg + ' / 180.0 * math.pi)';\n      break;\n    case 'COS':\n      code = 'math.cos(' + arg + ' / 180.0 * math.pi)';\n      break;\n    case 'TAN':\n      code = 'math.tan(' + arg + ' / 180.0 * math.pi)';\n      break;\n  }\n  if (code) {\n    return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n  }\n  // Second, handle cases which generate values that may need parentheses\n  // wrapping the code.\n  switch (operator) {\n    case 'ASIN':\n      code = 'math.asin(' + arg + ') / math.pi * 180';\n      break;\n    case 'ACOS':\n      code = 'math.acos(' + arg + ') / math.pi * 180';\n      break;\n    case 'ATAN':\n      code = 'math.atan(' + arg + ') / math.pi * 180';\n      break;\n    default:\n      throw 'Unknown math operator: ' + operator;\n  }\n  return [code, Blockly.Python.ORDER_MULTIPLICATIVE];\n};\n\nBlockly.Python['math_constant'] = function(block) {\n  // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.\n  var CONSTANTS = {\n    PI: ['math.pi', Blockly.Python.ORDER_MEMBER],\n    E: ['math.e', Blockly.Python.ORDER_MEMBER],\n    GOLDEN_RATIO: ['(1 + math.sqrt(5)) / 2', Blockly.Python.ORDER_MULTIPLICATIVE],\n    SQRT2: ['math.sqrt(2)', Blockly.Python.ORDER_MEMBER],\n    SQRT1_2: ['math.sqrt(1.0 / 2)', Blockly.Python.ORDER_MEMBER],\n    INFINITY: ['float(\\'inf\\')', Blockly.Python.ORDER_ATOMIC]\n  };\n  var constant = block.getFieldValue('CONSTANT');\n  if (constant != 'INFINITY') {\n    Blockly.Python.definitions_['import_math'] = 'import math';\n  }\n  return CONSTANTS[constant];\n};\n\nBlockly.Python['math_number_property'] = function(block) {\n  // Check if a number is even, odd, prime, whole, positive, or negative\n  // or if it is divisible by certain number. Returns true or false.\n  var number_to_check = Blockly.Python.valueToCode(block, 'NUMBER_TO_CHECK',\n      Blockly.Python.ORDER_MULTIPLICATIVE) || '0';\n  var dropdown_property = block.getFieldValue('PROPERTY');\n  var code;\n  if (dropdown_property == 'PRIME') {\n    Blockly.Python.definitions_['import_math'] = 'import math';\n    var functionName = Blockly.Python.provideFunction_(\n        'math_isPrime',\n        ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(n):',\n         '  # https://en.wikipedia.org/wiki/Primality_test#Naive_methods',\n         '  # If n is not a number but a string, try parsing it.',\n         '  if type(n) not in (int, float, long):',\n         '    try:',\n         '      n = float(n)',\n         '    except:',\n         '      return False',\n         '  if n == 2 or n == 3:',\n         '    return True',\n         '  # False if n is negative, is 1, or not whole,' +\n             ' or if n is divisible by 2 or 3.',\n         '  if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:',\n         '    return False',\n         '  # Check all the numbers of form 6k +/- 1, up to sqrt(n).',\n         '  for x in range(6, int(math.sqrt(n)) + 2, 6):',\n         '    if n % (x - 1) == 0 or n % (x + 1) == 0:',\n         '      return False',\n         '  return True']);\n    code = functionName + '(' + number_to_check + ')';\n    return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n  }\n  switch (dropdown_property) {\n    case 'EVEN':\n      code = number_to_check + ' % 2 == 0';\n      break;\n    case 'ODD':\n      code = number_to_check + ' % 2 == 1';\n      break;\n    case 'WHOLE':\n      code = number_to_check + ' % 1 == 0';\n      break;\n    case 'POSITIVE':\n      code = number_to_check + ' > 0';\n      break;\n    case 'NEGATIVE':\n      code = number_to_check + ' < 0';\n      break;\n    case 'DIVISIBLE_BY':\n      var divisor = Blockly.Python.valueToCode(block, 'DIVISOR',\n          Blockly.Python.ORDER_MULTIPLICATIVE);\n      // If 'divisor' is some code that evals to 0, Python will raise an error.\n      if (!divisor || divisor == '0') {\n        return ['False', Blockly.Python.ORDER_ATOMIC];\n      }\n      code = number_to_check + ' % ' + divisor + ' == 0';\n      break;\n  }\n  return [code, Blockly.Python.ORDER_RELATIONAL];\n};\n\nBlockly.Python['math_change'] = function(block) {\n  // Add to a variable in place.\n  var argument0 = Blockly.Python.valueToCode(block, 'DELTA',\n      Blockly.Python.ORDER_ADDITIVE) || '0';\n  var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  return varName + ' = (' + varName + ' if type(' + varName +\n      ') in (int, float, long) else 0) + ' + argument0 + '\\n';\n};\n\n// Rounding functions have a single operand.\nBlockly.Python['math_round'] = Blockly.Python['math_single'];\n// Trigonometry functions have a single operand.\nBlockly.Python['math_trig'] = Blockly.Python['math_single'];\n\nBlockly.Python['math_on_list'] = function(block) {\n  // Math functions for lists.\n  var func = block.getFieldValue('OP');\n  var list = Blockly.Python.valueToCode(block, 'LIST',\n      Blockly.Python.ORDER_NONE) || '[]';\n  var code;\n  switch (func) {\n    case 'SUM':\n      code = 'sum(' + list + ')';\n      break;\n    case 'MIN':\n      code = 'min(' + list + ')';\n      break;\n    case 'MAX':\n      code = 'max(' + list + ')';\n      break;\n    case 'AVERAGE':\n      var functionName = Blockly.Python.provideFunction_(\n          'math_mean',\n          // This operation excludes null and values that are not int or float:',\n          // math_mean([null, null, \"aString\", 1, 9]) == 5.0.',\n          ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):',\n           '  localList = [e for e in myList if type(e) in (int, float, long)]',\n           '  if not localList: return',\n           '  return float(sum(localList)) / len(localList)']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'MEDIAN':\n      var functionName = Blockly.Python.provideFunction_(\n          'math_median',\n          // This operation excludes null values:\n          // math_median([null, null, 1, 3]) == 2.0.\n          ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):',\n           '  localList = sorted([e for e in myList ' +\n               'if type(e) in (int, float, long)])',\n           '  if not localList: return',\n           '  if len(localList) % 2 == 0:',\n           '    return (localList[len(localList) / 2 - 1] + ' +\n               'localList[len(localList) / 2]) / 2.0',\n           '  else:',\n           '    return localList[(len(localList) - 1) / 2]']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'MODE':\n      var functionName = Blockly.Python.provideFunction_(\n          'math_modes',\n          // As a list of numbers can contain more than one mode,\n          // the returned result is provided as an array.\n          // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1].\n          ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(some_list):',\n           '  modes = []',\n           '  # Using a lists of [item, count] to keep count rather than dict',\n           '  # to avoid \"unhashable\" errors when the counted item is ' +\n               'itself a list or dict.',\n           '  counts = []',\n           '  maxCount = 1',\n           '  for item in some_list:',\n           '    found = False',\n           '    for count in counts:',\n           '      if count[0] == item:',\n           '        count[1] += 1',\n           '        maxCount = max(maxCount, count[1])',\n           '        found = True',\n           '    if not found:',\n           '      counts.append([item, 1])',\n           '  for counted_item, item_count in counts:',\n           '    if item_count == maxCount:',\n           '      modes.append(counted_item)',\n           '  return modes']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'STD_DEV':\n      Blockly.Python.definitions_['import_math'] = 'import math';\n      var functionName = Blockly.Python.provideFunction_(\n          'math_standard_deviation',\n          ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(numbers):',\n           '  n = len(numbers)',\n           '  if n == 0: return',\n           '  mean = float(sum(numbers)) / n',\n           '  variance = sum((x - mean) ** 2 for x in numbers) / n',\n           '  return math.sqrt(variance)']);\n      code = functionName + '(' + list + ')';\n      break;\n    case 'RANDOM':\n      Blockly.Python.definitions_['import_random'] = 'import random';\n      code = 'random.choice(' + list + ')';\n      break;\n    default:\n      throw 'Unknown operator: ' + func;\n  }\n  return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n};\n\nBlockly.Python['math_modulo'] = function(block) {\n  // Remainder computation.\n  var argument0 = Blockly.Python.valueToCode(block, 'DIVIDEND',\n      Blockly.Python.ORDER_MULTIPLICATIVE) || '0';\n  var argument1 = Blockly.Python.valueToCode(block, 'DIVISOR',\n      Blockly.Python.ORDER_MULTIPLICATIVE) || '0';\n  var code = argument0 + ' % ' + argument1;\n  return [code, Blockly.Python.ORDER_MULTIPLICATIVE];\n};\n\nBlockly.Python['math_constrain'] = function(block) {\n  // Constrain a number between two limits.\n  var argument0 = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_NONE) || '0';\n  var argument1 = Blockly.Python.valueToCode(block, 'LOW',\n      Blockly.Python.ORDER_NONE) || '0';\n  var argument2 = Blockly.Python.valueToCode(block, 'HIGH',\n      Blockly.Python.ORDER_NONE) || 'float(\\'inf\\')';\n  var code = 'min(max(' + argument0 + ', ' + argument1 + '), ' +\n      argument2 + ')';\n  return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n};\n\nBlockly.Python['math_random_int'] = function(block) {\n  // Random integer between [X] and [Y].\n  Blockly.Python.definitions_['import_random'] = 'import random';\n  var argument0 = Blockly.Python.valueToCode(block, 'FROM',\n      Blockly.Python.ORDER_NONE) || '0';\n  var argument1 = Blockly.Python.valueToCode(block, 'TO',\n      Blockly.Python.ORDER_NONE) || '0';\n  var code = 'random.randint(' + argument0 + ', ' + argument1 + ')';\n  return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n};\n\nBlockly.Python['math_random_float'] = function(block) {\n  // Random fraction between 0 and 1.\n  Blockly.Python.definitions_['import_random'] = 'import random';\n  return ['random.random()', Blockly.Python.ORDER_FUNCTION_CALL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/python/procedures.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for procedure blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Python.procedures');\n\ngoog.require('Blockly.Python');\n\n\nBlockly.Python['procedures_defreturn'] = function(block) {\n  // Define a procedure with a return value.\n  // First, add a 'global' statement for every variable that is assigned.\n  var globals = Blockly.Variables.allVariables(block);\n  for (var i = globals.length - 1; i >= 0; i--) {\n    var varName = globals[i];\n    if (block.arguments_.indexOf(varName) == -1) {\n      globals[i] = Blockly.Python.variableDB_.getName(varName,\n          Blockly.Variables.NAME_TYPE);\n    } else {\n      // This variable is actually a parameter name.  Do not include it in\n      // the list of globals, thus allowing it be of local scope.\n      globals.splice(i, 1);\n    }\n  }\n  globals = globals.length ? '  global ' + globals.join(', ') + '\\n' : '';\n  var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'),\n      Blockly.Procedures.NAME_TYPE);\n  var branch = Blockly.Python.statementToCode(block, 'STACK');\n  if (Blockly.Python.INFINITE_LOOP_TRAP) {\n    branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,\n        '\"' + block.id + '\"') + branch;\n  }\n  var returnValue = Blockly.Python.valueToCode(block, 'RETURN',\n      Blockly.Python.ORDER_NONE) || '';\n  if (returnValue) {\n    returnValue = '  return ' + returnValue + '\\n';\n  } else if (!branch) {\n    branch = '  pass';\n  }\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.Python.variableDB_.getName(block.arguments_[x],\n        Blockly.Variables.NAME_TYPE);\n  }\n  var code = 'def ' + funcName + '(' + args.join(', ') + '):\\n' +\n      globals + branch + returnValue;\n  code = Blockly.Python.scrub_(block, code);\n  Blockly.Python.definitions_[funcName] = code;\n  return null;\n};\n\n// Defining a procedure without a return value uses the same generator as\n// a procedure with a return value.\nBlockly.Python['procedures_defnoreturn'] =\n    Blockly.Python['procedures_defreturn'];\n\nBlockly.Python['procedures_callreturn'] = function(block) {\n  // Call a procedure with a return value.\n  var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'),\n      Blockly.Procedures.NAME_TYPE);\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.Python.valueToCode(block, 'ARG' + x,\n        Blockly.Python.ORDER_NONE) || 'None';\n  }\n  var code = funcName + '(' + args.join(', ') + ')';\n  return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n};\n\nBlockly.Python['procedures_callnoreturn'] = function(block) {\n  // Call a procedure with no return value.\n  var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'),\n      Blockly.Procedures.NAME_TYPE);\n  var args = [];\n  for (var x = 0; x < block.arguments_.length; x++) {\n    args[x] = Blockly.Python.valueToCode(block, 'ARG' + x,\n        Blockly.Python.ORDER_NONE) || 'None';\n  }\n  var code = funcName + '(' + args.join(', ') + ')\\n';\n  return code;\n};\n\nBlockly.Python['procedures_ifreturn'] = function(block) {\n  // Conditionally return value from a procedure.\n  var condition = Blockly.Python.valueToCode(block, 'CONDITION',\n      Blockly.Python.ORDER_NONE) || 'False';\n  var code = 'if ' + condition + ':\\n';\n  if (block.hasReturnValue_) {\n    var value = Blockly.Python.valueToCode(block, 'VALUE',\n        Blockly.Python.ORDER_NONE) || 'None';\n    code += '  return ' + value + '\\n';\n  } else {\n    code += '  return\\n';\n  }\n  return code;\n};\n"
  },
  {
    "path": "extern/blockly/generators/python/text.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for text blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Python.text');\n\ngoog.require('Blockly.Python');\n\n\nBlockly.Python['text'] = function(block) {\n  // Text value.\n  var code = Blockly.Python.quote_(block.getFieldValue('TEXT'));\n  return [code, Blockly.Python.ORDER_ATOMIC];\n};\n\nBlockly.Python['text_join'] = function(block) {\n  // Create a string made up of any number of elements of any type.\n  //Should we allow joining by '-' or ',' or any other characters?\n  var code;\n  if (block.itemCount_ == 0) {\n    return ['\\'\\'', Blockly.Python.ORDER_ATOMIC];\n  } else if (block.itemCount_ == 1) {\n    var argument0 = Blockly.Python.valueToCode(block, 'ADD0',\n        Blockly.Python.ORDER_NONE) || '\\'\\'';\n    code = 'str(' + argument0 + ')';\n    return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n  } else if (block.itemCount_ == 2) {\n    var argument0 = Blockly.Python.valueToCode(block, 'ADD0',\n        Blockly.Python.ORDER_NONE) || '\\'\\'';\n    var argument1 = Blockly.Python.valueToCode(block, 'ADD1',\n        Blockly.Python.ORDER_NONE) || '\\'\\'';\n    var code = 'str(' + argument0 + ') + str(' + argument1 + ')';\n    return [code, Blockly.Python.ORDER_UNARY_SIGN];\n  } else {\n    var code = [];\n    for (var n = 0; n < block.itemCount_; n++) {\n      code[n] = Blockly.Python.valueToCode(block, 'ADD' + n,\n          Blockly.Python.ORDER_NONE) || '\\'\\'';\n    }\n    var tempVar = Blockly.Python.variableDB_.getDistinctName('temp_value',\n        Blockly.Variables.NAME_TYPE);\n    code = '\\'\\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' +\n        code.join(', ') + ']])';\n    return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n  }\n};\n\nBlockly.Python['text_append'] = function(block) {\n  // Append to a variable in place.\n  var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  var argument0 = Blockly.Python.valueToCode(block, 'TEXT',\n      Blockly.Python.ORDER_NONE) || '\\'\\'';\n  return varName + ' = str(' + varName + ') + str(' + argument0 + ')\\n';\n};\n\nBlockly.Python['text_length'] = function(block) {\n  // String length.\n  var argument0 = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_NONE) || '\\'\\'';\n  return ['len(' + argument0 + ')', Blockly.Python.ORDER_FUNCTION_CALL];\n};\n\nBlockly.Python['text_isEmpty'] = function(block) {\n  // Is the string null?\n  var argument0 = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_NONE) || '\\'\\'';\n  var code = 'not len(' + argument0 + ')';\n  return [code, Blockly.Python.ORDER_LOGICAL_NOT];\n};\n\nBlockly.Python['text_indexOf'] = function(block) {\n  // Search the text for a substring.\n  // Should we allow for non-case sensitive???\n  var operator = block.getFieldValue('END') == 'FIRST' ? 'find' : 'rfind';\n  var argument0 = Blockly.Python.valueToCode(block, 'FIND',\n      Blockly.Python.ORDER_NONE) || '\\'\\'';\n  var argument1 = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_MEMBER) || '\\'\\'';\n  var code = argument1 + '.' + operator + '(' + argument0 + ') + 1';\n  return [code, Blockly.Python.ORDER_MEMBER];\n};\n\nBlockly.Python['text_charAt'] = function(block) {\n  // Get letter at index.\n  // Note: Until January 2013 this block did not have the WHERE input.\n  var where = block.getFieldValue('WHERE') || 'FROM_START';\n  var at = Blockly.Python.valueToCode(block, 'AT',\n      Blockly.Python.ORDER_UNARY_SIGN) || '1';\n  var text = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_MEMBER) || '\\'\\'';\n  switch (where) {\n    case 'FIRST':\n      var code = text + '[0]';\n      return [code, Blockly.Python.ORDER_MEMBER];\n    case 'LAST':\n      var code = text + '[-1]';\n      return [code, Blockly.Python.ORDER_MEMBER];\n    case 'FROM_START':\n      // Blockly uses one-based indicies.\n      if (Blockly.isNumber(at)) {\n        // If the index is a naked number, decrement it right now.\n        at = parseInt(at, 10) - 1;\n      } else {\n        // If the index is dynamic, decrement it in code.\n        at = 'int(' + at + ' - 1)';\n      }\n      var code = text + '[' + at + ']';\n      return [code, Blockly.Python.ORDER_MEMBER];\n    case 'FROM_END':\n      var code = text + '[-' + at + ']';\n      return [code, Blockly.Python.ORDER_MEMBER];\n    case 'RANDOM':\n      Blockly.Python.definitions_['import_random'] = 'import random';\n      var functionName = Blockly.Python.provideFunction_(\n          'text_random_letter',\n          ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(text):',\n           '  x = int(random.random() * len(text))',\n           '  return text[x];']);\n      code = functionName + '(' + text + ')';\n      return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n  }\n  throw 'Unhandled option (text_charAt).';\n};\n\nBlockly.Python['text_getSubstring'] = function(block) {\n  // Get substring.\n  var text = Blockly.Python.valueToCode(block, 'STRING',\n      Blockly.Python.ORDER_MEMBER) || '\\'\\'';\n  var where1 = block.getFieldValue('WHERE1');\n  var where2 = block.getFieldValue('WHERE2');\n  var at1 = Blockly.Python.valueToCode(block, 'AT1',\n      Blockly.Python.ORDER_ADDITIVE) || '1';\n  var at2 = Blockly.Python.valueToCode(block, 'AT2',\n      Blockly.Python.ORDER_ADDITIVE) || '1';\n  if (where1 == 'FIRST' || (where1 == 'FROM_START' && at1 == '1')) {\n    at1 = '';\n  } else if (where1 == 'FROM_START') {\n    // Blockly uses one-based indicies.\n    if (Blockly.isNumber(at1)) {\n      // If the index is a naked number, decrement it right now.\n      at1 = parseInt(at1, 10) - 1;\n    } else {\n      // If the index is dynamic, decrement it in code.\n      at1 = 'int(' + at1 + ' - 1)';\n    }\n  } else if (where1 == 'FROM_END') {\n    if (Blockly.isNumber(at1)) {\n      at1 = -parseInt(at1, 10);\n    } else {\n      at1 = '-int(' + at1 + ')';\n    }\n  }\n  if (where2 == 'LAST' || (where2 == 'FROM_END' && at2 == '1')) {\n    at2 = '';\n  } else if (where1 == 'FROM_START') {\n    if (Blockly.isNumber(at2)) {\n      at2 = parseInt(at2, 10);\n    } else {\n      at2 = 'int(' + at2 + ')';\n    }\n  } else if (where1 == 'FROM_END') {\n    if (Blockly.isNumber(at2)) {\n      // If the index is a naked number, increment it right now.\n      at2 = 1 - parseInt(at2, 10);\n      if (at2 == 0) {\n        at2 = '';\n      }\n    } else {\n      // If the index is dynamic, increment it in code.\n      // Add special case for -0.\n      Blockly.Python.definitions_['import_sys'] = 'import sys';\n      at2 = 'int(1 - ' + at2 + ') or sys.maxsize';\n    }\n  }\n  var code = text + '[' + at1 + ' : ' + at2 + ']';\n  return [code, Blockly.Python.ORDER_MEMBER];\n};\n\nBlockly.Python['text_changeCase'] = function(block) {\n  // Change capitalization.\n  var OPERATORS = {\n    UPPERCASE: '.upper()',\n    LOWERCASE: '.lower()',\n    TITLECASE: '.title()'\n  };\n  var operator = OPERATORS[block.getFieldValue('CASE')];\n  var argument0 = Blockly.Python.valueToCode(block, 'TEXT',\n      Blockly.Python.ORDER_MEMBER) || '\\'\\'';\n  var code = argument0 + operator;\n  return [code, Blockly.Python.ORDER_MEMBER];\n};\n\nBlockly.Python['text_trim'] = function(block) {\n  // Trim spaces.\n  var OPERATORS = {\n    LEFT: '.lstrip()',\n    RIGHT: '.rstrip()',\n    BOTH: '.strip()'\n  };\n  var operator = OPERATORS[block.getFieldValue('MODE')];\n  var argument0 = Blockly.Python.valueToCode(block, 'TEXT',\n      Blockly.Python.ORDER_MEMBER) || '\\'\\'';\n  var code = argument0 + operator;\n  return [code, Blockly.Python.ORDER_MEMBER];\n};\n\nBlockly.Python['text_print'] = function(block) {\n  // Print statement.\n  var argument0 = Blockly.Python.valueToCode(block, 'TEXT',\n      Blockly.Python.ORDER_NONE) || '\\'\\'';\n  return 'print(' + argument0 + ')\\n';\n};\n\nBlockly.Python['text_prompt'] = function(block) {\n  // Prompt function.\n  var functionName = Blockly.Python.provideFunction_(\n      'text_prompt',\n      ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(msg):',\n       '  try:',\n       '    return raw_input(msg)',\n       '  except NameError:',\n       '    return input(msg)']);\n  var msg = Blockly.Python.quote_(block.getFieldValue('TEXT'));\n  var code = functionName + '(' + msg + ')';\n  var toNumber = block.getFieldValue('TYPE') == 'NUMBER';\n  if (toNumber) {\n    code = 'float(' + code + ')';\n  }\n  return [code, Blockly.Python.ORDER_FUNCTION_CALL];\n};\n"
  },
  {
    "path": "extern/blockly/generators/python/variables.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for variable blocks.\n * @author q.neutron@gmail.com (Quynh Neutron)\n */\n'use strict';\n\ngoog.provide('Blockly.Python.variables');\n\ngoog.require('Blockly.Python');\n\n\nBlockly.Python['variables_get'] = function(block) {\n  // Variable getter.\n  var code = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  return [code, Blockly.Python.ORDER_ATOMIC];\n};\n\nBlockly.Python['variables_set'] = function(block) {\n  // Variable setter.\n  var argument0 = Blockly.Python.valueToCode(block, 'VALUE',\n      Blockly.Python.ORDER_NONE) || '0';\n  var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),\n      Blockly.Variables.NAME_TYPE);\n  return varName + ' = ' + argument0 + '\\n';\n};\n"
  },
  {
    "path": "extern/blockly/generators/python.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Helper functions for generating Python for blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Python');\n\ngoog.require('Blockly.Generator');\n\n\nBlockly.Python = new Blockly.Generator('Python');\n\n/**\n * List of illegal variable names.\n * This is not intended to be a security feature.  Blockly is 100% client-side,\n * so bypassing this list is trivial.  This is intended to prevent users from\n * accidentally clobbering a built-in object or function.\n * @private\n */\nBlockly.Python.addReservedWords(\n    // import keyword\n    // print ','.join(keyword.kwlist)\n    // http://docs.python.org/reference/lexical_analysis.html#keywords\n    'and,as,assert,break,class,continue,def,del,elif,else,except,exec,finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,return,try,while,with,yield,' +\n    //http://docs.python.org/library/constants.html\n    'True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,' +\n    // http://docs.python.org/library/functions.html\n    'abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,coerce,dir,id,oct,sorted,intern');\n\n/**\n * Order of operation ENUMs.\n * http://docs.python.org/reference/expressions.html#summary\n */\nBlockly.Python.ORDER_ATOMIC = 0;            // 0 \"\" ...\nBlockly.Python.ORDER_COLLECTION = 1;        // tuples, lists, dictionaries\nBlockly.Python.ORDER_STRING_CONVERSION = 1; // `expression...`\nBlockly.Python.ORDER_MEMBER = 2;            // . []\nBlockly.Python.ORDER_FUNCTION_CALL = 2;     // ()\nBlockly.Python.ORDER_EXPONENTIATION = 3;    // **\nBlockly.Python.ORDER_UNARY_SIGN = 4;        // + -\nBlockly.Python.ORDER_BITWISE_NOT = 4;       // ~\nBlockly.Python.ORDER_MULTIPLICATIVE = 5;    // * / // %\nBlockly.Python.ORDER_ADDITIVE = 6;          // + -\nBlockly.Python.ORDER_BITWISE_SHIFT = 7;     // << >>\nBlockly.Python.ORDER_BITWISE_AND = 8;       // &\nBlockly.Python.ORDER_BITWISE_XOR = 9;       // ^\nBlockly.Python.ORDER_BITWISE_OR = 10;       // |\nBlockly.Python.ORDER_RELATIONAL = 11;       // in, not in, is, is not,\n                                            //     <, <=, >, >=, <>, !=, ==\nBlockly.Python.ORDER_LOGICAL_NOT = 12;      // not\nBlockly.Python.ORDER_LOGICAL_AND = 13;      // and\nBlockly.Python.ORDER_LOGICAL_OR = 14;       // or\nBlockly.Python.ORDER_CONDITIONAL = 15;      // if else\nBlockly.Python.ORDER_LAMBDA = 16;           // lambda\nBlockly.Python.ORDER_NONE = 99;             // (...)\n\n/**\n * Arbitrary code to inject into locations that risk causing infinite loops.\n * Any instances of '%1' will be replaced by the block ID that failed.\n * E.g. '  checkTimeout(%1)\\n'\n * @type ?string\n */\nBlockly.Python.INFINITE_LOOP_TRAP = null;\n\n/**\n * Initialise the database of variable names.\n */\nBlockly.Python.init = function() {\n  // Create a dictionary of definitions to be printed before the code.\n  Blockly.Python.definitions_ = Object.create(null);\n  // Create a dictionary mapping desired function names in definitions_\n  // to actual function names (to avoid collisions with user functions).\n  Blockly.Python.functionNames_ = Object.create(null);\n\n  if (Blockly.Variables) {\n    if (!Blockly.Python.variableDB_) {\n      Blockly.Python.variableDB_ =\n          new Blockly.Names(Blockly.Python.RESERVED_WORDS_);\n    } else {\n      Blockly.Python.variableDB_.reset();\n    }\n\n    var defvars = [];\n    var variables = Blockly.Variables.allVariables();\n    for (var x = 0; x < variables.length; x++) {\n      defvars[x] = Blockly.Python.variableDB_.getName(variables[x],\n          Blockly.Variables.NAME_TYPE) + ' = None';\n    }\n    Blockly.Python.definitions_['variables'] = defvars.join('\\n');\n  }\n};\n\n/**\n * Prepend the generated code with the variable definitions.\n * @param {string} code Generated code.\n * @return {string} Completed code.\n */\nBlockly.Python.finish = function(code) {\n  // Convert the definitions dictionary into a list.\n  var imports = [];\n  var definitions = [];\n  for (var name in Blockly.Python.definitions_) {\n    var def = Blockly.Python.definitions_[name];\n    if (def.match(/^(from\\s+\\S+\\s+)?import\\s+\\S+/)) {\n      imports.push(def);\n    } else {\n      definitions.push(def);\n    }\n  }\n  var allDefs = imports.join('\\n') + '\\n\\n' + definitions.join('\\n\\n');\n  return allDefs.replace(/\\n\\n+/g, '\\n\\n').replace(/\\n*$/, '\\n\\n\\n') + code;\n};\n\n/**\n * Naked values are top-level blocks with outputs that aren't plugged into\n * anything.\n * @param {string} line Line of generated code.\n * @return {string} Legal line of code.\n */\nBlockly.Python.scrubNakedValue = function(line) {\n  return line + '\\n';\n};\n\n/**\n * Encode a string as a properly escaped Python string, complete with quotes.\n * @param {string} string Text to encode.\n * @return {string} Python string.\n * @private\n */\nBlockly.Python.quote_ = function(string) {\n  // TODO: This is a quick hack.  Replace with goog.string.quote\n  string = string.replace(/\\\\/g, '\\\\\\\\')\n                 .replace(/\\n/g, '\\\\\\n')\n                 .replace(/\\%/g, '\\\\%')\n                 .replace(/'/g, '\\\\\\'');\n  return '\\'' + string + '\\'';\n};\n\n/**\n * Common tasks for generating Python from blocks.\n * Handles comments for the specified block and any connected value blocks.\n * Calls any statements following this block.\n * @param {!Blockly.Block} block The current block.\n * @param {string} code The Python code created for this block.\n * @return {string} Python code with comments and subsequent blocks added.\n * @this {Blockly.CodeGenerator}\n * @private\n */\nBlockly.Python.scrub_ = function(block, code) {\n  if (code === null) {\n    // Block has handled code generation itself.\n    return '';\n  }\n  var commentCode = '';\n  // Only collect comments for blocks that aren't inline.\n  if (!block.outputConnection || !block.outputConnection.targetConnection) {\n    // Collect comment for this block.\n    var comment = block.getCommentText();\n    if (comment) {\n      commentCode += this.prefixLines(comment, '# ') + '\\n';\n    }\n    // Collect comments for all value arguments.\n    // Don't collect comments for nested statements.\n    for (var x = 0; x < block.inputList.length; x++) {\n      if (block.inputList[x].type == Blockly.INPUT_VALUE) {\n        var childBlock = block.inputList[x].connection.targetBlock();\n        if (childBlock) {\n          var comment = this.allNestedComments(childBlock);\n          if (comment) {\n            commentCode += this.prefixLines(comment, '# ');\n          }\n        }\n      }\n    }\n  }\n  var nextBlock = block.nextConnection && block.nextConnection.targetBlock();\n  var nextCode = this.blockToCode(nextBlock);\n  return commentCode + code + nextCode;\n};\n"
  },
  {
    "path": "extern/blockly/i18n/common.py",
    "content": "#!/usr/bin/python\n\n# Code shared by translation conversion scripts.\n#\n# Copyright 2013 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport codecs\nimport json\nimport os\nfrom datetime import datetime\n\nclass InputError(Exception):\n    \"\"\"Exception raised for errors in the input.\n\n    Attributes:\n        location -- where error occurred\n        msg -- explanation of the error\n\n    \"\"\"\n\n    def __init__(self, location, msg):\n        Exception.__init__(self, '{0}: {1}'.format(location, msg))\n        self.location = location\n        self.msg = msg\n\n\ndef read_json_file(filename):\n  \"\"\"Read a JSON file as UTF-8 into a dictionary, discarding @metadata.\n\n  Args:\n    filename: The filename, which must end \".json\".\n\n  Returns:\n    The dictionary.\n\n  Raises:\n    InputError: The filename did not end with \".json\" or an error occurred\n        while opening or reading the file.\n  \"\"\"\n  if not filename.endswith('.json'):\n    raise InputError(filename, 'filenames must end with \".json\"')\n  try:\n    # Read in file.\n    with codecs.open(filename, 'r', 'utf-8') as infile:\n      defs = json.load(infile)\n    if '@metadata' in defs:\n      del defs['@metadata']\n    return defs\n  except ValueError, e:\n    print('Error reading ' + filename)\n    raise InputError(file, str(e))\n\n\ndef _create_qqq_file(output_dir):\n    \"\"\"Creates a qqq.json file with message documentation for translatewiki.net.\n\n    The file consists of key-value pairs, where the keys are message ids and\n    the values are descriptions for the translators of the messages.\n    What documentation exists for the format can be found at:\n    http://translatewiki.net/wiki/Translating:Localisation_for_developers#Message_documentation\n\n    The file should be closed by _close_qqq_file().\n\n    Parameters:\n        output_dir: The output directory.\n\n    Returns:\n        A pointer to a file to which a left brace and newline have been written.\n\n    Raises:\n        IOError: An error occurred while opening or writing the file.\n    \"\"\"\n    qqq_file_name = os.path.join(os.curdir, output_dir, 'qqq.json')\n    qqq_file = codecs.open(qqq_file_name, 'w', 'utf-8')\n    print 'Created file: ' + qqq_file_name\n    qqq_file.write('{\\n')\n    return qqq_file\n\n\ndef _close_qqq_file(qqq_file):\n    \"\"\"Closes a qqq.json file created and opened by _create_qqq_file().\n\n    This writes the final newlines and right brace.\n\n    Args:\n        qqq_file: A file created by _create_qqq_file().\n\n    Raises:\n        IOError: An error occurred while writing to or closing the file.\n    \"\"\"\n    qqq_file.write('\\n}\\n')\n    qqq_file.close()\n\n\ndef _create_lang_file(author, lang, output_dir):\n    \"\"\"Creates a <lang>.json file for translatewiki.net.\n\n    The file consists of metadata, followed by key-value pairs, where the keys\n    are message ids and the values are the messages in the language specified\n    by the corresponding command-line argument.  The file should be closed by\n    _close_lang_file().\n\n    Args:\n        author: Name and email address of contact for translators.\n        lang: ISO 639-1 source language code.\n        output_dir: Relative directory for output files.\n\n    Returns:\n        A pointer to a file to which the metadata has been written.\n\n    Raises:\n        IOError: An error occurred while opening or writing the file.\n    \"\"\"\n    lang_file_name = os.path.join(os.curdir, output_dir, lang + '.json')\n    lang_file = codecs.open(lang_file_name, 'w', 'utf-8')\n    print 'Created file: ' + lang_file_name\n    # string.format doesn't like printing braces, so break up our writes.\n    lang_file.write('{\\n    \"@metadata\": {')\n    lang_file.write(\"\"\"\n        \"author\": \"{0}\",\n        \"lastupdated\": \"{1}\",\n        \"locale\": \"{2}\",\n        \"messagedocumentation\" : \"qqq\"\n\"\"\".format(author, str(datetime.now()), lang))\n    lang_file.write('    },\\n')\n    return lang_file\n\n\ndef _close_lang_file(lang_file):\n    \"\"\"Closes a <lang>.json file created with _create_lang_file().\n\n    This also writes the terminating left brace and newline.\n\n    Args:\n        lang_file: A file opened with _create_lang_file().\n\n    Raises:\n        IOError: An error occurred while writing to or closing the file.\n    \"\"\"\n    lang_file.write('\\n}\\n')\n    lang_file.close()\n\n\ndef _create_key_file(output_dir):\n    \"\"\"Creates a keys.json file mapping Closure keys to Blockly keys.\n\n    Args:\n        output_dir: Relative directory for output files.\n\n    Raises:\n        IOError: An error occurred while creating the file.\n    \"\"\"\n    key_file_name = os.path.join(os.curdir, output_dir, 'keys.json')\n    key_file = open(key_file_name, 'w')\n    key_file.write('{\\n')\n    print 'Created file: ' + key_file_name\n    return key_file\n\n\ndef _close_key_file(key_file):\n    \"\"\"Closes a key file created and opened with _create_key_file().\n\n    Args:\n        key_file: A file created by _create_key_file().\n\n    Raises:\n        IOError: An error occurred while writing to or closing the file.\n    \"\"\"\n    key_file.write('\\n}\\n')\n    key_file.close()\n\n\ndef write_files(author, lang, output_dir, units, write_key_file):\n    \"\"\"Writes the output files for the given units.\n\n    There are three possible output files:\n    * lang_file: JSON file mapping meanings (e.g., Maze.turnLeft) to the\n      English text.  The base name of the language file is specified by the\n      \"lang\" command-line argument.\n    * key_file: JSON file mapping meanings to Soy-generated keys (long hash\n      codes).  This is only output if the parameter write_key_file is True.\n    * qqq_file: JSON file mapping meanings to descriptions.\n\n    Args:\n        author: Name and email address of contact for translators.\n        lang: ISO 639-1 source language code.\n        output_dir: Relative directory for output files.\n        units: A list of dictionaries with entries for 'meaning', 'source',\n            'description', and 'keys' (the last only if write_key_file is true),\n            in the order desired in the output files.\n        write_key_file: Whether to output a keys.json file.\n\n    Raises:\n        IOError: An error occurs opening, writing to, or closing a file.\n        KeyError: An expected key is missing from units.\n    \"\"\"\n    lang_file = _create_lang_file(author, lang, output_dir)\n    qqq_file = _create_qqq_file(output_dir)\n    if write_key_file:\n      key_file = _create_key_file(output_dir)\n    first_entry = True\n    for unit in units:\n        if not first_entry:\n            lang_file.write(',\\n')\n            if write_key_file:\n              key_file.write(',\\n')\n            qqq_file.write(',\\n')\n        lang_file.write(u'    \"{0}\": \"{1}\"'.format(\n            unit['meaning'],\n            unit['source'].replace('\"', \"'\")))\n        if write_key_file:\n          key_file.write('\"{0}\": \"{1}\"'.format(unit['meaning'], unit['key']))\n        qqq_file.write(u'    \"{0}\": \"{1}\"'.format(\n            unit['meaning'],\n            unit['description'].replace('\"', \"'\").replace(\n                '{lb}', '{').replace('{rb}', '}')))\n        first_entry = False\n    _close_lang_file(lang_file)\n    if write_key_file:\n      _close_key_file(key_file)\n    _close_qqq_file(qqq_file)\n\n\ndef insert_breaks(s, min_length, max_length):\n  \"\"\"Inserts line breaks to try to get line lengths within the given range.\n\n  This tries to minimize raggedness and to break lines at punctuation\n  (periods and commas).  It never splits words or numbers.  Multiple spaces\n  may be converted into single spaces.\n\n  Args:\n      s: The string to split.\n      min_length: The requested minimum number of characters per line.\n      max_length: The requested minimum number of characters per line.\n\n  Returns:\n      A copy of the original string with zero or more line breaks inserted.\n  \"\"\"\n  newline = '\\\\n'\n  if len(s) < min_length:\n      return s\n  # Try splitting by sentences.  This assumes sentences end with periods.\n  sentences = s.split('.')\n  # Remove empty sentences.\n  sentences = [sen for sen in sentences if sen]\n\n  # If all sentences are at least min_length and at most max_length,\n  # then return one per line.\n  if not [sen for sen in sentences if\n          len(sen) > max_length or len(sen) < min_length]:\n      return newline.join([sen.strip() + '.' for sen in sentences])\n\n  # Otherwise, divide into words, and use a greedy algorithm for the first\n  # line, and try to get later lines as close as possible in length.\n  words = [word for word in s.split(' ') if word]\n  line1 = ''\n  while (len(line1) + 1 + len(words[0]) < max_length and\n         # Preferentially split on periods and commas.\n         (not ((line1.endswith('. ') or line1.endswith(', ')) and\n               len(line1) > min_length))):\n    line1 += words.pop(0) + ' '\n    # If it all fits on one line, return that line.\n    if not words:\n      return line1\n  ideal_length = len(line1)\n  output = line1\n  line = ''\n  while words:\n    line += words.pop(0) + ' '\n    if words:\n      potential_len = len(line) + len(words[0])\n      if (potential_len > max_length or\n          potential_len - ideal_length > ideal_length - len(line) or\n          (line.endswith('. ') and len(line) > min_length)):\n        output += newline + line\n        line = ''\n  output += newline + line\n  return output\n"
  },
  {
    "path": "extern/blockly/i18n/create_messages.py",
    "content": "#!/usr/bin/python\n\n# Generate .js files defining Blockly core and language messages.\n#\n# Copyright 2013 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport argparse\nimport codecs\nimport os\nimport re\nimport sys\nfrom common import read_json_file\n\n\n_NEWLINE_PATTERN = re.compile('[\\n\\r]')\n\n\ndef main():\n  \"\"\"Generate .js files defining Blockly core and language messages.\"\"\"\n\n  # Process command-line arguments.\n  parser = argparse.ArgumentParser(description='Convert JSON files to JS.')\n  parser.add_argument('--source_lang', default='en',\n                      help='ISO 639-1 source language code')\n  parser.add_argument('--source_lang_file',\n                      default=os.path.join('json', 'en.json'),\n                      help='Path to .json file for source language')\n  parser.add_argument('--source_synonym_file',\n                      default=os.path.join('json', 'synonyms.json'),\n                      help='Path to .json file with synonym definitions')\n  parser.add_argument('--output_dir', default='js/',\n                      help='relative directory for output files')\n  parser.add_argument('--key_file', default='keys.json',\n                      help='relative path to input keys file')\n  parser.add_argument('--min_length', default=30,\n                      help='minimum line length (not counting last line)')\n  parser.add_argument('--max_length', default=50,\n                      help='maximum line length (not guaranteed)')\n  parser.add_argument('--quiet', action='store_true', default=False,\n                      help='do not write anything to standard output')\n  parser.add_argument('files', nargs='+', help='input files')\n  args = parser.parse_args()\n  if not args.output_dir.endswith(os.path.sep):\n    args.output_dir += os.path.sep\n\n  # Read in source language .json file, which provides any values missing\n  # in target languages' .json files.\n  source_defs = read_json_file(os.path.join(os.curdir, args.source_lang_file))\n  # Make sure the source file doesn't contain a newline or carriage return.\n  for key, value in source_defs.items():\n    if _NEWLINE_PATTERN.search(value):\n      print('ERROR: definition of {0} in {1} contained a newline character.'.\n            format(key, args.source_lang_file))\n      sys.exit(1)\n  sorted_keys = source_defs.keys()\n  sorted_keys.sort()\n\n  # Read in synonyms file, which must be output in every language.\n  synonym_defs = read_json_file(os.path.join(\n      os.curdir, args.source_synonym_file))\n  synonym_text = '\\n'.join(['Blockly.Msg.{0} = Blockly.Msg.{1};'.format(\n      key, synonym_defs[key]) for key in synonym_defs])\n\n  # Create each output file.\n  for arg_file in args.files:\n    (_, filename) = os.path.split(arg_file)\n    target_lang = filename[:filename.index('.')]\n    if target_lang not in ('qqq', 'keys', 'synonyms'):\n      target_defs = read_json_file(os.path.join(os.curdir, arg_file))\n      # If there's a '\\n' or '\\r', remove it and print a warning.\n      for key, value in target_defs.items():\n        if _NEWLINE_PATTERN.search(value):\n          print('WARNING: definition of {0} in {1} contained '\n                'a newline character.'.\n                format(key, arg_file))\n          target_defs[key] = _NEWLINE_PATTERN.sub(' ', value)\n\n      # Output file.\n      outname = os.path.join(os.curdir, args.output_dir, target_lang + '.js')\n      with codecs.open(outname, 'w', 'utf-8') as outfile:\n        outfile.write(\n            \"\"\"// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.{0}');\n\ngoog.require('Blockly.Msg');\n\n\"\"\".format(target_lang))\n        # For each key in the source language file, output the target value\n        # if present; otherwise, output the source language value with a\n        # warning comment.\n        for key in sorted_keys:\n          if key in target_defs:\n            value = target_defs[key]\n            comment = ''\n            del target_defs[key]\n          else:\n            value = source_defs[key]\n            comment = '  // untranslated'\n          value = value.replace('\"', '\\\\\"')\n          outfile.write(u'Blockly.Msg.{0} = \"{1}\";{2}\\n'.format(\n              key, value, comment))\n\n        # Announce any keys defined only for target language.\n        if target_defs:\n          extra_keys = [key for key in target_defs if key not in synonym_defs]\n          synonym_keys = [key for key in target_defs if key in synonym_defs]\n          if not args.quiet:\n            if extra_keys:\n              print('These extra keys appeared in {0}: {1}'.format(\n                  filename, ', '.join(extra_keys)))\n            if synonym_keys:\n              print('These synonym keys appeared in {0}: {1}'.format(\n                  filename, ', '.join(synonym_keys)))\n\n        outfile.write(synonym_text)\n\n      if not args.quiet:\n        print('Created {0}.'.format(outname))\n\n\nif __name__ == '__main__':\n  main()\n"
  },
  {
    "path": "extern/blockly/i18n/dedup_json.py",
    "content": "#!/usr/bin/python\n\n# Consolidates duplicate key-value pairs in a JSON file.\n# If the same key is used with different values, no warning is given,\n# and there is no guarantee about which key-value pair will be output.\n# There is also no guarantee as to the order of the key-value pairs\n# output.\n#\n# Copyright 2013 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport argparse\nimport codecs\nimport json\nfrom common import InputError\n\n\ndef main():\n  \"\"\"Parses arguments and iterates over files.\n\n  Raises:\n    IOError: An I/O error occurred with an input or output file.\n    InputError: Input JSON could not be parsed.\n  \"\"\"\n\n  # Set up argument parser.\n  parser = argparse.ArgumentParser(\n      description='Removes duplicate key-value pairs from JSON files.')\n  parser.add_argument('--suffix', default='',\n                      help='optional suffix for output files; '\n                      'if empty, files will be changed in place')\n  parser.add_argument('files', nargs='+', help='input files')\n  args = parser.parse_args()\n\n  # Iterate over files.\n  for filename in args.files:\n    # Read in json using Python libraries.  This eliminates duplicates.\n    print('Processing ' + filename + '...')\n    try:\n      with codecs.open(filename, 'r', 'utf-8') as infile:\n        j = json.load(infile)\n    except ValueError, e:\n      print('Error reading ' + filename)\n      raise InputError(file, str(e))\n\n    # Built up output strings as an array to make output of delimiters easier.\n    output = []\n    for key in j:\n      if key != '@metadata':\n        output.append('\\t\"' + key + '\": \"' +\n                      j[key].replace('\\n', '\\\\n') + '\"')\n\n    # Output results.\n    with codecs.open(filename + args.suffix, 'w', 'utf-8') as outfile:\n      outfile.write('{\\n')\n      outfile.write(',\\n'.join(output))\n      outfile.write('\\n}\\n')\n\n\nif __name__ == '__main__':\n  main()\n"
  },
  {
    "path": "extern/blockly/i18n/js_to_json.py",
    "content": "#!/usr/bin/python\n\n# Gives the translation status of the specified apps and languages.\n#\n# Copyright 2013 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Extracts messages from .js files into .json files for translation.\n\nSpecifically, lines with the following formats are extracted:\n\n    /// Here is a description of the following message.\n    Blockly.SOME_KEY = 'Some value';\n\nAdjacent \"///\" lines are concatenated.\n\nThere are two output files, each of which is proper JSON.  For each key, the\nfile en.json would get an entry of the form:\n\n    \"Blockly.SOME_KEY\", \"Some value\",\n\nThe file qqq.json would get:\n\n    \"Blockly.SOME_KEY\", \"Here is a description of the following message.\",\n\nCommas would of course be omitted for the final entry of each value.\n\n@author Ellen Spertus (ellen.spertus@gmail.com)\n\"\"\"\n\nimport argparse\nimport codecs\nimport json\nimport os\nimport re\nfrom common import write_files\n\n\n_INPUT_DEF_PATTERN = re.compile(\"\"\"Blockly.Msg.(\\w*)\\s*=\\s*'([^']*)';?$\"\"\")\n\n_INPUT_SYN_PATTERN = re.compile(\n    \"\"\"Blockly.Msg.(\\w*)\\s*=\\s*Blockly.Msg.(\\w*);\"\"\")\n\ndef main():\n  # Set up argument parser.\n  parser = argparse.ArgumentParser(description='Create translation files.')\n  parser.add_argument(\n      '--author',\n      default='Ellen Spertus <ellen.spertus@gmail.com>',\n      help='name and email address of contact for translators')\n  parser.add_argument('--lang', default='en',\n                      help='ISO 639-1 source language code')\n  parser.add_argument('--output_dir', default='json',\n                      help='relative directory for output files')\n  parser.add_argument('--input_file', default='messages.js',\n                      help='input file')\n  parser.add_argument('--quiet', action='store_true', default=False,\n                      help='only display warnings, not routine info')\n  args = parser.parse_args()\n  if (not args.output_dir.endswith(os.path.sep)):\n    args.output_dir += os.path.sep\n\n  # Read and parse input file.\n  results = []\n  synonyms = {}\n  description = ''\n  infile = codecs.open(args.input_file, 'r', 'utf-8')\n  for line in infile:\n    if line.startswith('///'):\n      if description:\n        description = description + ' ' + line[3:].strip()\n      else:\n        description = line[3:].strip()\n    else:\n      match = _INPUT_DEF_PATTERN.match(line)\n      if match:\n        result = {}\n        result['meaning'] = match.group(1)\n        result['source'] = match.group(2)\n        if not description:\n          print('Warning: No description for ' + result['meaning'])\n        result['description'] = description\n        description = ''\n        results.append(result)\n      else:\n        match = _INPUT_SYN_PATTERN.match(line)\n        if match:\n          if description:\n            print('Warning: Description preceding definition of synonym {0}.'.\n                  format(match.group(1)))\n            description = ''\n          synonyms[match.group(1)] = match.group(2)\n  infile.close()\n\n  # Create <lang_file>.json, keys.json, and qqq.json.\n  write_files(args.author, args.lang, args.output_dir, results, False)\n\n  # Create synonyms.json.\n  synonym_file_name = os.path.join(os.curdir, args.output_dir, 'synonyms.json')\n  with open(synonym_file_name, 'w') as outfile:\n    json.dump(synonyms, outfile)\n  if not args.quiet:\n    print(\"Wrote {0} synonym pairs to {1}.\".format(\n        len(synonyms), synonym_file_name))\n\n\nif __name__ == '__main__':\n  main()\n"
  },
  {
    "path": "extern/blockly/i18n/json_to_js.py",
    "content": "#!/usr/bin/python\n\n# Converts .json files into .js files for use within Blockly apps.\n#\n# Copyright 2013 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport argparse\nimport codecs      # for codecs.open(..., 'utf-8')\nimport json        # for json.load()\nimport os          # for os.path()\nimport subprocess  # for subprocess.check_call()\nfrom common import InputError\nfrom common import insert_breaks\nfrom common import read_json_file\n\n\n# Store parsed command-line arguments in global variable.\nargs = None\n\n\ndef _create_xlf(target_lang):\n    \"\"\"Creates a <target_lang>.xlf file for Soy.\n\n    Args:\n        target_lang: The ISO 639 language code for the target language.\n            This is used in the name of the file and in the metadata.\n\n    Returns:\n        A pointer to a file to which the metadata has been written.\n\n    Raises:\n        IOError: An error occurred while opening or writing the file.\n    \"\"\"\n    filename = os.path.join(os.curdir, args.output_dir, target_lang + '.xlf')\n    out_file = codecs.open(filename, 'w', 'utf-8')\n    out_file.write(\"\"\"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\">\n  <file original=\"SoyMsgBundle\"\n        datatype=\"x-soy-msg-bundle\"\n        xml:space=\"preserve\"\n        source-language=\"{0}\"\n        target-language=\"{1}\">\n    <body>\"\"\".format(args.source_lang, target_lang))\n    return out_file\n\n\ndef _close_xlf(xlf_file):\n    \"\"\"Closes a <target_lang>.xlf file created with create_xlf().\n\n    This includes writing the terminating XML.\n\n    Args:\n        xlf_file: A pointer to a file created by _create_xlf().\n\n    Raises:\n        IOError: An error occurred while writing to or closing the file.\n    \"\"\"\n    xlf_file.write(\"\"\"\n    </body>\n  </file>\n</xliff>\n\"\"\")\n    xlf_file.close()\n\n\ndef _process_file(path_to_json, target_lang, key_dict):\n    \"\"\"Creates an .xlf file corresponding to the specified .json input file.\n\n    The name of the input file must be target_lang followed by '.json'.\n    The name of the output file will be target_lang followed by '.js'.\n\n    Args:\n        path_to_json: Path to the directory of xx.json files.\n        target_lang: A IETF language code (RFC 4646), such as 'es' or 'pt-br'.\n        key_dict: Dictionary mapping Blockly keys (e.g., Maze.turnLeft) to\n            Closure keys (hash numbers).\n\n    Raises:\n        IOError: An I/O error occurred with an input or output file.\n        InputError: Input JSON could not be parsed.\n        KeyError: Key found in input file but not in key file.\n    \"\"\"\n    keyfile = os.path.join(path_to_json, target_lang + '.json')\n    j = read_json_file(keyfile)\n    out_file = _create_xlf(target_lang)\n    for key in j:\n        if key != '@metadata':\n            try:\n                identifier = key_dict[key]\n            except KeyError, e:\n                print('Key \"%s\" is in %s but not in %s' %\n                      (key, keyfile, args.key_file))\n                raise e\n            target = j.get(key)\n            # Only insert line breaks for tooltips.\n            if key.lower().find('tooltip') != -1:\n                target = insert_breaks(\n                    j.get(key), args.min_length, args.max_length)\n            out_file.write(u\"\"\"\n      <trans-unit id=\"{0}\" datatype=\"html\">\n        <target>{1}</target>\n      </trans-unit>\"\"\".format(identifier, target))\n    _close_xlf(out_file)\n\n\ndef main():\n    \"\"\"Parses arguments and iterates over files.\"\"\"\n\n    # Set up argument parser.\n    parser = argparse.ArgumentParser(description='Convert JSON files to JS.')\n    parser.add_argument('--source_lang', default='en',\n                        help='ISO 639-1 source language code')\n    parser.add_argument('--output_dir', default='generated',\n                        help='relative directory for output files')\n    parser.add_argument('--key_file', default='json' + os.path.sep + 'keys.json',\n                        help='relative path to input keys file')\n    parser.add_argument('--template', default='template.soy')\n    parser.add_argument('--min_length', default=30,\n                        help='minimum line length (not counting last line)')\n    parser.add_argument('--max_length', default=50,\n                        help='maximum line length (not guaranteed)')\n    parser.add_argument('--path_to_jar',\n                        default='..' + os.path.sep + 'apps' + os.path.sep\n                        + '_soy',\n                        help='relative path from working directory to '\n                        'SoyToJsSrcCompiler.jar')\n    parser.add_argument('files', nargs='+', help='input files')\n\n    # Initialize global variables.\n    global args\n    args = parser.parse_args()\n\n    # Make sure output_dir ends with slash.\n    if (not args.output_dir.endswith(os.path.sep)):\n      args.output_dir += os.path.sep\n\n    # Read in keys.json, mapping descriptions (e.g., Maze.turnLeft) to\n    # Closure keys (long hash numbers).\n    key_file = open(args.key_file)\n    key_dict = json.load(key_file)\n    key_file.close()\n\n    # Process each input file.\n    print('Creating .xlf files...')\n    processed_langs = []\n    for arg_file in args.files:\n      (path_to_json, filename) = os.path.split(arg_file)\n      if not filename.endswith('.json'):\n        raise InputError(filename, 'filenames must end with \".json\"')\n      target_lang = filename[:filename.index('.')]\n      if not target_lang in ('qqq', 'keys'):\n        processed_langs.append(target_lang)\n        _process_file(path_to_json, target_lang, key_dict)\n\n    # Output command line for Closure compiler.\n    if processed_langs:\n      print('Creating .js files...')\n      processed_lang_list = ','.join(processed_langs)\n      subprocess.check_call([\n          'java',\n          '-jar', os.path.join(args.path_to_jar, 'SoyToJsSrcCompiler.jar'),\n          '--locales', processed_lang_list,\n          '--messageFilePathFormat', args.output_dir + '{LOCALE}.xlf',\n          '--outputPathFormat', args.output_dir + '{LOCALE}.js',\n          '--srcs', args.template])\n      if len(processed_langs) == 1:\n        print('Created ' + processed_lang_list + '.js in ' + args.output_dir)\n      else:\n        print('Created {' + processed_lang_list + '}.js in ' + args.output_dir)\n      command = ['rm']\n      command.extend(map(lambda s: args.output_dir + s + '.xlf',\n                         processed_langs))\n      subprocess.check_call(command)\n      print('Removed .xlf files.')\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "extern/blockly/i18n/status.py",
    "content": "#!/usr/bin/python\n\n# Gives the translation status of the specified apps and languages.\n#\n# Copyright 2013 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Produce a table showing the translation status of each app by language.\n\n@author Ellen Spertus (ellen.spertus@gmail.com)\n\"\"\"\n\nimport argparse\nimport os\nfrom common import read_json_file\n\n# Bogus language name representing all messages defined.\nTOTAL = 'qqq'\n\n# List of key prefixes, which are app names, except for 'Apps', which\n# has common messages.  It is included here for convenience.\nAPPS = ['Apps', 'Code', 'Graph', 'Maze', 'Plane', 'Puzzle', 'Turtle']\n\n\ndef get_prefix(s):\n  \"\"\"Gets the portion of a string before the first period.\n\n  Args:\n      s: A string.\n\n  Returns:\n      The portion of the string before the first period, or the entire\n      string if it does not contain a period.\n  \"\"\"\n  return s.split('.')[0]\n\n\ndef get_prefix_count(prefix, arr):\n  \"\"\"Counts how many strings in the array start with the prefix.\n\n  Args:\n      prefix: The prefix string.\n      arr: An array of strings.\n  Returns:\n      The number of strings in arr starting with prefix.\n  \"\"\"\n  # This code was chosen for its elegance not its efficiency.\n  return len([elt for elt in arr if elt.startswith(prefix)])\n\n\ndef output_as_html(messages, apps, verbose):\n  \"\"\"Outputs the given prefix counts and percentages as HTML.\n\n  Specifically, a sortable HTML table is produced, where the app names\n  are column headers, and one language is output per row.  Entries\n  are color-coded based on the percent completeness.\n\n  Args:\n      messages: A dictionary of dictionaries, where the outer keys are language\n          codes used by translatewiki (generally, ISO 639 language codes) or\n          the string TOTAL, used to indicate the total set of messages.  The\n          inner dictionary makes message keys to values in that language.\n      apps: Apps to consider.\n      verbose: Whether to list missing keys.\n  \"\"\"\n  def generate_language_url(lang):\n    return 'https://translatewiki.net/wiki/Special:SupportedLanguages#' + lang\n\n  def generate_number_as_percent(num, total, tag):\n    percent = num * 100 / total\n    if percent == 100:\n      color = 'green'\n    elif percent >= 90:\n      color = 'orange'\n    elif percent >= 60:\n      color = 'black'\n    else:\n      color = 'gray'\n    s = '<font color={0}>{1} ({2}%)</font>'.format(color, num, percent)\n    if verbose and percent < 100:\n      return '<a href=\"#{0}\">{1}'.format(tag, s)\n    else:\n      return s\n\n  print('<head><title>Blockly app translation status</title></head><body>')\n  print(\"<SCRIPT LANGUAGE='JavaScript1.2' SRC='https://neil.fraser.name/\"\n        \"software/tablesort/tablesort-min.js'></SCRIPT>\")\n  print('<table cellspacing=5><thead><tr>')\n  print('<th class=nocase>Language</th><th class=num>' +\n        '</th><th class=num>'.join(apps) + '</th></tr></thead><tbody>')\n  for lang in messages:\n    if lang != TOTAL:\n      print('<tr><td><a href=\"{1}\">{0}</a></td>'.format(\n          lang, generate_language_url(lang)))\n      for app in apps:\n        print '<td>'\n        print(generate_number_as_percent(\n            get_prefix_count(app, messages[lang]),\n            get_prefix_count(app, messages[TOTAL]),\n            (lang + app)))\n        print '</td>'\n      print('</tr>')\n  print('</tbody><tfoot><tr><td>ALL</td><td>')\n  print('</td><td>'.join([str(get_prefix_count(app, TOTAL)) for app in apps]))\n  print('</td></tr></tfoot></table>')\n\n  if verbose:\n    for lang in messages:\n      if lang != TOTAL:\n        for app in apps:\n          if (get_prefix_count(app, messages[lang]) <\n              get_prefix_count(app, messages[TOTAL])):\n            print('<div id={0}{1}><strong>{1} (<a href=\"{2}\">{0}</a>)'.\n                  format(lang, app, generate_language_url(lang)))\n            print('</strong> missing: ')\n            print(', '.join(\n                [key for key in messages[TOTAL] if\n                 key.startswith(app) and key not in messages[lang]]))\n            print('<br><br></div>')\n  print('</body>')\n\n\ndef output_as_text(messages, apps, verbose):\n  \"\"\"Outputs the given prefix counts and percentages as text.\n\n  Args:\n      messages: A dictionary of dictionaries, where the outer keys are language\n          codes used by translatewiki (generally, ISO 639 language codes) or\n          the string TOTAL, used to indicate the total set of messages.  The\n          inner dictionary makes message keys to values in that language.\n      apps: Apps to consider.\n      verbose: Whether to list missing keys.\n  \"\"\"\n  def generate_number_as_percent(num, total):\n    return '{0} ({1}%)'.format(num, num * 100 / total)\n  MAX_WIDTH = len('999 (100%)') + 1\n  FIELD_STRING = '{0: <' + str(MAX_WIDTH) + '}'\n  print(FIELD_STRING.format('Language') + ''.join(\n      [FIELD_STRING.format(app) for app in apps]))\n  print(('-' * (MAX_WIDTH - 1) + ' ') * (len(apps) + 1))\n  for lang in messages:\n    if lang != TOTAL:\n      print(FIELD_STRING.format(lang) +\n            ''.join([FIELD_STRING.format(generate_number_as_percent(\n                get_prefix_count(app, messages[lang]),\n                get_prefix_count(app, messages[TOTAL])))\n                     for app in apps]))\n  print(FIELD_STRING.format(TOTAL) +\n        ''.join(\n            [FIELD_STRING.format(get_prefix_count(app, messages[TOTAL]))\n             for app in apps]))\n  if verbose:\n    for lang in messages:\n      if lang != TOTAL:\n        for app in apps:\n          missing = [key for key in messages[TOTAL]\n                     if key.startswith(app) and key not in messages[lang]]\n          print('{0} {1}: Missing: {2}'.format(\n              app.upper(), lang, (', '.join(missing) if missing else 'none')))\n\n\ndef output_as_csv(messages, apps):\n  \"\"\"Outputs the given prefix counts and percentages as CSV.\n\n  Args:\n      messages: A dictionary of dictionaries, where the outer keys are language\n          codes used by translatewiki (generally, ISO 639 language codes) or\n          the string TOTAL, used to indicate the total set of messages.  The\n          inner dictionary makes message keys to values in that language.\n      apps: Apps to consider.\n  \"\"\"\n  # Header row.\n  print('Language, ' + ', ,'.join(apps))\n\n  # Total row.\n  # Put at top, rather than bottom, so it can be frozen.\n  print('TOTAL, ' + ', '.join(\n      [str(get_prefix_count(app, messages[TOTAL])) + ', '\n       for app in apps]))\n\n  # One line per language.\n  for lang in messages:\n    if lang != TOTAL:\n      print(lang + ', ' + ', '.join(\n          [str(get_prefix_count(app, messages[lang]))\n           + ', '\n           + str((get_prefix_count(app, messages[lang]) * 1.0 /\n                  get_prefix_count(app, messages[TOTAL])))\n           for app in apps]))\n\n\ndef main():\n  \"\"\"Processes input files and outputs results in specified format.\n  \"\"\"\n  # Argument parsing.\n  parser = argparse.ArgumentParser(\n      description='Display translation status by app and language.')\n  parser.add_argument('--key_file', default='json' + os.path.sep + 'keys.json',\n                      help='file with complete list of keys.')\n  parser.add_argument('--output', default='text',\n                      choices=['text', 'html', 'csv'],\n                      help='output format')\n  parser.add_argument('--verbose', action='store_true', default=False,\n                      help='whether to indicate which messages were translated '\n                      '(only used in text and html output modes)')\n  parser.add_argument('--app', default=None, choices=APPS,\n                      help='if set, only consider the specified app (prefix).')\n  parser.add_argument('lang_files', nargs='+',\n                      help='names of JSON files to examine')\n  args = parser.parse_args()\n  apps = [args.app] if args.app else APPS\n\n\n  # Read in JSON files.\n  messages = {}  # A dictionary of dictionaries.\n  messages[TOTAL] = read_json_file(args.key_file)\n  for lang_file in args.lang_files:\n    prefix = get_prefix(os.path.split(lang_file)[1])\n    # Skip non-language files.\n    if prefix not in ['qqq', 'keys']:\n      messages[prefix] = read_json_file(lang_file)\n\n  # Output results.\n  if args.output == 'text':\n    output_as_text(messages, apps, args.verbose)\n  elif args.output == 'html':\n    output_as_html(messages, apps, args.verbose)\n  elif args.output == 'csv':\n    output_as_csv(messages, apps)\n  else:\n    print('No output?!')\n\n\nif __name__ == '__main__':\n  main()\n"
  },
  {
    "path": "extern/blockly/i18n/tests.py",
    "content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\n# Tests of i18n scripts.\n#\n# Copyright 2013 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport common\nimport re\nimport unittest\n\nclass TestSequenceFunctions(unittest.TestCase):\n  def test_insert_breaks(self):\n    spaces = re.compile(r'\\s+|\\\\n')\n    def contains_all_chars(orig, result):\n      return re.sub(spaces, '', orig) == re.sub(spaces, '', result)\n\n    sentences = [u'Quay Pegman qua bên trái hoặc bên phải 90 độ.',\n                 u'Foo bar baz this is english that is okay bye.',\n                 u'If there is a path in the specified direction, \\nthen ' +\n                 u'do some actions.',\n                 u'If there is a path in the specified direction, then do ' +\n                 u'the first block of actions. Otherwise, do the second ' +\n                 u'block of actions.']\n    for sentence in sentences:\n      output = common.insert_breaks(sentence, 30, 50)\n      self.assert_(contains_all_chars(sentence, output),\n                   u'Mismatch between:\\n{0}\\n{1}'.format(\n                       re.sub(spaces, '', sentence),\n                       re.sub(spaces, '', output)))\n\n\nif __name__ == '__main__':\n    unittest.main()\n"
  },
  {
    "path": "extern/blockly/i18n/xliff_to_json.py",
    "content": "#!/usr/bin/python\n\n# Converts .xlf files into .json files for use at http://translatewiki.net.\n#\n# Copyright 2013 Google Inc.\n# https://blockly.googlecode.com/\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#   http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport argparse\nimport os\nimport re\nimport subprocess\nimport sys\nfrom xml.dom import minidom\nfrom common import InputError\nfrom common import write_files\n\n# Global variables\nargs = None      # parsed command-line arguments\n\n\ndef _parse_trans_unit(trans_unit):\n    \"\"\"Converts a trans-unit XML node into a more convenient dictionary format.\n\n    Args:\n        trans_unit: An XML representation of a .xlf translation unit.\n\n    Returns:\n        A dictionary with useful information about the translation unit.\n        The returned dictionary is guaranteed to have an entry for 'key' and\n        may have entries for 'source', 'target', 'description', and 'meaning'\n        if present in the argument.\n\n    Raises:\n        InputError: A required field was not present.\n    \"\"\"\n\n    def get_value(tag_name):\n        elts = trans_unit.getElementsByTagName(tag_name)\n        if not elts:\n            return None\n        elif len(elts) == 1:\n            return ''.join([child.toxml() for child in elts[0].childNodes])\n        else:\n            raise InputError('', 'Unable to extract ' + tag_name)\n\n    result = {}\n    key = trans_unit.getAttribute('id')\n    if not key:\n        raise InputError('', 'id attribute not found')\n    result['key'] = key\n\n    # Get source and target, if present.\n    try:\n        result['source'] = get_value('source')\n        result['target'] = get_value('target')\n    except InputError, e:\n        raise InputError(key, e.msg)\n\n    # Get notes, using the from value as key and the data as value.\n    notes = trans_unit.getElementsByTagName('note')\n    for note in notes:\n        from_value = note.getAttribute('from')\n        if from_value and len(note.childNodes) == 1:\n            result[from_value] = note.childNodes[0].data\n        else:\n            raise InputError(key, 'Unable to extract ' + from_value)\n\n    return result\n\n\ndef _process_file(filename):\n    \"\"\"Builds list of translation units from input file.\n\n    Each translation unit in the input file includes:\n    - an id (opaquely generated by Soy)\n    - the Blockly name for the message\n    - the text in the source language (generally English)\n    - a description for the translator\n\n    The Soy and Blockly ids are joined with a hyphen and serve as the\n    keys in both output files.  The value is the corresponding text (in the\n    <lang>.json file) or the description (in the qqq.json file).\n\n    Args:\n        filename: The name of an .xlf file produced by Closure.\n\n    Raises:\n        IOError: An I/O error occurred with an input or output file.\n        InputError: The input file could not be parsed or lacked required\n            fields.\n\n    Returns:\n        A list of dictionaries produced by parse_trans_unit().\n    \"\"\"\n    try:\n        results = []  # list of dictionaries (return value)\n        names = []    # list of names of encountered keys (local variable)\n        try:\n            parsed_xml = minidom.parse(filename)\n        except IOError:\n            # Don't get caught by below handler\n            raise\n        except Exception, e:\n            print\n            raise InputError(filename, str(e))\n\n        # Make sure needed fields are present and non-empty.\n        for trans_unit in parsed_xml.getElementsByTagName('trans-unit'):\n            unit = _parse_trans_unit(trans_unit)\n            for key in ['description', 'meaning', 'source']:\n                if not key in unit or not unit[key]:\n                    raise InputError(filename + ':' + unit['key'],\n                                     key + ' not found')\n            if unit['description'].lower() == 'ibid':\n              if unit['meaning'] not in names:\n                # If the term has not already been described, the use of 'ibid'\n                # is an error.\n                raise InputError(\n                    filename,\n                    'First encountered definition of: ' + unit['meaning']\n                    + ' has definition: ' + unit['description']\n                    + '.  This error can occur if the definition was not'\n                    + ' provided on the first appearance of the message'\n                    + ' or if the source (English-language) messages differ.')\n              else:\n                # If term has already been described, 'ibid' was used correctly,\n                # and we output nothing.\n                pass\n            else:\n              if unit['meaning'] in names:\n                raise InputError(filename,\n                                 'Second definition of: ' + unit['meaning'])\n              names.append(unit['meaning'])\n              results.append(unit)\n\n        return results\n    except IOError, e:\n        print 'Error with file {0}: {1}'.format(filename, e.strerror)\n        sys.exit(1)\n\n\ndef sort_units(units, templates):\n    \"\"\"Sorts the translation units by their definition order in the template.\n\n    Args:\n        units: A list of dictionaries produced by parse_trans_unit()\n            that have a non-empty value for the key 'meaning'.\n        templates: A string containing the Soy templates in which each of\n            the units' meanings is defined.\n\n    Returns:\n        A new list of translation units, sorted by the order in which\n        their meaning is defined in the templates.\n\n    Raises:\n        InputError: If a meaning definition cannot be found in the\n            templates.\n    \"\"\"\n    def key_function(unit):\n        match = re.search(\n            '\\\\smeaning\\\\s*=\\\\s*\"{0}\"\\\\s'.format(unit['meaning']),\n            templates)\n        if match:\n            return match.start()\n        else:\n            raise InputError(args.templates,\n                             'msg definition for meaning not found: ' +\n                             unit['meaning'])\n    return sorted(units, key=key_function)\n\n\ndef main():\n    \"\"\"Parses arguments and processes the specified file.\n\n    Raises:\n        IOError: An I/O error occurred with an input or output file.\n        InputError: Input files lacked required fields.\n    \"\"\"\n    # Set up argument parser.\n    parser = argparse.ArgumentParser(description='Create translation files.')\n    parser.add_argument(\n        '--author',\n        default='Ellen Spertus <ellen.spertus@gmail.com>',\n        help='name and email address of contact for translators')\n    parser.add_argument('--lang', default='en',\n                        help='ISO 639-1 source language code')\n    parser.add_argument('--output_dir', default='json',\n                        help='relative directory for output files')\n    parser.add_argument('--xlf', help='file containing xlf definitions')\n    parser.add_argument('--templates', default=['template.soy'], nargs='+',\n                        help='relative path to Soy templates, comma or space '\n                        'separated (used for ordering messages)')\n    global args\n    args = parser.parse_args()\n\n    # Make sure output_dir ends with slash.\n    if (not args.output_dir.endswith(os.path.sep)):\n      args.output_dir += os.path.sep\n\n    # Process the input file, and sort the entries.\n    units = _process_file(args.xlf)\n    files = []\n    for arg in args.templates:\n      for filename in arg.split(','):\n        filename = filename.strip();\n        if filename:\n          with open(filename) as myfile:\n            files.append(' '.join(line.strip() for line in myfile))\n    sorted_units = sort_units(units, ' '.join(files))\n\n    # Write the output files.\n    write_files(args.author, args.lang, args.output_dir, sorted_units, True)\n\n    # Delete the input .xlf file.\n    command = ['rm', args.xlf]\n    subprocess.check_call(command)\n    print('Removed ' + args.xlf)\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "extern/blockly/javascript_compressed.js",
    "content": "// Do not edit this file; automatically generated by build.py.\n\"use strict\";\n\n\n// Copyright 2012 Google Inc.  Apache License 2.0\nBlockly.JavaScript=new Blockly.Generator(\"JavaScript\");Blockly.JavaScript.addReservedWords(\"Blockly,break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,class,enum,export,extends,import,super,implements,interface,let,package,private,protected,public,static,yield,const,null,true,false,Array,ArrayBuffer,Boolean,Date,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Error,eval,EvalError,Float32Array,Float64Array,Function,Infinity,Int16Array,Int32Array,Int8Array,isFinite,isNaN,Iterator,JSON,Math,NaN,Number,Object,parseFloat,parseInt,RangeError,ReferenceError,RegExp,StopIteration,String,SyntaxError,TypeError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,undefined,uneval,URIError,applicationCache,closed,Components,content,_content,controllers,crypto,defaultStatus,dialogArguments,directories,document,frameElement,frames,fullScreen,globalStorage,history,innerHeight,innerWidth,length,location,locationbar,localStorage,menubar,messageManager,mozAnimationStartTime,mozInnerScreenX,mozInnerScreenY,mozPaintCount,name,navigator,opener,outerHeight,outerWidth,pageXOffset,pageYOffset,parent,performance,personalbar,pkcs11,returnValue,screen,screenX,screenY,scrollbars,scrollMaxX,scrollMaxY,scrollX,scrollY,self,sessionStorage,sidebar,status,statusbar,toolbar,top,URL,window,addEventListener,alert,atob,back,blur,btoa,captureEvents,clearImmediate,clearInterval,clearTimeout,close,confirm,disableExternalCapture,dispatchEvent,dump,enableExternalCapture,escape,find,focus,forward,GeckoActiveXObject,getAttention,getAttentionWithCycleCount,getComputedStyle,getSelection,home,matchMedia,maximize,minimize,moveBy,moveTo,mozRequestAnimationFrame,open,openDialog,postMessage,print,prompt,QueryInterface,releaseEvents,removeEventListener,resizeBy,resizeTo,restore,routeEvent,scroll,scrollBy,scrollByLines,scrollByPages,scrollTo,setCursor,setImmediate,setInterval,setResizable,setTimeout,showModalDialog,sizeToContent,stop,unescape,updateCommands,XPCNativeWrapper,XPCSafeJSObjectWrapper,onabort,onbeforeunload,onblur,onchange,onclick,onclose,oncontextmenu,ondevicemotion,ondeviceorientation,ondragdrop,onerror,onfocus,onhashchange,onkeydown,onkeypress,onkeyup,onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup,onmozbeforepaint,onpaint,onpopstate,onreset,onresize,onscroll,onselect,onsubmit,onunload,onpageshow,onpagehide,Image,Option,Worker,Event,Range,File,FileReader,Blob,BlobBuilder,Attr,CDATASection,CharacterData,Comment,console,DocumentFragment,DocumentType,DomConfiguration,DOMError,DOMErrorHandler,DOMException,DOMImplementation,DOMImplementationList,DOMImplementationRegistry,DOMImplementationSource,DOMLocator,DOMObject,DOMString,DOMStringList,DOMTimeStamp,DOMUserData,Entity,EntityReference,MediaQueryList,MediaQueryListListener,NameList,NamedNodeMap,Node,NodeFilter,NodeIterator,NodeList,Notation,Plugin,PluginArray,ProcessingInstruction,SharedWorker,Text,TimeRanges,Treewalker,TypeInfo,UserDataHandler,Worker,WorkerGlobalScope,HTMLDocument,HTMLElement,HTMLAnchorElement,HTMLAppletElement,HTMLAudioElement,HTMLAreaElement,HTMLBaseElement,HTMLBaseFontElement,HTMLBodyElement,HTMLBRElement,HTMLButtonElement,HTMLCanvasElement,HTMLDirectoryElement,HTMLDivElement,HTMLDListElement,HTMLEmbedElement,HTMLFieldSetElement,HTMLFontElement,HTMLFormElement,HTMLFrameElement,HTMLFrameSetElement,HTMLHeadElement,HTMLHeadingElement,HTMLHtmlElement,HTMLHRElement,HTMLIFrameElement,HTMLImageElement,HTMLInputElement,HTMLKeygenElement,HTMLLabelElement,HTMLLIElement,HTMLLinkElement,HTMLMapElement,HTMLMenuElement,HTMLMetaElement,HTMLModElement,HTMLObjectElement,HTMLOListElement,HTMLOptGroupElement,HTMLOptionElement,HTMLOutputElement,HTMLParagraphElement,HTMLParamElement,HTMLPreElement,HTMLQuoteElement,HTMLScriptElement,HTMLSelectElement,HTMLSourceElement,HTMLSpanElement,HTMLStyleElement,HTMLTableElement,HTMLTableCaptionElement,HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement,HTMLTableColElement,HTMLTableRowElement,HTMLTableSectionElement,HTMLTextAreaElement,HTMLTimeElement,HTMLTitleElement,HTMLTrackElement,HTMLUListElement,HTMLUnknownElement,HTMLVideoElement,HTMLCanvasElement,CanvasRenderingContext2D,CanvasGradient,CanvasPattern,TextMetrics,ImageData,CanvasPixelArray,HTMLAudioElement,HTMLVideoElement,NotifyAudioAvailableEvent,HTMLCollection,HTMLAllCollection,HTMLFormControlsCollection,HTMLOptionsCollection,HTMLPropertiesCollection,DOMTokenList,DOMSettableTokenList,DOMStringMap,RadioNodeList,SVGDocument,SVGElement,SVGAElement,SVGAltGlyphElement,SVGAltGlyphDefElement,SVGAltGlyphItemElement,SVGAnimationElement,SVGAnimateElement,SVGAnimateColorElement,SVGAnimateMotionElement,SVGAnimateTransformElement,SVGSetElement,SVGCircleElement,SVGClipPathElement,SVGColorProfileElement,SVGCursorElement,SVGDefsElement,SVGDescElement,SVGEllipseElement,SVGFilterElement,SVGFilterPrimitiveStandardAttributes,SVGFEBlendElement,SVGFEColorMatrixElement,SVGFEComponentTransferElement,SVGFECompositeElement,SVGFEConvolveMatrixElement,SVGFEDiffuseLightingElement,SVGFEDisplacementMapElement,SVGFEDistantLightElement,SVGFEFloodElement,SVGFEGaussianBlurElement,SVGFEImageElement,SVGFEMergeElement,SVGFEMergeNodeElement,SVGFEMorphologyElement,SVGFEOffsetElement,SVGFEPointLightElement,SVGFESpecularLightingElement,SVGFESpotLightElement,SVGFETileElement,SVGFETurbulenceElement,SVGComponentTransferFunctionElement,SVGFEFuncRElement,SVGFEFuncGElement,SVGFEFuncBElement,SVGFEFuncAElement,SVGFontElement,SVGFontFaceElement,SVGFontFaceFormatElement,SVGFontFaceNameElement,SVGFontFaceSrcElement,SVGFontFaceUriElement,SVGForeignObjectElement,SVGGElement,SVGGlyphElement,SVGGlyphRefElement,SVGGradientElement,SVGLinearGradientElement,SVGRadialGradientElement,SVGHKernElement,SVGImageElement,SVGLineElement,SVGMarkerElement,SVGMaskElement,SVGMetadataElement,SVGMissingGlyphElement,SVGMPathElement,SVGPathElement,SVGPatternElement,SVGPolylineElement,SVGPolygonElement,SVGRectElement,SVGScriptElement,SVGStopElement,SVGStyleElement,SVGSVGElement,SVGSwitchElement,SVGSymbolElement,SVGTextElement,SVGTextPathElement,SVGTitleElement,SVGTRefElement,SVGTSpanElement,SVGUseElement,SVGViewElement,SVGVKernElement,SVGAngle,SVGColor,SVGICCColor,SVGElementInstance,SVGElementInstanceList,SVGLength,SVGLengthList,SVGMatrix,SVGNumber,SVGNumberList,SVGPaint,SVGPoint,SVGPointList,SVGPreserveAspectRatio,SVGRect,SVGStringList,SVGTransform,SVGTransformList,SVGAnimatedAngle,SVGAnimatedBoolean,SVGAnimatedEnumeration,SVGAnimatedInteger,SVGAnimatedLength,SVGAnimatedLengthList,SVGAnimatedNumber,SVGAnimatedNumberList,SVGAnimatedPreserveAspectRatio,SVGAnimatedRect,SVGAnimatedString,SVGAnimatedTransformList,SVGPathSegList,SVGPathSeg,SVGPathSegArcAbs,SVGPathSegArcRel,SVGPathSegClosePath,SVGPathSegCurvetoCubicAbs,SVGPathSegCurvetoCubicRel,SVGPathSegCurvetoCubicSmoothAbs,SVGPathSegCurvetoCubicSmoothRel,SVGPathSegCurvetoQuadraticAbs,SVGPathSegCurvetoQuadraticRel,SVGPathSegCurvetoQuadraticSmoothAbs,SVGPathSegCurvetoQuadraticSmoothRel,SVGPathSegLinetoAbs,SVGPathSegLinetoHorizontalAbs,SVGPathSegLinetoHorizontalRel,SVGPathSegLinetoRel,SVGPathSegLinetoVerticalAbs,SVGPathSegLinetoVerticalRel,SVGPathSegMovetoAbs,SVGPathSegMovetoRel,ElementTimeControl,TimeEvent,SVGAnimatedPathData,SVGAnimatedPoints,SVGColorProfileRule,SVGCSSRule,SVGExternalResourcesRequired,SVGFitToViewBox,SVGLangSpace,SVGLocatable,SVGRenderingIntent,SVGStylable,SVGTests,SVGTextContentElement,SVGTextPositioningElement,SVGTransformable,SVGUnitTypes,SVGURIReference,SVGViewSpec,SVGZoomAndPan\");\nBlockly.JavaScript.ORDER_ATOMIC=0;Blockly.JavaScript.ORDER_MEMBER=1;Blockly.JavaScript.ORDER_NEW=1;Blockly.JavaScript.ORDER_FUNCTION_CALL=2;Blockly.JavaScript.ORDER_INCREMENT=3;Blockly.JavaScript.ORDER_DECREMENT=3;Blockly.JavaScript.ORDER_LOGICAL_NOT=4;Blockly.JavaScript.ORDER_BITWISE_NOT=4;Blockly.JavaScript.ORDER_UNARY_PLUS=4;Blockly.JavaScript.ORDER_UNARY_NEGATION=4;Blockly.JavaScript.ORDER_TYPEOF=4;Blockly.JavaScript.ORDER_VOID=4;Blockly.JavaScript.ORDER_DELETE=4;\nBlockly.JavaScript.ORDER_MULTIPLICATION=5;Blockly.JavaScript.ORDER_DIVISION=5;Blockly.JavaScript.ORDER_MODULUS=5;Blockly.JavaScript.ORDER_ADDITION=6;Blockly.JavaScript.ORDER_SUBTRACTION=6;Blockly.JavaScript.ORDER_BITWISE_SHIFT=7;Blockly.JavaScript.ORDER_RELATIONAL=8;Blockly.JavaScript.ORDER_IN=8;Blockly.JavaScript.ORDER_INSTANCEOF=8;Blockly.JavaScript.ORDER_EQUALITY=9;Blockly.JavaScript.ORDER_BITWISE_AND=10;Blockly.JavaScript.ORDER_BITWISE_XOR=11;Blockly.JavaScript.ORDER_BITWISE_OR=12;\nBlockly.JavaScript.ORDER_LOGICAL_AND=13;Blockly.JavaScript.ORDER_LOGICAL_OR=14;Blockly.JavaScript.ORDER_CONDITIONAL=15;Blockly.JavaScript.ORDER_ASSIGNMENT=16;Blockly.JavaScript.ORDER_COMMA=17;Blockly.JavaScript.ORDER_NONE=99;Blockly.JavaScript.INFINITE_LOOP_TRAP=null;\nBlockly.JavaScript.init=function(){Blockly.JavaScript.definitions_=Object.create(null);Blockly.JavaScript.functionNames_=Object.create(null);if(Blockly.Variables){Blockly.JavaScript.variableDB_?Blockly.JavaScript.variableDB_.reset():Blockly.JavaScript.variableDB_=new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_);for(var a=[],b=Blockly.Variables.allVariables(),c=0;c<b.length;c++)a[c]=\"var \"+Blockly.JavaScript.variableDB_.getName(b[c],Blockly.Variables.NAME_TYPE)+\";\";Blockly.JavaScript.definitions_.variables=\na.join(\"\\n\")}};Blockly.JavaScript.finish=function(a){var b=[],c;for(c in Blockly.JavaScript.definitions_)b.push(Blockly.JavaScript.definitions_[c]);return b.join(\"\\n\\n\")+\"\\n\\n\\n\"+a};Blockly.JavaScript.scrubNakedValue=function(a){return a+\";\\n\"};Blockly.JavaScript.quote_=function(a){a=a.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\n/g,\"\\\\\\n\").replace(/'/g,\"\\\\'\");return\"'\"+a+\"'\"};\nBlockly.JavaScript.scrub_=function(a,b){if(null===b)return\"\";var c=\"\";if(!a.outputConnection||!a.outputConnection.targetConnection){var d=a.getCommentText();d&&(c+=this.prefixLines(d,\"// \")+\"\\n\");for(var e=0;e<a.inputList.length;e++)a.inputList[e].type==Blockly.INPUT_VALUE&&(d=a.inputList[e].connection.targetBlock())&&(d=this.allNestedComments(d))&&(c+=this.prefixLines(d,\"// \"))}e=a.nextConnection&&a.nextConnection.targetBlock();e=this.blockToCode(e);return c+b+e};Blockly.JavaScript.colour={};Blockly.JavaScript.colour_picker=function(a){return[\"'\"+a.getFieldValue(\"COLOUR\")+\"'\",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.colour_random=function(a){return[Blockly.JavaScript.provideFunction_(\"colour_random\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"() {\",\"  var num = Math.floor(Math.random() * Math.pow(2, 24));\",\"  return '#' + ('00000' + num.toString(16)).substr(-6);\",\"}\"])+\"()\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};\nBlockly.JavaScript.colour_rgb=function(a){var b=Blockly.JavaScript.valueToCode(a,\"RED\",Blockly.JavaScript.ORDER_COMMA)||0,c=Blockly.JavaScript.valueToCode(a,\"GREEN\",Blockly.JavaScript.ORDER_COMMA)||0;a=Blockly.JavaScript.valueToCode(a,\"BLUE\",Blockly.JavaScript.ORDER_COMMA)||0;return[Blockly.JavaScript.provideFunction_(\"colour_rgb\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(r, g, b) {\",\"  r = Math.max(Math.min(Number(r), 100), 0) * 2.55;\",\"  g = Math.max(Math.min(Number(g), 100), 0) * 2.55;\",\n\"  b = Math.max(Math.min(Number(b), 100), 0) * 2.55;\",\"  r = ('0' + (Math.round(r) || 0).toString(16)).slice(-2);\",\"  g = ('0' + (Math.round(g) || 0).toString(16)).slice(-2);\",\"  b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);\",\"  return '#' + r + g + b;\",\"}\"])+\"(\"+b+\", \"+c+\", \"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};\nBlockly.JavaScript.colour_blend=function(a){var b=Blockly.JavaScript.valueToCode(a,\"COLOUR1\",Blockly.JavaScript.ORDER_COMMA)||\"'#000000'\",c=Blockly.JavaScript.valueToCode(a,\"COLOUR2\",Blockly.JavaScript.ORDER_COMMA)||\"'#000000'\";a=Blockly.JavaScript.valueToCode(a,\"RATIO\",Blockly.JavaScript.ORDER_COMMA)||.5;return[Blockly.JavaScript.provideFunction_(\"colour_blend\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(c1, c2, ratio) {\",\"  ratio = Math.max(Math.min(Number(ratio), 1), 0);\",\"  var r1 = parseInt(c1.substring(1, 3), 16);\",\n\"  var g1 = parseInt(c1.substring(3, 5), 16);\",\"  var b1 = parseInt(c1.substring(5, 7), 16);\",\"  var r2 = parseInt(c2.substring(1, 3), 16);\",\"  var g2 = parseInt(c2.substring(3, 5), 16);\",\"  var b2 = parseInt(c2.substring(5, 7), 16);\",\"  var r = Math.round(r1 * (1 - ratio) + r2 * ratio);\",\"  var g = Math.round(g1 * (1 - ratio) + g2 * ratio);\",\"  var b = Math.round(b1 * (1 - ratio) + b2 * ratio);\",\"  r = ('0' + (r || 0).toString(16)).slice(-2);\",\"  g = ('0' + (g || 0).toString(16)).slice(-2);\",\"  b = ('0' + (b || 0).toString(16)).slice(-2);\",\n\"  return '#' + r + g + b;\",\"}\"])+\"(\"+b+\", \"+c+\", \"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.lists={};Blockly.JavaScript.lists_create_empty=function(a){return[\"[]\",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c<a.itemCount_;c++)b[c]=Blockly.JavaScript.valueToCode(a,\"ADD\"+c,Blockly.JavaScript.ORDER_COMMA)||\"null\";b=\"[\"+b.join(\", \")+\"]\";return[b,Blockly.JavaScript.ORDER_ATOMIC]};\nBlockly.JavaScript.lists_repeat=function(a){var b=Blockly.JavaScript.provideFunction_(\"lists_repeat\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(value, n) {\",\"  var array = [];\",\"  for (var i = 0; i < n; i++) {\",\"    array[i] = value;\",\"  }\",\"  return array;\",\"}\"]),c=Blockly.JavaScript.valueToCode(a,\"ITEM\",Blockly.JavaScript.ORDER_COMMA)||\"null\";a=Blockly.JavaScript.valueToCode(a,\"NUM\",Blockly.JavaScript.ORDER_COMMA)||\"0\";return[b+\"(\"+c+\", \"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};\nBlockly.JavaScript.lists_length=function(a){return[(Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_FUNCTION_CALL)||\"[]\")+\".length\",Blockly.JavaScript.ORDER_MEMBER]};Blockly.JavaScript.lists_isEmpty=function(a){return[\"!\"+(Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_MEMBER)||\"[]\")+\".length\",Blockly.JavaScript.ORDER_LOGICAL_NOT]};\nBlockly.JavaScript.lists_indexOf=function(a){var b=\"FIRST\"==a.getFieldValue(\"END\")?\"indexOf\":\"lastIndexOf\",c=Blockly.JavaScript.valueToCode(a,\"FIND\",Blockly.JavaScript.ORDER_NONE)||\"''\";return[(Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_MEMBER)||\"[]\")+\".\"+b+\"(\"+c+\") + 1\",Blockly.JavaScript.ORDER_MEMBER]};\nBlockly.JavaScript.lists_getIndex=function(a){var b=a.getFieldValue(\"MODE\")||\"GET\",c=a.getFieldValue(\"WHERE\")||\"FROM_START\",d=Blockly.JavaScript.valueToCode(a,\"AT\",Blockly.JavaScript.ORDER_UNARY_NEGATION)||\"1\";a=Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_MEMBER)||\"[]\";if(\"FIRST\"==c){if(\"GET\"==b)return[a+\"[0]\",Blockly.JavaScript.ORDER_MEMBER];if(\"GET_REMOVE\"==b)return[a+\".shift()\",Blockly.JavaScript.ORDER_MEMBER];if(\"REMOVE\"==b)return a+\".shift();\\n\"}else if(\"LAST\"==c){if(\"GET\"==\nb)return[a+\".slice(-1)[0]\",Blockly.JavaScript.ORDER_MEMBER];if(\"GET_REMOVE\"==b)return[a+\".pop()\",Blockly.JavaScript.ORDER_MEMBER];if(\"REMOVE\"==b)return a+\".pop();\\n\"}else if(\"FROM_START\"==c){d=Blockly.isNumber(d)?parseFloat(d)-1:d+\" - 1\";if(\"GET\"==b)return[a+\"[\"+d+\"]\",Blockly.JavaScript.ORDER_MEMBER];if(\"GET_REMOVE\"==b)return[a+\".splice(\"+d+\", 1)[0]\",Blockly.JavaScript.ORDER_FUNCTION_CALL];if(\"REMOVE\"==b)return a+\".splice(\"+d+\", 1);\\n\"}else if(\"FROM_END\"==c){if(\"GET\"==b)return[a+\".slice(-\"+d+\")[0]\",\nBlockly.JavaScript.ORDER_FUNCTION_CALL];if(\"GET_REMOVE\"==b||\"REMOVE\"==b){c=Blockly.JavaScript.provideFunction_(\"lists_remove_from_end\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(list, x) {\",\"  x = list.length - x;\",\"  return list.splice(x, 1)[0];\",\"}\"]);d=c+\"(\"+a+\", \"+d+\")\";if(\"GET_REMOVE\"==b)return[d,Blockly.JavaScript.ORDER_FUNCTION_CALL];if(\"REMOVE\"==b)return d+\";\\n\"}}else if(\"RANDOM\"==c){c=Blockly.JavaScript.provideFunction_(\"lists_get_random_item\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\n\"(list, remove) {\",\"  var x = Math.floor(Math.random() * list.length);\",\"  if (remove) {\",\"    return list.splice(x, 1)[0];\",\"  } else {\",\"    return list[x];\",\"  }\",\"}\"]);d=c+\"(\"+a+\", \"+(\"GET\"!=b)+\")\";if(\"GET\"==b||\"GET_REMOVE\"==b)return[d,Blockly.JavaScript.ORDER_FUNCTION_CALL];if(\"REMOVE\"==b)return d+\";\\n\"}throw\"Unhandled combination (lists_getIndex).\";};\nBlockly.JavaScript.lists_setIndex=function(a){function b(){if(c.match(/^\\w+$/))return\"\";var a=Blockly.JavaScript.variableDB_.getDistinctName(\"tmp_list\",Blockly.Variables.NAME_TYPE),b=\"var \"+a+\" = \"+c+\";\\n\";c=a;return b}var c=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_MEMBER)||\"[]\",d=a.getFieldValue(\"MODE\")||\"GET\",e=a.getFieldValue(\"WHERE\")||\"FROM_START\",f=Blockly.JavaScript.valueToCode(a,\"AT\",Blockly.JavaScript.ORDER_NONE)||\"1\";a=Blockly.JavaScript.valueToCode(a,\"TO\",Blockly.JavaScript.ORDER_ASSIGNMENT)||\n\"null\";if(\"FIRST\"==e){if(\"SET\"==d)return c+\"[0] = \"+a+\";\\n\";if(\"INSERT\"==d)return c+\".unshift(\"+a+\");\\n\"}else if(\"LAST\"==e){if(\"SET\"==d)return e=b(),e+(c+\"[\"+c+\".length - 1] = \"+a+\";\\n\");if(\"INSERT\"==d)return c+\".push(\"+a+\");\\n\"}else if(\"FROM_START\"==e){f=Blockly.isNumber(f)?parseFloat(f)-1:f+\" - 1\";if(\"SET\"==d)return c+\"[\"+f+\"] = \"+a+\";\\n\";if(\"INSERT\"==d)return c+\".splice(\"+f+\", 0, \"+a+\");\\n\"}else if(\"FROM_END\"==e){e=b();if(\"SET\"==d)return e+(c+\"[\"+c+\".length - \"+f+\"] = \"+a+\";\\n\");if(\"INSERT\"==d)return e+\n(c+\".splice(\"+c+\".length - \"+f+\", 0, \"+a+\");\\n\")}else if(\"RANDOM\"==e){e=b();f=Blockly.JavaScript.variableDB_.getDistinctName(\"tmp_x\",Blockly.Variables.NAME_TYPE);e+=\"var \"+f+\" = Math.floor(Math.random() * \"+c+\".length);\\n\";if(\"SET\"==d)return e+(c+\"[\"+f+\"] = \"+a+\";\\n\");if(\"INSERT\"==d)return e+(c+\".splice(\"+f+\", 0, \"+a+\");\\n\")}throw\"Unhandled combination (lists_setIndex).\";};\nBlockly.JavaScript.lists_getSublist=function(a){var b=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_MEMBER)||\"[]\",c=a.getFieldValue(\"WHERE1\"),d=a.getFieldValue(\"WHERE2\"),e=Blockly.JavaScript.valueToCode(a,\"AT1\",Blockly.JavaScript.ORDER_NONE)||\"1\";a=Blockly.JavaScript.valueToCode(a,\"AT2\",Blockly.JavaScript.ORDER_NONE)||\"1\";return[\"FIRST\"==c&&\"LAST\"==d?b+\".concat()\":Blockly.JavaScript.provideFunction_(\"lists_get_sublist\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\n\"(list, where1, at1, where2, at2) {\",\"  function getAt(where, at) {\",\"    if (where == 'FROM_START') {\",\"      at--;\",\"    } else if (where == 'FROM_END') {\",\"      at = list.length - at;\",\"    } else if (where == 'FIRST') {\",\"      at = 0;\",\"    } else if (where == 'LAST') {\",\"      at = list.length - 1;\",\"    } else {\",\"      throw 'Unhandled option (lists_getSublist).';\",\"    }\",\"    return at;\",\"  }\",\"  at1 = getAt(where1, at1);\",\"  at2 = getAt(where2, at2) + 1;\",\"  return list.slice(at1, at2);\",\n\"}\"])+\"(\"+b+\", '\"+c+\"', \"+e+\", '\"+d+\"', \"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.logic={};\nBlockly.JavaScript.controls_if=function(a){for(var b=0,c=Blockly.JavaScript.valueToCode(a,\"IF\"+b,Blockly.JavaScript.ORDER_NONE)||\"false\",d=Blockly.JavaScript.statementToCode(a,\"DO\"+b),e=\"if (\"+c+\") {\\n\"+d+\"}\",b=1;b<=a.elseifCount_;b++)c=Blockly.JavaScript.valueToCode(a,\"IF\"+b,Blockly.JavaScript.ORDER_NONE)||\"false\",d=Blockly.JavaScript.statementToCode(a,\"DO\"+b),e+=\" else if (\"+c+\") {\\n\"+d+\"}\";a.elseCount_&&(d=Blockly.JavaScript.statementToCode(a,\"ELSE\"),e+=\" else {\\n\"+d+\"}\");return e+\"\\n\"};\nBlockly.JavaScript.logic_compare=function(a){var b={EQ:\"==\",NEQ:\"!=\",LT:\"<\",LTE:\"<=\",GT:\">\",GTE:\">=\"}[a.getFieldValue(\"OP\")],c=\"==\"==b||\"!=\"==b?Blockly.JavaScript.ORDER_EQUALITY:Blockly.JavaScript.ORDER_RELATIONAL,d=Blockly.JavaScript.valueToCode(a,\"A\",c)||\"0\";a=Blockly.JavaScript.valueToCode(a,\"B\",c)||\"0\";return[d+\" \"+b+\" \"+a,c]};\nBlockly.JavaScript.logic_operation=function(a){var b=\"AND\"==a.getFieldValue(\"OP\")?\"&&\":\"||\",c=\"&&\"==b?Blockly.JavaScript.ORDER_LOGICAL_AND:Blockly.JavaScript.ORDER_LOGICAL_OR,d=Blockly.JavaScript.valueToCode(a,\"A\",c);a=Blockly.JavaScript.valueToCode(a,\"B\",c);if(d||a){var e=\"&&\"==b?\"true\":\"false\";d||(d=e);a||(a=e)}else a=d=\"false\";return[d+\" \"+b+\" \"+a,c]};\nBlockly.JavaScript.logic_negate=function(a){var b=Blockly.JavaScript.ORDER_LOGICAL_NOT;return[\"!\"+(Blockly.JavaScript.valueToCode(a,\"BOOL\",b)||\"true\"),b]};Blockly.JavaScript.logic_boolean=function(a){return[\"TRUE\"==a.getFieldValue(\"BOOL\")?\"true\":\"false\",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.logic_null=function(a){return[\"null\",Blockly.JavaScript.ORDER_ATOMIC]};\nBlockly.JavaScript.logic_ternary=function(a){var b=Blockly.JavaScript.valueToCode(a,\"IF\",Blockly.JavaScript.ORDER_CONDITIONAL)||\"false\",c=Blockly.JavaScript.valueToCode(a,\"THEN\",Blockly.JavaScript.ORDER_CONDITIONAL)||\"null\";a=Blockly.JavaScript.valueToCode(a,\"ELSE\",Blockly.JavaScript.ORDER_CONDITIONAL)||\"null\";return[b+\" ? \"+c+\" : \"+a,Blockly.JavaScript.ORDER_CONDITIONAL]};Blockly.JavaScript.loops={};Blockly.JavaScript.controls_repeat=function(a){var b=Number(a.getFieldValue(\"TIMES\")),c=Blockly.JavaScript.statementToCode(a,\"DO\");Blockly.JavaScript.INFINITE_LOOP_TRAP&&(c=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+c);a=Blockly.JavaScript.variableDB_.getDistinctName(\"count\",Blockly.Variables.NAME_TYPE);return\"for (var \"+a+\" = 0; \"+a+\" < \"+b+\"; \"+a+\"++) {\\n\"+c+\"}\\n\"};\nBlockly.JavaScript.controls_repeat_ext=function(a){var b=Blockly.JavaScript.valueToCode(a,\"TIMES\",Blockly.JavaScript.ORDER_ASSIGNMENT)||\"0\",c=Blockly.JavaScript.statementToCode(a,\"DO\");Blockly.JavaScript.INFINITE_LOOP_TRAP&&(c=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+c);a=\"\";var d=Blockly.JavaScript.variableDB_.getDistinctName(\"count\",Blockly.Variables.NAME_TYPE),e=b;b.match(/^\\w+$/)||Blockly.isNumber(b)||(e=Blockly.JavaScript.variableDB_.getDistinctName(\"repeat_end\",Blockly.Variables.NAME_TYPE),\na+=\"var \"+e+\" = \"+b+\";\\n\");return a+(\"for (var \"+d+\" = 0; \"+d+\" < \"+e+\"; \"+d+\"++) {\\n\"+c+\"}\\n\")};\nBlockly.JavaScript.controls_whileUntil=function(a){var b=\"UNTIL\"==a.getFieldValue(\"MODE\"),c=Blockly.JavaScript.valueToCode(a,\"BOOL\",b?Blockly.JavaScript.ORDER_LOGICAL_NOT:Blockly.JavaScript.ORDER_NONE)||\"false\",d=Blockly.JavaScript.statementToCode(a,\"DO\");Blockly.JavaScript.INFINITE_LOOP_TRAP&&(d=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+d);b&&(c=\"!\"+c);return\"while (\"+c+\") {\\n\"+d+\"}\\n\"};\nBlockly.JavaScript.controls_for=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),c=Blockly.JavaScript.valueToCode(a,\"FROM\",Blockly.JavaScript.ORDER_ASSIGNMENT)||\"0\",d=Blockly.JavaScript.valueToCode(a,\"TO\",Blockly.JavaScript.ORDER_ASSIGNMENT)||\"0\",e=Blockly.JavaScript.valueToCode(a,\"BY\",Blockly.JavaScript.ORDER_ASSIGNMENT)||\"1\",f=Blockly.JavaScript.statementToCode(a,\"DO\");Blockly.JavaScript.INFINITE_LOOP_TRAP&&(f=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\n\"'\"+a.id+\"'\")+f);if(Blockly.isNumber(c)&&Blockly.isNumber(d)&&Blockly.isNumber(e)){var g=parseFloat(c)<=parseFloat(d);a=\"for (\"+b+\" = \"+c+\"; \"+b+(g?\" <= \":\" >= \")+d+\"; \"+b;b=Math.abs(parseFloat(e));a=(1==b?a+(g?\"++\":\"--\"):a+((g?\" += \":\" -= \")+b))+(\") {\\n\"+f+\"}\\n\")}else a=\"\",g=c,c.match(/^\\w+$/)||Blockly.isNumber(c)||(g=Blockly.JavaScript.variableDB_.getDistinctName(b+\"_start\",Blockly.Variables.NAME_TYPE),a+=\"var \"+g+\" = \"+c+\";\\n\"),c=d,d.match(/^\\w+$/)||Blockly.isNumber(d)||(c=Blockly.JavaScript.variableDB_.getDistinctName(b+\n\"_end\",Blockly.Variables.NAME_TYPE),a+=\"var \"+c+\" = \"+d+\";\\n\"),d=Blockly.JavaScript.variableDB_.getDistinctName(b+\"_inc\",Blockly.Variables.NAME_TYPE),a+=\"var \"+d+\" = \",a=Blockly.isNumber(e)?a+(Math.abs(e)+\";\\n\"):a+(\"Math.abs(\"+e+\");\\n\"),a=a+(\"if (\"+g+\" > \"+c+\") {\\n\")+(\"  \"+d+\" = -\"+d+\";\\n\"),a+=\"}\\n\",a+=\"for (\"+b+\" = \"+g+\";\\n     \"+d+\" >= 0 ? \"+b+\" <= \"+c+\" : \"+b+\" >= \"+c+\";\\n     \"+b+\" += \"+d+\") {\\n\"+f+\"}\\n\";return a};\nBlockly.JavaScript.controls_forEach=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),c=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_ASSIGNMENT)||\"[]\",d=Blockly.JavaScript.statementToCode(a,\"DO\");Blockly.JavaScript.INFINITE_LOOP_TRAP&&(d=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+d);a=Blockly.JavaScript.variableDB_.getDistinctName(b+\"_index\",Blockly.Variables.NAME_TYPE);return\"for (var \"+a+\" in  \"+\nc+\") {\\n\"+(\"  \"+b+\" = \"+c+\"[\"+a+\"];\\n\"+d)+\"}\\n\"};Blockly.JavaScript.controls_flow_statements=function(a){switch(a.getFieldValue(\"FLOW\")){case \"BREAK\":return\"break;\\n\";case \"CONTINUE\":return\"continue;\\n\"}throw\"Unknown flow statement.\";};Blockly.JavaScript.math={};Blockly.JavaScript.math_number=function(a){return[parseFloat(a.getFieldValue(\"NUM\")),Blockly.JavaScript.ORDER_ATOMIC]};\nBlockly.JavaScript.math_arithmetic=function(a){var b={ADD:[\" + \",Blockly.JavaScript.ORDER_ADDITION],MINUS:[\" - \",Blockly.JavaScript.ORDER_SUBTRACTION],MULTIPLY:[\" * \",Blockly.JavaScript.ORDER_MULTIPLICATION],DIVIDE:[\" / \",Blockly.JavaScript.ORDER_DIVISION],POWER:[null,Blockly.JavaScript.ORDER_COMMA]}[a.getFieldValue(\"OP\")],c=b[0],b=b[1],d=Blockly.JavaScript.valueToCode(a,\"A\",b)||\"0\";a=Blockly.JavaScript.valueToCode(a,\"B\",b)||\"0\";return c?[d+c+a,b]:[\"Math.pow(\"+d+\", \"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};\nBlockly.JavaScript.math_single=function(a){var b=a.getFieldValue(\"OP\"),c;if(\"NEG\"==b)return a=Blockly.JavaScript.valueToCode(a,\"NUM\",Blockly.JavaScript.ORDER_UNARY_NEGATION)||\"0\",\"-\"==a[0]&&(a=\" \"+a),[\"-\"+a,Blockly.JavaScript.ORDER_UNARY_NEGATION];a=\"SIN\"==b||\"COS\"==b||\"TAN\"==b?Blockly.JavaScript.valueToCode(a,\"NUM\",Blockly.JavaScript.ORDER_DIVISION)||\"0\":Blockly.JavaScript.valueToCode(a,\"NUM\",Blockly.JavaScript.ORDER_NONE)||\"0\";switch(b){case \"ABS\":c=\"Math.abs(\"+a+\")\";break;case \"ROOT\":c=\"Math.sqrt(\"+\na+\")\";break;case \"LN\":c=\"Math.log(\"+a+\")\";break;case \"EXP\":c=\"Math.exp(\"+a+\")\";break;case \"POW10\":c=\"Math.pow(10,\"+a+\")\";break;case \"ROUND\":c=\"Math.round(\"+a+\")\";break;case \"ROUNDUP\":c=\"Math.ceil(\"+a+\")\";break;case \"ROUNDDOWN\":c=\"Math.floor(\"+a+\")\";break;case \"SIN\":c=\"Math.sin(\"+a+\" / 180 * Math.PI)\";break;case \"COS\":c=\"Math.cos(\"+a+\" / 180 * Math.PI)\";break;case \"TAN\":c=\"Math.tan(\"+a+\" / 180 * Math.PI)\"}if(c)return[c,Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(b){case \"LOG10\":c=\"Math.log(\"+a+\n\") / Math.log(10)\";break;case \"ASIN\":c=\"Math.asin(\"+a+\") / Math.PI * 180\";break;case \"ACOS\":c=\"Math.acos(\"+a+\") / Math.PI * 180\";break;case \"ATAN\":c=\"Math.atan(\"+a+\") / Math.PI * 180\";break;default:throw\"Unknown math operator: \"+b;}return[c,Blockly.JavaScript.ORDER_DIVISION]};\nBlockly.JavaScript.math_constant=function(a){return{PI:[\"Math.PI\",Blockly.JavaScript.ORDER_MEMBER],E:[\"Math.E\",Blockly.JavaScript.ORDER_MEMBER],GOLDEN_RATIO:[\"(1 + Math.sqrt(5)) / 2\",Blockly.JavaScript.ORDER_DIVISION],SQRT2:[\"Math.SQRT2\",Blockly.JavaScript.ORDER_MEMBER],SQRT1_2:[\"Math.SQRT1_2\",Blockly.JavaScript.ORDER_MEMBER],INFINITY:[\"Infinity\",Blockly.JavaScript.ORDER_ATOMIC]}[a.getFieldValue(\"CONSTANT\")]};\nBlockly.JavaScript.math_number_property=function(a){var b=Blockly.JavaScript.valueToCode(a,\"NUMBER_TO_CHECK\",Blockly.JavaScript.ORDER_MODULUS)||\"0\",c=a.getFieldValue(\"PROPERTY\"),d;if(\"PRIME\"==c)return[Blockly.JavaScript.provideFunction_(\"math_isPrime\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(n) {\",\"  // https://en.wikipedia.org/wiki/Primality_test#Naive_methods\",\"  if (n == 2 || n == 3) {\",\"    return true;\",\"  }\",\"  // False if n is NaN, negative, is 1, or not whole.\",\"  // And false if n is divisible by 2 or 3.\",\n\"  if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {\",\"    return false;\",\"  }\",\"  // Check all the numbers of form 6k +/- 1, up to sqrt(n).\",\"  for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {\",\"    if (n % (x - 1) == 0 || n % (x + 1) == 0) {\",\"      return false;\",\"    }\",\"  }\",\"  return true;\",\"}\"])+\"(\"+b+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(c){case \"EVEN\":d=b+\" % 2 == 0\";break;case \"ODD\":d=b+\" % 2 == 1\";break;case \"WHOLE\":d=b+\" % 1 == 0\";break;case \"POSITIVE\":d=\nb+\" > 0\";break;case \"NEGATIVE\":d=b+\" < 0\";break;case \"DIVISIBLE_BY\":a=Blockly.JavaScript.valueToCode(a,\"DIVISOR\",Blockly.JavaScript.ORDER_MODULUS)||\"0\",d=b+\" % \"+a+\" == 0\"}return[d,Blockly.JavaScript.ORDER_EQUALITY]};Blockly.JavaScript.math_change=function(a){var b=Blockly.JavaScript.valueToCode(a,\"DELTA\",Blockly.JavaScript.ORDER_ADDITION)||\"0\";a=Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE);return a+\" = (typeof \"+a+\" == 'number' ? \"+a+\" : 0) + \"+b+\";\\n\"};\nBlockly.JavaScript.math_round=Blockly.JavaScript.math_single;Blockly.JavaScript.math_trig=Blockly.JavaScript.math_single;\nBlockly.JavaScript.math_on_list=function(a){var b=a.getFieldValue(\"OP\");switch(b){case \"SUM\":a=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_MEMBER)||\"[]\";a+=\".reduce(function(x, y) {return x + y;})\";break;case \"MIN\":a=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_COMMA)||\"[]\";a=\"Math.min.apply(null, \"+a+\")\";break;case \"MAX\":a=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_COMMA)||\"[]\";a=\"Math.max.apply(null, \"+a+\")\";break;case \"AVERAGE\":b=Blockly.JavaScript.provideFunction_(\"math_mean\",\n[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(myList) {\",\"  return myList.reduce(function(x, y) {return x + y;}) / myList.length;\",\"}\"]);a=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_NONE)||\"[]\";a=b+\"(\"+a+\")\";break;case \"MEDIAN\":b=Blockly.JavaScript.provideFunction_(\"math_median\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(myList) {\",\"  var localList = myList.filter(function (x) {return typeof x == 'number';});\",\"  if (!localList.length) return null;\",\n\"  localList.sort(function(a, b) {return b - a;});\",\"  if (localList.length % 2 == 0) {\",\"    return (localList[localList.length / 2 - 1] + localList[localList.length / 2]) / 2;\",\"  } else {\",\"    return localList[(localList.length - 1) / 2];\",\"  }\",\"}\"]);a=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_NONE)||\"[]\";a=b+\"(\"+a+\")\";break;case \"MODE\":b=Blockly.JavaScript.provideFunction_(\"math_modes\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(values) {\",\"  var modes = [];\",\n\"  var counts = [];\",\"  var maxCount = 0;\",\"  for (var i = 0; i < values.length; i++) {\",\"    var value = values[i];\",\"    var found = false;\",\"    var thisCount;\",\"    for (var j = 0; j < counts.length; j++) {\",\"      if (counts[j][0] === value) {\",\"        thisCount = ++counts[j][1];\",\"        found = true;\",\"        break;\",\"      }\",\"    }\",\"    if (!found) {\",\"      counts.push([value, 1]);\",\"      thisCount = 1;\",\"    }\",\"    maxCount = Math.max(thisCount, maxCount);\",\"  }\",\"  for (var j = 0; j < counts.length; j++) {\",\n\"    if (counts[j][1] == maxCount) {\",\"        modes.push(counts[j][0]);\",\"    }\",\"  }\",\"  return modes;\",\"}\"]);a=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_NONE)||\"[]\";a=b+\"(\"+a+\")\";break;case \"STD_DEV\":b=Blockly.JavaScript.provideFunction_(\"math_standard_deviation\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(numbers) {\",\"  var n = numbers.length;\",\"  if (!n) return null;\",\"  var mean = numbers.reduce(function(x, y) {return x + y;}) / n;\",\"  var variance = 0;\",\n\"  for (var j = 0; j < n; j++) {\",\"    variance += Math.pow(numbers[j] - mean, 2);\",\"  }\",\"  variance = variance / n;\",\"  return Math.sqrt(variance);\",\"}\"]);a=Blockly.JavaScript.valueToCode(a,\"LIST\",Blockly.JavaScript.ORDER_NONE)||\"[]\";a=b+\"(\"+a+\")\";break;case \"RANDOM\":b=Blockly.JavaScript.provideFunction_(\"math_random_list\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(list) {\",\"  var x = Math.floor(Math.random() * list.length);\",\"  return list[x];\",\"}\"]);a=Blockly.JavaScript.valueToCode(a,\n\"LIST\",Blockly.JavaScript.ORDER_NONE)||\"[]\";a=b+\"(\"+a+\")\";break;default:throw\"Unknown operator: \"+b;}return[a,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_modulo=function(a){var b=Blockly.JavaScript.valueToCode(a,\"DIVIDEND\",Blockly.JavaScript.ORDER_MODULUS)||\"0\";a=Blockly.JavaScript.valueToCode(a,\"DIVISOR\",Blockly.JavaScript.ORDER_MODULUS)||\"0\";return[b+\" % \"+a,Blockly.JavaScript.ORDER_MODULUS]};\nBlockly.JavaScript.math_constrain=function(a){var b=Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_COMMA)||\"0\",c=Blockly.JavaScript.valueToCode(a,\"LOW\",Blockly.JavaScript.ORDER_COMMA)||\"0\";a=Blockly.JavaScript.valueToCode(a,\"HIGH\",Blockly.JavaScript.ORDER_COMMA)||\"Infinity\";return[\"Math.min(Math.max(\"+b+\", \"+c+\"), \"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};\nBlockly.JavaScript.math_random_int=function(a){var b=Blockly.JavaScript.valueToCode(a,\"FROM\",Blockly.JavaScript.ORDER_COMMA)||\"0\";a=Blockly.JavaScript.valueToCode(a,\"TO\",Blockly.JavaScript.ORDER_COMMA)||\"0\";return[Blockly.JavaScript.provideFunction_(\"math_random_int\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(a, b) {\",\"  if (a > b) {\",\"    // Swap a and b to ensure a is smaller.\",\"    var c = a;\",\"    a = b;\",\"    b = c;\",\"  }\",\"  return Math.floor(Math.random() * (b - a + 1) + a);\",\n\"}\"])+\"(\"+b+\", \"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_random_float=function(a){return[\"Math.random()\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.procedures={};\nBlockly.JavaScript.procedures_defreturn=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE),c=Blockly.JavaScript.statementToCode(a,\"STACK\");Blockly.JavaScript.INFINITE_LOOP_TRAP&&(c=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+c);var d=Blockly.JavaScript.valueToCode(a,\"RETURN\",Blockly.JavaScript.ORDER_NONE)||\"\";d&&(d=\"  return \"+d+\";\\n\");for(var e=[],f=0;f<a.arguments_.length;f++)e[f]=Blockly.JavaScript.variableDB_.getName(a.arguments_[f],\nBlockly.Variables.NAME_TYPE);c=\"function \"+b+\"(\"+e.join(\", \")+\") {\\n\"+c+d+\"}\";c=Blockly.JavaScript.scrub_(a,c);Blockly.JavaScript.definitions_[b]=c;return null};Blockly.JavaScript.procedures_defnoreturn=Blockly.JavaScript.procedures_defreturn;\nBlockly.JavaScript.procedures_callreturn=function(a){for(var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE),c=[],d=0;d<a.arguments_.length;d++)c[d]=Blockly.JavaScript.valueToCode(a,\"ARG\"+d,Blockly.JavaScript.ORDER_COMMA)||\"null\";return[b+\"(\"+c.join(\", \")+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};\nBlockly.JavaScript.procedures_callnoreturn=function(a){for(var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE),c=[],d=0;d<a.arguments_.length;d++)c[d]=Blockly.JavaScript.valueToCode(a,\"ARG\"+d,Blockly.JavaScript.ORDER_COMMA)||\"null\";return b+\"(\"+c.join(\", \")+\");\\n\"};\nBlockly.JavaScript.procedures_ifreturn=function(a){var b=\"if (\"+(Blockly.JavaScript.valueToCode(a,\"CONDITION\",Blockly.JavaScript.ORDER_NONE)||\"false\")+\") {\\n\";a.hasReturnValue_?(a=Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_NONE)||\"null\",b+=\"  return \"+a+\";\\n\"):b+=\"  return;\\n\";return b+\"}\\n\"};Blockly.JavaScript.text={};Blockly.JavaScript.text=function(a){return[Blockly.JavaScript.quote_(a.getFieldValue(\"TEXT\")),Blockly.JavaScript.ORDER_ATOMIC]};\nBlockly.JavaScript.text_join=function(a){var b;if(0==a.itemCount_)return[\"''\",Blockly.JavaScript.ORDER_ATOMIC];if(1==a.itemCount_)return b=Blockly.JavaScript.valueToCode(a,\"ADD0\",Blockly.JavaScript.ORDER_NONE)||\"''\",[\"String(\"+b+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL];if(2==a.itemCount_)return b=Blockly.JavaScript.valueToCode(a,\"ADD0\",Blockly.JavaScript.ORDER_NONE)||\"''\",a=Blockly.JavaScript.valueToCode(a,\"ADD1\",Blockly.JavaScript.ORDER_NONE)||\"''\",[\"String(\"+b+\") + String(\"+a+\")\",Blockly.JavaScript.ORDER_ADDITION];\nb=Array(a.itemCount_);for(var c=0;c<a.itemCount_;c++)b[c]=Blockly.JavaScript.valueToCode(a,\"ADD\"+c,Blockly.JavaScript.ORDER_COMMA)||\"''\";b=\"[\"+b.join(\",\")+\"].join('')\";return[b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.text_append=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE);a=Blockly.JavaScript.valueToCode(a,\"TEXT\",Blockly.JavaScript.ORDER_NONE)||\"''\";return b+\" = String(\"+b+\") + String(\"+a+\");\\n\"};\nBlockly.JavaScript.text_length=function(a){return[(Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_FUNCTION_CALL)||\"''\")+\".length\",Blockly.JavaScript.ORDER_MEMBER]};Blockly.JavaScript.text_isEmpty=function(a){return[\"!\"+(Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_MEMBER)||\"''\"),Blockly.JavaScript.ORDER_LOGICAL_NOT]};\nBlockly.JavaScript.text_indexOf=function(a){var b=\"FIRST\"==a.getFieldValue(\"END\")?\"indexOf\":\"lastIndexOf\",c=Blockly.JavaScript.valueToCode(a,\"FIND\",Blockly.JavaScript.ORDER_NONE)||\"''\";return[(Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_MEMBER)||\"''\")+\".\"+b+\"(\"+c+\") + 1\",Blockly.JavaScript.ORDER_MEMBER]};\nBlockly.JavaScript.text_charAt=function(a){var b=a.getFieldValue(\"WHERE\")||\"FROM_START\",c=Blockly.JavaScript.valueToCode(a,\"AT\",Blockly.JavaScript.ORDER_UNARY_NEGATION)||\"1\";a=Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_MEMBER)||\"''\";switch(b){case \"FIRST\":return[a+\".charAt(0)\",Blockly.JavaScript.ORDER_FUNCTION_CALL];case \"LAST\":return[a+\".slice(-1)\",Blockly.JavaScript.ORDER_FUNCTION_CALL];case \"FROM_START\":return c=Blockly.isNumber(c)?parseFloat(c)-1:c+\" - 1\",[a+\".charAt(\"+\nc+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL];case \"FROM_END\":return[a+\".slice(-\"+c+\").charAt(0)\",Blockly.JavaScript.ORDER_FUNCTION_CALL];case \"RANDOM\":return[Blockly.JavaScript.provideFunction_(\"text_random_letter\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(text) {\",\"  var x = Math.floor(Math.random() * text.length);\",\"  return text[x];\",\"}\"])+\"(\"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]}throw\"Unhandled option (text_charAt).\";};\nBlockly.JavaScript.text_getSubstring=function(a){var b=Blockly.JavaScript.valueToCode(a,\"STRING\",Blockly.JavaScript.ORDER_MEMBER)||\"''\",c=a.getFieldValue(\"WHERE1\"),d=a.getFieldValue(\"WHERE2\"),e=Blockly.JavaScript.valueToCode(a,\"AT1\",Blockly.JavaScript.ORDER_NONE)||\"1\";a=Blockly.JavaScript.valueToCode(a,\"AT2\",Blockly.JavaScript.ORDER_NONE)||\"1\";return[\"FIRST\"==c&&\"LAST\"==d?b:Blockly.JavaScript.provideFunction_(\"text_get_substring\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(text, where1, at1, where2, at2) {\",\n\"  function getAt(where, at) {\",\"    if (where == 'FROM_START') {\",\"      at--;\",\"    } else if (where == 'FROM_END') {\",\"      at = text.length - at;\",\"    } else if (where == 'FIRST') {\",\"      at = 0;\",\"    } else if (where == 'LAST') {\",\"      at = text.length - 1;\",\"    } else {\",\"      throw 'Unhandled option (text_getSubstring).';\",\"    }\",\"    return at;\",\"  }\",\"  at1 = getAt(where1, at1);\",\"  at2 = getAt(where2, at2) + 1;\",\"  return text.slice(at1, at2);\",\"}\"])+\"(\"+b+\", '\"+c+\"', \"+e+\", '\"+\nd+\"', \"+a+\")\",Blockly.JavaScript.ORDER_FUNCTION_CALL]};\nBlockly.JavaScript.text_changeCase=function(a){var b={UPPERCASE:\".toUpperCase()\",LOWERCASE:\".toLowerCase()\",TITLECASE:null}[a.getFieldValue(\"CASE\")];b?(a=Blockly.JavaScript.valueToCode(a,\"TEXT\",Blockly.JavaScript.ORDER_MEMBER)||\"''\",a+=b):(b=Blockly.JavaScript.provideFunction_(\"text_toTitleCase\",[\"function \"+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+\"(str) {\",\"  return str.replace(/\\\\S+/g,\",\"      function(txt) {return txt[0].toUpperCase() + txt.substring(1).toLowerCase();});\",\"}\"]),a=Blockly.JavaScript.valueToCode(a,\n\"TEXT\",Blockly.JavaScript.ORDER_NONE)||\"''\",a=b+\"(\"+a+\")\");return[a,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.text_trim=function(a){var b={LEFT:\".trimLeft()\",RIGHT:\".trimRight()\",BOTH:\".trim()\"}[a.getFieldValue(\"MODE\")];return[(Blockly.JavaScript.valueToCode(a,\"TEXT\",Blockly.JavaScript.ORDER_MEMBER)||\"''\")+b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};\nBlockly.JavaScript.text_print=function(a){return\"window.alert(\"+(Blockly.JavaScript.valueToCode(a,\"TEXT\",Blockly.JavaScript.ORDER_NONE)||\"''\")+\");\\n\"};Blockly.JavaScript.text_prompt=function(a){var b=\"window.prompt(\"+Blockly.JavaScript.quote_(a.getFieldValue(\"TEXT\"))+\")\";\"NUMBER\"==a.getFieldValue(\"TYPE\")&&(b=\"parseFloat(\"+b+\")\");return[b,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.variables={};Blockly.JavaScript.variables_get=function(a){return[Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.variables_set=function(a){var b=Blockly.JavaScript.valueToCode(a,\"VALUE\",Blockly.JavaScript.ORDER_ASSIGNMENT)||\"0\";return Blockly.JavaScript.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE)+\" = \"+b+\";\\n\"};"
  },
  {
    "path": "extern/blockly/msg/js/ar.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.ar');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"اضافة تعليق\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"تغيير قيمة:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"إخفاء القطع\";\nBlockly.Msg.COLLAPSE_BLOCK = \"إخفاء القطعة\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"اللون 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"اللون 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"نسبة\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"دمج\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"دمج لونين ببعضهما البعض بنسبة (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://ar.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"اختر لون من اللوحة.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"لون عشوائي\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"اختر لون بشكل عشوائي.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"أزرق\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"أخضر\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"أحمر\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"لون مع\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"إنشئ لون بالكمية المحددة من الأحمر, الأخضر والأزرق. بحيث يجب تكون كافة القيم بين 0 و 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"اخرج من الحلقة\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"استمر ابتداءا من التكرار التالي من الحلقة\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"اخرج من الحلقة الحالية.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"تخط ما تبقى من هذه الحلقة، واستمر ابتداءا من التكرار التالي.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"تحذير: يمكن استخدام هذه القطعة فقط داخل حلقة.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"_each https://code.google.com/p/blockly/wiki/Loops#for العبارة الشرطية \\\"لِكُل\\\"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"في قائمة\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"لكل عنصر\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"لكل عنصر في قائمة ما، عين المتغير '%1' لهذا الغنصر، ومن ثم نفذ بعض الأوامر.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"من %1 إلى %2 بمعدل %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"عد بـ\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"اجعل المتغير  %1 يأخذ القيم من رقم البداية الى رقم النهاية، قم بالعد داخل المجال المحدد، وطبق أوامر القطع المحددة.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"إضف شرطا إلى القطعة الشرطية \\\"إذا\\\".\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"أضف شرط \\\"نهاية، إجمع\\\" إلى القطعة الشرطية \\\"إذا\\\".\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"أضف, إزل, أو أعد ترتيب المقاطع لإعادة تكوين القطعة الشرطية \\\"إذا\\\".\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"والا\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"وإﻻ إذا\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"إذا\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"إذا كانت قيمة ما تساوي صحيح, إذن قم بتنفيذ أمر ما.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"إذا كانت قيمة ما تساوي \\\"صحيح\\\"، إذن قم بتنفيذ أول قطعة من الأوامر. والا ،قم بتنفيذ القطعة الثانية من الأوامر.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"إذا كانت القيمة الأولى تساوي \\\"صحيح\\\", إذن قم بتنفيذ القطعة الأولى من الأوامر. والا, إذا كانت القيمة الثانية تساوي \\\"صحيح\\\", قم بتنفيذ القطعة الثانية من الأوامر.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"إذا كانت القيمة الأولى تساوي \\\"صحيح\\\", إذن قم بتنفيذ القطعة الأولى من الأوامر. والا , إذا كانت القيمة الثانية تساوي \\\"صحيح\\\", قم بتنفيذ القطعة الثانية من الأوامر. إذا لم تكن هناك أي قيمة تساوي صحيح, قم بتنفيذ آخر قطعة من الأوامر.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"نفّذ\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"كرر  %1 مرات\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"أكرر\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"مرات\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"نفّذ بعض الأوامر عدة مرات.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"اكرّر حتى\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"اكرّر طالما\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"بما ان القيمة خاطئة, نفّذ بعض الأوامر.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"بما ان القيمة صحيحة, نفّذ بعض الأوامر.\";\nBlockly.Msg.DELETE_BLOCK = \"إحذف القطعة\";\nBlockly.Msg.DELETE_X_BLOCKS = \"إحذف قطع %1\";\nBlockly.Msg.DISABLE_BLOCK = \"عطّل القطعة\";\nBlockly.Msg.DUPLICATE_BLOCK = \"ادمج\";\nBlockly.Msg.ENABLE_BLOCK = \"أعد تفعيل القطعة\";\nBlockly.Msg.EXPAND_ALL = \"وسٌّع القطع\";\nBlockly.Msg.EXPAND_BLOCK = \"وسٌّع القطعة\";\nBlockly.Msg.EXTERNAL_INPUTS = \"ادخال خارجي\";\nBlockly.Msg.HELP = \"مساعدة\";\nBlockly.Msg.INLINE_INPUTS = \"ادخال خطي\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"إنشئ قائمة فارغة\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"تقوم بإرجاع قائمة، طولها 0, لا تحتوي على أية سجلات البيانات\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"قائمة\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"أضف, إزل, أو أعد ترتيب المقاطع لإعادة تكوين القطعة قائمة القطع التالية.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"أتشئ قائمة مع\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"أضف عنصرا إلى القائمة.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"أنشيء قائمة من أي عدد من العناصر.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"أول\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# من نهاية\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"احصل على\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"احصل على و ازل\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"أخير\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"عشوائي\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"ازل\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"يرجع العنصر الأول في قائمة ما.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"يقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"يقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"يرجع العنصر الأخير في قائمة ما.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"يرجع عنصرا عشوائيا في قائمة.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"يزيل ويرجع العنصر الأول في قائمة.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"يزيل ويقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"يزيل ويقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"يزيل ويرجع العنصر الأخير في قائمة ما.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"يزيل و يرجع عنصرا عشوائيا في قائمة ما.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"يزيل العنصر الأول في قائمة ما.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"يزيل العنصر الموجود في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"يزيل العنصر الموجود في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"يزيل العنصر الأخير في قائمة ما.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"يزيل عنصرا عشوائيا في قائمة ما.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"إلى # من نهاية\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"إلى #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"إلى الأخير\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"احصل على قائمة فرعية من الأول\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"احصل  على قائمة فرعية من # من نهاية\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"احصل على قائمة فرعية من #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"يقوم بإنشاء نسخة من الجزء المحدد من قائمة ما.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"ابحث على على التواجد الأول للعنصر\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"ابحث على التواجد الأخير للعنصر\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"تقوم بإرجاع مؤشر التواجد  الأول/الأخير في القائمة.  تقوم بإرجاع 0 إذا لم يتم العثور على النص.\";\nBlockly.Msg.LISTS_INLIST = \"في قائمة\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 فارغ\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"الطول من %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"تقوم بإرجاع طول قائمة.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"إنشئ قائمة مع العنصر  %1 %2 مرات\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"انشئ قائمة تتألف من القيمة المعطاة متكررة لعدد محدد من المرات.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"مثل\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"أدخل في\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"تعيين\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"يقوم بإدراج هذا العنصر في بداية قائمة.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"يقوم بإدخال العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"يقوم بإدخال العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"ألصق هذا العنصر بنهاية قائمة.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"ادخل العنصر عشوائياً في القائمة.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"يحدد العنصر الأول في قائمة.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"يحدد العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"يحدد العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"يحدد العنصر الأخير في قائمة.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"يحدد عنصرا عشوائيا في قائمة.\";\nBlockly.Msg.LISTS_TOOLTIP = \"يرجع \\\"صحيح\\\" إذا كانت القائمة فارغة.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"خاطئ\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"يرجع صحيح أو خاطئ.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"صحيح\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"يرجع صحيح إذا كان كلا المدخلات مساوية بعضها البعض.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"يرجع صحيح إذا كان الإدخال الأول أكبر من الإدخال الثاني.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"يرجع صحيح إذا كان الإدخال الأول أكبر من أو يساوي الإدخال الثاني.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"يرجع صحيح إذا كان الإدخال الأول أصغر من الإدخال الثاني.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"يرجع صحيح إذا كان الإدخال الأول أصغر من أو يساوي الإدخال الثاني.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"يرجع صحيح إذا كانت كلا المدخلات غير مساوية لبعضها البعض.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"ليس من %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"يرجع صحيح إذا كان الإدخال خاطئ .  يرجع خاطئ إذا كان الإدخال صحيح.\";\nBlockly.Msg.LOGIC_NULL = \"ملغى\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"ترجع ملغى.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"و\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"أو\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"ترجع صحيح إذا كان كلا المٌدخلات صحيح.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"ترجع صحيح إذا كان واحد على الأقل من المدخلات صحيح.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"اختبار\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"إذا كانت العبارة خاطئة\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"إذا كانت العبارة صحيحة\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"تحقق الشرط في 'الاختبار'. إذا كان الشرط صحيح، يقوم بإرجاع قيمة 'اذا كانت العبارة صحيحة'؛ خلاف ذلك يرجع قيمة 'اذا كانت العبارة خاطئة'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"يرجع مجموع الرقمين.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"يرجع حاصل قسمة الرقمين.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"يرجع الفرق بين الرقمين.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"يرجع حاصل ضرب الرقمين.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"يرجع الرقم الأول مرفوع إلى تربيع الرقم الثاني.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"بـ\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"غير\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"إضف رقم إلى متغير '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"ير جع واحد من الثوابت الشائعة : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"تقيد %1 منخفض %2 مرتفع %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"تقييد العددليكون بين الحدود المحددة (ضمناً).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"قابل للقسمة\";\nBlockly.Msg.MATH_IS_EVEN = \"هو زوجي\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"هو سالب\";\nBlockly.Msg.MATH_IS_ODD = \"هو فرذي\";\nBlockly.Msg.MATH_IS_POSITIVE = \"هو موجب\";\nBlockly.Msg.MATH_IS_PRIME = \"هو أولي\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"تحقق إذا كان عدد ما زوجيا، فرذيا, أوليا، صحيحا،موجبا أو سالبا، أو إذا كان قابلا للقسمة على عدد معين.  يرجع صحيح أو خاطئ.\";\nBlockly.Msg.MATH_IS_WHOLE = \"هو صحيح\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"باقي %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"يرجع الباقي من قسمة الرقمين.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"عدد ما.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"متوسط القائمة\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"الحد الأقصى لقائمة\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"متوسط القائمة\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"الحد الأدنى من قائمة\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"منوال القائمة\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"عنصر عشوائي من القائمة\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"الانحراف المعياري للقائمة\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"مجموع القائمة\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"يرجع المعدل (الوسط الحسابي) للقيم الرقمية في القائمة.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"يرجع أكبر عدد في القائمة.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"يرجع وسيط العدد في القائمة.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"يرجع أصغر رقم في القائمة.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"يرجع قائمة من العنصر أو العناصر الأكثر شيوعاً في القائمة.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"يرجع عنصر عشوائي من القائمة.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"يرجع الانحراف المعياري للقائمة.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"يرجع مجموع كافة الأرقام الموجودة في القائمة.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"كسر عشوائي\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"يرجع جزء عشوائي بين 0.0 (ضمنياً) و 1.0 (خارجيا).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \" عدد صحيح عشوائي من %1 إلى %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"يرجع عدد صحيح عشوائي بين حدين محددين, ضمنيا.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"تقريب\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"تقريب إلى اصغر عدد صحيح\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"تقريب الى اكبر عدد صحيح\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"تقريب الى اكبر عدد صحيح أو الى اصغر عدد صحيح.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"مطلق\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"الجذر التربيعي\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"يرجع القيمة المطلقة لرقم.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"يرجع  e الذي هو الاس المرفوع للرقم.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"يرجع اللوغاريتم الطبيعي لرقم.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"يرجع لوغاريتم عدد معين للاساس 10.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"يرجع عدد سالب.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"يرجع مضروب الرقم 10 في نفسه .\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"يرجع الجذر التربيعي للرقم.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"جيب تمام\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"جيب\";\nBlockly.Msg.MATH_TRIG_TAN = \"ظل\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"يرجع قوس جيب التمام لرقم.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"يرجع قوس الجيب للرقم.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"يرجع قوس الظل للرقم.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"يرجع جيب التمام لدرجة (لا زواية نصف قطرية).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"يرجع جيب التمام لدرجة (لا زواية نصف قطرية).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"يرجع الظل لدرجة (لا دائرة نصف قطرية).\";\nBlockly.Msg.NEW_VARIABLE = \"متغير جديد...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"اسم المتغير الجديد:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"مع:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"تشغيل الدالة المعرفة من قبل المستخدم '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"تشغيل الدالة المعرفة من قبل المستخدم %1 واستخدام  مخرجاتها.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"إنشئ '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"القيام بشيء ما\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"إلى\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"انشئ دالة بدون مخرجات .\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"يرجع\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"انشئ دالة مع المخرجات.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"تحذير: هذه الدالة تحتوي على معلمات مكررة.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"تسليط الضوء على تعريف الدالة\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"إذا كانت القيمة صحيحة ، اذان قم بارجاع القيمة الثانية.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"تحذير:هذه القطعة تستخدم فقط داخل تعريف دالة.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"اسم الإدخال:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"المدخلات\";\nBlockly.Msg.REMOVE_COMMENT = \"ازل التعليق\";\nBlockly.Msg.RENAME_VARIABLE = \"إعادة تسمية المتغير...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"إعادة تسمية كافة المتغيرات '%1' إلى:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"إلصق نص\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"إلى\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"إلصق جزءا من النص إلى متغير '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"الى حروف صغيرة\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"الى حروف العنوان\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"الى حروف كبيرة\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"يرجع نسخة من النص في حالة مختلفة.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"احصل على الحرف الأول\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"الحصول على الحرف # من نهاية\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"الحصول على الحرف #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"في النص\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"احصل على آخر حرف\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"الحصول على حرف عشوائي\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"يرجع حرف ما في الموضع المحدد.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"إضف عنصر إلى النص.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"الانضمام إلى\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"أضف, إحذف, أو أعد ترتيب المقاطع لإعادة تكوين النص من القطع التالية.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"إلى حرف # من نهاية\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"إلى حرف #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"إلى آخر حرف\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"في النص\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"الحصول على سلسلة فرعية من الحرف الأول\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"الحصول على سلسلة حروف فرعية من الحرف # من نهاية\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"الحصول على سلسلة حروف فرعية من الحرف #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"يرجع جزء معين من النص.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"في النص\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"ابحث عن التواجد الأول للنص\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"ابحث عن التواجد الأخير للنص\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"تقوم بإرجاع مؤشر التواجد الأول/الأخير للنص الأول في النص الثاني.  تقوم بإرجاع 0 إذا لم يتم العثور على النص.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 فارغ\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"يرجع \\\"صحيح\\\" إذا كان النص المقدم فارغ.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"انشئ نص مع\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"أنشئ جزء من النص بالصاق أي عدد من العناصر ببعضها البعض.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"طول %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"تقوم بإرجاع عدد الاحرف (بما في ذلك الفراغات) في النص المقدم.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"اطبع %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"اطبع النص المحدد أو العدد أو قيمة أخرى.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"انتظر ادخال المستخذم لرقم ما.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"انتظر ادخال المستخدم لنص ما.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"انتظر ادخال المستخدم لرقم ما مع اظهار رسالة\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"انتظر ادخال المستخدم لنص ما مع اظهار رسالة\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"حرف أو كلمة أو سطر من النص.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"ازالة الفراغات من كلا الجانبين\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"ازالة الفراغات من الجانب الأيسر\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"ازالة الفراغات من الجانب الأيمن\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"يرجع نسخة من النص مع حذف من أحد أو كلا الفراغات من أطرافه.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"البند\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"انشئ 'التعيين %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"يرجع قيمة هذا المتغير.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"انشئ 'احصل على %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"إلى\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"تعيين\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"تعيين هذا المتغير لتكون مساوية للقيمة المدخلة.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/az-latn.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.az-latn');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Şərh əlavə et\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Qiyməti dəyiş:\";\nBlockly.Msg.COLLAPSE_ALL = \"Blokları yığ\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Bloku yığ\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"rəng 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"rəng 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"nisbət\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"qarışdır\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"İki rəngi verilmiş nisbətdə (0,0 - 1,0) qarışdırır.\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Palitradan bir rəng seçin.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"təsadüfi rəng\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Təsadüfi bir rəng seçin.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"mavi\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"yaşıl\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"qırmızı\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"rəngin komponentləri:\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Qırmızı, yaşıl və mavinin göstərilən miqdarı ilə bir rəng düzəlt. Bütün qiymətlər 0 ilə 100 arasında olmalıdır.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"dövrdən çıx\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"dövrün növbəti addımından davam et\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Cari dövrdən çıx.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Bu dövrün qalanını ötür və növbəti addımla davam et.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Xəbərdarlıq: Bu blok ancaq dövr daxilində istifadə oluna bilər.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"siyahıda\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"hər element üçün\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Siyahıdakı hər element üçün \\\"%1\\\" dəyişənini elementə mənimsət və bundan sonra bəzi əmrləri yerinə yetir.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"%1 ilə başlayıb, %2 qiymətinə kimi %3 qədır dəyiş\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"say:\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"%1 dəyişəni başlanğıc ədəddən son ədədə qədər göstərilən aralıqla qiymətlər aldıqca göstərilən blokları yerinə yetir.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"\\\"Əgər\\\" blokuna bir şərt əlavə et.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"\\\"Əgər\\\" blokuna qalan bütün halları əhatə edəb son bir şərt əlavə et.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Bu \\\"əgər\\\" blokunu dəyişdirmək üçün bölümlərin yenisini əlavə et, sil və ya yerini dəyiş.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"əks halda\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"əks halda əgər\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"əgər\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Əgər qiymət doğrudursa, onda bəzi əmrləri yerinə yetir.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Əgər qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda isə ikinci əmrlər blokunu yerinə yetir.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir. Əgər qiymətlərdən heç biri doğru deyilsə, onda axırıncı əmrlər blokunu yerinə yetir.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"yerinə yetir\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1 dəfə təkrar et\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"təkrar et\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"dəfə\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Bəzi əmrləri bir neçə dəfə yerinə yetir.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"təkrar et, o vaxta qədər ki\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"təkrar et, hələ ki\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Hələ ki, qiymət \\\"yalan\\\"dır, bəzi əmrləri yerinə yetir.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Hələ ki, qiymət \\\"doğru\\\"dur, bəzi əmrləri yerinə yetir.\";\nBlockly.Msg.DELETE_BLOCK = \"Bloku sil\";\nBlockly.Msg.DELETE_X_BLOCKS = \"%1 bloku sil\";\nBlockly.Msg.DISABLE_BLOCK = \"Bloku söndür\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Dublikatını düzəlt\";\nBlockly.Msg.ENABLE_BLOCK = \"Bloku aktivləşdir\";\nBlockly.Msg.EXPAND_ALL = \"Blokları aç\";\nBlockly.Msg.EXPAND_BLOCK = \"Bloku aç\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Xarici girişlər\";\nBlockly.Msg.HELP = \"Kömək\";\nBlockly.Msg.INLINE_INPUTS = \"Sətiriçi girişlər\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"boş siyahı düzəlt\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Heç bir verilən qeyd olunmamış, uzunluğu 0 olan bir siyahı verir\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"siyahı\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Bu siyahı blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"bunlardan siyahı düzəlt\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Siyahıya element əlavə edin.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"İstənilən ölçülü siyahı yaradın.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"birinci\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"sondan # nömrəli\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"Götürün\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"Götür və sil\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"axırıncı\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"təsadüfi\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"Sil\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Siyahının ilk elementini qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Siyahıdan təyin olunmuş indeksli elementi qaytarır. #1 son elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Siyahıdan təyin olunmuş indeksli elementi qaytarır. #1 ilk elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Siyahının son elementini qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Siyahıdan hər hansı təsadüfi elementi qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Siyahıdan ilk elementi silir və qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Siyahıdan təyin olunmuş indeksli elementi silir və qaytarır. #1 son elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Siyahıdan təyin olunmuş indeksli elementi silir və qaytarır. #1 ilk elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Siyahıdan son elementi silir və qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Siyahıdan təsadufi elementi silir və qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Siyahıdan ilk elementi silir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Siyahıdan təyin olunmuş indeksli elementi silir. #1 son elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Siyahıdan təyin olunmuş indeksli elementi silir. #1 ilk elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Siyahıdan son elementi silir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Siyahıdan təsadüfi elementi silir.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"sondan # nömrəliyə\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"# nömrəliyə\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"Sonuncuya\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"Birincidən alt-siyahını alın\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"# sonuncudan alt-siyahını alın\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"# - dən alt-siyahını alın\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Siyahının təyin olunmuş hissəsinin surətini yaradın.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"Element ilə ilk rastlaşma indeksini müəyyən edin\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"Element ilə son rastlaşma indeksini müəyyən edin\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Siyahıda element ilə ilk/son rastlaşma indeksini qaytarır. Əgər tekst siyahıda tapılmazsa, 0 qaytarılır.\";\nBlockly.Msg.LISTS_INLIST = \"siyahıda\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 boşdur\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"%1 siyahısının uzunluğu\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Siyahının uzunluğunu verir.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"%1 elementinin siyahıda %2 dəfə təkrarlandığı siyahı yaradım\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Təyin olunmuş elementin/qiymətin təyin olunmuş sayda təkrarlandığı siyahını yaradır.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"Kimi\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"daxil et\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"təyin et\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Elementi siyahının əvvəlinə daxil edir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Elementi siyahıda göstərilən yerə daxil edir. #1 axırıncı elementdir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Elementi siyahıda göstərilən yerə daxil edir. #1 birinci elementdir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Elementi siyahının sonuna artırır.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Elementi siyahıda təsadüfi seçilmiş bir yerə atır.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Siyahıda birinci elementi təyin edir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Siyahının göstərilən yerdəki elementini təyin edir. #1 axırıncı elementdir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Siyahının göstərilən yerdəki elementini təyin edir. #1 birinci elementdir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Siyahının sonuncu elementini təyin edir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Siyahının təsadüfi seçilmiş bir elementini təyin edir.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Siyahı boşdursa \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"yalan\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"\\\"doğru\\\" və ya \\\"yalan\\\" cavanını qaytarır.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"doğru\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Girişlər bir birinə bərabərdirsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Birinci giriş ikincidən böyükdürsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Birinci giriş ikincidən böyük və ya bərarbərdirsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Birinci giriş ikincidən kiçikdirsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Birinci giriş ikincidən kiçik və ya bərarbərdirsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Girişlər bərabər deyillərsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"%1 deyil\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Giriş \\\"yalan\\\"-dursa \\\"doğru\\\" cavabını qaytarır. Giriş \\\"doğru\\\"-dursa \\\"yalan\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_NULL = \"boş\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Boş cavab qaytarır.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"və\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"və ya\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Hər iki giriş \\\"doğru\\\"-dursa \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Girişlərdən heç olmasa biri \\\"doğru\\\"-dursa \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"yoxla\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"əgər yalandırsa\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"əgər doğrudursa\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"'Yoxla' əmrindəki şərtə nəzər yetirin. Əgər şərt \\\"doğru\\\"-dursa \\\"əgər doğru\\\", əks halda isə \\\"əgər yalan\\\" cavabını qaytarır.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://az.wikipedia.org/wiki/Hesab\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"İki ədədin cəmini qaytarır.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"İki ədədin nisbətini qaytarır.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"İki ədədin fərqini qaytarır.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"İki ədədin hasilini verir.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Birinci ədədin ikinci ədəd dərəcəsindən qüvvətini qaytarır.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"buna:\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"dəyiş:\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"'%1' dəyişəninin üzərinə bir ədəd artır.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Ümumi sabitlərdən birini qaytarır π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), və ya ∞ (sonsuzluq).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"%1 üçün ən aşağı %2, ən yuxarı %3 olmağı tələb et\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Bir ədədin verilmiş iki ədəd arasında olmasını tələb edir (sərhədlər də daxil olmaqla).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"bölünür\";\nBlockly.Msg.MATH_IS_EVEN = \"cütdür\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"mənfidir\";\nBlockly.Msg.MATH_IS_ODD = \"təkdir\";\nBlockly.Msg.MATH_IS_POSITIVE = \"müsətdir\";\nBlockly.Msg.MATH_IS_PRIME = \"sadədir\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Bir ədədin cüt, tək, sadə, mürəkkəb, mənfi, müsbət olmasını və ya müəyyən bir ədədə bölünməsini yoxlayır. \\\"Doğru\\\" və ya \\\"yalan\\\" cavablarını qaytarır.\";\nBlockly.Msg.MATH_IS_WHOLE = \"mürəkkəbdir\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"%1 ÷ %2 bölməsinin qalığı\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"İki ədədin nisbətindən alınan qalığı qaytarır.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Ədəd.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"siyahının ədədi ortası\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"siyahının maksimumu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"siyahının medianı\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"siyahının minimumu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"Siyahı modları( Ən çox rastlaşılan elementləri)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"siyahıdan təsadüfi seçilmiş bir element\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"Siyahının standart deviasiyası\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"Siyahının cəmi\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Siyahıdaki ədədlərin ədədi ortasını qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Siyahıdaki ən böyük elementi qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Siyahının median elementini qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Siyahıdaki ən kiçik ədədi qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Siyahıdaki ən çox rastlanan element(lər)dən ibarət siyahı qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Siyahıdan təsadüfi bir element qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Siyahının standart deviasiyasını qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Siyahıdakı bütün ədədlərin cəmini qaytarır.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"təsadüfi kəsr\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"0.0 (daxil olmaqla) və 1.0 (daxil olmamaqla) ədədlərinin arasından təsadüfi bir kəsr ədəd qaytarır.\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"%1 ilə %2 arasından təsadüfi tam ədəd\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Verilmiş iki ədəd arasından (ədədrlər də daxil olmaqla) təsadüfi bir tam ədəd qaytarır.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"yuvarlaq\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"aşağı yuvarlaqlaşdır\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"yuxarı yuvarlaqlaşdır\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Ədədi aşağı və ya yuxari yuvarlaqşdır.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"modul\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"kvadrat kök\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Ədədin modulunu qaytarır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"e sabitinin verilmiş ədədə qüvvətini qaytarır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Ədədin natural loqarifmini tapır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Ədədin 10-cu dərəcədən loqarifmini tapır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Ədədin əksini qaytarır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"10-un verilmiş ədədə qüvvətini qaytarır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Ədədin kvadrat kökünü qaytarır.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"arccos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"arcsin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"arctan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tg\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Ədədin arccosinusunu qaytarır.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Ədədin arcsinusunu qaytarır.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Ədədin arctanqensini qaytarır.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Dərəcənin kosinusunu qaytarır (radianın yox).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Dərəcənin sinusunu qaytar (radianın yox).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Dərəcənin tangensini qaytar (radianın yox).\";\nBlockly.Msg.NEW_VARIABLE = \"Yeni dəyişən...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Yeni dəyişənin adı:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"ilə:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Yaradılmış '%1' funksiyasını çalışdır.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Yaradılmış '%1' funksiyasını çalışdır və nəticəni istifadə et.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"'%1' yarat\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"hansısa əməliyyat\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"icra et:\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Nəticəsi olmayan funksiya yaradır.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"qaytar\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Nəticəsi olan funksiya yaradır.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Xəbərdarlıq: Bu funksiyanın təkrar olunmuş parametrləri var.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Funksiyanın təyinatını vurğula\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Əgər bir dəyər \\\"doğru\\\"-dursa onda ikinci dəyəri qaytar.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Xəbərdarlıq: Bu blok ancaq bir funksiyanın təyinatı daxilində işlədilə bilər.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"Giriş adı:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"girişlər\";\nBlockly.Msg.REMOVE_COMMENT = \"Şərhi sil\";\nBlockly.Msg.RENAME_VARIABLE = \"Dəyişənin adını dəyiş...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Bütün '%1' dəyişənlərinin adını buna dəyiş:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"bu mətni əlavə et:\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"bu mətnin sonuna:\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"'%1' dəyişəninin sonuna nəsə əlavə et.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"kiçik hərflərlə\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"Baş Hərflərlə\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"BÖYÜK HƏRFLƏRLƏ\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Mətndə hərflərin böyük-kiçikliyini dəyiş.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"birinci hərfi götür\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"axırdan bu nömrəli hərfi götür\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"bu nömrəli hərfi götür\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"növbəti mətndə\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"axırıncı hərfi götür\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"təsadüfi hərf götür\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Göstərilən mövqedəki hərfi qaytarır.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Mətnə bir element əlavə et.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"birləşdir\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Bu mətn blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"axırdan bu nömrəli hərfə qədər\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"bu nömrəli hərfə qədər\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"son hərfə qədər\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"mətndə\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"Mətnin surətini ilk hərfdən\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"Mətnin surətini sondan bu nömrəli # hərfdən\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"Mətnin surətini bu nömrəli hərfdən\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Mətnin təyin olunmuş hissəsini qaytarır.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"mətndə\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"Bu mətn ilə ilk rastlaşmanı tap:\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"Bu mətn ilə son rastlaşmanı tap:\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Birinci mətnin ikinci mətndə ilk/son rastlaşma indeksini qaytarır. Əgər rastlaşma baş verməzsə, 0 qaytarır.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 boşdur\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Verilmiş mətn boşdursa, doğru qiymətini qaytarır.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"Verilmişlərlə mətn yarat\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"İxtiyari sayda elementlərinin birləşməsi ilə mətn parçası yarat.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"%1 - ın uzunluğu\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Verilmiş mətndəki hərflərin(sözlər arası boşluqlar sayılmaqla) sayını qaytarır.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"%1 - i çap elə\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Təyin olunmuş mətn, ədəd və ya hər hansı bir başqa elementi çap elə.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"İstifadəçiyə ədəd daxil etməsi üçün sorğu/tələb göndərin.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"İstifadəçiyə mətn daxil etməsi üçün sorğu/tələb göndərin.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"İstifadəçiyə ədəd daxil etməsi üçün sorğunu/tələbi ismarıc kimi göndərin\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"İstifadəçiyə mətn daxil etməsi üçün sorğunu/tələbi ismarıc ilə göndərin\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Mətndəki hərf, söz və ya sətir.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"Boşluqları hər iki tərəfdən pozun\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"Boşluqlari yalnız sol tərəfdən pozun\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"Boşluqları yalnız sağ tərəfdən pozun\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Mətnin hər iki və ya yalnız bir tərəfdən olan boşluqları pozulmuş surətini qaytarın.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"'%1 - i təyin et' - i yarat\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Bu dəyişənin qiymətini qaytarır.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"'%1 - i götür' - ü yarat\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"- i bu qiymət ilə təyin et:\";\nBlockly.Msg.VARIABLES_SET_TITLE = \" \";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Bu dəyişəni daxil edilmiş qiymətə bərabər edir.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/az.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.az');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Şərh əlavə et\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Qiyməti dəyiş:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Blokları yığ\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Bloku yığ\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"rəng 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"rəng 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"nisbət\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"qarışdır\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"İki rəngi verilmiş nisbətdə (0,0 - 1,0) qarışdırır.\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";  // untranslated\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Palitradan bir rəng seçin.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"təsadüfi rəng\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Təsadüfi bir rəng seçin.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"mavi\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"yaşıl\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"qırmızı\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"rəngin komponentləri:\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Qırmızı, yaşıl və mavinin göstərilən miqdarı ilə bir rəng düzəlt. Bütün qiymətlər 0 ilə 100 arasında olmalıdır.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"dövrdən çıx\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"dövrün növbəti addımından davam et\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Cari dövrdən çıx.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Bu dövrün qalanını ötür və növbəti addımla davam et.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Xəbərdarlıq: Bu blok ancaq dövr daxilində istifadə oluna bilər.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"siyahıda\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"hər element üçün\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Siyahıdakı hər element üçün \\\"%1\\\" dəyişənini elementə mənimsət və bundan sonra bəzi əmrləri yerinə yetir.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"%1 ilə başlayıb, %2 qiymətinə kimi %3 qədər dəyiş\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"say:\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"%1 dəyişəni başlanğıc ədəddən son ədədə qədər göstərilən aralıqla qiymətlər aldıqca göstərilən blokları yerinə yetir.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"\\\"Əgər\\\" blokuna bir şərt əlavə et.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"\\\"Əgər\\\" blokuna qalan bütün halları əhatə edəb son bir şərt əlavə et.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Bu \\\"əgər\\\" blokunu dəyişdirmək üçün bölümlərin yenisini əlavə et, sil və ya yerini dəyiş.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"əks halda\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"əks halda əgər\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"əgər\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Əgər qiymət doğrudursa, onda bəzi əmrləri yerinə yetir.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Əgər qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda isə ikinci əmrlər blokunu yerinə yetir.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir. Əgər qiymətlərdən heç biri doğru deyilsə, onda axırıncı əmrlər blokunu yerinə yetir.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";  // untranslated\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"icra et\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1 dəfə təkrar et\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"təkrar et\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"dəfə\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Bəzi əmrləri bir neçə dəfə yerinə yetir.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"təkrar et, ta ki\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"təkrar et, hələ ki\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Hələ ki, qiymət \\\"yalan\\\"dır, bəzi əmrləri yerinə yetir.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Hələ ki, qiymət \\\"doğru\\\"dur, bəzi əmrləri yerinə yetir.\";\nBlockly.Msg.DELETE_BLOCK = \"Bloku sil\";\nBlockly.Msg.DELETE_X_BLOCKS = \"%1 bloku sil\";\nBlockly.Msg.DISABLE_BLOCK = \"Bloku söndür\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Dublikat\";\nBlockly.Msg.ENABLE_BLOCK = \"Bloku aktivləşdir\";\nBlockly.Msg.EXPAND_ALL = \"Blokları aç\";\nBlockly.Msg.EXPAND_BLOCK = \"Bloku aç\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Xarici girişlər\";\nBlockly.Msg.HELP = \"Kömək\";\nBlockly.Msg.INLINE_INPUTS = \"Sətiriçi girişlər\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"boş siyahı düzəlt\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Heç bir verilən qeyd olunmamış, uzunluğu 0 olan bir siyahı verir\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"siyahı\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Bu siyahı blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"bunlardan siyahı düzəlt\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Siyahıya element əlavə edin.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"İstənilən ölçülü siyahı yaradın.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"birinci\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"axırdan # nömrəli\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"götür\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"götür və sil\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"axırıncı\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"təsadüfi\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"yığışdır\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Siyahının ilk elementini qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Siyahıdan təyin olunmuş indeksli elementi qaytarır. #1 son elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Siyahıdan təyin olunmuş indeksli elementi qaytarır. #1 ilk elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Siyahının son elementini qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Siyahıdan hər hansı təsadüfi elementi qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Siyahıdan ilk elementi silir və qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Siyahıdan təyin olunmuş indeksli elementi silir və qaytarır. #1 son elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Siyahıdan təyin olunmuş indeksli elementi silir və qaytarır. #1 ilk elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Siyahıdan son elementi silir və qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Siyahıdan təsadufi elementi silir və qaytarır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Siyahıdan ilk elementi silir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Siyahıdan təyin olunmuş indeksli elementi silir. #1 son elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Siyahıdan təyin olunmuş indeksli elementi silir. #1 ilk elementdir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Siyahıdan son elementi silir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Siyahıdan təsadüfi bir elementi silir.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"sondan # nömrəliyə\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"# nömrəliyə\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"Sonuncuya\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"Birincidən alt-siyahını alın\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"# sonuncudan alt-siyahını alın\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"# - dən alt-siyahını alın\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Siyahının təyin olunmuş hissəsinin surətini yaradın.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"Element ilə ilk rastlaşma indeksini müəyyən edin\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"Element ilə son rastlaşma indeksini müəyyən edin\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Siyahıda element ilə ilk/son rastlaşma indeksini qaytarır. Əgər tekst siyahıda tapılmazsa, 0 qaytarılır.\";\nBlockly.Msg.LISTS_INLIST = \"siyahıda\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 boşdur\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"%1 siyahısının uzunluğu\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Siyahının uzunluğunu verir.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"%1 elementinin %2 dəfə təkrarlandığı siyahı düzəlt\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Təyin olunmuş elementin/qiymətin təyin olunmuş sayda təkrarlandığı siyahını yaradır.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"Kimi\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"daxil et\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"təyin et\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Elementi siyahının əvvəlinə daxil edir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Elementi siyahıda göstərilən yerə daxil edir. #1 axırıncı elementdir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Elementi siyahıda göstərilən yerə daxil edir. #1 birinci elementdir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Elementi siyahının sonuna artırır.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Elementi siyahıda təsadüfi seçilmiş bir yerə atır.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Siyahıda birinci elementi təyin edir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Siyahının göstərilən yerdəki elementini təyin edir. #1 axırıncı elementdir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Siyahının göstərilən yerdəki elementini təyin edir. #1 birinci elementdir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Siyahının sonuncu elementini təyin edir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Siyahının təsadüfi seçilmiş bir elementini təyin edir.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Siyahı boşdursa \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"yalan\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"\\\"doğru\\\" və ya \\\"yalan\\\" cavanını qaytarır.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"doğru\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Girişlər bir birinə bərabərdirsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Birinci giriş ikincidən böyükdürsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Birinci giriş ikincidən böyük və ya bərarbərdirsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Birinci giriş ikincidən kiçikdirsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Birinci giriş ikincidən kiçik və ya bərarbərdirsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Girişlər bərabər deyillərsə \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"%1 deyil\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Giriş \\\"yalan\\\"-dursa \\\"doğru\\\" cavabını qaytarır. Giriş \\\"doğru\\\"-dursa \\\"yalan\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_NULL = \"boş\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Boş cavab qaytarır.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"və\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"və ya\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Hər iki giriş \\\"doğru\\\"-dursa \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Girişlərdən heç olmasa biri \\\"doğru\\\"-dursa \\\"doğru\\\" cavabını qaytarır.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"əgər yalandırsa\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"əgər doğrudursa\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"'Yoxla' əmrindəki şərtə nəzər yetirin. Əgər şərt \\\"doğru\\\"-dursa \\\"əgər doğru\\\", əks halda isə \\\"əgər yalan\\\" cavabını qaytarır.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://az.wikipedia.org/wiki/Hesab\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"İki ədədin cəmini qaytarır.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"İki ədədin nisbətini qaytarır.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"İki ədədin fərqini qaytarır.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"İki ədədin hasilini verir.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Birinci ədədin ikinci ədəd dərəcəsindən qüvvətini qaytarır.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";  // untranslated\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"buna:\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"dəyiş:\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"'%1' dəyişəninin üzərinə bir ədəd artır.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";  // untranslated\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Ümumi sabitlərdən birini qaytarır π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), və ya ∞ (sonsuzluq).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"%1 üçün ən aşağı %2, ən yuxarı %3 olmağı tələb et\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Bir ədədin verilmiş iki ədəd arasında olmasını tələb edir (sərhədlər də daxil olmaqla).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"bölünür\";\nBlockly.Msg.MATH_IS_EVEN = \"cütdür\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"mənfidir\";\nBlockly.Msg.MATH_IS_ODD = \"təkdir\";\nBlockly.Msg.MATH_IS_POSITIVE = \"müsətdir\";\nBlockly.Msg.MATH_IS_PRIME = \"sadədir\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Bir ədədin cüt, tək, sadə, tam, müsbət, mənfi olmasını və ya müəyyən bir ədədə bölünməsini yoxlayır. \\\"Doğru\\\" və ya \\\"yalan\\\" qiymətini qaytarır.\";\nBlockly.Msg.MATH_IS_WHOLE = \"tamdır\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";  // untranslated\nBlockly.Msg.MATH_MODULO_TITLE = \"%1 ÷ %2 bölməsinin qalığı\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"İki ədədin nisbətindən alınan qalığı qaytarır.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";  // untranslated\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Ədəd.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"siyahının ədədi ortası\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"siyahının maksimumu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"siyahının medianı\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"siyahının minimumu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"Siyahı modları( Ən çox rastlaşılan elementləri)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"siyahıdan təsadüfi seçilmiş bir element\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"Siyahının standart deviasiyası\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"Siyahının cəmi\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Siyahıdaki ədədlərin ədədi ortasını qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Siyahıdaki ən böyük elementi qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Siyahının median elementini qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Siyahıdaki ən kiçik ədədi qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Siyahıdaki ən çox rastlanan element(lər)dən ibarət siyahı qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Siyahıdan təsadüfi bir element qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Siyahının standart deviasiyasını qaytarır.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Siyahıdakı bütün ədədlərin cəmini qaytarır.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"təsadüfi kəsr\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"0.0 (daxil olmaqla) və 1.0 (daxil olmamaqla) ədədlərinin arasından təsadüfi bir kəsr ədəd qaytarır.\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"%1 ilə %2 arasından təsadüfi tam ədəd\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Verilmiş iki ədəd arasından (ədədrlər də daxil olmaqla) təsadüfi bir tam ədəd qaytarır.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"yuvarlaqlaşdır\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"aşağı yuvarlaqlaşdır\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"yuxarı yuvarlaqlaşdır\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Ədədi aşağı və ya yuxari yuvarlaqşdır.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";  // untranslated\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"modul\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"kvadrat kök\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Ədədin modulunu qaytarır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"e sabitinin verilmiş ədədə qüvvətini qaytarır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Ədədin natural loqarifmini tapır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Ədədin 10-cu dərəcədən loqarifmini tapır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Ədədin əksini qaytarır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"10-un verilmiş ədədə qüvvətini qaytarır.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Ədədin kvadrat kökünü qaytarır.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"arccos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"arcsin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"arctan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";  // untranslated\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tg\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Ədədin arccosinusunu qaytarır.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Ədədin arcsinusunu qaytarır.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Ədədin arctanqensini qaytarır.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Dərəcənin kosinusunu qaytarır (radianın yox).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Dərəcənin sinusunu qaytar (radianın yox).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Dərəcənin tangensini qaytar (radianın yox).\";\nBlockly.Msg.NEW_VARIABLE = \"Yeni dəyişən...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Yeni dəyişənin adı:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"ilə:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Yaradılmış '%1' funksiyasını çalışdır.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Yaradılmış '%1' funksiyasını çalışdır və nəticəni istifadə et.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"'%1' yarat\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"hansısa əməliyyat\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"icra et:\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Nəticəsi olmayan funksiya yaradır.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"qaytar\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Nəticəsi olan funksiya yaradır.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Xəbərdarlıq: Bu funksiyanın təkrar olunmuş parametrləri var.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Funksiyanın təyinatını vurğula\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Əgər bir dəyər \\\"doğru\\\"-dursa onda ikinci dəyəri qaytar.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Xəbərdarlıq: Bu blok ancaq bir funksiyanın təyinatı daxilində işlədilə bilər.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"Giriş adı:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"girişlər\";\nBlockly.Msg.REMOVE_COMMENT = \"Şərhi sil\";\nBlockly.Msg.RENAME_VARIABLE = \"Dəyişənin adını dəyiş...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Bütün '%1' dəyişənlərinin adını buna dəyiş:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"bu mətni əlavə et:\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"bu mətnin sonuna:\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"'%1' dəyişəninin sonuna nəsə əlavə et.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"kiçik hərflərlə\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"Baş Hərflərlə\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"BÖYÜK HƏRFLƏRLƏ\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Mətndə hərflərin böyük-kiçikliyini dəyiş.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"birinci hərfi götür\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"axırdan bu nömrəli hərfi götür\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"bu nömrəli hərfi götür\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"növbəti mətndə\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"axırıncı hərfi götür\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"təsadüfi hərf götür\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Göstərilən mövqedəki hərfi qaytarır.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Mətnə bir element əlavə et.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"birləşdir\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Bu mətn blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"axırdan bu nömrəli hərfə qədər\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"bu nömrəli hərfə qədər\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"son hərfə qədər\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"mətndə\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"Mətnin surətini ilk hərfdən\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"Mətnin surətini sondan bu nömrəli # hərfdən\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"Mətnin surətini bu nömrəli hərfdən\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Mətnin təyin olunmuş hissəsini qaytarır.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"mətndə\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"Bu mətn ilə ilk rastlaşmanı tap:\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"Bu mətn ilə son rastlaşmanı tap:\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Birinci mətnin ikinci mətndə ilk/son rastlaşma indeksini qaytarır. Əgər rastlaşma baş verməzsə, 0 qaytarır.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 boşdur\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Verilmiş mətn boşdursa, doğru qiymətini qaytarır.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"Verilmişlərlə mətn yarat\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"İxtiyari sayda elementlərinin birləşməsi ilə mətn parçası yarat.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"%1 - ın uzunluğu\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Verilmiş mətndəki hərflərin(sözlər arası boşluqlar sayılmaqla) sayını qaytarır.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"%1 - i çap elə\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Təyin olunmuş mətn, ədəd və ya hər hansı bir başqa elementi çap elə.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"İstifadəçiyə ədəd daxil etməsi üçün sorğu/tələb göndərin.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"İstifadəçiyə mətn daxil etməsi üçün sorğu/tələb göndərin.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"İstifadəçiyə ədəd daxil etməsi üçün sorğunu/tələbi ismarıc kimi göndərin\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"İstifadəçiyə mətn daxil etməsi üçün sorğunu/tələbi ismarıc ilə göndərin\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";  // untranslated\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Mətndəki hərf, söz və ya sətir.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"Boşluqları hər iki tərəfdən pozun\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"Boşluqlari yalnız sol tərəfdən pozun\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"Boşluqları yalnız sağ tərəfdən pozun\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Mətnin hər iki və ya yalnız bir tərəfdən olan boşluqları pozulmuş surətini qaytarın.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"'%1 - i təyin et' - i yarat\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Bu dəyişənin qiymətini qaytarır.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"'%1 - i götür' - ü yarat\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"- i bu qiymət ilə təyin et:\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Bu dəyişəni daxil edilmiş qiymətə bərabər edir.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/be-tarask.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.be-tarask');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Дадаць камэнтар\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Зьмяніць значэньне:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Згарнуць блёкі\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Згарнуць блёк\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"колер 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"колер 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"дзеля\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"зьмяшаць\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Зьмешвае два колеры ў дадзенай прапорцыі (0.0 — 1.0)\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://be-x-old.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BB%D0%B5%D1%80\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Абярыце колер з палітры.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"выпадковы колер\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Абраць выпадковы колер.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"сіняга\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"зялёнага\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"чырвонага\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"колер з\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Стварыць колер з абранымі прапорцыямі чырвонага, зялёнага і сіняга. Усе значэньні павінны быць ад 0 да 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"перарваць цыкль\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"працягнуць з наступнага кроку цыклю\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Спыніць гэты цыкль.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Прапусьціць рэшту цыклю і перайсьці да наступнага кроку.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Увага: гэты блёк можа быць выкарыстаны толькі ў цыклі.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"у сьпісе\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"для кожнага элемэнта\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"For each item in a list, set the variable '%1' to the item, and then do some statements.\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"ад %1 да %2 па %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"лічыць з\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Дадаць умову да блёку «калі».\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Дадаць заключную ўмову для ўсіх астатніх варыянтаў блёку «калі».\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Дадаць, выдаліць ці пераставіць сэкцыі для пераканфігураваньня гэтага блёку «калі».\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"інакш\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"інакш, калі\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"калі\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Калі значэньне ісьціна, выканаць пэўныя апэрацыі.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Калі значэньне ісьціна, выканаць першы блёк апэрацыяў, інакш выканаць другі блёк.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Калі першае значэньне ісьціна, выканаць першы блёк апэрацыяў. Інакш, калі другое значэньне ісьціна, выканаць другі блёк апэрацыяў.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Калі першае значэньне ісьціна, выканаць першы блёк апэрацыяў. Інакш, калі другое значэньне ісьціна, выканаць другі блёк апэрацыяў. Калі ніводнае з значэньняў не сапраўднае, выканаць апошні блёк апэрацыяў.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"выканаць\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"паўтарыць %1 раз(ы)\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"паўтарыць\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"раз(ы)\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Выконвае апэрацыі некалькі разоў.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"паўтараць, пакуль не\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"паўтараць, пакуль\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Пакуль значэньне хлусьня, выконваць пэўныя апэрацыі.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Пакуль значэньне ісьціна, выконваць пэўныя апэрацыі.\";\nBlockly.Msg.DELETE_BLOCK = \"Выдаліць блёк\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Выдаліць %1 блёкі\";\nBlockly.Msg.DISABLE_BLOCK = \"Адключыць блёк\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Капіяваць\";\nBlockly.Msg.ENABLE_BLOCK = \"Адключыць блёкі\";\nBlockly.Msg.EXPAND_ALL = \"Разгарнуць блёкі\";\nBlockly.Msg.EXPAND_BLOCK = \"Разгарнуць блёк\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Зьнешнія ўваходы\";\nBlockly.Msg.HELP = \"Дапамога\";\nBlockly.Msg.INLINE_INPUTS = \"Унутраныя ўваходы\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"create empty list\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returns a list, of length 0, containing no data records\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"list\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this list block.\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"create list with\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Add an item to the list.\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Create a list with any number of items.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"first\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# from end\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"get\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"get and remove\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"last\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"random\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"remove\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returns the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returns the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returns a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Removes and returns the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Removes and returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Removes and returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Removes and returns the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Removes and returns a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Removes the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Removes the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Removes the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Removes the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Removes a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"to # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"to #\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"to last\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"get sub-list from first\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"get sub-list from # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"get sub-list from #\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Creates a copy of the specified portion of a list.\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"find first occurrence of item\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"find last occurrence of item\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.LISTS_INLIST = \"in list\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 is empty\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"length of %1\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returns the length of a list.\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"create list with item %1 repeated %2 times\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Creates a list consisting of the given value repeated the specified number of times.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"as\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"insert at\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_SET = \"set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserts the item at the start of a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserts the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserts the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Append the item to the end of a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserts the item randomly in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Sets the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Sets the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Sets the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Sets the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Sets a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_TOOLTIP = \"Returns true if the list is empty.\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"хлусьня\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Вяртае «ісьціна» ці «хлусьня».\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"ісьціна\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://be-x-old.wikipedia.org/wiki/%D0%9D%D1%8F%D1%80%D0%BE%D1%9E%D0%BD%D0%B0%D1%81%D1%8C%D1%86%D1%8C\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Вяртае «ісьціна», калі абодва ўводы роўныя.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Вяртае «ісьціна», калі першы ўвод большы за другі.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Вяртае «ісьціна», калі першы ўвод большы ці роўны другому.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Вяртае «ісьціна», калі першы ўвод меншы за другі.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Вяртае «ісьціна», калі першы ўвод меншы ці роўны другому.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Вяртае «ісьціна», калі абодва ўводы ня роўныя.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"не %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Вяртае «ісьціна», калі ўвод непраўдзівы. Вяртае «хлусьня», калі ўвод праўдзівы.\";\nBlockly.Msg.LOGIC_NULL = \"нічога\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Вяртае нічога.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"і\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"ці\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Вяртае «ісьціна», калі абодва ўводы праўдзівыя.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Вяртае «ісьціна», калі прынамсі адзін з уводаў праўдзівы.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"тэст\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"калі хлусьня\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"калі ісьціна\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Праверыць умову ў 'тэст'. Калі ўмова праўдзівая, будзе вернутае значэньне «калі ісьціна»; інакш будзе вернутае «калі хлусьня».\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://be-x-old.wikipedia.org/wiki/%D0%90%D1%80%D1%8B%D1%82%D0%BC%D1%8D%D1%82%D1%8B%D0%BA%D0%B0\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Вяртае суму двух лікаў.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Вяртае дзель двух лікаў.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Вяртае рознасьць двух лікаў.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Вяртае здабытак двух лікаў.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Вяртае першы лік у ступені другога ліку.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";  // untranslated\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"by\";  // untranslated\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"change\";  // untranslated\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Add a number to variable '%1'.\";  // untranslated\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://be-x-old.wikipedia.org/wiki/%D0%9C%D0%B0%D1%82%D1%8D%D0%BC%D0%B0%D1%82%D1%8B%D1%87%D0%BD%D0%B0%D1%8F_%D0%BA%D0%B0%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B0\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";  // untranslated\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"is divisible by\";  // untranslated\nBlockly.Msg.MATH_IS_EVEN = \"is even\";  // untranslated\nBlockly.Msg.MATH_IS_NEGATIVE = \"is negative\";  // untranslated\nBlockly.Msg.MATH_IS_ODD = \"is odd\";  // untranslated\nBlockly.Msg.MATH_IS_POSITIVE = \"is positive\";  // untranslated\nBlockly.Msg.MATH_IS_PRIME = \"is prime\";  // untranslated\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";  // untranslated\nBlockly.Msg.MATH_IS_WHOLE = \"is whole\";  // untranslated\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";  // untranslated\nBlockly.Msg.MATH_MODULO_TITLE = \"remainder of %1 ÷ %2\";  // untranslated\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Return the remainder from dividing the two numbers.\";  // untranslated\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://be-x-old.wikipedia.org/wiki/%D0%9B%D1%96%D0%BA\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Лік.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"average of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"max of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"median of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"min of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modes of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"random item of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standard deviation of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"sum of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Return the average (arithmetic mean) of the numeric values in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Return the largest number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Return the median number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Return the smallest number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Return a list of the most common item(s) in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Return a random element from the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Return the standard deviation of the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Return the sum of all the numbers in the list.\";  // untranslated\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"random fraction\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"random integer from %1 to %2\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Return a random integer between the two specified limits, inclusive.\";  // untranslated\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"round\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"round down\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"round up\";  // untranslated\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Round a number up or down.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://be-x-old.wikipedia.org/wiki/%D0%9A%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D1%8B_%D0%BA%D0%BE%D1%80%D0%B0%D0%BD%D1%8C\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"модуль\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"квадратны корань\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Вяртае модуль ліку.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Вяртае e ў ступені ліку.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Вяртае натуральны лягарытм ліку.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Вяртае дзесятковы лягарытм ліку.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Вяртае супрацьлеглы лік.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Вяртае 10 у ступені ліку.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Вяртае квадратны корань ліку.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://be-x-old.wikipedia.org/wiki/%D0%A2%D1%80%D1%8B%D0%B3%D0%B0%D0%BD%D0%B0%D0%BC%D1%8D%D1%82%D1%80%D1%8B%D1%8F#.D0.A2.D1.80.D1.8B.D0.B3.D0.B0.D0.BD.D0.B0.D0.BC.D1.8D.D1.82.D1.80.D1.8B.D1.87.D0.BD.D1.8B.D1.8F_.D1.84.D1.83.D0.BD.D0.BA.D1.86.D1.8B.D1.96\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Вяртае арккосынус ліку.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Вяртае арксынус ліку.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Вяртае арктангэнс ліку.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Вяртае косынус кута ў градусах.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Вяртае сынус кута ў градусах.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Вяртае тангэнс кута ў градусах.\";\nBlockly.Msg.NEW_VARIABLE = \"Новая зьменная…\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Імя новай зьменнай:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"with:\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Run the user-defined function '%1'.\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Run the user-defined function '%1' and use its output.\";  // untranslated\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Create '%1'\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"do something\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"to\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Creates a function with no output.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"return\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Creates a function with an output.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Warning: This function has duplicate parameters.\";  // untranslated\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Highlight function definition\";  // untranslated\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"If a value is true, then return a second value.\";  // untranslated\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Warning: This block may be used only within a function definition.\";  // untranslated\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"input name:\";  // untranslated\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"inputs\";  // untranslated\nBlockly.Msg.REMOVE_COMMENT = \"Выдаліць камэнтар\";\nBlockly.Msg.RENAME_VARIABLE = \"Перайменаваць зьменную…\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Перайменаваць усе назвы зьменных '%1' на:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"append text\";  // untranslated\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"to\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Append some text to variable '%1'.\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"to lower case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"to Title Case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"to UPPER CASE\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FIRST = \"get first letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"get letter # from end\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"get letter #\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"in text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_LAST = \"get last letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"get random letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returns the letter at the specified position.\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Add an item to the text.\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"join\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"to letter # from end\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"to letter #\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"to last letter\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"in text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"get substring from first letter\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"get substring from letter # from end\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"get substring from letter #\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"in text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"find first occurrence of text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"find last occurrence of text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 is empty\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returns true if the provided text is empty.\";  // untranslated\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"create text with\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Create a piece of text by joining together any number of items.\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"length of %1\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returns the number of letters (including spaces) in the provided text.\";  // untranslated\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"print %1\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Print the specified text, number or other value.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Prompt for user for a number.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Prompt for user for some text.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"prompt for number with message\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"prompt for text with message\";  // untranslated\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";  // untranslated\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"A letter, word, or line of text.\";  // untranslated\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"trim spaces from both sides of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"trim spaces from left side of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"trim spaces from right side of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Return a copy of the text with spaces removed from one or both ends.\";  // untranslated\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"аб’ект\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Create 'set %1'\";  // untranslated\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returns the value of this variable.\";  // untranslated\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create 'get %1'\";  // untranslated\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"to\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Sets this variable to be equal to the input.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/br.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.br');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Ouzhpennañ un evezhiadenn\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Kemmañ an talvoudenn :\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Collapse Blocks\";  // untranslated\nBlockly.Msg.COLLAPSE_BLOCK = \"Collapse Block\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"liv 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"liv 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"feur\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"meskañ\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"a gemmesk daou liv gant ur feur roet(0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"http://br.wikipedia.org/wiki/Liv\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Dibab ul liv diwar al livaoueg.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"liv dre zegouezh\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Tennañ ul liv d'ar sord\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"glas\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"gwer\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"ruz\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"liv gant\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Krouiñ ul liv gant ar c'hementad spisaet a ruz, a wer hag a c'hlas. Etre 0 ha 100 e tle bezañ an holl dalvoudoù.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"Mont e-maez an adlañsañ\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continue with next iteration of loop\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Break out of the containing loop.\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Skip the rest of this loop, and continue with the next iteration.\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Diwallit : ne c'hall ar bloc'h-mañ bezañ implijet nemet e-barzh ur boukl.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"er roll\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"evit pep elfenn\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Evit pep elfenn en ur roll, reiñ talvoud an elfenn d'an argemmenn '%1', ha seveniñ urzhioù zo da c'houde.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"eus %1 da %2 dre %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"kontañ gant\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Ouzhpennañ un amplegad d'ar bloc'h ma.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Add a final, catch-all condition to the if block.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h ma.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"a-hend-all\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"mod all ma\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"ma\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"If a value is true, then do some statements.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"If a value is true, then do the first block of statements.  Otherwise, do the second block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.  If none of the values are true, do the last block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"ober\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"adober %1 gwech\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"adober\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"gwech\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Seveniñ uzhioù zo meur a wech\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"adober betek\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"adober keit ha ma\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"While a value is false, then do some statements.\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"While a value is true, then do some statements.\";  // untranslated\nBlockly.Msg.DELETE_BLOCK = \"Dilemel ar bloc'h\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Dilemel %1 bloc'h\";\nBlockly.Msg.DISABLE_BLOCK = \"Diweredekaat ar bloc'h\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Eiladuriñ\";\nBlockly.Msg.ENABLE_BLOCK = \"Gweredekaat ar bloc'h\";\nBlockly.Msg.EXPAND_ALL = \"AStenn ar bloc'hoù\";\nBlockly.Msg.EXPAND_BLOCK = \"Astenn ar bloc'h\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Monedoù diavaez\";\nBlockly.Msg.HELP = \"Skoazell\";\nBlockly.Msg.INLINE_INPUTS = \"Monedoù enlinenn\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"krouiñ ur roll goullo\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returns a list, of length 0, containing no data records\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"roll\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this list block.\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"krouiñ ur roll gant\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Ouzhpennañ un elfenn d'ar roll\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Create a list with any number of items.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"kentañ\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# adalek ar fin\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"tapout\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"tapout ha lemel\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"diwezhañ\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"dre zegouezh\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"lemel\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returns the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returns the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returns a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Removes and returns the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Removes and returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Removes and returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Removes and returns the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Removes and returns a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Removes the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Removes the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Removes the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Removes the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Removes a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"to # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"da #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"betek ar fin\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"get sub-list from first\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"get sub-list from # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"get sub-list from #\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Creates a copy of the specified portion of a list.\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"kavout reveziadenn gentañ un elfenn\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"kavout reveziadenn diwezhañ un elfenn\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.LISTS_INLIST = \"er roll\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 zo goullo\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"hirder %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returns the length of a list.\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"create list with item %1 repeated %2 times\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Creates a list consisting of the given value repeated the specified number of times.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"evel\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"ensoc'hañ evel\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"termeniñ\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserts the item at the start of a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserts the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserts the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Append the item to the end of a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserts the item randomly in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Sets the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Sets the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Sets the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Sets the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Sets a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_TOOLTIP = \"Returns true if the list is empty.\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"gaou\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Returns either true or false.\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"gwir\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Return true if both inputs equal each other.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Return true if the first input is greater than the second input.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Return true if the first input is greater than or equal to the second input.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Return true if the first input is smaller than the second input.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Return true if the first input is smaller than or equal to the second input.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Return true if both inputs are not equal to each other.\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"nann %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returns true if the input is false.  Returns false if the input is true.\";  // untranslated\nBlockly.Msg.LOGIC_NULL = \"null\";  // untranslated\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returns null.\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_AND = \"ha(g)\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"pe\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Return true if both inputs are true.\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Return true if at least one of the inputs is true.\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"amprouad\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"m'eo gaou\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"m'eo gwir\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\";  // untranslated\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://br.wikipedia.org/wiki/Aritmetik\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Return the sum of the two numbers.\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Return the quotient of the two numbers.\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Return the difference of the two numbers.\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Return the product of the two numbers.\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Return the first number raised to the power of the second number.\";  // untranslated\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";  // untranslated\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"gant\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"kemmañ\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Add a number to variable '%1'.\";  // untranslated\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";  // untranslated\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";  // untranslated\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"a zo rannadus dre\";\nBlockly.Msg.MATH_IS_EVEN = \"zo par\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"a zo negativel\";\nBlockly.Msg.MATH_IS_ODD = \"a zo ampar\";\nBlockly.Msg.MATH_IS_POSITIVE = \"a zo pozitivel\";\nBlockly.Msg.MATH_IS_PRIME = \"is prime\";  // untranslated\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";  // untranslated\nBlockly.Msg.MATH_IS_WHOLE = \"zo anterin\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";  // untranslated\nBlockly.Msg.MATH_MODULO_TITLE = \"rest eus %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Return the remainder from dividing the two numbers.\";  // untranslated\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://br.wikipedia.org/wiki/Niver\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Un niver.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"average of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"max of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"median of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"min of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modes of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"Elfennn eus al listenn tennet d'ar sord\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standard deviation of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"sum of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Return the average (arithmetic mean) of the numeric values in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Return the largest number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Return the median number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Return the smallest number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Return a list of the most common item(s) in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Return a random element from the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Return the standard deviation of the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Return the sum of all the numbers in the list.\";  // untranslated\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"random fraction\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"random integer from %1 to %2\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Return a random integer between the two specified limits, inclusive.\";  // untranslated\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"round\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"round down\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"round up\";  // untranslated\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Round a number up or down.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";  // untranslated\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolute\";  // untranslated\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"gwrizienn karrez\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Return the absolute value of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Return e to the power of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Return the natural logarithm of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Return the base 10 logarithm of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Return the negation of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Return 10 to the power of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Return the square root of a number.\";  // untranslated\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";  // untranslated\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Return the arccosine of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Return the arcsine of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Return the arctangent of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Return the cosine of a degree (not radian).\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Return the sine of a degree (not radian).\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Return the tangent of a degree (not radian).\";  // untranslated\nBlockly.Msg.NEW_VARIABLE = \"Argemmenn nevez...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Anv an argemmenn nevez :\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"gant :\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Run the user-defined function '%1'.\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Run the user-defined function '%1' and use its output.\";  // untranslated\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Krouiñ '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"ober un dra bennak\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"da\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Creates a function with no output.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"distreiñ\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Creates a function with an output.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Warning: This function has duplicate parameters.\";  // untranslated\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Highlight function definition\";  // untranslated\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"If a value is true, then return a second value.\";  // untranslated\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Warning: This block may be used only within a function definition.\";  // untranslated\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"input name:\";  // untranslated\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"inputs\";  // untranslated\nBlockly.Msg.REMOVE_COMMENT = \"Lemel an evezhiadenn kuit\";\nBlockly.Msg.RENAME_VARIABLE = \"Adenvel an argemmenn...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Adenvel an holl argemmennoù '%1' e :\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"ouzhpennañ an destenn\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"da\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Append some text to variable '%1'.\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"to lower case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"to Title Case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"to UPPER CASE\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FIRST = \"tapout al lizherenn gentañ\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"get letter # from end\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"get letter #\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"en destenn\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"tapout al lizherenn diwezhañ\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"get random letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returns the letter at the specified position.\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Add an item to the text.\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"join\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"to letter # from end\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"to letter #\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"d'al lizherenn diwezhañ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"en destenn\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"get substring from first letter\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"get substring from letter # from end\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"get substring from letter #\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"en destenn\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"find first occurrence of text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"find last occurrence of text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 a zo goullo\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returns true if the provided text is empty.\";  // untranslated\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"krouiñ un destenn gant\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Create a piece of text by joining together any number of items.\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"hirder %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returns the number of letters (including spaces) in the provided text.\";  // untranslated\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"moullañ %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Print the specified text, number or other value.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Prompt for user for a number.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Prompt for user for some text.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"prompt for number with message\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"prompt for text with message\";  // untranslated\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";  // untranslated\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Ul lizherenn, ur ger pe ul linennad testenn.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"trim spaces from both sides of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"trim spaces from left side of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"trim spaces from right side of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Return a copy of the text with spaces removed from one or both ends.\";  // untranslated\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"elfenn\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Create 'set %1'\";  // untranslated\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returns the value of this variable.\";  // untranslated\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create 'get %1'\";  // untranslated\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"da\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Sets this variable to be equal to the input.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/ca.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.ca');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Afegeix un comentari\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Canvia valor:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Contraure blocs\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Contraure bloc\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"color 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"color 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"proporció\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"barreja\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Barreja dos colors amb una proporció donada (0,0 - 1,0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://ca.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Escolliu un color de la paleta.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"color aleatori\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Escolliu un color a l'atzar.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blau\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"verd\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"vermell\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"color amb\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Crear un color amb les quantitats especificades de vermell, verd i blau. Tots els valors han de ser entre 0 i 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"sortir del bucle\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continuar amb la següent iteració del bucle\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Sortir del bucle interior.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Ometre la resta d'aquest bucle, i continuar amb la següent iteració.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Advertència: Aquest bloc només es pot utilitzar dins d'un bucle.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"en la llista\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"per a cada element\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Per a cada element en la llista, desar l'element dins la variable '%1', i llavors executar unes sentències.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"des de %1 fins a %2 en increments de %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"comptar amb\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Fer que la variable %1 prengui els valors des del nombre inicial fins al nombre final, incrementant a cada pas l'interval indicat, i executar els blocs especificats.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Afegeix una condició al bloc 'si'.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Afegeix una condició final, que recull qualsevol altra possibilitat, al bloc 'si'.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Afegeix, esborra o reordena seccions per reconfigurar aquest bloc 'si'.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"si no\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"si no, si\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"si\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Si un valor és cert, llavors executar unes sentències.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Si un valor és cert, llavors executar el primer bloc de sentències. En cas contrari, executar el segon bloc de sentències.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Si el primer valor és cert, llavors executar el primer bloc de sentències. En cas contrari, si el segon valor és cert, executar el segon bloc de sentències.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Si el primer valor és cert, llavors executar el primer bloc de sentències. En cas contrari, si el segon valor és cert, executar el segon bloc de sentències. Si cap dels valors és cert, executar l'últim bloc de sentències.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://ca.wikipedia.org/wiki/Bucle_For\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"fer\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"repetir %1 vegades\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"repetir\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"vegades\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Executar unes sentències diverses vegades.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"repetir fins que\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"repetir mentre\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Mentre un valor sigui fals, llavors executar unes sentències.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Mentre un valor sigui cert, llavors executar unes sentències.\";\nBlockly.Msg.DELETE_BLOCK = \"Esborra bloc\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Esborra %1 blocs\";\nBlockly.Msg.DISABLE_BLOCK = \"Desactiva bloc\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplica\";\nBlockly.Msg.ENABLE_BLOCK = \"Activa bloc\";\nBlockly.Msg.EXPAND_ALL = \"Expandir blocs\";\nBlockly.Msg.EXPAND_BLOCK = \"Expandir bloc\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Entrades externes\";\nBlockly.Msg.HELP = \"Ajuda\";\nBlockly.Msg.INLINE_INPUTS = \"Entrades en línia\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"crear llista buida\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Retorna una llista, de longitud 0, que no conté cap dada.\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"llista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Afegeix, esborra o reordena seccions per reconfigurar aquest bloc de llista.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"crear llista amb\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Afegeix un element a la llista.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Crea una llista amb qualsevol nombre d'elements.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"primer\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"núm.# des del final\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"recupera\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"recupera i esborra\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"últim\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"a l'atzar\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"esborra\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Retorna el primer element d'una llista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Retorna l'element de la posició especificada a la llista. #1 és l'últim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Retorna l'element de la posició especificada a la llista. #1 és el primer element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Retorna l'últim element d'una llista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Retorna un element a l'atzar d'una llista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Esborra i retorna el primer element d'una llista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Esborra i retorna l'element de la posició especificada de la llista. #1 és l'últim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Esborra i retorna l'element de la posició especificada de la llista. #1 és el primer element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Esborra i retorna l'últim element d'una llista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Esborra i retorna un element a l'atzar d'una llista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Esborra el primer element d'una llista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Esborra l'element de la posició especificada de la llista. #1 és l'últim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Esborra l'element de la posició especificada de la llista. #1 és el primer element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Esborra l'últim element d'una llista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Esborra un element a l'atzar d'una llista.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"fins # des del final\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"fins #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"fins l'últim\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"recupera sub-llista des del principi\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"recupera sub-llista des de # des del final\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"recupera sub-llista des de #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Crea una còpia de la part especificada d'una llista.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"buscar primera aparició d'un element\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"buscar última aparició d'un element\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Retorna l'índex de la primera/última aparició d'un element a la llista. Retorna 0 si no s'hi troba el text.\";\nBlockly.Msg.LISTS_INLIST = \"en la llista\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 és buida\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"longitud de %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Retorna la longitud d'una llista.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"crea llista amb element %1 repetit %2 vegades\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Crea una llista formada pel valor donat, repetit tantes vegades com s'indiqui.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"com\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"insereix a\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"modifica\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Insereix l'element al principi d'una llista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Insereix l'element a la posició especificada d'una llista. #1 és l'últim element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Insereix l'element a la posició especificada d'una llista. #1 és el primer element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Afegeix l'element al final d'una llista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Insereix l'element en una posició a l'atzar d'una llista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Modifica el primer element d'una llista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Modifica l'element de la posició especificada d'una llista. #1 és l'últim element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Modifica l'element de la posició especificada d'una llista. #1 és el primer element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Modifica l'últim element d'una llista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Modifica un element a l'atzar d'una llista.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Retorna cert si la llista és buida.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"fals\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Retorna o bé cert o bé fals.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"cert\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://ca.wikipedia.org/wiki/Inequaci%C3%B3\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Retorna cert si totes dues entrades són iguals.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Retorna cert si la primera entrada és més gran que la segona entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Retorna cert si la primera entrada és més gran o igual a la segona entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Retorna cert si la primera entrada és més petita que la segona entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Retorna cert si la primera entra és més petita o igual a la segona entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Retorna cert si totes dues entrades són diferents.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"no %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Retorna cert si l'entrada és falsa. Retorna fals si l'entrada és certa.\";\nBlockly.Msg.LOGIC_NULL = \"nul\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Retorna nul.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"i\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"o\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Retorna cer si totes dues entrades són certes.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Retorna cert si almenys una de les entrades és certa.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"condició\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"si és fals\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"si és cert\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Comprova la condició de 'condició'. Si la condició és certa, retorna el valor 'si és cert'; en cas contrari, retorna el valor 'si és fals'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://ca.wikipedia.org/wiki/Aritm%C3%A8tica\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Retorna la suma dels dos nombres.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Retorna el quocient dels dos nombres.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Retorna la diferència entre els dos nombres.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Retorna el producte del dos nombres.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Retorna el primer nombre elevat a la potència indicada pel segon nombre.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://ca.wikipedia.org/wiki/Suma\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"per\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"canvia\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Afegeix un nombre a la variable '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://ca.wikipedia.org/wiki/Constant_matem%C3%A0tica\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Retorna una de les constants més habituals: π (3,141…), e (2,718…), φ (1,618…), sqrt(2) (1,414…), sqrt(½) (0,707…), o ∞ (infinit).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"limitar %1 entre %2 i %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Limita un nombre per tal que estigui entre els límits especificats (inclosos).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"és divisible per\";\nBlockly.Msg.MATH_IS_EVEN = \"és parell\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"és negatiu\";\nBlockly.Msg.MATH_IS_ODD = \"és senar\";\nBlockly.Msg.MATH_IS_POSITIVE = \"és positiu\";\nBlockly.Msg.MATH_IS_PRIME = \"és primer\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Comprova si un nombre és parell, senar, enter, positium negatiu, o si és divisible per un cert nombre. Retorna cert o fals.\";\nBlockly.Msg.MATH_IS_WHOLE = \"és enter\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://ca.wikipedia.org/wiki/Residu_%28aritm%C3%A8tica%29\";\nBlockly.Msg.MATH_MODULO_TITLE = \"residu de %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Retorna el residu de dividir els dos nombres.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://ca.wikipedia.org/wiki/Nombre\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Un nombre.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"mitjana de llista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"màxim de llista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mediana de llista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"mínim de llista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"moda de llista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"element aleatori de llista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"desviació estàndard de llista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"suma de llista\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Retorna la mitjana (mitjana aritmètica) dels valors numèrics de la llista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Retorna el nombre més gran de la llista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Retorna la mediana de la llista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Retorna el nombre més petit de la llista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Retorna una llista dels elements que apareixen més vegades a la llista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Retorna un element aleatori de la lllista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Retorna la desviació estàndard de la llista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Retorna la suma de tots els nombres de la llista.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://ca.wikipedia.org/wiki/Generaci%C3%B3_de_nombres_aleatoris\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"fracció aleatòria\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Retorna una fracció aleatòria entre 0,0 (inclòs) i 1,0 (exclòs).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://ca.wikipedia.org/wiki/Generaci%C3%B3_de_nombres_aleatoris\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"nombre aleatori entre %1 i %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Retorna un nombre aleatori entre els dos límits especificats, inclosos.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://ca.wikipedia.org/wiki/Arrodoniment\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"arrodonir\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"arrodonir cap avall\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"arrodonir cap amunt\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Arrodonir un nombre cap amunt o cap avall.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://ca.wikipedia.org/wiki/Arrel_quadrada\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolut\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"arrel quadrada\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Retorna el valor absolut d'un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Retorna ''e'' elevat a la potència del nombre indicat.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Retorna el logaritme natural d'un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Retorna el logaritme en base 10 d'un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Retorna l'oposat d'un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Retorna 10 elevat a la potència del nombre indicat.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Retorna l'arrel quadrada d'un nombre.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://ca.wikipedia.org/wiki/Funci%C3%B3_trigonom%C3%A8trica\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Retorna l'arccosinus d'un nombre.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Retorna l'arcsinus d'un nombre.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Retorna l'arctangent d'un nombre.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Retorna el cosinus d'un grau (no radiant).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Retorna el sinus d'un grau (no radiant).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Retorna la tangent d'un grau (no radiant).\";\nBlockly.Msg.NEW_VARIABLE = \"Nova variable...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nou nom de variable:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"amb:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://ca.wikipedia.org/wiki/Procediment_%28Programació%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Executa la funció definida per usuari '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://ca.wikipedia.org/wiki/Procediment_%28Programació%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Executa la funció definida per l'usuari '%1' i utilitza la seva sortida.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Crear '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"fes alguna cosa\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"a\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Crea una funció sense sortida.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"retorna\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Crea una funció amb una sortida.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Advertència: Aquesta funció té paràmetres duplicats.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Iluminar la definició de la funció\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Si el valor és cert, llavors retorna un segon valor.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Advertència: Aquest bloc només es pot utilitzar dins de la definició d'una funció.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nom d'entrada:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"entrades\";\nBlockly.Msg.REMOVE_COMMENT = \"Elimina el comentari\";\nBlockly.Msg.RENAME_VARIABLE = \"Reanomena variable...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Reanomena totes les variables '%1' a:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"afegir text\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"a\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Afegir un text a la variable '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"a minúscules\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"a Text De Títol\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"a MAJÚSCULES\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Retorna una còpia del text amb diferents majúscules/minúscules.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"recupera la primera lletra\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"recupera la lletra núm.# des del final\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"recupera la lletra núm.#\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"en el text\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"recupera l'última lletra\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"recupera una lletra a l'atzar\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Recupera la lletra de la posició especificada.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Afegeix un element al text.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"unir\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Afegeix, esborrar o reordenar seccions per reconfigurar aquest bloc de text.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"fins a la lletra núm.# des del final\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"fins a la lletra núm.#\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"fins a l'última lletra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"en el text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"recupera subcadena des de la primera lletra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"recupera subcadena des de la lletra núm.# des del final\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"recupera subcadena des de la lletra núm.#\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Recupera una part especificada del text.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"en el text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"trobar la primera aparició del text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"trobar l'última aparició del text\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Retorna l'índex de la primera/última aparició del primer text dins el segon. Retorna 0 si no es troba el text.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 està buit\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Retorna cert si el text proporcionat està buit.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"crear text amb\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Crea un tros de text per unió de qualsevol nombre d'elements.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"llargària de %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Retorna el nombre de lletres (espais inclosos) en el text proporcionat.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"imprimir %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Imprimir el text, el nombre o altre valor especificat.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Demana que l'usuari introdueixi un nombre.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Demana que l'usuari introdueixi un text.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"demanar un nombre amb el missatge\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"demanar text amb el missatge\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://ca.wikipedia.org/wiki/Cadena_%28inform%C3%A0tica%29\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Una lletra, paraula o línia de text.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"retalla espais de tots dos extrems\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"retalla espais de l'esquerra\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"retalla espais de la dreta\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Retorna una còpia del text on s'han esborrat els espais d'un o dels dos extrems.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Crea 'modifica %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Retorna el valor d'aquesta variable.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Crear 'recupera %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"a\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"modifica\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Modifica aquesta variable al valor introduït.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/cs.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.cs');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Přidat komentář\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Změna hodnoty:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Skrýt bloky\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Skrýt blok\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"barva 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"barva 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"poměr\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"smíchat\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Smíchá dvě barvy v daném poměru (0.0–1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://cs.wikipedia.org/wiki/Barva\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Vyberte barvu z palety.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"náhodná barva\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Zvolte barvu náhodně.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"modrá\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"zelená\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"červená\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"barva s\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Vytvoř barvu se zadaným množstvím červené, zelené a modré.  Všechny hodnoty musí být mezi 0 a 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"vymanit se ze smyčky\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"pokračuj dalším opakováním smyčky\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Přeruš vnitřní smyčku.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Přeskoč zbytek této smyčky a pokračuj dalším opakováním.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Upozornění: Tento blok může být použit pouze uvnitř smyčky.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"v seznamu\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"pro každou položku\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Pro každou položku v seznamu nastavte do proměnné '%1' danou položku a proveďte nějaké operace.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"od %1 do %2 po %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"počítat s\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Nechá proměnnou %1 nabývat hodnot od počátečního do koncového čísla po daném přírůstku a provádí s ní příslušné bloky.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Přidat podmínku do \\\"pokud\\\" bloku.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Přidej konečnou podmínku zahrnující ostatní případy do bloku pokud.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Přidej, odstraň či uspořádej sekce k přenastavení tohoto bloku pokud.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"jinak\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"nebo pokud\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"pokud\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Je-li hodnota pravda, proveď určité příkazy.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Je-li hodnota pravda, proveď první blok příkazů.  V opačném případě proveď druhý blok příkazů.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Je-li první hodnota pravdivá, proveď první blok příkazů. V opačném případě, je-li pravdivá druhá hodnota, proveď druhý blok příkazů.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Je-li první hodnota pravda, proveď první blok příkazů.  Je-li druhá hodnota pravda, proveď druhý blok příkazů.  Pokud žádná hodnota není pravda, proveď poslední blok příkazů.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://cs.wikipedia.org/wiki/Cyklus_for\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"udělej\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"opakovat %1 krát\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"opakovat\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"krát\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Proveď určité příkazy několikrát.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"opakovat dokud\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"opakovat když\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Dokud je hodnota nepravdivá, prováděj určité příkazy.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Dokud je hodnota pravdivá, prováděj určité příkazy.\";\nBlockly.Msg.DELETE_BLOCK = \"Odstranit blok\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Odstranit %1 bloky\";\nBlockly.Msg.DISABLE_BLOCK = \"Zakázat blok\";\nBlockly.Msg.DUPLICATE_BLOCK = \"zdvojit\";\nBlockly.Msg.ENABLE_BLOCK = \"Povolit blok\";\nBlockly.Msg.EXPAND_ALL = \"Rozbalit bloky\";\nBlockly.Msg.EXPAND_BLOCK = \"Rozbalení bloku\";\nBlockly.Msg.EXTERNAL_INPUTS = \"vnější vstupy\";\nBlockly.Msg.HELP = \"Nápověda\";\nBlockly.Msg.INLINE_INPUTS = \"Vložené vstupy\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"vytvořit prázdný seznam\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Vrátí seznam nulové délky, který neobsahuje žádné datové záznamy\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"seznam\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Přidat, odebrat nebo změnit pořadí oddílů tohoto seznamu bloku.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"vytvořit seznam s\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Přidat položku do seznamu.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Vytvoř seznam s libovolným počtem položek.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"první\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# od konce\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"získat\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"získat a odstranit\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"poslední\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"náhodné\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"odstranit\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Vrátí první položku v seznamu.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Vrátí položku z určené pozice v seznamu.  #1 je poslední položka.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Vrátí položku z určené pozice v seznamu.  #1 je první položka.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Vrátí poslední položku v seznamu.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Vrátí náhodnou položku ze seznamu.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Odstraní a vrátí první položku v seznamu.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Odstraní a vrátí položku z určené pozice v seznamu.  #1 je poslední položka.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Odstraní a vrátí položku z určené pozice v seznamu.  #1 je první položka.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Odstraní a vrátí poslední položku v seznamu.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Odstraní a vrátí náhodnou položku v seznamu.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Odstraní první položku v seznamu.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Odstraní položku na konkrétním místu v seznamu. #1 je poslední položka.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Odebere položku na konkrétním místě v seznamu.  #1 je první položka.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Odstraní poslední položku v seznamu.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Odstraní náhodou položku v seznamu.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"do # od konce\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"do #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"jako poslední\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"získat podseznam od první položky\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"získat podseznam od # od konce\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"získat podseznam od #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Vytvoří kopii určené části seznamu.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"najít první výskyt položky\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"najít poslední výskyt položky\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.LISTS_INLIST = \"v seznamu\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 je prázdné\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"délka %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Vrací počet položek v seznamu.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"vytvoř seznam s položkou %1 opakovanou %1 krát\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Vytváří seznam obsahující danou hodnotu n-krát.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"jako\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"vložit na\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"nastavit\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Vložit položku na začátek seznamu.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Vloží položku na určenou pozici v seznamu.  #1 je poslední položka.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Vloží položku na určenou pozici v seznamu.  #1 je první položka.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Připojí položku na konec seznamu.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Připojí položku náhodně do seznamu.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Nastaví první položku v seznamu.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Nastaví položku na konkrétní místo v seznamu. #1 je poslední položka.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Nastaví položku na konkrétní místo v seznamu. #1 je první položka.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Nastaví poslední položku v seznamu.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Nastaví náhodnou položku v seznamu.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Returns true if the list is empty.\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"nepravda\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Vrací pravda nebo nepravda.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"pravda\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://cs.wikipedia.org/wiki/Nerovnost_(matematika)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Vrátí hodnotu pravda, pokud se oba vstupy rovnají jeden druhému.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Navrátí hodnotu pravda, pokud první vstup je větší než druhý vstup.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Navrátí hodnotu pravda, pokud je první vstup větší a nebo rovný druhému vstupu.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Navrátí hodnotu pravda, pokud je první vstup menší než druhý vstup.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Navrátí hodnotu pravda, pokud je první vstup menší a nebo rovný druhému vstupu.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Vrátí hodnotu pravda, pokud se oba vstupy nerovnají sobě navzájem.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"není %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Navrátí hodnotu pravda, pokud je vstup nepravda. Navrátí hodnotu nepravda, pokud je vstup pravda.\";\nBlockly.Msg.LOGIC_NULL = \"nula\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Vrátí nulovou hodnotu\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"a\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"nebo\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Vrátí hodnotu pravda, pokud oba dva vstupy jsou pravdivé.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Vrátí hodnotu pravda, pokud alespoň jeden ze vstupů má hodnotu pravda.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"je-li nepravda\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"je-li to pravda\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Zkontroluje podmínku v \\\"testu\\\". Když je podmínka pravda, vrátí hodnotu \\\"pokud pravda\\\"; v opačném případě vrátí hodnotu \\\"pokud nepravda\\\".\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://cs.wikipedia.org/wiki/Aritmetika\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Vrátí součet dvou čísel.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Vrátí podíl dvou čísel.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Vrátí rozdíl dvou čísel.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Vrátí součin dvou čísel.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Vrátí první číslo umocněné na druhé číslo.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"od\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"změnit\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Přičti číslo k proměnné '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Vraťte jednu z následujících konstant: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"omez %1 na rozmezí od %2 do %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Omezí číslo tak, aby bylo ve stanovených mezích (včetně).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"je dělitelné\";\nBlockly.Msg.MATH_IS_EVEN = \"je sudé\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"je záporné\";\nBlockly.Msg.MATH_IS_ODD = \"je liché\";\nBlockly.Msg.MATH_IS_POSITIVE = \"je kladné\";\nBlockly.Msg.MATH_IS_PRIME = \"je prvočíslo\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Kontrola, zda je číslo sudé, liché, prvočíslo, celé, kladné, záporné nebo zda je dělitelné daným číslem. Vrací pravdu nebo nepravdu.\";\nBlockly.Msg.MATH_IS_WHOLE = \"je celé\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://cs.wikipedia.org/wiki/Modul%C3%A1rn%C3%AD_aritmetika\";\nBlockly.Msg.MATH_MODULO_TITLE = \"zbytek po dělení %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Vrátí zbytek po dělení dvou čísel.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://cs.wikipedia.org/wiki/Číslo\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Číslo.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"průměr v seznamu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"největší v seznamu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"medián v seznamu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"nejmenší v seznamu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modes of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"náhodná položka seznamu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"směrodatná odchylka ze seznamu\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"suma seznamu\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Vrátí průměr (aritmetický průměr) číselných hodnot v seznamu.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Vrátí největší číslo v seznamu.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Vrátí medián seznamu.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Vrátí nejmenší číslo v seznamu.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Vrátí seznam nejčastějších položek seznamu.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Vrátí náhodnou položku ze seznamu.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Vrátí směrodatnou odchylku seznamu.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Vrátí součet všech čísel v seznamu.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://cs.wikipedia.org/wiki/Gener%C3%A1tor_n%C3%A1hodn%C3%BDch_%C4%8D%C3%ADsel\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"náhodné číslo mezi 0 (včetně) do 1\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Vrátí náhodné číslo mezi 0,0 (včetně) až 1,0\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://cs.wikipedia.org/wiki/Gener%C3%A1tor_n%C3%A1hodn%C3%BDch_%C4%8D%C3%ADsel\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"náhodné celé číslo od %1 do %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Vrací náhodné celé číslo mezi dvěma určenými mezemi, včetně mezních hodnot.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://cs.wikipedia.org/wiki/Zaokrouhlení\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"zaokrouhlit\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"zaokrouhlit dolu\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"zaokrouhlit nahoru\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Zaokrouhlit číslo nahoru nebo dolů.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://cs.wikipedia.org/wiki/Druhá_odmocnina\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolutní\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"druhá odmocnina\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Vrátí absolutní hodnotu čísla.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Vrátí mocninu čísla e.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Vrátí přirozený logaritmus čísla.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Vrátí desítkový logaritmus čísla.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Vrátí zápornou hodnotu čísla.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Vrátí mocninu čísla 10.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Vrátí druhou odmocninu čísla.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"arcsin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"arctan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://cs.wikipedia.org/wiki/Goniometrická_funkce\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Vrátí arckosinus čísla.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Vrátí arcsinus čísla.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Vrátí arctangens čísla.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Vrátí kosinus úhlu ve stupních.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Vrátí sinus úhlu ve stupních.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Vrátí tangens úhlu ve stupních.\";\nBlockly.Msg.NEW_VARIABLE = \"Nová proměnná...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nový název proměnné:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"s:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://cs.wikipedia.org/wiki/Funkce_(programov%C3%A1n%C3%AD)\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Spustí uživatelem definovanou funkci '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://cs.wikipedia.org/wiki/Funkce_(programov%C3%A1n%C3%AD)\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Spustí uživatelem definovanou funkci '%1' a použije její výstup.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Vytvořit '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"proveď něco\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"k provedení\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Vytvořit funkci bez výstupu.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"navrátit\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Vytvořit funkci s výstupem.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Upozornění: Tato funkce má duplicitní parametry.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Zvýraznit definici funkce\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Je-li hodnota pravda, pak vrátí druhou hodnotu.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Varování: Tento blok může být použit pouze uvnitř definici funkce.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"vstupní jméno:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"vstupy\";\nBlockly.Msg.REMOVE_COMMENT = \"Odstranit komentář\";\nBlockly.Msg.RENAME_VARIABLE = \"Přejmenovat proměnné...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Přejmenujte všechny proměnné '%1':\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"přidat text\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"do\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Přidá určitý text k proměnné '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"na malá písmena\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"na Počáteční Velká Písmena\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"na VELKÁ PÍSMENA\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Vrátí kopii textu s jinou velikostí písmen.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"získat první písmeno\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"získat # písmeno od konce\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"získat písmeno #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"v textu\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"získat poslední písmeno\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"získat náhodné písmeno\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Získat písmeno na konkrétní pozici.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Přidat položku do textu.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"spojit\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Přidat, odebrat nebo změnit pořadí oddílů tohoto textového bloku.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"do # písmene od konce\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"do písmene #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"do posledního písmene\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"v textu\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"získat podřetězec od prvního písmene\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"získat podřetězec od písmene # od konce\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"získat podřetězec od písmene #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Získat zadanou část textu.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"v textu\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"najít první výskyt textu\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"najít poslední výskyt textu\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Vrátí index prvního/posledního výskytu prvního textu v druhém textu.  Pokud text není nalezen, vrátí hodnotu 0.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 je prázdný\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Vrátí pravda pokud je zadaný text prázdný.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"vytvořit text s\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Vytvoří kousek textu spojením libovolného počtu položek.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"délka %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Vrátí počet písmen (včetně mezer) v zadaném textu.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"tisk %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Tisk zadaného textu, čísla nebo jiné hodnoty.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Výzva pro uživatele k zadání čísla.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Výzva pro uživatele k zadání nějakého textu.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"výzva k zadání čísla se zprávou\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"výzva k zadání textu se zprávou\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://cs.wikipedia.org/wiki/Textov%C3%BD_%C5%99et%C4%9Bzec\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Písmeno, slovo nebo řádek textu.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"odstranit mezery z obou stran\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"odstranit mezery z levé strany\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"odstranit mezery z pravé strany\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Vrátí kopii textu s odstraněnými mezerami z jednoho nebo obou konců.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"položka\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Vytvořit \\\"nastavit %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Vrátí hodnotu této proměnné.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Vytvořit \\\"získat %1\\\"\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"na\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"nastavit\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Nastaví tuto proměnnou, aby se rovnala vstupu.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/da.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.da');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Tilføj kommentar\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Ændr værdi:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Fold blokkene sammen\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Fold blokken sammen\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"farve 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"med farve 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"i forholdet\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"bland\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Blander to farver sammen i et bestemt forhold (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://da.wikipedia.org/wiki/Farve\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Vælg en farve fra paletten.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"tilfældig farve\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Vælg en tilfældig farve.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blå\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"grøn\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"rød\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"farve med\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Lav en farve med den angivne mængde af rød, grøn og blå. Alle værdier skal være mellem 0 og 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"bryd ud af løkken\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"fortsæt med den næste gentagelse i løkken\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Bryd ud af den omgivende løkke.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Spring resten af denne løkke over, og fortsæt med den næste gentagelse.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Advarsel: Denne blok kan kun bruges i en løkke.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"i listen\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"for hvert element\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"For hvert element i en liste, sæt variablen '%1' til elementet, og udfør derefter nogle kommandoer.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"fra %1 til %2 med %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"tæl med\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Få variablen %1 til at have værdierne fra startværdien til slutværdien, mens der tælles med det angivne interval, og udfør de angivne blokke.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Tilføj en betingelse til denne \\\"hvis\\\" blok.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Tilføj en sidste fang-alt betingelse, til denne \\\"hvis\\\" blok.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne \\\"hvis\\\" blok.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"ellers\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"ellers hvis\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"hvis\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Hvis en værdi er sand, så udfør nogle kommandoer.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Hvis en værdi er sand, så udfør den første blok af kommandoer. Ellers udfør den anden blok af kommandoer.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Hvis den første værdi er sand, så udfør den første blok af kommandoer.  Ellers, hvis den anden værdi er sand, så udfør den anden blok af kommandoer.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Hvis den første værdi er sand, så udfør den første blok af kommandoer. Ellers, hvis den anden værdi er sand, så udfør den anden blok af kommandoer. Hvis ingen af værdierne er sande, så udfør den sidste blok af kommandoer.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://da.wikipedia.org/wiki/For-l%C3%B8kke\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"udfør\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"gentag %1 gange\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"gentag\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"gange\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Udfør nogle kommandoer flere gange.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"gentag indtil\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"gentag sålænge\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Udfør nogle kommandoer, sålænge en værdi er falsk.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Udfør nogle kommandoer, sålænge en værdi er sand.\";\nBlockly.Msg.DELETE_BLOCK = \"Slet blok\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Slet %1 blokke\";\nBlockly.Msg.DISABLE_BLOCK = \"Deaktivér blok\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Kopiér\";\nBlockly.Msg.ENABLE_BLOCK = \"Aktivér blok\";\nBlockly.Msg.EXPAND_ALL = \"Fold blokkene ud\";\nBlockly.Msg.EXPAND_BLOCK = \"Fold blokken ud\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Udvendige inputs\";\nBlockly.Msg.HELP = \"Hjælp\";\nBlockly.Msg.INLINE_INPUTS = \"Indlejrede inputs\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"opret en tom liste\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returnerer en liste af længde 0, som ikke indeholder nogen data\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"liste\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne blok.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"opret liste med\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Føj et element til listen.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Opret en liste med et vilkårligt antal elementer.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"første\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# fra slutningen\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"hent\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"hent og fjern\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"sidste\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"tilfældig\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"fjern\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returnerer det første element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returnerer elementet på den angivne position på en liste. #1 er det sidste element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returnerer elementet på den angivne position på en liste. #1 er det første element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returnerer den sidste element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returnerer et tilfældigt element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Fjerner og returnerer det første element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Fjerner og returnerer elementet på den angivne position på en liste. #1 er det sidste element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Fjerner og returnerer elementet på den angivne position på en liste. #1 er det første element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Fjerner og returnerer det sidste element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Fjerner og returnerer et tilfældigt element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Fjerner det første element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Fjerner elementet på den angivne position på en liste. #1 er det sidste element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Fjerner elementet på den angivne position på en liste. #1 er det første element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Fjerner sidste element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Fjerner et tilfældigt element i en liste.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"til # fra slutningen\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"til #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"til sidste\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"hent underliste fra første\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"hent underliste fra # fra slutningen\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"hent underliste fra #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Opretter en kopi af den angivne del af en liste.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"find første forekomst af elementet\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"find sidste forekomst af elementet\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returnerer indeks for første/sidste forekomst af elementet i listen. Returnerer 0, hvis teksten ikke er fundet.\";\nBlockly.Msg.LISTS_INLIST = \"i listen\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 er tom\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"længden af %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returnerer længden af en liste.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"opret liste med elementet %1 gentaget %2 gange\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Opretter en liste bestående af den givne værdi gentaget et bestemt antal gange.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"som\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"sæt ind ved\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"sæt\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Indsætter elementet i starten af en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Indsætter elementet på den angivne position i en liste. #1 er det sidste element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Indsætter elementet på den angivne position i en liste. #1 er det første element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Føj elementet til slutningen af en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Indsætter elementet tilfældigt i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Sætter det første element i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Sætter elementet på den angivne position i en liste. #1 er det sidste element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Sætter elementet på den angivne position i en liste. #1 er det første element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Sætter det sidste element i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Sætter et tilfældigt element i en liste.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Returnerer sand, hvis listen er tom.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"falsk\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Returnerer enten sand eller falsk.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"sand\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://da.wikipedia.org/wiki/Ulighed_(matematik)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Returnere sand, hvis begge inputs er lig med hinanden.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Returnere sand, hvis det første input er større end det andet input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Returnere sand, hvis det første input er større end eller lig med det andet input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Returnere sand, hvis det første input er mindre end det andet input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Returnere sand, hvis det første input er mindre end eller lig med det andet input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Returnere sand, hvis begge inputs ikke er lig med hinanden.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"ikke %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returnerer sand, hvis input er falsk. Returnerer falsk, hvis input er sandt.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returnerer null.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"og\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"eller\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Returnere sand, hvis begge inputs er sande.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Returnere sand, hvis mindst et af inputtene er sande.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"hvis falsk\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"hvis sand\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Kontrollér betingelsen i 'test'. Hvis betingelsen er sand, returnér \\\"hvis sand\\\" værdien; ellers returnér \\\"hvis falsk\\\" værdien.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://da.wikipedia.org/wiki/Aritmetik\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Returnere summen af de to tal.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Returnere kvotienten af de to tal.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Returnere forskellen mellem de to tal.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Returnere produktet af de to tal.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Returnere det første tal opløftet til potensen af det andet tal.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"med\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"ændr\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Læg et tal til variablen '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://da.wikipedia.org/wiki/Matematisk_konstant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Returnere en af de ofte brugte konstanter: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(2) (1.414…), sqrt(½) (0.707…) eller ∞ (uendeligt).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"begræns %1 til mellem %2 og %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Begræns et tal til at være mellem de angivne grænser (inklusiv).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \":\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"er deleligt med\";\nBlockly.Msg.MATH_IS_EVEN = \"er lige\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"er negativt\";\nBlockly.Msg.MATH_IS_ODD = \"er ulige\";\nBlockly.Msg.MATH_IS_POSITIVE = \"er positivt\";\nBlockly.Msg.MATH_IS_PRIME = \"er et primtal\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Kontrollere, om et tal er lige, ulige, primtal, helt, positivt, negativt, eller om det er deleligt med bestemt tal. Returnere sandt eller falskt.\";\nBlockly.Msg.MATH_IS_WHOLE = \"er helt\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://da.wikipedia.org/wiki/Modulo\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resten af %1 : %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Returner resten fra at dividere de to tal.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://da.wikipedia.org/wiki/Tal\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Et tal.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"gennemsnit af listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"største tal i listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"listens median\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"mindste tal i listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"listens typetal\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"tilfældigt element fra listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standardafvigelsen for listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"summen af listen\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Returner gennemsnittet (middelværdien) af de numeriske værdier i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Returner det største tal i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Returner listens median.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Returner det mindste tal i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Returner en liste over de mest almindelige elementer på listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Returner et tilfældigt element fra listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Returner standardafvigelsen for listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Returner summen af alle tal i listen.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://da.wikipedia.org/wiki/Tilfældighedsgenerator\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"tilfældigt decimaltal (mellem 0 og 1)\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Returner et tilfældigt decimaltal mellem 0,0 (inklusiv) og 1,0 (eksklusiv).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://da.wikipedia.org/wiki/Tilfældighedsgenerator\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"tilfældigt heltal mellem %1 og %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Returner et tilfældigt heltal mellem de to angivne grænser (inklusiv).\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://da.wikipedia.org/wiki/Afrunding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"afrund\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"rund ned\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"rund op\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Runde et tal op eller ned.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://da.wikipedia.org/wiki/Kvadratrod\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolut\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"kvadratrod\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Returnere den absolutte værdi af et tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Returnere e til potensen af et tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Returnere den naturlige logaritme af et tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Returnere 10-talslogaritmen af et tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Returnere negationen af et tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Returnere 10 til potensen af et tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Returnere kvadratroden af et tal.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://da.wikipedia.org/wiki/Trigonometrisk_funktion\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Returnere arcus cosinus af et tal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Returnere arcus sinus af et tal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Returnere arcus tangens af et tal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Returnere cosinus af en vinkel (i grader).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Returnere sinus af en vinkel (i grader).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Returnere tangens af en vinkel (i grader).\";\nBlockly.Msg.NEW_VARIABLE = \"Ny variabel...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Navn til den nye variabel:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"med:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://da.wikipedia.org/wiki/Funktion_%28programmering%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Kør den brugerdefinerede funktion '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://da.wikipedia.org/wiki/Funktion_%28programmering%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Kør den brugerdefinerede funktion '%1' og brug dens output.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Opret '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"gøre noget\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"for at\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Opretter en funktion der ikke har output.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"returnér\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Opretter en funktion der har output.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Advarsel: Denne funktion har dublerede parametre.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Markér funktionsdefinitionen\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Hvis en værdi er sand, så returnér en anden værdi.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Advarsel: Denne blok kan kun anvendes inden for en funktionsdefinition.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"parameternavn:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"inputs\";\nBlockly.Msg.REMOVE_COMMENT = \"Fjern kommentar\";\nBlockly.Msg.RENAME_VARIABLE = \"Omdøb variabel...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Omdøb alle '%1' variabler til:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"tilføj tekst\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"til\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Tilføj noget tekst til variablen '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"til små bogstaver\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"til Stort Begyndelsesbogstav\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"til STORE BOGSTAVER\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Returner en kopi af teksten hvor bogstaverne enten er udelukkende store eller små, eller hvor første bogstav i hvert ord er stort.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"hent første bogstav\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"hent bogstav # fra slutningen\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"hent bogstav #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"i teksten\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"hent sidste bogstav\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"hent tilfældigt bogstav\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returnerer bogstavet på den angivne placering.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Føj et element til teksten.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"sammenføj\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne tekstblok.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"til bogstav # fra slutningen\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"til bogstav #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"til sidste bogstav\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"i teksten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"hent delstreng fra første bogstav\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"hent delstreng fra bogstav # fra slutningen\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"hent delstreng fra bogstav #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returnerer den angivne del af teksten.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"i teksten\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"find første forekomst af teksten\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"find sidste forekomst af teksten\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returnerer indeks for første/sidste forekomst af første tekst i den anden tekst.  Returnerer 0, hvis teksten ikke kan findes.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 er tom\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returnerer sand, hvis den angivne tekst er tom.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"lav en tekst med\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Lav et stykke tekst ved at sætte et antal elementer sammen.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"længden af %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returnerer antallet af bogstaver (herunder mellemrum) i den angivne tekst.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"skriv %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Skriv den angivne tekst, tal eller anden værdi.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Spørg brugeren efter et tal\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Spørg brugeren efter en tekst\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"spørg efter et tal med meddelelsen\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"spørg efter tekst med meddelelsen\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://da.wikipedia.org/wiki/Tekststreng\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"En bogstav, et ord eller en linje med tekst.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"fjern mellemrum fra begge sider af\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"fjern mellemrum fra venstre side af\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"fjern mellemrum fra højre side af\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Returner en kopi af teksten med mellemrum fjernet fra den ene eller begge sider.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Opret 'sæt %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returnerer værdien af denne variabel.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Opret 'hent %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"til\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"sæt\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Sætter denne variabel til at være lig med input.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/de.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.de');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Kommentar hinzufügen\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Wert ändern:\";\nBlockly.Msg.CHAT = \"Chatte mit unserem Mitarbeiter durch Eingeben von Text in diesen Kasten!\";\nBlockly.Msg.COLLAPSE_ALL = \"Collapse Blocks\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Block zusammenfalten\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"Farbe 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"mit Farbe 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"im Verhältniss\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"mische\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Vermische 2 Farbe mit konfigurierbaren Farbverhältniss (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://de.wikipedia.org/wiki/Farbe\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Wählen eine Farbe von der Palette.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"zufällige Farbe\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Wählen Sie eine Farbe nach dem Zufallsprinzip.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blau\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"grün\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"https://de.wikipedia.org/wiki/RGB-Farbraum\";\nBlockly.Msg.COLOUR_RGB_RED = \"rot\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"Farbe mit\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Kreiere eine Farbe mit selbst definierten rot, grün und blau Werten. Alle Werte müssen zwischen 0 und 100 liegen.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://de.wikipedia.org/wiki/Kontrollstruktur\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"ausbrechen aus der Schleife\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"mit der nächsten Iteration fortfahren aus der Schleife\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Die umgebene Schleife beenden.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Diese Anweisung abbrechen und mit der nächsten Schleifeniteration fortfahren.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Warnung: Diese block sollte nur in einer Schleife verwendet werden.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://de.wikipedia.org/wiki/For-Schleif\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"aus der Liste\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"Für Wert\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Führe eine Anweisung für jeden Wert in der Liste aus und setzte dabei die Variable \\\"%1\\\" auf den aktuellen Listen Wert.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://de.wikipedia.org/wiki/For-Schleif\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"von %1 bis %2 mit %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"Zähle\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Zähle die Variable \\\"%1\\\" von einem Startwert bis zu einem Zielwert und führe für jeden Wert eine Anweisung aus.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Eine weitere Bedingung hinzufügen.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Eine oder Bedingung hinzufügen, führt eine Anweisung aus falls keine Bedingung zutrifft.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Hinzufügen, entfernen oder sortieren von Sektionen\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"oder\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"oder wenn\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"wenn\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Wenn eine Bedingung wahr (true) ist, dann führe eine Anweisung aus.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Wenn eine Bedingung wahr (true) ist, dann führe die erste Anweisung aus.  Ansonsten führe die zweite Anweisung aus.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Wenn der erste Bedingung wahr (true) ist, dann führe die erste Anweisung aus.  Oder wenn die zweite Bedingung wahr (true) ist, dann führe die zweite Anweisung aus.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Wenn der erste Bedingung wahr (true) ist, dann führe die erste Anweisung aus.  Oder wenn die zweite Bedingung wahr (true) ist, dann führe die zweite Anweisung aus.  Falls keine der beiden Bedingungen wahr (true) ist, dann führe die dritte Anweisung aus.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://de.wikipedia.org/wiki/For-Schleife\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"mache\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"wiederhole %1 mal\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"wiederhole\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"mal\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Eine Anweisung mehrfach ausführen.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://de.wikipedia.org/wiki/Schleife_%28Programmierung%29\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"Wiederhole bis\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"Wiederhole solange\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Führe die Anweisung solange aus wie die Bedingung falsch (false) ist.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Führe die Anweisung solange aus wie die Bedingung wahr (true) ist.\";\nBlockly.Msg.DELETE_BLOCK = \"Block löschen\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Block %1 löschen\";\nBlockly.Msg.DISABLE_BLOCK = \"Block deaktivieren\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Kopieren\";\nBlockly.Msg.ENABLE_BLOCK = \"Block aktivieren\";\nBlockly.Msg.EXPAND_ALL = \"Expand Blocks\";\nBlockly.Msg.EXPAND_BLOCK = \"Block entfalten\";\nBlockly.Msg.EXTERNAL_INPUTS = \"externe Eingänge\";\nBlockly.Msg.HELP = \"Hilfe\";\nBlockly.Msg.INLINE_INPUTS = \"interne Eingänge\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"Erzeuge eine leere Liste\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Erzeugt eine leere Liste ohne Inhalt.\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"Liste\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Hinzufügen, entfernen und sortieren von Elementen.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"Erzeuge Liste mit\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Ein Element zur Liste hinzufügen.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Erzeugt eine List mit konfigurierten Elementen.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"erste\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"#te von hinten\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#te\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"Nehme\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"Nehme und entferne\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"letzte\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"zufälliges\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"Entferne\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Extrahiere das erste Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Extrahiere das #1te Element vom Ende der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Extrahiere das #1te Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Extrahiere das letzte Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Extrahiere ein zufälliges Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Extrahiere und entfernt das erste Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Extrahiere und entfernt das #1te Element vom Ende der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Extrahiere und entfernt das #1te Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Extrahiere und entfernt das letzte Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Extrahiere und entfernt ein zufälliges Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Entfernt das erste Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Entfernt das #1te Element vom Ende der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Entfernt das #1te Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Entfernt das letzte Element von der Liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Entfernt ein zufälliges Element von der Liste.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"zu # vom Ende\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"zu #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"zum Letzten\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"erhalte Unterliste vom Ersten\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"erhalte Unterliste von # vom Ende\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"erhalte Unterliste von #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Creates a copy of the specified portion of a list.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"Suche erstes Vorkommniss\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"Suche letztes Vorkommniss\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Sucht die Position (index) eines Elementes in der Liste Gibt 0 zurück wenn nichts gefunden wurde.\";\nBlockly.Msg.LISTS_INLIST = \"in der Liste\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 ist leer?\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"länge %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Die Anzahl von Elementen in der Liste.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"Erzeuge Liste mit Element %1 wiederhole es %2 mal\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Erzeugt eine Liste mit einer variablen Anzahl von Elementen\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"auf\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"insert\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"set\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserts the item at the start of a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserts the item at the specified position in a list.  #1 is the last item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserts the item at the specified position in a list.  #1 is the first item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Append the item to the end of a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserts the item randomly in a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Sets the first item in a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Sets the item at the specified position in a list.  #1 is the last item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Sets the item at the specified position in a list.  #1 is the first item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Sets the last item in a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Sets a random item in a list.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Ist wahr (true), wenn die Liste leer ist.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"falsch\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Ist entweder wahr (true) oder falsch (false)\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"wahr\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://de.wikipedia.org/wiki/Vergleich_%28Zahlen%29\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Ist wahr (true) wenn beide Werte identisch sind.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Ist wahr (true) wenn der erste Wert grösser als der zweite Wert ist.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Ist wahr (true) wenn der erste Wert grösser als oder gleich gross wie zweite Wert ist.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Ist wahr (true) wenn der erste Wert kleiner als der zweite Wert ist.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Ist wahr (true) wenn der erste Wert kleiner als oder gleich gross wie zweite Wert ist.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Ist wahr (true) wenn beide Werte unterschiedlich sind.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"nicht %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Ist wahr (true) wenn der Eingabewert falsch (false) ist.  Ist falsch (false) wenn der Eingabewert wahr (true) ist.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://de.wikipedia.org/wiki/Nullwert\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Ist NULL.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"und\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"oder\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Ist wahr (true) wenn beide Werte wahr (true) sind.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Ist wahr (true) wenn einer der beiden Werte wahr (true) ist.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://de.wikipedia.org/wiki/%3F:#Auswahloperator\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"wenn falsch\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"wenn wahr\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Überprüft eine Bedingung \\\"test\\\". Wenn die Bedingung wahr ist wird der \\\"wenn wahr\\\" Wert zurückgegeben, andernfalls der \\\"wenn falsch\\\" Wert\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://de.wikipedia.org/wiki/Grundrechenart\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Ist die Summe zweier Werte.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Ist der Quotient zweier Werte.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Ist die Differenz zweier Werte.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Ist das Produkt zweier Werte.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Ist der erste Wert potenziert mit dem zweiten Wert.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://de.wikipedia.org/wiki/Inkrement_und_Dekrement\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"um\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"erhöhe\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Addiert einen Wert zur Variable \\\"%1\\\" hinzu.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://de.wikipedia.org/wiki/Mathematische_Konstante\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Mathematische Konstanten wie: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) oder ∞ (unendlich).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"begrenzen %1 von %2 bis %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Begrenzt den Wertebereich mittels von / bis Werte. (inklusiv)\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"ist teilbar durch\";\nBlockly.Msg.MATH_IS_EVEN = \"ist gerade\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"ist negativ\";\nBlockly.Msg.MATH_IS_ODD = \"ist ungerade\";\nBlockly.Msg.MATH_IS_POSITIVE = \"ist positiv\";\nBlockly.Msg.MATH_IS_PRIME = \"ist eine Primenzahl\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Überprüft ob eine Zahl gerade, ungerade, eine Primenzahl, ganzzahlig, positiv, negativ oder durch eine zweite Zahl teilbar ist.  Gibt wahr (true) oder falsch (false) zurück.\";\nBlockly.Msg.MATH_IS_WHOLE = \"ganze Zahl\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://de.wikipedia.org/wiki/Modulo\";\nBlockly.Msg.MATH_MODULO_TITLE = \"Rest von %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Der Rest nach einer Division.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://de.wikipedia.org/wiki/Zahl\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Eine Zahl.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"http://www.sysplus.ch/einstieg.php?links=menu&seite=4125&grad=Crash&prog=Excel\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"Mittelwert einer Liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"Maximalwert einer Liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"Median einer Liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"Minimalwert einer Liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"Modulo / Restwert einer Liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"Zufallswert einer Liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"Standart Abweichung einer Liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"Summme einer Liste\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Ist der Durchschnittswert aller Werte in einer Liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Ist der grösste Wert in einer Liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Ist der Zentralwert aller Werte in einer Liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Ist der kleinste Wert in einer Liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Findet den am häufigsten vorkommenden Wert in einer Liste.  Falls kein Wert öfter vorkomme als alle anderen, wird die originale Liste zurückgegen\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Gebe einen Zufallswert aus der Liste zurück.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Ist die standartiesierte Standartabweichung aller Werte in der Liste\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Ist die Summe aller Werte in einer Liste.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://de.wikipedia.org/wiki/Zufallszahlen\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"Zufallszahl (0.0 -1.0)\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Erzeuge eine Zufallszahl zwischen 0.0 (inklusiv) und 1.0 (exklusiv).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://de.wikipedia.org/wiki/Zufallszahlen\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"ganzahliger Zufallswerte zwischen %1 bis %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Erzeuge eine ganzahligen Zufallswert zwischen zwei Werten (inklusiv).\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://de.wikipedia.org/wiki/Runden\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"runden\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"ab runden\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"auf runden\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Eine Zahl auf oder ab runden.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://de.wikipedia.org/wiki/Quadratwurzel\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"Absolutwert\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"Quadratwurzel\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Ist der Absolutwert eines Wertes.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Ist Wert der Exponentialfunktion eines Wertes.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Ist der natürliche Logarithmus eines Wertes.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Ist der dekadische Logarithmus eines Wertes.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Negiert einen Wert.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Rechnet 10 hoch Eingabewert.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Ist die Qudratwurzel eines Wertes.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://de.wikipedia.org/wiki/Trigonometrie\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Ist der Arcuscosinus des Eingabewertes.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Ist der Arcussinus des Eingabewertes.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Ist der Arcustangens des Eingabewertes.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Ist der Cosinus eins Winkels.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Ist der Sinus eins Winkels.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Ist der Tangens eins Winkels.\";\nBlockly.Msg.NEW_VARIABLE = \"Neue Variable...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Name der neuen Variable:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"mit:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Rufe einen Funktionsblock ohne Rückgabewert auf.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Rufe einen Funktionsblock mit Rückgabewert auf.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Erzeuge \\\"Aufruf %1\\\"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"Funktionsblock\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"to\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Ein Funktionsblock ohne Rückgabewert.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"gebe zurück\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Ein Funktionsblock mit Rückgabewert.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Warnung: dieser Funktionsblock hat doppelte Parameter.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Markiere Funktionsblock\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Wenn der erste Wert wahr (true) ist, Gebe den zweiten Wert zurück.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Warnung: Dieser Block darf nur innerhalb eines Funktionsblock genutzt werden.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"Variable:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"Parameter\";\nBlockly.Msg.REMOVE_COMMENT = \"Kommentar entfernen\";\nBlockly.Msg.RENAME_VARIABLE = \"Variable umbenennen...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Alle \\\"%1\\\" Variablen umbenennen in:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"Text anhängen\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_APPEND_TO = \"An\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Text an die Variable \\\"%1\\\" anhängen.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"umwandeln in kleinbuchstaben\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"umwandeln in Wörter\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"umwandeln in GROSSBUCHSTABEN\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Wandelt Schreibweise von Texten um, in Grossbuchstaben, Kleinbuchstaben oder den ersten Buchstaben jedes Wortes gross und die anderen klein.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"Nehme ersten Buchstabe\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"Nehme #te Buchstabe von hinten\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"Nehme Buchstabe #ten\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"vom Text\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"Nehme letzten Buchstabe\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"Nehme zufälligen Buchstabe\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Extrahiere einen Buchstaben von einer spezifizierten Position.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Ein Element zum Text hinzufügen.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"verbinden\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Hinzufügen, entfernen und sortieren von Elementen.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"bis #te Buchstabe von hinten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"bis Buchstabe #ten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"bis letzten Buchstabe\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"in Text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"ersten Buchstabe\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"#te Buchstabe von hinten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"Buchstabe #ten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"im Text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"Suche erstes Vorkommniss des Begriff\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"Suche letztes Vorkommniss des Begriff\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Findest das erste / letzte Vorkommniss eines cuchbegriffes in einem Text.  Gibt die Position des Begriffes oder 0 zurück.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 ist leer?\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Ist wahr (true), wenn der Text leer ist.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"Erstelle Text aus\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Erstellt einen Text durch das verbinden von mehreren Textelementen.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"länge %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Die Anzahl von Zeichen in einem Textes. (inkl. Leerzeichen)\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"Ausgabe %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Gib den Inhalt einer Variable aus.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Fragt den Benutzer nach ein Zahl.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Fragt den Benutzer nach einem Text.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"Fragt nach Zahl mit Hinweis\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"Fragt nach Text mit Hinweis\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://de.wikipedia.org/wiki/Zeichenkette\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Ein Buchstabe, Text oder Satz.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"entferne Leerzeichen von Anfang und Ende Seiten\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"entferne Leerzeichen von Anfang Seite\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"entferne Leerzeichen von Ende Seite von\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Entfernt Leerzeichen vom Anfang und / oder Ende eines Textes.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"Element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Erzeuge \\\"Schreibe %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://de.wikipedia.org/wiki/Variable_%28Programmierung%29\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Gibt den Wert der Variable zurück.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Erzeuge \\\"Lese %1\\\"\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://de.wikipedia.org/wiki/Variable_%28Programmierung%29\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"Schreibe\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Setzt den Wert einer Variable.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/el.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.el');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Πρόσθεσε Σχόλιο\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Άλλαξε την τιμή:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Σύμπτυξτε Όλα Τα Μπλοκ\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Σύμπτυξε Το Μπλοκ\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"χρώμα 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"χρώμα 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"αναλογία\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"μείγμα\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Συνδυάζει δύο χρώματα μαζί με μια δεδομένη αναλογία (0.0 - 1,0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://el.wikipedia.org/wiki/Χρώμα\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Επιτρέπει επιλογή χρώματος από την παλέτα.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"τυχαίο χρώμα\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Επιλέγει χρώμα τυχαία.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"μπλε\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"πράσινο\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"κόκκινο\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"χρώμα με\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Δημιουργεί χρώμα με το συγκεκριμένο ποσό του κόκκινου, πράσινου και μπλε που ορίζεις. Όλες οι τιμές πρέπει να είναι μεταξύ 0 και 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"φεύγει από το μπλοκ επαναλήψεως\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"συνέχισε με την επόμενη επανάληψη του μπλοκ επαναλήψεως\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Ξεφεύγει (βγαίνει έξω) από την επανάληψη.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Παραλείπει το υπόλοιπο τμήμα αυτού του μπλοκ επαναλήψεως, και συνεχίζει με την επόμενη επανάληψη.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Προειδοποίηση: Αυτό το μπλοκ μπορεί να χρησιμοποιηθεί μόνο μέσα σε μια επανάληψη.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.Google.com/p/blockly/wiki/loops#for _each ΓΙΑ ΚΑΘΕ μπλοκ\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"στη λίστα\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"για κάθε στοιχείο\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Για κάθε στοιχείο σε μια λίστα, ορίζει τη μεταβλητή «%1» στο στοιχείο και, στη συνέχεια, εκτελεί κάποιες εντολές.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"Blockly\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"από το %1 έως το %2 ανά %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"μέτρησε με\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Η μεταβλητή %1 παίρνει τιμές ξεκινώντας από τον αριθμό έναρξης μέχρι τον αριθμό τέλους αυξάνοντας κάθε φορά με το καθορισμένο βήμα και εκτελώντας το καθορισμένο μπλοκ.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Πρόσθετει μια κατάσταση/συνθήκη στο μπλοκ «εάν».\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Προσθέτει μια τελική κατάσταση/συνθήκη, που πιάνει όλες τις άλλες περιπτώσεις, στο μπλοκ «εάν».\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then ΑΝ_ΤΟΤΕ\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Προσθέτει, αφαιρεί ή αναδιατάσσει τα τμήματα για να αναδιαμορφώσει αυτό το μπλοκ «εάν».\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"αλλιώς\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"εναλλακτικά αν\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"αν\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Αν μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Αν μια τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, εκτελεί το δεύτερο τμήμα εντολών.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Αν η πρώτη τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, αν η δεύτερη τιμή είναι αληθής, εκτελεί το δεύτερο μπλοκ εντολών.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Αν η πρώτη τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών.  Διαφορετικά, αν η δεύτερη τιμή είναι αληθής, εκτελεί το δεύτερο τμήμα εντολών. Αν καμία από τις τιμές δεν είναι αληθής, εκτελεί το τελευταίο τμήμα εντολών.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"κάνε\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"επανάλαβε %1 φορές\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"επανάλαβε\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"φορές\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Εκτελεί κάποιες εντολές αρκετές φορές.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat ΕΠΑΝΑΛΑΒΕ\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"επανάλαβε μέχρι\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"επανάλαβε ενώ\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Ενόσω μια τιμή είναι ψευδής, τότε εκτελεί κάποιες εντολές.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Ενόσω μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές.\";\nBlockly.Msg.DELETE_BLOCK = \"Διέγραψε Το Μπλοκ\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Διέγραψε %1 Μπλοκ\";\nBlockly.Msg.DISABLE_BLOCK = \"Απενεργοποίησε Το Μπλοκ\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Αντίγραφο\";\nBlockly.Msg.ENABLE_BLOCK = \"Ενεργοποίησε Το Μπλοκ\";\nBlockly.Msg.EXPAND_ALL = \"Επέκτεινε Όλα Τα Μπλοκ\";\nBlockly.Msg.EXPAND_BLOCK = \"Επέκτεινε Το Μπλοκ\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Εξωτερικές Είσοδοι\";\nBlockly.Msg.HELP = \"Βοήθεια\";\nBlockly.Msg.INLINE_INPUTS = \"Εσωτερικές Είσοδοι\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"λίστα\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"δημιούργησε κενή λίστα\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Επιστρέφει μια λίστα, με μήκος 0, η οποία δεν περιέχει εγγραφές δεδομένων\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"λίστα\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Προσθέτει, αφαιρεί ή αναδιατάσσει τα τμήματα για να αναδιαμορφώσει αυτό το μπλοκ λίστας.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"δημιούργησε λίστα με\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Προσθέτει αντικείμενο στη λίστα.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Δημιουργεί λίστα με οποιονδήποτε αριθμό αντικειμένων.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"πρώτο\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# από το τέλος\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"πάρε\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"πάρε και αφαίρεσε\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"τελευταίο\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"τυχαίο\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"αφαίρεσε\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Επιστρέφει το πρώτο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Επιστρέφει το τελευταίο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Επιστρέφει ένα τυχαίο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Καταργεί και επιστρέφει το πρώτο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Καταργεί και επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Καταργεί και επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Καταργεί και επιστρέφει το τελευταίο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Καταργεί και επιστρέφει ένα τυχαίο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Καταργεί το πρώτο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Καταργεί το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Καταργεί το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Καταργεί το τελευταίο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Καταργεί ένα τυχαίο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"έως # από το τέλος\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"έως #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"έως το τελευταίο\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"Blockly\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"πάρε υπολίστα από την αρχή\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"πάρε υπολίστα από # από το τέλος\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"πάρε υπολίστα από #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Δημιουργεί ένα αντίγραφο του καθορισμένου τμήματος μιας λίστας.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"βρες την πρώτη εμφάνιση του στοιχείου\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"Blockly\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"βρες την τελευταία εμφάνιση του στοιχείου\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Επιστρέφει τον δείκτη της πρώτης/τελευταίας εμφάνισης του στοιχείου στη λίστα.  Επιστρέφει τιμή 0, αν το κείμενο δεν βρεθεί.\";\nBlockly.Msg.LISTS_INLIST = \"στη λίστα\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty ΕΙΝΑΙ_ΑΔΕΙΑ\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"το %1 είναι κενό\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"Blockly\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"το μήκος του %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Επιστρέφει το μήκος μιας λίστας.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"Blockly\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"δημιούργησε λίστα με το στοιχείο %1 να επαναλαμβάνεται %2 φορές\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Δημιουργεί μια λίστα που αποτελείται από την δεδομένη τιμή που επαναλαμβάνεται για συγκεκριμένο αριθμό επαναλήψεων.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"σε\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"είσαγε στο\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"όρισε\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Εισάγει το στοιχείο στην αρχή μιας λίστας.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Εισάγει το στοιχείο σε συγκεκριμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Εισάγει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Αναθέτει το στοιχείο στο τέλος μιας λίστας.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Εισάγει το στοιχείο τυχαία σε μια λίστα.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Ορίζει το πρώτο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Ορίζει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Ορίζει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Ορίζει το τελευταίο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Ορίζει ένα τυχαίο στοιχείο σε μια λίστα.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Επιστρέφει αληθής αν η λίστα είναι κενή.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"ψευδής\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Επιστρέφει είτε αληθής είτε ψευδής.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"αληθής\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Επιστρέφει αληθής αν και οι δύο είσοδοι είναι ίσες μεταξύ τους.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Επιστρέφει αληθής αν η πρώτη είσοδος είναι μεγαλύτερη από τη δεύτερη είσοδο.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη ή ίση με τη δεύτερη είσοδο.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη από τη δεύτερη είσοδο.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη από ή ίση με τη δεύτερη είσοδο.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Επιστρέφει αληθής αν και οι δύο είσοδοι δεν είναι ίσες μεταξύ τους.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"όχι %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Επιστρέφει αληθής αν η είσοδος είναι ψευδής. Επιστρέφει ψευδής αν η είσοδος είναι αληθής.\";\nBlockly.Msg.LOGIC_NULL = \"κενό\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Επιστρέφει κενό.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"και\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or ΚΑΙ_Ή\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"ή\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Επιστρέφει αληθής αν και οι δύο είσοδοι είναι αληθής.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Επιστρέφει αληθής αν τουλάχιστον μια από τις εισόδους είναι αληθής.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"έλεγχος\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"αν είναι ψευδής\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"αν είναι αληθής\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Ελέγχει την κατάσταση/συνθήκη στον «έλεγχο». Αν η κατάσταση/συνθήκη είναι αληθής, επιστρέφει την τιμή «αν αληθής», διαφορετικά επιστρέφει την τιμή «αν ψευδής».\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://el.wikipedia.org/wiki/Αριθμητική\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Επιστρέφει το άθροισμα των δύο αριθμών.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Επιστρέφει το πηλίκο των δύο αριθμών.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Επιστρέφει τη διαφορά των δύο αριθμών.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Επιστρέφει το προϊόν των δύο αριθμών.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Επιστρέφει τον πρώτο αριθμό υψωμένο στη δύναμη του δεύτερου αριθμού.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://el.wikipedia.org/wiki/%CE%A0%CF%81%CF%8C%CF%83%CE%B8%CE%B5%CF%83%CE%B7\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"από\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"άλλαξε\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Προσθέτει έναν αριθμό στη μεταβλητή «%1».\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Επιστρέφει μία από τις κοινές σταθερές: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...), ή ∞ (άπειρο).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29 ΓΡΑΦΙΚΑ\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"περιόρισε %1 χαμηλή %2 υψηλή %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Περιορίζει έναν αριθμό μεταξύ των προβλεπόμενων ορίων (χωρίς αποκλεισμούς).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"είναι διαιρετός από το\";\nBlockly.Msg.MATH_IS_EVEN = \"είναι άρτιος\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"είναι αρνητικός\";\nBlockly.Msg.MATH_IS_ODD = \"είναι περιττός\";\nBlockly.Msg.MATH_IS_POSITIVE = \"είναι θετικός\";\nBlockly.Msg.MATH_IS_PRIME = \"είναι πρώτος\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Ελέγχει αν ένας αριθμός είναι άρτιος, περιττός, πρώτος, ακέραιος, θετικός, αρνητικός, ή αν είναι διαιρετός από έναν ορισμένο αριθμό. Επιστρέφει αληθής ή ψευδής.\";\nBlockly.Msg.MATH_IS_WHOLE = \"είναι ακέραιος\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"υπόλοιπο της %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Επιστρέφει το υπόλοιπο της διαίρεσης των δύο αριθμών.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://el.wikipedia.org/wiki/Αριθμός\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Ένας αριθμός.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"μέσος όρος λίστας\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"μεγαλύτερος λίστας\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"διάμεσος λίστας\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"μικρότερος λίστας\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"μορφές λίστας\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"τυχαίο στοιχείο λίστας\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"τυπική απόκλιση λίστας\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"άθροισμα λίστας\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Επιστρέφει τον αριθμητικό μέσο όρο από τις αριθμητικές τιμές στη λίστα.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Επιστρέφει τον μεγαλύτερο αριθμό στη λίστα.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Επιστρέφει τον διάμεσο της λίστας.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Επιστρέφει τον μικρότερο αριθμό στη λίστα.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Επιστρέφει μια λίστα με τα πιο κοινά στοιχεία στη λίστα.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Επιστρέφει ένα τυχαίο στοιχείο από τη λίστα.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Επιστρέφει την τυπική απόκλιση της λίστας.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Επιστρέφει το άθροισμα όλων των αριθμών στη λίστα.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^ ύψωση σε δύναμη\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"τυχαίο κλάσμα\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Επιστρέψει ένα τυχαία κλάσμα μεταξύ 0,0 (κλειστό) και 1,0 (ανοικτό).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"τυχαίος ακέραιος από το %1 έως το %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Επιστρέφει έναν τυχαίο ακέραιο αριθμό μεταξύ δύο συγκεκριμένων ορίων (εντός - συμπεριλαμβανομένων και των ακραίων τιμών).\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"στρογγυλοποίησε\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"στρογγυλοποίησε προς τα κάτω\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"στρογγυλοποίησε προς τα πάνω\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Στρογγυλοποιεί έναν αριθμό προς τα πάνω ή προς τα κάτω.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://el.wikipedia.org/wiki/Τετραγωνική_ρίζα\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"απόλυτη\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"τετραγωνική ρίζα\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Επιστρέφει την απόλυτη τιμή ενός αριθμού.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Επιστρέφει το e υψωμένο στη δύναμη ενός αριθμού.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Επιστρέφει τον νεπέρειο λογάριθμο ενός αριθμού.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Επιστρέφει τον λογάριθμο με βάση το 10 ενός αριθμού.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Επιστρέφει την άρνηση ενός αριθμού.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Επιστρέφει το 10 υψωμένο στη δύναμη ενός αριθμού.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Επιστρέφει την τετραγωνική ρίζα ενός αριθμού.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"συν\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://el.wikipedia.org/wiki/Τριγωνομετρική_συνάρτηση\";\nBlockly.Msg.MATH_TRIG_SIN = \"ημ\";\nBlockly.Msg.MATH_TRIG_TAN = \"εφ\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Επιστρέφει το τόξο συνημίτονου ενός αριθμού.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Επιστρέφει το τόξο ημίτονου ενός αριθμού.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Επιστρέφει το τόξο εφαπτομένης ενός αριθμού.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Επιστρέφει το συνημίτονο ενός βαθμού (όχι ακτινίου).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Επιστρέφει το ημίτονο ενός βαθμού (όχι ακτινίου).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Επιστρέφει την εφαπτομένη ενός βαθμού (όχι ακτινίου).\";\nBlockly.Msg.NEW_VARIABLE = \"Νέα μεταβλητή...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Νέο όνομα μεταβλητής:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"με:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://el.wikipedia.org/wiki/Διαδικασία_(υπολογιστές)\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Εκτελεί την ορισμένη από τον χρήστη συνάρτηση «%1».\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://el.wikipedia.org/wiki/Διαδικασία_(υπολογιστές)\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Εκτελεί την ορισμένη από τον χρήστη συνάρτηση «%1» και χρησιμοποίησε την έξοδό της.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Δημιούργησε «%1»\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"κάνε κάτι\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"στο\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Δημιουργεί μια συνάρτηση χωρίς έξοδο.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"επιστροφή\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Δημιουργεί μια συνάρτηση με μια έξοδο.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Προειδοποίηση: Αυτή η συνάρτηση έχει διπλότυπες παραμέτρους.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Επισημάνετε τον ορισμό συνάρτησης\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Αν μια τιμή είναι αληθής, τότε επιστρέφει τη δεύτερη τιμή.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Προειδοποίηση: Αυτό το μπλοκ μπορεί να χρησιμοποιηθεί μόνο στον ορισμό μιας συνάρτησης.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"όνομα εισόδου:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"είσοδοι\";\nBlockly.Msg.REMOVE_COMMENT = \"Αφαίρεσε Το Σχόλιο\";\nBlockly.Msg.RENAME_VARIABLE = \"Μετονόμασε τη μεταβλητή...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Μετονόμασε όλες τις μεταβλητές «%1» σε:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"ανάθεσε κείμενο\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification ΑΛΛΑΓΗ_ΚΕΙΜΕΝΟΥ\";\nBlockly.Msg.TEXT_APPEND_TO = \"έως\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Αναθέτει κείμενο στη μεταβλητή «%1».\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"σε πεζά\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"σε Λέξεις Με Πρώτα Κεφαλαία\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"σε ΚΕΦΑΛΑΙΑ\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Επιστρέφει ένα αντίγραφο του κειμένου σε διαφορετική μορφή γραμμάτων.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"πάρε το πρώτο γράμμα\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"πάρε το γράμμα # από το τέλος\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"πάρε το γράμμα #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"στο κείμενο\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"πάρε το τελευταίο γράμμα\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"πάρε τυχαίο γράμμα\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Επιστρέφει το γράμμα στην καθορισμένη θέση.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Προσθέτει ένα στοιχείο στο κείμενο.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"ένωσε\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Προσθέτει, αφαιρεί ή αναδιατάσσει τους τομείς για να αναδιαμορφώσει αυτό το μπλοκ κειμένου.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"μέχρι το # γράμμα από το τέλος\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"μέχρι το # γράμμα\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"μέχρι το τελευταίο γράμμα\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"στο κείμενο\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"πάρε τη δευτερεύουσα συμβολοσειρά από το πρώτο γράμμα\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"πάρε τη δευτερεύουσα συμβολοσειρά από το # γράμμα από το τέλος\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"πάρε τη δευτερεύουσα συμβολοσειρά από το # γράμμα\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Επιστρέφει ένα συγκεκριμένο τμήμα του κειμένου.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text ΕΥΡΕΣΗ ΚΕΙΜΕΝΟΥ\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"στο κείμενο\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"βρες την πρώτη εμφάνιση του κειμένου\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"βρες την τελευταία εμφάνιση του κειμένου\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Επιστρέφει τον δείκτη της πρώτης/τελευταίας εμφάνισης του πρώτου κειμένου στο δεύτερο κείμενο.  Επιστρέφει τιμή 0, αν δε βρει το κείμενο.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"το %1 είναι κενό\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Επιστρέφει αληθής αν το παρεχόμενο κείμενο είναι κενό.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"δημιούργησε κείμενο με\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Δημιουργεί ένα κομμάτι κειμένου ενώνοντας έναν  απεριόριστο αριθμό αντικειμένων.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification ΑΛΛΑΓΗ_ΚΕΙΜΕΝΟΥ\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"το μήκος του %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Επιστρέφει το πλήθος των γραμμάτων (συμπεριλαμβανομένων και των κενών διαστημάτων) στο παρεχόμενο κείμενο.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text ΕΜΦΑΝΙΣΗ_ΚΕΙΜΕΝΟΥ\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"εκτύπωσε %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Εκτυπώνει το καθορισμένο κείμενο, αριθμό ή άλλη τιμή.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user ΕΙΣΑΓΩΓΗ_ΔΕΔΟΜΕΝΩΝ_ΑΠΟ_ΤΟΝ_ΧΡΗΣΤΗ\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Δημιουργεί προτροπή για τον χρήστη για να δώσει ένα αριθμό.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Δημιουργεί προτροπή για το χρήστη για να δώσει κάποιο κείμενο.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"πρότρεψε με μήνυμα για να δοθεί αριθμός\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"πρότρεψε με μήνυμα για να δοθεί κείμενο\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://el.wikipedia.org/wiki/Συμβολοσειρά\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Ένα γράμμα, μια λέξη ή μια γραμμή κειμένου.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"περίκοψε τα κενά και από τις δυο πλευρές του\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"περίκοψε τα κενά από την αριστερή πλευρά του\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"περίκοψε τα κενά από την δεξιά πλευρά του\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Επιστρέφει ένα αντίγραφο του κειμένου με αφαιρεμένα τα κενά από το ένα ή και τα δύο άκρα.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"αντικείμενο\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Δημιούργησε «όρισε %1»\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Επιστρέφει την τιμή αυτής της μεταβλητής.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Δημιούργησε «πάρε %1»\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set ΟΡΙΣΜΟΣ ΜΕΤΑΒΛΗΤΩΝ\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"μέχρι το\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"όρισε\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Ορίζει αυτή τη μεταβλητή να είναι ίση με την είσοδο.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/en.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.en');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Add Comment\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Change value:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";\nBlockly.Msg.COLLAPSE_ALL = \"Collapse Blocks\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Collapse Block\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"colour 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"colour 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"ratio\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"blend\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Blends two colours together with a given ratio (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Choose a colour from the palette.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"random colour\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Choose a colour at random.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blue\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"green\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"red\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"colour with\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Create a colour with the specified amount of red, green, and blue.  All values must be between 0 and 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"break out of loop\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continue with next iteration of loop\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Break out of the containing loop.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Skip the rest of this loop, and continue with the next iteration.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Warning: This block may only be used within a loop.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"in list\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"for each item\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"For each item in a list, set the variable '%1' to the item, and then do some statements.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"from %1 to %2 by %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"count with\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Add a condition to the if block.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Add a final, catch-all condition to the if block.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this if block.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"else\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"else if\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"if\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"If a value is true, then do some statements.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"If a value is true, then do the first block of statements.  Otherwise, do the second block of statements.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.  If none of the values are true, do the last block of statements.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"do\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"repeat %1 times\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"repeat\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"times\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Do some statements several times.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"repeat until\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"repeat while\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"While a value is false, then do some statements.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"While a value is true, then do some statements.\";\nBlockly.Msg.DELETE_BLOCK = \"Delete Block\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Delete %1 Blocks\";\nBlockly.Msg.DISABLE_BLOCK = \"Disable Block\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplicate\";\nBlockly.Msg.CLEAR_BLOCKS = \"모든 블록 삭제하기\";\nBlockly.Msg.ENABLE_BLOCK = \"Enable Block\";\nBlockly.Msg.EXPAND_ALL = \"Expand Blocks\";\nBlockly.Msg.EXPAND_BLOCK = \"Expand Block\";\nBlockly.Msg.EXTERNAL_INPUTS = \"External Inputs\";\nBlockly.Msg.HELP = \"Help\";\nBlockly.Msg.INLINE_INPUTS = \"Inline Inputs\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"create empty list\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returns a list, of length 0, containing no data records\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"list\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this list block.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"create list with\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Add an item to the list.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Create a list with any number of items.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"first\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# from end\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"get\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"get and remove\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"last\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"random\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"remove\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returns the first item in a list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returns the item at the specified position in a list.  #1 is the last item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returns the item at the specified position in a list.  #1 is the first item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returns the last item in a list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returns a random item in a list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Removes and returns the first item in a list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Removes and returns the item at the specified position in a list.  #1 is the last item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Removes and returns the item at the specified position in a list.  #1 is the first item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Removes and returns the last item in a list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Removes and returns a random item in a list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Removes the first item in a list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Removes the item at the specified position in a list.  #1 is the last item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Removes the item at the specified position in a list.  #1 is the first item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Removes the last item in a list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Removes a random item in a list.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"to # from end\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"to #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"to last\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"get sub-list from first\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"get sub-list from # from end\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"get sub-list from #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Creates a copy of the specified portion of a list.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"find first occurrence of item\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"find last occurrence of item\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.\";\nBlockly.Msg.LISTS_INLIST = \"in list\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 is empty\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"length of %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returns the length of a list.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"create list with item %1 repeated %2 times\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Creates a list consisting of the given value repeated the specified number of times.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"as\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"insert at\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"set\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserts the item at the start of a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserts the item at the specified position in a list.  #1 is the last item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserts the item at the specified position in a list.  #1 is the first item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Append the item to the end of a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserts the item randomly in a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Sets the first item in a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Sets the item at the specified position in a list.  #1 is the last item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Sets the item at the specified position in a list.  #1 is the first item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Sets the last item in a list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Sets a random item in a list.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Returns true if the list is empty.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"false\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Returns either true or false.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"true\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Return true if both inputs equal each other.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Return true if the first input is greater than the second input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Return true if the first input is greater than or equal to the second input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Return true if the first input is smaller than the second input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Return true if the first input is smaller than or equal to the second input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Return true if both inputs are not equal to each other.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"not %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returns true if the input is false.  Returns false if the input is true.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returns null.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"and\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"or\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Return true if both inputs are true.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Return true if at least one of the inputs is true.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"if false\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"if true\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Return the sum of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Return the quotient of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Return the difference of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Return the product of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Return the first number raised to the power of the second number.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"by\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"change\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Add a number to variable '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"is divisible by\";\nBlockly.Msg.MATH_IS_EVEN = \"is even\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"is negative\";\nBlockly.Msg.MATH_IS_ODD = \"is odd\";\nBlockly.Msg.MATH_IS_POSITIVE = \"is positive\";\nBlockly.Msg.MATH_IS_PRIME = \"is prime\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";\nBlockly.Msg.MATH_IS_WHOLE = \"is whole\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"remainder of %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Return the remainder from dividing the two numbers.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"A number.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"average of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"max of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"median of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"min of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modes of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"random item of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standard deviation of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"sum of list\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Return the average (arithmetic mean) of the numeric values in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Return the largest number in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Return the median number in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Return the smallest number in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Return a list of the most common item(s) in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Return a random element from the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Return the standard deviation of the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Return the sum of all the numbers in the list.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"random fraction\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"random integer from %1 to %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Return a random integer between the two specified limits, inclusive.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"round\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"round down\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"round up\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Round a number up or down.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolute\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"square root\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Return the absolute value of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Return e to the power of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Return the natural logarithm of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Return the base 10 logarithm of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Return the negation of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Return 10 to the power of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Return the square root of a number.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Return the arccosine of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Return the arcsine of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Return the arctangent of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Return the cosine of a degree (not radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Return the sine of a degree (not radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Return the tangent of a degree (not radian).\";\nBlockly.Msg.NEW_VARIABLE = \"New variable...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"New variable name:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"with:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Run the user-defined function '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Run the user-defined function '%1' and use its output.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Create '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"do something\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"to\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Creates a function with no output.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"return\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Creates a function with an output.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Warning: This function has duplicate parameters.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Highlight function definition\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"If a value is true, then return a second value.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Warning: This block may be used only within a function definition.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"input name:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"inputs\";\nBlockly.Msg.REMOVE_COMMENT = \"Remove Comment\";\nBlockly.Msg.RENAME_VARIABLE = \"Rename variable...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Rename all '%1' variables to:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"append text\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"to\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Append some text to variable '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"to lower case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"to Title Case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"to UPPER CASE\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"get first letter\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"get letter # from end\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"get letter #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"in text\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"get last letter\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"get random letter\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returns the letter at the specified position.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Add an item to the text.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"join\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"to letter # from end\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"to letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"to last letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"in text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"get substring from first letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"get substring from letter # from end\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"get substring from letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"in text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"find first occurrence of text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"find last occurrence of text\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 is empty\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returns true if the provided text is empty.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"create text with\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Create a piece of text by joining together any number of items.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"length of %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returns the number of letters (including spaces) in the provided text.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"print %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Print the specified text, number or other value.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Prompt for user for a number.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Prompt for user for some text.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"prompt for number with message\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"prompt for text with message\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"A letter, word, or line of text.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"trim spaces from both sides of\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"trim spaces from left side of\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"trim spaces from right side of\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Return a copy of the text with spaces removed from one or both ends.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"item\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Create 'set %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returns the value of this variable.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create 'get %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"to\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Sets this variable to be equal to the input.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/en_us.js",
    "content": "/**\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview English strings.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\ngoog.provide('Blockly.Msg.en_us');\n\ngoog.require('Blockly.Msg');\n\n\n/**\n * Due to the frequency of long strings, the 80-column wrap rule need not apply\n * to message files.\n */\n\n// Context menus.\nBlockly.Msg.DUPLICATE_BLOCK = 'Duplicate';\nBlockly.Msg.CLEAR_BLOCKS = \"모든 블록 삭제하기\";\nBlockly.Msg.REMOVE_COMMENT = 'Remove Comment';\nBlockly.Msg.ADD_COMMENT = 'Add Comment';\nBlockly.Msg.EXTERNAL_INPUTS = 'External Inputs';\nBlockly.Msg.INLINE_INPUTS = 'Inline Inputs';\nBlockly.Msg.DELETE_BLOCK = 'Delete Block';\nBlockly.Msg.DELETE_X_BLOCKS = 'Delete %1 Blocks';\nBlockly.Msg.COLLAPSE_BLOCK = 'Collapse Block';\nBlockly.Msg.EXPAND_BLOCK = 'Expand Block';\nBlockly.Msg.DISABLE_BLOCK = 'Disable Block';\nBlockly.Msg.ENABLE_BLOCK = 'Enable Block';\nBlockly.Msg.HELP = 'Help';\nBlockly.Msg.COLLAPSE_ALL = 'Collapse Blocks';\nBlockly.Msg.EXPAND_ALL = 'Expand Blocks';\n\n// Variable renaming.\nBlockly.Msg.CHANGE_VALUE_TITLE = 'Change value:';\nBlockly.Msg.NEW_VARIABLE = 'New variable...';\nBlockly.Msg.NEW_VARIABLE_TITLE = 'New variable name:';\nBlockly.Msg.RENAME_VARIABLE = 'Rename variable...';\nBlockly.Msg.RENAME_VARIABLE_TITLE = 'Rename all \"%1\" variables to:';\n\n// Colour Blocks.\nBlockly.Msg.COLOUR_PICKER_HELPURL = 'http://en.wikipedia.org/wiki/Color';\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = 'Choose a color from the palette.';\n\nBlockly.Msg.COLOUR_RANDOM_HELPURL = 'http://randomcolour.com';\nBlockly.Msg.COLOUR_RANDOM_TITLE = 'random color';\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = 'Choose a color at random.';\n\nBlockly.Msg.COLOUR_RGB_HELPURL = 'http://www.december.com/html/spec/colorper.html';\nBlockly.Msg.COLOUR_RGB_TITLE = 'color with';\nBlockly.Msg.COLOUR_RGB_RED = 'red';\nBlockly.Msg.COLOUR_RGB_GREEN = 'green';\nBlockly.Msg.COLOUR_RGB_BLUE = 'blue';\nBlockly.Msg.COLOUR_RGB_TOOLTIP = 'Create a color with the specified amount of red, green,\\n' +\n    'and blue.  All values must be between 0 and 100.';\n\nBlockly.Msg.COLOUR_BLEND_HELPURL = 'http://meyerweb.com/eric/tools/color-blend/';\nBlockly.Msg.COLOUR_BLEND_TITLE = 'blend';\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = 'color 1';\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = 'color 2';\nBlockly.Msg.COLOUR_BLEND_RATIO = 'ratio';\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = 'Blends two colors together with a given ratio (0.0 - 1.0).';\n\n// Loop Blocks.\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = 'http://en.wikipedia.org/wiki/For_loop';\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = 'repeat';\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = 'times';\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = 'do';\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = 'Do some statements several times.';\n\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = 'http://code.google.com/p/blockly/wiki/Repeat';\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = 'do';\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = 'repeat while';\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = 'repeat until';\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = 'While a value is true, then do some statements.';\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = 'While a value is false, then do some statements.';\n\nBlockly.Msg.CONTROLS_FOR_HELPURL = 'http://en.wikipedia.org/wiki/For_loop';\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = 'count with';\nBlockly.Msg.CONTROLS_FOR_INPUT_VAR = 'x';\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = 'from %1 to %2 y %3';\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = 'do';\nBlockly.Msg.CONTROLS_FOR_TAIL = '';\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = 'Count from a start number to an end number by the specified interval.\\n' +\n    'For each count, set the current count number to\\n' +\n    'variable \"%1\", and then do some statements.';\n\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = 'http://en.wikipedia.org/wiki/For_loop';\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = 'for each item';\nBlockly.Msg.CONTROLS_FOREACH_INPUT_VAR = 'x';\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = 'in list';\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = '';\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = 'do';\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = 'For each item in a list, set the item to\\n' +\n    'variable \"%1\", and then do some statements.';\n\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = 'http://en.wikipedia.org/wiki/Control_flow';\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = 'break out of loop';\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = 'continue with next iteration of loop';\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = 'Break out of the containing loop.';\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = 'Skip the rest of this loop, and\\n' +\n    'continue with the next iteration.';\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = 'Warning:\\n' +\n    'This block may only\\n' +\n    'be used within a loop.';\n\n// Logic Blocks.\nBlockly.Msg.CONTROLS_IF_HELPURL = 'http://code.google.com/p/blockly/wiki/If_Then';\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = 'If a value is true, then do some statements.';\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = 'If a value is true, then do the first block of statements.\\n' +\n    'Otherwise, do the second block of statements.';\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = 'If the first value is true, then do the first block of statements.\\n' +\n    'Otherwise, if the second value is true, do the second block of statements.';\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = 'If the first value is true, then do the first block of statements.\\n' +\n    'Otherwise, if the second value is true, do the second block of statements.\\n' +\n    'If none of the values are true, do the last block of statements.';\nBlockly.Msg.CONTROLS_IF_MSG_IF = 'if';\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = 'else if';\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = 'else';\nBlockly.Msg.CONTROLS_IF_MSG_THEN = 'do';\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = 'if';\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = 'Add, remove, or reorder sections\\n' +\n    'to reconfigure this if block.';\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = 'else if';\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = 'Add a condition to the if block.';\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = 'else';\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = 'Add a final, catch-all condition to the if block.';\n\nBlockly.Msg.LOGIC_COMPARE_HELPURL = 'http://en.wikipedia.org/wiki/Inequality_(mathematics)';\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = 'Return true if both inputs equal each other.';\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = 'Return true if both inputs are not equal to each other.';\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = 'Return true if the first input is smaller\\n' +\n    'than the second input.';\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = 'Return true if the first input is smaller\\n' +\n    'than or equal to the second input.';\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = 'Return true if the first input is greater\\n' +\n    'than the second input.';\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = 'Return true if the first input is greater\\n' +\n    'than or equal to the second input.';\n\nBlockly.Msg.LOGIC_OPERATION_HELPURL = 'http://code.google.com/p/blockly/wiki/And_Or';\nBlockly.Msg.LOGIC_OPERATION_AND = 'and';\nBlockly.Msg.LOGIC_OPERATION_OR = 'or';\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = 'Return true if both inputs are true.';\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = 'Return true if either inputs are true.';\n\nBlockly.Msg.LOGIC_NEGATE_HELPURL = 'http://code.google.com/p/blockly/wiki/Not';\nBlockly.Msg.LOGIC_NEGATE_INPUT_NOT = 'not';\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = 'Returns true if the input is false.\\n' +\n    'Returns false if the input is true.';\n\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = 'http://code.google.com/p/blockly/wiki/True_False';\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = 'true';\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = 'false';\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = 'Returns either true or false.';\n\nBlockly.Msg.LOGIC_NULL_HELPURL = 'http://en.wikipedia.org/wiki/Nullable_type';\nBlockly.Msg.LOGIC_NULL = 'null';\nBlockly.Msg.LOGIC_NULL_TOOLTIP = 'Returns null.';\n\nBlockly.Msg.LOGIC_TERNARY_HELPURL = 'http://en.wikipedia.org/wiki/%3F:';\nBlockly.Msg.LOGIC_TERNARY_CONDITION = 'test';\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = 'if true';\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = 'if false';\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = 'Check the condition in \"test\". If the condition is true\\n' +\n    'returns the \"if true\" value, otherwise returns the \"if false\" value.';\n\n// Math Blocks.\nBlockly.Msg.MATH_NUMBER_HELPURL = 'http://en.wikipedia.org/wiki/Number';\nBlockly.Msg.MATH_NUMBER_TOOLTIP = 'A number.';\n\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = 'http://en.wikipedia.org/wiki/Arithmetic';\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = 'Return the sum of the two numbers.';\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = 'Return the difference of the two numbers.';\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = 'Return the product of the two numbers.';\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = 'Return the quotient of the two numbers.';\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = 'Return the first number raised to\\n' +\n    'the power of the second number.';\n\nBlockly.Msg.MATH_SINGLE_HELPURL = 'http://en.wikipedia.org/wiki/Square_root';\nBlockly.Msg.MATH_SINGLE_OP_ROOT = 'square root';\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = 'absolute';\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = 'Return the square root of a number.';\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = 'Return the absolute value of a number.';\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = 'Return the negation of a number.';\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = 'Return the natural logarithm of a number.';\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = 'Return the base 10 logarithm of a number.';\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = 'Return e to the power of a number.';\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = 'Return 10 to the power of a number.';\n\nBlockly.Msg.MATH_TRIG_HELPURL = 'http://en.wikipedia.org/wiki/Trigonometric_functions';\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = 'Return the sine of a degree (not radian).';\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = 'Return the cosine of a degree (not radian).';\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = 'Return the tangent of a degree (not radian).';\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = 'Return the arcsine of a number.';\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = 'Return the arccosine of a number.';\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = 'Return the arctangent of a number.';\n\nBlockly.Msg.MATH_CONSTANT_HELPURL = 'http://en.wikipedia.org/wiki/Mathematical_constant';\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = 'Return one of the common constants: \\u03c0 (3.141\\u2026), e (2.718\\u2026), \\u03c6 (1.618\\u2026),\\n' +\n    'sqrt(2) (1.414\\u2026), sqrt(\\u00bd) (0.707\\u2026), or \\u221e (infinity).';\n\nBlockly.Msg.MATH_IS_EVEN = 'is even';\nBlockly.Msg.MATH_IS_ODD = 'is odd';\nBlockly.Msg.MATH_IS_PRIME = 'is prime';\nBlockly.Msg.MATH_IS_WHOLE = 'is whole';\nBlockly.Msg.MATH_IS_POSITIVE = 'is positive';\nBlockly.Msg.MATH_IS_NEGATIVE = 'is negative';\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = 'is divisible by';\nBlockly.Msg.MATH_IS_TOOLTIP = 'Check if a number is an even, odd, prime, whole, positive, negative,\\n' +\n    'or if it is divisible by certain number.  Returns true or false.';\n\nBlockly.Msg.MATH_CHANGE_HELPURL = 'http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter';\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = 'change';\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = 'item';\nBlockly.Msg.MATH_CHANGE_INPUT_BY = 'by';\nBlockly.Msg.MATH_CHANGE_TOOLTIP = 'Add a number to variable \"%1\".';\n\nBlockly.Msg.MATH_ROUND_HELPURL = 'http://en.wikipedia.org/wiki/Rounding';\nBlockly.Msg.MATH_ROUND_TOOLTIP = 'Round a number up or down.';\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = 'round';\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = 'round up';\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = 'round down';\n\nBlockly.Msg.MATH_ONLIST_HELPURL = '';\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = 'sum of list';\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = 'min of list';\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = 'max of list';\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = 'average of list';\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = 'median of list';\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = 'modes of list';\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = 'standard deviation of list';\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = 'random item of list';\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = 'Return the sum of all the numbers in the list.';\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = 'Return the smallest number in the list.';\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = 'Return the largest number in the list.';\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = 'Return the arithmetic mean of the list.';\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = 'Return the median number in the list.';\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = 'Return a list of the most common item(s) in the list.';\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = 'Return the standard deviation of the list.';\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = 'Return a random element from the list.';\n\nBlockly.Msg.MATH_MODULO_HELPURL = 'http://en.wikipedia.org/wiki/Modulo_operation';\nBlockly.Msg.MATH_MODULO_INPUT_DIVIDEND = 'remainder of';\nBlockly.Msg.MATH_MODULO_TOOLTIP = 'Return the remainder from dividing the two numbers.';\n\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = 'http://en.wikipedia.org/wiki/Clamping_%28graphics%29';\nBlockly.Msg.MATH_CONSTRAIN_INPUT_CONSTRAIN = 'constrain';\nBlockly.Msg.MATH_CONSTRAIN_INPUT_LOW = 'low';\nBlockly.Msg.MATH_CONSTRAIN_INPUT_HIGH = 'high';\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = 'Constrain a number to be between the specified limits (inclusive).';\n\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = 'http://en.wikipedia.org/wiki/Random_number_generation';\nBlockly.Msg.MATH_RANDOM_INT_TITLE = 'random integer from %1 to %2';\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = 'Return a random integer between the two\\n' +\n    'specified limits, inclusive.';\n\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = 'http://en.wikipedia.org/wiki/Random_number_generation';\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = 'random fraction';\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = 'Return a random fraction between\\n' +\n    '0.0 (inclusive) and 1.0 (exclusive).';\n\n// Text Blocks.\nBlockly.Msg.TEXT_TEXT_HELPURL = 'http://en.wikipedia.org/wiki/String_(computer_science)';\nBlockly.Msg.TEXT_TEXT_TOOLTIP = 'A letter, word, or line of text.';\n\nBlockly.Msg.TEXT_JOIN_HELPURL = '';\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = 'create text with';\nBlockly.Msg.TEXT_JOIN_TOOLTIP = 'Create a piece of text by joining\\n' +\n    'together any number of items.';\n\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = 'join';\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this text block.';\n\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = 'item';\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = 'Add an item to the text.';\n\nBlockly.Msg.TEXT_APPEND_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html';\nBlockly.Msg.TEXT_APPEND_TO = 'to';\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = 'append text';\nBlockly.Msg.TEXT_APPEND_VARIABLE = 'item';\nBlockly.Msg.TEXT_APPEND_TOOLTIP = 'Append some text to variable \"%1\".';\n\nBlockly.Msg.TEXT_LENGTH_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html';\nBlockly.Msg.TEXT_LENGTH_INPUT_LENGTH = 'length of';\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = 'Returns number of letters (including spaces)\\n' +\n    'in the provided text.';\n\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html';\nBlockly.Msg.TEXT_ISEMPTY_INPUT_ISEMPTY = 'is empty';\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = 'Returns true if the provided text is empty.';\n\nBlockly.Msg.TEXT_INDEXOF_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = 'in text';\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = 'find first occurrence of text';\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = 'find last occurrence of text';\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = 'Returns the index of the first/last occurrence\\n' +\n    'of first text in the second text.\\n' +\n    'Returns 0 if text is not found.';\n\nBlockly.Msg.TEXT_CHARAT_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = 'in text';\nBlockly.Msg.TEXT_CHARAT_FROM_START = 'get letter #';\nBlockly.Msg.TEXT_CHARAT_FROM_END = 'get letter # from end';\nBlockly.Msg.TEXT_CHARAT_FIRST = 'get first letter';\nBlockly.Msg.TEXT_CHARAT_LAST = 'get last letter';\nBlockly.Msg.TEXT_CHARAT_RANDOM = 'get random letter';\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = 'Returns the letter at the specified position.';\n\nBlockly.Msg.TEXT_SUBSTRING_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';\nBlockly.Msg.TEXT_SUBSTRING_INPUT_IN_TEXT = 'in text';\nBlockly.Msg.TEXT_SUBSTRING_INPUT_AT1 = 'get substring from';\nBlockly.Msg.TEXT_SUBSTRING_INPUT_AT2 = 'to';\nBlockly.Msg.TEXT_SUBSTRING_FROM_START = 'letter #';\nBlockly.Msg.TEXT_SUBSTRING_FROM_END = 'letter # from end';\nBlockly.Msg.TEXT_SUBSTRING_FIRST = 'first letter';\nBlockly.Msg.TEXT_SUBSTRING_LAST = 'last letter';\nBlockly.Msg.TEXT_SUBSTRING_TOOLTIP = 'Returns a specified portion of the text.';\n\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html';\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = 'to UPPER CASE';\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = 'to lower case';\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = 'to Title Case';\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = 'Return a copy of the text in a different case.';\n\nBlockly.Msg.TEXT_TRIM_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html';\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = 'trim spaces from both sides';\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = 'trim spaces from left side';\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = 'trim spaces from right side';\nBlockly.Msg.TEXT_TRIM_TOOLTIP = 'Return a copy of the text with spaces\\n' +\n    'removed from one or both ends.';\n\nBlockly.Msg.TEXT_PRINT_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html';\nBlockly.Msg.TEXT_PRINT_TITLE_PRINT = 'print';\nBlockly.Msg.TEXT_PRINT_TOOLTIP = 'Print the specified text, number or other value.';\n\nBlockly.Msg.TEXT_PROMPT_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html';\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = 'prompt for text with message';\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = 'prompt for number with message';\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = 'Prompt for user for a number.';\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = 'Prompt for user for some text.';\n\n// Lists Blocks.\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = 'http://en.wikipedia.org/wiki/Linked_list#Empty_lists';\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = 'create empty list';\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = 'Returns a list, of length 0, containing no data records';\n\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = 'create list with';\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = 'Create a list with any number of items.';\n\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = 'list';\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this list block.';\n\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = 'item';\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = 'Add an item to the list.';\n\nBlockly.Msg.LISTS_REPEAT_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';\nBlockly.Msg.LISTS_REPEAT_INPUT_WITH = 'create list with item';\nBlockly.Msg.LISTS_REPEAT_INPUT_REPEATED = 'repeated';\nBlockly.Msg.LISTS_REPEAT_INPUT_TIMES = 'times';\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = 'Creates a list consisting of the given value\\n' +\n    'repeated the specified number of times.';\n\nBlockly.Msg.LISTS_LENGTH_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html';\nBlockly.Msg.LISTS_LENGTH_INPUT_LENGTH = 'length of';\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = 'Returns the length of a list.';\n\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = 'http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html';\nBlockly.Msg.LISTS_INPUT_IS_EMPTY = 'is empty';\nBlockly.Msg.LISTS_TOOLTIP = 'Returns true if the list is empty.';\n\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = 'in list';\nBlockly.Msg.LISTS_INDEX_OF_FIRST = 'find first occurrence of item';\nBlockly.Msg.LISTS_INDEX_OF_LAST = 'find last occurrence of item';\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = 'Returns the index of the first/last occurrence\\n' +\n    'of the item in the list.\\n' +\n    'Returns 0 if text is not found.';\n\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';\nBlockly.Msg.LISTS_GET_INDEX_GET = 'get';\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = 'get and remove';\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = 'remove';\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = '#';\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = '# from end';\nBlockly.Msg.LISTS_GET_INDEX_FIRST = 'first';\nBlockly.Msg.LISTS_GET_INDEX_LAST = 'last';\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = 'random';\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = 'in list';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = 'Returns the item at the specified position in a list.\\n' +\n    '#1 is the first item.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = 'Returns the item at the specified position in a list.\\n' +\n    '#1 is the last item.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = 'Returns the first item in a list.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = 'Returns the last item in a list.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = 'Returns a random item in a list.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = 'Removes and returns the item at the specified position\\n' +\n    ' in a list.  #1 is the first item.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = 'Removes and returns the item at the specified position\\n' +\n    ' in a list.  #1 is the last item.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = 'Removes and returns the first item in a list.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = 'Removes and returns the last item in a list.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = 'Removes and returns a random item in a list.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = 'Removes the item at the specified position\\n' +\n    ' in a list.  #1 is the first item.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = 'Removes the item at the specified position\\n' +\n    ' in a list.  #1 is the last item.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = 'Removes the first item in a list.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = 'Removes the last item in a list.';\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = 'Removes a random item in a list.';\n\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = 'in list';\nBlockly.Msg.LISTS_SET_INDEX_SET = 'set';\nBlockly.Msg.LISTS_SET_INDEX_INSERT = 'insert at';\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = 'as';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = 'Sets the item at the specified position in a list.\\n' +\n    '#1 is the first item.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = 'Sets the item at the specified position in a list.\\n' +\n    '#1 is the last item.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = 'Sets the first item in a list.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = 'Sets the last item in a list.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = 'Sets a random item in a list.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = 'Inserts the item at the specified position in a list.\\n' +\n    '#1 is the first item.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = 'Inserts the item at the specified position in a list.\\n' +\n    '#1 is the last item.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = 'Inserts the item at the start of a list.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = 'Append the item to the end of a list.';\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = 'Inserts the item randomly in a list.';\n\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = 'http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm';\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = 'in list';\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_AT1 = 'get sub-list from';\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_AT2 = 'to';\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = 'Creates a copy of the specified portion of a list.';\n\n// Variables Blocks.\nBlockly.Msg.VARIABLES_GET_HELPURL = 'http://en.wikipedia.org/wiki/Variable_(computer_science)';\nBlockly.Msg.VARIABLES_GET_TITLE = '';\nBlockly.Msg.VARIABLES_GET_ITEM = 'item';\nBlockly.Msg.VARIABLES_GET_TAIL = '';\nBlockly.Msg.VARIABLES_GET_TOOLTIP = 'Returns the value of this variable.';\nBlockly.Msg.VARIABLES_GET_CREATE_SET = 'Create \"set %1\"';\n\nBlockly.Msg.VARIABLES_SET_HELPURL = 'http://en.wikipedia.org/wiki/Variable_(computer_science)';\nBlockly.Msg.VARIABLES_SET_TITLE = 'set';\nBlockly.Msg.VARIABLES_SET_ITEM = 'item';\nBlockly.Msg.VARIABLES_SET_TAIL = 'to';\nBlockly.Msg.VARIABLES_SET_TOOLTIP = 'Sets this variable to be equal to the input.';\nBlockly.Msg.VARIABLES_SET_CREATE_GET = 'Create \"get %1\"';\n\n// Procedures Blocks.\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29';\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = 'to';\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = 'do something';\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = 'with:';\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = '';\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = 'Creates a function with no output.';\n\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29';\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = 'return';\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = 'Creates a function with an output.';\n\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = 'Warning:\\n' +\n    'This function has\\n' +\n    'duplicate parameters.';\n\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29';\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = '';\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = 'Run the user-defined function \"%1\".';\n\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = 'http://en.wikipedia.org/wiki/Procedure_%28computer_science%29';\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = 'Run the user-defined function \"%1\" and use its output.';\n\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = 'inputs';\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = 'input name:';\n\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = 'Highlight procedure definition';\nBlockly.Msg.PROCEDURES_CREATE_DO = 'Create \"%1\"';\n\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = 'If a value is true, then return a value.';\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = 'Warning:\\n' +\n    'This block may only be\\n' +\n    'used within a function definition.';\n"
  },
  {
    "path": "extern/blockly/msg/js/es.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.es');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Añadir comentario\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Cambiar el valor:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Contraer bloques\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Contraer bloque\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"color 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"color 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"razón\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"combinar\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Combina dos colores con una proporción determinada (0,0–1,0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://es.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Elige un color de la paleta.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"color aleatorio\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Elige un color al azar.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"azul\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"verde\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"rojo\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"color con\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Crea un color con cantidades específicas de rojo, verde y azul. Todos los valores deben encontrarse entre 0 y 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"romper el bucle\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continuar con la siguiente iteración del bucle\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Rompe el que contiene el bucle.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Saltar el resto de este bucle, y continuar con la siguiente iteración.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"ADVERTENCIA: Este bloque puede usarse sólo dentro de un bucle.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"en la lista\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"para cada elemento\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Para cada elemento en una lista, establece la variable '%1' en el elemento y luego hacer algunas declaraciones.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"de %1 a %2 por %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"contar con\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Tiene la variable %1 que toma los valores desde el número de inicio hasta el número final, contando por el intervalo especificado, y hacer los bloques especificados.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Agregar una condición a este bloque.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Agregar una condición general final a este bloque.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Agregar, eliminar o reordenar las secciones para reconfigurar este bloque.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"sino\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"o si\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"si\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Si un valor es verdadero, entonces hacer algunas declaraciones.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Si un valor es verdadero, entonces hacer el primer bloque de declaraciones.  De lo contrario, hacer el segundo bloque de declaraciones.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones. Si ninguno de los valores son verdaderos, hacer el último bloque de declaraciones.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://es.wikipedia.org/wiki/Bucle_for\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"haz\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"repetir %1 veces\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"repetir\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"veces\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Hacer algunas declaraciones varias veces.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"repetir hasta\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"repetir mientras\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Mientras que un valor es falso, entonces hacer algunas declaraciones.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Mientras que un valor es verdadero, entonces hacer algunas declaraciones.\";\nBlockly.Msg.DELETE_BLOCK = \"Eliminar bloque\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Eliminar %1 bloques\";\nBlockly.Msg.DISABLE_BLOCK = \"Desactivr bloque\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplicar\";\nBlockly.Msg.ENABLE_BLOCK = \"Activar bloque\";\nBlockly.Msg.EXPAND_ALL = \"Expandir bloques\";\nBlockly.Msg.EXPAND_BLOCK = \"Expandir bloque\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Entradas externas\";\nBlockly.Msg.HELP = \"Ayuda\";\nBlockly.Msg.INLINE_INPUTS = \"Entradas en línea\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"crear lista vacía\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Devuelve una lista, de longitud de 0, que no contenga ningún registro de datos\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Agregar, eliminar o reorganizar las secciones para reconfigurar esta lista de bloques.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"crear lista con\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Agregar un elemento a la lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Crear una lista con cualquier número de elementos.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"primero\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# del final\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"obtener\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"obtener y retirar\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"último\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"aleatorio\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"eliminar\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Devuelve el primer elemento de una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Devuelve el elemento a la posición especificada en la lista. #1 es el último elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Devuelve el elemento a la posición especificada en la lista. #1 es el primer elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Devuelve el último elemento de una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Devuelve un elemento aleatorio en una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Elimina y devuelve el primer elemento de una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Elimina y devuelve el elemento a la posición especificada en la lista. #1 es el último elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Elimina y devuelve el elemento a la posición especificada en la lista. #1 es el primer elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Elimina y devuelve el último elemento de una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Elimina y devuelve un elemento aleatorio en una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Elimina el primer elemento de una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Elimina el elemento a la posición especificada en la lista. #1 es el último elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Elimina el elemento a la posición especificada en la lista. #1 es el primer elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Elimina el último elemento de una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Elimina un elemento aleatorio en una lista.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"a # del final\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"a #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"a la última\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"obtener sub-lista del primero\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"obtener sub-lista de # del final\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"obtener sub-lista de #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Crea una copia de la parte especificada de una lista.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"encontrar la primera aparición del elemento\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"encontrar la última aparición del elemento\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Devuelve el índice de la primera/última aparición del elemento en la lista. Devuelve 0 si el texto no se encuentra.\";\nBlockly.Msg.LISTS_INLIST = \"en la lista\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 está vacío\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"longitud de %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Devuelve la longitud de una lista.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"crear lista con el elemento %1 repetido %2 veces\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Crea una lista que consta de un valor dado repetido el número de veces especificado.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"como\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"inserta en\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"establece\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserta el elemento al inicio de una lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserta el elemento a la posición especificada en la lista. #1 es el último elemento.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserta el elemento a la posición especificada en la lista. #1 es el primer elemento.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Añade el elemento al final de una lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserta el elemento aleatoriamente en una lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Establece el primer elemento de una lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Establece el elemento a la posición especificada en una lista. #1 es el último elemento.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Establece el elemento a la posición especificada en una lista. #1 es el primer elemento.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Establece el último elemento de una lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Establece un elemento aleatorio en una lista.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Devuelve verdadero si la lista está vacía.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"falso\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Devuelve «verdadero» o «falso».\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"verdadero\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://es.wikipedia.org/wiki/Desigualdad_matemática\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Devolver verdadero si ambas entradas igualan unas a otras.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Devolver verdadero si la primera entrada es mayor que la segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Devolver verdadero si la primera entrada es mayor o igual a la segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Devolver verdadero si la primera entrada es menor que la segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Devolver verdadero si la primera entrada es menor que o igual a la segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Devolver verdadero si ambas entradas no son iguales entre sí.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"no %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Devolver verdadero si la entrada es falsa. Devolver falso si la entrada es verdadera.\";\nBlockly.Msg.LOGIC_NULL = \"nulo\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Devuelve «nulo».\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"y\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"o\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Devolver verdadero si ambas entradas son verdaderas.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Devolver verdadero si al menos una de las entradas es verdadera.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"prueba\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"si es falso\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"si es verdadero\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Comprobar la condición en \\\"probar\\\". Si la condición es verdadera, devolver el valor \\\"si es cierto\\\"; de lo contrario, devolver el valor \\\"si es falso\\\".\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://es.wikipedia.org/wiki/Aritmética\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Devuelve la suma de ambos numeros.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Devuelve el cociente de ambos números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Devuelve la diferencia de ambos números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Devuelve el producto de ambos números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Devuelve el primer número elevado a la potencia del segundo.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"por\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"cambiar\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Añadir un número a la variable «%1».\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://es.wikipedia.org/wiki/Anexo:Constantes_matemáticas\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Devolver una de las constantes comunes: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), o ∞ (infinito).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"limitar %1 bajo %2 alto %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Limitar un número entre los límites especificados (inclusive).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"es divisible por\";\nBlockly.Msg.MATH_IS_EVEN = \"es par\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"es negativo\";\nBlockly.Msg.MATH_IS_ODD = \"es impar\";\nBlockly.Msg.MATH_IS_POSITIVE = \"es positivo\";\nBlockly.Msg.MATH_IS_PRIME = \"es primo\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Comprobar si un número es par, impar, primo, entero, positivo, negativo, o si es divisible por un número determinado. Devuelve verdadero o falso.\";\nBlockly.Msg.MATH_IS_WHOLE = \"es entero\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resultado de %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Devolver el resultado al dividir los dos números.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://es.wikipedia.org/wiki/Número\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Un número.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"promedio de la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"max de la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mediana de lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"min de la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modos de la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"elemento aleatorio de la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"desviación estándar de la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"suma de la lista\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Devolver el promedio (media aritmética) de los valores numéricos en la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Devolver el número más grande en la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Devolver la mediana en la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Devolver el número más pequeño en la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Devolver una lista de los elementos más comunes en la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Devolver un elemento aleatorio de la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Devolver la desviación estándar de la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Devolver la suma de todos los números en la lista.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://es.wikipedia.org/wiki/Generador_de_números_aleatorios\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"fracción aleatoria\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Devolver una fracción aleatoria entre 0,0 (ambos inclusive) y 1.0 (exclusivo).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://es.wikipedia.org/wiki/Generador_de_números_aleatorios\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"entero aleatorio de %1 a %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Devolver un entero aleatorio entre los dos límites especificados, inclusive.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://es.wikipedia.org/wiki/Redondeo\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"redondear\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"redondear menos\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"redondear más\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Redondear un número hacia arriba o hacia abajo.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://es.wikipedia.org/wiki/Ra%C3%ADz_cuadrada\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absoluto\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"raíz cuadrada\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Devuelve el valor absoluto de un número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Devuelve e a la potencia de un número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Devuelve el logaritmo natural de un número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Devuelve el logaritmo base 10 de un número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Devolver la negación de un número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Devuelve 10 a la potencia de un número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Devuelve la raíz cuadrada de un número.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://es.wikipedia.org/wiki/Función_trigonométrica\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Devolver el arcocoseno de un número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Devolver el arcoseno de un número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Devolver el arcotangente de un número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Devolver el coseno de un grado (no radián).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Devolver el seno de un grado (no radián).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Devolver la tangente de un grado (no radián).\";\nBlockly.Msg.NEW_VARIABLE = \"Variable nueva…\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nombre de variable nueva:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"con:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://es.wikipedia.org/wiki/Subrutina\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Ejecuta la función definida por el usuario '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://es.wikipedia.org/wiki/Subrutina\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Ejecuta la función definida por el usuario '%1' y usar su salida.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Crear '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"hacer algo\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"a\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Crea una función sin salida.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"devuelve\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Crea una función con una salida.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Advertencia: Esta función tiene parámetros duplicados.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Destacar definición de la función\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Si el valor es verdadero, entonces devuelve un segundo valor.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Advertencia: Este bloque solo puede ser utilizado dentro de la definición de una función.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nombre de entrada:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"entradas\";\nBlockly.Msg.REMOVE_COMMENT = \"Eliminar comentario\";\nBlockly.Msg.RENAME_VARIABLE = \"Renombrar la variable…\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Renombrar todas las variables «%1» a:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"añadir texto\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"a\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Añadir texto a la variable '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"a minúsculas\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"a mayúsculas cada palabra\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"a mayúsculas\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Devuelve una copia del texto en un caso diferente.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"obtener la primera letra\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"obtener la letra # del final\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"obtener la letra #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"en el texto\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"obtener la última letra\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"obtener letra aleatoria\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Devuelve la letra a la posición especificada.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Agregar un elemento al texto.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"unir\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Agregar, eliminar o reordenar las secciones para reconfigurar este bloque de texto.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"a la letra # del final\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"a la letra #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"a la última letra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"en el texto\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"obtener subcadena de la primera letra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"obtener subcadena de la letra # del final\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"obtener subcadena de la letra #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Devuelve una porción determinada del texto.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"en el texto\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"encontrar la primera aparición del texto\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"encontrar la última aparición del texto\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Devuelve el índice de la primera/última aparición del primer texto en el segundo texto. Devuelve 0 si el texto no se encuentra.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 está vacío\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Devuelve verdadero si el texto proporcionado está vacío.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"crear texto con\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Crear un fragmento de texto al unir cualquier número de elementos.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"longitud de %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Devuelve el número de letras (incluyendo espacios) en el texto proporcionado.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"imprimir %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Imprimir el texto especificado, número u otro valor.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Solicitar al usuario por un número.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Solicitar al usuario por un texto.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"solicitar el número con el mensaje\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"solicitar el texto con el mensaje\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://es.wikipedia.org/wiki/Cadena_de_caracteres\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Una letra, palabra o línea de texto.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"quitar espacios de ambos lados de\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"quitar espacios al inicio de\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"quitar espacios al final de\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Devuelve una copia del texto con espacios retirados de uno o ambos extremos.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"elemento\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Crear 'set %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Devuelve el valor de esta variable.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Crear 'obtener %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"a\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"establece\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Establece esta variable para que sea igual a la entrada.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/fa.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.fa');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"افزودن نظر\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"تغییر مقدار:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"فروپاشی بلوک‌ها\";\nBlockly.Msg.COLLAPSE_BLOCK = \"فروپاشی بلوک\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"رنگ ۱\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"رنگ ۲\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"نسبت\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"مخلوط\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%B1%D9%86%DA%AF\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"انتخاب یک رنگ از تخته‌رنگ.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"رنگ تصادفی\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"انتخاب یک رنگ به شکل تصادفی.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"آبی\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"سبز\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"قرمز\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"رنگ با\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"ساخت یک رنگ با مقدار مشخص‌شده‌ای از قرمز، سبز و آبی. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"شکستن حلقه\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"ادامه با تکرار بعدی حلقه\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"شکستن حلقهٔ شامل.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"در فهرست\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"برای هر مورد\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"از %1 به %2 با گام‌های %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"با تعداد\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"متغیر %1 را در مقادیر شروع‌شده از عدد انتهای  به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"افزودن یک شرط به بلوک اگر.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"اضافه‌کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"اضافه، حذف یا ترتیب‌سازی قسمت‌ها برای تنظیم مجدد این بلوک اگر مسدود است.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"آنگاه\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"اگر آنگاه\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"اگر\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده.  در غیر این صورت بلوک دوم عبارات انجام بده.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده.  در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"اگر مقدار اول درست است، بلوک اول عبارات را انجام بده.  در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده.  اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%AD%D9%84%D9%82%D9%87_%D9%81%D9%88%D8%B1\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"انحام\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1 بار تکرار\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"تکرار\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"بار\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"انجام چند عبارت چندین بار.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"تکرار تا زمانی که\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"تکرار در حالی که\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده.\";\nBlockly.Msg.DELETE_BLOCK = \"حذف بلوک\";\nBlockly.Msg.DELETE_X_BLOCKS = \"حذف بلوک‌های %1\";\nBlockly.Msg.DISABLE_BLOCK = \"غیرفعال‌سازی بلوک\";\nBlockly.Msg.DUPLICATE_BLOCK = \"تکراری\";\nBlockly.Msg.ENABLE_BLOCK = \"فعال‌سازی بلوک\";\nBlockly.Msg.EXPAND_ALL = \"گسترش بلوک‌ها\";\nBlockly.Msg.EXPAND_BLOCK = \"گسترش بلوک\";\nBlockly.Msg.EXTERNAL_INPUTS = \"ورودی‌های خارجی\";\nBlockly.Msg.HELP = \"راهنما\";\nBlockly.Msg.INLINE_INPUTS = \"ورودی‌های درون خطی\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"ایجاد فهرست خالی\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند.\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"فهرست\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"اضافه‌کردن، حذف‌کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"ایجاد فهرست با\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"اضافه‌کردن یک مورد به فهرست.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"فهرستی از هر عددی از موارد می‌سازد.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"اولین\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# از انتها\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"گرفتن\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"گرفتن و حذف‌کردن\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"آخرین\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"تصادفی\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"حذف‌کردن\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"اولین مورد یک فهرست را بر می‌گرداند.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"موردی در محل مشخص در فهرست بر می‌گرداند.  #1 آخرین مورد است.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"موردی در محل مشخص‌شده بر می‌گرداند.  #1 اولین مورد است.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"آخرین مورد در یک فهرست را بر می‌گرداند.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"یک مورد تصادفی در یک فهرست بر می‌گرداند.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند.  #1 آخرین مورد است.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند.  #1 اولین مورد است.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"اولین مورد را در یک فهرست حذف می‌کند.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند.  #1 آخرین مورد است.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند.  #1 اولین مورد است.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"آخرین مورد را در یک فهرست حذف می‌کند.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"یک مورد تصادفی را یک فهرست حذف می‌کند.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"به # از انتها\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"به #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"به آخرین\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"گرفتن زیرمجموعه‌ای از ابتدا\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"گرفتن زیرمجموعه‌ای از # از انتها\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"گرفتن زیرمجموعه‌ای از #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"یافتن اولین رخ‌داد مورد\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"یافتن آخرین رخ‌داد مورد\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. ۰ بر می‌گرداند اگر متن موجود نبود.\";\nBlockly.Msg.LISTS_INLIST = \"در فهرست\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 خالی است\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"طول %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"طول یک فهرست را برمی‌گرداند.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"به‌عنوان\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"درج در\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"مجموعه\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"موردی به ته فهرست اضافه می‌کند.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند.  #1 آخرین مورد است.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند.  #1 اولین مورد است.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"موردی به ته فهرست الحاق می‌کند.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"مورد را به صورت تصادفی در یک فهرست می‌افزاید.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"اولین مورد در یک فهرست را تعیین می‌کند.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"مورد مشخص‌شده در یک فهرست را قرار می‌دهد.  #1 آخرین مورد است.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"مورد مشخص‌شده در یک فهرست را قرار می‌دهد.  #1 اولین مورد است.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"آخرین مورد در یک فهرست را تعیین می‌کند.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"یک مورد تصادفی در یک فهرست را تعیین می‌کند.\";\nBlockly.Msg.LISTS_TOOLTIP = \"اگر فهرست خالی است مقدار صجیج بر می‌گرداند.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"ناصحیح\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"بازگرداندن یکی از صحیح یا ناصحیح.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"صحیح\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://fa.wikipedia.org/wiki/%D9%86%D8%A7%D8%A8%D8%B1%D8%A7%D8%A8%D8%B1%DB%8C\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"نه %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد.\";\nBlockly.Msg.LOGIC_NULL = \"تهی\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"تهی بازمی‌گرداند.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"و\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"یا\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"بازگرداندن صحیح اگر هر دو ورودی صحیح باشد.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"آزمایش\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"اگر ناصحیح\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"اگر صحیح\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%AD%D8%B3%D8%A7%D8%A8\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"بازگرداندن مقدار جمع دو عدد.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"بازگرداندن باقی‌ماندهٔ دو عدد.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"بازگرداندن تفاوت دو عدد.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"بازگرداندن حاصلضرب دو عدد.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%E2%80%8C%D9%86%D9%88%DB%8C%D8%B3%DB%8C#.D8.A7.D9.81.D8.B2.D8.A7.DB.8C.D8.B4_.D8.B4.D9.85.D8.A7.D8.B1.D9.86.D8.AF.D9.87\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"با\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"تغییر\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"افزودن یک عدد به متغیر '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%AB%D8%A7%D8%A8%D8%AA_%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"محدودکردن %1 پایین %2 بالا %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"تقسیم شده بر\";\nBlockly.Msg.MATH_IS_EVEN = \"زوج است\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"منفی است\";\nBlockly.Msg.MATH_IS_ODD = \"فرد است\";\nBlockly.Msg.MATH_IS_POSITIVE = \"مثبت است\";\nBlockly.Msg.MATH_IS_PRIME = \"عدد اول است\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند.\";\nBlockly.Msg.MATH_IS_WHOLE = \"کامل است\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA_%D9%BE%DB%8C%D9%85%D8%A7%D9%86%D9%87\";\nBlockly.Msg.MATH_MODULO_TITLE = \"باقی‌ماندهٔ %1 + %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"یک عدد.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"میانگین فهرست\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"بزرگ‌ترین فهرست\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"میانهٔ فهرست\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"کوچکترین فهرست\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"مد فهرست\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"مورد تصادفی از فهرست\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"انحراف معیار فهرست\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"جمع فهرست\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"بزرگ‌ترین عدد در فهرست را باز می‌گرداند.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"میانهٔ عدد در فهرست را بر می‌گرداند.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"کوچک‌ترین عدد در فهرست را باز می‌گرداند.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"شایع‌ترین قلم(های) در فهرست را بر می‌گرداند.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"موردی تصادفی از فهرست را بر می‌گرداند.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"انحراف معیار فهرست را بر می‌گرداند.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"جمع همهٔ عددهای فهرست را باز می‌گرداند.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"کسر تصادفی\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"عدد صحیح تصادفی بین %1 تا %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"گردکردن\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"گرد به پایین\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"گرد به بالا\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"گردکردن یک عدد به بالا یا پایین.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%B1%DB%8C%D8%B4%D9%87_%D8%AF%D9%88%D9%85\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"مطلق\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"ریشهٔ دوم\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"قدر مطلق یک عدد را بازمی‌گرداند.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"بازگرداندن توان e یک عدد.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"لوگاریتم طبیعی یک عدد را باز می‌گرداند.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"منفی‌شدهٔ یک عدد را باز می‌گرداند.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"بازگرداندن توان ۱۰ یک عدد.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"ریشهٔ دوم یک عدد را باز می‌گرداند.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%AA%D8%A7%D8%A8%D8%B9%E2%80%8C%D9%87%D8%A7%DB%8C_%D9%85%D8%AB%D9%84%D8%AB%D8%A7%D8%AA%DB%8C\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"بازگرداندن آرک‌کسینوس درجه (نه رادیان).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"بازگرداندن آرک‌سینوس درجه (نه رادیان).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"بازگرداندن آرک‌تانژانت درجه (نه رادیان).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"بازگرداندن کسینوس درجه (نه رادیان).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"بازگرداندن سینوس درجه (نه رادیان).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"بازگرداندن تانژانت یک درجه (نه رادیان).\";\nBlockly.Msg.NEW_VARIABLE = \"متغیر جدید...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"نام متغیر جدید:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"با:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"اجرای تابع تعریف‌شده توسط کاربر «%1».\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"ساختن «%1»\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"انجام چیزی\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"به\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"تابعی می‌سازد بدون هیچ خروجی.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"بازگشت\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"تابعی با یک خروجی می‌سازد.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"اخطار: این تابعی پارامتر تکراری دارد.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"برجسته‌سازی تعریف تابع\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"اگر یک مقدار صحیح است، مقدار دوم را برگردان.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"اخطار: این بلوک احتمالاً فقط داخل یک تابع استفاده می‌شود.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"نام ورودی:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"ورودی‌ها\";\nBlockly.Msg.REMOVE_COMMENT = \"حذف نظر\";\nBlockly.Msg.RENAME_VARIABLE = \"تغییر نام متغیر...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"تغییر نام همهٔ متغیرهای «%1» به:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"الحاق متن\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"به\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"الحاق متنی به متغیر «%1».\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"به حروف کوچک\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"به حروف بزرگ عنوان\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"به حروف بزرگ\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"بازگرداندن کپی متن در حالتی متفاوت.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"گرفتن اولین حرف\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"گرفتن حرف # از آخر\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"گرفتن حرف #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"در متن\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"گرفتن آخرین حرف\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"گرفتن حرف تصادفی\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"حرفی در موقعیت مشخص‌شده بر می‌گرداند.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"افزودن یک مورد به متن.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"عضویت\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"اضافه‌کردن، حذف یا مرتب‌سازی بحش‌ها برای تنظیم مجدد این بلوک متنی.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"به حرف # از انتها\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"به حرف #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"به آخرین حرف\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"در متن\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"گرفتن زیرمتن از اولین حرف\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"گرفتن زیرمتن از حرف # به انتها\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"گرفتن زیرمتن از حرف #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"در متن\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"اولین رخداد متن را بیاب\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"آخرین رخداد متن را بیاب\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد ۰ باز می‌گرداند.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 خالی است\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"اضافه‌کردن صحیح اگر متن فراهم‌شده خالی است.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"ایجاد متن با\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"طول %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"چاپ %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"اعلان برای کاربر با یک عدد.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"اعلان برای کاربر برای یک متن.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"اعلان برای عدد با پیام\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"اعلان برای متن با پیام\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://fa.wikipedia.org/wiki/%D8%B1%D8%B4%D8%AA%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"یک حرف، کلمه یا خطی از متن.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"تراشیدن فاصله‌ها از  هر دو طرف\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"تراشیدن فاصله‌ها از  طرف چپ\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"تراشیدن فاصله‌ها از  طرف چپ\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"مورد\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"درست‌کردن «تنظیم %1»\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"مقدار این متغیر را بر می‌گرداند.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"درست‌کردن «گرفتن %1»\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"به\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"مجموعه\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"متغیر برابر با خروجی را مشخص می‌کند.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/fi.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.fi');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Lisää kommentti\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Muuta arvoa:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Sulje lohkot\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Sulje lohko\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"väri 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"väri 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"suhde\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"sekoitus\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Sekoittaa kaksi väriä keskenään annetussa suhteessa (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://fi.wikipedia.org/wiki/V%C3%A4ri\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Valitse väri paletista.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"satunnainen väri\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Valitse väri sattumanvaraisesti.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"sininen\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"vihreä\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"punainen\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"väri, jossa on\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Luo väri, jossa on tietty määrä punaista, vihreää ja sinistä. Kaikkien arvojen tulee olla välillä 0 - 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"poistu silmukasta\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"jatka silmukan seuraavaan toistoon\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Poistu sisemmästä silmukasta.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Ohita loput tästä silmukasta ja siirry seuraavaan toistoon.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Varoitus: Tätä lohkoa voi käyttää vain silmukan sisällä.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"listassa\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"kullekin kohteelle\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Aseta muuttujan %1 arvoksi kukin listan kohde vuorollaan ja suorita joukko lausekkeita.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"Väli %1-%2 %3:n välein\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"laske\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Aseta muuttujaan %1 arvot alkuarvosta loppuarvoon annetun askeleen välein ja suorita joka askeleella annettu koodilohko.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Lisää ehto \\\"jos\\\" lohkoon.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Lisää lopullinen \\\"muuten\\\" lohko \\\"jos\\\" lohkoon.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Lisää, poista tai järjestele osioita tässä \\\"jos\\\" lohkossa.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"muuten\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"muuten jos\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"jos\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Jos arvo on tosi, suorita lauseke.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Jos arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten suorita toinen lohko lausekkeita.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Jos ensimmäinen arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten, jos toinen arvo on tosi, suorita toinen lohko lausekkeita.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Jos ensimmäinen arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten, jos toinen arvo on tosi, suorita toinen lohko lausekkeita. Jos mikään arvoista ei ole tosi, suorita viimeinen lohko lausekkeita.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"tee\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"toista %1 kertaa\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"toista\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"kertaa\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Suorita joukko lausekkeita useampi kertaa.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"toista kunnes\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"toista niin kauan kuin\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Niin kauan kuin arvo on epätosi, suorita joukko lausekkeita.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Niin kauan kuin arvo on tosi, suorita joukko lausekkeita.\";\nBlockly.Msg.DELETE_BLOCK = \"Poista lohko\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Poista %1 lohkoa\";\nBlockly.Msg.DISABLE_BLOCK = \"Passivoi lohko\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Kopioi\";\nBlockly.Msg.ENABLE_BLOCK = \"Aktivoi lohko\";\nBlockly.Msg.EXPAND_ALL = \"Laajenna lohkot\";\nBlockly.Msg.EXPAND_BLOCK = \"Laajenna lohko\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Ulkoiset syötteet\";\nBlockly.Msg.HELP = \"Apua\";\nBlockly.Msg.INLINE_INPUTS = \"Tuo syötteet\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"Luo tyhjä lista\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Palauta tyhjä lista, pituus 0\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Listää, poista tai järjestele uudestaan osioita tässä lohkossa.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"luo lista\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Lisää kohde listaan.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Luo lista, jossa on mikä tahansa määrä kohteita.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"ensimmäinen\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"nro (lopusta laskien)\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"nro\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"hae\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"hae ja poista\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"viimeinen\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"satunnainen\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"poista\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Palauta ensimmäinen kohde listalta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Palauta kohde annetusta kohdasta listaa. Numero 1 tarkoittaa listan viimeistä kohdetta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Palauta kohde annetusta kohdasta listaa. Numero 1 tarkoittaa listan ensimmäistä kohdetta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Palauttaa listan viimeisen kohteen.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Palauttaa satunnaisen kohteen listalta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Poistaa ja palauttaa ensimmäisen kohteen listalta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Poistaa ja palauttaa kohteen annetusta kohden listaa. Nro 1 on ensimmäinen kohde.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Poistaa ja palauttaa kohteen annetusta kohden listaa. Nro 1 on ensimmäinen kohde.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Poistaa ja palauttaa viimeisen kohteen listalta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Poistaa ja palauttaa satunnaisen kohteen listalta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Poistaa ensimmäisen kohteen listalta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Poistaa kohteen listalta annetusta kohtaa. Nro 1 on viimeinen kohde.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Poistaa kohteen listalta annetusta kohtaa. Nro 1 on ensimmäinen kohde.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Poistaa viimeisen kohteen listalta.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Poistaa satunnaisen kohteen listalta.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"päättyen kohtaan (lopusta laskien)\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"päättyen kohtaan\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"viimeinen\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"hae osalista alkaen alusta\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"hae osalista alkaen kohdasta (lopusta laskien)\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"hae osalista alkaen kohdasta\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Luo kopio määrätystä kohden listaa.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"etsi ensimmäinen esiintymä kohteelle\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"etsi viimeinen esiintymä kohteelle\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Palauttaa kohteen ensimmäisen/viimeisen esiintymän kohdan. Palauttaa 0 jos tekstiä ei löydy.\";\nBlockly.Msg.LISTS_INLIST = \"listassa\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 on tyhjä\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"%1:n pituus\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Palauttaa listan pituuden.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"luo lista, jossa kohde %1 toistuu %2 kertaa\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Luo listan, jossa annettu arvo toistuu määrätyn monta kertaa.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"kohteeksi\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"lisää kohtaan\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"aseta\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Lisää kohteen listan kärkeen.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Lisää kohteen annettuun kohtaan listaa. Nro 1 on listan häntä.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Lisää kohteen listan annettuun kohtaan. Nro 1 on listan kärki.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Lisää kohteen listan loppuun.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Lisää kohteen satunnaiseen kohtaan listassa.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Asettaa listan ensimmäisen kohteen.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Asettaa listan määrätyssä kohtaa olevan kohteen. Nro 1 on listan loppu.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Asettaa kohteen määrättyyn kohtaa listassa. Nro 1 on listan alku.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Asettaa listan viimeisen kohteen.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Asettaa satunnaisen kohteen listassa.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Palauttaa tosi, jos lista on tyhjä.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"epätosi\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Palauttaa joko tosi tai epätosi.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"tosi\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://fi.wikipedia.org/wiki/Ep%C3%A4yht%C3%A4l%C3%B6\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Palauta tosi, jos syötteet ovat keskenään samat.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Palauttaa tosi, jos ensimmäinen syöte on suurempi, kuin toinen.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Palauttaa tosi, jos ensimmäinen syöte on suurempi tai yhtä suuri, kuin toinen.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Palauttaa tosi, jos ensimmäinen syöte on pienempi, kuin toinen.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Palauttaa tosi, jos ensimmäinen syöte on pienempi tai yhtä suuri, kuin toinen.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Palauttaa tosi, jos syötteet eivät ole keskenään samoja.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"ei %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Palauttaa tosi, jos syöte on epätosi. Palauttaa epätosi, jos syöte on tosi.\";\nBlockly.Msg.LOGIC_NULL = \"ei mitään\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Palauttaa \\\"ei mitään\\\"-arvon.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"ja\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"tai\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Palauttaa tosi, jos kummatkin syötteet ovat tosia.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Palauttaa tosi, jos ainakin yksi syötteistä on tosi.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"ehto\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"jos epätosi\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"jos tosi\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Tarkistaa testin ehdon. Jos ehto on tosi, palauttaa \\\"jos tosi\\\" arvon, muuten palauttaa \\\"jos epätosi\\\" arvon.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"http://fi.wikipedia.org/wiki/Aritmetiikka\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Palauttaa kahden luvun summan.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Palauttaa jakolaskun osamäärän.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Palauttaa kahden luvun erotuksen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Palauttaa kertolaskun tulon.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Palauttaa ensimmäisen luvun korotettuna toisen luvun potenssiin.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://fi.wikipedia.org/wiki/Yhteenlasku\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"arvolla\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"muuta\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Lisää arvo muuttujaan '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Palauttaa jonkin seuraavista vakioista: π (3.141…), e (2.718…), φ (1.618…), neliöjuuri(2) (1.414…), neliöjuuri(½) (0.707…), or ∞ (ääretön).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"rajoita %1 vähintään %2 enintään %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Rajoittaa arvon annetulle suljetulle välille.\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"on jaollinen luvulla\";\nBlockly.Msg.MATH_IS_EVEN = \"on parillinen\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"on negatiivinen\";\nBlockly.Msg.MATH_IS_ODD = \"on pariton\";\nBlockly.Msg.MATH_IS_POSITIVE = \"on positiivinen\";\nBlockly.Msg.MATH_IS_PRIME = \"on alkuluku\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Tarkistaa onko numero parillinen, pariton, alkuluku, kokonaisluku, positiivinen, negatiivinen, tai jos se on jaollinen toisella luvulla. Palauttaa tosi tai epätosi.\";\nBlockly.Msg.MATH_IS_WHOLE = \"on kokonaisluku\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"%1 ÷ %2 jakojäännös\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Palauttaa jakolaskun jakojäännöksen.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"⋅\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://fi.wikipedia.org/wiki/Luku\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Luku.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"keskiarvo luvuista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"suurin luvuista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"keskiluku luvuista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"pienin luvuista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"tyyppiarvo luvuista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"satunnainen valinta luvuista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"keskihajonta luvuista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"summa luvuista\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Palauttaa aritmeettisen keskiarvon annetuista luvuista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Palauttaa suurimman annetuista luvuista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Palauttaa annettujen lukujen keskiluvun.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Palauttaa pienimmän annetuista luvuista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Palauttaa luettelon yleisimmistä luvuista annetussa listassa.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Palauttaa satunnaisesti valitun luvun annetuista luvuista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Palauttaa annettujen lukujen keskihajonnan.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Palauttaa kaikkien annettujen lukujen summan.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://fi.wikipedia.org/wiki/Satunnaisluku\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"satunnainen murtoluku\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Palauttaa satunnaisen luvun oikealta puoliavoimesta välistä [0.0, 1.0).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://fi.wikipedia.org/wiki/Satunnaisluku\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"Palauttaa satunnaisen kokonaisluvun väliltä %1-%2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Palauttaa satunnaisen kokonaisluvun kahden annetun arvon suljetulta väliltä.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://fi.wikipedia.org/wiki/Py%C3%B6rist%C3%A4minen\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"pyöristä\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"pyöristä alaspäin\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"pyöristä ylöspäin\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Pyöristää luvun ylös- tai alaspäin.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://fi.wikipedia.org/wiki/Neli%C3%B6juuri\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"itseisarvo\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"neliöjuuri\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Palauttaa luvun itseisarvon.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Palauttaa e potenssiin luku.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Palauttaa luvun luonnollisen logaritmin.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Palauttaa luvun kymmenkantaisen logaritmin.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Palauttaa numeron vastaluvun.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Palauttaa 10 potenssiin luku.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Palauttaa luvun neliöjuuren.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://fi.wikipedia.org/wiki/Trigonometrinen_funktio\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Palauttaa luvun arkuskosinin.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Palauttaa luvun arkussinin.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Palauttaa luvun arkustangentin.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Palauttaa asteluvun (ei radiaanin) kosinin.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Palauttaa asteluvun (ei radiaanin) sinin.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Palauttaa asteluvun (ei radiaanin) tangentin.\";\nBlockly.Msg.NEW_VARIABLE = \"Uusi muuttuja...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Uuden muuttujan nimi:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"parametrit:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://fi.wikipedia.org/wiki/Aliohjelma\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Suorittaa käyttäjän määrittelemä funktio '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://fi.wikipedia.org/wiki/Aliohjelma\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Suorittaa käyttäjän määrittelemän funktion '%1' ja käyttää sen tuotosta.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Luo '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"tee jotain\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"tehdäksesi\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Luo funktio, jolla ei ole tuotosta.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"palauta\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Luo funktio, jolla ei ole tuotosta.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Varoitus: tällä funktiolla on sama parametri useamman kerran.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Korosta funktion määritelmä\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Jos arvo on tosi, palauta toinen arvo.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Varoitus: tätä lohkoa voi käyttää vain funktion määrityksessä.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"syötteen nimi:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"syötteet\";\nBlockly.Msg.REMOVE_COMMENT = \"Poista kommentti\";\nBlockly.Msg.RENAME_VARIABLE = \"Nimeä uudelleen muuttuja...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Nimeä uudelleen kaikki '%1' muuttujaa:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"lisää teksti\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"muuttujaan\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Lisää tekstiä muuttujaan '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"pienet kirjaimet\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"isot alkukirjaimet\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"isot kirjaimet\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Palauttaa kopion tekstistä eri kirjainkoossa.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"hae ensimmäinen kirjain\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"Hae kirjain nro (lopusta laskien)\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"Hae kirjain nro\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"tekstistä\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"hae viimeinen kirjain\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"hae satunnainen kirjain\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Palauttaa annetussa kohdassa olevan kirjaimen.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Lisää kohteen tekstiin.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"liitä\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Lisää, poista tai uudelleen järjestä osioita tässä lohkossa.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"kirjaimeen nro (lopusta laskien)\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"kirjaimeen nro\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"viimeiseen kirjaimeen\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"merkkijonosta\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"hae osa alkaen ensimmäisestä kirjaimesta\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"hae osa alkaen kirjaimesta nro (lopusta laskien)\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"hae osa alkaen kirjaimesta nro\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Palauttaa määrätyn osan tekstistä.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"tekstistä\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"etsi ensimmäinen esiintymä merkkijonolle\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"etsi viimeinen esiintymä merkkijonolle\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Palauttaa ensin annetun tekstin ensimmäisen/viimeisen esiintymän osoitteen toisessa tekstissä. Palauttaa osoitteen 0 jos tekstiä ei löytynyt.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 on tyhjä\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Palauttaa tosi, jos annettu teksti on tyhjä.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"luo teksti\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Luo merkkijonon liittämällä yhteen minkä tahansa määrän kohteita.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"%1:n pituus\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Palauttaa annetussa tekstissä olevien merkkien määrän (välilyönnit mukaan lukien).\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"tulosta %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Tulostaa annetun tekstin, numeron tia muun arvon.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Kehottaa käyttäjää syöttämään numeron.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Kehottaa käyttäjää syöttämään tekstiä.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"käyttäen annettua viestiä, kehottaa syöttämään numeron\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"käyttäen annettua viestiä, kehottaa syöttämään tekstiä\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://fi.wikipedia.org/wiki/Merkkijono\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Kirjain, sana tai rivi tekstiä.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"poistaa välilyönnit kummaltakin puolelta\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"poistaa välilyönnit vasemmalta puolelta\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"poistaa välilyönnit oikealta puolelta\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Palauttaa kopion tekstistä siten, että välilyönnit on poistettu yhdestä tai molemmista päistä.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"kohde\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Luo 'aseta %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Palauttaa muuttujan arvon.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Luo 'hae %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"arvoksi\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"aseta\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Asettaa muutujan arvoksi annetun syötteen.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/fr.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.fr');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Ajouter un commentaire\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Modifier la valeur :\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Réduire les blocs\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Réduire le bloc\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"couleur 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"couleur 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"ratio\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"mélanger\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Mélange deux couleurs ensemble avec un ratio donné (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://fr.wikipedia.org/wiki/Couleur\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Choisir une couleur dans la palette\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"couleur aléatoire\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Choisir une couleur au hasard.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"bleu\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"vert\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"rouge\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"colorer avec\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Créer une couleur avec la quantité spécifiée de rouge, vert et bleu. Toutes les valeurs doivent être entre 0 et 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"sortir de la boucle\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continuer avec la prochaine itération de la boucle\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Sortir de la boucle englobante.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Sauter le reste de cette boucle, et poursuivre avec l’itération suivante.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Attention : Ce bloc ne devrait être utilisé que dans une boucle.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each pour chaque bloc\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"dans la liste\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"pour chaque élément\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Pour chaque élément dans une liste, donner la valeur de l’élément à la variable '%1', puis exécuter certains ordres.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"de %1 à %2 par %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"compter avec\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Faire en sorte que la variable %1 prenne les valeurs depuis le numéro de début jusqu’au numéro de fin, en s’incrémentant de l’intervalle spécifié, et exécuter les ordres spécifiés.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Ajouter une condition au bloc si.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Ajouter une condition finale fourre-tout au bloc si.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Ajouter, supprimer ou réordonner les sections pour reconfigurer ce bloc si.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"sinon\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"sinon si\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"si\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Si une valeur est vraie, alors exécuter certains ordres.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Si une valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, exécuter le second bloc d’ordres.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Si la première valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, si la seconde valeur est vraie, exécuter le second bloc d’ordres.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Si la première valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, si la seconde valeur est vraie, exécuter le second bloc d’ordres. Si aucune des valeurs n’est vraie, exécuter le dernier bloc d’ordres.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"faire\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"répéter %1 fois\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"répéter\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"fois\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Exécuter certains ordres plusieurs fois.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"répéter jusqu’à\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"répéter tant que\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Tant qu’une valeur est fausse, alors exécuter certains ordres.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Tant qu’une valeur est vraie, alors exécuter certains ordres.\";\nBlockly.Msg.DELETE_BLOCK = \"Supprimer le bloc\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Supprimer %1 blocs\";\nBlockly.Msg.DISABLE_BLOCK = \"Désactiver le bloc\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Dupliquer\";\nBlockly.Msg.ENABLE_BLOCK = \"Activer le bloc\";\nBlockly.Msg.EXPAND_ALL = \"Développer les blocs\";\nBlockly.Msg.EXPAND_BLOCK = \"Développer le bloc\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Entrées externes\";\nBlockly.Msg.HELP = \"Aide\";\nBlockly.Msg.INLINE_INPUTS = \"Entrées en ligne\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"créer une liste vide\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Renvoyer une liste, de longueur 0, ne contenant aucun enregistrement\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"liste\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Ajouter, supprimer, ou réordonner les sections pour reconfigurer ce bloc de liste.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"créer une liste avec\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Ajouter un élément à la liste.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Créer une liste avec un nombre quelconque d’éléments.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"premier\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# depuis la fin\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"obtenir\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"obtenir et supprimer\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"dernier\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"aléatoire\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"supprimer\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Renvoie le premier élément dans une liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Renvoie l’élément à la position indiquée dans une liste. #1 est le dernier élément.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Renvoie l’élément à la position indiquée dans une liste. #1 est le premier élément.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Renvoie le dernier élément dans une liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Renvoie un élément au hasard dans une liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Supprime et renvoie le premier élément dans une liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Supprime et renvoie l’élément à la position indiquée dans une liste. #1 est le dernier élément.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Supprime et renvoie l’élément à la position indiquée dans une liste. #1 est le premier élément.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Supprime et renvoie le dernier élément dans une liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Supprime et renvoie un élément au hasard dans une liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Supprime le premier élément dans une liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Supprime l’élément à la position indiquée dans une liste. #1 est le dernier élément.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Supprime l’élément à la position indiquée dans une liste. #1 est le premier élément.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Supprime le dernier élément dans une liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Supprime un élément au hasard dans une liste.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"jusqu’à # depuis la fin\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"jusqu’à #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"jusqu’à la fin\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"obtenir la sous-liste depuis le début\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"obtenir la sous-liste depuis # depuis la fin\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"obtenir la sous-liste depuis #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Crée une copie de la partie spécifiée d’une liste.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"trouver la première occurrence de l’élément\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"trouver la dernière occurrence de l’élément\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Renvoie l’index de la première/dernière occurrence de l’élément dans la liste. Renvoie 0 si le texte n’est pas trouvé.\";\nBlockly.Msg.LISTS_INLIST = \"dans la liste\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 est vide\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"longueur de %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Renvoie la longueur d’une liste.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"créer une liste avec l’élément %1 répété %2 fois\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Crée une liste consistant en la valeur fournie répétée le nombre de fois indiqué.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"comme\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"insérer en\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"mettre\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Insère l’élément au début d’une liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Insère l’élément à la position indiquée dans une liste. #1 est le dernier élément.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Insère l’élément à la position indiquée dans une liste. #1 est le premier élément.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Ajouter l’élément à la fin d’une liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Insère l’élément au hasard dans une liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Fixe le premier élément dans une liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Fixe l’élément à la position indiquée dans une liste. #1 est le dernier élément.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Fixe l’élément à la position indiquée dans une liste. #1 est le premier élément.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Fixe le dernier élément dans une liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Fixe un élément au hasard dans une liste.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Renvoie vrai si la liste est vide.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"faux\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Renvoie soit vrai soit faux.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"vrai\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Renvoyer vrai si les deux entrées sont égales.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Renvoyer vrai si la première entrée est plus grande que la seconde.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Renvoyer vrai si la première entrée est plus grande ou égale à la seconde.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Renvoyer vrai si la première entrée est plus petite que la seconde.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Renvoyer vrai si la première entrée est plus petite ou égale à la seconde.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Renvoyer vrai si les deux entrées ne sont pas égales.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"pas %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Renvoie vrai si l’entrée est fausse. Renvoie faux si l’entrée est vraie.\";\nBlockly.Msg.LOGIC_NULL = \"nul\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Renvoie nul.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"et\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"ou\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Renvoyer vrai si les deux entrées sont vraies.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Renvoyer vrai si au moins une des entrées est vraie.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"si faux\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"si vrai\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Vérifier la condition dans 'test'. Si elle est vraie, renvoie la valeur 'si vrai' ; sinon renvoie la valeur 'si faux'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Renvoie la somme des deux nombres.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Renvoie le quotient des deux nombres.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Renvoie la différence des deux nombres.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Renvoie le produit des deux nombres.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Renvoie le premier nombre élevé à la puissance du second.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"de\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"incrémenter\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Ajouter un nombre à la variable '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Renvoie une des constantes courantes : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infini).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"contraindre %1 entre %2 et %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Contraindre un nombre à être entre les limites spécifiées (incluses).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"est divisible par\";\nBlockly.Msg.MATH_IS_EVEN = \"est pair\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"est négatif\";\nBlockly.Msg.MATH_IS_ODD = \"est impair\";\nBlockly.Msg.MATH_IS_POSITIVE = \"est positif\";\nBlockly.Msg.MATH_IS_PRIME = \"est premier\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Vérifier si un nombre est pair, impair, premier, entier, positif, négatif, ou s’il est divisible par un certain nombre. Renvoie vrai ou faux.\";\nBlockly.Msg.MATH_IS_WHOLE = \"est entier\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"reste de %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Renvoyer le reste de la division des deux nombres.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Un nombre.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"moyenne de la liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"maximum de la liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"médiane de la liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minimum de la liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"majoritaires de la liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"élément aléatoire de la liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"écart-type de la liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"somme de la liste\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Renvoyer la moyenne (arithmétique) des valeurs numériques dans la liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Renvoyer le plus grand nombre dans la liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Renvoyer le nombre médian dans la liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Renvoyer le plus petit nombre dans la liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Renvoyer une liste des élément(s) le(s) plus courant(s) dans la liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Renvoyer un élément dans la liste au hasard.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Renvoyer l’écart-type de la liste.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Renvoyer la somme de tous les nombres dans la liste.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"fraction aléatoire\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Renvoyer une fraction aléatoire entre 0.0 (inclus) et 1.0 (exclus).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"entier aléatoire entre %1 et %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Renvoyer un entier aléatoire entre les deux limites spécifiées, incluses.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"arrondir\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"arrondir à l’inférieur\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"arrondir au supérieur\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Arrondir un nombre au-dessus ou au-dessous.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolu\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"racine carrée\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Renvoie la valeur absolue d’un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Renvoie e à la puissance d’un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Renvoie le logarithme naturel d’un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Renvoie le logarithme base 10 d’un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Renvoie l’opposé d’un nombre\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Renvoie 10 à la puissance d’un nombre.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Renvoie la racine carrée d’un nombre.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Renvoie l’arccosinus d’un nombre.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Renvoie l’arcsinus d’un nombre.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Renvoie l’arctangente d’un nombre.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Renvoie le cosinus d’un angle en degrés (pas en radians).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Renvoie le sinus d’un angle en degrés (pas en radians).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Renvoie la tangente d’un angle en degrés (pas en radians).\";\nBlockly.Msg.NEW_VARIABLE = \"Nouvelle variable…\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nom de la nouvelle variable :\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"avec :\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Exécuter la fonction '%1' définie par l’utilisateur.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Exécuter la fonction '%1' définie par l’utilisateur et utiliser son résultat.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Créer '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"faire quelque chose\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"à\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Crée une fonction sans sortie.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"retour\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Crée une fonction avec une sortie.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Attention : Cette fonction a des paramètres dupliqués.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Surligner la définition de la fonction\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Si une valeur est vraie, alors renvoyer une seconde valeur.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Attention : Ce bloc pourrait n’être utilisé que dans une définition de fonction.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nom de l’entrée :\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"entrées\";\nBlockly.Msg.REMOVE_COMMENT = \"Supprimer un commentaire\";\nBlockly.Msg.RENAME_VARIABLE = \"Renommer la variable…\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Renommer toutes les variables '%1' en :\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"ajouter le texte\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"à\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Ajouter du texte à la variable '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"en minuscules\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"en Majuscule Au Début De Chaque Mot\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"en MAJUSCULES\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Renvoyer une copie du texte dans une autre casse.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"obtenir la première lettre\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"obtenir la lettre # depuis la fin\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"obtenir la lettre #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"dans le texte\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"obtenir la dernière lettre\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"obtenir une lettre au hasard\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Renvoie la lettre à la position indiquée.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Ajouter un élément au texte.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"joindre\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Ajouter, supprimer, ou réordonner des sections pour reconfigurer ce bloc de texte.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"jusqu’à la lettre # depuis la fin\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"jusqu’à la lettre #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"jusqu’à la dernière lettre\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"dans le texte\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"obtenir la sous-chaîne depuis la première lettre\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"obtenir la sous-chaîne depuis la lettre # depuis la fin\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"obtenir la sous-chaîne depuis la lettre #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Renvoie une partie indiquée du texte.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"dans le texte\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"trouver la première occurrence de la chaîne\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"trouver la dernière occurrence de la chaîne\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Renvoie l’index de la première/dernière occurrence de la première chaîne dans la seconde. Renvoie 0 si la chaîne n’est pas trouvée.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 est vide\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Renvoie vrai si le texte fourni est vide.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"créer le texte avec\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Créer un morceau de texte en agrégeant un nombre quelconque d’éléments.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"longueur de %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Renvoie le nombre de lettres (espaces compris) dans le texte fourni.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"afficher %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Afficher le texte, le nombre ou une autre valeur spécifié.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Demander un nombre à l’utilisateur.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Demander un texte à l’utilisateur.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"invite pour un nombre avec un message\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"invite pour un texte avec un message\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Une lettre, un mot ou une ligne de texte.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"supprimer les espaces des deux côtés\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"supprimer les espaces du côté gauche\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"supprimer les espaces du côté droit\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Renvoyer une copie du texte avec les espaces supprimés d’un bout ou des deux.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"élément\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Créer 'fixer %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Renvoie la valeur de cette variable.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Créer 'obtenir %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"à\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"fixer\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Fixe cette variable pour qu’elle soit égale à la valeur de l’entrée.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/he.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.he');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"הוסף תגובה\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"שנה ערך:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"צמצם קטעי קוד\";\nBlockly.Msg.COLLAPSE_BLOCK = \"צמצם קטע קוד\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"צבע 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"צבע 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"יחס\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"ערבב\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"מערבב שני צבעים יחד עם יחס נתון(0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"http://he.wikipedia.org/wiki/%D7%A6%D7%91%D7%A2\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"בחר צבע מן הצבעים.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"צבע אקראי\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"בחר צבא אקראי.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"כחול\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"ירוק\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"אדום\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"צבע עם\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"צור צבע עם הסכום המצוין של אדום, ירוק וכחול. כל הערכים חייבים להיות בין 0 ל100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"צא מהלולאה\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"המשך עם האיטרציה הבאה של הלולאה\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"צא אל מחוץ ללולאה הכוללת.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"דלג על שאר הלולאה והמשך עם האיטרציה הבאה.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"אזהרה: בלוק זה עשוי לשמש רק בתוך לולאה.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"ברשימה\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"לכל פריט\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"הגדר את המשתנה '%1' לכל פריט ברשימה, ולאחר מכן בצע כמה חישובים.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"מ- %1 ל- %2 עד- %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"תספור עם\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"תוסיף תנאי לבלוק If.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"לסיום, כל התנאים תקפים לגבי בלוק If.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"תוסיף, תמחק, או תסדר מחדש כדי להגדיר מחדש את הבלוק If.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"אחרת\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"אחרת אם\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"אם\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"אם ערך נכון, בצע מספר חישובים.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"אם הערך נכון, אז תבצע את הבלוק הראשון של הצהרות. אחרת, בצע את הבלוק השני של הצהרות.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"אם הערך הראשון שווה לנכון, אז בצע את הבלוק הראשון של הצהרות. אחרת, אם הערך השני נכון, בצע את הבלוק השני של הצהרות.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"אם הערך הראשון נכון, אז תבצע את הבלוק הראשון של הצהרות. אחרת, אם הערך השני נכון, בצע את הבלוק השני של הצהרות. אם אף אחד מהם לא נכון, בצע את הבלוק האחרון של הצהרות.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"http://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"תעשה\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"חזור על הפעולה %1 פעמים\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"חזור\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"פעמים\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"תעשה כמה פעולות מספר פעמים.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"חזור עד ש...\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"חזור כל עוד\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"בזמן שהערך שווה לשגוי, תעשה מספר חישובים.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"בזמן שהערך שווה לשגוי, תעשה מספר חישובים.\";\nBlockly.Msg.DELETE_BLOCK = \"מחק קטע קוד\";\nBlockly.Msg.DELETE_X_BLOCKS = \"מחק %1 קטעי קוד\";\nBlockly.Msg.DISABLE_BLOCK = \"נטרל קטע קוד\";\nBlockly.Msg.DUPLICATE_BLOCK = \"שכפל\";\nBlockly.Msg.ENABLE_BLOCK = \"הפעל קטע קוד\";\nBlockly.Msg.EXPAND_ALL = \"הרחב קטעי קוד\";\nBlockly.Msg.EXPAND_BLOCK = \"הרחב קטע קוד\";\nBlockly.Msg.EXTERNAL_INPUTS = \"קלטים חיצוניים\";\nBlockly.Msg.HELP = \"עזרה\";\nBlockly.Msg.INLINE_INPUTS = \"קלטים פנימיים\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"צור רשימה ריקה\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"החזר רשימה,באורך 0, המכילה רשומות נתונים\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"רשימה\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"תוסיף, תמחק, או תסדר מחדש כדי להגדיר מחדש את הבלוק If.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"צור רשימה עם\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"הוסף פריט לרשימה.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"צור רשימה עם כל מספר של פריטים.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"ראשון\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# מהסוף\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"לקבל\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"קבל ומחק\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"אחרון\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"אקראי\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"הסרה\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"מחזיר את הפריט הראשון ברשימה.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"מחזיר פריט במיקום שצוין ברשימה. #1 הוא הפריט האחרון.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"מחזיר פריט במיקום שצוין ברשימה. #1 הוא הפריט הראשון.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"מחזיר את הפריט האחרון ברשימה.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"מחזיר פריט אקראי מהרשימה.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"מסיר ומחזיר את הפריט הראשון ברשימה.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"מסיר ומחזיר את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט האחרון.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"מסיר ומחזיר את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט הראשון.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"מסיר ומחזיר את הפריט האחרון ברשימה.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"מחק והחזר פריט אקראי מהרשימה.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"הסר את הפריט הראשון ברשימה.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"מחזיר פריט במיקום שצוין ברשימה. #1 הוא הפריט האחרון.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"מחזיר פריט במיקום שצוין ברשימה. #1 הוא הפריט הראשון.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"הסר את הפריט הראשון ברשימה.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"הסר פריט אקראי ברשימה.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"ל # מהסוף\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"ל #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"לאחרון\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"get sub-list from first\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"מחזירה חלק מהרשימה החל מ-# עד הסוף\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"מחזירה חלק מהרשימה החל מ-#\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"יוצרת עותק של חלק מסוים מהרשימה.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"מחזירה את המיקום הראשון של פריט ברשימה\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"מחזירה את המיקום האחרון של פריט ברשימה\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"מחזירה את האינדקס של המופע ראשון/אחרון של הפריט ברשימה.  מחזירה 0 אם טקסט אינו נמצא.\";\nBlockly.Msg.LISTS_INLIST = \"ברשימה\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 הוא ריק\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"אורכו של %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"מחזירה את האורך של רשימה.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"ליצור רשימה עם הפריט %1 %2 פעמים\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"יוצר רשימה המורכבת מהערך נתון חוזר מספר פעמים שצוין.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"כמו\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"הכנס ב\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"הגדר\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"מכניס את הפריט בתחילת רשימה.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"מכניס את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט האחרון.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"מכניס את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט הראשון.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"מוסיף את הפריט בסוף רשימה.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"הוסף פריט באופן אקראי ברשימה.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"מגדיר את הפריט הראשון ברשימה.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"מגדיר את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט האחרון.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"מגדיר את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט הראשון.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"מגדיר את הפריט האחרון ברשימה.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"מגדיר פריט אקראי ברשימה.\";\nBlockly.Msg.LISTS_TOOLTIP = \"מחזיר אמת אם הרשימה ריקה.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"שגוי\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"תחזיר אם נכון או אם שגוי.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"נכון\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"http://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"תחזיר נכון אם שני הקלטים שווים אחד לשני.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"תחזיר נכון אם הקלט הראשון גדול יותר מהקלט השני.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"תחזיר נכון אם הקלט הראשון גדול יותר או שווה לכניסה השנייה.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"תחזיר אמת (true) אם הקלט הראשון הוא קטן יותר מאשר הקלט השני.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"תחזיר אמת אם הקלט הראשון הוא קטן יותר או שווה לקלט השני.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"תחזיר אמת אם שני הקלטים אינם שווים זה לזה.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"לא %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returns true if the input is false.  Returns false if the input is true.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"http://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"תחזיר ריק.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"ו\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"או\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"תחזיר נכון אם שני הקלטים נכונים.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"תחזיר נכון אם מתקיים לפחות אחד מהקלטים נכונים.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"בדיקה\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"http://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"אם שגוי\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"אם נכון\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"בדוק את התנאי ב'מבחן'. אם התנאי נכון, תחזיר את הערך 'אם נכון'; אחרת תחזיר את הערך 'אם שגוי'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"http://he.wikipedia.org/wiki/%D7%90%D7%A8%D7%99%D7%AA%D7%9E%D7%98%D7%99%D7%A7%D7%94\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"תחזיר את סכום שני המספרים.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Return the quotient of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Return the difference of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Return the product of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Return the first number raised to the power of the second number.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"by\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"שנה\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"הוסף מספר למשתנה '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"http://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"מתחלק ב\";\nBlockly.Msg.MATH_IS_EVEN = \"זוגי\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"שלילי\";\nBlockly.Msg.MATH_IS_ODD = \"אי-זוגי\";\nBlockly.Msg.MATH_IS_POSITIVE = \"חיובי\";\nBlockly.Msg.MATH_IS_PRIME = \"ראשוני\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";\nBlockly.Msg.MATH_IS_WHOLE = \"שלם\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"http://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"שארית החילוק %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"החזרת השארית מחלוקת שני המספרים.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"http://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"מספר.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"ממוצע של רשימה\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"מקסימום של רשימה\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"median of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"מינימום של רשימה\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modes of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"פריט אקראי מרשימה\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standard deviation of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"סכום של רשימה\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Return the average (arithmetic mean) of the numeric values in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"תחזיר את המספר הגדול ביותר ברשימה.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"תחזיר את המספר החיצוני ביותר ברשימה.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"תחזיר את המספר הקטן ביותר ברשימה.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Return a list of the most common item(s) in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"תחזיר רכיב אקראי מרשימה.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Return the standard deviation of the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Return the sum of all the numbers in the list.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"http://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"random fraction\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"http://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"random integer from %1 to %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Return a random integer between the two specified limits, inclusive.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"http://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"עיגול\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"עיגול למטה\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"עיגול למעלה\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Round a number up or down.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"http://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"ערך מוחלט\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"square root\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Return the absolute value of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Return e to the power of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Return the natural logarithm of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Return the base 10 logarithm of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Return the negation of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Return 10 to the power of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Return the square root of a number.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"http://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Return the arccosine of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Return the arcsine of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Return the arctangent of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Return the cosine of a degree (not radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Return the sine of a degree (not radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Return the tangent of a degree (not radian).\";\nBlockly.Msg.NEW_VARIABLE = \"משתנה חדש...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"שם המשתנה החדש:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"with:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Run the user-defined function '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Run the user-defined function '%1' and use its output.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Create '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"do something\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"to\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Creates a function with no output.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"return\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Creates a function with an output.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Warning: This function has duplicate parameters.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Highlight function definition\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"If a value is true, then return a second value.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Warning: This block may be used only within a function definition.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"שם הקלט:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"מקורות קלט\";\nBlockly.Msg.REMOVE_COMMENT = \"הסר הערה\";\nBlockly.Msg.RENAME_VARIABLE = \"שנה את שם המשתנה...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"שנה את שם כל '%1' המשתנים ל:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"append text\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"to\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Append some text to variable '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"to lower case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"to Title Case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"to UPPER CASE\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"get first letter\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"get letter # from end\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"get letter #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"in text\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"get last letter\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"get random letter\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returns the letter at the specified position.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Add an item to the text.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"join\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"to letter # from end\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"to letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"to last letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"in text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"get substring from first letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"get substring from letter # from end\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"get substring from letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"in text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"find first occurrence of text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"find last occurrence of text\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 is empty\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returns true if the provided text is empty.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"create text with\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Create a piece of text by joining together any number of items.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"length of %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returns the number of letters (including spaces) in the provided text.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"print %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Print the specified text, number or other value.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Prompt for user for a number.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Prompt for user for some text.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"prompt for number with message\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"prompt for text with message\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"http://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"A letter, word, or line of text.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"למחוק רווחים משני הקצוות\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"למחוק רווחים מימין\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"למחוק רווחים משמאל\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Return a copy of the text with spaces removed from one or both ends.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"פריט\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Create 'set %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returns the value of this variable.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create 'get %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"to\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Sets this variable to be equal to the input.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/hi.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.hi');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"टिप्पणी छोड़ें\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"मान परिवर्तित करें:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"ब्लॉक संक्षिप्त करें\";\nBlockly.Msg.COLLAPSE_BLOCK = \"ब्लॉक को संक्षिप्त करें\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"रंग 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"रंग 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"अनुपात\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"मिश्रण करें\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"दिए गए अनुपात (0.0 - 1.0) के साथ दो रंगों का मिश्रण करता है।\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"पैलेट से एक रंग चुनें।\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"रैन्डम रंग\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"रैन्डम्ली एक रंग चयन करें।\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"नीला\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"हरा\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"लाल\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"इसके साथ रंग करें\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Create a colour with the specified amount of red, green, and blue.  All values must be between 0 and 100.\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"लूप से बाहर निकलें\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"लूप का अगला आईटरेशन जारी रखें\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"भीतरी लूप से बाहर निकलें।\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"बाकी बचे लूप को छोड़ें, और अगला आईटरेशन जारी रखें।\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"सावधान: ये ब्लॉक केवल लूप के अंदर इस्तेमाल किया जा सकता है।\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"सूची में\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"प्रत्येक आइटम के लिए\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"For each item in a list, set the variable '%1' to the item, and then do some statements.\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"from %1 to %2 by %3\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"काउंट करें\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"यदि ब्लॉक मे एक शर्त जोड़ें।\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Add a final, catch-all condition to the if block.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this if block.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"एल्स\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"एल्स इफ\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"इफ\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"यदी मान ट्रू है, तो कुछ स्टेट्मेंट्स चलाएँ।\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"If a value is true, then do the first block of statements.  Otherwise, do the second block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.  If none of the values are true, do the last block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"डू\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1 बार दोहराएँ\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"दोहराएँ\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"इतनी बार\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"कुछ स्टेट्मन्ट कई बार चलाएँ।\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"दोहराएँ जब तक\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"दोहराएँ जब कि\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"जब तक मान फॉल्स है, तब तक कुछ स्टेट्मेंट्स चलाएँ।\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"जब तक मान ट्रू है, तब तक कुछ स्टेट्मेंट्स चलाएँ।\";\nBlockly.Msg.DELETE_BLOCK = \"ब्लॉक हटाएँ\";\nBlockly.Msg.DELETE_X_BLOCKS = \"%1 ब्लॉक हटाएँ\";\nBlockly.Msg.DISABLE_BLOCK = \"ब्लॉक को अक्षम करें\";\nBlockly.Msg.DUPLICATE_BLOCK = \"कॉपी करें\";\nBlockly.Msg.ENABLE_BLOCK = \"ब्लॉक को सक्षम करें\";\nBlockly.Msg.EXPAND_ALL = \"ब्लॉक विस्तार करें\";\nBlockly.Msg.EXPAND_BLOCK = \"ब्लॉक का विस्तार करें\";\nBlockly.Msg.EXTERNAL_INPUTS = \"बाहरी इनपुट\";\nBlockly.Msg.HELP = \"सहायता\";\nBlockly.Msg.INLINE_INPUTS = \"इनलाइन इनपुट\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"खाली सूची बनाएँ\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returns a list, of length 0, containing no data records\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"सूची\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this list block.\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"इसके सूची बनाएँ\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"सूची मे एक आइटम जोड़ें।\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"कितने भी आइटम वाली एक सूची बनाएँ।\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"पहला\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"अंत से #\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"get\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"get and remove\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"आखिरी\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"रैन्डम\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"निकालें\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"सूची का पहला आइटम रिटर्न करता है।\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"सूची का आखरी आइटम रिटर्न करता है।\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"सूची से रैन्डम आइटम रिटर्न करता है।\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"सूची का पहला आइटम निकालता है और रिटर्न करता है।\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Removes and returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Removes and returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"सूची का आखरी आइटम निकालता है और रिटर्न करता है।\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"सूची से रैन्डम आइटम निकालता है और रिटर्न करता है।\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"सूची का पहला आइटम निकालता है।\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Removes the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Removes the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"सूची का आखरी आइटम निकालता है।\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"सूची से रैन्डम आइटम निकालता है।\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"to # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"to #\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"to last\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"get sub-list from first\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"get sub-list from # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"get sub-list from #\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"सूची के बताए गये भाग की कॉपी बनता है।\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"आइटम पहली बार जहाँ आया है उसे ढूढ़े\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"आइटम आखरी बार जहाँ आया है उसे ढूढ़े\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.LISTS_INLIST = \"सूची में\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 खाली है\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"%1 की लंबाई\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"सूची की लंबाई रिटर्न करता है।\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"create list with item %1 repeated %2 times\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Creates a list consisting of the given value repeated the specified number of times.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"as\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"insert at\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_SET = \"सैट करें\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"आइटम को सूची के शुरू में इनसर्ट करता है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"सूची मे बताए गये स्थान में आइटम इनसर्ट करता है। #1 आखरी आइटम है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"सूची मे बताए गये स्थान में आइटम इनसर्ट करता है। #1 पहला आइटम है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"आइटम को सूची के अंत में जोड़ता है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"आइटम को सूची में रैन्डम्ली इनसर्ट करता है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"सूची में पहला आइटम सैट करता है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"सूची मे बताए गये स्थान में आइटम सैट करता है। #1 आखरी आइटम है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"सूची मे बताए गये स्थान में आइटम सैट करता है। #1 पहला आइटम है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"सूची में आखरी आइटम सैट करता है।\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"सूची में रैन्डम आइटम सैट करता है।\";\nBlockly.Msg.LISTS_TOOLTIP = \"यदि सूची खाली है तो ट्रू रिटर्न करता है।\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"फॉल्स\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"ट्रू या फॉल्स रिटर्न करता है।\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"ट्रू\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"ट्रू रिटर्न करें यदि दोनो इनपुट इक दूसरे के बराबर हों।\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से बड़ा हो।\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से बड़ा हो या बराबर हो।\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से छोटा हो।\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से छोटा हो या बराबर हो।\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"ट्रू रिटर्न करें यदि दोनो इनपुट इक दूसरे के बराबर नहीं हों।\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"NOT (पूरक) %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"ट्रू रिटर्न करता है यदि इनपुट फॉल्स है। फॉल्स रिटर्न करता है यदि इनपुट ट्रू है।\";\nBlockly.Msg.LOGIC_NULL = \"NULL (अमान्य)\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"null (अमान्य) रिटर्न करता है।\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"AND (तथा)\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"OR (अथवा)\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"ट्रू रिटर्न करें यदि दोनो इनपुट ट्रू हों।\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"ट्रू रिटर्न करें यदि दोनो मे से इक इनपुट ट्रू हो।\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"टेस्ट\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"यदि फॉल्स है\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"यदि ट्रू है\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\";  // untranslated\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"दो संख्याओं का योग रिटर्न करें।\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"दो संख्याओं का भागफल रिटर्न करें।\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"दो संख्याओं का अंतर रिटर्न करें।\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"दो संख्याओं का गुणन रिटर्न करें।\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Return the first number raised to the power of the second number.\";  // untranslated\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"by\";  // untranslated\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"बदलें\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"संख्या को चर '%1' से जोड़ें।\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";  // untranslated\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"इसके द्वारा विभाज्य है\";\nBlockly.Msg.MATH_IS_EVEN = \"सम है\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"ऋणात्मक है\";\nBlockly.Msg.MATH_IS_ODD = \"विषम है\";\nBlockly.Msg.MATH_IS_POSITIVE = \"धनात्मक है\";\nBlockly.Msg.MATH_IS_PRIME = \"अभाज्य है\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";  // untranslated\nBlockly.Msg.MATH_IS_WHOLE = \"पूर्णांक है\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"%1 ÷ %2 का शेषफल\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"दो संख्याओं के भाग का शेषफल रिटर्न करें।\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"एक संख्या।\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"सूची का औसत मान\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"सूची मे अधिकतम\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"सूची की माध्यिका\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"सूची मे न्यूनतम\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"सूची का मोड\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"सूची का रैन्डम आइटम\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"सूची का मानक विचलन\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"सूची का योग\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Return the average (arithmetic mean) of the numeric values in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"सूची मे सबसे बड़ी संख्या रिटर्न करें।\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"सूची की माध्यिका संख्या रिटर्न करें।\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"सूची मे सबसे छोटी संख्या रिटर्न करें।\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"सूची मे सबसे आम आइटम(s) की सूची रिटर्न करें।\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"सूची से एक रैन्डम आइटम रिटर्न करें।\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"सूची का मानक विचलन रिटर्न करें।\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"सूची की सभी संख्याओं का योग रिटर्न करें।\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"रैन्डम अंश\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"%1 से % 2 तक रैन्डम पूर्णांक\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Return a random integer between the two specified limits, inclusive.\";  // untranslated\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"पूर्णांक बनाएँ\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"घटा के पूर्णांक बनाएँ\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"बड़ा के पूर्णांक बनाएँ\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"संख्या को बड़ा या घटा के पूर्णांक बनाएँ।\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"परम\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"वर्गमूल\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"संख्या का परम मान रिटर्न करें।\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Return e to the power of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"संख्या का प्राकृतिक लघुगणक रिटर्न करें।\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"संख्या का मूल 10 लघुगणक रिटर्न करें।\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"संख्या का निषेध मान रिटर्न करें।\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Return 10 to the power of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"संख्या का वर्गमूल रिटर्न करें।\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"संख्या का आर्ककोसाइन रिटर्न करें।\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"संख्या का आर्कसाइन रिटर्न करें।\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"संख्या का आर्कटैन्जन्ट रिटर्न करें।\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"डिग्री का कोसाइन रिटर्न करें (रेडियन नही)\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"डिग्री का साइन रिटर्न करें (रेडियन नही)\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"डिग्री का टैन्जन्ट रिटर्न करें (रेडियन नही)\";\nBlockly.Msg.NEW_VARIABLE = \"नया चर...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"नए चर का नाम:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \": के साथ\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"यूज़र द्वारा वर्णन किया गया फ़ंक्शन '%1' चलाएँ।\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"यूज़र द्वारा वर्णन किया गया फ़ंक्शन '%1' चलाएँ और उसका आउटपुट इस्तेमाल करें।\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"'%1' बनाएँ\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"कुछ करें\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"to\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"बिना आउटपुट वाला एक फ़ंक्शन बनाता है।\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"रिटर्न\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"आउटपुट वाला एक फ़ंक्शन बनाता है।\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"सावधान: इस फ़ंक्शन मे डुप्लिकेट पैरामीटर हैं।\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"फ़ंक्शन परिभाषा को हाइलाइट करें\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"यदि एक मान ट्रू है तो, दूसरा मान रिटर्न करें।\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"सावधान: ये ब्लॉक फ़ंक्शन परिभाषा के अंदर ही इस्तेमाल किया जा सकता।\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"इनपुट का नाम:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"इनपुट\";\nBlockly.Msg.REMOVE_COMMENT = \"टिप्पणी हटायें\";\nBlockly.Msg.RENAME_VARIABLE = \"चर का नाम बदलें...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"सभी '%1' चरों के नाम बदलें:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"से जोड़ें ये टेक्स्ट\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"इस\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"कुछ टेक्स्ट इस चर '%1' से जोड़ें।\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"छोटे अक्षर मे\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"टाइटल केस मे\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"बड़े अक्षर मे\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"टेक्स्ट की कॉपी भिन्न केस (अक्षर से संबंधित) मे रिटर्न करें।\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"पहला अक्षर पाएँ\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"आखिर से अक्षर # पाएँ\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"अक्षर # पाएँ\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"इस टेक्स्ट मे\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"आखरी अक्षर पाएँ\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"रैन्डम अक्षर पाएँ\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"बताई गयी जगह से अक्षर रिटर्न करता है\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"सूची मे एक आइटम जोड़ें।\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"जोड़\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"आखिर से यहाँ तक अक्षर #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"यहाँ तक अक्षर #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"यहाँ तक आखरी अक्षर\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"इस टेक्स्ट मे\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"पहले अक्षर से सबस्ट्रिंग पाएँ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"आखरी अक्षर # से सबस्ट्रिंग पाएँ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"अक्षर # से सबस्ट्रिंग पाएँ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"टेक्स्ट का बताया गया अंश रिटर्न करता है\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"इस टेक्स्ट मे\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"टेक्स्ट पहली बार जहाँ आया है उसे ढूढ़े\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"टेक्स्ट आखरी बार जहाँ आया है उसे ढूढ़े\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 खाली है\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"ट्रू रिटर्न करता है यदि दिया गया टेक्स्ट खाली है।\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"इसके साथ टेक्स्ट बनाएँ\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Create a piece of text by joining together any number of items.\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"%1 की लंबाई\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"दिए गये टेक्स्ट मे अक्षरों की संख्या रिटर्न करता है (खाली स्थान मिला के)।\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"प्रिंट करें %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"दिया गया टेक्स्ट प्रिंट करें, संख्या या अन्य मान।\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"यूज़र से संख्या के लिए प्रॉम्प्ट करें।\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"यूज़र से कुछ टेक्स्ट के लिए प्रॉम्प्ट करें।\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"सूचना के साथ संख्या के लिए प्रॉम्प्ट करें\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"सूचना के साथ टेक्स्ट के लिए प्रॉम्प्ट करें\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"एक अक्षर, शब्द, या टेक्स्ट की पंक्ति।\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"रिक्त स्थान को इस टेक्स्ट के दोनों तरफ से निकालें\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"रिक्त स्थान को इस टेक्स्ट के बायें तरफ से निकालें\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"रिक्त स्थान को इस टेक्स्ट के दाईं तरफ से निकालें\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Return a copy of the text with spaces removed from one or both ends.\";  // untranslated\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"आइटम\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"सेट '%1' बनाएँ\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"इस चर का मान रिटर्न करता है।\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create 'get %1'\";  // untranslated\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"को\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"सेट करें\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"इस चर को इनपुट के बराबर सेट करता है।\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/hu.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.hu');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Megjegyzés hozzáadása\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Érték módosítása:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Összezár\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Összezár\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"+\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"arány:\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"Színkeverés\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Két színt kever össze a megadott arányban (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://hu.wikipedia.org/wiki/Szín\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Válassz színt a palettáról.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"Véletlen szín\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Véletlenszerűen kiválasztott szín.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"kék\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"zöld\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"vörös\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"Szín\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Szín előállítása a megadott vörös, zöld, és kék értékekkel.  Minden értéknek 0 és 100 közé kell esnie.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"befejezi az ismétlést\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"folytatja a következővel\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Megszakítja végtelen ciklust.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Megszakítja az aktuális futást és folytatja elölről.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Figyelem: Ez a blokk, csak egy ciklusban használható.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Iter.C3.A1l.C3.B3_ciklus\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"elemre a\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"listában\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"Minden\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"A lista elemszámának megfelelő lépésszámú ciklus.  A \\\"%1\\\" változó minden lépésben megkapja a lista adott elemének értékét.  Minden lépésben végrehajtódnak az utasítások.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"értékét %1 és %2 között, lépésköz: %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"Számold ki\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Véges lépésszámú ciklus.  A \\\"%1\\\" változó értékét számolja ki a kezdőérték és a végérték között.  Minden lépésben végrehajtódnak az utasítások.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Újabb feltételes elágazás.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Végső, 'egyébként' feltételt ad a 'ha' blokkhoz.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"A feltételes elágazás (ha) blokk testreszabásához bővítsd, töröld vagy rendezd át a részeit.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"különben\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"ha\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"Ha\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Ha a kifejezés igaz, akkor végrehajtjuk az utasításokat.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Ha a kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot.  Különben a második utasítás blokk kerül végrehajtásra.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Ha az első kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot.  Ha a második kifejezés igaz, akkor végrehajtjuk a második utasítás blokkot.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Ha az első kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot.  Ha a második kifejezés igaz, akkor végrehajtjuk a második utasítás blokkot.  Amennyiben egyik kifejezés sem igaz, akkor az utolsó utasítás blokk kerül végrehajtásra.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Sz.C3.A1ml.C3.A1l.C3.B3s_.28FOR.29_ciklus\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"Ismételd %1 alkalommal\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"Ismételd\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"alkalommal\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Megadott kódrészlet ismételt végrehajtása.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"amíg nem\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"ismételd amíg igazː\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Amíg a feltétel hamis, végrehajtja az utasításokat.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Amíg a feltétel igaz, végrehajtja az utasításokat.\";\nBlockly.Msg.DELETE_BLOCK = \"Töröl\";\nBlockly.Msg.DELETE_X_BLOCKS = \"%1 blokk törlése\";\nBlockly.Msg.DISABLE_BLOCK = \"Letilt\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Másolat\";\nBlockly.Msg.ENABLE_BLOCK = \"Engedélyez\";\nBlockly.Msg.EXPAND_ALL = \"Kinyit\";\nBlockly.Msg.EXPAND_BLOCK = \"Kibont\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Külső kapcsolatok\";\nBlockly.Msg.HELP = \"Sugó\";\nBlockly.Msg.INLINE_INPUTS = \"Belső kapcsolatok\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"üres lista\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Elemeket nem tartalmazó üres listát ad eredményül\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this list block.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"Lista készítés, elemek:\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Elem hozzáadása listához.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Listát készít a megadott elemekből.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"az első\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"a végétől számított\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"az elejétől számított\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"listából értéke\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"listából kivétele\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"az utolsó\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"bármely\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"listából törlése\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"elemnek\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"A lista első elemét adja eredményül.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"A lista megadott sorszámú elemét adja eredményül.  1 az utolsó elemet jelenti.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"A lista megadott sorszámú elemét adja eredményül.  1 az első elemet jelenti.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"A lista utolsó elemét adja eredményül.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"A lista véletlenszerűen választott elemét adja eredményül.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Az első elem kivétele a listából.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"A megadott sorszámú elem kivétele a listából 1 az utolsó elemet jelenti.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"A megadott sorszámú elem kivétele a listából 1 az első elemet jelenti.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Az utolsó elem kivétele a listából.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Véletlenszerűen választott elem kivétele a listából.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Az első elem törlése a listából.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"A megadott sorszámú elem törlése a listából 1 az utolsó elemet jelenti.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"A megadott sorszámú elem törlése a listából 1 az első elemet jelenti.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Az utolsó elem törlése a listából.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Véletlenszerűen választott elem törlése a listából.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"és a végétől számított\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"és az elejétől számított\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"és az utolsó\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"részlistája az első\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"részlistája a végétől számított\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"részlistája az elejétől számított\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"elem között\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"A lista adott részéről másolat.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"listában első előfordulásaː\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"listában utolsó előfordulásaː\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"A megadtott elem eslő vagy utolsó előfordulásával tér vissza.  0 esetén nincs ilyen eleme a listának.\";\nBlockly.Msg.LISTS_INLIST = \"A(z)\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 üres lista?\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"%1 lista hossza\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"A lista elemszámát adja eredményül.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"Lista készítése %1 elemet %2 alkalommal hozzáadva\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"A megadtott elem felhasználásával n elemű listát készít\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"elemkéntː\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"listába szúrd be\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"listába állítsd be\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Beszúrás a lista elejére.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Beszúrás a megadott sorszámú elem elé a listában.  1 az utolsó elemet jelenti.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Beszúrás a megadott sorszámú elem elé a listában.  1 az első elemet jelenti.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Beszúrás a lista végére.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Beszúrás véletlenszerűen választott elem elé a listában.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Az első elem cseréje a listában.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"A megadott sorszámú elem cseréje a listában.  1 az utolsó elemet jelenti.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"A megadott sorszámú elem cseréje a listában.  1 az első elemet jelenti.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Az utolsó elem cseréje a listában.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Véletlenszerűen választott elem cseréje a listában.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Az eredmény igaz, ha a lista nem tartalmaz elemeket.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"hamis\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Igaz, vagy Hamis érték\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"igaz\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://hu.wikipedia.org/wiki/Egyenl%C5%91tlens%C3%A9g\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Igaz, ha a kifejezés két oldala egyenlő.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Igaz, ha a bal oldali kifejezés nagyobb, mint a jobb oldali.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Igaz, ha a bal oldali kifejezés nagyobb vagy egyenlő, mint a jobb oldali.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Igaz, ha a bal oldali kifejezés kisebb, mint a jobb oldali.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Igaz, ha a bal oldali kifejezés kisebb vagy egyenlő, mint a jobb oldali.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Igaz, ha a kifejezés két oldala nem egyenlő..\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"nem %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Igaz, ha a kifejezés hamis.  Hamis, ha a kifejezés igaz.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"null érték.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"és\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"vagy\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Igaz, ha mindkét kifejezés igaz.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Igaz, ha bármelyik kifejezés igaz.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"kifejezés:\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"érték, ha hamis:\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"érték, ha igaz:\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Kiértékeli a kifejezést.  Ha a kifejezés igaz visszatér az \\\"érték, ha igaz\\\" értékkel, különben az \\\"érték, ha hamis\\\" értékkel.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://hu.wikipedia.org/wiki/Matematikai_m%C5%B1velet\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Két szám összege.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Két szám hányadosa.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Két szám különbsége.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Két szám szorzata.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Az első számnak a második számmal megyegyező hatványa.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://hu.wikipedia.org/wiki/JavaScript#Aritmetikai_oper.C3.A1torok\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"értékét, (növekmény)ː\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"Növeld\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"A(z) \\\"%1\\\" változó értékének növelése.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://hu.wikipedia.org/wiki/Matematikai_konstans\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Ismert matematikai konstans: π (3.141…), e (2.718…), φ (1.618…), gyök(2) (1.414…), gyök(½) (0.707…), vagy ∞ (végtelen).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"korlátozd %1 -t %2 és %3 közé\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Egy változó értékének korlátozása a megadott zárt intervallumra.\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"osztható ezzel?ː\";\nBlockly.Msg.MATH_IS_EVEN = \"páros szám?\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"negatív szám?\";\nBlockly.Msg.MATH_IS_ODD = \"páratlan szám?\";\nBlockly.Msg.MATH_IS_POSITIVE = \"pozitív szám?\";\nBlockly.Msg.MATH_IS_PRIME = \"prímszám?\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Megadja a számról, hogy páros, páratlan, prím, egész, pozitív vagy negatív szám, illetve osztható-e a másodikkal.  Igaz, vagy Hamis értéket ad eredményül.\";\nBlockly.Msg.MATH_IS_WHOLE = \"egész szám?\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://hu.wikipedia.org/wiki/Eg%C3%A9szr%C3%A9sz#Als.C3.B3_eg.C3.A9szr.C3.A9sz\";\nBlockly.Msg.MATH_MODULO_TITLE = \"maradék %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Az egész osztás maradékát adja eredméynül.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://hu.wikipedia.org/wiki/Sz%C3%A1m\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Egy szám.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"lista átlaga\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"lista maximuma\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"lista mediánja\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"lista minimuma\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"lista módusza\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"lista véletlen eleme\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"lista szórása\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"lista összege\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"A lista elemeinek átlagát adja eredményül.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"A lista elemeinek maximumát adja eredményül.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"A lista elemeinek mediánját adja eredményül.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"A lista elemeinek minimumát adja eredményül.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"A lista elemeinek móduszát adja eredményül.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"A lista egy véletlen elemét adja eredményül.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"A lista elemeinek szórását adja eredményül.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"A lista elemeinek összegét adja eredményül.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://hu.wikipedia.org/wiki/V%C3%A9letlen\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"véletlen tört\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Véletlen tört érték 0.0 és 1.0 között.\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://hu.wikipedia.org/wiki/V%C3%A9letlen\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"véletlen egész szám %1 között %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Véletlen egész szám a megadott zárt intervallumon belül.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://hu.wikipedia.org/wiki/Eg%C3%A9szr%C3%A9sz#Kerek.C3.ADt.C3.A9s\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"Kerekítés\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"Kerekítés le\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"Kerekítés fel\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Kerekítés a következő, vagy megelőző egész számra.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://hu.wikipedia.org/wiki/Gy%C3%B6kvon%C3%A1s\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"abszolútérték\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"négyzetgyök\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"A szám abszolútértéke.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Az e megadott számú hatványa.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"A szám természetes alapú logaritmusa.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"A szám 10-es alapú logaritmusa.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"A szám -1 szerese.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"A 10 megadott számú hatványa.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"A szám négyzetgyöke.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://hu.wikipedia.org/wiki/Sz%C3%B6gf%C3%BCggv%C3%A9nyek\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"A fokban megadott szög arkusz koszinusz értéke.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"A fokban megadott szög arkusz szinusz értéke.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"A fokban megadott szög arkusz tangens értéke.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"A fokban megadott szög koszinusz értéke.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"A fokban megadott szög szinusz értéke.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"A fokban megadott szög tangens értéke.\";\nBlockly.Msg.NEW_VARIABLE = \"Új...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Az új változó neve:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \".\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"paraméterlistaː\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://hu.wikipedia.org/wiki/F%C3%BCggv%C3%A9ny_(programoz%C3%A1s)\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Végrehajtja az eljárást.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://hu.wikipedia.org/wiki/F%C3%BCggv%C3%A9ny_(programoz%C3%A1s)\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Meghívja a függvényt.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Create \\\"do %1\\\"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"név\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"Eljárás\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Eljárás (nem ad vissza eredményt).\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"eredménye\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Függvény eredménnyel.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Figyelem: Az eljárásban azonos elnevezésű paramétert adtál meg.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Eljárás kiemelése\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Ha az érték igaz, akkor visszatér a függvény értékével.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Figyelem: Ez a blokk csak eljáráson belül használható.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"változó:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"paraméterek\";\nBlockly.Msg.REMOVE_COMMENT = \"Megjegyzés tölése\";\nBlockly.Msg.RENAME_VARIABLE = \"Átnevezés...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"\\\"%1\\\" változó átnevezése:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"szövegéhez fűzd hozzá\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"A\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Szöveget fűz a \\\"%1\\\" változó értékéhez.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"kisbetűs\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"Címként Formázott\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"NAGYBETŰS\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"szövegnek az első\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"szövegnek a végétől számított\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"szövegnek az elejétől számított\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"A\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"szövegnek az utolsó\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"szövegnek tetszőleges\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"karaktere\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"A szöveg egy megadott karakterét adja eredményül.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Elem hozzáfűzése a szöveghez.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"összefűz\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Összefűzéssel, törléssel vagy rendezéssel kapcsolato sblokkok szöveg szerkesztéséhez.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"betűtől a hátulról számított\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"betűtől a(z)\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"betűtől az utolsó\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"a\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"szövegben válaszd ki az első\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"szövegben válaszd ki a hátulról a(z)\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"szövegben válaszd ki a(z)\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"betűig tartó betűsort\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"A megadott szövegrészletet adja eredményül.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"A(z)\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"szövegben első előfordulásának indexe\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"szövegben utolsó előfordulásának indexe\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"szövegnek\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"A keresett szöveg első vagy utolsó előfordulásával tér vissza.  0 esetén a szövegrészlet nem található.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 üres sztring?\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Igaz, ha a vizsgált sztring üres.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"összefűz\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Tetszőleges számú szövegrészletet fűz össze egybefüggő szöveggé.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"hossz %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"A megadott szöveg karaktereinek számát adja eredményül (beleértve a szóközöket).\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"Üzenet %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Megejelníti a megadott kaakterláncot üzenetként a képernyőn.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Számot kér be a felhasználótól.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Szöveget kér be a felhasználótól.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"Kérj be számot\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"Kérj be szöveget\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://hu.wikipedia.org/wiki/String\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Egy betű, szó vagy szöveg egy sora.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"a végekről\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"az elejéről\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"a végéről\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Levágja a megadott szöveg végeiről a szóközöket.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"változó\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Create \\\"set %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"A változó értékét adja eredményül.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create \\\"get %1\\\"\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"A változónak adhatunk értéket.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/ia.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.ia');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Adder commento\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Cambiar valor:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Plicar blocos\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Plicar bloco\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"color 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"color 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"ration\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"miscer\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Misce duo colores con un ration specificate (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://ia.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Elige un color del paletta.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"color aleatori\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Eliger un color al hasardo.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blau\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"verde\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"rubie\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"colorar con\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Crear un color con le quantitate specificate de rubie, verde e blau. Tote le valores debe esser inter 0 e 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"escappar del bucla\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continuar con le proxime iteration del bucla\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Escappar del bucla continente.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Saltar le resto de iste bucla e continuar con le proxime iteration.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Attention: Iste bloco pote solmente esser usate in un bucla.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"in lista\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"pro cata elemento\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Pro cata elemento in un lista, mitter lo in le variabile '%1' e exequer certe instructiones.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"de %1 a %2 per %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"contar con\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Mitter in le variabile %1 le valores ab le numero initial usque al numero final, con passos secundo le intervallo specificate, e exequer le blocos specificate.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Adder un condition al bloco \\\"si\\\".\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Adder un condition final de reserva al bloco \\\"si\\\".\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Adder, remover o reordinar sectiones pro reconfigurar iste bloco \\\"si\\\".\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"si non\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"si non si\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"si\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Si un valor es ver, exequer certe instructiones.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Si un valor es ver, exequer le prime bloco de instructiones. Si non, exequer le secunde bloco de instructiones.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones. Si necun del valores es ver, exequer le ultime bloco de instructiones.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"face\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"repeter %1 vices\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"repeter\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"vices\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Exequer certe instructiones plure vices.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"repeter usque a\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"repeter durante que\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Durante que un valor es false, exequer certe instructiones.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Durante que un valor es ver, exequer certe instructiones.\";\nBlockly.Msg.DELETE_BLOCK = \"Deler bloco\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Deler %1 blocos\";\nBlockly.Msg.DISABLE_BLOCK = \"Disactivar bloco\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplicar\";\nBlockly.Msg.ENABLE_BLOCK = \"Activar bloco\";\nBlockly.Msg.EXPAND_ALL = \"Displicar blocos\";\nBlockly.Msg.EXPAND_BLOCK = \"Displicar bloco\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Entrata externe\";\nBlockly.Msg.HELP = \"Adjuta\";\nBlockly.Msg.INLINE_INPUTS = \"Entrata interne\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"create empty list\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returns a list, of length 0, containing no data records\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"list\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this list block.\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"create list with\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Add an item to the list.\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Create a list with any number of items.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"first\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# from end\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"get\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"get and remove\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"last\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"random\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"remove\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returns the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returns the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returns a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Removes and returns the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Removes and returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Removes and returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Removes and returns the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Removes and returns a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Removes the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Removes the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Removes the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Removes the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Removes a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"to # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"to #\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"to last\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"get sub-list from first\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"get sub-list from # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"get sub-list from #\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Creates a copy of the specified portion of a list.\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"find first occurrence of item\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"find last occurrence of item\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.LISTS_INLIST = \"in list\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 is empty\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"length of %1\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returns the length of a list.\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"create list with item %1 repeated %2 times\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Creates a list consisting of the given value repeated the specified number of times.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"as\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"insert at\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_SET = \"set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserts the item at the start of a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserts the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserts the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Append the item to the end of a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserts the item randomly in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Sets the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Sets the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Sets the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Sets the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Sets a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_TOOLTIP = \"Returns true if the list is empty.\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"false\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Retorna o ver o false.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"ver\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Retornar ver si le duo entratas es equal.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Retornar ver si le prime entrata es major que le secunde.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Retornar ver si le prime entrata es major que o equal al secunde.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Retornar ver si le prime entrata es minor que le secunde.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Retornar ver si le prime entrata es minor que o equal al secunde.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Retornar ver si le duo entratas non es equal.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"non %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Retornar ver si le entrata es false. Retornar false si le entrata es ver.\";\nBlockly.Msg.LOGIC_NULL = \"nulle\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Retorna nulle.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"e\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"o\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Retornar ver si ambe entratas es ver.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Retornar ver si al minus un del entratas es ver.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"si false\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"si ver\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Verificar le condition in 'test'. Si le condition es ver, retorna le valor de 'si ver'; si non, retorna le valor de 'si false'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://ia.wikipedia.org/wiki/Arithmetica\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Retornar le summa del duo numeros.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Retornar le quotiente del duo numeros.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Retornar le differentia del duo numeros.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Retornar le producto del duo numeros.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Retornar le prime numero elevate al potentia del secunde numero.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";  // untranslated\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"by\";  // untranslated\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"change\";  // untranslated\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Add a number to variable '%1'.\";  // untranslated\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";  // untranslated\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";  // untranslated\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"is divisible by\";  // untranslated\nBlockly.Msg.MATH_IS_EVEN = \"is even\";  // untranslated\nBlockly.Msg.MATH_IS_NEGATIVE = \"is negative\";  // untranslated\nBlockly.Msg.MATH_IS_ODD = \"is odd\";  // untranslated\nBlockly.Msg.MATH_IS_POSITIVE = \"is positive\";  // untranslated\nBlockly.Msg.MATH_IS_PRIME = \"is prime\";  // untranslated\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";  // untranslated\nBlockly.Msg.MATH_IS_WHOLE = \"is whole\";  // untranslated\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";  // untranslated\nBlockly.Msg.MATH_MODULO_TITLE = \"remainder of %1 ÷ %2\";  // untranslated\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Return the remainder from dividing the two numbers.\";  // untranslated\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://ia.wikipedia.org/wiki/Numero\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Un numero.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"average of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"max of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"median of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"min of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modes of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"random item of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standard deviation of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"sum of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Return the average (arithmetic mean) of the numeric values in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Return the largest number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Return the median number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Return the smallest number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Return a list of the most common item(s) in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Return a random element from the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Return the standard deviation of the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Return the sum of all the numbers in the list.\";  // untranslated\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"random fraction\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"random integer from %1 to %2\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Return a random integer between the two specified limits, inclusive.\";  // untranslated\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"round\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"round down\";  // untranslated\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"round up\";  // untranslated\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Round a number up or down.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://ia.wikipedia.org/wiki/Radice_quadrate\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolute\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"radice quadrate\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Retornar le valor absolute de un numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Retornar e elevate al potentia del numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Retornar le logarithmo natural de un numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Retornar le logarithmo in base 10 del numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Retornar le negation de un numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Retornar 10 elevate al potentia de un numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Retornar le radice quadrate de un numero.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";  // untranslated\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Return the arccosine of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Return the arcsine of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Return the arctangent of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Return the cosine of a degree (not radian).\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Return the sine of a degree (not radian).\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Return the tangent of a degree (not radian).\";  // untranslated\nBlockly.Msg.NEW_VARIABLE = \"Nove variabile...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nomine del nove variabile:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"with:\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Run the user-defined function '%1'.\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Run the user-defined function '%1' and use its output.\";  // untranslated\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Create '%1'\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"do something\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"to\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Creates a function with no output.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"return\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Creates a function with an output.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Warning: This function has duplicate parameters.\";  // untranslated\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Highlight function definition\";  // untranslated\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"If a value is true, then return a second value.\";  // untranslated\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Warning: This block may be used only within a function definition.\";  // untranslated\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"input name:\";  // untranslated\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"inputs\";  // untranslated\nBlockly.Msg.REMOVE_COMMENT = \"Remover commento\";\nBlockly.Msg.RENAME_VARIABLE = \"Renominar variabile...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Renominar tote le variabiles '%1' a:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"append text\";  // untranslated\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"to\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Append some text to variable '%1'.\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"to lower case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"to Title Case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"to UPPER CASE\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FIRST = \"get first letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"get letter # from end\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"get letter #\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"in text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_LAST = \"get last letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"get random letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returns the letter at the specified position.\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Add an item to the text.\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"join\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"to letter # from end\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"to letter #\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"to last letter\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"in text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"get substring from first letter\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"get substring from letter # from end\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"get substring from letter #\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"in text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"find first occurrence of text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"find last occurrence of text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 is empty\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returns true if the provided text is empty.\";  // untranslated\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"create text with\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Create a piece of text by joining together any number of items.\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"length of %1\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returns the number of letters (including spaces) in the provided text.\";  // untranslated\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"print %1\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Print the specified text, number or other value.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Prompt for user for a number.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Prompt for user for some text.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"prompt for number with message\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"prompt for text with message\";  // untranslated\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";  // untranslated\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"A letter, word, or line of text.\";  // untranslated\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"trim spaces from both sides of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"trim spaces from left side of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"trim spaces from right side of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Return a copy of the text with spaces removed from one or both ends.\";  // untranslated\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"cosa\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Create 'set %1'\";  // untranslated\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returns the value of this variable.\";  // untranslated\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create 'get %1'\";  // untranslated\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"to\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Sets this variable to be equal to the input.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/id.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.id');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Tambahkan sebuah comment\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Ubah nilai:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Tutup blok\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Tutup blok\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"Warna 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"Warna 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"rasio\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"Tertutup\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"mencampur dua warna secara bersamaan dengan perbandingan (0.0-1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Pilih warna dari daftar warna.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"Warna acak\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Pilih warna secara acak.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"biru\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"hijau\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"merah\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"Dengan warna\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Buatlah warna dengan jumlah yang ditentukan dari merah, hijau dan biru. Semua nilai harus antarai 0 sampai 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"Keluar dari perulangan\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"Lanjutkan dengan langkah penggulangan berikutnya\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Keluar sementara dari perulanggan.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Abaikan sisa dari loop ini, dan lanjutkan dengan iterasi berikutnya.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Peringatan: Blok ini hanya dapat digunakan dalam loop.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"di dalam list\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"untuk setiap item\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Untuk tiap-tiap item di dalam list, tetapkan variabel '%1' ke dalam item, selanjutnya kerjakan beberapa statement.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"dari %1 ke %2 dengan step / penambahan %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"Cacah dengan\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Menggunakan variabel %1 dengan mengambil nilai dari batas awal hingga ke batas akhir, dengan interval tertentu, dan mengerjakan block tertentu.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"tambahkan prasyarat ke dalam blok IF.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Terakhir, tambahkan tangkap-semua kondisi kedalam blok jika (if).\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Menambahkan, menghapus, atau menyusun kembali bagian untuk mengkonfigurasi blok IF ini.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"else\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"else if\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"Jika\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"jika nilainya benar maka kerjakan perintah berikutnya.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"jika nilainya benar, maka kerjakan blok perintah yang pertama. Jika tidak, kerjakan blok perintah yang kedua.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Jika nilai pertama adalah benar (true), maka lakukan perintah-perintah yang berada didalam blok pertama. Jika nilai kedua adalah benar (true), maka lakukan perintah-perintah yang berada didalam blok kedua.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Jika blok pertama adalah benar (true), maka lakukan perintah-perintah yang berada  didalam blok pertama. Atau jika blok kedua adalah benar (true), maka lakukan perintah-perintah yang berada didalam blok kedua.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"kerjakan\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"ulangi %1 kali\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"ulangi\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"kali\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Lakukan beberapa perintah beberapa kali.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"Ulangi sampai\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"Ulangi jika\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Jika sementara nilai tidak  benar (false), maka lakukan beberapa perintah.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Jika sementara nilai benar (true), maka lakukan beberapa perintah.\";\nBlockly.Msg.DELETE_BLOCK = \"Hapus blok\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Hapus %1 blok\";\nBlockly.Msg.DISABLE_BLOCK = \"Nonaktifkan blok\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplikat\";\nBlockly.Msg.ENABLE_BLOCK = \"Aktifkan blok\";\nBlockly.Msg.EXPAND_ALL = \"Kembangkan blok-blok\";\nBlockly.Msg.EXPAND_BLOCK = \"Kembangkan blok\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Input-input eksternal\";\nBlockly.Msg.HELP = \"Tolong\";\nBlockly.Msg.INLINE_INPUTS = \"Input inline\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"buat list kosong\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Mengembalikan daftar, dengan panjang 0, tidak berisi data\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"list\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Tambahkan, hapus, atau susun ulang bagian untuk mengkonfigurasi blok LIST (daftar) ini.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"buat daftar (list) dengan\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Tambahkan sebuah item ke daftar (list).\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Buat sebuah daftar (list) dengan sejumlah item.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"pertama\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# dari akhir\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"dapatkan\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"dapatkan dan hapus\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"terakhir\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"acak\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"Hapus\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Kembalikan item pertama dalam daftar (list).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Sisipkan item ke dalam posisi yang telah ditentukan didalam list (daftar). Item pertama adalah item yang terakhir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Sisipkan item ke dalam posisi yang telah ditentukan didalam list (daftar). Item pertama adalah item terakhir (yg paling akhir).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Mengembalikan item pertama dalam list (daftar).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Mengembalikan item acak dalam list (daftar).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Menghilangkan dan mengembalikan item pertama dalam list (daftar).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Menghilangkan dan mengembalikan barang di posisi tertentu dalam list (daftar).  #1 adalah item terakhir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Menghilangkan dan mengembalikan barang di posisi tertentu dalam list (daftar).  #1 adalah item pertama.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Menghilangkan dan mengembalikan item terakhir dalam list (daftar).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Menghilangkan dan mengembalikan barang dengan acak dalam list (daftar).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Menghapus item pertama dalam daftar.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Menghapus item dengan posisi tertentu dalam daftar. Item pertama adalah item yang terakhir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Menghapus item dengan posisi tertentu dalam daftar. Item pertama adalah item yang terakhir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Menghapus item terakhir dalam daftar.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Menghapus sebuah item secara acak dalam list.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"ke # dari akhir\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"ke #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"ke yang paling akhir\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"Dapatkan bagian pertama dari list\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"Dapatkan bagian list nomor # dari akhir\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"Dapatkan bagian daftar dari #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Membuat salinan dari bagian tertentu dari list.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"cari kejadian pertama item\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"Cari kejadian terakhir item\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Mengembalikan indeks dari kejadian pertama/terakhir item dalam daftar.  Menghasilkan 0 jika teks tidak ditemukan.\";\nBlockly.Msg.LISTS_INLIST = \"dalam daftar\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 kosong\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"panjang dari %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Mengembalikan panjang daftar.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"membuat daftar dengan item %1 diulang %2 kali\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Ciptakan daftar yang terdiri dari nilai yang diberikan diulang jumlah waktu yang ditentukan.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"sebagai\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"sisipkan di\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"tetapkan\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Sisipkan item di bagian awal dari list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Sisipkan item ke dalam posisi yang telah ditentukan di dalam list. #1 adalah item yang terakhir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Sisipkan item ke dalam posisi yang telah ditentukan di dalam list. #1 adalah item yang pertama.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Tambahkan item ke bagian akhir list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Sisipkan item secara acak ke dalam list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Tetapkan item pertama di dalam list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Tetapkan item ke dalam posisi yang telah ditentukan di dalam list. #1 adalah item yang terakhir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Tetapkan item ke dalam posisi yang telah ditentukan di dalam list. #1 adalah item yang pertama.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Menetapkan item terakhir dalam list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Tetapkan secara acak sebuah item dalam list.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Mengembalikan nilai benar (true) jika list kosong.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"Salah\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Mengembalikan betul (true) atau salah (false).\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"Benar\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Mengembalikan betul jika input kedua-duanya sama dengan satu sama lain.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Mengembalikan nilai benar (true) jika input yang pertama lebih besar dari input yang kedua.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Mengembalikan nilai benar (true) jika input yang pertama lebih besar dari atau sama dengan input yang kedua.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Mengembalikan nilai benar (true) jika input yang pertama lebih kecil dari input yang kedua.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Mengembalikan nilai benar (true) jika input yang pertama lebih kecil atau sama dengan input yang kedua .\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Mengembalikan nilai benar (true) jika kedua input tidak sama satu dengan yang lain.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"bukan (not) %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Mengembalikan nilai benar (true) jika input false.  Mengembalikan nilai salah (false) jika input true.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"mengembalikan kosong.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"dan\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"atau\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Kembalikan betul jika kedua-dua input adalah betul.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Mengembalikan nilai benar (true) jika setidaknya salah satu masukan nilainya benar (true).\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"jika tidak benar (false)\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"jika benar (true)\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Periksa kondisi di \\\"test\\\". Jika kondisi benar (true), mengembalikan nilai \\\"jika benar\\\" ; Jik sebaliknya akan mengembalikan nilai \\\"jika salah\\\".\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://id.wikipedia.org/wiki/Aritmetika\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Kembalikan jumlah dari kedua angka.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Kembalikan hasil bagi dari kedua angka.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Kembalikan selisih dari kedua angka.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Kembalikan perkalian dari kedua angka.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Kembalikan angka pertama pangkat angka kedua.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"oleh\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"ubah\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Tambahkan angka kedalam variabel '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Kembalikan salah satu konstant: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), atau ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"Batasi %1 rendah %2 tinggi %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Batasi angka antara batas yang ditentukan (inklusif).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"dibagi oleh\";\nBlockly.Msg.MATH_IS_EVEN = \"adalah bilangan genap\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"adalah  bilangan negatif\";\nBlockly.Msg.MATH_IS_ODD = \"adalah bilangan ganjil\";\nBlockly.Msg.MATH_IS_POSITIVE = \"adalah  bilangan positif\";\nBlockly.Msg.MATH_IS_PRIME = \"adalah bilangan pokok\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Periksa apakah angka adalah bilangan genap, bilangan pokok, bilangan bulat, bilangan positif, bilangan negatif, atau apakan bisa dibagi oleh angka tertentu. Mengembalikan benar (true) atau salah (false).\";\nBlockly.Msg.MATH_IS_WHOLE = \"adalah bilangan bulat\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"sisa %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Kembalikan sisa dari pembagian ke dua angka.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Suatu angka.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"rata-rata dari list (daftar)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"maximum dari list (daftar)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"median dari list (daftar)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minimum dari list (daftar)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"mode-mode dari list (daftar)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"item acak dari list (daftar)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"deviasi standar dari list (daftar)\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"jumlah dari list (daftar)\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Kembalikan rata-rata (mean aritmetik) dari nilai numerik dari list (daftar).\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Kembalikan angka terbesar dari list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Kembalikan median dari list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Kembalikan angka terkecil dari list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Kembalikan list berisi item-item yang paling umum dari dalam list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Kembalikan element acak dari list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Kembalikan standard deviasi dari list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Kembalikan jumlah dari seluruh bilangan dari list.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"Nilai pecahan acak\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Mengembalikan nilai acak pecahan antara 0.0 (inklusif) dan 1.0 (ekslusif).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"acak bulat dari %1 sampai %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Mengembalikan bilangan acak antara dua batas yang ditentukan, inklusif.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"membulatkan\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"membulatkan kebawah\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"mengumpulkan\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Bulatkan suatu bilangan naik atau turun.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"mutlak\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"akar\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Kembalikan nilai absolut angka.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Kembalikan 10 pangkat angka.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Kembalikan logaritma natural dari angka.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Kembalikan dasar logaritma 10 dari angka.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Kembalikan penyangkalan terhadap angka.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Kembalikan 10 pangkat angka.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Kembalikan akar dari angka.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Kembalikan acosine dari angka.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Kembalikan asin dari angka.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Kembalikan atan dari angka.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Kembalikan cos dari derajat (bukan radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Kembalikan sinus dari derajat (bukan radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Kembalikan tangen dari derajat (tidak radian).\";\nBlockly.Msg.NEW_VARIABLE = \"Pembolehubah baru...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nama pembolehubah baru:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"dengan:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Menjalankan fungsi '%1' yang ditetapkan pengguna.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Menjalankan fungsi  '%1' yang ditetapkan pengguna dan menggunakan outputnya.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Buat '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"buat sesuatu\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"untuk\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Menciptakan sebuah fungsi dengan tiada output.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"kembali\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Menciptakan sebuah fungsi dengan satu output.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Peringatan: Fungsi ini memiliki parameter duplikat.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Sorot definisi fungsi\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Jika nilai yang benar, kemudian kembalikan nilai kedua.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Peringatan: Blok ini dapat digunakan hanya dalam definisi fungsi.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"masukan Nama:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"input\";\nBlockly.Msg.REMOVE_COMMENT = \"Hapus komentar\";\nBlockly.Msg.RENAME_VARIABLE = \"namai ulang variabel...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Ubah nama semua variabel '%1' menjadi:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"tambahkan teks\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"untuk\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Tambahkan beberapa teks ke variabel '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"menjadi huruf kecil\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"menjadi huruf pertama kapital\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"menjadi huruf kapital\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Kembalikan kopi dari text dengan kapitalisasi yang berbeda.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"ambil  huruf pertama\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"ambil  huruf nomor # dari belakang\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"ambil huruf ke #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"dalam teks\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"ambil  huruf terakhir\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"ambil huruf secara acak\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Kembalikan karakter dari posisi tertentu.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Tambahkan suatu item ke dalam teks.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"join\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Tambah, ambil, atau susun ulang teks blok.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"pada huruf nomer # dari terakhir\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"pada huruf #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"pada huruf terakhir\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"in teks\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"ambil bagian teks (substring) dari huruf pertama\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"ambil bagian teks (substring) dari huruf ke # dari terakhir\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"ambil bagian teks (substring) dari huruf no #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Mengembalikan spesifik bagian dari teks.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"dalam teks\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"temukan kejadian pertama dalam teks\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"temukan kejadian terakhir dalam teks\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Kembalikan indeks pertama dan terakhir dari kejadian pertama/terakhir dari teks pertama dalam teks kedua.  Kembalikan 0 jika teks tidak ditemukan.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 kosong\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Kembalikan benar (true) jika teks yang disediakan kosong.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"Buat teks dengan\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Buat teks dengan cara gabungkan sejumlah item.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"panjang dari %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Kembalikan sejumlah huruf (termasuk spasi) dari teks yang disediakan.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"cetak %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Cetak teks yant ditentukan, angka atau ninlai lainnya.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Meminta pengguna untuk memberi sebuah angka.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Meminta pengguna untuk memberi beberapa teks.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"Meminta angka dengan pesan\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"meminta teks dengan pesan\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Huruf, kata atau baris teks.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"pangkas ruang dari kedua belah sisi\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"pangkas ruang dari sisi kiri\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"pangkas ruang dari sisi kanan\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Kembali salinan teks dengan spasi dihapus dari satu atau kedua ujungnya.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"item\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Membuat 'tetapkan %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Mengembalikan nilai variabel ini.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Membuat 'dapatkan %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"untuk\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"tetapkan\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"tetapkan variabel ini dengan input yang sama.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/is.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.is');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Skrifa skýringu\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Breyta gildi:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Loka kubbum\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Loka kubbi\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"litur 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"litur 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"hlutfall\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"blöndun\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Blandar tveimur litum í gefnu hlutfalli (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Velja lit úr litakorti.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"einhver litur\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Velja einhvern lit af handahófi.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blátt\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"grænt\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"rautt\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"litur\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Búa til lit úr tilteknu magni af rauðu, grænu og bláu. Allar tölurnar verða að vera á bilinu 0 til 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"fara út úr lykkju\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"fara beint í næstu umferð lykkjunnar\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Fara út úr umlykjandi lykkju.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Sleppa afganginum af lykkjunni og fara beint í næstu umferð hennar.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Aðvörun: Þennan kubb má aðeins nota innan lykkju.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"í lista\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"fyrir hvert\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Fyrir hvert atriði í lista er breyta '%1' stillt á atriðið og skipanir gerðar.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"frá %1 til %2 um %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"telja með\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Láta breytuna %1 taka inn gildi frá fyrstu tölu til síðustu tölu hlaupandi á bilinu og endurtaka kubbana fyrir hverja tölu.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Bæta skilyrði við EF kubbinn.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Bæta við hluta EF kubbs sem grípur öll tilfelli sem uppfylla ekki hin skilyrðin.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Bæta við, fjarlægja eða umraða til að breyta skipan þessa EF kubbs.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"annars\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"annars ef\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"ef\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Ef gildi er satt skal gera einhverjar skipanir.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Ef gildi er satt skal gera skipanir í fyrri kubbnum. Annars skal gera skipanir í seinni kubbnum.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Ef fyrra gildið er satt skal gera skipanir í fyrri kubbnum. Annars, ef seinna gildið er satt, þá skal gera skipanir í seinni kubbnum.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Ef fyrra gildið er satt skal gera skipanir í fyrri kubbnum. Annars, ef seinna gildið er satt, skal gera skipanir í seinni kubbnum. Ef hvorugt gildið er satt, skal gera skipanir í síðasta kubbnum.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"gera\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"endurtaka %1 sinnum\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"endurtaka\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"sinnum\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Gera eitthvað aftur og aftur.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"endurtaka þar til\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"endurtaka á meðan\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Endurtaka eitthvað á meðan gildi er ósatt.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Endurtaka eitthvað á meðan gildi er satt.\";\nBlockly.Msg.DELETE_BLOCK = \"Eyða kubbi\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Eyða %1 kubbum\";\nBlockly.Msg.DISABLE_BLOCK = \"Óvirkja kubb\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Afrita\";\nBlockly.Msg.ENABLE_BLOCK = \"Virkja kubb\";\nBlockly.Msg.EXPAND_ALL = \"Opna kubba\";\nBlockly.Msg.EXPAND_BLOCK = \"Opna kubb\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Ytri inntök\";\nBlockly.Msg.HELP = \"Hjálp\";\nBlockly.Msg.INLINE_INPUTS = \"Innri inntök\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"búa til tóman lista\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Skilar lista með lengdina 0 án gagna\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"listi\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Bæta við, fjarlægja eða umraða hlutum til að breyta skipan þessa listakubbs.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"búa til lista með\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Bæta atriði við listann.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Búa til lista með einhverjum fjölda atriða.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"fyrsta\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# frá enda\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"sækja\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"sækja og fjarlægja\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"síðasta\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"eitthvert\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"fjarlægja\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Skilar fyrsta atriði í lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Skilar atriðinu á hinum tiltekna stað í lista. #1 er síðasta atriðið.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Skilar atriðinu í hinum tiltekna stað í lista. #1 er fyrsta atriðið.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Skilar síðasta atriði í lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Skilar einhverju atriði úr lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Fjarlægir og skilar fyrsta atriðinu í lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Fjarlægir og skilar atriðinu á hinum tiltekna stað í lista. #1 er síðasta atriðið.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Fjarlægir og skilar atriðinu á hinum tiltekna stað í lista. #1 er fyrsta atriðið.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Fjarlægir og skilar síðasta atriðinu í lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Fjarlægir og skilar einhverju atriði úr lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Fjarlægir fyrsta atriðið í lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Fjarlægir atriðið á hinum tiltekna stað í lista. #1 er síðasta atriðið.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Fjarlægir atriðið á hinum tiltekna stað í lista. #1 er fyrsta atriðið.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Fjarlægir síðasta atriðið í lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Fjarlægir eitthvert atriði úr lista.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"til # frá enda\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"til #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"til síðasta\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"sækja undirlista frá fyrsta\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"sækja undirlista frá # frá enda\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"sækja undirlista frá #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Býr til afrit af tilteknum hluta lista.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"finna fyrsta tilfelli atriðis\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"finna síðasta tilfelli atriðis\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Finnur hvar atriðið kemur fyrir fyrst/síðast í listanum og skilar sæti þess. Skilar 0 ef textinn finnst ekki.\";\nBlockly.Msg.LISTS_INLIST = \"í lista\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 er tómur\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"lengd %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Skilar lengd lista.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"búa til lista með atriði %1 endurtekið %2 sinnum\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Býr til lista sem inniheldur tiltekna gildið endurtekið tiltekið oft.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"sem\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"bæta við\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"setja í\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Bætir atriðinu fremst í listann.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Bætir atriðinu í listann á tilteknum stað. #1 er síðasta atriðið.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Bætir atriðinu í listann á tilteknum stað. #1 er fyrsta atriðið.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Bætir atriðinu aftan við listann.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Bætir atriðinu einhversstaðar við listann.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Setur atriðið í fyrsta sæti lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Setur atriðið í tiltekna sætið í listanum. #1 er síðasta atriðið.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Setur atriðið í tiltekna sætið í listanum. #1 er fyrsta atriðið.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Setur atriðið í síðasta sæti lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Setur atriðið í eitthvert sæti lista.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Skilar sönnu ef listinn er tómur.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"ósatt\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Skilar annað hvort sönnu eða ósönnu.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"satt\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Skila sönnu ef inntökin eru jöfn.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Skila sönnu ef fyrra inntakið er stærra en seinna inntakið.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Skila sönnu ef fyrra inntakið er stærra en eða jafnt og seinna inntakið.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Skila sönnu ef fyrra inntakið er minna en seinna inntakið.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Skila sönnu ef fyrra inntakið er minna en eða jafnt og seinna inntakið.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Skila sönnu ef inntökin eru ekki jöfn.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"ekki %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Skilar sönnu ef inntakið er ósatt. Skilar ósönnu ef inntakið er satt.\";\nBlockly.Msg.LOGIC_NULL = \"tómagildi\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Skilar tómagildi.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"og\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"eða\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Skila sönnu ef bæði inntökin eru sönn.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Skila sönnu ef að minnsta kosti eitt inntak er satt.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"prófun\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"ef ósatt\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"ef satt\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Kanna skilyrðið í 'prófun'. Skilar 'ef satt' gildinu ef skilyrðið er satt, en skilar annars 'ef ósatt' gildinu.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Skila summu talnanna tveggja.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Skila deilingu talnanna.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Skila mismun talnanna.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Skila margfeldi talnanna.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Skila fyrri tölunni í veldinu seinni talan.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"um\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"breyta\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Bæta tölu við breytu '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Skila algengum fasta: π (3.141…), e (2.718…), φ (1.618…), kvrót(2) (1.414…), kvrót(½) (0.707…) eða ∞ (óendanleika).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"þröngva %1 lægst %2 hæst %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Þröngva tölu til að vera innan hinna tilgreindu marka (að báðum meðtöldum).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"er\\u00A0deilanleg með\";\nBlockly.Msg.MATH_IS_EVEN = \"er\\u00A0jöfn tala\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"er neikvæð\";\nBlockly.Msg.MATH_IS_ODD = \"er oddatala\";\nBlockly.Msg.MATH_IS_POSITIVE = \"er jákvæð\";\nBlockly.Msg.MATH_IS_PRIME = \"er prímtala\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Kanna hvort tala sé jöfn tala, oddatala, jákvæð, neikvæð eða deilanleg með tiltekinni tölu. Skilar sönnu eða ósönnu.\";\nBlockly.Msg.MATH_IS_WHOLE = \"er heiltala\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"afgangur af %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Skila afgangi deilingar með tölunum.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Tala.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"meðaltal lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"stærst í lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"miðgildi lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minnst í lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"tíðast í lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"eitthvað úr lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"staðalfrávik lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"summa lista\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Skila meðaltali talna í listanum.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Skila stærstu tölu í listanum.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Skila miðgildi listans.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Skila minnstu tölu í listanum.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Skila lista yfir tíðustu gildin í listanum.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Skila einhverju atriði úr listanum.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Skila staðalfráviki lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Skila summu allra talna í listanum.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"slembibrot\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Skila broti sem er valið af handahófi úr tölum á bilinu frá og með 0.0 til (en ekki með) 1.0.\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"slembitala frá %1 til %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Skila heiltölu sem valin er af handahófi og er innan tilgreindra marka, að báðum meðtöldum.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"námunda\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"námunda niður\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"námunda upp\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Námunda tölu upp eða niður.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"algildi\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"kvaðratrót\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Skila algildi tölu.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Skila e í veldi tölu.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Skila náttúrlegum lógaritma tölu.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Skila tugalógaritma tölu.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Skila neitun tölu (tölunni með öfugu formerki).\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Skila 10 í veldi tölu.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Skila kvaðratrót tölu.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Skilar arkarkósínusi tölu.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Skilar arkarsínusi tölu.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Skilar arkartangensi tölu.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Skila kósínusi horns gefnu í gráðum.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Skila sínusi horns gefnu í gráðum.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Skila tangensi horns gefnu í gráðum.\";\nBlockly.Msg.NEW_VARIABLE = \"Ný breyta...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Heiti nýrrar breytu:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"með:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Keyra heimatilbúna fallið '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Keyra heimatilbúna fallið '%1' og nota úttak þess.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Búa til '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"gera eitthvað\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"til að\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Býr til fall sem skilar engu.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"skila\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Býr til fall sem skilar úttaki.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Aðvörun: Þetta fall er með tvítekna stika.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Sýna skilgreiningu falls\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Ef gildi er satt, skal skila öðru gildi.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Aðvörun: Þennan kubb má aðeins nota í skilgreiningu falls.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"heiti inntaks:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"inntök\";\nBlockly.Msg.REMOVE_COMMENT = \"Fjarlægja skýringu\";\nBlockly.Msg.RENAME_VARIABLE = \"Endurnefna breytu...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Endurnefna allar '%1' breyturnar:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"bæta texta\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"við\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Bæta texta við breytuna '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"í lágstafi\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"í Upphafstafi\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"í HÁSTAFI\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Skila afriti af textanum með annarri stafastöðu.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"sækja fyrsta staf\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"sækja staf # frá enda\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"sækja staf #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"í texta\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"sækja síðasta staf\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"sækja einhvern staf\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Skila staf á tilteknum stað.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Bæta atriði við textann.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"tengja\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Bæta við, fjarlægja eða umraða hlutum til að breyta skipan þessa textakubbs.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"að staf # frá enda\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"að staf #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"að síðasta staf\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"í texta\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"sækja textabút frá fyrsta staf\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"sækja textabút frá staf # frá enda\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"sækja textabút frá staf #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Skilar tilteknum hluta textans.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"í texta\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"finna fyrsta tilfelli texta\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"finna síðasta tilfelli texta\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Finnur fyrsta/síðasta tilfelli fyrri textans í seinni textanum og skilar sæti hans. Skilar 0 ef textinn finnst ekki.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 er tómur\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Skilar sönnu ef gefni textinn er tómur.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"búa til texta með\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Búa til texta með því að tengja saman einhvern fjölda atriða.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"lengd %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Skilar fjölda stafa (með bilum) í gefna textanum.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"prenta %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Prenta tiltekinn texta, tölu eða annað gildi.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Biðja notandann um tölu.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Biðja notandann um texta.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"biðja um tölu með skilaboðum\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"biðja um texta með skilaboðum\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Stafur, orð eða textalína.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"eyða bilum af báðum endum\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"eyða bilum af vinstri enda\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"eyða bilum af hægri enda\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Skila afriti af textanum þar sem möguleg bil við báða enda hafa verið fjarlægð.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"atriði\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Búa til 'stilla %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Skilar gildi þessarar breytu.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Búa til 'sækja %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"á\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"stilla\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Stillir þessa breytu á innihald inntaksins.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/it.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.it');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Aggiungi commento\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Modifica valore:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Comprimi blocchi\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Comprimi blocco\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"colore 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"colore 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"rapporto\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"miscela\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Mescola due colori insieme con un determinato rapporto (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://it.wikipedia.org/wiki/Colore\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Scegli un colore dalla tavolozza.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"colore casuale\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Scegli un colore a caso.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blu\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"verde\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"rosso\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"colora con\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Crea un colore con la quantità specificata di rosso, verde e blu. Tutti i valori devono essere compresi tra 0 e 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"esce dal ciclo\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"prosegui con la successiva iterazione del ciclo\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Esce dal ciclo.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Salta il resto di questo ciclo e prosegue con la successiva iterazione.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Attenzioneː Questo blocco può essere usato solo in un ciclo.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"nella lista\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"per ogni elemento\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Per ogni elemento in una lista, imposta la variabile '%1'  pari all'elemento e quindi esegue alcune istruzioni.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"da %1 a %2 per %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"conta con\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Fa sì che la variabile %1 prenda tutti i valori a partire dal numero di partenza fino a quello di arrivo, con passo pari all'intervallo specificato, ed esegue il blocco indicato.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Aggiungi una condizione al blocco se.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Aggiungi una condizione finale pigliatutto al blocco se.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Aggiungi, elimina o riordina le sezioni per riconfigurare questo blocco se.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"altrimenti\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"altrimenti se\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"se\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Se un valore è vero allora esegue alcune istruzioni.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Se un valore è vero allora esegue il primo blocco di istruzioni. Altrimenti esegue il secondo blocco di istruzioni.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni. Se nessuno dei valori è vero esegue l'ultimo blocco di istruzioni.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://it.wikipedia.org/wiki/Ciclo_for\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"fai\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"ripeti %1 volte\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"ripeti\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"volte\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Esegue alcune istruzione diverse volte.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"ripeti fino a che\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"ripeti mentre\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Finché un valore è falso, esegue alcune istruzioni.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Finché un valore è vero, esegue alcune istruzioni.\";\nBlockly.Msg.DELETE_BLOCK = \"Cancella blocco\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Cancella %1 blocchi\";\nBlockly.Msg.DISABLE_BLOCK = \"Disattiva blocco\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplica\";\nBlockly.Msg.ENABLE_BLOCK = \"Attiva blocco\";\nBlockly.Msg.EXPAND_ALL = \"Espandi blocchi\";\nBlockly.Msg.EXPAND_BLOCK = \"Espandi blocco\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Ingressi esterni\";\nBlockly.Msg.HELP = \"Aiuto\";\nBlockly.Msg.INLINE_INPUTS = \"Ingressi in linea\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"crea lista vuota\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Restituisce una lista, di lunghezza 0, contenente nessun record di dati\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Aggiungi, rimuovi o riordina le sezioni per riconfigurare il blocco lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"crea lista con\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Aggiunge un elemento alla lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Crea una lista con un certo numero di elementi.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"primo\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# dalla fine\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"prendi\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"prendi e rimuovi\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"ultimo\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"casuale\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"rimuovi\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Restituisce il primo elemento in una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Restituisce l'elemento nella posizione indicata della lista. 1 corrisponde all'ultimo elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Restituisce l'elemento nella posizione indicata della lista. 1 corrisponde al primo elemento della lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Restituisce l'ultimo elemento in una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Restituisce un elemento casuale in una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Rimuove e restituisce il primo elemento in una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Rimuove e restituisce l'elemento nella posizione indicata in una lista. 1 corrisponde all'ultimo elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Rimuove e restituisce l'elemento nella posizione indicata in una lista. 1 corrisponde al primo elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Restituisce e rimuove l'ultimo elemento in una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Restituisce e rimuove un elemento casuale in una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Rimuove il primo elemento in una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Rimuove l'elemento nella posizione indicata in una lista. 1 corrisponde all'ultimo elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Rimuove l'elemento nella posizione indicata in una lista. 1 corrisponde al primo elemento.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Rimuove l'ultimo elemento in una lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Rimuove un elemento casuale in una lista.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"da # dalla fine\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"fino a #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"dagli ultimi\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"prendi sotto-lista dall'inizio\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"prendi sotto-lista da # dalla fine\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"prendi sotto-lista da #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Crea una copia della porzione specificata di una lista.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"trova la prima occorrenza dell'elemento\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"trova l'ultima occorrenza dell'elemento\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Restituisce l'indice della prima/ultima occorrenza dell'elemento nella lista. Restituisce 0 se il testo non viene trovato.\";\nBlockly.Msg.LISTS_INLIST = \"nella lista\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 è vuota\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"lunghezza di %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Restituisce la lunghezza della lista\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"crea una lista con l'elemento %1 ripetuto %2 volte\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Crea una lista costituita dal valore indicato ripetuto per il numero di volte specificato.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"come\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"inserisci in\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"imposta\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserisci l'elemento all'inizio della lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserisci l'elemento nella posizione indicata in una lista. #1 corrisponde all'ultimo elemento.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserisci un elemento nella posizione indicata in una lista. #1 corrisponde al primo elemento.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Aggiungi un elemento alla fine di una lista\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserisce l'elemento casualmente in una lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Imposta il primo elemento in una lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Imposta l'elemento nella posizione indicata di una lista. 1 corrisponde all'ultimo elemento.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Imposta l'elemento nella posizione indicata di una lista. 1 corrisponde al primo elemento.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Imposta l'ultimo elemento in una lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Imposta un elemento casuale in una lista.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Restituisce vero se la lista è vuota.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"falso\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Restituisce vero o falso.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"vero\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://it.wikipedia.org/wiki/Disuguaglianza\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Restituisce vero se gli input sono uno uguale all'altro.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Restituisce vero se il primo input è maggiore o uguale al secondo.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Restituisce uguale se il primo input è maggiore o uguale al secondo input.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Restituisce vero se il primo input è minore del secondo.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Restituisce vero se il primo input è minore o uguale al secondo.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Restituisce vero se gli input non sono uno uguale all'altro.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"non %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Restituisce vero se l'input è falso. Restituisce falso se l'input è vero.\";\nBlockly.Msg.LOGIC_NULL = \"nullo\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Restituisce valore nullo.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"e\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"o\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Restituisce vero se entrambi gli input sono veri.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Restituisce vero se almeno uno degli input è vero.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"se falso\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"se vero\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Verifica la condizione in 'test'. Se questa è vera restituisce il valore 'se vero' altrimenti restituisce il valore 'se falso'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://it.wikipedia.org/wiki/Aritmetica\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Restituisce la somma dei due numeri.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Restituisce il quoziente dei due numeri.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Restituisce la differenza dei due numeri.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Restituisce il prodotto dei due numeri.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Restituisce il primo numero elevato alla potenza del secondo numero.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://it.wikipedia.org/wiki/Addizione\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"di\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"cambia\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Aggiunge un numero alla variabile '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://it.wikipedia.org/wiki/Costante_matematica\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Restituisce una delle costanti comuniː π (3.141…), e (2.718…), φ (1.618…), radq(2) (1.414…), radq(½) (0.707…) o ∞ (infinito).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"costringi %1 da %2 a %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Costringe un numero all'interno dei limiti indicati (compresi).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"è divisibile per\";\nBlockly.Msg.MATH_IS_EVEN = \"è pari\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"è negativo\";\nBlockly.Msg.MATH_IS_ODD = \"è dispari\";\nBlockly.Msg.MATH_IS_POSITIVE = \"è positivo\";\nBlockly.Msg.MATH_IS_PRIME = \"è primo\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Verifica se un numero è pari, dispari, primo, intero, positivo, negativo o se è divisibile per un certo numero. Restituisce vero o falso.\";\nBlockly.Msg.MATH_IS_WHOLE = \"è intero\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://it.wikipedia.org/wiki/Resto\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resto di %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Restituisce il resto della divisione di due numeri.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://it.wikipedia.org/wiki/Numero\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Un numero.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"media della lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"massimo della lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mediana della lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minimo della lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"mode della lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"elemento casuale della lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"deviazione standard della lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"somma la lista\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Restituisce la media (media aritmetica) dei valori numerici nella lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Restituisce il più grande numero della lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Restituisce il valore mediano della lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Restituisce il più piccolo numero della lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Restituisce una lista degli elementi più frequenti nella lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Restituisce un elemento casuale della lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Restituisce la deviazione standard della lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Restituisce la somma si tutti i numeri nella lista.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://it.wikipedia.org/wiki/Numeri_pseudo-casuali\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"frazione casuale\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Restituisce una frazione compresa fra 0.0 (incluso) e 1.0 (escluso).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://it.wikipedia.org/wiki/Numeri_pseudo-casuali\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"intero casuale da %1 a %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Restituisce un numero intero casuale compreso tra i due limiti indicati (inclusi).\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://it.wikipedia.org/wiki/Arrotondamento\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"arrotonda\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"arrotonda verso il basso\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"arrotonda verso l'alto\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Arrotonda un numero verso l'alto o verso il basso.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://it.wikipedia.org/wiki/Radice_quadrata\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"assoluto\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"radice quadrata\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Restituisce il valore assoluto del numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Restituisce e elevato alla potenza del numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Restituisce il logaritmo naturale del numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Restituisce il logaritmo in base 10 del numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Restituisce l'opposto del numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Restituisce 10 elevato alla potenza del numero.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Restituisce la radice quadrata del numero.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://it.wikipedia.org/wiki/Funzione_trigonometrica\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Restituisce l'arco-coseno di un numero.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Restituisce l'arco-seno di un numero.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Restituisce l'arco-tangente di un numero.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Restituisce il coseno di un angolo espresso in gradi (non radianti).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Restituisce il seno di un angolo espresso in gradi (non radianti).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Restituisce la tangente di un angolo espresso in gradi (non radianti).\";\nBlockly.Msg.NEW_VARIABLE = \"Nuova variabile...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nome della nuova variabile:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"conː\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://it.wikipedia.org/wiki/Funzione_(informatica)\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Esegue la funzione definita dall'utente '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://it.wikipedia.org/wiki/Funzione_(informatica)\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Esegue la funzione definita dall'utente '%1' ed usa il suo output.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Crea '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"fai qualcosa\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"per\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Crea una funzione senza output.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"ritorna\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Crea una funzione con un output.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Attenzioneː Questa funzione ha parametri duplicati.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Evidenzia definizione di funzione\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Se un valore è vero allora restituisce un secondo valore.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Attenzioneː Questo blocco può essere usato solo all'interno di una definizione di funzione.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nome inputː\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"input\";\nBlockly.Msg.REMOVE_COMMENT = \"Rimuovi commento\";\nBlockly.Msg.RENAME_VARIABLE = \"Rinomina variabile...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Rinomina tutte le variabili '%1' in:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"aggiungi il testo\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"a\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Aggiunge del testo alla variabile '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"in minuscolo\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"con Iniziali Maiuscole\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"in MAIUSCOLO\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Restituisce una copia del testo in un diverso formato maiuscole/minuscole.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"prendi la prima lettera\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"prendi la lettera # dalla fine\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"prendi la lettera #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"nel testo\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"prendi l'ultima lettera\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"prendi lettera casuale\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Restituisce la lettera nella posizione indicata.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Aggiungi un elemento al testo.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"unisci\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Aggiungi, rimuovi o riordina le sezioni per riconfigurare questo blocco testo.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"alla lettera # dalla fine\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"alla lettera #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"all'ultima lettera\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"nel testo\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"prendi sotto-stringa dalla prima lettera\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"prendi sotto-stringa dalla lettera # dalla fine\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"prendi sotto-stringa dalla lettera #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Restituisce la porzione di testo indicata.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"nel testo\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"trova la prima occorrenza del testo\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"trova l'ultima occorrenza del testo\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Restituisce l'indice della prima occorrenza del primo testo all'interno del secondo testo. Restituisce 0 se il testo non viene trovato.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 è vuoto\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Restituisce vero se il testo fornito è vuoto.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"crea testo con\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Crea un blocco di testo unendo un certo numero di elementi.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"lunghezza di %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Restituisce il numero di lettere (inclusi gli spazi) nel testo fornito.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"scrivi %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Scrive il testo, numero o altro valore indicato.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Richiedi un numero all'utente.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Richiede del testo da parte dell'utente.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"richiedi numero con messaggio\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"richiedi testo con messaggio\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://it.wikipedia.org/wiki/Stringa_(informatica)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Una lettera, una parola o una linea di testo.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"rimuovi spazi da entrambi gli estremi\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"rimuovi spazi a sinistra\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"rimuovi spazi a destra\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Restituisce una copia del testo con gli spazi rimossi ad uno o entrambe le estremità.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"elemento\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Crea 'imposta %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Restituisce il valore di una variabile.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Crea 'prendi %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"a\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"imposta\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Imposta questa variabile ad essere pari all'input.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/ja.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.ja');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"コメントを追加\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"値を変更します。\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"ブロックを折りたたむ\";\nBlockly.Msg.COLLAPSE_BLOCK = \"ブロックを折りたたむ\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"色 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"色 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"割合\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"ブレンド\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"ブレンド2 つの色を指定された比率に混ぜる」  (0.0 ～ 1.0)。\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://ja.wikipedia.org/wiki/色\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"パレットから色を選んでください。\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"ランダムな色\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"ランダムな色を選択します。\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"青\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"緑\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"赤\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"カラーと\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"赤、緑、および青の指定された量で色を作成します。すべての値は 0 ～ 100 の間でなければなりません。\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"ループから抜け出す\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"ループの次の反復処理を続行します。\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"含むループから抜け出します。\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"このループの残りの部分をスキップし、次のイテレーションに進みます。\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"注意: このブロックは、ループ内でのみ使用します。\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"リストで\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"各項目の\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"リストの各項目に対して変数 '%1' のアイテムに設定し、いくつかのステートメントをしてください。\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"%1 から%2、 %3 で\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"で、カウントします。\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"変数 %1は、指定した間隔ごとのカウントを開始番号から 終了番号まで、値をとり、指定したブロックを行う必要があります。\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"場合に条件にブロック追加。\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Ifブロックに、すべてをキャッチする条件を追加。\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"追加、削除、またはセクションを順序変更して、ブロックをこれを再構成します。\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"他\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"他でもし\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"もし\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"値が true の場合はその後ステートメントを行をいくつかします。\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"値が true 場合は、ステートメントの最初のブロックを行います。それ以外の場合は、ステートメントの 2 番目のブロックを行います。\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"最初の値が true 場合は、ステートメントの最初のブロックを行います。それ以外の場合は、2 番目の値が true の場合、ステートメントの 2 番目のブロックをします。\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"最初の値が true 場合は、ステートメントの最初のブロックを行います。2 番目の値が true の場合は、ステートメントの 2 番目のブロックを行います。それ以外の場合は最後のブロックのステートメントを行います。\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://ja.wikipedia.org/wiki/for文\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"してください\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1 回、繰り返します\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"繰り返し\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"回\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"いくつかのステートメントを数回行います。\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"までを繰り返します\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"つつその間、繰り返す4\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"値は false のあいだ、いくつかのステートメントを行います。\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"値は true のあいだ、いくつかのステートメントを行います。\";\nBlockly.Msg.DELETE_BLOCK = \"ブロックを消す\";\nBlockly.Msg.DELETE_X_BLOCKS = \"%1 個のブロックを消す\";\nBlockly.Msg.DISABLE_BLOCK = \"ブロックを無効にします。\";\nBlockly.Msg.DUPLICATE_BLOCK = \"複製\";\nBlockly.Msg.ENABLE_BLOCK = \"ブロックを有効にします。\";\nBlockly.Msg.EXPAND_ALL = \"ブロックを展開します。\";\nBlockly.Msg.EXPAND_BLOCK = \"ブロックを展開します。\";\nBlockly.Msg.EXTERNAL_INPUTS = \"外部入力\";\nBlockly.Msg.HELP = \"ヘルプ\";\nBlockly.Msg.INLINE_INPUTS = \"インライン入力\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"空のリストを作成します。\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"長さゼロ、データ レコード空のリストを返します\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"リスト\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"追加、削除、またはセクションを順序変更して、ブロックを再構成します。\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"これを使ってリストを作成します。\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"リストにアイテムを追加します。\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"アイテム数かぎりないのリストを作成します。\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"最初\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"終しまいから #\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"取得\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"取得と削除\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"最後\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"ランダム\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"削除\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"リストの最初の項目を返信します。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"リスト内の指定位置にある項目を返します。＃ 1 は、最後の項目です。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"リスト内の指定位置にある項目を返します。＃ 1 は、最初の項目です。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"リストの最後の項目を返します。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"ランダム アイテム リストを返します。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"リスト内の最初の項目を削除したあと返します。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"リスト内の指定位置にある項目を削除し、返します。＃ 1 は、最後の項目です。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"リスト内の指定位置にある項目を削除し、返します。＃ 1 は、最後の項目です。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"リスト内の最後の項目を削除したあと返します。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"リストのランダムなアイテムを削除し、返します。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"リスト内の最初の項目を削除します。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"リスト内の指定位置にある項目を削除します。＃ 1 は、最後の項目です。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"リスト内の指定位置にある項目を返します。＃ 1 は、最初の項目です。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"リスト内の最後の項目を削除します。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"リスト内にある任意のアイテムを削除します。\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"最後から＃へ\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"＃へ\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"最後へ\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"最初からサブリストを取得する。\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"端から #のサブリストを取得します。\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"# からサブディレクトリのリストを取得します。\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"リストの指定された部分のコピーを作成してくださ。\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"最初に見つかった項目を検索します。\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"最後に見つかったアイテムを見つける\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"リスト項目の最初/最後に出現するインデックス位置を返します。テキストが見つからない場合は 0 を返します。\";\nBlockly.Msg.LISTS_INLIST = \"リストで\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 が空\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \" %1の長さ\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"リストの長さを返します。\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"アイテム %1 と一緒にリストを作成し %2 回繰り\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"指定された値をなんどか繰り返してリストを作ります。\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"として\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"挿入します。\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"セット\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"リストの先頭に項目を挿入します。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"リスト内の指定位置に項目を挿入します。＃ 1 は、最後の項目です。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"リスト内の指定位置に項目を挿入します。＃ 1 は、最初の項目です。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"リストの末尾に項目を追加します。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"リストに項目をランダムに挿入します。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"リスト内に最初の項目を設定します。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"リスト内の指定された位置に項目を設定します。＃ 1 は、最後の項目です。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"リスト内の指定された位置に項目を設定します。＃ 1 は、最初の項目です。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"リスト内の最後の項目を設定します。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"リスト内にランダムなアイテムを設定します。\";\nBlockly.Msg.LISTS_TOOLTIP = \"リストが空の場合は、true を返します。\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"false\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"True または false を返します。\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"true\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://ja.wikipedia.org/wiki/不等式\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"もし両方がお互いに等しく入力した場合は true を返します。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"最初の入力が 2 番目の入力よりも大きい場合は true を返します。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"もし入力がふたつめの入よりも大きかったらtrueをり返します。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"最初の入力が 2 番目の入力よりも小さいい場合は true を返します。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"もし、最初の入力が二つ目入力より少ないか、おなじであったらTRUEをかえしてください\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"両方の入力が互いに等しくない場合に true を返します。\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"%1 ではないです。\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"入力が false の場合は、true を返します。入力が true の場合は false を返します。\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Null を返します。\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"そして\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"または\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"両方の入力がおんなじ場わいわtrue を返します。\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"最低少なくとも 1 つの入力が true の場合は true を返します。\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"テスト\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://ja.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"false の場合\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"true の場合\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"'テスト' の条件をチェックします。条件が true の場合、'true' の値を返します。それ以外の場合 'false' のを返します。\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://ja.wikipedia.org/wiki/算術\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"2 つの数の合計を返します。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"2 つの数の商を返します。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"2 つの数の差を返します。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"2 つの数の積を返します。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"最初の数を2 番目の値で累乗した結果を返します。\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"に\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"変更\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"'%1' をたします。\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://ja.wikipedia.org/wiki/数学定数\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"いずれかの共通の定数のを返す: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (無限).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"制限%1下リミット%2上限リミット%3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"値を、上限 x と下限 y のあいだに制限んする（上限と下限が、x と  y　とに同じ場合わ、上限の値は　x, 下限の値はy）。\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"割り切れる\";\nBlockly.Msg.MATH_IS_EVEN = \"わ偶数\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"負の値\";\nBlockly.Msg.MATH_IS_ODD = \"奇数です。\";\nBlockly.Msg.MATH_IS_POSITIVE = \"正の値\";\nBlockly.Msg.MATH_IS_PRIME = \"素数です\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"数字が、偶数、奇数、素数、整数、正数、負数、またはそれが特定の数で割り切れる場合かどうかを確認してください。どの制限が一つでも本当でしたら true をかえしてください、そうでない場合わ falseを返してください。\";\nBlockly.Msg.MATH_IS_WHOLE = \"は整数\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"残りの %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"2 つの数値を除算した残りを返します。\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://ja.wikipedia.org/wiki/数\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"数です。\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"リストの平均\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"リストの最大値\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"リストの中央値\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"リストの最小の数\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"一覧モード\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"リストのランダム アイテム\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"リストの標準偏差\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"リストの合計\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"リストの数値の平均 (算術平均) を返します。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"リストの最大数を返します。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"リストの中央値の数を返します。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"リストの最小数を返します。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"リストで最も一般的な項目のリストを返します。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"リストからランダムに要素を返します。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"リウトの標準偏差をかえす\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"全部リストの数をたして返す\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"ランダムな分数\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"ランダムな分数を返すー0.0 (包括) の間のと 1.0 (排他的な)。\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"%1 から %2 への無作為の整数\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"指定した下限の間、無作為なランダムな整数を返します。\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://ja.wikipedia.org/wiki/端数処理\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"概数\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"端数を切り捨てる\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"数値を切り上げ\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"数値を切り上げるか切り捨てる\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://ja.wikipedia.org/wiki/平方根\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"絶対値\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"平方根\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"絶対値を返す\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"数値の e 粂を返す\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"数値の自然対数をかえしてください\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"log 10 を返す。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"負の数を返す\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"１０の　x　乗\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"平方根を返す\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://ja.wikipedia.org/wiki/三角関数\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"arccosine の値を返す\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"番号のarcsine を返すます\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"番号のarctangent を返すます\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"番号のcosineの次数を返す\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"番号のsineの次数を返す\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"番号のtangentの次数を返す\";\nBlockly.Msg.NEW_VARIABLE = \"新しい変数\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"新しい変数の、名前\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"で。\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://ja.wikipedia.org/wiki/サブルーチン\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"ユーザー定義関数 '%1' を実行します。\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://ja.wikipedia.org/wiki/サブルーチン\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"ユーザー定義関数 '%1' を実行し、その出力を使用します。\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"%1をつくる\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://ja.wikipedia.org/wiki/サブルーチン\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"何かしてください\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"宛先\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"出力なしで関数を作成します。\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://ja.wikipedia.org/wiki/サブルーチン\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"返す\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"出力を持つ関数を作成します。\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"警告: この関数は、重複するパラメーターがあります。\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"関数の内容を強調表示します。\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"1番目値が true の場合、2 番目の値を返します。\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"警告: このブロックは、関数定義内でのみ使用できます。\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"入力名:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"入力\";\nBlockly.Msg.REMOVE_COMMENT = \"コメントを削除します。\";\nBlockly.Msg.RENAME_VARIABLE = \"変数の名前を変更.\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"%1の変数すべてを名前変更します。\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"テキストを追加します。\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"宛先\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"変数 '%1' にいくつかのテキストを追加します。\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"小文字に\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"タイトル ケースに\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"大文字に変換する\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"別のケースに、テキストのコピーを返します。\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"最初の文字を得る\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"一番最後の言葉、キャラクターを所得\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"文字# を取得\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"テキストで\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"最後の文字を得る\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"ランダムな文字を得る\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"指定された位置に文字を返します。\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"テキスト をアイテム追加します。\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"結合\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"追加、削除、またはセクションを順序変更して、ブロックを再構成します。\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"文字列の＃ 終わりからの＃\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"# の文字\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"最後のの文字\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"テキストで\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"部分文字列を取得する。\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"部分文字列を取得する #端から得る\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"文字列からの部分文字列を取得 ＃\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"テキストの指定部分を返します。\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"テキストで\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"テキストの最初の出現箇所を検索します。\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"テキストの最後に見つかったを検索します。\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"最初のテキストの二番目のてきすとの、最初と最後の、出現したインデックスをかえします。テキストが見つからない場合は 0 を返します。\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 が空\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"指定されたテキストが空の場合は、true を返します。\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"テキストを作成します。\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"任意の数の項目一部を一緒に接合してテキストの作成します。\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"%1 の長さ\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"指定されたテキストの文字 (スペースを含む) の数を返します。\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"%1 を印刷します。\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"指定したテキスト、番号または他の値を印刷します。\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"ユーザーにプロンプトして数字のインプットを求めます\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"いくつかのテキストを、ユーザーに入力するようにプロンプト。\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"メッセージを送って番号の入力を求める\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"メッセージをプロンプトしてにテキストを求める\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://ja.wikipedia.org/wiki/文字列\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"文字、単語、または行のテキスト。\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"両端のスペースを取り除く\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"左端のスペースを取り除く\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"右端のスペースを取り除く\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"スペースを 1 つまたは両方の端から削除したのち、テキストのコピーを返します。\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"項目\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"'セット%1を作成します。\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"この変数の値を返します。\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"'%1 を取得' を作成します。\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"宛先\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"セット\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"この入力を変数と等しくなるように設定します。\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/ko.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.ko');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"덧글 추가\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"값 변경:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"블록 축소\";\nBlockly.Msg.COLLAPSE_BLOCK = \"블록 축소\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"색 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"색 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"비율\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"혼합\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"두 색을 주어진 비율로 혼합 (0.0 - 1.0)\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://ko.wikipedia.org/wiki/색\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"팔레트에서 색을 고릅니다\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"임의 색상\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"무작위로 색을 고릅니다.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"파랑\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"초록\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"빨강\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"RGB 색\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"빨강,파랑,초록의 값을 이용하여 색을 만드십시오. 모든 값은 0과 100 사이에 있어야 합니다.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"블록 복사\";\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"붙여넣기\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"반복 중단\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"다음 반복\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"현재 반복 실행 블록을, 빠져나갑니다.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"나머지 반복 부분을 더이상 실행하지 않고, 다음 반복을 수행합니다.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"경고 : 이 블록은 반복 실행 블록 안에서만 사용됩니다.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"목록으로\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"각 항목에 대해\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"리스트 안에 들어있는 각 아이템들을, 순서대로 변수 '%1' 에 한 번씩 저장시키고, 그 때 마다 명령을 실행합니다.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"%1에서 %3을 이용하여 %2로\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"으로 계산\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"변수 %1 의 값을 변경하면서 반복 실행합니다. 변수에 저장되는 값은, 첫번째 수부터 두번째 수까지, 일정 값씩 늘어납니다.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"\\\"만약\\\" 블록에 조건 검사를 추가합니다.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"\\\"만약\\\" 블록의 마지막에, 모든 검사 결과가 거짓인 경우 실행할 부분을 추가합니다.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"\\\"만약\\\" 블록의 내용을 추가, 삭제, 재구성 합니다.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"아니라면\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"다른 경우\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"만약에\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"조건식의 계산 결과가 참이면, 명령을 실행합니다.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"조건식의 계산 결과가 참이면, 첫번째 블록의 명령을 실행하고, 그렇지 않으면 두번째 블록의 명령을 실행합니다.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"첫번째 조건식의 계산 결과가 참이면, 첫번째 블록의 명령을 실행하고, 두번째 조건식의 계산 결과가 참이면, 두번째 블록의 명령을 실행합니다.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"첫번째 조건식의 계산 결과가 참이면, 첫번째 블록의 명령을 실행하고, 두번째 조건식의 계산 결과가 참이면, 두번째 블록의 명령을 실행하고, ... , 어떤 조건식의 계산 결과도 참이 아니면, 마지막 블록의 명령을 실행합니다.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://ko.wikipedia.org/wiki/For_루프\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"하기\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1회 반복\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"반복\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"회\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"여러 번 반복해 명령들을 실행합니다.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"다음까지 반복\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"동안 반복\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"값이 거짓일 때, 몇가지 선언을 합니다.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"값이 참일 때, 몇가지 선언을 합니다.\";\nBlockly.Msg.DELETE_BLOCK = \"블록 삭제\";\nBlockly.Msg.DELETE_X_BLOCKS = \"블록 삭제\";\nBlockly.Msg.DISABLE_BLOCK = \"블록 비활성화\";\nBlockly.Msg.DUPLICATE_BLOCK = \"블록 복사 & 붙여넣기\";\nBlockly.Msg.CLEAR_BLOCKS = \"모든 블록 삭제하기\";\nBlockly.Msg.ENABLE_BLOCK = \"블록 활성화\";\nBlockly.Msg.EXPAND_ALL = \"블록 확장\";\nBlockly.Msg.EXPAND_BLOCK = \"블록 확장\";\nBlockly.Msg.EXTERNAL_INPUTS = \"외부 입력\";\nBlockly.Msg.HELP = \"도움말\";\nBlockly.Msg.INLINE_INPUTS = \"내부 입력\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"빈 리스트 생성\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"아이템이 없는, 빈 리스트를 만들어 돌려줍니다.\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"리스트\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"리스트 블록의 내용을 추가, 삭제, 재구성 합니다.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"리스트 만들기\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"아이템을 리스트에 추가합니다.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"원하는 아이템 갯수로 리스트를 생성합니다.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"첫번째\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"마지막 번째 위치부터, # 번째\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"첫번째 위치부터, # 번째\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"아이템 가져오기\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"잘라 내기\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"마지막\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"임의로\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"삭제\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"첫 번째 아이템을 찾아 돌려줍니다.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"특정 위치의 아이템을 찾아 돌려줍니다. #1 은 마지막 아이템.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"특정 위치의 아이템을 찾아 돌려줍니다. #1 은 첫번째 아이템.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"마지막 아이템을 찾아 돌려줍니다.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"리스트의 아이템들 중, 랜덤으로 선택해 돌려줍니다.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"첫 번째 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"특정 위치의 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다. #1 는 마지막 아이템.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"특정 위치의 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다. #1 는 첫번째 아이템.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"마지막 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"랜덤 위치의 아이템을 찾아내 돌려주고,그 아이템을 리스트에서 삭제합니다.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"리스트에서 첫 번째 아이템을 삭제합니다.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"특정 위치의 아이템을 찾아내 삭제합니다. #1 는 마지막 아이템.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"특정 위치의 아이템을 찾아내 삭제합니다. #1 는 첫번째 아이템.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"리스트에서 마지막 아이템을 찾아 삭제합니다.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"리스트에서 랜덤하게 아이템을 삭제합니다.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"끝에서부터 # 번째로\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"앞에서부터 # 번째로\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"마지막으로\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"첫 번째 위치부터, 서브 리스트 추출\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"마지막부터 # 번째 위치부터, 서브 리스트 추출\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"처음 # 번째 위치부터, 서브 리스트 추출\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"특정 부분을 복사해 새로운 리스트로 생성합니다.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"처음으로 나타난 위치\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"마지막으로 나타난 위치\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"아이템이 나타난, 처음 또는 마지막 위치를 찾아 돌려줍니다. 아이템이 없으면 0 돌려줌.\";\nBlockly.Msg.LISTS_INLIST = \"리스트\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1이 비어있습니다\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"%1의 길이\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"리스트에 포함되어있는, 아이템 갯수를 돌려줍니다.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"%1 을 %2 번 넣어, 리스트 생성\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"원하는 값을, 원하는 갯수 만큼 넣어, 새로운 리스트를 생성합니다.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"에\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"에서 원하는 위치에 삽입\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"에서 설정\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"아이템을 리스트의 첫번째 위치에 삽입합니다.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"아이템을 리스트의 특정 위치에 삽입합니다. 마지막 아이템은 #1.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"아이템을 리스트의 특정 위치에 삽입합니다. 첫번째 아이템은 #1.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"리스트의 마지막에 아이템을 추가합니다.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"리스트의 랜덤 위치에 아이템을 삽입합니다.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"첫 번째 위치의 아이템으로 설정합니다.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"특정 번째 위치의 아이템으로 설정합니다. #1 는 마지막 아이템.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"특정 번째 위치의 아이템으로 설정합니다. #1 는 첫번째 아이템.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"마지막 아이템으로 설정합니다.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"랜덤 위치의 아이템으로 설정합니다.\";\nBlockly.Msg.LISTS_TOOLTIP = \"목록이 비었을 때 참을 반환합니다.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"거짓\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"참 혹은 거짓 모두 반환합니다.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"참\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"두 값이 같으면, 참(true) 값을 돌려줍니다.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"첫 번째 값이 두 번째 값보다 크면, 참(true) 값을 돌려줍니다.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"첫 번째 값이 두 번째 값보다 크거나 같으면, 참(true) 값을 돌려줍니다.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"첫 번째 값이 두 번째 값보다 작으면, 참(true) 값을 돌려줍니다.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"첫 번째 값이 두 번째 값보다 작거나 같으면, 참(true) 값을 돌려줍니다.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"두 값이 서로 다르면, 참(true) 값을 돌려줍니다.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"%1 의 반대\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"입력값이 거짓이라면 참을 반환합니다. 참이라면 거짓을 반환합니다.\";\nBlockly.Msg.LOGIC_NULL = \"빈 값\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"빈 값을 반환합니다.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"그리고\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"또는\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"두 값이 모두 참(true) 값이면, 참 값을 돌려줍니다.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"적어도 하나의 값이 참일 경우 참을 반환합니다.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"테스트\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"만약 거짓이라면\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"만약 참이라면\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"'검사' 를 진행해, 결과가 참(true)이면 '참이면' 부분의 값을 돌려줍니다. ; 결과가 참이 아니면, '거짓이면' 부분의 값을 돌려줍니다.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"두 수의 합을 반환합니다.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"두 수의 나눈 결과를 반환합니다.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"두 수간의 차이를 반환합니다.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"두 수의 곱을 반환합니다.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"첫 번째 수를 두 번째 수 만큼, 거듭제곱 한 결괏값을 돌려줍니다.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"만큼\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"값 변경\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"변수 '%1' 에 저장되어있는 값에, 어떤 수를 더해, 변수에 다시 저장합니다.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"일반적인 상수 값들 중 하나를 돌려줍니다. : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"%1 의 값을, 최소 %2 최대 %3 으로 조정\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"어떤 수를, 특정 범위의 값이 되도록 강제로 조정합니다.\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"가 다음 수로 나누어 떨어지면 :\";\nBlockly.Msg.MATH_IS_EVEN = \"가 짝수(even) 이면\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"가 음(-)수 이면\";\nBlockly.Msg.MATH_IS_ODD = \"가 홀수(odd) 이면\";\nBlockly.Msg.MATH_IS_POSITIVE = \"가 양(+)수 이면\";\nBlockly.Msg.MATH_IS_PRIME = \"가 소수(prime) 이면\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"어떤 수가 짝 수, 홀 수, 소 수, 정 수, 양 수, 음 수, 나누어 떨어지는 수 인지 검사해 결괏값을 돌려줍니다. 참(true) 또는 거짓(false) 값을 돌려줌.\";\nBlockly.Msg.MATH_IS_WHOLE = \"가 정수이면\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"%1 를 %2 로 나눈 나머지\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"첫 번째 수를 두 번째 수로 나눈, 나머지 값을 돌려줍니다.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"x\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"수\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"평균값\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"최대값\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"중간값\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"최소값\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"가장 여러 개 있는 값\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"랜덤 아이템\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"표준 편차\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"합\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"리스트에 들어있는 수(값)들에 대해, 산술 평균(arithmetic mean) 한 값을 돌려줍니다.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"리스트에 들어있는 수(값) 들 중, 가장 큰(max) 수(값)를 돌려줍니다.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"리스트에 들어있는 수(값) 들 중, 중간(median) 수(값)를 돌려줍니다.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"리스트에 들어있는 수(값) 들 중, 가장 작은(min) 수(값)를 돌려줍니다.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"리스트에 들어있는 아이템들 중에서, 가장 여러 번 들어있는 아이템들을 리스트로 만들어 돌려줍니다. (최빈값, modes)\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"리스트에 들어있는 아이템들 중에서, 랜덤(random)으로 아이템을 돌려줍니다.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"리스트에 들어있는 수(값)들에 대해, 표준 편차(standard deviation) 를 구해 돌려줍니다.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"리스트에 들어있는 수(값)들을, 모두 합(sum) 한, 총합(sum)을 돌려줍니다.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"랜덤 실수(0.0<= f <1.0)\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"랜덤 실수 값(0.0<= f <1.0)을 돌려줍니다.\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"랜덤정수(%1<= n <=%2)\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"주어진 범위에서, 랜덤 정수값을 돌려줍니다.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"반올림\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"버림\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"올림\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"어떤 수를 반올림/올림/버림한 결과를, 정수값으로 돌려줍니다.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"절대값\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"제곱근\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"어떤 수의 절대값(absolute)을 계산한 결과를, 정수값으로 돌려줍니다.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"e 의, 거듭제곱(power) 값을 돌려줍니다.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"어떤 수의, 자연로그(natural logarithm) 값을 돌려줍니다.(밑 e, 예시 log e x)\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"어떤 수의, 기본로그(logarithm) 값을 돌려줍니다.(밑 10, 예시 log 10 x)\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"음(-)/양(+), 부호를 반대로 하여 값을 돌려줍니다.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"10 의, 거듭제곱(power) 값을 돌려줍니다.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"숫자의 제곱근을 반환합니다.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"어떤 수에 대한, acos(arccosine) 값을 돌려줍니다.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"어떤 수에 대한, asin(arcsine) 값을 돌려줍니다.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"어떤 수에 대한, atan(arctangent) 값을 돌려줍니다.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"어떤 각도(degree, radian 아님)의, cos(cosine) 값을 계산해 돌려줍니다.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"어떤 각도(degree, radian 아님)의, sin(sine) 값을 계산해 돌려줍니다.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"어떤 각도(degree, radian 아님)의,  tan(tangent) 값을 계산해 돌려줍니다.\";\nBlockly.Msg.NEW_VARIABLE = \"새 변수\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"새 변수 이름:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"사용:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"미리 정의해 둔 '%1' 함수를 실행합니다.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"미리 정의해 둔 '%1' 함수를 실행하고, 함수를 실행한 결과 값을 돌려줍니다.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"'%1' 생성\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"함수 이름\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"함수\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"실행 후, 결과 값을 돌려주지 않는 함수를 만듭니다.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"다음을 돌려줌\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"실행 후, 결과 값을 돌려주는 함수를 만듭니다.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"경고: 이 함수에는, 같은 이름을 사용하는 매개 변수들이 있습니다.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"함수 정의 찾기\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"값이 참이라면, 두번째 값을 반환합니다.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"경고: 이 블록은, 함수 정의 블록 안에서만 사용할 수 있습니다.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"매개 변수:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"매개 변수들\";\nBlockly.Msg.REMOVE_COMMENT = \"내용 제거\";\nBlockly.Msg.RENAME_VARIABLE = \"변수 이름 바꾸기:\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"'%1' 변수 이름을 바꾸기:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"내용 덧붙이기\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"다음\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"'%1' 의 마지막에 문장을 덧붙입니다.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"소문자로\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"첫 문자만 대문자로\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"대문자로\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"영문 대소문자 형태를 변경해 돌려줍니다.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"에서, 첫 번째 문자 얻기\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"에서, 마지막부터 # 번째 위치의 문자 얻기\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"에서, 앞에서부터 # 번째 위치의 문자 얻기\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"문장\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"에서, 마지막 문자 얻기\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"에서, 랜덤하게 한 문자 얻기\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"특정 번째 위치에서, 문자를 얻어내 돌려줍니다.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"문장을 만들 조각 아이템\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"가입\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"이 문장 블록의 구성을 추가, 삭제, 재구성 합니다.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"끝에서부터 # 번째 문자까지\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"# 번째 문자까지\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"마지막 문자까지\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"문장\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"에서, 처음부터 얻어냄\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"에서, 마지막에서 # 번째부터 얻어냄\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"에서, 처음부터 # 번째 문자부터 얻어냄\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"문장 중 일부를 얻어내 돌려줍니다.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"문장\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"에서 다음 문장이 처음으로 나타난 위치 찾기 :\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"에서 다음 문장이 마지막으로 나타난 위치 찾기 :\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"어떤 문장이 가장 처음 나타난 위치 또는, 가장 마지막으로 나타난 위치를 찾아 돌려줍니다. 찾는 문장이 없는 경우는 0 값을 돌려줌.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1이 비어있습니다\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"입력된 문장이, 빈 문장(\\\"\\\")이면 참(true) 값을 돌려줍니다.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"텍스트 만들기\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"여러 개의 아이템들을 연결해(묶어), 새로운 문장을 만듭니다.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"다음 문장의 문자 개수 %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"입력된 문장의, 문자 개수를 돌려줍니다.(공백문자 포함)\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"다음 내용 출력 %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"원하는 문장, 수, 값 등을 출력합니다.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"수 입력 받음.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"문장 입력 받음.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"다음 안내 멘트를 활용해 수 입력\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"다음 안내 멘트를 활용해 문장 입력\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"문자, 단어, 문장.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"다음 문장에서 양쪽(왼쪽+오른쪽) 공백문자(space) 제거 :\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"다음 문장에서 왼쪽 공백문자(space) 제거 :\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"다음 문장에서 오른쪽 공백문자(space) 제거 :\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"문장의 왼쪽/오른쪽/양쪽에서 스페이스 문자를 제거해 돌려줍니다.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"항목\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"'집합 %1' 생성\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"변수에 저장 되어있는 값을 돌려줍니다.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"'%1 값 읽기' 블록 생성\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"를 다음 값으로 변경\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"값 변경:\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"변수의 값을 입력한 값으로 변경해 줍니다.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/lrc.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.lrc');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"نظرتونه اضاف بکید\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"ارزشت آلشت کو:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Collapse Blocks\";  // untranslated\nBlockly.Msg.COLLAPSE_BLOCK = \"Collapse Block\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"رن 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"رن 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"نسوت\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"شیوسته\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"هر کوم د رنگیانه وا نسوت دائه بیه به شیون(0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"یه رن د رنگ دو انتخاو بکید\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"رن بختکی\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"یه رنگ بختکی انتخاو بکید\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"آوی\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"سوز\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"سور\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"رن وا\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Create a colour with the specified amount of red, green, and blue.  All values must be between 0 and 100.\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"حلقه نه خراو کو\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continue with next iteration of loop\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"حلقه شومل بیه نه خراو کو\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Skip the rest of this loop, and continue with the next iteration.\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Warning: This block may only be used within a loop.\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"د نوم گه\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"سی هر قلم\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"For each item in a list, set the variable '%1' to the item, and then do some statements.\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"from %1 to %2 by %3\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"اشماردن وا\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Add a condition to the if block.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Add a final, catch-all condition to the if block.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this if block.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"هنی\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"هنی ار\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"ار\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"If a value is true, then do some statements.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"If a value is true, then do the first block of statements.  Otherwise, do the second block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.  If none of the values are true, do the last block of statements.\";  // untranslated\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"انجوم بئه\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1 تکرار کو چن بار\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"د نو انجوم دئن\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"وختیا\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Do some statements several times.\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"تا تکرار کو\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"تا تکرار کو\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"While a value is false, then do some statements.\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"While a value is true, then do some statements.\";  // untranslated\nBlockly.Msg.DELETE_BLOCK = \"Delete Block\";  // untranslated\nBlockly.Msg.DELETE_X_BLOCKS = \"Delete %1 Blocks\";  // untranslated\nBlockly.Msg.DISABLE_BLOCK = \"Disable Block\";  // untranslated\nBlockly.Msg.DUPLICATE_BLOCK = \"کپی کردن\";\nBlockly.Msg.ENABLE_BLOCK = \"Enable Block\";  // untranslated\nBlockly.Msg.EXPAND_ALL = \"Expand Blocks\";  // untranslated\nBlockly.Msg.EXPAND_BLOCK = \"Expand Block\";  // untranslated\nBlockly.Msg.EXTERNAL_INPUTS = \"داده یا وه دری\";\nBlockly.Msg.HELP = \"هومياری\";\nBlockly.Msg.INLINE_INPUTS = \"داده یا مئنجا\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"یه گل نوم گه حالی راس بکیت\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returns a list, of length 0, containing no data records\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"نوم گه\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this list block.\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"create list with\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Add an item to the list.\";  // untranslated\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Create a list with any number of items.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"اولی\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# تا آخر\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"گرتن\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"گرتن و جاوه جا بیئن\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"آخر\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"بختكی\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"ؤرداشتن\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returns the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returns the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returns a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Removes and returns the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Removes and returns the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Removes and returns the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Removes and returns the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Removes and returns a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Removes the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Removes the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Removes the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Removes the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Removes a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"to # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"سی#\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"سی آخر\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"get sub-list from first\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"get sub-list from # from end\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"get sub-list from #\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Creates a copy of the specified portion of a list.\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"find first occurrence of item\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"find last occurrence of item\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.LISTS_INLIST = \"د نوم گه\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 حالیه\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"length of %1\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returns the length of a list.\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"create list with item %1 repeated %2 times\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Creates a list consisting of the given value repeated the specified number of times.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"چی\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"بنه د\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserts the item at the start of a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserts the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserts the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Append the item to the end of a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserts the item randomly in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Sets the first item in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Sets the item at the specified position in a list.  #1 is the last item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Sets the item at the specified position in a list.  #1 is the first item.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Sets the last item in a list.\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Sets a random item in a list.\";  // untranslated\nBlockly.Msg.LISTS_TOOLTIP = \"Returns true if the list is empty.\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"غلط\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"هم غلط و هم راس ورگن\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"راست و دوروست\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Return true if both inputs equal each other.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Return true if the first input is greater than the second input.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Return true if the first input is greater than or equal to the second input.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Return true if the first input is smaller than the second input.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Return true if the first input is smaller than or equal to the second input.\";  // untranslated\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Return true if both inputs are not equal to each other.\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"نه %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returns true if the input is false.  Returns false if the input is true.\";  // untranslated\nBlockly.Msg.LOGIC_NULL = \"خمثی\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returns null.\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_AND = \"و\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"یا\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Return true if both inputs are true.\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Return true if at least one of the inputs is true.\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"آزماشت کردن\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"ار غلط بی\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"ار درس بی\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\";  // untranslated\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"وه انازه دو گل شماره ورگن.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Return the quotient of the two numbers.\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Return the difference of the two numbers.\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Return the product of the two numbers.\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Return the first number raised to the power of the second number.\";  // untranslated\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"وا\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"آلشت بكيد\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Add a number to variable '%1'.\";  // untranslated\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";  // untranslated\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"یه وا بهر بیه\";\nBlockly.Msg.MATH_IS_EVEN = \"همیشه هیئش\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"منفیه\";\nBlockly.Msg.MATH_IS_ODD = \"تهنائه\";\nBlockly.Msg.MATH_IS_POSITIVE = \"مثبته\";\nBlockly.Msg.MATH_IS_PRIME = \"is prime\";  // untranslated\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";  // untranslated\nBlockly.Msg.MATH_IS_WHOLE = \"همشه\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"remainder of %1 ÷ %2\";  // untranslated\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Return the remainder from dividing the two numbers.\";  // untranslated\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"یه شماره.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"مینجاگه نوم گه\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"max of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"مینجا نوم گه\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"min of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modes of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"random item of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standard deviation of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"sum of list\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Return the average (arithmetic mean) of the numeric values in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Return the largest number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Return the median number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Return the smallest number in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Return a list of the most common item(s) in the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Return a random element from the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Return the standard deviation of the list.\";  // untranslated\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Return the sum of all the numbers in the list.\";  // untranslated\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"random fraction\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"random integer from %1 to %2\";  // untranslated\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Return a random integer between the two specified limits, inclusive.\";  // untranslated\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"گرد کردن\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"وه هار گرد کردن\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"وه رو گرد کردن\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Round a number up or down.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"تموم و کمال\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"چارسوک ریشه\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Return the absolute value of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Return e to the power of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Return the natural logarithm of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Return the base 10 logarithm of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Return the negation of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Return 10 to the power of a number.\";  // untranslated\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Return the square root of a number.\";  // untranslated\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Return the arccosine of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Return the arcsine of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Return the arctangent of a number.\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Return the cosine of a degree (not radian).\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Return the sine of a degree (not radian).\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Return the tangent of a degree (not radian).\";  // untranslated\nBlockly.Msg.NEW_VARIABLE = \"New variable...\";  // untranslated\nBlockly.Msg.NEW_VARIABLE_TITLE = \"New variable name:\";  // untranslated\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"وا:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Run the user-defined function '%1'.\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Run the user-defined function '%1' and use its output.\";  // untranslated\nBlockly.Msg.PROCEDURES_CREATE_DO = \"راس کردن%1\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"do something\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"سی\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Creates a function with no output.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"ورگنیئن\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Creates a function with an output.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Warning: This function has duplicate parameters.\";  // untranslated\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Highlight function definition\";  // untranslated\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"If a value is true, then return a second value.\";  // untranslated\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Warning: This block may be used only within a function definition.\";  // untranslated\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"نوم داده:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"داده یا\";\nBlockly.Msg.REMOVE_COMMENT = \"نظر جا وه جا کو\";\nBlockly.Msg.RENAME_VARIABLE = \"Rename variable...\";  // untranslated\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Rename all '%1' variables to:\";  // untranslated\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"append text\";  // untranslated\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"سی\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Append some text to variable '%1'.\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"سی واج کؤچک\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"to Title Case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"سی حرف گپ\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FIRST = \"get first letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"get letter # from end\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"get letter #\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"د متن\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"get last letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"get random letter\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returns the letter at the specified position.\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Add an item to the text.\";  // untranslated\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"پیوسن\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"سی واج# تا آخر\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"سی واج#\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"سی آخرین واج\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"د متن\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"get substring from first letter\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"get substring from letter # from end\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"get substring from letter #\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"د متن\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"find first occurrence of text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"find last occurrence of text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 حالیه\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returns true if the provided text is empty.\";  // untranslated\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"راس کردن متن وا\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Create a piece of text by joining together any number of items.\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"length of %1\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returns the number of letters (including spaces) in the provided text.\";  // untranslated\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"print %1\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Print the specified text, number or other value.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Prompt for user for a number.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Prompt for user for some text.\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"prompt for number with message\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"prompt for text with message\";  // untranslated\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"A letter, word, or line of text.\";  // untranslated\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"trim spaces from both sides of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"trim spaces from left side of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"trim spaces from right side of\";  // untranslated\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Return a copy of the text with spaces removed from one or both ends.\";  // untranslated\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"item\";  // untranslated\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Create 'set %1'\";  // untranslated\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returns the value of this variable.\";  // untranslated\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create 'get %1'\";  // untranslated\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"سی\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Sets this variable to be equal to the input.\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/ms.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.ms');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Berikan Komen\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Ubah nilai:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Lipat Blok²\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Lipat Blok\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"warna 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"warna 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"nisbah\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"adun\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Campurkan dua warna sekali pada nisbah yang ditentukan (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://ms.wikipedia.org/wiki/Warna\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Pilih satu warna daripada palet.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"warna rawak\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Pilih satu warna secara rawak.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"biru\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"hijau\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"merah\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"warnakan\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Peroleh satu warna dengan menentukan amaun campuran merah, hijau dan biru. Kesemua nilai haruslah antara 0 hingga 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"Keluar daripada gelung lingkaran\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"Teruskan dengan pengulangan seterusnya gelung\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Pecahkan kandungan lingkaran.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Langkau seluruh gelung ini, dan teruskan dengan lelaran seterusnya.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Amaran: Blok ini hanya boleh digunakan dalam satu lingkaran.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"dalam senarai\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"untuk setiap perkara\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Untuk setiap perkara dalam senarai, tetapkan pembolehubah '%1' pada perkara, kemudian lakukan beberapa perintah.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"dari %1 hingga %2 selang %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"kira dengan\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Gunakan pembolehubah %1 pada nilai-nilai dari nombor pangkal hingga nombor hujung, mengira mengikut selang yang ditentukan, dan lakukan blok-blok yang tertentu.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Tambah satu syarat kepada blok jika.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Tambah yang terakhir, alihkan semua keadaan ke blok jika.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Tambah, alih keluar, atau susun semula bahagian-bahagian untuk menyusun semula blok jika.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"lain\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"lain jika\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"jika\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Jika nilai yang benar, lakukan beberapa penyata.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Jika suatu nilai benar, lakukan penyata blok pertama.  Jika tidak, bina penyata blok kedua.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Jika nilai yang pertama adalah benar, lakukan penyata pertama blok.  Sebaliknya, jika nilai kedua adalah benar, lakukan penyata blok kedua.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Jika nilai yang pertama adalah benar, lakukan penyata blok pertama.  Sebaliknya, jika nilai kedua adalah benar, lakukan penyata blok kedua.  Jika tiada nilai adalah benar, lakukan penyata blok terakhir.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"lakukan\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"ulang %1 kali\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"ulang\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"kali\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Lakukan perintah berulang kali.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"ulangi sehingga\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"ulangi apabila\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Lakukan beberapa perintah apabila nilainya palsu (false).\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Lakukan beberapa perintah apabila nilainya benar (true).\";\nBlockly.Msg.DELETE_BLOCK = \"Hapuskan Blok\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Hapuskan %1 Blok\";\nBlockly.Msg.DISABLE_BLOCK = \"Matikan Blok\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Pendua\";\nBlockly.Msg.ENABLE_BLOCK = \"Hidupkan Blok\";\nBlockly.Msg.EXPAND_ALL = \"Buka Blok²\";\nBlockly.Msg.EXPAND_BLOCK = \"Buka Blok\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Input Luaran\";\nBlockly.Msg.HELP = \"Bantuan\";\nBlockly.Msg.INLINE_INPUTS = \"Input Sebaris\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"Wujudkan senarai kosong\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Kembalikan senarai panjang 0, yang tidak mengandungi rekod data\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"senarai\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Tambah, alih keluar, atau susun semula bahagian-bahagian untuk menyusun semula senarai blok.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"wujudkan senarai dengan\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Tambah item ke dalam senarai.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Wujudkan senarai dengan apa jua nombor item.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"pertama\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# dari akhir\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"dapatkan\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"dapat dan alihkan\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"terakhir\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"rawak\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"alihkan\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Kembalikan item pertama dalam senarai.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Kembalikan item dalam kedudukan yang ditetapkan dalam senarai. #1 ialah item terakhir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Kembalikan item dalam kedudukan yang ditetapkan dalam senarai. #1 ialah item terakhir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Kembalikan item pertama dalam senarai.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Kembalikan item rawak dalam senarai.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Alihkan dan kembalikan item pertama dalam senarai.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Alihkan dan kembalikan item mengikut spesifikasi posisi dalam senarai. #1 ialah item terakhir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Alihkan dan kembalikan item mengikut spesifikasi posisi dalam senarai. #1 ialah item pertama.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Alihkan dan kembalikan item terakhir dalam senarai.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Alihkan dan kembalikan item rawak dalam senarai.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Alihkan item pertama dalam senarai.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Alihkan item mengikut spesifikasi posisi dalam senarai. #1 ialah item terakhir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Alihkan item pada posisi mengikut spesifikasi dalam senarai. #1 ialah item pertama.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Alihkan item terakhir dalam senarai.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Alihkan item rawak dalam senarai.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"ke  # dari akhir\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"ke #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"ke akhir\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"dapatkan sub-senarai daripada pertama\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"dapatkan sub-senarai daripada # daripada terakhir\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"dapatkan sub-senarai daripada #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Wujudkan salinan bahagian yang ditentukan dari senarai.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"cari pertama item kejadian\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"cari kejadian akhir item\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Kembalikan indeks kejadian pertama/terakhir item dalam senarai. Kembalikan 0 jika teks tidak ditemui.\";\nBlockly.Msg.LISTS_INLIST = \"dalam senarai\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 adalah kosong\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"panjang %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Kembalikan panjang senarai\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"wujudkan senarai dengan item %1 diulangi %2 kali\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Wujudkan senarai yang terdiri daripada nilai berulang mengikut nombor yang ditentukan.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"sebagai\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"masukkan pada\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"set\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Selit item pada permulaan senarai.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Masukkan item pada posisi yang ditentukan dalam senarai. #1 ialah item terakhir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Masukkan item pada posisi yand ditentukan dalam senarai. #1 ialah item terakhir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Tambahkan item dalam senarai akhir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Selit item secara rawak di dalam senarai.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Set item pertama dalam senarai.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Masukkan item pada posisi yang ditentukan dalam senarai. #1 ialah item terakhir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Masukkan item pada posisi yang ditentukan dalam senarai. #1 ialah item terakhir.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Set item terakhir dalam senarai.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Set item rawak dalam senarai.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Kembalikan benar jika senarai kosong.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"palsu\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Kembalikan samada benar atau palsu.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"benar\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://id.wikipedia.org/wiki/Pertidaksamaan\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Kembali benar jika kedua-dua input benar antara satu sama lain.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Kembali benar jika input pertama adalah lebih besar daripada input kedua.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Kembali benar jika input pertama adalah lebih besar daripada atau sama dengan input kedua.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Kembali benar jika input pertama adalah lebih kecil daripada input kedua.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Kembali benar jika input pertama adalah lebih kecil daripada atau sama dengan input kedua.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Taip balik benar jika kedua-dua input tidak sama.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"bukan %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"'Benar' akan dibalas jika inputnya salah. 'Salah' akan dibalas jika inputnya benar.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returns null.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"dan\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"atau\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Return true if both inputs are true.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Return true if at least one of the inputs is true.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"Jika palsu\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"Jika benar\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://ms.wikipedia.org/wiki/Aritmetik\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Return the sum of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Taip balik hasil bahagi dua nombor tersebut.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Taip balik hasil tolak dua nombor tersebut.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Taip balik hasil darab dua nombor tersebut.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Return the first number raised to the power of the second number.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://id.wikipedia.org/wiki/Perjumlahan\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"oleh\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"perubahan\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Tambah nombor kepada pembolehubah '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://ms.wikipedia.org/wiki/Pemalar_matematik\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"Boleh dibahagikan dengan\";\nBlockly.Msg.MATH_IS_EVEN = \"Adalah genap\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"negatif\";\nBlockly.Msg.MATH_IS_ODD = \"aneh\";\nBlockly.Msg.MATH_IS_POSITIVE = \"adalah positif\";\nBlockly.Msg.MATH_IS_PRIME = \"is prime\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";\nBlockly.Msg.MATH_IS_WHOLE = \"is whole\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://id.wikipedia.org/wiki/Operasi_modulus\";\nBlockly.Msg.MATH_MODULO_TITLE = \"remainder of %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Taip balik baki yang didapat daripada pembahagian dua nombor tersebut.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://ms.wikipedia.org/wiki/Nombor\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Suatu nombor.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"purata daripada senarai\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"Max senarai\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"Median senarai\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"min dalam senarai\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"jenis senarai\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"Item rawak daripada senarai\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"sisihan piawai bagi senarai\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"Jumlah senarai\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Kembalikan purata (min aritmetik) nilai-nilai angka di dalam senarai.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Pulangkan jumlah terbesar dalam senarai.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Kembalikan nombor median dalam senarai.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Kembalikan nombor terkecil dalam senarai.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Kembali senarai item yang paling biasa dalam senarai.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Kembalikan elemen rawak daripada senarai.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Kembali dengan sisihan piawai daripada senarai.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Kembalikan jumlah semua nombor dalam senarai.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"pecahan rawak\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Kembali sebahagian kecil rawak antara 0.0 (inklusif) dan 1.0 (eksklusif).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"integer rawak dari %1ke %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Kembalikan integer rawak diantara dua had yang ditentukan, inklusif.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"pusingan\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"Pusingan ke bawah\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"pusingan ke atas\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Bulat nombor yang naik atau turun.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://ms.wikipedia.org/wiki/Punca_kuasa_dua\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"mutlak\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"Punca kuasa dua\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Kembalikan nilai mutlak suatu nombor.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Kembalikan e kepada kuasa nombor.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Kembali dalam logaritma nombor asli.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Kembali logarithm 10 asas nombor.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Kembalikan nombor yang songsang.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Kembalikan 10 kepada kuasa nombor.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Kembalikan punca kuasa nombor.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://ms.wikipedia.org/wiki/Fungsi_trigonometri\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Kembali arccosine beberapa nombor.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Kembalikan arcsince beberapa nombor.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Kembalikan beberapa nombor arctangent.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Kembalikan darjah kosinus (bukan radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Kembalikan darjah sine (bukan radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Kembalikan darjah tangen (bukan radian).\";\nBlockly.Msg.NEW_VARIABLE = \"Pembolehubah baru...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nama pembolehubah baru:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"dengan:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://ms.wikipedia.org/wiki/Fungsi\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Run the user-defined function '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://ms.wikipedia.org/wiki/Fungsi\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Run the user-defined function '%1' and use its output.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Hasilkan '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"Buat sesuatu\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"Untuk\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Menghasilkan suatu fungsi tanpa output.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"kembali\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Mencipta satu fungsi dengan pengeluaran.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Amaran: Fungsi ini mempunyai parameter yang berganda.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Serlahkan definisi fungsi\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"If a value is true, then return a second value.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Amaran: Blok ini hanya boleh digunakan dalam fungsi definisi.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"Nama input:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"Input-input\";\nBlockly.Msg.REMOVE_COMMENT = \"Padamkan Komen\";\nBlockly.Msg.RENAME_VARIABLE = \"Tukar nama pembolehubah...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Tukar nama semua pembolehubah '%1' kepada:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"append text\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"Untuk\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Append some text to variable '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"Kepada huruf kecil\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"to Title Case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"Kepada HURUF BESAR\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"get first letter\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"get letter # from end\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"get letter #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"Dalam teks\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"Dapatkan abjad terakhir\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"Dapatkan abjad rawak\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returns the letter at the specified position.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Add an item to the text.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"Sertai\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"to letter # from end\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"to letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"untuk huruf terakhir\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"dalam teks\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"get substring from first letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"get substring from letter # from end\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"get substring from letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"dalam teks\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"mencari kejadian pertama teks\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"mencari kejadian terakhir teks\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Kembalikan Indeks kejadian pertama/terakhir dari teks pertama ke dalam teks kedua.  Kembalikan 0 Jika teks tidak ditemui.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 adalah kosong\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Kembalikan benar jika teks yang disediakan adalah kosong.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"hasilkan teks dengan\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Hasilkan sebahagian teks dengan menghubungkan apa jua nombor item.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"panjang %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Kembalikan jumlah huruf (termasuk ruang) dalam teks yang disediakan.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"cetak %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Cetak teks yang ditentukan, nombor atau nilai lain.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Peringatan kepada pengguna untuk nombor.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Peringatkan pengguna untuk sebahagian teks.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"Prom untuk nombor dengan mesej\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"Prom untuk teks dengan mesej\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://ms.wikipedia.org/wiki/Rentetan\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Huruf, perkataan, atau baris teks.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"mengurangkan kawasan dari kedua-dua belah\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"mengurangkan ruang dari sebelah kiri\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"mengurangkan kawasan dari sisi kanan\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Kembali salinan teks dengan ruang yang dikeluarkan daripada satu atau hujung kedua belah.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"Perkara\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Hasilkan 'set %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Kembalikan nilai pemboleh ubah ini.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Hasilkan 'set %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"ke\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Set pembolehubah ini supaya sama dengan input.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/nb.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.nb');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Legg til kommentar\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Bytt verdi:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Skjul blokker\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Skjul blokk\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"farge 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"farge 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"forhold\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"blande\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Blander to farger sammen med et gitt forhold (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Velg en farge fra paletten.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"tilfeldig farge\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Velg en tilfeldig farge.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blå\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"grønn\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"rød\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"farge med\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Lag en farge med angitt verdi av rød, grønn og blå. Alle verdier må være mellom 0 og 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"bryt ut av løkken\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"fortsett med neste gjentakelse av løkken\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Bryt ut av den gjeldende løkken.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Hopp over resten av denne løkken og fortsett med neste gjentakelse.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Advarsel: Denne blokken kan kun brukes innenfor en løkke.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"i listen\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"for hvert element\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"For hvert element i en liste, angi variabelen '%1' til elementet, og deretter lag noen setninger.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"fra %1 til %2 med %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"tell med\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Ha variabel %1 ta verdiene fra start nummer til slutt nummer, telle med spesifisert intervall og lag de spesifiserte blokkene.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Legg til en betingelse til hvis blokken.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Legg til hva som skal skje hvis de andre ikke slår til.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Legg til, fjern eller flytt seksjoner i denne hvis-blokken.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"ellers\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"ellers hvis\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"hvis\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Hvis dette er sant, så gjør følgende.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Hvis dette er sant, så utfør den første blokken av instruksjoner. Hvis ikke, utfør den andre blokken.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Hvis det første stemmer, så utfør den første blokken av instruksjoner. Ellers, hvis det andre stemmer, utfør den andre blokken av instruksjoner.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Hvis den første verdien er sann, så utfør den første blokken med setninger. Ellers, hvis den andre verdien er sann, så utfør den andre blokken med setninger. Hvis ingen av verdiene er sanne, så utfør den siste blokken med setninger.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"gjør\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"gjenta %1 ganger\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"gjenta\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"ganger\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Gjenta noen instruksjoner flere ganger.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"gjenta til\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"gjenta mens\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Så lenge et utsagn ikke stemmer, gjør noen instruksjoner.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Så lenge et utsagn stemmer, utfør noen instruksjoner.\";\nBlockly.Msg.DELETE_BLOCK = \"Slett blokk\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Slett %1 blokk(er)\";\nBlockly.Msg.DISABLE_BLOCK = \"Deaktiver blokk\";\nBlockly.Msg.DUPLICATE_BLOCK = \"duplikat\";\nBlockly.Msg.ENABLE_BLOCK = \"Aktiver blokk\";\nBlockly.Msg.EXPAND_ALL = \"Utvid blokker\";\nBlockly.Msg.EXPAND_BLOCK = \"Utvid blokk\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Eksterne kilder\";\nBlockly.Msg.HELP = \"Hjelp\";\nBlockly.Msg.INLINE_INPUTS = \"Interne kilder\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"opprett en tom liste\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returnerer en tom liste, altså med lengde 0\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"liste\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Legg til, fjern eller endre rekkefølgen for å endre på denne delen av listen.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"lag en liste med\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Tilføy et element til listen.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Lag en liste med et vilkårlig antall elementer.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"først\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# fra slutten\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"hent\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"hent og fjern\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"siste\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"tilfeldig\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"fjern\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returnerer det første elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returner elementet på den angitte posisjonen i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returner elementet på den angitte posisjonen i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returnerer det siste elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returnerer et tilfeldig element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Fjerner og returnerer det første elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Fjerner og returnerer elementet ved en gitt posisjon i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Fjerner og returnerer elementet ved en gitt posisjon i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Fjerner og returnerer det siste elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Fjerner og returnerer et tilfeldig element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Fjerner det første elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Fjerner et element ved en gitt posisjon i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Fjerner et element ved en gitt posisjon i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Fjerner det siste elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Fjerner et tilfeldig element i en liste.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"til # fra slutten\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"til #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"til siste\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"Hent en del av listen\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"Hent de siste # elementene\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"Hent del-listen fra #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Kopiérer en ønsket del av en liste.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"finn første forekomst av elementet\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"finn siste forekomst av elementet\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returnerer posisjonen til den første/siste forekomsten av elementet i en liste. Returnerer 0 hvis ikke funnet.\";\nBlockly.Msg.LISTS_INLIST = \"i listen\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 er tom\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"lengden på %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returnerer lengden til en liste.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"Lag en liste hvor elementet %1 forekommer %2 ganger\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Lager en liste hvor den gitte verdien gjentas et antall ganger.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"som\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"sett inn ved\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"sett\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Setter inn elementet i starten av en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Tilføy elementet til slutten av en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Setter inn elementet ved en tilfeldig posisjon i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Angir det første elementet i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Angir det siste elementet i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Angir et tilfeldig element i en liste.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Returnerer sann hvis listen er tom.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"usann\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Returnerer enten sann eller usann.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"sann\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Returnerer sann hvis begge inputene er like hverandre.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Returnerer sant hvis det første argumentet er større enn den andre argumentet.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Returnerer sant hvis det første argumentet er større enn eller likt det andre argumentet.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Returnerer sant hvis det første argumentet er mindre enn det andre argumentet.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Returnerer sant hvis det første argumentet er mindre enn eller likt det andre argumentet.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Returnerer sant hvis begge argumentene er ulike hverandre.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"ikke %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returnerer sant hvis argumentet er usant. Returnerer usant hvis argumentet er sant.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returnerer null.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"og\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"eller\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Returnerer sant hvis begge argumentene er sanne.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Returnerer sant hvis minst ett av argumentene er sant.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"hvis usant\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"hvis sant\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Sjekk betingelsen i 'test'. Hvis betingelsen er sann, da returneres 'hvis sant' verdien. Hvis ikke returneres 'hvis usant' verdien.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://no.wikipedia.org/wiki/Aritmetikk\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Returnerer summen av to tall.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Returner kvotienten av to tall.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Returner differansen mellom to tall.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Returner produktet av to tall.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Returner det første tallet opphøyd i den andre tallet.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"ved\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"endre\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Addere et tall til variabelen '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Returner en av felleskonstantene π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), eller ∞ (uendelig).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"begrense %1 lav %2 høy %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Begrens et tall til å være mellom de angitte grenseverdiene (inklusiv).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"er delelig med\";\nBlockly.Msg.MATH_IS_EVEN = \"er et partall\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"er negativer negativt\";\nBlockly.Msg.MATH_IS_ODD = \"er et oddetall\";\nBlockly.Msg.MATH_IS_POSITIVE = \"er positivt\";\nBlockly.Msg.MATH_IS_PRIME = \"er et primtall\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Sjekk om et tall er et partall, oddetall, primtall, heltall, positivt, negativt, eller om det er delelig med et annet tall. Returnerer sant eller usant.\";\nBlockly.Msg.MATH_IS_WHOLE = \"er et heltall\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resten av %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Returner resten fra delingen av to tall.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"x\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Et tall.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"gjennomsnittet av listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"maksimum av liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"medianen til listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minimum av listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"Listens typetall\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"tilfeldig element i listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standardavviket til listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"summen av listen\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Returner det aritmetiske gjennomsnittet av tallene i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Returner det største tallet i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Returner listens median.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Returner det minste tallet i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Returner en liste av de vanligste elementene i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Returner et tilfeldig element fra listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Returner listens standardavvik.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Returner summen av alle tallene i listen.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"tilfeldig flyttall\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Returner et tilfeldig flyttall mellom 0.0 (inkludert) og 1.0 (ikke inkludert).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"Et tilfeldig heltall mellom %1 og %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Returner et tilfeldig tall mellom de to spesifiserte grensene, inkludert de to.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"avrunding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"rund ned\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"rund opp\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Avrund et tall ned eller opp.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absoluttverdi\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"kvadratrot\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Returner absoluttverdien av et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Returner e opphøyd i et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Returner den naturlige logaritmen til et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Returner base-10 logaritmen til et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Returner det negative tallet.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Returner 10 opphøyd i et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Returner kvadratroten av et tall.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Returner arccosinus til et tall.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Returner arcsinus til et tall.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Returner arctangens til et tall.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Returner cosinus av en vinkel (ikke radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Returner sinus av en vinkel (ikke radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Returner tangenten av en vinkel (ikke radian).\";\nBlockly.Msg.NEW_VARIABLE = \"Ny variabel...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nytt variabelnavn:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"med:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Kjør den brukerdefinerte funksjonen '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Kjør den brukerdefinerte funksjonen'%1' og bruk resultatet av den.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Opprett '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"gjør noe\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"til\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Opprett en funksjon som ikke har noe resultat.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"returner\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Oppretter en funksjon som har et resultat.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Advarsel: Denne funksjonen har duplikate parametere.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Marker funksjonsdefinisjonen\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Hvis en verdi er sann, returner da en annen verdi.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Advarsel: Denne blokken kan bare benyttes innenfor en funksjonsdefinisjon.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"Navn på parameter:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"parametere\";\nBlockly.Msg.REMOVE_COMMENT = \"Fjern kommentar\";\nBlockly.Msg.RENAME_VARIABLE = \"Gi nytt navn til variabel...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Endre navnet til alle '%1' variabler til:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"tilføy tekst\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"til\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Tilføy tekst til variabelen '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"til små bokstaver\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"til store forbokstaver\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"til STORE BOKSTAVER\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Returnerer en kopi av teksten der store og små bokstaver er byttet om.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"hent første bokstav\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"hent bokstav # fra slutten\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"hent bokstav #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"i tekst\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"hent den siste bokstaven\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"hent en tilfeldig bokstav\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returnerer bokstaven på angitt plassering.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Legg til et element til teksten.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"føy sammen\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Legg til, fjern eller forandre rekkefølgen for å forandre på denne tekstblokken.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"til bokstav # fra slutten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"til bokstav #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"til siste bokstav\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"i tekst\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"hent delstreng fra første bokstav\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"hent delstreng fra bokstav # fra slutten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"hent delstreng fra bokstav #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returnerer den angitte delen av teksten.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"i tekst\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"finn første forekomst av tekst\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"finn siste forekomst av tekst\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returnerer posisjonen for første/siste forekomsten av den første tekst i den andre teksten.  Returnerer 0 hvis teksten ikke blir funnet.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 er tom\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returnerer sann hvis den angitte teksten er tom.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"lage tekst med\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Opprett en tekst ved å sette sammen et antall elementer.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"lengden av %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returnerer antall bokstaver (inkludert mellomrom) i den angitte teksten.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"skriv ut %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Skriv ut angitt tekst, tall eller annet innhold.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Be brukeren om et tall.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Spør brukeren om tekst.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"spør om et tall med en melding\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"spør om tekst med en melding\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"En bokstav, ett ord eller en linje med tekst.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"fjern mellomrom fra begge sider\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"fjern mellomrom fra venstre side\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"fjern mellomrom fra høyre side\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Returner en kopi av teksten med mellomrom fjernet fra en eller begge sidene.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Opprett 'sett %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returnerer verdien av denne variabelen.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Opprett 'hent %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"til\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"sett\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Setter verdien av denne variablen lik parameteren.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/nl.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.nl');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Reactie toevoegen\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Waarde wijzigen:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Blokken inklappen\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Blok inklappen\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"kleur 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"kleur 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"verhouding\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"mengen\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Mengt twee kleuren samen met een bepaalde verhouding (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://nl.wikipedia.org/wiki/Kleur\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Kies een kleur in het palet.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"willekeurige kleur\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Kies een willekeurige kleur.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blauw\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"groen\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"rood\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"kleuren met\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Maak een kleur met de opgegeven hoeveelheid rood, groen en blauw.  Alle waarden moeten tussen 0 en 100 liggen.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"uit lus breken\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"doorgaan met de volgende iteratie van de lus\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"uit de bovenliggende lus breken\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"De rest van deze lus overslaan en doorgaan met de volgende herhaling.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Waarschuwing: dit blok mag alleen gebruikt worden in een lus.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"in lijst\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"voor ieder item\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Voor ieder item in een lijst, stel de variabele \\\"%1\\\" in op het item en voer daarna opdrachten uit.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"van %1 tot %2 in stappen van %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"rekenen met\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Laat de variabele %1 de waarden aannemen van het beginnummer tot het laatste nummer, tellende met het opgegeven interval, en met uitvoering van de opgegeven blokken.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Voeg een voorwaarde toe aan het als-blok.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Voeg een laatste, vang-alles conditie toe aan het als-statement.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Voeg stukken toe, verwijder of verander de volgorde om dit \\\"als\\\"-blok te wijzigen.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"anders\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"anders als\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"als\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Als een waarde waar is, voer dan opdrachten uit.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Als een waarde waar is, voert dan het eerste blok met opdrachten uit. Voer andere het tweede blok met opdrachten uit.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Als de eerste waarde waar is, voer dan het eerste blok met opdrachten uit. Voer anders, als de tweede waarde waar is, het tweede blok met opdrachten uit.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Als de eerste waarde \\\"waar\\\" is, voer dan het eerste blok uit. Voer anders wanneer de tweede waarde \\\"waar\\\" is, het tweede blok uit. Als geen van beide waarden waar zijn, voer dan het laatste blok uit.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://nl.wikipedia.org/wiki/Repetitie_(informatica)#For_en_Foreach\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"voer uit\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1 keer herhalen\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"herhalen\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"keer\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Voer een aantal opdrachten meerdere keren uit.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"herhalen totdat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"herhalen zolang\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Terwijl een waarde onwaar is de volgende opdrachten uitvoeren.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Terwijl een waarde waar is de volgende opdrachten uitvoeren.\";\nBlockly.Msg.DELETE_BLOCK = \"Blok verwijderen\";\nBlockly.Msg.DELETE_X_BLOCKS = \"%1 blokken verwijderen\";\nBlockly.Msg.DISABLE_BLOCK = \"Blok uitschakelen\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplicaat\";\nBlockly.Msg.ENABLE_BLOCK = \"Blok inschakelen\";\nBlockly.Msg.EXPAND_ALL = \"Blokken uitvouwen\";\nBlockly.Msg.EXPAND_BLOCK = \"Blok uitvouwen\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Externe invoer\";\nBlockly.Msg.HELP = \"Hulp\";\nBlockly.Msg.INLINE_INPUTS = \"Inline invoer\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"maak een lege lijst\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Geeft een lijst terug met lengte 0, zonder items\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lijst\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Voeg stukken toe, verwijder ze of verander de volgorde om dit lijstblok aan te passen.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"maak een lijst met\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Voeg iets toe aan de lijst.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Maak een lijst met een willekeurig aantal items.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"eerste\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# van einde\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"haal op\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"haal op en verwijder\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"laatste\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"willekeurig\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"verwijder\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Geeft het eerste item in een lijst terug.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Geeft het item op de opgegeven positie in een lijst terug. Item 1 is het laatste item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Geeft het item op de opgegeven positie in een lijst. Item 1 is het eerste item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Geeft het laatste item in een lijst terug.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Geeft een willekeurig item uit een lijst.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Geeft het laatste item in een lijst terug en verwijdert het.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Verwijdert en geeft het item op de opgegeven positie in de lijst. Item 1 is het laatste item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Geeft het item op de opgegeven positie in een lijst terug en verwijdert het. Item 1 is het eerste item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Geeft het laatste item uit een lijst terug en verwijdert het.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Geeft een willekeurig item in een lijst terug en verwijdert het.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Verwijdert het eerste item in een lijst.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Verwijdert een item op de opgegeven positie in een lijst. Item 1 is het laatste item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Verwijdert het item op de opgegeven positie in een lijst. Item 1 is het eerste item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Verwijdert het laatste item uit een lijst.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Verwijdert een willekeurig item uit een lijst.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"naar # vanaf einde\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"naar item\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"naar laatste\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"haal sublijst op vanaf eerste\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"haal sublijst op van positie vanaf einde\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"haal sublijst op vanaf positie\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Maakt een kopie van het opgegeven deel van de lijst.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"zoek eerste voorkomen van item\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"zoek laatste voorkomen van item\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Geeft de index van het eerste of laatste voorkomen van een item in de lijst terug. Geeft 0 terug als de tekst niet is gevonden.\";\nBlockly.Msg.LISTS_INLIST = \"in lijst\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 is leeg\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"lengte van %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Geeft de lengte van een lijst terug.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"Maak lijst met item %1, %2 keer herhaald\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Maakt een lijst die bestaat uit de opgegeven waarde, het opgegeven aantal keer herhaald.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"als\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"tussenvoegen op\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"stel in\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Voegt het item toe aan het begin van de lijst.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Voegt het item op de opgegeven positie toe aan een lijst in. Item 1 is het laatste item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Voegt het item op een opgegeven positie in een lijst in. Item 1 is het eerste item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Voeg het item aan het einde van een lijst toe.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Voegt het item op een willekeurige positie in de lijst in.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Stelt het eerste item in een lijst in.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Stelt het item op een opgegeven positie in de lijst in. Item 1 is het laatste item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Stelt het item op de opgegeven positie in de lijst in. Item 1 is het eerste item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Stelt het laatste item van een lijst in.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Stelt een willekeurig item uit de lijst in.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Geeft waar terug als de lijst leeg is.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"onwaar\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Geeft \\\"waar\\\" of \\\"onwaar\\\" terug.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"waar\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://nl.wikipedia.org/wiki/Ongelijkheid\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Geeft \\\"waar\\\", als beide waarden gelijk aan elkaar zijn.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Geeft \\\"waar\\\" terug als de eerste invoer meer is dan de tweede invoer.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Geeft \\\"waar\\\" terug als de eerste invoer groter is of gelijk aan de tweede invoer.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Geeft \\\"waar\\\" als de eerste invoer kleiner is dan de tweede invoer.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Geeft \\\"waar\\\" terug als de eerste invoer kleiner of gelijk is aan de tweede invoer.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Geeft \\\"waar\\\" terug als de waarden niet gelijk zijn aan elkaar.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"niet %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Geeft \\\"waar\\\" terug als de invoer \\\"onwaar\\\" is. Geeft \\\"onwaar\\\" als de invoer \\\"waar\\\" is.\";\nBlockly.Msg.LOGIC_NULL = \"niets\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Geeft niets terug.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"en\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"of\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Geeft waar als beide waarden waar zijn.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Geeft \\\"waar\\\" terug als in ieder geval één van de waarden waar is.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"als onwaar\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"als waar\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Test de voorwaarde in \\\"test\\\". Als de voorwaarde \\\"waar\\\" is, geef de waarde van \\\"als waar\\\" terug; geef anders de waarde van \\\"als onwaar\\\" terug.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://nl.wikipedia.org/wiki/Rekenen\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Geeft de som van 2 getallen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Geeft de gedeelde waarde van twee getallen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Geeft het verschil van de twee getallen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Geeft het product terug van de twee getallen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Geeft het eerste getal tot de macht van het tweede getal.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"met\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"wijzigen\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Voegt een getal toe aan variabele \\\"%1\\\".\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://nl.wikipedia.org/wiki/Wiskundige_constante\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Geeft een van de vaak voorkomende constante waardes:  π (3.141…), e (2.718…), φ (1.618…), √2 (1.414…), √½ (0.707…), of ∞ (oneindig).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"beperk %1 van minimaal %2 tot maximaal %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Beperk een getal tussen de twee opgegeven limieten (inclusief).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"is deelbaar door\";\nBlockly.Msg.MATH_IS_EVEN = \"is even\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"is negatief\";\nBlockly.Msg.MATH_IS_ODD = \"is oneven\";\nBlockly.Msg.MATH_IS_POSITIVE = \"is positief\";\nBlockly.Msg.MATH_IS_PRIME = \"is priemgetal\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Test of een getal even, oneven, een priemgetal, geheel, positief of negatief is, of deelbaar is door een bepaald getal. Geeft \\\"waar\\\" of \\\"onwaar\\\".\";\nBlockly.Msg.MATH_IS_WHOLE = \"is geheel getal\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://nl.wikipedia.org/wiki/Modulair_rekenen\";\nBlockly.Msg.MATH_MODULO_TITLE = \"restgetal van %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Geeft het restgetal van het resultaat van de deling van de twee getallen.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://nl.wikipedia.org/wiki/Getal_%28wiskunde%29\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Een getal.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"gemiddelde van lijst\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"hoogste uit lijst\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mediaan van lijst\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"laagste uit lijst\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modi van lijst\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"willekeurige item van lijst\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standaarddeviatie van lijst\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"som van lijst\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Geeft het gemiddelde terug van de numerieke waardes in een lijst.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Geeft het grootste getal in een lijst.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Geeft de mediaan in de lijst.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Geeft het kleinste getal uit een lijst.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Geeft een lijst van de meest voorkomende onderdelen in de lijst.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Geeft een willekeurig item uit de lijst terug.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Geeft de standaardafwijking van de lijst.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Geeft de som van alle getallen in de lijst.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://nl.wikipedia.org/wiki/Toevalsgenerator\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"willekeurige fractie\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Geeft een willekeurige fractie tussen 0.0 (inclusief) en 1.0 (exclusief).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://nl.wikipedia.org/wiki/Toevalsgenerator\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"willekeurig getal van %1 tot %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Geeft een willekeurig getal tussen de 2 opgegeven limieten in, inclusief.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://nl.wikipedia.org/wiki/Afronden\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"afronden\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"naar beneden afronden\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"omhoog afronden\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Rondt een getal af omhoog of naar beneden.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://nl.wikipedia.org/wiki/Vierkantswortel\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absoluut\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"wortel\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Geeft de absolute waarde van een getal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Geeft e tot de macht van een getal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Geeft het natuurlijk logaritme van een getal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Geeft het logaritme basis 10 van een getal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Geeft de negatief van een getal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Geeft 10 tot de macht van een getal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Geeft de wortel van een getal.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"arctan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://nl.wikipedia.org/wiki/Goniometrische_functie\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Geeft de arccosinus van een getal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Geeft de arcsinus van een getal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Geeft de arctangens van een getal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Geeft de cosinus van een graad (geen radialen).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Geeft de sinus van een graad (geen radialen).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Geeft de tangens van een graad (geen radialen).\";\nBlockly.Msg.NEW_VARIABLE = \"Nieuwe variabele...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nieuwe variabelenaam:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"met:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://nl.wikipedia.org/wiki/Subprogramma\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Voer de door de gebruiker gedefinieerde functie \\\"%1\\\" uit.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://nl.wikipedia.org/wiki/Subprogramma\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Voer de door de gebruiker gedefinieerde functie \\\"%1\\\" uit en gebruik de uitvoer.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Maak \\\"%1\\\"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://nl.wikipedia.org/wiki/Subprogramma\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"doe iets\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"om\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Maakt een functie zonder uitvoer.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://nl.wikipedia.org/wiki/Subprogramma\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"uitvoeren\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Maakt een functie met een uitvoer.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Waarschuwing: deze functie heeft parameters met dezelfde naam.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Accentueer functiedefinitie\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Als de eerste waarde \\\"waar\\\" is, geef dan de tweede waarde terug.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Waarschuwing: dit blok mag alleen gebruikt worden binnen de definitie van een functie.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"invoernaam:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"ingangen\";\nBlockly.Msg.REMOVE_COMMENT = \"Opmerking verwijderen\";\nBlockly.Msg.RENAME_VARIABLE = \"Variabele hernoemen...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Alle variabelen \\\"%1\\\" hernoemen naar:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"tekst\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"voeg toe aan\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Voeg tekst toe aan de variabele \\\"%1\\\".\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"naar kleine letters\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"naar Hoofdletter Per Woord\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"naar HOOFDLETTERS\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Geef een kopie van de tekst met veranderde hoofdletters terug.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"haal eerste letter op\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"haal letter # op vanaf einde\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"haal letter # op\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"in tekst\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"haal laatste letter op\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"haal willekeurige letter op\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Geeft de letter op de opgegeven positie terug.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Voegt een item aan de tekst toe.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"samenvoegen\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Toevoegen, verwijderen of volgorde veranderen van secties om dit tekstblok opnieuw in te stellen.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"van letter # tot einde\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"naar letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"naar laatste letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"in tekst\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"haal subtekst op van eerste letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"haal subtekst op vanaf letter # vanaf einde\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"haal subtekst op vanaf letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Geeft het opgegeven onderdeel van de tekst terug.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"in tekst\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"zoek eerste voorkomen van tekst\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"zoek het laatste voorkomen van tekst\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Geeft de index terug van de eerste/laatste aanwezigheid van de eerste tekst in de tweede tekst. Geeft 0 terug als de tekst niet gevonden is.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 is leeg\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Geeft \\\"waar\\\" terug, als de opgegeven tekst leeg is.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"maak tekst met\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Maakt een stuk tekst door één of meer items samen te voegen.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"lengte van %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Geeft het aantal tekens terug (inclusief spaties) in de opgegeven tekst.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"tekst weergeven: %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Drukt de opgegeven tekst, getal of een andere waarde af.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Vraagt de gebruiker om een getal in te voeren.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Vraagt de gebruiker om invoer.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"vraagt de gebruiker om een getal met de tekst\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"vraagt om invoer met bericht\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://nl.wikipedia.org/wiki/String_%28informatica%29\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Een letter, woord of een regel tekst.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"spaties van beide kanten afhalen\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"spaties van de linkerkant verwijderen\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"spaties van de rechterkant verwijderen\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Geeft een kopie van de tekst met verwijderde spaties van één of beide kanten.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"item\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Maak \\\"verander %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Geeft de waarde van deze variabele.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Maak 'opvragen van %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"naar\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"stel in\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Verandert de waarde van de variabele naar de waarde van de invoer.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/no.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.no');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Legg til kommentar\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Bytt verdi:\";\nBlockly.Msg.COLLAPSE_ALL = \"Skjul blokker\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Skjul blokk\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"farge 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"farge 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"forhold\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"blande\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Blander to farger sammen med et gitt forhold (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"http://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Velg en farge fra paletten.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"tilfeldig farge\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Velg en tilfeldig farge.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blå\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"grønn\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"rød\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"farge med\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Lag en farge med angitt verdi av rød, grønn og blå. Alle verdier må være mellom 0 og 100.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"bryt ut av løkken\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"fortsett med neste gjentakelse av løkken\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Bryt ut av den gjeldende løkken.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Hopp over resten av denne løkken og fortsett med neste gjentakelse.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Advarsel: Denne blokken kan kun brukes innenfor en løkke.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"i listen\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"for hvert element\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"For hvert element i en liste, angi variabelen '%1' til elementet, og deretter lag noen setninger.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"fra %1 til %2 med %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"tell med\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Ha variabel %1 ta verdiene fra start nummer til slutt nummer, telle med spesifisert intervall og lag de spesifiserte blokkene.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Legg til en betingelse til hvis blokken.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Legg til hva som skal skje hvis de andre ikke slår til.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Legg til, fjern eller flytt seksjoner i denne hvis-blokken.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"ellers\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"ellers hvis\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"hvis\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Hvis dette er sant, så gjør følgende.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Hvis dette er sant, så utfør den første blokken av instruksjoner. Hvis ikke, utfør den andre blokken.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Hvis det første stemmer, så utfør den første blokken av instruksjoner. Ellers, hvis det andre stemmer, utfør den andre blokken av instruksjoner.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Hvis den første verdien er sann, så utfør den første blokken med setninger. Ellers, hvis den andre verdien er sann, så utfør den andre blokken med setninger. Hvis ingen av verdiene er sanne, så utfør den siste blokken med setninger.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"http://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"gjør\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"gjenta %1 ganger\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"gjenta\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"ganger\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Gjenta noen instruksjoner flere ganger.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"gjenta til\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"gjenta mens\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Så lenge et utsagn ikke stemmer, gjør noen instruksjoner.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Så lenge et utsagn stemmer, utfør noen instruksjoner.\";\nBlockly.Msg.DELETE_BLOCK = \"Slett blokk\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Slett %1 blokk(er)\";\nBlockly.Msg.DISABLE_BLOCK = \"Deaktiver blokk\";\nBlockly.Msg.DUPLICATE_BLOCK = \"duplikat\";\nBlockly.Msg.ENABLE_BLOCK = \"Aktiver blokk\";\nBlockly.Msg.EXPAND_ALL = \"Utvid blokker\";\nBlockly.Msg.EXPAND_BLOCK = \"Utvid blokk\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Eksterne kilder\";\nBlockly.Msg.HELP = \"Hjelp\";\nBlockly.Msg.INLINE_INPUTS = \"Interne kilder\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"opprett en tom liste\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returnerer en tom liste, altså med lengde 0\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"liste\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Legg til, fjern eller endre rekkefølgen for å endre på denne delen av listen.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"lag en liste med\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Tilføy et element til listen.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Lag en liste med et vilkårlig antall elementer.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"først\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# fra slutten\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"hent\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"hent og fjern\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"siste\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"tilfeldig\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"fjern\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returnerer det første elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returner elementet på den angitte posisjonen i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returner elementet på den angitte posisjonen i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returnerer det siste elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returnerer et tilfeldig element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Fjerner og returnerer det første elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Fjerner og returnerer elementet ved en gitt posisjon i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Fjerner og returnerer elementet ved en gitt posisjon i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Fjerner og returnerer det siste elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Fjerner og returnerer et tilfeldig element i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Fjerner det første elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Fjerner et element ved en gitt posisjon i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Fjerner et element ved en gitt posisjon i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Fjerner det siste elementet i en liste.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Fjerner et tilfeldig element i en liste.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"til # fra slutten\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"til #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"til siste\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"Hent en del av listen\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"Hent de siste # elementene\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"Hent del-listen fra #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Kopiérer en ønsket del av en liste.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"finn første forekomst av elementet\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"finn siste forekomst av elementet\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returnerer posisjonen til den første/siste forekomsten av elementet i en liste. Returnerer 0 hvis ikke funnet.\";\nBlockly.Msg.LISTS_INLIST = \"i listen\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 er tom\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"lengden på %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returnerer lengden til en liste.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"Lag en liste hvor elementet %1 forekommer %2 ganger\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Lager en liste hvor den gitte verdien gjentas et antall ganger.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"som\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"sett inn ved\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"sett\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Setter inn elementet i starten av en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Tilføy elementet til slutten av en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Setter inn elementet ved en tilfeldig posisjon i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Angir det første elementet i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det siste elementet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det første elementet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Angir det siste elementet i en liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Angir et tilfeldig element i en liste.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Returnerer sann hvis listen er tom.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"usann\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Returnerer enten sann eller usann.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"sann\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"http://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Returnerer sann hvis begge inputene er like hverandre.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Returnerer sant hvis det første argumentet er større enn den andre argumentet.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Returnerer sant hvis det første argumentet er større enn eller likt det andre argumentet.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Returnerer sant hvis det første argumentet er mindre enn det andre argumentet.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Returnerer sant hvis det første argumentet er mindre enn eller likt det andre argumentet.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Returnerer sant hvis begge argumentene er ulike hverandre.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"ikke %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returnerer sant hvis argumentet er usant. Returnerer usant hvis argumentet er sant.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"http://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returnerer null.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"og\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"eller\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Returnerer sant hvis begge argumentene er sanne.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Returnerer sant hvis minst ett av argumentene er sant.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"http://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"hvis usant\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"hvis sant\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Sjekk betingelsen i 'test'. Hvis betingelsen er sann, da returneres 'hvis sant' verdien. Hvis ikke returneres 'hvis usant' verdien.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"http://no.wikipedia.org/wiki/Aritmetikk\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Returnerer summen av to tall.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Returner kvotienten av to tall.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Returner differansen mellom to tall.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Returner produktet av to tall.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Returner det første tallet opphøyd i den andre tallet.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"ved\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"endre\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Addere et tall til variabelen '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"http://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Returner en av felleskonstantene π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), eller ∞ (uendelig).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"begrense %1 lav %2 høy %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Begrens et tall til å være mellom de angitte grenseverdiene (inklusiv).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"er delelig med\";\nBlockly.Msg.MATH_IS_EVEN = \"er et partall\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"er negativer negativt\";\nBlockly.Msg.MATH_IS_ODD = \"er et oddetall\";\nBlockly.Msg.MATH_IS_POSITIVE = \"er positivt\";\nBlockly.Msg.MATH_IS_PRIME = \"er et primtall\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Sjekk om et tall er et partall, oddetall, primtall, heltall, positivt, negativt, eller om det er delelig med et annet tall. Returnerer sant eller usant.\";\nBlockly.Msg.MATH_IS_WHOLE = \"er et heltall\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"http://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resten av %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Returner resten fra delingen av to tall.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"x\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"http://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Et tall.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"gjennomsnittet av listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"maksimum av liste\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"medianen til listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minimum av listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"Listens typetall\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"tilfeldig element i listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standardavviket til listen\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"summen av listen\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Returner det aritmetiske gjennomsnittet av tallene i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Returner det største tallet i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Returner listens median.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Returner det minste tallet i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Returner en liste av de vanligste elementene i listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Returner et tilfeldig element fra listen.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Returner listens standardavvik.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Returner summen av alle tallene i listen.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"http://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"tilfeldig flyttall\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Returner et tilfeldig flyttall mellom 0.0 (inkludert) og 1.0 (ikke inkludert).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"http://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"Et tilfeldig heltall mellom %1 og %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Returner et tilfeldig tall mellom de to spesifiserte grensene, inkludert de to.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"http://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"avrunding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"rund ned\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"rund opp\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Avrund et tall ned eller opp.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"http://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absoluttverdi\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"kvadratrot\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Returner absoluttverdien av et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Returner e opphøyd i et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Returner den naturlige logaritmen til et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Returner base-10 logaritmen til et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Returner det negative tallet.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Returner 10 opphøyd i et tall.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Returner kvadratroten av et tall.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"http://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Returner arccosinus til et tall.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Returner arcsinus til et tall.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Returner arctangens til et tall.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Returner cosinus av en vinkel (ikke radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Returner sinus av en vinkel (ikke radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Returner tangenten av en vinkel (ikke radian).\";\nBlockly.Msg.NEW_VARIABLE = \"Ny variabel...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nytt variabelnavn:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"med:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Kjør den brukerdefinerte funksjonen '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Kjør den brukerdefinerte funksjonen'%1' og bruk resultatet av den.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Opprett '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"gjør noe\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"til\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Opprett en funksjon som ikke har noe resultat.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"returner\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Oppretter en funksjon som har et resultat.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Advarsel: Denne funksjonen har duplikate parametere.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Marker funksjonsdefinisjonen\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Hvis en verdi er sann, returner da en annen verdi.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Advarsel: Denne blokken kan bare benyttes innenfor en funksjonsdefinisjon.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"Navn på parameter:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"parametere\";\nBlockly.Msg.REMOVE_COMMENT = \"Fjern kommentar\";\nBlockly.Msg.RENAME_VARIABLE = \"Gi nytt navn til variabel...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Endre navnet til alle '%1' variabler til:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"tilføy tekst\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"til\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Tilføy tekst til variabelen '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"til små bokstaver\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"til store forbokstaver\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"til STORE BOKSTAVER\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Returnerer en kopi av teksten der store og små bokstaver er byttet om.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"hent første bokstav\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"hent bokstav # fra slutten\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"hent bokstav #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"i tekst\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"hent den siste bokstaven\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"hent en tilfeldig bokstav\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returnerer bokstaven på angitt plassering.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Legg til et element til teksten.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"føy sammen\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Legg til, fjern eller forandre rekkefølgen for å forandre på denne tekstblokken.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"til bokstav # fra slutten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"til bokstav #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"til siste bokstav\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"i tekst\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"hent delstreng fra første bokstav\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"hent delstreng fra bokstav # fra slutten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"hent delstreng fra bokstav #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returnerer den angitte delen av teksten.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"i tekst\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"finn første forekomst av tekst\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"finn siste forekomst av tekst\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returnerer posisjonen for første/siste forekomsten av den første tekst i den andre teksten.  Returnerer 0 hvis teksten ikke blir funnet.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 er tom\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returnerer sann hvis den angitte teksten er tom.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"lage tekst med\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Opprett en tekst ved å sette sammen et antall elementer.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"lengden av %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returnerer antall bokstaver (inkludert mellomrom) i den angitte teksten.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"skriv ut %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Skriv ut angitt tekst, tall eller annet innhold.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Be brukeren om et tall.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Spør brukeren om tekst.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"spør om et tall med en melding\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"spør om tekst med en melding\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"http://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"En bokstav, ett ord eller en linje med tekst.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"fjern mellomrom fra begge sider\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"fjern mellomrom fra venstre side\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"fjern mellomrom fra høyre side\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Returner en kopi av teksten med mellomrom fjernet fra en eller begge sidene.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Opprett 'sett %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returnerer verdien av denne variabelen.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Opprett 'hent %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"til\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"sett\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Setter verdien av denne variablen lik parameteren.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/pl.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.pl');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Dodaj komentarz\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Zmień wartość:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Zwiń bloki\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Zwiń blok\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"kolor 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"kolor 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"proporcja\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"mieszanka\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Miesza dwa kolory w danej proporcji (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Wybierz kolor z palety.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"losowy kolor\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Wybierz kolor w sposób losowy.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"niebieski\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"zielony\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"czerwony\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"kolor z\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Połącz czerwony, zielony i niebieski w odpowiednich proporcjach, tak aby powstał nowy kolor. Zawartość każdego z nich określa liczba z przedziału od 0 do 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"wyjść z pętli\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"Przejdź do kolejnej iteracji pętli\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Wyjść z zawierającej pętli.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Pomiń resztę pętli i kontynuuj w kolejnej iteracji.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Ostrzeżenie: Ten blok może być użyty tylko w pętli.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"na liście\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"dla każdego elementu\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Dla każdego elementu z listy przyporządkuj zmienną '%1', a następnie wykonaj kilka instrukcji.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"od %1 do %2 co %3 (wartość kroku)\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"liczyć z\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Czy zmienna %1 przyjmuje wartości od numeru startowego do numeru końcowego, licząc przez określony interwał, i wykonuje  określone bloki.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Dodać warunek do bloku if.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Dodać warunek końcowy, warunek złap wszystkie do bloku if.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Dodać, usunąć lub zmienić kolejność sekcji żeby zrekonfigurować blok if.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"w przeciwnym razie\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"w przeciwnym razie jeśli\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"jeśli\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Jeśli wartość jest prawdziwa,  to wykonaj kilka instrukcji.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Jeśli wartość jest prawdą, to wykonaj pierwszy blok instrukcji.  W przeciwnym razie, wykonaj drugi blok instrukcji.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Jeśli pierwsza wartość jest prawdą, to wykonaj pierwszy blok instrukcji.  W przeciwnym razie, jeśli druga wartość jest prawdą, to wykonaj drugi blok instrukcji.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Jeśli pierwsza wartość jest prawdziwa, wykonaj pierwszy blok instrukcji.  W przeciwnym razie jeśli druga wartość jest prawdziwa, wykonaj drugi blok instrukcji.  Jeżeli żadna z wartości nie jest prawdziwa, wykonaj ostatni blok instrukcji.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"wykonaj\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"powtórz %1 razy\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"powtórz\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"razy\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Wykonaj niektóre instrukcje kilka razy.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"powtarzaj aż\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"powtarzaj dopóki\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Gdy wartość jest nieprawdziwa, wykonaj kilka instrukcji.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Gdy wartość jest prawdziwa, wykonaj kilka instrukcji.\";\nBlockly.Msg.DELETE_BLOCK = \"Usuń blok\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Usunąć %1 bloki\";\nBlockly.Msg.DISABLE_BLOCK = \"Wyłącz blok\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Powiel\";\nBlockly.Msg.ENABLE_BLOCK = \"Włącz blok\";\nBlockly.Msg.EXPAND_ALL = \"Rozwiń bloki\";\nBlockly.Msg.EXPAND_BLOCK = \"Rozwiń blok\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Zewnętrzne wejścia\";\nBlockly.Msg.HELP = \"Pomoc\";\nBlockly.Msg.INLINE_INPUTS = \"Webdowane wejscia\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"utwórz pustą listę\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Zwraca listę, o długości 0, nie zawierającą rekordów z danymi\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Dodać, usunąć lub zmienić kolejność sekcji żeby zrekonfigurować blok tej listy.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"Tworzenie listy z\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Dodaj element do listy.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Utwórz listę z dowolną ilością elementów.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"pierwszy\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# od końca\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"pobierz\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"Pobierz i usuń\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"ostatni\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"losowy\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"usuń\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Zwraca pierwszy element z listy.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Zwraca element z określonej pozycji na liście. #1 to ostatni element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Zwraca element z konkretnej pozycji na liście. #1 to pierwszy element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Zwraca ostatni element z listy.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Zwraca losowy element z listy.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Usuwa i zwraca pierwszy element z listy.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Usuwa i zwraca element z określonej pozycji na liście. #1 to ostatni element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Usuwa i zwraca element z określonej pozycji na liście. #1 to pierwszy element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Usuwa i zwraca ostatni element z listy.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Usuwa i zwraca losowy element z listy.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Usuwa pierwszy element z listy.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Usuwa element z określonej pozycji na liście. #1 to ostatni element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Usuwa element z określonej pozycji na liście. #1 to pierwszy element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Usuwa ostatni element z listy.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Usuwa losowy element z listy.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"do # od końca\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"do #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"do ostatniego\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"Pobierz listę podrzędną z pierwszego\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"Pobierz listę podrzędną z # od końca\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"Pobierz listę podrzędną z #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Tworzy kopię z określoną część listy.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"znaleźć pierwsze wystąpienie elementu\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"znajduje ostatanie wystąpienie elementu\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Zwraca indeks pierwszego/ostatniego wystąpienia elementu na liście.  Zwraca wartość 0, jeśli tekst nie zostanie znaleziony.\";\nBlockly.Msg.LISTS_INLIST = \"na liście\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 jest pusty\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"długość %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Zwraca długość listy.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"stwórz listę, powtarzając element %1 %2 razy\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Tworzy listę składającą się z podanej wartości powtórzonej odpowiednią liczbę razy.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"jako\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"wstaw w\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"ustaw\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Wstawia element na początku listy.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Wstawia element w odpowiednim miejscu na liście. #1 to ostatni element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Wstawia element w odpowiednim miejscu na liście. #1 to pierwszy element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Wstaw element na koniec listy.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Wstawia element w losowym miejscu na liście.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Wstawia pierwszy element na liście.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Wstawia element w odpowiednie miejsce na liście. #1 to ostatni element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Wstawia element w odpowiednie miejsce na liście. #1 to pierwszy element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Wstawia ostatni element na liście.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Wstawia losowy element na liście.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Zwraca \\\"prawda\\\" jeśli lista jest pusta.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"fałsz\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Zwraca 'prawda' lub 'fałsz'.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"prawda\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Zwraca \\\"prawda\\\", jeśli obie dane wejściowe są sobie równe.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Zwraca \\\"prawda\\\" jeśli pierwszy dany element jest większy od drugiego.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Zwraca \\\"prawda\\\", jeśli pierwsza dana wejściowa jest większa niż lub równa drugiej danej wejściowej.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Zwraca \\\"prawda\\\" jeśli pierwsza dana wejściowa jest większa od drugiej.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Zwraca \\\"prawda\\\", jeśli pierwsza dana wejściowa jest większa lub równa drugiej danej wejściowej.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Zwraca \\\"prawda\\\", jeśli obie dane wejściowe nie są sobie równe.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"nie %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Zwraca \\\"prawda\\\", jeśli dane wejściowe są fałszywe.  Zwraca \\\"fałsz\\\", jeśli dana wejściowa jest prawdziwa.\";\nBlockly.Msg.LOGIC_NULL = \"nic\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Zwraca zero.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"i\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"lub\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Zwraca \\\"prawda\\\" jeśli oba dane elementy mają wartość \\\"prawda\\\".\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Zwraca \\\"prawda\\\" jeśli co najmniej jeden dany element ma wartość \\\"prawda\\\".\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"jeśli fałsz\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"jeśli prawda\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Sprawdz warunek w 'test'. Jesli warunek jest prawdziwy, to zwroci 'if true'; jesli nie jest prawdziwy to zwroci 'if false'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://pl.wikipedia.org/wiki/Arytmetyka\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Zwroci sume dwoch numerow.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Zwróć iloraz dwóch liczb.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Zwroci roznicy miedzy dwoch numerow.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Zwróć iloczyn dwóch liczb.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Zwróć pierwszą liczbę podniesioną do potęgi drugiej liczby.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"o\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"zmien\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Dodaj liczbę do zmiennej '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Zwróć jedną wspólną stałą: π (3.141), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) lub ∞ (nieskończoność).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"zaokrągl %1 w dół %2 w górę %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Zaokrągl liczbę, aby była w określonych granicach (włącznie).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"/\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"jest podzielna przez\";\nBlockly.Msg.MATH_IS_EVEN = \"jest parzysta\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"jest ujemna\";\nBlockly.Msg.MATH_IS_ODD = \"jest nieparzysta\";\nBlockly.Msg.MATH_IS_POSITIVE = \"jest dodatnia\";\nBlockly.Msg.MATH_IS_PRIME = \"jest liczbą pierwszą\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Sprawdź, czy liczba jest parzysta, nieparzysta, pierwsza, całkowita, dodatnia, ujemna, lub jeśli jest podzielna przez konkretną liczbę.  Zwraca wartość \\\"prawda\\\" lub \\\"fałsz\\\".\";\nBlockly.Msg.MATH_IS_WHOLE = \"jest liczbą całkowitą\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"reszta z dzielenia %1 przez %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Zwraca resztę z dzielenia dwóch liczb przez siebie.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Liczba.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"średnia z listy\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"maksymalna wartość z listy\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mediana z listy\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minimalna wartość z listy\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"dominanty listy\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"losowy element z listy\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"odchylenie standardowe z listy\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"suma z listy\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Zwróć średnią (średnią arytmetyczną) wartości liczbowych z listy.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Zwraca najwyzszy numer w liscie.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Zwróć medianę liczby na liście.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Zwraca najnizszy numer w liscie.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Zwróć listę najczęściej występujących elementów na liście.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Zwróć losowy element z listy.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Zwróć odchylenie standardowe listy.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Zwraca sume wszystkich liczb z listy.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"losowy ułamek\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Zwróć losowy ułamek między 0.0 (włącznie), a 1.0 (wyłącznie).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"losowa liczba całkowita od %1 do %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Zwróć losową liczbę całkowitą w ramach dwóch określonych granic, włącznie.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"zaokrąglić\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"zaokrąglić w dół\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"zaokrąglić w górę\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Zaokrąglić w górę lub w dół.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"wartość bezwzględna\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"pierwiastek kwadratowy\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Zwróć wartość bezwzględną danej liczby.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Zwraca e do potęgi danej liczby.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Zwróć logarytm naturalny danej liczby.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Zwróć logarytm dziesiętny danej liczby.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Zwróć negację danej liczby.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Zwróć 10 do potęgi danej liczby.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Zwróć pierwiastek kwadratowy danej liczby.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"arc cos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"arc sin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"arc tan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Zwróć arcus cosinus danej liczby.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Zwróć arcus sinus danej liczby.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Zwróć arcus tangens danej liczby.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Zwraca wartość cosinusa o stopniu (nie radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Zwraca wartość sinusa o stopniu (nie radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Zwróć tangens o stopniu (nie radian).\";\nBlockly.Msg.NEW_VARIABLE = \"Nowa zmienna...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nowa nazwa zmiennej:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"z:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Uruchom funkcję zdefiniowaną przez użytkownika '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Uruchom funkcję zdefiniowaną przez użytkownika '%1' i skorzystaj z jej wyniku.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Stwórz '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"zrób coś\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"do\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Tworzy funkcję bez wyniku.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"zwróć\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Tworzy funkcję z wynikiem.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Ostrzeżenie: Ta funkcja ma powtórzone parametry.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Podświetl definicję funkcji\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Jeśli wartość jest prawdziwa, zwróć drugą wartość.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Ostrzeżenie: Ten blok może być używany tylko w definicji funkcji.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nazwa wejścia:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"wejścia\";\nBlockly.Msg.REMOVE_COMMENT = \"Usuń Komentarz\";\nBlockly.Msg.RENAME_VARIABLE = \"Zmień nazwę zmiennej...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Zmień nazwy wszystkich '%1' zmiennych na:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"dołącz tekst\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"do\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Dołącz tekst do zmiennej '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"zmień na małe litery\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"zmień na od Wielkich Liter\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"zmień na WIELKIE LITERY\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Zwraca kopię tekstu z inną wielkością liter.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"pobierz pierwszą literę\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"pobierz literę # od końca\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"pobierz literę #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"z tekstu\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"pobierz ostatnią literę\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"pobierz losową literę\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Zwraca literę na określonej pozycji.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Dodaj element do tekstu.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"połącz\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Dodaj, usuń lub zmień kolejność sekcji, aby zmodyfikować blok tekstowy.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"do litery # od końca\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"do litery #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"do ostatniej litery\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"w tekście\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"pobierz podsłowo od pierwszej litery\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"pobierz podsłowo od litery # od końca\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"pobierz podsłowo od litery #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Zwraca określoną część tekstu.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"w tekście\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"znajdź pierwsze wystąpienie tekstu\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"znajdź ostatnie wystąpienie tekstu\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Zwraca indeks pierwszego/ostatniego wystąpienia pierwszego tekstu w drugim tekście. Zwraca wartość 0, jeśli tekst nie został znaleziony.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 jest pusty\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Zwraca prawda (true), jeśli podany tekst jest pusty.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"utwórz tekst z\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Utwórz fragment tekstu, łącząc ze sobą dowolną liczbę tekstów.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"długość %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Zwraca liczbę liter (łącznie ze spacjami) w podanym tekście.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"wydrukuj %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Drukuj określony tekst, liczbę lub coś innego.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Zapytaj użytkownika  o liczbę.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Zapytaj użytkownika o jakiś tekst.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"poproś o liczbę z tą wiadomością\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"poproś o tekst z tą wiadomością\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Litera, wyraz lub linia tekstu.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"usuń spacje po obu stronach tekstu\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"usuń spacje z lewej strony tekstu\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"usuń spacje z prawej strony tekstu\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Zwróć kopię tekstu z usuniętymi spacjami z jednego lub z obu końców tekstu.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Utwórz blok 'ustaw %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Zwraca wartość tej zmiennej.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Utwórz blok 'pobierz %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"wartość\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"przypisz\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Nadaj tej zmiennej wartość.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/pms.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.pms');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Gionté un coment\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Modifiché ël valor:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Arduve ij blòch\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Arduve ël blòch\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"color 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"color 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"rapòrt\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"mës-cé\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"A mës-cia doi color ansema con un rapòrt dàit (0,0 - 1,0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Serne un color ant la taulòssa.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"color a asar\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Serne un color a asar.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"bleu\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"verd\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"ross\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"coloré con\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Creé un color con la quantità spessificà ëd ross, verd e bleu. Tuti ij valor a devo esse antra 0 e 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"seurte da la liassa\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continué con l'iterassion sucessiva dla liassa\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Seurte da la liassa anglobanta.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Sauté ël rest ëd sa liassa, e continué con l'iterassion apress.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Atension: Ës blòch a peul mach esse dovrà andrinta a na liassa.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"ant la lista\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"për minca element\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Për minca element an na lista, dé ël valor ëd l'element a la variàbil '%1', peui eseguì chèiche anstrussion.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"da %1 a %2 për %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"conté con\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Fé an manera che la variàbil %1 a pija ij valor dal nùmer inissial fin-a al nùmer final, an contand për l'antërval ëspessificà, e eseguì ij bloch ëspessificà.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Gionté na condission al blòch si.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Gionté na condission final ch'a cheuj tut al blòch si.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Gionté, gavé o riordiné le session për cinfiguré torna ës blòch si.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"dësnò\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"dësnò si\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"si\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Si un valor a l'é ver, antlora eseguì chèiche anstrussion.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Si un valor a l'é ver, antlora eseguì ël prim blòch d'anstrussion. Dësnò, eseguì ël second blòch d'anstrussion.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Si ël prim valor a l'é ver, antlora fé andé ël prim blòch d'anstrussion. Dësnò, si ël second valor a l'é ver, fé andé ël second blòch d'anstrussion.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Si ël prim valor a l'é ver, antlora fé andé ël prim blòch d'anstrussion. Dësnò, si ël second valor a l'é ver, fé andé ël second blòcj d'anstrussion. Si gnun dij valor a l'é ver, fé andé l'ùltim blòch d'anstrussion.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"fé\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"arpete %1 vire\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"arpete\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"vire\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Eseguì chèiche anstrussion vàire vire.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"arpete fin-a a\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"arpete antramentre che\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Cand un valor a l'é fàuss, eseguì chèiche anstrussion.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Cand un valor a l'é ver, eseguì chèiche anstrussion.\";\nBlockly.Msg.DELETE_BLOCK = \"Scancelé ël blòch\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Scancelé %1 blòch\";\nBlockly.Msg.DISABLE_BLOCK = \"Disativé ël blòch\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Dupliché\";\nBlockly.Msg.ENABLE_BLOCK = \"Ativé ël blòch\";\nBlockly.Msg.EXPAND_ALL = \"Dësvlupé ij blòch\";\nBlockly.Msg.EXPAND_BLOCK = \"Dësvlupé ël blòch\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Imission esterne\";\nBlockly.Msg.HELP = \"Agiut\";\nBlockly.Msg.INLINE_INPUTS = \"Imission an linia\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"creé na lista veuida\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Smon-e na lista, ëd longheur 0, ch'a conten gnun-a argistrassion\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Gionté, gavé o riordiné le session për configuré torna cost blòch ëd lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"creé na lista con\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Gionté n'element a la lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Creé na lista con un nùmer qualsëssìa d'element.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"prim\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# da la fin\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"oten-e\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"oten-e e eliminé\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"ùltim\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"a l'ancàpit\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"eliminé\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"A smon ël prim element an na lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"A smon l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"A smon l'element a la posission ëspessificà an na lista. #1 a l'é ël prim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"A smon l'ùltim element an na lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"A smon n'element a l'ancàpit an na lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"A gava e a smon ël prim element an na lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"A gava e a smon l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"A gava e a smon l'element a la posission ëspessificà an na lista. #1 a l'é 'l prim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"A gava e a smon l'ùltim element an na lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"A gava e a smon n'element a l'ancàpit an na lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"A gava ël prim element an na lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"A gava l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"A gava l'element a la posission ëspessificà an na lista. #1 a l'é ël prim element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"A gava l'ùltim element an na lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"A gava n'element a l'ancàpit da na lista.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"fin-a a # da la fin\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"fin-a a #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"fin-a a l'ùltim\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"oten-e la sot-lista dal prim\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"oten-e la sot-lista da # da la fin\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"oten-e la sot-lista da #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"A crea na còpia dël tòch ëspessificà ëd na lista.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"trové la prima ocorensa dl'element\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"trové l'ùltima ocorensa dl'element\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"A smon l'ìndes ëd la prima/ùltima ocorensa dl'element ant la lista. A smon 0 se ël test a l'é nen trovà.\";\nBlockly.Msg.LISTS_INLIST = \"ant la lista\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 a l'é veuid\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"longheur ëd %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"A smon la longheur ¨d na lista.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"creé na lista con l'element %1 arpetù %2 vire\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"A crea na lista ch'a consist dël valor dàit arpetù ël nùmer ëspessificà ëd vire.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"tanme\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"anserì an\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"buté\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"A anseriss l'element al prinsipi ëd na lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"A anseriss l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"A anseriss l'element a la posission ëspessificà an na lista. #1 a l'é ël prim element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Gionté l'element a la fin ëd na lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"A anseriss l'element a l'ancàpit an na lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"A fissa ël prim element an na lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"A fissa l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"A fissa l'element a la posission ëspessificà an na lista. #1 a l'é ël prim element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"A fissa l'ùltim element an na lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"A fissa n'element a l'ancàpit an na lista.\";\nBlockly.Msg.LISTS_TOOLTIP = \"A smon ver se la lista a l'é veuida.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"fàuss\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"A rëspond ver o fàuss.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"ver\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Rësponde ver si le doe imission a son uguaj.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Rësponde ver si la prima imission a l'é pi granda che la sconda.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Rësponde ver si la prima imission a l'é pi granda o ugual a la sconda.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Rësponde ver si la prima imission a l'é pi cita dla sconda.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Rësponde ver si la prima imission a l'é pi cita o ugual a la sconda.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Rësponde ver si le doe imission a son nen uguaj.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"nen %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"A rëspond ver se l'imission a l'é fàussa. A rëspond fàuss se l'imission a l'é vera.\";\nBlockly.Msg.LOGIC_NULL = \"gnente\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"A rëspond gnente.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"e\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"o\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Rësponde ver se tute doe j'imission a son vere.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Rësponde ver se almanch un-a d'imission a l'é vera.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"preuva\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"se fàuss\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"se ver\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Controlé la condission an 'preuva'. Se la condission a l'é vera, a rëspond con ël valor 'se ver'; dësnò a rëspond con ël valor 'se fàuss'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"A smon la soma ëd doi nùmer.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"A smon ël cossient dij doi nùmer.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"A smon la diferensa dij doi nùmer.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"A smon ël prodot dij doi nùmer.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"A smon ël prim nùmer alvà a la potensa dël second.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"për\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"ancrementé\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Gionté un nùmer a la variàbil '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"A smon un-a dle costante comun-e π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) o ∞ (infinì).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"limité %1 antra %2 e %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Limité un nùmer a esse antra le limitassion ëspessificà (comprèise).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"a l'é divisìbil për\";\nBlockly.Msg.MATH_IS_EVEN = \"a l'é cobi\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"a l'é negativ\";\nBlockly.Msg.MATH_IS_ODD = \"a l'é dëscobi\";\nBlockly.Msg.MATH_IS_POSITIVE = \"a l'é positiv\";\nBlockly.Msg.MATH_IS_PRIME = \"a l'é prim\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"A contròla si un nùmer a l'é cobi, dëscobi, prim, antreghm positiv, negativ, o s'a l'é divisìbil për un nùmer dàit. A rëspond ver o fàuss.\";\nBlockly.Msg.MATH_IS_WHOLE = \"a l'é antregh\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resta ëd %1:%2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"A smon la resta ëd la division dij doi nùmer.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Un nùmer.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"media dla lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"màssim ëd la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mesan-a dla lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"mìnim ëd la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"mòde dla lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"element a l'ancàpit ëd la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"deviassion ëstàndard ëd la lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"soma dla lista\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"A smon la media (aritmética) dij valor numérich ant la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"A smon ël pi gròss nùmer ëd la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"A smon ël nùmer mesan ëd la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"A smon ël pi cit nùmer ëd la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"A smon na lista dj'element pi frequent ëd la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"A smon n'element a l'ancàpit da la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"A smon la deviassion ëstàndard ëd la lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"A smon la soma ëd tuti ij nùmer ant la lista.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"frassion aleatòria\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"A smon na frassion aleatòria antra 0,0 (comprèis) e 1,0 (esclus).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"antregh aleatòri antra %1 e %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"A smon n'antregh aleatòri antra ij doi lìmit ëspessificà, comprèis.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"ariondé\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"ariondé për difet\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"ariondé për ecess\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"A arionda un nùmer për difet o ecess.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"assolù\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"rèis quadra\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"A smon ël valor assolù d'un nùmer.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"A smon e a la potensa d'un nùmer.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"A smon ël logaritm natural d'un nùmer.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"A smon ël logaritm an base 10 d'un nùmer.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"A smon l'opòst d'un nùmer.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"A smon 10 a la potensa d'un nùmer.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"A smon la rèis quadra d'un nùmer.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"A smon l'arch-cosen d'un nùmer.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"A smon l'arch-sen d'un nùmer.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"A smon l'arch-tangenta d'un nùmer.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"A smon ël cosen ëd n'àngol an gré (pa an radiant).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"A smon ël sen ëd n'àngol an gré (pa an radiant).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"A smon la tangenta ëd n'àngol an gré (pa an radiant).\";\nBlockly.Msg.NEW_VARIABLE = \"Neuva variàbil...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nòm ëd la neuva variàbil:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"con:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Eseguì la fonsion '%1' definìa da l'utent.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Eseguì la fonsion '%1' definìa da l'utent e dovré sò arzultà.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Creé '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"fé cheicòs\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"a\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"A crea na fonsion sensa surtìa.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"artorn\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"A crea na fonsion con na surtìa.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Atension: Costa fonsion a l'ha dij paràmeter duplicà.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Sot-ligné la definission dla fonsion\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Se un valor a l'é ver, antlora smon-e un second valor.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Atension: Ës blòch a podria esse dovrà mach an na definission ëd fonsion.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nòm ëd l'imission:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"imission\";\nBlockly.Msg.REMOVE_COMMENT = \"Scancelé un coment\";\nBlockly.Msg.RENAME_VARIABLE = \"Arnomé la variàbil...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Arnomé tute le variàbij '%1' 'me:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"taché ël test\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"a\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Taché dël test a la variàbil '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"an minùscul\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"an Majùscol A L'Ancamin Ëd Minca Paròla\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"an MAJÙSCOL\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"A smon na còpia dël test ant un caràter diferent.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"oten-e la prima litra\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"oten-e la litra # da la fin\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"oten-e la litra #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"ant ël test\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"oten-e l'ùltima litra\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"oten-e na litra a l'ancàpit\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"A smon la litra ant la posission ëspessificà.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Gionté n'element al test.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"gionze\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Gionté, gavé o riordiné le session për configuré torna ës blòch ëd test.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"fin-a a la litra # da la fin\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"fin-a a la litra #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"fin-a a l'ùltima litra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"ant ël test\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"oten-e la sota-stringa da la prima litra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"oten-e la sota-stringa da la litra # da la fin\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"oten-e la sota-stringa da la litra #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"A smon un tòch ëspessificà dël test.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"ant ël test\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"trové la prima ocorensa dël test\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"trové l'ùltima ocorensa dël test\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"A smon l'ìndes dla prima/ùltima ocorensa dël prim test ant ël second test. A smon 0 se ël test a l'é nen trovà.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 a l'é veuid\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"A smon ver se ël test fornì a l'é veuid.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"creé ël test con\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Creé un tòch ëd test an gionzend un nùmer qualsëssìa d'element.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"longheur ëd %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"A smon ël nùmer ëd litre (spassi comprèis) ant ël test fornì.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"smon-e %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Smon-e ël test, ël nùmer o n'àutr valor ëspessificà.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Ciamé un nùmer a l'utent.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Ciamé un test a l'utent.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"anvit për un nùmer con un mëssagi\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"anvit për un test con un mëssagi\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Na litra, na paròla o na linia ëd test.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"gavé jë spassi da le doe bande ëd\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"gavé jë spassi da la banda snistra ëd\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"gavé jë spassi da la banda drita ëd\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"A smon na còpia dël test con jë spassi gavà da n'estremità o da tute doe.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Creé 'fissé %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"A smon ël valor ëd sa variàbil.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Creé 'oten-e %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"a\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"fissé\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Fissé costa variàbil ugual al valor d'imission.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/pt-br.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.pt-br');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Adicionar Comentário\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Mudar valor:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Recolher Blocos\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Recolher Bloco\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"cor 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"cor 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"proporção\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"misturar\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Mistura duas cores dada uma proporção (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://pt.wikipedia.org/wiki/Cor\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Escolher uma cor da palheta de cores.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"cor aleatória\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Escolher cor de forma aleatória.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"azul\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"verde\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"vermelho\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"colorir com\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Cria uma cor de acordo com a quantidade especificada de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"encerra o laço\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continua com a próxima iteração do laço\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Encerra o laço.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Ignora o resto deste laço, e continua com a próxima iteração.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Atenção: Este bloco só pode ser usado dentro de um laço.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"na lista\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"para cada item\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Para cada item em uma lista, atribui o item à variável \\\"%1\\\", e então realiza algumas instruções.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"de %1 até %2 por %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"contar com\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Faz com que a variável %1 assuma os valores do número inicial ao número final, contando de acordo com o intervalo especificado, e executa os blocos especificados.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Acrescente uma condição para o bloco se.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Acrescente uma condição final para o bloco se.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Acrescente, remova ou reordene seções para reconfigurar este bloco.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"senão\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"senão se\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"se\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Se um valor é verdadeiro, então realize algumas instruções.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Se um valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, realize o segundo bloco de instruções.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.  Se nenhum dos blocos for verdadeiro, realize o último bloco de instruções.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o#Repeti.C3.A7.C3.A3o_com_vari.C3.A1vel_de_controle\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"faça\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"Repita %1 vezes\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"repita\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"vezes\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Faça algumas instruções várias vezes.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"repita até\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"repita enquanto\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Enquanto um valor é falso, então faça algumas instruções.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Enquanto um valor for verdadeiro, então faça algumas instruções.\";\nBlockly.Msg.DELETE_BLOCK = \"Remover Bloco\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Remover %1 Blocos\";\nBlockly.Msg.DISABLE_BLOCK = \"Desabilitar Bloco\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplicar\";\nBlockly.Msg.ENABLE_BLOCK = \"Habilitar Bloco\";\nBlockly.Msg.EXPAND_ALL = \"Expandir Blocos\";\nBlockly.Msg.EXPAND_BLOCK = \"Expandir Bloco\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Entrada externa\";\nBlockly.Msg.HELP = \"Ajuda\";\nBlockly.Msg.INLINE_INPUTS = \"Entradas Internas\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"criar lista vazia\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Retorna uma lista, de tamanho 0, contendo nenhum registro\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Acrescenta, remove ou reordena seções para reconfigurar este bloco de lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"criar lista com\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Acrescenta um item à lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Cria uma lista com a quantidade de itens informada.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"primeiro\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"nº a partir do final\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"nº\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"obter\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"obter e remover\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"último\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"aleatório\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"remover\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Retorna o primeiro item em uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Retorna o item da lista na posição especificada.  #1 é o último item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Retorna o item da lista na posição especificada.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Retorna o último item em uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Retorna um item aleatório de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Remove e retorna o primeiro item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Remove e retorna o item na posição especificada em uma lista.  #1 é o último item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Remove e retorna o item na posição especificada em uma lista.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Remove e retorna o último item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Remove e retorna um item aleatório de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Remove o primeiro item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Remove o item na posição especificada em uma lista.  #1 é o último item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Remove o item na posição especificada em uma lista.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Remove o último item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Remove um item aleatório de uma lista.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"até nº a partir do final\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"até nº\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"até último\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"obtém sublista a partir do primeiro\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"obtém sublista de nº a partir do final\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"obtém sublista de nº\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Cria uma cópia da porção especificada de uma lista.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"encontre a primeira ocorrência do item\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"encontre a última ocorrência do item\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Retorna a posição da primeira/última ocorrência do item na lista.  Retorna 0 se o texto não for encontrado.\";\nBlockly.Msg.LISTS_INLIST = \"na lista\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 é vazia\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"tamanho de %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Retorna o tamanho de uma lista.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"criar lista com item %1 repetido %2 vezes\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Cria uma lista consistindo no valor informado repetido o número de vezes especificado.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"como\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"inserir em\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"definir\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Insere o item no início de uma lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Insere o item na posição especificada em uma lista.  #1 é o último item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Insere o item na posição especificada em uma lista.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Insere o item no final de uma lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Insere o item em uma posição qualquer de uma lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Define o primeiro item de uma lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Define o item da posição especificada de uma lista.  #1 é o último item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Define o item da posição especificada de uma lista.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Define o último item de uma lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Define um item aleatório de uma lista.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Retona verdadeiro se a lista estiver vazia.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"falso\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Retorna verdadeiro ou falso.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"verdadeiro\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://pt.wikipedia.org/wiki/Inequa%C3%A7%C3%A3o\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Retorna verdadeiro se ambas as entradas forem iguais.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Retorna verdadeiro se a primeira entrada for maior que a segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Retorna verdadeiro se a primeira entrada for menor que a segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Retorna verdadeiro se ambas as entradas forem diferentes.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"não %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Retorna verdadeiro se a entrada for falsa.  Retorna falsa se a entrada for verdadeira.\";\nBlockly.Msg.LOGIC_NULL = \"nulo\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Retorna nulo.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"e\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"ou\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Retorna verdadeiro se ambas as entradas forem verdadeiras.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Retorna verdadeiro se uma das estradas for verdadeira.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"teste\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"se falso\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"se verdadeiro\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Avalia a condição em \\\"teste\\\". Se a condição for verdadeira retorna o valor \\\"se verdadeiro\\\", senão retorna o valor \\\"se falso\\\".\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://pt.wikipedia.org/wiki/Aritm%C3%A9tica\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Retorna a soma dos dois números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Retorna o quociente da divisão dos dois números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Retorna a diferença entre os dois números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Retorna o produto dos dois números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Retorna o primeiro número elevado à potência do segundo número.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"por\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"alterar\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Soma um número à variável \\\"%1\\\".\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://pt.wikipedia.org/wiki/Anexo:Lista_de_constantes_matem%C3%A1ticas\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"restringe %1 inferior %2 superior %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Restringe um número entre os limites especificados (inclusivo).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"é divisível por\";\nBlockly.Msg.MATH_IS_EVEN = \"é par\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"é negativo\";\nBlockly.Msg.MATH_IS_ODD = \"é ímpar\";\nBlockly.Msg.MATH_IS_POSITIVE = \"é positivo\";\nBlockly.Msg.MATH_IS_PRIME = \"é primo\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Verifica se um número é par, ímpar, inteiro, positivo, negativo, ou se é divisível por outro número.  Retorna verdadeiro ou falso.\";\nBlockly.Msg.MATH_IS_WHOLE = \"é inteiro\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://pt.wikipedia.org/wiki/Opera%C3%A7%C3%A3o_m%C3%B3dulo\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resto da divisão de %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Retorna o resto da divisão de dois números.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://pt.wikipedia.org/wiki/N%C3%BAmero\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Um número.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"média da lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"maior da lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mediana da lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"menor da lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"moda da lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"item aleatório da lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"desvio padrão da lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"soma de uma lista\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Retorna a média aritmética dos números da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Retorna o maior número da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Retorna a mediana dos números da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Retorna o menor número da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Retorna uma lista do(s) item(ns) mais comum(ns) da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Retorna um elemento aleatório da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Retorna o desvio padrão dos números da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Retorna a soma de todos os números na lista.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://pt.wikipedia.org/wiki/Gerador_de_n%C3%BAmeros_pseudoaleat%C3%B3rios\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"fração aleatória\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Retorna uma fração aleatória entre 0.0 (inclusivo) e 1.0 (exclusivo).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://pt.wikipedia.org/wiki/Gerador_de_n%C3%BAmeros_pseudoaleat%C3%B3rios\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"inteiro aleatório entre %1 e %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Retorna um número inteiro entre os dois limites informados, inclusivo.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://pt.wikipedia.org/wiki/Arredondamento\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"arredonda\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"arredonda para baixo\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"arredonda para cima\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Arredonda um número para cima ou para baixo.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://pt.wikipedia.org/wiki/Raiz_quadrada\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absoluto\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"raiz quadrada\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Retorna o valor absoluto de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Retorna o número e elevado à potência de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Retorna o logaritmo natural de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Retorna o logaritmo em base 10 de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Retorna o oposto de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Retorna 10 elevado à potência de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Retorna a raiz quadrada de um número.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_trigonom%C3%A9trica\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Retorna o arco cosseno de um número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Retorna o arco seno de um número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Retorna o arco tangente de um número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Retorna o cosseno de um grau (não radiano).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Retorna o seno de um grau (não radiano).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Retorna a tangente de um grau (não radiano).\";\nBlockly.Msg.NEW_VARIABLE = \"Nova variável...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nome da nova variável:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"com:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://pt.wikipedia.org/wiki/Sub-rotina\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Executa a função definida pelo usuário \\\"%1\\\".\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://pt.wikipedia.org/wiki/Sub-rotina\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Executa a função definida pelo usuário \\\"%1\\\" e usa seu retorno.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Criar \\\"%1\\\"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"faça algo\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"para\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Cria uma função que não tem retorno.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"retorna\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Cria uma função que possui um valor de retorno.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Atenção: Esta função tem parâmetros duplicados.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Destacar definição da função\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Se um valor é verdadeiro, então retorna um valor.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Atenção: Este bloco só pode ser utilizado dentro da definição de uma função.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nome da entrada:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"entradas\";\nBlockly.Msg.REMOVE_COMMENT = \"Remover Comentário\";\nBlockly.Msg.RENAME_VARIABLE = \"Renomear variável...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Renomear todas as variáveis '%1' para:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"acrescentar texto\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"para\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Acrescentar um pedaço de texto à variável \\\"%1\\\".\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"para minúsculas\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"para Nomes Próprios\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"para MAIÚSCULAS\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Retorna uma cópia do texto em um formato diferente.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"obter primeira letra\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"obter letra nº a partir do final\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"obter letra nº\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"no texto\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"obter última letra\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"obter letra aleatória\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Retorna a letra na posição especificada.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Acrescentar um item ao texto.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"unir\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"até letra nº a partir do final\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"até letra nº\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"até última letra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"no texto\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"obter trecho de primeira letra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"obter trecho de letra nº a partir do final\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"obter trecho de letra nº\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Retorna o trecho de texto especificado.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"no texto\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"primeira ocorrência do texto\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"última ocorrência do texto\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto.  Retorna 0 se o texto não for encontrado.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 é vazio\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Retorna verdadeiro se o texto fornecido for vazio.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"criar texto com\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Criar um pedaço de texto juntando qualquer número de itens.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"tamanho de %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Retorna o número de letras (incluindo espaços) no texto fornecido.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"imprime %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Imprime o texto, número ou valor especificado.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Pede ao usuário um número.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Pede ao usuário um texto.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"Pede um número com uma mensagem\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"Pede um texto com uma mensagem\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://pt.wikipedia.org/wiki/Cadeia_de_caracteres\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Uma letra, palavra ou linha de texto.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"remover espaços de ambos os lados de\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"remover espaços à esquerda de\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"remover espaços à direita de\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Retorna uma cópia do texto com os espaços removidos de uma ou ambas extremidades.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"item\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Criar \\\"definir %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Retorna o valor desta variável.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Criar \\\"obter %1\\\"\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"para\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"definir\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Define esta variável para o valor da entrada.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/pt.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.pt');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Adicionar Comentário\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Alterar valor:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Recolher Blocos\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Colapsar Bloco\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"cor 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"cor 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"proporção\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"misturar\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Mistura duas cores dada uma proporção (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"http://pt.wikipedia.org/wiki/Cor\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Escolhe uma cor da paleta de cores.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"cor aleatória\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Escolher cor de forma aleatória.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"azul\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"verde\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"vermelho\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"pinte com\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Cria uma cor de acordo com a quantidade especificada de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"sair do ciclo\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continuar com a próxima iteração do ciclo\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Sair do ciclo que está contido.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Ignora o resto deste ciclo e continua na próxima iteração.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Atenção: Este bloco só pode ser usado dentro de um ciclo.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Ciclos#para_cada\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"na lista\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"para cada item\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Para cada item numa lista, define a variável \\\"%1\\\" para o item e então faz algumas instruções.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"de %1 até %2 de %3 em %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"contar com\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Faz com que a variável %1 assuma os valores desde o número inicial até ao número final, contando de acordo com o intervalo especificado e executa os blocos especificados.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Acrescente uma condição ao bloco se.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Acrescente uma condição de excepação final para o bloco se.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Acrescente, remova ou reordene secções para reconfigurar este bloco se.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"senão\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"senão se\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"se\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Se um valor é verdadeiro, então realize alguns passos.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Se um valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, realize o segundo bloco de instruções\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.  Se nenhum dos blocos for verdadeiro, realize o último bloco de instruções.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"http://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o#Repeti.C3.A7.C3.A3o_com_vari.C3.A1vel_de_controle\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"faça\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"repita %1 vez\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"repita\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"vezes\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Faça algumas instruções várias vezes.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"repita até\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"repita enquanto\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Enquanto um valor for falso, então faça algumas instruções.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Enquanto um valor for verdadeiro, então faça algumas instruções.\";\nBlockly.Msg.DELETE_BLOCK = \"Remover Bloco\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Remover %1 Blocos\";\nBlockly.Msg.DISABLE_BLOCK = \"Desabilitar Bloco\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplicar\";\nBlockly.Msg.ENABLE_BLOCK = \"Habilitar Bloco\";\nBlockly.Msg.EXPAND_ALL = \"Expandir Blocos\";\nBlockly.Msg.EXPAND_BLOCK = \"Expandir Bloco\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Entradas externas\";\nBlockly.Msg.HELP = \"Ajuda\";\nBlockly.Msg.INLINE_INPUTS = \"Entradas Internas\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"criar lista vazia\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Retorna uma lista, de tamanho 0, contendo nenhum registo\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Acrescente, remova ou reordene as seções para reconfigurar este bloco lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"criar lista com\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Acrescenta um item à lista.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Cria uma lista com qualquer número de itens.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"primeiro\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# a partir do final\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"obter\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"obter e remover\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"último\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"aleatório\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"remover\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Retorna o primeiro item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Retorna o item da lista na posição especificada.  #1 é o último item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Retorna o item na posição especificada da lista .  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Retorna o último item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Retorna um item aleatório de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Remove e retorna o primeiro item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Remove e retorna o item na posição especificada de uma lista.  #1 é o último item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Remove e retorna o item na posição especificada de uma lista.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Remove e retorna o último item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Remove e retorna um item aleatório de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Remove o primeiro item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Remove o item na posição especificada de uma lista.  #1 é o ultimo item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Remove o item de uma posição especifica da lista.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Remove o último item de uma lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Remove um item aleatório de uma lista.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"até #, a partir do final\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"até #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"para o último\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"obtem sublista da primeira lista\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"obtem sublista de # a partir do final\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"obtem sublista de #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Cria uma cópia da porção especificada de uma lista.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"encontre a primeira ocorrência do item\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"encontre a última ocorrência do item\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Retorna a posição da primeira/última ocorrência do item na lista.  Retorna 0 se o texto não for encontrado.\";\nBlockly.Msg.LISTS_INLIST = \"na lista\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 está vazia\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"tamanho de %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Retorna o tamanho de uma lista.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"criar lista com o item %1 repetido %2 vezes\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Cria uma lista constituída por um dado valor repetido o número de vezes especificado.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"como\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"inserir em\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"definir\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Insere o item no início da lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Insere o item numa posição especificada de uma lista.  #1 é o último item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Insere o item numa posição especificada numa lista.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Insere o item no final da lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Insere o item numa posição aleatória de uma lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Define o primeiro item de uma lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Define o item na posição especificada de uma lista.  #1 é o último item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Define o item na posição especificada de uma lista.  #1 é o primeiro item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Define o último item de uma lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Define um item aleatório de uma lista.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Retona verdadeiro se a lista estiver vazia.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"falso\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Retorna verdadeiro ou falso.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"verdadeiro\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"http://pt.wikipedia.org/wiki/Inequa%C3%A7%C3%A3o\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Retorna verdadeiro se ambas as entradas forem iguais entre si.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Retorna verdadeiro se a primeira entrada for maior que a segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Retorna verdadeiro se a primeira entrada for menor que a segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Retorna verdadeiro se ambas as entradas forem diferentes entre si.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"não %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Retorna verdadeiro se a entrada for falsa.  Retorna falso se a entrada for verdadeira.\";\nBlockly.Msg.LOGIC_NULL = \"nulo\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"http://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Retorna nulo.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"e\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"ou\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Retorna verdadeiro se ambas as entradas forem verdadeiras.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Retorna verdadeiro se pelo menos uma das estradas for verdadeira.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"teste\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"http://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"se falso\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"se verdadeiro\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Avalia a condição em \\\"teste\\\". Se a condição for verdadeira retorna o valor \\\"se verdadeiro\\\", senão retorna o valor \\\"se falso\\\".\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"http://pt.wikipedia.org/wiki/Aritm%C3%A9tica\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Retorna a soma de dois números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Retorna o quociente da divisão de dois números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Retorna a diferença de dois números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Retorna o produto de dois números.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Retorna o primeiro número elevado à potência do segundo número.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"http://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"por\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"alterar\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Soma um número à variável \\\"%1\\\".\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"http://pt.wikipedia.org/wiki/Anexo:Lista_de_constantes_matem%C3%A1ticas\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"restringe %1 inferior %2 superior %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Restringe um número entre os limites especificados (inclusive).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"é divisível por\";\nBlockly.Msg.MATH_IS_EVEN = \"é par\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"é negativo\";\nBlockly.Msg.MATH_IS_ODD = \"é impar\";\nBlockly.Msg.MATH_IS_POSITIVE = \"é positivo\";\nBlockly.Msg.MATH_IS_PRIME = \"é primo\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Verifica se um número é par, impar, primo, inteiro, positivo, negativo, ou se é divisível por outro número.  Retorna verdadeiro ou falso.\";\nBlockly.Msg.MATH_IS_WHOLE = \"é inteiro\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"http://pt.wikipedia.org/wiki/Opera%C3%A7%C3%A3o_m%C3%B3dulo\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resto da divisão de %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Retorna o resto da divisão de dois números.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"http://pt.wikipedia.org/wiki/N%C3%BAmero\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Um número.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"média de uma lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"maior de uma lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mediana de uma lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"menor de uma lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"moda de uma lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"item aleatório de uma lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"desvio padrão de uma lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"soma da lista\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Retorna a média aritmética dos valores números da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Retorna o maior número da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Retorna a mediana da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Retorna o menor número da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Retorna a lista de item(ns) mais comum(ns) da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Retorna um elemento aleatório da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Retorna o desvio padrão dos números da lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Retorna a soma de todos os números da lista.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"http://pt.wikipedia.org/wiki/N%C3%BAmero_aleat%C3%B3rio\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"fração aleatória\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Insere uma fração aleatória entre 0.0 (inclusive) e 1.0 (exclusive).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"http://pt.wikipedia.org/wiki/N%C3%BAmero_aleat%C3%B3rio\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"inteiro aleatório entre %1 e %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Retorna um número inteiro entre os dois limites especificados, inclusive.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"http://pt.wikipedia.org/wiki/Arredondamento\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"arredonda\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"arredonda para baixo\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"arredonda para cima\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Arredonda um número para cima ou para baixo.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"http://pt.wikipedia.org/wiki/Raiz_quadrada\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absoluto\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"raíz quadrada\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Retorna o valor absoluto de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Retorna o número e elevado à potência de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Retorna o logarítmo natural de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Retorna o logarítmo em base 10 de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Retorna o oposto de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Retorna 10 elevado à potência de um número.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Retorna a raiz quadrada de um número.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"http://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_trigonom%C3%A9trica\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Retorna o arco cosseno de um número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Retorna o arco seno de um número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Retorna o arco tangente de um número.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Retorna o cosseno de um grau (não radiano).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Retorna o seno de um grau (não radiano).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Retorna a tangente de um grau (não radiano).\";\nBlockly.Msg.NEW_VARIABLE = \"Nova variável...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nome da nova variável:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"com:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"http://pt.wikipedia.org/wiki/Sub-rotina\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Executa a função \\\"%1\\\".\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"http://pt.wikipedia.org/wiki/Sub-rotina\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Executa a função \\\"%1\\\" e usa o seu retorno.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Criar \\\"%1\\\"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"faz algo\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"para\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Cria uma função que não tem retorno.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"retorna\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Cria uma função que possui um valor de retorno.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Atenção: Esta função tem parâmetros duplicados.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Destacar definição da função\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"se o valor é verdadeiro, então retorna um segundo valor.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Atenção: Este bloco só pode ser utilizado dentro da definição de uma função.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nome da entrada:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"entradas\";\nBlockly.Msg.REMOVE_COMMENT = \"Remover Comentário\";\nBlockly.Msg.RENAME_VARIABLE = \"Renomear variável...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Renomear todas as variáveis '%1' para:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"acrescentar texto\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"para\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Acrescentar um pedaço de texto à variável \\\"%1\\\".\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"para minúsculas\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"para Iniciais Maiúsculas\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"para MAIÚSCULAS\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Retorna uma cópia do texto em formato diferente.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"obter primeira letra\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"obter letra nº a partir do final\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"obter letra nº\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"no texto\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"obter última letra\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"obter letra aleatória\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Retorna a letra na posição especificada.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Acrescentar um item ao texto.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"unir\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"até letra nº a partir do final\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"até letra nº\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"até última letra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"no texto\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"obter subsequência a partir da primeira letra\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"obter subsequência de tamanho # a partir do final\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"obter subsequência de tamanho #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Retorna a parte especificada do texto.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"no texto\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"primeira ocorrência do texto\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"última ocorrência do texto\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto.  Retorna 0 se o texto não for encontrado.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 está vazio\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Retorna verdadeiro se o texto fornecido estiver vazio.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"criar texto com\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Criar um pedaço de texto juntando qualquer número de itens.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"tamanho de %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Devolve o número de letras (incluindo espaços) do texto fornecido.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"imprime %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Imprime o texto, número ou outro valor especificado.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Pede ao utilizador um número.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Pede ao utilizador um texto.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"pede um número com a mensagem\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"Pede um texto com a mensagem\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"http://pt.wikipedia.org/wiki/Cadeia_de_caracteres\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Uma letra, palavra ou linha de texto.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"remover espaços de ambos os lados\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"remover espaços à esquerda\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"remover espaços à direita\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Retorna uma cópia do texto com os espaços removidos de uma ou ambas as extremidades.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"item\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Criar \\\"definir %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Retorna o valor desta variável.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Criar \\\"obter %1\\\"\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"para\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"definir\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Define esta variável para o valor inserido.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/ro.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.ro');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Adaugă un comentariu\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Schimbaţi valoarea:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Restrange blocurile\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Restrange blocul\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"culoare 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"culoare 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"Raport\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"amestec\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Amestecă două culori cu un raport dat (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://ro.wikipedia.org/wiki/Culoare\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Alege o culoare din paleta de culori.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"culoare aleatorie\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Alege o culoare la întâmplare.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"albastru\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"verde\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"roşu\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"colorează cu\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Creează o culoare cu suma specificată de roşu, verde şi albastru.  Toate valorile trebuie să fie între 0 şi 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"ieşi din bucla\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"continuă cu următoarea iterație a buclei\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Ieși din bucla care conţine.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Sari peste restul aceastei bucle, şi continuă cu urmatoarea iteratie.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Avertisment: Acest bloc pote fi utilizat numai în interiorul unei bucle.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"în listă\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"pentru fiecare element\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Pentru fiecare element din listă, setaţi variabila '%1' ca valoarea elementului, şi apoi faceţi unele declaraţii.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"de la %1 la %2 prin %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"numără cu\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Cu variablia %1 ia o valoare din numărul început la numărul final, numara in intervalul specificat, apoi face blocurile specificate.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Adăugaţi o condiţie in blocul if.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Adauga o stare finala, cuprinde toata conditia din blocul if.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Adaugă, elimină sau reordonează secţiuni pentru a reconfigura acest bloc if.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"altfel\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"altfel dacă\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"dacă\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Dacă o valoare este adevărată, atunci fa unele declaraţii.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Dacă o valoare este adevărat, atunci face primul bloc de declaraţii.  Altfel, face al doilea bloc de declaraţii.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Dacă prima valoare este adevărat, atunci face primul bloc de declaraţii.  Altfel, dacă a doua valoare este adevărat, face al doilea bloc de declaraţii.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Dacă prima valoare este adevărat, atunci face primul bloc de declaraţii.  Altfel, dacă a doua valoare este adevărat, face al doilea bloc de declaraţii.  În cazul în care niciuna din  valorilor nu este adevărat, face ultimul bloc de declaraţii.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"fă\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"repetă de %1 ori\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"repetă\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"ori\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Face unele afirmaţii de mai multe ori.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"Repetaţi până când\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"repetă în timp ce\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"În timp ce o valoare este adevărat, atunci face unele declaraţii.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"În timp ce o valoare este adevărat, atunci face unele declaraţii.\";\nBlockly.Msg.DELETE_BLOCK = \"Șterge Bloc\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Ștergeți %1 Blocuri\";\nBlockly.Msg.DISABLE_BLOCK = \"Dezactivaţi bloc\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplicati\";\nBlockly.Msg.ENABLE_BLOCK = \"Permite bloc\";\nBlockly.Msg.EXPAND_ALL = \"Extinde blocuri\";\nBlockly.Msg.EXPAND_BLOCK = \"Extinde bloc\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Intrări Externe\";\nBlockly.Msg.HELP = \"Ajutor\";\nBlockly.Msg.INLINE_INPUTS = \"Intrari de Linie\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"creează listă goală\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Returnează o listă, de lungime 0, care nu conţine înregistrări de date\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"listă\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Adaugă, elimină sau reordonează secţiuni ca să reconfiguraţi aceste blocuri de listă.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"creează listă cu\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Adăugaţi un element la listă.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Creaţi o listă cu orice număr de elemente.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"primul\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# de la sfârșit\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"obţine\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"obţine şi elimină\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"ultimul\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"aleator\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"elimină\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returnează primul element dintr-o listă.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Returneaza elementul la poziţia specificată într-o listă.  #1 este ultimul element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Returneaza elementul la poziţia specificată într-o listă.  #1 este primul element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returnează ultimul element într-o listă.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returneaza un element aleatoriu într-o listă.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Elimină şi returnează primul element într-o listă.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Elimină şi returneaza elementul la poziţia specificată într-o listă.  #1 este ultimul element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Elimină şi returneaza elementul la poziţia specificată într-o listă.  #1 este primul element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Elimină şi returnează ultimul element într-o listă.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Elimină şi returnează un element aleatoriu într-o listă.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Elimină primul element într-o listă.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Elimină elementul la poziţia specificată într-o listă.  #1 este ultimul element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Elimină elementul la poziţia specificată într-o listă.  #1 este primul element.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Elimină ultimul element într-o listă.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Elimină un element aleatoriu într-o listă.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"la # de la sfarsit\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"la #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"la ultima\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"obţine sub-lista de la primul\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"obţine sub-lista de la # de la sfârşitul\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"obţine sub-lista de la #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Creează o copie a porţiunii specificate dintr-o listă.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"Găseşte prima apariţie a elementului\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"găseşte ultima apariţie a elementului\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Returneaza indexul de la prima/ultima aparitie a elementuli din lista. Returneaza 0 daca textul nu este gasit.\";\nBlockly.Msg.LISTS_INLIST = \"în listă\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 este gol\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"lungime de %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returnează lungimea unei liste.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"creaza lista cu %1 elemente repetate de %2 ori\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Creează o listă alcătuită dintr-o anumită valoare repetată de numărul specificat de ori.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"ca\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"introduceţi la\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"seteaza\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Inserează elementul la începutul unei liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Inserează elementul la poziţia specificată într-o listă.  #1 este ultimul element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Inserează elementul la poziţia specificată într-o listă.  #1 este primul element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Adăugă elementul la sfârşitul unei liste.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Inserează elementul aleatoriu într-o listă.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Setează primul element într-o listă.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Setează elementul la poziţia specificată într-o listă.  #1 este ultimul element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Setează elementul la poziţia specificată într-o listă.  #1 este primul element.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Setează ultimul element într-o listă.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Setează un element aleator într-o listă.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Returnează adevărat dacă lista este goală.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"fals\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Returnează adevărat sau fals.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"adevărat\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Returnează adevărat dacă ambele intrări sunt egale.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Returnează adevărat dacă prima intrare este mai mare decât a doua intrare.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Returnează adevărat dacă prima intrare este mai mare sau egală cu a doua intrare.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Returnează adevărat dacă prima intrare este mai mică decât a doua intrare.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Returnează adevărat dacă prima intrare este mai mică sau egală cu a doua intrare.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Returnează adevărat daca cele două intrări nu sunt egale.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"non %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returnează adevărat dacă intrarea este falsă.  Returnează fals dacă intrarea este adevărată.\";\nBlockly.Msg.LOGIC_NULL = \"nul\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"returnează nul.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"şi\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"sau\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Returnează adevărat daca ambele intrări sunt adevărate.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Returnează adevărat dacă cel puţin una din intrări este adevărată.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"dacă este fals\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"dacă este adevărat\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Verifică condiţia din \\\"test\\\". Dacă condiţia este adevărată, returnează valoarea \\\"în cazul în care adevărat\\\"; în caz contrar întoarce valoarea \\\"în cazul în care e fals\\\".\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://ro.wikipedia.org/wiki/Aritmetic%C4%83\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Returnează suma a două numere.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Returnează câtul celor două numere.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Returneaza diferenţa dintre cele două numere.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Returnează produsul celor două numere.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Returneaza numărul rezultat prin ridicarea primului număr la puterea celui de-al doilea.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"de\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"schimbă\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Adaugă un număr variabilei '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://ro.wikipedia.org/wiki/Constant%C4%83_matematic%C4%83\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Întoarcă una din constantele comune: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) sau ∞ (infinitate).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrânge %1 redus %2 ridicat %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrânge un număr să fie între limitele specificate (inclusiv).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"este divizibil cu\";\nBlockly.Msg.MATH_IS_EVEN = \"este par\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"este negativ\";\nBlockly.Msg.MATH_IS_ODD = \"este impar\";\nBlockly.Msg.MATH_IS_POSITIVE = \"este pozitiv\";\nBlockly.Msg.MATH_IS_PRIME = \"este prim\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Verifică dacă un număr este un par, impar, prim, întreg, pozitiv, negativ, sau dacă este divizibil cu un anumit număr.  Returnează true sau false.\";\nBlockly.Msg.MATH_IS_WHOLE = \"este întreg\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"restul la %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Întoarce restul din împărţirea celor două numere.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Un număr.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"media listei\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"maximul listei\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"media listei\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minimul listei\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"moduri de listă\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"element aleatoriu din lista\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"deviația standard a listei\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"suma listei\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Întoarce media (aritmetică) a valorilor numerice în listă.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Întoarce cel mai mare număr din listă.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Întoarce numărul median în listă.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Returnează cel mai mic număr din listă.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Returnează o listă cu cel(e) mai frecvent(e) element(e) din listă.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Returnează un element aleatoriu din listă.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Întoarce deviația standard a listei.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Returnează suma tuturor numerelor din lista.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"fracții aleatorii\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Returnează o fracţie aleatoare între 0.0 (inclusiv) si 1.0 (exclusiv).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"un număr întreg aleator de la %1 la %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Returnează un număr întreg aleator aflat între cele două limite specificate, inclusiv.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"rotund\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"rotunjit\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"rotunjește în sus\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Rotunjirea unui număr în sus sau în jos.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolută\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"rădăcina pătrată\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Returnează valoarea absolută a unui număr.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Returnează e la puterea unui număr.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Întoarce logaritmul natural al unui număr.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Returnează logaritmul în baza 10 a unui număr.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Returnează negaţia unui număr.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Returnează 10 la puterea unui număr.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Returnează rădăcina pătrată a unui număr.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"arccos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"arcsin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"arctg\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tg\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Returnează arccosinusul unui număr.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Returnează arcsinusul unui număr.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Returnează arctangenta unui număr.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Întoarce cosinusul unui grad (nu radianul).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Întoarce cosinusul unui grad (nu radianul).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Întoarce tangenta unui grad (nu radianul).\";\nBlockly.Msg.NEW_VARIABLE = \"Variabilă nouă...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Noul nume de variabilă:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"cu:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Executați funcția '%1 'definită de utilizator.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Executați funcția '%1 'definită de utilizator şi folosiţi producţia sa.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Creaţi '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"fă ceva\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"la\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Crează o funcţie cu nici o ieşire.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"returnează\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Creează o funcţie cu o ieşire.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Atenţie: Această funcţie are parametri duplicaţi.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Evidenţiază definiţia funcţiei\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Dacă o valoare este adevărată, atunci returnează valoarea a doua.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Avertisment: Acest bloc poate fi utilizat numai în definiţia unei funcţii.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"nume de intrare:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"intrări\";\nBlockly.Msg.REMOVE_COMMENT = \"Elimină comentariu\";\nBlockly.Msg.RENAME_VARIABLE = \"Redenumirea variabilei...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Redenumeşte toate variabilele '%1' în:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"Adăugaţi text\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"la\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Adăugaţi text la variabila '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"la litere mici\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"către Titlul de caz\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"la MAJUSCULE\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Întoarce o copie a textului într-un caz diferit.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"obţine prima litera\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"obţine litera # de la sfârșit\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"obtine litera #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"în text\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"obţine o litera oarecare\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"obtine o litera oarecare\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returnează litera la poziția specificată.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Adaugă un element în text.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"alăturaţi-vă\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Adaugă, elimină sau reordonează secțiuni ca să reconfigureze blocul text.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"la litera # de la sfarsit\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"la litera #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"la ultima literă\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"în text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"obţine un subșir de la prima literă\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"obține un subșir de la litera # de la sfârșit\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"obține subșir de la litera #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returnează o anumită parte din text.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"în text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"găseşte prima apariţie a textului\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"găseşte ultima apariţie a textului\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returnează indicele primei/ultimei apariţii din primul text în al doilea text.  Returnează 0 dacă textul nu este găsit.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 este gol\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returnează adevărat dacă textul furnizat este gol.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"crează text cu\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Creaţi o bucată de text prin unirea oricărui număr de elemente.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"lungime de %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returnează numărul de litere (inclusiv spaţiile) în textul furnizat.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"imprimare %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Afișează textul specificat, numărul sau altă valoare.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Solicită utilizatorul pentru un număr.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Solicită utilizatorul pentru text.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"solicită pentru număr cu mesaj\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"solicită pentru text cu mesaj\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"O literă, cuvânt sau linie de text.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"taie spațiile de pe ambele părți\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"tăiaţi spațiile din partea stângă\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"taie spațiile din partea dreaptă\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Returnează o copie a textului fără spațiile de la unul sau ambele capete.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"element\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Crează 'set %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returnează valoarea acestei variabile.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Crează 'get %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"la\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"seteaza\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Setează această variabilă sa fie egală la intrare.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/ru.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.ru');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Добавить комментарий\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Измените значение:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Свернуть блоки\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Свернуть блок\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"цвет 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"цвет 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"доля цвета 1\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"смешать\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Смешивает два цвета в заданном соотношении (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://ru.wikipedia.org/wiki/Цвет\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Выберите цвет из палитры.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"случайный цвет\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Выбирает цвет случайным образом.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"синего\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"зелёного\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"красного\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"цвет из\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Создаёт цвет с указанной пропорцией  красного, зеленого и синего.  Все значения должны быть между 0 и 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"выйти из цикла\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"перейти к следующему шагу цикла\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Прерывает этот цикл.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Пропускает остаток цикла и переходит к следующему шагу.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Предупреждение: этот блок может использоваться только внутри цикла.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"в списке\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"для каждого элемента\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Для каждого элемента в списке, присваивает переменной '%1' значение элемента  и выполняет указанные  команды.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"от %1 до %2 с шагом %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"цикл по\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Присваивает переменной %1 значения от начального до конечного с заданным шагом и выполняет указанные команды.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Добавляет условие к блоку \\\"если\\\"\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Добавить заключительный подблок для случая, когда все условия ложны.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Добавьте, удалите, переставьте фрагменты для переделки блока \\\"если\\\".\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"иначе\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"иначе если\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"если\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Если условие истинно, выполняет команды.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Если условие истинно, выполняет первый блок команд. Иначе выполняется второй блок команд.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Если первое условие истинно, то выполняет первый блок команд. Иначе, если второе условие истинно, выполняет второй блок команд.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Если первое условие истинно, то выполняет первый блок команд.  В противном случае, если второе условие истинно, выполняет второй блок команд.  Если ни одно из условий не истинно, выполняет последний блок команд.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://ru.wikipedia.org/wiki/Цикл_(программирование)\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"выполнить\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"повторить %1 раз\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"повторить\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"раз\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Выполняет команды несколько раз.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"повторять, пока не\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"повторять, пока\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Пока значение ложно, выполняет команды\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Пока значение истинно, выполняет команды.\";\nBlockly.Msg.DELETE_BLOCK = \"Удалить блок\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Удалить %1 блоков\";\nBlockly.Msg.DISABLE_BLOCK = \"Отключить блок\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Скопировать\";\nBlockly.Msg.ENABLE_BLOCK = \"Включить блок\";\nBlockly.Msg.EXPAND_ALL = \"Развернуть блоки\";\nBlockly.Msg.EXPAND_BLOCK = \"Развернуть блок\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Вставки снаружи\";\nBlockly.Msg.HELP = \"Справка\";\nBlockly.Msg.INLINE_INPUTS = \"Вставки внутри\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"создать пустой список\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Возвращает список длины 0, не содержащий данных\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"список\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Добавьте, удалите, переставьте элементы для переделки блока списка.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"создать список из\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Добавляет элемент к списку.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Создаёт список с любым числом элементов.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"первый\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"№ с конца\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"взять\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"взять и удалить\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"последний\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"произвольный\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"удалить\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Возвращает первый элемент списка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Возвращает элемент в указанной позиции списка (№1 - последний элемент).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Возвращает элемент в указанной позиции списка (№1 - первый элемент).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Возвращает последний элемент списка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Возвращает случайный элемент списка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Удаляет и возвращает первый элемент списка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Удаляет и возвращает элемент в указанной позиции списка (№1 -  последний элемент).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Удаляет и возвращает элемент в указанной позиции списка (№1 - первый элемент).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Удаляет и возвращает последний элемент списка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Удаляет и возвращает случайный элемент списка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Удаляет первый элемент списка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Удаляет элемент в указанной позиции списка (№1 - последний элемент).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Удаляет элемент в указанной позиции списка (№1 - первый элемент).\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Удаляет последний элемент списка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Удаляет случайный элемент списка.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"по № с конца\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"по №\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"по последний\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"взять подсписок с первого\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"взять подсписок с № с конца\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"взять подсписок с №\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Создаёт копию указанной части списка.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"найти первое вхождение элемента\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"найти последнее вхождение элемента\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Возвращает номер позиции первого/последнего вхождения элемента в списке.  Возвращает 0, если текст не найден.\";\nBlockly.Msg.LISTS_INLIST = \"в списке\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 пуст\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"длина %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Возвращает длину списка.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"создать список из элемента %1, повторяющегося %2 раз\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Создаёт список, состоящий из заданного числа копий элемента.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"=\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"вставить в\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"присвоить\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Вставляет элемент в начало списка.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Вставляет элемент в указанной позиции списка (№1 - последний элемент).\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Вставляет элемент в указанной позиции списка (№1 - первый элемент).\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Добавляет элемент в конец списка.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Вставляет элемент в случайное место в списке.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Присваивает значение первому элементу списка.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Присваивает значение элементу в указанной позиции списка (№1 - последний элемент).\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Присваивает значение элементу в указанной позиции списка (№1 - первый элемент).\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Присваивает значение последнему элементу списка.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Присваивает значение случайному элементу списка.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Возвращает значение истина, если список пуст.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"ложь\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Возвращает значение истина или ложь.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"истина\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Возвращает значение истина, если вставки равны.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Возвращает значение истина, если первая вставка больше второй.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Возвращает значение истина, если первая вставка больше или равна  второй.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Возвращает значение истина, если первая вставка меньше второй.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Возвращает значение истина, если первая вставка меньше или равна  второй.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Возвращает значение истина, если вставки не равны.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"не %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Возвращает значение истина, если вставка ложна.  Возвращает значение ложь, если вставка истинна.\";\nBlockly.Msg.LOGIC_NULL = \"ничто\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Возвращает ничто.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"и\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"или\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Возвращает значение истина, если обе вставки истинны.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Возвращает значение истина, если хотя бы одна из вставок истинна.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"выбрать по\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://ru.wikipedia.org/wiki/Тернарная_условная_операция\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"если ложь\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"если истина\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Проверяет условие выбора. Если условие истинно, возвращает первое значение, в противном случае возвращает второе значение.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://ru.wikipedia.org/wiki/Арифметика\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Возвращает сумму двух чисел.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Возвращает частное от деления первого числа на второе.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Возвращает разность двух чисел.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Возвращает произведение двух чисел.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Возвращает первое число, возведённое в степень второго числа.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://ru.wikipedia.org/wiki/%D0%98%D0%B4%D0%B8%D0%BE%D0%BC%D0%B0_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29#.D0.98.D0.BD.D0.BA.D1.80.D0.B5.D0.BC.D0.B5.D0.BD.D1.82\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"на\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"увеличить\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Добавляет число к переменной '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://ru.wikipedia.org/wiki/Математическая_константа\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Возвращает одну из распространённых  констант: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) или ∞ (бесконечность).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"ограничить %1 снизу %2 сверху %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Ограничивает число нижней и верхней границами (включительно).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"делится на\";\nBlockly.Msg.MATH_IS_EVEN = \"чётное\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"отрицательное\";\nBlockly.Msg.MATH_IS_ODD = \"нечётное\";\nBlockly.Msg.MATH_IS_POSITIVE = \"положительное\";\nBlockly.Msg.MATH_IS_PRIME = \"простое\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Проверяет, является ли число чётным, нечётным, простым, целым, положительным, отрицательным или оно кратно определённому числу.  Возвращает значение истина или ложь.\";\nBlockly.Msg.MATH_IS_WHOLE = \"целое\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://ru.wikipedia.org/wiki/Деление_с_остатком\";\nBlockly.Msg.MATH_MODULO_TITLE = \"остаток от %1 : %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Возвращает остаток от деления двух чисел.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://ru.wikipedia.org/wiki/Число\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Число.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"среднее арифметическое списка\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"наибольшее в списке\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"медиана списка\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"наименьшее в списке\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"моды списка\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"случайный элемент списка\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"стандартное отклонение списка\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"сумма списка\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Возвращает среднее арифметическое списка.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Возвращает наибольшее число списка.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Возвращает медиану списка.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Возвращает наименьшее число списка.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Возвращает список наиболее часто встречающихся элементов списка.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Возвращает случайный элемент списка.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Возвращает стандартное отклонение списка.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Возвращает сумму всех чисел в списке.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"случайное число от 0 (включительно) до 1\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Возвращает случайное число от 0.0 (включительно) до 1.0.\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"случайное целое число от %1 для %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Возвращает случайное число между двумя заданными пределами (включая и их).\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://ru.wikipedia.org/wiki/Округление\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"округлить\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"округлить к меньшему\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"округлить к большему\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Округляет число до большего или меньшего.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://ru.wikipedia.org/wiki/Квадратный_корень\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"модуль\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"квадратный корень\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Возвращает модуль числа\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Возвращает е в указанной степени.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Возвращает натуральный логарифм числа.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Возвращает десятичный логарифм числа.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Возвращает противоположное число.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Возвращает 10 в указанной степени.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Возвращает квадратный корень числа.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://ru.wikipedia.org/wiki/Тригонометрические_функции\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Возвращает арккосинус (в градусах).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Возвращает арксинус (в градусах).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Возвращает арктангенс (в градусах)\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Возвращает косинус угла в градусах.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Возвращает синус угла в градусах.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Возвращает тангенс угла в градусах.\";\nBlockly.Msg.NEW_VARIABLE = \"Новая переменная…\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Имя новой переменной:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"с:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://ru.wikipedia.org/wiki/Функция_%28программирование%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Исполняет определённую пользователем процедуру '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://ru.wikipedia.org/wiki/Функция_%28программирование%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Исполняет определённую пользователем процедуру '%1' и возвращает вычисленное  значение.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Создать вызов '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"выполнить что-то\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"чтобы\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Создаёт процедуру, не возвращающую значение.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"вернуть\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Создаёт процедуру, возвращающую значение.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Предупреждение: эта функция имеет повторяющиеся параметры.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Выделить определение процедуры\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Если первое значение истинно, возвращает второе значение.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Предупреждение: Этот блок может использоваться только внутри определения функции.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"имя параметра:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"параметры\";\nBlockly.Msg.REMOVE_COMMENT = \"Удалить комментарий\";\nBlockly.Msg.RENAME_VARIABLE = \"Переименовать переменную…\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Переименовать все переменные '%1' в:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"добавить текст\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"к\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Добавить текст к переменной «%1».\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"в строчные буквы\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"в Заглавные Начальные Буквы\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"в ЗАГЛАВНЫЕ БУКВЫ\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Возвращает копию текста с ЗАГЛАВНЫМИ или строчными буквами.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"взять первую букву\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"взять букву № с конца\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"взять букву №\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"в тексте\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"взять последнюю букву\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"взять случайную букву\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Возвращает букву в указанной позиции.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Добавить элемент к тексту.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"соединить\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Добавьте, удалите, переставьте фрагменты для переделки текстового блока.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"по букву № с конца\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"по букву №\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"по последнюю букву\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"в тексте\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"взять подстроку с первой буквы\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"взять подстроку с буквы № с конца\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"взять подстроку с буквы №\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Возвращает указанную часть текста.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"в тексте\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"найти первое вхождение текста\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"найти последнее вхождение текста\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Возвращает номер позиции первого/последнего вхождения первого текста во  втором.  Возвращает 0, если текст не найден.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 пуст\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Возвращает значение истина, если предоставленный текст пуст.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"создать текст из\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Создаёт фрагмент текста, объединяя любое число элементов\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"длина %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Возвращает число символов (включая пробелы) в заданном тексте.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"напечатать %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Печатает текст, число или другой объект.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Запросить у пользователя число.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Запросить у пользователя текст.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"запросить число с подсказкой\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"запросить текст с подсказкой\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://ru.wikipedia.org/wiki/Строковый_тип\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Буква, слово или строка текста.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"обрезать пробелы с двух сторон\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"обрезать пробелы слева\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"обрезать пробелы справа\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Возвращает копию текста с пробелами, удалеными с одного или обоих концов.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"элемент\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Создать блок \\\"присвоить\\\" для %1\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Возвращает значение этой переменной.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Создать вставку %1\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"=\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"присвоить\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Присваивает переменной значение вставки.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/sq.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.sq');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Vendos nje Koment\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Ndrysho Vlerat:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Mbyll blloqet\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Mbyll bllokun\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"Ngjyra 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"Ngjyra 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"Perpjesetim\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"Përzierje\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Perzien dy ngjyra së bashku me një raport të dhënë (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"http://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Zgjidh nje ngjyre nga nje game ngjyrash.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"ngjyre e rastesishme\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Zgjidhni një ngjyrë në mënyrë të rastësishme.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blu\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"jeshile\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"e kuqe\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"ngjyre me\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Krijo një ngjyrë me shumën e specifikuar te te kuqes, te gjelbëres, dhe bluse. Te gjitha vlerat duhet te jene mes 0 dhe 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"dil nga nje faze perseritese\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"vazhdo me elementin tjeter te nje faze perseritese\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Ndahu nga unaza.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Kapërce pjesën e mbetur të unazës, dhe vazhdo me ripërsëritjen tjetër.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Paralajmërim: Ky bllok mund të përdoret vetëm brenda unazës.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"ne liste\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"per cdo produkt\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Per cdo produkt ne nje \\\"liste\\\" \\\"vendos\\\" ndryshoren '%1' produktit, dhe pastaj bej disa deklarata.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"nga '%1' ne '%2' me nga '%3'\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"numero me\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Bëje identifikuesin %1 që ta ketë vlerat prej numrit të fillimit deri tek numri i fundit, duke numëruar nga intervali i specifikuar, dhe ti bëj blloqet e specifikuara.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"\\\"Vendos\\\" \\\"kushtein\\\"tek \\\"pjesa\\\" \\\"if\\\"\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Shto një përfundues, që i mbërrin të gjitha kushtet në bllokun nëse.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këte bllok nëse.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"përndryshe\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"përndryshe nëse\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"nëse\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Nëse një vlerë është e saktë, atëherë ekzekuto disa fjali.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Nëse një vlerë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, ekzekuto bllokun e dytë të fjalive.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Nëse vlera e parë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, nëse vlera e dytë është e saktë, ekzekuto bllokun e dytë të fjalive.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Nëse vlera e parë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, nëse vlera e dytë është e saktë, ekzekuto bllokun e dytë të fjalive. Nëse asnjëra nga vlerat nuk është e saktë, ekzekuto bllokun e fundit të fjalive.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"http://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"ekzekuto\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"përsërit %1 herë\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"përsërit\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"herë\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Ekzekuto disa fjali disa herë.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"përsërit derisa\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"përsërit përderisa\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Përderisa një vlerë është e pasaktë, atëherë ekzekuto disa fjali.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Përderisa një vlerë është e saktë, atëherë ekzekuto disa fjali.\";\nBlockly.Msg.DELETE_BLOCK = \"Fshij bllokun\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Fshij %1 blloqe\";\nBlockly.Msg.DISABLE_BLOCK = \"Çaktivizo bllokun\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Kopjo\";\nBlockly.Msg.ENABLE_BLOCK = \"Aktivizo bllokun\";\nBlockly.Msg.EXPAND_ALL = \"Zmadho blloqet\";\nBlockly.Msg.EXPAND_BLOCK = \"Zmadho bllokun\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Hyrjet e jashtme\";\nBlockly.Msg.HELP = \"Ndihmë\";\nBlockly.Msg.INLINE_INPUTS = \"Hyrjet e brendshme\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"krijo një listë të zbrazët\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Kthen një listë, te gjatësisë 0, duke mos përmbajtur asnjë regjistrim të të dhënave\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"listë\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këtë bllok të listës.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"krijo listë me\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Shto një send në listë.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Krijo një listë me ndonjë numbër të sendeve.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"i parë\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# nga fundi\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"merr\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"merr dhe fshij\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"i fundit\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"i rastësishëm\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"largo\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Rikthen tek artikulli i par në list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Kthen një send në pozicionin e specifikuar në listë. #1 është sendi i fundit.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Kthen një send në pozicionin e specifikuar në listë. #1 është sendi i parë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Kthen artikullin e fundit në list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Kthen një send të rastësishëm në listë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Fshin dhe kthen sendin e parë në listë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Fshin dhe kthen sendin në pozicionin e specifikuar në listë. #1 është sendi i fundit.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Fshin dhe kthen sendin në pozicionin e specifikuar në listë. #1 është sendi i parë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Fshin dhe kthen sendin e fundit në listë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Fshin dhe kthen një send të rastësishëm në listë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Fshin sendin e parë në listë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Fshin sendin në pozicionin e specifikuar në listë. #1 është sendi i fundit.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Fshin sendin në pozicionin e specifikuar në listë. #1 është sendi i parë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Fshin sendin e fundit në listë.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Kthen një send të rastësishëm në listë.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"tek # nga fundi\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"tek #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"tek i fundit\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"merr nën-listën nga i pari\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"merr nën listën nga # nga fundi\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"merr nën-listën nga #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Krijon në kopje të pjesës së specifikuar të listës.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"gjen ndodhjen e parë të sendit\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"gjen ndodhjen e fundit të sendit\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Kthen indeksin e ndodhjes së parë/fudit të sendit në listë. Kthen 0 nëse teksti nuk është gjetur.\";\nBlockly.Msg.LISTS_INLIST = \"në listë\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 është e zbraztë\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"gjatësia e %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Kthen gjatësinë e listës.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"krijo listën me sendin %1 të përsëritur %2 herë\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Krijon në listë qe përmban vlerën e dhënë të përsëritur aq herë sa numri i specifikuar.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"sikurse\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"fut në\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"vendos\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Fut sendin në fillim të listës.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Fut sendin në pozicionin e specifikuar të listës. #1 është sendi i fundit.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Fut sendin në pozicionin e specifikuar të listës. #1 është sendi i parë.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Bashkangjit sendin në fund të listës.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Fut sendin rastësisht në listë.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Vendos sendin e parë në listë.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Vendos sendin ne pozicionin e specifikuar në listë. #1 është sendi i fundit.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Vendos sendin në pozicionin e specifikuar në listë. #1 është sendi i parë.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Vendos sendin e fundit në listë.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Vendos një send të rastësishëm në listë.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Kthehet i saktë nëse lista është e zbraztë.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"e pasaktë\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Kthehet ose të saktë ose të pasaktë.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"e saktë\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"http://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Ktheje të saktë nëse të dy hyrjet janë të barabarta me njëra-tjetrën.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Ktheje të saktë nëse hyrja e parë është më e madhe se hyrja e dytë.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Ktheje të saktë nëse hyrja e parë është më e madhe ose e barabartë me hyrjen e dytë.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Ktheje të saktë nëse hyrja e parë është më e vogël se hyrja e dytë.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Ktheje të saktë nëse hyrja e parë është më e vogël ose e barabartë me hyrjen e dytë.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Ktheje të saktë nëse të dy hyrjet nuk janë të barabarta me njëra-tjetrën.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"jo %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Kthehet e saktë nëse hyrja është e pasaktë. Kthehet e pasaktë nëse hyrja është e saktë.\";\nBlockly.Msg.LOGIC_NULL = \"pavlerë\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"http://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Kthehet e pavlerë.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"dhe\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"ose\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Kthehet të saktë nëse të dy hyrjet janë të sakta.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Kthehet e saktë nëse së paku njëra nga hyrjet është e saktë.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"http://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"nëse e pasaktë\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"nëse e saktë\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Kontrollo kushtin në 'test'. Nëse kushti është i saktë, kthen vlerën 'nëse e saktë'; përndryshe kthen vlerën 'nëse e pasaktë'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"http://sq.wikipedia.org/wiki/Aritmetika\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Kthen shumën e dy numrave.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Kthen herësin e dy numrave.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Kthen ndryshimin e dy numrave.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Kthen produktin e dy numrave.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Kthen numrin e parë të ngritur në fuqinë e numrit të dytë.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"nga\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"ndrysho\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Shto një numër në ndryshoren '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"http://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Kthen një nga konstantet e përbashkëta: : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infiniti).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"detyro %1 e ulët %2 e lartë %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Vëni një numër që të jetë në mes të kufive të specifikuara(përfshirëse).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"është i pjestueshme me\";\nBlockly.Msg.MATH_IS_EVEN = \"është çift\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"është negativ\";\nBlockly.Msg.MATH_IS_ODD = \"është tek\";\nBlockly.Msg.MATH_IS_POSITIVE = \"është pozitiv\";\nBlockly.Msg.MATH_IS_PRIME = \"është prim\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Kontrollo nëse një numër është çift, tek, prim, i plotë, pozitiv, negativ, ose nëse është i pjestueshëm me një numër të caktuar. Kthehet e saktë ose e pasaktë.\";\nBlockly.Msg.MATH_IS_WHOLE = \"është i plotë\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"http://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"mbetësi i %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Kthen mbetësin nga pjestimi i dy numrave.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"x\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"http://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Një numër.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"mesatarja e listës\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"numri më i madh i listës\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"mediana e listës\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"numri më i ulët i listës\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modat e listës\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"send i rastësishëm i listës\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"devijimi standard i listës\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"mbledhja e listës\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Kthen mesatarën (kuptimi aritmetik) i vlerave numerike të listës.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Kthe numrin më të madh të listës.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Kthe numrin median të listës.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Kthe numrin me të vogël të listës.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Kthe listën e sendit(eve) më të zakonshme të listës.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Kthe një element të rastësishëm nga lista.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Kthe devijimin standard të listës.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Kthe shumën e të gjithë numrave të listës.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"http://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"fraksioni i rastësishëm\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Kthe fraksionin e rastësishëm në mes të 0.0 (përfshirëse) dhe 1.0 (jopërfshirëse).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"http://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"numër i plotë i rastësishëm nga %1 deri në %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Kthe një numër të plotë të rastësishëm të dy kufijve të specifikuar, të përfshirë.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"http://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"rrumbullakësimi\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"rrumbullakësimi i ulët\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"rrumbullakësimi i lartë\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Rrumbullakësimi i numrit të lartë ose të ulët.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"http://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolut\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"rrënja katrore\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Kthen vlerën absolute të një numri.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Kthen e në fuqinë e një numri.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Kthen logaritmën natyrale të një numri.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Kthen 10 logaritmet bazë të një numri.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Kthe negacionin e një numri.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Kthen 10 në fuqinë e një numri.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Kthen rrënjën katrore të një numri.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acosinus\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asinus\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atangjentë\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"http://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Rikthe cos-1 e nje numeri.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Rikthe sin-1 e nje numeri.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Kthe tg-1 e nje numeri.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Kthe kosinusin e nje grade (jo ne radiant).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Kthe kosinusin e nje kendi (jo ne radiant).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Kthe tangentin e nje kendi (jo radiant).\";\nBlockly.Msg.NEW_VARIABLE = \"Identifikatorë i ri...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Emri i identifikatorit të ri:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"me:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Lësho funksionin e definuar nga përdoruesi '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Lëho funksionin e definuar nga përdoruesi '%1' dhe përdor daljen e tij.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Krijo '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"bëj diqka\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"te\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Krijon një funksion pa dalje.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"rikthe\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Krijon një funksion me një dalje.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Paralajmërim: Ky funksion ka parametra të dyfishuar.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Thekso definicionin e funksionit\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Nëse një vlerë është e saktë, atëherë kthe një vlerë të dytë.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Paralajmërim: Ky bllok mund të përdoret vetëm brenda definicionit të funksionit.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"Fut emrin:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"Informacioni i futur\";\nBlockly.Msg.REMOVE_COMMENT = \"Fshij komentin\";\nBlockly.Msg.RENAME_VARIABLE = \"Ndrysho emrin variables...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Ndrysho emrin e te gjitha '%1' variablave ne :\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"shto tekst\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"ne\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"shto tekst tek varibla '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"me shkronja te vogla shtypi\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"Fillimi me shkronje te madhe shtypi\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"me shkronja te medha shtypi\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Kthe nje kopje te tekstit ne nje rast te ndryshem.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"merr shkronjen e pare\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"merr shkronjen # nga fundi\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"merr shkronjen #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"ne tekst\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"merr shkronjen e fundit\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"merr nje shkronje te rastesishme\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Kthe nje shkronje nga nje pozicion i caktuar.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Shto nje gje ne tekst\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"bashkangjit\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këtë bllok teksti.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"ne shkronjen # nga fundi\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"ne shkronjen #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"tek shkronja e fundit\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"ne tekst\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"merr vlerat qe vazhdojne me shkronjen e pare\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"merr nenvargun nga shkronja # nga fundi\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"Merr nenvargun nga shkronja #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Pergjigjet me nje pjese te caktuar teksti.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"ne tekst\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"gjej rastisjen e pare te tekstit\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"gjej rastisjen e fundit te tekstit\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Pergjigjet me indeksin e pare/fundit te rastisjes se tekstit te pare ne tekstin e dyte. Pergjigjet me 0 ne qofte se teksti nuk u gjet.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 eshte bosh\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Kthehet e vertete neqoftese teksti i dhene eshte bosh.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"krijo tekst me\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Krijo nje pjese te tekstit duke bashkuar se bashku disa sende\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"gjatesi %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Pergjigjet me nje numer shkronjash (duke perfshire hapesire) ne tekstin e dhene.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"printo %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Printo tekstin e caktuar, numer ose vlere tjeter.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Kerkoji perdoruesit nje numer.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Kerkoji perdoruesit ca tekst.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"kerko nje numer me njoftim\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"kerko tekst me njoftim\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"http://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Nje shkronje, fjale, ose rresht teksti.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"prit hapesirat nga te dyja anet\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"prit hapesirat nga ana e majte\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"prit hapesirat nga ana e djathte\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Pergjigju me nje kopje te tekstit me hapesira te fshira nga njera ane ose te dyja anet.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"send\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Krijo 'vendos %1\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Pergjigjet me nje vlere te kesaj variable.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Krijo 'merr %1\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"ne\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"vendos\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Vendos kete variable te jete e barabarte me te dhenat ne hyrje.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/sr.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.sr');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Додај Коментар\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Промени вредност:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Скупи Блокове\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Скупи Блок\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"Боја 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"Боја 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"Коефициент\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"Помешати\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Помешати две боје заједно са датим односом (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Изаберите боју са палете.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"насумична боја\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Изаберите боју насумице.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"плава\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"зелена\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"црвена\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"обоји са\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Креирај боју са одређеном количином црвене,зелене, и плаве. Све вредности морају бити између 0 и 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"Изађите из петље\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"настави са следећом итерацијом петље\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Напусти садржај петље.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Прескочи остатак ове петље, и настави са следећом итерацијом(понављанјем).\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Упозорење: Овај блок може да се употреби само унутар петље.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"у листи\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"за сваку ставку\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"За сваку ставку унутар листе, подеси промењиву '%1' по ставци, и онда начини неке изјаве-наредбе.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"од %1 до %2 од %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"преброј са\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Имај промењиву %1 узми вредности од почетног броја до задњег броја, бројећи по одређеном интервалу, и изврши одређене блокове.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Додај услов иф блоку.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Додај коначни, catch-all  (ухвати све) услове иф блока.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Додај, уклони, или преуреди делове како бих реконфигурисали овај иф блок.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"друго (у другом случају)\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"друго ако\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"ако\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"ако је вредност тачна, онда изврши неке наредбе-изјаве.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"ако је вредност тачна, онда изврши први блок наредби, У супротном, изврши други блок наредби.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Ако је прва вредност тачна, онда изврши први блок наредби, у супротном, ако је друга вредност тачна , изврши други блок наредби.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Ако је прва вредност тачна, онда изврши први блок наредби, у супротном, ако је друга вредност тачна , изврши други блок наредби. Ако ни једна од вредности није тачна, изврши последнји блок наредби.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"урадите\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"поновите %1 пута\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"поновите\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"пута\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Одрадити неке наредбе неколико пута.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"понављати до\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"понављати док\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Док вредност није тачна, онда извршити неке наредбе.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Док је вредност тачна, онда извршите неке наредбе.\";\nBlockly.Msg.DELETE_BLOCK = \"Избриши Блок\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Избриши %1 Блокова\";\nBlockly.Msg.DISABLE_BLOCK = \"Онеспособи Блок\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Дуплирај\";\nBlockly.Msg.ENABLE_BLOCK = \"Оспособи Блок\";\nBlockly.Msg.EXPAND_ALL = \"Прошири Блокове\";\nBlockly.Msg.EXPAND_BLOCK = \"Прошири Блок\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Спољашњи Уноси\";\nBlockly.Msg.HELP = \"Помоћ\";\nBlockly.Msg.INLINE_INPUTS = \"Линијски Уноси\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"креирај празну листу\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"враћа листу, дужине 0, не садржавајући  евиденцију података\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"листа\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Додајте, избришите, или преуредите делове како би се реорганизовали овај блок листе.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"креирај листу са\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Додај ставку листи.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Креирај листу са било којим бројем ставки.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"први\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# од краја\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"узми\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"узми и уклони\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"последњи\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"насумичан\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"уклони\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Враћа прву ставку на листи.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Враћа ставку на одређену позицију на листи. #1 је последња ставка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Враћа ставку на одређену позицију на листи. #1 је прва ставка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Враћа последњу ставку у листи.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Враћа ставку из листе случајним одабиром.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Укланја и враћа прву ставку са листе.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Укланја и враћа ставку са одређене позиције са листе.#1 је последнја ставка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Укланја и враћа ставку са одређене позиције са листе.#1 је прва ставка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Укланја и враћа последнју ставку са листе.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Укланја и враћа насумићно одабрану ставку са листе.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Уклања прву ставку на листи.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Укланја ставку са одређене позиције на листи.#1 је последнја ставка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Укланја ставку са одређене позиције на листи.#1 је прва ставка.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Уклања последнју ставку са листе.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Уклања насумичну ставку на листи.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"до # од краја\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"до #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"до последњег\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"узмите под-листу од прве-ог\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"узми под-листу од # од краја\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"узми под листу од #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Прави копију одређеног дела листе.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"наћи прво појавлјиванје ставке\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"наћи последнје појавлјиванје ставке\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Враћа однос првог/последнјег појавлјиванја ставке у листи. Враћа 0 ако се текст не наће.\";\nBlockly.Msg.LISTS_INLIST = \"у листи\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 је празан\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"дужина од %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Враћа дужину листе.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"Направити листу са ставком %1 која се понавлја %2 пута\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Прави листу која се састоји од задане вредности коју понавлјамо одређени број шута.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"као\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"Убацити у\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"поставити\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Убацује ставку на почетак листе.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Убацује ставку на одређену позицију на листи.#1 је последнја ставка.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Убацује ставку на одређену позицију на листи.#1 је прва ставка.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Вратити ставку на крај листе.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Убацује ставку на насумићно место на листи.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"подешава прву ставку у листи.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Убацује ставку на одређену позицију на листи.#1 је последња ставка.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Убацује ставку на одређену позицију на листи.#1 је прва ставка.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Убацује последњу ставку у листи.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Убацује-Подешава насумичну ставку на листи.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Враћа вредност тачно ако је листа празна.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"нетачно\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"враћа вредност или тачно или нетачно.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"тачно\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://sr.wikipedia.org/wiki/Неједнакост\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"враћа вредност тачно ако су оба уноса једнака један другом.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Враћа за вредност тачно ако је први унос већи од другог уноса.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"враћа за вредност тачно ако је први унос већи или једнак другом уносу.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Враћа за вредност тачно ако је први унос мањи од другог уноса.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"враћа за вредност тачно ако је први унос мањи или једнак другом уносу.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"враћа за вредност тачно ако су оба уноса различита.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"није %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Враћа за вредност тачно ако је унос нетачан. Враћа за вредност нетачно ако је унос тачан.\";\nBlockly.Msg.LOGIC_NULL = \"НИШТА\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Враћа нулу.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"И\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"или\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Враћа за вредност тачно ако су оба уноса тачна.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"враћа за вредност тачно ако је бар један од уноса тачан.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"тест\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"ако је нетачно\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"ако је тачно\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Провери услов у 'test'. Ако је услов тачан, тада враћа 'if true' вредност; у другом случају враћа 'if false' вредност.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Вратите збир два броја.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Вратите количник два броја.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Вратите разлику два броја.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Вратите производ два броја.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Вратите први број подигнут на власт другог броја.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"по, за, од\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"промени\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"додај број промењивој '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"врати једну од заједничких константи: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), или ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"Ограничи %1 ниско %2 високо %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Ограничити број  да буде између одређених ограниченја (закључно).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"Је дељиво са\";\nBlockly.Msg.MATH_IS_EVEN = \"је једнако\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"је негативно\";\nBlockly.Msg.MATH_IS_ODD = \"је непарно\";\nBlockly.Msg.MATH_IS_POSITIVE = \"је позитивно\";\nBlockly.Msg.MATH_IS_PRIME = \"је прост\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Провјерава да ли је број паран, непаран, прост, цио, позитиван, негативан, или да ли је делјив са одређеним бројем. Враћа тачно или нетачно.\";\nBlockly.Msg.MATH_IS_WHOLE = \"цео је\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"подсетник од %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Вратити подсетник од дељења два броја.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Неки број.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"просечни са листе\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"Максимални са листе\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"са средине листе\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"минимални са листе\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"облици листе\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"Насумична ставка са листе\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"стандардна девиација листе\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"збир листе\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Враћа просјечну (аритметичку средину) нумеричких вредности са листе.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Враћа највећи број са листе.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Враћа среднји број са листе.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Враћа најманји број са листе.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Враћа најчешћу ставку(е) са листе.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Враћа насумично одабрани елемент са листе.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Враћа стандардну девијацију листе.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Враћа суму свих бројева са листе.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"Насумична функција\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Враћа насумучно одабран дио између 0.0 (уклјучиво) и 1.0 (исклјучиво).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"сличајно одабрани цијели број од %1 до %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Враћа случајно одабрани цели број између две одређене границе, уклјучиво.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"Заокружити\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"Заокружити испод\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"Заокружити изнад\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Заокружити број изнад или испод.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"апсолутан\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"квадратни корен\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Вратите апсолутну вредност броја.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"вратити е на власти броја.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Вратити природни логаритам броја.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Враћа логаритам са базом 10 броја.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Враћа негативну вредност броја.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Враћа 10-ти степен броја.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Вратити квадратни корен броја.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"арц цос\";\nBlockly.Msg.MATH_TRIG_ASIN = \"арц син\";\nBlockly.Msg.MATH_TRIG_ATAN = \"арц тан\";\nBlockly.Msg.MATH_TRIG_COS = \"цос\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"син\";\nBlockly.Msg.MATH_TRIG_TAN = \"тан\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Вратити аркус косинуса броја.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Вратите аркус  броја.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Вратите аркус тангенс броја.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Вратите косинус степена (не радијан).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Вратите синус степена (не радијан).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Вратите тангенс степена (не радијан).\";\nBlockly.Msg.NEW_VARIABLE = \"Нова промењјива...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Име нове промењиве:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"са:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Извршити функцију  '%1' коју корисник дефинира.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Извршити функцију  '%1' коју корисник дефинира и користи резултат.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Израчунати '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"урадити нешто\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"како би\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Прави функцију без избациванја излазне вредности.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"Вратити\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Прави функцију са избациванјем излазне вредности.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Упозоренје: ова функција има дупле параметре.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Истакнути дефиницију функције\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Ако је вредност тачна, врати другу вредност.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Упозоренје: овај се блок може користити једино ако постоји дефиниција функције.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"Назив улазне вредности:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"улазне вредности\";\nBlockly.Msg.REMOVE_COMMENT = \"Уклонити коментар\";\nBlockly.Msg.RENAME_VARIABLE = \"Преименовати варијаблу...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Преименовати све '%1' варијабле у:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"закачити текст\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"како би\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"додати неки текст варијабли  '%1.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"малим словима\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"свака реч починје великим словом\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"великим словима\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Враћа копију текста у другачијем случају.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"добити прво слово\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"добити сливо # са краја\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"добити слово #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"у тексту\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"Узми заднје слово\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"насумично одабери слово\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Враћа слово на одређену позицију.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Додати ставку у текст.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"придружити се\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Додај, уклони, или другачије поредај одјелке како би изнова поставили овај текст блок.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"слову # са краја\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"слову #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"заднјем слову\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"у тексту\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"узмите низ од првог слова\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"узмите низ од слова # од краја\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"узмите низ од слова #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Враћа одређен дио текста.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"у тексту\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"нађи прво појавлјиванје текста\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"нађи заднје појавлјиванје текста\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Враћа однос првог/заднјег појавлјиванја текста у другом тексту. Врађа 0 ако текст није пронађен.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 је празно\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Враћа тачно ако је доставлјени текст празан.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"написати текст са\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Направити дио текста спајајући различите ставке.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"дужина %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Враћа број слова (уклјучујући размаке) у датом тексту.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"принатати %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Принтати одређени текст, број друге вредности.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Питај корисника за број.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Питај корисника да ти да нешто текста.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"тражити број са поруком\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"тражити текст са поруком\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Слово, реч, линија текста.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"скратити простор са обе стране\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"скратити простор са леве стране\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"скратити простор са десне стране\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Враћа копију текста са уклонјеним простором са једног од два краја.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"ставка\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Направити сет %1\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Враћа вриједност варијабле.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Креирај добити %1\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"како би\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"поставити\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Чини да варијабла буде једнака уносу.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/sv.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.sv');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Lägg till kommentar\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Ändra värde:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Fäll ihop block\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Fäll ihop block\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"färg 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"färg 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"förhållande\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"blanda\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Blandar ihop två färger med ett bestämt förhållande (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://sv.wikipedia.org/wiki/Färg\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Välj en färg från paletten.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"slumpfärg\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Välj en slumpartad färg.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"blå\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"grön\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"röd\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"färg med\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Skapa en färg med det angivna mängden röd, grön och blå. Alla värden måste vara mellan 0 och 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"bryt ut ur upprepning\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"fortsätta med nästa upprepning av loop\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Bryta ut ur den innehållande upprepningen.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Hoppa över resten av denna upprepning och fortsätt med nästa upprepning.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Varning: Detta block kan endast användas i en upprepning.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each för \\\"varje\\\"-block\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"i listan\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"för varje föremål\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"För varje objekt i en lista, ange variabeln '%1' till objektet, och utför sedan några kommandon.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"från %1 till %2 med %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"räkna med\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Låt variabeln %1 ta värden från starttalet till sluttalet, beräknat med det angivna intervallet, och utför de angivna blocken.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Lägg till ett villkor blocket \\\"om\\\".\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Lägg till ett sista villkor som täcker alla alternativ som är kvar för \\\"if\\\"-blocket.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Lägg till, ta bort eller ändra ordningen för sektioner för att omkonfigurera blocket \\\"om\\\".\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"annars\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"annars om\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"om\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Om ett värde är sant, utför några kommandon.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Om värdet är sant, utför det första kommandoblocket. Annars utför det andra kommandoblocket.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Om det första värdet är sant, utför det första kommandoblocket. Annars, om det andra värdet är sant, utför det andra kommandoblocket.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Om det första värdet är sant, utför det första kommandoblocket. Annars, om det andra värdet är sant, utför det andra kommandoblocket. Om ingen av värdena är sanna, utför det sista kommandoblocket.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"utför\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"upprepa %1 gånger\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"upprepa\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"gånger\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Utför några kommandon flera gånger.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"upprepa tills\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"upprepa medan\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Medan ett värde är falskt, utför några kommandon.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Medan ett värde är sant, utför några kommandon.\";\nBlockly.Msg.DELETE_BLOCK = \"Radera block\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Radera %1 block\";\nBlockly.Msg.DISABLE_BLOCK = \"Inaktivera block\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Duplicera\";\nBlockly.Msg.ENABLE_BLOCK = \"Aktivera block\";\nBlockly.Msg.EXPAND_ALL = \"Expandera block\";\nBlockly.Msg.EXPAND_BLOCK = \"Expandera block\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Externa inmatningar\";\nBlockly.Msg.HELP = \"Hjälp\";\nBlockly.Msg.INLINE_INPUTS = \"radinmatning\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"skapa tom lista\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Ger tillbaka en lista utan någon data, alltså med längden 0\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"lista\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Lägg till, ta bort eller ändra ordningen på objekten för att göra om det här \\\"list\\\"-blocket.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"skapa lista med\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Lägg till ett föremål till listan.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Skapa en lista med valfritt antal föremål.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"första\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# från slutet\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"hämta\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"hämta och ta bort\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"sista\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"slumpad\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"ta bort\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Returnerar det första objektet i en lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Ger tillbaka objektet på den efterfrågade positionen i en lista. #1 är det sista objektet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Ger tillbaka objektet på den efterfrågade positionen i en lista. #1 är det första objektet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Returnerar det sista objektet i en lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Returnerar ett slumpmässigt objekt i en lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Tar bort och återställer det första objektet i en lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Tar bort och återställer objektet på den specificerade positionen i en lista. #1 är det sista objektet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Tar bort och återställer objektet på den specificerade positionen i en lista. #1 är det första objektet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Tar bort och återställer det sista objektet i en lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Tar bort och återställer ett slumpmässigt objekt i en lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Tar bort det första objektet i en lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Tar bort objektet på den efterfrågade positionen i en lista. #1 är det sista objektet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Tar bort objektet på den specificerade positionen i en lista. #1 är det första objektet.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Tar bort det sista objektet i en lista.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Tar bort en slumpmässig post i en lista.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"till # från slutet\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"till #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"till sista\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"få underlista från första\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"få underlista från # från slutet\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"få underlista från #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Skapar en kopia av den specificerade delen av en lista.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"hitta första förekomsten av objektet\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"hitta sista förekomsten av objektet\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Ger tillbaka den första/sista förekomsten av objektet i listan. Ger tillbaka 0 om texten inte hittas.\";\nBlockly.Msg.LISTS_INLIST = \"i listan\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 är tom\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"längden på %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Returnerar längden på en lista.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"skapa lista med föremålet %1 upprepat %2 gånger\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Skapar en lista som innehåller ett valt värde upprepat ett bestämt antalet gånger.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"som\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"Sätt in vid\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"ange\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"sätter in objektet i början av en lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"sätter in objektet vid en specificerad position i en lista. #1 är det sista objektet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Sätter in objektet vid en specificerad position i en lista. #1 är det första objektet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Lägg till objektet i slutet av en lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"sätter in objektet på en slumpad position i en lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Anger det första objektet i en lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Sätter in objektet vid en specificerad position i en lista. #1 är det sista objektet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Sätter in objektet vid en specificerad position i en lista. #1 är det första objektet.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Anger det sista elementet i en lista.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Sätter in ett slumpat objekt i en lista.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Returnerar sant om listan är tom.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"falskt\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Returnerar antingen sant eller falskt.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"sant\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://sv.wikipedia.org/wiki/Olikhet\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Ger tillbaka sant om båda värdena är lika med varandra.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Ger tillbaka sant om den första värdet är större än det andra.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Ger tillbaka sant om den första värdet är större än eller lika med det andra.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Ger tillbaka sant om den första värdet är mindre än det andra.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Ger tillbaka sant om den första värdet är mindre än eller lika med det andra.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Ger tillbaka sant om båda värdena inte är lika med varandra.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"inte %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Ger tillbaka sant om inmatningen är falsk. Ger tillbaka falskt och inmatningen är sann.\";\nBlockly.Msg.LOGIC_NULL = \"null\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://sv.wikipedia.org/wiki/Null\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returnerar null.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"och\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"eller\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Ger tillbaka sant om båda värdena är sanna.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Ger tillbaka sant om minst ett av värdena är sant.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"om falskt\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"om sant\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Kontrollera villkoret i \\\"test\\\". Om villkoret är sant, ge tillbaka \\\"om sant\\\"-värdet; annars ge tillbaka \\\"om falskt\\\"-värdet.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://sv.wikipedia.org/wiki/Aritmetik\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Returnerar summan av de två talen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Returnerar kvoten av de två talen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Returnerar differensen mellan de två talen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Returnerar produkten av de två talen.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Ger tillbaka det första talet upphöjt till det andra talet.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"med\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"ändra\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Lägg till ett tal till variabeln '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://sv.wikipedia.org/wiki/Matematisk_konstant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Returnerar en av de vanliga konstanterna: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) eller ∞ (oändligt).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"begränsa %1 till mellan %2 och %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Begränsa ett tal till att mellan de angivna gränsvärden (inklusive).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"är delbart med\";\nBlockly.Msg.MATH_IS_EVEN = \"är jämnt\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"är negativt\";\nBlockly.Msg.MATH_IS_ODD = \"är ojämnt\";\nBlockly.Msg.MATH_IS_POSITIVE = \"är positivt\";\nBlockly.Msg.MATH_IS_PRIME = \"är ett primtal\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Kontrollera om ett tal är jämnt, ojämnt, helt, positivt, negativt eller det är delbart med ett bestämt tal. Returnerar med sant eller falskt.\";\nBlockly.Msg.MATH_IS_WHOLE = \"är helt\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"resten av %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Returnerar kvoten från divisionen av de två talen.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://sv.wikipedia.org/wiki/Tal\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Ett tal.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"medelvärdet av listan\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"högsta talet i listan\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"medianen av listan\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"minsta talet i listan\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"typvärdet i listan\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"slumpmässigt objekt i listan\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standardavvikelsen i listan\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"summan av listan\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Ger tillbaka medelvärdet (aritmetiskt) av de numeriska värdena i listan.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Ger tillbaka det största talet i listan.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Returnerar medianen av talen i listan.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Ger tillbaka det minsta talet i listan.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Ger tillbaka en lista med de(t) vanligaste objekte(t/n) i listan.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Returnerar ett slumpmässigt element från listan.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Ger tillbaka standardavvikelsen i listan.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Ger tillbaka summan av alla talen i listan.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://sv.wikipedia.org/wiki/Slumptalsgenerator\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"slumpat decimaltal\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Ger tillbaka ett slumpat decimaltal mellan 0.0 (inkluderat) och 1.0 (exkluderat).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://sv.wikipedia.org/wiki/Slumptalsgenerator\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"slumpartat heltal från %1 till %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Ger tillbaka ett slumpat heltal mellan två värden (inklusive).\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://sv.wikipedia.org/wiki/Avrundning\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"avrunda\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"avrunda nedåt\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"avrunda uppåt\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Avrunda ett tal uppåt eller nedåt.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://sv.wikipedia.org/wiki/Kvadratrot\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolut\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"kvadratrot\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Returnerar absolutvärdet av ett tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Ger tillbaka e upphöjt i ett tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Returnera den naturliga logaritmen av ett tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Returnerar logaritmen för bas 10 av ett tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Returnerar negationen av ett tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Ger tillbaka 10 upphöjt i ett tal.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Returnerar kvadratroten av ett tal.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"arccos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"arcsin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"arctan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://sv.wikipedia.org/wiki/Trigonometrisk_funktion\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Ger tillbaka arcus cosinus (arccos) för ett tal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Ger tillbaka arcus sinus (arcsin) för ett tal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Ger tillbaka arcus tangens (arctan) av ett tal.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Ger tillbaka cosinus för en grad (inte radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Ger tillbaka sinus för en grad (inte radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Ger tillbaka tangens för en grad (inte radian).\";\nBlockly.Msg.NEW_VARIABLE = \"Ny variabel...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Nytt variabelnamn:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"med:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://sv.wikipedia.org/wiki/Funktion_%28programmering%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Kör den användardefinierade funktionen \\\"%1\\\".\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://sv.wikipedia.org/wiki/Funktion_%28programmering%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Kör den användardefinierade funktionen \\\"%1\\\" och använd resultatet av den.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Skapa '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://sv.wikipedia.org/wiki/Funktion_%28programmering%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"göra något\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"för att\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Skapar en funktion utan output.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://sv.wikipedia.org/wiki/Funktion_%28programmering%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"returnera\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Skapar en funktion med output.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Varning: Denna funktion har dubbla parametrar.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Markera funktionsdefinition\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Om ett värde är sant returneras ett andra värde.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Varning: Detta block får användas endast i en funktionsdefinition.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"inmatningsnamn:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"inmatningar\";\nBlockly.Msg.REMOVE_COMMENT = \"Radera kommentar\";\nBlockly.Msg.RENAME_VARIABLE = \"Byt namn på variabel...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Byt namn på alla variablerna '%1' till:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"lägg till text\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"till\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Lägg till lite text till variabeln '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"till gemener\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"till Versala Initialer\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"till VERSALER\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Returnerar en kopia av texten i ett annat skiftläge.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"hämta första bokstaven\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"hämta bokstaven # från slutet\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"hämta bokstaven #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"i texten\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"hämta sista bokstaven\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"hämta slumpad bokstav\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Ger tillbaka bokstaven på den specificerade positionen.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Lägg till ett föremål till texten.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"sammanfoga\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Lägg till, ta bort eller ändra ordningen för sektioner för att omkonfigurera detta textblock.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"till bokstav # från slutet\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"till bokstav #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"till sista bokstaven\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"i texten\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"få textdel från första bokstaven\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"få textdel från bokstav # från slutet\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"få textdel från bokstav #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Ger tillbaka en viss del av texten.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"i texten\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"hitta första förekomsten av texten\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"hitta sista förekomsten av texten\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Ger tillbaka indexet för den första/sista förekomsten av första texten i den andra texten.  Ger tillbaka 0 om texten inte hittas.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 är tom\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returnerar sant om den angivna texten är tom.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"skapa text med\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Skapa en textbit genom att sammanfoga ett valfritt antal föremål.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"längden på %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Ger tillbaka antalet bokstäver (inklusive mellanslag) i den angivna texten.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"skriv %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Skriv den angivna texten, talet eller annat värde.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Fråga användaren efter ett tal.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Fråga användaren efter lite text.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"fråga efter ett tal med meddelande\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"fråga efter text med meddelande\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://sv.wikipedia.org/wiki/Str%C3%A4ng_%28data%29\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"En bokstav, ord eller textrad.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"ta bort mellanrum från båda sidorna av\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"ta bort mellanrum från vänstra sidan av\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"ta bort mellanrum från högra sidan av\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Returnerar en kopia av texten med borttagna mellanrum från en eller båda ändar.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"föremål\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Skapa \\\"välj %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returnerar värdet av denna variabel.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Skapa 'hämta %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"till\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"välj\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Gör så att den här variabeln blir lika med inputen.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/th.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.th');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"ใส่คำอธิบาย\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"เปลี่ยนค่า:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"ย่อบล็อก\";\nBlockly.Msg.COLLAPSE_BLOCK = \"ย่อบล็อก\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"สีที่ 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"สีที่ 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"อัตราส่วน\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"ผสม\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"ผสมสีทั้งสองเข้าด้วยกันด้วยอัตราส่วน (0.0 - 1.0)\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://th.wikipedia.org/wiki/สี\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"เลือกสีจากจานสี\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"สุ่มสี\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"เลือกสีแบบสุ่ม\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"ค่าสีน้ำเงิน\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"ค่าสีเขียว\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"ค่าสีแดง\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"สีที่ประกอบด้วย\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"สร้างสีด้วยการกำหนดค่าของสีแดง เขียว และน้ำเงิน โดยต้องเป็นค่าระหว่าง 0 จนถึง 100\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"ออกจากการวนซ้ำ\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"เริ่มการวนซ้ำรอบต่อไป\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"ออกจากการวนซ้ำที่มีอยู่\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"ข้ามสิ่งที่เหลืออยู่ และไปเริ่มวนซ้ำรอบต่อไปทันที\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"ระวัง: บล็อกชนิดนี้สามารถใช้งานได้เมื่ออยู่ภายในการวนซ้ำเท่านั้น\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"ในรายการ\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"วนซ้ำทุกรายการ\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"ทำซ้ำทุกรายการ กำหนดค่าตัวแปร \\\"%1\\\" ตามรายการ และทำตามคำสั่งที่กำหนดไว้\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"จาก %1 จนถึง %2 เปลี่ยนค่าทีละ %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"นับ\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"ตัวแปร \\\"%1\\\" จะมีค่าตั้งแต่จำนวนเริ่มต้น ไปจนถึงจำนวนสิ้นสุด โดยมีการเปลี่ยนแปลงตามจำนวนที่กำหนด\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"กำหนดเงื่อนไขของบล็อก \\\"ถ้า\\\"\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"เพิ่มสิ่งสุดท้าย ที่จะตรวจจับความเป็นไปได้ทั้งหมดของบล็อก \\\"ถ้า\\\"\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"เพิ่ม ลบ หรือจัดเรียงบล็อก \\\"ถ้า\\\" นี้ใหม่\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"นอกเหนือจากนี้\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"นอกเหนือจากนี้ ถ้า\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"ถ้า\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"ว่าเงื่อนไขเป็นจริง ก็จะ \\\"ทำ\\\" ตามที่กำหนด\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"ถ้าเงื่อนไขเป็นจริง ก็จะ \\\"ทำ\\\" ตามที่กำหนด แต่ถ้าเงื่อนไขเป็นเท็จก็จะทำ \\\"นอกเหนือจากนี้\\\"\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"ถ้าเงื่อนไขแรกเป็นจริง ก็จะทำตามคำสั่งในบล็อกแรก แต่ถ้าไม่ก็จะไปตรวจเงื่อนไขที่สอง ถ้าเงื่อนไขที่สองเป็นจริง ก็จะทำตามเงื่อนไขในบล็อกที่สองนี้\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"ถ้าเงื่อนไขแรกเป็นจริง ก็จะทำคำสั่งในบล็อกแรก จากนั้นจะข้ามคำสั่งในบล็อกที่เหลือ แต่ถ้าเงื่อนไขแรกเป็นเท็จ ก็จะทำการตรวจเงื่อนไขที่สอง ถ้าเงื่อนไขที่สองเป็นจริง ก็จะทำตามคำสั่งในบล็อกที่สอง จากนั้นจะข้ามคำสั่งในบล็อกที่เหลือ แต่ถ้าทั้งเงื่อนไขแรกและเงื่อนไขที่สองเป็นเท็จทั้งหมด ก็จะมาทำบล็อกที่สาม\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"ทำ:\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"ทำซ้ำ %1 ครั้ง\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"ทำซ้ำ\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"ครั้ง\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"ทำซ้ำคำสั่งตามจำนวนครั้งที่กำหนด\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"ทำซ้ำ จนกว่าจะ\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"ทำซ้ำ ตราบใดที่\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"ถ้าเงื่อนไขเป็นเท็จ ก็จะทำตามคำสั่งที่กำหนด\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"ถ้าเงื่อนไขเป็นจริง ก็จะทำตามคำสั่งที่กำหนด\";\nBlockly.Msg.DELETE_BLOCK = \"ลบบล็อก\";\nBlockly.Msg.DELETE_X_BLOCKS = \"ลบ %1 บล็อก\";\nBlockly.Msg.DISABLE_BLOCK = \"ปิดการทำงานของบล็อกนี้\";\nBlockly.Msg.DUPLICATE_BLOCK = \"สร้างซ้ำ\";\nBlockly.Msg.ENABLE_BLOCK = \"เปิดการทำงานของบล็อกนี้\";\nBlockly.Msg.EXPAND_ALL = \"ขยายบล็อก\";\nBlockly.Msg.EXPAND_BLOCK = \"ขยายบล็อก\";\nBlockly.Msg.EXTERNAL_INPUTS = \"อินพุตภายนอก\";\nBlockly.Msg.HELP = \"ช่วยเหลือ\";\nBlockly.Msg.INLINE_INPUTS = \"อินพุตแบบอินไลน์\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"สร้างรายการเปล่า\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"สร้างรายการเปล่า (ความยาวเป็น 0) ยังไม่มีข้อมูลใดๆ อยู่\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"รายการ\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"เพิ่ม ลบ หรือจัดเรียงบล็อกรายการนี้ใหม่\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"สร้างข้อความด้วย\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"เพิ่มไอเท็มเข้าไปในรายการ\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"สร้างรายการพร้อมด้วยไอเท็ม\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"แรกสุด\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# จากท้าย\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"เรียกดู\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"เรียกดูและเอาออก\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"ท้ายสุด\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"สุ่ม\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"เอาออก\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"คืนค่าไอเท็มอันแรกในรายการ\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ #1 คือไอเท็มอันท้ายสุด\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ #1 คือไอเท็มอันแรกสุด\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"คืนค่าไอเท็มอันสุดท้ายในรายการ\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"คืนค่าไอเท็มแบบสุ่มจากรายการ\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"เอาออก และคืนค่าไอเท็มอันแรกในรายการ\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"เอาออก และคืนค่าไอเท็มในตำแหน่งที่ระบุจากรายการ #1 คือไอเท็มอันสุดท้าย\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"เอาออก และคืนค่าไอเท็มในตำแหน่งที่ระบุจากรายการ #1 คือไอเท็มอันแรก\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"เอาออก และคืนค่าไอเท็มอันสุดท้ายในรายการ\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"เอาออก และคืนค่าไอเท็มแบบสุ่มจากรายการ\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"เอาไอเท็มแรกสุดในรายการออก\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ #1 คือไอเท็มอันท้ายสุด\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ #1 คือไอเท็มอันแรกสุด\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"เอาไอเท็มอันท้ายสุดในรายการออก\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"เอาไอเท็มแบบสุ่มจากรายการออก\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"ถึง #  จากท้ายสุด\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"จนถึง #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"ถึง ท้ายสุด\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"ดึงรายการย่อยทั้งแต่แรกสุด\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"ดึงรายการย่อยจาก # จากท้ายสุด\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"ดึงรายการย่อยจาก #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"สร้างสำเนารายการในช่วงที่กำหนด\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"หาอันแรกที่พบ\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"หาอันสุดท้ายที่พบ\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"คืนค่าตำแหน่งของไอเท็มอันแรก/สุดท้ายที่พบในรายการ คืนค่า 0 ถ้าหาไม่พบ\";\nBlockly.Msg.LISTS_INLIST = \"ในรายการ\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 ว่างเปล่า\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"ความยาวของ %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"ส่งคืนค่าความยาวของรายการ\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"สร้างรายการที่มีไอเท็ม %1 จำนวน %2\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"สร้างรายการที่ประกอบด้วยค่าตามที่ระบุในจำนวนตามที่ต้องการ\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"เป็น\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"แทรกที่\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"กำหนด\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"แทรกไอเท็มเข้าไปเป็นอันแรกสุดของรายการ\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"แทรกไอเท็มเข้าไปในตำแหน่งที่กำหนด #1 คือไอเท็มอันสุดท้าย\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"แทรกไอเท็มเข้าไปในตำแหน่งที่กำหนด #1 คือไอเท็มอันแรก\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"เพิ่มไอเท็มเข้าไปท้ายสุดของรายการ\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"เพิ่มไอเท็มเข้าไปในรายการแบบสุ่ม\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"กำหนดไอเท็มอันแรกในรายการ\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"กำหนดไอเท็มในตำแหน่งที่ระบุในรายการ #1 คือไอเท็มอันท้ายสุด\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"กำหนดไอเท็มในตำแหน่งที่ระบุในรายการ #1 คือไอเท็มอันแรกสุด\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"กำหนดไอเท็มอันสุดท้ายในรายการ\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"กำหนดไอเท็มแบบสุ่มในรายการ\";\nBlockly.Msg.LISTS_TOOLTIP = \"คืนค่าเป็นจริง ถ้ารายการยังว่างเปล่า\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"เท็จ\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"คืนค่าเป็นจริงหรือเท็จ\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"จริง\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://th.wikipedia.org/wiki/อสมการ\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าที่ใส่ทั้งสองค่านั้นเท่ากัน\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าแรกมากกว่าค่าที่สอง\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าแรกมากกว่าหรือเท่ากับค่าที่สอง\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าแรกน้อยกว่าค่าที่สอง\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าแรกน้อยกว่าหรือเท่ากับค่าที่สอง\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าที่ใส่ทั้งสองค่านั้นไม่เท่ากัน\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"ไม่ %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าที่ใส่เป็นเท็จ คืนค่าเป็น \\\"เท็จ\\\" ถ้าค่าที่ใส่เป็นจริง\";\nBlockly.Msg.LOGIC_NULL = \"ไม่กำหนด\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"คืนค่า \\\"ไม่กำหนด\\\"\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"และ\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"หรือ\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าทั้งสองค่าเป็นจริง\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"คืนค่าเป็น \\\"จริง\\\" ถ้ามีอย่างน้อยหนึ่งค่าที่เป็นจริง\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"ทดสอบ\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"ถ้า เป็นเท็จ\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"ถ้า เป็นจริง\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"ตรวจสอบเงื่อนไขใน \\\"ทดสอบ\\\" ถ้าเงื่อนไขเป็นจริง จะคืนค่า \\\"ถ้า เป็นจริง\\\" ถ้าเงื่อนไขเป็นเท็จ จะคืนค่า \\\"ถ้า เป็นเท็จ\\\"\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://th.wikipedia.org/wiki/เลขคณิต\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"คืนค่าผลรวมของตัวเลขทั้งสองจำนวน\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"คืนค่าผลหารของตัวเลขทั้งสองจำนวน\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"คืนค่าผลต่างของตัวเลขทั้งสองจำนวน\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"คืนค่าผลคูณของตัวเลขทั้งสองจำนวน\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"คืนค่าผลการยกกำลัง โดยตัวเลขแรกเป็นฐาน และตัวเลขที่สองเป็นเลขชี้กำลัง\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"เป็น\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"เปลี่ยนค่า\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"เพิ่มค่าของตัวแปร \\\"%1\\\"\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://th.wikipedia.org/wiki/ค่าคงตัวทางคณิตศาสตร์\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"คืนค่าคงตัวทางคณิตศาสตร์ที่พบบ่อยๆ เช่น π (3.141…), e (2.718…), φ (1.618…), รากที่สอง (1.414…), รากที่ ½ (0.707…), ∞ (อนันต์)\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"จำกัดค่า %1 ต่ำสุด %2 สูงสุด %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"จำกัดค่าของตัวเลขให้อยู่ในช่วงที่กำหนด\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"หารลงตัว\";\nBlockly.Msg.MATH_IS_EVEN = \"เป็นจำนวนคู่\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"เป็นเลขติดลบ\";\nBlockly.Msg.MATH_IS_ODD = \"เป็นจำนวนคี่\";\nBlockly.Msg.MATH_IS_POSITIVE = \"เป็นเลขบวก\";\nBlockly.Msg.MATH_IS_PRIME = \"เป็นจำนวนเฉพาะ\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"ตรวจว่าตัวเลขเป็นจำนวนคู่ จำนวนคี่ จำนวนเฉพาะ จำนวนเต็ม เลขบวก เลขติดลบ หรือหารด้วยเลขที่กำหนดลงตัวหรือไม่ คืนค่าเป็นจริงหรือเท็จ\";\nBlockly.Msg.MATH_IS_WHOLE = \"เป็นเลขจำนวนเต็ม\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"เศษของ %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"คืนค่าเศษที่ได้จากการหารของตัวเลขทั้งสองจำนวน\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://th.wikipedia.org/wiki/จำนวน\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"จำนวน\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"ค่าเฉลี่ยของรายการ\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"มากที่สุดในรายการ\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"ค่ามัธยฐานของรายการ\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"น้อยที่สุดในรายการ\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"ฐานนิยมของรายการ\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"สุ่มรายการ\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"ส่วนเบี่ยงเบนมาตรฐานของรายการ\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"ผลรวมของรายการ\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"คืนค่าเฉลี่ยของรายการ\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"คืนค่าตัวเลขที่มากที่สุดในรายการ\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"คืนค่ามัธยฐานของรายการ\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"คืนค่าตัวเลขที่น้อยที่สุดในรายการ\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"คืนค่าฐานนิยมของรายการ\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"สุ่มคืนค่าสิ่งที่อยู่ในรายการ\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"คืนค่าส่วนเบี่ยงเบนมาตรฐานของรายการ\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"คืนค่าผลรวมของตัวเลขทั้งหมดในรายการ\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"สุ่มเลขเศษส่วน\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"สุ่มเลขเศษส่วน ตั้งแต่ 0.0 แต่ไม่เกิน 1.0\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"สุ่มเลขจำนวนเต็มตั้งแต่ %1 จนถึง %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"สุ่มเลขจำนวนเต็มจากช่วงที่กำหนด\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://th.wikipedia.org/wiki/การปัดเศษ\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"ปัดเศษ\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"ปัดเศษลง\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"ปัดเศษขึ้น\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"ปัดเศษของตัวเลขขึ้นหรือลง\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"ค่าสัมบูรณ์\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"รากที่สอง\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"คืนค่าค่าสัมบูรณ์ของตัวเลข\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"คืนค่า e ยกกำลังด้วยตัวเลข\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"คืนค่าลอการิทึมธรรมชาติของตัวเลข\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"คืนค่าลอการิทึมฐานสิบของตัวเลข\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"คืนค่าติดลบของตัวเลข\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"คืนค่า 10 ยกกำลังด้วยตัวเลข\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"คืนค่ารากที่สองของตัวเลข\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://th.wikipedia.org/wiki/ฟังก์ชันตรีโกณมิติ\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"คืนค่า arccosine ของตัวเลข\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"คืนค่า arcsine ของตัวเลข\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"คืนค่า arctangent ของตัวเลข\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"คืนค่า cosine ขององศา (ไม่ใช่เรเดียน)\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"คืนค่า sine ขององศา (ไม่ใช่เรเดียน)\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"คืนค่า tangent ขององศา (ไม่ใช่เรเดียน)\";\nBlockly.Msg.NEW_VARIABLE = \"สร้างตัวแปรใหม่\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"ชื่อตัวแปร:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"ด้วย:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_(computer_science)\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"เรียกใช้ฟังก์ชันที่สร้างโดยผู้ใช้ \\\"%1\\\"\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_(computer_science)\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"เรียกใช้ฟังก์ชันที่สร้างโดยผู้ใช้ \\\"%1\\\" และใช้ผลลัพธ์ของมัน\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"สร้าง \\\"%1\\\"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"ทำอะไรบางอย่าง\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"ถึง\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"สร้างฟังก์ชันที่ไม่มีผลลัพธ์\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"คืนค่า\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"สร้างฟังก์ชันที่มีผลลัพธ์\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"ระวัง: ฟังก์ชันนี้มีพารามิเตอร์ที่มีชื่อซ้ำกัน\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"เน้นฟังก์ชันนิยาม\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"ถ้ามีค่าเป็นจริง ให้คืนค่าที่สอง\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"ระวัง: บล็อกนี้ใช้เฉพาะในการสร้างฟังก์ชันเท่านั้น\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"ชื่อนำเข้า:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"นำเข้า\";\nBlockly.Msg.REMOVE_COMMENT = \"เอาคำอธิบายออก\";\nBlockly.Msg.RENAME_VARIABLE = \"เปลี่ยนชื่อตัวแปร...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"เปลี่ยนชื่อ \\\"%1\\\" เป็น:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"ต่อด้วยข้อความ\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"นำเอา\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"ต่อข้อความให้ตัวแปร \\\"%1\\\"\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"เปลี่ยนเป็น ตัวพิมพ์เล็ก\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"เปลี่ยนเป็น ตัวอักษรแรกเป็นตัวพิมพ์ใหญ่\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"เปลี่ยนเป็น ตัวพิมพ์ใหญ่\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"คืนค่าสำเนาของข้อความในกรณีต่างๆ\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"ดึง ตัวอักษรตัวแรก\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"ดึง ตัวอักษรตัวที่ # จากท้าย\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"ดึง ตัวอักษรตัวที่\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"ในข้อความ\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"ดึง ตัวอักษรตัวสุดท้าย\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"ถึงตัวอักษรแบบสุ่ม\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"คืนค่าตัวอักษรจากตำแหน่งที่ระบุ\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"เพิ่มรายการเข้าไปในข้อความ\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"รวม\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"เพิ่ม ลบ หรือจัดเรียงบล็อกข้อความนี้ใหม่\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"จนถึง ตัวอักษรที่ # จากท้าย\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"จนถึง ตัวอักษรที่\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"จนถึง ตัวอักษรสุดท้าย\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"ในข้อความ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"แยกข้อความย่อยตั้งแต่ ตัวอักษรแรก\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"แยกข้อความย่อยตั้งแต่ ตัวอักษรที่ # จากท้าย\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"แยกข้อความย่อยตั้งแต่ ตัวอักษรที่\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"คืนค่าบางส่วนของข้อความ\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"ในข้อความ\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"หาข้อความแรกที่พบ\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"หาข้อความสุดท้ายที่พบ\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"คืนค่าตำแหน่งที่พบข้อความแรกอยู่ในข้อความที่สอง คืนค่า 0 ถ้าหาไม่พบ\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 ว่าง\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"คืนค่าจริง ถ้าข้อความยังว่าง\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"สร้างข้อความด้วย\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"สร้างข้อความด้วยการรวมจำนวนของรายการเข้าด้วยกัน\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"ความยาวของ %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"คืนค่าความยาวของข้อความ (รวมช่องว่าง)\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"พิมพ์ %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"พิมพ์ข้อความ ตัวเลข หรือค่าอื่นๆ\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"แสดงหน้าต่างให้ผู้ใช้ใส่ตัวเลข\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"แสดงหน้าต่างให้ผู้ใช้ใส่ข้อความ\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"แสดงหน้าต่างตัวเลข\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"แสดงหน้าต่างข้อความ\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://th.wikipedia.org/wiki/สายอักขระ\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"ตัวหนังสือ คำ หรือข้อความ\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"ลบช่องว่างทั้งสองข้างของ\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"ลบช่องว่างด้านหน้าของ\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"ลบช่องว่างข้างท้ายของ\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"คืนค่าสำเนาของข้อความที่ลบเอาช่องว่างหน้าและหลังข้อความออกแล้ว\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"รายการ\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"สร้าง \\\"กำหนด %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"คืนค่าของตัวแปรนี้\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"สร้าง \\\"get %1\\\"\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"จนถึง\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"กำหนด\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"กำหนดให้ตัวแปรนี้เท่ากับการป้อนข้อมูล\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/tl.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.tl');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Dagdag komento\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"pagbago ng value:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"bloke\";\nBlockly.Msg.COLLAPSE_BLOCK = \"bloke\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"kulay 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"kulay 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"proporsyon\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"halo\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Paghalo ng dalawang kulay kasama ng ibinigay na proporsyon (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"http://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"pagpili ng kulay sa paleta.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"iba ibang kulay\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"pagpili ng iba't ibang kulay.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"asul\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"berde\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"pula\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"kulayan ng\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"gumawa ng kulay ng may espisipikong dami ng kulay pula, berde, at asul. lahat ng halaga ay dapat sa pagitan ng 0 at 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"putulin ang paulit ulit\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"Magpatuloy sa susunod na pag-ulit ng loop\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Hatiin ang nilalaman ng loop.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Laktawan ang natitirang bahagi ng loop, at magpatuloy sa susunod na pag-ulit.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Babala: Ang block ito ay maaari lamang magamit sa loob ng loop.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"sa listahan\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"sa bawat bagay\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Para sa bawat item sa isang list, i-set ang variable ng '% 1' sa mga item, at pagkatapos ay gumawa ng ilang mga statements.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"mula %1 hanggang %2 ng %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"bilangin\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Magkaroon ng mga variable na %1 na tanggalin ng mga halaga mula sa simulang numero hanggang sa dulong numero, at bilangin sa pamamagitan ng tinukoy na agwat, at gawin ang mga tinukoy na mga blocks.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Mag dagdag ng condition sa if block.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Mag Add ng final, kunin lahat ng condition sa if block.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Mag Add, remove o kaya mag reorder ng sections para maayos ang if block.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"else\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"else if\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"kung\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"kung ang value ay true,  gagawin ang do statements.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Kung ang value ay true, gagawin ang unang block ng do statements. Kung hindi, gagawin ang pangalawang block ng statement.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Kung ang unang value ay true, gagawin ang first block ng statement. Kung hindi, kung ang second value ay true, gagawin ang second block ng statement.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Kung ang first value ay true, gagawin ang first block ng statement. Kung hindi true ang second value, gagawin ang second block ng statement. Kung wala sa mga values ay true, gagawin ang last block ng statements.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"http://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"gawin\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"ulitin %1 beses\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"ulitin\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"beses\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"gumawa ng ilang pangungusap ng ilang ulit.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"ulitin hanggang\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"ulitin habang\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Habang ang value ay false, gagawin ang ibang statements.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Habang ang value ay true, gagawin ang ibang statements.\";\nBlockly.Msg.DELETE_BLOCK = \"burahin ang bloke\";\nBlockly.Msg.DELETE_X_BLOCKS = \"burahin %1 ng bloke\";\nBlockly.Msg.DISABLE_BLOCK = \"Ipangwalang bisa ang Block\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Kaparehas\";\nBlockly.Msg.ENABLE_BLOCK = \"Bigyan ng bisa ang Block\";\nBlockly.Msg.EXPAND_ALL = \"Palawakin ang Blocks\";\nBlockly.Msg.EXPAND_BLOCK = \"Palawakin ang Block\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Panlabas na Inputs\";\nBlockly.Msg.HELP = \"Tulong\";\nBlockly.Msg.INLINE_INPUTS = \"Inline na Inputs\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"Gumawa ng walang laman na list\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Ibabalik ang list, na may haba na 0, nag lalaman ng walang data records\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"list\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Magdagdag, mag tanggal or mag ayos ng sections para muling maayos ang listahan ng block.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"gumawa ng list kasama\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Mag dagdag ng item sa list.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Gumawa ng list na may kahit anong number ng items.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"Una\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# mula katapusan\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"kunin\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"kunin at tanggalin\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"huli\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"nang hindi pinipili\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"tanggalin\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Ibalik ang unang item sa list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Ibalik ang item sa tinakdang posisyon sa list. #1 ay ang huling item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Ibalik ang item sa itinakdang posisyon sa list. #1 ay ang unang item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Ibalik ang huling item sa list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Nag babalik ng hindi pinipiling item sa list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Nag tatanggal at nag babalik ng mga unang item sa list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Nag tatanggal at nag babalik ng items sa tinukoy na posisyon sa list. #1 ay ang huling item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Nag tatanggal at nag babalik ng mga items sa tinukoy na posisyon sa list. #1 ang unang item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Nag tatanggal at nag babalik ng huling item sa list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Nag tatanggal at nag babalik ng mga hindi pinipiling item sa list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Nag tatanggal ng unang item sa list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Nag tatanggal ng item sa tinukoy na posisyon sa list. #1 ay ang huling item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Nag tatanggal ng item sa tinukoy na posisyon sa list. #1 ay ang unang item.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Nag tatanggal ng huling item sa list.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Nag tatanggal ng item mula sa walang pinipiling list.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"mula # hanggang huli\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"mula #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"hanggang huli\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Pagkuha_ng_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"pag kuha ng sub-list mula sa una\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"pag kuha ng sub-list mula sa # mula huli\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"pag kuha ng sub-list mula #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Gumagawa ng kopya ng tinukoy na bahagi ng list.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"Hanapin ang unang pangyayari ng item\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Pagkuha_ng_Items_mula_sa_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"hanapin ang huling pangyayari ng item\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Pagbalik ng index ng una/huli pangyayari ng item sa list. Pagbalik ng 0 kung ang item ay hindi makita.\";\nBlockly.Msg.LISTS_INLIST = \"sa list\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#ay_walang_laman\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 ay walang laman\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#haba_ng\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"haba ng %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Pag balik ng haba ng list.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#paggawa_ng_list_kasama\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"pag gawa ng list kasama ng item %1 inuulit %2 beses\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Pag gawa ng list na binubuo ng binigay na value at inulit na tinuloy na bilang ng beses.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#sa_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"gaya ng\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"isingit sa\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"set\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Nag singit ng item sa simula ng list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Nag singit ng item sa tinukoy na posisyon sa list. #1 ay ang huling item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Nag singit ng item sa tinukoy na posistion sa list. #1 ay ang unang item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Idagdag ang item sa huli ng isang list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Isingit ang item ng walang pinipili sa isang list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Pag set ng unang item sa isang list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Pag set ng item sa tinukoy na posisyon sa isang list. #1 ay ang huling item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Pag set ng item sa tinukoy na position sa isang list. #1 ay ang unang item.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Pag set sa huling item sa isang list.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Pag set ng walang pinipiling item sa isang list.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Nagbabalik ng true kung ang list ay walang laman.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"mali\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Nag babalik ng true or false.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"tama\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"http://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Nag babalik ng true kung ang pinasok ay parehong magkatumbas.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Nagbabalik ng true kung ang unang pinasok ay mas malaki kaysa pangalawang pinasok.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Nag babalik ng true kung ang unang pinasok ay mas malaki or katumbas ng pangalawang pinasok.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Nag babalik ng true kung ang unang pinasok ay maliit kaysa sa pangalawang pinasok.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Nag babalik ng true kung ang unang pinasok ay maliit sa o katumbas sa pangalawang pinasok.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Return true if both inputs are not equal to each other.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"not %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Returns true if the input is false.  Returns false if the input is true.\";\nBlockly.Msg.LOGIC_NULL = \"blangko\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"http://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Returns null.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"at\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"o\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Return true if both inputs are true.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Return true if at least one of the inputs is true.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"http://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"kung mali\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"kung tama\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"http://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Return the sum of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Return the quotient of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Return the difference of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Return the product of the two numbers.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Return the first number raised to the power of the second number.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"by\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"baguhin\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Add a number to variable '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"http://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"constrain %1 low %2 high %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Constrain a number to be between the specified limits (inclusive).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"is divisible by\";\nBlockly.Msg.MATH_IS_EVEN = \"is even\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"ay negatibo\";\nBlockly.Msg.MATH_IS_ODD = \"is odd\";\nBlockly.Msg.MATH_IS_POSITIVE = \"ay positibo\";\nBlockly.Msg.MATH_IS_PRIME = \"is prime\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\";\nBlockly.Msg.MATH_IS_WHOLE = \"is whole\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"http://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"remainder of %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Return the remainder from dividing the two numbers.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"http://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"A number.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"average of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"max of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"median of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"min of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"modes of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"random item of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"standard deviation of list\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"sum of list\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Return the average (arithmetic mean) of the numeric values in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Return the largest number in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Return the median number in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Return the smallest number in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Return a list of the most common item(s) in the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Return a random element from the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Return the standard deviation of the list.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Return the sum of all the numbers in the list.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"http://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"random fraction\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"http://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"random integer from %1 to %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Return a random integer between the two specified limits, inclusive.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"http://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"round\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"round down\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"round up\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Round a number up or down.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"http://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"absolute\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"square root\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Return the absolute value of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Return e to the power of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Return the natural logarithm of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Return the base 10 logarithm of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Return the negation of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Return 10 to the power of a number.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Return the square root of a number.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";\nBlockly.Msg.MATH_TRIG_COS = \"cos\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"http://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Return the arccosine of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Return the arcsine of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Return the arctangent of a number.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Return the cosine of a degree (not radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Return the sine of a degree (not radian).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Return the tangent of a degree (not radian).\";\nBlockly.Msg.NEW_VARIABLE = \"New variable...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"New variable name:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"with:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Run the user-defined function '%1'.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Run the user-defined function '%1' and use its output.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Create '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"do something\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"to\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Creates a function with no output.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"return\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Creates a function with an output.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Warning: This function has duplicate parameters.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Highlight function definition\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"If a value is true, then return a second value.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Warning: This block may be used only within a function definition.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"input name:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"inputs\";\nBlockly.Msg.REMOVE_COMMENT = \"Remove Comment\";\nBlockly.Msg.RENAME_VARIABLE = \"Rename variable...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Rename all '%1' variables to:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"append text\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"to\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Append some text to variable '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"to lower case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"to Title Case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"to UPPER CASE\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Return a copy of the text in a different case.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"get first letter\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"get letter # from end\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"get letter #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"in text\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"get last letter\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"get random letter\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Returns the letter at the specified position.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Add an item to the text.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"join\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Add, remove, or reorder sections to reconfigure this text block.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"to letter # from end\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"to letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"to last letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"in text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"get substring from first letter\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"get substring from letter # from end\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"get substring from letter #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Returns a specified portion of the text.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"in text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"find first occurrence of text\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"find last occurrence of text\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 is empty\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Returns true if the provided text is empty.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"create text with\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Create a piece of text by joining together any number of items.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"length of %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Returns the number of letters (including spaces) in the provided text.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"print %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Print the specified text, number or other value.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Prompt for user for a number.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Prompt for user for some text.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"prompt for number with message\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"prompt for text with message\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"http://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"A letter, word, or line of text.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"trim spaces from both sides\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"trim spaces from left side\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"trim spaces from right side\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Return a copy of the text with spaces removed from one or both ends.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"item\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Create 'set %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Returns the value of this variable.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Create 'get %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"to\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"set\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Sets this variable to be equal to the input.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/tr.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.tr');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Yorum Ekle\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Değeri değiştir:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Blokları Daralt\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Blok'u Daralt\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"renk 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"renk 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"oran\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"karıştır\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Verilen bir orana bağlı olarak iki rengi karıştırır. (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Paletten bir renk seçin.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"rastgele renk\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Rastgele bir renk seçin.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"mavi\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"yeşil\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"kırmızı\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"renk değerleri\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Kırmızı, yeşil ve mavinin belirtilen miktarıyla bir renk oluşturun.  Tüm değerler 0 ile 100 arasında olmalıdır.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"döngüden çık\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"döngünün sonraki adımından devam et\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"İçeren döngüden çık.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Bu döngünün geri kalanını atlayın ve sonraki adım ile devam edin.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Uyarı: Bu blok sadece bir döngü içinde kullanılabilir.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"listede\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"her öğe için\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Bir listedeki her öğe için  '%1' değişkenini maddeye atayın  ve bundan sonra bazı açıklamalar yapın.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"%1 den %2 ye, her adımda %3 değişim\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"ile sayılır\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"%1 değişkenini başlangıç numarasından bitiş numarasına kadar tanımlı farkla değerler verirken tanımlı blokları yap.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"If bloğuna bir koşul ekleyin.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"If bloğuna kalan durumları \\\"yakalayan\\\" bir son ekle.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"If bloğuna ekle, kaldır veya yeniden düzenleme yap.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"değilse\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"değilse eğer\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"eğer\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Eğer değişken true , yani gerçekleşmiş ise , ardından gelen işlemi yerine getir .\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Eğer değişken true, yani gerçekleşiyor ise ilk blok'taki işlemleri yerine getir, Aksi halde ikinci blok'taki işlemleri yerine getir.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Eğer ilk değişken true, yani koşul gerçekleşmiş ise ilk blok içerisindeki işlem(ler)i gerçekleştir. Eğer ikinci değişken true ise, ikinci bloktaki işlem(ler)i gerçekleştir .\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Eğer ilk değer true, yani olumlu ise, ilk blok'taki işlem(ler)i gerçekleştir. İlk değer true değil ama ikinci değer true ise, ikinci bloktaki işlem(ler)i gerçekleştir. Eğer değerlerin hiçbiri true değil ise son blok'taki işlem(ler)i gerçekleştir.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop  Döngü\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"yap\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"%1 kez tekrarla\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"tekrarla\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"kez\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Bazı işlemleri birkaç kez yap.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"kadar tekrarla\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"tekrar ederken\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Bir değer false ise, o zaman bazı ifadeleri yap.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Bir değer true ise, o zaman bazı ifadeleri yap.\";\nBlockly.Msg.DELETE_BLOCK = \"Bloğu Sil\";\nBlockly.Msg.DELETE_X_BLOCKS = \"%1 Bloğu Sil\";\nBlockly.Msg.DISABLE_BLOCK = \"Bloğu Devre Dışı Bırak\";\nBlockly.Msg.DUPLICATE_BLOCK = \"çoğalt\";\nBlockly.Msg.ENABLE_BLOCK = \"Bloğu Etkinleştir\";\nBlockly.Msg.EXPAND_ALL = \"Blokları Genişlet\";\nBlockly.Msg.EXPAND_BLOCK = \"Bloğu Genişlet\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Harici Girişler\";\nBlockly.Msg.HELP = \"Yardım\";\nBlockly.Msg.INLINE_INPUTS = \"Satır içi girdi\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists Boş Listeler\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"Boş liste oluştur\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Veri kaydı içermeyen uzunluğu 0 olan bir listeyi verir\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"liste\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Bu liste bloğunu yeniden yapılandırmak için bölüm ekle,kaldır veya yeniden çağır.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"İle liste oluşturma\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Listeye bir nesne ekle.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Herhangi sayıda nesne içeren bir liste oluştur.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"ilk\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# sonundan\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"# Kare\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"Al\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"al ve kaldır\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"son\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"rastgele\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"kaldır\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Listedeki ilk öğeyi verir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Listede belirli pozisyondaki bir öğeyi verir.#1 son öğedir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Listede belirli pozisyondaki bir öğeyi verir.#1 ilk öğedir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Listedeki son öğeyi verir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Listedeki rastgele bir öğeyi verir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Kaldırır ve listedeki ilk öğeyi döndürür.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Kaldırır ve listede belirtilen konumdaki bir ögeyi döndürür.  #1 son ögedir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Kaldırır ve listede belirtilen konumdaki bir öğeyi döndürür.  #1 son öğedir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Kaldırır ve listedeki son öğeyi döndürür.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Kaldırır ve listedeki rastgele bir öğeyi verir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Listedeki ilk nesneyi kaldırır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Liste içerisinde , tanımlanan pozisyondaki bir öğeyi kaldırır . #1 son öğe dir .\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Bir liste içerisinde , tanımlanan pozisyonda ki öğeyi kaldırır.#1 ilk öğedir.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Listedeki son nesneyi kaldırır.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Listedeki rastgele bir nesneyi kaldırır.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"Sondan #'a kadar\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"#'a\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"Sona kadar\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist alt liste\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"ilk öğeden alt liste al\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"# işaretinden sonra gelen ifadeye göre  alt liste al , # sondan\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"# dan alt liste al\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Listenin belirli bir kısmının kopyasını yaratır.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"Öğenin ilk varolduğu yeri bul\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List  Bir listeden öğe almak\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"Öğenin son varolduğu yeri bul\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Öğenin  listede ,  ilk ve son görüldüğü dizinleri döndürür . Öğe bulunmassa , 0 döndürür .\";\nBlockly.Msg.LISTS_INLIST = \"Listede\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty Boş Listeler\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 boş\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of  Uzunluk Listeleri\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"%1'in uzunluğu\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Bir listenin uzunluğunu verir.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with  İle liste yaratma\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"%1 nesnenin %2 kez tekrarlandığı bir liste yarat\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Verilen bir değerin , belirli bir sayıda tekrarlanmasından oluşan bir liste yaratır .\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set   Listeler#Liste içi ...gurubu\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"olarak\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"e yerleştir\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"yerleştir\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Nesneyi listenin başlangıcına ekler.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Bir öğeyi , belirtilen yer pozisyonuna göre , listeye yerleştirir . #1 son öğedir .\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Bir öğeyi belirtilen pozisyona göre listeye yerleştirir . #1 ilk öğedir .\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Öğeyi listenin sonuna ekle .\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Bir öğeyi listeye rast gele ekler .\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Bir listenin ilk öğesini yerleştirir .\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Bir öğeyi belirtilen yere göre listeye yerleştirir . #1 son öğedir .\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Bir öğeyi belirtilen yere göre listeye yerleştirir . #1 ilk öğedir .\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Bir listedeki son öğeyi yerleştirir .\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Listeye rast gele bir öğe yerleştirir .\";\nBlockly.Msg.LISTS_TOOLTIP = \"Eğer liste boş ise true döndürür .\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"false = Olumsuz\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False  olumlu_olumsuz\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Ya 'True' yada 'False' değerini verir.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"Olumlu\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)  eşitsizlik işlemi\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Girilen iki değer birbirine eşitse \\\"True\\\" değerini verir.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Girilen ilk değer ikinci değerden daha büyükse \\\"True\\\" değerini verir.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Girilen ilk değer ikinci değerden büyük veya eşitse \\\"True\\\" değerini verir.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Girilen ilk değer ikinci değerden küçükse \\\"True\\\" değerini verir.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Girilen ilk değer ikinci değerden küçük veya eşitse \\\"True\\\" değerini verir.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Girilen iki değerde birbirine eşit değilse \\\"True\\\" değerini verir.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"%1 değil\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Girilen değer yanlışsa \\\"True\\\" değerini verir.Girilen değer doğruysa \\\"False\\\" değerini verir.\";\nBlockly.Msg.LOGIC_NULL = \"sıfır\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"sıfır verir.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"ve\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"veya\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Girilen iki değerde doğruysa \\\"True\\\" değerini verir.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Girilen iki değerden en az biri doğruysa \\\"True\\\" değerini verir.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"test\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"yanlış ise\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"doğru ise\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"'test'deki şartı test eder. Eğer şart doğru ise 'doğru' değeri döndürür, aksi halde 'yanlış' değeri döndürür.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://tr.wikipedia.org/wiki/Aritmetik\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"İki rakamın toplamını döndür.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"İki sayının bölümünü döndür.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"İki sayını farkını döndür.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"İki sayının çarpımını döndür.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"İlk sayinin ikincinin kuvvetine yükseltilmişini döndür.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"ile\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"Değiştirmek\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"'%1' değişkenine bir sayı ekle.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Yaygın sabitlerden birini döndür:π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (sonsuz).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"%1 i en düşük %2 en yüksek %3 ile sınırla\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Bir sayıyı belirli iki sayı arasında sınırlandır(dahil).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"bölünebilir\";\nBlockly.Msg.MATH_IS_EVEN = \"çift\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"negatif\";\nBlockly.Msg.MATH_IS_ODD = \"tek\";\nBlockly.Msg.MATH_IS_POSITIVE = \"pozitif\";\nBlockly.Msg.MATH_IS_PRIME = \"asal\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Bir sayinin çift mi tek mi , tam mı, asal mı , pozitif mi, negatif mi, veya tam bir  sayıyla bölünebilirliğini kontrol et.'True' veya 'False' değerini döndür.\";\nBlockly.Msg.MATH_IS_WHOLE = \"Bütün olduğunu\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"%1 ÷ %2 nin kalanı\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"İki sayının bölümünden kalanı döndür.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"x\";\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Bir sayı.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"listenin ortalaması\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"en büyük sayı\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"Listenin medyanı\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"Listenin en küçüğü\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"Listenin modları\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"Listenin rastgele öğesi\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"Listenin standart sapması\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"Listenin toplamı\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Listedeki sayısal değerlerin ortalamasını (aritmetik anlamda) döndür.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Listenin en büyüğünü döndür.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Listenin medyanını döndür.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Listenin en küçüğünü döndür.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Listede ki en yaygın öğe veya öğelerinin listesini döndür.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Listeden rastgele bir element döndür.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Listenin standart sapmasını döndür.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Listede ki tüm sayıların toplamını döndür.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"üst alma\";\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation  Rastgele sayı yaratma\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"Rast gele kesirli sayı , yada parça\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"0.0(dahil) ve 1.0 (hariç) sayıları arasında bir sayı döndür .\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation  Rast gele sayı üretme\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"%1 ile %2 arasında rastgele tam sayı üret\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Herhangi iki sayı arasında , sayılar dahil olmak üzere , rastgele bir tam sayı döndür.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding  Yuvarlama\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"Yuvarla\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"aşağı yuvarla\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"yukarı yuvarla\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Bir sayı yı yukarı yada aşağı yuvarla .\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root  Kare kök\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"Kesin\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"Kare kök\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Bir sayının tam değerini döndür .\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Bir sayının e ' inci  kuvvetini döndür .\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Bir sayının doğal logaritmasını döndür .\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Bir sayının 10  temelinde logaritmasını döndür .\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Bir sayıyı geçersiz olarak döndür .\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Bir sayının 10. kuvvetini döndür .\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Bir sayının karekökü nü döndür .\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"tire\";\nBlockly.Msg.MATH_TRIG_ACOS = \"akosünüs\";\nBlockly.Msg.MATH_TRIG_ASIN = \"asinüs\";\nBlockly.Msg.MATH_TRIG_ATAN = \"atanjant\";\nBlockly.Msg.MATH_TRIG_COS = \"kosünüs\";\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions  Trigonometrik fonksiyonlar\";\nBlockly.Msg.MATH_TRIG_SIN = \"Sinüs\";\nBlockly.Msg.MATH_TRIG_TAN = \"tanjant\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Bir sayının ters kosunusunu döndür .\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Bir sayının ters sinüsünü döndür .\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Bir sayının ters tanjantını döndür .\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Bir açının kosinüsünü döndür(radyan olarak değil).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Bir açının sinüsünü döndür(radyan olarak değil).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Bir açının tanjantını döndür(radyan olarak değil).\";\nBlockly.Msg.NEW_VARIABLE = \"Yeni değişken...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Yeni değişken ismi :\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"ile :\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29  prosedür_%28bilgisayar_bilimi%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Kullanıcı tanımlı fonksiyonu çalıştır '%1' .\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Kullanıcı tanımlı fonksiyonu çalıştır '%1' ve çıktısını kullan .\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"'%1' oluştur\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"birşey yap\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"e\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Çıktı vermeyen bir fonksiyon yaratır .\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"Geri dön\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Çıktı veren bir fonksiyon oluşturur.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Uyarı: Bu fonksiyon yinelenen parametreler vardır.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Fonksiyon tanımı vurgulamak\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Eğer değer doğruysa, ikinci değere geri dön.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Uyarı: Bu blok yalnızca bir fonksiyon tanımı içinde kullanılır.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"girdi adı:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"girdiler\";\nBlockly.Msg.REMOVE_COMMENT = \"Yorumları sil\";\nBlockly.Msg.RENAME_VARIABLE = \"Değişkeni yeniden adlandır...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Tüm '%1' değişkenlerini yeniden isimlendir:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"Metin Ekle\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"e\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Değişken '%1' e bazı metinler ekleyin.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"küçük harf\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"Baş Harfler Büyük\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"büyük harf\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Metnin bir kopyasını farklı bir harf durumunda (HEPSİ BÜYÜK - hepsi küçük) getirir.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"İlk harfini al\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"# dan sona harfleri al\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"# harfini al\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"metinde\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"son harfi al\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"Rastgele bir harf al\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Belirli pozisyonda ki bir harfi döndürür.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Metine bir öğe ekle.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"Katıl\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Bu metin bloğunu düzenlemek için bölüm ekle,sil veya yeniden görevlendir.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"Sondan # harfe\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"# harfe\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"son harfe\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"metinde\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"ilk harften başlayarak alt-string alma\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"n inci harften sona kadar alt-string alma\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"n inci harften alt-string alma\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Metinin belirli bir kısmını döndürür.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"metinde\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"Metnin ilk varolduğu yeri bul\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"Metnin son varolduğu yeri bul\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"İlk metnin ikinci metnin içindeki ilk ve son varoluşlarının indeksini döndürür.Metin bulunamadıysa 0 döndürür.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 boş\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Verilen metin boşsa true(doğru) değerini verir.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"ile metin oluştur\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Herhangi bir sayıda ki öğeleri bir araya getirerek metnin bir parçasını oluştur.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification   Yazı değişimi\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"%1 in uzunluğu\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Yazı içerisinde verilen harflerin ( harf arasındaki boşluklar dahil) sayısını verir .\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text  Yazıyı yazdırmak\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"%1 ' i Yaz\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Belirli bir metni,sayıyı veya başka bir değeri yaz.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user  Kullanıcıdan veri almak\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Kullanıcıdan sayı al .\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Kullanıcıdan Yazım al .\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"Kullanıcıdan sayı al , istek mesajı göstererek\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"Kullanıcıdan yazım al , istek mesajıyla\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Metnin bir harfi,kelimesi veya satırı.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"İki tarafdan da boşlukları düzenle\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"Soldan boşlukları düzenle\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"Sağdan boşlukları düzenle\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Metnin bir veya her iki sondan da boşlukları silinmiş şekilde kopyasını verir.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"öge\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"'set %1' oluştur\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Bu değişkenin değerini verir.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"'get %1' oluştur\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"e\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"Atamak\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Bu değişkeni girilen değere eşitler.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/uk.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.uk');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Додати коментар\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Змінити значення:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Згорнути блоки\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Згорнути блок\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"колір 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"колір 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";\nBlockly.Msg.COLOUR_BLEND_RATIO = \"співвідношення\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"суміш\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Змішує дві барви разом з даним співвідношенням (0.0 - 1.0).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://uk.wikipedia.org/wiki/Колір\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Вибрати колір з палітри.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"випадковий колір\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"Вибрати колір навмання.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"синій\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"зелений\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";\nBlockly.Msg.COLOUR_RGB_RED = \"червоний\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"колір з\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Створити колір з указаного червоного, зеленого та синього.  Усі значення мають бути від 0 до 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"перервати цикл\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"продовжити з наступної ітерації циклу\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Вирватися з циклічних оточень.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Пропустити залишок цього циклу і перейти до виконання наступної ітерації.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Попередження: цей блок може бути використаний тільки в межах циклу.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"у списку\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"блок тексту\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"для кожного елемента\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Для кожного елемента в списку задайте змінну '%1' для елемента, а потім зробіть деякі заяви.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"від %1 до %2 через %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"рахувати з\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Наявна змінна %1 приймає значення від початкового значення до кінцевого значення, враховуючи заданий інтервал, і зробіть вказані блоки.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Додати умову до якщо блокувати.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Додати остаточну, всеосяжну умова до блоку якщо.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"http://code.google.com/p/blockly/wiki/If_Then\";\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Додати, видалити або змінити порядок розділів переналаштувати це, якщо блокується.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"інакше\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"Інакше якщо\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"якщо\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Якщо значення true, зробити деякі заяви.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Якщо значення істина, то виконується перший блок операторів. В іншому випадку виконується другий блок операторів.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Якщо перше значення істина, то виконується перший блок операторів. В іншому випадку, якщо друге значення істина, то виконується другий блок операторів.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Якщо перше значення істина, то виконується перший блок операторів. В іншому випадку, якщо друге значення істина, то виконується другий блок операторів. Якщо жодне із значень не є істинним, то виконується останній блок операторів.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"http://en.Wikipedia.org/Wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"зробити\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"повторити %1 разів\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"повторити\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"разів\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Зробити деякі заяви кілька разів.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"http://code.google.com/p/blockly/wiki/Repeat\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"повторювати доки\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"повторювати поки\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Поки значення false, зробити деякі заяви.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Поки значення true, зробити деякі заяви.\";\nBlockly.Msg.DELETE_BLOCK = \"Видалити блок\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Видалити %1 блоків\";\nBlockly.Msg.DISABLE_BLOCK = \"Вимкнути блок\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Дублікат\";\nBlockly.Msg.ENABLE_BLOCK = \"Увімкнути блок\";\nBlockly.Msg.EXPAND_ALL = \"Розгорнути блоки\";\nBlockly.Msg.EXPAND_BLOCK = \"Розгорнути блок\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Зовнішні входи\";\nBlockly.Msg.HELP = \"Довідка\";\nBlockly.Msg.INLINE_INPUTS = \"Вбудовані входи\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://uk.wikipedia.org/wiki/Зв%27язаний_список\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"створити порожній список\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Повертає список, довжиною 0, що не містить записів даних\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"список\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Додати, видалити або змінити порядок розділів для переналаштування блокування списку.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"створює список з\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Додати елемент до списку.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Створює список з будь-якою кількістю елементів.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"перший\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"# з кінця\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"отримати\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"отримати і видалити\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"останній\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"випадковий\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"вилучити\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"-ий.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Повертає перший елемент у списку.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Повертає елемент у заданій позиції у списку. #1 - це останній пункт.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Повертає елемент у заданій позицію у списку. #1 - це перший пункт.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Повертає останній елемент списку.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Повертає випадковий елемент у списку.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Видаляє і повертає перший елемент у списку.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Видаляє і повертає елемент у заданій позиції у списку. #1 - це останній пункт.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Видаляє і повертає елемент у заданій позиції у списку. #1 - це перший пункт.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Видаляє і повертає останній елемент списку.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Видаляє і повертає випадковий елемент у список.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Видаляє перший елемент у списку.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Вилучає елемент у вказаній позиції списку. #1 - це останній пункт.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Вилучає елемент у вказаній позиції списку. #1 - це перший пункт.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Видаляє останній елемент списку.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Видаляє випадковий елемент у списку.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"до # з кінця\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"до #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"до останнього\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"отримати вкладений список з першого\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"отримати вкладений список від # з кінця\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"отримати вкладений список з #\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"символу.\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Створює копію вказаної частини списку.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"знайти перше входження елемента\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"знайти останнє входження елемента\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Повертає індекс першого/останнього входження першого елементу у списку. Повертає 0, якщо текст не знайдений.\";\nBlockly.Msg.LISTS_INLIST = \"у списку\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 є порожнім\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"довжина %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Повертає довжину списку.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"створити список з елемента %1 повтореного %2 разів\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Створює список, що складається з заданого значення повтореного певну кількість разів.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"як\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"вставити в\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"встановити\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Вставляє елемент на початок списку.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Вставляє елемент у вказану позицію списку. #1 - це останній пункт.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Вставка елемента у вказану позицію списку.  #1 є першим пунктом.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Додає елемент до кінця списку.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Випадковим чином вставляє елемент у списку.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Задає перший елемент у списку.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Задає елемент у вказаній позиції списку. #1 - це останній пункт.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Задає елемент у вказаній позиції списку. #1 - це перший пункт.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Задає останній елемент списку.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Задає випадковий елемент у списку.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Повертає істина, якщо список порожній.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"хибність\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"http://code.google.com/p/blockly/wiki/True_False\";\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Повертає значення ІСТИНА або ХИБНІСТЬ.\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"істина\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://uk.wikipedia.org/wiki/Нерівність\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Повертає true, якщо обидва входи рівні один одному.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Повертає true, якщо перше вхідне значення більше, ніж другий вхід.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Повертає true, якщо перше вхідне значення більше або дорівнює другому входу.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Повертає true, якщо перше вхідне значення менше, ніж другий вхід.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Повертає true, якщо перше вхідне значення менше або дорівнює другому входу.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Повертає true, якщо обидва входи не дорівнюють один одному.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"http://code.google.com/p/blockly/wiki/Not\";\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"не %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Повертає істина, якщо вхідне значення хибність. Повертає хибність, якщо вхідна значення істина.\";\nBlockly.Msg.LOGIC_NULL = \"нічого\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Повертає null.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"та\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"http://code.google.com/p/blockly/wiki/And_Or\";\nBlockly.Msg.LOGIC_OPERATION_OR = \"або\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Повертає true, якщо обидва входи істинні.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Повертає true, якщо принаймні один з входів  true.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"тест\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"Якщо хибність\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"якщо істина\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Перевірте умову в 'test'. Якщо умова істинна, то повертає  значення типу 'якщо істина'; в іншому випадку повертає значення 'якщо хибність'.\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://uk.wikipedia.org/wiki/Арифметика\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Повертає суму двох чисел.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Повертає частку двох чисел.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Повертає різницю двох чисел.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Повертає добуток двох чисел.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Повертає перше число, піднесене до степеня другого числа.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"від\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"змінити\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Додати число змінній '%1'.\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://uk.wikipedia.org/wiki/Математична_константа\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Повертає одну з поширених констант: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) або ∞ (безмежність).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"обмежити %1 від %2 до %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Обмежує число вказаними межами (включно).\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"ділиться на\";\nBlockly.Msg.MATH_IS_EVEN = \"парне\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"від'ємне\";\nBlockly.Msg.MATH_IS_ODD = \"непарне\";\nBlockly.Msg.MATH_IS_POSITIVE = \"додатне\";\nBlockly.Msg.MATH_IS_PRIME = \"просте\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Перевіряє, чи число парне, непарне, просте, ціле, додатне, від'ємне або чи воно ділиться на певне число без остачі. Повертає істина або хибність.\";\nBlockly.Msg.MATH_IS_WHOLE = \"ціле\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://uk.wikipedia.org/wiki/Ділення_з_остачею\";\nBlockly.Msg.MATH_MODULO_TITLE = \"остача від %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Повертає остачу від ділення двох чисел.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://uk.wikipedia.org/wiki/Число\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Число.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"http://www.mapleprimes.com/questions/100441-Applying-Function-To-List-Of-Numbers\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"середнє списку\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"максимум списку\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"медіана списку\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"мінімум списку\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"моди списку\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"випадковий елемент списку\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"стандартне відхилення списку\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"сума списку\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Повертає середнє (арифметичне) числових значень у списку.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Повертає найбільше число у списку.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Повертає медіану списку.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Повертає найменше число у списку.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Повертає перелік найпоширеніших елементів у списку.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Повертає випадковий елемент зі списку.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Повертає стандартне відхилення списку.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Повертає суму всіх чисел у списку.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://uk.wikipedia.org/wiki/Генерація_випадкових_чисел\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"випадковий дріб\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Повертає випадковий дріб від 0,0 (включно) та 1.0 (не включно).\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://uk.wikipedia.org/wiki/Генерація_випадкових_чисел\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"випадкове ціле число від %1 до %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Повертає випадкове ціле число між двома заданими межами включно.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"округлити\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"округлити у меншу сторону\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"округлити у більшу сторону\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Округлення числа у більшу або меншу сторону.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://uk.wikipedia.org/wiki/Квадратний_корінь\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"модуль\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"квадратний корінь\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Повертає модуль числа.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Повертає e у степені.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Повертає натуральний логарифм числа.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Повертає десятковий логарифм числа.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Повертає протилежне число.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Повертає 10 у степені.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Повертає квадратний корінь числа.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://uk.wikipedia.org/wiki/Тригонометричні_функції\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Повертає арккосинус числа.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Повертає арксинус числа.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Повертає арктангенс числа.\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Повертає косинус кута у градусах (не у радіанах).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Повертає синус кута у градусах (не у радіанах).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Повертає тангенс кута у градусах (не у радіанах).\";\nBlockly.Msg.NEW_VARIABLE = \"Нова змінна...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Нове ім'я змінної:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"-ий.\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"з:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"блок тексту\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Запустити користувацьку функцію \\\"%1\\\".\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://uk.wikipedia.org/wiki/Підпрограма\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Запустити користувацьку функцію \\\"%1\\\" і використовувати її вивід.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Створити \\\"%1\\\"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"блок тексту\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://uk.wikipedia.org/wiki/Підпрограма\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"щось зробити\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"до\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Створює функцію без виводу.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://uk.wikipedia.org/wiki/Підпрограма\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"повернути\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Створює функцію з виводу.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Увага: ця функція має дубльовані параметри.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Визначення функції підсвітки\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Якщо значення true, то повернути друге значення.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Попередження: Цей блок може використовуватися лише в межах визначення функції.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"ім'я входу:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"вхід\";\nBlockly.Msg.REMOVE_COMMENT = \"Видалити коментар\";\nBlockly.Msg.RENAME_VARIABLE = \"Перейменувати змінну...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Перейменувати усі змінні \\\"%1\\\" до:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"додати текст\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_APPEND_TO = \"до\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Додати який-небудь текст змінній '%1'.\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"до нижнього регістру\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"Великі Перші Букви\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"до ВЕРХНЬОГО регістру\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Повернути копію тексту в іншому випадку.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"отримати перший символ\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"отримати символ # з кінця\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"отримати символ\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"у тексті\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"отримати останній символ\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"отримати випадковий символ\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"-ий.\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Повертає символ у зазначеній позиції.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"Додати елемент до тексту.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"приєднати\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Додати, видалити або змінити порядок розділів для переналаштування блокування тексту.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"до символу з кінця\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"до символу #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"до останнього символу\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"у тексті\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"отримати підрядок від першого символу\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"отримати підрядок від символу # з кінця\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"отримати підрядок від символу\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"-ого.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Повертає заданий фрагмент тексту.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"у тексті\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"знайти перше входження тексту\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"знайти останнє входження тексту\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \".\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Повертає індекс першого/останнього входження першого тексту у другому. Повертає 0, якщо текст не знайдений.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 є порожнім\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Повертає true, якщо вказаний текст порожній.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_8.html\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"створити текст з\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Створити фрагмент тексту шляхом приєднання будь-якого числа елементів.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"довжина %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Повертає число символів (включаючи пробіли) у даному тексті.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"друк %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"Надрукувати заданий текст, числа або інші символи.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Запитувати у користувача число.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Запитувати у користувача деякий текст.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"запит на число з повідомлення\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"запит на текст з повідомлення\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://uk.wikipedia.org/wiki/Рядок_(програмування)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Символ, слово або рядок тексту.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"викидати крайні пробіли з обох сторін\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"вилучати пробіли з лівого боку\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"вилучати пробіли з правого боку\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Повертає копію тексту з пробілами вилученими від одного або обох кінців.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"елемент\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Створити 'set %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Get\";\nBlockly.Msg.VARIABLES_GET_TAIL = \"значення\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"значення\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Повертає значення цієї змінної.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Створити 'get %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"до\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"встановити\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Задає цю змінну рівною вводу.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/vi.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.vi');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"Thêm Chú Giải\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"Thay giá trị thành:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"Thu Nhỏ Mọi Mảnh\";\nBlockly.Msg.COLLAPSE_BLOCK = \"Thu Nhỏ Mảnh\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"màu 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"màu 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"tỉ lệ\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"pha\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"Pha hai màu với nhau theo tỉ lệ (0 - 100).\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://vi.wikipedia.org/wiki/M%C3%A0u_s%E1%BA%AFc\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"Chọn một màu từ bảng màu.\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"màu bất kỳ\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"chọn một màu bất kỳ.\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"màu xanh dương\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"màu xanh lá cây\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"màu đỏ\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"Tạo màu từ\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"Tạo màu từ ba màu: đỏ, xanh lá cây, xanh dương với số lượng cụ thể.  Mỗi số phải có giá trị từ 0 đến 100.\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"thoát\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"sang lần lặp tiếp theo\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"Thoát khỏi vòng lặp hiện tại.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"Bỏ qua phần còn lại trong vòng lặp này, và sang lần lặp tiếp theo.\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"Chú ý: Mảnh này chỉ có thế dùng trong các vòng lặp.\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"trong danh sách\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"với mỗi thành phần\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"Trong một danh sách, lấy từng thành phần, gán vào biến \\\"%1\\\", rồi thực hiện một số lệnh.\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"từ %1 đến %2 mỗi lần thêm %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"đếm theo\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"Đếm từ số đầu đến số cuối. Khi đến mỗi số, gán số vào biến \\\"%1\\\" rồi thực hiện các lệnh.\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"Thêm một điều kiện vào mảnh nếu.\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"Cuối cùng, khi không điều kiện nào đúng.\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"Thêm, bỏ, hoặc đổi thứ tự các mảnh con để tạo cấu trúc mới cho mảnh nếu.\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"nếu không\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"nếu không nếu\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"nếu\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"Nếu điều kiện đúng, thực hiện các lệnh.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"Nếu điều kiện đúng, thực hiện các lệnh đầu.  Nếu sai, thực hiện các lệnh sau.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"Nếu điều kiện đúng, thực hiện các lệnh đầu.  Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai.\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"Nếu điều kiện đúng, thực hiện các lệnh đầu.  Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai.  Nếu không điều kiện nào đúng, thực hiện các lệnh cuối cùng.\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"thực hiện\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"lặp lại %1 lần\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"lặp lại\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"lần\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"Thực hiện các lệnh vài lần.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"lặp lại cho đến khi\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"lặp lại trong khi\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"Miễn là điều kiện còn sai, thì thực hiện các lệnh.  Khi điều kiện đúng thì ngưng.\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"Miễn là điều kiện còn đúng, thì thực hiện các lệnh.\";\nBlockly.Msg.DELETE_BLOCK = \"Xóa Mảnh Này\";\nBlockly.Msg.DELETE_X_BLOCKS = \"Xóa %1 Mảnh\";\nBlockly.Msg.DISABLE_BLOCK = \"Ngưng Tác Dụng\";\nBlockly.Msg.DUPLICATE_BLOCK = \"Tạo Bản Sao\";\nBlockly.Msg.CLEAR_BLOCKS = \"Clear all blocks\";\nBlockly.Msg.ENABLE_BLOCK = \"Phục Hồi Tác Dụng\";\nBlockly.Msg.EXPAND_ALL = \"Mở Lớn Mọi Mảnh\";\nBlockly.Msg.EXPAND_BLOCK = \"Mở Lớn Mảnh\";\nBlockly.Msg.EXTERNAL_INPUTS = \"Chỗ Gắn Bên Ngoài\";\nBlockly.Msg.HELP = \"Trợ Giúp\";\nBlockly.Msg.INLINE_INPUTS = \"Chỗ Gắn Cùng Dòng\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"tạo danh sách trống\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"Hoàn trả một danh sách, với độ dài 0, không có thành tố nào cả\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"danh sách\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh danh sách này.\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"tạo danh sách gồm\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"Thêm vật vào danh sách.\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"Tạo một danh sách bao gồm nhiều vậts, với một số lượng bất kỳ.\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"đầu tiên\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"(đếm từ cuối) thứ\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"thứ\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"lấy thành tố\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"lấy và xóa thành tố\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"cuối cùng\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"bất kỳ\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"xóa thành tố\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"Hoàn trả thành tố đầu tiên trong danh sách.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"Hoàn trả thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố cuối cùng.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"Hoàn trả thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố đầu tiên.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"Hoàn trả thành tố cuối cùng trong danh sách.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"Hoàn trả một thành tố bất kỳ trong danh sách.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"Hoàn trả và xóa thành tố đầu tiên trong danh sách.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"Hoàn trả và xóa thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố cuối cùng.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"Hoàn trả và xóa thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố đầu tiên.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"Hoàn trả và xóa thành tố cuối cùng trong danh sách.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"Hoàn trả và xóa mộtthành tố bất kỳ trong danh sách.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"Xóa thành tố đầu tiên trong danh sách.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"Xóa thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố cuối cùng.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"Xóa thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố đầu tiên.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"Xóa thành tố cuối cùng trong danh sách.\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"Xóa thành tố bất kỳ trong danh sách.\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"đến (đếm từ cuối) thứ\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"đến thứ\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"đến cuối cùng\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"lấy một danh sách con từ đầu tiên\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"lấy một danh sách con từ (đếm từ cuối) thứ\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"lấy một danh sách con từ thứ\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"Lấy một mảng của danh sách này để tạo danh sách con.\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"tìm sự có mặt đầu tiên của vật\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"tìm sự có mặt cuối cùng của vật\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"Hoàn trả vị trí xuất hiện đầu/cuối của vật trong danh sách.  Nếu không tìm thấy thì hoàn trả số 0.\";\nBlockly.Msg.LISTS_INLIST = \"trong dánh sách\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 trống rỗng\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"độ dài của %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"Hoàn trả độ dài của một danh sách.\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"tạo danh sách gồm một vật %1 lặp lại %2 lần\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"Tạo danh sách gồm một số lượng vật nhất định với mỗi vật đều giống nhau.\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"giá trị\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"gắn chèn vào vị trí\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"đặt thành tố\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"Gắn chèn vật vào đầu danh sách.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"Gắn chèn vật vào danh sách theo vị trí ấn định từ phía cuối.  #1 là thành tố cuối cùng.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"Gắn chèn vật vào danh sách theo vị trí ấn định.  #1 là thành tố đầu tiên.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"Gắn thêm vật vào cuối danh sách.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"Gắn chèn vật vào danh sách ở vị trí ngẫu nhiên.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"Đặt giá trị của thành tố đầu tiên trong danh sách.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"Đặt giá trị của thành tố trong một danh sách ở vị trí ấn định từ phía cuối.  #1 là thành tố cuối cùng.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"Đặt giá trị của thành tố ở vị trí ấn định trong một danh sách.  #1 là thành tố đầu tiên.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"Đặt giá trị của thành tố cuối cùng trong danh sách.\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"Đặt giá trị của thành tố ngẫu nhiên trong danh sách.\";\nBlockly.Msg.LISTS_TOOLTIP = \"Hoàn trả “đúng\\\" nếu danh sách không có thành tử nào.\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"sai\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"Hoàn trả \\\"đúng\\\" hoặc \\\"sai\\\".\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"đúng\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://vi.wikipedia.org/wiki/B%E1%BA%A5t_%C4%91%E1%BA%B3ng_th%E1%BB%A9c\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu giá trị hai đầu vào bằng nhau.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu đầu vào thứ nhất lớn hơn đầu vào thứ hai.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu đầu vào thứ nhất lớn hơn hoặc bằng đầu vào thứ hai.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu đầu vào thứ nhất nhỏ hơn đầu vào thứ hai.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu đầu vào thứ nhất nhỏ hơn hoặc bằng đầu vào thứ hai.\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu giá trị hai đầu vào không bằng nhau.\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"không %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"Hoàn trả \\\"đúng\\\" (true) nếu đầu vào sai.  Hoàn trả \\\"sai\\\" (false) nếu đầu vào đúng.\";\nBlockly.Msg.LOGIC_NULL = \"trống không\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"Hoàn trả trống không.\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"và\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"hoặc\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"Hoàn trả \\\"đúng\\\" (true) nếu cả hai đầu vào đều đúng.\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"Hoàn trả \\\"đúng\\\" (true) nếu ít nhất một trong hai đầu vào đúng.\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"kiểm tra\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"nếu sai\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"nếu đúng\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"Kiểm tra điều kiện. Nếu điều kiện đúng, hoàn trả giá trị từ mệnh đề \\\"nếu đúng\\\" nếu không đúng, hoàn trả giá trị từ mệnh đề \\\"nếu sai\\\".\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://vi.wikipedia.org/wiki/S%E1%BB%91_h%E1%BB%8Dc\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"Hoàn trả tổng của hai con số.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"Hoàn trả thương của hai con số.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"Hoàn trả hiệu của hai con số.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"Hoàn trả tích của hai con số.\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"Hoàn trả số lũy thừa với số thứ nhất là cơ số và số thứ hai là số mũ.\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://vi.wikipedia.org/wiki/Ph%C3%A9p_c%E1%BB%99ng\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"giá trị\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"cộng vào\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"Cộng số đầu vào vào biến \\\"%1\\\".\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"Hoàn trả các đẳng số thường gặp: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (vô cực).\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"giới hạn %1 không dưới %2 không hơn %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"Giới hạn số đầu vào để không dưới số thứ nhất và không hơn số thứ hai.\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"chia hết cho\";\nBlockly.Msg.MATH_IS_EVEN = \"chẵn\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"là số âm\";\nBlockly.Msg.MATH_IS_ODD = \"lẻ\";\nBlockly.Msg.MATH_IS_POSITIVE = \"là số dương\";\nBlockly.Msg.MATH_IS_PRIME = \"là số nguyên tố\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"Kiểm tra con số xem nó có phải là số chẵn, lẻ, nguyên tố, nguyên, dương, âm,  hay xem nó có chia hết cho số đầu vào hay không.  Hoàn trả đúng hay sai.\";\nBlockly.Msg.MATH_IS_WHOLE = \"là số nguyên\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"số dư của %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"Chia số thứ nhất cho số thứ hai rồi hoàn trả số dư từ.\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://vi.wikipedia.org/wiki/S%E1%BB%91\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"Một con số.\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"giá trị trung bình của một danh sách\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"số lớn nhât của một danh sách\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"số trung vị của một danh sách\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"số nhỏ nhất của một danh sách\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"các mode của một danh sách\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"một số bất kỳ của một danh sách\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"độ lệch chuẩn của một danh sách\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"tổng của một danh sách\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"Hoàn trả giá trị trung bình từ của danh sách số.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"Hoàn trả số lớn nhất trong tất cả các số trong danh sách.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"Hoàn trả số trung vị của danh sách số.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"Hoàn trả số nhỏ nhất trong tất cả các số trong danh sách.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"Hoàn trả các số có mặt nhiều nhất trong danh sách.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"Hoàn trả một số bất kỳ từ các số trong danh sách.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"Hoàn trả độ lệch chuẩn của danh sách số.\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"Hoàn trả tổng số của tất cả các số trong danh sách.\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"phân số bất kỳ\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"Hoàn trả một phân số bất kỳ không nhỏ hơn 0.0 và không lớn hơn 1.0.\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"Một số nguyên bất kỳ từ %1 đến %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"Hoàn trả một số nguyên bất kỳ lớn hơn hoặc bằng số đầu và nhỏ hơn hoặc bằng số sau.\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"làm tròn\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"làm tròn xuống\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"làm tròn lên\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"Làm tròn lên hoặc tròn xuống số đầu vào.\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://vi.wikipedia.org/wiki/C%C4%83n_b%E1%BA%ADc_hai\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"giá trị tuyệt đối\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"căn bật hai\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"Hoàn trả giá trị tuyệt đối của số đầu vào.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"Hoàn trả lũy thừa của số e với số mũ đầu vào.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"Hoàn trả lôgarit tự nhiên của số đầu vào.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"Hoàn trả lôgarit cơ số 10 của số đầu vào.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"Đổi dấu của số đầu vào: âm thành dương và dương thành âm, và hoàn trả số mới.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"Hoàn trả lũy thừa của số 10 với số mũ đầu vào.\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"Hoàn trả căn bật hai của số đầu vào.\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://vi.wikipedia.org/wiki/H%C3%A0m_l%C6%B0%E1%BB%A3ng_gi%C3%A1c\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"Hoàn trả Arccos của một góc (theo độ).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"Hoàn trả Arcsin của một góc (theo độ).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"Hoàn trả Arctang của một góc (theo độ).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"Hoàn trả Cos của một góc (theo độ).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"Hoàn trả Sin của một góc (theo độ).\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"Hoàn trả Tang của một góc (theo độ).\";\nBlockly.Msg.NEW_VARIABLE = \"Biến mới...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"Tên của biến mới:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"với:\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"thực hiện\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/procedure _ %28computer_science% 29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"Chạy một thủ tục không có giá trị hoàn trả.\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/procedure _ %28computer_science% 29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"Chạy một thủ tục có giá trị hoàn trả.\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"Tạo mảnh \\\"thực hiện %1\\\"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"thủ tục\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"Một thủ tục không có giá trị hoàn trả.\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"hoàn trả\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"Một thủ tục có giá trị hoàn trả.\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"Chú ý: Thủ tục này có lặp lại tên các tham số.\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"Làm nổi bật thủ tục\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"Khi điều kiện đúng thì hoàn trả một giá trị.\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"Chú ý: Mảnh này chỉ có thể dùng trong một thủ tục.\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"biến:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"các tham số\";\nBlockly.Msg.REMOVE_COMMENT = \"Xóa Chú Giải\";\nBlockly.Msg.RENAME_VARIABLE = \"Thay tên biến...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"Thay tên tất cả \\\"%1\\\" biến này thành:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"thêm văn bản\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"ở cuối\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"Thêm một mảng văn bản vào biến \\\"%1\\\".\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"thành chữ thường\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"thành Chữ In Đầu Mỗi Từ\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"thành CHỮ IN HOA\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"Hoàn trả văn bản sau khi chuyển đổi chữ in hoa hay thường.\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"lấy ký tự đầu tiên\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"lấy từ phía cuối, ký tự thứ\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"lấy ký tự thứ\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"trong văn bản\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"lấy ký tự cuối cùng\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"lấy ký tự bất kỳ\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"Hoàn trả ký tự ở vị trí đặt ra.\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"thêm vật mới vào văn bản.\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"kết nối\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh văn bản này.\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"đến từ phía cuối, ký tự thứ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"đến ký tự thứ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"đến ký tự cuối cùng\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"trong văn bản\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"lấy từ ký tự đầu tiên\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"lấy từ phía cuối, ký tự thứ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"lấy từ ký tự thứ\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"Hoàn trả một mảng ký tự ấn định từ trong văn bản.\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"trong văn bản\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"tìm sự có mặt đầu tiên của\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"tìm sự có mặt cuối cùng của\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"Hoàn trả vị trí xuất hiện đầu/cuối của văn bản thứ nhất trong văn bản thứ hai.  Nếu không tìm thấy thì hoàn trả số 0.\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 trống không\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"Hoàn trả “đúng nếu văn bản không có ký tự nào.\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"tạo văn bản từ\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"Tạo một văn bản từ các thành phần.\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"độ dài của %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"Hoàn trả số lượng ký tự (kể cả khoảng trắng) trong văn bản đầu vào.\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"in lên màng hình %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"In ra màng hình một văn bản, con số, hay một giá trị đầu vào khác.\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"Xin người dùng nhập vào một con số.\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"Xin người dùng nhập vào một văn bản.\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"Xin người dùng nhập vào con số với dòng hướng dẫn\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"Xin người dùng nhập vào văn bản với dòng hướng dẫn\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/string _(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"Một ký tự, một từ, hay một dòng.\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"cắt các không gian từ cả hai mặt của\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"cắt các không gian từ bên trái của\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"cắt các không gian từ bên phải của\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"Hoàn trả bản sao của văn bản sau khi xóa khoảng trắng từ một hoặc hai bên.\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"vật\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"Tạo mảnh \\\"đặt vào %1\\\"\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"Hoàn trả giá trị của.\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"Tạo mảnh \\\"lấy %1\\\"\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"bằng\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"cho\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"Đặt giá trị của biến này thành...\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/zh-hans.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.zh-hans');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"添加注释\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"更改值：\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"折叠块\";\nBlockly.Msg.COLLAPSE_BLOCK = \"折叠块\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"颜色1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"颜色2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"比例\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"混合\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"用一个给定的比率(0.0-1.0)混合两种颜色。\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://zh.wikipedia.org/wiki/颜色\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"从调色板中选择一种颜色。\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"随机颜色\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"随机选择一种颜色。\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"蓝色\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"绿色\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"红色\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"颜色\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"通过指定红色、绿色和蓝色的量创建一种颜色。所有的值必须介于0和100之间。\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"中断循环\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"继续下一次循环\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"中断包含它的循环。\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"跳过这个循环的剩余部分，并继续下一次迭代。\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"警告：此块仅可用于在一个循环内。\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"在列表中\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"为每个项目\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"遍历每个列表中的项目，将变量“%1”设定到该项中，然后执行某些语句。\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"从范围 %1 到 %2 每隔 %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"使用\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"从起始数到结尾数中取出变量“%1”的值，按指定的时间间隔，执行指定的块。\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"在if语句块中增加一个条件。\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"添加一个最终的，包括所有情况的节到if块中。\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"增加、删除或重新排列各节来重新配置“if”块。\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"否则\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"否则如果\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"如果\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"如果值为真，执行一些语句。\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"如果值为真，则执行语句的第一块；否则，则执行语句的第二块。\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"如果第一个值为真，则执行语句的第一个块；否则，如果第二个值为真，则执行语句的第二块。\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"如果第一个值为真，则执行语句的第一块；否则，如果第二个值为真，则执行语句的第二块；如果没有值为真，则执行语句的最后一块。\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://zh.wikipedia.org/wiki/For回圈\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"执行\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"重复 %1 次\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"重复\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"次\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"多次执行一些语句。\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"重复直到\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"重复当\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"只要值为假，执行一些语句。\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"只要值为真，执行一些语句。\";\nBlockly.Msg.DELETE_BLOCK = \"删除块\";\nBlockly.Msg.DELETE_X_BLOCKS = \"删除 %1 块\";\nBlockly.Msg.DISABLE_BLOCK = \"禁用块\";\nBlockly.Msg.DUPLICATE_BLOCK = \"复制\";\nBlockly.Msg.ENABLE_BLOCK = \"启用块\";\nBlockly.Msg.EXPAND_ALL = \"展开块\";\nBlockly.Msg.EXPAND_BLOCK = \"展开块\";\nBlockly.Msg.EXTERNAL_INPUTS = \"外部输入\";\nBlockly.Msg.HELP = \"帮助\";\nBlockly.Msg.INLINE_INPUTS = \"单行输入\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"创建空列表\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"返回一个列表，长度为 0，不包含任何数据记录\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"列表\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"增加、删除或重新排列各部分以此重新配置这个列表块。\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"建立字串使用\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"将一个项添加到列表中。\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"建立一个具有任意数量项目的列表。\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"第一\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"倒数第#\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";\nBlockly.Msg.LISTS_GET_INDEX_GET = \"获得\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"取出并移除\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"最后\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"随机\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"移除\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"空白\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"返回列表中的第一个项目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"返回在列表中的指定位置的项。#1是最后一项。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"返回在列表中的指定位置的项。#1是第一个项目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"返回列表中的最后一项。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"随机返回列表中的一个项目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"移除并返回列表中的第一个项目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"移除并返回列表中的指定位置的项。#1 是最后一项。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"移除并返回列表中的指定位置的项。#1 是第一项。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"移除并返回列表中的最后一个项目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"移除并返回列表中的一个随机项目中。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"移除列表中的第一项\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"删除在列表中的指定位置的项。#1是最后一项。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"移除在列表中的指定位置的项。#1 是第一项。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"移除列表中的最后一项\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"删除列表中的一个随机的项。\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"到倒数第#\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"到#\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"到最后\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"从头获得子列表\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"从倒数#取得子列表\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"从#取得子列表\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"空白\";\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"复制列表中指定的部分。\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"找出第一个项出现\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"找出最后一个项出现\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"返回在列表中的第一/最后一个匹配项的索引值。如果未找到则返回 0。\";\nBlockly.Msg.LISTS_INLIST = \"在列表中\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1是空的\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";\nBlockly.Msg.LISTS_LENGTH_TITLE = \"%1的长度\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"返回列表的长度。\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";\nBlockly.Msg.LISTS_REPEAT_TITLE = \"建立列表使用项 %1 重复 %2 次\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"建立包含指定重复次数的值的列表。\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"为\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"插入在\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"设置\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"在列表的起始处添加该项。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"插入在列表中的指定位置的项。#1是最后一项。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"插入在列表中指定位置的项。#1是第一项。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"将该项追加到列表的末尾。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"在列表中随机插入项。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"设置列表中的第一个项目。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"设置在列表中指定位置的项。#1是最后一项。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"设置在列表中指定位置的项。#1是第一项。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"设置列表中的最后一项。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"设置列表中一个随机的项目。\";\nBlockly.Msg.LISTS_TOOLTIP = \"如果改列表为空，则返回真。\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"错\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"同时返回真或假。\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"真\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://zh.wikipedia.org/wiki/不等\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"如果两个输入结果相等，则返回真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"如果第一个输入结果比第二个大，则返回真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"如果第一个输入结果大于或等于第二个输入结果，则返回真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"如果第一个输入结果比第二个小，则返回真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"如果第一个输入结果小于或等于第二个输入结果，则返回真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"如果两个输入结果不相等，则返回真。\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"并非%1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"如果输入结果为假，则返回真；如果输入结果为真，则返回假。\";\nBlockly.Msg.LOGIC_NULL = \"空\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"返回空值。\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"和\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"或\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"如果两个输入结果都为真，则返回真。\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"如果至少有一个输入结果为真，则返回真。\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"测试\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://zh.wikipedia.org/wiki/条件运算符\";\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"如果为假\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"如果为真\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"检查“test”中的条件。如果条件为真，则返回“if true”的值，否则，则返回“if false”的值。\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://zh.wikipedia.org/wiki/算术\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"返回两个数字的和。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"返回两个数字的商。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"返回两个数字的区别。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"返回两个数字的乘积。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"返回第一个数的第二个数次幂。\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://zh.wikipedia.org/wiki/%E5%8A%A0%E6%B3%95\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"由\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"更改\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"将一个数添加到变量“%1”。\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://zh.wikipedia.org/wiki/数学常数\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"返回一个常见常量：π (3.141......)，e (2.718...)、φ (1.618...)、 sqrt(2) (1.414......)、sqrt(½) (0.707......)或 ∞（无穷大）。\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"限制数字 %1 介于 (低) %2 到 (高) %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"限制数字介于两个指定的数字之间\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"可被整除\";\nBlockly.Msg.MATH_IS_EVEN = \"是偶数\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"为负\";\nBlockly.Msg.MATH_IS_ODD = \"是奇数\";\nBlockly.Msg.MATH_IS_POSITIVE = \"是正值\";\nBlockly.Msg.MATH_IS_PRIME = \"是质数\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"如果数字是偶数、奇数、非负整数、正数、负数或如果它可被某数字整除，则返回真或假。\";\nBlockly.Msg.MATH_IS_WHOLE = \"为整数\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://zh.wikipedia.org/wiki/%E6%A8%A1%E9%99%A4\";\nBlockly.Msg.MATH_MODULO_TITLE = \"取余数自 %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"返回这两个数字相除后的余数。\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://zh.wikipedia.org/wiki/数字\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"一个数字。\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"列表中的平均数\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"列表中的最大值\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"列表中位数\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"列表中的最小值\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"列表模式\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"列表的随机项\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"列表中的标准差\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"列表中的数的总和\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"返回列表中的数值的平均值。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"返回列表中最大数。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"返回列表中的中位数。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"返回列表中最小数。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"返回列表中的最常见的项的列表。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"从列表中返回一个随机的元素。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"返回列表的标准偏差。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"返回列表中的所有数字的和。\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://zh.wikipedia.org/wiki/随机数发生器\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"随机分数\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"返回介于（包含）0.0到1.0之间的随机数。\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://zh.wikipedia.org/wiki/随机数发生器\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"从 %1 到 %2 之间的随机整数\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"返回两个指定的范围（含）之间的随机整数。\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://zh.wikipedia.org/wiki/四舍五入\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"向下舍入\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"向下舍入\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"向上舍入\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"数字向上或向下舍入。\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://zh.wikipedia.org/wiki/平方根\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"绝对\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"平方根\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"返回一个数的绝对值。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"返回数的e次幂。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"返回一个数的自然对数。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"返回数字的对数。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"返回数的逻辑非。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"返回数的10次幂。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"返回数的平方根。\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://zh.wikipedia.org/wiki/三角函数\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"返回一个数的反余弦值。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"返回一个数的反正弦值。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"返回指定角度的反正切值。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"返回指定角度的余弦值(非弧度）。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"返回指定角度的正弦值(非弧度）。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"返回指定角度的正切值(非弧度）。\";\nBlockly.Msg.NEW_VARIABLE = \"新变量...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"新变量的名称：\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"空白\";\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"与：\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"空白\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://zh.wikipedia.org/wiki/子程序\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"运行用户定义的函数“%1”。\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://zh.wikipedia.org/wiki/子程序\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"运行用户定义的函数“%1”，并使用它的输出值。\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"创建“%1”\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"空白\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://zh.wikipedia.org/wiki/子程序\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"做点什么\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"至\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"创建一个不带输出值的函数。\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://zh.wikipedia.org/wiki/子程序\";\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"返回\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"创建一个有输出值的函数。\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"警告: 此函数具有重复参数。\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"突出显示函数定义\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"如果值为真，则返回第二个值。\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"警告: 仅在定义函数内可使用此块。\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"输入名称：\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"參數\";\nBlockly.Msg.REMOVE_COMMENT = \"删除注释\";\nBlockly.Msg.RENAME_VARIABLE = \"重命名变量...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"将所有“%1”变量重命名为:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"追加文本\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_APPEND_TO = \"在\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"将一些文本追加到变量“%1”。\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"为小写\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"为首字母大写\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"为大写\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"使用不同的大小写复制这段文字。\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"获得第一个字符\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"获得倒数第#个字符\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"获得字符#\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"于文本中\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"获得最后一个字符\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"获取随机的字母\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"空白\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"返回位于指定位置的字母。\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"将一个项添加到文本中。\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"加入\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"添加、删除或重新排列各节来重新配置这个文本块。\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"到倒数第#个字符\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"到字符#\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"到最后一个字符\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"自文本\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"取得一段字串自第一个字符\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"取得一段字串自#到末尾\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"取得一段字串自#\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"空白\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"返回指定的部分文本。\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"自文本\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"寻找第一个出现的文本\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"寻找最后一个出现的文本\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"空白\";\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"返回在第二个字串中的第一/最后一个匹配项的索引值。如果未找到则返回 0。\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1是空的\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"如果提供的文本为空，则返回真。\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"建立字串使用\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"通过串起任意数量的项以建立一段文字。\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";\nBlockly.Msg.TEXT_LENGTH_TITLE = \"%1的长度\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"返回文本的字符数（包括空格）。\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";\nBlockly.Msg.TEXT_PRINT_TITLE = \"打印%1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"打印指定的文字、数字或其他值。\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"提示用户输入数字。\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"提示用户输入一些文本。\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"输入数字并显示提示消息\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"输入数字并显示提示消息\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://zh.wikipedia.org/wiki/字符串\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"一个字母、单词或一行文本。\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"消除两侧空格\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"消除左侧空格\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"消除右侧空格\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"复制这段文字的同时删除两端多余的空格。\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"项\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"创建“设定%1”\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"空白\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"空白\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"返回此变量的值。\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"创建“获得%1”\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"http://code.google.com/p/blockly/wiki/Variables#Set\";\nBlockly.Msg.VARIABLES_SET_TAIL = \"到\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"赋值\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"设置此变量，以使它和输入值相等。\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/js/zh-hant.js",
    "content": "// This file was automatically generated.  Do not modify.\n\n'use strict';\n\ngoog.provide('Blockly.Msg.zh-hant');\n\ngoog.require('Blockly.Msg');\n\nBlockly.Msg.ADD_COMMENT = \"加入註解\";\nBlockly.Msg.CHANGE_VALUE_TITLE = \"修改值:\";\nBlockly.Msg.CHAT = \"Chat with your collaborator by typing in this box!\";  // untranslated\nBlockly.Msg.COLLAPSE_ALL = \"收合積木\";\nBlockly.Msg.COLLAPSE_BLOCK = \"收合積木\";\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = \"顏色 1\";\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = \"顏色 2\";\nBlockly.Msg.COLOUR_BLEND_HELPURL = \"http://meyerweb.com/eric/tools/color-blend/\";  // untranslated\nBlockly.Msg.COLOUR_BLEND_RATIO = \"比例\";\nBlockly.Msg.COLOUR_BLEND_TITLE = \"混合\";\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = \"透過一個比率 (0.0-1.0)來混合兩種顏色。\";\nBlockly.Msg.COLOUR_PICKER_HELPURL = \"https://en.wikipedia.org/wiki/Color\";\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = \"從調色板中選擇一種顏色。\";\nBlockly.Msg.COLOUR_RANDOM_HELPURL = \"http://randomcolour.com\";  // untranslated\nBlockly.Msg.COLOUR_RANDOM_TITLE = \"隨機顏色\";\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = \"隨機選擇一種顏色。\";\nBlockly.Msg.COLOUR_RGB_BLUE = \"藍\";\nBlockly.Msg.COLOUR_RGB_GREEN = \"綠\";\nBlockly.Msg.COLOUR_RGB_HELPURL = \"http://www.december.com/html/spec/colorper.html\";  // untranslated\nBlockly.Msg.COLOUR_RGB_RED = \"紅\";\nBlockly.Msg.COLOUR_RGB_TITLE = \"顏色\";\nBlockly.Msg.COLOUR_RGB_TOOLTIP = \"透過指定紅、綠、 藍色的值來建立一種顏色。所有的值必須介於 0 和 100 之間。\";\nBlockly.Msg.CONTEXT_BLOCK_COPY = \"Copy\";  // untranslated\nBlockly.Msg.CONTEXT_BLOCK_PASTE = \"Paste\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\";  // untranslated\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = \"停止 迴圈\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = \"繼續下一個 迴圈\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = \"離開當前的 迴圈\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = \"跳過這個迴圈的其餘步驟，並繼續下一次的迴圈運算。\";\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = \"警告： 此積木僅可用於迴圈內。\";\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\";  // untranslated\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = \"自列表\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = \"\";\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = \"取出每個\";\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = \"遍歷每個列表中的項目，將變量  '%1' 設定到該項目中，然後執行某些語句\";\nBlockly.Msg.CONTROLS_FOR_HELPURL = \"https://code.google.com/p/blockly/wiki/Loops#count_with\";  // untranslated\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = \"從範圍 %1 到 %2 每隔 %3\";\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = \"使用\";\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = \"從起始數到結尾數中取出變數 %1 的值，按指定的時間間隔，執行指定的積木。\";\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = \"將條件添加到'如果'積木。\";\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = \"加入一個最終，所有條件下都都執行的區塊到'如果'積木中\";\nBlockly.Msg.CONTROLS_IF_HELPURL = \"https://code.google.com/p/blockly/wiki/If_Then\";  // untranslated\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = \"添加、 刪除或重新排列各區塊來此重新配置這個'如果'積木。\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = \"否則\";\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = \"否則如果\";\nBlockly.Msg.CONTROLS_IF_MSG_IF = \"如果\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = \"當值為真時，執行一些語句\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = \"當值為真時，執行第一個語句，否則則執行第二個語句\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = \"如果第一個值為真，則執行第一個語句。否則當第二個值為真時，則執行第二個語句\";\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = \"如果第一個值為真，則執行第一個語句。否則當第二個值為真時，則執行第二個語句。如果前幾個敘述都不為真，則執行最後一個語句\";\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = \"https://en.wikipedia.org/wiki/For_loop\";\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = \"執行\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE = \"重複 %1 次\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = \"重複\";\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = \"次數\";\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = \"多次執行一些語句\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = \"https://code.google.com/p/blockly/wiki/Repeat\";  // untranslated\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = \"重複 直到\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = \"重複 當\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = \"當值為否時，執行一些語句\";\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = \"當值為真時，執行一些語句\";\nBlockly.Msg.DELETE_BLOCK = \"刪除積木\";\nBlockly.Msg.DELETE_X_BLOCKS = \"刪除 %1 塊積木\";\nBlockly.Msg.DISABLE_BLOCK = \"停用積木\";\nBlockly.Msg.DUPLICATE_BLOCK = \"複製\";\nBlockly.Msg.ENABLE_BLOCK = \"啟用積木\";\nBlockly.Msg.EXPAND_ALL = \"展開積木\";\nBlockly.Msg.EXPAND_BLOCK = \"展開積木\";\nBlockly.Msg.EXTERNAL_INPUTS = \"多行輸入\";\nBlockly.Msg.HELP = \"說明\";\nBlockly.Msg.INLINE_INPUTS = \"單行輸入\";\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\";  // untranslated\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = \"建立空列表\";\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = \"返回一個長度為 0 的列表，不包含任何資料記錄\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = \"加入\";\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = \"添加、 刪除或重新排列各區塊來此重新配置這個 列表 積木。\";\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = \"使用這些值建立列表\";\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = \"將一個項目加入到列表中。\";\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = \"建立一個具備任意數量項目的列表。\";\nBlockly.Msg.LISTS_GET_INDEX_FIRST = \"第一筆\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = \"倒數第#筆\";\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = \"#\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_GET = \"取值\";\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = \"取出並移除\";\nBlockly.Msg.LISTS_GET_INDEX_LAST = \"最後一筆\";\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = \"隨機\";\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = \"移除\";\nBlockly.Msg.LISTS_GET_INDEX_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = \"返回列表中的第一個項目\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = \"返回在列表中的指定位置的項目。#1 是最後一個項目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = \"返回在列表中的指定位置的項目。#1 是第一個項目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = \"返回列表中的最後一個項目\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = \"返回列表中隨機的一個項目\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = \"移除並返回列表中的第一個項目\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = \"移除並返回列表中的指定位置的項目。#1 是最後一個項目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = \"移除並返回列表中的指定位置的項目。#1 是第一個項目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = \"移除並返回列表中的最後一個項目\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = \"移除並返回列表中的隨機一個項目\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = \"移除列表中的第一個項目\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = \"移除在列表中的指定位置的項目。#1 是最後一個項目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = \"移除在列表中的指定位置的項目。#1 是第一個項目。\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = \"移除列表中的最後一個項目\";\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = \"移除列表中隨機的一個項目\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = \"到 倒數 # 位\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = \"到 #\";\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = \"到 最後\";\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = \"從 頭 取得子列表\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = \"從倒數 # 取得子列表\";\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = \"從 # 取得子列表\";\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = \"\";  // untranslated\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = \"複製列表中指定的部分。\";\nBlockly.Msg.LISTS_INDEX_OF_FIRST = \"找出 第一個 項目出現\";\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\";  // untranslated\nBlockly.Msg.LISTS_INDEX_OF_LAST = \"找出 最後一個 項目出現\";\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = \"返回在列表中的第一個/最後一個匹配項目的索引值。如果未找到則返回 0。\";\nBlockly.Msg.LISTS_INLIST = \"自列表\";\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#is_empty\";  // untranslated\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = \"%1 值為空\";\nBlockly.Msg.LISTS_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#length_of\";  // untranslated\nBlockly.Msg.LISTS_LENGTH_TITLE = \"長度 %1\";\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = \"返回列表的長度。\";\nBlockly.Msg.LISTS_REPEAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\";  // untranslated\nBlockly.Msg.LISTS_REPEAT_TITLE = \"建立列表使用項目 %1 重複 %2 次數\";\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = \"建立包含指定重複次數的 值 的列表。\";\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\";  // untranslated\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = \"為\";\nBlockly.Msg.LISTS_SET_INDEX_INSERT = \"插入到\";\nBlockly.Msg.LISTS_SET_INDEX_SET = \"設定\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = \"在列表的起始處添加一個項目。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = \"插入在列表中的指定位置的項目。#1 是最後一個項目。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = \"插入在列表中的指定位置的項目。#1 是第一個項目。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = \"在列表的尾端加入一個項目\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = \"在列表中隨機插入項目\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = \"設定列表中的第一個項目\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = \"設定在列表中的指定位置的項目。#1 是最後一個項目。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = \"設定在列表中的指定位置的項目。#1 是第一個項目。\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = \"設定列表中的最後一個項目\";\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = \"設定列表中隨機的一個項目\";\nBlockly.Msg.LISTS_TOOLTIP = \"如果該列表為空，則返回 真。\";\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = \"否\";\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = \"https://code.google.com/p/blockly/wiki/True_False\";  // untranslated\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = \"返回 真 或 否。\";\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = \"真\";\nBlockly.Msg.LOGIC_COMPARE_HELPURL = \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = \"如果這兩個輸入區塊內容相等，返回 真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = \"如果第一個輸入大於第二個輸入，返回 真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = \"如果第一個輸入大於或等於第二個輸入，返回 真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = \"如果第一個輸入小於第二個輸入，返回 真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = \"如果第一個輸入是小於或等於第二個輸入，返回 真。\";\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = \"如果這兩個輸入區塊內容不相等，返回 真。\";\nBlockly.Msg.LOGIC_NEGATE_HELPURL = \"https://code.google.com/p/blockly/wiki/Not\";  // untranslated\nBlockly.Msg.LOGIC_NEGATE_TITLE = \"非 %1\";\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = \"如果輸入的值是 否，則返回 真。如果輸入的值是 真 返回 否。\";\nBlockly.Msg.LOGIC_NULL = \"空\";\nBlockly.Msg.LOGIC_NULL_HELPURL = \"https://en.wikipedia.org/wiki/Nullable_type\";  // untranslated\nBlockly.Msg.LOGIC_NULL_TOOLTIP = \"返回 空。\";\nBlockly.Msg.LOGIC_OPERATION_AND = \"且\";\nBlockly.Msg.LOGIC_OPERATION_HELPURL = \"https://code.google.com/p/blockly/wiki/And_Or\";  // untranslated\nBlockly.Msg.LOGIC_OPERATION_OR = \"或\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = \"如果這兩個輸入值都為 真，則返回 真。\";\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = \"如果至少一個輸入的值為 真，返回 真。\";\nBlockly.Msg.LOGIC_TERNARY_CONDITION = \"測試\";\nBlockly.Msg.LOGIC_TERNARY_HELPURL = \"https://en.wikipedia.org/wiki/%3F:\";  // untranslated\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = \"如果為非\";\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = \"如果為真\";\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = \"檢查 'test' 中的條件。如果條件為 真，將返回 '如果為 真' 值 ；否則，返回 '如果為 否' 的值。\";\nBlockly.Msg.MATH_ADDITION_SYMBOL = \"+\";  // untranslated\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = \"https://en.wikipedia.org/wiki/Arithmetic\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = \"返回兩個數字的總和。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = \"返回兩個數字的商。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = \"返回兩個數字的差。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = \"返回兩個數字的乘積。\";\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = \"返回第二個數字的指數的第一個數字。\";\nBlockly.Msg.MATH_CHANGE_HELPURL = \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\";\nBlockly.Msg.MATH_CHANGE_INPUT_BY = \"自\";\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = \"修改\";\nBlockly.Msg.MATH_CHANGE_TOOLTIP = \"將數字添加到變量 '%1'。\";\nBlockly.Msg.MATH_CONSTANT_HELPURL = \"https://en.wikipedia.org/wiki/Mathematical_constant\";\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = \"返回一個的常見常量： π (3.141......)，e (2.718...)、 φ (1.618...)、 開方(2) (1.414......)、 開方(½) (0.707......) 或 ∞ （無窮大）。\";\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\";  // untranslated\nBlockly.Msg.MATH_CONSTRAIN_TITLE = \"限制數字 %1 介於 (低) %2 到 (高) %3\";\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = \"限制數字介於兩個指定的數字之間\";\nBlockly.Msg.MATH_DIVISION_SYMBOL = \"÷\";  // untranslated\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = \"可被整除\";\nBlockly.Msg.MATH_IS_EVEN = \"是偶數\";\nBlockly.Msg.MATH_IS_NEGATIVE = \"是負值\";\nBlockly.Msg.MATH_IS_ODD = \"是奇數\";\nBlockly.Msg.MATH_IS_POSITIVE = \"是正值\";\nBlockly.Msg.MATH_IS_PRIME = \"是質數\";\nBlockly.Msg.MATH_IS_TOOLTIP = \"如果數字是偶數，奇數，非負整數，正數、 負數或如果它是可被某數字整除，則返回 真 或 否。\";\nBlockly.Msg.MATH_IS_WHOLE = \"是非負整數\";\nBlockly.Msg.MATH_MODULO_HELPURL = \"https://en.wikipedia.org/wiki/Modulo_operation\";\nBlockly.Msg.MATH_MODULO_TITLE = \"取餘數自 %1 ÷ %2\";\nBlockly.Msg.MATH_MODULO_TOOLTIP = \"回傳兩個數字相除的餘數\";\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = \"×\";  // untranslated\nBlockly.Msg.MATH_NUMBER_HELPURL = \"https://en.wikipedia.org/wiki/Number\";\nBlockly.Msg.MATH_NUMBER_TOOLTIP = \"一個數字。\";\nBlockly.Msg.MATH_ONLIST_HELPURL = \"\";  // untranslated\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = \"平均值 自列表\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = \"最大值 自列表\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = \"中位數 自列表\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = \"最小值 自列表\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = \"比較眾數 自列表\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = \"隨機抽取 自列表\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = \"標準差 自列表\";\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = \"總和 自列表\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = \"返回列表中數值的平均值 （算術平均值）。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = \"返回列表中的最大數字。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = \"返回列表中數值的中位數。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = \"返回列表中的最小數字。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = \"返回一個列表中的最常見項目的列表。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = \"從列表中返回一個隨機的項目。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = \"返回列表中數字的標準差。\";\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = \"返回列表中的所有數字的總和。\";\nBlockly.Msg.MATH_POWER_SYMBOL = \"^\";  // untranslated\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = \"取隨機分數\";\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = \"返回介於 （包含） 0.0 到 1.0 之間的隨機數。\";\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = \"https://en.wikipedia.org/wiki/Random_number_generation\";\nBlockly.Msg.MATH_RANDOM_INT_TITLE = \"取隨機整數介於 (低) %1 到 %2\";\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = \"回傳限制的數字區間內的隨機數字\";\nBlockly.Msg.MATH_ROUND_HELPURL = \"https://en.wikipedia.org/wiki/Rounding\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = \"四捨五入\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = \"無條件捨去\";\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = \"無條件進位\";\nBlockly.Msg.MATH_ROUND_TOOLTIP = \"將數字向上或向下舍入。\";\nBlockly.Msg.MATH_SINGLE_HELPURL = \"https://en.wikipedia.org/wiki/Square_root\";\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = \"絕對值\";\nBlockly.Msg.MATH_SINGLE_OP_ROOT = \"開根號\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = \"返回指定數字的絕對值。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = \"返回指定數字指數的 e\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = \"返回指定數字的自然對數。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = \"返回指定數字的對數。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = \"返回指定數字的 negation。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = \"返回指定數字指數的10的冪次。\";\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = \"返回指定數字的平方根。\";\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = \"-\";  // untranslated\nBlockly.Msg.MATH_TRIG_ACOS = \"acos\";  // untranslated\nBlockly.Msg.MATH_TRIG_ASIN = \"asin\";  // untranslated\nBlockly.Msg.MATH_TRIG_ATAN = \"atan\";  // untranslated\nBlockly.Msg.MATH_TRIG_COS = \"cos\";  // untranslated\nBlockly.Msg.MATH_TRIG_HELPURL = \"https://en.wikipedia.org/wiki/Trigonometric_functions\";\nBlockly.Msg.MATH_TRIG_SIN = \"sin\";  // untranslated\nBlockly.Msg.MATH_TRIG_TAN = \"tan\";  // untranslated\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = \"返回指定角度的反餘弦值(非弧度）。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = \"返回指定角度的反正弦值(非弧度）。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = \"返回指定角度的反正切值。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = \"返回指定角度的餘弦值(非弧度）。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = \"返回指定角度的正弦值(非弧度）。\";\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = \"返回指定角度的正切值(非弧度）。\";\nBlockly.Msg.NEW_VARIABLE = \"新變量...\";\nBlockly.Msg.NEW_VARIABLE_TITLE = \"新變量名稱:\";\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = \"與：\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = \"呼叫\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = \"執行使用者定義的函數 '%1'。\";\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = \"執行使用者定義的函數 '%1' 並使用它的回傳值\";\nBlockly.Msg.PROCEDURES_CREATE_DO = \"建立 '%1'\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = \"\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = \"流程\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = \"到\";\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = \"創建一個無回傳值的函數。\";\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\";  // untranslated\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = \"回傳\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = \"創建一個有回傳值的函數。\";\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = \"警告: 此函數中有重複的參數。\";\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = \"高亮顯示函式定義\";\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = \"如果值為 真，則返回第二個值。\";\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = \"警告: 此積木僅可在定義函式時使用。\";\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = \"變量:\";\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = \"參數\";\nBlockly.Msg.REMOVE_COMMENT = \"移除註解\";\nBlockly.Msg.RENAME_VARIABLE = \"重新命名變量...\";\nBlockly.Msg.RENAME_VARIABLE_TITLE = \"將所有 \\\"%1\\\" 變量重新命名為:\";\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = \"後加入文字\";\nBlockly.Msg.TEXT_APPEND_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_APPEND_TO = \"在\";\nBlockly.Msg.TEXT_APPEND_TOOLTIP = \"將一些文字追加到變量 '%1'。\";\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\";  // untranslated\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = \"轉成 小寫\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = \"轉成 首字母大寫\";\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = \"轉成 大寫\";\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = \"使用不同的大小寫複製這段文字。\";\nBlockly.Msg.TEXT_CHARAT_FIRST = \"取第一個字元\";\nBlockly.Msg.TEXT_CHARAT_FROM_END = \"取得 倒數第 # 個字元\";\nBlockly.Msg.TEXT_CHARAT_FROM_START = \"取得 字元 #\";\nBlockly.Msg.TEXT_CHARAT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\";  // untranslated\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = \"的字元在字串\";\nBlockly.Msg.TEXT_CHARAT_LAST = \"取最後一個字元\";\nBlockly.Msg.TEXT_CHARAT_RANDOM = \"取隨機一個字元\";\nBlockly.Msg.TEXT_CHARAT_TAIL = \"\";\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = \"返回位於指定位置的字元。\";\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = \"將一個項目加入到字串中。\";\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = \"加入\";\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = \"添加、 刪除或重新排列各區塊來此重新配置這個文字積木。\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = \"到 倒數第 # 個字元\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = \"到 字元 #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = \"到 最後一個字元\";\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = \"自字串\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = \"取得一段字串 自 第一個字元\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = \"取得一段字串自 #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = \"取得一段字串自 #\";\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = \"返回指定的部分文字。\";\nBlockly.Msg.TEXT_INDEXOF_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Finding_text\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = \"在字串\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = \"尋找 第一個 出現的字串\";\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = \"尋找 最後一個 出現的字串\";\nBlockly.Msg.TEXT_INDEXOF_TAIL = \"\";  // untranslated\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = \"返回在第二個字串中的第一個/最後一個匹配項目的索引值。如果未找到則返回 0。\";\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\";  // untranslated\nBlockly.Msg.TEXT_ISEMPTY_TITLE = \"%1 為空\";\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = \"如果提供的字串為空，則返回 真。\";\nBlockly.Msg.TEXT_JOIN_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_creation\";  // untranslated\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = \"建立字串使用\";\nBlockly.Msg.TEXT_JOIN_TOOLTIP = \"通過串起任意數量的項目來建立一段文字。\";\nBlockly.Msg.TEXT_LENGTH_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Text_modification\";  // untranslated\nBlockly.Msg.TEXT_LENGTH_TITLE = \"長度 %1\";\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = \"返回這串文字的字元數（含空格） 。\";\nBlockly.Msg.TEXT_PRINT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Printing_text\";  // untranslated\nBlockly.Msg.TEXT_PRINT_TITLE = \"印出 %1\";\nBlockly.Msg.TEXT_PRINT_TOOLTIP = \"印出指定的文字、 數字或其他值。\";\nBlockly.Msg.TEXT_PROMPT_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\";  // untranslated\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = \"輸入數字\";\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = \"輸入文字\";\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = \"輸入 數字 並顯示提示訊息\";\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = \"輸入 文字 並顯示提示訊息\";\nBlockly.Msg.TEXT_TEXT_HELPURL = \"https://en.wikipedia.org/wiki/String_(computer_science)\";\nBlockly.Msg.TEXT_TEXT_TOOLTIP = \"字元、 單詞或一行文字。\";\nBlockly.Msg.TEXT_TRIM_HELPURL = \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\";  // untranslated\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = \"從 兩側 消除空格\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = \"從 左側 消除空格\";\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = \"從 右側 消除空格\";\nBlockly.Msg.TEXT_TRIM_TOOLTIP = \"複製這段文字的同時刪除兩端多餘的空格。\";\nBlockly.Msg.VARIABLES_DEFAULT_NAME = \"變量\";\nBlockly.Msg.VARIABLES_GET_CREATE_SET = \"創立 '設定 %1'\";\nBlockly.Msg.VARIABLES_GET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Get\";  // untranslated\nBlockly.Msg.VARIABLES_GET_TAIL = \"\";\nBlockly.Msg.VARIABLES_GET_TITLE = \"\";\nBlockly.Msg.VARIABLES_GET_TOOLTIP = \"返回此變量的值。\";\nBlockly.Msg.VARIABLES_SET_CREATE_GET = \"建立 '取得 %1'\";\nBlockly.Msg.VARIABLES_SET_HELPURL = \"https://code.google.com/p/blockly/wiki/Variables#Set\";  // untranslated\nBlockly.Msg.VARIABLES_SET_TAIL = \"到\";\nBlockly.Msg.VARIABLES_SET_TITLE = \"賦值\";\nBlockly.Msg.VARIABLES_SET_TOOLTIP = \"設定此變量，好和輸入值相等。\";\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;"
  },
  {
    "path": "extern/blockly/msg/json/ar.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"البند\",\n    \"DUPLICATE_BLOCK\": \"ادمج\",\n    \"ADD_COMMENT\": \"اضافة تعليق\",\n    \"REMOVE_COMMENT\": \"ازل التعليق\",\n    \"EXTERNAL_INPUTS\": \"ادخال خارجي\",\n    \"INLINE_INPUTS\": \"ادخال خطي\",\n    \"DELETE_BLOCK\": \"إحذف القطعة\",\n    \"DELETE_X_BLOCKS\": \"إحذف قطع %1\",\n    \"COLLAPSE_BLOCK\": \"إخفاء القطعة\",\n    \"COLLAPSE_ALL\": \"إخفاء القطع\",\n    \"EXPAND_BLOCK\": \"وسٌّع القطعة\",\n    \"EXPAND_ALL\": \"وسٌّع القطع\",\n    \"DISABLE_BLOCK\": \"عطّل القطعة\",\n    \"ENABLE_BLOCK\": \"أعد تفعيل القطعة\",\n    \"HELP\": \"مساعدة\",\n    \"CHANGE_VALUE_TITLE\": \"تغيير قيمة:\",\n    \"NEW_VARIABLE\": \"متغير جديد...\",\n    \"NEW_VARIABLE_TITLE\": \"اسم المتغير الجديد:\",\n    \"RENAME_VARIABLE\": \"إعادة تسمية المتغير...\",\n    \"RENAME_VARIABLE_TITLE\": \"إعادة تسمية كافة المتغيرات '%1' إلى:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://ar.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"اختر لون من اللوحة.\",\n    \"COLOUR_RANDOM_TITLE\": \"لون عشوائي\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"اختر لون بشكل عشوائي.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"لون مع\",\n    \"COLOUR_RGB_RED\": \"أحمر\",\n    \"COLOUR_RGB_GREEN\": \"أخضر\",\n    \"COLOUR_RGB_BLUE\": \"أزرق\",\n    \"COLOUR_RGB_TOOLTIP\": \"إنشئ لون بالكمية المحددة من الأحمر, الأخضر والأزرق. بحيث يجب تكون كافة القيم بين 0 و 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"دمج\",\n    \"COLOUR_BLEND_COLOUR1\": \"اللون 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"اللون 2\",\n    \"COLOUR_BLEND_RATIO\": \"نسبة\",\n    \"COLOUR_BLEND_TOOLTIP\": \"دمج لونين ببعضهما البعض بنسبة (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"كرر  %1 مرات\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"أكرر\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"مرات\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"نفّذ\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"نفّذ بعض الأوامر عدة مرات.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"اكرّر طالما\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"اكرّر حتى\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"بما ان القيمة صحيحة, نفّذ بعض الأوامر.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"بما ان القيمة خاطئة, نفّذ بعض الأوامر.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"اجعل المتغير  %1 يأخذ القيم من رقم البداية الى رقم النهاية، قم بالعد داخل المجال المحدد، وطبق أوامر القطع المحددة.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"عد بـ\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"من %1 إلى %2 بمعدل %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"_each https://code.google.com/p/blockly/wiki/Loops#for العبارة الشرطية \\\"لِكُل\\\"\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"لكل عنصر\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"في قائمة\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"لكل عنصر في قائمة ما، عين المتغير '%1' لهذا الغنصر، ومن ثم نفذ بعض الأوامر.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"اخرج من الحلقة\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"استمر ابتداءا من التكرار التالي من الحلقة\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"اخرج من الحلقة الحالية.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"تخط ما تبقى من هذه الحلقة، واستمر ابتداءا من التكرار التالي.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"تحذير: يمكن استخدام هذه القطعة فقط داخل حلقة.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"إذا كانت قيمة ما تساوي صحيح, إذن قم بتنفيذ أمر ما.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"إذا كانت قيمة ما تساوي \\\"صحيح\\\"، إذن قم بتنفيذ أول قطعة من الأوامر. والا ،قم بتنفيذ القطعة الثانية من الأوامر.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"إذا كانت القيمة الأولى تساوي \\\"صحيح\\\", إذن قم بتنفيذ القطعة الأولى من الأوامر. والا, إذا كانت القيمة الثانية تساوي \\\"صحيح\\\", قم بتنفيذ القطعة الثانية من الأوامر.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"إذا كانت القيمة الأولى تساوي \\\"صحيح\\\", إذن قم بتنفيذ القطعة الأولى من الأوامر. والا , إذا كانت القيمة الثانية تساوي \\\"صحيح\\\", قم بتنفيذ القطعة الثانية من الأوامر. إذا لم تكن هناك أي قيمة تساوي صحيح, قم بتنفيذ آخر قطعة من الأوامر.\",\n    \"CONTROLS_IF_MSG_IF\": \"إذا\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"وإﻻ إذا\",\n    \"CONTROLS_IF_MSG_ELSE\": \"والا\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"أضف, إزل, أو أعد ترتيب المقاطع لإعادة تكوين القطعة الشرطية \\\"إذا\\\".\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"إضف شرطا إلى القطعة الشرطية \\\"إذا\\\".\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"أضف شرط \\\"نهاية، إجمع\\\" إلى القطعة الشرطية \\\"إذا\\\".\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"يرجع صحيح إذا كان كلا المدخلات مساوية بعضها البعض.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"يرجع صحيح إذا كانت كلا المدخلات غير مساوية لبعضها البعض.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"يرجع صحيح إذا كان الإدخال الأول أصغر من الإدخال الثاني.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"يرجع صحيح إذا كان الإدخال الأول أصغر من أو يساوي الإدخال الثاني.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"يرجع صحيح إذا كان الإدخال الأول أكبر من الإدخال الثاني.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"يرجع صحيح إذا كان الإدخال الأول أكبر من أو يساوي الإدخال الثاني.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"ترجع صحيح إذا كان كلا المٌدخلات صحيح.\",\n    \"LOGIC_OPERATION_AND\": \"و\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"ترجع صحيح إذا كان واحد على الأقل من المدخلات صحيح.\",\n    \"LOGIC_OPERATION_OR\": \"أو\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"ليس من %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"يرجع صحيح إذا كان الإدخال خاطئ .  يرجع خاطئ إذا كان الإدخال صحيح.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"صحيح\",\n    \"LOGIC_BOOLEAN_FALSE\": \"خاطئ\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"يرجع صحيح أو خاطئ.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"ملغى\",\n    \"LOGIC_NULL_TOOLTIP\": \"ترجع ملغى.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"اختبار\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"إذا كانت العبارة صحيحة\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"إذا كانت العبارة خاطئة\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"تحقق الشرط في 'الاختبار'. إذا كان الشرط صحيح، يقوم بإرجاع قيمة 'اذا كانت العبارة صحيحة'؛ خلاف ذلك يرجع قيمة 'اذا كانت العبارة خاطئة'.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"عدد ما.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"جيب\",\n    \"MATH_TRIG_COS\": \"جيب تمام\",\n    \"MATH_TRIG_TAN\": \"ظل\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"يرجع مجموع الرقمين.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"يرجع الفرق بين الرقمين.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"يرجع حاصل ضرب الرقمين.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"يرجع حاصل قسمة الرقمين.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"يرجع الرقم الأول مرفوع إلى تربيع الرقم الثاني.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"الجذر التربيعي\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"يرجع الجذر التربيعي للرقم.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"مطلق\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"يرجع القيمة المطلقة لرقم.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"يرجع عدد سالب.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"يرجع اللوغاريتم الطبيعي لرقم.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"يرجع لوغاريتم عدد معين للاساس 10.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"يرجع  e الذي هو الاس المرفوع للرقم.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"يرجع مضروب الرقم 10 في نفسه .\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"يرجع جيب التمام لدرجة (لا زواية نصف قطرية).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"يرجع جيب التمام لدرجة (لا زواية نصف قطرية).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"يرجع الظل لدرجة (لا دائرة نصف قطرية).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"يرجع قوس الجيب للرقم.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"يرجع قوس جيب التمام لرقم.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"يرجع قوس الظل للرقم.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"ير جع واحد من الثوابت الشائعة : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"هو زوجي\",\n    \"MATH_IS_ODD\": \"هو فرذي\",\n    \"MATH_IS_PRIME\": \"هو أولي\",\n    \"MATH_IS_WHOLE\": \"هو صحيح\",\n    \"MATH_IS_POSITIVE\": \"هو موجب\",\n    \"MATH_IS_NEGATIVE\": \"هو سالب\",\n    \"MATH_IS_DIVISIBLE_BY\": \"قابل للقسمة\",\n    \"MATH_IS_TOOLTIP\": \"تحقق إذا كان عدد ما زوجيا، فرذيا, أوليا، صحيحا،موجبا أو سالبا، أو إذا كان قابلا للقسمة على عدد معين.  يرجع صحيح أو خاطئ.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"غير\",\n    \"MATH_CHANGE_INPUT_BY\": \"بـ\",\n    \"MATH_CHANGE_TOOLTIP\": \"إضف رقم إلى متغير '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"تقريب الى اكبر عدد صحيح أو الى اصغر عدد صحيح.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"تقريب\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"تقريب الى اكبر عدد صحيح\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"تقريب إلى اصغر عدد صحيح\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"مجموع القائمة\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"يرجع مجموع كافة الأرقام الموجودة في القائمة.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"الحد الأدنى من قائمة\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"يرجع أصغر رقم في القائمة.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"الحد الأقصى لقائمة\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"يرجع أكبر عدد في القائمة.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"متوسط القائمة\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"يرجع المعدل (الوسط الحسابي) للقيم الرقمية في القائمة.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"متوسط القائمة\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"يرجع وسيط العدد في القائمة.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"منوال القائمة\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"يرجع قائمة من العنصر أو العناصر الأكثر شيوعاً في القائمة.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"الانحراف المعياري للقائمة\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"يرجع الانحراف المعياري للقائمة.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"عنصر عشوائي من القائمة\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"يرجع عنصر عشوائي من القائمة.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"باقي %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"يرجع الباقي من قسمة الرقمين.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"تقيد %1 منخفض %2 مرتفع %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"تقييد العددليكون بين الحدود المحددة (ضمناً).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \" عدد صحيح عشوائي من %1 إلى %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"يرجع عدد صحيح عشوائي بين حدين محددين, ضمنيا.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"كسر عشوائي\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"يرجع جزء عشوائي بين 0.0 (ضمنياً) و 1.0 (خارجيا).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"حرف أو كلمة أو سطر من النص.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"انشئ نص مع\",\n    \"TEXT_JOIN_TOOLTIP\": \"أنشئ جزء من النص بالصاق أي عدد من العناصر ببعضها البعض.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"الانضمام إلى\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"أضف, إحذف, أو أعد ترتيب المقاطع لإعادة تكوين النص من القطع التالية.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"إضف عنصر إلى النص.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"إلى\",\n    \"TEXT_APPEND_APPENDTEXT\": \"إلصق نص\",\n    \"TEXT_APPEND_TOOLTIP\": \"إلصق جزءا من النص إلى متغير '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"طول %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"تقوم بإرجاع عدد الاحرف (بما في ذلك الفراغات) في النص المقدم.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 فارغ\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"يرجع \\\"صحيح\\\" إذا كان النص المقدم فارغ.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"تقوم بإرجاع مؤشر التواجد الأول/الأخير للنص الأول في النص الثاني.  تقوم بإرجاع 0 إذا لم يتم العثور على النص.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"في النص\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"ابحث عن التواجد الأول للنص\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"ابحث عن التواجد الأخير للنص\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"في النص\",\n    \"TEXT_CHARAT_FROM_START\": \"الحصول على الحرف #\",\n    \"TEXT_CHARAT_FROM_END\": \"الحصول على الحرف # من نهاية\",\n    \"TEXT_CHARAT_FIRST\": \"احصل على الحرف الأول\",\n    \"TEXT_CHARAT_LAST\": \"احصل على آخر حرف\",\n    \"TEXT_CHARAT_RANDOM\": \"الحصول على حرف عشوائي\",\n    \"TEXT_CHARAT_TOOLTIP\": \"يرجع حرف ما في الموضع المحدد.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"يرجع جزء معين من النص.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"في النص\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"الحصول على سلسلة حروف فرعية من الحرف #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"الحصول على سلسلة حروف فرعية من الحرف # من نهاية\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"الحصول على سلسلة فرعية من الحرف الأول\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"إلى حرف #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"إلى حرف # من نهاية\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"إلى آخر حرف\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"يرجع نسخة من النص في حالة مختلفة.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"الى حروف كبيرة\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"الى حروف صغيرة\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"الى حروف العنوان\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"يرجع نسخة من النص مع حذف من أحد أو كلا الفراغات من أطرافه.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"ازالة الفراغات من كلا الجانبين\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"ازالة الفراغات من الجانب الأيسر\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"ازالة الفراغات من الجانب الأيمن\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"اطبع %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"اطبع النص المحدد أو العدد أو قيمة أخرى.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"انتظر ادخال المستخدم لنص ما مع اظهار رسالة\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"انتظر ادخال المستخدم لرقم ما مع اظهار رسالة\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"انتظر ادخال المستخذم لرقم ما.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"انتظر ادخال المستخدم لنص ما.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"إنشئ قائمة فارغة\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"تقوم بإرجاع قائمة، طولها 0, لا تحتوي على أية سجلات البيانات\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"أنشيء قائمة من أي عدد من العناصر.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"أتشئ قائمة مع\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"قائمة\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"أضف, إزل, أو أعد ترتيب المقاطع لإعادة تكوين القطعة قائمة القطع التالية.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"أضف عنصرا إلى القائمة.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"انشئ قائمة تتألف من القيمة المعطاة متكررة لعدد محدد من المرات.\",\n    \"LISTS_REPEAT_TITLE\": \"إنشئ قائمة مع العنصر  %1 %2 مرات\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"الطول من %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"تقوم بإرجاع طول قائمة.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 فارغ\",\n    \"LISTS_TOOLTIP\": \"يرجع \\\"صحيح\\\" إذا كانت القائمة فارغة.\",\n    \"LISTS_INLIST\": \"في قائمة\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"ابحث على على التواجد الأول للعنصر\",\n    \"LISTS_INDEX_OF_LAST\": \"ابحث على التواجد الأخير للعنصر\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"تقوم بإرجاع مؤشر التواجد  الأول/الأخير في القائمة.  تقوم بإرجاع 0 إذا لم يتم العثور على النص.\",\n    \"LISTS_GET_INDEX_GET\": \"احصل على\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"احصل على و ازل\",\n    \"LISTS_GET_INDEX_REMOVE\": \"ازل\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# من نهاية\",\n    \"LISTS_GET_INDEX_FIRST\": \"أول\",\n    \"LISTS_GET_INDEX_LAST\": \"أخير\",\n    \"LISTS_GET_INDEX_RANDOM\": \"عشوائي\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"يقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"يقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"يرجع العنصر الأول في قائمة ما.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"يرجع العنصر الأخير في قائمة ما.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"يرجع عنصرا عشوائيا في قائمة.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"يزيل ويقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"يزيل ويقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"يزيل ويرجع العنصر الأول في قائمة.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"يزيل ويرجع العنصر الأخير في قائمة ما.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"يزيل و يرجع عنصرا عشوائيا في قائمة ما.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"يزيل العنصر الموجود في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"يزيل العنصر الموجود في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"يزيل العنصر الأول في قائمة ما.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"يزيل العنصر الأخير في قائمة ما.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"يزيل عنصرا عشوائيا في قائمة ما.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"تعيين\",\n    \"LISTS_SET_INDEX_INSERT\": \"أدخل في\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"مثل\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"يحدد العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"يحدد العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"يحدد العنصر الأول في قائمة.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"يحدد العنصر الأخير في قائمة.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"يحدد عنصرا عشوائيا في قائمة.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"يقوم بإدخال العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأول.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"يقوم بإدخال العنصر في الموضع المحدد في قائمة ما.  #1 هو العنصر الأخير.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"يقوم بإدراج هذا العنصر في بداية قائمة.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"ألصق هذا العنصر بنهاية قائمة.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"ادخل العنصر عشوائياً في القائمة.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"احصل على قائمة فرعية من #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"احصل  على قائمة فرعية من # من نهاية\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"احصل على قائمة فرعية من الأول\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"إلى #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"إلى # من نهاية\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"إلى الأخير\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"يقوم بإنشاء نسخة من الجزء المحدد من قائمة ما.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"يرجع قيمة هذا المتغير.\",\n    \"VARIABLES_GET_CREATE_SET\": \"انشئ 'التعيين %1'\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"تعيين\",\n    \"VARIABLES_SET_TAIL\": \"إلى\",\n    \"VARIABLES_SET_TOOLTIP\": \"تعيين هذا المتغير لتكون مساوية للقيمة المدخلة.\",\n    \"VARIABLES_SET_CREATE_GET\": \"انشئ 'احصل على %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"إلى\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"القيام بشيء ما\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"مع:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"انشئ دالة بدون مخرجات .\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"يرجع\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"انشئ دالة مع المخرجات.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"تحذير: هذه الدالة تحتوي على معلمات مكررة.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"تشغيل الدالة المعرفة من قبل المستخدم '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"تشغيل الدالة المعرفة من قبل المستخدم %1 واستخدام  مخرجاتها.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"المدخلات\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"اسم الإدخال:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"تسليط الضوء على تعريف الدالة\",\n    \"PROCEDURES_CREATE_DO\": \"إنشئ '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"إذا كانت القيمة صحيحة ، اذان قم بارجاع القيمة الثانية.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"تحذير:هذه القطعة تستخدم فقط داخل تعريف دالة.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/az.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Cekli829\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"element\",\n    \"DUPLICATE_BLOCK\": \"Dublikat\",\n    \"ADD_COMMENT\": \"Şərh əlavə et\",\n    \"REMOVE_COMMENT\": \"Şərhi sil\",\n    \"EXTERNAL_INPUTS\": \"Xarici girişlər\",\n    \"INLINE_INPUTS\": \"Sətiriçi girişlər\",\n    \"DELETE_BLOCK\": \"Bloku sil\",\n    \"DELETE_X_BLOCKS\": \"%1 bloku sil\",\n    \"COLLAPSE_BLOCK\": \"Bloku yığ\",\n    \"COLLAPSE_ALL\": \"Blokları yığ\",\n    \"EXPAND_BLOCK\": \"Bloku aç\",\n    \"EXPAND_ALL\": \"Blokları aç\",\n    \"DISABLE_BLOCK\": \"Bloku söndür\",\n    \"ENABLE_BLOCK\": \"Bloku aktivləşdir\",\n    \"HELP\": \"Kömək\",\n    \"CHANGE_VALUE_TITLE\": \"Qiyməti dəyiş:\",\n    \"NEW_VARIABLE\": \"Yeni dəyişən...\",\n    \"NEW_VARIABLE_TITLE\": \"Yeni dəyişənin adı:\",\n    \"RENAME_VARIABLE\": \"Dəyişənin adını dəyiş...\",\n    \"RENAME_VARIABLE_TITLE\": \"Bütün '%1' dəyişənlərinin adını buna dəyiş:\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Palitradan bir rəng seçin.\",\n    \"COLOUR_RANDOM_TITLE\": \"təsadüfi rəng\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Təsadüfi bir rəng seçin.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"rəngin komponentləri:\",\n    \"COLOUR_RGB_RED\": \"qırmızı\",\n    \"COLOUR_RGB_GREEN\": \"yaşıl\",\n    \"COLOUR_RGB_BLUE\": \"mavi\",\n    \"COLOUR_RGB_TOOLTIP\": \"Qırmızı, yaşıl və mavinin göstərilən miqdarı ilə bir rəng düzəlt. Bütün qiymətlər 0 ilə 100 arasında olmalıdır.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"qarışdır\",\n    \"COLOUR_BLEND_COLOUR1\": \"rəng 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"rəng 2\",\n    \"COLOUR_BLEND_RATIO\": \"nisbət\",\n    \"COLOUR_BLEND_TOOLTIP\": \"İki rəngi verilmiş nisbətdə (0,0 - 1,0) qarışdırır.\",\n    \"CONTROLS_REPEAT_TITLE\": \"%1 dəfə təkrar et\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"təkrar et\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"dəfə\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"icra et\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Bəzi əmrləri bir neçə dəfə yerinə yetir.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"təkrar et, hələ ki\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"təkrar et, ta ki\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Hələ ki, qiymət \\\"doğru\\\"dur, bəzi əmrləri yerinə yetir.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Hələ ki, qiymət \\\"yalan\\\"dır, bəzi əmrləri yerinə yetir.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"%1 dəyişəni başlanğıc ədəddən son ədədə qədər göstərilən aralıqla qiymətlər aldıqca göstərilən blokları yerinə yetir.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"say:\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"%1 ilə başlayıb, %2 qiymətinə kimi %3 qədər dəyiş\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"hər element üçün\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"siyahıda\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Siyahıdakı hər element üçün \\\"%1\\\" dəyişənini elementə mənimsət və bundan sonra bəzi əmrləri yerinə yetir.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"dövrdən çıx\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"dövrün növbəti addımından davam et\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Cari dövrdən çıx.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Bu dövrün qalanını ötür və növbəti addımla davam et.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Xəbərdarlıq: Bu blok ancaq dövr daxilində istifadə oluna bilər.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Əgər qiymət doğrudursa, onda bəzi əmrləri yerinə yetir.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Əgər qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda isə ikinci əmrlər blokunu yerinə yetir.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir. Əgər qiymətlərdən heç biri doğru deyilsə, onda axırıncı əmrlər blokunu yerinə yetir.\",\n    \"CONTROLS_IF_MSG_IF\": \"əgər\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"əks halda əgər\",\n    \"CONTROLS_IF_MSG_ELSE\": \"əks halda\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Bu \\\"əgər\\\" blokunu dəyişdirmək üçün bölümlərin yenisini əlavə et, sil və ya yerini dəyiş.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"\\\"Əgər\\\" blokuna bir şərt əlavə et.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"\\\"Əgər\\\" blokuna qalan bütün halları əhatə edəb son bir şərt əlavə et.\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Girişlər bir birinə bərabərdirsə \\\"doğru\\\" cavabını qaytarır.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Girişlər bərabər deyillərsə \\\"doğru\\\" cavabını qaytarır.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Birinci giriş ikincidən kiçikdirsə \\\"doğru\\\" cavabını qaytarır.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Birinci giriş ikincidən kiçik və ya bərarbərdirsə \\\"doğru\\\" cavabını qaytarır.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Birinci giriş ikincidən böyükdürsə \\\"doğru\\\" cavabını qaytarır.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Birinci giriş ikincidən böyük və ya bərarbərdirsə \\\"doğru\\\" cavabını qaytarır.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Hər iki giriş \\\"doğru\\\"-dursa \\\"doğru\\\" cavabını qaytarır.\",\n    \"LOGIC_OPERATION_AND\": \"və\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Girişlərdən heç olmasa biri \\\"doğru\\\"-dursa \\\"doğru\\\" cavabını qaytarır.\",\n    \"LOGIC_OPERATION_OR\": \"və ya\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"%1 deyil\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Giriş \\\"yalan\\\"-dursa \\\"doğru\\\" cavabını qaytarır. Giriş \\\"doğru\\\"-dursa \\\"yalan\\\" cavabını qaytarır.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"doğru\",\n    \"LOGIC_BOOLEAN_FALSE\": \"yalan\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"\\\"doğru\\\" və ya \\\"yalan\\\" cavanını qaytarır.\",\n    \"LOGIC_NULL\": \"boş\",\n    \"LOGIC_NULL_TOOLTIP\": \"Boş cavab qaytarır.\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"əgər doğrudursa\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"əgər yalandırsa\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"'Yoxla' əmrindəki şərtə nəzər yetirin. Əgər şərt \\\"doğru\\\"-dursa \\\"əgər doğru\\\", əks halda isə \\\"əgər yalan\\\" cavabını qaytarır.\",\n    \"MATH_NUMBER_TOOLTIP\": \"Ədəd.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tg\",\n    \"MATH_TRIG_ASIN\": \"arcsin\",\n    \"MATH_TRIG_ACOS\": \"arccos\",\n    \"MATH_TRIG_ATAN\": \"arctan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://az.wikipedia.org/wiki/Hesab\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"İki ədədin cəmini qaytarır.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"İki ədədin fərqini qaytarır.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"İki ədədin hasilini verir.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"İki ədədin nisbətini qaytarır.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Birinci ədədin ikinci ədəd dərəcəsindən qüvvətini qaytarır.\",\n    \"MATH_SINGLE_OP_ROOT\": \"kvadrat kök\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Ədədin kvadrat kökünü qaytarır.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"modul\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Ədədin modulunu qaytarır.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Ədədin əksini qaytarır.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Ədədin natural loqarifmini tapır.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Ədədin 10-cu dərəcədən loqarifmini tapır.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"e sabitinin verilmiş ədədə qüvvətini qaytarır.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"10-un verilmiş ədədə qüvvətini qaytarır.\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Dərəcənin sinusunu qaytar (radianın yox).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Dərəcənin kosinusunu qaytarır (radianın yox).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Dərəcənin tangensini qaytar (radianın yox).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Ədədin arcsinusunu qaytarır.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Ədədin arccosinusunu qaytarır.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Ədədin arctanqensini qaytarır.\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Ümumi sabitlərdən birini qaytarır π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), və ya ∞ (sonsuzluq).\",\n    \"MATH_IS_EVEN\": \"cütdür\",\n    \"MATH_IS_ODD\": \"təkdir\",\n    \"MATH_IS_PRIME\": \"sadədir\",\n    \"MATH_IS_WHOLE\": \"tamdır\",\n    \"MATH_IS_POSITIVE\": \"müsətdir\",\n    \"MATH_IS_NEGATIVE\": \"mənfidir\",\n    \"MATH_IS_DIVISIBLE_BY\": \"bölünür\",\n    \"MATH_IS_TOOLTIP\": \"Bir ədədin cüt, tək, sadə, tam, müsbət, mənfi olmasını və ya müəyyən bir ədədə bölünməsini yoxlayır. \\\"Doğru\\\" və ya \\\"yalan\\\" qiymətini qaytarır.\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"dəyiş:\",\n    \"MATH_CHANGE_INPUT_BY\": \"buna:\",\n    \"MATH_CHANGE_TOOLTIP\": \"'%1' dəyişəninin üzərinə bir ədəd artır.\",\n    \"MATH_ROUND_TOOLTIP\": \"Ədədi aşağı və ya yuxari yuvarlaqşdır.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"yuvarlaqlaşdır\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"yuxarı yuvarlaqlaşdır\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"aşağı yuvarlaqlaşdır\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"Siyahının cəmi\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Siyahıdakı bütün ədədlərin cəmini qaytarır.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"siyahının minimumu\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Siyahıdaki ən kiçik ədədi qaytarır.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"siyahının maksimumu\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Siyahıdaki ən böyük elementi qaytarır.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"siyahının ədədi ortası\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Siyahıdaki ədədlərin ədədi ortasını qaytarır.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"siyahının medianı\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Siyahının median elementini qaytarır.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"Siyahı modları( Ən çox rastlaşılan elementləri)\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Siyahıdaki ən çox rastlanan element(lər)dən ibarət siyahı qaytarır.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"Siyahının standart deviasiyası\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Siyahının standart deviasiyasını qaytarır.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"siyahıdan təsadüfi seçilmiş bir element\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Siyahıdan təsadüfi bir element qaytarır.\",\n    \"MATH_MODULO_TITLE\": \"%1 ÷ %2 bölməsinin qalığı\",\n    \"MATH_MODULO_TOOLTIP\": \"İki ədədin nisbətindən alınan qalığı qaytarır.\",\n    \"MATH_CONSTRAIN_TITLE\": \"%1 üçün ən aşağı %2, ən yuxarı %3 olmağı tələb et\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Bir ədədin verilmiş iki ədəd arasında olmasını tələb edir (sərhədlər də daxil olmaqla).\",\n    \"MATH_RANDOM_INT_TITLE\": \"%1 ilə %2 arasından təsadüfi tam ədəd\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Verilmiş iki ədəd arasından (ədədrlər də daxil olmaqla) təsadüfi bir tam ədəd qaytarır.\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"təsadüfi kəsr\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"0.0 (daxil olmaqla) və 1.0 (daxil olmamaqla) ədədlərinin arasından təsadüfi bir kəsr ədəd qaytarır.\",\n    \"TEXT_TEXT_TOOLTIP\": \"Mətndəki hərf, söz və ya sətir.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"Verilmişlərlə mətn yarat\",\n    \"TEXT_JOIN_TOOLTIP\": \"İxtiyari sayda elementlərinin birləşməsi ilə mətn parçası yarat.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"birləşdir\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Bu mətn blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Mətnə bir element əlavə et.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"bu mətnin sonuna:\",\n    \"TEXT_APPEND_APPENDTEXT\": \"bu mətni əlavə et:\",\n    \"TEXT_APPEND_TOOLTIP\": \"'%1' dəyişəninin sonuna nəsə əlavə et.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"%1 - ın uzunluğu\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Verilmiş mətndəki hərflərin(sözlər arası boşluqlar sayılmaqla) sayını qaytarır.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 boşdur\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Verilmiş mətn boşdursa, doğru qiymətini qaytarır.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Birinci mətnin ikinci mətndə ilk/son rastlaşma indeksini qaytarır. Əgər rastlaşma baş verməzsə, 0 qaytarır.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"mətndə\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"Bu mətn ilə ilk rastlaşmanı tap:\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"Bu mətn ilə son rastlaşmanı tap:\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"növbəti mətndə\",\n    \"TEXT_CHARAT_FROM_START\": \"bu nömrəli hərfi götür\",\n    \"TEXT_CHARAT_FROM_END\": \"axırdan bu nömrəli hərfi götür\",\n    \"TEXT_CHARAT_FIRST\": \"birinci hərfi götür\",\n    \"TEXT_CHARAT_LAST\": \"axırıncı hərfi götür\",\n    \"TEXT_CHARAT_RANDOM\": \"təsadüfi hərf götür\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Göstərilən mövqedəki hərfi qaytarır.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Mətnin təyin olunmuş hissəsini qaytarır.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"mətndə\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"Mətnin surətini bu nömrəli hərfdən\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"Mətnin surətini sondan bu nömrəli # hərfdən\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"Mətnin surətini ilk hərfdən\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"bu nömrəli hərfə qədər\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"axırdan bu nömrəli hərfə qədər\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"son hərfə qədər\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Mətndə hərflərin böyük-kiçikliyini dəyiş.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"BÖYÜK HƏRFLƏRLƏ\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"kiçik hərflərlə\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"Baş Hərflərlə\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Mətnin hər iki və ya yalnız bir tərəfdən olan boşluqları pozulmuş surətini qaytarın.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"Boşluqları hər iki tərəfdən pozun\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"Boşluqlari yalnız sol tərəfdən pozun\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"Boşluqları yalnız sağ tərəfdən pozun\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"%1 - i çap elə\",\n    \"TEXT_PRINT_TOOLTIP\": \"Təyin olunmuş mətn, ədəd və ya hər hansı bir başqa elementi çap elə.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"İstifadəçiyə mətn daxil etməsi üçün sorğunu/tələbi ismarıc ilə göndərin\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"İstifadəçiyə ədəd daxil etməsi üçün sorğunu/tələbi ismarıc kimi göndərin\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"İstifadəçiyə ədəd daxil etməsi üçün sorğu/tələb göndərin.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"İstifadəçiyə mətn daxil etməsi üçün sorğu/tələb göndərin.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"boş siyahı düzəlt\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Heç bir verilən qeyd olunmamış, uzunluğu 0 olan bir siyahı verir\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"İstənilən ölçülü siyahı yaradın.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"bunlardan siyahı düzəlt\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"siyahı\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Bu siyahı blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Siyahıya element əlavə edin.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Təyin olunmuş elementin/qiymətin təyin olunmuş sayda təkrarlandığı siyahını yaradır.\",\n    \"LISTS_REPEAT_TITLE\": \"%1 elementinin %2 dəfə təkrarlandığı siyahı düzəlt\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"%1 siyahısının uzunluğu\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Siyahının uzunluğunu verir.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 boşdur\",\n    \"LISTS_TOOLTIP\": \"Siyahı boşdursa \\\"doğru\\\" cavabını qaytarır.\",\n    \"LISTS_INLIST\": \"siyahıda\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"Element ilə ilk rastlaşma indeksini müəyyən edin\",\n    \"LISTS_INDEX_OF_LAST\": \"Element ilə son rastlaşma indeksini müəyyən edin\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Siyahıda element ilə ilk/son rastlaşma indeksini qaytarır. Əgər tekst siyahıda tapılmazsa, 0 qaytarılır.\",\n    \"LISTS_GET_INDEX_GET\": \"götür\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"götür və sil\",\n    \"LISTS_GET_INDEX_REMOVE\": \"yığışdır\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"axırdan # nömrəli\",\n    \"LISTS_GET_INDEX_FIRST\": \"birinci\",\n    \"LISTS_GET_INDEX_LAST\": \"axırıncı\",\n    \"LISTS_GET_INDEX_RANDOM\": \"təsadüfi\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Siyahıdan təyin olunmuş indeksli elementi qaytarır. #1 ilk elementdir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Siyahıdan təyin olunmuş indeksli elementi qaytarır. #1 son elementdir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Siyahının ilk elementini qaytarır.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Siyahının son elementini qaytarır.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Siyahıdan hər hansı təsadüfi elementi qaytarır.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Siyahıdan təyin olunmuş indeksli elementi silir və qaytarır. #1 ilk elementdir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Siyahıdan təyin olunmuş indeksli elementi silir və qaytarır. #1 son elementdir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Siyahıdan ilk elementi silir və qaytarır.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Siyahıdan son elementi silir və qaytarır.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Siyahıdan təsadufi elementi silir və qaytarır.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Siyahıdan təyin olunmuş indeksli elementi silir. #1 ilk elementdir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Siyahıdan təyin olunmuş indeksli elementi silir. #1 son elementdir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Siyahıdan ilk elementi silir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Siyahıdan son elementi silir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Siyahıdan təsadüfi bir elementi silir.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"təyin et\",\n    \"LISTS_SET_INDEX_INSERT\": \"daxil et\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"Kimi\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Siyahının göstərilən yerdəki elementini təyin edir. #1 birinci elementdir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Siyahının göstərilən yerdəki elementini təyin edir. #1 axırıncı elementdir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Siyahıda birinci elementi təyin edir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Siyahının sonuncu elementini təyin edir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Siyahının təsadüfi seçilmiş bir elementini təyin edir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Elementi siyahıda göstərilən yerə daxil edir. #1 birinci elementdir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Elementi siyahıda göstərilən yerə daxil edir. #1 axırıncı elementdir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Elementi siyahının əvvəlinə daxil edir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Elementi siyahının sonuna artırır.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Elementi siyahıda təsadüfi seçilmiş bir yerə atır.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"# - dən alt-siyahını alın\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"# sonuncudan alt-siyahını alın\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"Birincidən alt-siyahını alın\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"# nömrəliyə\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"sondan # nömrəliyə\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"Sonuncuya\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Siyahının təyin olunmuş hissəsinin surətini yaradın.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Bu dəyişənin qiymətini qaytarır.\",\n    \"VARIABLES_GET_CREATE_SET\": \"'%1 - i təyin et' - i yarat\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TAIL\": \"- i bu qiymət ilə təyin et:\",\n    \"VARIABLES_SET_TOOLTIP\": \"Bu dəyişəni daxil edilmiş qiymətə bərabər edir.\",\n    \"VARIABLES_SET_CREATE_GET\": \"'%1 - i götür' - ü yarat\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"icra et:\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"hansısa əməliyyat\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"ilə:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Nəticəsi olmayan funksiya yaradır.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"qaytar\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Nəticəsi olan funksiya yaradır.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Xəbərdarlıq: Bu funksiyanın təkrar olunmuş parametrləri var.\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Yaradılmış '%1' funksiyasını çalışdır.\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Yaradılmış '%1' funksiyasını çalışdır və nəticəni istifadə et.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"girişlər\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"Giriş adı:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Funksiyanın təyinatını vurğula\",\n    \"PROCEDURES_CREATE_DO\": \"'%1' yarat\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Əgər bir dəyər \\\"doğru\\\"-dursa onda ikinci dəyəri qaytar.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Xəbərdarlıq: Bu blok ancaq bir funksiyanın təyinatı daxilində işlədilə bilər.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/be-tarask.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Renessaince\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"аб’ект\",\n    \"DUPLICATE_BLOCK\": \"Капіяваць\",\n    \"ADD_COMMENT\": \"Дадаць камэнтар\",\n    \"REMOVE_COMMENT\": \"Выдаліць камэнтар\",\n    \"EXTERNAL_INPUTS\": \"Зьнешнія ўваходы\",\n    \"INLINE_INPUTS\": \"Унутраныя ўваходы\",\n    \"DELETE_BLOCK\": \"Выдаліць блёк\",\n    \"DELETE_X_BLOCKS\": \"Выдаліць %1 блёкі\",\n    \"COLLAPSE_BLOCK\": \"Згарнуць блёк\",\n    \"COLLAPSE_ALL\": \"Згарнуць блёкі\",\n    \"EXPAND_BLOCK\": \"Разгарнуць блёк\",\n    \"EXPAND_ALL\": \"Разгарнуць блёкі\",\n    \"DISABLE_BLOCK\": \"Адключыць блёк\",\n    \"ENABLE_BLOCK\": \"Адключыць блёкі\",\n    \"HELP\": \"Дапамога\",\n    \"CHANGE_VALUE_TITLE\": \"Зьмяніць значэньне:\",\n    \"NEW_VARIABLE\": \"Новая зьменная…\",\n    \"NEW_VARIABLE_TITLE\": \"Імя новай зьменнай:\",\n    \"RENAME_VARIABLE\": \"Перайменаваць зьменную…\",\n    \"RENAME_VARIABLE_TITLE\": \"Перайменаваць усе назвы зьменных '%1' на:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://be-x-old.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BB%D0%B5%D1%80\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Абярыце колер з палітры.\",\n    \"COLOUR_RANDOM_TITLE\": \"выпадковы колер\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Абраць выпадковы колер.\",\n    \"COLOUR_RGB_TITLE\": \"колер з\",\n    \"COLOUR_RGB_RED\": \"чырвонага\",\n    \"COLOUR_RGB_GREEN\": \"зялёнага\",\n    \"COLOUR_RGB_BLUE\": \"сіняга\",\n    \"COLOUR_RGB_TOOLTIP\": \"Стварыць колер з абранымі прапорцыямі чырвонага, зялёнага і сіняга. Усе значэньні павінны быць ад 0 да 100.\",\n    \"COLOUR_BLEND_TITLE\": \"зьмяшаць\",\n    \"COLOUR_BLEND_COLOUR1\": \"колер 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"колер 2\",\n    \"COLOUR_BLEND_RATIO\": \"дзеля\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Зьмешвае два колеры ў дадзенай прапорцыі (0.0 — 1.0)\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"паўтарыць %1 раз(ы)\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"паўтарыць\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"раз(ы)\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"выканаць\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Выконвае апэрацыі некалькі разоў.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"паўтараць, пакуль\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"паўтараць, пакуль не\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Пакуль значэньне ісьціна, выконваць пэўныя апэрацыі.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Пакуль значэньне хлусьня, выконваць пэўныя апэрацыі.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"лічыць з\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"ад %1 да %2 па %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"для кожнага элемэнта\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"у сьпісе\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"перарваць цыкль\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"працягнуць з наступнага кроку цыклю\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Спыніць гэты цыкль.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Прапусьціць рэшту цыклю і перайсьці да наступнага кроку.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Увага: гэты блёк можа быць выкарыстаны толькі ў цыклі.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Калі значэньне ісьціна, выканаць пэўныя апэрацыі.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Калі значэньне ісьціна, выканаць першы блёк апэрацыяў, інакш выканаць другі блёк.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Калі першае значэньне ісьціна, выканаць першы блёк апэрацыяў. Інакш, калі другое значэньне ісьціна, выканаць другі блёк апэрацыяў.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Калі першае значэньне ісьціна, выканаць першы блёк апэрацыяў. Інакш, калі другое значэньне ісьціна, выканаць другі блёк апэрацыяў. Калі ніводнае з значэньняў не сапраўднае, выканаць апошні блёк апэрацыяў.\",\n    \"CONTROLS_IF_MSG_IF\": \"калі\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"інакш, калі\",\n    \"CONTROLS_IF_MSG_ELSE\": \"інакш\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Дадаць, выдаліць ці пераставіць сэкцыі для пераканфігураваньня гэтага блёку «калі».\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Дадаць умову да блёку «калі».\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Дадаць заключную ўмову для ўсіх астатніх варыянтаў блёку «калі».\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://be-x-old.wikipedia.org/wiki/%D0%9D%D1%8F%D1%80%D0%BE%D1%9E%D0%BD%D0%B0%D1%81%D1%8C%D1%86%D1%8C\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Вяртае «ісьціна», калі абодва ўводы роўныя.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Вяртае «ісьціна», калі абодва ўводы ня роўныя.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Вяртае «ісьціна», калі першы ўвод меншы за другі.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Вяртае «ісьціна», калі першы ўвод меншы ці роўны другому.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Вяртае «ісьціна», калі першы ўвод большы за другі.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Вяртае «ісьціна», калі першы ўвод большы ці роўны другому.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Вяртае «ісьціна», калі абодва ўводы праўдзівыя.\",\n    \"LOGIC_OPERATION_AND\": \"і\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Вяртае «ісьціна», калі прынамсі адзін з уводаў праўдзівы.\",\n    \"LOGIC_OPERATION_OR\": \"ці\",\n    \"LOGIC_NEGATE_TITLE\": \"не %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Вяртае «ісьціна», калі ўвод непраўдзівы. Вяртае «хлусьня», калі ўвод праўдзівы.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"ісьціна\",\n    \"LOGIC_BOOLEAN_FALSE\": \"хлусьня\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Вяртае «ісьціна» ці «хлусьня».\",\n    \"LOGIC_NULL\": \"нічога\",\n    \"LOGIC_NULL_TOOLTIP\": \"Вяртае нічога.\",\n    \"LOGIC_TERNARY_CONDITION\": \"тэст\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"калі ісьціна\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"калі хлусьня\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Праверыць умову ў 'тэст'. Калі ўмова праўдзівая, будзе вернутае значэньне «калі ісьціна»; інакш будзе вернутае «калі хлусьня».\",\n    \"MATH_NUMBER_HELPURL\": \"https://be-x-old.wikipedia.org/wiki/%D0%9B%D1%96%D0%BA\",\n    \"MATH_NUMBER_TOOLTIP\": \"Лік.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://be-x-old.wikipedia.org/wiki/%D0%90%D1%80%D1%8B%D1%82%D0%BC%D1%8D%D1%82%D1%8B%D0%BA%D0%B0\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Вяртае суму двух лікаў.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Вяртае рознасьць двух лікаў.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Вяртае здабытак двух лікаў.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Вяртае дзель двух лікаў.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Вяртае першы лік у ступені другога ліку.\",\n    \"MATH_SINGLE_HELPURL\": \"https://be-x-old.wikipedia.org/wiki/%D0%9A%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D1%8B_%D0%BA%D0%BE%D1%80%D0%B0%D0%BD%D1%8C\",\n    \"MATH_SINGLE_OP_ROOT\": \"квадратны корань\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Вяртае квадратны корань ліку.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"модуль\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Вяртае модуль ліку.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Вяртае супрацьлеглы лік.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Вяртае натуральны лягарытм ліку.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Вяртае дзесятковы лягарытм ліку.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Вяртае e ў ступені ліку.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Вяртае 10 у ступені ліку.\",\n    \"MATH_TRIG_HELPURL\": \"https://be-x-old.wikipedia.org/wiki/%D0%A2%D1%80%D1%8B%D0%B3%D0%B0%D0%BD%D0%B0%D0%BC%D1%8D%D1%82%D1%80%D1%8B%D1%8F#.D0.A2.D1.80.D1.8B.D0.B3.D0.B0.D0.BD.D0.B0.D0.BC.D1.8D.D1.82.D1.80.D1.8B.D1.87.D0.BD.D1.8B.D1.8F_.D1.84.D1.83.D0.BD.D0.BA.D1.86.D1.8B.D1.96\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Вяртае сынус кута ў градусах.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Вяртае косынус кута ў градусах.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Вяртае тангэнс кута ў градусах.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Вяртае арксынус ліку.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Вяртае арккосынус ліку.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Вяртае арктангэнс ліку.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://be-x-old.wikipedia.org/wiki/%D0%9C%D0%B0%D1%82%D1%8D%D0%BC%D0%B0%D1%82%D1%8B%D1%87%D0%BD%D0%B0%D1%8F_%D0%BA%D0%B0%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B0\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/br.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Fohanno\",\n            \"Y-M D\",\n            \"Gwenn-Ael\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"elfenn\",\n    \"DUPLICATE_BLOCK\": \"Eiladuriñ\",\n    \"ADD_COMMENT\": \"Ouzhpennañ un evezhiadenn\",\n    \"REMOVE_COMMENT\": \"Lemel an evezhiadenn kuit\",\n    \"EXTERNAL_INPUTS\": \"Monedoù diavaez\",\n    \"INLINE_INPUTS\": \"Monedoù enlinenn\",\n    \"DELETE_BLOCK\": \"Dilemel ar bloc'h\",\n    \"DELETE_X_BLOCKS\": \"Dilemel %1 bloc'h\",\n    \"EXPAND_BLOCK\": \"Astenn ar bloc'h\",\n    \"EXPAND_ALL\": \"AStenn ar bloc'hoù\",\n    \"DISABLE_BLOCK\": \"Diweredekaat ar bloc'h\",\n    \"ENABLE_BLOCK\": \"Gweredekaat ar bloc'h\",\n    \"HELP\": \"Skoazell\",\n    \"CHANGE_VALUE_TITLE\": \"Kemmañ an talvoudenn :\",\n    \"NEW_VARIABLE\": \"Argemmenn nevez...\",\n    \"NEW_VARIABLE_TITLE\": \"Anv an argemmenn nevez :\",\n    \"RENAME_VARIABLE\": \"Adenvel an argemmenn...\",\n    \"RENAME_VARIABLE_TITLE\": \"Adenvel an holl argemmennoù '%1' e :\",\n    \"COLOUR_PICKER_HELPURL\": \"http://br.wikipedia.org/wiki/Liv\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Dibab ul liv diwar al livaoueg.\",\n    \"COLOUR_RANDOM_TITLE\": \"liv dre zegouezh\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Tennañ ul liv d'ar sord\",\n    \"COLOUR_RGB_TITLE\": \"liv gant\",\n    \"COLOUR_RGB_RED\": \"ruz\",\n    \"COLOUR_RGB_GREEN\": \"gwer\",\n    \"COLOUR_RGB_BLUE\": \"glas\",\n    \"COLOUR_RGB_TOOLTIP\": \"Krouiñ ul liv gant ar c'hementad spisaet a ruz, a wer hag a c'hlas. Etre 0 ha 100 e tle bezañ an holl dalvoudoù.\",\n    \"COLOUR_BLEND_TITLE\": \"meskañ\",\n    \"COLOUR_BLEND_COLOUR1\": \"liv 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"liv 2\",\n    \"COLOUR_BLEND_RATIO\": \"feur\",\n    \"COLOUR_BLEND_TOOLTIP\": \"a gemmesk daou liv gant ur feur roet(0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"adober %1 gwech\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"adober\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"gwech\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"ober\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Seveniñ uzhioù zo meur a wech\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"adober keit ha ma\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"adober betek\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"kontañ gant\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"eus %1 da %2 dre %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"evit pep elfenn\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"er roll\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Evit pep elfenn en ur roll, reiñ talvoud an elfenn d'an argemmenn '%1', ha seveniñ urzhioù zo da c'houde.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"Mont e-maez an adlañsañ\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Diwallit : ne c'hall ar bloc'h-mañ bezañ implijet nemet e-barzh ur boukl.\",\n    \"CONTROLS_IF_MSG_IF\": \"ma\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"mod all ma\",\n    \"CONTROLS_IF_MSG_ELSE\": \"a-hend-all\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h ma.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Ouzhpennañ un amplegad d'ar bloc'h ma.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_OPERATION_AND\": \"ha(g)\",\n    \"LOGIC_OPERATION_OR\": \"pe\",\n    \"LOGIC_NEGATE_TITLE\": \"nann %1\",\n    \"LOGIC_BOOLEAN_TRUE\": \"gwir\",\n    \"LOGIC_BOOLEAN_FALSE\": \"gaou\",\n    \"LOGIC_TERNARY_CONDITION\": \"amprouad\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"m'eo gwir\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"m'eo gaou\",\n    \"MATH_NUMBER_HELPURL\": \"https://br.wikipedia.org/wiki/Niver\",\n    \"MATH_NUMBER_TOOLTIP\": \"Un niver.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://br.wikipedia.org/wiki/Aritmetik\",\n    \"MATH_SINGLE_OP_ROOT\": \"gwrizienn karrez\",\n    \"MATH_IS_EVEN\": \"zo par\",\n    \"MATH_IS_ODD\": \"a zo ampar\",\n    \"MATH_IS_WHOLE\": \"zo anterin\",\n    \"MATH_IS_POSITIVE\": \"a zo pozitivel\",\n    \"MATH_IS_NEGATIVE\": \"a zo negativel\",\n    \"MATH_IS_DIVISIBLE_BY\": \"a zo rannadus dre\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"kemmañ\",\n    \"MATH_CHANGE_INPUT_BY\": \"gant\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"Elfennn eus al listenn tennet d'ar sord\",\n    \"MATH_MODULO_TITLE\": \"rest eus %1 ÷ %2\",\n    \"TEXT_TEXT_TOOLTIP\": \"Ul lizherenn, ur ger pe ul linennad testenn.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"krouiñ un destenn gant\",\n    \"TEXT_APPEND_TO\": \"da\",\n    \"TEXT_APPEND_APPENDTEXT\": \"ouzhpennañ an destenn\",\n    \"TEXT_LENGTH_TITLE\": \"hirder %1\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 a zo goullo\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"en destenn\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"en destenn\",\n    \"TEXT_CHARAT_FIRST\": \"tapout al lizherenn gentañ\",\n    \"TEXT_CHARAT_LAST\": \"tapout al lizherenn diwezhañ\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"en destenn\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"d'al lizherenn diwezhañ\",\n    \"TEXT_PRINT_TITLE\": \"moullañ %1\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"krouiñ ur roll goullo\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"krouiñ ur roll gant\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"roll\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Ouzhpennañ un elfenn d'ar roll\",\n    \"LISTS_LENGTH_TITLE\": \"hirder %1\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 zo goullo\",\n    \"LISTS_INLIST\": \"er roll\",\n    \"LISTS_INDEX_OF_FIRST\": \"kavout reveziadenn gentañ un elfenn\",\n    \"LISTS_INDEX_OF_LAST\": \"kavout reveziadenn diwezhañ un elfenn\",\n    \"LISTS_GET_INDEX_GET\": \"tapout\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"tapout ha lemel\",\n    \"LISTS_GET_INDEX_REMOVE\": \"lemel\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# adalek ar fin\",\n    \"LISTS_GET_INDEX_FIRST\": \"kentañ\",\n    \"LISTS_GET_INDEX_LAST\": \"diwezhañ\",\n    \"LISTS_GET_INDEX_RANDOM\": \"dre zegouezh\",\n    \"LISTS_SET_INDEX_SET\": \"termeniñ\",\n    \"LISTS_SET_INDEX_INSERT\": \"ensoc'hañ evel\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"evel\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"da #\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"betek ar fin\",\n    \"VARIABLES_SET_TAIL\": \"da\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"da\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"ober un dra bennak\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"gant :\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"distreiñ\",\n    \"PROCEDURES_CREATE_DO\": \"Krouiñ '%1'\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/ca.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Alvaro Vidal-Abarca\",\n            \"Espertus\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"element\",\n    \"DUPLICATE_BLOCK\": \"Duplica\",\n    \"ADD_COMMENT\": \"Afegeix un comentari\",\n    \"REMOVE_COMMENT\": \"Elimina el comentari\",\n    \"EXTERNAL_INPUTS\": \"Entrades externes\",\n    \"INLINE_INPUTS\": \"Entrades en línia\",\n    \"DELETE_BLOCK\": \"Esborra bloc\",\n    \"DELETE_X_BLOCKS\": \"Esborra %1 blocs\",\n    \"COLLAPSE_BLOCK\": \"Contraure bloc\",\n    \"COLLAPSE_ALL\": \"Contraure blocs\",\n    \"EXPAND_BLOCK\": \"Expandir bloc\",\n    \"EXPAND_ALL\": \"Expandir blocs\",\n    \"DISABLE_BLOCK\": \"Desactiva bloc\",\n    \"ENABLE_BLOCK\": \"Activa bloc\",\n    \"HELP\": \"Ajuda\",\n    \"CHANGE_VALUE_TITLE\": \"Canvia valor:\",\n    \"NEW_VARIABLE\": \"Nova variable...\",\n    \"NEW_VARIABLE_TITLE\": \"Nou nom de variable:\",\n    \"RENAME_VARIABLE\": \"Reanomena variable...\",\n    \"RENAME_VARIABLE_TITLE\": \"Reanomena totes les variables '%1' a:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://ca.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Escolliu un color de la paleta.\",\n    \"COLOUR_RANDOM_TITLE\": \"color aleatori\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Escolliu un color a l'atzar.\",\n    \"COLOUR_RGB_TITLE\": \"color amb\",\n    \"COLOUR_RGB_RED\": \"vermell\",\n    \"COLOUR_RGB_GREEN\": \"verd\",\n    \"COLOUR_RGB_BLUE\": \"blau\",\n    \"COLOUR_RGB_TOOLTIP\": \"Crear un color amb les quantitats especificades de vermell, verd i blau. Tots els valors han de ser entre 0 i 100.\",\n    \"COLOUR_BLEND_TITLE\": \"barreja\",\n    \"COLOUR_BLEND_COLOUR1\": \"color 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"color 2\",\n    \"COLOUR_BLEND_RATIO\": \"proporció\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Barreja dos colors amb una proporció donada (0,0 - 1,0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://ca.wikipedia.org/wiki/Bucle_For\",\n    \"CONTROLS_REPEAT_TITLE\": \"repetir %1 vegades\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"repetir\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"vegades\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"fer\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Executar unes sentències diverses vegades.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"repetir mentre\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"repetir fins que\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Mentre un valor sigui cert, llavors executar unes sentències.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Mentre un valor sigui fals, llavors executar unes sentències.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Fer que la variable %1 prengui els valors des del nombre inicial fins al nombre final, incrementant a cada pas l'interval indicat, i executar els blocs especificats.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"comptar amb\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"des de %1 fins a %2 en increments de %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"per a cada element\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"en la llista\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Per a cada element en la llista, desar l'element dins la variable '%1', i llavors executar unes sentències.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"sortir del bucle\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continuar amb la següent iteració del bucle\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Sortir del bucle interior.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Ometre la resta d'aquest bucle, i continuar amb la següent iteració.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Advertència: Aquest bloc només es pot utilitzar dins d'un bucle.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Si un valor és cert, llavors executar unes sentències.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Si un valor és cert, llavors executar el primer bloc de sentències. En cas contrari, executar el segon bloc de sentències.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Si el primer valor és cert, llavors executar el primer bloc de sentències. En cas contrari, si el segon valor és cert, executar el segon bloc de sentències.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Si el primer valor és cert, llavors executar el primer bloc de sentències. En cas contrari, si el segon valor és cert, executar el segon bloc de sentències. Si cap dels valors és cert, executar l'últim bloc de sentències.\",\n    \"CONTROLS_IF_MSG_IF\": \"si\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"si no, si\",\n    \"CONTROLS_IF_MSG_ELSE\": \"si no\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Afegeix, esborra o reordena seccions per reconfigurar aquest bloc 'si'.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Afegeix una condició al bloc 'si'.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Afegeix una condició final, que recull qualsevol altra possibilitat, al bloc 'si'.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://ca.wikipedia.org/wiki/Inequaci%C3%B3\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Retorna cert si totes dues entrades són iguals.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Retorna cert si totes dues entrades són diferents.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Retorna cert si la primera entrada és més petita que la segona entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Retorna cert si la primera entra és més petita o igual a la segona entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Retorna cert si la primera entrada és més gran que la segona entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Retorna cert si la primera entrada és més gran o igual a la segona entrada.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Retorna cer si totes dues entrades són certes.\",\n    \"LOGIC_OPERATION_AND\": \"i\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Retorna cert si almenys una de les entrades és certa.\",\n    \"LOGIC_OPERATION_OR\": \"o\",\n    \"LOGIC_NEGATE_TITLE\": \"no %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Retorna cert si l'entrada és falsa. Retorna fals si l'entrada és certa.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"cert\",\n    \"LOGIC_BOOLEAN_FALSE\": \"fals\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Retorna o bé cert o bé fals.\",\n    \"LOGIC_NULL\": \"nul\",\n    \"LOGIC_NULL_TOOLTIP\": \"Retorna nul.\",\n    \"LOGIC_TERNARY_CONDITION\": \"condició\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"si és cert\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"si és fals\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Comprova la condició de 'condició'. Si la condició és certa, retorna el valor 'si és cert'; en cas contrari, retorna el valor 'si és fals'.\",\n    \"MATH_NUMBER_HELPURL\": \"https://ca.wikipedia.org/wiki/Nombre\",\n    \"MATH_NUMBER_TOOLTIP\": \"Un nombre.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://ca.wikipedia.org/wiki/Aritm%C3%A8tica\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Retorna la suma dels dos nombres.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Retorna la diferència entre els dos nombres.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Retorna el producte del dos nombres.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Retorna el quocient dels dos nombres.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Retorna el primer nombre elevat a la potència indicada pel segon nombre.\",\n    \"MATH_SINGLE_HELPURL\": \"https://ca.wikipedia.org/wiki/Arrel_quadrada\",\n    \"MATH_SINGLE_OP_ROOT\": \"arrel quadrada\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Retorna l'arrel quadrada d'un nombre.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolut\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Retorna el valor absolut d'un nombre.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Retorna l'oposat d'un nombre.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Retorna el logaritme natural d'un nombre.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Retorna el logaritme en base 10 d'un nombre.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Retorna ''e'' elevat a la potència del nombre indicat.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Retorna 10 elevat a la potència del nombre indicat.\",\n    \"MATH_TRIG_HELPURL\": \"https://ca.wikipedia.org/wiki/Funci%C3%B3_trigonom%C3%A8trica\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Retorna el sinus d'un grau (no radiant).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Retorna el cosinus d'un grau (no radiant).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Retorna la tangent d'un grau (no radiant).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Retorna l'arcsinus d'un nombre.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Retorna l'arccosinus d'un nombre.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Retorna l'arctangent d'un nombre.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://ca.wikipedia.org/wiki/Constant_matem%C3%A0tica\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Retorna una de les constants més habituals: π (3,141…), e (2,718…), φ (1,618…), sqrt(2) (1,414…), sqrt(½) (0,707…), o ∞ (infinit).\",\n    \"MATH_IS_EVEN\": \"és parell\",\n    \"MATH_IS_ODD\": \"és senar\",\n    \"MATH_IS_PRIME\": \"és primer\",\n    \"MATH_IS_WHOLE\": \"és enter\",\n    \"MATH_IS_POSITIVE\": \"és positiu\",\n    \"MATH_IS_NEGATIVE\": \"és negatiu\",\n    \"MATH_IS_DIVISIBLE_BY\": \"és divisible per\",\n    \"MATH_IS_TOOLTIP\": \"Comprova si un nombre és parell, senar, enter, positium negatiu, o si és divisible per un cert nombre. Retorna cert o fals.\",\n    \"MATH_CHANGE_HELPURL\": \"https://ca.wikipedia.org/wiki/Suma\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"canvia\",\n    \"MATH_CHANGE_INPUT_BY\": \"per\",\n    \"MATH_CHANGE_TOOLTIP\": \"Afegeix un nombre a la variable '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://ca.wikipedia.org/wiki/Arrodoniment\",\n    \"MATH_ROUND_TOOLTIP\": \"Arrodonir un nombre cap amunt o cap avall.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"arrodonir\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"arrodonir cap amunt\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"arrodonir cap avall\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"suma de llista\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Retorna la suma de tots els nombres de la llista.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"mínim de llista\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Retorna el nombre més petit de la llista.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"màxim de llista\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Retorna el nombre més gran de la llista.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"mitjana de llista\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Retorna la mitjana (mitjana aritmètica) dels valors numèrics de la llista.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mediana de llista\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Retorna la mediana de la llista.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"moda de llista\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Retorna una llista dels elements que apareixen més vegades a la llista.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"desviació estàndard de llista\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Retorna la desviació estàndard de la llista.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"element aleatori de llista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Retorna un element aleatori de la lllista.\",\n    \"MATH_MODULO_HELPURL\": \"https://ca.wikipedia.org/wiki/Residu_%28aritm%C3%A8tica%29\",\n    \"MATH_MODULO_TITLE\": \"residu de %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Retorna el residu de dividir els dos nombres.\",\n    \"MATH_CONSTRAIN_TITLE\": \"limitar %1 entre %2 i %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Limita un nombre per tal que estigui entre els límits especificats (inclosos).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://ca.wikipedia.org/wiki/Generaci%C3%B3_de_nombres_aleatoris\",\n    \"MATH_RANDOM_INT_TITLE\": \"nombre aleatori entre %1 i %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Retorna un nombre aleatori entre els dos límits especificats, inclosos.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://ca.wikipedia.org/wiki/Generaci%C3%B3_de_nombres_aleatoris\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"fracció aleatòria\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Retorna una fracció aleatòria entre 0,0 (inclòs) i 1,0 (exclòs).\",\n    \"TEXT_TEXT_HELPURL\": \"https://ca.wikipedia.org/wiki/Cadena_%28inform%C3%A0tica%29\",\n    \"TEXT_TEXT_TOOLTIP\": \"Una lletra, paraula o línia de text.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"crear text amb\",\n    \"TEXT_JOIN_TOOLTIP\": \"Crea un tros de text per unió de qualsevol nombre d'elements.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"unir\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Afegeix, esborrar o reordenar seccions per reconfigurar aquest bloc de text.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Afegeix un element al text.\",\n    \"TEXT_APPEND_TO\": \"a\",\n    \"TEXT_APPEND_APPENDTEXT\": \"afegir text\",\n    \"TEXT_APPEND_TOOLTIP\": \"Afegir un text a la variable '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"llargària de %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Retorna el nombre de lletres (espais inclosos) en el text proporcionat.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 està buit\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Retorna cert si el text proporcionat està buit.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Retorna l'índex de la primera/última aparició del primer text dins el segon. Retorna 0 si no es troba el text.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"en el text\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"trobar la primera aparició del text\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"trobar l'última aparició del text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"en el text\",\n    \"TEXT_CHARAT_FROM_START\": \"recupera la lletra núm.#\",\n    \"TEXT_CHARAT_FROM_END\": \"recupera la lletra núm.# des del final\",\n    \"TEXT_CHARAT_FIRST\": \"recupera la primera lletra\",\n    \"TEXT_CHARAT_LAST\": \"recupera l'última lletra\",\n    \"TEXT_CHARAT_RANDOM\": \"recupera una lletra a l'atzar\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Recupera la lletra de la posició especificada.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Recupera una part especificada del text.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"en el text\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"recupera subcadena des de la lletra núm.#\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"recupera subcadena des de la lletra núm.# des del final\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"recupera subcadena des de la primera lletra\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"fins a la lletra núm.#\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"fins a la lletra núm.# des del final\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"fins a l'última lletra\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Retorna una còpia del text amb diferents majúscules/minúscules.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"a MAJÚSCULES\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"a minúscules\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"a Text De Títol\",\n    \"TEXT_TRIM_TOOLTIP\": \"Retorna una còpia del text on s'han esborrat els espais d'un o dels dos extrems.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"retalla espais de tots dos extrems\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"retalla espais de l'esquerra\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"retalla espais de la dreta\",\n    \"TEXT_PRINT_TITLE\": \"imprimir %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Imprimir el text, el nombre o altre valor especificat.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"demanar text amb el missatge\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"demanar un nombre amb el missatge\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Demana que l'usuari introdueixi un nombre.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Demana que l'usuari introdueixi un text.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"crear llista buida\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Retorna una llista, de longitud 0, que no conté cap dada.\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Crea una llista amb qualsevol nombre d'elements.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"crear llista amb\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"llista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Afegeix, esborra o reordena seccions per reconfigurar aquest bloc de llista.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Afegeix un element a la llista.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Crea una llista formada pel valor donat, repetit tantes vegades com s'indiqui.\",\n    \"LISTS_REPEAT_TITLE\": \"crea llista amb element %1 repetit %2 vegades\",\n    \"LISTS_LENGTH_TITLE\": \"longitud de %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Retorna la longitud d'una llista.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 és buida\",\n    \"LISTS_TOOLTIP\": \"Retorna cert si la llista és buida.\",\n    \"LISTS_INLIST\": \"en la llista\",\n    \"LISTS_INDEX_OF_FIRST\": \"buscar primera aparició d'un element\",\n    \"LISTS_INDEX_OF_LAST\": \"buscar última aparició d'un element\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Retorna l'índex de la primera/última aparició d'un element a la llista. Retorna 0 si no s'hi troba el text.\",\n    \"LISTS_GET_INDEX_GET\": \"recupera\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"recupera i esborra\",\n    \"LISTS_GET_INDEX_REMOVE\": \"esborra\",\n    \"LISTS_GET_INDEX_FROM_END\": \"núm.# des del final\",\n    \"LISTS_GET_INDEX_FIRST\": \"primer\",\n    \"LISTS_GET_INDEX_LAST\": \"últim\",\n    \"LISTS_GET_INDEX_RANDOM\": \"a l'atzar\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Retorna l'element de la posició especificada a la llista. #1 és el primer element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Retorna l'element de la posició especificada a la llista. #1 és l'últim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Retorna el primer element d'una llista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Retorna l'últim element d'una llista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Retorna un element a l'atzar d'una llista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Esborra i retorna l'element de la posició especificada de la llista. #1 és el primer element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Esborra i retorna l'element de la posició especificada de la llista. #1 és l'últim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Esborra i retorna el primer element d'una llista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Esborra i retorna l'últim element d'una llista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Esborra i retorna un element a l'atzar d'una llista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Esborra l'element de la posició especificada de la llista. #1 és el primer element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Esborra l'element de la posició especificada de la llista. #1 és l'últim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Esborra el primer element d'una llista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Esborra l'últim element d'una llista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Esborra un element a l'atzar d'una llista.\",\n    \"LISTS_SET_INDEX_SET\": \"modifica\",\n    \"LISTS_SET_INDEX_INSERT\": \"insereix a\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"com\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Modifica l'element de la posició especificada d'una llista. #1 és el primer element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Modifica l'element de la posició especificada d'una llista. #1 és l'últim element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Modifica el primer element d'una llista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Modifica l'últim element d'una llista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Modifica un element a l'atzar d'una llista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Insereix l'element a la posició especificada d'una llista. #1 és el primer element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Insereix l'element a la posició especificada d'una llista. #1 és l'últim element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Insereix l'element al principi d'una llista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Afegeix l'element al final d'una llista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Insereix l'element en una posició a l'atzar d'una llista.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"recupera sub-llista des de #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"recupera sub-llista des de # des del final\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"recupera sub-llista des del principi\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"fins #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"fins # des del final\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"fins l'últim\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Crea una còpia de la part especificada d'una llista.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Retorna el valor d'aquesta variable.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Crea 'modifica %1'\",\n    \"VARIABLES_SET_TITLE\": \"modifica\",\n    \"VARIABLES_SET_TAIL\": \"a\",\n    \"VARIABLES_SET_TOOLTIP\": \"Modifica aquesta variable al valor introduït.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Crear 'recupera %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"a\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"fes alguna cosa\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"amb:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Crea una funció sense sortida.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"retorna\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Crea una funció amb una sortida.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Advertència: Aquesta funció té paràmetres duplicats.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://ca.wikipedia.org/wiki/Procediment_%28Programació%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Executa la funció definida per usuari '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://ca.wikipedia.org/wiki/Procediment_%28Programació%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Executa la funció definida per l'usuari '%1' i utilitza la seva sortida.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"entrades\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nom d'entrada:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Iluminar la definició de la funció\",\n    \"PROCEDURES_CREATE_DO\": \"Crear '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Si el valor és cert, llavors retorna un segon valor.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Advertència: Aquest bloc només es pot utilitzar dins de la definició d'una funció.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/cs.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Chmee2\",\n            \"Rosnicka.kacka\",\n            \"Matěj Grabovský\",\n            \"Espertus\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"položka\",\n    \"DUPLICATE_BLOCK\": \"zdvojit\",\n    \"ADD_COMMENT\": \"Přidat komentář\",\n    \"REMOVE_COMMENT\": \"Odstranit komentář\",\n    \"EXTERNAL_INPUTS\": \"vnější vstupy\",\n    \"INLINE_INPUTS\": \"Vložené vstupy\",\n    \"DELETE_BLOCK\": \"Odstranit blok\",\n    \"DELETE_X_BLOCKS\": \"Odstranit %1 bloky\",\n    \"COLLAPSE_BLOCK\": \"Skrýt blok\",\n    \"COLLAPSE_ALL\": \"Skrýt bloky\",\n    \"EXPAND_BLOCK\": \"Rozbalení bloku\",\n    \"EXPAND_ALL\": \"Rozbalit bloky\",\n    \"DISABLE_BLOCK\": \"Zakázat blok\",\n    \"ENABLE_BLOCK\": \"Povolit blok\",\n    \"HELP\": \"Nápověda\",\n    \"CHANGE_VALUE_TITLE\": \"Změna hodnoty:\",\n    \"NEW_VARIABLE\": \"Nová proměnná...\",\n    \"NEW_VARIABLE_TITLE\": \"Nový název proměnné:\",\n    \"RENAME_VARIABLE\": \"Přejmenovat proměnné...\",\n    \"RENAME_VARIABLE_TITLE\": \"Přejmenujte všechny proměnné '%1':\",\n    \"COLOUR_PICKER_HELPURL\": \"https://cs.wikipedia.org/wiki/Barva\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Vyberte barvu z palety.\",\n    \"COLOUR_RANDOM_TITLE\": \"náhodná barva\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Zvolte barvu náhodně.\",\n    \"COLOUR_RGB_TITLE\": \"barva s\",\n    \"COLOUR_RGB_RED\": \"červená\",\n    \"COLOUR_RGB_GREEN\": \"zelená\",\n    \"COLOUR_RGB_BLUE\": \"modrá\",\n    \"COLOUR_RGB_TOOLTIP\": \"Vytvoř barvu se zadaným množstvím červené, zelené a modré.  Všechny hodnoty musí být mezi 0 a 100.\",\n    \"COLOUR_BLEND_TITLE\": \"smíchat\",\n    \"COLOUR_BLEND_COLOUR1\": \"barva 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"barva 2\",\n    \"COLOUR_BLEND_RATIO\": \"poměr\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Smíchá dvě barvy v daném poměru (0.0–1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://cs.wikipedia.org/wiki/Cyklus_for\",\n    \"CONTROLS_REPEAT_TITLE\": \"opakovat %1 krát\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"opakovat\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"krát\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"udělej\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Proveď určité příkazy několikrát.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"opakovat když\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"opakovat dokud\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Dokud je hodnota pravdivá, prováděj určité příkazy.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Dokud je hodnota nepravdivá, prováděj určité příkazy.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Nechá proměnnou %1 nabývat hodnot od počátečního do koncového čísla po daném přírůstku a provádí s ní příslušné bloky.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"počítat s\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"od %1 do %2 po %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"pro každou položku\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"v seznamu\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Pro každou položku v seznamu nastavte do proměnné '%1' danou položku a proveďte nějaké operace.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"vymanit se ze smyčky\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"pokračuj dalším opakováním smyčky\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Přeruš vnitřní smyčku.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Přeskoč zbytek této smyčky a pokračuj dalším opakováním.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Upozornění: Tento blok může být použit pouze uvnitř smyčky.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Je-li hodnota pravda, proveď určité příkazy.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Je-li hodnota pravda, proveď první blok příkazů.  V opačném případě proveď druhý blok příkazů.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Je-li první hodnota pravdivá, proveď první blok příkazů. V opačném případě, je-li pravdivá druhá hodnota, proveď druhý blok příkazů.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Je-li první hodnota pravda, proveď první blok příkazů.  Je-li druhá hodnota pravda, proveď druhý blok příkazů.  Pokud žádná hodnota není pravda, proveď poslední blok příkazů.\",\n    \"CONTROLS_IF_MSG_IF\": \"pokud\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"nebo pokud\",\n    \"CONTROLS_IF_MSG_ELSE\": \"jinak\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Přidej, odstraň či uspořádej sekce k přenastavení tohoto bloku pokud.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Přidat podmínku do \\\"pokud\\\" bloku.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Přidej konečnou podmínku zahrnující ostatní případy do bloku pokud.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://cs.wikipedia.org/wiki/Nerovnost_(matematika)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Vrátí hodnotu pravda, pokud se oba vstupy rovnají jeden druhému.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Vrátí hodnotu pravda, pokud se oba vstupy nerovnají sobě navzájem.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Navrátí hodnotu pravda, pokud je první vstup menší než druhý vstup.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Navrátí hodnotu pravda, pokud je první vstup menší a nebo rovný druhému vstupu.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Navrátí hodnotu pravda, pokud první vstup je větší než druhý vstup.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Navrátí hodnotu pravda, pokud je první vstup větší a nebo rovný druhému vstupu.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Vrátí hodnotu pravda, pokud oba dva vstupy jsou pravdivé.\",\n    \"LOGIC_OPERATION_AND\": \"a\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Vrátí hodnotu pravda, pokud alespoň jeden ze vstupů má hodnotu pravda.\",\n    \"LOGIC_OPERATION_OR\": \"nebo\",\n    \"LOGIC_NEGATE_TITLE\": \"není %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Navrátí hodnotu pravda, pokud je vstup nepravda. Navrátí hodnotu nepravda, pokud je vstup pravda.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"pravda\",\n    \"LOGIC_BOOLEAN_FALSE\": \"nepravda\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Vrací pravda nebo nepravda.\",\n    \"LOGIC_NULL\": \"nula\",\n    \"LOGIC_NULL_TOOLTIP\": \"Vrátí nulovou hodnotu\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"je-li to pravda\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"je-li nepravda\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Zkontroluje podmínku v \\\"testu\\\". Když je podmínka pravda, vrátí hodnotu \\\"pokud pravda\\\"; v opačném případě vrátí hodnotu \\\"pokud nepravda\\\".\",\n    \"MATH_NUMBER_HELPURL\": \"https://cs.wikipedia.org/wiki/Číslo\",\n    \"MATH_NUMBER_TOOLTIP\": \"Číslo.\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"arcsin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"arctan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://cs.wikipedia.org/wiki/Aritmetika\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Vrátí součet dvou čísel.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Vrátí rozdíl dvou čísel.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Vrátí součin dvou čísel.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Vrátí podíl dvou čísel.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Vrátí první číslo umocněné na druhé číslo.\",\n    \"MATH_SINGLE_HELPURL\": \"https://cs.wikipedia.org/wiki/Druhá_odmocnina\",\n    \"MATH_SINGLE_OP_ROOT\": \"druhá odmocnina\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Vrátí druhou odmocninu čísla.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolutní\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Vrátí absolutní hodnotu čísla.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Vrátí zápornou hodnotu čísla.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Vrátí přirozený logaritmus čísla.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Vrátí desítkový logaritmus čísla.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Vrátí mocninu čísla e.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Vrátí mocninu čísla 10.\",\n    \"MATH_TRIG_HELPURL\": \"https://cs.wikipedia.org/wiki/Goniometrická_funkce\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Vrátí sinus úhlu ve stupních.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Vrátí kosinus úhlu ve stupních.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Vrátí tangens úhlu ve stupních.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Vrátí arcsinus čísla.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Vrátí arckosinus čísla.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Vrátí arctangens čísla.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Vraťte jednu z následujících konstant: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"je sudé\",\n    \"MATH_IS_ODD\": \"je liché\",\n    \"MATH_IS_PRIME\": \"je prvočíslo\",\n    \"MATH_IS_WHOLE\": \"je celé\",\n    \"MATH_IS_POSITIVE\": \"je kladné\",\n    \"MATH_IS_NEGATIVE\": \"je záporné\",\n    \"MATH_IS_DIVISIBLE_BY\": \"je dělitelné\",\n    \"MATH_IS_TOOLTIP\": \"Kontrola, zda je číslo sudé, liché, prvočíslo, celé, kladné, záporné nebo zda je dělitelné daným číslem. Vrací pravdu nebo nepravdu.\",\n    \"MATH_CHANGE_HELPURL\": \"https://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"změnit\",\n    \"MATH_CHANGE_INPUT_BY\": \"od\",\n    \"MATH_CHANGE_TOOLTIP\": \"Přičti číslo k proměnné '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://cs.wikipedia.org/wiki/Zaokrouhlení\",\n    \"MATH_ROUND_TOOLTIP\": \"Zaokrouhlit číslo nahoru nebo dolů.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"zaokrouhlit\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"zaokrouhlit nahoru\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"zaokrouhlit dolu\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"suma seznamu\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Vrátí součet všech čísel v seznamu.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"nejmenší v seznamu\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Vrátí nejmenší číslo v seznamu.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"největší v seznamu\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Vrátí největší číslo v seznamu.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"průměr v seznamu\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Vrátí průměr (aritmetický průměr) číselných hodnot v seznamu.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"medián v seznamu\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Vrátí medián seznamu.\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Vrátí seznam nejčastějších položek seznamu.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"směrodatná odchylka ze seznamu\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Vrátí směrodatnou odchylku seznamu.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"náhodná položka seznamu\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Vrátí náhodnou položku ze seznamu.\",\n    \"MATH_MODULO_HELPURL\": \"https://cs.wikipedia.org/wiki/Modul%C3%A1rn%C3%AD_aritmetika\",\n    \"MATH_MODULO_TITLE\": \"zbytek po dělení %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Vrátí zbytek po dělení dvou čísel.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"omez %1 na rozmezí od %2 do %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Omezí číslo tak, aby bylo ve stanovených mezích (včetně).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://cs.wikipedia.org/wiki/Gener%C3%A1tor_n%C3%A1hodn%C3%BDch_%C4%8D%C3%ADsel\",\n    \"MATH_RANDOM_INT_TITLE\": \"náhodné celé číslo od %1 do %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Vrací náhodné celé číslo mezi dvěma určenými mezemi, včetně mezních hodnot.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://cs.wikipedia.org/wiki/Gener%C3%A1tor_n%C3%A1hodn%C3%BDch_%C4%8D%C3%ADsel\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"náhodné číslo mezi 0 (včetně) do 1\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Vrátí náhodné číslo mezi 0,0 (včetně) až 1,0\",\n    \"TEXT_TEXT_HELPURL\": \"https://cs.wikipedia.org/wiki/Textov%C3%BD_%C5%99et%C4%9Bzec\",\n    \"TEXT_TEXT_TOOLTIP\": \"Písmeno, slovo nebo řádek textu.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"vytvořit text s\",\n    \"TEXT_JOIN_TOOLTIP\": \"Vytvoří kousek textu spojením libovolného počtu položek.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"spojit\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Přidat, odebrat nebo změnit pořadí oddílů tohoto textového bloku.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Přidat položku do textu.\",\n    \"TEXT_APPEND_TO\": \"do\",\n    \"TEXT_APPEND_APPENDTEXT\": \"přidat text\",\n    \"TEXT_APPEND_TOOLTIP\": \"Přidá určitý text k proměnné '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"délka %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Vrátí počet písmen (včetně mezer) v zadaném textu.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 je prázdný\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Vrátí pravda pokud je zadaný text prázdný.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Vrátí index prvního/posledního výskytu prvního textu v druhém textu.  Pokud text není nalezen, vrátí hodnotu 0.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"v textu\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"najít první výskyt textu\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"najít poslední výskyt textu\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"v textu\",\n    \"TEXT_CHARAT_FROM_START\": \"získat písmeno #\",\n    \"TEXT_CHARAT_FROM_END\": \"získat # písmeno od konce\",\n    \"TEXT_CHARAT_FIRST\": \"získat první písmeno\",\n    \"TEXT_CHARAT_LAST\": \"získat poslední písmeno\",\n    \"TEXT_CHARAT_RANDOM\": \"získat náhodné písmeno\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Získat písmeno na konkrétní pozici.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Získat zadanou část textu.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"v textu\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"získat podřetězec od písmene #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"získat podřetězec od písmene # od konce\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"získat podřetězec od prvního písmene\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"do písmene #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"do # písmene od konce\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"do posledního písmene\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Vrátí kopii textu s jinou velikostí písmen.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"na VELKÁ PÍSMENA\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"na malá písmena\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"na Počáteční Velká Písmena\",\n    \"TEXT_TRIM_TOOLTIP\": \"Vrátí kopii textu s odstraněnými mezerami z jednoho nebo obou konců.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"odstranit mezery z obou stran\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"odstranit mezery z levé strany\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"odstranit mezery z pravé strany\",\n    \"TEXT_PRINT_TITLE\": \"tisk %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Tisk zadaného textu, čísla nebo jiné hodnoty.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"výzva k zadání textu se zprávou\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"výzva k zadání čísla se zprávou\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Výzva pro uživatele k zadání čísla.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Výzva pro uživatele k zadání nějakého textu.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"vytvořit prázdný seznam\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Vrátí seznam nulové délky, který neobsahuje žádné datové záznamy\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Vytvoř seznam s libovolným počtem položek.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"vytvořit seznam s\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"seznam\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Přidat, odebrat nebo změnit pořadí oddílů tohoto seznamu bloku.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Přidat položku do seznamu.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Vytváří seznam obsahující danou hodnotu n-krát.\",\n    \"LISTS_REPEAT_TITLE\": \"vytvoř seznam s položkou %1 opakovanou %1 krát\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"délka %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Vrací počet položek v seznamu.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 je prázdné\",\n    \"LISTS_INLIST\": \"v seznamu\",\n    \"LISTS_INDEX_OF_FIRST\": \"najít první výskyt položky\",\n    \"LISTS_INDEX_OF_LAST\": \"najít poslední výskyt položky\",\n    \"LISTS_GET_INDEX_GET\": \"získat\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"získat a odstranit\",\n    \"LISTS_GET_INDEX_REMOVE\": \"odstranit\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# od konce\",\n    \"LISTS_GET_INDEX_FIRST\": \"první\",\n    \"LISTS_GET_INDEX_LAST\": \"poslední\",\n    \"LISTS_GET_INDEX_RANDOM\": \"náhodné\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Vrátí položku z určené pozice v seznamu.  #1 je první položka.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Vrátí položku z určené pozice v seznamu.  #1 je poslední položka.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Vrátí první položku v seznamu.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Vrátí poslední položku v seznamu.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Vrátí náhodnou položku ze seznamu.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Odstraní a vrátí položku z určené pozice v seznamu.  #1 je první položka.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Odstraní a vrátí položku z určené pozice v seznamu.  #1 je poslední položka.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Odstraní a vrátí první položku v seznamu.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Odstraní a vrátí poslední položku v seznamu.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Odstraní a vrátí náhodnou položku v seznamu.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Odebere položku na konkrétním místě v seznamu.  #1 je první položka.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Odstraní položku na konkrétním místu v seznamu. #1 je poslední položka.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Odstraní první položku v seznamu.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Odstraní poslední položku v seznamu.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Odstraní náhodou položku v seznamu.\",\n    \"LISTS_SET_INDEX_SET\": \"nastavit\",\n    \"LISTS_SET_INDEX_INSERT\": \"vložit na\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"jako\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Nastaví položku na konkrétní místo v seznamu. #1 je první položka.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Nastaví položku na konkrétní místo v seznamu. #1 je poslední položka.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Nastaví první položku v seznamu.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Nastaví poslední položku v seznamu.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Nastaví náhodnou položku v seznamu.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Vloží položku na určenou pozici v seznamu.  #1 je první položka.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Vloží položku na určenou pozici v seznamu.  #1 je poslední položka.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Vložit položku na začátek seznamu.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Připojí položku na konec seznamu.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Připojí položku náhodně do seznamu.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"získat podseznam od #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"získat podseznam od # od konce\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"získat podseznam od první položky\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"do #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"do # od konce\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"jako poslední\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Vytvoří kopii určené části seznamu.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Vrátí hodnotu této proměnné.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Vytvořit \\\"nastavit %1\\\"\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"nastavit\",\n    \"VARIABLES_SET_TAIL\": \"na\",\n    \"VARIABLES_SET_TOOLTIP\": \"Nastaví tuto proměnnou, aby se rovnala vstupu.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Vytvořit \\\"získat %1\\\"\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"k provedení\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"proveď něco\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"s:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Vytvořit funkci bez výstupu.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"navrátit\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Vytvořit funkci s výstupem.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Upozornění: Tato funkce má duplicitní parametry.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://cs.wikipedia.org/wiki/Funkce_(programov%C3%A1n%C3%AD)\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Spustí uživatelem definovanou funkci '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://cs.wikipedia.org/wiki/Funkce_(programov%C3%A1n%C3%AD)\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Spustí uživatelem definovanou funkci '%1' a použije její výstup.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"vstupy\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"vstupní jméno:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Zvýraznit definici funkce\",\n    \"PROCEDURES_CREATE_DO\": \"Vytvořit '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Je-li hodnota pravda, pak vrátí druhou hodnotu.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Varování: Tento blok může být použit pouze uvnitř definici funkce.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/da.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Christian List\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"element\",\n    \"DUPLICATE_BLOCK\": \"Kopiér\",\n    \"ADD_COMMENT\": \"Tilføj kommentar\",\n    \"REMOVE_COMMENT\": \"Fjern kommentar\",\n    \"EXTERNAL_INPUTS\": \"Udvendige inputs\",\n    \"INLINE_INPUTS\": \"Indlejrede inputs\",\n    \"DELETE_BLOCK\": \"Slet blok\",\n    \"DELETE_X_BLOCKS\": \"Slet %1 blokke\",\n    \"COLLAPSE_BLOCK\": \"Fold blokken sammen\",\n    \"COLLAPSE_ALL\": \"Fold blokkene sammen\",\n    \"EXPAND_BLOCK\": \"Fold blokken ud\",\n    \"EXPAND_ALL\": \"Fold blokkene ud\",\n    \"DISABLE_BLOCK\": \"Deaktivér blok\",\n    \"ENABLE_BLOCK\": \"Aktivér blok\",\n    \"HELP\": \"Hjælp\",\n    \"CHANGE_VALUE_TITLE\": \"Ændr værdi:\",\n    \"NEW_VARIABLE\": \"Ny variabel...\",\n    \"NEW_VARIABLE_TITLE\": \"Navn til den nye variabel:\",\n    \"RENAME_VARIABLE\": \"Omdøb variabel...\",\n    \"RENAME_VARIABLE_TITLE\": \"Omdøb alle '%1' variabler til:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://da.wikipedia.org/wiki/Farve\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Vælg en farve fra paletten.\",\n    \"COLOUR_RANDOM_TITLE\": \"tilfældig farve\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Vælg en tilfældig farve.\",\n    \"COLOUR_RGB_TITLE\": \"farve med\",\n    \"COLOUR_RGB_RED\": \"rød\",\n    \"COLOUR_RGB_GREEN\": \"grøn\",\n    \"COLOUR_RGB_BLUE\": \"blå\",\n    \"COLOUR_RGB_TOOLTIP\": \"Lav en farve med den angivne mængde af rød, grøn og blå. Alle værdier skal være mellem 0 og 100.\",\n    \"COLOUR_BLEND_TITLE\": \"bland\",\n    \"COLOUR_BLEND_COLOUR1\": \"farve 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"med farve 2\",\n    \"COLOUR_BLEND_RATIO\": \"i forholdet\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Blander to farver sammen i et bestemt forhold (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://da.wikipedia.org/wiki/For-l%C3%B8kke\",\n    \"CONTROLS_REPEAT_TITLE\": \"gentag %1 gange\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"gentag\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"gange\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"udfør\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Udfør nogle kommandoer flere gange.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"gentag sålænge\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"gentag indtil\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Udfør nogle kommandoer, sålænge en værdi er sand.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Udfør nogle kommandoer, sålænge en værdi er falsk.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Få variablen %1 til at have værdierne fra startværdien til slutværdien, mens der tælles med det angivne interval, og udfør de angivne blokke.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"tæl med\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"fra %1 til %2 med %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"for hvert element\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"i listen\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"For hvert element i en liste, sæt variablen '%1' til elementet, og udfør derefter nogle kommandoer.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"bryd ud af løkken\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"fortsæt med den næste gentagelse i løkken\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Bryd ud af den omgivende løkke.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Spring resten af denne løkke over, og fortsæt med den næste gentagelse.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Advarsel: Denne blok kan kun bruges i en løkke.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Hvis en værdi er sand, så udfør nogle kommandoer.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Hvis en værdi er sand, så udfør den første blok af kommandoer. Ellers udfør den anden blok af kommandoer.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Hvis den første værdi er sand, så udfør den første blok af kommandoer.  Ellers, hvis den anden værdi er sand, så udfør den anden blok af kommandoer.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Hvis den første værdi er sand, så udfør den første blok af kommandoer. Ellers, hvis den anden værdi er sand, så udfør den anden blok af kommandoer. Hvis ingen af værdierne er sande, så udfør den sidste blok af kommandoer.\",\n    \"CONTROLS_IF_MSG_IF\": \"hvis\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"ellers hvis\",\n    \"CONTROLS_IF_MSG_ELSE\": \"ellers\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne \\\"hvis\\\" blok.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Tilføj en betingelse til denne \\\"hvis\\\" blok.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Tilføj en sidste fang-alt betingelse, til denne \\\"hvis\\\" blok.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://da.wikipedia.org/wiki/Ulighed_(matematik)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Returnere sand, hvis begge inputs er lig med hinanden.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Returnere sand, hvis begge inputs ikke er lig med hinanden.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Returnere sand, hvis det første input er mindre end det andet input.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Returnere sand, hvis det første input er mindre end eller lig med det andet input.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Returnere sand, hvis det første input er større end det andet input.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Returnere sand, hvis det første input er større end eller lig med det andet input.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Returnere sand, hvis begge inputs er sande.\",\n    \"LOGIC_OPERATION_AND\": \"og\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Returnere sand, hvis mindst et af inputtene er sande.\",\n    \"LOGIC_OPERATION_OR\": \"eller\",\n    \"LOGIC_NEGATE_TITLE\": \"ikke %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Returnerer sand, hvis input er falsk. Returnerer falsk, hvis input er sandt.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"sand\",\n    \"LOGIC_BOOLEAN_FALSE\": \"falsk\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Returnerer enten sand eller falsk.\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"Returnerer null.\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"hvis sand\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"hvis falsk\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Kontrollér betingelsen i 'test'. Hvis betingelsen er sand, returnér \\\"hvis sand\\\" værdien; ellers returnér \\\"hvis falsk\\\" værdien.\",\n    \"MATH_NUMBER_HELPURL\": \"https://da.wikipedia.org/wiki/Tal\",\n    \"MATH_NUMBER_TOOLTIP\": \"Et tal.\",\n    \"MATH_DIVISION_SYMBOL\": \":\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://da.wikipedia.org/wiki/Aritmetik\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Returnere summen af de to tal.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Returnere forskellen mellem de to tal.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Returnere produktet af de to tal.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Returnere kvotienten af de to tal.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Returnere det første tal opløftet til potensen af det andet tal.\",\n    \"MATH_SINGLE_HELPURL\": \"https://da.wikipedia.org/wiki/Kvadratrod\",\n    \"MATH_SINGLE_OP_ROOT\": \"kvadratrod\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Returnere kvadratroden af et tal.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolut\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Returnere den absolutte værdi af et tal.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Returnere negationen af et tal.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Returnere den naturlige logaritme af et tal.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Returnere 10-talslogaritmen af et tal.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Returnere e til potensen af et tal.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Returnere 10 til potensen af et tal.\",\n    \"MATH_TRIG_HELPURL\": \"https://da.wikipedia.org/wiki/Trigonometrisk_funktion\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Returnere sinus af en vinkel (i grader).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Returnere cosinus af en vinkel (i grader).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Returnere tangens af en vinkel (i grader).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Returnere arcus sinus af et tal.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Returnere arcus cosinus af et tal.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Returnere arcus tangens af et tal.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://da.wikipedia.org/wiki/Matematisk_konstant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Returnere en af de ofte brugte konstanter: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(2) (1.414…), sqrt(½) (0.707…) eller ∞ (uendeligt).\",\n    \"MATH_IS_EVEN\": \"er lige\",\n    \"MATH_IS_ODD\": \"er ulige\",\n    \"MATH_IS_PRIME\": \"er et primtal\",\n    \"MATH_IS_WHOLE\": \"er helt\",\n    \"MATH_IS_POSITIVE\": \"er positivt\",\n    \"MATH_IS_NEGATIVE\": \"er negativt\",\n    \"MATH_IS_DIVISIBLE_BY\": \"er deleligt med\",\n    \"MATH_IS_TOOLTIP\": \"Kontrollere, om et tal er lige, ulige, primtal, helt, positivt, negativt, eller om det er deleligt med bestemt tal. Returnere sandt eller falskt.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"ændr\",\n    \"MATH_CHANGE_INPUT_BY\": \"med\",\n    \"MATH_CHANGE_TOOLTIP\": \"Læg et tal til variablen '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://da.wikipedia.org/wiki/Afrunding\",\n    \"MATH_ROUND_TOOLTIP\": \"Runde et tal op eller ned.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"afrund\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"rund op\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"rund ned\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"summen af listen\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Returner summen af alle tal i listen.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"mindste tal i listen\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Returner det mindste tal i listen.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"største tal i listen\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Returner det største tal i listen.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"gennemsnit af listen\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Returner gennemsnittet (middelværdien) af de numeriske værdier i listen.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"listens median\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Returner listens median.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"listens typetal\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Returner en liste over de mest almindelige elementer på listen.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"standardafvigelsen for listen\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Returner standardafvigelsen for listen.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"tilfældigt element fra listen\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Returner et tilfældigt element fra listen.\",\n    \"MATH_MODULO_HELPURL\": \"https://da.wikipedia.org/wiki/Modulo\",\n    \"MATH_MODULO_TITLE\": \"resten af %1 : %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Returner resten fra at dividere de to tal.\",\n    \"MATH_CONSTRAIN_TITLE\": \"begræns %1 til mellem %2 og %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Begræns et tal til at være mellem de angivne grænser (inklusiv).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://da.wikipedia.org/wiki/Tilfældighedsgenerator\",\n    \"MATH_RANDOM_INT_TITLE\": \"tilfældigt heltal mellem %1 og %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Returner et tilfældigt heltal mellem de to angivne grænser (inklusiv).\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://da.wikipedia.org/wiki/Tilfældighedsgenerator\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"tilfældigt decimaltal (mellem 0 og 1)\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Returner et tilfældigt decimaltal mellem 0,0 (inklusiv) og 1,0 (eksklusiv).\",\n    \"TEXT_TEXT_HELPURL\": \"https://da.wikipedia.org/wiki/Tekststreng\",\n    \"TEXT_TEXT_TOOLTIP\": \"En bogstav, et ord eller en linje med tekst.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"lav en tekst med\",\n    \"TEXT_JOIN_TOOLTIP\": \"Lav et stykke tekst ved at sætte et antal elementer sammen.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"sammenføj\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne tekstblok.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Føj et element til teksten.\",\n    \"TEXT_APPEND_TO\": \"til\",\n    \"TEXT_APPEND_APPENDTEXT\": \"tilføj tekst\",\n    \"TEXT_APPEND_TOOLTIP\": \"Tilføj noget tekst til variablen '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"længden af %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Returnerer antallet af bogstaver (herunder mellemrum) i den angivne tekst.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 er tom\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Returnerer sand, hvis den angivne tekst er tom.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Returnerer indeks for første/sidste forekomst af første tekst i den anden tekst.  Returnerer 0, hvis teksten ikke kan findes.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"i teksten\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"find første forekomst af teksten\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"find sidste forekomst af teksten\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"i teksten\",\n    \"TEXT_CHARAT_FROM_START\": \"hent bogstav #\",\n    \"TEXT_CHARAT_FROM_END\": \"hent bogstav # fra slutningen\",\n    \"TEXT_CHARAT_FIRST\": \"hent første bogstav\",\n    \"TEXT_CHARAT_LAST\": \"hent sidste bogstav\",\n    \"TEXT_CHARAT_RANDOM\": \"hent tilfældigt bogstav\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Returnerer bogstavet på den angivne placering.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Returnerer den angivne del af teksten.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"i teksten\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"hent delstreng fra bogstav #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"hent delstreng fra bogstav # fra slutningen\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"hent delstreng fra første bogstav\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"til bogstav #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"til bogstav # fra slutningen\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"til sidste bogstav\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Returner en kopi af teksten hvor bogstaverne enten er udelukkende store eller små, eller hvor første bogstav i hvert ord er stort.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"til STORE BOGSTAVER\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"til små bogstaver\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"til Stort Begyndelsesbogstav\",\n    \"TEXT_TRIM_TOOLTIP\": \"Returner en kopi af teksten med mellemrum fjernet fra den ene eller begge sider.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"fjern mellemrum fra begge sider af\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"fjern mellemrum fra venstre side af\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"fjern mellemrum fra højre side af\",\n    \"TEXT_PRINT_TITLE\": \"skriv %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Skriv den angivne tekst, tal eller anden værdi.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"spørg efter tekst med meddelelsen\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"spørg efter et tal med meddelelsen\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Spørg brugeren efter et tal\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Spørg brugeren efter en tekst\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"opret en tom liste\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Returnerer en liste af længde 0, som ikke indeholder nogen data\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Opret en liste med et vilkårligt antal elementer.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"opret liste med\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"liste\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne blok.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Føj et element til listen.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Opretter en liste bestående af den givne værdi gentaget et bestemt antal gange.\",\n    \"LISTS_REPEAT_TITLE\": \"opret liste med elementet %1 gentaget %2 gange\",\n    \"LISTS_LENGTH_TITLE\": \"længden af %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Returnerer længden af en liste.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 er tom\",\n    \"LISTS_TOOLTIP\": \"Returnerer sand, hvis listen er tom.\",\n    \"LISTS_INLIST\": \"i listen\",\n    \"LISTS_INDEX_OF_FIRST\": \"find første forekomst af elementet\",\n    \"LISTS_INDEX_OF_LAST\": \"find sidste forekomst af elementet\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Returnerer indeks for første/sidste forekomst af elementet i listen. Returnerer 0, hvis teksten ikke er fundet.\",\n    \"LISTS_GET_INDEX_GET\": \"hent\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"hent og fjern\",\n    \"LISTS_GET_INDEX_REMOVE\": \"fjern\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# fra slutningen\",\n    \"LISTS_GET_INDEX_FIRST\": \"første\",\n    \"LISTS_GET_INDEX_LAST\": \"sidste\",\n    \"LISTS_GET_INDEX_RANDOM\": \"tilfældig\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Returnerer elementet på den angivne position på en liste. #1 er det første element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Returnerer elementet på den angivne position på en liste. #1 er det sidste element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Returnerer det første element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Returnerer den sidste element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Returnerer et tilfældigt element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Fjerner og returnerer elementet på den angivne position på en liste. #1 er det første element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Fjerner og returnerer elementet på den angivne position på en liste. #1 er det sidste element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Fjerner og returnerer det første element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Fjerner og returnerer det sidste element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Fjerner og returnerer et tilfældigt element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Fjerner elementet på den angivne position på en liste. #1 er det første element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Fjerner elementet på den angivne position på en liste. #1 er det sidste element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Fjerner det første element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Fjerner sidste element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Fjerner et tilfældigt element i en liste.\",\n    \"LISTS_SET_INDEX_SET\": \"sæt\",\n    \"LISTS_SET_INDEX_INSERT\": \"sæt ind ved\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"som\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Sætter elementet på den angivne position i en liste. #1 er det første element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Sætter elementet på den angivne position i en liste. #1 er det sidste element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Sætter det første element i en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Sætter det sidste element i en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Sætter et tilfældigt element i en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Indsætter elementet på den angivne position i en liste. #1 er det første element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Indsætter elementet på den angivne position i en liste. #1 er det sidste element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Indsætter elementet i starten af en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Føj elementet til slutningen af en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Indsætter elementet tilfældigt i en liste.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"hent underliste fra #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"hent underliste fra # fra slutningen\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"hent underliste fra første\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"til #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"til # fra slutningen\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"til sidste\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Opretter en kopi af den angivne del af en liste.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Returnerer værdien af denne variabel.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Opret 'sæt %1'\",\n    \"VARIABLES_SET_TITLE\": \"sæt\",\n    \"VARIABLES_SET_TAIL\": \"til\",\n    \"VARIABLES_SET_TOOLTIP\": \"Sætter denne variabel til at være lig med input.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Opret 'hent %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"for at\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"gøre noget\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"med:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Opretter en funktion der ikke har output.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"returnér\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Opretter en funktion der har output.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Advarsel: Denne funktion har dublerede parametre.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://da.wikipedia.org/wiki/Funktion_%28programmering%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Kør den brugerdefinerede funktion '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://da.wikipedia.org/wiki/Funktion_%28programmering%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Kør den brugerdefinerede funktion '%1' og brug dens output.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"inputs\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"parameternavn:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Markér funktionsdefinitionen\",\n    \"PROCEDURES_CREATE_DO\": \"Opret '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Hvis en værdi er sand, så returnér en anden værdi.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Advarsel: Denne blok kan kun anvendes inden for en funktionsdefinition.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/de.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Metalhead64\",\n            \"M165437\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"Element\",\n    \"DUPLICATE_BLOCK\": \"Kopieren\",\n    \"ADD_COMMENT\": \"Kommentar hinzufügen\",\n    \"REMOVE_COMMENT\": \"Kommentar entfernen\",\n    \"EXTERNAL_INPUTS\": \"externe Eingänge\",\n    \"INLINE_INPUTS\": \"interne Eingänge\",\n    \"DELETE_BLOCK\": \"Block löschen\",\n    \"DELETE_X_BLOCKS\": \"Block %1 löschen\",\n    \"COLLAPSE_BLOCK\": \"Block zusammenfalten\",\n    \"COLLAPSE_ALL\": \"Collapse Blocks\",\n    \"EXPAND_BLOCK\": \"Block entfalten\",\n    \"EXPAND_ALL\": \"Expand Blocks\",\n    \"DISABLE_BLOCK\": \"Block deaktivieren\",\n    \"ENABLE_BLOCK\": \"Block aktivieren\",\n    \"HELP\": \"Hilfe\",\n    \"CHAT\": \"Chatte mit unserem Mitarbeiter durch Eingeben von Text in diesen Kasten!\",\n    \"CHANGE_VALUE_TITLE\": \"Wert ändern:\",\n    \"NEW_VARIABLE\": \"Neue Variable...\",\n    \"NEW_VARIABLE_TITLE\": \"Name der neuen Variable:\",\n    \"RENAME_VARIABLE\": \"Variable umbenennen...\",\n    \"RENAME_VARIABLE_TITLE\": \"Alle \\\"%1\\\" Variablen umbenennen in:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://de.wikipedia.org/wiki/Farbe\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Wählen eine Farbe von der Palette.\",\n    \"COLOUR_RANDOM_TITLE\": \"zufällige Farbe\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Wählen Sie eine Farbe nach dem Zufallsprinzip.\",\n    \"COLOUR_RGB_HELPURL\": \"https://de.wikipedia.org/wiki/RGB-Farbraum\",\n    \"COLOUR_RGB_TITLE\": \"Farbe mit\",\n    \"COLOUR_RGB_RED\": \"rot\",\n    \"COLOUR_RGB_GREEN\": \"grün\",\n    \"COLOUR_RGB_BLUE\": \"blau\",\n    \"COLOUR_RGB_TOOLTIP\": \"Kreiere eine Farbe mit selbst definierten rot, grün und blau Werten. Alle Werte müssen zwischen 0 und 100 liegen.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"mische\",\n    \"COLOUR_BLEND_COLOUR1\": \"Farbe 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"mit Farbe 2\",\n    \"COLOUR_BLEND_RATIO\": \"im Verhältniss\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Vermische 2 Farbe mit konfigurierbaren Farbverhältniss (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://de.wikipedia.org/wiki/For-Schleife\",\n    \"CONTROLS_REPEAT_TITLE\": \"wiederhole %1 mal\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"wiederhole\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"mal\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"mache\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Eine Anweisung mehrfach ausführen.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"https://de.wikipedia.org/wiki/Schleife_%28Programmierung%29\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"Wiederhole solange\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"Wiederhole bis\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Führe die Anweisung solange aus wie die Bedingung wahr (true) ist.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Führe die Anweisung solange aus wie die Bedingung falsch (false) ist.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://de.wikipedia.org/wiki/For-Schleif\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Zähle die Variable \\\"%1\\\" von einem Startwert bis zu einem Zielwert und führe für jeden Wert eine Anweisung aus.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"Zähle\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"von %1 bis %2 mit %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://de.wikipedia.org/wiki/For-Schleif\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"Für Wert\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"aus der Liste\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Führe eine Anweisung für jeden Wert in der Liste aus und setzte dabei die Variable \\\"%1\\\" auf den aktuellen Listen Wert.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://de.wikipedia.org/wiki/Kontrollstruktur\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"ausbrechen aus der Schleife\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"mit der nächsten Iteration fortfahren aus der Schleife\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Die umgebene Schleife beenden.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Diese Anweisung abbrechen und mit der nächsten Schleifeniteration fortfahren.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Warnung: Diese block sollte nur in einer Schleife verwendet werden.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Wenn eine Bedingung wahr (true) ist, dann führe eine Anweisung aus.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Wenn eine Bedingung wahr (true) ist, dann führe die erste Anweisung aus.  Ansonsten führe die zweite Anweisung aus.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Wenn der erste Bedingung wahr (true) ist, dann führe die erste Anweisung aus.  Oder wenn die zweite Bedingung wahr (true) ist, dann führe die zweite Anweisung aus.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Wenn der erste Bedingung wahr (true) ist, dann führe die erste Anweisung aus.  Oder wenn die zweite Bedingung wahr (true) ist, dann führe die zweite Anweisung aus.  Falls keine der beiden Bedingungen wahr (true) ist, dann führe die dritte Anweisung aus.\",\n    \"CONTROLS_IF_MSG_IF\": \"wenn\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"oder wenn\",\n    \"CONTROLS_IF_MSG_ELSE\": \"oder\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Hinzufügen, entfernen oder sortieren von Sektionen\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Eine weitere Bedingung hinzufügen.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Eine oder Bedingung hinzufügen, führt eine Anweisung aus falls keine Bedingung zutrifft.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://de.wikipedia.org/wiki/Vergleich_%28Zahlen%29\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Ist wahr (true) wenn beide Werte identisch sind.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Ist wahr (true) wenn beide Werte unterschiedlich sind.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Ist wahr (true) wenn der erste Wert kleiner als der zweite Wert ist.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Ist wahr (true) wenn der erste Wert kleiner als oder gleich gross wie zweite Wert ist.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Ist wahr (true) wenn der erste Wert grösser als der zweite Wert ist.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Ist wahr (true) wenn der erste Wert grösser als oder gleich gross wie zweite Wert ist.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Ist wahr (true) wenn beide Werte wahr (true) sind.\",\n    \"LOGIC_OPERATION_AND\": \"und\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Ist wahr (true) wenn einer der beiden Werte wahr (true) ist.\",\n    \"LOGIC_OPERATION_OR\": \"oder\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"nicht %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Ist wahr (true) wenn der Eingabewert falsch (false) ist.  Ist falsch (false) wenn der Eingabewert wahr (true) ist.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"wahr\",\n    \"LOGIC_BOOLEAN_FALSE\": \"falsch\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Ist entweder wahr (true) oder falsch (false)\",\n    \"LOGIC_NULL_HELPURL\": \"https://de.wikipedia.org/wiki/Nullwert\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"Ist NULL.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://de.wikipedia.org/wiki/%3F:#Auswahloperator\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"wenn wahr\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"wenn falsch\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Überprüft eine Bedingung \\\"test\\\". Wenn die Bedingung wahr ist wird der \\\"wenn wahr\\\" Wert zurückgegeben, andernfalls der \\\"wenn falsch\\\" Wert\",\n    \"MATH_NUMBER_HELPURL\": \"https://de.wikipedia.org/wiki/Zahl\",\n    \"MATH_NUMBER_TOOLTIP\": \"Eine Zahl.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://de.wikipedia.org/wiki/Grundrechenart\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Ist die Summe zweier Werte.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Ist die Differenz zweier Werte.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Ist das Produkt zweier Werte.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Ist der Quotient zweier Werte.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Ist der erste Wert potenziert mit dem zweiten Wert.\",\n    \"MATH_SINGLE_HELPURL\": \"https://de.wikipedia.org/wiki/Quadratwurzel\",\n    \"MATH_SINGLE_OP_ROOT\": \"Quadratwurzel\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Ist die Qudratwurzel eines Wertes.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"Absolutwert\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Ist der Absolutwert eines Wertes.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Negiert einen Wert.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Ist der natürliche Logarithmus eines Wertes.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Ist der dekadische Logarithmus eines Wertes.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Ist Wert der Exponentialfunktion eines Wertes.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Rechnet 10 hoch Eingabewert.\",\n    \"MATH_TRIG_HELPURL\": \"https://de.wikipedia.org/wiki/Trigonometrie\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Ist der Sinus eins Winkels.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Ist der Cosinus eins Winkels.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Ist der Tangens eins Winkels.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Ist der Arcussinus des Eingabewertes.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Ist der Arcuscosinus des Eingabewertes.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Ist der Arcustangens des Eingabewertes.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://de.wikipedia.org/wiki/Mathematische_Konstante\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Mathematische Konstanten wie: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) oder ∞ (unendlich).\",\n    \"MATH_IS_EVEN\": \"ist gerade\",\n    \"MATH_IS_ODD\": \"ist ungerade\",\n    \"MATH_IS_PRIME\": \"ist eine Primenzahl\",\n    \"MATH_IS_WHOLE\": \"ganze Zahl\",\n    \"MATH_IS_POSITIVE\": \"ist positiv\",\n    \"MATH_IS_NEGATIVE\": \"ist negativ\",\n    \"MATH_IS_DIVISIBLE_BY\": \"ist teilbar durch\",\n    \"MATH_IS_TOOLTIP\": \"Überprüft ob eine Zahl gerade, ungerade, eine Primenzahl, ganzzahlig, positiv, negativ oder durch eine zweite Zahl teilbar ist.  Gibt wahr (true) oder falsch (false) zurück.\",\n    \"MATH_CHANGE_HELPURL\": \"https://de.wikipedia.org/wiki/Inkrement_und_Dekrement\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"erhöhe\",\n    \"MATH_CHANGE_INPUT_BY\": \"um\",\n    \"MATH_CHANGE_TOOLTIP\": \"Addiert einen Wert zur Variable \\\"%1\\\" hinzu.\",\n    \"MATH_ROUND_HELPURL\": \"https://de.wikipedia.org/wiki/Runden\",\n    \"MATH_ROUND_TOOLTIP\": \"Eine Zahl auf oder ab runden.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"runden\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"auf runden\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"ab runden\",\n    \"MATH_ONLIST_HELPURL\": \"http://www.sysplus.ch/einstieg.php?links=menu\\u0026seite=4125\\u0026grad=Crash\\u0026prog=Excel\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"Summme einer Liste\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Ist die Summe aller Werte in einer Liste.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"Minimalwert einer Liste\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Ist der kleinste Wert in einer Liste.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"Maximalwert einer Liste\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Ist der grösste Wert in einer Liste.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"Mittelwert einer Liste\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Ist der Durchschnittswert aller Werte in einer Liste.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"Median einer Liste\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Ist der Zentralwert aller Werte in einer Liste.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"Modulo / Restwert einer Liste\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Findet den am häufigsten vorkommenden Wert in einer Liste.  Falls kein Wert öfter vorkomme als alle anderen, wird die originale Liste zurückgegen\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"Standart Abweichung einer Liste\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Ist die standartiesierte Standartabweichung aller Werte in der Liste\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"Zufallswert einer Liste\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Gebe einen Zufallswert aus der Liste zurück.\",\n    \"MATH_MODULO_HELPURL\": \"https://de.wikipedia.org/wiki/Modulo\",\n    \"MATH_MODULO_TITLE\": \"Rest von %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Der Rest nach einer Division.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"begrenzen %1 von %2 bis %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Begrenzt den Wertebereich mittels von / bis Werte. (inklusiv)\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://de.wikipedia.org/wiki/Zufallszahlen\",\n    \"MATH_RANDOM_INT_TITLE\": \"ganzahliger Zufallswerte zwischen %1 bis %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Erzeuge eine ganzahligen Zufallswert zwischen zwei Werten (inklusiv).\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://de.wikipedia.org/wiki/Zufallszahlen\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"Zufallszahl (0.0 -1.0)\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Erzeuge eine Zufallszahl zwischen 0.0 (inklusiv) und 1.0 (exklusiv).\",\n    \"TEXT_TEXT_HELPURL\": \"https://de.wikipedia.org/wiki/Zeichenkette\",\n    \"TEXT_TEXT_TOOLTIP\": \"Ein Buchstabe, Text oder Satz.\",\n    \"TEXT_JOIN_HELPURL\": \"\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"Erstelle Text aus\",\n    \"TEXT_JOIN_TOOLTIP\": \"Erstellt einen Text durch das verbinden von mehreren Textelementen.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"verbinden\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Hinzufügen, entfernen und sortieren von Elementen.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Ein Element zum Text hinzufügen.\",\n    \"TEXT_APPEND_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_APPEND_TO\": \"An\",\n    \"TEXT_APPEND_APPENDTEXT\": \"Text anhängen\",\n    \"TEXT_APPEND_TOOLTIP\": \"Text an die Variable \\\"%1\\\" anhängen.\",\n    \"TEXT_LENGTH_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_LENGTH_TITLE\": \"länge %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Die Anzahl von Zeichen in einem Textes. (inkl. Leerzeichen)\",\n    \"TEXT_ISEMPTY_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 ist leer?\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Ist wahr (true), wenn der Text leer ist.\",\n    \"TEXT_INDEXOF_HELPURL\": \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Findest das erste / letzte Vorkommniss eines cuchbegriffes in einem Text.  Gibt die Position des Begriffes oder 0 zurück.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"im Text\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"Suche erstes Vorkommniss des Begriff\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"Suche letztes Vorkommniss des Begriff\",\n    \"TEXT_INDEXOF_TAIL\": \"\",\n    \"TEXT_CHARAT_HELPURL\": \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"vom Text\",\n    \"TEXT_CHARAT_FROM_START\": \"Nehme Buchstabe #ten\",\n    \"TEXT_CHARAT_FROM_END\": \"Nehme #te Buchstabe von hinten\",\n    \"TEXT_CHARAT_FIRST\": \"Nehme ersten Buchstabe\",\n    \"TEXT_CHARAT_LAST\": \"Nehme letzten Buchstabe\",\n    \"TEXT_CHARAT_RANDOM\": \"Nehme zufälligen Buchstabe\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Extrahiere einen Buchstaben von einer spezifizierten Position.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Returns a specified portion of the text.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"in Text\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"Buchstabe #ten\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"#te Buchstabe von hinten\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"ersten Buchstabe\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"bis Buchstabe #ten\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"bis #te Buchstabe von hinten\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"bis letzten Buchstabe\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Wandelt Schreibweise von Texten um, in Grossbuchstaben, Kleinbuchstaben oder den ersten Buchstaben jedes Wortes gross und die anderen klein.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"umwandeln in GROSSBUCHSTABEN\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"umwandeln in kleinbuchstaben\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"umwandeln in Wörter\",\n    \"TEXT_TRIM_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_TRIM_TOOLTIP\": \"Entfernt Leerzeichen vom Anfang und / oder Ende eines Textes.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"entferne Leerzeichen von Anfang und Ende Seiten\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"entferne Leerzeichen von Anfang Seite\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"entferne Leerzeichen von Ende Seite von\",\n    \"TEXT_PRINT_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_PRINT_TITLE\": \"Ausgabe %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Gib den Inhalt einer Variable aus.\",\n    \"TEXT_PROMPT_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"Fragt nach Text mit Hinweis\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"Fragt nach Zahl mit Hinweis\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Fragt den Benutzer nach ein Zahl.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Fragt den Benutzer nach einem Text.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"Erzeuge eine leere Liste\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Erzeugt eine leere Liste ohne Inhalt.\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Erzeugt eine List mit konfigurierten Elementen.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"Erzeuge Liste mit\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"Liste\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Hinzufügen, entfernen und sortieren von Elementen.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Ein Element zur Liste hinzufügen.\",\n    \"LISTS_REPEAT_HELPURL\": \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Erzeugt eine Liste mit einer variablen Anzahl von Elementen\",\n    \"LISTS_REPEAT_TITLE\": \"Erzeuge Liste mit Element %1 wiederhole es %2 mal\",\n    \"LISTS_LENGTH_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"LISTS_LENGTH_TITLE\": \"länge %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Die Anzahl von Elementen in der Liste.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 ist leer?\",\n    \"LISTS_TOOLTIP\": \"Ist wahr (true), wenn die Liste leer ist.\",\n    \"LISTS_INLIST\": \"in der Liste\",\n    \"LISTS_INDEX_OF_HELPURL\": \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\",\n    \"LISTS_INDEX_OF_FIRST\": \"Suche erstes Vorkommniss\",\n    \"LISTS_INDEX_OF_LAST\": \"Suche letztes Vorkommniss\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Sucht die Position (index) eines Elementes in der Liste Gibt 0 zurück wenn nichts gefunden wurde.\",\n    \"LISTS_GET_INDEX_GET\": \"Nehme\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"Nehme und entferne\",\n    \"LISTS_GET_INDEX_REMOVE\": \"Entferne\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#te\",\n    \"LISTS_GET_INDEX_FROM_END\": \"#te von hinten\",\n    \"LISTS_GET_INDEX_FIRST\": \"erste\",\n    \"LISTS_GET_INDEX_LAST\": \"letzte\",\n    \"LISTS_GET_INDEX_RANDOM\": \"zufälliges\",\n    \"LISTS_GET_INDEX_TAIL\": \"\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Extrahiere das #1te Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Extrahiere das #1te Element vom Ende der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Extrahiere das erste Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Extrahiere das letzte Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Extrahiere ein zufälliges Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Extrahiere und entfernt das #1te Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Extrahiere und entfernt das #1te Element vom Ende der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Extrahiere und entfernt das erste Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Extrahiere und entfernt das letzte Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Extrahiere und entfernt ein zufälliges Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Entfernt das #1te Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Entfernt das #1te Element vom Ende der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Entfernt das erste Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Entfernt das letzte Element von der Liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Entfernt ein zufälliges Element von der Liste.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\",\n    \"LISTS_SET_INDEX_SET\": \"set\",\n    \"LISTS_SET_INDEX_INSERT\": \"insert\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"auf\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Sets the item at the specified position in a list.  #1 is the first item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Sets the item at the specified position in a list.  #1 is the last item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Sets the first item in a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Sets the last item in a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Sets a random item in a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Inserts the item at the specified position in a list.  #1 is the first item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Inserts the item at the specified position in a list.  #1 is the last item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Inserts the item at the start of a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Append the item to the end of a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Inserts the item randomly in a list.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"erhalte Unterliste von #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"erhalte Unterliste von # vom Ende\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"erhalte Unterliste vom Ersten\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"zu #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"zu # vom Ende\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"zum Letzten\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Creates a copy of the specified portion of a list.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"\",\n    \"VARIABLES_GET_HELPURL\": \"https://de.wikipedia.org/wiki/Variable_%28Programmierung%29\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"Gibt den Wert der Variable zurück.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Erzeuge \\\"Schreibe %1\\\"\",\n    \"VARIABLES_SET_HELPURL\": \"https://de.wikipedia.org/wiki/Variable_%28Programmierung%29\",\n    \"VARIABLES_SET_TITLE\": \"Schreibe\",\n    \"VARIABLES_SET_TAIL\": \"\",\n    \"VARIABLES_SET_TOOLTIP\": \"Setzt den Wert einer Variable.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Erzeuge \\\"Lese %1\\\"\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"to\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"Funktionsblock\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"mit:\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Ein Funktionsblock ohne Rückgabewert.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"gebe zurück\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Ein Funktionsblock mit Rückgabewert.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Warnung: dieser Funktionsblock hat doppelte Parameter.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Rufe einen Funktionsblock ohne Rückgabewert auf.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Rufe einen Funktionsblock mit Rückgabewert auf.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"Parameter\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"Variable:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Markiere Funktionsblock\",\n    \"PROCEDURES_CREATE_DO\": \"Erzeuge \\\"Aufruf %1\\\"\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Wenn der erste Wert wahr (true) ist, Gebe den zweiten Wert zurück.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Warnung: Dieser Block darf nur innerhalb eines Funktionsblock genutzt werden.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/el.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Azountas\",\n            \"Espertus\",\n            \"Evropi\",\n            \"Namatreasure\",\n            \"Sfyrakis\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"αντικείμενο\",\n    \"DUPLICATE_BLOCK\": \"Αντίγραφο\",\n    \"ADD_COMMENT\": \"Πρόσθεσε Σχόλιο\",\n    \"REMOVE_COMMENT\": \"Αφαίρεσε Το Σχόλιο\",\n    \"EXTERNAL_INPUTS\": \"Εξωτερικές Είσοδοι\",\n    \"INLINE_INPUTS\": \"Εσωτερικές Είσοδοι\",\n    \"DELETE_BLOCK\": \"Διέγραψε Το Μπλοκ\",\n    \"DELETE_X_BLOCKS\": \"Διέγραψε %1 Μπλοκ\",\n    \"COLLAPSE_BLOCK\": \"Σύμπτυξε Το Μπλοκ\",\n    \"COLLAPSE_ALL\": \"Σύμπτυξτε Όλα Τα Μπλοκ\",\n    \"EXPAND_BLOCK\": \"Επέκτεινε Το Μπλοκ\",\n    \"EXPAND_ALL\": \"Επέκτεινε Όλα Τα Μπλοκ\",\n    \"DISABLE_BLOCK\": \"Απενεργοποίησε Το Μπλοκ\",\n    \"ENABLE_BLOCK\": \"Ενεργοποίησε Το Μπλοκ\",\n    \"HELP\": \"Βοήθεια\",\n    \"CHANGE_VALUE_TITLE\": \"Άλλαξε την τιμή:\",\n    \"NEW_VARIABLE\": \"Νέα μεταβλητή...\",\n    \"NEW_VARIABLE_TITLE\": \"Νέο όνομα μεταβλητής:\",\n    \"RENAME_VARIABLE\": \"Μετονόμασε τη μεταβλητή...\",\n    \"RENAME_VARIABLE_TITLE\": \"Μετονόμασε όλες τις μεταβλητές «%1» σε:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://el.wikipedia.org/wiki/Χρώμα\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Επιτρέπει επιλογή χρώματος από την παλέτα.\",\n    \"COLOUR_RANDOM_TITLE\": \"τυχαίο χρώμα\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Επιλέγει χρώμα τυχαία.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"χρώμα με\",\n    \"COLOUR_RGB_RED\": \"κόκκινο\",\n    \"COLOUR_RGB_GREEN\": \"πράσινο\",\n    \"COLOUR_RGB_BLUE\": \"μπλε\",\n    \"COLOUR_RGB_TOOLTIP\": \"Δημιουργεί χρώμα με το συγκεκριμένο ποσό του κόκκινου, πράσινου και μπλε που ορίζεις. Όλες οι τιμές πρέπει να είναι μεταξύ 0 και 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"μείγμα\",\n    \"COLOUR_BLEND_COLOUR1\": \"χρώμα 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"χρώμα 2\",\n    \"COLOUR_BLEND_RATIO\": \"αναλογία\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Συνδυάζει δύο χρώματα μαζί με μια δεδομένη αναλογία (0.0 - 1,0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"επανάλαβε %1 φορές\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"επανάλαβε\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"φορές\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"κάνε\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Εκτελεί κάποιες εντολές αρκετές φορές.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat ΕΠΑΝΑΛΑΒΕ\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"επανάλαβε ενώ\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"επανάλαβε μέχρι\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Ενόσω μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Ενόσω μια τιμή είναι ψευδής, τότε εκτελεί κάποιες εντολές.\",\n    \"CONTROLS_FOR_HELPURL\": \"Blockly\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Η μεταβλητή %1 παίρνει τιμές ξεκινώντας από τον αριθμό έναρξης μέχρι τον αριθμό τέλους αυξάνοντας κάθε φορά με το καθορισμένο βήμα και εκτελώντας το καθορισμένο μπλοκ.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"μέτρησε με\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"από το %1 έως το %2 ανά %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.Google.com/p/blockly/wiki/loops#for _each ΓΙΑ ΚΑΘΕ μπλοκ\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"για κάθε στοιχείο\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"στη λίστα\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Για κάθε στοιχείο σε μια λίστα, ορίζει τη μεταβλητή «%1» στο στοιχείο και, στη συνέχεια, εκτελεί κάποιες εντολές.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"φεύγει από το μπλοκ επαναλήψεως\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"συνέχισε με την επόμενη επανάληψη του μπλοκ επαναλήψεως\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Ξεφεύγει (βγαίνει έξω) από την επανάληψη.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Παραλείπει το υπόλοιπο τμήμα αυτού του μπλοκ επαναλήψεως, και συνεχίζει με την επόμενη επανάληψη.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Προειδοποίηση: Αυτό το μπλοκ μπορεί να χρησιμοποιηθεί μόνο μέσα σε μια επανάληψη.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then ΑΝ_ΤΟΤΕ\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Αν μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Αν μια τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, εκτελεί το δεύτερο τμήμα εντολών.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Αν η πρώτη τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, αν η δεύτερη τιμή είναι αληθής, εκτελεί το δεύτερο μπλοκ εντολών.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Αν η πρώτη τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών.  Διαφορετικά, αν η δεύτερη τιμή είναι αληθής, εκτελεί το δεύτερο τμήμα εντολών. Αν καμία από τις τιμές δεν είναι αληθής, εκτελεί το τελευταίο τμήμα εντολών.\",\n    \"CONTROLS_IF_MSG_IF\": \"αν\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"εναλλακτικά αν\",\n    \"CONTROLS_IF_MSG_ELSE\": \"αλλιώς\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Προσθέτει, αφαιρεί ή αναδιατάσσει τα τμήματα για να αναδιαμορφώσει αυτό το μπλοκ «εάν».\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Πρόσθετει μια κατάσταση/συνθήκη στο μπλοκ «εάν».\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Προσθέτει μια τελική κατάσταση/συνθήκη, που πιάνει όλες τις άλλες περιπτώσεις, στο μπλοκ «εάν».\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Επιστρέφει αληθής αν και οι δύο είσοδοι είναι ίσες μεταξύ τους.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Επιστρέφει αληθής αν και οι δύο είσοδοι δεν είναι ίσες μεταξύ τους.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη από τη δεύτερη είσοδο.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη από ή ίση με τη δεύτερη είσοδο.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Επιστρέφει αληθής αν η πρώτη είσοδος είναι μεγαλύτερη από τη δεύτερη είσοδο.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη ή ίση με τη δεύτερη είσοδο.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or ΚΑΙ_Ή\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Επιστρέφει αληθής αν και οι δύο είσοδοι είναι αληθής.\",\n    \"LOGIC_OPERATION_AND\": \"και\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Επιστρέφει αληθής αν τουλάχιστον μια από τις εισόδους είναι αληθής.\",\n    \"LOGIC_OPERATION_OR\": \"ή\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"όχι %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Επιστρέφει αληθής αν η είσοδος είναι ψευδής. Επιστρέφει ψευδής αν η είσοδος είναι αληθής.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"αληθής\",\n    \"LOGIC_BOOLEAN_FALSE\": \"ψευδής\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Επιστρέφει είτε αληθής είτε ψευδής.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"κενό\",\n    \"LOGIC_NULL_TOOLTIP\": \"Επιστρέφει κενό.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"έλεγχος\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"αν είναι αληθής\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"αν είναι ψευδής\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Ελέγχει την κατάσταση/συνθήκη στον «έλεγχο». Αν η κατάσταση/συνθήκη είναι αληθής, επιστρέφει την τιμή «αν αληθής», διαφορετικά επιστρέφει την τιμή «αν ψευδής».\",\n    \"MATH_NUMBER_HELPURL\": \"https://el.wikipedia.org/wiki/Αριθμός\",\n    \"MATH_NUMBER_TOOLTIP\": \"Ένας αριθμός.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^ ύψωση σε δύναμη\",\n    \"MATH_TRIG_SIN\": \"ημ\",\n    \"MATH_TRIG_COS\": \"συν\",\n    \"MATH_TRIG_TAN\": \"εφ\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://el.wikipedia.org/wiki/Αριθμητική\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Επιστρέφει το άθροισμα των δύο αριθμών.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Επιστρέφει τη διαφορά των δύο αριθμών.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Επιστρέφει το προϊόν των δύο αριθμών.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Επιστρέφει το πηλίκο των δύο αριθμών.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Επιστρέφει τον πρώτο αριθμό υψωμένο στη δύναμη του δεύτερου αριθμού.\",\n    \"MATH_SINGLE_HELPURL\": \"https://el.wikipedia.org/wiki/Τετραγωνική_ρίζα\",\n    \"MATH_SINGLE_OP_ROOT\": \"τετραγωνική ρίζα\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Επιστρέφει την τετραγωνική ρίζα ενός αριθμού.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"απόλυτη\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Επιστρέφει την απόλυτη τιμή ενός αριθμού.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Επιστρέφει την άρνηση ενός αριθμού.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Επιστρέφει τον νεπέρειο λογάριθμο ενός αριθμού.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Επιστρέφει τον λογάριθμο με βάση το 10 ενός αριθμού.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Επιστρέφει το e υψωμένο στη δύναμη ενός αριθμού.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Επιστρέφει το 10 υψωμένο στη δύναμη ενός αριθμού.\",\n    \"MATH_TRIG_HELPURL\": \"https://el.wikipedia.org/wiki/Τριγωνομετρική_συνάρτηση\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Επιστρέφει το ημίτονο ενός βαθμού (όχι ακτινίου).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Επιστρέφει το συνημίτονο ενός βαθμού (όχι ακτινίου).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Επιστρέφει την εφαπτομένη ενός βαθμού (όχι ακτινίου).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Επιστρέφει το τόξο ημίτονου ενός αριθμού.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Επιστρέφει το τόξο συνημίτονου ενός αριθμού.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Επιστρέφει το τόξο εφαπτομένης ενός αριθμού.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Επιστρέφει μία από τις κοινές σταθερές: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...), ή ∞ (άπειρο).\",\n    \"MATH_IS_EVEN\": \"είναι άρτιος\",\n    \"MATH_IS_ODD\": \"είναι περιττός\",\n    \"MATH_IS_PRIME\": \"είναι πρώτος\",\n    \"MATH_IS_WHOLE\": \"είναι ακέραιος\",\n    \"MATH_IS_POSITIVE\": \"είναι θετικός\",\n    \"MATH_IS_NEGATIVE\": \"είναι αρνητικός\",\n    \"MATH_IS_DIVISIBLE_BY\": \"είναι διαιρετός από το\",\n    \"MATH_IS_TOOLTIP\": \"Ελέγχει αν ένας αριθμός είναι άρτιος, περιττός, πρώτος, ακέραιος, θετικός, αρνητικός, ή αν είναι διαιρετός από έναν ορισμένο αριθμό. Επιστρέφει αληθής ή ψευδής.\",\n    \"MATH_CHANGE_HELPURL\": \"https://el.wikipedia.org/wiki/%CE%A0%CF%81%CF%8C%CF%83%CE%B8%CE%B5%CF%83%CE%B7\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"άλλαξε\",\n    \"MATH_CHANGE_INPUT_BY\": \"από\",\n    \"MATH_CHANGE_TOOLTIP\": \"Προσθέτει έναν αριθμό στη μεταβλητή «%1».\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Στρογγυλοποιεί έναν αριθμό προς τα πάνω ή προς τα κάτω.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"στρογγυλοποίησε\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"στρογγυλοποίησε προς τα πάνω\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"στρογγυλοποίησε προς τα κάτω\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"άθροισμα λίστας\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Επιστρέφει το άθροισμα όλων των αριθμών στη λίστα.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"μικρότερος λίστας\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Επιστρέφει τον μικρότερο αριθμό στη λίστα.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"μεγαλύτερος λίστας\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Επιστρέφει τον μεγαλύτερο αριθμό στη λίστα.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"μέσος όρος λίστας\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Επιστρέφει τον αριθμητικό μέσο όρο από τις αριθμητικές τιμές στη λίστα.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"διάμεσος λίστας\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Επιστρέφει τον διάμεσο της λίστας.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"μορφές λίστας\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Επιστρέφει μια λίστα με τα πιο κοινά στοιχεία στη λίστα.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"τυπική απόκλιση λίστας\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Επιστρέφει την τυπική απόκλιση της λίστας.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"τυχαίο στοιχείο λίστας\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Επιστρέφει ένα τυχαίο στοιχείο από τη λίστα.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"υπόλοιπο της %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Επιστρέφει το υπόλοιπο της διαίρεσης των δύο αριθμών.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29 ΓΡΑΦΙΚΑ\",\n    \"MATH_CONSTRAIN_TITLE\": \"περιόρισε %1 χαμηλή %2 υψηλή %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Περιορίζει έναν αριθμό μεταξύ των προβλεπόμενων ορίων (χωρίς αποκλεισμούς).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"τυχαίος ακέραιος από το %1 έως το %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Επιστρέφει έναν τυχαίο ακέραιο αριθμό μεταξύ δύο συγκεκριμένων ορίων (εντός - συμπεριλαμβανομένων και των ακραίων τιμών).\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"τυχαίο κλάσμα\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Επιστρέψει ένα τυχαία κλάσμα μεταξύ 0,0 (κλειστό) και 1,0 (ανοικτό).\",\n    \"TEXT_TEXT_HELPURL\": \"https://el.wikipedia.org/wiki/Συμβολοσειρά\",\n    \"TEXT_TEXT_TOOLTIP\": \"Ένα γράμμα, μια λέξη ή μια γραμμή κειμένου.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"δημιούργησε κείμενο με\",\n    \"TEXT_JOIN_TOOLTIP\": \"Δημιουργεί ένα κομμάτι κειμένου ενώνοντας έναν  απεριόριστο αριθμό αντικειμένων.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"ένωσε\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Προσθέτει, αφαιρεί ή αναδιατάσσει τους τομείς για να αναδιαμορφώσει αυτό το μπλοκ κειμένου.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Προσθέτει ένα στοιχείο στο κείμενο.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification ΑΛΛΑΓΗ_ΚΕΙΜΕΝΟΥ\",\n    \"TEXT_APPEND_TO\": \"έως\",\n    \"TEXT_APPEND_APPENDTEXT\": \"ανάθεσε κείμενο\",\n    \"TEXT_APPEND_TOOLTIP\": \"Αναθέτει κείμενο στη μεταβλητή «%1».\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification ΑΛΛΑΓΗ_ΚΕΙΜΕΝΟΥ\",\n    \"TEXT_LENGTH_TITLE\": \"το μήκος του %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Επιστρέφει το πλήθος των γραμμάτων (συμπεριλαμβανομένων και των κενών διαστημάτων) στο παρεχόμενο κείμενο.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"το %1 είναι κενό\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Επιστρέφει αληθής αν το παρεχόμενο κείμενο είναι κενό.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text ΕΥΡΕΣΗ ΚΕΙΜΕΝΟΥ\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Επιστρέφει τον δείκτη της πρώτης/τελευταίας εμφάνισης του πρώτου κειμένου στο δεύτερο κείμενο.  Επιστρέφει τιμή 0, αν δε βρει το κείμενο.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"στο κείμενο\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"βρες την πρώτη εμφάνιση του κειμένου\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"βρες την τελευταία εμφάνιση του κειμένου\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"στο κείμενο\",\n    \"TEXT_CHARAT_FROM_START\": \"πάρε το γράμμα #\",\n    \"TEXT_CHARAT_FROM_END\": \"πάρε το γράμμα # από το τέλος\",\n    \"TEXT_CHARAT_FIRST\": \"πάρε το πρώτο γράμμα\",\n    \"TEXT_CHARAT_LAST\": \"πάρε το τελευταίο γράμμα\",\n    \"TEXT_CHARAT_RANDOM\": \"πάρε τυχαίο γράμμα\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Επιστρέφει το γράμμα στην καθορισμένη θέση.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Επιστρέφει ένα συγκεκριμένο τμήμα του κειμένου.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"στο κείμενο\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"πάρε τη δευτερεύουσα συμβολοσειρά από το # γράμμα\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"πάρε τη δευτερεύουσα συμβολοσειρά από το # γράμμα από το τέλος\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"πάρε τη δευτερεύουσα συμβολοσειρά από το πρώτο γράμμα\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"μέχρι το # γράμμα\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"μέχρι το # γράμμα από το τέλος\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"μέχρι το τελευταίο γράμμα\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Επιστρέφει ένα αντίγραφο του κειμένου σε διαφορετική μορφή γραμμάτων.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"σε ΚΕΦΑΛΑΙΑ\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"σε πεζά\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"σε Λέξεις Με Πρώτα Κεφαλαία\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Επιστρέφει ένα αντίγραφο του κειμένου με αφαιρεμένα τα κενά από το ένα ή και τα δύο άκρα.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"περίκοψε τα κενά και από τις δυο πλευρές του\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"περίκοψε τα κενά από την αριστερή πλευρά του\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"περίκοψε τα κενά από την δεξιά πλευρά του\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text ΕΜΦΑΝΙΣΗ_ΚΕΙΜΕΝΟΥ\",\n    \"TEXT_PRINT_TITLE\": \"εκτύπωσε %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Εκτυπώνει το καθορισμένο κείμενο, αριθμό ή άλλη τιμή.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user ΕΙΣΑΓΩΓΗ_ΔΕΔΟΜΕΝΩΝ_ΑΠΟ_ΤΟΝ_ΧΡΗΣΤΗ\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"πρότρεψε με μήνυμα για να δοθεί κείμενο\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"πρότρεψε με μήνυμα για να δοθεί αριθμός\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Δημιουργεί προτροπή για τον χρήστη για να δώσει ένα αριθμό.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Δημιουργεί προτροπή για το χρήστη για να δώσει κάποιο κείμενο.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"λίστα\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"δημιούργησε κενή λίστα\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Επιστρέφει μια λίστα, με μήκος 0, η οποία δεν περιέχει εγγραφές δεδομένων\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Δημιουργεί λίστα με οποιονδήποτε αριθμό αντικειμένων.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"δημιούργησε λίστα με\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"λίστα\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Προσθέτει, αφαιρεί ή αναδιατάσσει τα τμήματα για να αναδιαμορφώσει αυτό το μπλοκ λίστας.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Προσθέτει αντικείμενο στη λίστα.\",\n    \"LISTS_REPEAT_HELPURL\": \"Blockly\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Δημιουργεί μια λίστα που αποτελείται από την δεδομένη τιμή που επαναλαμβάνεται για συγκεκριμένο αριθμό επαναλήψεων.\",\n    \"LISTS_REPEAT_TITLE\": \"δημιούργησε λίστα με το στοιχείο %1 να επαναλαμβάνεται %2 φορές\",\n    \"LISTS_LENGTH_HELPURL\": \"Blockly\",\n    \"LISTS_LENGTH_TITLE\": \"το μήκος του %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Επιστρέφει το μήκος μιας λίστας.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty ΕΙΝΑΙ_ΑΔΕΙΑ\",\n    \"LISTS_IS_EMPTY_TITLE\": \"το %1 είναι κενό\",\n    \"LISTS_TOOLTIP\": \"Επιστρέφει αληθής αν η λίστα είναι κενή.\",\n    \"LISTS_INLIST\": \"στη λίστα\",\n    \"LISTS_INDEX_OF_HELPURL\": \"Blockly\",\n    \"LISTS_INDEX_OF_FIRST\": \"βρες την πρώτη εμφάνιση του στοιχείου\",\n    \"LISTS_INDEX_OF_LAST\": \"βρες την τελευταία εμφάνιση του στοιχείου\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Επιστρέφει τον δείκτη της πρώτης/τελευταίας εμφάνισης του στοιχείου στη λίστα.  Επιστρέφει τιμή 0, αν το κείμενο δεν βρεθεί.\",\n    \"LISTS_GET_INDEX_GET\": \"πάρε\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"πάρε και αφαίρεσε\",\n    \"LISTS_GET_INDEX_REMOVE\": \"αφαίρεσε\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# από το τέλος\",\n    \"LISTS_GET_INDEX_FIRST\": \"πρώτο\",\n    \"LISTS_GET_INDEX_LAST\": \"τελευταίο\",\n    \"LISTS_GET_INDEX_RANDOM\": \"τυχαίο\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Επιστρέφει το πρώτο στοιχείο σε μια λίστα.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Επιστρέφει το τελευταίο στοιχείο σε μια λίστα.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Επιστρέφει ένα τυχαίο στοιχείο σε μια λίστα.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Καταργεί και επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Καταργεί και επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Καταργεί και επιστρέφει το πρώτο στοιχείο σε μια λίστα.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Καταργεί και επιστρέφει το τελευταίο στοιχείο σε μια λίστα.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Καταργεί και επιστρέφει ένα τυχαίο στοιχείο σε μια λίστα.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Καταργεί το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Καταργεί το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Καταργεί το πρώτο στοιχείο σε μια λίστα.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Καταργεί το τελευταίο στοιχείο σε μια λίστα.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Καταργεί ένα τυχαίο στοιχείο σε μια λίστα.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"όρισε\",\n    \"LISTS_SET_INDEX_INSERT\": \"είσαγε στο\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"σε\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Ορίζει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Ορίζει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Ορίζει το πρώτο στοιχείο σε μια λίστα.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Ορίζει το τελευταίο στοιχείο σε μια λίστα.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Ορίζει ένα τυχαίο στοιχείο σε μια λίστα.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Εισάγει το στοιχείο στην καθορισμένη θέση σε μια λίστα. Το #1 είναι το πρώτο στοιχείο.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Εισάγει το στοιχείο σε συγκεκριμένη θέση σε μια λίστα. Το #1 είναι το τελευταίο στοιχείο.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Εισάγει το στοιχείο στην αρχή μιας λίστας.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Αναθέτει το στοιχείο στο τέλος μιας λίστας.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Εισάγει το στοιχείο τυχαία σε μια λίστα.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"Blockly\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"πάρε υπολίστα από #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"πάρε υπολίστα από # από το τέλος\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"πάρε υπολίστα από την αρχή\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"έως #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"έως # από το τέλος\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"έως το τελευταίο\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Δημιουργεί ένα αντίγραφο του καθορισμένου τμήματος μιας λίστας.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Επιστρέφει την τιμή αυτής της μεταβλητής.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Δημιούργησε «όρισε %1»\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set ΟΡΙΣΜΟΣ ΜΕΤΑΒΛΗΤΩΝ\",\n    \"VARIABLES_SET_TITLE\": \"όρισε\",\n    \"VARIABLES_SET_TAIL\": \"μέχρι το\",\n    \"VARIABLES_SET_TOOLTIP\": \"Ορίζει αυτή τη μεταβλητή να είναι ίση με την είσοδο.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Δημιούργησε «πάρε %1»\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"στο\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"κάνε κάτι\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"με:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Δημιουργεί μια συνάρτηση χωρίς έξοδο.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"επιστροφή\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Δημιουργεί μια συνάρτηση με μια έξοδο.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Προειδοποίηση: Αυτή η συνάρτηση έχει διπλότυπες παραμέτρους.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://el.wikipedia.org/wiki/Διαδικασία_(υπολογιστές)\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Εκτελεί την ορισμένη από τον χρήστη συνάρτηση «%1».\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://el.wikipedia.org/wiki/Διαδικασία_(υπολογιστές)\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Εκτελεί την ορισμένη από τον χρήστη συνάρτηση «%1» και χρησιμοποίησε την έξοδό της.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"είσοδοι\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"όνομα εισόδου:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Επισημάνετε τον ορισμό συνάρτησης\",\n    \"PROCEDURES_CREATE_DO\": \"Δημιούργησε «%1»\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Αν μια τιμή είναι αληθής, τότε επιστρέφει τη δεύτερη τιμή.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Προειδοποίηση: Αυτό το μπλοκ μπορεί να χρησιμοποιηθεί μόνο στον ορισμό μιας συνάρτησης.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/en.json",
    "content": "{\n    \"@metadata\": {\n        \"author\": \"Ellen Spertus <ellen.spertus@gmail.com>\",\n        \"lastupdated\": \"2014-09-01 18:13:57.039117\",\n        \"locale\": \"en\",\n        \"messagedocumentation\" : \"qqq\"\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"item\",\n    \"DUPLICATE_BLOCK\": \"Duplicate\",\n    \"ADD_COMMENT\": \"Add Comment\",\n    \"REMOVE_COMMENT\": \"Remove Comment\",\n    \"EXTERNAL_INPUTS\": \"External Inputs\",\n    \"INLINE_INPUTS\": \"Inline Inputs\",\n    \"DELETE_BLOCK\": \"Delete Block\",\n    \"DELETE_X_BLOCKS\": \"Delete %1 Blocks\",\n    \"COLLAPSE_BLOCK\": \"Collapse Block\",\n    \"COLLAPSE_ALL\": \"Collapse Blocks\",\n    \"EXPAND_BLOCK\": \"Expand Block\",\n    \"EXPAND_ALL\": \"Expand Blocks\",\n    \"DISABLE_BLOCK\": \"Disable Block\",\n    \"ENABLE_BLOCK\": \"Enable Block\",\n    \"HELP\": \"Help\",\n    \"CHAT\": \"Chat with your collaborator by typing in this box!\",\n    \"CHANGE_VALUE_TITLE\": \"Change value:\",\n    \"NEW_VARIABLE\": \"New variable...\",\n    \"NEW_VARIABLE_TITLE\": \"New variable name:\",\n    \"RENAME_VARIABLE\": \"Rename variable...\",\n    \"RENAME_VARIABLE_TITLE\": \"Rename all '%1' variables to:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Choose a colour from the palette.\",\n    \"COLOUR_RANDOM_HELPURL\": \"http://randomcolour.com\",\n    \"COLOUR_RANDOM_TITLE\": \"random colour\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Choose a colour at random.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"colour with\",\n    \"COLOUR_RGB_RED\": \"red\",\n    \"COLOUR_RGB_GREEN\": \"green\",\n    \"COLOUR_RGB_BLUE\": \"blue\",\n    \"COLOUR_RGB_TOOLTIP\": \"Create a colour with the specified amount of red, green, and blue.  All values must be between 0 and 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"blend\",\n    \"COLOUR_BLEND_COLOUR1\": \"colour 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"colour 2\",\n    \"COLOUR_BLEND_RATIO\": \"ratio\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Blends two colours together with a given ratio (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"repeat %1 times\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"repeat\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"times\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"do\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Do some statements several times.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"https://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"repeat while\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"repeat until\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"While a value is true, then do some statements.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"While a value is false, then do some statements.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"count with\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"from %1 to %2 by %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"for each item\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"in list\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"For each item in a list, set the variable '%1' to the item, and then do some statements.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"break out of loop\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continue with next iteration of loop\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Break out of the containing loop.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Skip the rest of this loop, and continue with the next iteration.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Warning: This block may only be used within a loop.\",\n    \"CONTROLS_IF_HELPURL\": \"https://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"If a value is true, then do some statements.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"If a value is true, then do the first block of statements.  Otherwise, do the second block of statements.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.  If none of the values are true, do the last block of statements.\",\n    \"CONTROLS_IF_MSG_IF\": \"if\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"else if\",\n    \"CONTROLS_IF_MSG_ELSE\": \"else\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Add, remove, or reorder sections to reconfigure this if block.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Add a condition to the if block.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Add a final, catch-all condition to the if block.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Return true if both inputs equal each other.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Return true if both inputs are not equal to each other.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Return true if the first input is smaller than the second input.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Return true if the first input is smaller than or equal to the second input.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Return true if the first input is greater than the second input.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Return true if the first input is greater than or equal to the second input.\",\n    \"LOGIC_OPERATION_HELPURL\": \"https://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Return true if both inputs are true.\",\n    \"LOGIC_OPERATION_AND\": \"and\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Return true if at least one of the inputs is true.\",\n    \"LOGIC_OPERATION_OR\": \"or\",\n    \"LOGIC_NEGATE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"not %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Returns true if the input is false.  Returns false if the input is true.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"https://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"true\",\n    \"LOGIC_BOOLEAN_FALSE\": \"false\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Returns either true or false.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"Returns null.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"if true\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"if false\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"A number.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Return the sum of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Return the difference of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Return the product of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Return the quotient of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Return the first number raised to the power of the second number.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"square root\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Return the square root of a number.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolute\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Return the absolute value of a number.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Return the negation of a number.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Return the natural logarithm of a number.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Return the base 10 logarithm of a number.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Return e to the power of a number.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Return 10 to the power of a number.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Return the sine of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Return the cosine of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Return the tangent of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Return the arcsine of a number.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Return the arccosine of a number.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Return the arctangent of a number.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"is even\",\n    \"MATH_IS_ODD\": \"is odd\",\n    \"MATH_IS_PRIME\": \"is prime\",\n    \"MATH_IS_WHOLE\": \"is whole\",\n    \"MATH_IS_POSITIVE\": \"is positive\",\n    \"MATH_IS_NEGATIVE\": \"is negative\",\n    \"MATH_IS_DIVISIBLE_BY\": \"is divisible by\",\n    \"MATH_IS_TOOLTIP\": \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"change\",\n    \"MATH_CHANGE_INPUT_BY\": \"by\",\n    \"MATH_CHANGE_TOOLTIP\": \"Add a number to variable '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Round a number up or down.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"round\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"round up\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"round down\",\n    \"MATH_ONLIST_HELPURL\": \"\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"sum of list\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Return the sum of all the numbers in the list.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"min of list\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Return the smallest number in the list.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"max of list\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Return the largest number in the list.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"average of list\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Return the average (arithmetic mean) of the numeric values in the list.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"median of list\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Return the median number in the list.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"modes of list\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Return a list of the most common item(s) in the list.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"standard deviation of list\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Return the standard deviation of the list.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"random item of list\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Return a random element from the list.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"remainder of %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Return the remainder from dividing the two numbers.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"constrain %1 low %2 high %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Constrain a number to be between the specified limits (inclusive).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"random integer from %1 to %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Return a random integer between the two specified limits, inclusive.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"random fraction\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"A letter, word, or line of text.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"create text with\",\n    \"TEXT_JOIN_TOOLTIP\": \"Create a piece of text by joining together any number of items.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"join\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Add, remove, or reorder sections to reconfigure this text block.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Add an item to the text.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"to\",\n    \"TEXT_APPEND_APPENDTEXT\": \"append text\",\n    \"TEXT_APPEND_TOOLTIP\": \"Append some text to variable '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"length of %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Returns the number of letters (including spaces) in the provided text.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 is empty\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Returns true if the provided text is empty.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"in text\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"find first occurrence of text\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"find last occurrence of text\",\n    \"TEXT_INDEXOF_TAIL\": \"\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"in text\",\n    \"TEXT_CHARAT_FROM_START\": \"get letter #\",\n    \"TEXT_CHARAT_FROM_END\": \"get letter # from end\",\n    \"TEXT_CHARAT_FIRST\": \"get first letter\",\n    \"TEXT_CHARAT_LAST\": \"get last letter\",\n    \"TEXT_CHARAT_RANDOM\": \"get random letter\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Returns the letter at the specified position.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Returns a specified portion of the text.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"in text\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"get substring from letter #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"get substring from letter # from end\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"get substring from first letter\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"to letter #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"to letter # from end\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"to last letter\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Return a copy of the text in a different case.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"to UPPER CASE\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"to lower case\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"to Title Case\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Return a copy of the text with spaces removed from one or both ends.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"trim spaces from both sides of\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"trim spaces from left side of\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"trim spaces from right side of\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"print %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Print the specified text, number or other value.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"prompt for text with message\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"prompt for number with message\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Prompt for user for a number.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Prompt for user for some text.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"create empty list\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Returns a list, of length 0, containing no data records\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Create a list with any number of items.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"create list with\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"list\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Add, remove, or reorder sections to reconfigure this list block.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Add an item to the list.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Creates a list consisting of the given value repeated the specified number of times.\",\n    \"LISTS_REPEAT_TITLE\": \"create list with item %1 repeated %2 times\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"length of %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Returns the length of a list.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 is empty\",\n    \"LISTS_TOOLTIP\": \"Returns true if the list is empty.\",\n    \"LISTS_INLIST\": \"in list\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"find first occurrence of item\",\n    \"LISTS_INDEX_OF_LAST\": \"find last occurrence of item\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.\",\n    \"LISTS_GET_INDEX_GET\": \"get\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"get and remove\",\n    \"LISTS_GET_INDEX_REMOVE\": \"remove\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# from end\",\n    \"LISTS_GET_INDEX_FIRST\": \"first\",\n    \"LISTS_GET_INDEX_LAST\": \"last\",\n    \"LISTS_GET_INDEX_RANDOM\": \"random\",\n    \"LISTS_GET_INDEX_TAIL\": \"\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Returns the item at the specified position in a list.  #1 is the first item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Returns the item at the specified position in a list.  #1 is the last item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Returns the first item in a list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Returns the last item in a list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Returns a random item in a list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Removes and returns the item at the specified position in a list.  #1 is the first item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Removes and returns the item at the specified position in a list.  #1 is the last item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Removes and returns the first item in a list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Removes and returns the last item in a list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Removes and returns a random item in a list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Removes the item at the specified position in a list.  #1 is the first item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Removes the item at the specified position in a list.  #1 is the last item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Removes the first item in a list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Removes the last item in a list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Removes a random item in a list.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"set\",\n    \"LISTS_SET_INDEX_INSERT\": \"insert at\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"as\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Sets the item at the specified position in a list.  #1 is the first item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Sets the item at the specified position in a list.  #1 is the last item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Sets the first item in a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Sets the last item in a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Sets a random item in a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Inserts the item at the specified position in a list.  #1 is the first item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Inserts the item at the specified position in a list.  #1 is the last item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Inserts the item at the start of a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Append the item to the end of a list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Inserts the item randomly in a list.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"get sub-list from #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"get sub-list from # from end\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"get sub-list from first\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"to #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"to # from end\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"to last\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Creates a copy of the specified portion of a list.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"\",\n    \"VARIABLES_GET_HELPURL\": \"https://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"Returns the value of this variable.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Create 'set %1'\",\n    \"VARIABLES_SET_HELPURL\": \"https://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"set\",\n    \"VARIABLES_SET_TAIL\": \"to\",\n    \"VARIABLES_SET_TOOLTIP\": \"Sets this variable to be equal to the input.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Create 'get %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"to\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"do something\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"with:\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Creates a function with no output.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"return\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Creates a function with an output.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Warning: This function has duplicate parameters.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Run the user-defined function '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Run the user-defined function '%1' and use its output.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"inputs\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"input name:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Highlight function definition\",\n    \"PROCEDURES_CREATE_DO\": \"Create '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"If a value is true, then return a second value.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Warning: This block may be used only within a function definition.\",\n    \"CONTEXT_BLOCK_COPY\": \"Copy\",\n    \"CONTEXT_BLOCK_PASTE\": \"Paste\"\n}\n"
  },
  {
    "path": "extern/blockly/msg/json/es.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Fitoschido\",\n            \"VegaDark\",\n            \"WeSiToS\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"elemento\",\n    \"DUPLICATE_BLOCK\": \"Duplicar\",\n    \"ADD_COMMENT\": \"Añadir comentario\",\n    \"REMOVE_COMMENT\": \"Eliminar comentario\",\n    \"EXTERNAL_INPUTS\": \"Entradas externas\",\n    \"INLINE_INPUTS\": \"Entradas en línea\",\n    \"DELETE_BLOCK\": \"Eliminar bloque\",\n    \"DELETE_X_BLOCKS\": \"Eliminar %1 bloques\",\n    \"COLLAPSE_BLOCK\": \"Contraer bloque\",\n    \"COLLAPSE_ALL\": \"Contraer bloques\",\n    \"EXPAND_BLOCK\": \"Expandir bloque\",\n    \"EXPAND_ALL\": \"Expandir bloques\",\n    \"DISABLE_BLOCK\": \"Desactivr bloque\",\n    \"ENABLE_BLOCK\": \"Activar bloque\",\n    \"HELP\": \"Ayuda\",\n    \"CHANGE_VALUE_TITLE\": \"Cambiar el valor:\",\n    \"NEW_VARIABLE\": \"Variable nueva…\",\n    \"NEW_VARIABLE_TITLE\": \"Nombre de variable nueva:\",\n    \"RENAME_VARIABLE\": \"Renombrar la variable…\",\n    \"RENAME_VARIABLE_TITLE\": \"Renombrar todas las variables «%1» a:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://es.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Elige un color de la paleta.\",\n    \"COLOUR_RANDOM_TITLE\": \"color aleatorio\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Elige un color al azar.\",\n    \"COLOUR_RGB_TITLE\": \"color con\",\n    \"COLOUR_RGB_RED\": \"rojo\",\n    \"COLOUR_RGB_GREEN\": \"verde\",\n    \"COLOUR_RGB_BLUE\": \"azul\",\n    \"COLOUR_RGB_TOOLTIP\": \"Crea un color con cantidades específicas de rojo, verde y azul. Todos los valores deben encontrarse entre 0 y 100.\",\n    \"COLOUR_BLEND_TITLE\": \"combinar\",\n    \"COLOUR_BLEND_COLOUR1\": \"color 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"color 2\",\n    \"COLOUR_BLEND_RATIO\": \"razón\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Combina dos colores con una proporción determinada (0,0–1,0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://es.wikipedia.org/wiki/Bucle_for\",\n    \"CONTROLS_REPEAT_TITLE\": \"repetir %1 veces\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"repetir\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"veces\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"haz\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Hacer algunas declaraciones varias veces.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"repetir mientras\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"repetir hasta\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Mientras que un valor es verdadero, entonces hacer algunas declaraciones.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Mientras que un valor es falso, entonces hacer algunas declaraciones.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Tiene la variable %1 que toma los valores desde el número de inicio hasta el número final, contando por el intervalo especificado, y hacer los bloques especificados.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"contar con\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"de %1 a %2 por %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"para cada elemento\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"en la lista\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Para cada elemento en una lista, establece la variable '%1' en el elemento y luego hacer algunas declaraciones.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"romper el bucle\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continuar con la siguiente iteración del bucle\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Rompe el que contiene el bucle.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Saltar el resto de este bucle, y continuar con la siguiente iteración.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"ADVERTENCIA: Este bloque puede usarse sólo dentro de un bucle.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Si un valor es verdadero, entonces hacer algunas declaraciones.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Si un valor es verdadero, entonces hacer el primer bloque de declaraciones.  De lo contrario, hacer el segundo bloque de declaraciones.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones. Si ninguno de los valores son verdaderos, hacer el último bloque de declaraciones.\",\n    \"CONTROLS_IF_MSG_IF\": \"si\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"o si\",\n    \"CONTROLS_IF_MSG_ELSE\": \"sino\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Agregar, eliminar o reordenar las secciones para reconfigurar este bloque.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Agregar una condición a este bloque.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Agregar una condición general final a este bloque.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://es.wikipedia.org/wiki/Desigualdad_matemática\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Devolver verdadero si ambas entradas igualan unas a otras.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Devolver verdadero si ambas entradas no son iguales entre sí.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Devolver verdadero si la primera entrada es menor que la segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Devolver verdadero si la primera entrada es menor que o igual a la segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Devolver verdadero si la primera entrada es mayor que la segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Devolver verdadero si la primera entrada es mayor o igual a la segunda entrada.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Devolver verdadero si ambas entradas son verdaderas.\",\n    \"LOGIC_OPERATION_AND\": \"y\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Devolver verdadero si al menos una de las entradas es verdadera.\",\n    \"LOGIC_OPERATION_OR\": \"o\",\n    \"LOGIC_NEGATE_TITLE\": \"no %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Devolver verdadero si la entrada es falsa. Devolver falso si la entrada es verdadera.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"verdadero\",\n    \"LOGIC_BOOLEAN_FALSE\": \"falso\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Devuelve «verdadero» o «falso».\",\n    \"LOGIC_NULL\": \"nulo\",\n    \"LOGIC_NULL_TOOLTIP\": \"Devuelve «nulo».\",\n    \"LOGIC_TERNARY_CONDITION\": \"prueba\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"si es verdadero\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"si es falso\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Comprobar la condición en \\\"probar\\\". Si la condición es verdadera, devolver el valor \\\"si es cierto\\\"; de lo contrario, devolver el valor \\\"si es falso\\\".\",\n    \"MATH_NUMBER_HELPURL\": \"https://es.wikipedia.org/wiki/Número\",\n    \"MATH_NUMBER_TOOLTIP\": \"Un número.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://es.wikipedia.org/wiki/Aritmética\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Devuelve la suma de ambos numeros.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Devuelve la diferencia de ambos números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Devuelve el producto de ambos números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Devuelve el cociente de ambos números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Devuelve el primer número elevado a la potencia del segundo.\",\n    \"MATH_SINGLE_HELPURL\": \"https://es.wikipedia.org/wiki/Ra%C3%ADz_cuadrada\",\n    \"MATH_SINGLE_OP_ROOT\": \"raíz cuadrada\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Devuelve la raíz cuadrada de un número.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absoluto\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Devuelve el valor absoluto de un número.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Devolver la negación de un número.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Devuelve el logaritmo natural de un número.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Devuelve el logaritmo base 10 de un número.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Devuelve e a la potencia de un número.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Devuelve 10 a la potencia de un número.\",\n    \"MATH_TRIG_HELPURL\": \"https://es.wikipedia.org/wiki/Función_trigonométrica\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Devolver el seno de un grado (no radián).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Devolver el coseno de un grado (no radián).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Devolver la tangente de un grado (no radián).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Devolver el arcoseno de un número.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Devolver el arcocoseno de un número.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Devolver el arcotangente de un número.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://es.wikipedia.org/wiki/Anexo:Constantes_matemáticas\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Devolver una de las constantes comunes: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), o ∞ (infinito).\",\n    \"MATH_IS_EVEN\": \"es par\",\n    \"MATH_IS_ODD\": \"es impar\",\n    \"MATH_IS_PRIME\": \"es primo\",\n    \"MATH_IS_WHOLE\": \"es entero\",\n    \"MATH_IS_POSITIVE\": \"es positivo\",\n    \"MATH_IS_NEGATIVE\": \"es negativo\",\n    \"MATH_IS_DIVISIBLE_BY\": \"es divisible por\",\n    \"MATH_IS_TOOLTIP\": \"Comprobar si un número es par, impar, primo, entero, positivo, negativo, o si es divisible por un número determinado. Devuelve verdadero o falso.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"cambiar\",\n    \"MATH_CHANGE_INPUT_BY\": \"por\",\n    \"MATH_CHANGE_TOOLTIP\": \"Añadir un número a la variable «%1».\",\n    \"MATH_ROUND_HELPURL\": \"https://es.wikipedia.org/wiki/Redondeo\",\n    \"MATH_ROUND_TOOLTIP\": \"Redondear un número hacia arriba o hacia abajo.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"redondear\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"redondear más\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"redondear menos\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"suma de la lista\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Devolver la suma de todos los números en la lista.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"min de la lista\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Devolver el número más pequeño en la lista.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"max de la lista\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Devolver el número más grande en la lista.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"promedio de la lista\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Devolver el promedio (media aritmética) de los valores numéricos en la lista.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mediana de lista\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Devolver la mediana en la lista.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"modos de la lista\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Devolver una lista de los elementos más comunes en la lista.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"desviación estándar de la lista\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Devolver la desviación estándar de la lista.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"elemento aleatorio de la lista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Devolver un elemento aleatorio de la lista.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"resultado de %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Devolver el resultado al dividir los dos números.\",\n    \"MATH_CONSTRAIN_TITLE\": \"limitar %1 bajo %2 alto %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Limitar un número entre los límites especificados (inclusive).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://es.wikipedia.org/wiki/Generador_de_números_aleatorios\",\n    \"MATH_RANDOM_INT_TITLE\": \"entero aleatorio de %1 a %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Devolver un entero aleatorio entre los dos límites especificados, inclusive.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://es.wikipedia.org/wiki/Generador_de_números_aleatorios\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"fracción aleatoria\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Devolver una fracción aleatoria entre 0,0 (ambos inclusive) y 1.0 (exclusivo).\",\n    \"TEXT_TEXT_HELPURL\": \"https://es.wikipedia.org/wiki/Cadena_de_caracteres\",\n    \"TEXT_TEXT_TOOLTIP\": \"Una letra, palabra o línea de texto.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"crear texto con\",\n    \"TEXT_JOIN_TOOLTIP\": \"Crear un fragmento de texto al unir cualquier número de elementos.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"unir\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Agregar, eliminar o reordenar las secciones para reconfigurar este bloque de texto.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Agregar un elemento al texto.\",\n    \"TEXT_APPEND_TO\": \"a\",\n    \"TEXT_APPEND_APPENDTEXT\": \"añadir texto\",\n    \"TEXT_APPEND_TOOLTIP\": \"Añadir texto a la variable '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"longitud de %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Devuelve el número de letras (incluyendo espacios) en el texto proporcionado.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 está vacío\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Devuelve verdadero si el texto proporcionado está vacío.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Devuelve el índice de la primera/última aparición del primer texto en el segundo texto. Devuelve 0 si el texto no se encuentra.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"en el texto\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"encontrar la primera aparición del texto\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"encontrar la última aparición del texto\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"en el texto\",\n    \"TEXT_CHARAT_FROM_START\": \"obtener la letra #\",\n    \"TEXT_CHARAT_FROM_END\": \"obtener la letra # del final\",\n    \"TEXT_CHARAT_FIRST\": \"obtener la primera letra\",\n    \"TEXT_CHARAT_LAST\": \"obtener la última letra\",\n    \"TEXT_CHARAT_RANDOM\": \"obtener letra aleatoria\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Devuelve la letra a la posición especificada.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Devuelve una porción determinada del texto.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"en el texto\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"obtener subcadena de la letra #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"obtener subcadena de la letra # del final\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"obtener subcadena de la primera letra\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"a la letra #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"a la letra # del final\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"a la última letra\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Devuelve una copia del texto en un caso diferente.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"a mayúsculas\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"a minúsculas\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"a mayúsculas cada palabra\",\n    \"TEXT_TRIM_TOOLTIP\": \"Devuelve una copia del texto con espacios retirados de uno o ambos extremos.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"quitar espacios de ambos lados de\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"quitar espacios al inicio de\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"quitar espacios al final de\",\n    \"TEXT_PRINT_TITLE\": \"imprimir %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Imprimir el texto especificado, número u otro valor.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"solicitar el texto con el mensaje\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"solicitar el número con el mensaje\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Solicitar al usuario por un número.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Solicitar al usuario por un texto.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"crear lista vacía\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Devuelve una lista, de longitud de 0, que no contenga ningún registro de datos\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Crear una lista con cualquier número de elementos.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"crear lista con\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Agregar, eliminar o reorganizar las secciones para reconfigurar esta lista de bloques.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Agregar un elemento a la lista.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Crea una lista que consta de un valor dado repetido el número de veces especificado.\",\n    \"LISTS_REPEAT_TITLE\": \"crear lista con el elemento %1 repetido %2 veces\",\n    \"LISTS_LENGTH_TITLE\": \"longitud de %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Devuelve la longitud de una lista.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 está vacío\",\n    \"LISTS_TOOLTIP\": \"Devuelve verdadero si la lista está vacía.\",\n    \"LISTS_INLIST\": \"en la lista\",\n    \"LISTS_INDEX_OF_FIRST\": \"encontrar la primera aparición del elemento\",\n    \"LISTS_INDEX_OF_LAST\": \"encontrar la última aparición del elemento\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Devuelve el índice de la primera/última aparición del elemento en la lista. Devuelve 0 si el texto no se encuentra.\",\n    \"LISTS_GET_INDEX_GET\": \"obtener\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"obtener y retirar\",\n    \"LISTS_GET_INDEX_REMOVE\": \"eliminar\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# del final\",\n    \"LISTS_GET_INDEX_FIRST\": \"primero\",\n    \"LISTS_GET_INDEX_LAST\": \"último\",\n    \"LISTS_GET_INDEX_RANDOM\": \"aleatorio\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Devuelve el elemento a la posición especificada en la lista. #1 es el primer elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Devuelve el elemento a la posición especificada en la lista. #1 es el último elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Devuelve el primer elemento de una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Devuelve el último elemento de una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Devuelve un elemento aleatorio en una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Elimina y devuelve el elemento a la posición especificada en la lista. #1 es el primer elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Elimina y devuelve el elemento a la posición especificada en la lista. #1 es el último elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Elimina y devuelve el primer elemento de una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Elimina y devuelve el último elemento de una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Elimina y devuelve un elemento aleatorio en una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Elimina el elemento a la posición especificada en la lista. #1 es el primer elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Elimina el elemento a la posición especificada en la lista. #1 es el último elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Elimina el primer elemento de una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Elimina el último elemento de una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Elimina un elemento aleatorio en una lista.\",\n    \"LISTS_SET_INDEX_SET\": \"establece\",\n    \"LISTS_SET_INDEX_INSERT\": \"inserta en\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"como\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Establece el elemento a la posición especificada en una lista. #1 es el primer elemento.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Establece el elemento a la posición especificada en una lista. #1 es el último elemento.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Establece el primer elemento de una lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Establece el último elemento de una lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Establece un elemento aleatorio en una lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Inserta el elemento a la posición especificada en la lista. #1 es el primer elemento.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Inserta el elemento a la posición especificada en la lista. #1 es el último elemento.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Inserta el elemento al inicio de una lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Añade el elemento al final de una lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Inserta el elemento aleatoriamente en una lista.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"obtener sub-lista de #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"obtener sub-lista de # del final\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"obtener sub-lista del primero\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"a #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"a # del final\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"a la última\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Crea una copia de la parte especificada de una lista.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Devuelve el valor de esta variable.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Crear 'set %1'\",\n    \"VARIABLES_SET_TITLE\": \"establece\",\n    \"VARIABLES_SET_TAIL\": \"a\",\n    \"VARIABLES_SET_TOOLTIP\": \"Establece esta variable para que sea igual a la entrada.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Crear 'obtener %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"a\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"hacer algo\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"con:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Crea una función sin salida.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"devuelve\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Crea una función con una salida.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Advertencia: Esta función tiene parámetros duplicados.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://es.wikipedia.org/wiki/Subrutina\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Ejecuta la función definida por el usuario '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://es.wikipedia.org/wiki/Subrutina\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Ejecuta la función definida por el usuario '%1' y usar su salida.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"entradas\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nombre de entrada:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Destacar definición de la función\",\n    \"PROCEDURES_CREATE_DO\": \"Crear '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Si el valor es verdadero, entonces devuelve un segundo valor.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Advertencia: Este bloque solo puede ser utilizado dentro de la definición de una función.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/fa.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Ebraminio\",\n            \"Reza1615\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"مورد\",\n    \"DUPLICATE_BLOCK\": \"تکراری\",\n    \"ADD_COMMENT\": \"افزودن نظر\",\n    \"REMOVE_COMMENT\": \"حذف نظر\",\n    \"EXTERNAL_INPUTS\": \"ورودی‌های خارجی\",\n    \"INLINE_INPUTS\": \"ورودی‌های درون خطی\",\n    \"DELETE_BLOCK\": \"حذف بلوک\",\n    \"DELETE_X_BLOCKS\": \"حذف بلوک‌های %1\",\n    \"COLLAPSE_BLOCK\": \"فروپاشی بلوک\",\n    \"COLLAPSE_ALL\": \"فروپاشی بلوک‌ها\",\n    \"EXPAND_BLOCK\": \"گسترش بلوک\",\n    \"EXPAND_ALL\": \"گسترش بلوک‌ها\",\n    \"DISABLE_BLOCK\": \"غیرفعال‌سازی بلوک\",\n    \"ENABLE_BLOCK\": \"فعال‌سازی بلوک\",\n    \"HELP\": \"راهنما\",\n    \"CHANGE_VALUE_TITLE\": \"تغییر مقدار:\",\n    \"NEW_VARIABLE\": \"متغیر جدید...\",\n    \"NEW_VARIABLE_TITLE\": \"نام متغیر جدید:\",\n    \"RENAME_VARIABLE\": \"تغییر نام متغیر...\",\n    \"RENAME_VARIABLE_TITLE\": \"تغییر نام همهٔ متغیرهای «%1» به:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%B1%D9%86%DA%AF\",\n    \"COLOUR_PICKER_TOOLTIP\": \"انتخاب یک رنگ از تخته‌رنگ.\",\n    \"COLOUR_RANDOM_TITLE\": \"رنگ تصادفی\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"انتخاب یک رنگ به شکل تصادفی.\",\n    \"COLOUR_RGB_TITLE\": \"رنگ با\",\n    \"COLOUR_RGB_RED\": \"قرمز\",\n    \"COLOUR_RGB_GREEN\": \"سبز\",\n    \"COLOUR_RGB_BLUE\": \"آبی\",\n    \"COLOUR_RGB_TOOLTIP\": \"ساخت یک رنگ با مقدار مشخص‌شده‌ای از قرمز، سبز و آبی. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند.\",\n    \"COLOUR_BLEND_TITLE\": \"مخلوط\",\n    \"COLOUR_BLEND_COLOUR1\": \"رنگ ۱\",\n    \"COLOUR_BLEND_COLOUR2\": \"رنگ ۲\",\n    \"COLOUR_BLEND_RATIO\": \"نسبت\",\n    \"COLOUR_BLEND_TOOLTIP\": \"دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%AD%D9%84%D9%82%D9%87_%D9%81%D9%88%D8%B1\",\n    \"CONTROLS_REPEAT_TITLE\": \"%1 بار تکرار\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"تکرار\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"بار\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"انحام\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"انجام چند عبارت چندین بار.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"تکرار در حالی که\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"تکرار تا زمانی که\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"متغیر %1 را در مقادیر شروع‌شده از عدد انتهای  به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"با تعداد\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"از %1 به %2 با گام‌های %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"برای هر مورد\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"در فهرست\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"شکستن حلقه\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"ادامه با تکرار بعدی حلقه\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"شکستن حلقهٔ شامل.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده.  در غیر این صورت بلوک دوم عبارات انجام بده.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده.  در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"اگر مقدار اول درست است، بلوک اول عبارات را انجام بده.  در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده.  اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده.\",\n    \"CONTROLS_IF_MSG_IF\": \"اگر\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"اگر آنگاه\",\n    \"CONTROLS_IF_MSG_ELSE\": \"آنگاه\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"اضافه، حذف یا ترتیب‌سازی قسمت‌ها برای تنظیم مجدد این بلوک اگر مسدود است.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"افزودن یک شرط به بلوک اگر.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"اضافه‌کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://fa.wikipedia.org/wiki/%D9%86%D8%A7%D8%A8%D8%B1%D8%A7%D8%A8%D8%B1%DB%8C\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"بازگرداندن صحیح اگر هر دو ورودی صحیح باشد.\",\n    \"LOGIC_OPERATION_AND\": \"و\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد.\",\n    \"LOGIC_OPERATION_OR\": \"یا\",\n    \"LOGIC_NEGATE_TITLE\": \"نه %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"صحیح\",\n    \"LOGIC_BOOLEAN_FALSE\": \"ناصحیح\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"بازگرداندن یکی از صحیح یا ناصحیح.\",\n    \"LOGIC_NULL\": \"تهی\",\n    \"LOGIC_NULL_TOOLTIP\": \"تهی بازمی‌گرداند.\",\n    \"LOGIC_TERNARY_CONDITION\": \"آزمایش\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"اگر صحیح\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"اگر ناصحیح\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را.\",\n    \"MATH_NUMBER_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF\",\n    \"MATH_NUMBER_TOOLTIP\": \"یک عدد.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%AD%D8%B3%D8%A7%D8%A8\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"بازگرداندن مقدار جمع دو عدد.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"بازگرداندن تفاوت دو عدد.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"بازگرداندن حاصلضرب دو عدد.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"بازگرداندن باقی‌ماندهٔ دو عدد.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد.\",\n    \"MATH_SINGLE_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%B1%DB%8C%D8%B4%D9%87_%D8%AF%D9%88%D9%85\",\n    \"MATH_SINGLE_OP_ROOT\": \"ریشهٔ دوم\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"ریشهٔ دوم یک عدد را باز می‌گرداند.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"مطلق\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"قدر مطلق یک عدد را بازمی‌گرداند.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"منفی‌شدهٔ یک عدد را باز می‌گرداند.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"لوگاریتم طبیعی یک عدد را باز می‌گرداند.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"بازگرداندن توان e یک عدد.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"بازگرداندن توان ۱۰ یک عدد.\",\n    \"MATH_TRIG_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%AA%D8%A7%D8%A8%D8%B9%E2%80%8C%D9%87%D8%A7%DB%8C_%D9%85%D8%AB%D9%84%D8%AB%D8%A7%D8%AA%DB%8C\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"بازگرداندن سینوس درجه (نه رادیان).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"بازگرداندن کسینوس درجه (نه رادیان).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"بازگرداندن تانژانت یک درجه (نه رادیان).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"بازگرداندن آرک‌سینوس درجه (نه رادیان).\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"بازگرداندن آرک‌کسینوس درجه (نه رادیان).\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"بازگرداندن آرک‌تانژانت درجه (نه رادیان).\",\n    \"MATH_CONSTANT_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%AB%D8%A7%D8%A8%D8%AA_%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C\",\n    \"MATH_CONSTANT_TOOLTIP\": \"یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت).\",\n    \"MATH_IS_EVEN\": \"زوج است\",\n    \"MATH_IS_ODD\": \"فرد است\",\n    \"MATH_IS_PRIME\": \"عدد اول است\",\n    \"MATH_IS_WHOLE\": \"کامل است\",\n    \"MATH_IS_POSITIVE\": \"مثبت است\",\n    \"MATH_IS_NEGATIVE\": \"منفی است\",\n    \"MATH_IS_DIVISIBLE_BY\": \"تقسیم شده بر\",\n    \"MATH_IS_TOOLTIP\": \"بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند.\",\n    \"MATH_CHANGE_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%E2%80%8C%D9%86%D9%88%DB%8C%D8%B3%DB%8C#.D8.A7.D9.81.D8.B2.D8.A7.DB.8C.D8.B4_.D8.B4.D9.85.D8.A7.D8.B1.D9.86.D8.AF.D9.87\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"تغییر\",\n    \"MATH_CHANGE_INPUT_BY\": \"با\",\n    \"MATH_CHANGE_TOOLTIP\": \"افزودن یک عدد به متغیر '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29\",\n    \"MATH_ROUND_TOOLTIP\": \"گردکردن یک عدد به بالا یا پایین.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"گردکردن\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"گرد به بالا\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"گرد به پایین\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"جمع فهرست\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"جمع همهٔ عددهای فهرست را باز می‌گرداند.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"کوچکترین فهرست\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"کوچک‌ترین عدد در فهرست را باز می‌گرداند.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"بزرگ‌ترین فهرست\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"بزرگ‌ترین عدد در فهرست را باز می‌گرداند.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"میانگین فهرست\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"میانهٔ فهرست\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"میانهٔ عدد در فهرست را بر می‌گرداند.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"مد فهرست\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"شایع‌ترین قلم(های) در فهرست را بر می‌گرداند.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"انحراف معیار فهرست\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"انحراف معیار فهرست را بر می‌گرداند.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"مورد تصادفی از فهرست\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"موردی تصادفی از فهرست را بر می‌گرداند.\",\n    \"MATH_MODULO_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA_%D9%BE%DB%8C%D9%85%D8%A7%D9%86%D9%87\",\n    \"MATH_MODULO_TITLE\": \"باقی‌ماندهٔ %1 + %2\",\n    \"MATH_MODULO_TOOLTIP\": \"باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند.\",\n    \"MATH_CONSTRAIN_TITLE\": \"محدودکردن %1 پایین %2 بالا %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C\",\n    \"MATH_RANDOM_INT_TITLE\": \"عدد صحیح تصادفی بین %1 تا %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"کسر تصادفی\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز).\",\n    \"TEXT_TEXT_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%B1%D8%B4%D8%AA%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29\",\n    \"TEXT_TEXT_TOOLTIP\": \"یک حرف، کلمه یا خطی از متن.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"ایجاد متن با\",\n    \"TEXT_JOIN_TOOLTIP\": \"یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"عضویت\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"اضافه‌کردن، حذف یا مرتب‌سازی بحش‌ها برای تنظیم مجدد این بلوک متنی.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"افزودن یک مورد به متن.\",\n    \"TEXT_APPEND_TO\": \"به\",\n    \"TEXT_APPEND_APPENDTEXT\": \"الحاق متن\",\n    \"TEXT_APPEND_TOOLTIP\": \"الحاق متنی به متغیر «%1».\",\n    \"TEXT_LENGTH_TITLE\": \"طول %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 خالی است\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"اضافه‌کردن صحیح اگر متن فراهم‌شده خالی است.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد ۰ باز می‌گرداند.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"در متن\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"اولین رخداد متن را بیاب\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"آخرین رخداد متن را بیاب\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"در متن\",\n    \"TEXT_CHARAT_FROM_START\": \"گرفتن حرف #\",\n    \"TEXT_CHARAT_FROM_END\": \"گرفتن حرف # از آخر\",\n    \"TEXT_CHARAT_FIRST\": \"گرفتن اولین حرف\",\n    \"TEXT_CHARAT_LAST\": \"گرفتن آخرین حرف\",\n    \"TEXT_CHARAT_RANDOM\": \"گرفتن حرف تصادفی\",\n    \"TEXT_CHARAT_TOOLTIP\": \"حرفی در موقعیت مشخص‌شده بر می‌گرداند.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"در متن\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"گرفتن زیرمتن از حرف #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"گرفتن زیرمتن از حرف # به انتها\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"گرفتن زیرمتن از اولین حرف\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"به حرف #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"به حرف # از انتها\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"به آخرین حرف\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"بازگرداندن کپی متن در حالتی متفاوت.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"به حروف بزرگ\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"به حروف کوچک\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"به حروف بزرگ عنوان\",\n    \"TEXT_TRIM_TOOLTIP\": \"کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"تراشیدن فاصله‌ها از  هر دو طرف\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"تراشیدن فاصله‌ها از  طرف چپ\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"تراشیدن فاصله‌ها از  طرف چپ\",\n    \"TEXT_PRINT_TITLE\": \"چاپ %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"اعلان برای متن با پیام\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"اعلان برای عدد با پیام\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"اعلان برای کاربر با یک عدد.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"اعلان برای کاربر برای یک متن.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"ایجاد فهرست خالی\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند.\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"فهرستی از هر عددی از موارد می‌سازد.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"ایجاد فهرست با\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"فهرست\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"اضافه‌کردن، حذف‌کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"اضافه‌کردن یک مورد به فهرست.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد.\",\n    \"LISTS_REPEAT_TITLE\": \"فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد\",\n    \"LISTS_LENGTH_TITLE\": \"طول %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"طول یک فهرست را برمی‌گرداند.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 خالی است\",\n    \"LISTS_TOOLTIP\": \"اگر فهرست خالی است مقدار صجیج بر می‌گرداند.\",\n    \"LISTS_INLIST\": \"در فهرست\",\n    \"LISTS_INDEX_OF_FIRST\": \"یافتن اولین رخ‌داد مورد\",\n    \"LISTS_INDEX_OF_LAST\": \"یافتن آخرین رخ‌داد مورد\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. ۰ بر می‌گرداند اگر متن موجود نبود.\",\n    \"LISTS_GET_INDEX_GET\": \"گرفتن\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"گرفتن و حذف‌کردن\",\n    \"LISTS_GET_INDEX_REMOVE\": \"حذف‌کردن\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# از انتها\",\n    \"LISTS_GET_INDEX_FIRST\": \"اولین\",\n    \"LISTS_GET_INDEX_LAST\": \"آخرین\",\n    \"LISTS_GET_INDEX_RANDOM\": \"تصادفی\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"موردی در محل مشخص‌شده بر می‌گرداند.  #1 اولین مورد است.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"موردی در محل مشخص در فهرست بر می‌گرداند.  #1 آخرین مورد است.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"اولین مورد یک فهرست را بر می‌گرداند.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"آخرین مورد در یک فهرست را بر می‌گرداند.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"یک مورد تصادفی در یک فهرست بر می‌گرداند.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند.  #1 اولین مورد است.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند.  #1 آخرین مورد است.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند.  #1 اولین مورد است.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند.  #1 آخرین مورد است.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"اولین مورد را در یک فهرست حذف می‌کند.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"آخرین مورد را در یک فهرست حذف می‌کند.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"یک مورد تصادفی را یک فهرست حذف می‌کند.\",\n    \"LISTS_SET_INDEX_SET\": \"مجموعه\",\n    \"LISTS_SET_INDEX_INSERT\": \"درج در\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"به‌عنوان\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"مورد مشخص‌شده در یک فهرست را قرار می‌دهد.  #1 اولین مورد است.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"مورد مشخص‌شده در یک فهرست را قرار می‌دهد.  #1 آخرین مورد است.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"اولین مورد در یک فهرست را تعیین می‌کند.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"آخرین مورد در یک فهرست را تعیین می‌کند.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"یک مورد تصادفی در یک فهرست را تعیین می‌کند.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند.  #1 اولین مورد است.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند.  #1 آخرین مورد است.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"موردی به ته فهرست اضافه می‌کند.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"موردی به ته فهرست الحاق می‌کند.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"مورد را به صورت تصادفی در یک فهرست می‌افزاید.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"گرفتن زیرمجموعه‌ای از #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"گرفتن زیرمجموعه‌ای از # از انتها\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"گرفتن زیرمجموعه‌ای از ابتدا\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"به #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"به # از انتها\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"به آخرین\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند.\",\n    \"VARIABLES_GET_TOOLTIP\": \"مقدار این متغیر را بر می‌گرداند.\",\n    \"VARIABLES_GET_CREATE_SET\": \"درست‌کردن «تنظیم %1»\",\n    \"VARIABLES_SET_TITLE\": \"مجموعه\",\n    \"VARIABLES_SET_TAIL\": \"به\",\n    \"VARIABLES_SET_TOOLTIP\": \"متغیر برابر با خروجی را مشخص می‌کند.\",\n    \"VARIABLES_SET_CREATE_GET\": \"درست‌کردن «گرفتن %1»\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"به\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"انجام چیزی\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"با:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"تابعی می‌سازد بدون هیچ خروجی.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"بازگشت\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"تابعی با یک خروجی می‌سازد.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"اخطار: این تابعی پارامتر تکراری دارد.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"اجرای تابع تعریف‌شده توسط کاربر «%1».\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"ورودی‌ها\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"نام ورودی:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"برجسته‌سازی تعریف تابع\",\n    \"PROCEDURES_CREATE_DO\": \"ساختن «%1»\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"اگر یک مقدار صحیح است، مقدار دوم را برگردان.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"اخطار: این بلوک احتمالاً فقط داخل یک تابع استفاده می‌شود.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/fi.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Nike\",\n            \"Silvonen\",\n            \"Espertus\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"kohde\",\n    \"DUPLICATE_BLOCK\": \"Kopioi\",\n    \"ADD_COMMENT\": \"Lisää kommentti\",\n    \"REMOVE_COMMENT\": \"Poista kommentti\",\n    \"EXTERNAL_INPUTS\": \"Ulkoiset syötteet\",\n    \"INLINE_INPUTS\": \"Tuo syötteet\",\n    \"DELETE_BLOCK\": \"Poista lohko\",\n    \"DELETE_X_BLOCKS\": \"Poista %1 lohkoa\",\n    \"COLLAPSE_BLOCK\": \"Sulje lohko\",\n    \"COLLAPSE_ALL\": \"Sulje lohkot\",\n    \"EXPAND_BLOCK\": \"Laajenna lohko\",\n    \"EXPAND_ALL\": \"Laajenna lohkot\",\n    \"DISABLE_BLOCK\": \"Passivoi lohko\",\n    \"ENABLE_BLOCK\": \"Aktivoi lohko\",\n    \"HELP\": \"Apua\",\n    \"CHANGE_VALUE_TITLE\": \"Muuta arvoa:\",\n    \"NEW_VARIABLE\": \"Uusi muuttuja...\",\n    \"NEW_VARIABLE_TITLE\": \"Uuden muuttujan nimi:\",\n    \"RENAME_VARIABLE\": \"Nimeä uudelleen muuttuja...\",\n    \"RENAME_VARIABLE_TITLE\": \"Nimeä uudelleen kaikki '%1' muuttujaa:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://fi.wikipedia.org/wiki/V%C3%A4ri\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Valitse väri paletista.\",\n    \"COLOUR_RANDOM_TITLE\": \"satunnainen väri\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Valitse väri sattumanvaraisesti.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"väri, jossa on\",\n    \"COLOUR_RGB_RED\": \"punainen\",\n    \"COLOUR_RGB_GREEN\": \"vihreä\",\n    \"COLOUR_RGB_BLUE\": \"sininen\",\n    \"COLOUR_RGB_TOOLTIP\": \"Luo väri, jossa on tietty määrä punaista, vihreää ja sinistä. Kaikkien arvojen tulee olla välillä 0 - 100.\",\n    \"COLOUR_BLEND_TITLE\": \"sekoitus\",\n    \"COLOUR_BLEND_COLOUR1\": \"väri 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"väri 2\",\n    \"COLOUR_BLEND_RATIO\": \"suhde\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Sekoittaa kaksi väriä keskenään annetussa suhteessa (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"toista %1 kertaa\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"toista\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"kertaa\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"tee\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Suorita joukko lausekkeita useampi kertaa.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"toista niin kauan kuin\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"toista kunnes\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Niin kauan kuin arvo on tosi, suorita joukko lausekkeita.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Niin kauan kuin arvo on epätosi, suorita joukko lausekkeita.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Aseta muuttujaan %1 arvot alkuarvosta loppuarvoon annetun askeleen välein ja suorita joka askeleella annettu koodilohko.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"laske\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"Väli %1-%2 %3:n välein\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"kullekin kohteelle\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"listassa\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Aseta muuttujan %1 arvoksi kukin listan kohde vuorollaan ja suorita joukko lausekkeita.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"poistu silmukasta\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"jatka silmukan seuraavaan toistoon\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Poistu sisemmästä silmukasta.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Ohita loput tästä silmukasta ja siirry seuraavaan toistoon.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Varoitus: Tätä lohkoa voi käyttää vain silmukan sisällä.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Jos arvo on tosi, suorita lauseke.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Jos arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten suorita toinen lohko lausekkeita.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Jos ensimmäinen arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten, jos toinen arvo on tosi, suorita toinen lohko lausekkeita.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Jos ensimmäinen arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten, jos toinen arvo on tosi, suorita toinen lohko lausekkeita. Jos mikään arvoista ei ole tosi, suorita viimeinen lohko lausekkeita.\",\n    \"CONTROLS_IF_MSG_IF\": \"jos\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"muuten jos\",\n    \"CONTROLS_IF_MSG_ELSE\": \"muuten\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Lisää, poista tai järjestele osioita tässä \\\"jos\\\" lohkossa.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Lisää ehto \\\"jos\\\" lohkoon.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Lisää lopullinen \\\"muuten\\\" lohko \\\"jos\\\" lohkoon.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://fi.wikipedia.org/wiki/Ep%C3%A4yht%C3%A4l%C3%B6\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Palauta tosi, jos syötteet ovat keskenään samat.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Palauttaa tosi, jos syötteet eivät ole keskenään samoja.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Palauttaa tosi, jos ensimmäinen syöte on pienempi, kuin toinen.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Palauttaa tosi, jos ensimmäinen syöte on pienempi tai yhtä suuri, kuin toinen.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Palauttaa tosi, jos ensimmäinen syöte on suurempi, kuin toinen.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Palauttaa tosi, jos ensimmäinen syöte on suurempi tai yhtä suuri, kuin toinen.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Palauttaa tosi, jos kummatkin syötteet ovat tosia.\",\n    \"LOGIC_OPERATION_AND\": \"ja\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Palauttaa tosi, jos ainakin yksi syötteistä on tosi.\",\n    \"LOGIC_OPERATION_OR\": \"tai\",\n    \"LOGIC_NEGATE_TITLE\": \"ei %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Palauttaa tosi, jos syöte on epätosi. Palauttaa epätosi, jos syöte on tosi.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"tosi\",\n    \"LOGIC_BOOLEAN_FALSE\": \"epätosi\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Palauttaa joko tosi tai epätosi.\",\n    \"LOGIC_NULL\": \"ei mitään\",\n    \"LOGIC_NULL_TOOLTIP\": \"Palauttaa \\\"ei mitään\\\"-arvon.\",\n    \"LOGIC_TERNARY_CONDITION\": \"ehto\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"jos tosi\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"jos epätosi\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Tarkistaa testin ehdon. Jos ehto on tosi, palauttaa \\\"jos tosi\\\" arvon, muuten palauttaa \\\"jos epätosi\\\" arvon.\",\n    \"MATH_NUMBER_HELPURL\": \"https://fi.wikipedia.org/wiki/Luku\",\n    \"MATH_NUMBER_TOOLTIP\": \"Luku.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"⋅\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"http://fi.wikipedia.org/wiki/Aritmetiikka\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Palauttaa kahden luvun summan.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Palauttaa kahden luvun erotuksen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Palauttaa kertolaskun tulon.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Palauttaa jakolaskun osamäärän.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Palauttaa ensimmäisen luvun korotettuna toisen luvun potenssiin.\",\n    \"MATH_SINGLE_HELPURL\": \"https://fi.wikipedia.org/wiki/Neli%C3%B6juuri\",\n    \"MATH_SINGLE_OP_ROOT\": \"neliöjuuri\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Palauttaa luvun neliöjuuren.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"itseisarvo\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Palauttaa luvun itseisarvon.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Palauttaa numeron vastaluvun.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Palauttaa luvun luonnollisen logaritmin.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Palauttaa luvun kymmenkantaisen logaritmin.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Palauttaa e potenssiin luku.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Palauttaa 10 potenssiin luku.\",\n    \"MATH_TRIG_HELPURL\": \"https://fi.wikipedia.org/wiki/Trigonometrinen_funktio\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Palauttaa asteluvun (ei radiaanin) sinin.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Palauttaa asteluvun (ei radiaanin) kosinin.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Palauttaa asteluvun (ei radiaanin) tangentin.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Palauttaa luvun arkussinin.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Palauttaa luvun arkuskosinin.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Palauttaa luvun arkustangentin.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Palauttaa jonkin seuraavista vakioista: π (3.141…), e (2.718…), φ (1.618…), neliöjuuri(2) (1.414…), neliöjuuri(½) (0.707…), or ∞ (ääretön).\",\n    \"MATH_IS_EVEN\": \"on parillinen\",\n    \"MATH_IS_ODD\": \"on pariton\",\n    \"MATH_IS_PRIME\": \"on alkuluku\",\n    \"MATH_IS_WHOLE\": \"on kokonaisluku\",\n    \"MATH_IS_POSITIVE\": \"on positiivinen\",\n    \"MATH_IS_NEGATIVE\": \"on negatiivinen\",\n    \"MATH_IS_DIVISIBLE_BY\": \"on jaollinen luvulla\",\n    \"MATH_IS_TOOLTIP\": \"Tarkistaa onko numero parillinen, pariton, alkuluku, kokonaisluku, positiivinen, negatiivinen, tai jos se on jaollinen toisella luvulla. Palauttaa tosi tai epätosi.\",\n    \"MATH_CHANGE_HELPURL\": \"https://fi.wikipedia.org/wiki/Yhteenlasku\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"muuta\",\n    \"MATH_CHANGE_INPUT_BY\": \"arvolla\",\n    \"MATH_CHANGE_TOOLTIP\": \"Lisää arvo muuttujaan '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://fi.wikipedia.org/wiki/Py%C3%B6rist%C3%A4minen\",\n    \"MATH_ROUND_TOOLTIP\": \"Pyöristää luvun ylös- tai alaspäin.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"pyöristä\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"pyöristä ylöspäin\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"pyöristä alaspäin\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"summa luvuista\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Palauttaa kaikkien annettujen lukujen summan.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"pienin luvuista\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Palauttaa pienimmän annetuista luvuista.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"suurin luvuista\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Palauttaa suurimman annetuista luvuista.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"keskiarvo luvuista\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Palauttaa aritmeettisen keskiarvon annetuista luvuista.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"keskiluku luvuista\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Palauttaa annettujen lukujen keskiluvun.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"tyyppiarvo luvuista\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Palauttaa luettelon yleisimmistä luvuista annetussa listassa.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"keskihajonta luvuista\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Palauttaa annettujen lukujen keskihajonnan.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"satunnainen valinta luvuista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Palauttaa satunnaisesti valitun luvun annetuista luvuista.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"%1 ÷ %2 jakojäännös\",\n    \"MATH_MODULO_TOOLTIP\": \"Palauttaa jakolaskun jakojäännöksen.\",\n    \"MATH_CONSTRAIN_TITLE\": \"rajoita %1 vähintään %2 enintään %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Rajoittaa arvon annetulle suljetulle välille.\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://fi.wikipedia.org/wiki/Satunnaisluku\",\n    \"MATH_RANDOM_INT_TITLE\": \"Palauttaa satunnaisen kokonaisluvun väliltä %1-%2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Palauttaa satunnaisen kokonaisluvun kahden annetun arvon suljetulta väliltä.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://fi.wikipedia.org/wiki/Satunnaisluku\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"satunnainen murtoluku\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Palauttaa satunnaisen luvun oikealta puoliavoimesta välistä [0.0, 1.0).\",\n    \"TEXT_TEXT_HELPURL\": \"https://fi.wikipedia.org/wiki/Merkkijono\",\n    \"TEXT_TEXT_TOOLTIP\": \"Kirjain, sana tai rivi tekstiä.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"luo teksti\",\n    \"TEXT_JOIN_TOOLTIP\": \"Luo merkkijonon liittämällä yhteen minkä tahansa määrän kohteita.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"liitä\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Lisää, poista tai uudelleen järjestä osioita tässä lohkossa.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Lisää kohteen tekstiin.\",\n    \"TEXT_APPEND_TO\": \"muuttujaan\",\n    \"TEXT_APPEND_APPENDTEXT\": \"lisää teksti\",\n    \"TEXT_APPEND_TOOLTIP\": \"Lisää tekstiä muuttujaan '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"%1:n pituus\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Palauttaa annetussa tekstissä olevien merkkien määrän (välilyönnit mukaan lukien).\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 on tyhjä\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Palauttaa tosi, jos annettu teksti on tyhjä.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Palauttaa ensin annetun tekstin ensimmäisen/viimeisen esiintymän osoitteen toisessa tekstissä. Palauttaa osoitteen 0 jos tekstiä ei löytynyt.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"tekstistä\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"etsi ensimmäinen esiintymä merkkijonolle\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"etsi viimeinen esiintymä merkkijonolle\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"tekstistä\",\n    \"TEXT_CHARAT_FROM_START\": \"Hae kirjain nro\",\n    \"TEXT_CHARAT_FROM_END\": \"Hae kirjain nro (lopusta laskien)\",\n    \"TEXT_CHARAT_FIRST\": \"hae ensimmäinen kirjain\",\n    \"TEXT_CHARAT_LAST\": \"hae viimeinen kirjain\",\n    \"TEXT_CHARAT_RANDOM\": \"hae satunnainen kirjain\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Palauttaa annetussa kohdassa olevan kirjaimen.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Palauttaa määrätyn osan tekstistä.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"merkkijonosta\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"hae osa alkaen kirjaimesta nro\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"hae osa alkaen kirjaimesta nro (lopusta laskien)\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"hae osa alkaen ensimmäisestä kirjaimesta\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"kirjaimeen nro\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"kirjaimeen nro (lopusta laskien)\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"viimeiseen kirjaimeen\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Palauttaa kopion tekstistä eri kirjainkoossa.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"isot kirjaimet\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"pienet kirjaimet\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"isot alkukirjaimet\",\n    \"TEXT_TRIM_TOOLTIP\": \"Palauttaa kopion tekstistä siten, että välilyönnit on poistettu yhdestä tai molemmista päistä.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"poistaa välilyönnit kummaltakin puolelta\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"poistaa välilyönnit vasemmalta puolelta\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"poistaa välilyönnit oikealta puolelta\",\n    \"TEXT_PRINT_TITLE\": \"tulosta %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Tulostaa annetun tekstin, numeron tia muun arvon.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"käyttäen annettua viestiä, kehottaa syöttämään tekstiä\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"käyttäen annettua viestiä, kehottaa syöttämään numeron\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Kehottaa käyttäjää syöttämään numeron.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Kehottaa käyttäjää syöttämään tekstiä.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"Luo tyhjä lista\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Palauta tyhjä lista, pituus 0\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Luo lista, jossa on mikä tahansa määrä kohteita.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"luo lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Listää, poista tai järjestele uudestaan osioita tässä lohkossa.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Lisää kohde listaan.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Luo listan, jossa annettu arvo toistuu määrätyn monta kertaa.\",\n    \"LISTS_REPEAT_TITLE\": \"luo lista, jossa kohde %1 toistuu %2 kertaa\",\n    \"LISTS_LENGTH_TITLE\": \"%1:n pituus\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Palauttaa listan pituuden.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 on tyhjä\",\n    \"LISTS_TOOLTIP\": \"Palauttaa tosi, jos lista on tyhjä.\",\n    \"LISTS_INLIST\": \"listassa\",\n    \"LISTS_INDEX_OF_FIRST\": \"etsi ensimmäinen esiintymä kohteelle\",\n    \"LISTS_INDEX_OF_LAST\": \"etsi viimeinen esiintymä kohteelle\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Palauttaa kohteen ensimmäisen/viimeisen esiintymän kohdan. Palauttaa 0 jos tekstiä ei löydy.\",\n    \"LISTS_GET_INDEX_GET\": \"hae\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"hae ja poista\",\n    \"LISTS_GET_INDEX_REMOVE\": \"poista\",\n    \"LISTS_GET_INDEX_FROM_START\": \"nro\",\n    \"LISTS_GET_INDEX_FROM_END\": \"nro (lopusta laskien)\",\n    \"LISTS_GET_INDEX_FIRST\": \"ensimmäinen\",\n    \"LISTS_GET_INDEX_LAST\": \"viimeinen\",\n    \"LISTS_GET_INDEX_RANDOM\": \"satunnainen\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Palauta kohde annetusta kohdasta listaa. Numero 1 tarkoittaa listan ensimmäistä kohdetta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Palauta kohde annetusta kohdasta listaa. Numero 1 tarkoittaa listan viimeistä kohdetta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Palauta ensimmäinen kohde listalta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Palauttaa listan viimeisen kohteen.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Palauttaa satunnaisen kohteen listalta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Poistaa ja palauttaa kohteen annetusta kohden listaa. Nro 1 on ensimmäinen kohde.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Poistaa ja palauttaa kohteen annetusta kohden listaa. Nro 1 on ensimmäinen kohde.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Poistaa ja palauttaa ensimmäisen kohteen listalta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Poistaa ja palauttaa viimeisen kohteen listalta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Poistaa ja palauttaa satunnaisen kohteen listalta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Poistaa kohteen listalta annetusta kohtaa. Nro 1 on ensimmäinen kohde.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Poistaa kohteen listalta annetusta kohtaa. Nro 1 on viimeinen kohde.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Poistaa ensimmäisen kohteen listalta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Poistaa viimeisen kohteen listalta.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Poistaa satunnaisen kohteen listalta.\",\n    \"LISTS_SET_INDEX_SET\": \"aseta\",\n    \"LISTS_SET_INDEX_INSERT\": \"lisää kohtaan\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"kohteeksi\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Asettaa kohteen määrättyyn kohtaa listassa. Nro 1 on listan alku.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Asettaa listan määrätyssä kohtaa olevan kohteen. Nro 1 on listan loppu.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Asettaa listan ensimmäisen kohteen.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Asettaa listan viimeisen kohteen.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Asettaa satunnaisen kohteen listassa.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Lisää kohteen listan annettuun kohtaan. Nro 1 on listan kärki.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Lisää kohteen annettuun kohtaan listaa. Nro 1 on listan häntä.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Lisää kohteen listan kärkeen.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Lisää kohteen listan loppuun.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Lisää kohteen satunnaiseen kohtaan listassa.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"hae osalista alkaen kohdasta\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"hae osalista alkaen kohdasta (lopusta laskien)\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"hae osalista alkaen alusta\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"päättyen kohtaan\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"päättyen kohtaan (lopusta laskien)\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"viimeinen\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Luo kopio määrätystä kohden listaa.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Palauttaa muuttujan arvon.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Luo 'aseta %1'\",\n    \"VARIABLES_SET_TITLE\": \"aseta\",\n    \"VARIABLES_SET_TAIL\": \"arvoksi\",\n    \"VARIABLES_SET_TOOLTIP\": \"Asettaa muutujan arvoksi annetun syötteen.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Luo 'hae %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"tehdäksesi\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"tee jotain\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"parametrit:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Luo funktio, jolla ei ole tuotosta.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"palauta\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Luo funktio, jolla ei ole tuotosta.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Varoitus: tällä funktiolla on sama parametri useamman kerran.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://fi.wikipedia.org/wiki/Aliohjelma\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Suorittaa käyttäjän määrittelemä funktio '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://fi.wikipedia.org/wiki/Aliohjelma\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Suorittaa käyttäjän määrittelemän funktion '%1' ja käyttää sen tuotosta.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"syötteet\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"syötteen nimi:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Korosta funktion määritelmä\",\n    \"PROCEDURES_CREATE_DO\": \"Luo '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Jos arvo on tosi, palauta toinen arvo.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Varoitus: tätä lohkoa voi käyttää vain funktion määrityksessä.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/fr.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Espertus\",\n            \"Gomoko\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"élément\",\n    \"DUPLICATE_BLOCK\": \"Dupliquer\",\n    \"ADD_COMMENT\": \"Ajouter un commentaire\",\n    \"REMOVE_COMMENT\": \"Supprimer un commentaire\",\n    \"EXTERNAL_INPUTS\": \"Entrées externes\",\n    \"INLINE_INPUTS\": \"Entrées en ligne\",\n    \"DELETE_BLOCK\": \"Supprimer le bloc\",\n    \"DELETE_X_BLOCKS\": \"Supprimer %1 blocs\",\n    \"COLLAPSE_BLOCK\": \"Réduire le bloc\",\n    \"COLLAPSE_ALL\": \"Réduire les blocs\",\n    \"EXPAND_BLOCK\": \"Développer le bloc\",\n    \"EXPAND_ALL\": \"Développer les blocs\",\n    \"DISABLE_BLOCK\": \"Désactiver le bloc\",\n    \"ENABLE_BLOCK\": \"Activer le bloc\",\n    \"HELP\": \"Aide\",\n    \"CHANGE_VALUE_TITLE\": \"Modifier la valeur :\",\n    \"NEW_VARIABLE\": \"Nouvelle variable…\",\n    \"NEW_VARIABLE_TITLE\": \"Nom de la nouvelle variable :\",\n    \"RENAME_VARIABLE\": \"Renommer la variable…\",\n    \"RENAME_VARIABLE_TITLE\": \"Renommer toutes les variables '%1' en :\",\n    \"COLOUR_PICKER_HELPURL\": \"https://fr.wikipedia.org/wiki/Couleur\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Choisir une couleur dans la palette\",\n    \"COLOUR_RANDOM_TITLE\": \"couleur aléatoire\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Choisir une couleur au hasard.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"colorer avec\",\n    \"COLOUR_RGB_RED\": \"rouge\",\n    \"COLOUR_RGB_GREEN\": \"vert\",\n    \"COLOUR_RGB_BLUE\": \"bleu\",\n    \"COLOUR_RGB_TOOLTIP\": \"Créer une couleur avec la quantité spécifiée de rouge, vert et bleu. Toutes les valeurs doivent être entre 0 et 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"mélanger\",\n    \"COLOUR_BLEND_COLOUR1\": \"couleur 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"couleur 2\",\n    \"COLOUR_BLEND_RATIO\": \"ratio\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Mélange deux couleurs ensemble avec un ratio donné (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"répéter %1 fois\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"répéter\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"fois\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"faire\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Exécuter certains ordres plusieurs fois.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"répéter tant que\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"répéter jusqu’à\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Tant qu’une valeur est vraie, alors exécuter certains ordres.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Tant qu’une valeur est fausse, alors exécuter certains ordres.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Faire en sorte que la variable %1 prenne les valeurs depuis le numéro de début jusqu’au numéro de fin, en s’incrémentant de l’intervalle spécifié, et exécuter les ordres spécifiés.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"compter avec\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"de %1 à %2 par %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each pour chaque bloc\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"pour chaque élément\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"dans la liste\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Pour chaque élément dans une liste, donner la valeur de l’élément à la variable '%1', puis exécuter certains ordres.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"sortir de la boucle\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continuer avec la prochaine itération de la boucle\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Sortir de la boucle englobante.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Sauter le reste de cette boucle, et poursuivre avec l’itération suivante.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Attention : Ce bloc ne devrait être utilisé que dans une boucle.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Si une valeur est vraie, alors exécuter certains ordres.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Si une valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, exécuter le second bloc d’ordres.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Si la première valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, si la seconde valeur est vraie, exécuter le second bloc d’ordres.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Si la première valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, si la seconde valeur est vraie, exécuter le second bloc d’ordres. Si aucune des valeurs n’est vraie, exécuter le dernier bloc d’ordres.\",\n    \"CONTROLS_IF_MSG_IF\": \"si\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"sinon si\",\n    \"CONTROLS_IF_MSG_ELSE\": \"sinon\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Ajouter, supprimer ou réordonner les sections pour reconfigurer ce bloc si.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Ajouter une condition au bloc si.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Ajouter une condition finale fourre-tout au bloc si.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Renvoyer vrai si les deux entrées sont égales.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Renvoyer vrai si les deux entrées ne sont pas égales.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Renvoyer vrai si la première entrée est plus petite que la seconde.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Renvoyer vrai si la première entrée est plus petite ou égale à la seconde.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Renvoyer vrai si la première entrée est plus grande que la seconde.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Renvoyer vrai si la première entrée est plus grande ou égale à la seconde.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Renvoyer vrai si les deux entrées sont vraies.\",\n    \"LOGIC_OPERATION_AND\": \"et\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Renvoyer vrai si au moins une des entrées est vraie.\",\n    \"LOGIC_OPERATION_OR\": \"ou\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"pas %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Renvoie vrai si l’entrée est fausse. Renvoie faux si l’entrée est vraie.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"vrai\",\n    \"LOGIC_BOOLEAN_FALSE\": \"faux\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Renvoie soit vrai soit faux.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"nul\",\n    \"LOGIC_NULL_TOOLTIP\": \"Renvoie nul.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"si vrai\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"si faux\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Vérifier la condition dans 'test'. Si elle est vraie, renvoie la valeur 'si vrai' ; sinon renvoie la valeur 'si faux'.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Un nombre.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Renvoie la somme des deux nombres.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Renvoie la différence des deux nombres.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Renvoie le produit des deux nombres.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Renvoie le quotient des deux nombres.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Renvoie le premier nombre élevé à la puissance du second.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"racine carrée\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Renvoie la racine carrée d’un nombre.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolu\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Renvoie la valeur absolue d’un nombre.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Renvoie l’opposé d’un nombre\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Renvoie le logarithme naturel d’un nombre.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Renvoie le logarithme base 10 d’un nombre.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Renvoie e à la puissance d’un nombre.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Renvoie 10 à la puissance d’un nombre.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Renvoie le sinus d’un angle en degrés (pas en radians).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Renvoie le cosinus d’un angle en degrés (pas en radians).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Renvoie la tangente d’un angle en degrés (pas en radians).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Renvoie l’arcsinus d’un nombre.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Renvoie l’arccosinus d’un nombre.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Renvoie l’arctangente d’un nombre.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Renvoie une des constantes courantes : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infini).\",\n    \"MATH_IS_EVEN\": \"est pair\",\n    \"MATH_IS_ODD\": \"est impair\",\n    \"MATH_IS_PRIME\": \"est premier\",\n    \"MATH_IS_WHOLE\": \"est entier\",\n    \"MATH_IS_POSITIVE\": \"est positif\",\n    \"MATH_IS_NEGATIVE\": \"est négatif\",\n    \"MATH_IS_DIVISIBLE_BY\": \"est divisible par\",\n    \"MATH_IS_TOOLTIP\": \"Vérifier si un nombre est pair, impair, premier, entier, positif, négatif, ou s’il est divisible par un certain nombre. Renvoie vrai ou faux.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"incrémenter\",\n    \"MATH_CHANGE_INPUT_BY\": \"de\",\n    \"MATH_CHANGE_TOOLTIP\": \"Ajouter un nombre à la variable '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Arrondir un nombre au-dessus ou au-dessous.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"arrondir\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"arrondir au supérieur\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"arrondir à l’inférieur\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"somme de la liste\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Renvoyer la somme de tous les nombres dans la liste.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"minimum de la liste\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Renvoyer le plus petit nombre dans la liste.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"maximum de la liste\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Renvoyer le plus grand nombre dans la liste.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"moyenne de la liste\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Renvoyer la moyenne (arithmétique) des valeurs numériques dans la liste.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"médiane de la liste\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Renvoyer le nombre médian dans la liste.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"majoritaires de la liste\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Renvoyer une liste des élément(s) le(s) plus courant(s) dans la liste.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"écart-type de la liste\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Renvoyer l’écart-type de la liste.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"élément aléatoire de la liste\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Renvoyer un élément dans la liste au hasard.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"reste de %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Renvoyer le reste de la division des deux nombres.\",\n    \"MATH_CONSTRAIN_TITLE\": \"contraindre %1 entre %2 et %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Contraindre un nombre à être entre les limites spécifiées (incluses).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"entier aléatoire entre %1 et %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Renvoyer un entier aléatoire entre les deux limites spécifiées, incluses.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"fraction aléatoire\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Renvoyer une fraction aléatoire entre 0.0 (inclus) et 1.0 (exclus).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Une lettre, un mot ou une ligne de texte.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"créer le texte avec\",\n    \"TEXT_JOIN_TOOLTIP\": \"Créer un morceau de texte en agrégeant un nombre quelconque d’éléments.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"joindre\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Ajouter, supprimer, ou réordonner des sections pour reconfigurer ce bloc de texte.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Ajouter un élément au texte.\",\n    \"TEXT_APPEND_TO\": \"à\",\n    \"TEXT_APPEND_APPENDTEXT\": \"ajouter le texte\",\n    \"TEXT_APPEND_TOOLTIP\": \"Ajouter du texte à la variable '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"longueur de %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Renvoie le nombre de lettres (espaces compris) dans le texte fourni.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 est vide\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Renvoie vrai si le texte fourni est vide.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Renvoie l’index de la première/dernière occurrence de la première chaîne dans la seconde. Renvoie 0 si la chaîne n’est pas trouvée.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"dans le texte\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"trouver la première occurrence de la chaîne\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"trouver la dernière occurrence de la chaîne\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"dans le texte\",\n    \"TEXT_CHARAT_FROM_START\": \"obtenir la lettre #\",\n    \"TEXT_CHARAT_FROM_END\": \"obtenir la lettre # depuis la fin\",\n    \"TEXT_CHARAT_FIRST\": \"obtenir la première lettre\",\n    \"TEXT_CHARAT_LAST\": \"obtenir la dernière lettre\",\n    \"TEXT_CHARAT_RANDOM\": \"obtenir une lettre au hasard\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Renvoie la lettre à la position indiquée.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Renvoie une partie indiquée du texte.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"dans le texte\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"obtenir la sous-chaîne depuis la lettre #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"obtenir la sous-chaîne depuis la lettre # depuis la fin\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"obtenir la sous-chaîne depuis la première lettre\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"jusqu’à la lettre #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"jusqu’à la lettre # depuis la fin\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"jusqu’à la dernière lettre\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Renvoyer une copie du texte dans une autre casse.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"en MAJUSCULES\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"en minuscules\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"en Majuscule Au Début De Chaque Mot\",\n    \"TEXT_TRIM_TOOLTIP\": \"Renvoyer une copie du texte avec les espaces supprimés d’un bout ou des deux.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"supprimer les espaces des deux côtés\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"supprimer les espaces du côté gauche\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"supprimer les espaces du côté droit\",\n    \"TEXT_PRINT_TITLE\": \"afficher %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Afficher le texte, le nombre ou une autre valeur spécifié.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"invite pour un texte avec un message\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"invite pour un nombre avec un message\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Demander un nombre à l’utilisateur.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Demander un texte à l’utilisateur.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"créer une liste vide\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Renvoyer une liste, de longueur 0, ne contenant aucun enregistrement\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Créer une liste avec un nombre quelconque d’éléments.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"créer une liste avec\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"liste\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Ajouter, supprimer, ou réordonner les sections pour reconfigurer ce bloc de liste.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Ajouter un élément à la liste.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Crée une liste consistant en la valeur fournie répétée le nombre de fois indiqué.\",\n    \"LISTS_REPEAT_TITLE\": \"créer une liste avec l’élément %1 répété %2 fois\",\n    \"LISTS_LENGTH_TITLE\": \"longueur de %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Renvoie la longueur d’une liste.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 est vide\",\n    \"LISTS_TOOLTIP\": \"Renvoie vrai si la liste est vide.\",\n    \"LISTS_INLIST\": \"dans la liste\",\n    \"LISTS_INDEX_OF_FIRST\": \"trouver la première occurrence de l’élément\",\n    \"LISTS_INDEX_OF_LAST\": \"trouver la dernière occurrence de l’élément\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Renvoie l’index de la première/dernière occurrence de l’élément dans la liste. Renvoie 0 si le texte n’est pas trouvé.\",\n    \"LISTS_GET_INDEX_GET\": \"obtenir\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"obtenir et supprimer\",\n    \"LISTS_GET_INDEX_REMOVE\": \"supprimer\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# depuis la fin\",\n    \"LISTS_GET_INDEX_FIRST\": \"premier\",\n    \"LISTS_GET_INDEX_LAST\": \"dernier\",\n    \"LISTS_GET_INDEX_RANDOM\": \"aléatoire\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Renvoie l’élément à la position indiquée dans une liste. #1 est le premier élément.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Renvoie l’élément à la position indiquée dans une liste. #1 est le dernier élément.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Renvoie le premier élément dans une liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Renvoie le dernier élément dans une liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Renvoie un élément au hasard dans une liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Supprime et renvoie l’élément à la position indiquée dans une liste. #1 est le premier élément.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Supprime et renvoie l’élément à la position indiquée dans une liste. #1 est le dernier élément.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Supprime et renvoie le premier élément dans une liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Supprime et renvoie le dernier élément dans une liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Supprime et renvoie un élément au hasard dans une liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Supprime l’élément à la position indiquée dans une liste. #1 est le premier élément.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Supprime l’élément à la position indiquée dans une liste. #1 est le dernier élément.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Supprime le premier élément dans une liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Supprime le dernier élément dans une liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Supprime un élément au hasard dans une liste.\",\n    \"LISTS_SET_INDEX_SET\": \"mettre\",\n    \"LISTS_SET_INDEX_INSERT\": \"insérer en\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"comme\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Fixe l’élément à la position indiquée dans une liste. #1 est le premier élément.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Fixe l’élément à la position indiquée dans une liste. #1 est le dernier élément.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Fixe le premier élément dans une liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Fixe le dernier élément dans une liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Fixe un élément au hasard dans une liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Insère l’élément à la position indiquée dans une liste. #1 est le premier élément.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Insère l’élément à la position indiquée dans une liste. #1 est le dernier élément.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Insère l’élément au début d’une liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Ajouter l’élément à la fin d’une liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Insère l’élément au hasard dans une liste.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"obtenir la sous-liste depuis #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"obtenir la sous-liste depuis # depuis la fin\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"obtenir la sous-liste depuis le début\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"jusqu’à #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"jusqu’à # depuis la fin\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"jusqu’à la fin\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Crée une copie de la partie spécifiée d’une liste.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Renvoie la valeur de cette variable.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Créer 'fixer %1'\",\n    \"VARIABLES_SET_TITLE\": \"fixer\",\n    \"VARIABLES_SET_TAIL\": \"à\",\n    \"VARIABLES_SET_TOOLTIP\": \"Fixe cette variable pour qu’elle soit égale à la valeur de l’entrée.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Créer 'obtenir %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"à\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"faire quelque chose\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"avec :\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Crée une fonction sans sortie.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"retour\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Crée une fonction avec une sortie.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Attention : Cette fonction a des paramètres dupliqués.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Exécuter la fonction '%1' définie par l’utilisateur.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Exécuter la fonction '%1' définie par l’utilisateur et utiliser son résultat.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"entrées\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nom de l’entrée :\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Surligner la définition de la fonction\",\n    \"PROCEDURES_CREATE_DO\": \"Créer '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Si une valeur est vraie, alors renvoyer une seconde valeur.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Attention : Ce bloc pourrait n’être utilisé que dans une définition de fonction.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/he.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Dorongol\",\n            \"YaronSh\",\n            \"Amire80\",\n            \"Inkbug\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"פריט\",\n    \"DUPLICATE_BLOCK\": \"שכפל\",\n    \"ADD_COMMENT\": \"הוסף תגובה\",\n    \"REMOVE_COMMENT\": \"הסר הערה\",\n    \"EXTERNAL_INPUTS\": \"קלטים חיצוניים\",\n    \"INLINE_INPUTS\": \"קלטים פנימיים\",\n    \"DELETE_BLOCK\": \"מחק קטע קוד\",\n    \"DELETE_X_BLOCKS\": \"מחק %1 קטעי קוד\",\n    \"COLLAPSE_BLOCK\": \"צמצם קטע קוד\",\n    \"COLLAPSE_ALL\": \"צמצם קטעי קוד\",\n    \"EXPAND_BLOCK\": \"הרחב קטע קוד\",\n    \"EXPAND_ALL\": \"הרחב קטעי קוד\",\n    \"DISABLE_BLOCK\": \"נטרל קטע קוד\",\n    \"ENABLE_BLOCK\": \"הפעל קטע קוד\",\n    \"HELP\": \"עזרה\",\n    \"CHANGE_VALUE_TITLE\": \"שנה ערך:\",\n    \"NEW_VARIABLE\": \"משתנה חדש...\",\n    \"NEW_VARIABLE_TITLE\": \"שם המשתנה החדש:\",\n    \"RENAME_VARIABLE\": \"שנה את שם המשתנה...\",\n    \"RENAME_VARIABLE_TITLE\": \"שנה את שם כל '%1' המשתנים ל:\",\n    \"COLOUR_PICKER_HELPURL\": \"http://he.wikipedia.org/wiki/%D7%A6%D7%91%D7%A2\",\n    \"COLOUR_PICKER_TOOLTIP\": \"בחר צבע מן הצבעים.\",\n    \"COLOUR_RANDOM_TITLE\": \"צבע אקראי\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"בחר צבא אקראי.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"צבע עם\",\n    \"COLOUR_RGB_RED\": \"אדום\",\n    \"COLOUR_RGB_GREEN\": \"ירוק\",\n    \"COLOUR_RGB_BLUE\": \"כחול\",\n    \"COLOUR_RGB_TOOLTIP\": \"צור צבע עם הסכום המצוין של אדום, ירוק וכחול. כל הערכים חייבים להיות בין 0 ל100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"ערבב\",\n    \"COLOUR_BLEND_COLOUR1\": \"צבע 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"צבע 2\",\n    \"COLOUR_BLEND_RATIO\": \"יחס\",\n    \"COLOUR_BLEND_TOOLTIP\": \"מערבב שני צבעים יחד עם יחס נתון(0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"http://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"חזור על הפעולה %1 פעמים\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"חזור\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"פעמים\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"תעשה\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"תעשה כמה פעולות מספר פעמים.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"חזור כל עוד\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"חזור עד ש...\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"בזמן שהערך שווה לשגוי, תעשה מספר חישובים.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"בזמן שהערך שווה לשגוי, תעשה מספר חישובים.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"תספור עם\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"מ- %1 ל- %2 עד- %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"לכל פריט\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"ברשימה\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"הגדר את המשתנה '%1' לכל פריט ברשימה, ולאחר מכן בצע כמה חישובים.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"צא מהלולאה\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"המשך עם האיטרציה הבאה של הלולאה\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"צא אל מחוץ ללולאה הכוללת.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"דלג על שאר הלולאה והמשך עם האיטרציה הבאה.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"אזהרה: בלוק זה עשוי לשמש רק בתוך לולאה.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"אם ערך נכון, בצע מספר חישובים.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"אם הערך נכון, אז תבצע את הבלוק הראשון של הצהרות. אחרת, בצע את הבלוק השני של הצהרות.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"אם הערך הראשון שווה לנכון, אז בצע את הבלוק הראשון של הצהרות. אחרת, אם הערך השני נכון, בצע את הבלוק השני של הצהרות.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"אם הערך הראשון נכון, אז תבצע את הבלוק הראשון של הצהרות. אחרת, אם הערך השני נכון, בצע את הבלוק השני של הצהרות. אם אף אחד מהם לא נכון, בצע את הבלוק האחרון של הצהרות.\",\n    \"CONTROLS_IF_MSG_IF\": \"אם\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"אחרת אם\",\n    \"CONTROLS_IF_MSG_ELSE\": \"אחרת\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"תוסיף, תמחק, או תסדר מחדש כדי להגדיר מחדש את הבלוק If.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"תוסיף תנאי לבלוק If.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"לסיום, כל התנאים תקפים לגבי בלוק If.\",\n    \"LOGIC_COMPARE_HELPURL\": \"http://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"תחזיר נכון אם שני הקלטים שווים אחד לשני.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"תחזיר אמת אם שני הקלטים אינם שווים זה לזה.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"תחזיר אמת (true) אם הקלט הראשון הוא קטן יותר מאשר הקלט השני.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"תחזיר אמת אם הקלט הראשון הוא קטן יותר או שווה לקלט השני.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"תחזיר נכון אם הקלט הראשון גדול יותר מהקלט השני.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"תחזיר נכון אם הקלט הראשון גדול יותר או שווה לכניסה השנייה.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"תחזיר נכון אם שני הקלטים נכונים.\",\n    \"LOGIC_OPERATION_AND\": \"ו\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"תחזיר נכון אם מתקיים לפחות אחד מהקלטים נכונים.\",\n    \"LOGIC_OPERATION_OR\": \"או\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"לא %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Returns true if the input is false.  Returns false if the input is true.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"נכון\",\n    \"LOGIC_BOOLEAN_FALSE\": \"שגוי\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"תחזיר אם נכון או אם שגוי.\",\n    \"LOGIC_NULL_HELPURL\": \"http://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"תחזיר ריק.\",\n    \"LOGIC_TERNARY_HELPURL\": \"http://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"בדיקה\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"אם נכון\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"אם שגוי\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"בדוק את התנאי ב'מבחן'. אם התנאי נכון, תחזיר את הערך 'אם נכון'; אחרת תחזיר את הערך 'אם שגוי'.\",\n    \"MATH_NUMBER_HELPURL\": \"http://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"מספר.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"http://he.wikipedia.org/wiki/%D7%90%D7%A8%D7%99%D7%AA%D7%9E%D7%98%D7%99%D7%A7%D7%94\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"תחזיר את סכום שני המספרים.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Return the difference of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Return the product of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Return the quotient of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Return the first number raised to the power of the second number.\",\n    \"MATH_SINGLE_HELPURL\": \"http://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"square root\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Return the square root of a number.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"ערך מוחלט\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Return the absolute value of a number.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Return the negation of a number.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Return the natural logarithm of a number.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Return the base 10 logarithm of a number.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Return e to the power of a number.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Return 10 to the power of a number.\",\n    \"MATH_TRIG_HELPURL\": \"http://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Return the sine of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Return the cosine of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Return the tangent of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Return the arcsine of a number.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Return the arccosine of a number.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Return the arctangent of a number.\",\n    \"MATH_CONSTANT_HELPURL\": \"http://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"זוגי\",\n    \"MATH_IS_ODD\": \"אי-זוגי\",\n    \"MATH_IS_PRIME\": \"ראשוני\",\n    \"MATH_IS_WHOLE\": \"שלם\",\n    \"MATH_IS_POSITIVE\": \"חיובי\",\n    \"MATH_IS_NEGATIVE\": \"שלילי\",\n    \"MATH_IS_DIVISIBLE_BY\": \"מתחלק ב\",\n    \"MATH_IS_TOOLTIP\": \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\",\n    \"MATH_CHANGE_HELPURL\": \"http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"שנה\",\n    \"MATH_CHANGE_INPUT_BY\": \"by\",\n    \"MATH_CHANGE_TOOLTIP\": \"הוסף מספר למשתנה '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"http://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Round a number up or down.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"עיגול\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"עיגול למעלה\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"עיגול למטה\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"סכום של רשימה\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Return the sum of all the numbers in the list.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"מינימום של רשימה\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"תחזיר את המספר הקטן ביותר ברשימה.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"מקסימום של רשימה\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"תחזיר את המספר הגדול ביותר ברשימה.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"ממוצע של רשימה\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Return the average (arithmetic mean) of the numeric values in the list.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"median of list\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"תחזיר את המספר החיצוני ביותר ברשימה.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"modes of list\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Return a list of the most common item(s) in the list.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"standard deviation of list\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Return the standard deviation of the list.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"פריט אקראי מרשימה\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"תחזיר רכיב אקראי מרשימה.\",\n    \"MATH_MODULO_HELPURL\": \"http://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"שארית החילוק %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"החזרת השארית מחלוקת שני המספרים.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"constrain %1 low %2 high %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Constrain a number to be between the specified limits (inclusive).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"http://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"random integer from %1 to %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Return a random integer between the two specified limits, inclusive.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"http://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"random fraction\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\",\n    \"TEXT_TEXT_HELPURL\": \"http://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"A letter, word, or line of text.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"create text with\",\n    \"TEXT_JOIN_TOOLTIP\": \"Create a piece of text by joining together any number of items.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"join\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Add, remove, or reorder sections to reconfigure this text block.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Add an item to the text.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"to\",\n    \"TEXT_APPEND_APPENDTEXT\": \"append text\",\n    \"TEXT_APPEND_TOOLTIP\": \"Append some text to variable '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"length of %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Returns the number of letters (including spaces) in the provided text.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 is empty\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Returns true if the provided text is empty.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"in text\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"find first occurrence of text\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"find last occurrence of text\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"in text\",\n    \"TEXT_CHARAT_FROM_START\": \"get letter #\",\n    \"TEXT_CHARAT_FROM_END\": \"get letter # from end\",\n    \"TEXT_CHARAT_FIRST\": \"get first letter\",\n    \"TEXT_CHARAT_LAST\": \"get last letter\",\n    \"TEXT_CHARAT_RANDOM\": \"get random letter\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Returns the letter at the specified position.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Returns a specified portion of the text.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"in text\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"get substring from letter #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"get substring from letter # from end\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"get substring from first letter\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"to letter #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"to letter # from end\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"to last letter\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Return a copy of the text in a different case.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"to UPPER CASE\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"to lower case\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"to Title Case\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Return a copy of the text with spaces removed from one or both ends.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"למחוק רווחים משני הקצוות\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"למחוק רווחים מימין\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"למחוק רווחים משמאל\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"print %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Print the specified text, number or other value.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"prompt for text with message\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"prompt for number with message\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Prompt for user for a number.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Prompt for user for some text.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"צור רשימה ריקה\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"החזר רשימה,באורך 0, המכילה רשומות נתונים\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"צור רשימה עם כל מספר של פריטים.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"צור רשימה עם\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"רשימה\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"תוסיף, תמחק, או תסדר מחדש כדי להגדיר מחדש את הבלוק If.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"הוסף פריט לרשימה.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"יוצר רשימה המורכבת מהערך נתון חוזר מספר פעמים שצוין.\",\n    \"LISTS_REPEAT_TITLE\": \"ליצור רשימה עם הפריט %1 %2 פעמים\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"אורכו של %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"מחזירה את האורך של רשימה.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 הוא ריק\",\n    \"LISTS_TOOLTIP\": \"מחזיר אמת אם הרשימה ריקה.\",\n    \"LISTS_INLIST\": \"ברשימה\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"מחזירה את המיקום הראשון של פריט ברשימה\",\n    \"LISTS_INDEX_OF_LAST\": \"מחזירה את המיקום האחרון של פריט ברשימה\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"מחזירה את האינדקס של המופע ראשון/אחרון של הפריט ברשימה.  מחזירה 0 אם טקסט אינו נמצא.\",\n    \"LISTS_GET_INDEX_GET\": \"לקבל\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"קבל ומחק\",\n    \"LISTS_GET_INDEX_REMOVE\": \"הסרה\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# מהסוף\",\n    \"LISTS_GET_INDEX_FIRST\": \"ראשון\",\n    \"LISTS_GET_INDEX_LAST\": \"אחרון\",\n    \"LISTS_GET_INDEX_RANDOM\": \"אקראי\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"מחזיר פריט במיקום שצוין ברשימה. #1 הוא הפריט הראשון.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"מחזיר פריט במיקום שצוין ברשימה. #1 הוא הפריט האחרון.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"מחזיר את הפריט הראשון ברשימה.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"מחזיר את הפריט האחרון ברשימה.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"מחזיר פריט אקראי מהרשימה.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"מסיר ומחזיר את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט הראשון.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"מסיר ומחזיר את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט האחרון.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"מסיר ומחזיר את הפריט הראשון ברשימה.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"מסיר ומחזיר את הפריט האחרון ברשימה.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"מחק והחזר פריט אקראי מהרשימה.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"מחזיר פריט במיקום שצוין ברשימה. #1 הוא הפריט הראשון.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"מחזיר פריט במיקום שצוין ברשימה. #1 הוא הפריט האחרון.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"הסר את הפריט הראשון ברשימה.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"הסר את הפריט הראשון ברשימה.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"הסר פריט אקראי ברשימה.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"הגדר\",\n    \"LISTS_SET_INDEX_INSERT\": \"הכנס ב\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"כמו\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"מגדיר את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט הראשון.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"מגדיר את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט האחרון.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"מגדיר את הפריט הראשון ברשימה.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"מגדיר את הפריט האחרון ברשימה.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"מגדיר פריט אקראי ברשימה.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"מכניס את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט הראשון.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"מכניס את הפריט במיקום שצוין ברשימה.  #1 הוא הפריט האחרון.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"מכניס את הפריט בתחילת רשימה.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"מוסיף את הפריט בסוף רשימה.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"הוסף פריט באופן אקראי ברשימה.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"מחזירה חלק מהרשימה החל מ-#\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"מחזירה חלק מהרשימה החל מ-# עד הסוף\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"get sub-list from first\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"ל #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"ל # מהסוף\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"לאחרון\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"יוצרת עותק של חלק מסוים מהרשימה.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Returns the value of this variable.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Create 'set %1'\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"set\",\n    \"VARIABLES_SET_TAIL\": \"to\",\n    \"VARIABLES_SET_TOOLTIP\": \"Sets this variable to be equal to the input.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Create 'get %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"to\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"do something\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"with:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Creates a function with no output.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"return\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Creates a function with an output.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Warning: This function has duplicate parameters.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Run the user-defined function '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Run the user-defined function '%1' and use its output.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"מקורות קלט\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"שם הקלט:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Highlight function definition\",\n    \"PROCEDURES_CREATE_DO\": \"Create '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"If a value is true, then return a second value.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Warning: This block may be used only within a function definition.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/hi.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Bl707\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"आइटम\",\n    \"DUPLICATE_BLOCK\": \"कॉपी करें\",\n    \"ADD_COMMENT\": \"टिप्पणी छोड़ें\",\n    \"REMOVE_COMMENT\": \"टिप्पणी हटायें\",\n    \"EXTERNAL_INPUTS\": \"बाहरी इनपुट\",\n    \"INLINE_INPUTS\": \"इनलाइन इनपुट\",\n    \"DELETE_BLOCK\": \"ब्लॉक हटाएँ\",\n    \"DELETE_X_BLOCKS\": \"%1 ब्लॉक हटाएँ\",\n    \"COLLAPSE_BLOCK\": \"ब्लॉक को संक्षिप्त करें\",\n    \"COLLAPSE_ALL\": \"ब्लॉक संक्षिप्त करें\",\n    \"EXPAND_BLOCK\": \"ब्लॉक का विस्तार करें\",\n    \"EXPAND_ALL\": \"ब्लॉक विस्तार करें\",\n    \"DISABLE_BLOCK\": \"ब्लॉक को अक्षम करें\",\n    \"ENABLE_BLOCK\": \"ब्लॉक को सक्षम करें\",\n    \"HELP\": \"सहायता\",\n    \"CHANGE_VALUE_TITLE\": \"मान परिवर्तित करें:\",\n    \"NEW_VARIABLE\": \"नया चर...\",\n    \"NEW_VARIABLE_TITLE\": \"नए चर का नाम:\",\n    \"RENAME_VARIABLE\": \"चर का नाम बदलें...\",\n    \"RENAME_VARIABLE_TITLE\": \"सभी '%1' चरों के नाम बदलें:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"पैलेट से एक रंग चुनें।\",\n    \"COLOUR_RANDOM_TITLE\": \"रैन्डम रंग\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"रैन्डम्ली एक रंग चयन करें।\",\n    \"COLOUR_RGB_TITLE\": \"इसके साथ रंग करें\",\n    \"COLOUR_RGB_RED\": \"लाल\",\n    \"COLOUR_RGB_GREEN\": \"हरा\",\n    \"COLOUR_RGB_BLUE\": \"नीला\",\n    \"COLOUR_BLEND_TITLE\": \"मिश्रण करें\",\n    \"COLOUR_BLEND_COLOUR1\": \"रंग 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"रंग 2\",\n    \"COLOUR_BLEND_RATIO\": \"अनुपात\",\n    \"COLOUR_BLEND_TOOLTIP\": \"दिए गए अनुपात (0.0 - 1.0) के साथ दो रंगों का मिश्रण करता है।\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"%1 बार दोहराएँ\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"दोहराएँ\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"इतनी बार\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"डू\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"कुछ स्टेट्मन्ट कई बार चलाएँ।\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"दोहराएँ जब कि\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"दोहराएँ जब तक\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"जब तक मान ट्रू है, तब तक कुछ स्टेट्मेंट्स चलाएँ।\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"जब तक मान फॉल्स है, तब तक कुछ स्टेट्मेंट्स चलाएँ।\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"काउंट करें\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"प्रत्येक आइटम के लिए\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"सूची में\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"लूप से बाहर निकलें\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"लूप का अगला आईटरेशन जारी रखें\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"भीतरी लूप से बाहर निकलें।\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"बाकी बचे लूप को छोड़ें, और अगला आईटरेशन जारी रखें।\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"सावधान: ये ब्लॉक केवल लूप के अंदर इस्तेमाल किया जा सकता है।\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"यदी मान ट्रू है, तो कुछ स्टेट्मेंट्स चलाएँ।\",\n    \"CONTROLS_IF_MSG_IF\": \"इफ\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"एल्स इफ\",\n    \"CONTROLS_IF_MSG_ELSE\": \"एल्स\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"यदि ब्लॉक मे एक शर्त जोड़ें।\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"ट्रू रिटर्न करें यदि दोनो इनपुट इक दूसरे के बराबर हों।\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"ट्रू रिटर्न करें यदि दोनो इनपुट इक दूसरे के बराबर नहीं हों।\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से छोटा हो।\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से छोटा हो या बराबर हो।\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से बड़ा हो।\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से बड़ा हो या बराबर हो।\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"ट्रू रिटर्न करें यदि दोनो इनपुट ट्रू हों।\",\n    \"LOGIC_OPERATION_AND\": \"AND (तथा)\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"ट्रू रिटर्न करें यदि दोनो मे से इक इनपुट ट्रू हो।\",\n    \"LOGIC_OPERATION_OR\": \"OR (अथवा)\",\n    \"LOGIC_NEGATE_TITLE\": \"NOT (पूरक) %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"ट्रू रिटर्न करता है यदि इनपुट फॉल्स है। फॉल्स रिटर्न करता है यदि इनपुट ट्रू है।\",\n    \"LOGIC_BOOLEAN_TRUE\": \"ट्रू\",\n    \"LOGIC_BOOLEAN_FALSE\": \"फॉल्स\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"ट्रू या फॉल्स रिटर्न करता है।\",\n    \"LOGIC_NULL\": \"NULL (अमान्य)\",\n    \"LOGIC_NULL_TOOLTIP\": \"null (अमान्य) रिटर्न करता है।\",\n    \"LOGIC_TERNARY_CONDITION\": \"टेस्ट\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"यदि ट्रू है\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"यदि फॉल्स है\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"एक संख्या।\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"दो संख्याओं का योग रिटर्न करें।\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"दो संख्याओं का अंतर रिटर्न करें।\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"दो संख्याओं का गुणन रिटर्न करें।\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"दो संख्याओं का भागफल रिटर्न करें।\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"वर्गमूल\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"संख्या का वर्गमूल रिटर्न करें।\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"परम\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"संख्या का परम मान रिटर्न करें।\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"संख्या का निषेध मान रिटर्न करें।\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"संख्या का प्राकृतिक लघुगणक रिटर्न करें।\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"संख्या का मूल 10 लघुगणक रिटर्न करें।\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"डिग्री का साइन रिटर्न करें (रेडियन नही)\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"डिग्री का कोसाइन रिटर्न करें (रेडियन नही)\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"डिग्री का टैन्जन्ट रिटर्न करें (रेडियन नही)\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"संख्या का आर्कसाइन रिटर्न करें।\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"संख्या का आर्ककोसाइन रिटर्न करें।\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"संख्या का आर्कटैन्जन्ट रिटर्न करें।\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_IS_EVEN\": \"सम है\",\n    \"MATH_IS_ODD\": \"विषम है\",\n    \"MATH_IS_PRIME\": \"अभाज्य है\",\n    \"MATH_IS_WHOLE\": \"पूर्णांक है\",\n    \"MATH_IS_POSITIVE\": \"धनात्मक है\",\n    \"MATH_IS_NEGATIVE\": \"ऋणात्मक है\",\n    \"MATH_IS_DIVISIBLE_BY\": \"इसके द्वारा विभाज्य है\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"बदलें\",\n    \"MATH_CHANGE_TOOLTIP\": \"संख्या को चर '%1' से जोड़ें।\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"संख्या को बड़ा या घटा के पूर्णांक बनाएँ।\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"पूर्णांक बनाएँ\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"बड़ा के पूर्णांक बनाएँ\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"घटा के पूर्णांक बनाएँ\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"सूची का योग\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"सूची की सभी संख्याओं का योग रिटर्न करें।\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"सूची मे न्यूनतम\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"सूची मे सबसे छोटी संख्या रिटर्न करें।\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"सूची मे अधिकतम\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"सूची मे सबसे बड़ी संख्या रिटर्न करें।\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"सूची का औसत मान\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"सूची की माध्यिका\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"सूची की माध्यिका संख्या रिटर्न करें।\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"सूची का मोड\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"सूची मे सबसे आम आइटम(s) की सूची रिटर्न करें।\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"सूची का मानक विचलन\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"सूची का मानक विचलन रिटर्न करें।\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"सूची का रैन्डम आइटम\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"सूची से एक रैन्डम आइटम रिटर्न करें।\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"%1 ÷ %2 का शेषफल\",\n    \"MATH_MODULO_TOOLTIP\": \"दो संख्याओं के भाग का शेषफल रिटर्न करें।\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"%1 से % 2 तक रैन्डम पूर्णांक\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"रैन्डम अंश\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"एक अक्षर, शब्द, या टेक्स्ट की पंक्ति।\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"इसके साथ टेक्स्ट बनाएँ\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"जोड़\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"सूची मे एक आइटम जोड़ें।\",\n    \"TEXT_APPEND_TO\": \"इस\",\n    \"TEXT_APPEND_APPENDTEXT\": \"से जोड़ें ये टेक्स्ट\",\n    \"TEXT_APPEND_TOOLTIP\": \"कुछ टेक्स्ट इस चर '%1' से जोड़ें।\",\n    \"TEXT_LENGTH_TITLE\": \"%1 की लंबाई\",\n    \"TEXT_LENGTH_TOOLTIP\": \"दिए गये टेक्स्ट मे अक्षरों की संख्या रिटर्न करता है (खाली स्थान मिला के)।\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 खाली है\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"ट्रू रिटर्न करता है यदि दिया गया टेक्स्ट खाली है।\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"इस टेक्स्ट मे\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"टेक्स्ट पहली बार जहाँ आया है उसे ढूढ़े\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"टेक्स्ट आखरी बार जहाँ आया है उसे ढूढ़े\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"इस टेक्स्ट मे\",\n    \"TEXT_CHARAT_FROM_START\": \"अक्षर # पाएँ\",\n    \"TEXT_CHARAT_FROM_END\": \"आखिर से अक्षर # पाएँ\",\n    \"TEXT_CHARAT_FIRST\": \"पहला अक्षर पाएँ\",\n    \"TEXT_CHARAT_LAST\": \"आखरी अक्षर पाएँ\",\n    \"TEXT_CHARAT_RANDOM\": \"रैन्डम अक्षर पाएँ\",\n    \"TEXT_CHARAT_TOOLTIP\": \"बताई गयी जगह से अक्षर रिटर्न करता है\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"टेक्स्ट का बताया गया अंश रिटर्न करता है\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"इस टेक्स्ट मे\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"अक्षर # से सबस्ट्रिंग पाएँ\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"आखरी अक्षर # से सबस्ट्रिंग पाएँ\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"पहले अक्षर से सबस्ट्रिंग पाएँ\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"यहाँ तक अक्षर #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"आखिर से यहाँ तक अक्षर #\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"यहाँ तक आखरी अक्षर\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"टेक्स्ट की कॉपी भिन्न केस (अक्षर से संबंधित) मे रिटर्न करें।\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"बड़े अक्षर मे\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"छोटे अक्षर मे\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"टाइटल केस मे\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"रिक्त स्थान को इस टेक्स्ट के दोनों तरफ से निकालें\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"रिक्त स्थान को इस टेक्स्ट के बायें तरफ से निकालें\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"रिक्त स्थान को इस टेक्स्ट के दाईं तरफ से निकालें\",\n    \"TEXT_PRINT_TITLE\": \"प्रिंट करें %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"दिया गया टेक्स्ट प्रिंट करें, संख्या या अन्य मान।\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"सूचना के साथ टेक्स्ट के लिए प्रॉम्प्ट करें\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"सूचना के साथ संख्या के लिए प्रॉम्प्ट करें\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"यूज़र से संख्या के लिए प्रॉम्प्ट करें।\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"यूज़र से कुछ टेक्स्ट के लिए प्रॉम्प्ट करें।\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"खाली सूची बनाएँ\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"कितने भी आइटम वाली एक सूची बनाएँ।\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"इसके सूची बनाएँ\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"सूची\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"सूची मे एक आइटम जोड़ें।\",\n    \"LISTS_LENGTH_TITLE\": \"%1 की लंबाई\",\n    \"LISTS_LENGTH_TOOLTIP\": \"सूची की लंबाई रिटर्न करता है।\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 खाली है\",\n    \"LISTS_TOOLTIP\": \"यदि सूची खाली है तो ट्रू रिटर्न करता है।\",\n    \"LISTS_INLIST\": \"सूची में\",\n    \"LISTS_INDEX_OF_FIRST\": \"आइटम पहली बार जहाँ आया है उसे ढूढ़े\",\n    \"LISTS_INDEX_OF_LAST\": \"आइटम आखरी बार जहाँ आया है उसे ढूढ़े\",\n    \"LISTS_GET_INDEX_REMOVE\": \"निकालें\",\n    \"LISTS_GET_INDEX_FROM_END\": \"अंत से #\",\n    \"LISTS_GET_INDEX_FIRST\": \"पहला\",\n    \"LISTS_GET_INDEX_LAST\": \"आखिरी\",\n    \"LISTS_GET_INDEX_RANDOM\": \"रैन्डम\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"सूची का पहला आइटम रिटर्न करता है।\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"सूची का आखरी आइटम रिटर्न करता है।\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"सूची से रैन्डम आइटम रिटर्न करता है।\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"सूची का पहला आइटम निकालता है और रिटर्न करता है।\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"सूची का आखरी आइटम निकालता है और रिटर्न करता है।\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"सूची से रैन्डम आइटम निकालता है और रिटर्न करता है।\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"सूची का पहला आइटम निकालता है।\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"सूची का आखरी आइटम निकालता है।\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"सूची से रैन्डम आइटम निकालता है।\",\n    \"LISTS_SET_INDEX_SET\": \"सैट करें\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"सूची मे बताए गये स्थान में आइटम सैट करता है। #1 पहला आइटम है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"सूची मे बताए गये स्थान में आइटम सैट करता है। #1 आखरी आइटम है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"सूची में पहला आइटम सैट करता है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"सूची में आखरी आइटम सैट करता है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"सूची में रैन्डम आइटम सैट करता है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"सूची मे बताए गये स्थान में आइटम इनसर्ट करता है। #1 पहला आइटम है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"सूची मे बताए गये स्थान में आइटम इनसर्ट करता है। #1 आखरी आइटम है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"आइटम को सूची के शुरू में इनसर्ट करता है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"आइटम को सूची के अंत में जोड़ता है।\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"आइटम को सूची में रैन्डम्ली इनसर्ट करता है।\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"सूची के बताए गये भाग की कॉपी बनता है।\",\n    \"VARIABLES_GET_TOOLTIP\": \"इस चर का मान रिटर्न करता है।\",\n    \"VARIABLES_GET_CREATE_SET\": \"सेट '%1' बनाएँ\",\n    \"VARIABLES_SET_TITLE\": \"सेट करें\",\n    \"VARIABLES_SET_TAIL\": \"को\",\n    \"VARIABLES_SET_TOOLTIP\": \"इस चर को इनपुट के बराबर सेट करता है।\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"कुछ करें\",\n    \"PROCEDURES_BEFORE_PARAMS\": \": के साथ\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"बिना आउटपुट वाला एक फ़ंक्शन बनाता है।\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"रिटर्न\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"आउटपुट वाला एक फ़ंक्शन बनाता है।\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"सावधान: इस फ़ंक्शन मे डुप्लिकेट पैरामीटर हैं।\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"यूज़र द्वारा वर्णन किया गया फ़ंक्शन '%1' चलाएँ।\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"यूज़र द्वारा वर्णन किया गया फ़ंक्शन '%1' चलाएँ और उसका आउटपुट इस्तेमाल करें।\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"इनपुट\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"इनपुट का नाम:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"फ़ंक्शन परिभाषा को हाइलाइट करें\",\n    \"PROCEDURES_CREATE_DO\": \"'%1' बनाएँ\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"यदि एक मान ट्रू है तो, दूसरा मान रिटर्न करें।\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"सावधान: ये ब्लॉक फ़ंक्शन परिभाषा के अंदर ही इस्तेमाल किया जा सकता।\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/hu.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Espertus\",\n            \"Takács Viktor László\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"változó\",\n    \"DUPLICATE_BLOCK\": \"Másolat\",\n    \"ADD_COMMENT\": \"Megjegyzés hozzáadása\",\n    \"REMOVE_COMMENT\": \"Megjegyzés tölése\",\n    \"EXTERNAL_INPUTS\": \"Külső kapcsolatok\",\n    \"INLINE_INPUTS\": \"Belső kapcsolatok\",\n    \"DELETE_BLOCK\": \"Töröl\",\n    \"DELETE_X_BLOCKS\": \"%1 blokk törlése\",\n    \"COLLAPSE_BLOCK\": \"Összezár\",\n    \"COLLAPSE_ALL\": \"Összezár\",\n    \"EXPAND_BLOCK\": \"Kibont\",\n    \"EXPAND_ALL\": \"Kinyit\",\n    \"DISABLE_BLOCK\": \"Letilt\",\n    \"ENABLE_BLOCK\": \"Engedélyez\",\n    \"HELP\": \"Sugó\",\n    \"CHANGE_VALUE_TITLE\": \"Érték módosítása:\",\n    \"NEW_VARIABLE\": \"Új...\",\n    \"NEW_VARIABLE_TITLE\": \"Az új változó neve:\",\n    \"RENAME_VARIABLE\": \"Átnevezés...\",\n    \"RENAME_VARIABLE_TITLE\": \"\\\"%1\\\" változó átnevezése:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://hu.wikipedia.org/wiki/Szín\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Válassz színt a palettáról.\",\n    \"COLOUR_RANDOM_TITLE\": \"Véletlen szín\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Véletlenszerűen kiválasztott szín.\",\n    \"COLOUR_RGB_TITLE\": \"Szín\",\n    \"COLOUR_RGB_RED\": \"vörös\",\n    \"COLOUR_RGB_GREEN\": \"zöld\",\n    \"COLOUR_RGB_BLUE\": \"kék\",\n    \"COLOUR_RGB_TOOLTIP\": \"Szín előállítása a megadott vörös, zöld, és kék értékekkel.  Minden értéknek 0 és 100 közé kell esnie.\",\n    \"COLOUR_BLEND_TITLE\": \"Színkeverés\",\n    \"COLOUR_BLEND_COLOUR1\": \"\",\n    \"COLOUR_BLEND_COLOUR2\": \"+\",\n    \"COLOUR_BLEND_RATIO\": \"arány:\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Két színt kever össze a megadott arányban (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Sz.C3.A1ml.C3.A1l.C3.B3s_.28FOR.29_ciklus\",\n    \"CONTROLS_REPEAT_TITLE\": \"Ismételd %1 alkalommal\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"Ismételd\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"alkalommal\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Megadott kódrészlet ismételt végrehajtása.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"ismételd amíg igazː\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"amíg nem\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Amíg a feltétel igaz, végrehajtja az utasításokat.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Amíg a feltétel hamis, végrehajtja az utasításokat.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Véges lépésszámú ciklus.  A \\\"%1\\\" változó értékét számolja ki a kezdőérték és a végérték között.  Minden lépésben végrehajtódnak az utasítások.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"Számold ki\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"értékét %1 és %2 között, lépésköz: %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Iter.C3.A1l.C3.B3_ciklus\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"Minden\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"elemre a\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"listában\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"A lista elemszámának megfelelő lépésszámú ciklus.  A \\\"%1\\\" változó minden lépésben megkapja a lista adott elemének értékét.  Minden lépésben végrehajtódnak az utasítások.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"befejezi az ismétlést\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"folytatja a következővel\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Megszakítja végtelen ciklust.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Megszakítja az aktuális futást és folytatja elölről.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Figyelem: Ez a blokk, csak egy ciklusban használható.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Ha a kifejezés igaz, akkor végrehajtjuk az utasításokat.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Ha a kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot.  Különben a második utasítás blokk kerül végrehajtásra.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Ha az első kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot.  Ha a második kifejezés igaz, akkor végrehajtjuk a második utasítás blokkot.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Ha az első kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot.  Ha a második kifejezés igaz, akkor végrehajtjuk a második utasítás blokkot.  Amennyiben egyik kifejezés sem igaz, akkor az utolsó utasítás blokk kerül végrehajtásra.\",\n    \"CONTROLS_IF_MSG_IF\": \"Ha\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"ha\",\n    \"CONTROLS_IF_MSG_ELSE\": \"különben\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"A feltételes elágazás (ha) blokk testreszabásához bővítsd, töröld vagy rendezd át a részeit.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Újabb feltételes elágazás.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Végső, 'egyébként' feltételt ad a 'ha' blokkhoz.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://hu.wikipedia.org/wiki/Egyenl%C5%91tlens%C3%A9g\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Igaz, ha a kifejezés két oldala egyenlő.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Igaz, ha a kifejezés két oldala nem egyenlő..\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Igaz, ha a bal oldali kifejezés kisebb, mint a jobb oldali.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Igaz, ha a bal oldali kifejezés kisebb vagy egyenlő, mint a jobb oldali.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Igaz, ha a bal oldali kifejezés nagyobb, mint a jobb oldali.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Igaz, ha a bal oldali kifejezés nagyobb vagy egyenlő, mint a jobb oldali.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Igaz, ha mindkét kifejezés igaz.\",\n    \"LOGIC_OPERATION_AND\": \"és\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Igaz, ha bármelyik kifejezés igaz.\",\n    \"LOGIC_OPERATION_OR\": \"vagy\",\n    \"LOGIC_NEGATE_TITLE\": \"nem %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Igaz, ha a kifejezés hamis.  Hamis, ha a kifejezés igaz.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"igaz\",\n    \"LOGIC_BOOLEAN_FALSE\": \"hamis\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Igaz, vagy Hamis érték\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"null érték.\",\n    \"LOGIC_TERNARY_CONDITION\": \"kifejezés:\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"érték, ha igaz:\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"érték, ha hamis:\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Kiértékeli a kifejezést.  Ha a kifejezés igaz visszatér az \\\"érték, ha igaz\\\" értékkel, különben az \\\"érték, ha hamis\\\" értékkel.\",\n    \"MATH_NUMBER_HELPURL\": \"https://hu.wikipedia.org/wiki/Sz%C3%A1m\",\n    \"MATH_NUMBER_TOOLTIP\": \"Egy szám.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://hu.wikipedia.org/wiki/Matematikai_m%C5%B1velet\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Két szám összege.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Két szám különbsége.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Két szám szorzata.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Két szám hányadosa.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Az első számnak a második számmal megyegyező hatványa.\",\n    \"MATH_SINGLE_HELPURL\": \"https://hu.wikipedia.org/wiki/Gy%C3%B6kvon%C3%A1s\",\n    \"MATH_SINGLE_OP_ROOT\": \"négyzetgyök\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"A szám négyzetgyöke.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"abszolútérték\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"A szám abszolútértéke.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"A szám -1 szerese.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"A szám természetes alapú logaritmusa.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"A szám 10-es alapú logaritmusa.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Az e megadott számú hatványa.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"A 10 megadott számú hatványa.\",\n    \"MATH_TRIG_HELPURL\": \"https://hu.wikipedia.org/wiki/Sz%C3%B6gf%C3%BCggv%C3%A9nyek\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"A fokban megadott szög szinusz értéke.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"A fokban megadott szög koszinusz értéke.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"A fokban megadott szög tangens értéke.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"A fokban megadott szög arkusz szinusz értéke.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"A fokban megadott szög arkusz koszinusz értéke.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"A fokban megadott szög arkusz tangens értéke.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://hu.wikipedia.org/wiki/Matematikai_konstans\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Ismert matematikai konstans: π (3.141…), e (2.718…), φ (1.618…), gyök(2) (1.414…), gyök(½) (0.707…), vagy ∞ (végtelen).\",\n    \"MATH_IS_EVEN\": \"páros szám?\",\n    \"MATH_IS_ODD\": \"páratlan szám?\",\n    \"MATH_IS_PRIME\": \"prímszám?\",\n    \"MATH_IS_WHOLE\": \"egész szám?\",\n    \"MATH_IS_POSITIVE\": \"pozitív szám?\",\n    \"MATH_IS_NEGATIVE\": \"negatív szám?\",\n    \"MATH_IS_DIVISIBLE_BY\": \"osztható ezzel?ː\",\n    \"MATH_IS_TOOLTIP\": \"Megadja a számról, hogy páros, páratlan, prím, egész, pozitív vagy negatív szám, illetve osztható-e a másodikkal.  Igaz, vagy Hamis értéket ad eredményül.\",\n    \"MATH_CHANGE_HELPURL\": \"https://hu.wikipedia.org/wiki/JavaScript#Aritmetikai_oper.C3.A1torok\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"Növeld\",\n    \"MATH_CHANGE_INPUT_BY\": \"értékét, (növekmény)ː\",\n    \"MATH_CHANGE_TOOLTIP\": \"A(z) \\\"%1\\\" változó értékének növelése.\",\n    \"MATH_ROUND_HELPURL\": \"https://hu.wikipedia.org/wiki/Eg%C3%A9szr%C3%A9sz#Kerek.C3.ADt.C3.A9s\",\n    \"MATH_ROUND_TOOLTIP\": \"Kerekítés a következő, vagy megelőző egész számra.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"Kerekítés\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"Kerekítés fel\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"Kerekítés le\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"lista összege\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"A lista elemeinek összegét adja eredményül.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"lista minimuma\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"A lista elemeinek minimumát adja eredményül.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"lista maximuma\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"A lista elemeinek maximumát adja eredményül.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"lista átlaga\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"A lista elemeinek átlagát adja eredményül.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"lista mediánja\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"A lista elemeinek mediánját adja eredményül.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"lista módusza\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"A lista elemeinek móduszát adja eredményül.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"lista szórása\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"A lista elemeinek szórását adja eredményül.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"lista véletlen eleme\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"A lista egy véletlen elemét adja eredményül.\",\n    \"MATH_MODULO_HELPURL\": \"https://hu.wikipedia.org/wiki/Eg%C3%A9szr%C3%A9sz#Als.C3.B3_eg.C3.A9szr.C3.A9sz\",\n    \"MATH_MODULO_TITLE\": \"maradék %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Az egész osztás maradékát adja eredméynül.\",\n    \"MATH_CONSTRAIN_TITLE\": \"korlátozd %1 -t %2 és %3 közé\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Egy változó értékének korlátozása a megadott zárt intervallumra.\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://hu.wikipedia.org/wiki/V%C3%A9letlen\",\n    \"MATH_RANDOM_INT_TITLE\": \"véletlen egész szám %1 között %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Véletlen egész szám a megadott zárt intervallumon belül.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://hu.wikipedia.org/wiki/V%C3%A9letlen\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"véletlen tört\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Véletlen tört érték 0.0 és 1.0 között.\",\n    \"TEXT_TEXT_HELPURL\": \"https://hu.wikipedia.org/wiki/String\",\n    \"TEXT_TEXT_TOOLTIP\": \"Egy betű, szó vagy szöveg egy sora.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"összefűz\",\n    \"TEXT_JOIN_TOOLTIP\": \"Tetszőleges számú szövegrészletet fűz össze egybefüggő szöveggé.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"összefűz\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Összefűzéssel, törléssel vagy rendezéssel kapcsolato sblokkok szöveg szerkesztéséhez.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Elem hozzáfűzése a szöveghez.\",\n    \"TEXT_APPEND_TO\": \"A\",\n    \"TEXT_APPEND_APPENDTEXT\": \"szövegéhez fűzd hozzá\",\n    \"TEXT_APPEND_TOOLTIP\": \"Szöveget fűz a \\\"%1\\\" változó értékéhez.\",\n    \"TEXT_LENGTH_TITLE\": \"hossz %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"A megadott szöveg karaktereinek számát adja eredményül (beleértve a szóközöket).\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 üres sztring?\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Igaz, ha a vizsgált sztring üres.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"A keresett szöveg első vagy utolsó előfordulásával tér vissza.  0 esetén a szövegrészlet nem található.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"A(z)\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"szövegben első előfordulásának indexe\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"szövegben utolsó előfordulásának indexe\",\n    \"TEXT_INDEXOF_TAIL\": \"szövegnek\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"A\",\n    \"TEXT_CHARAT_FROM_START\": \"szövegnek az elejétől számított\",\n    \"TEXT_CHARAT_FROM_END\": \"szövegnek a végétől számított\",\n    \"TEXT_CHARAT_FIRST\": \"szövegnek az első\",\n    \"TEXT_CHARAT_LAST\": \"szövegnek az utolsó\",\n    \"TEXT_CHARAT_RANDOM\": \"szövegnek tetszőleges\",\n    \"TEXT_CHARAT_TAIL\": \"karaktere\",\n    \"TEXT_CHARAT_TOOLTIP\": \"A szöveg egy megadott karakterét adja eredményül.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"A megadott szövegrészletet adja eredményül.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"a\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"szövegben válaszd ki a(z)\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"szövegben válaszd ki a hátulról a(z)\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"szövegben válaszd ki az első\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"betűtől a(z)\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"betűtől a hátulról számított\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"betűtől az utolsó\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"betűig tartó betűsort\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Return a copy of the text in a different case.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"NAGYBETŰS\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"kisbetűs\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"Címként Formázott\",\n    \"TEXT_TRIM_TOOLTIP\": \"Levágja a megadott szöveg végeiről a szóközöket.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"a végekről\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"az elejéről\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"a végéről\",\n    \"TEXT_PRINT_TITLE\": \"Üzenet %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Megejelníti a megadott kaakterláncot üzenetként a képernyőn.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"Kérj be szöveget\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"Kérj be számot\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Számot kér be a felhasználótól.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Szöveget kér be a felhasználótól.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"üres lista\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Elemeket nem tartalmazó üres listát ad eredményül\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Listát készít a megadott elemekből.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"Lista készítés, elemek:\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Add, remove, or reorder sections to reconfigure this list block.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Elem hozzáadása listához.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"A megadtott elem felhasználásával n elemű listát készít\",\n    \"LISTS_REPEAT_TITLE\": \"Lista készítése %1 elemet %2 alkalommal hozzáadva\",\n    \"LISTS_LENGTH_TITLE\": \"%1 lista hossza\",\n    \"LISTS_LENGTH_TOOLTIP\": \"A lista elemszámát adja eredményül.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 üres lista?\",\n    \"LISTS_TOOLTIP\": \"Az eredmény igaz, ha a lista nem tartalmaz elemeket.\",\n    \"LISTS_INLIST\": \"A(z)\",\n    \"LISTS_INDEX_OF_FIRST\": \"listában első előfordulásaː\",\n    \"LISTS_INDEX_OF_LAST\": \"listában utolsó előfordulásaː\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"A megadtott elem eslő vagy utolsó előfordulásával tér vissza.  0 esetén nincs ilyen eleme a listának.\",\n    \"LISTS_GET_INDEX_GET\": \"listából értéke\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"listából kivétele\",\n    \"LISTS_GET_INDEX_REMOVE\": \"listából törlése\",\n    \"LISTS_GET_INDEX_FROM_START\": \"az elejétől számított\",\n    \"LISTS_GET_INDEX_FROM_END\": \"a végétől számított\",\n    \"LISTS_GET_INDEX_FIRST\": \"az első\",\n    \"LISTS_GET_INDEX_LAST\": \"az utolsó\",\n    \"LISTS_GET_INDEX_RANDOM\": \"bármely\",\n    \"LISTS_GET_INDEX_TAIL\": \"elemnek\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"A lista megadott sorszámú elemét adja eredményül.  1 az első elemet jelenti.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"A lista megadott sorszámú elemét adja eredményül.  1 az utolsó elemet jelenti.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"A lista első elemét adja eredményül.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"A lista utolsó elemét adja eredményül.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"A lista véletlenszerűen választott elemét adja eredményül.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"A megadott sorszámú elem kivétele a listából 1 az első elemet jelenti.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"A megadott sorszámú elem kivétele a listából 1 az utolsó elemet jelenti.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Az első elem kivétele a listából.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Az utolsó elem kivétele a listából.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Véletlenszerűen választott elem kivétele a listából.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"A megadott sorszámú elem törlése a listából 1 az első elemet jelenti.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"A megadott sorszámú elem törlése a listából 1 az utolsó elemet jelenti.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Az első elem törlése a listából.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Az utolsó elem törlése a listából.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Véletlenszerűen választott elem törlése a listából.\",\n    \"LISTS_SET_INDEX_SET\": \"listába állítsd be\",\n    \"LISTS_SET_INDEX_INSERT\": \"listába szúrd be\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"elemkéntː\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"A megadott sorszámú elem cseréje a listában.  1 az első elemet jelenti.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"A megadott sorszámú elem cseréje a listában.  1 az utolsó elemet jelenti.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Az első elem cseréje a listában.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Az utolsó elem cseréje a listában.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Véletlenszerűen választott elem cseréje a listában.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Beszúrás a megadott sorszámú elem elé a listában.  1 az első elemet jelenti.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Beszúrás a megadott sorszámú elem elé a listában.  1 az utolsó elemet jelenti.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Beszúrás a lista elejére.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Beszúrás a lista végére.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Beszúrás véletlenszerűen választott elem elé a listában.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"részlistája az elejétől számított\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"részlistája a végétől számított\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"részlistája az első\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"és az elejétől számított\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"és a végétől számított\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"és az utolsó\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"elem között\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"A lista adott részéről másolat.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \".\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"A változó értékét adja eredményül.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Create \\\"set %1\\\"\",\n    \"VARIABLES_SET_TITLE\": \"\",\n    \"VARIABLES_SET_TAIL\": \"\",\n    \"VARIABLES_SET_TOOLTIP\": \"A változónak adhatunk értéket.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Create \\\"get %1\\\"\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"Eljárás\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"név\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"paraméterlistaː\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Eljárás (nem ad vissza eredményt).\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"eredménye\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Függvény eredménnyel.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Figyelem: Az eljárásban azonos elnevezésű paramétert adtál meg.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://hu.wikipedia.org/wiki/F%C3%BCggv%C3%A9ny_(programoz%C3%A1s)\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Végrehajtja az eljárást.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://hu.wikipedia.org/wiki/F%C3%BCggv%C3%A9ny_(programoz%C3%A1s)\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Meghívja a függvényt.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"paraméterek\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"változó:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Eljárás kiemelése\",\n    \"PROCEDURES_CREATE_DO\": \"Create \\\"do %1\\\"\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Ha az érték igaz, akkor visszatér a függvény értékével.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Figyelem: Ez a blokk csak eljáráson belül használható.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/ia.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"McDutchie\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"cosa\",\n    \"DUPLICATE_BLOCK\": \"Duplicar\",\n    \"ADD_COMMENT\": \"Adder commento\",\n    \"REMOVE_COMMENT\": \"Remover commento\",\n    \"EXTERNAL_INPUTS\": \"Entrata externe\",\n    \"INLINE_INPUTS\": \"Entrata interne\",\n    \"DELETE_BLOCK\": \"Deler bloco\",\n    \"DELETE_X_BLOCKS\": \"Deler %1 blocos\",\n    \"COLLAPSE_BLOCK\": \"Plicar bloco\",\n    \"COLLAPSE_ALL\": \"Plicar blocos\",\n    \"EXPAND_BLOCK\": \"Displicar bloco\",\n    \"EXPAND_ALL\": \"Displicar blocos\",\n    \"DISABLE_BLOCK\": \"Disactivar bloco\",\n    \"ENABLE_BLOCK\": \"Activar bloco\",\n    \"HELP\": \"Adjuta\",\n    \"CHANGE_VALUE_TITLE\": \"Cambiar valor:\",\n    \"NEW_VARIABLE\": \"Nove variabile...\",\n    \"NEW_VARIABLE_TITLE\": \"Nomine del nove variabile:\",\n    \"RENAME_VARIABLE\": \"Renominar variabile...\",\n    \"RENAME_VARIABLE_TITLE\": \"Renominar tote le variabiles '%1' a:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://ia.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Elige un color del paletta.\",\n    \"COLOUR_RANDOM_TITLE\": \"color aleatori\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Eliger un color al hasardo.\",\n    \"COLOUR_RGB_TITLE\": \"colorar con\",\n    \"COLOUR_RGB_RED\": \"rubie\",\n    \"COLOUR_RGB_GREEN\": \"verde\",\n    \"COLOUR_RGB_BLUE\": \"blau\",\n    \"COLOUR_RGB_TOOLTIP\": \"Crear un color con le quantitate specificate de rubie, verde e blau. Tote le valores debe esser inter 0 e 100.\",\n    \"COLOUR_BLEND_TITLE\": \"miscer\",\n    \"COLOUR_BLEND_COLOUR1\": \"color 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"color 2\",\n    \"COLOUR_BLEND_RATIO\": \"ration\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Misce duo colores con un ration specificate (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"repeter %1 vices\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"repeter\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"vices\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"face\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Exequer certe instructiones plure vices.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"repeter durante que\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"repeter usque a\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Durante que un valor es ver, exequer certe instructiones.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Durante que un valor es false, exequer certe instructiones.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Mitter in le variabile %1 le valores ab le numero initial usque al numero final, con passos secundo le intervallo specificate, e exequer le blocos specificate.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"contar con\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"de %1 a %2 per %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"pro cata elemento\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"in lista\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Pro cata elemento in un lista, mitter lo in le variabile '%1' e exequer certe instructiones.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"escappar del bucla\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continuar con le proxime iteration del bucla\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Escappar del bucla continente.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Saltar le resto de iste bucla e continuar con le proxime iteration.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Attention: Iste bloco pote solmente esser usate in un bucla.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Si un valor es ver, exequer certe instructiones.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Si un valor es ver, exequer le prime bloco de instructiones. Si non, exequer le secunde bloco de instructiones.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones. Si necun del valores es ver, exequer le ultime bloco de instructiones.\",\n    \"CONTROLS_IF_MSG_IF\": \"si\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"si non si\",\n    \"CONTROLS_IF_MSG_ELSE\": \"si non\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Adder, remover o reordinar sectiones pro reconfigurar iste bloco \\\"si\\\".\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Adder un condition al bloco \\\"si\\\".\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Adder un condition final de reserva al bloco \\\"si\\\".\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Retornar ver si le duo entratas es equal.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Retornar ver si le duo entratas non es equal.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Retornar ver si le prime entrata es minor que le secunde.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Retornar ver si le prime entrata es minor que o equal al secunde.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Retornar ver si le prime entrata es major que le secunde.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Retornar ver si le prime entrata es major que o equal al secunde.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Retornar ver si ambe entratas es ver.\",\n    \"LOGIC_OPERATION_AND\": \"e\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Retornar ver si al minus un del entratas es ver.\",\n    \"LOGIC_OPERATION_OR\": \"o\",\n    \"LOGIC_NEGATE_TITLE\": \"non %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Retornar ver si le entrata es false. Retornar false si le entrata es ver.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"ver\",\n    \"LOGIC_BOOLEAN_FALSE\": \"false\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Retorna o ver o false.\",\n    \"LOGIC_NULL\": \"nulle\",\n    \"LOGIC_NULL_TOOLTIP\": \"Retorna nulle.\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"si ver\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"si false\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Verificar le condition in 'test'. Si le condition es ver, retorna le valor de 'si ver'; si non, retorna le valor de 'si false'.\",\n    \"MATH_NUMBER_HELPURL\": \"https://ia.wikipedia.org/wiki/Numero\",\n    \"MATH_NUMBER_TOOLTIP\": \"Un numero.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://ia.wikipedia.org/wiki/Arithmetica\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Retornar le summa del duo numeros.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Retornar le differentia del duo numeros.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Retornar le producto del duo numeros.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Retornar le quotiente del duo numeros.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Retornar le prime numero elevate al potentia del secunde numero.\",\n    \"MATH_SINGLE_HELPURL\": \"https://ia.wikipedia.org/wiki/Radice_quadrate\",\n    \"MATH_SINGLE_OP_ROOT\": \"radice quadrate\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Retornar le radice quadrate de un numero.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolute\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Retornar le valor absolute de un numero.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Retornar le negation de un numero.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Retornar le logarithmo natural de un numero.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Retornar le logarithmo in base 10 del numero.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Retornar e elevate al potentia del numero.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Retornar 10 elevate al potentia de un numero.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/id.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"item\",\n    \"DUPLICATE_BLOCK\": \"Duplikat\",\n    \"ADD_COMMENT\": \"Tambahkan sebuah comment\",\n    \"REMOVE_COMMENT\": \"Hapus komentar\",\n    \"EXTERNAL_INPUTS\": \"Input-input eksternal\",\n    \"INLINE_INPUTS\": \"Input inline\",\n    \"DELETE_BLOCK\": \"Hapus blok\",\n    \"DELETE_X_BLOCKS\": \"Hapus %1 blok\",\n    \"COLLAPSE_BLOCK\": \"Tutup blok\",\n    \"COLLAPSE_ALL\": \"Tutup blok\",\n    \"EXPAND_BLOCK\": \"Kembangkan blok\",\n    \"EXPAND_ALL\": \"Kembangkan blok-blok\",\n    \"DISABLE_BLOCK\": \"Nonaktifkan blok\",\n    \"ENABLE_BLOCK\": \"Aktifkan blok\",\n    \"HELP\": \"Tolong\",\n    \"CHANGE_VALUE_TITLE\": \"Ubah nilai:\",\n    \"NEW_VARIABLE\": \"Pembolehubah baru...\",\n    \"NEW_VARIABLE_TITLE\": \"Nama pembolehubah baru:\",\n    \"RENAME_VARIABLE\": \"namai ulang variabel...\",\n    \"RENAME_VARIABLE_TITLE\": \"Ubah nama semua variabel '%1' menjadi:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Pilih warna dari daftar warna.\",\n    \"COLOUR_RANDOM_TITLE\": \"Warna acak\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Pilih warna secara acak.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"Dengan warna\",\n    \"COLOUR_RGB_RED\": \"merah\",\n    \"COLOUR_RGB_GREEN\": \"hijau\",\n    \"COLOUR_RGB_BLUE\": \"biru\",\n    \"COLOUR_RGB_TOOLTIP\": \"Buatlah warna dengan jumlah yang ditentukan dari merah, hijau dan biru. Semua nilai harus antarai 0 sampai 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"Tertutup\",\n    \"COLOUR_BLEND_COLOUR1\": \"Warna 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"Warna 2\",\n    \"COLOUR_BLEND_RATIO\": \"rasio\",\n    \"COLOUR_BLEND_TOOLTIP\": \"mencampur dua warna secara bersamaan dengan perbandingan (0.0-1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"ulangi %1 kali\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"ulangi\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"kali\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"kerjakan\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Lakukan beberapa perintah beberapa kali.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"Ulangi jika\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"Ulangi sampai\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Jika sementara nilai benar (true), maka lakukan beberapa perintah.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Jika sementara nilai tidak  benar (false), maka lakukan beberapa perintah.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Menggunakan variabel %1 dengan mengambil nilai dari batas awal hingga ke batas akhir, dengan interval tertentu, dan mengerjakan block tertentu.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"Cacah dengan\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"dari %1 ke %2 dengan step / penambahan %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"untuk setiap item\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"di dalam list\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Untuk tiap-tiap item di dalam list, tetapkan variabel '%1' ke dalam item, selanjutnya kerjakan beberapa statement.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"Keluar dari perulangan\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"Lanjutkan dengan langkah penggulangan berikutnya\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Keluar sementara dari perulanggan.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Abaikan sisa dari loop ini, dan lanjutkan dengan iterasi berikutnya.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Peringatan: Blok ini hanya dapat digunakan dalam loop.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"jika nilainya benar maka kerjakan perintah berikutnya.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"jika nilainya benar, maka kerjakan blok perintah yang pertama. Jika tidak, kerjakan blok perintah yang kedua.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Jika nilai pertama adalah benar (true), maka lakukan perintah-perintah yang berada didalam blok pertama. Jika nilai kedua adalah benar (true), maka lakukan perintah-perintah yang berada didalam blok kedua.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Jika blok pertama adalah benar (true), maka lakukan perintah-perintah yang berada  didalam blok pertama. Atau jika blok kedua adalah benar (true), maka lakukan perintah-perintah yang berada didalam blok kedua.\",\n    \"CONTROLS_IF_MSG_IF\": \"Jika\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"else if\",\n    \"CONTROLS_IF_MSG_ELSE\": \"else\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Menambahkan, menghapus, atau menyusun kembali bagian untuk mengkonfigurasi blok IF ini.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"tambahkan prasyarat ke dalam blok IF.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Terakhir, tambahkan tangkap-semua kondisi kedalam blok jika (if).\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Mengembalikan betul jika input kedua-duanya sama dengan satu sama lain.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Mengembalikan nilai benar (true) jika kedua input tidak sama satu dengan yang lain.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Mengembalikan nilai benar (true) jika input yang pertama lebih kecil dari input yang kedua.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Mengembalikan nilai benar (true) jika input yang pertama lebih kecil atau sama dengan input yang kedua .\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Mengembalikan nilai benar (true) jika input yang pertama lebih besar dari input yang kedua.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Mengembalikan nilai benar (true) jika input yang pertama lebih besar dari atau sama dengan input yang kedua.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Kembalikan betul jika kedua-dua input adalah betul.\",\n    \"LOGIC_OPERATION_AND\": \"dan\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Mengembalikan nilai benar (true) jika setidaknya salah satu masukan nilainya benar (true).\",\n    \"LOGIC_OPERATION_OR\": \"atau\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"bukan (not) %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Mengembalikan nilai benar (true) jika input false.  Mengembalikan nilai salah (false) jika input true.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"Benar\",\n    \"LOGIC_BOOLEAN_FALSE\": \"Salah\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Mengembalikan betul (true) atau salah (false).\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"mengembalikan kosong.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"jika benar (true)\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"jika tidak benar (false)\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Periksa kondisi di \\\"test\\\". Jika kondisi benar (true), mengembalikan nilai \\\"jika benar\\\" ; Jik sebaliknya akan mengembalikan nilai \\\"jika salah\\\".\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Suatu angka.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://id.wikipedia.org/wiki/Aritmetika\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Kembalikan jumlah dari kedua angka.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Kembalikan selisih dari kedua angka.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Kembalikan perkalian dari kedua angka.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Kembalikan hasil bagi dari kedua angka.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Kembalikan angka pertama pangkat angka kedua.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"akar\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Kembalikan akar dari angka.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"mutlak\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Kembalikan nilai absolut angka.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Kembalikan penyangkalan terhadap angka.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Kembalikan logaritma natural dari angka.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Kembalikan dasar logaritma 10 dari angka.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Kembalikan 10 pangkat angka.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Kembalikan 10 pangkat angka.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Kembalikan sinus dari derajat (bukan radian).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Kembalikan cos dari derajat (bukan radian).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Kembalikan tangen dari derajat (tidak radian).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Kembalikan asin dari angka.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Kembalikan acosine dari angka.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Kembalikan atan dari angka.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Kembalikan salah satu konstant: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), atau ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"adalah bilangan genap\",\n    \"MATH_IS_ODD\": \"adalah bilangan ganjil\",\n    \"MATH_IS_PRIME\": \"adalah bilangan pokok\",\n    \"MATH_IS_WHOLE\": \"adalah bilangan bulat\",\n    \"MATH_IS_POSITIVE\": \"adalah  bilangan positif\",\n    \"MATH_IS_NEGATIVE\": \"adalah  bilangan negatif\",\n    \"MATH_IS_DIVISIBLE_BY\": \"dibagi oleh\",\n    \"MATH_IS_TOOLTIP\": \"Periksa apakah angka adalah bilangan genap, bilangan pokok, bilangan bulat, bilangan positif, bilangan negatif, atau apakan bisa dibagi oleh angka tertentu. Mengembalikan benar (true) atau salah (false).\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"ubah\",\n    \"MATH_CHANGE_INPUT_BY\": \"oleh\",\n    \"MATH_CHANGE_TOOLTIP\": \"Tambahkan angka kedalam variabel '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Bulatkan suatu bilangan naik atau turun.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"membulatkan\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"mengumpulkan\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"membulatkan kebawah\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"jumlah dari list (daftar)\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Kembalikan jumlah dari seluruh bilangan dari list.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"minimum dari list (daftar)\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Kembalikan angka terkecil dari list.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"maximum dari list (daftar)\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Kembalikan angka terbesar dari list.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"rata-rata dari list (daftar)\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Kembalikan rata-rata (mean aritmetik) dari nilai numerik dari list (daftar).\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"median dari list (daftar)\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Kembalikan median dari list.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"mode-mode dari list (daftar)\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Kembalikan list berisi item-item yang paling umum dari dalam list.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"deviasi standar dari list (daftar)\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Kembalikan standard deviasi dari list.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"item acak dari list (daftar)\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Kembalikan element acak dari list.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"sisa %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Kembalikan sisa dari pembagian ke dua angka.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"Batasi %1 rendah %2 tinggi %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Batasi angka antara batas yang ditentukan (inklusif).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"acak bulat dari %1 sampai %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Mengembalikan bilangan acak antara dua batas yang ditentukan, inklusif.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"Nilai pecahan acak\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Mengembalikan nilai acak pecahan antara 0.0 (inklusif) dan 1.0 (ekslusif).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Huruf, kata atau baris teks.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"Buat teks dengan\",\n    \"TEXT_JOIN_TOOLTIP\": \"Buat teks dengan cara gabungkan sejumlah item.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"join\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Tambah, ambil, atau susun ulang teks blok.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Tambahkan suatu item ke dalam teks.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"untuk\",\n    \"TEXT_APPEND_APPENDTEXT\": \"tambahkan teks\",\n    \"TEXT_APPEND_TOOLTIP\": \"Tambahkan beberapa teks ke variabel '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"panjang dari %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Kembalikan sejumlah huruf (termasuk spasi) dari teks yang disediakan.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 kosong\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Kembalikan benar (true) jika teks yang disediakan kosong.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Kembalikan indeks pertama dan terakhir dari kejadian pertama/terakhir dari teks pertama dalam teks kedua.  Kembalikan 0 jika teks tidak ditemukan.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"dalam teks\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"temukan kejadian pertama dalam teks\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"temukan kejadian terakhir dalam teks\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"dalam teks\",\n    \"TEXT_CHARAT_FROM_START\": \"ambil huruf ke #\",\n    \"TEXT_CHARAT_FROM_END\": \"ambil  huruf nomor # dari belakang\",\n    \"TEXT_CHARAT_FIRST\": \"ambil  huruf pertama\",\n    \"TEXT_CHARAT_LAST\": \"ambil  huruf terakhir\",\n    \"TEXT_CHARAT_RANDOM\": \"ambil huruf secara acak\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Kembalikan karakter dari posisi tertentu.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Mengembalikan spesifik bagian dari teks.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"in teks\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"ambil bagian teks (substring) dari huruf no #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"ambil bagian teks (substring) dari huruf ke # dari terakhir\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"ambil bagian teks (substring) dari huruf pertama\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"pada huruf #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"pada huruf nomer # dari terakhir\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"pada huruf terakhir\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Kembalikan kopi dari text dengan kapitalisasi yang berbeda.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"menjadi huruf kapital\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"menjadi huruf kecil\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"menjadi huruf pertama kapital\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Kembali salinan teks dengan spasi dihapus dari satu atau kedua ujungnya.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"pangkas ruang dari kedua belah sisi\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"pangkas ruang dari sisi kiri\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"pangkas ruang dari sisi kanan\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"cetak %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Cetak teks yant ditentukan, angka atau ninlai lainnya.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"meminta teks dengan pesan\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"Meminta angka dengan pesan\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Meminta pengguna untuk memberi sebuah angka.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Meminta pengguna untuk memberi beberapa teks.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"buat list kosong\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Mengembalikan daftar, dengan panjang 0, tidak berisi data\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Buat sebuah daftar (list) dengan sejumlah item.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"buat daftar (list) dengan\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"list\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Tambahkan, hapus, atau susun ulang bagian untuk mengkonfigurasi blok LIST (daftar) ini.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Tambahkan sebuah item ke daftar (list).\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Ciptakan daftar yang terdiri dari nilai yang diberikan diulang jumlah waktu yang ditentukan.\",\n    \"LISTS_REPEAT_TITLE\": \"membuat daftar dengan item %1 diulang %2 kali\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"panjang dari %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Mengembalikan panjang daftar.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 kosong\",\n    \"LISTS_TOOLTIP\": \"Mengembalikan nilai benar (true) jika list kosong.\",\n    \"LISTS_INLIST\": \"dalam daftar\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"cari kejadian pertama item\",\n    \"LISTS_INDEX_OF_LAST\": \"Cari kejadian terakhir item\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Mengembalikan indeks dari kejadian pertama/terakhir item dalam daftar.  Menghasilkan 0 jika teks tidak ditemukan.\",\n    \"LISTS_GET_INDEX_GET\": \"dapatkan\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"dapatkan dan hapus\",\n    \"LISTS_GET_INDEX_REMOVE\": \"Hapus\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# dari akhir\",\n    \"LISTS_GET_INDEX_FIRST\": \"pertama\",\n    \"LISTS_GET_INDEX_LAST\": \"terakhir\",\n    \"LISTS_GET_INDEX_RANDOM\": \"acak\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Sisipkan item ke dalam posisi yang telah ditentukan didalam list (daftar). Item pertama adalah item terakhir (yg paling akhir).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Sisipkan item ke dalam posisi yang telah ditentukan didalam list (daftar). Item pertama adalah item yang terakhir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Kembalikan item pertama dalam daftar (list).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Mengembalikan item pertama dalam list (daftar).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Mengembalikan item acak dalam list (daftar).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Menghilangkan dan mengembalikan barang di posisi tertentu dalam list (daftar).  #1 adalah item pertama.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Menghilangkan dan mengembalikan barang di posisi tertentu dalam list (daftar).  #1 adalah item terakhir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Menghilangkan dan mengembalikan item pertama dalam list (daftar).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Menghilangkan dan mengembalikan item terakhir dalam list (daftar).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Menghilangkan dan mengembalikan barang dengan acak dalam list (daftar).\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Menghapus item dengan posisi tertentu dalam daftar. Item pertama adalah item yang terakhir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Menghapus item dengan posisi tertentu dalam daftar. Item pertama adalah item yang terakhir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Menghapus item pertama dalam daftar.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Menghapus item terakhir dalam daftar.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Menghapus sebuah item secara acak dalam list.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"tetapkan\",\n    \"LISTS_SET_INDEX_INSERT\": \"sisipkan di\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"sebagai\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Tetapkan item ke dalam posisi yang telah ditentukan di dalam list. #1 adalah item yang pertama.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Tetapkan item ke dalam posisi yang telah ditentukan di dalam list. #1 adalah item yang terakhir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Tetapkan item pertama di dalam list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Menetapkan item terakhir dalam list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Tetapkan secara acak sebuah item dalam list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Sisipkan item ke dalam posisi yang telah ditentukan di dalam list. #1 adalah item yang pertama.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Sisipkan item ke dalam posisi yang telah ditentukan di dalam list. #1 adalah item yang terakhir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Sisipkan item di bagian awal dari list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Tambahkan item ke bagian akhir list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Sisipkan item secara acak ke dalam list.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"Dapatkan bagian daftar dari #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"Dapatkan bagian list nomor # dari akhir\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"Dapatkan bagian pertama dari list\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"ke #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"ke # dari akhir\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"ke yang paling akhir\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Membuat salinan dari bagian tertentu dari list.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Mengembalikan nilai variabel ini.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Membuat 'tetapkan %1'\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"tetapkan\",\n    \"VARIABLES_SET_TAIL\": \"untuk\",\n    \"VARIABLES_SET_TOOLTIP\": \"tetapkan variabel ini dengan input yang sama.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Membuat 'dapatkan %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"untuk\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"buat sesuatu\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"dengan:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Menciptakan sebuah fungsi dengan tiada output.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"kembali\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Menciptakan sebuah fungsi dengan satu output.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Peringatan: Fungsi ini memiliki parameter duplikat.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Menjalankan fungsi '%1' yang ditetapkan pengguna.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Menjalankan fungsi  '%1' yang ditetapkan pengguna dan menggunakan outputnya.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"input\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"masukan Nama:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Sorot definisi fungsi\",\n    \"PROCEDURES_CREATE_DO\": \"Buat '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Jika nilai yang benar, kemudian kembalikan nilai kedua.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Peringatan: Blok ini dapat digunakan hanya dalam definisi fungsi.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/is.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Jonbg\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"atriði\",\n    \"DUPLICATE_BLOCK\": \"Afrita\",\n    \"ADD_COMMENT\": \"Skrifa skýringu\",\n    \"REMOVE_COMMENT\": \"Fjarlægja skýringu\",\n    \"EXTERNAL_INPUTS\": \"Ytri inntök\",\n    \"INLINE_INPUTS\": \"Innri inntök\",\n    \"DELETE_BLOCK\": \"Eyða kubbi\",\n    \"DELETE_X_BLOCKS\": \"Eyða %1 kubbum\",\n    \"COLLAPSE_BLOCK\": \"Loka kubbi\",\n    \"COLLAPSE_ALL\": \"Loka kubbum\",\n    \"EXPAND_BLOCK\": \"Opna kubb\",\n    \"EXPAND_ALL\": \"Opna kubba\",\n    \"DISABLE_BLOCK\": \"Óvirkja kubb\",\n    \"ENABLE_BLOCK\": \"Virkja kubb\",\n    \"HELP\": \"Hjálp\",\n    \"CHANGE_VALUE_TITLE\": \"Breyta gildi:\",\n    \"NEW_VARIABLE\": \"Ný breyta...\",\n    \"NEW_VARIABLE_TITLE\": \"Heiti nýrrar breytu:\",\n    \"RENAME_VARIABLE\": \"Endurnefna breytu...\",\n    \"RENAME_VARIABLE_TITLE\": \"Endurnefna allar '%1' breyturnar:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Velja lit úr litakorti.\",\n    \"COLOUR_RANDOM_TITLE\": \"einhver litur\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Velja einhvern lit af handahófi.\",\n    \"COLOUR_RGB_TITLE\": \"litur\",\n    \"COLOUR_RGB_RED\": \"rautt\",\n    \"COLOUR_RGB_GREEN\": \"grænt\",\n    \"COLOUR_RGB_BLUE\": \"blátt\",\n    \"COLOUR_RGB_TOOLTIP\": \"Búa til lit úr tilteknu magni af rauðu, grænu og bláu. Allar tölurnar verða að vera á bilinu 0 til 100.\",\n    \"COLOUR_BLEND_TITLE\": \"blöndun\",\n    \"COLOUR_BLEND_COLOUR1\": \"litur 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"litur 2\",\n    \"COLOUR_BLEND_RATIO\": \"hlutfall\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Blandar tveimur litum í gefnu hlutfalli (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"endurtaka %1 sinnum\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"endurtaka\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"sinnum\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"gera\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Gera eitthvað aftur og aftur.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"endurtaka á meðan\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"endurtaka þar til\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Endurtaka eitthvað á meðan gildi er satt.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Endurtaka eitthvað á meðan gildi er ósatt.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Láta breytuna %1 taka inn gildi frá fyrstu tölu til síðustu tölu hlaupandi á bilinu og endurtaka kubbana fyrir hverja tölu.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"telja með\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"frá %1 til %2 um %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"fyrir hvert\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"í lista\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Fyrir hvert atriði í lista er breyta '%1' stillt á atriðið og skipanir gerðar.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"fara út úr lykkju\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"fara beint í næstu umferð lykkjunnar\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Fara út úr umlykjandi lykkju.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Sleppa afganginum af lykkjunni og fara beint í næstu umferð hennar.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Aðvörun: Þennan kubb má aðeins nota innan lykkju.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Ef gildi er satt skal gera einhverjar skipanir.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Ef gildi er satt skal gera skipanir í fyrri kubbnum. Annars skal gera skipanir í seinni kubbnum.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Ef fyrra gildið er satt skal gera skipanir í fyrri kubbnum. Annars, ef seinna gildið er satt, þá skal gera skipanir í seinni kubbnum.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Ef fyrra gildið er satt skal gera skipanir í fyrri kubbnum. Annars, ef seinna gildið er satt, skal gera skipanir í seinni kubbnum. Ef hvorugt gildið er satt, skal gera skipanir í síðasta kubbnum.\",\n    \"CONTROLS_IF_MSG_IF\": \"ef\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"annars ef\",\n    \"CONTROLS_IF_MSG_ELSE\": \"annars\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Bæta við, fjarlægja eða umraða til að breyta skipan þessa EF kubbs.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Bæta skilyrði við EF kubbinn.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Bæta við hluta EF kubbs sem grípur öll tilfelli sem uppfylla ekki hin skilyrðin.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Skila sönnu ef inntökin eru jöfn.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Skila sönnu ef inntökin eru ekki jöfn.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Skila sönnu ef fyrra inntakið er minna en seinna inntakið.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Skila sönnu ef fyrra inntakið er minna en eða jafnt og seinna inntakið.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Skila sönnu ef fyrra inntakið er stærra en seinna inntakið.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Skila sönnu ef fyrra inntakið er stærra en eða jafnt og seinna inntakið.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Skila sönnu ef bæði inntökin eru sönn.\",\n    \"LOGIC_OPERATION_AND\": \"og\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Skila sönnu ef að minnsta kosti eitt inntak er satt.\",\n    \"LOGIC_OPERATION_OR\": \"eða\",\n    \"LOGIC_NEGATE_TITLE\": \"ekki %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Skilar sönnu ef inntakið er ósatt. Skilar ósönnu ef inntakið er satt.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"satt\",\n    \"LOGIC_BOOLEAN_FALSE\": \"ósatt\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Skilar annað hvort sönnu eða ósönnu.\",\n    \"LOGIC_NULL\": \"tómagildi\",\n    \"LOGIC_NULL_TOOLTIP\": \"Skilar tómagildi.\",\n    \"LOGIC_TERNARY_CONDITION\": \"prófun\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"ef satt\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"ef ósatt\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Kanna skilyrðið í 'prófun'. Skilar 'ef satt' gildinu ef skilyrðið er satt, en skilar annars 'ef ósatt' gildinu.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Tala.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Skila summu talnanna tveggja.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Skila mismun talnanna.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Skila margfeldi talnanna.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Skila deilingu talnanna.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Skila fyrri tölunni í veldinu seinni talan.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"kvaðratrót\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Skila kvaðratrót tölu.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"algildi\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Skila algildi tölu.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Skila neitun tölu (tölunni með öfugu formerki).\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Skila náttúrlegum lógaritma tölu.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Skila tugalógaritma tölu.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Skila e í veldi tölu.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Skila 10 í veldi tölu.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Skila sínusi horns gefnu í gráðum.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Skila kósínusi horns gefnu í gráðum.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Skila tangensi horns gefnu í gráðum.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Skilar arkarsínusi tölu.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Skilar arkarkósínusi tölu.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Skilar arkartangensi tölu.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Skila algengum fasta: π (3.141…), e (2.718…), φ (1.618…), kvrót(2) (1.414…), kvrót(½) (0.707…) eða ∞ (óendanleika).\",\n    \"MATH_IS_EVEN\": \"er\\\\u00A0jöfn tala\",\n    \"MATH_IS_ODD\": \"er oddatala\",\n    \"MATH_IS_PRIME\": \"er prímtala\",\n    \"MATH_IS_WHOLE\": \"er heiltala\",\n    \"MATH_IS_POSITIVE\": \"er jákvæð\",\n    \"MATH_IS_NEGATIVE\": \"er neikvæð\",\n    \"MATH_IS_DIVISIBLE_BY\": \"er\\\\u00A0deilanleg með\",\n    \"MATH_IS_TOOLTIP\": \"Kanna hvort tala sé jöfn tala, oddatala, jákvæð, neikvæð eða deilanleg með tiltekinni tölu. Skilar sönnu eða ósönnu.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"breyta\",\n    \"MATH_CHANGE_INPUT_BY\": \"um\",\n    \"MATH_CHANGE_TOOLTIP\": \"Bæta tölu við breytu '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Námunda tölu upp eða niður.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"námunda\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"námunda upp\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"námunda niður\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"summa lista\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Skila summu allra talna í listanum.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"minnst í lista\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Skila minnstu tölu í listanum.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"stærst í lista\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Skila stærstu tölu í listanum.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"meðaltal lista\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Skila meðaltali talna í listanum.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"miðgildi lista\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Skila miðgildi listans.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"tíðast í lista\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Skila lista yfir tíðustu gildin í listanum.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"staðalfrávik lista\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Skila staðalfráviki lista.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"eitthvað úr lista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Skila einhverju atriði úr listanum.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"afgangur af %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Skila afgangi deilingar með tölunum.\",\n    \"MATH_CONSTRAIN_TITLE\": \"þröngva %1 lægst %2 hæst %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Þröngva tölu til að vera innan hinna tilgreindu marka (að báðum meðtöldum).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"slembitala frá %1 til %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Skila heiltölu sem valin er af handahófi og er innan tilgreindra marka, að báðum meðtöldum.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"slembibrot\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Skila broti sem er valið af handahófi úr tölum á bilinu frá og með 0.0 til (en ekki með) 1.0.\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Stafur, orð eða textalína.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"búa til texta með\",\n    \"TEXT_JOIN_TOOLTIP\": \"Búa til texta með því að tengja saman einhvern fjölda atriða.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"tengja\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Bæta við, fjarlægja eða umraða hlutum til að breyta skipan þessa textakubbs.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Bæta atriði við textann.\",\n    \"TEXT_APPEND_TO\": \"við\",\n    \"TEXT_APPEND_APPENDTEXT\": \"bæta texta\",\n    \"TEXT_APPEND_TOOLTIP\": \"Bæta texta við breytuna '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"lengd %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Skilar fjölda stafa (með bilum) í gefna textanum.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 er tómur\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Skilar sönnu ef gefni textinn er tómur.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Finnur fyrsta/síðasta tilfelli fyrri textans í seinni textanum og skilar sæti hans. Skilar 0 ef textinn finnst ekki.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"í texta\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"finna fyrsta tilfelli texta\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"finna síðasta tilfelli texta\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"í texta\",\n    \"TEXT_CHARAT_FROM_START\": \"sækja staf #\",\n    \"TEXT_CHARAT_FROM_END\": \"sækja staf # frá enda\",\n    \"TEXT_CHARAT_FIRST\": \"sækja fyrsta staf\",\n    \"TEXT_CHARAT_LAST\": \"sækja síðasta staf\",\n    \"TEXT_CHARAT_RANDOM\": \"sækja einhvern staf\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Skila staf á tilteknum stað.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Skilar tilteknum hluta textans.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"í texta\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"sækja textabút frá staf #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"sækja textabút frá staf # frá enda\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"sækja textabút frá fyrsta staf\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"að staf #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"að staf # frá enda\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"að síðasta staf\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Skila afriti af textanum með annarri stafastöðu.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"í HÁSTAFI\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"í lágstafi\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"í Upphafstafi\",\n    \"TEXT_TRIM_TOOLTIP\": \"Skila afriti af textanum þar sem möguleg bil við báða enda hafa verið fjarlægð.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"eyða bilum af báðum endum\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"eyða bilum af vinstri enda\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"eyða bilum af hægri enda\",\n    \"TEXT_PRINT_TITLE\": \"prenta %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Prenta tiltekinn texta, tölu eða annað gildi.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"biðja um texta með skilaboðum\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"biðja um tölu með skilaboðum\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Biðja notandann um tölu.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Biðja notandann um texta.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"búa til tóman lista\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Skilar lista með lengdina 0 án gagna\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Búa til lista með einhverjum fjölda atriða.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"búa til lista með\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"listi\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Bæta við, fjarlægja eða umraða hlutum til að breyta skipan þessa listakubbs.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Bæta atriði við listann.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Býr til lista sem inniheldur tiltekna gildið endurtekið tiltekið oft.\",\n    \"LISTS_REPEAT_TITLE\": \"búa til lista með atriði %1 endurtekið %2 sinnum\",\n    \"LISTS_LENGTH_TITLE\": \"lengd %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Skilar lengd lista.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 er tómur\",\n    \"LISTS_TOOLTIP\": \"Skilar sönnu ef listinn er tómur.\",\n    \"LISTS_INLIST\": \"í lista\",\n    \"LISTS_INDEX_OF_FIRST\": \"finna fyrsta tilfelli atriðis\",\n    \"LISTS_INDEX_OF_LAST\": \"finna síðasta tilfelli atriðis\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Finnur hvar atriðið kemur fyrir fyrst/síðast í listanum og skilar sæti þess. Skilar 0 ef textinn finnst ekki.\",\n    \"LISTS_GET_INDEX_GET\": \"sækja\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"sækja og fjarlægja\",\n    \"LISTS_GET_INDEX_REMOVE\": \"fjarlægja\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# frá enda\",\n    \"LISTS_GET_INDEX_FIRST\": \"fyrsta\",\n    \"LISTS_GET_INDEX_LAST\": \"síðasta\",\n    \"LISTS_GET_INDEX_RANDOM\": \"eitthvert\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Skilar atriðinu í hinum tiltekna stað í lista. #1 er fyrsta atriðið.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Skilar atriðinu á hinum tiltekna stað í lista. #1 er síðasta atriðið.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Skilar fyrsta atriði í lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Skilar síðasta atriði í lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Skilar einhverju atriði úr lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Fjarlægir og skilar atriðinu á hinum tiltekna stað í lista. #1 er fyrsta atriðið.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Fjarlægir og skilar atriðinu á hinum tiltekna stað í lista. #1 er síðasta atriðið.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Fjarlægir og skilar fyrsta atriðinu í lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Fjarlægir og skilar síðasta atriðinu í lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Fjarlægir og skilar einhverju atriði úr lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Fjarlægir atriðið á hinum tiltekna stað í lista. #1 er fyrsta atriðið.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Fjarlægir atriðið á hinum tiltekna stað í lista. #1 er síðasta atriðið.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Fjarlægir fyrsta atriðið í lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Fjarlægir síðasta atriðið í lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Fjarlægir eitthvert atriði úr lista.\",\n    \"LISTS_SET_INDEX_SET\": \"setja í\",\n    \"LISTS_SET_INDEX_INSERT\": \"bæta við\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"sem\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Setur atriðið í tiltekna sætið í listanum. #1 er fyrsta atriðið.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Setur atriðið í tiltekna sætið í listanum. #1 er síðasta atriðið.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Setur atriðið í fyrsta sæti lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Setur atriðið í síðasta sæti lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Setur atriðið í eitthvert sæti lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Bætir atriðinu í listann á tilteknum stað. #1 er fyrsta atriðið.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Bætir atriðinu í listann á tilteknum stað. #1 er síðasta atriðið.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Bætir atriðinu fremst í listann.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Bætir atriðinu aftan við listann.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Bætir atriðinu einhversstaðar við listann.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"sækja undirlista frá #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"sækja undirlista frá # frá enda\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"sækja undirlista frá fyrsta\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"til #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"til # frá enda\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"til síðasta\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Býr til afrit af tilteknum hluta lista.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Skilar gildi þessarar breytu.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Búa til 'stilla %1'\",\n    \"VARIABLES_SET_TITLE\": \"stilla\",\n    \"VARIABLES_SET_TAIL\": \"á\",\n    \"VARIABLES_SET_TOOLTIP\": \"Stillir þessa breytu á innihald inntaksins.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Búa til 'sækja %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"til að\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"gera eitthvað\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"með:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Býr til fall sem skilar engu.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"skila\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Býr til fall sem skilar úttaki.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Aðvörun: Þetta fall er með tvítekna stika.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Keyra heimatilbúna fallið '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Keyra heimatilbúna fallið '%1' og nota úttak þess.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"inntök\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"heiti inntaks:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Sýna skilgreiningu falls\",\n    \"PROCEDURES_CREATE_DO\": \"Búa til '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Ef gildi er satt, skal skila öðru gildi.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Aðvörun: Þennan kubb má aðeins nota í skilgreiningu falls.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/it.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Beta16\",\n            \"Espertus\",\n            \"Nerimic\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"elemento\",\n    \"DUPLICATE_BLOCK\": \"Duplica\",\n    \"ADD_COMMENT\": \"Aggiungi commento\",\n    \"REMOVE_COMMENT\": \"Rimuovi commento\",\n    \"EXTERNAL_INPUTS\": \"Ingressi esterni\",\n    \"INLINE_INPUTS\": \"Ingressi in linea\",\n    \"DELETE_BLOCK\": \"Cancella blocco\",\n    \"DELETE_X_BLOCKS\": \"Cancella %1 blocchi\",\n    \"COLLAPSE_BLOCK\": \"Comprimi blocco\",\n    \"COLLAPSE_ALL\": \"Comprimi blocchi\",\n    \"EXPAND_BLOCK\": \"Espandi blocco\",\n    \"EXPAND_ALL\": \"Espandi blocchi\",\n    \"DISABLE_BLOCK\": \"Disattiva blocco\",\n    \"ENABLE_BLOCK\": \"Attiva blocco\",\n    \"HELP\": \"Aiuto\",\n    \"CHANGE_VALUE_TITLE\": \"Modifica valore:\",\n    \"NEW_VARIABLE\": \"Nuova variabile...\",\n    \"NEW_VARIABLE_TITLE\": \"Nome della nuova variabile:\",\n    \"RENAME_VARIABLE\": \"Rinomina variabile...\",\n    \"RENAME_VARIABLE_TITLE\": \"Rinomina tutte le variabili '%1' in:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://it.wikipedia.org/wiki/Colore\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Scegli un colore dalla tavolozza.\",\n    \"COLOUR_RANDOM_TITLE\": \"colore casuale\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Scegli un colore a caso.\",\n    \"COLOUR_RGB_TITLE\": \"colora con\",\n    \"COLOUR_RGB_RED\": \"rosso\",\n    \"COLOUR_RGB_GREEN\": \"verde\",\n    \"COLOUR_RGB_BLUE\": \"blu\",\n    \"COLOUR_RGB_TOOLTIP\": \"Crea un colore con la quantità specificata di rosso, verde e blu. Tutti i valori devono essere compresi tra 0 e 100.\",\n    \"COLOUR_BLEND_TITLE\": \"miscela\",\n    \"COLOUR_BLEND_COLOUR1\": \"colore 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"colore 2\",\n    \"COLOUR_BLEND_RATIO\": \"rapporto\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Mescola due colori insieme con un determinato rapporto (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://it.wikipedia.org/wiki/Ciclo_for\",\n    \"CONTROLS_REPEAT_TITLE\": \"ripeti %1 volte\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"ripeti\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"volte\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"fai\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Esegue alcune istruzione diverse volte.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"ripeti mentre\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"ripeti fino a che\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Finché un valore è vero, esegue alcune istruzioni.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Finché un valore è falso, esegue alcune istruzioni.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Fa sì che la variabile %1 prenda tutti i valori a partire dal numero di partenza fino a quello di arrivo, con passo pari all'intervallo specificato, ed esegue il blocco indicato.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"conta con\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"da %1 a %2 per %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"per ogni elemento\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"nella lista\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Per ogni elemento in una lista, imposta la variabile '%1'  pari all'elemento e quindi esegue alcune istruzioni.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"esce dal ciclo\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"prosegui con la successiva iterazione del ciclo\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Esce dal ciclo.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Salta il resto di questo ciclo e prosegue con la successiva iterazione.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Attenzioneː Questo blocco può essere usato solo in un ciclo.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Se un valore è vero allora esegue alcune istruzioni.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Se un valore è vero allora esegue il primo blocco di istruzioni. Altrimenti esegue il secondo blocco di istruzioni.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni. Se nessuno dei valori è vero esegue l'ultimo blocco di istruzioni.\",\n    \"CONTROLS_IF_MSG_IF\": \"se\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"altrimenti se\",\n    \"CONTROLS_IF_MSG_ELSE\": \"altrimenti\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Aggiungi, elimina o riordina le sezioni per riconfigurare questo blocco se.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Aggiungi una condizione al blocco se.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Aggiungi una condizione finale pigliatutto al blocco se.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://it.wikipedia.org/wiki/Disuguaglianza\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Restituisce vero se gli input sono uno uguale all'altro.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Restituisce vero se gli input non sono uno uguale all'altro.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Restituisce vero se il primo input è minore del secondo.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Restituisce vero se il primo input è minore o uguale al secondo.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Restituisce vero se il primo input è maggiore o uguale al secondo.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Restituisce uguale se il primo input è maggiore o uguale al secondo input.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Restituisce vero se entrambi gli input sono veri.\",\n    \"LOGIC_OPERATION_AND\": \"e\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Restituisce vero se almeno uno degli input è vero.\",\n    \"LOGIC_OPERATION_OR\": \"o\",\n    \"LOGIC_NEGATE_TITLE\": \"non %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Restituisce vero se l'input è falso. Restituisce falso se l'input è vero.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"vero\",\n    \"LOGIC_BOOLEAN_FALSE\": \"falso\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Restituisce vero o falso.\",\n    \"LOGIC_NULL\": \"nullo\",\n    \"LOGIC_NULL_TOOLTIP\": \"Restituisce valore nullo.\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"se vero\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"se falso\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Verifica la condizione in 'test'. Se questa è vera restituisce il valore 'se vero' altrimenti restituisce il valore 'se falso'.\",\n    \"MATH_NUMBER_HELPURL\": \"https://it.wikipedia.org/wiki/Numero\",\n    \"MATH_NUMBER_TOOLTIP\": \"Un numero.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://it.wikipedia.org/wiki/Aritmetica\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Restituisce la somma dei due numeri.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Restituisce la differenza dei due numeri.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Restituisce il prodotto dei due numeri.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Restituisce il quoziente dei due numeri.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Restituisce il primo numero elevato alla potenza del secondo numero.\",\n    \"MATH_SINGLE_HELPURL\": \"https://it.wikipedia.org/wiki/Radice_quadrata\",\n    \"MATH_SINGLE_OP_ROOT\": \"radice quadrata\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Restituisce la radice quadrata del numero.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"assoluto\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Restituisce il valore assoluto del numero.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Restituisce l'opposto del numero.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Restituisce il logaritmo naturale del numero.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Restituisce il logaritmo in base 10 del numero.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Restituisce e elevato alla potenza del numero.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Restituisce 10 elevato alla potenza del numero.\",\n    \"MATH_TRIG_HELPURL\": \"https://it.wikipedia.org/wiki/Funzione_trigonometrica\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Restituisce il seno di un angolo espresso in gradi (non radianti).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Restituisce il coseno di un angolo espresso in gradi (non radianti).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Restituisce la tangente di un angolo espresso in gradi (non radianti).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Restituisce l'arco-seno di un numero.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Restituisce l'arco-coseno di un numero.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Restituisce l'arco-tangente di un numero.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://it.wikipedia.org/wiki/Costante_matematica\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Restituisce una delle costanti comuniː π (3.141…), e (2.718…), φ (1.618…), radq(2) (1.414…), radq(½) (0.707…) o ∞ (infinito).\",\n    \"MATH_IS_EVEN\": \"è pari\",\n    \"MATH_IS_ODD\": \"è dispari\",\n    \"MATH_IS_PRIME\": \"è primo\",\n    \"MATH_IS_WHOLE\": \"è intero\",\n    \"MATH_IS_POSITIVE\": \"è positivo\",\n    \"MATH_IS_NEGATIVE\": \"è negativo\",\n    \"MATH_IS_DIVISIBLE_BY\": \"è divisibile per\",\n    \"MATH_IS_TOOLTIP\": \"Verifica se un numero è pari, dispari, primo, intero, positivo, negativo o se è divisibile per un certo numero. Restituisce vero o falso.\",\n    \"MATH_CHANGE_HELPURL\": \"https://it.wikipedia.org/wiki/Addizione\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"cambia\",\n    \"MATH_CHANGE_INPUT_BY\": \"di\",\n    \"MATH_CHANGE_TOOLTIP\": \"Aggiunge un numero alla variabile '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://it.wikipedia.org/wiki/Arrotondamento\",\n    \"MATH_ROUND_TOOLTIP\": \"Arrotonda un numero verso l'alto o verso il basso.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"arrotonda\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"arrotonda verso l'alto\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"arrotonda verso il basso\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"somma la lista\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Restituisce la somma si tutti i numeri nella lista.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"minimo della lista\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Restituisce il più piccolo numero della lista.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"massimo della lista\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Restituisce il più grande numero della lista.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"media della lista\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Restituisce la media (media aritmetica) dei valori numerici nella lista.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mediana della lista\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Restituisce il valore mediano della lista.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"mode della lista\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Restituisce una lista degli elementi più frequenti nella lista.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"deviazione standard della lista\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Restituisce la deviazione standard della lista.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"elemento casuale della lista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Restituisce un elemento casuale della lista.\",\n    \"MATH_MODULO_HELPURL\": \"https://it.wikipedia.org/wiki/Resto\",\n    \"MATH_MODULO_TITLE\": \"resto di %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Restituisce il resto della divisione di due numeri.\",\n    \"MATH_CONSTRAIN_TITLE\": \"costringi %1 da %2 a %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Costringe un numero all'interno dei limiti indicati (compresi).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://it.wikipedia.org/wiki/Numeri_pseudo-casuali\",\n    \"MATH_RANDOM_INT_TITLE\": \"intero casuale da %1 a %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Restituisce un numero intero casuale compreso tra i due limiti indicati (inclusi).\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://it.wikipedia.org/wiki/Numeri_pseudo-casuali\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"frazione casuale\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Restituisce una frazione compresa fra 0.0 (incluso) e 1.0 (escluso).\",\n    \"TEXT_TEXT_HELPURL\": \"https://it.wikipedia.org/wiki/Stringa_(informatica)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Una lettera, una parola o una linea di testo.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"crea testo con\",\n    \"TEXT_JOIN_TOOLTIP\": \"Crea un blocco di testo unendo un certo numero di elementi.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"unisci\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Aggiungi, rimuovi o riordina le sezioni per riconfigurare questo blocco testo.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Aggiungi un elemento al testo.\",\n    \"TEXT_APPEND_TO\": \"a\",\n    \"TEXT_APPEND_APPENDTEXT\": \"aggiungi il testo\",\n    \"TEXT_APPEND_TOOLTIP\": \"Aggiunge del testo alla variabile '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"lunghezza di %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Restituisce il numero di lettere (inclusi gli spazi) nel testo fornito.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 è vuoto\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Restituisce vero se il testo fornito è vuoto.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Restituisce l'indice della prima occorrenza del primo testo all'interno del secondo testo. Restituisce 0 se il testo non viene trovato.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"nel testo\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"trova la prima occorrenza del testo\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"trova l'ultima occorrenza del testo\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"nel testo\",\n    \"TEXT_CHARAT_FROM_START\": \"prendi la lettera #\",\n    \"TEXT_CHARAT_FROM_END\": \"prendi la lettera # dalla fine\",\n    \"TEXT_CHARAT_FIRST\": \"prendi la prima lettera\",\n    \"TEXT_CHARAT_LAST\": \"prendi l'ultima lettera\",\n    \"TEXT_CHARAT_RANDOM\": \"prendi lettera casuale\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Restituisce la lettera nella posizione indicata.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Restituisce la porzione di testo indicata.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"nel testo\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"prendi sotto-stringa dalla lettera #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"prendi sotto-stringa dalla lettera # dalla fine\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"prendi sotto-stringa dalla prima lettera\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"alla lettera #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"alla lettera # dalla fine\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"all'ultima lettera\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Restituisce una copia del testo in un diverso formato maiuscole/minuscole.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"in MAIUSCOLO\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"in minuscolo\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"con Iniziali Maiuscole\",\n    \"TEXT_TRIM_TOOLTIP\": \"Restituisce una copia del testo con gli spazi rimossi ad uno o entrambe le estremità.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"rimuovi spazi da entrambi gli estremi\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"rimuovi spazi a sinistra\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"rimuovi spazi a destra\",\n    \"TEXT_PRINT_TITLE\": \"scrivi %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Scrive il testo, numero o altro valore indicato.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"richiedi testo con messaggio\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"richiedi numero con messaggio\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Richiedi un numero all'utente.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Richiede del testo da parte dell'utente.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"crea lista vuota\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Restituisce una lista, di lunghezza 0, contenente nessun record di dati\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Crea una lista con un certo numero di elementi.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"crea lista con\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Aggiungi, rimuovi o riordina le sezioni per riconfigurare il blocco lista.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Aggiunge un elemento alla lista.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Crea una lista costituita dal valore indicato ripetuto per il numero di volte specificato.\",\n    \"LISTS_REPEAT_TITLE\": \"crea una lista con l'elemento %1 ripetuto %2 volte\",\n    \"LISTS_LENGTH_TITLE\": \"lunghezza di %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Restituisce la lunghezza della lista\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 è vuota\",\n    \"LISTS_TOOLTIP\": \"Restituisce vero se la lista è vuota.\",\n    \"LISTS_INLIST\": \"nella lista\",\n    \"LISTS_INDEX_OF_FIRST\": \"trova la prima occorrenza dell'elemento\",\n    \"LISTS_INDEX_OF_LAST\": \"trova l'ultima occorrenza dell'elemento\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Restituisce l'indice della prima/ultima occorrenza dell'elemento nella lista. Restituisce 0 se il testo non viene trovato.\",\n    \"LISTS_GET_INDEX_GET\": \"prendi\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"prendi e rimuovi\",\n    \"LISTS_GET_INDEX_REMOVE\": \"rimuovi\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# dalla fine\",\n    \"LISTS_GET_INDEX_FIRST\": \"primo\",\n    \"LISTS_GET_INDEX_LAST\": \"ultimo\",\n    \"LISTS_GET_INDEX_RANDOM\": \"casuale\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Restituisce l'elemento nella posizione indicata della lista. 1 corrisponde al primo elemento della lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Restituisce l'elemento nella posizione indicata della lista. 1 corrisponde all'ultimo elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Restituisce il primo elemento in una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Restituisce l'ultimo elemento in una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Restituisce un elemento casuale in una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Rimuove e restituisce l'elemento nella posizione indicata in una lista. 1 corrisponde al primo elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Rimuove e restituisce l'elemento nella posizione indicata in una lista. 1 corrisponde all'ultimo elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Rimuove e restituisce il primo elemento in una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Restituisce e rimuove l'ultimo elemento in una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Restituisce e rimuove un elemento casuale in una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Rimuove l'elemento nella posizione indicata in una lista. 1 corrisponde al primo elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Rimuove l'elemento nella posizione indicata in una lista. 1 corrisponde all'ultimo elemento.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Rimuove il primo elemento in una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Rimuove l'ultimo elemento in una lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Rimuove un elemento casuale in una lista.\",\n    \"LISTS_SET_INDEX_SET\": \"imposta\",\n    \"LISTS_SET_INDEX_INSERT\": \"inserisci in\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"come\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Imposta l'elemento nella posizione indicata di una lista. 1 corrisponde al primo elemento.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Imposta l'elemento nella posizione indicata di una lista. 1 corrisponde all'ultimo elemento.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Imposta il primo elemento in una lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Imposta l'ultimo elemento in una lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Imposta un elemento casuale in una lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Inserisci un elemento nella posizione indicata in una lista. #1 corrisponde al primo elemento.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Inserisci l'elemento nella posizione indicata in una lista. #1 corrisponde all'ultimo elemento.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Inserisci l'elemento all'inizio della lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Aggiungi un elemento alla fine di una lista\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Inserisce l'elemento casualmente in una lista.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"prendi sotto-lista da #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"prendi sotto-lista da # dalla fine\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"prendi sotto-lista dall'inizio\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"fino a #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"da # dalla fine\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"dagli ultimi\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Crea una copia della porzione specificata di una lista.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Restituisce il valore di una variabile.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Crea 'imposta %1'\",\n    \"VARIABLES_SET_TITLE\": \"imposta\",\n    \"VARIABLES_SET_TAIL\": \"a\",\n    \"VARIABLES_SET_TOOLTIP\": \"Imposta questa variabile ad essere pari all'input.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Crea 'prendi %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"per\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"fai qualcosa\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"conː\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Crea una funzione senza output.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"ritorna\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Crea una funzione con un output.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Attenzioneː Questa funzione ha parametri duplicati.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://it.wikipedia.org/wiki/Funzione_(informatica)\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Esegue la funzione definita dall'utente '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://it.wikipedia.org/wiki/Funzione_(informatica)\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Esegue la funzione definita dall'utente '%1' ed usa il suo output.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"input\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nome inputː\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Evidenzia definizione di funzione\",\n    \"PROCEDURES_CREATE_DO\": \"Crea '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Se un valore è vero allora restituisce un secondo valore.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Attenzioneː Questo blocco può essere usato solo all'interno di una definizione di funzione.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/ja.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Shirayuki\",\n            \"Oda\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"項目\",\n    \"DUPLICATE_BLOCK\": \"複製\",\n    \"ADD_COMMENT\": \"コメントを追加\",\n    \"REMOVE_COMMENT\": \"コメントを削除します。\",\n    \"EXTERNAL_INPUTS\": \"外部入力\",\n    \"INLINE_INPUTS\": \"インライン入力\",\n    \"DELETE_BLOCK\": \"ブロックを消す\",\n    \"DELETE_X_BLOCKS\": \"%1 個のブロックを消す\",\n    \"COLLAPSE_BLOCK\": \"ブロックを折りたたむ\",\n    \"COLLAPSE_ALL\": \"ブロックを折りたたむ\",\n    \"EXPAND_BLOCK\": \"ブロックを展開します。\",\n    \"EXPAND_ALL\": \"ブロックを展開します。\",\n    \"DISABLE_BLOCK\": \"ブロックを無効にします。\",\n    \"ENABLE_BLOCK\": \"ブロックを有効にします。\",\n    \"HELP\": \"ヘルプ\",\n    \"CHANGE_VALUE_TITLE\": \"値を変更します。\",\n    \"NEW_VARIABLE\": \"新しい変数\",\n    \"NEW_VARIABLE_TITLE\": \"新しい変数の、名前\",\n    \"RENAME_VARIABLE\": \"変数の名前を変更.\",\n    \"RENAME_VARIABLE_TITLE\": \"%1の変数すべてを名前変更します。\",\n    \"COLOUR_PICKER_HELPURL\": \"https://ja.wikipedia.org/wiki/色\",\n    \"COLOUR_PICKER_TOOLTIP\": \"パレットから色を選んでください。\",\n    \"COLOUR_RANDOM_TITLE\": \"ランダムな色\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"ランダムな色を選択します。\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"カラーと\",\n    \"COLOUR_RGB_RED\": \"赤\",\n    \"COLOUR_RGB_GREEN\": \"緑\",\n    \"COLOUR_RGB_BLUE\": \"青\",\n    \"COLOUR_RGB_TOOLTIP\": \"赤、緑、および青の指定された量で色を作成します。すべての値は 0 ～ 100 の間でなければなりません。\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"ブレンド\",\n    \"COLOUR_BLEND_COLOUR1\": \"色 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"色 2\",\n    \"COLOUR_BLEND_RATIO\": \"割合\",\n    \"COLOUR_BLEND_TOOLTIP\": \"ブレンド2 つの色を指定された比率に混ぜる」  (0.0 ～ 1.0)。\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://ja.wikipedia.org/wiki/for文\",\n    \"CONTROLS_REPEAT_TITLE\": \"%1 回、繰り返します\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"繰り返し\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"回\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"してください\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"いくつかのステートメントを数回行います。\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"つつその間、繰り返す4\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"までを繰り返します\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"値は true のあいだ、いくつかのステートメントを行います。\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"値は false のあいだ、いくつかのステートメントを行います。\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"変数 %1は、指定した間隔ごとのカウントを開始番号から 終了番号まで、値をとり、指定したブロックを行う必要があります。\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"で、カウントします。\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"%1 から%2、 %3 で\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"各項目の\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"リストで\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"リストの各項目に対して変数 '%1' のアイテムに設定し、いくつかのステートメントをしてください。\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"ループから抜け出す\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"ループの次の反復処理を続行します。\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"含むループから抜け出します。\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"このループの残りの部分をスキップし、次のイテレーションに進みます。\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"注意: このブロックは、ループ内でのみ使用します。\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"値が true の場合はその後ステートメントを行をいくつかします。\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"値が true 場合は、ステートメントの最初のブロックを行います。それ以外の場合は、ステートメントの 2 番目のブロックを行います。\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"最初の値が true 場合は、ステートメントの最初のブロックを行います。それ以外の場合は、2 番目の値が true の場合、ステートメントの 2 番目のブロックをします。\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"最初の値が true 場合は、ステートメントの最初のブロックを行います。2 番目の値が true の場合は、ステートメントの 2 番目のブロックを行います。それ以外の場合は最後のブロックのステートメントを行います。\",\n    \"CONTROLS_IF_MSG_IF\": \"もし\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"他でもし\",\n    \"CONTROLS_IF_MSG_ELSE\": \"他\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"追加、削除、またはセクションを順序変更して、ブロックをこれを再構成します。\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"場合に条件にブロック追加。\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Ifブロックに、すべてをキャッチする条件を追加。\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://ja.wikipedia.org/wiki/不等式\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"もし両方がお互いに等しく入力した場合は true を返します。\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"両方の入力が互いに等しくない場合に true を返します。\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"最初の入力が 2 番目の入力よりも小さいい場合は true を返します。\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"もし、最初の入力が二つ目入力より少ないか、おなじであったらTRUEをかえしてください\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"最初の入力が 2 番目の入力よりも大きい場合は true を返します。\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"もし入力がふたつめの入よりも大きかったらtrueをり返します。\",\n    \"LOGIC_OPERATION_HELPURL\": \"https://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"両方の入力がおんなじ場わいわtrue を返します。\",\n    \"LOGIC_OPERATION_AND\": \"そして\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"最低少なくとも 1 つの入力が true の場合は true を返します。\",\n    \"LOGIC_OPERATION_OR\": \"または\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"%1 ではないです。\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"入力が false の場合は、true を返します。入力が true の場合は false を返します。\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"true\",\n    \"LOGIC_BOOLEAN_FALSE\": \"false\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"True または false を返します。\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"Null を返します。\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://ja.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"テスト\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"true の場合\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"false の場合\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"'テスト' の条件をチェックします。条件が true の場合、'true' の値を返します。それ以外の場合 'false' のを返します。\",\n    \"MATH_NUMBER_HELPURL\": \"https://ja.wikipedia.org/wiki/数\",\n    \"MATH_NUMBER_TOOLTIP\": \"数です。\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://ja.wikipedia.org/wiki/算術\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"2 つの数の合計を返します。\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"2 つの数の差を返します。\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"2 つの数の積を返します。\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"2 つの数の商を返します。\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"最初の数を2 番目の値で累乗した結果を返します。\",\n    \"MATH_SINGLE_HELPURL\": \"https://ja.wikipedia.org/wiki/平方根\",\n    \"MATH_SINGLE_OP_ROOT\": \"平方根\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"平方根を返す\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"絶対値\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"絶対値を返す\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"負の数を返す\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"数値の自然対数をかえしてください\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"log 10 を返す。\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"数値の e 粂を返す\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"１０の　x　乗\",\n    \"MATH_TRIG_HELPURL\": \"https://ja.wikipedia.org/wiki/三角関数\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"番号のsineの次数を返す\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"番号のcosineの次数を返す\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"番号のtangentの次数を返す\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"番号のarcsine を返すます\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"arccosine の値を返す\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"番号のarctangent を返すます\",\n    \"MATH_CONSTANT_HELPURL\": \"https://ja.wikipedia.org/wiki/数学定数\",\n    \"MATH_CONSTANT_TOOLTIP\": \"いずれかの共通の定数のを返す: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (無限).\",\n    \"MATH_IS_EVEN\": \"わ偶数\",\n    \"MATH_IS_ODD\": \"奇数です。\",\n    \"MATH_IS_PRIME\": \"素数です\",\n    \"MATH_IS_WHOLE\": \"は整数\",\n    \"MATH_IS_POSITIVE\": \"正の値\",\n    \"MATH_IS_NEGATIVE\": \"負の値\",\n    \"MATH_IS_DIVISIBLE_BY\": \"割り切れる\",\n    \"MATH_IS_TOOLTIP\": \"数字が、偶数、奇数、素数、整数、正数、負数、またはそれが特定の数で割り切れる場合かどうかを確認してください。どの制限が一つでも本当でしたら true をかえしてください、そうでない場合わ falseを返してください。\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"変更\",\n    \"MATH_CHANGE_INPUT_BY\": \"に\",\n    \"MATH_CHANGE_TOOLTIP\": \"'%1' をたします。\",\n    \"MATH_ROUND_HELPURL\": \"https://ja.wikipedia.org/wiki/端数処理\",\n    \"MATH_ROUND_TOOLTIP\": \"数値を切り上げるか切り捨てる\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"概数\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"数値を切り上げ\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"端数を切り捨てる\",\n    \"MATH_ONLIST_HELPURL\": \"\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"リストの合計\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"全部リストの数をたして返す\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"リストの最小の数\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"リストの最小数を返します。\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"リストの最大値\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"リストの最大数を返します。\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"リストの平均\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"リストの数値の平均 (算術平均) を返します。\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"リストの中央値\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"リストの中央値の数を返します。\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"一覧モード\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"リストで最も一般的な項目のリストを返します。\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"リストの標準偏差\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"リウトの標準偏差をかえす\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"リストのランダム アイテム\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"リストからランダムに要素を返します。\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"残りの %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"2 つの数値を除算した残りを返します。\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"制限%1下リミット%2上限リミット%3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"値を、上限 x と下限 y のあいだに制限んする（上限と下限が、x と  y　とに同じ場合わ、上限の値は　x, 下限の値はy）。\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"%1 から %2 への無作為の整数\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"指定した下限の間、無作為なランダムな整数を返します。\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"ランダムな分数\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"ランダムな分数を返すー0.0 (包括) の間のと 1.0 (排他的な)。\",\n    \"TEXT_TEXT_HELPURL\": \"https://ja.wikipedia.org/wiki/文字列\",\n    \"TEXT_TEXT_TOOLTIP\": \"文字、単語、または行のテキスト。\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"テキストを作成します。\",\n    \"TEXT_JOIN_TOOLTIP\": \"任意の数の項目一部を一緒に接合してテキストの作成します。\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"結合\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"追加、削除、またはセクションを順序変更して、ブロックを再構成します。\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"テキスト をアイテム追加します。\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"宛先\",\n    \"TEXT_APPEND_APPENDTEXT\": \"テキストを追加します。\",\n    \"TEXT_APPEND_TOOLTIP\": \"変数 '%1' にいくつかのテキストを追加します。\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"%1 の長さ\",\n    \"TEXT_LENGTH_TOOLTIP\": \"指定されたテキストの文字 (スペースを含む) の数を返します。\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 が空\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"指定されたテキストが空の場合は、true を返します。\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"最初のテキストの二番目のてきすとの、最初と最後の、出現したインデックスをかえします。テキストが見つからない場合は 0 を返します。\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"テキストで\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"テキストの最初の出現箇所を検索します。\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"テキストの最後に見つかったを検索します。\",\n    \"TEXT_INDEXOF_TAIL\": \"\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"テキストで\",\n    \"TEXT_CHARAT_FROM_START\": \"文字# を取得\",\n    \"TEXT_CHARAT_FROM_END\": \"一番最後の言葉、キャラクターを所得\",\n    \"TEXT_CHARAT_FIRST\": \"最初の文字を得る\",\n    \"TEXT_CHARAT_LAST\": \"最後の文字を得る\",\n    \"TEXT_CHARAT_RANDOM\": \"ランダムな文字を得る\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"指定された位置に文字を返します。\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"テキストの指定部分を返します。\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"テキストで\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"文字列からの部分文字列を取得 ＃\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"部分文字列を取得する #端から得る\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"部分文字列を取得する。\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"# の文字\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"文字列の＃ 終わりからの＃\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"最後のの文字\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"別のケースに、テキストのコピーを返します。\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"大文字に変換する\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"小文字に\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"タイトル ケースに\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"スペースを 1 つまたは両方の端から削除したのち、テキストのコピーを返します。\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"両端のスペースを取り除く\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"左端のスペースを取り除く\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"右端のスペースを取り除く\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"%1 を印刷します。\",\n    \"TEXT_PRINT_TOOLTIP\": \"指定したテキスト、番号または他の値を印刷します。\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"メッセージをプロンプトしてにテキストを求める\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"メッセージを送って番号の入力を求める\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"ユーザーにプロンプトして数字のインプットを求めます\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"いくつかのテキストを、ユーザーに入力するようにプロンプト。\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"空のリストを作成します。\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"長さゼロ、データ レコード空のリストを返します\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"アイテム数かぎりないのリストを作成します。\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"これを使ってリストを作成します。\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"リスト\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"追加、削除、またはセクションを順序変更して、ブロックを再構成します。\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"リストにアイテムを追加します。\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"指定された値をなんどか繰り返してリストを作ります。\",\n    \"LISTS_REPEAT_TITLE\": \"アイテム %1 と一緒にリストを作成し %2 回繰り\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \" %1の長さ\",\n    \"LISTS_LENGTH_TOOLTIP\": \"リストの長さを返します。\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 が空\",\n    \"LISTS_TOOLTIP\": \"リストが空の場合は、true を返します。\",\n    \"LISTS_INLIST\": \"リストで\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"最初に見つかった項目を検索します。\",\n    \"LISTS_INDEX_OF_LAST\": \"最後に見つかったアイテムを見つける\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"リスト項目の最初/最後に出現するインデックス位置を返します。テキストが見つからない場合は 0 を返します。\",\n    \"LISTS_GET_INDEX_GET\": \"取得\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"取得と削除\",\n    \"LISTS_GET_INDEX_REMOVE\": \"削除\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"終しまいから #\",\n    \"LISTS_GET_INDEX_FIRST\": \"最初\",\n    \"LISTS_GET_INDEX_LAST\": \"最後\",\n    \"LISTS_GET_INDEX_RANDOM\": \"ランダム\",\n    \"LISTS_GET_INDEX_TAIL\": \"\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"リスト内の指定位置にある項目を返します。＃ 1 は、最初の項目です。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"リスト内の指定位置にある項目を返します。＃ 1 は、最後の項目です。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"リストの最初の項目を返信します。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"リストの最後の項目を返します。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"ランダム アイテム リストを返します。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"リスト内の指定位置にある項目を削除し、返します。＃ 1 は、最後の項目です。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"リスト内の指定位置にある項目を削除し、返します。＃ 1 は、最後の項目です。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"リスト内の最初の項目を削除したあと返します。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"リスト内の最後の項目を削除したあと返します。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"リストのランダムなアイテムを削除し、返します。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"リスト内の指定位置にある項目を返します。＃ 1 は、最初の項目です。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"リスト内の指定位置にある項目を削除します。＃ 1 は、最後の項目です。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"リスト内の最初の項目を削除します。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"リスト内の最後の項目を削除します。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"リスト内にある任意のアイテムを削除します。\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"セット\",\n    \"LISTS_SET_INDEX_INSERT\": \"挿入します。\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"として\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"リスト内の指定された位置に項目を設定します。＃ 1 は、最初の項目です。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"リスト内の指定された位置に項目を設定します。＃ 1 は、最後の項目です。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"リスト内に最初の項目を設定します。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"リスト内の最後の項目を設定します。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"リスト内にランダムなアイテムを設定します。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"リスト内の指定位置に項目を挿入します。＃ 1 は、最初の項目です。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"リスト内の指定位置に項目を挿入します。＃ 1 は、最後の項目です。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"リストの先頭に項目を挿入します。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"リストの末尾に項目を追加します。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"リストに項目をランダムに挿入します。\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"# からサブディレクトリのリストを取得します。\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"端から #のサブリストを取得します。\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"最初からサブリストを取得する。\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"＃へ\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"最後から＃へ\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"最後へ\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"リストの指定された部分のコピーを作成してくださ。\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"\",\n    \"VARIABLES_GET_HELPURL\": \"https://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"この変数の値を返します。\",\n    \"VARIABLES_GET_CREATE_SET\": \"'セット%1を作成します。\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"セット\",\n    \"VARIABLES_SET_TAIL\": \"宛先\",\n    \"VARIABLES_SET_TOOLTIP\": \"この入力を変数と等しくなるように設定します。\",\n    \"VARIABLES_SET_CREATE_GET\": \"'%1 を取得' を作成します。\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://ja.wikipedia.org/wiki/サブルーチン\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"宛先\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"何かしてください\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"で。\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"出力なしで関数を作成します。\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://ja.wikipedia.org/wiki/サブルーチン\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"返す\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"出力を持つ関数を作成します。\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"警告: この関数は、重複するパラメーターがあります。\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://ja.wikipedia.org/wiki/サブルーチン\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"ユーザー定義関数 '%1' を実行します。\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://ja.wikipedia.org/wiki/サブルーチン\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"ユーザー定義関数 '%1' を実行し、その出力を使用します。\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"入力\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"入力名:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"関数の内容を強調表示します。\",\n    \"PROCEDURES_CREATE_DO\": \"%1をつくる\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"1番目値が true の場合、2 番目の値を返します。\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"警告: このブロックは、関数定義内でのみ使用できます。\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/keys.json",
    "content": "{\n"
  },
  {
    "path": "extern/blockly/msg/json/ko.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Hym411\",\n            \"아라\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"항목\",\n    \"DUPLICATE_BLOCK\": \"블록 복사 & 붙여넣기\",\n    \"ADD_COMMENT\": \"덧글 추가\",\n    \"REMOVE_COMMENT\": \"내용 제거\",\n    \"EXTERNAL_INPUTS\": \"외부 입력\",\n    \"INLINE_INPUTS\": \"내부 입력\",\n    \"DELETE_BLOCK\": \"블록 삭제\",\n    \"DELETE_X_BLOCKS\": \"블록 삭제\",\n    \"COLLAPSE_BLOCK\": \"블록 축소\",\n    \"COLLAPSE_ALL\": \"블록 축소\",\n    \"EXPAND_BLOCK\": \"블록 확장\",\n    \"EXPAND_ALL\": \"블록 확장\",\n    \"DISABLE_BLOCK\": \"블록 비활성화\",\n    \"ENABLE_BLOCK\": \"블록 활성화\",\n    \"HELP\": \"도움말\",\n    \"CHANGE_VALUE_TITLE\": \"값 변경:\",\n    \"NEW_VARIABLE\": \"새 변수\",\n    \"NEW_VARIABLE_TITLE\": \"새 변수 이름:\",\n    \"RENAME_VARIABLE\": \"변수 이름 바꾸기:\",\n    \"RENAME_VARIABLE_TITLE\": \"'%1' 변수 이름을 바꾸기:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://ko.wikipedia.org/wiki/색\",\n    \"COLOUR_PICKER_TOOLTIP\": \"팔레트에서 색을 고릅니다\",\n    \"COLOUR_RANDOM_TITLE\": \"임의 색상\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"무작위로 색을 고릅니다.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"RGB 색\",\n    \"COLOUR_RGB_RED\": \"빨강\",\n    \"COLOUR_RGB_GREEN\": \"초록\",\n    \"COLOUR_RGB_BLUE\": \"파랑\",\n    \"COLOUR_RGB_TOOLTIP\": \"빨강,파랑,초록의 값을 이용하여 색을 만드십시오. 모든 값은 0과 100 사이에 있어야 합니다.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"혼합\",\n    \"COLOUR_BLEND_COLOUR1\": \"색 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"색 2\",\n    \"COLOUR_BLEND_RATIO\": \"비율\",\n    \"COLOUR_BLEND_TOOLTIP\": \"두 색을 주어진 비율로 혼합 (0.0 - 1.0)\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://ko.wikipedia.org/wiki/For_루프\",\n    \"CONTROLS_REPEAT_TITLE\": \"%1회 반복\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"반복\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"회\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"하기\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"여러 번 반복해 명령들을 실행합니다.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"동안 반복\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"다음까지 반복\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"값이 참일 때, 몇가지 선언을 합니다.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"값이 거짓일 때, 몇가지 선언을 합니다.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"변수 %1 의 값을 변경하면서 반복 실행합니다. 변수에 저장되는 값은, 첫번째 수부터 두번째 수까지, 일정 값씩 늘어납니다.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"으로 계산\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"%1에서 %3을 이용하여 %2로\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"각 항목에 대해\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"목록으로\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"리스트 안에 들어있는 각 아이템들을, 순서대로 변수 '%1' 에 한 번씩 저장시키고, 그 때 마다 명령을 실행합니다.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"반복 중단\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"다음 반복\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"현재 반복 실행 블록을, 빠져나갑니다.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"나머지 반복 부분을 더이상 실행하지 않고, 다음 반복을 수행합니다.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"경고 : 이 블록은 반복 실행 블록 안에서만 사용됩니다.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"조건식의 계산 결과가 참이면, 명령을 실행합니다.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"조건식의 계산 결과가 참이면, 첫번째 블록의 명령을 실행하고, 그렇지 않으면 두번째 블록의 명령을 실행합니다.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"첫번째 조건식의 계산 결과가 참이면, 첫번째 블록의 명령을 실행하고, 두번째 조건식의 계산 결과가 참이면, 두번째 블록의 명령을 실행합니다.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"첫번째 조건식의 계산 결과가 참이면, 첫번째 블록의 명령을 실행하고, 두번째 조건식의 계산 결과가 참이면, 두번째 블록의 명령을 실행하고, ... , 어떤 조건식의 계산 결과도 참이 아니면, 마지막 블록의 명령을 실행합니다.\",\n    \"CONTROLS_IF_MSG_IF\": \"만약에\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"다른 경우\",\n    \"CONTROLS_IF_MSG_ELSE\": \"아니라면\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"\\\"만약\\\" 블록의 내용을 추가, 삭제, 재구성 합니다.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"\\\"만약\\\" 블록에 조건 검사를 추가합니다.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"\\\"만약\\\" 블록의 마지막에, 모든 검사 결과가 거짓인 경우 실행할 부분을 추가합니다.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"두 값이 같으면, 참(true) 값을 돌려줍니다.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"두 값이 서로 다르면, 참(true) 값을 돌려줍니다.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"첫 번째 값이 두 번째 값보다 작으면, 참(true) 값을 돌려줍니다.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"첫 번째 값이 두 번째 값보다 작거나 같으면, 참(true) 값을 돌려줍니다.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"첫 번째 값이 두 번째 값보다 크면, 참(true) 값을 돌려줍니다.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"첫 번째 값이 두 번째 값보다 크거나 같으면, 참(true) 값을 돌려줍니다.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"두 값이 모두 참(true) 값이면, 참 값을 돌려줍니다.\",\n    \"LOGIC_OPERATION_AND\": \"그리고\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"적어도 하나의 값이 참일 경우 참을 반환합니다.\",\n    \"LOGIC_OPERATION_OR\": \"또는\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"%1 의 반대\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"입력값이 거짓이라면 참을 반환합니다. 참이라면 거짓을 반환합니다.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"참\",\n    \"LOGIC_BOOLEAN_FALSE\": \"거짓\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"참 혹은 거짓 모두 반환합니다.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"빈 값\",\n    \"LOGIC_NULL_TOOLTIP\": \"빈 값을 반환합니다.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"테스트\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"만약 참이라면\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"만약 거짓이라면\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"'검사' 를 진행해, 결과가 참(true)이면 '참이면' 부분의 값을 돌려줍니다. ; 결과가 참이 아니면, '거짓이면' 부분의 값을 돌려줍니다.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"수\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"x\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"두 수의 합을 반환합니다.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"두 수간의 차이를 반환합니다.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"두 수의 곱을 반환합니다.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"두 수의 나눈 결과를 반환합니다.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"첫 번째 수를 두 번째 수 만큼, 거듭제곱 한 결괏값을 돌려줍니다.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"제곱근\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"숫자의 제곱근을 반환합니다.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"절대값\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"어떤 수의 절대값(absolute)을 계산한 결과를, 정수값으로 돌려줍니다.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"음(-)/양(+), 부호를 반대로 하여 값을 돌려줍니다.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"어떤 수의, 자연로그(natural logarithm) 값을 돌려줍니다.(밑 e, 예시 log e x)\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"어떤 수의, 기본로그(logarithm) 값을 돌려줍니다.(밑 10, 예시 log 10 x)\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"e 의, 거듭제곱(power) 값을 돌려줍니다.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"10 의, 거듭제곱(power) 값을 돌려줍니다.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"어떤 각도(degree, radian 아님)의, sin(sine) 값을 계산해 돌려줍니다.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"어떤 각도(degree, radian 아님)의, cos(cosine) 값을 계산해 돌려줍니다.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"어떤 각도(degree, radian 아님)의,  tan(tangent) 값을 계산해 돌려줍니다.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"어떤 수에 대한, asin(arcsine) 값을 돌려줍니다.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"어떤 수에 대한, acos(arccosine) 값을 돌려줍니다.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"어떤 수에 대한, atan(arctangent) 값을 돌려줍니다.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"일반적인 상수 값들 중 하나를 돌려줍니다. : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"가 짝수(even) 이면\",\n    \"MATH_IS_ODD\": \"가 홀수(odd) 이면\",\n    \"MATH_IS_PRIME\": \"가 소수(prime) 이면\",\n    \"MATH_IS_WHOLE\": \"가 정수이면\",\n    \"MATH_IS_POSITIVE\": \"가 양(+)수 이면\",\n    \"MATH_IS_NEGATIVE\": \"가 음(-)수 이면\",\n    \"MATH_IS_DIVISIBLE_BY\": \"가 다음 수로 나누어 떨어지면 :\",\n    \"MATH_IS_TOOLTIP\": \"어떤 수가 짝 수, 홀 수, 소 수, 정 수, 양 수, 음 수, 나누어 떨어지는 수 인지 검사해 결괏값을 돌려줍니다. 참(true) 또는 거짓(false) 값을 돌려줌.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"값 변경\",\n    \"MATH_CHANGE_INPUT_BY\": \"만큼\",\n    \"MATH_CHANGE_TOOLTIP\": \"변수 '%1' 에 저장되어있는 값에, 어떤 수를 더해, 변수에 다시 저장합니다.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"어떤 수를 반올림/올림/버림한 결과를, 정수값으로 돌려줍니다.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"반올림\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"올림\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"버림\",\n    \"MATH_ONLIST_HELPURL\": \"\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"합\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"리스트에 들어있는 수(값)들을, 모두 합(sum) 한, 총합(sum)을 돌려줍니다.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"최소값\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"리스트에 들어있는 수(값) 들 중, 가장 작은(min) 수(값)를 돌려줍니다.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"최대값\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"리스트에 들어있는 수(값) 들 중, 가장 큰(max) 수(값)를 돌려줍니다.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"평균값\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"리스트에 들어있는 수(값)들에 대해, 산술 평균(arithmetic mean) 한 값을 돌려줍니다.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"중간값\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"리스트에 들어있는 수(값) 들 중, 중간(median) 수(값)를 돌려줍니다.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"가장 여러 개 있는 값\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"리스트에 들어있는 아이템들 중에서, 가장 여러 번 들어있는 아이템들을 리스트로 만들어 돌려줍니다. (최빈값, modes)\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"표준 편차\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"리스트에 들어있는 수(값)들에 대해, 표준 편차(standard deviation) 를 구해 돌려줍니다.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"랜덤 아이템\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"리스트에 들어있는 아이템들 중에서, 랜덤(random)으로 아이템을 돌려줍니다.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"%1 를 %2 로 나눈 나머지\",\n    \"MATH_MODULO_TOOLTIP\": \"첫 번째 수를 두 번째 수로 나눈, 나머지 값을 돌려줍니다.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"%1 의 값을, 최소 %2 최대 %3 으로 조정\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"어떤 수를, 특정 범위의 값이 되도록 강제로 조정합니다.\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"랜덤정수(%1\\u003C= n \\u003C=%2)\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"주어진 범위에서, 랜덤 정수값을 돌려줍니다.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"랜덤 실수(0.0\\u003C= f \\u003C1.0)\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"랜덤 실수 값(0.0\\u003C= f \\u003C1.0)을 돌려줍니다.\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"문자, 단어, 문장.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"텍스트 만들기\",\n    \"TEXT_JOIN_TOOLTIP\": \"여러 개의 아이템들을 연결해(묶어), 새로운 문장을 만듭니다.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"가입\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"이 문장 블록의 구성을 추가, 삭제, 재구성 합니다.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"문장을 만들 조각 아이템\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"다음\",\n    \"TEXT_APPEND_APPENDTEXT\": \"내용 덧붙이기\",\n    \"TEXT_APPEND_TOOLTIP\": \"'%1' 의 마지막에 문장을 덧붙입니다.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"다음 문장의 문자 개수 %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"입력된 문장의, 문자 개수를 돌려줍니다.(공백문자 포함)\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1이 비어있습니다\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"입력된 문장이, 빈 문장(\\\"\\\")이면 참(true) 값을 돌려줍니다.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"어떤 문장이 가장 처음 나타난 위치 또는, 가장 마지막으로 나타난 위치를 찾아 돌려줍니다. 찾는 문장이 없는 경우는 0 값을 돌려줌.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"문장\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"에서 다음 문장이 처음으로 나타난 위치 찾기 :\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"에서 다음 문장이 마지막으로 나타난 위치 찾기 :\",\n    \"TEXT_INDEXOF_TAIL\": \"\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"문장\",\n    \"TEXT_CHARAT_FROM_START\": \"에서, 앞에서부터 # 번째 위치의 문자 얻기\",\n    \"TEXT_CHARAT_FROM_END\": \"에서, 마지막부터 # 번째 위치의 문자 얻기\",\n    \"TEXT_CHARAT_FIRST\": \"에서, 첫 번째 문자 얻기\",\n    \"TEXT_CHARAT_LAST\": \"에서, 마지막 문자 얻기\",\n    \"TEXT_CHARAT_RANDOM\": \"에서, 랜덤하게 한 문자 얻기\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"특정 번째 위치에서, 문자를 얻어내 돌려줍니다.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"문장 중 일부를 얻어내 돌려줍니다.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"문장\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"에서, 처음부터 # 번째 문자부터 얻어냄\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"에서, 마지막에서 # 번째부터 얻어냄\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"에서, 처음부터 얻어냄\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"# 번째 문자까지\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"끝에서부터 # 번째 문자까지\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"마지막 문자까지\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"영문 대소문자 형태를 변경해 돌려줍니다.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"대문자로\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"소문자로\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"첫 문자만 대문자로\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"문장의 왼쪽/오른쪽/양쪽에서 스페이스 문자를 제거해 돌려줍니다.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"다음 문장에서 양쪽(왼쪽+오른쪽) 공백문자(space) 제거 :\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"다음 문장에서 왼쪽 공백문자(space) 제거 :\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"다음 문장에서 오른쪽 공백문자(space) 제거 :\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"다음 내용 출력 %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"원하는 문장, 수, 값 등을 출력합니다.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"다음 안내 멘트를 활용해 문장 입력\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"다음 안내 멘트를 활용해 수 입력\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"수 입력 받음.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"문장 입력 받음.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"빈 리스트 생성\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"아이템이 없는, 빈 리스트를 만들어 돌려줍니다.\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"원하는 아이템 갯수로 리스트를 생성합니다.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"리스트 만들기\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"리스트\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"리스트 블록의 내용을 추가, 삭제, 재구성 합니다.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"아이템을 리스트에 추가합니다.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"원하는 값을, 원하는 갯수 만큼 넣어, 새로운 리스트를 생성합니다.\",\n    \"LISTS_REPEAT_TITLE\": \"%1 을 %2 번 넣어, 리스트 생성\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"%1의 길이\",\n    \"LISTS_LENGTH_TOOLTIP\": \"리스트에 포함되어있는, 아이템 갯수를 돌려줍니다.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1이 비어있습니다\",\n    \"LISTS_TOOLTIP\": \"목록이 비었을 때 참을 반환합니다.\",\n    \"LISTS_INLIST\": \"리스트\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"처음으로 나타난 위치\",\n    \"LISTS_INDEX_OF_LAST\": \"마지막으로 나타난 위치\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"아이템이 나타난, 처음 또는 마지막 위치를 찾아 돌려줍니다. 아이템이 없으면 0 돌려줌.\",\n    \"LISTS_GET_INDEX_GET\": \"아이템 가져오기\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"잘라 내기\",\n    \"LISTS_GET_INDEX_REMOVE\": \"삭제\",\n    \"LISTS_GET_INDEX_FROM_START\": \"첫번째 위치부터, # 번째\",\n    \"LISTS_GET_INDEX_FROM_END\": \"마지막 번째 위치부터, # 번째\",\n    \"LISTS_GET_INDEX_FIRST\": \"첫번째\",\n    \"LISTS_GET_INDEX_LAST\": \"마지막\",\n    \"LISTS_GET_INDEX_RANDOM\": \"임의로\",\n    \"LISTS_GET_INDEX_TAIL\": \"\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"특정 위치의 아이템을 찾아 돌려줍니다. #1 은 첫번째 아이템.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"특정 위치의 아이템을 찾아 돌려줍니다. #1 은 마지막 아이템.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"첫 번째 아이템을 찾아 돌려줍니다.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"마지막 아이템을 찾아 돌려줍니다.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"리스트의 아이템들 중, 랜덤으로 선택해 돌려줍니다.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"특정 위치의 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다. #1 는 첫번째 아이템.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"특정 위치의 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다. #1 는 마지막 아이템.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"첫 번째 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"마지막 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"랜덤 위치의 아이템을 찾아내 돌려주고,그 아이템을 리스트에서 삭제합니다.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"특정 위치의 아이템을 찾아내 삭제합니다. #1 는 첫번째 아이템.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"특정 위치의 아이템을 찾아내 삭제합니다. #1 는 마지막 아이템.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"리스트에서 첫 번째 아이템을 삭제합니다.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"리스트에서 마지막 아이템을 찾아 삭제합니다.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"리스트에서 랜덤하게 아이템을 삭제합니다.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"에서 설정\",\n    \"LISTS_SET_INDEX_INSERT\": \"에서 원하는 위치에 삽입\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"에\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"특정 번째 위치의 아이템으로 설정합니다. #1 는 첫번째 아이템.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"특정 번째 위치의 아이템으로 설정합니다. #1 는 마지막 아이템.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"첫 번째 위치의 아이템으로 설정합니다.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"마지막 아이템으로 설정합니다.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"랜덤 위치의 아이템으로 설정합니다.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"아이템을 리스트의 특정 위치에 삽입합니다. 첫번째 아이템은 #1.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"아이템을 리스트의 특정 위치에 삽입합니다. 마지막 아이템은 #1.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"아이템을 리스트의 첫번째 위치에 삽입합니다.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"리스트의 마지막에 아이템을 추가합니다.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"리스트의 랜덤 위치에 아이템을 삽입합니다.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"처음 # 번째 위치부터, 서브 리스트 추출\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"마지막부터 # 번째 위치부터, 서브 리스트 추출\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"첫 번째 위치부터, 서브 리스트 추출\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"앞에서부터 # 번째로\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"끝에서부터 # 번째로\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"마지막으로\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"특정 부분을 복사해 새로운 리스트로 생성합니다.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"변수에 저장 되어있는 값을 돌려줍니다.\",\n    \"VARIABLES_GET_CREATE_SET\": \"'집합 %1' 생성\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"값 변경:\",\n    \"VARIABLES_SET_TAIL\": \"를 다음 값으로 변경\",\n    \"VARIABLES_SET_TOOLTIP\": \"변수의 값을 입력한 값으로 변경해 줍니다.\",\n    \"VARIABLES_SET_CREATE_GET\": \"'%1 값 읽기' 블록 생성\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"함수\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"함수 이름\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"사용:\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"실행 후, 결과 값을 돌려주지 않는 함수를 만듭니다.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"다음을 돌려줌\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"실행 후, 결과 값을 돌려주는 함수를 만듭니다.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"경고: 이 함수에는, 같은 이름을 사용하는 매개 변수들이 있습니다.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"미리 정의해 둔 '%1' 함수를 실행합니다.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"미리 정의해 둔 '%1' 함수를 실행하고, 함수를 실행한 결과 값을 돌려줍니다.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"매개 변수들\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"매개 변수:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"함수 정의 찾기\",\n    \"PROCEDURES_CREATE_DO\": \"'%1' 생성\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"값이 참이라면, 두번째 값을 반환합니다.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"경고: 이 블록은, 함수 정의 블록 안에서만 사용할 수 있습니다.\",\n    \"CONTEXT_BLOCK_COPY\": \"블록 복사\",\n    \"CONTEXT_BLOCK_PASTE\": \"붙여넣기\"\n}\n"
  },
  {
    "path": "extern/blockly/msg/json/lrc.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Mogoeilor\"\n        ]\n    },\n    \"DUPLICATE_BLOCK\": \"کپی کردن\",\n    \"ADD_COMMENT\": \"نظرتونه اضاف بکید\",\n    \"REMOVE_COMMENT\": \"نظر جا وه جا کو\",\n    \"EXTERNAL_INPUTS\": \"داده یا وه دری\",\n    \"INLINE_INPUTS\": \"داده یا مئنجا\",\n    \"HELP\": \"هومياری\",\n    \"CHANGE_VALUE_TITLE\": \"ارزشت آلشت کو:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"یه رن د رنگ دو انتخاو بکید\",\n    \"COLOUR_RANDOM_TITLE\": \"رن بختکی\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"یه رنگ بختکی انتخاو بکید\",\n    \"COLOUR_RGB_TITLE\": \"رن وا\",\n    \"COLOUR_RGB_RED\": \"سور\",\n    \"COLOUR_RGB_GREEN\": \"سوز\",\n    \"COLOUR_RGB_BLUE\": \"آوی\",\n    \"COLOUR_BLEND_TITLE\": \"شیوسته\",\n    \"COLOUR_BLEND_COLOUR1\": \"رن 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"رن 2\",\n    \"COLOUR_BLEND_RATIO\": \"نسوت\",\n    \"COLOUR_BLEND_TOOLTIP\": \"هر کوم د رنگیانه وا نسوت دائه بیه به شیون(0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"%1 تکرار کو چن بار\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"د نو انجوم دئن\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"وختیا\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"انجوم بئه\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"تا تکرار کو\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"تا تکرار کو\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"اشماردن وا\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"سی هر قلم\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"د نوم گه\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"حلقه نه خراو کو\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"حلقه شومل بیه نه خراو کو\",\n    \"CONTROLS_IF_MSG_IF\": \"ار\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"هنی ار\",\n    \"CONTROLS_IF_MSG_ELSE\": \"هنی\",\n    \"LOGIC_OPERATION_AND\": \"و\",\n    \"LOGIC_OPERATION_OR\": \"یا\",\n    \"LOGIC_NEGATE_TITLE\": \"نه %1\",\n    \"LOGIC_BOOLEAN_TRUE\": \"راست و دوروست\",\n    \"LOGIC_BOOLEAN_FALSE\": \"غلط\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"هم غلط و هم راس ورگن\",\n    \"LOGIC_NULL\": \"خمثی\",\n    \"LOGIC_TERNARY_CONDITION\": \"آزماشت کردن\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"ار درس بی\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"ار غلط بی\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"یه شماره.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"وه انازه دو گل شماره ورگن.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"چارسوک ریشه\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"تموم و کمال\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_IS_EVEN\": \"همیشه هیئش\",\n    \"MATH_IS_ODD\": \"تهنائه\",\n    \"MATH_IS_WHOLE\": \"همشه\",\n    \"MATH_IS_POSITIVE\": \"مثبته\",\n    \"MATH_IS_NEGATIVE\": \"منفیه\",\n    \"MATH_IS_DIVISIBLE_BY\": \"یه وا بهر بیه\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"آلشت بكيد\",\n    \"MATH_CHANGE_INPUT_BY\": \"وا\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"گرد کردن\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"وه رو گرد کردن\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"وه هار گرد کردن\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"مینجاگه نوم گه\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"مینجا نوم گه\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"راس کردن متن وا\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"پیوسن\",\n    \"TEXT_APPEND_TO\": \"سی\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 حالیه\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"د متن\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"د متن\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"د متن\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"سی واج#\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"سی واج# تا آخر\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"سی آخرین واج\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"سی حرف گپ\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"سی واج کؤچک\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"یه گل نوم گه حالی راس بکیت\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"نوم گه\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 حالیه\",\n    \"LISTS_INLIST\": \"د نوم گه\",\n    \"LISTS_GET_INDEX_GET\": \"گرتن\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"گرتن و جاوه جا بیئن\",\n    \"LISTS_GET_INDEX_REMOVE\": \"ؤرداشتن\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# تا آخر\",\n    \"LISTS_GET_INDEX_FIRST\": \"اولی\",\n    \"LISTS_GET_INDEX_LAST\": \"آخر\",\n    \"LISTS_GET_INDEX_RANDOM\": \"بختكی\",\n    \"LISTS_SET_INDEX_INSERT\": \"بنه د\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"چی\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"سی#\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"سی آخر\",\n    \"VARIABLES_SET_TAIL\": \"سی\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"سی\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"وا:\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"ورگنیئن\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"داده یا\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"نوم داده:\",\n    \"PROCEDURES_CREATE_DO\": \"راس کردن%1\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/ms.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Anakmalaysia\",\n            \"Espertus\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"Perkara\",\n    \"DUPLICATE_BLOCK\": \"Pendua\",\n    \"ADD_COMMENT\": \"Berikan Komen\",\n    \"REMOVE_COMMENT\": \"Padamkan Komen\",\n    \"EXTERNAL_INPUTS\": \"Input Luaran\",\n    \"INLINE_INPUTS\": \"Input Sebaris\",\n    \"DELETE_BLOCK\": \"Hapuskan Blok\",\n    \"DELETE_X_BLOCKS\": \"Hapuskan %1 Blok\",\n    \"COLLAPSE_BLOCK\": \"Lipat Blok\",\n    \"COLLAPSE_ALL\": \"Lipat Blok²\",\n    \"EXPAND_BLOCK\": \"Buka Blok\",\n    \"EXPAND_ALL\": \"Buka Blok²\",\n    \"DISABLE_BLOCK\": \"Matikan Blok\",\n    \"ENABLE_BLOCK\": \"Hidupkan Blok\",\n    \"HELP\": \"Bantuan\",\n    \"CHANGE_VALUE_TITLE\": \"Ubah nilai:\",\n    \"NEW_VARIABLE\": \"Pembolehubah baru...\",\n    \"NEW_VARIABLE_TITLE\": \"Nama pembolehubah baru:\",\n    \"RENAME_VARIABLE\": \"Tukar nama pembolehubah...\",\n    \"RENAME_VARIABLE_TITLE\": \"Tukar nama semua pembolehubah '%1' kepada:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://ms.wikipedia.org/wiki/Warna\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Pilih satu warna daripada palet.\",\n    \"COLOUR_RANDOM_TITLE\": \"warna rawak\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Pilih satu warna secara rawak.\",\n    \"COLOUR_RGB_TITLE\": \"warnakan\",\n    \"COLOUR_RGB_RED\": \"merah\",\n    \"COLOUR_RGB_GREEN\": \"hijau\",\n    \"COLOUR_RGB_BLUE\": \"biru\",\n    \"COLOUR_RGB_TOOLTIP\": \"Peroleh satu warna dengan menentukan amaun campuran merah, hijau dan biru. Kesemua nilai haruslah antara 0 hingga 100.\",\n    \"COLOUR_BLEND_TITLE\": \"adun\",\n    \"COLOUR_BLEND_COLOUR1\": \"warna 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"warna 2\",\n    \"COLOUR_BLEND_RATIO\": \"nisbah\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Campurkan dua warna sekali pada nisbah yang ditentukan (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"ulang %1 kali\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"ulang\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"kali\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"lakukan\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Lakukan perintah berulang kali.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"ulangi apabila\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"ulangi sehingga\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Lakukan beberapa perintah apabila nilainya benar (true).\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Lakukan beberapa perintah apabila nilainya palsu (false).\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Gunakan pembolehubah %1 pada nilai-nilai dari nombor pangkal hingga nombor hujung, mengira mengikut selang yang ditentukan, dan lakukan blok-blok yang tertentu.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"kira dengan\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"dari %1 hingga %2 selang %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"untuk setiap perkara\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"dalam senarai\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Untuk setiap perkara dalam senarai, tetapkan pembolehubah '%1' pada perkara, kemudian lakukan beberapa perintah.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"Keluar daripada gelung lingkaran\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"Teruskan dengan pengulangan seterusnya gelung\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Pecahkan kandungan lingkaran.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Langkau seluruh gelung ini, dan teruskan dengan lelaran seterusnya.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Amaran: Blok ini hanya boleh digunakan dalam satu lingkaran.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Jika nilai yang benar, lakukan beberapa penyata.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Jika suatu nilai benar, lakukan penyata blok pertama.  Jika tidak, bina penyata blok kedua.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Jika nilai yang pertama adalah benar, lakukan penyata pertama blok.  Sebaliknya, jika nilai kedua adalah benar, lakukan penyata blok kedua.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Jika nilai yang pertama adalah benar, lakukan penyata blok pertama.  Sebaliknya, jika nilai kedua adalah benar, lakukan penyata blok kedua.  Jika tiada nilai adalah benar, lakukan penyata blok terakhir.\",\n    \"CONTROLS_IF_MSG_IF\": \"jika\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"lain jika\",\n    \"CONTROLS_IF_MSG_ELSE\": \"lain\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Tambah, alih keluar, atau susun semula bahagian-bahagian untuk menyusun semula blok jika.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Tambah satu syarat kepada blok jika.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Tambah yang terakhir, alihkan semua keadaan ke blok jika.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://id.wikipedia.org/wiki/Pertidaksamaan\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Kembali benar jika kedua-dua input benar antara satu sama lain.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Taip balik benar jika kedua-dua input tidak sama.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Kembali benar jika input pertama adalah lebih kecil daripada input kedua.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Kembali benar jika input pertama adalah lebih kecil daripada atau sama dengan input kedua.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Kembali benar jika input pertama adalah lebih besar daripada input kedua.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Kembali benar jika input pertama adalah lebih besar daripada atau sama dengan input kedua.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Return true if both inputs are true.\",\n    \"LOGIC_OPERATION_AND\": \"dan\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Return true if at least one of the inputs is true.\",\n    \"LOGIC_OPERATION_OR\": \"atau\",\n    \"LOGIC_NEGATE_TITLE\": \"bukan %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"'Benar' akan dibalas jika inputnya salah. 'Salah' akan dibalas jika inputnya benar.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"benar\",\n    \"LOGIC_BOOLEAN_FALSE\": \"palsu\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Kembalikan samada benar atau palsu.\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"Returns null.\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"Jika benar\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"Jika palsu\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\",\n    \"MATH_NUMBER_HELPURL\": \"https://ms.wikipedia.org/wiki/Nombor\",\n    \"MATH_NUMBER_TOOLTIP\": \"Suatu nombor.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://ms.wikipedia.org/wiki/Aritmetik\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Return the sum of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Taip balik hasil tolak dua nombor tersebut.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Taip balik hasil darab dua nombor tersebut.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Taip balik hasil bahagi dua nombor tersebut.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Return the first number raised to the power of the second number.\",\n    \"MATH_SINGLE_HELPURL\": \"https://ms.wikipedia.org/wiki/Punca_kuasa_dua\",\n    \"MATH_SINGLE_OP_ROOT\": \"Punca kuasa dua\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Kembalikan punca kuasa nombor.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"mutlak\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Kembalikan nilai mutlak suatu nombor.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Kembalikan nombor yang songsang.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Kembali dalam logaritma nombor asli.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Kembali logarithm 10 asas nombor.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Kembalikan e kepada kuasa nombor.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Kembalikan 10 kepada kuasa nombor.\",\n    \"MATH_TRIG_HELPURL\": \"https://ms.wikipedia.org/wiki/Fungsi_trigonometri\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Kembalikan darjah sine (bukan radian).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Kembalikan darjah kosinus (bukan radian).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Kembalikan darjah tangen (bukan radian).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Kembalikan arcsince beberapa nombor.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Kembali arccosine beberapa nombor.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Kembalikan beberapa nombor arctangent.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://ms.wikipedia.org/wiki/Pemalar_matematik\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"Adalah genap\",\n    \"MATH_IS_ODD\": \"aneh\",\n    \"MATH_IS_PRIME\": \"is prime\",\n    \"MATH_IS_WHOLE\": \"is whole\",\n    \"MATH_IS_POSITIVE\": \"adalah positif\",\n    \"MATH_IS_NEGATIVE\": \"negatif\",\n    \"MATH_IS_DIVISIBLE_BY\": \"Boleh dibahagikan dengan\",\n    \"MATH_IS_TOOLTIP\": \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\",\n    \"MATH_CHANGE_HELPURL\": \"https://id.wikipedia.org/wiki/Perjumlahan\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"perubahan\",\n    \"MATH_CHANGE_INPUT_BY\": \"oleh\",\n    \"MATH_CHANGE_TOOLTIP\": \"Tambah nombor kepada pembolehubah '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Bulat nombor yang naik atau turun.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"pusingan\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"pusingan ke atas\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"Pusingan ke bawah\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"Jumlah senarai\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Kembalikan jumlah semua nombor dalam senarai.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"min dalam senarai\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Kembalikan nombor terkecil dalam senarai.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"Max senarai\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Pulangkan jumlah terbesar dalam senarai.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"purata daripada senarai\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Kembalikan purata (min aritmetik) nilai-nilai angka di dalam senarai.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"Median senarai\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Kembalikan nombor median dalam senarai.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"jenis senarai\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Kembali senarai item yang paling biasa dalam senarai.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"sisihan piawai bagi senarai\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Kembali dengan sisihan piawai daripada senarai.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"Item rawak daripada senarai\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Kembalikan elemen rawak daripada senarai.\",\n    \"MATH_MODULO_HELPURL\": \"https://id.wikipedia.org/wiki/Operasi_modulus\",\n    \"MATH_MODULO_TITLE\": \"remainder of %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Taip balik baki yang didapat daripada pembahagian dua nombor tersebut.\",\n    \"MATH_CONSTRAIN_TITLE\": \"constrain %1 low %2 high %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Constrain a number to be between the specified limits (inclusive).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"integer rawak dari %1ke %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Kembalikan integer rawak diantara dua had yang ditentukan, inklusif.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"pecahan rawak\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Kembali sebahagian kecil rawak antara 0.0 (inklusif) dan 1.0 (eksklusif).\",\n    \"TEXT_TEXT_HELPURL\": \"https://ms.wikipedia.org/wiki/Rentetan\",\n    \"TEXT_TEXT_TOOLTIP\": \"Huruf, perkataan, atau baris teks.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"hasilkan teks dengan\",\n    \"TEXT_JOIN_TOOLTIP\": \"Hasilkan sebahagian teks dengan menghubungkan apa jua nombor item.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"Sertai\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Add, remove, or reorder sections to reconfigure this text block.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Add an item to the text.\",\n    \"TEXT_APPEND_TO\": \"Untuk\",\n    \"TEXT_APPEND_APPENDTEXT\": \"append text\",\n    \"TEXT_APPEND_TOOLTIP\": \"Append some text to variable '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"panjang %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Kembalikan jumlah huruf (termasuk ruang) dalam teks yang disediakan.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 adalah kosong\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Kembalikan benar jika teks yang disediakan adalah kosong.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Kembalikan Indeks kejadian pertama/terakhir dari teks pertama ke dalam teks kedua.  Kembalikan 0 Jika teks tidak ditemui.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"dalam teks\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"mencari kejadian pertama teks\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"mencari kejadian terakhir teks\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"Dalam teks\",\n    \"TEXT_CHARAT_FROM_START\": \"get letter #\",\n    \"TEXT_CHARAT_FROM_END\": \"get letter # from end\",\n    \"TEXT_CHARAT_FIRST\": \"get first letter\",\n    \"TEXT_CHARAT_LAST\": \"Dapatkan abjad terakhir\",\n    \"TEXT_CHARAT_RANDOM\": \"Dapatkan abjad rawak\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Returns the letter at the specified position.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Returns a specified portion of the text.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"dalam teks\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"get substring from letter #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"get substring from letter # from end\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"get substring from first letter\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"to letter #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"to letter # from end\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"untuk huruf terakhir\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Return a copy of the text in a different case.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"Kepada HURUF BESAR\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"Kepada huruf kecil\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"to Title Case\",\n    \"TEXT_TRIM_TOOLTIP\": \"Kembali salinan teks dengan ruang yang dikeluarkan daripada satu atau hujung kedua belah.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"mengurangkan kawasan dari kedua-dua belah\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"mengurangkan ruang dari sebelah kiri\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"mengurangkan kawasan dari sisi kanan\",\n    \"TEXT_PRINT_TITLE\": \"cetak %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Cetak teks yang ditentukan, nombor atau nilai lain.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"Prom untuk teks dengan mesej\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"Prom untuk nombor dengan mesej\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Peringatan kepada pengguna untuk nombor.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Peringatkan pengguna untuk sebahagian teks.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"Wujudkan senarai kosong\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Kembalikan senarai panjang 0, yang tidak mengandungi rekod data\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Wujudkan senarai dengan apa jua nombor item.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"wujudkan senarai dengan\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"senarai\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Tambah, alih keluar, atau susun semula bahagian-bahagian untuk menyusun semula senarai blok.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Tambah item ke dalam senarai.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Wujudkan senarai yang terdiri daripada nilai berulang mengikut nombor yang ditentukan.\",\n    \"LISTS_REPEAT_TITLE\": \"wujudkan senarai dengan item %1 diulangi %2 kali\",\n    \"LISTS_LENGTH_TITLE\": \"panjang %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Kembalikan panjang senarai\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 adalah kosong\",\n    \"LISTS_TOOLTIP\": \"Kembalikan benar jika senarai kosong.\",\n    \"LISTS_INLIST\": \"dalam senarai\",\n    \"LISTS_INDEX_OF_FIRST\": \"cari pertama item kejadian\",\n    \"LISTS_INDEX_OF_LAST\": \"cari kejadian akhir item\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Kembalikan indeks kejadian pertama/terakhir item dalam senarai. Kembalikan 0 jika teks tidak ditemui.\",\n    \"LISTS_GET_INDEX_GET\": \"dapatkan\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"dapat dan alihkan\",\n    \"LISTS_GET_INDEX_REMOVE\": \"alihkan\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# dari akhir\",\n    \"LISTS_GET_INDEX_FIRST\": \"pertama\",\n    \"LISTS_GET_INDEX_LAST\": \"terakhir\",\n    \"LISTS_GET_INDEX_RANDOM\": \"rawak\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Kembalikan item dalam kedudukan yang ditetapkan dalam senarai. #1 ialah item terakhir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Kembalikan item dalam kedudukan yang ditetapkan dalam senarai. #1 ialah item terakhir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Kembalikan item pertama dalam senarai.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Kembalikan item pertama dalam senarai.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Kembalikan item rawak dalam senarai.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Alihkan dan kembalikan item mengikut spesifikasi posisi dalam senarai. #1 ialah item pertama.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Alihkan dan kembalikan item mengikut spesifikasi posisi dalam senarai. #1 ialah item terakhir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Alihkan dan kembalikan item pertama dalam senarai.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Alihkan dan kembalikan item terakhir dalam senarai.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Alihkan dan kembalikan item rawak dalam senarai.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Alihkan item pada posisi mengikut spesifikasi dalam senarai. #1 ialah item pertama.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Alihkan item mengikut spesifikasi posisi dalam senarai. #1 ialah item terakhir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Alihkan item pertama dalam senarai.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Alihkan item terakhir dalam senarai.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Alihkan item rawak dalam senarai.\",\n    \"LISTS_SET_INDEX_SET\": \"set\",\n    \"LISTS_SET_INDEX_INSERT\": \"masukkan pada\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"sebagai\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Masukkan item pada posisi yang ditentukan dalam senarai. #1 ialah item terakhir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Masukkan item pada posisi yang ditentukan dalam senarai. #1 ialah item terakhir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Set item pertama dalam senarai.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Set item terakhir dalam senarai.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Set item rawak dalam senarai.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Masukkan item pada posisi yand ditentukan dalam senarai. #1 ialah item terakhir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Masukkan item pada posisi yang ditentukan dalam senarai. #1 ialah item terakhir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Selit item pada permulaan senarai.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Tambahkan item dalam senarai akhir.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Selit item secara rawak di dalam senarai.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"dapatkan sub-senarai daripada #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"dapatkan sub-senarai daripada # daripada terakhir\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"dapatkan sub-senarai daripada pertama\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"ke #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"ke  # dari akhir\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"ke akhir\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Wujudkan salinan bahagian yang ditentukan dari senarai.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Kembalikan nilai pemboleh ubah ini.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Hasilkan 'set %1'\",\n    \"VARIABLES_SET_TITLE\": \"set\",\n    \"VARIABLES_SET_TAIL\": \"ke\",\n    \"VARIABLES_SET_TOOLTIP\": \"Set pembolehubah ini supaya sama dengan input.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Hasilkan 'set %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"Untuk\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"Buat sesuatu\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"dengan:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Menghasilkan suatu fungsi tanpa output.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"kembali\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Mencipta satu fungsi dengan pengeluaran.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Amaran: Fungsi ini mempunyai parameter yang berganda.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://ms.wikipedia.org/wiki/Fungsi\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Run the user-defined function '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://ms.wikipedia.org/wiki/Fungsi\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Run the user-defined function '%1' and use its output.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"Input-input\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"Nama input:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Serlahkan definisi fungsi\",\n    \"PROCEDURES_CREATE_DO\": \"Hasilkan '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"If a value is true, then return a second value.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Amaran: Blok ini hanya boleh digunakan dalam fungsi definisi.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/nb.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"element\",\n    \"DUPLICATE_BLOCK\": \"duplikat\",\n    \"ADD_COMMENT\": \"Legg til kommentar\",\n    \"REMOVE_COMMENT\": \"Fjern kommentar\",\n    \"EXTERNAL_INPUTS\": \"Eksterne kilder\",\n    \"INLINE_INPUTS\": \"Interne kilder\",\n    \"DELETE_BLOCK\": \"Slett blokk\",\n    \"DELETE_X_BLOCKS\": \"Slett %1 blokk(er)\",\n    \"COLLAPSE_BLOCK\": \"Skjul blokk\",\n    \"COLLAPSE_ALL\": \"Skjul blokker\",\n    \"EXPAND_BLOCK\": \"Utvid blokk\",\n    \"EXPAND_ALL\": \"Utvid blokker\",\n    \"DISABLE_BLOCK\": \"Deaktiver blokk\",\n    \"ENABLE_BLOCK\": \"Aktiver blokk\",\n    \"HELP\": \"Hjelp\",\n    \"CHANGE_VALUE_TITLE\": \"Bytt verdi:\",\n    \"NEW_VARIABLE\": \"Ny variabel...\",\n    \"NEW_VARIABLE_TITLE\": \"Nytt variabelnavn:\",\n    \"RENAME_VARIABLE\": \"Gi nytt navn til variabel...\",\n    \"RENAME_VARIABLE_TITLE\": \"Endre navnet til alle '%1' variabler til:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Velg en farge fra paletten.\",\n    \"COLOUR_RANDOM_TITLE\": \"tilfeldig farge\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Velg en tilfeldig farge.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"farge med\",\n    \"COLOUR_RGB_RED\": \"rød\",\n    \"COLOUR_RGB_GREEN\": \"grønn\",\n    \"COLOUR_RGB_BLUE\": \"blå\",\n    \"COLOUR_RGB_TOOLTIP\": \"Lag en farge med angitt verdi av rød, grønn og blå. Alle verdier må være mellom 0 og 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"blande\",\n    \"COLOUR_BLEND_COLOUR1\": \"farge 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"farge 2\",\n    \"COLOUR_BLEND_RATIO\": \"forhold\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Blander to farger sammen med et gitt forhold (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"gjenta %1 ganger\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"gjenta\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"ganger\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"gjør\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Gjenta noen instruksjoner flere ganger.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"gjenta mens\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"gjenta til\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Så lenge et utsagn stemmer, utfør noen instruksjoner.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Så lenge et utsagn ikke stemmer, gjør noen instruksjoner.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Ha variabel %1 ta verdiene fra start nummer til slutt nummer, telle med spesifisert intervall og lag de spesifiserte blokkene.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"tell med\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"fra %1 til %2 med %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"for hvert element\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"i listen\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"For hvert element i en liste, angi variabelen '%1' til elementet, og deretter lag noen setninger.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"bryt ut av løkken\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"fortsett med neste gjentakelse av løkken\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Bryt ut av den gjeldende løkken.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Hopp over resten av denne løkken og fortsett med neste gjentakelse.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Advarsel: Denne blokken kan kun brukes innenfor en løkke.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Hvis dette er sant, så gjør følgende.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Hvis dette er sant, så utfør den første blokken av instruksjoner. Hvis ikke, utfør den andre blokken.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Hvis det første stemmer, så utfør den første blokken av instruksjoner. Ellers, hvis det andre stemmer, utfør den andre blokken av instruksjoner.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Hvis den første verdien er sann, så utfør den første blokken med setninger. Ellers, hvis den andre verdien er sann, så utfør den andre blokken med setninger. Hvis ingen av verdiene er sanne, så utfør den siste blokken med setninger.\",\n    \"CONTROLS_IF_MSG_IF\": \"hvis\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"ellers hvis\",\n    \"CONTROLS_IF_MSG_ELSE\": \"ellers\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Legg til, fjern eller flytt seksjoner i denne hvis-blokken.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Legg til en betingelse til hvis blokken.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Legg til hva som skal skje hvis de andre ikke slår til.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Returnerer sann hvis begge inputene er like hverandre.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Returnerer sant hvis begge argumentene er ulike hverandre.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Returnerer sant hvis det første argumentet er mindre enn det andre argumentet.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Returnerer sant hvis det første argumentet er mindre enn eller likt det andre argumentet.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Returnerer sant hvis det første argumentet er større enn den andre argumentet.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Returnerer sant hvis det første argumentet er større enn eller likt det andre argumentet.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Returnerer sant hvis begge argumentene er sanne.\",\n    \"LOGIC_OPERATION_AND\": \"og\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Returnerer sant hvis minst ett av argumentene er sant.\",\n    \"LOGIC_OPERATION_OR\": \"eller\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"ikke %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Returnerer sant hvis argumentet er usant. Returnerer usant hvis argumentet er sant.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"sann\",\n    \"LOGIC_BOOLEAN_FALSE\": \"usann\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Returnerer enten sann eller usann.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"Returnerer null.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"hvis sant\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"hvis usant\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Sjekk betingelsen i 'test'. Hvis betingelsen er sann, da returneres 'hvis sant' verdien. Hvis ikke returneres 'hvis usant' verdien.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Et tall.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"x\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://no.wikipedia.org/wiki/Aritmetikk\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Returnerer summen av to tall.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Returner differansen mellom to tall.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Returner produktet av to tall.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Returner kvotienten av to tall.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Returner det første tallet opphøyd i den andre tallet.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"kvadratrot\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Returner kvadratroten av et tall.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absoluttverdi\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Returner absoluttverdien av et tall.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Returner det negative tallet.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Returner den naturlige logaritmen til et tall.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Returner base-10 logaritmen til et tall.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Returner e opphøyd i et tall.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Returner 10 opphøyd i et tall.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Returner sinus av en vinkel (ikke radian).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Returner cosinus av en vinkel (ikke radian).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Returner tangenten av en vinkel (ikke radian).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Returner arcsinus til et tall.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Returner arccosinus til et tall.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Returner arctangens til et tall.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Returner en av felleskonstantene π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), eller ∞ (uendelig).\",\n    \"MATH_IS_EVEN\": \"er et partall\",\n    \"MATH_IS_ODD\": \"er et oddetall\",\n    \"MATH_IS_PRIME\": \"er et primtall\",\n    \"MATH_IS_WHOLE\": \"er et heltall\",\n    \"MATH_IS_POSITIVE\": \"er positivt\",\n    \"MATH_IS_NEGATIVE\": \"er negativer negativt\",\n    \"MATH_IS_DIVISIBLE_BY\": \"er delelig med\",\n    \"MATH_IS_TOOLTIP\": \"Sjekk om et tall er et partall, oddetall, primtall, heltall, positivt, negativt, eller om det er delelig med et annet tall. Returnerer sant eller usant.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"endre\",\n    \"MATH_CHANGE_INPUT_BY\": \"ved\",\n    \"MATH_CHANGE_TOOLTIP\": \"Addere et tall til variabelen '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Avrund et tall ned eller opp.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"avrunding\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"rund opp\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"rund ned\",\n    \"MATH_ONLIST_HELPURL\": \"\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"summen av listen\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Returner summen av alle tallene i listen.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"minimum av listen\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Returner det minste tallet i listen.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"maksimum av liste\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Returner det største tallet i listen.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"gjennomsnittet av listen\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Returner det aritmetiske gjennomsnittet av tallene i listen.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"medianen til listen\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Returner listens median.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"Listens typetall\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Returner en liste av de vanligste elementene i listen.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"standardavviket til listen\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Returner listens standardavvik.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"tilfeldig element i listen\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Returner et tilfeldig element fra listen.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"resten av %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Returner resten fra delingen av to tall.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"begrense %1 lav %2 høy %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Begrens et tall til å være mellom de angitte grenseverdiene (inklusiv).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"Et tilfeldig heltall mellom %1 og %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Returner et tilfeldig tall mellom de to spesifiserte grensene, inkludert de to.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"tilfeldig flyttall\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Returner et tilfeldig flyttall mellom 0.0 (inkludert) og 1.0 (ikke inkludert).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"En bokstav, ett ord eller en linje med tekst.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"lage tekst med\",\n    \"TEXT_JOIN_TOOLTIP\": \"Opprett en tekst ved å sette sammen et antall elementer.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"føy sammen\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Legg til, fjern eller forandre rekkefølgen for å forandre på denne tekstblokken.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Legg til et element til teksten.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"til\",\n    \"TEXT_APPEND_APPENDTEXT\": \"tilføy tekst\",\n    \"TEXT_APPEND_TOOLTIP\": \"Tilføy tekst til variabelen '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"lengden av %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Returnerer antall bokstaver (inkludert mellomrom) i den angitte teksten.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 er tom\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Returnerer sann hvis den angitte teksten er tom.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Returnerer posisjonen for første/siste forekomsten av den første tekst i den andre teksten.  Returnerer 0 hvis teksten ikke blir funnet.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"i tekst\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"finn første forekomst av tekst\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"finn siste forekomst av tekst\",\n    \"TEXT_INDEXOF_TAIL\": \"\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"i tekst\",\n    \"TEXT_CHARAT_FROM_START\": \"hent bokstav #\",\n    \"TEXT_CHARAT_FROM_END\": \"hent bokstav # fra slutten\",\n    \"TEXT_CHARAT_FIRST\": \"hent første bokstav\",\n    \"TEXT_CHARAT_LAST\": \"hent den siste bokstaven\",\n    \"TEXT_CHARAT_RANDOM\": \"hent en tilfeldig bokstav\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Returnerer bokstaven på angitt plassering.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Returnerer den angitte delen av teksten.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"i tekst\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"hent delstreng fra bokstav #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"hent delstreng fra bokstav # fra slutten\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"hent delstreng fra første bokstav\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"til bokstav #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"til bokstav # fra slutten\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"til siste bokstav\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Returnerer en kopi av teksten der store og små bokstaver er byttet om.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"til STORE BOKSTAVER\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"til små bokstaver\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"til store forbokstaver\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Returner en kopi av teksten med mellomrom fjernet fra en eller begge sidene.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"fjern mellomrom fra begge sider\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"fjern mellomrom fra venstre side\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"fjern mellomrom fra høyre side\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"skriv ut %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Skriv ut angitt tekst, tall eller annet innhold.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"spør om tekst med en melding\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"spør om et tall med en melding\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Be brukeren om et tall.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Spør brukeren om tekst.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"opprett en tom liste\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Returnerer en tom liste, altså med lengde 0\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Lag en liste med et vilkårlig antall elementer.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"lag en liste med\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"liste\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Legg til, fjern eller endre rekkefølgen for å endre på denne delen av listen.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Tilføy et element til listen.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Lager en liste hvor den gitte verdien gjentas et antall ganger.\",\n    \"LISTS_REPEAT_TITLE\": \"Lag en liste hvor elementet %1 forekommer %2 ganger\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"lengden på %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Returnerer lengden til en liste.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 er tom\",\n    \"LISTS_TOOLTIP\": \"Returnerer sann hvis listen er tom.\",\n    \"LISTS_INLIST\": \"i listen\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"finn første forekomst av elementet\",\n    \"LISTS_INDEX_OF_LAST\": \"finn siste forekomst av elementet\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Returnerer posisjonen til den første/siste forekomsten av elementet i en liste. Returnerer 0 hvis ikke funnet.\",\n    \"LISTS_GET_INDEX_GET\": \"hent\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"hent og fjern\",\n    \"LISTS_GET_INDEX_REMOVE\": \"fjern\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# fra slutten\",\n    \"LISTS_GET_INDEX_FIRST\": \"først\",\n    \"LISTS_GET_INDEX_LAST\": \"siste\",\n    \"LISTS_GET_INDEX_RANDOM\": \"tilfeldig\",\n    \"LISTS_GET_INDEX_TAIL\": \"\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Returner elementet på den angitte posisjonen i en liste. #1 er det første elementet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Returner elementet på den angitte posisjonen i en liste. #1 er det siste elementet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Returnerer det første elementet i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Returnerer det siste elementet i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Returnerer et tilfeldig element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Fjerner og returnerer elementet ved en gitt posisjon i en liste. #1 er det første elementet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Fjerner og returnerer elementet ved en gitt posisjon i en liste. #1 er det siste elementet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Fjerner og returnerer det første elementet i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Fjerner og returnerer det siste elementet i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Fjerner og returnerer et tilfeldig element i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Fjerner et element ved en gitt posisjon i en liste. #1 er det første elementet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Fjerner et element ved en gitt posisjon i en liste. #1 er det siste elementet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Fjerner det første elementet i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Fjerner det siste elementet i en liste.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Fjerner et tilfeldig element i en liste.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"sett\",\n    \"LISTS_SET_INDEX_INSERT\": \"sett inn ved\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"som\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det første elementet.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det siste elementet.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Angir det første elementet i en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Angir det siste elementet i en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Angir et tilfeldig element i en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det første elementet.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Setter inn elementet ved den angitte posisjonen i en liste. #1 er det siste elementet.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Setter inn elementet i starten av en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Tilføy elementet til slutten av en liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Setter inn elementet ved en tilfeldig posisjon i en liste.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"Hent del-listen fra #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"Hent de siste # elementene\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"Hent en del av listen\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"til #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"til # fra slutten\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"til siste\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Kopiérer en ønsket del av en liste.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"Returnerer verdien av denne variabelen.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Opprett 'sett %1'\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"sett\",\n    \"VARIABLES_SET_TAIL\": \"til\",\n    \"VARIABLES_SET_TOOLTIP\": \"Setter verdien av denne variablen lik parameteren.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Opprett 'hent %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"til\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"gjør noe\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"med:\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Opprett en funksjon som ikke har noe resultat.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"returner\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Oppretter en funksjon som har et resultat.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Advarsel: Denne funksjonen har duplikate parametere.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Kjør den brukerdefinerte funksjonen '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Kjør den brukerdefinerte funksjonen'%1' og bruk resultatet av den.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"parametere\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"Navn på parameter:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Marker funksjonsdefinisjonen\",\n    \"PROCEDURES_CREATE_DO\": \"Opprett '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Hvis en verdi er sann, returner da en annen verdi.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Advarsel: Denne blokken kan bare benyttes innenfor en funksjonsdefinisjon.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/nl.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Siebrand\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"item\",\n    \"DUPLICATE_BLOCK\": \"Duplicaat\",\n    \"ADD_COMMENT\": \"Reactie toevoegen\",\n    \"REMOVE_COMMENT\": \"Opmerking verwijderen\",\n    \"EXTERNAL_INPUTS\": \"Externe invoer\",\n    \"INLINE_INPUTS\": \"Inline invoer\",\n    \"DELETE_BLOCK\": \"Blok verwijderen\",\n    \"DELETE_X_BLOCKS\": \"%1 blokken verwijderen\",\n    \"COLLAPSE_BLOCK\": \"Blok inklappen\",\n    \"COLLAPSE_ALL\": \"Blokken inklappen\",\n    \"EXPAND_BLOCK\": \"Blok uitvouwen\",\n    \"EXPAND_ALL\": \"Blokken uitvouwen\",\n    \"DISABLE_BLOCK\": \"Blok uitschakelen\",\n    \"ENABLE_BLOCK\": \"Blok inschakelen\",\n    \"HELP\": \"Hulp\",\n    \"CHANGE_VALUE_TITLE\": \"Waarde wijzigen:\",\n    \"NEW_VARIABLE\": \"Nieuwe variabele...\",\n    \"NEW_VARIABLE_TITLE\": \"Nieuwe variabelenaam:\",\n    \"RENAME_VARIABLE\": \"Variabele hernoemen...\",\n    \"RENAME_VARIABLE_TITLE\": \"Alle variabelen \\\"%1\\\" hernoemen naar:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://nl.wikipedia.org/wiki/Kleur\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Kies een kleur in het palet.\",\n    \"COLOUR_RANDOM_TITLE\": \"willekeurige kleur\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Kies een willekeurige kleur.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"kleuren met\",\n    \"COLOUR_RGB_RED\": \"rood\",\n    \"COLOUR_RGB_GREEN\": \"groen\",\n    \"COLOUR_RGB_BLUE\": \"blauw\",\n    \"COLOUR_RGB_TOOLTIP\": \"Maak een kleur met de opgegeven hoeveelheid rood, groen en blauw.  Alle waarden moeten tussen 0 en 100 liggen.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"mengen\",\n    \"COLOUR_BLEND_COLOUR1\": \"kleur 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"kleur 2\",\n    \"COLOUR_BLEND_RATIO\": \"verhouding\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Mengt twee kleuren samen met een bepaalde verhouding (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://nl.wikipedia.org/wiki/Repetitie_(informatica)#For_en_Foreach\",\n    \"CONTROLS_REPEAT_TITLE\": \"%1 keer herhalen\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"herhalen\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"keer\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"voer uit\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Voer een aantal opdrachten meerdere keren uit.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"herhalen zolang\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"herhalen totdat\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Terwijl een waarde waar is de volgende opdrachten uitvoeren.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Terwijl een waarde onwaar is de volgende opdrachten uitvoeren.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Laat de variabele %1 de waarden aannemen van het beginnummer tot het laatste nummer, tellende met het opgegeven interval, en met uitvoering van de opgegeven blokken.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"rekenen met\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"van %1 tot %2 in stappen van %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"voor ieder item\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"in lijst\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Voor ieder item in een lijst, stel de variabele \\\"%1\\\" in op het item en voer daarna opdrachten uit.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"uit lus breken\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"doorgaan met de volgende iteratie van de lus\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"uit de bovenliggende lus breken\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"De rest van deze lus overslaan en doorgaan met de volgende herhaling.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Waarschuwing: dit blok mag alleen gebruikt worden in een lus.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Als een waarde waar is, voer dan opdrachten uit.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Als een waarde waar is, voert dan het eerste blok met opdrachten uit. Voer andere het tweede blok met opdrachten uit.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Als de eerste waarde waar is, voer dan het eerste blok met opdrachten uit. Voer anders, als de tweede waarde waar is, het tweede blok met opdrachten uit.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Als de eerste waarde \\\"waar\\\" is, voer dan het eerste blok uit. Voer anders wanneer de tweede waarde \\\"waar\\\" is, het tweede blok uit. Als geen van beide waarden waar zijn, voer dan het laatste blok uit.\",\n    \"CONTROLS_IF_MSG_IF\": \"als\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"anders als\",\n    \"CONTROLS_IF_MSG_ELSE\": \"anders\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Voeg stukken toe, verwijder of verander de volgorde om dit \\\"als\\\"-blok te wijzigen.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Voeg een voorwaarde toe aan het als-blok.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Voeg een laatste, vang-alles conditie toe aan het als-statement.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://nl.wikipedia.org/wiki/Ongelijkheid\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Geeft \\\"waar\\\", als beide waarden gelijk aan elkaar zijn.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Geeft \\\"waar\\\" terug als de waarden niet gelijk zijn aan elkaar.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Geeft \\\"waar\\\" als de eerste invoer kleiner is dan de tweede invoer.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Geeft \\\"waar\\\" terug als de eerste invoer kleiner of gelijk is aan de tweede invoer.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Geeft \\\"waar\\\" terug als de eerste invoer meer is dan de tweede invoer.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Geeft \\\"waar\\\" terug als de eerste invoer groter is of gelijk aan de tweede invoer.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Geeft waar als beide waarden waar zijn.\",\n    \"LOGIC_OPERATION_AND\": \"en\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Geeft \\\"waar\\\" terug als in ieder geval één van de waarden waar is.\",\n    \"LOGIC_OPERATION_OR\": \"of\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"niet %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Geeft \\\"waar\\\" terug als de invoer \\\"onwaar\\\" is. Geeft \\\"onwaar\\\" als de invoer \\\"waar\\\" is.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"waar\",\n    \"LOGIC_BOOLEAN_FALSE\": \"onwaar\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Geeft \\\"waar\\\" of \\\"onwaar\\\" terug.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"niets\",\n    \"LOGIC_NULL_TOOLTIP\": \"Geeft niets terug.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"als waar\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"als onwaar\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Test de voorwaarde in \\\"test\\\". Als de voorwaarde \\\"waar\\\" is, geef de waarde van \\\"als waar\\\" terug; geef anders de waarde van \\\"als onwaar\\\" terug.\",\n    \"MATH_NUMBER_HELPURL\": \"https://nl.wikipedia.org/wiki/Getal_%28wiskunde%29\",\n    \"MATH_NUMBER_TOOLTIP\": \"Een getal.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"arctan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://nl.wikipedia.org/wiki/Rekenen\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Geeft de som van 2 getallen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Geeft het verschil van de twee getallen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Geeft het product terug van de twee getallen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Geeft de gedeelde waarde van twee getallen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Geeft het eerste getal tot de macht van het tweede getal.\",\n    \"MATH_SINGLE_HELPURL\": \"https://nl.wikipedia.org/wiki/Vierkantswortel\",\n    \"MATH_SINGLE_OP_ROOT\": \"wortel\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Geeft de wortel van een getal.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absoluut\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Geeft de absolute waarde van een getal.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Geeft de negatief van een getal.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Geeft het natuurlijk logaritme van een getal.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Geeft het logaritme basis 10 van een getal.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Geeft e tot de macht van een getal.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Geeft 10 tot de macht van een getal.\",\n    \"MATH_TRIG_HELPURL\": \"https://nl.wikipedia.org/wiki/Goniometrische_functie\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Geeft de sinus van een graad (geen radialen).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Geeft de cosinus van een graad (geen radialen).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Geeft de tangens van een graad (geen radialen).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Geeft de arcsinus van een getal.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Geeft de arccosinus van een getal.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Geeft de arctangens van een getal.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://nl.wikipedia.org/wiki/Wiskundige_constante\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Geeft een van de vaak voorkomende constante waardes:  π (3.141…), e (2.718…), φ (1.618…), √2 (1.414…), √½ (0.707…), of ∞ (oneindig).\",\n    \"MATH_IS_EVEN\": \"is even\",\n    \"MATH_IS_ODD\": \"is oneven\",\n    \"MATH_IS_PRIME\": \"is priemgetal\",\n    \"MATH_IS_WHOLE\": \"is geheel getal\",\n    \"MATH_IS_POSITIVE\": \"is positief\",\n    \"MATH_IS_NEGATIVE\": \"is negatief\",\n    \"MATH_IS_DIVISIBLE_BY\": \"is deelbaar door\",\n    \"MATH_IS_TOOLTIP\": \"Test of een getal even, oneven, een priemgetal, geheel, positief of negatief is, of deelbaar is door een bepaald getal. Geeft \\\"waar\\\" of \\\"onwaar\\\".\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"wijzigen\",\n    \"MATH_CHANGE_INPUT_BY\": \"met\",\n    \"MATH_CHANGE_TOOLTIP\": \"Voegt een getal toe aan variabele \\\"%1\\\".\",\n    \"MATH_ROUND_HELPURL\": \"https://nl.wikipedia.org/wiki/Afronden\",\n    \"MATH_ROUND_TOOLTIP\": \"Rondt een getal af omhoog of naar beneden.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"afronden\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"omhoog afronden\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"naar beneden afronden\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"som van lijst\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Geeft de som van alle getallen in de lijst.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"laagste uit lijst\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Geeft het kleinste getal uit een lijst.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"hoogste uit lijst\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Geeft het grootste getal in een lijst.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"gemiddelde van lijst\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Geeft het gemiddelde terug van de numerieke waardes in een lijst.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mediaan van lijst\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Geeft de mediaan in de lijst.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"modi van lijst\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Geeft een lijst van de meest voorkomende onderdelen in de lijst.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"standaarddeviatie van lijst\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Geeft de standaardafwijking van de lijst.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"willekeurige item van lijst\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Geeft een willekeurig item uit de lijst terug.\",\n    \"MATH_MODULO_HELPURL\": \"https://nl.wikipedia.org/wiki/Modulair_rekenen\",\n    \"MATH_MODULO_TITLE\": \"restgetal van %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Geeft het restgetal van het resultaat van de deling van de twee getallen.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"beperk %1 van minimaal %2 tot maximaal %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Beperk een getal tussen de twee opgegeven limieten (inclusief).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://nl.wikipedia.org/wiki/Toevalsgenerator\",\n    \"MATH_RANDOM_INT_TITLE\": \"willekeurig getal van %1 tot %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Geeft een willekeurig getal tussen de 2 opgegeven limieten in, inclusief.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://nl.wikipedia.org/wiki/Toevalsgenerator\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"willekeurige fractie\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Geeft een willekeurige fractie tussen 0.0 (inclusief) en 1.0 (exclusief).\",\n    \"TEXT_TEXT_HELPURL\": \"https://nl.wikipedia.org/wiki/String_%28informatica%29\",\n    \"TEXT_TEXT_TOOLTIP\": \"Een letter, woord of een regel tekst.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"maak tekst met\",\n    \"TEXT_JOIN_TOOLTIP\": \"Maakt een stuk tekst door één of meer items samen te voegen.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"samenvoegen\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Toevoegen, verwijderen of volgorde veranderen van secties om dit tekstblok opnieuw in te stellen.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Voegt een item aan de tekst toe.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"voeg toe aan\",\n    \"TEXT_APPEND_APPENDTEXT\": \"tekst\",\n    \"TEXT_APPEND_TOOLTIP\": \"Voeg tekst toe aan de variabele \\\"%1\\\".\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"lengte van %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Geeft het aantal tekens terug (inclusief spaties) in de opgegeven tekst.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 is leeg\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Geeft \\\"waar\\\" terug, als de opgegeven tekst leeg is.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Geeft de index terug van de eerste/laatste aanwezigheid van de eerste tekst in de tweede tekst. Geeft 0 terug als de tekst niet gevonden is.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"in tekst\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"zoek eerste voorkomen van tekst\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"zoek het laatste voorkomen van tekst\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"in tekst\",\n    \"TEXT_CHARAT_FROM_START\": \"haal letter # op\",\n    \"TEXT_CHARAT_FROM_END\": \"haal letter # op vanaf einde\",\n    \"TEXT_CHARAT_FIRST\": \"haal eerste letter op\",\n    \"TEXT_CHARAT_LAST\": \"haal laatste letter op\",\n    \"TEXT_CHARAT_RANDOM\": \"haal willekeurige letter op\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Geeft de letter op de opgegeven positie terug.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Geeft het opgegeven onderdeel van de tekst terug.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"in tekst\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"haal subtekst op vanaf letter #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"haal subtekst op vanaf letter # vanaf einde\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"haal subtekst op van eerste letter\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"naar letter #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"van letter # tot einde\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"naar laatste letter\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Geef een kopie van de tekst met veranderde hoofdletters terug.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"naar HOOFDLETTERS\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"naar kleine letters\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"naar Hoofdletter Per Woord\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Geeft een kopie van de tekst met verwijderde spaties van één of beide kanten.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"spaties van beide kanten afhalen\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"spaties van de linkerkant verwijderen\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"spaties van de rechterkant verwijderen\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"tekst weergeven: %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Drukt de opgegeven tekst, getal of een andere waarde af.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"vraagt om invoer met bericht\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"vraagt de gebruiker om een getal met de tekst\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Vraagt de gebruiker om een getal in te voeren.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Vraagt de gebruiker om invoer.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"maak een lege lijst\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Geeft een lijst terug met lengte 0, zonder items\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Maak een lijst met een willekeurig aantal items.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"maak een lijst met\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lijst\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Voeg stukken toe, verwijder ze of verander de volgorde om dit lijstblok aan te passen.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Voeg iets toe aan de lijst.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Maakt een lijst die bestaat uit de opgegeven waarde, het opgegeven aantal keer herhaald.\",\n    \"LISTS_REPEAT_TITLE\": \"Maak lijst met item %1, %2 keer herhaald\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"lengte van %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Geeft de lengte van een lijst terug.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 is leeg\",\n    \"LISTS_TOOLTIP\": \"Geeft waar terug als de lijst leeg is.\",\n    \"LISTS_INLIST\": \"in lijst\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"zoek eerste voorkomen van item\",\n    \"LISTS_INDEX_OF_LAST\": \"zoek laatste voorkomen van item\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Geeft de index van het eerste of laatste voorkomen van een item in de lijst terug. Geeft 0 terug als de tekst niet is gevonden.\",\n    \"LISTS_GET_INDEX_GET\": \"haal op\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"haal op en verwijder\",\n    \"LISTS_GET_INDEX_REMOVE\": \"verwijder\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# van einde\",\n    \"LISTS_GET_INDEX_FIRST\": \"eerste\",\n    \"LISTS_GET_INDEX_LAST\": \"laatste\",\n    \"LISTS_GET_INDEX_RANDOM\": \"willekeurig\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Geeft het item op de opgegeven positie in een lijst. Item 1 is het eerste item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Geeft het item op de opgegeven positie in een lijst terug. Item 1 is het laatste item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Geeft het eerste item in een lijst terug.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Geeft het laatste item in een lijst terug.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Geeft een willekeurig item uit een lijst.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Geeft het item op de opgegeven positie in een lijst terug en verwijdert het. Item 1 is het eerste item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Verwijdert en geeft het item op de opgegeven positie in de lijst. Item 1 is het laatste item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Geeft het laatste item in een lijst terug en verwijdert het.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Geeft het laatste item uit een lijst terug en verwijdert het.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Geeft een willekeurig item in een lijst terug en verwijdert het.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Verwijdert het item op de opgegeven positie in een lijst. Item 1 is het eerste item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Verwijdert een item op de opgegeven positie in een lijst. Item 1 is het laatste item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Verwijdert het eerste item in een lijst.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Verwijdert het laatste item uit een lijst.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Verwijdert een willekeurig item uit een lijst.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"stel in\",\n    \"LISTS_SET_INDEX_INSERT\": \"tussenvoegen op\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"als\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Stelt het item op de opgegeven positie in de lijst in. Item 1 is het eerste item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Stelt het item op een opgegeven positie in de lijst in. Item 1 is het laatste item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Stelt het eerste item in een lijst in.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Stelt het laatste item van een lijst in.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Stelt een willekeurig item uit de lijst in.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Voegt het item op een opgegeven positie in een lijst in. Item 1 is het eerste item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Voegt het item op de opgegeven positie toe aan een lijst in. Item 1 is het laatste item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Voegt het item toe aan het begin van de lijst.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Voeg het item aan het einde van een lijst toe.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Voegt het item op een willekeurige positie in de lijst in.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"haal sublijst op vanaf positie\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"haal sublijst op van positie vanaf einde\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"haal sublijst op vanaf eerste\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"naar item\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"naar # vanaf einde\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"naar laatste\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Maakt een kopie van het opgegeven deel van de lijst.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Geeft de waarde van deze variabele.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Maak \\\"verander %1\\\"\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"stel in\",\n    \"VARIABLES_SET_TAIL\": \"naar\",\n    \"VARIABLES_SET_TOOLTIP\": \"Verandert de waarde van de variabele naar de waarde van de invoer.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Maak 'opvragen van %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://nl.wikipedia.org/wiki/Subprogramma\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"om\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"doe iets\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"met:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Maakt een functie zonder uitvoer.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://nl.wikipedia.org/wiki/Subprogramma\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"uitvoeren\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Maakt een functie met een uitvoer.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Waarschuwing: deze functie heeft parameters met dezelfde naam.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://nl.wikipedia.org/wiki/Subprogramma\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Voer de door de gebruiker gedefinieerde functie \\\"%1\\\" uit.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://nl.wikipedia.org/wiki/Subprogramma\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Voer de door de gebruiker gedefinieerde functie \\\"%1\\\" uit en gebruik de uitvoer.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"ingangen\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"invoernaam:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Accentueer functiedefinitie\",\n    \"PROCEDURES_CREATE_DO\": \"Maak \\\"%1\\\"\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Als de eerste waarde \\\"waar\\\" is, geef dan de tweede waarde terug.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Waarschuwing: dit blok mag alleen gebruikt worden binnen de definitie van een functie.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/pl.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"element\",\n    \"DUPLICATE_BLOCK\": \"Powiel\",\n    \"ADD_COMMENT\": \"Dodaj komentarz\",\n    \"REMOVE_COMMENT\": \"Usuń Komentarz\",\n    \"EXTERNAL_INPUTS\": \"Zewnętrzne wejścia\",\n    \"INLINE_INPUTS\": \"Webdowane wejscia\",\n    \"DELETE_BLOCK\": \"Usuń blok\",\n    \"DELETE_X_BLOCKS\": \"Usunąć %1 bloki\",\n    \"COLLAPSE_BLOCK\": \"Zwiń blok\",\n    \"COLLAPSE_ALL\": \"Zwiń bloki\",\n    \"EXPAND_BLOCK\": \"Rozwiń blok\",\n    \"EXPAND_ALL\": \"Rozwiń bloki\",\n    \"DISABLE_BLOCK\": \"Wyłącz blok\",\n    \"ENABLE_BLOCK\": \"Włącz blok\",\n    \"HELP\": \"Pomoc\",\n    \"CHANGE_VALUE_TITLE\": \"Zmień wartość:\",\n    \"NEW_VARIABLE\": \"Nowa zmienna...\",\n    \"NEW_VARIABLE_TITLE\": \"Nowa nazwa zmiennej:\",\n    \"RENAME_VARIABLE\": \"Zmień nazwę zmiennej...\",\n    \"RENAME_VARIABLE_TITLE\": \"Zmień nazwy wszystkich '%1' zmiennych na:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Wybierz kolor z palety.\",\n    \"COLOUR_RANDOM_TITLE\": \"losowy kolor\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Wybierz kolor w sposób losowy.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"kolor z\",\n    \"COLOUR_RGB_RED\": \"czerwony\",\n    \"COLOUR_RGB_GREEN\": \"zielony\",\n    \"COLOUR_RGB_BLUE\": \"niebieski\",\n    \"COLOUR_RGB_TOOLTIP\": \"Połącz czerwony, zielony i niebieski w odpowiednich proporcjach, tak aby powstał nowy kolor. Zawartość każdego z nich określa liczba z przedziału od 0 do 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"mieszanka\",\n    \"COLOUR_BLEND_COLOUR1\": \"kolor 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"kolor 2\",\n    \"COLOUR_BLEND_RATIO\": \"proporcja\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Miesza dwa kolory w danej proporcji (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"powtórz %1 razy\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"powtórz\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"razy\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"wykonaj\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Wykonaj niektóre instrukcje kilka razy.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"powtarzaj dopóki\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"powtarzaj aż\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Gdy wartość jest prawdziwa, wykonaj kilka instrukcji.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Gdy wartość jest nieprawdziwa, wykonaj kilka instrukcji.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Czy zmienna %1 przyjmuje wartości od numeru startowego do numeru końcowego, licząc przez określony interwał, i wykonuje  określone bloki.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"liczyć z\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"od %1 do %2 co %3 (wartość kroku)\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"dla każdego elementu\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"na liście\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Dla każdego elementu z listy przyporządkuj zmienną '%1', a następnie wykonaj kilka instrukcji.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"wyjść z pętli\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"Przejdź do kolejnej iteracji pętli\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Wyjść z zawierającej pętli.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Pomiń resztę pętli i kontynuuj w kolejnej iteracji.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Ostrzeżenie: Ten blok może być użyty tylko w pętli.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Jeśli wartość jest prawdziwa,  to wykonaj kilka instrukcji.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Jeśli wartość jest prawdą, to wykonaj pierwszy blok instrukcji.  W przeciwnym razie, wykonaj drugi blok instrukcji.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Jeśli pierwsza wartość jest prawdą, to wykonaj pierwszy blok instrukcji.  W przeciwnym razie, jeśli druga wartość jest prawdą, to wykonaj drugi blok instrukcji.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Jeśli pierwsza wartość jest prawdziwa, wykonaj pierwszy blok instrukcji.  W przeciwnym razie jeśli druga wartość jest prawdziwa, wykonaj drugi blok instrukcji.  Jeżeli żadna z wartości nie jest prawdziwa, wykonaj ostatni blok instrukcji.\",\n    \"CONTROLS_IF_MSG_IF\": \"jeśli\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"w przeciwnym razie jeśli\",\n    \"CONTROLS_IF_MSG_ELSE\": \"w przeciwnym razie\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Dodać, usunąć lub zmienić kolejność sekcji żeby zrekonfigurować blok if.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Dodać warunek do bloku if.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Dodać warunek końcowy, warunek złap wszystkie do bloku if.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Zwraca \\\"prawda\\\", jeśli obie dane wejściowe są sobie równe.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Zwraca \\\"prawda\\\", jeśli obie dane wejściowe nie są sobie równe.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Zwraca \\\"prawda\\\" jeśli pierwsza dana wejściowa jest większa od drugiej.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Zwraca \\\"prawda\\\", jeśli pierwsza dana wejściowa jest większa lub równa drugiej danej wejściowej.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Zwraca \\\"prawda\\\" jeśli pierwszy dany element jest większy od drugiego.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Zwraca \\\"prawda\\\", jeśli pierwsza dana wejściowa jest większa niż lub równa drugiej danej wejściowej.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Zwraca \\\"prawda\\\" jeśli oba dane elementy mają wartość \\\"prawda\\\".\",\n    \"LOGIC_OPERATION_AND\": \"i\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Zwraca \\\"prawda\\\" jeśli co najmniej jeden dany element ma wartość \\\"prawda\\\".\",\n    \"LOGIC_OPERATION_OR\": \"lub\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"nie %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Zwraca \\\"prawda\\\", jeśli dane wejściowe są fałszywe.  Zwraca \\\"fałsz\\\", jeśli dana wejściowa jest prawdziwa.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"prawda\",\n    \"LOGIC_BOOLEAN_FALSE\": \"fałsz\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Zwraca 'prawda' lub 'fałsz'.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"nic\",\n    \"LOGIC_NULL_TOOLTIP\": \"Zwraca zero.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"jeśli prawda\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"jeśli fałsz\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Sprawdz warunek w 'test'. Jesli warunek jest prawdziwy, to zwroci 'if true'; jesli nie jest prawdziwy to zwroci 'if false'.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Liczba.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"/\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"arc sin\",\n    \"MATH_TRIG_ACOS\": \"arc cos\",\n    \"MATH_TRIG_ATAN\": \"arc tan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://pl.wikipedia.org/wiki/Arytmetyka\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Zwroci sume dwoch numerow.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Zwroci roznicy miedzy dwoch numerow.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Zwróć iloczyn dwóch liczb.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Zwróć iloraz dwóch liczb.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Zwróć pierwszą liczbę podniesioną do potęgi drugiej liczby.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"pierwiastek kwadratowy\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Zwróć pierwiastek kwadratowy danej liczby.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"wartość bezwzględna\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Zwróć wartość bezwzględną danej liczby.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Zwróć negację danej liczby.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Zwróć logarytm naturalny danej liczby.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Zwróć logarytm dziesiętny danej liczby.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Zwraca e do potęgi danej liczby.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Zwróć 10 do potęgi danej liczby.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Zwraca wartość sinusa o stopniu (nie radian).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Zwraca wartość cosinusa o stopniu (nie radian).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Zwróć tangens o stopniu (nie radian).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Zwróć arcus sinus danej liczby.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Zwróć arcus cosinus danej liczby.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Zwróć arcus tangens danej liczby.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Zwróć jedną wspólną stałą: π (3.141), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) lub ∞ (nieskończoność).\",\n    \"MATH_IS_EVEN\": \"jest parzysta\",\n    \"MATH_IS_ODD\": \"jest nieparzysta\",\n    \"MATH_IS_PRIME\": \"jest liczbą pierwszą\",\n    \"MATH_IS_WHOLE\": \"jest liczbą całkowitą\",\n    \"MATH_IS_POSITIVE\": \"jest dodatnia\",\n    \"MATH_IS_NEGATIVE\": \"jest ujemna\",\n    \"MATH_IS_DIVISIBLE_BY\": \"jest podzielna przez\",\n    \"MATH_IS_TOOLTIP\": \"Sprawdź, czy liczba jest parzysta, nieparzysta, pierwsza, całkowita, dodatnia, ujemna, lub jeśli jest podzielna przez konkretną liczbę.  Zwraca wartość \\\"prawda\\\" lub \\\"fałsz\\\".\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"zmien\",\n    \"MATH_CHANGE_INPUT_BY\": \"o\",\n    \"MATH_CHANGE_TOOLTIP\": \"Dodaj liczbę do zmiennej '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Zaokrąglić w górę lub w dół.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"zaokrąglić\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"zaokrąglić w górę\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"zaokrąglić w dół\",\n    \"MATH_ONLIST_HELPURL\": \"\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"suma z listy\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Zwraca sume wszystkich liczb z listy.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"minimalna wartość z listy\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Zwraca najnizszy numer w liscie.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"maksymalna wartość z listy\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Zwraca najwyzszy numer w liscie.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"średnia z listy\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Zwróć średnią (średnią arytmetyczną) wartości liczbowych z listy.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mediana z listy\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Zwróć medianę liczby na liście.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"dominanty listy\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Zwróć listę najczęściej występujących elementów na liście.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"odchylenie standardowe z listy\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Zwróć odchylenie standardowe listy.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"losowy element z listy\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Zwróć losowy element z listy.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"reszta z dzielenia %1 przez %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Zwraca resztę z dzielenia dwóch liczb przez siebie.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"zaokrągl %1 w dół %2 w górę %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Zaokrągl liczbę, aby była w określonych granicach (włącznie).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"losowa liczba całkowita od %1 do %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Zwróć losową liczbę całkowitą w ramach dwóch określonych granic, włącznie.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"losowy ułamek\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Zwróć losowy ułamek między 0.0 (włącznie), a 1.0 (wyłącznie).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Litera, wyraz lub linia tekstu.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"utwórz tekst z\",\n    \"TEXT_JOIN_TOOLTIP\": \"Utwórz fragment tekstu, łącząc ze sobą dowolną liczbę tekstów.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"połącz\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Dodaj, usuń lub zmień kolejność sekcji, aby zmodyfikować blok tekstowy.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Dodaj element do tekstu.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"do\",\n    \"TEXT_APPEND_APPENDTEXT\": \"dołącz tekst\",\n    \"TEXT_APPEND_TOOLTIP\": \"Dołącz tekst do zmiennej '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"długość %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Zwraca liczbę liter (łącznie ze spacjami) w podanym tekście.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 jest pusty\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Zwraca prawda (true), jeśli podany tekst jest pusty.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Zwraca indeks pierwszego/ostatniego wystąpienia pierwszego tekstu w drugim tekście. Zwraca wartość 0, jeśli tekst nie został znaleziony.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"w tekście\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"znajdź pierwsze wystąpienie tekstu\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"znajdź ostatnie wystąpienie tekstu\",\n    \"TEXT_INDEXOF_TAIL\": \"\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"z tekstu\",\n    \"TEXT_CHARAT_FROM_START\": \"pobierz literę #\",\n    \"TEXT_CHARAT_FROM_END\": \"pobierz literę # od końca\",\n    \"TEXT_CHARAT_FIRST\": \"pobierz pierwszą literę\",\n    \"TEXT_CHARAT_LAST\": \"pobierz ostatnią literę\",\n    \"TEXT_CHARAT_RANDOM\": \"pobierz losową literę\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Zwraca literę na określonej pozycji.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Zwraca określoną część tekstu.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"w tekście\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"pobierz podsłowo od litery #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"pobierz podsłowo od litery # od końca\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"pobierz podsłowo od pierwszej litery\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"do litery #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"do litery # od końca\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"do ostatniej litery\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Zwraca kopię tekstu z inną wielkością liter.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"zmień na WIELKIE LITERY\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"zmień na małe litery\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"zmień na od Wielkich Liter\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Zwróć kopię tekstu z usuniętymi spacjami z jednego lub z obu końców tekstu.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"usuń spacje po obu stronach tekstu\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"usuń spacje z lewej strony tekstu\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"usuń spacje z prawej strony tekstu\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"wydrukuj %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Drukuj określony tekst, liczbę lub coś innego.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"poproś o tekst z tą wiadomością\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"poproś o liczbę z tą wiadomością\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Zapytaj użytkownika  o liczbę.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Zapytaj użytkownika o jakiś tekst.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"utwórz pustą listę\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Zwraca listę, o długości 0, nie zawierającą rekordów z danymi\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Utwórz listę z dowolną ilością elementów.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"Tworzenie listy z\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Dodać, usunąć lub zmienić kolejność sekcji żeby zrekonfigurować blok tej listy.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Dodaj element do listy.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Tworzy listę składającą się z podanej wartości powtórzonej odpowiednią liczbę razy.\",\n    \"LISTS_REPEAT_TITLE\": \"stwórz listę, powtarzając element %1 %2 razy\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"długość %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Zwraca długość listy.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 jest pusty\",\n    \"LISTS_TOOLTIP\": \"Zwraca \\\"prawda\\\" jeśli lista jest pusta.\",\n    \"LISTS_INLIST\": \"na liście\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"znaleźć pierwsze wystąpienie elementu\",\n    \"LISTS_INDEX_OF_LAST\": \"znajduje ostatanie wystąpienie elementu\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Zwraca indeks pierwszego/ostatniego wystąpienia elementu na liście.  Zwraca wartość 0, jeśli tekst nie zostanie znaleziony.\",\n    \"LISTS_GET_INDEX_GET\": \"pobierz\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"Pobierz i usuń\",\n    \"LISTS_GET_INDEX_REMOVE\": \"usuń\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# od końca\",\n    \"LISTS_GET_INDEX_FIRST\": \"pierwszy\",\n    \"LISTS_GET_INDEX_LAST\": \"ostatni\",\n    \"LISTS_GET_INDEX_RANDOM\": \"losowy\",\n    \"LISTS_GET_INDEX_TAIL\": \"\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Zwraca element z konkretnej pozycji na liście. #1 to pierwszy element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Zwraca element z określonej pozycji na liście. #1 to ostatni element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Zwraca pierwszy element z listy.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Zwraca ostatni element z listy.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Zwraca losowy element z listy.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Usuwa i zwraca element z określonej pozycji na liście. #1 to pierwszy element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Usuwa i zwraca element z określonej pozycji na liście. #1 to ostatni element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Usuwa i zwraca pierwszy element z listy.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Usuwa i zwraca ostatni element z listy.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Usuwa i zwraca losowy element z listy.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Usuwa element z określonej pozycji na liście. #1 to pierwszy element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Usuwa element z określonej pozycji na liście. #1 to ostatni element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Usuwa pierwszy element z listy.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Usuwa ostatni element z listy.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Usuwa losowy element z listy.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"ustaw\",\n    \"LISTS_SET_INDEX_INSERT\": \"wstaw w\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"jako\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Wstawia element w odpowiednie miejsce na liście. #1 to pierwszy element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Wstawia element w odpowiednie miejsce na liście. #1 to ostatni element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Wstawia pierwszy element na liście.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Wstawia ostatni element na liście.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Wstawia losowy element na liście.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Wstawia element w odpowiednim miejscu na liście. #1 to pierwszy element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Wstawia element w odpowiednim miejscu na liście. #1 to ostatni element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Wstawia element na początku listy.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Wstaw element na koniec listy.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Wstawia element w losowym miejscu na liście.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"Pobierz listę podrzędną z #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"Pobierz listę podrzędną z # od końca\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"Pobierz listę podrzędną z pierwszego\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"do #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"do # od końca\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"do ostatniego\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Tworzy kopię z określoną część listy.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"Zwraca wartość tej zmiennej.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Utwórz blok 'ustaw %1'\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"przypisz\",\n    \"VARIABLES_SET_TAIL\": \"wartość\",\n    \"VARIABLES_SET_TOOLTIP\": \"Nadaj tej zmiennej wartość.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Utwórz blok 'pobierz %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"do\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"zrób coś\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"z:\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Tworzy funkcję bez wyniku.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"zwróć\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Tworzy funkcję z wynikiem.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Ostrzeżenie: Ta funkcja ma powtórzone parametry.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Uruchom funkcję zdefiniowaną przez użytkownika '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Uruchom funkcję zdefiniowaną przez użytkownika '%1' i skorzystaj z jej wyniku.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"wejścia\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nazwa wejścia:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Podświetl definicję funkcji\",\n    \"PROCEDURES_CREATE_DO\": \"Stwórz '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Jeśli wartość jest prawdziwa, zwróć drugą wartość.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Ostrzeżenie: Ten blok może być używany tylko w definicji funkcji.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/pms.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Borichèt\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"element\",\n    \"DUPLICATE_BLOCK\": \"Dupliché\",\n    \"ADD_COMMENT\": \"Gionté un coment\",\n    \"REMOVE_COMMENT\": \"Scancelé un coment\",\n    \"EXTERNAL_INPUTS\": \"Imission esterne\",\n    \"INLINE_INPUTS\": \"Imission an linia\",\n    \"DELETE_BLOCK\": \"Scancelé ël blòch\",\n    \"DELETE_X_BLOCKS\": \"Scancelé %1 blòch\",\n    \"COLLAPSE_BLOCK\": \"Arduve ël blòch\",\n    \"COLLAPSE_ALL\": \"Arduve ij blòch\",\n    \"EXPAND_BLOCK\": \"Dësvlupé ël blòch\",\n    \"EXPAND_ALL\": \"Dësvlupé ij blòch\",\n    \"DISABLE_BLOCK\": \"Disativé ël blòch\",\n    \"ENABLE_BLOCK\": \"Ativé ël blòch\",\n    \"HELP\": \"Agiut\",\n    \"CHANGE_VALUE_TITLE\": \"Modifiché ël valor:\",\n    \"NEW_VARIABLE\": \"Neuva variàbil...\",\n    \"NEW_VARIABLE_TITLE\": \"Nòm ëd la neuva variàbil:\",\n    \"RENAME_VARIABLE\": \"Arnomé la variàbil...\",\n    \"RENAME_VARIABLE_TITLE\": \"Arnomé tute le variàbij '%1' 'me:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Serne un color ant la taulòssa.\",\n    \"COLOUR_RANDOM_TITLE\": \"color a asar\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Serne un color a asar.\",\n    \"COLOUR_RGB_TITLE\": \"coloré con\",\n    \"COLOUR_RGB_RED\": \"ross\",\n    \"COLOUR_RGB_GREEN\": \"verd\",\n    \"COLOUR_RGB_BLUE\": \"bleu\",\n    \"COLOUR_RGB_TOOLTIP\": \"Creé un color con la quantità spessificà ëd ross, verd e bleu. Tuti ij valor a devo esse antra 0 e 100.\",\n    \"COLOUR_BLEND_TITLE\": \"mës-cé\",\n    \"COLOUR_BLEND_COLOUR1\": \"color 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"color 2\",\n    \"COLOUR_BLEND_RATIO\": \"rapòrt\",\n    \"COLOUR_BLEND_TOOLTIP\": \"A mës-cia doi color ansema con un rapòrt dàit (0,0 - 1,0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"arpete %1 vire\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"arpete\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"vire\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"fé\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Eseguì chèiche anstrussion vàire vire.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"arpete antramentre che\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"arpete fin-a a\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Cand un valor a l'é ver, eseguì chèiche anstrussion.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Cand un valor a l'é fàuss, eseguì chèiche anstrussion.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Fé an manera che la variàbil %1 a pija ij valor dal nùmer inissial fin-a al nùmer final, an contand për l'antërval ëspessificà, e eseguì ij bloch ëspessificà.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"conté con\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"da %1 a %2 për %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"për minca element\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"ant la lista\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Për minca element an na lista, dé ël valor ëd l'element a la variàbil '%1', peui eseguì chèiche anstrussion.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"seurte da la liassa\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continué con l'iterassion sucessiva dla liassa\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Seurte da la liassa anglobanta.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Sauté ël rest ëd sa liassa, e continué con l'iterassion apress.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Atension: Ës blòch a peul mach esse dovrà andrinta a na liassa.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Si un valor a l'é ver, antlora eseguì chèiche anstrussion.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Si un valor a l'é ver, antlora eseguì ël prim blòch d'anstrussion. Dësnò, eseguì ël second blòch d'anstrussion.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Si ël prim valor a l'é ver, antlora fé andé ël prim blòch d'anstrussion. Dësnò, si ël second valor a l'é ver, fé andé ël second blòch d'anstrussion.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Si ël prim valor a l'é ver, antlora fé andé ël prim blòch d'anstrussion. Dësnò, si ël second valor a l'é ver, fé andé ël second blòcj d'anstrussion. Si gnun dij valor a l'é ver, fé andé l'ùltim blòch d'anstrussion.\",\n    \"CONTROLS_IF_MSG_IF\": \"si\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"dësnò si\",\n    \"CONTROLS_IF_MSG_ELSE\": \"dësnò\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Gionté, gavé o riordiné le session për cinfiguré torna ës blòch si.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Gionté na condission al blòch si.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Gionté na condission final ch'a cheuj tut al blòch si.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Rësponde ver si le doe imission a son uguaj.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Rësponde ver si le doe imission a son nen uguaj.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Rësponde ver si la prima imission a l'é pi cita dla sconda.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Rësponde ver si la prima imission a l'é pi cita o ugual a la sconda.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Rësponde ver si la prima imission a l'é pi granda che la sconda.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Rësponde ver si la prima imission a l'é pi granda o ugual a la sconda.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Rësponde ver se tute doe j'imission a son vere.\",\n    \"LOGIC_OPERATION_AND\": \"e\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Rësponde ver se almanch un-a d'imission a l'é vera.\",\n    \"LOGIC_OPERATION_OR\": \"o\",\n    \"LOGIC_NEGATE_TITLE\": \"nen %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"A rëspond ver se l'imission a l'é fàussa. A rëspond fàuss se l'imission a l'é vera.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"ver\",\n    \"LOGIC_BOOLEAN_FALSE\": \"fàuss\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"A rëspond ver o fàuss.\",\n    \"LOGIC_NULL\": \"gnente\",\n    \"LOGIC_NULL_TOOLTIP\": \"A rëspond gnente.\",\n    \"LOGIC_TERNARY_CONDITION\": \"preuva\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"se ver\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"se fàuss\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Controlé la condission an 'preuva'. Se la condission a l'é vera, a rëspond con ël valor 'se ver'; dësnò a rëspond con ël valor 'se fàuss'.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Un nùmer.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"A smon la soma ëd doi nùmer.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"A smon la diferensa dij doi nùmer.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"A smon ël prodot dij doi nùmer.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"A smon ël cossient dij doi nùmer.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"A smon ël prim nùmer alvà a la potensa dël second.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"rèis quadra\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"A smon la rèis quadra d'un nùmer.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"assolù\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"A smon ël valor assolù d'un nùmer.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"A smon l'opòst d'un nùmer.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"A smon ël logaritm natural d'un nùmer.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"A smon ël logaritm an base 10 d'un nùmer.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"A smon e a la potensa d'un nùmer.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"A smon 10 a la potensa d'un nùmer.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"A smon ël sen ëd n'àngol an gré (pa an radiant).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"A smon ël cosen ëd n'àngol an gré (pa an radiant).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"A smon la tangenta ëd n'àngol an gré (pa an radiant).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"A smon l'arch-sen d'un nùmer.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"A smon l'arch-cosen d'un nùmer.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"A smon l'arch-tangenta d'un nùmer.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"A smon un-a dle costante comun-e π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) o ∞ (infinì).\",\n    \"MATH_IS_EVEN\": \"a l'é cobi\",\n    \"MATH_IS_ODD\": \"a l'é dëscobi\",\n    \"MATH_IS_PRIME\": \"a l'é prim\",\n    \"MATH_IS_WHOLE\": \"a l'é antregh\",\n    \"MATH_IS_POSITIVE\": \"a l'é positiv\",\n    \"MATH_IS_NEGATIVE\": \"a l'é negativ\",\n    \"MATH_IS_DIVISIBLE_BY\": \"a l'é divisìbil për\",\n    \"MATH_IS_TOOLTIP\": \"A contròla si un nùmer a l'é cobi, dëscobi, prim, antreghm positiv, negativ, o s'a l'é divisìbil për un nùmer dàit. A rëspond ver o fàuss.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"ancrementé\",\n    \"MATH_CHANGE_INPUT_BY\": \"për\",\n    \"MATH_CHANGE_TOOLTIP\": \"Gionté un nùmer a la variàbil '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"A arionda un nùmer për difet o ecess.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"ariondé\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"ariondé për ecess\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"ariondé për difet\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"soma dla lista\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"A smon la soma ëd tuti ij nùmer ant la lista.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"mìnim ëd la lista\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"A smon ël pi cit nùmer ëd la lista.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"màssim ëd la lista\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"A smon ël pi gròss nùmer ëd la lista.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"media dla lista\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"A smon la media (aritmética) dij valor numérich ant la lista.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mesan-a dla lista\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"A smon ël nùmer mesan ëd la lista.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"mòde dla lista\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"A smon na lista dj'element pi frequent ëd la lista.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"deviassion ëstàndard ëd la lista\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"A smon la deviassion ëstàndard ëd la lista.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"element a l'ancàpit ëd la lista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"A smon n'element a l'ancàpit da la lista.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"resta ëd %1:%2\",\n    \"MATH_MODULO_TOOLTIP\": \"A smon la resta ëd la division dij doi nùmer.\",\n    \"MATH_CONSTRAIN_TITLE\": \"limité %1 antra %2 e %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Limité un nùmer a esse antra le limitassion ëspessificà (comprèise).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"antregh aleatòri antra %1 e %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"A smon n'antregh aleatòri antra ij doi lìmit ëspessificà, comprèis.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"frassion aleatòria\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"A smon na frassion aleatòria antra 0,0 (comprèis) e 1,0 (esclus).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Na litra, na paròla o na linia ëd test.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"creé ël test con\",\n    \"TEXT_JOIN_TOOLTIP\": \"Creé un tòch ëd test an gionzend un nùmer qualsëssìa d'element.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"gionze\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Gionté, gavé o riordiné le session për configuré torna ës blòch ëd test.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Gionté n'element al test.\",\n    \"TEXT_APPEND_TO\": \"a\",\n    \"TEXT_APPEND_APPENDTEXT\": \"taché ël test\",\n    \"TEXT_APPEND_TOOLTIP\": \"Taché dël test a la variàbil '%1'.\",\n    \"TEXT_LENGTH_TITLE\": \"longheur ëd %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"A smon ël nùmer ëd litre (spassi comprèis) ant ël test fornì.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 a l'é veuid\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"A smon ver se ël test fornì a l'é veuid.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"A smon l'ìndes dla prima/ùltima ocorensa dël prim test ant ël second test. A smon 0 se ël test a l'é nen trovà.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"ant ël test\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"trové la prima ocorensa dël test\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"trové l'ùltima ocorensa dël test\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"ant ël test\",\n    \"TEXT_CHARAT_FROM_START\": \"oten-e la litra #\",\n    \"TEXT_CHARAT_FROM_END\": \"oten-e la litra # da la fin\",\n    \"TEXT_CHARAT_FIRST\": \"oten-e la prima litra\",\n    \"TEXT_CHARAT_LAST\": \"oten-e l'ùltima litra\",\n    \"TEXT_CHARAT_RANDOM\": \"oten-e na litra a l'ancàpit\",\n    \"TEXT_CHARAT_TOOLTIP\": \"A smon la litra ant la posission ëspessificà.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"A smon un tòch ëspessificà dël test.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"ant ël test\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"oten-e la sota-stringa da la litra #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"oten-e la sota-stringa da la litra # da la fin\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"oten-e la sota-stringa da la prima litra\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"fin-a a la litra #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"fin-a a la litra # da la fin\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"fin-a a l'ùltima litra\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"A smon na còpia dël test ant un caràter diferent.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"an MAJÙSCOL\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"an minùscul\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"an Majùscol A L'Ancamin Ëd Minca Paròla\",\n    \"TEXT_TRIM_TOOLTIP\": \"A smon na còpia dël test con jë spassi gavà da n'estremità o da tute doe.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"gavé jë spassi da le doe bande ëd\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"gavé jë spassi da la banda snistra ëd\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"gavé jë spassi da la banda drita ëd\",\n    \"TEXT_PRINT_TITLE\": \"smon-e %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Smon-e ël test, ël nùmer o n'àutr valor ëspessificà.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"anvit për un test con un mëssagi\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"anvit për un nùmer con un mëssagi\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Ciamé un nùmer a l'utent.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Ciamé un test a l'utent.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"creé na lista veuida\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Smon-e na lista, ëd longheur 0, ch'a conten gnun-a argistrassion\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Creé na lista con un nùmer qualsëssìa d'element.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"creé na lista con\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Gionté, gavé o riordiné le session për configuré torna cost blòch ëd lista.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Gionté n'element a la lista.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"A crea na lista ch'a consist dël valor dàit arpetù ël nùmer ëspessificà ëd vire.\",\n    \"LISTS_REPEAT_TITLE\": \"creé na lista con l'element %1 arpetù %2 vire\",\n    \"LISTS_LENGTH_TITLE\": \"longheur ëd %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"A smon la longheur ¨d na lista.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 a l'é veuid\",\n    \"LISTS_TOOLTIP\": \"A smon ver se la lista a l'é veuida.\",\n    \"LISTS_INLIST\": \"ant la lista\",\n    \"LISTS_INDEX_OF_FIRST\": \"trové la prima ocorensa dl'element\",\n    \"LISTS_INDEX_OF_LAST\": \"trové l'ùltima ocorensa dl'element\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"A smon l'ìndes ëd la prima/ùltima ocorensa dl'element ant la lista. A smon 0 se ël test a l'é nen trovà.\",\n    \"LISTS_GET_INDEX_GET\": \"oten-e\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"oten-e e eliminé\",\n    \"LISTS_GET_INDEX_REMOVE\": \"eliminé\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# da la fin\",\n    \"LISTS_GET_INDEX_FIRST\": \"prim\",\n    \"LISTS_GET_INDEX_LAST\": \"ùltim\",\n    \"LISTS_GET_INDEX_RANDOM\": \"a l'ancàpit\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"A smon l'element a la posission ëspessificà an na lista. #1 a l'é ël prim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"A smon l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"A smon ël prim element an na lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"A smon l'ùltim element an na lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"A smon n'element a l'ancàpit an na lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"A gava e a smon l'element a la posission ëspessificà an na lista. #1 a l'é 'l prim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"A gava e a smon l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"A gava e a smon ël prim element an na lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"A gava e a smon l'ùltim element an na lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"A gava e a smon n'element a l'ancàpit an na lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"A gava l'element a la posission ëspessificà an na lista. #1 a l'é ël prim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"A gava l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"A gava ël prim element an na lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"A gava l'ùltim element an na lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"A gava n'element a l'ancàpit da na lista.\",\n    \"LISTS_SET_INDEX_SET\": \"buté\",\n    \"LISTS_SET_INDEX_INSERT\": \"anserì an\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"tanme\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"A fissa l'element a la posission ëspessificà an na lista. #1 a l'é ël prim element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"A fissa l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"A fissa ël prim element an na lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"A fissa l'ùltim element an na lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"A fissa n'element a l'ancàpit an na lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"A anseriss l'element a la posission ëspessificà an na lista. #1 a l'é ël prim element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"A anseriss l'element a la posission ëspessificà an na lista. #1 a l'é l'ùltim element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"A anseriss l'element al prinsipi ëd na lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Gionté l'element a la fin ëd na lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"A anseriss l'element a l'ancàpit an na lista.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"oten-e la sot-lista da #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"oten-e la sot-lista da # da la fin\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"oten-e la sot-lista dal prim\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"fin-a a #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"fin-a a # da la fin\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"fin-a a l'ùltim\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"A crea na còpia dël tòch ëspessificà ëd na lista.\",\n    \"VARIABLES_GET_TOOLTIP\": \"A smon ël valor ëd sa variàbil.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Creé 'fissé %1'\",\n    \"VARIABLES_SET_TITLE\": \"fissé\",\n    \"VARIABLES_SET_TAIL\": \"a\",\n    \"VARIABLES_SET_TOOLTIP\": \"Fissé costa variàbil ugual al valor d'imission.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Creé 'oten-e %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"a\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"fé cheicòs\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"con:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"A crea na fonsion sensa surtìa.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"artorn\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"A crea na fonsion con na surtìa.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Atension: Costa fonsion a l'ha dij paràmeter duplicà.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Eseguì la fonsion '%1' definìa da l'utent.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Eseguì la fonsion '%1' definìa da l'utent e dovré sò arzultà.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"imission\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nòm ëd l'imission:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Sot-ligné la definission dla fonsion\",\n    \"PROCEDURES_CREATE_DO\": \"Creé '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Se un valor a l'é ver, antlora smon-e un second valor.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Atension: Ës blòch a podria esse dovrà mach an na definission ëd fonsion.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/pt-br.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Espertus\",\n            \"Prilopes\",\n            \"Mordecaista\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"item\",\n    \"DUPLICATE_BLOCK\": \"Duplicar\",\n    \"ADD_COMMENT\": \"Adicionar Comentário\",\n    \"REMOVE_COMMENT\": \"Remover Comentário\",\n    \"EXTERNAL_INPUTS\": \"Entrada externa\",\n    \"INLINE_INPUTS\": \"Entradas Internas\",\n    \"DELETE_BLOCK\": \"Remover Bloco\",\n    \"DELETE_X_BLOCKS\": \"Remover %1 Blocos\",\n    \"COLLAPSE_BLOCK\": \"Recolher Bloco\",\n    \"COLLAPSE_ALL\": \"Recolher Blocos\",\n    \"EXPAND_BLOCK\": \"Expandir Bloco\",\n    \"EXPAND_ALL\": \"Expandir Blocos\",\n    \"DISABLE_BLOCK\": \"Desabilitar Bloco\",\n    \"ENABLE_BLOCK\": \"Habilitar Bloco\",\n    \"HELP\": \"Ajuda\",\n    \"CHANGE_VALUE_TITLE\": \"Mudar valor:\",\n    \"NEW_VARIABLE\": \"Nova variável...\",\n    \"NEW_VARIABLE_TITLE\": \"Nome da nova variável:\",\n    \"RENAME_VARIABLE\": \"Renomear variável...\",\n    \"RENAME_VARIABLE_TITLE\": \"Renomear todas as variáveis '%1' para:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://pt.wikipedia.org/wiki/Cor\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Escolher uma cor da palheta de cores.\",\n    \"COLOUR_RANDOM_TITLE\": \"cor aleatória\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Escolher cor de forma aleatória.\",\n    \"COLOUR_RGB_TITLE\": \"colorir com\",\n    \"COLOUR_RGB_RED\": \"vermelho\",\n    \"COLOUR_RGB_GREEN\": \"verde\",\n    \"COLOUR_RGB_BLUE\": \"azul\",\n    \"COLOUR_RGB_TOOLTIP\": \"Cria uma cor de acordo com a quantidade especificada de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100.\",\n    \"COLOUR_BLEND_TITLE\": \"misturar\",\n    \"COLOUR_BLEND_COLOUR1\": \"cor 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"cor 2\",\n    \"COLOUR_BLEND_RATIO\": \"proporção\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Mistura duas cores dada uma proporção (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o#Repeti.C3.A7.C3.A3o_com_vari.C3.A1vel_de_controle\",\n    \"CONTROLS_REPEAT_TITLE\": \"Repita %1 vezes\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"repita\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"vezes\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"faça\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Faça algumas instruções várias vezes.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"repita enquanto\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"repita até\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Enquanto um valor for verdadeiro, então faça algumas instruções.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Enquanto um valor é falso, então faça algumas instruções.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Faz com que a variável %1 assuma os valores do número inicial ao número final, contando de acordo com o intervalo especificado, e executa os blocos especificados.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"contar com\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"de %1 até %2 por %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"para cada item\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"na lista\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Para cada item em uma lista, atribui o item à variável \\\"%1\\\", e então realiza algumas instruções.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"encerra o laço\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continua com a próxima iteração do laço\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Encerra o laço.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Ignora o resto deste laço, e continua com a próxima iteração.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Atenção: Este bloco só pode ser usado dentro de um laço.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Se um valor é verdadeiro, então realize algumas instruções.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Se um valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, realize o segundo bloco de instruções.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.  Se nenhum dos blocos for verdadeiro, realize o último bloco de instruções.\",\n    \"CONTROLS_IF_MSG_IF\": \"se\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"senão se\",\n    \"CONTROLS_IF_MSG_ELSE\": \"senão\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Acrescente, remova ou reordene seções para reconfigurar este bloco.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Acrescente uma condição para o bloco se.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Acrescente uma condição final para o bloco se.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://pt.wikipedia.org/wiki/Inequa%C3%A7%C3%A3o\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Retorna verdadeiro se ambas as entradas forem iguais.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Retorna verdadeiro se ambas as entradas forem diferentes.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Retorna verdadeiro se a primeira entrada for menor que a segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Retorna verdadeiro se a primeira entrada for maior que a segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Retorna verdadeiro se ambas as entradas forem verdadeiras.\",\n    \"LOGIC_OPERATION_AND\": \"e\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Retorna verdadeiro se uma das estradas for verdadeira.\",\n    \"LOGIC_OPERATION_OR\": \"ou\",\n    \"LOGIC_NEGATE_TITLE\": \"não %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Retorna verdadeiro se a entrada for falsa.  Retorna falsa se a entrada for verdadeira.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"verdadeiro\",\n    \"LOGIC_BOOLEAN_FALSE\": \"falso\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Retorna verdadeiro ou falso.\",\n    \"LOGIC_NULL\": \"nulo\",\n    \"LOGIC_NULL_TOOLTIP\": \"Retorna nulo.\",\n    \"LOGIC_TERNARY_CONDITION\": \"teste\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"se verdadeiro\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"se falso\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Avalia a condição em \\\"teste\\\". Se a condição for verdadeira retorna o valor \\\"se verdadeiro\\\", senão retorna o valor \\\"se falso\\\".\",\n    \"MATH_NUMBER_HELPURL\": \"https://pt.wikipedia.org/wiki/N%C3%BAmero\",\n    \"MATH_NUMBER_TOOLTIP\": \"Um número.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://pt.wikipedia.org/wiki/Aritm%C3%A9tica\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Retorna a soma dos dois números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Retorna a diferença entre os dois números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Retorna o produto dos dois números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Retorna o quociente da divisão dos dois números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Retorna o primeiro número elevado à potência do segundo número.\",\n    \"MATH_SINGLE_HELPURL\": \"https://pt.wikipedia.org/wiki/Raiz_quadrada\",\n    \"MATH_SINGLE_OP_ROOT\": \"raiz quadrada\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Retorna a raiz quadrada de um número.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absoluto\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Retorna o valor absoluto de um número.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Retorna o oposto de um número.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Retorna o logaritmo natural de um número.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Retorna o logaritmo em base 10 de um número.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Retorna o número e elevado à potência de um número.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Retorna 10 elevado à potência de um número.\",\n    \"MATH_TRIG_HELPURL\": \"https://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_trigonom%C3%A9trica\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Retorna o seno de um grau (não radiano).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Retorna o cosseno de um grau (não radiano).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Retorna a tangente de um grau (não radiano).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Retorna o arco seno de um número.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Retorna o arco cosseno de um número.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Retorna o arco tangente de um número.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://pt.wikipedia.org/wiki/Anexo:Lista_de_constantes_matem%C3%A1ticas\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito).\",\n    \"MATH_IS_EVEN\": \"é par\",\n    \"MATH_IS_ODD\": \"é ímpar\",\n    \"MATH_IS_PRIME\": \"é primo\",\n    \"MATH_IS_WHOLE\": \"é inteiro\",\n    \"MATH_IS_POSITIVE\": \"é positivo\",\n    \"MATH_IS_NEGATIVE\": \"é negativo\",\n    \"MATH_IS_DIVISIBLE_BY\": \"é divisível por\",\n    \"MATH_IS_TOOLTIP\": \"Verifica se um número é par, ímpar, inteiro, positivo, negativo, ou se é divisível por outro número.  Retorna verdadeiro ou falso.\",\n    \"MATH_CHANGE_HELPURL\": \"https://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"alterar\",\n    \"MATH_CHANGE_INPUT_BY\": \"por\",\n    \"MATH_CHANGE_TOOLTIP\": \"Soma um número à variável \\\"%1\\\".\",\n    \"MATH_ROUND_HELPURL\": \"https://pt.wikipedia.org/wiki/Arredondamento\",\n    \"MATH_ROUND_TOOLTIP\": \"Arredonda um número para cima ou para baixo.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"arredonda\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"arredonda para cima\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"arredonda para baixo\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"soma de uma lista\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Retorna a soma de todos os números na lista.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"menor da lista\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Retorna o menor número da lista.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"maior da lista\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Retorna o maior número da lista.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"média da lista\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Retorna a média aritmética dos números da lista.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mediana da lista\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Retorna a mediana dos números da lista.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"moda da lista\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Retorna uma lista do(s) item(ns) mais comum(ns) da lista.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"desvio padrão da lista\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Retorna o desvio padrão dos números da lista.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"item aleatório da lista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Retorna um elemento aleatório da lista.\",\n    \"MATH_MODULO_HELPURL\": \"https://pt.wikipedia.org/wiki/Opera%C3%A7%C3%A3o_m%C3%B3dulo\",\n    \"MATH_MODULO_TITLE\": \"resto da divisão de %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Retorna o resto da divisão de dois números.\",\n    \"MATH_CONSTRAIN_TITLE\": \"restringe %1 inferior %2 superior %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Restringe um número entre os limites especificados (inclusivo).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://pt.wikipedia.org/wiki/Gerador_de_n%C3%BAmeros_pseudoaleat%C3%B3rios\",\n    \"MATH_RANDOM_INT_TITLE\": \"inteiro aleatório entre %1 e %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Retorna um número inteiro entre os dois limites informados, inclusivo.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://pt.wikipedia.org/wiki/Gerador_de_n%C3%BAmeros_pseudoaleat%C3%B3rios\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"fração aleatória\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Retorna uma fração aleatória entre 0.0 (inclusivo) e 1.0 (exclusivo).\",\n    \"TEXT_TEXT_HELPURL\": \"https://pt.wikipedia.org/wiki/Cadeia_de_caracteres\",\n    \"TEXT_TEXT_TOOLTIP\": \"Uma letra, palavra ou linha de texto.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"criar texto com\",\n    \"TEXT_JOIN_TOOLTIP\": \"Criar um pedaço de texto juntando qualquer número de itens.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"unir\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Acrescentar um item ao texto.\",\n    \"TEXT_APPEND_TO\": \"para\",\n    \"TEXT_APPEND_APPENDTEXT\": \"acrescentar texto\",\n    \"TEXT_APPEND_TOOLTIP\": \"Acrescentar um pedaço de texto à variável \\\"%1\\\".\",\n    \"TEXT_LENGTH_TITLE\": \"tamanho de %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Retorna o número de letras (incluindo espaços) no texto fornecido.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 é vazio\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Retorna verdadeiro se o texto fornecido for vazio.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto.  Retorna 0 se o texto não for encontrado.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"no texto\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"primeira ocorrência do texto\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"última ocorrência do texto\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"no texto\",\n    \"TEXT_CHARAT_FROM_START\": \"obter letra nº\",\n    \"TEXT_CHARAT_FROM_END\": \"obter letra nº a partir do final\",\n    \"TEXT_CHARAT_FIRST\": \"obter primeira letra\",\n    \"TEXT_CHARAT_LAST\": \"obter última letra\",\n    \"TEXT_CHARAT_RANDOM\": \"obter letra aleatória\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Retorna a letra na posição especificada.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Retorna o trecho de texto especificado.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"no texto\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"obter trecho de letra nº\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"obter trecho de letra nº a partir do final\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"obter trecho de primeira letra\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"até letra nº\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"até letra nº a partir do final\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"até última letra\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Retorna uma cópia do texto em um formato diferente.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"para MAIÚSCULAS\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"para minúsculas\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"para Nomes Próprios\",\n    \"TEXT_TRIM_TOOLTIP\": \"Retorna uma cópia do texto com os espaços removidos de uma ou ambas extremidades.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"remover espaços de ambos os lados de\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"remover espaços à esquerda de\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"remover espaços à direita de\",\n    \"TEXT_PRINT_TITLE\": \"imprime %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Imprime o texto, número ou valor especificado.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"Pede um texto com uma mensagem\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"Pede um número com uma mensagem\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Pede ao usuário um número.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Pede ao usuário um texto.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"criar lista vazia\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Retorna uma lista, de tamanho 0, contendo nenhum registro\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Cria uma lista com a quantidade de itens informada.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"criar lista com\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Acrescenta, remove ou reordena seções para reconfigurar este bloco de lista.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Acrescenta um item à lista.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Cria uma lista consistindo no valor informado repetido o número de vezes especificado.\",\n    \"LISTS_REPEAT_TITLE\": \"criar lista com item %1 repetido %2 vezes\",\n    \"LISTS_LENGTH_TITLE\": \"tamanho de %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Retorna o tamanho de uma lista.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 é vazia\",\n    \"LISTS_TOOLTIP\": \"Retona verdadeiro se a lista estiver vazia.\",\n    \"LISTS_INLIST\": \"na lista\",\n    \"LISTS_INDEX_OF_FIRST\": \"encontre a primeira ocorrência do item\",\n    \"LISTS_INDEX_OF_LAST\": \"encontre a última ocorrência do item\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Retorna a posição da primeira/última ocorrência do item na lista.  Retorna 0 se o texto não for encontrado.\",\n    \"LISTS_GET_INDEX_GET\": \"obter\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"obter e remover\",\n    \"LISTS_GET_INDEX_REMOVE\": \"remover\",\n    \"LISTS_GET_INDEX_FROM_START\": \"nº\",\n    \"LISTS_GET_INDEX_FROM_END\": \"nº a partir do final\",\n    \"LISTS_GET_INDEX_FIRST\": \"primeiro\",\n    \"LISTS_GET_INDEX_LAST\": \"último\",\n    \"LISTS_GET_INDEX_RANDOM\": \"aleatório\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Retorna o item da lista na posição especificada.  #1 é o primeiro item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Retorna o item da lista na posição especificada.  #1 é o último item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Retorna o primeiro item em uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Retorna o último item em uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Retorna um item aleatório de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Remove e retorna o item na posição especificada em uma lista.  #1 é o primeiro item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Remove e retorna o item na posição especificada em uma lista.  #1 é o último item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Remove e retorna o primeiro item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Remove e retorna o último item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Remove e retorna um item aleatório de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Remove o item na posição especificada em uma lista.  #1 é o primeiro item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Remove o item na posição especificada em uma lista.  #1 é o último item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Remove o primeiro item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Remove o último item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Remove um item aleatório de uma lista.\",\n    \"LISTS_SET_INDEX_SET\": \"definir\",\n    \"LISTS_SET_INDEX_INSERT\": \"inserir em\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"como\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Define o item da posição especificada de uma lista.  #1 é o primeiro item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Define o item da posição especificada de uma lista.  #1 é o último item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Define o primeiro item de uma lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Define o último item de uma lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Define um item aleatório de uma lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Insere o item na posição especificada em uma lista.  #1 é o primeiro item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Insere o item na posição especificada em uma lista.  #1 é o último item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Insere o item no início de uma lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Insere o item no final de uma lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Insere o item em uma posição qualquer de uma lista.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"obtém sublista de nº\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"obtém sublista de nº a partir do final\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"obtém sublista a partir do primeiro\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"até nº\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"até nº a partir do final\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"até último\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Cria uma cópia da porção especificada de uma lista.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Retorna o valor desta variável.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Criar \\\"definir %1\\\"\",\n    \"VARIABLES_SET_TITLE\": \"definir\",\n    \"VARIABLES_SET_TAIL\": \"para\",\n    \"VARIABLES_SET_TOOLTIP\": \"Define esta variável para o valor da entrada.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Criar \\\"obter %1\\\"\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"para\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"faça algo\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"com:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Cria uma função que não tem retorno.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"retorna\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Cria uma função que possui um valor de retorno.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Atenção: Esta função tem parâmetros duplicados.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://pt.wikipedia.org/wiki/Sub-rotina\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Executa a função definida pelo usuário \\\"%1\\\".\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://pt.wikipedia.org/wiki/Sub-rotina\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Executa a função definida pelo usuário \\\"%1\\\" e usa seu retorno.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"entradas\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nome da entrada:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Destacar definição da função\",\n    \"PROCEDURES_CREATE_DO\": \"Criar \\\"%1\\\"\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Se um valor é verdadeiro, então retorna um valor.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Atenção: Este bloco só pode ser utilizado dentro da definição de uma função.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/pt.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"item\",\n    \"DUPLICATE_BLOCK\": \"Duplicar\",\n    \"ADD_COMMENT\": \"Adicionar Comentário\",\n    \"REMOVE_COMMENT\": \"Remover Comentário\",\n    \"EXTERNAL_INPUTS\": \"Entradas externas\",\n    \"INLINE_INPUTS\": \"Entradas Internas\",\n    \"DELETE_BLOCK\": \"Remover Bloco\",\n    \"DELETE_X_BLOCKS\": \"Remover %1 Blocos\",\n    \"COLLAPSE_BLOCK\": \"Colapsar Bloco\",\n    \"COLLAPSE_ALL\": \"Recolher Blocos\",\n    \"EXPAND_BLOCK\": \"Expandir Bloco\",\n    \"EXPAND_ALL\": \"Expandir Blocos\",\n    \"DISABLE_BLOCK\": \"Desabilitar Bloco\",\n    \"ENABLE_BLOCK\": \"Habilitar Bloco\",\n    \"HELP\": \"Ajuda\",\n    \"CHANGE_VALUE_TITLE\": \"Alterar valor:\",\n    \"NEW_VARIABLE\": \"Nova variável...\",\n    \"NEW_VARIABLE_TITLE\": \"Nome da nova variável:\",\n    \"RENAME_VARIABLE\": \"Renomear variável...\",\n    \"RENAME_VARIABLE_TITLE\": \"Renomear todas as variáveis '%1' para:\",\n    \"COLOUR_PICKER_HELPURL\": \"http://pt.wikipedia.org/wiki/Cor\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Escolhe uma cor da paleta de cores.\",\n    \"COLOUR_RANDOM_TITLE\": \"cor aleatória\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Escolher cor de forma aleatória.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"pinte com\",\n    \"COLOUR_RGB_RED\": \"vermelho\",\n    \"COLOUR_RGB_GREEN\": \"verde\",\n    \"COLOUR_RGB_BLUE\": \"azul\",\n    \"COLOUR_RGB_TOOLTIP\": \"Cria uma cor de acordo com a quantidade especificada de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"misturar\",\n    \"COLOUR_BLEND_COLOUR1\": \"cor 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"cor 2\",\n    \"COLOUR_BLEND_RATIO\": \"proporção\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Mistura duas cores dada uma proporção (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"http://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o#Repeti.C3.A7.C3.A3o_com_vari.C3.A1vel_de_controle\",\n    \"CONTROLS_REPEAT_TITLE\": \"repita %1 vez\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"repita\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"vezes\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"faça\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Faça algumas instruções várias vezes.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"repita enquanto\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"repita até\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Enquanto um valor for verdadeiro, então faça algumas instruções.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Enquanto um valor for falso, então faça algumas instruções.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Faz com que a variável %1 assuma os valores desde o número inicial até ao número final, contando de acordo com o intervalo especificado e executa os blocos especificados.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"contar com\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"de %1 até %2 de %3 em %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Ciclos#para_cada\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"para cada item\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"na lista\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Para cada item numa lista, define a variável \\\"%1\\\" para o item e então faz algumas instruções.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"sair do ciclo\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continuar com a próxima iteração do ciclo\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Sair do ciclo que está contido.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Ignora o resto deste ciclo e continua na próxima iteração.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Atenção: Este bloco só pode ser usado dentro de um ciclo.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Se um valor é verdadeiro, então realize alguns passos.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Se um valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, realize o segundo bloco de instruções\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções.  Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.  Se nenhum dos blocos for verdadeiro, realize o último bloco de instruções.\",\n    \"CONTROLS_IF_MSG_IF\": \"se\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"senão se\",\n    \"CONTROLS_IF_MSG_ELSE\": \"senão\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Acrescente, remova ou reordene secções para reconfigurar este bloco se.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Acrescente uma condição ao bloco se.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Acrescente uma condição de excepação final para o bloco se.\",\n    \"LOGIC_COMPARE_HELPURL\": \"http://pt.wikipedia.org/wiki/Inequa%C3%A7%C3%A3o\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Retorna verdadeiro se ambas as entradas forem iguais entre si.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Retorna verdadeiro se ambas as entradas forem diferentes entre si.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Retorna verdadeiro se a primeira entrada for menor que a segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Retorna verdadeiro se a primeira entrada for maior que a segunda entrada.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Retorna verdadeiro se ambas as entradas forem verdadeiras.\",\n    \"LOGIC_OPERATION_AND\": \"e\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Retorna verdadeiro se pelo menos uma das estradas for verdadeira.\",\n    \"LOGIC_OPERATION_OR\": \"ou\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"não %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Retorna verdadeiro se a entrada for falsa.  Retorna falso se a entrada for verdadeira.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"verdadeiro\",\n    \"LOGIC_BOOLEAN_FALSE\": \"falso\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Retorna verdadeiro ou falso.\",\n    \"LOGIC_NULL_HELPURL\": \"http://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"nulo\",\n    \"LOGIC_NULL_TOOLTIP\": \"Retorna nulo.\",\n    \"LOGIC_TERNARY_HELPURL\": \"http://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"teste\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"se verdadeiro\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"se falso\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Avalia a condição em \\\"teste\\\". Se a condição for verdadeira retorna o valor \\\"se verdadeiro\\\", senão retorna o valor \\\"se falso\\\".\",\n    \"MATH_NUMBER_HELPURL\": \"http://pt.wikipedia.org/wiki/N%C3%BAmero\",\n    \"MATH_NUMBER_TOOLTIP\": \"Um número.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"http://pt.wikipedia.org/wiki/Aritm%C3%A9tica\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Retorna a soma de dois números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Retorna a diferença de dois números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Retorna o produto de dois números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Retorna o quociente da divisão de dois números.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Retorna o primeiro número elevado à potência do segundo número.\",\n    \"MATH_SINGLE_HELPURL\": \"http://pt.wikipedia.org/wiki/Raiz_quadrada\",\n    \"MATH_SINGLE_OP_ROOT\": \"raíz quadrada\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Retorna a raiz quadrada de um número.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absoluto\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Retorna o valor absoluto de um número.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Retorna o oposto de um número.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Retorna o logarítmo natural de um número.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Retorna o logarítmo em base 10 de um número.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Retorna o número e elevado à potência de um número.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Retorna 10 elevado à potência de um número.\",\n    \"MATH_TRIG_HELPURL\": \"http://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_trigonom%C3%A9trica\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Retorna o seno de um grau (não radiano).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Retorna o cosseno de um grau (não radiano).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Retorna a tangente de um grau (não radiano).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Retorna o arco seno de um número.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Retorna o arco cosseno de um número.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Retorna o arco tangente de um número.\",\n    \"MATH_CONSTANT_HELPURL\": \"http://pt.wikipedia.org/wiki/Anexo:Lista_de_constantes_matem%C3%A1ticas\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito).\",\n    \"MATH_IS_EVEN\": \"é par\",\n    \"MATH_IS_ODD\": \"é impar\",\n    \"MATH_IS_PRIME\": \"é primo\",\n    \"MATH_IS_WHOLE\": \"é inteiro\",\n    \"MATH_IS_POSITIVE\": \"é positivo\",\n    \"MATH_IS_NEGATIVE\": \"é negativo\",\n    \"MATH_IS_DIVISIBLE_BY\": \"é divisível por\",\n    \"MATH_IS_TOOLTIP\": \"Verifica se um número é par, impar, primo, inteiro, positivo, negativo, ou se é divisível por outro número.  Retorna verdadeiro ou falso.\",\n    \"MATH_CHANGE_HELPURL\": \"http://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"alterar\",\n    \"MATH_CHANGE_INPUT_BY\": \"por\",\n    \"MATH_CHANGE_TOOLTIP\": \"Soma um número à variável \\\"%1\\\".\",\n    \"MATH_ROUND_HELPURL\": \"http://pt.wikipedia.org/wiki/Arredondamento\",\n    \"MATH_ROUND_TOOLTIP\": \"Arredonda um número para cima ou para baixo.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"arredonda\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"arredonda para cima\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"arredonda para baixo\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"soma da lista\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Retorna a soma de todos os números da lista.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"menor de uma lista\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Retorna o menor número da lista.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"maior de uma lista\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Retorna o maior número da lista.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"média de uma lista\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Retorna a média aritmética dos valores números da lista.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mediana de uma lista\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Retorna a mediana da lista.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"moda de uma lista\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Retorna a lista de item(ns) mais comum(ns) da lista.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"desvio padrão de uma lista\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Retorna o desvio padrão dos números da lista.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"item aleatório de uma lista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Retorna um elemento aleatório da lista.\",\n    \"MATH_MODULO_HELPURL\": \"http://pt.wikipedia.org/wiki/Opera%C3%A7%C3%A3o_m%C3%B3dulo\",\n    \"MATH_MODULO_TITLE\": \"resto da divisão de %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Retorna o resto da divisão de dois números.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"restringe %1 inferior %2 superior %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Restringe um número entre os limites especificados (inclusive).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"http://pt.wikipedia.org/wiki/N%C3%BAmero_aleat%C3%B3rio\",\n    \"MATH_RANDOM_INT_TITLE\": \"inteiro aleatório entre %1 e %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Retorna um número inteiro entre os dois limites especificados, inclusive.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"http://pt.wikipedia.org/wiki/N%C3%BAmero_aleat%C3%B3rio\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"fração aleatória\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Insere uma fração aleatória entre 0.0 (inclusive) e 1.0 (exclusive).\",\n    \"TEXT_TEXT_HELPURL\": \"http://pt.wikipedia.org/wiki/Cadeia_de_caracteres\",\n    \"TEXT_TEXT_TOOLTIP\": \"Uma letra, palavra ou linha de texto.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"criar texto com\",\n    \"TEXT_JOIN_TOOLTIP\": \"Criar um pedaço de texto juntando qualquer número de itens.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"unir\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Acrescentar um item ao texto.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"para\",\n    \"TEXT_APPEND_APPENDTEXT\": \"acrescentar texto\",\n    \"TEXT_APPEND_TOOLTIP\": \"Acrescentar um pedaço de texto à variável \\\"%1\\\".\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"tamanho de %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Devolve o número de letras (incluindo espaços) do texto fornecido.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 está vazio\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Retorna verdadeiro se o texto fornecido estiver vazio.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto.  Retorna 0 se o texto não for encontrado.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"no texto\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"primeira ocorrência do texto\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"última ocorrência do texto\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"no texto\",\n    \"TEXT_CHARAT_FROM_START\": \"obter letra nº\",\n    \"TEXT_CHARAT_FROM_END\": \"obter letra nº a partir do final\",\n    \"TEXT_CHARAT_FIRST\": \"obter primeira letra\",\n    \"TEXT_CHARAT_LAST\": \"obter última letra\",\n    \"TEXT_CHARAT_RANDOM\": \"obter letra aleatória\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Retorna a letra na posição especificada.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Retorna a parte especificada do texto.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"no texto\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"obter subsequência de tamanho #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"obter subsequência de tamanho # a partir do final\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"obter subsequência a partir da primeira letra\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"até letra nº\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"até letra nº a partir do final\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"até última letra\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Retorna uma cópia do texto em formato diferente.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"para MAIÚSCULAS\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"para minúsculas\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"para Iniciais Maiúsculas\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Retorna uma cópia do texto com os espaços removidos de uma ou ambas as extremidades.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"remover espaços de ambos os lados\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"remover espaços à esquerda\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"remover espaços à direita\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"imprime %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Imprime o texto, número ou outro valor especificado.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"Pede um texto com a mensagem\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"pede um número com a mensagem\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Pede ao utilizador um número.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Pede ao utilizador um texto.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"criar lista vazia\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Retorna uma lista, de tamanho 0, contendo nenhum registo\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Cria uma lista com qualquer número de itens.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"criar lista com\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Acrescente, remova ou reordene as seções para reconfigurar este bloco lista.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Acrescenta um item à lista.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Cria uma lista constituída por um dado valor repetido o número de vezes especificado.\",\n    \"LISTS_REPEAT_TITLE\": \"criar lista com o item %1 repetido %2 vezes\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"tamanho de %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Retorna o tamanho de uma lista.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 está vazia\",\n    \"LISTS_TOOLTIP\": \"Retona verdadeiro se a lista estiver vazia.\",\n    \"LISTS_INLIST\": \"na lista\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"encontre a primeira ocorrência do item\",\n    \"LISTS_INDEX_OF_LAST\": \"encontre a última ocorrência do item\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Retorna a posição da primeira/última ocorrência do item na lista.  Retorna 0 se o texto não for encontrado.\",\n    \"LISTS_GET_INDEX_GET\": \"obter\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"obter e remover\",\n    \"LISTS_GET_INDEX_REMOVE\": \"remover\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# a partir do final\",\n    \"LISTS_GET_INDEX_FIRST\": \"primeiro\",\n    \"LISTS_GET_INDEX_LAST\": \"último\",\n    \"LISTS_GET_INDEX_RANDOM\": \"aleatório\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Retorna o item na posição especificada da lista .  #1 é o primeiro item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Retorna o item da lista na posição especificada.  #1 é o último item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Retorna o primeiro item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Retorna o último item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Retorna um item aleatório de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Remove e retorna o item na posição especificada de uma lista.  #1 é o primeiro item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Remove e retorna o item na posição especificada de uma lista.  #1 é o último item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Remove e retorna o primeiro item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Remove e retorna o último item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Remove e retorna um item aleatório de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Remove o item de uma posição especifica da lista.  #1 é o primeiro item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Remove o item na posição especificada de uma lista.  #1 é o ultimo item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Remove o primeiro item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Remove o último item de uma lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Remove um item aleatório de uma lista.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"definir\",\n    \"LISTS_SET_INDEX_INSERT\": \"inserir em\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"como\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Define o item na posição especificada de uma lista.  #1 é o primeiro item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Define o item na posição especificada de uma lista.  #1 é o último item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Define o primeiro item de uma lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Define o último item de uma lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Define um item aleatório de uma lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Insere o item numa posição especificada numa lista.  #1 é o primeiro item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Insere o item numa posição especificada de uma lista.  #1 é o último item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Insere o item no início da lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Insere o item no final da lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Insere o item numa posição aleatória de uma lista.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"obtem sublista de #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"obtem sublista de # a partir do final\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"obtem sublista da primeira lista\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"até #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"até #, a partir do final\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"para o último\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Cria uma cópia da porção especificada de uma lista.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Retorna o valor desta variável.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Criar \\\"definir %1\\\"\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"definir\",\n    \"VARIABLES_SET_TAIL\": \"para\",\n    \"VARIABLES_SET_TOOLTIP\": \"Define esta variável para o valor inserido.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Criar \\\"obter %1\\\"\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"para\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"faz algo\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"com:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Cria uma função que não tem retorno.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"retorna\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Cria uma função que possui um valor de retorno.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Atenção: Esta função tem parâmetros duplicados.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"http://pt.wikipedia.org/wiki/Sub-rotina\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Executa a função \\\"%1\\\".\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"http://pt.wikipedia.org/wiki/Sub-rotina\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Executa a função \\\"%1\\\" e usa o seu retorno.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"entradas\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nome da entrada:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Destacar definição da função\",\n    \"PROCEDURES_CREATE_DO\": \"Criar \\\"%1\\\"\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"se o valor é verdadeiro, então retorna um segundo valor.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Atenção: Este bloco só pode ser utilizado dentro da definição de uma função.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/qqq.json",
    "content": "{\n    \"VARIABLES_DEFAULT_NAME\": \"default name - A simple, general default name for a variable, preferably short. For more context, see [[Translating:Blockly#infrequent_message_types]].\",\n    \"DUPLICATE_BLOCK\": \"context menu - Make a copy of the selected block (and any blocks it contains).\",\n    \"ADD_COMMENT\": \"context menu - Add a descriptive comment to the selected block.\",\n    \"REMOVE_COMMENT\": \"context menu - Remove the descriptive comment from the selected block.\",\n    \"EXTERNAL_INPUTS\": \"context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block.  See [[Translating:Blockly#context_menus]].\",\n    \"INLINE_INPUTS\": \"context menu - Change from 'internal' to 'external' mode for displaying blocks used as inputs to the selected block.  See [[Translating:Blockly#context_menus]].\",\n    \"DELETE_BLOCK\": \"context menu - Permanently delete the selected block.\",\n    \"DELETE_X_BLOCKS\": \"context menu - Permanently delete the %1 selected blocks.\\n\\nParameters:\\n* %1 - an integer greater than 1.\",\n    \"COLLAPSE_BLOCK\": \"context menu - Make the appearance of the selected block smaller by hiding some information about it.\",\n    \"COLLAPSE_ALL\": \"context menu - Make the appearance of the selected blocks smaller by hiding some information about it.  Use the same terminology as in the previous message.\",\n    \"EXPAND_BLOCK\": \"context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier.\",\n    \"EXPAND_ALL\": \"context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier.  Use the same terminology as in the previous message.\",\n    \"DISABLE_BLOCK\": \"context menu - Make the selected block have no effect (unless reenabled).\",\n    \"ENABLE_BLOCK\": \"context menu - Make the selected block have effect (after having been disabled earlier).\",\n    \"HELP\": \"context menu - Provide helpful information about the selected block.\\n{{Identical|Help}}\",\n    \"CHAT\": \"collaboration instruction - Tell the user that they can talk with other users.\",\n    \"CHANGE_VALUE_TITLE\": \"prompt - This message is only seen in the Opera browser.  With most browsers, users can edit numeric values in blocks by just clicking and typing.  Opera does not allows this, so we have to open a new window and prompt users with this message to chanage a value.\",\n    \"NEW_VARIABLE\": \"dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices.  It is used to define a new variable.  See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\",\n    \"NEW_VARIABLE_TITLE\": \"prompt - Prompts the user to enter the name for a new variable.  See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\",\n    \"RENAME_VARIABLE\": \"dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices.  It is used to rename the current variable.  See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\",\n    \"RENAME_VARIABLE_TITLE\": \"prompt - Prompts the user to enter the new name for the selected variable.  See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\\n\\nParameters:\\n* %1 - the name of the variable to be renamed.\",\n    \"COLOUR_PICKER_HELPURL\": \"url - Information about colour.\",\n    \"COLOUR_PICKER_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Picking_a_colour_from_a_palette https://code.google.com/p/blockly/wiki/Colour#Picking_a_colour_from_a_palette].\",\n    \"COLOUR_RANDOM_HELPURL\": \"url - A link that displays a random colour each time you visit it.\",\n    \"COLOUR_RANDOM_TITLE\": \"block text - Title of block that generates a colour at random.\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Generating_a_random_colour https://code.google.com/p/blockly/wiki/Colour#Generating_a_random_colour].\",\n    \"COLOUR_RGB_HELPURL\": \"url - A link for color codes with percentages (0-100%) for each component, instead of the more common 0-255, which may be more difficult for beginners.\",\n    \"COLOUR_RGB_TITLE\": \"block text - Title of block for [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\",\n    \"COLOUR_RGB_RED\": \"block input text - The amount of red (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\\n{{Identical|Red}}\",\n    \"COLOUR_RGB_GREEN\": \"block input text - The amount of green (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\",\n    \"COLOUR_RGB_BLUE\": \"block input text - The amount of blue (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\\n{{Identical|Blue}}\",\n    \"COLOUR_RGB_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\",\n    \"COLOUR_BLEND_HELPURL\": \"url - A useful link that displays blending of two colors.\",\n    \"COLOUR_BLEND_TITLE\": \"block text - A verb for blending two shades of paint.\",\n    \"COLOUR_BLEND_COLOUR1\": \"block input text - The first of two colours to [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend].\",\n    \"COLOUR_BLEND_COLOUR2\": \"block input text - The second of two colours to [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend].\",\n    \"COLOUR_BLEND_RATIO\": \"block input text - The proportion of the [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend] containing the first color; the remaining proportion is of the second colour.  For example, if the first colour is red and the second color blue, a ratio of 1 would yield pure red, a ratio of .5 would yield purple (equal amounts of red and blue), and a ratio of 0 would yield pure blue.\",\n    \"COLOUR_BLEND_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Blending_colours https://code.google.com/p/blockly/wiki/Colour#Blending_colours].\",\n    \"CONTROLS_REPEAT_HELPURL\": \"url - Describes 'repeat loops' in computer programs; consider using the translation of the page [https://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow].\",\n    \"CONTROLS_REPEAT_TITLE\": \"block input text - Title of [https://code.google.com/p/blockly/wiki/Loops#repeat repeat block].\\n\\nParameters:\\n* %1 - the number of times the body of the loop should be repeated.\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"block text - Text preceding the number of repetitions in a [https://code.google.com/p/blockly/wiki/Loops#repeat repeat block]. (This is redundant with the previous message but is needed to support older code.)\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"block text - Text following the number of times a [https://code.google.com/p/blockly/wiki/Loops#repeat repeat loop] should be repeated. (This is redundant but is needed to support older code.)\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"block text - Preceding the blocks in the body of the loop.  See [https://code.google.com/p/blockly/wiki/Loops https://code.google.com/p/blockly/wiki/Loops].\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat https://code.google.com/p/blockly/wiki/Loops#repeat].\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"url - Describes 'while loops' in computer programs; consider using the translation of [https://en.wikipedia.org/wiki/While_loop https://en.wikipedia.org/wiki/While_loop], if present, or [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow].\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"dropdown - Specifies that a loop should [https://code.google.com/p/blockly/wiki/Loops#Repeat_while repeat while] the following condition is true.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"dropdown - Specifies that a loop should [https://code.google.com/p/blockly/wiki/Loops#Repeat_until repeat until] the following condition becomes true.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat_while Loops#repeat_while https://code.google.com/p/blockly/wiki/Loops#repeat_while Loops#repeat_while].\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat_until https://code.google.com/p/blockly/wiki/Loops#repeat_until].\",\n    \"CONTROLS_FOR_HELPURL\": \"url - Describes 'for loops' in computer programs.  Consider using your language's translation of [https://en.wikipedia.org/wiki/For_loop https://en.wikipedia.org/wiki/For_loop], if present.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Loops#count_with https://code.google.com/p/blockly/wiki/Loops#count_with].\\n\\nParameters:\\n* %1 - the name of the loop variable.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"block title - Title of [https://code.google.com/p/blockly/wiki/Loops#count_with count with] blocks. [[File:Blockly-count-with.png]]\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"block text - Starting with a (usually lower) number in a range (%1), ending with a (usually higher) number in a range (%2), and counting the iterations by a number of steps (%3).  As in [https://code.google.com/p/blockly/wiki/Loops#count_with https://code.google.com/p/blockly/wiki/Loops#count_with]. [[File:Blockly-count-with.png]]\",\n    \"CONTROLS_FOREACH_HELPURL\": \"url - Describes 'for-each loops' in computer programs.  Consider using your language's translation of [https://en.wikipedia.org/wiki/Foreach https://en.wikipedia.org/wiki/Foreach] if present.\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"block text - Title of [https://code.google.com/p/blockly/wiki/Loops#for_each for each block].\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"block text - Preceding the list that should be iterated over in a [https://code.google.com/p/blockly/wiki/Loops#for_each for each loop].\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"block text - Following the list that should be iterated over in a [https://code.google.com/p/blockly/wiki/Loops#for_each for each loop].  This is empty in most, but not all, languages.\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"block text - Description of [https://code.google.com/p/blockly/wiki/Loops#for_each for each blocks].\\n\\nParameters:\\n* %1 - the name of the loop variable.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"url - Describes control flow in computer programs.  Consider using your language's translation of [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow], if it exists.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"dropdown - The current loop should be exited.  See [https://code.google.com/p/blockly/wiki/Loops#break https://code.google.com/p/blockly/wiki/Loops#break].\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"dropdown - The current iteration of the loop should be ended and the next should begin.  See [https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration].\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Loops#break_out_of_loop https://code.google.com/p/blockly/wiki/Loops#break_out_of_loop].\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration].\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"warning - The user has tried placing a block outside of a loop (for each, while, repeat, etc.), but this type of block may only be used within a loop.  See [https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks].\",\n    \"CONTROLS_IF_HELPURL\": \"url - Describes conditional statements (if-then-else) in computer programs.  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_else https://en.wikipedia.org/wiki/If_else], if present.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If_blocks 'if' blocks].  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else_blocks if-else blocks].  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else-If_blocks if-else-if blocks].  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else-If-Else_blocks if-else-if-else blocks].  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.\",\n    \"CONTROLS_IF_MSG_IF\": \"block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse]. It is recommended, but not essential, that this have text in common with the translation of 'else if'\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse].  The English words 'otherwise if' would probably be clearer than 'else if', but the latter is used because it is traditional and shorter.\",\n    \"CONTROLS_IF_MSG_ELSE\": \"block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse].  The English word 'otherwise' would probably be superior to 'else', but the latter is used because it is traditional and shorter.\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"tooltip - Describes the 'else if' subblock during [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"tooltip - Describes the 'else' subblock during [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].\",\n    \"LOGIC_COMPARE_HELPURL\": \"url - Information about comparisons.\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"tooltip - Describes the equals (=) block.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"tooltip - Describes the equals (\\u0026ne;) block.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"tooltip - Describes the equals (\\u0026lt;) block.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"tooltip - Describes the equals (\\u0026le;) block.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"tooltip - Describes the equals (\\u0026gt;) block.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"tooltip - Describes the equals (\\u0026ge;) block.\",\n    \"LOGIC_OPERATION_HELPURL\": \"url - Information about the Boolean conjunction ('and') and disjunction ('or') operators.  Consider using the translation of [https://en.wikipedia.org/wiki/Boolean_logic https://en.wikipedia.org/wiki/Boolean_logic], if it exists in your language.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"tooltip - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction].\",\n    \"LOGIC_OPERATION_AND\": \"block text - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction].\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction].\",\n    \"LOGIC_OPERATION_OR\": \"block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction].\",\n    \"LOGIC_NEGATE_HELPURL\": \"url - Information about logical negation.  The translation of [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation] is recommended if it exists in the target language.\",\n    \"LOGIC_NEGATE_TITLE\": \"block text - This is a unary operator that returns ''false'' when the input is ''true'', and ''true'' when the input is ''false''. \\n\\nParameters:\\n* %1 - the input (which should be either the value 'true' or 'false')\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"tooltip - See [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation].\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"url - Information about the logic values ''true'' and ''false''.  Consider using the translation of [https://en.wikipedia.org/wiki/Truth_value https://en.wikipedia.org/wiki/Truth_value] if it exists in your language.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''true''.\",\n    \"LOGIC_BOOLEAN_FALSE\": \"block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''false''.\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"tooltip - Indicates that the block returns either of the two possible [https://en.wikipedia.org/wiki/Truth_value logical values].\",\n    \"LOGIC_NULL_HELPURL\": \"url - Provide a link to the translation of [https://en.wikipedia.org/wiki/Nullable_type https://en.wikipedia.org/wiki/Nullable_type], if it exists in your language; otherwise, do not worry about translating this advanced concept.\",\n    \"LOGIC_NULL\": \"block text - In computer languages, ''null'' is a special value that indicates that no value has been set.  You may use your language's word for 'nothing' or 'invalid'.\",\n    \"LOGIC_NULL_TOOLTIP\": \"tooltip - This should use the word from the previous message.\",\n    \"LOGIC_TERNARY_HELPURL\": \"url - Describes the programming language operator known as the ''ternary'' or ''conditional'' operator.  It is recommended that you use the translation of [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:] if it exists.\",\n    \"LOGIC_TERNARY_CONDITION\": \"block input text - Label for the input whose value determines which of the other two inputs is returned.  In some programming languages, this is called a ''''predicate''''.\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"block input text - Indicates that the following input should be returned (used as output) if the test input is true.  Remember to try to keep block text terse (short).\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"block input text - Indicates that the following input should be returned (used as output) if the test input is false.\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"tooltip - See [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:].\",\n    \"MATH_NUMBER_HELPURL\": \"url - Information about (real) numbers.\",\n    \"MATH_NUMBER_TOOLTIP\": \"tooltip - Any positive or negative number, not necessarily an integer.\",\n    \"MATH_ADDITION_SYMBOL\": \"math - The symbol for the binary operation addition.\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"math - The symbol for the binary operation indicating that the right operand should be subtracted from the left operand.\",\n    \"MATH_DIVISION_SYMBOL\": \"math - The binary operation indicating that the left operand should be divided by the right operand.\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"math - The symbol for the binary operation multiplication.\",\n    \"MATH_POWER_SYMBOL\": \"math - The symbol for the binary operation exponentiation.  Specifically, if the value of the left operand is L and the value of the right operand (the exponent) is R, multiply L by itself R times.  (Fractional and negative exponents are also legal.)\",\n    \"MATH_TRIG_SIN\": \"math - The short name of the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine].\",\n    \"MATH_TRIG_COS\": \"math - The short name of the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine].\",\n    \"MATH_TRIG_TAN\": \"math - The short name of the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent].\",\n    \"MATH_TRIG_ASIN\": \"math - The short name of the ''inverse of'' the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine].\",\n    \"MATH_TRIG_ACOS\": \"math - The short name of the ''inverse of'' the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine].\",\n    \"MATH_TRIG_ATAN\": \"math - The short name of the ''inverse of'' the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent].\",\n    \"MATH_ARITHMETIC_HELPURL\": \"url - Information about addition, subtraction, multiplication, division, and exponentiation.\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"tooltip - See [https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition].\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"tooltip - See [https://en.wikipedia.org/wiki/Subtraction https://en.wikipedia.org/wiki/Subtraction].\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"tooltip - See [https://en.wikipedia.org/wiki/Multiplication https://en.wikipedia.org/wiki/Multiplication].\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"tooltip - See [https://en.wikipedia.org/wiki/Division_(mathematics) https://en.wikipedia.org/wiki/Division_(mathematics)].\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"tooltip - See [https://en.wikipedia.org/wiki/Exponentiation https://en.wikipedia.org/wiki/Exponentiation].\",\n    \"MATH_SINGLE_HELPURL\": \"url - Information about the square root operation.\",\n    \"MATH_SINGLE_OP_ROOT\": \"dropdown - This computes the positive [https://en.wikipedia.org/wiki/Square_root square root] of its input.  For example, the square root of 16 is 4.\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"tooltip - Please use the same term as in the previous message.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"dropdown - This leaves positive numeric inputs changed and inverts negative inputs.  For example, the absolute value of 5 is 5; the absolute value of -5 is also 5.  For more information, see [https://en.wikipedia.org/wiki/Absolute_value https://en.wikipedia.org/wiki/Absolute_value].\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"tooltip - Please use the same term as in the previous message.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"tooltip - Calculates '''0-n''', where '''n''' is the single numeric input.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"tooltip - Calculates the [https://en.wikipedia.org/wiki/Natural_logarithm|natural logarithm] of its single numeric input.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"tooltip - Calculates the [https://en.wikipedia.org/wiki/Common_logarithm common logarithm] of its single numeric input.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"tooltip - Multiplies [https://en.wikipedia.org/wiki/E_%28mathematical_constant%29 e] by itself n times, where n is the single numeric input.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"tooltip - Multiplies 10 by itself n times, where n is the single numeric input.\",\n    \"MATH_TRIG_HELPURL\": \"url - Information about the trigonometric functions sine, cosine, tangent, and their inverses (ideally using degrees, not radians).\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent sine function], using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent cosine] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent tangent] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.\",\n    \"MATH_CONSTANT_HELPURL\": \"url - Information about the mathematical constants \\u0026pi;, e, the golden ratio (\\u0026phi;), \\u0026radic; 2, \\u0026radic; 1/2, and infinity (\\u0026infin;).\",\n    \"MATH_CONSTANT_TOOLTIP\": \"tooltip - Provides the specified [https://en.wikipedia.org/wiki/Mathematical_constant mathematical constant].\",\n    \"MATH_IS_EVEN\": \"dropdown - A number is '''even''' if it is a multiple of 2.  For example, 4 is even (yielding true), but 3 is not (false).\",\n    \"MATH_IS_ODD\": \"dropdown - A number is '''odd''' if it is not a multiple of 2.  For example, 3 is odd (yielding true), but 4 is not (false).  The opposite of 'odd' is 'even'.\",\n    \"MATH_IS_PRIME\": \"dropdown - A number is [https://en.wikipedia.org/wiki/Prime prime] if it cannot be evenly divided by any positive integers except for 1 and itself.  For example, 5 is prime, but 6 is not because 2 \\u0026times; 3 = 6.\",\n    \"MATH_IS_WHOLE\": \"dropdown - A number is '''whole''' if it is an [https://en.wikipedia.org/wiki/Integer integer].  For example, 5 is whole, but 5.1 is not.\",\n    \"MATH_IS_POSITIVE\": \"dropdown - A number is '''positive''' if it is greater than 0.  (0 is neither negative nor positive.)\",\n    \"MATH_IS_NEGATIVE\": \"dropdown - A number is '''negative''' if it is less than 0.  (0 is neither negative nor positive.)\",\n    \"MATH_IS_DIVISIBLE_BY\": \"dropdown - A number x is divisible by y if y goes into x evenly.  For example, 10 is divisible by 5, but 10 is not divisible by 3.\",\n    \"MATH_IS_TOOLTIP\": \"tooltip - This block lets the user specify via a dropdown menu whether to check if the numeric input is even, odd, prime, whole, positive, negative, or divisible by a given value.\",\n    \"MATH_CHANGE_HELPURL\": \"url - Information about incrementing (increasing the value of) a variable. For other languages, just use the translation of the Wikipedia page about addition ([https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition]).\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"- As in: '''change''' [the value of variable] ''item by'' 1 (e.g., if the variable named 'item' had the value 5, change it to 6).\",\n    \"MATH_CHANGE_INPUT_BY\": \"- As in: ''change'' [the value of variable] ''item'' '''by''' 1 (e.g., if the variable named 'item' had the value 5, change it to 6).\",\n    \"MATH_CHANGE_TOOLTIP\": \"tooltip - This updates the value of the variable by adding to it the following numeric input.\\n\\nParameters:\\n* %1 - the name of the variable whose value should be increased.\",\n    \"MATH_ROUND_HELPURL\": \"url - Information about how numbers are rounded to the nearest integer\",\n    \"MATH_ROUND_TOOLTIP\": \"tooltip - See [https://en.wikipedia.org/wiki/Rounding https://en.wikipedia.org/wiki/Rounding].\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"dropdown - This rounds its input to the nearest whole number.  For example, 3.4 is rounded to 3.\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"dropdown - This rounds its input up to the nearest whole number.  For example, if the input was 2.2, the result would be 3.\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"dropdown - This rounds its input down to the nearest whole number.  For example, if the input was 3.8, the result would be 3.\",\n    \"MATH_ONLIST_HELPURL\": \"url - Information about applying a function to a list of numbers.  (We were unable to find such information in English.  Feel free to skip this and any other URLs that are difficult.)\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"dropdown - This computes the sum of the numeric elements in the list.  For example, the sum of the list {1, 4} is 5.\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"tooltip - Please use the same term for 'sum' as in the previous message.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"dropdown - This finds the smallest (minimum) number in a list.  For example, the smallest number in the list [-5, 0, 3] is -5.\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"tooltip - Please use the same term for 'min' or 'minimum' as in the previous message.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"dropdown - This finds the largest (maximum) number in a list.  For example, the largest number in the list [-5, 0, 3] is 3.\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"tooltip\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"dropdown - This adds up all of the numbers in a list and divides the sum by the number of elements in the list.  For example, the [https://en.wikipedia.org/wiki/Arithmetic_mean average] of the list [1, 2, 3, 4] is 2.5 (10/4).\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"tooltip - See [https://en.wikipedia.org/wiki/Arithmetic_mean https://en.wikipedia.org/wiki/Arithmetic_mean] for more informatin.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"dropdown - This finds the [https://en.wikipedia.org/wiki/Median median] of the numeric values in a list.  For example, the median of the list {1, 2, 7, 12, 13} is 7.\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"tooltip - See [https://en.wikipedia.org/wiki/Median median https://en.wikipedia.org/wiki/Median median] for more information.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"dropdown - This finds the most common numbers ([https://en.wikipedia.org/wiki/Mode_(statistics) modes]) in a list.  For example, the modes of the list {1, 3, 9, 3, 9}  are {3, 9}.\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"tooltip - See [https://en.wikipedia.org/wiki/Mode_(statistics) https://en.wikipedia.org/wiki/Mode_(statistics)] for more information.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"dropdown - This finds the [https://en.wikipedia.org/wiki/Standard_deviation standard deviation] of the numeric values in a list.\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"tooltip - See [https://en.wikipedia.org/wiki/Standard_deviation https://en.wikipedia.org/wiki/Standard_deviation] for more information.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"dropdown - This choose an element at random from a list.  Each element is chosen with equal probability.\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"tooltip - Please use same term for 'random' as in previous entry.\",\n    \"MATH_MODULO_HELPURL\": \"url - information about the modulo (remainder) operation.\",\n    \"MATH_MODULO_TITLE\": \"block text - Title of block providing the remainder when dividing the first numerical input by the second.  For example, the remainder of 10 divided by 3 is 1.\\n\\nParameters:\\n* %1 - the dividend (10, in our example)\\n* %2 - the divisor (3 in our example).\",\n    \"MATH_MODULO_TOOLTIP\": \"tooltip - For example, the remainder of 10 divided by 3 is 1.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"url - Information about constraining a numeric value to be in a specific range.  (The English URL is not ideal.  Recall that translating URLs is the lowest priority.)\",\n    \"MATH_CONSTRAIN_TITLE\": \"block text - The title of the block that '''constrain'''s (forces) a number to be in a given range. For example, if the number 150 is constrained to be between 5 and 100, the result will be 100. \\n\\nParameters:\\n* %1 - the value to constrain (e.g., 150)\\n* %2 - the minimum value (e.g., 5)\\n* %3 - the maximum value (e.g., 100).\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"tooltip - This compares a number ''x'' to a low value ''L'' and a high value ''H''.  If ''x'' is less then ''L'', the result is ''L''.  If ''x'' is greater than ''H'', the result is ''H''.  Otherwise, the result is ''x''.\",\n    \"MATH_RANDOM_INT_HELPURL\": \"url - Information about how computers generate random numbers.\",\n    \"MATH_RANDOM_INT_TITLE\": \"block text - The title of the block that generates a random integer (whole number) in the specified range.  For example, if the range is from 5 to 7, this returns 5, 6, or 7 with equal likelihood. %1 is a placeholder for the lower number, %2 is the placeholder for the larger number.\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"tooltip - Return a random integer between two values specified as inputs.  For example, if one input was 7 and another 9, any of the numbers 7, 8, or 9 could be produced.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"url - Information about how computers generate random numbers (specifically, numbers in the range from 0 to just below 1).\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"block text - The title of the block that generates a random number greater than or equal to 0 and less than 1.\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"tooltip - Return a random fraction between 0 and 1.  The value may be equal to 0 but must be less than 1.\",\n    \"TEXT_TEXT_HELPURL\": \"url - Information about how computers represent text (sometimes referred to as ''string''s).\",\n    \"TEXT_TEXT_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Introduction https://code.google.com/p/blockly/wiki/Text#Introduction].\",\n    \"TEXT_JOIN_HELPURL\": \"url - Information on concatenating/appending pieces of text.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"block text - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation].\",\n    \"TEXT_JOIN_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_creation create text with] for more information.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"block text - This is shown when the programmer wants to change the number of pieces of text being joined together.  See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"block text - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.\",\n    \"TEXT_APPEND_HELPURL\": \"url - This and the other text-related URLs are going to be hard to translate.  As always, it is okay to leave untranslated or paste in the English-language URL.  For these URLs, you might also consider a general URL about how computers represent text (such as the translation of [https://en.wikipedia.org/wiki/String_(computer_science) this Wikipedia page]).\",\n    \"TEXT_APPEND_TO\": \"block input text - Message preceding the name of a variable to which text should be appended. [[File:blockly-append-text.png]]\",\n    \"TEXT_APPEND_APPENDTEXT\": \"block input text - Message following the variable and preceding the piece of text that should be appended, as shown below. [[File:blockly-append-text.png]]\",\n    \"TEXT_APPEND_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_modification https://code.google.com/p/blockly/wiki/Text#Text_modification] for more information.\\n\\nParameters:\\n* %1 - the name of the variable to which text should be appended\",\n    \"TEXT_LENGTH_HELPURL\": \"url - Information about text on computers (usually referred to as 'strings').\",\n    \"TEXT_LENGTH_TITLE\": \"block text - See [https://code.google.com/p/blockly/wiki/Text#Text_length https://code.google.com/p/blockly/wiki/Text#Text_length]. \\n\\nParameters:\\n* %1 - the piece of text to take the length of\",\n    \"TEXT_LENGTH_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_length https://code.google.com/p/blockly/wiki/Text#Text_length].\",\n    \"TEXT_ISEMPTY_HELPURL\": \"url - Information about empty pieces of text on computers (usually referred to as 'empty strings').\",\n    \"TEXT_ISEMPTY_TITLE\": \"block text - See [https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text]. \\n\\nParameters:\\n* %1 - the piece of text to test for emptiness\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text].\",\n    \"TEXT_INDEXOF_HELPURL\": \"url - Information about finding a character in a piece of text.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text].\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"block text - Title of blocks allowing users to find text.  See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text]. [[File:Blockly-find-text.png]].\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"dropdown - See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text]. [[File:Blockly-find-text.png]].\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"dropdown - See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text].  This would replace 'find first occurrence of text' below.  (For more information on how common text is factored out of dropdown menus, see [https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus)].) [[File:Blockly-find-text.png]].\",\n    \"TEXT_INDEXOF_TAIL\": \"block text - Optional text to follow the rightmost block in a [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text in text ... find block] (after the 'a' in the below picture).  This will be the empty string in most languages. [[File:Blockly-find-text.png]].\",\n    \"TEXT_CHARAT_HELPURL\": \"url - Information about extracting characters (letters, number, symbols, etc.) from text.\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"block text - Appears before the piece of text from which a letter (or number, punctuation character, etc.) should be extracted, as shown below.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]\",\n    \"TEXT_CHARAT_FROM_START\": \"dropdown - Indicates that the letter (or number, punctuation character, etc.) with the specified index should be obtained from the preceding piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]\",\n    \"TEXT_CHARAT_FROM_END\": \"block text - Indicates that the letter (or number, punctuation character, etc.) with the specified index from the end of a given piece of text should be obtained. See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]\",\n    \"TEXT_CHARAT_FIRST\": \"block text - Indicates that the first letter of the following piece of text should be retrieved.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]\",\n    \"TEXT_CHARAT_LAST\": \"block text - Indicates that the last letter (or number, punctuation mark, etc.) of the following piece of text should be retrieved.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]\",\n    \"TEXT_CHARAT_RANDOM\": \"block text - Indicates that any letter (or number, punctuation mark, etc.) in the following piece of text should be randomly selected.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]\",\n    \"TEXT_CHARAT_TAIL\": \"block text - Text that goes after the rightmost block/dropdown when getting a single letter from a piece of text, as in [https://blockly-demo.appspot.com/static/apps/code/index.html#3m23km these blocks] or shown below.  For most languages, this will be blank. [[File:Blockly-text-get.png]]\",\n    \"TEXT_CHARAT_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character]. [[File:Blockly-text-get.png]]\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"url - Information about extracting characters from text.  Reminder: urls are the lowest priority translations.  Feel free to skip.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"block text - Precedes a piece of text from which a portion should be extracted. [[File:Blockly-get-substring.png]]\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"dropdown - Indicates that the following number specifies the position (relative to the start position) of the beginning of the region of text that should be obtained from the preceding piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"dropdown - Indicates that the following number specifies the position (relative to the end position) of the beginning of the region of text that should be obtained from the preceding piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this and any other [https://translatewiki.net/wiki/Translating:Blockly#Ordinal_numbers ordinal numbers] on this block. [[File:Blockly-get-substring.png]]\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"block text - Indicates that a region starting with the first letter of the preceding piece of text should be extracted.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"dropdown - Indicates that the following number specifies the position (relative to the start position) of the end of the region of text that should be obtained from the preceding piece of text.  See [ https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"dropdown - Indicates that the following number specifies the position (relative to the end position) of the end of the region of text that should be obtained from the preceding piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"block text - Indicates that a region ending with the last letter of the preceding piece of text should be extracted.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text]. [[File:Blockly-get-substring.png]]\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"block text - Text that should go after the rightmost block/dropdown when [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text extracting a region of text].  In most languages, this will be the empty string. [[File:Blockly-get-substring.png]]\",\n    \"TEXT_CHANGECASE_HELPURL\": \"url - Information about the case of letters (upper-case and lower-case).\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"tooltip - Describes a block to adjust the case of letters.  For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"block text - Indicates that all of the letters in the following piece of text should be capitalized.  If your language does not use case, you may indicate that this is not applicable to your language.  For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"block text - Indicates that all of the letters in the following piece of text should be converted to lower-case.  If your language does not use case, you may indicate that this is not applicable to your language.  For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"block text - Indicates that the first letter of each of the following words should be capitalized and the rest converted to lower-case.  If your language does not use case, you may indicate that this is not applicable to your language.  For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].\",\n    \"TEXT_TRIM_HELPURL\": \"url - Information about trimming (removing) text off the beginning and ends of pieces of text.\",\n    \"TEXT_TRIM_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces].\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"dropdown - Removes spaces from the beginning and end of a piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces].  Note that neither this nor the other options modify the original piece of text (that follows); the block just returns a version of the text without the specified spaces.\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"dropdown - Removes spaces from the beginning of a piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. Note that in right-to-left scripts, this will remove spaces from the right side.\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"dropdown - Removes spaces from the end of a piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces]. Note that in right-to-left scripts, this will remove spaces from the left side.\",\n    \"TEXT_PRINT_HELPURL\": \"url - Information about displaying text on computers.\",\n    \"TEXT_PRINT_TITLE\": \"block text - Display the input on the screen.  See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text]. \\n\\nParameters:\\n* %1 - the value to print\",\n    \"TEXT_PRINT_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].\",\n    \"TEXT_PROMPT_HELPURL\": \"url - Information about getting text from users.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"dropdown - Specifies that a piece of text should be requested from the user with the following message.  See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"dropdown - Specifies that a number should be requested from the user with the following message.  See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"dropdown - Precedes the message with which the user should be prompted for a number.  See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"dropdown - Precedes the message with which the user should be prompted for some text. See [https://code.google.com/p/blockly/wiki/Text#Printing_text https://code.google.com/p/blockly/wiki/Text#Printing_text].\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"url - Information on empty lists.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"block text - See [https://code.google.com/p/blockly/wiki/Lists#create_empty_list https://code.google.com/p/blockly/wiki/Lists#create_empty_list].\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"block text - See [https://code.google.com/p/blockly/wiki/Lists#create_empty_list https://code.google.com/p/blockly/wiki/Lists#create_empty_list].\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with].\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"block text - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with].\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"block text - This appears in a sub-block when [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs changing the number of inputs in a ''''create list with'''' block].\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs].\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs].\",\n    \"LISTS_REPEAT_HELPURL\": \"url - Information about [https://code.google.com/p/blockly/wiki/Lists#create_list_with creating a list with multiple copies of a single item].\",\n    \"LISTS_REPEAT_TOOLTIP\": \"url - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with creating a list with multiple copies of a single item].\",\n    \"LISTS_REPEAT_TITLE\": \"block text - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with]. \\n\\nParameters:\\n* %1 - the item (text) to be repeated\\n* %2 - the number of times to repeat it\",\n    \"LISTS_LENGTH_HELPURL\": \"url - Information about how the length of a list is computed (i.e., by the total number of elements, not the number of different elements).\",\n    \"LISTS_LENGTH_TITLE\": \"block text - See [https://code.google.com/p/blockly/wiki/Lists#length_of https://code.google.com/p/blockly/wiki/Lists#length_of]. \\n\\nParameters:\\n* %1 - the list whose length is desired\",\n    \"LISTS_LENGTH_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#length_of https://code.google.com/p/blockly/wiki/Lists#length_of Blockly:Lists:length of].\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"url - See [https://code.google.com/p/blockly/wiki/Lists#is_empty https://code.google.com/p/blockly/wiki/Lists#is_empty].\",\n    \"LISTS_IS_EMPTY_TITLE\": \"block text - See [https://code.google.com/p/blockly/wiki/Lists#is_empty https://code.google.com/p/blockly/wiki/Lists#is_empty]. \\n\\nParameters:\\n* %1 - the list to test\",\n    \"LISTS_TOOLTIP\": \"block tooltip - See [https://code.google.com/p/blockly/wiki/Lists#is_empty https://code.google.com/p/blockly/wiki/Lists#is_empty].\",\n    \"LISTS_INLIST\": \"block text - Title of blocks operating on [https://code.google.com/p/blockly/wiki/Lists lists].\",\n    \"LISTS_INDEX_OF_HELPURL\": \"url - See [https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List].\",\n    \"LISTS_INDEX_OF_FIRST\": \"dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List Lists#Finding_Items_in_a_List]. [[File:Blockly-list-find.png]]\",\n    \"LISTS_INDEX_OF_LAST\": \"dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List]. [[File:Blockly-list-find.png]]\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List]. [[File:Blockly-list-find.png]]\",\n    \"LISTS_GET_INDEX_GET\": \"dropdown - Indicates that the user wishes to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item get an item from a list] without removing it from the list.\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"dropdown - Indicates that the user wishes to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item get and remove an item from a list], as opposed to merely getting it without modifying the list.\",\n    \"LISTS_GET_INDEX_REMOVE\": \"dropdown - Indicates that the user wishes to [https://code.google.com/p/blockly/wiki/Lists#Removing_an_item remove an item from a list].\",\n    \"LISTS_GET_INDEX_FROM_START\": \"dropdown - Indicates that an index relative to the front of the list should be used to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item get and/or remove an item from a list].  Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this number (and any other ordinal numbers on this block). See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. [[File:Blockly-list-get-item.png]]\",\n    \"LISTS_GET_INDEX_FROM_END\": \"dropdown - Indicates that an index relative to the end of the list should be used to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item access an item in a list]. [[File:Blockly-list-get-item.png]]\",\n    \"LISTS_GET_INDEX_FIRST\": \"dropdown - Indicates that the '''first''' item should be [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. [[File:Blockly-list-get-item.png]]\",\n    \"LISTS_GET_INDEX_LAST\": \"dropdown - Indicates that the '''last''' item should be [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. [[File:Blockly-list-get-item.png]]\",\n    \"LISTS_GET_INDEX_RANDOM\": \"dropdown - Indicates that a '''random''' item should be [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list]. [[File:Blockly-list-get-item.png]]\",\n    \"LISTS_GET_INDEX_TAIL\": \"block text - Text that should go after the rightmost block/dropdown when [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessing an item from a list].  In most languages, this will be the empty string. [[File:Blockly-list-get-item.png]]\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from start'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from end'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'first'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'last'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'random'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from start'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from end'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'first'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'last'.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'random'.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"url - Information about putting items in lists.\",\n    \"LISTS_SET_INDEX_SET\": \"block text - [https://code.google.com/p/blockly/wiki/Lists#in_list_..._set Replaces an item in a list]. [[File:Blockly-in-list-set-insert.png]]\",\n    \"LISTS_SET_INDEX_INSERT\": \"block text - [https://code.google.com/p/blockly/wiki/Lists#in_list_..._insert_at Inserts an item into a list]. [[File:Blockly-in-list-set-insert.png]]\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"block text - The word(s) after the position in the list and before the item to be set/inserted. [[File:Blockly-in-list-set-insert.png]]\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"url - Information describing extracting a sublist from an existing list.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"dropdown - Indicates that an index relative to the front of the list should be used to specify the beginning of the range from which to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. [[File:Blockly-get-sublist.png]] Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this number (and any other ordinal numbers on this block). See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly.\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"dropdown - Indicates that an index relative to the end of the list should be used to specify the beginning of the range from which to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist].\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"dropdown - Indicates that the [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist sublist to extract] should begin with the list's first item.\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"dropdown - Indicates that an index relative to the front of the list should be used to specify the end of the range from which to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. [[File:Blockly-get-sublist.png]]\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"dropdown - Indicates that an index relative to the end of the list should be used to specify the end of the range from which to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist]. [[File:Blockly-get-sublist.png]]\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"dropdown - Indicates that the '''last''' item in the given list should be [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist the end of the selected sublist]. [[File:Blockly-get-sublist.png]]\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"block text - This appears in the rightmost position ('tail') of the sublist block, as described at [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist]. In English and most other languages, this is the empty string. [[File:Blockly-get-sublist.png]]\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist] for more information. [[File:Blockly-get-sublist.png]]\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"grammar - Text that follows an ordinal number (a number that indicates position relative to other numbers).  In most languages, such text appears before the number, so this should be blank.  An exception is Hungarian. See [[Translating:Blockly#Ordinal_numbers]] for more information.\",\n    \"VARIABLES_GET_HELPURL\": \"url - Information about ''variables'' in computer programming.  Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists.\",\n    \"VARIABLES_GET_TITLE\": \"block text - This precedes the name of a variable when getting its values.  In most (all?) languages, it should be the empty string.  If unsure, ask yourself if any word should go before 'x' in the expression 'x + 1'.\",\n    \"VARIABLES_GET_TAIL\": \"block text - This follows the name of a variable.  In most (all?) languages, it should be the empty string.  If unsure, ask yourself if any word should go after 'x' in the expression 'x + 1'.\",\n    \"VARIABLES_GET_TOOLTIP\": \"tooltip - This gets the value of the named variable without modifying it.\",\n    \"VARIABLES_GET_CREATE_SET\": \"context menu - Selecting this creates a block to set (change) the value of this variable. \\n\\nParameters:\\n* %1 - the name of the variable.\",\n    \"VARIABLES_SET_HELPURL\": \"url - Information about ''variables'' in computer programming.  Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists.\",\n    \"VARIABLES_SET_TITLE\": \"block text - The imperative or infinitive form of the verb 'set', as in: '''set''' [the value of] x to 7.\",\n    \"VARIABLES_SET_TAIL\": \"block text - The word that goes after the name of the variable and before its new value in: set [the value of] x '''to''' 7.\",\n    \"VARIABLES_SET_TOOLTIP\": \"tooltip - This initializes or changes the value of the named variable.\",\n    \"VARIABLES_SET_CREATE_GET\": \"context menu - Selecting this creates a block to get (change) the value of this variable.\\n\\nParameters:\\n* %1 - the name of the variable.\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"url - Information about defining [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not have return values.\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"block text - This precedes the name of the procedure when defining it.  See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample procedure definition].\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"default name - This acts as a placeholder for the name of a function on a function definition block, as shown on [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#w7cfju this block]. The user will replace it with the function's name.\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"block text - This precedes the list of parameters to a function.  See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample function with parameters].\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"block text - This appears next to the function's 'body', the blocks that should be run when the function is called, as shown in [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample procedure definition].\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"tooltip\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"url - Information about defining [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that have return values.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"block text - This imperative or infinite verb precedes the value that is used as the return value (output) of this function.  See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample function that returns a value].\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"tooltip\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"alert - The user has created a function with two parameters that have the same name.  Every parameter must have a different name.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"url - Information about calling [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not return values.\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"block text - In most (if not all) languages, this will be the empty string. It precedes the name of the function that should be run.  See, for example, the 'draw square' block in [https://blockly-demo.appspot.com/static/apps/turtle/index.html#ztz96g].\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"tooltip - This block causes the body (blocks inside) of the named function definition to be run.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"url - Information about calling [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that return values.\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"tooltip - This block causes the body (blocks inside) of the named function definition to be run.\\n\\nParameters:\\n* %1 - the name of the function.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"block text - This text appears on a block in a window that appears when the user clicks on the plus sign or star on a function definition block.  It refers to the set of parameters (referred to by the simpler term 'inputs') to the function.  See [[Translating:Blockly#function_definitions]].\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"block text - This text appears on a block in a window that appears when the user clicks on the plus sign or star on a function definition block].  It appears on the block for adding an individual parameter (referred to by the simpler term 'inputs') to the function. See [[Translating:Blockly#function_definitions]].\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"context menu - This appears on the context menu for function calls.  Selecting it causes the corresponding function definition to be highlighted (as shown at [[Translating:Blockly#context_menus]].\",\n    \"PROCEDURES_CREATE_DO\": \"context menu - This appears on the context menu for function definitions. Selecting it creates a block to call the function.  \\n\\nParameters:\\n* %1 - the name of the function.\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"tooltip - If the first value is true, this causes the second value to be returned immediately from the enclosing function.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"warning - This appears if the user tries to use this block outside of a function definition.\",\n    \"CONTEXT_BLOCK_COPY\": \"Context Menu Copy\",\n    \"CONTEXT_BLOCK_PASTE\": \"Context Menu Paste\"\n}\n"
  },
  {
    "path": "extern/blockly/msg/json/ro.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"element\",\n    \"DUPLICATE_BLOCK\": \"Duplicati\",\n    \"ADD_COMMENT\": \"Adaugă un comentariu\",\n    \"REMOVE_COMMENT\": \"Elimină comentariu\",\n    \"EXTERNAL_INPUTS\": \"Intrări Externe\",\n    \"INLINE_INPUTS\": \"Intrari de Linie\",\n    \"DELETE_BLOCK\": \"Șterge Bloc\",\n    \"DELETE_X_BLOCKS\": \"Ștergeți %1 Blocuri\",\n    \"COLLAPSE_BLOCK\": \"Restrange blocul\",\n    \"COLLAPSE_ALL\": \"Restrange blocurile\",\n    \"EXPAND_BLOCK\": \"Extinde bloc\",\n    \"EXPAND_ALL\": \"Extinde blocuri\",\n    \"DISABLE_BLOCK\": \"Dezactivaţi bloc\",\n    \"ENABLE_BLOCK\": \"Permite bloc\",\n    \"HELP\": \"Ajutor\",\n    \"CHANGE_VALUE_TITLE\": \"Schimbaţi valoarea:\",\n    \"NEW_VARIABLE\": \"Variabilă nouă...\",\n    \"NEW_VARIABLE_TITLE\": \"Noul nume de variabilă:\",\n    \"RENAME_VARIABLE\": \"Redenumirea variabilei...\",\n    \"RENAME_VARIABLE_TITLE\": \"Redenumeşte toate variabilele '%1' în:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://ro.wikipedia.org/wiki/Culoare\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Alege o culoare din paleta de culori.\",\n    \"COLOUR_RANDOM_TITLE\": \"culoare aleatorie\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Alege o culoare la întâmplare.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"colorează cu\",\n    \"COLOUR_RGB_RED\": \"roşu\",\n    \"COLOUR_RGB_GREEN\": \"verde\",\n    \"COLOUR_RGB_BLUE\": \"albastru\",\n    \"COLOUR_RGB_TOOLTIP\": \"Creează o culoare cu suma specificată de roşu, verde şi albastru.  Toate valorile trebuie să fie între 0 şi 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"amestec\",\n    \"COLOUR_BLEND_COLOUR1\": \"culoare 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"culoare 2\",\n    \"COLOUR_BLEND_RATIO\": \"Raport\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Amestecă două culori cu un raport dat (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"repetă de %1 ori\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"repetă\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"ori\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"fă\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Face unele afirmaţii de mai multe ori.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"repetă în timp ce\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"Repetaţi până când\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"În timp ce o valoare este adevărat, atunci face unele declaraţii.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"În timp ce o valoare este adevărat, atunci face unele declaraţii.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Cu variablia %1 ia o valoare din numărul început la numărul final, numara in intervalul specificat, apoi face blocurile specificate.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"numără cu\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"de la %1 la %2 prin %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"pentru fiecare element\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"în listă\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Pentru fiecare element din listă, setaţi variabila '%1' ca valoarea elementului, şi apoi faceţi unele declaraţii.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"ieşi din bucla\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"continuă cu următoarea iterație a buclei\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Ieși din bucla care conţine.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Sari peste restul aceastei bucle, şi continuă cu urmatoarea iteratie.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Avertisment: Acest bloc pote fi utilizat numai în interiorul unei bucle.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Dacă o valoare este adevărată, atunci fa unele declaraţii.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Dacă o valoare este adevărat, atunci face primul bloc de declaraţii.  Altfel, face al doilea bloc de declaraţii.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Dacă prima valoare este adevărat, atunci face primul bloc de declaraţii.  Altfel, dacă a doua valoare este adevărat, face al doilea bloc de declaraţii.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Dacă prima valoare este adevărat, atunci face primul bloc de declaraţii.  Altfel, dacă a doua valoare este adevărat, face al doilea bloc de declaraţii.  În cazul în care niciuna din  valorilor nu este adevărat, face ultimul bloc de declaraţii.\",\n    \"CONTROLS_IF_MSG_IF\": \"dacă\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"altfel dacă\",\n    \"CONTROLS_IF_MSG_ELSE\": \"altfel\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Adaugă, elimină sau reordonează secţiuni pentru a reconfigura acest bloc if.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Adăugaţi o condiţie in blocul if.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Adauga o stare finala, cuprinde toata conditia din blocul if.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Returnează adevărat dacă ambele intrări sunt egale.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Returnează adevărat daca cele două intrări nu sunt egale.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Returnează adevărat dacă prima intrare este mai mică decât a doua intrare.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Returnează adevărat dacă prima intrare este mai mică sau egală cu a doua intrare.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Returnează adevărat dacă prima intrare este mai mare decât a doua intrare.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Returnează adevărat dacă prima intrare este mai mare sau egală cu a doua intrare.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Returnează adevărat daca ambele intrări sunt adevărate.\",\n    \"LOGIC_OPERATION_AND\": \"şi\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Returnează adevărat dacă cel puţin una din intrări este adevărată.\",\n    \"LOGIC_OPERATION_OR\": \"sau\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"non %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Returnează adevărat dacă intrarea este falsă.  Returnează fals dacă intrarea este adevărată.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"adevărat\",\n    \"LOGIC_BOOLEAN_FALSE\": \"fals\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Returnează adevărat sau fals.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"nul\",\n    \"LOGIC_NULL_TOOLTIP\": \"returnează nul.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"dacă este adevărat\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"dacă este fals\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Verifică condiţia din \\\"test\\\". Dacă condiţia este adevărată, returnează valoarea \\\"în cazul în care adevărat\\\"; în caz contrar întoarce valoarea \\\"în cazul în care e fals\\\".\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Un număr.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tg\",\n    \"MATH_TRIG_ASIN\": \"arcsin\",\n    \"MATH_TRIG_ACOS\": \"arccos\",\n    \"MATH_TRIG_ATAN\": \"arctg\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://ro.wikipedia.org/wiki/Aritmetic%C4%83\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Returnează suma a două numere.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Returneaza diferenţa dintre cele două numere.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Returnează produsul celor două numere.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Returnează câtul celor două numere.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Returneaza numărul rezultat prin ridicarea primului număr la puterea celui de-al doilea.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"rădăcina pătrată\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Returnează rădăcina pătrată a unui număr.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolută\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Returnează valoarea absolută a unui număr.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Returnează negaţia unui număr.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Întoarce logaritmul natural al unui număr.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Returnează logaritmul în baza 10 a unui număr.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Returnează e la puterea unui număr.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Returnează 10 la puterea unui număr.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Întoarce cosinusul unui grad (nu radianul).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Întoarce cosinusul unui grad (nu radianul).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Întoarce tangenta unui grad (nu radianul).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Returnează arcsinusul unui număr.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Returnează arccosinusul unui număr.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Returnează arctangenta unui număr.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://ro.wikipedia.org/wiki/Constant%C4%83_matematic%C4%83\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Întoarcă una din constantele comune: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) sau ∞ (infinitate).\",\n    \"MATH_IS_EVEN\": \"este par\",\n    \"MATH_IS_ODD\": \"este impar\",\n    \"MATH_IS_PRIME\": \"este prim\",\n    \"MATH_IS_WHOLE\": \"este întreg\",\n    \"MATH_IS_POSITIVE\": \"este pozitiv\",\n    \"MATH_IS_NEGATIVE\": \"este negativ\",\n    \"MATH_IS_DIVISIBLE_BY\": \"este divizibil cu\",\n    \"MATH_IS_TOOLTIP\": \"Verifică dacă un număr este un par, impar, prim, întreg, pozitiv, negativ, sau dacă este divizibil cu un anumit număr.  Returnează true sau false.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"schimbă\",\n    \"MATH_CHANGE_INPUT_BY\": \"de\",\n    \"MATH_CHANGE_TOOLTIP\": \"Adaugă un număr variabilei '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Rotunjirea unui număr în sus sau în jos.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"rotund\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"rotunjește în sus\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"rotunjit\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"suma listei\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Returnează suma tuturor numerelor din lista.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"minimul listei\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Returnează cel mai mic număr din listă.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"maximul listei\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Întoarce cel mai mare număr din listă.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"media listei\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Întoarce media (aritmetică) a valorilor numerice în listă.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"media listei\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Întoarce numărul median în listă.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"moduri de listă\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Returnează o listă cu cel(e) mai frecvent(e) element(e) din listă.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"deviația standard a listei\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Întoarce deviația standard a listei.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"element aleatoriu din lista\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Returnează un element aleatoriu din listă.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"restul la %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Întoarce restul din împărţirea celor două numere.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"constrânge %1 redus %2 ridicat %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Constrânge un număr să fie între limitele specificate (inclusiv).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"un număr întreg aleator de la %1 la %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Returnează un număr întreg aleator aflat între cele două limite specificate, inclusiv.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"fracții aleatorii\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Returnează o fracţie aleatoare între 0.0 (inclusiv) si 1.0 (exclusiv).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"O literă, cuvânt sau linie de text.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"crează text cu\",\n    \"TEXT_JOIN_TOOLTIP\": \"Creaţi o bucată de text prin unirea oricărui număr de elemente.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"alăturaţi-vă\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Adaugă, elimină sau reordonează secțiuni ca să reconfigureze blocul text.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Adaugă un element în text.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"la\",\n    \"TEXT_APPEND_APPENDTEXT\": \"Adăugaţi text\",\n    \"TEXT_APPEND_TOOLTIP\": \"Adăugaţi text la variabila '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"lungime de %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Returnează numărul de litere (inclusiv spaţiile) în textul furnizat.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 este gol\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Returnează adevărat dacă textul furnizat este gol.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Returnează indicele primei/ultimei apariţii din primul text în al doilea text.  Returnează 0 dacă textul nu este găsit.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"în text\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"găseşte prima apariţie a textului\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"găseşte ultima apariţie a textului\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"în text\",\n    \"TEXT_CHARAT_FROM_START\": \"obtine litera #\",\n    \"TEXT_CHARAT_FROM_END\": \"obţine litera # de la sfârșit\",\n    \"TEXT_CHARAT_FIRST\": \"obţine prima litera\",\n    \"TEXT_CHARAT_LAST\": \"obţine o litera oarecare\",\n    \"TEXT_CHARAT_RANDOM\": \"obtine o litera oarecare\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Returnează litera la poziția specificată.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Returnează o anumită parte din text.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"în text\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"obține subșir de la litera #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"obține un subșir de la litera # de la sfârșit\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"obţine un subșir de la prima literă\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"la litera #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"la litera # de la sfarsit\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"la ultima literă\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Întoarce o copie a textului într-un caz diferit.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"la MAJUSCULE\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"la litere mici\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"către Titlul de caz\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Returnează o copie a textului fără spațiile de la unul sau ambele capete.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"taie spațiile de pe ambele părți\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"tăiaţi spațiile din partea stângă\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"taie spațiile din partea dreaptă\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"imprimare %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Afișează textul specificat, numărul sau altă valoare.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"solicită pentru text cu mesaj\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"solicită pentru număr cu mesaj\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Solicită utilizatorul pentru un număr.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Solicită utilizatorul pentru text.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"creează listă goală\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Returnează o listă, de lungime 0, care nu conţine înregistrări de date\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Creaţi o listă cu orice număr de elemente.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"creează listă cu\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"listă\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Adaugă, elimină sau reordonează secţiuni ca să reconfiguraţi aceste blocuri de listă.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Adăugaţi un element la listă.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Creează o listă alcătuită dintr-o anumită valoare repetată de numărul specificat de ori.\",\n    \"LISTS_REPEAT_TITLE\": \"creaza lista cu %1 elemente repetate de %2 ori\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"lungime de %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Returnează lungimea unei liste.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 este gol\",\n    \"LISTS_TOOLTIP\": \"Returnează adevărat dacă lista este goală.\",\n    \"LISTS_INLIST\": \"în listă\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"Găseşte prima apariţie a elementului\",\n    \"LISTS_INDEX_OF_LAST\": \"găseşte ultima apariţie a elementului\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Returneaza indexul de la prima/ultima aparitie a elementuli din lista. Returneaza 0 daca textul nu este gasit.\",\n    \"LISTS_GET_INDEX_GET\": \"obţine\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"obţine şi elimină\",\n    \"LISTS_GET_INDEX_REMOVE\": \"elimină\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# de la sfârșit\",\n    \"LISTS_GET_INDEX_FIRST\": \"primul\",\n    \"LISTS_GET_INDEX_LAST\": \"ultimul\",\n    \"LISTS_GET_INDEX_RANDOM\": \"aleator\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Returneaza elementul la poziţia specificată într-o listă.  #1 este primul element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Returneaza elementul la poziţia specificată într-o listă.  #1 este ultimul element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Returnează primul element dintr-o listă.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Returnează ultimul element într-o listă.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Returneaza un element aleatoriu într-o listă.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Elimină şi returneaza elementul la poziţia specificată într-o listă.  #1 este primul element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Elimină şi returneaza elementul la poziţia specificată într-o listă.  #1 este ultimul element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Elimină şi returnează primul element într-o listă.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Elimină şi returnează ultimul element într-o listă.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Elimină şi returnează un element aleatoriu într-o listă.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Elimină elementul la poziţia specificată într-o listă.  #1 este primul element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Elimină elementul la poziţia specificată într-o listă.  #1 este ultimul element.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Elimină primul element într-o listă.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Elimină ultimul element într-o listă.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Elimină un element aleatoriu într-o listă.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"seteaza\",\n    \"LISTS_SET_INDEX_INSERT\": \"introduceţi la\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"ca\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Setează elementul la poziţia specificată într-o listă.  #1 este primul element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Setează elementul la poziţia specificată într-o listă.  #1 este ultimul element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Setează primul element într-o listă.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Setează ultimul element într-o listă.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Setează un element aleator într-o listă.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Inserează elementul la poziţia specificată într-o listă.  #1 este primul element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Inserează elementul la poziţia specificată într-o listă.  #1 este ultimul element.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Inserează elementul la începutul unei liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Adăugă elementul la sfârşitul unei liste.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Inserează elementul aleatoriu într-o listă.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"obţine sub-lista de la #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"obţine sub-lista de la # de la sfârşitul\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"obţine sub-lista de la primul\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"la #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"la # de la sfarsit\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"la ultima\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Creează o copie a porţiunii specificate dintr-o listă.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Returnează valoarea acestei variabile.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Crează 'set %1'\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"seteaza\",\n    \"VARIABLES_SET_TAIL\": \"la\",\n    \"VARIABLES_SET_TOOLTIP\": \"Setează această variabilă sa fie egală la intrare.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Crează 'get %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"la\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"fă ceva\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"cu:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Crează o funcţie cu nici o ieşire.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"returnează\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Creează o funcţie cu o ieşire.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Atenţie: Această funcţie are parametri duplicaţi.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Executați funcția '%1 'definită de utilizator.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Executați funcția '%1 'definită de utilizator şi folosiţi producţia sa.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"intrări\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"nume de intrare:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Evidenţiază definiţia funcţiei\",\n    \"PROCEDURES_CREATE_DO\": \"Creaţi '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Dacă o valoare este adevărată, atunci returnează valoarea a doua.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Avertisment: Acest bloc poate fi utilizat numai în definiţia unei funcţii.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/ru.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Espertus\",\n            \"MS\",\n            \"Okras\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"элемент\",\n    \"DUPLICATE_BLOCK\": \"Скопировать\",\n    \"ADD_COMMENT\": \"Добавить комментарий\",\n    \"REMOVE_COMMENT\": \"Удалить комментарий\",\n    \"EXTERNAL_INPUTS\": \"Вставки снаружи\",\n    \"INLINE_INPUTS\": \"Вставки внутри\",\n    \"DELETE_BLOCK\": \"Удалить блок\",\n    \"DELETE_X_BLOCKS\": \"Удалить %1 блоков\",\n    \"COLLAPSE_BLOCK\": \"Свернуть блок\",\n    \"COLLAPSE_ALL\": \"Свернуть блоки\",\n    \"EXPAND_BLOCK\": \"Развернуть блок\",\n    \"EXPAND_ALL\": \"Развернуть блоки\",\n    \"DISABLE_BLOCK\": \"Отключить блок\",\n    \"ENABLE_BLOCK\": \"Включить блок\",\n    \"HELP\": \"Справка\",\n    \"CHANGE_VALUE_TITLE\": \"Измените значение:\",\n    \"NEW_VARIABLE\": \"Новая переменная…\",\n    \"NEW_VARIABLE_TITLE\": \"Имя новой переменной:\",\n    \"RENAME_VARIABLE\": \"Переименовать переменную…\",\n    \"RENAME_VARIABLE_TITLE\": \"Переименовать все переменные '%1' в:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://ru.wikipedia.org/wiki/Цвет\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Выберите цвет из палитры.\",\n    \"COLOUR_RANDOM_TITLE\": \"случайный цвет\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Выбирает цвет случайным образом.\",\n    \"COLOUR_RGB_TITLE\": \"цвет из\",\n    \"COLOUR_RGB_RED\": \"красного\",\n    \"COLOUR_RGB_GREEN\": \"зелёного\",\n    \"COLOUR_RGB_BLUE\": \"синего\",\n    \"COLOUR_RGB_TOOLTIP\": \"Создаёт цвет с указанной пропорцией  красного, зеленого и синего.  Все значения должны быть между 0 и 100.\",\n    \"COLOUR_BLEND_TITLE\": \"смешать\",\n    \"COLOUR_BLEND_COLOUR1\": \"цвет 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"цвет 2\",\n    \"COLOUR_BLEND_RATIO\": \"доля цвета 1\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Смешивает два цвета в заданном соотношении (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://ru.wikipedia.org/wiki/Цикл_(программирование)\",\n    \"CONTROLS_REPEAT_TITLE\": \"повторить %1 раз\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"повторить\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"раз\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"выполнить\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Выполняет команды несколько раз.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"повторять, пока\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"повторять, пока не\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Пока значение истинно, выполняет команды.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Пока значение ложно, выполняет команды\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Присваивает переменной %1 значения от начального до конечного с заданным шагом и выполняет указанные команды.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"цикл по\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"от %1 до %2 с шагом %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"для каждого элемента\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"в списке\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Для каждого элемента в списке, присваивает переменной '%1' значение элемента  и выполняет указанные  команды.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"выйти из цикла\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"перейти к следующему шагу цикла\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Прерывает этот цикл.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Пропускает остаток цикла и переходит к следующему шагу.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Предупреждение: этот блок может использоваться только внутри цикла.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Если условие истинно, выполняет команды.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Если условие истинно, выполняет первый блок команд. Иначе выполняется второй блок команд.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Если первое условие истинно, то выполняет первый блок команд. Иначе, если второе условие истинно, выполняет второй блок команд.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Если первое условие истинно, то выполняет первый блок команд.  В противном случае, если второе условие истинно, выполняет второй блок команд.  Если ни одно из условий не истинно, выполняет последний блок команд.\",\n    \"CONTROLS_IF_MSG_IF\": \"если\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"иначе если\",\n    \"CONTROLS_IF_MSG_ELSE\": \"иначе\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Добавьте, удалите, переставьте фрагменты для переделки блока \\\"если\\\".\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Добавляет условие к блоку \\\"если\\\"\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Добавить заключительный подблок для случая, когда все условия ложны.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Возвращает значение истина, если вставки равны.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Возвращает значение истина, если вставки не равны.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Возвращает значение истина, если первая вставка меньше второй.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Возвращает значение истина, если первая вставка меньше или равна  второй.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Возвращает значение истина, если первая вставка больше второй.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Возвращает значение истина, если первая вставка больше или равна  второй.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Возвращает значение истина, если обе вставки истинны.\",\n    \"LOGIC_OPERATION_AND\": \"и\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Возвращает значение истина, если хотя бы одна из вставок истинна.\",\n    \"LOGIC_OPERATION_OR\": \"или\",\n    \"LOGIC_NEGATE_TITLE\": \"не %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Возвращает значение истина, если вставка ложна.  Возвращает значение ложь, если вставка истинна.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"истина\",\n    \"LOGIC_BOOLEAN_FALSE\": \"ложь\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Возвращает значение истина или ложь.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"ничто\",\n    \"LOGIC_NULL_TOOLTIP\": \"Возвращает ничто.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://ru.wikipedia.org/wiki/Тернарная_условная_операция\",\n    \"LOGIC_TERNARY_CONDITION\": \"выбрать по\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"если истина\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"если ложь\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Проверяет условие выбора. Если условие истинно, возвращает первое значение, в противном случае возвращает второе значение.\",\n    \"MATH_NUMBER_HELPURL\": \"https://ru.wikipedia.org/wiki/Число\",\n    \"MATH_NUMBER_TOOLTIP\": \"Число.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://ru.wikipedia.org/wiki/Арифметика\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Возвращает сумму двух чисел.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Возвращает разность двух чисел.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Возвращает произведение двух чисел.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Возвращает частное от деления первого числа на второе.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Возвращает первое число, возведённое в степень второго числа.\",\n    \"MATH_SINGLE_HELPURL\": \"https://ru.wikipedia.org/wiki/Квадратный_корень\",\n    \"MATH_SINGLE_OP_ROOT\": \"квадратный корень\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Возвращает квадратный корень числа.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"модуль\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Возвращает модуль числа\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Возвращает противоположное число.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Возвращает натуральный логарифм числа.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Возвращает десятичный логарифм числа.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Возвращает е в указанной степени.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Возвращает 10 в указанной степени.\",\n    \"MATH_TRIG_HELPURL\": \"https://ru.wikipedia.org/wiki/Тригонометрические_функции\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Возвращает синус угла в градусах.\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Возвращает косинус угла в градусах.\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Возвращает тангенс угла в градусах.\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Возвращает арксинус (в градусах).\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Возвращает арккосинус (в градусах).\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Возвращает арктангенс (в градусах)\",\n    \"MATH_CONSTANT_HELPURL\": \"https://ru.wikipedia.org/wiki/Математическая_константа\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Возвращает одну из распространённых  констант: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) или ∞ (бесконечность).\",\n    \"MATH_IS_EVEN\": \"чётное\",\n    \"MATH_IS_ODD\": \"нечётное\",\n    \"MATH_IS_PRIME\": \"простое\",\n    \"MATH_IS_WHOLE\": \"целое\",\n    \"MATH_IS_POSITIVE\": \"положительное\",\n    \"MATH_IS_NEGATIVE\": \"отрицательное\",\n    \"MATH_IS_DIVISIBLE_BY\": \"делится на\",\n    \"MATH_IS_TOOLTIP\": \"Проверяет, является ли число чётным, нечётным, простым, целым, положительным, отрицательным или оно кратно определённому числу.  Возвращает значение истина или ложь.\",\n    \"MATH_CHANGE_HELPURL\": \"https://ru.wikipedia.org/wiki/%D0%98%D0%B4%D0%B8%D0%BE%D0%BC%D0%B0_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29#.D0.98.D0.BD.D0.BA.D1.80.D0.B5.D0.BC.D0.B5.D0.BD.D1.82\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"увеличить\",\n    \"MATH_CHANGE_INPUT_BY\": \"на\",\n    \"MATH_CHANGE_TOOLTIP\": \"Добавляет число к переменной '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://ru.wikipedia.org/wiki/Округление\",\n    \"MATH_ROUND_TOOLTIP\": \"Округляет число до большего или меньшего.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"округлить\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"округлить к большему\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"округлить к меньшему\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"сумма списка\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Возвращает сумму всех чисел в списке.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"наименьшее в списке\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Возвращает наименьшее число списка.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"наибольшее в списке\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Возвращает наибольшее число списка.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"среднее арифметическое списка\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Возвращает среднее арифметическое списка.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"медиана списка\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Возвращает медиану списка.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"моды списка\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Возвращает список наиболее часто встречающихся элементов списка.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"стандартное отклонение списка\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Возвращает стандартное отклонение списка.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"случайный элемент списка\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Возвращает случайный элемент списка.\",\n    \"MATH_MODULO_HELPURL\": \"https://ru.wikipedia.org/wiki/Деление_с_остатком\",\n    \"MATH_MODULO_TITLE\": \"остаток от %1 : %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Возвращает остаток от деления двух чисел.\",\n    \"MATH_CONSTRAIN_TITLE\": \"ограничить %1 снизу %2 сверху %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Ограничивает число нижней и верхней границами (включительно).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел\",\n    \"MATH_RANDOM_INT_TITLE\": \"случайное целое число от %1 для %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Возвращает случайное число между двумя заданными пределами (включая и их).\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"случайное число от 0 (включительно) до 1\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Возвращает случайное число от 0.0 (включительно) до 1.0.\",\n    \"TEXT_TEXT_HELPURL\": \"https://ru.wikipedia.org/wiki/Строковый_тип\",\n    \"TEXT_TEXT_TOOLTIP\": \"Буква, слово или строка текста.\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"создать текст из\",\n    \"TEXT_JOIN_TOOLTIP\": \"Создаёт фрагмент текста, объединяя любое число элементов\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"соединить\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Добавьте, удалите, переставьте фрагменты для переделки текстового блока.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Добавить элемент к тексту.\",\n    \"TEXT_APPEND_TO\": \"к\",\n    \"TEXT_APPEND_APPENDTEXT\": \"добавить текст\",\n    \"TEXT_APPEND_TOOLTIP\": \"Добавить текст к переменной «%1».\",\n    \"TEXT_LENGTH_TITLE\": \"длина %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Возвращает число символов (включая пробелы) в заданном тексте.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 пуст\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Возвращает значение истина, если предоставленный текст пуст.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Возвращает номер позиции первого/последнего вхождения первого текста во  втором.  Возвращает 0, если текст не найден.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"в тексте\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"найти первое вхождение текста\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"найти последнее вхождение текста\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"в тексте\",\n    \"TEXT_CHARAT_FROM_START\": \"взять букву №\",\n    \"TEXT_CHARAT_FROM_END\": \"взять букву № с конца\",\n    \"TEXT_CHARAT_FIRST\": \"взять первую букву\",\n    \"TEXT_CHARAT_LAST\": \"взять последнюю букву\",\n    \"TEXT_CHARAT_RANDOM\": \"взять случайную букву\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Возвращает букву в указанной позиции.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Возвращает указанную часть текста.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"в тексте\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"взять подстроку с буквы №\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"взять подстроку с буквы № с конца\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"взять подстроку с первой буквы\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"по букву №\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"по букву № с конца\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"по последнюю букву\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Возвращает копию текста с ЗАГЛАВНЫМИ или строчными буквами.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"в ЗАГЛАВНЫЕ БУКВЫ\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"в строчные буквы\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"в Заглавные Начальные Буквы\",\n    \"TEXT_TRIM_TOOLTIP\": \"Возвращает копию текста с пробелами, удалеными с одного или обоих концов.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"обрезать пробелы с двух сторон\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"обрезать пробелы слева\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"обрезать пробелы справа\",\n    \"TEXT_PRINT_TITLE\": \"напечатать %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Печатает текст, число или другой объект.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"запросить текст с подсказкой\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"запросить число с подсказкой\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Запросить у пользователя число.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Запросить у пользователя текст.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"создать пустой список\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Возвращает список длины 0, не содержащий данных\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Создаёт список с любым числом элементов.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"создать список из\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"список\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Добавьте, удалите, переставьте элементы для переделки блока списка.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Добавляет элемент к списку.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Создаёт список, состоящий из заданного числа копий элемента.\",\n    \"LISTS_REPEAT_TITLE\": \"создать список из элемента %1, повторяющегося %2 раз\",\n    \"LISTS_LENGTH_TITLE\": \"длина %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Возвращает длину списка.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 пуст\",\n    \"LISTS_TOOLTIP\": \"Возвращает значение истина, если список пуст.\",\n    \"LISTS_INLIST\": \"в списке\",\n    \"LISTS_INDEX_OF_FIRST\": \"найти первое вхождение элемента\",\n    \"LISTS_INDEX_OF_LAST\": \"найти последнее вхождение элемента\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Возвращает номер позиции первого/последнего вхождения элемента в списке.  Возвращает 0, если текст не найден.\",\n    \"LISTS_GET_INDEX_GET\": \"взять\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"взять и удалить\",\n    \"LISTS_GET_INDEX_REMOVE\": \"удалить\",\n    \"LISTS_GET_INDEX_FROM_END\": \"№ с конца\",\n    \"LISTS_GET_INDEX_FIRST\": \"первый\",\n    \"LISTS_GET_INDEX_LAST\": \"последний\",\n    \"LISTS_GET_INDEX_RANDOM\": \"произвольный\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Возвращает элемент в указанной позиции списка (№1 - первый элемент).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Возвращает элемент в указанной позиции списка (№1 - последний элемент).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Возвращает первый элемент списка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Возвращает последний элемент списка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Возвращает случайный элемент списка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Удаляет и возвращает элемент в указанной позиции списка (№1 - первый элемент).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Удаляет и возвращает элемент в указанной позиции списка (№1 -  последний элемент).\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Удаляет и возвращает первый элемент списка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Удаляет и возвращает последний элемент списка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Удаляет и возвращает случайный элемент списка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Удаляет элемент в указанной позиции списка (№1 - первый элемент).\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Удаляет элемент в указанной позиции списка (№1 - последний элемент).\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Удаляет первый элемент списка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Удаляет последний элемент списка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Удаляет случайный элемент списка.\",\n    \"LISTS_SET_INDEX_SET\": \"присвоить\",\n    \"LISTS_SET_INDEX_INSERT\": \"вставить в\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"=\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Присваивает значение элементу в указанной позиции списка (№1 - первый элемент).\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Присваивает значение элементу в указанной позиции списка (№1 - последний элемент).\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Присваивает значение первому элементу списка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Присваивает значение последнему элементу списка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Присваивает значение случайному элементу списка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Вставляет элемент в указанной позиции списка (№1 - первый элемент).\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Вставляет элемент в указанной позиции списка (№1 - последний элемент).\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Вставляет элемент в начало списка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Добавляет элемент в конец списка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Вставляет элемент в случайное место в списке.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"взять подсписок с №\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"взять подсписок с № с конца\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"взять подсписок с первого\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"по №\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"по № с конца\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"по последний\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Создаёт копию указанной части списка.\",\n    \"VARIABLES_GET_TOOLTIP\": \"Возвращает значение этой переменной.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Создать блок \\\"присвоить\\\" для %1\",\n    \"VARIABLES_SET_TITLE\": \"присвоить\",\n    \"VARIABLES_SET_TAIL\": \"=\",\n    \"VARIABLES_SET_TOOLTIP\": \"Присваивает переменной значение вставки.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Создать вставку %1\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"чтобы\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"выполнить что-то\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"с:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Создаёт процедуру, не возвращающую значение.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"вернуть\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Создаёт процедуру, возвращающую значение.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Предупреждение: эта функция имеет повторяющиеся параметры.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://ru.wikipedia.org/wiki/Функция_%28программирование%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Исполняет определённую пользователем процедуру '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://ru.wikipedia.org/wiki/Функция_%28программирование%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Исполняет определённую пользователем процедуру '%1' и возвращает вычисленное  значение.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"параметры\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"имя параметра:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Выделить определение процедуры\",\n    \"PROCEDURES_CREATE_DO\": \"Создать вызов '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Если первое значение истинно, возвращает второе значение.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Предупреждение: Этот блок может использоваться только внутри определения функции.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/sq.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"send\",\n    \"DUPLICATE_BLOCK\": \"Kopjo\",\n    \"ADD_COMMENT\": \"Vendos nje Koment\",\n    \"REMOVE_COMMENT\": \"Fshij komentin\",\n    \"EXTERNAL_INPUTS\": \"Hyrjet e jashtme\",\n    \"INLINE_INPUTS\": \"Hyrjet e brendshme\",\n    \"DELETE_BLOCK\": \"Fshij bllokun\",\n    \"DELETE_X_BLOCKS\": \"Fshij %1 blloqe\",\n    \"COLLAPSE_BLOCK\": \"Mbyll bllokun\",\n    \"COLLAPSE_ALL\": \"Mbyll blloqet\",\n    \"EXPAND_BLOCK\": \"Zmadho bllokun\",\n    \"EXPAND_ALL\": \"Zmadho blloqet\",\n    \"DISABLE_BLOCK\": \"Çaktivizo bllokun\",\n    \"ENABLE_BLOCK\": \"Aktivizo bllokun\",\n    \"HELP\": \"Ndihmë\",\n    \"CHANGE_VALUE_TITLE\": \"Ndrysho Vlerat:\",\n    \"NEW_VARIABLE\": \"Identifikatorë i ri...\",\n    \"NEW_VARIABLE_TITLE\": \"Emri i identifikatorit të ri:\",\n    \"RENAME_VARIABLE\": \"Ndrysho emrin variables...\",\n    \"RENAME_VARIABLE_TITLE\": \"Ndrysho emrin e te gjitha '%1' variablave ne :\",\n    \"COLOUR_PICKER_HELPURL\": \"http://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Zgjidh nje ngjyre nga nje game ngjyrash.\",\n    \"COLOUR_RANDOM_TITLE\": \"ngjyre e rastesishme\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Zgjidhni një ngjyrë në mënyrë të rastësishme.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"ngjyre me\",\n    \"COLOUR_RGB_RED\": \"e kuqe\",\n    \"COLOUR_RGB_GREEN\": \"jeshile\",\n    \"COLOUR_RGB_BLUE\": \"blu\",\n    \"COLOUR_RGB_TOOLTIP\": \"Krijo një ngjyrë me shumën e specifikuar te te kuqes, te gjelbëres, dhe bluse. Te gjitha vlerat duhet te jene mes 0 dhe 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"Përzierje\",\n    \"COLOUR_BLEND_COLOUR1\": \"Ngjyra 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"Ngjyra 2\",\n    \"COLOUR_BLEND_RATIO\": \"Perpjesetim\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Perzien dy ngjyra së bashku me një raport të dhënë (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"http://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"përsërit %1 herë\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"përsërit\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"herë\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"ekzekuto\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Ekzekuto disa fjali disa herë.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"përsërit përderisa\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"përsërit derisa\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Përderisa një vlerë është e saktë, atëherë ekzekuto disa fjali.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Përderisa një vlerë është e pasaktë, atëherë ekzekuto disa fjali.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Bëje identifikuesin %1 që ta ketë vlerat prej numrit të fillimit deri tek numri i fundit, duke numëruar nga intervali i specifikuar, dhe ti bëj blloqet e specifikuara.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"numero me\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"nga '%1' ne '%2' me nga '%3'\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"per cdo produkt\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"ne liste\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Per cdo produkt ne nje \\\"liste\\\" \\\"vendos\\\" ndryshoren '%1' produktit, dhe pastaj bej disa deklarata.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"dil nga nje faze perseritese\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"vazhdo me elementin tjeter te nje faze perseritese\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Ndahu nga unaza.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Kapërce pjesën e mbetur të unazës, dhe vazhdo me ripërsëritjen tjetër.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Paralajmërim: Ky bllok mund të përdoret vetëm brenda unazës.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Nëse një vlerë është e saktë, atëherë ekzekuto disa fjali.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Nëse një vlerë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, ekzekuto bllokun e dytë të fjalive.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Nëse vlera e parë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, nëse vlera e dytë është e saktë, ekzekuto bllokun e dytë të fjalive.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Nëse vlera e parë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, nëse vlera e dytë është e saktë, ekzekuto bllokun e dytë të fjalive. Nëse asnjëra nga vlerat nuk është e saktë, ekzekuto bllokun e fundit të fjalive.\",\n    \"CONTROLS_IF_MSG_IF\": \"nëse\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"përndryshe nëse\",\n    \"CONTROLS_IF_MSG_ELSE\": \"përndryshe\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këte bllok nëse.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"\\\"Vendos\\\" \\\"kushtein\\\"tek \\\"pjesa\\\" \\\"if\\\"\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Shto një përfundues, që i mbërrin të gjitha kushtet në bllokun nëse.\",\n    \"LOGIC_COMPARE_HELPURL\": \"http://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Ktheje të saktë nëse të dy hyrjet janë të barabarta me njëra-tjetrën.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Ktheje të saktë nëse të dy hyrjet nuk janë të barabarta me njëra-tjetrën.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Ktheje të saktë nëse hyrja e parë është më e vogël se hyrja e dytë.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Ktheje të saktë nëse hyrja e parë është më e vogël ose e barabartë me hyrjen e dytë.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Ktheje të saktë nëse hyrja e parë është më e madhe se hyrja e dytë.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Ktheje të saktë nëse hyrja e parë është më e madhe ose e barabartë me hyrjen e dytë.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Kthehet të saktë nëse të dy hyrjet janë të sakta.\",\n    \"LOGIC_OPERATION_AND\": \"dhe\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Kthehet e saktë nëse së paku njëra nga hyrjet është e saktë.\",\n    \"LOGIC_OPERATION_OR\": \"ose\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"jo %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Kthehet e saktë nëse hyrja është e pasaktë. Kthehet e pasaktë nëse hyrja është e saktë.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"e saktë\",\n    \"LOGIC_BOOLEAN_FALSE\": \"e pasaktë\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Kthehet ose të saktë ose të pasaktë.\",\n    \"LOGIC_NULL_HELPURL\": \"http://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"pavlerë\",\n    \"LOGIC_NULL_TOOLTIP\": \"Kthehet e pavlerë.\",\n    \"LOGIC_TERNARY_HELPURL\": \"http://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"nëse e saktë\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"nëse e pasaktë\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Kontrollo kushtin në 'test'. Nëse kushti është i saktë, kthen vlerën 'nëse e saktë'; përndryshe kthen vlerën 'nëse e pasaktë'.\",\n    \"MATH_NUMBER_HELPURL\": \"http://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Një numër.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"x\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asinus\",\n    \"MATH_TRIG_ACOS\": \"acosinus\",\n    \"MATH_TRIG_ATAN\": \"atangjentë\",\n    \"MATH_ARITHMETIC_HELPURL\": \"http://sq.wikipedia.org/wiki/Aritmetika\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Kthen shumën e dy numrave.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Kthen ndryshimin e dy numrave.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Kthen produktin e dy numrave.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Kthen herësin e dy numrave.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Kthen numrin e parë të ngritur në fuqinë e numrit të dytë.\",\n    \"MATH_SINGLE_HELPURL\": \"http://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"rrënja katrore\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Kthen rrënjën katrore të një numri.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolut\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Kthen vlerën absolute të një numri.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Kthe negacionin e një numri.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Kthen logaritmën natyrale të një numri.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Kthen 10 logaritmet bazë të një numri.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Kthen e në fuqinë e një numri.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Kthen 10 në fuqinë e një numri.\",\n    \"MATH_TRIG_HELPURL\": \"http://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Kthe kosinusin e nje kendi (jo ne radiant).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Kthe kosinusin e nje grade (jo ne radiant).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Kthe tangentin e nje kendi (jo radiant).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Rikthe sin-1 e nje numeri.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Rikthe cos-1 e nje numeri.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Kthe tg-1 e nje numeri.\",\n    \"MATH_CONSTANT_HELPURL\": \"http://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Kthen një nga konstantet e përbashkëta: : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infiniti).\",\n    \"MATH_IS_EVEN\": \"është çift\",\n    \"MATH_IS_ODD\": \"është tek\",\n    \"MATH_IS_PRIME\": \"është prim\",\n    \"MATH_IS_WHOLE\": \"është i plotë\",\n    \"MATH_IS_POSITIVE\": \"është pozitiv\",\n    \"MATH_IS_NEGATIVE\": \"është negativ\",\n    \"MATH_IS_DIVISIBLE_BY\": \"është i pjestueshme me\",\n    \"MATH_IS_TOOLTIP\": \"Kontrollo nëse një numër është çift, tek, prim, i plotë, pozitiv, negativ, ose nëse është i pjestueshëm me një numër të caktuar. Kthehet e saktë ose e pasaktë.\",\n    \"MATH_CHANGE_HELPURL\": \"http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"ndrysho\",\n    \"MATH_CHANGE_INPUT_BY\": \"nga\",\n    \"MATH_CHANGE_TOOLTIP\": \"Shto një numër në ndryshoren '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"http://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Rrumbullakësimi i numrit të lartë ose të ulët.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"rrumbullakësimi\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"rrumbullakësimi i lartë\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"rrumbullakësimi i ulët\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"mbledhja e listës\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Kthe shumën e të gjithë numrave të listës.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"numri më i ulët i listës\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Kthe numrin me të vogël të listës.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"numri më i madh i listës\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Kthe numrin më të madh të listës.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"mesatarja e listës\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Kthen mesatarën (kuptimi aritmetik) i vlerave numerike të listës.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"mediana e listës\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Kthe numrin median të listës.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"modat e listës\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Kthe listën e sendit(eve) më të zakonshme të listës.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"devijimi standard i listës\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Kthe devijimin standard të listës.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"send i rastësishëm i listës\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Kthe një element të rastësishëm nga lista.\",\n    \"MATH_MODULO_HELPURL\": \"http://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"mbetësi i %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Kthen mbetësin nga pjestimi i dy numrave.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"detyro %1 e ulët %2 e lartë %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Vëni një numër që të jetë në mes të kufive të specifikuara(përfshirëse).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"http://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"numër i plotë i rastësishëm nga %1 deri në %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Kthe një numër të plotë të rastësishëm të dy kufijve të specifikuar, të përfshirë.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"http://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"fraksioni i rastësishëm\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Kthe fraksionin e rastësishëm në mes të 0.0 (përfshirëse) dhe 1.0 (jopërfshirëse).\",\n    \"TEXT_TEXT_HELPURL\": \"http://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Nje shkronje, fjale, ose rresht teksti.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"krijo tekst me\",\n    \"TEXT_JOIN_TOOLTIP\": \"Krijo nje pjese te tekstit duke bashkuar se bashku disa sende\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"bashkangjit\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këtë bllok teksti.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Shto nje gje ne tekst\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"ne\",\n    \"TEXT_APPEND_APPENDTEXT\": \"shto tekst\",\n    \"TEXT_APPEND_TOOLTIP\": \"shto tekst tek varibla '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"gjatesi %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Pergjigjet me nje numer shkronjash (duke perfshire hapesire) ne tekstin e dhene.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 eshte bosh\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Kthehet e vertete neqoftese teksti i dhene eshte bosh.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Pergjigjet me indeksin e pare/fundit te rastisjes se tekstit te pare ne tekstin e dyte. Pergjigjet me 0 ne qofte se teksti nuk u gjet.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"ne tekst\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"gjej rastisjen e pare te tekstit\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"gjej rastisjen e fundit te tekstit\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"ne tekst\",\n    \"TEXT_CHARAT_FROM_START\": \"merr shkronjen #\",\n    \"TEXT_CHARAT_FROM_END\": \"merr shkronjen # nga fundi\",\n    \"TEXT_CHARAT_FIRST\": \"merr shkronjen e pare\",\n    \"TEXT_CHARAT_LAST\": \"merr shkronjen e fundit\",\n    \"TEXT_CHARAT_RANDOM\": \"merr nje shkronje te rastesishme\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Kthe nje shkronje nga nje pozicion i caktuar.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Pergjigjet me nje pjese te caktuar teksti.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"ne tekst\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"Merr nenvargun nga shkronja #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"merr nenvargun nga shkronja # nga fundi\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"merr vlerat qe vazhdojne me shkronjen e pare\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"ne shkronjen #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"ne shkronjen # nga fundi\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"tek shkronja e fundit\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Kthe nje kopje te tekstit ne nje rast te ndryshem.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"me shkronja te medha shtypi\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"me shkronja te vogla shtypi\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"Fillimi me shkronje te madhe shtypi\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Pergjigju me nje kopje te tekstit me hapesira te fshira nga njera ane ose te dyja anet.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"prit hapesirat nga te dyja anet\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"prit hapesirat nga ana e majte\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"prit hapesirat nga ana e djathte\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"printo %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Printo tekstin e caktuar, numer ose vlere tjeter.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"kerko tekst me njoftim\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"kerko nje numer me njoftim\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Kerkoji perdoruesit nje numer.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Kerkoji perdoruesit ca tekst.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"krijo një listë të zbrazët\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Kthen një listë, te gjatësisë 0, duke mos përmbajtur asnjë regjistrim të të dhënave\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Krijo një listë me ndonjë numbër të sendeve.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"krijo listë me\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"listë\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këtë bllok të listës.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Shto një send në listë.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Krijon në listë qe përmban vlerën e dhënë të përsëritur aq herë sa numri i specifikuar.\",\n    \"LISTS_REPEAT_TITLE\": \"krijo listën me sendin %1 të përsëritur %2 herë\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"gjatësia e %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Kthen gjatësinë e listës.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 është e zbraztë\",\n    \"LISTS_TOOLTIP\": \"Kthehet i saktë nëse lista është e zbraztë.\",\n    \"LISTS_INLIST\": \"në listë\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"gjen ndodhjen e parë të sendit\",\n    \"LISTS_INDEX_OF_LAST\": \"gjen ndodhjen e fundit të sendit\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Kthen indeksin e ndodhjes së parë/fudit të sendit në listë. Kthen 0 nëse teksti nuk është gjetur.\",\n    \"LISTS_GET_INDEX_GET\": \"merr\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"merr dhe fshij\",\n    \"LISTS_GET_INDEX_REMOVE\": \"largo\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# nga fundi\",\n    \"LISTS_GET_INDEX_FIRST\": \"i parë\",\n    \"LISTS_GET_INDEX_LAST\": \"i fundit\",\n    \"LISTS_GET_INDEX_RANDOM\": \"i rastësishëm\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Kthen një send në pozicionin e specifikuar në listë. #1 është sendi i parë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Kthen një send në pozicionin e specifikuar në listë. #1 është sendi i fundit.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Rikthen tek artikulli i par në list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Kthen artikullin e fundit në list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Kthen një send të rastësishëm në listë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Fshin dhe kthen sendin në pozicionin e specifikuar në listë. #1 është sendi i parë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Fshin dhe kthen sendin në pozicionin e specifikuar në listë. #1 është sendi i fundit.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Fshin dhe kthen sendin e parë në listë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Fshin dhe kthen sendin e fundit në listë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Fshin dhe kthen një send të rastësishëm në listë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Fshin sendin në pozicionin e specifikuar në listë. #1 është sendi i parë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Fshin sendin në pozicionin e specifikuar në listë. #1 është sendi i fundit.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Fshin sendin e parë në listë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Fshin sendin e fundit në listë.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Kthen një send të rastësishëm në listë.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"vendos\",\n    \"LISTS_SET_INDEX_INSERT\": \"fut në\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"sikurse\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Vendos sendin në pozicionin e specifikuar në listë. #1 është sendi i parë.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Vendos sendin ne pozicionin e specifikuar në listë. #1 është sendi i fundit.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Vendos sendin e parë në listë.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Vendos sendin e fundit në listë.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Vendos një send të rastësishëm në listë.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Fut sendin në pozicionin e specifikuar të listës. #1 është sendi i parë.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Fut sendin në pozicionin e specifikuar të listës. #1 është sendi i fundit.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Fut sendin në fillim të listës.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Bashkangjit sendin në fund të listës.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Fut sendin rastësisht në listë.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"merr nën-listën nga #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"merr nën listën nga # nga fundi\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"merr nën-listën nga i pari\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"tek #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"tek # nga fundi\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"tek i fundit\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Krijon në kopje të pjesës së specifikuar të listës.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Pergjigjet me nje vlere te kesaj variable.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Krijo 'vendos %1\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"vendos\",\n    \"VARIABLES_SET_TAIL\": \"ne\",\n    \"VARIABLES_SET_TOOLTIP\": \"Vendos kete variable te jete e barabarte me te dhenat ne hyrje.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Krijo 'merr %1\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"te\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"bëj diqka\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"me:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Krijon një funksion pa dalje.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"rikthe\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Krijon një funksion me një dalje.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Paralajmërim: Ky funksion ka parametra të dyfishuar.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Lësho funksionin e definuar nga përdoruesi '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Lëho funksionin e definuar nga përdoruesi '%1' dhe përdor daljen e tij.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"Informacioni i futur\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"Fut emrin:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Thekso definicionin e funksionit\",\n    \"PROCEDURES_CREATE_DO\": \"Krijo '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Nëse një vlerë është e saktë, atëherë kthe një vlerë të dytë.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Paralajmërim: Ky bllok mund të përdoret vetëm brenda definicionit të funksionit.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/sr.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"ставка\",\n    \"DUPLICATE_BLOCK\": \"Дуплирај\",\n    \"ADD_COMMENT\": \"Додај Коментар\",\n    \"REMOVE_COMMENT\": \"Уклонити коментар\",\n    \"EXTERNAL_INPUTS\": \"Спољашњи Уноси\",\n    \"INLINE_INPUTS\": \"Линијски Уноси\",\n    \"DELETE_BLOCK\": \"Избриши Блок\",\n    \"DELETE_X_BLOCKS\": \"Избриши %1 Блокова\",\n    \"COLLAPSE_BLOCK\": \"Скупи Блок\",\n    \"COLLAPSE_ALL\": \"Скупи Блокове\",\n    \"EXPAND_BLOCK\": \"Прошири Блок\",\n    \"EXPAND_ALL\": \"Прошири Блокове\",\n    \"DISABLE_BLOCK\": \"Онеспособи Блок\",\n    \"ENABLE_BLOCK\": \"Оспособи Блок\",\n    \"HELP\": \"Помоћ\",\n    \"CHANGE_VALUE_TITLE\": \"Промени вредност:\",\n    \"NEW_VARIABLE\": \"Нова промењјива...\",\n    \"NEW_VARIABLE_TITLE\": \"Име нове промењиве:\",\n    \"RENAME_VARIABLE\": \"Преименовати варијаблу...\",\n    \"RENAME_VARIABLE_TITLE\": \"Преименовати све '%1' варијабле у:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Изаберите боју са палете.\",\n    \"COLOUR_RANDOM_TITLE\": \"насумична боја\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Изаберите боју насумице.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"обоји са\",\n    \"COLOUR_RGB_RED\": \"црвена\",\n    \"COLOUR_RGB_GREEN\": \"зелена\",\n    \"COLOUR_RGB_BLUE\": \"плава\",\n    \"COLOUR_RGB_TOOLTIP\": \"Креирај боју са одређеном количином црвене,зелене, и плаве. Све вредности морају бити између 0 и 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"Помешати\",\n    \"COLOUR_BLEND_COLOUR1\": \"Боја 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"Боја 2\",\n    \"COLOUR_BLEND_RATIO\": \"Коефициент\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Помешати две боје заједно са датим односом (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"поновите %1 пута\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"поновите\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"пута\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"урадите\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Одрадити неке наредбе неколико пута.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"понављати док\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"понављати до\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Док је вредност тачна, онда извршите неке наредбе.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Док вредност није тачна, онда извршити неке наредбе.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Имај промењиву %1 узми вредности од почетног броја до задњег броја, бројећи по одређеном интервалу, и изврши одређене блокове.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"преброј са\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"од %1 до %2 од %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"за сваку ставку\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"у листи\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"За сваку ставку унутар листе, подеси промењиву '%1' по ставци, и онда начини неке изјаве-наредбе.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"Изађите из петље\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"настави са следећом итерацијом петље\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Напусти садржај петље.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Прескочи остатак ове петље, и настави са следећом итерацијом(понављанјем).\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Упозорење: Овај блок може да се употреби само унутар петље.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"ако је вредност тачна, онда изврши неке наредбе-изјаве.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"ако је вредност тачна, онда изврши први блок наредби, У супротном, изврши други блок наредби.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Ако је прва вредност тачна, онда изврши први блок наредби, у супротном, ако је друга вредност тачна , изврши други блок наредби.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Ако је прва вредност тачна, онда изврши први блок наредби, у супротном, ако је друга вредност тачна , изврши други блок наредби. Ако ни једна од вредности није тачна, изврши последнји блок наредби.\",\n    \"CONTROLS_IF_MSG_IF\": \"ако\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"друго ако\",\n    \"CONTROLS_IF_MSG_ELSE\": \"друго (у другом случају)\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Додај, уклони, или преуреди делове како бих реконфигурисали овај иф блок.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Додај услов иф блоку.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Додај коначни, catch-all  (ухвати све) услове иф блока.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://sr.wikipedia.org/wiki/Неједнакост\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"враћа вредност тачно ако су оба уноса једнака један другом.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"враћа за вредност тачно ако су оба уноса различита.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Враћа за вредност тачно ако је први унос мањи од другог уноса.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"враћа за вредност тачно ако је први унос мањи или једнак другом уносу.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Враћа за вредност тачно ако је први унос већи од другог уноса.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"враћа за вредност тачно ако је први унос већи или једнак другом уносу.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Враћа за вредност тачно ако су оба уноса тачна.\",\n    \"LOGIC_OPERATION_AND\": \"И\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"враћа за вредност тачно ако је бар један од уноса тачан.\",\n    \"LOGIC_OPERATION_OR\": \"или\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"није %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Враћа за вредност тачно ако је унос нетачан. Враћа за вредност нетачно ако је унос тачан.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"тачно\",\n    \"LOGIC_BOOLEAN_FALSE\": \"нетачно\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"враћа вредност или тачно или нетачно.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"НИШТА\",\n    \"LOGIC_NULL_TOOLTIP\": \"Враћа нулу.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"тест\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"ако је тачно\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"ако је нетачно\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Провери услов у 'test'. Ако је услов тачан, тада враћа 'if true' вредност; у другом случају враћа 'if false' вредност.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Неки број.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"син\",\n    \"MATH_TRIG_COS\": \"цос\",\n    \"MATH_TRIG_TAN\": \"тан\",\n    \"MATH_TRIG_ASIN\": \"арц син\",\n    \"MATH_TRIG_ACOS\": \"арц цос\",\n    \"MATH_TRIG_ATAN\": \"арц тан\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Вратите збир два броја.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Вратите разлику два броја.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Вратите производ два броја.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Вратите количник два броја.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Вратите први број подигнут на власт другог броја.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"квадратни корен\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Вратити квадратни корен броја.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"апсолутан\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Вратите апсолутну вредност броја.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Враћа негативну вредност броја.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Вратити природни логаритам броја.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Враћа логаритам са базом 10 броја.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"вратити е на власти броја.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Враћа 10-ти степен броја.\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Вратите синус степена (не радијан).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Вратите косинус степена (не радијан).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Вратите тангенс степена (не радијан).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Вратите аркус  броја.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Вратити аркус косинуса броја.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Вратите аркус тангенс броја.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"врати једну од заједничких константи: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), или ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"је једнако\",\n    \"MATH_IS_ODD\": \"је непарно\",\n    \"MATH_IS_PRIME\": \"је прост\",\n    \"MATH_IS_WHOLE\": \"цео је\",\n    \"MATH_IS_POSITIVE\": \"је позитивно\",\n    \"MATH_IS_NEGATIVE\": \"је негативно\",\n    \"MATH_IS_DIVISIBLE_BY\": \"Је дељиво са\",\n    \"MATH_IS_TOOLTIP\": \"Провјерава да ли је број паран, непаран, прост, цио, позитиван, негативан, или да ли је делјив са одређеним бројем. Враћа тачно или нетачно.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"промени\",\n    \"MATH_CHANGE_INPUT_BY\": \"по, за, од\",\n    \"MATH_CHANGE_TOOLTIP\": \"додај број промењивој '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Заокружити број изнад или испод.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"Заокружити\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"Заокружити изнад\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"Заокружити испод\",\n    \"MATH_ONLIST_HELPURL\": \"\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"збир листе\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Враћа суму свих бројева са листе.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"минимални са листе\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Враћа најманји број са листе.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"Максимални са листе\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Враћа највећи број са листе.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"просечни са листе\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Враћа просјечну (аритметичку средину) нумеричких вредности са листе.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"са средине листе\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Враћа среднји број са листе.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"облици листе\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Враћа најчешћу ставку(е) са листе.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"стандардна девиација листе\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Враћа стандардну девијацију листе.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"Насумична ставка са листе\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Враћа насумично одабрани елемент са листе.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"подсетник од %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Вратити подсетник од дељења два броја.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"Ограничи %1 ниско %2 високо %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Ограничити број  да буде између одређених ограниченја (закључно).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"сличајно одабрани цијели број од %1 до %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Враћа случајно одабрани цели број између две одређене границе, уклјучиво.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"Насумична функција\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Враћа насумучно одабран дио између 0.0 (уклјучиво) и 1.0 (исклјучиво).\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Слово, реч, линија текста.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"написати текст са\",\n    \"TEXT_JOIN_TOOLTIP\": \"Направити дио текста спајајући различите ставке.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"придружити се\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Додај, уклони, или другачије поредај одјелке како би изнова поставили овај текст блок.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Додати ставку у текст.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"како би\",\n    \"TEXT_APPEND_APPENDTEXT\": \"закачити текст\",\n    \"TEXT_APPEND_TOOLTIP\": \"додати неки текст варијабли  '%1.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"дужина %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Враћа број слова (уклјучујући размаке) у датом тексту.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 је празно\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Враћа тачно ако је доставлјени текст празан.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Враћа однос првог/заднјег појавлјиванја текста у другом тексту. Врађа 0 ако текст није пронађен.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"у тексту\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"нађи прво појавлјиванје текста\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"нађи заднје појавлјиванје текста\",\n    \"TEXT_INDEXOF_TAIL\": \"\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"у тексту\",\n    \"TEXT_CHARAT_FROM_START\": \"добити слово #\",\n    \"TEXT_CHARAT_FROM_END\": \"добити сливо # са краја\",\n    \"TEXT_CHARAT_FIRST\": \"добити прво слово\",\n    \"TEXT_CHARAT_LAST\": \"Узми заднје слово\",\n    \"TEXT_CHARAT_RANDOM\": \"насумично одабери слово\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Враћа слово на одређену позицију.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Враћа одређен дио текста.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"у тексту\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"узмите низ од слова #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"узмите низ од слова # од краја\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"узмите низ од првог слова\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"слову #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"слову # са краја\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"заднјем слову\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Враћа копију текста у другачијем случају.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"великим словима\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"малим словима\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"свака реч починје великим словом\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Враћа копију текста са уклонјеним простором са једног од два краја.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"скратити простор са обе стране\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"скратити простор са леве стране\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"скратити простор са десне стране\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_PRINT_TITLE\": \"принатати %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Принтати одређени текст, број друге вредности.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"тражити текст са поруком\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"тражити број са поруком\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Питај корисника за број.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Питај корисника да ти да нешто текста.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"креирај празну листу\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"враћа листу, дужине 0, не садржавајући  евиденцију података\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Креирај листу са било којим бројем ставки.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"креирај листу са\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"листа\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Додајте, избришите, или преуредите делове како би се реорганизовали овај блок листе.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Додај ставку листи.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Прави листу која се састоји од задане вредности коју понавлјамо одређени број шута.\",\n    \"LISTS_REPEAT_TITLE\": \"Направити листу са ставком %1 која се понавлја %2 пута\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"дужина од %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Враћа дужину листе.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 је празан\",\n    \"LISTS_TOOLTIP\": \"Враћа вредност тачно ако је листа празна.\",\n    \"LISTS_INLIST\": \"у листи\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"наћи прво појавлјиванје ставке\",\n    \"LISTS_INDEX_OF_LAST\": \"наћи последнје појавлјиванје ставке\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Враћа однос првог/последнјег појавлјиванја ставке у листи. Враћа 0 ако се текст не наће.\",\n    \"LISTS_GET_INDEX_GET\": \"узми\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"узми и уклони\",\n    \"LISTS_GET_INDEX_REMOVE\": \"уклони\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# од краја\",\n    \"LISTS_GET_INDEX_FIRST\": \"први\",\n    \"LISTS_GET_INDEX_LAST\": \"последњи\",\n    \"LISTS_GET_INDEX_RANDOM\": \"насумичан\",\n    \"LISTS_GET_INDEX_TAIL\": \"\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Враћа ставку на одређену позицију на листи. #1 је прва ставка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Враћа ставку на одређену позицију на листи. #1 је последња ставка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Враћа прву ставку на листи.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Враћа последњу ставку у листи.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Враћа ставку из листе случајним одабиром.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Укланја и враћа ставку са одређене позиције са листе.#1 је прва ставка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Укланја и враћа ставку са одређене позиције са листе.#1 је последнја ставка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Укланја и враћа прву ставку са листе.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Укланја и враћа последнју ставку са листе.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Укланја и враћа насумићно одабрану ставку са листе.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Укланја ставку са одређене позиције на листи.#1 је прва ставка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Укланја ставку са одређене позиције на листи.#1 је последнја ставка.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Уклања прву ставку на листи.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Уклања последнју ставку са листе.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Уклања насумичну ставку на листи.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"поставити\",\n    \"LISTS_SET_INDEX_INSERT\": \"Убацити у\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"као\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Убацује ставку на одређену позицију на листи.#1 је прва ставка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Убацује ставку на одређену позицију на листи.#1 је последња ставка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"подешава прву ставку у листи.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Убацује последњу ставку у листи.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Убацује-Подешава насумичну ставку на листи.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Убацује ставку на одређену позицију на листи.#1 је прва ставка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Убацује ставку на одређену позицију на листи.#1 је последнја ставка.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Убацује ставку на почетак листе.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Вратити ставку на крај листе.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Убацује ставку на насумићно место на листи.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"узми под листу од #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"узми под-листу од # од краја\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"узмите под-листу од прве-ог\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"до #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"до # од краја\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"до последњег\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Прави копију одређеног дела листе.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"Враћа вриједност варијабле.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Направити сет %1\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"поставити\",\n    \"VARIABLES_SET_TAIL\": \"како би\",\n    \"VARIABLES_SET_TOOLTIP\": \"Чини да варијабла буде једнака уносу.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Креирај добити %1\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"како би\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"урадити нешто\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"са:\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Прави функцију без избациванја излазне вредности.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"Вратити\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Прави функцију са избациванјем излазне вредности.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Упозоренје: ова функција има дупле параметре.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Извршити функцију  '%1' коју корисник дефинира.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Извршити функцију  '%1' коју корисник дефинира и користи резултат.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"улазне вредности\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"Назив улазне вредности:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Истакнути дефиницију функције\",\n    \"PROCEDURES_CREATE_DO\": \"Израчунати '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Ако је вредност тачна, врати другу вредност.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Упозоренје: овај се блок може користити једино ако постоји дефиниција функције.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/sv.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Jopparn\",\n            \"WikiPhoenix\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"föremål\",\n    \"DUPLICATE_BLOCK\": \"Duplicera\",\n    \"ADD_COMMENT\": \"Lägg till kommentar\",\n    \"REMOVE_COMMENT\": \"Radera kommentar\",\n    \"EXTERNAL_INPUTS\": \"Externa inmatningar\",\n    \"INLINE_INPUTS\": \"radinmatning\",\n    \"DELETE_BLOCK\": \"Radera block\",\n    \"DELETE_X_BLOCKS\": \"Radera %1 block\",\n    \"COLLAPSE_BLOCK\": \"Fäll ihop block\",\n    \"COLLAPSE_ALL\": \"Fäll ihop block\",\n    \"EXPAND_BLOCK\": \"Expandera block\",\n    \"EXPAND_ALL\": \"Expandera block\",\n    \"DISABLE_BLOCK\": \"Inaktivera block\",\n    \"ENABLE_BLOCK\": \"Aktivera block\",\n    \"HELP\": \"Hjälp\",\n    \"CHANGE_VALUE_TITLE\": \"Ändra värde:\",\n    \"NEW_VARIABLE\": \"Ny variabel...\",\n    \"NEW_VARIABLE_TITLE\": \"Nytt variabelnamn:\",\n    \"RENAME_VARIABLE\": \"Byt namn på variabel...\",\n    \"RENAME_VARIABLE_TITLE\": \"Byt namn på alla variablerna '%1' till:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://sv.wikipedia.org/wiki/Färg\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Välj en färg från paletten.\",\n    \"COLOUR_RANDOM_TITLE\": \"slumpfärg\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Välj en slumpartad färg.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"färg med\",\n    \"COLOUR_RGB_RED\": \"röd\",\n    \"COLOUR_RGB_GREEN\": \"grön\",\n    \"COLOUR_RGB_BLUE\": \"blå\",\n    \"COLOUR_RGB_TOOLTIP\": \"Skapa en färg med det angivna mängden röd, grön och blå. Alla värden måste vara mellan 0 och 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"blanda\",\n    \"COLOUR_BLEND_COLOUR1\": \"färg 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"färg 2\",\n    \"COLOUR_BLEND_RATIO\": \"förhållande\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Blandar ihop två färger med ett bestämt förhållande (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"upprepa %1 gånger\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"upprepa\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"gånger\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"utför\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Utför några kommandon flera gånger.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"upprepa medan\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"upprepa tills\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Medan ett värde är sant, utför några kommandon.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Medan ett värde är falskt, utför några kommandon.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Låt variabeln %1 ta värden från starttalet till sluttalet, beräknat med det angivna intervallet, och utför de angivna blocken.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"räkna med\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"från %1 till %2 med %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each för \\\"varje\\\"-block\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"för varje föremål\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"i listan\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"För varje objekt i en lista, ange variabeln '%1' till objektet, och utför sedan några kommandon.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"bryt ut ur upprepning\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"fortsätta med nästa upprepning av loop\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Bryta ut ur den innehållande upprepningen.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Hoppa över resten av denna upprepning och fortsätt med nästa upprepning.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Varning: Detta block kan endast användas i en upprepning.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Om ett värde är sant, utför några kommandon.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Om värdet är sant, utför det första kommandoblocket. Annars utför det andra kommandoblocket.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Om det första värdet är sant, utför det första kommandoblocket. Annars, om det andra värdet är sant, utför det andra kommandoblocket.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Om det första värdet är sant, utför det första kommandoblocket. Annars, om det andra värdet är sant, utför det andra kommandoblocket. Om ingen av värdena är sanna, utför det sista kommandoblocket.\",\n    \"CONTROLS_IF_MSG_IF\": \"om\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"annars om\",\n    \"CONTROLS_IF_MSG_ELSE\": \"annars\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Lägg till, ta bort eller ändra ordningen för sektioner för att omkonfigurera blocket \\\"om\\\".\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Lägg till ett villkor blocket \\\"om\\\".\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Lägg till ett sista villkor som täcker alla alternativ som är kvar för \\\"if\\\"-blocket.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://sv.wikipedia.org/wiki/Olikhet\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Ger tillbaka sant om båda värdena är lika med varandra.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Ger tillbaka sant om båda värdena inte är lika med varandra.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Ger tillbaka sant om den första värdet är mindre än det andra.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Ger tillbaka sant om den första värdet är mindre än eller lika med det andra.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Ger tillbaka sant om den första värdet är större än det andra.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Ger tillbaka sant om den första värdet är större än eller lika med det andra.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Ger tillbaka sant om båda värdena är sanna.\",\n    \"LOGIC_OPERATION_AND\": \"och\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Ger tillbaka sant om minst ett av värdena är sant.\",\n    \"LOGIC_OPERATION_OR\": \"eller\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"inte %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Ger tillbaka sant om inmatningen är falsk. Ger tillbaka falskt och inmatningen är sann.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"sant\",\n    \"LOGIC_BOOLEAN_FALSE\": \"falskt\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Returnerar antingen sant eller falskt.\",\n    \"LOGIC_NULL_HELPURL\": \"https://sv.wikipedia.org/wiki/Null\",\n    \"LOGIC_NULL\": \"null\",\n    \"LOGIC_NULL_TOOLTIP\": \"Returnerar null.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"om sant\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"om falskt\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Kontrollera villkoret i \\\"test\\\". Om villkoret är sant, ge tillbaka \\\"om sant\\\"-värdet; annars ge tillbaka \\\"om falskt\\\"-värdet.\",\n    \"MATH_NUMBER_HELPURL\": \"https://sv.wikipedia.org/wiki/Tal\",\n    \"MATH_NUMBER_TOOLTIP\": \"Ett tal.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"arcsin\",\n    \"MATH_TRIG_ACOS\": \"arccos\",\n    \"MATH_TRIG_ATAN\": \"arctan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://sv.wikipedia.org/wiki/Aritmetik\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Returnerar summan av de två talen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Returnerar differensen mellan de två talen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Returnerar produkten av de två talen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Returnerar kvoten av de två talen.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Ger tillbaka det första talet upphöjt till det andra talet.\",\n    \"MATH_SINGLE_HELPURL\": \"https://sv.wikipedia.org/wiki/Kvadratrot\",\n    \"MATH_SINGLE_OP_ROOT\": \"kvadratrot\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Returnerar kvadratroten av ett tal.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolut\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Returnerar absolutvärdet av ett tal.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Returnerar negationen av ett tal.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Returnera den naturliga logaritmen av ett tal.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Returnerar logaritmen för bas 10 av ett tal.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Ger tillbaka e upphöjt i ett tal.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Ger tillbaka 10 upphöjt i ett tal.\",\n    \"MATH_TRIG_HELPURL\": \"https://sv.wikipedia.org/wiki/Trigonometrisk_funktion\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Ger tillbaka sinus för en grad (inte radian).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Ger tillbaka cosinus för en grad (inte radian).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Ger tillbaka tangens för en grad (inte radian).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Ger tillbaka arcus sinus (arcsin) för ett tal.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Ger tillbaka arcus cosinus (arccos) för ett tal.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Ger tillbaka arcus tangens (arctan) av ett tal.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://sv.wikipedia.org/wiki/Matematisk_konstant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Returnerar en av de vanliga konstanterna: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) eller ∞ (oändligt).\",\n    \"MATH_IS_EVEN\": \"är jämnt\",\n    \"MATH_IS_ODD\": \"är ojämnt\",\n    \"MATH_IS_PRIME\": \"är ett primtal\",\n    \"MATH_IS_WHOLE\": \"är helt\",\n    \"MATH_IS_POSITIVE\": \"är positivt\",\n    \"MATH_IS_NEGATIVE\": \"är negativt\",\n    \"MATH_IS_DIVISIBLE_BY\": \"är delbart med\",\n    \"MATH_IS_TOOLTIP\": \"Kontrollera om ett tal är jämnt, ojämnt, helt, positivt, negativt eller det är delbart med ett bestämt tal. Returnerar med sant eller falskt.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"ändra\",\n    \"MATH_CHANGE_INPUT_BY\": \"med\",\n    \"MATH_CHANGE_TOOLTIP\": \"Lägg till ett tal till variabeln '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://sv.wikipedia.org/wiki/Avrundning\",\n    \"MATH_ROUND_TOOLTIP\": \"Avrunda ett tal uppåt eller nedåt.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"avrunda\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"avrunda uppåt\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"avrunda nedåt\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"summan av listan\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Ger tillbaka summan av alla talen i listan.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"minsta talet i listan\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Ger tillbaka det minsta talet i listan.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"högsta talet i listan\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Ger tillbaka det största talet i listan.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"medelvärdet av listan\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Ger tillbaka medelvärdet (aritmetiskt) av de numeriska värdena i listan.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"medianen av listan\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Returnerar medianen av talen i listan.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"typvärdet i listan\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Ger tillbaka en lista med de(t) vanligaste objekte(t/n) i listan.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"standardavvikelsen i listan\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Ger tillbaka standardavvikelsen i listan.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"slumpmässigt objekt i listan\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Returnerar ett slumpmässigt element från listan.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"resten av %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Returnerar kvoten från divisionen av de två talen.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"begränsa %1 till mellan %2 och %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Begränsa ett tal till att mellan de angivna gränsvärden (inklusive).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://sv.wikipedia.org/wiki/Slumptalsgenerator\",\n    \"MATH_RANDOM_INT_TITLE\": \"slumpartat heltal från %1 till %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Ger tillbaka ett slumpat heltal mellan två värden (inklusive).\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://sv.wikipedia.org/wiki/Slumptalsgenerator\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"slumpat decimaltal\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Ger tillbaka ett slumpat decimaltal mellan 0.0 (inkluderat) och 1.0 (exkluderat).\",\n    \"TEXT_TEXT_HELPURL\": \"https://sv.wikipedia.org/wiki/Str%C3%A4ng_%28data%29\",\n    \"TEXT_TEXT_TOOLTIP\": \"En bokstav, ord eller textrad.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"skapa text med\",\n    \"TEXT_JOIN_TOOLTIP\": \"Skapa en textbit genom att sammanfoga ett valfritt antal föremål.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"sammanfoga\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Lägg till, ta bort eller ändra ordningen för sektioner för att omkonfigurera detta textblock.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Lägg till ett föremål till texten.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"till\",\n    \"TEXT_APPEND_APPENDTEXT\": \"lägg till text\",\n    \"TEXT_APPEND_TOOLTIP\": \"Lägg till lite text till variabeln '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"längden på %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Ger tillbaka antalet bokstäver (inklusive mellanslag) i den angivna texten.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 är tom\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Returnerar sant om den angivna texten är tom.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Ger tillbaka indexet för den första/sista förekomsten av första texten i den andra texten.  Ger tillbaka 0 om texten inte hittas.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"i texten\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"hitta första förekomsten av texten\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"hitta sista förekomsten av texten\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"i texten\",\n    \"TEXT_CHARAT_FROM_START\": \"hämta bokstaven #\",\n    \"TEXT_CHARAT_FROM_END\": \"hämta bokstaven # från slutet\",\n    \"TEXT_CHARAT_FIRST\": \"hämta första bokstaven\",\n    \"TEXT_CHARAT_LAST\": \"hämta sista bokstaven\",\n    \"TEXT_CHARAT_RANDOM\": \"hämta slumpad bokstav\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Ger tillbaka bokstaven på den specificerade positionen.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Ger tillbaka en viss del av texten.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"i texten\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"få textdel från bokstav #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"få textdel från bokstav # från slutet\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"få textdel från första bokstaven\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"till bokstav #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"till bokstav # från slutet\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"till sista bokstaven\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Returnerar en kopia av texten i ett annat skiftläge.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"till VERSALER\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"till gemener\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"till Versala Initialer\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Returnerar en kopia av texten med borttagna mellanrum från en eller båda ändar.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"ta bort mellanrum från båda sidorna av\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"ta bort mellanrum från vänstra sidan av\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"ta bort mellanrum från högra sidan av\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"skriv %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Skriv den angivna texten, talet eller annat värde.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"fråga efter text med meddelande\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"fråga efter ett tal med meddelande\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Fråga användaren efter ett tal.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Fråga användaren efter lite text.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"skapa tom lista\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Ger tillbaka en lista utan någon data, alltså med längden 0\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Skapa en lista med valfritt antal föremål.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"skapa lista med\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"lista\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Lägg till, ta bort eller ändra ordningen på objekten för att göra om det här \\\"list\\\"-blocket.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Lägg till ett föremål till listan.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Skapar en lista som innehåller ett valt värde upprepat ett bestämt antalet gånger.\",\n    \"LISTS_REPEAT_TITLE\": \"skapa lista med föremålet %1 upprepat %2 gånger\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"längden på %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Returnerar längden på en lista.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 är tom\",\n    \"LISTS_TOOLTIP\": \"Returnerar sant om listan är tom.\",\n    \"LISTS_INLIST\": \"i listan\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"hitta första förekomsten av objektet\",\n    \"LISTS_INDEX_OF_LAST\": \"hitta sista förekomsten av objektet\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Ger tillbaka den första/sista förekomsten av objektet i listan. Ger tillbaka 0 om texten inte hittas.\",\n    \"LISTS_GET_INDEX_GET\": \"hämta\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"hämta och ta bort\",\n    \"LISTS_GET_INDEX_REMOVE\": \"ta bort\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# från slutet\",\n    \"LISTS_GET_INDEX_FIRST\": \"första\",\n    \"LISTS_GET_INDEX_LAST\": \"sista\",\n    \"LISTS_GET_INDEX_RANDOM\": \"slumpad\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Ger tillbaka objektet på den efterfrågade positionen i en lista. #1 är det första objektet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Ger tillbaka objektet på den efterfrågade positionen i en lista. #1 är det sista objektet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Returnerar det första objektet i en lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Returnerar det sista objektet i en lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Returnerar ett slumpmässigt objekt i en lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Tar bort och återställer objektet på den specificerade positionen i en lista. #1 är det första objektet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Tar bort och återställer objektet på den specificerade positionen i en lista. #1 är det sista objektet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Tar bort och återställer det första objektet i en lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Tar bort och återställer det sista objektet i en lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Tar bort och återställer ett slumpmässigt objekt i en lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Tar bort objektet på den specificerade positionen i en lista. #1 är det första objektet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Tar bort objektet på den efterfrågade positionen i en lista. #1 är det sista objektet.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Tar bort det första objektet i en lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Tar bort det sista objektet i en lista.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Tar bort en slumpmässig post i en lista.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"ange\",\n    \"LISTS_SET_INDEX_INSERT\": \"Sätt in vid\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"som\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Sätter in objektet vid en specificerad position i en lista. #1 är det första objektet.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Sätter in objektet vid en specificerad position i en lista. #1 är det sista objektet.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Anger det första objektet i en lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Anger det sista elementet i en lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Sätter in ett slumpat objekt i en lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Sätter in objektet vid en specificerad position i en lista. #1 är det första objektet.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"sätter in objektet vid en specificerad position i en lista. #1 är det sista objektet.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"sätter in objektet i början av en lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Lägg till objektet i slutet av en lista.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"sätter in objektet på en slumpad position i en lista.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"få underlista från #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"få underlista från # från slutet\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"få underlista från första\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"till #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"till # från slutet\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"till sista\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Skapar en kopia av den specificerade delen av en lista.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Returnerar värdet av denna variabel.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Skapa \\\"välj %1\\\"\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"välj\",\n    \"VARIABLES_SET_TAIL\": \"till\",\n    \"VARIABLES_SET_TOOLTIP\": \"Gör så att den här variabeln blir lika med inputen.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Skapa 'hämta %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://sv.wikipedia.org/wiki/Funktion_%28programmering%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"för att\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"göra något\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"med:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Skapar en funktion utan output.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://sv.wikipedia.org/wiki/Funktion_%28programmering%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"returnera\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Skapar en funktion med output.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Varning: Denna funktion har dubbla parametrar.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://sv.wikipedia.org/wiki/Funktion_%28programmering%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Kör den användardefinierade funktionen \\\"%1\\\".\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://sv.wikipedia.org/wiki/Funktion_%28programmering%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Kör den användardefinierade funktionen \\\"%1\\\" och använd resultatet av den.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"inmatningar\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"inmatningsnamn:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Markera funktionsdefinition\",\n    \"PROCEDURES_CREATE_DO\": \"Skapa '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Om ett värde är sant returneras ett andra värde.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Varning: Detta block får användas endast i en funktionsdefinition.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/synonyms.json",
    "content": "{\"PROCEDURES_DEFRETURN_TITLE\": \"PROCEDURES_DEFNORETURN_TITLE\", \"LISTS_GET_SUBLIST_INPUT_IN_LIST\": \"LISTS_INLIST\", \"LISTS_SET_INDEX_INPUT_IN_LIST\": \"LISTS_INLIST\", \"PROCEDURES_DEFRETURN_PROCEDURE\": \"PROCEDURES_DEFNORETURN_PROCEDURE\", \"VARIABLES_SET_ITEM\": \"VARIABLES_DEFAULT_NAME\", \"LISTS_CREATE_WITH_ITEM_TITLE\": \"VARIABLES_DEFAULT_NAME\", \"CONTROLS_IF_ELSE_TITLE_ELSE\": \"CONTROLS_IF_MSG_ELSE\", \"VARIABLES_GET_ITEM\": \"VARIABLES_DEFAULT_NAME\", \"PROCEDURES_DEFRETURN_DO\": \"PROCEDURES_DEFNORETURN_DO\", \"LISTS_GET_INDEX_HELPURL\": \"LISTS_INDEX_OF_HELPURL\", \"TEXT_CREATE_JOIN_ITEM_TITLE_ITEM\": \"VARIABLES_DEFAULT_NAME\", \"CONTROLS_IF_MSG_THEN\": \"CONTROLS_REPEAT_INPUT_DO\", \"LISTS_INDEX_OF_INPUT_IN_LIST\": \"LISTS_INLIST\", \"PROCEDURES_CALLRETURN_CALL\": \"PROCEDURES_CALLNORETURN_CALL\", \"LISTS_GET_INDEX_INPUT_IN_LIST\": \"LISTS_INLIST\", \"CONTROLS_IF_ELSEIF_TITLE_ELSEIF\": \"CONTROLS_IF_MSG_ELSEIF\", \"CONTROLS_FOREACH_INPUT_DO\": \"CONTROLS_REPEAT_INPUT_DO\", \"CONTROLS_IF_IF_TITLE_IF\": \"CONTROLS_IF_MSG_IF\", \"CONTROLS_WHILEUNTIL_INPUT_DO\": \"CONTROLS_REPEAT_INPUT_DO\", \"CONTROLS_FOR_INPUT_DO\": \"CONTROLS_REPEAT_INPUT_DO\", \"TEXT_APPEND_VARIABLE\": \"VARIABLES_DEFAULT_NAME\", \"MATH_CHANGE_TITLE_ITEM\": \"VARIABLES_DEFAULT_NAME\"}"
  },
  {
    "path": "extern/blockly/msg/json/th.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Azpirin\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"รายการ\",\n    \"DUPLICATE_BLOCK\": \"สร้างซ้ำ\",\n    \"ADD_COMMENT\": \"ใส่คำอธิบาย\",\n    \"REMOVE_COMMENT\": \"เอาคำอธิบายออก\",\n    \"EXTERNAL_INPUTS\": \"อินพุตภายนอก\",\n    \"INLINE_INPUTS\": \"อินพุตแบบอินไลน์\",\n    \"DELETE_BLOCK\": \"ลบบล็อก\",\n    \"DELETE_X_BLOCKS\": \"ลบ %1 บล็อก\",\n    \"COLLAPSE_BLOCK\": \"ย่อบล็อก\",\n    \"COLLAPSE_ALL\": \"ย่อบล็อก\",\n    \"EXPAND_BLOCK\": \"ขยายบล็อก\",\n    \"EXPAND_ALL\": \"ขยายบล็อก\",\n    \"DISABLE_BLOCK\": \"ปิดการทำงานของบล็อกนี้\",\n    \"ENABLE_BLOCK\": \"เปิดการทำงานของบล็อกนี้\",\n    \"HELP\": \"ช่วยเหลือ\",\n    \"CHANGE_VALUE_TITLE\": \"เปลี่ยนค่า:\",\n    \"NEW_VARIABLE\": \"สร้างตัวแปรใหม่\",\n    \"NEW_VARIABLE_TITLE\": \"ชื่อตัวแปร:\",\n    \"RENAME_VARIABLE\": \"เปลี่ยนชื่อตัวแปร...\",\n    \"RENAME_VARIABLE_TITLE\": \"เปลี่ยนชื่อ \\\"%1\\\" เป็น:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://th.wikipedia.org/wiki/สี\",\n    \"COLOUR_PICKER_TOOLTIP\": \"เลือกสีจากจานสี\",\n    \"COLOUR_RANDOM_TITLE\": \"สุ่มสี\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"เลือกสีแบบสุ่ม\",\n    \"COLOUR_RGB_TITLE\": \"สีที่ประกอบด้วย\",\n    \"COLOUR_RGB_RED\": \"ค่าสีแดง\",\n    \"COLOUR_RGB_GREEN\": \"ค่าสีเขียว\",\n    \"COLOUR_RGB_BLUE\": \"ค่าสีน้ำเงิน\",\n    \"COLOUR_RGB_TOOLTIP\": \"สร้างสีด้วยการกำหนดค่าของสีแดง เขียว และน้ำเงิน โดยต้องเป็นค่าระหว่าง 0 จนถึง 100\",\n    \"COLOUR_BLEND_TITLE\": \"ผสม\",\n    \"COLOUR_BLEND_COLOUR1\": \"สีที่ 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"สีที่ 2\",\n    \"COLOUR_BLEND_RATIO\": \"อัตราส่วน\",\n    \"COLOUR_BLEND_TOOLTIP\": \"ผสมสีทั้งสองเข้าด้วยกันด้วยอัตราส่วน (0.0 - 1.0)\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"ทำซ้ำ %1 ครั้ง\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"ทำซ้ำ\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"ครั้ง\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"ทำ:\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"ทำซ้ำคำสั่งตามจำนวนครั้งที่กำหนด\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"ทำซ้ำ ตราบใดที่\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"ทำซ้ำ จนกว่าจะ\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"ถ้าเงื่อนไขเป็นจริง ก็จะทำตามคำสั่งที่กำหนด\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"ถ้าเงื่อนไขเป็นเท็จ ก็จะทำตามคำสั่งที่กำหนด\",\n    \"CONTROLS_FOR_TOOLTIP\": \"ตัวแปร \\\"%1\\\" จะมีค่าตั้งแต่จำนวนเริ่มต้น ไปจนถึงจำนวนสิ้นสุด โดยมีการเปลี่ยนแปลงตามจำนวนที่กำหนด\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"นับ\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"จาก %1 จนถึง %2 เปลี่ยนค่าทีละ %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"วนซ้ำทุกรายการ\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"ในรายการ\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"ทำซ้ำทุกรายการ กำหนดค่าตัวแปร \\\"%1\\\" ตามรายการ และทำตามคำสั่งที่กำหนดไว้\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"ออกจากการวนซ้ำ\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"เริ่มการวนซ้ำรอบต่อไป\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"ออกจากการวนซ้ำที่มีอยู่\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"ข้ามสิ่งที่เหลืออยู่ และไปเริ่มวนซ้ำรอบต่อไปทันที\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"ระวัง: บล็อกชนิดนี้สามารถใช้งานได้เมื่ออยู่ภายในการวนซ้ำเท่านั้น\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"ว่าเงื่อนไขเป็นจริง ก็จะ \\\"ทำ\\\" ตามที่กำหนด\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"ถ้าเงื่อนไขเป็นจริง ก็จะ \\\"ทำ\\\" ตามที่กำหนด แต่ถ้าเงื่อนไขเป็นเท็จก็จะทำ \\\"นอกเหนือจากนี้\\\"\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"ถ้าเงื่อนไขแรกเป็นจริง ก็จะทำตามคำสั่งในบล็อกแรก แต่ถ้าไม่ก็จะไปตรวจเงื่อนไขที่สอง ถ้าเงื่อนไขที่สองเป็นจริง ก็จะทำตามเงื่อนไขในบล็อกที่สองนี้\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"ถ้าเงื่อนไขแรกเป็นจริง ก็จะทำคำสั่งในบล็อกแรก จากนั้นจะข้ามคำสั่งในบล็อกที่เหลือ แต่ถ้าเงื่อนไขแรกเป็นเท็จ ก็จะทำการตรวจเงื่อนไขที่สอง ถ้าเงื่อนไขที่สองเป็นจริง ก็จะทำตามคำสั่งในบล็อกที่สอง จากนั้นจะข้ามคำสั่งในบล็อกที่เหลือ แต่ถ้าทั้งเงื่อนไขแรกและเงื่อนไขที่สองเป็นเท็จทั้งหมด ก็จะมาทำบล็อกที่สาม\",\n    \"CONTROLS_IF_MSG_IF\": \"ถ้า\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"นอกเหนือจากนี้ ถ้า\",\n    \"CONTROLS_IF_MSG_ELSE\": \"นอกเหนือจากนี้\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"เพิ่ม ลบ หรือจัดเรียงบล็อก \\\"ถ้า\\\" นี้ใหม่\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"กำหนดเงื่อนไขของบล็อก \\\"ถ้า\\\"\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"เพิ่มสิ่งสุดท้าย ที่จะตรวจจับความเป็นไปได้ทั้งหมดของบล็อก \\\"ถ้า\\\"\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://th.wikipedia.org/wiki/อสมการ\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าที่ใส่ทั้งสองค่านั้นเท่ากัน\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าที่ใส่ทั้งสองค่านั้นไม่เท่ากัน\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าแรกน้อยกว่าค่าที่สอง\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าแรกน้อยกว่าหรือเท่ากับค่าที่สอง\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าแรกมากกว่าค่าที่สอง\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าแรกมากกว่าหรือเท่ากับค่าที่สอง\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าทั้งสองค่าเป็นจริง\",\n    \"LOGIC_OPERATION_AND\": \"และ\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"คืนค่าเป็น \\\"จริง\\\" ถ้ามีอย่างน้อยหนึ่งค่าที่เป็นจริง\",\n    \"LOGIC_OPERATION_OR\": \"หรือ\",\n    \"LOGIC_NEGATE_TITLE\": \"ไม่ %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"คืนค่าเป็น \\\"จริง\\\" ถ้าค่าที่ใส่เป็นเท็จ\\nคืนค่าเป็น \\\"เท็จ\\\" ถ้าค่าที่ใส่เป็นจริง\",\n    \"LOGIC_BOOLEAN_TRUE\": \"จริง\",\n    \"LOGIC_BOOLEAN_FALSE\": \"เท็จ\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"คืนค่าเป็นจริงหรือเท็จ\",\n    \"LOGIC_NULL\": \"ไม่กำหนด\",\n    \"LOGIC_NULL_TOOLTIP\": \"คืนค่า \\\"ไม่กำหนด\\\"\",\n    \"LOGIC_TERNARY_CONDITION\": \"ทดสอบ\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"ถ้า เป็นจริง\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"ถ้า เป็นเท็จ\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"ตรวจสอบเงื่อนไขใน \\\"ทดสอบ\\\" ถ้าเงื่อนไขเป็นจริง จะคืนค่า \\\"ถ้า เป็นจริง\\\" ถ้าเงื่อนไขเป็นเท็จ จะคืนค่า \\\"ถ้า เป็นเท็จ\\\"\",\n    \"MATH_NUMBER_HELPURL\": \"https://th.wikipedia.org/wiki/จำนวน\",\n    \"MATH_NUMBER_TOOLTIP\": \"จำนวน\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://th.wikipedia.org/wiki/เลขคณิต\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"คืนค่าผลรวมของตัวเลขทั้งสองจำนวน\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"คืนค่าผลต่างของตัวเลขทั้งสองจำนวน\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"คืนค่าผลคูณของตัวเลขทั้งสองจำนวน\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"คืนค่าผลหารของตัวเลขทั้งสองจำนวน\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"คืนค่าผลการยกกำลัง โดยตัวเลขแรกเป็นฐาน และตัวเลขที่สองเป็นเลขชี้กำลัง\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"รากที่สอง\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"คืนค่ารากที่สองของตัวเลข\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"ค่าสัมบูรณ์\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"คืนค่าค่าสัมบูรณ์ของตัวเลข\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"คืนค่าติดลบของตัวเลข\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"คืนค่าลอการิทึมธรรมชาติของตัวเลข\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"คืนค่าลอการิทึมฐานสิบของตัวเลข\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"คืนค่า e ยกกำลังด้วยตัวเลข\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"คืนค่า 10 ยกกำลังด้วยตัวเลข\",\n    \"MATH_TRIG_HELPURL\": \"https://th.wikipedia.org/wiki/ฟังก์ชันตรีโกณมิติ\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"คืนค่า sine ขององศา (ไม่ใช่เรเดียน)\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"คืนค่า cosine ขององศา (ไม่ใช่เรเดียน)\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"คืนค่า tangent ขององศา (ไม่ใช่เรเดียน)\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"คืนค่า arcsine ของตัวเลข\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"คืนค่า arccosine ของตัวเลข\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"คืนค่า arctangent ของตัวเลข\",\n    \"MATH_CONSTANT_HELPURL\": \"https://th.wikipedia.org/wiki/ค่าคงตัวทางคณิตศาสตร์\",\n    \"MATH_CONSTANT_TOOLTIP\": \"คืนค่าคงตัวทางคณิตศาสตร์ที่พบบ่อยๆ เช่น π (3.141…), e (2.718…), φ (1.618…), รากที่สอง (1.414…), รากที่ ½ (0.707…), ∞ (อนันต์)\",\n    \"MATH_IS_EVEN\": \"เป็นจำนวนคู่\",\n    \"MATH_IS_ODD\": \"เป็นจำนวนคี่\",\n    \"MATH_IS_PRIME\": \"เป็นจำนวนเฉพาะ\",\n    \"MATH_IS_WHOLE\": \"เป็นเลขจำนวนเต็ม\",\n    \"MATH_IS_POSITIVE\": \"เป็นเลขบวก\",\n    \"MATH_IS_NEGATIVE\": \"เป็นเลขติดลบ\",\n    \"MATH_IS_DIVISIBLE_BY\": \"หารลงตัว\",\n    \"MATH_IS_TOOLTIP\": \"ตรวจว่าตัวเลขเป็นจำนวนคู่ จำนวนคี่ จำนวนเฉพาะ จำนวนเต็ม เลขบวก เลขติดลบ หรือหารด้วยเลขที่กำหนดลงตัวหรือไม่ คืนค่าเป็นจริงหรือเท็จ\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"เปลี่ยนค่า\",\n    \"MATH_CHANGE_INPUT_BY\": \"เป็น\",\n    \"MATH_CHANGE_TOOLTIP\": \"เพิ่มค่าของตัวแปร \\\"%1\\\"\",\n    \"MATH_ROUND_HELPURL\": \"https://th.wikipedia.org/wiki/การปัดเศษ\",\n    \"MATH_ROUND_TOOLTIP\": \"ปัดเศษของตัวเลขขึ้นหรือลง\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"ปัดเศษ\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"ปัดเศษขึ้น\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"ปัดเศษลง\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"ผลรวมของรายการ\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"คืนค่าผลรวมของตัวเลขทั้งหมดในรายการ\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"น้อยที่สุดในรายการ\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"คืนค่าตัวเลขที่น้อยที่สุดในรายการ\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"มากที่สุดในรายการ\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"คืนค่าตัวเลขที่มากที่สุดในรายการ\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"ค่าเฉลี่ยของรายการ\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"คืนค่าเฉลี่ยของรายการ\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"ค่ามัธยฐานของรายการ\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"คืนค่ามัธยฐานของรายการ\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"ฐานนิยมของรายการ\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"คืนค่าฐานนิยมของรายการ\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"ส่วนเบี่ยงเบนมาตรฐานของรายการ\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"คืนค่าส่วนเบี่ยงเบนมาตรฐานของรายการ\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"สุ่มรายการ\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"สุ่มคืนค่าสิ่งที่อยู่ในรายการ\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"เศษของ %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"คืนค่าเศษที่ได้จากการหารของตัวเลขทั้งสองจำนวน\",\n    \"MATH_CONSTRAIN_TITLE\": \"จำกัดค่า %1 ต่ำสุด %2 สูงสุด %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"จำกัดค่าของตัวเลขให้อยู่ในช่วงที่กำหนด\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"สุ่มเลขจำนวนเต็มตั้งแต่ %1 จนถึง %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"สุ่มเลขจำนวนเต็มจากช่วงที่กำหนด\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"สุ่มเลขเศษส่วน\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"สุ่มเลขเศษส่วน ตั้งแต่ 0.0 แต่ไม่เกิน 1.0\",\n    \"TEXT_TEXT_HELPURL\": \"https://th.wikipedia.org/wiki/สายอักขระ\",\n    \"TEXT_TEXT_TOOLTIP\": \"ตัวหนังสือ คำ หรือข้อความ\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"สร้างข้อความด้วย\",\n    \"TEXT_JOIN_TOOLTIP\": \"สร้างข้อความด้วยการรวมจำนวนของรายการเข้าด้วยกัน\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"รวม\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"เพิ่ม ลบ หรือจัดเรียงบล็อกข้อความนี้ใหม่\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"เพิ่มรายการเข้าไปในข้อความ\",\n    \"TEXT_APPEND_TO\": \"นำเอา\",\n    \"TEXT_APPEND_APPENDTEXT\": \"ต่อด้วยข้อความ\",\n    \"TEXT_APPEND_TOOLTIP\": \"ต่อข้อความให้ตัวแปร \\\"%1\\\"\",\n    \"TEXT_LENGTH_TITLE\": \"ความยาวของ %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"คืนค่าความยาวของข้อความ (รวมช่องว่าง)\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 ว่าง\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"คืนค่าจริง ถ้าข้อความยังว่าง\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"คืนค่าตำแหน่งที่พบข้อความแรกอยู่ในข้อความที่สอง คืนค่า 0 ถ้าหาไม่พบ\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"ในข้อความ\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"หาข้อความแรกที่พบ\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"หาข้อความสุดท้ายที่พบ\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"ในข้อความ\",\n    \"TEXT_CHARAT_FROM_START\": \"ดึง ตัวอักษรตัวที่\",\n    \"TEXT_CHARAT_FROM_END\": \"ดึง ตัวอักษรตัวที่ # จากท้าย\",\n    \"TEXT_CHARAT_FIRST\": \"ดึง ตัวอักษรตัวแรก\",\n    \"TEXT_CHARAT_LAST\": \"ดึง ตัวอักษรตัวสุดท้าย\",\n    \"TEXT_CHARAT_RANDOM\": \"ถึงตัวอักษรแบบสุ่ม\",\n    \"TEXT_CHARAT_TOOLTIP\": \"คืนค่าตัวอักษรจากตำแหน่งที่ระบุ\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"คืนค่าบางส่วนของข้อความ\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"ในข้อความ\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"แยกข้อความย่อยตั้งแต่ ตัวอักษรที่\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"แยกข้อความย่อยตั้งแต่ ตัวอักษรที่ # จากท้าย\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"แยกข้อความย่อยตั้งแต่ ตัวอักษรแรก\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"จนถึง ตัวอักษรที่\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"จนถึง ตัวอักษรที่ # จากท้าย\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"จนถึง ตัวอักษรสุดท้าย\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"คืนค่าสำเนาของข้อความในกรณีต่างๆ\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"เปลี่ยนเป็น ตัวพิมพ์ใหญ่\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"เปลี่ยนเป็น ตัวพิมพ์เล็ก\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"เปลี่ยนเป็น ตัวอักษรแรกเป็นตัวพิมพ์ใหญ่\",\n    \"TEXT_TRIM_TOOLTIP\": \"คืนค่าสำเนาของข้อความที่ลบเอาช่องว่างหน้าและหลังข้อความออกแล้ว\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"ลบช่องว่างทั้งสองข้างของ\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"ลบช่องว่างด้านหน้าของ\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"ลบช่องว่างข้างท้ายของ\",\n    \"TEXT_PRINT_TITLE\": \"พิมพ์ %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"พิมพ์ข้อความ ตัวเลข หรือค่าอื่นๆ\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"แสดงหน้าต่างข้อความ\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"แสดงหน้าต่างตัวเลข\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"แสดงหน้าต่างให้ผู้ใช้ใส่ตัวเลข\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"แสดงหน้าต่างให้ผู้ใช้ใส่ข้อความ\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"สร้างรายการเปล่า\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"สร้างรายการเปล่า (ความยาวเป็น 0) ยังไม่มีข้อมูลใดๆ อยู่\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"สร้างรายการพร้อมด้วยไอเท็ม\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"สร้างข้อความด้วย\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"รายการ\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"เพิ่ม ลบ หรือจัดเรียงบล็อกรายการนี้ใหม่\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"เพิ่มไอเท็มเข้าไปในรายการ\",\n    \"LISTS_REPEAT_TOOLTIP\": \"สร้างรายการที่ประกอบด้วยค่าตามที่ระบุในจำนวนตามที่ต้องการ\",\n    \"LISTS_REPEAT_TITLE\": \"สร้างรายการที่มีไอเท็ม %1 จำนวน %2\",\n    \"LISTS_LENGTH_TITLE\": \"ความยาวของ %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"ส่งคืนค่าความยาวของรายการ\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 ว่างเปล่า\",\n    \"LISTS_TOOLTIP\": \"คืนค่าเป็นจริง ถ้ารายการยังว่างเปล่า\",\n    \"LISTS_INLIST\": \"ในรายการ\",\n    \"LISTS_INDEX_OF_FIRST\": \"หาอันแรกที่พบ\",\n    \"LISTS_INDEX_OF_LAST\": \"หาอันสุดท้ายที่พบ\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"คืนค่าตำแหน่งของไอเท็มอันแรก/สุดท้ายที่พบในรายการ คืนค่า 0 ถ้าหาไม่พบ\",\n    \"LISTS_GET_INDEX_GET\": \"เรียกดู\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"เรียกดูและเอาออก\",\n    \"LISTS_GET_INDEX_REMOVE\": \"เอาออก\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# จากท้าย\",\n    \"LISTS_GET_INDEX_FIRST\": \"แรกสุด\",\n    \"LISTS_GET_INDEX_LAST\": \"ท้ายสุด\",\n    \"LISTS_GET_INDEX_RANDOM\": \"สุ่ม\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ #1 คือไอเท็มอันแรกสุด\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ #1 คือไอเท็มอันท้ายสุด\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"คืนค่าไอเท็มอันแรกในรายการ\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"คืนค่าไอเท็มอันสุดท้ายในรายการ\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"คืนค่าไอเท็มแบบสุ่มจากรายการ\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"เอาออก และคืนค่าไอเท็มในตำแหน่งที่ระบุจากรายการ #1 คือไอเท็มอันแรก\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"เอาออก และคืนค่าไอเท็มในตำแหน่งที่ระบุจากรายการ #1 คือไอเท็มอันสุดท้าย\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"เอาออก และคืนค่าไอเท็มอันแรกในรายการ\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"เอาออก และคืนค่าไอเท็มอันสุดท้ายในรายการ\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"เอาออก และคืนค่าไอเท็มแบบสุ่มจากรายการ\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ #1 คือไอเท็มอันแรกสุด\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ #1 คือไอเท็มอันท้ายสุด\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"เอาไอเท็มแรกสุดในรายการออก\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"เอาไอเท็มอันท้ายสุดในรายการออก\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"เอาไอเท็มแบบสุ่มจากรายการออก\",\n    \"LISTS_SET_INDEX_SET\": \"กำหนด\",\n    \"LISTS_SET_INDEX_INSERT\": \"แทรกที่\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"เป็น\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"กำหนดไอเท็มในตำแหน่งที่ระบุในรายการ #1 คือไอเท็มอันแรกสุด\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"กำหนดไอเท็มในตำแหน่งที่ระบุในรายการ #1 คือไอเท็มอันท้ายสุด\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"กำหนดไอเท็มอันแรกในรายการ\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"กำหนดไอเท็มอันสุดท้ายในรายการ\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"กำหนดไอเท็มแบบสุ่มในรายการ\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"แทรกไอเท็มเข้าไปในตำแหน่งที่กำหนด #1 คือไอเท็มอันแรก\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"แทรกไอเท็มเข้าไปในตำแหน่งที่กำหนด #1 คือไอเท็มอันสุดท้าย\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"แทรกไอเท็มเข้าไปเป็นอันแรกสุดของรายการ\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"เพิ่มไอเท็มเข้าไปท้ายสุดของรายการ\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"เพิ่มไอเท็มเข้าไปในรายการแบบสุ่ม\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"ดึงรายการย่อยจาก #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"ดึงรายการย่อยจาก # จากท้ายสุด\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"ดึงรายการย่อยทั้งแต่แรกสุด\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"จนถึง #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"ถึง #  จากท้ายสุด\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"ถึง ท้ายสุด\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"สร้างสำเนารายการในช่วงที่กำหนด\",\n    \"VARIABLES_GET_TOOLTIP\": \"คืนค่าของตัวแปรนี้\",\n    \"VARIABLES_GET_CREATE_SET\": \"สร้าง \\\"กำหนด %1\\\"\",\n    \"VARIABLES_SET_TITLE\": \"กำหนด\",\n    \"VARIABLES_SET_TAIL\": \"จนถึง\",\n    \"VARIABLES_SET_TOOLTIP\": \"กำหนดให้ตัวแปรนี้เท่ากับการป้อนข้อมูล\",\n    \"VARIABLES_SET_CREATE_GET\": \"สร้าง \\\"get %1\\\"\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"ถึง\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"ทำอะไรบางอย่าง\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"ด้วย:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"สร้างฟังก์ชันที่ไม่มีผลลัพธ์\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"คืนค่า\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"สร้างฟังก์ชันที่มีผลลัพธ์\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"ระวัง: ฟังก์ชันนี้มีพารามิเตอร์ที่มีชื่อซ้ำกัน\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_(computer_science)\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"เรียกใช้ฟังก์ชันที่สร้างโดยผู้ใช้ \\\"%1\\\"\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_(computer_science)\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"เรียกใช้ฟังก์ชันที่สร้างโดยผู้ใช้ \\\"%1\\\" และใช้ผลลัพธ์ของมัน\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"นำเข้า\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"ชื่อนำเข้า:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"เน้นฟังก์ชันนิยาม\",\n    \"PROCEDURES_CREATE_DO\": \"สร้าง \\\"%1\\\"\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"ถ้ามีค่าเป็นจริง ให้คืนค่าที่สอง\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"ระวัง: บล็อกนี้ใช้เฉพาะในการสร้างฟังก์ชันเท่านั้น\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/tl.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"item\",\n    \"DUPLICATE_BLOCK\": \"Kaparehas\",\n    \"ADD_COMMENT\": \"Dagdag komento\",\n    \"REMOVE_COMMENT\": \"Remove Comment\",\n    \"EXTERNAL_INPUTS\": \"Panlabas na Inputs\",\n    \"INLINE_INPUTS\": \"Inline na Inputs\",\n    \"DELETE_BLOCK\": \"burahin ang bloke\",\n    \"DELETE_X_BLOCKS\": \"burahin %1 ng bloke\",\n    \"COLLAPSE_BLOCK\": \"bloke\",\n    \"COLLAPSE_ALL\": \"bloke\",\n    \"EXPAND_BLOCK\": \"Palawakin ang Block\",\n    \"EXPAND_ALL\": \"Palawakin ang Blocks\",\n    \"DISABLE_BLOCK\": \"Ipangwalang bisa ang Block\",\n    \"ENABLE_BLOCK\": \"Bigyan ng bisa ang Block\",\n    \"HELP\": \"Tulong\",\n    \"CHANGE_VALUE_TITLE\": \"pagbago ng value:\",\n    \"NEW_VARIABLE\": \"New variable...\",\n    \"NEW_VARIABLE_TITLE\": \"New variable name:\",\n    \"RENAME_VARIABLE\": \"Rename variable...\",\n    \"RENAME_VARIABLE_TITLE\": \"Rename all '%1' variables to:\",\n    \"COLOUR_PICKER_HELPURL\": \"http://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"pagpili ng kulay sa paleta.\",\n    \"COLOUR_RANDOM_TITLE\": \"iba ibang kulay\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"pagpili ng iba't ibang kulay.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"kulayan ng\",\n    \"COLOUR_RGB_RED\": \"pula\",\n    \"COLOUR_RGB_GREEN\": \"berde\",\n    \"COLOUR_RGB_BLUE\": \"asul\",\n    \"COLOUR_RGB_TOOLTIP\": \"gumawa ng kulay ng may espisipikong dami ng kulay pula, berde, at asul. lahat ng halaga ay dapat sa pagitan ng 0 at 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"halo\",\n    \"COLOUR_BLEND_COLOUR1\": \"kulay 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"kulay 2\",\n    \"COLOUR_BLEND_RATIO\": \"proporsyon\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Paghalo ng dalawang kulay kasama ng ibinigay na proporsyon (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"http://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"ulitin %1 beses\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"ulitin\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"beses\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"gawin\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"gumawa ng ilang pangungusap ng ilang ulit.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"ulitin habang\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"ulitin hanggang\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Habang ang value ay true, gagawin ang ibang statements.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Habang ang value ay false, gagawin ang ibang statements.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Magkaroon ng mga variable na %1 na tanggalin ng mga halaga mula sa simulang numero hanggang sa dulong numero, at bilangin sa pamamagitan ng tinukoy na agwat, at gawin ang mga tinukoy na mga blocks.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"bilangin\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"mula %1 hanggang %2 ng %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"sa bawat bagay\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"sa listahan\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Para sa bawat item sa isang list, i-set ang variable ng '% 1' sa mga item, at pagkatapos ay gumawa ng ilang mga statements.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"putulin ang paulit ulit\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"Magpatuloy sa susunod na pag-ulit ng loop\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Hatiin ang nilalaman ng loop.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Laktawan ang natitirang bahagi ng loop, at magpatuloy sa susunod na pag-ulit.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Babala: Ang block ito ay maaari lamang magamit sa loob ng loop.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"kung ang value ay true,  gagawin ang do statements.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Kung ang value ay true, gagawin ang unang block ng do statements. Kung hindi, gagawin ang pangalawang block ng statement.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Kung ang unang value ay true, gagawin ang first block ng statement. Kung hindi, kung ang second value ay true, gagawin ang second block ng statement.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Kung ang first value ay true, gagawin ang first block ng statement. Kung hindi true ang second value, gagawin ang second block ng statement. Kung wala sa mga values ay true, gagawin ang last block ng statements.\",\n    \"CONTROLS_IF_MSG_IF\": \"kung\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"else if\",\n    \"CONTROLS_IF_MSG_ELSE\": \"else\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Mag Add, remove o kaya mag reorder ng sections para maayos ang if block.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Mag dagdag ng condition sa if block.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Mag Add ng final, kunin lahat ng condition sa if block.\",\n    \"LOGIC_COMPARE_HELPURL\": \"http://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Nag babalik ng true kung ang pinasok ay parehong magkatumbas.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Return true if both inputs are not equal to each other.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Nag babalik ng true kung ang unang pinasok ay maliit kaysa sa pangalawang pinasok.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Nag babalik ng true kung ang unang pinasok ay maliit sa o katumbas sa pangalawang pinasok.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Nagbabalik ng true kung ang unang pinasok ay mas malaki kaysa pangalawang pinasok.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Nag babalik ng true kung ang unang pinasok ay mas malaki or katumbas ng pangalawang pinasok.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Return true if both inputs are true.\",\n    \"LOGIC_OPERATION_AND\": \"at\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Return true if at least one of the inputs is true.\",\n    \"LOGIC_OPERATION_OR\": \"o\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"not %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Returns true if the input is false.  Returns false if the input is true.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"tama\",\n    \"LOGIC_BOOLEAN_FALSE\": \"mali\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Nag babalik ng true or false.\",\n    \"LOGIC_NULL_HELPURL\": \"http://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"blangko\",\n    \"LOGIC_NULL_TOOLTIP\": \"Returns null.\",\n    \"LOGIC_TERNARY_HELPURL\": \"http://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"kung tama\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"kung mali\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.\",\n    \"MATH_NUMBER_HELPURL\": \"http://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"A number.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"-\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"×\",\n    \"MATH_POWER_SYMBOL\": \"^\",\n    \"MATH_TRIG_SIN\": \"sin\",\n    \"MATH_TRIG_COS\": \"cos\",\n    \"MATH_TRIG_TAN\": \"tan\",\n    \"MATH_TRIG_ASIN\": \"asin\",\n    \"MATH_TRIG_ACOS\": \"acos\",\n    \"MATH_TRIG_ATAN\": \"atan\",\n    \"MATH_ARITHMETIC_HELPURL\": \"http://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Return the sum of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Return the difference of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Return the product of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Return the quotient of the two numbers.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Return the first number raised to the power of the second number.\",\n    \"MATH_SINGLE_HELPURL\": \"http://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"square root\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Return the square root of a number.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"absolute\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Return the absolute value of a number.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Return the negation of a number.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Return the natural logarithm of a number.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Return the base 10 logarithm of a number.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Return e to the power of a number.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Return 10 to the power of a number.\",\n    \"MATH_TRIG_HELPURL\": \"http://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Return the sine of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Return the cosine of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Return the tangent of a degree (not radian).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Return the arcsine of a number.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Return the arccosine of a number.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Return the arctangent of a number.\",\n    \"MATH_CONSTANT_HELPURL\": \"http://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).\",\n    \"MATH_IS_EVEN\": \"is even\",\n    \"MATH_IS_ODD\": \"is odd\",\n    \"MATH_IS_PRIME\": \"is prime\",\n    \"MATH_IS_WHOLE\": \"is whole\",\n    \"MATH_IS_POSITIVE\": \"ay positibo\",\n    \"MATH_IS_NEGATIVE\": \"ay negatibo\",\n    \"MATH_IS_DIVISIBLE_BY\": \"is divisible by\",\n    \"MATH_IS_TOOLTIP\": \"Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.\",\n    \"MATH_CHANGE_HELPURL\": \"http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"baguhin\",\n    \"MATH_CHANGE_INPUT_BY\": \"by\",\n    \"MATH_CHANGE_TOOLTIP\": \"Add a number to variable '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"http://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Round a number up or down.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"round\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"round up\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"round down\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"sum of list\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Return the sum of all the numbers in the list.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"min of list\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Return the smallest number in the list.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"max of list\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Return the largest number in the list.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"average of list\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Return the average (arithmetic mean) of the numeric values in the list.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"median of list\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Return the median number in the list.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"modes of list\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Return a list of the most common item(s) in the list.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"standard deviation of list\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Return the standard deviation of the list.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"random item of list\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Return a random element from the list.\",\n    \"MATH_MODULO_HELPURL\": \"http://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"remainder of %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Return the remainder from dividing the two numbers.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"http://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"constrain %1 low %2 high %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Constrain a number to be between the specified limits (inclusive).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"http://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"random integer from %1 to %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Return a random integer between the two specified limits, inclusive.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"http://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"random fraction\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).\",\n    \"TEXT_TEXT_HELPURL\": \"http://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"A letter, word, or line of text.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"create text with\",\n    \"TEXT_JOIN_TOOLTIP\": \"Create a piece of text by joining together any number of items.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"join\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Add, remove, or reorder sections to reconfigure this text block.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Add an item to the text.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"to\",\n    \"TEXT_APPEND_APPENDTEXT\": \"append text\",\n    \"TEXT_APPEND_TOOLTIP\": \"Append some text to variable '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"length of %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Returns the number of letters (including spaces) in the provided text.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 is empty\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Returns true if the provided text is empty.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"in text\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"find first occurrence of text\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"find last occurrence of text\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"in text\",\n    \"TEXT_CHARAT_FROM_START\": \"get letter #\",\n    \"TEXT_CHARAT_FROM_END\": \"get letter # from end\",\n    \"TEXT_CHARAT_FIRST\": \"get first letter\",\n    \"TEXT_CHARAT_LAST\": \"get last letter\",\n    \"TEXT_CHARAT_RANDOM\": \"get random letter\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Returns the letter at the specified position.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Returns a specified portion of the text.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"in text\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"get substring from letter #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"get substring from letter # from end\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"get substring from first letter\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"to letter #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"to letter # from end\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"to last letter\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Return a copy of the text in a different case.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"to UPPER CASE\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"to lower case\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"to Title Case\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Return a copy of the text with spaces removed from one or both ends.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"trim spaces from both sides\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"trim spaces from left side\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"trim spaces from right side\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"print %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Print the specified text, number or other value.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"prompt for text with message\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"prompt for number with message\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Prompt for user for a number.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Prompt for user for some text.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"http://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"Gumawa ng walang laman na list\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Ibabalik ang list, na may haba na 0, nag lalaman ng walang data records\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Gumawa ng list na may kahit anong number ng items.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"gumawa ng list kasama\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"list\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Magdagdag, mag tanggal or mag ayos ng sections para muling maayos ang listahan ng block.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Mag dagdag ng item sa list.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#paggawa_ng_list_kasama\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Pag gawa ng list na binubuo ng binigay na value at inulit na tinuloy na bilang ng beses.\",\n    \"LISTS_REPEAT_TITLE\": \"pag gawa ng list kasama ng item %1 inuulit %2 beses\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#haba_ng\",\n    \"LISTS_LENGTH_TITLE\": \"haba ng %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Pag balik ng haba ng list.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#ay_walang_laman\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 ay walang laman\",\n    \"LISTS_TOOLTIP\": \"Nagbabalik ng true kung ang list ay walang laman.\",\n    \"LISTS_INLIST\": \"sa list\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Pagkuha_ng_Items_mula_sa_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"Hanapin ang unang pangyayari ng item\",\n    \"LISTS_INDEX_OF_LAST\": \"hanapin ang huling pangyayari ng item\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Pagbalik ng index ng una/huli pangyayari ng item sa list. Pagbalik ng 0 kung ang item ay hindi makita.\",\n    \"LISTS_GET_INDEX_GET\": \"kunin\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"kunin at tanggalin\",\n    \"LISTS_GET_INDEX_REMOVE\": \"tanggalin\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# mula katapusan\",\n    \"LISTS_GET_INDEX_FIRST\": \"Una\",\n    \"LISTS_GET_INDEX_LAST\": \"huli\",\n    \"LISTS_GET_INDEX_RANDOM\": \"nang hindi pinipili\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Ibalik ang item sa itinakdang posisyon sa list. #1 ay ang unang item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Ibalik ang item sa tinakdang posisyon sa list. #1 ay ang huling item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Ibalik ang unang item sa list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Ibalik ang huling item sa list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Nag babalik ng hindi pinipiling item sa list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Nag tatanggal at nag babalik ng mga items sa tinukoy na posisyon sa list. #1 ang unang item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Nag tatanggal at nag babalik ng items sa tinukoy na posisyon sa list. #1 ay ang huling item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Nag tatanggal at nag babalik ng mga unang item sa list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Nag tatanggal at nag babalik ng huling item sa list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Nag tatanggal at nag babalik ng mga hindi pinipiling item sa list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Nag tatanggal ng item sa tinukoy na posisyon sa list. #1 ay ang unang item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Nag tatanggal ng item sa tinukoy na posisyon sa list. #1 ay ang huling item.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Nag tatanggal ng unang item sa list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Nag tatanggal ng huling item sa list.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Nag tatanggal ng item mula sa walang pinipiling list.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#sa_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"set\",\n    \"LISTS_SET_INDEX_INSERT\": \"isingit sa\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"gaya ng\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Pag set ng item sa tinukoy na position sa isang list. #1 ay ang unang item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Pag set ng item sa tinukoy na posisyon sa isang list. #1 ay ang huling item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Pag set ng unang item sa isang list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Pag set sa huling item sa isang list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Pag set ng walang pinipiling item sa isang list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Nag singit ng item sa tinukoy na posistion sa list. #1 ay ang unang item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Nag singit ng item sa tinukoy na posisyon sa list. #1 ay ang huling item.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Nag singit ng item sa simula ng list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Idagdag ang item sa huli ng isang list.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Isingit ang item ng walang pinipili sa isang list.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Pagkuha_ng_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"pag kuha ng sub-list mula #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"pag kuha ng sub-list mula sa # mula huli\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"pag kuha ng sub-list mula sa una\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"mula #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"mula # hanggang huli\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"hanggang huli\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Gumagawa ng kopya ng tinukoy na bahagi ng list.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TOOLTIP\": \"Returns the value of this variable.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Create 'set %1'\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"set\",\n    \"VARIABLES_SET_TAIL\": \"to\",\n    \"VARIABLES_SET_TOOLTIP\": \"Sets this variable to be equal to the input.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Create 'get %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"to\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"do something\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"with:\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Creates a function with no output.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"return\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Creates a function with an output.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Warning: This function has duplicate parameters.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Run the user-defined function '%1'.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"http://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Run the user-defined function '%1' and use its output.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"inputs\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"input name:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Highlight function definition\",\n    \"PROCEDURES_CREATE_DO\": \"Create '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"If a value is true, then return a second value.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Warning: This block may be used only within a function definition.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/tr.json",
    "content": "{\n    \"@metadata\": [],\n    \"VARIABLES_DEFAULT_NAME\": \"öge\",\n    \"DUPLICATE_BLOCK\": \"çoğalt\",\n    \"ADD_COMMENT\": \"Yorum Ekle\",\n    \"REMOVE_COMMENT\": \"Yorumları sil\",\n    \"EXTERNAL_INPUTS\": \"Harici Girişler\",\n    \"INLINE_INPUTS\": \"Satır içi girdi\",\n    \"DELETE_BLOCK\": \"Bloğu Sil\",\n    \"DELETE_X_BLOCKS\": \"%1 Bloğu Sil\",\n    \"COLLAPSE_BLOCK\": \"Blok'u Daralt\",\n    \"COLLAPSE_ALL\": \"Blokları Daralt\",\n    \"EXPAND_BLOCK\": \"Bloğu Genişlet\",\n    \"EXPAND_ALL\": \"Blokları Genişlet\",\n    \"DISABLE_BLOCK\": \"Bloğu Devre Dışı Bırak\",\n    \"ENABLE_BLOCK\": \"Bloğu Etkinleştir\",\n    \"HELP\": \"Yardım\",\n    \"CHANGE_VALUE_TITLE\": \"Değeri değiştir:\",\n    \"NEW_VARIABLE\": \"Yeni değişken...\",\n    \"NEW_VARIABLE_TITLE\": \"Yeni değişken ismi :\",\n    \"RENAME_VARIABLE\": \"Değişkeni yeniden adlandır...\",\n    \"RENAME_VARIABLE_TITLE\": \"Tüm '%1' değişkenlerini yeniden isimlendir:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Paletten bir renk seçin.\",\n    \"COLOUR_RANDOM_TITLE\": \"rastgele renk\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Rastgele bir renk seçin.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"renk değerleri\",\n    \"COLOUR_RGB_RED\": \"kırmızı\",\n    \"COLOUR_RGB_GREEN\": \"yeşil\",\n    \"COLOUR_RGB_BLUE\": \"mavi\",\n    \"COLOUR_RGB_TOOLTIP\": \"Kırmızı, yeşil ve mavinin belirtilen miktarıyla bir renk oluşturun.  Tüm değerler 0 ile 100 arasında olmalıdır.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"karıştır\",\n    \"COLOUR_BLEND_COLOUR1\": \"renk 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"renk 2\",\n    \"COLOUR_BLEND_RATIO\": \"oran\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Verilen bir orana bağlı olarak iki rengi karıştırır. (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop  Döngü\",\n    \"CONTROLS_REPEAT_TITLE\": \"%1 kez tekrarla\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"tekrarla\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"kez\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"yap\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Bazı işlemleri birkaç kez yap.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"tekrar ederken\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"kadar tekrarla\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Bir değer true ise, o zaman bazı ifadeleri yap.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Bir değer false ise, o zaman bazı ifadeleri yap.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"%1 değişkenini başlangıç numarasından bitiş numarasına kadar tanımlı farkla değerler verirken tanımlı blokları yap.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"ile sayılır\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"%1 den %2 ye, her adımda %3 değişim\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"her öğe için\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"listede\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Bir listedeki her öğe için  '%1' değişkenini maddeye atayın  ve bundan sonra bazı açıklamalar yapın.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"döngüden çık\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"döngünün sonraki adımından devam et\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"İçeren döngüden çık.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Bu döngünün geri kalanını atlayın ve sonraki adım ile devam edin.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Uyarı: Bu blok sadece bir döngü içinde kullanılabilir.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Eğer değişken true , yani gerçekleşmiş ise , ardından gelen işlemi yerine getir .\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Eğer değişken true, yani gerçekleşiyor ise ilk blok'taki işlemleri yerine getir, Aksi halde ikinci blok'taki işlemleri yerine getir.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Eğer ilk değişken true, yani koşul gerçekleşmiş ise ilk blok içerisindeki işlem(ler)i gerçekleştir. Eğer ikinci değişken true ise, ikinci bloktaki işlem(ler)i gerçekleştir .\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Eğer ilk değer true, yani olumlu ise, ilk blok'taki işlem(ler)i gerçekleştir. İlk değer true değil ama ikinci değer true ise, ikinci bloktaki işlem(ler)i gerçekleştir. Eğer değerlerin hiçbiri true değil ise son blok'taki işlem(ler)i gerçekleştir.\",\n    \"CONTROLS_IF_MSG_IF\": \"eğer\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"değilse eğer\",\n    \"CONTROLS_IF_MSG_ELSE\": \"değilse\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"If bloğuna ekle, kaldır veya yeniden düzenleme yap.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"If bloğuna bir koşul ekleyin.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"If bloğuna kalan durumları \\\"yakalayan\\\" bir son ekle.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)  eşitsizlik işlemi\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Girilen iki değer birbirine eşitse \\\"True\\\" değerini verir.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Girilen iki değerde birbirine eşit değilse \\\"True\\\" değerini verir.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Girilen ilk değer ikinci değerden küçükse \\\"True\\\" değerini verir.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Girilen ilk değer ikinci değerden küçük veya eşitse \\\"True\\\" değerini verir.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Girilen ilk değer ikinci değerden daha büyükse \\\"True\\\" değerini verir.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Girilen ilk değer ikinci değerden büyük veya eşitse \\\"True\\\" değerini verir.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Girilen iki değerde doğruysa \\\"True\\\" değerini verir.\",\n    \"LOGIC_OPERATION_AND\": \"ve\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Girilen iki değerden en az biri doğruysa \\\"True\\\" değerini verir.\",\n    \"LOGIC_OPERATION_OR\": \"veya\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"%1 değil\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Girilen değer yanlışsa \\\"True\\\" değerini verir.Girilen değer doğruysa \\\"False\\\" değerini verir.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False  olumlu_olumsuz\",\n    \"LOGIC_BOOLEAN_TRUE\": \"Olumlu\",\n    \"LOGIC_BOOLEAN_FALSE\": \"false = Olumsuz\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Ya 'True' yada 'False' değerini verir.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"sıfır\",\n    \"LOGIC_NULL_TOOLTIP\": \"sıfır verir.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"test\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"doğru ise\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"yanlış ise\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"'test'deki şartı test eder. Eğer şart doğru ise 'doğru' değeri döndürür, aksi halde 'yanlış' değeri döndürür.\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"Bir sayı.\",\n    \"MATH_ADDITION_SYMBOL\": \"+\",\n    \"MATH_SUBTRACTION_SYMBOL\": \"tire\",\n    \"MATH_DIVISION_SYMBOL\": \"÷\",\n    \"MATH_MULTIPLICATION_SYMBOL\": \"x\",\n    \"MATH_POWER_SYMBOL\": \"üst alma\",\n    \"MATH_TRIG_SIN\": \"Sinüs\",\n    \"MATH_TRIG_COS\": \"kosünüs\",\n    \"MATH_TRIG_TAN\": \"tanjant\",\n    \"MATH_TRIG_ASIN\": \"asinüs\",\n    \"MATH_TRIG_ACOS\": \"akosünüs\",\n    \"MATH_TRIG_ATAN\": \"atanjant\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://tr.wikipedia.org/wiki/Aritmetik\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"İki rakamın toplamını döndür.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"İki sayını farkını döndür.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"İki sayının çarpımını döndür.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"İki sayının bölümünü döndür.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"İlk sayinin ikincinin kuvvetine yükseltilmişini döndür.\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root  Kare kök\",\n    \"MATH_SINGLE_OP_ROOT\": \"Kare kök\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Bir sayının karekökü nü döndür .\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"Kesin\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Bir sayının tam değerini döndür .\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Bir sayıyı geçersiz olarak döndür .\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Bir sayının doğal logaritmasını döndür .\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Bir sayının 10  temelinde logaritmasını döndür .\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Bir sayının e ' inci  kuvvetini döndür .\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Bir sayının 10. kuvvetini döndür .\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions  Trigonometrik fonksiyonlar\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Bir açının sinüsünü döndür(radyan olarak değil).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Bir açının kosinüsünü döndür(radyan olarak değil).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Bir açının tanjantını döndür(radyan olarak değil).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Bir sayının ters sinüsünü döndür .\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Bir sayının ters kosunusunu döndür .\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Bir sayının ters tanjantını döndür .\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Yaygın sabitlerden birini döndür:π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (sonsuz).\",\n    \"MATH_IS_EVEN\": \"çift\",\n    \"MATH_IS_ODD\": \"tek\",\n    \"MATH_IS_PRIME\": \"asal\",\n    \"MATH_IS_WHOLE\": \"Bütün olduğunu\",\n    \"MATH_IS_POSITIVE\": \"pozitif\",\n    \"MATH_IS_NEGATIVE\": \"negatif\",\n    \"MATH_IS_DIVISIBLE_BY\": \"bölünebilir\",\n    \"MATH_IS_TOOLTIP\": \"Bir sayinin çift mi tek mi , tam mı, asal mı , pozitif mi, negatif mi, veya tam bir  sayıyla bölünebilirliğini kontrol et.'True' veya 'False' değerini döndür.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"Değiştirmek\",\n    \"MATH_CHANGE_INPUT_BY\": \"ile\",\n    \"MATH_CHANGE_TOOLTIP\": \"'%1' değişkenine bir sayı ekle.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding  Yuvarlama\",\n    \"MATH_ROUND_TOOLTIP\": \"Bir sayı yı yukarı yada aşağı yuvarla .\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"Yuvarla\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"yukarı yuvarla\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"aşağı yuvarla\",\n    \"MATH_ONLIST_HELPURL\": \"\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"Listenin toplamı\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Listede ki tüm sayıların toplamını döndür.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"Listenin en küçüğü\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Listenin en küçüğünü döndür.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"en büyük sayı\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Listenin en büyüğünü döndür.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"listenin ortalaması\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Listedeki sayısal değerlerin ortalamasını (aritmetik anlamda) döndür.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"Listenin medyanı\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Listenin medyanını döndür.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"Listenin modları\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Listede ki en yaygın öğe veya öğelerinin listesini döndür.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"Listenin standart sapması\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Listenin standart sapmasını döndür.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"Listenin rastgele öğesi\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Listeden rastgele bir element döndür.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"%1 ÷ %2 nin kalanı\",\n    \"MATH_MODULO_TOOLTIP\": \"İki sayının bölümünden kalanı döndür.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"%1 i en düşük %2 en yüksek %3 ile sınırla\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Bir sayıyı belirli iki sayı arasında sınırlandır(dahil).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation  Rast gele sayı üretme\",\n    \"MATH_RANDOM_INT_TITLE\": \"%1 ile %2 arasında rastgele tam sayı üret\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Herhangi iki sayı arasında , sayılar dahil olmak üzere , rastgele bir tam sayı döndür.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation  Rastgele sayı yaratma\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"Rast gele kesirli sayı , yada parça\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"0.0(dahil) ve 1.0 (hariç) sayıları arasında bir sayı döndür .\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Metnin bir harfi,kelimesi veya satırı.\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"ile metin oluştur\",\n    \"TEXT_JOIN_TOOLTIP\": \"Herhangi bir sayıda ki öğeleri bir araya getirerek metnin bir parçasını oluştur.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"Katıl\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Bu metin bloğunu düzenlemek için bölüm ekle,sil veya yeniden görevlendir.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Metine bir öğe ekle.\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"e\",\n    \"TEXT_APPEND_APPENDTEXT\": \"Metin Ekle\",\n    \"TEXT_APPEND_TOOLTIP\": \"Değişken '%1' e bazı metinler ekleyin.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification   Yazı değişimi\",\n    \"TEXT_LENGTH_TITLE\": \"%1 in uzunluğu\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Yazı içerisinde verilen harflerin ( harf arasındaki boşluklar dahil) sayısını verir .\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 boş\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Verilen metin boşsa true(doğru) değerini verir.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"İlk metnin ikinci metnin içindeki ilk ve son varoluşlarının indeksini döndürür.Metin bulunamadıysa 0 döndürür.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"metinde\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"Metnin ilk varolduğu yeri bul\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"Metnin son varolduğu yeri bul\",\n    \"TEXT_INDEXOF_TAIL\": \"\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"metinde\",\n    \"TEXT_CHARAT_FROM_START\": \"# harfini al\",\n    \"TEXT_CHARAT_FROM_END\": \"# dan sona harfleri al\",\n    \"TEXT_CHARAT_FIRST\": \"İlk harfini al\",\n    \"TEXT_CHARAT_LAST\": \"son harfi al\",\n    \"TEXT_CHARAT_RANDOM\": \"Rastgele bir harf al\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Belirli pozisyonda ki bir harfi döndürür.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Metinin belirli bir kısmını döndürür.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"metinde\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"n inci harften alt-string alma\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"n inci harften sona kadar alt-string alma\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"ilk harften başlayarak alt-string alma\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"# harfe\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"Sondan # harfe\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"son harfe\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Metnin bir kopyasını farklı bir harf durumunda (HEPSİ BÜYÜK - hepsi küçük) getirir.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"büyük harf\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"küçük harf\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"Baş Harfler Büyük\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"Metnin bir veya her iki sondan da boşlukları silinmiş şekilde kopyasını verir.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"İki tarafdan da boşlukları düzenle\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"Soldan boşlukları düzenle\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"Sağdan boşlukları düzenle\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text  Yazıyı yazdırmak\",\n    \"TEXT_PRINT_TITLE\": \"%1 ' i Yaz\",\n    \"TEXT_PRINT_TOOLTIP\": \"Belirli bir metni,sayıyı veya başka bir değeri yaz.\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user  Kullanıcıdan veri almak\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"Kullanıcıdan yazım al , istek mesajıyla\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"Kullanıcıdan sayı al , istek mesajı göstererek\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Kullanıcıdan sayı al .\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Kullanıcıdan Yazım al .\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists Boş Listeler\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"Boş liste oluştur\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Veri kaydı içermeyen uzunluğu 0 olan bir listeyi verir\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Herhangi sayıda nesne içeren bir liste oluştur.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"İle liste oluşturma\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"liste\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Bu liste bloğunu yeniden yapılandırmak için bölüm ekle,kaldır veya yeniden çağır.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Listeye bir nesne ekle.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with  İle liste yaratma\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Verilen bir değerin , belirli bir sayıda tekrarlanmasından oluşan bir liste yaratır .\",\n    \"LISTS_REPEAT_TITLE\": \"%1 nesnenin %2 kez tekrarlandığı bir liste yarat\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of  Uzunluk Listeleri\",\n    \"LISTS_LENGTH_TITLE\": \"%1'in uzunluğu\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Bir listenin uzunluğunu verir.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty Boş Listeler\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 boş\",\n    \"LISTS_TOOLTIP\": \"Eğer liste boş ise true döndürür .\",\n    \"LISTS_INLIST\": \"Listede\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List  Bir listeden öğe almak\",\n    \"LISTS_INDEX_OF_FIRST\": \"Öğenin ilk varolduğu yeri bul\",\n    \"LISTS_INDEX_OF_LAST\": \"Öğenin son varolduğu yeri bul\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Öğenin  listede ,  ilk ve son görüldüğü dizinleri döndürür . Öğe bulunmassa , 0 döndürür .\",\n    \"LISTS_GET_INDEX_GET\": \"Al\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"al ve kaldır\",\n    \"LISTS_GET_INDEX_REMOVE\": \"kaldır\",\n    \"LISTS_GET_INDEX_FROM_START\": \"# Kare\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# sonundan\",\n    \"LISTS_GET_INDEX_FIRST\": \"ilk\",\n    \"LISTS_GET_INDEX_LAST\": \"son\",\n    \"LISTS_GET_INDEX_RANDOM\": \"rastgele\",\n    \"LISTS_GET_INDEX_TAIL\": \"\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Listede belirli pozisyondaki bir öğeyi verir.#1 ilk öğedir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Listede belirli pozisyondaki bir öğeyi verir.#1 son öğedir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Listedeki ilk öğeyi verir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Listedeki son öğeyi verir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Listedeki rastgele bir öğeyi verir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Kaldırır ve listede belirtilen konumdaki bir öğeyi döndürür.  #1 son öğedir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Kaldırır ve listede belirtilen konumdaki bir ögeyi döndürür.  #1 son ögedir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Kaldırır ve listedeki ilk öğeyi döndürür.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Kaldırır ve listedeki son öğeyi döndürür.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Kaldırır ve listedeki rastgele bir öğeyi verir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Bir liste içerisinde , tanımlanan pozisyonda ki öğeyi kaldırır.#1 ilk öğedir.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Liste içerisinde , tanımlanan pozisyondaki bir öğeyi kaldırır . #1 son öğe dir .\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Listedeki ilk nesneyi kaldırır.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Listedeki son nesneyi kaldırır.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Listedeki rastgele bir nesneyi kaldırır.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set   Listeler#Liste içi ...gurubu\",\n    \"LISTS_SET_INDEX_SET\": \"yerleştir\",\n    \"LISTS_SET_INDEX_INSERT\": \"e yerleştir\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"olarak\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Bir öğeyi belirtilen yere göre listeye yerleştirir . #1 ilk öğedir .\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Bir öğeyi belirtilen yere göre listeye yerleştirir . #1 son öğedir .\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Bir listenin ilk öğesini yerleştirir .\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Bir listedeki son öğeyi yerleştirir .\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Listeye rast gele bir öğe yerleştirir .\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Bir öğeyi belirtilen pozisyona göre listeye yerleştirir . #1 ilk öğedir .\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Bir öğeyi , belirtilen yer pozisyonuna göre , listeye yerleştirir . #1 son öğedir .\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Nesneyi listenin başlangıcına ekler.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Öğeyi listenin sonuna ekle .\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Bir öğeyi listeye rast gele ekler .\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist alt liste\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"# dan alt liste al\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"# işaretinden sonra gelen ifadeye göre  alt liste al , # sondan\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"ilk öğeden alt liste al\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"#'a\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"Sondan #'a kadar\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"Sona kadar\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Listenin belirli bir kısmının kopyasını yaratır.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"Bu değişkenin değerini verir.\",\n    \"VARIABLES_GET_CREATE_SET\": \"'set %1' oluştur\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"Atamak\",\n    \"VARIABLES_SET_TAIL\": \"e\",\n    \"VARIABLES_SET_TOOLTIP\": \"Bu değişkeni girilen değere eşitler.\",\n    \"VARIABLES_SET_CREATE_GET\": \"'get %1' oluştur\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"e\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"birşey yap\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"ile :\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Çıktı vermeyen bir fonksiyon yaratır .\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"Geri dön\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Çıktı veren bir fonksiyon oluşturur.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Uyarı: Bu fonksiyon yinelenen parametreler vardır.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29  prosedür_%28bilgisayar_bilimi%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Kullanıcı tanımlı fonksiyonu çalıştır '%1' .\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Kullanıcı tanımlı fonksiyonu çalıştır '%1' ve çıktısını kullan .\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"girdiler\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"girdi adı:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Fonksiyon tanımı vurgulamak\",\n    \"PROCEDURES_CREATE_DO\": \"'%1' oluştur\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Eğer değer doğruysa, ikinci değere geri dön.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Uyarı: Bu blok yalnızca bir fonksiyon tanımı içinde kullanılır.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/uk.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Andriykopanytsia\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"елемент\",\n    \"DUPLICATE_BLOCK\": \"Дублікат\",\n    \"ADD_COMMENT\": \"Додати коментар\",\n    \"REMOVE_COMMENT\": \"Видалити коментар\",\n    \"EXTERNAL_INPUTS\": \"Зовнішні входи\",\n    \"INLINE_INPUTS\": \"Вбудовані входи\",\n    \"DELETE_BLOCK\": \"Видалити блок\",\n    \"DELETE_X_BLOCKS\": \"Видалити %1 блоків\",\n    \"COLLAPSE_BLOCK\": \"Згорнути блок\",\n    \"COLLAPSE_ALL\": \"Згорнути блоки\",\n    \"EXPAND_BLOCK\": \"Розгорнути блок\",\n    \"EXPAND_ALL\": \"Розгорнути блоки\",\n    \"DISABLE_BLOCK\": \"Вимкнути блок\",\n    \"ENABLE_BLOCK\": \"Увімкнути блок\",\n    \"HELP\": \"Довідка\",\n    \"CHANGE_VALUE_TITLE\": \"Змінити значення:\",\n    \"NEW_VARIABLE\": \"Нова змінна...\",\n    \"NEW_VARIABLE_TITLE\": \"Нове ім'я змінної:\",\n    \"RENAME_VARIABLE\": \"Перейменувати змінну...\",\n    \"RENAME_VARIABLE_TITLE\": \"Перейменувати усі змінні \\\"%1\\\" до:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://uk.wikipedia.org/wiki/Колір\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Вибрати колір з палітри.\",\n    \"COLOUR_RANDOM_TITLE\": \"випадковий колір\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"Вибрати колір навмання.\",\n    \"COLOUR_RGB_HELPURL\": \"http://www.december.com/html/spec/colorper.html\",\n    \"COLOUR_RGB_TITLE\": \"колір з\",\n    \"COLOUR_RGB_RED\": \"червоний\",\n    \"COLOUR_RGB_GREEN\": \"зелений\",\n    \"COLOUR_RGB_BLUE\": \"синій\",\n    \"COLOUR_RGB_TOOLTIP\": \"Створити колір з указаного червоного, зеленого та синього.  Усі значення мають бути від 0 до 100.\",\n    \"COLOUR_BLEND_HELPURL\": \"http://meyerweb.com/eric/tools/color-blend/\",\n    \"COLOUR_BLEND_TITLE\": \"суміш\",\n    \"COLOUR_BLEND_COLOUR1\": \"колір 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"колір 2\",\n    \"COLOUR_BLEND_RATIO\": \"співвідношення\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Змішує дві барви разом з даним співвідношенням (0.0 - 1.0).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"http://en.Wikipedia.org/Wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"повторити %1 разів\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"повторити\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"разів\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"зробити\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Зробити деякі заяви кілька разів.\",\n    \"CONTROLS_WHILEUNTIL_HELPURL\": \"http://code.google.com/p/blockly/wiki/Repeat\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"повторювати поки\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"повторювати доки\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Поки значення true, зробити деякі заяви.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Поки значення false, зробити деякі заяви.\",\n    \"CONTROLS_FOR_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#count_with\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Наявна змінна %1 приймає значення від початкового значення до кінцевого значення, враховуючи заданий інтервал, і зробіть вказані блоки.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"рахувати з\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"від %1 до %2 через %3\",\n    \"CONTROLS_FOREACH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#for_each for each block\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"для кожного елемента\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"у списку\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"блок тексту\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Для кожного елемента в списку задайте змінну '%1' для елемента, а потім зробіть деякі заяви.\",\n    \"CONTROLS_FLOW_STATEMENTS_HELPURL\": \"https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"перервати цикл\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"продовжити з наступної ітерації циклу\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Вирватися з циклічних оточень.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Пропустити залишок цього циклу і перейти до виконання наступної ітерації.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Попередження: цей блок може бути використаний тільки в межах циклу.\",\n    \"CONTROLS_IF_HELPURL\": \"http://code.google.com/p/blockly/wiki/If_Then\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Якщо значення true, зробити деякі заяви.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Якщо значення істина, то виконується перший блок операторів. В іншому випадку виконується другий блок операторів.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Якщо перше значення істина, то виконується перший блок операторів. В іншому випадку, якщо друге значення істина, то виконується другий блок операторів.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Якщо перше значення істина, то виконується перший блок операторів. В іншому випадку, якщо друге значення істина, то виконується другий блок операторів. Якщо жодне із значень не є істинним, то виконується останній блок операторів.\",\n    \"CONTROLS_IF_MSG_IF\": \"якщо\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"Інакше якщо\",\n    \"CONTROLS_IF_MSG_ELSE\": \"інакше\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Додати, видалити або змінити порядок розділів переналаштувати це, якщо блокується.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Додати умову до якщо блокувати.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Додати остаточну, всеосяжну умова до блоку якщо.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://uk.wikipedia.org/wiki/Нерівність\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Повертає true, якщо обидва входи рівні один одному.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Повертає true, якщо обидва входи не дорівнюють один одному.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Повертає true, якщо перше вхідне значення менше, ніж другий вхід.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Повертає true, якщо перше вхідне значення менше або дорівнює другому входу.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Повертає true, якщо перше вхідне значення більше, ніж другий вхід.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Повертає true, якщо перше вхідне значення більше або дорівнює другому входу.\",\n    \"LOGIC_OPERATION_HELPURL\": \"http://code.google.com/p/blockly/wiki/And_Or\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Повертає true, якщо обидва входи істинні.\",\n    \"LOGIC_OPERATION_AND\": \"та\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Повертає true, якщо принаймні один з входів  true.\",\n    \"LOGIC_OPERATION_OR\": \"або\",\n    \"LOGIC_NEGATE_HELPURL\": \"http://code.google.com/p/blockly/wiki/Not\",\n    \"LOGIC_NEGATE_TITLE\": \"не %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Повертає істина, якщо вхідне значення хибність. Повертає хибність, якщо вхідна значення істина.\",\n    \"LOGIC_BOOLEAN_HELPURL\": \"http://code.google.com/p/blockly/wiki/True_False\",\n    \"LOGIC_BOOLEAN_TRUE\": \"істина\",\n    \"LOGIC_BOOLEAN_FALSE\": \"хибність\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Повертає значення ІСТИНА або ХИБНІСТЬ.\",\n    \"LOGIC_NULL_HELPURL\": \"https://en.wikipedia.org/wiki/Nullable_type\",\n    \"LOGIC_NULL\": \"нічого\",\n    \"LOGIC_NULL_TOOLTIP\": \"Повертає null.\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://en.wikipedia.org/wiki/%3F:\",\n    \"LOGIC_TERNARY_CONDITION\": \"тест\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"якщо істина\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"Якщо хибність\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Перевірте умову в 'test'. Якщо умова істинна, то повертає  значення типу 'якщо істина'; в іншому випадку повертає значення 'якщо хибність'.\",\n    \"MATH_NUMBER_HELPURL\": \"https://uk.wikipedia.org/wiki/Число\",\n    \"MATH_NUMBER_TOOLTIP\": \"Число.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://uk.wikipedia.org/wiki/Арифметика\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Повертає суму двох чисел.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Повертає різницю двох чисел.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Повертає добуток двох чисел.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Повертає частку двох чисел.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Повертає перше число, піднесене до степеня другого числа.\",\n    \"MATH_SINGLE_HELPURL\": \"https://uk.wikipedia.org/wiki/Квадратний_корінь\",\n    \"MATH_SINGLE_OP_ROOT\": \"квадратний корінь\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Повертає квадратний корінь числа.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"модуль\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Повертає модуль числа.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Повертає протилежне число.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Повертає натуральний логарифм числа.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Повертає десятковий логарифм числа.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Повертає e у степені.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Повертає 10 у степені.\",\n    \"MATH_TRIG_HELPURL\": \"https://uk.wikipedia.org/wiki/Тригонометричні_функції\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Повертає синус кута у градусах (не у радіанах).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Повертає косинус кута у градусах (не у радіанах).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Повертає тангенс кута у градусах (не у радіанах).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Повертає арксинус числа.\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Повертає арккосинус числа.\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Повертає арктангенс числа.\",\n    \"MATH_CONSTANT_HELPURL\": \"https://uk.wikipedia.org/wiki/Математична_константа\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Повертає одну з поширених констант: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) або ∞ (безмежність).\",\n    \"MATH_IS_EVEN\": \"парне\",\n    \"MATH_IS_ODD\": \"непарне\",\n    \"MATH_IS_PRIME\": \"просте\",\n    \"MATH_IS_WHOLE\": \"ціле\",\n    \"MATH_IS_POSITIVE\": \"додатне\",\n    \"MATH_IS_NEGATIVE\": \"від'ємне\",\n    \"MATH_IS_DIVISIBLE_BY\": \"ділиться на\",\n    \"MATH_IS_TOOLTIP\": \"Перевіряє, чи число парне, непарне, просте, ціле, додатне, від'ємне або чи воно ділиться на певне число без остачі. Повертає істина або хибність.\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"змінити\",\n    \"MATH_CHANGE_INPUT_BY\": \"від\",\n    \"MATH_CHANGE_TOOLTIP\": \"Додати число змінній '%1'.\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Округлення числа у більшу або меншу сторону.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"округлити\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"округлити у більшу сторону\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"округлити у меншу сторону\",\n    \"MATH_ONLIST_HELPURL\": \"http://www.mapleprimes.com/questions/100441-Applying-Function-To-List-Of-Numbers\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"сума списку\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Повертає суму всіх чисел у списку.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"мінімум списку\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Повертає найменше число у списку.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"максимум списку\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Повертає найбільше число у списку.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"середнє списку\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Повертає середнє (арифметичне) числових значень у списку.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"медіана списку\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Повертає медіану списку.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"моди списку\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Повертає перелік найпоширеніших елементів у списку.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"стандартне відхилення списку\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Повертає стандартне відхилення списку.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"випадковий елемент списку\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Повертає випадковий елемент зі списку.\",\n    \"MATH_MODULO_HELPURL\": \"https://uk.wikipedia.org/wiki/Ділення_з_остачею\",\n    \"MATH_MODULO_TITLE\": \"остача від %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Повертає остачу від ділення двох чисел.\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"обмежити %1 від %2 до %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Обмежує число вказаними межами (включно).\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://uk.wikipedia.org/wiki/Генерація_випадкових_чисел\",\n    \"MATH_RANDOM_INT_TITLE\": \"випадкове ціле число від %1 до %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Повертає випадкове ціле число між двома заданими межами включно.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://uk.wikipedia.org/wiki/Генерація_випадкових_чисел\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"випадковий дріб\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Повертає випадковий дріб від 0,0 (включно) та 1.0 (не включно).\",\n    \"TEXT_TEXT_HELPURL\": \"https://uk.wikipedia.org/wiki/Рядок_(програмування)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Символ, слово або рядок тексту.\",\n    \"TEXT_JOIN_HELPURL\": \"http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_8.html\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"створити текст з\",\n    \"TEXT_JOIN_TOOLTIP\": \"Створити фрагмент тексту шляхом приєднання будь-якого числа елементів.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"приєднати\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Додати, видалити або змінити порядок розділів для переналаштування блокування тексту.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"Додати елемент до тексту.\",\n    \"TEXT_APPEND_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_APPEND_TO\": \"до\",\n    \"TEXT_APPEND_APPENDTEXT\": \"додати текст\",\n    \"TEXT_APPEND_TOOLTIP\": \"Додати який-небудь текст змінній '%1'.\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"довжина %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Повертає число символів (включаючи пробіли) у даному тексті.\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 є порожнім\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Повертає true, якщо вказаний текст порожній.\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Повертає індекс першого/останнього входження першого тексту у другому. Повертає 0, якщо текст не знайдений.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"у тексті\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"знайти перше входження тексту\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"знайти останнє входження тексту\",\n    \"TEXT_INDEXOF_TAIL\": \".\",\n    \"TEXT_CHARAT_HELPURL\": \"http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"у тексті\",\n    \"TEXT_CHARAT_FROM_START\": \"отримати символ\",\n    \"TEXT_CHARAT_FROM_END\": \"отримати символ # з кінця\",\n    \"TEXT_CHARAT_FIRST\": \"отримати перший символ\",\n    \"TEXT_CHARAT_LAST\": \"отримати останній символ\",\n    \"TEXT_CHARAT_RANDOM\": \"отримати випадковий символ\",\n    \"TEXT_CHARAT_TAIL\": \"-ий.\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Повертає символ у зазначеній позиції.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Повертає заданий фрагмент тексту.\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"у тексті\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"отримати підрядок від символу\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"отримати підрядок від символу # з кінця\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"отримати підрядок від першого символу\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"до символу #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"до символу з кінця\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"до останнього символу\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"-ого.\",\n    \"TEXT_CHANGECASE_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Повернути копію тексту в іншому випадку.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"до ВЕРХНЬОГО регістру\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"до нижнього регістру\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"Великі Перші Букви\",\n    \"TEXT_TRIM_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_TRIM_TOOLTIP\": \"Повертає копію тексту з пробілами вилученими від одного або обох кінців.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"викидати крайні пробіли з обох сторін\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"вилучати пробіли з лівого боку\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"вилучати пробіли з правого боку\",\n    \"TEXT_PRINT_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode91.html\",\n    \"TEXT_PRINT_TITLE\": \"друк %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"Надрукувати заданий текст, числа або інші символи.\",\n    \"TEXT_PROMPT_HELPURL\": \"http://www.liv.ac.uk/HPC/HTMLF90Course/HTMLF90CourseNotesnode92.html\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"запит на текст з повідомлення\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"запит на число з повідомлення\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Запитувати у користувача число.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Запитувати у користувача деякий текст.\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://uk.wikipedia.org/wiki/Зв%27язаний_список\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"створити порожній список\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Повертає список, довжиною 0, що не містить записів даних\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Створює список з будь-якою кількістю елементів.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"створює список з\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"список\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Додати, видалити або змінити порядок розділів для переналаштування блокування списку.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Додати елемент до списку.\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Створює список, що складається з заданого значення повтореного певну кількість разів.\",\n    \"LISTS_REPEAT_TITLE\": \"створити список з елемента %1 повтореного %2 разів\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"довжина %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Повертає довжину списку.\",\n    \"LISTS_IS_EMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#is_empty\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 є порожнім\",\n    \"LISTS_TOOLTIP\": \"Повертає істина, якщо список порожній.\",\n    \"LISTS_INLIST\": \"у списку\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"знайти перше входження елемента\",\n    \"LISTS_INDEX_OF_LAST\": \"знайти останнє входження елемента\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Повертає індекс першого/останнього входження першого елементу у списку. Повертає 0, якщо текст не знайдений.\",\n    \"LISTS_GET_INDEX_GET\": \"отримати\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"отримати і видалити\",\n    \"LISTS_GET_INDEX_REMOVE\": \"вилучити\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"# з кінця\",\n    \"LISTS_GET_INDEX_FIRST\": \"перший\",\n    \"LISTS_GET_INDEX_LAST\": \"останній\",\n    \"LISTS_GET_INDEX_RANDOM\": \"випадковий\",\n    \"LISTS_GET_INDEX_TAIL\": \"-ий.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Повертає елемент у заданій позицію у списку. #1 - це перший пункт.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Повертає елемент у заданій позиції у списку. #1 - це останній пункт.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Повертає перший елемент у списку.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Повертає останній елемент списку.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Повертає випадковий елемент у списку.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Видаляє і повертає елемент у заданій позиції у списку. #1 - це перший пункт.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Видаляє і повертає елемент у заданій позиції у списку. #1 - це останній пункт.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Видаляє і повертає перший елемент у списку.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Видаляє і повертає останній елемент списку.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Видаляє і повертає випадковий елемент у список.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Вилучає елемент у вказаній позиції списку. #1 - це перший пункт.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Вилучає елемент у вказаній позиції списку. #1 - це останній пункт.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Видаляє перший елемент у списку.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Видаляє останній елемент списку.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Видаляє випадковий елемент у списку.\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"встановити\",\n    \"LISTS_SET_INDEX_INSERT\": \"вставити в\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"як\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Задає елемент у вказаній позиції списку. #1 - це перший пункт.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Задає елемент у вказаній позиції списку. #1 - це останній пункт.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Задає перший елемент у списку.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Задає останній елемент списку.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Задає випадковий елемент у списку.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Вставка елемента у вказану позицію списку.  #1 є першим пунктом.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Вставляє елемент у вказану позицію списку. #1 - це останній пункт.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Вставляє елемент на початок списку.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Додає елемент до кінця списку.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Випадковим чином вставляє елемент у списку.\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"отримати вкладений список з #\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"отримати вкладений список від # з кінця\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"отримати вкладений список з першого\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"до #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"до # з кінця\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"до останнього\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"символу.\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Створює копію вказаної частини списку.\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"-ий.\",\n    \"VARIABLES_GET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Get\",\n    \"VARIABLES_GET_TITLE\": \"значення\",\n    \"VARIABLES_GET_TAIL\": \"значення\",\n    \"VARIABLES_GET_TOOLTIP\": \"Повертає значення цієї змінної.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Створити 'set %1'\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"встановити\",\n    \"VARIABLES_SET_TAIL\": \"до\",\n    \"VARIABLES_SET_TOOLTIP\": \"Задає цю змінну рівною вводу.\",\n    \"VARIABLES_SET_CREATE_GET\": \"Створити 'get %1'\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://uk.wikipedia.org/wiki/Підпрограма\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"до\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"щось зробити\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"з:\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"блок тексту\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Створює функцію без виводу.\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://uk.wikipedia.org/wiki/Підпрограма\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"повернути\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Створює функцію з виводу.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Увага: ця функція має дубльовані параметри.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"блок тексту\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Запустити користувацьку функцію \\\"%1\\\".\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://uk.wikipedia.org/wiki/Підпрограма\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Запустити користувацьку функцію \\\"%1\\\" і використовувати її вивід.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"вхід\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"ім'я входу:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Визначення функції підсвітки\",\n    \"PROCEDURES_CREATE_DO\": \"Створити \\\"%1\\\"\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Якщо значення true, то повернути друге значення.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Попередження: Цей блок може використовуватися лише в межах визначення функції.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/vi.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Baonguyen21022003\",\n            \"Espertus\",\n            \"Qneutron\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"vật\",\n    \"DUPLICATE_BLOCK\": \"Tạo Bản Sao\",\n    \"ADD_COMMENT\": \"Thêm Chú Giải\",\n    \"REMOVE_COMMENT\": \"Xóa Chú Giải\",\n    \"EXTERNAL_INPUTS\": \"Chỗ Gắn Bên Ngoài\",\n    \"INLINE_INPUTS\": \"Chỗ Gắn Cùng Dòng\",\n    \"DELETE_BLOCK\": \"Xóa Mảnh Này\",\n    \"DELETE_X_BLOCKS\": \"Xóa %1 Mảnh\",\n    \"COLLAPSE_BLOCK\": \"Thu Nhỏ Mảnh\",\n    \"COLLAPSE_ALL\": \"Thu Nhỏ Mọi Mảnh\",\n    \"EXPAND_BLOCK\": \"Mở Lớn Mảnh\",\n    \"EXPAND_ALL\": \"Mở Lớn Mọi Mảnh\",\n    \"DISABLE_BLOCK\": \"Ngưng Tác Dụng\",\n    \"ENABLE_BLOCK\": \"Phục Hồi Tác Dụng\",\n    \"HELP\": \"Trợ Giúp\",\n    \"CHANGE_VALUE_TITLE\": \"Thay giá trị thành:\",\n    \"NEW_VARIABLE\": \"Biến mới...\",\n    \"NEW_VARIABLE_TITLE\": \"Tên của biến mới:\",\n    \"RENAME_VARIABLE\": \"Thay tên biến...\",\n    \"RENAME_VARIABLE_TITLE\": \"Thay tên tất cả \\\"%1\\\" biến này thành:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://vi.wikipedia.org/wiki/M%C3%A0u_s%E1%BA%AFc\",\n    \"COLOUR_PICKER_TOOLTIP\": \"Chọn một màu từ bảng màu.\",\n    \"COLOUR_RANDOM_TITLE\": \"màu bất kỳ\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"chọn một màu bất kỳ.\",\n    \"COLOUR_RGB_TITLE\": \"Tạo màu từ\",\n    \"COLOUR_RGB_RED\": \"màu đỏ\",\n    \"COLOUR_RGB_GREEN\": \"màu xanh lá cây\",\n    \"COLOUR_RGB_BLUE\": \"màu xanh dương\",\n    \"COLOUR_RGB_TOOLTIP\": \"Tạo màu từ ba màu: đỏ, xanh lá cây, xanh dương với số lượng cụ thể.  Mỗi số phải có giá trị từ 0 đến 100.\",\n    \"COLOUR_BLEND_TITLE\": \"pha\",\n    \"COLOUR_BLEND_COLOUR1\": \"màu 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"màu 2\",\n    \"COLOUR_BLEND_RATIO\": \"tỉ lệ\",\n    \"COLOUR_BLEND_TOOLTIP\": \"Pha hai màu với nhau theo tỉ lệ (0 - 100).\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"lặp lại %1 lần\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"lặp lại\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"lần\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"thực hiện\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"Thực hiện các lệnh vài lần.\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"lặp lại trong khi\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"lặp lại cho đến khi\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"Miễn là điều kiện còn đúng, thì thực hiện các lệnh.\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"Miễn là điều kiện còn sai, thì thực hiện các lệnh.  Khi điều kiện đúng thì ngưng.\",\n    \"CONTROLS_FOR_TOOLTIP\": \"Đếm từ số đầu đến số cuối. Khi đến mỗi số, gán số vào biến \\\"%1\\\" rồi thực hiện các lệnh.\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"đếm theo\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"từ %1 đến %2 mỗi lần thêm %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"với mỗi thành phần\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"trong danh sách\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"Trong một danh sách, lấy từng thành phần, gán vào biến \\\"%1\\\", rồi thực hiện một số lệnh.\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"thoát\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"sang lần lặp tiếp theo\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"Thoát khỏi vòng lặp hiện tại.\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"Bỏ qua phần còn lại trong vòng lặp này, và sang lần lặp tiếp theo.\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"Chú ý: Mảnh này chỉ có thế dùng trong các vòng lặp.\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"Nếu điều kiện đúng, thực hiện các lệnh.\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"Nếu điều kiện đúng, thực hiện các lệnh đầu.  Nếu sai, thực hiện các lệnh sau.\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"Nếu điều kiện đúng, thực hiện các lệnh đầu.  Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai.\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"Nếu điều kiện đúng, thực hiện các lệnh đầu.  Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai.  Nếu không điều kiện nào đúng, thực hiện các lệnh cuối cùng.\",\n    \"CONTROLS_IF_MSG_IF\": \"nếu\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"nếu không nếu\",\n    \"CONTROLS_IF_MSG_ELSE\": \"nếu không\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"Thêm, bỏ, hoặc đổi thứ tự các mảnh con để tạo cấu trúc mới cho mảnh nếu.\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"Thêm một điều kiện vào mảnh nếu.\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"Cuối cùng, khi không điều kiện nào đúng.\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://vi.wikipedia.org/wiki/B%E1%BA%A5t_%C4%91%E1%BA%B3ng_th%E1%BB%A9c\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu giá trị hai đầu vào bằng nhau.\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu giá trị hai đầu vào không bằng nhau.\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu đầu vào thứ nhất nhỏ hơn đầu vào thứ hai.\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu đầu vào thứ nhất nhỏ hơn hoặc bằng đầu vào thứ hai.\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu đầu vào thứ nhất lớn hơn đầu vào thứ hai.\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"Hoàn trả giá trị \\\"đúng\\\" (true) nếu đầu vào thứ nhất lớn hơn hoặc bằng đầu vào thứ hai.\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"Hoàn trả \\\"đúng\\\" (true) nếu cả hai đầu vào đều đúng.\",\n    \"LOGIC_OPERATION_AND\": \"và\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"Hoàn trả \\\"đúng\\\" (true) nếu ít nhất một trong hai đầu vào đúng.\",\n    \"LOGIC_OPERATION_OR\": \"hoặc\",\n    \"LOGIC_NEGATE_TITLE\": \"không %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"Hoàn trả \\\"đúng\\\" (true) nếu đầu vào sai.  Hoàn trả \\\"sai\\\" (false) nếu đầu vào đúng.\",\n    \"LOGIC_BOOLEAN_TRUE\": \"đúng\",\n    \"LOGIC_BOOLEAN_FALSE\": \"sai\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"Hoàn trả \\\"đúng\\\" hoặc \\\"sai\\\".\",\n    \"LOGIC_NULL\": \"trống không\",\n    \"LOGIC_NULL_TOOLTIP\": \"Hoàn trả trống không.\",\n    \"LOGIC_TERNARY_CONDITION\": \"kiểm tra\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"nếu đúng\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"nếu sai\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"Kiểm tra điều kiện. Nếu điều kiện đúng, hoàn trả giá trị từ mệnh đề \\\"nếu đúng\\\" nếu không đúng, hoàn trả giá trị từ mệnh đề \\\"nếu sai\\\".\",\n    \"MATH_NUMBER_HELPURL\": \"https://vi.wikipedia.org/wiki/S%E1%BB%91\",\n    \"MATH_NUMBER_TOOLTIP\": \"Một con số.\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://vi.wikipedia.org/wiki/S%E1%BB%91_h%E1%BB%8Dc\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"Hoàn trả tổng của hai con số.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"Hoàn trả hiệu của hai con số.\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"Hoàn trả tích của hai con số.\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"Hoàn trả thương của hai con số.\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"Hoàn trả số lũy thừa với số thứ nhất là cơ số và số thứ hai là số mũ.\",\n    \"MATH_SINGLE_HELPURL\": \"https://vi.wikipedia.org/wiki/C%C4%83n_b%E1%BA%ADc_hai\",\n    \"MATH_SINGLE_OP_ROOT\": \"căn bật hai\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"Hoàn trả căn bật hai của số đầu vào.\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"giá trị tuyệt đối\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"Hoàn trả giá trị tuyệt đối của số đầu vào.\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"Đổi dấu của số đầu vào: âm thành dương và dương thành âm, và hoàn trả số mới.\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"Hoàn trả lôgarit tự nhiên của số đầu vào.\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"Hoàn trả lôgarit cơ số 10 của số đầu vào.\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"Hoàn trả lũy thừa của số e với số mũ đầu vào.\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"Hoàn trả lũy thừa của số 10 với số mũ đầu vào.\",\n    \"MATH_TRIG_HELPURL\": \"https://vi.wikipedia.org/wiki/H%C3%A0m_l%C6%B0%E1%BB%A3ng_gi%C3%A1c\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"Hoàn trả Sin của một góc (theo độ).\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"Hoàn trả Cos của một góc (theo độ).\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"Hoàn trả Tang của một góc (theo độ).\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"Hoàn trả Arcsin của một góc (theo độ).\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"Hoàn trả Arccos của một góc (theo độ).\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"Hoàn trả Arctang của một góc (theo độ).\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"Hoàn trả các đẳng số thường gặp: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (vô cực).\",\n    \"MATH_IS_EVEN\": \"chẵn\",\n    \"MATH_IS_ODD\": \"lẻ\",\n    \"MATH_IS_PRIME\": \"là số nguyên tố\",\n    \"MATH_IS_WHOLE\": \"là số nguyên\",\n    \"MATH_IS_POSITIVE\": \"là số dương\",\n    \"MATH_IS_NEGATIVE\": \"là số âm\",\n    \"MATH_IS_DIVISIBLE_BY\": \"chia hết cho\",\n    \"MATH_IS_TOOLTIP\": \"Kiểm tra con số xem nó có phải là số chẵn, lẻ, nguyên tố, nguyên, dương, âm,  hay xem nó có chia hết cho số đầu vào hay không.  Hoàn trả đúng hay sai.\",\n    \"MATH_CHANGE_HELPURL\": \"https://vi.wikipedia.org/wiki/Ph%C3%A9p_c%E1%BB%99ng\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"cộng vào\",\n    \"MATH_CHANGE_INPUT_BY\": \"giá trị\",\n    \"MATH_CHANGE_TOOLTIP\": \"Cộng số đầu vào vào biến \\\"%1\\\".\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"Làm tròn lên hoặc tròn xuống số đầu vào.\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"làm tròn\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"làm tròn lên\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"làm tròn xuống\",\n    \"MATH_ONLIST_HELPURL\": \"\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"tổng của một danh sách\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"Hoàn trả tổng số của tất cả các số trong danh sách.\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"số nhỏ nhất của một danh sách\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"Hoàn trả số nhỏ nhất trong tất cả các số trong danh sách.\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"số lớn nhât của một danh sách\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"Hoàn trả số lớn nhất trong tất cả các số trong danh sách.\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"giá trị trung bình của một danh sách\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"Hoàn trả giá trị trung bình từ của danh sách số.\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"số trung vị của một danh sách\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"Hoàn trả số trung vị của danh sách số.\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"các mode của một danh sách\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"Hoàn trả các số có mặt nhiều nhất trong danh sách.\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"độ lệch chuẩn của một danh sách\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"Hoàn trả độ lệch chuẩn của danh sách số.\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"một số bất kỳ của một danh sách\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"Hoàn trả một số bất kỳ từ các số trong danh sách.\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"số dư của %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"Chia số thứ nhất cho số thứ hai rồi hoàn trả số dư từ.\",\n    \"MATH_CONSTRAIN_TITLE\": \"giới hạn %1 không dưới %2 không hơn %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"Giới hạn số đầu vào để không dưới số thứ nhất và không hơn số thứ hai.\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"Một số nguyên bất kỳ từ %1 đến %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"Hoàn trả một số nguyên bất kỳ lớn hơn hoặc bằng số đầu và nhỏ hơn hoặc bằng số sau.\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"phân số bất kỳ\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"Hoàn trả một phân số bất kỳ không nhỏ hơn 0.0 và không lớn hơn 1.0.\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/string _(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"Một ký tự, một từ, hay một dòng.\",\n    \"TEXT_JOIN_HELPURL\": \"\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"tạo văn bản từ\",\n    \"TEXT_JOIN_TOOLTIP\": \"Tạo một văn bản từ các thành phần.\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"kết nối\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh văn bản này.\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"thêm vật mới vào văn bản.\",\n    \"TEXT_APPEND_TO\": \"ở cuối\",\n    \"TEXT_APPEND_APPENDTEXT\": \"thêm văn bản\",\n    \"TEXT_APPEND_TOOLTIP\": \"Thêm một mảng văn bản vào biến \\\"%1\\\".\",\n    \"TEXT_LENGTH_TITLE\": \"độ dài của %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"Hoàn trả số lượng ký tự (kể cả khoảng trắng) trong văn bản đầu vào.\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 trống không\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"Hoàn trả “đúng nếu văn bản không có ký tự nào.\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"Hoàn trả vị trí xuất hiện đầu/cuối của văn bản thứ nhất trong văn bản thứ hai.  Nếu không tìm thấy thì hoàn trả số 0.\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"trong văn bản\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"tìm sự có mặt đầu tiên của\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"tìm sự có mặt cuối cùng của\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"trong văn bản\",\n    \"TEXT_CHARAT_FROM_START\": \"lấy ký tự thứ\",\n    \"TEXT_CHARAT_FROM_END\": \"lấy từ phía cuối, ký tự thứ\",\n    \"TEXT_CHARAT_FIRST\": \"lấy ký tự đầu tiên\",\n    \"TEXT_CHARAT_LAST\": \"lấy ký tự cuối cùng\",\n    \"TEXT_CHARAT_RANDOM\": \"lấy ký tự bất kỳ\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"Hoàn trả ký tự ở vị trí đặt ra.\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"Hoàn trả một mảng ký tự ấn định từ trong văn bản.\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"trong văn bản\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"lấy từ ký tự thứ\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"lấy từ phía cuối, ký tự thứ\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"lấy từ ký tự đầu tiên\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"đến ký tự thứ\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"đến từ phía cuối, ký tự thứ\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"đến ký tự cuối cùng\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"Hoàn trả văn bản sau khi chuyển đổi chữ in hoa hay thường.\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"thành CHỮ IN HOA\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"thành chữ thường\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"thành Chữ In Đầu Mỗi Từ\",\n    \"TEXT_TRIM_TOOLTIP\": \"Hoàn trả bản sao của văn bản sau khi xóa khoảng trắng từ một hoặc hai bên.\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"cắt các không gian từ cả hai mặt của\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"cắt các không gian từ bên trái của\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"cắt các không gian từ bên phải của\",\n    \"TEXT_PRINT_TITLE\": \"in lên màng hình %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"In ra màng hình một văn bản, con số, hay một giá trị đầu vào khác.\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"Xin người dùng nhập vào văn bản với dòng hướng dẫn\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"Xin người dùng nhập vào con số với dòng hướng dẫn\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"Xin người dùng nhập vào một con số.\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"Xin người dùng nhập vào một văn bản.\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"tạo danh sách trống\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"Hoàn trả một danh sách, với độ dài 0, không có thành tố nào cả\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"Tạo một danh sách bao gồm nhiều vậts, với một số lượng bất kỳ.\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"tạo danh sách gồm\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"danh sách\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh danh sách này.\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"Thêm vật vào danh sách.\",\n    \"LISTS_REPEAT_TOOLTIP\": \"Tạo danh sách gồm một số lượng vật nhất định với mỗi vật đều giống nhau.\",\n    \"LISTS_REPEAT_TITLE\": \"tạo danh sách gồm một vật %1 lặp lại %2 lần\",\n    \"LISTS_LENGTH_TITLE\": \"độ dài của %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"Hoàn trả độ dài của một danh sách.\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 trống rỗng\",\n    \"LISTS_TOOLTIP\": \"Hoàn trả “đúng\\\" nếu danh sách không có thành tử nào.\",\n    \"LISTS_INLIST\": \"trong dánh sách\",\n    \"LISTS_INDEX_OF_FIRST\": \"tìm sự có mặt đầu tiên của vật\",\n    \"LISTS_INDEX_OF_LAST\": \"tìm sự có mặt cuối cùng của vật\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"Hoàn trả vị trí xuất hiện đầu/cuối của vật trong danh sách.  Nếu không tìm thấy thì hoàn trả số 0.\",\n    \"LISTS_GET_INDEX_GET\": \"lấy thành tố\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"lấy và xóa thành tố\",\n    \"LISTS_GET_INDEX_REMOVE\": \"xóa thành tố\",\n    \"LISTS_GET_INDEX_FROM_START\": \"thứ\",\n    \"LISTS_GET_INDEX_FROM_END\": \"(đếm từ cuối) thứ\",\n    \"LISTS_GET_INDEX_FIRST\": \"đầu tiên\",\n    \"LISTS_GET_INDEX_LAST\": \"cuối cùng\",\n    \"LISTS_GET_INDEX_RANDOM\": \"bất kỳ\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"Hoàn trả thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố đầu tiên.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"Hoàn trả thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố cuối cùng.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"Hoàn trả thành tố đầu tiên trong danh sách.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"Hoàn trả thành tố cuối cùng trong danh sách.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"Hoàn trả một thành tố bất kỳ trong danh sách.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"Hoàn trả và xóa thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố đầu tiên.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"Hoàn trả và xóa thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố cuối cùng.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"Hoàn trả và xóa thành tố đầu tiên trong danh sách.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"Hoàn trả và xóa thành tố cuối cùng trong danh sách.\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"Hoàn trả và xóa mộtthành tố bất kỳ trong danh sách.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"Xóa thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố đầu tiên.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"Xóa thành tố trong danh sách ở vị trí ấn định.  Số 1 là thành tố cuối cùng.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"Xóa thành tố đầu tiên trong danh sách.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"Xóa thành tố cuối cùng trong danh sách.\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"Xóa thành tố bất kỳ trong danh sách.\",\n    \"LISTS_SET_INDEX_SET\": \"đặt thành tố\",\n    \"LISTS_SET_INDEX_INSERT\": \"gắn chèn vào vị trí\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"giá trị\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"Đặt giá trị của thành tố ở vị trí ấn định trong một danh sách.  #1 là thành tố đầu tiên.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"Đặt giá trị của thành tố trong một danh sách ở vị trí ấn định từ phía cuối.  #1 là thành tố cuối cùng.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"Đặt giá trị của thành tố đầu tiên trong danh sách.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"Đặt giá trị của thành tố cuối cùng trong danh sách.\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"Đặt giá trị của thành tố ngẫu nhiên trong danh sách.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"Gắn chèn vật vào danh sách theo vị trí ấn định.  #1 là thành tố đầu tiên.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"Gắn chèn vật vào danh sách theo vị trí ấn định từ phía cuối.  #1 là thành tố cuối cùng.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"Gắn chèn vật vào đầu danh sách.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"Gắn thêm vật vào cuối danh sách.\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"Gắn chèn vật vào danh sách ở vị trí ngẫu nhiên.\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"lấy một danh sách con từ thứ\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"lấy một danh sách con từ (đếm từ cuối) thứ\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"lấy một danh sách con từ đầu tiên\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"đến thứ\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"đến (đếm từ cuối) thứ\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"đến cuối cùng\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"Lấy một mảng của danh sách này để tạo danh sách con.\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"Hoàn trả giá trị của.\",\n    \"VARIABLES_GET_CREATE_SET\": \"Tạo mảnh \\\"đặt vào %1\\\"\",\n    \"VARIABLES_SET_TITLE\": \"cho\",\n    \"VARIABLES_SET_TAIL\": \"bằng\",\n    \"VARIABLES_SET_TOOLTIP\": \"Đặt giá trị của biến này thành...\",\n    \"VARIABLES_SET_CREATE_GET\": \"Tạo mảnh \\\"lấy %1\\\"\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"thủ tục\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"với:\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"Một thủ tục không có giá trị hoàn trả.\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"hoàn trả\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"Một thủ tục có giá trị hoàn trả.\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"Chú ý: Thủ tục này có lặp lại tên các tham số.\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/procedure _ %28computer_science% 29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"thực hiện\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"Chạy một thủ tục không có giá trị hoàn trả.\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/procedure _ %28computer_science% 29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"Chạy một thủ tục có giá trị hoàn trả.\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"các tham số\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"biến:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"Làm nổi bật thủ tục\",\n    \"PROCEDURES_CREATE_DO\": \"Tạo mảnh \\\"thực hiện %1\\\"\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"Khi điều kiện đúng thì hoàn trả một giá trị.\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"Chú ý: Mảnh này chỉ có thể dùng trong một thủ tục.\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/zh-hans.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Espertus\",\n            \"Liuxinyu970226\",\n            \"Luotiancheng\",\n            \"Qiyue2001\",\n            \"Xiaomingyan\",\n            \"Yfdyh000\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"项\",\n    \"DUPLICATE_BLOCK\": \"复制\",\n    \"ADD_COMMENT\": \"添加注释\",\n    \"REMOVE_COMMENT\": \"删除注释\",\n    \"EXTERNAL_INPUTS\": \"外部输入\",\n    \"INLINE_INPUTS\": \"单行输入\",\n    \"DELETE_BLOCK\": \"删除块\",\n    \"DELETE_X_BLOCKS\": \"删除 %1 块\",\n    \"COLLAPSE_BLOCK\": \"折叠块\",\n    \"COLLAPSE_ALL\": \"折叠块\",\n    \"EXPAND_BLOCK\": \"展开块\",\n    \"EXPAND_ALL\": \"展开块\",\n    \"DISABLE_BLOCK\": \"禁用块\",\n    \"ENABLE_BLOCK\": \"启用块\",\n    \"HELP\": \"帮助\",\n    \"CHANGE_VALUE_TITLE\": \"更改值：\",\n    \"NEW_VARIABLE\": \"新变量...\",\n    \"NEW_VARIABLE_TITLE\": \"新变量的名称：\",\n    \"RENAME_VARIABLE\": \"重命名变量...\",\n    \"RENAME_VARIABLE_TITLE\": \"将所有“%1”变量重命名为:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://zh.wikipedia.org/wiki/颜色\",\n    \"COLOUR_PICKER_TOOLTIP\": \"从调色板中选择一种颜色。\",\n    \"COLOUR_RANDOM_TITLE\": \"随机颜色\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"随机选择一种颜色。\",\n    \"COLOUR_RGB_TITLE\": \"颜色\",\n    \"COLOUR_RGB_RED\": \"红色\",\n    \"COLOUR_RGB_GREEN\": \"绿色\",\n    \"COLOUR_RGB_BLUE\": \"蓝色\",\n    \"COLOUR_RGB_TOOLTIP\": \"通过指定红色、绿色和蓝色的量创建一种颜色。所有的值必须介于0和100之间。\",\n    \"COLOUR_BLEND_TITLE\": \"混合\",\n    \"COLOUR_BLEND_COLOUR1\": \"颜色1\",\n    \"COLOUR_BLEND_COLOUR2\": \"颜色2\",\n    \"COLOUR_BLEND_RATIO\": \"比例\",\n    \"COLOUR_BLEND_TOOLTIP\": \"用一个给定的比率(0.0-1.0)混合两种颜色。\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://zh.wikipedia.org/wiki/For回圈\",\n    \"CONTROLS_REPEAT_TITLE\": \"重复 %1 次\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"重复\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"次\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"执行\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"多次执行一些语句。\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"重复当\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"重复直到\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"只要值为真，执行一些语句。\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"只要值为假，执行一些语句。\",\n    \"CONTROLS_FOR_TOOLTIP\": \"从起始数到结尾数中取出变量“%1”的值，按指定的时间间隔，执行指定的块。\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"使用\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"从范围 %1 到 %2 每隔 %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"为每个项目\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"在列表中\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"遍历每个列表中的项目，将变量“%1”设定到该项中，然后执行某些语句。\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"中断循环\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"继续下一次循环\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"中断包含它的循环。\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"跳过这个循环的剩余部分，并继续下一次迭代。\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"警告：此块仅可用于在一个循环内。\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"如果值为真，执行一些语句。\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"如果值为真，则执行语句的第一块；否则，则执行语句的第二块。\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"如果第一个值为真，则执行语句的第一个块；否则，如果第二个值为真，则执行语句的第二块。\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"如果第一个值为真，则执行语句的第一块；否则，如果第二个值为真，则执行语句的第二块；如果没有值为真，则执行语句的最后一块。\",\n    \"CONTROLS_IF_MSG_IF\": \"如果\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"否则如果\",\n    \"CONTROLS_IF_MSG_ELSE\": \"否则\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"增加、删除或重新排列各节来重新配置“if”块。\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"在if语句块中增加一个条件。\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"添加一个最终的，包括所有情况的节到if块中。\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://zh.wikipedia.org/wiki/不等\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"如果两个输入结果相等，则返回真。\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"如果两个输入结果不相等，则返回真。\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"如果第一个输入结果比第二个小，则返回真。\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"如果第一个输入结果小于或等于第二个输入结果，则返回真。\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"如果第一个输入结果比第二个大，则返回真。\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"如果第一个输入结果大于或等于第二个输入结果，则返回真。\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"如果两个输入结果都为真，则返回真。\",\n    \"LOGIC_OPERATION_AND\": \"和\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"如果至少有一个输入结果为真，则返回真。\",\n    \"LOGIC_OPERATION_OR\": \"或\",\n    \"LOGIC_NEGATE_TITLE\": \"并非%1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"如果输入结果为假，则返回真；如果输入结果为真，则返回假。\",\n    \"LOGIC_BOOLEAN_TRUE\": \"真\",\n    \"LOGIC_BOOLEAN_FALSE\": \"错\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"同时返回真或假。\",\n    \"LOGIC_NULL\": \"空\",\n    \"LOGIC_NULL_TOOLTIP\": \"返回空值。\",\n    \"LOGIC_TERNARY_HELPURL\": \"https://zh.wikipedia.org/wiki/条件运算符\",\n    \"LOGIC_TERNARY_CONDITION\": \"测试\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"如果为真\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"如果为假\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"检查“test”中的条件。如果条件为真，则返回“if true”的值，否则，则返回“if false”的值。\",\n    \"MATH_NUMBER_HELPURL\": \"https://zh.wikipedia.org/wiki/数字\",\n    \"MATH_NUMBER_TOOLTIP\": \"一个数字。\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://zh.wikipedia.org/wiki/算术\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"返回两个数字的和。\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"返回两个数字的区别。\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"返回两个数字的乘积。\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"返回两个数字的商。\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"返回第一个数的第二个数次幂。\",\n    \"MATH_SINGLE_HELPURL\": \"https://zh.wikipedia.org/wiki/平方根\",\n    \"MATH_SINGLE_OP_ROOT\": \"平方根\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"返回数的平方根。\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"绝对\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"返回一个数的绝对值。\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"返回数的逻辑非。\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"返回一个数的自然对数。\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"返回数字的对数。\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"返回数的e次幂。\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"返回数的10次幂。\",\n    \"MATH_TRIG_HELPURL\": \"https://zh.wikipedia.org/wiki/三角函数\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"返回指定角度的正弦值(非弧度）。\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"返回指定角度的余弦值(非弧度）。\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"返回指定角度的正切值(非弧度）。\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"返回一个数的反正弦值。\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"返回一个数的反余弦值。\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"返回指定角度的反正切值。\",\n    \"MATH_CONSTANT_HELPURL\": \"https://zh.wikipedia.org/wiki/数学常数\",\n    \"MATH_CONSTANT_TOOLTIP\": \"返回一个常见常量：π (3.141......)，e (2.718...)、φ (1.618...)、 sqrt(2) (1.414......)、sqrt(½) (0.707......)或 ∞（无穷大）。\",\n    \"MATH_IS_EVEN\": \"是偶数\",\n    \"MATH_IS_ODD\": \"是奇数\",\n    \"MATH_IS_PRIME\": \"是质数\",\n    \"MATH_IS_WHOLE\": \"为整数\",\n    \"MATH_IS_POSITIVE\": \"是正值\",\n    \"MATH_IS_NEGATIVE\": \"为负\",\n    \"MATH_IS_DIVISIBLE_BY\": \"可被整除\",\n    \"MATH_IS_TOOLTIP\": \"如果数字是偶数、奇数、非负整数、正数、负数或如果它可被某数字整除，则返回真或假。\",\n    \"MATH_CHANGE_HELPURL\": \"https://zh.wikipedia.org/wiki/%E5%8A%A0%E6%B3%95\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"更改\",\n    \"MATH_CHANGE_INPUT_BY\": \"由\",\n    \"MATH_CHANGE_TOOLTIP\": \"将一个数添加到变量“%1”。\",\n    \"MATH_ROUND_HELPURL\": \"https://zh.wikipedia.org/wiki/四舍五入\",\n    \"MATH_ROUND_TOOLTIP\": \"数字向上或向下舍入。\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"向下舍入\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"向上舍入\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"向下舍入\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"列表中的数的总和\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"返回列表中的所有数字的和。\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"列表中的最小值\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"返回列表中最小数。\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"列表中的最大值\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"返回列表中最大数。\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"列表中的平均数\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"返回列表中的数值的平均值。\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"列表中位数\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"返回列表中的中位数。\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"列表模式\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"返回列表中的最常见的项的列表。\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"列表中的标准差\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"返回列表的标准偏差。\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"列表的随机项\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"从列表中返回一个随机的元素。\",\n    \"MATH_MODULO_HELPURL\": \"https://zh.wikipedia.org/wiki/%E6%A8%A1%E9%99%A4\",\n    \"MATH_MODULO_TITLE\": \"取余数自 %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"返回这两个数字相除后的余数。\",\n    \"MATH_CONSTRAIN_HELPURL\": \"https://en.wikipedia.org/wiki/Clamping_%28graphics%29\",\n    \"MATH_CONSTRAIN_TITLE\": \"限制数字 %1 介于 (低) %2 到 (高) %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"限制数字介于两个指定的数字之间\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://zh.wikipedia.org/wiki/随机数发生器\",\n    \"MATH_RANDOM_INT_TITLE\": \"从 %1 到 %2 之间的随机整数\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"返回两个指定的范围（含）之间的随机整数。\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://zh.wikipedia.org/wiki/随机数发生器\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"随机分数\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"返回介于（包含）0.0到1.0之间的随机数。\",\n    \"TEXT_TEXT_HELPURL\": \"https://zh.wikipedia.org/wiki/字符串\",\n    \"TEXT_TEXT_TOOLTIP\": \"一个字母、单词或一行文本。\",\n    \"TEXT_JOIN_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_creation\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"建立字串使用\",\n    \"TEXT_JOIN_TOOLTIP\": \"通过串起任意数量的项以建立一段文字。\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"加入\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"添加、删除或重新排列各节来重新配置这个文本块。\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"将一个项添加到文本中。\",\n    \"TEXT_APPEND_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_APPEND_TO\": \"在\",\n    \"TEXT_APPEND_APPENDTEXT\": \"追加文本\",\n    \"TEXT_APPEND_TOOLTIP\": \"将一些文本追加到变量“%1”。\",\n    \"TEXT_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Text_modification\",\n    \"TEXT_LENGTH_TITLE\": \"%1的长度\",\n    \"TEXT_LENGTH_TOOLTIP\": \"返回文本的字符数（包括空格）。\",\n    \"TEXT_ISEMPTY_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1是空的\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"如果提供的文本为空，则返回真。\",\n    \"TEXT_INDEXOF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Finding_text\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"返回在第二个字串中的第一/最后一个匹配项的索引值。如果未找到则返回 0。\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"自文本\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"寻找第一个出现的文本\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"寻找最后一个出现的文本\",\n    \"TEXT_INDEXOF_TAIL\": \"空白\",\n    \"TEXT_CHARAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Extracting_text\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"于文本中\",\n    \"TEXT_CHARAT_FROM_START\": \"获得字符#\",\n    \"TEXT_CHARAT_FROM_END\": \"获得倒数第#个字符\",\n    \"TEXT_CHARAT_FIRST\": \"获得第一个字符\",\n    \"TEXT_CHARAT_LAST\": \"获得最后一个字符\",\n    \"TEXT_CHARAT_RANDOM\": \"获取随机的字母\",\n    \"TEXT_CHARAT_TAIL\": \"空白\",\n    \"TEXT_CHARAT_TOOLTIP\": \"返回位于指定位置的字母。\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"返回指定的部分文本。\",\n    \"TEXT_GET_SUBSTRING_HELPURL\": \"http://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"自文本\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"取得一段字串自#\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"取得一段字串自#到末尾\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"取得一段字串自第一个字符\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"到字符#\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"到倒数第#个字符\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"到最后一个字符\",\n    \"TEXT_GET_SUBSTRING_TAIL\": \"空白\",\n    \"TEXT_CHANGECASE_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"使用不同的大小写复制这段文字。\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"为大写\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"为小写\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"为首字母大写\",\n    \"TEXT_TRIM_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces\",\n    \"TEXT_TRIM_TOOLTIP\": \"复制这段文字的同时删除两端多余的空格。\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"消除两侧空格\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"消除左侧空格\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"消除右侧空格\",\n    \"TEXT_PRINT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Printing_text\",\n    \"TEXT_PRINT_TITLE\": \"打印%1\",\n    \"TEXT_PRINT_TOOLTIP\": \"打印指定的文字、数字或其他值。\",\n    \"TEXT_PROMPT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"输入数字并显示提示消息\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"输入数字并显示提示消息\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"提示用户输入数字。\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"提示用户输入一些文本。\",\n    \"LISTS_CREATE_EMPTY_HELPURL\": \"https://en.wikipedia.org/wiki/Linked_list#Empty_lists\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"创建空列表\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"返回一个列表，长度为 0，不包含任何数据记录\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"建立一个具有任意数量项目的列表。\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"建立字串使用\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"列表\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"增加、删除或重新排列各部分以此重新配置这个列表块。\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"将一个项添加到列表中。\",\n    \"LISTS_REPEAT_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#create_list_with\",\n    \"LISTS_REPEAT_TOOLTIP\": \"建立包含指定重复次数的值的列表。\",\n    \"LISTS_REPEAT_TITLE\": \"建立列表使用项 %1 重复 %2 次\",\n    \"LISTS_LENGTH_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#length_of\",\n    \"LISTS_LENGTH_TITLE\": \"%1的长度\",\n    \"LISTS_LENGTH_TOOLTIP\": \"返回列表的长度。\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1是空的\",\n    \"LISTS_TOOLTIP\": \"如果改列表为空，则返回真。\",\n    \"LISTS_INLIST\": \"在列表中\",\n    \"LISTS_INDEX_OF_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\",\n    \"LISTS_INDEX_OF_FIRST\": \"找出第一个项出现\",\n    \"LISTS_INDEX_OF_LAST\": \"找出最后一个项出现\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"返回在列表中的第一/最后一个匹配项的索引值。如果未找到则返回 0。\",\n    \"LISTS_GET_INDEX_GET\": \"获得\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"取出并移除\",\n    \"LISTS_GET_INDEX_REMOVE\": \"移除\",\n    \"LISTS_GET_INDEX_FROM_START\": \"#\",\n    \"LISTS_GET_INDEX_FROM_END\": \"倒数第#\",\n    \"LISTS_GET_INDEX_FIRST\": \"第一\",\n    \"LISTS_GET_INDEX_LAST\": \"最后\",\n    \"LISTS_GET_INDEX_RANDOM\": \"随机\",\n    \"LISTS_GET_INDEX_TAIL\": \"空白\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"返回在列表中的指定位置的项。#1是第一个项目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"返回在列表中的指定位置的项。#1是最后一项。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"返回列表中的第一个项目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"返回列表中的最后一项。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"随机返回列表中的一个项目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"移除并返回列表中的指定位置的项。#1 是第一项。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"移除并返回列表中的指定位置的项。#1 是最后一项。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"移除并返回列表中的第一个项目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"移除并返回列表中的最后一个项目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"移除并返回列表中的一个随机项目中。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"移除在列表中的指定位置的项。#1 是第一项。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"删除在列表中的指定位置的项。#1是最后一项。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"移除列表中的第一项\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"移除列表中的最后一项\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"删除列表中的一个随机的项。\",\n    \"LISTS_SET_INDEX_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\",\n    \"LISTS_SET_INDEX_SET\": \"设置\",\n    \"LISTS_SET_INDEX_INSERT\": \"插入在\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"为\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"设置在列表中指定位置的项。#1是第一项。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"设置在列表中指定位置的项。#1是最后一项。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"设置列表中的第一个项目。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"设置列表中的最后一项。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"设置列表中一个随机的项目。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"插入在列表中指定位置的项。#1是第一项。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"插入在列表中的指定位置的项。#1是最后一项。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"在列表的起始处添加该项。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"将该项追加到列表的末尾。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"在列表中随机插入项。\",\n    \"LISTS_GET_SUBLIST_HELPURL\": \"https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"从#取得子列表\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"从倒数#取得子列表\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"从头获得子列表\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"到#\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"到倒数第#\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"到最后\",\n    \"LISTS_GET_SUBLIST_TAIL\": \"空白\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"复制列表中指定的部分。\",\n    \"ORDINAL_NUMBER_SUFFIX\": \"空白\",\n    \"VARIABLES_GET_TITLE\": \"空白\",\n    \"VARIABLES_GET_TAIL\": \"空白\",\n    \"VARIABLES_GET_TOOLTIP\": \"返回此变量的值。\",\n    \"VARIABLES_GET_CREATE_SET\": \"创建“设定%1”\",\n    \"VARIABLES_SET_HELPURL\": \"http://code.google.com/p/blockly/wiki/Variables#Set\",\n    \"VARIABLES_SET_TITLE\": \"赋值\",\n    \"VARIABLES_SET_TAIL\": \"到\",\n    \"VARIABLES_SET_TOOLTIP\": \"设置此变量，以使它和输入值相等。\",\n    \"VARIABLES_SET_CREATE_GET\": \"创建“获得%1”\",\n    \"PROCEDURES_DEFNORETURN_HELPURL\": \"https://zh.wikipedia.org/wiki/子程序\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"至\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"做点什么\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"与：\",\n    \"PROCEDURES_DEFNORETURN_DO\": \"空白\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"创建一个不带输出值的函数。\",\n    \"PROCEDURES_DEFRETURN_HELPURL\": \"https://zh.wikipedia.org/wiki/子程序\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"返回\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"创建一个有输出值的函数。\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"警告: 此函数具有重复参数。\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://zh.wikipedia.org/wiki/子程序\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"空白\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"运行用户定义的函数“%1”。\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://zh.wikipedia.org/wiki/子程序\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"运行用户定义的函数“%1”，并使用它的输出值。\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"參數\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"输入名称：\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"突出显示函数定义\",\n    \"PROCEDURES_CREATE_DO\": \"创建“%1”\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"如果值为真，则返回第二个值。\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"警告: 仅在定义函数内可使用此块。\"\n}"
  },
  {
    "path": "extern/blockly/msg/json/zh-hant.json",
    "content": "{\n    \"@metadata\": {\n        \"authors\": [\n            \"Gasolin\"\n        ]\n    },\n    \"VARIABLES_DEFAULT_NAME\": \"變量\",\n    \"DUPLICATE_BLOCK\": \"複製\",\n    \"ADD_COMMENT\": \"加入註解\",\n    \"REMOVE_COMMENT\": \"移除註解\",\n    \"EXTERNAL_INPUTS\": \"多行輸入\",\n    \"INLINE_INPUTS\": \"單行輸入\",\n    \"DELETE_BLOCK\": \"刪除積木\",\n    \"DELETE_X_BLOCKS\": \"刪除 %1 塊積木\",\n    \"COLLAPSE_BLOCK\": \"收合積木\",\n    \"COLLAPSE_ALL\": \"收合積木\",\n    \"EXPAND_BLOCK\": \"展開積木\",\n    \"EXPAND_ALL\": \"展開積木\",\n    \"DISABLE_BLOCK\": \"停用積木\",\n    \"ENABLE_BLOCK\": \"啟用積木\",\n    \"HELP\": \"說明\",\n    \"CHANGE_VALUE_TITLE\": \"修改值:\",\n    \"NEW_VARIABLE\": \"新變量...\",\n    \"NEW_VARIABLE_TITLE\": \"新變量名稱:\",\n    \"RENAME_VARIABLE\": \"重新命名變量...\",\n    \"RENAME_VARIABLE_TITLE\": \"將所有 \\\"%1\\\" 變量重新命名為:\",\n    \"COLOUR_PICKER_HELPURL\": \"https://en.wikipedia.org/wiki/Color\",\n    \"COLOUR_PICKER_TOOLTIP\": \"從調色板中選擇一種顏色。\",\n    \"COLOUR_RANDOM_TITLE\": \"隨機顏色\",\n    \"COLOUR_RANDOM_TOOLTIP\": \"隨機選擇一種顏色。\",\n    \"COLOUR_RGB_TITLE\": \"顏色\",\n    \"COLOUR_RGB_RED\": \"紅\",\n    \"COLOUR_RGB_GREEN\": \"綠\",\n    \"COLOUR_RGB_BLUE\": \"藍\",\n    \"COLOUR_RGB_TOOLTIP\": \"透過指定紅、綠、 藍色的值來建立一種顏色。所有的值必須介於 0 和 100 之間。\",\n    \"COLOUR_BLEND_TITLE\": \"混合\",\n    \"COLOUR_BLEND_COLOUR1\": \"顏色 1\",\n    \"COLOUR_BLEND_COLOUR2\": \"顏色 2\",\n    \"COLOUR_BLEND_RATIO\": \"比例\",\n    \"COLOUR_BLEND_TOOLTIP\": \"透過一個比率 (0.0-1.0)來混合兩種顏色。\",\n    \"CONTROLS_REPEAT_HELPURL\": \"https://en.wikipedia.org/wiki/For_loop\",\n    \"CONTROLS_REPEAT_TITLE\": \"重複 %1 次\",\n    \"CONTROLS_REPEAT_TITLE_REPEAT\": \"重複\",\n    \"CONTROLS_REPEAT_TITLE_TIMES\": \"次數\",\n    \"CONTROLS_REPEAT_INPUT_DO\": \"執行\",\n    \"CONTROLS_REPEAT_TOOLTIP\": \"多次執行一些語句\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_WHILE\": \"重複 當\",\n    \"CONTROLS_WHILEUNTIL_OPERATOR_UNTIL\": \"重複 直到\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_WHILE\": \"當值為真時，執行一些語句\",\n    \"CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL\": \"當值為否時，執行一些語句\",\n    \"CONTROLS_FOR_TOOLTIP\": \"從起始數到結尾數中取出變數 %1 的值，按指定的時間間隔，執行指定的積木。\",\n    \"CONTROLS_FOR_INPUT_WITH\": \"使用\",\n    \"CONTROLS_FOR_INPUT_FROM_TO_BY\": \"從範圍 %1 到 %2 每隔 %3\",\n    \"CONTROLS_FOREACH_INPUT_ITEM\": \"取出每個\",\n    \"CONTROLS_FOREACH_INPUT_INLIST\": \"自列表\",\n    \"CONTROLS_FOREACH_INPUT_INLIST_TAIL\": \"\",\n    \"CONTROLS_FOREACH_TOOLTIP\": \"遍歷每個列表中的項目，將變量  '%1' 設定到該項目中，然後執行某些語句\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK\": \"停止 迴圈\",\n    \"CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE\": \"繼續下一個 迴圈\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK\": \"離開當前的 迴圈\",\n    \"CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE\": \"跳過這個迴圈的其餘步驟，並繼續下一次的迴圈運算。\",\n    \"CONTROLS_FLOW_STATEMENTS_WARNING\": \"警告： 此積木僅可用於迴圈內。\",\n    \"CONTROLS_IF_TOOLTIP_1\": \"當值為真時，執行一些語句\",\n    \"CONTROLS_IF_TOOLTIP_2\": \"當值為真時，執行第一個語句，否則則執行第二個語句\",\n    \"CONTROLS_IF_TOOLTIP_3\": \"如果第一個值為真，則執行第一個語句。否則當第二個值為真時，則執行第二個語句\",\n    \"CONTROLS_IF_TOOLTIP_4\": \"如果第一個值為真，則執行第一個語句。否則當第二個值為真時，則執行第二個語句。如果前幾個敘述都不為真，則執行最後一個語句\",\n    \"CONTROLS_IF_MSG_IF\": \"如果\",\n    \"CONTROLS_IF_MSG_ELSEIF\": \"否則如果\",\n    \"CONTROLS_IF_MSG_ELSE\": \"否則\",\n    \"CONTROLS_IF_IF_TOOLTIP\": \"添加、 刪除或重新排列各區塊來此重新配置這個'如果'積木。\",\n    \"CONTROLS_IF_ELSEIF_TOOLTIP\": \"將條件添加到'如果'積木。\",\n    \"CONTROLS_IF_ELSE_TOOLTIP\": \"加入一個最終，所有條件下都都執行的區塊到'如果'積木中\",\n    \"LOGIC_COMPARE_HELPURL\": \"https://en.wikipedia.org/wiki/Inequality_(mathematics)\",\n    \"LOGIC_COMPARE_TOOLTIP_EQ\": \"如果這兩個輸入區塊內容相等，返回 真。\",\n    \"LOGIC_COMPARE_TOOLTIP_NEQ\": \"如果這兩個輸入區塊內容不相等，返回 真。\",\n    \"LOGIC_COMPARE_TOOLTIP_LT\": \"如果第一個輸入小於第二個輸入，返回 真。\",\n    \"LOGIC_COMPARE_TOOLTIP_LTE\": \"如果第一個輸入是小於或等於第二個輸入，返回 真。\",\n    \"LOGIC_COMPARE_TOOLTIP_GT\": \"如果第一個輸入大於第二個輸入，返回 真。\",\n    \"LOGIC_COMPARE_TOOLTIP_GTE\": \"如果第一個輸入大於或等於第二個輸入，返回 真。\",\n    \"LOGIC_OPERATION_TOOLTIP_AND\": \"如果這兩個輸入值都為 真，則返回 真。\",\n    \"LOGIC_OPERATION_AND\": \"且\",\n    \"LOGIC_OPERATION_TOOLTIP_OR\": \"如果至少一個輸入的值為 真，返回 真。\",\n    \"LOGIC_OPERATION_OR\": \"或\",\n    \"LOGIC_NEGATE_TITLE\": \"非 %1\",\n    \"LOGIC_NEGATE_TOOLTIP\": \"如果輸入的值是 否，則返回 真。如果輸入的值是 真 返回 否。\",\n    \"LOGIC_BOOLEAN_TRUE\": \"真\",\n    \"LOGIC_BOOLEAN_FALSE\": \"否\",\n    \"LOGIC_BOOLEAN_TOOLTIP\": \"返回 真 或 否。\",\n    \"LOGIC_NULL\": \"空\",\n    \"LOGIC_NULL_TOOLTIP\": \"返回 空。\",\n    \"LOGIC_TERNARY_CONDITION\": \"測試\",\n    \"LOGIC_TERNARY_IF_TRUE\": \"如果為真\",\n    \"LOGIC_TERNARY_IF_FALSE\": \"如果為非\",\n    \"LOGIC_TERNARY_TOOLTIP\": \"檢查 'test' 中的條件。如果條件為 真，將返回 '如果為 真' 值 ；否則，返回 '如果為 否' 的值。\",\n    \"MATH_NUMBER_HELPURL\": \"https://en.wikipedia.org/wiki/Number\",\n    \"MATH_NUMBER_TOOLTIP\": \"一個數字。\",\n    \"MATH_ARITHMETIC_HELPURL\": \"https://en.wikipedia.org/wiki/Arithmetic\",\n    \"MATH_ARITHMETIC_TOOLTIP_ADD\": \"返回兩個數字的總和。\",\n    \"MATH_ARITHMETIC_TOOLTIP_MINUS\": \"返回兩個數字的差。\",\n    \"MATH_ARITHMETIC_TOOLTIP_MULTIPLY\": \"返回兩個數字的乘積。\",\n    \"MATH_ARITHMETIC_TOOLTIP_DIVIDE\": \"返回兩個數字的商。\",\n    \"MATH_ARITHMETIC_TOOLTIP_POWER\": \"返回第二個數字的指數的第一個數字。\",\n    \"MATH_SINGLE_HELPURL\": \"https://en.wikipedia.org/wiki/Square_root\",\n    \"MATH_SINGLE_OP_ROOT\": \"開根號\",\n    \"MATH_SINGLE_TOOLTIP_ROOT\": \"返回指定數字的平方根。\",\n    \"MATH_SINGLE_OP_ABSOLUTE\": \"絕對值\",\n    \"MATH_SINGLE_TOOLTIP_ABS\": \"返回指定數字的絕對值。\",\n    \"MATH_SINGLE_TOOLTIP_NEG\": \"返回指定數字的 negation。\",\n    \"MATH_SINGLE_TOOLTIP_LN\": \"返回指定數字的自然對數。\",\n    \"MATH_SINGLE_TOOLTIP_LOG10\": \"返回指定數字的對數。\",\n    \"MATH_SINGLE_TOOLTIP_EXP\": \"返回指定數字指數的 e\",\n    \"MATH_SINGLE_TOOLTIP_POW10\": \"返回指定數字指數的10的冪次。\",\n    \"MATH_TRIG_HELPURL\": \"https://en.wikipedia.org/wiki/Trigonometric_functions\",\n    \"MATH_TRIG_TOOLTIP_SIN\": \"返回指定角度的正弦值(非弧度）。\",\n    \"MATH_TRIG_TOOLTIP_COS\": \"返回指定角度的餘弦值(非弧度）。\",\n    \"MATH_TRIG_TOOLTIP_TAN\": \"返回指定角度的正切值(非弧度）。\",\n    \"MATH_TRIG_TOOLTIP_ASIN\": \"返回指定角度的反正弦值(非弧度）。\",\n    \"MATH_TRIG_TOOLTIP_ACOS\": \"返回指定角度的反餘弦值(非弧度）。\",\n    \"MATH_TRIG_TOOLTIP_ATAN\": \"返回指定角度的反正切值。\",\n    \"MATH_CONSTANT_HELPURL\": \"https://en.wikipedia.org/wiki/Mathematical_constant\",\n    \"MATH_CONSTANT_TOOLTIP\": \"返回一個的常見常量： π (3.141......)，e (2.718...)、 φ (1.618...)、 開方(2) (1.414......)、 開方(½) (0.707......) 或 ∞ （無窮大）。\",\n    \"MATH_IS_EVEN\": \"是偶數\",\n    \"MATH_IS_ODD\": \"是奇數\",\n    \"MATH_IS_PRIME\": \"是質數\",\n    \"MATH_IS_WHOLE\": \"是非負整數\",\n    \"MATH_IS_POSITIVE\": \"是正值\",\n    \"MATH_IS_NEGATIVE\": \"是負值\",\n    \"MATH_IS_DIVISIBLE_BY\": \"可被整除\",\n    \"MATH_IS_TOOLTIP\": \"如果數字是偶數，奇數，非負整數，正數、 負數或如果它是可被某數字整除，則返回 真 或 否。\",\n    \"MATH_CHANGE_HELPURL\": \"https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter\",\n    \"MATH_CHANGE_TITLE_CHANGE\": \"修改\",\n    \"MATH_CHANGE_INPUT_BY\": \"自\",\n    \"MATH_CHANGE_TOOLTIP\": \"將數字添加到變量 '%1'。\",\n    \"MATH_ROUND_HELPURL\": \"https://en.wikipedia.org/wiki/Rounding\",\n    \"MATH_ROUND_TOOLTIP\": \"將數字向上或向下舍入。\",\n    \"MATH_ROUND_OPERATOR_ROUND\": \"四捨五入\",\n    \"MATH_ROUND_OPERATOR_ROUNDUP\": \"無條件進位\",\n    \"MATH_ROUND_OPERATOR_ROUNDDOWN\": \"無條件捨去\",\n    \"MATH_ONLIST_OPERATOR_SUM\": \"總和 自列表\",\n    \"MATH_ONLIST_TOOLTIP_SUM\": \"返回列表中的所有數字的總和。\",\n    \"MATH_ONLIST_OPERATOR_MIN\": \"最小值 自列表\",\n    \"MATH_ONLIST_TOOLTIP_MIN\": \"返回列表中的最小數字。\",\n    \"MATH_ONLIST_OPERATOR_MAX\": \"最大值 自列表\",\n    \"MATH_ONLIST_TOOLTIP_MAX\": \"返回列表中的最大數字。\",\n    \"MATH_ONLIST_OPERATOR_AVERAGE\": \"平均值 自列表\",\n    \"MATH_ONLIST_TOOLTIP_AVERAGE\": \"返回列表中數值的平均值 （算術平均值）。\",\n    \"MATH_ONLIST_OPERATOR_MEDIAN\": \"中位數 自列表\",\n    \"MATH_ONLIST_TOOLTIP_MEDIAN\": \"返回列表中數值的中位數。\",\n    \"MATH_ONLIST_OPERATOR_MODE\": \"比較眾數 自列表\",\n    \"MATH_ONLIST_TOOLTIP_MODE\": \"返回一個列表中的最常見項目的列表。\",\n    \"MATH_ONLIST_OPERATOR_STD_DEV\": \"標準差 自列表\",\n    \"MATH_ONLIST_TOOLTIP_STD_DEV\": \"返回列表中數字的標準差。\",\n    \"MATH_ONLIST_OPERATOR_RANDOM\": \"隨機抽取 自列表\",\n    \"MATH_ONLIST_TOOLTIP_RANDOM\": \"從列表中返回一個隨機的項目。\",\n    \"MATH_MODULO_HELPURL\": \"https://en.wikipedia.org/wiki/Modulo_operation\",\n    \"MATH_MODULO_TITLE\": \"取餘數自 %1 ÷ %2\",\n    \"MATH_MODULO_TOOLTIP\": \"回傳兩個數字相除的餘數\",\n    \"MATH_CONSTRAIN_TITLE\": \"限制數字 %1 介於 (低) %2 到 (高) %3\",\n    \"MATH_CONSTRAIN_TOOLTIP\": \"限制數字介於兩個指定的數字之間\",\n    \"MATH_RANDOM_INT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_INT_TITLE\": \"取隨機整數介於 (低) %1 到 %2\",\n    \"MATH_RANDOM_INT_TOOLTIP\": \"回傳限制的數字區間內的隨機數字\",\n    \"MATH_RANDOM_FLOAT_HELPURL\": \"https://en.wikipedia.org/wiki/Random_number_generation\",\n    \"MATH_RANDOM_FLOAT_TITLE_RANDOM\": \"取隨機分數\",\n    \"MATH_RANDOM_FLOAT_TOOLTIP\": \"返回介於 （包含） 0.0 到 1.0 之間的隨機數。\",\n    \"TEXT_TEXT_HELPURL\": \"https://en.wikipedia.org/wiki/String_(computer_science)\",\n    \"TEXT_TEXT_TOOLTIP\": \"字元、 單詞或一行文字。\",\n    \"TEXT_JOIN_TITLE_CREATEWITH\": \"建立字串使用\",\n    \"TEXT_JOIN_TOOLTIP\": \"通過串起任意數量的項目來建立一段文字。\",\n    \"TEXT_CREATE_JOIN_TITLE_JOIN\": \"加入\",\n    \"TEXT_CREATE_JOIN_TOOLTIP\": \"添加、 刪除或重新排列各區塊來此重新配置這個文字積木。\",\n    \"TEXT_CREATE_JOIN_ITEM_TOOLTIP\": \"將一個項目加入到字串中。\",\n    \"TEXT_APPEND_TO\": \"在\",\n    \"TEXT_APPEND_APPENDTEXT\": \"後加入文字\",\n    \"TEXT_APPEND_TOOLTIP\": \"將一些文字追加到變量 '%1'。\",\n    \"TEXT_LENGTH_TITLE\": \"長度 %1\",\n    \"TEXT_LENGTH_TOOLTIP\": \"返回這串文字的字元數（含空格） 。\",\n    \"TEXT_ISEMPTY_TITLE\": \"%1 為空\",\n    \"TEXT_ISEMPTY_TOOLTIP\": \"如果提供的字串為空，則返回 真。\",\n    \"TEXT_INDEXOF_TOOLTIP\": \"返回在第二個字串中的第一個/最後一個匹配項目的索引值。如果未找到則返回 0。\",\n    \"TEXT_INDEXOF_INPUT_INTEXT\": \"在字串\",\n    \"TEXT_INDEXOF_OPERATOR_FIRST\": \"尋找 第一個 出現的字串\",\n    \"TEXT_INDEXOF_OPERATOR_LAST\": \"尋找 最後一個 出現的字串\",\n    \"TEXT_CHARAT_INPUT_INTEXT\": \"的字元在字串\",\n    \"TEXT_CHARAT_FROM_START\": \"取得 字元 #\",\n    \"TEXT_CHARAT_FROM_END\": \"取得 倒數第 # 個字元\",\n    \"TEXT_CHARAT_FIRST\": \"取第一個字元\",\n    \"TEXT_CHARAT_LAST\": \"取最後一個字元\",\n    \"TEXT_CHARAT_RANDOM\": \"取隨機一個字元\",\n    \"TEXT_CHARAT_TAIL\": \"\",\n    \"TEXT_CHARAT_TOOLTIP\": \"返回位於指定位置的字元。\",\n    \"TEXT_GET_SUBSTRING_TOOLTIP\": \"返回指定的部分文字。\",\n    \"TEXT_GET_SUBSTRING_INPUT_IN_TEXT\": \"自字串\",\n    \"TEXT_GET_SUBSTRING_START_FROM_START\": \"取得一段字串自 #\",\n    \"TEXT_GET_SUBSTRING_START_FROM_END\": \"取得一段字串自 #\",\n    \"TEXT_GET_SUBSTRING_START_FIRST\": \"取得一段字串 自 第一個字元\",\n    \"TEXT_GET_SUBSTRING_END_FROM_START\": \"到 字元 #\",\n    \"TEXT_GET_SUBSTRING_END_FROM_END\": \"到 倒數第 # 個字元\",\n    \"TEXT_GET_SUBSTRING_END_LAST\": \"到 最後一個字元\",\n    \"TEXT_CHANGECASE_TOOLTIP\": \"使用不同的大小寫複製這段文字。\",\n    \"TEXT_CHANGECASE_OPERATOR_UPPERCASE\": \"轉成 大寫\",\n    \"TEXT_CHANGECASE_OPERATOR_LOWERCASE\": \"轉成 小寫\",\n    \"TEXT_CHANGECASE_OPERATOR_TITLECASE\": \"轉成 首字母大寫\",\n    \"TEXT_TRIM_TOOLTIP\": \"複製這段文字的同時刪除兩端多餘的空格。\",\n    \"TEXT_TRIM_OPERATOR_BOTH\": \"從 兩側 消除空格\",\n    \"TEXT_TRIM_OPERATOR_LEFT\": \"從 左側 消除空格\",\n    \"TEXT_TRIM_OPERATOR_RIGHT\": \"從 右側 消除空格\",\n    \"TEXT_PRINT_TITLE\": \"印出 %1\",\n    \"TEXT_PRINT_TOOLTIP\": \"印出指定的文字、 數字或其他值。\",\n    \"TEXT_PROMPT_TYPE_TEXT\": \"輸入 文字 並顯示提示訊息\",\n    \"TEXT_PROMPT_TYPE_NUMBER\": \"輸入 數字 並顯示提示訊息\",\n    \"TEXT_PROMPT_TOOLTIP_NUMBER\": \"輸入數字\",\n    \"TEXT_PROMPT_TOOLTIP_TEXT\": \"輸入文字\",\n    \"LISTS_CREATE_EMPTY_TITLE\": \"建立空列表\",\n    \"LISTS_CREATE_EMPTY_TOOLTIP\": \"返回一個長度為 0 的列表，不包含任何資料記錄\",\n    \"LISTS_CREATE_WITH_TOOLTIP\": \"建立一個具備任意數量項目的列表。\",\n    \"LISTS_CREATE_WITH_INPUT_WITH\": \"使用這些值建立列表\",\n    \"LISTS_CREATE_WITH_CONTAINER_TITLE_ADD\": \"加入\",\n    \"LISTS_CREATE_WITH_CONTAINER_TOOLTIP\": \"添加、 刪除或重新排列各區塊來此重新配置這個 列表 積木。\",\n    \"LISTS_CREATE_WITH_ITEM_TOOLTIP\": \"將一個項目加入到列表中。\",\n    \"LISTS_REPEAT_TOOLTIP\": \"建立包含指定重複次數的 值 的列表。\",\n    \"LISTS_REPEAT_TITLE\": \"建立列表使用項目 %1 重複 %2 次數\",\n    \"LISTS_LENGTH_TITLE\": \"長度 %1\",\n    \"LISTS_LENGTH_TOOLTIP\": \"返回列表的長度。\",\n    \"LISTS_IS_EMPTY_TITLE\": \"%1 值為空\",\n    \"LISTS_TOOLTIP\": \"如果該列表為空，則返回 真。\",\n    \"LISTS_INLIST\": \"自列表\",\n    \"LISTS_INDEX_OF_FIRST\": \"找出 第一個 項目出現\",\n    \"LISTS_INDEX_OF_LAST\": \"找出 最後一個 項目出現\",\n    \"LISTS_INDEX_OF_TOOLTIP\": \"返回在列表中的第一個/最後一個匹配項目的索引值。如果未找到則返回 0。\",\n    \"LISTS_GET_INDEX_GET\": \"取值\",\n    \"LISTS_GET_INDEX_GET_REMOVE\": \"取出並移除\",\n    \"LISTS_GET_INDEX_REMOVE\": \"移除\",\n    \"LISTS_GET_INDEX_FROM_END\": \"倒數第#筆\",\n    \"LISTS_GET_INDEX_FIRST\": \"第一筆\",\n    \"LISTS_GET_INDEX_LAST\": \"最後一筆\",\n    \"LISTS_GET_INDEX_RANDOM\": \"隨機\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_START\": \"返回在列表中的指定位置的項目。#1 是第一個項目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FROM_END\": \"返回在列表中的指定位置的項目。#1 是最後一個項目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_FIRST\": \"返回列表中的第一個項目\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_LAST\": \"返回列表中的最後一個項目\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_RANDOM\": \"返回列表中隨機的一個項目\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START\": \"移除並返回列表中的指定位置的項目。#1 是第一個項目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END\": \"移除並返回列表中的指定位置的項目。#1 是最後一個項目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST\": \"移除並返回列表中的第一個項目\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST\": \"移除並返回列表中的最後一個項目\",\n    \"LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM\": \"移除並返回列表中的隨機一個項目\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START\": \"移除在列表中的指定位置的項目。#1 是第一個項目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END\": \"移除在列表中的指定位置的項目。#1 是最後一個項目。\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST\": \"移除列表中的第一個項目\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST\": \"移除列表中的最後一個項目\",\n    \"LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM\": \"移除列表中隨機的一個項目\",\n    \"LISTS_SET_INDEX_SET\": \"設定\",\n    \"LISTS_SET_INDEX_INSERT\": \"插入到\",\n    \"LISTS_SET_INDEX_INPUT_TO\": \"為\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_START\": \"設定在列表中的指定位置的項目。#1 是第一個項目。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FROM_END\": \"設定在列表中的指定位置的項目。#1 是最後一個項目。\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_FIRST\": \"設定列表中的第一個項目\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_LAST\": \"設定列表中的最後一個項目\",\n    \"LISTS_SET_INDEX_TOOLTIP_SET_RANDOM\": \"設定列表中隨機的一個項目\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START\": \"插入在列表中的指定位置的項目。#1 是第一個項目。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END\": \"插入在列表中的指定位置的項目。#1 是最後一個項目。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST\": \"在列表的起始處添加一個項目。\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_LAST\": \"在列表的尾端加入一個項目\",\n    \"LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM\": \"在列表中隨機插入項目\",\n    \"LISTS_GET_SUBLIST_START_FROM_START\": \"從 # 取得子列表\",\n    \"LISTS_GET_SUBLIST_START_FROM_END\": \"從倒數 # 取得子列表\",\n    \"LISTS_GET_SUBLIST_START_FIRST\": \"從 頭 取得子列表\",\n    \"LISTS_GET_SUBLIST_END_FROM_START\": \"到 #\",\n    \"LISTS_GET_SUBLIST_END_FROM_END\": \"到 倒數 # 位\",\n    \"LISTS_GET_SUBLIST_END_LAST\": \"到 最後\",\n    \"LISTS_GET_SUBLIST_TOOLTIP\": \"複製列表中指定的部分。\",\n    \"VARIABLES_GET_TITLE\": \"\",\n    \"VARIABLES_GET_TAIL\": \"\",\n    \"VARIABLES_GET_TOOLTIP\": \"返回此變量的值。\",\n    \"VARIABLES_GET_CREATE_SET\": \"創立 '設定 %1'\",\n    \"VARIABLES_SET_TITLE\": \"賦值\",\n    \"VARIABLES_SET_TAIL\": \"到\",\n    \"VARIABLES_SET_TOOLTIP\": \"設定此變量，好和輸入值相等。\",\n    \"VARIABLES_SET_CREATE_GET\": \"建立 '取得 %1'\",\n    \"PROCEDURES_DEFNORETURN_TITLE\": \"到\",\n    \"PROCEDURES_DEFNORETURN_PROCEDURE\": \"流程\",\n    \"PROCEDURES_BEFORE_PARAMS\": \"與：\",\n    \"PROCEDURES_DEFNORETURN_TOOLTIP\": \"創建一個無回傳值的函數。\",\n    \"PROCEDURES_DEFRETURN_RETURN\": \"回傳\",\n    \"PROCEDURES_DEFRETURN_TOOLTIP\": \"創建一個有回傳值的函數。\",\n    \"PROCEDURES_DEF_DUPLICATE_WARNING\": \"警告: 此函數中有重複的參數。\",\n    \"PROCEDURES_CALLNORETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLNORETURN_CALL\": \"呼叫\",\n    \"PROCEDURES_CALLNORETURN_TOOLTIP\": \"執行使用者定義的函數 '%1'。\",\n    \"PROCEDURES_CALLRETURN_HELPURL\": \"https://en.wikipedia.org/wiki/Procedure_%28computer_science%29\",\n    \"PROCEDURES_CALLRETURN_TOOLTIP\": \"執行使用者定義的函數 '%1' 並使用它的回傳值\",\n    \"PROCEDURES_MUTATORCONTAINER_TITLE\": \"參數\",\n    \"PROCEDURES_MUTATORARG_TITLE\": \"變量:\",\n    \"PROCEDURES_HIGHLIGHT_DEF\": \"高亮顯示函式定義\",\n    \"PROCEDURES_CREATE_DO\": \"建立 '%1'\",\n    \"PROCEDURES_IFRETURN_TOOLTIP\": \"如果值為 真，則返回第二個值。\",\n    \"PROCEDURES_IFRETURN_WARNING\": \"警告: 此積木僅可在定義函式時使用。\"\n}"
  },
  {
    "path": "extern/blockly/msg/messages.js",
    "content": "/**\n * @license\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview English strings.\n * @author fraser@google.com (Neil Fraser)\n *\n * After modifying this file, either run \"build.py\" from the parent directory,\n * or run (from this directory):\n * ../i18n/js_to_json.py\n * to regenerate json/{en,qqq,synonyms}.json.\n *\n * To convert all of the json files to .js files, run:\n * ../i18n/create_messages.py json/*.json\n */\n'use strict';\n\ngoog.provide('Blockly.Msg.en');\n\ngoog.require('Blockly.Msg');\n\n\n/**\n * Due to the frequency of long strings, the 80-column wrap rule need not apply\n * to message files.\n */\n\n/**\n * Tip: Generate URLs for read-only blocks by creating the blocks in the Code app,\n * then evaluating this in the console:\n * 'http://blockly-demo.appspot.com/static/apps/code/readonly.html?lang=en&xml=' + encodeURIComponent(Blockly.Xml.domToText(Blockly.Xml.workspaceToDom(Blockly.mainWorkspace)).slice(5, -6))\n */\n\n/// default name - A simple, general default name for a variable, preferably short.\n/// For more context, see\n/// [[Translating:Blockly#infrequent_message_types]].\nBlockly.Msg.VARIABLES_DEFAULT_NAME = 'item';\n\n// Context menus.\n/// context menu - Make a copy of the selected block (and any blocks it contains).\nBlockly.Msg.DUPLICATE_BLOCK = 'Duplicate';\n/// context menu - Add a descriptive comment to the selected block.\nBlockly.Msg.ADD_COMMENT = 'Add Comment';\n/// context menu - Remove the descriptive comment from the selected block.\nBlockly.Msg.REMOVE_COMMENT = 'Remove Comment';\n/// context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block.  See [[Translating:Blockly#context_menus]].\nBlockly.Msg.EXTERNAL_INPUTS = 'External Inputs';\n/// context menu - Change from 'internal' to 'external' mode for displaying blocks used as inputs to the selected block.  See [[Translating:Blockly#context_menus]].\nBlockly.Msg.INLINE_INPUTS = 'Inline Inputs';\n/// context menu - Permanently delete the selected block.\nBlockly.Msg.DELETE_BLOCK = 'Delete Block';\n/// context menu - Permanently delete the %1 selected blocks.\\n\\nParameters:\\n* %1 - an integer greater than 1.\nBlockly.Msg.DELETE_X_BLOCKS = 'Delete %1 Blocks';\n/// context menu - Make the appearance of the selected block smaller by hiding some information about it.\nBlockly.Msg.COLLAPSE_BLOCK = 'Collapse Block';\n/// context menu - Make the appearance of the selected blocks smaller by hiding some information about it.  Use the same terminology as in the previous message.\nBlockly.Msg.COLLAPSE_ALL = 'Collapse Blocks';\n/// context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier.\nBlockly.Msg.EXPAND_BLOCK = 'Expand Block';\n/// context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier.  Use the same terminology as in the previous message.\nBlockly.Msg.EXPAND_ALL = 'Expand Blocks';\n/// context menu - Make the selected block have no effect (unless reenabled).\nBlockly.Msg.DISABLE_BLOCK = 'Disable Block';\n/// context menu - Make the selected block have effect (after having been disabled earlier).\nBlockly.Msg.ENABLE_BLOCK = 'Enable Block';\n/// context menu - Provide helpful information about the selected block.\\n{{Identical|Help}}\nBlockly.Msg.HELP = 'Help';\n\n// Realtime collaboration.\n/// collaboration instruction - Tell the user that they can talk with other users.\nBlockly.Msg.CHAT = 'Chat with your collaborator by typing in this box!';\n\n// Variable renaming.\n/// prompt - This message is only seen in the Opera browser.  With most browsers, users can edit numeric values in blocks by just clicking and typing.  Opera does not allows this, so we have to open a new window and prompt users with this message to chanage a value.\nBlockly.Msg.CHANGE_VALUE_TITLE = 'Change value:';\n/// dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices.  It is used to define a new variable.  See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\nBlockly.Msg.NEW_VARIABLE = 'New variable...';\n/// prompt - Prompts the user to enter the name for a new variable.  See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\nBlockly.Msg.NEW_VARIABLE_TITLE = 'New variable name:';\n/// dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices.  It is used to rename the current variable.  See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\nBlockly.Msg.RENAME_VARIABLE = 'Rename variable...';\n/// prompt - Prompts the user to enter the new name for the selected variable.  See [https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu https://code.google.com/p/blockly/wiki/Variables#Dropdown_menu].\\n\\nParameters:\\n* %1 - the name of the variable to be renamed.\nBlockly.Msg.RENAME_VARIABLE_TITLE = 'Rename all \"%1\" variables to:';\n\n// Colour Blocks.\n/// url - Information about colour.\nBlockly.Msg.COLOUR_PICKER_HELPURL = 'https://en.wikipedia.org/wiki/Color';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Picking_a_colour_from_a_palette https://code.google.com/p/blockly/wiki/Colour#Picking_a_colour_from_a_palette].\nBlockly.Msg.COLOUR_PICKER_TOOLTIP = 'Choose a colour from the palette.';\n/// url - A link that displays a random colour each time you visit it.\nBlockly.Msg.COLOUR_RANDOM_HELPURL = 'http://randomcolour.com';\n/// block text - Title of block that generates a colour at random.\nBlockly.Msg.COLOUR_RANDOM_TITLE = 'random colour';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Generating_a_random_colour https://code.google.com/p/blockly/wiki/Colour#Generating_a_random_colour].\nBlockly.Msg.COLOUR_RANDOM_TOOLTIP = 'Choose a colour at random.';\n/// url - A link for color codes with percentages (0-100%) for each component, instead of the more common 0-255, which may be more difficult for beginners.\nBlockly.Msg.COLOUR_RGB_HELPURL = 'http://www.december.com/html/spec/colorper.html';\n/// block text - Title of block for [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\nBlockly.Msg.COLOUR_RGB_TITLE = 'colour with';\n/// block input text - The amount of red (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\\n{{Identical|Red}}\nBlockly.Msg.COLOUR_RGB_RED = 'red';\n/// block input text - The amount of green (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\nBlockly.Msg.COLOUR_RGB_GREEN = 'green';\n/// block input text - The amount of blue (from 0 to 100) to use when [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\\n{{Identical|Blue}}\nBlockly.Msg.COLOUR_RGB_BLUE = 'blue';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components https://code.google.com/p/blockly/wiki/Colour#Creating_a_colour_from_red,_green,_and_blue_components].\nBlockly.Msg.COLOUR_RGB_TOOLTIP = 'Create a colour with the specified amount of red, green, and blue.  All values must be between 0 and 100.';\n/// url - A useful link that displays blending of two colors.\nBlockly.Msg.COLOUR_BLEND_HELPURL = 'http://meyerweb.com/eric/tools/color-blend/';\n/// block text - A verb for blending two shades of paint.\nBlockly.Msg.COLOUR_BLEND_TITLE = 'blend';\n/// block input text - The first of two colours to [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend].\nBlockly.Msg.COLOUR_BLEND_COLOUR1 = 'colour 1';\n/// block input text - The second of two colours to [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend].\nBlockly.Msg.COLOUR_BLEND_COLOUR2 = 'colour 2';\n/// block input text - The proportion of the [https://code.google.com/p/blockly/wiki/Colour#Blending_colours blend] containing the first color; the remaining proportion is of the second colour.  For example, if the first colour is red and the second color blue, a ratio of 1 would yield pure red, a ratio of .5 would yield purple (equal amounts of red and blue), and a ratio of 0 would yield pure blue.\nBlockly.Msg.COLOUR_BLEND_RATIO = 'ratio';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Colour#Blending_colours https://code.google.com/p/blockly/wiki/Colour#Blending_colours].\nBlockly.Msg.COLOUR_BLEND_TOOLTIP = 'Blends two colours together with a given ratio (0.0 - 1.0).';\n\n// Loop Blocks.\n/// url - Describes 'repeat loops' in computer programs; consider using the translation of the page [https://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow].\nBlockly.Msg.CONTROLS_REPEAT_HELPURL = 'https://en.wikipedia.org/wiki/For_loop';\n/// block input text - Title of [https://code.google.com/p/blockly/wiki/Loops#repeat repeat block].\\n\\nParameters:\\n* %1 - the number of times the body of the loop should be repeated.\nBlockly.Msg.CONTROLS_REPEAT_TITLE = 'repeat %1 times';\n/// block text - Text preceding the number of repetitions in a [https://code.google.com/p/blockly/wiki/Loops#repeat repeat block].\n/// (This is redundant with the previous message but is needed to support older code.)\nBlockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT = 'repeat';\n/// block text - Text following the number of times a [https://code.google.com/p/blockly/wiki/Loops#repeat repeat loop] should be repeated.\n/// (This is redundant but is needed to support older code.)\nBlockly.Msg.CONTROLS_REPEAT_TITLE_TIMES = 'times';\n/// block text - Preceding the blocks in the body of the loop.  See [https://code.google.com/p/blockly/wiki/Loops https://code.google.com/p/blockly/wiki/Loops].\nBlockly.Msg.CONTROLS_REPEAT_INPUT_DO = 'do';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat https://code.google.com/p/blockly/wiki/Loops#repeat].\nBlockly.Msg.CONTROLS_REPEAT_TOOLTIP = 'Do some statements several times.';\n/// url - Describes 'while loops' in computer programs; consider using the translation of [https://en.wikipedia.org/wiki/While_loop https://en.wikipedia.org/wiki/While_loop], if present, or [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow].\nBlockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = 'https://code.google.com/p/blockly/wiki/Repeat';\nBlockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\n/// dropdown - Specifies that a loop should [https://code.google.com/p/blockly/wiki/Loops#Repeat_while repeat while] the following condition is true.\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = 'repeat while';\n/// dropdown - Specifies that a loop should [https://code.google.com/p/blockly/wiki/Loops#Repeat_until repeat until] the following condition becomes true.\nBlockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = 'repeat until';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat_while Loops#repeat_while https://code.google.com/p/blockly/wiki/Loops#repeat_while Loops#repeat_while].\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = 'While a value is true, then do some statements.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#repeat_until https://code.google.com/p/blockly/wiki/Loops#repeat_until].\nBlockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = 'While a value is false, then do some statements.';\n\n/// url - Describes 'for loops' in computer programs.  Consider using your language's translation of [https://en.wikipedia.org/wiki/For_loop https://en.wikipedia.org/wiki/For_loop], if present.\nBlockly.Msg.CONTROLS_FOR_HELPURL = 'https://code.google.com/p/blockly/wiki/Loops#count_with';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#count_with https://code.google.com/p/blockly/wiki/Loops#count_with].\\n\\nParameters:\\n* %1 - the name of the loop variable.\nBlockly.Msg.CONTROLS_FOR_TOOLTIP = 'Have the variable %1 take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.';\n/// block title - Title of [https://code.google.com/p/blockly/wiki/Loops#count_with count with] blocks.\n/// [[File:Blockly-count-with.png]]\nBlockly.Msg.CONTROLS_FOR_INPUT_WITH = 'count with';\n/// block text - Starting with a (usually lower) number in a range (%1),\n/// ending with a (usually higher) number in a range (%2), and counting the\n/// iterations by a number of steps (%3).  As in\n/// [https://code.google.com/p/blockly/wiki/Loops#count_with\n/// https://code.google.com/p/blockly/wiki/Loops#count_with].\n/// [[File:Blockly-count-with.png]]\nBlockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY = 'from %1 to %2 by %3';\nBlockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\n\n/// url - Describes 'for-each loops' in computer programs.  Consider using your language's translation of [https://en.wikipedia.org/wiki/Foreach https://en.wikipedia.org/wiki/Foreach] if present.\nBlockly.Msg.CONTROLS_FOREACH_HELPURL = 'https://code.google.com/p/blockly/wiki/Loops#for_each for each block';\n/// block text - Title of [https://code.google.com/p/blockly/wiki/Loops#for_each for each block].\nBlockly.Msg.CONTROLS_FOREACH_INPUT_ITEM = 'for each item';\n/// block text - Preceding the list that should be iterated over in a [https://code.google.com/p/blockly/wiki/Loops#for_each for each loop].\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST = 'in list';\n/// block text - Following the list that should be iterated over in a [https://code.google.com/p/blockly/wiki/Loops#for_each for each loop].  This is empty in most, but not all, languages.\nBlockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL = '';\nBlockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\n/// block text - Description of [https://code.google.com/p/blockly/wiki/Loops#for_each for each blocks].\\n\\nParameters:\\n* %1 - the name of the loop variable.\nBlockly.Msg.CONTROLS_FOREACH_TOOLTIP = 'For each item in a list, set the variable \"%1\" to the item, and then do some statements.';\n\n/// url - Describes control flow in computer programs.  Consider using your language's translation of [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow], if it exists.\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = 'https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks';\n/// dropdown - The current loop should be exited.  See [https://code.google.com/p/blockly/wiki/Loops#break https://code.google.com/p/blockly/wiki/Loops#break].\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = 'break out of loop';\n/// dropdown - The current iteration of the loop should be ended and the next should begin.  See [https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration].\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = 'continue with next iteration of loop';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#break_out_of_loop https://code.google.com/p/blockly/wiki/Loops#break_out_of_loop].\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = 'Break out of the containing loop.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration https://code.google.com/p/blockly/wiki/Loops#continue_with_next_iteration].\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = 'Skip the rest of this loop, and continue with the next iteration.';\n/// warning - The user has tried placing a block outside of a loop (for each, while, repeat, etc.), but this type of block may only be used within a loop.  See [https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks https://code.google.com/p/blockly/wiki/Loops#Loop_Termination_Blocks].\nBlockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = 'Warning: This block may only be used within a loop.';\n\n// Logic Blocks.\n/// url - Describes conditional statements (if-then-else) in computer programs.  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_else https://en.wikipedia.org/wiki/If_else], if present.\nBlockly.Msg.CONTROLS_IF_HELPURL = 'https://code.google.com/p/blockly/wiki/If_Then';\n/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If_blocks 'if' blocks].  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.\nBlockly.Msg.CONTROLS_IF_TOOLTIP_1 = 'If a value is true, then do some statements.';\n/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else_blocks if-else blocks].  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.\nBlockly.Msg.CONTROLS_IF_TOOLTIP_2 = 'If a value is true, then do the first block of statements.  Otherwise, do the second block of statements.';\n/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else-If_blocks if-else-if blocks].  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.\nBlockly.Msg.CONTROLS_IF_TOOLTIP_3 = 'If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.';\n/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#If-Else-If-Else_blocks if-else-if-else blocks].  Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.\nBlockly.Msg.CONTROLS_IF_TOOLTIP_4 = 'If the first value is true, then do the first block of statements.  Otherwise, if the second value is true, do the second block of statements.  If none of the values are true, do the last block of statements.';\n/// block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse].\n/// It is recommended, but not essential, that this have text in common with the translation of 'else if'\nBlockly.Msg.CONTROLS_IF_MSG_IF = 'if';\n/// block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse].  The English words \"otherwise if\" would probably be clearer than \"else if\", but the latter is used because it is traditional and shorter.\nBlockly.Msg.CONTROLS_IF_MSG_ELSEIF = 'else if';\n/// block text - See [https://code.google.com/p/blockly/wiki/IfElse https://code.google.com/p/blockly/wiki/IfElse].  The English word \"otherwise\" would probably be superior to \"else\", but the latter is used because it is traditional and shorter.\nBlockly.Msg.CONTROLS_IF_MSG_ELSE = 'else';\nBlockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO;\nBlockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF;\n/// tooltip - Describes [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].\nBlockly.Msg.CONTROLS_IF_IF_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this if block.';\nBlockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF;\n/// tooltip - Describes the 'else if' subblock during [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].\nBlockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = 'Add a condition to the if block.';\nBlockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE;\n/// tooltip - Describes the 'else' subblock during [https://code.google.com/p/blockly/wiki/IfElse#Block_Modification if block modification].\nBlockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = 'Add a final, catch-all condition to the if block.';\n\n/// url - Information about comparisons.\nBlockly.Msg.LOGIC_COMPARE_HELPURL = 'https://en.wikipedia.org/wiki/Inequality_(mathematics)';\n/// tooltip - Describes the equals (=) block.\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = 'Return true if both inputs equal each other.';\n/// tooltip - Describes the equals (\\u0026ne;) block.\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = 'Return true if both inputs are not equal to each other.';\n/// tooltip - Describes the equals (\\u0026lt;) block.\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = 'Return true if the first input is smaller than the second input.';\n/// tooltip - Describes the equals (\\u0026le;) block.\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = 'Return true if the first input is smaller than or equal to the second input.';\n/// tooltip - Describes the equals (\\u0026gt;) block.\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = 'Return true if the first input is greater than the second input.';\n/// tooltip - Describes the equals (\\u0026ge;) block.\nBlockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = 'Return true if the first input is greater than or equal to the second input.';\n\n/// url - Information about the Boolean conjunction (\"and\") and disjunction (\"or\") operators.  Consider using the translation of [https://en.wikipedia.org/wiki/Boolean_logic https://en.wikipedia.org/wiki/Boolean_logic], if it exists in your language.\nBlockly.Msg.LOGIC_OPERATION_HELPURL = 'https://code.google.com/p/blockly/wiki/And_Or';\n/// tooltip - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction].\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = 'Return true if both inputs are true.';\n/// block text - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction].\nBlockly.Msg.LOGIC_OPERATION_AND = 'and';\n/// block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction].\nBlockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = 'Return true if at least one of the inputs is true.';\n/// block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction].\nBlockly.Msg.LOGIC_OPERATION_OR = 'or';\n\n/// url - Information about logical negation.  The translation of [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation] is recommended if it exists in the target language.\nBlockly.Msg.LOGIC_NEGATE_HELPURL = 'https://code.google.com/p/blockly/wiki/Not';\n/// block text - This is a unary operator that returns ''false'' when the input is ''true'', and ''true'' when the input is ''false''.\n/// \\n\\nParameters:\\n* %1 - the input (which should be either the value \"true\" or \"false\")\nBlockly.Msg.LOGIC_NEGATE_TITLE = 'not %1';\n/// tooltip - See [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation].\nBlockly.Msg.LOGIC_NEGATE_TOOLTIP = 'Returns true if the input is false.  Returns false if the input is true.';\n\n/// url - Information about the logic values ''true'' and ''false''.  Consider using the translation of [https://en.wikipedia.org/wiki/Truth_value https://en.wikipedia.org/wiki/Truth_value] if it exists in your language.\nBlockly.Msg.LOGIC_BOOLEAN_HELPURL = 'https://code.google.com/p/blockly/wiki/True_False';\n/// block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''true''.\nBlockly.Msg.LOGIC_BOOLEAN_TRUE = 'true';\n/// block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''false''.\nBlockly.Msg.LOGIC_BOOLEAN_FALSE = 'false';\n/// tooltip - Indicates that the block returns either of the two possible [https://en.wikipedia.org/wiki/Truth_value logical values].\nBlockly.Msg.LOGIC_BOOLEAN_TOOLTIP = 'Returns either true or false.';\n\n/// url - Provide a link to the translation of [https://en.wikipedia.org/wiki/Nullable_type https://en.wikipedia.org/wiki/Nullable_type], if it exists in your language; otherwise, do not worry about translating this advanced concept.\nBlockly.Msg.LOGIC_NULL_HELPURL = 'https://en.wikipedia.org/wiki/Nullable_type';\n/// block text - In computer languages, ''null'' is a special value that indicates that no value has been set.  You may use your language's word for \"nothing\" or \"invalid\".\nBlockly.Msg.LOGIC_NULL = 'null';\n/// tooltip - This should use the word from the previous message.\nBlockly.Msg.LOGIC_NULL_TOOLTIP = 'Returns null.';\n\n/// url - Describes the programming language operator known as the ''ternary'' or ''conditional'' operator.  It is recommended that you use the translation of [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:] if it exists.\nBlockly.Msg.LOGIC_TERNARY_HELPURL = 'https://en.wikipedia.org/wiki/%3F:';\n/// block input text - Label for the input whose value determines which of the other two inputs is returned.  In some programming languages, this is called a ''''predicate''''.\nBlockly.Msg.LOGIC_TERNARY_CONDITION = 'test';\n/// block input text - Indicates that the following input should be returned (used as output) if the test input is true.  Remember to try to keep block text terse (short).\nBlockly.Msg.LOGIC_TERNARY_IF_TRUE = 'if true';\n/// block input text - Indicates that the following input should be returned (used as output) if the test input is false.\nBlockly.Msg.LOGIC_TERNARY_IF_FALSE = 'if false';\n/// tooltip - See [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:].\nBlockly.Msg.LOGIC_TERNARY_TOOLTIP = 'Check the condition in \"test\". If the condition is true, returns the \"if true\" value; otherwise returns the \"if false\" value.';\n\n// Math Blocks.\n/// url - Information about (real) numbers.\nBlockly.Msg.MATH_NUMBER_HELPURL = 'https://en.wikipedia.org/wiki/Number';\n/// tooltip - Any positive or negative number, not necessarily an integer.\nBlockly.Msg.MATH_NUMBER_TOOLTIP = 'A number.';\n\n/// math - The symbol for the binary operation addition.\nBlockly.Msg.MATH_ADDITION_SYMBOL = '+';\n/// math - The symbol for the binary operation indicating that the right operand should be\n/// subtracted from the left operand.\nBlockly.Msg.MATH_SUBTRACTION_SYMBOL = '-';\n/// math - The binary operation indicating that the left operand should be divided by\n/// the right operand.\nBlockly.Msg.MATH_DIVISION_SYMBOL = '÷';\n/// math - The symbol for the binary operation multiplication.\nBlockly.Msg.MATH_MULTIPLICATION_SYMBOL = '×';\n/// math - The symbol for the binary operation exponentiation.  Specifically, if the\n/// value of the left operand is L and the value of the right operand (the exponent) is\n/// R, multiply L by itself R times.  (Fractional and negative exponents are also legal.)\nBlockly.Msg.MATH_POWER_SYMBOL = '^';\n\n/// math - The short name of the trigonometric function\n/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine].\nBlockly.Msg.MATH_TRIG_SIN = 'sin';\n/// math - The short name of the trigonometric function\n/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine].\nBlockly.Msg.MATH_TRIG_COS = 'cos';\n/// math - The short name of the trigonometric function\n/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent].\nBlockly.Msg.MATH_TRIG_TAN = 'tan';\n/// math - The short name of the ''inverse of'' the trigonometric function\n/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine].\nBlockly.Msg.MATH_TRIG_ASIN = 'asin';\n/// math - The short name of the ''inverse of'' the trigonometric function\n/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine].\nBlockly.Msg.MATH_TRIG_ACOS = 'acos';\n/// math - The short name of the ''inverse of'' the trigonometric function\n/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent].\nBlockly.Msg.MATH_TRIG_ATAN = 'atan';\n\n/// url - Information about addition, subtraction, multiplication, division, and exponentiation.\nBlockly.Msg.MATH_ARITHMETIC_HELPURL = 'https://en.wikipedia.org/wiki/Arithmetic';\n/// tooltip - See [https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition].\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = 'Return the sum of the two numbers.';\n/// tooltip - See [https://en.wikipedia.org/wiki/Subtraction https://en.wikipedia.org/wiki/Subtraction].\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = 'Return the difference of the two numbers.';\n/// tooltip - See [https://en.wikipedia.org/wiki/Multiplication https://en.wikipedia.org/wiki/Multiplication].\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = 'Return the product of the two numbers.';\n/// tooltip - See [https://en.wikipedia.org/wiki/Division_(mathematics) https://en.wikipedia.org/wiki/Division_(mathematics)].\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = 'Return the quotient of the two numbers.';\n/// tooltip - See [https://en.wikipedia.org/wiki/Exponentiation https://en.wikipedia.org/wiki/Exponentiation].\nBlockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = 'Return the first number raised to the power of the second number.';\n\n/// url - Information about the square root operation.\nBlockly.Msg.MATH_SINGLE_HELPURL = 'https://en.wikipedia.org/wiki/Square_root';\n/// dropdown - This computes the positive [https://en.wikipedia.org/wiki/Square_root square root] of its input.  For example, the square root of 16 is 4.\nBlockly.Msg.MATH_SINGLE_OP_ROOT = 'square root';\n/// tooltip - Please use the same term as in the previous message.\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = 'Return the square root of a number.';\n/// dropdown - This leaves positive numeric inputs changed and inverts negative inputs.  For example, the absolute value of 5 is 5; the absolute value of -5 is also 5.  For more information, see [https://en.wikipedia.org/wiki/Absolute_value https://en.wikipedia.org/wiki/Absolute_value].\nBlockly.Msg.MATH_SINGLE_OP_ABSOLUTE = 'absolute';\n/// tooltip - Please use the same term as in the previous message.\nBlockly.Msg.MATH_SINGLE_TOOLTIP_ABS = 'Return the absolute value of a number.';\n\n/// tooltip - Calculates '''0-n''', where '''n''' is the single numeric input.\nBlockly.Msg.MATH_SINGLE_TOOLTIP_NEG = 'Return the negation of a number.';\n/// tooltip - Calculates the [https://en.wikipedia.org/wiki/Natural_logarithm|natural logarithm] of its single numeric input.\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LN = 'Return the natural logarithm of a number.';\n/// tooltip - Calculates the [https://en.wikipedia.org/wiki/Common_logarithm common logarithm] of its single numeric input.\nBlockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = 'Return the base 10 logarithm of a number.';\n/// tooltip - Multiplies [https://en.wikipedia.org/wiki/E_%28mathematical_constant%29 e] by itself n times, where n is the single numeric input.\nBlockly.Msg.MATH_SINGLE_TOOLTIP_EXP = 'Return e to the power of a number.';\n/// tooltip - Multiplies 10 by itself n times, where n is the single numeric input.\nBlockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = 'Return 10 to the power of a number.';\n\n/// url - Information about the trigonometric functions sine, cosine, tangent, and their inverses (ideally using degrees, not radians).\nBlockly.Msg.MATH_TRIG_HELPURL = 'https://en.wikipedia.org/wiki/Trigonometric_functions';\n/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.\nBlockly.Msg.MATH_TRIG_TOOLTIP_SIN = 'Return the sine of a degree (not radian).';\n/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.\nBlockly.Msg.MATH_TRIG_TOOLTIP_COS = 'Return the cosine of a degree (not radian).';\n/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.\nBlockly.Msg.MATH_TRIG_TOOLTIP_TAN = 'Return the tangent of a degree (not radian).';\n/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent sine function], using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.\nBlockly.Msg.MATH_TRIG_TOOLTIP_ASIN = 'Return the arcsine of a number.';\n/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent cosine] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.\nBlockly.Msg.MATH_TRIG_TOOLTIP_ACOS = 'Return the arccosine of a number.';\n/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent tangent] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.\nBlockly.Msg.MATH_TRIG_TOOLTIP_ATAN = 'Return the arctangent of a number.';\n\n/// url - Information about the mathematical constants \\u0026pi;, e, the golden ratio (\\u0026phi;), \\u0026radic; 2, \\u0026radic; 1/2, and infinity (\\u0026infin;).\nBlockly.Msg.MATH_CONSTANT_HELPURL = 'https://en.wikipedia.org/wiki/Mathematical_constant';\n/// tooltip - Provides the specified [https://en.wikipedia.org/wiki/Mathematical_constant mathematical constant].\nBlockly.Msg.MATH_CONSTANT_TOOLTIP = 'Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).';\n/// dropdown - A number is '''even''' if it is a multiple of 2.  For example, 4 is even (yielding true), but 3 is not (false).\nBlockly.Msg.MATH_IS_EVEN = 'is even';\n/// dropdown - A number is '''odd''' if it is not a multiple of 2.  For example, 3 is odd (yielding true), but 4 is not (false).  The opposite of \"odd\" is \"even\".\nBlockly.Msg.MATH_IS_ODD = 'is odd';\n/// dropdown - A number is [https://en.wikipedia.org/wiki/Prime prime] if it cannot be evenly divided by any positive integers except for 1 and itself.  For example, 5 is prime, but 6 is not because 2 \\u0026times; 3 = 6.\nBlockly.Msg.MATH_IS_PRIME = 'is prime';\n/// dropdown - A number is '''whole''' if it is an [https://en.wikipedia.org/wiki/Integer integer].  For example, 5 is whole, but 5.1 is not.\nBlockly.Msg.MATH_IS_WHOLE = 'is whole';\n/// dropdown - A number is '''positive''' if it is greater than 0.  (0 is neither negative nor positive.)\nBlockly.Msg.MATH_IS_POSITIVE = 'is positive';\n/// dropdown - A number is '''negative''' if it is less than 0.  (0 is neither negative nor positive.)\nBlockly.Msg.MATH_IS_NEGATIVE = 'is negative';\n/// dropdown - A number x is divisible by y if y goes into x evenly.  For example, 10 is divisible by 5, but 10 is not divisible by 3.\nBlockly.Msg.MATH_IS_DIVISIBLE_BY = 'is divisible by';\n/// tooltip - This block lets the user specify via a dropdown menu whether to check if the numeric input is even, odd, prime, whole, positive, negative, or divisible by a given value.\nBlockly.Msg.MATH_IS_TOOLTIP = 'Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number.  Returns true or false.';\n\n/// url - Information about incrementing (increasing the value of) a variable.\n/// For other languages, just use the translation of the Wikipedia page about\n/// addition ([https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition]).\nBlockly.Msg.MATH_CHANGE_HELPURL = 'https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter';\n/// - As in: '''change''' [the value of variable] ''item by'' 1 (e.g., if the variable named 'item' had the value 5, change it to 6).\nBlockly.Msg.MATH_CHANGE_TITLE_CHANGE = 'change';\nBlockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\n/// - As in: ''change'' [the value of variable] ''item'' '''by''' 1 (e.g., if the variable named 'item' had the value 5, change it to 6).\nBlockly.Msg.MATH_CHANGE_INPUT_BY = 'by';\n/// tooltip - This updates the value of the variable by adding to it the following numeric input.\\n\\nParameters:\\n* %1 - the name of the variable whose value should be increased.\nBlockly.Msg.MATH_CHANGE_TOOLTIP = 'Add a number to variable \"%1\".';\n\n/// url - Information about how numbers are rounded to the nearest integer\nBlockly.Msg.MATH_ROUND_HELPURL = 'https://en.wikipedia.org/wiki/Rounding';\n/// tooltip - See [https://en.wikipedia.org/wiki/Rounding https://en.wikipedia.org/wiki/Rounding].\nBlockly.Msg.MATH_ROUND_TOOLTIP = 'Round a number up or down.';\n/// dropdown - This rounds its input to the nearest whole number.  For example, 3.4 is rounded to 3.\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUND = 'round';\n/// dropdown - This rounds its input up to the nearest whole number.  For example, if the input was 2.2, the result would be 3.\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = 'round up';\n/// dropdown - This rounds its input down to the nearest whole number.  For example, if the input was 3.8, the result would be 3.\nBlockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = 'round down';\n\n/// url - Information about applying a function to a list of numbers.  (We were unable to find such information in English.  Feel free to skip this and any other URLs that are difficult.)\nBlockly.Msg.MATH_ONLIST_HELPURL = '';\n/// dropdown - This computes the sum of the numeric elements in the list.  For example, the sum of the list {1, 4} is 5.\nBlockly.Msg.MATH_ONLIST_OPERATOR_SUM = 'sum of list';\n/// tooltip - Please use the same term for \"sum\" as in the previous message.\nBlockly.Msg.MATH_ONLIST_TOOLTIP_SUM = 'Return the sum of all the numbers in the list.';\n/// dropdown - This finds the smallest (minimum) number in a list.  For example, the smallest number in the list [-5, 0, 3] is -5.\nBlockly.Msg.MATH_ONLIST_OPERATOR_MIN = 'min of list';\n/// tooltip - Please use the same term for \"min\" or \"minimum\" as in the previous message.\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MIN = 'Return the smallest number in the list.';\n/// dropdown - This finds the largest (maximum) number in a list.  For example, the largest number in the list [-5, 0, 3] is 3.\nBlockly.Msg.MATH_ONLIST_OPERATOR_MAX = 'max of list';\n/// tooltip\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MAX = 'Return the largest number in the list.';\n/// dropdown - This adds up all of the numbers in a list and divides the sum by the number of elements in the list.  For example, the [https://en.wikipedia.org/wiki/Arithmetic_mean average] of the list [1, 2, 3, 4] is 2.5 (10/4).\nBlockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = 'average of list';\n/// tooltip - See [https://en.wikipedia.org/wiki/Arithmetic_mean https://en.wikipedia.org/wiki/Arithmetic_mean] for more informatin.\nBlockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = 'Return the average (arithmetic mean) of the numeric values in the list.';\n/// dropdown - This finds the [https://en.wikipedia.org/wiki/Median median] of the numeric values in a list.  For example, the median of the list {1, 2, 7, 12, 13} is 7.\nBlockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = 'median of list';\n/// tooltip - See [https://en.wikipedia.org/wiki/Median median https://en.wikipedia.org/wiki/Median median] for more information.\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = 'Return the median number in the list.';\n/// dropdown - This finds the most common numbers ([https://en.wikipedia.org/wiki/Mode_(statistics) modes]) in a list.  For example, the modes of the list {1, 3, 9, 3, 9}  are {3, 9}.\nBlockly.Msg.MATH_ONLIST_OPERATOR_MODE = 'modes of list';\n/// tooltip - See [https://en.wikipedia.org/wiki/Mode_(statistics) https://en.wikipedia.org/wiki/Mode_(statistics)] for more information.\nBlockly.Msg.MATH_ONLIST_TOOLTIP_MODE = 'Return a list of the most common item(s) in the list.';\n/// dropdown - This finds the [https://en.wikipedia.org/wiki/Standard_deviation standard deviation] of the numeric values in a list.\nBlockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = 'standard deviation of list';\n/// tooltip - See [https://en.wikipedia.org/wiki/Standard_deviation https://en.wikipedia.org/wiki/Standard_deviation] for more information.\nBlockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = 'Return the standard deviation of the list.';\n/// dropdown - This choose an element at random from a list.  Each element is chosen with equal probability.\nBlockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = 'random item of list';\n/// tooltip - Please use same term for 'random' as in previous entry.\nBlockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = 'Return a random element from the list.';\n\n/// url - information about the modulo (remainder) operation.\nBlockly.Msg.MATH_MODULO_HELPURL = 'https://en.wikipedia.org/wiki/Modulo_operation';\n/// block text - Title of block providing the remainder when dividing the first numerical input by the second.  For example, the remainder of 10 divided by 3 is 1.\\n\\nParameters:\\n* %1 - the dividend (10, in our example)\\n* %2 - the divisor (3 in our example).\nBlockly.Msg.MATH_MODULO_TITLE = 'remainder of %1 ÷ %2';\n/// tooltip - For example, the remainder of 10 divided by 3 is 1.\nBlockly.Msg.MATH_MODULO_TOOLTIP = 'Return the remainder from dividing the two numbers.';\n\n/// url - Information about constraining a numeric value to be in a specific range.  (The English URL is not ideal.  Recall that translating URLs is the lowest priority.)\nBlockly.Msg.MATH_CONSTRAIN_HELPURL = 'https://en.wikipedia.org/wiki/Clamping_%28graphics%29';\n/// block text - The title of the block that '''constrain'''s (forces) a number to be in a given range.\n///For example, if the number 150 is constrained to be between 5 and 100, the result will be 100.\n///\\n\\nParameters:\\n* %1 - the value to constrain (e.g., 150)\\n* %2 - the minimum value (e.g., 5)\\n* %3 - the maximum value (e.g., 100).\nBlockly.Msg.MATH_CONSTRAIN_TITLE = 'constrain %1 low %2 high %3';\n/// tooltip - This compares a number ''x'' to a low value ''L'' and a high value ''H''.  If ''x'' is less then ''L'', the result is ''L''.  If ''x'' is greater than ''H'', the result is ''H''.  Otherwise, the result is ''x''.\nBlockly.Msg.MATH_CONSTRAIN_TOOLTIP = 'Constrain a number to be between the specified limits (inclusive).';\n\n/// url - Information about how computers generate random numbers.\nBlockly.Msg.MATH_RANDOM_INT_HELPURL = 'https://en.wikipedia.org/wiki/Random_number_generation';\n/// block text - The title of the block that generates a random integer (whole number) in the specified range.  For example, if the range is from 5 to 7, this returns 5, 6, or 7 with equal likelihood. %1 is a placeholder for the lower number, %2 is the placeholder for the larger number.\nBlockly.Msg.MATH_RANDOM_INT_TITLE = 'random integer from %1 to %2';\n/// tooltip - Return a random integer between two values specified as inputs.  For example, if one input was 7 and another 9, any of the numbers 7, 8, or 9 could be produced.\nBlockly.Msg.MATH_RANDOM_INT_TOOLTIP = 'Return a random integer between the two specified limits, inclusive.';\n\n/// url - Information about how computers generate random numbers (specifically, numbers in the range from 0 to just below 1).\nBlockly.Msg.MATH_RANDOM_FLOAT_HELPURL = 'https://en.wikipedia.org/wiki/Random_number_generation';\n/// block text - The title of the block that generates a random number greater than or equal to 0 and less than 1.\nBlockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = 'random fraction';\n/// tooltip - Return a random fraction between 0 and 1.  The value may be equal to 0 but must be less than 1.\nBlockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = 'Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).';\n\n// Text Blocks.\n/// url - Information about how computers represent text (sometimes referred to as ''string''s).\nBlockly.Msg.TEXT_TEXT_HELPURL = 'https://en.wikipedia.org/wiki/String_(computer_science)';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Introduction https://code.google.com/p/blockly/wiki/Text#Introduction].\nBlockly.Msg.TEXT_TEXT_TOOLTIP = 'A letter, word, or line of text.';\n\n/// url - Information on concatenating/appending pieces of text.\nBlockly.Msg.TEXT_JOIN_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Text_creation';\n/// block text - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation].\nBlockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = 'create text with';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_creation create text with] for more information.\nBlockly.Msg.TEXT_JOIN_TOOLTIP = 'Create a piece of text by joining together any number of items.';\n\n/// block text - This is shown when the programmer wants to change the number of pieces of text being joined together.  See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.\nBlockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = 'join';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.\nBlockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this text block.';\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\n/// block text - See [https://code.google.com/p/blockly/wiki/Text#Text_creation https://code.google.com/p/blockly/wiki/Text#Text_creation], specifically the last picture in the 'Text creation' section.\nBlockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = 'Add an item to the text.';\n\n/// url - This and the other text-related URLs are going to be hard to translate.  As always, it is okay to leave untranslated or paste in the English-language URL.  For these URLs, you might also consider a general URL about how computers represent text (such as the translation of [https://en.wikipedia.org/wiki/String_(computer_science) this Wikipedia page]).\nBlockly.Msg.TEXT_APPEND_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Text_modification';\n/// block input text - Message preceding the name of a variable to which text should be appended.\n/// [[File:blockly-append-text.png]]\nBlockly.Msg.TEXT_APPEND_TO = 'to';\n/// block input text - Message following the variable and preceding the piece of text that should\n/// be appended, as shown below.\n/// [[File:blockly-append-text.png]]\nBlockly.Msg.TEXT_APPEND_APPENDTEXT = 'append text';\nBlockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_modification https://code.google.com/p/blockly/wiki/Text#Text_modification] for more information.\\n\\nParameters:\\n* %1 - the name of the variable to which text should be appended\nBlockly.Msg.TEXT_APPEND_TOOLTIP = 'Append some text to variable \"%1\".';\n\n/// url - Information about text on computers (usually referred to as 'strings').\nBlockly.Msg.TEXT_LENGTH_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Text_modification';\n/// block text - See [https://code.google.com/p/blockly/wiki/Text#Text_length https://code.google.com/p/blockly/wiki/Text#Text_length].\n/// \\n\\nParameters:\\n* %1 - the piece of text to take the length of\nBlockly.Msg.TEXT_LENGTH_TITLE = 'length of %1';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Text_length https://code.google.com/p/blockly/wiki/Text#Text_length].\nBlockly.Msg.TEXT_LENGTH_TOOLTIP = 'Returns the number of letters (including spaces) in the provided text.';\n\n/// url - Information about empty pieces of text on computers (usually referred to as 'empty strings').\nBlockly.Msg.TEXT_ISEMPTY_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text';\n/// block text - See [https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text].\n/// \\n\\nParameters:\\n* %1 - the piece of text to test for emptiness\nBlockly.Msg.TEXT_ISEMPTY_TITLE = '%1 is empty';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text https://code.google.com/p/blockly/wiki/Text#Checking_for_empty_text].\nBlockly.Msg.TEXT_ISEMPTY_TOOLTIP = 'Returns true if the provided text is empty.';\n\n/// url - Information about finding a character in a piece of text.\nBlockly.Msg.TEXT_INDEXOF_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Finding_text';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Finding_text https://code.google.com/p/blockly/wiki/Text#Finding_text].\nBlockly.Msg.TEXT_INDEXOF_TOOLTIP = 'Returns the index of the first/last occurrence of first text in the second text.  Returns 0 if text is not found.';\n/// block text - Title of blocks allowing users to find text.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Finding_text\n/// https://code.google.com/p/blockly/wiki/Text#Finding_text].\n/// [[File:Blockly-find-text.png]].\nBlockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = 'in text';\n/// dropdown - See [https://code.google.com/p/blockly/wiki/Text#Finding_text\n/// https://code.google.com/p/blockly/wiki/Text#Finding_text].\n/// [[File:Blockly-find-text.png]].\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = 'find first occurrence of text';\n/// dropdown - See [https://code.google.com/p/blockly/wiki/Text#Finding_text\n/// https://code.google.com/p/blockly/wiki/Text#Finding_text].  This would\n/// replace \"find first occurrence of text\" below.  (For more information on\n/// how common text is factored out of dropdown menus, see\n/// [https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus\n/// https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus)].)\n/// [[File:Blockly-find-text.png]].\nBlockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = 'find last occurrence of text';\n/// block text - Optional text to follow the rightmost block in a\n/// [https://code.google.com/p/blockly/wiki/Text#Finding_text\n/// https://code.google.com/p/blockly/wiki/Text#Finding_text in text ... find block]\n/// (after the \"a\" in the below picture).  This will be the empty string in most languages.\n/// [[File:Blockly-find-text.png]].\nBlockly.Msg.TEXT_INDEXOF_TAIL = '';\n\n/// url - Information about extracting characters (letters, number, symbols, etc.) from text.\nBlockly.Msg.TEXT_CHARAT_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Extracting_text';\n/// block text - Appears before the piece of text from which a letter (or number,\n/// punctuation character, etc.) should be extracted, as shown below.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character].\n/// [[File:Blockly-text-get.png]]\nBlockly.Msg.TEXT_CHARAT_INPUT_INTEXT = 'in text';\n/// dropdown - Indicates that the letter (or number, punctuation character, etc.) with the\n/// specified index should be obtained from the preceding piece of text.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character].\n/// [[File:Blockly-text-get.png]]\nBlockly.Msg.TEXT_CHARAT_FROM_START = 'get letter #';\n/// block text - Indicates that the letter (or number, punctuation character, etc.) with the\n/// specified index from the end of a given piece of text should be obtained. See\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character].\n/// [[File:Blockly-text-get.png]]\nBlockly.Msg.TEXT_CHARAT_FROM_END = 'get letter # from end';\n/// block text - Indicates that the first letter of the following piece of text should be\n/// retrieved.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character].\n/// [[File:Blockly-text-get.png]]\nBlockly.Msg.TEXT_CHARAT_FIRST = 'get first letter';\n/// block text - Indicates that the last letter (or number, punctuation mark, etc.) of the\n/// following piece of text should be retrieved.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character].\n/// [[File:Blockly-text-get.png]]\nBlockly.Msg.TEXT_CHARAT_LAST = 'get last letter';\n/// block text - Indicates that any letter (or number, punctuation mark, etc.) in the\n/// following piece of text should be randomly selected.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character].\n/// [[File:Blockly-text-get.png]]\nBlockly.Msg.TEXT_CHARAT_RANDOM = 'get random letter';\n/// block text - Text that goes after the rightmost block/dropdown when getting a single letter from\n/// a piece of text, as in [https://blockly-demo.appspot.com/static/apps/code/index.html#3m23km these\n/// blocks] or shown below.  For most languages, this will be blank.\n/// [[File:Blockly-text-get.png]]\nBlockly.Msg.TEXT_CHARAT_TAIL = '';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_single_character].\n/// [[File:Blockly-text-get.png]]\nBlockly.Msg.TEXT_CHARAT_TOOLTIP = 'Returns the letter at the specified position.';\n\n/// See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].\nBlockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = 'Returns a specified portion of the text.';\n/// url - Information about extracting characters from text.  Reminder: urls are the\n/// lowest priority translations.  Feel free to skip.\nBlockly.Msg.TEXT_GET_SUBSTRING_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text';\n/// block text - Precedes a piece of text from which a portion should be extracted.\n/// [[File:Blockly-get-substring.png]]\nBlockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = 'in text';\n/// dropdown - Indicates that the following number specifies the position (relative to the start\n/// position) of the beginning of the region of text that should be obtained from the preceding\n/// piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].\n/// [[File:Blockly-get-substring.png]]\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = 'get substring from letter #';\n/// dropdown - Indicates that the following number specifies the position (relative to the end\n/// position) of the beginning of the region of text that should be obtained from the preceding\n/// piece of text.  See [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].\n/// Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will\n/// automatically appear ''after'' this and any other\n/// [https://translatewiki.net/wiki/Translating:Blockly#Ordinal_numbers ordinal numbers]\n/// on this block.\n/// [[File:Blockly-get-substring.png]]\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = 'get substring from letter # from end';\n/// block text - Indicates that a region starting with the first letter of the preceding piece\n/// of text should be extracted.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].\n/// [[File:Blockly-get-substring.png]]\nBlockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = 'get substring from first letter';\n/// dropdown - Indicates that the following number specifies the position (relative to\n/// the start position) of the end of the region of text that should be obtained from the\n/// preceding piece of text.  See [\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].\n/// [[File:Blockly-get-substring.png]]\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = 'to letter #';\n/// dropdown - Indicates that the following number specifies the position (relative to the\n/// end position) of the end of the region of text that should be obtained from the preceding\n/// piece of text.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].\n/// [[File:Blockly-get-substring.png]]\nBlockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = 'to letter # from end';\n/// block text - Indicates that a region ending with the last letter of the preceding piece\n/// of text should be extracted.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\n/// https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text].\n/// [[File:Blockly-get-substring.png]]\nBlockly.Msg.TEXT_GET_SUBSTRING_END_LAST = 'to last letter';\n/// block text - Text that should go after the rightmost block/dropdown when\n/// [https://code.google.com/p/blockly/wiki/Text#Extracting_a_region_of_text\n/// extracting a region of text].  In most languages, this will be the empty string.\n/// [[File:Blockly-get-substring.png]]\nBlockly.Msg.TEXT_GET_SUBSTRING_TAIL = '';\n\n/// url - Information about the case of letters (upper-case and lower-case).\nBlockly.Msg.TEXT_CHANGECASE_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case'\n/// tooltip - Describes a block to adjust the case of letters.  For more information on this block,\n/// see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\n/// https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].\nBlockly.Msg.TEXT_CHANGECASE_TOOLTIP = 'Return a copy of the text in a different case.';\n/// block text - Indicates that all of the letters in the following piece of text should be\n/// capitalized.  If your language does not use case, you may indicate that this is not\n/// applicable to your language.  For more information on this block, see\n/// [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case\n/// https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = 'to UPPER CASE';\n/// block text - Indicates that all of the letters in the following piece of text should be converted to lower-case.  If your language does not use case, you may indicate that this is not applicable to your language.  For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = 'to lower case';\n/// block text - Indicates that the first letter of each of the following words should be capitalized and the rest converted to lower-case.  If your language does not use case, you may indicate that this is not applicable to your language.  For more information on this block, see [https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case https://code.google.com/p/blockly/wiki/Text#Adjusting_text_case].\nBlockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = 'to Title Case';\n\n/// url - Information about trimming (removing) text off the beginning and ends of pieces of text.\nBlockly.Msg.TEXT_TRIM_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Trimming_%28removing%29_spaces';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces\n/// https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces].\nBlockly.Msg.TEXT_TRIM_TOOLTIP = 'Return a copy of the text with spaces removed from one or both ends.';\n/// dropdown - Removes spaces from the beginning and end of a piece of text.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces\n/// https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces].  Note that neither\n/// this nor the other options modify the original piece of text (that follows);\n/// the block just returns a version of the text without the specified spaces.\nBlockly.Msg.TEXT_TRIM_OPERATOR_BOTH = 'trim spaces from both sides of';\n/// dropdown - Removes spaces from the beginning of a piece of text.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces\n/// https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces].\n/// Note that in right-to-left scripts, this will remove spaces from the right side.\nBlockly.Msg.TEXT_TRIM_OPERATOR_LEFT = 'trim spaces from left side of';\n/// dropdown - Removes spaces from the end of a piece of text.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces\n/// https://code.google.com/p/blockly/wiki/Text#Trimming_(removing)_spaces].\n/// Note that in right-to-left scripts, this will remove spaces from the left side.\nBlockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = 'trim spaces from right side of';\n\n/// url - Information about displaying text on computers.\nBlockly.Msg.TEXT_PRINT_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Printing_text';\n/// block text - Display the input on the screen.  See\n/// [https://code.google.com/p/blockly/wiki/Text#Printing_text\n/// https://code.google.com/p/blockly/wiki/Text#Printing_text].\n/// \\n\\nParameters:\\n* %1 - the value to print\nBlockly.Msg.TEXT_PRINT_TITLE = 'print %1';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Text#Printing_text\n/// https://code.google.com/p/blockly/wiki/Text#Printing_text].\nBlockly.Msg.TEXT_PRINT_TOOLTIP = 'Print the specified text, number or other value.';\n/// url - Information about getting text from users.\nBlockly.Msg.TEXT_PROMPT_HELPURL = 'https://code.google.com/p/blockly/wiki/Text#Getting_input_from_the_user';\n/// dropdown - Specifies that a piece of text should be requested from the user with\n/// the following message.  See [https://code.google.com/p/blockly/wiki/Text#Printing_text\n/// https://code.google.com/p/blockly/wiki/Text#Printing_text].\nBlockly.Msg.TEXT_PROMPT_TYPE_TEXT = 'prompt for text with message';\n/// dropdown - Specifies that a number should be requested from the user with the\n/// following message.  See [https://code.google.com/p/blockly/wiki/Text#Printing_text\n/// https://code.google.com/p/blockly/wiki/Text#Printing_text].\nBlockly.Msg.TEXT_PROMPT_TYPE_NUMBER = 'prompt for number with message';\n/// dropdown - Precedes the message with which the user should be prompted for\n/// a number.  See [https://code.google.com/p/blockly/wiki/Text#Printing_text\n/// https://code.google.com/p/blockly/wiki/Text#Printing_text].\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = 'Prompt for user for a number.';\n/// dropdown - Precedes the message with which the user should be prompted for some text.\n/// See [https://code.google.com/p/blockly/wiki/Text#Printing_text\n/// https://code.google.com/p/blockly/wiki/Text#Printing_text].\nBlockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = 'Prompt for user for some text.';\n\n// Lists Blocks.\n/// url - Information on empty lists.\nBlockly.Msg.LISTS_CREATE_EMPTY_HELPURL = 'https://en.wikipedia.org/wiki/Linked_list#Empty_lists';\n/// block text - See [https://code.google.com/p/blockly/wiki/Lists#create_empty_list https://code.google.com/p/blockly/wiki/Lists#create_empty_list].\nBlockly.Msg.LISTS_CREATE_EMPTY_TITLE = 'create empty list';\n/// block text - See [https://code.google.com/p/blockly/wiki/Lists#create_empty_list https://code.google.com/p/blockly/wiki/Lists#create_empty_list].\nBlockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = 'Returns a list, of length 0, containing no data records';\n\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with].\nBlockly.Msg.LISTS_CREATE_WITH_TOOLTIP = 'Create a list with any number of items.';\n/// block text - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with https://code.google.com/p/blockly/wiki/Lists#create_list_with].\nBlockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = 'create list with';\n/// block text - This appears in a sub-block when [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs changing the number of inputs in a ''''create list with'''' block].\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = 'list';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs].\nBlockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this list block.';\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME;\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs https://code.google.com/p/blockly/wiki/Lists#changing_number_of_inputs].\nBlockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = 'Add an item to the list.';\n\n/// url - Information about [https://code.google.com/p/blockly/wiki/Lists#create_list_with creating a list with multiple copies of a single item].\nBlockly.Msg.LISTS_REPEAT_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#create_list_with';\n/// url - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with creating a list with multiple copies of a single item].\nBlockly.Msg.LISTS_REPEAT_TOOLTIP = 'Creates a list consisting of the given value repeated the specified number of times.';\n/// block text - See [https://code.google.com/p/blockly/wiki/Lists#create_list_with\n/// https://code.google.com/p/blockly/wiki/Lists#create_list_with].\n///\\n\\nParameters:\\n* %1 - the item (text) to be repeated\\n* %2 - the number of times to repeat it\nBlockly.Msg.LISTS_REPEAT_TITLE = 'create list with item %1 repeated %2 times';\n\n/// url - Information about how the length of a list is computed (i.e., by the total number of elements, not the number of different elements).\nBlockly.Msg.LISTS_LENGTH_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#length_of';\n/// block text - See [https://code.google.com/p/blockly/wiki/Lists#length_of https://code.google.com/p/blockly/wiki/Lists#length_of].\n/// \\n\\nParameters:\\n* %1 - the list whose length is desired\nBlockly.Msg.LISTS_LENGTH_TITLE = 'length of %1';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#length_of https://code.google.com/p/blockly/wiki/Lists#length_of Blockly:Lists:length of].\nBlockly.Msg.LISTS_LENGTH_TOOLTIP = 'Returns the length of a list.';\n\n/// url - See [https://code.google.com/p/blockly/wiki/Lists#is_empty https://code.google.com/p/blockly/wiki/Lists#is_empty].\nBlockly.Msg.LISTS_IS_EMPTY_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#is_empty';\n/// block text - See [https://code.google.com/p/blockly/wiki/Lists#is_empty\n/// https://code.google.com/p/blockly/wiki/Lists#is_empty].\n/// \\n\\nParameters:\\n* %1 - the list to test\nBlockly.Msg.LISTS_IS_EMPTY_TITLE = '%1 is empty';\n/// block tooltip - See [https://code.google.com/p/blockly/wiki/Lists#is_empty\n/// https://code.google.com/p/blockly/wiki/Lists#is_empty].\nBlockly.Msg.LISTS_TOOLTIP = 'Returns true if the list is empty.';\n\n/// block text - Title of blocks operating on [https://code.google.com/p/blockly/wiki/Lists lists].\nBlockly.Msg.LISTS_INLIST = 'in list';\n\n/// url - See [https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List\n/// https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List].\nBlockly.Msg.LISTS_INDEX_OF_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#Getting_Items_from_a_List';\nBlockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\n/// dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List\n/// Lists#Finding_Items_in_a_List].\n/// [[File:Blockly-list-find.png]]\nBlockly.Msg.LISTS_INDEX_OF_FIRST = 'find first occurrence of item';\n/// dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List\n/// https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List].\n/// [[File:Blockly-list-find.png]]\nBlockly.Msg.LISTS_INDEX_OF_LAST = 'find last occurrence of item';\n/// dropdown - See [https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List\n/// https://code.google.com/p/blockly/wiki/Lists#Finding_Items_in_a_List].\n/// [[File:Blockly-list-find.png]]\nBlockly.Msg.LISTS_INDEX_OF_TOOLTIP = 'Returns the index of the first/last occurrence of the item in the list.  Returns 0 if text is not found.';\n\nBlockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL;\n/// dropdown - Indicates that the user wishes to\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item\n/// get an item from a list] without removing it from the list.\nBlockly.Msg.LISTS_GET_INDEX_GET = 'get';\n/// dropdown - Indicates that the user wishes to\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item\n/// get and remove an item from a list], as opposed to merely getting\n/// it without modifying the list.\nBlockly.Msg.LISTS_GET_INDEX_GET_REMOVE = 'get and remove';\n/// dropdown - Indicates that the user wishes to\n/// [https://code.google.com/p/blockly/wiki/Lists#Removing_an_item\n/// remove an item from a list].\nBlockly.Msg.LISTS_GET_INDEX_REMOVE = 'remove';\n/// dropdown - Indicates that an index relative to the front of the list should be used to\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item get and/or remove\n/// an item from a list].  Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will\n/// automatically appear ''after'' this number (and any other ordinal numbers on this block).\n/// See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly.\n/// [[File:Blockly-list-get-item.png]]\nBlockly.Msg.LISTS_GET_INDEX_FROM_START = '#';\n/// dropdown - Indicates that an index relative to the end of the list should be used\n/// to [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item access an item in a list].\n/// [[File:Blockly-list-get-item.png]]\nBlockly.Msg.LISTS_GET_INDEX_FROM_END = '# from end';\n/// dropdown - Indicates that the '''first''' item should be\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list].\n/// [[File:Blockly-list-get-item.png]]\nBlockly.Msg.LISTS_GET_INDEX_FIRST = 'first';\n/// dropdown - Indicates that the '''last''' item should be\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list].\n/// [[File:Blockly-list-get-item.png]]\nBlockly.Msg.LISTS_GET_INDEX_LAST = 'last';\n/// dropdown - Indicates that a '''random''' item should be\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item accessed in a list].\n/// [[File:Blockly-list-get-item.png]]\nBlockly.Msg.LISTS_GET_INDEX_RANDOM = 'random';\n/// block text - Text that should go after the rightmost block/dropdown when\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item\n/// accessing an item from a list].  In most languages, this will be the empty string.\n/// [[File:Blockly-list-get-item.png]]\nBlockly.Msg.LISTS_GET_INDEX_TAIL = '';\nBlockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item\n/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_START = 'Returns the item at the specified position in a list.  #1 is the first item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item\n/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM_END = 'Returns the item at the specified position in a list.  #1 is the last item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item\n/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = 'Returns the first item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item\n/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = 'Returns the last item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item\n/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for more information.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = 'Returns a random item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item]\n/// (for remove and return) and\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from start'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_START = 'Removes and returns the item at the specified position in a list.  #1 is the first item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from end'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM_END = 'Removes and returns the item at the specified position in a list.  #1 is the last item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'first'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = 'Removes and returns the first item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'last'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = 'Removes and returns the last item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'random'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = 'Removes and returns a random item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from start'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_START = 'Removes the item at the specified position in a list.  #1 is the first item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for '# from end'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM_END = 'Removes the item at the specified position in a list.  #1 is the last item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'first'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = 'Removes the first item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'last'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = 'Removes the last item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_and_removing_an_item] (for remove and return) and [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item] for 'random'.\nBlockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = 'Removes a random item in a list.';\n/// url - Information about putting items in lists.\nBlockly.Msg.LISTS_SET_INDEX_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#in_list_..._set';\nBlockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\n/// block text - [https://code.google.com/p/blockly/wiki/Lists#in_list_..._set\n/// Replaces an item in a list].\n/// [[File:Blockly-in-list-set-insert.png]]\nBlockly.Msg.LISTS_SET_INDEX_SET = 'set';\n/// block text - [https://code.google.com/p/blockly/wiki/Lists#in_list_..._insert_at\n/// Inserts an item into a list].\n/// [[File:Blockly-in-list-set-insert.png]]\nBlockly.Msg.LISTS_SET_INDEX_INSERT = 'insert at';\n/// block text - The word(s) after the position in the list and before the item to be set/inserted.\n/// [[File:Blockly-in-list-set-insert.png]]\nBlockly.Msg.LISTS_SET_INDEX_INPUT_TO = 'as';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"set\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_START = 'Sets the item at the specified position in a list.  #1 is the first item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"set\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM_END = 'Sets the item at the specified position in a list.  #1 is the last item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"set\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = 'Sets the first item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"set\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = 'Sets the last item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"set\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = 'Sets a random item in a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"insert\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_START = 'Inserts the item at the specified position in a list.  #1 is the first item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"insert\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM_END = 'Inserts the item at the specified position in a list.  #1 is the last item.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"insert\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = 'Inserts the item at the start of a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"insert\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = 'Append the item to the end of a list.';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_single_item} (even though the page describes the \"get\" block, the idea is the same for the \"insert\" block).\nBlockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = 'Inserts the item randomly in a list.';\n\n/// url - Information describing extracting a sublist from an existing list.\nBlockly.Msg.LISTS_GET_SUBLIST_HELPURL = 'https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist';\nBlockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST;\n/// dropdown - Indicates that an index relative to the front of the list should be used\n/// to specify the beginning of the range from which to\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist].\n/// [[File:Blockly-get-sublist.png]]\n/// Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will\n/// automatically appear ''after'' this number (and any other ordinal numbers on this block).\n/// See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly.\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = 'get sub-list from #';\n/// dropdown - Indicates that an index relative to the end of the list should be used\n/// to specify the beginning of the range from which to\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist].\nBlockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = 'get sub-list from # from end';\n/// dropdown - Indicates that the\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist sublist to extract]\n/// should begin with the list's first item.\nBlockly.Msg.LISTS_GET_SUBLIST_START_FIRST = 'get sub-list from first';\n/// dropdown - Indicates that an index relative to the front of the list should be\n/// used to specify the end of the range from which to\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist].\n/// [[File:Blockly-get-sublist.png]]\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = 'to #';\n/// dropdown - Indicates that an index relative to the end of the list should be\n/// used to specify the end of the range from which to\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist get a sublist].\n/// [[File:Blockly-get-sublist.png]]\nBlockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = 'to # from end';\n/// dropdown - Indicates that the '''last''' item in the given list should be\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist the end\n/// of the selected sublist].\n/// [[File:Blockly-get-sublist.png]]\nBlockly.Msg.LISTS_GET_SUBLIST_END_LAST = 'to last';\n/// block text - This appears in the rightmost position (\"tail\") of the\n/// sublist block, as described at\n/// [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\n/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist].\n/// In English and most other languages, this is the empty string.\n/// [[File:Blockly-get-sublist.png]]\nBlockly.Msg.LISTS_GET_SUBLIST_TAIL = '';\n/// tooltip - See [https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist\n/// https://code.google.com/p/blockly/wiki/Lists#Getting_a_sublist] for more information.\n/// [[File:Blockly-get-sublist.png]]\nBlockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = 'Creates a copy of the specified portion of a list.';\n\n/// grammar - Text that follows an ordinal number (a number that indicates\n/// position relative to other numbers).  In most languages, such text appears\n/// before the number, so this should be blank.  An exception is Hungarian.\n/// See [[Translating:Blockly#Ordinal_numbers]] for more information.\nBlockly.Msg.ORDINAL_NUMBER_SUFFIX = '';\n\n// Variables Blocks.\n/// url - Information about ''variables'' in computer programming.  Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists.\nBlockly.Msg.VARIABLES_GET_HELPURL = 'https://code.google.com/p/blockly/wiki/Variables#Get';\n/// block text - This precedes the name of a variable when getting its values.  In most (all?) languages, it should be the empty string.  If unsure, ask yourself if any word should go before \"x\" in the expression \"x + 1\".\nBlockly.Msg.VARIABLES_GET_TITLE = '';\nBlockly.Msg.VARIABLES_GET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\n/// block text - This follows the name of a variable.  In most (all?) languages, it should be the empty string.  If unsure, ask yourself if any word should go after \"x\" in the expression \"x + 1\".\nBlockly.Msg.VARIABLES_GET_TAIL = '';\n/// tooltip - This gets the value of the named variable without modifying it.\nBlockly.Msg.VARIABLES_GET_TOOLTIP = 'Returns the value of this variable.';\n/// context menu - Selecting this creates a block to set (change) the value of this variable.\n/// \\n\\nParameters:\\n* %1 - the name of the variable.\nBlockly.Msg.VARIABLES_GET_CREATE_SET = 'Create \"set %1\"';\n\n/// url - Information about ''variables'' in computer programming.  Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists.\nBlockly.Msg.VARIABLES_SET_HELPURL = 'https://code.google.com/p/blockly/wiki/Variables#Set';\n/// block text - The imperative or infinitive form of the verb \"set\", as in: '''set''' [the value of] x to 7.\nBlockly.Msg.VARIABLES_SET_TITLE = 'set';\nBlockly.Msg.VARIABLES_SET_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME;\n/// block text - The word that goes after the name of the variable and before its new\n/// value in: set [the value of] x '''to''' 7.\nBlockly.Msg.VARIABLES_SET_TAIL = 'to';\n/// tooltip - This initializes or changes the value of the named variable.\nBlockly.Msg.VARIABLES_SET_TOOLTIP = 'Sets this variable to be equal to the input.';\n/// context menu - Selecting this creates a block to get (change) the value of\n/// this variable.\\n\\nParameters:\\n* %1 - the name of the variable.\nBlockly.Msg.VARIABLES_SET_CREATE_GET = 'Create \"get %1\"';\n\n// Procedures Blocks.\n/// url - Information about defining [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not have return values.\nBlockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = 'https://en.wikipedia.org/wiki/Procedure_%28computer_science%29';\n/// block text - This precedes the name of the procedure when defining it.  See\n/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample\n/// procedure definition].\nBlockly.Msg.PROCEDURES_DEFNORETURN_TITLE = 'to';\n/// default name - This acts as a placeholder for the name of a function on a\n/// function definition block, as shown on\n/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#w7cfju this block].\n/// The user will replace it with the function's name.\nBlockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = 'do something';\n/// block text - This precedes the list of parameters to a function.  See\n/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample\n/// function with parameters].\nBlockly.Msg.PROCEDURES_BEFORE_PARAMS = 'with:';\n/// block text - This appears next to the function's \"body\", the blocks that should be\n/// run when the function is called, as shown in\n/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample\n/// procedure definition].\n\nBlockly.Msg.PROCEDURES_DEFNORETURN_DO = '';\n/// tooltip\nBlockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = 'Creates a function with no output.';\n\n/// url - Information about defining [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that have return values.\nBlockly.Msg.PROCEDURES_DEFRETURN_HELPURL = 'https://en.wikipedia.org/wiki/Procedure_%28computer_science%29';\nBlockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE;\nBlockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE;\nBlockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO;\n/// block text - This imperative or infinite verb precedes the value that is used as the return value\n/// (output) of this function.  See\n/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample\n/// function that returns a value].\n\nBlockly.Msg.PROCEDURES_DEFRETURN_RETURN = 'return';\n/// tooltip\nBlockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = 'Creates a function with an output.';\n\n/// alert - The user has created a function with two parameters that have the same name.  Every parameter must have a different name.\nBlockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = 'Warning: This function has duplicate parameters.';\n\n/// url - Information about calling [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not return values.\nBlockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = 'https://en.wikipedia.org/wiki/Procedure_%28computer_science%29';\n/// block text - In most (if not all) languages, this will be the empty string.\n/// It precedes the name of the function that should be run.  See, for example,\n/// the \"draw square\" block in [https://blockly-demo.appspot.com/static/apps/turtle/index.html#ztz96g].\nBlockly.Msg.PROCEDURES_CALLNORETURN_CALL = '';\n/// tooltip - This block causes the body (blocks inside) of the named function definition to be run.\nBlockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = 'Run the user-defined function \"%1\".';\n\n/// url - Information about calling [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that return values.\nBlockly.Msg.PROCEDURES_CALLRETURN_HELPURL = 'https://en.wikipedia.org/wiki/Procedure_%28computer_science%29';\nBlockly.Msg.PROCEDURES_CALLRETURN_CALL = Blockly.Msg.PROCEDURES_CALLNORETURN_CALL;\n/// tooltip - This block causes the body (blocks inside) of the named function definition to be run.\\n\\nParameters:\\n* %1 - the name of the function.\nBlockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = 'Run the user-defined function \"%1\" and use its output.';\n\n/// block text - This text appears on a block in a window that appears when the user clicks\n/// on the plus sign or star on a function definition block.  It refers to the set of parameters\n/// (referred to by the simpler term \"inputs\") to the function.  See\n/// [[Translating:Blockly#function_definitions]].\nBlockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = 'inputs';\n/// block text - This text appears on a block in a window that appears when the user clicks\n/// on the plus sign or star on a function definition block].  It appears on the block for\n/// adding an individual parameter (referred to by the simpler term \"inputs\") to the function.\n/// See [[Translating:Blockly#function_definitions]].\nBlockly.Msg.PROCEDURES_MUTATORARG_TITLE = 'input name:';\n\n/// context menu - This appears on the context menu for function calls.  Selecting\n/// it causes the corresponding function definition to be highlighted (as shown at\n/// [[Translating:Blockly#context_menus]].\nBlockly.Msg.PROCEDURES_HIGHLIGHT_DEF = 'Highlight function definition';\n/// context menu - This appears on the context menu for function definitions.\n/// Selecting it creates a block to call the function.  \\n\\nParameters:\\n* %1 - the name of the function.\nBlockly.Msg.PROCEDURES_CREATE_DO = 'Create \"%1\"';\n\n/// tooltip - If the first value is true, this causes the second value to be returned\n/// immediately from the enclosing function.\nBlockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = 'If a value is true, then return a second value.';\n/// warning - This appears if the user tries to use this block outside of a function definition.\nBlockly.Msg.PROCEDURES_IFRETURN_WARNING = 'Warning: This block may be used only within a function definition.';\n/// Context Menu Copy\nBlockly.Msg.CONTEXT_BLOCK_COPY = 'Copy';\n/// Context Menu Paste\nBlockly.Msg.CONTEXT_BLOCK_PASTE = 'Paste';\n"
  },
  {
    "path": "extern/blockly/python_compressed.js",
    "content": "// Do not edit this file; automatically generated by build.py.\n\"use strict\";\n\n\n// Copyright 2012 Google Inc.  Apache License 2.0\nBlockly.Python=new Blockly.Generator(\"Python\");Blockly.Python.addReservedWords(\"and,as,assert,break,class,continue,def,del,elif,else,except,exec,finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,return,try,while,with,yield,True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,coerce,dir,id,oct,sorted,intern\");\nBlockly.Python.ORDER_ATOMIC=0;Blockly.Python.ORDER_COLLECTION=1;Blockly.Python.ORDER_STRING_CONVERSION=1;Blockly.Python.ORDER_MEMBER=2;Blockly.Python.ORDER_FUNCTION_CALL=2;Blockly.Python.ORDER_EXPONENTIATION=3;Blockly.Python.ORDER_UNARY_SIGN=4;Blockly.Python.ORDER_BITWISE_NOT=4;Blockly.Python.ORDER_MULTIPLICATIVE=5;Blockly.Python.ORDER_ADDITIVE=6;Blockly.Python.ORDER_BITWISE_SHIFT=7;Blockly.Python.ORDER_BITWISE_AND=8;Blockly.Python.ORDER_BITWISE_XOR=9;Blockly.Python.ORDER_BITWISE_OR=10;\nBlockly.Python.ORDER_RELATIONAL=11;Blockly.Python.ORDER_LOGICAL_NOT=12;Blockly.Python.ORDER_LOGICAL_AND=13;Blockly.Python.ORDER_LOGICAL_OR=14;Blockly.Python.ORDER_CONDITIONAL=15;Blockly.Python.ORDER_LAMBDA=16;Blockly.Python.ORDER_NONE=99;Blockly.Python.INFINITE_LOOP_TRAP=null;\nBlockly.Python.init=function(){Blockly.Python.definitions_=Object.create(null);Blockly.Python.functionNames_=Object.create(null);if(Blockly.Variables){Blockly.Python.variableDB_?Blockly.Python.variableDB_.reset():Blockly.Python.variableDB_=new Blockly.Names(Blockly.Python.RESERVED_WORDS_);for(var a=[],b=Blockly.Variables.allVariables(),c=0;c<b.length;c++)a[c]=Blockly.Python.variableDB_.getName(b[c],Blockly.Variables.NAME_TYPE)+\" = None\";Blockly.Python.definitions_.variables=a.join(\"\\n\")}};\nBlockly.Python.finish=function(a){var b=[],c=[],d;for(d in Blockly.Python.definitions_){var e=Blockly.Python.definitions_[d];e.match(/^(from\\s+\\S+\\s+)?import\\s+\\S+/)?b.push(e):c.push(e)}return(b.join(\"\\n\")+\"\\n\\n\"+c.join(\"\\n\\n\")).replace(/\\n\\n+/g,\"\\n\\n\").replace(/\\n*$/,\"\\n\\n\\n\")+a};Blockly.Python.scrubNakedValue=function(a){return a+\"\\n\"};Blockly.Python.quote_=function(a){a=a.replace(/\\\\/g,\"\\\\\\\\\").replace(/\\n/g,\"\\\\\\n\").replace(/\\%/g,\"\\\\%\").replace(/'/g,\"\\\\'\");return\"'\"+a+\"'\"};\nBlockly.Python.scrub_=function(a,b){if(null===b)return\"\";var c=\"\";if(!a.outputConnection||!a.outputConnection.targetConnection){var d=a.getCommentText();d&&(c+=this.prefixLines(d,\"# \")+\"\\n\");for(var e=0;e<a.inputList.length;e++)a.inputList[e].type==Blockly.INPUT_VALUE&&(d=a.inputList[e].connection.targetBlock())&&(d=this.allNestedComments(d))&&(c+=this.prefixLines(d,\"# \"))}e=a.nextConnection&&a.nextConnection.targetBlock();e=this.blockToCode(e);return c+b+e};Blockly.Python.colour={};Blockly.Python.colour_picker=function(a){return[\"'\"+a.getFieldValue(\"COLOUR\")+\"'\",Blockly.Python.ORDER_ATOMIC]};Blockly.Python.colour_random=function(a){Blockly.Python.definitions_.import_random=\"import random\";return[\"'#%06x' % random.randint(0, 2**24 - 1)\",Blockly.Python.ORDER_FUNCTION_CALL]};\nBlockly.Python.colour_rgb=function(a){var b=Blockly.Python.provideFunction_(\"colour_rgb\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(r, g, b):\",\"  r = round(min(100, max(0, r)) * 2.55)\",\"  g = round(min(100, max(0, g)) * 2.55)\",\"  b = round(min(100, max(0, b)) * 2.55)\",\"  return '#%02x%02x%02x' % (r, g, b)\"]),c=Blockly.Python.valueToCode(a,\"RED\",Blockly.Python.ORDER_NONE)||0,d=Blockly.Python.valueToCode(a,\"GREEN\",Blockly.Python.ORDER_NONE)||0;a=Blockly.Python.valueToCode(a,\"BLUE\",Blockly.Python.ORDER_NONE)||\n0;return[b+\"(\"+c+\", \"+d+\", \"+a+\")\",Blockly.Python.ORDER_FUNCTION_CALL]};\nBlockly.Python.colour_blend=function(a){var b=Blockly.Python.provideFunction_(\"colour_blend\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(colour1, colour2, ratio):\",\"  r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)\",\"  g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)\",\"  b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)\",\"  ratio = min(1, max(0, ratio))\",\"  r = round(r1 * (1 - ratio) + r2 * ratio)\",\"  g = round(g1 * (1 - ratio) + g2 * ratio)\",\"  b = round(b1 * (1 - ratio) + b2 * ratio)\",\n\"  return '#%02x%02x%02x' % (r, g, b)\"]),c=Blockly.Python.valueToCode(a,\"COLOUR1\",Blockly.Python.ORDER_NONE)||\"'#000000'\",d=Blockly.Python.valueToCode(a,\"COLOUR2\",Blockly.Python.ORDER_NONE)||\"'#000000'\";a=Blockly.Python.valueToCode(a,\"RATIO\",Blockly.Python.ORDER_NONE)||0;return[b+\"(\"+c+\", \"+d+\", \"+a+\")\",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.lists={};Blockly.Python.lists_create_empty=function(a){return[\"[]\",Blockly.Python.ORDER_ATOMIC]};Blockly.Python.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c<a.itemCount_;c++)b[c]=Blockly.Python.valueToCode(a,\"ADD\"+c,Blockly.Python.ORDER_NONE)||\"None\";b=\"[\"+b.join(\", \")+\"]\";return[b,Blockly.Python.ORDER_ATOMIC]};\nBlockly.Python.lists_repeat=function(a){var b=Blockly.Python.valueToCode(a,\"ITEM\",Blockly.Python.ORDER_NONE)||\"None\";a=Blockly.Python.valueToCode(a,\"NUM\",Blockly.Python.ORDER_MULTIPLICATIVE)||\"0\";return[\"[\"+b+\"] * \"+a,Blockly.Python.ORDER_MULTIPLICATIVE]};Blockly.Python.lists_length=function(a){return[\"len(\"+(Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_NONE)||\"[]\")+\")\",Blockly.Python.ORDER_FUNCTION_CALL]};\nBlockly.Python.lists_isEmpty=function(a){return[\"not len(\"+(Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_NONE)||\"[]\")+\")\",Blockly.Python.ORDER_LOGICAL_NOT]};\nBlockly.Python.lists_indexOf=function(a){var b=Blockly.Python.valueToCode(a,\"FIND\",Blockly.Python.ORDER_NONE)||\"[]\",c=Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_MEMBER)||\"''\";return[(\"FIRST\"==a.getFieldValue(\"END\")?Blockly.Python.provideFunction_(\"first_index\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(myList, elem):\",\"  try: theIndex = myList.index(elem) + 1\",\"  except: theIndex = 0\",\"  return theIndex\"]):Blockly.Python.provideFunction_(\"last_index\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\n\"(myList, elem):\",\"  try: theIndex = len(myList) - myList[::-1].index(elem)\",\"  except: theIndex = 0\",\"  return theIndex\"]))+\"(\"+c+\", \"+b+\")\",Blockly.Python.ORDER_FUNCTION_CALL]};\nBlockly.Python.lists_getIndex=function(a){var b=a.getFieldValue(\"MODE\")||\"GET\",c=a.getFieldValue(\"WHERE\")||\"FROM_START\",d=Blockly.Python.valueToCode(a,\"AT\",Blockly.Python.ORDER_UNARY_SIGN)||\"1\";a=Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_MEMBER)||\"[]\";if(\"FIRST\"==c){if(\"GET\"==b)return[a+\"[0]\",Blockly.Python.ORDER_MEMBER];c=a+\".pop(0)\";if(\"GET_REMOVE\"==b)return[c,Blockly.Python.ORDER_FUNCTION_CALL];if(\"REMOVE\"==b)return c+\"\\n\"}else if(\"LAST\"==c){if(\"GET\"==b)return[a+\"[-1]\",Blockly.Python.ORDER_MEMBER];\nc=a+\".pop()\";if(\"GET_REMOVE\"==b)return[c,Blockly.Python.ORDER_FUNCTION_CALL];if(\"REMOVE\"==b)return c+\"\\n\"}else if(\"FROM_START\"==c){d=Blockly.isNumber(d)?parseInt(d,10)-1:\"int(\"+d+\" - 1)\";if(\"GET\"==b)return[a+\"[\"+d+\"]\",Blockly.Python.ORDER_MEMBER];c=a+\".pop(\"+d+\")\";if(\"GET_REMOVE\"==b)return[c,Blockly.Python.ORDER_FUNCTION_CALL];if(\"REMOVE\"==b)return c+\"\\n\"}else if(\"FROM_END\"==c){if(\"GET\"==b)return[a+\"[-\"+d+\"]\",Blockly.Python.ORDER_MEMBER];c=a+\".pop(-\"+d+\")\";if(\"GET_REMOVE\"==b)return[c,Blockly.Python.ORDER_FUNCTION_CALL];\nif(\"REMOVE\"==b)return c+\"\\n\"}else if(\"RANDOM\"==c){Blockly.Python.definitions_.import_random=\"import random\";if(\"GET\"==b)return[\"random.choice(\"+a+\")\",Blockly.Python.ORDER_FUNCTION_CALL];c=Blockly.Python.provideFunction_(\"lists_remove_random_item\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(myList):\",\"  x = int(random.random() * len(myList))\",\"  return myList.pop(x)\"])+\"(\"+a+\")\";if(\"GET_REMOVE\"==b)return[c,Blockly.Python.ORDER_FUNCTION_CALL];if(\"REMOVE\"==b)return c+\"\\n\"}throw\"Unhandled combination (lists_getIndex).\";\n};\nBlockly.Python.lists_setIndex=function(a){var b=Blockly.Python.valueToCode(a,\"LIST\",Blockly.Python.ORDER_MEMBER)||\"[]\",c=a.getFieldValue(\"MODE\")||\"GET\",d=a.getFieldValue(\"WHERE\")||\"FROM_START\",e=Blockly.Python.valueToCode(a,\"AT\",Blockly.Python.ORDER_NONE)||\"1\";a=Blockly.Python.valueToCode(a,\"TO\",Blockly.Python.ORDER_NONE)||\"None\";if(\"FIRST\"==d){if(\"SET\"==c)return b+\"[0] = \"+a+\"\\n\";if(\"INSERT\"==c)return b+\".insert(0, \"+a+\")\\n\"}else if(\"LAST\"==d){if(\"SET\"==c)return b+\"[-1] = \"+a+\"\\n\";if(\"INSERT\"==c)return b+\n\".append(\"+a+\")\\n\"}else if(\"FROM_START\"==d){e=Blockly.isNumber(e)?parseInt(e,10)-1:\"int(\"+e+\" - 1)\";if(\"SET\"==c)return b+\"[\"+e+\"] = \"+a+\"\\n\";if(\"INSERT\"==c)return b+\".insert(\"+e+\", \"+a+\")\\n\"}else if(\"FROM_END\"==d){if(\"SET\"==c)return b+\"[-\"+e+\"] = \"+a+\"\\n\";if(\"INSERT\"==c)return b+\".insert(-\"+e+\", \"+a+\")\\n\"}else if(\"RANDOM\"==d){Blockly.Python.definitions_.import_random=\"import random\";b.match(/^\\w+$/)?d=\"\":(d=Blockly.Python.variableDB_.getDistinctName(\"tmp_list\",Blockly.Variables.NAME_TYPE),e=d+\" = \"+\nb+\"\\n\",b=d,d=e);e=Blockly.Python.variableDB_.getDistinctName(\"tmp_x\",Blockly.Variables.NAME_TYPE);d+=e+\" = int(random.random() * len(\"+b+\"))\\n\";if(\"SET\"==c)return d+(b+\"[\"+e+\"] = \"+a+\"\\n\");if(\"INSERT\"==c)return d+(b+\".insert(\"+e+\", \"+a+\")\\n\")}throw\"Unhandled combination (lists_setIndex).\";};\nBlockly.Python.lists_getSublist=function(a){var b=Blockly.Python.valueToCode(a,\"LIST\",Blockly.Python.ORDER_MEMBER)||\"[]\",c=a.getFieldValue(\"WHERE1\"),d=a.getFieldValue(\"WHERE2\"),e=Blockly.Python.valueToCode(a,\"AT1\",Blockly.Python.ORDER_ADDITIVE)||\"1\";a=Blockly.Python.valueToCode(a,\"AT2\",Blockly.Python.ORDER_ADDITIVE)||\"1\";\"FIRST\"==c||\"FROM_START\"==c&&\"1\"==e?e=\"\":\"FROM_START\"==c?e=Blockly.isNumber(e)?parseInt(e,10)-1:\"int(\"+e+\" - 1)\":\"FROM_END\"==c&&(e=Blockly.isNumber(e)?-parseInt(e,10):\"-int(\"+e+\")\");\n\"LAST\"==d||\"FROM_END\"==d&&\"1\"==a?a=\"\":\"FROM_START\"==c?a=Blockly.isNumber(a)?parseInt(a,10):\"int(\"+a+\")\":\"FROM_END\"==c&&(Blockly.isNumber(a)?(a=1-parseInt(a,10),0==a&&(a=\"\")):(Blockly.Python.definitions_.import_sys=\"import sys\",a=\"int(1 - \"+a+\") or sys.maxsize\"));return[b+\"[\"+e+\" : \"+a+\"]\",Blockly.Python.ORDER_MEMBER]};Blockly.Python.logic={};Blockly.Python.controls_if=function(a){for(var b=0,c=Blockly.Python.valueToCode(a,\"IF\"+b,Blockly.Python.ORDER_NONE)||\"False\",d=Blockly.Python.statementToCode(a,\"DO\"+b)||\"  pass\\n\",e=\"if \"+c+\":\\n\"+d,b=1;b<=a.elseifCount_;b++)c=Blockly.Python.valueToCode(a,\"IF\"+b,Blockly.Python.ORDER_NONE)||\"False\",d=Blockly.Python.statementToCode(a,\"DO\"+b)||\"  pass\\n\",e+=\"elif \"+c+\":\\n\"+d;a.elseCount_&&(d=Blockly.Python.statementToCode(a,\"ELSE\")||\"  pass\\n\",e+=\"else:\\n\"+d);return e};\nBlockly.Python.logic_compare=function(a){var b={EQ:\"==\",NEQ:\"!=\",LT:\"<\",LTE:\"<=\",GT:\">\",GTE:\">=\"}[a.getFieldValue(\"OP\")],c=Blockly.Python.ORDER_RELATIONAL,d=Blockly.Python.valueToCode(a,\"A\",c)||\"0\";a=Blockly.Python.valueToCode(a,\"B\",c)||\"0\";return[d+\" \"+b+\" \"+a,c]};\nBlockly.Python.logic_operation=function(a){var b=\"AND\"==a.getFieldValue(\"OP\")?\"and\":\"or\",c=\"and\"==b?Blockly.Python.ORDER_LOGICAL_AND:Blockly.Python.ORDER_LOGICAL_OR,d=Blockly.Python.valueToCode(a,\"A\",c);a=Blockly.Python.valueToCode(a,\"B\",c);if(d||a){var e=\"and\"==b?\"True\":\"False\";d||(d=e);a||(a=e)}else a=d=\"False\";return[d+\" \"+b+\" \"+a,c]};Blockly.Python.logic_negate=function(a){return[\"not \"+(Blockly.Python.valueToCode(a,\"BOOL\",Blockly.Python.ORDER_LOGICAL_NOT)||\"True\"),Blockly.Python.ORDER_LOGICAL_NOT]};\nBlockly.Python.logic_boolean=function(a){return[\"TRUE\"==a.getFieldValue(\"BOOL\")?\"True\":\"False\",Blockly.Python.ORDER_ATOMIC]};Blockly.Python.logic_null=function(a){return[\"None\",Blockly.Python.ORDER_ATOMIC]};\nBlockly.Python.logic_ternary=function(a){var b=Blockly.Python.valueToCode(a,\"IF\",Blockly.Python.ORDER_CONDITIONAL)||\"False\",c=Blockly.Python.valueToCode(a,\"THEN\",Blockly.Python.ORDER_CONDITIONAL)||\"None\";a=Blockly.Python.valueToCode(a,\"ELSE\",Blockly.Python.ORDER_CONDITIONAL)||\"None\";return[c+\" if \"+b+\" else \"+a,Blockly.Python.ORDER_CONDITIONAL]};Blockly.Python.loops={};Blockly.Python.controls_repeat=function(a){var b=parseInt(a.getFieldValue(\"TIMES\"),10),c=Blockly.Python.statementToCode(a,\"DO\")||\"  pass\\n\";Blockly.Python.INFINITE_LOOP_TRAP&&(c=Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+c);return\"for \"+Blockly.Python.variableDB_.getDistinctName(\"count\",Blockly.Variables.NAME_TYPE)+\" in range(\"+b+\"):\\n\"+c};\nBlockly.Python.controls_repeat_ext=function(a){var b=Blockly.Python.valueToCode(a,\"TIMES\",Blockly.Python.ORDER_NONE)||\"0\",b=Blockly.isNumber(b)?parseInt(b,10):\"int(\"+b+\")\",c=Blockly.Python.statementToCode(a,\"DO\")||\"  pass\\n\";Blockly.Python.INFINITE_LOOP_TRAP&&(c=Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,\"'\"+a.id+\"'\")+c);return\"for \"+Blockly.Python.variableDB_.getDistinctName(\"count\",Blockly.Variables.NAME_TYPE)+\" in range(\"+b+\"):\\n\"+c};\nBlockly.Python.controls_whileUntil=function(a){var b=\"UNTIL\"==a.getFieldValue(\"MODE\"),c=Blockly.Python.valueToCode(a,\"BOOL\",b?Blockly.Python.ORDER_LOGICAL_NOT:Blockly.Python.ORDER_NONE)||\"False\",d=Blockly.Python.statementToCode(a,\"DO\")||\"  pass\\n\";Blockly.Python.INFINITE_LOOP_TRAP&&(d=Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,'\"'+a.id+'\"')+d);b&&(c=\"not \"+c);return\"while \"+c+\":\\n\"+d};\nBlockly.Python.controls_for=function(a){var b=Blockly.Python.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),c=Blockly.Python.valueToCode(a,\"FROM\",Blockly.Python.ORDER_NONE)||\"0\",d=Blockly.Python.valueToCode(a,\"TO\",Blockly.Python.ORDER_NONE)||\"0\",e=Blockly.Python.valueToCode(a,\"BY\",Blockly.Python.ORDER_NONE)||\"1\",g=Blockly.Python.statementToCode(a,\"DO\")||\"  pass\\n\";Blockly.Python.INFINITE_LOOP_TRAP&&(g=Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,'\"'+a.id+'\"')+g);var f=\n\"\",h=function(){return Blockly.Python.provideFunction_(\"upRange\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(start, stop, step):\",\"  while start <= stop:\",\"    yield start\",\"    start += abs(step)\"])},k=function(){return Blockly.Python.provideFunction_(\"downRange\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(start, stop, step):\",\"  while start >= stop:\",\"    yield start\",\"    start -= abs(step)\"])};a=function(a,b,c){return\"(\"+a+\" <= \"+b+\") and \"+h()+\"(\"+a+\", \"+b+\", \"+c+\") or \"+k()+\n\"(\"+a+\", \"+b+\", \"+c+\")\"};if(Blockly.isNumber(c)&&Blockly.isNumber(d)&&Blockly.isNumber(e))c=parseFloat(c),d=parseFloat(d),e=Math.abs(parseFloat(e)),0===c%1&&0===d%1&&0===e%1?(c<=d?(d++,a=0==c&&1==e?d:c+\", \"+d,1!=e&&(a+=\", \"+e)):(d--,a=c+\", \"+d+\", -\"+e),a=\"range(\"+a+\")\"):(a=c<d?h():k(),a+=\"(\"+c+\", \"+d+\", \"+e+\")\");else{var l=function(a,c){if(Blockly.isNumber(a))a=parseFloat(a);else if(a.match(/^\\w+$/))a=\"float(\"+a+\")\";else{var d=Blockly.Python.variableDB_.getDistinctName(b+c,Blockly.Variables.NAME_TYPE);\nf+=d+\" = float(\"+a+\")\\n\";a=d}return a},c=l(c,\"_start\"),d=l(d,\"_end\");l(e,\"_inc\");a=\"number\"==typeof c&&\"number\"==typeof d?c<d?h(c,d,e):k(c,d,e):a(c,d,e)}return f+=\"for \"+b+\" in \"+a+\":\\n\"+g};\nBlockly.Python.controls_forEach=function(a){var b=Blockly.Python.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),c=Blockly.Python.valueToCode(a,\"LIST\",Blockly.Python.ORDER_RELATIONAL)||\"[]\",d=Blockly.Python.statementToCode(a,\"DO\")||\"  pass\\n\";Blockly.Python.INFINITE_LOOP_TRAP&&(d=Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,'\"'+a.id+'\"')+d);return\"for \"+b+\" in \"+c+\":\\n\"+d};\nBlockly.Python.controls_flow_statements=function(a){switch(a.getFieldValue(\"FLOW\")){case \"BREAK\":return\"break\\n\";case \"CONTINUE\":return\"continue\\n\"}throw\"Unknown flow statement.\";};Blockly.Python.math={};Blockly.Python.addReservedWords(\"math,random\");Blockly.Python.math_number=function(a){a=parseFloat(a.getFieldValue(\"NUM\"));return[a,0>a?Blockly.Python.ORDER_UNARY_SIGN:Blockly.Python.ORDER_ATOMIC]};\nBlockly.Python.math_arithmetic=function(a){var b={ADD:[\" + \",Blockly.Python.ORDER_ADDITIVE],MINUS:[\" - \",Blockly.Python.ORDER_ADDITIVE],MULTIPLY:[\" * \",Blockly.Python.ORDER_MULTIPLICATIVE],DIVIDE:[\" / \",Blockly.Python.ORDER_MULTIPLICATIVE],POWER:[\" ** \",Blockly.Python.ORDER_EXPONENTIATION]}[a.getFieldValue(\"OP\")],c=b[0],b=b[1],d=Blockly.Python.valueToCode(a,\"A\",b)||\"0\";a=Blockly.Python.valueToCode(a,\"B\",b)||\"0\";return[d+c+a,b]};\nBlockly.Python.math_single=function(a){var b=a.getFieldValue(\"OP\"),c;if(\"NEG\"==b)return c=Blockly.Python.valueToCode(a,\"NUM\",Blockly.Python.ORDER_UNARY_SIGN)||\"0\",[\"-\"+c,Blockly.Python.ORDER_UNARY_SIGN];Blockly.Python.definitions_.import_math=\"import math\";a=\"SIN\"==b||\"COS\"==b||\"TAN\"==b?Blockly.Python.valueToCode(a,\"NUM\",Blockly.Python.ORDER_MULTIPLICATIVE)||\"0\":Blockly.Python.valueToCode(a,\"NUM\",Blockly.Python.ORDER_NONE)||\"0\";switch(b){case \"ABS\":c=\"math.fabs(\"+a+\")\";break;case \"ROOT\":c=\"math.sqrt(\"+\na+\")\";break;case \"LN\":c=\"math.log(\"+a+\")\";break;case \"LOG10\":c=\"math.log10(\"+a+\")\";break;case \"EXP\":c=\"math.exp(\"+a+\")\";break;case \"POW10\":c=\"math.pow(10,\"+a+\")\";break;case \"ROUND\":c=\"round(\"+a+\")\";break;case \"ROUNDUP\":c=\"math.ceil(\"+a+\")\";break;case \"ROUNDDOWN\":c=\"math.floor(\"+a+\")\";break;case \"SIN\":c=\"math.sin(\"+a+\" / 180.0 * math.pi)\";break;case \"COS\":c=\"math.cos(\"+a+\" / 180.0 * math.pi)\";break;case \"TAN\":c=\"math.tan(\"+a+\" / 180.0 * math.pi)\"}if(c)return[c,Blockly.Python.ORDER_FUNCTION_CALL];switch(b){case \"ASIN\":c=\n\"math.asin(\"+a+\") / math.pi * 180\";break;case \"ACOS\":c=\"math.acos(\"+a+\") / math.pi * 180\";break;case \"ATAN\":c=\"math.atan(\"+a+\") / math.pi * 180\";break;default:throw\"Unknown math operator: \"+b;}return[c,Blockly.Python.ORDER_MULTIPLICATIVE]};\nBlockly.Python.math_constant=function(a){var b={PI:[\"math.pi\",Blockly.Python.ORDER_MEMBER],E:[\"math.e\",Blockly.Python.ORDER_MEMBER],GOLDEN_RATIO:[\"(1 + math.sqrt(5)) / 2\",Blockly.Python.ORDER_MULTIPLICATIVE],SQRT2:[\"math.sqrt(2)\",Blockly.Python.ORDER_MEMBER],SQRT1_2:[\"math.sqrt(1.0 / 2)\",Blockly.Python.ORDER_MEMBER],INFINITY:[\"float('inf')\",Blockly.Python.ORDER_ATOMIC]};a=a.getFieldValue(\"CONSTANT\");\"INFINITY\"!=a&&(Blockly.Python.definitions_.import_math=\"import math\");return b[a]};\nBlockly.Python.math_number_property=function(a){var b=Blockly.Python.valueToCode(a,\"NUMBER_TO_CHECK\",Blockly.Python.ORDER_MULTIPLICATIVE)||\"0\",c=a.getFieldValue(\"PROPERTY\"),d;if(\"PRIME\"==c)return Blockly.Python.definitions_.import_math=\"import math\",[Blockly.Python.provideFunction_(\"math_isPrime\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(n):\",\"  # https://en.wikipedia.org/wiki/Primality_test#Naive_methods\",\"  # If n is not a number but a string, try parsing it.\",\"  if type(n) not in (int, float, long):\",\n\"    try:\",\"      n = float(n)\",\"    except:\",\"      return False\",\"  if n == 2 or n == 3:\",\"    return True\",\"  # False if n is negative, is 1, or not whole, or if n is divisible by 2 or 3.\",\"  if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:\",\"    return False\",\"  # Check all the numbers of form 6k +/- 1, up to sqrt(n).\",\"  for x in range(6, int(math.sqrt(n)) + 2, 6):\",\"    if n % (x - 1) == 0 or n % (x + 1) == 0:\",\"      return False\",\"  return True\"])+\"(\"+b+\")\",Blockly.Python.ORDER_FUNCTION_CALL];\nswitch(c){case \"EVEN\":d=b+\" % 2 == 0\";break;case \"ODD\":d=b+\" % 2 == 1\";break;case \"WHOLE\":d=b+\" % 1 == 0\";break;case \"POSITIVE\":d=b+\" > 0\";break;case \"NEGATIVE\":d=b+\" < 0\";break;case \"DIVISIBLE_BY\":a=Blockly.Python.valueToCode(a,\"DIVISOR\",Blockly.Python.ORDER_MULTIPLICATIVE);if(!a||\"0\"==a)return[\"False\",Blockly.Python.ORDER_ATOMIC];d=b+\" % \"+a+\" == 0\"}return[d,Blockly.Python.ORDER_RELATIONAL]};\nBlockly.Python.math_change=function(a){var b=Blockly.Python.valueToCode(a,\"DELTA\",Blockly.Python.ORDER_ADDITIVE)||\"0\";a=Blockly.Python.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE);return a+\" = (\"+a+\" if type(\"+a+\") in (int, float, long) else 0) + \"+b+\"\\n\"};Blockly.Python.math_round=Blockly.Python.math_single;Blockly.Python.math_trig=Blockly.Python.math_single;\nBlockly.Python.math_on_list=function(a){var b=a.getFieldValue(\"OP\");a=Blockly.Python.valueToCode(a,\"LIST\",Blockly.Python.ORDER_NONE)||\"[]\";switch(b){case \"SUM\":b=\"sum(\"+a+\")\";break;case \"MIN\":b=\"min(\"+a+\")\";break;case \"MAX\":b=\"max(\"+a+\")\";break;case \"AVERAGE\":b=Blockly.Python.provideFunction_(\"math_mean\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(myList):\",\"  localList = [e for e in myList if type(e) in (int, float, long)]\",\"  if not localList: return\",\"  return float(sum(localList)) / len(localList)\"]);\nb=b+\"(\"+a+\")\";break;case \"MEDIAN\":b=Blockly.Python.provideFunction_(\"math_median\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(myList):\",\"  localList = sorted([e for e in myList if type(e) in (int, float, long)])\",\"  if not localList: return\",\"  if len(localList) % 2 == 0:\",\"    return (localList[len(localList) / 2 - 1] + localList[len(localList) / 2]) / 2.0\",\"  else:\",\"    return localList[(len(localList) - 1) / 2]\"]);b=b+\"(\"+a+\")\";break;case \"MODE\":b=Blockly.Python.provideFunction_(\"math_modes\",\n[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(some_list):\",\"  modes = []\",\"  # Using a lists of [item, count] to keep count rather than dict\",'  # to avoid \"unhashable\" errors when the counted item is itself a list or dict.',\"  counts = []\",\"  maxCount = 1\",\"  for item in some_list:\",\"    found = False\",\"    for count in counts:\",\"      if count[0] == item:\",\"        count[1] += 1\",\"        maxCount = max(maxCount, count[1])\",\"        found = True\",\"    if not found:\",\"      counts.append([item, 1])\",\n\"  for counted_item, item_count in counts:\",\"    if item_count == maxCount:\",\"      modes.append(counted_item)\",\"  return modes\"]);b=b+\"(\"+a+\")\";break;case \"STD_DEV\":Blockly.Python.definitions_.import_math=\"import math\";b=Blockly.Python.provideFunction_(\"math_standard_deviation\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(numbers):\",\"  n = len(numbers)\",\"  if n == 0: return\",\"  mean = float(sum(numbers)) / n\",\"  variance = sum((x - mean) ** 2 for x in numbers) / n\",\"  return math.sqrt(variance)\"]);\nb=b+\"(\"+a+\")\";break;case \"RANDOM\":Blockly.Python.definitions_.import_random=\"import random\";b=\"random.choice(\"+a+\")\";break;default:throw\"Unknown operator: \"+b;}return[b,Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.math_modulo=function(a){var b=Blockly.Python.valueToCode(a,\"DIVIDEND\",Blockly.Python.ORDER_MULTIPLICATIVE)||\"0\";a=Blockly.Python.valueToCode(a,\"DIVISOR\",Blockly.Python.ORDER_MULTIPLICATIVE)||\"0\";return[b+\" % \"+a,Blockly.Python.ORDER_MULTIPLICATIVE]};\nBlockly.Python.math_constrain=function(a){var b=Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_NONE)||\"0\",c=Blockly.Python.valueToCode(a,\"LOW\",Blockly.Python.ORDER_NONE)||\"0\";a=Blockly.Python.valueToCode(a,\"HIGH\",Blockly.Python.ORDER_NONE)||\"float('inf')\";return[\"min(max(\"+b+\", \"+c+\"), \"+a+\")\",Blockly.Python.ORDER_FUNCTION_CALL]};\nBlockly.Python.math_random_int=function(a){Blockly.Python.definitions_.import_random=\"import random\";var b=Blockly.Python.valueToCode(a,\"FROM\",Blockly.Python.ORDER_NONE)||\"0\";a=Blockly.Python.valueToCode(a,\"TO\",Blockly.Python.ORDER_NONE)||\"0\";return[\"random.randint(\"+b+\", \"+a+\")\",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.math_random_float=function(a){Blockly.Python.definitions_.import_random=\"import random\";return[\"random.random()\",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.procedures={};\nBlockly.Python.procedures_defreturn=function(a){for(var b=Blockly.Variables.allVariables(a),c=b.length-1;0<=c;c--){var d=b[c];-1==a.arguments_.indexOf(d)?b[c]=Blockly.Python.variableDB_.getName(d,Blockly.Variables.NAME_TYPE):b.splice(c,1)}b=b.length?\"  global \"+b.join(\", \")+\"\\n\":\"\";c=Blockly.Python.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE);d=Blockly.Python.statementToCode(a,\"STACK\");Blockly.Python.INFINITE_LOOP_TRAP&&(d=Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,'\"'+\na.id+'\"')+d);var e=Blockly.Python.valueToCode(a,\"RETURN\",Blockly.Python.ORDER_NONE)||\"\";e?e=\"  return \"+e+\"\\n\":d||(d=\"  pass\");for(var g=[],f=0;f<a.arguments_.length;f++)g[f]=Blockly.Python.variableDB_.getName(a.arguments_[f],Blockly.Variables.NAME_TYPE);b=\"def \"+c+\"(\"+g.join(\", \")+\"):\\n\"+b+d+e;b=Blockly.Python.scrub_(a,b);Blockly.Python.definitions_[c]=b;return null};Blockly.Python.procedures_defnoreturn=Blockly.Python.procedures_defreturn;\nBlockly.Python.procedures_callreturn=function(a){for(var b=Blockly.Python.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE),c=[],d=0;d<a.arguments_.length;d++)c[d]=Blockly.Python.valueToCode(a,\"ARG\"+d,Blockly.Python.ORDER_NONE)||\"None\";return[b+\"(\"+c.join(\", \")+\")\",Blockly.Python.ORDER_FUNCTION_CALL]};\nBlockly.Python.procedures_callnoreturn=function(a){for(var b=Blockly.Python.variableDB_.getName(a.getFieldValue(\"NAME\"),Blockly.Procedures.NAME_TYPE),c=[],d=0;d<a.arguments_.length;d++)c[d]=Blockly.Python.valueToCode(a,\"ARG\"+d,Blockly.Python.ORDER_NONE)||\"None\";return b+\"(\"+c.join(\", \")+\")\\n\"};\nBlockly.Python.procedures_ifreturn=function(a){var b=\"if \"+(Blockly.Python.valueToCode(a,\"CONDITION\",Blockly.Python.ORDER_NONE)||\"False\")+\":\\n\";a.hasReturnValue_?(a=Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_NONE)||\"None\",b+=\"  return \"+a+\"\\n\"):b+=\"  return\\n\";return b};Blockly.Python.text={};Blockly.Python.text=function(a){return[Blockly.Python.quote_(a.getFieldValue(\"TEXT\")),Blockly.Python.ORDER_ATOMIC]};\nBlockly.Python.text_join=function(a){var b;if(0==a.itemCount_)return[\"''\",Blockly.Python.ORDER_ATOMIC];if(1==a.itemCount_)return b=Blockly.Python.valueToCode(a,\"ADD0\",Blockly.Python.ORDER_NONE)||\"''\",[\"str(\"+b+\")\",Blockly.Python.ORDER_FUNCTION_CALL];if(2==a.itemCount_)return b=Blockly.Python.valueToCode(a,\"ADD0\",Blockly.Python.ORDER_NONE)||\"''\",a=Blockly.Python.valueToCode(a,\"ADD1\",Blockly.Python.ORDER_NONE)||\"''\",[\"str(\"+b+\") + str(\"+a+\")\",Blockly.Python.ORDER_UNARY_SIGN];b=[];for(var c=0;c<a.itemCount_;c++)b[c]=\nBlockly.Python.valueToCode(a,\"ADD\"+c,Blockly.Python.ORDER_NONE)||\"''\";a=Blockly.Python.variableDB_.getDistinctName(\"temp_value\",Blockly.Variables.NAME_TYPE);b=\"''.join([str(\"+a+\") for \"+a+\" in [\"+b.join(\", \")+\"]])\";return[b,Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.text_append=function(a){var b=Blockly.Python.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE);a=Blockly.Python.valueToCode(a,\"TEXT\",Blockly.Python.ORDER_NONE)||\"''\";return b+\" = str(\"+b+\") + str(\"+a+\")\\n\"};\nBlockly.Python.text_length=function(a){return[\"len(\"+(Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_NONE)||\"''\")+\")\",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.text_isEmpty=function(a){return[\"not len(\"+(Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_NONE)||\"''\")+\")\",Blockly.Python.ORDER_LOGICAL_NOT]};\nBlockly.Python.text_indexOf=function(a){var b=\"FIRST\"==a.getFieldValue(\"END\")?\"find\":\"rfind\",c=Blockly.Python.valueToCode(a,\"FIND\",Blockly.Python.ORDER_NONE)||\"''\";return[(Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_MEMBER)||\"''\")+\".\"+b+\"(\"+c+\") + 1\",Blockly.Python.ORDER_MEMBER]};\nBlockly.Python.text_charAt=function(a){var b=a.getFieldValue(\"WHERE\")||\"FROM_START\",c=Blockly.Python.valueToCode(a,\"AT\",Blockly.Python.ORDER_UNARY_SIGN)||\"1\";a=Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_MEMBER)||\"''\";switch(b){case \"FIRST\":return[a+\"[0]\",Blockly.Python.ORDER_MEMBER];case \"LAST\":return[a+\"[-1]\",Blockly.Python.ORDER_MEMBER];case \"FROM_START\":return c=Blockly.isNumber(c)?parseInt(c,10)-1:\"int(\"+c+\" - 1)\",[a+\"[\"+c+\"]\",Blockly.Python.ORDER_MEMBER];case \"FROM_END\":return[a+\n\"[-\"+c+\"]\",Blockly.Python.ORDER_MEMBER];case \"RANDOM\":return Blockly.Python.definitions_.import_random=\"import random\",[Blockly.Python.provideFunction_(\"text_random_letter\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(text):\",\"  x = int(random.random() * len(text))\",\"  return text[x];\"])+\"(\"+a+\")\",Blockly.Python.ORDER_FUNCTION_CALL]}throw\"Unhandled option (text_charAt).\";};\nBlockly.Python.text_getSubstring=function(a){var b=Blockly.Python.valueToCode(a,\"STRING\",Blockly.Python.ORDER_MEMBER)||\"''\",c=a.getFieldValue(\"WHERE1\"),d=a.getFieldValue(\"WHERE2\"),e=Blockly.Python.valueToCode(a,\"AT1\",Blockly.Python.ORDER_ADDITIVE)||\"1\";a=Blockly.Python.valueToCode(a,\"AT2\",Blockly.Python.ORDER_ADDITIVE)||\"1\";\"FIRST\"==c||\"FROM_START\"==c&&\"1\"==e?e=\"\":\"FROM_START\"==c?e=Blockly.isNumber(e)?parseInt(e,10)-1:\"int(\"+e+\" - 1)\":\"FROM_END\"==c&&(e=Blockly.isNumber(e)?-parseInt(e,10):\"-int(\"+\ne+\")\");\"LAST\"==d||\"FROM_END\"==d&&\"1\"==a?a=\"\":\"FROM_START\"==c?a=Blockly.isNumber(a)?parseInt(a,10):\"int(\"+a+\")\":\"FROM_END\"==c&&(Blockly.isNumber(a)?(a=1-parseInt(a,10),0==a&&(a=\"\")):(Blockly.Python.definitions_.import_sys=\"import sys\",a=\"int(1 - \"+a+\") or sys.maxsize\"));return[b+\"[\"+e+\" : \"+a+\"]\",Blockly.Python.ORDER_MEMBER]};\nBlockly.Python.text_changeCase=function(a){var b={UPPERCASE:\".upper()\",LOWERCASE:\".lower()\",TITLECASE:\".title()\"}[a.getFieldValue(\"CASE\")];return[(Blockly.Python.valueToCode(a,\"TEXT\",Blockly.Python.ORDER_MEMBER)||\"''\")+b,Blockly.Python.ORDER_MEMBER]};Blockly.Python.text_trim=function(a){var b={LEFT:\".lstrip()\",RIGHT:\".rstrip()\",BOTH:\".strip()\"}[a.getFieldValue(\"MODE\")];return[(Blockly.Python.valueToCode(a,\"TEXT\",Blockly.Python.ORDER_MEMBER)||\"''\")+b,Blockly.Python.ORDER_MEMBER]};\nBlockly.Python.text_print=function(a){return\"print(\"+(Blockly.Python.valueToCode(a,\"TEXT\",Blockly.Python.ORDER_NONE)||\"''\")+\")\\n\"};Blockly.Python.text_prompt=function(a){var b=Blockly.Python.provideFunction_(\"text_prompt\",[\"def \"+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+\"(msg):\",\"  try:\",\"    return raw_input(msg)\",\"  except NameError:\",\"    return input(msg)\"]),c=Blockly.Python.quote_(a.getFieldValue(\"TEXT\")),b=b+\"(\"+c+\")\";\"NUMBER\"==a.getFieldValue(\"TYPE\")&&(b=\"float(\"+b+\")\");return[b,Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.variables={};Blockly.Python.variables_get=function(a){return[Blockly.Python.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE),Blockly.Python.ORDER_ATOMIC]};Blockly.Python.variables_set=function(a){var b=Blockly.Python.valueToCode(a,\"VALUE\",Blockly.Python.ORDER_NONE)||\"0\";return Blockly.Python.variableDB_.getName(a.getFieldValue(\"VAR\"),Blockly.Variables.NAME_TYPE)+\" = \"+b+\"\\n\"};"
  },
  {
    "path": "extern/blockly/tests/blockly_test.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <title>Unit tests for Blockly</title>\n    <script type=\"text/javascript\" src=\"../../closure-library-read-only/closure/goog/base.js\"></script>\n    <script type=\"text/javascript\">goog.require('goog.testing.jsunit');</script>\n    <script type=\"text/javascript\" src=\"../blockly_uncompressed.js\"></script>\n  </head>\n  <body>\n    <script type=\"text/javascript\" src=\"blockly_test.js\"></script>\n    <script type=\"text/javascript\" src=\"generator_test.js\"></script>\n    <script type=\"text/javascript\" src=\"names_test.js\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "extern/blockly/tests/blockly_test.js",
    "content": "/**\n * Visual Blocks Editor\n *\n * Copyright 2011 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use strict';\n\nfunction verify_DB_(msg, expected, db) {\n   var equal = (expected.length == db.length);\n   if (equal) {\n     for (var x = 0; x < expected.length; x++) {\n       if (expected[x] != db[x]) {\n         equal = false;\n         break;\n       }\n     }\n   }\n   if (equal) {\n     assertTrue(msg, true);\n   } else {\n     assertEquals(msg, expected, db);\n   }\n}\n\nfunction test_DB_addConnection() {\n  var db = new Blockly.ConnectionDB();\n  var o2 = {y_: 2};\n  db.addConnection_(o2);\n  verify_DB_('Adding connection #2', [o2], db);\n\n  var o4 = {y_: 4};\n  db.addConnection_(o4);\n  verify_DB_('Adding connection #4', [o2, o4], db);\n\n  var o1 = {y_: 1};\n  db.addConnection_(o1);\n  verify_DB_('Adding connection #1', [o1, o2, o4], db);\n\n  var o3a = {y_: 3};\n  db.addConnection_(o3a);\n  verify_DB_('Adding connection #3a', [o1, o2, o3a, o4], db);\n\n  var o3b = {y_: 3};\n  db.addConnection_(o3b);\n  verify_DB_('Adding connection #3b', [o1, o2, o3b, o3a, o4], db);\n}\n\nfunction test_DB_removeConnection() {\n  var db = new Blockly.ConnectionDB();\n  var o1 = {y_: 1};\n  var o2 = {y_: 2};\n  var o3a = {y_: 3};\n  var o3b = {y_: 3};\n  var o3c = {y_: 3};\n  var o4 = {y_: 4};\n  db.addConnection_(o1);\n  db.addConnection_(o2);\n  db.addConnection_(o3c);\n  db.addConnection_(o3b);\n  db.addConnection_(o3a);\n  db.addConnection_(o4);\n  verify_DB_('Adding connections 1-4', [o1, o2, o3a, o3b, o3c, o4], db);\n\n  db.removeConnection_(o2);\n  verify_DB_('Removing connection #2', [o1, o3a, o3b, o3c, o4], db);\n\n  db.removeConnection_(o4);\n  verify_DB_('Removing connection #4', [o1, o3a, o3b, o3c], db);\n\n  db.removeConnection_(o1);\n  verify_DB_('Removing connection #1', [o3a, o3b, o3c], db);\n\n  db.removeConnection_(o3a);\n  verify_DB_('Removing connection #3a', [o3b, o3c], db);\n\n  db.removeConnection_(o3c);\n  verify_DB_('Removing connection #3c', [o3b], db);\n\n  db.removeConnection_(o3b);\n  verify_DB_('Removing connection #3b', [], db);\n}\n\nfunction test_addClass() {\n  var p = document.createElement('p');\n  Blockly.addClass_(p, 'one');\n  assertEquals('Adding \"one\"', 'one', p.className);\n  Blockly.addClass_(p, 'one');\n  assertEquals('Adding duplicate \"one\"', 'one', p.className);\n  Blockly.addClass_(p, 'two');\n  assertEquals('Adding \"two\"', 'one two', p.className);\n  Blockly.addClass_(p, 'two');\n  assertEquals('Adding duplicate \"two\"', 'one two', p.className);\n  Blockly.addClass_(p, 'three');\n  assertEquals('Adding \"three\"', 'one two three', p.className);\n}\n\nfunction test_removeClass() {\n  var p = document.createElement('p');\n  p.className = ' one three  two three  ';\n  Blockly.removeClass_(p, 'two');\n  assertEquals('Removing \"two\"', 'one three three', p.className);\n  Blockly.removeClass_(p, 'four');\n  assertEquals('Removing \"four\"', 'one three three', p.className);\n  Blockly.removeClass_(p, 'three');\n  assertEquals('Removing \"three\"', 'one', p.className);\n  Blockly.removeClass_(p, 'ne');\n  assertEquals('Removing \"ne\"', 'one', p.className);\n  Blockly.removeClass_(p, 'one');\n  assertEquals('Removing \"one\"', '', p.className);\n  Blockly.removeClass_(p, 'zero');\n  assertEquals('Removing \"zero\"', '', p.className);\n}\n\nfunction test_shortestStringLength() {\n  var len = Blockly.shortestStringLength('one,two,three,four,five'.split(','));\n  assertEquals('Length of \"one\"', 3, len);\n  len = Blockly.shortestStringLength('one,two,three,four,five,'.split(','));\n  assertEquals('Length of \"\"', 0, len);\n  len = Blockly.shortestStringLength(['Hello World']);\n  assertEquals('List of one', 11, len);\n  len = Blockly.shortestStringLength([]);\n  assertEquals('Empty list', 0, len);\n}\n\nfunction test_commonWordPrefix() {\n  var len = Blockly.commonWordPrefix('one,two,three,four,five'.split(','));\n  assertEquals('No prefix', 0, len);\n  len = Blockly.commonWordPrefix('Xone,Xtwo,Xthree,Xfour,Xfive'.split(','));\n  assertEquals('No word prefix', 0, len);\n  len = Blockly.commonWordPrefix('abc de,abc de,abc de,abc de'.split(','));\n  assertEquals('Full equality', 6, len);\n  len = Blockly.commonWordPrefix('abc deX,abc deY'.split(','));\n  assertEquals('One word prefix', 4, len);\n  len = Blockly.commonWordPrefix('abc de,abc deY'.split(','));\n  assertEquals('Overflow no', 4, len);\n  len = Blockly.commonWordPrefix('abc de,abc de Y'.split(','));\n  assertEquals('Overflow yes', 6, len);\n  len = Blockly.commonWordPrefix(['Hello World']);\n  assertEquals('List of one', 11, len);\n  len = Blockly.commonWordPrefix([]);\n  assertEquals('Empty list', 0, len);\n  len = Blockly.commonWordPrefix('turn&nbsp;left,turn&nbsp;right'.split(','));\n  assertEquals('No prefix due to &amp;nbsp;', 0, len);\n  len = Blockly.commonWordPrefix('turn\\u00A0left,turn\\u00A0right'.split(','));\n  assertEquals('No prefix due to \\\\u00A0', 0, len);\n}\n\nfunction test_commonWordSuffix() {\n  var len = Blockly.commonWordSuffix('one,two,three,four,five'.split(','));\n  assertEquals('No prefix', 0, len);\n  len = Blockly.commonWordSuffix('oneX,twoX,threeX,fourX,fiveX'.split(','));\n  assertEquals('No word prefix', 0, len);\n  len = Blockly.commonWordSuffix('abc de,abc de,abc de,abc de'.split(','));\n  assertEquals('Full equality', 6, len);\n  len = Blockly.commonWordSuffix('Xabc de,Yabc de'.split(','));\n  assertEquals('One word prefix', 3, len);\n  len = Blockly.commonWordSuffix('abc de,Yabc de'.split(','));\n  assertEquals('Overflow no', 3, len);\n  len = Blockly.commonWordSuffix('abc de,Y abc de'.split(','));\n  assertEquals('Overflow yes', 6, len);\n  len = Blockly.commonWordSuffix(['Hello World']);\n  assertEquals('List of one', 11, len);\n  len = Blockly.commonWordSuffix([]);\n  assertEquals('Empty list', 0, len);\n}\n"
  },
  {
    "path": "extern/blockly/tests/generator_test.js",
    "content": "/**\n * Blockly Tests\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use strict';\n\nfunction test_prefix() {\n  var generator = new Blockly.Generator('INTERCAL');\n  assertEquals('Prefix nothing.', '', generator.prefixLines('', ''));\n  assertEquals('Prefix a word.', '@Hello', generator.prefixLines('Hello', '@'));\n  assertEquals('Prefix one line.', '12Hello\\n', generator.prefixLines('Hello\\n', '12'));\n  assertEquals('Prefix two lines.', '***Hello\\n***World\\n', generator.prefixLines('Hello\\nWorld\\n', '***'));\n}\n"
  },
  {
    "path": "extern/blockly/tests/generators/colour.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"procedures_defnoreturn\" x=\"630\" y=\"13\">\n    <mutation></mutation>\n    <field name=\"NAME\">test rgb</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">from rgb</field>\n        <value name=\"ACTUAL\">\n          <block type=\"colour_rgb\" inline=\"false\">\n            <value name=\"RED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">100</field>\n              </block>\n            </value>\n            <value name=\"GREEN\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">40</field>\n              </block>\n            </value>\n            <value name=\"BLUE\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">0</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"text\">\n            <field name=\"TEXT\">#ff6600</field>\n          </block>\n        </value>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"260\" y=\"14\">\n    <mutation></mutation>\n    <field name=\"NAME\">test colour picker</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">static colour</field>\n        <value name=\"ACTUAL\">\n          <block type=\"colour_picker\">\n            <field name=\"COLOUR\">#ff6600</field>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"text\">\n            <field name=\"TEXT\">#ff6600</field>\n          </block>\n        </value>\n      </block>\n    </statement>\n  </block>\n  <block type=\"unittest_main\" x=\"-5\" y=\"49\">\n    <statement name=\"DO\">\n      <block type=\"procedures_callnoreturn\">\n        <mutation name=\"test colour picker\"></mutation>\n        <next>\n          <block type=\"procedures_callnoreturn\">\n            <mutation name=\"test blend\"></mutation>\n            <next>\n              <block type=\"procedures_callnoreturn\">\n                <mutation name=\"test rgb\"></mutation>\n                <next>\n                  <block type=\"procedures_callnoreturn\">\n                    <mutation name=\"test colour random\"></mutation>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"520\" y=\"205\">\n    <mutation></mutation>\n    <field name=\"NAME\">test blend</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">blend</field>\n        <value name=\"ACTUAL\">\n          <block type=\"colour_blend\" inline=\"false\">\n            <value name=\"COLOUR1\">\n              <block type=\"colour_picker\">\n                <field name=\"COLOUR\">#ff0000</field>\n              </block>\n            </value>\n            <value name=\"COLOUR2\">\n              <block type=\"colour_rgb\" inline=\"false\">\n                <value name=\"RED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">100</field>\n                  </block>\n                </value>\n                <value name=\"GREEN\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">40</field>\n                  </block>\n                </value>\n                <value name=\"BLUE\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">0</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"RATIO\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">0.4</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"text\">\n            <field name=\"TEXT\">#ff2900</field>\n          </block>\n        </value>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-7\" y=\"223\">\n    <mutation></mutation>\n    <field name=\"NAME\">test colour random</field>\n    <statement name=\"STACK\">\n      <block type=\"controls_repeat_ext\" inline=\"true\">\n        <value name=\"TIMES\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">100</field>\n          </block>\n        </value>\n        <statement name=\"DO\">\n          <block type=\"variables_set\" inline=\"false\">\n            <field name=\"VAR\">item</field>\n            <value name=\"VALUE\">\n              <block type=\"colour_random\"></block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">test name</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"text_length\" inline=\"false\">\n                    <value name=\"VALUE\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">item</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">7</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">test name</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"text_charAt\" inline=\"true\">\n                        <mutation at=\"false\"></mutation>\n                        <field name=\"WHERE\">FIRST</field>\n                        <value name=\"VALUE\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">item</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">#</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"controls_for\" inline=\"true\">\n                        <field name=\"VAR\">i</field>\n                        <value name=\"FROM\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">2</field>\n                          </block>\n                        </value>\n                        <value name=\"TO\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">7</field>\n                          </block>\n                        </value>\n                        <statement name=\"DO\">\n                          <block type=\"unittest_assertvalue\" inline=\"false\">\n                            <field name=\"MESSAGE\">test name</field>\n                            <field name=\"EXPECTED\">TRUE</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"logic_compare\" inline=\"true\">\n                                <field name=\"OP\">NEQ</field>\n                                <value name=\"A\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">0</field>\n                                  </block>\n                                </value>\n                                <value name=\"B\">\n                                  <block type=\"text_indexOf\" inline=\"false\">\n                                    <field name=\"END\">FIRST</field>\n                                    <value name=\"VALUE\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">abcdefABDEF0123456789</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"FIND\">\n                                      <block type=\"text_charAt\" inline=\"true\">\n                                        <mutation at=\"true\"></mutation>\n                                        <field name=\"WHERE\">FROM_START</field>\n                                        <value name=\"VALUE\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">item</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"AT\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">i</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                          </block>\n                        </statement>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </statement>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<title>Blockly Generator Test</title>\n<script type=\"text/javascript\" src=\"../../blockly_uncompressed.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript.js\"></script>\n<script type=\"text/javascript\" src=\"unittest_javascript.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript/logic.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript/loops.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript/math.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript/text.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript/lists.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript/colour.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript/variables.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/javascript/procedures.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python.js\"></script>\n<script type=\"text/javascript\" src=\"unittest_python.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python/logic.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python/loops.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python/math.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python/text.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python/lists.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python/colour.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python/variables.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/python/procedures.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart.js\"></script>\n<script type=\"text/javascript\" src=\"unittest_dart.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart/logic.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart/loops.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart/math.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart/text.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart/lists.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart/colour.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart/variables.js\"></script>\n<script type=\"text/javascript\" src=\"../../generators/dart/procedures.js\"></script>\n<script type=\"text/javascript\" src=\"unittest.js\"></script>\n<script type=\"text/javascript\" src=\"../../msg/messages.js\"></script>\n<script type=\"text/javascript\" src=\"../../blocks/logic.js\"></script>\n<script type=\"text/javascript\" src=\"../../blocks/loops.js\"></script>\n<script type=\"text/javascript\" src=\"../../blocks/math.js\"></script>\n<script type=\"text/javascript\" src=\"../../blocks/text.js\"></script>\n<script type=\"text/javascript\" src=\"../../blocks/lists.js\"></script>\n<script type=\"text/javascript\" src=\"../../blocks/colour.js\"></script>\n<script type=\"text/javascript\" src=\"../../blocks/variables.js\"></script>\n<script type=\"text/javascript\" src=\"../../blocks/procedures.js\"></script>\n<script type=\"text/javascript\">\n'use strict';\n\nfunction start() {\n  var toolbox = document.getElementById('toolbox');\n  Blockly.inject(document.getElementById('svg'),\n                 {path: '../../', toolbox: toolbox});\n}\n\nfunction loadXml() {\n  var dropdown = document.getElementById('testUrl');\n  var url = dropdown.options[dropdown.selectedIndex].value;\n  if (!url) {\n    url = window.prompt('Enter URL of test file.');\n    if (!url) {\n      return;\n    }\n  }\n  var xmlText = fetchFile(url);\n  if (xmlText !== null) {\n    fromXml(xmlText);\n  }\n}\n\nfunction fetchFile(xmlUrl) {\n  try {\n    var xmlHttp = new XMLHttpRequest();\n    xmlHttp.open('GET', xmlUrl, false);\n    xmlHttp.setRequestHeader('Content-Type', 'text/xml');\n    xmlHttp.send('');\n  } catch (e) {\n    // Attempt to diagnose the problem.\n    var msg = 'Error: Unable to load XML data.\\n';\n    if (window.location.protocol == 'file:') {\n      msg += 'This may be due to a security restriction preventing\\n' +\n          'access when using the file:// protocol.\\n' +\n          'Use an http webserver, or a less paranoid browser.\\n';\n    }\n    alert(msg + '\\n' + e);\n    return null;\n  }\n  return xmlHttp.responseText;\n}\n\nfunction fromXml(xmlText) {\n  var output = document.getElementById('importExport');\n  output.value = xmlText;\n  Blockly.mainWorkspace.clear();\n  try {\n    var xmlDoc = Blockly.Xml.textToDom(xmlText);\n  } catch (e) {\n    alert('Error parsing XML:\\n' + e);\n    return;\n  }\n  Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xmlDoc);\n}\n\nfunction setOutput(text) {\n  var output = document.getElementById('importExport');\n  output.value = text;\n  output.focus();\n  output.select();\n}\n\nfunction toXml() {\n  var xmlDom = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);\n  var xmlText = Blockly.Xml.domToPrettyText(xmlDom);\n  setOutput(xmlText);\n}\n\nfunction toJavaScript() {\n  var code = '\\'use strict\\';\\n\\n'\n  code += Blockly.JavaScript.workspaceToCode();\n  setOutput(code);\n}\n\nfunction toPython() {\n  var code = Blockly.Python.workspaceToCode();\n  setOutput(code);\n}\n\nfunction toDart() {\n  var code = Blockly.Dart.workspaceToCode();\n  setOutput(code);\n}\n</script>\n\n<style>\nhtml, body {\n  height: 100%;\n  overflow: hidden;\n}\nbody {\n  background-color: #fff;\n  font-family: sans-serif;\n  margin: 0 5px;\n}\nh1 {\n  font-weight: normal;\n  font-size: 140%;\n}\n#svg {\n  float: right;\n  height: 95%;\n  width: 69%;\n  margin-top: 5px;\n}\n.blocklySvg {\n  border: 1px solid #000;\n}\n#importExport {\n  height: 100%;\n  width: 100%;\n}\n</style>\n</head>\n<body onload=\"start()\">\n\n  <div id=\"svg\"></div>\n\n  <xml id=\"toolbox\" style=\"display: none\">\n    <category name=\"Unit test\">\n      <block type=\"unittest_main\"></block>\n      <block type=\"unittest_assertequals\"></block>\n      <block type=\"unittest_assertvalue\"></block>\n      <block type=\"unittest_fail\"></block>\n    </category>\n    <category name=\"Logic\">\n      <block type=\"controls_if\"></block>\n      <block type=\"logic_compare\"></block>\n      <block type=\"logic_operation\"></block>\n      <block type=\"logic_negate\"></block>\n      <block type=\"logic_boolean\"></block>\n      <block type=\"logic_null\"></block>\n      <block type=\"logic_ternary\"></block>\n    </category>\n    <category name=\"Loops\">\n      <block type=\"controls_repeat_ext\">\n        <value name=\"TIMES\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">10</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"controls_whileUntil\"></block>\n      <block type=\"controls_for\">\n        <value name=\"FROM\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n        <value name=\"TO\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">10</field>\n          </block>\n        </value>\n        <value name=\"BY\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"controls_forEach\"></block>\n      <block type=\"controls_flow_statements\"></block>\n    </category>\n    <category name=\"Math\">\n      <block type=\"math_number\"></block>\n      <block type=\"math_arithmetic\"></block>\n      <block type=\"math_single\"></block>\n      <block type=\"math_trig\"></block>\n      <block type=\"math_constant\"></block>\n      <block type=\"math_number_property\"></block>\n      <block type=\"math_change\">\n        <value name=\"DELTA\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"math_round\"></block>\n      <block type=\"math_on_list\"></block>\n      <block type=\"math_modulo\"></block>\n      <block type=\"math_constrain\">\n        <value name=\"LOW\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n        <value name=\"HIGH\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">100</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"math_random_int\">\n        <value name=\"FROM\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n        <value name=\"TO\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">100</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"math_random_float\"></block>\n    </category>\n    <category name=\"Text\">\n      <block type=\"text\"></block>\n      <block type=\"text_join\"></block>\n      <block type=\"text_append\">\n        <value name=\"TEXT\">\n          <block type=\"text\"></block>\n        </value>\n      </block>\n      <block type=\"text_length\"></block>\n      <block type=\"text_isEmpty\"></block>\n      <block type=\"text_indexOf\">\n        <value name=\"VALUE\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">text</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"text_charAt\">\n        <value name=\"VALUE\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">text</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"text_getSubstring\">\n        <value name=\"STRING\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">text</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"text_changeCase\"></block>\n      <block type=\"text_trim\"></block>\n      <block type=\"text_print\"></block>\n      <block type=\"text_prompt\"></block>\n    </category>\n    <category name=\"Lists\">\n      <block type=\"lists_create_empty\"></block>\n      <block type=\"lists_create_with\"></block>\n      <block type=\"lists_repeat\">\n        <value name=\"NUM\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">5</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"lists_length\"></block>\n      <block type=\"lists_isEmpty\"></block>\n      <block type=\"lists_indexOf\">\n        <value name=\"VALUE\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">list</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"lists_getIndex\">\n        <value name=\"VALUE\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">list</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"lists_setIndex\">\n        <value name=\"LIST\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">list</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"lists_getSublist\">\n        <value name=\"LIST\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">list</field>\n          </block>\n        </value>\n      </block>\n    </category>\n    <category name=\"Colour\">\n      <block type=\"colour_picker\"></block>\n      <block type=\"colour_random\"></block>\n      <block type=\"colour_rgb\"></block>\n      <block type=\"colour_blend\"></block>\n    </category>\n    <category name=\"Variables\" custom=\"VARIABLE\"></category>\n    <category name=\"Functions\" custom=\"PROCEDURE\"></category>\n  </xml>\n\n  <table height=\"95%\" width=\"30%\"><tr><td valign=\"top\">\n    <h1>Blockly Generator Test</h1>\n\n    <p>\n      <select id=\"testUrl\">\n        <option value=\"logic.xml\">Logic</option>\n        <option value=\"loops1.xml\">Loops 1 (repeat, while, foreach)</option>\n        <option value=\"loops2.xml\">Loops 2 (count)</option>\n        <option value=\"loops3.xml\">Loops 3 (continue, break)</option>\n        <option value=\"math.xml\">Math</option>\n        <option value=\"text.xml\">Text</option>\n        <option value=\"lists.xml\">Lists</option>\n        <option value=\"colour.xml\">Colour</option>\n        <option value=\"variables.xml\">Variables</option>\n        <option value=\"procedures.xml\">Procedures</option>\n        <option value=\"\">Other...</option>\n      </select>\n      <input type=\"button\" value=\"Load\" onclick=\"loadXml()\">\n    </p>\n\n    <p>\n      Generate:\n      <input type=\"button\" value=\"XML\" onclick=\"toXml()\">\n      <input type=\"button\" value=\"JavaScript\" onclick=\"toJavaScript()\">\n      <input type=\"button\" value=\"Python\" onclick=\"toPython()\">\n      <input type=\"button\" value=\"Dart\" onclick=\"toDart()\">\n    </p>\n  </td></tr><tr><td height=\"99%\">\n    <textarea id=\"importExport\" readonly=\"readonly\" wrap=\"off\"></textarea>\n  </td></tr></table>\n</body>\n</html>\n"
  },
  {
    "path": "extern/blockly/tests/generators/lists.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"unittest_main\" x=\"0\" y=\"1\">\n    <statement name=\"DO\">\n      <block type=\"procedures_callnoreturn\">\n        <mutation name=\"test empty\"></mutation>\n        <next>\n          <block type=\"procedures_callnoreturn\">\n            <mutation name=\"test length\"></mutation>\n            <next>\n              <block type=\"procedures_callnoreturn\">\n                <mutation name=\"test find\"></mutation>\n                <next>\n                  <block type=\"procedures_callnoreturn\">\n                    <mutation name=\"test get\"></mutation>\n                    <next>\n                      <block type=\"procedures_callnoreturn\">\n                        <mutation name=\"test get remove\"></mutation>\n                        <next>\n                          <block type=\"procedures_callnoreturn\">\n                            <mutation name=\"test remove\"></mutation>\n                            <next>\n                              <block type=\"procedures_callnoreturn\">\n                                <mutation name=\"test set\"></mutation>\n                                <next>\n                                  <block type=\"procedures_callnoreturn\">\n                                    <mutation name=\"test insert\"></mutation>\n                                    <next>\n                                      <block type=\"procedures_callnoreturn\">\n                                        <mutation name=\"test sublist\"></mutation>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"36\" y=\"439\">\n    <mutation></mutation>\n    <field name=\"NAME\">test create</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">test create empty</field>\n        <value name=\"ACTUAL\">\n          <block type=\"lists_create_with\">\n            <mutation items=\"0\"></mutation>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"lists_create_empty\"></block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">test create items</field>\n            <value name=\"ACTUAL\">\n              <block type=\"lists_create_with\" inline=\"false\">\n                <mutation items=\"2\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">TRUE</field>\n                  </block>\n                </value>\n                <value name=\"ADD1\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">love</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"lists_create_with\" inline=\"false\">\n                <mutation items=\"2\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">TRUE</field>\n                  </block>\n                </value>\n                <value name=\"ADD1\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">love</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">test create repeated</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"lists_repeat\" inline=\"true\">\n                    <value name=\"ITEM\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Eject</field>\n                      </block>\n                    </value>\n                    <value name=\"NUM\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">3</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"lists_create_with\" inline=\"false\">\n                    <mutation items=\"3\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Eject</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Eject</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD2\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Eject</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"33\" y=\"965\">\n    <mutation></mutation>\n    <field name=\"NAME\">test empty</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertvalue\" inline=\"false\">\n        <field name=\"MESSAGE\">not empty</field>\n        <field name=\"EXPECTED\">FALSE</field>\n        <value name=\"ACTUAL\">\n          <block type=\"lists_isEmpty\" inline=\"false\">\n            <value name=\"VALUE\">\n              <block type=\"lists_create_with\" inline=\"false\">\n                <mutation items=\"1\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">0</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">empty</field>\n            <field name=\"EXPECTED\">TRUE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"lists_isEmpty\" inline=\"false\">\n                <value name=\"VALUE\">\n                  <block type=\"lists_create_empty\"></block>\n                </value>\n              </block>\n            </value>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"25\" y=\"1181\">\n    <mutation></mutation>\n    <field name=\"NAME\">test length</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">zero length</field>\n        <value name=\"ACTUAL\">\n          <block type=\"lists_length\" inline=\"false\">\n            <value name=\"VALUE\">\n              <block type=\"lists_create_empty\"></block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">0</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">one length</field>\n            <value name=\"ACTUAL\">\n              <block type=\"lists_length\" inline=\"false\">\n                <value name=\"VALUE\">\n                  <block type=\"lists_create_with\" inline=\"false\">\n                    <mutation items=\"1\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">cat</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">1</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">three length</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"lists_length\" inline=\"false\">\n                    <value name=\"VALUE\">\n                      <block type=\"lists_create_with\" inline=\"false\">\n                        <mutation items=\"3\"></mutation>\n                        <value name=\"ADD0\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">cat</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD1\">\n                          <block type=\"logic_boolean\">\n                            <field name=\"BOOL\">TRUE</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD2\">\n                          <block type=\"lists_create_empty\"></block>\n                        </value>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">3</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"24\" y=\"1556\">\n    <mutation></mutation>\n    <field name=\"NAME\">test find</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">find first</field>\n        <value name=\"ACTUAL\">\n          <block type=\"lists_indexOf\" inline=\"false\">\n            <field name=\"END\">FIRST</field>\n            <value name=\"VALUE\">\n              <block type=\"lists_create_with\" inline=\"false\">\n                <mutation items=\"4\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Alice</field>\n                  </block>\n                </value>\n                <value name=\"ADD1\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Eve</field>\n                  </block>\n                </value>\n                <value name=\"ADD2\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Bob</field>\n                  </block>\n                </value>\n                <value name=\"ADD3\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Eve</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"FIND\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Eve</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">2</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">find last</field>\n            <value name=\"ACTUAL\">\n              <block type=\"lists_indexOf\" inline=\"false\">\n                <field name=\"END\">LAST</field>\n                <value name=\"VALUE\">\n                  <block type=\"lists_create_with\" inline=\"false\">\n                    <mutation items=\"4\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Alice</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Eve</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD2\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Bob</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD3\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Eve</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"FIND\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Eve</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">4</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">find none</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"lists_indexOf\" inline=\"false\">\n                    <field name=\"END\">FIRST</field>\n                    <value name=\"VALUE\">\n                      <block type=\"lists_create_with\" inline=\"false\">\n                        <mutation items=\"4\"></mutation>\n                        <value name=\"ADD0\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Alice</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD1\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Bob</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD2\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Carol</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD3\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Dave</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"FIND\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Eve</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">0</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"25\" y=\"2199\">\n    <mutation></mutation>\n    <field name=\"NAME\">test get</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">list</field>\n        <value name=\"VALUE\">\n          <block type=\"lists_create_with\" inline=\"false\">\n            <mutation items=\"3\"></mutation>\n            <value name=\"ADD0\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Kirk</field>\n              </block>\n            </value>\n            <value name=\"ADD1\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Spock</field>\n              </block>\n            </value>\n            <value name=\"ADD2\">\n              <block type=\"text\">\n                <field name=\"TEXT\">McCoy</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">get first</field>\n            <value name=\"ACTUAL\">\n              <block type=\"lists_getIndex\" inline=\"true\">\n                <mutation statement=\"false\" at=\"false\"></mutation>\n                <field name=\"MODE\">GET</field>\n                <field name=\"WHERE\">FIRST</field>\n                <value name=\"VALUE\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">list</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Kirk</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">get last</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"lists_getIndex\" inline=\"true\">\n                    <mutation statement=\"false\" at=\"false\"></mutation>\n                    <field name=\"MODE\">GET</field>\n                    <field name=\"WHERE\">LAST</field>\n                    <value name=\"VALUE\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">list</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">McCoy</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                    <field name=\"MESSAGE\">get random</field>\n                    <field name=\"EXPECTED\">TRUE</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"math_number_property\" inline=\"true\">\n                        <mutation divisor_input=\"false\"></mutation>\n                        <field name=\"PROPERTY\">POSITIVE</field>\n                        <value name=\"NUMBER_TO_CHECK\">\n                          <block type=\"lists_indexOf\" inline=\"false\">\n                            <field name=\"END\">FIRST</field>\n                            <value name=\"VALUE\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">list</field>\n                              </block>\n                            </value>\n                            <value name=\"FIND\">\n                              <block type=\"lists_getIndex\" inline=\"true\">\n                                <mutation statement=\"false\" at=\"false\"></mutation>\n                                <field name=\"MODE\">GET</field>\n                                <field name=\"WHERE\">RANDOM</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"variables_get\">\n                                    <field name=\"VAR\">list</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">get #</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"lists_getIndex\" inline=\"true\">\n                            <mutation statement=\"false\" at=\"true\"></mutation>\n                            <field name=\"MODE\">GET</field>\n                            <field name=\"WHERE\">FROM_START</field>\n                            <value name=\"VALUE\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">list</field>\n                              </block>\n                            </value>\n                            <value name=\"AT\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">2</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Spock</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">get #-end</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"lists_getIndex\" inline=\"true\">\n                                <mutation statement=\"false\" at=\"true\"></mutation>\n                                <field name=\"MODE\">GET</field>\n                                <field name=\"WHERE\">FROM_END</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"variables_get\">\n                                    <field name=\"VAR\">list</field>\n                                  </block>\n                                </value>\n                                <value name=\"AT\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">3</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"text\">\n                                <field name=\"TEXT\">Kirk</field>\n                              </block>\n                            </value>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"23\" y=\"2832\">\n    <mutation></mutation>\n    <field name=\"NAME\">test get remove</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">list</field>\n        <value name=\"VALUE\">\n          <block type=\"lists_create_with\" inline=\"false\">\n            <mutation items=\"3\"></mutation>\n            <value name=\"ADD0\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Kirk</field>\n              </block>\n            </value>\n            <value name=\"ADD1\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Spock</field>\n              </block>\n            </value>\n            <value name=\"ADD2\">\n              <block type=\"text\">\n                <field name=\"TEXT\">McCoy</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">getremove first</field>\n            <value name=\"ACTUAL\">\n              <block type=\"lists_getIndex\" inline=\"true\">\n                <mutation statement=\"false\" at=\"false\"></mutation>\n                <field name=\"MODE\">GET_REMOVE</field>\n                <field name=\"WHERE\">FIRST</field>\n                <value name=\"VALUE\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">list</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Kirk</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">getremove first list</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">list</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"lists_create_with\" inline=\"false\">\n                    <mutation items=\"2\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Spock</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">McCoy</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">list</field>\n                    <value name=\"VALUE\">\n                      <block type=\"lists_create_with\" inline=\"false\">\n                        <mutation items=\"3\"></mutation>\n                        <value name=\"ADD0\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Kirk</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD1\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Spock</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD2\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">McCoy</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">getremove last</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"lists_getIndex\" inline=\"true\">\n                            <mutation statement=\"false\" at=\"false\"></mutation>\n                            <field name=\"MODE\">GET_REMOVE</field>\n                            <field name=\"WHERE\">LAST</field>\n                            <value name=\"VALUE\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">list</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">McCoy</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">getremove last list</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">list</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"lists_create_with\" inline=\"false\">\n                                <mutation items=\"2\"></mutation>\n                                <value name=\"ADD0\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Kirk</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD1\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Spock</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"variables_set\" inline=\"false\">\n                                <field name=\"VAR\">list</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"lists_create_with\" inline=\"false\">\n                                    <mutation items=\"3\"></mutation>\n                                    <value name=\"ADD0\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Kirk</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"ADD1\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Spock</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"ADD2\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">McCoy</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                                    <field name=\"MESSAGE\">getremove random</field>\n                                    <field name=\"EXPECTED\">TRUE</field>\n                                    <value name=\"ACTUAL\">\n                                      <block type=\"logic_compare\" inline=\"true\">\n                                        <field name=\"OP\">EQ</field>\n                                        <value name=\"A\">\n                                          <block type=\"lists_indexOf\" inline=\"false\">\n                                            <field name=\"END\">FIRST</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">list</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"FIND\">\n                                              <block type=\"lists_getIndex\" inline=\"true\">\n                                                <mutation statement=\"false\" at=\"false\"></mutation>\n                                                <field name=\"MODE\">GET_REMOVE</field>\n                                                <field name=\"WHERE\">RANDOM</field>\n                                                <value name=\"VALUE\">\n                                                  <block type=\"variables_get\">\n                                                    <field name=\"VAR\">list</field>\n                                                  </block>\n                                                </value>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <value name=\"B\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">0</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"unittest_assertequals\" inline=\"false\">\n                                        <field name=\"MESSAGE\">getremove random list</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"lists_length\" inline=\"false\">\n                                            <value name=\"VALUE\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">list</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <value name=\"EXPECTED\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">2</field>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"variables_set\" inline=\"false\">\n                                            <field name=\"VAR\">list</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"lists_create_with\" inline=\"false\">\n                                                <mutation items=\"3\"></mutation>\n                                                <value name=\"ADD0\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Kirk</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD1\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Spock</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD2\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">McCoy</field>\n                                                  </block>\n                                                </value>\n                                              </block>\n                                            </value>\n                                            <next>\n                                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                                <field name=\"MESSAGE\">getremove #</field>\n                                                <value name=\"ACTUAL\">\n                                                  <block type=\"lists_getIndex\" inline=\"true\">\n                                                    <mutation statement=\"false\" at=\"true\"></mutation>\n                                                    <field name=\"MODE\">GET_REMOVE</field>\n                                                    <field name=\"WHERE\">FROM_START</field>\n                                                    <value name=\"VALUE\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">list</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"AT\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">2</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <value name=\"EXPECTED\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Spock</field>\n                                                  </block>\n                                                </value>\n                                                <next>\n                                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                                    <field name=\"MESSAGE\">getremove # list</field>\n                                                    <value name=\"ACTUAL\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">list</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"EXPECTED\">\n                                                      <block type=\"lists_create_with\" inline=\"false\">\n                                                        <mutation items=\"2\"></mutation>\n                                                        <value name=\"ADD0\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Kirk</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD1\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">McCoy</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </value>\n                                                    <next>\n                                                      <block type=\"variables_set\" inline=\"false\">\n                                                        <field name=\"VAR\">list</field>\n                                                        <value name=\"VALUE\">\n                                                          <block type=\"lists_create_with\" inline=\"false\">\n                                                            <mutation items=\"3\"></mutation>\n                                                            <value name=\"ADD0\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Kirk</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD1\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Spock</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD2\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">McCoy</field>\n                                                              </block>\n                                                            </value>\n                                                          </block>\n                                                        </value>\n                                                        <next>\n                                                          <block type=\"unittest_assertequals\" inline=\"false\">\n                                                            <field name=\"MESSAGE\">getremove #-end</field>\n                                                            <value name=\"ACTUAL\">\n                                                              <block type=\"lists_getIndex\" inline=\"true\">\n                                                                <mutation statement=\"false\" at=\"true\"></mutation>\n                                                                <field name=\"MODE\">GET_REMOVE</field>\n                                                                <field name=\"WHERE\">FROM_END</field>\n                                                                <value name=\"VALUE\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">list</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"AT\">\n                                                                  <block type=\"math_number\">\n                                                                    <field name=\"NUM\">3</field>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"EXPECTED\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Kirk</field>\n                                                              </block>\n                                                            </value>\n                                                            <next>\n                                                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                                                <field name=\"MESSAGE\">getremove #-end list</field>\n                                                                <value name=\"ACTUAL\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">list</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"EXPECTED\">\n                                                                  <block type=\"lists_create_with\" inline=\"false\">\n                                                                    <mutation items=\"2\"></mutation>\n                                                                    <value name=\"ADD0\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Spock</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD1\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">McCoy</field>\n                                                                      </block>\n                                                                    </value>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </next>\n                                                          </block>\n                                                        </next>\n                                                      </block>\n                                                    </next>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"15\" y=\"4378\">\n    <mutation></mutation>\n    <field name=\"NAME\">test remove</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">list</field>\n        <value name=\"VALUE\">\n          <block type=\"lists_create_with\" inline=\"false\">\n            <mutation items=\"3\"></mutation>\n            <value name=\"ADD0\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Kirk</field>\n              </block>\n            </value>\n            <value name=\"ADD1\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Spock</field>\n              </block>\n            </value>\n            <value name=\"ADD2\">\n              <block type=\"text\">\n                <field name=\"TEXT\">McCoy</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"lists_getIndex\" inline=\"true\">\n            <mutation statement=\"true\" at=\"false\"></mutation>\n            <field name=\"MODE\">REMOVE</field>\n            <field name=\"WHERE\">FIRST</field>\n            <value name=\"VALUE\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">list</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">remove first list</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">list</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"lists_create_with\" inline=\"false\">\n                    <mutation items=\"2\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Spock</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">McCoy</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">list</field>\n                    <value name=\"VALUE\">\n                      <block type=\"lists_create_with\" inline=\"false\">\n                        <mutation items=\"3\"></mutation>\n                        <value name=\"ADD0\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Kirk</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD1\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Spock</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD2\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">McCoy</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"lists_getIndex\" inline=\"true\">\n                        <mutation statement=\"true\" at=\"false\"></mutation>\n                        <field name=\"MODE\">REMOVE</field>\n                        <field name=\"WHERE\">LAST</field>\n                        <value name=\"VALUE\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">list</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">remove last list</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">list</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"lists_create_with\" inline=\"false\">\n                                <mutation items=\"2\"></mutation>\n                                <value name=\"ADD0\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Kirk</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD1\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Spock</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"variables_set\" inline=\"false\">\n                                <field name=\"VAR\">list</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"lists_create_with\" inline=\"false\">\n                                    <mutation items=\"3\"></mutation>\n                                    <value name=\"ADD0\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Kirk</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"ADD1\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Spock</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"ADD2\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">McCoy</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"lists_getIndex\" inline=\"true\">\n                                    <mutation statement=\"true\" at=\"false\"></mutation>\n                                    <field name=\"MODE\">REMOVE</field>\n                                    <field name=\"WHERE\">RANDOM</field>\n                                    <value name=\"VALUE\">\n                                      <block type=\"variables_get\">\n                                        <field name=\"VAR\">list</field>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"unittest_assertequals\" inline=\"false\">\n                                        <field name=\"MESSAGE\">remove random list</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"lists_length\" inline=\"false\">\n                                            <value name=\"VALUE\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">list</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <value name=\"EXPECTED\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">2</field>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"variables_set\" inline=\"false\">\n                                            <field name=\"VAR\">list</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"lists_create_with\" inline=\"false\">\n                                                <mutation items=\"3\"></mutation>\n                                                <value name=\"ADD0\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Kirk</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD1\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Spock</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD2\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">McCoy</field>\n                                                  </block>\n                                                </value>\n                                              </block>\n                                            </value>\n                                            <next>\n                                              <block type=\"lists_getIndex\" inline=\"true\">\n                                                <mutation statement=\"true\" at=\"true\"></mutation>\n                                                <field name=\"MODE\">REMOVE</field>\n                                                <field name=\"WHERE\">FROM_START</field>\n                                                <value name=\"VALUE\">\n                                                  <block type=\"variables_get\">\n                                                    <field name=\"VAR\">list</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"AT\">\n                                                  <block type=\"math_number\">\n                                                    <field name=\"NUM\">2</field>\n                                                  </block>\n                                                </value>\n                                                <next>\n                                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                                    <field name=\"MESSAGE\">remove # list</field>\n                                                    <value name=\"ACTUAL\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">list</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"EXPECTED\">\n                                                      <block type=\"lists_create_with\" inline=\"false\">\n                                                        <mutation items=\"2\"></mutation>\n                                                        <value name=\"ADD0\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Kirk</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD1\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">McCoy</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </value>\n                                                    <next>\n                                                      <block type=\"variables_set\" inline=\"false\">\n                                                        <field name=\"VAR\">list</field>\n                                                        <value name=\"VALUE\">\n                                                          <block type=\"lists_create_with\" inline=\"false\">\n                                                            <mutation items=\"3\"></mutation>\n                                                            <value name=\"ADD0\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Kirk</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD1\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Spock</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD2\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">McCoy</field>\n                                                              </block>\n                                                            </value>\n                                                          </block>\n                                                        </value>\n                                                        <next>\n                                                          <block type=\"lists_getIndex\" inline=\"true\">\n                                                            <mutation statement=\"true\" at=\"true\"></mutation>\n                                                            <field name=\"MODE\">REMOVE</field>\n                                                            <field name=\"WHERE\">FROM_END</field>\n                                                            <value name=\"VALUE\">\n                                                              <block type=\"variables_get\">\n                                                                <field name=\"VAR\">list</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"AT\">\n                                                              <block type=\"math_number\">\n                                                                <field name=\"NUM\">3</field>\n                                                              </block>\n                                                            </value>\n                                                            <next>\n                                                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                                                <field name=\"MESSAGE\">remove #-end list</field>\n                                                                <value name=\"ACTUAL\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">list</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"EXPECTED\">\n                                                                  <block type=\"lists_create_with\" inline=\"false\">\n                                                                    <mutation items=\"2\"></mutation>\n                                                                    <value name=\"ADD0\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Spock</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD1\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">McCoy</field>\n                                                                      </block>\n                                                                    </value>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </next>\n                                                          </block>\n                                                        </next>\n                                                      </block>\n                                                    </next>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"17\" y=\"5626\">\n    <mutation></mutation>\n    <field name=\"NAME\">test set</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">x</field>\n        <value name=\"VALUE\">\n          <block type=\"lists_create_with\" inline=\"false\">\n            <mutation items=\"3\"></mutation>\n            <value name=\"ADD0\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Picard</field>\n              </block>\n            </value>\n            <value name=\"ADD1\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Riker</field>\n              </block>\n            </value>\n            <value name=\"ADD2\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Crusher</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"lists_setIndex\" inline=\"true\">\n            <mutation at=\"false\"></mutation>\n            <field name=\"MODE\">SET</field>\n            <field name=\"WHERE\">FIRST</field>\n            <value name=\"LIST\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">x</field>\n              </block>\n            </value>\n            <value name=\"TO\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Jean-Luc</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">set first list</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">x</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"lists_create_with\" inline=\"false\">\n                    <mutation items=\"3\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Jean-Luc</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Riker</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD2\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Crusher</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">x</field>\n                    <value name=\"VALUE\">\n                      <block type=\"lists_create_with\" inline=\"false\">\n                        <mutation items=\"3\"></mutation>\n                        <value name=\"ADD0\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Picard</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD1\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Riker</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD2\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Crusher</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"lists_setIndex\" inline=\"true\">\n                        <mutation at=\"false\"></mutation>\n                        <field name=\"MODE\">SET</field>\n                        <field name=\"WHERE\">LAST</field>\n                        <value name=\"LIST\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">x</field>\n                          </block>\n                        </value>\n                        <value name=\"TO\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Beverly</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">set last list</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">x</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"lists_create_with\" inline=\"false\">\n                                <mutation items=\"3\"></mutation>\n                                <value name=\"ADD0\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Picard</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD1\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Riker</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD2\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Beverly</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"variables_set\" inline=\"false\">\n                                <field name=\"VAR\">x</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"lists_create_with\" inline=\"false\">\n                                    <mutation items=\"3\"></mutation>\n                                    <value name=\"ADD0\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Picard</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"ADD1\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Riker</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"ADD2\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Crusher</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"lists_setIndex\" inline=\"true\">\n                                    <mutation at=\"false\"></mutation>\n                                    <field name=\"MODE\">SET</field>\n                                    <field name=\"WHERE\">RANDOM</field>\n                                    <value name=\"LIST\">\n                                      <block type=\"variables_get\">\n                                        <field name=\"VAR\">x</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"TO\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Data</field>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"unittest_assertequals\" inline=\"false\">\n                                        <field name=\"MESSAGE\">set random list</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"lists_length\" inline=\"false\">\n                                            <value name=\"VALUE\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">x</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <value name=\"EXPECTED\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">3</field>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"variables_set\" inline=\"false\">\n                                            <field name=\"VAR\">x</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"lists_create_with\" inline=\"false\">\n                                                <mutation items=\"3\"></mutation>\n                                                <value name=\"ADD0\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Picard</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD1\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Riker</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD2\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Crusher</field>\n                                                  </block>\n                                                </value>\n                                              </block>\n                                            </value>\n                                            <next>\n                                              <block type=\"lists_setIndex\" inline=\"true\">\n                                                <mutation at=\"true\"></mutation>\n                                                <field name=\"MODE\">SET</field>\n                                                <field name=\"WHERE\">FROM_START</field>\n                                                <value name=\"LIST\">\n                                                  <block type=\"variables_get\">\n                                                    <field name=\"VAR\">x</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"AT\">\n                                                  <block type=\"math_number\">\n                                                    <field name=\"NUM\">3</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"TO\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Pulaski</field>\n                                                  </block>\n                                                </value>\n                                                <next>\n                                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                                    <field name=\"MESSAGE\">set # list</field>\n                                                    <value name=\"ACTUAL\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">x</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"EXPECTED\">\n                                                      <block type=\"lists_create_with\" inline=\"false\">\n                                                        <mutation items=\"3\"></mutation>\n                                                        <value name=\"ADD0\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Picard</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD1\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Riker</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD2\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Pulaski</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </value>\n                                                    <next>\n                                                      <block type=\"variables_set\" inline=\"false\">\n                                                        <field name=\"VAR\">x</field>\n                                                        <value name=\"VALUE\">\n                                                          <block type=\"lists_create_with\" inline=\"false\">\n                                                            <mutation items=\"3\"></mutation>\n                                                            <value name=\"ADD0\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Picard</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD1\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Riker</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD2\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Crusher</field>\n                                                              </block>\n                                                            </value>\n                                                          </block>\n                                                        </value>\n                                                        <next>\n                                                          <block type=\"lists_setIndex\" inline=\"true\">\n                                                            <mutation at=\"true\"></mutation>\n                                                            <field name=\"MODE\">SET</field>\n                                                            <field name=\"WHERE\">FROM_END</field>\n                                                            <value name=\"LIST\">\n                                                              <block type=\"variables_get\">\n                                                                <field name=\"VAR\">x</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"AT\">\n                                                              <block type=\"math_number\">\n                                                                <field name=\"NUM\">1</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"TO\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Pulaski</field>\n                                                              </block>\n                                                            </value>\n                                                            <next>\n                                                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                                                <field name=\"MESSAGE\">set #-end list</field>\n                                                                <value name=\"ACTUAL\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">x</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"EXPECTED\">\n                                                                  <block type=\"lists_create_with\" inline=\"false\">\n                                                                    <mutation items=\"3\"></mutation>\n                                                                    <value name=\"ADD0\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Picard</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD1\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Riker</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD2\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Pulaski</field>\n                                                                      </block>\n                                                                    </value>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </next>\n                                                          </block>\n                                                        </next>\n                                                      </block>\n                                                    </next>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"32\" y=\"6947\">\n    <mutation></mutation>\n    <field name=\"NAME\">test insert</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">x</field>\n        <value name=\"VALUE\">\n          <block type=\"lists_create_with\" inline=\"false\">\n            <mutation items=\"3\"></mutation>\n            <value name=\"ADD0\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Picard</field>\n              </block>\n            </value>\n            <value name=\"ADD1\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Riker</field>\n              </block>\n            </value>\n            <value name=\"ADD2\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Crusher</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"lists_setIndex\" inline=\"true\">\n            <mutation at=\"false\"></mutation>\n            <field name=\"MODE\">INSERT</field>\n            <field name=\"WHERE\">FIRST</field>\n            <value name=\"LIST\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">x</field>\n              </block>\n            </value>\n            <value name=\"TO\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Data</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">insert first list</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">x</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"lists_create_with\" inline=\"false\">\n                    <mutation items=\"4\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Data</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Picard</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD2\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Riker</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD3\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Crusher</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">x</field>\n                    <value name=\"VALUE\">\n                      <block type=\"lists_create_with\" inline=\"false\">\n                        <mutation items=\"3\"></mutation>\n                        <value name=\"ADD0\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Picard</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD1\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Riker</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD2\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Crusher</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"lists_setIndex\" inline=\"true\">\n                        <mutation at=\"false\"></mutation>\n                        <field name=\"MODE\">INSERT</field>\n                        <field name=\"WHERE\">LAST</field>\n                        <value name=\"LIST\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">x</field>\n                          </block>\n                        </value>\n                        <value name=\"TO\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Data</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">insert last list</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">x</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"lists_create_with\" inline=\"false\">\n                                <mutation items=\"4\"></mutation>\n                                <value name=\"ADD0\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Picard</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD1\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Riker</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD2\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Crusher</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD3\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Data</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"variables_set\" inline=\"false\">\n                                <field name=\"VAR\">x</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"lists_create_with\" inline=\"false\">\n                                    <mutation items=\"3\"></mutation>\n                                    <value name=\"ADD0\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Picard</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"ADD1\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Riker</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"ADD2\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Crusher</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"lists_setIndex\" inline=\"true\">\n                                    <mutation at=\"false\"></mutation>\n                                    <field name=\"MODE\">INSERT</field>\n                                    <field name=\"WHERE\">RANDOM</field>\n                                    <value name=\"LIST\">\n                                      <block type=\"variables_get\">\n                                        <field name=\"VAR\">x</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"TO\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Data</field>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"unittest_assertequals\" inline=\"false\">\n                                        <field name=\"MESSAGE\">insert random list</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"lists_length\" inline=\"false\">\n                                            <value name=\"VALUE\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">x</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <value name=\"EXPECTED\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">4</field>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"variables_set\" inline=\"false\">\n                                            <field name=\"VAR\">x</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"lists_create_with\" inline=\"false\">\n                                                <mutation items=\"3\"></mutation>\n                                                <value name=\"ADD0\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Picard</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD1\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Riker</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD2\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Crusher</field>\n                                                  </block>\n                                                </value>\n                                              </block>\n                                            </value>\n                                            <next>\n                                              <block type=\"lists_setIndex\" inline=\"true\">\n                                                <mutation at=\"true\"></mutation>\n                                                <field name=\"MODE\">INSERT</field>\n                                                <field name=\"WHERE\">FROM_START</field>\n                                                <value name=\"LIST\">\n                                                  <block type=\"variables_get\">\n                                                    <field name=\"VAR\">x</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"AT\">\n                                                  <block type=\"math_number\">\n                                                    <field name=\"NUM\">3</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"TO\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">Data</field>\n                                                  </block>\n                                                </value>\n                                                <next>\n                                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                                    <field name=\"MESSAGE\">insert # list</field>\n                                                    <value name=\"ACTUAL\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">x</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"EXPECTED\">\n                                                      <block type=\"lists_create_with\" inline=\"false\">\n                                                        <mutation items=\"4\"></mutation>\n                                                        <value name=\"ADD0\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Picard</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD1\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Riker</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD2\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Data</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD3\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">Crusher</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </value>\n                                                    <next>\n                                                      <block type=\"variables_set\" inline=\"false\">\n                                                        <field name=\"VAR\">x</field>\n                                                        <value name=\"VALUE\">\n                                                          <block type=\"lists_create_with\" inline=\"false\">\n                                                            <mutation items=\"3\"></mutation>\n                                                            <value name=\"ADD0\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Picard</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD1\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Riker</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD2\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Crusher</field>\n                                                              </block>\n                                                            </value>\n                                                          </block>\n                                                        </value>\n                                                        <next>\n                                                          <block type=\"lists_setIndex\" inline=\"true\">\n                                                            <mutation at=\"true\"></mutation>\n                                                            <field name=\"MODE\">INSERT</field>\n                                                            <field name=\"WHERE\">FROM_END</field>\n                                                            <value name=\"LIST\">\n                                                              <block type=\"variables_get\">\n                                                                <field name=\"VAR\">x</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"AT\">\n                                                              <block type=\"math_number\">\n                                                                <field name=\"NUM\">1</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"TO\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">Data</field>\n                                                              </block>\n                                                            </value>\n                                                            <next>\n                                                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                                                <field name=\"MESSAGE\">insert #-end list</field>\n                                                                <value name=\"ACTUAL\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">x</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"EXPECTED\">\n                                                                  <block type=\"lists_create_with\" inline=\"false\">\n                                                                    <mutation items=\"4\"></mutation>\n                                                                    <value name=\"ADD0\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Picard</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD1\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Riker</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD2\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Data</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD3\">\n                                                                      <block type=\"text\">\n                                                                        <field name=\"TEXT\">Crusher</field>\n                                                                      </block>\n                                                                    </value>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </next>\n                                                          </block>\n                                                        </next>\n                                                      </block>\n                                                    </next>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"47\" y=\"8393\">\n    <mutation></mutation>\n    <field name=\"NAME\">test sublist</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">list</field>\n        <value name=\"VALUE\">\n          <block type=\"lists_create_with\" inline=\"false\">\n            <mutation items=\"5\"></mutation>\n            <value name=\"ADD0\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Columbia</field>\n              </block>\n            </value>\n            <value name=\"ADD1\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Challenger</field>\n              </block>\n            </value>\n            <value name=\"ADD2\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Discovery</field>\n              </block>\n            </value>\n            <value name=\"ADD3\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Atlantis</field>\n              </block>\n            </value>\n            <value name=\"ADD4\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Endeavour</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">sublist # start</field>\n            <value name=\"ACTUAL\">\n              <block type=\"lists_getSublist\" inline=\"true\">\n                <mutation at1=\"true\" at2=\"true\"></mutation>\n                <field name=\"WHERE1\">FROM_START</field>\n                <field name=\"WHERE2\">FROM_START</field>\n                <value name=\"LIST\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">list</field>\n                  </block>\n                </value>\n                <value name=\"AT1\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">2</field>\n                  </block>\n                </value>\n                <value name=\"AT2\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">3</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"lists_create_with\" inline=\"false\">\n                <mutation items=\"2\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Challenger</field>\n                  </block>\n                </value>\n                <value name=\"ADD1\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Discovery</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">sublist # end</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"lists_getSublist\" inline=\"true\">\n                    <mutation at1=\"true\" at2=\"true\"></mutation>\n                    <field name=\"WHERE1\">FROM_END</field>\n                    <field name=\"WHERE2\">FROM_END</field>\n                    <value name=\"LIST\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">list</field>\n                      </block>\n                    </value>\n                    <value name=\"AT1\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">3</field>\n                      </block>\n                    </value>\n                    <value name=\"AT2\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">2</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"lists_create_with\" inline=\"false\">\n                    <mutation items=\"2\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Discovery</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Atlantis</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">sublist first-last</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"lists_getSublist\" inline=\"true\">\n                        <mutation at1=\"false\" at2=\"false\"></mutation>\n                        <field name=\"WHERE1\">FIRST</field>\n                        <field name=\"WHERE2\">LAST</field>\n                        <value name=\"LIST\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">list</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">list</field>\n                      </block>\n                    </value>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/logic.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"unittest_main\" x=\"-4\" y=\"-12\">\n    <statement name=\"DO\">\n      <block type=\"unittest_assertvalue\" inline=\"false\">\n        <field name=\"MESSAGE\">True</field>\n        <field name=\"EXPECTED\">TRUE</field>\n        <value name=\"ACTUAL\">\n          <block type=\"logic_boolean\">\n            <field name=\"BOOL\">TRUE</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">False</field>\n            <field name=\"EXPECTED\">FALSE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">FALSE</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertvalue\" inline=\"false\">\n                <field name=\"MESSAGE\">Not true</field>\n                <field name=\"EXPECTED\">TRUE</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"logic_negate\" inline=\"false\">\n                    <value name=\"BOOL\">\n                      <block type=\"logic_boolean\">\n                        <field name=\"BOOL\">FALSE</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                    <field name=\"MESSAGE\">Not false</field>\n                    <field name=\"EXPECTED\">FALSE</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"logic_negate\" inline=\"false\">\n                        <value name=\"BOOL\">\n                          <block type=\"logic_boolean\">\n                            <field name=\"BOOL\">TRUE</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"procedures_callnoreturn\">\n                        <mutation name=\"test if\"></mutation>\n                        <next>\n                          <block type=\"procedures_callnoreturn\">\n                            <mutation name=\"test equalities\"></mutation>\n                            <next>\n                              <block type=\"procedures_callnoreturn\">\n                                <mutation name=\"test and\"></mutation>\n                                <next>\n                                  <block type=\"procedures_callnoreturn\">\n                                    <mutation name=\"test or\"></mutation>\n                                    <next>\n                                      <block type=\"procedures_callnoreturn\">\n                                        <mutation name=\"test ternary\"></mutation>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"385\" y=\"-3\">\n    <mutation></mutation>\n    <field name=\"NAME\">test if</field>\n    <statement name=\"STACK\">\n      <block type=\"controls_if\" inline=\"false\">\n        <value name=\"IF0\">\n          <block type=\"logic_boolean\">\n            <field name=\"BOOL\">FALSE</field>\n          </block>\n        </value>\n        <statement name=\"DO0\">\n          <block type=\"unittest_fail\">\n            <field name=\"MESSAGE\">if false</field>\n          </block>\n        </statement>\n        <next>\n          <block type=\"variables_set\" inline=\"false\">\n            <field name=\"VAR\">ok</field>\n            <value name=\"VALUE\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">FALSE</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"controls_if\" inline=\"false\">\n                <value name=\"IF0\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">TRUE</field>\n                  </block>\n                </value>\n                <statement name=\"DO0\">\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">ok</field>\n                    <value name=\"VALUE\">\n                      <block type=\"logic_boolean\">\n                        <field name=\"BOOL\">TRUE</field>\n                      </block>\n                    </value>\n                  </block>\n                </statement>\n                <next>\n                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                    <field name=\"MESSAGE\">if true</field>\n                    <field name=\"EXPECTED\">TRUE</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">ok</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"variables_set\" inline=\"false\">\n                        <field name=\"VAR\">ok</field>\n                        <value name=\"VALUE\">\n                          <block type=\"logic_boolean\">\n                            <field name=\"BOOL\">FALSE</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"controls_if\" inline=\"false\">\n                            <mutation else=\"1\"></mutation>\n                            <value name=\"IF0\">\n                              <block type=\"logic_boolean\">\n                                <field name=\"BOOL\">FALSE</field>\n                              </block>\n                            </value>\n                            <statement name=\"DO0\">\n                              <block type=\"unittest_fail\">\n                                <field name=\"MESSAGE\">if/else false</field>\n                              </block>\n                            </statement>\n                            <statement name=\"ELSE\">\n                              <block type=\"variables_set\" inline=\"false\">\n                                <field name=\"VAR\">ok</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"logic_boolean\">\n                                    <field name=\"BOOL\">TRUE</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </statement>\n                            <next>\n                              <block type=\"unittest_assertvalue\" inline=\"false\">\n                                <field name=\"MESSAGE\">if/else false</field>\n                                <field name=\"EXPECTED\">TRUE</field>\n                                <value name=\"ACTUAL\">\n                                  <block type=\"variables_get\">\n                                    <field name=\"VAR\">ok</field>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"variables_set\" inline=\"false\">\n                                    <field name=\"VAR\">ok</field>\n                                    <value name=\"VALUE\">\n                                      <block type=\"logic_boolean\">\n                                        <field name=\"BOOL\">FALSE</field>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"controls_if\" inline=\"false\">\n                                        <mutation else=\"1\"></mutation>\n                                        <value name=\"IF0\">\n                                          <block type=\"logic_boolean\">\n                                            <field name=\"BOOL\">TRUE</field>\n                                          </block>\n                                        </value>\n                                        <statement name=\"DO0\">\n                                          <block type=\"variables_set\" inline=\"false\">\n                                            <field name=\"VAR\">ok</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"logic_boolean\">\n                                                <field name=\"BOOL\">TRUE</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </statement>\n                                        <statement name=\"ELSE\">\n                                          <block type=\"unittest_fail\">\n                                            <field name=\"MESSAGE\">if/else true</field>\n                                          </block>\n                                        </statement>\n                                        <next>\n                                          <block type=\"unittest_assertvalue\" inline=\"false\">\n                                            <field name=\"MESSAGE\">if/else true</field>\n                                            <field name=\"EXPECTED\">TRUE</field>\n                                            <value name=\"ACTUAL\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">ok</field>\n                                              </block>\n                                            </value>\n                                            <next>\n                                              <block type=\"variables_set\" inline=\"false\">\n                                                <field name=\"VAR\">ok</field>\n                                                <value name=\"VALUE\">\n                                                  <block type=\"logic_boolean\">\n                                                    <field name=\"BOOL\">FALSE</field>\n                                                  </block>\n                                                </value>\n                                                <next>\n                                                  <block type=\"controls_if\" inline=\"false\">\n                                                    <mutation elseif=\"2\" else=\"1\"></mutation>\n                                                    <value name=\"IF0\">\n                                                      <block type=\"logic_boolean\">\n                                                        <field name=\"BOOL\">FALSE</field>\n                                                      </block>\n                                                    </value>\n                                                    <statement name=\"DO0\">\n                                                      <block type=\"unittest_fail\">\n                                                        <field name=\"MESSAGE\">elseif 1</field>\n                                                      </block>\n                                                    </statement>\n                                                    <value name=\"IF1\">\n                                                      <block type=\"logic_boolean\">\n                                                        <field name=\"BOOL\">TRUE</field>\n                                                      </block>\n                                                    </value>\n                                                    <statement name=\"DO1\">\n                                                      <block type=\"variables_set\" inline=\"false\">\n                                                        <field name=\"VAR\">ok</field>\n                                                        <value name=\"VALUE\">\n                                                          <block type=\"logic_boolean\">\n                                                            <field name=\"BOOL\">TRUE</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </statement>\n                                                    <value name=\"IF2\">\n                                                      <block type=\"logic_boolean\">\n                                                        <field name=\"BOOL\">TRUE</field>\n                                                      </block>\n                                                    </value>\n                                                    <statement name=\"DO2\">\n                                                      <block type=\"unittest_fail\">\n                                                        <field name=\"MESSAGE\">elseif 2</field>\n                                                      </block>\n                                                    </statement>\n                                                    <statement name=\"ELSE\">\n                                                      <block type=\"unittest_fail\">\n                                                        <field name=\"MESSAGE\">elseif 3</field>\n                                                      </block>\n                                                    </statement>\n                                                    <next>\n                                                      <block type=\"unittest_assertvalue\" inline=\"false\">\n                                                        <field name=\"MESSAGE\">elseif 4</field>\n                                                        <field name=\"EXPECTED\">TRUE</field>\n                                                        <value name=\"ACTUAL\">\n                                                          <block type=\"variables_get\">\n                                                            <field name=\"VAR\">ok</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </next>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-7\" y=\"384\">\n    <mutation></mutation>\n    <field name=\"NAME\">test equalities</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertvalue\" inline=\"false\">\n        <field name=\"MESSAGE\">Equal yes</field>\n        <field name=\"EXPECTED\">TRUE</field>\n        <value name=\"ACTUAL\">\n          <block type=\"logic_compare\" inline=\"true\">\n            <field name=\"OP\">EQ</field>\n            <value name=\"A\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">2</field>\n              </block>\n            </value>\n            <value name=\"B\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">2</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">Equal no</field>\n            <field name=\"EXPECTED\">FALSE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"logic_compare\" inline=\"true\">\n                <field name=\"OP\">EQ</field>\n                <value name=\"A\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">3</field>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">4</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertvalue\" inline=\"false\">\n                <field name=\"MESSAGE\">Not equal yes</field>\n                <field name=\"EXPECTED\">TRUE</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"logic_compare\" inline=\"true\">\n                    <field name=\"OP\">NEQ</field>\n                    <value name=\"A\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">5</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">6</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                    <field name=\"MESSAGE\">Not equal no</field>\n                    <field name=\"EXPECTED\">FALSE</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"logic_compare\" inline=\"true\">\n                        <field name=\"OP\">EQ</field>\n                        <value name=\"A\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">3</field>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">4</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertvalue\" inline=\"false\">\n                        <field name=\"MESSAGE\">Smaller yes</field>\n                        <field name=\"EXPECTED\">TRUE</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"logic_compare\" inline=\"true\">\n                            <field name=\"OP\">LT</field>\n                            <value name=\"A\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">5</field>\n                              </block>\n                            </value>\n                            <value name=\"B\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">6</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertvalue\" inline=\"false\">\n                            <field name=\"MESSAGE\">Smaller no</field>\n                            <field name=\"EXPECTED\">FALSE</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"logic_compare\" inline=\"true\">\n                                <field name=\"OP\">LT</field>\n                                <value name=\"A\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">7</field>\n                                  </block>\n                                </value>\n                                <value name=\"B\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">7</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"unittest_assertvalue\" inline=\"false\">\n                                <field name=\"MESSAGE\">Greater yes</field>\n                                <field name=\"EXPECTED\">TRUE</field>\n                                <value name=\"ACTUAL\">\n                                  <block type=\"logic_compare\" inline=\"true\">\n                                    <field name=\"OP\">GT</field>\n                                    <value name=\"A\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">9</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"B\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">8</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                                    <field name=\"MESSAGE\">Greater no</field>\n                                    <field name=\"EXPECTED\">FALSE</field>\n                                    <value name=\"ACTUAL\">\n                                      <block type=\"logic_compare\" inline=\"true\">\n                                        <field name=\"OP\">GT</field>\n                                        <value name=\"A\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">10</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"B\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">10</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"unittest_assertvalue\" inline=\"false\">\n                                        <field name=\"MESSAGE\">Smaller-equal yes</field>\n                                        <field name=\"EXPECTED\">TRUE</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"logic_compare\" inline=\"true\">\n                                            <field name=\"OP\">LTE</field>\n                                            <value name=\"A\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">11</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"B\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">11</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"unittest_assertvalue\" inline=\"false\">\n                                            <field name=\"MESSAGE\">Smaller-equal no</field>\n                                            <field name=\"EXPECTED\">FALSE</field>\n                                            <value name=\"ACTUAL\">\n                                              <block type=\"logic_compare\" inline=\"true\">\n                                                <field name=\"OP\">LTE</field>\n                                                <value name=\"A\">\n                                                  <block type=\"math_number\">\n                                                    <field name=\"NUM\">13</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"B\">\n                                                  <block type=\"math_number\">\n                                                    <field name=\"NUM\">12</field>\n                                                  </block>\n                                                </value>\n                                              </block>\n                                            </value>\n                                            <next>\n                                              <block type=\"unittest_assertvalue\" inline=\"false\">\n                                                <field name=\"MESSAGE\">Greater-equal yes</field>\n                                                <field name=\"EXPECTED\">TRUE</field>\n                                                <value name=\"ACTUAL\">\n                                                  <block type=\"logic_compare\" inline=\"true\">\n                                                    <field name=\"OP\">GTE</field>\n                                                    <value name=\"A\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">14</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"B\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">14</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <next>\n                                                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                                                    <field name=\"MESSAGE\">Greater-equal no</field>\n                                                    <field name=\"EXPECTED\">FALSE</field>\n                                                    <value name=\"ACTUAL\">\n                                                      <block type=\"logic_compare\" inline=\"true\">\n                                                        <field name=\"OP\">GTE</field>\n                                                        <value name=\"A\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">15</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"B\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">16</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-5\" y=\"1200\">\n    <mutation></mutation>\n    <field name=\"NAME\">test or</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertvalue\" inline=\"false\">\n        <field name=\"MESSAGE\">Or true/true</field>\n        <field name=\"EXPECTED\">TRUE</field>\n        <value name=\"ACTUAL\">\n          <block type=\"logic_operation\" inline=\"true\">\n            <field name=\"OP\">OR</field>\n            <value name=\"A\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">TRUE</field>\n              </block>\n            </value>\n            <value name=\"B\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">TRUE</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">Or false/true</field>\n            <field name=\"EXPECTED\">TRUE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"logic_operation\" inline=\"true\">\n                <field name=\"OP\">OR</field>\n                <value name=\"A\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">FALSE</field>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">TRUE</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertvalue\" inline=\"false\">\n                <field name=\"MESSAGE\">Or true/false</field>\n                <field name=\"EXPECTED\">TRUE</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"logic_operation\" inline=\"true\">\n                    <field name=\"OP\">OR</field>\n                    <value name=\"A\">\n                      <block type=\"logic_boolean\">\n                        <field name=\"BOOL\">TRUE</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"logic_boolean\">\n                        <field name=\"BOOL\">FALSE</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                    <field name=\"MESSAGE\">Or false/false</field>\n                    <field name=\"EXPECTED\">FALSE</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"logic_operation\" inline=\"true\">\n                        <field name=\"OP\">OR</field>\n                        <value name=\"A\">\n                          <block type=\"logic_boolean\">\n                            <field name=\"BOOL\">FALSE</field>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"logic_boolean\">\n                            <field name=\"BOOL\">FALSE</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"385\" y=\"1208\">\n    <mutation></mutation>\n    <field name=\"NAME\">test and</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertvalue\" inline=\"false\">\n        <field name=\"MESSAGE\">And true/true</field>\n        <field name=\"EXPECTED\">TRUE</field>\n        <value name=\"ACTUAL\">\n          <block type=\"logic_operation\" inline=\"true\">\n            <field name=\"OP\">AND</field>\n            <value name=\"A\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">TRUE</field>\n              </block>\n            </value>\n            <value name=\"B\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">TRUE</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">And false/true</field>\n            <field name=\"EXPECTED\">FALSE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"logic_operation\" inline=\"true\">\n                <field name=\"OP\">AND</field>\n                <value name=\"A\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">FALSE</field>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">TRUE</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertvalue\" inline=\"false\">\n                <field name=\"MESSAGE\">And true/false</field>\n                <field name=\"EXPECTED\">FALSE</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"logic_operation\" inline=\"true\">\n                    <field name=\"OP\">AND</field>\n                    <value name=\"A\">\n                      <block type=\"logic_boolean\">\n                        <field name=\"BOOL\">TRUE</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"logic_boolean\">\n                        <field name=\"BOOL\">FALSE</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                    <field name=\"MESSAGE\">And false/false</field>\n                    <field name=\"EXPECTED\">FALSE</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"logic_operation\" inline=\"true\">\n                        <field name=\"OP\">AND</field>\n                        <value name=\"A\">\n                          <block type=\"logic_boolean\">\n                            <field name=\"BOOL\">FALSE</field>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"logic_boolean\">\n                            <field name=\"BOOL\">FALSE</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"3\" y=\"1527\">\n    <mutation></mutation>\n    <field name=\"NAME\">test ternary</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">if true</field>\n        <value name=\"ACTUAL\">\n          <block type=\"logic_ternary\" inline=\"true\">\n            <value name=\"IF\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">TRUE</field>\n              </block>\n            </value>\n            <value name=\"THEN\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">42</field>\n              </block>\n            </value>\n            <value name=\"ELSE\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">99</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">42</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">if true</field>\n            <value name=\"ACTUAL\">\n              <block type=\"logic_ternary\" inline=\"true\">\n                <value name=\"IF\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">FALSE</field>\n                  </block>\n                </value>\n                <value name=\"THEN\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">42</field>\n                  </block>\n                </value>\n                <value name=\"ELSE\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">99</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">99</field>\n              </block>\n            </value>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/loops1.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"unittest_main\" x=\"33\" y=\"140\">\n    <statement name=\"DO\">\n      <block type=\"procedures_callnoreturn\">\n        <mutation name=\"test repeat\"></mutation>\n        <next>\n          <block type=\"procedures_callnoreturn\">\n            <mutation name=\"test while\"></mutation>\n            <next>\n              <block type=\"procedures_callnoreturn\">\n                <mutation name=\"test foreach\"></mutation>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"31\" y=\"296\">\n    <mutation></mutation>\n    <field name=\"NAME\">test foreach</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">log</field>\n        <value name=\"VALUE\">\n          <block type=\"text\">\n            <field name=\"TEXT\"></field>\n          </block>\n        </value>\n        <next>\n          <block type=\"controls_forEach\" inline=\"false\">\n            <field name=\"VAR\">x</field>\n            <value name=\"LIST\">\n              <block type=\"lists_create_with\" inline=\"false\">\n                <mutation items=\"3\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">a</field>\n                  </block>\n                </value>\n                <value name=\"ADD1\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">b</field>\n                  </block>\n                </value>\n                <value name=\"ADD2\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">c</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <statement name=\"DO\">\n              <block type=\"text_append\" inline=\"false\">\n                <field name=\"VAR\">log</field>\n                <value name=\"TEXT\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">x</field>\n                  </block>\n                </value>\n              </block>\n            </statement>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">for loop</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">log</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">abc</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"30\" y=\"624\">\n    <mutation></mutation>\n    <field name=\"NAME\">test while</field>\n    <statement name=\"STACK\">\n      <block type=\"controls_whileUntil\" inline=\"false\">\n        <field name=\"MODE\">WHILE</field>\n        <value name=\"BOOL\">\n          <block type=\"logic_boolean\">\n            <field name=\"BOOL\">FALSE</field>\n          </block>\n        </value>\n        <statement name=\"DO\">\n          <block type=\"unittest_fail\">\n            <field name=\"MESSAGE\">while 0</field>\n          </block>\n        </statement>\n        <next>\n          <block type=\"controls_whileUntil\" inline=\"false\">\n            <field name=\"MODE\">UNTIL</field>\n            <value name=\"BOOL\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">TRUE</field>\n              </block>\n            </value>\n            <statement name=\"DO\">\n              <block type=\"unittest_fail\">\n                <field name=\"MESSAGE\">until 0</field>\n              </block>\n            </statement>\n            <next>\n              <block type=\"variables_set\" inline=\"false\">\n                <field name=\"VAR\">count</field>\n                <value name=\"VALUE\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">1</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"controls_whileUntil\" inline=\"false\">\n                    <field name=\"MODE\">WHILE</field>\n                    <value name=\"BOOL\">\n                      <block type=\"logic_compare\" inline=\"true\">\n                        <field name=\"OP\">NEQ</field>\n                        <value name=\"A\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">count</field>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">10</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <statement name=\"DO\">\n                      <block type=\"math_change\" inline=\"false\">\n                        <field name=\"VAR\">count</field>\n                        <value name=\"DELTA\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">1</field>\n                          </block>\n                        </value>\n                      </block>\n                    </statement>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">while 10</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">count</field>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">10</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"variables_set\" inline=\"false\">\n                            <field name=\"VAR\">count</field>\n                            <value name=\"VALUE\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">1</field>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"controls_whileUntil\" inline=\"false\">\n                                <field name=\"MODE\">UNTIL</field>\n                                <value name=\"BOOL\">\n                                  <block type=\"logic_compare\" inline=\"true\">\n                                    <field name=\"OP\">EQ</field>\n                                    <value name=\"A\">\n                                      <block type=\"variables_get\">\n                                        <field name=\"VAR\">count</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"B\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">10</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <statement name=\"DO\">\n                                  <block type=\"math_change\" inline=\"false\">\n                                    <field name=\"VAR\">count</field>\n                                    <value name=\"DELTA\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">1</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </statement>\n                                <next>\n                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                    <field name=\"MESSAGE\">until 10</field>\n                                    <value name=\"ACTUAL\">\n                                      <block type=\"variables_get\">\n                                        <field name=\"VAR\">count</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"EXPECTED\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">10</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"397\" y=\"628\">\n    <mutation></mutation>\n    <field name=\"NAME\">test repeat</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">count</field>\n        <value name=\"VALUE\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">0</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"controls_repeat_ext\" inline=\"true\">\n            <value name=\"TIMES\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">10</field>\n              </block>\n            </value>\n            <statement name=\"DO\">\n              <block type=\"math_change\" inline=\"false\">\n                <field name=\"VAR\">count</field>\n                <value name=\"DELTA\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">1</field>\n                  </block>\n                </value>\n              </block>\n            </statement>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">repeat 10</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">count</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">10</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/loops2.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"procedures_defnoreturn\" x=\"679\" y=\"-10\">\n    <mutation></mutation>\n    <field name=\"NAME\">test count by</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">log</field>\n        <value name=\"VALUE\">\n          <block type=\"text\">\n            <field name=\"TEXT\"></field>\n          </block>\n        </value>\n        <next>\n          <block type=\"controls_for\" inline=\"true\">\n            <field name=\"VAR\">x</field>\n            <value name=\"FROM\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">1</field>\n              </block>\n            </value>\n            <value name=\"TO\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">8</field>\n              </block>\n            </value>\n            <value name=\"BY\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">2</field>\n              </block>\n            </value>\n            <statement name=\"DO\">\n              <block type=\"text_append\" inline=\"false\">\n                <field name=\"VAR\">log</field>\n                <value name=\"TEXT\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">x</field>\n                  </block>\n                </value>\n              </block>\n            </statement>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">count up ints</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">log</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">1357</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">log</field>\n                    <value name=\"VALUE\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\"></field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"controls_for\" inline=\"true\">\n                        <field name=\"VAR\">x</field>\n                        <value name=\"FROM\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">8</field>\n                          </block>\n                        </value>\n                        <value name=\"TO\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">1</field>\n                          </block>\n                        </value>\n                        <value name=\"BY\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">2</field>\n                          </block>\n                        </value>\n                        <statement name=\"DO\">\n                          <block type=\"text_append\" inline=\"false\">\n                            <field name=\"VAR\">log</field>\n                            <value name=\"TEXT\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">x</field>\n                              </block>\n                            </value>\n                          </block>\n                        </statement>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">count down ints</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">log</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"text\">\n                                <field name=\"TEXT\">8642</field>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"variables_set\" inline=\"false\">\n                                <field name=\"VAR\">loglist</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"lists_create_empty\"></block>\n                                </value>\n                                <next>\n                                  <block type=\"controls_for\" inline=\"true\">\n                                    <field name=\"VAR\">x</field>\n                                    <value name=\"FROM\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">1</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"TO\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">8</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"BY\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">1.5</field>\n                                      </block>\n                                    </value>\n                                    <statement name=\"DO\">\n                                      <block type=\"lists_setIndex\" inline=\"true\">\n                                        <mutation at=\"false\"></mutation>\n                                        <field name=\"MODE\">INSERT</field>\n                                        <field name=\"WHERE\">LAST</field>\n                                        <value name=\"LIST\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">loglist</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"TO\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">x</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </statement>\n                                    <next>\n                                      <block type=\"unittest_assertequals\" inline=\"false\">\n                                        <field name=\"MESSAGE\">count with floats</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">loglist</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"EXPECTED\">\n                                          <block type=\"lists_create_with\" inline=\"false\">\n                                            <mutation items=\"5\"></mutation>\n                                            <value name=\"ADD0\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">1</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"ADD1\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">2.5</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"ADD2\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">4</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"ADD3\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">5.5</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"ADD4\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">7</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"variables_set\" inline=\"false\">\n                                            <field name=\"VAR\">loglist</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"lists_create_empty\"></block>\n                                            </value>\n                                            <next>\n                                              <block type=\"controls_for\" inline=\"true\">\n                                                <field name=\"VAR\">x</field>\n                                                <value name=\"FROM\">\n                                                  <block type=\"math_arithmetic\" inline=\"true\">\n                                                    <field name=\"OP\">ADD</field>\n                                                    <value name=\"A\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">1</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"B\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">0</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <value name=\"TO\">\n                                                  <block type=\"math_arithmetic\" inline=\"true\">\n                                                    <field name=\"OP\">ADD</field>\n                                                    <value name=\"A\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">8</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"B\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">0</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <value name=\"BY\">\n                                                  <block type=\"math_arithmetic\" inline=\"true\">\n                                                    <field name=\"OP\">MINUS</field>\n                                                    <value name=\"A\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">1</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"B\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">2</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <statement name=\"DO\">\n                                                  <block type=\"lists_setIndex\" inline=\"true\">\n                                                    <mutation at=\"false\"></mutation>\n                                                    <field name=\"MODE\">INSERT</field>\n                                                    <field name=\"WHERE\">LAST</field>\n                                                    <value name=\"LIST\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">loglist</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"TO\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">x</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </statement>\n                                                <next>\n                                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                                    <field name=\"MESSAGE\">count up non-trivial ints</field>\n                                                    <value name=\"ACTUAL\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">loglist</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"EXPECTED\">\n                                                      <block type=\"lists_create_with\" inline=\"false\">\n                                                        <mutation items=\"8\"></mutation>\n                                                        <value name=\"ADD0\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">1</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD1\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">2</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD2\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">3</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD3\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">4</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD4\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">5</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD5\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">6</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD6\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">7</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD7\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">8</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </value>\n                                                    <next>\n                                                      <block type=\"variables_set\" inline=\"false\">\n                                                        <field name=\"VAR\">loglist</field>\n                                                        <value name=\"VALUE\">\n                                                          <block type=\"lists_create_empty\"></block>\n                                                        </value>\n                                                        <next>\n                                                          <block type=\"controls_for\" inline=\"true\">\n                                                            <field name=\"VAR\">x</field>\n                                                            <value name=\"FROM\">\n                                                              <block type=\"math_arithmetic\" inline=\"true\">\n                                                                <field name=\"OP\">ADD</field>\n                                                                <value name=\"A\">\n                                                                  <block type=\"math_number\">\n                                                                    <field name=\"NUM\">8</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"B\">\n                                                                  <block type=\"math_number\">\n                                                                    <field name=\"NUM\">0</field>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"TO\">\n                                                              <block type=\"math_arithmetic\" inline=\"true\">\n                                                                <field name=\"OP\">ADD</field>\n                                                                <value name=\"A\">\n                                                                  <block type=\"math_number\">\n                                                                    <field name=\"NUM\">1</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"B\">\n                                                                  <block type=\"math_number\">\n                                                                    <field name=\"NUM\">0</field>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"BY\">\n                                                              <block type=\"math_number\">\n                                                                <field name=\"NUM\">2</field>\n                                                              </block>\n                                                            </value>\n                                                            <statement name=\"DO\">\n                                                              <block type=\"lists_setIndex\" inline=\"true\">\n                                                                <mutation at=\"false\"></mutation>\n                                                                <field name=\"MODE\">INSERT</field>\n                                                                <field name=\"WHERE\">LAST</field>\n                                                                <value name=\"LIST\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">loglist</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"TO\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">x</field>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </statement>\n                                                            <next>\n                                                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                                                <field name=\"MESSAGE\">count down non-trivial ints</field>\n                                                                <value name=\"ACTUAL\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">loglist</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"EXPECTED\">\n                                                                  <block type=\"lists_create_with\" inline=\"false\">\n                                                                    <mutation items=\"4\"></mutation>\n                                                                    <value name=\"ADD0\">\n                                                                      <block type=\"math_number\">\n                                                                        <field name=\"NUM\">8</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD1\">\n                                                                      <block type=\"math_number\">\n                                                                        <field name=\"NUM\">6</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD2\">\n                                                                      <block type=\"math_number\">\n                                                                        <field name=\"NUM\">4</field>\n                                                                      </block>\n                                                                    </value>\n                                                                    <value name=\"ADD3\">\n                                                                      <block type=\"math_number\">\n                                                                        <field name=\"NUM\">2</field>\n                                                                      </block>\n                                                                    </value>\n                                                                  </block>\n                                                                </value>\n                                                                <next>\n                                                                  <block type=\"variables_set\" inline=\"false\">\n                                                                    <field name=\"VAR\">loglist</field>\n                                                                    <value name=\"VALUE\">\n                                                                      <block type=\"lists_create_empty\"></block>\n                                                                    </value>\n                                                                    <next>\n                                                                      <block type=\"controls_for\" inline=\"true\">\n                                                                        <field name=\"VAR\">x</field>\n                                                                        <value name=\"FROM\">\n                                                                          <block type=\"math_arithmetic\" inline=\"true\">\n                                                                            <field name=\"OP\">ADD</field>\n                                                                            <value name=\"A\">\n                                                                              <block type=\"math_number\">\n                                                                                <field name=\"NUM\">5</field>\n                                                                              </block>\n                                                                            </value>\n                                                                            <value name=\"B\">\n                                                                              <block type=\"math_number\">\n                                                                                <field name=\"NUM\">0.5</field>\n                                                                              </block>\n                                                                            </value>\n                                                                          </block>\n                                                                        </value>\n                                                                        <value name=\"TO\">\n                                                                          <block type=\"math_arithmetic\" inline=\"true\">\n                                                                            <field name=\"OP\">ADD</field>\n                                                                            <value name=\"A\">\n                                                                              <block type=\"math_number\">\n                                                                                <field name=\"NUM\">1</field>\n                                                                              </block>\n                                                                            </value>\n                                                                            <value name=\"B\">\n                                                                              <block type=\"math_number\">\n                                                                                <field name=\"NUM\">0</field>\n                                                                              </block>\n                                                                            </value>\n                                                                          </block>\n                                                                        </value>\n                                                                        <value name=\"BY\">\n                                                                          <block type=\"math_arithmetic\" inline=\"true\">\n                                                                            <field name=\"OP\">ADD</field>\n                                                                            <value name=\"A\">\n                                                                              <block type=\"math_number\">\n                                                                                <field name=\"NUM\">1</field>\n                                                                              </block>\n                                                                            </value>\n                                                                            <value name=\"B\">\n                                                                              <block type=\"math_number\">\n                                                                                <field name=\"NUM\">0</field>\n                                                                              </block>\n                                                                            </value>\n                                                                          </block>\n                                                                        </value>\n                                                                        <statement name=\"DO\">\n                                                                          <block type=\"lists_setIndex\" inline=\"true\">\n                                                                            <mutation at=\"false\"></mutation>\n                                                                            <field name=\"MODE\">INSERT</field>\n                                                                            <field name=\"WHERE\">LAST</field>\n                                                                            <value name=\"LIST\">\n                                                                              <block type=\"variables_get\">\n                                                                                <field name=\"VAR\">loglist</field>\n                                                                              </block>\n                                                                            </value>\n                                                                            <value name=\"TO\">\n                                                                              <block type=\"variables_get\">\n                                                                                <field name=\"VAR\">x</field>\n                                                                              </block>\n                                                                            </value>\n                                                                          </block>\n                                                                        </statement>\n                                                                        <next>\n                                                                          <block type=\"unittest_assertequals\" inline=\"false\">\n                                                                            <field name=\"MESSAGE\">count with floats</field>\n                                                                            <value name=\"ACTUAL\">\n                                                                              <block type=\"variables_get\">\n                                                                                <field name=\"VAR\">loglist</field>\n                                                                              </block>\n                                                                            </value>\n                                                                            <value name=\"EXPECTED\">\n                                                                              <block type=\"lists_create_with\" inline=\"false\">\n                                                                                <mutation items=\"5\"></mutation>\n                                                                                <value name=\"ADD0\">\n                                                                                  <block type=\"math_number\">\n                                                                                    <field name=\"NUM\">5.5</field>\n                                                                                  </block>\n                                                                                </value>\n                                                                                <value name=\"ADD1\">\n                                                                                  <block type=\"math_number\">\n                                                                                    <field name=\"NUM\">4.5</field>\n                                                                                  </block>\n                                                                                </value>\n                                                                                <value name=\"ADD2\">\n                                                                                  <block type=\"math_number\">\n                                                                                    <field name=\"NUM\">3.5</field>\n                                                                                  </block>\n                                                                                </value>\n                                                                                <value name=\"ADD3\">\n                                                                                  <block type=\"math_number\">\n                                                                                    <field name=\"NUM\">2.5</field>\n                                                                                  </block>\n                                                                                </value>\n                                                                                <value name=\"ADD4\">\n                                                                                  <block type=\"math_number\">\n                                                                                    <field name=\"NUM\">1.5</field>\n                                                                                  </block>\n                                                                                </value>\n                                                                              </block>\n                                                                            </value>\n                                                                          </block>\n                                                                        </next>\n                                                                      </block>\n                                                                    </next>\n                                                                  </block>\n                                                                </next>\n                                                              </block>\n                                                            </next>\n                                                          </block>\n                                                        </next>\n                                                      </block>\n                                                    </next>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"unittest_main\" x=\"66\" y=\"-2\">\n    <statement name=\"DO\">\n      <block type=\"procedures_callnoreturn\">\n        <mutation name=\"test count\"></mutation>\n        <next>\n          <block type=\"procedures_callnoreturn\">\n            <mutation name=\"test count by\"></mutation>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"29\" y=\"184\">\n    <mutation></mutation>\n    <field name=\"NAME\">test count</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">log</field>\n        <value name=\"VALUE\">\n          <block type=\"text\">\n            <field name=\"TEXT\"></field>\n          </block>\n        </value>\n        <next>\n          <block type=\"controls_for\" inline=\"true\">\n            <field name=\"VAR\">x</field>\n            <value name=\"FROM\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">1</field>\n              </block>\n            </value>\n            <value name=\"TO\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">8</field>\n              </block>\n            </value>\n            <statement name=\"DO\">\n              <block type=\"text_append\" inline=\"false\">\n                <field name=\"VAR\">log</field>\n                <value name=\"TEXT\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">x</field>\n                  </block>\n                </value>\n              </block>\n            </statement>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">count up</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">log</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">12345678</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">log</field>\n                    <value name=\"VALUE\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\"></field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"controls_for\" inline=\"true\">\n                        <field name=\"VAR\">x</field>\n                        <value name=\"FROM\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">8</field>\n                          </block>\n                        </value>\n                        <value name=\"TO\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">1</field>\n                          </block>\n                        </value>\n                        <statement name=\"DO\">\n                          <block type=\"text_append\" inline=\"false\">\n                            <field name=\"VAR\">log</field>\n                            <value name=\"TEXT\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">x</field>\n                              </block>\n                            </value>\n                          </block>\n                        </statement>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">count down</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">log</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"text\">\n                                <field name=\"TEXT\">87654321</field>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"variables_set\" inline=\"false\">\n                                <field name=\"VAR\">loglist</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"lists_create_empty\"></block>\n                                </value>\n                                <next>\n                                  <block type=\"controls_for\" inline=\"true\">\n                                    <field name=\"VAR\">x</field>\n                                    <value name=\"FROM\">\n                                      <block type=\"math_arithmetic\" inline=\"true\">\n                                        <field name=\"OP\">ADD</field>\n                                        <value name=\"A\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">1</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"B\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">0</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                    <value name=\"TO\">\n                                      <block type=\"math_arithmetic\" inline=\"true\">\n                                        <field name=\"OP\">ADD</field>\n                                        <value name=\"A\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">4</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"B\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">0</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                    <statement name=\"DO\">\n                                      <block type=\"lists_setIndex\" inline=\"true\">\n                                        <mutation at=\"false\"></mutation>\n                                        <field name=\"MODE\">INSERT</field>\n                                        <field name=\"WHERE\">LAST</field>\n                                        <value name=\"LIST\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">loglist</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"TO\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">x</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </statement>\n                                    <next>\n                                      <block type=\"unittest_assertequals\" inline=\"false\">\n                                        <field name=\"MESSAGE\">count up non-trivial</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">loglist</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"EXPECTED\">\n                                          <block type=\"lists_create_with\" inline=\"false\">\n                                            <mutation items=\"4\"></mutation>\n                                            <value name=\"ADD0\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">1</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"ADD1\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">2</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"ADD2\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">3</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"ADD3\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">4</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"variables_set\" inline=\"false\">\n                                            <field name=\"VAR\">loglist</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"lists_create_empty\"></block>\n                                            </value>\n                                            <next>\n                                              <block type=\"controls_for\" inline=\"true\">\n                                                <field name=\"VAR\">x</field>\n                                                <value name=\"FROM\">\n                                                  <block type=\"math_arithmetic\" inline=\"true\">\n                                                    <field name=\"OP\">ADD</field>\n                                                    <value name=\"A\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">3</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"B\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">1</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <value name=\"TO\">\n                                                  <block type=\"math_arithmetic\" inline=\"true\">\n                                                    <field name=\"OP\">ADD</field>\n                                                    <value name=\"A\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">1</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"B\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">0</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <statement name=\"DO\">\n                                                  <block type=\"lists_setIndex\" inline=\"true\">\n                                                    <mutation at=\"false\"></mutation>\n                                                    <field name=\"MODE\">INSERT</field>\n                                                    <field name=\"WHERE\">LAST</field>\n                                                    <value name=\"LIST\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">loglist</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"TO\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">x</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </statement>\n                                                <next>\n                                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                                    <field name=\"MESSAGE\">count down non-trivial</field>\n                                                    <value name=\"ACTUAL\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">loglist</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"EXPECTED\">\n                                                      <block type=\"lists_create_with\" inline=\"false\">\n                                                        <mutation items=\"4\"></mutation>\n                                                        <value name=\"ADD0\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">4</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD1\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">3</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD2\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">2</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"ADD3\">\n                                                          <block type=\"math_number\">\n                                                            <field name=\"NUM\">1</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/loops3.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"unittest_main\" x=\"19\" y=\"106\">\n    <statement name=\"DO\">\n      <block type=\"procedures_callnoreturn\">\n        <mutation name=\"test break\"></mutation>\n        <next>\n          <block type=\"procedures_callnoreturn\">\n            <mutation name=\"test continue\"></mutation>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"600\" y=\"300\">\n    <mutation></mutation>\n    <field name=\"NAME\">test break</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">count</field>\n        <value name=\"VALUE\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"controls_whileUntil\" inline=\"false\">\n            <field name=\"MODE\">WHILE</field>\n            <value name=\"BOOL\">\n              <block type=\"logic_compare\" inline=\"true\">\n                <field name=\"OP\">NEQ</field>\n                <value name=\"A\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">count</field>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">10</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <statement name=\"DO\">\n              <block type=\"controls_if\" inline=\"false\">\n                <value name=\"IF0\">\n                  <block type=\"logic_compare\" inline=\"true\">\n                    <field name=\"OP\">EQ</field>\n                    <value name=\"A\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">count</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">5</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <statement name=\"DO0\">\n                  <block type=\"controls_flow_statements\">\n                    <field name=\"FLOW\">BREAK</field>\n                  </block>\n                </statement>\n                <next>\n                  <block type=\"math_change\" inline=\"false\">\n                    <field name=\"VAR\">count</field>\n                    <value name=\"DELTA\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">1</field>\n                      </block>\n                    </value>\n                  </block>\n                </next>\n              </block>\n            </statement>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">while break</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">count</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">5</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">count</field>\n                    <value name=\"VALUE\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">1</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"controls_whileUntil\" inline=\"false\">\n                        <field name=\"MODE\">UNTIL</field>\n                        <value name=\"BOOL\">\n                          <block type=\"logic_compare\" inline=\"true\">\n                            <field name=\"OP\">EQ</field>\n                            <value name=\"A\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">count</field>\n                              </block>\n                            </value>\n                            <value name=\"B\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">10</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <statement name=\"DO\">\n                          <block type=\"controls_if\" inline=\"false\">\n                            <value name=\"IF0\">\n                              <block type=\"logic_compare\" inline=\"true\">\n                                <field name=\"OP\">EQ</field>\n                                <value name=\"A\">\n                                  <block type=\"variables_get\">\n                                    <field name=\"VAR\">count</field>\n                                  </block>\n                                </value>\n                                <value name=\"B\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">5</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <statement name=\"DO0\">\n                              <block type=\"controls_flow_statements\">\n                                <field name=\"FLOW\">BREAK</field>\n                              </block>\n                            </statement>\n                            <next>\n                              <block type=\"math_change\" inline=\"false\">\n                                <field name=\"VAR\">count</field>\n                                <value name=\"DELTA\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">1</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </next>\n                          </block>\n                        </statement>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">until break</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">count</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">5</field>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"variables_set\" inline=\"false\">\n                                <field name=\"VAR\">log</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\"></field>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"controls_for\" inline=\"true\">\n                                    <field name=\"VAR\">x</field>\n                                    <value name=\"FROM\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">1</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"TO\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">8</field>\n                                      </block>\n                                    </value>\n                                    <statement name=\"DO\">\n                                      <block type=\"controls_if\" inline=\"false\">\n                                        <value name=\"IF0\">\n                                          <block type=\"logic_compare\" inline=\"true\">\n                                            <field name=\"OP\">EQ</field>\n                                            <value name=\"A\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">x</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"B\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">5</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <statement name=\"DO0\">\n                                          <block type=\"controls_flow_statements\">\n                                            <field name=\"FLOW\">BREAK</field>\n                                          </block>\n                                        </statement>\n                                        <next>\n                                          <block type=\"text_append\" inline=\"false\">\n                                            <field name=\"VAR\">log</field>\n                                            <value name=\"TEXT\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">x</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </statement>\n                                    <next>\n                                      <block type=\"unittest_assertequals\" inline=\"false\">\n                                        <field name=\"MESSAGE\">count break</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"variables_get\">\n                                            <field name=\"VAR\">log</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"EXPECTED\">\n                                          <block type=\"text\">\n                                            <field name=\"TEXT\">1234</field>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"variables_set\" inline=\"false\">\n                                            <field name=\"VAR\">log</field>\n                                            <value name=\"VALUE\">\n                                              <block type=\"text\">\n                                                <field name=\"TEXT\"></field>\n                                              </block>\n                                            </value>\n                                            <next>\n                                              <block type=\"controls_forEach\" inline=\"false\">\n                                                <field name=\"VAR\">x</field>\n                                                <value name=\"LIST\">\n                                                  <block type=\"lists_create_with\" inline=\"false\">\n                                                    <mutation items=\"4\"></mutation>\n                                                    <value name=\"ADD0\">\n                                                      <block type=\"text\">\n                                                        <field name=\"TEXT\">a</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"ADD1\">\n                                                      <block type=\"text\">\n                                                        <field name=\"TEXT\">b</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"ADD2\">\n                                                      <block type=\"text\">\n                                                        <field name=\"TEXT\">c</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"ADD3\">\n                                                      <block type=\"text\">\n                                                        <field name=\"TEXT\">d</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <statement name=\"DO\">\n                                                  <block type=\"controls_if\" inline=\"false\">\n                                                    <value name=\"IF0\">\n                                                      <block type=\"logic_compare\" inline=\"true\">\n                                                        <field name=\"OP\">EQ</field>\n                                                        <value name=\"A\">\n                                                          <block type=\"variables_get\">\n                                                            <field name=\"VAR\">x</field>\n                                                          </block>\n                                                        </value>\n                                                        <value name=\"B\">\n                                                          <block type=\"text\">\n                                                            <field name=\"TEXT\">c</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </value>\n                                                    <statement name=\"DO0\">\n                                                      <block type=\"controls_flow_statements\">\n                                                        <field name=\"FLOW\">BREAK</field>\n                                                      </block>\n                                                    </statement>\n                                                    <next>\n                                                      <block type=\"text_append\" inline=\"false\">\n                                                        <field name=\"VAR\">log</field>\n                                                        <value name=\"TEXT\">\n                                                          <block type=\"variables_get\">\n                                                            <field name=\"VAR\">x</field>\n                                                          </block>\n                                                        </value>\n                                                      </block>\n                                                    </next>\n                                                  </block>\n                                                </statement>\n                                                <next>\n                                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                                    <field name=\"MESSAGE\">for break</field>\n                                                    <value name=\"ACTUAL\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">log</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"EXPECTED\">\n                                                      <block type=\"text\">\n                                                        <field name=\"TEXT\">ab</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"13\" y=\"300\">\n    <mutation></mutation>\n    <field name=\"NAME\">test continue</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">log</field>\n        <value name=\"VALUE\">\n          <block type=\"text\">\n            <field name=\"TEXT\"></field>\n          </block>\n        </value>\n        <next>\n          <block type=\"variables_set\" inline=\"false\">\n            <field name=\"VAR\">count</field>\n            <value name=\"VALUE\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">0</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"controls_whileUntil\" inline=\"false\">\n                <field name=\"MODE\">WHILE</field>\n                <value name=\"BOOL\">\n                  <block type=\"logic_compare\" inline=\"true\">\n                    <field name=\"OP\">NEQ</field>\n                    <value name=\"A\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">count</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">8</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <statement name=\"DO\">\n                  <block type=\"math_change\" inline=\"false\">\n                    <field name=\"VAR\">count</field>\n                    <value name=\"DELTA\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">1</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"controls_if\" inline=\"false\">\n                        <value name=\"IF0\">\n                          <block type=\"logic_compare\" inline=\"true\">\n                            <field name=\"OP\">EQ</field>\n                            <value name=\"A\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">count</field>\n                              </block>\n                            </value>\n                            <value name=\"B\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">5</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <statement name=\"DO0\">\n                          <block type=\"controls_flow_statements\">\n                            <field name=\"FLOW\">CONTINUE</field>\n                          </block>\n                        </statement>\n                        <next>\n                          <block type=\"text_append\" inline=\"false\">\n                            <field name=\"VAR\">log</field>\n                            <value name=\"TEXT\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">count</field>\n                              </block>\n                            </value>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </statement>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">while continue</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">log</field>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">1234678</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"variables_set\" inline=\"false\">\n                        <field name=\"VAR\">log</field>\n                        <value name=\"VALUE\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\"></field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"variables_set\" inline=\"false\">\n                            <field name=\"VAR\">count</field>\n                            <value name=\"VALUE\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">0</field>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"controls_whileUntil\" inline=\"false\">\n                                <field name=\"MODE\">UNTIL</field>\n                                <value name=\"BOOL\">\n                                  <block type=\"logic_compare\" inline=\"true\">\n                                    <field name=\"OP\">EQ</field>\n                                    <value name=\"A\">\n                                      <block type=\"variables_get\">\n                                        <field name=\"VAR\">count</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"B\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">8</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <statement name=\"DO\">\n                                  <block type=\"math_change\" inline=\"false\">\n                                    <field name=\"VAR\">count</field>\n                                    <value name=\"DELTA\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">1</field>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"controls_if\" inline=\"false\">\n                                        <value name=\"IF0\">\n                                          <block type=\"logic_compare\" inline=\"true\">\n                                            <field name=\"OP\">EQ</field>\n                                            <value name=\"A\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">count</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"B\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">5</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <statement name=\"DO0\">\n                                          <block type=\"controls_flow_statements\">\n                                            <field name=\"FLOW\">CONTINUE</field>\n                                          </block>\n                                        </statement>\n                                        <next>\n                                          <block type=\"text_append\" inline=\"false\">\n                                            <field name=\"VAR\">log</field>\n                                            <value name=\"TEXT\">\n                                              <block type=\"variables_get\">\n                                                <field name=\"VAR\">count</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </statement>\n                                <next>\n                                  <block type=\"unittest_assertequals\" inline=\"false\">\n                                    <field name=\"MESSAGE\">until continue</field>\n                                    <value name=\"ACTUAL\">\n                                      <block type=\"variables_get\">\n                                        <field name=\"VAR\">log</field>\n                                      </block>\n                                    </value>\n                                    <value name=\"EXPECTED\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">1234678</field>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"variables_set\" inline=\"false\">\n                                        <field name=\"VAR\">log</field>\n                                        <value name=\"VALUE\">\n                                          <block type=\"text\">\n                                            <field name=\"TEXT\"></field>\n                                          </block>\n                                        </value>\n                                        <next>\n                                          <block type=\"controls_for\" inline=\"true\">\n                                            <field name=\"VAR\">x</field>\n                                            <value name=\"FROM\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">1</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"TO\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">8</field>\n                                              </block>\n                                            </value>\n                                            <statement name=\"DO\">\n                                              <block type=\"controls_if\" inline=\"false\">\n                                                <value name=\"IF0\">\n                                                  <block type=\"logic_compare\" inline=\"true\">\n                                                    <field name=\"OP\">EQ</field>\n                                                    <value name=\"A\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">x</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"B\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">5</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                                <statement name=\"DO0\">\n                                                  <block type=\"controls_flow_statements\">\n                                                    <field name=\"FLOW\">CONTINUE</field>\n                                                  </block>\n                                                </statement>\n                                                <next>\n                                                  <block type=\"text_append\" inline=\"false\">\n                                                    <field name=\"VAR\">log</field>\n                                                    <value name=\"TEXT\">\n                                                      <block type=\"variables_get\">\n                                                        <field name=\"VAR\">x</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </statement>\n                                            <next>\n                                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                                <field name=\"MESSAGE\">count continue</field>\n                                                <value name=\"ACTUAL\">\n                                                  <block type=\"variables_get\">\n                                                    <field name=\"VAR\">log</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"EXPECTED\">\n                                                  <block type=\"text\">\n                                                    <field name=\"TEXT\">1234678</field>\n                                                  </block>\n                                                </value>\n                                                <next>\n                                                  <block type=\"variables_set\" inline=\"false\">\n                                                    <field name=\"VAR\">log</field>\n                                                    <value name=\"VALUE\">\n                                                      <block type=\"text\">\n                                                        <field name=\"TEXT\"></field>\n                                                      </block>\n                                                    </value>\n                                                    <next>\n                                                      <block type=\"controls_forEach\" inline=\"false\">\n                                                        <field name=\"VAR\">x</field>\n                                                        <value name=\"LIST\">\n                                                          <block type=\"lists_create_with\" inline=\"false\">\n                                                            <mutation items=\"4\"></mutation>\n                                                            <value name=\"ADD0\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">a</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD1\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">b</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD2\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">c</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"ADD3\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">d</field>\n                                                              </block>\n                                                            </value>\n                                                          </block>\n                                                        </value>\n                                                        <statement name=\"DO\">\n                                                          <block type=\"controls_if\" inline=\"false\">\n                                                            <value name=\"IF0\">\n                                                              <block type=\"logic_compare\" inline=\"true\">\n                                                                <field name=\"OP\">EQ</field>\n                                                                <value name=\"A\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">x</field>\n                                                                  </block>\n                                                                </value>\n                                                                <value name=\"B\">\n                                                                  <block type=\"text\">\n                                                                    <field name=\"TEXT\">c</field>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </value>\n                                                            <statement name=\"DO0\">\n                                                              <block type=\"controls_flow_statements\">\n                                                                <field name=\"FLOW\">CONTINUE</field>\n                                                              </block>\n                                                            </statement>\n                                                            <next>\n                                                              <block type=\"text_append\" inline=\"false\">\n                                                                <field name=\"VAR\">log</field>\n                                                                <value name=\"TEXT\">\n                                                                  <block type=\"variables_get\">\n                                                                    <field name=\"VAR\">x</field>\n                                                                  </block>\n                                                                </value>\n                                                              </block>\n                                                            </next>\n                                                          </block>\n                                                        </statement>\n                                                        <next>\n                                                          <block type=\"unittest_assertequals\" inline=\"false\">\n                                                            <field name=\"MESSAGE\">for continue</field>\n                                                            <value name=\"ACTUAL\">\n                                                              <block type=\"variables_get\">\n                                                                <field name=\"VAR\">log</field>\n                                                              </block>\n                                                            </value>\n                                                            <value name=\"EXPECTED\">\n                                                              <block type=\"text\">\n                                                                <field name=\"TEXT\">abd</field>\n                                                              </block>\n                                                            </value>\n                                                          </block>\n                                                        </next>\n                                                      </block>\n                                                    </next>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/math.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"unittest_main\" x=\"1\" y=\"-198\">\n    <statement name=\"DO\">\n      <block type=\"procedures_callnoreturn\">\n        <mutation name=\"test arithmetic\"></mutation>\n        <next>\n          <block type=\"procedures_callnoreturn\">\n            <mutation name=\"test operations on single\"></mutation>\n            <next>\n              <block type=\"procedures_callnoreturn\">\n                <mutation name=\"test trig\"></mutation>\n                <next>\n                  <block type=\"procedures_callnoreturn\">\n                    <mutation name=\"test constant\"></mutation>\n                    <next>\n                      <block type=\"procedures_callnoreturn\">\n                        <mutation name=\"test change\"></mutation>\n                        <next>\n                          <block type=\"procedures_callnoreturn\">\n                            <mutation name=\"test number properties\"></mutation>\n                            <next>\n                              <block type=\"procedures_callnoreturn\">\n                                <mutation name=\"test round\"></mutation>\n                                <next>\n                                  <block type=\"procedures_callnoreturn\">\n                                    <mutation name=\"test operations on list\"></mutation>\n                                    <next>\n                                      <block type=\"procedures_callnoreturn\">\n                                        <mutation name=\"test constraint\"></mutation>\n                                        <next>\n                                          <block type=\"procedures_callnoreturn\">\n                                            <mutation name=\"test mod\"></mutation>\n                                            <next>\n                                              <block type=\"procedures_callnoreturn\">\n                                                <mutation name=\"test random integer\"></mutation>\n                                                <next>\n                                                  <block type=\"procedures_callnoreturn\">\n                                                    <mutation name=\"test random fraction\"></mutation>\n                                                  </block>\n                                                </next>\n                                              </block>\n                                            </next>\n                                          </block>\n                                        </next>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"395\" y=\"125\">\n    <mutation></mutation>\n    <field name=\"NAME\">test operations on single</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">sqrt</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_single\" inline=\"false\">\n            <field name=\"OP\">ROOT</field>\n            <value name=\"NUM\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">25</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">5</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">abs</field>\n            <value name=\"ACTUAL\">\n              <block type=\"math_single\" inline=\"false\">\n                <field name=\"OP\">ABS</field>\n                <value name=\"NUM\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">-25</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">25</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">negate</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"math_single\" inline=\"false\">\n                    <field name=\"OP\">NEG</field>\n                    <value name=\"NUM\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">-25</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">25</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">ln</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"math_single\" inline=\"false\">\n                        <field name=\"OP\">LN</field>\n                        <value name=\"NUM\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">1</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">0</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">log10</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"math_single\" inline=\"false\">\n                            <field name=\"OP\">LOG10</field>\n                            <value name=\"NUM\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">100</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">2</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">exp</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"math_single\" inline=\"false\">\n                                <field name=\"OP\">EXP</field>\n                                <value name=\"NUM\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">2</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">7.38905609893065</field>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                <field name=\"MESSAGE\">power10</field>\n                                <value name=\"ACTUAL\">\n                                  <block type=\"math_single\" inline=\"false\">\n                                    <field name=\"OP\">POW10</field>\n                                    <value name=\"NUM\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">2</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <value name=\"EXPECTED\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">100</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"23\" y=\"194\">\n    <mutation></mutation>\n    <field name=\"NAME\">test arithmetic</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">add</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_arithmetic\" inline=\"true\">\n            <field name=\"OP\">ADD</field>\n            <value name=\"A\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">1</field>\n              </block>\n            </value>\n            <value name=\"B\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">2</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">3</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">subtract</field>\n            <value name=\"ACTUAL\">\n              <block type=\"math_arithmetic\" inline=\"true\">\n                <field name=\"OP\">MINUS</field>\n                <value name=\"A\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">1</field>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">2</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">-1</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">multiply</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"math_arithmetic\" inline=\"true\">\n                    <field name=\"OP\">MULTIPLY</field>\n                    <value name=\"A\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">4</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">2.5</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">10</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">divide</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"math_arithmetic\" inline=\"true\">\n                        <field name=\"OP\">DIVIDE</field>\n                        <value name=\"A\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">8.2</field>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">-5</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">-1.64</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">power</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"math_arithmetic\" inline=\"true\">\n                            <field name=\"OP\">POWER</field>\n                            <value name=\"A\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">10</field>\n                              </block>\n                            </value>\n                            <value name=\"B\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">4</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">10000</field>\n                          </block>\n                        </value>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"16\" y=\"727\">\n    <mutation></mutation>\n    <field name=\"NAME\">test trig</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">sin</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_trig\" inline=\"false\">\n            <field name=\"OP\">SIN</field>\n            <value name=\"NUM\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">90</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">cos</field>\n            <value name=\"ACTUAL\">\n              <block type=\"math_trig\" inline=\"false\">\n                <field name=\"OP\">COS</field>\n                <value name=\"NUM\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">180</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">-1</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">tan</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"math_trig\" inline=\"false\">\n                    <field name=\"OP\">TAN</field>\n                    <value name=\"NUM\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">0</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">0</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">asin</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"math_trig\" inline=\"false\">\n                        <field name=\"OP\">ASIN</field>\n                        <value name=\"NUM\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">-1</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">-90</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">acos</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"math_trig\" inline=\"false\">\n                            <field name=\"OP\">ACOS</field>\n                            <value name=\"NUM\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">1</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">0</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">atan</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"math_trig\" inline=\"false\">\n                                <field name=\"OP\">ATAN</field>\n                                <value name=\"NUM\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">1</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">45</field>\n                              </block>\n                            </value>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"311\" y=\"733\">\n    <mutation></mutation>\n    <field name=\"NAME\">test constant</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">const pi</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_round\" inline=\"false\">\n            <field name=\"OP\">ROUNDDOWN</field>\n            <value name=\"NUM\">\n              <block type=\"math_arithmetic\" inline=\"true\">\n                <field name=\"OP\">MULTIPLY</field>\n                <value name=\"A\">\n                  <block type=\"math_constant\">\n                    <field name=\"CONSTANT\">PI</field>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">1000</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">3141</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">const e</field>\n            <value name=\"ACTUAL\">\n              <block type=\"math_round\" inline=\"false\">\n                <field name=\"OP\">ROUNDDOWN</field>\n                <value name=\"NUM\">\n                  <block type=\"math_arithmetic\" inline=\"true\">\n                    <field name=\"OP\">MULTIPLY</field>\n                    <value name=\"A\">\n                      <block type=\"math_constant\">\n                        <field name=\"CONSTANT\">E</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">1000</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">2718</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">const golden</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"math_round\" inline=\"false\">\n                    <field name=\"OP\">ROUNDDOWN</field>\n                    <value name=\"NUM\">\n                      <block type=\"math_arithmetic\" inline=\"true\">\n                        <field name=\"OP\">MULTIPLY</field>\n                        <value name=\"A\">\n                          <block type=\"math_constant\">\n                            <field name=\"CONSTANT\">GOLDEN_RATIO</field>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">1000</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">1618</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">const sqrt 2</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"math_round\" inline=\"false\">\n                        <field name=\"OP\">ROUNDDOWN</field>\n                        <value name=\"NUM\">\n                          <block type=\"math_arithmetic\" inline=\"true\">\n                            <field name=\"OP\">MULTIPLY</field>\n                            <value name=\"A\">\n                              <block type=\"math_constant\">\n                                <field name=\"CONSTANT\">SQRT2</field>\n                              </block>\n                            </value>\n                            <value name=\"B\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">1000</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">1414</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">const sqrt 0.5</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"math_round\" inline=\"false\">\n                            <field name=\"OP\">ROUNDDOWN</field>\n                            <value name=\"NUM\">\n                              <block type=\"math_arithmetic\" inline=\"true\">\n                                <field name=\"OP\">MULTIPLY</field>\n                                <value name=\"A\">\n                                  <block type=\"math_constant\">\n                                    <field name=\"CONSTANT\">SQRT1_2</field>\n                                  </block>\n                                </value>\n                                <value name=\"B\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">1000</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">707</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertvalue\" inline=\"false\">\n                            <field name=\"MESSAGE\">const infinity</field>\n                            <field name=\"EXPECTED\">TRUE</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"logic_compare\" inline=\"true\">\n                                <field name=\"OP\">LT</field>\n                                <value name=\"A\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">9999</field>\n                                  </block>\n                                </value>\n                                <value name=\"B\">\n                                  <block type=\"math_constant\">\n                                    <field name=\"CONSTANT\">INFINITY</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"18\" y=\"1279\">\n    <mutation></mutation>\n    <field name=\"NAME\">test number properties</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertvalue\" inline=\"false\">\n        <field name=\"MESSAGE\">even</field>\n        <field name=\"EXPECTED\">TRUE</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_number_property\" inline=\"true\">\n            <mutation divisor_input=\"false\"></mutation>\n            <field name=\"PROPERTY\">EVEN</field>\n            <value name=\"NUMBER_TO_CHECK\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">42</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">odd</field>\n            <field name=\"EXPECTED\">FALSE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"math_number_property\" inline=\"true\">\n                <mutation divisor_input=\"false\"></mutation>\n                <field name=\"PROPERTY\">ODD</field>\n                <value name=\"NUMBER_TO_CHECK\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">42.1</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertvalue\" inline=\"false\">\n                <field name=\"MESSAGE\">prime 5</field>\n                <field name=\"EXPECTED\">TRUE</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"math_number_property\" inline=\"true\">\n                    <mutation divisor_input=\"false\"></mutation>\n                    <field name=\"PROPERTY\">PRIME</field>\n                    <value name=\"NUMBER_TO_CHECK\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">5</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                    <field name=\"MESSAGE\">prime 25</field>\n                    <field name=\"EXPECTED\">FALSE</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"math_number_property\" inline=\"true\">\n                        <mutation divisor_input=\"false\"></mutation>\n                        <field name=\"PROPERTY\">PRIME</field>\n                        <value name=\"NUMBER_TO_CHECK\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">25</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertvalue\" inline=\"false\">\n                        <field name=\"MESSAGE\">prime negative</field>\n                        <field name=\"EXPECTED\">FALSE</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"math_number_property\" inline=\"true\">\n                            <mutation divisor_input=\"false\"></mutation>\n                            <field name=\"PROPERTY\">PRIME</field>\n                            <value name=\"NUMBER_TO_CHECK\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">-31.1</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertvalue\" inline=\"false\">\n                            <field name=\"MESSAGE\">whole</field>\n                            <field name=\"EXPECTED\">FALSE</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"math_number_property\" inline=\"true\">\n                                <mutation divisor_input=\"false\"></mutation>\n                                <field name=\"PROPERTY\">WHOLE</field>\n                                <value name=\"NUMBER_TO_CHECK\">\n                                  <block type=\"math_constant\">\n                                    <field name=\"CONSTANT\">PI</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"unittest_assertvalue\" inline=\"false\">\n                                <field name=\"MESSAGE\">positive</field>\n                                <field name=\"EXPECTED\">TRUE</field>\n                                <value name=\"ACTUAL\">\n                                  <block type=\"math_number_property\" inline=\"true\">\n                                    <mutation divisor_input=\"false\"></mutation>\n                                    <field name=\"PROPERTY\">POSITIVE</field>\n                                    <value name=\"NUMBER_TO_CHECK\">\n                                      <block type=\"math_constant\">\n                                        <field name=\"CONSTANT\">INFINITY</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                                    <field name=\"MESSAGE\">negative</field>\n                                    <field name=\"EXPECTED\">TRUE</field>\n                                    <value name=\"ACTUAL\">\n                                      <block type=\"math_number_property\" inline=\"true\">\n                                        <mutation divisor_input=\"false\"></mutation>\n                                        <field name=\"PROPERTY\">NEGATIVE</field>\n                                        <value name=\"NUMBER_TO_CHECK\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">-42</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                    <next>\n                                      <block type=\"unittest_assertvalue\" inline=\"false\">\n                                        <field name=\"MESSAGE\">divisible</field>\n                                        <field name=\"EXPECTED\">TRUE</field>\n                                        <value name=\"ACTUAL\">\n                                          <block type=\"math_number_property\" inline=\"true\">\n                                            <mutation divisor_input=\"true\"></mutation>\n                                            <field name=\"PROPERTY\">DIVISIBLE_BY</field>\n                                            <value name=\"NUMBER_TO_CHECK\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">42</field>\n                                              </block>\n                                            </value>\n                                            <value name=\"DIVISOR\">\n                                              <block type=\"math_number\">\n                                                <field name=\"NUM\">2</field>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"387\" y=\"1282\">\n    <mutation></mutation>\n    <field name=\"NAME\">test round</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">round</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_round\" inline=\"false\">\n            <field name=\"OP\">ROUND</field>\n            <value name=\"NUM\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">42.42</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">42</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">round up</field>\n            <value name=\"ACTUAL\">\n              <block type=\"math_round\" inline=\"false\">\n                <field name=\"OP\">ROUNDUP</field>\n                <value name=\"NUM\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">-42.42</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">-42</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">round down</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"math_round\" inline=\"false\">\n                    <field name=\"OP\">ROUNDDOWN</field>\n                    <value name=\"NUM\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">42.42</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">42</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"394\" y=\"1819\">\n    <mutation></mutation>\n    <field name=\"NAME\">test change</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">varToChange</field>\n        <value name=\"VALUE\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">100</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"math_change\" inline=\"false\">\n            <field name=\"VAR\">varToChange</field>\n            <value name=\"DELTA\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">42</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">change</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">varToChange</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">142</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defreturn\" inline=\"false\" x=\"30\" y=\"2074\">\n    <mutation>\n      <arg name=\"a\"></arg>\n      <arg name=\"b\"></arg>\n    </mutation>\n    <field name=\"NAME\">assert list equal</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">equal</field>\n        <value name=\"VALUE\">\n          <block type=\"logic_boolean\">\n            <field name=\"BOOL\">TRUE</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"controls_if\" inline=\"false\">\n            <mutation else=\"1\"></mutation>\n            <value name=\"IF0\">\n              <block type=\"logic_compare\" inline=\"true\">\n                <field name=\"OP\">NEQ</field>\n                <value name=\"A\">\n                  <block type=\"lists_length\" inline=\"false\">\n                    <value name=\"VALUE\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">a</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"lists_length\" inline=\"false\">\n                    <value name=\"VALUE\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">b</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <statement name=\"DO0\">\n              <block type=\"variables_set\" inline=\"false\">\n                <field name=\"VAR\">equal</field>\n                <value name=\"VALUE\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">FALSE</field>\n                  </block>\n                </value>\n              </block>\n            </statement>\n            <statement name=\"ELSE\">\n              <block type=\"controls_for\" inline=\"true\">\n                <field name=\"VAR\">x</field>\n                <value name=\"FROM\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">1</field>\n                  </block>\n                </value>\n                <value name=\"TO\">\n                  <block type=\"lists_length\" inline=\"false\">\n                    <value name=\"VALUE\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">a</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <statement name=\"DO\">\n                  <block type=\"controls_if\" inline=\"false\">\n                    <value name=\"IF0\">\n                      <block type=\"logic_compare\" inline=\"false\">\n                        <field name=\"OP\">NEQ</field>\n                        <value name=\"A\">\n                          <block type=\"lists_getIndex\" inline=\"true\">\n                            <mutation statement=\"false\" at=\"true\"></mutation>\n                            <field name=\"MODE\">GET</field>\n                            <field name=\"WHERE\">FROM_START</field>\n                            <value name=\"AT\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">x</field>\n                              </block>\n                            </value>\n                            <value name=\"VALUE\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">a</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"lists_getIndex\" inline=\"true\">\n                            <mutation statement=\"false\" at=\"true\"></mutation>\n                            <field name=\"MODE\">GET</field>\n                            <field name=\"WHERE\">FROM_START</field>\n                            <value name=\"AT\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">x</field>\n                              </block>\n                            </value>\n                            <value name=\"VALUE\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">b</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <statement name=\"DO0\">\n                      <block type=\"variables_set\" inline=\"false\">\n                        <field name=\"VAR\">equal</field>\n                        <value name=\"VALUE\">\n                          <block type=\"logic_boolean\">\n                            <field name=\"BOOL\">FALSE</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"controls_flow_statements\">\n                            <field name=\"FLOW\">BREAK</field>\n                          </block>\n                        </next>\n                      </block>\n                    </statement>\n                  </block>\n                </statement>\n              </block>\n            </statement>\n            <next>\n              <block type=\"controls_if\" inline=\"false\">\n                <value name=\"IF0\">\n                  <block type=\"logic_negate\" inline=\"false\">\n                    <value name=\"BOOL\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">equal</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <statement name=\"DO0\">\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">list equality</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">a</field>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">b</field>\n                      </block>\n                    </value>\n                  </block>\n                </statement>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n    <value name=\"RETURN\">\n      <block type=\"variables_get\">\n        <field name=\"VAR\">equal</field>\n      </block>\n    </value>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"24\" y=\"2568\">\n    <mutation></mutation>\n    <field name=\"NAME\">test operations on list</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">sum</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_on_list\" inline=\"false\">\n            <field name=\"OP\">SUM</field>\n            <value name=\"LIST\">\n              <block type=\"lists_create_with\" inline=\"true\">\n                <mutation items=\"3\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">3</field>\n                  </block>\n                </value>\n                <value name=\"ADD1\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">4</field>\n                  </block>\n                </value>\n                <value name=\"ADD2\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">5</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">12</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">min</field>\n            <value name=\"ACTUAL\">\n              <block type=\"math_on_list\" inline=\"false\">\n                <field name=\"OP\">MIN</field>\n                <value name=\"LIST\">\n                  <block type=\"lists_create_with\" inline=\"true\">\n                    <mutation items=\"3\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">3</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">4</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD2\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">5</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">3</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">max</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"math_on_list\" inline=\"false\">\n                    <field name=\"OP\">MAX</field>\n                    <value name=\"LIST\">\n                      <block type=\"lists_create_with\" inline=\"true\">\n                        <mutation items=\"3\"></mutation>\n                        <value name=\"ADD0\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">3</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD1\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">4</field>\n                          </block>\n                        </value>\n                        <value name=\"ADD2\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">5</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">5</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">average</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"math_on_list\" inline=\"false\">\n                        <field name=\"OP\">AVERAGE</field>\n                        <value name=\"LIST\">\n                          <block type=\"lists_create_with\" inline=\"true\">\n                            <mutation items=\"3\"></mutation>\n                            <value name=\"ADD0\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">3</field>\n                              </block>\n                            </value>\n                            <value name=\"ADD1\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">4</field>\n                              </block>\n                            </value>\n                            <value name=\"ADD2\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">5</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">4</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">median</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"math_on_list\" inline=\"false\">\n                            <field name=\"OP\">MEDIAN</field>\n                            <value name=\"LIST\">\n                              <block type=\"lists_create_with\" inline=\"true\">\n                                <mutation items=\"4\"></mutation>\n                                <value name=\"ADD0\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">3</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD1\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">4</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD2\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">5</field>\n                                  </block>\n                                </value>\n                                <value name=\"ADD3\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">1</field>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">3.5</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertvalue\" inline=\"false\">\n                            <field name=\"MESSAGE\">modes</field>\n                            <field name=\"EXPECTED\">TRUE</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"procedures_callreturn\" inline=\"false\">\n                                <mutation name=\"assert list equal\">\n                                  <arg name=\"a\"></arg>\n                                  <arg name=\"b\"></arg>\n                                </mutation>\n                                <value name=\"ARG0\">\n                                  <block type=\"math_on_list\" inline=\"false\">\n                                    <field name=\"OP\">MODE</field>\n                                    <value name=\"LIST\">\n                                      <block type=\"lists_create_with\" inline=\"true\">\n                                        <mutation items=\"3\"></mutation>\n                                        <value name=\"ADD0\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">3</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"ADD1\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">4</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"ADD2\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">3</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <value name=\"ARG1\">\n                                  <block type=\"lists_create_with\" inline=\"true\">\n                                    <mutation items=\"1\"></mutation>\n                                    <value name=\"ADD0\">\n                                      <block type=\"math_number\">\n                                        <field name=\"NUM\">3</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"unittest_assertequals\" inline=\"false\">\n                                <field name=\"MESSAGE\">standard dev</field>\n                                <value name=\"ACTUAL\">\n                                  <block type=\"math_on_list\" inline=\"false\">\n                                    <field name=\"OP\">STD_DEV</field>\n                                    <value name=\"LIST\">\n                                      <block type=\"lists_create_with\" inline=\"true\">\n                                        <mutation items=\"3\"></mutation>\n                                        <value name=\"ADD0\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">3</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"ADD1\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">3</field>\n                                          </block>\n                                        </value>\n                                        <value name=\"ADD2\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">3</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <value name=\"EXPECTED\">\n                                  <block type=\"math_number\">\n                                    <field name=\"NUM\">0</field>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                                    <field name=\"MESSAGE\">random</field>\n                                    <field name=\"EXPECTED\">TRUE</field>\n                                    <value name=\"ACTUAL\">\n                                      <block type=\"logic_compare\" inline=\"false\">\n                                        <field name=\"OP\">GT</field>\n                                        <value name=\"A\">\n                                          <block type=\"lists_indexOf\" inline=\"false\">\n                                            <field name=\"END\">FIRST</field>\n                                            <value name=\"FIND\">\n                                              <block type=\"math_on_list\" inline=\"false\">\n                                                <field name=\"OP\">RANDOM</field>\n                                                <value name=\"LIST\">\n                                                  <block type=\"lists_create_with\" inline=\"false\">\n                                                    <mutation items=\"3\"></mutation>\n                                                    <value name=\"ADD0\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">3</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"ADD1\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">4</field>\n                                                      </block>\n                                                    </value>\n                                                    <value name=\"ADD2\">\n                                                      <block type=\"math_number\">\n                                                        <field name=\"NUM\">5</field>\n                                                      </block>\n                                                    </value>\n                                                  </block>\n                                                </value>\n                                              </block>\n                                            </value>\n                                            <value name=\"VALUE\">\n                                              <block type=\"lists_create_with\" inline=\"true\">\n                                                <mutation items=\"3\"></mutation>\n                                                <value name=\"ADD0\">\n                                                  <block type=\"math_number\">\n                                                    <field name=\"NUM\">3</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD1\">\n                                                  <block type=\"math_number\">\n                                                    <field name=\"NUM\">4</field>\n                                                  </block>\n                                                </value>\n                                                <value name=\"ADD2\">\n                                                  <block type=\"math_number\">\n                                                    <field name=\"NUM\">5</field>\n                                                  </block>\n                                                </value>\n                                              </block>\n                                            </value>\n                                          </block>\n                                        </value>\n                                        <value name=\"B\">\n                                          <block type=\"math_number\">\n                                            <field name=\"NUM\">0</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"15\" y=\"3494\">\n    <mutation></mutation>\n    <field name=\"NAME\">test mod</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">mod</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_modulo\" inline=\"true\">\n            <value name=\"DIVIDEND\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">42</field>\n              </block>\n            </value>\n            <value name=\"DIVISOR\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">5</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">2</field>\n          </block>\n        </value>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"373\" y=\"3499\">\n    <mutation></mutation>\n    <field name=\"NAME\">test constraint</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">constraint</field>\n        <value name=\"ACTUAL\">\n          <block type=\"math_constrain\" inline=\"true\">\n            <value name=\"VALUE\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">100</field>\n              </block>\n            </value>\n            <value name=\"LOW\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">0</field>\n              </block>\n            </value>\n            <value name=\"HIGH\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">42</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">42</field>\n          </block>\n        </value>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"15\" y=\"3664\">\n    <mutation></mutation>\n    <field name=\"NAME\">test random integer</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">rand</field>\n        <value name=\"VALUE\">\n          <block type=\"math_random_int\" inline=\"true\">\n            <value name=\"FROM\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">5</field>\n              </block>\n            </value>\n            <value name=\"TO\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">10</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">randRange</field>\n            <field name=\"EXPECTED\">TRUE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"logic_operation\" inline=\"true\">\n                <field name=\"OP\">AND</field>\n                <value name=\"A\">\n                  <block type=\"logic_compare\" inline=\"true\">\n                    <field name=\"OP\">GTE</field>\n                    <value name=\"A\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">rand</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">5</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"logic_compare\" inline=\"true\">\n                    <field name=\"OP\">LTE</field>\n                    <value name=\"A\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">rand</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">10</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertvalue\" inline=\"false\">\n                <field name=\"MESSAGE\">randInteger</field>\n                <field name=\"EXPECTED\">TRUE</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"math_number_property\" inline=\"true\">\n                    <mutation divisor_input=\"false\"></mutation>\n                    <field name=\"PROPERTY\">WHOLE</field>\n                    <value name=\"NUMBER_TO_CHECK\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">rand</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"15\" y=\"3931\">\n    <mutation></mutation>\n    <field name=\"NAME\">test random fraction</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">rand</field>\n        <value name=\"VALUE\">\n          <block type=\"math_random_float\"></block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">randFloat</field>\n            <field name=\"EXPECTED\">TRUE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"logic_operation\" inline=\"true\">\n                <field name=\"OP\">AND</field>\n                <value name=\"A\">\n                  <block type=\"logic_compare\" inline=\"true\">\n                    <field name=\"OP\">GTE</field>\n                    <value name=\"A\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">rand</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">0</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"B\">\n                  <block type=\"logic_compare\" inline=\"true\">\n                    <field name=\"OP\">LTE</field>\n                    <value name=\"A\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">rand</field>\n                      </block>\n                    </value>\n                    <value name=\"B\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">1</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </value>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/procedures.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"unittest_main\" x=\"0\" y=\"1\">\n    <statement name=\"DO\">\n      <block type=\"procedures_callnoreturn\">\n        <mutation name=\"test procedure\"></mutation>\n        <next>\n          <block type=\"procedures_callnoreturn\">\n            <mutation name=\"test function\"></mutation>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">test recurse</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"procedures_callreturn\" inline=\"false\">\n                    <mutation name=\"recurse\">\n                      <arg name=\"n\"></arg>\n                    </mutation>\n                    <value name=\"ARG0\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">3</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">-1-2-1-3-1-2-1-</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-3\" y=\"249\">\n    <mutation></mutation>\n    <field name=\"NAME\">test procedure</field>\n    <statement name=\"STACK\">\n      <block type=\"procedures_callnoreturn\" inline=\"false\">\n        <mutation name=\"procedure 1\">\n          <arg name=\"proc x\"></arg>\n          <arg name=\"proc y\"></arg>\n        </mutation>\n        <value name=\"ARG0\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">8</field>\n          </block>\n        </value>\n        <value name=\"ARG1\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">2</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">procedure with global</field>\n            <value name=\"ACTUAL\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">proc z</field>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">4</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"variables_set\" inline=\"false\">\n                <field name=\"VAR\">proc w</field>\n                <value name=\"VALUE\">\n                  <block type=\"logic_boolean\">\n                    <field name=\"BOOL\">FALSE</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"procedures_callnoreturn\" inline=\"false\">\n                    <mutation name=\"procedure 2\">\n                      <arg name=\"proc x\"></arg>\n                    </mutation>\n                    <value name=\"ARG0\">\n                      <block type=\"logic_boolean\">\n                        <field name=\"BOOL\">FALSE</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertvalue\" inline=\"false\">\n                        <field name=\"MESSAGE\">procedure no return</field>\n                        <field name=\"EXPECTED\">TRUE</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">proc w</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"variables_set\" inline=\"false\">\n                            <field name=\"VAR\">proc w</field>\n                            <value name=\"VALUE\">\n                              <block type=\"logic_boolean\">\n                                <field name=\"BOOL\">FALSE</field>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"procedures_callnoreturn\" inline=\"false\">\n                                <mutation name=\"procedure 2\">\n                                  <arg name=\"proc x\"></arg>\n                                </mutation>\n                                <value name=\"ARG0\">\n                                  <block type=\"logic_boolean\">\n                                    <field name=\"BOOL\">TRUE</field>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                                    <field name=\"MESSAGE\">procedure return</field>\n                                    <field name=\"EXPECTED\">FALSE</field>\n                                    <value name=\"ACTUAL\">\n                                      <block type=\"variables_get\">\n                                        <field name=\"VAR\">proc w</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"302\" y=\"277\">\n    <mutation>\n      <arg name=\"proc x\"></arg>\n      <arg name=\"proc y\"></arg>\n    </mutation>\n    <field name=\"NAME\">procedure 1</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">proc z</field>\n        <value name=\"VALUE\">\n          <block type=\"math_arithmetic\" inline=\"true\">\n            <field name=\"OP\">DIVIDE</field>\n            <value name=\"A\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">proc x</field>\n              </block>\n            </value>\n            <value name=\"B\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">proc y</field>\n              </block>\n            </value>\n          </block>\n        </value>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"307\" y=\"435\">\n    <mutation>\n      <arg name=\"proc x\"></arg>\n    </mutation>\n    <field name=\"NAME\">procedure 2</field>\n    <statement name=\"STACK\">\n      <block type=\"procedures_ifreturn\" inline=\"true\">\n        <mutation value=\"0\"></mutation>\n        <value name=\"CONDITION\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">proc x</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"variables_set\" inline=\"false\">\n            <field name=\"VAR\">proc w</field>\n            <value name=\"VALUE\">\n              <block type=\"logic_boolean\">\n                <field name=\"BOOL\">TRUE</field>\n              </block>\n            </value>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-2\" y=\"731\">\n    <mutation></mutation>\n    <field name=\"NAME\">test function</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">function with arguments</field>\n        <value name=\"ACTUAL\">\n          <block type=\"procedures_callreturn\" inline=\"false\">\n            <mutation name=\"function 1\">\n              <arg name=\"func x\"></arg>\n              <arg name=\"func y\"></arg>\n            </mutation>\n            <value name=\"ARG0\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">2</field>\n              </block>\n            </value>\n            <value name=\"ARG1\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">3</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">-1</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">function with side effect</field>\n            <value name=\"ACTUAL\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">func z</field>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"text\">\n                <field name=\"TEXT\">side effect</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"variables_set\" inline=\"false\">\n                <field name=\"VAR\">func a</field>\n                <value name=\"VALUE\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">unchanged</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">func c</field>\n                    <value name=\"VALUE\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">global</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertequals\" inline=\"false\">\n                        <field name=\"MESSAGE\">function with global</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"procedures_callreturn\" inline=\"false\">\n                            <mutation name=\"function 2\">\n                              <arg name=\"func a\"></arg>\n                            </mutation>\n                            <value name=\"ARG0\">\n                              <block type=\"math_number\">\n                                <field name=\"NUM\">2</field>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                        <value name=\"EXPECTED\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">3global</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">function with scope</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">func a</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"text\">\n                                <field name=\"TEXT\">unchanged</field>\n                              </block>\n                            </value>\n                            <next>\n                              <block type=\"unittest_assertvalue\" inline=\"false\">\n                                <field name=\"MESSAGE\">function return</field>\n                                <field name=\"EXPECTED\">TRUE</field>\n                                <value name=\"ACTUAL\">\n                                  <block type=\"procedures_callreturn\" inline=\"false\">\n                                    <mutation name=\"function 3\">\n                                      <arg name=\"func a\"></arg>\n                                    </mutation>\n                                    <value name=\"ARG0\">\n                                      <block type=\"logic_boolean\">\n                                        <field name=\"BOOL\">TRUE</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                                <next>\n                                  <block type=\"unittest_assertvalue\" inline=\"false\">\n                                    <field name=\"MESSAGE\">function no return</field>\n                                    <field name=\"EXPECTED\">FALSE</field>\n                                    <value name=\"ACTUAL\">\n                                      <block type=\"procedures_callreturn\" inline=\"false\">\n                                        <mutation name=\"function 3\">\n                                          <arg name=\"func a\"></arg>\n                                        </mutation>\n                                        <value name=\"ARG0\">\n                                          <block type=\"logic_boolean\">\n                                            <field name=\"BOOL\">FALSE</field>\n                                          </block>\n                                        </value>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defreturn\" inline=\"false\" x=\"-3\" y=\"1384\">\n    <mutation>\n      <arg name=\"func x\"></arg>\n      <arg name=\"func y\"></arg>\n    </mutation>\n    <field name=\"NAME\">function 1</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">func z</field>\n        <value name=\"VALUE\">\n          <block type=\"text\">\n            <field name=\"TEXT\">side effect</field>\n          </block>\n        </value>\n      </block>\n    </statement>\n    <value name=\"RETURN\">\n      <block type=\"math_arithmetic\" inline=\"true\">\n        <field name=\"OP\">MINUS</field>\n        <value name=\"A\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">func x</field>\n          </block>\n        </value>\n        <value name=\"B\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">func y</field>\n          </block>\n        </value>\n      </block>\n    </value>\n  </block>\n  <block type=\"procedures_defreturn\" inline=\"false\" x=\"-1\" y=\"1503\">\n    <mutation>\n      <arg name=\"func a\"></arg>\n    </mutation>\n    <field name=\"NAME\">function 2</field>\n    <statement name=\"STACK\">\n      <block type=\"math_change\" inline=\"false\">\n        <field name=\"VAR\">func a</field>\n        <value name=\"DELTA\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n      </block>\n    </statement>\n    <value name=\"RETURN\">\n      <block type=\"text_join\" inline=\"false\">\n        <mutation items=\"2\"></mutation>\n        <value name=\"ADD0\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">func a</field>\n          </block>\n        </value>\n        <value name=\"ADD1\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">func c</field>\n          </block>\n        </value>\n      </block>\n    </value>\n  </block>\n  <block type=\"procedures_defreturn\" inline=\"false\" x=\"0\" y=\"1655\">\n    <mutation>\n      <arg name=\"func a\"></arg>\n    </mutation>\n    <field name=\"NAME\">function 3</field>\n    <statement name=\"STACK\">\n      <block type=\"procedures_ifreturn\" inline=\"true\">\n        <mutation value=\"1\"></mutation>\n        <value name=\"CONDITION\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">func a</field>\n          </block>\n        </value>\n        <value name=\"VALUE\">\n          <block type=\"logic_boolean\">\n            <field name=\"BOOL\">TRUE</field>\n          </block>\n        </value>\n      </block>\n    </statement>\n    <value name=\"RETURN\">\n      <block type=\"logic_boolean\">\n        <field name=\"BOOL\">FALSE</field>\n      </block>\n    </value>\n  </block>\n  <block type=\"procedures_defreturn\" inline=\"false\" x=\"0\" y=\"1789\">\n    <mutation>\n      <arg name=\"n\"></arg>\n    </mutation>\n    <field name=\"NAME\">recurse</field>\n    <statement name=\"STACK\">\n      <block type=\"controls_if\" inline=\"false\">\n        <mutation else=\"1\"></mutation>\n        <value name=\"IF0\">\n          <block type=\"logic_compare\" inline=\"true\">\n            <field name=\"OP\">GT</field>\n            <value name=\"A\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">n</field>\n              </block>\n            </value>\n            <value name=\"B\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">0</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <statement name=\"DO0\">\n          <block type=\"variables_set\" inline=\"false\">\n            <field name=\"VAR\">text</field>\n            <value name=\"VALUE\">\n              <block type=\"text_join\" inline=\"false\">\n                <mutation items=\"3\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"procedures_callreturn\" inline=\"false\">\n                    <mutation name=\"recurse\">\n                      <arg name=\"n\"></arg>\n                    </mutation>\n                    <value name=\"ARG0\">\n                      <block type=\"math_arithmetic\" inline=\"true\">\n                        <field name=\"OP\">MINUS</field>\n                        <value name=\"A\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">n</field>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">1</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"ADD1\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">n</field>\n                  </block>\n                </value>\n                <value name=\"ADD2\">\n                  <block type=\"procedures_callreturn\" inline=\"false\">\n                    <mutation name=\"recurse\">\n                      <arg name=\"n\"></arg>\n                    </mutation>\n                    <value name=\"ARG0\">\n                      <block type=\"math_arithmetic\" inline=\"true\">\n                        <field name=\"OP\">MINUS</field>\n                        <value name=\"A\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">n</field>\n                          </block>\n                        </value>\n                        <value name=\"B\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">1</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n              </block>\n            </value>\n          </block>\n        </statement>\n        <statement name=\"ELSE\">\n          <block type=\"variables_set\" inline=\"false\">\n            <field name=\"VAR\">text</field>\n            <value name=\"VALUE\">\n              <block type=\"text\">\n                <field name=\"TEXT\">-</field>\n              </block>\n            </value>\n          </block>\n        </statement>\n      </block>\n    </statement>\n    <value name=\"RETURN\">\n      <block type=\"variables_get\">\n        <field name=\"VAR\">text</field>\n      </block>\n    </value>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/text.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"unittest_main\" x=\"-33\" y=\"-11\">\n    <statement name=\"DO\">\n      <block type=\"procedures_callnoreturn\">\n        <mutation name=\"test create text\"></mutation>\n        <next>\n          <block type=\"procedures_callnoreturn\">\n            <mutation name=\"test append item\"></mutation>\n            <next>\n              <block type=\"procedures_callnoreturn\">\n                <mutation name=\"test length\"></mutation>\n                <next>\n                  <block type=\"procedures_callnoreturn\">\n                    <mutation name=\"test empty\"></mutation>\n                    <next>\n                      <block type=\"procedures_callnoreturn\">\n                        <mutation name=\"test substring\"></mutation>\n                        <next>\n                          <block type=\"procedures_callnoreturn\">\n                            <mutation name=\"test find\"></mutation>\n                            <next>\n                              <block type=\"procedures_callnoreturn\">\n                                <mutation name=\"test letter\"></mutation>\n                                <next>\n                                  <block type=\"procedures_callnoreturn\">\n                                    <mutation name=\"test case\"></mutation>\n                                    <next>\n                                      <block type=\"procedures_callnoreturn\">\n                                        <mutation name=\"test trim\"></mutation>\n                                      </block>\n                                    </next>\n                                  </block>\n                                </next>\n                              </block>\n                            </next>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"261\" y=\"3\">\n    <mutation></mutation>\n    <field name=\"NAME\">test length</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">length</field>\n        <value name=\"ACTUAL\">\n          <block type=\"text_length\" inline=\"false\">\n            <value name=\"VALUE\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Google</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">6</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">length</field>\n            <value name=\"ACTUAL\">\n              <block type=\"text_length\" inline=\"false\">\n                <value name=\"VALUE\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\"></field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">0</field>\n              </block>\n            </value>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"266\" y=\"219\">\n    <mutation></mutation>\n    <field name=\"NAME\">test empty</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertvalue\" inline=\"false\">\n        <field name=\"MESSAGE\">not empty</field>\n        <field name=\"EXPECTED\">FALSE</field>\n        <value name=\"ACTUAL\">\n          <block type=\"text_isEmpty\" inline=\"false\">\n            <value name=\"VALUE\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Google</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertvalue\" inline=\"false\">\n            <field name=\"MESSAGE\">empty</field>\n            <field name=\"EXPECTED\">TRUE</field>\n            <value name=\"ACTUAL\">\n              <block type=\"text_isEmpty\" inline=\"false\">\n                <value name=\"VALUE\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\"></field>\n                  </block>\n                </value>\n              </block>\n            </value>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-21\" y=\"342\">\n    <mutation></mutation>\n    <field name=\"NAME\">test create text</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">single text</field>\n        <value name=\"ACTUAL\">\n          <block type=\"text_join\" inline=\"false\">\n            <mutation items=\"1\"></mutation>\n            <value name=\"ADD0\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Hello</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"text\">\n            <field name=\"TEXT\">Hello</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">double text</field>\n            <value name=\"ACTUAL\">\n              <block type=\"text_join\" inline=\"false\">\n                <mutation items=\"2\"></mutation>\n                <value name=\"ADD0\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">K</field>\n                  </block>\n                </value>\n                <value name=\"ADD1\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">9</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"text\">\n                <field name=\"TEXT\">K9</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">triple text</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"text_join\" inline=\"false\">\n                    <mutation items=\"3\"></mutation>\n                    <value name=\"ADD0\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">1</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD1\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">2</field>\n                      </block>\n                    </value>\n                    <value name=\"ADD2\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">3</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">123</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-23\" y=\"733\">\n    <mutation></mutation>\n    <field name=\"NAME\">test append item</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">item</field>\n        <value name=\"VALUE\">\n          <block type=\"text\">\n            <field name=\"TEXT\">Miserable</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"text_append\" inline=\"false\">\n            <field name=\"VAR\">item</field>\n            <value name=\"TEXT\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Failure</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">append text</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">item</field>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">MiserableFailure</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"variables_set\" inline=\"false\">\n                    <field name=\"VAR\">item</field>\n                    <value name=\"VALUE\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">12</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"text_append\" inline=\"false\">\n                        <field name=\"VAR\">item</field>\n                        <value name=\"TEXT\">\n                          <block type=\"math_number\">\n                            <field name=\"NUM\">34</field>\n                          </block>\n                        </value>\n                        <next>\n                          <block type=\"unittest_assertequals\" inline=\"false\">\n                            <field name=\"MESSAGE\">append number</field>\n                            <value name=\"ACTUAL\">\n                              <block type=\"variables_get\">\n                                <field name=\"VAR\">item</field>\n                              </block>\n                            </value>\n                            <value name=\"EXPECTED\">\n                              <block type=\"text\">\n                                <field name=\"TEXT\">1234</field>\n                              </block>\n                            </value>\n                          </block>\n                        </next>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-24\" y=\"1069\">\n    <mutation></mutation>\n    <field name=\"NAME\">test substring</field>\n    <statement name=\"STACK\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">text</field>\n        <value name=\"VALUE\">\n          <block type=\"text\">\n            <field name=\"TEXT\">123456789</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">substring # start</field>\n            <value name=\"ACTUAL\">\n              <block type=\"text_getSubstring\" inline=\"true\">\n                <mutation at1=\"true\" at2=\"true\"></mutation>\n                <field name=\"WHERE1\">FROM_START</field>\n                <field name=\"WHERE2\">FROM_START</field>\n                <value name=\"STRING\">\n                  <block type=\"variables_get\">\n                    <field name=\"VAR\">text</field>\n                  </block>\n                </value>\n                <value name=\"AT1\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">2</field>\n                  </block>\n                </value>\n                <value name=\"AT2\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">3</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"text\">\n                <field name=\"TEXT\">23</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">substring # end</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"text_getSubstring\" inline=\"true\">\n                    <mutation at1=\"true\" at2=\"true\"></mutation>\n                    <field name=\"WHERE1\">FROM_END</field>\n                    <field name=\"WHERE2\">FROM_END</field>\n                    <value name=\"STRING\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">text</field>\n                      </block>\n                    </value>\n                    <value name=\"AT1\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">3</field>\n                      </block>\n                    </value>\n                    <value name=\"AT2\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">2</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">78</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">substring first-last</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"text_getSubstring\" inline=\"true\">\n                        <mutation at1=\"false\" at2=\"false\"></mutation>\n                        <field name=\"WHERE1\">FIRST</field>\n                        <field name=\"WHERE2\">LAST</field>\n                        <value name=\"STRING\">\n                          <block type=\"variables_get\">\n                            <field name=\"VAR\">text</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">text</field>\n                      </block>\n                    </value>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-24\" y=\"1429\">\n    <mutation></mutation>\n    <field name=\"NAME\">test find</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">first find</field>\n        <value name=\"ACTUAL\">\n          <block type=\"text_indexOf\" inline=\"true\">\n            <field name=\"END\">FIRST</field>\n            <value name=\"VALUE\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Banana</field>\n              </block>\n            </value>\n            <value name=\"FIND\">\n              <block type=\"text\">\n                <field name=\"TEXT\">an</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">2</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">last find</field>\n            <value name=\"ACTUAL\">\n              <block type=\"text_indexOf\" inline=\"true\">\n                <field name=\"END\">LAST</field>\n                <value name=\"VALUE\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Banana</field>\n                  </block>\n                </value>\n                <value name=\"FIND\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">an</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">4</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">no find</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"text_indexOf\" inline=\"true\">\n                    <field name=\"END\">FIRST</field>\n                    <value name=\"VALUE\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Banana</field>\n                      </block>\n                    </value>\n                    <value name=\"FIND\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Peel</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">0</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-22\" y=\"1789\">\n    <mutation></mutation>\n    <field name=\"NAME\">test letter</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">letter #</field>\n        <value name=\"ACTUAL\">\n          <block type=\"text_charAt\" inline=\"true\">\n            <mutation at=\"true\"></mutation>\n            <field name=\"WHERE\">FROM_START</field>\n            <value name=\"VALUE\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Blockly</field>\n              </block>\n            </value>\n            <value name=\"AT\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">3</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"text\">\n            <field name=\"TEXT\">o</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">letter # from end</field>\n            <value name=\"ACTUAL\">\n              <block type=\"text_charAt\" inline=\"true\">\n                <mutation at=\"true\"></mutation>\n                <field name=\"WHERE\">FROM_END</field>\n                <value name=\"VALUE\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Blockly</field>\n                  </block>\n                </value>\n                <value name=\"AT\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">3</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"text\">\n                <field name=\"TEXT\">k</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">first letter</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"text_charAt\" inline=\"true\">\n                    <mutation at=\"false\"></mutation>\n                    <field name=\"WHERE\">FIRST</field>\n                    <value name=\"VALUE\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">Blockly</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">B</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">last letter</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"text_charAt\" inline=\"true\">\n                        <mutation at=\"false\"></mutation>\n                        <field name=\"WHERE\">LAST</field>\n                        <value name=\"VALUE\">\n                          <block type=\"text\">\n                            <field name=\"TEXT\">Blockly</field>\n                          </block>\n                        </value>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">y</field>\n                      </block>\n                    </value>\n                    <next>\n                      <block type=\"unittest_assertvalue\" inline=\"false\">\n                        <field name=\"MESSAGE\">random letter</field>\n                        <field name=\"EXPECTED\">TRUE</field>\n                        <value name=\"ACTUAL\">\n                          <block type=\"math_number_property\" inline=\"true\">\n                            <mutation divisor_input=\"false\"></mutation>\n                            <field name=\"PROPERTY\">POSITIVE</field>\n                            <value name=\"NUMBER_TO_CHECK\">\n                              <block type=\"text_indexOf\" inline=\"false\">\n                                <field name=\"END\">FIRST</field>\n                                <value name=\"VALUE\">\n                                  <block type=\"text\">\n                                    <field name=\"TEXT\">Blockly</field>\n                                  </block>\n                                </value>\n                                <value name=\"FIND\">\n                                  <block type=\"text_charAt\" inline=\"true\">\n                                    <mutation at=\"false\"></mutation>\n                                    <field name=\"WHERE\">RANDOM</field>\n                                    <value name=\"VALUE\">\n                                      <block type=\"text\">\n                                        <field name=\"TEXT\">Blockly</field>\n                                      </block>\n                                    </value>\n                                  </block>\n                                </value>\n                              </block>\n                            </value>\n                          </block>\n                        </value>\n                      </block>\n                    </next>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-20\" y=\"2295\">\n    <mutation></mutation>\n    <field name=\"NAME\">test case</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">uppercase</field>\n        <value name=\"ACTUAL\">\n          <block type=\"text_changeCase\" inline=\"false\">\n            <field name=\"CASE\">UPPERCASE</field>\n            <value name=\"TEXT\">\n              <block type=\"text\">\n                <field name=\"TEXT\">Hello World</field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"text\">\n            <field name=\"TEXT\">HELLO WORLD</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">lowercase</field>\n            <value name=\"ACTUAL\">\n              <block type=\"text_changeCase\" inline=\"false\">\n                <field name=\"CASE\">LOWERCASE</field>\n                <value name=\"TEXT\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Hello World</field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"text\">\n                <field name=\"TEXT\">hello world</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">titlecase</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"text_changeCase\" inline=\"false\">\n                    <field name=\"CASE\">TITLECASE</field>\n                    <value name=\"TEXT\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">heLLo WorlD</field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">Hello World</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n  <block type=\"procedures_defnoreturn\" x=\"-20\" y=\"2598\">\n    <mutation></mutation>\n    <field name=\"NAME\">test trim</field>\n    <statement name=\"STACK\">\n      <block type=\"unittest_assertequals\" inline=\"false\">\n        <field name=\"MESSAGE\">trim both</field>\n        <value name=\"ACTUAL\">\n          <block type=\"text_trim\" inline=\"false\">\n            <mutation plural=\"true\"></mutation>\n            <field name=\"MODE\">BOTH</field>\n            <value name=\"TEXT\">\n              <block type=\"text\">\n                <field name=\"TEXT\">   abc def   </field>\n              </block>\n            </value>\n          </block>\n        </value>\n        <value name=\"EXPECTED\">\n          <block type=\"text\">\n            <field name=\"TEXT\">abc def</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">trim left</field>\n            <value name=\"ACTUAL\">\n              <block type=\"text_trim\" inline=\"false\">\n                <mutation plural=\"false\"></mutation>\n                <field name=\"MODE\">LEFT</field>\n                <value name=\"TEXT\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">   abc def   </field>\n                  </block>\n                </value>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"text\">\n                <field name=\"TEXT\">abc def   </field>\n              </block>\n            </value>\n            <next>\n              <block type=\"unittest_assertequals\" inline=\"false\">\n                <field name=\"MESSAGE\">trim right</field>\n                <value name=\"ACTUAL\">\n                  <block type=\"text_trim\" inline=\"false\">\n                    <mutation plural=\"false\"></mutation>\n                    <field name=\"MODE\">RIGHT</field>\n                    <value name=\"TEXT\">\n                      <block type=\"text\">\n                        <field name=\"TEXT\">   abc def   </field>\n                      </block>\n                    </value>\n                  </block>\n                </value>\n                <value name=\"EXPECTED\">\n                  <block type=\"text\">\n                    <field name=\"TEXT\">   abc def</field>\n                  </block>\n                </value>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/generators/unittest.js",
    "content": "/**\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Unit test blocks for Blockly.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\nBlockly.Blocks['unittest_main'] = {\n  // Container for unit tests.\n  init: function() {\n    this.setColour(65);\n    this.appendDummyInput()\n        .appendField('run tests');\n    this.appendStatementInput('DO');\n    this.setTooltip('Executes the enclosed unit tests,\\n' +\n                    'then prints a summary.');\n  },\n  getVars: function() {\n    return ['unittestResults'];\n  }\n};\n\nBlockly.Blocks['unittest_assertequals'] = {\n  // Asserts that a value equals another value.\n  init: function() {\n    this.setColour(65);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldTextInput('test name'), 'MESSAGE');\n    this.appendValueInput('ACTUAL', null)\n        .appendField('actual');\n    this.appendValueInput('EXPECTED', null)\n        .appendField('expected');\n    this.setTooltip('Tests that \"actual == expected\".');\n  },\n  getVars: function() {\n    return ['unittestResults'];\n  }\n};\n\nBlockly.Blocks['unittest_assertvalue'] = {\n  // Asserts that a value is true, false, or null.\n  init: function() {\n    this.setColour(65);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldTextInput('test name'), 'MESSAGE');\n    this.appendValueInput('ACTUAL', Boolean)\n        .appendField('assert')\n        .appendField(new Blockly.FieldDropdown(\n        [['true', 'TRUE'], ['false', 'FALSE'], ['null', 'NULL']]), 'EXPECTED');\n    this.setTooltip('Tests that the value is true, false, or null.');\n  },\n  getVars: function() {\n    return ['unittestResults'];\n  }\n};\n\nBlockly.Blocks['unittest_fail'] = {\n  // Always assert an error.\n  init: function() {\n    this.setColour(65);\n    this.setPreviousStatement(true);\n    this.setNextStatement(true);\n    this.appendDummyInput()\n        .appendField(new Blockly.FieldTextInput('test name'), 'MESSAGE')\n        .appendField('fail');\n    this.setTooltip('Records an error.');\n  },\n  getVars: function() {\n    return ['unittestResults'];\n  }\n};\n"
  },
  {
    "path": "extern/blockly/tests/generators/unittest_dart.js",
    "content": "/**\n * Visual Blocks Language\n *\n * Copyright 2014 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Dart for unit test blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\nBlockly.Dart['unittest_main'] = function(block) {\n  // Container for unit tests.\n  var resultsVar = Blockly.Dart.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var functionName = Blockly.Dart.provideFunction_(\n      'unittest_report',\n      [ 'String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '() {',\n        '  // Create test report.',\n        '  List report = [];',\n        '  StringBuffer summary = new StringBuffer();',\n        '  int fails = 0;',\n        '  for (int x = 0; x < ' + resultsVar + '.length; x++) {',\n        '    if (' + resultsVar + '[x][0]) {',\n        '      summary.write(\".\");',\n        '    } else {',\n        '      summary.write(\"F\");',\n        '      fails++;',\n        '      report.add(\"\");',\n        '      report.add(\"FAIL: ${' + resultsVar + '[x][2]}\");',\n        '      report.add(' + resultsVar + '[x][1]);',\n        '    }',\n        '  }',\n        '  report.insert(0, summary.toString());',\n        '  report.add(\"\");',\n        '  report.add(\"Ran ${' + resultsVar + '.length} tests.\");',\n        '  report.add(\"\");',\n        '  if (fails != 0) {',\n        '    report.add(\"FAILED (failures=$fails)\");',\n        '  } else {',\n        '    report.add(\"OK\");',\n        '  }',\n        '  return report.join(\"\\\\n\");',\n        '}']);\n  // Setup global to hold test results.\n  var code = resultsVar + ' = [];\\n';\n  // Run tests (unindented).\n  code += Blockly.Dart.statementToCode(block, 'DO')\n      .replace(/^  /, '').replace(/\\n  /g, '\\n');\n  var reportVar = Blockly.Dart.variableDB_.getDistinctName(\n      'report', Blockly.Variables.NAME_TYPE);\n  code += 'String ' + reportVar + ' = ' + functionName + '();\\n';\n  // Destroy results.\n  code += resultsVar + ' = null;\\n';\n  // Print the report to the console (that's where errors will go anyway).\n  code += 'print(' + reportVar + ');\\n';\n  return code;\n};\n\nBlockly.Dart['unittest_main'].defineAssert_ = function() {\n  var resultsVar = Blockly.Dart.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var functionName = Blockly.Dart.provideFunction_(\n      'unittest_assertequals',\n      [ 'void ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n          '(dynamic actual, dynamic expected, String message) {',\n        '  // Asserts that a value equals another value.',\n        '  if (' + resultsVar + ' == null) {',\n        '    throw \"Orphaned assert: ${message}\";',\n        '  }',\n        '  bool equals(a, b) {',\n        '    if (a == b) {',\n        '      return true;',\n        '    } else if (a is List && b is List) {',\n        '      if (a.length != b.length) {',\n        '        return false;',\n        '      }',\n        '      for (num i = 0; i < a.length; i++) {',\n        '        if (!equals(a[i], b[i])) {',\n        '          return false;',\n        '        }',\n        '      }',\n        '      return true;',\n        '    }',\n        '    return false;',\n        '  }',\n        '  if (equals(actual, expected)) {',\n        '    ' + resultsVar + '.add([true, \"OK\", message]);',\n        '  } else {',\n        '    ' + resultsVar + '.add([false, ' +\n          '\"Expected: $expected\\\\nActual: $actual\", message]);',\n        '  }',\n        '}']);\n  return functionName;\n};\n\nBlockly.Dart['unittest_assertequals'] = function(block) {\n  // Asserts that a value equals another value.\n  var message = Blockly.Dart.quote_(block.getFieldValue('MESSAGE'));\n  var actual = Blockly.Dart.valueToCode(block, 'ACTUAL',\n      Blockly.Dart.ORDER_NONE) || 'null';\n  var expected = Blockly.Dart.valueToCode(block, 'EXPECTED',\n      Blockly.Dart.ORDER_NONE) || 'null';\n  return Blockly.Dart['unittest_main'].defineAssert_() +\n      '(' + actual + ', ' + expected + ', ' + message + ');\\n';\n};\n\nBlockly.Dart['unittest_assertvalue'] = function(block) {\n  // Asserts that a value is true, false, or null.\n  var message = Blockly.Dart.quote_(block.getFieldValue('MESSAGE'));\n  var actual = Blockly.Dart.valueToCode(block, 'ACTUAL',\n      Blockly.Dart.ORDER_NONE) || 'null';\n  var expected = block.getFieldValue('EXPECTED');\n  if (expected == 'TRUE') {\n    expected = 'true';\n  } else if (expected == 'FALSE') {\n    expected = 'false';\n  } else if (expected == 'NULL') {\n    expected = 'null';\n  }\n  return Blockly.Dart['unittest_main'].defineAssert_() +\n      '(' + actual + ', ' + expected + ', ' + message + ');\\n';\n};\n\nBlockly.Dart['unittest_fail'] = function(block) {\n  // Always assert an error.\n  var resultsVar = Blockly.Dart.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var message = Blockly.Dart.quote_(block.getFieldValue('MESSAGE'));\n  var functionName = Blockly.Dart.provideFunction_(\n      'unittest_fail',\n      [ 'void ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ +\n          '(String message) {',\n        '  // Always assert an error.',\n        '  if (' + resultsVar + ' == null) {',\n        '    throw \"Orphaned assert fail: ${message}\";',\n        '  }',\n        '  ' + resultsVar + '.add([false, \"Fail.\", message]);',\n        '}']);\n  return functionName + '(' + message + ');\\n';\n};\n"
  },
  {
    "path": "extern/blockly/tests/generators/unittest_javascript.js",
    "content": "/**\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating JavaScript for unit test blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\nBlockly.JavaScript['unittest_main'] = function(block) {\n  // Container for unit tests.\n  var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var functionName = Blockly.JavaScript.provideFunction_(\n      'unittest_report',\n      [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '() {',\n        '  // Create test report.',\n        '  var report = [];',\n        '  var summary = [];',\n        '  var fails = 0;',\n        '  for (var x = 0; x < ' + resultsVar + '.length; x++) {',\n        '    if (' + resultsVar + '[x][0]) {',\n        '      summary.push(\".\");',\n        '    } else {',\n        '      summary.push(\"F\");',\n        '      fails++;',\n        '      report.push(\"\");',\n        '      report.push(\"FAIL: \" + ' + resultsVar + '[x][2]);',\n        '      report.push(' + resultsVar + '[x][1]);',\n        '    }',\n        '  }',\n        '  report.unshift(summary.join(\"\"));',\n        '  report.push(\"\");',\n        '  report.push(\"Number of tests run: \" + ' + resultsVar +\n              '.length);',\n        '  report.push(\"\");',\n        '  if (fails) {',\n        '    report.push(\"FAILED (failures=\" + fails + \")\");',\n        '  } else {',\n        '    report.push(\"OK\");',\n        '  }',\n        '  return report.join(\"\\\\n\");',\n        '}']);\n  // Setup global to hold test results.\n  var code = resultsVar + ' = [];\\n';\n  // Run tests (unindented).\n  code += Blockly.JavaScript.statementToCode(block, 'DO')\n      .replace(/^  /, '').replace(/\\n  /g, '\\n');\n  var reportVar = Blockly.JavaScript.variableDB_.getDistinctName(\n      'report', Blockly.Variables.NAME_TYPE);\n  code += 'var ' + reportVar + ' = ' + functionName + '();\\n';\n  // Destroy results.\n  code += resultsVar + ' = null;\\n';\n  // Send the report to the console (that's where errors will go anyway).\n  code += 'console.log(' + reportVar + ');\\n';\n  return code;\n};\n\nBlockly.JavaScript['unittest_main'].defineAssert_ = function(block) {\n  var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var functionName = Blockly.JavaScript.provideFunction_(\n      'assertEquals',\n      [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n          '(actual, expected, message) {',\n        '  // Asserts that a value equals another value.',\n        '  if (!' + resultsVar + ') {',\n        '    throw \"Orphaned assert: \" + message;',\n        '  }',\n        '  function equals(a, b) {',\n        '    if (a === b) {',\n        '      return true;',\n        '    } else if (a instanceof Array && b instanceof Array) {',\n        '      if (a.length != b.length) {',\n        '        return false;',\n        '      }',\n        '      for (var i = 0; i < a.length; i++) {',\n        '        if (!equals(a[i], b[i])) {',\n        '          return false;',\n        '        }',\n        '      }',\n        '      return true;',\n        '    }',\n        '    return false;',\n        '  }',\n        '  if (equals(actual, expected)) {',\n        '    ' + resultsVar + '.push([true, \"OK\", message]);',\n        '  } else {',\n        '    ' + resultsVar + '.push([false, ' +\n          '\"Expected: \" + expected + \"\\\\nActual: \" + actual, message]);',\n        '  }',\n        '}']);\n  return functionName;\n};\n\nBlockly.JavaScript['unittest_assertequals'] = function(block) {\n  // Asserts that a value equals another value.\n  var message = Blockly.JavaScript.quote_(block.getFieldValue('MESSAGE'));\n  var actual = Blockly.JavaScript.valueToCode(block, 'ACTUAL',\n      Blockly.JavaScript.ORDER_COMMA) || 'null';\n  var expected = Blockly.JavaScript.valueToCode(block, 'EXPECTED',\n      Blockly.JavaScript.ORDER_COMMA) || 'null';\n  return Blockly.JavaScript['unittest_main'].defineAssert_() +\n      '(' + actual + ', ' + expected + ', ' + message + ');\\n';\n};\n\nBlockly.JavaScript['unittest_assertvalue'] = function(block) {\n  // Asserts that a value is true, false, or null.\n  var message = Blockly.JavaScript.quote_(block.getFieldValue('MESSAGE'));\n  var actual = Blockly.JavaScript.valueToCode(block, 'ACTUAL',\n      Blockly.JavaScript.ORDER_COMMA) || 'null';\n  var expected = block.getFieldValue('EXPECTED');\n  if (expected == 'TRUE') {\n    expected = 'true';\n  } else if (expected == 'FALSE') {\n    expected = 'false';\n  } else if (expected == 'NULL') {\n    expected = 'null';\n  }\n  return Blockly.JavaScript['unittest_main'].defineAssert_() +\n      '(' + actual + ', ' + expected + ', ' + message + ');\\n';\n};\n\nBlockly.JavaScript['unittest_fail'] = function(block) {\n  // Always assert an error.\n  var resultsVar = Blockly.JavaScript.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var message = Blockly.JavaScript.quote_(block.getFieldValue('MESSAGE'));\n  var functionName = Blockly.JavaScript.provideFunction_(\n      'unittest_fail',\n      [ 'function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ +\n          '(message) {',\n        '  // Always assert an error.',\n        '  if (!' + resultsVar + ') {',\n        '    throw \"Orphaned assert fail: \" + message;',\n        '  }',\n        '  ' + resultsVar + '.push([false, \"Fail.\", message]);',\n        '}']);\n  return functionName + '(' + message + ');\\n';\n};\n"
  },
  {
    "path": "extern/blockly/tests/generators/unittest_python.js",
    "content": "/**\n * Visual Blocks Language\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * @fileoverview Generating Python for unit test blocks.\n * @author fraser@google.com (Neil Fraser)\n */\n'use strict';\n\nBlockly.Python['unittest_main'] = function(block) {\n  // Container for unit tests.\n  var resultsVar = Blockly.Python.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var functionName = Blockly.Python.provideFunction_(\n      'unittest_report',\n      ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '():',\n       '  # Create test report.',\n       '  report = []',\n       '  summary = []',\n       '  fails = 0',\n       '  for (success, log, message) in ' + resultsVar + ':',\n       '    if success:',\n       '      summary.append(\".\")',\n       '    else:',\n       '      summary.append(\"F\")',\n       '      fails += 1',\n       '      report.append(\"\")',\n       '      report.append(\"FAIL: \" + message)',\n       '      report.append(log)',\n       '  report.insert(0, \"\".join(summary))',\n       '  report.append(\"\")',\n       '  report.append(\"Number of tests run: %d\" % len(' + resultsVar + '))',\n       '  report.append(\"\")',\n       '  if fails:',\n       '    report.append(\"FAILED (failures=%d)\" % fails)',\n       '  else:',\n       '    report.append(\"OK\")',\n       '  return \"\\\\n\".join(report)']);\n\n  // Setup global to hold test results.\n  var code = resultsVar + ' = []\\n';\n  // Run tests (unindented).\n  code += Blockly.Python.statementToCode(block, 'DO')\n      .replace(/^  /, '').replace(/\\n  /g, '\\n');\n  var reportVar = Blockly.Python.variableDB_.getDistinctName(\n      'report', Blockly.Variables.NAME_TYPE);\n  code += reportVar + ' = ' + functionName + '()\\n';\n  // Destroy results.\n  code += resultsVar + ' = None\\n';\n  // Print the report.\n  code += 'print(' + reportVar + ')\\n';\n  return code;\n};\n\nBlockly.Python['unittest_main'].defineAssert_ = function() {\n  var resultsVar = Blockly.Python.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var functionName = Blockly.Python.provideFunction_(\n      'assertEquals',\n      ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ +\n          '(actual, expected, message):',\n       '  # Asserts that a value equals another value.',\n       '  if ' + resultsVar + ' == None:',\n       '    raise Exception(\"Orphaned assert equals: \" + message)',\n       '  if actual == expected:',\n       '    ' + resultsVar + '.append((True, \"OK\", message))',\n       '  else:',\n       '    ' + resultsVar + '.append((False, ' +\n           '\"Expected: %s\\\\nActual: %s\" % (expected, actual), message))']);\n  return functionName;\n};\n\nBlockly.Python['unittest_assertequals'] = function(block) {\n  // Asserts that a value equals another value.\n  var message = Blockly.Python.quote_(block.getFieldValue('MESSAGE'));\n  var actual = Blockly.Python.valueToCode(block, 'ACTUAL',\n      Blockly.Python.ORDER_NONE) || 'None';\n  var expected = Blockly.Python.valueToCode(block, 'EXPECTED',\n      Blockly.Python.ORDER_NONE) || 'None';\n  return Blockly.Python['unittest_main'].defineAssert_() +\n      '(' + actual + ', ' + expected + ', ' + message + ')\\n';\n};\n\nBlockly.Python['unittest_assertvalue'] = function(block) {\n  // Asserts that a value is true, false, or null.\n  var message = Blockly.Python.quote_(block.getFieldValue('MESSAGE'));\n  var actual = Blockly.Python.valueToCode(block, 'ACTUAL',\n      Blockly.Python.ORDER_NONE) || 'None';\n  var expected = block.getFieldValue('EXPECTED');\n  if (expected == 'TRUE') {\n    expected = 'True';\n  } else if (expected == 'FALSE') {\n    expected = 'False';\n  } else if (expected == 'NULL') {\n    expected = 'None';\n  }\n  return Blockly.Python['unittest_main'].defineAssert_() +\n      '(' + actual + ', ' + expected + ', ' + message + ')\\n';\n};\n\nBlockly.Python['unittest_fail'] = function(block) {\n  // Always assert an error.\n  var resultsVar = Blockly.Python.variableDB_.getName('unittestResults',\n      Blockly.Variables.NAME_TYPE);\n  var message = Blockly.Python.quote_(block.getFieldValue('MESSAGE'));\n  var functionName = Blockly.Python.provideFunction_(\n      'fail',\n      ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(message):',\n       '  # Always assert an error.',\n       '  if ' + resultsVar + ' == None:',\n       '    raise Exception(\"Orphaned assert equals: \" + message)',\n       '  ' + resultsVar + '.append((False, \"Fail.\", message))']);\n  return functionName + '(' + message + ')\\n';\n};\n"
  },
  {
    "path": "extern/blockly/tests/generators/variables.xml",
    "content": "<xml xmlns=\"http://www.w3.org/1999/xhtml\">\n  <block type=\"unittest_main\" x=\"0\" y=\"0\">\n    <statement name=\"DO\">\n      <block type=\"variables_set\" inline=\"false\">\n        <field name=\"VAR\">item</field>\n        <value name=\"VALUE\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">123</field>\n          </block>\n        </value>\n        <next>\n          <block type=\"unittest_assertequals\" inline=\"false\">\n            <field name=\"MESSAGE\">variable</field>\n            <value name=\"ACTUAL\">\n              <block type=\"variables_get\">\n                <field name=\"VAR\">item</field>\n              </block>\n            </value>\n            <value name=\"EXPECTED\">\n              <block type=\"math_number\">\n                <field name=\"NUM\">123</field>\n              </block>\n            </value>\n            <next>\n              <block type=\"variables_set\" inline=\"false\">\n                <field name=\"VAR\">if</field>\n                <value name=\"VALUE\">\n                  <block type=\"math_number\">\n                    <field name=\"NUM\">123</field>\n                  </block>\n                </value>\n                <next>\n                  <block type=\"unittest_assertequals\" inline=\"false\">\n                    <field name=\"MESSAGE\">reserved variable</field>\n                    <value name=\"ACTUAL\">\n                      <block type=\"variables_get\">\n                        <field name=\"VAR\">if</field>\n                      </block>\n                    </value>\n                    <value name=\"EXPECTED\">\n                      <block type=\"math_number\">\n                        <field name=\"NUM\">123</field>\n                      </block>\n                    </value>\n                  </block>\n                </next>\n              </block>\n            </next>\n          </block>\n        </next>\n      </block>\n    </statement>\n  </block>\n</xml>\n"
  },
  {
    "path": "extern/blockly/tests/names_test.js",
    "content": "/**\n * Blockly Tests\n *\n * Copyright 2012 Google Inc.\n * https://blockly.googlecode.com/\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *   http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use strict';\n\nfunction test_safeName() {\n  var varDB = new Blockly.Names('window,door');\n  assertEquals('SafeName empty.', 'unnamed', varDB.safeName_(''));\n  assertEquals('SafeName ok.', 'foobar', varDB.safeName_('foobar'));\n  assertEquals('SafeName number start.', 'my_9lives',\n               varDB.safeName_('9lives'));\n  assertEquals('SafeName number end.', 'lives9', varDB.safeName_('lives9'));\n  assertEquals('SafeName special chars.', '____', varDB.safeName_('!@#$'));\n  assertEquals('SafeName reserved.', 'door', varDB.safeName_('door'));\n}\n\nfunction test_getName() {\n  var varDB = new Blockly.Names('window,door');\n  assertEquals('Name add #1.', 'Foo_bar', varDB.getName('Foo.bar', 'var'));\n  assertEquals('Name get #1.', 'Foo_bar', varDB.getName('Foo.bar', 'var'));\n  assertEquals('Name add #2.', 'Foo_bar2', varDB.getName('Foo bar', 'var'));\n  assertEquals('Name get #2.', 'Foo_bar2', varDB.getName('foo BAR', 'var'));\n  assertEquals('Name add #3.', 'door2', varDB.getName('door', 'var'));\n  assertEquals('Name add #4.', 'Foo_bar3', varDB.getName('Foo.bar', 'proc'));\n  assertEquals('Name get #1b.', 'Foo_bar', varDB.getName('Foo.bar', 'var'));\n  assertEquals('Name get #4.', 'Foo_bar3', varDB.getName('Foo.bar', 'proc'));\n}\n\nfunction test_getDistinctName() {\n  var varDB = new Blockly.Names('window,door');\n  assertEquals('Name distinct #1.', 'Foo_bar',\n               varDB.getDistinctName('Foo.bar', 'var'));\n  assertEquals('Name distinct #2.', 'Foo_bar2',\n               varDB.getDistinctName('Foo.bar', 'var'));\n  assertEquals('Name distinct #3.', 'Foo_bar3',\n               varDB.getDistinctName('Foo.bar', 'proc'));\n  varDB.reset();\n  assertEquals('Name distinct #4.', 'Foo_bar',\n               varDB.getDistinctName('Foo.bar', 'var'));\n}\n\nfunction test_nameEquals() {\n  assertTrue('Name equals #1.', Blockly.Names.equals('Foo.bar', 'Foo.bar'));\n  assertFalse('Name equals #2.', Blockly.Names.equals('Foo.bar', 'Foo_bar'));\n  assertTrue('Name equals #3.', Blockly.Names.equals('Foo.bar', 'FOO.BAR'));\n}\n"
  },
  {
    "path": "extern/blockly/tests/playground.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<title>Blockly Playground</title>\n<script type=\"text/javascript\" src=\"../blockly_uncompressed.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript/logic.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript/loops.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript/math.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript/text.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript/lists.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript/colour.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript/variables.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/javascript/procedures.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python/logic.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python/loops.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python/math.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python/text.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python/lists.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python/colour.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python/variables.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/python/procedures.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart/logic.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart/loops.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart/math.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart/text.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart/lists.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart/colour.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart/variables.js\"></script>\n<script type=\"text/javascript\" src=\"../generators/dart/procedures.js\"></script>\n<script type=\"text/javascript\" src=\"../msg/messages.js\"></script>\n<script type=\"text/javascript\" src=\"../blocks/logic.js\"></script>\n<script type=\"text/javascript\" src=\"../blocks/loops.js\"></script>\n<script type=\"text/javascript\" src=\"../blocks/math.js\"></script>\n<script type=\"text/javascript\" src=\"../blocks/text.js\"></script>\n<script type=\"text/javascript\" src=\"../blocks/lists.js\"></script>\n<script type=\"text/javascript\" src=\"../blocks/colour.js\"></script>\n<script type=\"text/javascript\" src=\"../blocks/variables.js\"></script>\n<script type=\"text/javascript\" src=\"../blocks/procedures.js\"></script>\n<!-- Load the Google Drive SDK Realtime libraries. -->\n<script type=\"text/javascript\" src=\"https://apis.google.com/js/api.js\"></script>\n<script type=\"text/javascript\">\n'use strict';\n// Depending on the URL argument, render as LTR or RTL.\nvar rtl = (document.location.search == '?rtl');\nvar block = null;\n\nfunction start() {\n  var startUi = function () {\n    var toolbox = document.getElementById('toolbox');\n    Blockly.inject(document.getElementById('blocklyDiv'),\n            {rtl: rtl, path: '../', toolbox: toolbox});\n  };\n\n  // Set up realtime collaboration.\n  // If you want to use the realtime collaboration features then uncomment out\n  // the next 2 lines and comment out the call to startUi() below.\n//  document.getElementById(\"realtime\").style.display = \"block\";\n//  Blockly.Realtime.startRealtime(startUi);\n\n  // If you don't want to use the realtime collaboration features then uncomment\n  // out the next line and comment out the call to\n  // Blockly.Realtime.startRealtime() above it.  You can also comment out\n  // (or delete) the loading of the realtime related libraries up above in this\n  // case, if you want.\n  startUi();\n}\n\nfunction toXml() {\n  var output = document.getElementById('importExport');\n  var xml = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);\n  output.value = Blockly.Xml.domToPrettyText(xml);\n  output.focus();\n  output.select();\n}\n\nfunction fromXml() {\n  var input = document.getElementById('importExport');\n  var xml = Blockly.Xml.textToDom(input.value);\n  Blockly.Xml.domToWorkspace(Blockly.mainWorkspace, xml);\n}\n\nfunction toCode(lang) {\n  var output = document.getElementById('importExport');\n  output.value = Blockly[lang].workspaceToCode();\n}\n\nfunction airstrike(n) {\n  var prototypes = [];\n  var toolbox = document.getElementById('toolbox');\n  var blocks = toolbox.getElementsByTagName('block');\n  for (var x = 0, block; block = blocks[x]; x++) {\n    prototypes.push(block.getAttribute('type'));\n  }\n  for (var x = 0; x < n; x++) {\n    var prototype = prototypes[Math.floor(Math.random() * prototypes.length)];\n    var block = Blockly.Block.obtain(Blockly.mainWorkspace, prototype);\n    block.initSvg();\n    block.getSvgRoot().setAttribute('transform', 'translate(' +\n        Math.round(Math.random() * 450 + 40) + ', ' +\n        Math.round(Math.random() * 600 + 40) + ')');\n    block.render();\n  }\n}\n</script>\n\n<style>\nhtml, body {\n  height: 100%;\n}\nbody {\n  background-color: #fff;\n  font-family: sans-serif;\n  overflow: hidden;\n}\nh1 {\n  font-weight: normal;\n  font-size: 140%;\n}\n#blocklyDiv {\n  float: right;\n  height: 95%;\n  width: 70%;\n}\n</style>\n</head>\n<body onload=\"start()\">\n\n  <div id=\"blocklyDiv\"></div>\n\n  <xml id=\"toolbox\" style=\"display: none\">\n    <category name=\"Logic\">\n      <block type=\"controls_if\"></block>\n      <block type=\"logic_compare\"></block>\n      <block type=\"logic_operation\"></block>\n      <block type=\"logic_negate\"></block>\n      <block type=\"logic_boolean\"></block>\n      <block type=\"logic_null\"></block>\n      <block type=\"logic_ternary\"></block>\n    </category>\n    <category name=\"Loops\">\n      <block type=\"controls_repeat_ext\">\n        <value name=\"TIMES\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">10</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"controls_whileUntil\"></block>\n      <block type=\"controls_for\">\n        <value name=\"FROM\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n        <value name=\"TO\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">10</field>\n          </block>\n        </value>\n        <value name=\"BY\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"controls_forEach\"></block>\n      <block type=\"controls_flow_statements\"></block>\n    </category>\n    <category name=\"Math\">\n      <block type=\"math_number\"></block>\n      <block type=\"math_arithmetic\"></block>\n      <block type=\"math_single\"></block>\n      <block type=\"math_trig\"></block>\n      <block type=\"math_constant\"></block>\n      <block type=\"math_number_property\"></block>\n      <block type=\"math_change\">\n        <value name=\"DELTA\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"math_round\"></block>\n      <block type=\"math_on_list\"></block>\n      <block type=\"math_modulo\"></block>\n      <block type=\"math_constrain\">\n        <value name=\"LOW\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n        <value name=\"HIGH\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">100</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"math_random_int\">\n        <value name=\"FROM\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">1</field>\n          </block>\n        </value>\n        <value name=\"TO\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">100</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"math_random_float\"></block>\n    </category>\n    <category name=\"Text\">\n      <block type=\"text\"></block>\n      <block type=\"text_join\"></block>\n      <block type=\"text_append\">\n        <value name=\"TEXT\">\n          <block type=\"text\"></block>\n        </value>\n      </block>\n      <block type=\"text_length\"></block>\n      <block type=\"text_isEmpty\"></block>\n      <block type=\"text_indexOf\">\n        <value name=\"VALUE\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">text</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"text_charAt\">\n        <value name=\"VALUE\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">text</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"text_getSubstring\">\n        <value name=\"STRING\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">text</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"text_changeCase\"></block>\n      <block type=\"text_trim\"></block>\n      <block type=\"text_print\"></block>\n      <block type=\"text_prompt\"></block>\n    </category>\n    <category name=\"Lists\">\n      <block type=\"lists_create_empty\"></block>\n      <block type=\"lists_create_with\"></block>\n      <block type=\"lists_repeat\">\n        <value name=\"NUM\">\n          <block type=\"math_number\">\n            <field name=\"NUM\">5</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"lists_length\"></block>\n      <block type=\"lists_isEmpty\"></block>\n      <block type=\"lists_indexOf\">\n        <value name=\"VALUE\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">list</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"lists_getIndex\">\n        <value name=\"VALUE\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">list</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"lists_setIndex\">\n        <value name=\"LIST\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">list</field>\n          </block>\n        </value>\n      </block>\n      <block type=\"lists_getSublist\">\n        <value name=\"LIST\">\n          <block type=\"variables_get\">\n            <field name=\"VAR\">list</field>\n          </block>\n        </value>\n      </block>\n    </category>\n    <category name=\"Colour\">\n      <block type=\"colour_picker\"></block>\n      <block type=\"colour_random\"></block>\n      <block type=\"colour_rgb\"></block>\n      <block type=\"colour_blend\"></block>\n    </category>\n    <category name=\"Variables\" custom=\"VARIABLE\"></category>\n    <category name=\"Functions\" custom=\"PROCEDURE\"></category>\n  </xml>\n\n  <h1>Blockly Playground</h1>\n\n  <p><a href=\"javascript:void([document.getElementById('blocklyDiv').style.display = 'block', Blockly.mainWorkspace.render()])\">Show</a>\n   - <a href=\"javascript:void(document.getElementById('blocklyDiv').style.display = 'none')\">Hide</a></p>\n\n  <script type=\"text/javascript\">\n    if (rtl) {\n      document.write('[ &larr; RTL. Switch to <A HREF=\"?ltr\">LTR</A>. ]');\n    } else {\n      document.write('[ &rarr; LTR. Switch to <A HREF=\"?rtl\">RTL</A>. ]');\n    }\n  </script>\n\n  <p>\n    <input type=\"button\" value=\"Export to XML\" onclick=\"toXml()\">\n    &nbsp;\n    <input type=\"button\" value=\"Import from XML\" onclick=\"fromXml()\">\n    <br>\n    <input type=\"button\" value=\"To JavaScript\" onclick=\"toCode('JavaScript')\">\n    &nbsp;\n    <input type=\"button\" value=\"To Python\" onclick=\"toCode('Python')\">\n    &nbsp;\n    <input type=\"button\" value=\"To Dart\" onclick=\"toCode('Dart')\">\n    <br>\n    <textarea id=\"importExport\" style=\"width: 26%; height: 12em\"></textarea>\n  </p>\n  <hr>\n\n  <p>\n    Stress test with an <input type=\"button\" value=\"Airstrike!\" onclick=\"airstrike(100)\">\n  </p>\n\n  <!-- Realtime setup buttons. -->\n\n  <div id=\"realtime\" style=\"display: none\">\n\n    <p>Test realtime collaboration by opening\n      <a target=\"_blank\" href=\"#\" onmouseover=\"this.href = window.location.href\">this link in a separate\n        browser window or tab</a> and they will be synchronized.  If this is the first time you've used\n      realtime collaboration with Blockly you'll need to authorize using the following button if it is enabled.</p>\n\n    <button id=\"authorizeButton\">You must authorize</button>\n\n    <br>\n    <br>\n\n    <!-- Undo and redo buttons. -->\n    <!--\n      <button id=\"undoButton\" disabled>Undo</button>\n      <button id=\"redoButton\" disabled>Redo</button>\n      <br />\n    -->\n\n    <!-- Text area that will be used for our collaborative chat box. -->\n    <textarea id=\"chatbox\" style=\"width: 26%; height: 12em\" disabled=\"true\"></textarea>\n\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "extern/face-landmarker.worker.js",
    "content": "self.importScripts(`${self.location.pathname}/../human/human.js`);\n\nconst config = {\n    backend: 'humangl',\n    modelBasePath: './human/models/',\n    cacheModels: true,\n    validateModels: true,\n    wasmPlatformFetch: false,\n    debug: false,\n    async: true,\n    warmup: 'full',\n    cacheSensitivity: 0.7,\n    skipAllowed: false,\n    deallocate: false,\n    flags: {},\n    softwareKernels: false,\n    face: {\n        enabled: true,\n        detector: {\n            modelPath: 'blazeface.json',\n            rotation: false,\n            maxDetected: 4,\n            minConfidence: 0.2,\n            return: true,\n        },\n        mesh: {\n            enabled: true,\n            modelPath: 'facemesh.json',\n            keepInvalid: false,\n        },\n        attention: {\n            enabled: false,\n            modelPath: 'facemesh-attention.json',\n        },\n        iris: {\n            enabled: false,\n            modelPath: 'iris.json',\n        },\n        emotion: {\n            enabled: true,\n            minConfidence: 0.1,\n            skipFrames: 99,\n            skipTime: 1500,\n            modelPath: 'emotion.json',\n        },\n        description: {\n            enabled: true,\n            modelPath: 'faceres.json',\n            skipFrames: 99,\n            skipTime: 3000,\n            minConfidence: 0.1,\n        },\n        antispoof: {\n            enabled: false,\n            skipFrames: 99,\n            skipTime: 4000,\n            modelPath: 'antispoof.json',\n        },\n        liveness: {\n            enabled: false,\n            skipFrames: 99,\n            skipTime: 4000,\n            modelPath: 'liveness.json',\n        },\n    },\n    filter: { enabled: false },\n    object: { enabled: false },\n    gesture: { enabled: false },\n    hand: { enabled: false },\n    body: { enabled: false },\n    segmentation: { enabled: false },\n};\n\nconst drawOption = {\n    alpha: 1,\n    color: '#ffffff',\n    drawPoints: true,\n    drawPolygons: true,\n    drawAttention: false,\n    drawBoxes: false,\n    drawGaze: false,\n    drawGestures: false,\n    drawLabels: false,\n};\n\nlet flipState;\nlet isRun = false;\nlet isFirstIdle = false;\n\nself.onmessage = async ({ data }) => {\n    if (data.action === 'face_landmarker_init') {\n        initializeFaceLandmarker(data);\n    } else if (data.action === 'face_landmarker_restart') {\n        isRun = true;\n        self.postMessage({ action: 'run_start_face_landmarker' });\n    } else if (data.action === 'face_landmarker_change_option') {\n        changeFaceLandmarkerOption(data.option);\n    } else if (data.action === 'face_landmarker') {\n        flipState = data.flipState;\n        predictFaceLandmarker(data.imageBitmap);\n    } else if (data.action === 'clear_face_landmarker') {\n        clearPredictFaceLandmarker();\n    }\n};\n\nlet human;\nlet faceLang;\nlet offCanvas;\nlet workerContext;\nlet drawingUtils;\nlet faceLandmarker;\nlet isPrevFaceLandmarker = false;\nlet countDetectedFace = 0;\nlet isDrawDetectedFaceLandmarker = false;\n\nconst initializeFaceLandmarker = async (data) => {\n    const { canvas, option, isSafari, lang } = data;\n    faceLang = lang.face;\n    isDrawDetectedFaceLandmarker = option.isDrawDetectedFaceLandmarker;\n    offCanvas = canvas;\n    workerContext = canvas.getContext('2d');\n    workerContext.font = '20px Arial';\n\n    if (isSafari) {\n        config.backend = 'wasm';\n    }\n\n    if (!human) human = new Human.default(config);\n    await human.load(); // optional as models would be loaded on-demand first time they are required\n    await human.warmup(); // optional as model warmup is performed on-demand first time its executed\n\n    isRun = true;\n    self.postMessage({ action: 'run_start_face_landmarker' });\n    self.postMessage({ action: 'next_face_landmarker' });\n};\n\nconst changeFaceLandmarkerOption = (option) => {\n    isDrawDetectedFaceLandmarker = option.isDrawDetectedFaceLandmarker;\n};\n\nconst contextFlip = (context, axis) => {\n    if (flipState === 0) {\n        context.scale(-1, 1);\n        return {\n            x: -axis[0] * 640,\n            y: axis[1] * 360 - 20,\n        };\n    } else if (flipState === 1) {\n        context.scale(1, 1);\n        return {\n            x: axis[0] * 640,\n            y: axis[1] * 360 - 20,\n        };\n    } else if (flipState === 2) {\n        context.scale(-1, -1);\n        return {\n            x: -axis[0] * 640,\n            y: -axis[1] * 360 + 20,\n        };\n    } else if (flipState === 3) {\n        context.scale(1, -1);\n        return {\n            x: axis[0] * 640,\n            y: -axis[1] * 360 + 20,\n        };\n    }\n};\n\nlet lastDetect;\nconst predictFaceLandmarker = async (imageBitmap) => {\n    try {\n        if (!workerContext || !human) {\n            return;\n        }\n        if (!isFirstIdle && human.state === 'idle') {\n            isFirstIdle = true;\n        }\n        if (!isRun || !isFirstIdle) {\n            return;\n        }\n        lastDetect = human.detect(imageBitmap);\n        const results = await lastDetect;\n\n        workerContext.save();\n        workerContext.clearRect(0, 0, 640, 360);\n\n        const { face } = results;\n        self.postMessage({\n            action: 'face_landmarker_data',\n            faceLandmarkerResult: { face },\n        });\n        if (face.length) {\n            if (!isPrevFaceLandmarker) {\n                isPrevFaceLandmarker = true;\n                self.postMessage({ action: 'start_face_landmarker' });\n            }\n            if (face.length !== countDetectedFace) {\n                countDetectedFace = face.length;\n                self.postMessage({\n                    action: 'count_detected_face_landmarker',\n                    count: countDetectedFace,\n                });\n            }\n            if (!isDrawDetectedFaceLandmarker) {\n                return;\n            }\n            face.forEach((item, i) => {\n                const { meshRaw } = item;\n                const mark297 = meshRaw[297];\n                const { x, y } = contextFlip(workerContext, mark297);\n                workerContext.fillStyle = '#FF0000';\n                workerContext.fillText(`${i + 1}-${faceLang}`, x, y);\n                contextFlip(workerContext, mark297);\n            });\n            await human.draw.face(offCanvas, face, drawOption);\n        } else if (isPrevFaceLandmarker) {\n            isPrevFaceLandmarker = false;\n            countDetectedFace = 0;\n            self.postMessage({ action: 'stop_face_landmarker' });\n        }\n    } catch (e) {\n        console.error(e);\n    } finally {\n        workerContext.restore();\n        requestAnimationFrame(() => {\n            self.postMessage({ action: 'next_face_landmarker' });\n        });\n    }\n};\n\nconst clearPredictFaceLandmarker = async () => {\n    isRun = false;\n    await lastDetect;\n    requestAnimationFrame(() => {\n        self.postMessage({ action: 'run_stop_face_landmarker' });\n        isPrevFaceLandmarker = false;\n        countDetectedFace = 0;\n        workerContext.clearRect(0, 0, 640, 360);\n    });\n};\n"
  },
  {
    "path": "extern/face-landmarker2.worker.js",
    "content": "self.importScripts(`${self.location.pathname}/../vision_bundle.js`);\n\nself.onmessage = async ({ data }) => {\n    if (data.action === 'face_landmarker_init') {\n        initializeFaceLandmarker(data);\n    } else if (data.action === 'face_landmarker_change_option') {\n        changeFaceLandmarkerOption(data.option);\n    } else if (data.action === 'face_landmarker') {\n        predictFaceLandmarker(data.imageBitmap);\n    } else if (data.action === 'clear_face_landmarker') {\n        clearPredictFaceLandmarker();\n    }\n};\n\nlet workerContext;\nlet drawingUtils;\nlet faceLandmarker;\nlet isPrevFaceLandmarker = false;\nlet countDetectedFace = 0;\nlet isDrawDetectedFaceLandmarker = false;\n\nconst initializeFaceLandmarker = async (data) => {\n    const { canvas, option } = data;\n    isDrawDetectedFaceLandmarker = option.isDrawDetectedFaceLandmarker;\n    workerContext = canvas.getContext('2d');\n    workerContext.font = '20px Arial';\n    drawingUtils = new DrawingUtils(workerContext);\n    const vision = await FilesetResolver.forVisionTasks(`${self.location.pathname}/../wasm`);\n    faceLandmarker = await FaceLandmarker.createFromOptions(vision, {\n        baseOptions: {\n            modelAssetPath: `${self.location.pathname}/../model/face_landmarker.task`,\n            delegate: 'GPU',\n        },\n        runningMode: 'VIDEO',\n        numFaces: 4,\n    });\n    self.postMessage({ action: 'next_face_landmarker' });\n};\n\nconst changeFaceLandmarkerOption = (option) => {\n    isDrawDetectedFaceLandmarker = option.isDrawDetectedFaceLandmarker;\n};\n\nconst predictFaceLandmarker = async (imageBitmap) => {\n    try {\n        if (!workerContext || !faceLandmarker) {\n            return;\n        }\n        const results = await faceLandmarker.detectForVideo(imageBitmap, Date.now());\n        workerContext.save();\n        workerContext.clearRect(0, 0, 640, 360);\n        const { faceLandmarks } = results;\n        self.postMessage({\n            action: 'face_landmarker_data',\n            faceLandmarkerResult: results,\n        });\n        if (faceLandmarks.length) {\n            if (!isPrevFaceLandmarker) {\n                isPrevFaceLandmarker = true;\n                self.postMessage({ action: 'start_face_landmarker' });\n            }\n            if (faceLandmarks.length !== countDetectedFace) {\n                countDetectedFace = faceLandmarks.length;\n                self.postMessage({\n                    action: 'count_detected_face_landmarker',\n                    count: countDetectedFace,\n                });\n            }\n            if (!isDrawDetectedFaceLandmarker) {\n                return;\n            }\n            faceLandmarks.forEach((landmark, i) => {\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_TESSELATION, {\n                    color: '#C0C0C070',\n                    lineWidth: 1,\n                });\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_RIGHT_EYE, {\n                    color: '#FF3030',\n                });\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_RIGHT_EYEBROW, {\n                    color: '#FF3030',\n                });\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_LEFT_EYE, {\n                    color: '#30FF30',\n                });\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_LEFT_EYEBROW, {\n                    color: '#30FF30',\n                });\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_FACE_OVAL, {\n                    color: '#E0E0E0',\n                });\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_LIPS, {\n                    color: '#E0E0E0',\n                });\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_RIGHT_IRIS, {\n                    color: '#FF3030',\n                });\n                drawingUtils.drawConnectors(landmark, FaceLandmarker.FACE_LANDMARKS_LEFT_IRIS, {\n                    color: '#30FF30',\n                });\n            });\n        } else if (isPrevFaceLandmarker) {\n            isPrevFaceLandmarker = false;\n            countDetectedFace = 0;\n            self.postMessage({ action: 'stop_face_landmarker' });\n        }\n    } catch (e) {\n        console.error(e);\n    } finally {\n        workerContext.restore();\n        requestAnimationFrame(() => {\n            self.postMessage({ action: 'next_face_landmarker' });\n        });\n    }\n};\n\nconst clearPredictFaceLandmarker = () => {\n    console.log('clearPredictFaceLandmarker');\n    isPrevFaceLandmarker = false;\n    workerContext.clearRect(0, 0, 640, 360);\n};\n"
  },
  {
    "path": "extern/gesture-recognition.worker.js",
    "content": "self.importScripts(`${self.location.pathname}/../vision_bundle.js`);\n\nlet flipState;\nlet isRun = false;\nself.onmessage = async ({ data }) => {\n    if (data.action === 'gesture_recognizer_init') {\n        initializeGesture(data);\n    } else if (data.action === 'gesture_recognizer_restart') {\n        isRun = true;\n    } else if (data.action === 'gesture_recognizer_change_option') {\n        changeGestureOption(data.option);\n    } else if (data.action === 'gesture_recognizer') {\n        flipState = data.flipState || 0;\n        predictGesture(data.imageBitmap);\n    } else if (data.action === 'clear_gesture_recognizer') {\n        clearPredictGesture();\n    }\n};\n\nlet leftHand;\nlet rightHand;\nlet workerContext;\nlet drawingUtils;\nlet gestureRecognizer;\nlet isPrevHandDetected = false;\nlet countDetectedHand = 0;\nlet isDrawDetectedHand = false;\n\nconst initializeGesture = async (data) => {\n    const { canvas, lang, option } = data;\n    isRun = true;\n    leftHand = lang.leftHand;\n    rightHand = lang.rightHand;\n    isDrawDetectedHand = option.isDrawDetectedHand;\n    workerContext = canvas.getContext('2d');\n    workerContext.font = '20px Arial';\n    drawingUtils = new DrawingUtils(workerContext);\n    const vision = await FilesetResolver.forVisionTasks(`${self.location.pathname}/../wasm`);\n    gestureRecognizer = await GestureRecognizer.createFromOptions(vision, {\n        baseOptions: {\n            modelAssetPath: `${self.location.pathname}/../model/gesture_recognizer.task`,\n            delegate: 'GPU',\n        },\n        runningMode: 'VIDEO',\n        numHands: 2,\n    });\n    self.postMessage({ action: 'next_gesture_recognizer' });\n};\n\nconst changeGestureOption = (option) => {\n    isDrawDetectedHand = option.isDrawDetectedHand;\n};\n\nconst YX = (a) => {\n    return Math.max(1, Math.min(10, 10 * (1 - (a - -0.15) / 0.25) + (1 - (0.1 - a) / 0.25)));\n};\n\nconst contextFlip = (context, axis) => {\n    if (flipState === 0) {\n        context.scale(-1, 1);\n        return {\n            x: -axis.x * 640,\n            y: axis.y * 360 - 20,\n        };\n    } else if (flipState === 1) {\n        context.scale(1, 1);\n        return {\n            x: axis.x * 640,\n            y: axis.y * 360 - 20,\n        };\n    } else if (flipState === 2) {\n        context.scale(-1, -1);\n        return {\n            x: -axis.x * 640,\n            y: -axis.y * 360 + 20,\n        };\n    } else if (flipState === 3) {\n        context.scale(1, -1);\n        return {\n            x: axis.x * 640,\n            y: -axis.y * 360 + 20,\n        };\n    }\n};\n\nconst predictGesture = (imageBitmap) => {\n    try {\n        if (!workerContext || !gestureRecognizer || !isRun) {\n            return;\n        }\n        const results = gestureRecognizer.recognizeForVideo(imageBitmap, Date.now());\n        workerContext.save();\n        workerContext.clearRect(0, 0, 640, 360);\n        const { landmarks, handednesses } = results;\n        self.postMessage({\n            action: 'gesture_recognizer_data',\n            gestureRecognizerResult: results,\n        });\n        if (landmarks.length) {\n            if (!isPrevHandDetected) {\n                isPrevHandDetected = true;\n                self.postMessage({ action: 'start_gesture_recognizer' });\n            }\n            if (landmarks.length !== countDetectedHand) {\n                countDetectedHand = landmarks.length;\n                self.postMessage({\n                    action: 'count_detected_hand_gesture_recognizer',\n                    count: countDetectedHand,\n                });\n            }\n            if (!isDrawDetectedHand) {\n                return;\n            }\n            landmarks.forEach((landmark, i) => {\n                let connectColor;\n                let landmarkColor;\n                const [handedness] = handednesses[i];\n                const mark12 = landmark[12];\n                const { x, y } = contextFlip(workerContext, mark12);\n                if (handedness.categoryName === 'Left') {\n                    workerContext.fillStyle = '#FF0000';\n                    workerContext.fillText(`${i + 1}-${rightHand}`, x, y);\n                    connectColor = '#FF0000';\n                    landmarkColor = '#00FF00';\n                } else {\n                    workerContext.fillStyle = '#00FF00';\n                    workerContext.fillText(`${i + 1}-${leftHand}`, x, y);\n                    connectColor = '#00FF00';\n                    landmarkColor = '#FF0000';\n                }\n                contextFlip(workerContext, mark12);\n                drawingUtils.drawConnectors(landmark, GestureRecognizer.HAND_CONNECTIONS, {\n                    color: connectColor,\n                    lineWidth: 4,\n                });\n                drawingUtils.drawLandmarks(landmark, {\n                    color: connectColor,\n                    lineWidth: 4,\n                    fillColor: landmarkColor,\n                    radius: (e) => {\n                        return YX(e.from?.z || 0);\n                    },\n                });\n            });\n        } else if (isPrevHandDetected) {\n            isPrevHandDetected = false;\n            countDetectedHand = 0;\n            self.postMessage({ action: 'stop_gesture_recognizer' });\n        }\n    } catch (e) {\n        console.error(e);\n    } finally {\n        workerContext.restore();\n        requestAnimationFrame(() => {\n            self.postMessage({ action: 'next_gesture_recognizer' });\n        });\n    }\n};\n\nconst clearPredictGesture = () => {\n    console.log('clearPredictGesture');\n    isRun = false;\n    isPrevHandDetected = false;\n    countDetectedHand = 0;\n    workerContext.clearRect(0, 0, 640, 360);\n};\n"
  },
  {
    "path": "extern/human/human.js",
    "content": "/*\n  Human\n  homepage: <https://github.com/vladmandic/human>\n  author: <https://github.com/vladmandic>'\n*/\n\n\"use strict\";var Human=(()=>{var sc=Object.defineProperty;var MI=Object.getOwnPropertyDescriptor;var $I=Object.getOwnPropertyNames;var _I=Object.prototype.hasOwnProperty;var PI=(e,t,a)=>t in e?sc(e,t,{enumerable:!0,configurable:!0,writable:!0,value:a}):e[t]=a;var Cs=(e=>typeof require!=\"undefined\"?require:typeof Proxy!=\"undefined\"?new Proxy(e,{get:(t,a)=>(typeof require!=\"undefined\"?require:t)[a]}):e)(function(e){if(typeof require!=\"undefined\")return require.apply(this,arguments);throw new Error('Dynamic require of \"'+e+'\" is not supported')});var hr=(e,t)=>{for(var a in t)sc(e,a,{get:t[a],enumerable:!0})},FI=(e,t,a,n)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let r of $I(t))!_I.call(e,r)&&r!==a&&sc(e,r,{get:()=>t[r],enumerable:!(n=MI(t,r))||n.enumerable});return e};var OI=e=>FI(sc({},\"__esModule\",{value:!0}),e);var ue=(e,t,a)=>(PI(e,typeof t!=\"symbol\"?t+\"\":t,a),a),O5=(e,t,a)=>{if(!t.has(e))throw TypeError(\"Cannot \"+a)};var Ga=(e,t,a)=>(O5(e,t,\"read from private field\"),a?a.call(e):t.get(e)),Gn=(e,t,a)=>{if(t.has(e))throw TypeError(\"Cannot add the same private member more than once\");t instanceof WeakSet?t.add(e):t.set(e,a)},fr=(e,t,a,n)=>(O5(e,t,\"write to private field\"),n?n.call(e,a):t.set(e,a),a);var w0e={};hr(w0e,{Env:()=>Ap,Human:()=>A5,default:()=>A5,defaults:()=>Io,draw:()=>s0,empty:()=>or,env:()=>ne,match:()=>$0,models:()=>x5});var Ue={};hr(Ue,{Abs:()=>wl,Acos:()=>kl,Acosh:()=>Il,AdadeltaOptimizer:()=>Th,AdagradOptimizer:()=>Ch,AdamOptimizer:()=>Nh,AdamaxOptimizer:()=>Eh,Add:()=>ts,AddN:()=>Ks,All:()=>Zs,Any:()=>Ys,ArgMax:()=>Js,ArgMin:()=>kd,Asin:()=>Sl,Asinh:()=>Tl,Atan:()=>Cl,Atan2:()=>El,Atanh:()=>Nl,AvgPool:()=>Qs,AvgPool3D:()=>Hc,AvgPool3DGrad:()=>G1,AvgPoolGrad:()=>U1,BackendWasm:()=>I8,BatchMatMul:()=>ei,BatchToSpaceND:()=>Rl,Bincount:()=>Id,BroadcastArgs:()=>jc,BroadcastTo:()=>TS,Cast:()=>ti,Ceil:()=>ai,ClipByValue:()=>as,Complex:()=>Sd,ComplexAbs:()=>qc,Concat:()=>Ml,Conv2D:()=>ni,Conv2DBackpropFilter:()=>Xc,Conv2DBackpropInput:()=>ri,Conv3D:()=>Kc,Conv3DBackpropFilterV2:()=>H1,Conv3DBackpropInputV2:()=>Zc,Cos:()=>si,Cosh:()=>ii,CropAndResize:()=>ui,Cumprod:()=>oi,Cumsum:()=>li,DataStorage:()=>vd,DenseBincount:()=>Td,DepthToSpace:()=>di,DepthwiseConv2dNative:()=>pi,DepthwiseConv2dNativeBackpropFilter:()=>Yc,DepthwiseConv2dNativeBackpropInput:()=>Jc,Diag:()=>Qc,Dilation2D:()=>eh,Dilation2DBackpropFilter:()=>Gm,Dilation2DBackpropInput:()=>Um,ENV:()=>W1,Einsum:()=>Cd,Elu:()=>hi,EluGrad:()=>j1,Environment:()=>mA,Equal:()=>fi,Erf:()=>$l,Exp:()=>mi,ExpandDims:()=>_l,Expm1:()=>Pl,FFT:()=>Nd,Fill:()=>Fl,FlipLeftRight:()=>gi,Floor:()=>xi,FloorDiv:()=>Ai,FromPixels:()=>rd,FusedBatchNorm:()=>yi,FusedConv2D:()=>qr,FusedDepthwiseConv2D:()=>Xr,GPGPUContext:()=>il,GatherNd:()=>bi,GatherV2:()=>Ol,GraphModel:()=>op,Greater:()=>vi,GreaterEqual:()=>wi,IFFT:()=>Ed,Identity:()=>ki,Imag:()=>Rd,IsFinite:()=>Dl,IsInf:()=>zl,IsNan:()=>Ii,KernelBackend:()=>bl,LRN:()=>ah,LRNGrad:()=>q1,LeakyRelu:()=>Si,Less:()=>Ti,LessEqual:()=>Ci,LinSpace:()=>th,Log:()=>Ni,Log1p:()=>Ll,LogSoftmax:()=>CS,LogicalAnd:()=>Ei,LogicalNot:()=>Ri,LogicalOr:()=>Bl,LogicalXor:()=>xA,LowerBound:()=>NS,MathBackendCPU:()=>$h,MathBackendWebGL:()=>fu,Max:()=>Mi,MaxPool:()=>_i,MaxPool3D:()=>nh,MaxPool3DGrad:()=>K1,MaxPoolGrad:()=>X1,MaxPoolWithArgmax:()=>rh,Maximum:()=>$i,Mean:()=>Pi,Min:()=>Fi,Minimum:()=>Oi,MirrorPad:()=>Di,Mod:()=>Wl,MomentumOptimizer:()=>Rh,Multinomial:()=>sh,Multiply:()=>zi,Neg:()=>Vl,NonMaxSuppressionV3:()=>Bi,NonMaxSuppressionV4:()=>Ul,NonMaxSuppressionV5:()=>Wi,NotEqual:()=>Li,OP_SCOPE_SUFFIX:()=>e2,OneHot:()=>Vi,OnesLike:()=>Gl,Optimizer:()=>is,OptimizerConstructors:()=>Or,Pack:()=>Hl,PadV2:()=>Ui,Pool:()=>ES,Pow:()=>Gi,Prelu:()=>Hi,Prod:()=>ji,RMSPropOptimizer:()=>Mh,RaggedGather:()=>ih,RaggedRange:()=>oh,RaggedTensorToTensor:()=>lh,Range:()=>jl,Rank:()=>qm,Real:()=>Md,RealDiv:()=>ci,Reciprocal:()=>qi,Reduction:()=>ya,Relu:()=>Xi,Relu6:()=>Yi,Reshape:()=>ql,ResizeBilinear:()=>Zi,ResizeBilinearGrad:()=>Y1,ResizeNearestNeighbor:()=>Ki,ResizeNearestNeighborGrad:()=>Z1,Reverse:()=>Ji,RotateWithOffset:()=>mo,Round:()=>Xl,Rsqrt:()=>Qi,SGDOptimizer:()=>ip,ScatterNd:()=>eo,SearchSorted:()=>$d,Select:()=>Kl,Selu:()=>_d,Sigmoid:()=>ao,Sign:()=>Pd,Sin:()=>to,Sinh:()=>Yl,Slice:()=>Zl,Softmax:()=>so,Softplus:()=>Fd,SpaceToBatchND:()=>Jl,SparseFillEmptyRows:()=>Od,SparseReshape:()=>eu,SparseSegmentMean:()=>Dd,SparseSegmentSum:()=>zd,SparseToDense:()=>Ld,SplitV:()=>Ql,Sqrt:()=>no,Square:()=>Bd,SquaredDifference:()=>io,Step:()=>fo,StridedSlice:()=>oo,StringNGrams:()=>tu,StringSplit:()=>Wd,StringToHashBucketFast:()=>Vd,Sub:()=>lo,Sum:()=>ro,Tan:()=>uo,Tanh:()=>po,Tensor:()=>pt,TensorBuffer:()=>jt,Tile:()=>ns,TopK:()=>co,Transform:()=>ho,Transpose:()=>Ar,Unique:()=>uh,Unpack:()=>au,UnsortedSegmentSum:()=>dh,UpperBound:()=>RS,Variable:()=>od,WebGPUBackend:()=>Vh,ZerosLike:()=>nu,_FusedMatMul:()=>jr,abs:()=>qa,acos:()=>oy,acosh:()=>ly,add:()=>be,addN:()=>ch,all:()=>uy,any:()=>dy,argMax:()=>ar,argMin:()=>py,asin:()=>cy,asinh:()=>hy,atan:()=>fy,atan2:()=>my,atanh:()=>gy,avgPool:()=>b2,avgPool3d:()=>by,backend:()=>tr,backend_util:()=>T,basicLSTMCell:()=>vy,batchNorm:()=>Qd,batchNorm2d:()=>wy,batchNorm3d:()=>ky,batchNorm4d:()=>Iy,batchToSpaceND:()=>v2,bincount:()=>w2,booleanMaskAsync:()=>a4,broadcastArgs:()=>Sy,broadcastTo:()=>sl,broadcast_util:()=>xo,browser:()=>wr,buffer:()=>Me,cast:()=>He,ceil:()=>Ty,clipByValue:()=>Cy,clone:()=>wa,complex:()=>br,concat:()=>at,concat1d:()=>Ny,concat2d:()=>ru,concat3d:()=>Ey,concat4d:()=>Ry,conv1d:()=>My,conv2d:()=>ep,conv2dTranspose:()=>_y,conv3d:()=>Py,conv3dTranspose:()=>Fy,copyRegisteredKernels:()=>FS,cos:()=>Oy,cosh:()=>Dy,cosineWindow:()=>vh,cumprod:()=>zy,cumsum:()=>Ly,customGrad:()=>Qn,denseBincount:()=>By,deprecationWarn:()=>l2,depthToSpace:()=>Wy,depthwiseConv2d:()=>hh,deregisterOp:()=>yP,device_util:()=>jd,diag:()=>Vy,dilation2d:()=>Uy,disableDeprecationWarnings:()=>uC,dispose:()=>Y,disposeVariables:()=>dC,div:()=>me,divNoNan:()=>Gy,dot:()=>Hy,dropout:()=>o4,einsum:()=>jy,elu:()=>I2,enableDebugMode:()=>lC,enableProdMode:()=>o2,enclosingPowerOfTwo:()=>J2,engine:()=>kt,env:()=>W,equal:()=>k2,erf:()=>qy,euclideanNorm:()=>Zy,exp:()=>Zr,expandDims:()=>Gt,expm1:()=>Yy,eye:()=>T2,fft:()=>yh,fill:()=>nr,findBackend:()=>u2,findBackendFactory:()=>mC,floor:()=>C2,floorDiv:()=>Yd,forceHalfFloat:()=>G6,fused:()=>Q2,gather:()=>N2,gatherND:()=>i4,gather_util:()=>c2,getBackend:()=>ia,getGradient:()=>Hm,getKernel:()=>Sc,getKernelsForBackend:()=>Zn,getThreadsCount:()=>Ene,gpgpu_util:()=>w6,grad:()=>UE,grads:()=>GE,greater:()=>np,greaterEqual:()=>E2,ifft:()=>hd,imag:()=>Zd,image:()=>ge,inTopKAsync:()=>l4,io:()=>jn,irfft:()=>X2,isFinite:()=>Jy,isInf:()=>Qy,isNaN:()=>eb,keep:()=>On,kernel_impls:()=>Tn,leakyRelu:()=>R2,less:()=>tb,lessEqual:()=>fh,linalg:()=>g4,linspace:()=>ab,loadGraphModel:()=>r3,loadGraphModelSync:()=>kF,localResponseNormalization:()=>nb,log:()=>cl,log1p:()=>M2,logSigmoid:()=>sb,logSoftmax:()=>ib,logSumExp:()=>_2,logicalAnd:()=>pd,logicalNot:()=>P2,logicalOr:()=>F2,logicalXor:()=>ob,losses:()=>x4,lowerBound:()=>lb,matMul:()=>st,math:()=>UA,max:()=>pa,maxPool:()=>O2,maxPool3d:()=>ub,maxPoolWithArgmax:()=>db,maximum:()=>D2,mean:()=>cd,memory:()=>pC,meshgrid:()=>pb,min:()=>Kr,minimum:()=>z2,mirrorPad:()=>cb,mod:()=>su,moments:()=>hb,movingAverage:()=>n4,mul:()=>ae,multiRNNCell:()=>fb,multinomial:()=>mb,neg:()=>Xn,nextFrame:()=>b4,norm:()=>ap,notEqual:()=>L2,oneHot:()=>Nc,ones:()=>Wr,onesLike:()=>gb,op:()=>D,outerProduct:()=>xb,pad:()=>rr,pad1d:()=>Ab,pad2d:()=>yb,pad3d:()=>bb,pad4d:()=>vb,pool:()=>wb,pow:()=>pl,prelu:()=>W2,print:()=>r2,prod:()=>kb,profile:()=>cC,raggedGather:()=>Ib,raggedRange:()=>Sb,raggedTensorToTensor:()=>Tb,rand:()=>Cb,randomGamma:()=>Nb,randomNormal:()=>G2,randomStandardNormal:()=>Eb,randomUniform:()=>H2,range:()=>hl,ready:()=>Kd,real:()=>dl,reciprocal:()=>Rb,registerBackend:()=>go,registerGradient:()=>$S,registerKernel:()=>mn,registerOp:()=>AP,relu:()=>rp,relu6:()=>j2,removeBackend:()=>fC,reshape:()=>J,reverse:()=>Yr,reverse1d:()=>Mb,reverse2d:()=>$b,reverse3d:()=>_b,reverse4d:()=>Pb,rfft:()=>bh,round:()=>q2,rsqrt:()=>Fb,scalar:()=>Fe,scatterND:()=>r4,scatter_util:()=>h2,searchSorted:()=>gh,selu:()=>Ob,separableConv2d:()=>Db,serialization:()=>ay,setBackend:()=>Xd,setPlatform:()=>gC,setThreadsCount:()=>Nne,setWasmPath:()=>Cne,setWasmPaths:()=>Wh,setWebGLContext:()=>Fh,setdiff1dAsync:()=>zb,shared:()=>_h,sigmoid:()=>Da,sign:()=>Lb,signal:()=>m4,sin:()=>Bb,sinh:()=>Wb,slice:()=>Pe,slice1d:()=>Vb,slice2d:()=>Ub,slice3d:()=>sp,slice4d:()=>xh,slice_util:()=>It,softmax:()=>Ah,softplus:()=>$2,spaceToBatchND:()=>B2,sparse:()=>A4,sparseToDense:()=>s4,spectral:()=>f4,split:()=>ka,sqrt:()=>Jn,square:()=>In,squaredDifference:()=>K2,squeeze:()=>_e,stack:()=>sa,step:()=>Z2,stridedSlice:()=>Gb,string:()=>y4,sub:()=>fe,sum:()=>tt,sumOutType:()=>Hd,tan:()=>Hb,tanh:()=>Rc,tensor:()=>Be,tensor1d:()=>Ht,tensor2d:()=>Kn,tensor3d:()=>p2,tensor4d:()=>jb,tensor5d:()=>qb,tensor6d:()=>Xb,tensor_util:()=>vA,test_util:()=>ry,tidy:()=>$e,tile:()=>Gr,time:()=>hC,topk:()=>Kb,train:()=>m_,transpose:()=>Ws,truncatedNormal:()=>Zb,unique:()=>Yb,unregisterGradient:()=>PS,unregisterKernel:()=>_S,unsortedSegmentSum:()=>Jb,unstack:()=>Ta,upcastType:()=>ca,upperBound:()=>Qb,util:()=>v,valueAndGrad:()=>HE,valueAndGrads:()=>jE,variable:()=>e4,variableGrads:()=>rb,version:()=>xp,version_converter:()=>SF,version_core:()=>A2,version_cpu:()=>$O,version_wasm:()=>Rne,version_webgl:()=>AG,webgl:()=>yG,webgl_util:()=>j7,webgpu_util:()=>C8,where:()=>Vs,whereAsync:()=>Y2,zeros:()=>fn,zerosLike:()=>Ka});var DI=Object.create,z1=Object.defineProperty,zI=Object.getOwnPropertyDescriptor,LI=Object.getOwnPropertyNames,BI=Object.getPrototypeOf,WI=Object.prototype.hasOwnProperty,aA=(e=>typeof Cs!=\"undefined\"?Cs:typeof Proxy!=\"undefined\"?new Proxy(e,{get:(t,a)=>(typeof Cs!=\"undefined\"?Cs:t)[a]}):e)(function(e){if(typeof Cs!=\"undefined\")return Cs.apply(this,arguments);throw new Error('Dynamic require of \"'+e+'\" is not supported')}),qt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Xe=(e,t)=>{for(var a in t)z1(e,a,{get:t[a],enumerable:!0})},VI=(e,t,a,n)=>{if(t&&typeof t==\"object\"||typeof t==\"function\")for(let r of LI(t))!WI.call(e,r)&&r!==a&&z1(e,r,{get:()=>t[r],enumerable:!(n=zI(t,r))||n.enumerable});return e},yl=(e,t,a)=>(a=e!=null?DI(BI(e)):{},VI(t||!e||!e.__esModule?z1(a,\"default\",{value:e,enumerable:!0}):a,e)),UI=qt((e,t)=>{t.exports=n;var a=null;try{a=new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([0,97,115,109,1,0,0,0,1,13,2,96,0,1,127,96,4,127,127,127,127,1,127,3,7,6,0,1,1,1,1,1,6,6,1,127,1,65,0,11,7,50,6,3,109,117,108,0,1,5,100,105,118,95,115,0,2,5,100,105,118,95,117,0,3,5,114,101,109,95,115,0,4,5,114,101,109,95,117,0,5,8,103,101,116,95,104,105,103,104,0,0,10,191,1,6,4,0,35,0,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,126,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,127,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,128,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,129,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,130,34,4,66,32,135,167,36,0,32,4,167,11])),{}).exports}catch(I){}function n(I,N,O){this.low=I|0,this.high=N|0,this.unsigned=!!O}n.prototype.__isLong__,Object.defineProperty(n.prototype,\"__isLong__\",{value:!0});function r(I){return(I&&I.__isLong__)===!0}n.isLong=r;var s={},i={};function o(I,N){var O,L,B;return N?(I>>>=0,(B=0<=I&&I<256)&&(L=i[I],L)?L:(O=u(I,(I|0)<0?-1:0,!0),B&&(i[I]=O),O)):(I|=0,(B=-128<=I&&I<128)&&(L=s[I],L)?L:(O=u(I,I<0?-1:0,!1),B&&(s[I]=O),O))}n.fromInt=o;function l(I,N){if(isNaN(I))return N?b:y;if(N){if(I<0)return b;if(I>=g)return _}else{if(I<=-x)return $;if(I+1>=x)return E}return I<0?l(-I,N).neg():u(I%m|0,I/m|0,N)}n.fromNumber=l;function u(I,N,O){return new n(I,N,O)}n.fromBits=u;var p=Math.pow;function c(I,N,O){if(I.length===0)throw Error(\"empty string\");if(I===\"NaN\"||I===\"Infinity\"||I===\"+Infinity\"||I===\"-Infinity\")return y;if(typeof N==\"number\"?(O=N,N=!1):N=!!N,O=O||10,O<2||36<O)throw RangeError(\"radix\");var L;if((L=I.indexOf(\"-\"))>0)throw Error(\"interior hyphen\");if(L===0)return c(I.substring(1),N,O).neg();for(var B=l(p(O,8)),G=y,j=0;j<I.length;j+=8){var U=Math.min(8,I.length-j),H=parseInt(I.substring(j,j+U),O);if(U<8){var V=l(p(O,U));G=G.mul(V).add(l(H))}else G=G.mul(B),G=G.add(l(H))}return G.unsigned=N,G}n.fromString=c;function d(I,N){return typeof I==\"number\"?l(I,N):typeof I==\"string\"?c(I,N):u(I.low,I.high,typeof N==\"boolean\"?N:I.unsigned)}n.fromValue=d;var h=1<<16,f=1<<24,m=h*h,g=m*m,x=g/2,A=o(f),y=o(0);n.ZERO=y;var b=o(0,!0);n.UZERO=b;var w=o(1);n.ONE=w;var S=o(1,!0);n.UONE=S;var C=o(-1);n.NEG_ONE=C;var E=u(-1,2147483647,!1);n.MAX_VALUE=E;var _=u(-1,-1,!0);n.MAX_UNSIGNED_VALUE=_;var $=u(0,-2147483648,!1);n.MIN_VALUE=$;var M=n.prototype;M.toInt=function(){return this.unsigned?this.low>>>0:this.low},M.toNumber=function(){return this.unsigned?(this.high>>>0)*m+(this.low>>>0):this.high*m+(this.low>>>0)},M.toString=function(I){if(I=I||10,I<2||36<I)throw RangeError(\"radix\");if(this.isZero())return\"0\";if(this.isNegative())if(this.eq($)){var N=l(I),O=this.div(N),L=O.mul(N).sub(this);return O.toString(I)+L.toInt().toString(I)}else return\"-\"+this.neg().toString(I);for(var B=l(p(I,6),this.unsigned),G=this,j=\"\";;){var U=G.div(B),H=G.sub(U.mul(B)).toInt()>>>0,V=H.toString(I);if(G=U,G.isZero())return V+j;for(;V.length<6;)V=\"0\"+V;j=\"\"+V+j}},M.getHighBits=function(){return this.high},M.getHighBitsUnsigned=function(){return this.high>>>0},M.getLowBits=function(){return this.low},M.getLowBitsUnsigned=function(){return this.low>>>0},M.getNumBitsAbs=function(){if(this.isNegative())return this.eq($)?64:this.neg().getNumBitsAbs();for(var I=this.high!=0?this.high:this.low,N=31;N>0&&(I&1<<N)==0;N--);return this.high!=0?N+33:N+1},M.isZero=function(){return this.high===0&&this.low===0},M.eqz=M.isZero,M.isNegative=function(){return!this.unsigned&&this.high<0},M.isPositive=function(){return this.unsigned||this.high>=0},M.isOdd=function(){return(this.low&1)===1},M.isEven=function(){return(this.low&1)===0},M.equals=function(I){return r(I)||(I=d(I)),this.unsigned!==I.unsigned&&this.high>>>31===1&&I.high>>>31===1?!1:this.high===I.high&&this.low===I.low},M.eq=M.equals,M.notEquals=function(I){return!this.eq(I)},M.neq=M.notEquals,M.ne=M.notEquals,M.lessThan=function(I){return this.comp(I)<0},M.lt=M.lessThan,M.lessThanOrEqual=function(I){return this.comp(I)<=0},M.lte=M.lessThanOrEqual,M.le=M.lessThanOrEqual,M.greaterThan=function(I){return this.comp(I)>0},M.gt=M.greaterThan,M.greaterThanOrEqual=function(I){return this.comp(I)>=0},M.gte=M.greaterThanOrEqual,M.ge=M.greaterThanOrEqual,M.compare=function(I){if(r(I)||(I=d(I)),this.eq(I))return 0;var N=this.isNegative(),O=I.isNegative();return N&&!O?-1:!N&&O?1:this.unsigned?I.high>>>0>this.high>>>0||I.high===this.high&&I.low>>>0>this.low>>>0?-1:1:this.sub(I).isNegative()?-1:1},M.comp=M.compare,M.negate=function(){return!this.unsigned&&this.eq($)?$:this.not().add(w)},M.neg=M.negate,M.add=function(I){r(I)||(I=d(I));var N=this.high>>>16,O=this.high&65535,L=this.low>>>16,B=this.low&65535,G=I.high>>>16,j=I.high&65535,U=I.low>>>16,H=I.low&65535,V=0,Q=0,Z=0,re=0;return re+=B+H,Z+=re>>>16,re&=65535,Z+=L+U,Q+=Z>>>16,Z&=65535,Q+=O+j,V+=Q>>>16,Q&=65535,V+=N+G,V&=65535,u(Z<<16|re,V<<16|Q,this.unsigned)},M.subtract=function(I){return r(I)||(I=d(I)),this.add(I.neg())},M.sub=M.subtract,M.multiply=function(I){if(this.isZero())return y;if(r(I)||(I=d(I)),a){var N=a.mul(this.low,this.high,I.low,I.high);return u(N,a.get_high(),this.unsigned)}if(I.isZero())return y;if(this.eq($))return I.isOdd()?$:y;if(I.eq($))return this.isOdd()?$:y;if(this.isNegative())return I.isNegative()?this.neg().mul(I.neg()):this.neg().mul(I).neg();if(I.isNegative())return this.mul(I.neg()).neg();if(this.lt(A)&&I.lt(A))return l(this.toNumber()*I.toNumber(),this.unsigned);var O=this.high>>>16,L=this.high&65535,B=this.low>>>16,G=this.low&65535,j=I.high>>>16,U=I.high&65535,H=I.low>>>16,V=I.low&65535,Q=0,Z=0,re=0,ee=0;return ee+=G*V,re+=ee>>>16,ee&=65535,re+=B*V,Z+=re>>>16,re&=65535,re+=G*H,Z+=re>>>16,re&=65535,Z+=L*V,Q+=Z>>>16,Z&=65535,Z+=B*H,Q+=Z>>>16,Z&=65535,Z+=G*U,Q+=Z>>>16,Z&=65535,Q+=O*V+L*H+B*U+G*j,Q&=65535,u(re<<16|ee,Q<<16|Z,this.unsigned)},M.mul=M.multiply,M.divide=function(I){if(r(I)||(I=d(I)),I.isZero())throw Error(\"division by zero\");if(a){if(!this.unsigned&&this.high===-2147483648&&I.low===-1&&I.high===-1)return this;var N=(this.unsigned?a.div_u:a.div_s)(this.low,this.high,I.low,I.high);return u(N,a.get_high(),this.unsigned)}if(this.isZero())return this.unsigned?b:y;var O,L,B;if(this.unsigned){if(I.unsigned||(I=I.toUnsigned()),I.gt(this))return b;if(I.gt(this.shru(1)))return S;B=b}else{if(this.eq($)){if(I.eq(w)||I.eq(C))return $;if(I.eq($))return w;var G=this.shr(1);return O=G.div(I).shl(1),O.eq(y)?I.isNegative()?w:C:(L=this.sub(I.mul(O)),B=O.add(L.div(I)),B)}else if(I.eq($))return this.unsigned?b:y;if(this.isNegative())return I.isNegative()?this.neg().div(I.neg()):this.neg().div(I).neg();if(I.isNegative())return this.div(I.neg()).neg();B=y}for(L=this;L.gte(I);){O=Math.max(1,Math.floor(L.toNumber()/I.toNumber()));for(var j=Math.ceil(Math.log(O)/Math.LN2),U=j<=48?1:p(2,j-48),H=l(O),V=H.mul(I);V.isNegative()||V.gt(L);)O-=U,H=l(O,this.unsigned),V=H.mul(I);H.isZero()&&(H=w),B=B.add(H),L=L.sub(V)}return B},M.div=M.divide,M.modulo=function(I){if(r(I)||(I=d(I)),a){var N=(this.unsigned?a.rem_u:a.rem_s)(this.low,this.high,I.low,I.high);return u(N,a.get_high(),this.unsigned)}return this.sub(this.div(I).mul(I))},M.mod=M.modulo,M.rem=M.modulo,M.not=function(){return u(~this.low,~this.high,this.unsigned)},M.and=function(I){return r(I)||(I=d(I)),u(this.low&I.low,this.high&I.high,this.unsigned)},M.or=function(I){return r(I)||(I=d(I)),u(this.low|I.low,this.high|I.high,this.unsigned)},M.xor=function(I){return r(I)||(I=d(I)),u(this.low^I.low,this.high^I.high,this.unsigned)},M.shiftLeft=function(I){return r(I)&&(I=I.toInt()),(I&=63)===0?this:I<32?u(this.low<<I,this.high<<I|this.low>>>32-I,this.unsigned):u(0,this.low<<I-32,this.unsigned)},M.shl=M.shiftLeft,M.shiftRight=function(I){return r(I)&&(I=I.toInt()),(I&=63)===0?this:I<32?u(this.low>>>I|this.high<<32-I,this.high>>I,this.unsigned):u(this.high>>I-32,this.high>=0?0:-1,this.unsigned)},M.shr=M.shiftRight,M.shiftRightUnsigned=function(I){if(r(I)&&(I=I.toInt()),I&=63,I===0)return this;var N=this.high;if(I<32){var O=this.low;return u(O>>>I|N<<32-I,N>>>I,this.unsigned)}else return I===32?u(N,0,this.unsigned):u(N>>>I-32,0,this.unsigned)},M.shru=M.shiftRightUnsigned,M.shr_u=M.shiftRightUnsigned,M.toSigned=function(){return this.unsigned?u(this.low,this.high,!1):this},M.toUnsigned=function(){return this.unsigned?this:u(this.low,this.high,!0)},M.toBytes=function(I){return I?this.toBytesLE():this.toBytesBE()},M.toBytesLE=function(){var I=this.high,N=this.low;return[N&255,N>>>8&255,N>>>16&255,N>>>24,I&255,I>>>8&255,I>>>16&255,I>>>24]},M.toBytesBE=function(){var I=this.high,N=this.low;return[I>>>24,I>>>16&255,I>>>8&255,I&255,N>>>24,N>>>16&255,N>>>8&255,N&255]},n.fromBytes=function(I,N,O){return O?n.fromBytesLE(I,N):n.fromBytesBE(I,N)},n.fromBytesLE=function(I,N){return new n(I[0]|I[1]<<8|I[2]<<16|I[3]<<24,I[4]|I[5]<<8|I[6]<<16|I[7]<<24,N)},n.fromBytesBE=function(I,N){return new n(I[4]<<24|I[5]<<16|I[6]<<8|I[7],I[0]<<24|I[1]<<16|I[2]<<8|I[3],N)}}),GI=qt(()=>{}),HI=qt(()=>{}),jI=qt((e,t)=>{(function(a,n,r){function s(u){var p=this,c=l();p.next=function(){var d=2091639*p.s0+p.c*23283064365386963e-26;return p.s0=p.s1,p.s1=p.s2,p.s2=d-(p.c=d|0)},p.c=1,p.s0=c(\" \"),p.s1=c(\" \"),p.s2=c(\" \"),p.s0-=c(u),p.s0<0&&(p.s0+=1),p.s1-=c(u),p.s1<0&&(p.s1+=1),p.s2-=c(u),p.s2<0&&(p.s2+=1),c=null}function i(u,p){return p.c=u.c,p.s0=u.s0,p.s1=u.s1,p.s2=u.s2,p}function o(u,p){var c=new s(u),d=p&&p.state,h=c.next;return h.int32=function(){return c.next()*4294967296|0},h.double=function(){return h()+(h()*2097152|0)*11102230246251565e-32},h.quick=h,d&&(typeof d==\"object\"&&i(d,c),h.state=function(){return i(c,{})}),h}function l(){var u=4022871197,p=function(c){c=String(c);for(var d=0;d<c.length;d++){u+=c.charCodeAt(d);var h=.02519603282416938*u;u=h>>>0,h-=u,h*=u,u=h>>>0,h-=u,u+=h*4294967296}return(u>>>0)*23283064365386963e-26};return p}n&&n.exports?n.exports=o:r&&r.amd?r(function(){return o}):this.alea=o})(e,typeof t==\"object\"&&t,typeof define==\"function\"&&define)}),qI=qt((e,t)=>{(function(a,n,r){function s(l){var u=this,p=\"\";u.x=0,u.y=0,u.z=0,u.w=0,u.next=function(){var d=u.x^u.x<<11;return u.x=u.y,u.y=u.z,u.z=u.w,u.w^=u.w>>>19^d^d>>>8},l===(l|0)?u.x=l:p+=l;for(var c=0;c<p.length+64;c++)u.x^=p.charCodeAt(c)|0,u.next()}function i(l,u){return u.x=l.x,u.y=l.y,u.z=l.z,u.w=l.w,u}function o(l,u){var p=new s(l),c=u&&u.state,d=function(){return(p.next()>>>0)/4294967296};return d.double=function(){do var h=p.next()>>>11,f=(p.next()>>>0)/4294967296,m=(h+f)/(1<<21);while(m===0);return m},d.int32=p.next,d.quick=d,c&&(typeof c==\"object\"&&i(c,p),d.state=function(){return i(p,{})}),d}n&&n.exports?n.exports=o:r&&r.amd?r(function(){return o}):this.xor128=o})(e,typeof t==\"object\"&&t,typeof define==\"function\"&&define)}),XI=qt((e,t)=>{(function(a,n,r){function s(l){var u=this,p=\"\";u.next=function(){var d=u.x^u.x>>>2;return u.x=u.y,u.y=u.z,u.z=u.w,u.w=u.v,(u.d=u.d+362437|0)+(u.v=u.v^u.v<<4^(d^d<<1))|0},u.x=0,u.y=0,u.z=0,u.w=0,u.v=0,l===(l|0)?u.x=l:p+=l;for(var c=0;c<p.length+64;c++)u.x^=p.charCodeAt(c)|0,c==p.length&&(u.d=u.x<<10^u.x>>>4),u.next()}function i(l,u){return u.x=l.x,u.y=l.y,u.z=l.z,u.w=l.w,u.v=l.v,u.d=l.d,u}function o(l,u){var p=new s(l),c=u&&u.state,d=function(){return(p.next()>>>0)/4294967296};return d.double=function(){do var h=p.next()>>>11,f=(p.next()>>>0)/4294967296,m=(h+f)/(1<<21);while(m===0);return m},d.int32=p.next,d.quick=d,c&&(typeof c==\"object\"&&i(c,p),d.state=function(){return i(p,{})}),d}n&&n.exports?n.exports=o:r&&r.amd?r(function(){return o}):this.xorwow=o})(e,typeof t==\"object\"&&t,typeof define==\"function\"&&define)}),KI=qt((e,t)=>{(function(a,n,r){function s(l){var u=this;u.next=function(){var c=u.x,d=u.i,h,f,m;return h=c[d],h^=h>>>7,f=h^h<<24,h=c[d+1&7],f^=h^h>>>10,h=c[d+3&7],f^=h^h>>>3,h=c[d+4&7],f^=h^h<<7,h=c[d+7&7],h=h^h<<13,f^=h^h<<9,c[d]=f,u.i=d+1&7,f};function p(c,d){var h,f,m=[];if(d===(d|0))f=m[0]=d;else for(d=\"\"+d,h=0;h<d.length;++h)m[h&7]=m[h&7]<<15^d.charCodeAt(h)+m[h+1&7]<<13;for(;m.length<8;)m.push(0);for(h=0;h<8&&m[h]===0;++h);for(h==8?f=m[7]=-1:f=m[h],c.x=m,c.i=0,h=256;h>0;--h)c.next()}p(u,l)}function i(l,u){return u.x=l.x.slice(),u.i=l.i,u}function o(l,u){l==null&&(l=+new Date);var p=new s(l),c=u&&u.state,d=function(){return(p.next()>>>0)/4294967296};return d.double=function(){do var h=p.next()>>>11,f=(p.next()>>>0)/4294967296,m=(h+f)/(1<<21);while(m===0);return m},d.int32=p.next,d.quick=d,c&&(c.x&&i(c,p),d.state=function(){return i(p,{})}),d}n&&n.exports?n.exports=o:r&&r.amd?r(function(){return o}):this.xorshift7=o})(e,typeof t==\"object\"&&t,typeof define==\"function\"&&define)}),ZI=qt((e,t)=>{(function(a,n,r){function s(l){var u=this;u.next=function(){var c=u.w,d=u.X,h=u.i,f,m;return u.w=c=c+1640531527|0,m=d[h+34&127],f=d[h=h+1&127],m^=m<<13,f^=f<<17,m^=m>>>15,f^=f>>>12,m=d[h]=m^f,u.i=h,m+(c^c>>>16)|0};function p(c,d){var h,f,m,g,x,A=[],y=128;for(d===(d|0)?(f=d,d=null):(d=d+\"\\0\",f=0,y=Math.max(y,d.length)),m=0,g=-32;g<y;++g)d&&(f^=d.charCodeAt((g+32)%d.length)),g===0&&(x=f),f^=f<<10,f^=f>>>15,f^=f<<4,f^=f>>>13,g>=0&&(x=x+1640531527|0,h=A[g&127]^=f+x,m=h==0?m+1:0);for(m>=128&&(A[(d&&d.length||0)&127]=-1),m=127,g=4*128;g>0;--g)f=A[m+34&127],h=A[m=m+1&127],f^=f<<13,h^=h<<17,f^=f>>>15,h^=h>>>12,A[m]=f^h;c.w=x,c.X=A,c.i=m}p(u,l)}function i(l,u){return u.i=l.i,u.w=l.w,u.X=l.X.slice(),u}function o(l,u){l==null&&(l=+new Date);var p=new s(l),c=u&&u.state,d=function(){return(p.next()>>>0)/4294967296};return d.double=function(){do var h=p.next()>>>11,f=(p.next()>>>0)/4294967296,m=(h+f)/(1<<21);while(m===0);return m},d.int32=p.next,d.quick=d,c&&(c.X&&i(c,p),d.state=function(){return i(p,{})}),d}n&&n.exports?n.exports=o:r&&r.amd?r(function(){return o}):this.xor4096=o})(e,typeof t==\"object\"&&t,typeof define==\"function\"&&define)}),YI=qt((e,t)=>{(function(a,n,r){function s(l){var u=this,p=\"\";u.next=function(){var d=u.b,h=u.c,f=u.d,m=u.a;return d=d<<25^d>>>7^h,h=h-f|0,f=f<<24^f>>>8^m,m=m-d|0,u.b=d=d<<20^d>>>12^h,u.c=h=h-f|0,u.d=f<<16^h>>>16^m,u.a=m-d|0},u.a=0,u.b=0,u.c=-1640531527,u.d=1367130551,l===Math.floor(l)?(u.a=l/4294967296|0,u.b=l|0):p+=l;for(var c=0;c<p.length+20;c++)u.b^=p.charCodeAt(c)|0,u.next()}function i(l,u){return u.a=l.a,u.b=l.b,u.c=l.c,u.d=l.d,u}function o(l,u){var p=new s(l),c=u&&u.state,d=function(){return(p.next()>>>0)/4294967296};return d.double=function(){do var h=p.next()>>>11,f=(p.next()>>>0)/4294967296,m=(h+f)/(1<<21);while(m===0);return m},d.int32=p.next,d.quick=d,c&&(typeof c==\"object\"&&i(c,p),d.state=function(){return i(p,{})}),d}n&&n.exports?n.exports=o:r&&r.amd?r(function(){return o}):this.tychei=o})(e,typeof t==\"object\"&&t,typeof define==\"function\"&&define)}),JI=qt(()=>{}),QI=qt((e,t)=>{(function(a,n,r){var s=256,i=6,o=52,l=\"random\",u=r.pow(s,i),p=r.pow(2,o),c=p*2,d=s-1,h;function f(w,S,C){var E=[];S=S==!0?{entropy:!0}:S||{};var _=A(x(S.entropy?[w,b(n)]:w==null?y():w,3),E),$=new m(E),M=function(){for(var I=$.g(i),N=u,O=0;I<p;)I=(I+O)*s,N*=s,O=$.g(1);for(;I>=c;)I/=2,N/=2,O>>>=1;return(I+O)/N};return M.int32=function(){return $.g(4)|0},M.quick=function(){return $.g(4)/4294967296},M.double=M,A(b($.S),n),(S.pass||C||function(I,N,O,L){return L&&(L.S&&g(L,$),I.state=function(){return g($,{})}),O?(r[l]=I,N):I})(M,_,\"global\"in S?S.global:this==r,S.state)}function m(w){var S,C=w.length,E=this,_=0,$=E.i=E.j=0,M=E.S=[];for(C||(w=[C++]);_<s;)M[_]=_++;for(_=0;_<s;_++)M[_]=M[$=d&$+w[_%C]+(S=M[_])],M[$]=S;(E.g=function(I){for(var N,O=0,L=E.i,B=E.j,G=E.S;I--;)N=G[L=d&L+1],O=O*s+G[d&(G[L]=G[B=d&B+N])+(G[B]=N)];return E.i=L,E.j=B,O})(s)}function g(w,S){return S.i=w.i,S.j=w.j,S.S=w.S.slice(),S}function x(w,S){var C=[],E=typeof w,_;if(S&&E==\"object\")for(_ in w)try{C.push(x(w[_],S-1))}catch($){}return C.length?C:E==\"string\"?w:w+\"\\0\"}function A(w,S){for(var C=w+\"\",E,_=0;_<C.length;)S[d&_]=d&(E^=S[d&_]*19)+C.charCodeAt(_++);return b(S)}function y(){try{var w;return h&&(w=h.randomBytes)?w=w(s):(w=new Uint8Array(s),(a.crypto||a.msCrypto).getRandomValues(w)),b(w)}catch(E){var S=a.navigator,C=S&&S.plugins;return[+new Date,a,C,a.screen,b(n)]}}function b(w){return String.fromCharCode.apply(0,w)}if(A(r.random(),n),typeof t==\"object\"&&t.exports){t.exports=f;try{h=JI()}catch(w){}}else typeof define==\"function\"&&define.amd?define(function(){return f}):r[\"seed\"+l]=f})(typeof self!=\"undefined\"?self:e,[],Math)}),nA=qt((e,t)=>{var a=jI(),n=qI(),r=XI(),s=KI(),i=ZI(),o=YI(),l=QI();l.alea=a,l.xor128=n,l.xorwow=r,l.xorshift7=s,l.xor4096=i,l.tychei=o,t.exports=l}),wc=qt(()=>{}),rA=qt(()=>{}),eS=qt(()=>{}),tS=qt(()=>{}),aS=qt(()=>{}),nS=qt((e,t)=>{var a=(()=>{var n=typeof document!=\"undefined\"&&document.currentScript?document.currentScript.src:void 0;return typeof __filename!=\"undefined\"&&(n=n||__filename),function(r){r=r||{};function s(){return oe.buffer!=je&&dt(oe.buffer),ht}function i(){return oe.buffer!=je&&dt(oe.buffer),Va}function o(){return oe.buffer!=je&&dt(oe.buffer),Ft}function l(){return oe.buffer!=je&&dt(oe.buffer),aa}function u(){return oe.buffer!=je&&dt(oe.buffer),$a}function p(){return oe.buffer!=je&&dt(oe.buffer),on}function c(){return oe.buffer!=je&&dt(oe.buffer),_a}var d=typeof r!=\"undefined\"?r:{},h,f;d.ready=new Promise(function(F,q){h=F,f=q});var m;typeof process!=\"undefined\"&&process.listeners&&(m={uncaughtException:process.listeners(\"uncaughtException\"),unhandledRejection:process.listeners(\"unhandledRejection\")});var g=Object.assign({},d),x=[],A=\"./this.program\",y=(F,q)=>{throw q},b=typeof window==\"object\",w=typeof importScripts==\"function\",S=typeof process==\"object\"&&typeof process.versions==\"object\"&&typeof process.versions.node==\"string\",C=d.ENVIRONMENT_IS_PTHREAD||!1,E=\"\";function _(F){return d.locateFile?d.locateFile(F,E):E+F}var $,M,I,N;function O(F){F instanceof Ss||H(\"exiting due to exception: \"+F)}if(S){w?E=wc().dirname(E)+\"/\":E=__dirname+\"/\";var L,B;typeof aA==\"function\"&&(L=rA(),B=wc()),$=(q,se)=>(q=B.normalize(q),L.readFileSync(q,se?void 0:\"utf8\")),I=q=>{var se=$(q,!0);return se.buffer||(se=new Uint8Array(se)),se},M=(q,se,pe)=>{q=B.normalize(q),L.readFile(q,function(Te,Je){Te?pe(Te):se(Je.buffer)})},process.argv.length>1&&(A=process.argv[1].replace(/\\\\/g,\"/\")),x=process.argv.slice(2),process.on(\"uncaughtException\",function(q){if(!(q instanceof Ss))throw q}),process.on(\"unhandledRejection\",function(q){throw q}),y=(q,se)=>{if(bn())throw process.exitCode=q,se;O(se),process.exit(q)},d.inspect=function(){return\"[Emscripten Module object]\"};let F;try{F=eS()}catch(q){throw console.error('The \"worker_threads\" module is not supported in this node.js build - perhaps a newer version is needed?'),q}global.Worker=F.Worker}else(b||w)&&(w?E=self.location.href:typeof document!=\"undefined\"&&document.currentScript&&(E=document.currentScript.src),typeof n!=\"undefined\"&&n&&(E=n),E.indexOf(\"blob:\")!==0?E=E.substr(0,E.replace(/[?#].*/,\"\").lastIndexOf(\"/\")+1):E=\"\",S||($=F=>{var q=new XMLHttpRequest;return q.open(\"GET\",F,!1),q.send(null),q.responseText},w&&(I=F=>{var q=new XMLHttpRequest;return q.open(\"GET\",F,!1),q.responseType=\"arraybuffer\",q.send(null),new Uint8Array(q.response)}),M=(F,q,se)=>{var pe=new XMLHttpRequest;pe.open(\"GET\",F,!0),pe.responseType=\"arraybuffer\",pe.onload=()=>{if(pe.status==200||pe.status==0&&pe.response){q(pe.response);return}se()},pe.onerror=se,pe.send(null)}),N=F=>document.title=F);S&&typeof performance==\"undefined\"&&(global.performance=tS().performance);var G=console.log.bind(console),j=console.warn.bind(console);S&&(G=F=>L.writeSync(1,F+`\n`),j=F=>L.writeSync(2,F+`\n`));var U=d.print||G,H=d.printErr||j;Object.assign(d,g),g=null,d.arguments&&(x=d.arguments),d.thisProgram&&(A=d.thisProgram),d.quit&&(y=d.quit);var V=4,Q=Atomics.load,Z=Atomics.store,re=Atomics.compareExchange,ee;d.wasmBinary&&(ee=d.wasmBinary);var he=d.noExitRuntime||!0;typeof WebAssembly!=\"object\"&&Uo(\"no native wasm support detected\");var oe,Ae,we=!1,Re;function Ge(F,q){F||Uo(q)}var Ke=typeof TextDecoder!=\"undefined\"?new TextDecoder(\"utf8\"):void 0;function nt(F,q,se){for(var pe=q+se,Te=q;F[Te]&&!(Te>=pe);)++Te;if(Te-q>16&&F.buffer&&Ke)return Ke.decode(F.buffer instanceof SharedArrayBuffer?F.slice(q,Te):F.subarray(q,Te));for(var Je=\"\";q<Te;){var Oe=F[q++];if(!(Oe&128)){Je+=String.fromCharCode(Oe);continue}var We=F[q++]&63;if((Oe&224)==192){Je+=String.fromCharCode((Oe&31)<<6|We);continue}var Dt=F[q++]&63;if((Oe&240)==224?Oe=(Oe&15)<<12|We<<6|Dt:Oe=(Oe&7)<<18|We<<12|Dt<<6|F[q++]&63,Oe<65536)Je+=String.fromCharCode(Oe);else{var un=Oe-65536;Je+=String.fromCharCode(55296|un>>10,56320|un&1023)}}return Je}function ut(F,q){return F?nt(i(),F,q):\"\"}function et(F,q,se,pe){if(!(pe>0))return 0;for(var Te=se,Je=se+pe-1,Oe=0;Oe<F.length;++Oe){var We=F.charCodeAt(Oe);if(We>=55296&&We<=57343){var Dt=F.charCodeAt(++Oe);We=65536+((We&1023)<<10)|Dt&1023}if(We<=127){if(se>=Je)break;q[se++]=We}else if(We<=2047){if(se+1>=Je)break;q[se++]=192|We>>6,q[se++]=128|We&63}else if(We<=65535){if(se+2>=Je)break;q[se++]=224|We>>12,q[se++]=128|We>>6&63,q[se++]=128|We&63}else{if(se+3>=Je)break;q[se++]=240|We>>18,q[se++]=128|We>>12&63,q[se++]=128|We>>6&63,q[se++]=128|We&63}}return q[se]=0,se-Te}function rt(F,q,se){return et(F,i(),q,se)}var je,ht,Va,Ft,sn,aa,$a,on,_a;C&&(je=d.buffer);function dt(F){je=F,d.HEAP8=ht=new Int8Array(F),d.HEAP16=Ft=new Int16Array(F),d.HEAP32=aa=new Int32Array(F),d.HEAPU8=Va=new Uint8Array(F),d.HEAPU16=sn=new Uint16Array(F),d.HEAPU32=$a=new Uint32Array(F),d.HEAPF32=on=new Float32Array(F),d.HEAPF64=_a=new Float64Array(F)}var Pa=d.INITIAL_MEMORY||16777216;if(C)oe=d.wasmMemory,je=d.buffer;else if(d.wasmMemory)oe=d.wasmMemory;else if(oe=new WebAssembly.Memory({initial:Pa/65536,maximum:32768,shared:!0}),!(oe.buffer instanceof SharedArrayBuffer))throw H(\"requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag\"),S&&console.log(\"(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)\"),Error(\"bad memory\");oe&&(je=oe.buffer),Pa=je.byteLength,dt(je);var Ua,ur=[],Bo=[],Un=[],$u=!1;function bn(){return he}function Wo(){if(d.preRun)for(typeof d.preRun==\"function\"&&(d.preRun=[d.preRun]);d.preRun.length;)U0(d.preRun.shift());Ou(ur)}function Xt(){$u=!0,!C&&Ou(Bo)}function _p(){if(!C){if(d.postRun)for(typeof d.postRun==\"function\"&&(d.postRun=[d.postRun]);d.postRun.length;)y5(d.postRun.shift());Ou(Un)}}function U0(F){ur.unshift(F)}function G0(F){Bo.unshift(F)}function y5(F){Un.unshift(F)}var _r=0,Vo=null,dr=null;function b5(F){_r++,d.monitorRunDependencies&&d.monitorRunDependencies(_r)}function v5(F){if(_r--,d.monitorRunDependencies&&d.monitorRunDependencies(_r),_r==0&&(Vo!==null&&(clearInterval(Vo),Vo=null),dr)){var q=dr;dr=null,q()}}function Uo(F){C?postMessage({cmd:\"onAbort\",arg:F}):d.onAbort&&d.onAbort(F),F=\"Aborted(\"+F+\")\",H(F),we=!0,Re=1,F+=\". Build with -sASSERTIONS for more info.\";var q=new WebAssembly.RuntimeError(F);throw f(q),q}var H0=\"data:application/octet-stream;base64,\";function Pp(F){return F.startsWith(H0)}function _u(F){return F.startsWith(\"file://\")}var xa;xa=\"tfjs-backend-wasm-threaded-simd.wasm\",Pp(xa)||(xa=_(xa));function Fp(F){try{if(F==xa&&ee)return new Uint8Array(ee);if(I)return I(F);throw\"both async and sync fetching of the wasm failed\"}catch(q){Uo(q)}}function j0(){if(!ee&&(b||w)){if(typeof fetch==\"function\"&&!_u(xa))return fetch(xa,{credentials:\"same-origin\"}).then(function(F){if(!F.ok)throw\"failed to load wasm binary file at '\"+xa+\"'\";return F.arrayBuffer()}).catch(function(){return Fp(xa)});if(M)return new Promise(function(F,q){M(xa,function(se){F(new Uint8Array(se))},q)})}return Promise.resolve().then(function(){return Fp(xa)})}function q0(){var F={env:qp,wasi_snapshot_preview1:qp};function q(Oe,We){var Dt=Oe.exports;if(d.asm=Dt,nf(d.asm._emscripten_tls_init),Ua=d.asm.__indirect_function_table,G0(d.asm.__wasm_call_ctors),Ae=We,!C){var un=Le.unusedWorkers.length;Le.unusedWorkers.forEach(function(cr){Le.loadWasmModuleToWorker(cr,function(){--un||v5(\"wasm-instantiate\")})})}}C||b5(\"wasm-instantiate\");function se(Oe){q(Oe.instance,Oe.module)}function pe(Oe){return j0().then(function(We){return WebAssembly.instantiate(We,F)}).then(function(We){return We}).then(Oe,function(We){H(\"failed to asynchronously prepare wasm: \"+We),Uo(We)})}function Te(){return!ee&&typeof WebAssembly.instantiateStreaming==\"function\"&&!Pp(xa)&&!_u(xa)&&!S&&typeof fetch==\"function\"?fetch(xa,{credentials:\"same-origin\"}).then(function(Oe){var We=WebAssembly.instantiateStreaming(Oe,F);return We.then(se,function(Dt){return H(\"wasm streaming compile failed: \"+Dt),H(\"falling back to ArrayBuffer instantiation\"),pe(se)})}):pe(se)}if(d.instantiateWasm)try{var Je=d.instantiateWasm(F,q);return Je}catch(Oe){H(\"Module.instantiateWasm callback failed with error: \"+Oe),f(Oe)}return Te().catch(f),{}}var X0,w5,K0={};function Ss(F){this.name=\"ExitStatus\",this.message=\"Program terminated with exit(\"+F+\")\",this.status=F}function Z0(F){var q=Le.pthreads[F];delete Le.pthreads[F],q.terminate(),Nm(F),Le.runningWorkers.splice(Le.runningWorkers.indexOf(q),1),q.pthread_ptr=0}function Y0(F){var q=Le.pthreads[F];q.postMessage({cmd:\"cancel\"})}function Pu(F){var q=Le.pthreads[F];Ge(q),Le.returnWorkerToPool(q)}function Op(F){var q=Le.getNewWorker();if(!q)return 6;Le.runningWorkers.push(q),Le.pthreads[F.pthread_ptr]=q,q.pthread_ptr=F.pthread_ptr;var se={cmd:\"run\",start_routine:F.startRoutine,arg:F.arg,pthread_ptr:F.pthread_ptr};return q.runPthread=()=>{se.time=performance.now(),q.postMessage(se,F.transferList)},q.loaded&&(q.runPthread(),delete q.runPthread),0}var Dp={varargs:void 0,get:function(){Dp.varargs+=4;var F=l()[Dp.varargs-4>>2];return F},getStr:function(F){var q=ut(F);return q}};function Fu(F){if(C)return Pr(1,1,F);Re=F,bn()||(Le.terminateAllThreads(),d.onExit&&d.onExit(F),we=!0),y(F,new Ss(F))}function k5(F,q){if(Re=F,!q&&C)throw Lp(F),\"unwind\";Fu(F)}var zp=k5;function J0(F){if(F instanceof Ss||F==\"unwind\")return Re;y(1,F)}var Le={unusedWorkers:[],runningWorkers:[],tlsInitFunctions:[],pthreads:{},init:function(){C?Le.initWorker():Le.initMainThread()},initMainThread:function(){for(var F=8;F--;)Le.allocateUnusedWorker()},initWorker:function(){he=!1},setExitStatus:function(F){Re=F},terminateAllThreads:function(){for(var F of Object.values(Le.pthreads))Le.returnWorkerToPool(F);for(var F of Le.unusedWorkers)F.terminate();Le.unusedWorkers=[]},returnWorkerToPool:function(F){var q=F.pthread_ptr;delete Le.pthreads[q],Le.unusedWorkers.push(F),Le.runningWorkers.splice(Le.runningWorkers.indexOf(F),1),F.pthread_ptr=0,Nm(q)},receiveObjectTransfer:function(F){},threadInitTLS:function(){Le.tlsInitFunctions.forEach(F=>F())},loadWasmModuleToWorker:function(F,q){F.onmessage=se=>{var pe=se.data,Te=pe.cmd;if(F.pthread_ptr&&(Le.currentProxiedOperationCallerThread=F.pthread_ptr),pe.targetThread&&pe.targetThread!=Qp()){var Je=Le.pthreads[pe.targetThread];Je?Je.postMessage(pe,pe.transferList):H('Internal error! Worker sent a message \"'+Te+'\" to target pthread '+pe.targetThread+\", but that thread no longer exists!\"),Le.currentProxiedOperationCallerThread=void 0;return}Te===\"processProxyingQueue\"?Du(pe.queue):Te===\"spawnThread\"?Op(pe):Te===\"cleanupThread\"?Pu(pe.thread):Te===\"killThread\"?Z0(pe.thread):Te===\"cancelThread\"?Y0(pe.thread):Te===\"loaded\"?(F.loaded=!0,q&&q(F),F.runPthread&&(F.runPthread(),delete F.runPthread)):Te===\"print\"?U(\"Thread \"+pe.threadId+\": \"+pe.text):Te===\"printErr\"?H(\"Thread \"+pe.threadId+\": \"+pe.text):Te===\"alert\"?alert(\"Thread \"+pe.threadId+\": \"+pe.text):pe.target===\"setimmediate\"?F.postMessage(pe):Te===\"onAbort\"?d.onAbort&&d.onAbort(pe.arg):Te&&H(\"worker sent an unknown command \"+Te),Le.currentProxiedOperationCallerThread=void 0},F.onerror=se=>{var pe=\"worker sent an error!\";throw H(pe+\" \"+se.filename+\":\"+se.lineno+\": \"+se.message),se},S&&(F.on(\"message\",function(se){F.onmessage({data:se})}),F.on(\"error\",function(se){F.onerror(se)}),F.on(\"detachedExit\",function(){})),F.postMessage({cmd:\"load\",urlOrBlob:d.mainScriptUrlOrBlob||n,wasmMemory:oe,wasmModule:Ae})},allocateUnusedWorker:function(){var F=_(\"tfjs-backend-wasm-threaded-simd.worker.js\");Le.unusedWorkers.push(new Worker(F))},getNewWorker:function(){return Le.unusedWorkers.length==0&&(Le.allocateUnusedWorker(),Le.loadWasmModuleToWorker(Le.unusedWorkers[0])),Le.unusedWorkers.pop()}};d.PThread=Le;function Ou(F){for(;F.length>0;)F.shift()(d)}function Q0(F){var q=Em(),se=F();return ec(q),se}function I5(F){return F}function S5(F){var q=/\\b_Z[\\w\\d_]+/g;return F.replace(q,function(se){var pe=se;return se===pe?se:pe+\" [\"+se+\"]\"})}function ef(){var F=Qp(),q=l()[F+44>>2],se=l()[F+48>>2],pe=q-se;$5(q,pe),ec(q)}d.establishStackSpace=ef;function Lp(F){if(C)return Pr(2,0,F);try{zp(F)}catch(q){J0(q)}}var Go=[];function tf(F){var q=Go[F];return q||(F>=Go.length&&(Go.length=F+1),Go[F]=q=Ua.get(F)),q}function af(F,q){var se=tf(F)(q);bn()?Le.setExitStatus(se):M5(se)}d.invokeEntryPoint=af;function T5(){var F=new Error;if(!F.stack){try{throw new Error}catch(q){F=q}if(!F.stack)return\"(no stack trace available)\"}return F.stack.toString()}function nf(F){Le.tlsInitFunctions.push(F)}function rf(F,q){s().set(F,q)}function sf(F){N5(F,!w,1,!b),Le.threadInitTLS()}function of(F){C?postMessage({cmd:\"cleanupThread\",thread:F}):Pu(F)}function Bp(F,q,se,pe){return C?Pr(3,1,F,q,se,pe):Wp(F,q,se,pe)}function Wp(F,q,se,pe){if(typeof SharedArrayBuffer==\"undefined\")return H(\"Current environment does not support SharedArrayBuffer, pthreads are not available!\"),6;var Te=[],Je=0;if(C&&(Te.length===0||Je))return Bp(F,q,se,pe);if(Je)return Je;var Oe={startRoutine:se,pthread_ptr:F,arg:pe,transferList:Te};return C?(Oe.cmd=\"spawnThread\",postMessage(Oe,Te),0):Op(Oe)}function lf(){return 2097152}var uf=!0;function df(){return uf}function Du(F){Atomics.store(l(),F>>2,1),Qp()&&R5(F),Atomics.compareExchange(l(),F>>2,1,0)}d.executeNotifiedProxyingQueue=Du;function pf(F,q,se,pe){if(F==q)setTimeout(()=>Du(pe));else if(C)postMessage({targetThread:F,cmd:\"processProxyingQueue\",queue:pe});else{var Te=Le.pthreads[F];if(!Te)return;Te.postMessage({cmd:\"processProxyingQueue\",queue:pe})}return 1}function cf(F,q,se){return-1}function hf(){Uo(\"\")}function Ts(F){Ts.shown||(Ts.shown={}),Ts.shown[F]||(Ts.shown[F]=1,S&&(F=\"warning: \"+F),H(F))}function ff(){S||w||Ts(\"Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread\")}function mf(){return Date.now()}function Vp(){return 2147483648}function gf(){return Vp()}var Ho;S?Ho=()=>{var F=process.hrtime();return F[0]*1e3+F[1]/1e6}:C?Ho=()=>performance.now()-d.__performance_now_clock_drift:Ho=()=>performance.now();function xf(F,q,se){i().copyWithin(F,q,q+se)}function Af(){return S?aS().cpus().length:navigator.hardwareConcurrency}function Pr(F,q){var se=arguments.length-2,pe=arguments;return Q0(()=>{for(var Te=se,Je=tc(Te*8),Oe=Je>>3,We=0;We<se;We++){var Dt=pe[2+We];c()[Oe+We]=Dt}return E5(F,Te,Je,q)})}var zu=[];function yf(F,q,se){zu.length=q;for(var pe=se>>3,Te=0;Te<q;Te++)zu[Te]=c()[pe+Te];var Je=F<0,Oe=Je?K0[-F-1]:Cf[F];return Oe.apply(null,zu)}function bf(F){try{return oe.grow(F-je.byteLength+65535>>>16),dt(oe.buffer),1}catch(q){}}function vf(F){var q=i().length;if(F=F>>>0,F<=q)return!1;var se=Vp();if(F>se)return!1;let pe=(Dt,un)=>Dt+(un-Dt%un)%un;for(var Te=1;Te<=4;Te*=2){var Je=q*(1+.2/Te);Je=Math.min(Je,F+100663296);var Oe=Math.min(se,pe(Math.max(F,Je),65536)),We=bf(Oe);if(We)return!0}return!1}function wf(){throw\"unwind\"}function Up(F){return C?Pr(4,1,F):52}function Gp(F,q,se,pe,Te){return C?Pr(5,1,F,q,se,pe,Te):70}var kf=[null,[],[]];function If(F,q){var se=kf[F];q===0||q===10?((F===1?U:H)(nt(se,0)),se.length=0):se.push(q)}function Hp(F,q,se,pe){if(C)return Pr(6,1,F,q,se,pe);for(var Te=0,Je=0;Je<se;Je++){var Oe=u()[q>>2],We=u()[q+4>>2];q+=8;for(var Dt=0;Dt<We;Dt++)If(F,i()[Oe+Dt]);Te+=We}return u()[pe>>2]=Te,0}function jp(F){var q=d[\"_\"+F];return q}function Sf(F,q,se,pe,Te){var Je={string:dn=>{var Ko=0;if(dn!=null&&dn!==0){var F5=(dn.length<<2)+1;Ko=tc(F5),rt(dn,Ko,F5)}return Ko},array:dn=>{var Ko=tc(dn.length);return rf(dn,Ko),Ko}};function Oe(dn){return q===\"string\"?ut(dn):q===\"boolean\"?Boolean(dn):dn}var We=jp(F),Dt=[],un=0;if(pe)for(var cr=0;cr<pe.length;cr++){var P5=Je[se[cr]];P5?(un===0&&(un=Em()),Dt[cr]=P5(pe[cr])):Dt[cr]=pe[cr]}var Rm=We.apply(null,Dt);function RI(dn){return un!==0&&ec(un),Oe(dn)}return Rm=RI(Rm),Rm}function Tf(F,q,se,pe){se=se||[];var Te=se.every(Oe=>Oe===\"number\"||Oe===\"boolean\"),Je=q!==\"string\";return Je&&Te&&!pe?jp(F):function(){return Sf(F,q,se,arguments,pe)}}Le.init();var Cf=[null,Fu,Lp,Bp,Up,Gp,Hp],qp={__emscripten_init_main_thread_js:sf,__emscripten_thread_cleanup:of,__pthread_create_js:Wp,_emscripten_default_pthread_stack_size:lf,_emscripten_get_now_is_monotonic:df,_emscripten_notify_task_queue:pf,_emscripten_set_offscreencanvas_size:cf,abort:hf,emscripten_check_blocking_allowed:ff,emscripten_date_now:mf,emscripten_get_heap_max:gf,emscripten_get_now:Ho,emscripten_memcpy_big:xf,emscripten_num_logical_cores:Af,emscripten_receive_on_main_thread_js:yf,emscripten_resize_heap:vf,emscripten_unwind_to_js_event_loop:wf,exit:zp,fd_close:Up,fd_seek:Gp,fd_write:Hp,memory:oe||d.wasmMemory},C5=q0(),Nf=d.___wasm_call_ctors=function(){return(Nf=d.___wasm_call_ctors=d.asm.__wasm_call_ctors).apply(null,arguments)},Ef=d._init=function(){return(Ef=d._init=d.asm.init).apply(null,arguments)},Rf=d._init_with_threads_count=function(){return(Rf=d._init_with_threads_count=d.asm.init_with_threads_count).apply(null,arguments)},Mf=d._get_threads_count=function(){return(Mf=d._get_threads_count=d.asm.get_threads_count).apply(null,arguments)},$f=d._register_tensor=function(){return($f=d._register_tensor=d.asm.register_tensor).apply(null,arguments)},_f=d._dispose_data=function(){return(_f=d._dispose_data=d.asm.dispose_data).apply(null,arguments)},Pf=d._dispose=function(){return(Pf=d._dispose=d.asm.dispose).apply(null,arguments)},Ff=d._Abs=function(){return(Ff=d._Abs=d.asm.Abs).apply(null,arguments)},Of=d._Add=function(){return(Of=d._Add=d.asm.Add).apply(null,arguments)},Df=d._AddN=function(){return(Df=d._AddN=d.asm.AddN).apply(null,arguments)},zf=d._All=function(){return(zf=d._All=d.asm.All).apply(null,arguments)},Lf=d._Any=function(){return(Lf=d._Any=d.asm.Any).apply(null,arguments)},Bf=d._ArgMax=function(){return(Bf=d._ArgMax=d.asm.ArgMax).apply(null,arguments)},Wf=d._AvgPool=function(){return(Wf=d._AvgPool=d.asm.AvgPool).apply(null,arguments)},Vf=d._BatchMatMul=function(){return(Vf=d._BatchMatMul=d.asm.BatchMatMul).apply(null,arguments)},Uf=d._Ceil=function(){return(Uf=d._Ceil=d.asm.Ceil).apply(null,arguments)},Gf=d._ClipByValue=function(){return(Gf=d._ClipByValue=d.asm.ClipByValue).apply(null,arguments)},Hf=d._Conv2D=function(){return(Hf=d._Conv2D=d.asm.Conv2D).apply(null,arguments)},jf=d._Conv2DBackpropInput=function(){return(jf=d._Conv2DBackpropInput=d.asm.Conv2DBackpropInput).apply(null,arguments)},qf=d._Cos=function(){return(qf=d._Cos=d.asm.Cos).apply(null,arguments)},Xf=d._Cosh=function(){return(Xf=d._Cosh=d.asm.Cosh).apply(null,arguments)},Kf=d._CropAndResize=function(){return(Kf=d._CropAndResize=d.asm.CropAndResize).apply(null,arguments)},Zf=d._Cumprod=function(){return(Zf=d._Cumprod=d.asm.Cumprod).apply(null,arguments)},Yf=d._Cumsum=function(){return(Yf=d._Cumsum=d.asm.Cumsum).apply(null,arguments)},Jf=d._DepthToSpace=function(){return(Jf=d._DepthToSpace=d.asm.DepthToSpace).apply(null,arguments)},Qf=d._DepthwiseConv2dNative=function(){return(Qf=d._DepthwiseConv2dNative=d.asm.DepthwiseConv2dNative).apply(null,arguments)},em=d._Elu=function(){return(em=d._Elu=d.asm.Elu).apply(null,arguments)},tm=d._Equal=function(){return(tm=d._Equal=d.asm.Equal).apply(null,arguments)},am=d._Exp=function(){return(am=d._Exp=d.asm.Exp).apply(null,arguments)},nm=d._FlipLeftRight=function(){return(nm=d._FlipLeftRight=d.asm.FlipLeftRight).apply(null,arguments)},rm=d._Floor=function(){return(rm=d._Floor=d.asm.Floor).apply(null,arguments)},sm=d._FloorDiv=function(){return(sm=d._FloorDiv=d.asm.FloorDiv).apply(null,arguments)},im=d._FusedBatchNorm=function(){return(im=d._FusedBatchNorm=d.asm.FusedBatchNorm).apply(null,arguments)},om=d._FusedConv2D=function(){return(om=d._FusedConv2D=d.asm.FusedConv2D).apply(null,arguments)},lm=d._FusedDepthwiseConv2D=function(){return(lm=d._FusedDepthwiseConv2D=d.asm.FusedDepthwiseConv2D).apply(null,arguments)},um=d._Gather=function(){return(um=d._Gather=d.asm.Gather).apply(null,arguments)},dm=d._GatherNd=function(){return(dm=d._GatherNd=d.asm.GatherNd).apply(null,arguments)},pm=d._Greater=function(){return(pm=d._Greater=d.asm.Greater).apply(null,arguments)},cm=d._GreaterEqual=function(){return(cm=d._GreaterEqual=d.asm.GreaterEqual).apply(null,arguments)},hm=d._IsNan=function(){return(hm=d._IsNan=d.asm.IsNan).apply(null,arguments)},fm=d._LeakyRelu=function(){return(fm=d._LeakyRelu=d.asm.LeakyRelu).apply(null,arguments)},mm=d._Less=function(){return(mm=d._Less=d.asm.Less).apply(null,arguments)},gm=d._LessEqual=function(){return(gm=d._LessEqual=d.asm.LessEqual).apply(null,arguments)},xm=d._Log=function(){return(xm=d._Log=d.asm.Log).apply(null,arguments)},Am=d._LogicalAnd=function(){return(Am=d._LogicalAnd=d.asm.LogicalAnd).apply(null,arguments)},ym=d._LogicalNot=function(){return(ym=d._LogicalNot=d.asm.LogicalNot).apply(null,arguments)},bm=d._LogicalOr=function(){return(bm=d._LogicalOr=d.asm.LogicalOr).apply(null,arguments)},vm=d._LogicalXor=function(){return(vm=d._LogicalXor=d.asm.LogicalXor).apply(null,arguments)},wm=d._Max=function(){return(wm=d._Max=d.asm.Max).apply(null,arguments)},km=d._MaxPool=function(){return(km=d._MaxPool=d.asm.MaxPool).apply(null,arguments)},Xp=d._Maximum=function(){return(Xp=d._Maximum=d.asm.Maximum).apply(null,arguments)},Kp=d._Mean=function(){return(Kp=d._Mean=d.asm.Mean).apply(null,arguments)},Lu=d._Min=function(){return(Lu=d._Min=d.asm.Min).apply(null,arguments)},Im=d._Minimum=function(){return(Im=d._Minimum=d.asm.Minimum).apply(null,arguments)},Sm=d._MirrorPad=function(){return(Sm=d._MirrorPad=d.asm.MirrorPad).apply(null,arguments)},jo=d._Multiply=function(){return(jo=d._Multiply=d.asm.Multiply).apply(null,arguments)},Zp=d._Neg=function(){return(Zp=d._Neg=d.asm.Neg).apply(null,arguments)},qo=d._NonMaxSuppressionV3=function(){return(qo=d._NonMaxSuppressionV3=d.asm.NonMaxSuppressionV3).apply(null,arguments)},Xo=d._NonMaxSuppressionV4=function(){return(Xo=d._NonMaxSuppressionV4=d.asm.NonMaxSuppressionV4).apply(null,arguments)},Tm=d._NonMaxSuppressionV5=function(){return(Tm=d._NonMaxSuppressionV5=d.asm.NonMaxSuppressionV5).apply(null,arguments)},X=d._NotEqual=function(){return(X=d._NotEqual=d.asm.NotEqual).apply(null,arguments)},ie=d._OneHot=function(){return(ie=d._OneHot=d.asm.OneHot).apply(null,arguments)},ke=d._PadV2=function(){return(ke=d._PadV2=d.asm.PadV2).apply(null,arguments)},Ye=d._Pow=function(){return(Ye=d._Pow=d.asm.Pow).apply(null,arguments)},yt=d._Prelu=function(){return(yt=d._Prelu=d.asm.Prelu).apply(null,arguments)},bt=d._Prod=function(){return(bt=d._Prod=d.asm.Prod).apply(null,arguments)},Ze=d._RealDiv=function(){return(Ze=d._RealDiv=d.asm.RealDiv).apply(null,arguments)},qe=d._Reciprocal=function(){return(qe=d._Reciprocal=d.asm.Reciprocal).apply(null,arguments)},Ot=d._Relu=function(){return(Ot=d._Relu=d.asm.Relu).apply(null,arguments)},ln=d._Relu6=function(){return(ln=d._Relu6=d.asm.Relu6).apply(null,arguments)},pr=d._ResizeBilinear=function(){return(pr=d._ResizeBilinear=d.asm.ResizeBilinear).apply(null,arguments)},Yp=d._ResizeNearestNeighbor=function(){return(Yp=d._ResizeNearestNeighbor=d.asm.ResizeNearestNeighbor).apply(null,arguments)},Bu=d._Reverse=function(){return(Bu=d._Reverse=d.asm.Reverse).apply(null,arguments)},Cm=d._RotateWithOffset=function(){return(Cm=d._RotateWithOffset=d.asm.RotateWithOffset).apply(null,arguments)},Fa=d._Round=function(){return(Fa=d._Round=d.asm.Round).apply(null,arguments)},Fr=d._Rsqrt=function(){return(Fr=d._Rsqrt=d.asm.Rsqrt).apply(null,arguments)},Jp=d._ScatterNd=function(){return(Jp=d._ScatterNd=d.asm.ScatterNd).apply(null,arguments)},Jk=d._SelectV2=function(){return(Jk=d._SelectV2=d.asm.SelectV2).apply(null,arguments)},Qk=d._Sigmoid=function(){return(Qk=d._Sigmoid=d.asm.Sigmoid).apply(null,arguments)},eI=d._Sin=function(){return(eI=d._Sin=d.asm.Sin).apply(null,arguments)},tI=d._Softmax=function(){return(tI=d._Softmax=d.asm.Softmax).apply(null,arguments)},aI=d._SparseFillEmptyRows=function(){return(aI=d._SparseFillEmptyRows=d.asm.SparseFillEmptyRows).apply(null,arguments)},nI=d._SparseReshape=function(){return(nI=d._SparseReshape=d.asm.SparseReshape).apply(null,arguments)},rI=d._SparseSegmentReduction=function(){return(rI=d._SparseSegmentReduction=d.asm.SparseSegmentReduction).apply(null,arguments)},sI=d._Sqrt=function(){return(sI=d._Sqrt=d.asm.Sqrt).apply(null,arguments)},iI=d._Square=function(){return(iI=d._Square=d.asm.Square).apply(null,arguments)},oI=d._SquaredDifference=function(){return(oI=d._SquaredDifference=d.asm.SquaredDifference).apply(null,arguments)},lI=d._Step=function(){return(lI=d._Step=d.asm.Step).apply(null,arguments)},uI=d._StridedSlice=function(){return(uI=d._StridedSlice=d.asm.StridedSlice).apply(null,arguments)},dI=d._Sub=function(){return(dI=d._Sub=d.asm.Sub).apply(null,arguments)},pI=d._Sum=function(){return(pI=d._Sum=d.asm.Sum).apply(null,arguments)},cI=d._Tan=function(){return(cI=d._Tan=d.asm.Tan).apply(null,arguments)},hI=d._Tanh=function(){return(hI=d._Tanh=d.asm.Tanh).apply(null,arguments)},fI=d._Tile=function(){return(fI=d._Tile=d.asm.Tile).apply(null,arguments)},mI=d._TopK=function(){return(mI=d._TopK=d.asm.TopK).apply(null,arguments)},gI=d._Transform=function(){return(gI=d._Transform=d.asm.Transform).apply(null,arguments)},xI=d._Transpose=function(){return(xI=d._Transpose=d.asm.Transpose).apply(null,arguments)},AI=d.__FusedMatMul=function(){return(AI=d.__FusedMatMul=d.asm._FusedMatMul).apply(null,arguments)},yI=d._malloc=function(){return(yI=d._malloc=d.asm.malloc).apply(null,arguments)},bI=d._free=function(){return(bI=d._free=d.asm.free).apply(null,arguments)},vI=d.__emscripten_tls_init=function(){return(vI=d.__emscripten_tls_init=d.asm._emscripten_tls_init).apply(null,arguments)},Qp=d._pthread_self=function(){return(Qp=d._pthread_self=d.asm.pthread_self).apply(null,arguments)},wI=d.___errno_location=function(){return(wI=d.___errno_location=d.asm.__errno_location).apply(null,arguments)},N5=d.__emscripten_thread_init=function(){return(N5=d.__emscripten_thread_init=d.asm._emscripten_thread_init).apply(null,arguments)},kI=d.__emscripten_thread_crashed=function(){return(kI=d.__emscripten_thread_crashed=d.asm._emscripten_thread_crashed).apply(null,arguments)},II=d._emscripten_main_thread_process_queued_calls=function(){return(II=d._emscripten_main_thread_process_queued_calls=d.asm.emscripten_main_thread_process_queued_calls).apply(null,arguments)},SI=d._emscripten_main_browser_thread_id=function(){return(SI=d._emscripten_main_browser_thread_id=d.asm.emscripten_main_browser_thread_id).apply(null,arguments)},E5=d._emscripten_run_in_main_runtime_thread_js=function(){return(E5=d._emscripten_run_in_main_runtime_thread_js=d.asm.emscripten_run_in_main_runtime_thread_js).apply(null,arguments)},TI=d._emscripten_dispatch_to_thread_=function(){return(TI=d._emscripten_dispatch_to_thread_=d.asm.emscripten_dispatch_to_thread_).apply(null,arguments)},R5=d.__emscripten_proxy_execute_task_queue=function(){return(R5=d.__emscripten_proxy_execute_task_queue=d.asm._emscripten_proxy_execute_task_queue).apply(null,arguments)},Nm=d.__emscripten_thread_free_data=function(){return(Nm=d.__emscripten_thread_free_data=d.asm._emscripten_thread_free_data).apply(null,arguments)},M5=d.__emscripten_thread_exit=function(){return(M5=d.__emscripten_thread_exit=d.asm._emscripten_thread_exit).apply(null,arguments)},$5=d._emscripten_stack_set_limits=function(){return($5=d._emscripten_stack_set_limits=d.asm.emscripten_stack_set_limits).apply(null,arguments)},Em=d.stackSave=function(){return(Em=d.stackSave=d.asm.stackSave).apply(null,arguments)},ec=d.stackRestore=function(){return(ec=d.stackRestore=d.asm.stackRestore).apply(null,arguments)},tc=d.stackAlloc=function(){return(tc=d.stackAlloc=d.asm.stackAlloc).apply(null,arguments)},CI=d.dynCall_iijjiiii=function(){return(CI=d.dynCall_iijjiiii=d.asm.dynCall_iijjiiii).apply(null,arguments)},NI=d.dynCall_jiji=function(){return(NI=d.dynCall_jiji=d.asm.dynCall_jiji).apply(null,arguments)};d.keepRuntimeAlive=bn,d.wasmMemory=oe,d.cwrap=Tf,d.ExitStatus=Ss,d.PThread=Le;var ac;dr=function F(){ac||_5(),ac||(dr=F)};function _5(F){if(F=F||x,_r>0)return;if(C){h(d),Xt(),postMessage({cmd:\"loaded\"});return}if(Wo(),_r>0)return;function q(){ac||(ac=!0,d.calledRun=!0,!we&&(Xt(),h(d),d.onRuntimeInitialized&&d.onRuntimeInitialized(),_p()))}d.setStatus?(d.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){d.setStatus(\"\")},1),q()},1)):q()}if(d.preInit)for(typeof d.preInit==\"function\"&&(d.preInit=[d.preInit]);d.preInit.length>0;)d.preInit.pop()();_5();var nc;m&&(nc={uncaughtException:process.listeners(\"uncaughtException\").filter(function(F){return!m.uncaughtException.indexOf(F)>-1}),unhandledRejection:process.listeners(\"unhandledRejection\").filter(function(F){return!m.unhandledRejection.indexOf(F)>-1})});var rc;if(typeof WasmBackendModule!=\"undefined\")rc=WasmBackendModule;else if(typeof r!=\"undefined\")rc=r;else throw new Error(\"Could not find wasm module in post.js\");if(nc){var EI=rc._dispose;rc._dispose=function(){EI(),nc.uncaughtException.forEach(function(F){process.removeListener(\"uncaughtException\",F)}),nc.unhandledRejection.forEach(function(F){process.removeListener(\"unhandledRejection\",F)})}}return r.ready}})();typeof e==\"object\"&&typeof t==\"object\"?t.exports=a:typeof define==\"function\"&&define.amd?define([],function(){return a}):typeof e==\"object\"&&(e.WasmBackendModuleThreadedSimd=a)}),rS=qt((e,t)=>{t.exports.wasmWorkerContents=`\"use strict\";var Module={};var ENVIRONMENT_IS_NODE=typeof process==\"object\"&&typeof process.versions==\"object\"&&typeof process.versions.node==\"string\";if(ENVIRONMENT_IS_NODE){var nodeWorkerThreads=require(\"worker_threads\");var parentPort=nodeWorkerThreads.parentPort;parentPort.on(\"message\",data=>onmessage({data:data}));var fs=require(\"fs\");Object.assign(global,{self:global,require:require,Module:Module,location:{href:__filename},Worker:nodeWorkerThreads.Worker,importScripts:function(f){(0,eval)(fs.readFileSync(f,\"utf8\"))},postMessage:function(msg){parentPort.postMessage(msg)},performance:global.performance||{now:function(){return Date.now()}}})}var initializedJS=false;var pendingNotifiedProxyingQueues=[];function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(\" \");if(ENVIRONMENT_IS_NODE){fs.writeSync(2,text+\"\n\");return}console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(\" \");postMessage({cmd:\"alert\",text:text,threadId:Module[\"_pthread_self\"]()})}var err=threadPrintErr;self.alert=threadAlert;Module[\"instantiateWasm\"]=(info,receiveInstance)=>{var instance=new WebAssembly.Instance(Module[\"wasmModule\"],info);receiveInstance(instance);Module[\"wasmModule\"]=null;return instance.exports};self.onunhandledrejection=e=>{throw e.reason??e};self.onmessage=e=>{try{if(e.data.cmd===\"load\"){Module[\"wasmModule\"]=e.data.wasmModule;Module[\"wasmMemory\"]=e.data.wasmMemory;Module[\"buffer\"]=Module[\"wasmMemory\"].buffer;Module[\"ENVIRONMENT_IS_PTHREAD\"]=true;if(typeof e.data.urlOrBlob==\"string\"){importScripts(e.data.urlOrBlob)}else{var objectUrl=URL.createObjectURL(e.data.urlOrBlob);importScripts(objectUrl);URL.revokeObjectURL(objectUrl)}WasmBackendModuleThreadedSimd(Module).then(function(instance){Module=instance})}else if(e.data.cmd===\"run\"){Module[\"__performance_now_clock_drift\"]=performance.now()-e.data.time;Module[\"__emscripten_thread_init\"](e.data.pthread_ptr,0,0,1);Module[\"establishStackSpace\"]();Module[\"PThread\"].receiveObjectTransfer(e.data);Module[\"PThread\"].threadInitTLS();if(!initializedJS){pendingNotifiedProxyingQueues.forEach(queue=>{Module[\"executeNotifiedProxyingQueue\"](queue)});pendingNotifiedProxyingQueues=[];initializedJS=true}try{Module[\"invokeEntryPoint\"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!=\"unwind\"){if(ex instanceof Module[\"ExitStatus\"]){if(Module[\"keepRuntimeAlive\"]()){}else{Module[\"__emscripten_thread_exit\"](ex.status)}}else{throw ex}}}}else if(e.data.cmd===\"cancel\"){if(Module[\"_pthread_self\"]()){Module[\"__emscripten_thread_exit\"](-1)}}else if(e.data.target===\"setimmediate\"){}else if(e.data.cmd===\"processProxyingQueue\"){if(initializedJS){Module[\"executeNotifiedProxyingQueue\"](e.data.queue)}else{pendingNotifiedProxyingQueues.push(e.data.queue)}}else if(e.data.cmd){err(\"worker.js received unknown command \"+e.data.cmd);err(e.data)}}catch(ex){if(Module[\"__emscripten_thread_crashed\"]){Module[\"__emscripten_thread_crashed\"]()}throw ex}};`}),sS=qt((e,t)=>{var a=(()=>{var n=typeof document!=\"undefined\"&&document.currentScript?document.currentScript.src:void 0;return typeof __filename!=\"undefined\"&&(n=n||__filename),function(r){r=r||{};var s=typeof r!=\"undefined\"?r:{},i,o;s.ready=new Promise(function(X,ie){i=X,o=ie});var l;typeof process!=\"undefined\"&&process.listeners&&(l={uncaughtException:process.listeners(\"uncaughtException\"),unhandledRejection:process.listeners(\"unhandledRejection\")});var u=Object.assign({},s),p=[],c=\"./this.program\",d=(X,ie)=>{throw ie},h=typeof window==\"object\",f=typeof importScripts==\"function\",m=typeof process==\"object\"&&typeof process.versions==\"object\"&&typeof process.versions.node==\"string\",g=\"\";function x(X){return s.locateFile?s.locateFile(X,g):g+X}var A,y,b,w;function S(X){X instanceof Vo||$(\"exiting due to exception: \"+X)}if(m){f?g=wc().dirname(g)+\"/\":g=__dirname+\"/\";var C,E;typeof aA==\"function\"&&(C=rA(),E=wc()),A=(X,ie)=>(X=E.normalize(X),C.readFileSync(X,ie?void 0:\"utf8\")),b=X=>{var ie=A(X,!0);return ie.buffer||(ie=new Uint8Array(ie)),ie},y=(X,ie,ke)=>{X=E.normalize(X),C.readFile(X,function(Ye,yt){Ye?ke(Ye):ie(yt.buffer)})},process.argv.length>1&&(c=process.argv[1].replace(/\\\\/g,\"/\")),p=process.argv.slice(2),process.on(\"uncaughtException\",function(X){if(!(X instanceof Vo))throw X}),process.on(\"unhandledRejection\",function(X){throw X}),d=(X,ie)=>{if(Va())throw process.exitCode=X,ie;S(ie),process.exit(X)},s.inspect=function(){return\"[Emscripten Module object]\"}}else(h||f)&&(f?g=self.location.href:typeof document!=\"undefined\"&&document.currentScript&&(g=document.currentScript.src),n&&(g=n),g.indexOf(\"blob:\")!==0?g=g.substr(0,g.replace(/[?#].*/,\"\").lastIndexOf(\"/\")+1):g=\"\",A=X=>{var ie=new XMLHttpRequest;return ie.open(\"GET\",X,!1),ie.send(null),ie.responseText},f&&(b=X=>{var ie=new XMLHttpRequest;return ie.open(\"GET\",X,!1),ie.responseType=\"arraybuffer\",ie.send(null),new Uint8Array(ie.response)}),y=(X,ie,ke)=>{var Ye=new XMLHttpRequest;Ye.open(\"GET\",X,!0),Ye.responseType=\"arraybuffer\",Ye.onload=()=>{if(Ye.status==200||Ye.status==0&&Ye.response){ie(Ye.response);return}ke()},Ye.onerror=ke,Ye.send(null)},w=X=>document.title=X);var _=s.print||console.log.bind(console),$=s.printErr||console.warn.bind(console);Object.assign(s,u),u=null,s.arguments&&(p=s.arguments),s.thisProgram&&(c=s.thisProgram),s.quit&&(d=s.quit);var M=4,I;s.wasmBinary&&(I=s.wasmBinary);var N=s.noExitRuntime||!0;typeof WebAssembly!=\"object\"&&Un(\"no native wasm support detected\");var O,L=!1,B;function G(X,ie){X||Un(ie)}var j=typeof TextDecoder!=\"undefined\"?new TextDecoder(\"utf8\"):void 0;function U(X,ie,ke){for(var Ye=ie+ke,yt=ie;X[yt]&&!(yt>=Ye);)++yt;if(yt-ie>16&&X.buffer&&j)return j.decode(X.subarray(ie,yt));for(var bt=\"\";ie<yt;){var Ze=X[ie++];if(!(Ze&128)){bt+=String.fromCharCode(Ze);continue}var qe=X[ie++]&63;if((Ze&224)==192){bt+=String.fromCharCode((Ze&31)<<6|qe);continue}var Ot=X[ie++]&63;if((Ze&240)==224?Ze=(Ze&15)<<12|qe<<6|Ot:Ze=(Ze&7)<<18|qe<<12|Ot<<6|X[ie++]&63,Ze<65536)bt+=String.fromCharCode(Ze);else{var ln=Ze-65536;bt+=String.fromCharCode(55296|ln>>10,56320|ln&1023)}}return bt}function H(X,ie){return X?U(ee,X,ie):\"\"}function V(X,ie,ke,Ye){if(!(Ye>0))return 0;for(var yt=ke,bt=ke+Ye-1,Ze=0;Ze<X.length;++Ze){var qe=X.charCodeAt(Ze);if(qe>=55296&&qe<=57343){var Ot=X.charCodeAt(++Ze);qe=65536+((qe&1023)<<10)|Ot&1023}if(qe<=127){if(ke>=bt)break;ie[ke++]=qe}else if(qe<=2047){if(ke+1>=bt)break;ie[ke++]=192|qe>>6,ie[ke++]=128|qe&63}else if(qe<=65535){if(ke+2>=bt)break;ie[ke++]=224|qe>>12,ie[ke++]=128|qe>>6&63,ie[ke++]=128|qe&63}else{if(ke+3>=bt)break;ie[ke++]=240|qe>>18,ie[ke++]=128|qe>>12&63,ie[ke++]=128|qe>>6&63,ie[ke++]=128|qe&63}}return ie[ke]=0,ke-yt}function Q(X,ie,ke){return V(X,ee,ie,ke)}var Z,re,ee,he,oe,Ae,we,Re,Ge;function Ke(X){Z=X,s.HEAP8=re=new Int8Array(X),s.HEAP16=he=new Int16Array(X),s.HEAP32=Ae=new Int32Array(X),s.HEAPU8=ee=new Uint8Array(X),s.HEAPU16=oe=new Uint16Array(X),s.HEAPU32=we=new Uint32Array(X),s.HEAPF32=Re=new Float32Array(X),s.HEAPF64=Ge=new Float64Array(X)}var nt=s.INITIAL_MEMORY||16777216,ut,et=[],rt=[],je=[],ht=!1;function Va(){return N}function Ft(){if(s.preRun)for(typeof s.preRun==\"function\"&&(s.preRun=[s.preRun]);s.preRun.length;)$a(s.preRun.shift());dr(et)}function sn(){ht=!0,dr(rt)}function aa(){if(s.postRun)for(typeof s.postRun==\"function\"&&(s.postRun=[s.postRun]);s.postRun.length;)_a(s.postRun.shift());dr(je)}function $a(X){et.unshift(X)}function on(X){rt.unshift(X)}function _a(X){je.unshift(X)}var dt=0,Pa=null,Ua=null;function ur(X){dt++,s.monitorRunDependencies&&s.monitorRunDependencies(dt)}function Bo(X){if(dt--,s.monitorRunDependencies&&s.monitorRunDependencies(dt),dt==0&&(Pa!==null&&(clearInterval(Pa),Pa=null),Ua)){var ie=Ua;Ua=null,ie()}}function Un(X){s.onAbort&&s.onAbort(X),X=\"Aborted(\"+X+\")\",$(X),L=!0,B=1,X+=\". Build with -sASSERTIONS for more info.\";var ie=new WebAssembly.RuntimeError(X);throw o(ie),ie}var $u=\"data:application/octet-stream;base64,\";function bn(X){return X.startsWith($u)}function Wo(X){return X.startsWith(\"file://\")}var Xt;Xt=\"tfjs-backend-wasm.wasm\",bn(Xt)||(Xt=x(Xt));function _p(X){try{if(X==Xt&&I)return new Uint8Array(I);if(b)return b(X);throw\"both async and sync fetching of the wasm failed\"}catch(ie){Un(ie)}}function U0(){if(!I&&(h||f)){if(typeof fetch==\"function\"&&!Wo(Xt))return fetch(Xt,{credentials:\"same-origin\"}).then(function(X){if(!X.ok)throw\"failed to load wasm binary file at '\"+Xt+\"'\";return X.arrayBuffer()}).catch(function(){return _p(Xt)});if(y)return new Promise(function(X,ie){y(Xt,function(ke){X(new Uint8Array(ke))},ie)})}return Promise.resolve().then(function(){return _p(Xt)})}function G0(){var X={env:Fu,wasi_snapshot_preview1:Fu};function ie(Ze,qe){var Ot=Ze.exports;s.asm=Ot,O=s.asm.memory,Ke(O.buffer),ut=s.asm.__indirect_function_table,on(s.asm.__wasm_call_ctors),Bo(\"wasm-instantiate\")}ur(\"wasm-instantiate\");function ke(Ze){ie(Ze.instance)}function Ye(Ze){return U0().then(function(qe){return WebAssembly.instantiate(qe,X)}).then(function(qe){return qe}).then(Ze,function(qe){$(\"failed to asynchronously prepare wasm: \"+qe),Un(qe)})}function yt(){return!I&&typeof WebAssembly.instantiateStreaming==\"function\"&&!bn(Xt)&&!Wo(Xt)&&!m&&typeof fetch==\"function\"?fetch(Xt,{credentials:\"same-origin\"}).then(function(Ze){var qe=WebAssembly.instantiateStreaming(Ze,X);return qe.then(ke,function(Ot){return $(\"wasm streaming compile failed: \"+Ot),$(\"falling back to ArrayBuffer instantiation\"),Ye(ke)})}):Ye(ke)}if(s.instantiateWasm)try{var bt=s.instantiateWasm(X,ie);return bt}catch(Ze){$(\"Module.instantiateWasm callback failed with error: \"+Ze),o(Ze)}return yt().catch(o),{}}var y5,_r;function Vo(X){this.name=\"ExitStatus\",this.message=\"Program terminated with exit(\"+X+\")\",this.status=X}function dr(X){for(;X.length>0;)X.shift()(s)}function b5(X){return X}function v5(X){var ie=/\\b_Z[\\w\\d_]+/g;return X.replace(ie,function(ke){var Ye=ke;return ke===Ye?ke:Ye+\" [\"+ke+\"]\"})}function Uo(){var X=new Error;if(!X.stack){try{throw new Error}catch(ie){X=ie}if(!X.stack)return\"(no stack trace available)\"}return X.stack.toString()}function H0(X,ie){re.set(X,ie)}function Pp(){Un(\"\")}function _u(){return 2147483648}function xa(){return _u()}function Fp(X,ie,ke){ee.copyWithin(X,ie,ie+ke)}function j0(X){try{return O.grow(X-Z.byteLength+65535>>>16),Ke(O.buffer),1}catch(ie){}}function q0(X){var ie=ee.length;X=X>>>0;var ke=_u();if(X>ke)return!1;let Ye=(Ot,ln)=>Ot+(ln-Ot%ln)%ln;for(var yt=1;yt<=4;yt*=2){var bt=ie*(1+.2/yt);bt=Math.min(bt,X+100663296);var Ze=Math.min(ke,Ye(Math.max(X,bt),65536)),qe=j0(Ze);if(qe)return!0}return!1}var X0={varargs:void 0,get:function(){X0.varargs+=4;var X=Ae[X0.varargs-4>>2];return X},getStr:function(X){var ie=H(X);return ie}};function w5(X){return 52}function K0(X,ie,ke,Ye,yt){return 70}var Ss=[null,[],[]];function Z0(X,ie){var ke=Ss[X];ie===0||ie===10?((X===1?_:$)(U(ke,0)),ke.length=0):ke.push(ie)}function Y0(X,ie,ke,Ye){for(var yt=0,bt=0;bt<ke;bt++){var Ze=we[ie>>2],qe=we[ie+4>>2];ie+=8;for(var Ot=0;Ot<qe;Ot++)Z0(X,ee[Ze+Ot]);yt+=qe}return we[Ye>>2]=yt,0}function Pu(X){var ie=s[\"_\"+X];return ie}function Op(X,ie,ke,Ye,yt){var bt={string:Fa=>{var Fr=0;if(Fa!=null&&Fa!==0){var Jp=(Fa.length<<2)+1;Fr=Lu(Jp),Q(Fa,Fr,Jp)}return Fr},array:Fa=>{var Fr=Lu(Fa.length);return H0(Fa,Fr),Fr}};function Ze(Fa){return ie===\"string\"?H(Fa):ie===\"boolean\"?Boolean(Fa):Fa}var qe=Pu(X),Ot=[],ln=0;if(Ye)for(var pr=0;pr<Ye.length;pr++){var Yp=bt[ke[pr]];Yp?(ln===0&&(ln=Xp()),Ot[pr]=Yp(Ye[pr])):Ot[pr]=Ye[pr]}var Bu=qe.apply(null,Ot);function Cm(Fa){return ln!==0&&Kp(ln),Ze(Fa)}return Bu=Cm(Bu),Bu}function Dp(X,ie,ke,Ye){ke=ke||[];var yt=ke.every(Ze=>Ze===\"number\"||Ze===\"boolean\"),bt=ie!==\"string\";return bt&&yt&&!Ye?Pu(X):function(){return Op(X,ie,ke,arguments,Ye)}}var Fu={abort:Pp,emscripten_get_heap_max:xa,emscripten_memcpy_big:Fp,emscripten_resize_heap:q0,fd_close:w5,fd_seek:K0,fd_write:Y0},k5=G0(),zp=s.___wasm_call_ctors=function(){return(zp=s.___wasm_call_ctors=s.asm.__wasm_call_ctors).apply(null,arguments)},J0=s._init=function(){return(J0=s._init=s.asm.init).apply(null,arguments)},Le=s._init_with_threads_count=function(){return(Le=s._init_with_threads_count=s.asm.init_with_threads_count).apply(null,arguments)},Ou=s._get_threads_count=function(){return(Ou=s._get_threads_count=s.asm.get_threads_count).apply(null,arguments)},Q0=s._register_tensor=function(){return(Q0=s._register_tensor=s.asm.register_tensor).apply(null,arguments)},I5=s._dispose_data=function(){return(I5=s._dispose_data=s.asm.dispose_data).apply(null,arguments)},S5=s._dispose=function(){return(S5=s._dispose=s.asm.dispose).apply(null,arguments)},ef=s._Abs=function(){return(ef=s._Abs=s.asm.Abs).apply(null,arguments)},Lp=s._Add=function(){return(Lp=s._Add=s.asm.Add).apply(null,arguments)},Go=s._AddN=function(){return(Go=s._AddN=s.asm.AddN).apply(null,arguments)},tf=s._All=function(){return(tf=s._All=s.asm.All).apply(null,arguments)},af=s._Any=function(){return(af=s._Any=s.asm.Any).apply(null,arguments)},T5=s._ArgMax=function(){return(T5=s._ArgMax=s.asm.ArgMax).apply(null,arguments)},nf=s._AvgPool=function(){return(nf=s._AvgPool=s.asm.AvgPool).apply(null,arguments)},rf=s._BatchMatMul=function(){return(rf=s._BatchMatMul=s.asm.BatchMatMul).apply(null,arguments)},sf=s._Ceil=function(){return(sf=s._Ceil=s.asm.Ceil).apply(null,arguments)},of=s._ClipByValue=function(){return(of=s._ClipByValue=s.asm.ClipByValue).apply(null,arguments)},Bp=s._Conv2D=function(){return(Bp=s._Conv2D=s.asm.Conv2D).apply(null,arguments)},Wp=s._Conv2DBackpropInput=function(){return(Wp=s._Conv2DBackpropInput=s.asm.Conv2DBackpropInput).apply(null,arguments)},lf=s._Cos=function(){return(lf=s._Cos=s.asm.Cos).apply(null,arguments)},uf=s._Cosh=function(){return(uf=s._Cosh=s.asm.Cosh).apply(null,arguments)},df=s._CropAndResize=function(){return(df=s._CropAndResize=s.asm.CropAndResize).apply(null,arguments)},Du=s._Cumprod=function(){return(Du=s._Cumprod=s.asm.Cumprod).apply(null,arguments)},pf=s._Cumsum=function(){return(pf=s._Cumsum=s.asm.Cumsum).apply(null,arguments)},cf=s._DepthToSpace=function(){return(cf=s._DepthToSpace=s.asm.DepthToSpace).apply(null,arguments)},hf=s._DepthwiseConv2dNative=function(){return(hf=s._DepthwiseConv2dNative=s.asm.DepthwiseConv2dNative).apply(null,arguments)},Ts=s._Elu=function(){return(Ts=s._Elu=s.asm.Elu).apply(null,arguments)},ff=s._Equal=function(){return(ff=s._Equal=s.asm.Equal).apply(null,arguments)},mf=s._Exp=function(){return(mf=s._Exp=s.asm.Exp).apply(null,arguments)},Vp=s._FlipLeftRight=function(){return(Vp=s._FlipLeftRight=s.asm.FlipLeftRight).apply(null,arguments)},gf=s._Floor=function(){return(gf=s._Floor=s.asm.Floor).apply(null,arguments)},Ho=s._FloorDiv=function(){return(Ho=s._FloorDiv=s.asm.FloorDiv).apply(null,arguments)},xf=s._FusedBatchNorm=function(){return(xf=s._FusedBatchNorm=s.asm.FusedBatchNorm).apply(null,arguments)},Af=s._FusedConv2D=function(){return(Af=s._FusedConv2D=s.asm.FusedConv2D).apply(null,arguments)},Pr=s._FusedDepthwiseConv2D=function(){return(Pr=s._FusedDepthwiseConv2D=s.asm.FusedDepthwiseConv2D).apply(null,arguments)},zu=s._Gather=function(){return(zu=s._Gather=s.asm.Gather).apply(null,arguments)},yf=s._GatherNd=function(){return(yf=s._GatherNd=s.asm.GatherNd).apply(null,arguments)},bf=s._Greater=function(){return(bf=s._Greater=s.asm.Greater).apply(null,arguments)},vf=s._GreaterEqual=function(){return(vf=s._GreaterEqual=s.asm.GreaterEqual).apply(null,arguments)},wf=s._IsNan=function(){return(wf=s._IsNan=s.asm.IsNan).apply(null,arguments)},Up=s._LeakyRelu=function(){return(Up=s._LeakyRelu=s.asm.LeakyRelu).apply(null,arguments)},Gp=s._Less=function(){return(Gp=s._Less=s.asm.Less).apply(null,arguments)},kf=s._LessEqual=function(){return(kf=s._LessEqual=s.asm.LessEqual).apply(null,arguments)},If=s._Log=function(){return(If=s._Log=s.asm.Log).apply(null,arguments)},Hp=s._LogicalAnd=function(){return(Hp=s._LogicalAnd=s.asm.LogicalAnd).apply(null,arguments)},jp=s._LogicalNot=function(){return(jp=s._LogicalNot=s.asm.LogicalNot).apply(null,arguments)},Sf=s._LogicalOr=function(){return(Sf=s._LogicalOr=s.asm.LogicalOr).apply(null,arguments)},Tf=s._LogicalXor=function(){return(Tf=s._LogicalXor=s.asm.LogicalXor).apply(null,arguments)},Cf=s._Max=function(){return(Cf=s._Max=s.asm.Max).apply(null,arguments)},qp=s._MaxPool=function(){return(qp=s._MaxPool=s.asm.MaxPool).apply(null,arguments)},C5=s._Maximum=function(){return(C5=s._Maximum=s.asm.Maximum).apply(null,arguments)},Nf=s._Mean=function(){return(Nf=s._Mean=s.asm.Mean).apply(null,arguments)},Ef=s._Min=function(){return(Ef=s._Min=s.asm.Min).apply(null,arguments)},Rf=s._Minimum=function(){return(Rf=s._Minimum=s.asm.Minimum).apply(null,arguments)},Mf=s._MirrorPad=function(){return(Mf=s._MirrorPad=s.asm.MirrorPad).apply(null,arguments)},$f=s._Multiply=function(){return($f=s._Multiply=s.asm.Multiply).apply(null,arguments)},_f=s._Neg=function(){return(_f=s._Neg=s.asm.Neg).apply(null,arguments)},Pf=s._NonMaxSuppressionV3=function(){return(Pf=s._NonMaxSuppressionV3=s.asm.NonMaxSuppressionV3).apply(null,arguments)},Ff=s._NonMaxSuppressionV4=function(){return(Ff=s._NonMaxSuppressionV4=s.asm.NonMaxSuppressionV4).apply(null,arguments)},Of=s._NonMaxSuppressionV5=function(){return(Of=s._NonMaxSuppressionV5=s.asm.NonMaxSuppressionV5).apply(null,arguments)},Df=s._NotEqual=function(){return(Df=s._NotEqual=s.asm.NotEqual).apply(null,arguments)},zf=s._OneHot=function(){return(zf=s._OneHot=s.asm.OneHot).apply(null,arguments)},Lf=s._PadV2=function(){return(Lf=s._PadV2=s.asm.PadV2).apply(null,arguments)},Bf=s._Pow=function(){return(Bf=s._Pow=s.asm.Pow).apply(null,arguments)},Wf=s._Prelu=function(){return(Wf=s._Prelu=s.asm.Prelu).apply(null,arguments)},Vf=s._Prod=function(){return(Vf=s._Prod=s.asm.Prod).apply(null,arguments)},Uf=s._RealDiv=function(){return(Uf=s._RealDiv=s.asm.RealDiv).apply(null,arguments)},Gf=s._Reciprocal=function(){return(Gf=s._Reciprocal=s.asm.Reciprocal).apply(null,arguments)},Hf=s._Relu=function(){return(Hf=s._Relu=s.asm.Relu).apply(null,arguments)},jf=s._Relu6=function(){return(jf=s._Relu6=s.asm.Relu6).apply(null,arguments)},qf=s._ResizeBilinear=function(){return(qf=s._ResizeBilinear=s.asm.ResizeBilinear).apply(null,arguments)},Xf=s._ResizeNearestNeighbor=function(){return(Xf=s._ResizeNearestNeighbor=s.asm.ResizeNearestNeighbor).apply(null,arguments)},Kf=s._Reverse=function(){return(Kf=s._Reverse=s.asm.Reverse).apply(null,arguments)},Zf=s._RotateWithOffset=function(){return(Zf=s._RotateWithOffset=s.asm.RotateWithOffset).apply(null,arguments)},Yf=s._Round=function(){return(Yf=s._Round=s.asm.Round).apply(null,arguments)},Jf=s._Rsqrt=function(){return(Jf=s._Rsqrt=s.asm.Rsqrt).apply(null,arguments)},Qf=s._ScatterNd=function(){return(Qf=s._ScatterNd=s.asm.ScatterNd).apply(null,arguments)},em=s._SelectV2=function(){return(em=s._SelectV2=s.asm.SelectV2).apply(null,arguments)},tm=s._Sigmoid=function(){return(tm=s._Sigmoid=s.asm.Sigmoid).apply(null,arguments)},am=s._Sin=function(){return(am=s._Sin=s.asm.Sin).apply(null,arguments)},nm=s._Softmax=function(){return(nm=s._Softmax=s.asm.Softmax).apply(null,arguments)},rm=s._SparseFillEmptyRows=function(){return(rm=s._SparseFillEmptyRows=s.asm.SparseFillEmptyRows).apply(null,arguments)},sm=s._SparseReshape=function(){return(sm=s._SparseReshape=s.asm.SparseReshape).apply(null,arguments)},im=s._SparseSegmentReduction=function(){return(im=s._SparseSegmentReduction=s.asm.SparseSegmentReduction).apply(null,arguments)},om=s._Sqrt=function(){return(om=s._Sqrt=s.asm.Sqrt).apply(null,arguments)},lm=s._Square=function(){return(lm=s._Square=s.asm.Square).apply(null,arguments)},um=s._SquaredDifference=function(){return(um=s._SquaredDifference=s.asm.SquaredDifference).apply(null,arguments)},dm=s._Step=function(){return(dm=s._Step=s.asm.Step).apply(null,arguments)},pm=s._StridedSlice=function(){return(pm=s._StridedSlice=s.asm.StridedSlice).apply(null,arguments)},cm=s._Sub=function(){return(cm=s._Sub=s.asm.Sub).apply(null,arguments)},hm=s._Sum=function(){return(hm=s._Sum=s.asm.Sum).apply(null,arguments)},fm=s._Tan=function(){return(fm=s._Tan=s.asm.Tan).apply(null,arguments)},mm=s._Tanh=function(){return(mm=s._Tanh=s.asm.Tanh).apply(null,arguments)},gm=s._Tile=function(){return(gm=s._Tile=s.asm.Tile).apply(null,arguments)},xm=s._TopK=function(){return(xm=s._TopK=s.asm.TopK).apply(null,arguments)},Am=s._Transform=function(){return(Am=s._Transform=s.asm.Transform).apply(null,arguments)},ym=s._Transpose=function(){return(ym=s._Transpose=s.asm.Transpose).apply(null,arguments)},bm=s.__FusedMatMul=function(){return(bm=s.__FusedMatMul=s.asm._FusedMatMul).apply(null,arguments)},vm=s._malloc=function(){return(vm=s._malloc=s.asm.malloc).apply(null,arguments)},wm=s._free=function(){return(wm=s._free=s.asm.free).apply(null,arguments)},km=s.___errno_location=function(){return(km=s.___errno_location=s.asm.__errno_location).apply(null,arguments)},Xp=s.stackSave=function(){return(Xp=s.stackSave=s.asm.stackSave).apply(null,arguments)},Kp=s.stackRestore=function(){return(Kp=s.stackRestore=s.asm.stackRestore).apply(null,arguments)},Lu=s.stackAlloc=function(){return(Lu=s.stackAlloc=s.asm.stackAlloc).apply(null,arguments)},Im=s.dynCall_iijjiiii=function(){return(Im=s.dynCall_iijjiiii=s.asm.dynCall_iijjiiii).apply(null,arguments)},Sm=s.dynCall_jiji=function(){return(Sm=s.dynCall_jiji=s.asm.dynCall_jiji).apply(null,arguments)};s.cwrap=Dp;var jo;Ua=function X(){jo||Zp(),jo||(Ua=X)};function Zp(X){if(X=X||p,dt>0||(Ft(),dt>0))return;function ie(){jo||(jo=!0,s.calledRun=!0,!L&&(sn(),i(s),s.onRuntimeInitialized&&s.onRuntimeInitialized(),aa()))}s.setStatus?(s.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){s.setStatus(\"\")},1),ie()},1)):ie()}if(s.preInit)for(typeof s.preInit==\"function\"&&(s.preInit=[s.preInit]);s.preInit.length>0;)s.preInit.pop()();Zp();var qo;l&&(qo={uncaughtException:process.listeners(\"uncaughtException\").filter(function(X){return!l.uncaughtException.indexOf(X)>-1}),unhandledRejection:process.listeners(\"unhandledRejection\").filter(function(X){return!l.unhandledRejection.indexOf(X)>-1})});var Xo;if(typeof r!=\"undefined\")Xo=r;else if(typeof WasmBackendModuleThreadedSimd!=\"undefined\")Xo=WasmBackendModuleThreadedSimd;else throw new Error(\"Could not find wasm module in post.js\");if(qo){var Tm=Xo._dispose;Xo._dispose=function(){Tm(),qo.uncaughtException.forEach(function(X){process.removeListener(\"uncaughtException\",X)}),qo.unhandledRejection.forEach(function(X){process.removeListener(\"unhandledRejection\",X)})}}return r.ready}})();typeof e==\"object\"&&typeof t==\"object\"?t.exports=a:typeof define==\"function\"&&define.amd?define([],function(){return a}):typeof e==\"object\"&&(e.WasmBackendModule=a)}),vd=class{constructor(e,t){this.backend=e,this.dataMover=t,this.data=new WeakMap,this.dataIdsCount=0}get(e){return this.data.has(e)||this.dataMover.moveData(this.backend,e),this.data.get(e)}set(e,t){this.dataIdsCount++,this.data.set(e,t)}has(e){return this.data.has(e)}delete(e){return this.dataIdsCount--,this.data.delete(e)}numDataIds(){return this.dataIdsCount}},bl=class{refCount(e){return Ha(\"refCount\")}incRef(e){return Ha(\"incRef\")}timerAvailable(){return!0}time(e){return Ha(\"time\")}read(e){return Ha(\"read\")}readSync(e){return Ha(\"readSync\")}readToGPU(e,t){return Ha(\"readToGPU\")}numDataIds(){return Ha(\"numDataIds\")}disposeData(e,t){return Ha(\"disposeData\")}write(e,t,a){return Ha(\"write\")}move(e,t,a,n,r){return Ha(\"move\")}createTensorFromTexture(e,t,a){return Ha(\"createTensorFromTexture\")}memory(){return Ha(\"memory\")}floatPrecision(){return Ha(\"floatPrecision\")}epsilon(){return this.floatPrecision()===32?1e-7:1e-4}dispose(){return Ha(\"dispose\")}};function Ha(e){throw new Error(`'${e}' not yet implemented or not found in the registry. This kernel may not be supported by the tfjs backend you have chosen`)}function sA(e){let t=e.length,a=0;for(;t>0;)a=Math.random()*t|0,t--,kc(e,t,a)}function iS(e,t){if(e.length!==t.length)throw new Error(`Array sizes must match to be shuffled together First array length was ${e.length}Second array length was ${t.length}`);let a=e.length,n=0;for(;a>0;)n=Math.random()*a|0,a--,kc(e,a,n),kc(t,a,n)}function nd(e,t,a){return Math.max(e,Math.min(t,a))}function oS(e){return e%2===0?e:e+1}function kc(e,t,a){let n=e[t];e[t]=e[a],e[a]=n}function lS(e){let t=0;for(let a=0;a<e.length;a++)t+=e[a];return t}function uS(e,t){let a=Math.random();return t*a+(1-a)*e}function dS(e,t){let a=0;for(let n=0;n<e.length;n++){let r=Number(e[n])-Number(t[n]);a+=r*r}return a}function P(e,t){if(!e)throw new Error(typeof t==\"string\"?t:t())}function Sa(e,t,a=\"\"){P(es(e,t),()=>a+` Shapes ${e} and ${t} must match`)}function Xs(e){P(e!=null,()=>\"The input to the tensor constructor must be a non-null value.\")}function zs(e,t=[],a=!1){if(t==null&&(t=[]),Array.isArray(e)||da(e)&&!a)for(let n=0;n<e.length;++n)zs(e[n],t,a);else t.push(e);return t}function At(e){if(e.length===0)return 1;let t=e[0];for(let a=1;a<e.length;a++)t*=e[a];return t}function pS(e){return e.length===0}function es(e,t){if(e===t)return!0;if(e==null||t==null||e.length!==t.length)return!1;for(let a=0;a<e.length;a++)if(e[a]!==t[a])return!1;return!0}function ol(e){return e%1===0}function cS(e){if(Math.tanh!=null)return Math.tanh(e);if(e===1/0)return 1;if(e===-1/0)return-1;{let t=Math.exp(2*e);return(t-1)/(t+1)}}function hS(e){let t=Math.ceil(Math.sqrt(e));return[t,Math.ceil(e/t)]}function fS(e){let t=new Uint32Array(e);for(let a=0;a<e;++a)t[a]=a;return sA(t),t}function Qu(e,t){return t<=e.length?e:e+\" \".repeat(t-e.length)}function mS(e,t=r=>0,a,n){return new Promise((r,s)=>{let i=0,o=()=>{if(e()){r();return}i++;let l=t(i);if(a!=null&&i>=a){s();return}n!=null?n(o,l):setTimeout(o,l)};o()})}function gS(e,t){let a=1,n=-1;for(let s=0;s<e.length;++s)if(e[s]>=0)a*=e[s];else if(e[s]===-1){if(n!==-1)throw Error(`Shapes can only have 1 implicit size. Found -1 at dim ${n} and dim ${s}`);n=s}else if(e[s]<0)throw Error(`Shapes can not be < 0. Found ${e[s]} at dim ${s}`);if(n===-1){if(t>0&&t!==a)throw Error(`Size(${t}) must match the product of shape ${e}`);return e}if(a===0)throw Error(`Cannot infer the missing size in [${e}] when there are 0 elements`);if(t%a!==0)throw Error(`The implicit shape can't be a fractional number. Got ${t} / ${a}`);let r=e.slice();return r[n]=t/a,r}function wd(e,t){let a=t.length;return e=e==null?t.map((n,r)=>r):[].concat(e),P(e.every(n=>n>=-a&&n<a),()=>`All values in axis param must be in range [-${a}, ${a}) but got axis ${e}`),P(e.every(n=>ol(n)),()=>`All values in axis param must be integers but got axis ${e}`),e.map(n=>n<0?a+n:n)}function iA(e,t){let a=[],n=[],r=t!=null&&Array.isArray(t)&&t.length===0,s=t==null||r?null:wd(t,e).sort(),i=0;for(let o=0;o<e.length;++o){if(s!=null){if(s[i]===o&&e[o]!==1)throw new Error(`Can't squeeze axis ${o} since its dim '${e[o]}' is not 1`);(s[i]==null||s[i]>o)&&e[o]===1&&(a.push(e[o]),n.push(o)),s[i]<=o&&i++}e[o]!==1&&(a.push(e[o]),n.push(o))}return{newShape:a,keptDims:n}}function oA(e,t){let a=null;if(e==null||e===\"float32\")a=new Float32Array(t);else if(e===\"int32\")a=new Int32Array(t);else if(e===\"bool\")a=new Uint8Array(t);else throw new Error(`Unknown data type ${e}`);return a}function lA(e,t){let a=null;if(e==null||e===\"float32\")a=new Float32Array(t);else if(e===\"int32\")a=new Int32Array(t);else if(e===\"bool\")a=new Uint8Array(t);else if(e===\"string\")a=new Array(t);else throw new Error(`Unknown data type ${e}`);return a}function uA(e,t){for(let a=0;a<e.length;a++){let n=e[a];if(isNaN(n)||!isFinite(n))throw Error(`A tensor of type ${t} being uploaded contains ${n}.`)}}function dA(e){return e===\"bool\"||e===\"complex64\"||e===\"float32\"||e===\"int32\"||e===\"string\"}function xS(e,t){return!(t===\"complex64\"||t===\"float32\"&&e!==\"complex64\"||t===\"int32\"&&e!==\"float32\"&&e!==\"complex64\"||t===\"bool\"&&e===\"bool\")}function da(e){return e instanceof Float32Array||e instanceof Int32Array||e instanceof Uint8Array||e instanceof Uint8ClampedArray}function Vm(e){if(e===\"float32\"||e===\"int32\")return 4;if(e===\"complex64\")return 8;if(e===\"bool\")return 1;throw new Error(`Unknown dtype ${e}`)}function pA(e){if(e==null)return 0;let t=0;return e.forEach(a=>t+=a.length),t}function Lr(e){return typeof e==\"string\"||e instanceof String}function cA(e){return typeof e==\"boolean\"}function hA(e){return typeof e==\"number\"}function Uc(e){return Array.isArray(e)?Uc(e[0]):e instanceof Float32Array?\"float32\":e instanceof Int32Array||e instanceof Uint8Array||e instanceof Uint8ClampedArray?\"int32\":hA(e)?\"float32\":Lr(e)?\"string\":cA(e)?\"bool\":\"float32\"}function Hr(e){return!!(e&&e.constructor&&e.call&&e.apply)}function Ic(e,t){for(let a=t;a<e;++a)if(e%a===0)return a;return e}function vl(e){let t=e.length;if(t<2)return[];let a=new Array(t-1);a[t-2]=e[t-1];for(let n=t-3;n>=0;--n)a[n]=a[n+1]*e[n+1];return a}function fA(e,t,a,n=!1){let r=new Array;if(t.length===1){let s=t[0]*(n?2:1);for(let i=0;i<s;i++)r[i]=a[e+i]}else{let s=t[0],i=t.slice(1),o=i.reduce((l,u)=>l*u)*(n?2:1);for(let l=0;l<s;l++)r[l]=fA(e+l*o,i,a,n)}return r}function al(e,t,a=!1){if(e.length===0)return t[0];let n=e.reduce((r,s)=>r*s)*(a?2:1);if(n===0)return[];if(n!==t.length)throw new Error(`[${e}] does not match the input size ${t.length}${a?\" for a complex tensor\":\"\"}.`);return fA(0,e,t,a)}function L1(e,t){let a=Gc(e,t);for(let n=0;n<a.length;n++)a[n]=1;return a}function Gc(e,t){if(t==null||t===\"float32\"||t===\"complex64\")return new Float32Array(e);if(t===\"int32\")return new Int32Array(e);if(t===\"bool\")return new Uint8Array(e);throw new Error(`Unknown data type ${t}`)}function AS(e,t){let a=e.reduce((n,r)=>n*r,1);if(t==null||t===\"float32\")return al(e,new Float32Array(a));if(t===\"int32\")return al(e,new Int32Array(a));if(t===\"bool\")return al(e,new Uint8Array(a));throw new Error(`Unknown data type ${t}`)}function Ja(e){e.forEach(t=>{P(Number.isInteger(t)&&t>=0,()=>`Tensor must have a shape comprised of positive integers but got shape [${e}].`)})}function yS(e,t,a){if(t===0)return 0;if(t===1)return e[0];let n=e[e.length-1];for(let r=0;r<e.length-1;++r)n+=a[r]*e[r];return n}function bS(e,t,a){if(t===0)return[];if(t===1)return[e];let n=new Array(t);for(let r=0;r<n.length-1;++r)n[r]=Math.floor(e/a[r]),e-=n[r]*a[r];return n[n.length-1]=e,n}function B1(e){return e&&e.then&&typeof e.then==\"function\"}var D5=\"tfjsflags\",mA=class{constructor(e){this.global=e,this.flags={},this.flagRegistry={},this.urlFlags={},this.getQueryParams=vS,this.populateURLFlags()}setPlatform(e,t){this.platform!=null&&(W().getBool(\"IS_TEST\")||W().getBool(\"PROD\")||console.warn(`Platform ${this.platformName} has already been set. Overwriting the platform with ${e}.`)),this.platformName=e,this.platform=t}registerFlag(e,t,a){if(this.flagRegistry[e]={evaluationFn:t,setHook:a},this.urlFlags[e]!=null){let n=this.urlFlags[e];W().getBool(\"IS_TEST\")||W().getBool(\"PROD\")||console.warn(`Setting feature override from URL ${e}: ${n}.`),this.set(e,n)}}async getAsync(e){return e in this.flags?this.flags[e]:(this.flags[e]=await this.evaluateFlag(e),this.flags[e])}get(e){if(e in this.flags)return this.flags[e];let t=this.evaluateFlag(e);if(B1(t))throw new Error(`Flag ${e} cannot be synchronously evaluated. Please use getAsync() instead.`);return this.flags[e]=t,this.flags[e]}getNumber(e){return this.get(e)}getBool(e){return this.get(e)}getFlags(){return this.flags}get features(){return this.flags}set(e,t){if(this.flagRegistry[e]==null)throw new Error(`Cannot set flag ${e} as it has not been registered.`);this.flags[e]=t,this.flagRegistry[e].setHook!=null&&this.flagRegistry[e].setHook(t)}evaluateFlag(e){if(this.flagRegistry[e]==null)throw new Error(`Cannot evaluate flag '${e}': no evaluation function found.`);return this.flagRegistry[e].evaluationFn()}setFlags(e){this.flags=Object.assign({},e)}reset(){this.flags={},this.urlFlags={},this.populateURLFlags()}populateURLFlags(){if(typeof this.global==\"undefined\"||typeof this.global.location==\"undefined\"||typeof this.global.location.search==\"undefined\")return;let e=this.getQueryParams(this.global.location.search);D5 in e&&e[D5].split(\",\").forEach(t=>{let[a,n]=t.split(\":\");this.urlFlags[a]=kS(a,n)})}};function vS(e){let t={};return e.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g,(a,...n)=>(wS(t,n[0],n[1]),n.join(\"=\"))),t}function wS(e,t,a){e[decodeURIComponent(t)]=decodeURIComponent(a||\"\")}function kS(e,t){if(t=t.toLowerCase(),t===\"true\"||t===\"false\")return t===\"true\";if(`${+t}`===t)return+t;throw new Error(`Could not parse value flag value ${t} for flag ${e}.`)}function W(){return W1}var W1=null;function IS(e){W1=e}var Mm;function gA(){if(Mm==null){let e;if(typeof window!=\"undefined\")e=window;else if(typeof global!=\"undefined\")e=global;else if(typeof process!=\"undefined\")e=process;else if(typeof self!=\"undefined\")e=self;else throw new Error(\"Could not find a global object\");Mm=e}return Mm}function SS(){let e=gA();return e._tfGlobals==null&&(e._tfGlobals=new Map),e._tfGlobals}function V1(e,t){let a=SS();if(a.has(e))return a.get(e);{let n=t();return a.set(e,n),a.get(e)}}var wl=\"Abs\",kl=\"Acos\",Il=\"Acosh\",ts=\"Add\",Ks=\"AddN\",Zs=\"All\",Ys=\"Any\",Js=\"ArgMax\",kd=\"ArgMin\",Sl=\"Asin\",Tl=\"Asinh\",Cl=\"Atan\",Nl=\"Atanh\",El=\"Atan2\",Qs=\"AvgPool\",U1=\"AvgPoolGrad\",Hc=\"AvgPool3D\",G1=\"AvgPool3DGrad\",ei=\"BatchMatMul\",Rl=\"BatchToSpaceND\",Id=\"Bincount\",TS=\"BroadcastTo\",jc=\"BroadcastArgs\",ti=\"Cast\",ai=\"Ceil\",as=\"ClipByValue\",Sd=\"Complex\",qc=\"ComplexAbs\",Ml=\"Concat\",ni=\"Conv2D\",Xc=\"Conv2DBackpropFilter\",ri=\"Conv2DBackpropInput\",Kc=\"Conv3D\",H1=\"Conv3DBackpropFilterV2\",Zc=\"Conv3DBackpropInputV2\",si=\"Cos\",ii=\"Cosh\",oi=\"Cumprod\",li=\"Cumsum\",ui=\"CropAndResize\",Td=\"DenseBincount\",di=\"DepthToSpace\",pi=\"DepthwiseConv2dNative\",Yc=\"DepthwiseConv2dNativeBackpropFilter\",Jc=\"DepthwiseConv2dNativeBackpropInput\",Qc=\"Diag\",eh=\"Dilation2D\",Um=\"Dilation2DBackpropInput\",Gm=\"Dilation2DBackpropFilter\",ci=\"RealDiv\",Cd=\"Einsum\",hi=\"Elu\",j1=\"EluGrad\",$l=\"Erf\",fi=\"Equal\",mi=\"Exp\",_l=\"ExpandDims\",Pl=\"Expm1\",Nd=\"FFT\",Fl=\"Fill\",gi=\"FlipLeftRight\",xi=\"Floor\",Ai=\"FloorDiv\",yi=\"FusedBatchNorm\",Ol=\"GatherV2\",bi=\"GatherNd\",vi=\"Greater\",wi=\"GreaterEqual\",ki=\"Identity\",Ed=\"IFFT\",Rd=\"Imag\",Dl=\"IsFinite\",zl=\"IsInf\",Ii=\"IsNan\",Si=\"LeakyRelu\",Ti=\"Less\",Ci=\"LessEqual\",th=\"LinSpace\",Ni=\"Log\",Ll=\"Log1p\",Ei=\"LogicalAnd\",Ri=\"LogicalNot\",Bl=\"LogicalOr\",xA=\"LogicalXor\",CS=\"LogSoftmax\",NS=\"LowerBound\",ah=\"LRN\",q1=\"LRNGrad\",Mi=\"Max\",$i=\"Maximum\",_i=\"MaxPool\",X1=\"MaxPoolGrad\",nh=\"MaxPool3D\",K1=\"MaxPool3DGrad\",rh=\"MaxPoolWithArgmax\",Pi=\"Mean\",Fi=\"Min\",Oi=\"Minimum\",Di=\"MirrorPad\",Wl=\"Mod\",sh=\"Multinomial\",zi=\"Multiply\",Vl=\"Neg\",Li=\"NotEqual\",Bi=\"NonMaxSuppressionV3\",Ul=\"NonMaxSuppressionV4\",Wi=\"NonMaxSuppressionV5\",Gl=\"OnesLike\",Vi=\"OneHot\",Hl=\"Pack\",Ui=\"PadV2\",ES=\"Pool\",Gi=\"Pow\",Hi=\"Prelu\",ji=\"Prod\",ih=\"RaggedGather\",oh=\"RaggedRange\",lh=\"RaggedTensorToTensor\",jl=\"Range\",Md=\"Real\",qi=\"Reciprocal\",Xi=\"Relu\",ql=\"Reshape\",Ki=\"ResizeNearestNeighbor\",Z1=\"ResizeNearestNeighborGrad\",Zi=\"ResizeBilinear\",Y1=\"ResizeBilinearGrad\",Yi=\"Relu6\",Ji=\"Reverse\",Xl=\"Round\",Qi=\"Rsqrt\",eo=\"ScatterNd\",$d=\"SearchSorted\",Kl=\"Select\",_d=\"Selu\",Zl=\"Slice\",to=\"Sin\",Yl=\"Sinh\",Pd=\"Sign\",ao=\"Sigmoid\",Fd=\"Softplus\",no=\"Sqrt\",ro=\"Sum\",Jl=\"SpaceToBatchND\",Ql=\"SplitV\",so=\"Softmax\",Od=\"SparseFillEmptyRows\",eu=\"SparseReshape\",Dd=\"SparseSegmentMean\",zd=\"SparseSegmentSum\",Ld=\"SparseToDense\",io=\"SquaredDifference\",Bd=\"Square\",oo=\"StridedSlice\",tu=\"StringNGrams\",Wd=\"StringSplit\",Vd=\"StringToHashBucketFast\",lo=\"Sub\",uo=\"Tan\",po=\"Tanh\",ns=\"Tile\",co=\"TopK\",ho=\"Transform\",Ar=\"Transpose\",uh=\"Unique\",au=\"Unpack\",dh=\"UnsortedSegmentSum\",RS=\"UpperBound\",nu=\"ZerosLike\",fo=\"Step\",rd=\"FromPixels\",mo=\"RotateWithOffset\",jr=\"_FusedMatMul\",qr=\"FusedConv2D\",Xr=\"FusedDepthwiseConv2D\";function zr(...e){W().getBool(\"IS_TEST\")||W().getBool(\"PROD\")||console.warn(...e)}function MS(...e){W().getBool(\"IS_TEST\")||W().getBool(\"PROD\")||console.log(...e)}var ll=V1(\"kernelRegistry\",()=>new Map),sd=V1(\"gradRegistry\",()=>new Map);function Sc(e,t){let a=J1(e,t);return ll.get(a)}function Hm(e){return sd.get(e)}function Zn(e){let t=ll.entries(),a=[];for(;;){let{done:n,value:r}=t.next();if(n)break;let[s,i]=r,[o]=s.split(\"_\");o===e&&a.push(i)}return a}function mn(e){let{kernelName:t,backendName:a}=e,n=J1(t,a);ll.has(n)&&zr(`The kernel '${t}' for backend '${a}' is already registered`),ll.set(n,e)}function $S(e){let{kernelName:t}=e;sd.has(t)&&W().getBool(\"DEBUG\")&&zr(`Overriding the gradient for '${t}'`),sd.set(t,e)}function _S(e,t){let a=J1(e,t);if(!ll.has(a))throw new Error(`The kernel '${e}' for backend '${t}' is not registered`);ll.delete(a)}function PS(e){if(!sd.has(e))throw new Error(`The gradient '${e}' for backend is not registered`);sd.delete(e)}function FS(e,t){Zn(e).forEach(a=>{let n=Object.assign({},a,{backendName:t});mn(n)})}function J1(e,t){return`${t}_${e}`}var v={};Xe(v,{arraysEqual:()=>es,assert:()=>P,assertNonNegativeIntegerDimensions:()=>Ja,assertNonNull:()=>Xs,assertShapesMatch:()=>Sa,bytesFromStringArray:()=>pA,bytesPerElement:()=>Vm,checkConversionForErrors:()=>uA,clamp:()=>nd,computeStrides:()=>vl,createScalarValue:()=>WS,createShuffledIndices:()=>fS,decodeString:()=>Tc,distSquared:()=>dS,encodeString:()=>Gd,fetch:()=>US,fingerPrint64:()=>BS,flatten:()=>zs,getArrayFromDType:()=>lA,getTypedArrayFromDType:()=>oA,hasEncodingLoss:()=>xS,hexToLong:()=>Ud,indexToLoc:()=>bS,inferDtype:()=>Uc,inferFromImplicitShape:()=>gS,isBoolean:()=>cA,isFunction:()=>Hr,isInt:()=>ol,isNumber:()=>hA,isPromise:()=>B1,isScalarShape:()=>pS,isString:()=>Lr,isTypedArray:()=>da,isValidDtype:()=>dA,locToIndex:()=>yS,makeOnesTypedArray:()=>L1,makeZerosNestedTypedArray:()=>AS,makeZerosTypedArray:()=>Gc,nearestDivisor:()=>Ic,nearestLargerEven:()=>oS,now:()=>id,parseAxisParam:()=>wd,randUniform:()=>uS,repeatedTry:()=>mS,rightPad:()=>Qu,shuffle:()=>sA,shuffleCombo:()=>iS,sizeFromShape:()=>At,sizeToSquarishShape:()=>hS,squeezeShape:()=>iA,sum:()=>lS,swap:()=>kc,tanh:()=>cS,toNestedArray:()=>al,toTypedArray:()=>ph});var z5=yl(UI()),$s=z5.default||z5;function Ud(e){return $s.fromString(e,!0,16)}var AA=Ud(\"c3a5c85c97cb3127\"),Rs=Ud(\"b492b66fbe98f273\"),Aa=Ud(\"9ae16a3b2f90404f\");function jm(e){return e.xor(e.shru(47))}function yA(e,t,a){let n=e.slice(t,t+a);return $s.fromBytes(Array.from(n),!0,!0)}function ft(e,t){return yA(e,t,8)}function L5(e,t){return yA(e,t,4)}function Kt(e,t){return t===0?e:e.shru(t).or(e.shl(64-t))}function Ur(e,t,a=Ud(\"9ddfea08eb382d69\")){let n=e.xor(t).mul(a);n=n.xor(n.shru(47));let r=t.xor(n).mul(a);return r=r.xor(r.shru(47)),r=r.mul(a),r}function OS(e,t,a,n,r,s){r=r.add(e),s=Kt(s.add(r).add(n),21);let i=r;return r=r.add(t),r=r.add(a),s=s.add(Kt(r,44)),[r.add(n),s.add(i)]}function ic(e,t,a,n){return OS(ft(e,t),ft(e,t+8),ft(e,t+16),ft(e,t+24),a,n)}function DS(e,t=e.length){if(t>=8){let a=Aa.add(t*2),n=ft(e,0).add(Aa),r=ft(e,t-8),s=Kt(r,37).mul(a).add(n),i=Kt(n,25).add(r).mul(a);return Ur(s,i,a)}if(t>=4){let a=Aa.add(t*2),n=L5(e,0);return Ur(n.shl(3).add(t),L5(e,t-4),a)}if(t>0){let a=e[0],n=e[t>>1],r=e[t-1],s=a+(n<<8),i=t+(r<<2);return jm(Aa.mul(s).xor(AA.mul(i))).mul(Aa)}return Aa}function zS(e,t=e.length){let a=Aa.add(t*2),n=ft(e,0).mul(Rs),r=ft(e,8),s=ft(e,t-8).mul(a),i=ft(e,t-16).mul(Aa);return Ur(Kt(n.add(r),43).add(Kt(s,30)).add(i),n.add(Kt(r.add(Aa),18)).add(s),a)}function LS(e,t=e.length){let a=Aa.add(t*2),n=ft(e,0).mul(Aa),r=ft(e,8),s=ft(e,t-8).mul(a),i=ft(e,t-16).mul(Aa),o=Kt(n.add(r),43).add(Kt(s,30)).add(i),l=Ur(o,n.add(Kt(r.add(Aa),18)).add(s),a),u=ft(e,16).mul(a),p=ft(e,24),c=o.add(ft(e,t-32)).mul(a),d=l.add(ft(e,t-24)).mul(a);return Ur(Kt(u.add(p),43).add(Kt(c,30)).add(d),u.add(Kt(p.add(n),18)).add(c),a)}function BS(e,t=e.length){let a=$s.fromNumber(81,!0);if(t<=32)return t<=16?DS(e,t):zS(e,t);if(t<=64)return LS(e,t);let n=a,r=a.mul(Rs).add(113),s=jm(r.mul(Aa).add(113)).mul(Aa),i=[$s.UZERO,$s.UZERO],o=[$s.UZERO,$s.UZERO];n=n.mul(Aa).add(ft(e,0));let l=0,u=(t-1>>6)*64,p=u+(t-1&63)-63;do n=Kt(n.add(r).add(i[0]).add(ft(e,l+8)),37).mul(Rs),r=Kt(r.add(i[1]).add(ft(e,l+48)),42).mul(Rs),n=n.xor(o[1]),r=r.add(i[0]).add(ft(e,l+40)),s=Kt(s.add(o[0]),33).mul(Rs),i=ic(e,l,i[1].mul(Rs),n.add(o[0])),o=ic(e,l+32,s.add(o[1]),r.add(ft(e,l+16))),[s,n]=[n,s],l+=64;while(l!==u);let c=Rs.add(s.and(255).shl(1));return l=p,o[0]=o[0].add(t-1&63),i[0]=i[0].add(o[0]),o[0]=o[0].add(i[0]),n=Kt(n.add(r).add(i[0]).add(ft(e,l+8)),37).mul(c),r=Kt(r.add(i[1]).add(ft(e,l+48)),42).mul(c),n=n.xor(o[1].mul(9)),r=r.add(i[0].mul(9).add(ft(e,l+40))),s=Kt(s.add(o[0]),33).mul(c),i=ic(e,l,i[1].mul(c),n.add(o[0])),o=ic(e,l+32,s.add(o[1]),r.add(ft(e,l+16))),[s,n]=[n,s],Ur(Ur(i[0],o[0],c).add(jm(r).mul(AA)).add(s),Ur(i[1],o[1],c).add(n),c)}function WS(e,t){return t===\"string\"?Gd(e):ph([e],t)}function VS(e,t){return e instanceof Float32Array&&t===\"float32\"||e instanceof Int32Array&&t===\"int32\"||e instanceof Uint8Array&&t===\"bool\"}function ph(e,t){if(t===\"string\")throw new Error(\"Cannot convert a string[] to a TypedArray\");if(Array.isArray(e)&&(e=zs(e)),W().getBool(\"DEBUG\")&&uA(e,t),VS(e,t))return e;if(t==null||t===\"float32\"||t===\"complex64\")return new Float32Array(e);if(t===\"int32\")return new Int32Array(e);if(t===\"bool\"){let a=new Uint8Array(e.length);for(let n=0;n<a.length;++n)Math.round(e[n])!==0&&(a[n]=1);return a}else throw new Error(`Unknown data type ${t}`)}function id(){return W().platform.now()}function US(e,t){return W().platform.fetch(e,t)}function Gd(e,t=\"utf-8\"){return t=t||\"utf-8\",W().platform.encode(e,t)}function Tc(e,t=\"utf-8\"){return t=t||\"utf-8\",W().platform.decode(e,t)}var GS=class{constructor(e,t){this.backendTimer=e,this.logger=t,t==null&&(this.logger=new jS)}profileKernel(e,t,a){let n,r=()=>{n=a()},s,i=id();if(this.backendTimer.timerAvailable())s=this.backendTimer.time(r);else{r();for(let o of n)o.dataSync();s=Promise.resolve({kernelMs:id()-i})}if(W().getBool(\"CHECK_COMPUTATION_FOR_ERRORS\"))for(let o=0;o<n.length;o++){let l=n[o];l.data().then(u=>{HS(u,l.dtype,e)})}return{kernelName:e,outputs:n,inputs:t,timeMs:s.then(o=>o.kernelMs),extraInfo:s.then(o=>o.getExtraProfileInfo!=null?o.getExtraProfileInfo():\"\")}}logKernelProfile(e){let{kernelName:t,outputs:a,timeMs:n,inputs:r,extraInfo:s}=e;a.forEach(i=>{Promise.all([i.data(),n,s]).then(o=>{this.logger.logKernelProfile(t,i,o[0],o[1],r,o[2])})})}};function HS(e,t,a){if(t!==\"float32\")return!1;for(let n=0;n<e.length;n++){let r=e[n];if(isNaN(r)||!isFinite(r))return console.warn(`Found ${r} in the result of '${a}'`),!0}return!1}var jS=class{logKernelProfile(e,t,a,n,r,s){let i=typeof n==\"number\"?Qu(`${n}ms`,9):n.error,o=Qu(e,25),l=t.rank,u=t.size,p=Qu(t.shape.toString(),14),c=\"\";for(let d in r){let h=r[d];if(h!=null){let f=h.shape||t.shape,m=f.length;c+=`${d}: ${m}D ${m>0?f:\"\"} `}}console.log(`%c${o}\t%c${i}\t%c${l}D ${p}\t%c${u}\t%c${c}\t%c${s}`,\"font-weight:bold\",\"color:red\",\"color:blue\",\"color: orange\",\"color: green\",\"color: steelblue\")}};function qS(e,t,a){let n={},r={};for(let l=0;l<t.length;l++)n[t[l].id]=!0;for(let l=0;l<e.length;l++){let u=e[l],p=u.inputs;for(let c in p){let d=p[c],h=!1;for(let f=0;f<t.length;f++)if(n[d.id]){u.outputs.forEach(m=>n[m.id]=!0),h=!0,r[u.id]=!0;break}if(h)break}}let s={};s[a.id]=!0;let i={};for(let l=e.length-1;l>=0;l--){let u=e[l],p=u.inputs;for(let c=0;c<u.outputs.length;c++)if(s[u.outputs[c].id]){for(let d in p)s[p[d].id]=!0,i[u.id]=!0;break}}let o=[];for(let l=0;l<e.length;l++){let u=e[l];if(r[u.id]&&i[u.id]){let p={};for(let d in u.inputs){let h=u.inputs[d];n[h.id]&&(p[d]=h)}let c=Object.assign({},u);c.inputs=p,c.outputs=u.outputs,o.push(c)}}return o}function XS(e,t,a,n){for(let r=t.length-1;r>=0;r--){let s=t[r],i=[];if(s.outputs.forEach(l=>{let u=e[l.id];u!=null?i.push(u):i.push(null)}),s.gradient==null)throw new Error(`Cannot compute gradient: gradient function not found for ${s.kernelName}.`);let o=s.gradient(i);for(let l in s.inputs){if(!(l in o))throw new Error(`Cannot backprop through input ${l}. Available gradients found: ${Object.keys(o)}.`);let u=a(()=>o[l]());if(u.dtype!==\"float32\")throw new Error(`Error in gradient for op ${s.kernelName}. The gradient of input ${l} must have 'float32' dtype, but has '${u.dtype}'`);let p=s.inputs[l];if(!es(u.shape,p.shape))throw new Error(`Error in gradient for op ${s.kernelName}. The gradient of input '${l}' has shape '${u.shape}', which does not match the shape of the input '${p.shape}'`);if(e[p.id]==null)e[p.id]=u;else{let c=e[p.id];e[p.id]=n(c,u),c.dispose()}}}}var B5=20,Wu=3,$m=7;function KS(e,t,a,n){let r=vl(t),s=ZS(e,t,a,r),i=t.length,o=hc(e,t,a,r,s),l=[\"Tensor\"];return n&&(l.push(`  dtype: ${a}`),l.push(`  rank: ${i}`),l.push(`  shape: [${t}]`),l.push(\"  values:\")),l.push(o.map(u=>\"    \"+u).join(`\n`)),l.join(`\n`)}function ZS(e,t,a,n){let r=At(t),s=n[n.length-1],i=new Array(s).fill(0),o=t.length,l=a===\"complex64\"?Gu(e):e;if(o>1)for(let u=0;u<r/s;u++){let p=u*s;for(let c=0;c<s;c++)i[c]=Math.max(i[c],Uu(l[p+c],0,a).length)}return i}function Uu(e,t,a){let n;return Array.isArray(e)?n=`${parseFloat(e[0].toFixed($m))} + ${parseFloat(e[1].toFixed($m))}j`:Lr(e)?n=`'${e}'`:a===\"bool\"?n=bA(e):n=parseFloat(e.toFixed($m)).toString(),Qu(n,t)}function bA(e){return e===0?\"false\":\"true\"}function hc(e,t,a,n,r,s=!0){let i=a===\"complex64\"?2:1,o=t[0],l=t.length;if(l===0){if(a===\"complex64\"){let m=Gu(e);return[Uu(m[0],0,a)]}return a===\"bool\"?[bA(e[0])]:[e[0].toString()]}if(l===1){if(o>B5){let m=Wu*i,g=Array.from(e.slice(0,m)),x=Array.from(e.slice((o-Wu)*i,o*i));return a===\"complex64\"&&(g=Gu(g),x=Gu(x)),[\"[\"+g.map((A,y)=>Uu(A,r[y],a)).join(\", \")+\", ..., \"+x.map((A,y)=>Uu(A,r[o-Wu+y],a)).join(\", \")+\"]\"]}return[\"[\"+(a===\"complex64\"?Gu(e):Array.from(e)).map((m,g)=>Uu(m,r[g],a)).join(\", \")+\"]\"]}let u=t.slice(1),p=n.slice(1),c=n[0]*i,d=[];if(o>B5){for(let m=0;m<Wu;m++){let g=m*c,x=g+c;d.push(...hc(e.slice(g,x),u,a,p,r,!1))}d.push(\"...\");for(let m=o-Wu;m<o;m++){let g=m*c,x=g+c;d.push(...hc(e.slice(g,x),u,a,p,r,m===o-1))}}else for(let m=0;m<o;m++){let g=m*c,x=g+c;d.push(...hc(e.slice(g,x),u,a,p,r,m===o-1))}let h=l===2?\",\":\"\";d[0]=\"[\"+d[0]+h;for(let m=1;m<d.length-1;m++)d[m]=\" \"+d[m]+h;let f=`,\n`;for(let m=2;m<l;m++)f+=`\n`;return d[d.length-1]=\" \"+d[d.length-1]+\"]\"+(s?\"\":f),d}function Gu(e){let t=[];for(let a=0;a<e.length;a+=2)t.push([e[a],e[a+1]]);return t}var jt=class{constructor(e,t,a){if(this.dtype=t,this.shape=e.slice(),this.size=At(e),a!=null){let n=a.length;P(n===this.size,()=>`Length of values '${n}' does not match the size inferred by the shape '${this.size}'.`)}if(t===\"complex64\")throw new Error(\"complex64 dtype TensorBuffers are not supported. Please create a TensorBuffer for the real and imaginary parts separately and call tf.complex(real, imag).\");this.values=a||lA(t,this.size),this.strides=vl(e)}set(e,...t){t.length===0&&(t=[0]),P(t.length===this.rank,()=>`The number of provided coordinates (${t.length}) must match the rank (${this.rank})`);let a=this.locToIndex(t);this.values[a]=e}get(...e){e.length===0&&(e=[0]);let t=0;for(let n of e){if(n<0||n>=this.shape[t]){let r=`Requested out of range element at ${e}.   Buffer shape=${this.shape}`;throw new Error(r)}t++}let a=e[e.length-1];for(let n=0;n<e.length-1;++n)a+=this.strides[n]*e[n];return this.values[a]}locToIndex(e){if(this.rank===0)return 0;if(this.rank===1)return e[0];let t=e[e.length-1];for(let a=0;a<e.length-1;++a)t+=this.strides[a]*e[a];return t}indexToLoc(e){if(this.rank===0)return[];if(this.rank===1)return[e];let t=new Array(this.shape.length);for(let a=0;a<t.length-1;++a)t[a]=Math.floor(e/this.strides[a]),e-=t[a]*this.strides[a];return t[t.length-1]=e,t}get rank(){return this.shape.length}toTensor(){return Fn().makeTensor(this.values,this.shape,this.dtype)}},Fn=null,Qo=null,YS=null;function JS(e){Fn=e}function QS(e){Qo=e}function eT(e){YS=e}var pt=class{constructor(e,t,a,n){this.kept=!1,this.isDisposedInternal=!1,this.shape=e.slice(),this.dtype=t||\"float32\",this.size=At(e),this.strides=vl(e),this.dataId=a,this.id=n,this.rankType=this.rank<5?this.rank.toString():\"higher\"}get rank(){return this.shape.length}async buffer(){let e=await this.data();return Qo.buffer(this.shape,this.dtype,e)}bufferSync(){return Qo.buffer(this.shape,this.dtype,this.dataSync())}async array(){let e=await this.data();return al(this.shape,e,this.dtype===\"complex64\")}arraySync(){return al(this.shape,this.dataSync(),this.dtype===\"complex64\")}async data(){this.throwIfDisposed();let e=Fn().read(this.dataId);if(this.dtype===\"string\"){let t=await e;try{return t.map(a=>Tc(a))}catch(a){throw new Error(\"Failed to decode the string bytes into utf-8. To get the original bytes, call tensor.bytes().\")}}return e}dataToGPU(e){return this.throwIfDisposed(),Fn().readToGPU(this.dataId,e)}dataSync(){this.throwIfDisposed();let e=Fn().readSync(this.dataId);if(this.dtype===\"string\")try{return e.map(t=>Tc(t))}catch(t){throw new Error(\"Failed to decode the string bytes into utf-8. To get the original bytes, call tensor.bytes().\")}return e}async bytes(){this.throwIfDisposed();let e=await Fn().read(this.dataId);return this.dtype===\"string\"?e:new Uint8Array(e.buffer)}dispose(){this.isDisposed||(Fn().disposeTensor(this),this.isDisposedInternal=!0)}get isDisposed(){return this.isDisposedInternal}throwIfDisposed(){if(this.isDisposed)throw new Error(\"Tensor is disposed.\")}print(e=!1){return Qo.print(this,e)}clone(){return this.throwIfDisposed(),Qo.clone(this)}toString(e=!1){let t=this.dataSync();return KS(t,this.shape,this.dtype,e)}cast(e){return this.throwIfDisposed(),Qo.cast(this,e)}variable(e=!0,t,a){return this.throwIfDisposed(),Fn().makeVariable(this,e,t,a)}};Object.defineProperty(pt,Symbol.hasInstance,{value:e=>!!e&&e.data!=null&&e.dataSync!=null&&e.throwIfDisposed!=null});function tT(){return V1(\"Tensor\",()=>pt)}tT();var od=class extends pt{constructor(e,t,a,n){super(e.shape,e.dtype,e.dataId,n),this.trainable=t,this.name=a}assign(e){if(e.dtype!==this.dtype)throw new Error(`dtype of the new value (${e.dtype}) and previous value (${this.dtype}) must match`);if(!es(e.shape,this.shape))throw new Error(`shape of the new value (${e.shape}) and previous value (${this.shape}) must match`);Fn().disposeTensor(this),this.dataId=e.dataId,Fn().incRef(this,null)}dispose(){Fn().disposeVariable(this),this.isDisposedInternal=!0}};Object.defineProperty(od,Symbol.hasInstance,{value:e=>e instanceof pt&&e.assign!=null&&e.assign instanceof Function});var vA={};Xe(vA,{assertTypesMatch:()=>wA,getTensorsInContainer:()=>Q1,isTensorInList:()=>nT,makeTypesMatch:()=>St});var qm;(function(e){e.R0=\"R0\",e.R1=\"R1\",e.R2=\"R2\",e.R3=\"R3\",e.R4=\"R4\",e.R5=\"R5\",e.R6=\"R6\"})(qm||(qm={}));var Xm;(function(e){e.float32=\"float32\",e.int32=\"int32\",e.bool=\"int32\",e.complex64=\"complex64\"})(Xm||(Xm={}));var Km;(function(e){e.float32=\"float32\",e.int32=\"int32\",e.bool=\"bool\",e.complex64=\"complex64\"})(Km||(Km={}));var Zm;(function(e){e.float32=\"float32\",e.int32=\"float32\",e.bool=\"float32\",e.complex64=\"complex64\"})(Zm||(Zm={}));var Ym;(function(e){e.float32=\"complex64\",e.int32=\"complex64\",e.bool=\"complex64\",e.complex64=\"complex64\"})(Ym||(Ym={}));var aT={float32:Zm,int32:Xm,bool:Km,complex64:Ym};function ca(e,t){if(e===\"string\"||t===\"string\"){if(e===\"string\"&&t===\"string\")return\"string\";throw new Error(`Can not upcast ${e} with ${t}`)}return aT[e][t]}function Hd(e){return ca(e,\"int32\")}function St(e,t){if(e.dtype===t.dtype)return[e,t];let a=ca(e.dtype,t.dtype);return[e.cast(a),t.cast(a)]}function wA(e,t){P(e.dtype===t.dtype,()=>`The dtypes of the first(${e.dtype}) and second(${t.dtype}) input must match`)}function nT(e,t){return t.some(a=>a.id===e.id)}function Q1(e){let t=[];return kA(e,t,new Set),t}function kA(e,t,a){if(e==null)return;if(e instanceof pt){t.push(e);return}if(!rT(e))return;let n=e;for(let r in n){let s=n[r];a.has(s)||(a.add(s),kA(s,t,a))}}function rT(e){return Array.isArray(e)||typeof e==\"object\"}function _m(e){return e.kernelName!=null}var W5=class{constructor(){this.registeredVariables={},this.nextTapeNodeId=0,this.numBytes=0,this.numTensors=0,this.numStringTensors=0,this.numDataBuffers=0,this.gradientDepth=0,this.kernelDepth=0,this.scopeStack=[],this.numDataMovesStack=[],this.nextScopeId=0,this.tensorInfo=new WeakMap,this.profiling=!1,this.activeProfile={newBytes:0,newTensors:0,peakBytes:0,kernels:[],result:null,get kernelNames(){return Array.from(new Set(this.kernels.map(e=>e.name)))}}}dispose(){for(let e in this.registeredVariables)this.registeredVariables[e].dispose()}},ld=class{constructor(e){this.ENV=e,this.registry={},this.registryFactory={},this.pendingBackendInitId=0,this.state=new W5}async ready(){if(this.pendingBackendInit!=null)return this.pendingBackendInit.then(()=>{});if(this.backendInstance!=null)return;let e=this.getSortedBackends();for(let t=0;t<e.length;t++){let a=e[t];if(await this.initializeBackend(a).success){await this.setBackend(a);return}}throw new Error(\"Could not initialize any backends, all backend initializations failed.\")}get backend(){if(this.pendingBackendInit!=null)throw new Error(`Backend '${this.backendName}' has not yet been initialized. Make sure to await tf.ready() or await tf.setBackend() before calling other methods`);if(this.backendInstance==null){let{name:e,asyncInit:t}=this.initializeBackendsAndReturnBest();if(t)throw new Error(`The highest priority backend '${e}' has not yet been initialized. Make sure to await tf.ready() or await tf.setBackend() before calling other methods`);this.setBackend(e)}return this.backendInstance}backendNames(){return Object.keys(this.registryFactory)}findBackend(e){if(!(e in this.registry))if(e in this.registryFactory){let{asyncInit:t}=this.initializeBackend(e);if(t)return null}else return null;return this.registry[e]}findBackendFactory(e){return e in this.registryFactory?this.registryFactory[e].factory:null}registerBackend(e,t,a=1){return e in this.registryFactory?(zr(`${e} backend was already registered. Reusing existing backend factory.`),!1):(this.registryFactory[e]={factory:t,priority:a},!0)}async setBackend(e){if(this.registryFactory[e]==null)throw new Error(`Backend name '${e}' not found in registry`);if(this.backendName=e,this.registry[e]==null){this.backendInstance=null;let{success:t,asyncInit:a}=this.initializeBackend(e);if(!(a?await t:t))return!1}return this.backendInstance=this.registry[e],this.setupRegisteredKernels(),this.profiler=new GS(this.backendInstance),!0}setupRegisteredKernels(){Zn(this.backendName).forEach(e=>{e.setupFunc!=null&&e.setupFunc(this.backendInstance)})}disposeRegisteredKernels(e){Zn(e).forEach(t=>{t.disposeFunc!=null&&t.disposeFunc(this.registry[e])})}initializeBackend(e){let t=this.registryFactory[e];if(t==null)throw new Error(`Cannot initialize backend ${e}, no registration found.`);try{let a=t.factory();if(a&&!(a instanceof bl)&&typeof a.then==\"function\"){let n=++this.pendingBackendInitId,r=a.then(s=>n<this.pendingBackendInitId?!1:(this.registry[e]=s,this.pendingBackendInit=null,!0)).catch(s=>(n<this.pendingBackendInitId||(this.pendingBackendInit=null,zr(`Initialization of backend ${e} failed`),zr(s.stack||s.message)),!1));return this.pendingBackendInit=r,{success:r,asyncInit:!0}}else return this.registry[e]=a,{success:!0,asyncInit:!1}}catch(a){return zr(`Initialization of backend ${e} failed`),zr(a.stack||a.message),{success:!1,asyncInit:!1}}}removeBackend(e){if(!(e in this.registryFactory))throw new Error(`${e} backend not found in registry`);this.backendName===e&&this.pendingBackendInit!=null&&this.pendingBackendInitId++,e in this.registry&&(this.disposeRegisteredKernels(e),this.registry[e].dispose(),delete this.registry[e]),delete this.registryFactory[e],this.backendName===e&&(this.pendingBackendInit=null,this.backendName=null,this.backendInstance=null)}getSortedBackends(){if(Object.keys(this.registryFactory).length===0)throw new Error(\"No backend found in registry.\");return Object.keys(this.registryFactory).sort((e,t)=>this.registryFactory[t].priority-this.registryFactory[e].priority)}initializeBackendsAndReturnBest(){let e=this.getSortedBackends();for(let t=0;t<e.length;t++){let a=e[t],{success:n,asyncInit:r}=this.initializeBackend(a);if(r||n)return{name:a,asyncInit:r}}throw new Error(\"Could not initialize any backends, all backend initializations failed.\")}moveData(e,t){let a=this.state.tensorInfo.get(t),n=a.backend,r=this.readSync(t),s=n.refCount(t);n.disposeData(t,!0),a.backend=e,e.move(t,r,a.shape,a.dtype,s),this.shouldCheckForMemLeaks()&&this.state.numDataMovesStack[this.state.numDataMovesStack.length-1]++}tidy(e,t){let a=null;if(t==null){if(typeof e!=\"function\")throw new Error(\"Please provide a function to tidy()\");t=e}else{if(typeof e!=\"string\"&&!(e instanceof String))throw new Error(\"When calling with two arguments, the first argument to tidy() must be a string\");if(typeof t!=\"function\")throw new Error(\"When calling with two arguments, the 2nd argument to tidy() must be a function\");a=e}let n;return this.scopedRun(()=>this.startScope(a),()=>this.endScope(n),()=>(n=t(),n instanceof Promise&&console.error(\"Cannot return a Promise inside of tidy.\"),n))}scopedRun(e,t,a){e();try{let n=a();return t(),n}catch(n){throw t(),n}}nextTensorId(){return ld.nextTensorId++}nextVariableId(){return ld.nextVariableId++}clone(e){let t=z.runKernel(ki,{x:e}),a={x:e},n=s=>({x:()=>{let i=\"float32\",o={x:s},l={dtype:i};return z.runKernel(ti,o,l)}}),r=[];return this.addTapeNode(this.state.activeScope.name,a,[t],n,r,{}),t}runKernel(e,t,a){if(this.backendName==null&&this.backend,Sc(e,this.backendName)==null)throw new Error(`Kernel '${e}' not registered for backend '${this.backendName}'`);return this.runKernelFunc({kernelName:e,inputs:t,attrs:a})}shouldCheckForMemLeaks(){return this.ENV.getBool(\"IS_TEST\")}checkKernelForMemLeak(e,t,a){let n=this.backend.numDataIds(),r=0;a.forEach(o=>{r+=o.dtype===\"complex64\"?3:1});let s=this.state.numDataMovesStack[this.state.numDataMovesStack.length-1],i=n-t-r-s;if(i>0)throw new Error(`Backend '${this.backendName}' has an internal memory leak (${i} data ids) after running '${e}'`)}runKernelFunc(e){let t,a=[],n=this.isTapeOn(),r=this.state.numBytes,s=this.state.numTensors;this.shouldCheckForMemLeaks()&&this.state.numDataMovesStack.push(0);let i;this.backendName==null&&this.backend;let o,l=_m(e)?e.kernelName:this.state.activeScope!=null?this.state.activeScope.name:\"\";if(_m(e)){let{kernelName:h,inputs:f,attrs:m}=e;this.backendName==null&&this.backend;let g=Sc(h,this.backendName);P(g!=null,()=>`Cannot find registered kernel '${h}' for backend '${this.backendName}'`),i=()=>{let x=this.backend.numDataIds();o=g.kernelFunc({inputs:f,attrs:m,backend:this.backend});let A=Array.isArray(o)?o:[o];this.shouldCheckForMemLeaks()&&this.checkKernelForMemLeak(h,x,A);let y=A.map(b=>b.rank!=null?b:this.makeTensorFromTensorInfo(b));if(n){let b=this.getTensorsForGradient(h,f,y);a=this.saveTensorsForBackwardMode(b)}return y}}else{let{forwardFunc:h}=e,f=m=>{!n||(a=m.map(g=>this.keep(this.clone(g))))};i=()=>{let m=this.backend.numDataIds();o=this.tidy(()=>h(this.backend,f));let g=Array.isArray(o)?o:[o];return this.shouldCheckForMemLeaks()&&this.checkKernelForMemLeak(l,m,g),g}}let{inputs:u,attrs:p}=e,c=_m(e)?null:e.backwardsFunc,d;return this.scopedRun(()=>this.state.kernelDepth++,()=>this.state.kernelDepth--,()=>{!this.ENV.getBool(\"DEBUG\")&&!this.state.profiling?t=i():(d=this.profiler.profileKernel(l,u,()=>i()),this.ENV.getBool(\"DEBUG\")&&this.profiler.logKernelProfile(d),t=d.outputs)}),n&&this.addTapeNode(l,u,t,c,a,p),this.state.profiling&&this.state.activeProfile.kernels.push({name:l,bytesAdded:this.state.numBytes-r,totalBytesSnapshot:this.state.numBytes,tensorsAdded:this.state.numTensors-s,totalTensorsSnapshot:this.state.numTensors,inputShapes:Object.keys(u).map(h=>u[h]!=null?u[h].shape:null),outputShapes:t.map(h=>h.shape),kernelTimeMs:d.timeMs,extraInfo:d.extraInfo}),Array.isArray(o)?t:t[0]}saveTensorsForBackwardMode(e){return e.map(t=>this.keep(this.clone(t)))}getTensorsForGradient(e,t,a){let n=Hm(e);if(n!=null){let r=n.inputsToSave||[],s=n.outputsToSave||[],i;n.saveAllInputs?(P(Array.isArray(t),()=>\"saveAllInputs is true, expected inputs to be an array.\"),i=Object.keys(t).map(l=>t[l])):i=r.map(l=>t[l]);let o=a.filter((l,u)=>s[u]);return i.concat(o)}return[]}makeTensor(e,t,a,n){if(e==null)throw new Error(\"Values passed to engine.makeTensor() are null\");a=a||\"float32\",n=n||this.backend;let r=e;a===\"string\"&&Lr(e[0])&&(r=e.map(o=>Gd(o)));let s=n.write(r,t,a),i=new pt(t,a,s,this.nextTensorId());if(this.trackTensor(i,n),a===\"string\"){let o=this.state.tensorInfo.get(s),l=pA(r);this.state.numBytes+=l-o.bytes,o.bytes=l}return i}makeTensorFromDataId(e,t,a,n){a=a||\"float32\";let r={dataId:e,shape:t,dtype:a};return this.makeTensorFromTensorInfo(r,n)}makeTensorFromTensorInfo(e,t){let{dataId:a,shape:n,dtype:r}=e,s=new pt(n,r,a,this.nextTensorId());return this.trackTensor(s,t),s}makeVariable(e,t=!0,a,n){a=a||this.nextVariableId().toString(),n!=null&&n!==e.dtype&&(e=e.cast(n));let r=new od(e,t,a,this.nextTensorId());if(this.state.registeredVariables[r.name]!=null)throw new Error(`Variable with name ${r.name} was already registered`);return this.state.registeredVariables[r.name]=r,this.incRef(r,this.backend),r}trackTensor(e,t){this.state.numTensors++,e.dtype===\"string\"&&this.state.numStringTensors++;let a=0;e.dtype!==\"complex64\"&&e.dtype!==\"string\"&&(a=e.size*Vm(e.dtype)),this.state.numBytes+=a,this.state.tensorInfo.has(e.dataId)||(this.state.numDataBuffers++,this.state.tensorInfo.set(e.dataId,{backend:t||this.backend,dtype:e.dtype,shape:e.shape,bytes:a})),e instanceof od||this.track(e)}incRef(e,t){this.trackTensor(e,t),this.backend.incRef(e.dataId)}removeDataId(e,t){this.state.tensorInfo.has(e)&&this.state.tensorInfo.get(e).backend===t&&(this.state.tensorInfo.delete(e),this.state.numDataBuffers--)}disposeTensor(e){if(!this.state.tensorInfo.has(e.dataId))return;let t=this.state.tensorInfo.get(e.dataId);if(this.state.numTensors--,e.dtype===\"string\"&&(this.state.numStringTensors--,this.state.numBytes-=t.bytes),e.dtype!==\"complex64\"&&e.dtype!==\"string\"){let a=e.size*Vm(e.dtype);this.state.numBytes-=a}t.backend.disposeData(e.dataId)&&this.removeDataId(e.dataId,t.backend)}disposeVariables(){for(let e in this.state.registeredVariables){let t=this.state.registeredVariables[e];this.disposeVariable(t)}}disposeVariable(e){this.disposeTensor(e),this.state.registeredVariables[e.name]!=null&&delete this.state.registeredVariables[e.name]}memory(){let e=this.backend.memory();return e.numTensors=this.state.numTensors,e.numDataBuffers=this.state.numDataBuffers,e.numBytes=this.state.numBytes,this.state.numStringTensors>0&&(e.unreliable=!0,e.reasons==null&&(e.reasons=[]),e.reasons.push(\"Memory usage by string tensors is approximate (2 bytes per character)\")),e}async profile(e){this.state.profiling=!0;let t=this.state.numBytes,a=this.state.numTensors;this.state.activeProfile.kernels=[],this.state.activeProfile.result=await e(),this.state.profiling=!1,this.state.activeProfile.peakBytes=Math.max(...this.state.activeProfile.kernels.map(n=>n.totalBytesSnapshot)),this.state.activeProfile.newBytes=this.state.numBytes-t,this.state.activeProfile.newTensors=this.state.numTensors-a;for(let n of this.state.activeProfile.kernels)n.kernelTimeMs=await n.kernelTimeMs,n.extraInfo=await n.extraInfo;return this.state.activeProfile}isTapeOn(){return this.state.gradientDepth>0&&this.state.kernelDepth===0}addTapeNode(e,t,a,n,r,s){let i={id:this.state.nextTapeNodeId++,kernelName:e,inputs:t,outputs:a,saved:r},o=Hm(e);o!=null&&(n=o.gradFunc),n!=null&&(i.gradient=l=>(l=l.map((u,p)=>{if(u==null){let c=a[p],d=Gc(c.size,c.dtype);return this.makeTensor(d,c.shape,c.dtype)}return u}),n(l.length>1?l:l[0],r,s))),this.state.activeTape.push(i)}keep(e){return e.kept=!0,e}startTape(){this.state.gradientDepth===0&&(this.state.activeTape=[]),this.state.gradientDepth++}endTape(){this.state.gradientDepth--}startScope(e){let t={track:[],name:\"unnamed scope\",id:this.state.nextScopeId++};e&&(t.name=e),this.state.scopeStack.push(t),this.state.activeScope=t}endScope(e){let t=Q1(e),a=new Set(t.map(r=>r.id));for(let r=0;r<this.state.activeScope.track.length;r++){let s=this.state.activeScope.track[r];!s.kept&&!a.has(s.id)&&s.dispose()}let n=this.state.scopeStack.pop();this.state.activeScope=this.state.scopeStack.length===0?null:this.state.scopeStack[this.state.scopeStack.length-1],t.forEach(r=>{!r.kept&&r.scopeId===n.id&&this.track(r)})}gradients(e,t,a,n=!1){if(P(t.length>0,()=>\"gradients() received an empty list of xs.\"),a!=null&&a.dtype!==\"float32\")throw new Error(`dy must have 'float32' dtype, but has '${a.dtype}'`);let r=this.scopedRun(()=>this.startTape(),()=>this.endTape(),()=>this.tidy(\"forward\",e));P(r instanceof pt,()=>\"The result y returned by f() must be a tensor.\");let s=qS(this.state.activeTape,t,r);if(!n&&s.length===0&&t.length>0)throw new Error(\"Cannot compute gradient of y=f(x) with respect to x. Make sure that the f you passed encloses all operations that lead from x to y.\");return this.tidy(\"backward\",()=>{let i={};i[r.id]=a==null?sT(r.shape):a,XS(i,s,l=>this.tidy(l),iT);let o=t.map(l=>i[l.id]);return this.state.gradientDepth===0&&(this.state.activeTape.forEach(l=>{for(let u of l.saved)u.dispose()}),this.state.activeTape=null),{value:r,grads:o}})}customGrad(e){return P(Hr(e),()=>\"The f passed in customGrad(f) must be a function.\"),(...t)=>{P(t.every(i=>i instanceof pt),()=>\"The args passed in customGrad(f)(x1, x2,...) must all be tensors\");let a,n={};t.forEach((i,o)=>{n[o]=i});let r=(i,o)=>(a=e(...t,o),P(a.value instanceof pt,()=>\"The function f passed in customGrad(f) must return an object where `obj.value` is a tensor\"),P(Hr(a.gradFunc),()=>\"The function f passed in customGrad(f) must return an object where `obj.gradFunc` is a function.\"),a.value),s=(i,o)=>{let l=a.gradFunc(i,o),u=Array.isArray(l)?l:[l];P(u.length===t.length,()=>\"The function f passed in customGrad(f) must return an object where `obj.gradFunc` is a function that returns the same number of tensors as inputs passed to f(...).\"),P(u.every(c=>c instanceof pt),()=>\"The function f passed in customGrad(f) must return an object where `obj.gradFunc` is a function that returns a list of only tensors.\");let p={};return u.forEach((c,d)=>{p[d]=()=>c}),p};return this.runKernelFunc({forwardFunc:r,backwardsFunc:s,inputs:n})}}readSync(e){return this.state.tensorInfo.get(e).backend.readSync(e)}read(e){return this.state.tensorInfo.get(e).backend.read(e)}readToGPU(e,t){return this.state.tensorInfo.get(e).backend.readToGPU(e,t)}async time(e){let t=id(),a=await this.backend.time(e);return a.wallMs=id()-t,a}track(e){return this.state.activeScope!=null&&(e.scopeId=this.state.activeScope.id,this.state.activeScope.track.push(e)),e}get registeredVariables(){return this.state.registeredVariables}reset(){this.pendingBackendInitId++,this.state.dispose(),this.ENV.reset(),this.state=new W5;for(let e in this.registry)this.disposeRegisteredKernels(e),this.registry[e].dispose(),delete this.registry[e];this.backendName=null,this.backendInstance=null,this.pendingBackendInit=null}};ld.nextTensorId=0;ld.nextVariableId=0;function sT(e){let t=L1(At(e),\"float32\");return z.makeTensor(t,e,\"float32\")}function IA(){let e=gA();if(e._tfengine==null){let t=new mA(e);e._tfengine=new ld(t)}return IS(e._tfengine.ENV),JS(()=>e._tfengine),e._tfengine}var z=IA();function iT(e,t){let a={a:e,b:t};return z.runKernel(ts,a)}var jd={};Xe(jd,{isBrowser:()=>SA,isMobile:()=>uT,mockIsMobile:()=>lT});function oT(){return typeof navigator!=\"undefined\"&&navigator!=null}var Jm;function lT(e){Jm=e}function uT(e){if(Jm!==void 0)return Jm;if(e||oT()){if(e||(e=navigator),e.product===\"ReactNative\")return!0;let t=e.userAgent||e.vendor||(typeof window!=\"undefined\"?window.opera:\"\");if(!t){let a=e;return a.userAgentData&&a.userAgentData.mobile}return/(android|bb\\d+|meego).+mobile|avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(t)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\\-|your|zeto|zte\\-/i.test(t.substr(0,4))}return!1}function SA(){return typeof window!=\"undefined\"&&window.document!=null||typeof WorkerGlobalScope!=\"undefined\"}var hn=W();hn.registerFlag(\"DEBUG\",()=>!1,e=>{e&&console.warn(\"Debugging mode is ON. The output of every math call will be downloaded to CPU and checked for NaNs. This significantly impacts performance.\")});hn.registerFlag(\"IS_BROWSER\",()=>SA());hn.registerFlag(\"IS_NODE\",()=>typeof process!=\"undefined\"&&typeof process.versions!=\"undefined\"&&typeof process.versions.node!=\"undefined\");hn.registerFlag(\"IS_CHROME\",()=>typeof navigator!=\"undefined\"&&navigator!=null&&navigator.userAgent!=null&&/Chrome/.test(navigator.userAgent)&&/Google Inc/.test(navigator.vendor));hn.registerFlag(\"PROD\",()=>!1);hn.registerFlag(\"TENSORLIKE_CHECK_SHAPE_CONSISTENCY\",()=>hn.getBool(\"DEBUG\"));hn.registerFlag(\"DEPRECATION_WARNINGS_ENABLED\",()=>!0);hn.registerFlag(\"IS_TEST\",()=>!1);hn.registerFlag(\"CHECK_COMPUTATION_FOR_ERRORS\",()=>!0);hn.registerFlag(\"WRAP_TO_IMAGEBITMAP\",()=>!1);hn.registerFlag(\"CANVAS2D_WILL_READ_FREQUENTLY_FOR_GPU\",()=>!1);hn.registerFlag(\"USE_SETTIMEOUTCUSTOM\",()=>!1);function Yn(e,t){let a=e;if(da(e))return t===\"string\"?[]:[e.length];if(typeof e==\"object\"&&\"texture\"in e){let r=e.channels||\"RGBA\";return[e.height,e.width*r.length]}if(!Array.isArray(e))return[];let n=[];for(;Array.isArray(a)||da(a)&&t!==\"string\";)n.push(a.length),a=a[0];return Array.isArray(e)&&W().getBool(\"TENSORLIKE_CHECK_SHAPE_CONSISTENCY\")&&TA(e,n,[]),n}function TA(e,t,a){if(a=a||[],!Array.isArray(e)&&!da(e)){P(t.length===0,()=>`Element arr[${a.join(\"][\")}] is a primitive, but should be an array/TypedArray of ${t[0]} elements`);return}P(t.length>0,()=>`Element arr[${a.join(\"][\")}] should be a primitive, but is an array of ${e.length} elements`),P(e.length===t[0],()=>`Element arr[${a.join(\"][\")}] should have ${t[0]} elements, but has ${e.length} elements`);let n=t.slice(1);for(let r=0;r<e.length;++r)TA(e[r],n,a.concat(r))}function V5(e,t,a,n){if(e!==\"string_or_numeric\"){if(e==null)throw new Error(\"Expected dtype cannot be null.\");if(e!==\"numeric\"&&e!==t||e===\"numeric\"&&t===\"string\")throw new Error(`Argument '${a}' passed to '${n}' must be ${e} tensor, but got ${t} tensor`)}}function R(e,t,a,n=\"numeric\"){if(e instanceof pt)return V5(n,e.dtype,t,a),e;let r=Uc(e);if(r!==\"string\"&&[\"bool\",\"int32\",\"float32\"].indexOf(n)>=0&&(r=n),V5(n,r,t,a),e==null||!da(e)&&!Array.isArray(e)&&typeof e!=\"number\"&&typeof e!=\"boolean\"&&typeof e!=\"string\"){let o=e==null?\"null\":e.constructor.name;throw new Error(`Argument '${t}' passed to '${a}' must be a Tensor or TensorLike, but got '${o}'`)}let s=Yn(e,r);!da(e)&&!Array.isArray(e)&&(e=[e]);let i=r!==\"string\"?ph(e,r):zs(e,[],!0);return z.makeTensor(i,s,r)}function ud(e,t,a,n=\"numeric\"){if(!Array.isArray(e))throw new Error(`Argument ${t} passed to ${a} must be a \\`Tensor[]\\` or \\`TensorLike[]\\``);return e.map((r,s)=>R(r,`${t}[${s}]`,a,n))}var e2=\"__op\";function D(e){let t=Object.keys(e);if(t.length!==1)throw new Error(`Please provide an object with a single key (operation name) mapping to a function. Got an object with ${t.length} keys.`);let a=t[0],n=e[a];a.endsWith(\"_\")&&(a=a.substring(0,a.length-1)),a=a+e2;let r=(...s)=>{z.startScope(a);try{let i=n(...s);return B1(i)&&console.error(\"Cannot return a Promise inside of tidy.\"),z.endScope(i),i}catch(i){throw z.endScope(null),i}};return Object.defineProperty(r,\"name\",{value:a,configurable:!0}),r}function dT(e,t){let a=R(e,\"real\",\"complex\"),n=R(t,\"imag\",\"complex\");Sa(a.shape,n.shape,`real and imag shapes, ${a.shape} and ${n.shape}, must match in call to tf.complex().`);let r={real:a,imag:n};return z.runKernel(Sd,r)}var br=D({complex_:dT});function rs(e,t,a,n){if(n==null&&(n=Uc(e)),n===\"complex64\")throw new Error(\"Cannot construct a complex64 tensor directly. Please use tf.complex(real, imag).\");if(typeof e==\"object\"&&\"texture\"in e){if(n!==\"float32\"&&n!==\"int32\")throw new Error(`Creating tensor from texture only supports 'float32'|'int32' dtype, while the dtype is ${n}.`);return e.channels=e.channels||\"RGBA\",z.backend.createTensorFromTexture(e,t||a,n)}if(!da(e)&&!Array.isArray(e)&&typeof e!=\"number\"&&typeof e!=\"boolean\"&&typeof e!=\"string\")throw new Error(\"values passed to tensor(values) must be a number/boolean/string or an array of numbers/booleans/strings, or a TypedArray\");if(t!=null){Ja(t);let r=At(t),s=At(a);P(r===s,()=>`Based on the provided shape, [${t}], the tensor should have ${r} values but has ${s}`);for(let i=0;i<a.length;++i){let o=a[i],l=i===a.length-1?o!==At(t.slice(i)):!0;P(a[i]===t[i]||!l,()=>`Error creating a new Tensor. Inferred shape (${a}) does not match the provided shape (${t}). `)}}return!da(e)&&!Array.isArray(e)&&(e=[e]),t=t||a,e=n!==\"string\"?ph(e,n):zs(e,[],!0),z.makeTensor(e,t,n)}function Be(e,t,a){let n=Yn(e,a);return rs(e,t,n,a)}var Qm={float32:4,float16:2,int32:4,uint16:2,uint8:1,bool:1,complex64:8},Cc=4;async function pT(e,t){let a=[],n=[],r=Array.isArray(e)?e.map(i=>i.name):Object.keys(e);for(let i=0;i<r.length;++i){let o=r[i],l=Array.isArray(e)?e[i].tensor:e[o];if(l.dtype!==\"float32\"&&l.dtype!==\"int32\"&&l.dtype!==\"bool\"&&l.dtype!==\"string\"&&l.dtype!==\"complex64\")throw new Error(`Unsupported dtype in weight '${o}': ${l.dtype}`);let u={name:o,shape:l.shape,dtype:l.dtype};if(l.dtype===\"string\"){let p=new Promise(async c=>{let d=await l.bytes(),h=d.reduce((g,x)=>g+x.length,0)+Cc*d.length,f=new Uint8Array(h),m=0;for(let g=0;g<d.length;g++){let x=d[g],A=new Uint8Array(new Uint32Array([x.length]).buffer);f.set(A,m),m+=Cc,f.set(x,m),m+=x.length}c(f)});n.push(p)}else n.push(l.data());t!=null&&(u.group=t),a.push(u)}let s=await Promise.all(n);return{data:cT(s),specs:a}}function CA(e,t){let a={},n,r=0;for(let s of t){let i=s.name,o=s.dtype,l=s.shape,u=At(l),p;if(\"quantization\"in s){let c=s.quantization;if(c.dtype===\"uint8\"||c.dtype===\"uint16\"){if(!(\"min\"in c&&\"scale\"in c))throw new Error(`Weight ${s.name} with quantization ${c.dtype} doesn't have corresponding metadata min and scale.`)}else if(c.dtype===\"float16\"){if(o!==\"float32\")throw new Error(`Weight ${s.name} is quantized with ${c.dtype} which only supports weights of type float32 not ${o}.`)}else throw new Error(`Weight ${s.name} has unknown quantization dtype ${c.dtype}. Supported quantization dtypes are: 'uint8', 'uint16', and 'float16'.`);let d=Qm[c.dtype],h=e.slice(r,r+u*d),f=c.dtype===\"uint8\"?new Uint8Array(h):new Uint16Array(h);if(o===\"float32\")if(c.dtype===\"uint8\"||c.dtype===\"uint16\"){p=new Float32Array(f.length);for(let m=0;m<f.length;m++){let g=f[m];p[m]=g*c.scale+c.min}}else if(c.dtype===\"float16\")n===void 0&&(n=AT()),p=n(f);else throw new Error(`Unsupported quantization type ${c.dtype} for weight type float32.`);else if(o===\"int32\"){if(c.dtype!==\"uint8\"&&c.dtype!==\"uint16\")throw new Error(`Unsupported quantization type ${c.dtype} for weight type int32.`);p=new Int32Array(f.length);for(let m=0;m<f.length;m++){let g=f[m];p[m]=Math.round(g*c.scale+c.min)}}else throw new Error(`Unsupported dtype in weight '${i}': ${o}`);r+=u*d}else if(o===\"string\"){let c=At(s.shape);p=[];for(let d=0;d<c;d++){let h=new Uint32Array(e.slice(r,r+Cc))[0];r+=Cc;let f=new Uint8Array(e.slice(r,r+h));p.push(f),r+=h}}else{let c=Qm[o],d=e.slice(r,r+u*c);if(o===\"float32\")p=new Float32Array(d);else if(o===\"int32\")p=new Int32Array(d);else if(o===\"bool\")p=new Uint8Array(d);else if(o===\"complex64\"){p=new Float32Array(d);let h=new Float32Array(p.length/2),f=new Float32Array(p.length/2);for(let x=0;x<h.length;x++)h[x]=p[x*2],f[x]=p[x*2+1];let m=Be(h,l,\"float32\"),g=Be(f,l,\"float32\");a[i]=br(m,g),m.dispose(),g.dispose()}else throw new Error(`Unsupported dtype in weight '${i}': ${o}`);r+=u*c}o!==\"complex64\"&&(a[i]=Be(p,l,o))}return a}function cT(e){if(e===null)throw new Error(`Invalid input value: ${JSON.stringify(e)}`);let t=0,a=[];e.forEach(s=>{if(t+=s.byteLength,a.push(s.byteLength===s.buffer.byteLength?s:new s.constructor(s)),!(s instanceof Float32Array||s instanceof Int32Array||s instanceof Uint8Array))throw new Error(`Unsupported TypedArray subtype: ${s.constructor.name}`)});let n=new Uint8Array(t),r=0;return a.forEach(s=>{n.set(new Uint8Array(s.buffer),r),r+=s.byteLength}),n.buffer}var t2=typeof Buffer!=\"undefined\"&&(typeof Blob==\"undefined\"||typeof atob==\"undefined\"||typeof btoa==\"undefined\");function U5(e){return t2?Buffer.byteLength(e):new Blob([e]).size}function hT(e){if(t2)return Buffer.from(e).toString(\"base64\");let t=new Uint8Array(e),a=\"\";for(let n=0,r=t.length;n<r;n++)a+=String.fromCharCode(t[n]);return btoa(a)}function fT(e){if(t2){let n=Buffer.from(e,\"base64\");return n.buffer.slice(n.byteOffset,n.byteOffset+n.byteLength)}let t=atob(e),a=new Uint8Array(t.length);for(let n=0;n<t.length;++n)a.set([t.charCodeAt(n)],n);return a.buffer}function a2(e){if(e.length===1)return e[0];let t=0;e.forEach(r=>{t+=r.byteLength});let a=new Uint8Array(t),n=0;return e.forEach(r=>{a.set(new Uint8Array(r),n),n+=r.byteLength}),a.buffer}function G5(e){let t=\"/\";for(e=e.trim();e.endsWith(t);)e=e.slice(0,e.length-1);let a=e.split(t);return a[a.length-1]}function NA(e,t){let a={modelTopology:e.modelTopology,format:e.format,generatedBy:e.generatedBy,convertedBy:e.convertedBy,weightsManifest:t};return e.signature!=null&&(a.signature=e.signature),e.userDefinedMetadata!=null&&(a.userDefinedMetadata=e.userDefinedMetadata),e.modelInitializer!=null&&(a.modelInitializer=e.modelInitializer),e.initializerSignature!=null&&(a.initializerSignature=e.initializerSignature),e.trainingConfig!=null&&(a.trainingConfig=e.trainingConfig),a}function EA(e,t,a){let n={modelTopology:e.modelTopology,format:e.format,generatedBy:e.generatedBy,convertedBy:e.convertedBy};if(e.trainingConfig!=null&&(n.trainingConfig=e.trainingConfig),e.weightsManifest!=null){if(!t)throw new Error(\"modelJSON has weightsManifest but weightSpecs is null\");if(!a)throw new Error(\"modelJSON has weightsManifest but weightData is null\");n.weightSpecs=t,n.weightData=a}return e.signature!=null&&(n.signature=e.signature),e.userDefinedMetadata!=null&&(n.userDefinedMetadata=e.userDefinedMetadata),e.modelInitializer!=null&&(n.modelInitializer=e.modelInitializer),e.initializerSignature!=null&&(n.initializerSignature=e.initializerSignature),n}async function n2(e,t){let a,n;return e.weightsManifest!=null&&([a,n]=await t(e.weightsManifest)),EA(e,a,n)}function qd(e){if(e.modelTopology instanceof ArrayBuffer)throw new Error(\"Expected JSON model topology, received ArrayBuffer.\");return{dateSaved:new Date,modelTopologyType:\"JSON\",modelTopologyBytes:e.modelTopology==null?0:U5(JSON.stringify(e.modelTopology)),weightSpecsBytes:e.weightSpecs==null?0:U5(JSON.stringify(e.weightSpecs)),weightDataBytes:e.weightData==null?0:e.weightData.byteLength}}function RA(e){let t=[];for(let a of e)t.push(...a.weights);return t}function mT(){let e=a=>{let n=a<<13,r=0;for(;(n&8388608)===0;)r-=8388608,n<<=1;return n&=-8388609,r+=947912704,n|r},t=new Uint32Array(2048);t[0]=0;for(let a=1;a<1024;a++)t[a]=e(a);for(let a=1024;a<2048;a++)t[a]=939524096+(a-1024<<13);return t}function gT(){let e=new Uint32Array(64);e[0]=0,e[31]=1199570944,e[32]=2147483648,e[63]=3347054592;for(let t=1;t<31;t++)e[t]=t<<23;for(let t=33;t<63;t++)e[t]=2147483648+(t-32<<23);return e}function xT(){let e=new Uint32Array(64);for(let t=0;t<64;t++)e[t]=1024;return e[0]=e[32]=0,e}function AT(){let e=mT(),t=gT(),a=xT();return n=>{let r=new ArrayBuffer(4*n.length),s=new Uint32Array(r);for(let i=0;i<n.length;i++){let o=n[i],l=e[a[o>>10]+(o&1023)]+t[o>>10];s[i]=l}return new Float32Array(r)}}var Rt=class{constructor(){this.saveRouters=[],this.loadRouters=[]}static getInstance(){return Rt.instance==null&&(Rt.instance=new Rt),Rt.instance}static registerSaveRouter(e){Rt.getInstance().saveRouters.push(e)}static registerLoadRouter(e){Rt.getInstance().loadRouters.push(e)}static getSaveHandlers(e){return Rt.getHandlers(e,\"save\")}static getLoadHandlers(e,t){return Rt.getHandlers(e,\"load\",t)}static getHandlers(e,t,a){let n=[];return(t===\"load\"?Rt.getInstance().loadRouters:Rt.getInstance().saveRouters).forEach(r=>{let s=r(e,a);s!==null&&n.push(s)}),n}},yT=e=>Rt.registerSaveRouter(e),bT=e=>Rt.registerLoadRouter(e),vT=e=>Rt.getSaveHandlers(e),wT=(e,t)=>Rt.getLoadHandlers(e,t),e1=\"tensorflowjs\",t1=1,Fs=\"models_store\",Br=\"model_info_store\";function MA(){if(!W().getBool(\"IS_BROWSER\"))throw new Error(\"Failed to obtain IndexedDB factory because the current environmentis not a web browser.\");let e=typeof window==\"undefined\"?self:window,t=e.indexedDB||e.mozIndexedDB||e.webkitIndexedDB||e.msIndexedDB||e.shimIndexedDB;if(t==null)throw new Error(\"The current browser does not appear to support IndexedDB.\");return t}function a1(e){let t=e.result;t.createObjectStore(Fs,{keyPath:\"modelPath\"}),t.createObjectStore(Br,{keyPath:\"modelPath\"})}var Ls=class{constructor(e){if(this.indexedDB=MA(),e==null||!e)throw new Error(\"For IndexedDB, modelPath must not be null, undefined or empty.\");this.modelPath=e}async save(e){if(e.modelTopology instanceof ArrayBuffer)throw new Error(\"BrowserLocalStorage.save() does not support saving model topology in binary formats yet.\");return this.databaseAction(this.modelPath,e)}async load(){return this.databaseAction(this.modelPath)}databaseAction(e,t){return new Promise((a,n)=>{let r=this.indexedDB.open(e1,t1);r.onupgradeneeded=()=>a1(r),r.onsuccess=()=>{let s=r.result;if(t==null){let i=s.transaction(Fs,\"readonly\"),o=i.objectStore(Fs).get(this.modelPath);o.onsuccess=()=>{if(o.result==null)return s.close(),n(new Error(`Cannot find model with path '${this.modelPath}' in IndexedDB.`));a(o.result.modelArtifacts)},o.onerror=l=>(s.close(),n(o.error)),i.oncomplete=()=>s.close()}else{let i=qd(t),o=s.transaction(Br,\"readwrite\"),l=o.objectStore(Br),u=l.put({modelPath:this.modelPath,modelArtifactsInfo:i}),p;u.onsuccess=()=>{p=s.transaction(Fs,\"readwrite\");let c=p.objectStore(Fs).put({modelPath:this.modelPath,modelArtifacts:t,modelArtifactsInfo:i});c.onsuccess=()=>a({modelArtifactsInfo:i}),c.onerror=d=>{l=o.objectStore(Br);let h=l.delete(this.modelPath);h.onsuccess=()=>(s.close(),n(c.error)),h.onerror=f=>(s.close(),n(c.error))}},u.onerror=c=>(s.close(),n(u.error)),o.oncomplete=()=>{p==null?s.close():p.oncomplete=()=>s.close()}}},r.onerror=s=>n(r.error)})}};Ls.URL_SCHEME=\"indexeddb://\";var $A=e=>W().getBool(\"IS_BROWSER\")&&!Array.isArray(e)&&e.startsWith(Ls.URL_SCHEME)?kT(e.slice(Ls.URL_SCHEME.length)):null;Rt.registerSaveRouter($A);Rt.registerLoadRouter($A);function kT(e){return new Ls(e)}function IT(e){return e.startsWith(Ls.URL_SCHEME)?e.slice(Ls.URL_SCHEME.length):e}var ST=class{constructor(){this.indexedDB=MA()}async listModels(){return new Promise((e,t)=>{let a=this.indexedDB.open(e1,t1);a.onupgradeneeded=()=>a1(a),a.onsuccess=()=>{let n=a.result,r=n.transaction(Br,\"readonly\"),s=r.objectStore(Br).getAll();s.onsuccess=()=>{let i={};for(let o of s.result)i[o.modelPath]=o.modelArtifactsInfo;e(i)},s.onerror=i=>(n.close(),t(s.error)),r.oncomplete=()=>n.close()},a.onerror=n=>t(a.error)})}async removeModel(e){return e=IT(e),new Promise((t,a)=>{let n=this.indexedDB.open(e1,t1);n.onupgradeneeded=()=>a1(n),n.onsuccess=()=>{let r=n.result,s=r.transaction(Br,\"readwrite\"),i=s.objectStore(Br),o=i.get(e),l;o.onsuccess=()=>{if(o.result==null)return r.close(),a(new Error(`Cannot find model with path '${e}' in IndexedDB.`));{let u=i.delete(e),p=()=>{l=r.transaction(Fs,\"readwrite\");let c=l.objectStore(Fs).delete(e);c.onsuccess=()=>t(o.result.modelArtifactsInfo),c.onerror=d=>a(o.error)};u.onsuccess=p,u.onerror=c=>(p(),r.close(),a(o.error))}},o.onerror=u=>(r.close(),a(o.error)),s.oncomplete=()=>{l==null?r.close():l.oncomplete=()=>r.close()}},n.onerror=r=>a(n.error)})}},xr=\"/\",el=\"tensorflowjs_models\",_A=\"info\",TT=\"model_topology\",CT=\"weight_specs\",NT=\"weight_data\",ET=\"model_metadata\";function PA(e){return{info:[el,e,_A].join(xr),topology:[el,e,TT].join(xr),weightSpecs:[el,e,CT].join(xr),weightData:[el,e,NT].join(xr),modelMetadata:[el,e,ET].join(xr)}}function FA(e){for(let t of Object.values(e))window.localStorage.removeItem(t)}function RT(e){let t=e.split(xr);if(t.length<3)throw new Error(`Invalid key format: ${e}`);return t.slice(1,t.length-1).join(xr)}function MT(e){return e.startsWith(Bs.URL_SCHEME)?e.slice(Bs.URL_SCHEME.length):e}var Bs=class{constructor(e){if(!W().getBool(\"IS_BROWSER\")||typeof window==\"undefined\"||typeof window.localStorage==\"undefined\")throw new Error(\"The current environment does not support local storage.\");if(this.LS=window.localStorage,e==null||!e)throw new Error(\"For local storage, modelPath must not be null, undefined or empty.\");this.modelPath=e,this.keys=PA(this.modelPath)}async save(e){if(e.modelTopology instanceof ArrayBuffer)throw new Error(\"BrowserLocalStorage.save() does not support saving model topology in binary formats yet.\");{let t=JSON.stringify(e.modelTopology),a=JSON.stringify(e.weightSpecs),n=qd(e);try{this.LS.setItem(this.keys.info,JSON.stringify(n)),this.LS.setItem(this.keys.topology,t),this.LS.setItem(this.keys.weightSpecs,a),this.LS.setItem(this.keys.weightData,hT(e.weightData));let r={format:e.format,generatedBy:e.generatedBy,convertedBy:e.convertedBy,signature:e.signature!=null?e.signature:void 0,userDefinedMetadata:e.userDefinedMetadata!=null?e.userDefinedMetadata:void 0,modelInitializer:e.modelInitializer!=null?e.modelInitializer:void 0,initializerSignature:e.initializerSignature!=null?e.initializerSignature:void 0,trainingConfig:e.trainingConfig!=null?e.trainingConfig:void 0};return this.LS.setItem(this.keys.modelMetadata,JSON.stringify(r)),{modelArtifactsInfo:n}}catch(r){throw FA(this.keys),new Error(`Failed to save model '${this.modelPath}' to local storage: size quota being exceeded is a possible cause of this failure: modelTopologyBytes=${n.modelTopologyBytes}, weightSpecsBytes=${n.weightSpecsBytes}, weightDataBytes=${n.weightDataBytes}.`)}}}async load(){let e=JSON.parse(this.LS.getItem(this.keys.info));if(e==null)throw new Error(`In local storage, there is no model with name '${this.modelPath}'`);if(e.modelTopologyType!==\"JSON\")throw new Error(\"BrowserLocalStorage does not support loading non-JSON model topology yet.\");let t={},a=JSON.parse(this.LS.getItem(this.keys.topology));if(a==null)throw new Error(`In local storage, the topology of model '${this.modelPath}' is missing.`);t.modelTopology=a;let n=JSON.parse(this.LS.getItem(this.keys.weightSpecs));if(n==null)throw new Error(`In local storage, the weight specs of model '${this.modelPath}' are missing.`);t.weightSpecs=n;let r=this.LS.getItem(this.keys.modelMetadata);if(r!=null){let i=JSON.parse(r);t.format=i.format,t.generatedBy=i.generatedBy,t.convertedBy=i.convertedBy,i.signature!=null&&(t.signature=i.signature),i.userDefinedMetadata!=null&&(t.userDefinedMetadata=i.userDefinedMetadata),i.modelInitializer!=null&&(t.modelInitializer=i.modelInitializer),i.initializerSignature!=null&&(t.initializerSignature=i.initializerSignature),i.trainingConfig!=null&&(t.trainingConfig=i.trainingConfig)}let s=this.LS.getItem(this.keys.weightData);if(s==null)throw new Error(`In local storage, the binary weight values of model '${this.modelPath}' are missing.`);return t.weightData=fT(s),t}};Bs.URL_SCHEME=\"localstorage://\";var OA=e=>W().getBool(\"IS_BROWSER\")&&!Array.isArray(e)&&e.startsWith(Bs.URL_SCHEME)?$T(e.slice(Bs.URL_SCHEME.length)):null;Rt.registerSaveRouter(OA);Rt.registerLoadRouter(OA);function $T(e){return new Bs(e)}var _T=class{constructor(){P(W().getBool(\"IS_BROWSER\"),()=>\"Current environment is not a web browser\"),P(typeof window==\"undefined\"||typeof window.localStorage!=\"undefined\",()=>\"Current browser does not appear to support localStorage\"),this.LS=window.localStorage}async listModels(){let e={},t=el+xr,a=xr+_A;for(let n=0;n<this.LS.length;++n){let r=this.LS.key(n);if(r.startsWith(t)&&r.endsWith(a)){let s=RT(r);e[s]=JSON.parse(this.LS.getItem(r))}}return e}async removeModel(e){e=MT(e);let t=PA(e);if(this.LS.getItem(t.info)==null)throw new Error(`Cannot find model at path '${e}'`);let a=JSON.parse(this.LS.getItem(t.info));return FA(t),a}},nl=\"://\",Oa=class{constructor(){this.managers={}}static getInstance(){return Oa.instance==null&&(Oa.instance=new Oa),Oa.instance}static registerManager(e,t){P(e!=null,()=>\"scheme must not be undefined or null.\"),e.endsWith(nl)&&(e=e.slice(0,e.indexOf(nl))),P(e.length>0,()=>\"scheme must not be an empty string.\");let a=Oa.getInstance();P(a.managers[e]==null,()=>`A model store manager is already registered for scheme '${e}'.`),a.managers[e]=t}static getManager(e){let t=Oa.getInstance().managers[e];if(t==null)throw new Error(`Cannot find model manager for scheme '${e}'`);return t}static getSchemes(){return Object.keys(Oa.getInstance().managers)}};function fc(e){if(e.indexOf(nl)===-1)throw new Error(`The url string provided does not contain a scheme. Supported schemes are: ${Oa.getSchemes().join(\",\")}`);return{scheme:e.split(nl)[0],path:e.split(nl)[1]}}async function DA(e,t,a=!1){P(e!==t,()=>`Old path and new path are the same: '${e}'`);let n=Rt.getLoadHandlers(e);P(n.length>0,()=>`Copying failed because no load handler is found for source URL ${e}.`),P(n.length<2,()=>`Copying failed because more than one (${n.length}) load handlers for source URL ${e}.`);let r=n[0],s=Rt.getSaveHandlers(t);P(s.length>0,()=>`Copying failed because no save handler is found for destination URL ${t}.`),P(s.length<2,()=>`Copying failed because more than one (${n.length}) save handlers for destination URL ${t}.`);let i=s[0],o=fc(e).scheme,l=fc(e).path,u=o===fc(e).scheme,p=await r.load();a&&u&&await Oa.getManager(o).removeModel(l);let c=await i.save(p);return a&&!u&&await Oa.getManager(o).removeModel(l),c.modelArtifactsInfo}async function PT(){let e=Oa.getSchemes(),t={};for(let a of e){let n=await Oa.getManager(a).listModels();for(let r in n){let s=a+nl+r;t[s]=n[r]}}return t}async function FT(e){let t=fc(e);return Oa.getManager(t.scheme).removeModel(t.path)}async function OT(e,t){return DA(e,t,!1)}async function DT(e,t){return DA(e,t,!0)}var zT=class{constructor(){this.messageName=\"setTimeoutCustom\",this.functionRefs=[],this.handledMessageCount=0,this.hasEventListener=!1}fetch(e,t){return fetch(e,t)}now(){return performance.now()}encode(e,t){if(t!==\"utf-8\"&&t!==\"utf8\")throw new Error(`Browser's encoder only supports utf-8, but got ${t}`);return this.textEncoder==null&&(this.textEncoder=new TextEncoder),this.textEncoder.encode(e)}decode(e,t){return new TextDecoder(t).decode(e)}setTimeoutCustom(e,t){if(typeof window==\"undefined\"||!W().getBool(\"USE_SETTIMEOUTCUSTOM\")){setTimeout(e,t);return}this.functionRefs.push(e),setTimeout(()=>{window.postMessage({name:this.messageName,index:this.functionRefs.length-1},\"*\")},t),this.hasEventListener||(this.hasEventListener=!0,window.addEventListener(\"message\",a=>{if(a.source===window&&a.data.name===this.messageName){a.stopPropagation();let n=this.functionRefs[a.data.index];n(),this.handledMessageCount++,this.handledMessageCount===this.functionRefs.length&&(this.functionRefs=[],this.handledMessageCount=0)}},!0))}};if(W().get(\"IS_BROWSER\")){W().setPlatform(\"browser\",new zT);try{Oa.registerManager(Bs.URL_SCHEME,new _T)}catch(e){}try{Oa.registerManager(Ls.URL_SCHEME,new ST)}catch(e){}}var LT={importFetch:()=>GI()},Pm,BT=class{constructor(){this.util=HI(),this.textEncoder=new this.util.TextEncoder}fetch(e,t){return W().global.fetch!=null?W().global.fetch(e,t):(Pm==null&&(Pm=LT.importFetch()),Pm(e,t))}now(){let e=process.hrtime();return e[0]*1e3+e[1]/1e6}encode(e,t){if(t!==\"utf-8\"&&t!==\"utf8\")throw new Error(`Node built-in encoder only supports utf-8, but got ${t}`);return this.textEncoder.encode(e)}decode(e,t){return e.length===0?\"\":new this.util.TextDecoder(t).decode(e)}};W().get(\"IS_NODE\")&&!W().get(\"IS_BROWSER\")&&W().setPlatform(\"node\",new BT);function Me(e,t=\"float32\",a){return t=t||\"float32\",Ja(e),new jt(e,t,a)}function WT(e,t){let a=R(e,\"x\",\"cast\");if(!dA(t))throw new Error(`Failed to cast to unknown dtype ${t}`);if(t===\"string\"&&a.dtype!==\"string\"||t!==\"string\"&&a.dtype===\"string\")throw new Error(\"Only strings can be casted to strings\");let n={x:a},r={dtype:t};return z.runKernel(ti,n,r)}var He=D({cast_:WT});function VT(e){let t={x:R(e,\"x\",\"clone\",\"string_or_numeric\")};return z.runKernel(ki,t)}var wa=D({clone_:VT});function r2(e,t=!1){console.log(e.toString(t))}IA();var UT={buffer:Me,cast:He,clone:wa,print:r2};QS(UT);var jn={};Xe(jn,{browserFiles:()=>ZT,browserHTTPRequest:()=>tC,concatenateArrayBuffers:()=>a2,copyModel:()=>OT,decodeWeights:()=>CA,encodeWeights:()=>pT,fromMemory:()=>nC,fromMemorySync:()=>VA,getLoadHandlers:()=>wT,getModelArtifactsForJSON:()=>n2,getModelArtifactsForJSONSync:()=>EA,getModelArtifactsInfoForJSON:()=>qd,getSaveHandlers:()=>vT,getWeightSpecs:()=>RA,http:()=>i2,isHTTPScheme:()=>n1,listModels:()=>PT,loadWeights:()=>YT,moveModel:()=>DT,registerLoadRouter:()=>bT,registerSaveRouter:()=>yT,removeModel:()=>FT,weightsLoaderFactory:()=>LA,withSaveHandler:()=>rC,withSaveHandlerSync:()=>sC});var GT=\"model\",HT=\".json\",jT=\".weights.bin\";function H5(e){return new Promise(t=>setTimeout(t)).then(e)}var ul=class{constructor(e){if(!W().getBool(\"IS_BROWSER\"))throw new Error(\"browserDownloads() cannot proceed because the current environment is not a browser.\");e.startsWith(ul.URL_SCHEME)&&(e=e.slice(ul.URL_SCHEME.length)),(e==null||e.length===0)&&(e=GT),this.modelJsonFileName=e+HT,this.weightDataFileName=e+jT}async save(e){if(typeof document==\"undefined\")throw new Error(\"Browser downloads are not supported in this environment since `document` is not present\");let t=window.URL.createObjectURL(new Blob([e.weightData],{type:\"application/octet-stream\"}));if(e.modelTopology instanceof ArrayBuffer)throw new Error(\"BrowserDownloads.save() does not support saving model topology in binary formats yet.\");{let a=[{paths:[\"./\"+this.weightDataFileName],weights:e.weightSpecs}],n=NA(e,a),r=window.URL.createObjectURL(new Blob([JSON.stringify(n)],{type:\"application/json\"})),s=this.modelJsonAnchor==null?document.createElement(\"a\"):this.modelJsonAnchor;if(s.download=this.modelJsonFileName,s.href=r,await H5(()=>s.dispatchEvent(new MouseEvent(\"click\"))),e.weightData!=null){let i=this.weightDataAnchor==null?document.createElement(\"a\"):this.weightDataAnchor;i.download=this.weightDataFileName,i.href=t,await H5(()=>i.dispatchEvent(new MouseEvent(\"click\")))}return{modelArtifactsInfo:qd(e)}}}};ul.URL_SCHEME=\"downloads://\";var qT=class{constructor(e){if(e==null||e.length<1)throw new Error(`When calling browserFiles, at least 1 file is required, but received ${e}`);this.jsonFile=e[0],this.weightsFiles=e.slice(1)}async load(){return new Promise((e,t)=>{let a=new FileReader;a.onload=n=>{let r=JSON.parse(n.target.result),s=r.modelTopology;if(s==null){t(new Error(`modelTopology field is missing from file ${this.jsonFile.name}`));return}if(r.weightsManifest==null){t(new Error(`weightManifest field is missing from file ${this.jsonFile.name}`));return}if(this.weightsFiles.length===0){e({modelTopology:s});return}let i=n2(r,o=>this.loadWeights(o));e(i)},a.onerror=n=>t(`Failed to read model topology and weights manifest JSON from file '${this.jsonFile.name}'. BrowserFiles supports loading Keras-style tf.Model artifacts only.`),a.readAsText(this.jsonFile)})}loadWeights(e){let t=[],a=[];for(let s of e)t.push(...s.weights),a.push(...s.paths);let n=this.checkManifestAndWeightFiles(e),r=a.map(s=>this.loadWeightsFile(s,n[s]));return Promise.all(r).then(s=>[t,a2(s)])}loadWeightsFile(e,t){return new Promise((a,n)=>{let r=new FileReader;r.onload=s=>{let i=s.target.result;a(i)},r.onerror=s=>n(`Failed to weights data from file of path '${e}'.`),r.readAsArrayBuffer(t)})}checkManifestAndWeightFiles(e){let t=[],a=this.weightsFiles.map(r=>G5(r.name)),n={};for(let r of e)r.paths.forEach(s=>{let i=G5(s);if(t.indexOf(i)!==-1)throw new Error(`Duplicate file basename found in weights manifest: '${i}'`);if(t.push(i),a.indexOf(i)===-1)throw new Error(`Weight file with basename '${i}' is not provided.`);n[s]=this.weightsFiles[a.indexOf(i)]});if(t.length!==this.weightsFiles.length)throw new Error(`Mismatch in the number of files in weights manifest (${t.length}) and the number of weight files provided (${this.weightsFiles.length}).`);return n}},XT=e=>W().getBool(\"IS_BROWSER\")&&!Array.isArray(e)&&e.startsWith(ul.URL_SCHEME)?KT(e.slice(ul.URL_SCHEME.length)):null;Rt.registerSaveRouter(XT);function KT(e=\"model\"){return new ul(e)}function ZT(e){return new qT(e)}function j5(e,t,a,n){i(e),a=a==null?0:a,n=n==null?1:n,o(a,n);let r=0,s=l=>(l.then(u=>{let p=a+ ++r/e.length*(n-a);return t(p),u}),l);function i(l){P(l!=null&&Array.isArray(l)&&l.length>0,()=>\"promises must be a none empty array\")}function o(l,u){P(l>=0&&l<=1,()=>`Progress fraction must be in range [0, 1], but got startFraction ${l}`),P(u>=0&&u<=1,()=>`Progress fraction must be in range [0, 1], but got endFraction ${u}`),P(u>=l,()=>`startFraction must be no more than endFraction, but got startFraction ${l} and endFraction ${u}`)}return Promise.all(e.map(s))}async function zA(e,t){t==null&&(t={});let a=t.fetchFunc==null?W().platform.fetch:t.fetchFunc,n=e.map(u=>a(u,t.requestInit,{isBinary:!0})),r=0,s=.5,i=(t.onProgress==null?await Promise.all(n):await j5(n,t.onProgress,r,s)).map(u=>u.arrayBuffer()),o=.5,l=1;return t.onProgress==null?await Promise.all(i):await j5(i,t.onProgress,o,l)}async function YT(e,t=\"\",a,n){return LA(r=>zA(r,{requestInit:n}))(e,t,a)}function LA(e){return async(t,a=\"\",n)=>{let r=t.map(()=>!1),s={},i=n!=null?n.map(()=>!1):[],o=[];if(t.forEach((h,f)=>{let m=0;h.weights.forEach(g=>{let x=\"quantization\"in g?g.quantization.dtype:g.dtype,A=Qm[x]*At(g.shape),y=()=>{r[f]=!0,s[f]==null&&(s[f]=[]),s[f].push({manifestEntry:g,groupOffset:m,sizeBytes:A})};n!=null?n.forEach((b,w)=>{b===g.name&&(y(),i[w]=!0)}):y(),o.push(g.name),m+=A})}),!i.every(h=>h)){let h=n.filter((f,m)=>!i[m]);throw new Error(`Could not find weights in manifest with names: ${h.join(\", \")}. \nManifest JSON has weights with names: ${o.join(\", \")}.`)}let l=r.reduce((h,f,m)=>(f&&h.push(m),h),[]),u=[];l.forEach(h=>{t[h].paths.forEach(f=>{let m=a+(a.endsWith(\"/\")?\"\":\"/\")+f;u.push(m)})});let p=await e(u),c={},d=0;return l.forEach(h=>{let f=t[h].paths.length,m=0;for(let y=0;y<f;y++)m+=p[d+y].byteLength;let g=new ArrayBuffer(m),x=new Uint8Array(g),A=0;for(let y=0;y<f;y++){let b=new Uint8Array(p[d+y]);x.set(b,A),A+=b.byteLength}s[h].forEach(y=>{let b=g.slice(y.groupOffset,y.groupOffset+y.sizeBytes),w=CA(b,[y.manifestEntry]);for(let S in w)c[S]=w[S]}),d+=f}),c}}var JT=\"application/octet-stream\",QT=\"application/json\",s2=class{constructor(e,t){if(this.DEFAULT_METHOD=\"POST\",t==null&&(t={}),this.weightPathPrefix=t.weightPathPrefix,this.onProgress=t.onProgress,this.weightUrlConverter=t.weightUrlConverter,t.fetchFunc!=null?(P(typeof t.fetchFunc==\"function\",()=>\"Must pass a function that matches the signature of `fetch` (see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)\"),this.fetch=t.fetchFunc):this.fetch=W().platform.fetch,P(e!=null&&e.length>0,()=>\"URL path for http must not be null, undefined or empty.\"),Array.isArray(e)&&P(e.length===2,()=>`URL paths for http must have a length of 2, (actual length is ${e.length}).`),this.path=e,t.requestInit!=null&&t.requestInit.body!=null)throw new Error(\"requestInit is expected to have no pre-existing body, but has one.\");this.requestInit=t.requestInit||{}}async save(e){if(e.modelTopology instanceof ArrayBuffer)throw new Error(\"BrowserHTTPRequest.save() does not support saving model topology in binary formats yet.\");let t=Object.assign({method:this.DEFAULT_METHOD},this.requestInit);t.body=new FormData;let a=[{paths:[\"./model.weights.bin\"],weights:e.weightSpecs}],n=NA(e,a);t.body.append(\"model.json\",new Blob([JSON.stringify(n)],{type:QT}),\"model.json\"),e.weightData!=null&&t.body.append(\"model.weights.bin\",new Blob([e.weightData],{type:JT}),\"model.weights.bin\");let r=await this.fetch(this.path,t);if(r.ok)return{modelArtifactsInfo:qd(e),responses:[r]};throw new Error(`BrowserHTTPRequest.save() failed due to HTTP response status ${r.status}.`)}async load(){let e=await this.fetch(this.path,this.requestInit);if(!e.ok)throw new Error(`Request to ${this.path} failed with status code ${e.status}. Please verify this URL points to the model JSON of the model to load.`);let t;try{t=await e.json()}catch(r){let s=`Failed to parse model JSON of response from ${this.path}.`;throw this.path.endsWith(\".pb\")?s+=\" Your path contains a .pb file extension. Support for .pb models have been removed in TensorFlow.js 1.0 in favor of .json models. You can re-convert your Python TensorFlow model using the TensorFlow.js 1.0 conversion scripts or you can convert your.pb models with the 'pb2json'NPM script in the tensorflow/tfjs-converter repository.\":s+=\" Please make sure the server is serving valid JSON for this request.\",new Error(s)}let a=t.modelTopology,n=t.weightsManifest;if(a==null&&n==null)throw new Error(`The JSON from HTTP path ${this.path} contains neither model topology or manifest for weights.`);return n2(t,r=>this.loadWeights(r))}async loadWeights(e){let t=Array.isArray(this.path)?this.path[1]:this.path,[a,n]=eC(t),r=this.weightPathPrefix||a,s=RA(e),i=[],o=[];for(let u of e)for(let p of u.paths)this.weightUrlConverter!=null?o.push(this.weightUrlConverter(p)):i.push(r+p+n);this.weightUrlConverter&&i.push(...await Promise.all(o));let l=await zA(i,{requestInit:this.requestInit,fetchFunc:this.fetch,onProgress:this.onProgress});return[s,a2(l)]}};s2.URL_SCHEME_REGEX=/^https?:\\/\\//;function eC(e){let t=e.lastIndexOf(\"/\"),a=e.lastIndexOf(\"?\"),n=e.substring(0,t),r=a>t?e.substring(a):\"\";return[n+\"/\",r]}function n1(e){return e.match(s2.URL_SCHEME_REGEX)!=null}var BA=(e,t)=>{if(typeof fetch==\"undefined\"&&(t==null||t.fetchFunc==null))return null;{let a=!0;if(Array.isArray(e)?a=e.every(n=>n1(n)):a=n1(e),a)return i2(e,t)}return null};Rt.registerSaveRouter(BA);Rt.registerLoadRouter(BA);function i2(e,t){return new s2(e,t)}function tC(e,t){return i2(e,t)}var Fm=class{constructor(e){this.modelArtifacts=e}load(){return this.modelArtifacts}},WA=class{constructor(e){this.saveHandler=e}save(e){return this.saveHandler(e)}},aC=class{constructor(e){e.load&&(this.load=()=>Promise.resolve(e.load())),e.save&&(this.save=t=>Promise.resolve(e.save(t)))}};function nC(e,t,a,n){let r=arguments;return new aC(VA(...r))}function VA(e,t,a,n){return arguments.length===1?e.modelTopology!=null||e.weightSpecs!=null?new Fm(e):(console.warn(\"Please call tf.io.fromMemory() with only one argument. The argument should be of type ModelArtifacts. The multi-argument signature of tf.io.fromMemory() has been deprecated and will be removed in a future release.\"),new Fm({modelTopology:e})):(console.warn(\"Please call tf.io.fromMemory() with only one argument. The argument should be of type ModelArtifacts. The multi-argument signature of tf.io.fromMemory() has been deprecated and will be removed in a future release.\"),new Fm({modelTopology:e,weightSpecs:t,weightData:a,trainingConfig:n}))}function rC(e){return new WA(e)}function sC(e){return new WA(e)}var UA={};Xe(UA,{confusionMatrix:()=>wC});function iC(e,t,a=!1,n=!1){let r=R(e,\"a\",\"matMul\"),s=R(t,\"b\",\"matMul\");[r,s]=St(r,s);let i={a:r,b:s},o={transposeA:a,transposeB:n};return z.runKernel(ei,i,o)}var st=D({matMul_:iC});function oC(e,t,a=1,n=0,r=\"int32\"){if(t<2)throw new Error(`Error in oneHot: depth must be >=2, but it is ${t}`);let s={indices:R(e,\"indices\",\"oneHot\",\"int32\")},i={dtype:r,depth:t,onValue:a,offValue:n};return z.runKernel(Vi,s,i)}var Nc=D({oneHot_:oC});function o2(){W().set(\"PROD\",!0)}function lC(){W().set(\"DEBUG\",!0)}function uC(){W().set(\"DEPRECATION_WARNINGS_ENABLED\",!1),console.warn(\"TensorFlow.js deprecation warnings have been disabled.\")}function l2(e){W().getBool(\"DEPRECATION_WARNINGS_ENABLED\")&&console.warn(e+\" You can disable deprecation warnings with tf.disableDeprecationWarnings().\")}eT(l2);function dC(){z.disposeVariables()}function kt(){return z}function pC(){return z.memory()}function cC(e){return z.profile(e)}function $e(e,t){return z.tidy(e,t)}function Y(e){Q1(e).forEach(t=>t.dispose())}function On(e){return z.keep(e)}function hC(e){return z.time(e)}function Xd(e){return z.setBackend(e)}function Kd(){return z.ready()}function ia(){return z.backendName}function fC(e){z.removeBackend(e)}function u2(e){return z.findBackend(e)}function mC(e){return z.findBackendFactory(e)}function go(e,t,a=1){return z.registerBackend(e,t,a)}function tr(){return z.backend}function gC(e,t){W().setPlatform(e,t)}function xC(e){let t={input:R(e,\"input\",\"imag\")};return z.runKernel(Rd,t)}var Zd=D({imag_:xC});function AC(e){let t={x:R(e,\"x\",\"neg\")};return z.runKernel(Vl,t)}var Xn=D({neg_:AC});function yC(e){let t={input:R(e,\"input\",\"real\")};return z.runKernel(Md,t)}var dl=D({real_:yC});function bC(e,t,a){let n=R(e,\"x\",\"transpose\");if(t==null&&(t=n.shape.map((i,o)=>o).reverse()),P(n.rank===t.length,()=>`Error in transpose: rank of input ${n.rank} must match length of perm ${t}.`),t.forEach(i=>{P(i>=0&&i<n.rank,()=>`All entries in 'perm' must be between 0 and ${n.rank-1} but got ${t}`)}),n.rank<=1)return n.clone();let r={x:n},s={perm:t};return n.dtype===\"complex64\"?$e(()=>{let i=dl(n),o=Zd(n);return i=z.runKernel(Ar,{x:i},s),o=z.runKernel(Ar,{x:o},s),a&&(o=Xn(o)),br(i,o)}):z.runKernel(Ar,r,s)}var Ws=D({transpose_:bC});function vC(e,t,a){let n=R(e,\"labels\",\"confusionMatrix\"),r=R(t,\"predictions\",\"confusionMatrix\");P(a==null||a>0&&Number.isInteger(a),()=>`If provided, numClasses must be a positive integer, but got ${a}`),P(n.rank===1,()=>`Expected the rank of labels to be 1, but got ${n.rank}`),P(r.rank===1,()=>`Expected the rank of predictions to be 1, but got ${r.rank}`),P(n.shape[0]===r.shape[0],()=>`Mismatch in the number of examples: ${n.shape[0]} vs. ${r.shape[0]}. Labels and predictions should have the same number of elements.`),P(a>0&&Number.isInteger(a),()=>`numClasses is required to be a positive integer, but got ${a}`);let s=Nc(He(n,\"int32\"),a),i=Nc(He(r,\"int32\"),a),o=Ws(s),l=st(o,i);return He(l,\"int32\")}var wC=D({confusionMatrix_:vC}),xo={};Xe(xo,{assertAndGetBroadcastShape:()=>zt,getBroadcastDims:()=>GA,getReductionAxes:()=>d2});function GA(e,t){let a=e.length,n=[];for(let r=0;r<a;r++){let s=a-1-r,i=e[s]||1;(t[t.length-1-r]||1)>1&&i===1&&n.unshift(s)}return n}function d2(e,t){let a=[];for(let n=0;n<t.length;n++){let r=e[e.length-n-1],s=t.length-n-1,i=t[s];(r==null||r===1&&i>1)&&a.unshift(s)}return a}function zt(e,t){let a=[],n=Math.max(e.length,t.length);for(let r=0;r<n;r++){let s=e[e.length-r-1];s==null&&(s=1);let i=t[t.length-r-1];if(i==null&&(i=1),s===1)a.unshift(i);else if(i===1)a.unshift(s);else if(s!==i){let o=`Operands could not be broadcast together with shapes ${e} and ${t}.`;throw Error(o)}else a.unshift(s)}return a}var wr={};Xe(wr,{fromPixels:()=>EC,fromPixelsAsync:()=>CC,toPixels:()=>NC});function p2(e,t,a){if(Xs(e),t!=null&&t.length!==3)throw new Error(\"tensor3d() requires shape to have three numbers\");let n=Yn(e,a);if(n.length!==3&&n.length!==1)throw new Error(\"tensor3d() requires values to be number[][][] or flat/TypedArray\");if(n.length===1&&t==null)throw new Error(\"tensor3d() requires shape to be provided when `values` are a flat array\");return rs(e,t,n,a)}var Ns;function HA(e,t=3){if(t>4)throw new Error(\"Cannot construct Tensor with more than 4 channels from pixels.\");if(e==null)throw new Error(\"pixels passed to tf.browser.fromPixels() can not be null\");let a=!1,n=!1,r=!1,s=!1,i=!1,o=!1;if(e.data instanceof Uint8Array)a=!0;else if(typeof ImageData!=\"undefined\"&&e instanceof ImageData)n=!0;else if(typeof HTMLVideoElement!=\"undefined\"&&e instanceof HTMLVideoElement)r=!0;else if(typeof HTMLImageElement!=\"undefined\"&&e instanceof HTMLImageElement)s=!0;else if(e.getContext!=null)i=!0;else if(typeof ImageBitmap!=\"undefined\"&&e instanceof ImageBitmap)o=!0;else throw new Error(`pixels passed to tf.browser.fromPixels() must be either an HTMLVideoElement, HTMLImageElement, HTMLCanvasElement, ImageData in browser, or OffscreenCanvas, ImageData in webworker or {data: Uint32Array, width: number, height: number}, but was ${e.constructor.name}`);if(Sc(rd,z.backendName)!=null){let d={pixels:e},h={numChannels:t};return z.runKernel(rd,d,h)}let[l,u]=r?[e.videoWidth,e.videoHeight]:[e.width,e.height],p;if(i)p=e.getContext(\"2d\").getImageData(0,0,l,u).data;else if(n||a)p=e.data;else if(s||r||o){if(Ns==null)if(typeof document==\"undefined\")if(typeof OffscreenCanvas!=\"undefined\"&&typeof OffscreenCanvasRenderingContext2D!=\"undefined\")Ns=new OffscreenCanvas(1,1).getContext(\"2d\");else throw new Error(\"Cannot parse input in current context. Reason: OffscreenCanvas Context2D rendering is not supported.\");else Ns=document.createElement(\"canvas\").getContext(\"2d\",{willReadFrequently:!0});Ns.canvas.width=l,Ns.canvas.height=u,Ns.drawImage(e,0,0,l,u),p=Ns.getImageData(0,0,l,u).data}let c;if(t===4)c=new Int32Array(p);else{let d=l*u;c=new Int32Array(d*t);for(let h=0;h<d;h++)for(let f=0;f<t;++f)c[h*t+f]=p[h*4+f]}return p2(c,[u,l,t],\"int32\")}function kC(e){return e!=null&&e.data instanceof Uint8Array}function IC(){return typeof window!=\"undefined\"&&typeof ImageBitmap!=\"undefined\"&&window.hasOwnProperty(\"createImageBitmap\")}function SC(e){return e!=null&&e.width!==0&&e.height!==0}function TC(e){return IC()&&!(e instanceof ImageBitmap)&&SC(e)&&!kC(e)}async function CC(e,t=3){let a=null;if(W().getBool(\"WRAP_TO_IMAGEBITMAP\")&&TC(e)){let n;try{n=await createImageBitmap(e,{premultiplyAlpha:\"none\"})}catch(r){n=null}n!=null&&n.width===e.width&&n.height===e.height?a=n:a=e}else a=e;return HA(a,t)}async function NC(e,t){let a=R(e,\"img\",\"toPixels\");if(!(e instanceof pt)){let u=a;a=He(u,\"int32\"),u.dispose()}if(a.rank!==2&&a.rank!==3)throw new Error(`toPixels only supports rank 2 or 3 tensors, got rank ${a.rank}.`);let[n,r]=a.shape.slice(0,2),s=a.rank===2?1:a.shape[2];if(s>4||s===2)throw new Error(`toPixels only supports depth of size 1, 3 or 4 but got ${s}`);if(a.dtype!==\"float32\"&&a.dtype!==\"int32\")throw new Error(`Unsupported type for toPixels: ${a.dtype}. Please use float32 or int32 tensors.`);let i=await a.data(),o=a.dtype===\"float32\"?255:1,l=new Uint8ClampedArray(r*n*4);for(let u=0;u<n*r;++u){let p=[0,0,0,255];for(let d=0;d<s;d++){let h=i[u*s+d];if(a.dtype===\"float32\"){if(h<0||h>1)throw new Error(`Tensor values for a float32 Tensor must be in the range [0 - 1] but encountered ${h}.`)}else if(a.dtype===\"int32\"&&(h<0||h>255))throw new Error(`Tensor values for a int32 Tensor must be in the range [0 - 255] but encountered ${h}.`);s===1?(p[0]=h*o,p[1]=h*o,p[2]=h*o):p[d]=h*o}let c=u*4;l[c+0]=Math.round(p[0]),l[c+1]=Math.round(p[1]),l[c+2]=Math.round(p[2]),l[c+3]=Math.round(p[3])}if(t!=null){t.width=r,t.height=n;let u=t.getContext(\"2d\"),p=new ImageData(l,r,n);u.putImageData(p,0,0)}return a!==e&&a.dispose(),l}var EC=D({fromPixels_:HA}),c2={};Xe(c2,{prepareAndValidate:()=>jA});function jA(e,t){let a=e.shape.length,n=t.shape.length;if(a<1)throw new Error(`tf.gatherND() expects the input to be rank 1 or higher, but the rank was ${a}.`);if(n<1)throw new Error(`tf.gatherND() expects the indices to be rank 1 or higher, but the rank was ${n}.`);if(t.dtype!==\"int32\")throw new Error(`tf.gatherND() expects the indices to be int32 type, but the dtype was ${t.dtype}.`);if(t.shape[n-1]>a)throw new Error(`index innermost dimension length must be <= tensor rank; saw: ${t.shape[n-1]} vs. ${a}`);if(At(e.shape)===0)throw new Error(`Requested more than 0 entries, but input is empty. Input shape: ${e.shape}.`);let r=t.shape,s=r[r.length-1],i=1;for(let c=0;c<r.length-1;++c)i*=r[c];let o=e.shape,l=r.slice();l.pop();let u=1;for(let c=s;c<a;++c)u*=o[c],l.push(o[c]);let p=[...vl(e.shape).map(c=>c/u),1].slice(0,s);return[l,i,u,p]}var h2={};Xe(h2,{calculateShapes:()=>qA,validateInput:()=>m2,validateUpdateShape:()=>f2});function f2(e,t,a){let n=t.rank>1?t.shape[t.rank-1]:1,r=t.rank>1?t.rank-1:1,s=`Must have updates.shape = indices.shape[:batchDim] + shape[sliceDim:], got updates.shape: ${a.shape}, indices.shape: ${t.shape}, shape: ${e}, sliceDim: ${n}, and batchDim: ${r}.`;if(a.rank<r)throw new Error(s+` update.rank < ${r}. `);if(e.length<n+(a.rank-r))throw new Error(s+` Output shape length < ${n+(a.rank-r)}`);if(a.rank!==r+e.length-n)throw new Error(s+` update.rank != ${r+e.length-n}`);for(let i=0;i<r;++i)if(a.shape[i]!==t.shape[i])throw new Error(s+` updates.shape[${i}] (${a.shape[i]}) != indices.shape[${i}] (${t.shape[i]}).`);for(let i=0;i<a.rank-r;++i)if(a.shape[i+r]!==e[i+n])throw new Error(s+` updates.shape[${i+r}] (${a.shape[i+r]}) != shape[${i+r}] (${e[i+r]})`)}function m2(e,t,a){if(t.rank<1)throw new Error(`tf.scatterND() expects the indices to be rank 1 or higher, but the rank was ${t.rank}.`);if(e.rank<1)throw new Error(`tf.scatterND() expects the updates to be rank 1 or higher, but the rank was ${e.rank}.`);if(t.dtype!==\"int32\")throw new Error(`The dtype of 'indices' should be int32, but got dtype: ${t.dtype}`);if(a.length<1)throw new Error(`Output rank must be greater or equal to 1, but got shape: ${a}`);if(a.length===0){if(t.size===0)throw new Error(`Indices specified for empty output. indices shape: ${t.shape}`);if(e.size===0)throw new Error(`Updates specified for empty output. updates shape: ${e.shape}`)}f2(a,t,e)}function qA(e,t,a){let n=t.shape.length,r=n>1?t.shape[n-1]:1,s=a.length,i=1;for(let c=r;c<s;++c)i*=a[c];let o=r<1?1:r,l=At(t.shape)/o,u=[...vl(a.slice(0,r)),1],p=At(a);return{sliceRank:r,numUpdates:l,sliceSize:i,strides:u,outputSize:p}}var It={};Xe(It,{assertParamsValid:()=>MC,computeFlatOffset:()=>OC,computeOutShape:()=>_C,getNormalizedAxes:()=>PC,isSliceContinous:()=>FC,maskToAxes:()=>$C,parseSliceParams:()=>DC,sliceInfo:()=>zC,startForAxis:()=>ey,startIndicesWithElidedDims:()=>YA,stopForAxis:()=>ty,stopIndicesWithElidedDims:()=>JA,stridesForAxis:()=>QA,stridesWithElidedDims:()=>XA});var r1=-2,RC=-1;function MC(e,t,a){let n=e.shape.length;P(n===t.length,()=>`Error in slice${n}D: Length of begin ${t} must match the rank of the array (${n}).`),P(n===a.length,()=>`Error in slice${n}D: Length of size ${a} must match the rank of the array (${n}).`);for(let r=0;r<n;++r)P(t[r]+a[r]<=e.shape[r],()=>`Error in slice${n}D: begin[${r}] + size[${r}] (${t[r]+a[r]}) would overflow input.shape[${r}] (${e.shape[r]})`)}function $C(e){let t=[],a=0;for(;e>0;)e&1&&t.push(a),e/=2,a++;return t}function _C(e,t,a){let n=[];for(let r=0;r<e.length;r++)n[r]=Math.ceil((t[r]-e[r])/a[r]);return n}function XA(e,t,a,n){let r=[...e];for(let s=r.length;s<n.length;s++)r.push(1);for(let s=0;s<a;s++)s===0?r[t]=1:(r.splice(t,0,1),r.pop());return r}function KA(e,t,a){return a<=e?a:a-(t-1)}function ZA(e,t){let a=[];for(let n=0;n<e;n++)a.push(t+n);return a}function PC(e,t,a,n,r,s,i,o,l){let u=e.length,p=new Array(u),c=new Array(u),d=new Array(u);if(t.length&&a>0){let h=t[0],f=a+1;p=YA(i,h,f,n,e),c=JA(o,h,f,r,e),d=XA(s,h,f,e)}else for(let h=0;h<u;h++)p[h]=ey(i,n,s,e,h,l),c[h]=ty(o,r,s,e,h,l),d[h]=QA(s,h,l);return{begin:p,end:c,strides:d}}function YA(e,t,a,n,r){let s=[...r],i=ZA(a,t);for(let o=0;o<s.length;o++)if(i.indexOf(o)>-1)s[o]=0;else{let l=KA(t,a,o),u=n[l];e&1<<l&&(u=0),s[o]=u}return s}function JA(e,t,a,n,r){let s=[...r],i=ZA(a,t);for(let o=0;o<s.length;o++)if(i.indexOf(o)>-1)s[o]=Number.MAX_SAFE_INTEGER;else{let l=KA(t,a,o),u=n[l];e&1<<l&&(u=Number.MAX_SAFE_INTEGER),s[o]=u}for(let o=0;o<s.length;o++){let l=r[o];s[o]<0&&(s[o]+=l),s[o]=nd(0,s[o],r[o])}return s}function QA(e,t,a){let n=e[t];return(a&1<<t||n==null)&&(n=1),n}function ey(e,t,a,n,r,s){let i=t[r],o=a[r]||1;(e&1<<r||s&1<<r||i==null)&&(o>0?i=Number.MIN_SAFE_INTEGER:i=Number.MAX_SAFE_INTEGER);let l=n[r];return i<0&&(i+=l),i=nd(0,i,l-1),i}function ty(e,t,a,n,r,s){let i=t[r],o=a[r]||1;(e&1<<r||s&1<<r||i==null)&&(o>0?i=Number.MAX_SAFE_INTEGER:i=Number.MIN_SAFE_INTEGER);let l=n[r];return i<0&&(i+=l),o>0?i=nd(0,i,l):i=nd(-1,i,l-1),i}function FC(e,t,a){let n=a.length;for(let r=0;r<a.length;r++)if(a[r]>1){n=r;break}for(let r=n+1;r<a.length;r++)if(t[r]>0||a[r]!==e[r])return!1;return!0}function OC(e,t){let a=e.length>0?e[e.length-1]:1;for(let n=0;n<e.length-1;n++)a+=e[n]*t[n];return a}function DC(e,t,a){let n,r=e.shape.length;typeof t==\"number\"?n=[t,...new Array(r-1).fill(0)]:t.length<r?n=t.concat(new Array(r-t.length).fill(0)):n=t.slice(),n.forEach(i=>{P(i!==-1,()=>\"slice() does not support negative begin indexing.\")});let s;return a==null?s=new Array(r).fill(-1):typeof a==\"number\"?s=[a,...new Array(r-1).fill(-1)]:a.length<r?s=a.concat(new Array(r-a.length).fill(-1)):s=a,s=s.map((i,o)=>i>=0?i:(P(i===-1,()=>`Negative size values should be exactly -1 but got ${i} for the slice() size at index ${o}.`),e.shape[o]-n[o])),[n,s]}function zC(e,t,a,n,r,s,i,o,l){let u;if(n==null?(u=new Array(t.length),u.fill(1)):u=n,i!=null&&(i&i-1)!==0)throw new Error(\"Multiple ellipses in slice is not allowed.\");let p=!1,c={dims:u.length,numAddAxisAfterEllipsis:0,begin:t.slice(),end:a.slice(),strides:u.slice(),beginMask:r,endMask:s,ellipsisMask:i,newAxisMask:o,shrinkAxisMask:l};for(let A=0;A<c.dims;A++)p&&(1<<A&o)!==0&&c.numAddAxisAfterEllipsis++,1<<A&i&&(p=!0);p||(c.ellipsisMask|=1<<c.dims,c.dims++);let d={dims:e.length,beginMask:0,endMask:0,beginValid:!1,endValid:!1};LC(c,d);let h=!0,f=!0,m=!0,g=[],x=[];for(let A=0;A<e.length;++A){if(d.strides[A]===0)throw Error(`strides[${A}] must be non-zero`);let y=!!(d.shrinkAxisMask&1<<A),b=e[A];if(b===-1){g.push(y?1:-1);continue}let w=[d.beginMask&1<<A,d.endMask&1<<A],S=[d.strides[A]>0?0:-1,d.strides[A]>0?b:b-1];if(y&&d.strides[A]<=0)throw Error(\"only stride 1 allowed on non-range indexing.\");m=m&&d.strides[A]===1;let C=!!(d.beginMask&1<<A&&d.endMask&1<<A);if(d.beginValid&&d.endValid){if(y){let M=d.begin[A]<0?b+d.begin[A]:d.begin[A];if(d.begin[A]=M,d.end[A]=d.begin[A]+1,M<0||M>=b)throw Error(`slice index ${d.begin[A]} of dimension ${A} out of bounds.`)}else d.begin[A]=q5(d.begin[A],0,d.strides[A],b,w,S),d.end[A]=q5(d.end[A],1,d.strides[A],b,w,S);let $=d.strides[A]===1&&d.begin[A]===0&&d.end[A]===b;h=h&&$,f=f&&(A===0&&d.strides[A]===1||$)}else h=h&&d.strides[A]===1&&C,f=f&&(A===0&&d.strides[A]===1||C);let E,_=!1;if(d.beginValid&&d.endValid?(E=d.end[A]-d.begin[A],_=!0):y?(E=1,_=!0):C&&b>=0&&(d.strides[A]<0?E=-b:E=b,_=!0),_){let $;E===0||E<0!=d.strides[A]<0?$=0:$=Math.trunc(E/d.strides[A])+(E%d.strides[A]!==0?1:0),g.push($)}else g.push(-1)}for(let A=0;A<d.finalShapeGatherIndices.length;++A){let y=d.finalShapeGatherIndices[A];y>=0?x.push(g[y]):y===r1&&x.push(1)}return{finalShapeSparse:x.filter((A,y)=>d.finalShapeGatherIndices[y]!==r1),finalShape:x,isIdentity:h,sliceDim0:f,isSimpleSlice:m,begin:d.begin,end:d.end,strides:d.strides}}function LC(e,t){t.beginMask=0,t.endMask=0,t.shrinkAxisMask=0;let a=0;t.beginValid=e.begin!=null,t.endValid=e.end!=null,t.begin=new Array(t.dims),t.end=new Array(t.dims),t.strides=new Array(t.dims),t.finalShapeGatherIndices=[],t.finalShapeGatherIndicesSparse=[],t.inputShapeGatherIndicesSparse=new Array(t.dims);for(let n=0;n<e.dims;n++)if(1<<n&e.ellipsisMask){let r=Math.min(t.dims-(e.dims-n)+1+e.numAddAxisAfterEllipsis,t.dims);for(;a<r;a++)t.begin[a]=0,t.end[a]=0,t.strides[a]=1,t.beginMask|=1<<a,t.endMask|=1<<a,t.finalShapeGatherIndices.push(a),t.finalShapeGatherIndicesSparse.push(-1),t.inputShapeGatherIndicesSparse[a]=n}else if(1<<n&e.newAxisMask)t.finalShapeGatherIndices.push(r1),t.finalShapeGatherIndicesSparse.push(-1);else{if(a===t.begin.length)throw Error(`Index out of range using input dim ${a}; input has only ${t.dims} dims, ${t.begin.length}.`);e.begin!=null&&(t.begin[a]=e.begin[n]),e.end!=null&&(t.end[a]=e.end[n]),t.strides[a]=e.strides[n],e.beginMask&1<<n&&(t.beginMask|=1<<a),e.endMask&1<<n&&(t.endMask|=1<<a),e.shrinkAxisMask&1<<n?(t.finalShapeGatherIndices.push(RC),t.finalShapeGatherIndicesSparse.push(-1),t.shrinkAxisMask|=1<<a):(t.finalShapeGatherIndices.push(a),t.finalShapeGatherIndicesSparse.push(n)),t.inputShapeGatherIndicesSparse[a]=n,a++}}function q5(e,t,a,n,r,s){if(r[t])return a>0?s[t]:s[t+1&1];{let i=e<0?n+e:e;return i<s[0]?s[0]:i>s[1]?s[1]:i}}var ay={};Xe(ay,{Serializable:()=>ny,SerializationMap:()=>_s,registerClass:()=>ss});var ny=class{getClassName(){return this.constructor.className}static fromConfig(e,t){return new e(t)}},_s=class{constructor(){this.classNameMap={}}static getMap(){return _s.instance==null&&(_s.instance=new _s),_s.instance}static register(e){_s.getMap().classNameMap[e.className]=[e,e.fromConfig]}};function ss(e){P(e.className!=null,()=>\"Class being registered does not have the static className property defined.\"),P(typeof e.className==\"string\",()=>\"className is required to be a string, but got type \"+typeof e.className),P(e.className.length>0,()=>\"Class being registered has an empty-string as its className, which is disallowed.\"),_s.register(e)}var ry={};Xe(ry,{TEST_EPSILON_FLOAT16:()=>sy,createVideoElement:()=>qC,encodeStrings:()=>iy,expectArrayBuffersEqual:()=>jC,expectArraysClose:()=>WC,expectArraysEqual:()=>UC,expectNumbersClose:()=>GC,expectPromiseToFail:()=>VC,expectValuesInRange:()=>HC,play:()=>XC,testEpsilon:()=>g2});var BC=.001,sy=.1;function WC(e,t,a){return a==null&&(a=g2()),s1(e,t,(n,r)=>x2(n,r,a))}function g2(){return z.backend.floatPrecision()===32?BC:sy}function s1(e,t,a){let n=!0;if((da(e)||da(t))&&(n=!1),da(e)&&da(t)&&(n=!0),n){let i=e.constructor.name,o=t.constructor.name;if(i!==o)throw new Error(`Arrays are of different type. Actual: ${i}. Expected: ${o}`)}if(Array.isArray(e)&&Array.isArray(t)){let i=Yn(e),o=Yn(t);if(!es(i,o))throw new Error(`Arrays have different shapes. Actual: [${i}]. Expected: [${o}]`)}let r=da(e)?e:zs(e),s=da(t)?t:zs(t);if(r.length!==s.length)throw new Error(`Arrays have different lengths actual: ${r.length} vs expected: ${s.length}.\nActual:   ${r}.\nExpected: ${s}.`);for(let i=0;i<s.length;++i){let o=r[i],l=s[i];if(!a(o,l))throw new Error(`Arrays differ: actual[${i}] = ${o}, expected[${i}] = ${l}.\nActual:   ${r}.\nExpected: ${s}.`)}typeof expect!=\"undefined\"&&expect().nothing()}function VC(e,t){e().then(()=>t.fail(),()=>t()),typeof expect!=\"undefined\"&&expect().nothing()}function UC(e,t){let a=typeof t==\"string\"||typeof t==\"number\"||typeof t==\"boolean\"?[t]:t;return Lr(e)||Lr(e[0])||Lr(t)||Lr(t[0])?s1(e,a,(n,r)=>n==r):s1(e,t,(n,r)=>x2(n,r,0))}function GC(e,t,a){if(a==null&&(a=g2()),!x2(e,t,a))throw new Error(`Numbers differ: actual === ${e}, expected === ${t}`);typeof expect!=\"undefined\"&&expect().nothing()}function x2(e,t,a){return!isFinite(e)&&!isFinite(t)?!0:!(isNaN(e)||isNaN(t)||Math.abs(e-t)>a)}function HC(e,t,a){for(let n=0;n<e.length;n++)if(e[n]<t||e[n]>a)throw new Error(`Value out of range:${e[n]} low: ${t}, high: ${a}`)}function jC(e,t){let a=new Float32Array(e),n=new Float32Array(t);if(a.length!==n.length)throw new Error(`Expected ArrayBuffer to be of length ${n.length}, but it was ${a.length}`);for(let r=0;r<n.length;r++)if(a[r]!==n[r])throw new Error(`Expected ArrayBuffer value at ${r} to be ${n[r]} but got ${a[r]} instead`)}function iy(e){for(let t=0;t<e.length;t++){let a=e[t];Array.isArray(a)?iy(a):e[t]=Gd(a)}return e}function qC(e){let t=document.createElement(\"video\");return\"playsInline\"in t&&(t.playsInline=!0),t.muted=!0,t.loop=!0,t.style.position=\"fixed\",t.style.left=\"0px\",t.style.top=\"0px\",t.preload=\"auto\",t.appendChild(e),new Promise(a=>{t.addEventListener(\"loadeddata\",n=>a(t)),t.load()})}async function XC(e){await e.play(),\"requestVideoFrameCallback\"in e&&await new Promise(t=>{e.requestVideoFrameCallback(t)})}var A2=\"4.1.0\";function KC(e,t){let a=R(e,\"a\",\"add\"),n=R(t,\"b\",\"add\");[a,n]=St(a,n);let r={a,b:n};return z.runKernel(ts,r)}var be=D({add_:KC});function ZC(e,t){let a=R(e,\"a\",\"floorDiv\"),n=R(t,\"b\",\"floorDiv\");[a,n]=St(a,n);let r={a,b:n};return z.runKernel(Ai,r)}var Yd=D({floorDiv_:ZC});function YC(e,t){let a=R(e,\"a\",\"div\"),n=R(t,\"b\",\"div\");if([a,n]=St(a,n),a.dtype===\"int32\"&&n.dtype===\"int32\")return Yd(a,n);let r={a,b:n},s={};return z.runKernel(ci,r,s)}var me=D({div_:YC});function JC(e,t){let a=R(e,\"a\",\"mul\"),n=R(t,\"b\",\"mul\");[a,n]=St(a,n);let r={a,b:n};return z.runKernel(zi,r)}var ae=D({mul_:JC});function QC(e){let t=R(e,\"x\",\"abs\");if(t.dtype===\"complex64\"){let a={x:t};return z.runKernel(qc,a)}else{let a={x:t};return z.runKernel(wl,a)}}var qa=D({abs_:QC});function eN(e){let t={x:R(e,\"x\",\"acos\")};return z.runKernel(kl,t)}var oy=D({acos_:eN});function tN(e){let t={x:R(e,\"x\",\"acosh\")};return z.runKernel(Il,t)}var ly=D({acosh_:tN});function aN(e){P(Array.isArray(e),()=>\"The argument passed to tf.addN() must be a list of tensors\"),P(e.length>=1,()=>`Must pass at least one tensor to tf.addN(), but got ${e.length}`);let t=e.map((r,s)=>R(r,`tensors${s}`,\"addN\")),a=t[0];t.forEach(r=>{if(r.dtype!==a.dtype)throw new Error(\"All tensors passed to tf.addN() must have the same dtype\")}),t.forEach(r=>{if(!es(r.shape,a.shape))throw new Error(\"All tensors passed to tf.addN() must have the same shape\")});let n=t;return z.runKernel(Ks,n)}var ch=D({addN_:aN});function nN(e,t=null,a=!1){let n={x:R(e,\"x\",\"all\",\"bool\")},r={axis:t,keepDims:a};return z.runKernel(Zs,n,r)}var uy=D({all_:nN});function rN(e,t=null,a=!1){let n={x:R(e,\"x\",\"any\",\"bool\")},r={axis:t,keepDims:a};return z.runKernel(Ys,n,r)}var dy=D({any_:rN});function sN(e,t=0){let a={x:R(e,\"x\",\"argMax\")},n={axis:t};return z.runKernel(Js,a,n)}var ar=D({argMax_:sN});function iN(e,t=0){let a={x:R(e,\"x\",\"argMin\")},n={axis:t};return z.runKernel(kd,a,n)}var py=D({argMin_:iN});function oN(e){let t={x:R(e,\"x\",\"asin\")};return z.runKernel(Sl,t)}var cy=D({asin_:oN});function lN(e){let t={x:R(e,\"x\",\"asinh\")};return z.runKernel(Tl,t)}var hy=D({asinh_:lN});function uN(e){let t={x:R(e,\"x\",\"atan\")};return z.runKernel(Cl,t)}var fy=D({atan_:uN});function dN(e,t){let a=R(e,\"a\",\"atan2\"),n=R(t,\"b\",\"atan2\");[a,n]=St(a,n);let r={a,b:n};return z.runKernel(El,r)}var my=D({atan2_:dN});function pN(e){let t={x:R(e,\"x\",\"atanh\")};return z.runKernel(Nl,t)}var gy=D({atanh_:pN});function cN(e,t,a,n,r=\"NHWC\",s){let i=e[3],o=[...t,i],l=yy(r);return Jd(e,o,a,s,n,null,null,l)}function xy(e,t,a,n,r,s,i=\"channelsLast\"){let[o,l]=Ec(t),u;if(i===\"channelsLast\")u=[o,l,e[3],e[3]];else if(i===\"channelsFirst\")u=[o,l,e[1],e[1]];else throw new Error(`Unknown dataFormat ${i}`);return Jd(e,u,a,n,r,s,!1,i)}function hN(e,t,a,n,r,s,i=\"NDHWC\"){let[o,l,u]=i1(t),p,c;if(i===\"NDHWC\")c=\"channelsLast\",p=[o,l,u,e[4],e[4]];else if(i===\"NCDHW\")c=\"channelsFirst\",p=[o,l,u,e[1],e[1]];else throw new Error(`Unknown dataFormat ${i}`);return Ay(e,p,a,n,r,!1,c,s)}function Jd(e,t,a,n,r,s,i=!1,o=\"channelsLast\"){let[l,u,p,c]=[-1,-1,-1,-1];if(o===\"channelsLast\")[l,u,p,c]=e;else if(o===\"channelsFirst\")[l,c,u,p]=e;else throw new Error(`Unknown dataFormat ${o}`);let[d,h,,f]=t,[m,g]=Ec(a),[x,A]=Ec(n),y=rl(d,x),b=rl(h,A),{padInfo:w,outHeight:S,outWidth:C}=gN(r,u,p,m,g,y,b,s,o),E=i?f*c:f,_;return o===\"channelsFirst\"?_=[l,E,S,C]:o===\"channelsLast\"&&(_=[l,S,C,E]),{batchSize:l,dataFormat:o,inHeight:u,inWidth:p,inChannels:c,outHeight:S,outWidth:C,outChannels:E,padInfo:w,strideHeight:m,strideWidth:g,filterHeight:d,filterWidth:h,effectiveFilterHeight:y,effectiveFilterWidth:b,dilationHeight:x,dilationWidth:A,inShape:e,outShape:_,filterShape:t}}function Ay(e,t,a,n,r,s=!1,i=\"channelsLast\",o){let[l,u,p,c,d]=[-1,-1,-1,-1,-1];if(i===\"channelsLast\")[l,u,p,c,d]=e;else if(i===\"channelsFirst\")[l,d,u,p,c]=e;else throw new Error(`Unknown dataFormat ${i}`);let[h,f,m,,g]=t,[x,A,y]=i1(a),[b,w,S]=i1(n),C=rl(h,b),E=rl(f,w),_=rl(m,S),{padInfo:$,outDepth:M,outHeight:I,outWidth:N}=xN(r,u,p,c,x,A,y,C,E,_,o),O=s?g*d:g,L;return i===\"channelsFirst\"?L=[l,O,M,I,N]:i===\"channelsLast\"&&(L=[l,M,I,N,O]),{batchSize:l,dataFormat:i,inDepth:u,inHeight:p,inWidth:c,inChannels:d,outDepth:M,outHeight:I,outWidth:N,outChannels:O,padInfo:$,strideDepth:x,strideHeight:A,strideWidth:y,filterDepth:h,filterHeight:f,filterWidth:m,effectiveFilterDepth:C,effectiveFilterHeight:E,effectiveFilterWidth:_,dilationDepth:b,dilationHeight:w,dilationWidth:S,inShape:e,outShape:L,filterShape:t}}function fN(e,t,a,n,r){n==null&&(n=y2(e,t,a));let s=e[0],i=e[1],o=Os((s-t+2*n)/a+1,r),l=Os((i-t+2*n)/a+1,r);return[o,l]}function mN(e,t,a,n,r,s){r==null&&(r=y2(e,t,n));let i=e[0],o=e[1],l=e[2],u=Os((i-t+2*r)/n+1,s),p=Os((o-t+2*r)/n+1,s),c=Os((l-t+2*r)/n+1,s);return[u,p,c,a]}function y2(e,t,a,n=1){let r=rl(t,n);return Math.floor((e[0]*(a-1)-a+r)/2)}function Ec(e){return typeof e==\"number\"?[e,e,e]:e.length===2?[e[0],e[1],1]:e}function i1(e){return typeof e==\"number\"?[e,e,e]:e}function rl(e,t){return t<=1?e:e+(e-1)*(t-1)}function gN(e,t,a,n,r,s,i,o,l){let u,p,c;if(typeof e==\"number\"){u={top:e,bottom:e,left:e,right:e,type:e===0?\"VALID\":\"NUMBER\"};let d=fN([t,a],s,n,e,o);p=d[0],c=d[1]}else if(e===\"same\"){p=Math.ceil(t/n),c=Math.ceil(a/r);let d=Math.max(0,(p-1)*n+s-t),h=Math.max(0,(c-1)*r+i-a),f=Math.floor(d/2),m=d-f,g=Math.floor(h/2),x=h-g;u={top:f,bottom:m,left:g,right:x,type:\"SAME\"}}else if(e===\"valid\")u={top:0,bottom:0,left:0,right:0,type:\"VALID\"},p=Math.ceil((t-s+1)/n),c=Math.ceil((a-i+1)/r);else if(typeof e==\"object\"){let d=l===\"channelsLast\"?e[1][0]:e[2][0],h=l===\"channelsLast\"?e[1][1]:e[2][1],f=l===\"channelsLast\"?e[2][0]:e[3][0],m=l===\"channelsLast\"?e[2][1]:e[3][1];u={top:d,bottom:h,left:f,right:m,type:d===0&&h===0&&f===0&&m===0?\"VALID\":\"EXPLICIT\"},p=Os((t-s+d+h)/n+1,o),c=Os((a-i+f+m)/r+1,o)}else throw Error(`Unknown padding parameter: ${e}`);return{padInfo:u,outHeight:p,outWidth:c}}function xN(e,t,a,n,r,s,i,o,l,u,p){let c,d,h,f;if(typeof e==\"number\"){c={top:e,bottom:e,left:e,right:e,front:e,back:e,type:e===0?\"VALID\":\"NUMBER\"};let m=mN([t,a,n,1],o,1,r,e,p);d=m[0],h=m[1],f=m[2]}else if(e===\"same\"){d=Math.ceil(t/r),h=Math.ceil(a/s),f=Math.ceil(n/i);let m=(d-1)*r+o-t,g=(h-1)*s+l-a,x=(f-1)*i+u-n,A=Math.floor(m/2),y=m-A,b=Math.floor(g/2),w=g-b,S=Math.floor(x/2),C=x-S;c={top:b,bottom:w,left:S,right:C,front:A,back:y,type:\"SAME\"}}else if(e===\"valid\")c={top:0,bottom:0,left:0,right:0,front:0,back:0,type:\"VALID\"},d=Math.ceil((t-o+1)/r),h=Math.ceil((a-l+1)/s),f=Math.ceil((n-u+1)/i);else throw Error(`Unknown padding parameter: ${e}`);return{padInfo:c,outDepth:d,outHeight:h,outWidth:f}}function Os(e,t){if(!t)return Math.trunc(e);switch(t){case\"round\":return Math.round(e);case\"ceil\":return Math.ceil(e);case\"floor\":return Math.floor(e);default:throw new Error(`Unknown roundingMode ${t}`)}}function dd(e){let[t,a,n]=Ec(e);return t===1&&a===1&&n===1}function kr(e,t){return dd(e)||dd(t)}function yy(e){if(e===\"NHWC\")return\"channelsLast\";if(e===\"NCHW\")return\"channelsFirst\";throw new Error(`Unknown dataFormat ${e}`)}function Sn(e,t,a){if(a!=null){if(typeof t==\"string\")throw Error(`Error in ${e}: pad must be an integer when using dimRoundingMode ${a} but got pad ${t}.`);if(typeof t==\"number\")P(ol(t),()=>`Error in ${e}: pad must be an integer when using dimRoundingMode ${a} but got pad ${t}.`);else if(typeof t==\"object\")t.forEach(n=>{n.forEach(r=>{P(ol(r),()=>`Error in ${e}: pad must be an integer when using dimRoundingMode ${a} but got pad ${r}.`)})});else throw Error(`Error in ${e}: Unknown padding parameter: ${t}`)}}function AN(e,t){let a={x:R(e,\"x\",\"reshape\",\"string_or_numeric\")},n={shape:t};return z.runKernel(ql,a,n)}var J=D({reshape_:AN});function yN(e,t,a,n,r){let s=R(e,\"x\",\"avgPool\",\"float32\"),i=1;P(kr(a,i),()=>`Error in avgPool: Either strides or dilations must be 1. Got strides ${a} and dilations '${i}'`);let o=s,l=!1;s.rank===3&&(l=!0,o=J(s,[1,s.shape[0],s.shape[1],s.shape[2]])),P(o.rank===4,()=>`Error in avgPool: x must be rank 4 but got rank ${o.rank}.`),Sn(\"avgPool\",n,r);let u={x:o},p={filterSize:t,strides:a,pad:n,dimRoundingMode:r},c=z.runKernel(Qs,u,p);return c=He(c,s.dtype),l?J(c,[c.shape[1],c.shape[2],c.shape[3]]):c}var b2=D({avgPool_:yN});function bN(e,t,a,n,r,s=\"NDHWC\"){let i=R(e,\"x\",\"avgPool3d\",\"float32\"),o=i,l=!1;i.rank===4&&(l=!0,o=J(i,[1,i.shape[0],i.shape[1],i.shape[2],i.shape[3]])),P(o.rank===5,()=>`Error in avgPool3d: x must be rank 5 but got rank ${o.rank}.`),P(s===\"NDHWC\",()=>`Error in avgPool3d: Only NDHWC is currently supported, but got dataFormat of ${s}`),Sn(\"avgPool3d\",n,r);let u={x:o},p={filterSize:t,strides:a,pad:n,dimRoundingMode:r,dataFormat:s},c=z.runKernel(Hc,u,p);return c=He(c,o.dtype),l?J(c,[c.shape[1],c.shape[2],c.shape[3],c.shape[4]]):c}var by=D({avgPool3d_:bN});function vN(e,t=0){P(e.length>=1,()=>\"Pass at least one tensor to concat\");let a=ud(e,\"tensors\",\"concat\",\"string_or_numeric\");if(a[0].dtype===\"complex64\"&&a.forEach(s=>{if(s.dtype!==\"complex64\")throw new Error(`Cannot concatenate complex64 tensors with a tensor\n          with dtype ${s.dtype}. `)}),a.length===1)return wa(a[0]);let n=a,r={axis:t};return z.runKernel(Ml,n,r)}var at=D({concat_:vN});function wN(e){let t={x:R(e,\"x\",\"sigmoid\",\"float32\")};return z.runKernel(ao,t)}var Da=D({sigmoid_:wN});function kN(e,t,a){let n=R(e,\"x\",\"slice\",\"string_or_numeric\");if(n.rank===0)throw new Error(\"Slicing scalar is not possible\");let r={x:n},s={begin:t,size:a};return z.runKernel(Zl,r,s)}var Pe=D({slice_:kN});function IN(e){let t={x:R(e,\"x\",\"tanh\",\"float32\")};return z.runKernel(po,t)}var Rc=D({tanh_:IN});function SN(e,t,a,n,r,s){let i=R(e,\"forgetBias\",\"basicLSTMCell\"),o=R(t,\"lstmKernel\",\"basicLSTMCell\"),l=R(a,\"lstmBias\",\"basicLSTMCell\"),u=R(n,\"data\",\"basicLSTMCell\"),p=R(r,\"c\",\"basicLSTMCell\"),c=R(s,\"h\",\"basicLSTMCell\"),d=at([u,c],1),h=st(d,o),f=be(h,l),m=f.shape[0],g=f.shape[1]/4,x=[m,g],A=Pe(f,[0,0],x),y=Pe(f,[0,g],x),b=Pe(f,[0,g*2],x),w=Pe(f,[0,g*3],x),S=be(ae(Da(A),Rc(y)),ae(p,Da(be(i,b)))),C=ae(Rc(S),Da(w));return[S,C]}var vy=D({basicLSTMCell_:SN});function TN(e,t,a){let n=R(e,\"x\",\"batchToSpaceND\"),r=t.reduce((o,l)=>o*l);P(n.rank>=1+t.length,()=>`input rank is ${n.rank} but should be > than blockShape.length ${t.length}`),P(a.length===t.length,()=>`crops.length is ${a.length} but should be equal to blockShape.length  ${t.length}`),P(n.shape[0]%r===0,()=>`input tensor batch is ${n.shape[0]} but is not divisible by the product of the elements of blockShape ${t.join(\" * \")} === ${r}`);let s={x:n},i={blockShape:t,crops:a};return z.runKernel(Rl,s,i)}var v2=D({batchToSpaceND_:TN});function CN(e){let t;return e.rank===0||e.rank===1?t=J(e,[1,1,1,e.size]):e.rank===2?t=J(e,[1,1,e.shape[0],e.shape[1]]):e.rank===3?t=J(e,[1,e.shape[0],e.shape[1],e.shape[2]]):t=e,t}function NN(e,t,a,n,r,s){s==null&&(s=.001);let i=R(e,\"x\",\"batchNorm\"),o=R(t,\"mean\",\"batchNorm\"),l=R(a,\"variance\",\"batchNorm\"),u;r!=null&&(u=R(r,\"scale\",\"batchNorm\"));let p;n!=null&&(p=R(n,\"offset\",\"batchNorm\")),P(o.rank===l.rank,()=>\"Batch normalization gradient requires mean and variance to have equal ranks.\"),P(p==null||o.rank===p.rank,()=>\"Batch normalization gradient requires mean and offset to have equal ranks.\"),P(u==null||o.rank===u.rank,()=>\"Batch normalization gradient requires mean and scale to have equal ranks.\");let c={x:CN(i),scale:u,offset:p,mean:o,variance:l},d={varianceEpsilon:s},h=z.runKernel(yi,c,d);return J(h,i.shape)}var Qd=D({batchNorm_:NN});function EN(e,t,a,n,r,s){let i=R(e,\"x\",\"batchNorm\"),o=R(t,\"mean\",\"batchNorm\"),l=R(a,\"variance\",\"batchNorm\"),u;r!=null&&(u=R(r,\"scale\",\"batchNorm\"));let p;return n!=null&&(p=R(n,\"offset\",\"batchNorm\")),P(i.rank===2,()=>`Error in batchNorm2D: x must be rank 2 but got rank ${i.rank}.`),P(o.rank===2||o.rank===1,()=>`Error in batchNorm2D: mean must be rank 2 or rank 1 but got rank ${o.rank}.`),P(l.rank===2||l.rank===1,()=>`Error in batchNorm2D: variance must be rank 2 or rank 1 but got rank ${l.rank}.`),u!=null&&P(u.rank===2||u.rank===1,()=>`Error in batchNorm2D: scale must be rank 2 or rank 1 but got rank ${u.rank}.`),p!=null&&P(p.rank===2||p.rank===1,()=>`Error in batchNorm2D: offset must be rank 2 or rank 1 but got rank ${p.rank}.`),Qd(i,o,l,p,u,s)}var wy=D({batchNorm2d_:EN});function RN(e,t,a,n,r,s){let i=R(e,\"x\",\"batchNorm\"),o=R(t,\"mean\",\"batchNorm\"),l=R(a,\"variance\",\"batchNorm\"),u;r!=null&&(u=R(r,\"scale\",\"batchNorm\"));let p;return n!=null&&(p=R(n,\"offset\",\"batchNorm\")),P(i.rank===3,()=>`Error in batchNorm3D: x must be rank 3 but got rank ${i.rank}.`),P(o.rank===3||o.rank===1,()=>`Error in batchNorm3D: mean must be rank 3 or rank 1 but got rank ${o.rank}.`),P(l.rank===3||l.rank===1,()=>`Error in batchNorm3D: variance must be rank 3 or rank 1 but got rank ${l.rank}.`),u!=null&&P(u.rank===3||u.rank===1,()=>`Error in batchNorm3D: scale must be rank 3 or rank 1 but got rank ${u.rank}.`),p!=null&&P(p.rank===3||p.rank===1,()=>`Error in batchNorm3D: offset must be rank 3 or rank 1 but got rank ${p.rank}.`),Qd(i,o,l,p,u,s)}var ky=D({batchNorm3d_:RN});function MN(e,t,a,n,r,s){let i=R(e,\"x\",\"batchNorm\"),o=R(t,\"mean\",\"batchNorm\"),l=R(a,\"variance\",\"batchNorm\"),u;r!=null&&(u=R(r,\"scale\",\"batchNorm\"));let p;return n!=null&&(p=R(n,\"offset\",\"batchNorm\")),P(i.rank===4,()=>`Error in batchNorm4D: x must be rank 4 but got rank ${i.rank}.`),P(o.rank===4||o.rank===1,()=>`Error in batchNorm4D: mean must be rank 4 or rank 1 but got rank ${o.rank}.`),P(l.rank===4||l.rank===1,()=>`Error in batchNorm4D: variance must be rank 4 or rank 1 but got rank ${l.rank}.`),u!=null&&P(u.rank===4||u.rank===1,()=>`Error in batchNorm4D: scale must be rank 4 or rank 1 but got rank ${u.rank}.`),p!=null&&P(p.rank===4||p.rank===1,()=>`Error in batchNorm4D: offset must be rank 4 or rank 1 but got rank ${p.rank}.`),Qd(i,o,l,p,u,s)}var Iy=D({batchNorm4d_:MN});function $N(e,t,a){let n=R(e,\"x\",\"bincount\"),r=R(t,\"weights\",\"bincount\");P(n.dtype===\"int32\",()=>`Error in bincount: input dtype must be int32, but got ${n.dtype}`),P(a>=0,()=>`size must be non-negative, but got ${a}.`),P(r.size===n.size||r.size===0,()=>`Error in bincount: weights must have the same size as input or0-length, but got input shape: ${n.shape}, weights shape: ${r.shape}.`);let s={x:n,weights:r},i={size:a};return z.runKernel(Id,s,i)}var w2=D({bincount_:$N});function _N(e,t){let a=R(e,\"s0\",\"broadcastArgs\",\"int32\"),n=R(t,\"s1\",\"broadcastArgs\",\"int32\");if(a.rank!==1)throw new Error(`broadcastArgs(): first input must be a vector (rank=1). Has rank ${a.rank}`);if(n.rank!==1)throw new Error(`broadcastArgs(): second input must be a vector (rank=1). Has rank ${n.rank}`);let r={s0:a,s1:n};return z.runKernel(jc,r)}var Sy=D({broadcastArgs_:_N});function PN(e,t){let a=R(e,\"broadcastTo\",\"x\"),n=a.shape;if(Ja(t),t.length<a.rank)throw new Error(`broadcastTo(): shape.length=${t.length} < input.rank=${a.rank}.`);if(t.length>a.rank){let l=a.shape.slice();for(;l.length<t.length;)l.unshift(1);a=J(a,l)}let r=a.shape,s=Array.from(t);for(let l=t.length-1;l>=0;l--)if(r[l]===t[l])s[l]=1;else if(a.shape[l]!==1)throw new Error(`broadcastTo(): [${n}] cannot be broadcast to [${t}].`);if(s.map((l,u)=>l>1?u:-1).filter(l=>l>=0).length===0)return wa(a);let i={x:a},o={reps:s};return z.runKernel(ns,i,o)}var sl=D({broadcastTo_:PN});function FN(e){let t={x:R(e,\"x\",\"ceil\",\"float32\")};return z.runKernel(ai,t)}var Ty=D({ceil_:FN});function nr(e,t,a){Ja(e);let n={shape:e,value:t,dtype:a};return z.runKernel(Fl,{},n)}function ON(e,t,a){let n=R(e,\"x\",\"clipByValue\");if(P(t<=a,()=>`Error in clip: min (${t}) must be less than or equal to max (${a}).`),t===a)return nr(n.shape,t,n.dtype);let r={x:n},s={clipValueMin:t,clipValueMax:a};return z.runKernel(as,r,s)}var Cy=D({clipByValue_:ON});function DN(e){return at(e,0)}var Ny=D({concat1d_:DN});function zN(e,t){return at(e,t)}var ru=D({concat2d_:zN});function LN(e,t){return at(e,t)}var Ey=D({concat3d_:LN});function BN(e,t){return at(e,t)}var Ry=D({concat4d_:BN});function WN(e,t,a,n,r=\"NHWC\",s=[1,1],i){let o=R(e,\"x\",\"conv2d\",\"float32\"),l=R(t,\"filter\",\"conv2d\",\"float32\"),u=o,p=!1;o.rank===3&&(p=!0,u=J(o,[1,o.shape[0],o.shape[1],o.shape[2]])),P(u.rank===4,()=>`Error in conv2d: input must be rank 4, but got rank ${u.rank}.`),P(l.rank===4,()=>`Error in conv2d: filter must be rank 4, but got rank ${l.rank}.`),Sn(\"conv2d\",n,i);let c=r===\"NHWC\"?u.shape[3]:u.shape[1];P(c===l.shape[2],()=>`Error in conv2d: depth of input (${c}) must match input depth for filter ${l.shape[2]}.`),P(kr(a,s),()=>`Error in conv2D: Either strides or dilations must be 1. Got strides ${a} and dilations '${s}'`);let d={x:u,filter:l},h={strides:a,pad:n,dataFormat:r,dilations:s,dimRoundingMode:i},f=z.runKernel(ni,d,h);return p?J(f,[f.shape[1],f.shape[2],f.shape[3]]):f}var ep=D({conv2d_:WN});function VN(e,t,a,n,r=\"NWC\",s=1,i){let o=R(e,\"x\",\"conv1d\"),l=R(t,\"filter\",\"conv1d\"),u=o,p=!1;o.rank===2&&(p=!0,u=J(o,[1,o.shape[0],o.shape[1]])),P(u.rank===3,()=>`Error in conv1d: input must be rank 3, but got rank ${u.rank}.`),P(l.rank===3,()=>`Error in conv1d: filter must be rank 3, but got rank ${l.rank}.`),Sn(\"conv1d\",n,i),P(u.shape[2]===l.shape[1],()=>`Error in conv1d: depth of input (${u.shape[2]}) must match input depth for filter ${l.shape[1]}.`),P(kr(a,s),()=>`Error in conv1D: Either stride or dilation must be 1. Got stride ${a} and dilation '${s}'`),P(r===\"NWC\",()=>`Error in conv1d: got dataFormat of ${r} but only NWC is currently supported.`);let c=J(l,[1,l.shape[0],l.shape[1],l.shape[2]]),d=J(u,[u.shape[0],1,u.shape[1],u.shape[2]]),h=ep(d,c,[1,a],n,\"NHWC\",[1,s],i);return p?J(h,[h.shape[2],h.shape[3]]):J(h,[h.shape[0],h.shape[2],h.shape[3]])}var My=D({conv1d_:VN});function UN(e,t,a,n,r,s=\"NHWC\",i){P(e.length===t.rank,()=>`Length of inShape (${e.length}) and rank of dy (${t.rank}) must match`);let o=e,l=t,u=!1;t.rank===3&&(u=!0,l=J(t,[1,t.shape[0],t.shape[1],t.shape[2]]),o=[1,e[0],e[1],e[2]]),P(o.length===4,()=>`Error in conv2dDerInput: inShape must be length 4, but got length ${o.length}.`),P(l.rank===4,()=>`Error in conv2dDerInput: dy must be rank 4, but got rank ${l.rank}`),P(a.rank===4,()=>`Error in conv2dDerInput: filter must be rank 4, but got rank ${a.rank}`);let p=s===\"NHWC\"?o[3]:o[1],c=s===\"NHWC\"?l.shape[3]:l.shape[1];P(p===a.shape[2],()=>`Error in conv2dDerInput: depth of input (${p}) must match input depth for filter ${a.shape[2]}.`),P(c===a.shape[3],()=>`Error in conv2dDerInput: depth of output (${c}) must match output depth for filter ${a.shape[3]}.`),Sn(\"conv2dDerInput\",r,i);let d={dy:l,filter:a},h={strides:n,pad:r,dataFormat:s,dimRoundingMode:i,inputShape:o},f=z.runKernel(ri,d,h);return u?J(f,[f.shape[1],f.shape[2],f.shape[3]]):f}var $y=D({conv2DBackpropInput_:UN});function GN(e,t,a,n,r,s){let i=R(e,\"x\",\"conv2dTranspose\"),o=R(t,\"filter\",\"conv2dTranspose\");return $y(a,i,o,n,r,\"NHWC\",s)}var _y=D({conv2dTranspose_:GN});function HN(e,t,a,n,r=\"NDHWC\",s=[1,1,1]){let i=R(e,\"x\",\"conv3d\"),o=R(t,\"filter\",\"conv3d\"),l=i,u=!1;i.rank===4&&(u=!0,l=J(i,[1,i.shape[0],i.shape[1],i.shape[2],i.shape[3]])),P(l.rank===5,()=>`Error in conv3d: input must be rank 5, but got rank ${l.rank}.`),P(o.rank===5,()=>`Error in conv3d: filter must be rank 5, but got rank ${o.rank}.`),P(l.shape[4]===o.shape[3],()=>`Error in conv3d: depth of input (${l.shape[4]}) must match input depth for filter ${o.shape[3]}.`),P(kr(a,s),()=>`Error in conv3D: Either strides or dilations must be 1. Got strides ${a} and dilations '${s}'`),P(r===\"NDHWC\",()=>`Error in conv3d: got dataFormat of ${r} but only NDHWC is currently supported.`);let p={x:l,filter:o},c={strides:a,pad:n,dataFormat:r,dilations:s},d=z.runKernel(Kc,p,c);return u?J(d,[d.shape[1],d.shape[2],d.shape[3],d.shape[4]]):d}var Py=D({conv3d_:HN});function jN(e,t,a,n,r){P(e.length===t.rank,()=>`Length of inShape (${e.length}) and rank of dy (${t.rank}) must match`);let s=e,i=t,o=!1;t.rank===4&&(o=!0,i=J(t,[1,t.shape[0],t.shape[1],t.shape[2],t.shape[3]]),s=[1,e[0],e[1],e[2],e[3]]);let l=s[4],u=i.shape[4];P(s.length===5,()=>`Error in conv3dDerInput: inShape must be length 5, but got length ${s.length}.`),P(i.rank===5,()=>`Error in conv3dDerInput: dy must be rank 5, but got rank ${i.rank}`),P(a.rank===5,()=>`Error in conv3dDerInput: filter must be rank 5, but got rank ${a.rank}`),P(l===a.shape[3],()=>`Error in conv3dDerInput: depth of input (${l}) must match input depth for filter ${a.shape[3]}.`),P(u===a.shape[4],()=>`Error in conv3dDerInput: depth of output (${u}) must match output depth for filter ${a.shape[4]}.`);let p={dy:i,filter:a},c={pad:r,strides:n,inputShape:s},d=z.runKernel(Zc,p,c);return o?J(d,[d.shape[1],d.shape[2],d.shape[3],d.shape[4]]):d}var qN=D({conv3DBackpropInput_:jN});function XN(e,t,a,n,r){let s=R(e,\"x\",\"conv3dTranspose\"),i=R(t,\"filter\",\"conv3dTranspose\");return qN(a,s,i,n,r)}var Fy=D({conv3dTranspose_:XN});function KN(e){let t={x:R(e,\"x\",\"cos\",\"float32\")};return z.runKernel(si,t)}var Oy=D({cos_:KN});function ZN(e){let t={x:R(e,\"x\",\"cosh\",\"float32\")};return z.runKernel(ii,t)}var Dy=D({cosh_:ZN});function YN(e,t=0,a=!1,n=!1){let r={x:R(e,\"x\",\"cumprod\")},s={axis:t,exclusive:a,reverse:n};return z.runKernel(oi,r,s)}var zy=D({cumprod_:YN});function JN(e,t=0,a=!1,n=!1){let r={x:R(e,\"x\",\"cumsum\")},s={axis:t,exclusive:a,reverse:n};return z.runKernel(li,r,s)}var Ly=D({cumsum_:JN});function QN(e,t,a,n=!1){let r=R(e,\"x\",\"denseBincount\"),s=R(t,\"weights\",\"denseBincount\");P(r.dtype===\"int32\",()=>`Error in denseBincount: input dtype must be int32, but got ${r.dtype}`),P(r.rank<=2,()=>`Error in denseBincount: input must be at most rank 2, but got rank ${r.rank}.`),P(a>=0,()=>`size must be non-negative, but got ${a}.`),P(s.size===r.size||s.size===0,()=>`Error in denseBincount: weights must have the same shape as x or 0-length, but got x shape: ${r.shape}, weights shape: ${s.shape}.`);let i={x:r,weights:s},o={size:a,binaryOutput:n};return z.runKernel(Td,i,o)}var By=D({denseBincount_:QN});function eE(e,t,a=\"NHWC\"){let n=R(e,\"x\",\"depthToSpace\",\"float32\"),r=a===\"NHWC\"?n.shape[1]:n.shape[2],s=a===\"NHWC\"?n.shape[2]:n.shape[3],i=a===\"NHWC\"?n.shape[3]:n.shape[1];P(t>1,()=>`blockSize should be > 1 for depthToSpace, but was: ${t}`),P(r*t>=0,()=>`Negative dimension size caused by overflow when multiplying\n    ${r} and ${t}  for depthToSpace with input shape\n    ${n.shape}`),P(s*t>=0,()=>`Negative dimension size caused by overflow when multiplying\n    ${s} and ${t} for depthToSpace with input shape\n        ${n.shape}`),P(i%(t*t)===0,()=>`Dimension size must be evenly divisible by ${t*t} but is ${i} for depthToSpace with input shape ${n.shape}`);let o={x:n},l={blockSize:t,dataFormat:a};return z.runKernel(di,o,l)}var Wy=D({depthToSpace_:eE});function tE(e,t,a,n,r=\"NHWC\",s=[1,1],i){let o=R(e,\"x\",\"depthwiseConv2d\",\"float32\"),l=R(t,\"filter\",\"depthwiseConv2d\",\"float32\"),u=o,p=!1;o.rank===3&&(p=!0,u=J(o,[1,o.shape[0],o.shape[1],o.shape[2]])),P(u.rank===4,()=>`Error in depthwiseConv2d: input must be rank 4, but got rank ${u.rank}.`),P(l.rank===4,()=>`Error in depthwiseConv2d: filter must be rank 4, but got rank ${l.rank}.`);let c=r===\"NHWC\"?u.shape[3]:u.shape[1];P(c===l.shape[2],()=>`Error in depthwiseConv2d: number of input channels (${c}) must match the inChannels dimension in filter ${l.shape[2]}.`),Sn(\"depthwiseConv2d\",n,i);let d={x:u,filter:l},h={strides:a,pad:n,dataFormat:r,dilations:s,dimRoundingMode:i},f=z.runKernel(pi,d,h);return p?J(f,[f.shape[1],f.shape[2],f.shape[3]]):f}var hh=D({depthwiseConv2d_:tE});function aE(e){let t={x:R(e,\"x\",\"diag\")};return z.runKernel(Qc,t)}var Vy=D({diag_:aE});function nE(e,t,a,n,r=[1,1],s=\"NHWC\"){let i=R(e,\"x\",\"dilation2d\"),o=R(t,\"filter\",\"dilation2d\");P(i.rank===3||i.rank===4,()=>`Error in dilation2d: input must be rank 3 or 4, but got rank ${i.rank}.`),P(o.rank===3,()=>`Error in dilation2d: filter must be rank 3, but got rank ${o.rank}.`),P(s===\"NHWC\",()=>`Error in dilation2d: Only NHWC is currently supported, but got dataFormat of ${s}`);let l=i,u=!1;i.rank===3&&(l=J(i,[1,i.shape[0],i.shape[1],i.shape[2]]),u=!0);let p={x:l,filter:o},c={strides:a,pad:n,dilations:r},d=z.runKernel(eh,p,c);return u?J(d,[d.shape[1],d.shape[2],d.shape[3]]):d}var Uy=D({dilation2d_:nE});function rE(e,t){let a=R(e,\"a\",\"equal\",\"string_or_numeric\"),n=R(t,\"b\",\"equal\",\"string_or_numeric\");[a,n]=St(a,n),zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(fi,r)}var k2=D({equal_:rE});function sE(e,t,a){let n=R(t,\"a\",\"where\"),r=R(a,\"b\",\"where\"),s=R(e,\"condition\",\"where\",\"bool\"),i=zt(zt(s.shape,n.shape),r.shape),o=sl(s,i),l=sl(n,i),u=sl(r,i),p={condition:o,t:l,e:u};return z.runKernel(Kl,p)}var Vs=D({where_:sE});function iE(e){let t={x:R(e,\"x\",\"zerosLike\")};return z.runKernel(nu,t)}var Ka=D({zerosLike_:iE});function oE(e,t){let a=R(e,\"a\",\"div\"),n=R(t,\"b\",\"div\");[a,n]=St(a,n);let r=me(a,n),s=Ka(r),i=k2(n,s);return Vs(i,s,r)}var Gy=D({divNoNan_:oE});function lE(e,t){let a=R(e,\"t1\",\"dot\"),n=R(t,\"t2\",\"dot\");P((a.rank===1||a.rank===2)&&(n.rank===1||n.rank===2),()=>`Error in dot: inputs must all be rank 1 or 2, but got ranks ${a.rank} and ${n.rank}.`);let r=a.rank===1?a.size:a.shape[1],s=n.rank===1?n.size:n.shape[0];if(P(r===s,()=>`Error in dot: inner dimensions of inputs must match, but got ${r} and ${s}.`),a.rank===1&&n.rank===1){let i=J(a,[1,-1]),o=J(n,[-1,1]),l=st(i,o);return J(l,[])}else if(a.rank===1&&n.rank===2){let i=J(a,[1,-1]),o=J(n,[n.shape[0],n.shape[1]]),l=st(i,o);return J(l,[l.size])}else if(a.rank===2&&n.rank===1){let i=J(n,[-1,1]),o=st(a,i);return J(o,[o.size])}else{let i=J(n,[n.shape[0],n.shape[1]]);return st(a,i)}}var Hy=D({dot_:lE});function uE(e,...t){let a=t.map((r,s)=>R(r,`tensors${s}`,\"einsum\")),n={equation:e};return z.runKernel(Cd,a,n)}var jy=D({einsum_:uE});function dE(e){let t={x:R(e,\"x\",\"elu\",\"float32\")};return z.runKernel(hi,t)}var I2=D({elu_:dE});function pE(e){let t=R(e,\"x\",\"erf\");P(t.dtype===\"int32\"||t.dtype===\"float32\",()=>\"Input dtype must be `int32` or `float32`.\"),t.dtype===\"int32\"&&(t=He(t,\"float32\"));let a={x:t};return z.runKernel($l,a)}var qy=D({erf_:pE});function S2(e,t){for(let a=0;a<e.length;++a)if(e[e.length-a-1]!==t-1-a)return!1;return!0}function Xy(e,t,a){let n=e.length+t.length,r=[],s=0,i=0;for(let o=0;o<n;o++)a.indexOf(o)===-1?r.push(e[s++]):r.push(t[i++]);return r}function cE(e,t){let a=[],n=e.length;for(let s=0;s<n;s++)t.indexOf(s)===-1&&a.push(e[s]);let r=t.map(s=>e[s]);return[a,r]}function tp(e,t){let a=t.map(n=>1);return Xy(e,a,t)}function hE(e,t,a){P(S2(t,a),()=>`${e} supports only inner-most axes for now. Got axes ${t} and rank-${a} input.`)}function fE(e,t){if(S2(e,t))return null;let a=[];for(let n=0;n<t;++n)e.indexOf(n)===-1&&a.push(n);return e.forEach(n=>a.push(n)),a}function mE(e){return e.map((t,a)=>[a,t]).sort((t,a)=>t[1]-a[1]).map(t=>t[0])}function gE(e,t){let a=[];for(let n=t-e;n<t;++n)a.push(n);return a}function xE(e,t=null,a=!1){let n={x:R(e,\"x\",\"max\")},r={reductionIndices:t,keepDims:a};return z.runKernel(Mi,n,r)}var pa=D({max_:xE});function AE(e,t=null,a=!1){let n={x:R(e,\"x\",\"min\")},r={axis:t,keepDims:a};return z.runKernel(Fi,n,r)}var Kr=D({min_:AE});function yE(e,t){let a=R(e,\"base\",\"pow\"),n=R(t,\"exp\",\"pow\");[a,n]=St(a,n);let r={a,b:n};return z.runKernel(Gi,r)}var pl=D({pow_:yE});function Fe(e,t){if((da(e)&&t!==\"string\"||Array.isArray(e))&&t!==\"complex64\")throw new Error(\"Error creating a new Scalar: value must be a primitive (number|boolean|string)\");if(t===\"string\"&&da(e)&&!(e instanceof Uint8Array))throw new Error(\"When making a scalar from encoded string, the value must be `Uint8Array`.\");return rs(e,[],[],t)}function bE(e){let t={x:R(e,\"x\",\"sqrt\",\"float32\")};return z.runKernel(no,t)}var Jn=D({sqrt_:bE});function vE(e){let t=R(e,\"x\",\"square\"),a={};return z.runKernel(\"Square\",{x:t},a)}var In=D({square_:vE});function wE(e,t=null,a=!1){let n=R(e,\"x\",\"sum\");n.dtype===\"bool\"&&(n=He(n,\"int32\"));let r={x:n},s={axis:t,keepDims:a};return z.runKernel(ro,r,s)}var tt=D({sum_:wE});function kE(e,t=\"euclidean\",a=null,n=!1){e=R(e,\"x\",\"norm\");let r=Ky(e,t,a),s=r.shape;if(n){let i=wd(a,e.shape);s=tp(r.shape,i)}return J(r,s)}function Ky(e,t,a=null){if(e.rank===0)return qa(e);if(e.rank!==1&&a===null)return Ky(J(e,[-1]),t,a);if(e.rank===1||typeof a==\"number\"||Array.isArray(a)&&a.length===1){if(t===1)return tt(qa(e),a);if(t===1/0)return pa(qa(e),a);if(t===-1/0)return Kr(qa(e),a);if(t===\"euclidean\"||t===2)return Jn(tt(pl(qa(e),Fe(2,\"int32\")),a));throw new Error(`Error in norm: invalid ord value: ${t}`)}if(Array.isArray(a)&&a.length===2){if(t===1)return pa(tt(qa(e),a[0]),a[1]-1);if(t===1/0)return pa(tt(qa(e),a[1]),a[0]);if(t===-1/0)return Kr(tt(qa(e),a[1]),a[0]);if(t===\"fro\"||t===\"euclidean\")return Jn(tt(In(e),a));throw new Error(`Error in norm: invalid ord value: ${t}`)}throw new Error(`Error in norm: invalid axis: ${a}`)}var ap=D({norm_:kE});function IE(e,t=null,a=!1){return ap(e,\"euclidean\",t,a)}var Zy=D({euclideanNorm_:IE});function SE(e){let t={x:R(e,\"x\",\"exp\")};return z.runKernel(mi,t)}var Zr=D({exp_:SE});function TE(e,t=0){let a=R(e,\"x\",\"expandDims\",\"string_or_numeric\");P(t<=a.rank,()=>\"Axis must be <= rank of the tensor\");let n={input:a},r={dim:t};return z.runKernel(_l,n,r)}var Gt=D({expandDims_:TE});function CE(e){let t={x:R(e,\"x\",\"expm1\")};return z.runKernel(Pl,t)}var Yy=D({expm1_:CE});function NE(e,t){let a=R(e,\"x\",\"tile\",\"string_or_numeric\");P(a.rank===t.length,()=>`Error in transpose: rank of input ${a.rank} must match length of reps ${t}.`);let n={x:a},r={reps:t};return z.runKernel(ns,n,r)}var Gr=D({tile_:NE});function EE(e,t,a,n=\"float32\"){t==null&&(t=e);let r=Me([e,t],n),s=e<=t?e:t;for(let o=0;o<s;++o)r.set(1,o,o);let i=J(r.toTensor(),[e,t]);if(a==null)return i;if(a.length===1)return Gr(Gt(i,0),[a[0],1,1]);if(a.length===2)return Gr(Gt(Gt(i,0),0),[a[0],a[1],1,1]);if(a.length===3)return Gr(Gt(Gt(Gt(i,0),0),0),[a[0],a[1],a[2],1,1]);throw new Error(`eye() currently supports only 1D and 2D batchShapes, but received ${a.length}D.`)}var T2=D({eye_:EE});function RE(e){let t={x:R(e,\"x\",\"floor\",\"float32\")};return z.runKernel(xi,t)}var C2=D({floor_:RE});function ME(e,t,a=0,n=0){let r=R(e,\"x\",\"gather\"),s=R(t,\"indices\",\"gather\",\"int32\"),i={x:r,indices:s},o={axis:a,batchDims:n};return z.runKernel(Ol,i,o)}var N2=D({gather_:ME});function $E(e,t){let a=R(e,\"a\",\"greater\",\"string_or_numeric\"),n=R(t,\"b\",\"greater\",\"string_or_numeric\");[a,n]=St(a,n),zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(vi,r)}var np=D({greater_:$E});function _E(e,t){let a=R(e,\"a\",\"greaterEqual\",\"string_or_numeric\"),n=R(t,\"b\",\"greaterEqual\",\"string_or_numeric\");[a,n]=St(a,n),zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(wi,r)}var E2=D({greaterEqual_:_E});function PE(e){let t={x:R(e,\"x\",\"isFinite\")};return z.runKernel(Dl,t)}var Jy=D({isFinite_:PE});function FE(e){let t={x:R(e,\"x\",\"isInf\")};return z.runKernel(zl,t)}var Qy=D({isInf_:FE});function OE(e){let t={x:R(e,\"x\",\"isNaN\")};return z.runKernel(Ii,t)}var eb=D({isNaN_:OE});function DE(e,t=.2){let a={x:R(e,\"x\",\"leakyRelu\")},n={alpha:t};return z.runKernel(Si,a,n)}var R2=D({leakyRelu_:DE});function zE(e,t){let a=R(e,\"a\",\"less\",\"string_or_numeric\"),n=R(t,\"b\",\"less\",\"string_or_numeric\");[a,n]=St(a,n),zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(Ti,r)}var tb=D({less_:zE});function LE(e,t){let a=R(e,\"a\",\"lessEqual\",\"string_or_numeric\"),n=R(t,\"b\",\"lessEqual\",\"string_or_numeric\");[a,n]=St(a,n),zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(Ci,r)}var fh=D({lessEqual_:LE});function ab(e,t,a){if(a<=0)throw new Error(\"The number of values should be positive.\");let n={start:e,stop:t,num:a};return z.runKernel(th,{},n)}function BE(e,t=5,a=1,n=1,r=.5){let s=R(e,\"x\",\"localResponseNormalization\");P(s.rank===4||s.rank===3,()=>`Error in localResponseNormalization: x must be rank 3 or 4 but got\n               rank ${s.rank}.`),P(ol(t),()=>`Error in localResponseNormalization: depthRadius must be an integer but got depthRadius ${t}.`);let i=s,o=!1;s.rank===3&&(o=!0,i=J(s,[1,s.shape[0],s.shape[1],s.shape[2]]));let l={x:i},u={depthRadius:t,bias:a,alpha:n,beta:r},p=z.runKernel(ah,l,u);return o?J(p,[p.shape[1],p.shape[2],p.shape[3]]):p}var nb=D({localResponseNormalization_:BE});function WE(e){let t={x:R(e,\"x\",\"log\",\"float32\")};return z.runKernel(Ni,t)}var cl=D({log_:WE});function VE(e){let t={x:R(e,\"x\",\"log1p\")};return z.runKernel(Ll,t)}var M2=D({log1p_:VE});function UE(e){return P(Hr(e),()=>\"The f passed in grad(f) must be a function\"),(t,a)=>{let n=R(t,\"x\",\"tf.grad\",\"string_or_numeric\"),r=a!=null?R(a,\"dy\",\"tf.grad\"):null;return z.tidy(()=>{let{value:s,grads:i}=z.gradients(()=>e(n),[n],r);return r!=null&&Sa(s.shape,r.shape,\"The shape of dy passed in grad(f)(x, dy) must match the shape returned by f(x)\"),mh(i),i[0]})}}function GE(e){return P(Hr(e),()=>\"The f passed in grads(f) must be a function\"),(t,a)=>{P(Array.isArray(t),()=>\"The args passed in grads(f)(args) must be an array of `Tensor`s or `TensorLike`s\");let n=ud(t,\"args\",\"tf.grads\",\"string_or_numeric\"),r=a!=null?R(a,\"dy\",\"tf.grads\"):null;return z.tidy(()=>{let{value:s,grads:i}=z.gradients(()=>e(...n),n,r);return r!=null&&Sa(s.shape,r.shape,\"The shape of dy passed in grads(f)([x1,...], dy) must match the shape returned by f([x1,...])\"),mh(i),i})}}function HE(e){return P(Hr(e),()=>\"The f passed in valueAndGrad(f) must be a function\"),(t,a)=>{P(t instanceof pt,()=>\"The x passed in valueAndGrad(f)(x) must be a tensor\"),P(a==null||a instanceof pt,()=>\"The dy passed in valueAndGrad(f)(x, dy) must be a tensor\");let{grads:n,value:r}=z.gradients(()=>e(t),[t],a);return mh(n),{grad:n[0],value:r}}}function jE(e){return P(Hr(e),()=>\"The f passed in valueAndGrads(f) must be a function\"),(t,a)=>{P(Array.isArray(t)&&t.every(r=>r instanceof pt),()=>\"The args passed in valueAndGrads(f)(args) must be array of tensors\"),P(a==null||a instanceof pt,()=>\"The dy passed in valueAndGrads(f)(args, dy) must be a tensor\");let n=z.gradients(()=>e(...t),t,a);return a!=null&&Sa(n.value.shape,a.shape,\"The shape of dy passed in valueAndGrads(f)([x1,...], dy) must match the shape returned by f([x1,...])\"),mh(n.grads),n}}function rb(e,t){P(Hr(e),()=>\"The f passed in variableGrads(f) must be a function\"),P(t==null||Array.isArray(t)&&t.every(u=>u instanceof od),()=>\"The varList passed in variableGrads(f, varList) must be an array of variables\");let a=t!=null;if(!a){t=[];for(let u in z.registeredVariables)t.push(z.registeredVariables[u])}let n=a?t.filter(u=>!u.trainable):null,r=t.length;t=t.filter(u=>u.trainable),P(t.length>0,()=>`variableGrads() expects at least one of the input variables to be trainable, but none of the ${r} variables is trainable.`);let s=!0,{value:i,grads:o}=z.gradients(e,t,null,s);P(o.some(u=>u!=null),()=>\"Cannot find a connection between any variable and the result of the loss function y=f(x). Please make sure the operations that use variables are inside the function f passed to minimize().\"),P(i.rank===0,()=>`The f passed in variableGrads(f) must return a scalar, but it returned a rank-${i.rank} tensor`);let l={};return t.forEach((u,p)=>{o[p]!=null&&(l[u.name]=o[p])}),n!=null&&n.forEach(u=>l[u.name]=null),{value:i,grads:l}}function Qn(e){return z.customGrad(e)}function mh(e){if(e.filter(t=>t==null).length>0)throw new Error(`Cannot compute gradient of y=f(x) with respect to x. Make sure that\n    the f you passed encloses all operations that lead from x to y.`)}function qE(e){let t={x:R(e,\"x\",\"softplus\")};return z.runKernel(Fd,t)}var $2=D({softplus_:qE});function XE(e){let t=R(e,\"x\",\"logSigmoid\");return Qn(a=>({value:Xn($2(Xn(a))),gradFunc:n=>ae(n,Da(Xn(a)))}))(t)}var sb=D({logSigmoid_:XE});function KE(e,t){let a=R(e,\"a\",\"sub\"),n=R(t,\"b\",\"sub\");[a,n]=St(a,n);let r={a,b:n};return z.runKernel(lo,r)}var fe=D({sub_:KE});function ZE(e,t=-1){let a=R(e,\"logits\",\"logSoftmax\");if(t===-1&&(t=a.rank-1),t!==a.rank-1)throw Error(`Log Softmax along a non-last dimension is not yet supported. Logits was rank ${a.rank} and axis was ${t}`);return Qn((n,r)=>{let s=pa(n,t,!0),i=fe(n,s),o=fe(He(i,\"float32\"),cl(tt(Zr(i),t,!0)));return r([o]),{value:o,gradFunc:(l,u)=>{let[p]=u,c=!0,d=Zr(p);return fe(l,ae(tt(l,t,c),d))}}})(a)}var ib=D({logSoftmax_:ZE});function YE(e,t=null,a=!1){let n=R(e,\"x\",\"logSumExp\"),r=wd(t,n.shape),s=pa(n,r,!0),i=fe(n,s),o=Zr(i),l=tt(o,r),u=cl(l),p=be(J(s,u.shape),u);if(a){let c=tp(p.shape,r);return J(p,c)}return p}var _2=D({logSumExp_:YE});function JE(e,t){let a=R(e,\"a\",\"logicalAnd\",\"bool\"),n=R(t,\"b\",\"logicalAnd\",\"bool\");zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(Ei,r)}var pd=D({logicalAnd_:JE});function QE(e){let t={x:R(e,\"x\",\"logicalNot\",\"bool\")};return z.runKernel(Ri,t)}var P2=D({logicalNot_:QE});function eR(e,t){let a=R(e,\"a\",\"logicalOr\",\"bool\"),n=R(t,\"b\",\"logicalOr\",\"bool\");zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(Bl,r)}var F2=D({logicalOr_:eR});function tR(e,t){let a=R(e,\"a\",\"logicalXor\",\"bool\"),n=R(t,\"b\",\"logicalXor\",\"bool\");return zt(a.shape,n.shape),pd(F2(e,t),P2(pd(e,t)))}var ob=D({logicalXor_:tR}),oc=2147483648;function aR(e,t,a=\"left\"){let n=R(e,\"sortedSequence\",\"searchSorted\"),r=R(t,\"values\",\"searchSorted\"),s=n.shape[n.shape.length-1],i=r.shape[r.shape.length-1],o=J(n,[-1,s]),l=J(r,[-1,i]);if(o.rank<2)throw new Error(\"Sorted input argument must be at least 2-dimensional\");if(o.shape[0]!==l.shape[0])throw new Error(\"Leading dimension of 'sortedSequence' and 'values' must match.\");if(At(l.shape)>=oc)throw new Error(`values tensor size must less than ${oc}`);if(o.shape[1]>=oc)throw new Error(`trailing dim_size must less than ${oc} for int32 output type, was ${o.shape[1]}`);let u={sortedSequence:o,values:l},p={side:a};return z.runKernel($d,u,p)}var gh=D({searchSorted_:aR});function lb(e,t){return gh(e,t,\"left\")}function nR(e,t,a,n,r){let s=R(e,\"x\",\"maxPool\"),i=1,o=s,l=!1;s.rank===3&&(l=!0,o=J(s,[1,s.shape[0],s.shape[1],s.shape[2]])),P(o.rank===4,()=>`Error in maxPool: input must be rank 4 but got rank ${o.rank}.`),P(kr(a,i),()=>`Error in maxPool: Either strides or dilations must be 1. Got strides ${a} and dilations '${i}'`),Sn(\"maxPool\",n,r);let u={x:o},p={filterSize:t,strides:a,pad:n,dimRoundingMode:r},c=z.runKernel(_i,u,p);return l?J(c,[c.shape[1],c.shape[2],c.shape[3]]):c}var O2=D({maxPool_:nR});function rR(e,t=[1,1,1],a,n,r,s=\"NDHWC\"){let i=R(e,\"x\",\"maxPool3d\"),o=i,l=!1;i.rank===4&&(l=!0,o=J(i,[1,i.shape[0],i.shape[1],i.shape[2],i.shape[3]])),P(o.rank===5,()=>`Error in maxPool3d: x must be rank 5 but got rank ${o.rank}.`),P(s===\"NDHWC\",()=>`Error in maxPool3d: Only NDHWC is currently supported, but got dataFormat of ${s}`),Sn(\"maxPool3d\",n,r);let u={x:o},p={filterSize:t,strides:a,pad:n,dimRoundingMode:r,dataFormat:s},c=z.runKernel(nh,u,p);return l?J(c,[c.shape[1],c.shape[2],c.shape[3],c.shape[4]]):c}var ub=D({maxPool3d_:rR});function sR(e,t,a,n,r=!1){let s={x:R(e,\"x\",\"maxPoolWithArgmax\")},i={filterSize:t,strides:a,pad:n,includeBatchInIndex:r},o=z.runKernel(rh,s,i);return{result:o[0],indexes:o[1]}}var db=D({maxPoolWithArgmax_:sR});function iR(e,t){let a=R(e,\"a\",\"maximum\"),n=R(t,\"b\",\"maximum\");[a,n]=St(a,n),a.dtype===\"bool\"&&(a=He(a,\"int32\"),n=He(n,\"int32\")),zt(a.shape,n.shape);let r={a,b:n};return z.runKernel($i,r)}var D2=D({maximum_:iR});function oR(e,t=null,a=!1){let n={x:R(e,\"x\",\"mean\")},r={axis:t,keepDims:a};return z.runKernel(Pi,n,r)}var cd=D({mean_:oR});function fn(e,t=\"float32\"){if(Ja(e),t===\"complex64\"){let n=fn(e,\"float32\"),r=fn(e,\"float32\");return br(n,r)}let a=Gc(At(e),t);return z.makeTensor(a,e,t)}function Wr(e,t=\"float32\"){if(Ja(e),t===\"complex64\"){let n=Wr(e,\"float32\"),r=fn(e,\"float32\");return br(n,r)}let a=L1(At(e),t);return z.makeTensor(a,e,t)}function pb(e,t,{indexing:a=\"xy\"}={}){if(a!==\"xy\"&&a!==\"ij\")throw new TypeError(`${a} is not a valid third argument to meshgrid`);if(e===void 0)return[];let n=R(e,\"x\",\"meshgrid\",e instanceof pt?e.dtype:\"float32\");if(t===void 0)return[n];let r=R(t,\"y\",\"meshgrid\",t instanceof pt?t.dtype:\"float32\"),s=At(n.shape),i=At(r.shape);return a===\"xy\"?(n=J(n,[1,-1]),r=J(r,[-1,1]),[st(Wr([i,1],n.dtype),n),st(r,Wr([1,s],r.dtype))]):(n=J(n,[-1,1]),r=J(r,[1,-1]),[st(n,Wr([1,i],n.dtype)),st(Wr([s,1],r.dtype),r)])}function lR(e,t){let a=R(e,\"a\",\"minimum\"),n=R(t,\"b\",\"minimum\");[a,n]=St(a,n),a.dtype===\"bool\"&&(a=He(a,\"int32\"),n=He(n,\"int32\")),zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(Oi,r)}var z2=D({minimum_:lR});function uR(e,t,a){P(a===\"reflect\"||a===\"symmetric\",()=>`Invalid mode. Mode must be either reflect or symmetric. Got ${a}.`);let n=R(e,\"x\",\"mirrorPad\");if(n.rank===0)throw new Error(\"mirrorPad(scalar) is not defined. Pass non-scalar to mirrorPad\");P(t.length===n.rank,()=>`Padding doesn't match input. Must be ${n.rank}. Got ${t.length}.`);let r=a===\"reflect\"?1:0;for(let o=0;o<n.rank;o++)P(t[o].length===2,()=>\"Invalid number of paddings. Must be length of 2 each.\"),P(t[o][0]>=0&&t[o][0]<=n.shape[o]-r&&t[o][1]>=0&&t[o][1]<=n.shape[o]-r,()=>`Padding in dimension ${o} cannot be greater than or equal to ${n.shape[o]-r} or less than 0 for input of shape ${n.shape}`);let s={paddings:t,mode:a},i={x:n};return z.runKernel(Di,i,s)}var cb=D({mirrorPad_:uR});function dR(e,t){let a=R(e,\"a\",\"mod\"),n=R(t,\"b\",\"mod\");[a,n]=St(a,n);let r={a,b:n};return z.runKernel(Wl,r)}var su=D({mod_:dR});function pR(e,t=null,a=!1){e=R(e,\"x\",\"moments\");let n=wd(t,e.shape),r=cd(e,n,a),s=r.shape;a||(s=tp(r.shape,n));let i=In(fe(He(e,\"float32\"),J(r,s))),o=cd(i,n,a);return{mean:r,variance:o}}var hb=D({moments_:pR});function cR(e,t,a,n){let r=R(t,\"data\",\"multiRNNCell\"),s=ud(a,\"c\",\"multiRNNCell\"),i=ud(n,\"h\",\"multiRNNCell\"),o=r,l=[];for(let c=0;c<e.length;c++){let d=e[c](o,s[c],i[c]);l.push(d[0]),l.push(d[1]),o=d[1]}let u=[],p=[];for(let c=0;c<l.length;c+=2)u.push(l[c]),p.push(l[c+1]);return[u,p]}var fb=D({multiRNNCell_:cR});function hR(e,t,a,n=!1){let r=R(e,\"logits\",\"multinomial\"),s=r.size,i=r.rank;if(s<2)throw new Error(`Error in multinomial: you need at least 2 outcomes, but got ${s}.`);if(i>2)throw new Error(`Rank of probabilities must be 1 or 2, but is ${i}`);a=a||Math.random();let o={logits:i===1?J(r,[1,-1]):r},l={numSamples:t,seed:a,normalized:n},u=z.runKernel(sh,o,l);return i===1?J(u,[u.size]):u}var mb=D({multinomial_:hR});function fR(e,t){let a=R(e,\"a\",\"notEqual\",\"string_or_numeric\"),n=R(t,\"b\",\"notEqual\",\"string_or_numeric\");[a,n]=St(a,n),zt(a.shape,n.shape);let r={a,b:n};return z.runKernel(Li,r)}var L2=D({notEqual_:fR});function mR(e){let t={x:R(e,\"x\",\"onesLike\")};return z.runKernel(Gl,t)}var gb=D({onesLike_:mR});function gR(e,t){let a=R(e,\"v1\",\"outerProduct\"),n=R(t,\"v2\",\"outerProduct\");P(a.rank===1&&n.rank===1,()=>`Error in outerProduct: inputs must be rank 1, but got ranks ${a.rank} and ${n.rank}.`);let r=J(a,[-1,1]),s=J(n,[1,-1]);return st(r,s)}var xb=D({outerProduct_:gR});function xR(e,t,a=0){let n=R(e,\"x\",\"pad\");if(n.rank===0)throw new Error(\"pad(scalar) is not defined. Pass non-scalar to pad\");let r={paddings:t,constantValue:a},s={x:n};return z.runKernel(Ui,s,r)}var rr=D({pad_:xR});function AR(e,t,a=0){return P(t.length===2,()=>\"Invalid number of paddings. Must be length of 2.\"),rr(e,[t],a)}var Ab=D({pad1d_:AR});function yR(e,t,a=0){return P(t.length===2&&t[0].length===2&&t[1].length===2,()=>\"Invalid number of paddings. Must be length of 2 each.\"),rr(e,t,a)}var yb=D({pad2d_:yR});function bR(e,t,a=0){return P(t.length===3&&t[0].length===2&&t[1].length===2&&t[2].length===2,()=>\"Invalid number of paddings. Must be length of 2 each.\"),rr(e,t,a)}var bb=D({pad3d_:bR});function vR(e,t,a=0){return P(t.length===4&&t[0].length===2&&t[1].length===2&&t[2].length===2&&t[3].length===2,()=>\"Invalid number of paddings. Must be length of 2 each.\"),rr(e,t,a)}var vb=D({pad4d_:vR});function wR(e,t,a){let n=R(e,\"x\",\"spaceToBatchND\");P(n.rank>=1+t.length,()=>`input rank ${n.rank} should be > than [blockShape] ${t.length}`),P(a.length===t.length,()=>`paddings.shape[0] ${a.length} must be equal to [blockShape] ${t.length}`),P(n.shape.reduce((i,o,l)=>l>0&&l<=t.length?i&&(o+a[l-1][0]+a[l-1][1])%t[l-1]===0:i,!0),()=>`input spatial dimensions ${n.shape.slice(1)} with paddings ${a.toString()} must be divisible by blockShapes ${t.toString()}`);let r={x:n},s={blockShape:t,paddings:a};return z.runKernel(Jl,r,s)}var B2=D({spaceToBatchND_:wR});function kR(e,t,a,n,r,s,i){r==null&&(r=[1,1]),s==null&&(s=1),n===0&&(n=\"valid\");let o=R(e,\"x\",\"maxPool\"),l=o,u=!1;o.rank===3&&(u=!0,l=J(o,[1,o.shape[0],o.shape[1],o.shape[2]])),P(kr(s,r),()=>`Error in pool: Either strides or dilations must be 1. Got strides ${s} and dilations '${r}'`);let p=xy(l.shape,t,s,r,n),c=[p.dilationHeight,p.dilationWidth],d;n===\"same\"?d=SR([p.filterHeight,p.filterWidth],c):d=[[0,0],[0,0]];let h=c[0]===1&&c[1]===1,[f,m]=IR([p.inHeight,p.inWidth],c,d),g=h?n:\"valid\",x=h?l:B2(l,c,f),A=(a===\"avg\"?()=>b2(x,t,s,g,i):()=>O2(x,t,s,g,i))(),y=h?A:v2(A,c,m);return u?J(y,[y.shape[1],y.shape[2],y.shape[3]]):y}function IR(e,t,a){let n=a.map(p=>p[0]),r=a.map(p=>p[1]),s=e.concat(n,r),i=t.map((p,c)=>(p-s[c]%p)%p),o=r.map((p,c)=>p+i[c]),l=t.map((p,c)=>[n[c],o[c]]),u=t.map((p,c)=>[0,i[c]]);return[l,u]}function SR(e,t){let a=e.map((s,i)=>s+(s-1)*(t[i]-1)).map(s=>s-1),n=a.map(s=>Math.floor(s/2)),r=a.map((s,i)=>s-n[i]);return a.map((s,i)=>[n[i],r[i]])}var wb=D({pool_:kR});function TR(e,t){let a=R(e,\"x\",\"prelu\"),n=R(t,\"alpha\",\"prelu\"),r={x:a,alpha:n};return z.runKernel(Hi,r)}var W2=D({prelu_:TR});function CR(e,t=null,a=!1){let n=R(e,\"x\",\"prod\");n.dtype===\"bool\"&&(n=He(n,\"int32\"));let r={x:n},s={axis:t,keepDims:a};return z.runKernel(ji,r,s)}var kb=D({prod_:CR});function NR(e,t,a,n){let r=e.map((p,c)=>R(p,`tensors${c}`,\"raggedGather\",\"int32\")),s=R(t,\"paramsDenseValues\",\"raggedGather\"),i=R(a,\"indices\",\"raggedGather\",\"int32\"),o={paramsNestedSplits:r,paramsDenseValues:s,indices:i},l={outputRaggedRank:n},u=z.runKernel(ih,o,l);return{outputNestedSplits:u.slice(0,u.length-1),outputDenseValues:u[u.length-1]}}var Ib=D({raggedGather_:NR});function ER(e,t,a){let n=R(e,\"starts\",\"raggedRange\"),r=R(t,\"limits\",\"raggedRange\",n.dtype),s=R(a,\"deltas\",\"raggedRange\",n.dtype),i={starts:n,limits:r,deltas:s},o=z.runKernel(oh,i);return{rtNestedSplits:o[0],rtDenseValues:o[1]}}var Sb=D({raggedRange_:ER});function RR(e,t,a,n,r){let s=R(e,\"shape\",\"raggedTensorToTensor\",\"int32\"),i=R(t,\"values\",\"raggedTensorToTensor\"),o=R(a,\"defaultValue\",\"raggedTensorToTensor\",i.dtype),l=n.map((c,d)=>R(c,`tensors${d}`,\"raggedTensorToTensor\",\"int32\")),u={shape:s,values:i,defaultValue:o,rowPartitionTensors:l},p={rowPartitionTypes:r};return z.runKernel(lh,u,p)}var Tb=D({raggedTensorToTensor_:RR});function MR(e,t,a){Ja(e);let n=At(e),r=null;if(a==null||a===\"float32\")r=new Float32Array(n);else if(a===\"int32\")r=new Int32Array(n);else if(a===\"bool\")r=new Uint8Array(n);else throw new Error(`Unknown data type ${a}`);for(let s=0;s<n;s++)r[s]=t();return z.makeTensor(r,e,a)}var Cb=D({rand_:MR}),V2=yl(nA()),U2=class{constructor(e,t,a,n,r){this.mean=e,this.stdDev=t,this.dtype=a,this.nextVal=NaN,this.truncated=n,this.truncated&&(this.upper=this.mean+this.stdDev*2,this.lower=this.mean-this.stdDev*2);let s=r||Math.random();this.random=V2.alea(s.toString())}nextValue(){if(!isNaN(this.nextVal)){let n=this.nextVal;return this.nextVal=NaN,n}let e,t,a=!1;for(;!a;){let n,r,s;do n=2*this.random()-1,r=2*this.random()-1,s=n*n+r*r;while(s>=1||s===0);let i=Math.sqrt(-2*Math.log(s)/s);e=this.mean+this.stdDev*n*i,t=this.mean+this.stdDev*r*i,(!this.truncated||this.isValidTruncated(e))&&(a=!0)}return(!this.truncated||this.isValidTruncated(t))&&(this.nextVal=this.convertValue(t)),this.convertValue(e)}convertValue(e){return this.dtype==null||this.dtype===\"float32\"?e:Math.round(e)}isValidTruncated(e){return e<=this.upper&&e>=this.lower}},$R=class{constructor(e,t,a,n){this.alpha=e,this.beta=1/t,this.dtype=a;let r=n||Math.random();this.randu=V2.alea(r.toString()),this.randn=new U2(0,1,a,!1,this.randu()),e<1?this.d=e+2/3:this.d=e-1/3,this.c=1/Math.sqrt(9*this.d)}nextValue(){let e,t,a,n,r,s;for(;;){do n=this.randn.nextValue(),s=1+this.c*n;while(s<=0);if(s*=s*s,e=n*n,t=1-.331*e*e,a=.5*e+this.d*(1-s+Math.log(s)),r=this.randu(),r<t||Math.log(r)<a)break}return s=1/this.beta*this.d*s,this.alpha<1&&(s*=Math.pow(this.randu(),1/this.alpha)),this.convertValue(s)}convertValue(e){return this.dtype===\"float32\"?e:Math.round(e)}},_R=class{constructor(e=0,t=1,a,n){if(this.canReturnFloat=()=>this.dtype==null||this.dtype===\"float32\",this.min=e,this.range=t-e,this.dtype=a,n==null&&(n=Math.random()),typeof n==\"number\"&&(n=n.toString()),!this.canReturnFloat()&&this.range<=1)throw new Error(`The difference between ${e} - ${t} <= 1 and dtype is not float`);this.random=V2.alea(n)}convertValue(e){return this.canReturnFloat()?e:Math.round(e)}nextValue(){return this.convertValue(this.min+this.range*this.random())}};function PR(e,t,a=1,n=\"float32\",r){if(Ja(e),a==null&&(a=1),n==null&&(n=\"float32\"),n!==\"float32\"&&n!==\"int32\")throw new Error(`Unsupported data type ${n}`);let s=new $R(t,a,n,r),i=Me(e,n);for(let o=0;o<i.values.length;o++)i.values[o]=s.nextValue();return i.toTensor()}var Nb=D({randomGamma_:PR});function FR(e,t=0,a=1,n,r){if(Ja(e),n!=null&&n===\"bool\")throw new Error(`Unsupported data type ${n}`);let s=new U2(t,a,n,!1,r),i=Me(e,n);for(let o=0;o<i.values.length;o++)i.values[o]=s.nextValue();return i.toTensor()}var G2=D({randomNormal_:FR});function OR(e,t,a){if(t!=null&&t===\"bool\")throw new Error(`Unsupported data type ${t}`);return G2(e,0,1,t,a)}var Eb=D({randomStandardNormal_:OR});function DR(e,t=0,a=1,n=\"float32\",r){Ja(e);let s=Me(e,n),i=new _R(t,a,null,r);for(let o=0;o<s.values.length;o++)s.values[o]=i.nextValue();return s.toTensor()}var H2=D({randomUniform_:DR});function hl(e,t,a=1,n=\"float32\"){if(a===0)throw new Error(\"Cannot have a step of zero\");let r={start:e,stop:t,step:a,dtype:n};return z.runKernel(jl,{},r)}function zR(e){let t={x:R(e,\"x\",\"reciprocal\")};return z.runKernel(qi,t)}var Rb=D({reciprocal_:zR});function LR(e){let t={x:R(e,\"x\",\"relu\")};return z.runKernel(Xi,t)}var rp=D({relu_:LR});function BR(e){let t={x:R(e,\"x\",\"relu6\")};return z.runKernel(Yi,t)}var j2=D({relu6_:BR});function WR(e,t){let a={x:R(e,\"x\",\"reverse\")},n={dims:t};return z.runKernel(Ji,a,n)}var Yr=D({reverse_:WR});function VR(e){let t=R(e,\"x\",\"reverse\");return P(t.rank===1,()=>`Error in reverse1D: x must be rank 1 but got rank ${t.rank}.`),Yr(t,0)}var Mb=D({reverse1d_:VR});function UR(e,t){let a=R(e,\"x\",\"reverse\");return P(a.rank===2,()=>`Error in reverse2D: x must be rank 2 but got rank ${a.rank}.`),Yr(a,t)}var $b=D({reverse2d_:UR});function GR(e,t){let a=R(e,\"x\",\"reverse\");return P(a.rank===3,()=>`Error in reverse3D: x must be rank 3 but got rank ${a.rank}.`),Yr(a,t)}var _b=D({reverse3d_:GR});function HR(e,t){let a=R(e,\"x\",\"reverse\");return P(a.rank===4,()=>`Error in reverse4D: x must be rank 4 but got rank ${a.rank}.`),Yr(a,t)}var Pb=D({reverse4d_:HR});function jR(e){let t={x:R(e,\"x\",\"round\")};return z.runKernel(Xl,t)}var q2=D({round_:jR});function qR(e){let t={x:R(e,\"x\",\"rsqrt\",\"float32\")};return z.runKernel(Qi,t)}var Fb=D({rsqrt_:qR});function XR(e){let t={x:R(e,\"x\",\"selu\")};return z.runKernel(_d,t)}var Ob=D({selu_:XR});function KR(e,t,a,n,r,s=[1,1],i=\"NHWC\"){let o=R(e,\"x\",\"separableConv2d\"),l=R(t,\"depthwiseFilter\",\"separableConv2d\"),u=R(a,\"pointwiseFilter\",\"separableConv2d\"),p=o,c=!1;if(o.rank===3&&(c=!0,p=J(o,[1,o.shape[0],o.shape[1],o.shape[2]])),i===\"NCHW\")throw new Error(\"separableConv2d currently does not support dataFormat NCHW; only NHWC is supported\");P(p.rank===4,()=>`Error in separableConv2d: input must be rank 4, but got rank ${p.rank}.`),P(l.rank===4,()=>`Error in separableConv2d: depthwise filter must be rank 4, but got rank ${l.rank}.`),P(u.rank===4,()=>`Error in separableConv2d: pointwise filter must be rank 4, but got rank ${l.rank}.`),P(u.shape[0]===1,()=>`Error in separableConv2d: the first dimension of pointwise filter  must be 1, but got ${u.shape[0]}.`),P(u.shape[1]===1,()=>`Error in separableConv2d: the second dimension of pointwise filter must be 1, but got ${u.shape[1]}.`);let d=l.shape[2],h=l.shape[3];P(u.shape[2]===d*h,()=>`Error in separableConv2d: the third dimension of pointwise filter must be ${d*h}, but got ${u.shape[2]}.`);let f=hh(p,l,n,r,i,s),m=ep(f,u,1,\"valid\",i);return c?J(m,[m.shape[1],m.shape[2],m.shape[3]]):m}var Db=D({separableConv2d_:KR});async function ZR(e,t){let a=R(e,\"x\",\"setdiff1d\"),n=R(t,\"y\",\"setdiff1d\");P(a.dtype===n.dtype,()=>`x and y should have the same dtype, but got x (${a.dtype}) and y (${n.dtype}).`),P(a.rank===1,()=>`x should be 1D tensor, but got x (${a.shape}).`),P(n.rank===1,()=>`y should be 1D tensor, but got y (${n.shape}).`);let r=await a.data(),s=await n.data(),i=new Set(s),o=0;for(let p=0;p<r.length;p++)i.has(r[p])||o++;let l=new jt([o],a.dtype),u=new jt([o],\"int32\");for(let p=0,c=0;p<r.length;p++)i.has(r[p])||(l.values[c]=r[p],u.values[c]=p,c++);return[l.toTensor(),u.toTensor()]}var zb=ZR;function YR(e){let t={x:R(e,\"x\",\"sign\")};return z.runKernel(Pd,t)}var Lb=D({sign_:YR});function JR(e){let t={x:R(e,\"x\",\"sin\",\"float32\")};return z.runKernel(to,t)}var Bb=D({sin_:JR});function QR(e){let t={x:R(e,\"x\",\"sinh\")};return z.runKernel(Yl,t)}var Wb=D({sinh_:QR});function eM(e,t,a){let n=R(e,\"x\",\"slice1d\");return P(n.rank===1,()=>`slice1d expects a rank-1 tensor, but got a rank-${n.rank} tensor`),Pe(n,[t],[a])}var Vb=D({slice1d_:eM});function tM(e,t,a){let n=R(e,\"x\",\"slice2d\");return P(n.rank===2,()=>`slice2d expects a rank-2 tensor, but got a rank-${n.rank} tensor`),Pe(n,t,a)}var Ub=D({slice2d_:tM});function aM(e,t,a){let n=R(e,\"x\",\"slice3d\");return P(n.rank===3,()=>`slice3d expects a rank-3 tensor, but got a rank-${n.rank} tensor`),Pe(n,t,a)}var sp=D({slice3d_:aM});function nM(e,t,a){let n=R(e,\"x\",\"slice4d\");return P(n.rank===4,()=>`slice4d expects a rank-4 tensor, but got a rank-${n.rank} tensor`),Pe(n,t,a)}var xh=D({slice4d_:nM});function rM(e,t=-1){let a=R(e,\"logits\",\"softmax\",\"float32\");if(t===-1&&(t=a.rank-1),t!==a.rank-1)throw Error(`Softmax along a non-last dimension is not yet supported. Logits was rank ${a.rank} and dim was ${t}`);let n={logits:a},r={dim:t};return z.runKernel(so,n,r)}var Ah=D({softmax_:rM});function sM(e){P(e.dtype===\"complex64\",()=>`The dtype for tf.spectral.fft() must be complex64 but got ${e.dtype}.`);let t={input:e};return z.runKernel(Nd,t)}var yh=D({fft_:sM});function iM(e){P(e.dtype===\"complex64\",()=>`The dtype for tf.spectral.ifft() must be complex64 but got ${e.dtype}.`);let t={input:e};return z.runKernel(Ed,t)}var hd=D({ifft_:iM});function oM(e){let t=e.shape[e.shape.length-1],a=e.size/t,n;if(t<=2){let r=J(e,[a,t]);n=hd(r)}else{let r=[a,2*(t-1)],s=J(dl(e),[a,t]),i=J(Zd(e),[a,t]),o=Yr(Pe(s,[0,1],[a,t-2]),1),l=ae(Yr(Pe(i,[0,1],[a,t-2]),1),Fe(-1)),u=at([s,o],1),p=at([i,l],1),c=J(br(u,p),[r[0],r[1]]);n=hd(c)}if(n=dl(n),e.rank===3&&e.shape[0]!==0){let r=n,s=e.shape[0];n=J(n,[s,n.shape[0]/s,n.shape[1]]),r.dispose()}return n}var X2=D({irfft_:oM});function lM(e,t,a=0){let n={x:R(e,\"x\",\"split\")},r={numOrSizeSplits:t,axis:a};return z.runKernel(Ql,n,r)}var ka=D({split_:lM});function uM(e,t){P(e.dtype===\"float32\",()=>`The dtype for rfft() must be real value but got ${e.dtype}`);let a=e.shape[e.shape.length-1],n=e.size/a,r;if(t!=null&&t<a){let f=e.shape.map(g=>0),m=e.shape.map(g=>g);m[e.shape.length-1]=t,r=Pe(e,f,m),a=t}else if(t!=null&&t>a){let f=e.shape.map(m=>m);f[e.shape.length-1]=t-a,r=at([e,fn(f)],e.shape.length-1),a=t}else r=e;let s=Ka(r),i=J(br(r,s),[n,a]),o=yh(i),l=Math.floor(a/2)+1,u=dl(o),p=Zd(o),c=ka(u,[l,a-l],u.shape.length-1),d=ka(p,[l,a-l],p.shape.length-1),h=r.shape.slice();return h[r.shape.length-1]=l,J(br(c[0],d[0]),h)}var bh=D({rfft_:uM});function dM(e,t){let a=R(e,\"a\",\"squaredDifference\"),n=R(t,\"b\",\"squaredDifference\");[a,n]=St(a,n),zt(a.shape,n.shape);let r={a,b:n},s={};return z.runKernel(io,r,s)}var K2=D({squaredDifference_:dM});function pM(e,t){let a=R(e,\"x\",\"squeeze\",\"string_or_numeric\");return J(a,iA(a.shape,t).newShape)}var _e=D({squeeze_:pM});function cM(e,t=0){let a=ud(e,\"tensors\",\"stack\",\"string_or_numeric\");P(a.length>=1,()=>\"Pass at least one tensor to tf.stack\"),a.length>0&&P(t<=a[0].rank,()=>\"Axis must be <= rank of the tensor\");let n=a,r={axis:t};return z.runKernel(Hl,n,r)}var sa=D({stack_:cM});function hM(e,t=0){let a={x:R(e,\"x\",\"step\")},n={alpha:t};return z.runKernel(fo,a,n)}var Z2=D({step_:hM});function fM(e,t,a,n,r=0,s=0,i=0,o=0,l=0){let u={x:R(e,\"x\",\"stridedSlice\",\"string_or_numeric\")},p={begin:t,end:a,strides:n,beginMask:r,endMask:s,ellipsisMask:i,newAxisMask:o,shrinkAxisMask:l};return z.runKernel(oo,u,p)}var Gb=D({stridedSlice_:fM});function mM(e){let t={x:R(e,\"x\",\"tan\",\"float32\")};return z.runKernel(uo,t)}var Hb=D({tan_:mM});function Ht(e,t){Xs(e);let a=Yn(e,t);if(a.length!==1)throw new Error(\"tensor1d() requires values to be a flat/TypedArray\");return rs(e,null,a,t)}function Kn(e,t,a){if(Xs(e),t!=null&&t.length!==2)throw new Error(\"tensor2d() requires shape to have two numbers\");let n=Yn(e,a);if(n.length!==2&&n.length!==1)throw new Error(\"tensor2d() requires values to be number[][] or flat/TypedArray\");if(n.length===1&&t==null)throw new Error(\"tensor2d() requires shape to be provided when `values` are a flat/TypedArray\");return rs(e,t,n,a)}function jb(e,t,a){if(Xs(e),t!=null&&t.length!==4)throw new Error(\"tensor4d() requires shape to have four numbers\");let n=Yn(e,a);if(n.length!==4&&n.length!==1)throw new Error(\"tensor4d() requires values to be number[][][][] or flat/TypedArray\");if(n.length===1&&t==null)throw new Error(\"tensor4d() requires shape to be provided when `values` are a flat array\");return rs(e,t,n,a)}function qb(e,t,a){if(Xs(e),t!=null&&t.length!==5)throw new Error(\"tensor5d() requires shape to have five numbers\");let n=Yn(e,a);if(n.length!==5&&n.length!==1)throw new Error(\"tensor5d() requires values to be number[][][][][] or flat/TypedArray\");if(n.length===1&&t==null)throw new Error(\"tensor5d() requires shape to be provided when `values` are a flat array\");return rs(e,t,n,a)}function Xb(e,t,a){if(Xs(e),t!=null&&t.length!==6)throw new Error(\"tensor6d() requires shape to have six numbers\");let n=Yn(e,a);if(n.length!==6&&n.length!==1)throw new Error(\"tensor6d() requires values to be number[][][][][][] or flat/TypedArray\");if(n.length===1&&t==null)throw new Error(\"tensor6d() requires shape to be provided when `values` are a flat array\");return t=t||n,rs(e,t,n,a)}function gM(e,t=1,a=!0){let n=R(e,\"x\",\"topk\");if(n.rank===0)throw new Error(\"topk() expects the input to be of rank 1 or higher\");let r=n.shape[n.shape.length-1];if(t<0)throw new Error(`'k' passed to topk() must be >= 0 but got ${t}`);if(t>r)throw new Error(`'k' passed to topk() must be <= the last dimension (${r}) but got ${t}`);let s={x:n},i={k:t,sorted:a},[o,l]=z.runKernel(co,s,i);return{values:o,indices:l}}var Kb=D({topk_:gM});function xM(e,t=0,a=1,n,r){if(Ja(e),n!=null&&n===\"bool\")throw new Error(\"Unsupported data type $ { dtype }\");let s=new U2(t,a,n,!0,r),i=Me(e,n);for(let o=0;o<i.values.length;o++)i.values[o]=s.nextValue();return i.toTensor()}var Zb=D({truncatedNormal_:xM});function AM(e,t=0){let a=R(e,\"x\",\"unique\",\"string_or_numeric\");P(a.rank>0,()=>\"The input tensor must be at least 1D\");let n={x:a},r={axis:t},[s,i]=z.runKernel(uh,n,r);return{values:s,indices:i}}var Yb=D({unique_:AM});function yM(e,t,a){let n=R(e,\"x\",\"unsortedSegmentSum\"),r=R(t,\"segmentIds\",\"unsortedSegmentSum\",\"int32\");P(ol(a),()=>\"numSegments must be of dtype int\");let s={x:n,segmentIds:r},i={numSegments:a};return z.runKernel(dh,s,i)}var Jb=D({unsortedSegmentSum_:yM});function bM(e,t=0){let a=R(e,\"x\",\"unstack\",\"string_or_numeric\");P(t>=-a.shape.length&&t<a.shape.length,()=>`Axis = ${t} is not in [-${a.shape.length}, ${a.shape.length})`);let n={value:a},r={axis:t};return z.runKernel(au,n,r)}var Ta=D({unstack_:bM});function Qb(e,t){return gh(e,t,\"right\")}function e4(e,t=!0,a,n){return z.makeVariable(e,t,a,n)}function t4(e,t){let a=[];for(let s=0;s<t.length;s++)t[s]&&a.push(s);let n=Me(e,\"int32\"),r=Me([a.length,e.length],\"int32\");for(let s=0;s<a.length;s++){let i=n.indexToLoc(a[s]),o=s*e.length;r.values.set(i,o)}return r.toTensor()}async function vM(e){let t=R(e,\"condition\",\"whereAsync\",\"bool\"),a=await t.data(),n=t4(t.shape,a);return e!==t&&t.dispose(),n}var Y2=vM;async function wM(e,t,a){let n=R(e,\"tensor\",\"boolMask\"),r=R(t,\"mask\",\"boolMask\",\"bool\"),s=a==null?0:a,i=r.rank,o=n.shape;P(i>0,()=>\"mask cannot be scalar\"),Sa(o.slice(s,s+i),r.shape,\"mask's shape must match the first K dimensions of tensor's shape,\");let l=1;for(let m=s;m<s+i;m++)l*=o[m];let u=o.slice(0,s).concat([l],o.slice(s+i)),p=J(n,u),c=J(r,[-1]),d=await Y2(c),h=_e(d,[1]),f=N2(p,h,s);return e!==n&&n.dispose(),t!==r&&r.dispose(),h.dispose(),p.dispose(),c.dispose(),d.dispose(),f}var a4=wM;function kM(e,t,a,n,r=!0){let s=R(e,\"v\",\"movingAverage\"),i=R(t,\"x\",\"movingAverage\"),o=R(a,\"decay\",\"movingAverage\");wA(s,i),P(es(s.shape,i.shape),()=>\"Shape mismatch in v and x\");let l=Fe(1),u=fe(l,o),p=ae(fe(i,s),u);if(r){P(n!=null,()=>\"When using zeroDebias: true, step is required.\");let c=R(n,\"step\",\"movingAverage\");p=me(p,fe(l,pl(o,c)))}return be(s,p)}var n4=D({movingAverage_:kM});function IM(e,t,a){Ja(a);let n=R(e,\"indices\",\"scatterND\",\"int32\"),r=R(t,\"updates\",\"scatterND\");m2(r,n,a);let s={indices:n,updates:r},i={shape:a};return z.runKernel(eo,s,i)}var r4=D({scatterND_:IM});function SM(e,t,a,n){if(e.dtype!==\"int32\")throw new Error(`tf.sparseToDense() expects the indices to be int32 type, but the dtype was ${e.dtype}.`);if(e.rank>2)throw new Error(`sparseIndices should be a scalar, vector, or matrix, but got shape ${e.shape}.`);let r=e.rank>0?e.shape[0]:1,s=e.rank>1?e.shape[1]:1;if(a.length!==s)throw new Error(`outputShape has incorrect number of elements:, ${a.length}, should be: ${s}.`);let i=t.size;if(!(t.rank===0||t.rank===1&&i===r))throw new Error(`sparseValues has incorrect shape ${t.shape}, should be [] or [${r}]`);if(t.dtype!==n.dtype)throw new Error(\"sparseValues.dtype must match defaultValues.dtype\")}function TM(e,t,a,n=0){Ja(a);let r=R(e,\"sparseIndices\",\"sparseToDense\",\"int32\"),s=R(t,\"sparseValues\",\"sparseToDense\",\"string_or_numeric\"),i=R(n,\"defaultValue\",\"sparseToDense\",s.dtype);SM(r,s,a,i);let o={sparseIndices:r,sparseValues:s,defaultValue:i},l={outputShape:a};return z.runKernel(Ld,o,l)}var s4=D({sparseToDense_:TM});function CM(e,t){let a=R(t,\"indices\",\"gatherND\",\"int32\"),n={params:R(e,\"x\",\"gatherND\",\"string_or_numeric\"),indices:a};return z.runKernel(bi,n)}var i4=D({gatherND_:CM});function NM(e,t){if(t==null)return e.shape.slice();if(es(e.shape,t))return t;if(e.shape.length===t.length){let a=[];for(let n=0;n<e.shape.length;n++)t[n]==null&&e.shape[n]!=null?a.push(e.shape[n]):a.push(t[n]);return a}return t}function EM(e,t,a,n){let r=R(e,\"x\",\"dropout\");if(P(r.dtype===\"float32\",()=>`x has to be a floating point tensor since it's going to be scaled, but got a ${r.dtype} tensor instead.`),P(t>=0&&t<1,()=>`rate must be a float in the range [0, 1), but got ${t}.`),t===0)return e instanceof pt?r.clone():r;let s=NM(r,a),i=1-t,o=me(C2(be(H2(s,0,1,\"float32\",n),i)),i);return ae(r,o)}var o4=D({dropout_:EM});function J2(e){return Math.floor(Math.pow(2,Math.ceil(Math.log(e)/Math.log(2))))}function vh(e,t,a){let n=1-e%2,r=new Float32Array(e);for(let s=0;s<e;++s){let i=2*Math.PI*s/(e+n-1);r[s]=t-a*Math.cos(i)}return Ht(r,\"float32\")}async function RM(e,t,a=1){let n=R(e,\"predictions\",\"inTopK\"),r=R(t,\"targets\",\"inTopK\");P(n.rank>1,()=>`inTopK() expects the predictions to be of rank 2 or higher, but got ${n.rank}`),P(n.rank-1===r.rank,()=>`predictions rank should be 1 larger than targets rank, but got predictions rank ${n.rank} and targets rank ${r.rank}`),Sa(n.shape.slice(0,n.shape.length-1),r.shape,\"predictions's shape should be align with the targets' shape, except the last dimension.\");let s=n.shape[n.shape.length-1];P(a>0&&a<=s,()=>`'k' passed to inTopK() must be > 0 && <= the predictions last dimension (${s}), but got ${a}`);let i=await n.data(),o=await r.data(),[l,u]=[i.length/s,s],p=oA(\"bool\",l);for(let c=0;c<l;c++){let d=c*u,h=i.subarray(d,d+u),f=[];for(let m=0;m<h.length;m++)f.push({value:h[m],index:m});f.sort((m,g)=>g.value-m.value),p[c]=0;for(let m=0;m<a;m++)if(f[m].index===o[c]){p[c]=1;break}}return e!==n&&n.dispose(),t!==r&&r.dispose(),Be(p,r.shape,\"bool\")}var l4=RM,Q2={};Xe(Q2,{conv2d:()=>PM,depthwiseConv2d:()=>BM,matMul:()=>VM});function MM(e,t,a,n,r,s=\"NHWC\",i){let o=e;e.rank===3&&(o=J(e,[1,e.shape[0],e.shape[1],e.shape[2]]));let l=t;l.rank===3&&(l=J(t,[1,t.shape[0],t.shape[1],t.shape[2]])),P(o.rank===4,()=>`Error in conv2dDerFilter: input must be rank 4, but got shape ${o.shape}.`),P(l.rank===4,()=>`Error in conv2dDerFilter: dy must be rank 4, but got shape ${l.shape}.`),P(a.length===4,()=>`Error in conv2dDerFilter: filterShape must be length 4, but got ${a}.`);let u=s===\"NHWC\"?o.shape[3]:o.shape[1],p=s===\"NHWC\"?l.shape[3]:l.shape[1];P(u===a[2],()=>`Error in conv2dDerFilter: depth of input ${u}) must match input depth in filter (${a[2]}.`),P(p===a[3],()=>`Error in conv2dDerFilter: depth of dy (${p}) must match output depth for filter (${a[3]}).`),Sn(\"conv2dDerFilter\",r,i);let c={x:o,dy:l},d={strides:n,pad:r,dataFormat:s,dimRoundingMode:i,filterShape:a};return z.runKernel(Xc,c,d)}var $M=D({conv2DBackpropFilter_:MM});function wh(e,t,a){if(a==null||a===\"linear\")return e;if(a===\"relu\")return ae(e,Z2(t));throw new Error(`Cannot compute gradient for fused activation ${a}.`)}function kh(e,t){let a=t,n=d2(e.shape,t.shape);return n.length>0&&(a=tt(a,n)),J(a,e.shape)}function Ih(e,t,a,n){if(t===\"linear\")return e;if(t===\"relu\")return rp(e);if(t===\"elu\")return I2(e);if(t===\"relu6\")return j2(e);if(t===\"prelu\")return W2(e,a);if(t===\"leakyrelu\")return R2(e,n);if(t===\"sigmoid\")return Da(e);throw new Error(`Unknown fused activation ${t}.`)}var Sh=(e,t)=>!(e>0)||t===\"linear\";function _M({x:e,filter:t,strides:a,pad:n,dataFormat:r=\"NHWC\",dilations:s=[1,1],dimRoundingMode:i,bias:o,activation:l=\"linear\",preluActivationWeights:u,leakyreluAlpha:p}){if(l=l||\"linear\",Sh(z.state.gradientDepth,l)===!1){P(r===\"NHWC\",()=>`Error in fused conv2d: got dataFormat of ${r} but only NHWC is currently supported for the case of gradient depth is 0 and the activation is not linear.`);let S=ep(e,t,a,n,r,s,i);return o!=null&&(S=be(S,o)),Ih(S,l,u,p)}let c=R(e,\"x\",\"conv2d\",\"float32\"),d=R(t,\"filter\",\"conv2d\",\"float32\"),h=c,f=!1;c.rank===3&&(f=!0,h=J(c,[1,c.shape[0],c.shape[1],c.shape[2]])),P(h.rank===4,()=>`Error in fused conv2d: input must be rank 4, but got rank ${h.rank}.`),P(d.rank===4,()=>`Error in fused conv2d: filter must be rank 4, but got rank ${d.rank}.`),Sn(\"fused conv2d\",n,i);let m=r===\"NHWC\"?h.shape[3]:h.shape[1];P(d.shape[2]===m,()=>`Error in conv2d: depth of input (${m}) must match input depth for filter ${d.shape[2]}.`),P(kr(a,s),()=>`Error in conv2D: Either strides or dilations must be 1. Got strides ${a} and dilations '${s}'`);let g=Jd(h.shape,d.shape,a,s,n,i),x;o!=null&&(x=R(o,\"bias\",\"fused conv2d\"),[x]=St(x,c),r===\"NHWC\"?zt(g.outShape,x.shape):(P(x.shape.length<=1,()=>`Error in fused conv2d: only supports scalar or 1-D Tensor bias for NCHW format but got the bias of rank-${x.shape.length}.`),P(x.shape.length===0||x.shape[0]===g.outChannels||x.shape[0]===1,()=>`Error in fused conv2d: bias shape (${x.shape}) is not compatible with the number of output channels (${g.outChannels})`)));let A;if(u!=null){let S=u.shape;if(P(S.length<=1||S.length===3,()=>`Error in fused conv2d: only supports scalar, 1-D Tensor or 3-D Tensor PReLU activation weights but got a tensor of rank-${S.length}.`),S.length===1)P(S[0]===1||S[0]===g.outChannels,()=>`Error in fused conv2d: PReLU activation weights (${S}) is not compatible with the number of output channels (${g.outChannels}).`);else if(S.length===3)try{zt(S,g.outShape)}catch(C){let E=`Error in fused conv2d: PReLU activation weights (${S}) is not compatible with the output shape of the conv2d (${g.outShape}).`;throw Error(E)}A=R(u,\"prelu weights\",\"fused conv2d\")}let y=(S,C)=>{P(r===\"NHWC\",()=>`Error in gradient of fused conv2D: got dataFormat of ${r} but only NHWC is currently supported.`);let[E,_,$,M]=C,I=wh(S,$,l);P(dd(s),()=>`Error in gradient of fused conv2D: dilation rates greater than 1 are not yet supported in gradients. Got dilations '${s}'`);let N=$y(_.shape,I,E,a,n),O=$M(_,I,E.shape,a,n),L=[N,O];if(M!=null){let B=kh(M,I);L.push(B)}return L},b={x:h,filter:d,bias:x,preluActivationWeights:A},w={strides:a,pad:n,dataFormat:r,dilations:s,dimRoundingMode:i,activation:l,leakyreluAlpha:p};return o==null?Qn((S,C,E)=>{let _=z.runKernel(qr,b,w);return E([C,S,_]),f&&(_=J(_,[_.shape[1],_.shape[2],_.shape[3]])),{value:_,gradFunc:y}})(h,d):Qn((S,C,E,_)=>{let $=z.runKernel(qr,b,w);return _([C,S,$,E]),f&&($=J($,[$.shape[1],$.shape[2],$.shape[3]])),{value:$,gradFunc:y}})(h,d,x)}var PM=D({fusedConv2d_:_M});function FM(e,t,a,n,r,s=[1,1],i){let o=e;e.rank===3&&(o=J(e,[1,e.shape[0],e.shape[1],e.shape[2]]));let l=t;l.rank===3&&(l=J(t,[1,t.shape[0],t.shape[1],t.shape[2]]));let u={x:o,dy:l},p={strides:n,pad:r,dimRoundingMode:i,dilations:s,filterShape:a};return z.runKernel(Yc,u,p)}var OM=D({depthwiseConv2dNativeBackpropFilter_:FM});function DM(e,t,a,n,r,s=[1,1],i){let o=t,l=!1;t.rank===3&&(l=!0,o=J(t,[1,t.shape[0],t.shape[1],t.shape[2]]));let u={dy:o,filter:a},p={strides:n,pad:r,dimRoundingMode:i,dilations:s,inputShape:e},c=z.runKernel(Jc,u,p);return l?J(c,[c.shape[1],c.shape[2],c.shape[3]]):c}var zM=D({depthwiseConv2dNativeBackpropInput_:DM});function LM({x:e,filter:t,strides:a,pad:n,dataFormat:r=\"NHWC\",dilations:s=[1,1],dimRoundingMode:i,bias:o,activation:l=\"linear\",preluActivationWeights:u,leakyreluAlpha:p}){if(Sh(z.state.gradientDepth,l)===!1){let w=hh(e,t,a,n,r,s,i);return o!=null&&(w=be(w,o)),Ih(w,l,u,p)}let c=R(e,\"x\",\"depthwiseConv2d\",\"float32\"),d=R(t,\"filter\",\"depthwiseConv2d\",\"float32\"),h=c,f=!1;c.rank===3&&(f=!0,h=J(c,[1,c.shape[0],c.shape[1],c.shape[2]])),P(h.rank===4,()=>`Error in fused depthwiseConv2d: input must be rank 4, but got rank ${h.rank}.`),P(d.rank===4,()=>`Error in fused depthwiseConv2d: filter must be rank 4, but got rank ${d.rank}.`),P(h.shape[3]===d.shape[2],()=>`Error in fused depthwiseConv2d: number of input channels (${h.shape[3]}) must match the inChannels dimension in filter ${d.shape[2]}.`),s==null&&(s=[1,1]),P(kr(a,s),()=>`Error in fused depthwiseConv2d: Either strides or dilations must be 1. Got strides ${a} and dilations '${s}'`),Sn(\"fused depthwiseConv2d\",n,i);let m=Jd(h.shape,d.shape,a,s,n,i,!0),g;o!=null&&(g=R(o,\"bias\",\"fused conv2d\"),[g]=St(g,c),zt(m.outShape,g.shape));let x;u!=null&&(x=R(u,\"prelu weights\",\"fused depthwiseConv2d\"));let A=(w,S)=>{P(dd(s),()=>`Error in gradient of fused depthwiseConv2d: dilation rates greater than 1 are not yet supported. Got dilations '${s}'`);let[C,E,_,$]=S,M=wh(w,_,l),I=zM(E.shape,M,C,a,n,s,i),N=OM(E,M,C.shape,a,n,s,i);if($!=null){let O=kh(g,M);return[I,N,O]}return[I,N]},y={x:h,filter:d,bias:g,preluActivationWeights:x},b={strides:a,pad:n,dataFormat:r,dilations:s,dimRoundingMode:i,activation:l,leakyreluAlpha:p};return o==null?Qn((w,S,C)=>{let E=z.runKernel(Xr,y,b);return C([S,w,E]),f&&(E=J(E,[E.shape[1],E.shape[2],E.shape[3]])),{value:E,gradFunc:A}})(h,d):Qn((w,S,C,E)=>{let _=z.runKernel(Xr,y,b);return E([S,w,_,C]),f&&(_=J(_,[_.shape[1],_.shape[2],_.shape[3]])),{value:_,gradFunc:A}})(h,d,g)}var BM=D({fusedDepthwiseConv2d_:LM});function WM({a:e,b:t,transposeA:a=!1,transposeB:n=!1,bias:r,activation:s=\"linear\",preluActivationWeights:i,leakyreluAlpha:o=.2}){if(Sh(z.state.gradientDepth,s)===!1){let $=st(e,t,a,n);return r!=null&&($=be($,r)),Ih($,s,i,o)}let l=R(e,\"a\",\"fused matMul\"),u=R(t,\"b\",\"fused matMul\");[l,u]=St(l,u);let p=a?l.shape[l.rank-2]:l.shape[l.rank-1],c=n?u.shape[u.rank-1]:u.shape[u.rank-2],d=a?l.shape[l.rank-1]:l.shape[l.rank-2],h=n?u.shape[u.rank-2]:u.shape[u.rank-1],f=l.shape.slice(0,-2),m=u.shape.slice(0,-2),g=At(f),x=At(m);P(p===c,()=>`Error in fused matMul: inner shapes (${p}) and (${c}) of Tensors with shapes ${l.shape} and ${u.shape} and transposeA=${a} and transposeB=${n} must match.`);let A=zt(l.shape.slice(0,-2),u.shape.slice(0,-2)).concat([d,h]),y=a?J(l,[g,p,d]):J(l,[g,d,p]),b=n?J(u,[x,h,c]):J(u,[x,c,h]),w;r!=null&&(w=R(r,\"bias\",\"fused matMul\"),[w]=St(w,l),zt(A,w.shape));let S;i!=null&&(S=R(i,\"prelu weights\",\"fused matMul\"));let C=($,M)=>{let[I,N,O,L]=M,B=wh(J($,O.shape),O,s),G,j;if(!a&&!n?(G=st(B,N,!1,!0),j=st(I,B,!0,!1)):!a&&n?(G=st(B,N,!1,!1),j=st(B,I,!0,!1)):a&&!n?(G=st(N,B,!1,!0),j=st(I,B,!1,!1)):(G=st(N,B,!0,!0),j=st(B,I,!0,!0)),r!=null){let U=kh(L,B);return[G,j,U]}else return[G,j]},E={a:y,b,bias:w,preluActivationWeights:S},_={transposeA:a,transposeB:n,activation:s,leakyreluAlpha:o};return r==null?Qn(($,M,I)=>{let N=z.runKernel(jr,E,_);return I([$,M,N]),{value:J(N,A),gradFunc:C}})(y,b):Qn(($,M,I,N)=>{let O=z.runKernel(jr,E,_);return N([$,M,O,I]),{value:J(O,A),gradFunc:C}})(y,b,w)}var VM=D({fusedMatMul_:WM});function UM(e){return vh(e,.54,.46)}var GM=D({hammingWindow_:UM});function HM(e){return vh(e,.5,.5)}var u4=D({hannWindow_:HM});function jM(e,t,a,n=!1,r=0){let s=0,i=[];for(;s+t<=e.size;)i.push(Pe(e,s,t)),s+=a;if(n)for(;s<e.size;){let o=s+t-e.size,l=at([Pe(e,s,t-o),nr([o],r)]);i.push(l),s+=a}return i.length===0?Kn([],[0,t]):J(at(i),[i.length,t])}var d4=D({frame_:jM});function qM(e,t,a,n,r=u4){n==null&&(n=J2(t));let s=d4(e,t,a),i=ae(s,r(t));return bh(i,n)}var XM=D({stft_:qM});function KM(e,t,a,n,r=\"bilinear\",s=0){let i=R(e,\"image\",\"cropAndResize\"),o=R(t,\"boxes\",\"cropAndResize\",\"float32\"),l=R(a,\"boxInd\",\"cropAndResize\",\"int32\"),u=o.shape[0];P(i.rank===4,()=>`Error in cropAndResize: image must be rank 4,but got rank ${i.rank}.`),P(o.rank===2&&o.shape[1]===4,()=>`Error in cropAndResize: boxes must be have size [${u},4] but had shape ${o.shape}.`),P(l.rank===1&&l.shape[0]===u,()=>`Error in cropAndResize: boxInd must be have size [${u}] but had shape ${o.shape}.`),P(n.length===2,()=>`Error in cropAndResize: cropSize must be of length 2, but got length ${n.length}.`),P(n[0]>=1&&n[1]>=1,()=>`cropSize must be atleast [1,1], but was ${n}`),P(r===\"bilinear\"||r===\"nearest\",()=>`method must be bilinear or nearest, but was ${r}`);let p={image:i,boxes:o,boxInd:l},c={method:r,extrapolationValue:s,cropSize:n};return z.runKernel(ui,p,c)}var ZM=D({cropAndResize_:KM});function YM(e){let t=R(e,\"image\",\"flipLeftRight\",\"float32\");P(t.rank===4,()=>`Error in flipLeftRight: image must be rank 4,but got rank ${t.rank}.`);let a={image:t};return z.runKernel(gi,a,{})}var JM=D({flipLeftRight_:YM});function QM(e){let t=R(e,\"image\",\"grayscaleToRGB\"),a=t.rank-1,n=t.shape[a];P(t.rank>=2,()=>`Error in grayscaleToRGB: images must be at least rank 2, but got rank ${t.rank}.`),P(n===1,()=>`Error in grayscaleToRGB: last dimension of a grayscale image should be size 1, but got size ${n}.`);let r=new Array(t.rank);return r.fill(1,0,a),r[a]=3,Gr(t,r)}var e$=D({grayscaleToRGB_:QM});function t$(e,t,a=0,n=.5){let r=R(e,\"image\",\"rotateWithOffset\",\"float32\");P(r.rank===4,()=>`Error in rotateWithOffset: image must be rank 4,but got rank ${r.rank}.`);let s={image:r},i={radians:t,fillValue:a,center:n};return z.runKernel(mo,s,i)}var a$=D({rotateWithOffset_:t$});function iu(e,t,a,n,r,s){n==null&&(n=.5),r==null&&(r=Number.NEGATIVE_INFINITY),s==null&&(s=0);let i=e.shape[0];return a=Math.min(a,i),P(0<=n&&n<=1,()=>`iouThreshold must be in [0, 1], but was '${n}'`),P(e.rank===2,()=>`boxes must be a 2D tensor, but was of rank '${e.rank}'`),P(e.shape[1]===4,()=>`boxes must have 4 columns, but 2nd dimension was ${e.shape[1]}`),P(t.rank===1,()=>\"scores must be a 1D tensor\"),P(t.shape[0]===i,()=>`scores has incompatible shape with boxes. Expected ${i}, but was ${t.shape[0]}`),P(0<=s&&s<=1,()=>`softNmsSigma must be in [0, 1], but was '${s}'`),{maxOutputSize:a,iouThreshold:n,scoreThreshold:r,softNmsSigma:s}}function n$(e,t,a,n=.5,r=Number.NEGATIVE_INFINITY){let s=R(e,\"boxes\",\"nonMaxSuppression\",\"float32\"),i=R(t,\"scores\",\"nonMaxSuppression\",\"float32\"),o=iu(s,i,a,n,r);a=o.maxOutputSize,n=o.iouThreshold,r=o.scoreThreshold;let l={maxOutputSize:a,iouThreshold:n,scoreThreshold:r};return z.runKernel(Bi,{boxes:s,scores:i},l)}var r$=D({nonMaxSuppression_:n$});function s$(e,t,a){let n=i$(e,t,a),r=n<0?-(n+1):n;e.splice(r,0,t)}function i$(e,t,a){return l$(e,t,a||o$)}function o$(e,t){return e>t?1:e<t?-1:0}function l$(e,t,a){let n=0,r=e.length,s=0,i=!1;for(;n<r;){s=n+(r-n>>>1);let o=a(t,e[s]);o>0?n=s+1:(r=s,i=!o)}return i?n:-n-1}function p4(e,t,a,n,r){return e3(e,t,a,n,r,0)}function c4(e,t,a,n,r,s){return e3(e,t,a,n,r,0,!1,s,!0)}function h4(e,t,a,n,r,s){return e3(e,t,a,n,r,s,!0)}function e3(e,t,a,n,r,s,i=!1,o=!1,l=!1){let u=[];for(let g=0;g<t.length;g++)t[g]>r&&u.push({score:t[g],boxIndex:g,suppressBeginIndex:0});u.sort(X5);let p=s>0?-.5/s:0,c=[],d=[];for(;c.length<a&&u.length>0;){let g=u.pop(),{score:x,boxIndex:A,suppressBeginIndex:y}=g;if(x<r)break;let b=!1;for(let w=c.length-1;w>=y;--w){let S=u$(e,A,c[w]);if(S>=n){b=!0;break}if(g.score=g.score*d$(n,p,S),g.score<=r)break}g.suppressBeginIndex=c.length,b||(g.score===x?(c.push(A),d.push(g.score)):g.score>r&&s$(u,g,X5))}let h=c.length,f=a-h;o&&f>0&&(c.push(...new Array(f).fill(0)),d.push(...new Array(f).fill(0)));let m={selectedIndices:c};return i&&(m.selectedScores=d),l&&(m.validOutputs=h),m}function u$(e,t,a){let n=e.subarray(t*4,t*4+4),r=e.subarray(a*4,a*4+4),s=Math.min(n[0],n[2]),i=Math.min(n[1],n[3]),o=Math.max(n[0],n[2]),l=Math.max(n[1],n[3]),u=Math.min(r[0],r[2]),p=Math.min(r[1],r[3]),c=Math.max(r[0],r[2]),d=Math.max(r[1],r[3]),h=(o-s)*(l-i),f=(c-u)*(d-p);if(h<=0||f<=0)return 0;let m=Math.max(s,u),g=Math.max(i,p),x=Math.min(o,c),A=Math.min(l,d),y=Math.max(x-m,0)*Math.max(A-g,0);return y/(h+f-y)}function d$(e,t,a){let n=Math.exp(t*a*a);return a<=e?n:0}function X5(e,t){return e.score-t.score||e.score===t.score&&t.boxIndex-e.boxIndex}async function p$(e,t,a,n=.5,r=Number.NEGATIVE_INFINITY){let s=R(e,\"boxes\",\"nonMaxSuppressionAsync\"),i=R(t,\"scores\",\"nonMaxSuppressionAsync\"),o=iu(s,i,a,n,r);a=o.maxOutputSize,n=o.iouThreshold,r=o.scoreThreshold;let l=await Promise.all([s.data(),i.data()]),u=l[0],p=l[1],{selectedIndices:c}=p4(u,p,a,n,r);return s!==e&&s.dispose(),i!==t&&i.dispose(),Ht(c,\"int32\")}var c$=p$;function h$(e,t,a,n=.5,r=Number.NEGATIVE_INFINITY,s=0){let i=R(e,\"boxes\",\"nonMaxSuppression\"),o=R(t,\"scores\",\"nonMaxSuppression\"),l=iu(i,o,a,n,r,s);a=l.maxOutputSize,n=l.iouThreshold,r=l.scoreThreshold,s=l.softNmsSigma;let u={boxes:i,scores:o},p={maxOutputSize:a,iouThreshold:n,scoreThreshold:r,softNmsSigma:s},c=z.runKernel(Wi,u,p);return{selectedIndices:c[0],selectedScores:c[1]}}var f$=D({nonMaxSuppressionWithScore_:h$});async function m$(e,t,a,n=.5,r=Number.NEGATIVE_INFINITY,s=0){let i=R(e,\"boxes\",\"nonMaxSuppressionAsync\"),o=R(t,\"scores\",\"nonMaxSuppressionAsync\"),l=iu(i,o,a,n,r,s);a=l.maxOutputSize,n=l.iouThreshold,r=l.scoreThreshold,s=l.softNmsSigma;let u=await Promise.all([i.data(),o.data()]),p=u[0],c=u[1],{selectedIndices:d,selectedScores:h}=h4(p,c,a,n,r,s);return i!==e&&i.dispose(),o!==t&&o.dispose(),{selectedIndices:Ht(d,\"int32\"),selectedScores:Ht(h)}}var g$=m$;function x$(e,t,a,n=.5,r=Number.NEGATIVE_INFINITY,s=!1){let i=R(e,\"boxes\",\"nonMaxSuppression\"),o=R(t,\"scores\",\"nonMaxSuppression\"),l=iu(i,o,a,n,r,null),u=l.maxOutputSize,p=l.iouThreshold,c=l.scoreThreshold,d={boxes:i,scores:o},h={maxOutputSize:u,iouThreshold:p,scoreThreshold:c,padToMaxOutputSize:s},f=z.runKernel(Ul,d,h);return{selectedIndices:f[0],validOutputs:f[1]}}var A$=D({nonMaxSuppressionPadded_:x$});async function y$(e,t,a,n=.5,r=Number.NEGATIVE_INFINITY,s=!1){let i=R(e,\"boxes\",\"nonMaxSuppressionAsync\"),o=R(t,\"scores\",\"nonMaxSuppressionAsync\"),l=iu(i,o,a,n,r,null),u=l.maxOutputSize,p=l.iouThreshold,c=l.scoreThreshold,[d,h]=await Promise.all([i.data(),o.data()]),{selectedIndices:f,validOutputs:m}=c4(d,h,u,p,c,s);return i!==e&&i.dispose(),o!==t&&o.dispose(),{selectedIndices:Ht(f,\"int32\"),validOutputs:Fe(m,\"int32\")}}var b$=y$;function v$(e,t,a=!1,n=!1){let r=R(e,\"images\",\"resizeBilinear\");P(r.rank===3||r.rank===4,()=>`Error in resizeBilinear: x must be rank 3 or 4, but got rank ${r.rank}.`),P(t.length===2,()=>`Error in resizeBilinear: new shape must 2D, but got shape ${t}.`),P(n===!1||a===!1,()=>\"Error in resizeBilinear: If halfPixelCenters is true, alignCorners must be false.\");let s=r,i=!1;r.rank===3&&(i=!0,s=J(r,[1,r.shape[0],r.shape[1],r.shape[2]]));let[]=t,o={images:s},l={alignCorners:a,halfPixelCenters:n,size:t},u=z.runKernel(Zi,o,l);return i?J(u,[u.shape[1],u.shape[2],u.shape[3]]):u}var w$=D({resizeBilinear_:v$});function k$(e,t,a=!1,n=!1){let r=R(e,\"images\",\"resizeNearestNeighbor\");P(r.rank===3||r.rank===4,()=>`Error in resizeNearestNeighbor: x must be rank 3 or 4, but got rank ${r.rank}.`),P(t.length===2,()=>`Error in resizeNearestNeighbor: new shape must 2D, but got shape ${t}.`),P(r.dtype===\"float32\"||r.dtype===\"int32\",()=>\"`images` must have `int32` or `float32` as dtype\"),P(n===!1||a===!1,()=>\"Error in resizeNearestNeighbor: If halfPixelCenters is true, alignCorners must be false.\");let s=r,i=!1;r.rank===3&&(i=!0,s=J(r,[1,r.shape[0],r.shape[1],r.shape[2]]));let[]=t,o={images:s},l={alignCorners:a,halfPixelCenters:n,size:t},u=z.runKernel(Ki,o,l);return i?J(u,[u.shape[1],u.shape[2],u.shape[3]]):u}var I$=D({resizeNearestNeighbor_:k$});function S$(e,t=\"binary\",a=!1,n=.5){let r=R(e,\"image\",\"threshold\"),s=.2989,i=.587,o=.114,l=r.shape[0]*r.shape[1],u=ae(Ht([n]),255),p,c,d,h;if(P(r.rank===3,()=>`Error in threshold: image must be rank 3,but got rank ${r.rank}.`),P(r.shape[2]===3||r.shape[2]===1,()=>`Error in threshold: image color channel must be equal to 3 or 1but got ${r.shape[2]}.`),P(r.dtype===\"int32\"||r.dtype===\"float32\",()=>`Error in dtype: image dtype must be int32 or float32,but got dtype ${r.dtype}.`),P(t===\"otsu\"||t===\"binary\",()=>`Method must be binary or otsu, but was ${t}`),r.shape[2]===3){[p,c,d]=ka(r,[1,1,1],-1);let m=ae(p,s),g=ae(c,i),x=ae(d,o);h=be(be(m,g),x)}else h=e;if(t===\"otsu\"){let m=w2(He(q2(h),\"int32\"),Be([]),256);u=T$(m,l)}let f=a?fh(h,u):np(h,u);return He(ae(f,255),\"int32\")}function T$(e,t){let a=Ht([-1]),n=Ht([0]),r=Ht([0]),s,i,o,l,u,p;for(let c=0;c<e.size-1;c++){s=Pe(e,0,c+1),i=Pe(e,c+1),u=me(tt(s),t),p=me(tt(i),t);let d=tt(ae(s,hl(0,s.size)));o=me(d,tt(s));let h=nr(i.shape,s.size),f=be(hl(0,i.size),h),m=ae(i,f);l=me(tt(m),tt(i));let g=fe(o,l),x=fe(o,l),A=ae(u,p);r=ae(ae(A,g),x);let y=np(r,n);n=Vs(y,r,n),a=Vs(y,Ht([c]),a)}return a}var C$=D({threshold_:S$});function N$(e,t,a=\"nearest\",n=\"constant\",r=0,s){let i=R(e,\"image\",\"transform\",\"float32\"),o=R(t,\"transforms\",\"transform\",\"float32\");P(i.rank===4,()=>`Error in transform: image must be rank 4,but got rank ${i.rank}.`),P(o.rank===2&&(o.shape[0]===i.shape[0]||o.shape[0]===1)&&o.shape[1]===8,()=>\"Error in transform: Input transform should be batch x 8 or 1 x 8\"),P(s==null||s.length===2,()=>`Error in transform: outputShape must be [height, width] or null, but got ${s}.`);let l={image:i,transforms:o},u={interpolation:a,fillMode:n,fillValue:r,outputShape:s};return z.runKernel(ho,l,u)}var E$=D({transform_:N$});function R$(e,t,a){P(t%1===0,()=>`bandPart(): numLower must be an integer, got ${t}.`),P(a%1===0,()=>`bandPart(): numUpper must be an integer, got ${a}.`);let n=R(e,\"a\",\"bandPart\");P(n.rank>=2,()=>`bandPart(): Rank must be at least 2, got ${n.rank}.`);let r=n.shape,[s,i]=n.shape.slice(-2);if(!(t<=s))throw new Error(`bandPart(): numLower (${t}) must not be greater than the number of rows (${s}).`);if(!(a<=i))throw new Error(`bandPart(): numUpper (${a}) must not be greater than the number of columns (${i}).`);t<0&&(t=s),a<0&&(a=i);let o=J(hl(0,s,1,\"int32\"),[-1,1]),l=hl(0,i,1,\"int32\"),u=fe(o,l),p=pd(fh(u,Fe(+t,\"int32\")),E2(u,Fe(-a,\"int32\"))),c=fn([s,i],n.dtype);return J(sa(Ta(J(n,[-1,s,i])).map(d=>Vs(p,d,c))),r)}var M$=D({bandPart_:R$});function $$(e){let t;if(Array.isArray(e)){t=!1,P(e!=null&&e.length>0,()=>\"Gram-Schmidt process: input must not be null, undefined, or empty\");let r=e[0].shape[0];for(let s=1;s<e.length;++s)P(e[s].shape[0]===r,()=>`Gram-Schmidt: Non-unique lengths found in the input vectors: (${e[s].shape[0]} vs. ${r})`)}else t=!0,e=ka(e,e.shape[0],0).map(r=>_e(r,[0]));P(e.length<=e[0].shape[0],()=>`Gram-Schmidt: Number of vectors (${e.length}) exceeds number of dimensions (${e[0].shape[0]}).`);let a=[],n=e;for(let r=0;r<e.length;++r)a.push(z.tidy(()=>{let s=n[r];if(r>0)for(let i=0;i<r;++i){let o=ae(tt(ae(a[i],s)),a[i]);s=fe(s,o)}return me(s,ap(s,\"euclidean\"))}));return t?sa(a,0):a}var _$=D({gramSchmidt_:$$});function P$(e,t=!1){if(P(e.rank>=2,()=>`qr() requires input tensor to have a rank >= 2, but got rank ${e.rank}`),e.rank===2)return K5(e,t);{let a=e.shape.slice(0,e.shape.length-2).reduce((l,u)=>l*u),n=Ta(J(e,[a,e.shape[e.shape.length-2],e.shape[e.shape.length-1]]),0),r=[],s=[];n.forEach(l=>{let[u,p]=K5(l,t);r.push(u),s.push(p)});let i=J(sa(r,0),e.shape),o=J(sa(s,0),e.shape);return[i,o]}}function K5(e,t=!1){return z.tidy(()=>{P(e.shape.length===2,()=>`qr2d() requires a 2D Tensor, but got a ${e.shape.length}D Tensor.`);let a=e.shape[0],n=e.shape[1],r=T2(a),s=wa(e),i=Kn([[1]],[1,1]),o=wa(i),l=a>=n?n:a;for(let u=0;u<l;++u){let p=s,c=o,d=r;[o,s,r]=z.tidy(()=>{let h=Pe(s,[u,u],[a-u,1]),f=ap(h),m=Pe(s,[u,u],[1,1]),g=Vs(np(m,0),Kn([[-1]]),Kn([[1]])),x=fe(m,ae(g,f)),A=me(h,x);A.shape[0]===1?o=wa(i):o=at([i,Pe(A,[1,0],[A.shape[0]-1,A.shape[1]])],0);let y=Xn(me(st(g,x),f)),b=Pe(s,[u,0],[a-u,n]),w=ae(y,o),S=Ws(o);if(u===0)s=fe(b,st(w,st(S,b)));else{let _=fe(b,st(w,st(S,b)));s=at([Pe(s,[0,0],[u,n]),_],0)}let C=Ws(w),E=Pe(r,[0,u],[a,r.shape[1]-u]);if(u===0)r=fe(E,st(st(E,o),C));else{let _=fe(E,st(st(E,o),C));r=at([Pe(r,[0,0],[a,u]),_],1)}return[o,s,r]}),Y([p,c,d])}return!t&&a>n&&(r=Pe(r,[0,0],[a,n]),s=Pe(s,[0,0],[n,n])),[r,s]})}var F$=D({qr_:P$}),ya;(function(e){e[e.NONE=0]=\"NONE\",e[e.MEAN=1]=\"MEAN\",e[e.SUM=2]=\"SUM\",e[e.SUM_BY_NONZERO_WEIGHTS=3]=\"SUM_BY_NONZERO_WEIGHTS\"})(ya||(ya={}));function O$(e,t,a=ya.SUM_BY_NONZERO_WEIGHTS){let n=R(e,\"losses\",\"computeWeightedLoss\"),r=null;t!=null&&(r=R(t,\"weights\",\"computeWeightedLoss\"));let s=r==null?n:ae(n,r);if(a===ya.NONE)return s;if(a===ya.SUM)return tt(s);if(a===ya.MEAN){if(r==null)return cd(s);{let i=n.size/r.size,o=me(tt(s),tt(r));return i>1?me(o,Fe(i)):o}}if(a===ya.SUM_BY_NONZERO_WEIGHTS){if(r==null)return me(tt(s),Fe(n.size));{let i=ae(r,Wr(n.shape)),o=He(tt(L2(i,Fe(0))),\"float32\");return me(tt(s),o)}}throw Error(`Unknown reduction: ${a}`)}var Ir=D({computeWeightedLoss_:O$});function D$(e,t,a,n=ya.SUM_BY_NONZERO_WEIGHTS){let r=R(e,\"labels\",\"absoluteDifference\"),s=R(t,\"predictions\",\"absoluteDifference\"),i=null;a!=null&&(i=R(a,\"weights\",\"absoluteDifference\")),Sa(r.shape,s.shape,\"Error in absoluteDifference: \");let o=qa(fe(r,s));return Ir(o,i,n)}var z$=D({absoluteDifference_:D$});function L$(e,t,a,n,r=ya.SUM_BY_NONZERO_WEIGHTS){let s=R(e,\"labels\",\"cosineDistance\"),i=R(t,\"predictions\",\"cosineDistance\"),o=null;n!=null&&(o=R(n,\"weights\",\"cosineDistance\")),Sa(s.shape,i.shape,\"Error in cosineDistance: \");let l=Fe(1),u=fe(l,tt(ae(s,i),a,!0));return Ir(u,o,r)}var B$=D({cosineDistance_:L$});function W$(e,t,a,n=ya.SUM_BY_NONZERO_WEIGHTS){let r=R(e,\"labels\",\"hingeLoss\"),s=R(t,\"predictions\",\"hingeLoss\"),i=null;a!=null&&(i=R(a,\"weights\",\"hingeLoss\")),Sa(r.shape,s.shape,\"Error in hingeLoss: \");let o=Fe(1);r=fe(ae(Fe(2),r),o);let l=rp(fe(o,ae(r,s)));return Ir(l,i,n)}var V$=D({hingeLoss_:W$});function U$(e,t,a,n=1,r=ya.SUM_BY_NONZERO_WEIGHTS){let s=R(e,\"labels\",\"huberLoss\"),i=R(t,\"predictions\",\"huberLoss\"),o=null;a!=null&&(o=R(a,\"weights\",\"huberLoss\")),Sa(s.shape,i.shape,\"Error in huberLoss: \");let l=Fe(n),u=qa(fe(i,s)),p=z2(u,l),c=fe(u,p),d=be(ae(Fe(.5),In(p)),ae(l,c));return Ir(d,o,r)}var G$=D({huberLoss_:U$});function H$(e,t,a,n=1e-7,r=ya.SUM_BY_NONZERO_WEIGHTS){let s=R(e,\"labels\",\"logLoss\"),i=R(t,\"predictions\",\"logLoss\"),o=null;a!=null&&(o=R(a,\"weights\",\"logLoss\")),Sa(s.shape,i.shape,\"Error in logLoss: \");let l=Fe(1),u=Fe(n),p=Xn(ae(s,cl(be(i,u)))),c=ae(fe(l,s),cl(be(fe(l,i),u))),d=fe(p,c);return Ir(d,o,r)}var j$=D({logLoss_:H$});function q$(e,t,a,n=ya.SUM_BY_NONZERO_WEIGHTS){let r=R(e,\"labels\",\"meanSquaredError\"),s=R(t,\"predictions\",\"meanSquaredError\"),i=null;a!=null&&(i=R(a,\"weights\",\"meanSquaredError\")),Sa(r.shape,s.shape,\"Error in meanSquaredError: \");let o=K2(r,s);return Ir(o,i,n)}var X$=D({meanSquaredError_:q$});function K$(e,t){let a=R(e,\"labels\",\"sigmoidCrossEntropyWithLogits\"),n=R(t,\"logits\",\"sigmoidCrossEntropyWithLogits\");Sa(a.shape,n.shape,\"Error in sigmoidCrossEntropyWithLogits: \");let r=rp(n),s=ae(n,a),i=M2(Zr(Xn(qa(n))));return be(fe(r,s),i)}function Z$(e,t,a,n=0,r=ya.SUM_BY_NONZERO_WEIGHTS){let s=R(e,\"multiClassLabels\",\"sigmoidCrossEntropy\"),i=R(t,\"logits\",\"sigmoidCrossEntropy\"),o=null;if(a!=null&&(o=R(a,\"weights\",\"sigmoidCrossEntropy\")),Sa(s.shape,i.shape,\"Error in sigmoidCrossEntropy: \"),n>0){let u=Fe(n),p=Fe(1),c=Fe(.5);s=be(ae(s,fe(p,u)),ae(c,u))}let l=K$(s,i);return Ir(l,o,r)}var Y$=D({sigmoidCrossEntropy_:Z$});function J$(e,t,a=-1){if(a===-1&&(a=t.rank-1),a!==t.rank-1)throw Error(`Softmax cross entropy along a non-last dimension is not yet supported. Labels / logits was rank ${t.rank} and dim was ${a}`);return Qn((n,r,s)=>{let i=_2(r,[a],!0),o=fe(He(r,\"float32\"),i);s([n,o]);let l=Xn(ae(o,n));return{value:tt(l,[a]),gradFunc:(u,p)=>{let[c,d]=p,h=tp(u.shape,[a]);return[ae(J(u,h),fe(He(c,\"float32\"),Zr(d))),ae(J(u,h),fe(Zr(d),He(c,\"float32\")))]}}})(e,t)}function Q$(e,t,a,n=0,r=ya.SUM_BY_NONZERO_WEIGHTS){let s=R(e,\"onehotLabels\",\"softmaxCrossEntropy\"),i=R(t,\"logits\",\"softmaxCrossEntropy\"),o=null;if(a!=null&&(o=R(a,\"weights\",\"softmaxCrossEntropy\")),Sa(s.shape,i.shape,\"Error in softmaxCrossEntropy: \"),n>0){let u=Fe(n),p=Fe(1),c=Fe(s.shape[1]);s=be(ae(s,fe(p,u)),me(u,c))}let l=J$(s,i);return Ir(l,o,r)}var e_=D({softmaxCrossEntropy_:Q$});function t_(e,t,a,n){let r=R(e,\"indices\",\"sparseFillEmptyRows\",\"int32\"),s=R(t,\"values\",\"sparseFillEmptyRows\"),i=R(a,\"denseShape\",\"sparseFillEmptyRows\",\"int32\"),o=R(n,\"defaultValue\",\"sparseFillEmptyRows\",s.dtype);if(r.rank!==2)throw new Error(`Indices should be Tensor2D but received shape\n        ${r.shape}`);if(s.rank!==1)throw new Error(`Values should be Tensor1D but received shape ${s.shape}`);if(i.rank!==1)throw new Error(`Dense shape should be Tensor1D but received shape ${i.shape}`);if(o.rank!==0)throw new Error(`Default value should be a scalar but received shape ${o.shape}`);let l={indices:r,values:s,denseShape:i,defaultValue:o},u=z.runKernel(Od,l);return{outputIndices:u[0],outputValues:u[1],emptyRowIndicator:u[2],reverseIndexMap:u[3]}}var a_=D({sparseFillEmptyRows_:t_});function n_(e,t,a){let n=R(e,\"inputIndices\",\"sparseReshape\",\"int32\"),r=R(t,\"inputShape\",\"sparseReshape\",\"int32\"),s=R(a,\"newShape\",\"sparseReshape\",\"int32\");if(n.rank!==2)throw new Error(`Input indices should be Tensor2D but received shape\n        ${n.shape}`);if(r.rank!==1)throw new Error(`Input shape should be Tensor1D but received shape ${r.shape}`);if(s.rank!==1)throw new Error(`New shape should be Tensor1D but received shape ${s.shape}`);let i={inputIndices:n,inputShape:r,newShape:s},o=z.runKernel(eu,i);return{outputIndices:o[0],outputShape:o[1]}}var r_=D({sparseReshape_:n_});function s_(e,t,a){let n=R(e,\"data\",\"sparseSegmentMean\"),r=R(t,\"indices\",\"sparseSegmentMean\",\"int32\"),s=R(a,\"segmentIds\",\"sparseSegmentMean\",\"int32\");if(n.rank<1)throw new Error(\"Data should be at least 1 dimensional but received scalar\");if(r.rank!==1)throw new Error(`Indices should be Tensor1D but received shape\n          ${r.shape}`);if(s.rank!==1)throw new Error(`Segment ids should be Tensor1D but received shape\n          ${s.shape}`);let i={data:n,indices:r,segmentIds:s};return z.runKernel(Dd,i)}var i_=D({sparseSegmentMean_:s_});function o_(e,t,a){let n=R(e,\"data\",\"sparseSegmentSum\"),r=R(t,\"indices\",\"sparseSegmentSum\",\"int32\"),s=R(a,\"segmentIds\",\"sparseSegmentSum\",\"int32\");if(n.rank<1)throw new Error(\"Data should be at least 1 dimensional but received scalar\");if(r.rank!==1)throw new Error(`Indices should be Tensor1D but received shape\n         ${r.shape}`);if(s.rank!==1)throw new Error(`Segment ids should be Tensor1D but received shape\n         ${s.shape}`);let i={data:n,indices:r,segmentIds:s};return z.runKernel(zd,i)}var l_=D({sparseSegmentSum_:o_});function u_(e,t,a,n,r,s,i,o){let l=R(e,\"data\",\"stringNGrams\",\"string\");if(l.dtype!==\"string\")throw new Error(\"Data must be of datatype string\");if(l.shape.length!==1)throw new Error(`Data must be a vector, saw: ${l.shape}`);let u=R(t,\"dataSplits\",\"stringNGrams\");if(u.dtype!==\"int32\")throw new Error(\"Data splits must be of datatype int32\");let p={separator:a,nGramWidths:n,leftPad:r,rightPad:s,padWidth:i,preserveShortSequences:o},c={data:l,dataSplits:u},d=z.runKernel(tu,c,p);return{nGrams:d[0],nGramsSplits:d[1]}}var d_=D({stringNGrams_:u_});function p_(e,t,a=!0){let n=R(e,\"input\",\"stringSplit\",\"string\"),r=R(t,\"delimiter\",\"stringSplit\",\"string\");if(n.rank!==1)throw new Error(`Input should be Tensor1D but received shape ${n.shape}`);if(r.rank!==0)throw new Error(`Delimiter should be a scalar but received shape ${r.shape}`);let s={skipEmpty:a},i={input:n,delimiter:r},o=z.runKernel(Wd,i,s);return{indices:o[0],values:o[1],shape:o[2]}}var c_=D({stringSplit_:p_});function h_(e,t){let a=R(e,\"input\",\"stringToHashBucketFast\",\"string\"),n={numBuckets:t};if(t<=0)throw new Error(\"Number of buckets must be at least 1\");let r={input:a};return z.runKernel(Vd,r,n)}var f_=D({stringToHashBucketFast_:h_}),f4={fft:yh,ifft:hd,rfft:bh,irfft:X2},m4={hammingWindow:GM,hannWindow:u4,frame:d4,stft:XM},ge={flipLeftRight:JM,grayscaleToRGB:e$,resizeNearestNeighbor:I$,resizeBilinear:w$,rotateWithOffset:a$,cropAndResize:ZM,nonMaxSuppression:r$,nonMaxSuppressionAsync:c$,nonMaxSuppressionWithScore:f$,nonMaxSuppressionWithScoreAsync:g$,nonMaxSuppressionPadded:A$,nonMaxSuppressionPaddedAsync:b$,threshold:C$,transform:E$},g4={bandPart:M$,gramSchmidt:_$,qr:F$},x4={absoluteDifference:z$,computeWeightedLoss:Ir,cosineDistance:B$,hingeLoss:V$,huberLoss:G$,logLoss:j$,meanSquaredError:X$,sigmoidCrossEntropy:Y$,softmaxCrossEntropy:e_},A4={sparseFillEmptyRows:a_,sparseReshape:r_,sparseSegmentMean:i_,sparseSegmentSum:l_},y4={stringNGrams:d_,stringSplit:c_,stringToHashBucketFast:f_},is=class extends ny{minimize(e,t=!1,a){let{value:n,grads:r}=this.computeGradients(e,a);if(a!=null){let s=a.map(i=>({name:i.name,tensor:r[i.name]}));this.applyGradients(s)}else this.applyGradients(r);return Y(r),t?n:(n.dispose(),null)}get iterations(){return this.iterations_==null&&(this.iterations_=0),this.iterations_}incrementIterations(){this.iterations_=this.iterations+1}computeGradients(e,t){return rb(e,t)}dispose(){this.iterations_!=null&&Y(this.iterations_)}async saveIterations(){return this.iterations_==null&&(this.iterations_=0),{name:\"iter\",tensor:Fe(this.iterations_,\"int32\")}}async getWeights(){throw new Error(\"getWeights() is not implemented for this optimizer yet.\")}async setWeights(e){throw new Error(`setWeights() is not implemented for this optimizer class ${this.getClassName()}`)}async extractIterations(e){return this.iterations_=(await e[0].tensor.data())[0],e.slice(1)}};Object.defineProperty(is,Symbol.hasInstance,{value:e=>e.minimize!=null&&e.computeGradients!=null&&e.applyGradients!=null});var Th=class extends is{constructor(e,t,a=null){super(),this.learningRate=e,this.rho=t,this.epsilon=a,this.accumulatedGrads=[],this.accumulatedUpdates=[],a==null&&(this.epsilon=z.backend.epsilon())}applyGradients(e){(Array.isArray(e)?e.map(t=>t.name):Object.keys(e)).forEach((t,a)=>{let n=z.registeredVariables[t],r=!1;this.accumulatedGrads[a]==null&&(this.accumulatedGrads[a]={originalName:`${t}/accum_grad`,variable:$e(()=>Ka(n).variable(r))}),this.accumulatedUpdates[a]==null&&(this.accumulatedUpdates[a]={originalName:`${t}/accum_var`,variable:$e(()=>Ka(n).variable(r))});let s=Array.isArray(e)?e[a].tensor:e[t];if(s==null)return;let i=this.accumulatedGrads[a].variable,o=this.accumulatedUpdates[a].variable;$e(()=>{let l=be(ae(i,this.rho),ae(In(s),1-this.rho)),u=ae(me(Jn(be(o,this.epsilon)),Jn(be(i,this.epsilon))),s),p=be(ae(o,this.rho),ae(In(u),1-this.rho));i.assign(l),o.assign(p);let c=be(ae(u,-this.learningRate),n);n.assign(c)})}),this.incrementIterations()}dispose(){this.accumulatedUpdates!=null&&(Y(this.accumulatedGrads.map(e=>e.variable)),Y(this.accumulatedUpdates.map(e=>e.variable)))}async getWeights(){let e=[...this.accumulatedGrads,...this.accumulatedUpdates];return[await this.saveIterations()].concat(e.map(t=>({name:t.originalName,tensor:t.variable})))}async setWeights(e){e=await this.extractIterations(e);let t=e.length/2,a=!1;this.accumulatedGrads=e.slice(0,t).map(n=>({originalName:n.name,variable:n.tensor.variable(a)})),this.accumulatedUpdates=e.slice(t,t*2).map(n=>({originalName:n.name,variable:n.tensor.variable(a)}))}getConfig(){return{learningRate:this.learningRate,rho:this.rho,epsilon:this.epsilon}}static fromConfig(e,t){return new e(t.learningRate,t.rho,t.epsilon)}};Th.className=\"Adadelta\";ss(Th);var Ch=class extends is{constructor(e,t=.1){super(),this.learningRate=e,this.initialAccumulatorValue=t,this.accumulatedGrads=[]}applyGradients(e){(Array.isArray(e)?e.map(t=>t.name):Object.keys(e)).forEach((t,a)=>{let n=z.registeredVariables[t];this.accumulatedGrads[a]==null&&(this.accumulatedGrads[a]={originalName:`${t}/accumulator`,variable:$e(()=>nr(n.shape,this.initialAccumulatorValue).variable(!1))});let r=Array.isArray(e)?e[a].tensor:e[t];if(r==null)return;let s=this.accumulatedGrads[a].variable;$e(()=>{let i=be(s,In(r));s.assign(i);let o=be(ae(me(r,Jn(be(i,z.backend.epsilon()))),-this.learningRate),n);n.assign(o)})}),this.incrementIterations()}dispose(){this.accumulatedGrads!=null&&Y(this.accumulatedGrads.map(e=>e.variable))}async getWeights(){return[await this.saveIterations()].concat(this.accumulatedGrads.map(e=>({name:e.originalName,tensor:e.variable})))}async setWeights(e){e=await this.extractIterations(e);let t=!1;this.accumulatedGrads=e.map(a=>({originalName:a.name,variable:a.tensor.variable(t)}))}getConfig(){return{learningRate:this.learningRate,initialAccumulatorValue:this.initialAccumulatorValue}}static fromConfig(e,t){return new e(t.learningRate,t.initialAccumulatorValue)}};Ch.className=\"Adagrad\";ss(Ch);var Nh=class extends is{constructor(e,t,a,n=null){super(),this.learningRate=e,this.beta1=t,this.beta2=a,this.epsilon=n,this.accumulatedFirstMoment=[],this.accumulatedSecondMoment=[],$e(()=>{this.accBeta1=Fe(t).variable(),this.accBeta2=Fe(a).variable()}),n==null&&(this.epsilon=z.backend.epsilon())}applyGradients(e){let t=Array.isArray(e)?e.map(a=>a.name):Object.keys(e);$e(()=>{let a=fe(1,this.accBeta1),n=fe(1,this.accBeta2);t.forEach((r,s)=>{let i=z.registeredVariables[r],o=!1;this.accumulatedFirstMoment[s]==null&&(this.accumulatedFirstMoment[s]={originalName:`${r}/m`,variable:$e(()=>Ka(i).variable(o))}),this.accumulatedSecondMoment[s]==null&&(this.accumulatedSecondMoment[s]={originalName:`${r}/v`,variable:$e(()=>Ka(i).variable(o))});let l=Array.isArray(e)?e[s].tensor:e[r];if(l==null)return;let u=this.accumulatedFirstMoment[s].variable,p=this.accumulatedSecondMoment[s].variable,c=be(ae(u,this.beta1),ae(l,1-this.beta1)),d=be(ae(p,this.beta2),ae(In(l),1-this.beta2)),h=me(c,a),f=me(d,n);u.assign(c),p.assign(d);let m=be(ae(me(h,be(Jn(f),this.epsilon)),-this.learningRate),i);i.assign(m)}),this.accBeta1.assign(ae(this.accBeta1,this.beta1)),this.accBeta2.assign(ae(this.accBeta2,this.beta2))}),this.incrementIterations()}dispose(){this.accBeta1.dispose(),this.accBeta2.dispose(),this.accumulatedFirstMoment!=null&&Y(this.accumulatedFirstMoment.map(e=>e.variable)),this.accumulatedSecondMoment!=null&&Y(this.accumulatedSecondMoment.map(e=>e.variable))}async getWeights(){let e=[...this.accumulatedFirstMoment,...this.accumulatedSecondMoment];return[await this.saveIterations()].concat(e.map(t=>({name:t.originalName,tensor:t.variable})))}async setWeights(e){e=await this.extractIterations(e),$e(()=>{this.accBeta1.assign(pl(this.beta1,this.iterations_+1)),this.accBeta2.assign(pl(this.beta2,this.iterations_+1))});let t=e.length/2,a=!1;this.accumulatedFirstMoment=e.slice(0,t).map(n=>({originalName:n.name,variable:n.tensor.variable(a)})),this.accumulatedSecondMoment=e.slice(t,t*2).map(n=>({originalName:n.name,variable:n.tensor.variable(a)}))}getConfig(){return{learningRate:this.learningRate,beta1:this.beta1,beta2:this.beta2,epsilon:this.epsilon}}static fromConfig(e,t){return new e(t.learningRate,t.beta1,t.beta2,t.epsilon)}};Nh.className=\"Adam\";ss(Nh);var Eh=class extends is{constructor(e,t,a,n=null,r=0){super(),this.learningRate=e,this.beta1=t,this.beta2=a,this.epsilon=n,this.decay=r,this.accumulatedFirstMoment=[],this.accumulatedWeightedInfNorm=[],$e(()=>{this.iteration=Fe(0).variable(),this.accBeta1=Fe(t).variable()}),n==null&&(this.epsilon=z.backend.epsilon())}applyGradients(e){let t=Array.isArray(e)?e.map(a=>a.name):Object.keys(e);$e(()=>{let a=fe(1,this.accBeta1),n=me(-this.learningRate,be(ae(this.iteration,this.decay),1));t.forEach((r,s)=>{let i=z.registeredVariables[r],o=!1;this.accumulatedFirstMoment[s]==null&&(this.accumulatedFirstMoment[s]={originalName:`${r}/m`,variable:Ka(i).variable(o)}),this.accumulatedWeightedInfNorm[s]==null&&(this.accumulatedWeightedInfNorm[s]={originalName:`${r}/v`,variable:Ka(i).variable(o)});let l=Array.isArray(e)?e[s].tensor:e[r];if(l==null)return;let u=this.accumulatedFirstMoment[s].variable,p=this.accumulatedWeightedInfNorm[s].variable,c=be(ae(u,this.beta1),ae(l,1-this.beta1)),d=ae(p,this.beta2),h=qa(l),f=D2(d,h);u.assign(c),p.assign(f);let m=be(ae(me(n,a),me(c,be(f,this.epsilon))),i);i.assign(m)}),this.iteration.assign(be(this.iteration,1)),this.accBeta1.assign(ae(this.accBeta1,this.beta1))}),this.incrementIterations()}dispose(){this.accBeta1.dispose(),this.iteration.dispose(),this.accumulatedFirstMoment!=null&&Y(this.accumulatedFirstMoment.map(e=>e.variable)),this.accumulatedWeightedInfNorm!=null&&Y(this.accumulatedWeightedInfNorm.map(e=>e.variable))}async getWeights(){throw new Error(\"getWeights() is not implemented for Adamax yet.\")}async setWeights(e){throw new Error(\"setWeights() is not implemented for Adamax yet.\")}getConfig(){return{learningRate:this.learningRate,beta1:this.beta1,beta2:this.beta2,epsilon:this.epsilon,decay:this.decay}}static fromConfig(e,t){return new e(t.learningRate,t.beta1,t.beta2,t.epsilon,t.decay)}};Eh.className=\"Adamax\";ss(Eh);var ip=class extends is{constructor(e){super(),this.learningRate=e,this.setLearningRate(e)}applyGradients(e){(Array.isArray(e)?e.map(t=>t.name):Object.keys(e)).forEach((t,a)=>{let n=Array.isArray(e)?e[a].tensor:e[t];if(n==null)return;let r=z.registeredVariables[t];$e(()=>{let s=be(ae(this.c,n),r);r.assign(s)})}),this.incrementIterations()}setLearningRate(e){this.learningRate=e,this.c!=null&&this.c.dispose(),this.c=On(Fe(-e))}dispose(){this.c.dispose()}async getWeights(){return[await this.saveIterations()]}async setWeights(e){if(e=await this.extractIterations(e),e.length!==0)throw new Error(\"SGD optimizer does not have settable weights.\")}getConfig(){return{learningRate:this.learningRate}}static fromConfig(e,t){return new e(t.learningRate)}};ip.className=\"SGD\";ss(ip);var Rh=class extends ip{constructor(e,t,a=!1){super(e),this.learningRate=e,this.momentum=t,this.useNesterov=a,this.accumulations=[],this.m=Fe(this.momentum)}applyGradients(e){(Array.isArray(e)?e.map(t=>t.name):Object.keys(e)).forEach((t,a)=>{let n=z.registeredVariables[t];this.accumulations[a]==null&&(this.accumulations[a]={originalName:`${t}/momentum`,variable:$e(()=>Ka(n).variable(!1))});let r=this.accumulations[a].variable,s=Array.isArray(e)?e[a].tensor:e[t];s!=null&&$e(()=>{let i,o=be(ae(this.m,r),s);this.useNesterov?i=be(ae(this.c,be(s,ae(o,this.m))),n):i=be(ae(this.c,o),n),r.assign(o),n.assign(i)})}),this.incrementIterations()}dispose(){this.m.dispose(),this.accumulations!=null&&Y(this.accumulations.map(e=>e.variable))}setMomentum(e){this.momentum=e}async getWeights(){return[await this.saveIterations()].concat(this.accumulations.map(e=>({name:e.originalName,tensor:e.variable})))}async setWeights(e){e=await this.extractIterations(e);let t=!1;this.accumulations=e.map(a=>({originalName:a.name,variable:a.tensor.variable(t)}))}getConfig(){return{learningRate:this.learningRate,momentum:this.momentum,useNesterov:this.useNesterov}}static fromConfig(e,t){return new e(t.learningRate,t.momentum,t.useNesterov)}};Rh.className=\"Momentum\";ss(Rh);var Mh=class extends is{constructor(e,t=.9,a=0,n=null,r=!1){if(super(),this.learningRate=e,this.decay=t,this.momentum=a,this.epsilon=n,this.accumulatedMeanSquares=[],this.accumulatedMoments=[],this.accumulatedMeanGrads=[],this.centered=r,n==null&&(this.epsilon=z.backend.epsilon()),e==null)throw new Error(\"learningRate for RMSPropOptimizer must be defined.\")}applyGradients(e){(Array.isArray(e)?e.map(t=>t.name):Object.keys(e)).forEach((t,a)=>{let n=z.registeredVariables[t],r=!1;this.accumulatedMeanSquares[a]==null&&(this.accumulatedMeanSquares[a]={originalName:`${t}/rms`,variable:$e(()=>Ka(n).variable(r))}),this.accumulatedMoments[a]==null&&(this.accumulatedMoments[a]={originalName:`${t}/momentum`,variable:$e(()=>Ka(n).variable(r))}),this.accumulatedMeanGrads[a]==null&&this.centered&&(this.accumulatedMeanGrads[a]={originalName:`${t}/mg`,variable:$e(()=>Ka(n).variable(r))});let s=Array.isArray(e)?e[a].tensor:e[t];if(s==null)return;let i=this.accumulatedMeanSquares[a].variable,o=this.accumulatedMoments[a].variable;$e(()=>{let l=be(ae(i,this.decay),ae(In(s),1-this.decay));if(this.centered){let u=this.accumulatedMeanGrads[a].variable,p=be(ae(u,this.decay),ae(s,1-this.decay)),c=me(ae(s,this.learningRate),Jn(fe(l,be(In(p),this.epsilon)))),d=be(ae(o,this.momentum),c);i.assign(l),u.assign(p),o.assign(d);let h=fe(n,d);n.assign(h)}else{let u=be(ae(i,this.decay),ae(In(s),1-this.decay)),p=be(ae(o,this.momentum),me(ae(s,this.learningRate),Jn(be(u,this.epsilon))));i.assign(u),o.assign(p);let c=fe(n,p);n.assign(c)}})}),this.incrementIterations()}dispose(){this.accumulatedMeanSquares!=null&&Y(this.accumulatedMeanSquares.map(e=>e.variable)),this.accumulatedMeanGrads!=null&&this.centered&&Y(this.accumulatedMeanGrads.map(e=>e.variable)),this.accumulatedMoments!=null&&Y(this.accumulatedMoments.map(e=>e.variable))}async getWeights(){let e=[...this.accumulatedMeanSquares,...this.accumulatedMoments];return this.centered&&e.push(...this.accumulatedMeanGrads),[await this.saveIterations()].concat(e.map(t=>({name:t.originalName,tensor:t.variable})))}async setWeights(e){e=await this.extractIterations(e);let t=this.centered?e.length/3:e.length/2,a=!1;this.accumulatedMeanSquares=e.slice(0,t).map(n=>({originalName:n.name,variable:n.tensor.variable(a)})),this.accumulatedMoments=e.slice(t,t*2).map(n=>({originalName:n.name,variable:n.tensor.variable(a)})),this.centered&&(this.accumulatedMeanGrads=e.slice(t*2,t*3).map(n=>({originalName:n.name,variable:n.tensor.variable(a)})))}getConfig(){return{learningRate:this.learningRate,decay:this.decay,momentum:this.momentum,epsilon:this.epsilon,centered:this.centered}}static fromConfig(e,t){return new e(t.learningRate,t.decay,t.momentum,t.epsilon,t.centered)}};Mh.className=\"RMSProp\";ss(Mh);var Or=class{static sgd(e){return new ip(e)}static momentum(e,t,a=!1){return new Rh(e,t,a)}static rmsprop(e,t=.9,a=0,n=null,r=!1){return new Mh(e,t,a,n,r)}static adam(e=.001,t=.9,a=.999,n=null){return new Nh(e,t,a,n)}static adadelta(e=.001,t=.95,a=null){return new Th(e,t,a)}static adamax(e=.002,t=.9,a=.999,n=null,r=0){return new Eh(e,t,a,n,r)}static adagrad(e,t=.1){return new Ch(e,t)}},m_={sgd:Or.sgd,momentum:Or.momentum,adadelta:Or.adadelta,adagrad:Or.adagrad,rmsprop:Or.rmsprop,adamax:Or.adamax,adam:Or.adam},g_=(()=>typeof requestAnimationFrame!=\"undefined\"?requestAnimationFrame:typeof setImmediate!=\"undefined\"?setImmediate:e=>e())();function b4(){return new Promise(e=>g_(()=>e()))}var T={};Xe(T,{ERF_A1:()=>__,ERF_A2:()=>P_,ERF_A3:()=>F_,ERF_A4:()=>O_,ERF_A5:()=>D_,ERF_P:()=>$_,PARALLELIZE_THRESHOLD:()=>t3,RowPartitionType:()=>Hn,SELU_SCALE:()=>M_,SELU_SCALEALPHA:()=>R_,applyActivation:()=>Ih,assertAndGetBroadcastShape:()=>zt,assertAxesAreInnerMostDims:()=>hE,assertParamsConsistent:()=>x_,assignToTypedArray:()=>U_,axesAreInnerMostDims:()=>S2,calculateShapes:()=>qA,checkEinsumDimSizes:()=>K_,checkPadOnDimRoundingMode:()=>Sn,combineLocations:()=>Xy,combineRaggedTensorToTensorShapes:()=>y_,complexWithEvenIndex:()=>B_,complexWithOddIndex:()=>W_,computeConv2DInfo:()=>Jd,computeConv3DInfo:()=>Ay,computeDefaultPad:()=>y2,computeDilation2DInfo:()=>cN,computeOptimalWindowSize:()=>k_,computeOutAndReduceShapes:()=>cE,computeOutShape:()=>A_,computePool2DInfo:()=>xy,computePool3DInfo:()=>hN,convertConv2DDataFormat:()=>yy,decodeEinsumEquation:()=>q_,eitherStridesOrDilationsAreOne:()=>kr,expandShapeToKeepDim:()=>tp,exponent:()=>H_,exponents:()=>G_,fromStringArrayToUint8:()=>gP,fromUint8ToStringArray:()=>mP,getAxesPermutation:()=>fE,getBroadcastDims:()=>GA,getComplexWithIndex:()=>V_,getEinsumComputePath:()=>Z_,getEinsumPermutation:()=>X_,getFusedBiasGradient:()=>kh,getFusedDyActivation:()=>wh,getImageCenter:()=>I_,getInnerMostAxes:()=>gE,getPermuted:()=>T_,getRaggedRank:()=>v_,getReductionAxes:()=>d2,getReshaped:()=>S_,getReshapedPermuted:()=>C_,getRowPartitionTypesHelper:()=>b_,getSliceBeginCoords:()=>N_,getSliceSize:()=>E_,getSparseFillEmptyRowsIndicesDenseShapeMismatch:()=>eP,getSparseFillEmptyRowsNegativeIndexErrorMessage:()=>tP,getSparseFillEmptyRowsOutOfRangeIndexErrorMessage:()=>aP,getSparseReshapeEmptyTensorZeroOutputDimErrorMessage:()=>sP,getSparseReshapeInputOutputMismatchErrorMessage:()=>oP,getSparseReshapeInputOutputMultipleErrorMessage:()=>iP,getSparseReshapeMultipleNegativeOneOutputDimErrorMessage:()=>nP,getSparseReshapeNegativeOutputDimErrorMessage:()=>rP,getSparseSegmentReductionIndicesOutOfRangeErrorMessage:()=>pP,getSparseSegmentReductionNegativeSegmentIdsErrorMessage:()=>lP,getSparseSegmentReductionNonIncreasingSegmentIdsErrorMessage:()=>uP,getSparseSegmentReductionSegmentIdOutOfRangeErrorMessage:()=>dP,getUndoAxesPermutation:()=>mE,isIdentityPermutation:()=>Y_,log:()=>MS,mergeRealAndImagArrays:()=>z_,prepareAndValidate:()=>jA,prepareSplitSize:()=>Q_,segment_util:()=>v4,shouldFuse:()=>Sh,slice_util:()=>It,splitRealAndImagArrays:()=>L_,tupleValuesAreOne:()=>dd,upcastType:()=>ca,validateDefaultValueShape:()=>w_,validateInput:()=>m2,validateUpdateShape:()=>f2,warn:()=>zr});function x_(e,t){let a=e[0].length;e.forEach((r,s)=>{P(r.length===a,()=>`Error in concat${a}D: rank of tensors[${s}] must be the same as the rank of the rest (${a})`)}),P(t>=0&&t<a,()=>`Error in concat${a}D: axis must be between 0 and ${a-1}.`);let n=e[0];e.forEach((r,s)=>{for(let i=0;i<a;i++)P(i===t||r[i]===n[i],()=>`Error in concat${a}D: Shape of tensors[${s}] (${r}) does not match the shape of the rest (${n}) along the non-concatenated axis ${s}.`)})}function A_(e,t){let a=e[0].slice();for(let n=1;n<e.length;n++)a[t]+=e[n][t];return a}var Hn;(function(e){e[e.FIRST_DIM_SIZE=0]=\"FIRST_DIM_SIZE\",e[e.VALUE_ROWIDS=1]=\"VALUE_ROWIDS\",e[e.ROW_LENGTHS=2]=\"ROW_LENGTHS\",e[e.ROW_SPLITS=3]=\"ROW_SPLITS\",e[e.ROW_LIMITS=4]=\"ROW_LIMITS\",e[e.ROW_STARTS=5]=\"ROW_STARTS\"})(Hn||(Hn={}));function y_(e,t,a){let n=new Array;if(a==null&&t==null)return n;if(t==null)for(;n.length<e+a.length;)n.push(-1);else n=t.slice();if(a==null)return n;if(e+a.length!==n.length)throw new Error(`rt input.shape and shape=${t} are incompatible: rt input.rank = ${e+a.length}, but shape.rank = ${n.length}`);for(let r=1;r<a.length;++r){let s=a[r],i=n[n.length-a.length+r],o=n[i];if(s>=0)if(o>=0){if(o!==s)throw new Error(`rt input.shape and shape=${t} are incompatible: rt input.shape[${r+e}] = ${s} but shape[${r+e}] = ${o}`)}else n[i]=s}return n}function b_(e){let t={FIRST_DIM_SIZE:Hn.FIRST_DIM_SIZE,VALUE_ROWIDS:Hn.VALUE_ROWIDS,ROW_LENGTHS:Hn.ROW_LENGTHS,ROW_SPLITS:Hn.ROW_SPLITS,ROW_LIMITS:Hn.ROW_LIMITS,ROW_STARTS:Hn.ROW_STARTS},a=[];for(let n of e)if(n in t)a.push(t[n]);else break;return a}function v_(e){return e.length===0?0:e[0]===Hn.FIRST_DIM_SIZE?e.length-1:e.length}function w_(e,t){if(e==null||t==null)return;let a=e.length,n=t.length;if(a>=n)throw new Error(`defaultValue.shape=${e} and ragged tensor flatValues.shape=${t}, are incompatible: defaultValue.rank = ${a} must be less than ragged tensor input flatValues.rank = ${n})`);for(let r=0;r<Math.min(a,n-1);++r){let s=e[r],i=t[r+1];if(s>=0&&i>=0&&s!==1&&s!==i)throw new Error(`defaultValue.shape=${e}, and ragged tensor input flatValues.shape=${t} are incompatible: defaultValue.shape[${r-e.length}] = ${s} but ragged tensor input.flatValues.shape[${r-e.length}] = ${i}`)}}var t3=30;function k_(e){return e<=t3?e:Ic(e,Math.floor(Math.sqrt(e)))}function I_(e,t,a){let n=a*(typeof e==\"number\"?e:e[0]),r=t*(typeof e==\"number\"?e:e[1]);return[n,r]}function S_(e,t,a,n=!0){let r=[];if(n)r=r.concat(t.slice(0)),r.push(e[0]/a),r=r.concat(e.slice(1));else{r=r.concat(e[0]);let s=t.length;for(let i=0;i<s;++i)r=r.concat([e[i+1]/t[i],t[i]]);r=r.concat(e.slice(s+1))}return r}function T_(e,t,a=!0){let n=[];if(a){n.push(t);for(let r=t+1;r<e;++r)r<=2*t?(n.push(r),n.push(r-(t+1))):n.push(r)}else{let r=[],s=[];for(let i=1;i<e;++i)i>=t*2+1||i%2===1?s.push(i):r.push(i);n.push(...r),n.push(0),n.push(...s)}return n}function C_(e,t,a,n=!0){let r=[];n?r.push(e[0]/a):r.push(e[0]*a);for(let s=1;s<e.length;++s)s<=t.length?n?r.push(t[s-1]*e[s]):r.push(e[s]/t[s-1]):r.push(e[s]);return r}function N_(e,t){let a=[0];for(let n=0;n<t;++n)a.push(e[n][0]);return a}function E_(e,t,a){let n=e.slice(0,1);for(let r=0;r<a;++r)n.push(e[r+1]-t[r][0]-t[r][1]);return n}var R_=1.7580993408473768,M_=1.0507009873554805,$_=.3275911,__=.254829592,P_=-.284496736,F_=1.421413741,O_=-1.453152027,D_=1.061405429;function z_(e,t){if(e.length!==t.length)throw new Error(`Cannot merge real and imag arrays of different lengths. real:${e.length}, imag: ${t.length}.`);let a=new Float32Array(e.length*2);for(let n=0;n<a.length;n+=2)a[n]=e[n/2],a[n+1]=t[n/2];return a}function L_(e){let t=new Float32Array(e.length/2),a=new Float32Array(e.length/2);for(let n=0;n<e.length;n+=2)t[n/2]=e[n],a[n/2]=e[n+1];return{real:t,imag:a}}function B_(e){let t=Math.ceil(e.length/4),a=new Float32Array(t),n=new Float32Array(t);for(let r=0;r<e.length;r+=4)a[Math.floor(r/4)]=e[r],n[Math.floor(r/4)]=e[r+1];return{real:a,imag:n}}function W_(e){let t=Math.floor(e.length/4),a=new Float32Array(t),n=new Float32Array(t);for(let r=2;r<e.length;r+=4)a[Math.floor(r/4)]=e[r],n[Math.floor(r/4)]=e[r+1];return{real:a,imag:n}}function V_(e,t){let a=e[t*2],n=e[t*2+1];return{real:a,imag:n}}function U_(e,t,a,n){e[n*2]=t,e[n*2+1]=a}function G_(e,t){let a=new Float32Array(e/2),n=new Float32Array(e/2);for(let r=0;r<Math.ceil(e/2);r++){let s=(t?2:-2)*Math.PI*(r/e);a[r]=Math.cos(s),n[r]=Math.sin(s)}return{real:a,imag:n}}function H_(e,t,a){let n=(a?2:-2)*Math.PI*(e/t),r=Math.cos(n),s=Math.sin(n);return{real:r,imag:s}}var Om=\"->\",j_=/->/g,Z5=\",\",Y5=\"...\";function q_(e,t){e=e.replace(/\\s/g,\"\");let a=(e.length-e.replace(j_,\"\").length)/Om.length;if(a<1)throw new Error(\"Equations without an arrow are not supported.\");if(a>1)throw new Error(`Equation must contain exactly one arrow (\"${Om}\").`);let[n,r]=e.split(Om);P(n.indexOf(Y5)===-1,()=>`The ellipsis notation (\"${Y5}\") is not supported yet.`);let s=n.split(Z5),i=s.length;if(t!==i)throw new Error(`Expected ${i} input tensors, received ${t}`);if(i>2)throw new Error(\"Support for more than 2 input tensors is not implemented yet.\");let o=[];for(let d=0;d<r.length;++d){let h=r[d];if(!s.some(f=>f.indexOf(h)!==-1))throw new Error(`Output subscripts contain the label ${h} not present in the input subscripts.`);o.indexOf(h)===-1&&o.push(h)}for(let d=0;d<n.length;++d){let h=n[d];o.indexOf(h)===-1&&h!==Z5&&o.push(h)}let l=new Array(s.length);for(let d=0;d<i;++d){if(new Set(s[d].split(\"\")).size!==s[d].length)throw new Error(`Found duplicate axes in input component ${s[d]}. Support for duplicate axes in input is not implemented yet.`);l[d]=[];for(let h=0;h<s[d].length;++h)l[d].push(o.indexOf(s[d][h]))}let u=o.length,p=r.length,c=[];for(let d=p;d<u;++d)c.push(d);return{allDims:o,summedDims:c,idDims:l}}function X_(e,t){let a=new Array(e);a.fill(-1);for(let r=0;r<t.length;++r)a[t[r]]=r;let n=[];for(let r=0;r<e;++r)a[r]===-1&&n.push(r);return a=a.filter(r=>r!==-1),{permutationIndices:a,expandDims:n}}function K_(e,t,a){let n=new Array(e);for(let r=0;r<a.length;++r){let s=a[r].shape;for(let i=0;i<t[r].length;++i)n[t[r][i]]===void 0?n[t[r][i]]=s[i]:P(n[t[r][i]]===s[i],()=>`Expected dimension ${n[t[r][i]]} at axis ${i} of input shaped ${JSON.stringify(s)}, but got dimension ${s[i]}`)}}function Z_(e,t){let a=e,n=[],r=0;e.length===0&&a.push(-1),r=e.length+1;for(let i=0;i<r;++i)n.push([]);let s=[];for(let i=0;i<a.length;++i){let o=a[i],l=J_(t,o);for(let u of l)s.indexOf(u)===-1&&(n[i].push(u),s.push(u))}return{path:a,steps:n}}function Y_(e){return e.every((t,a)=>t===a)}function J_(e,t){let a=[];for(let n=0;n<e.length;++n)(e[n].length===0||e[n].indexOf(t)!==-1||t===-1)&&a.push(n);return a}function Q_(e,t,a=0){let n=[];if(typeof t==\"number\")P(e.shape[a]%t===0,()=>\"Number of splits must evenly divide the axis.\"),n=new Array(t).fill(e.shape[a]/t);else{let r=t.reduce((i,o)=>(o===-1&&(i+=1),i),0);P(r<=1,()=>\"There should be only one negative value in split array.\");let s=t.indexOf(-1);if(s!==-1){let i=t.reduce((o,l)=>l>0?o+l:o);t[s]=e.shape[a]-i}P(e.shape[a]===t.reduce((i,o)=>i+o),()=>\"The sum of sizes must match the size of the axis dimension.\"),n=t}return n}function eP(e){return`Received SparseTensor with denseShape[0] = 0 but\n  indices.shape[0] = ${e}`}function tP(e,t){return`indices(${e}, 0) is invalid: ${t} < 0`}function aP(e,t,a){return`indices(${e}, 0) is invalid: ${t} >= ${a}`}function nP(e,t){return`only one output dimension may be -1, not both ${e} and ${t}`}function rP(e,t){return`size ${e} must be non-negative, not ${t}`}function sP(){return\"reshape cannot infer the missing input size for an empty tensor unless all specified input sizes are non-zero\"}function iP(e,t){let a=At(e),n=At(t);return`Input to reshape is a SparseTensor with ${a}\n  dense values, but the requested shape requires a multiple of ${n}. inputShape=${e} outputShape= ${t}`}function oP(e,t){let a=At(e),n=At(t);return`Input to reshape is a tensor with ${a} dense values, but the requested shape has ${n}. inputShape=${e} outputShape=${t}`}function lP(){return\"segment ids must be >= 0\"}function uP(){return\"segment ids are not increasing\"}function dP(e,t){return`Segment id ${e} out of range [0, ${t}), possibly because segmentIds input is not sorted.`}function pP(e,t,a){return`Bad: indices[${e}] == ${t} out of range [0, ${a})`}var v4={};Xe(v4,{collectGatherOpShapeInfo:()=>fP,computeOutShape:()=>hP,segOpComputeOptimalWindowSize:()=>cP});function cP(e,t){let a=!1,n;for(e<=t3?(n=e,a=!0):n=Ic(e,Math.floor(Math.sqrt(e)));!a;)n>t||n===e?a=!0:n=Ic(e,n+1);return n}function hP(e,t,a){let n=[],r=e.length;for(let s=0;s<r;s++)s!==t?n.push(e[s]):n.push(a);return n}function fP(e,t,a,n){let r=t.shape.length,s=e.shape.length;if(n!==0&&(n<-r||n>r))throw new Error(`Expect batchDims in the range of [-${r}, ${r}], but got ${n}`);if(n<0&&(n+=r),n>s)throw new Error(`batchDims (${n}) must be less than rank(x) (\n    ${s}).`);if(a<n)throw new Error(`batchDims (${n}) must be less than or equal to axis (${a}).`);for(let c=0;c<n;++c)if(e.shape[c]!==t.shape[c])throw new Error(`x.shape[${c}]: ${e.shape[c]} should be equal to indices.shape[${c}]: ${t.shape[c]}.`);let i=e.shape[a],o=[],l=1,u=1,p=1;for(let c=0;c<n;++c)o.push(e.shape[c]),l*=e.shape[c];for(let c=n;c<a;c++)o.push(e.shape[c]),u*=e.shape[c];for(let c=n;c<r;c++)o.push(t.shape[c]);for(let c=a+1;c<s;c++)o.push(e.shape[c]),p*=e.shape[c];return{batchSize:l,sliceSize:p,outerSize:u,dimSize:i,outputShape:o}}function mP(e){try{return e.map(t=>Tc(t))}catch(t){throw new Error(`Failed to decode encoded string bytes into utf-8, error: ${t}`)}}function gP(e){return e.map(t=>Gd(t))}var Tn={};Xe(Tn,{nonMaxSuppressionV3Impl:()=>p4,nonMaxSuppressionV4Impl:()=>c4,nonMaxSuppressionV5Impl:()=>h4,whereImpl:()=>t4});var xP=W();xP.registerFlag(\"KEEP_INTERMEDIATE_TENSORS\",()=>!1,e=>{e&&console.warn(\"Keep intermediate tensors is ON. This will print the values of all intermediate tensors during model inference. Not all models support this mode. For details, check e2e/benchmarks/ model_config.js. This significantly impacts performance.\")});var wn;(function(e){e[e.DT_INVALID=0]=\"DT_INVALID\",e[e.DT_FLOAT=1]=\"DT_FLOAT\",e[e.DT_DOUBLE=2]=\"DT_DOUBLE\",e[e.DT_INT32=3]=\"DT_INT32\",e[e.DT_UINT8=4]=\"DT_UINT8\",e[e.DT_INT16=5]=\"DT_INT16\",e[e.DT_INT8=6]=\"DT_INT8\",e[e.DT_STRING=7]=\"DT_STRING\",e[e.DT_COMPLEX64=8]=\"DT_COMPLEX64\",e[e.DT_INT64=9]=\"DT_INT64\",e[e.DT_BOOL=10]=\"DT_BOOL\",e[e.DT_QINT8=11]=\"DT_QINT8\",e[e.DT_QUINT8=12]=\"DT_QUINT8\",e[e.DT_QINT32=13]=\"DT_QINT32\",e[e.DT_BFLOAT16=14]=\"DT_BFLOAT16\",e[e.DT_QINT16=15]=\"DT_QINT16\",e[e.DT_QUINT16=16]=\"DT_QUINT16\",e[e.DT_UINT16=17]=\"DT_UINT16\",e[e.DT_COMPLEX128=18]=\"DT_COMPLEX128\",e[e.DT_HALF=19]=\"DT_HALF\",e[e.DT_RESOURCE=20]=\"DT_RESOURCE\",e[e.DT_VARIANT=21]=\"DT_VARIANT\",e[e.DT_UINT32=22]=\"DT_UINT32\",e[e.DT_UINT64=23]=\"DT_UINT64\",e[e.DT_FLOAT_REF=101]=\"DT_FLOAT_REF\",e[e.DT_DOUBLE_REF=102]=\"DT_DOUBLE_REF\",e[e.DT_INT32_REF=103]=\"DT_INT32_REF\",e[e.DT_UINT8_REF=104]=\"DT_UINT8_REF\",e[e.DT_INT16_REF=105]=\"DT_INT16_REF\",e[e.DT_INT8_REF=106]=\"DT_INT8_REF\",e[e.DT_STRING_REF=107]=\"DT_STRING_REF\",e[e.DT_COMPLEX64_REF=108]=\"DT_COMPLEX64_REF\",e[e.DT_INT64_REF=109]=\"DT_INT64_REF\",e[e.DT_BOOL_REF=110]=\"DT_BOOL_REF\",e[e.DT_QINT8_REF=111]=\"DT_QINT8_REF\",e[e.DT_QUINT8_REF=112]=\"DT_QUINT8_REF\",e[e.DT_QINT32_REF=113]=\"DT_QINT32_REF\",e[e.DT_BFLOAT16_REF=114]=\"DT_BFLOAT16_REF\",e[e.DT_QINT16_REF=115]=\"DT_QINT16_REF\",e[e.DT_QUINT16_REF=116]=\"DT_QUINT16_REF\",e[e.DT_UINT16_REF=117]=\"DT_UINT16_REF\",e[e.DT_COMPLEX128_REF=118]=\"DT_COMPLEX128_REF\",e[e.DT_HALF_REF=119]=\"DT_HALF_REF\",e[e.DT_RESOURCE_REF=120]=\"DT_RESOURCE_REF\",e[e.DT_VARIANT_REF=121]=\"DT_VARIANT_REF\",e[e.DT_UINT32_REF=122]=\"DT_UINT32_REF\",e[e.DT_UINT64_REF=123]=\"DT_UINT64_REF\"})(wn||(wn={}));var J5;(function(e){let t;(function(a){a[a.LEGACY=0]=\"LEGACY\",a[a.V1=1]=\"V1\",a[a.V2=2]=\"V2\"})(t=e.CheckpointFormatVersion||(e.CheckpointFormatVersion={}))})(J5||(J5={}));var a3={};function AP(e,t){let a={tfOpName:e,category:\"custom\",inputs:[],attrs:[],customExecutor:t};a3[e]=a}function w4(e){return a3[e]}function yP(e){delete a3[e]}function k(e,t,a,n,r){let s=t.inputParams[e];if(s&&s.inputIndexStart!==void 0){let o=s.inputIndexStart,l=s.inputIndexEnd===0?void 0:s.inputIndexEnd===void 0?o+1:s.inputIndexEnd;if(s.type===\"tensor\")return ba(t.inputNames[s.inputIndexStart],a,n,r);if(s.type===\"tensors\")return t.inputNames.slice(o,l).map(c=>ba(c,a,n,r));let u=ba(t.inputNames.slice(o)[0],a,n,r),p=u.dataSync();return s.type===\"number\"?p[0]:v.toNestedArray(u.shape,p)}let i=t.attrParams[e];return i&&i.value}function ba(e,t,a,n){let[r,s]=ja(e);if(n!=null){let o=n.getHashTableHandleByName(r);if(o!=null)return o}let i=a.currentContextIds.find(o=>!!t[Mc(r,o)]);return i!==void 0?t[Mc(r,i)][s]:void 0}function bP(e,t,a){return t[Mc(e,a.currentContextId)]}function mr(e,t){let[a,n,r]=ja(e);return[Mc(a,t&&t.currentContextId),n,r]}function Mc(e,t){return t?`${e}-${t}`:e}function ja(e){let t=e.split(\":\");if(t.length===1)return[e,0,void 0];let a=t[0],n=t.length===3?t[1]:void 0,r=Number(t[t.length-1]);return[a,r,n]}function mc(e,t,a){let n=k(\"pad\",e,t,a);if(n===\"explicit\"){n=k(\"explicitPaddings\",e,t,a);let r=[[0,0],[0,0],[0,0],[0,0]];for(let s=0;s<4;s++)r[s][0]=n[s*2],r[s][1]=n[s*2+1];return r}return n}function gr(e){return e.kept?e:wa(e)}var k4={};Xe(k4,{json:()=>vP});var vP=[{tfOpName:\"Add\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"AddV2\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"AddN\",category:\"arithmetic\",inputs:[{start:0,end:0,name:\"tensors\",type:\"tensors\"}]},{tfOpName:\"BiasAdd\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0}]},{tfOpName:\"Sub\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"RealDiv\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Div\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"DivNoNan\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"FloorDiv\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Mul\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Maximum\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Minimum\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Pow\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"SquaredDifference\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Mod\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"FloorMod\",category:\"arithmetic\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]}],I4={};Xe(I4,{json:()=>wP});var wP=[{tfOpName:\"Abs\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Acos\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Asin\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Atan\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Atan2\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"y\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Ceil\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"ClipByValue\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"clipValueMin\",type:\"number\"},{start:2,name:\"clipValueMax\",type:\"number\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Complex\",category:\"basic_math\",inputs:[{start:0,name:\"real\",type:\"tensor\"},{start:1,name:\"imag\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"ComplexAbs\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Cos\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Cosh\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Elu\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Exp\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Floor\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Log\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Imag\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"Tout\",name:\"outputType\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Neg\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Real\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"Tout\",name:\"outputType\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Prelu\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"alpha\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Relu\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Relu6\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Selu\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Sigmoid\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Sin\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Sinh\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Sqrt\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Rsqrt\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Square\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Tan\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Tanh\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Sign\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Round\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Expm1\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Log1p\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Reciprocal\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Softplus\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Asinh\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Acosh\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Atanh\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Erf\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Prod\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axes\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\",notSupported:!0},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LeakyRelu\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"alpha\",name:\"alpha\",type:\"number\",defaultValue:.2},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"IsNan\",category:\"basic_math\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]}],S4={};Xe(S4,{json:()=>kP});var kP=[{tfOpName:\"EmptyTensorList\",category:\"control\",inputs:[{start:0,name:\"elementShape\",type:\"shape\"},{start:1,name:\"maxNumElements\",type:\"number\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"LoopCond\",category:\"control\",inputs:[{start:0,name:\"pred\",type:\"tensor\"}]},{tfOpName:\"Switch\",category:\"control\",inputs:[{start:0,name:\"data\",type:\"tensor\"},{start:1,name:\"pred\",type:\"tensor\"}]},{tfOpName:\"Merge\",category:\"control\",inputs:[{start:0,end:0,name:\"tensors\",type:\"tensors\"}]},{tfOpName:\"Enter\",category:\"control\",inputs:[{start:0,name:\"tensor\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"frame_name\",name:\"frameName\",type:\"string\"},{tfName:\"is_constant\",name:\"isConstant\",type:\"bool\"}]},{tfOpName:\"Exit\",category:\"control\",inputs:[{start:0,name:\"tensor\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"NextIteration\",category:\"control\",inputs:[{start:0,name:\"tensor\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"TensorArrayV3\",category:\"control\",inputs:[{start:0,name:\"size\",type:\"number\"}],attrs:[{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"},{tfName:\"element_shape\",name:\"elementShape\",type:\"shape\"},{tfName:\"dynamic_size\",name:\"dynamicSize\",type:\"bool\"},{tfName:\"clear_after_read\",name:\"clearAfterRead\",type:\"bool\"},{tfName:\"identical_element_shapes\",name:\"identicalElementShapes\",type:\"bool\"},{tfName:\"tensor_array_name\",name:\"name\",type:\"string\"}]},{tfOpName:\"TensorArrayWriteV3\",category:\"control\",inputs:[{start:0,name:\"tensorArrayId\",type:\"tensor\"},{start:1,name:\"index\",type:\"number\"},{start:2,name:\"tensor\",type:\"tensor\"},{start:3,name:\"flowIn\",type:\"number\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"TensorArrayReadV3\",category:\"control\",inputs:[{start:0,name:\"tensorArrayId\",type:\"tensor\"},{start:1,name:\"index\",type:\"number\"},{start:2,name:\"flowIn\",type:\"number\"}],attrs:[{tfName:\"dtype\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"TensorArrayGatherV3\",category:\"control\",inputs:[{start:0,name:\"tensorArrayId\",type:\"tensor\"},{start:1,name:\"indices\",type:\"number[]\"},{start:2,name:\"flowIn\",type:\"number\"}],attrs:[{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"},{tfName:\"element_shape\",name:\"elementShape\",type:\"shape\"}]},{tfOpName:\"TensorArrayScatterV3\",category:\"control\",inputs:[{start:0,name:\"tensorArrayId\",type:\"tensor\"},{start:1,name:\"indices\",type:\"number[]\"},{start:2,name:\"tensor\",type:\"tensor\"},{start:3,name:\"flowIn\",type:\"number\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"TensorArrayConcatV3\",category:\"control\",inputs:[{start:0,name:\"tensorArrayId\",type:\"tensor\"},{start:1,name:\"flowIn\",type:\"number\"}],attrs:[{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"},{tfName:\"element_shape_except0\",name:\"elementShapeExcept0\",type:\"shape\",notSupported:!0}]},{tfOpName:\"TensorArraySplitV3\",category:\"control\",inputs:[{start:0,name:\"tensorArrayId\",type:\"tensor\"},{start:1,name:\"tensor\",type:\"tensor\"},{start:2,name:\"lengths\",type:\"number[]\"},{start:3,name:\"flowIn\",type:\"number\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"TensorArraySizeV3\",category:\"control\",inputs:[{start:0,name:\"tensorArrayId\",type:\"tensor\"},{start:1,name:\"flowIn\",type:\"number\"}]},{tfOpName:\"TensorArrayCloseV3\",category:\"control\",inputs:[{start:0,name:\"tensorArrayId\",type:\"tensor\"}]},{tfOpName:\"StatelessIf\",category:\"control\",inputs:[{start:0,name:\"cond\",type:\"tensor\"},{start:1,end:0,name:\"args\",type:\"tensors\"}],attrs:[{tfName:\"then_branch\",name:\"thenBranch\",type:\"func\"},{tfName:\"else_branch\",name:\"elseBranch\",type:\"func\"}]},{tfOpName:\"If\",category:\"control\",inputs:[{start:0,name:\"cond\",type:\"tensor\"},{start:1,end:0,name:\"args\",type:\"tensors\"}],attrs:[{tfName:\"then_branch\",name:\"thenBranch\",type:\"func\"},{tfName:\"else_branch\",name:\"elseBranch\",type:\"func\"}]},{tfOpName:\"StatelessWhile\",category:\"control\",inputs:[{start:0,end:0,name:\"args\",type:\"tensors\"}],attrs:[{tfName:\"cond\",name:\"cond\",type:\"func\"},{tfName:\"body\",name:\"body\",type:\"func\"}]},{tfOpName:\"While\",category:\"control\",inputs:[{start:0,end:0,name:\"args\",type:\"tensors\"}],attrs:[{tfName:\"cond\",name:\"cond\",type:\"func\"},{tfName:\"body\",name:\"body\",type:\"func\"}]},{tfOpName:\"TensorListScatter\",category:\"control\",inputs:[{start:0,name:\"tensor\",type:\"tensor\"},{start:1,name:\"indices\",type:\"number[]\"},{start:2,name:\"elementShape\",type:\"shape\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListScatterV2\",category:\"control\",inputs:[{start:0,name:\"tensor\",type:\"tensor\"},{start:1,name:\"indices\",type:\"number[]\"},{start:2,name:\"elementShape\",type:\"shape\"},{start:3,name:\"numElements\",type:\"number\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListGather\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"},{start:1,name:\"indices\",type:\"number[]\"},{start:2,name:\"elementShape\",type:\"shape\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListGetItem\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"},{start:1,name:\"index\",type:\"number\"},{start:2,name:\"elementShape\",type:\"shape\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListSetItem\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"},{start:1,name:\"index\",type:\"number\"},{start:2,name:\"tensor\",type:\"tensor\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListReserve\",category:\"control\",inputs:[{start:0,name:\"elementShape\",type:\"shape\"},{start:1,name:\"numElements\",type:\"number\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListFromTensor\",category:\"control\",inputs:[{start:0,name:\"tensor\",type:\"tensor\"},{start:1,name:\"elementShape\",type:\"shape\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListStack\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"},{start:1,name:\"elementShape\",type:\"shape\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"},{tfName:\"num_elements\",name:\"numElements\",type:\"dtype\"}]},{tfOpName:\"TensorListSplit\",category:\"control\",inputs:[{start:0,name:\"tensor\",type:\"tensor\"},{start:1,name:\"elementShape\",type:\"shape\"},{start:2,name:\"lengths\",type:\"number[]\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListConcat\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"}],attrs:[{tfName:\"element_shape\",name:\"elementShape\",type:\"shape\"},{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListConcatV2\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"}],attrs:[{tfName:\"element_shape\",name:\"elementShape\",type:\"shape\"},{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListPopBack\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"},{start:1,name:\"elementShape\",type:\"shape\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListPushBack\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"},{start:1,name:\"tensor\",type:\"tensor\"}],attrs:[{tfName:\"element_dtype\",name:\"elementDType\",type:\"dtype\"}]},{tfOpName:\"TensorListLength\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"}]},{tfOpName:\"TensorListResize\",category:\"control\",inputs:[{start:0,name:\"tensorListId\",type:\"tensor\"},{start:1,name:\"size\",type:\"number\"}]}],T4={};Xe(T4,{json:()=>IP});var IP=[{tfOpName:\"AvgPool\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0},{tfName:\"ksize\",name:\"kernelSize\",type:\"number[]\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"MaxPool\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0},{tfName:\"ksize\",name:\"kernelSize\",type:\"number[]\"},{tfName:\"explicit_paddings\",name:\"explicitPaddings\",type:\"number[]\",defaultValue:[],notSupported:!0},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"MaxPoolWithArgmax\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"ksize\",name:\"kernelSize\",type:\"number[]\"},{tfName:\"include_batch_in_index\",name:\"includeBatchInIndex\",type:\"bool\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"AvgPool3D\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0},{tfName:\"ksize\",name:\"kernelSize\",type:\"number[]\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"MaxPool3D\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0},{tfName:\"ksize\",name:\"kernelSize\",type:\"number[]\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Conv1D\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"}],attrs:[{tfName:\"stride\",name:\"stride\",type:\"number\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",defaultValue:\"NWC\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"dilation\",name:\"dilation\",type:\"number\",defaultValue:1}]},{tfOpName:\"Conv2D\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"useCudnnOnGpu\",name:\"useCudnnOnGpu\",type:\"bool\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",defaultValue:\"NHWC\"},{tfName:\"explicit_paddings\",name:\"explicitPaddings\",type:\"number[]\",defaultValue:[]},{tfName:\"dilations\",name:\"dilations\",type:\"number[]\"}]},{tfOpName:\"_FusedConv2D\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"},{start:2,end:0,name:\"args\",type:\"tensors\"}],attrs:[{tfName:\"num_args\",name:\"numArgs\",type:\"number\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"explicit_paddings\",name:\"explicitPaddings\",type:\"number[]\",defaultValue:[]},{tfName:\"use_cudnn_on_gpu\",name:\"useCudnnOnGpu\",type:\"bool\",defaultValue:!0},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",defaultValue:\"NHWC\"},{tfName:\"dilations\",name:\"dilations\",type:\"number[]\",defaultValue:[1,1,1,1]},{tfName:\"fused_ops\",name:\"fusedOps\",type:\"string[]\",defaultValue:[]},{tfName:\"epsilon\",name:\"epsilon\",type:\"number\",defaultValue:1e-4},{tfName:\"leakyrelu_alpha\",name:\"leakyreluAlpha\",type:\"number\",defaultValue:.2}]},{tfOpName:\"Conv2DBackpropInput\",category:\"convolution\",inputs:[{start:2,name:\"x\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"},{start:0,name:\"outputShape\",type:\"number[]\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0},{tfName:\"explicit_paddings\",name:\"explicitPaddings\",type:\"number[]\",defaultValue:[]},{tfName:\"dilations\",name:\"dilations\",type:\"number[]\",notSupported:!0}]},{tfOpName:\"DepthwiseConv2d\",category:\"convolution\",inputs:[{start:0,name:\"input\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",defaultValue:\"NHWC\"},{tfName:\"explicit_paddings\",name:\"explicitPaddings\",type:\"number[]\",defaultValue:[]},{tfName:\"dilations\",name:\"dilations\",type:\"number[]\"}]},{tfOpName:\"DepthwiseConv2dNative\",category:\"convolution\",inputs:[{start:0,name:\"input\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",defaultValue:\"NHWC\"},{tfName:\"explicit_paddings\",name:\"explicitPaddings\",type:\"number[]\",defaultValue:[]},{tfName:\"dilations\",name:\"dilations\",type:\"number[]\"}]},{tfOpName:\"FusedDepthwiseConv2dNative\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"},{start:2,end:0,name:\"args\",type:\"tensors\"}],attrs:[{tfName:\"num_args\",name:\"numArgs\",type:\"number\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",defaultValue:\"NHWC\"},{tfName:\"dilations\",name:\"dilations\",type:\"number[]\",defaultValue:[1,1,1,1]},{tfName:\"fused_ops\",name:\"fusedOps\",type:\"string[]\",defaultValue:[]},{tfName:\"explicit_paddings\",name:\"explicitPaddings\",type:\"number[]\",defaultValue:[]}]},{tfOpName:\"Conv3D\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",defaultValue:\"NHWC\"},{tfName:\"dilations\",name:\"dilations\",type:\"number[]\"}]},{tfOpName:\"Dilation2D\",category:\"convolution\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"filter\",type:\"tensor\"}],attrs:[{tfName:\"strides\",name:\"strides\",type:\"number[]\"},{tfName:\"rates\",name:\"dilations\",type:\"number[]\"},{tfName:\"padding\",name:\"pad\",type:\"string\"}]}],C4={};Xe(C4,{json:()=>SP});var SP=[{tfOpName:\"Fill\",category:\"creation\",inputs:[{start:0,name:\"shape\",type:\"number[]\"},{start:1,name:\"value\",type:\"number\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"LinSpace\",category:\"creation\",inputs:[{start:0,name:\"start\",type:\"number\"},{start:1,name:\"stop\",type:\"number\"},{start:2,name:\"num\",type:\"number\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"OneHot\",category:\"creation\",inputs:[{start:0,name:\"indices\",type:\"tensor\"},{start:1,name:\"depth\",type:\"number\"},{start:2,name:\"onValue\",type:\"number\",defaultValue:1},{start:3,name:\"offValue\",type:\"number\",defaultValue:0}],attrs:[{tfName:\"axis\",name:\"axis\",type:\"number\",notSupported:!0},{tfName:\"T\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"Ones\",category:\"creation\",inputs:[{start:0,name:\"shape\",type:\"number[]\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"OnesLike\",category:\"creation\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"RandomStandardNormal\",category:\"creation\",inputs:[{start:0,name:\"shape\",type:\"number[]\"}],attrs:[{tfName:\"seed\",name:\"seed\",type:\"number\",defaultValue:0},{tfName:\"seed2\",name:\"seed2\",type:\"number\",defaultValue:0,notSupported:!0},{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"},{tfName:\"T\",name:\"T\",type:\"number\",notSupported:!0}]},{tfOpName:\"RandomUniform\",category:\"creation\",inputs:[{start:0,name:\"shape\",type:\"number[]\"}],attrs:[{tfName:\"minval\",name:\"minval\",type:\"number\",defaultValue:0},{tfName:\"maxval\",name:\"maxval\",type:\"number\",defaultValue:1},{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"},{tfName:\"seed\",name:\"seed\",type:\"number\",defaultValue:0},{tfName:\"seed2\",name:\"seed2\",type:\"number\",defaultValue:0,notSupported:!0},{tfName:\"T\",name:\"T\",type:\"number\",notSupported:!0}]},{tfOpName:\"Range\",category:\"creation\",inputs:[{start:0,name:\"start\",type:\"number\"},{start:1,name:\"stop\",type:\"number\"},{start:2,name:\"step\",type:\"number\",defaultValue:0}],attrs:[{tfName:\"Tidx\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"TruncatedNormal\",category:\"creation\",inputs:[{start:0,name:\"shape\",type:\"number[]\"}],attrs:[{tfName:\"means\",name:\"mean\",type:\"number\",defaultValue:0},{tfName:\"stddev\",name:\"stdDev\",type:\"number\",defaultValue:1},{tfName:\"seed\",name:\"seed\",type:\"number\"},{tfName:\"seed2\",name:\"seed2\",type:\"number\",defaultValue:0,notSupported:!0},{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"},{tfName:\"T\",name:\"T\",type:\"number\",notSupported:!0}]},{tfOpName:\"Zeros\",category:\"creation\",inputs:[{start:0,name:\"shape\",type:\"number[]\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"ZerosLike\",category:\"creation\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"Multinomial\",category:\"creation\",inputs:[{start:0,name:\"logits\",type:\"tensor\"},{start:1,name:\"numSamples\",type:\"number\"}],attrs:[{tfName:\"seed\",name:\"seed\",type:\"number\"},{tfName:\"seed2\",name:\"seed2\",type:\"number\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\"},{tfName:\"output_dtype\",name:\"output_dtype\",type:\"dtype\"}]}],N4={};Xe(N4,{json:()=>TP});var TP=[{tfOpName:\"NonMaxSuppressionV2\",category:\"dynamic\",inputs:[{start:0,name:\"boxes\",type:\"tensor\"},{start:1,name:\"scores\",type:\"tensor\"},{start:2,name:\"maxOutputSize\",type:\"number\"},{start:3,name:\"iouThreshold\",type:\"number\"}]},{tfOpName:\"NonMaxSuppressionV3\",category:\"dynamic\",inputs:[{start:0,name:\"boxes\",type:\"tensor\"},{start:1,name:\"scores\",type:\"tensor\"},{start:2,name:\"maxOutputSize\",type:\"number\"},{start:3,name:\"iouThreshold\",type:\"number\"},{start:4,name:\"scoreThreshold\",type:\"number\"}]},{tfOpName:\"NonMaxSuppressionV4\",category:\"dynamic\",inputs:[{start:0,name:\"boxes\",type:\"tensor\"},{start:1,name:\"scores\",type:\"tensor\"},{start:2,name:\"maxOutputSize\",type:\"number\"},{start:3,name:\"iouThreshold\",type:\"number\"},{start:4,name:\"scoreThreshold\",type:\"number\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0},{tfName:\"T_threshold\",name:\"threshold\",type:\"dtype\",notSupported:!0},{tfName:\"pad_to_max_output_size\",name:\"padToMaxOutputSize\",type:\"bool\"}]},{tfOpName:\"NonMaxSuppressionV5\",category:\"dynamic\",inputs:[{start:0,name:\"boxes\",type:\"tensor\"},{start:1,name:\"scores\",type:\"tensor\"},{start:2,name:\"maxOutputSize\",type:\"number\"},{start:3,name:\"iouThreshold\",type:\"number\"},{start:4,name:\"scoreThreshold\",type:\"number\"},{start:5,name:\"softNmsSigma\",type:\"number\"}]},{tfOpName:\"Where\",category:\"dynamic\",inputs:[{start:0,name:\"condition\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"ListDiff\",category:\"dynamic\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"y\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]}],E4={};Xe(E4,{json:()=>CP});var CP=[{tfOpName:\"LowerBound\",category:\"evaluation\",inputs:[{start:0,name:\"sortedSequence\",type:\"tensor\"},{start:1,name:\"values\",type:\"tensor\"}]},{tfOpName:\"TopKV2\",category:\"evaluation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"k\",type:\"number\"}],attrs:[{tfName:\"sorted\",name:\"sorted\",type:\"bool\"}]},{tfOpName:\"UpperBound\",category:\"evaluation\",inputs:[{start:0,name:\"sortedSequence\",type:\"tensor\"},{start:1,name:\"values\",type:\"tensor\"}]},{tfOpName:\"Unique\",category:\"evaluation\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"UniqueV2\",category:\"evaluation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number\"}]}],R4={};Xe(R4,{json:()=>NP});var NP=[{tfOpName:\"PlaceholderWithDefault\",category:\"graph\",inputs:[{start:0,name:\"default\",type:\"tensor\"}],attrs:[{tfName:\"shape\",name:\"shape\",type:\"shape\"},{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"Placeholder\",category:\"graph\",attrs:[{tfName:\"shape\",name:\"shape\",type:\"shape\"},{tfName:\"dtype\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"Const\",category:\"graph\"},{tfOpName:\"Identity\",category:\"graph\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"IdentityN\",category:\"graph\",inputs:[{start:0,end:0,name:\"x\",type:\"tensors\"}]},{tfOpName:\"Snapshot\",category:\"graph\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"Rank\",category:\"graph\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"Size\",category:\"graph\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"Shape\",category:\"graph\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"ShapeN\",category:\"graph\",inputs:[{start:0,end:0,name:\"x\",type:\"tensors\"}]},{tfOpName:\"Print\",category:\"graph\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"data\",type:\"tensors\"}],attrs:[{tfName:\"message\",name:\"message\",type:\"string\"},{tfName:\"first_n\",name:\"firstN\",type:\"number\",notSupported:!0},{tfName:\"summarize\",name:\"summarize\",type:\"number\",defaultValue:3}]},{tfOpName:\"NoOp\",category:\"graph\",inputs:[]},{tfOpName:\"StopGradient\",category:\"graph\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"FakeQuantWithMinMaxVars\",category:\"graph\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"min\",name:\"min\",type:\"number\"},{tfName:\"max\",name:\"max\",type:\"number\"}]}],M4={};Xe(M4,{json:()=>EP});var EP=[{tfOpName:\"HashTable\",category:\"hash_table\",inputs:[],attrs:[{tfName:\"shared_name\",name:\"sharedName\",type:\"string\"},{tfName:\"use_node_name_sharing\",name:\"useNodeNameSharing\",type:\"bool\"},{tfName:\"key_dtype\",name:\"keyDType\",type:\"dtype\"},{tfName:\"value_dtype\",name:\"valueDType\",type:\"dtype\"}]},{tfOpName:\"HashTableV2\",category:\"hash_table\",inputs:[],attrs:[{tfName:\"shared_name\",name:\"sharedName\",type:\"string\"},{tfName:\"use_node_name_sharing\",name:\"useNodeNameSharing\",type:\"bool\"},{tfName:\"key_dtype\",name:\"keyDType\",type:\"dtype\"},{tfName:\"value_dtype\",name:\"valueDType\",type:\"dtype\"}]},{tfOpName:\"LookupTableImport\",category:\"hash_table\",inputs:[{start:0,name:\"tableHandle\",type:\"tensor\"},{start:1,name:\"keys\",type:\"tensor\"},{start:2,name:\"values\",type:\"tensor\"}],attrs:[{tfName:\"Tin\",name:\"tIn\",type:\"dtype\",notSupported:!0},{tfName:\"Tout\",name:\"tOut\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LookupTableImportV2\",category:\"hash_table\",inputs:[{start:0,name:\"tableHandle\",type:\"tensor\"},{start:1,name:\"keys\",type:\"tensor\"},{start:2,name:\"values\",type:\"tensor\"}],attrs:[{tfName:\"Tin\",name:\"tIn\",type:\"dtype\",notSupported:!0},{tfName:\"Tout\",name:\"tOut\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LookupTableFind\",category:\"hash_table\",inputs:[{start:0,name:\"tableHandle\",type:\"tensor\"},{start:1,name:\"keys\",type:\"tensor\"},{start:2,name:\"defaultValue\",type:\"tensor\"}],attrs:[{tfName:\"Tin\",name:\"tIn\",type:\"dtype\",notSupported:!0},{tfName:\"Tout\",name:\"tOut\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LookupTableFindV2\",category:\"hash_table\",inputs:[{start:0,name:\"tableHandle\",type:\"tensor\"},{start:1,name:\"keys\",type:\"tensor\"},{start:2,name:\"defaultValue\",type:\"tensor\"}],attrs:[{tfName:\"Tin\",name:\"tIn\",type:\"dtype\",notSupported:!0},{tfName:\"Tout\",name:\"tOut\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LookupTableSize\",category:\"hash_table\",inputs:[{start:0,name:\"tableHandle\",type:\"tensor\"}]},{tfOpName:\"LookupTableSizeV2\",category:\"hash_table\",inputs:[{start:0,name:\"tableHandle\",type:\"tensor\"}]},{tfOpName:\"InitializeTable\",category:\"hash_table\",inputs:[{start:0,name:\"tableHandle\",type:\"tensor\"},{start:1,name:\"keys\",type:\"tensor\"},{start:2,name:\"values\",type:\"tensor\"}]},{tfOpName:\"InitializeTableV2\",category:\"hash_table\",inputs:[{start:0,name:\"tableHandle\",type:\"tensor\"},{start:1,name:\"keys\",type:\"tensor\"},{start:2,name:\"values\",type:\"tensor\"}]}],$4={};Xe($4,{json:()=>RP});var RP=[{tfOpName:\"ResizeBilinear\",category:\"image\",inputs:[{start:0,name:\"images\",type:\"tensor\"},{start:1,name:\"size\",type:\"number[]\"}],attrs:[{tfName:\"align_corners\",name:\"alignCorners\",type:\"bool\"},{tfName:\"half_pixel_centers\",name:\"halfPixelCenters\",type:\"bool\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"ResizeNearestNeighbor\",category:\"image\",inputs:[{start:0,name:\"images\",type:\"tensor\"},{start:1,name:\"size\",type:\"number[]\"}],attrs:[{tfName:\"align_corners\",name:\"alignCorners\",type:\"bool\"},{tfName:\"half_pixel_centers\",name:\"halfPixelCenters\",type:\"bool\"},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"CropAndResize\",category:\"image\",inputs:[{start:0,name:\"image\",type:\"tensor\"},{start:1,name:\"boxes\",type:\"tensor\"},{start:2,name:\"boxInd\",type:\"tensor\"},{start:3,name:\"cropSize\",type:\"number[]\"}],attrs:[{tfName:\"method\",name:\"method\",type:\"string\"},{tfName:\"extrapolation_value\",name:\"extrapolationValue\",type:\"number\"}]},{tfOpName:\"ImageProjectiveTransformV3\",category:\"image\",inputs:[{start:0,name:\"images\",type:\"tensor\"},{start:1,name:\"transforms\",type:\"tensor\"},{start:2,name:\"outputShape\",type:\"number[]\"},{start:3,name:\"fillValue\",type:\"number\"}],attrs:[{tfName:\"interpolation\",name:\"interpolation\",type:\"string\"},{tfName:\"fill_mode\",name:\"fillMode\",type:\"string\"}]}],_4={};Xe(_4,{json:()=>MP});var MP=[{tfOpName:\"Equal\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"NotEqual\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Greater\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"GreaterEqual\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Less\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LessEqual\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LogicalAnd\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LogicalNot\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"LogicalOr\",category:\"logical\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Select\",category:\"logical\",inputs:[{start:0,name:\"condition\",type:\"tensor\"},{start:1,name:\"a\",type:\"tensor\"},{start:2,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"SelectV2\",category:\"logical\",inputs:[{start:0,name:\"condition\",type:\"tensor\"},{start:1,name:\"a\",type:\"tensor\"},{start:2,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]}],P4={};Xe(P4,{json:()=>$P});var $P=[{tfOpName:\"_FusedMatMul\",category:\"matrices\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"},{start:2,end:0,name:\"args\",type:\"tensors\"}],attrs:[{tfName:\"num_args\",name:\"numArgs\",type:\"number\"},{tfName:\"fused_ops\",name:\"fusedOps\",type:\"string[]\",defaultValue:[]},{tfName:\"epsilon\",name:\"epsilon\",type:\"number\",defaultValue:1e-4},{tfName:\"transpose_a\",name:\"transposeA\",type:\"bool\",defaultValue:!1},{tfName:\"transpose_b\",name:\"transposeB\",type:\"bool\",defaultValue:!1},{tfName:\"leakyrelu_alpha\",name:\"leakyreluAlpha\",type:\"number\",defaultValue:.2},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"MatMul\",category:\"matrices\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"transpose_a\",name:\"transposeA\",type:\"bool\",defaultValue:!1},{tfName:\"transpose_b\",name:\"transposeB\",type:\"bool\",defaultValue:!1},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"BatchMatMul\",category:\"matrices\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"adj_x\",name:\"transposeA\",type:\"bool\",defaultValue:!1},{tfName:\"adj_y\",name:\"transposeB\",type:\"bool\",defaultValue:!1},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"BatchMatMulV2\",category:\"matrices\",inputs:[{start:0,name:\"a\",type:\"tensor\"},{start:1,name:\"b\",type:\"tensor\"}],attrs:[{tfName:\"adj_x\",name:\"transposeA\",type:\"bool\",defaultValue:!1},{tfName:\"adj_y\",name:\"transposeB\",type:\"bool\",defaultValue:!1},{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Transpose\",category:\"matrices\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"perm\",type:\"number[]\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"Einsum\",category:\"matrices\",inputs:[{start:0,end:0,name:\"tensors\",type:\"tensors\"}],attrs:[{tfName:\"equation\",name:\"equation\",type:\"string\"},{tfName:\"N\",name:\"n\",type:\"number\",defaultValue:2},{tfName:\"T\",name:\"dtype\",type:\"dtype\"}]}],F4={};Xe(F4,{json:()=>_P});var _P=[{tfOpName:\"EuclideanNorm\",category:\"normalization\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\",defaultValue:!1}]},{tfOpName:\"FusedBatchNorm\",category:\"normalization\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"scale\",type:\"tensor\"},{start:2,name:\"offset\",type:\"tensor\"},{start:3,name:\"mean\",type:\"tensor\"},{start:4,name:\"variance\",type:\"tensor\"}],attrs:[{tfName:\"epsilon\",name:\"epsilon\",type:\"number\",defaultValue:.001},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0}]},{tfOpName:\"FusedBatchNormV2\",category:\"normalization\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"scale\",type:\"tensor\"},{start:2,name:\"offset\",type:\"tensor\"},{start:3,name:\"mean\",type:\"tensor\"},{start:4,name:\"variance\",type:\"tensor\"}],attrs:[{tfName:\"epsilon\",name:\"epsilon\",type:\"number\",defaultValue:.001},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0}]},{tfOpName:\"FusedBatchNormV3\",category:\"normalization\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"scale\",type:\"tensor\"},{start:2,name:\"offset\",type:\"tensor\"},{start:3,name:\"mean\",type:\"tensor\"},{start:4,name:\"variance\",type:\"tensor\"}],attrs:[{tfName:\"epsilon\",name:\"epsilon\",type:\"number\",defaultValue:.001},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\",notSupported:!0}]},{tfOpName:\"LRN\",category:\"normalization\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"depth_radius\",name:\"radius\",type:\"number\",defaultValue:5},{tfName:\"bias\",name:\"bias\",type:\"number\",defaultValue:1},{tfName:\"alpha\",name:\"alpha\",type:\"number\",defaultValue:1},{tfName:\"beta\",name:\"beta\",type:\"number\",defaultValue:.5}]},{tfOpName:\"Softmax\",category:\"normalization\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"LogSoftmax\",category:\"normalization\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"SparseToDense\",category:\"normalization\",inputs:[{start:0,name:\"sparseIndices\",type:\"tensor\"},{start:1,name:\"outputShape\",type:\"number[]\"},{start:2,name:\"sparseValues\",type:\"tensor\"},{start:3,name:\"defaultValue\",type:\"tensor\"}],attrs:[{tfName:\"validate_indices\",name:\"validateIndices\",type:\"bool\",defaultValue:!0,notSupported:!0}]}],O4={};Xe(O4,{json:()=>PP});var PP=[{tfOpName:\"Bincount\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"size\",type:\"number\"},{start:2,name:\"weights\",type:\"tensor\"}]},{tfOpName:\"DenseBincount\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"size\",type:\"number\"},{start:2,name:\"weights\",type:\"tensor\"}],attrs:[{tfName:\"binary_output\",name:\"binaryOutput\",type:\"bool\"}]},{tfOpName:\"Max\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\"}]},{tfOpName:\"Mean\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\"}]},{tfOpName:\"Min\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\"}]},{tfOpName:\"Sum\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\"}]},{tfOpName:\"All\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\"}]},{tfOpName:\"Any\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\"}]},{tfOpName:\"ArgMax\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number\"}]},{tfOpName:\"ArgMin\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number\"}]},{tfOpName:\"Prod\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}],attrs:[{tfName:\"keep_dims\",name:\"keepDims\",type:\"bool\"}]},{tfOpName:\"Cumprod\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number\"}],attrs:[{tfName:\"exclusive\",name:\"exclusive\",type:\"bool\"},{tfName:\"reverse\",name:\"reverse\",type:\"bool\"}]},{tfOpName:\"Cumsum\",category:\"reduction\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number\"}],attrs:[{tfName:\"exclusive\",name:\"exclusive\",type:\"bool\"},{tfName:\"reverse\",name:\"reverse\",type:\"bool\"}]}],D4={};Xe(D4,{json:()=>FP});var FP=[{tfOpName:\"ConcatV2\",category:\"slice_join\",inputs:[{start:0,end:-1,name:\"tensors\",type:\"tensors\"},{start:-1,name:\"axis\",type:\"number\"}],attrs:[{tfName:\"N\",name:\"n\",type:\"number\",defaultValue:2}]},{tfOpName:\"Concat\",category:\"slice_join\",inputs:[{start:1,end:0,name:\"tensors\",type:\"tensors\"},{start:0,name:\"axis\",type:\"number\"}],attrs:[{tfName:\"N\",name:\"n\",type:\"number\",defaultValue:2}]},{tfOpName:\"GatherV2\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"indices\",type:\"tensor\"},{start:2,name:\"axis\",type:\"number\",defaultValue:0}],attrs:[{tfName:\"batch_dims\",name:\"batchDims\",type:\"number\",defaultValue:0}]},{tfOpName:\"Gather\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"indices\",type:\"tensor\"}],attrs:[{tfName:\"validate_indices\",name:\"validateIndices\",type:\"bool\",notSupported:!0}]},{tfOpName:\"Reverse\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"dims\",type:\"bool[]\"}]},{tfOpName:\"ReverseV2\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number[]\"}]},{tfOpName:\"Slice\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"begin\",type:\"number[]\"},{start:2,name:\"size\",type:\"number[]\"}]},{tfOpName:\"StridedSlice\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"begin\",type:\"number[]\"},{start:2,name:\"end\",type:\"number[]\"},{start:3,name:\"strides\",type:\"number[]\"}],attrs:[{tfName:\"begin_mask\",name:\"beginMask\",type:\"number\",defaultValue:0},{tfName:\"end_mask\",name:\"endMask\",type:\"number\",defaultValue:0},{tfName:\"new_axis_mask\",name:\"newAxisMask\",type:\"number\",defaultValue:0},{tfName:\"ellipsis_mask\",name:\"ellipsisMask\",type:\"number\",defaultValue:0},{tfName:\"shrink_axis_mask\",name:\"shrinkAxisMask\",type:\"number\",defaultValue:0}]},{tfOpName:\"Pack\",category:\"slice_join\",inputs:[{start:0,end:0,name:\"tensors\",type:\"tensors\"}],attrs:[{tfName:\"axis\",name:\"axis\",type:\"number\",defaultValue:0}]},{tfOpName:\"Unpack\",category:\"slice_join\",inputs:[{start:0,name:\"tensor\",type:\"tensor\"}],attrs:[{tfName:\"axis\",name:\"axis\",type:\"number\",defaultValue:0},{tfName:\"num\",name:\"num\",type:\"number\",defaultValue:0,notSupported:!0}]},{tfOpName:\"Tile\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"reps\",type:\"number[]\"}]},{tfOpName:\"Split\",category:\"slice_join\",inputs:[{start:0,name:\"axis\",type:\"number\",defaultValue:0},{start:1,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"num_split\",name:\"numOrSizeSplits\",type:\"number\",defaultValue:1}]},{tfOpName:\"SplitV\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"numOrSizeSplits\",type:\"number[]\"},{start:2,name:\"axis\",type:\"number\",defaultValue:0}]},{tfOpName:\"ScatterNd\",category:\"slice_join\",inputs:[{start:0,name:\"indices\",type:\"tensor\"},{start:1,name:\"values\",type:\"tensor\"},{start:2,name:\"shape\",type:\"number[]\"}]},{tfOpName:\"GatherNd\",category:\"slice_join\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"indices\",type:\"tensor\"}]},{tfOpName:\"SparseToDense\",category:\"slice_join\",inputs:[{start:0,name:\"sparseIndices\",type:\"tensor\"},{start:1,name:\"outputShape\",type:\"number[]\"},{start:2,name:\"sparseValues\",type:\"tensor\"},{start:3,name:\"defaultValue\",type:\"tensor\"}],attrs:[{tfName:\"validate_indices\",name:\"validateIndices\",type:\"bool\",defaultValue:!1,notSupported:!0}]}],z4={};Xe(z4,{json:()=>OP});var OP=[{tfOpName:\"SparseFillEmptyRows\",category:\"sparse\",inputs:[{start:0,name:\"indices\",type:\"tensor\"},{start:1,name:\"values\",type:\"tensor\"},{start:2,name:\"denseShape\",type:\"tensor\"},{start:3,name:\"defaultValue\",type:\"tensor\"}]},{tfOpName:\"SparseReshape\",category:\"sparse\",inputs:[{start:0,name:\"inputIndices\",type:\"tensor\"},{start:1,name:\"inputShape\",type:\"tensor\"},{start:2,name:\"newShape\",type:\"tensor\"}],attrs:[{tfName:\"T\",name:\"dtype\",type:\"dtype\",notSupported:!0}]},{tfOpName:\"SparseSegmentMean\",category:\"sparse\",inputs:[{start:0,name:\"data\",type:\"tensor\"},{start:1,name:\"indices\",type:\"tensor\"},{start:2,name:\"segmentIds\",type:\"tensor\"}]},{tfOpName:\"SparseSegmentSum\",category:\"sparse\",inputs:[{start:0,name:\"data\",type:\"tensor\"},{start:1,name:\"indices\",type:\"tensor\"},{start:2,name:\"segmentIds\",type:\"tensor\"}]}],L4={};Xe(L4,{json:()=>DP});var DP=[{tfOpName:\"FFT\",category:\"spectral\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"IFFT\",category:\"spectral\",inputs:[{start:0,name:\"x\",type:\"tensor\"}]},{tfOpName:\"RFFT\",category:\"spectral\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"fft_length\",type:\"number\",notSupported:!0}]},{tfOpName:\"IRFFT\",category:\"spectral\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"fft_length\",type:\"number\",notSupported:!0}]}],B4={};Xe(B4,{json:()=>zP});var zP=[{tfOpName:\"StringNGrams\",category:\"string\",inputs:[{start:0,name:\"data\",type:\"tensor\"},{start:1,name:\"dataSplits\",type:\"tensor\"}],attrs:[{tfName:\"separator\",name:\"separator\",type:\"string\"},{tfName:\"ngram_widths\",name:\"nGramWidths\",type:\"number[]\"},{tfName:\"left_pad\",name:\"leftPad\",type:\"string\"},{tfName:\"right_pad\",name:\"rightPad\",type:\"string\"},{tfName:\"pad_width\",name:\"padWidth\",type:\"number\"},{tfName:\"preserve_short_sequences\",name:\"preserveShortSequences\",type:\"bool\"}],outputs:[\"ngrams\",\"ngrams_splits\"]},{tfOpName:\"StringSplit\",category:\"string\",inputs:[{start:0,name:\"input\",type:\"tensor\"},{start:1,name:\"delimiter\",type:\"tensor\"}],attrs:[{tfName:\"skip_empty\",name:\"skipEmpty\",type:\"bool\"}],outputs:[\"indices\",\"values\",\"shape\"]},{tfOpName:\"StringToHashBucketFast\",category:\"string\",inputs:[{start:0,name:\"input\",type:\"tensor\"}],attrs:[{tfName:\"num_buckets\",name:\"numBuckets\",type:\"number\"}]}],W4={};Xe(W4,{json:()=>LP});var LP=[{tfOpName:\"Cast\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"SrcT\",name:\"sdtype\",type:\"dtype\",notSupported:!0},{tfName:\"DstT\",name:\"dtype\",type:\"dtype\"}]},{tfOpName:\"ExpandDims\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"axis\",type:\"number\"}]},{tfOpName:\"MirrorPad\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"padding\",type:\"number[]\"}],attrs:[{tfName:\"mode\",name:\"mode\",type:\"string\"}]},{tfOpName:\"Pad\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"padding\",type:\"number[]\"}],attrs:[{tfName:\"constant_value\",name:\"constantValue\",type:\"number\",defaultValue:0}]},{tfOpName:\"PadV2\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"padding\",type:\"number[]\"},{start:2,name:\"constantValue\",type:\"number\",defaultValue:0}]},{tfOpName:\"Reshape\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"shape\",type:\"number[]\"}]},{tfOpName:\"Squeeze\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"axis\",tfDeprecatedName:\"squeeze_dims\",name:\"axis\",type:\"number[]\"}]},{tfOpName:\"SpaceToBatchND\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"blockShape\",type:\"number[]\"},{start:2,name:\"paddings\",type:\"number[]\"}]},{tfOpName:\"BatchToSpaceND\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"blockShape\",type:\"number[]\"},{start:2,name:\"crops\",type:\"number[]\"}]},{tfOpName:\"DepthToSpace\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"}],attrs:[{tfName:\"block_size\",name:\"blockSize\",type:\"number\"},{tfName:\"data_format\",name:\"dataFormat\",type:\"string\"}]},{tfOpName:\"BroadcastTo\",category:\"transformation\",inputs:[{start:0,name:\"x\",type:\"tensor\"},{start:1,name:\"shape\",type:\"number[]\"}],attrs:[]},{tfOpName:\"BroadcastArgs\",category:\"transformation\",inputs:[{start:0,name:\"s0\",type:\"tensor\"},{start:1,name:\"s1\",type:\"tensor\"}],attrs:[]}],Q5=class{constructor(){let e=[k4,I4,S4,T4,C4,N4,E4,R4,M4,$4,_4,P4,F4,O4,D4,z4,L4,B4,W4],t=[].concat(...e.map(a=>a.json));this.opMappers=t.reduce((a,n)=>(a[n.tfOpName]=n,a),{})}static get Instance(){return this._instance||(this._instance=new this)}transformGraph(e,t={}){let a=e.node,n=[],r=[],s=[],i=a.reduce((f,m)=>(f[m.name]=this.mapNode(m),m.op.startsWith(\"Placeholder\")?n.push(f[m.name]):m.op===\"Const\"?r.push(f[m.name]):(m.input==null||m.input.length===0)&&s.push(f[m.name]),f),{}),o=[],l=[],u={},p={};t!=null&&(u=this.mapSignatureEntries(t.inputs),p=this.mapSignatureEntries(t.outputs));let c=Object.keys(i);c.forEach(f=>{let m=i[f];m.inputNames.forEach((g,x)=>{let[A,,y]=mr(g),b=i[A];if(b.outputs!=null){let w=b.outputs.indexOf(y);if(w!==-1){let S=`${A}:${w}`;m.inputNames[x]=S}}m.inputs.push(b),b.children.push(m)})}),Object.keys(p).length===0?c.forEach(f=>{let m=i[f];m.children.length===0&&l.push(m)}):Object.keys(p).forEach(f=>{let[m]=mr(f),g=i[m];g!=null&&(g.signatureKey=p[f],l.push(g))}),Object.keys(u).length>0?Object.keys(u).forEach(f=>{let[m]=mr(f),g=i[m];g&&(g.signatureKey=u[f],o.push(g))}):o=n;let d={};e.library!=null&&e.library.function!=null&&(d=e.library.function.reduce((f,m)=>(f[m.signature.name]=this.mapFunction(m),f),{}));let h={nodes:i,inputs:o,outputs:l,weights:r,placeholders:n,signature:t,functions:d};return s.length>0&&(h.initNodes=s),h}mapSignatureEntries(e){return Object.keys(e||{}).reduce((t,a)=>(t[e[a].name]=a,t),{})}mapNode(e){let t=w4(e.op)||this.opMappers[e.op]||{};e.attr==null&&(e.attr={});let a={name:e.name,op:e.op,category:t.category,inputNames:(e.input||[]).map(n=>n.startsWith(\"^\")?n.slice(1):n),inputs:[],children:[],inputParams:{},attrParams:{},rawAttrs:e.attr,outputs:t.outputs};return t.inputs!=null&&(a.inputParams=t.inputs.reduce((n,r)=>(n[r.name]={type:r.type,inputIndexStart:r.start,inputIndexEnd:r.end},n),{})),t.attrs!=null&&(a.attrParams=t.attrs.reduce((n,r)=>{let s=r.type,i;switch(r.type){case\"string\":i=o1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=o1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"string[]\":i=f1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=f1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"number\":i=u1(e.attr,r.tfName,r.defaultValue||0),i===void 0&&!!r.tfDeprecatedName&&(i=u1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"number[]\":i=h1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=h1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"bool\":i=l1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=l1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"bool[]\":i=g1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=g1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"shape\":i=c1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=c1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"shape[]\":i=m1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=m1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"dtype\":i=d1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=d1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"dtype[]\":i=p1(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=p1(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"func\":i=ex(e.attr,r.tfName,r.defaultValue),i===void 0&&!!r.tfDeprecatedName&&(i=ex(e.attr,r.tfDeprecatedName,r.defaultValue));break;case\"tensor\":case\"tensors\":break;default:throw new Error(`Unsupported param type: ${r.type} for op: ${e.op}`)}return n[r.name]={value:i,type:s},n},{})),a}mapFunction(e){let t=e.nodeDef,a=[],n=[],r={};t!=null&&(r=t.reduce((u,p)=>(u[p.name]=this.mapNode(p),p.op===\"Const\"&&n.push(u[p.name]),u),{}));let s=[],i=[];e.signature.inputArg.forEach(u=>{let[p]=mr(u.name),c={name:p,op:\"Placeholder\",inputs:[],inputNames:[],category:\"graph\",inputParams:{},attrParams:{dtype:{value:n3(u.type),type:\"dtype\"}},children:[]};c.signatureKey=u.name,s.push(c),r[p]=c}),Object.keys(r).forEach(u=>{let p=r[u];p.inputNames.forEach((c,d)=>{let[h,,f]=mr(c),m=r[h];if(m.outputs!=null){let g=m.outputs.indexOf(f);if(g!==-1){let x=`${h}:${g}`;p.inputNames[d]=x}}p.inputs.push(m),m.children.push(p)})});let o=e.ret;e.signature.outputArg.forEach(u=>{let[p,c]=mr(o[u.name]),d=r[p];d!=null&&(d.defaultOutput=c,i.push(d))});let l=this.mapArgsToSignature(e);return{nodes:r,inputs:s,outputs:i,weights:n,placeholders:a,signature:l}}mapArgsToSignature(e){return{methodName:e.signature.name,inputs:e.signature.inputArg.reduce((t,a)=>(t[a.name]=this.mapArgToTensorInfo(a),t),{}),outputs:e.signature.outputArg.reduce((t,a)=>(t[a.name]=this.mapArgToTensorInfo(a,e.ret),t),{})}}mapArgToTensorInfo(e,t){let a=e.name;return t!=null&&(a=t[a]),{name:a,dtype:e.type}}};function BP(e){let t=W().global;if(typeof t.atob!=\"undefined\")return t.atob(e);if(typeof Buffer!=\"undefined\")return new Buffer(e,\"base64\").toString();throw new Error(\"Unable to decode base64 in this environment. Missing built-in atob() or Buffer()\")}function V4(e,t){let a=Array.isArray(e)?String.fromCharCode.apply(null,e):BP(e);return t?a:a.toLowerCase()}function o1(e,t,a,n=!1){let r=e[t];return r!=null?V4(r.s,n):a}function l1(e,t,a){let n=e[t];return n?n.b:a}function u1(e,t,a){let n=e[t]||{},r=n.i!=null?n.i:n.f!=null?n.f:a;return typeof r==\"number\"?r:parseInt(r,10)}function n3(e){switch(typeof e==\"string\"&&(e=wn[e]),e){case wn.DT_FLOAT:case wn.DT_HALF:return\"float32\";case wn.DT_INT32:case wn.DT_INT64:case wn.DT_INT8:case wn.DT_UINT8:return\"int32\";case wn.DT_BOOL:return\"bool\";case wn.DT_DOUBLE:return\"float32\";case wn.DT_STRING:return\"string\";default:return null}}function ex(e,t,a){let n=e[t];return n&&n.func?n.func.name:a}function d1(e,t,a){let n=e[t];return n&&n.type?n3(n.type):a}function p1(e,t,a){let n=e[t];return n&&n.list&&n.list.type?n.list.type.map(r=>n3(r)):a}function U4(e){if(!e.unknownRank)return e.dim!=null?e.dim.map(t=>typeof t.size==\"number\"?t.size:parseInt(t.size,10)):[]}function c1(e,t,a){let n=e[t];return n&&n.shape?U4(n.shape):a}function h1(e,t,a){let n=e[t];return n?((n.list.f&&n.list.f.length?n.list.f:n.list.i)||[]).map(r=>typeof r==\"number\"?r:parseInt(r,10)):a}function f1(e,t,a,n=!1){let r=e[t];return r&&r.list&&r.list.s?r.list.s.map(s=>V4(s,n)):a}function m1(e,t,a){let n=e[t];return n&&n.list&&n.list.shape?n.list.shape.map(r=>U4(r)):a}function g1(e,t,a){let n=e[t];return n&&n.list&&n.list.b?n.list.b:a}var WP=class{constructor(e,t,a){this.node=e,this.tensorMap=t,this.context=a,this.inputs=[],this.attrs={},this.inputs=e.inputNames.map(n=>this.getInput(n)),e.rawAttrs!=null&&(this.attrs=Object.keys(e.rawAttrs).reduce((n,r)=>(n[r]=this.getAttr(r),n),{}))}getInput(e){return ba(e,this.tensorMap,this.context)}getAttr(e,t){let a=this.node.rawAttrs[e];if(a.tensor!=null)return ba(e,this.tensorMap,this.context);if(a.i!=null||a.f!=null)return u1(this.node.rawAttrs,e,t);if(a.s!=null)return o1(this.node.rawAttrs,e,t);if(a.b!=null)return l1(this.node.rawAttrs,e,t);if(a.shape!=null)return c1(this.node.rawAttrs,e,t);if(a.type!=null)return d1(this.node.rawAttrs,e,t);if(a.list!=null){if(a.list.i!=null||a.list.f!=null)return h1(this.node.rawAttrs,e,t);if(a.list.s!=null)return f1(this.node.rawAttrs,e,t);if(a.list.shape!=null)return m1(this.node.rawAttrs,e,t);if(a.list.b!=null)return g1(this.node.rawAttrs,e,t);if(a.list.type!=null)return p1(this.node.rawAttrs,e,t)}return t}},Zt={};Xe(Zt,{OP_SCOPE_SUFFIX:()=>e2,abs:()=>qa,acos:()=>oy,acosh:()=>ly,add:()=>be,addN:()=>ch,all:()=>uy,any:()=>dy,argMax:()=>ar,argMin:()=>py,asin:()=>cy,asinh:()=>hy,atan:()=>fy,atan2:()=>my,atanh:()=>gy,avgPool:()=>b2,avgPool3d:()=>by,basicLSTMCell:()=>vy,batchNorm:()=>Qd,batchNorm2d:()=>wy,batchNorm3d:()=>ky,batchNorm4d:()=>Iy,batchToSpaceND:()=>v2,bincount:()=>w2,booleanMaskAsync:()=>a4,broadcastArgs:()=>Sy,broadcastTo:()=>sl,buffer:()=>Me,cast:()=>He,ceil:()=>Ty,clipByValue:()=>Cy,clone:()=>wa,complex:()=>br,concat:()=>at,concat1d:()=>Ny,concat2d:()=>ru,concat3d:()=>Ey,concat4d:()=>Ry,conv1d:()=>My,conv2d:()=>ep,conv2dTranspose:()=>_y,conv3d:()=>Py,conv3dTranspose:()=>Fy,cos:()=>Oy,cosh:()=>Dy,cosineWindow:()=>vh,cumprod:()=>zy,cumsum:()=>Ly,denseBincount:()=>By,depthToSpace:()=>Wy,depthwiseConv2d:()=>hh,diag:()=>Vy,dilation2d:()=>Uy,div:()=>me,divNoNan:()=>Gy,dot:()=>Hy,dropout:()=>o4,einsum:()=>jy,elu:()=>I2,enclosingPowerOfTwo:()=>J2,equal:()=>k2,erf:()=>qy,euclideanNorm:()=>Zy,exp:()=>Zr,expandDims:()=>Gt,expm1:()=>Yy,eye:()=>T2,fft:()=>yh,fill:()=>nr,floor:()=>C2,floorDiv:()=>Yd,fused:()=>Q2,gather:()=>N2,gatherND:()=>i4,greater:()=>np,greaterEqual:()=>E2,ifft:()=>hd,imag:()=>Zd,image:()=>ge,inTopKAsync:()=>l4,irfft:()=>X2,isFinite:()=>Jy,isInf:()=>Qy,isNaN:()=>eb,leakyRelu:()=>R2,less:()=>tb,lessEqual:()=>fh,linalg:()=>g4,linspace:()=>ab,localResponseNormalization:()=>nb,log:()=>cl,log1p:()=>M2,logSigmoid:()=>sb,logSoftmax:()=>ib,logSumExp:()=>_2,logicalAnd:()=>pd,logicalNot:()=>P2,logicalOr:()=>F2,logicalXor:()=>ob,losses:()=>x4,lowerBound:()=>lb,matMul:()=>st,max:()=>pa,maxPool:()=>O2,maxPool3d:()=>ub,maxPoolWithArgmax:()=>db,maximum:()=>D2,mean:()=>cd,meshgrid:()=>pb,min:()=>Kr,minimum:()=>z2,mirrorPad:()=>cb,mod:()=>su,moments:()=>hb,movingAverage:()=>n4,mul:()=>ae,multiRNNCell:()=>fb,multinomial:()=>mb,neg:()=>Xn,norm:()=>ap,notEqual:()=>L2,oneHot:()=>Nc,ones:()=>Wr,onesLike:()=>gb,op:()=>D,outerProduct:()=>xb,pad:()=>rr,pad1d:()=>Ab,pad2d:()=>yb,pad3d:()=>bb,pad4d:()=>vb,pool:()=>wb,pow:()=>pl,prelu:()=>W2,print:()=>r2,prod:()=>kb,raggedGather:()=>Ib,raggedRange:()=>Sb,raggedTensorToTensor:()=>Tb,rand:()=>Cb,randomGamma:()=>Nb,randomNormal:()=>G2,randomStandardNormal:()=>Eb,randomUniform:()=>H2,range:()=>hl,real:()=>dl,reciprocal:()=>Rb,relu:()=>rp,relu6:()=>j2,reshape:()=>J,reverse:()=>Yr,reverse1d:()=>Mb,reverse2d:()=>$b,reverse3d:()=>_b,reverse4d:()=>Pb,rfft:()=>bh,round:()=>q2,rsqrt:()=>Fb,scalar:()=>Fe,scatterND:()=>r4,searchSorted:()=>gh,selu:()=>Ob,separableConv2d:()=>Db,setdiff1dAsync:()=>zb,sigmoid:()=>Da,sign:()=>Lb,signal:()=>m4,sin:()=>Bb,sinh:()=>Wb,slice:()=>Pe,slice1d:()=>Vb,slice2d:()=>Ub,slice3d:()=>sp,slice4d:()=>xh,softmax:()=>Ah,softplus:()=>$2,spaceToBatchND:()=>B2,sparse:()=>A4,sparseToDense:()=>s4,spectral:()=>f4,split:()=>ka,sqrt:()=>Jn,square:()=>In,squaredDifference:()=>K2,squeeze:()=>_e,stack:()=>sa,step:()=>Z2,stridedSlice:()=>Gb,string:()=>y4,sub:()=>fe,sum:()=>tt,tan:()=>Hb,tanh:()=>Rc,tensor:()=>Be,tensor1d:()=>Ht,tensor2d:()=>Kn,tensor3d:()=>p2,tensor4d:()=>jb,tensor5d:()=>qb,tensor6d:()=>Xb,tile:()=>Gr,topk:()=>Kb,transpose:()=>Ws,truncatedNormal:()=>Zb,unique:()=>Yb,unsortedSegmentSum:()=>Jb,unstack:()=>Ta,upperBound:()=>Qb,variable:()=>e4,where:()=>Vs,whereAsync:()=>Y2,zeros:()=>fn,zerosLike:()=>Ka});var VP=(e,t,a,n=Zt)=>{switch(e.op){case\"BiasAdd\":case\"AddV2\":case\"Add\":return[n.add(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"AddN\":return[n.addN(k(\"tensors\",e,t,a))];case\"FloorMod\":case\"Mod\":return[n.mod(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"Mul\":return[n.mul(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"RealDiv\":case\"Div\":return[n.div(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"DivNoNan\":return[n.divNoNan(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"FloorDiv\":return[n.floorDiv(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"Sub\":return[n.sub(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"Minimum\":return[n.minimum(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"Maximum\":return[n.maximum(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"Pow\":return[n.pow(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"SquaredDifference\":return[n.squaredDifference(k(\"a\",e,t,a),k(\"b\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}},UP=(e,t,a,n=Zt)=>{switch(e.op){case\"Abs\":case\"ComplexAbs\":return[n.abs(k(\"x\",e,t,a))];case\"Acos\":return[n.acos(k(\"x\",e,t,a))];case\"Acosh\":return[n.acosh(k(\"x\",e,t,a))];case\"Asin\":return[n.asin(k(\"x\",e,t,a))];case\"Asinh\":return[n.asinh(k(\"x\",e,t,a))];case\"Atan\":return[n.atan(k(\"x\",e,t,a))];case\"Atan2\":return[n.atan2(k(\"x\",e,t,a),k(\"y\",e,t,a))];case\"Atanh\":return[n.atanh(k(\"x\",e,t,a))];case\"Ceil\":return[n.ceil(k(\"x\",e,t,a))];case\"Complex\":return[n.complex(k(\"real\",e,t,a),k(\"imag\",e,t,a))];case\"Cos\":return[n.cos(k(\"x\",e,t,a))];case\"Cosh\":return[n.cosh(k(\"x\",e,t,a))];case\"Elu\":return[n.elu(k(\"x\",e,t,a))];case\"Erf\":return[n.erf(k(\"x\",e,t,a))];case\"Exp\":return[n.exp(k(\"x\",e,t,a))];case\"Expm1\":return[n.expm1(k(\"x\",e,t,a))];case\"Floor\":return[n.floor(k(\"x\",e,t,a))];case\"Log\":return[n.log(k(\"x\",e,t,a))];case\"Log1p\":return[n.log1p(k(\"x\",e,t,a))];case\"Imag\":return[n.imag(k(\"x\",e,t,a))];case\"Neg\":return[n.neg(k(\"x\",e,t,a))];case\"Reciprocal\":return[n.reciprocal(k(\"x\",e,t,a))];case\"Real\":return[n.real(k(\"x\",e,t,a))];case\"Relu\":return[n.relu(k(\"x\",e,t,a))];case\"Round\":return[n.round(k(\"x\",e,t,a))];case\"Selu\":return[n.selu(k(\"x\",e,t,a))];case\"Sigmoid\":return[n.sigmoid(k(\"x\",e,t,a))];case\"Sin\":return[n.sin(k(\"x\",e,t,a))];case\"Sign\":return[n.sign(k(\"x\",e,t,a))];case\"Sinh\":return[n.sinh(k(\"x\",e,t,a))];case\"Softplus\":return[n.softplus(k(\"x\",e,t,a))];case\"Sqrt\":return[n.sqrt(k(\"x\",e,t,a))];case\"Square\":return[n.square(k(\"x\",e,t,a))];case\"Tanh\":return[n.tanh(k(\"x\",e,t,a))];case\"Tan\":return[n.tan(k(\"x\",e,t,a))];case\"ClipByValue\":return[n.clipByValue(k(\"x\",e,t,a),k(\"clipValueMin\",e,t,a),k(\"clipValueMax\",e,t,a))];case\"Relu6\":return[n.relu6(k(\"x\",e,t,a))];case\"Rsqrt\":return[n.rsqrt(ba(e.inputNames[0],t,a))];case\"Prod\":return[n.prod(k(\"x\",e,t,a),k(\"axes\",e,t,a))];case\"LeakyRelu\":return[n.leakyRelu(k(\"x\",e,t,a),k(\"alpha\",e,t,a))];case\"Prelu\":return[n.prelu(k(\"x\",e,t,a),k(\"alpha\",e,t,a))];case\"IsNan\":return[n.isNaN(ba(e.inputNames[0],t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}};function kn(e,t,a=\"\"){if(!(typeof e==\"number\"||typeof t==\"number\")){v.assert(e.length===t.length,()=>a+` Shapes ${e} and ${t} must match`);for(let n=0;n<e.length;n++){let r=e[n],s=t[n];v.assert(r<0||s<0||r===s,()=>a+` Shapes ${e} and ${t} must match`)}}}function tx(e){return!(typeof e==\"number\"||e.some(t=>t<0))}function Vu(e,t,a){let n=x1(e,a),r=!tx(n);if(r&&t.length===0)throw new Error(`Tried to calculate elements of an empty list with non-fully-defined elementShape: ${n}`);if(r&&t.forEach(s=>{n=x1(s.shape,n)}),!tx(n))throw new Error(`Non-fully-defined elementShape: ${n}`);return n}function x1(e,t){if(typeof e==\"number\")return t;if(typeof t==\"number\")return e;if(e.length!==t.length)throw new Error(`Incompatible ranks during merge: ${e} vs. ${t}`);let a=[];for(let n=0;n<e.length;++n){let r=e[n],s=t[n];if(r>=0&&s>=0&&r!==s)throw new Error(`Incompatible shape during merge: ${e} vs. ${t}`);a[n]=r>=0?r:s}return a}var GP=class{constructor(e,t,a,n,r,s,i){this.name=e,this.dtype=t,this.maxSize=a,this.elementShape=n,this.identicalElementShapes=r,this.dynamicSize=s,this.clearAfterRead=i,this.tensors=[],this.closed_=!1,this.idTensor=Fe(0),On(this.idTensor)}get id(){return this.idTensor.id}get closed(){return this.closed_}clearAndClose(e){this.tensors.forEach(t=>{(e==null||!e.has(t.tensor.id))&&t.tensor.dispose()}),this.tensors=[],this.closed_=!0,this.idTensor.dispose()}size(){return this.tensors.length}read(e){if(this.closed_)throw new Error(`TensorArray ${this.name} has already been closed.`);if(e<0||e>=this.size())throw new Error(`Tried to read from index ${e}, but array size is: ${this.size()}`);let t=this.tensors[e];if(t.cleared)throw new Error(`TensorArray ${this.name}: Could not read index ${e} twice because it was cleared after a previous read (perhaps try setting clear_after_read = false?).`);return this.clearAfterRead&&(t.cleared=!0),t.read=!0,t.tensor}readMany(e){return e.map(t=>this.read(t))}write(e,t){if(this.closed_)throw new Error(`TensorArray ${this.name} has already been closed.`);if(e<0||!this.dynamicSize&&e>=this.maxSize)throw new Error(`Tried to write to index ${e}, but array is not resizeable and size is: ${this.maxSize}`);let a=this.tensors[e]||{};if(t.dtype!==this.dtype)throw new Error(`TensorArray ${this.name}: Could not write to TensorArray index ${e},\n          because the value dtype is ${t.dtype}, but TensorArray dtype is ${this.dtype}.`);if(this.size()===0&&(this.elementShape==null||this.elementShape.length===0)&&(this.elementShape=t.shape),kn(this.elementShape,t.shape,`TensorArray ${this.name}: Could not write to TensorArray index ${e}.`),a.read)throw new Error(`TensorArray ${this.name}: Could not write to TensorArray index ${e}, because it has already been read.`);if(a.written)throw new Error(`TensorArray ${this.name}: Could not write to TensorArray index ${e}, because it has already been written.`);a.tensor=t,On(t),a.written=!0,this.tensors[e]=a}writeMany(e,t){if(e.length!==t.length)throw new Error(`TensorArray ${this.name}: could not write multiple tensors,because the index size: ${e.length} is not the same as tensors size: ${t.length}.`);e.forEach((a,n)=>this.write(a,t[n]))}gather(e,t){if(!!t&&t!==this.dtype)throw new Error(`TensorArray dtype is ${this.dtype} but gather requested dtype ${t}`);if(e)e=e.slice(0,this.size());else{e=[];for(let n=0;n<this.size();n++)e.push(n)}if(e.length===0)return Be([],[0].concat(this.elementShape));let a=this.readMany(e);return kn(this.elementShape,a[0].shape,\"TensorArray shape mismatch: \"),sa(a,0)}concat(e){if(!!e&&e!==this.dtype)throw new Error(`TensorArray dtype is ${this.dtype} but concat requested dtype ${e}`);if(this.size()===0)return Be([],[0].concat(this.elementShape));let t=[];for(let n=0;n<this.size();n++)t.push(n);let a=this.readMany(t);return kn(this.elementShape,a[0].shape,`TensorArray shape mismatch: tensor array shape (${this.elementShape}) vs first tensor shape (${a[0].shape})`),at(a,0)}scatter(e,t){if(t.dtype!==this.dtype)throw new Error(`TensorArray dtype is ${this.dtype} but tensor has dtype ${t.dtype}`);if(e.length!==t.shape[0])throw new Error(`Expected len(indices) == tensor.shape[0], but saw: ${e.length} vs. ${t.shape[0]}`);let a=Math.max(...e);if(!this.dynamicSize&&a>=this.maxSize)throw new Error(`Max index must be < array size (${a}  vs. ${this.maxSize})`);this.writeMany(e,Ta(t,0))}split(e,t){if(t.dtype!==this.dtype)throw new Error(`TensorArray dtype is ${this.dtype} but tensor has dtype ${t.dtype}`);let a=0,n=e.map(o=>(a+=o,a));if(a!==t.shape[0])throw new Error(`Expected sum of lengths to be equal to\n          tensor.shape[0], but sum of lengths is\n        ${a}, and tensor's shape is: ${t.shape}`);if(!this.dynamicSize&&e.length!==this.maxSize)throw new Error(`TensorArray's size is not equal to the size of lengths (${this.maxSize} vs. ${e.length}), and the TensorArray is not marked as dynamically resizeable`);let r=a===0?0:t.size/a,s=[];$e(()=>{t=J(t,[1,a,r]);for(let o=0;o<e.length;++o){let l=[0,o===0?0:n[o-1],0],u=[1,e[o],r];s[o]=J(Pe(t,l,u),this.elementShape)}return s});let i=[];for(let o=0;o<e.length;o++)i[o]=o;this.writeMany(i,s)}},fl=class{constructor(e,t,a,n=-1){this.tensors=e,this.elementShape=t,this.elementDtype=a,e!=null&&e.forEach(r=>{if(a!==r.dtype)throw new Error(`Invalid data types; op elements ${a}, but list elements ${r.dtype}`);kn(t,r.shape,\"TensorList shape mismatch: \"),On(r)}),this.idTensor=Fe(0),this.maxNumElements=n,On(this.idTensor)}get id(){return this.idTensor.id}copy(){return new fl([...this.tensors],this.elementShape,this.elementDtype)}clearAndClose(e){this.tensors.forEach(t=>{(e==null||!e.has(t.id))&&t.dispose()}),this.tensors.length=0,this.idTensor.dispose()}size(){return this.tensors.length}stack(e,t,a=-1){if(t!==this.elementDtype)throw new Error(`Invalid data types; op elements ${t}, but list elements ${this.elementDtype}`);if(a!==-1&&this.tensors.length!==a)throw new Error(`Operation expected a list with ${a} elements but got a list with ${this.tensors.length} elements.`);kn(e,this.elementShape,\"TensorList shape mismatch: \");let n=Vu(this.elementShape,this.tensors,e);return $e(()=>{let r=this.tensors.map(s=>J(s,n));return sa(r,0)})}popBack(e,t){if(t!==this.elementDtype)throw new Error(`Invalid data types; op elements ${t}, but list elements ${this.elementDtype}`);if(this.size()===0)throw new Error(\"Trying to pop from an empty list.\");let a=Vu(this.elementShape,this.tensors,e),n=this.tensors.pop();return n.kept=!1,kn(n.shape,e,\"TensorList shape mismatch: \"),J(n,a)}pushBack(e){if(e.dtype!==this.elementDtype)throw new Error(`Invalid data types; op elements ${e.dtype}, but list elements ${this.elementDtype}`);if(kn(e.shape,this.elementShape,\"TensorList shape mismatch: \"),this.maxNumElements===this.size())throw new Error(\"Trying to push element into a full list.\");On(e),this.tensors.push(e)}resize(e){if(e<0)throw new Error(`TensorListResize expects size to be non-negative. Got: ${e}`);if(this.maxNumElements!==-1&&e>this.maxNumElements)throw new Error(`TensorListResize input size ${e} is greater maxNumElement ${this.maxNumElements}.`);let t=new fl([],this.elementShape,this.elementDtype,this.maxNumElements);t.tensors.length=e;for(let a=0;a<Math.min(this.tensors.length,e);++a)t.tensors[a]=this.tensors[a];return t}getItem(e,t,a){if(a!==this.elementDtype)throw new Error(`Invalid data types; op elements ${a}, but list elements ${this.elementDtype}`);if(e<0||e>this.tensors.length)throw new Error(`Trying to access element ${e} in a list with ${this.tensors.length} elements.`);if(this.tensors[e]==null)throw new Error(`element at index ${e} is null.`);kn(this.tensors[e].shape,t,\"TensorList shape mismatch: \");let n=Vu(this.elementShape,this.tensors,t);return J(this.tensors[e],n)}setItem(e,t){if(t.dtype!==this.elementDtype)throw new Error(`Invalid data types; op elements ${t.dtype}, but list elements ${this.elementDtype}`);if(e<0||this.maxNumElements!==-1&&e>=this.maxNumElements)throw new Error(`Trying to set element ${e} in a list with max ${this.maxNumElements} elements.`);kn(this.elementShape,t.shape,\"TensorList shape mismatch: \"),On(t),this.tensors[e]!=null&&(this.tensors[e].kept=!1),this.tensors[e]=t}gather(e,t,a){if(t!==this.elementDtype)throw new Error(`Invalid data types; op elements ${t}, but list elements ${this.elementDtype}`);kn(this.elementShape,a,\"TensorList shape mismatch: \"),e=e.slice(0,this.size());let n=Vu(this.elementShape,this.tensors,a);return e.length===0?Be([],[0].concat(n)):$e(()=>{let r=e.map(s=>J(this.tensors[s],n));return sa(r,0)})}concat(e,t){if(!!e&&e!==this.elementDtype)throw new Error(`TensorList dtype is ${this.elementDtype} but concat requested dtype ${e}`);kn(this.elementShape,t,\"TensorList shape mismatch: \");let a=Vu(this.elementShape,this.tensors,t);return this.size()===0?Be([],[0].concat(a)):$e(()=>{let n=this.tensors.map(r=>J(r,a));return at(n,0)})}};function HP(e,t,a){let n=e.dtype;if(e.shape.length<1)throw new Error(`Tensor must be at least a vector, but saw shape: ${e.shape}`);if(e.dtype!==a)throw new Error(`Invalid data types; op elements ${e.dtype}, but list elements ${a}`);let r=e.shape.slice(1);kn(r,t,\"TensorList shape mismatch: \");let s=Ta(e);return new fl(s,t,n)}function jP(e,t,a,n){return new fl([],e,t,n)}function qP(e,t,a,n){if(t.length!==e.shape[0])throw new Error(`Expected len(indices) == tensor.shape[0], but saw: ${t.length} vs. ${e.shape[0]}`);let r=Math.max(...t);if(n!=null&&n!==-1&&r>=n)throw new Error(`Max index must be < array size (${r}  vs. ${n})`);let s=new fl([],a,e.dtype,n),i=Ta(e,0);return t.forEach((o,l)=>{s.setItem(o,i[l])}),s}function XP(e,t,a){let n=0,r=t.map(p=>(n+=p,n));if(n!==e.shape[0])throw new Error(`Expected sum of lengths to be equal to\n          tensor.shape[0], but sum of lengths is\n        ${n}, and tensor's shape is: ${e.shape}`);let s=e.shape.slice(1),i=x1(s,a),o=n===0?0:e.size/n,l=$e(()=>{let p=[];e=J(e,[1,n,o]);for(let c=0;c<t.length;++c){let d=[0,c===0?0:r[c-1],0],h=[1,t[c],o];p[c]=J(Pe(e,d,h),i)}return e.dispose(),p}),u=new fl([],a,e.dtype,t.length);for(let p=0;p<l.length;p++)u.setItem(p,l[p]);return u}var KP=async(e,t,a)=>{switch(e.op){case\"If\":case\"StatelessIf\":{let n=k(\"thenBranch\",e,t,a),r=k(\"elseBranch\",e,t,a),s=k(\"cond\",e,t,a),i=k(\"args\",e,t,a);return(await s.data())[0]?a.functionMap[n].executeFunctionAsync(i,a.tensorArrayMap,a.tensorListMap):a.functionMap[r].executeFunctionAsync(i,a.tensorArrayMap,a.tensorListMap)}case\"While\":case\"StatelessWhile\":{let n=k(\"body\",e,t,a),r=k(\"cond\",e,t,a),s=k(\"args\",e,t,a),i=await a.functionMap[r].executeFunctionAsync(s,a.tensorArrayMap,a.tensorListMap),o=s.map(p=>p.id),l=await i[0].data();i.forEach(p=>{!p.kept&&o.indexOf(p.id)===-1&&p.dispose()});let u=s;for(;l[0];){let p=u;u=await a.functionMap[n].executeFunctionAsync(u,a.tensorArrayMap,a.tensorListMap);let c=u.map(h=>h.id);p.forEach(h=>{!h.kept&&o.indexOf(h.id)===-1&&c.indexOf(h.id)===-1&&h.dispose()});let d=await a.functionMap[r].executeFunctionAsync(u,a.tensorArrayMap,a.tensorListMap);l=await d[0].data(),d.forEach(h=>{!h.kept&&o.indexOf(h.id)===-1&&c.indexOf(h.id)===-1&&h.dispose()})}return u}case\"LoopCond\":{let n=k(\"pred\",e,t,a);return[gr(n)]}case\"Switch\":{let n=k(\"pred\",e,t,a),r=k(\"data\",e,t,a);return r.kept||(r=gr(r)),(await n.data())[0]?[void 0,r]:[r,void 0]}case\"Merge\":{let n=e.inputNames.find(r=>ba(r,t,a)!==void 0);if(n){let r=ba(n,t,a);return[gr(r)]}return}case\"Enter\":{let n=k(\"frameName\",e,t,a),r=k(\"tensor\",e,t,a);return a.enterFrame(n),[gr(r)]}case\"Exit\":{let n=k(\"tensor\",e,t,a);return a.exitFrame(),[gr(n)]}case\"NextIteration\":{let n=k(\"tensor\",e,t,a);return a.nextIteration(),[gr(n)]}case\"TensorArrayV3\":{let n=k(\"size\",e,t,a),r=k(\"dtype\",e,t,a),s=k(\"elementShape\",e,t,a),i=k(\"dynamicSize\",e,t,a),o=k(\"clearAfterRead\",e,t,a),l=k(\"identicalElementShapes\",e,t,a),u=k(\"name\",e,t,a),p=new GP(u,r,n,s,l,i,o);return a.addTensorArray(p),[p.idTensor,Fe(1)]}case\"TensorArrayWriteV3\":{let n=k(\"tensorArrayId\",e,t,a),r=k(\"index\",e,t,a),s=k(\"tensor\",e,t,a),i=a.getTensorArray(n.id);return i.write(r,s),[i.idTensor]}case\"TensorArrayReadV3\":{let n=k(\"tensorArrayId\",e,t,a),r=k(\"index\",e,t,a);return[a.getTensorArray(n.id).read(r)]}case\"TensorArrayGatherV3\":{let n=k(\"tensorArrayId\",e,t,a),r=k(\"indices\",e,t,a),s=k(\"dtype\",e,t,a);return[a.getTensorArray(n.id).gather(r,s)]}case\"TensorArrayScatterV3\":{let n=k(\"tensorArrayId\",e,t,a),r=k(\"indices\",e,t,a),s=k(\"tensor\",e,t,a),i=a.getTensorArray(n.id);return i.scatter(r,s),[i.idTensor]}case\"TensorArrayConcatV3\":{let n=k(\"tensorArrayId\",e,t,a),r=a.getTensorArray(n.id),s=k(\"dtype\",e,t,a);return[r.concat(s)]}case\"TensorArraySplitV3\":{let n=k(\"tensorArrayId\",e,t,a),r=k(\"tensor\",e,t,a),s=k(\"lengths\",e,t,a),i=a.getTensorArray(n.id);return i.split(s,r),[i.idTensor]}case\"TensorArraySizeV3\":{let n=k(\"tensorArrayId\",e,t,a),r=a.getTensorArray(n.id);return[Fe(r.size(),\"int32\")]}case\"TensorArrayCloseV3\":{let n=k(\"tensorArrayId\",e,t,a),r=a.getTensorArray(n.id);return r.clearAndClose(),[r.idTensor]}case\"TensorListSetItem\":{let n=k(\"tensorListId\",e,t,a),r=k(\"index\",e,t,a),s=k(\"tensor\",e,t,a),i=a.getTensorList(n.id);return i.setItem(r,s),[i.idTensor]}case\"TensorListGetItem\":{let n=k(\"tensorListId\",e,t,a),r=k(\"index\",e,t,a),s=k(\"elementShape\",e,t,a),i=k(\"elementDType\",e,t,a);return[a.getTensorList(n.id).getItem(r,s,i)]}case\"TensorListScatterV2\":case\"TensorListScatter\":{let n=k(\"indices\",e,t,a),r=k(\"tensor\",e,t,a),s=k(\"elementShape\",e,t,a),i=k(\"numElements\",e,t,a),o=qP(r,n,s,i);return a.addTensorList(o),[o.idTensor]}case\"TensorListReserve\":case\"EmptyTensorList\":{let n=k(\"elementShape\",e,t,a),r=k(\"elementDType\",e,t,a),s;e.op===\"TensorListReserve\"?s=\"numElements\":s=\"maxNumElements\";let i=k(s,e,t,a),o=e.op===\"TensorListReserve\"?-1:i,l=jP(n,r,i,o);return a.addTensorList(l),[l.idTensor]}case\"TensorListGather\":{let n=k(\"tensorListId\",e,t,a),r=k(\"indices\",e,t,a),s=k(\"elementShape\",e,t,a),i=k(\"elementDType\",e,t,a);return[a.getTensorList(n.id).gather(r,i,s)]}case\"TensorListStack\":{let n=k(\"tensorListId\",e,t,a),r=k(\"elementShape\",e,t,a),s=k(\"elementDType\",e,t,a),i=k(\"numElements\",e,t,a);return[a.getTensorList(n.id).stack(r,s,i)]}case\"TensorListFromTensor\":{let n=k(\"tensor\",e,t,a),r=k(\"elementShape\",e,t,a),s=k(\"elementDType\",e,t,a),i=HP(n,r,s);return a.addTensorList(i),[i.idTensor]}case\"TensorListConcat\":case\"TensorListConcatV2\":{let n=k(\"tensorListId\",e,t,a),r=a.getTensorList(n.id),s=k(\"dtype\",e,t,a),i=k(\"elementShape\",e,t,a);return[r.concat(s,i)]}case\"TensorListPushBack\":{let n=k(\"tensorListId\",e,t,a),r=k(\"tensor\",e,t,a),s=a.getTensorList(n.id);return s.pushBack(r),[s.idTensor]}case\"TensorListPopBack\":{let n=k(\"tensorListId\",e,t,a),r=k(\"elementShape\",e,t,a),s=k(\"elementDType\",e,t,a);return[a.getTensorList(n.id).popBack(r,s)]}case\"TensorListSplit\":{let n=k(\"tensor\",e,t,a),r=k(\"elementShape\",e,t,a),s=k(\"lengths\",e,t,a),i=XP(n,s,r);return a.addTensorList(i),[i.idTensor]}case\"TensorListLength\":{let n=k(\"tensorListId\",e,t,a),r=a.getTensorList(n.id);return[Fe(r.size(),\"int32\")]}case\"TensorListResize\":{let n=k(\"tensorListId\",e,t,a),r=k(\"size\",e,t,a),s=a.getTensorList(n.id).resize(r);return a.addTensorList(s),[s.idTensor]}default:throw TypeError(`Node type ${e.op} is not implemented`)}};function ax(e,t,a){let[n,r]=k(\"fusedOps\",e,t,a),s=n===\"biasadd\",i=!s,o=r===\"prelu\",l=n===\"fusedbatchnorm\",u=k(\"numArgs\",e,t,a);if(s){if(o&&u!==2)throw new Error(\"FusedConv2d and DepthwiseConv2d with BiasAdd and Prelu must have two extra arguments: bias and alpha.\");if(!o&&s&&u!==1)throw new Error(\"FusedConv2d and DepthwiseConv2d with BiasAdd must have one extra argument: bias.\")}if(l)throw new Error(\"FusedConv2d and DepthwiseConv2d with FusedBatchNorm is not supported\");let p=k(\"strides\",e,t,a),c=mc(e,t,a),d=k(\"dataFormat\",e,t,a).toUpperCase(),h=k(\"dilations\",e,t,a),[f,m]=k(\"args\",e,t,a);i&&(m=f,f=void 0);let g=k(\"leakyreluAlpha\",e,t,a);return{stride:p,pad:c,dataFormat:d,dilations:h,biasArg:f,preluArg:m,activationFunc:r,leakyreluAlpha:g}}var ZP=(e,t,a,n=Zt)=>{switch(e.op){case\"Conv1D\":{let r=k(\"stride\",e,t,a),s=k(\"pad\",e,t,a),i=k(\"dataFormat\",e,t,a).toUpperCase(),o=k(\"dilation\",e,t,a);return[n.conv1d(k(\"x\",e,t,a),k(\"filter\",e,t,a),r,s,i,o)]}case\"Conv2D\":{let r=k(\"strides\",e,t,a),s=mc(e,t,a),i=k(\"dataFormat\",e,t,a).toUpperCase(),o=k(\"dilations\",e,t,a);return[n.conv2d(k(\"x\",e,t,a),k(\"filter\",e,t,a),[r[1],r[2]],s,i,[o[1],o[2]])]}case\"_FusedConv2D\":{let{stride:r,pad:s,dataFormat:i,dilations:o,biasArg:l,preluArg:u,activationFunc:p,leakyreluAlpha:c}=ax(e,t,a);return[n.fused.conv2d({x:k(\"x\",e,t,a),filter:k(\"filter\",e,t,a),strides:[r[1],r[2]],pad:s,dataFormat:i,dilations:[o[1],o[2]],bias:l,activation:p,preluActivationWeights:u,leakyreluAlpha:c})]}case\"FusedDepthwiseConv2dNative\":{let{stride:r,pad:s,dataFormat:i,dilations:o,biasArg:l,preluArg:u,activationFunc:p,leakyreluAlpha:c}=ax(e,t,a);return[n.fused.depthwiseConv2d({x:k(\"x\",e,t,a),filter:k(\"filter\",e,t,a),strides:[r[1],r[2]],pad:s,dataFormat:i,dilations:[o[1],o[2]],bias:l,activation:p,preluActivationWeights:u,leakyreluAlpha:c})]}case\"Conv2DBackpropInput\":case\"Conv2dTranspose\":{let r=k(\"outputShape\",e,t,a),s=k(\"strides\",e,t,a),i=mc(e,t,a);return[n.conv2dTranspose(k(\"x\",e,t,a),k(\"filter\",e,t,a),r,[s[1],s[2]],i)]}case\"DepthwiseConv2dNative\":case\"DepthwiseConv2d\":{let r=k(\"strides\",e,t,a),s=mc(e,t,a),i=k(\"dilations\",e,t,a),o=k(\"dataFormat\",e,t,a).toUpperCase();return[n.depthwiseConv2d(k(\"input\",e,t,a),k(\"filter\",e,t,a),[r[1],r[2]],s,o,[i[1],i[2]])]}case\"Conv3D\":{let r=k(\"strides\",e,t,a),s=k(\"pad\",e,t,a),i=k(\"dataFormat\",e,t,a).toUpperCase(),o=k(\"dilations\",e,t,a);return[n.conv3d(k(\"x\",e,t,a),k(\"filter\",e,t,a),[r[1],r[2],r[3]],s,i,[o[1],o[2],o[3]])]}case\"AvgPool\":{let r=k(\"strides\",e,t,a),s=k(\"pad\",e,t,a),i=k(\"kernelSize\",e,t,a);return[n.avgPool(k(\"x\",e,t,a),[i[1],i[2]],[r[1],r[2]],s)]}case\"MaxPool\":{let r=k(\"strides\",e,t,a),s=k(\"pad\",e,t,a),i=k(\"kernelSize\",e,t,a);return[n.maxPool(k(\"x\",e,t,a),[i[1],i[2]],[r[1],r[2]],s)]}case\"MaxPoolWithArgmax\":{let r=k(\"strides\",e,t,a),s=k(\"pad\",e,t,a),i=k(\"kernelSize\",e,t,a),o=k(\"includeBatchInIndex\",e,t,a),{result:l,indexes:u}=n.maxPoolWithArgmax(k(\"x\",e,t,a),[i[1],i[2]],[r[1],r[2]],s,o);return[l,u]}case\"AvgPool3D\":{let r=k(\"strides\",e,t,a),s=k(\"pad\",e,t,a),i=k(\"kernelSize\",e,t,a);return[n.avgPool3d(k(\"x\",e,t,a),[i[1],i[2],i[3]],[r[1],r[2],r[3]],s)]}case\"MaxPool3D\":{let r=k(\"strides\",e,t,a),s=k(\"pad\",e,t,a),i=k(\"kernelSize\",e,t,a);return[n.maxPool3d(k(\"x\",e,t,a),[i[1],i[2],i[3]],[r[1],r[2],r[3]],s)]}case\"Dilation2D\":{let r=k(\"strides\",e,t,a),s=k(\"pad\",e,t,a),i=k(\"dilations\",e,t,a),o=r[1],l=r[2],u=i[1],p=i[2];return[n.dilation2d(k(\"x\",e,t,a),k(\"filter\",e,t,a),[o,l],s,[u,p],\"NHWC\")]}default:throw TypeError(`Node type ${e.op} is not implemented`)}},YP=(e,t,a,n=Zt)=>{switch(e.op){case\"Fill\":{let r=k(\"shape\",e,t,a),s=k(\"dtype\",e,t,a),i=k(\"value\",e,t,a);return[n.fill(r,i,s)]}case\"LinSpace\":{let r=k(\"start\",e,t,a),s=k(\"stop\",e,t,a),i=k(\"num\",e,t,a);return[n.linspace(r,s,i)]}case\"Multinomial\":{let r=k(\"logits\",e,t,a),s=k(\"numSamples\",e,t,a),i=k(\"seed\",e,t,a);return[n.multinomial(r,s,i)]}case\"OneHot\":{let r=k(\"indices\",e,t,a),s=k(\"depth\",e,t,a),i=k(\"onValue\",e,t,a),o=k(\"offValue\",e,t,a),l=k(\"dtype\",e,t,a);return[n.oneHot(r,s,i,o,l)]}case\"Ones\":return[n.ones(k(\"shape\",e,t,a),k(\"dtype\",e,t,a))];case\"OnesLike\":return[n.onesLike(k(\"x\",e,t,a))];case\"RandomStandardNormal\":return[n.randomStandardNormal(k(\"shape\",e,t,a),k(\"dtype\",e,t,a),k(\"seed\",e,t,a))];case\"RandomUniform\":return[n.randomUniform(k(\"shape\",e,t,a),k(\"minval\",e,t,a),k(\"maxval\",e,t,a),k(\"dtype\",e,t,a))];case\"Range\":{let r=k(\"start\",e,t,a),s=k(\"stop\",e,t,a),i=k(\"step\",e,t,a);return[n.range(r,s,i,k(\"dtype\",e,t,a))]}case\"TruncatedNormal\":{let r=k(\"shape\",e,t,a),s=k(\"mean\",e,t,a),i=k(\"stdDev\",e,t,a),o=k(\"seed\",e,t,a);return[n.truncatedNormal(r,s,i,k(\"dtype\",e,t,a),o)]}case\"Zeros\":return[n.zeros(k(\"shape\",e,t,a),k(\"dtype\",e,t,a))];case\"ZerosLike\":return[n.zerosLike(k(\"x\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}};function Dm(e,t,a){let n=k(\"boxes\",e,t,a),r=k(\"scores\",e,t,a),s=k(\"maxOutputSize\",e,t,a),i=k(\"iouThreshold\",e,t,a),o=k(\"scoreThreshold\",e,t,a),l=k(\"softNmsSigma\",e,t,a);return{boxes:n,scores:r,maxOutputSize:s,iouThreshold:i,scoreThreshold:o,softNmsSigma:l}}var JP=async(e,t,a,n,r=Zt)=>{switch(e.op){case\"NonMaxSuppressionV5\":{let{boxes:s,scores:i,maxOutputSize:o,iouThreshold:l,scoreThreshold:u,softNmsSigma:p}=Dm(e,t,a),c=await r.image.nonMaxSuppressionWithScoreAsync(s,i,o,l,u,p);return[c.selectedIndices,c.selectedScores]}case\"NonMaxSuppressionV4\":{let{boxes:s,scores:i,maxOutputSize:o,iouThreshold:l,scoreThreshold:u}=Dm(e,t,a),p=k(\"padToMaxOutputSize\",e,t,a),c=await r.image.nonMaxSuppressionPaddedAsync(s,i,o,l,u,p);return[c.selectedIndices,c.validOutputs]}case\"NonMaxSuppressionV3\":case\"NonMaxSuppressionV2\":{let{boxes:s,scores:i,maxOutputSize:o,iouThreshold:l,scoreThreshold:u}=Dm(e,t,a);return[await r.image.nonMaxSuppressionAsync(s,i,o,l,u)]}case\"Where\":{let s=r.cast(k(\"condition\",e,t,a),\"bool\"),i=[await r.whereAsync(s)];return s.dispose(),i}case\"ListDiff\":return r.setdiff1dAsync(k(\"x\",e,t,a),k(\"y\",e,t,a));default:throw TypeError(`Node type ${e.op} is not implemented`)}},QP=(e,t,a,n=Zt)=>{switch(e.op){case\"LowerBound\":{let r=k(\"sortedSequence\",e,t,a),s=k(\"values\",e,t,a);return[n.lowerBound(r,s)]}case\"TopKV2\":{let r=k(\"x\",e,t,a),s=k(\"k\",e,t,a),i=k(\"sorted\",e,t,a),o=n.topk(r,s,i);return[o.values,o.indices]}case\"UpperBound\":{let r=k(\"sortedSequence\",e,t,a),s=k(\"values\",e,t,a);return[n.upperBound(r,s)]}case\"Unique\":{let r=k(\"x\",e,t,a),s=n.unique(r);return[s.values,s.indices]}case\"UniqueV2\":{let r=k(\"x\",e,t,a),s=k(\"axis\",e,t,a),i=n.unique(r,s);return[i.values,i.indices]}default:throw TypeError(`Node type ${e.op} is not implemented`)}},eF=(e,t,a,n=Zt)=>{switch(e.op){case\"Const\":return t[e.name];case\"PlaceholderWithDefault\":let r=k(\"default\",e,t,a);return[ba(e.name,t,a)||r];case\"Placeholder\":return[ba(e.name,t,a)];case\"Identity\":case\"StopGradient\":case\"FakeQuantWithMinMaxVars\":{let p=k(\"x\",e,t,a);return[gr(p)]}case\"IdentityN\":return k(\"x\",e,t,a).map(p=>gr(p));case\"Snapshot\":let s=k(\"x\",e,t,a);return[gr(s)];case\"Shape\":return[n.tensor1d(k(\"x\",e,t,a).shape,\"int32\")];case\"ShapeN\":return k(\"x\",e,t,a).map(p=>n.tensor1d(p.shape));case\"Size\":return[n.scalar(k(\"x\",e,t,a).size,\"int32\")];case\"Rank\":return[n.scalar(k(\"x\",e,t,a).rank,\"int32\")];case\"NoOp\":return[n.scalar(1)];case\"Print\":let i=k(\"x\",e,t,a),o=k(\"data\",e,t,a),l=k(\"message\",e,t,a),u=k(\"summarize\",e,t,a);console.warn(\"The graph has a tf.print() operation,usually used for debugging, which slows down performance.\"),console.log(l);for(let p=0;p<o.length;p++)console.log(Array.prototype.slice.call(o[p].dataSync()).slice(0,u));return[i];default:throw TypeError(`Node type ${e.op} is not implemented`)}},tF=class{constructor(e,t){this.keyDType=e,this.valueDType=t,this.handle=Fe(0),this.tensorMap=new Map,On(this.handle)}get id(){return this.handle.id}clearAndClose(){this.tensorMap.forEach(e=>e.dispose()),this.tensorMap.clear(),this.handle.dispose()}size(){return this.tensorMap.size}tensorSize(){return Fe(this.size(),\"int32\")}async import(e,t){this.checkKeyAndValueTensor(e,t);let a=await e.data();return this.tensorMap.forEach(n=>n.dispose()),this.tensorMap.clear(),$e(()=>{let n=Ta(t),r=a.length,s=n.length;v.assert(r===s,()=>`The number of elements doesn't match, keys has ${r} elements, the values has ${s} elements.`);for(let i=0;i<r;i++){let o=a[i],l=n[i];On(l),this.tensorMap.set(o,l)}return this.handle})}async find(e,t){this.checkKeyAndValueTensor(e,t);let a=await e.data();return $e(()=>{let n=[];for(let r=0;r<a.length;r++){let s=a[r],i=this.findWithDefault(s,t);n.push(i)}return sa(n)})}findWithDefault(e,t){let a=this.tensorMap.get(e);return a!=null?a:t}checkKeyAndValueTensor(e,t){if(e.dtype!==this.keyDType)throw new Error(`Expect key dtype ${this.keyDType}, but got ${e.dtype}`);if(t.dtype!==this.valueDType)throw new Error(`Expect value dtype ${this.valueDType}, but got ${t.dtype}`)}},aF=async(e,t,a,n)=>{switch(e.op){case\"HashTable\":case\"HashTableV2\":{let r=n.getHashTableHandleByName(e.name);if(r!=null)return[r];{let s=k(\"keyDType\",e,t,a),i=k(\"valueDType\",e,t,a),o=new tF(s,i);return n.addHashTable(e.name,o),[o.handle]}}case\"InitializeTable\":case\"InitializeTableV2\":case\"LookupTableImport\":case\"LookupTableImportV2\":{let r=k(\"tableHandle\",e,t,a,n),s=k(\"keys\",e,t,a),i=k(\"values\",e,t,a);return[await n.getHashTableById(r.id).import(s,i)]}case\"LookupTableFind\":case\"LookupTableFindV2\":{let r=k(\"tableHandle\",e,t,a,n),s=k(\"keys\",e,t,a),i=k(\"defaultValue\",e,t,a);return[await n.getHashTableById(r.id).find(s,i)]}case\"LookupTableSize\":case\"LookupTableSizeV2\":{let r=k(\"tableHandle\",e,t,a,n);return[n.getHashTableById(r.id).tensorSize()]}default:throw TypeError(`Node type ${e.op} is not implemented`)}},nF=(e,t,a,n=Zt)=>{switch(e.op){case\"ResizeBilinear\":{let r=k(\"images\",e,t,a),s=k(\"size\",e,t,a),i=k(\"alignCorners\",e,t,a),o=k(\"halfPixelCenters\",e,t,a);return[n.image.resizeBilinear(r,[s[0],s[1]],i,o)]}case\"ResizeNearestNeighbor\":{let r=k(\"images\",e,t,a),s=k(\"size\",e,t,a),i=k(\"alignCorners\",e,t,a),o=k(\"halfPixelCenters\",e,t,a);return[n.image.resizeNearestNeighbor(r,[s[0],s[1]],i,o)]}case\"CropAndResize\":{let r=k(\"image\",e,t,a),s=k(\"boxes\",e,t,a),i=k(\"boxInd\",e,t,a),o=k(\"cropSize\",e,t,a),l=k(\"method\",e,t,a),u=k(\"extrapolationValue\",e,t,a);return[n.image.cropAndResize(r,s,i,o,l,u)]}case\"ImageProjectiveTransformV3\":{let r=k(\"images\",e,t,a),s=k(\"transforms\",e,t,a),i=k(\"outputShape\",e,t,a),o=k(\"fillValue\",e,t,a),l=k(\"interpolation\",e,t,a),u=k(\"fillMode\",e,t,a);return[n.image.transform(r,s,l.toLowerCase(),u.toLowerCase(),o,i)]}default:throw TypeError(`Node type ${e.op} is not implemented`)}},rF=(e,t,a,n=Zt)=>{switch(e.op){case\"Equal\":return[n.equal(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"NotEqual\":return[n.notEqual(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"Greater\":return[n.greater(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"GreaterEqual\":return[n.greaterEqual(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"Less\":return[n.less(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"LessEqual\":return[n.lessEqual(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"LogicalAnd\":return[n.logicalAnd(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"LogicalNot\":return[n.logicalNot(k(\"a\",e,t,a))];case\"LogicalOr\":return[n.logicalOr(k(\"a\",e,t,a),k(\"b\",e,t,a))];case\"Select\":case\"SelectV2\":return[n.where(k(\"condition\",e,t,a),k(\"a\",e,t,a),k(\"b\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}},sF=(e,t,a,n=Zt)=>{switch(e.op){case\"BatchMatMul\":case\"BatchMatMulV2\":case\"MatMul\":return[n.matMul(k(\"a\",e,t,a),k(\"b\",e,t,a),k(\"transposeA\",e,t,a),k(\"transposeB\",e,t,a))];case\"Einsum\":return[n.einsum(k(\"equation\",e,t,a),...k(\"tensors\",e,t,a))];case\"Transpose\":return[n.transpose(k(\"x\",e,t,a),k(\"perm\",e,t,a))];case\"_FusedMatMul\":let[r,s]=k(\"fusedOps\",e,t,a),i=r===\"biasadd\",o=s===\"prelu\",l=k(\"numArgs\",e,t,a),u=k(\"leakyreluAlpha\",e,t,a);if(i){if(o&&l!==2)throw new Error(\"Fused MatMul with BiasAdd and Prelu must have two extra arguments: bias and alpha.\");if(!o&&l!==1)throw new Error(\"Fused MatMul with BiasAdd must have one extra argument: bias.\")}let[p,c]=k(\"args\",e,t,a);return[n.fused.matMul({a:k(\"a\",e,t,a),b:k(\"b\",e,t,a),transposeA:k(\"transposeA\",e,t,a),transposeB:k(\"transposeB\",e,t,a),bias:p,activation:s,preluActivationWeights:c,leakyreluAlpha:u})];default:throw TypeError(`Node type ${e.op} is not implemented`)}},iF=(e,t,a,n=Zt)=>{switch(e.op){case\"EuclideanNorm\":return[n.euclideanNorm(k(\"x\",e,t,a),k(\"axis\",e,t,a),k(\"keepDims\",e,t,a))];case\"FusedBatchNorm\":case\"FusedBatchNormV2\":return[n.batchNorm(k(\"x\",e,t,a),k(\"mean\",e,t,a),k(\"variance\",e,t,a),k(\"offset\",e,t,a),k(\"scale\",e,t,a),k(\"epsilon\",e,t,a))];case\"FusedBatchNormV3\":return[n.batchNorm(k(\"x\",e,t,a),k(\"mean\",e,t,a),k(\"variance\",e,t,a),k(\"offset\",e,t,a),k(\"scale\",e,t,a),k(\"epsilon\",e,t,a))];case\"LRN\":return[n.localResponseNormalization(k(\"x\",e,t,a),k(\"radius\",e,t,a),k(\"bias\",e,t,a),k(\"alpha\",e,t,a),k(\"beta\",e,t,a))];case\"Softmax\":return[n.softmax(k(\"x\",e,t,a))];case\"LogSoftmax\":return[n.logSoftmax(k(\"x\",e,t,a))];case\"SparseToDense\":return[n.sparseToDense(k(\"sparseIndices\",e,t,a),k(\"outputShape\",e,t,a),k(\"sparseValues\",e,t,a),k(\"defaultValue\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}},oF=(e,t,a,n=Zt)=>{switch(e.op){case\"RaggedGather\":{let{outputNestedSplits:r,outputDenseValues:s}=n.raggedGather(k(\"paramsNestedSplits\",e,t,a),k(\"paramsDenseValues\",e,t,a),k(\"indices\",e,t,a),k(\"outputRaggedRank\",e,t,a));return r.concat(s)}case\"RaggedRange\":{let{rtNestedSplits:r,rtDenseValues:s}=n.raggedRange(k(\"starts\",e,t,a),k(\"limits\",e,t,a),k(\"splits\",e,t,a));return[r,s]}case\"RaggedTensorToTensor\":return[n.raggedTensorToTensor(k(\"shape\",e,t,a),k(\"values\",e,t,a),k(\"defaultValue\",e,t,a),k(\"rowPartitionTensors\",e,t,a),k(\"rowPartitionTypes\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}},lF=(e,t,a,n=Zt)=>{switch(e.op){case\"Max\":{let o=k(\"axis\",e,t,a),l=k(\"keepDims\",e,t,a);return[n.max(k(\"x\",e,t,a),o,l)]}case\"Mean\":{let o=k(\"axis\",e,t,a),l=k(\"keepDims\",e,t,a);return[n.mean(k(\"x\",e,t,a),o,l)]}case\"Min\":{let o=k(\"axis\",e,t,a),l=k(\"keepDims\",e,t,a);return[n.min(k(\"x\",e,t,a),o,l)]}case\"Sum\":{let o=k(\"axis\",e,t,a),l=k(\"keepDims\",e,t,a);return[n.sum(k(\"x\",e,t,a),o,l)]}case\"All\":{let o=k(\"axis\",e,t,a),l=k(\"keepDims\",e,t,a);return[n.all(k(\"x\",e,t,a),o,l)]}case\"Any\":{let o=k(\"axis\",e,t,a),l=k(\"keepDims\",e,t,a);return[n.any(k(\"x\",e,t,a),o,l)]}case\"ArgMax\":{let o=k(\"axis\",e,t,a);return[n.argMax(k(\"x\",e,t,a),o)]}case\"ArgMin\":{let o=k(\"axis\",e,t,a);return[n.argMin(k(\"x\",e,t,a),o)]}case\"Prod\":{let o=k(\"axis\",e,t,a),l=k(\"keepDims\",e,t,a);return[n.prod(k(\"x\",e,t,a),o,l)]}case\"Cumprod\":{let o=k(\"axis\",e,t,a),l=k(\"exclusive\",e,t,a),u=k(\"reverse\",e,t,a);return[n.cumprod(k(\"x\",e,t,a),o,l,u)]}case\"Cumsum\":{let o=k(\"axis\",e,t,a),l=k(\"exclusive\",e,t,a),u=k(\"reverse\",e,t,a);return[n.cumsum(k(\"x\",e,t,a),o,l,u)]}case\"Bincount\":let r=k(\"x\",e,t,a),s=k(\"weights\",e,t,a),i=k(\"size\",e,t,a);return[n.bincount(r,s,i)];case\"DenseBincount\":{let o=k(\"x\",e,t,a),l=k(\"weights\",e,t,a),u=k(\"size\",e,t,a),p=k(\"binaryOutput\",e,t,a);return[n.denseBincount(o,l,u,p)]}default:throw TypeError(`Node type ${e.op} is not implemented`)}},uF=(e,t,a,n=Zt)=>{switch(e.op){case\"ConcatV2\":case\"Concat\":{let r=k(\"n\",e,t,a),s=k(\"axis\",e,t,a),i=k(\"tensors\",e,t,a);return i=i.slice(0,r),[n.concat(i,s)]}case\"Gather\":{let r=k(\"x\",e,t,a),s=k(\"indices\",e,t,a);return[n.gather(r,n.cast(s,\"int32\"),0)]}case\"GatherV2\":{let r=k(\"axis\",e,t,a),s=k(\"batchDims\",e,t,a),i=k(\"x\",e,t,a),o=k(\"indices\",e,t,a);return[n.gather(i,n.cast(o,\"int32\"),r,s)]}case\"Reverse\":{let r=k(\"dims\",e,t,a),s=[];for(let o=0;o<r.length;o++)r[o]&&s.push(o);let i=k(\"x\",e,t,a);return[n.reverse(i,s)]}case\"ReverseV2\":{let r=k(\"axis\",e,t,a),s=k(\"x\",e,t,a);return[n.reverse(s,r)]}case\"Slice\":{let r=k(\"begin\",e,t,a),s=k(\"size\",e,t,a);return[n.slice(k(\"x\",e,t,a),r,s)]}case\"StridedSlice\":{let r=k(\"begin\",e,t,a),s=k(\"end\",e,t,a),i=k(\"strides\",e,t,a),o=k(\"beginMask\",e,t,a),l=k(\"endMask\",e,t,a),u=k(\"ellipsisMask\",e,t,a),p=k(\"newAxisMask\",e,t,a),c=k(\"shrinkAxisMask\",e,t,a),d=k(\"x\",e,t,a);return[n.stridedSlice(d,r,s,i,o,l,u,p,c)]}case\"Pack\":return $e(()=>{let r=k(\"axis\",e,t,a),s=k(\"tensors\",e,t,a),i=s[0].shape,o=n.squeeze(s[0]).shape,l=s.map(u=>{let p=v.arraysEqual(u.shape,i);if(!p&&!v.arraysEqual(n.squeeze(u).shape,o))throw new Error(\"the input tensors shape does not match\");return p?u:n.reshape(u,i)});return[n.stack(l,r)]});case\"Unpack\":{let r=k(\"axis\",e,t,a),s=k(\"tensor\",e,t,a);return n.unstack(s,r)}case\"Tile\":{let r=k(\"reps\",e,t,a);return[n.tile(k(\"x\",e,t,a),r)]}case\"Split\":case\"SplitV\":{let r=k(\"axis\",e,t,a),s=k(\"numOrSizeSplits\",e,t,a),i=k(\"x\",e,t,a);return n.split(i,s,r)}case\"ScatterNd\":{let r=k(\"indices\",e,t,a),s=k(\"values\",e,t,a),i=k(\"shape\",e,t,a);return[n.scatterND(r,s,i)]}case\"GatherNd\":{let r=k(\"x\",e,t,a),s=k(\"indices\",e,t,a);return[n.gatherND(r,s)]}case\"SparseToDense\":{let r=k(\"sparseIndices\",e,t,a),s=k(\"outputShape\",e,t,a),i=k(\"sparseValues\",e,t,a),o=k(\"defaultValue\",e,t,a);return[n.sparseToDense(r,i,s,i.dtype===o.dtype?o:n.cast(o,i.dtype))]}default:throw TypeError(`Node type ${e.op} is not implemented`)}},dF=(e,t,a,n=Zt)=>{switch(e.op){case\"SparseFillEmptyRows\":{let{outputIndices:r,outputValues:s,emptyRowIndicator:i,reverseIndexMap:o}=n.sparse.sparseFillEmptyRows(k(\"indices\",e,t,a),k(\"values\",e,t,a),k(\"denseShape\",e,t,a),k(\"defaultValue\",e,t,a));return[r,s,i,o]}case\"SparseReshape\":{let{outputIndices:r,outputShape:s}=n.sparse.sparseReshape(k(\"inputIndices\",e,t,a),k(\"inputShape\",e,t,a),k(\"newShape\",e,t,a));return[r,s]}case\"SparseSegmentMean\":return[n.sparse.sparseSegmentMean(k(\"data\",e,t,a),k(\"indices\",e,t,a),k(\"segmentIds\",e,t,a))];case\"SparseSegmentSum\":return[n.sparse.sparseSegmentSum(k(\"data\",e,t,a),k(\"indices\",e,t,a),k(\"segmentIds\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}},pF=(e,t,a,n=Zt)=>{switch(e.op){case\"FFT\":return[n.fft(k(\"x\",e,t,a))];case\"IFFT\":return[n.ifft(k(\"x\",e,t,a))];case\"RFFT\":return[n.rfft(k(\"x\",e,t,a))];case\"IRFFT\":return[n.irfft(k(\"x\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}},cF=(e,t,a,n=Zt)=>{switch(e.op){case\"StringNGrams\":{let{nGrams:r,nGramsSplits:s}=n.string.stringNGrams(k(\"data\",e,t,a),k(\"dataSplits\",e,t,a),k(\"separator\",e,t,a),k(\"nGramWidths\",e,t,a),k(\"leftPad\",e,t,a),k(\"rightPad\",e,t,a),k(\"padWidth\",e,t,a),k(\"preserveShortSequences\",e,t,a));return[r,s]}case\"StringSplit\":{let{indices:r,values:s,shape:i}=n.string.stringSplit(k(\"input\",e,t,a),k(\"delimiter\",e,t,a),k(\"skipEmpty\",e,t,a));return[r,s,i]}case\"StringToHashBucketFast\":return[n.string.stringToHashBucketFast(k(\"input\",e,t,a),k(\"numBuckets\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}},hF=(e,t,a,n=Zt)=>{switch(e.op){case\"Cast\":return[n.cast(k(\"x\",e,t,a),k(\"dtype\",e,t,a))];case\"ExpandDims\":{let r=k(\"axis\",e,t,a);return[n.expandDims(k(\"x\",e,t,a),r)]}case\"Squeeze\":{let r=k(\"axis\",e,t,a);return[n.squeeze(k(\"x\",e,t,a),r)]}case\"Reshape\":return[n.reshape(k(\"x\",e,t,a),k(\"shape\",e,t,a))];case\"MirrorPad\":return[n.mirrorPad(k(\"x\",e,t,a),k(\"padding\",e,t,a),k(\"mode\",e,t,a))];case\"PadV2\":case\"Pad\":return[n.pad(k(\"x\",e,t,a),k(\"padding\",e,t,a),k(\"constantValue\",e,t,a))];case\"SpaceToBatchND\":{let r=k(\"blockShape\",e,t,a),s=k(\"paddings\",e,t,a);return[n.spaceToBatchND(k(\"x\",e,t,a),r,s)]}case\"BatchToSpaceND\":{let r=k(\"blockShape\",e,t,a),s=k(\"crops\",e,t,a);return[n.batchToSpaceND(k(\"x\",e,t,a),r,s)]}case\"DepthToSpace\":{let r=k(\"blockSize\",e,t,a),s=k(\"dataFormat\",e,t,a).toUpperCase();return[n.depthToSpace(k(\"x\",e,t,a),r,s)]}case\"BroadcastTo\":return[n.broadcastTo(k(\"x\",e,t,a),k(\"shape\",e,t,a))];case\"BroadcastArgs\":return[n.broadcastArgs(k(\"s0\",e,t,a),k(\"s1\",e,t,a))];default:throw TypeError(`Node type ${e.op} is not implemented`)}};function nx(e,t,a,n,r=$e){let s=((i,o,l)=>{switch(i.category){case\"arithmetic\":return r(()=>VP(i,o,l));case\"basic_math\":return r(()=>UP(i,o,l));case\"control\":return KP(i,o,l);case\"convolution\":return r(()=>ZP(i,o,l));case\"creation\":return r(()=>YP(i,o,l));case\"dynamic\":return JP(i,o,l);case\"evaluation\":return r(()=>QP(i,o,l));case\"image\":return r(()=>nF(i,o,l));case\"graph\":return r(()=>eF(i,o,l));case\"logical\":return r(()=>rF(i,o,l));case\"matrices\":return r(()=>sF(i,o,l));case\"normalization\":return r(()=>iF(i,o,l));case\"ragged\":return r(()=>oF(i,o,l));case\"reduction\":return r(()=>lF(i,o,l));case\"slice_join\":return r(()=>uF(i,o,l));case\"sparse\":return r(()=>dF(i,o,l));case\"spectral\":return r(()=>pF(i,o,l));case\"string\":return r(()=>cF(i,o,l));case\"transformation\":return r(()=>hF(i,o,l));case\"hash_table\":return aF(i,o,l,n);case\"custom\":let u=w4(i.op);if(u&&u.customExecutor)return u.customExecutor(new WP(i,o,l));throw TypeError(`Custom op ${i.op} is not registered.`);default:throw TypeError(`Unknown op '${i.op}'. File an issue at https://github.com/tensorflow/tfjs/issues so we can add it, or register a custom execution with tf.registerOp()`)}})(e,t,a);return v.isPromise(s)?s.then(i=>[].concat(i)):[].concat(s)}var rx=class{constructor(e={},t={},a={},n={}){this.weightMap=e,this.tensorArrayMap=t,this.tensorListMap=a,this.functionMap=n,this.rootContext={id:0,frameName:\"\",iterationId:0},this.contexts=[this.rootContext],this.lastId=0,this.generateCurrentContextIds()}newFrame(e,t){return{id:e,frameName:t,iterationId:0}}set currentContext(e){this.contexts!==e&&(this.contexts=e,this.generateCurrentContextIds())}get currentContext(){return this.contexts}get currentContextId(){return this._currentContextIds[0]}get currentContextIds(){return this._currentContextIds}generateCurrentContextIds(){let e=[];for(let t=0;t<this.contexts.length-1;t++){let a=this.contexts.slice(0,this.contexts.length-t);e.push(this.contextIdforContexts(a))}e.push(\"\"),this._currentContextIds=e}contextIdforContexts(e){return e?e.map(t=>t.id===0&&t.iterationId===0?\"\":`${t.frameName}-${t.iterationId}`).join(\"/\"):\"\"}enterFrame(e){this.contexts&&(this.lastId++,this.contexts=this.contexts.slice(),this.contexts.push(this.newFrame(this.lastId,e)),this._currentContextIds.unshift(this.contextIdforContexts(this.contexts)))}exitFrame(){if(this.contexts&&this.contexts.length>1)this.contexts=this.contexts.slice(),this.contexts.splice(-1),this.currentContextIds.shift();else throw new Error(\"Cannot exit frame, the context is empty\")}nextIteration(){if(this.contexts&&this.contexts.length>0){this.contexts=this.contexts.slice(),this.lastId++;let e=Object.assign({},this.contexts[this.contexts.length-1]);e.iterationId+=1,e.id=this.lastId,this.contexts.splice(-1,1,e),this._currentContextIds.splice(0,1,this.contextIdforContexts(this.contexts))}else throw new Error(\"Cannot increase frame iteration, the context is empty\")}getWeight(e){return this.weightMap[e]}addTensorArray(e){this.tensorArrayMap[e.id]=e}getTensorArray(e){return this.tensorArrayMap[e]}addTensorList(e){this.tensorListMap[e.id]=e}getTensorList(e){return this.tensorListMap[e]}dispose(e){for(let t in this.tensorArrayMap)this.tensorArrayMap[t].clearAndClose(e);for(let t in this.tensorListMap)this.tensorListMap[t].clearAndClose(e)}};function sx(e,t,a,n){let r=new Set,s=[],i=null,o=null,l=new Set,u=Object.keys(e).map(d=>ja(d)[0]),p=[];n!=null&&(p=n.map(d=>ja(d.name)[0]));let c=[...t];for(;c.length>0;){let d=c.pop();if((G4(d)||AF(d)||yF(d))&&i==null&&(i=d,o=i.children.map(h=>h.name).filter(h=>r.has(h))),r.add(d.name),a[d.name]==null&&u.indexOf(d.name)===-1&&p.indexOf(d.name)===-1){if(d.inputs.length===0){s.push(d.name);continue}d.inputs.forEach(h=>{l.has(h.name)||(l.add(h.name),c.push(h))})}}return{inputs:e,outputs:t,usedNodes:r,missingInputs:s,dynamicNode:i,syncInputs:o}}function fF(e,t,a){let{usedNodes:n,inputs:r}=a,s=[],i=Object.keys(r).map(p=>ja(p)[0]).map(p=>e.nodes[p]),o=e.initNodes;i.forEach(p=>{n.has(p.name)&&s.push(p)}),e.weights.forEach(p=>{n.has(p.name)&&s.push(p)}),o!=null&&o.forEach(p=>{n.has(p.name)&&s.push(p)});let l=new Set,u=[];for(;s.length>0;){let p=s.pop();l.add(p.name),t[p.name]||u.push(p),p.children.forEach(c=>{!l.has(c.name)&&n.has(c.name)&&c.inputs.every(d=>l.has(d.name))&&s.push(c)})}return u}var mF=[\"Switch\",\"Merge\",\"Enter\",\"Exit\",\"NextIteration\",\"StatelessIf\",\"StatelessWhile\",\"if\",\"While\"],gF=[\"NonMaxSuppressionV2\",\"NonMaxSuppressionV3\",\"NonMaxSuppressionV5\",\"Where\"],xF=[\"HashTable\",\"HashTableV2\",\"LookupTableImport\",\"LookupTableImportV2\",\"LookupTableFind\",\"LookupTableFindV2\",\"LookupTableSize\",\"LookupTableSizeV2\"];function G4(e){return mF.indexOf(e.op)>=0}function AF(e){return gF.indexOf(e.op)>=0}function yF(e){return xF.indexOf(e.op)>=0}var A1=class{constructor(e,t){this.graph=e,this.parent=t,this.compiledMap=new Map,this._weightMap={},this.SEPERATOR=\",\",this._functions={},this._functionExecutorMap={},this.keepIntermediateTensors=!1,this._outputs=e.outputs,this._inputs=e.inputs,this._initNodes=e.initNodes,this._signature=e.signature,this._functions=e.functions,e.functions!=null&&Object.keys(e.functions).forEach(a=>{this._functionExecutorMap[a]=new A1(e.functions[a],this)})}get weightIds(){return this.parent?this.parent.weightIds:this._weightIds}get functionExecutorMap(){return this.parent?this.parent.functionExecutorMap:this._functionExecutorMap}get weightMap(){return this.parent?this.parent.weightMap:this._weightMap}set weightMap(e){let t=Object.keys(e).map(a=>e[a].map(n=>n.id));this._weightIds=[].concat(...t),this._weightMap=e}set resourceManager(e){this._resourceManager=e}get inputs(){return this._inputs.map(e=>({name:e.name,shape:e.attrParams.shape?e.attrParams.shape.value:void 0,dtype:e.attrParams.dtype?e.attrParams.dtype.value:void 0}))}get outputs(){return this._outputs.map(e=>({name:e.name,shape:e.attrParams.shape?e.attrParams.shape.value:void 0,dtype:e.attrParams.dtype?e.attrParams.dtype.value:void 0}))}get inputNodes(){return this._inputs.map(e=>e.signatureKey||e.name)}get outputNodes(){return this._outputs.map(e=>{let t=e.signatureKey||e.name;return e.defaultOutput?`${t}:${e.defaultOutput}`:t})}get functions(){return Object.keys(this._functions).reduce((e,t)=>(e[t]=this._functions[t].signature,e),{})}getCompilationKey(e,t){let a=e.map(r=>r.name).sort(),n=t.map(r=>r.name).sort();return a.join(this.SEPERATOR)+\"--\"+n.join(this.SEPERATOR)}compile(e,t){let a=sx(e,t,this.weightMap,this._initNodes),{missingInputs:n,dynamicNode:r,syncInputs:s}=a;if(r!=null)throw new Error(`This execution contains the node '${r.name}', which has the dynamic op '${r.op}'. Please use model.executeAsync() instead. Alternatively, to avoid the dynamic ops, specify the inputs [${s}]`);if(n.length>0){let i=t.map(l=>l.name),o=Object.keys(e);throw new Error(`Cannot compute the outputs [${i}] from the provided inputs [${o}]. Missing the following inputs: [${n}]`)}return fF(this.graph,this.weightMap,a)}cloneAndKeepTensor(e){if(e==null)return null;let t=e.clone();return On(t),t}cloneTensorList(e){return e?e.map(t=>this.cloneAndKeepTensor(t)):null}cloneTensorMap(e){return Object.fromEntries(Object.entries(e).map(([t,a])=>[t,this.cloneTensorList(a)]))}execute(e,t){this.disposeIntermediateTensors(),e=this.mapInputs(e);let a=Object.keys(e).sort();this.checkInputs(e),this.checkInputShapeAndType(e),t=this.mapOutputs(t),this.checkOutputs(t);let n=a.map(p=>this.graph.nodes[ja(p)[0]]),r=t.map(p=>ja(p)[0]),s=r.map(p=>this.graph.nodes[p]);s.length===0&&(s=this._outputs);let i=this.getCompilationKey(n,s),o=this.compiledMap.get(i);o==null&&(o=this.compile(e,s),this.compiledMap.set(i,o));try{this.keepIntermediateTensors=W().getBool(\"KEEP_INTERMEDIATE_TENSORS\")}catch(p){this.keepIntermediateTensors=!1,console.warn(p.message)}let l={},u={};return $e(()=>{let p=new rx(this.weightMap,l,u,this.functionExecutorMap),c=Object.assign({},this.weightMap);this.keepIntermediateTensors&&(this.clonedTensorsMap=this.cloneTensorMap(this.weightMap)),Object.keys(e).forEach(f=>{let[m,g]=ja(f),x=[];x[g]=e[f],c[m]=x,this.keepIntermediateTensors&&(this.clonedTensorsMap[m]=this.cloneTensorList(x))});let d=this.getFrozenTensorIds(c),h={};for(let f=0;f<o.length;f++){let m=o[f];if(!c[m.name]){let g=nx(m,c,p,this._resourceManager);if(v.isPromise(g))throw new Error(`The execution of the op '${m.op}' returned a promise. Please use model.executeAsync() instead.`);c[m.name]=g,this.keepIntermediateTensors&&(this.clonedTensorsMap[m.name]=this.cloneTensorList(g)),this.checkTensorForDisposal(m.name,m,c,p,d,r,h)}}return this.parent==null&&p.dispose(d),t.map(f=>ba(f,c,p))})}getFrozenTensorIds(e){let t=[].concat.apply([],Object.keys(e).map(a=>e[a]).map(a=>a.map(n=>n.id)));return new Set(t)}checkTensorForDisposal(e,t,a,n,r,s,i){t.category===\"control\"||s.indexOf(e)!==-1||(a[e].forEach(o=>{o!=null&&(i[o.id]=(i[o.id]||0)+t.children.length)}),t.inputs.forEach(o=>{if(o.category!==\"control\"){let l=bP(o.name,a,n);l!=null&&l.forEach(u=>{if(u&&!u.kept&&!r.has(u.id)){let p=i[u.id];p===1?(u.dispose(),delete i[u.id]):p!=null&&i[u.id]--}})}}))}async executeAsync(e,t){return this._executeAsync(e,t)}disposeIntermediateTensors(){!this.clonedTensorsMap||(Object.values(this.clonedTensorsMap).forEach(e=>{for(let t of e)t&&!t.isDisposed&&t.dispose()}),this.clonedTensorsMap=null)}getIntermediateTensors(){return this.clonedTensorsMap}async _executeAsync(e,t,a=!1,n={},r={}){this.disposeIntermediateTensors(),a||(e=this.mapInputs(e),this.checkInputs(e),this.checkInputShapeAndType(e),t=this.mapOutputs(t),this.checkOutputs(t));try{this.keepIntermediateTensors=W().getBool(\"KEEP_INTERMEDIATE_TENSORS\")}catch(c){this.keepIntermediateTensors=!1,console.warn(c.message)}let s=new rx(this.weightMap,n,r,this.functionExecutorMap);this.keepIntermediateTensors&&(this.clonedTensorsMap=this.cloneTensorMap(this.weightMap));let i=await this.executeWithControlFlow(e,s,t,a),o=t.map(c=>ba(c,i,s)),l=o.map(c=>c.id),u=Object.keys(e).map(c=>e[c].id),p=new Set([...l,...u,...this.weightIds]);return Object.values(i).forEach(c=>{c.forEach(d=>{d&&!d.isDisposed&&!p.has(d.id)&&d.dispose()})}),this.parent==null&&s.dispose(p),o}async executeFunctionAsync(e,t,a){let n=e.reduce((r,s,i)=>(r[this.inputs[i].name]=s,r),{});return this._executeAsync(n,this.outputNodes,!0,t,a)}async executeWithControlFlow(e,t,a,n){let r=Object.keys(e),s=r.map(A=>this.graph.nodes[ja(A)[0]]),i=a.map(A=>ja(A)[0]),o=i.map(A=>this.graph.nodes[A]);o.length===0&&(o=this._outputs);let{usedNodes:l,missingInputs:u,dynamicNode:p,syncInputs:c}=sx(e,o,this.weightMap,this._initNodes),d=[...s,...this.graph.weights,...this._initNodes||[]].map(A=>({node:A,contexts:t.currentContext})),h=Object.assign({},this.weightMap);Object.keys(e).forEach(A=>{let[y,b]=ja(A),w=[];w[b]=e[A],h[y]=w});let f={},m=this.getFrozenTensorIds(h),g={};for(;d.length>0;){let A=this.processStack(s,d,t,h,g,m,i,f,l);await Promise.all(A)}p==null&&!n&&console.warn(\"This model execution did not contain any nodes with control flow or dynamic output shapes. You can use model.execute() instead.\");let x=o.filter(A=>!G4(A)&&!ba(A.name,h,t)).map(A=>A.name);if(x.length>0){let A=\"\";throw p!=null&&(A=`Alternatively, to avoid the dynamic ops, use model.execute() and specify the inputs [${c}]`),new Error(`Cannot compute the outputs [${x}] from the provided inputs [${r}]. Consider providing the following inputs: [${u}]. ${A}`)}return h}processStack(e,t,a,n,r,s,i,o,l){let u=[];for(;t.length>0;){let p=t.pop();a.currentContext=p.contexts;let c=\"\";if(p.node.op===\"Enter\"&&k(\"isConstant\",p.node,n,a)&&([c]=mr(p.node.name,a)),n[p.node.name]==null){let d=nx(p.node,n,a,this._resourceManager);c||([c]=mr(p.node.name,a));let h=a.currentContext;v.isPromise(d)?u.push(d.then(f=>(n[c]=f,this.keepIntermediateTensors&&(this.clonedTensorsMap[c]=this.cloneTensorList(f)),a.currentContext=h,this.checkTensorForDisposal(c,p.node,n,a,s,i,o),this.processChildNodes(p.node,t,a,n,r,l),f))):(n[c]=d,this.keepIntermediateTensors&&(this.clonedTensorsMap[c]=this.cloneTensorList(d)),this.checkTensorForDisposal(c,p.node,n,a,s,i,o),this.processChildNodes(p.node,t,a,n,r,l))}else this.processChildNodes(p.node,t,a,n,r,l)}return u}processChildNodes(e,t,a,n,r,s){e.children.forEach(i=>{let[o]=mr(i.name,a);r[o]||!s.has(i.name)||(i.op===\"Merge\"?i.inputNames.some(l=>!!ba(l,n,a))&&(r[o]=!0,t.push({contexts:a.currentContext,node:i})):i.inputNames.every(l=>!!ba(l,n,a))&&(r[o]=!0,t.push({contexts:a.currentContext,node:i})))})}dispose(){Object.keys(this.weightMap).forEach(e=>this.weightMap[e].forEach(t=>t.dispose()))}checkInputShapeAndType(e){Object.keys(e).forEach(t=>{let a=e[t],[n]=ja(t),r=this.graph.nodes[n];if(r.attrParams.shape&&r.attrParams.shape.value){let s=r.attrParams.shape.value,i=s.length===a.shape.length&&a.shape.every((o,l)=>s[l]===-1||s[l]===o);v.assert(i,()=>`The shape of dict['${r.name}'] provided in model.execute(dict) must be [${s}], but was [${a.shape}]`)}r.attrParams.dtype&&r.attrParams.dtype.value&&v.assert(a.dtype===r.attrParams.dtype.value,()=>`The dtype of dict['${r.name}'] provided in model.execute(dict) must be ${r.attrParams.dtype.value}, but was ${a.dtype}`)})}mapInputs(e){var t,a;let n={};for(let r in e){let s=(a=(t=this._signature)===null||t===void 0?void 0:t.inputs)===null||a===void 0?void 0:a[r];s!=null?n[s.name]=e[r]:n[r]=e[r]}return n}checkInputs(e){let t=Object.keys(e).filter(a=>{let[n]=ja(a);return this.graph.nodes[n]==null});if(t.length>0)throw new Error(`The dict provided in model.execute(dict) has keys: [${t}] that are not part of graph`)}mapOutputs(e){return e.map(t=>{var a,n;let r=(n=(a=this._signature)===null||a===void 0?void 0:a.outputs)===null||n===void 0?void 0:n[t];return r!=null?r.name:t},{})}checkOutputs(e){e.forEach(t=>{let[a]=ja(t);if(!this.graph.nodes[a])throw new Error(`The output '${t}' is not found in the graph`)})}},bF=class{constructor(e={},t={}){this.hashTableNameToHandle=e,this.hashTableMap=t}addHashTable(e,t){this.hashTableNameToHandle[e]=t.handle,this.hashTableMap[t.id]=t}getHashTableHandleByName(e){return this.hashTableNameToHandle[e]}getHashTableById(e){return this.hashTableMap[e]}dispose(){for(let e in this.hashTableMap)this.hashTableMap[e].clearAndClose(),delete this.hashTableMap[e];for(let e in this.hashTableNameToHandle)this.hashTableNameToHandle[e].dispose(),delete this.hashTableNameToHandle[e]}},vF=\"?tfjs-format=file\",wF=\"model.json\",op=class{constructor(e,t={},a=jn){this.modelUrl=e,this.loadOptions=t,this.version=\"n/a\",this.io=a,t==null&&(this.loadOptions={}),this.resourceManager=new bF}get modelVersion(){return this.version}get inputNodes(){return this.executor.inputNodes}get outputNodes(){return this.executor.outputNodes}get inputs(){return this.executor.inputs}get outputs(){return this.executor.outputs}get weights(){return this.executor.weightMap}get metadata(){return this.artifacts.userDefinedMetadata}get modelSignature(){return this.signature}get modelStructuredOutputKeys(){return this.structuredOutputKeys}findIOHandler(){let e=this.modelUrl;if(e.load!=null)this.handler=e;else if(this.loadOptions.requestInit!=null)this.handler=this.io.browserHTTPRequest(e,this.loadOptions);else{let t=this.io.getLoadHandlers(e,this.loadOptions);if(t.length===0)t.push(this.io.browserHTTPRequest(e,this.loadOptions));else if(t.length>1)throw new Error(`Found more than one (${t.length}) load handlers for URL '${[e]}'`);this.handler=t[0]}}load(){if(this.findIOHandler(),this.handler.load==null)throw new Error(\"Cannot proceed with model loading because the IOHandler provided does not have the `load` method implemented.\");let e=this.handler.load();return v.isPromise(e)?e.then(t=>this.loadSync(t)):this.loadSync(e)}loadSync(e){this.artifacts=e;let t=this.artifacts.modelTopology,a=this.artifacts.signature;if(this.artifacts.userDefinedMetadata!=null){let r=this.artifacts.userDefinedMetadata;r.signature!=null&&(a=r.signature),r.structuredOutputKeys!=null&&(this.structuredOutputKeys=r.structuredOutputKeys)}this.signature=a,this.version=`${t.versions.producer}.${t.versions.minConsumer}`;let n=this.io.decodeWeights(this.artifacts.weightData,this.artifacts.weightSpecs);if(this.executor=new A1(Q5.Instance.transformGraph(t,this.signature)),this.executor.weightMap=this.convertTensorMapToTensorsMap(n),this.executor.resourceManager=this.resourceManager,e.modelInitializer!=null&&e.modelInitializer.node!=null){let r=Q5.Instance.transformGraph(e.modelInitializer);this.initializer=new A1(r),this.initializer.weightMap=this.executor.weightMap,this.initializer.resourceManager=this.resourceManager,this.initializerSignature=e.initializerSignature}return!0}async save(e,t){if(typeof e==\"string\"){let a=this.io.getSaveHandlers(e);if(a.length===0)throw new Error(`Cannot find any save handlers for URL '${e}'`);if(a.length>1)throw new Error(`Found more than one (${a.length}) save handlers for URL '${e}'`);e=a[0]}if(e.save==null)throw new Error(\"GraphModel.save() cannot proceed because the IOHandler provided does not have the `save` attribute defined.\");return e.save(this.artifacts)}addStructuredOutputNames(e){if(this.structuredOutputKeys){let t=e instanceof pt?[e]:e,a={};return t.forEach((n,r)=>a[this.structuredOutputKeys[r]]=n),a}return e}predict(e,t){let a=this.execute(e,this.outputNodes);return this.addStructuredOutputNames(a)}async predictAsync(e,t){let a=await this.executeAsync(e,this.outputNodes);return this.addStructuredOutputNames(a)}normalizeInputs(e){var t;if(!(e instanceof pt)&&!Array.isArray(e)){let r=(t=this.signature)===null||t===void 0?void 0:t.inputs;if(r!=null)for(let s in r){let i=r[s];i.resourceId!=null&&(e[s]=this.resourceIdToCapturedInput[i.resourceId])}return e}e=Array.isArray(e)?e:[e];let a=Object.keys(this.resourceIdToCapturedInput).length;if(e.length+a!==this.inputNodes.length)throw new Error(`Input tensor count mismatch, the graph model has ${this.inputNodes.length-a} non-resource placeholders, while there are ${e.length} input tensors provided.`);let n=0;return this.inputNodes.reduce((r,s)=>{var i,o,l;let u=(l=(o=(i=this.signature)===null||i===void 0?void 0:i.inputs)===null||o===void 0?void 0:o[s])===null||l===void 0?void 0:l.resourceId;return u!=null?r[s]=this.resourceIdToCapturedInput[u]:r[s]=e[n++],r},{})}normalizeOutputs(e){return e=e||this.outputNodes,Array.isArray(e)?e:[e]}executeInitializerGraph(){return this.initializer==null?[]:this.initializerSignature==null?this.initializer.execute({},[]):this.initializer.execute({},Object.keys(this.initializerSignature.outputs))}async executeInitializerGraphAsync(){return this.initializer==null?[]:this.initializerSignature==null?this.initializer.executeAsync({},[]):this.initializer.executeAsync({},Object.keys(this.initializerSignature.outputs))}setResourceIdToCapturedInput(e){if(this.resourceIdToCapturedInput={},this.initializerSignature){let t=this.initializerSignature.outputs,a=Object.keys(t);for(let n=0;n<a.length;n++){let r=a[n],s=t[r];this.resourceIdToCapturedInput[s.resourceId]=e[n]}}}execute(e,t){this.resourceIdToCapturedInput==null&&this.setResourceIdToCapturedInput(this.executeInitializerGraph()),e=this.normalizeInputs(e),t=this.normalizeOutputs(t);let a=this.executor.execute(e,t);return a.length>1?a:a[0]}async executeAsync(e,t){this.resourceIdToCapturedInput==null&&this.setResourceIdToCapturedInput(await this.executeInitializerGraphAsync()),e=this.normalizeInputs(e),t=this.normalizeOutputs(t);let a=await this.executor.executeAsync(e,t);return a.length>1?a:a[0]}getIntermediateTensors(){return this.executor.getIntermediateTensors()}disposeIntermediateTensors(){this.executor.disposeIntermediateTensors()}convertTensorMapToTensorsMap(e){return Object.keys(e).reduce((t,a)=>(t[a]=[e[a]],t),{})}dispose(){this.executor.dispose(),this.initializer&&(this.initializer.dispose(),this.resourceIdToCapturedInput&&Y(this.resourceIdToCapturedInput)),this.resourceManager.dispose()}};async function r3(e,t={},a=jn){if(e==null)throw new Error(\"modelUrl in loadGraphModel() cannot be null. Please provide a url or an IOHandler that loads the model\");t==null&&(t={}),t.fromTFHub&&typeof e==\"string\"&&(e=IF(e));let n=new op(e,t,a);return await n.load(),n}function kF(e){if(e==null)throw new Error(\"modelUrl in loadGraphModelSync() cannot be null. Please provide model artifacts or an IOHandler that loads the model\");let t;if(e instanceof Array){let[n,r]=e;if(!n)throw new Error(\"modelJSON must be the first element of the array\");if(!r||!(r instanceof ArrayBuffer))throw new Error(\"An ArrayBuffer of weights must be the second element of the array\");if(!(\"modelTopology\"in n))throw new Error(\"Model JSON is missing 'modelTopology'\");if(!(\"weightsManifest\"in n))throw new Error(\"Model JSON is missing 'weightsManifest'\");let s=jn.getWeightSpecs(n.weightsManifest),i=jn.getModelArtifactsForJSONSync(n,s,r);t=jn.fromMemorySync(i)}else if(\"load\"in e)t=e;else if(\"modelTopology\"in e&&\"weightSpecs\"in e&&\"weightData\"in e)t=jn.fromMemorySync(e);else throw new Error(\"Unknown model format\");let a=new op(t);return a.load(),a}function IF(e){return e.endsWith(\"/\")||(e=e+\"/\"),`${e}${wF}${vF}`}var SF=\"4.1.0\";function ye(e,t){Array.isArray(e)||(e=[e]),e.forEach(a=>{a!=null&&v.assert(a.dtype!==\"complex64\",()=>`${t} does not support complex64 tensors in the CPU backend.`)})}var TF=Tn.whereImpl,$h=class extends bl{constructor(){super(),this.blockSize=48,this.firstUse=!0,this.data=new vd(this,kt())}nextDataId(){return $h.nextDataId++}write(e,t,a){this.firstUse&&(this.firstUse=!1,W().get(\"IS_NODE\")&&T.warn(`\n============================\nHi, looks like you are running TensorFlow.js in Node.js. To speed things up dramatically, install our node backend, visit https://github.com/tensorflow/tfjs-node for more details. \n============================`));let n={id:this.nextDataId()};return this.data.set(n,{values:e,dtype:a,refCount:1}),n}makeTensorInfo(e,t,a){let n;if(t===\"string\"&&a!=null&&a.length>0&&v.isString(a[0])){let r=a.map(s=>v.encodeString(s));n=this.write(r,e,t)}else n=this.write(a,e,t);return{dataId:n,shape:e,dtype:t}}refCount(e){return this.data.has(e)?this.data.get(e).refCount:0}incRef(e){let t=this.data.get(e);t.refCount++}decRef(e){if(this.data.has(e)){let t=this.data.get(e);t.refCount--}}move(e,t,a,n,r){this.data.set(e,{values:t,dtype:n,refCount:r})}numDataIds(){return this.data.numDataIds()}async read(e){return this.readSync(e)}readSync(e){let{dtype:t,complexTensorInfos:a}=this.data.get(e);if(t===\"complex64\"){let n=this.readSync(a.real.dataId),r=this.readSync(a.imag.dataId);return T.mergeRealAndImagArrays(n,r)}return this.data.get(e).values}bufferSync(e){let t=this.readSync(e.dataId);if(e.dtype===\"string\")try{let a=t.map(n=>v.decodeString(n));return Me(e.shape,e.dtype,a)}catch(a){throw new Error(\"Failed to decode encoded string bytes into utf-8\")}return Me(e.shape,e.dtype,t)}makeOutput(e,t,a){return kt().makeTensorFromTensorInfo(this.makeTensorInfo(t,a,e),this)}disposeData(e,t=!1){if(this.data.has(e)){if(this.data.get(e).refCount--,!t&&this.data.get(e).refCount>0)return!1;let{complexTensorInfos:a}=this.data.get(e);a!=null&&(this.disposeData(a.real.dataId,!0),this.disposeData(a.imag.dataId,!0)),this.data.delete(e)}return!0}disposeIntermediateTensorInfo(e){this.disposeData(e.dataId)}async time(e){let t=v.now();return e(),{kernelMs:v.now()-t}}memory(){return{unreliable:!0,reasons:[\"The reported memory is an upper bound. Due to automatic garbage collection, the true allocated memory may be less.\"]}}where(e){ye([e],\"where\");let t=this.readSync(e.dataId);return TF(e.shape,t)}dispose(){}floatPrecision(){return 32}epsilon(){return super.epsilon()}};$h.nextDataId=0;var _h={};Xe(_h,{addImpl:()=>q4,bincountImpl:()=>i3,bincountReduceImpl:()=>X4,castImpl:()=>j4,ceilImpl:()=>K4,concatImpl:()=>o3,equalImpl:()=>Z4,expImpl:()=>J4,expm1Impl:()=>e7,floorImpl:()=>t7,gatherNdImpl:()=>a7,gatherV2Impl:()=>n7,greaterEqualImpl:()=>s7,greaterImpl:()=>r7,lessEqualImpl:()=>o7,lessImpl:()=>i7,linSpaceImpl:()=>l7,logImpl:()=>u7,maxImpl:()=>d7,maximumImpl:()=>p7,minimumImpl:()=>c7,multiplyImpl:()=>l3,negImpl:()=>h7,notEqualImpl:()=>f7,prodImpl:()=>m7,raggedGatherImpl:()=>g7,raggedRangeImpl:()=>x7,raggedTensorToTensorImpl:()=>A7,rangeImpl:()=>d3,rsqrtImpl:()=>y7,scatterImpl:()=>tl,sigmoidImpl:()=>bO,simpleAbsImpl:()=>H4,sliceImpl:()=>_c,sparseFillEmptyRowsImpl:()=>v7,sparseReshapeImpl:()=>w7,sparseSegmentReductionImpl:()=>p3,sqrtImpl:()=>kO,squaredDifferenceImpl:()=>k7,stridedSliceImpl:()=>I7,stringNGramsImpl:()=>c3,stringSplitImpl:()=>h3,stringToHashBucketFastImpl:()=>f3,subImpl:()=>S7,tileImpl:()=>T7,topKImpl:()=>N7,transposeImpl:()=>u3,uniqueImpl:()=>E7});function H4(e){let t=new Float32Array(e.length);for(let a=0;a<e.length;++a)t[a]=Math.abs(e[a]);return t}var CF=e=>{let{x:t}=e.inputs,a=e.backend;ye(t,\"abs\");let n=new Float32Array(v.sizeFromShape(t.shape)),r=a.data.get(t.dataId).values;return n=H4(r),a.makeOutput(n,t.shape,t.dtype)},NF={kernelName:wl,backendName:\"cpu\",kernelFunc:CF};function Lt(e){return(t,a,n,r,s)=>{let i=T.assertAndGetBroadcastShape(t,a),o=i.length,l=v.computeStrides(i),u=v.sizeFromShape(i),p=v.getTypedArrayFromDType(s,u),c=t.length,d=a.length,h=v.computeStrides(t),f=v.computeStrides(a),m=T.getBroadcastDims(t,i),g=T.getBroadcastDims(a,i);if(m.length+g.length===0)for(let x=0;x<p.length;++x)p[x]=e(n[x%n.length],r[x%r.length]);else for(let x=0;x<p.length;++x){let A=v.indexToLoc(x,o,l),y=A.slice(-c);m.forEach(C=>y[C]=0);let b=v.locToIndex(y,c,h),w=A.slice(-d);g.forEach(C=>w[C]=0);let S=v.locToIndex(w,d,f);p[x]=e(n[b],r[S])}return[p,i]}}function Xa(e){let{inputs:t,backend:a}=e,{real:n,imag:r}=t,s=a.data.get(n.dataId).values,i=a.data.get(r.dataId).values,o=a.makeTensorInfo(n.shape,\"complex64\"),l=a.data.get(o.dataId);return l.complexTensorInfos={real:a.makeTensorInfo(n.shape,\"float32\",s),imag:a.makeTensorInfo(r.shape,\"float32\",i)},o}var EF={kernelName:Sd,backendName:\"cpu\",kernelFunc:Xa};function $c(e,t,a=\"float32\"){if(a===\"complex64\"){let r=$c(e,t,\"float32\"),s=$c(e,t,\"float32\");return Xa({inputs:{real:r,imag:s},backend:e})}let n=v.makeZerosTypedArray(v.sizeFromShape(t),a);return e.makeTensorInfo(t,a,n)}function er(e){let{inputs:t,backend:a}=e,{x:n}=t;return a.incRef(n.dataId),{dataId:n.dataId,shape:n.shape,dtype:n.dtype}}var RF={kernelName:ki,backendName:\"cpu\",kernelFunc:er};function Us(e){let{inputs:t,backend:a}=e,{input:n}=t,r=a.data.get(n.dataId).complexTensorInfos.real,s=a.data.get(r.dataId).values;return a.makeTensorInfo(r.shape,r.dtype,s)}var MF={kernelName:Md,backendName:\"cpu\",kernelFunc:Us};function j4(e,t,a,n){if(n===\"int32\"){let r=Int32Array.from(e);return[t,\"int32\",r]}if(n===\"bool\"){let r=v.toTypedArray([0],a),[s,i]=Lt((o,l)=>o!==l?1:0)(t,[],e,r,\"bool\");return[i,\"bool\",s]}throw new Error(`Error in Cast: failed to cast ${a} to ${n}`)}function Jr(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{dtype:s}=n;if(s===\"complex64\"){if(r.dtype===\"complex64\")return er({inputs:{x:r},backend:a});let p=$c(a,r.shape,r.dtype),c=Jr({inputs:{x:r},backend:a,attrs:{dtype:\"float32\"}}),d=Xa({inputs:{real:c,imag:p},backend:a});return a.disposeIntermediateTensorInfo(p),a.disposeIntermediateTensorInfo(c),d}if(r.dtype===\"complex64\"){let p=Us({inputs:{input:r},backend:a}),c=Jr({inputs:{x:p},backend:a,attrs:{dtype:s}});return a.disposeIntermediateTensorInfo(p),c}if(!v.hasEncodingLoss(r.dtype,s)){let p=er({inputs:{x:r},backend:a});return{dataId:p.dataId,shape:p.shape,dtype:s}}let i=a.data.get(r.dataId).values,[o,l,u]=j4(i,r.shape,r.dtype,s);return a.makeTensorInfo(o,l,u)}var $F={kernelName:ti,backendName:\"cpu\",kernelFunc:Jr};function Yt(e,t,a,n){return a==null?({inputs:r,backend:s})=>{let{a:i,b:o}=r,l=s;ye([i,o],e);let u=l.data.get(i.dataId).values,p=l.data.get(o.dataId).values,c=i.dtype===\"string\"?T.fromUint8ToStringArray(u):u,d=i.dtype===\"string\"?T.fromUint8ToStringArray(p):p,h=n||i.dtype,[f,m]=t(i.shape,o.shape,c,d,h);return l.makeTensorInfo(m,h,f)}:({inputs:r,backend:s})=>{let{a:i,b:o}=r,l=s;if(i.dtype===\"complex64\"||o.dtype===\"complex64\"){let u=Jr({inputs:{x:i},backend:l,attrs:{dtype:\"complex64\"}}),p=l.data.get(u.dataId),c=p.complexTensorInfos.real,d=p.complexTensorInfos.imag,h=l.data.get(c.dataId).values,f=l.data.get(d.dataId).values,m=Jr({inputs:{x:o},backend:l,attrs:{dtype:\"complex64\"}}),g=l.data.get(m.dataId),x=g.complexTensorInfos.real,A=g.complexTensorInfos.imag,y=l.data.get(x.dataId).values,b=l.data.get(A.dataId).values,[w,S,C]=a(i.shape,o.shape,h,f,y,b),E=l.makeTensorInfo(C,\"float32\",w),_=l.makeTensorInfo(C,\"float32\",S),$=Xa({inputs:{real:E,imag:_},backend:l});return l.disposeIntermediateTensorInfo(u),l.disposeIntermediateTensorInfo(m),l.disposeIntermediateTensorInfo(E),l.disposeIntermediateTensorInfo(_),$}else{let u=l.data.get(i.dataId).values,p=l.data.get(o.dataId).values,c=n||i.dtype,[d,h]=t(i.shape,o.shape,u,p,c);return l.makeTensorInfo(h,c,d)}}}function s3(e){return(t,a,n,r,s,i)=>{let o=T.assertAndGetBroadcastShape(t,a),l=v.sizeFromShape(o),u=o.length,p=v.computeStrides(o),c=v.getTypedArrayFromDType(\"float32\",l),d=v.getTypedArrayFromDType(\"float32\",l),h=T.getBroadcastDims(t,o),f=T.getBroadcastDims(a,o),m=T.mergeRealAndImagArrays(n,r),g=T.mergeRealAndImagArrays(s,i),x=t.length,A=v.computeStrides(t),y=a.length,b=v.computeStrides(a);if(h.length+f.length===0)for(let w=0;w<c.length;w++){let S=w%m.length,C=w%g.length,E=e(m[S*2],m[S*2+1],g[C*2],g[C*2+1]);c[w]=E.real,d[w]=E.imag}else for(let w=0;w<c.length;w++){let S=v.indexToLoc(w,u,p),C=S.slice(-x);h.forEach(I=>C[I]=0);let E=v.locToIndex(C,x,A),_=S.slice(-y);f.forEach(I=>_[I]=0);let $=v.locToIndex(_,y,b),M=e(m[E*2],m[E*2+1],g[$*2],g[$*2+1]);c[w]=M.real,d[w]=M.imag}return[c,d,o]}}var q4=Lt((e,t)=>e+t),_F=s3((e,t,a,n)=>({real:e+a,imag:t+n})),ml=Yt(ts,q4,_F),PF={kernelName:ts,backendName:\"cpu\",kernelFunc:ml};function i3(e,t,a,n,r){let s=v.sizeFromShape(n),i=v.makeZerosTypedArray(r,a);for(let o=0;o<e.length;o++){let l=e[o];if(l<0)throw new Error(\"Input x must be non-negative!\");l>=r||(s>0?i[l]+=t[o]:i[l]+=1)}return i}function X4(e,t,a,n=!1){let r=e.shape[0],s=e.shape[1],i=Me([r,a],t.dtype);for(let o=0;o<r;o++)for(let l=0;l<s;l++){let u=e.get(o,l);if(u<0)throw new Error(\"Input x must be non-negative!\");u>=a||(n?i.set(1,o,u):t.size>0?i.set(i.get(o,u)+t.get(o,l),o,u):i.set(i.get(o,u)+1,o,u))}return i}function os(e){return(t,a,n)=>{let r=v.getTypedArrayFromDType(a,t.length);for(let s=0;s<t.length;++s)r[s]=e(t[s],n);return r}}function ot(e,t,a){return({inputs:n,attrs:r,backend:s})=>{let{x:i}=n;if(ye(i,e),i.dtype===\"string\"||a===\"string\")throw new Error(\"unaryKernelFunc does not support string input/output\");let o=s,l=o.data.get(i.dataId).values,u=v.sizeFromShape(i.shape),p=a||i.dtype,c=v.getArrayFromDType(p,u);for(let d=0;d<u;++d)c[d]=t(l[d],r);return o.makeTensorInfo(i.shape,p,c)}}function ou(e,t,a){return({inputs:n,attrs:r,backend:s})=>{let{x:i}=n;if(ye(i,e),i.dtype===\"string\"||a===\"string\")throw new Error(\"unaryKernelFunc does not support string input/output\");let o=s,l=o.data.get(i.dataId).values,u=a||i.dtype,p=t(l,u,r);return o.makeTensorInfo(i.shape,u,p)}}var K4=os(e=>Math.ceil(e)),FF=ou(ai,K4),OF={kernelName:ai,backendName:\"cpu\",kernelFunc:FF};function o3(e,t,a,n){let r=v.getArrayFromDType(a,v.sizeFromShape(t));if(n&&a!==\"string\"){let s=0;e.forEach(i=>{let o=v.sizeFromShape(i.shape);r.set(i.vals,s),s+=o})}else{let s=0;e.forEach(i=>{let o=a===\"string\"?T.fromUint8ToStringArray(i.vals):i.vals,l=0;for(let u=0;u<i.shape[0];++u){let p=u*t[1]+s;for(let c=0;c<i.shape[1];++c)r[p+c]=o[l++]}s+=i.shape[1]})}return r}var Z4=Lt((e,t)=>e===t?1:0),Y4=Yt(fi,Z4,null,\"bool\"),DF={kernelName:fi,backendName:\"cpu\",kernelFunc:Y4},J4=os(e=>Math.exp(e)),Q4=ou(mi,J4,\"float32\"),zF={kernelName:mi,backendName:\"cpu\",kernelFunc:Q4},e7=os(e=>Math.expm1(e)),LF=ou(Pl,e7),BF={kernelName:Pl,backendName:\"cpu\",kernelFunc:LF},t7=os(e=>Math.floor(e)),WF=ou(xi,t7),VF={kernelName:xi,backendName:\"cpu\",kernelFunc:WF};function a7(e,t,a,n,r,s,i,o,l){let u=Me([n,s],a);for(let p=0;p<n;p++){let c=[],d=0;for(let h=0;h<r;h++){let f=e[p*r+h];d+=f*i[h],c.push(f)}if(d<0||d>=l/s)throw new Error(`Invalid indices: ${c} does not index into ${o}`);for(let h=0;h<s;h++)u.values[p*s+h]=t.get(...t.indexToLoc(d*s+h))}return u}function n7(e,t,a){let n=Me(a,e.dtype);for(let r=0;r<n.size;++r){let s=n.indexToLoc(r).slice(),i=s[0],o=s[2],l=t.locToIndex([i,o]);s[2]=t.values[l];let u=e.locToIndex(s);0<=u&&u<e.values.length&&(n.values[r]=e.values[u])}return n}var r7=Lt((e,t)=>e>t?1:0),UF=Yt(vi,r7,null,\"bool\"),GF={kernelName:vi,backendName:\"cpu\",kernelFunc:UF},s7=Lt((e,t)=>e>=t?1:0),HF=Yt(wi,s7,null,\"bool\"),jF={kernelName:wi,backendName:\"cpu\",kernelFunc:HF},i7=Lt((e,t)=>e<t?1:0),qF=Yt(Ti,i7,null,\"bool\"),XF={kernelName:Ti,backendName:\"cpu\",kernelFunc:qF},o7=Lt((e,t)=>e<=t?1:0),KF=Yt(Ci,o7,null,\"bool\"),ZF={kernelName:Ci,backendName:\"cpu\",kernelFunc:KF};function l7(e,t,a){let n=(t-e)/(a-1),r=v.makeZerosTypedArray(a,\"float32\");r[0]=e;for(let s=1;s<r.length;s++)r[s]=r[s-1]+n;return r}var u7=os(e=>Math.log(e)),YF=ou(Ni,u7),JF={kernelName:Ni,backendName:\"cpu\",kernelFunc:YF};function d7(e,t,a,n){let r=v.getTypedArrayFromDType(n,v.sizeFromShape(a));for(let s=0;s<r.length;++s){let i=s*t,o=e[i];for(let l=0;l<t;++l){let u=e[i+l];(Number.isNaN(u)||u>o)&&(o=u)}r[s]=o}return r}var p7=Lt((e,t)=>Math.max(e,t)),QF=Yt($i,p7),eO={kernelName:$i,backendName:\"cpu\",kernelFunc:QF},c7=Lt((e,t)=>Math.min(e,t)),tO=Yt(Oi,c7),aO={kernelName:Oi,backendName:\"cpu\",kernelFunc:tO},l3=Lt((e,t)=>e*t),nO=s3((e,t,a,n)=>({real:e*a-t*n,imag:e*n+t*a})),Ph=Yt(zi,l3,nO),rO={kernelName:zi,backendName:\"cpu\",kernelFunc:Ph};function h7(e,t,a){let n=v.createScalarValue(-1,a);return l3([],t,n,e,a)}function sO(e){let{inputs:t,backend:a}=e,{x:n}=t;ye(n,\"neg\");let r=a.data.get(n.dataId).values,[s,i]=h7(r,n.shape,n.dtype);return a.makeTensorInfo(i,n.dtype,s)}var iO={kernelName:Vl,backendName:\"cpu\",kernelFunc:sO},f7=Lt((e,t)=>e!==t?1:0),oO=Yt(Li,f7,null,\"bool\"),lO={kernelName:Li,backendName:\"cpu\",kernelFunc:oO};function u3(e,t,a,n,r){let s=t.length,i=v.sizeFromShape(t),o=v.computeStrides(t),l=v.computeStrides(r),u=v.getTypedArrayFromDType(a,v.sizeFromShape(r));for(let p=0;p<i;++p){let c=v.indexToLoc(p,s,o),d=new Array(c.length);for(let f=0;f<d.length;f++)d[f]=c[n[f]];let h=v.locToIndex(d,s,l);u[h]=e[p]}return u}function La(e){let{inputs:t,attrs:a,backend:n}=e,{x:r}=t,{perm:s}=a;ye(r,\"transpose\");let i=r.shape.length,o=new Array(i);for(let p=0;p<o.length;p++)o[p]=r.shape[s[p]];let l=n.data.get(r.dataId).values,u=u3(l,r.shape,r.dtype,s,o);return{dataId:n.write(u,o,r.dtype),shape:o,dtype:r.dtype}}var uO={kernelName:Ar,backendName:\"cpu\",kernelFunc:La};function m7(e,t,a,n){let[r,s]=T.computeOutAndReduceShapes(e,n),i=ca(t,\"int32\"),o=v.makeZerosTypedArray(v.sizeFromShape(r),i),l=v.sizeFromShape(s);for(let u=0;u<o.length;++u){let p=u*l,c=1;for(let d=0;d<l;++d)c*=a[p+d];o[u]=c}return{outVals:o,outShape:r,outDtype:i}}function dO(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;ye(r,\"prod\");let o=r.shape.length,l=v.parseAxisParam(s,r.shape),u=T.getAxesPermutation(l,o),p=l,c=r,d=[];u!=null&&(c=La({inputs:{x:r},backend:a,attrs:{perm:u}}),d.push(c),p=T.getInnerMostAxes(p.length,o));let h=a.data.get(c.dataId).values,{outVals:f,outShape:m,outDtype:g}=m7(c.shape,c.dtype,h,p),x=m;return i&&(x=T.expandShapeToKeepDim(m,l)),d.forEach(A=>a.disposeIntermediateTensorInfo(A)),a.makeTensorInfo(x,g,f)}var pO={kernelName:ji,backendName:\"cpu\",kernelFunc:dO};function cO(e,t,a){e.forEach((n,r)=>{if(n<0||n>=a){let s=v.indexToLoc(r,t.length,v.computeStrides(t)).join(\",\");throw new Error(`indices[${s}] = ${n} is not in [0, ${a})`)}})}function hO(e,t){for(let a=0;a<e.length;++a){let n=e[a],r=a===e.length-1?t:e[a+1].length;if(n.length===0)throw new Error(\"Ragged splits may not be empty\");if(n[0]<0)throw new Error(\"Ragged splits must be non-negative\");if(n[n.length-1]>r)throw new Error(\"Ragged splits must not point past values\");for(let s=1;s<n.length;++s)if(n[s-1]>n[s])throw new Error(\"Ragged splits must be sorted in ascending order\")}}function fO(e,t,a,n){let r=[],s=0,i=t.length-1+a.length,o=new Array(i).fill(null).map(()=>[0]);hO(a,n);let l=1;for(let u=0;u<t.length-1;++u){l*=t[u];let p=t[u+1];for(let c=1;c<l+1;++c)o[u].push(c*p)}for(let u=0;u<e.length;++u){let p=e[u],c=e[u]+1;for(let d=0;d<a.length;++d){let h=a[d],f=d+t.length-1;if(f>=0){let m=o[f],g=m[m.length-1]-h[p];for(let x=p;x<c;++x)o[f].push(h[x+1]+g)}p=h[p],c=h[c]}c!==p&&(r.push([p,c]),s+=c-p)}return{outSplits:o,valueSlices:r,numValues:s}}function mO(e){let t=[];for(let a=0;a<e.length;++a){let n=e[a].length,r=v.getArrayFromDType(\"int32\",n);t.push(r),e[a].forEach((s,i)=>r[i]=s)}return t}function ix(e,t){let a=e.slice(0,t);for(;a.length<t;)a.push(1);for(let n=t;n<e.length;n++)a[t-1]*=e[n];return a}function gO(e,t,a,n,r,s){let i=ix(t,2)[1],o=ix(s,2)[1],l=0;for(let u of a)for(let p=u[0];p<u[1];++p){for(let c=0;c<n;++c)r[l*o+c]=e[p*i+c];++l}}function xO(e,t,a,n,r){let s=t.slice();s[0]=r;let i=v.getArrayFromDType(a,v.sizeFromShape(s)),o=e.length,l=o===0?0:o/t[0];return gO(e,t,n,l,i,s),[i,s]}function g7(e,t,a,n,r,s,i,o){if(e.length===0)throw new Error(\"paramsNestedSplits must be non empty\");if(t[0].length===0)throw new Error(\"Split tensors must not be scalars\");let l=t[0][0]-1;if(cO(s,i,l),n.length===0)throw new Error(\"params.rank must be nonzero\");let u=n[0],{outSplits:p,valueSlices:c,numValues:d}=fO(s,i,e,u),h=mO(p),f=xO(a,n,r,c,d);return[h,f[0],f[1]]}var ox=2147483647;function x7(e,t,a,n,r,s,i){if(t.length>1)throw new Error(\"starts must be a scalar or vector\");if(r.length>1)throw new Error(\"limits must be a scalar or vector\");if(i.length>1)throw new Error(\"deltas must be a scalar or vector\");let o=t.length===0,l=r.length===0,u=i.length===0,p=[];o||p.push(t[0]),l||p.push(r[0]),u||p.push(i[0]);for(let g=1;g<p.length;++g)if(p[g]!==p[g-1])throw new Error(\"starts, limits, and deltas must have the same shape\");let c=p.length===0?1:p[0],d=v.getArrayFromDType(\"int32\",c+1);d[0]=0;for(let g=0;g<c;++g){let x=o?e[0]:e[g],A=l?n[0]:n[g],y=u?s[0]:s[g];if(y===0)throw new Error(\"Requires delta != 0\");let b;if(y>0&&A<x||y<0&&A>x)b=0;else if(b=Math.ceil(Math.abs((A-x)/y)),b>ox)throw new Error(`Requires ((limit - start) / delta) <= ${ox}`);d[g+1]=d[g]+b}let h=d[c],f=v.getArrayFromDType(a,h),m=0;for(let g=0;g<c;++g){let x=d[g+1]-d[g],A=o?e[0]:e[g],y=u?s[0]:s[g];for(let b=0;b<x;++b)f[m++]=A,A+=y}return[d,f]}var vn=T.RowPartitionType,y1=class{constructor(e,t,a,n,r,s,i,o,l,u){this.shape=e,this.shapeShape=t,this.values=a,this.valuesShape=n,this.valuesDType=r,this.defaultValue=s,this.defaultValueShape=i,this.rowPartitionValues=o,this.rowPartitionValuesShapes=l,this.rowPartitionTypes=T.getRowPartitionTypesHelper(u),this.raggedRank=T.getRaggedRank(this.rowPartitionTypes)}getRowPartitionTypeByDimension(e){return this.rowPartitionTypes[0]===vn.FIRST_DIM_SIZE?this.rowPartitionTypes[e+1]:this.rowPartitionTypes[e]}getRowPartitionTensor(e){return this.rowPartitionTypes[0]===vn.FIRST_DIM_SIZE?this.rowPartitionValues[e+1]:this.rowPartitionValues[e]}getMaxWidth(e){let t=this.getRowPartitionTensor(e-1);switch(this.getRowPartitionTypeByDimension(e-1)){case vn.VALUE_ROWIDS:return y1.getMaxWidthValueRowID(t);case vn.ROW_SPLITS:return y1.getMaxWidthRowSplit(t);default:throw new Error(`Cannot handle partition type ${vn[this.getRowPartitionTypeByDimension(e-1)]}`)}}static getMaxWidthRowSplit(e){let t=e.length;if(t===0||t===1)return 0;let a=0;for(let n=0;n<t-1;++n){let r=e[n+1]-e[n];r>a&&(a=r)}return a}static getMaxWidthValueRowID(e){let t=e.length;if(t===0)return 0;let a=0,n=e[0],r=0;for(let s=1;s<t;++s){let i=e[s];i!==n&&(n=i,r=Math.max(s-a,r),a=s)}return Math.max(t-a,r)}tensorShapeFromTensor(e,t,a=!0){if(t.length===0){if(e[0]===-1)return[];throw new Error(\"The only valid scalar shape tensor is the fully unknown shape specified as -1.\")}return ux(e,a)}calculateOutputSize(e){let t=this.valuesShape,a=this.defaultValueShape;T.validateDefaultValueShape(a,t);let n=this.tensorShapeFromTensor(this.shape,this.shapeShape),r=T.combineRaggedTensorToTensorShapes(this.raggedRank,n,t);r[0]<0&&(r[0]=e);for(let s=1;s<=this.raggedRank;++s)r[s]<0&&(r[s]=this.getMaxWidth(s));return r}calculateFirstParentOutputIndex(e,t,a){let n=Math.min(e,a),r=[],s=0;for(let i=0;i<n;++i,s+=t)r.push(s);for(let i=n;i<e;++i)r.push(-1);return v.assert(r.length===e,()=>\"Final length of result must be equal to firstDimension.\"),r}calculateOutputIndexRowSplit(e,t,a,n){let r=e.length,s=[];for(let i=0;i<r-1;++i){let o=e[i+1]-e[i],l=Math.min(n,o),u=t[i];u===-1&&(l=0);for(let p=0;p<l;++p)s.push(u),u+=a;for(let p=0;p<o-l;++p)s.push(-1)}if(r>0&&s.length!==e[r-1])throw new Error(\"Invalid row split size.\");return s}calculateOutputIndexValueRowID(e,t,a,n){let r=e.length,s=[];if(r===0)return[];let i=0,o=e[0];if(o>=t.length)throw new Error(`Got currentValueRowId=${o}, which is not less than ${t.length}`);let l=t[o];s.push(l);for(let u=1;u<r;++u){let p=e[u];if(p===o)l>=0&&(++i,i<n?l+=a:l=-1);else{if(i=0,o=p,p>=t.length)throw new Error(`Got nextValueRowId=${p} which is not less than ${t.length}`);l=t[p]}s.push(l)}if(s.length!==e.length)throw new Error(\"Invalid row ids.\");return s}calculateOutputIndex(e,t,a,n){let r=this.getRowPartitionTensor(e),s=this.getRowPartitionTypeByDimension(e);switch(s){case vn.VALUE_ROWIDS:return this.calculateOutputIndexValueRowID(r,t,a,n);case vn.ROW_SPLITS:if(r.length-1>t.length)throw new Error(`Row partition size is greater than output size: ${r.length-1} > ${t.length}`);return this.calculateOutputIndexRowSplit(r,t,a,n);default:throw new Error(`Unsupported partition type: ${vn[s]}`)}}getFirstDimensionSize(){let e=this.rowPartitionValues[0];if(this.rowPartitionTypes.length===0)throw new Error(\"No row_partition_types given.\");let t=this.rowPartitionTypes[0];switch(t){case vn.FIRST_DIM_SIZE:return e[0];case vn.VALUE_ROWIDS:throw new Error(\"Cannot handle VALUE_ROWIDS in first dimension.\");case vn.ROW_SPLITS:return this.rowPartitionValuesShapes[0][0]-1;default:throw new Error(`Cannot handle type ${vn[t]}`)}}compute(){if(this.rowPartitionValues[0].length<=0)throw new Error(\"Invalid first partition input. Tensor requires at least one element.\");let e=this.getFirstDimensionSize(),t=this.calculateOutputSize(e),a=new Array(this.raggedRank+1);a[a.length-1]=1;for(let s=a.length-2;s>=0;--s)a[s]=a[s+1]*t[s+1];let n=ux(t,!1),r=v.getArrayFromDType(this.valuesDType,v.sizeFromShape(n));if(a[0]*t[0]>0){let s=this.calculateFirstParentOutputIndex(e,a[0],t[0]);for(let i=1;i<=this.raggedRank;++i)s=this.calculateOutputIndex(i-1,s,a[i],t[i]);this.setOutput(this.raggedRank,s,r,n)}return[n,r]}setOutput(e,t,a,n){if(a.length===0)return;let r=this.values,s=a,i=n.slice();i=i.slice(e+1);let o=v.sizeFromShape(i),l=t.length,u=this.defaultValue;if(u.length!==o&&u.length!==1){let h=this.defaultValueShape;$e(()=>{let f=J(u,h);u=sl(f,i).dataSync()})}let p=0,c=0,d=0;for(let h=0;h<=l;++h){let f=h<l?t[h]:-1;if(f===d){++d;continue}if(c<d){let m=r.subarray(p*o),g=s.subarray(c*o),x=(d-c)*o;lx(g,m,x)}if(h>=l){let m=a.length;f=Math.floor(m/o)}if(f>d)if(this.defaultValue.length===1)s.subarray(d*o,f*o).fill(this.defaultValue[0]),d=f;else for(;f>d;){let m=s.slice(d*o);lx(m,u,o),++d}f<0?(p=h+1,c=d):(p=h,c=d,d=c+1)}}};function lx(e,t,a){for(let n=0;n<a;n++)e[n]=t[n]}function ux(e,t){let a=[];for(let n of e){if(n<0){if(!t)throw new Error(`Dimension ${n} must be >= 0`);if(n<-1)throw new Error(`Dimension ${n} must be >= -1`);n=-1}a.push(n)}return a}function A7(e,t,a,n,r,s,i,o,l,u){return new y1(e,t,a,n,r,s,i,o,l,u).compute()}function d3(e,t,a,n){let r=e===t,s=e<t&&a<0,i=t<e&&a>1;if(r||s||i)return v.makeZerosTypedArray(0,n);let o=Math.abs(Math.ceil((t-e)/a)),l=v.makeZerosTypedArray(o,n);t<e&&a===1&&(a=-1),l[0]=e;for(let u=1;u<l.length;u++)l[u]=l[u-1]+a;return l}var y7=os(e=>1/Math.sqrt(e)),AO=ou(Qi,y7),yO={kernelName:Qi,backendName:\"cpu\",kernelFunc:AO};function tl(e,t,a,n,r,s,i,o,l,u){let p=[n/r,r],c=e.values,d=t.values;if(n===0)return Me(a,t.dtype);let h=Me(p,t.dtype);typeof l==\"string\"||typeof l==\"number\"?h.values.fill(l):typeof l==\"boolean\"&&h.values.fill(+l);for(let f=0;f<s;f++){let m=[],g=0;for(let x=0;x<i;x++){let A=c[f*i+x];m.push(A),g+=A*o[x]}if(g<0||g>=n/r)throw new Error(`Invalid indices: ${m} does not index into ${a}`);for(let x=0;x<r;x++)u?h.values[g*r+x]+=d[f*r+x]:h.values[g*r+x]=t.rank===0?d[0]:d[f*r+x]}return h}var bO=os(e=>1/(1+Math.exp(-e))),b7=ot(ao,e=>1/(1+Math.exp(-e))),vO={kernelName:ao,backendName:\"cpu\",kernelFunc:b7};function _c(e,t,a,n,r){let s=It.isSliceContinous(n,t,a),i=v.sizeFromShape(a),o=v.computeStrides(n);if(s){let c=It.computeFlatOffset(t,o);return r===\"string\"?e.slice(c,c+i):e.subarray(c,c+i)}let l=r===\"string\"?T.fromUint8ToStringArray(e):e,u=Me(n,r,l),p=Me(a,r);for(let c=0;c<p.size;++c){let d=p.indexToLoc(c),h=d.map((f,m)=>f+t[m]);p.set(u.get(...h),...d)}return r===\"string\"?T.fromStringArrayToUint8(p.values):p.values}function Gs(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{begin:s,size:i}=n;ye(r,\"slice\");let[o,l]=It.parseSliceParams(r,s,i);It.assertParamsValid(r,o,l);let u=a.data.get(r.dataId).values,p=_c(u,o,l,r.shape,r.dtype);return a.makeTensorInfo(l,r.dtype,p)}var wO={kernelName:Zl,backendName:\"cpu\",kernelFunc:Gs};function v7(e,t,a,n,r,s,i){let o=t[0],l=s[0],u=new Array(l),p=new Array(o),c=t[1];if(l===0){if(o!==0)throw new Error(T.getSparseFillEmptyRowsIndicesDenseShapeMismatch(o));let g=v.getArrayFromDType(a,0),x=v.getArrayFromDType(r,0);return[g,[0,c],x,u,p]}let d=!0,h=0,f=new Array(l).fill(0);for(let g=0;g<o;++g){let x=e[g*c];if(x<0)throw new Error(T.getSparseFillEmptyRowsNegativeIndexErrorMessage(g,x));if(x>=l)throw new Error(T.getSparseFillEmptyRowsOutOfRangeIndexErrorMessage(g,x,l));++f[x],d=d&&x>=h,h=x}let m=!0;for(let g=0;g<l;++g){let x=f[g]===0;u[g]=x,m=m&&!x,f[g]=Math.max(f[g],1),g>0&&(f[g]+=f[g-1])}if(m&&d){let g=e,x=n;for(let A=0;A<o;++A)p[A]=A;return[g,[o,c],x,u,p]}else{let g=f[l-1],x=v.getArrayFromDType(a,g*c),A=v.getArrayFromDType(r,g),y=new Array(l).fill(0);for(let b=0;b<o;++b){let w=e[b*c],S=y[w],C=(w===0?0:f[w-1])+S;y[w]++;for(let E=0;E<c;++E)x[C*c+E]=e[b*c+E];A[C]=n[b],p[b]=C}for(let b=0;b<l;++b)if(y[b]===0){let w=b===0?0:f[b-1];x[w*c+0]=b;for(let S=1;S<c;++S)x[w*c+S]=0;A[w]=i}return[x,[g,c],A,u,p]}}function w7(e,t,a,n,r){let s=v.sizeFromShape(n),i=t[0],o=r.length,l=[],u=1,p=-1;for(let m=0;m<o;++m){let g=r[m];if(g===-1){if(p!==-1)throw new Error(T.getSparseReshapeMultipleNegativeOneOutputDimErrorMessage(p,m));p=m,l.push(1)}else{if(g<0)throw new Error(T.getSparseReshapeNegativeOutputDimErrorMessage(m,g));u*=g,l.push(g)}}if(p!==-1){if(u<=0)throw new Error(T.getSparseReshapeEmptyTensorZeroOutputDimErrorMessage());let m=Math.trunc(s/u);if(u*m!==s)throw new Error(T.getSparseReshapeInputOutputMultipleErrorMessage(n,l));l[p]=m}if(v.sizeFromShape(l)!==s)throw new Error(T.getSparseReshapeInputOutputMismatchErrorMessage(n,l));let c=n.length,d=[];if(c>0){d[c-1]=1;for(let m=c-2;m>=0;--m)d[m]=d[m+1]*n[m+1]}let h=[];if(o>0){h[o-1]=1;for(let m=o-2;m>=0;--m)h[m]=h[m+1]*l[m+1]}let f=v.getArrayFromDType(a,i*o);for(let m=0;m<i;++m){let g=0;for(let x=0;x<c;++x)g+=e[m*c+x]*d[x];for(let x=0;x<o;++x)f[m*o+x]=Math.trunc(g/h[x]),g%=h[x]}return[f,[i,o],l]}function p3(e,t,a,n,r,s=!1,i=0){let o=n.length,l=[t[0],e.length/t[0]],u=l[1],p=o>0?r[o-1]+1:0;if(p<0)throw new Error(T.getSparseSegmentReductionNegativeSegmentIdsErrorMessage());let c=t.slice();c[0]=p;let d=c.reduce((A,y)=>A*y,1),h=v.getArrayFromDType(a,d);if(o===0)return p>0&&h.fill(i),[h,c];if(p<=0)throw new Error(T.getSparseSegmentReductionNegativeSegmentIdsErrorMessage());let f=0,m=1,g=0,x=r[f];for(;;){let A=0;if(m<o){if(A=r[m],x===A){++m;continue}if(x>=A)throw new Error(T.getSparseSegmentReductionNonIncreasingSegmentIdsErrorMessage())}if(x<0||x>=p)throw new Error(T.getSparseSegmentReductionSegmentIdOutOfRangeErrorMessage(x,p));x>g&&h.fill(i,g*u,x*u);for(let y=f;y<m;++y){let b=n[y];if(b<0||b>=l[0])throw new Error(T.getSparseSegmentReductionIndicesOutOfRangeErrorMessage(y,n[y],l[0]));for(let w=0;w<u;w++)h[x*u+w]+=e[b*u+w]}if(s)for(let y=0;y<u;y++)h[x*u+y]/=m-f;if(f=m,++m,g=x+1,x=A,m>o)break}return g<p&&h.fill(i,g*u,p*u),[h,c]}var kO=os(e=>Math.sqrt(e)),IO=ot(no,e=>Math.sqrt(e)),SO={kernelName:no,backendName:\"cpu\",kernelFunc:IO},k7=Lt((e,t)=>{let a=e-t;return a*a}),TO=Yt(io,k7),CO={kernelName:io,backendName:\"cpu\",kernelFunc:TO};function I7(e,t,a,n){let r=Me(e,t.dtype);for(let s=0;s<r.size;s++){let i=r.indexToLoc(s),o=new Array(i.length);for(let l=0;l<o.length;l++)o[l]=i[l]*a[l]+n[l];r.set(t.get(...o),...i)}return r}var NO=class{constructor(e,t,a,n,r,s){this.separator=v.encodeString(e),this.nGramWidths=t,this.leftPad=v.encodeString(a),this.rightPad=v.encodeString(n),this.padWidth=r,this.preserveShort=s}getPadWidth(e){return Math.min(this.padWidth<0?e-1:this.padWidth,e-1)}getNumNGrams(e,t){let a=this.getPadWidth(t);return Math.max(0,e+2*a-t+1)}createNGrams(e,t,a,n,r,s){for(let i=0;i<r;++i){let o=this.getPadWidth(s),l=Math.max(0,o-i),u=Math.max(0,o-(r-(i+1))),p=s-(l+u),c=t+(l>0?0:i-o),d=0;d+=l*this.leftPad.length;for(let x=0;x<p;++x)d+=e[c+x].length;d+=u*this.rightPad.length;let h=l+u+p-1;d+=h*this.separator.length,a[n+i]=new Uint8Array(d);let f=a[n+i],m=0,g=x=>x.forEach(A=>f[m++]=A);for(let x=0;x<l;++x)g(this.leftPad),g(this.separator);for(let x=0;x<p-1;++x)g(e[c+x]),g(this.separator);if(p>0){g(e[c+p-1]);for(let x=0;x<u;++x)g(this.separator),g(this.rightPad)}else{for(let x=0;x<u-1;++x)g(this.rightPad),g(this.separator);g(this.rightPad)}}}compute(e,t){let a=e.length,n=t.length;if(n>0){let o=t[0];if(o!==0)throw new Error(`First split value must be 0, got ${o}`);for(let l=1;l<n;++l){let u=t[l]>=o;if(u=u&&t[l]<=a,!u)throw new Error(`Invalid split value ${t[l]}, must be in [${o}, ${a}]`);o=t[l]}if(o!==a)throw new Error(`Last split value must be data size. Expected ${a}, got ${o}`)}let r=n-1,s=v.getArrayFromDType(\"int32\",n);if(a===0||n===0){let o=new Array(a);for(let l=0;l<=r;++l)s[l]=0;return[o,s]}s[0]=0;for(let o=1;o<=r;++o){let l=t[o]-t[o-1],u=0;this.nGramWidths.forEach(p=>{u+=this.getNumNGrams(l,p)}),this.preserveShort&&l>0&&u===0&&(u=1),s[o]=s[o-1]+u}let i=new Array(s[r]);for(let o=0;o<r;++o){let l=t[o],u=s[o];if(this.nGramWidths.forEach(p=>{let c=t[o+1]-t[o],d=this.getNumNGrams(c,p);this.createNGrams(e,l,i,u,d,p),u+=d}),this.preserveShort&&u===s[o]){let p=t[o+1]-t[o];if(p===0)continue;let c=p+2*this.padWidth,d=1;this.createNGrams(e,l,i,u,d,c)}}return[i,s]}};function c3(e,t,a,n,r,s,i,o){return new NO(a,n,r,s,i,o).compute(e,t)}function EO(e,t,a,n){if(!e.length)return;if(t.length===0){for(let s=0;s<e.length;++s)n.push(e.subarray(s,s+1));return}if(t.length===1){let s=t[0],i=e.indexOf(s);for(;i!==-1;){let o=e.subarray(0,i);(!a||o.length!==0)&&n.push(o),e=e.subarray(i+1),i=e.indexOf(s)}(!a||e.length!==0)&&n.push(e);return}let r=0;for(let s=0;s<e.length+1;s++)if(s===e.length||t.indexOf(e[s])!==-1){let i=e.subarray(r,s);(!a||i.length!==0)&&n.push(i),r=s+1}}function h3(e,t,a){let n=e.length,r=[],s=0,i=0,o=new Array(n);for(let d=0;d<n;++d){let h=r.length;EO(e[d],t,a,r);let f=r.length-h;o[d]=f,s+=f,i=Math.max(i,f)}let l=v.getArrayFromDType(\"int32\",s*2),u=new Array(s),p=[n,i],c=0;for(let d=0;d<n;++d)for(let h=0;h<o[d];++h)l[c*2]=d,l[c*2+1]=h,u[c]=r[c],++c;return[l,u,p]}function f3(e,t){let a=v.getArrayFromDType(\"int32\",e.length);for(let n=0;n<e.length;++n)a[n]=v.fingerPrint64(e[n]).modulo(t).getLowBitsUnsigned();return a}var S7=Lt((e,t)=>e-t),RO=s3((e,t,a,n)=>({real:e-a,imag:t-n})),m3=Yt(lo,S7,RO),MO={kernelName:lo,backendName:\"cpu\",kernelFunc:m3};function T7(e,t){let a=new Array(e.rank);for(let r=0;r<a.length;r++)a[r]=e.shape[r]*t[r];let n=Me(a,e.dtype);for(let r=0;r<n.values.length;++r){let s=n.indexToLoc(r),i=new Array(e.rank);for(let l=0;l<i.length;l++)i[l]=s[l]%e.shape[l];let o=e.locToIndex(i);n.values[r]=e.values[o]}return n}var Hu=(e,t)=>{let a=t.value-e.value;return a===0?e.index-t.index:a};function C7(e,t,a=0,n=e.length-1){for(;n>a;){if(n-a>600){let o=n-a+1,l=t-a+1,u=Math.log(o),p=.5*Math.exp(2*u/3),c=.5*Math.sqrt(u*p*(o-p)/o)*Math.sign(l-o/2),d=Math.max(a,Math.floor(t-l*p/o+c)),h=Math.min(n,Math.floor(t+(o-l)*p/o+c));C7(e,t,d,h)}let r=e[t],s=a,i=n;for(v.swap(e,a,t),Hu(e[n],r)>0&&v.swap(e,a,n);s<i;){for(v.swap(e,s,i),s++,i--;Hu(e[s],r)<0;)s=s+1;for(;Hu(e[i],r)>0;)i=i-1}Hu(e[a],r)===0?v.swap(e,a,i):(i=i+1,v.swap(e,i,n)),i<=t&&(a=i+1),t<=i&&(n=i-1)}}function N7(e,t,a,n,r){let s=t[t.length-1],[i,o]=[e.length/s,s],l=v.getTypedArrayFromDType(a,i*n),u=v.getTypedArrayFromDType(\"int32\",i*n);for(let c=0;c<i;c++){let d=c*o,h=e.subarray(d,d+o),f=new Array(h.length);h.forEach((A,y)=>f[y]={value:A,index:y}),n<f.length&&(C7(f,n),f=f.slice(0,n)),r&&f.sort(Hu);let m=c*n,g=l.subarray(m,m+n),x=u.subarray(m,m+n);for(let A=0;A<n;A++)g[A]=f[A].value,x[A]=f[A].index}let p=t.slice();return p[p.length-1]=n,[Me(p,a,l),Me(p,\"int32\",u)]}function E7(e,t,a,n){let r=v.parseAxisParam(t,a)[0],s=[1,a[0],1];for(let f=0;f<r;f++)s[0]*=a[f];s[1]=a[r];for(let f=r+1;f<a.length;f++)s[2]*=a[f];let i={},o=new Int32Array(a[r]),l=new jt(s,n,e),u=[],p=s[0]===1&&s[2]===1;for(let f=0;f<a[r];f++){let m;if(p)m=e[f].toString();else{let g=[];for(let x=0;x<s[0];x++)for(let A=0;A<s[2];A++)g.push(l.get(x,f,A));m=g.join(\",\")}if(i[m]!==void 0)o[f]=i[m];else{let g=Object.keys(i).length;i[m]=g,o[f]=g,u.push(f)}}let c=s.slice();c[1]=Object.keys(i).length;let d=new jt(c,n);u.forEach((f,m)=>{for(let g=0;g<s[0];g++)for(let x=0;x<s[2];x++)d.set(l.get(g,f,x),g,m,x)});let h=a.slice();return h[r]=c[1],{outputValues:d.values,outputShape:h,indices:o}}var $O=\"4.1.0\";go(\"cpu\",()=>new $h,1);var R7=ot(hi,e=>e>=0?e:Math.exp(e)-1),_O={kernelName:hi,backendName:\"cpu\",kernelFunc:R7};function M7(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{alpha:s}=n;ye([r],\"leakyRelu\");let i=v.sizeFromShape(r.shape),o=a.data.get(r.dataId).values,l=v.getTypedArrayFromDType(\"float32\",i);for(let u=0;u<o.length;u++)l[u]=o[u]<0?s*o[u]:o[u];return a.makeTensorInfo(r.shape,\"float32\",l)}var PO={kernelName:Si,backendName:\"cpu\",kernelFunc:M7},FO=Lt((e,t)=>e<0?t*e:e);function $7(e){let{inputs:t,backend:a}=e,{x:n,alpha:r}=t;ye([n,r],\"prelu\");let s=a.data.get(n.dataId).values,i=a.data.get(r.dataId).values,[o,l]=FO(n.shape,r.shape,s,i,\"float32\");return a.makeTensorInfo(l,\"float32\",o)}var OO={kernelName:Hi,backendName:\"cpu\",kernelFunc:$7},_7=ot(Xi,e=>Math.max(0,e)),DO={kernelName:Xi,backendName:\"cpu\",kernelFunc:_7},P7=ot(Yi,e=>Math.min(Math.max(0,e),6)),zO={kernelName:Yi,backendName:\"cpu\",kernelFunc:P7};function Pc(e,t,a,n,r){if(a===\"linear\")return er({inputs:{x:t},backend:e});if(a===\"relu\")return _7({inputs:{x:t},backend:e});if(a===\"elu\")return R7({inputs:{x:t},backend:e});if(a===\"relu6\")return P7({inputs:{x:t},backend:e});if(a===\"prelu\")return $7({inputs:{x:t,alpha:n},backend:e});if(a===\"leakyrelu\")return M7({inputs:{x:t},backend:e,attrs:{alpha:r}});if(a===\"sigmoid\")return b7({inputs:{x:t},backend:e});throw new Error(`Activation ${a} has not been implemented for the CPU backend.`)}function mt(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{shape:s}=n,i=v.sizeFromShape(r.shape),o=v.inferFromImplicitShape(s,i),l=v.sizeFromShape(o);v.assert(i===l,()=>`The new shape (${o}) has ${l} elements and the old shape (${r.shape}) has ${i} elements. The new shape and old shape must have the same number of elements.`),a.incRef(r.dataId);let u=a.data.get(r.dataId);if(u.complexTensorInfos!=null){let p=u.complexTensorInfos.real,c=u.complexTensorInfos.imag;p.shape=o,c.shape=o}return{dataId:r.dataId,shape:o,dtype:r.dtype}}var LO={kernelName:ql,backendName:\"cpu\",kernelFunc:mt};function F7(e){let{inputs:t,backend:a,attrs:n}=e,{a:r,b:s}=t,{transposeA:i,transposeB:o}=n;ye([r,s],\"matMul\");let l=r.shape.length,u=s.shape.length,p=i?r.shape[l-2]:r.shape[l-1],c=o?s.shape[u-1]:s.shape[u-2],d=i?r.shape[l-1]:r.shape[l-2],h=o?s.shape[u-2]:s.shape[u-1],f=r.shape.slice(0,-2),m=s.shape.slice(0,-2),g=v.sizeFromShape(f),x=v.sizeFromShape(m),A=xo.assertAndGetBroadcastShape(r.shape.slice(0,-2),s.shape.slice(0,-2)).concat([d,h]);v.assert(p===c,()=>`Error in matMul: inner shapes (${p}) and (${c}) of Tensors with shapes ${r.shape} and ${s.shape} and transposeA=${i} and transposeB=${o} must match.`);let y=i?[g,p,d]:[g,d,p],b=o?[x,h,c]:[x,c,h],w=mt({inputs:{x:r},backend:a,attrs:{shape:y}}),S=mt({inputs:{x:s},backend:a,attrs:{shape:b}}),C=i?w.shape[1]:w.shape[2],E=i?w.shape[2]:w.shape[1],_=o?S.shape[1]:S.shape[2],$=Math.max(g,x),M=a.data.get(w.dataId).values,I=a.data.get(S.dataId).values,N=v.computeStrides(w.shape),O=v.computeStrides(S.shape),[L,B,G]=i?[N[0],1,N[1]]:[N[0],N[1],1],[j,U,H]=o?[1,O[1],O[0]]:[O[1],1,O[0]],V=E*_,Q=Me([$,E,_],w.dtype),Z=Q.values,re=a.blockSize;for(let ee=0;ee<$;ee++)for(let he=0;he<E;he+=re)for(let oe=0;oe<_;oe+=re)for(let Ae=0;Ae<C;Ae+=re){let we=Math.min(he+re,E),Re=Math.min(oe+re,_),Ge=Math.min(Ae+re,C);for(let Ke=he;Ke<we;Ke++)for(let nt=oe;nt<Re;nt++){let ut=0;for(let et=Ae;et<Ge;et++){let rt=Math.min(ee,g-1)*L,je=Math.min(ee,x-1)*H,ht=M[rt+Ke*B+et*G],Va=I[et*j+nt*U+je];ut+=ht*Va}Z[ee*V+(Ke*_+nt)]+=ut}}return a.disposeIntermediateTensorInfo(w),a.disposeIntermediateTensorInfo(S),a.makeTensorInfo(A,Q.dtype,Q.values)}var BO={kernelName:ei,backendName:\"cpu\",kernelFunc:F7};function WO(e){let{inputs:t,backend:a,attrs:n}=e,{a:r,b:s,bias:i,preluActivationWeights:o}=t,{transposeA:l,transposeB:u,activation:p,leakyreluAlpha:c}=n,d,h,f,m=[];d=F7({inputs:{a:r,b:s},attrs:{transposeA:l,transposeB:u},backend:a}),i&&(h=ml({inputs:{a:d,b:i},backend:a}),m.push(d),d=h),p&&(f=Pc(a,d,p,o,c),m.push(d),d=f);for(let g of m)a.disposeIntermediateTensorInfo(g);return d}var VO={kernelName:jr,backendName:\"cpu\",kernelFunc:WO},UO=ot(kl,e=>Math.acos(e)),GO={kernelName:kl,backendName:\"cpu\",kernelFunc:UO},HO=ot(Il,e=>Math.acosh(e)),jO={kernelName:Il,backendName:\"cpu\",kernelFunc:HO};function qO(e){let{inputs:t,backend:a}=e,n=t;ye(t,\"addN\");let r=n.map(o=>a.data.get(o.dataId).values),s=Me(n[0].shape,n[0].dtype),i=s.values;for(let o=0;o<n.length;o++){let l=r[o];for(let u=0;u<i.length;u++)i[u]+=l[u]}return a.makeTensorInfo(s.shape,s.dtype,s.values)}var XO={kernelName:Ks,backendName:\"cpu\",kernelFunc:qO};function KO(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;ye(r,\"all\");let o=v.parseAxisParam(s,r.shape),l=o,u=T.getAxesPermutation(l,r.shape.length),p=r;u!=null&&(p=La({inputs:{x:r},backend:a,attrs:{perm:u}}),l=T.getInnerMostAxes(l.length,r.shape.length)),T.assertAxesAreInnerMostDims(\"all\",l,p.shape.length);let[c,d]=T.computeOutAndReduceShapes(p.shape,l),h=v.sizeFromShape(d),f=v.makeZerosTypedArray(v.sizeFromShape(c),p.dtype),m=a.data.get(p.dataId).values;for(let x=0;x<f.length;++x){let A=x*h,y=m[A];for(let b=0;b<h;++b){let w=m[A+b];y=y&&w}f[x]=y}u!=null&&a.disposeIntermediateTensorInfo(p);let g=a.makeTensorInfo(c,p.dtype,f);if(i){let x=T.expandShapeToKeepDim(c,o),A=mt({inputs:{x:g},backend:a,attrs:{shape:x}});return a.disposeIntermediateTensorInfo(g),A}return g}var ZO={kernelName:Zs,backendName:\"cpu\",kernelFunc:KO};function YO(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;ye(r,\"any\");let o=v.parseAxisParam(s,r.shape),l=o,u=T.getAxesPermutation(l,r.shape.length),p=r;u!=null&&(p=La({inputs:{x:r},backend:a,attrs:{perm:u}}),l=T.getInnerMostAxes(l.length,r.shape.length)),T.assertAxesAreInnerMostDims(\"any\",l,p.shape.length);let[c,d]=T.computeOutAndReduceShapes(p.shape,l),h=v.sizeFromShape(d),f=v.makeZerosTypedArray(v.sizeFromShape(c),p.dtype),m=a.data.get(p.dataId).values;for(let x=0;x<f.length;++x){let A=x*h,y=m[A];for(let b=0;b<h;++b){let w=m[A+b];y=y||w}f[x]=y}u!=null&&a.disposeIntermediateTensorInfo(p);let g=a.makeTensorInfo(c,p.dtype,f);if(i){let x=T.expandShapeToKeepDim(c,o),A=mt({inputs:{x:g},backend:a,attrs:{shape:x}});return a.disposeIntermediateTensorInfo(g),A}return g}var JO={kernelName:Ys,backendName:\"cpu\",kernelFunc:YO};function QO(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s}=n;ye(r,\"argMax\");let i=v.parseAxisParam(s,r.shape),o=T.getAxesPermutation(i,r.shape.length),l=r,u=[];o!=null&&(l=La({inputs:{x:r},backend:a,attrs:{perm:o}}),u.push(l),i=T.getInnerMostAxes(i.length,l.shape.length)),i=[i[0]],T.assertAxesAreInnerMostDims(\"argMax\",i,l.shape.length);let[p,c]=T.computeOutAndReduceShapes(l.shape,i),d=v.sizeFromShape(p),h=v.makeZerosTypedArray(d,\"int32\"),f=v.sizeFromShape(c),m=a.data.get(l.dataId).values;for(let g=0;g<h.length;++g){let x=g*f,A=m[x],y=0;for(let b=0;b<f;++b){let w=m[x+b];w>A&&(A=w,y=b)}h[g]=y}return u.forEach(g=>a.disposeIntermediateTensorInfo(g)),a.makeTensorInfo(p,\"int32\",h)}var eD={kernelName:Js,backendName:\"cpu\",kernelFunc:QO};function tD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s}=n;ye(r,\"argMin\");let i=v.parseAxisParam(s,r.shape),o=T.getAxesPermutation(i,r.shape.length),l=r,u=[];o!=null&&(l=La({inputs:{x:r},backend:a,attrs:{perm:o}}),u.push(l),i=T.getInnerMostAxes(i.length,l.shape.length)),i=[i[0]],T.assertAxesAreInnerMostDims(\"argMin\",i,l.shape.length);let[p,c]=T.computeOutAndReduceShapes(l.shape,i),d=v.sizeFromShape(p),h=v.makeZerosTypedArray(d,\"int32\"),f=v.sizeFromShape(c),m=a.data.get(l.dataId).values;for(let g=0;g<h.length;++g){let x=g*f,A=m[x],y=0;for(let b=0;b<f;++b){let w=m[x+b];w<A&&(A=w,y=b)}h[g]=y}return u.forEach(g=>a.disposeIntermediateTensorInfo(g)),a.makeTensorInfo(p,\"int32\",h)}var aD={kernelName:kd,backendName:\"cpu\",kernelFunc:tD},nD=ot(Sl,e=>Math.asin(e)),rD={kernelName:Sl,backendName:\"cpu\",kernelFunc:nD},sD=ot(Tl,e=>Math.asinh(e)),iD={kernelName:Tl,backendName:\"cpu\",kernelFunc:sD},oD=ot(Cl,e=>Math.atan(e)),lD={kernelName:Cl,backendName:\"cpu\",kernelFunc:oD},uD=Lt((e,t)=>Math.atan2(e,t)),dD=Yt(El,uD),pD={kernelName:El,backendName:\"cpu\",kernelFunc:dD},cD=ot(Nl,e=>Math.atanh(e)),hD={kernelName:Nl,backendName:\"cpu\",kernelFunc:cD};function g3(e,t,a,n,r,s){let i=r.strideHeight,o=r.strideWidth,l=r.dilationHeight,u=r.dilationWidth,p=r.effectiveFilterHeight,c=r.effectiveFilterWidth,d=r.padInfo.top,h=r.padInfo.left,f=s===\"max\"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY,m=Me(r.outShape,a),g=m.values,x=r.outShape[1]*r.outShape[2]*r.outShape[3],A=r.outShape[2]*r.outShape[3],y=r.outShape[3];for(let b=0;b<r.batchSize;++b){let w=b*x,S=b*n[0];for(let C=0;C<r.inChannels;++C)for(let E=0;E<r.outHeight;++E){let _=E*i-d,$=Math.max(0,_),M=Math.min(r.inHeight,p+_),I=w+E*A;for(let N=0;N<r.outWidth;++N){let O=N*o-h,L=Math.max(0,O),B=Math.min(r.inWidth,c+O),G=f,j=0,U=0;for(let V=$;V<M;V+=l){let Q=S+V*n[1];for(let Z=L;Z<B;Z+=u){let re=Q+Z*n[2],ee=e[re+C];s===\"max\"&&ee>G?G=ee:s===\"avg\"&&(j+=ee,U++)}if(isNaN(G))break}let H=I+N*y+C;g[H]=s===\"avg\"?j/U:G}}}return m}function O7(e,t,a,n,r=!1,s=!1){let i=Me(n.outShape,\"int32\"),o=n.strideHeight,l=n.strideWidth,u=n.dilationHeight,p=n.dilationWidth,c=n.effectiveFilterHeight,d=n.effectiveFilterWidth,h=n.padInfo.top,f=n.padInfo.left,m=Me(t,a,e);for(let g=0;g<n.batchSize;++g)for(let x=0;x<n.inChannels;++x)for(let A=0;A<n.outHeight;++A){let y=A*o-h,b=y;for(;b<0;)b+=u;let w=Math.min(n.inHeight,c+y);for(let S=0;S<n.outWidth;++S){let C=S*l-f,E=C;for(;E<0;)E+=p;let _=Math.min(n.inWidth,d+C),$=Number.NEGATIVE_INFINITY,M=-1;for(let I=b;I<w;I+=u){let N=I-y;for(let O=E;O<_;O+=p){let L=O-C,B=m.get(g,I,O,x);B>$&&($=B,r?M=s?((g*n.inHeight+I)*n.inWidth+O)*n.inChannels+x:(I*n.inWidth+O)*n.inChannels+x:M=N*d+L)}}i.set(M,g,A,S,x)}}return i}function D7(e,t,a,n,r,s){let i=r.strideDepth,o=r.strideHeight,l=r.strideWidth,u=r.dilationDepth,p=r.dilationHeight,c=r.dilationWidth,d=r.effectiveFilterDepth,h=r.effectiveFilterHeight,f=r.effectiveFilterWidth,m=r.padInfo.front,g=r.padInfo.top,x=r.padInfo.left,A=s===\"max\"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY,y=Me(r.outShape,a),b=y.values,w=r.outShape[1]*r.outShape[2]*r.outShape[3]*r.outShape[4],S=r.outShape[2]*r.outShape[3]*r.outShape[4],C=r.outShape[3]*r.outShape[4],E=r.outShape[4];for(let _=0;_<r.batchSize;++_){let $=_*w,M=_*n[0];for(let I=0;I<r.inChannels;++I)for(let N=0;N<r.outDepth;++N){let O=N*i-m,L=O;for(;L<0;)L+=u;let B=Math.min(r.inDepth,d+O),G=$+N*S;for(let j=0;j<r.outHeight;++j){let U=j*o-g,H=U;for(;H<0;)H+=p;let V=Math.min(r.inHeight,h+U),Q=G+j*C;for(let Z=0;Z<r.outWidth;++Z){let re=Z*l-x,ee=re;for(;ee<0;)ee+=c;let he=Math.min(r.inWidth,f+re),oe=Q+Z*E,Ae=A,we=0,Re=0;for(let Ke=L;Ke<B;Ke+=u){let nt=M+Ke*n[1];for(let ut=H;ut<V;ut+=p){let et=nt+ut*n[2];for(let rt=ee;rt<he;rt+=c){let je=et+rt*n[3],ht=e[je+I];if(s===\"max\"&&ht>Ae?Ae=ht:s===\"avg\"&&(we+=ht,Re++),isNaN(Ae))break}if(isNaN(Ae))break}if(isNaN(Ae))break}let Ge=oe+I;b[Ge]=s===\"avg\"?we/Re:Ae}}}}return y}function fD(e,t){let a=Me(t.outShape,\"int32\"),n=t.strideDepth,r=t.strideHeight,s=t.strideWidth,i=t.dilationDepth,o=t.dilationHeight,l=t.dilationWidth,u=t.effectiveFilterDepth,p=t.effectiveFilterHeight,c=t.effectiveFilterWidth,d=t.padInfo.front,h=t.padInfo.top,f=t.padInfo.left;for(let m=0;m<t.batchSize;++m)for(let g=0;g<t.inChannels;++g)for(let x=0;x<t.outDepth;++x){let A=x*n-d,y=A;for(;y<0;)y+=i;let b=Math.min(t.inDepth,u+A);for(let w=0;w<t.outHeight;++w){let S=w*r-h,C=S;for(;C<0;)C+=o;let E=Math.min(t.inHeight,p+S);for(let _=0;_<t.outWidth;++_){let $=_*s-f,M=$;for(;M<0;)M+=l;let I=Math.min(t.inWidth,c+$),N=Number.NEGATIVE_INFINITY,O=-1;for(let L=y;L<b;L+=i){let B=L-A;for(let G=C;G<E;G+=o){let j=G-S;for(let U=M;U<I;U+=l){let H=U-$,V=e.get(m,L,G,U,g);V>=N&&(N=V,O=B*p*c+j*p+H)}}}a.set(O,m,x,w,_,g)}}}return a}function mD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t;ye(r,\"avgPool\");let{filterSize:s,strides:i,pad:o,dimRoundingMode:l}=n,u=1;v.assert(T.eitherStridesOrDilationsAreOne(i,u),()=>`Error in avgPool: Either strides or dilations must be 1. Got strides ${i} and dilations '${u}'`);let p=T.computePool2DInfo(r.shape,s,i,u,o,l),c;if(p.filterWidth===1&&p.filterHeight===1&&v.arraysEqual(p.inShape,p.outShape))c=er({inputs:{x:r},backend:a});else{let d=a.data.get(r.dataId).values,h=v.computeStrides(r.shape),f=g3(d,r.shape,r.dtype,h,p,\"avg\");c=a.makeTensorInfo(p.outShape,r.dtype,f.values)}return c}var gD={kernelName:Qs,backendName:\"cpu\",kernelFunc:mD};function xD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{filterSize:s,strides:i,pad:o,dimRoundingMode:l,dataFormat:u}=n;ye(r,\"avgPool3d\");let p=T.computePool3DInfo(r.shape,s,i,1,o,l,u),c=a.data.get(r.dataId).values,d=D7(c,r.shape,r.dtype,v.computeStrides(r.shape),p,\"avg\");return a.makeTensorInfo(d.shape,\"float32\",d.values)}var AD={kernelName:Hc,backendName:\"cpu\",kernelFunc:xD};function yD(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,input:s}=t,{filterSize:i,strides:o,pad:l,dimRoundingMode:u}=n;ye([r,s],\"avgPool3DGrad\");let p=T.computePool3DInfo(s.shape,i,o,1,l,u),c=p.strideDepth,d=p.strideHeight,h=p.strideWidth,f=p.filterDepth,m=p.filterHeight,g=p.filterWidth,x=p.dilationDepth,A=p.dilationHeight,y=p.dilationWidth,b=p.effectiveFilterDepth,w=p.effectiveFilterHeight,S=p.effectiveFilterWidth,C=b-1-p.padInfo.front,E=S-1-p.padInfo.left,_=w-1-p.padInfo.top,$=Me(s.shape,\"float32\"),M=1/(f*m*g),I=a.bufferSync(r);for(let N=0;N<p.batchSize;++N)for(let O=0;O<p.inChannels;++O)for(let L=0;L<p.inDepth;++L)for(let B=0;B<p.inHeight;++B)for(let G=0;G<p.inWidth;++G){let j=L-C,U=B-_,H=G-E,V=0;for(let Q=0;Q<b;Q+=x){let Z=(j+Q)/c;if(!(Z<0||Z>=p.outDepth||Math.floor(Z)!==Z))for(let re=0;re<w;re+=A){let ee=(U+re)/d;if(!(ee<0||ee>=p.outHeight||Math.floor(ee)!==ee))for(let he=0;he<S;he+=y){let oe=(H+he)/h;if(oe<0||oe>=p.outWidth||Math.floor(oe)!==oe)continue;let Ae=I.get(N,Z,ee,oe,O);V+=Ae}}}$.set(V*M,N,L,B,G,O)}return a.makeTensorInfo($.shape,$.dtype,$.values)}var bD={kernelName:G1,backendName:\"cpu\",kernelFunc:yD};function vD(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,input:s}=t,i=s;ye([r,s],\"avgPoolGrad\");let{filterSize:o,strides:l,pad:u}=n,p=T.computePool2DInfo(i.shape,o,l,1,u),c=p.strideHeight,d=p.strideWidth,h=p.filterHeight,f=p.filterWidth,m=p.dilationHeight,g=p.dilationWidth,x=p.effectiveFilterHeight,A=p.effectiveFilterWidth,y=A-1-p.padInfo.left,b=x-1-p.padInfo.top,w=Me(i.shape,\"float32\"),S=1/(h*f),C=a.data.get(r.dataId).values,E=Me(r.shape,\"float32\",C);for(let _=0;_<p.batchSize;++_)for(let $=0;$<p.inChannels;++$)for(let M=0;M<p.inHeight;++M)for(let I=0;I<p.inWidth;++I){let N=M-b,O=I-y,L=0;for(let B=0;B<x;B+=m){let G=(N+B)/c;if(!(G<0||G>=p.outHeight||Math.floor(G)!==G))for(let j=0;j<A;j+=g){let U=(O+j)/d;if(U<0||U>=p.outWidth||Math.floor(U)!==U)continue;let H=E.get(_,G,U,$);L+=H}}w.set(L*S,_,M,I,$)}return a.makeTensorInfo(w.shape,w.dtype,w.values)}var wD={kernelName:U1,backendName:\"cpu\",kernelFunc:vD};function kD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,scale:s,offset:i,mean:o,variance:l}=t;v.assert(o.shape.length===l.shape.length,()=>\"Batch normalization gradient requires mean and variance to have equal ranks.\"),v.assert(i==null||o.shape.length===i.shape.length,()=>\"Batch normalization gradient requires mean and offset to have equal ranks.\"),v.assert(s==null||o.shape.length===s.shape.length,()=>\"Batch normalization gradient requires mean and scale to have equal ranks.\"),ye([r,o,l,s,i],\"batchNorm\");let{varianceEpsilon:u}=n;u==null&&(u=.001);let p=a.data.get(r.dataId).values,c=a.data.get(o.dataId).values,d=a.data.get(l.dataId).values,h=s?a.data.get(s.dataId).values:new Float32Array([1]),f=i?a.data.get(i.dataId).values:new Float32Array([0]),m=new Float32Array(p.length),g=f.length,x=h.length,A=d.length,y=c.length,b=0,w=0,S=0,C=0;for(let E=0;E<p.length;++E)m[E]=f[b++]+(p[E]-c[w++])*h[S++]/Math.sqrt(d[C++]+u),b>=g&&(b=0),w>=y&&(w=0),S>=x&&(S=0),C>=A&&(C=0);return a.makeTensorInfo(r.shape,r.dtype,m)}var ID={kernelName:yi,backendName:\"cpu\",kernelFunc:kD};function SD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockShape:s,crops:i}=n;ye([r],\"batchToSpaceND\");let o=s.reduce((x,A)=>x*A),l=T.getReshaped(r.shape,s,o),u=T.getPermuted(l.length,s.length),p=T.getReshapedPermuted(r.shape,s,o),c=T.getSliceBeginCoords(i,s.length),d=T.getSliceSize(p,i,s.length),h=mt({inputs:{x:r},backend:a,attrs:{shape:l}}),f=La({inputs:{x:h},backend:a,attrs:{perm:u}}),m=mt({inputs:{x:f},backend:a,attrs:{shape:p}}),g=Gs({inputs:{x:m},backend:a,attrs:{begin:c,size:d}});return a.disposeIntermediateTensorInfo(h),a.disposeIntermediateTensorInfo(f),a.disposeIntermediateTensorInfo(m),g}var TD={kernelName:Rl,backendName:\"cpu\",kernelFunc:SD};function CD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,weights:s}=t,{size:i}=n,o=a.data.get(r.dataId).values,l=a.data.get(s.dataId).values,u=i3(o,l,s.dtype,s.shape,i);return a.makeTensorInfo([i],s.dtype,u)}var ND={kernelName:Id,backendName:\"cpu\",kernelFunc:CD};function ED(e){let{inputs:t,backend:a}=e,{s0:n,s1:r}=t,s=a.data.get(n.dataId).values,i=a.data.get(r.dataId).values,o=T.assertAndGetBroadcastShape(Array.from(s),Array.from(i));return a.makeTensorInfo([o.length],\"int32\",Int32Array.from(o))}var RD={kernelName:jc,backendName:\"cpu\",kernelFunc:ED},MD=ot(as,(e,t)=>{let a=t;return e>a.clipValueMax?a.clipValueMax:e<a.clipValueMin?a.clipValueMin:e}),$D={kernelName:as,backendName:\"cpu\",kernelFunc:MD},_D=e=>{let{x:t}=e.inputs,a=e.backend,n=new Float32Array(v.sizeFromShape(t.shape)),r=a.data.get(t.dataId),s=r.complexTensorInfos.real,i=r.complexTensorInfos.imag,o=a.data.get(s.dataId).values,l=a.data.get(i.dataId).values;for(let u=0;u<o.length;u++){let p=o[u],c=l[u];n[u]=Math.hypot(p,c)}return a.makeOutput(n,t.shape,\"float32\")},PD={kernelName:qc,backendName:\"cpu\",kernelFunc:_D};function gl(e){let{inputs:t,backend:a}=e,{input:n}=t,r=a.data.get(n.dataId).complexTensorInfos.imag,s=a.data.get(r.dataId).values;return a.makeTensorInfo(r.shape,r.dtype,s)}var FD={kernelName:Rd,backendName:\"cpu\",kernelFunc:gl};function xl(e){let{inputs:t,backend:a,attrs:n}=e,{axis:r}=n,s=v.parseAxisParam(r,t[0].shape)[0],i=t.map(m=>m.shape);T.assertParamsConsistent(i,s);let o=T.computeOutShape(t.map(m=>m.shape),s);if(v.sizeFromShape(o)===0)return a.makeTensorInfo(o,t[0].dtype,[]);let l=t.filter(m=>v.sizeFromShape(m.shape)>0);if(l.length===1)return er({inputs:{x:l[0]},backend:a});if(l[0].dtype===\"complex64\"){let m=l.map(b=>Us({inputs:{input:b},backend:a})),g=l.map(b=>gl({inputs:{input:b},backend:a})),x=xl({inputs:m,backend:a,attrs:{axis:s}}),A=xl({inputs:g,backend:a,attrs:{axis:s}}),y=Xa({inputs:{real:x,imag:A},backend:a});return m.forEach(b=>a.disposeIntermediateTensorInfo(b)),g.forEach(b=>a.disposeIntermediateTensorInfo(b)),a.disposeIntermediateTensorInfo(x),a.disposeIntermediateTensorInfo(A),y}let u=l.map(m=>{let g=[-1,v.sizeFromShape(m.shape.slice(s))];return mt({inputs:{x:m},backend:a,attrs:{shape:g}})}),p=u.map(m=>({vals:a.data.get(m.dataId).values,shape:m.shape}));o=T.computeOutShape(u.map(m=>m.shape),1);let c=u[0].shape[0]===1,d=o3(p,o,t[0].dtype,c),h=T.computeOutShape(l.map(m=>m.shape),s),f=a.makeTensorInfo(h,t[0].dtype,d);return u.forEach(m=>a.disposeIntermediateTensorInfo(m)),f}var OD={kernelName:Ml,backendName:\"cpu\",kernelFunc:xl};function z7(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dataFormat:l,dilations:u,dimRoundingMode:p}=n;ye([r,s],\"conv2d\");let c=T.convertConv2DDataFormat(l),d=T.computeConv2DInfo(r.shape,s.shape,i,u,o,p,!1,c),h=d.filterHeight,f=d.filterWidth,m=d.dilationHeight,g=d.dilationWidth,x=d.padInfo.left,A=d.padInfo.top,y=d.dataFormat===\"channelsLast\",b=new jt(d.outShape,r.dtype),w=v.computeStrides(r.shape),S=v.computeStrides(s.shape),C=w[0],E=y?w[1]:w[2],_=y?w[2]:1,$=y?1:w[1],M=b.strides[0],I=y?b.strides[1]:b.strides[2],N=y?b.strides[2]:1,O=y?1:b.strides[1],L=a.data.get(r.dataId).values,B=a.data.get(s.dataId).values,G=b.values;for(let j=0;j<d.batchSize;++j){let U=j*C,H=j*M;for(let V=0;V<d.outHeight;++V){let Q=H+V*I,Z=V*d.strideHeight-A;for(let re=0;re<h;++re){let ee=Z+re*m;if(ee<0||ee>=d.inHeight)continue;let he=re*S[0],oe=U+ee*E;for(let Ae=0;Ae<d.outWidth;++Ae){let we=Q+Ae*N,Re=Ae*d.strideWidth-x;for(let Ge=0;Ge<f;++Ge){let Ke=Re+Ge*g;if(Ke<0||Ke>=d.inWidth)continue;let nt=he+Ge*S[1],ut=oe+Ke*_,et=nt;for(let rt=0;rt<d.inChannels;++rt){let je=L[ut+rt*$];for(let ht=0;ht<d.outChannels;++ht)G[we+ht*O]+=je*B[et+ht];et+=d.outChannels}}}}}}return a.makeTensorInfo(b.shape,b.dtype,G)}var DD={kernelName:ni,backendName:\"cpu\",kernelFunc:z7};function zD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,dy:s}=t,{strides:i,pad:o,dataFormat:l,dimRoundingMode:u,filterShape:p}=n;ye([r,s],\"conv2dBackpropFilter\");let c=T.convertConv2DDataFormat(l),d=T.computeConv2DInfo(r.shape,p,i,1,o,u,!1,c),{strideHeight:h,strideWidth:f,filterHeight:m,filterWidth:g}=d,x=d.dataFormat===\"channelsLast\",A=new jt(d.filterShape,\"float32\"),y=d.padInfo.left,b=d.padInfo.top,w=a.data.get(r.dataId).values,S=a.data.get(s.dataId).values,C=new jt(r.shape,r.dtype,w),E=new jt(s.shape,s.dtype,S);for(let _=0;_<m;++_){let $=Math.max(0,Math.ceil((b-_)/h)),M=Math.min(d.outHeight,(d.inHeight+b-_)/h);for(let I=0;I<g;++I){let N=Math.max(0,Math.ceil((y-I)/f)),O=Math.min(d.outWidth,(d.inWidth+y-I)/f);for(let L=0;L<d.inChannels;++L)for(let B=0;B<d.outChannels;++B){let G=0;for(let j=0;j<d.batchSize;++j)for(let U=$;U<M;++U){let H=_+U*h-b;for(let V=N;V<O;++V){let Q=I+V*f-y;x?G+=C.get(j,H,Q,L)*E.get(j,U,V,B):G+=C.get(j,L,H,Q)*E.get(j,B,U,V)}}A.set(G,_,I,L,B)}}}return a.makeTensorInfo(A.shape,A.dtype,A.values)}var LD={kernelName:Xc,backendName:\"cpu\",kernelFunc:zD};function BD(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,filter:s}=t,{inputShape:i,strides:o,pad:l,dataFormat:u,dimRoundingMode:p}=n;ye([r,s],\"conv2dBackpropInput\");let c=v.computeStrides(s.shape),d=v.computeStrides(r.shape),h=T.convertConv2DDataFormat(u),f=T.computeConv2DInfo(i,s.shape,o,1,l,p,!1,h),m=new jt(f.inShape,\"float32\"),g=m.values,x=a.data.get(r.dataId).values,A=a.data.get(s.dataId).values,[y,b,w]=c,{batchSize:S,filterHeight:C,filterWidth:E,inChannels:_,inHeight:$,inWidth:M,outChannels:I,outHeight:N,outWidth:O,strideHeight:L,strideWidth:B}=f;h=f.dataFormat;let G=C-1-f.padInfo.top,j=E-1-f.padInfo.left,U=h===\"channelsLast\",H=m.strides[0],V=U?m.strides[1]:m.strides[2],Q=U?m.strides[2]:1,Z=U?1:m.strides[1],re=d[0],ee=U?d[1]:d[2],he=U?d[2]:1,oe=U?1:d[1];for(let Ae=0;Ae<S;++Ae)for(let we=0;we<_;++we)for(let Re=0;Re<$;++Re){let Ge=Re-G,Ke=Math.max(0,Math.ceil(Ge/L)),nt=Math.min(N,(C+Ge)/L);for(let ut=0;ut<M;++ut){let et=ut-j,rt=Math.max(0,Math.ceil(et/B)),je=Math.min(O,(E+et)/B),ht=0;for(let Ft=Ke;Ft<nt;++Ft){let sn=Ft*L-Ge;for(let aa=rt;aa<je;++aa){let $a=aa*B-et,on=re*Ae+ee*Ft+he*aa,_a=y*(C-1-sn)+b*(E-1-$a)+w*we;for(let dt=0;dt<I;++dt){let Pa=x[on+oe*dt],Ua=A[_a+dt];ht+=Pa*Ua}}}let Va=H*Ae+V*Re+Q*ut+Z*we;g[Va]=ht}}return a.makeTensorInfo(m.shape,m.dtype,m.values)}var WD={kernelName:ri,backendName:\"cpu\",kernelFunc:BD};function VD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dilations:l}=n;ye([r,s],\"conv3d\");let u=T.computeConv3DInfo(r.shape,s.shape,i,l,o),{filterDepth:p,filterHeight:c,filterWidth:d,dilationDepth:h,dilationHeight:f,dilationWidth:m,padInfo:g}=u,x=g.front,A=g.left,y=g.top,b=new jt(u.outShape,r.dtype),w=a.data.get(r.dataId).values,S=a.data.get(s.dataId).values,C=b.values,E=v.computeStrides(r.shape),_=v.computeStrides(s.shape);for(let $=0;$<u.batchSize;++$){let M=$*E[0],I=$*b.strides[0];for(let N=0;N<u.outDepth;++N){let O=I+N*b.strides[1],L=N*u.strideDepth-x;for(let B=0;B<p;++B){let G=L+B*h;if(G<0||G>=u.inDepth)continue;let j=B*_[0],U=M+G*E[1];for(let H=0;H<u.outHeight;++H){let V=O+H*b.strides[2],Q=H*u.strideHeight-y;for(let Z=0;Z<c;++Z){let re=Q+Z*f;if(re<0||re>=u.inHeight)continue;let ee=j+Z*_[1],he=U+re*E[2];for(let oe=0;oe<u.outWidth;++oe){let Ae=V+oe*u.outChannels,we=oe*u.strideWidth-A;for(let Re=0;Re<d;++Re){let Ge=we+Re*m;if(Ge<0||Ge>=u.inWidth)continue;let Ke=ee+Re*_[2],nt=he+Ge*u.inChannels,ut=Ke;for(let et=0;et<u.inChannels;++et){let rt=w[nt+et];for(let je=0;je<u.outChannels;++je)C[Ae+je]+=rt*S[ut+je];ut+=u.outChannels}}}}}}}}return a.makeTensorInfo(b.shape,b.dtype,b.values)}var UD={kernelName:Kc,backendName:\"cpu\",kernelFunc:VD};function GD(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,dy:s}=t,{strides:i,pad:o,filterShape:l}=n;ye([r,s],\"conv3dBackpropFilterV2\");let u=v.computeStrides(r.shape),p=v.computeStrides(s.shape),c=T.computeConv3DInfo(r.shape,l,i,1,o),d=c.strideDepth,h=c.strideHeight,f=c.strideWidth,m=c.filterDepth,g=c.filterHeight,x=c.filterWidth,A=new jt(c.filterShape,\"float32\"),y=A.values,[b,w,S,C]=A.strides,E=a.data.get(s.dataId).values,[_,$,M,I]=p,N=a.data.get(r.dataId).values,[O,L,B,G]=u,j=c.padInfo.front,U=c.padInfo.left,H=c.padInfo.top;for(let V=0;V<m;++V){let Q=Math.max(0,Math.ceil((j-V)/d)),Z=Math.min(c.outDepth,(c.inDepth+j-V)/d),re=V*b;for(let ee=0;ee<g;++ee){let he=Math.max(0,Math.ceil((H-ee)/h)),oe=Math.min(c.outHeight,(c.inHeight+H-ee)/h),Ae=ee*w+re;for(let we=0;we<x;++we){let Re=Math.max(0,Math.ceil((U-we)/f)),Ge=Math.min(c.outWidth,(c.inWidth+U-we)/f),Ke=we*S+Ae;for(let nt=0;nt<c.inChannels;++nt){let ut=nt*C+Ke;for(let et=0;et<c.outChannels;++et){let rt=0;for(let je=0;je<c.batchSize;++je){let ht=je*O,Va=je*_;for(let Ft=Q;Ft<Z;++Ft){let sn=(V+Ft*d-j)*L+ht,aa=Ft*$+Va;for(let $a=he;$a<oe;++$a){let on=(ee+$a*h-H)*B+sn,_a=$a*M+aa;for(let dt=Re;dt<Ge;++dt){let Pa=(we+dt*f-U)*G+on,Ua=dt*I+_a;rt+=N[Pa+nt]*E[Ua+et]}}}}y[ut+et]=rt}}}}}return a.makeTensorInfo(A.shape,A.dtype,A.values)}var HD={kernelName:H1,backendName:\"cpu\",kernelFunc:GD};function jD(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,filter:s}=t,{pad:i,strides:o,inputShape:l}=n;ye([r],\"conv3dBackpropInputV2\");let u=v.computeStrides(r.shape),p=v.computeStrides(s.shape),c=T.computeConv3DInfo(l,s.shape,o,1,i),d=new jt(c.inShape,\"float32\"),h=d.values,[f,m,g,x]=d.strides,A=a.data.get(r.dataId).values,[y,b,w,S]=u,C=a.data.get(s.dataId).values,[E,_,$,M]=p,{batchSize:I,filterDepth:N,filterHeight:O,filterWidth:L,inChannels:B,inDepth:G,inHeight:j,inWidth:U,outChannels:H,outDepth:V,outHeight:Q,outWidth:Z,strideDepth:re,strideHeight:ee,strideWidth:he}=c,oe=N-1-c.padInfo.front,Ae=O-1-c.padInfo.top,we=L-1-c.padInfo.left;for(let Re=0;Re<I;++Re)for(let Ge=0;Ge<B;++Ge)for(let Ke=0;Ke<G;++Ke){let nt=Ke-oe,ut=Math.max(0,Math.ceil(nt/re)),et=Math.min(V,(N+nt)/re);for(let rt=0;rt<j;++rt){let je=rt-Ae,ht=Math.max(0,Math.ceil(je/ee)),Va=Math.min(Q,(O+je)/ee);for(let Ft=0;Ft<U;++Ft){let sn=Ft-we,aa=Math.max(0,Math.ceil(sn/he)),$a=Math.min(Z,(L+sn)/he),on=0;for(let _a=ut;_a<et;++_a){let dt=_a*re-nt;for(let Pa=ht;Pa<Va;++Pa){let Ua=Pa*ee-je;for(let ur=aa;ur<$a;++ur){let Bo=ur*he-sn,Un=y*Re+b*_a+w*Pa+S*ur,$u=E*(N-1-dt)+_*(O-1-Ua)+$*(L-1-Bo)+M*Ge;for(let bn=0;bn<H;++bn){let Wo=A[Un+bn],Xt=C[$u+bn];on+=Wo*Xt}}}}h[f*Re+m*Ke+g*rt+x*Ft+Ge]=on}}}return a.makeTensorInfo(d.shape,d.dtype,d.values)}var qD={kernelName:Zc,backendName:\"cpu\",kernelFunc:jD},XD=ot(si,e=>Math.cos(e)),KD={kernelName:si,backendName:\"cpu\",kernelFunc:XD},ZD=ot(ii,e=>Math.cosh(e)),YD={kernelName:ii,backendName:\"cpu\",kernelFunc:ZD};function JD(e){let{inputs:t,backend:a,attrs:n}=e,{image:r,boxes:s,boxInd:i}=t,{cropSize:o,method:l,extrapolationValue:u}=n,[p,c,d,h]=r.shape,f=s.shape[0],[m,g]=o,x=Me([f,m,g,h],\"float32\"),A=a.data.get(s.dataId).values,y=a.data.get(i.dataId).values,b=a.data.get(r.dataId).values,w=v.computeStrides(r.shape),S=v.computeStrides(x.shape);for(let C=0;C<f;C++){let E=C*4,_=A[E],$=A[E+1],M=A[E+2],I=A[E+3],N=y[C];if(N>=p)continue;let O=m>1?(M-_)*(c-1)/(m-1):0,L=g>1?(I-$)*(d-1)/(g-1):0;for(let B=0;B<m;B++){let G=m>1?_*(c-1)+B*O:.5*(_+M)*(c-1);if(G<0||G>c-1){for(let j=0;j<g;j++)for(let U=0;U<h;U++){let H=U+j*S[2]+B*S[1]+C*S[0];x.values[H]=u}continue}if(l===\"bilinear\"){let j=Math.floor(G),U=Math.ceil(G),H=G-j;for(let V=0;V<g;V++){let Q=g>1?$*(d-1)+V*L:.5*($+I)*(d-1);if(Q<0||Q>d-1){for(let he=0;he<h;he++){let oe=he+V*S[2]+B*S[1]+C*S[0];x.values[oe]=u}continue}let Z=Math.floor(Q),re=Math.ceil(Q),ee=Q-Z;for(let he=0;he<h;he++){let oe=he+Z*w[2]+j*w[1]+N*w[0],Ae=b[oe];oe=he+re*w[2]+j*w[1]+N*w[0];let we=b[oe];oe=he+Z*w[2]+U*w[1]+N*w[0];let Re=b[oe];oe=he+re*w[2]+U*w[1]+N*w[0];let Ge=b[oe],Ke=Ae+(we-Ae)*ee,nt=Re+(Ge-Re)*ee;oe=he+V*S[2]+B*S[1]+C*S[0],x.values[oe]=Ke+(nt-Ke)*H}}}else for(let j=0;j<g;++j){let U=g>1?$*(d-1)+j*L:.5*($+I)*(d-1);if(U<0||U>d-1){for(let Q=0;Q<h;Q++){let Z=Q+j*S[2]+B*S[1]+C*S[0];x.values[Z]=u}continue}let H=Math.round(U),V=Math.round(G);for(let Q=0;Q<h;Q++){let Z=Q+H*w[2]+V*w[1]+N*w[0],re=Q+j*S[2]+B*S[1]+C*S[0];x.values[re]=b[Z]}}}}return a.makeTensorInfo(x.shape,x.dtype,x.values)}var QD={kernelName:ui,backendName:\"cpu\",kernelFunc:JD};function ez(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,exclusive:i,reverse:o}=n;ye(r,\"cumprod\");let l=T.getAxesPermutation([s],r.shape.length),u=r;l!=null&&(u=La({inputs:{x:r},backend:a,attrs:{perm:l}}));let p=T.getInnerMostAxes(1,r.shape.length)[0];if(p!==u.shape.length-1)throw new Error(`backend.cumprod in CPU expects an inner-most axis=${u.shape.length-1} but got axis=${p}`);let c=ca(u.dtype,\"int32\"),d=v.makeOnesTypedArray(v.sizeFromShape(u.shape),c),h=a.data.get(u.dataId).values,f=u.shape[u.shape.length-1],m=o?(x,A)=>x+f-A-1:(x,A)=>x+A;for(let x=0;x<h.length;x+=f)for(let A=0;A<f;A++){let y=m(x,A);if(A===0)d[y]=i?1:h[y];else{let b=m(x,A-1);d[y]=i?h[b]*d[b]:h[y]*d[b]}}let g=a.makeTensorInfo(u.shape,c,d);if(l!=null){let x=T.getUndoAxesPermutation(l),A=La({inputs:{x:g},backend:a,attrs:{perm:x}});return a.disposeIntermediateTensorInfo(g),a.disposeIntermediateTensorInfo(u),A}return g}var tz={kernelName:oi,backendName:\"cpu\",kernelFunc:ez};function az(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,exclusive:i,reverse:o}=n;ye(r,\"cumsum\");let l=T.getAxesPermutation([s],r.shape.length),u=r;l!=null&&(u=La({inputs:{x:r},backend:a,attrs:{perm:l}}));let p=T.getInnerMostAxes(1,r.shape.length)[0];if(p!==u.shape.length-1)throw new Error(`backend.cumsum in CPU expects an inner-most axis=${u.shape.length-1} but got axis=${p}`);let c=ca(u.dtype,\"int32\"),d=v.makeZerosTypedArray(v.sizeFromShape(u.shape),c),h=a.data.get(u.dataId).values,f=u.shape[u.shape.length-1],m=o?(x,A)=>x+f-A-1:(x,A)=>x+A;for(let x=0;x<h.length;x+=f)for(let A=0;A<f;A++){let y=m(x,A);if(A===0)d[y]=i?0:h[y];else{let b=m(x,A-1);d[y]=i?h[b]+d[b]:h[y]+d[b]}}let g=a.makeTensorInfo(u.shape,c,d);if(l!=null){let x=T.getUndoAxesPermutation(l),A=La({inputs:{x:g},backend:a,attrs:{perm:x}});return a.disposeIntermediateTensorInfo(g),a.disposeIntermediateTensorInfo(u),A}return g}var nz={kernelName:li,backendName:\"cpu\",kernelFunc:az};function rz(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,weights:s}=t,{size:i,binaryOutput:o}=n;if(r.shape.length===1){let l=a.data.get(r.dataId).values,u=a.data.get(s.dataId).values,p=i3(l,u,s.dtype,s.shape,i);return a.makeTensorInfo([i],s.dtype,p)}else if(r.shape.length===2){let l=a.bufferSync(r),u=a.bufferSync(s),p=X4(l,u,i,o);return a.makeTensorInfo(p.shape,s.dtype,p.values)}throw new Error(`Error in denseBincount: input must be at most rank 2, but got rank${r.shape.length}.`)}var sz={kernelName:Td,backendName:\"cpu\",kernelFunc:rz};function iz(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockSize:s,dataFormat:i}=n;v.assert(i===\"NHWC\",()=>`Only NHWC dataFormat supported on CPU for depthToSpace. Got ${i}`);let o=r.shape[0],l=r.shape[1],u=r.shape[2],p=r.shape[3],c=l*s,d=u*s,h=p/(s*s),f=a.data.get(r.dataId).values,m=new Float32Array(o*c*d*h),g=0;for(let x=0;x<o;++x)for(let A=0;A<c;++A){let y=Math.floor(A/s),b=A%s;for(let w=0;w<d;++w){let S=Math.floor(w/s),C=w%s,E=(b*s+C)*h;for(let _=0;_<h;++_){let $=_+E+p*(S+u*(y+l*x));m[g++]=f[$]}}}return a.makeTensorInfo([o,c,d,h],r.dtype,m)}var oz={kernelName:di,backendName:\"cpu\",kernelFunc:iz};function L7(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dilations:l,dimRoundingMode:u}=n;ye([r,s],\"depthwiseConv2DNative\");let p=v.computeStrides(r.shape),c=v.computeStrides(s.shape),d=l;d==null&&(d=[1,1]),v.assert(T.eitherStridesOrDilationsAreOne(i,d),()=>`Error in depthwiseConv2d: Either strides or dilations must be 1. Got strides ${i} and dilations '${d}'`);let h=T.computeConv2DInfo(r.shape,s.shape,i,d,o,u,!0),{filterHeight:f,filterWidth:m,dilationHeight:g,dilationWidth:x,padInfo:A}=h,y=A.left,b=A.top,w=h.outChannels/h.inChannels,S=new jt(h.outShape,r.dtype),C=a.data.get(r.dataId).values,E=a.data.get(s.dataId).values,_=S.values;for(let $=0;$<h.batchSize;++$){let M=$*p[0],I=$*S.strides[0];for(let N=0;N<h.outHeight;++N){let O=I+N*S.strides[1],L=N*h.strideHeight-b;for(let B=0;B<f;++B){let G=L+B*g;if(G<0||G>=h.inHeight)continue;let j=B*c[0],U=M+G*p[1];for(let H=0;H<h.outWidth;++H){let V=O+H*S.strides[2],Q=H*h.strideWidth-y;for(let Z=0;Z<m;++Z){let re=Q+Z*x;if(re<0||re>=h.inWidth)continue;let ee=j+Z*c[1],he=U+re*h.inChannels,oe=V,Ae=ee;for(let we=0;we<h.inChannels;++we){let Re=C[he+we];for(let Ge=0;Ge<w;++Ge)_[oe+Ge]+=Re*E[Ae+Ge];oe+=w,Ae+=w}}}}}}return a.makeTensorInfo(S.shape,S.dtype,S.values)}var lz={kernelName:pi,backendName:\"cpu\",kernelFunc:L7};function uz(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,dy:s}=t,{strides:i,dilations:o,pad:l,dimRoundingMode:u,filterShape:p}=n;ye([r,s],\"depthwiseConv2dNativeBackpropFilter\");let c=T.computeConv2DInfo(r.shape,p,i,o,l,u,!0),{strideHeight:d,strideWidth:h,filterHeight:f,filterWidth:m}=c,g=new jt(c.filterShape,\"float32\"),x=c.padInfo.left,A=c.padInfo.top,y=c.outChannels/c.inChannels,b=a.data.get(r.dataId).values,w=new jt(r.shape,r.dtype,b),S=a.data.get(s.dataId).values,C=new jt(s.shape,s.dtype,S);for(let E=0;E<f;++E){let _=Math.max(0,Math.ceil((A-E)/d)),$=Math.min(c.outHeight,(c.inHeight+A-E)/d);for(let M=0;M<m;++M){let I=Math.max(0,Math.ceil((x-M)/h)),N=Math.min(c.outWidth,(c.inWidth+x-M)/h);for(let O=0;O<c.outChannels;++O){let L=Math.trunc(O/y),B=O%y,G=0;for(let j=0;j<c.batchSize;++j)for(let U=_;U<$;++U){let H=E+U*d-A;for(let V=I;V<N;++V){let Q=M+V*h-x;G+=w.get(j,H,Q,L)*C.get(j,U,V,O)}}g.set(G,E,M,L,B)}}}return a.makeTensorInfo(g.shape,g.dtype,g.values)}var dz={kernelName:Yc,backendName:\"cpu\",kernelFunc:uz};function pz(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,filter:s}=t,{strides:i,dilations:o,pad:l,dimRoundingMode:u,inputShape:p}=n;ye([r,s],\"depthwiseConv2DNativeBackpropInput\");let c=v.computeStrides(r.shape),d=v.computeStrides(s.shape),h=T.computeConv2DInfo(p,s.shape,i,o,l,u,!0),f=new jt(h.inShape,\"float32\"),m=f.values,[g,x,A]=f.strides,y=a.data.get(r.dataId).values,[b,w,S]=c,C=a.data.get(s.dataId).values,[E,_,$]=d,{batchSize:M,filterHeight:I,filterWidth:N,inChannels:O,inHeight:L,inWidth:B,outChannels:G,outHeight:j,outWidth:U,strideHeight:H,strideWidth:V}=h,Q=I-1-h.padInfo.top,Z=N-1-h.padInfo.left,re=G/O;for(let ee=0;ee<M;++ee)for(let he=0;he<O;++he)for(let oe=0;oe<L;++oe){let Ae=oe-Q,we=Math.max(0,Math.ceil(Ae/H)),Re=Math.min(j,(I+Ae)/H);for(let Ge=0;Ge<B;++Ge){let Ke=Ge-Z,nt=Math.max(0,Math.ceil(Ke/V)),ut=Math.min(U,(N+Ke)/V),et=0;for(let rt=we;rt<Re;++rt){let je=rt*H-Ae;for(let ht=nt;ht<ut;++ht){let Va=ht*V-Ke,Ft=b*ee+w*rt+S*ht,sn=E*(I-1-je)+_*(N-1-Va)+$*he;for(let aa=0;aa<re;++aa){let $a=he*re+aa,on=y[Ft+$a],_a=C[sn+aa];et+=on*_a}}}m[g*ee+x*oe+A*Ge+he]=et}}return a.makeTensorInfo(f.shape,f.dtype,f.values)}var cz={kernelName:Jc,backendName:\"cpu\",kernelFunc:pz};function hz(e){let{inputs:t,backend:a}=e,{x:n}=t,r=v.sizeFromShape(n.shape),s=a.data.get(n.dataId).values,i=Me([r,r],n.dtype),o=i.values;for(let u=0;u<s.length;u++)o[u*r+u]=s[u];let l=[...n.shape,...n.shape];return a.makeTensorInfo(l,i.dtype,i.values)}var fz={kernelName:Qc,backendName:\"cpu\",kernelFunc:hz},mz={kernelName:eh,backendName:\"cpu\",kernelFunc:({inputs:e,backend:t,attrs:a})=>{let{x:n,filter:r}=e,{strides:s,pad:i,dilations:o}=a,l=t,u=l.data.get(n.dataId).values,p=n.shape.length,c=l.data.get(r.dataId).values,d=r.shape.length,{batchSize:h,inHeight:f,inWidth:m,inChannels:g,outHeight:x,outWidth:A,padInfo:y,strideHeight:b,strideWidth:w,filterHeight:S,filterWidth:C,dilationHeight:E,dilationWidth:_,outShape:$}=T.computeDilation2DInfo(n.shape,r.shape,s,i,\"NHWC\",o),M=v.sizeFromShape($),I=$.length,N=v.getArrayFromDType(n.dtype,M);for(let O=0;O<h;++O)for(let L=0;L<x;++L){let B=L*b-y.top;for(let G=0;G<A;++G){let j=G*w-y.left;for(let U=0;U<g;++U){let H=Number.MIN_SAFE_INTEGER;for(let Q=0;Q<S;++Q){let Z=B+Q*E;if(Z>=0&&Z<f)for(let re=0;re<C;++re){let ee=j+re*_;if(ee>=0&&ee<m){let he=v.locToIndex([O,Z,ee,U],p,v.computeStrides(n.shape)),oe=v.locToIndex([Q,re,U],d,v.computeStrides(r.shape)),Ae=u[he]+c[oe];Ae>H&&(H=Ae)}}}let V=v.locToIndex([O,L,G,U],I,v.computeStrides($));N[V]=H}}}return{dataId:l.write(v.toTypedArray(N,n.dtype),$,n.dtype),shape:$,dtype:n.dtype}}},gz={kernelName:Gm,backendName:\"cpu\",kernelFunc:({inputs:e,backend:t,attrs:a})=>{let{x:n,filter:r,dy:s}=e,{strides:i,pad:o,dilations:l}=a,u=t,p=v.toNestedArray(n.shape,u.data.get(n.dataId).values),c=v.toNestedArray(r.shape,u.data.get(r.dataId).values),{batchSize:d,inHeight:h,inWidth:f,inChannels:m,outHeight:g,outWidth:x,padInfo:A,strideHeight:y,strideWidth:b,filterHeight:w,filterWidth:S,dilationHeight:C,dilationWidth:E,outShape:_}=T.computeDilation2DInfo(n.shape,r.shape,i,o,\"NHWC\",l);v.assert(s.rank===_.length,()=>`Error in ${Gm}, dy must have the same rank as output ${_.length}, but got ${s.rank}`);let $=v.toNestedArray(_,u.data.get(s.dataId).values),M=v.makeZerosNestedTypedArray(r.shape,r.dtype);for(let I=0;I<d;++I)for(let N=0;N<g;++N){let O=N*y-A.top;for(let L=0;L<x;++L){let B=L*b-A.left;for(let G=0;G<m;++G){let j=Number.MIN_SAFE_INTEGER,U=0,H=0;for(let V=0;V<w;++V){let Q=O+V*C;if(Q>=0&&Q<h)for(let Z=0;Z<S;++Z){let re=B+Z*E;if(re>=0&&re<f){let ee=p[I][Q][re][G]+c[V][Z][G];ee>j&&(j=ee,U=V,H=Z)}}}M[U][H][G]+=$[I][N][L][G]}}}return{dataId:u.write(v.toTypedArray(M,n.dtype),r.shape,r.dtype),shape:r.shape,dtype:r.dtype}}},xz={kernelName:Um,backendName:\"cpu\",kernelFunc:({inputs:e,backend:t,attrs:a})=>{let{x:n,filter:r,dy:s}=e,{strides:i,pad:o,dilations:l}=a,u=t,p=v.toNestedArray(n.shape,u.data.get(n.dataId).values),c=v.toNestedArray(r.shape,u.data.get(r.dataId).values),{batchSize:d,inHeight:h,inWidth:f,inChannels:m,outHeight:g,outWidth:x,padInfo:A,strideHeight:y,strideWidth:b,filterHeight:w,filterWidth:S,dilationHeight:C,dilationWidth:E,outShape:_}=T.computeDilation2DInfo(n.shape,r.shape,i,o,\"NHWC\",l);v.assert(s.rank===_.length,()=>`Error in ${Um}, dy must have the same rank as output ${_.length}, but got ${s.rank}`);let $=v.toNestedArray(_,u.data.get(s.dataId).values),M=v.makeZerosNestedTypedArray(n.shape,n.dtype);for(let I=0;I<d;++I)for(let N=0;N<g;++N){let O=N*y-A.top;for(let L=0;L<x;++L){let B=L*b-A.left;for(let G=0;G<m;++G){let j=Number.MIN_SAFE_INTEGER,U=O<0?0:O,H=B<0?0:B;for(let V=0;V<w;++V){let Q=O+V*C;if(Q>=0&&Q<h)for(let Z=0;Z<S;++Z){let re=B+Z*E;if(re>=0&&re<f){let ee=p[I][Q][re][G]+c[V][Z][G];ee>j&&(j=ee,U=Q,H=re)}}}M[I][U][H][G]+=$[I][N][L][G]}}}return{dataId:u.write(v.toTypedArray(M,n.dtype),n.shape,n.dtype),shape:n.shape,dtype:n.dtype}}};function lp(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;ye(r,\"sum\");let o;r.dtype===\"bool\"?o=Jr({inputs:{x:r},backend:a,attrs:{dtype:\"int32\"}}):o=er({inputs:{x:r},backend:a});let l=o.shape.length,u=v.parseAxisParam(s,o.shape),p=T.getAxesPermutation(u,l),c=u,d=o;p!=null&&(d=La({inputs:{x:o},backend:a,attrs:{perm:p}}),c=T.getInnerMostAxes(c.length,l)),T.assertAxesAreInnerMostDims(\"sum\",c,d.shape.length);let[h,f]=T.computeOutAndReduceShapes(d.shape,c),m=T.upcastType(d.dtype,\"int32\"),g=$c(a,h,m),x=v.sizeFromShape(f),A=a.data.get(g.dataId).values,y=a.data.get(d.dataId).values;for(let b=0;b<A.length;++b){let w=b*x,S=0;for(let C=0;C<x;++C)S+=y[w+C];A[b]=S}if(i){let b=T.expandShapeToKeepDim(g.shape,u),w=g;g=mt({inputs:{x:g},backend:a,attrs:{shape:b}}),a.disposeIntermediateTensorInfo(w)}return a.disposeIntermediateTensorInfo(o),p!=null&&a.disposeIntermediateTensorInfo(d),g}var Az={kernelName:ro,backendName:\"cpu\",kernelFunc:lp};function yz(e){let{inputs:t,backend:a,attrs:n}=e,{equation:r}=n,s=t,{allDims:i,summedDims:o,idDims:l}=T.decodeEinsumEquation(r,s.length);T.checkEinsumDimSizes(i.length,l,s);let{path:u,steps:p}=T.getEinsumComputePath(o,l),c=p.length,d=null,h=i.length,f=[];for(let m=0;m<c;++m){for(let g of p[m]){let{permutationIndices:x,expandDims:A}=T.getEinsumPermutation(h,l[g]),y;T.isIdentityPermutation(x)?y=s[g]:(y=La({inputs:{x:s[g]},backend:a,attrs:{perm:x}}),f.push(y));let b=y.shape.slice();for(let w=0;w<A.length;++w)b.splice(A[w],0,1);v.arraysEqual(y.shape,b)||(y=mt({inputs:{x:y},backend:a,attrs:{shape:b}}),f.push(y)),d===null?d=y:(d=Ph({inputs:{a:y,b:d},backend:a}),f.push(d))}m<c-1&&(u[m]>=0&&(d=lp({inputs:{x:d},backend:a,attrs:{axis:u[m]-(i.length-h),keepDims:!1}}),f.push(d)),h--)}for(let m of f)m!==d&&a.disposeIntermediateTensorInfo(m);return d}var bz={kernelName:Cd,backendName:\"cpu\",kernelFunc:yz};function vz(e){let{inputs:t,backend:a}=e,{dy:n,y:r}=t;ye([n,r],\"eluGrad\");let s=new Float32Array(v.sizeFromShape(r.shape)),i=a.data.get(r.dataId).values,o=a.data.get(n.dataId).values;for(let l=0;l<i.length;++l){let u=i[l];u>=1?s[l]=o[l]:s[l]=o[l]*(u+1)}return a.makeTensorInfo(r.shape,\"float32\",s)}var wz={kernelName:j1,backendName:\"cpu\",kernelFunc:vz},kz=T.ERF_P,Iz=T.ERF_A1,Sz=T.ERF_A2,Tz=T.ERF_A3,Cz=T.ERF_A4,Nz=T.ERF_A5,Ez=ot($l,e=>{let t=Math.sign(e),a=Math.abs(e),n=1/(1+kz*a);return t*(1-((((Nz*n+Cz)*n+Tz)*n+Sz)*n+Iz)*n*Math.exp(-a*a))}),Rz={kernelName:$l,backendName:\"cpu\",kernelFunc:Ez};function Fc(e){let{inputs:t,backend:a,attrs:n}=e,{input:r}=t,{dim:s}=n,i=r.shape.length,o=r.shape.slice(),l=s;return s<0&&(v.assert(-(i+1)<=s,()=>`Axis must be in the interval [${-(i+1)}, ${i}]`),l=i+s+1),o.splice(l,0,1),mt({inputs:{x:r},backend:a,attrs:{shape:o}})}var Mz={kernelName:_l,backendName:\"cpu\",kernelFunc:Fc},$z=Lt((e,t)=>e/t),x3=Yt(ci,$z),b1={kernelName:ci,backendName:\"cpu\",kernelFunc:x3};function B7(e,t,a){let n=e.shape,r=n[0],s=n[1],i=a.data.get(e.dataId),o=i.complexTensorInfos.real,l=i.complexTensorInfos.imag,u=[r,s],p=v.sizeFromShape(u),c=v.getTypedArrayFromDType(\"float32\",p),d=v.getTypedArrayFromDType(\"float32\",p);for(let g=0;g<r;g++){let x=Gs({inputs:{x:o},backend:a,attrs:{begin:[g,0],size:[1,s]}}),A=Gs({inputs:{x:l},backend:a,attrs:{begin:[g,0],size:[1,s]}}),y=Xa({inputs:{real:x,imag:A},backend:a}),{real:b,imag:w}=_z(y,t,a),S=T.mergeRealAndImagArrays(b,w);for(let C=0;C<s;C++){let E=T.getComplexWithIndex(S,C);c[g*s+C]=E.real,d[g*s+C]=E.imag}a.disposeIntermediateTensorInfo(x),a.disposeIntermediateTensorInfo(A),a.disposeIntermediateTensorInfo(y)}let h=a.makeTensorInfo(u,\"float32\",c),f=a.makeTensorInfo(u,\"float32\",d),m=Xa({inputs:{real:h,imag:f},backend:a});return a.disposeIntermediateTensorInfo(h),a.disposeIntermediateTensorInfo(f),m}function _z(e,t,a){let n=v.sizeFromShape(e.shape),r=a.data.get(e.dataId),s=a.data.get(r.complexTensorInfos.real.dataId).values,i=a.data.get(r.complexTensorInfos.imag.dataId).values;if(Pz(n)){let o=v1(s,i,n,t,a),l=[e.shape[0],e.shape[1]];if(t){let u=a.makeTensorInfo(l,\"float32\",o.real),p=a.makeTensorInfo(l,\"float32\",o.imag),c=a.makeTensorInfo([],\"float32\",v.createScalarValue(n,\"float32\")),d=er({inputs:{x:c},backend:a}),h=b1.kernelFunc({inputs:{a:u,b:c},backend:a}),f=b1.kernelFunc({inputs:{a:p,b:d},backend:a}),m=a.data.get(h.dataId).values,g=a.data.get(f.dataId).values;return a.disposeIntermediateTensorInfo(u),a.disposeIntermediateTensorInfo(p),a.disposeIntermediateTensorInfo(c),a.disposeIntermediateTensorInfo(d),a.disposeIntermediateTensorInfo(h),a.disposeIntermediateTensorInfo(f),{real:m,imag:g}}return o}else{let o=T.mergeRealAndImagArrays(s,i),l=Fz(o,n,t);return T.splitRealAndImagArrays(l)}}function Pz(e){return(e&e-1)===0}function v1(e,t,a,n,r){if(a===1)return{real:e,imag:t};let s=T.mergeRealAndImagArrays(e,t),i=a/2,o=T.complexWithEvenIndex(s),l=o.real,u=o.imag,p=[l.length],c=r.makeTensorInfo(p,\"float32\",l),d=r.makeTensorInfo(p,\"float32\",u),h=Xa({inputs:{real:c,imag:d},backend:r}),f=T.complexWithOddIndex(s),m=f.real,g=f.imag,x=[m.length],A=r.makeTensorInfo(x,\"float32\",m),y=r.makeTensorInfo(x,\"float32\",g),b=Xa({inputs:{real:A,imag:y},backend:r}),w=v1(l,u,i,n,r),S=w.real,C=w.imag,E=[S.length],_=r.makeTensorInfo(E,\"float32\",S),$=r.makeTensorInfo(E,\"float32\",C),M=Xa({inputs:{real:_,imag:$},backend:r}),I=v1(m,g,i,n,r),N=I.real,O=I.imag,L=[N.length],B=r.makeTensorInfo(L,\"float32\",N),G=r.makeTensorInfo(L,\"float32\",O),j=Xa({inputs:{real:B,imag:G},backend:r}),U=T.exponents(a,n),H=[U.real.length],V=r.makeTensorInfo(H,\"float32\",U.real),Q=r.makeTensorInfo(H,\"float32\",U.imag),Z=Xa({inputs:{real:V,imag:Q},backend:r}),re=Ph({inputs:{a:Z,b:j},backend:r}),ee=ml({inputs:{a:M,b:re},backend:r}),he=m3({inputs:{a:M,b:re},backend:r}),oe=Us({inputs:{input:ee},backend:r}),Ae=Us({inputs:{input:he},backend:r}),we=gl({inputs:{input:ee},backend:r}),Re=gl({inputs:{input:he},backend:r}),Ge=xl({inputs:[oe,Ae],backend:r,attrs:{axis:0}}),Ke=xl({inputs:[we,Re],backend:r,attrs:{axis:0}}),nt=r.data.get(Ge.dataId).values,ut=r.data.get(Ke.dataId).values;return r.disposeIntermediateTensorInfo(c),r.disposeIntermediateTensorInfo(d),r.disposeIntermediateTensorInfo(h),r.disposeIntermediateTensorInfo(A),r.disposeIntermediateTensorInfo(y),r.disposeIntermediateTensorInfo(b),r.disposeIntermediateTensorInfo(_),r.disposeIntermediateTensorInfo($),r.disposeIntermediateTensorInfo(M),r.disposeIntermediateTensorInfo(B),r.disposeIntermediateTensorInfo(G),r.disposeIntermediateTensorInfo(j),r.disposeIntermediateTensorInfo(V),r.disposeIntermediateTensorInfo(Q),r.disposeIntermediateTensorInfo(Z),r.disposeIntermediateTensorInfo(re),r.disposeIntermediateTensorInfo(ee),r.disposeIntermediateTensorInfo(he),r.disposeIntermediateTensorInfo(oe),r.disposeIntermediateTensorInfo(we),r.disposeIntermediateTensorInfo(Ae),r.disposeIntermediateTensorInfo(Re),r.disposeIntermediateTensorInfo(Ge),r.disposeIntermediateTensorInfo(Ke),{real:nt,imag:ut}}function Fz(e,t,a){let n=new Float32Array(t*2);for(let r=0;r<t;r++){let s=0,i=0;for(let o=0;o<t;o++){let l=T.exponent(r*o,t,a),u=T.getComplexWithIndex(e,o);s+=u.real*l.real-u.imag*l.imag,i+=u.real*l.imag+u.imag*l.real}a&&(s/=t,i/=t),T.assignToTypedArray(n,s,i,r)}return n}function Oz(e){let{inputs:t,backend:a}=e,{input:n}=t,r=v.sizeFromShape(n.shape),s=n.shape[n.shape.length-1],i=r/s,o=mt({inputs:{x:n},backend:a,attrs:{shape:[i,s]}}),l=B7(o,!1,a),u=mt({inputs:{x:l},backend:a,attrs:{shape:n.shape}});return a.disposeIntermediateTensorInfo(o),a.disposeIntermediateTensorInfo(l),u}var Dz={kernelName:Nd,backendName:\"cpu\",kernelFunc:Oz};function A3(e){let{backend:t,attrs:a}=e,{shape:n,value:r,dtype:s}=a,i=s||v.inferDtype(r),o=v.getArrayFromDType(i,v.sizeFromShape(n));return Lz(o,r,i),t.makeTensorInfo(n,i,o)}var zz={kernelName:Fl,backendName:\"cpu\",kernelFunc:A3};function Lz(e,t,a){e.fill(t)}var Bz={kernelName:gi,backendName:\"cpu\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{image:n}=e,r=a,s=v.getTypedArrayFromDType(n.dtype,v.sizeFromShape(n.shape)),[i,o,l,u]=n.shape,p=r.data.get(n.dataId).values;for(let c=0;c<i;c++){let d=c*l*o*u;for(let h=0;h<o;h++){let f=h*(l*u);for(let m=0;m<l;m++){let g=m*u;for(let x=0;x<u;x++){let A=Math.round(l-m-1),y=d+f+g+x,b=p[y];if(A>=0&&A<l){let w=A*u,S=d+f+w+x;b=p[S]}s[y]=b}}}}return{dataId:r.write(s,n.shape,n.dtype),shape:n.shape,dtype:n.dtype}}},Wz=Lt((e,t)=>Math.floor(e/t)),Vz=Yt(Ai,Wz,null,\"int32\"),Uz={kernelName:Ai,backendName:\"cpu\",kernelFunc:Vz};function Gz(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s,bias:i,preluActivationWeights:o}=t,{strides:l,pad:u,dataFormat:p,dilations:c,dimRoundingMode:d,activation:h,leakyreluAlpha:f}=n,m=z7({inputs:{x:r,filter:s},backend:a,attrs:{strides:l,pad:u,dataFormat:p,dilations:c,dimRoundingMode:d}});if(i){let g=m;if(p===\"NCHW\"&&i.shape.length===1&&i.shape[0]!==1){let x=mt({inputs:{x:i},backend:a,attrs:{shape:[i.shape[0],1,1]}});m=ml({inputs:{a:m,b:x},backend:a}),a.disposeIntermediateTensorInfo(x)}else m=ml({inputs:{a:m,b:i},backend:a});a.disposeIntermediateTensorInfo(g)}if(h){let g=m;if(p===\"NCHW\"&&h===\"prelu\"&&o.shape.length===1&&o.shape[0]!==1){let x=mt({inputs:{x:o},backend:a,attrs:{shape:[o.shape[0],1,1]}});m=Pc(a,m,h,x,f),a.disposeIntermediateTensorInfo(x)}else m=Pc(a,m,h,o,f);a.disposeIntermediateTensorInfo(g)}return m}var Hz={kernelName:qr,backendName:\"cpu\",kernelFunc:Gz};function jz(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s,bias:i,preluActivationWeights:o}=t,{strides:l,pad:u,dataFormat:p,dilations:c,dimRoundingMode:d,activation:h,leakyreluAlpha:f}=n,m=L7({inputs:{x:r,filter:s},backend:a,attrs:{strides:l,pad:u,dataFormat:p,dilations:c,dimRoundingMode:d}});if(i){let g=m;m=ml({inputs:{a:m,b:i},backend:a}),a.disposeIntermediateTensorInfo(g)}if(h){let g=m;m=Pc(a,m,h,o,f),a.disposeIntermediateTensorInfo(g)}return m}var qz={kernelName:Xr,backendName:\"cpu\",kernelFunc:jz};function Xz(e){let{inputs:t,backend:a}=e,{params:n,indices:r}=t,s=v.sizeFromShape(n.shape),i=r.shape,o=i[i.length-1],[l,u,p,c]=T.prepareAndValidate(n,r);if(u===0)return a.makeTensorInfo(l,n.dtype,[]);let d=a.data.get(r.dataId).values,h=a.bufferSync(n),f=a7(d,h,n.dtype,u,o,p,c,n.shape,s);return a.makeTensorInfo(l,n.dtype,f.values)}var Kz={kernelName:bi,backendName:\"cpu\",kernelFunc:Xz};function Zz(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,indices:s}=t,{axis:i,batchDims:o}=n;ye([r,s],\"gatherV2\");let l=v.parseAxisParam(i,r.shape)[0],u=a.data.get(s.dataId).values,p=r.shape[l];for(let b=0;b<u.length;++b){let w=u[b];v.assert(w<=p-1&&w>=0,()=>`GatherV2: the index value ${w} is not in [0, ${p-1}]`)}let c=o;o==null&&(c=0);let d=v.sizeFromShape(s.shape),h=T.segment_util.collectGatherOpShapeInfo(r,s,l,c),f=mt({inputs:{x:r},backend:a,attrs:{shape:[h.batchSize,h.outerSize,h.dimSize,h.sliceSize]}}),m=mt({inputs:{x:s},backend:a,attrs:{shape:[h.batchSize,d/h.batchSize]}}),g=[h.batchSize,h.outerSize,d/h.batchSize,h.sliceSize],x=a.bufferSync(m),A=a.bufferSync(f),y=n7(A,x,g);return a.disposeIntermediateTensorInfo(f),a.disposeIntermediateTensorInfo(m),a.makeTensorInfo(h.outputShape,y.dtype,y.values)}var Yz={kernelName:Ol,backendName:\"cpu\",kernelFunc:Zz};function Jz(e){let{inputs:t,backend:a}=e,{input:n}=t,r=v.sizeFromShape(n.shape),s=n.shape[n.shape.length-1],i=r/s,o=mt({inputs:{x:n},backend:a,attrs:{shape:[i,s]}}),l=B7(o,!0,a),u=mt({inputs:{x:l},backend:a,attrs:{shape:n.shape}});return a.disposeIntermediateTensorInfo(o),a.disposeIntermediateTensorInfo(l),u}var Qz={kernelName:Ed,backendName:\"cpu\",kernelFunc:Jz},eL=ot(Dl,e=>Number.isFinite(e)?1:0,\"bool\"),tL={kernelName:Dl,backendName:\"cpu\",kernelFunc:eL},aL=ot(zl,e=>Math.abs(e)===1/0?1:0,\"bool\"),nL={kernelName:zl,backendName:\"cpu\",kernelFunc:aL},rL=ot(Ii,e=>Number.isNaN(e)?1:0,\"bool\"),sL={kernelName:Ii,backendName:\"cpu\",kernelFunc:rL};function iL(e){let{backend:t,attrs:a}=e,{start:n,stop:r,num:s}=a,i=l7(n,r,s);return t.makeTensorInfo([i.length],\"float32\",i)}var oL={kernelName:th,backendName:\"cpu\",kernelFunc:iL},lL=ot(Ll,e=>Math.log1p(e)),uL={kernelName:Ll,backendName:\"cpu\",kernelFunc:lL},dL=Lt((e,t)=>e&&t),pL=Yt(Ei,dL,null,\"bool\"),cL={kernelName:Ei,backendName:\"cpu\",kernelFunc:pL},hL=ot(Ri,e=>e?0:1,\"bool\"),fL={kernelName:Ri,backendName:\"cpu\",kernelFunc:hL},mL=Lt((e,t)=>e||t),gL=Yt(Bl,mL,null,\"bool\"),xL={kernelName:Bl,backendName:\"cpu\",kernelFunc:gL};function AL(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{depthRadius:s,bias:i,alpha:o,beta:l}=n;ye(r,\"LRN\");let u=r.shape[3],p=u-1,c=a.data.get(r.dataId).values,d=v.sizeFromShape(r.shape),h=new Float32Array(d);function f(m){let g=m%u,x=m-g+Math.max(0,g-s),A=m-g+Math.min(g+s,p),y=0;for(;x<=A;x++){let b=c[x];y+=b*b}return y}for(let m=0;m<d;m++){let g=f(m),x=c[m]*Math.pow(i+o*g,-l);h[m]=x}return a.makeTensorInfo(r.shape,r.dtype,h)}var yL={kernelName:ah,backendName:\"cpu\",kernelFunc:AL};function bL(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,y:s,dy:i}=t,{depthRadius:o,bias:l,alpha:u,beta:p}=n;ye(i,\"LRNGrad\");let c=v.sizeFromShape(i.shape),d=i.shape[3],h=a.data.get(i.dataId).values,f=a.data.get(r.dataId).values,m=a.data.get(s.dataId).values,g=new Float32Array(c),x=c;for(let A=0;A<x;A++){let y=A%d,b=A-y+Math.max(0,y-o),w=A-y+Math.min(d,y+o+1),S=0;for(let C=b;C<w;C++)S+=Math.pow(f[C],2);S=u*S+l;for(let C=b;C<w;C++){let E=-2*u*p*f[C]*m[A]/S;A===C&&(E+=Math.pow(S,-p)),E*=h[A],g[C]+=E}}return a.makeTensorInfo(i.shape,r.dtype,g)}var vL={kernelName:q1,backendName:\"cpu\",kernelFunc:bL};function W7(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{reductionIndices:s,keepDims:i}=n,o=a,l=r.shape,u=l.length,p=v.parseAxisParam(s,l),c=p,d=T.getAxesPermutation(c,u),h=o.data.get(r.dataId).values;if(d!=null){let b=new Array(u);for(let w=0;w<b.length;w++)b[w]=l[d[w]];h=u3(h,l,r.dtype,d,b),c=T.getInnerMostAxes(c.length,u),l=b}ye(r,\"max\"),T.assertAxesAreInnerMostDims(\"max\",c,u);let[f,m]=T.computeOutAndReduceShapes(l,c),g=v.sizeFromShape(m),x=d7(h,g,f,r.dtype),A=o.write(x,f,r.dtype),y=f;return i&&(y=T.expandShapeToKeepDim(f,p)),{dataId:A,shape:y,dtype:r.dtype}}var wL={kernelName:Mi,backendName:\"cpu\",kernelFunc:W7};function kL(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t;ye(r,\"maxPool\");let{filterSize:s,strides:i,pad:o,dimRoundingMode:l}=n,u=1;v.assert(T.eitherStridesOrDilationsAreOne(i,u),()=>`Error in maxPool: Either strides or dilations must be 1. Got strides ${i} and dilations '${u}'`);let p=T.computePool2DInfo(r.shape,s,i,u,o,l),c;if(p.filterWidth===1&&p.filterHeight===1&&v.arraysEqual(p.inShape,p.outShape))c=er({inputs:{x:r},backend:a});else{let d=a.data.get(r.dataId).values,h=v.computeStrides(r.shape),f=g3(d,r.shape,r.dtype,h,p,\"max\");c=a.makeTensorInfo(p.outShape,r.dtype,f.values)}return c}var IL={kernelName:_i,backendName:\"cpu\",kernelFunc:kL};function SL(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{filterSize:s,strides:i,pad:o,dimRoundingMode:l,dataFormat:u}=n;ye(r,\"maxPool3d\");let p=T.computePool3DInfo(r.shape,s,i,1,o,l,u),c=a.data.get(r.dataId).values,d=D7(c,r.shape,r.dtype,v.computeStrides(r.shape),p,\"max\");return a.makeTensorInfo(d.shape,\"float32\",d.values)}var TL={kernelName:nh,backendName:\"cpu\",kernelFunc:SL};function CL(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,input:s}=t,{filterSize:i,strides:o,pad:l,dimRoundingMode:u}=n;ye([r,s],\"maxPool3DGrad\");let p=T.computePool3DInfo(s.shape,i,o,1,l,u),c=a.bufferSync(s),d=fD(c,p),h=p.strideDepth,f=p.strideHeight,m=p.strideWidth,g=p.dilationDepth,x=p.dilationHeight,A=p.dilationWidth,y=p.effectiveFilterDepth,b=p.effectiveFilterHeight,w=p.effectiveFilterWidth,S=y-1-p.padInfo.front,C=w-1-p.padInfo.left,E=b-1-p.padInfo.top,_=Me(s.shape,\"float32\"),$=a.bufferSync(r);for(let M=0;M<p.batchSize;++M)for(let I=0;I<p.inChannels;++I)for(let N=0;N<p.inDepth;++N)for(let O=0;O<p.inHeight;++O)for(let L=0;L<p.inWidth;++L){let B=N-S,G=O-E,j=L-C,U=0;for(let H=0;H<y;H+=g){let V=(B+H)/h;if(!(V<0||V>=p.outDepth||Math.floor(V)!==V))for(let Q=0;Q<b;Q+=x){let Z=(G+Q)/f;if(!(Z<0||Z>=p.outHeight||Math.floor(Z)!==Z))for(let re=0;re<w;re+=A){let ee=(j+re)/m;if(ee<0||ee>=p.outWidth||Math.floor(ee)!==ee)continue;let he=y*b*w-1-d.get(M,V,Z,ee,I),oe=H*b*w+Q*w+re,Ae=he===oe?1:0;if(Ae===0)continue;let we=$.get(M,V,Z,ee,I);U+=we*Ae}}}_.set(U,M,N,O,L,I)}return a.makeTensorInfo(_.shape,_.dtype,_.values)}var NL={kernelName:K1,backendName:\"cpu\",kernelFunc:CL};function EL(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,input:s,output:i}=t,o=s;ye([s,i],\"maxPoolGrad\");let{filterSize:l,strides:u,pad:p,dimRoundingMode:c}=n,d=T.computePool2DInfo(o.shape,l,u,1,p,c),h=a.data.get(o.dataId).values,f=Me(d.outShape,o.dtype,O7(h,o.shape,o.dtype,d).values),m=d.strideHeight,g=d.strideWidth,x=d.dilationHeight,A=d.dilationWidth,y=d.effectiveFilterHeight,b=d.effectiveFilterWidth,w=b-1-d.padInfo.left,S=y-1-d.padInfo.top,C=Me(o.shape,\"float32\"),E=a.data.get(r.dataId).values,_=Me(r.shape,\"float32\",E);for(let $=0;$<d.batchSize;++$)for(let M=0;M<d.inChannels;++M)for(let I=0;I<d.inHeight;++I)for(let N=0;N<d.inWidth;++N){let O=I-S,L=N-w,B=0;for(let G=0;G<y;G+=x){let j=(O+G)/m;if(!(j<0||j>=d.outHeight||Math.floor(j)!==j))for(let U=0;U<b;U+=A){let H=(L+U)/g;if(H<0||H>=d.outWidth||Math.floor(H)!==H)continue;let V=y*b-1-f.get($,j,H,M),Q=G*b+U,Z=V===Q?1:0;if(Z===0)continue;let re=_.get($,j,H,M);B+=re*Z}}C.set(B,$,I,N,M)}return a.makeTensorInfo(C.shape,C.dtype,C.values)}var RL={kernelName:X1,backendName:\"cpu\",kernelFunc:EL};function ML(e,t,a,n,r){let s=v.computeStrides(t),i=g3(e,t,a,s,r,\"max\"),o=O7(e,t,a,r,!0,n);return[i.values,o.values]}var $L={kernelName:rh,backendName:\"cpu\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{x:n}=e,{filterSize:r,strides:s,pad:i,includeBatchInIndex:o}=t,l=a;ye(n,\"MaxPoolWithArgmax\");let u=l.data.get(n.dataId).values,p=T.computePool2DInfo(n.shape,r,s,[1,1],i),[c,d]=ML(u,n.shape,n.dtype,o,p),h=l.write(c,p.outShape,n.dtype),f=l.write(d,p.outShape,n.dtype);return[{dataId:h,shape:p.outShape,dtype:n.dtype},{dataId:f,shape:p.outShape,dtype:\"int32\"}]}};function _L(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n,o=v.parseAxisParam(s,r.shape),l=T.computeOutAndReduceShapes(r.shape,o)[1],u=v.sizeFromShape(l),p=[],c=a.makeTensorInfo([],\"float32\",new Float32Array([u]));p.push(c);let d=Jr({inputs:{x:r},backend:a,attrs:{dtype:\"float32\"}});p.push(d);let h=x3({inputs:{a:d,b:c},backend:a});p.push(h);let f=lp({inputs:{x:h},backend:a,attrs:{axis:s,keepDims:i}});return p.forEach(m=>a.disposeIntermediateTensorInfo(m)),f}var PL={kernelName:Pi,backendName:\"cpu\",kernelFunc:_L};function FL(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;ye(r,\"min\");let o=v.parseAxisParam(s,r.shape),l=o,u=T.getAxesPermutation(l,r.shape.length),p=r;u!=null&&(p=La({inputs:{x:r},backend:a,attrs:{perm:u}}),l=T.getInnerMostAxes(l.length,r.shape.length)),T.assertAxesAreInnerMostDims(\"min\",l,p.shape.length);let[c,d]=T.computeOutAndReduceShapes(p.shape,l),h=v.sizeFromShape(d),f=v.makeZerosTypedArray(v.sizeFromShape(c),p.dtype),m=a.data.get(p.dataId).values;for(let x=0;x<f.length;++x){let A=x*h,y=m[A];for(let b=0;b<h;++b){let w=m[A+b];(Number.isNaN(w)||w<y)&&(y=w)}f[x]=y}u!=null&&a.disposeIntermediateTensorInfo(p);let g=a.makeTensorInfo(c,p.dtype,f);if(i){let x=T.expandShapeToKeepDim(c,o),A=mt({inputs:{x:g},backend:a,attrs:{shape:x}});return a.disposeIntermediateTensorInfo(g),A}return g}var OL={kernelName:Fi,backendName:\"cpu\",kernelFunc:FL};function DL(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{paddings:s,mode:i}=n;ye(r,\"mirrorPad\");let o=s.map((A,y)=>A[0]+r.shape[y]+A[1]),l=s.map(A=>A[0]),u=s.map((A,y)=>A[0]+r.shape[y]),p=i===\"reflect\"?0:1,c=a.data.get(r.dataId).values,d=r.shape.length,h=v.computeStrides(r.shape),f=v.sizeFromShape(o),m=o.length,g=v.computeStrides(o),x=v.getTypedArrayFromDType(r.dtype,f);for(let A=0;A<f;A++){let y=v.indexToLoc(A,m,g);for(let w=0;w<m;w++)y[w]<l[w]?y[w]=l[w]*2-y[w]-p:y[w]>=u[w]&&(y[w]=(u[w]-1)*2-y[w]+p);y=y.map((w,S)=>w-l[S]);let b=v.locToIndex(y,d,h);x[A]=c[b]}return{dataId:a.write(x,o,r.dtype),shape:o,dtype:r.dtype}}var zL={kernelName:Di,backendName:\"cpu\",kernelFunc:DL},LL=Lt((e,t)=>{let a=e%t;return e<0&&t<0||e>=0&&t>=0?a:(a+t)%t}),BL=Yt(Wl,LL),WL={kernelName:Wl,backendName:\"cpu\",kernelFunc:BL},VL=yl(nA());function V7(e){let{inputs:t,backend:a,attrs:n}=e,{logits:r}=t,{dim:s}=n,i=r.shape.length,o=s;if(o===-1&&(o=i-1),o!==i-1)throw Error(`Softmax along a non-last dimension is not yet supported. Logits was rank ${i} and dim was ${o}`);let l=v.parseAxisParam([o],r.shape),u=W7({inputs:{x:r},backend:a,attrs:{reductionIndices:l,keepDims:!1}}),p=T.expandShapeToKeepDim(u.shape,l),c=mt({inputs:{x:u},backend:a,attrs:{shape:p}}),d=m3({inputs:{a:r,b:c},backend:a}),h=Q4({inputs:{x:d},backend:a}),f=lp({inputs:{x:h},backend:a,attrs:{axis:l,keepDims:!1}}),m=mt({inputs:{x:f},backend:a,attrs:{shape:p}}),g=x3({inputs:{a:h,b:m},backend:a});return a.disposeIntermediateTensorInfo(u),a.disposeIntermediateTensorInfo(c),a.disposeIntermediateTensorInfo(d),a.disposeIntermediateTensorInfo(h),a.disposeIntermediateTensorInfo(f),a.disposeIntermediateTensorInfo(m),g}var UL={kernelName:so,backendName:\"cpu\",kernelFunc:V7};function GL(e){let{inputs:t,backend:a,attrs:n}=e,{logits:r}=t,{numSamples:s,seed:i,normalized:o}=n;ye(r,\"multinomial\");let l=o?r:V7({inputs:{logits:r},backend:a,attrs:{dim:-1}}),u=l.shape[0],p=l.shape[1],c=a.data.get(l.dataId).values,d=[u,s],h=v.makeZerosTypedArray(v.sizeFromShape(d),\"int32\");for(let f=0;f<u;++f){let m=f*p,g=new Float32Array(p-1);g[0]=c[m];for(let y=1;y<g.length;++y)g[y]=g[y-1]+c[m+y];let x=VL.alea(i.toString()),A=f*s;for(let y=0;y<s;++y){let b=x();h[A+y]=g.length;for(let w=0;w<g.length;w++)if(b<g[w]){h[A+y]=w;break}}}return o||a.disposeIntermediateTensorInfo(l),a.makeTensorInfo(d,\"int32\",h)}var HL={kernelName:sh,backendName:\"cpu\",kernelFunc:GL},jL=Tn.nonMaxSuppressionV3Impl;function qL(e){let{inputs:t,backend:a,attrs:n}=e,{boxes:r,scores:s}=t,{maxOutputSize:i,iouThreshold:o,scoreThreshold:l}=n;ye(r,\"NonMaxSuppression\");let u=a.data.get(r.dataId).values,p=a.data.get(s.dataId).values,{selectedIndices:c}=jL(u,p,i,o,l);return a.makeTensorInfo([c.length],\"int32\",new Int32Array(c))}var XL={kernelName:Bi,backendName:\"cpu\",kernelFunc:qL},KL=Tn.nonMaxSuppressionV4Impl;function ZL(e){let{inputs:t,backend:a,attrs:n}=e,{boxes:r,scores:s}=t,{maxOutputSize:i,iouThreshold:o,scoreThreshold:l,padToMaxOutputSize:u}=n;ye(r,\"NonMaxSuppressionPadded\");let p=a.data.get(r.dataId).values,c=a.data.get(s.dataId).values,{selectedIndices:d,validOutputs:h}=KL(p,c,i,o,l,u);return[a.makeTensorInfo([d.length],\"int32\",new Int32Array(d)),a.makeTensorInfo([],\"int32\",new Int32Array([h]))]}var YL={kernelName:Ul,backendName:\"cpu\",kernelFunc:ZL},JL=Tn.nonMaxSuppressionV5Impl;function QL(e){let{inputs:t,backend:a,attrs:n}=e,{boxes:r,scores:s}=t,{maxOutputSize:i,iouThreshold:o,scoreThreshold:l,softNmsSigma:u}=n;ye(r,\"NonMaxSuppressionWithScore\");let p=a.data.get(r.dataId).values,c=a.data.get(s.dataId).values,d=i,h=o,f=l,m=u,{selectedIndices:g,selectedScores:x}=JL(p,c,d,h,f,m);return[a.makeTensorInfo([g.length],\"int32\",new Int32Array(g)),a.makeTensorInfo([x.length],\"float32\",new Float32Array(x))]}var eB={kernelName:Wi,backendName:\"cpu\",kernelFunc:QL};function tB(e){let{inputs:t,backend:a,attrs:n}=e,{indices:r}=t,{dtype:s,depth:i,onValue:o,offValue:l}=n;ye(r,\"oneHot\");let u=v.sizeFromShape(r.shape),p=new Float32Array(u*i);p.fill(l);let c=a.data.get(r.dataId).values;for(let d=0;d<u;++d)c[d]>=0&&c[d]<i&&(p[d*i+c[d]]=o);return a.makeTensorInfo([...r.shape,i],s,p)}var aB={kernelName:Vi,backendName:\"cpu\",kernelFunc:tB};function Oc(e){let{inputs:t,backend:a}=e,{x:n}=t;if(n.dtype===\"string\")throw new Error(\"zerosLike is not supported for string tensors\");if(n.dtype===\"complex64\"){let r=Us({inputs:{input:n},backend:a}),s=Oc({inputs:{x:r},backend:a}),i=gl({inputs:{input:n},backend:a}),o=Oc({inputs:{x:i},backend:a}),l=Xa({inputs:{real:s,imag:o},backend:a});return a.disposeIntermediateTensorInfo(r),a.disposeIntermediateTensorInfo(s),a.disposeIntermediateTensorInfo(i),a.disposeIntermediateTensorInfo(o),l}else return A3({backend:a,attrs:{shape:n.shape,value:0,dtype:n.dtype}})}var nB={kernelName:nu,backendName:\"cpu\",kernelFunc:Oc};function U7(e){let{inputs:t,backend:a}=e,{x:n}=t;if(n.dtype===\"string\")throw new Error(\"onesLike is not supported for string tensors\");if(n.dtype===\"complex64\"){let r=Us({inputs:{input:n},backend:a}),s=U7({inputs:{x:r},backend:a}),i=gl({inputs:{input:n},backend:a}),o=Oc({inputs:{x:i},backend:a}),l=Xa({inputs:{real:s,imag:o},backend:a});return a.disposeIntermediateTensorInfo(r),a.disposeIntermediateTensorInfo(s),a.disposeIntermediateTensorInfo(i),a.disposeIntermediateTensorInfo(o),l}else return A3({backend:a,attrs:{shape:n.shape,value:1,dtype:n.dtype}})}var rB={kernelName:Gl,backendName:\"cpu\",kernelFunc:U7};function G7(e){let{inputs:t,backend:a,attrs:n}=e,{axis:r}=n;if(t.length===1)return Fc({inputs:{input:t[0]},backend:a,attrs:{dim:r}});let s=t[0].shape,i=t[0].dtype;t.forEach(p=>{v.assertShapesMatch(s,p.shape,\"All tensors passed to stack must have matching shapes\"),v.assert(i===p.dtype,()=>\"All tensors passed to stack must have matching dtypes\")});let o=[],l=t.map(p=>{let c=Fc({inputs:{input:p},backend:a,attrs:{dim:r}});return o.push(c),c}),u=xl({inputs:l,backend:a,attrs:{axis:r}});return o.forEach(p=>a.disposeIntermediateTensorInfo(p)),u}var sB={kernelName:Hl,backendName:\"cpu\",kernelFunc:G7};function iB(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{paddings:s,constantValue:i}=n;ye(r,\"pad\");let o=s.map((x,A)=>x[0]+r.shape[A]+x[1]),l=s.map(x=>x[0]),u=a.data.get(r.dataId).values,p=v.sizeFromShape(r.shape),c=r.shape.length,d=v.computeStrides(r.shape),h=v.sizeFromShape(o),f=o.length,m=v.computeStrides(o),g=v.getTypedArrayFromDType(r.dtype,h);i!==0&&g.fill(i);for(let x=0;x<p;x++){let A=v.indexToLoc(x,c,d).map((b,w)=>b+l[w]),y=v.locToIndex(A,f,m);g[y]=u[x]}return{dataId:a.write(g,o,r.dtype),shape:o,dtype:r.dtype}}var H7={kernelName:Ui,backendName:\"cpu\",kernelFunc:iB},oB=Lt((e,t)=>Math.pow(e,t)),lB=Yt(Gi,oB),uB={kernelName:Gi,backendName:\"cpu\",kernelFunc:lB};function dB(e){let{inputs:t,backend:a,attrs:n}=e,{paramsNestedSplits:r,paramsDenseValues:s,indices:i}=t,{outputRaggedRank:o}=n,l=r.map(x=>a.data.get(x.dataId).values),u=r.map(x=>x.shape),p=a.data.get(s.dataId).values,c=a.data.get(i.dataId).values,[d,h,f]=g7(l,u,p,s.shape,s.dtype,c,i.shape,o),m=d.map(x=>a.makeTensorInfo([x.length],\"int32\",x)),g=a.makeTensorInfo(f,s.dtype,h);return m.concat([g])}var pB={kernelName:ih,backendName:\"cpu\",kernelFunc:dB};function cB(e){let{inputs:t,backend:a}=e,{starts:n,limits:r,deltas:s}=t,i=a.data.get(n.dataId).values,o=a.data.get(r.dataId).values,l=a.data.get(s.dataId).values,[u,p]=x7(i,n.shape,n.dtype,o,r.shape,l,s.shape),c=a.makeTensorInfo([u.length],\"int32\",u),d=a.makeTensorInfo([p.length],n.dtype,p);return[c,d]}var hB={kernelName:oh,backendName:\"cpu\",kernelFunc:cB};function fB(e){let{inputs:t,backend:a,attrs:n}=e,{shape:r,values:s,defaultValue:i,rowPartitionTensors:o}=t,{rowPartitionTypes:l}=n,u=a.data.get(r.dataId).values,p=a.data.get(s.dataId).values,c=a.data.get(i.dataId).values,d=o.map(g=>a.data.get(g.dataId).values),h=o.map(g=>g.shape),[f,m]=A7(u,r.shape,p,s.shape,s.dtype,c,i.shape,d,h,l);return a.makeTensorInfo(f,s.dtype,m)}var mB={kernelName:lh,backendName:\"cpu\",kernelFunc:fB};function gB(e){let{backend:t,attrs:a}=e,{start:n,stop:r,dtype:s,step:i}=a,o=d3(n,r,i,s);return t.makeTensorInfo([o.length],s,o)}var xB={kernelName:jl,backendName:\"cpu\",kernelFunc:gB},AB=ot(qi,e=>1/e),yB={kernelName:qi,backendName:\"cpu\",kernelFunc:AB};function bB(e){let{inputs:t,backend:a,attrs:n}=e,{images:r}=t,{alignCorners:s,halfPixelCenters:i,size:o}=n;ye(r,\"resizeBilinear\");let l=v.computeStrides(r.shape),[u,p]=o,[c,d,h,f]=r.shape,m=a.data.get(r.dataId).values,g=new Float32Array(v.sizeFromShape([c,u,p,f])),x=[s&&u>1?d-1:d,s&&p>1?h-1:h],A=[s&&u>1?u-1:u,s&&p>1?p-1:p],y=0,b=x[0]/A[0],w=x[1]/A[1];for(let S=0;S<c;S++)for(let C=0;C<u;C++){let E;i?E=b*(C+.5)-.5:E=b*C;let _=Math.max(0,Math.floor(E)),$=E-_,M=Math.min(d-1,Math.ceil(E)),I=S*l[0]+_*l[1],N=S*l[0]+M*l[1];for(let O=0;O<p;O++){let L;i?L=w*(O+.5)-.5:L=w*O;let B=Math.max(0,Math.floor(L)),G=L-B,j=Math.min(h-1,Math.ceil(L)),U=I+B*l[2],H=N+B*l[2],V=I+j*l[2],Q=N+j*l[2];for(let Z=0;Z<f;Z++){let re=m[U+Z],ee=m[H+Z],he=m[V+Z],oe=m[Q+Z],Ae=re+(he-re)*G,we=ee+(oe-ee)*G,Re=Ae+(we-Ae)*$;g[y++]=Re}}}return a.makeTensorInfo([c,u,p,f],\"float32\",g)}var vB={kernelName:Zi,backendName:\"cpu\",kernelFunc:bB};function wB(e){let{inputs:t,backend:a,attrs:n}=e,{images:r,dy:s}=t,{alignCorners:i}=n;ye([s,r],\"resizeBilinearGrad\");let o=v.computeStrides(r.shape),[l,u,p,c]=r.shape,[,d,h]=s.shape,f=new Float32Array(l*u*p*c),m=[i&&d>1?u-1:u,i&&h>1?p-1:p],g=[i&&d>1?d-1:d,i&&h>1?h-1:h],x=m[0]/g[0],A=m[1]/g[1],y=a.data.get(s.dataId).values,b=0;for(let w=0;w<l;w++){let S=w*o[0];for(let C=0;C<d;C++){let E=C*x,_=Math.floor(E),$=Math.min(Math.ceil(E),u-1),M=S+_*o[1],I=S+$*o[1],N=E-_,O=1-N;for(let L=0;L<h;L++){let B=L*A,G=Math.floor(B),j=Math.min(Math.ceil(B),p-1),U=B-G,H=1-U,V=M+G*o[2],Q=M+j*o[2],Z=I+G*o[2],re=I+j*o[2],ee=O*H,he=O*U,oe=N*H,Ae=N*U;for(let we=0;we<c;we++){let Re=y[b++];f[V+we]+=Re*ee,f[Q+we]+=Re*he,f[Z+we]+=Re*oe,f[re+we]+=Re*Ae}}}}return a.makeTensorInfo([l,p,u,c],\"float32\",f)}var kB={kernelName:Y1,backendName:\"cpu\",kernelFunc:wB};function IB(e){let{inputs:t,backend:a,attrs:n}=e,{images:r}=t,{alignCorners:s,halfPixelCenters:i,size:o}=n;ye(r,\"resizeNearestNeighbor\");let l=v.computeStrides(r.shape),[u,p]=o,[c,d,h,f]=r.shape,m=a.data.get(r.dataId).values,g=new Float32Array(c*u*p*f),x=[s&&u>1?d-1:d,s&&p>1?h-1:h],A=[s&&u>1?u-1:u,s&&p>1?p-1:p],y=x[0]/A[0],b=x[1]/A[1],w=0;for(let S=0;S<c;S++){let C=S*l[0];for(let E=0;E<u;E++){let _=i?y*(E+.5):y*E,$=Math.min(d-1,s?Math.round(_):Math.floor(_));i&&($=Math.max(0,$));let M=C+$*l[1];for(let I=0;I<p;I++){let N=i?b*(I+.5):b*I,O=Math.min(h-1,s?Math.round(N):Math.floor(N));i&&(O=Math.max(0,O));let L=M+O*l[2];for(let B=0;B<f;B++){let G=m[L+B];g[w++]=G}}}}return a.makeTensorInfo([c,u,p,f],r.dtype,g)}var SB={kernelName:Ki,backendName:\"cpu\",kernelFunc:IB};function TB(e){let{inputs:t,backend:a,attrs:n}=e,{images:r,dy:s}=t,{alignCorners:i}=n;ye([s,r],\"resizeNearestNeighborGrad\");let o=v.computeStrides(r.shape),l=v.computeStrides(s.shape),[u,p,c,d]=r.shape,[,h,f]=s.shape,m=new Float32Array(u*p*c*d),g=a.data.get(s.dataId).values,x=[i&&h>1?p-1:p,i&&f>1?c-1:c],A=[i&&h>1?h-1:h,i&&f>1?f-1:f],y=x[0]/A[0],b=x[1]/A[1],w=1/y,S=1/b,C=Math.ceil(w)*2+2,E=Math.ceil(S)*2+2;for(let _=0;_<u;_++){let $=_*o[0];for(let M=0;M<p;M++){let I=$+M*o[1],N=Math.floor(M*w),O=Math.floor(N-C/2);for(let L=0;L<c;L++){let B=I+L*o[2],G=Math.floor(L*S),j=Math.floor(G-E/2);for(let U=0;U<d;U++){let H=0;for(let V=0;V<C;V++){let Q=V+O;if(Q<0||Q>=h)continue;let Z=$+Q*l[1],re=Q*y,ee=Math.min(p-1,i?Math.round(re):Math.floor(re));if(M===ee)for(let he=0;he<E;he++){let oe=he+j;if(oe<0||oe>=f)continue;let Ae=Z+oe*l[2],we=oe*b,Re=Math.min(c-1,i?Math.round(we):Math.floor(we));L===Re&&(H+=g[Ae+U])}}m[B+U]=H}}}}return a.makeTensorInfo(r.shape,r.dtype,m)}var CB={kernelName:Z1,backendName:\"cpu\",kernelFunc:TB};function NB(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{dims:s}=n;ye(r,\"reverse\");let i=r.shape.length,o=v.parseAxisParam(s,r.shape);if(i===0)return er({inputs:{x:r},backend:a});let l=new jt(r.shape,r.dtype),u=a.bufferSync(r);for(let p=0;p<l.size;p++){let c=l.indexToLoc(p),d=c.slice();o.forEach(h=>d[h]=r.shape[h]-1-d[h]),l.set(u.get(...d),...c)}return a.makeTensorInfo(l.shape,l.dtype,l.values)}var EB={kernelName:Ji,backendName:\"cpu\",kernelFunc:NB},RB={kernelName:mo,backendName:\"cpu\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{image:n}=e,{radians:r,fillValue:s,center:i}=t,o=a,l=v.getTypedArrayFromDType(n.dtype,v.sizeFromShape(n.shape)),[u,p,c,d]=n.shape,[h,f]=T.getImageCenter(i,p,c),m=255,g=Math.sin(r),x=Math.cos(r),A=o.data.get(n.dataId).values;for(let y=0;y<u;y++){let b=y*c*p*d;for(let w=0;w<p;w++){let S=w*(c*d);for(let C=0;C<c;C++){let E=C*d;for(let _=0;_<d;_++){let $=[u,w,C,_],M=$[2],I=$[1],N=(M-h)*x-(I-f)*g,O=(M-h)*g+(I-f)*x;N=Math.round(N+h),O=Math.round(O+f);let L=s;if(typeof s!=\"number\"&&(_===3?L=m:L=s[_]),N>=0&&N<c&&O>=0&&O<p){let G=O*(c*d),j=N*d,U=b+G+j+_;L=A[U]}let B=b+S+E+_;l[B]=L}}}}return{dataId:o.write(l,n.shape,n.dtype),shape:n.shape,dtype:n.dtype}}},MB=ot(Xl,e=>{let t=Math.floor(e);return e-t<.5?Math.floor(e):e-t>.5?Math.ceil(e):t%2===0?t:t+1}),$B={kernelName:Xl,backendName:\"cpu\",kernelFunc:MB};function _B(e){let{inputs:t,backend:a,attrs:n}=e,{indices:r,updates:s}=t,{shape:i}=n,{sliceRank:o,numUpdates:l,sliceSize:u,strides:p,outputSize:c}=T.calculateShapes(s,r,i),d=!0,h=a.bufferSync(r),f=a.bufferSync(s),m=tl(h,f,i,c,u,l,o,p,0,d);return a.makeTensorInfo(i,m.dtype,m.values)}var PB={kernelName:eo,backendName:\"cpu\",kernelFunc:_B};function FB(e,t){let a=0,n=e.length,r=0;for(;a<n;)r=Math.floor((a+n)/2),e[r]<t?a=r+1:n=r;return n}function OB(e,t){let a=0,n=e.length,r=0;for(;a<n;)r=Math.floor((a+n)/2),e[r]<=t?a=r+1:n=r;return n}function DB(e,t,a,n,r,s){let i=v.getArrayFromDType(\"int32\",a*r);for(let o=0;o<a;++o){let l=e.slice(o*n,(o+1)*n),u=o*r;for(let p=0;p<r;++p)i[u+p]=s===\"left\"?FB(l,t[p+u]):OB(l,t[p+u])}return i}function zB(e){let{inputs:t,backend:a,attrs:n}=e,{sortedSequence:r,values:s}=t,{side:i}=n,o=a.data.get(r.dataId).values,l=a.data.get(s.dataId).values,u=DB(o,l,r.shape[0],r.shape[1],s.shape[1],i);return a.makeTensorInfo(s.shape,\"int32\",u)}var LB={kernelName:$d,backendName:\"cpu\",kernelFunc:zB};function BB(e){let{inputs:t,backend:a}=e,{condition:n,t:r,e:s}=t;ye([n,r,s],\"select\");let i=n.shape.length,o=a.data.get(n.dataId).values,l=a.data.get(r.dataId).values,u=a.data.get(s.dataId).values,p=ca(r.dtype,s.dtype),c=v.makeZerosTypedArray(v.sizeFromShape(r.shape),p),d=0,h=i===0||i>1||r.shape.length===1?1:v.sizeFromShape(r.shape.slice(1));for(let f=0;f<o.length;f++)for(let m=0;m<h;m++)o[f]===1?c[d++]=l[f]:c[d++]=u[f];return a.makeTensorInfo(r.shape,p,c)}var WB={kernelName:Kl,backendName:\"cpu\",kernelFunc:BB},VB=T.SELU_SCALEALPHA,UB=T.SELU_SCALE,GB=ot(_d,e=>e>=0?UB*e:VB*(Math.exp(e)-1)),HB={kernelName:_d,backendName:\"cpu\",kernelFunc:GB},jB=ot(Pd,e=>e<0?-1:e>0?1:0),qB={kernelName:Pd,backendName:\"cpu\",kernelFunc:jB},XB=ot(to,e=>Math.sin(e)),KB={kernelName:to,backendName:\"cpu\",kernelFunc:XB},ZB=ot(Yl,e=>Math.sinh(e)),YB={kernelName:Yl,backendName:\"cpu\",kernelFunc:ZB},JB=11920928955078125e-23,dx=Math.log(JB)+2,QB=ot(Fd,e=>{let t=e>-dx,a=e<dx,n=Math.exp(e),r;return a?r=n:t?r=e:r=Math.log(1+n),r}),eW={kernelName:Fd,backendName:\"cpu\",kernelFunc:QB};function tW(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockShape:s,paddings:i}=n;ye([r],\"spaceToBatchND\");let o=v.sizeFromShape(s),l=[[0,0]];l.push(...i);for(let g=1+s.length;g<r.shape.length;++g)l.push([0,0]);let u=H7.kernelFunc({inputs:{x:r},backend:a,attrs:{paddings:l,constantValue:0}}),p=T.getReshaped(u.shape,s,o,!1),c=T.getPermuted(p.length,s.length,!1),d=T.getReshapedPermuted(u.shape,s,o,!1),h=mt({inputs:{x:u},backend:a,attrs:{shape:p}}),f=La({inputs:{x:h},backend:a,attrs:{perm:c}}),m=mt({inputs:{x:f},backend:a,attrs:{shape:d}});return a.disposeIntermediateTensorInfo(u),a.disposeIntermediateTensorInfo(h),a.disposeIntermediateTensorInfo(f),m}var aW={kernelName:Jl,backendName:\"cpu\",kernelFunc:tW};function nW(e){let{inputs:t,backend:a}=e,{indices:n,values:r,denseShape:s,defaultValue:i}=t;if(s.shape.length!==1)throw new Error(`Dense shape must be a vector, saw:\n        ${s.shape}`);if(n.shape.length!==2)throw new Error(`Indices must be a matrix, saw:\n        ${n.shape}`);if(r.shape.length!==1)throw new Error(`Values must be a vector, saw:\n        ${r.shape}`);if(i.shape.length!==0)throw new Error(`Default value must be a scalar, saw:\n        ${i.shape}`);let o=a.data.get(n.dataId).values,l=a.data.get(r.dataId).values,u=a.data.get(s.dataId).values,p=a.data.get(i.dataId).values[0],[c,d,h,f,m]=v7(o,n.shape,n.dtype,l,r.dtype,u,p);return[a.makeTensorInfo(d,n.dtype,c),a.makeTensorInfo([d[0]],r.dtype,h),a.makeTensorInfo([f.length],\"bool\",new Uint8Array(f.map(g=>Number(g)))),a.makeTensorInfo([m.length],n.dtype,new Int32Array(m))]}var rW={kernelName:Od,backendName:\"cpu\",kernelFunc:nW};function sW(e){let{inputs:t,backend:a}=e,{inputIndices:n,inputShape:r,newShape:s}=t;if(n.shape.length!==2)throw new Error(`Input indices should be a matrix but received shape\n        ${n.shape}`);if(r.shape.length!==1)throw new Error(`Input shape should be a vector but received shape\n        ${r.shape}`);if(s.shape.length!==1)throw new Error(`Target shape should be a vector but received shape ${s.shape}`);let i=Array.from(a.data.get(r.dataId).values),o=a.data.get(n.dataId).values,l=Array.from(a.data.get(s.dataId).values),[u,p,c]=w7(o,n.shape,n.dtype,i,l);return[a.makeTensorInfo(p,n.dtype,u),a.makeTensorInfo([c.length],s.dtype,new Int32Array(c))]}var iW={kernelName:eu,backendName:\"cpu\",kernelFunc:sW};function oW(e){let{inputs:t,backend:a}=e,{data:n,indices:r,segmentIds:s}=t;if(n.shape.length<1)throw new Error(\"Data should be at least 1 dimensional but received scalar\");if(r.shape.length!==1)throw new Error(`Indices should be a vector but received shape\n          ${r.shape}`);if(s.shape.length!==1)throw new Error(`Segment ids should be a vector but received shape\n          ${s.shape}`);if(r.shape[0]!==s.shape[0])throw new Error(\"segmentIds and indices should have same size.\");let i=a.data.get(n.dataId).values,o=a.data.get(r.dataId).values,l=a.data.get(s.dataId).values,[u,p]=p3(i,n.shape,n.dtype,o,l,!0);return a.makeTensorInfo(p,n.dtype,u)}var lW={kernelName:Dd,backendName:\"cpu\",kernelFunc:oW};function uW(e){let{inputs:t,backend:a}=e,{data:n,indices:r,segmentIds:s}=t;if(n.shape.length<1)throw new Error(\"Data should be at least 1 dimensional but received scalar\");if(r.shape.length!==1)throw new Error(`Indices should be a vector but received shape\n         ${r.shape}`);if(s.shape.length!==1)throw new Error(`Segment ids should be a vector but received shape\n         ${s.shape}`);if(r.shape[0]!==s.shape[0])throw new Error(\"segmentIds and indices should have same size.\");let i=a.data.get(n.dataId).values,o=a.data.get(r.dataId).values,l=a.data.get(s.dataId).values,[u,p]=p3(i,n.shape,n.dtype,o,l);return a.makeTensorInfo(p,n.dtype,u)}var dW={kernelName:zd,backendName:\"cpu\",kernelFunc:uW};function pW(e){let{inputs:t,backend:a,attrs:n}=e,{sparseIndices:r,sparseValues:s,defaultValue:i}=t,{outputShape:o}=n,{sliceRank:l,numUpdates:u,sliceSize:p,strides:c,outputSize:d}=T.calculateShapes(s,r,o),h=!1,f=a.bufferSync(r),m;switch(s.dtype){case\"bool\":{let g=a.bufferSync(s),x=Boolean(a.data.get(i.dataId).values[0]);m=tl(f,g,o,d,p,u,l,c,x,h);break}case\"float32\":{let g=a.bufferSync(s),x=a.data.get(i.dataId).values[0];m=tl(f,g,o,d,p,u,l,c,x,h);break}case\"int32\":{let g=a.bufferSync(s),x=a.data.get(i.dataId).values[0];m=tl(f,g,o,d,p,u,l,c,x,h);break}case\"string\":{let g=a.bufferSync(s),x=v.decodeString(a.data.get(i.dataId).values[0]);m=tl(f,g,o,d,p,u,l,c,x,h);break}default:throw new Error(`Unsupported type ${s.dtype}`)}return a.makeTensorInfo(o,m.dtype,m.values)}var cW={kernelName:Ld,backendName:\"cpu\",kernelFunc:pW};function hW(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{numOrSizeSplits:s,axis:i}=n,o=v.parseAxisParam(i,r.shape)[0],l=T.prepareSplitSize(r,s,o),u=new Array(r.shape.length).fill(0),p=r.shape.slice();return l.map(c=>{let d=[...p];d[o]=c;let h=Gs({inputs:{x:r},backend:a,attrs:{begin:u,size:d}});return u[o]+=c,h})}var fW={kernelName:Ql,backendName:\"cpu\",kernelFunc:hW},mW={kernelName:Bd,backendName:\"cpu\",kernelFunc:({inputs:e,backend:t})=>{let{x:a}=e,n=t;ye(a,\"square\");let r=n.data.get(a.dataId).values,s=new Float32Array(r.length);for(let i=0;i<r.length;++i){let o=r[i];s[i]=o*o}return{dataId:n.write(s,a.shape,a.dtype),shape:a.shape,dtype:a.dtype}}},gW=ot(fo,(e,t)=>{let a=t;return isNaN(e)?NaN:e>0?1:a.alpha}),xW={kernelName:fo,backendName:\"cpu\",kernelFunc:gW};function AW(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{begin:s,end:i,strides:o,beginMask:l,endMask:u,ellipsisMask:p,newAxisMask:c,shrinkAxisMask:d}=n;ye(r,\"stridedSlice\");let{finalShapeSparse:h,finalShape:f,isIdentity:m,sliceDim0:g,isSimpleSlice:x,begin:A,end:y,strides:b}=It.sliceInfo(r.shape,s,i,o,l,u,p,c,d),w;if(m)w=mt({inputs:{x:r},backend:a,attrs:{shape:f}});else if(g||x){v.assert(r.shape.length>=1,()=>`Input must have rank at least 1, got: ${r.shape.length}`);let S=It.computeOutShape(A,y,b),C=Gs({inputs:{x:r},backend:a,attrs:{begin:A,size:S}});w=mt({inputs:{x:C},backend:a,attrs:{shape:f}}),a.disposeIntermediateTensorInfo(C)}else{let S=a.bufferSync(r),C=I7(h,S,b,A);w=a.makeTensorInfo(f,C.dtype,C.values)}return w}var yW={kernelName:oo,backendName:\"cpu\",kernelFunc:AW};function bW(e){let{inputs:t,backend:a,attrs:n}=e,{separator:r,nGramWidths:s,leftPad:i,rightPad:o,padWidth:l,preserveShortSequences:u}=n,{data:p,dataSplits:c}=t,d=a.data.get(p.dataId).values,h=a.data.get(c.dataId).values,[f,m]=c3(d,h,r,s,i,o,l,u);return[a.makeTensorInfo([f.length],\"string\",f),a.makeTensorInfo(c.shape,\"int32\",m)]}var vW={kernelName:tu,backendName:\"cpu\",kernelFunc:bW};function wW(e){let{inputs:t,backend:a,attrs:n}=e,{skipEmpty:r}=n,{input:s,delimiter:i}=t;if(s.dtype!==\"string\")throw new Error(\"Input must be of datatype string\");if(s.shape.length!==1)throw new Error(`Input must be a vector, got shape: ${s.shape}`);if(i.shape.length!==0)throw new Error(`Delimiter must be a scalar, got shape: ${i.shape}`);let o=a.data.get(s.dataId).values,l=a.data.get(i.dataId).values[0],[u,p,c]=h3(o,l,r),d=p.length;return[a.makeTensorInfo([d,2],\"int32\",u),a.makeTensorInfo([d],\"string\",p),a.makeTensorInfo([2],\"int32\",new Int32Array(c))]}var kW={kernelName:Wd,backendName:\"cpu\",kernelFunc:wW};function IW(e){let{inputs:t,backend:a,attrs:n}=e,{numBuckets:r}=n,{input:s}=t;if(s.dtype!==\"string\")throw new Error(\"Input must be of datatype string\");if(r<=0)throw new Error(\"Number of buckets must be at least 1\");let i=a.data.get(s.dataId).values,o=f3(i,r);return a.makeTensorInfo(s.shape,\"int32\",o)}var SW={kernelName:Vd,backendName:\"cpu\",kernelFunc:IW},TW=ot(uo,e=>Math.tan(e)),CW={kernelName:uo,backendName:\"cpu\",kernelFunc:TW},NW=ot(po,e=>Math.tanh(e)),EW={kernelName:po,backendName:\"cpu\",kernelFunc:NW};function RW(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{reps:s}=n;ye(r,\"tile\");let i=T7(a.bufferSync(r),s);return a.makeTensorInfo(i.shape,i.dtype,i.values)}var MW={kernelName:ns,backendName:\"cpu\",kernelFunc:RW};function $W(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{k:s,sorted:i}=n;ye(r,\"topk\");let o=a.data.get(r.dataId).values,[l,u]=N7(o,r.shape,r.dtype,s,i);return[a.makeTensorInfo(l.shape,l.dtype,l.values),a.makeTensorInfo(u.shape,u.dtype,u.values)]}var _W={kernelName:co,backendName:\"cpu\",kernelFunc:$W};function PW(e){let{inputs:t,attrs:a,backend:n}=e,{image:r,transforms:s}=t,{interpolation:i,fillMode:o,fillValue:l,outputShape:u}=a,[p,c,d,h]=r.shape,[f,m]=u!=null?u:[c,d],g=[p,f,m,h],x=v.computeStrides(r.shape),A=x[0],y=x[1],b=x[2],w=v.computeStrides(g),S=w[0],C=w[1],E=w[2],_=v.getTypedArrayFromDType(r.dtype,v.sizeFromShape(g));_.fill(l);let $=n.data.get(r.dataId).values,M=n.data.get(s.dataId).values;for(let I=0;I<p;++I){let N=s.shape[0]===1?M:M.subarray(I*8,I*8+8);for(let O=0;O<f;++O)for(let L=0;L<m;++L)for(let B=0;B<h;++B){let G,j=N[6]*L+N[7]*O+1;if(j===0)continue;let U=(N[0]*L+N[1]*O+N[2])/j,H=(N[3]*L+N[4]*O+N[5])/j,V=px(U,d,o),Q=px(H,c,o);switch(i){case\"nearest\":G=BW($,c,d,A,y,b,I,Q,V,B,l);break;case\"bilinear\":G=WW($,c,d,A,y,b,I,Q,V,B,l);break;default:throw new Error(`Error in Transform: Expect 'nearest' or 'bilinear', but got ${i}`)}let Z=I*S+O*C+L*E+B;_[Z]=G}return n.makeTensorInfo(g,r.dtype,_)}return{dataId:n.write(_,g,r.dtype),shape:r.shape,dtype:r.dtype}}var FW={kernelName:ho,backendName:\"cpu\",kernelFunc:PW};function px(e,t,a){switch(a){case\"reflect\":return OW(e,t);case\"wrap\":return DW(e,t);case\"nearest\":return LW(e,t);case\"constant\":default:return zW(e,t)}}function OW(e,t){let a=e;if(a<0)if(t<=1)a=0;else{let n=2*t;a<n&&(a=n*Math.trunc(-a/n)+a),a=a<-t?a+n:-a-1}else if(a>t-1)if(t<=1)a=0;else{let n=2*t;a-=n*Math.trunc(a/n),a>=t&&(a=n-a-1)}return v.clamp(0,a,t-1)}function DW(e,t){let a=e;if(a<0)if(t<=1)a=0;else{let n=t-1;a+=t*(Math.trunc(-a/n)+1)}else if(a>t-1)if(t<=1)a=0;else{let n=t-1;a-=t*Math.trunc(a/n)}return v.clamp(0,a,t-1)}function zW(e,t){return e}function LW(e,t){return v.clamp(0,e,t-1)}function ju(e,t,a,n,r,s,i,o,l,u,p){let c=i*n+o*r+l*s+u;return 0<=o&&o<t&&0<=l&&l<a?e[c]:p}function BW(e,t,a,n,r,s,i,o,l,u,p){let c=Math.round(o),d=Math.round(l);return ju(e,t,a,n,r,s,i,c,d,u,p)}function WW(e,t,a,n,r,s,i,o,l,u,p){let c=Math.floor(o),d=Math.floor(l),h=c+1,f=d+1,m=(f-l)*ju(e,t,a,n,r,s,i,c,d,u,p)+(l-d)*ju(e,t,a,n,r,s,i,c,f,u,p),g=(f-l)*ju(e,t,a,n,r,s,i,h,d,u,p)+(l-d)*ju(e,t,a,n,r,s,i,h,f,u,p);return(h-o)*m+(o-c)*g}function VW(e){let{inputs:t,attrs:a,backend:n}=e,{axis:r}=a,{x:s}=t;ye(s,\"unique\");let i=n.data.get(s.dataId).values,{outputValues:o,outputShape:l,indices:u}=E7(i,r,s.shape,s.dtype);return[n.makeTensorInfo(l,s.dtype,o),n.makeTensorInfo([u.length],\"int32\",u)]}var UW={kernelName:uh,backendName:\"cpu\",kernelFunc:VW};function GW(e){let{inputs:t,backend:a,attrs:n}=e,{value:r}=t,{axis:s}=n;s<0&&(s+=r.shape.length);let i=r.shape.length,o=r.shape[s],l=new Array(i-1),u=0;for(let h=0;h<i;h++)h!==s&&(l[u++]=r.shape[h]);let p=new Array(i).fill(0),c=r.shape.slice();c[s]=1;let d=new Array(o);for(let h=0;h<d.length;h++){p[s]=h;let f=Gs({inputs:{x:r},backend:a,attrs:{begin:p,size:c}});d[h]=mt({inputs:{x:f},backend:a,attrs:{shape:l}}),a.disposeIntermediateTensorInfo(f)}return d}var HW={kernelName:au,backendName:\"cpu\",kernelFunc:GW};function jW(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,segmentIds:s}=t,{numSegments:i}=n;ye(r,\"unsortedSegmentSum\");let o=r.shape.length,l=s.shape.length,u=[],p=[],c=o-l,d=s;for(let f=0;f<c;++f){let m=Fc({inputs:{input:d},backend:a,attrs:{dim:f+1}});d=m,p.push(m)}for(let f=0;f<i;++f){let m=v.createScalarValue(f,\"int32\"),g=a.makeTensorInfo([],\"int32\",m),x=Y4({inputs:{a:g,b:d},backend:a}),A=Jr({inputs:{x},backend:a,attrs:{dtype:\"float32\"}}),y=Ph({inputs:{a:A,b:r},backend:a}),b=lp({inputs:{x:y},backend:a,attrs:{axis:0,keepDims:!1}});u.push(b),p.push(g),p.push(x),p.push(A),p.push(y),p.push(b)}let h=G7({inputs:u,backend:a,attrs:{axis:0}});return p.forEach(f=>a.disposeIntermediateTensorInfo(f)),h}var qW={kernelName:dh,backendName:\"cpu\",kernelFunc:jW},XW=[VO,NF,GO,jO,PF,XO,ZO,JO,eD,aD,rD,iD,lD,pD,hD,gD,AD,bD,wD,BO,ID,TD,ND,RD,$F,OF,$D,EF,PD,OD,DD,LD,WD,UD,HD,qD,KD,YD,QD,tz,nz,sz,oz,lz,dz,cz,fz,mz,gz,xz,bz,_O,wz,DF,Rz,zF,Mz,BF,Dz,zz,Bz,VF,Uz,Hz,qz,Kz,Yz,GF,jF,RF,Qz,FD,tL,nL,sL,PO,XF,ZF,oL,JF,uL,cL,fL,xL,yL,vL,wL,eO,IL,TL,NL,RL,$L,PL,OL,aO,zL,WL,HL,rO,iO,XL,YL,eB,lO,aB,rB,sB,H7,uB,OO,pO,pB,hB,mB,xB,MF,b1,yB,DO,zO,LO,vB,kB,SB,CB,EB,RB,$B,yO,PB,LB,WB,HB,vO,qB,KB,YB,wO,UL,eW,aW,rW,iW,lW,dW,cW,fW,SO,mW,CO,xW,yW,vW,kW,SW,MO,Az,CW,EW,MW,_W,FW,uO,UW,HW,qW,nB];for(let e of XW)mn(e);var j7={};Xe(j7,{assertNotComplex:()=>uu,bindCanvasToFramebuffer:()=>sV,bindColorTextureToFramebuffer:()=>xc,bindTextureToProgramUniformSampler:()=>o6,bindTextureUnit:()=>r6,bindVertexBufferToProgramAttribute:()=>w1,callAndCheck:()=>le,canBeRepresented:()=>q7,createFragmentShader:()=>Z7,createFramebuffer:()=>n6,createProgram:()=>Y7,createStaticIndexBuffer:()=>e6,createStaticVertexBuffer:()=>Q7,createTexture:()=>t6,createVertexShader:()=>K7,getBatchDim:()=>Hs,getExtensionOrThrow:()=>qu,getFramebufferErrorMessage:()=>l6,getMaxTexturesInShader:()=>c6,getNumChannels:()=>nV,getProgramUniformLocation:()=>i6,getProgramUniformLocationOrThrow:()=>s6,getRowsCols:()=>js,getShapeAs3D:()=>Ku,getTextureShapeFromLogicalShape:()=>d6,getWebGLDisjointQueryTimerVersion:()=>h6,getWebGLErrorMessage:()=>X7,getWebGLMaxTextureSize:()=>p6,hasExtension:()=>cn,isCapableOfRenderingToFloatTexture:()=>f6,isDownloadFloatTextureEnabled:()=>m6,isReshapeFree:()=>md,isWebGLFenceEnabled:()=>g6,isWebGLVersionEnabled:()=>I1,linkProgram:()=>J7,logShaderSourceAndInfoLog:()=>b3,resetMaxTextureSize:()=>iV,resetMaxTexturesInShader:()=>oV,unbindColorTextureFromFramebuffer:()=>k1,unbindTextureUnit:()=>rV,validateFramebuffer:()=>Xu,validateProgram:()=>gc,validateTextureSize:()=>a6});var Ps={},lc={alpha:!1,antialias:!1,premultipliedAlpha:!1,preserveDrawingBuffer:!1,depth:!1,stencil:!1,failIfMajorPerformanceCaveat:!0};function Fh(e,t){Ps[e]=t}function Dn(e,t){if(!(e in Ps)||t!=null){let n=ZW(e,t);if(n!==null)Ps[e]=n;else return console.log(\"Could not get context for WebGL version\",e),null}let a=Ps[e];return a==null||a.isContextLost()?(delete Ps[e],Dn(e)):(a.disable(a.DEPTH_TEST),a.disable(a.STENCIL_TEST),a.disable(a.BLEND),a.disable(a.DITHER),a.disable(a.POLYGON_OFFSET_FILL),a.disable(a.SAMPLE_COVERAGE),a.enable(a.SCISSOR_TEST),a.enable(a.CULL_FACE),a.cullFace(a.BACK),Ps[e])}function KW(e){if(typeof OffscreenCanvas!=\"undefined\"&&e===2)return new OffscreenCanvas(300,150);if(typeof document!=\"undefined\")return document.createElement(\"canvas\");throw new Error(\"Cannot create a canvas in this context\")}function ZW(e,t){if(e!==1&&e!==2)throw new Error(\"Cannot get WebGL rendering context, WebGL is disabled.\");let a=t==null?KW(e):t;return a.addEventListener(\"webglcontextlost\",n=>{n.preventDefault(),delete Ps[e]},!1),W().getBool(\"SOFTWARE_WEBGL_ENABLED\")&&(lc.failIfMajorPerformanceCaveat=!1),e===1?a.getContext(\"webgl\",lc)||a.getContext(\"experimental-webgl\",lc):a.getContext(\"webgl2\",lc)}var fd;(function(e){e[e.DENSE=0]=\"DENSE\",e[e.SHARED_BATCH=1]=\"SHARED_BATCH\"})(fd||(fd={}));var pn;(function(e){e[e.RENDER=0]=\"RENDER\",e[e.UPLOAD=1]=\"UPLOAD\",e[e.PIXELS=2]=\"PIXELS\",e[e.DOWNLOAD=3]=\"DOWNLOAD\"})(pn||(pn={}));var na;(function(e){e[e.UNPACKED_FLOAT16=0]=\"UNPACKED_FLOAT16\",e[e.UNPACKED_FLOAT32=1]=\"UNPACKED_FLOAT32\",e[e.PACKED_4X1_UNSIGNED_BYTE=2]=\"PACKED_4X1_UNSIGNED_BYTE\",e[e.PACKED_2X2_FLOAT32=3]=\"PACKED_2X2_FLOAT32\",e[e.PACKED_2X2_FLOAT16=4]=\"PACKED_2X2_FLOAT16\"})(na||(na={}));function up(e,t){return[t,e]}function YW(e,t){return e*t}function uc(e){let t=v.sizeFromShape(e),a=Math.ceil(t/4);return v.sizeToSquarishShape(a)}function lu(e,t){return[Math.max(1,Math.ceil(t/2)),Math.max(1,Math.ceil(e/2))]}function JW(e,t){let[a,n]=lu(e,t);return a*n*4}function y3(e,t){let a=e,n,r,s,i,o,l,u,p,c,d;return W().getNumber(\"WEBGL_VERSION\")===2?(n=a.R32F,r=a.R16F,s=a.RGBA16F,i=a.RGBA32F,o=a.RED,u=4,p=1,c=a.HALF_FLOAT,d=a.FLOAT,l=a.RGBA8):(n=e.RGBA,r=e.RGBA,s=e.RGBA,i=a.RGBA,o=e.RGBA,u=4,p=4,c=t!=null?t.HALF_FLOAT_OES:null,d=e.FLOAT,l=e.RGBA),{internalFormatFloat:n,internalFormatHalfFloat:r,internalFormatPackedHalfFloat:s,internalFormatPackedFloat:i,textureFormatFloat:o,downloadTextureFormat:l,downloadUnpackNumChannels:u,defaultNumChannels:p,textureTypeHalfFloat:c,textureTypeFloat:d}}function le(e,t){let a=t();return W().getBool(\"DEBUG\")&&QW(e),a}function QW(e){let t=e.getError();if(t!==e.NO_ERROR)throw new Error(\"WebGL Error: \"+X7(e,t))}var eV=596e-10,tV=65504;function q7(e){return!!(W().getBool(\"WEBGL_RENDER_FLOAT32_ENABLED\")||e===0||eV<Math.abs(e)&&Math.abs(e)<tV)}function X7(e,t){switch(t){case e.NO_ERROR:return\"NO_ERROR\";case e.INVALID_ENUM:return\"INVALID_ENUM\";case e.INVALID_VALUE:return\"INVALID_VALUE\";case e.INVALID_OPERATION:return\"INVALID_OPERATION\";case e.INVALID_FRAMEBUFFER_OPERATION:return\"INVALID_FRAMEBUFFER_OPERATION\";case e.OUT_OF_MEMORY:return\"OUT_OF_MEMORY\";case e.CONTEXT_LOST_WEBGL:return\"CONTEXT_LOST_WEBGL\";default:return`Unknown error code ${t}`}}function qu(e,t){return Sr(e,()=>e.getExtension(t),'Extension \"'+t+'\" not supported on this browser.')}function K7(e,t){let a=Sr(e,()=>e.createShader(e.VERTEX_SHADER),\"Unable to create vertex WebGLShader.\");if(le(e,()=>e.shaderSource(a,t)),le(e,()=>e.compileShader(a)),e.getShaderParameter(a,e.COMPILE_STATUS)===!1)throw console.log(e.getShaderInfoLog(a)),new Error(\"Failed to compile vertex shader.\");return a}function Z7(e,t){let a=Sr(e,()=>e.createShader(e.FRAGMENT_SHADER),\"Unable to create fragment WebGLShader.\");if(le(e,()=>e.shaderSource(a,t)),le(e,()=>e.compileShader(a)),W().get(\"ENGINE_COMPILE_ONLY\"))return a;if(e.getShaderParameter(a,e.COMPILE_STATUS)===!1)throw b3(t,e.getShaderInfoLog(a)),new Error(\"Failed to compile fragment shader.\");return a}var aV=/ERROR: [0-9]+:([0-9]+):/g;function b3(e,t){let a=aV.exec(t);if(a==null){console.log(`Couldn't parse line number in error: ${t}`),console.log(e);return}let n=+a[1],r=e.split(`\n`),s=r.length.toString().length+2,i=r.map((c,d)=>v.rightPad((d+1).toString(),s)+c),o=0;for(let c=0;c<i.length;c++)o=Math.max(i[c].length,o);let l=i.slice(0,n-1),u=i.slice(n-1,n),p=i.slice(n);console.log(l.join(`\n`)),console.log(t.split(`\n`)[0]),console.log(`%c ${v.rightPad(u[0],o)}`,\"border:1px solid red; background-color:#e3d2d2; color:#a61717\"),console.log(p.join(`\n`))}function Y7(e){return Sr(e,()=>e.createProgram(),\"Unable to create WebGLProgram.\")}function J7(e,t){if(le(e,()=>e.linkProgram(t)),!W().get(\"ENGINE_COMPILE_ONLY\")&&e.getProgramParameter(t,e.LINK_STATUS)===!1)throw console.log(e.getProgramInfoLog(t)),new Error(\"Failed to link vertex and fragment shaders.\")}function gc(e,t){if(le(e,()=>e.validateProgram(t)),e.getProgramParameter(t,e.VALIDATE_STATUS)===!1)throw console.log(e.getProgramInfoLog(t)),new Error(\"Shader program validation failed.\")}function Q7(e,t){let a=Sr(e,()=>e.createBuffer(),\"Unable to create WebGLBuffer\");return le(e,()=>e.bindBuffer(e.ARRAY_BUFFER,a)),le(e,()=>e.bufferData(e.ARRAY_BUFFER,t,e.STATIC_DRAW)),a}function e6(e,t){let a=Sr(e,()=>e.createBuffer(),\"Unable to create WebGLBuffer\");return le(e,()=>e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,a)),le(e,()=>e.bufferData(e.ELEMENT_ARRAY_BUFFER,t,e.STATIC_DRAW)),a}function nV(){return W().getNumber(\"WEBGL_VERSION\")===2?1:4}function t6(e){return Sr(e,()=>e.createTexture(),\"Unable to create WebGLTexture.\")}function a6(e,t){let a=W().getNumber(\"WEBGL_MAX_TEXTURE_SIZE\");if(e<=0||t<=0){let n=`[${e}x${t}]`;throw new Error(\"Requested texture size \"+n+\" is invalid.\")}if(e>a||t>a){let n=`[${e}x${t}]`,r=`[${a}x${a}]`;throw new Error(\"Requested texture size \"+n+\" greater than WebGL maximum on this browser / GPU \"+r+\".\")}}function n6(e){return Sr(e,()=>e.createFramebuffer(),\"Unable to create WebGLFramebuffer.\")}function w1(e,t,a,n,r,s,i){let o=e.getAttribLocation(t,a);return o===-1?!1:(le(e,()=>e.bindBuffer(e.ARRAY_BUFFER,n)),le(e,()=>e.vertexAttribPointer(o,r,e.FLOAT,!1,s,i)),le(e,()=>e.enableVertexAttribArray(o)),!0)}function r6(e,t,a){u6(e,a),le(e,()=>e.activeTexture(e.TEXTURE0+a)),le(e,()=>e.bindTexture(e.TEXTURE_2D,t))}function rV(e,t){u6(e,t),le(e,()=>e.activeTexture(e.TEXTURE0+t)),le(e,()=>e.bindTexture(e.TEXTURE_2D,null))}function s6(e,t,a){return Sr(e,()=>e.getUniformLocation(t,a),'uniform \"'+a+'\" not present in program.')}function i6(e,t,a){return e.getUniformLocation(t,a)}function o6(e,t,a,n){le(e,()=>r6(e,t,n)),le(e,()=>e.uniform1i(a,n))}function sV(e){le(e,()=>e.bindFramebuffer(e.FRAMEBUFFER,null)),le(e,()=>e.viewport(0,0,e.canvas.width,e.canvas.height)),le(e,()=>e.scissor(0,0,e.canvas.width,e.canvas.height))}function xc(e,t,a){le(e,()=>e.bindFramebuffer(e.FRAMEBUFFER,a)),le(e,()=>e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t,0))}function k1(e,t){le(e,()=>e.bindFramebuffer(e.FRAMEBUFFER,t)),le(e,()=>e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,null,0))}function Xu(e){let t=e.checkFramebufferStatus(e.FRAMEBUFFER);if(t!==e.FRAMEBUFFER_COMPLETE)throw new Error(\"Error binding framebuffer: \"+l6(e,t))}function l6(e,t){switch(t){case e.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:return\"FRAMEBUFFER_INCOMPLETE_ATTACHMENT\";case e.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:return\"FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\";case e.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:return\"FRAMEBUFFER_INCOMPLETE_DIMENSIONS\";case e.FRAMEBUFFER_UNSUPPORTED:return\"FRAMEBUFFER_UNSUPPORTED\";default:return`unknown error ${t}`}}function Sr(e,t,a){let n=le(e,()=>t());if(n==null)throw new Error(a);return n}function u6(e,t){let a=e.MAX_COMBINED_TEXTURE_IMAGE_UNITS-1,n=t+e.TEXTURE0;if(n<e.TEXTURE0||n>a){let r=`[gl.TEXTURE0, gl.TEXTURE${a}]`;throw new Error(`textureUnit must be in ${r}.`)}}function Hs(e,t=2){return v.sizeFromShape(e.slice(0,e.length-t))}function js(e){if(e.length===0)throw Error(\"Cannot get rows and columns of an empty shape array.\");return[e.length>1?e[e.length-2]:1,e[e.length-1]]}function Ku(e){let t=[1,1,1];return e.length===0||e.length===1&&e[0]===1||(t=[Hs(e),...js(e)]),t}function d6(e,t=!1){let a=W().getNumber(\"WEBGL_MAX_TEXTURE_SIZE\"),n=W().getNumber(\"WEBGL_MAX_SIZE_FOR_NARROW_TEXTURE\");n===1/0&&W().getBool(\"WEBGL_AUTO_SQUARIFY_NARROW_TEXTURE_SHAPE\")&&(n=a/2),t&&(a=a*2,n=n*2,e=e.map((o,l)=>l>=e.length-2?v.nearestLargerEven(e[l]):e[l]),e.length===1&&(e=[2,e[0]])),e.length!==2&&(e=v.squeezeShape(e).newShape);let r=v.sizeFromShape(e),s=null;e.length<=1&&r<=a?s=[1,r]:e.length===2&&e[0]<=a&&e[1]<=a?s=e:e.length===3&&e[0]*e[1]<=a&&e[2]<=a?s=[e[0]*e[1],e[2]]:e.length===3&&e[0]<=a&&e[1]*e[2]<=a?s=[e[0],e[1]*e[2]]:e.length===4&&e[0]*e[1]*e[2]<=a&&e[3]<=a?s=[e[0]*e[1]*e[2],e[3]]:e.length===4&&e[0]<=a&&e[1]*e[2]*e[3]<=a&&(s=[e[0],e[1]*e[2]*e[3]]);let i=s!=null&&Math.max(...s)>n&&Math.min(...s)<=(t?2:1)&&Math.min(...s)>0;if(s==null||i)if(t){let o=Hs(e),l=2,u=2;e.length&&([l,u]=js(e)),r=o*(l/2)*(u/2),s=v.sizeToSquarishShape(r).map(p=>p*2)}else s=v.sizeToSquarishShape(r);return s}function dc(e){return e%2===0}function md(e,t){if(e=e.slice(-2),t=t.slice(-2),v.arraysEqual(e,t)||!e.length||!t.length||e[0]===0||e[1]===0||t[0]===0||t[1]===0)return!0;if(e.length!==t.length){let a=e.slice(-1)[0],n=t.slice(-1)[0];if(a===n||dc(a)&&dc(n)&&(e[0]===1||t[0]===1))return!0}return e[1]===t[1]&&dc(e[0])&&dc(t[0])}var Ac,yc;function p6(e){if(Ac==null){let t=Dn(e);Ac=t.getParameter(t.MAX_TEXTURE_SIZE)}return Ac}function iV(){Ac=null}function oV(){yc=null}function c6(e){if(yc==null){let t=Dn(e);yc=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS)}return Math.min(16,yc)}function h6(e){if(e===0)return 0;let t,a=Dn(e);return cn(a,\"EXT_disjoint_timer_query_webgl2\")&&e===2?t=2:cn(a,\"EXT_disjoint_timer_query\")?t=1:t=0,t}function cn(e,t){return e.getExtension(t)!=null}function I1(e){try{if(Dn(e)!=null)return!0}catch(t){return console.log(\"Error when getting WebGL context: \",t),!1}return!1}function f6(e){if(e===0)return!1;let t=Dn(e);if(e===1){if(!cn(t,\"OES_texture_float\"))return!1}else if(!cn(t,\"EXT_color_buffer_float\"))return!1;return S1(t)}function m6(e){if(e===0)return!1;let t=Dn(e);if(e===1){if(!cn(t,\"OES_texture_float\")||!cn(t,\"WEBGL_color_buffer_float\"))return!1}else{if(cn(t,\"EXT_color_buffer_float\"))return S1(t);let a=\"EXT_color_buffer_half_float\";if(cn(t,a)){let n=t.getExtension(a);return lV(t,n)}return!1}return S1(t)}function S1(e){let t=y3(e),a=e.createTexture();e.bindTexture(e.TEXTURE_2D,a);let n=1,r=1;e.texImage2D(e.TEXTURE_2D,0,t.internalFormatFloat,n,r,0,t.textureFormatFloat,t.textureTypeFloat,null);let s=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,s),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,a,0);let i=e.checkFramebufferStatus(e.FRAMEBUFFER)===e.FRAMEBUFFER_COMPLETE;return e.bindTexture(e.TEXTURE_2D,null),e.bindFramebuffer(e.FRAMEBUFFER,null),e.deleteTexture(a),e.deleteFramebuffer(s),i}function lV(e,t){let a=y3(e,t),n=e.createTexture();e.bindTexture(e.TEXTURE_2D,n);let r=1,s=1;e.texImage2D(e.TEXTURE_2D,0,a.internalFormatHalfFloat,r,s,0,a.textureFormatFloat,a.textureTypeHalfFloat,null);let i=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,i),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,n,0);let o=e.checkFramebufferStatus(e.FRAMEBUFFER)===e.FRAMEBUFFER_COMPLETE;return e.bindTexture(e.TEXTURE_2D,null),e.bindFramebuffer(e.FRAMEBUFFER,null),e.deleteTexture(n),e.deleteFramebuffer(i),o}function g6(e){return e!==2?!1:Dn(e).fenceSync!=null}function uu(e,t){Array.isArray(e)||(e=[e]),e.forEach(a=>{a!=null&&v.assert(a.dtype!==\"complex64\",()=>`${t} does not support complex64 tensors in the WebGL backend.`)})}var ve=W();ve.registerFlag(\"HAS_WEBGL\",()=>ve.getNumber(\"WEBGL_VERSION\")>0);ve.registerFlag(\"WEBGL_VERSION\",()=>I1(2)?2:I1(1)?1:0);ve.registerFlag(\"WEBGL_CHECK_NUMERICAL_PROBLEMS\",()=>!1);ve.registerFlag(\"WEBGL_BUFFER_SUPPORTED\",()=>ve.get(\"WEBGL_VERSION\")===2);ve.registerFlag(\"WEBGL_CPU_FORWARD\",()=>!0);ve.registerFlag(\"WEBGL_FORCE_F16_TEXTURES\",()=>!1);ve.registerFlag(\"WEBGL_PACK\",()=>ve.getBool(\"HAS_WEBGL\"));ve.registerFlag(\"WEBGL_PACK_NORMALIZATION\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_PACK_CLIP\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_PACK_DEPTHWISECONV\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_PACK_BINARY_OPERATIONS\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_PACK_UNARY_OPERATIONS\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_PACK_ARRAY_OPERATIONS\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_PACK_IMAGE_OPERATIONS\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_PACK_REDUCE\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_LAZILY_UNPACK\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_CONV_IM2COL\",()=>ve.getBool(\"WEBGL_PACK\"));ve.registerFlag(\"WEBGL_MAX_TEXTURE_SIZE\",()=>p6(ve.getNumber(\"WEBGL_VERSION\")));ve.registerFlag(\"WEBGL_MAX_TEXTURES_IN_SHADER\",()=>c6(ve.getNumber(\"WEBGL_VERSION\")));ve.registerFlag(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\",()=>{let e=ve.getNumber(\"WEBGL_VERSION\");return e===0?0:h6(e)});ve.registerFlag(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE\",()=>ve.getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\")>0&&!jd.isMobile());ve.registerFlag(\"WEBGL_RENDER_FLOAT32_CAPABLE\",()=>f6(ve.getNumber(\"WEBGL_VERSION\")));ve.registerFlag(\"WEBGL_RENDER_FLOAT32_ENABLED\",()=>ve.getBool(\"WEBGL_FORCE_F16_TEXTURES\")?!1:ve.getBool(\"WEBGL_RENDER_FLOAT32_CAPABLE\"));ve.registerFlag(\"WEBGL_DOWNLOAD_FLOAT_ENABLED\",()=>m6(ve.getNumber(\"WEBGL_VERSION\")));ve.registerFlag(\"WEBGL_FENCE_API_ENABLED\",()=>g6(ve.getNumber(\"WEBGL_VERSION\")));ve.registerFlag(\"WEBGL_SIZE_UPLOAD_UNIFORM\",()=>ve.getBool(\"WEBGL_RENDER_FLOAT32_ENABLED\")?4:0);ve.registerFlag(\"WEBGL_DELETE_TEXTURE_THRESHOLD\",()=>-1,e=>{if(e<0&&e!==-1)throw new Error(`WEBGL_DELETE_TEXTURE_THRESHOLD must be -1 (indicating never delete) or at least 0, but got ${e}.`)});ve.registerFlag(\"WEBGL_FLUSH_THRESHOLD\",()=>jd.isMobile()?1:-1,e=>{if(e<0&&e!==-1)throw new Error(`WEBGL_FLUSH_THRESHOLD must be -1 (indicating never manual flush) or at least 0, but got ${e}.`)});ve.registerFlag(\"CPU_HANDOFF_SIZE_THRESHOLD\",()=>128);ve.registerFlag(\"WEBGL_USE_SHAPES_UNIFORMS\",()=>!1);ve.registerFlag(\"TOPK_LAST_DIM_CPU_HANDOFF_SIZE_THRESHOLD\",()=>1e5);ve.registerFlag(\"TOPK_K_CPU_HANDOFF_THRESHOLD\",()=>128);ve.registerFlag(\"WEBGL_EXP_CONV\",()=>!1);ve.registerFlag(\"SOFTWARE_WEBGL_ENABLED\",()=>ve.getBool(\"IS_TEST\"));ve.registerFlag(\"WEBGL_MAX_SIZE_FOR_NARROW_TEXTURE\",()=>1/0);ve.registerFlag(\"WEBGL_AUTO_SQUARIFY_NARROW_TEXTURE_SHAPE\",()=>!1);ve.registerFlag(\"WEBGL2_ISNAN_CUSTOM\",()=>!1);ve.registerFlag(\"ENGINE_COMPILE_ONLY\",()=>!1);function Ca(){let e,t,a,n,r,s,i,o,l,u;return W().getNumber(\"WEBGL_VERSION\")===2?(e=\"#version 300 es\",t=\"in\",a=\"out\",n=\"in\",r=\"texture\",s=\"outputColor\",i=\"out vec4 outputColor;\",o=W().getBool(\"WEBGL2_ISNAN_CUSTOM\")?`\n      bool isnan_custom(float val) {\n        uint floatToUint = floatBitsToUint(val);\n        return (floatToUint & 0x7fffffffu) > 0x7f800000u;\n      }\n\n      bvec4 isnan_custom(vec4 val) {\n        return bvec4(isnan_custom(val.x),\n          isnan_custom(val.y), isnan_custom(val.z), isnan_custom(val.w));\n      }\n\n      #define isnan(value) isnan_custom(value)\n    `:\"\",l=\"\",u=`\n      #define round(value) newRound(value)\n      int newRound(float value) {\n        return int(floor(value + 0.5));\n      }\n\n      ivec4 newRound(vec4 value) {\n        return ivec4(floor(value + vec4(0.5)));\n      }\n    `):(e=\"\",t=\"attribute\",a=\"varying\",n=\"varying\",r=\"texture2D\",s=\"gl_FragColor\",i=\"\",o=`\n      #define isnan(value) isnan_custom(value)\n      bool isnan_custom(float val) {\n        return (val > 0. || val < 1. || val == 0.) ? false : true;\n      }\n      bvec4 isnan_custom(vec4 val) {\n        return bvec4(isnan(val.x), isnan(val.y), isnan(val.z), isnan(val.w));\n      }\n    `,l=`\n      uniform float INFINITY;\n\n      bool isinf(float val) {\n        return abs(val) == INFINITY;\n      }\n      bvec4 isinf(vec4 val) {\n        return equal(abs(val), vec4(INFINITY));\n      }\n    `,u=`\n      int round(float value) {\n        return int(floor(value + 0.5));\n      }\n\n      ivec4 round(vec4 value) {\n        return ivec4(floor(value + vec4(0.5)));\n      }\n    `),{version:e,attribute:t,varyingVs:a,varyingFs:n,texture2D:r,output:s,defineOutput:i,defineSpecialNaN:o,defineSpecialInf:l,defineRound:u}}function Ao(e,t,a=\"index\"){let n=v.computeStrides(t);return n.map((r,s)=>{let i=`int ${e[s]} = ${a} / ${r}`,o=s===n.length-1?`int ${e[s+1]} = ${a} - ${e[s]} * ${r}`:`index -= ${e[s]} * ${r}`;return`${i}; ${o};`}).join(\"\")}function Oh(e,t,a=\"index\"){let n=v.computeStrides(t);return n.map((r,s)=>{let i=`int ${e[s]} = ${a} / outShapeStrides[${s}]`,o=s===n.length-1?`int ${e[s+1]} = ${a} - ${e[s]} * outShapeStrides[${s}]`:`index -= ${e[s]} * outShapeStrides[${s}]`;return`${i}; ${o};`}).join(\"\")}function uV(e,t){let a=e.length,n=e.map(s=>`${t}[${s}]`),r=new Array(a-1);r[a-2]=n[a-1];for(let s=a-3;s>=0;--s)r[s]=`(${r[s+1]} * ${n[s+1]})`;return r}function dV(e,t,a=\"index\"){let n=e.map((s,i)=>i),r=uV(n,t);return r.map((s,i)=>{let o=`int ${e[i]} = ${a} / ${r[i]}`,l=i===r.length-1?`int ${e[i+1]} = ${a} - ${e[i]} * ${r[i]}`:`index -= ${e[i]} * ${r[i]}`;return`${o}; ${l};`}).join(\"\")}function v3(e){let t=v.computeStrides(e).map(a=>a.toString());return`\n  int getFlatIndex(ivec3 coords) {\n    return coords.x * ${t[0]} + coords.y * ${t[1]} + coords.z;\n  }\n`}function w3(){return`\n  int getFlatIndex(ivec3 coords) {\n    return coords.x * outShapeStrides[0] + coords.y * outShapeStrides[1] + coords.z;\n  }\n`}var x6=`\n  const float FLOAT_MAX = 1.70141184e38;\n  const float FLOAT_MIN = 1.17549435e-38;\n\n  lowp vec4 encode_float(highp float v) {\n    if (isnan(v)) {\n      return vec4(255, 255, 255, 255);\n    }\n\n    highp float av = abs(v);\n\n    if(av < FLOAT_MIN) {\n      return vec4(0.0, 0.0, 0.0, 0.0);\n    } else if(v > FLOAT_MAX) {\n      return vec4(0.0, 0.0, 128.0, 127.0) / 255.0;\n    } else if(v < -FLOAT_MAX) {\n      return vec4(0.0, 0.0,  128.0, 255.0) / 255.0;\n    }\n\n    highp vec4 c = vec4(0,0,0,0);\n\n    highp float e = floor(log2(av));\n    highp float m = exp2(fract(log2(av))) - 1.0;\n\n    c[2] = floor(128.0 * m);\n    m -= c[2] / 128.0;\n    c[1] = floor(32768.0 * m);\n    m -= c[1] / 32768.0;\n    c[0] = floor(8388608.0 * m);\n\n    highp float ebias = e + 127.0;\n    c[3] = floor(ebias / 2.0);\n    ebias -= c[3] * 2.0;\n    c[2] += floor(ebias) * 128.0;\n\n    c[3] += 128.0 * step(0.0, -v);\n\n    return c / 255.0;\n  }\n`,{getBroadcastDims:A6}=T;function pV(e,t,a){let n=[];if(e.forEach(d=>{let h=v.sizeFromShape(d.shapeInfo.logicalShape);if(d.shapeInfo.isUniform?n.push(`uniform float ${d.name}${h>1?`[${h}]`:\"\"};`):(n.push(`uniform sampler2D ${d.name};`),n.push(`uniform int offset${d.name};`)),a.enableShapeUniforms){let{uniformShape:f}=k3(a.packedInputs,d.shapeInfo.logicalShape,d.shapeInfo.texShape);switch(f.length){case 1:n.push(`uniform int ${d.name}Shape;`);break;case 2:n.push(`uniform ivec2 ${d.name}Shape;`);break;case 3:n.push(`uniform ivec3 ${d.name}Shape;`);break;case 4:n.push(`uniform ivec4 ${d.name}Shape;`);break;default:break}n.push(`uniform ivec2 ${d.name}TexShape;`)}}),a.enableShapeUniforms){switch(t.logicalShape.length){case 1:n.push(\"uniform int outShape;\");break;case 2:n.push(\"uniform ivec2 outShape;\"),n.push(\"uniform int outShapeStrides;\");break;case 3:n.push(\"uniform ivec3 outShape;\"),n.push(\"uniform ivec2 outShapeStrides;\");break;case 4:n.push(\"uniform ivec4 outShape;\"),n.push(\"uniform ivec3 outShapeStrides;\");break;default:break}n.push(\"uniform ivec2 outTexShape;\")}a.customUniforms&&a.customUniforms.forEach(d=>{n.push(`uniform ${d.type} ${d.name}${d.arrayIndex?`[${d.arrayIndex}]`:\"\"};`)});let r=n.join(`\n`),s=e.map(d=>cV(d,t,a.packedInputs,a.enableShapeUniforms)).join(`\n`),i=t.texShape,o=Ca(),l=mV(o),u,p,c=AV(o);return t.isPacked?(u=hV(t.logicalShape,i,a.enableShapeUniforms),p=xV(o)):(u=fV(t.logicalShape,i,a.enableShapeUniforms),p=gV(o)),a.packedInputs&&(c+=wV),[c,l,p,r,u,s,a.userCode].join(`\n`)}function du(e,t=!1){let a=e.shapeInfo.logicalShape;switch(a.length){case 0:return PV(e,t);case 1:return OV(e,t);case 2:return zV(e,t);case 3:return BV(e,t);case 4:return VV(e,t);case 5:return UV(e);case 6:return GV(e);default:throw new Error(`${a.length}-D input sampling is not yet supported`)}}function y6(e,t){switch(e.shapeInfo.logicalShape.length){case 0:return _V(e);case 1:return FV(e,t);case 2:return DV(e,t);case 3:return LV(e,t);default:return WV(e,t)}}function cV(e,t,a=!1,n){let r=\"\";a?r+=y6(e,n):r+=du(e,n);let s=e.shapeInfo.logicalShape,i=t.logicalShape;return s.length<=i.length&&(a?r+=HV(e,t):r+=jV(e,t)),r}function hV(e,t,a){switch(e.length){case 0:return b6();case 1:return kV(e,t,a);case 2:return MV(e,t,a);case 3:return SV(e,t,a);default:return CV(e,t,a)}}function fV(e,t,a){switch(e.length){case 0:return b6();case 1:return IV(e,t,a);case 2:return $V(e,t,a);case 3:return TV(e,t,a);case 4:return NV(e,t,a);case 5:return EV(e,t);case 6:return RV(e,t);default:throw new Error(`${e.length}-D output sampling is not yet supported`)}}function mV(e){return`\n    float sampleTexture(sampler2D textureSampler, vec2 uv) {\n      return ${e.texture2D}(textureSampler, uv).r;\n    }\n  `}function gV(e){return`\n    void setOutput(float val) {\n      ${e.output} = vec4(val, 0, 0, 0);\n    }\n  `}function xV(e){return`\n    void setOutput(vec4 val) {\n      ${e.output} = val;\n    }\n  `}function AV(e){return`${e.version}\n    precision highp float;\n    precision highp int;\n    precision highp sampler2D;\n    ${e.varyingFs} vec2 resultUV;\n    ${e.defineOutput}\n    const vec2 halfCR = vec2(0.5, 0.5);\n\n    struct ivec5\n    {\n      int x;\n      int y;\n      int z;\n      int w;\n      int u;\n    };\n\n    struct ivec6\n    {\n      int x;\n      int y;\n      int z;\n      int w;\n      int u;\n      int v;\n    };\n\n    uniform float NAN;\n    ${e.defineSpecialNaN}\n    ${e.defineSpecialInf}\n    ${e.defineRound}\n\n    int imod(int x, int y) {\n      return x - y * (x / y);\n    }\n\n    int idiv(int a, int b, float sign) {\n      int res = a / b;\n      int mod = imod(a, b);\n      if (sign < 0. && mod != 0) {\n        res -= 1;\n      }\n      return res;\n    }\n\n    //Based on the work of Dave Hoskins\n    //https://www.shadertoy.com/view/4djSRW\n    #define HASHSCALE1 443.8975\n    float random(float seed){\n      vec2 p = resultUV * seed;\n      vec3 p3  = fract(vec3(p.xyx) * HASHSCALE1);\n      p3 += dot(p3, p3.yzx + 19.19);\n      return fract((p3.x + p3.y) * p3.z);\n    }\n\n    ${yV}\n    ${bV}\n    ${vV}\n  `}var yV=`\nvec2 uvFromFlat(int texNumR, int texNumC, int index) {\n  int texR = index / texNumC;\n  int texC = index - texR * texNumC;\n  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\nvec2 packedUVfrom1D(int texNumR, int texNumC, int index) {\n  int texelIndex = index / 2;\n  int texR = texelIndex / texNumC;\n  int texC = texelIndex - texR * texNumC;\n  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n`,bV=`\nvec2 packedUVfrom2D(int texelsInLogicalRow, int texNumR,\n  int texNumC, int row, int col) {\n  int texelIndex = (row / 2) * texelsInLogicalRow + (col / 2);\n  int texR = texelIndex / texNumC;\n  int texC = texelIndex - texR * texNumC;\n  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n`,vV=`\nvec2 packedUVfrom3D(int texNumR, int texNumC,\n    int texelsInBatch, int texelsInLogicalRow, int b,\n    int row, int col) {\n  int index = b * texelsInBatch + (row / 2) * texelsInLogicalRow + (col / 2);\n  int texR = index / texNumC;\n  int texC = index - texR * texNumC;\n  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n`,wV=`\n  float getChannel(vec4 frag, vec2 innerDims) {\n    vec2 modCoord = mod(innerDims, 2.);\n    return modCoord.x == 0. ?\n      (modCoord.y == 0. ? frag.r : frag.g) :\n      (modCoord.y == 0. ? frag.b : frag.a);\n  }\n  float getChannel(vec4 frag, int dim) {\n    float modCoord = mod(float(dim), 2.);\n    return modCoord == 0. ? frag.r : frag.g;\n  }\n`;function b6(){return`\n    int getOutputCoords() {\n      return 0;\n    }\n  `}function kV(e,t,a){let n=[Math.ceil(t[0]/2),Math.ceil(t[1]/2)];return n[0]===1?a?`\n      int getOutputCoords() {\n        return 2 * int(resultUV.x * ceil(float(outTexShape[1]) / 2.0));\n      }\n    `:`\n      int getOutputCoords() {\n        return 2 * int(resultUV.x * ${n[1]}.0);\n      }\n    `:n[1]===1?a?`\n      int getOutputCoords() {\n        return 2 * int(resultUV.y * ceil(float(outTexShape[0]) / 2.0));\n      }\n    `:`\n      int getOutputCoords() {\n        return 2 * int(resultUV.y * ${n[0]}.0);\n      }\n    `:a?`\n    int getOutputCoords() {\n      ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(packedTexShape[0], packedTexShape[1]));\n      return 2 * (resTexRC.x * packedTexShape[1] + resTexRC.y);\n    }\n  `:`\n    int getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${n[0]}, ${n[1]}));\n      return 2 * (resTexRC.x * ${n[1]} + resTexRC.y);\n    }\n  `}function IV(e,t,a){return t[0]===1?a?`\n      int getOutputCoords() {\n        return int(resultUV.x * float(outTexShape[1]));\n      }\n    `:`\n      int getOutputCoords() {\n        return int(resultUV.x * ${t[1]}.0);\n      }\n    `:t[1]===1?a?`\n      int getOutputCoords() {\n        return int(resultUV.y * float(outTexShape[0]));\n      }\n    `:`\n      int getOutputCoords() {\n        return int(resultUV.y * ${t[0]}.0);\n      }\n    `:a?`\n    int getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(outTexShape[0], outTexShape[1]));\n      return resTexRC.x * outTexShape[1] + resTexRC.y;\n    }\n  `:`\n    int getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${t[0]}, ${t[1]}));\n      return resTexRC.x * ${t[1]} + resTexRC.y;\n    }\n  `}function SV(e,t,a){if(a)return`\n    ivec3 getOutputCoords() {\n      ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n      int texelsInLogicalRow = int(ceil(float(outShape[2]) / 2.0));\n      int texelsInBatch = texelsInLogicalRow * int(ceil(float(outShape[1]) / 2.0));\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(packedTexShape[0], packedTexShape[1]));\n      int index = resTexRC.x * packedTexShape[1] + resTexRC.y;\n\n      int b = index / texelsInBatch;\n      index -= b * texelsInBatch;\n\n      int r = 2 * (index / texelsInLogicalRow);\n      int c = imod(index, texelsInLogicalRow) * 2;\n\n      return ivec3(b, r, c);\n    }\n  `;let n=[Math.ceil(t[0]/2),Math.ceil(t[1]/2)],r=Math.ceil(e[2]/2),s=r*Math.ceil(e[1]/2);return`\n    ivec3 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${n[0]}, ${n[1]}));\n      int index = resTexRC.x * ${n[1]} + resTexRC.y;\n\n      int b = index / ${s};\n      index -= b * ${s};\n\n      int r = 2 * (index / ${r});\n      int c = imod(index, ${r}) * 2;\n\n      return ivec3(b, r, c);\n    }\n  `}function TV(e,t,a){if(a)return`\n  ivec3 getOutputCoords() {\n    ivec2 resTexRC = ivec2(resultUV.yx *\n                           vec2(outTexShape[0], outTexShape[1]));\n    int index = resTexRC.x * outTexShape[1] + resTexRC.y;\n    ${Oh([\"r\",\"c\",\"d\"],e)}\n    return ivec3(r, c, d);\n  }\n`;let n=Ao([\"r\",\"c\",\"d\"],e);return`\n    ivec3 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${t[0]}, ${t[1]}));\n      int index = resTexRC.x * ${t[1]} + resTexRC.y;\n      ${n}\n      return ivec3(r, c, d);\n    }\n  `}function CV(e,t,a){if(a)return`\n    ivec4 getOutputCoords() {\n      ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(packedTexShape[0], packedTexShape[1]));\n      int index = resTexRC.x * packedTexShape[1] + resTexRC.y;\n\n      int texelsInLogicalRow = int(ceil(float(outShape[3]) / 2.0));\n      int texelsInBatch = texelsInLogicalRow * int(ceil(float(outShape[2]) / 2.0));\n      int texelsInBatchN = texelsInBatch * outShape[1];\n\n      int b2 = index / texelsInBatchN;\n      index -= b2 * texelsInBatchN;\n\n      int b = index / texelsInBatch;\n      index -= b * texelsInBatch;\n\n      int r = 2 * (index / texelsInLogicalRow);\n      int c = imod(index, texelsInLogicalRow) * 2;\n\n      return ivec4(b2, b, r, c);\n    }\n  `;let n=[Math.ceil(t[0]/2),Math.ceil(t[1]/2)],r=Math.ceil(e[e.length-1]/2),s=r*Math.ceil(e[e.length-2]/2),i=s,o=\"\",l=\"b, r, c\";for(let u=2;u<e.length-1;u++)i*=e[e.length-u-1],o=`\n      int b${u} = index / ${i};\n      index -= b${u} * ${i};\n    `+o,l=`b${u}, `+l;return`\n    ivec${e.length} getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${n[0]}, ${n[1]}));\n      int index = resTexRC.x * ${n[1]} + resTexRC.y;\n\n      ${o}\n\n      int b = index / ${s};\n      index -= b * ${s};\n\n      int r = 2 * (index / ${r});\n      int c = imod(index, ${r}) * 2;\n\n      return ivec${e.length}(${l});\n    }\n  `}function NV(e,t,a){if(a)return`\n    ivec4 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n        vec2(outTexShape[0], outTexShape[1]));\n      int index = resTexRC.x * outTexShape[1] + resTexRC.y;\n      ${Oh([\"r\",\"c\",\"d\",\"d2\"],e)}\n      return ivec4(r, c, d, d2);\n    }\n  `;let n=Ao([\"r\",\"c\",\"d\",\"d2\"],e);return`\n    ivec4 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n        vec2(${t[0]}, ${t[1]}));\n      int index = resTexRC.x * ${t[1]} + resTexRC.y;\n      ${n}\n      return ivec4(r, c, d, d2);\n    }\n  `}function EV(e,t){let a=Ao([\"r\",\"c\",\"d\",\"d2\",\"d3\"],e);return`\n    ivec5 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx * vec2(${t[0]},\n                             ${t[1]}));\n\n      int index = resTexRC.x * ${t[1]} + resTexRC.y;\n\n      ${a}\n\n      ivec5 outShape = ivec5(r, c, d, d2, d3);\n      return outShape;\n    }\n  `}function RV(e,t){let a=Ao([\"r\",\"c\",\"d\",\"d2\",\"d3\",\"d4\"],e);return`\n    ivec6 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n        vec2(${t[0]}, ${t[1]}));\n      int index = resTexRC.x * ${t[1]} + resTexRC.y;\n\n      ${a}\n\n      ivec6 result = ivec6(r, c, d, d2, d3, d4);\n      return result;\n    }\n  `}function MV(e,t,a){let n=[Math.ceil(t[0]/2),Math.ceil(t[1]/2)];if(v.arraysEqual(e,t))return a?`\n      ivec2 getOutputCoords() {\n        ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n        return 2 * ivec2(resultUV.yx * vec2(packedTexShape[0], packedTexShape[1]));\n      }\n    `:`\n      ivec2 getOutputCoords() {\n        return 2 * ivec2(resultUV.yx * vec2(${n[0]}, ${n[1]}));\n      }\n    `;let r=Math.ceil(e[1]/2);return a?`\n    ivec2 getOutputCoords() {\n      ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n      int texelsInLogicalRow = int(ceil(float(outShape[1]) / 2.0));\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(packedTexShape[0], packedTexShape[1]));\n\n      int index = resTexRC.x * packedTexShape[1] + resTexRC.y;\n      int r = 2 * (index / texelsInLogicalRow);\n      int c = imod(index, texelsInLogicalRow) * 2;\n\n      return ivec2(r, c);\n    }\n  `:`\n    ivec2 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${n[0]}, ${n[1]}));\n\n      int index = resTexRC.x * ${n[1]} + resTexRC.y;\n      int r = 2 * (index / ${r});\n      int c = imod(index, ${r}) * 2;\n\n      return ivec2(r, c);\n    }\n  `}function $V(e,t,a){return v.arraysEqual(e,t)?a?`\n      ivec2 getOutputCoords() {\n        return ivec2(resultUV.yx * vec2(outTexShape[0], outTexShape[1]));\n      }\n    `:`\n      ivec2 getOutputCoords() {\n        return ivec2(resultUV.yx * vec2(${t[0]}, ${t[1]}));\n      }\n    `:e[1]===1?a?`\n      ivec2 getOutputCoords() {\n        ivec2 resTexRC = ivec2(resultUV.yx *\n                               vec2(outTexShape[0], outTexShape[1]));\n        int index = resTexRC.x * outTexShape[1] + resTexRC.y;\n        return ivec2(index, 0);\n      }\n    `:`\n      ivec2 getOutputCoords() {\n        ivec2 resTexRC = ivec2(resultUV.yx *\n                               vec2(${t[0]}, ${t[1]}));\n        int index = resTexRC.x * ${t[1]} + resTexRC.y;\n        return ivec2(index, 0);\n      }\n    `:e[0]===1?a?`\n      ivec2 getOutputCoords() {\n        ivec2 resTexRC = ivec2(resultUV.yx *\n                               vec2(outTexShape[0], outTexShape[1]));\n        int index = resTexRC.x * outTexShape[1] + resTexRC.y;\n        return ivec2(0, index);\n      }\n    `:`\n      ivec2 getOutputCoords() {\n        ivec2 resTexRC = ivec2(resultUV.yx *\n                               vec2(${t[0]}, ${t[1]}));\n        int index = resTexRC.x * ${t[1]} + resTexRC.y;\n        return ivec2(0, index);\n      }\n    `:a?`\n    ivec2 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(outTexShape[0], outTexShape[1]));\n      int index = resTexRC.x * outTexShape[1] + resTexRC.y;\n      int r = index / outShape[1];\n      int c = index - r * outShape[1];\n      return ivec2(r, c);\n    }\n  `:`\n    ivec2 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${t[0]}, ${t[1]}));\n      int index = resTexRC.x * ${t[1]} + resTexRC.y;\n      int r = index / ${e[1]};\n      int c = index - r * ${e[1]};\n      return ivec2(r, c);\n    }\n  `}function yo(e){return`offset${e}`}function _V(e){let t=e.name,a=\"get\"+t.charAt(0).toUpperCase()+t.slice(1),n=Ca();return`\n    vec4 ${a}() {\n      return ${n.texture2D}(${t}, halfCR);\n    }\n  `}function PV(e,t){let a=e.name,n=\"get\"+a.charAt(0).toUpperCase()+a.slice(1);if(e.shapeInfo.isUniform)return`float ${n}() {return ${a};}`;let[r,s]=e.shapeInfo.texShape;if(r===1&&s===1)return`\n      float ${n}() {\n        return sampleTexture(${a}, halfCR);\n      }\n    `;let i=yo(a);if(t)return`\n    float ${n}() {\n      vec2 uv = uvFromFlat(${a}TexShape[0], ${a}TexShape[1], ${i});\n      return sampleTexture(${a}, uv);\n    }\n  `;let[o,l]=e.shapeInfo.texShape;return`\n    float ${n}() {\n      vec2 uv = uvFromFlat(${o}, ${l}, ${i});\n      return sampleTexture(${a}, uv);\n    }\n  `}function FV(e,t){let a=e.name,n=\"get\"+a.charAt(0).toUpperCase()+a.slice(1),r=e.shapeInfo.texShape,s=Ca();if(t)return`\n    vec4 ${n}(int index) {\n      ivec2 packedTexShape = ivec2(ceil(float(${a}TexShape[0]) / 2.0), ceil(float(${a}TexShape[1]) / 2.0));\n      vec2 uv = packedUVfrom1D(\n        packedTexShape[0], packedTexShape[1], index);\n      return ${s.texture2D}(${a}, uv);\n    }\n  `;let i=[Math.ceil(r[0]/2),Math.ceil(r[1]/2)];return`\n    vec4 ${n}(int index) {\n      vec2 uv = packedUVfrom1D(\n        ${i[0]}, ${i[1]}, index);\n      return ${s.texture2D}(${a}, uv);\n    }\n  `}function OV(e,t){let a=e.name,n=\"get\"+a.charAt(0).toUpperCase()+a.slice(1);if(e.shapeInfo.isUniform)return`\n      float ${n}(int index) {\n        ${pu(e)}\n      }\n    `;let r=e.shapeInfo.texShape,s=r[0],i=r[1];if(i===1&&s===1)return`\n      float ${n}(int index) {\n        return sampleTexture(${a}, halfCR);\n      }\n    `;let o=yo(a);return i===1?t?`\n      float ${n}(int index) {\n        vec2 uv = vec2(0.5, (float(index + ${o}) + 0.5) / float(${a}TexShape[0]));\n        return sampleTexture(${a}, uv);\n      }\n    `:`\n      float ${n}(int index) {\n        vec2 uv = vec2(0.5, (float(index + ${o}) + 0.5) / ${s}.0);\n        return sampleTexture(${a}, uv);\n      }\n    `:s===1?t?`\n      float ${n}(int index) {\n        vec2 uv = vec2((float(index + ${o}) + 0.5) / float(${a}TexShape[1]), 0.5);\n        return sampleTexture(${a}, uv);\n      }\n    `:`\n      float ${n}(int index) {\n        vec2 uv = vec2((float(index + ${o}) + 0.5) / ${i}.0, 0.5);\n        return sampleTexture(${a}, uv);\n      }\n    `:t?`\n    float ${n}(int index) {\n      vec2 uv = uvFromFlat(${a}TexShape[0], ${a}TexShape[1], index + ${o});\n      return sampleTexture(${a}, uv);\n    }\n  `:`\n    float ${n}(int index) {\n      vec2 uv = uvFromFlat(${s}, ${i}, index + ${o});\n      return sampleTexture(${a}, uv);\n    }\n  `}function DV(e,t){let a=e.shapeInfo.logicalShape,n=e.name,r=\"get\"+n.charAt(0).toUpperCase()+n.slice(1),s=e.shapeInfo.texShape,i=s[0],o=s[1],l=Ca();if(s!=null&&v.arraysEqual(a,s))return t?`\n      vec4 ${r}(int row, int col) {\n        vec2 uv = (vec2(col, row) + halfCR) / vec2(${n}TexShape[1], ${n}TexShape[0]);\n\n        return ${l.texture2D}(${n}, uv);\n      }\n    `:`\n      vec4 ${r}(int row, int col) {\n        vec2 uv = (vec2(col, row) + halfCR) / vec2(${o}.0, ${i}.0);\n\n        return ${l.texture2D}(${n}, uv);\n      }\n    `;if(t)return`\n    vec4 ${r}(int row, int col) {\n      ivec2 packedTexShape = ivec2(ceil(float(${n}TexShape[0]) / 2.0), ceil(float(${n}TexShape[1]) / 2.0));\n      int valuesPerRow = int(ceil(float(${n}Shape[1]) / 2.0));\n      vec2 uv = packedUVfrom2D(valuesPerRow, packedTexShape[0], packedTexShape[1], row, col);\n      return ${l.texture2D}(${n}, uv);\n    }\n  `;let u=[Math.ceil(s[0]/2),Math.ceil(s[1]/2)],p=Math.ceil(a[1]/2);return`\n    vec4 ${r}(int row, int col) {\n      vec2 uv = packedUVfrom2D(${p}, ${u[0]}, ${u[1]}, row, col);\n      return ${l.texture2D}(${n}, uv);\n    }\n  `}function zV(e,t){let a=e.shapeInfo.logicalShape,n=e.name,r=\"get\"+n.charAt(0).toUpperCase()+n.slice(1),s=e.shapeInfo.texShape;if(s!=null&&v.arraysEqual(a,s)){if(t)return`\n      float ${r}(int row, int col) {\n        vec2 uv = (vec2(col, row) + halfCR) / vec2(${n}TexShape[1], ${n}TexShape[0]);\n        return sampleTexture(${n}, uv);\n      }\n    `;let d=s[0],h=s[1];return`\n    float ${r}(int row, int col) {\n      vec2 uv = (vec2(col, row) + halfCR) / vec2(${h}.0, ${d}.0);\n      return sampleTexture(${n}, uv);\n    }\n  `}let{newShape:i,keptDims:o}=v.squeezeShape(a),l=i;if(l.length<a.length){let d=cu(e,l),h=[\"row\",\"col\"];return`\n      ${du(d,t)}\n      float ${r}(int row, int col) {\n        return ${r}(${hu(h,o)});\n      }\n    `}if(e.shapeInfo.isUniform)return`\n      float ${r}(int row, int col) {\n        int index = round(dot(vec2(row, col), vec2(${a[1]}, 1)));\n        ${pu(e)}\n      }\n    `;let u=s[0],p=s[1],c=yo(n);return p===1?t?`\n      float ${r}(int row, int col) {\n        float index = dot(vec3(row, col, ${c}), vec3(${n}Shape[1], 1, 1));\n        vec2 uv = vec2(0.5, (index + 0.5) / float(${n}TexShape[0]));\n        return sampleTexture(${n}, uv);\n      }\n    `:`\n    float ${r}(int row, int col) {\n      float index = dot(vec3(row, col, ${c}), vec3(${a[1]}, 1, 1));\n      vec2 uv = vec2(0.5, (index + 0.5) / ${u}.0);\n      return sampleTexture(${n}, uv);\n    }\n  `:u===1?t?`\n      float ${r}(int row, int col) {\n        float index = dot(vec3(row, col, ${c}), vec3(${n}Shape[1], 1, 1));\n        vec2 uv = vec2((index + 0.5) / float(${n}TexShape[1]), 0.5);\n        return sampleTexture(${n}, uv);\n      }\n    `:`\n    float ${r}(int row, int col) {\n      float index = dot(vec3(row, col, ${c}), vec3(${a[1]}, 1, 1));\n      vec2 uv = vec2((index + 0.5) / ${p}.0, 0.5);\n      return sampleTexture(${n}, uv);\n    }\n  `:t?`\n      float ${r}(int row, int col) {\n        // Explicitly use integer operations as dot() only works on floats.\n        int index = row * ${n}Shape[1] + col + ${c};\n        vec2 uv = uvFromFlat(${n}TexShape[0], ${n}TexShape[1], index);\n        return sampleTexture(${n}, uv);\n      }\n    `:`\n  float ${r}(int row, int col) {\n    // Explicitly use integer operations as dot() only works on floats.\n    int index = row * ${a[1]} + col + ${c};\n    vec2 uv = uvFromFlat(${u}, ${p}, index);\n    return sampleTexture(${n}, uv);\n  }\n`}function LV(e,t){let a=e.shapeInfo.logicalShape,n=e.name,r=\"get\"+n.charAt(0).toUpperCase()+n.slice(1),s=e.shapeInfo.texShape,i=[Math.ceil(s[0]/2),Math.ceil(s[1]/2)];if(a[0]===1){let d=a.slice(1),h=[1,2],f=cu(e,d),m=[\"b\",\"row\",\"col\"];return`\n        ${y6(f,t)}\n        vec4 ${r}(int b, int row, int col) {\n          return ${r}(${hu(m,h)});\n        }\n      `}let o=Ca();if(t)return`\n    vec4 ${r}(int b, int row, int col) {\n      ivec2 packedTexShape = ivec2(ceil(float(${n}TexShape[0]) / 2.0), ceil(float(${n}TexShape[1]) / 2.0));\n      int valuesPerRow = int(ceil(float(${n}Shape[2]) / 2.0));\n      int texelsInBatch = valuesPerRow * int(ceil(float(${n}Shape[1]) / 2.0));\n      vec2 uv = packedUVfrom3D(\n        packedTexShape[0], packedTexShape[1], texelsInBatch, valuesPerRow, b, row, col);\n      return ${o.texture2D}(${n}, uv);\n    }\n  `;let l=i[0],u=i[1],p=Math.ceil(a[2]/2),c=p*Math.ceil(a[1]/2);return`\n    vec4 ${r}(int b, int row, int col) {\n      vec2 uv = packedUVfrom3D(\n        ${l}, ${u}, ${c}, ${p}, b, row, col);\n      return ${o.texture2D}(${n}, uv);\n    }\n  `}function BV(e,t){let a=e.shapeInfo.logicalShape,n=e.name,r=\"get\"+n.charAt(0).toUpperCase()+n.slice(1),s=a[1]*a[2],i=a[2],{newShape:o,keptDims:l}=v.squeezeShape(a),u=o;if(u.length<a.length){let m=cu(e,u),g=[\"row\",\"col\",\"depth\"];return`\n        ${du(m,t)}\n        float ${r}(int row, int col, int depth) {\n          return ${r}(${hu(g,l)});\n        }\n      `}if(e.shapeInfo.isUniform)return`\n      float ${r}(int row, int col, int depth) {\n        int index = round(dot(vec3(row, col, depth),\n                          vec3(${s}, ${i}, 1)));\n        ${pu(e)}\n      }\n    `;let p=e.shapeInfo.texShape,c=p[0],d=p[1],h=e.shapeInfo.flatOffset;if(d===s&&h==null)return t?`\n      float ${r}(int row, int col, int depth) {\n        int stride1 = ${n}Shape[2];\n        float texR = float(row);\n        float texC = dot(vec2(col, depth), vec2(stride1, 1));\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                   vec2(${n}TexShape[1], ${n}TexShape[0]);\n        return sampleTexture(${n}, uv);\n      }\n    `:`\n        float ${r}(int row, int col, int depth) {\n          float texR = float(row);\n          float texC = dot(vec2(col, depth), vec2(${i}, 1));\n          vec2 uv = (vec2(texC, texR) + halfCR) /\n                     vec2(${d}.0, ${c}.0);\n          return sampleTexture(${n}, uv);\n        }\n      `;if(d===i&&h==null)return t?`\n      float ${r}(int row, int col, int depth) {\n        float texR = dot(vec2(row, col), vec2(${n}Shape[1], 1));\n        float texC = float(depth);\n        vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${n}TexShape[1], ${n}TexShape[0]);\n        return sampleTexture(${n}, uv);\n      }\n    `:`\n    float ${r}(int row, int col, int depth) {\n      float texR = dot(vec2(row, col), vec2(${a[1]}, 1));\n      float texC = float(depth);\n      vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${d}.0, ${c}.0);\n      return sampleTexture(${n}, uv);\n    }\n  `;let f=yo(n);return t?`\n    float ${r}(int row, int col, int depth) {\n      // Explicitly use integer operations as dot() only works on floats.\n      int stride0 = ${n}Shape[1] * ${n}Shape[2];\n      int stride1 = ${n}Shape[2];\n      int index = row * stride0 + col * stride1 + depth + ${f};\n      vec2 uv = uvFromFlat(${n}TexShape[0], ${n}TexShape[1], index);\n      return sampleTexture(${n}, uv);\n    }\n    `:`\n      float ${r}(int row, int col, int depth) {\n        // Explicitly use integer operations as dot() only works on floats.\n        int index = row * ${s} + col * ${i} + depth + ${f};\n        vec2 uv = uvFromFlat(${c}, ${d}, index);\n        return sampleTexture(${n}, uv);\n      }\n  `}function WV(e,t){let a=e.name,n=\"get\"+a.charAt(0).toUpperCase()+a.slice(1),r=Ca();if(t)return`\n    vec4 ${n}(int b2, int b, int row, int col) {\n      int valuesPerRow = int(ceil(float(${a}Shape[3]) / 2.0));\n      int texelsInBatch = valuesPerRow * int(ceil(float(${a}Shape[2]) / 2.0));\n      int index = b * texelsInBatch + (row / 2) * valuesPerRow + (col / 2);\n      texelsInBatch *= ${a}Shape[1];\n      index = b2 * texelsInBatch + index;\n      ivec2 packedTexShape = ivec2(ceil(float(${a}TexShape[0]) / 2.0), ceil(float(${a}TexShape[1]) / 2.0));\n      int texR = index / packedTexShape[1];\n      int texC = index - texR * packedTexShape[1];\n      vec2 uv = (vec2(texC, texR) + halfCR) / vec2(packedTexShape[1], packedTexShape[0]); return ${r.texture2D}(${a}, uv);\n    }\n  `;let s=e.shapeInfo.logicalShape,i=s.length,o=e.shapeInfo.texShape,l=[Math.ceil(o[0]/2),Math.ceil(o[1]/2)],u=l[0],p=l[1],c=Math.ceil(s[i-1]/2),d=c*Math.ceil(s[i-2]/2),h=\"int b, int row, int col\",f=`b * ${d} + (row / 2) * ${c} + (col / 2)`;for(let m=2;m<i-1;m++)h=`int b${m}, `+h,d*=s[i-m-1],f=`b${m} * ${d} + `+f;return`\n    vec4 ${n}(${h}) {\n      int index = ${f};\n      int texR = index / ${p};\n      int texC = index - texR * ${p};\n      vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${p}, ${u});\n      return ${r.texture2D}(${a}, uv);\n    }\n  `}function VV(e,t){let a=e.shapeInfo.logicalShape,n=e.name,r=\"get\"+n.charAt(0).toUpperCase()+n.slice(1),s=a[3],i=a[2]*s,o=a[1]*i,{newShape:l,keptDims:u}=v.squeezeShape(a);if(l.length<a.length){let A=cu(e,l),y=[\"row\",\"col\",\"depth\",\"depth2\"];return`\n      ${du(A,t)}\n      float ${r}(int row, int col, int depth, int depth2) {\n        return ${r}(${hu(y,u)});\n      }\n    `}if(e.shapeInfo.isUniform)return`\n      float ${r}(int row, int col, int depth, int depth2) {\n        int index = round(dot(vec4(row, col, depth, depth2),\n                          vec4(${o}, ${i}, ${s}, 1)));\n        ${pu(e)}\n      }\n    `;let p=e.shapeInfo.flatOffset,c=e.shapeInfo.texShape,d=c[0],h=c[1],f=`int stride2 = ${n}Shape[3];`,m=`int stride1 = ${n}Shape[2] * stride2;`,g=`int stride0 = ${n}Shape[1] * stride1;`;if(h===o&&p==null)return t?`\n      float ${r}(int row, int col, int depth, int depth2) {\n        ${f}\n        ${m}\n        float texR = float(row);\n        float texC =\n            dot(vec3(col, depth, depth2),\n                vec3(stride1, stride2, 1));\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                   vec2(${n}TexShape[1], ${n}TexShape[0]);\n        return sampleTexture(${n}, uv);\n      }\n    `:`\n      float ${r}(int row, int col, int depth, int depth2) {\n        float texR = float(row);\n        float texC =\n            dot(vec3(col, depth, depth2),\n                vec3(${i}, ${s}, 1));\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                   vec2(${h}.0, ${d}.0);\n        return sampleTexture(${n}, uv);\n      }\n    `;if(h===s&&p==null)return t?`\n      float ${r}(int row, int col, int depth, int depth2) {\n        float texR = dot(vec3(row, col, depth),\n                         vec3(${n}Shape[1] * ${n}Shape[2], ${n}Shape[2], 1));\n        float texC = float(depth2);\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                  vec2(${n}TexShape[1], ${n}TexShape[0]);\n        return sampleTexture(${n}, uv);\n      }\n    `:`\n      float ${r}(int row, int col, int depth, int depth2) {\n        float texR = dot(vec3(row, col, depth),\n                         vec3(${a[1]*a[2]}, ${a[2]}, 1));\n        float texC = float(depth2);\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                  vec2(${h}.0, ${d}.0);\n        return sampleTexture(${n}, uv);\n      }\n    `;let x=yo(n);return t?`\n    float ${r}(int row, int col, int depth, int depth2) {\n      // Explicitly use integer operations as dot() only works on floats.\n      ${f}\n      ${m}\n      ${g}\n      int index = row * stride0 + col * stride1 +\n          depth * stride2 + depth2;\n      vec2 uv = uvFromFlat(${n}TexShape[0], ${n}TexShape[1], index + ${x});\n      return sampleTexture(${n}, uv);\n    }\n  `:`\n    float ${r}(int row, int col, int depth, int depth2) {\n      // Explicitly use integer operations as dot() only works on floats.\n      int index = row * ${o} + col * ${i} +\n          depth * ${s} + depth2;\n      vec2 uv = uvFromFlat(${d}, ${h}, index + ${x});\n      return sampleTexture(${n}, uv);\n    }\n  `}function UV(e){let t=e.shapeInfo.logicalShape,a=e.name,n=\"get\"+a.charAt(0).toUpperCase()+a.slice(1),r=t[4],s=t[3]*r,i=t[2]*s,o=t[1]*i,{newShape:l,keptDims:u}=v.squeezeShape(t);if(l.length<t.length){let m=cu(e,l),g=[\"row\",\"col\",\"depth\",\"depth2\",\"depth3\"];return`\n      ${du(m)}\n      float ${n}(int row, int col, int depth, int depth2, int depth3) {\n        return ${n}(${hu(g,u)});\n      }\n    `}if(e.shapeInfo.isUniform)return`\n      float ${n}(int row, int col, int depth, int depth2, int depth3) {\n        float index = dot(\n          vec4(row, col, depth, depth2),\n          vec4(${o}, ${i}, ${s}, ${r})) +\n          depth3;\n        ${pu(e)}\n      }\n    `;let p=e.shapeInfo.flatOffset,c=e.shapeInfo.texShape,d=c[0],h=c[1];if(h===o&&p==null)return`\n      float ${n}(int row, int col, int depth, int depth2, int depth3) {\n        int texR = row;\n        float texC = dot(vec4(col, depth, depth2, depth3),\n                         vec4(${i}, ${s}, ${r}, 1));\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                   vec2(${h}.0, ${d}.0);\n        return sampleTexture(${a}, uv);\n      }\n    `;if(h===r&&p==null)return`\n      float ${n}(int row, int col, int depth, int depth2, int depth3) {\n        float texR = dot(\n          vec4(row, col, depth, depth2),\n          vec4(${t[1]*t[2]*t[3]},\n               ${t[2]*t[3]}, ${t[3]}, 1));\n        int texC = depth3;\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                  vec2(${h}.0, ${d}.0);\n        return sampleTexture(${a}, uv);\n      }\n    `;let f=yo(a);return`\n    float ${n}(int row, int col, int depth, int depth2, int depth3) {\n      // Explicitly use integer operations as dot() only works on floats.\n      int index = row * ${o} + col * ${i} + depth * ${s} +\n          depth2 * ${r} + depth3 + ${f};\n      vec2 uv = uvFromFlat(${d}, ${h}, index);\n      return sampleTexture(${a}, uv);\n    }\n  `}function GV(e){let t=e.shapeInfo.logicalShape,a=e.name,n=\"get\"+a.charAt(0).toUpperCase()+a.slice(1),{newShape:r,keptDims:s}=v.squeezeShape(t);if(r.length<t.length){let g=cu(e,r),x=[\"row\",\"col\",\"depth\",\"depth2\",\"depth3\",\"depth4\"];return`\n      ${du(g)}\n      float ${n}(int row, int col, int depth,\n                    int depth2, int depth3, int depth4) {\n        return ${n}(${hu(x,s)});\n      }\n    `}let i=t[5],o=t[4]*i,l=t[3]*o,u=t[2]*l,p=t[1]*u;if(e.shapeInfo.isUniform)return`\n      float ${n}(int row, int col, int depth,\n                  int depth2, int depth3, int depth4) {\n        int index = round(dot(\n          vec4(row, col, depth, depth2),\n          vec4(${p}, ${u}, ${l}, ${o})) +\n          dot(\n            vec2(depth3, depth4),\n            vec2(${i}, 1)));\n        ${pu(e)}\n      }\n    `;let c=e.shapeInfo.flatOffset,d=e.shapeInfo.texShape,h=d[0],f=d[1];if(f===p&&c==null)return`\n      float ${n}(int row, int col, int depth,\n                    int depth2, int depth3, int depth4) {\n        int texR = row;\n        float texC = dot(vec4(col, depth, depth2, depth3),\n          vec4(${u}, ${l}, ${o}, ${i})) +\n               float(depth4);\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                   vec2(${f}.0, ${h}.0);\n        return sampleTexture(${a}, uv);\n      }\n    `;if(f===i&&c==null)return`\n      float ${n}(int row, int col, int depth,\n                    int depth2, int depth3, int depth4) {\n        float texR = dot(vec4(row, col, depth, depth2),\n          vec4(${t[1]*t[2]*t[3]*t[4]},\n               ${t[2]*t[3]*t[4]},\n               ${t[3]*t[4]},\n               ${t[4]})) + float(depth3);\n        int texC = depth4;\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                  vec2(${f}.0, ${h}.0);\n        return sampleTexture(${a}, uv);\n      }\n    `;let m=yo(a);return`\n    float ${n}(int row, int col, int depth,\n                  int depth2, int depth3, int depth4) {\n      // Explicitly use integer operations as dot() only works on floats.\n      int index = row * ${p} + col * ${u} + depth * ${l} +\n          depth2 * ${o} + depth3 * ${i} + depth4 + ${m};\n      vec2 uv = uvFromFlat(${h}, ${f}, index);\n      return sampleTexture(${a}, uv);\n    }\n  `}function pu(e){let t=e.name,a=v.sizeFromShape(e.shapeInfo.logicalShape);return a<2?`return ${t};`:`\n    for (int i = 0; i < ${a}; i++) {\n      if (i == index) {\n        return ${t}[i];\n      }\n    }\n  `}function HV(e,t){let a=e.name,n=a.charAt(0).toUpperCase()+a.slice(1),r=\"get\"+n+\"AtOutCoords\",s=e.shapeInfo.logicalShape.length,i=t.logicalShape.length,o=A6(e.shapeInfo.logicalShape,t.logicalShape),l=gt(i),u=i-s,p,c=[\"x\",\"y\",\"z\",\"w\",\"u\",\"v\"];s===0?p=\"\":i<2&&o.length>=1?p=\"coords = 0;\":p=o.map(g=>`coords.${c[g+u]} = 0;`).join(`\n`);let d=\"\";i<2&&s>0?d=\"coords\":d=e.shapeInfo.logicalShape.map((g,x)=>`coords.${c[x+u]}`).join(\", \");let h=\"return outputValue;\",f=v.sizeFromShape(e.shapeInfo.logicalShape)===1,m=v.sizeFromShape(t.logicalShape)===1;if(s===1&&!f&&!m)h=`\n      return vec4(outputValue.xy, outputValue.xy);\n    `;else if(f&&!m)i===1?h=`\n        return vec4(outputValue.x, outputValue.x, 0., 0.);\n      `:h=`\n        return vec4(outputValue.x);\n      `;else if(o.length){let g=s-2,x=s-1;o.indexOf(g)>-1&&o.indexOf(x)>-1?h=\"return vec4(outputValue.x);\":o.indexOf(g)>-1?h=\"return vec4(outputValue.x, outputValue.y, outputValue.x, outputValue.y);\":o.indexOf(x)>-1&&(h=\"return vec4(outputValue.xx, outputValue.zz);\")}return`\n    vec4 ${r}() {\n      ${l} coords = getOutputCoords();\n      ${p}\n      vec4 outputValue = get${n}(${d});\n      ${h}\n    }\n  `}function jV(e,t){let a=e.name,n=a.charAt(0).toUpperCase()+a.slice(1),r=\"get\"+n+\"AtOutCoords\",s=t.texShape,i=e.shapeInfo.texShape,o=e.shapeInfo.logicalShape.length,l=t.logicalShape.length;if(!e.shapeInfo.isUniform&&o===l&&e.shapeInfo.flatOffset==null&&v.arraysEqual(i,s))return`\n      float ${r}() {\n        return sampleTexture(${a}, resultUV);\n      }\n    `;let u=gt(l),p=A6(e.shapeInfo.logicalShape,t.logicalShape),c=l-o,d,h=[\"x\",\"y\",\"z\",\"w\",\"u\",\"v\"];o===0?d=\"\":l<2&&p.length>=1?d=\"coords = 0;\":d=p.map(m=>`coords.${h[m+c]} = 0;`).join(`\n`);let f=\"\";return l<2&&o>0?f=\"coords\":f=e.shapeInfo.logicalShape.map((m,g)=>`coords.${h[g+c]}`).join(\", \"),`\n    float ${r}() {\n      ${u} coords = getOutputCoords();\n      ${d}\n      return get${n}(${f});\n    }\n  `}function gt(e){if(e<=1)return\"int\";if(e===2)return\"ivec2\";if(e===3)return\"ivec3\";if(e===4)return\"ivec4\";if(e===5)return\"ivec5\";if(e===6)return\"ivec6\";throw Error(`GPU for rank ${e} is not yet supported`)}function k3(e,t,a){let{newShape:n,keptDims:r}=v.squeezeShape(t),s=t.length,i=e&&s===3&&t[0]===1,o=i?t.slice(1):n,l=!e&&s>1&&!v.arraysEqual(t,a)&&n.length<s||i;return{useSqueezeShape:l,uniformShape:l?o:t,keptDims:r}}function cu(e,t){let a=JSON.parse(JSON.stringify(e));return a.shapeInfo.logicalShape=t,a}function hu(e,t){return t.map(a=>e[a]).join(\", \")}function qV(e,t,a,n){let r=a.map((p,c)=>{let d={logicalShape:p.shape,texShape:p.isUniform?null:p.texData.texShape,isUniform:p.isUniform,isPacked:p.isUniform?!1:p.texData.isPacked,flatOffset:null};return p.texData!=null&&p.texData.slice!=null&&p.texData.slice.flatOffset>0&&(d.flatOffset=p.texData.slice.flatOffset),{name:t.variableNames[c],shapeInfo:d}}),s=r.map(p=>p.shapeInfo),i={logicalShape:n.shape,texShape:n.texData.texShape,isUniform:!1,isPacked:n.texData.isPacked,flatOffset:null},o=pV(r,i,t),l=Z7(e.gl,o),u=e.createProgram(l);return W().get(\"ENGINE_COMPILE_ONLY\")?{program:t,fragmentShader:l,source:o,webGLProgram:u,inShapeInfos:s,outShapeInfo:i,uniformLocations:null,customUniformLocations:null,infLoc:null,nanLoc:null,inShapesLocations:null,inTexShapesLocations:null,outShapeLocation:null,outShapeStridesLocation:null,outTexShapeLocation:null}:Object.assign({program:t,fragmentShader:l,source:o,webGLProgram:u,inShapeInfos:s,outShapeInfo:i},v6(e,t,u))}function v6(e,t,a){let n={},r={},s={},i=[],o,l,u,p=null,c=null;c=e.getUniformLocation(a,\"NAN\",!1),W().getNumber(\"WEBGL_VERSION\")===1&&(p=e.getUniformLocation(a,\"INFINITY\",!1));let d=!1;for(let h=0;h<t.variableNames.length;h++){let f=t.variableNames[h];n[f]=e.getUniformLocation(a,f,d),n[`offset${f}`]=e.getUniformLocation(a,`offset${f}`,d),t.enableShapeUniforms&&(r[`${f}Shape`]=e.getUniformLocation(a,`${f}Shape`,d),s[`${f}TexShape`]=e.getUniformLocation(a,`${f}TexShape`,d))}return t.enableShapeUniforms&&(o=e.getUniformLocation(a,\"outShape\",d),u=e.getUniformLocation(a,\"outShapeStrides\",d),l=e.getUniformLocation(a,\"outTexShape\",d)),t.customUniforms&&t.customUniforms.forEach((h,f)=>{i[f]=e.getUniformLocation(a,h.name,d)}),{uniformLocations:n,customUniformLocations:i,infLoc:p,nanLoc:c,inShapesLocations:r,inTexShapesLocations:s,outShapeLocation:o,outShapeStridesLocation:u,outTexShapeLocation:l}}function cx(e,t){if(e.length!==t.length)throw Error(`Binary was compiled with ${e.length} inputs, but was executed with ${t.length} inputs`);e.forEach((a,n)=>{let r=a.logicalShape,s=t[n],i=s.shape;if(!v.arraysEqual(r,i))throw Error(`Binary was compiled with different shapes than the current args. Shapes ${r} and ${i} must match`);if(a.isUniform&&s.isUniform)return;let o=a.texShape,l=s.isUniform?null:s.texData.texShape;if(!v.arraysEqual(o,l))throw Error(`Binary was compiled with different texture shapes than the current args. Shape ${o} and ${l} must match`)})}function XV(e,t,a,n,r){t.program.enableShapeUniforms||(cx(t.inShapeInfos,a),cx([t.outShapeInfo],[n]));let s=n.texData.texture,i=n.texData.texShape;n.texData.isPacked?e.setOutputPackedMatrixTexture(s.texture,i[0],i[1]):e.setOutputMatrixTexture(s.texture,i[0],i[1]),e.setProgram(t.webGLProgram),W().getNumber(\"WEBGL_VERSION\")===1&&t.infLoc!==null&&e.gl.uniform1f(t.infLoc,1/0),t.nanLoc!==null&&e.gl.uniform1f(t.nanLoc,NaN),a.forEach((l,u)=>{let p=t.program.variableNames[u],c=t.uniformLocations[p],d=t.uniformLocations[`offset${p}`],h=t.inShapesLocations[`${p}Shape`],f=t.inTexShapesLocations[`${p}TexShape`];if(h){let{uniformShape:m}=k3(t.program.packedInputs,l.shape,l.texData.texShape);switch(m.length){case 1:e.gl.uniform1iv(h,new Int32Array(m));break;case 2:e.gl.uniform2iv(h,new Int32Array(m));break;case 3:e.gl.uniform3iv(h,new Int32Array(m));break;case 4:e.gl.uniform4iv(h,new Int32Array(m));break;default:break}}if(f&&e.gl.uniform2i(f,l.texData.texShape[0],l.texData.texShape[1]),c!=null){if(l.isUniform){if(v.sizeFromShape(l.shape)<2)e.gl.uniform1f(c,l.uniformValues[0]);else{let m=l.uniformValues;m instanceof Float32Array||(m=new Float32Array(m)),e.gl.uniform1fv(c,m)}return}l.texData.slice!=null&&d!=null&&e.gl.uniform1i(d,l.texData.slice.flatOffset),e.setInputMatrixTexture(l.texData.texture.texture,c,u)}});let o=t.outShapeLocation;if(o)switch(n.shape.length){case 1:e.gl.uniform1iv(o,new Int32Array(n.shape));break;case 2:e.gl.uniform2iv(o,new Int32Array(n.shape));break;case 3:e.gl.uniform3iv(o,new Int32Array(n.shape));break;case 4:e.gl.uniform4iv(o,new Int32Array(n.shape));break;default:break}if(t.outShapeStridesLocation){let l=v.computeStrides(n.shape);switch(n.shape.length){case 2:e.gl.uniform1iv(t.outShapeStridesLocation,new Int32Array(l));break;case 3:e.gl.uniform2iv(t.outShapeStridesLocation,new Int32Array(l));break;case 4:e.gl.uniform3iv(t.outShapeStridesLocation,new Int32Array(l));break;default:break}}t.outTexShapeLocation&&e.gl.uniform2i(t.outTexShapeLocation,n.texData.texShape[0],n.texData.texShape[1]),t.program.customUniforms&&r&&t.program.customUniforms.forEach((l,u)=>{let p=t.customUniformLocations[u],c=r[u];if(l.type===\"float\")e.gl.uniform1fv(p,c);else if(l.type===\"vec2\")e.gl.uniform2fv(p,c);else if(l.type===\"vec3\")e.gl.uniform3fv(p,c);else if(l.type===\"vec4\")e.gl.uniform4fv(p,c);else if(l.type===\"int\")e.gl.uniform1iv(p,c);else if(l.type===\"ivec2\")e.gl.uniform2iv(p,c);else if(l.type===\"ivec3\")e.gl.uniform3iv(p,c);else if(l.type===\"ivec4\")e.gl.uniform4iv(p,c);else throw Error(`uniform type ${l.type} is not supported yet.`)}),e.executeProgram()}function KV(e,t,a){let n=\"\";t.concat(a).forEach(i=>{let o=i.texData!=null&&i.texData.slice!=null&&i.texData.slice.flatOffset>0;if(e.enableShapeUniforms&&!i.isUniform){let l=i.texData.texShape,{useSqueezeShape:u,uniformShape:p,keptDims:c}=k3(e.packedInputs,i.shape,l),d=\"\",h=\"\",f=\"\";if(p.length===1&&e.packedInputs){let w=[Math.ceil(l[0]/2),Math.ceil(l[1]/2)];d=`${w[0]>1}_${w[1]>1}`}else if(p.length===2&&!e.packedInputs)h=`${p[0]>1}_${p[1]>1}`;else if(p.length>2&&!e.packedInputs){let w=v.computeStrides(p);f=`${w[0]===l[1]}_${w[w.length-1]===l[1]}`}let m=i.shape.length,g=p.length===2&&v.arraysEqual(i.shape,l),x=v.sizeFromShape(i.shape)===1,A=T.getBroadcastDims(i.shape,a.shape),y=!e.packedInputs&&m===a.shape.length&&v.arraysEqual(l,a.texData.texShape),b=e.packedInputs||p.length>2?\"\":`${l[0]>1}_${l[1]>1}`;n+=`${m}_${y}_${u?c:\"\"}_${p.length}_${x}_${A}_${g}_${d}_${h}_${f}_${b}_${o}`}else{let l=i.isUniform?\"uniform\":i.texData.texShape;n+=`${i.shape}_${l}_${o}`}});let r=e.userCode,s=e.constructor.name;return s+=\"_\"+n+\"_\"+r+`${W().getNumber(\"WEBGL_VERSION\")}`,s}function Na(e){return W().getBool(\"WEBGL_USE_SHAPES_UNIFORMS\")&&e<=4}var ZV=class{constructor(e){this.variableNames=[\"A\"],this.packedInputs=!1,this.packedOutput=!0,this.outPackingScheme=fd.DENSE,this.customUniforms=[{name:\"texShape\",type:\"ivec2\"}];let t=Ca();this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length),this.userCode=`\n      ivec3 outCoordsFromFlatIndex(int index) {\n        ${this.enableShapeUniforms?Oh([\"r\",\"c\",\"d\"],e):Ao([\"r\",\"c\",\"d\"],e)}\n        return ivec3(r, c, d);\n      }\n\n      void main() {\n        ivec2 resTexRC = ivec2(resultUV.yx * vec2(texShape[0], texShape[1]));\n        int index = 4 * (resTexRC.x * texShape[1] + resTexRC.y);\n\n        vec4 result = vec4(0.);\n\n        for (int i=0; i<4; i++) {\n          int flatIndex = index + i;\n          ivec3 rc = outCoordsFromFlatIndex(flatIndex);\n          result[i] = getA(rc.x, rc.y, rc.z);\n        }\n\n        ${t.output} = result;\n      }\n    `}},YV=class{constructor(e){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0,this.outPackingScheme=fd.DENSE,this.customUniforms=[{name:\"texShape\",type:\"ivec2\"}];let t=Ca();this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length),this.userCode=`\n      ivec3 outCoordsFromFlatIndex(int index) {\n        ${this.enableShapeUniforms?Oh([\"r\",\"c\",\"d\"],e):Ao([\"r\",\"c\",\"d\"],e)}\n        return ivec3(r, c, d);\n      }\n\n      void main() {\n        ivec2 resTexRC = ivec2(resultUV.yx * vec2(texShape[0], texShape[1]));\n        int index = 4 * (resTexRC.x * texShape[1] + resTexRC.y);\n\n        vec4 result = vec4(0.);\n\n        for (int i=0; i<4; i++) {\n          int flatIndex = index + i;\n          ivec3 rc = outCoordsFromFlatIndex(flatIndex);\n          result[i] = getChannel(getA(rc.x, rc.y, rc.z), vec2(rc.y, rc.z));\n        }\n\n        ${t.output} = result;\n      }\n    `}},JV=class{constructor(e){this.variableNames=[\"A\"],this.outTexUsage=pn.DOWNLOAD;let t=Ca();this.outputShape=e,this.userCode=`\n      ${x6}\n\n      void main() {\n        float x = getAAtOutCoords();\n        ${t.output} = encode_float(x);\n      }\n    `}},QV=class{constructor(e){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!1,this.outTexUsage=pn.DOWNLOAD;let t=Ca();this.outputShape=e,this.userCode=`\n      ${x6}\n\n      void main() {\n        ivec3 coords = getOutputCoords();\n        float x = getChannel(getAAtOutCoords(), vec2(coords.y, coords.z));\n        ${t.output} = encode_float(x);\n      }\n    `}},eU={R:0,G:1,B:2,A:3},hx=class{constructor(e,t=!1,a=\"RGBA\"){this.variableNames=[\"A\"],this.customUniforms=[{name:\"texShape\",type:\"ivec2\"}];let n=Ca();this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length);let r=\"result\";t&&(r=\"floor(result * 255. + 0.5)\");let s=\"\";for(let i=0;i<a.length;i++){let o=a[i];s+=`\n          if(offset == ${i}) {\n            result = values[${eU[o]}];\n          }`}this.userCode=`\n      ${this.enableShapeUniforms?w3():v3(e)}\n\n      void main() {\n        ivec3 coords = getOutputCoords();\n        int flatIndex = getFlatIndex(coords);\n        float result = 0.;\n        int offset = imod(flatIndex, ${a.length});\n\n        flatIndex = idiv(flatIndex, ${a.length}, 1.);\n\n        int r = flatIndex / texShape[1];\n        if (r < texShape[0]) {\n          int c = imod(flatIndex, texShape[1]);\n          vec2 uv = (vec2(c, r) + halfCR) / vec2(texShape[1], texShape[0]);\n          vec4 values = ${n.texture2D}(A, uv);\n          ${s}\n        }\n        ${n.output} = vec4(${r}, 0., 0., 0.);\n      }\n    `}},tU=class{constructor(e,t=!1){this.variableNames=[\"A\"],this.packedInputs=!1,this.packedOutput=!0,this.customUniforms=[{name:\"texShape\",type:\"ivec2\"}];let a=Ca();this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length);let n=\"\",r=\"result\";t&&(r=\"floor(result * 255. + 0.5)\");for(let s=0;s<=1;s++)for(let i=0;i<=1;i++){let o=s*2+i;n+=`\n          localCoords = coords;\n          if(localCoords[2] + ${i} < ${this.enableShapeUniforms?\"outShape[2]\":`${e[2]}`}) {\n          localCoords[2] += ${i};\n          if (localCoords[1] + ${s} < ${this.enableShapeUniforms?\"outShape[1]\":`${e[1]}`}) {\n            localCoords[1] += ${s};\n\n            flatIndex = getFlatIndex(localCoords);\n            offset = imod(flatIndex, 4);\n\n            flatIndex = idiv(flatIndex, 4, 1.);\n\n            int r = flatIndex / texShape[1];\n            int c = imod(flatIndex, texShape[1]);\n            vec2 uv = (vec2(c, r) + halfCR) / vec2(texShape[1], texShape[0]);\n            values = ${a.texture2D}(A, uv);\n\n            if (offset == 0) {\n              result[${o}] = values[0];\n            } else if (offset == 1) {\n              result[${o}] = values[1];\n            } else if (offset == 2) {\n              result[${o}] = values[2];\n            } else {\n              result[${o}] = values[3];\n            }\n          }\n        }\n        `}this.userCode=`\n        ${this.enableShapeUniforms?w3():v3(e)}\n\n        void main() {\n          ivec3 coords = getOutputCoords();\n\n          vec4 result = vec4(0.);\n          int flatIndex, r, c, offset;\n          ivec3 localCoords;\n          vec2 uv;\n          vec4 values;\n\n          ${n}\n\n          ${a.output} = ${r};\n        }\n    `}},w6={};Xe(w6,{bindVertexProgramAttributeStreams:()=>M6,createBufferFromOutputTexture:()=>P6,createFloat16MatrixTexture:()=>C6,createFloat16PackedMatrixTexture:()=>R6,createFloat32MatrixTexture:()=>T6,createIndexBuffer:()=>S6,createPackedMatrixTexture:()=>E6,createUnsignedBytesMatrixTexture:()=>N6,createVertexBuffer:()=>I6,createVertexShader:()=>k6,downloadByteEncodedFloatMatrixFromOutputTexture:()=>O6,downloadFloat32MatrixFromBuffer:()=>F6,downloadMatrixFromPackedOutputTexture:()=>z6,downloadPackedMatrixFromBuffer:()=>D6,getInternalFormatForFloat16MatrixTexture:()=>S3,getInternalFormatForFloat16PackedMatrixTexture:()=>N3,getInternalFormatForFloat32MatrixTexture:()=>I3,getInternalFormatForPackedMatrixTexture:()=>C3,getInternalFormatForUnsignedBytesMatrixTexture:()=>T3,uploadDenseMatrixToTexture:()=>$6,uploadPixelDataToTexture:()=>_6});function k6(e){let t=Ca(),a=`${t.version}\n    precision highp float;\n    ${t.attribute} vec3 clipSpacePos;\n    ${t.attribute} vec2 uv;\n    ${t.varyingVs} vec2 resultUV;\n\n    void main() {\n      gl_Position = vec4(clipSpacePos, 1);\n      resultUV = uv;\n    }`;return K7(e,a)}function I6(e){let t=new Float32Array([-1,1,0,0,1,-1,-1,0,0,0,1,1,0,1,1,1,-1,0,1,0]);return Q7(e,t)}function S6(e){let t=new Uint16Array([0,1,2,2,1,3]);return e6(e,t)}function dp(e,t,a,n,r,s){a6(t,a);let i=t6(e),o=e.TEXTURE_2D;return le(e,()=>e.bindTexture(o,i)),le(e,()=>e.texParameteri(o,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE)),le(e,()=>e.texParameteri(o,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE)),le(e,()=>e.texParameteri(o,e.TEXTURE_MIN_FILTER,e.NEAREST)),le(e,()=>e.texParameteri(o,e.TEXTURE_MAG_FILTER,e.NEAREST)),W().getNumber(\"WEBGL_VERSION\")===1?le(e,()=>e.texImage2D(o,0,n,t,a,0,r,s,null)):le(e,()=>e.texStorage2D(o,1,n,t,a)),le(e,()=>e.bindTexture(e.TEXTURE_2D,null)),{texture:i,texShape:[a,t]}}function I3(e){return e.internalFormatFloat}function T6(e,t,a,n){let[r,s]=up(t,a);return dp(e,r,s,I3(n),n.textureFormatFloat,e.FLOAT)}function S3(e){return e.internalFormatHalfFloat}function C6(e,t,a,n){let[r,s]=up(t,a);return dp(e,r,s,S3(n),n.textureFormatFloat,n.textureTypeHalfFloat)}function T3(e){return e.downloadTextureFormat}function N6(e,t,a,n){let[r,s]=up(t,a);return dp(e,r,s,T3(n),e.RGBA,e.UNSIGNED_BYTE)}function C3(e){return e.internalFormatPackedFloat}function E6(e,t,a,n){let[r,s]=lu(t,a);return dp(e,r,s,C3(n),e.RGBA,e.FLOAT)}function N3(e){return e.internalFormatPackedHalfFloat}function R6(e,t,a,n){let[r,s]=lu(t,a);return dp(e,r,s,N3(n),e.RGBA,n.textureTypeHalfFloat)}function M6(e,t,a){return le(e,()=>e.bindBuffer(e.ARRAY_BUFFER,a)),w1(e,t,\"clipSpacePos\",a,3,20,0)&&w1(e,t,\"uv\",a,2,20,12)}function $6(e,t,a,n,r,s){le(e,()=>e.bindTexture(e.TEXTURE_2D,t));let i,o,l;r instanceof Uint8Array?(i=new Uint8Array(a*n*4),o=e.UNSIGNED_BYTE,l=e.RGBA):(i=new Float32Array(a*n*4),o=e.FLOAT,l=s.internalFormatPackedFloat),i.set(r),W().getNumber(\"WEBGL_VERSION\")===2?le(e,()=>e.texSubImage2D(e.TEXTURE_2D,0,0,0,a,n,e.RGBA,o,i)):le(e,()=>e.texImage2D(e.TEXTURE_2D,0,l,a,n,0,e.RGBA,o,i)),le(e,()=>e.bindTexture(e.TEXTURE_2D,null))}function _6(e,t,a){le(e,()=>e.bindTexture(e.TEXTURE_2D,t)),a.data instanceof Uint8Array?W().getNumber(\"WEBGL_VERSION\")===2?le(e,()=>e.texSubImage2D(e.TEXTURE_2D,0,0,0,a.width,a.height,e.RGBA,e.UNSIGNED_BYTE,a.data)):le(e,()=>e.texImage2D(e.TEXTURE_2D,0,e.RGBA,a.width,a.height,0,e.RGBA,e.UNSIGNED_BYTE,a.data)):W().getNumber(\"WEBGL_VERSION\")===2?le(e,()=>e.texSubImage2D(e.TEXTURE_2D,0,0,0,e.RGBA,e.UNSIGNED_BYTE,a)):le(e,()=>e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,a)),le(e,()=>e.bindTexture(e.TEXTURE_2D,null))}function P6(e,t,a,n){let r=e.createBuffer();le(e,()=>e.bindBuffer(e.PIXEL_PACK_BUFFER,r));let s=4*4*t*a;return le(e,()=>e.bufferData(e.PIXEL_PACK_BUFFER,s,e.STREAM_READ)),le(e,()=>e.readPixels(0,0,a,t,e.RGBA,e.FLOAT,0)),le(e,()=>e.bindBuffer(e.PIXEL_PACK_BUFFER,null)),r}function F6(e,t,a){let n=e,r=new Float32Array(a);return n.bindBuffer(n.PIXEL_PACK_BUFFER,t),n.getBufferSubData(n.PIXEL_PACK_BUFFER,0,r),n.bindBuffer(n.PIXEL_PACK_BUFFER,null),r}function O6(e,t,a,n){let[r,s]=up(t,a),i=4,o=new Uint8Array(YW(t*a,i));return le(e,()=>e.readPixels(0,0,r,s,n.downloadTextureFormat,e.UNSIGNED_BYTE,o)),new Float32Array(o.buffer)}function D6(e,t,a,n,r,s,i,o){let l=e,u=new Float32Array(JW(s,i));return l.bindBuffer(l.PIXEL_PACK_BUFFER,t),l.getBufferSubData(l.PIXEL_PACK_BUFFER,0,u),l.bindBuffer(l.PIXEL_PACK_BUFFER,null),u}function z6(e,t,a){let n=new Float32Array(t*a*4);return le(e,()=>e.readPixels(0,0,a,t,e.RGBA,e.FLOAT,n)),n}var il=class{constructor(e){this.outputTexture=null,this.program=null,this.disposed=!1,this.itemsToPoll=[];let t=W().getNumber(\"WEBGL_VERSION\");if(e!=null?(this.gl=e,Fh(t,e)):this.gl=Dn(t),e=this.gl,W().getNumber(\"WEBGL_VERSION\")===2){let r=e;this.createVertexArray=()=>le(r,()=>r.createVertexArray()),this.bindVertexArray=s=>le(r,()=>r.bindVertexArray(s)),this.deleteVertexArray=s=>le(r,()=>r.deleteVertexArray(s)),this.getVertexArray=()=>le(r,()=>r.getParameter(r.VERTEX_ARRAY_BINDING))}else if(e!=null){let r=e.getExtension(\"OES_vertex_array_object\");if(r==null)throw new Error(\"All WebGL1 implementations are expected to offer OES_vertex_array_object.\");this.createVertexArray=()=>le(e,()=>r.createVertexArrayOES()),this.bindVertexArray=s=>le(e,()=>r.bindVertexArrayOES(s)),this.deleteVertexArray=s=>le(e,()=>r.deleteVertexArrayOES(s)),this.getVertexArray=()=>le(e,()=>e.getParameter(r.VERTEX_ARRAY_BINDING_OES))}let a=\"WEBGL_color_buffer_float\",n=\"EXT_color_buffer_half_float\";if(this.parallelCompilationExtension=this.gl.getExtension(\"KHR_parallel_shader_compile\"),W().getNumber(\"WEBGL_VERSION\")===1){let r=\"OES_texture_float\",s=\"OES_texture_half_float\";if(this.textureFloatExtension=qu(this.gl,r),cn(this.gl,s))this.textureHalfFloatExtension=qu(this.gl,s);else if(W().get(\"WEBGL_FORCE_F16_TEXTURES\"))throw new Error(\"GL context does not support half float textures, yet the environment flag WEBGL_FORCE_F16_TEXTURES is set to true.\");if(this.colorBufferFloatExtension=this.gl.getExtension(a),cn(this.gl,n))this.colorBufferHalfFloatExtension=qu(this.gl,n);else if(W().get(\"WEBGL_FORCE_F16_TEXTURES\"))throw new Error(\"GL context does not support color renderable half floats, yet the environment flag WEBGL_FORCE_F16_TEXTURES is set to true.\")}else if(a=\"EXT_color_buffer_float\",cn(this.gl,a))this.colorBufferFloatExtension=this.gl.getExtension(a);else if(cn(this.gl,n))this.colorBufferHalfFloatExtension=this.gl.getExtension(n);else throw new Error(\"GL context does not support color renderable floats\");this.vertexBuffer=I6(this.gl),this.indexBuffer=S6(this.gl),this.framebuffer=n6(this.gl),this.textureConfig=y3(this.gl,this.textureHalfFloatExtension)}get debug(){return W().getBool(\"DEBUG\")}dispose(){if(this.disposed)return;this.program!=null&&console.warn(\"Disposing a GPGPUContext that still has a bound WebGLProgram. This is probably a resource leak, delete the program with GPGPUContext.deleteProgram before disposing.\"),this.outputTexture!=null&&console.warn(\"Disposing a GPGPUContext that still has a bound output matrix texture.  This is probably a resource leak, delete the output matrix texture with GPGPUContext.deleteMatrixTexture before disposing.\");let e=this.gl;le(e,()=>e.finish()),le(e,()=>e.bindFramebuffer(e.FRAMEBUFFER,null)),le(e,()=>e.deleteFramebuffer(this.framebuffer)),le(e,()=>e.bindBuffer(e.ARRAY_BUFFER,null)),le(e,()=>e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,null)),le(e,()=>e.deleteBuffer(this.indexBuffer)),this.disposed=!0}createFloat32MatrixTexture(e,t){return this.throwIfDisposed(),T6(this.gl,e,t,this.textureConfig)}createFloat16MatrixTexture(e,t){return this.throwIfDisposed(),C6(this.gl,e,t,this.textureConfig)}createUnsignedBytesMatrixTexture(e,t){return this.throwIfDisposed(),N6(this.gl,e,t,this.textureConfig)}uploadPixelDataToTexture(e,t){this.throwIfDisposed(),_6(this.gl,e,t)}uploadDenseMatrixToTexture(e,t,a,n){this.throwIfDisposed(),$6(this.gl,e,t,a,n,this.textureConfig)}createFloat16PackedMatrixTexture(e,t){return this.throwIfDisposed(),R6(this.gl,e,t,this.textureConfig)}createPackedMatrixTexture(e,t){return this.throwIfDisposed(),E6(this.gl,e,t,this.textureConfig)}deleteMatrixTexture(e){this.throwIfDisposed(),this.outputTexture===e&&(k1(this.gl,this.framebuffer),this.outputTexture=null),le(this.gl,()=>this.gl.deleteTexture(e))}downloadByteEncodedFloatMatrixFromOutputTexture(e,t,a){return this.downloadMatrixDriver(e,()=>O6(this.gl,t,a,this.textureConfig))}downloadPackedMatrixFromBuffer(e,t,a,n,r,s){return D6(this.gl,e,t,a,n,r,s,this.textureConfig)}downloadFloat32MatrixFromBuffer(e,t){return F6(this.gl,e,t)}createBufferFromTexture(e,t,a){this.bindTextureToFrameBuffer(e);let n=P6(this.gl,t,a,this.textureConfig);return this.unbindTextureToFrameBuffer(),n}createAndWaitForFence(){let e=this.createFence(this.gl);return this.pollFence(e)}createFence(e){let t,a;if(W().getBool(\"WEBGL_FENCE_API_ENABLED\")){let n=e,r=n.fenceSync(n.SYNC_GPU_COMMANDS_COMPLETE,0);e.flush(),a=()=>{let s=n.clientWaitSync(r,0,0);return s===n.ALREADY_SIGNALED||s===n.CONDITION_SATISFIED},t=r}else W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\")>0?(t=this.beginQuery(),this.endQuery(),a=()=>this.isQueryAvailable(t,W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\"))):a=()=>!0;return{query:t,isFencePassed:a}}downloadMatrixFromPackedTexture(e,t,a){return this.downloadMatrixDriver(e,()=>z6(this.gl,t,a))}createProgram(e){this.throwIfDisposed();let t=this.gl;this.vertexShader==null&&(this.vertexShader=k6(t));let a=Y7(t);le(t,()=>t.attachShader(a,this.vertexShader)),le(t,()=>t.attachShader(a,e)),J7(t,a);let n;return n=Object.assign(a,{vao:this.createVertexArray()}),this.bindVertexArray(n.vao),le(t,()=>t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.indexBuffer)),console.assert(M6(t,n,this.vertexBuffer),\"gpgpu_util.bindVertexProgramAttributeStreams not fully successful.\"),this.debug&&gc(t,n),this.setProgram(n),n}deleteProgram(e){this.throwIfDisposed(),e===this.program&&(this.program=null),e!=null&&(le(this.gl,()=>this.gl.deleteProgram(e)),this.deleteVertexArray(e.vao))}setProgram(e){this.throwIfDisposed(),this.program=e,this.program!=null&&(this.bindVertexArray(this.program.vao),this.debug&&gc(this.gl,this.program)),le(this.gl,()=>this.gl.useProgram(e))}getUniformLocation(e,t,a=!0){return this.throwIfDisposed(),a?s6(this.gl,e,t):i6(this.gl,e,t)}getAttributeLocation(e,t){return this.throwIfDisposed(),le(this.gl,()=>this.gl.getAttribLocation(e,t))}getUniformLocationNoThrow(e,t){return this.throwIfDisposed(),this.gl.getUniformLocation(e,t)}setInputMatrixTexture(e,t,a){this.throwIfDisposed(),this.throwIfNoProgram(),o6(this.gl,e,t,a)}setOutputMatrixTexture(e,t,a){this.setOutputMatrixTextureDriver(e,a,t)}setOutputPackedMatrixTexture(e,t,a){this.throwIfDisposed();let[n,r]=lu(t,a);this.setOutputMatrixTextureDriver(e,n,r)}setOutputMatrixWriteRegion(e,t,a,n){this.setOutputMatrixWriteRegionDriver(a,e,n,t)}setOutputPackedMatrixWriteRegion(e,t,a,n){throw new Error(\"setOutputPackedMatrixWriteRegion not implemented.\")}debugValidate(){this.program!=null&&gc(this.gl,this.program),Xu(this.gl)}executeProgram(){this.throwIfDisposed(),this.throwIfNoProgram();let e=this.gl;if(this.debug){let t=this.getVertexArray();console.assert(t===this.program.vao,\"VAO changed between setProgram and executeProgram!\"),this.debugValidate()}le(e,()=>e.drawElements(e.TRIANGLES,6,e.UNSIGNED_SHORT,0))}blockUntilAllProgramsCompleted(){this.throwIfDisposed(),le(this.gl,()=>this.gl.finish())}getQueryTimerExtension(){return this.disjointQueryTimerExtension==null&&(this.disjointQueryTimerExtension=qu(this.gl,W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\")===2?\"EXT_disjoint_timer_query_webgl2\":\"EXT_disjoint_timer_query\")),this.disjointQueryTimerExtension}getQueryTimerExtensionWebGL2(){return this.getQueryTimerExtension()}getQueryTimerExtensionWebGL1(){return this.getQueryTimerExtension()}beginQuery(){if(W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\")===2){let a=this.gl,n=this.getQueryTimerExtensionWebGL2(),r=a.createQuery();return a.beginQuery(n.TIME_ELAPSED_EXT,r),r}let e=this.getQueryTimerExtensionWebGL1(),t=e.createQueryEXT();return e.beginQueryEXT(e.TIME_ELAPSED_EXT,t),t}endQuery(){if(W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\")===2){let t=this.gl,a=this.getQueryTimerExtensionWebGL2();t.endQuery(a.TIME_ELAPSED_EXT);return}let e=this.getQueryTimerExtensionWebGL1();e.endQueryEXT(e.TIME_ELAPSED_EXT)}async waitForQueryAndGetTime(e){return await v.repeatedTry(()=>this.disposed||this.isQueryAvailable(e,W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\"))),this.getQueryTime(e,W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION\"))}getQueryTime(e,t){if(t===0)return null;if(t===2){let a=this.gl;return a.getQueryParameter(e,a.QUERY_RESULT)/1e6}else{let a=this.getQueryTimerExtensionWebGL1();return a.getQueryObjectEXT(e,a.QUERY_RESULT_EXT)/1e6}}isQueryAvailable(e,t){if(t===0)return!0;if(t===2){let a=this.gl,n=this.getQueryTimerExtensionWebGL2(),r=a.getQueryParameter(e,a.QUERY_RESULT_AVAILABLE);return this.disjoint==null&&(this.disjoint=this.gl.getParameter(n.GPU_DISJOINT_EXT)),r&&!this.disjoint}else{let a=this.getQueryTimerExtensionWebGL1(),n=a.getQueryObjectEXT(e,a.QUERY_RESULT_AVAILABLE_EXT);return this.disjoint==null&&(this.disjoint=this.gl.getParameter(a.GPU_DISJOINT_EXT)),n&&!this.disjoint}}pollFence(e){return new Promise(t=>{this.addItemToPoll(()=>e.isFencePassed(),()=>t())})}pollItems(){let e=aU(this.itemsToPoll.map(t=>t.isDoneFn));for(let t=0;t<=e;++t){let{resolveFn:a}=this.itemsToPoll[t];a()}this.itemsToPoll=this.itemsToPoll.slice(e+1)}addItemToPoll(e,t){if(this.itemsToPoll.push({isDoneFn:e,resolveFn:t}),this.itemsToPoll.length>1)return;let a;\"setTimeoutCustom\"in W().platform&&(a=W().platform.setTimeoutCustom.bind(W().platform)),v.repeatedTry(()=>(this.pollItems(),this.itemsToPoll.length===0),()=>0,null,a)}bindTextureToFrameBuffer(e){this.throwIfDisposed(),xc(this.gl,e,this.framebuffer),this.debug&&Xu(this.gl)}unbindTextureToFrameBuffer(){this.outputTexture!=null?(xc(this.gl,this.outputTexture,this.framebuffer),this.debug&&Xu(this.gl)):k1(this.gl,this.framebuffer)}downloadMatrixDriver(e,t){this.bindTextureToFrameBuffer(e);let a=t();return this.unbindTextureToFrameBuffer(),a}setOutputMatrixTextureDriver(e,t,a){this.throwIfDisposed();let n=this.gl;xc(n,e,this.framebuffer),this.debug&&Xu(n),this.outputTexture=e,le(n,()=>n.viewport(0,0,t,a)),le(n,()=>n.scissor(0,0,t,a))}setOutputMatrixWriteRegionDriver(e,t,a,n){this.throwIfDisposed(),le(this.gl,()=>this.gl.scissor(e,t,a,n))}throwIfDisposed(){if(this.disposed)throw new Error(\"Attempted to use disposed GPGPUContext.\")}throwIfNoProgram(){if(this.program==null)throw new Error(\"No GPU program is currently set.\")}};function aU(e){let t=0;for(;t<e.length&&e[t]();++t);return t-1}var{addImpl:nU,bincountImpl:L6,bincountReduceImpl:rU,castImpl:sU,ceilImpl:iU,concatImpl:oU,equalImpl:lU,expImpl:uU,expm1Impl:dU,floorImpl:pU,gatherNdImpl:cU,gatherV2Impl:hU,greaterImpl:fU,greaterEqualImpl:mU,lessImpl:gU,lessEqualImpl:xU,linSpaceImpl:AU,logImpl:yU,maxImpl:bU,maximumImpl:vU,minimumImpl:wU,multiplyImpl:kU,negImpl:IU,notEqualImpl:SU,prodImpl:TU,raggedGatherImpl:CU,raggedRangeImpl:NU,raggedTensorToTensorImpl:EU,rangeImpl:RU,rsqrtImpl:MU,scatterImpl:$U,sigmoidImpl:_U,simpleAbsImpl:B6,sliceImpl:PU,sparseFillEmptyRowsImpl:FU,sparseReshapeImpl:OU,sparseSegmentReductionImpl:W6,sqrtImpl:DU,stridedSliceImpl:zU,stringNGramsImpl:LU,stringSplitImpl:BU,stringToHashBucketFastImpl:WU,subImpl:VU,tileImpl:UU,topKImpl:GU,transposeImpl:E3,uniqueImpl:HU}=_h;function V6(e,t){return[\"x\",\"y\",\"z\",\"w\",\"u\",\"v\"].slice(0,t).map(a=>`${e}.${a}`)}function va(e,t){return t===1?[e]:V6(e,t)}function jU(e,t){if(e===1)return\"rc\";let a=\"\";for(let n=0;n<e;n++)a+=t[n],n<e-1&&(a+=\",\");return a}var qU=class{constructor(e){if(this.variableNames=[\"A\"],this.packedInputs=!1,this.packedOutput=!0,this.outputShape=e,this.rank=e.length,this.enableShapeUniforms=Na(this.outputShape.length),this.rank===0)this.userCode=`\n        void main() {\n          setOutput(vec4(getA(), 0., 0., 0.));\n        }\n      `;else{let t=va(\"rc\",this.rank),a=gt(this.rank),n=this.getOutOfBoundsCondition(t),r=this.getSetup(t),s=this.getOutput(t);this.userCode=`\n        void main() {\n          ${a} rc = getOutputCoords();\n\n          if(${n}) {\n            setOutput(vec4(0));\n          } else {\n            ${r}\n\n            setOutput(vec4(${s}));\n          }\n        }\n      `}}getSourceCoordsArr(e){let t=[];for(let a=0;a<=1;a++)for(let n=0;n<=1;n++){let r=`${a===0?\"r\":\"rp1\"}, ${n===0?\"c\":\"cp1\"}`;for(let s=2;s<this.rank;s++)r=`${e[e.length-1-s]},`+r;t.push(r)}return t}getOutOfBoundsCondition(e){if(this.rank===1)return`rc > ${this.enableShapeUniforms?\"outShape\":this.outputShape[0]}`;let t=\"\";for(let a=this.rank-2;a<this.rank;a++)t+=`${e[a]} >= ${this.enableShapeUniforms?`outShape[${a}]`:this.outputShape[a]}`,a<this.rank-1&&(t+=\"||\");return t}getSetup(e){if(this.rank===1)return\"\";let t=e.slice(-2),a=this.enableShapeUniforms?`outShape[${this.rank} - 1]`:this.outputShape[this.rank-1],n=this.enableShapeUniforms?`outShape[${this.rank} - 2]`:this.outputShape[this.rank-2];return`\n      int r = ${t[0]};\n      int c = ${t[1]};\n      int rp1 = r + 1;\n      int cp1 = c + 1;\n\n      bool cEdge = cp1 >= ${a};\n      bool rEdge = rp1 >= ${n};\n    `}getOutput(e){let t=this.getSourceCoordsArr(e);return this.rank===1?`getA(rc), (rc + 1 >= ${this.enableShapeUniforms?\"outShape\":this.outputShape[0]} ? 0. : getA(rc + 1)), 0, 0`:`getA(${t[0]}),\n            cEdge ? 0. : getA(${t[1]}),\n            rEdge ? 0. : getA(${t[2]}),\n            rEdge || cEdge ? 0. : getA(${t[3]})`}},U6=class{constructor(e,t){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0,this.customUniforms=[{name:\"inputShape\",type:\"ivec3\"}],this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length);let a=\"\";for(let n=0;n<4;n++){let r=\"thisRC = rc;\";n%2===1&&(r+=\"thisRC.z += 1;\"),n>1&&(r+=\"thisRC.y += 1;\"),a+=`\n        ${r}\n        ${n>0?\"if(thisRC.y < rows && thisRC.z < cols){\":\"\"}\n          int flatIndex = getFlatIndex(thisRC);\n\n          ivec3 inputRC = inputCoordsFromReshapedOutCoords(flatIndex);\n          vec2 inputRCInnerDims = vec2(float(inputRC.y),float(inputRC.z));\n\n          result[${n}] =\n            getChannel(getA(inputRC.x, inputRC.y, inputRC.z), inputRCInnerDims);\n        ${n>0?\"}\":\"\"}\n      `}this.userCode=`\n      ${XU(t,this.enableShapeUniforms)}\n      ${this.enableShapeUniforms?w3():v3(e)}\n\n      void main() {\n        ivec3 rc = getOutputCoords();\n\n        vec4 result = vec4(0.);\n\n        ivec3 thisRC;\n        int rows = ${this.enableShapeUniforms?\"outShape[1]\":e[1]};\n        int cols = ${this.enableShapeUniforms?\"outShape[2]\":e[2]};\n\n        ${a}\n\n        setOutput(result);\n      }\n    `}};function XU(e,t){return`\n    ivec3 inputCoordsFromReshapedOutCoords(int index) {\n      ${t?dV([\"r\",\"c\",\"d\"],\"inputShape\"):Ao([\"r\",\"c\",\"d\"],e)}\n      return ivec3(r, c, d);\n    }\n  `}var KU=class{constructor(e){this.gpgpu=e,this.numUsedTextures=0,this.numFreeTextures=0,this._numBytesAllocated=0,this._numBytesFree=0,this.freeTextures={},this.logEnabled=!1,this.usedTextures={}}acquireTexture(e,t,a){let n=mx(t,a),r=gx(e,n,a);r in this.freeTextures||(this.freeTextures[r]=[]),r in this.usedTextures||(this.usedTextures[r]=[]);let s=fx(e,n,this.gpgpu.gl,this.gpgpu.textureConfig,a);if(this.freeTextures[r].length>0){this.numFreeTextures--,this.numUsedTextures++,this._numBytesFree-=s,this.log();let o=this.freeTextures[r].shift();return this.usedTextures[r].push(o),o}let i;return n===na.PACKED_2X2_FLOAT32?i=this.gpgpu.createPackedMatrixTexture(e[0],e[1]):n===na.PACKED_2X2_FLOAT16?i=this.gpgpu.createFloat16PackedMatrixTexture(e[0],e[1]):n===na.UNPACKED_FLOAT32?i=this.gpgpu.createFloat32MatrixTexture(e[0],e[1]):n===na.UNPACKED_FLOAT16?i=this.gpgpu.createFloat16MatrixTexture(e[0],e[1]):n===na.PACKED_4X1_UNSIGNED_BYTE&&(i=this.gpgpu.createUnsignedBytesMatrixTexture(e[0],e[1])),this.usedTextures[r].push(i),this.numUsedTextures++,this._numBytesAllocated+=s,this.log(),i}releaseTexture(e,t,a,n){if(this.freeTextures==null)return;let r=mx(a,n),s=gx(t,r,n);s in this.freeTextures||(this.freeTextures[s]=[]);let i=fx(t,r,this.gpgpu.gl,this.gpgpu.textureConfig,n),o=W().get(\"WEBGL_DELETE_TEXTURE_THRESHOLD\");o!==-1&&this._numBytesAllocated>o?(this.gpgpu.deleteMatrixTexture(e.texture),this._numBytesAllocated-=i):(this.freeTextures[s].push(e),this.numFreeTextures++,this._numBytesFree+=i),this.numUsedTextures--;let l=this.usedTextures[s],u=l.indexOf(e);if(u<0)throw new Error(\"Cannot release a texture that was never provided by this texture manager\");l.splice(u,1),this.log()}log(){if(!this.logEnabled)return;let e=this.numFreeTextures+this.numUsedTextures;console.log(\"Free/Used\",`${this.numFreeTextures} / ${this.numUsedTextures}`,`(${e})`);let t=this._numBytesFree/this._numBytesAllocated;console.log(`Bytes allocated: ${this._numBytesAllocated}`),console.log(`Bytes unused: ${this._numBytesFree} (${Math.round(100*t)}%)`)}get numBytesAllocated(){return this._numBytesAllocated}get numBytesFree(){return this._numBytesFree}getNumUsedTextures(){return this.numUsedTextures}getNumFreeTextures(){return this.numFreeTextures}dispose(){if(this.freeTextures!=null){for(let e in this.freeTextures)this.freeTextures[e].forEach(t=>{this.gpgpu.deleteMatrixTexture(t.texture)});for(let e in this.usedTextures)this.usedTextures[e].forEach(t=>{this.gpgpu.deleteMatrixTexture(t.texture)});this.freeTextures=null,this.usedTextures=null,this.numUsedTextures=0,this.numFreeTextures=0,this._numBytesAllocated=0,this._numBytesFree=0}}};function ZU(e,t){let a=e;if(t===a.R32F)return 4;if(t===a.R16F)return 2;if(t===a.RGBA32F||t===e.RGBA)return 16;if(t===a.RGBA16F)return 8;if(t===a.RGBA8)return 4;throw new Error(`Unknown internal format ${t}`)}function fx(e,t,a,n,r){let s=YU(t,n),i;if(r){let[l,u]=lu(e[0],e[1]);i=l*u}else{let[l,u]=up(e[0],e[1]);i=l*u}let o=ZU(a,s);return i*o}function YU(e,t){switch(e){case na.PACKED_2X2_FLOAT32:return C3(t);case na.PACKED_2X2_FLOAT16:return N3(t);case na.UNPACKED_FLOAT32:return I3(t);case na.UNPACKED_FLOAT16:return S3(t);case na.PACKED_4X1_UNSIGNED_BYTE:return T3(t);default:throw new Error(`Unknown physical texture type ${e}`)}}function JU(e){return W().getBool(\"WEBGL_RENDER_FLOAT32_ENABLED\")?e?na.PACKED_2X2_FLOAT32:na.UNPACKED_FLOAT32:e?na.PACKED_2X2_FLOAT16:na.UNPACKED_FLOAT16}function mx(e,t){if(e===pn.UPLOAD)return na.PACKED_2X2_FLOAT32;if(e===pn.RENDER||e==null)return JU(t);if(e===pn.DOWNLOAD||e===pn.PIXELS)return na.PACKED_4X1_UNSIGNED_BYTE;throw new Error(`Unknown logical texture type ${e}`)}function gx(e,t,a){return`${e[0]}_${e[1]}_${t}_${a}`}var qn=class{constructor(e,t){this.variableNames=[\"A\"],this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length),this.userCode=`\n      float unaryOperation(float x) {\n        ${t}\n      }\n\n      void main() {\n        float x = getAAtOutCoords();\n        float y = unaryOperation(x);\n\n        setOutput(y);\n      }\n    `}},Cn=\"if (isnan(x)) return x;\",QU=\"return x;\",xx=\"return abs(x);\",eG=\"return (x >= 0.0) ? x : (exp(x) - 1.0);\",tG=Cn+`\n  return (x < 0.0) ? 0.0 : x;\n`,aG=Cn+`\n  return (x < 0.0) ? 0.0 : min(6.0, x);\n`,Dr=\"return x;\",nG=\"return 1.0 / (1.0 + exp(-1.0 * x));\",rG=\"return x;\",sG=`\n  vec4 result;\n\n  result.r = (x.r >= 0.0) ? x.r : (exp(x.r) - 1.0);\n  result.g = (x.g >= 0.0) ? x.g : (exp(x.g) - 1.0);\n  result.b = (x.b >= 0.0) ? x.b : (exp(x.b) - 1.0);\n  result.a = (x.a >= 0.0) ? x.a : (exp(x.a) - 1.0);\n\n  return result;\n`,iG=`\n  vec4 result = x * vec4(greaterThanEqual(x, vec4(0.0)));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n`,oG=`\n  vec4 result = min(x, vec4(6.)) * vec4(greaterThanEqual(x, vec4(0.0)));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n`,lG=\"return 1.0 / (1.0 + exp(-1.0 * x));\",Vr=class{constructor(e,t){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length),this.userCode=`\n      vec4 unaryOperation(vec4 x) {\n        ${t}\n      }\n\n      void main() {\n        vec4 x = getAAtOutCoords();\n        vec4 y = unaryOperation(x);\n\n        setOutput(y);\n      }\n    `}},uG=class{constructor(e){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!1,this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length);let t=e.length,a=va(\"rc\",t),n=gt(t),r=jU(t,a),s=a.slice(-2),i=t<=1?\"rc\":`vec2(${s.join(\",\")})`;this.userCode=`\n      void main() {\n        ${n} rc = getOutputCoords();\n        vec4 packedInput = getA(${r});\n\n        setOutput(getChannel(packedInput, ${i}));\n      }\n    `}},dG=Tn.whereImpl,pG=1e-7,cG=1e-4,zm={};function hG(e){return e in zm||(zm[e]={}),zm[e]}var fG=W().getNumber(\"CPU_HANDOFF_SIZE_THRESHOLD\"),mG=600;function gG(){return W().global.screen==null?1024:W().global.screen.height*W().global.screen.width*window.devicePixelRatio*mG/1024/1024}var fu=class extends bl{constructor(e){if(super(),this.pendingRead=new WeakMap,this.pendingDisposal=new WeakSet,this.dataRefCount=new WeakMap,this.numBytesInGPU=0,this.uploadWaitMs=0,this.downloadWaitMs=0,this.lastGlFlushTime=0,this.warnedAboutMemory=!1,this.pendingDeletes=0,this.disposed=!1,!W().getBool(\"HAS_WEBGL\"))throw new Error(\"WebGL is not supported on this device\");let t;if(e!=null){if(e instanceof il)t=e;else{let a=Dn(W().getNumber(\"WEBGL_VERSION\"),e);t=new il(a)}this.binaryCache={},this.gpgpuCreatedLocally=!1}else{let a=Dn(W().getNumber(\"WEBGL_VERSION\"));t=new il(a),this.binaryCache=hG(W().getNumber(\"WEBGL_VERSION\")),this.gpgpuCreatedLocally=!0}this.gpgpu=t,this.canvas=this.gpgpu.gl.canvas,this.textureManager=new KU(this.gpgpu),this.numMBBeforeWarning=gG(),this.texData=new vd(this,kt())}nextDataId(){return fu.nextDataId++}numDataIds(){return this.texData.numDataIds()-this.pendingDeletes}writeTexture(e,t,a,n,r,s){let i=this.makeTensorInfo(t,a),o=this.texData.get(i.dataId);o.isPacked=!1,o.texture={texture:e,texShape:[n,r]},o.texShape=[n,r];let l=Ku(t),u=new hx(l,!1,s),p=this.runWebGLProgram(u,[i],a,[[n,r]]);return p.shape=t,o.texture=null,this.disposeIntermediateTensorInfo(i),p.dataId}write(e,t,a){if((W().getBool(\"WEBGL_CHECK_NUMERICAL_PROBLEMS\")||W().getBool(\"DEBUG\"))&&this.checkNumericalProblems(e),a===\"complex64\"&&e!=null)throw new Error(\"Cannot write to a complex64 dtype. Please use tf.complex(real, imag).\");let n={id:this.nextDataId()};return this.texData.set(n,{shape:t,dtype:a,values:e,usage:pn.UPLOAD,refCount:1}),n}refCount(e){return this.texData.has(e)?this.texData.get(e).refCount:0}incRef(e){let t=this.texData.get(e);t.refCount++}decRef(e){if(this.texData.has(e)){let t=this.texData.get(e);t.refCount--}}move(e,t,a,n,r){if(W().getBool(\"DEBUG\")&&this.checkNumericalProblems(t),n===\"complex64\")throw new Error(\"Cannot write to a complex64 dtype. Please use tf.complex(real, imag).\");this.texData.set(e,{shape:a,dtype:n,values:t,usage:pn.UPLOAD,refCount:r})}disposeIntermediateTensorInfo(e){this.disposeData(e.dataId)}readSync(e){let t=this.texData.get(e),{values:a,dtype:n,complexTensorInfos:r,slice:s,shape:i,isPacked:o}=t;if(s!=null){let c;o?c=new Vr(i,Dr):c=new qn(i,Dr);let d=this.runWebGLProgram(c,[{dataId:e,shape:i,dtype:n}],n),h=this.readSync(d.dataId);return this.disposeIntermediateTensorInfo(d),h}if(a!=null)return this.convertAndCacheOnCPU(e);if(n===\"string\")return a;let l=this.activeTimers!=null,u;l&&(u=v.now());let p;if(n===\"complex64\"){let c=this.readSync(r.real.dataId),d=this.readSync(r.imag.dataId);p=T.mergeRealAndImagArrays(c,d)}else p=this.getValuesFromTexture(e);return l&&(this.downloadWaitMs+=v.now()-u),this.convertAndCacheOnCPU(e,p)}async read(e){if(this.pendingRead.has(e)){let h=this.pendingRead.get(e);return new Promise(f=>h.push(f))}let t=this.texData.get(e),{values:a,shape:n,slice:r,dtype:s,complexTensorInfos:i,isPacked:o}=t;if(r!=null){let h;o?h=new Vr(n,Dr):h=new qn(n,Dr);let f=this.runWebGLProgram(h,[{dataId:e,shape:n,dtype:s}],s),m=this.read(f.dataId);return this.disposeIntermediateTensorInfo(f),m}if(a!=null)return this.convertAndCacheOnCPU(e);if(W().getBool(\"DEBUG\")&&!W().getBool(\"WEBGL_DOWNLOAD_FLOAT_ENABLED\")&&W().getNumber(\"WEBGL_VERSION\")===2)throw new Error(\"tensor.data() with WEBGL_DOWNLOAD_FLOAT_ENABLED=false and WEBGL_VERSION=2 not yet supported.\");let l=null,u;if(s!==\"complex64\"&&W().get(\"WEBGL_BUFFER_SUPPORTED\")){u=this.decode(e);let h=this.texData.get(u.dataId);l=this.gpgpu.createBufferFromTexture(h.texture.texture,...uc(n))}this.pendingRead.set(e,[]),s!==\"complex64\"&&await this.gpgpu.createAndWaitForFence();let p;if(s===\"complex64\"){let h=await Promise.all([this.read(i.real.dataId),this.read(i.imag.dataId)]),f=h[0],m=h[1];p=T.mergeRealAndImagArrays(f,m)}else if(l==null)p=this.getValuesFromTexture(e);else{let h=v.sizeFromShape(n);p=this.gpgpu.downloadFloat32MatrixFromBuffer(l,h)}if(u!=null&&this.disposeIntermediateTensorInfo(u),l!=null){let h=this.gpgpu.gl;le(h,()=>h.deleteBuffer(l))}let c=this.convertAndCacheOnCPU(e,p),d=this.pendingRead.get(e);return this.pendingRead.delete(e),d.forEach(h=>h(c)),this.pendingDisposal.has(e)&&(this.pendingDisposal.delete(e),this.disposeData(e)&&kt().removeDataId(e,this),this.pendingDeletes--),c}readToGPU(e,t={}){let a=this.texData.get(e),{values:n,shape:r,slice:s,dtype:i,isPacked:o,texture:l}=a;if(i===\"complex64\")throw new Error(\"Does not support reading texture for complex64 dtype.\");if(s!=null){let d;o?d=new Vr(r,Dr):d=new qn(r,Dr);let h=this.runWebGLProgram(d,[{dataId:e,shape:r,dtype:i}],i),f=this.readToGPU(h,t);return this.disposeIntermediateTensorInfo(h),f}if(l==null)throw n!=null?new Error(\"Data is not on GPU but on CPU.\"):new Error(\"There is no data on GPU or CPU.\");let u=this.decode(e,t.customTexShape),p=kt().makeTensorFromTensorInfo(u),c=this.texData.get(u.dataId);return Object.assign({tensorRef:p},c.texture)}bufferSync(e){let t=this.readSync(e.dataId);if(e.dtype===\"string\")try{let a=t.map(n=>v.decodeString(n));return Me(e.shape,e.dtype,a)}catch(a){throw new Error(\"Failed to decode encoded string bytes into utf-8\")}return Me(e.shape,e.dtype,t)}checkNumericalProblems(e){if(e!=null)for(let t=0;t<e.length;t++){let a=e[t];if(!q7(a))throw W().getBool(\"WEBGL_RENDER_FLOAT32_CAPABLE\")?Error(`The value ${a} cannot be represented with your current settings. Consider enabling float32 rendering: 'tf.env().set('WEBGL_RENDER_FLOAT32_ENABLED', true);'`):Error(`The value ${a} cannot be represented on this device.`)}}getValuesFromTexture(e){let{shape:t,dtype:a,isPacked:n}=this.texData.get(e),r=v.sizeFromShape(t);if(W().getBool(\"WEBGL_DOWNLOAD_FLOAT_ENABLED\")){let c=this.decode(e),d=this.texData.get(c.dataId),h=this.gpgpu.downloadMatrixFromPackedTexture(d.texture.texture,...uc(t)).subarray(0,r);return this.disposeIntermediateTensorInfo(c),h}let s=W().getBool(\"WEBGL_PACK\")&&n===!0,i=s?Ku(t):t,o=s?new QV(i):new JV(i),l=this.runWebGLProgram(o,[{shape:i,dtype:a,dataId:e}],\"float32\"),u=this.texData.get(l.dataId),p=this.gpgpu.downloadByteEncodedFloatMatrixFromOutputTexture(u.texture.texture,u.texShape[0],u.texShape[1]).subarray(0,r);return this.disposeIntermediateTensorInfo(l),p}timerAvailable(){return W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE\")>0}time(e){let t=this.activeTimers,a=[],n=!1;this.programTimersStack==null?(this.programTimersStack=a,n=!0):this.activeTimers.push(a),this.activeTimers=a,e();let r=v.flatten(this.activeTimers.map(o=>o.query)).filter(o=>o!=null),s=v.flatten(this.activeTimers.map(o=>o.name)).filter(o=>o!=null);this.activeTimers=t,n&&(this.programTimersStack=null);let i={uploadWaitMs:this.uploadWaitMs,downloadWaitMs:this.downloadWaitMs,kernelMs:null,wallMs:null};return(async()=>{if(W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE\")>0){let o=await Promise.all(r);i.kernelMs=v.sum(o),i.getExtraProfileInfo=()=>o.map((l,u)=>({name:s[u],ms:l})).map(l=>`${l.name}: ${l.ms}`).join(\", \")}else i.kernelMs={error:\"WebGL query timers are not supported in this environment.\"};return this.uploadWaitMs=0,this.downloadWaitMs=0,i})()}memory(){return{unreliable:!1,numBytesInGPU:this.numBytesInGPU,numBytesInGPUAllocated:this.textureManager.numBytesAllocated,numBytesInGPUFree:this.textureManager.numBytesFree}}startTimer(){return W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE\")>0?this.gpgpu.beginQuery():{startMs:v.now(),endMs:null}}endTimer(e){return W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE\")>0?(this.gpgpu.endQuery(),e):(e.endMs=v.now(),e)}async getQueryTime(e){if(W().getNumber(\"WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE\")>0)return this.gpgpu.waitForQueryAndGetTime(e);let t=e;return t.endMs-t.startMs}disposeData(e,t=!1){if(this.pendingDisposal.has(e))return!1;if(!this.texData.has(e))return!0;if(t?this.texData.get(e).refCount=0:this.texData.get(e).refCount--,!t&&this.texData.get(e).refCount>0)return!1;if(this.pendingRead.has(e))return this.pendingDisposal.add(e),this.pendingDeletes++,!1;this.releaseGPUData(e);let{complexTensorInfos:a}=this.texData.get(e);return a!=null&&(this.disposeData(a.real.dataId,t),this.disposeData(a.imag.dataId,t)),this.texData.delete(e),!0}releaseGPUData(e){let{texture:t,dtype:a,texShape:n,usage:r,isPacked:s,slice:i}=this.texData.get(e),o=i&&i.origDataId||e,l=this.dataRefCount.get(o);l>1?this.dataRefCount.set(o,l-1):(this.dataRefCount.delete(o),t!=null&&(this.numBytesInGPU-=this.computeBytes(n,a),this.textureManager.releaseTexture(t,n,r,s)));let u=this.texData.get(e);u.texture=null,u.texShape=null,u.isPacked=!1,u.slice=null}getTexture(e){return this.uploadToGPU(e),this.texData.get(e).texture.texture}getDataInfo(e){return this.texData.get(e)}shouldExecuteOnCPU(e,t=fG){return W().getBool(\"WEBGL_CPU_FORWARD\")&&e.every(a=>this.texData.get(a.dataId).texture==null&&v.sizeFromShape(a.shape)<t)}getGPGPUContext(){return this.gpgpu}where(e){T.warn(\"tf.where() in webgl locks the UI thread. Call tf.whereAsync() instead\");let t=e.dataSync();return dG(e.shape,t)}packedUnaryOp(e,t,a){let n=new Vr(e.shape,t),r=this.compileAndRun(n,[e],a);return kt().makeTensorFromTensorInfo(r)}abs(e){if(this.shouldExecuteOnCPU([e])&&e.dtype!==\"complex64\"){let n=B6(this.texData.get(e.dataId).values);return this.makeOutput(e.shape,e.dtype,n)}if(W().getBool(\"WEBGL_PACK_UNARY_OPERATIONS\"))return this.packedUnaryOp(e,xx,e.dtype);let t=new qn(e.shape,xx),a=this.compileAndRun(t,[e]);return kt().makeTensorFromTensorInfo(a)}makeTensorInfo(e,t,a){let n;if(t===\"string\"&&a!=null&&a.length>0&&v.isString(a[0])){let r=a.map(s=>v.encodeString(s));n=this.write(r,e,t)}else n=this.write(a,e,t);return this.texData.get(n).usage=null,{dataId:n,shape:e,dtype:t}}makeOutput(e,t,a){return kt().makeTensorFromTensorInfo(this.makeTensorInfo(e,t,a),this)}unpackTensor(e){let t=new uG(e.shape);return this.runWebGLProgram(t,[e],e.dtype)}packTensor(e){let t=new qU(e.shape),a=!0;return this.runWebGLProgram(t,[e],e.dtype,null,a)}packedReshape(e,t){let a=[Hs(e.shape),...js(e.shape)],n={dtype:e.dtype,shape:a,dataId:e.dataId},r=[Hs(t),...js(t)],s=new U6(r,a),i=!0,o=[a],l=this.runWebGLProgram(s,[n],e.dtype,o,i);return{dataId:l.dataId,shape:t,dtype:l.dtype}}decode(e,t){let a=this.texData.get(e),{isPacked:n,shape:r,dtype:s}=a;if(t!=null){let c=v.sizeFromShape(r),d=t[0]*t[1]*4;v.assert(c<=d,()=>\"customTexShape is too small. Row * Column * 4 should be equal or larger than the size of the tensor data.\")}let i=Ku(r),o;n?o=new YV(i):o=new ZV(i);let l=!0,u=[t!=null?t:uc(i)],p=this.runWebGLProgram(o,[{shape:i,dtype:s,dataId:e}],s,u,l,t);return{dtype:s,shape:r,dataId:p.dataId}}runWebGLProgram(e,t,a,n,r=!1,s){let i=this.makeTensorInfo(e.outputShape,a),o=this.texData.get(i.dataId);if(e.packedOutput&&(o.isPacked=!0),e.outPackingScheme===fd.DENSE){let g=s!=null?s:uc(e.outputShape);o.texShape=g.map(x=>x*2)}if(e.outTexUsage!=null&&(o.usage=e.outTexUsage),v.sizeFromShape(i.shape)===0)return o.values=v.getTypedArrayFromDType(i.dtype,0),i;let l=[],u=t.map(g=>{if(g.dtype===\"complex64\")throw new Error(\"GPGPUProgram does not support complex64 input. For complex64 dtypes, please separate the program into real and imaginary parts.\");let x=this.texData.get(g.dataId);if(x.texture==null){if(!e.packedInputs&&v.sizeFromShape(g.shape)<=W().getNumber(\"WEBGL_SIZE_UPLOAD_UNIFORM\"))return{shape:g.shape,texData:null,isUniform:!0,uniformValues:x.values};e.packedInputs&&(x.isPacked=!0,x.shape=g.shape)}if(this.uploadToGPU(g.dataId),!!x.isPacked!=!!e.packedInputs)g=x.isPacked?this.unpackTensor(g):this.packTensor(g),l.push(g),x=this.texData.get(g.dataId);else if(x.isPacked&&!md(x.shape,g.shape)){let A=g,y=g.shape;g.shape=x.shape,g=this.packedReshape(g,y),l.push(g),x=this.texData.get(g.dataId),A.shape=y}return{shape:g.shape,texData:x,isUniform:!1}});this.uploadToGPU(i.dataId);let p={shape:i.shape,texData:o,isUniform:!1},c=KV(e,u,p),d=this.getAndSaveBinary(c,()=>qV(this.gpgpu,e,u,p)),h=this.activeTimers!=null,f;h&&(f=this.startTimer()),W().get(\"ENGINE_COMPILE_ONLY\")||XV(this.gpgpu,d,u,p,n),l.forEach(g=>this.disposeIntermediateTensorInfo(g)),h&&(f=this.endTimer(f),this.activeTimers.push({name:e.constructor.name,query:this.getQueryTime(f)}));let m=W().get(\"WEBGL_FLUSH_THRESHOLD\");if(m>0){let g=v.now();g-this.lastGlFlushTime>m&&(this.gpgpu.gl.flush(),this.lastGlFlushTime=g)}if(!W().getBool(\"WEBGL_LAZILY_UNPACK\")&&o.isPacked&&r===!1){let g=this.unpackTensor(i);return this.disposeIntermediateTensorInfo(i),g}return i}compileAndRun(e,t,a,n,r=!1){return a=a||t[0].dtype,this.runWebGLProgram(e,t,a,n,r)}getAndSaveBinary(e,t){return e in this.binaryCache||(this.binaryCache[e]=t()),this.binaryCache[e]}getTextureManager(){return this.textureManager}dispose(){this.disposed||(W().getBool(\"IS_TEST\")||Object.keys(this.binaryCache).forEach(e=>{this.gpgpu.deleteProgram(this.binaryCache[e].webGLProgram),delete this.binaryCache[e]}),this.textureManager.dispose(),this.canvas!=null&&typeof HTMLCanvasElement!=\"undefined\"&&this.canvas instanceof HTMLCanvasElement?this.canvas.remove():this.canvas=null,this.gpgpuCreatedLocally&&(this.gpgpu.program=null,this.gpgpu.dispose()),this.disposed=!0)}floatPrecision(){return this.floatPrecisionValue==null&&(this.floatPrecisionValue=$e(()=>{if(!W().get(\"WEBGL_RENDER_FLOAT32_ENABLED\")){let e=W().getBool(\"DEBUG\");W().set(\"DEBUG\",!1);let t=this.abs(Fe(1e-8)).dataSync()[0];if(W().set(\"DEBUG\",e),t>0)return 32}return 16})),this.floatPrecisionValue}epsilon(){return this.floatPrecision()===32?pG:cG}uploadToGPU(e){let t=this.texData.get(e),{shape:a,dtype:n,values:r,texture:s,usage:i,isPacked:o}=t;if(s!=null)return;let l=this.activeTimers!=null,u;l&&(u=v.now());let p=t.texShape;if(p==null&&(p=d6(a,o),t.texShape=p),r!=null){let c=Ku(a),d,h=p[1],f=p[0],m=r instanceof Uint8Array||r instanceof Uint8ClampedArray;(o||!m)&&([h,f]=lu(p[0],p[1])),o?d=new tU(c,m):d=new hx(c,m);let g=m?[f,h]:p,x=this.makeTensorInfo(g,n),A=this.texData.get(x.dataId);m?A.usage=pn.PIXELS:A.usage=pn.UPLOAD,A.texShape=g,this.gpgpu.uploadDenseMatrixToTexture(this.getTexture(x.dataId),h,f,r);let y=[[f,h]],b=!0,w=this.runWebGLProgram(d,[x],n,y,b),S=this.texData.get(w.dataId);t.texShape=S.texShape,t.isPacked=S.isPacked,t.usage=S.usage,W().get(\"ENGINE_COMPILE_ONLY\")?this.disposeData(w.dataId):(t.texture=S.texture,t.values=null,this.texData.delete(w.dataId)),this.disposeIntermediateTensorInfo(x),l&&(this.uploadWaitMs+=v.now()-u)}else{let c=this.acquireTexture(p,i,n,o);t.texture=c}}convertAndCacheOnCPU(e,t){let a=this.texData.get(e),{dtype:n}=a;return t!=null&&(a.values=xG(t,n)),a.values}acquireTexture(e,t,a,n){if(this.numBytesInGPU+=this.computeBytes(e,a),!this.warnedAboutMemory&&this.numBytesInGPU>this.numMBBeforeWarning*1024*1024){let r=(this.numBytesInGPU/1024/1024).toFixed(2);this.warnedAboutMemory=!0,console.warn(`High memory usage in GPU: ${r} MB, most likely due to a memory leak`)}return this.textureManager.acquireTexture(e,t,n)}computeBytes(e,t){return e[0]*e[1]*v.bytesPerElement(t)}checkCompileCompletion(){for(let[,e]of Object.entries(this.binaryCache))this.checkCompletion_(e)}async checkCompileCompletionAsync(){let e=[];if(this.gpgpu.parallelCompilationExtension){for(let[,t]of Object.entries(this.binaryCache))e.push(this.checkCompletionAsync_(t));return Promise.all(e)}else{for(let[,t]of Object.entries(this.binaryCache)){let a=new Promise(n=>{try{this.checkCompletion_(t),n(!0)}catch(r){throw r}});e.push(a)}return Promise.all(e)}}async checkCompletionAsync_(e){return this.gpgpu.gl.getProgramParameter(e.webGLProgram,this.gpgpu.parallelCompilationExtension.COMPLETION_STATUS_KHR)?this.checkCompletion_(e):(await b4(),this.checkCompletionAsync_(e))}checkCompletion_(e){if(this.gpgpu.gl.getProgramParameter(e.webGLProgram,this.gpgpu.gl.LINK_STATUS)===!1)throw console.log(this.gpgpu.gl.getProgramInfoLog(e.webGLProgram)),this.gpgpu.gl.getShaderParameter(e.fragmentShader,this.gpgpu.gl.COMPILE_STATUS)===!1?(b3(e.source,this.gpgpu.gl.getShaderInfoLog(e.fragmentShader)),new Error(\"Failed to compile fragment shader.\")):new Error(\"Failed to link vertex and fragment shaders.\");return!0}getUniformLocations(){for(let[,e]of Object.entries(this.binaryCache)){let{uniformLocations:t,customUniformLocations:a,infLoc:n,nanLoc:r,inShapesLocations:s,inTexShapesLocations:i,outShapeLocation:o,outShapeStridesLocation:l,outTexShapeLocation:u}=v6(this.gpgpu,e.program,e.webGLProgram);e.uniformLocations=t,e.customUniformLocations=a,e.infLoc=n,e.nanLoc=r,e.inShapesLocations=s,e.inTexShapesLocations=i,e.outShapeLocation=o,e.outShapeStridesLocation=l,e.outTexShapeLocation=u}}createTensorFromTexture(e,t,a){let{texture:n,height:r,width:s,channels:i}=e,o=kt().backend;if(!o.gpgpu.gl.isTexture(n))throw new Error(\"The texture is invalid. Also, please make sure the texture and the TFJS WebGL backend are using the same canvas. If you want to use your own custom canvas, you have to create and use the custom TFJS WebGL backend created from the canvas through 'new tf.MathBackendWebGL(customCanvas)'.\");let l=o.writeTexture(n,t,a,r,s,i);return kt().makeTensorFromDataId(l,t,a,o)}};fu.nextDataId=0;function xG(e,t){if(t===\"float32\"||t===\"complex64\")return e;if(t===\"int32\"||t===\"bool\"){let a=t===\"int32\"?new Int32Array(e.length):new Uint8Array(e.length);for(let n=0;n<a.length;++n)a[n]=Math.round(e[n]);return a}else throw new Error(`Unknown dtype ${t}`)}var AG=\"4.1.0\";function G6(){W().set(\"WEBGL_FORCE_F16_TEXTURES\",!0)}jd.isBrowser()&&go(\"webgl\",()=>new fu,2);var yG={forceHalfFloat:G6},R3=`\n  if (isnan(a)) return a;\n  if (isnan(b)) return b;\n`,Al=class{constructor(e,t,a){this.variableNames=[\"A\",\"B\"],this.outputShape=T.assertAndGetBroadcastShape(t,a),this.enableShapeUniforms=Na(this.outputShape.length),this.userCode=`\n      float binaryOperation(float a, float b) {\n        ${e}\n      }\n\n      void main() {\n        float a = getAAtOutCoords();\n        float b = getBAtOutCoords();\n        setOutput(binaryOperation(a, b));\n      }\n    `}},pp=`\n  result.r = isNaN.r ? NAN : result.r;\n  result.g = isNaN.g ? NAN : result.g;\n  result.b = isNaN.b ? NAN : result.b;\n  result.a = isNaN.a ? NAN : result.a;\n`,cp=class{constructor(e,t,a,n=!1){this.variableNames=[\"A\",\"B\"],this.supportsBroadcasting=!0,this.packedInputs=!0,this.packedOutput=!0,this.outputShape=T.assertAndGetBroadcastShape(t,a);let r=this.outputShape.length;this.enableShapeUniforms=Na(r);let s=\"\";if(n)if(r===0||v.sizeFromShape(this.outputShape)===1)s=`\n          result.y = 0.;\n          result.z = 0.;\n          result.w = 0.;\n        `;else if(s=`\n          ${gt(r)} coords = getOutputCoords();\n        `,r===1)this.enableShapeUniforms?s+=`\n            result.y = (coords + 1) >= outShape ? 0. : result.y;\n            result.z = 0.;\n            result.w = 0.;\n          `:s+=`\n            result.y = (coords + 1) >= ${this.outputShape[0]} ? 0. : result.y;\n            result.z = 0.;\n            result.w = 0.;\n          `;else{let i=va(\"coords\",r);this.enableShapeUniforms?s+=`\n            bool nextRowOutOfBounds =\n              (${i[r-2]} + 1) >= outShape[${r} - 2];\n            bool nextColOutOfBounds =\n              (${i[r-1]} + 1) >= outShape[${r} - 1];\n            result.y = nextColOutOfBounds ? 0. : result.y;\n            result.z = nextRowOutOfBounds ? 0. : result.z;\n            result.w = nextColOutOfBounds || nextRowOutOfBounds ? 0. : result.w;\n          `:s+=`\n            bool nextRowOutOfBounds =\n              (${i[r-2]} + 1) >= ${this.outputShape[r-2]};\n            bool nextColOutOfBounds =\n              (${i[r-1]} + 1) >= ${this.outputShape[r-1]};\n            result.y = nextColOutOfBounds ? 0. : result.y;\n            result.z = nextRowOutOfBounds ? 0. : result.z;\n            result.w = nextColOutOfBounds || nextRowOutOfBounds ? 0. : result.w;\n          `}this.userCode=`\n      vec4 binaryOperation(vec4 a, vec4 b) {\n        ${e}\n      }\n\n      void main() {\n        vec4 a = getAAtOutCoords();\n        vec4 b = getBAtOutCoords();\n\n        vec4 result = binaryOperation(a, b);\n        ${s}\n\n        setOutput(result);\n      }\n    `}};function Za(e){let{inputs:t,backend:a}=e,{x:n}=t;return a.incRef(n.dataId),{dataId:n.dataId,shape:n.shape,dtype:n.dtype}}var bG={kernelName:ki,backendName:\"webgl\",kernelFunc:Za};function ls(e){let{inputs:t,backend:a}=e,{real:n,imag:r}=t,s=a.makeTensorInfo(n.shape,\"complex64\"),i=a.texData.get(s.dataId),o=Za({inputs:{x:n},backend:a}),l=Za({inputs:{x:r},backend:a});return i.complexTensorInfos={real:o,imag:l},s}var vG={kernelName:Sd,backendName:\"webgl\",kernelFunc:ls},H6=\"return (a < 0.) ? b * a : a;\",j6=`\n  vec4 aLessThanZero = vec4(lessThan(a, vec4(0.)));\n  return (aLessThanZero * (b * a)) + ((vec4(1.0) - aLessThanZero) * a);\n`;function wG(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{alpha:s}=n,i=a.makeTensorInfo([],\"float32\",v.createScalarValue(s,\"float32\")),o=W().getBool(\"WEBGL_PACK_BINARY_OPERATIONS\")?new cp(j6,r.shape,i.shape):new Al(H6,r.shape,i.shape),l=a.runWebGLProgram(o,[r,i],\"float32\");return a.disposeIntermediateTensorInfo(i),l}var kG={kernelName:Si,backendName:\"webgl\",kernelFunc:wG},q6=\"return (a < 0.) ? b * a : a;\",X6=`\n  vec4 aLessThanZero = vec4(lessThan(a, vec4(0.)));\n  return (aLessThanZero * (b * a)) + ((vec4(1.0) - aLessThanZero) * a);\n`;function IG(e){let{inputs:t,backend:a}=e,{x:n,alpha:r}=t,s=W().getBool(\"WEBGL_PACK_BINARY_OPERATIONS\")?new cp(X6,n.shape,r.shape):new Al(q6,n.shape,r.shape);return a.runWebGLProgram(s,[n,r],\"float32\")}var SG={kernelName:Hi,backendName:\"webgl\",kernelFunc:IG},mu=\"if (isnan(x)) return x;\";function Qe({opSnippet:e,packedOpSnippet:t,cpuKernelImpl:a,dtype:n}){return({inputs:r,backend:s})=>{let{x:i}=r,o=s,l=n||i.dtype;if(o.shouldExecuteOnCPU([i])&&a!=null){let c=o.texData.get(i.dataId),d=a(c.values,l);return o.makeTensorInfo(i.shape,l,d)}let u=W().getBool(\"WEBGL_PACK_UNARY_OPERATIONS\")&&t!=null,p;return u?p=new Vr(i.shape,t):p=new qn(i.shape,e),o.runWebGLProgram(p,[i],l)}}function oa({opSnippet:e,packedOpSnippet:t,checkOutOfBounds:a=!1,supportsComplex:n=!1,cpuKernelImpl:r,dtype:s}){return({inputs:i,backend:o})=>{let{a:l,b:u}=i,p=o;if(n&&l.dtype===\"complex64\"){let f=p.texData.get(l.dataId),m=p.texData.get(u.dataId),[g,x]=[[f.complexTensorInfos.real,m.complexTensorInfos.real],[f.complexTensorInfos.imag,m.complexTensorInfos.imag]].map(y=>{let[b,w]=y,S={dataId:b.dataId,dtype:b.dtype,shape:l.shape},C={dataId:w.dataId,dtype:w.dtype,shape:u.shape},E=new Al(e,l.shape,u.shape);return p.runWebGLProgram(E,[S,C],ca(b.dtype,w.dtype))}),A=ls({inputs:{real:g,imag:x},backend:p});return p.disposeIntermediateTensorInfo(g),p.disposeIntermediateTensorInfo(x),A}let c=s||ca(l.dtype,u.dtype);if((l.dtype===\"string\"||u.dtype===\"string\"||p.shouldExecuteOnCPU([l,u]))&&r!=null){let f=p.texData.get(l.dataId).values,m=p.texData.get(u.dataId).values,g=l.dtype===\"string\"?T.fromUint8ToStringArray(f):f,x=l.dtype===\"string\"?T.fromUint8ToStringArray(m):m,[A,y]=r(l.shape,u.shape,g,x,c),b=p.makeTensorInfo(y,c),w=p.texData.get(b.dataId);return w.values=A,b}let d=W().getBool(\"WEBGL_PACK_BINARY_OPERATIONS\")&&t!=null,h;return d?h=new cp(t,l.shape,u.shape,a):h=new Al(e,l.shape,u.shape),p.runWebGLProgram(h,[l,u],c)}}function gd(e,t=!1){if(e===\"linear\")return t?rG:QU;if(e===\"relu\")return t?iG:tG;if(e===\"elu\")return t?sG:eG;if(e===\"relu6\")return t?oG:aG;if(e===\"prelu\")return t?X6:q6;if(e===\"leakyrelu\")return t?j6:H6;if(e===\"sigmoid\")return t?lG:nG;throw new Error(`Activation ${e} has not been implemented for the WebGL backend.`)}var K6=class{constructor(e,t,a,n=!1,r=!1,s=!1,i=null,o=!1,l=!1){this.variableNames=[\"matrixA\",\"matrixB\"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=a,this.enableShapeUniforms=Na(this.outputShape.length);let u=n?e[1]:e[2],p=Math.ceil(u/2),c=n?\"i * 2, rc.y\":\"rc.y, i * 2\",d=r?\"rc.z, i * 2\":\"i * 2, rc.z\",h=n?[\"a.xxyy\",\"a.zzww\"]:[\"a.xxzz\",\"a.yyww\"],f=r?[\"b.xzxz\",\"b.ywyw\"]:[\"b.xyxy\",\"b.zwzw\"],m=\"\",g=\"\";i&&(o?m=`vec4 activation(vec4 a) {\n          vec4 b = getPreluActivationWeightsAtOutCoords();\n          ${i}\n        }`:l?m=`vec4 activation(vec4 a) {\n          vec4 b = getLeakyreluAlphaAtOutCoords();\n          ${i}\n        }`:m=`vec4 activation(vec4 x) {\n          ${i}\n        }`,g=\"result = activation(result);\");let x=s?\"result += getBiasAtOutCoords();\":\"\";s&&this.variableNames.push(\"bias\"),o&&this.variableNames.push(\"preluActivationWeights\"),l&&this.variableNames.push(\"leakyreluAlpha\");let A=\"rc.x\",y=\"rc.x\";e[0]<t[0]?A=`int(min(float(rc.x), ${e[0]-1}.))`:t[0]<e[0]&&(y=`int(min(float(rc.x), ${t[0]-1}.))`),this.userCode=`\n      ${m}\n      // Don't use uniform for sharedDimensionPacked for performance.\n      const float sharedDimension = ${p}.0;\n\n      vec4 dot2x2ARowBCol(ivec3 rc) {\n        vec4 result = vec4(0);\n        for (int i = 0; i < ${p}; i++) {\n          int batchA = ${A};\n          int batchB = ${y};\n          vec4 a = getMatrixA(batchA, ${c});\n          vec4 b = getMatrixB(batchB, ${d});\n\n          // These swizzled products need to be separately added.\n          // See: https://github.com/tensorflow/tfjs/issues/1735\n          result += (${h[0]} * ${f[0]});\n          result += (${h[1]} * ${f[1]});\n        }\n        return result;\n      }\n\n      void main() {\n        ivec3 rc = getOutputCoords();\n        vec4 result = dot2x2ARowBCol(rc);\n\n        ${x}\n\n        ${g}\n\n        setOutput(result);\n      }\n    `}},Ax={REAL:\"return areal * breal - aimag * bimag;\",IMAG:\"return areal * bimag + aimag * breal;\"},yx=class{constructor(e,t,a){this.variableNames=[\"AReal\",\"AImag\",\"BReal\",\"BImag\"],this.outputShape=T.assertAndGetBroadcastShape(t,a),this.userCode=`\n      float binaryOpComplex(\n          float areal, float aimag, float breal, float bimag) {\n        ${e}\n      }\n\n      void main() {\n        float areal = getARealAtOutCoords();\n        float aimag = getAImagAtOutCoords();\n        float breal = getBRealAtOutCoords();\n        float bimag = getBImagAtOutCoords();\n        setOutput(binaryOpComplex(areal, aimag, breal, bimag));\n      }\n    `}},bx=\"return a * b;\";function M3(e){let{inputs:t,backend:a}=e,{a:n,b:r}=t,s=T.upcastType(n.dtype,r.dtype);if(n.dtype===\"complex64\"){let o=a.texData.get(n.dataId),l=a.texData.get(r.dataId),u=new yx(Ax.REAL,n.shape,r.shape),p=new yx(Ax.IMAG,n.shape,r.shape),c=[{dataId:o.complexTensorInfos.real.dataId,dtype:o.complexTensorInfos.real.dtype,shape:n.shape},{dataId:o.complexTensorInfos.imag.dataId,dtype:o.complexTensorInfos.imag.dtype,shape:n.shape},{dataId:l.complexTensorInfos.real.dataId,dtype:l.complexTensorInfos.real.dtype,shape:r.shape},{dataId:l.complexTensorInfos.imag.dataId,dtype:l.complexTensorInfos.imag.dtype,shape:r.shape}],d=a.runWebGLProgram(u,c,\"float32\"),h=a.runWebGLProgram(p,c,\"float32\"),f=ls({inputs:{real:d,imag:h},backend:a});return a.disposeIntermediateTensorInfo(d),a.disposeIntermediateTensorInfo(h),f}if(a.shouldExecuteOnCPU([n,r])){let o=a.texData.get(n.dataId),l=a.texData.get(r.dataId),[u,p]=kU(n.shape,r.shape,o.values,l.values,s),c=a.makeTensorInfo(p,s),d=a.texData.get(c.dataId);return d.values=u,c}let i;return W().getBool(\"WEBGL_PACK_BINARY_OPERATIONS\")?i=new cp(bx,n.shape,r.shape):i=new Al(bx,n.shape,r.shape),a.runWebGLProgram(i,[n,r],s)}var TG={kernelName:zi,backendName:\"webgl\",kernelFunc:M3};function CG(e,t,a){let n=[Hs(e.shape),...js(e.shape)],r={dtype:e.dtype,shape:n,dataId:e.dataId},s=[Hs(t),...js(t)],i=new U6(s,n),o=!0,l=[n],u=a.runWebGLProgram(i,[r],e.dtype,l,o);return{dataId:u.dataId,shape:t,dtype:u.dtype}}function ce(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{shape:s}=n,i=a,o=v.sizeFromShape(r.shape),l=v.inferFromImplicitShape(s,o),u=v.sizeFromShape(l);v.assert(o===u,()=>`The new shape (${l}) has ${u} elements and the old shape (${r.shape}) has ${o} elements. The new shape and old shape must have the same number of elements.`);let p=i.texData.get(r.dataId);return p.isPacked&&!md(r.shape,l)&&!(p.texture!==null&&md(p.shape,l))?CG(r,l,i):(i.incRef(r.dataId),{dataId:r.dataId,shape:l,dtype:r.dtype})}var NG={kernelName:ql,backendName:\"webgl\",kernelFunc:ce},vx=class{constructor(e,t){this.variableNames=[\"x\"];let{windowSize:a,batchSize:n,inSize:r,outSize:s}=e;this.outputShape=[n,s];let i=Math.floor(a/4)*4,o=a%4,l=\"sumValue += dot(values, ones);\";if(t!=null){let p=1/t;l=`sumValue += dot(values * ${v.isInt(p)?p.toPrecision(2):p}, ones);`}let u=\"\";r%a>0&&(u=`\n        if (inIdx < 0 || inIdx >= ${r}) {\n          return 0.0;\n        }\n      `),this.userCode=`\n      const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n      float getValue(int batch, int inIdx) {\n        ${u}\n        return getX(batch, inIdx);\n      }\n\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int batch = coords[0];\n        int outIdx = coords[1];\n        int inOffset = outIdx * ${a};\n\n        float sumValue = 0.0;\n\n        for (int i = 0; i < ${i}; i += 4) {\n          int inIdx = inOffset + i;\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2),\n            getValue(batch, inIdx + 3)\n          );\n\n          ${l}\n        }\n\n        int inIdx = inOffset + ${i};\n        if (${o===1}) {\n          vec4 values = vec4(getValue(batch, inIdx), 0.0, 0.0, 0.0);\n\n          ${l}\n        } else if (${o===2}) {\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1), 0.0, 0.0);\n\n          ${l}\n        } else if (${o===3}) {\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2), 0.0);\n\n          ${l}\n        }\n        setOutput(sumValue);\n      }\n    `}},EG=class{constructor(e,t){this.variableNames=[\"x\"];let{windowSize:a,batchSize:n,inSize:r,outSize:s}=e;this.outputShape=[n,s];let i=\"0.0\",o=\"\";t===\"prod\"?i=\"1.0\":t===\"min\"?(i=\"1.0 / 1e-20\",o=\"min\"):t===\"max\"&&(i=\"-1.0 / 1e-20\",o=\"max\");let l=`${t}(${t}(${t}(minMaxValue[0], minMaxValue[1]), minMaxValue[2]), minMaxValue[3])`;t===\"sum\"?l=\"sumValue\":t===\"prod\"?l=\"prodValue\":t===\"all\"?l=\"allValue\":t===\"any\"&&(l=\"anyValue\");let u=Math.floor(a/4)*4,p=a%4,c=`\n      if (${t===\"sum\"}) {\n        sumValue += dot(values, ones);\n      } else if (${t===\"prod\"}) {\n        vec2 tmp = vec2(values[0], values[1]) * vec2(values[2], values[3]);\n        prodValue *= tmp[0] * tmp[1];\n      } else {\n        minMaxValue = ${o}(values, minMaxValue);\n        if (${t===\"min\"} || ${t===\"max\"}) {\n          minMaxValue = ${o}(values, minMaxValue);\n          bvec4 isNaN = isnan(values);\n          if (isNaN.r || isNaN.g || isNaN.b || isNaN.a) {\n            minMaxValue = vec4(NAN);\n          }\n        }\n      }\n    `,d=\"vec4\";t===\"all\"?(i=\"1.0\",c=`\n        bool reducedAllValue = all(values);\n        float floatedReducedAllValue = float(reducedAllValue);\n        allValue = float(allValue >= 1.0 && floatedReducedAllValue >= 1.0);\n      `,d=\"bvec4\"):t===\"any\"&&(i=\"0.0\",c=`\n        bool reducedAnyValue = any(values);\n        float floatedReducedAnyValue = float(reducedAnyValue);\n        anyValue = float(anyValue >= 1.0 || floatedReducedAnyValue >= 1.0);\n      `,d=\"bvec4\");let h=\"\";r%a>0&&(h=`\n        if (inIdx < 0 || inIdx >= ${r}) {\n          return initializationValue;\n        }\n      `),this.userCode=`\n      const float initializationValue = ${i};\n      const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n      float getValue(int batch, int inIdx) {\n        ${h}\n        return getX(batch, inIdx);\n      }\n\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int batch = coords[0];\n        int outIdx = coords[1];\n        int inOffset = outIdx * ${a};\n\n        vec4 minMaxValue = vec4(${i});\n        float prodValue = 1.0;\n        float sumValue = 0.0;\n        float allValue = 1.0;\n        float anyValue = 0.0;\n\n        for (int i = 0; i < ${u}; i += 4) {\n          int inIdx = inOffset + i;\n          ${d} values = ${d}(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2),\n            getValue(batch, inIdx + 3)\n          );\n\n          ${c}\n        }\n\n        int inIdx = inOffset + ${u};\n        if (${p===1}) {\n          ${d} values = ${d}(\n            getValue(batch, inIdx),\n            initializationValue,\n            initializationValue,\n            initializationValue\n          );\n\n          ${c}\n        } else if (${p===2}) {\n          ${d} values = ${d}(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            initializationValue,\n            initializationValue\n          );\n\n          ${c}\n        } else if (${p===3}) {\n          ${d} values = ${d}(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2),\n            initializationValue\n          );\n\n          ${c}\n        }\n        setOutput(${l});\n      }\n    `}};function RG(e){let t=[];for(;t.length===0||t[t.length-1].outSize!==1;){let a=t.length?t[t.length-1].outSize:e[1],n=T.computeOptimalWindowSize(a);t.push({inSize:a,windowSize:n,outSize:Math.ceil(a/n)})}return t}function bo(e,t,a,n){let r=RG(e.shape),s=e;for(let i=0;i<r.length;i++){let{inSize:o,windowSize:l,outSize:u}=r[i],p,c;a===\"mean\"?p=i===0?new vx({windowSize:l,inSize:o,batchSize:e.shape[0],outSize:u},o):new vx({windowSize:l,inSize:o,batchSize:e.shape[0],outSize:u}):p=new EG({windowSize:l,inSize:o,batchSize:e.shape[0],outSize:u},a),c=s,s=n.runWebGLProgram(p,[s],t),c.dataId!==e.dataId&&n.disposeIntermediateTensorInfo(c)}return s}var MG=class{constructor(e,t){this.variableNames=[\"A\"];let a=new Array(e.length);for(let s=0;s<a.length;s++)a[s]=e[t[s]];this.outputShape=a,this.rank=a.length;let n=gt(this.rank),r=$G(t);this.userCode=`\n    void main() {\n      ${n} resRC = getOutputCoords();\n      setOutput(getA(${r}));\n    }\n    `}};function $G(e){let t=e.length;if(t>6)throw Error(`Transpose for rank ${t} is not yet supported`);let a=[\"resRC.x\",\"resRC.y\",\"resRC.z\",\"resRC.w\",\"resRC.u\",\"resRC.v\"],n=new Array(t);for(let r=0;r<e.length;r++)n[e[r]]=a[r];return n.join()}var _G=class{constructor(e,t){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0;let a=new Array(e.length);for(let u=0;u<a.length;u++)a[u]=e[t[u]];if(this.outputShape=a,this.rank=a.length,this.rank>6)throw Error(`Packed transpose for rank ${this.rank} is not yet supported.`);let n=gt(this.rank),r=V6(\"rc\",this.rank),s=new Array(this.rank);for(let u=0;u<t.length;u++)s[t[u]]=r[u];let i=`vec2(${s.slice(-2).join()})`,o=`++${r[this.rank-1]} < ${a[this.rank-1]}`,l=`getChannel(getA(${s.join()}), ${i})`;this.userCode=`\n    void main() {\n      ${n} rc = getOutputCoords();\n      vec4 result = vec4(0.);\n      result[0] = ${l};\n      if(${o}) {\n        result[1] = ${l};\n      }\n      --${r[this.rank-1]};\n      if(++${r[this.rank-2]} < ${a[this.rank-2]}) {\n        result[2] = ${l};\n        if(${o}) {\n          result[3] = ${l};\n        }\n      }\n      setOutput(result);\n    }\n    `}};function Dh(e,t,a){let n=W().getBool(\"WEBGL_PACK_ARRAY_OPERATIONS\")?new _G(e.shape,t):new MG(e.shape,t);return a.runWebGLProgram(n,[e],e.dtype)}function PG(e,t,a,n){let r=t,s=e.shape.length,i=v.parseAxisParam(r,e.shape),o=i,l=T.getAxesPermutation(o,s),u=l!=null,p=e;u&&(p=Dh(e,l,n),o=T.getInnerMostAxes(o.length,s)),T.assertAxesAreInnerMostDims(\"sum\",o,s);let[c,d]=T.computeOutAndReduceShapes(p.shape,o),h=c;a&&(h=T.expandShapeToKeepDim(c,i));let f=v.sizeFromShape(d),m=v.sizeFromShape(e.shape)/f,g=ce({inputs:{x:p},attrs:{shape:[m,f]},backend:n}),x=Hd(e.dtype),A=bo(g,x,\"sum\",n),y=ce({inputs:{x:A},attrs:{shape:h},backend:n});return n.disposeIntermediateTensorInfo(g),n.disposeIntermediateTensorInfo(A),u&&n.disposeIntermediateTensorInfo(p),y}function zh(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;return PG(r,s,i,a)}var FG={kernelName:ro,backendName:\"webgl\",kernelFunc:zh};function Ia(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{perm:s}=n,i=a,o=r.shape.length,l=new Array(o);for(let p=0;p<l.length;p++)l[p]=r.shape[s[p]];let u;if(i.shouldExecuteOnCPU([r])){let p=i.texData.get(r.dataId).values,c=E3(p,r.shape,r.dtype,s,l);u=i.makeTensorInfo(l,r.dtype);let d=i.texData.get(u.dataId);d.values=c}else u=Dh(r,s,i);return u}var OG={kernelName:Ar,backendName:\"webgl\",kernelFunc:Ia},Z6=1e3;function Dc({a:e,b:t,transposeA:a,transposeB:n,backend:r,bias:s=null,preluActivationWeights:i=null,leakyreluAlpha:o=0,activation:l=null}){let u=e.shape.length,p=t.shape.length,c=a?e.shape[u-2]:e.shape[u-1],d=n?t.shape[p-1]:t.shape[p-2],h=a?e.shape[u-1]:e.shape[u-2],f=n?t.shape[p-2]:t.shape[p-1],m=e.shape.slice(0,-2),g=t.shape.slice(0,-2),x=v.sizeFromShape(m),A=v.sizeFromShape(g),y=xo.assertAndGetBroadcastShape(e.shape.slice(0,-2),t.shape.slice(0,-2)).concat([h,f]);v.assert(c===d,()=>`Error in matMul: inner shapes (${c}) and (${d}) of Tensors with shapes ${e.shape} and ${t.shape} and transposeA=${a} and transposeB=${n} must match.`);let b=a?[x,c,h]:[x,h,c],w=n?[A,f,d]:[A,d,f],S=ce({inputs:{x:e},backend:r,attrs:{shape:b}}),C=ce({inputs:{x:t},backend:r,attrs:{shape:w}}),E=[S,C],_=Math.max(x,A),$=a?S.shape[1]:S.shape[2],M=s!=null,I=i!=null,N=l===\"leakyrelu\",O=l!=null?gd(l,!0):null,L=M||I||N||O!=null,B;if((h===1||f===1)&&$>Z6&&L===!1){let j=S,U=C;a&&(j=Ia({inputs:{x:S},backend:r,attrs:{perm:[0,2,1]}}),E.push(j)),n&&(U=Ia({inputs:{x:C},backend:r,attrs:{perm:[0,2,1]}}),E.push(U));let H=f!==1,V=f===1,Q=j;H&&(Q=ce({inputs:{x:j},backend:r,attrs:{shape:[_,$,1]}}),E.push(Q));let Z=f===1?2:1,re=U;V&&(re=ce({inputs:{x:U},backend:r,attrs:{shape:[_,1,$]}}),E.push(re));let ee=M3({inputs:{a:Q,b:re},backend:r});B=zh({inputs:{x:ee},backend:r,attrs:{axis:Z,keepDims:!0}}),E.push(ee)}else{let j=ca(e.dtype,t.dtype),U=new K6(b,w,[_,h,f],a,n,M,O,I,N),H=[S,C];if(s!=null&&H.push(s),I&&H.push(i),N){let V=r.makeTensorInfo([],\"float32\",v.createScalarValue(o,\"float32\"));H.push(V),E.push(V)}B=r.runWebGLProgram(U,H,j)}let G=ce({inputs:{x:B},backend:r,attrs:{shape:y}});E.push(B);for(let j of E)r.disposeIntermediateTensorInfo(j);return G}function DG(e){let{inputs:t,backend:a,attrs:n}=e,{a:r,b:s,bias:i,preluActivationWeights:o}=t,{transposeA:l,transposeB:u,activation:p,leakyreluAlpha:c}=n;return Dc({a:r,b:s,transposeA:l,transposeB:u,backend:a,bias:i,preluActivationWeights:o,leakyreluAlpha:c,activation:p})}var zG={kernelName:jr,backendName:\"webgl\",kernelFunc:DG},wx=\"return abs(x);\";function LG(e){let{inputs:t,backend:a}=e,{x:n}=t;if(a.shouldExecuteOnCPU([n])&&n.dtype!==\"complex64\"){let s=a.texData.get(n.dataId),i=B6(s.values);return a.makeTensorInfo(n.shape,n.dtype,i)}let r;return W().getBool(\"WEBGL_PACK_UNARY_OPERATIONS\")?r=new Vr(n.shape,wx):r=new qn(n.shape,wx),a.runWebGLProgram(r,[n],n.dtype)}var BG={kernelName:wl,backendName:\"webgl\",kernelFunc:LG},WG=Cn+`\n  if (abs(x) > 1.) {\n    return NAN;\n  }\n  return acos(x);\n`,VG=Qe({opSnippet:WG}),UG={kernelName:kl,backendName:\"webgl\",kernelFunc:VG},GG=Cn+`\n  if (x < 1.0) return NAN;\nreturn log(x + sqrt(x * x - 1.0));`,HG=Qe({opSnippet:GG}),jG={kernelName:Il,backendName:\"webgl\",kernelFunc:HG},kx=\"return a + b;\",qG=oa({opSnippet:kx,packedOpSnippet:kx,supportsComplex:!0,cpuKernelImpl:nU}),XG={kernelName:ts,backendName:\"webgl\",kernelFunc:qG},KG=class{constructor(e,t){this.outputShape=[],this.outputShape=e,this.variableNames=t.map((r,s)=>`T${s}`);let a=[];this.variableNames.forEach(r=>{a.push(`float v${r} = get${r}AtOutCoords();`)});let n=this.variableNames.map(r=>`v${r}`).join(\" + \");this.userCode=`\n      void main() {\n        ${a.join(`\n        `)}\n\n        float result = ${n};\n        setOutput(result);\n      }\n    `}},ZG=class{constructor(e,t){this.outputShape=[],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=e,this.variableNames=t.map((r,s)=>`T${s}`);let a=[];this.variableNames.forEach(r=>{a.push(`vec4 v${r} = get${r}AtOutCoords();`)});let n=this.variableNames.map(r=>`v${r}`).join(\" + \");this.userCode=`\n      void main() {\n        ${a.join(`\n        `)}\n\n        vec4 result = ${n};\n        setOutput(result);\n      }\n    `}};function bc(e){let{inputs:t,backend:a}=e,n=t;if(n.length===1)return Za({inputs:{x:n[0]},backend:a});if(n.length>W().get(\"WEBGL_MAX_TEXTURES_IN_SHADER\")){let o=Math.floor(n.length/2),l=bc({inputs:n.slice(0,o),backend:a}),u=bc({inputs:n.slice(o),backend:a});return bc({inputs:[l,u],backend:a})}let r=n.map(o=>o.dtype).reduce((o,l)=>ca(o,l)),s=n.map(o=>o.shape),i=W().getBool(\"WEBGL_PACK\")?new ZG(n[0].shape,s):new KG(n[0].shape,s);return a.runWebGLProgram(i,n,r)}var YG={kernelName:Ks,backendName:\"webgl\",kernelFunc:bc};function JG(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n,o=r.shape.length,l=v.parseAxisParam(s,r.shape),u=l,p=T.getAxesPermutation(u,o),c=r;p!=null&&(c=Ia({inputs:{x:r},backend:a,attrs:{perm:p}}),u=T.getInnerMostAxes(u.length,o)),T.assertAxesAreInnerMostDims(\"all\",u,o);let[d,h]=T.computeOutAndReduceShapes(c.shape,u),f=v.sizeFromShape(h),m=ce({inputs:{x:c},backend:a,attrs:{shape:[-1,f]}}),g=bo(m,m.dtype,\"all\",a),x;if(i){let A=T.expandShapeToKeepDim(d,l);x=ce({inputs:{x:g},backend:a,attrs:{shape:A}})}else x=ce({inputs:{x:g},backend:a,attrs:{shape:d}});return a.disposeIntermediateTensorInfo(m),a.disposeIntermediateTensorInfo(g),p!=null&&a.disposeIntermediateTensorInfo(c),x}var QG={kernelName:Zs,backendName:\"webgl\",kernelFunc:JG};function eH(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n,o=r.shape.length,l=v.parseAxisParam(s,r.shape),u=l,p=T.getAxesPermutation(u,o),c=r;p!=null&&(c=Ia({inputs:{x:r},backend:a,attrs:{perm:p}}),u=T.getInnerMostAxes(u.length,o)),T.assertAxesAreInnerMostDims(\"any\",u,o);let[d,h]=T.computeOutAndReduceShapes(c.shape,u),f=v.sizeFromShape(h),m=ce({inputs:{x:c},backend:a,attrs:{shape:[-1,f]}}),g=bo(m,m.dtype,\"any\",a),x;if(i){let A=T.expandShapeToKeepDim(d,l);x=ce({inputs:{x:g},backend:a,attrs:{shape:A}})}else x=ce({inputs:{x:g},backend:a,attrs:{shape:d}});return a.disposeIntermediateTensorInfo(m),a.disposeIntermediateTensorInfo(g),p!=null&&a.disposeIntermediateTensorInfo(c),x}var tH={kernelName:Ys,backendName:\"webgl\",kernelFunc:eH},aH=class{constructor(e,t,a){this.variableNames=[\"A\"];let{windowSize:n,batchSize:r,outSize:s}=e;a||this.variableNames.push(\"bestIndicesA\"),this.outputShape=[r,s];let i=t===\"max\"?\">\":\"<\",o=a?\"inOffset + i;\":\"round(getBestIndicesA(batch, inOffset + i));\";this.userCode=`\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int batch = coords[0];\n        int outIdx = coords[1];\n        int inOffset = outIdx * ${n};\n\n        int bestIndex = inOffset;\n        float bestValue = getA(batch, bestIndex);\n\n        for (int i = 0; i < ${n}; i++) {\n          int inIdx = ${o};\n          float candidate = getA(batch, inIdx);\n          if (candidate ${i} bestValue) {\n            bestValue = candidate;\n            bestIndex = inIdx;\n          }\n        }\n        setOutput(float(bestIndex));\n      }\n    `}},nH=class{constructor(e,t,a,n){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0,v.assert(e.length>2,()=>`Packed arg${a.charAt(0).toUpperCase()+a.slice(1)} supports only inputs with rank above 2.`);let r=e[e.length-1],s=Math.ceil(r/t);this.outputShape=e.slice(0,-1),s>1&&this.outputShape.push(s),n||this.variableNames.push(\"bestIndicesA\");let i=this.outputShape,o=i.length,l=gt(o),u=va(\"coords\",o),p,c;if(s===1){c=o+1;let C=gt(c);p=`\n        ${C} sourceLocR = ${C}(${u.join()}, 0);\n        ++${u[o-1]};\n        ${C} sourceLocG = ${C}(${u.join()}, 0);\n        ++${u[o-2]};\n        ${C} sourceLocA = ${C}(${u.join()}, 0);\n        --${u[o-1]};\n        ${C} sourceLocB = ${C}(${u.join()}, 0);\n        --${u[o-2]};`}else c=o,p=`\n        ${l} sourceLocR = coords;\n        ++${u[o-1]};\n        ${l} sourceLocG = coords;\n        ++${u[o-2]};\n        ${l} sourceLocA = coords;\n        --${u[o-1]};\n        ${l} sourceLocB = coords;\n        --${u[o-2]};`;let d=[\"x\",\"y\",\"z\",\"w\",\"u\",\"v\"].slice(0,c),h=\".\"+d[c-1],f=d.map(C=>\"int \"+C),m=va(\"sourceLocR\",c-1).concat(\"inIdx.r\"),g=va(\"sourceLocG\",c-1).concat(\"inIdx.g\"),x=va(\"sourceLocB\",c-1).concat(\"inIdx.b\"),A=va(\"sourceLocA\",c-1).concat(\"inIdx.a\"),y=a===\"max\"?\"greaterThan\":\"lessThan\",b=n?\"\":`\n          inIdx = round(vec4(getBestIndicesAChannel(${m.join()}),\n                             getBestIndicesAChannel(${g.join()}),\n                             getBestIndicesAChannel(${x.join()}),\n                             getBestIndicesAChannel(${A.join()})));`,w=`vec4(\n            getAChannel(${m.join()}),\n            hasNextCol ? getAChannel(${g.join()}) : 0.,\n            hasNextRow ? getAChannel(${x.join()}) : 0.,\n            hasNextRow && hasNextCol ? getAChannel(${A.join()}) : 0.)`,S=n?\"\":`\n      float getBestIndicesAChannel(${f.join()}) {\n        return getChannel(getBestIndicesA(${d.join()}),\n                                          vec2(${d.slice(-2).join()}));\n      }`;this.userCode=`\n      float getAChannel(${f.join()}) {\n        return getChannel(getA(${d.join()}),\n                               vec2(${d.slice(-2).join()}));\n      }\n      ${S}\n      void main() {\n        ${l} coords = getOutputCoords();\n        bool hasNextCol = ${u[o-1]} < ${i[o-1]-1};\n        bool hasNextRow = ${u[o-2]} < ${i[o-2]-1};\n        ${p}\n        ivec4 srcIdx = ivec4(sourceLocR${h}, sourceLocG${h},\n          sourceLocB${h}, sourceLocA${h}) * ${t};\n        ivec4 inIdx = srcIdx;\n        vec4 bestIndex = vec4(inIdx);\n        vec4 bestValue = ${w};\n\n        for (int i = 0; i < ${t}; i++) {\n          inIdx = srcIdx;\n          ${b}\n          vec4 candidate = ${w};\n          bvec4 nan = isnan(candidate);\n          bvec4 replace = bvec4(\n            vec4(${y}(candidate, bestValue)) * (vec4(1.0) - vec4(nan)));\n\n          bestValue = vec4(replace.x  ? candidate.x : bestValue.x,\n                           replace.y  ? candidate.y : bestValue.y,\n                           replace.z  ? candidate.z : bestValue.z,\n                           replace.w  ? candidate.w : bestValue.w);\n          bestIndex = mix(bestIndex, vec4(inIdx), vec4(replace));\n          srcIdx++;\n        }\n        setOutput(bestIndex);\n      }\n    `}};function Y6(e,t,a,n=null){let r=t.shape[0],s=t.shape[1];n!=null&&(r=n.shape[0],s=n.shape[1]);let i=T.computeOptimalWindowSize(s),o={windowSize:i,inSize:s,batchSize:r,outSize:Math.ceil(s/i)},l=new aH(o,a,n==null),u=[t];n!=null&&u.push(n);let p=e.runWebGLProgram(l,u,\"int32\");if(p.shape[1]===1)return p;let c=Y6(e,t,a,p);return e.disposeIntermediateTensorInfo(p),c}function J6(e,t,a,n=null){let r=n!=null?n.shape:t.shape,s=r[r.length-1],i=T.computeOptimalWindowSize(s),o=new nH(r,i,a,n==null),l=n==null?[t]:[t,n],u=e.runWebGLProgram(o,l,\"int32\");if(u.shape.length===t.shape.length){let p=J6(e,t,a,u);return e.disposeIntermediateTensorInfo(u),p}return u}function Q6(e,t,a,n){let r=[a];if(T.assertAxesAreInnerMostDims(\"arg\"+n.charAt(0).toUpperCase()+n.slice(1),r,t.shape.length),!W().getBool(\"WEBGL_PACK_REDUCE\")||t.shape.length<=2){let s=[],i=e.texData.get(t.dataId),o=i!==null&&i.isPacked,l=t;o&&(l=e.unpackTensor(t),s.push(l));let[u,p]=T.computeOutAndReduceShapes(l.shape,r),c=v.sizeFromShape(p),d=ce({inputs:{x:l},backend:e,attrs:{shape:[-1,c]}});s.push(d);let h=Y6(e,d,n);s.push(h);let f=ce({inputs:{x:h},backend:e,attrs:{shape:u}});return s.forEach(m=>e.disposeIntermediateTensorInfo(m)),f}return J6(e,t,n)}function rH(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s}=n,i=v.parseAxisParam(s,r.shape),o=T.getAxesPermutation(i,r.shape.length),l=r,u=[];o!=null&&(l=Ia({inputs:{x:r},backend:a,attrs:{perm:o}}),u.push(l),i=T.getInnerMostAxes(i.length,l.shape.length)),T.assertAxesAreInnerMostDims(\"argMax\",[i[0]],l.shape.length);let p=Q6(a,l,i[0],\"max\");return u.forEach(c=>a.disposeIntermediateTensorInfo(c)),p}var sH={kernelName:Js,backendName:\"webgl\",kernelFunc:rH};function iH(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s}=n,i=v.parseAxisParam(s,r.shape),o=T.getAxesPermutation(i,r.shape.length),l=r,u=[];o!=null&&(l=Ia({inputs:{x:r},backend:a,attrs:{perm:o}}),u.push(l),i=T.getInnerMostAxes(i.length,l.shape.length)),T.assertAxesAreInnerMostDims(\"argMin\",[i[0]],l.shape.length);let p=Q6(a,l,i[0],\"min\");return u.forEach(c=>a.disposeIntermediateTensorInfo(c)),p}var oH={kernelName:kd,backendName:\"webgl\",kernelFunc:iH},lH=Cn+`\n  if (abs(x) > 1.) {\n    return NAN;\n  }\n  return asin(x);\n`,uH=Qe({opSnippet:lH}),dH={kernelName:Sl,backendName:\"webgl\",kernelFunc:uH},pH=Cn+\"return log(x + sqrt(x * x + 1.0));\",cH=Qe({opSnippet:pH}),hH={kernelName:Tl,backendName:\"webgl\",kernelFunc:cH},fH=Cn+`\n  return atan(x);\n`,mH=Qe({opSnippet:fH}),gH={kernelName:Cl,backendName:\"webgl\",kernelFunc:mH},xH=R3+`\n  return atan(a, b);\n`,AH=`\n  vec4 result = atan(a, b);\n  bvec4 isNaNA = isnan(a);\n  bvec4 isNaNB = isnan(b);\n  bvec4 isNaN = bvec4(isNaNA.x || isNaNB.x, isNaNA.y || isNaNB.y, isNaNA.z || isNaNB.z, isNaNA.w || isNaNB.w);\n  `+pp+`\n  return result;\n`,yH=oa({opSnippet:xH,packedOpSnippet:AH}),bH={kernelName:El,backendName:\"webgl\",kernelFunc:yH},vH=Cn+`\n  if ((x < -1.0) || (x > 1.0)) return NAN;\nreturn (log(1.0 + x) - log(1.0 - x)) / 2.0;`,wH=Qe({opSnippet:vH}),kH={kernelName:Nl,backendName:\"webgl\",kernelFunc:wH},xd=class{constructor(e,t,a,n=!1,r=!1){if(this.variableNames=[\"x\"],t===\"avg\"&&a)throw new Error(\"Cannot compute positions for average pool.\");let s=e.filterWidth,i=e.strideHeight,o=e.strideWidth,l=e.dilationHeight,u=e.dilationWidth,p=e.effectiveFilterHeight,c=e.effectiveFilterWidth,d=e.padInfo.top,h=e.padInfo.left;this.outputShape=e.outShape;let f=t===\"avg\",m=`((batch  * ${e.inHeight} + xR) * ${e.inWidth} + xC) * ${e.inChannels} + d`,g=`(xR * ${e.inWidth} + xC) * ${e.inChannels} + d`,x=\"0.0\";if(f||(x=\"-1.0 / 1e-20\"),a){let C=\">=\";this.userCode=`\n        const ivec2 strides = ivec2(${i}, ${o});\n        const ivec2 pads = ivec2(${d}, ${h});\n\n        void main() {\n          ivec4 coords = getOutputCoords();\n          int batch = coords[0];\n          int d = coords[3];\n\n          ivec2 xRCCorner = coords.yz * strides - pads;\n          int xRCorner = xRCCorner.x;\n          int xCCorner = xRCCorner.y;\n\n          // max/min x(?, ?, d) to get y(yR, yC, d).\n          // ? = to be determined\n          float minMaxValue = 0.0;\n          float minMaxValueFound = 0.0;\n          int minMaxPosition = 0;\n          float avgValue = 0.0;\n\n          for (int wR = 0; wR < ${p};\n              wR += ${l}) {\n            int xR = xRCorner + wR;\n\n            if (xR < 0 || xR >= ${e.inHeight}) {\n              continue;\n            }\n\n            for (int wC = 0; wC < ${c};\n                wC += ${u}) {\n              int xC = xCCorner + wC;\n\n              if (xC < 0 || xC >= ${e.inWidth}) {\n                continue;\n              }\n\n              float value = getX(batch, xR, xC, d);\n\n              // If a min / max value has already been found, use it. If not,\n              // use the current value.\n              float currMinMaxValue = mix(\n                  value, minMaxValue, minMaxValueFound);\n              if (value ${C} currMinMaxValue) {\n                minMaxValue = value;\n                minMaxValueFound = 1.0;\n                minMaxPosition = ${n?r?m:g:`wR * ${c} + wC`};\n              }\n            }\n          }\n          setOutput(float(minMaxPosition));\n        }\n      `;return}let A=\"max\",y=`${t}(${t}(${t}(minMaxValue[0], minMaxValue[1]), minMaxValue[2]), minMaxValue[3])`;t===\"avg\"&&(y=\"avgValue / count\");let b=Math.floor(s/4)*4,w=s%4,S=`\n      if (${f}) {\n        avgValue += dot(values, ones);\n      } else {\n        minMaxValue = ${A}(values, minMaxValue);\n      }\n    `;this.userCode=`\n      const ivec2 strides = ivec2(${i}, ${o});\n      const ivec2 pads = ivec2(${d}, ${h});\n      const float initializationValue = ${x};\n      const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n      float count = 0.0;\n\n      float getValue(int batch, int xR, int xC, int d) {\n        if (xC < 0 || xC >= ${e.inWidth}) {\n          return initializationValue;\n        }\n        count += 1.0;\n        return getX(batch, xR, xC, d);\n      }\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int batch = coords[0];\n        int d = coords[3];\n\n        ivec2 xRCCorner = coords.yz * strides - pads;\n        int xRCorner = xRCCorner.x;\n        int xCCorner = xRCCorner.y;\n\n        // max/min x(?, ?, d) to get y(yR, yC, d).\n        // ? = to be determined\n        vec4 minMaxValue = vec4(${x});\n        float avgValue = 0.0;\n        count = 0.0;\n\n        for (int wR = 0; wR < ${p};\n            wR += ${l}) {\n          int xR = xRCorner + wR;\n\n          if (xR < 0 || xR >= ${e.inHeight}) {\n            continue;\n          }\n\n          for (int wC = 0; wC < ${b}; wC += 4) {\n            int xC = xCCorner + wC * ${u};\n\n            vec4 values = vec4(\n              getValue(batch, xR, xC, d),\n              getValue(batch, xR, xC + ${u}, d),\n              getValue(batch, xR, xC + 2 * ${u}, d),\n              getValue(batch, xR, xC + 3 * ${u}, d)\n            );\n\n            ${S}\n          }\n\n          int xC = xCCorner + ${b};\n          if (${w===1}) {\n            vec4 values = vec4(\n              getValue(batch, xR, xC, d),\n              initializationValue,\n              initializationValue,\n              initializationValue\n            );\n\n            ${S}\n          } else if (${w===2}) {\n            vec4 values = vec4(\n              getValue(batch, xR, xC, d),\n              getValue(batch, xR, xC + ${u}, d),\n              initializationValue,\n              initializationValue\n            );\n\n            ${S}\n          } else if (${w===3}) {\n            vec4 values = vec4(\n              getValue(batch, xR, xC, d),\n              getValue(batch, xR, xC + ${u}, d),\n              getValue(batch, xR, xC + 2 * ${u}, d),\n              initializationValue\n            );\n\n            ${S}\n          }\n        }\n        setOutput(${y});\n      }\n    `}},$3=class{constructor(e,t,a,n=!1,r=!1){if(this.variableNames=[\"x\"],t===\"avg\"&&a)throw new Error(\"Cannot compute positions for average pool.\");let s=e.filterWidth,i=e.strideDepth,o=e.strideHeight,l=e.strideWidth,u=e.dilationDepth,p=e.dilationHeight,c=e.dilationWidth,d=e.effectiveFilterDepth,h=e.effectiveFilterHeight,f=e.effectiveFilterWidth,m=e.padInfo.front,g=e.padInfo.top,x=e.padInfo.left;this.outputShape=e.outShape;let A=t===\"avg\",y=\"0.0\";if(A||(y=\"-1.0 / 1e-20\"),a){let _=\">=\";this.userCode=`\n        const ivec3 strides =\n            ivec3(${i}, ${o}, ${l});\n        const ivec3 pads = ivec3(${m}, ${g}, ${x});\n\n        void main() {\n          ivec5 coords = getOutputCoords();\n          int batch = coords.x;\n          int ch = coords.u;\n\n          ivec3 xCorner = ivec3(coords.y, coords.z, coords.w) * strides - pads;\n          int xDCorner = xCorner.x;\n          int xRCorner = xCorner.y;\n          int xCCorner = xCorner.z;\n\n          // max/min x(?, ?, ?, ch) to get y(yD, yR, yC, ch).\n          // ? = to be determined\n          float minMaxValue = 0.0;\n          float minMaxValueFound = 0.0;\n          int minMaxPosition = 0;\n\n          for (int wD = 0; wD < ${d};\n              wD += ${u}) {\n            int xD = xDCorner + wD;\n\n            if (xD < 0 || xD >= ${e.inDepth}) {\n              continue;\n            }\n\n            for (int wR = 0; wR < ${h};\n                wR += ${p}) {\n              int xR = xRCorner + wR;\n\n              if (xR < 0 || xR >= ${e.inHeight}) {\n                continue;\n              }\n\n              for (int wC = 0; wC < ${f};\n                  wC += ${c}) {\n                int xC = xCCorner + wC;\n\n                if (xC < 0 || xC >= ${e.inWidth}) {\n                  continue;\n                }\n\n                float value = getX(batch, xD, xR, xC, ch);\n\n                // If a min / max value has already been found, use it. If not,\n                // use the current value.\n                float currMinMaxValue = mix(\n                    value, minMaxValue, minMaxValueFound);\n                if (value ${_} currMinMaxValue) {\n                  minMaxValue = value;\n                  minMaxValueFound = 1.0;\n                  minMaxPosition = ${n?r?`(((batch * ${e.inDepth} + xD) * ${e.inHeight} + xR) * ${e.inWidth} + xC) * ${e.inChannels} + ch`:`((xD * ${e.inHeight} + xR) * ${e.inWidth} + xC) * ${e.inChannels} + ch`:`wD * ${h} * ${f} +\n                      wR * ${f} + wC`};\n                }\n              }\n            }\n          }\n          setOutput(float(minMaxPosition));\n        }\n      `;return}let b=\"max\",w=`${t}(${t}(${t}(minMaxValue[0], minMaxValue[1]), minMaxValue[2]), minMaxValue[3])`;t===\"avg\"&&(w=\"avgValue / count\");let S=Math.floor(s/4)*4,C=s%4,E=`\n      if (${A}) {\n        avgValue += dot(values, ones);\n      } else {\n        minMaxValue = ${b}(values, minMaxValue);\n      }\n    `;this.userCode=`\n      const ivec3 strides =\n        ivec3(${i}, ${o}, ${l});\n      const ivec3 pads = ivec3(${m}, ${g}, ${x});\n      const float initializationValue = ${y};\n      const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n      float count = 0.0;\n\n      float getValue(int batch, int xD, int xR, int xC, int ch) {\n        if (xC < 0 || xC >= ${e.inWidth}) {\n          return initializationValue;\n        }\n        count += 1.0;\n        return getX(batch, xD, xR, xC, ch);\n      }\n\n      void main() {\n        ivec5 coords = getOutputCoords();\n        int batch = coords.x;\n        int ch = coords.u;\n\n        ivec3 xCorner = ivec3(coords.y, coords.z, coords.w) * strides - pads;\n        int xDCorner = xCorner.x;\n        int xRCorner = xCorner.y;\n        int xCCorner = xCorner.z;\n\n        // max/min x(?, ?, ?, d) to get y(yD, yR, yC, ch).\n        // ? = to be determined\n        vec4 minMaxValue = vec4(${y});\n        float avgValue = 0.0;\n        count = 0.0;\n\n        for (int wD = 0; wD < ${d};\n            wD += ${u}) {\n          int xD = xDCorner + wD;\n\n          if (xD < 0 || xD >= ${e.inDepth}) {\n            continue;\n          }\n\n          for (int wR = 0; wR < ${h};\n            wR += ${p}) {\n            int xR = xRCorner + wR;\n\n            if (xR < 0 || xR >= ${e.inHeight}) {\n              continue;\n            }\n\n            for (int wC = 0; wC < ${S}; wC += 4) {\n              int xC = xCCorner + wC * ${c};\n\n              vec4 values = vec4(\n                getValue(batch, xD, xR, xC, ch),\n                getValue(batch, xD, xR, xC + ${c}, ch),\n                getValue(batch, xD, xR, xC + 2 * ${c}, ch),\n                getValue(batch, xD, xR, xC + 3 * ${c}, ch)\n              );\n\n              ${E}\n            }\n\n            int xC = xCCorner + ${S};\n            if (${C===1}) {\n              vec4 values = vec4(\n                getValue(batch, xD, xR, xC, ch),\n                initializationValue,\n                initializationValue,\n                initializationValue\n              );\n\n              ${E}\n            } else if (${C===2}) {\n              vec4 values = vec4(\n                getValue(batch, xD, xR, xC, ch),\n                getValue(batch, xD, xR, xC + ${c}, ch),\n                initializationValue,\n                initializationValue\n              );\n\n              ${E}\n            } else if (${C===3}) {\n              vec4 values = vec4(\n                getValue(batch, xD, xR, xC, ch),\n                getValue(batch, xD, xR, xC + ${c}, ch),\n                getValue(batch, xD, xR, xC + 2 * ${c}, ch),\n                initializationValue\n              );\n\n              ${E}\n            }\n          }\n          setOutput(${w});\n        }\n      }\n    `}};function IH(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t;uu(r,\"avgPool\");let{filterSize:s,strides:i,pad:o,dimRoundingMode:l}=n,u=1;v.assert(T.eitherStridesOrDilationsAreOne(i,u),()=>`Error in avgPool: Either strides or dilations must be 1. Got strides ${i} and dilations '${u}'`);let p=T.computePool2DInfo(r.shape,s,i,u,o,l);if(p.filterWidth===1&&p.filterHeight===1&&v.arraysEqual(p.inShape,p.outShape))return Za({inputs:{x:r},backend:a});let c=new xd(p,\"avg\",!1);return a.runWebGLProgram(c,[r],\"float32\")}var SH={kernelName:Qs,backendName:\"webgl\",kernelFunc:IH};function TH(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{filterSize:s,strides:i,pad:o,dimRoundingMode:l,dataFormat:u}=n,p=[1,1,1],c=T.computePool3DInfo(r.shape,s,i,p,o,l,u),d=new $3(c,\"avg\",!1);return a.runWebGLProgram(d,[r],\"float32\")}var CH={kernelName:Hc,backendName:\"webgl\",kernelFunc:TH},NH=class{constructor(e){this.variableNames=[\"dy\"],this.outputShape=e.inShape;let t=e.filterHeight,a=e.filterWidth,n=e.strideHeight,r=e.strideWidth,s=e.dilationHeight,i=e.dilationWidth,o=e.effectiveFilterHeight,l=e.effectiveFilterWidth,u=o-1-e.padInfo.top,p=l-1-e.padInfo.left,c=1/(t*a);this.userCode=`\n      const ivec2 pads = ivec2(${u}, ${p});\n      const float avgMultiplier = float(${c});\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int d = coords[3];\n\n        ivec2 dyRCCorner = coords.yz - pads;\n        int dyRCorner = dyRCCorner.x;\n        int dyCCorner = dyRCCorner.y;\n\n        // Convolve dy(?, ?, d) with pos mask(:, :, d) to get dx(xR, xC, d).\n        // ? = to be determined. : = across all values in that axis.\n        float dotProd = 0.0;\n        for (int wR = 0; wR < ${o};\n            wR += ${s}) {\n          float dyR = float(dyRCorner + wR) / ${n}.0;\n\n          if (dyR < 0.0 || dyR >= ${e.outHeight}.0 || fract(dyR) > 0.0) {\n            continue;\n          }\n          int idyR = int(dyR);\n\n          for (int wC = 0; wC < ${l};\n            wC+= ${i}) {\n            float dyC = float(dyCCorner + wC) / ${r}.0;\n\n            if (dyC < 0.0 || dyC >= ${e.outWidth}.0 ||\n                fract(dyC) > 0.0) {\n              continue;\n            }\n            int idyC = int(dyC);\n\n            float dyValue = getDy(b, idyR, idyC, d);\n\n            dotProd += dyValue * avgMultiplier;\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}},EH=class{constructor(e){this.variableNames=[\"dy\"],this.outputShape=e.inShape;let t=e.filterDepth,a=e.filterHeight,n=e.filterWidth,r=e.strideDepth,s=e.strideHeight,i=e.strideWidth,o=e.dilationDepth,l=e.dilationHeight,u=e.dilationWidth,p=e.effectiveFilterDepth,c=e.effectiveFilterHeight,d=e.effectiveFilterWidth,h=p-1-e.padInfo.front,f=c-1-e.padInfo.top,m=d-1-e.padInfo.left,g=1/(t*a*n);this.userCode=`\n      const ivec3 pads = ivec3(${h}, ${f}, ${m});\n      const float avgMultiplier = float(${g});\n\n      void main() {\n        ivec5 coords = getOutputCoords();\n        int batch = coords.x;\n        int ch = coords.u;\n\n        ivec3 dyCorner = ivec3(coords.y, coords.z, coords.w) - pads;\n        int dyDCorner = dyCorner.x;\n        int dyRCorner = dyCorner.y;\n        int dyCCorner = dyCorner.z;\n\n        // Convolve dy(?, ?, ?, d) with pos mask(:, :, :, ch) to get\n        // dx(xD, xR, xC, ch).\n        // ? = to be determined. : = across all values in that axis.\n        float dotProd = 0.0;\n\n        for (int wD = 0; wD < ${p};\n            wD += ${o}) {\n          float dyD = float(dyDCorner + wD) / ${r}.0;\n\n          if (dyD < 0.0 || dyD >= ${e.outDepth}.0 || fract(dyD) > 0.0) {\n            continue;\n          }\n          int idyD = int(dyD);\n\n          for (int wR = 0; wR < ${c};\n              wR += ${l}) {\n            float dyR = float(dyRCorner + wR) / ${s}.0;\n\n            if (dyR < 0.0 || dyR >= ${e.outHeight}.0 ||\n                fract(dyR) > 0.0) {\n              continue;\n            }\n            int idyR = int(dyR);\n\n            for (int wC = 0; wC < ${d};\n                wC += ${u}) {\n              float dyC = float(dyCCorner + wC) / ${i}.0;\n\n              if (dyC < 0.0 || dyC >= ${e.outWidth}.0 ||\n                  fract(dyC) > 0.0) {\n                continue;\n              }\n              int idyC = int(dyC);\n\n              float dyValue = getDy(batch, idyD, idyR, idyC, ch);\n\n              dotProd += dyValue * avgMultiplier;\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}};function RH(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,input:s}=t,i=s,{filterSize:o,strides:l,pad:u,dimRoundingMode:p}=n,c=[1,1,1],d=T.computePool3DInfo(i.shape,o,l,c,u,p),h=new EH(d);return a.runWebGLProgram(h,[r],i.dtype)}var MH={kernelName:G1,backendName:\"webgl\",kernelFunc:RH};function $H(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,input:s}=t,i=s;uu([r,s],\"avgPoolGrad\");let{filterSize:o,strides:l,pad:u}=n,p=T.computePool2DInfo(i.shape,o,l,1,u),c=new NH(p);return a.runWebGLProgram(c,[r],i.dtype)}var _H={kernelName:U1,backendName:\"webgl\",kernelFunc:$H};function PH(e){let{inputs:t,backend:a,attrs:n}=e,{a:r,b:s}=t,{transposeA:i,transposeB:o}=n;return Dc({a:r,b:s,transposeA:i,transposeB:o,backend:a})}var FH={kernelName:ei,backendName:\"webgl\",kernelFunc:PH},OH=class{constructor(e,t,a,n,r,s){this.outputShape=[],this.variableNames=[\"x\",\"mean\",\"variance\"],T.assertAndGetBroadcastShape(e,t),T.assertAndGetBroadcastShape(e,a);let i=\"0.0\";n!=null&&(T.assertAndGetBroadcastShape(e,n),this.variableNames.push(\"offset\"),i=\"getOffsetAtOutCoords()\");let o=\"1.0\";r!=null&&(T.assertAndGetBroadcastShape(e,r),this.variableNames.push(\"scale\"),o=\"getScaleAtOutCoords()\"),this.outputShape=e,this.userCode=`\n      void main() {\n        float x = getXAtOutCoords();\n        float mean = getMeanAtOutCoords();\n        float variance = getVarianceAtOutCoords();\n        float offset = ${i};\n        float scale = ${o};\n        float inv = scale * inversesqrt(variance + float(${s}));\n        setOutput(dot(vec3(x, -mean, offset), vec3(inv, inv, 1)));\n      }\n    `}},DH=class{constructor(e,t,a,n,r,s){this.packedInputs=!0,this.packedOutput=!0,this.variableNames=[\"x\",\"mean\",\"variance\"],T.assertAndGetBroadcastShape(e,t),T.assertAndGetBroadcastShape(e,a);let i=\"vec4(0.0)\";n!=null&&(T.assertAndGetBroadcastShape(e,n),this.variableNames.push(\"offset\"),i=\"getOffsetAtOutCoords()\");let o=\"vec4(1.0)\";r!=null&&(T.assertAndGetBroadcastShape(e,r),this.variableNames.push(\"scale\"),o=\"getScaleAtOutCoords()\"),this.outputShape=e,this.userCode=`\n      void main() {\n        vec4 offset = ${i};\n        vec4 scale = ${o};\n\n        vec4 x = getXAtOutCoords();\n        vec4 mean = getMeanAtOutCoords();\n        vec4 variance = getVarianceAtOutCoords();\n\n        vec4 inv = scale * inversesqrt(variance + vec4(${s}));\n\n        setOutput((x - mean) * inv + offset);\n      }\n    `}},zH=({inputs:e,backend:t,attrs:a})=>{let{x:n,mean:r,variance:s,offset:i,scale:o}=e;v.assert(r.shape.length===s.shape.length,()=>\"Batch normalization gradient requires mean and variance to have equal ranks.\"),v.assert(i==null||r.shape.length===i.shape.length,()=>\"Batch normalization gradient requires mean and offset to have equal ranks.\"),v.assert(o==null||r.shape.length===o.shape.length,()=>\"Batch normalization gradient requires mean and scale to have equal ranks.\");let{varianceEpsilon:l}=a;l==null&&(l=.001);let u=[n,r,s],p=null;i!=null&&(p=i.shape,u.push(i));let c=null;o!=null&&(c=o.shape,u.push(o));let d=W().getBool(\"WEBGL_PACK_NORMALIZATION\")?new DH(n.shape,r.shape,s.shape,p,c,l):new OH(n.shape,r.shape,s.shape,p,c,l);return t.runWebGLProgram(d,u,u[0].dtype)},LH={kernelName:yi,backendName:\"webgl\",kernelFunc:zH},BH=class{constructor(e){this.variableNames=[\"source\"],this.outputShape=e,this.rank=e.length;let t=gt(this.rank);this.customUniforms=[{name:\"start\",arrayIndex:this.rank,type:\"int\"}];let a=WH(this.rank),n,r=e.map((s,i)=>`sourceLoc.${T1[i]} = start[${i}] + coords.${T1[i]};`);n=`\n        ${t} sourceLoc;\n        ${t} coords = getOutputCoords();\n        ${r.join(`\n`)}\n      `,this.userCode=`\n      void main() {\n        ${n}\n        setOutput(getSource(${a}));\n      }\n    `}},T1=[\"x\",\"y\",\"z\",\"w\",\"u\",\"v\"];function WH(e){if(e===1)return\"sourceLoc\";if(e<=6)return T1.slice(0,e).map(t=>\"sourceLoc.\"+t).join(\",\");throw Error(`Slicing for rank ${e} is not yet supported`)}var VH=class{constructor(e){this.variableNames=[\"source\"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=e,this.rank=e.length,this.customUniforms=[{name:\"start\",arrayIndex:this.rank,type:\"int\"}];let t=gt(this.rank),a=va(\"coords\",this.rank),n=va(\"sourceLoc\",this.rank),r=this.rank===1?\"sourceLoc\":`vec2(${n.slice(-2).join()})`,s=`getChannel(getSource(${n.join()}), ${r})`,i=`\n      result.x = ${s};\n      if (++${a[this.rank-1]} < ${e[this.rank-1]}) {\n        ++${n[this.rank-1]};\n        result.y = ${s};\n        --${n[this.rank-1]};\n      }\n    `,o=this.rank===1?\"\":`\n      --${a[this.rank-1]};\n      if (++${a[this.rank-2]} < ${e[this.rank-2]}) {\n        ++${n[this.rank-2]};\n        result.z = ${s};\n        if (++${a[this.rank-1]} < ${e[this.rank-1]}) {\n          ++${n[this.rank-1]};\n          result.w = ${s};\n        }\n      }\n    `,l=this.rank<=4?`sourceLoc = coords +\n            ${t}(${e.map((u,p)=>`start[${p}]`).join()});`:e.map((u,p)=>`${n[p]} = ${a[p]} + start[${p}];`).join(`\n`);this.userCode=`\n      void main() {\n        ${t} coords = getOutputCoords();\n        ${t} sourceLoc;\n        ${l}\n        vec4 result = vec4(0.);\n        ${i}\n        ${o}\n        setOutput(result);\n      }\n    `}};function UH(e,t,a,n){let r=n.texData.get(e.dataId),s=n.makeTensorInfo(a,e.dtype),i=n.texData.get(s.dataId);Object.assign(i,r),i.refCount=1,i.shape=a,i.dtype=e.dtype;let o=It.computeFlatOffset(t,v.computeStrides(e.shape));r.slice&&(o+=r.slice.flatOffset),i.slice={flatOffset:o,origDataId:r.slice&&r.slice.origDataId||e.dataId};let l=n.dataRefCount.get(i.slice.origDataId)||1;return n.dataRefCount.set(i.slice.origDataId,l+1),s}function gu(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{begin:s,size:i}=n,[o,l]=It.parseSliceParams(r,s,i);if(It.assertParamsValid(r,o,l),v.sizeFromShape(l)===0)return a.makeTensorInfo(l,r.dtype,[]);if(a.shouldExecuteOnCPU([r])||r.dtype===\"string\"){let c=a.texData.get(r.dataId),d=PU(c.values,o,l,r.shape,r.dtype);return a.makeTensorInfo(l,r.dtype,d)}let{isPacked:u}=a.texData.get(r.dataId),p=It.isSliceContinous(r.shape,o,l);if(u||!p){let c=W().getBool(\"WEBGL_PACK_ARRAY_OPERATIONS\")?new VH(l):new BH(l),d=[o];return a.runWebGLProgram(c,[r],r.dtype,d)}return a.uploadToGPU(r.dataId),UH(r,o,l,a)}var GH={kernelName:Zl,backendName:\"webgl\",kernelFunc:gu},HH=e=>{let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockShape:s,crops:i}=n;v.assert(r.shape.length<=4,()=>\"batchToSpaceND for rank > 4 with a WebGL backend not implemented yet\");let o=s.reduce((A,y)=>A*y),l=T.getReshaped(r.shape,s,o),u=T.getPermuted(l.length,s.length),p=T.getReshapedPermuted(r.shape,s,o),c=T.getSliceBeginCoords(i,s.length),d=T.getSliceSize(p,i,s.length),h=[],f=ce({inputs:{x:r},backend:a,attrs:{shape:l}}),m=Ia({inputs:{x:f},backend:a,attrs:{perm:u}}),g=ce({inputs:{x:m},backend:a,attrs:{shape:p}}),x=gu({inputs:{x:g},backend:a,attrs:{begin:c,size:d}});return h.push(f),h.push(m),h.push(g),h.forEach(A=>a.disposeIntermediateTensorInfo(A)),x},jH={kernelName:Rl,backendName:\"webgl\",kernelFunc:HH};function qH(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,weights:s}=t,{size:i}=n,o=a.readSync(r.dataId),l=a.readSync(s.dataId),u=L6(o,l,s.dtype,s.shape,i);return a.makeTensorInfo([i],s.dtype,u)}var XH={kernelName:Id,backendName:\"webgl\",kernelFunc:qH};function KH(e){let{inputs:t,backend:a}=e,{s0:n,s1:r}=t,s=a.readSync(n.dataId),i=a.readSync(r.dataId),o=T.assertAndGetBroadcastShape(Array.from(s),Array.from(i));return a.makeTensorInfo([o.length],\"int32\",Int32Array.from(o))}var ZH={kernelName:jc,backendName:\"webgl\",kernelFunc:KH},YH=\"return float(a != b);\",ev=oa({opSnippet:YH,cpuKernelImpl:SU,dtype:\"bool\"}),JH={kernelName:Li,backendName:\"webgl\",kernelFunc:ev};function hp(e){let{inputs:t,backend:a}=e,{input:n}=t,r=a.texData.get(n.dataId);return Za({inputs:{x:r.complexTensorInfos.real},backend:a})}var QH={kernelName:Md,backendName:\"webgl\",kernelFunc:hp},ej=\"return float(int(x));\";function tj(e,t){let a=new qn(e.shape,ej),n=t.runWebGLProgram(a,[e],\"int32\");return{dataId:n.dataId,shape:n.shape,dtype:n.dtype}}function C1(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{dtype:s}=n;if(s===\"complex64\"){if(r.dtype===\"complex64\")return Za({inputs:{x:r},backend:a});let i=fn(r.shape),o=C1({inputs:{x:r},backend:a,attrs:{dtype:\"float32\"}}),l=ls({inputs:{real:o,imag:i},backend:a});return i.dispose(),a.disposeIntermediateTensorInfo(o),l}if(r.dtype===\"complex64\"){let i=hp({inputs:{input:r},backend:a}),o=C1({inputs:{x:i},backend:a,attrs:{dtype:s}});return a.disposeIntermediateTensorInfo(i),o}if(!v.hasEncodingLoss(r.dtype,s)){let i=Za({inputs:{x:r},backend:a});return{dataId:i.dataId,shape:i.shape,dtype:s}}if(a.shouldExecuteOnCPU([r])){let i=a.texData.get(r.dataId).values,[o,l,u]=sU(i,r.shape,r.dtype,s);return a.makeTensorInfo(o,l,u)}if(s===\"int32\")return tj(r,a);if(s===\"bool\"){let i=a.makeTensorInfo([],\"bool\",v.getTypedArrayFromDType(\"bool\",1)),o=ev({inputs:{a:r,b:i},backend:a});return a.disposeIntermediateTensorInfo(i),o}throw new Error(`Error in Cast: failed to cast ${r.dtype} to ${s}`)}var aj={kernelName:ti,backendName:\"webgl\",kernelFunc:C1},Ix=\"return ceil(x);\",nj=Qe({opSnippet:Ix,packedOpSnippet:Ix,cpuKernelImpl:iU}),rj={kernelName:ai,backendName:\"webgl\",kernelFunc:nj},sj=class{constructor(e){this.variableNames=[\"A\"],this.customUniforms=[{name:\"minVal\",type:\"float\"},{name:\"maxVal\",type:\"float\"}],this.outputShape=e,this.userCode=`\n\n      void main() {\n        float value = getAAtOutCoords();\n        if (isnan(value)) {\n          setOutput(value);\n          return;\n        }\n\n        setOutput(clamp(value, minVal, maxVal));\n      }\n    `}},ij=class{constructor(e){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0,this.customUniforms=[{name:\"minVal\",type:\"float\"},{name:\"maxVal\",type:\"float\"}],this.outputShape=e,this.userCode=`\n      void main() {\n        vec4 value = getAAtOutCoords();\n\n        if (any(isnan(value))) {\n          setOutput(value);\n          return;\n        }\n\n        setOutput(clamp(value, vec4(minVal), vec4(maxVal)));\n      }\n    `}};function oj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{clipValueMin:s,clipValueMax:i}=n,o;W().getBool(\"WEBGL_PACK_CLIP\")?o=new ij(r.shape):o=new sj(r.shape);let l=[[s],[i]];return a.runWebGLProgram(o,[r],r.dtype,l)}var lj={kernelName:as,backendName:\"webgl\",kernelFunc:oj},uj=class{constructor(e){this.variableNames=[\"real\",\"imag\"],this.outputShape=e,this.userCode=`\n      void main() {\n        float re = abs(getRealAtOutCoords());\n        float im = abs(getImagAtOutCoords());\n        float mx = max(re, im);\n\n        // sadly the length function in glsl is not underflow-safe\n        // (at least not on Intel GPUs). So the safe solution is\n        // to ensure underflow-safety in all cases.\n        setOutput(\n          mx == 0.0 ? 0.0 : mx * length(vec2(1, min(re, im)/mx))\n        );\n      }\n    `}};function Sx(e,t){return{dataId:t.dataId,dtype:t.dtype,shape:e.shape}}function dj(e){let{inputs:t,backend:a}=e,{x:n}=t,r=a.texData.get(n.dataId),s=new uj(n.shape),i=[Sx(n,r.complexTensorInfos.real),Sx(n,r.complexTensorInfos.imag)];return a.runWebGLProgram(s,i,i[0].dtype)}var pj={kernelName:qc,backendName:\"webgl\",kernelFunc:dj},cj=class{constructor(e){this.outputShape=[],this.outputShape=T.computeOutShape(e,1),this.variableNames=e.map((s,i)=>`T${i}`);let t=new Array(e.length-1);t[0]=e[0][1];for(let s=1;s<t.length;s++)t[s]=t[s-1]+e[s][1];let a=[`if (yC < ${t[0]}) setOutput(getT0(yR, yC));`];for(let s=1;s<t.length;s++){let i=t[s-1];a.push(`else if (yC < ${t[s]}) setOutput(getT${s}(yR, yC-${i}));`)}let n=t.length,r=t[t.length-1];a.push(`else setOutput(getT${n}(yR, yC-${r}));`),this.userCode=`\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int yR = coords.x;\n        int yC = coords.y;\n\n        ${a.join(`\n        `)}\n      }\n    `}},hj=class{constructor(e,t){this.packedInputs=!0,this.packedOutput=!0,this.outputShape=[],this.outputShape=T.computeOutShape(e,t);let a=this.outputShape,n=a.length,r=gt(n),s=va(\"coords\",n),i=[\"x\",\"y\",\"z\",\"w\",\"u\",\"v\"].slice(0,n);this.variableNames=e.map((f,m)=>`T${m}`);let o=new Array(e.length-1);o[0]=e[0][t];for(let f=1;f<o.length;f++)o[f]=o[f-1]+e[f][t];let l=i[t],u=i.slice(-2),p=i.join(),c=`if (${l} < ${o[0]}) {\n        return getChannel(\n            getT0(${p}), vec2(${u.join()}));\n        }`;for(let f=1;f<o.length;f++){let m=o[f-1];c+=`\n        if (${l} < ${o[f]}  && ${l} >= ${o[f-1]}) {\n          return getChannel(\n            getT${f}(${pc(i,l,m)}),\n            vec2(${pc(u,l,m)}));\n        }`}let d=o.length,h=o[o.length-1];c+=`\n        return getChannel(\n          getT${d}(${pc(i,l,h)}),\n          vec2(${pc(u,l,h)}));`,this.userCode=`\n      float getValue(${i.map(f=>\"int \"+f)}) {\n        ${c}\n      }\n\n      void main() {\n        ${r} coords = getOutputCoords();\n        vec4 result = vec4(getValue(${s}), 0., 0., 0.);\n\n        ${s[n-1]} = ${s[n-1]} + 1;\n        if (${s[n-1]} < ${a[n-1]}) {\n          result.g = getValue(${s});\n        }\n\n        ${s[n-2]} = ${s[n-2]} + 1;\n        if (${s[n-2]} < ${a[n-2]}) {\n          result.a = getValue(${s});\n        }\n\n        ${s[n-1]} = ${s[n-1]} - 1;\n        if (${s[n-2]} < ${a[n-2]} &&\n            ${s[n-1]} < ${a[n-1]}) {\n          result.b = getValue(${s});\n        }\n        setOutput(result);\n      }\n    `}};function pc(e,t,a){let n=e.indexOf(t);return e.map((r,s)=>s===n?`${r} - ${a}`:r).join()}function Lh(e){let{inputs:t,backend:a}=e,{input:n}=t,r=a.texData.get(n.dataId);return Za({inputs:{x:r.complexTensorInfos.imag},backend:a})}var fj={kernelName:Rd,backendName:\"webgl\",kernelFunc:Lh};function Zu(e,t,a){let n=e[0].dtype;if(n===\"complex64\"){let h=e.map(A=>hp({inputs:{input:A},backend:a})),f=e.map(A=>Lh({inputs:{input:A},backend:a})),m=Zu(h,t,a),g=Zu(f,t,a),x=ls({inputs:{real:m,imag:g},backend:a});return h.forEach(A=>a.disposeIntermediateTensorInfo(A)),f.forEach(A=>a.disposeIntermediateTensorInfo(A)),a.disposeIntermediateTensorInfo(m),a.disposeIntermediateTensorInfo(g),x}let r=a.shouldExecuteOnCPU(e);if(n===\"string\"&&(r=!0),r){let h=e.map(b=>{let w=[-1,v.sizeFromShape(b.shape.slice(t))];return ce({inputs:{x:b},backend:a,attrs:{shape:w}})}),f=h.map(b=>({vals:a.readSync(b.dataId),shape:b.shape})),m=T.computeOutShape(h.map(b=>b.shape),1),g=h[0].shape[0]===1,x=oU(f,m,n,g),A=T.computeOutShape(e.map(b=>b.shape),t),y=a.makeTensorInfo(A,n,x);return h.forEach(b=>a.disposeIntermediateTensorInfo(b)),y}let s=e.filter(h=>v.sizeFromShape(h.shape)>0),i=W().getBool(\"WEBGL_PACK_ARRAY_OPERATIONS\")&&s[0].shape.length>1;if(s.length===1){let h=i?new qn(e[0].shape,Dr):new Vr(e[0].shape,Dr);return a.runWebGLProgram(h,e,n)}let o=W().getNumber(\"WEBGL_MAX_TEXTURES_IN_SHADER\");if(s.length>o){let h=[];for(let m=0;m<s.length;m+=o){let g=s.slice(m,m+o);h.push(Zu(g,t,a))}let f=Zu(h,t,a);for(let m of h)a.disposeIntermediateTensorInfo(m);return f}if(i){let h=new hj(s.map(f=>f.shape),t);return a.runWebGLProgram(h,s,n)}let{tensors2D:l,outShape:u}=mj(s,t,a),p=new cj(l.map(h=>h.shape)),c=a.runWebGLProgram(p,l,n);l.forEach(h=>a.disposeIntermediateTensorInfo(h));let d=ce({inputs:{x:c},attrs:{shape:u},backend:a});return a.disposeIntermediateTensorInfo(c),d}function mj(e,t,a){let n=T.computeOutShape(e.map(r=>r.shape),t);return{tensors2D:e.map(r=>ce({inputs:{x:r},attrs:{shape:[-1,v.sizeFromShape(r.shape.slice(t))]},backend:a})),outShape:n}}function tv(e){let{inputs:t,backend:a,attrs:n}=e,{axis:r}=n,s=v.parseAxisParam(r,t[0].shape)[0],i=t.map(u=>u.shape);T.assertParamsConsistent(i,s);let o=T.computeOutShape(t.map(u=>u.shape),s);if(v.sizeFromShape(o)===0)return a.makeTensorInfo(o,t[0].dtype,[]);let l=t.filter(u=>v.sizeFromShape(u.shape)>0);return l.length===1?Za({inputs:{x:l[0]},backend:a}):Zu(l,s,a)}var gj={kernelName:Ml,backendName:\"webgl\",kernelFunc:tv},av=class{constructor(e,t=!1,a=null,n=!1,r=!1){this.variableNames=[\"x\",\"W\"],this.outputShape=e.outShape;let s=e.padInfo.top,i=e.padInfo.left,o=e.strideHeight,l=e.strideWidth,u=e.dilationHeight,p=e.dilationWidth,c=e.filterHeight,d=e.filterWidth,h=Math.floor(e.inChannels/4)*4,f=e.inChannels%4,m=e.dataFormat===\"channelsLast\",g=m?1:2,x=m?2:3,A=m?3:1,y=\"\",b=\"\";a&&(n?y=`float activation(float a) {\n          float b = getPreluActivationWeightsAtOutCoords();\n          ${a}\n        }`:r?y=`float activation(float a) {\n          float b = getLeakyreluAlphaAtOutCoords();\n          ${a}\n        }`:y=`\n          float activation(float x) {\n            ${a}\n          }\n        `,b=\"result = activation(result);\");let w=t?\"result += getBiasAtOutCoords();\":\"\";t&&this.variableNames.push(\"bias\"),n&&this.variableNames.push(\"preluActivationWeights\"),r&&this.variableNames.push(\"leakyreluAlpha\"),this.userCode=`\n      ${y}\n\n      const ivec2 strides = ivec2(${o}, ${l});\n      const ivec2 pads = ivec2(${s}, ${i});\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int batch = coords[0];\n        int d2 = coords[${A}];\n\n        ivec2 xRCCorner =\n            ivec2(coords[${g}], coords[${x}]) * strides - pads;\n        int xRCorner = xRCCorner.x;\n        int xCCorner = xRCCorner.y;\n\n        // Convolve x(?, ?, d1) with w(:, :, d1, d2) to get y(yR, yC, d2).\n        // ? = to be determined. : = across all values in that axis.\n        float dotProd = 0.0;\n        for (int wR = 0; wR < ${c}; wR++) {\n          int xR = xRCorner + wR * ${u};\n\n          if (xR < 0 || xR >= ${e.inHeight}) {\n            continue;\n          }\n\n          for (int wC = 0; wC < ${d}; wC++) {\n            int xC = xCCorner + wC * ${p};\n\n            if (xC < 0 || xC >= ${e.inWidth}) {\n              continue;\n            }\n\n            for (int d1 = 0; d1 < ${h}; d1 += 4) {\n              vec4 wValues = vec4(\n                getW(wR, wC, d1, d2),\n                getW(wR, wC, d1 + 1, d2),\n                getW(wR, wC, d1 + 2, d2),\n                getW(wR, wC, d1 + 3, d2)\n              );\n\n              if (${m}) {\n                vec4 xValues = vec4(\n                  getX(batch, xR, xC, d1),\n                  getX(batch, xR, xC, d1 + 1),\n                  getX(batch, xR, xC, d1 + 2),\n                  getX(batch, xR, xC, d1 + 3)\n                );\n                dotProd += dot(xValues, wValues);\n              } else {\n                vec4 xValues = vec4(\n                  getX(batch, d1, xR, xC),\n                  getX(batch, d1 + 1, xR, xC),\n                  getX(batch, d1 + 2, xR, xC),\n                  getX(batch, d1 + 3, xR, xC)\n                );\n                dotProd += dot(xValues, wValues);\n              }\n            }\n\n            if (${f===1}) {\n\n              if (${m}) {\n                dotProd +=\n                    getX(batch, xR, xC, ${h}) *\n                    getW(wR, wC, ${h}, d2);\n              } else {\n                dotProd +=\n                    getX(batch, ${h}, xR, xC) *\n                    getW(wR, wC, ${h}, d2);\n              }\n\n            } else if (${f===2}) {\n              vec2 wValues = vec2(\n                getW(wR, wC, ${h}, d2),\n                getW(wR, wC, ${h} + 1, d2)\n              );\n\n              if (${m}) {\n                vec2 xValues = vec2(\n                  getX(batch, xR, xC, ${h}),\n                  getX(batch, xR, xC, ${h} + 1)\n                );\n                dotProd += dot(xValues, wValues);\n              } else {\n                vec2 xValues = vec2(\n                  getX(batch, ${h}, xR, xC),\n                  getX(batch, ${h} + 1, xR, xC)\n                );\n                dotProd += dot(xValues, wValues);\n              }\n\n            } else if (${f===3}) {\n              vec3 wValues = vec3(\n                getW(wR, wC, ${h}, d2),\n                getW(wR, wC, ${h} + 1, d2),\n                getW(wR, wC, ${h} + 2, d2)\n              );\n\n              if (${m}) {\n                vec3 xValues = vec3(\n                  getX(batch, xR, xC, ${h}),\n                  getX(batch, xR, xC, ${h} + 1),\n                  getX(batch, xR, xC, ${h} + 2)\n                );\n                dotProd += dot(xValues, wValues);\n              } else {\n                vec3 xValues = vec3(\n                  getX(batch, ${h}, xR, xC),\n                  getX(batch, ${h} + 1, xR, xC),\n                  getX(batch, ${h} + 2, xR, xC)\n                );\n                dotProd += dot(xValues, wValues);\n              }\n\n            }\n          }\n        }\n\n        float result = dotProd;\n        ${w}\n        ${b}\n        setOutput(result);\n      }\n    `}},xj=class{constructor(e){this.variableNames=[\"x\",\"W\"],this.outputShape=e.outShape;let t=e.padInfo.front,a=e.padInfo.top,n=e.padInfo.left,r=e.strideDepth,s=e.strideHeight,i=e.strideWidth,o=e.dilationDepth,l=e.dilationHeight,u=e.dilationWidth,p=e.filterDepth,c=e.filterHeight,d=e.filterWidth,h=Math.floor(e.inChannels/4)*4,f=e.inChannels%4;this.userCode=`\n      const ivec3 strides = ivec3(${r}, ${s}, ${i});\n      const ivec3 pads = ivec3(${t}, ${a}, ${n});\n\n      void main() {\n        ivec5 coords = getOutputCoords();\n        int batch = coords.x;\n        int d2 = coords.u;\n\n        ivec3 xFRCCorner = ivec3(coords.y, coords.z, coords.w) * strides - pads;\n        int xFCorner = xFRCCorner.x;\n        int xRCorner = xFRCCorner.y;\n        int xCCorner = xFRCCorner.z;\n\n        // Convolve x(?, ?, ?, d1) with w(:, :, :, d1, d2) to get\n        // y(yF, yR, yC, d2). ? = to be determined. : = across all\n        // values in that axis.\n        float dotProd = 0.0;\n        for (int wF = 0; wF < ${p}; wF++) {\n          int xF = xFCorner + wF * ${o};\n\n          if (xF < 0 || xF >= ${e.inDepth}) {\n            continue;\n          }\n\n          for (int wR = 0; wR < ${c}; wR++) {\n            int xR = xRCorner + wR * ${l};\n\n            if (xR < 0 || xR >= ${e.inHeight}) {\n              continue;\n            }\n\n            for (int wC = 0; wC < ${d}; wC++) {\n              int xC = xCCorner + wC * ${u};\n\n              if (xC < 0 || xC >= ${e.inWidth}) {\n                continue;\n              }\n\n              for (int d1 = 0; d1 < ${h}; d1 += 4) {\n                vec4 xValues = vec4(\n                  getX(batch, xF, xR, xC, d1),\n                  getX(batch, xF, xR, xC, d1 + 1),\n                  getX(batch, xF, xR, xC, d1 + 2),\n                  getX(batch, xF, xR, xC, d1 + 3)\n                );\n                vec4 wValues = vec4(\n                  getW(wF, wR, wC, d1, d2),\n                  getW(wF, wR, wC, d1 + 1, d2),\n                  getW(wF, wR, wC, d1 + 2, d2),\n                  getW(wF, wR, wC, d1 + 3, d2)\n                );\n\n                dotProd += dot(xValues, wValues);\n              }\n\n              if (${f===1}) {\n                dotProd +=\n                  getX(batch, xF, xR, xC, ${h}) *\n                  getW(wF, wR, wC, ${h}, d2);\n              } else if (${f===2}) {\n                vec2 xValues = vec2(\n                  getX(batch, xF, xR, xC, ${h}),\n                  getX(batch, xF, xR, xC, ${h} + 1)\n                );\n                vec2 wValues = vec2(\n                  getW(wF, wR, wC, ${h}, d2),\n                  getW(wF, wR, wC, ${h} + 1, d2)\n                );\n                dotProd += dot(xValues, wValues);\n              } else if (${f===3}) {\n                vec3 xValues = vec3(\n                  getX(batch, xF, xR, xC, ${h}),\n                  getX(batch, xF, xR, xC, ${h} + 1),\n                  getX(batch, xF, xR, xC, ${h} + 2)\n                );\n                vec3 wValues = vec3(\n                  getW(wF, wR, wC, ${h}, d2),\n                  getW(wF, wR, wC, ${h} + 1, d2),\n                  getW(wF, wR, wC, ${h} + 2, d2)\n                );\n                dotProd += dot(xValues, wValues);\n              }\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}},nv=class{constructor(e,t=!1,a=null,n=!1,r=!1){this.variableNames=[\"x\",\"W\"],this.packedInputs=!0,this.packedOutput=!0,this.customUniforms=[{name:\"pads\",type:\"ivec2\"},{name:\"strides\",type:\"ivec2\"},{name:\"dilations\",type:\"ivec2\"},{name:\"inDims\",type:\"ivec2\"}],this.outputShape=e.outShape,this.enableShapeUniforms=Na(this.outputShape.length);let s=e.padInfo.left,i=e.strideWidth,o=e.dilationWidth,l=e.filterHeight,u=e.filterWidth,p=u,c=`\n       int xR; int xC; int xCOffset;\n       vec4 wTexel; vec4 previous; vec4 final;`;for(let m=0;m<u;m++)c+=`\n           vec4 xTexelC${m*2};\n           int xTexelC${m*2}Ready;\n           vec4 xTexelC${m*2+1};\n           int xTexelC${m*2+1}Ready;\n           vec4 xC${m};`;c+=`\n     for (int r = 0; r < ${l}; r++) {\n      for (int d1 = 0; d1 < ${e.inChannels}; d1 += 2) {\n       `;for(let m=0;m<u;m++)c+=`\n           xTexelC${m*2} = vec4(0.0);\n           xTexelC${m*2}Ready = 0;\n           xTexelC${m*2+1} = vec4(0.0);\n           xTexelC${m*2+1}Ready = 0;\n           xC${m} = vec4(0.0);`;c+=`\n         xR = xRCorner + r * dilations[0];\n         if (xR >=0 && xR < inDims[0]) {\n       `;for(let m=0;m<(p+1)/2;m++){let g=m*2;if(c+=`\n           xC = xCCorner + ${g*o};\n           `,i===1){if(g<u&&(s%2===1?(c+=`\n                 xCOffset = xC + 1;\n                 if (xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${g}Ready == 0) {\n                   xTexelC${g} = getX(batch, xR, xCOffset, d1);\n\n                   // Need to manually clear unused channels in case\n                   // we're reading from recycled texture.\n                   if (xCOffset + 1 >= inDims[1]) {\n                     xTexelC${g}.zw = vec2(0.0);\n                   }\n                   xTexelC${g}Ready = 1;\n                 }\n               `,o===1&&g>0?c+=`\n                 xC${g} = vec4(xTexelC${g-2}.zw, xTexelC${g}.xy);\n                 `:c+=`\n                   xCOffset = xC + 1 - 2;\n\n                   if (xCOffset >= 0 && xCOffset < inDims[1]) {\n                     previous = getX(batch, xR, xCOffset, d1);\n\n                     // Need to manually clear unused channels in case\n                     // we're reading from recycled texture.\n                     if (xCOffset + 1 >= inDims[1]) {\n                       previous.zw = vec2(0.0);\n                     }\n\n                     xC${g} = vec4(previous.zw, xTexelC${g}.xy);\n                   } else {\n                     xC${g} = vec4(0.0, 0.0, xTexelC${g}.xy);\n                   }\n                   `):c+=`\n                 if (xC >= 0 && xC < inDims[1] && xTexelC${g}Ready == 0) {\n                   xTexelC${g} = getX(batch, xR, xC, d1);\n                   if (xC + 1 >= inDims[1]) {\n                     xTexelC${g}.zw = vec2(0.0);\n                   }\n                   xTexelC${g}Ready = 1;\n                 }\n\n                 xC${g} = xTexelC${g};\n                 `,g+1<u)){let x=s%2===0?v.nearestLargerEven(o):o;o%2===0&&s%2===1||o%2!==0&&s%2!==1?(c+=`\n                   xCOffset = xC + imod(pads[1], 2) + ${x};\n\n                   if (xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${g+1}Ready == 0) {\n                     xTexelC${g+1} = getX(batch, xR, xCOffset, d1);\n\n                     // Need to manually clear unused channels in case\n                     // we're reading from recycled texture.\n                     if (xCOffset + 1 >= inDims[1]) {\n                       xTexelC${g+1}.zw = vec2(0.0);\n                     }\n                     xTexelC${g+1}Ready = 1;\n                   }\n                   `,o>1?c+=`\n                     xCOffset -= 2;\n                     if (xCOffset >= 0 && xCOffset < inDims[1]) {\n                      previous = getX(batch, xR, xCOffset, d1);\n                      xC${g+1} = vec4(previous.zw, xTexelC${g+1}.xy);\n                     } else {\n                      xC${g+1} = vec4(0.0, 0.0, xTexelC${g+1}.xy);\n                     }\n                     `:c+=`\n                     xC${g+1} = vec4(xTexelC${g}.zw, xTexelC${g+1}.xy);\n                     `):x===1?c+=`\n                     xC${g+1} = xTexelC${g};\n                     `:c+=`\n                     xCOffset = xC + ${x};\n\n                     if (xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${g+1}Ready == 0) {\n                       xTexelC${g+1} = getX(batch, xR, xCOffset, d1);\n                       if (xCOffset + 1 >= inDims[1]) {\n                         xTexelC${g+1}.zw = vec2(0.0);\n                       }\n                       xTexelC${g+1}Ready = 1;\n                     }\n\n                     xC${g+1} = xTexelC${g+1};\n                     `}}else g<u&&(s%2===1?(c+=`\n                 xCOffset = xC + 1 - strides[1];\n                 if(xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${g}Ready == 0) {\n                   xTexelC${g} = getX(batch, xR, xCOffset, d1);\n                   // Need to manually clear unused channels in case\n                   // we're reading from recycled texture.\n                   if (xCOffset + 1 >= inDims[1]) {\n                     xTexelC${g}.zw = vec2(0.0);\n                   }\n                   xTexelC${g}Ready = 1;\n                 }\n\n                 if(xC + 1 >= 0 && xC + 1 < inDims[1] && xTexelC${g+1}Ready == 0) {\n                   xTexelC${g+1} = getX(batch, xR, xC + 1, d1);\n                   // Need to manually clear unused channels in case\n                   // we're reading from recycled texture.\n                   if (xC + 2 >= inDims[1]) {\n                     xTexelC${g+1}.zw = vec2(0.0);\n                   }\n                   xTexelC${g+1}Ready = 1;\n                 }\n\n                 xC${g} = vec4(xTexelC${g}.zw, xTexelC${g+1}.zw);\n               `,g+1<u&&(c+=`\n                   final = vec4(0.0);\n                   xCOffset = xC + 1 + strides[1];\n                   if(xCOffset >= 0 && xCOffset < inDims[1]) {\n                     final = getX(batch, xR, xCOffset, d1);\n                   }\n                   xC${g+1} = vec4(xTexelC${g+1}.xy, final.xy);\n                 `)):(c+=`\n                 if(xC >= 0 && xC < inDims[1] && xTexelC${g}Ready == 0) {\n                   xTexelC${g} = getX(batch, xR, xC, d1);\n                   if (xC + 1 >= inDims[1]) {\n                     xTexelC${g}.zw = vec2(0.0);\n                   }\n                   xTexelC${g}Ready = 1;\n                 }\n\n                 xCOffset = xC + strides[1];\n                 if(xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${g+1}Ready == 0) {\n                   xTexelC${g+1} = getX(batch, xR, xCOffset, d1);\n                   if (xCOffset + 1 >= inDims[1]) {\n                     xTexelC${g+1}.zw = vec2(0.);\n                   }\n                   xTexelC${g+1}Ready = 1;\n                 }\n\n                 xC${g} = vec4(\n                   xTexelC${g}.xy, xTexelC${g+1}.xy);\n               `,g+1<u&&(c+=`\n                   xC${g+1} = vec4(xTexelC${g}.zw, xTexelC${g+1}.zw);\n                 `)));g<u&&(c+=`\n             wTexel = getW(r, ${g}, d1, d2);\n             dotProd += xC${g}.xxzz * vec4(wTexel.xy, wTexel.xy);\n             if(d1 + 1 < ${e.inChannels}) {\n               dotProd += xC${g}.yyww * vec4(wTexel.zw, wTexel.zw);\n             }\n           `,g+1<u&&(c+=`\n               wTexel = getW(r, ${g+1}, d1, d2);\n               dotProd += xC${g+1}.xxzz * vec4(wTexel.xy, wTexel.xy);\n               if(d1 + 1 < ${e.inChannels}) {\n                 dotProd += xC${g+1}.yyww * vec4(wTexel.zw, wTexel.zw);\n               }\n             `))}c+=`\n     }\n   `,c+=`\n     }\n   `,c+=`\n     }\n   `;let d=\"\",h=\"\";a&&(n?d=`vec4 activation(vec4 a) {\n           vec4 b = getPreluActivationWeightsAtOutCoords();\n           ${a}\n         }`:r?d=`vec4 activation(vec4 a) {\n           vec4 b = getLeakyreluAlphaAtOutCoords();\n           ${a}\n         }`:d=`vec4 activation(vec4 x) {\n           ${a}\n         }`,h=\"result = activation(result);\");let f=t?\"result += getBiasAtOutCoords();\":\"\";t&&this.variableNames.push(\"bias\"),n&&this.variableNames.push(\"preluActivationWeights\"),r&&this.variableNames.push(\"leakyreluAlpha\"),this.userCode=`\n       ${d}\n\n       void main() {\n         ivec4 coords = getOutputCoords();\n         int batch = coords.x;\n         ivec2 xRCCorner = coords.yz * strides - pads;\n         int d2 = coords.w;\n         int xRCorner = xRCCorner.x;\n         int xCCorner = xRCCorner.y;\n\n         //intialize dotProd with a small epsilon seems to reduce GPU accuracy loss.\n         vec4 dotProd = vec4(0.000000000000001);\n\n         ${c}\n\n         vec4 result = dotProd - vec4(0.000000000000001);\n         ${f}\n         ${h}\n         setOutput(result);\n       }\n     `}},Aj=class{constructor(e,t){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0,this.customUniforms=[{name:\"inputShape\",type:\"ivec4\"},{name:\"pad\",type:\"ivec2\"},{name:\"stride\",type:\"ivec2\"},{name:\"dilation\",type:\"ivec2\"},{name:\"inChannels\",type:\"int\"},{name:\"itemsPerBlockRow\",type:\"int\"},{name:\"outWidth\",type:\"int\"}],this.outputShape=e,this.enableShapeUniforms=Na(this.outputShape.length);let{dataFormat:a}=t,n=Ca(),r=a===\"channelsLast\",s=r?1:2,i=r?2:3,o=this.enableShapeUniforms?\"if(blockIndex < outShape[2] && pos < outShape[1]) {\":`if(blockIndex < ${e[2]} && pos < ${e[1]}) {`,l=\"\";for(let u=0;u<=1;u++)for(let p=0;p<=1;p++)l+=`\n          blockIndex = rc.z + ${p};\n          pos = rc.y + ${u};\n\n          ${o}\n            offsetY = int(blockIndex / outWidth) * stride[0] - pad[0];\n            d0 = offsetY + dilation[0] * (pos / itemsPerBlockRow);\n\n            if(d0 < inputShape[${s}] && d0 >= 0) {\n              // Use custom imod instead mod. On Intel GPU, mod may generate\n              // unexpected value.\n              // https://github.com/tensorflow/tfjs/issues/5447\n              offsetX = imod(blockIndex, outWidth) * stride[1] - pad[1];\n              d1 = offsetX + dilation[1] * (imod(pos, itemsPerBlockRow) /\n                  inChannels);\n\n              if(d1 < inputShape[${i}] && d1 >= 0) {\n\n                ch = imod(pos, inChannels);\n\n                if (${r}) {\n                  innerDims = vec2(d1, ch);\n                  result[${u*2+p}] = getChannel(\n                    getA(rc.x, d0, int(innerDims.x),\n                    int(innerDims.y)), innerDims);\n                } else {\n                  innerDims = vec2(d0, d1);\n                  result[${u*2+p}] = getChannel(\n                    getA(rc.x, ch, int(innerDims.x),\n                    int(innerDims.y)), innerDims);\n                }\n              }\n            }\n          }\n        `;this.userCode=`\n      void main() {\n        ivec3 rc = getOutputCoords();\n\n        vec4 result = vec4(0);\n\n        int blockIndex, pos, offsetY, d0, offsetX, d1, ch;\n        vec2 innerDims;\n\n        ${l}\n\n        ${n.output} = result;\n      }\n    `}};function zc(e,t){let a=e.length;return a>=3?t?[...e.slice(0,-3),e[a-3]*e[a-2],e[a-1]]:[...e.slice(0,-3),e[a-3],e[a-2]*e[a-1]]:!t&&a===1&&e[0]>1?[e[0],1]:null}function rv({x:e,filter:t,convInfo:a,backend:n,bias:r=null,preluActivationWeights:s=null,leakyreluAlpha:i=0,activation:o=null}){let l=e.shape,u=n.texData.get(e.dataId),p=a.inChannels,c=l[0]*l[1]*l[2],d=a.outChannels,h=a.dataFormat===\"channelsLast\",f=!1,m=!1,g,x=[];if(s!=null){let A=zc(s.shape,h);A!=null&&(s=ce({inputs:{x:s},backend:n,attrs:{shape:A}}),x.push(s))}if(r!=null){let A=zc(r.shape,h);A!=null&&(r=ce({inputs:{x:r},backend:n,attrs:{shape:A}}),x.push(r))}if(!((c===1||d===1)&&p>Z6)&&u.isPacked&&h&&u.texture!=null&&l[2]%2!==0&&v.arraysEqual(u.shape.slice(-3),l.slice(-3))){let A=l[0]*l[1]*(l[2]+1),y={dataId:e.dataId,shape:[1,A,a.inChannels],dtype:e.dtype},b=u.shape;u.shape=u.shape.slice(),u.shape[u.shape.length-2]++,v.assert(md(u.shape,y.shape),()=>`packed reshape ${u.shape} to ${y.shape} isn't free`);let w=ce({inputs:{x:t},backend:n,attrs:{shape:[1,a.inChannels,a.outChannels]}});x.push(w);let S=Dc({a:y,b:w,backend:n,transposeA:f,transposeB:m,bias:r,activation:o,preluActivationWeights:s,leakyreluAlpha:i}),C=n.texData.get(S.dataId);v.assert(C.isPacked,()=>\"batchMatMul result is expected to be packed\"),u.shape=b,C.shape=a.outShape,g=Za({inputs:{x:S},backend:n}),g.shape=a.outShape,x.push(S)}else{let A=a.outHeight*a.outWidth,y=ce({inputs:{x:e},backend:n,attrs:{shape:h?[a.batchSize,A,a.inChannels]:[a.batchSize,a.inChannels,A]}}),b=ce({inputs:{x:t},backend:n,attrs:{shape:[1,a.inChannels,a.outChannels]}}),w=Dc({a:h?y:b,b:h?b:y,transposeA:!h,transposeB:m,backend:n,bias:r,activation:o,preluActivationWeights:s,leakyreluAlpha:i});g=ce({inputs:{x:w},backend:n,attrs:{shape:a.outShape}}),x.push(y),x.push(b),x.push(w)}for(let A of x)n.disposeIntermediateTensorInfo(A);return g}function sv({x:e,filter:t,convInfo:a,backend:n,bias:r=null,preluActivationWeights:s=null,leakyreluAlpha:i=0,activation:o=null}){let{filterWidth:l,filterHeight:u,inChannels:p,outWidth:c,outHeight:d,dataFormat:h}=a,f=h===\"channelsLast\",m=l*u*p,g=d*c,x=[a.batchSize,m,g],A=!0,y=!1,b=[];if(s!=null){let j=zc(s.shape,f);j!=null&&(s=ce({inputs:{x:s},backend:n,attrs:{shape:j}}),b.push(s))}if(r!=null){let j=zc(r.shape,f);j!=null&&(r=ce({inputs:{x:r},backend:n,attrs:{shape:j}}),b.push(r))}let w=ce({inputs:{x:t},backend:n,attrs:{shape:[1,m,v.sizeFromShape(t.shape)/m]}});b.push(w);let S=new Aj(x,a),C=[e.shape,[a.padInfo.top,a.padInfo.left],[a.strideHeight,a.strideWidth],[a.dilationHeight,a.dilationWidth],[a.inChannels],[a.filterWidth*a.inChannels],[a.outWidth]],E=n.runWebGLProgram(S,[e],\"float32\",C),_=ce({inputs:{x:E},backend:n,attrs:{shape:x}});b.push(E),b.push(_);let $=r!=null,M=s!=null,I=o===\"leakyrelu\",N=o?gd(o,!0):null,O=new K6(f?_.shape:w.shape,f?w.shape:_.shape,f?[a.batchSize,g,a.outChannels]:[a.batchSize,a.outChannels,g],A,y,$,N,M,I),L=f?[_,w]:[w,_];if(r&&L.push(r),M&&L.push(s),I){let j=n.makeTensorInfo([],\"float32\",v.createScalarValue(i,\"float32\"));L.push(j),b.push(j)}let B=n.runWebGLProgram(O,L,\"float32\"),G=ce({inputs:{x:B},backend:n,attrs:{shape:a.outShape}});b.push(B);for(let j of b)n.disposeIntermediateTensorInfo(j);return G}function yj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dataFormat:l,dilations:u,dimRoundingMode:p}=n,c=T.convertConv2DDataFormat(l),d=T.computeConv2DInfo(r.shape,s.shape,i,u,o,p,!1,c),h;if(d.filterHeight===1&&d.filterWidth===1&&d.dilationHeight===1&&d.dilationWidth===1&&d.strideHeight===1&&d.strideWidth===1&&(d.padInfo.type===\"SAME\"||d.padInfo.type===\"VALID\"))h=rv({x:r,filter:s,convInfo:d,backend:a});else if(d.strideWidth<=2&&c===\"channelsLast\"&&W().getBool(\"WEBGL_EXP_CONV\")){let m=new nv(d),g=[[d.padInfo.top,d.padInfo.left],[d.strideHeight,d.strideWidth],[d.dilationHeight,d.dilationWidth],[d.inHeight,d.inWidth]];h=a.runWebGLProgram(m,[r,s],\"float32\",g)}else if(W().getBool(\"WEBGL_CONV_IM2COL\"))h=sv({x:r,filter:s,convInfo:d,backend:a});else{let m=new av(d);h=a.runWebGLProgram(m,[r,s],\"float32\")}let f=ce({inputs:{x:h},backend:a,attrs:{shape:d.outShape}});return a.disposeIntermediateTensorInfo(h),f}var bj={kernelName:ni,backendName:\"webgl\",kernelFunc:yj},vj=class{constructor(e){this.variableNames=[\"x\",\"dy\"],this.outputShape=e.filterShape;let t=e.strideHeight,a=e.strideWidth,n=e.padInfo.top,r=e.padInfo.left,s=e.dataFormat===\"channelsLast\";this.userCode=`\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int wR = coords.x;\n        int wC = coords.y;\n        int d1 = coords.z;\n        int d2 = coords.w;\n\n        // Convolve x(?, ?, d1) with dy(:, :, d2) to get dw(wR, wC, d1, d2).\n        // ? = to be determined. : = across all values in that axis.\n        float dotProd = 0.0;\n\n        for (int b = 0; b < ${e.batchSize}; b++) {\n          for (int yR = 0; yR < ${e.outHeight}; yR++) {\n            int xR = wR + yR * ${t} - ${n};\n\n            if (xR < 0 || xR >= ${e.inHeight}) {\n              continue;\n            }\n\n            for (int yC = 0; yC < ${e.outWidth}; yC++) {\n              int xC = wC + yC * ${a} - ${r};\n\n              if (xC < 0 || xC >= ${e.inWidth}) {\n                continue;\n              }\n\n              if (${s}) {\n                float dyValue = getDy(b, yR, yC, d2);\n                float xValue = getX(b, xR, xC, d1);\n                dotProd += (xValue * dyValue);\n              } else {\n                float dyValue = getDy(b, d2, yR, yC);\n                float xValue = getX(b, d1, xR, xC);\n                dotProd += (xValue * dyValue);\n              }\n\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}},wj=class{constructor(e){this.variableNames=[\"dy\",\"W\"],this.outputShape=e.inShape;let t=e.filterHeight,a=e.filterWidth,n=e.strideHeight,r=e.strideWidth,s=e.dataFormat===\"channelsLast\",i=t-1-e.padInfo.top,o=a-1-e.padInfo.left,l=s?1:2,u=s?2:3,p=s?3:1;this.userCode=`\n      const ivec2 pads = ivec2(${i}, ${o});\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int batch = coords[0];\n        int d1 = coords[${p}];\n\n        ivec2 dyCorner = ivec2(coords[${l}], coords[${u}]) - pads;\n        int dyRCorner = dyCorner.x;\n        int dyCCorner = dyCorner.y;\n\n        // Convolve dy(?, ?, d2) with w(:, :, d1, d2) to compute dx(xR, xC, d1).\n        // ? = to be determined. : = across all values in that axis.\n        float dotProd = 0.0;\n        for (int wR = 0; wR < ${t}; wR++) {\n          float dyR = float(dyRCorner + wR) / ${n}.0;\n\n          if (dyR < 0.0 || dyR >= ${e.outHeight}.0 || fract(dyR) > 0.0) {\n            continue;\n          }\n          int idyR = int(dyR);\n\n          int wRPerm = ${t} - 1 - wR;\n\n          for (int wC = 0; wC < ${a}; wC++) {\n            float dyC = float(dyCCorner + wC) / ${r}.0;\n\n            if (dyC < 0.0 || dyC >= ${e.outWidth}.0 ||\n                fract(dyC) > 0.0) {\n              continue;\n            }\n            int idyC = int(dyC);\n\n            int wCPerm = ${a} - 1 - wC;\n\n            for (int d2 = 0; d2 < ${e.outChannels}; d2++) {\n\n              if (${s}) {\n                float xValue = getDy(batch, idyR, idyC, d2);\n                float wValue = getW(wRPerm, wCPerm, d1, d2);\n                dotProd += xValue * wValue;\n              } else {\n                float xValue = getDy(batch, d2, idyR, idyC);\n                float wValue = getW(wRPerm, wCPerm, d1, d2);\n                dotProd += xValue * wValue;\n              }\n\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}},kj=class{constructor(e){this.variableNames=[\"x\",\"dy\"],this.outputShape=e.filterShape;let t=e.strideDepth,a=e.strideHeight,n=e.strideWidth,r=e.padInfo.front,s=e.padInfo.top,i=e.padInfo.left;this.userCode=`\n      void main() {\n        ivec5 coords = getOutputCoords();\n        int wF = coords.x;\n        int wR = coords.y;\n        int wC = coords.z;\n        int d1 = coords.w;\n        int d2 = coords.u;\n\n        float dotProd = 0.0;\n\n        for (int b = 0; b < ${e.batchSize}; b++) {\n          for (int yF = 0; yF < ${e.outDepth}; yF++) {\n            int xF = wF + yF * ${t} - ${r};\n\n            if (xF < 0 || xF >= ${e.inDepth}) {\n              continue;\n            }\n\n            for (int yR = 0; yR < ${e.outHeight}; yR++) {\n              int xR = wR + yR * ${a} - ${s};\n\n              if (xR < 0 || xR >= ${e.inHeight}) {\n                continue;\n              }\n\n              for (int yC = 0; yC < ${e.outWidth}; yC++) {\n                int xC = wC + yC * ${n} - ${i};\n\n                if (xC < 0 || xC >= ${e.inWidth}) {\n                  continue;\n                }\n\n                float dyValue = getDy(b, yF, yR, yC, d2);\n                float xValue = getX(b, xF, xR, xC, d1);\n                dotProd += (xValue * dyValue);\n              }\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}},Ij=class{constructor(e){this.variableNames=[\"dy\",\"W\"],this.outputShape=e.inShape;let t=e.filterDepth,a=e.filterHeight,n=e.filterWidth,r=e.strideDepth,s=e.strideHeight,i=e.strideWidth,o=t-1-e.padInfo.front,l=a-1-e.padInfo.top,u=n-1-e.padInfo.left;this.userCode=`\n      const ivec3 pads = ivec3(${o}, ${l}, ${u});\n\n      void main() {\n        ivec5 coords = getOutputCoords();\n        int batch = coords.x;\n        int d1 = coords.u;\n\n\n        ivec3 dyCorner = ivec3(coords.y, coords.z, coords.w) - pads;\n        int dyFCorner = dyCorner.x;\n        int dyRCorner = dyCorner.y;\n        int dyCCorner = dyCorner.z;\n\n        float dotProd = 0.0;\n        for (int wF = 0; wF < ${t}; wF++) {\n          float dyF = float(dyFCorner + wF) / ${r}.0;\n\n          if (dyF < 0.0 || dyF >= ${e.outDepth}.0 || fract(dyF) > 0.0) {\n            continue;\n          }\n          int idyF = int(dyF);\n\n          int wFPerm = ${t} - 1 - wF;\n\n          for (int wR = 0; wR < ${a}; wR++) {\n            float dyR = float(dyRCorner + wR) / ${s}.0;\n\n            if (dyR < 0.0 || dyR >= ${e.outHeight}.0 ||\n              fract(dyR) > 0.0) {\n              continue;\n            }\n            int idyR = int(dyR);\n\n            int wRPerm = ${a} - 1 - wR;\n\n            for (int wC = 0; wC < ${n}; wC++) {\n              float dyC = float(dyCCorner + wC) / ${i}.0;\n\n              if (dyC < 0.0 || dyC >= ${e.outWidth}.0 ||\n                  fract(dyC) > 0.0) {\n                continue;\n              }\n              int idyC = int(dyC);\n\n              int wCPerm = ${n} - 1 - wC;\n\n              for (int d2 = 0; d2 < ${e.outChannels}; d2++) {\n                float xValue = getDy(batch, idyF, idyR, idyC, d2);\n                float wValue = getW(wFPerm, wRPerm, wCPerm, d1, d2);\n                dotProd += xValue * wValue;\n              }\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}};function Sj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,dy:s}=t,{strides:i,pad:o,dataFormat:l,dimRoundingMode:u,filterShape:p}=n,c=T.convertConv2DDataFormat(l),d=T.computeConv2DInfo(r.shape,p,i,1,o,u,!1,c),h=new vj(d);return a.runWebGLProgram(h,[r,s],\"float32\")}var Tj={kernelName:Xc,backendName:\"webgl\",kernelFunc:Sj};function Cj(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,filter:s}=t,{inputShape:i,strides:o,pad:l,dataFormat:u,dimRoundingMode:p}=n,c=T.convertConv2DDataFormat(u),d=T.computeConv2DInfo(i,s.shape,o,1,l,p,!1,c),h=new wj(d);return a.runWebGLProgram(h,[r,s],\"float32\")}var Nj={kernelName:ri,backendName:\"webgl\",kernelFunc:Cj};function Ej(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dilations:l}=n,u=T.computeConv3DInfo(r.shape,s.shape,i,l,o),p=new xj(u);return a.runWebGLProgram(p,[r,s],\"float32\")}var Rj={kernelName:Kc,backendName:\"webgl\",kernelFunc:Ej};function Mj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,dy:s}=t,{strides:i,pad:o,filterShape:l}=n,u=T.computeConv3DInfo(r.shape,l,i,1,o),p=new kj(u);return a.runWebGLProgram(p,[r,s],\"float32\")}var $j={kernelName:H1,backendName:\"webgl\",kernelFunc:Mj};function _j(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,filter:s}=t,{pad:i,strides:o,inputShape:l}=n,u=T.computeConv3DInfo(l,s.shape,o,1,i),p=new Ij(u);return a.runWebGLProgram(p,[r,s],\"float32\")}var Pj={kernelName:Zc,backendName:\"webgl\",kernelFunc:_j},Fj=mu+`\n  return cos(x);\n`,Oj=Qe({opSnippet:Fj}),Dj={kernelName:si,backendName:\"webgl\",kernelFunc:Oj},zj=`\n  float e2x = exp(-x);\n  return (e2x + 1.0 / e2x) / 2.0;\n`,Lj=Qe({opSnippet:zj}),Bj={kernelName:ii,backendName:\"webgl\",kernelFunc:Lj},Wj=class{constructor(e,t,a,n,r){this.variableNames=[\"Image\",\"Boxes\",\"BoxInd\"],this.outputShape=[];let[s,i,o,l]=e,[u]=t,[p,c]=a;this.outputShape=[u,p,c,l];let d=n===\"bilinear\"?1:0,[h,f]=[`${i-1}.0`,`${o-1}.0`],[m,g,x]=p>1?[`${(i-1)/(p-1)}`,\"(y2-y1) * height_ratio\",`y1*${h} + float(y)*(height_scale)`]:[\"0.0\",\"0.0\",`0.5 * (y1+y2) * ${h}`],[A,y,b]=c>1?[`${(o-1)/(c-1)}`,\"(x2-x1) * width_ratio\",`x1*${f} + float(x)*(width_scale)`]:[\"0.0\",\"0.0\",`0.5 * (x1+x2) * ${f}`];this.userCode=`\n      const float height_ratio = float(${m});\n      const float width_ratio = float(${A});\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int y = coords[1];\n        int x = coords[2];\n        int d = coords[3];\n\n        // get box vals\n        float y1 = getBoxes(b,0);\n        float x1 = getBoxes(b,1);\n        float y2 = getBoxes(b,2);\n        float x2 = getBoxes(b,3);\n\n        // get image in batch index\n        int bInd = round(getBoxInd(b));\n        if(bInd < 0 || bInd >= ${s}) {\n          return;\n        }\n\n        float height_scale = ${g};\n        float width_scale = ${y};\n\n        float in_y = ${x};\n        if( in_y < 0.0 || in_y > ${h} ) {\n          setOutput(float(${r}));\n          return;\n        }\n        float in_x = ${b};\n        if( in_x < 0.0 || in_x > ${f} ) {\n          setOutput(float(${r}));\n          return;\n        }\n\n        vec2 sourceFracIndexCR = vec2(in_x,in_y);\n        if(${d} == 1) {\n          // Compute the four integer indices.\n          ivec2 sourceFloorCR = ivec2(sourceFracIndexCR);\n          ivec2 sourceCeilCR = ivec2(ceil(sourceFracIndexCR));\n\n          float topLeft = getImage(b, sourceFloorCR.y, sourceFloorCR.x, d);\n          float bottomLeft = getImage(b, sourceCeilCR.y, sourceFloorCR.x, d);\n          float topRight = getImage(b, sourceFloorCR.y, sourceCeilCR.x, d);\n          float bottomRight = getImage(b, sourceCeilCR.y, sourceCeilCR.x, d);\n\n          vec2 fracCR = sourceFracIndexCR - vec2(sourceFloorCR);\n\n          float top = topLeft + (topRight - topLeft) * fracCR.x;\n          float bottom = bottomLeft + (bottomRight - bottomLeft) * fracCR.x;\n          float newValue = top + (bottom - top) * fracCR.y;\n          setOutput(newValue);\n        } else {\n          // Compute the coordinators of nearest neighbor point.\n          ivec2 sourceNearestCR = ivec2(floor(\n            sourceFracIndexCR + vec2(0.5,0.5)));\n          float newValue = getImage(b, sourceNearestCR.y, sourceNearestCR.x, d);\n          setOutput(newValue);\n        }\n      }\n    `}},Vj=e=>{let{inputs:t,backend:a,attrs:n}=e,{image:r,boxes:s,boxInd:i}=t,{cropSize:o,method:l,extrapolationValue:u}=n,p=new Wj(r.shape,s.shape,o,l,u);return a.runWebGLProgram(p,[r,s,i],\"float32\")},Uj={kernelName:ui,backendName:\"webgl\",kernelFunc:Vj},Ad;(function(e){e.Prod=\"*\",e.Sum=\"+\"})(Ad||(Ad={}));var Tx=class{constructor(e,t,a,n){this.op=e,this.outputShape=t,this.variableNames=[\"x\"],this.customUniforms=[{name:\"index\",type:\"float\"}];let r=this.outputShape.length,s=this.op===Ad.Prod?\"1.0\":\"0.0\",i=a?s:`getX(${Cx(r,\"coords\",this.op)})`,o=this.outputShape[this.outputShape.length-1],l=\"\",u=\"\";a?(l=n?`end != ${o-1}`:\"end != 0\",u=n?\"end + 1\":\"end - 1\"):(l=n?`end + pow2 < ${o}`:\"end >= pow2\",u=n?\"end + pow2\":\"end - pow2\"),this.userCode=`\n      void main() {\n        ${gt(r)} coords = getOutputCoords();\n        int end = ${Nx(r,\"coords\",this.op)};\n        float val = ${i};\n        int pow2 = int(pow(2.0, index));\n        if (${l}) {\n          int idx = ${u};\n          ${Nx(r,\"coords\",this.op)} = idx;\n          val ${this.op}= getX(${Cx(r,\"coords\",this.op)});\n        }\n        setOutput(val);\n      }\n    `}};function Cx(e,t,a){if(e===1)return`${t}`;if(e===2)return`${t}.x, ${t}.y`;if(e===3)return`${t}.x, ${t}.y, ${t}.z`;if(e===4)return`${t}.x, ${t}.y, ${t}.z, ${t}.w`;throw new Error(`Cumulative ${a} for rank ${e} is not yet supported`)}function Nx(e,t,a){if(e===1)return`${t}`;if(e===2)return`${t}.y`;if(e===3)return`${t}.z`;if(e===4)return`${t}.w`;throw new Error(`Cumulative ${a} for rank ${e} is not yet supported`)}function iv(e,t,a,n,r,s){let i=t.shape.length,o=T.getAxesPermutation([n],i),l=t;o!=null&&(l=Ia({inputs:{x:t},backend:a,attrs:{perm:o}}));let u=T.getInnerMostAxes(1,i)[0];if(u!==i-1)throw new Error(`WebGL cumprod shader expects an inner-most axis=${t.shape.length-1} but got axis=${n}`);let p=l.shape[u],c=Za({inputs:{x:l},backend:a});for(let d=0;d<=Math.ceil(Math.log2(p))-1;d++){let h=new Tx(e,l.shape,!1,s),f=[[d]],m=c;c=a.runWebGLProgram(h,[c],c.dtype,f),a.disposeIntermediateTensorInfo(m)}if(r){let d=new Tx(e,l.shape,r,s),h=c;c=a.runWebGLProgram(d,[c],c.dtype),a.disposeIntermediateTensorInfo(h)}if(o!=null){let d=T.getUndoAxesPermutation(o),h=Ia({inputs:{x:c},backend:a,attrs:{perm:d}});return a.disposeIntermediateTensorInfo(c),a.disposeIntermediateTensorInfo(l),h}return c}function Gj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,exclusive:i,reverse:o}=n;return iv(Ad.Prod,r,a,s,i,o)}var Hj={kernelName:oi,backendName:\"webgl\",kernelFunc:Gj};function jj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,exclusive:i,reverse:o}=n;return iv(Ad.Sum,r,a,s,i,o)}var qj={kernelName:li,backendName:\"webgl\",kernelFunc:jj};function Xj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,weights:s}=t,{size:i,binaryOutput:o}=n;if(r.shape.length===1){let l=a.readSync(r.dataId),u=a.readSync(s.dataId),p=L6(l,u,s.dtype,s.shape,i);return a.makeTensorInfo([i],s.dtype,p)}else if(r.shape.length===2){let l=a.bufferSync(r),u=a.bufferSync(s),p=rU(l,u,i,o);return a.makeTensorInfo(p.shape,s.dtype,p.values)}throw new Error(`Error in denseBincount: input must be at most rank 2, but got rank${r.shape.length}.`)}var Kj={kernelName:Td,backendName:\"webgl\",kernelFunc:Xj},Zj=class{constructor(e,t,a){this.variableNames=[\"x\"],this.outputShape=[],this.outputShape=e,this.blockSize=t,this.dataFormat=a,this.userCode=`\n    void main() {\n      ivec4 coords = getOutputCoords();\n      int b = coords[0];\n      int h = ${this.getHeightCoordString()};\n      int w = ${this.getWidthCoordString()};\n      int d = ${this.getDepthCoordString()};\n\n      int in_h = h / ${t};\n      int offset_h = imod(h, ${t});\n      int in_w = w / ${t};\n      int offset_w = imod(w, ${t});\n      int offset_d = (offset_h * ${t} + offset_w) *\n        ${this.getOutputDepthSize()};\n      int in_d = d + offset_d;\n\n      float result = ${this.getInputSamplingString()};\n      setOutput(result);\n    }\n  `}getHeightCoordString(){return this.dataFormat===\"NHWC\"?\"coords[1]\":\"coords[2]\"}getWidthCoordString(){return this.dataFormat===\"NHWC\"?\"coords[2]\":\"coords[3]\"}getDepthCoordString(){return this.dataFormat===\"NHWC\"?\"coords[3]\":\"coords[1]\"}getOutputDepthSize(){return this.dataFormat===\"NHWC\"?this.outputShape[3]:this.outputShape[1]}getInputSamplingString(){return this.dataFormat===\"NHWC\"?\"getX(b, in_h, in_w, in_d)\":\"getX(b, in_d, in_h, in_w)\"}};function Yj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockSize:s,dataFormat:i}=n,o=r.shape[0],l=i===\"NHWC\"?r.shape[1]:r.shape[2],u=i===\"NHWC\"?r.shape[2]:r.shape[3],p=i===\"NHWC\"?r.shape[3]:r.shape[1],c=l*s,d=u*s,h=p/(s*s),f=i===\"NHWC\"?[o,c,d,h]:[o,h,c,d],m=new Zj(f,s,i);return a.runWebGLProgram(m,[r],r.dtype)}var Jj={kernelName:di,backendName:\"webgl\",kernelFunc:Yj},ov=class{constructor(e,t=!1,a=null,n=!1,r=!1){this.variableNames=[\"x\",\"W\"],this.customUniforms=[{name:\"pads\",type:\"ivec2\"},{name:\"strides\",type:\"ivec2\"},{name:\"dilations\",type:\"ivec2\"},{name:\"inDims\",type:\"ivec2\"}],this.outputShape=e.outShape,this.enableShapeUniforms=Na(this.outputShape.length);let s=e.filterHeight,i=e.filterWidth,o=e.outChannels/e.inChannels,l=\"\",u=\"\";a&&(n?l=`float activation(float a) {\n          float b = getPreluActivationWeightsAtOutCoords();\n          ${a}\n        }`:r?l=`float activation(float a) {\n          float b = getLeakyreluAlphaAtOutCoords();\n          ${a}\n        }`:l=`\n          float activation(float x) {\n            ${a}\n          }\n        `,u=\"result = activation(result);\");let p=t?\"result += getBiasAtOutCoords();\":\"\";t&&this.variableNames.push(\"bias\"),n&&this.variableNames.push(\"preluActivationWeights\"),r&&this.variableNames.push(\"leakyreluAlpha\"),this.userCode=`\n      ${l}\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int batch = coords.x;\n        ivec2 xRCCorner = coords.yz * strides - pads;\n        int d2 = coords.w;\n        int d1 = d2 / ${o};\n        int q = d2 - d1 * ${o};\n\n        int xRCorner = xRCCorner.x;\n        int xCCorner = xRCCorner.y;\n\n        // Convolve x(?, ?, d1) with w(:, :, d1, q) to get y(yR, yC, d2).\n        // ? = to be determined. : = across all values in that axis.\n        float dotProd = 0.0;\n        // TO DO(dsmilkov): Flatten the two for loops and vec4 the operations.\n        for (int wR = 0; wR < ${s}; wR++) {\n          int xR = xRCorner + wR * dilations[0];\n\n          if (xR < 0 || xR >= inDims[0]) {\n            continue;\n          }\n\n          for (int wC = 0; wC < ${i}; wC++) {\n            int xC = xCCorner + wC * dilations[1];\n\n            if (xC < 0 || xC >= inDims[1]) {\n              continue;\n            }\n\n            float xVal = getX(batch, xR, xC, d1);\n            float wVal = getW(wR, wC, d1, q);\n            dotProd += xVal * wVal;\n          }\n        }\n\n        float result = dotProd;\n        ${p}\n        ${u}\n        setOutput(result);\n      }\n    `}},lv=class{constructor(e,t=!1,a=null,n=!1,r=!1){this.variableNames=[\"x\",\"W\"],this.packedInputs=!0,this.packedOutput=!0,this.customUniforms=[{name:\"pads\",type:\"ivec2\"},{name:\"strides\",type:\"ivec2\"},{name:\"dilations\",type:\"ivec2\"},{name:\"inDims\",type:\"ivec2\"}],this.outputShape=e.outShape,this.enableShapeUniforms=Na(this.outputShape.length);let s=e.outChannels/e.inChannels,i=e.padInfo.left,o=e.strideWidth,l=e.dilationWidth,u=e.filterHeight,p=e.filterWidth,c=p,d=`\n      int xR; int xC; int xCOffset;\n      vec4 wTexel; vec4 previous; vec4 final;`;for(let g=0;g<p;g++)d+=`\n          vec4 xTexelC${g*2};\n          int xTexelC${g*2}Ready;\n          vec4 xTexelC${g*2+1};\n          int xTexelC${g*2+1}Ready;\n          vec4 xC${g};`;d+=`\n    for (int r = 0; r < ${u}; r++) {\n      `;for(let g=0;g<p;g++)d+=`\n          xTexelC${g*2} = vec4(0.0);\n          xTexelC${g*2}Ready = 0;\n          xTexelC${g*2+1} = vec4(0.0);\n          xTexelC${g*2+1}Ready = 0;\n          xC${g} = vec4(0.0);`;d+=`\n        xR = xRCorner + r * dilations[0];\n        if (xR >=0 && xR < inDims[0]) {\n      `;for(let g=0;g<(c+1)/2;g++){let x=g*2;if(d+=`\n          xC = xCCorner + ${x*l};\n          `,o===1){if(x<p&&(i%2===1?(d+=`\n                xCOffset = xC + 1;\n                if (xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${x}Ready == 0) {\n                  xTexelC${x} = getX(batch, xR, xCOffset, d1);\n\n                  // Need to manually clear unused channels in case\n                  // we're reading from recycled texture.\n                  if (xCOffset + 1 >= inDims[1]) {\n                    xTexelC${x}.zw = vec2(0.0);\n                  }\n                  xTexelC${x}Ready = 1;\n                }\n              `,l===1&&x>0?d+=`\n                xC${x} = vec4(xTexelC${x-2}.zw, xTexelC${x}.xy);\n                `:d+=`\n                  xCOffset = xC + 1 - 2;\n\n                  if (xCOffset >= 0 && xCOffset < inDims[1]) {\n                    previous = getX(batch, xR, xCOffset, d1);\n\n                    // Need to manually clear unused channels in case\n                    // we're reading from recycled texture.\n                    if (xCOffset + 1 >= inDims[1]) {\n                      previous.zw = vec2(0.0);\n                    }\n\n                    xC${x} = vec4(previous.zw, xTexelC${x}.xy);\n                  } else {\n                    xC${x} = vec4(0.0, 0.0, xTexelC${x}.xy);\n                  }\n                  `):d+=`\n                if (xC >= 0 && xC < inDims[1] && xTexelC${x}Ready == 0) {\n                  xTexelC${x} = getX(batch, xR, xC, d1);\n                  if (xC + 1 >= inDims[1]) {\n                    xTexelC${x}.zw = vec2(0.0);\n                  }\n                  xTexelC${x}Ready = 1;\n                }\n\n                xC${x} = xTexelC${x};\n                `,x+1<p)){let A=i%2===0?v.nearestLargerEven(l):l;l%2===0&&i%2===1||l%2!==0&&i%2!==1?(d+=`\n                  xCOffset = xC + imod(pads[1], 2) + ${A};\n\n                  if (xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${x+1}Ready == 0) {\n                    xTexelC${x+1} = getX(batch, xR, xCOffset, d1);\n\n                    // Need to manually clear unused channels in case\n                    // we're reading from recycled texture.\n                    if (xCOffset + 1 >= inDims[1]) {\n                      xTexelC${x+1}.zw = vec2(0.0);\n                    }\n                    xTexelC${x+1}Ready = 1;\n                  }\n                  `,l>1?d+=`\n                    xCOffset -= 2;\n                    if (xCOffset >= 0 && xCOffset < inDims[1]) {\n                     previous = getX(batch, xR, xCOffset, d1);\n                     xC${x+1} = vec4(previous.zw, xTexelC${x+1}.xy);\n                    } else {\n                     xC${x+1} = vec4(0.0, 0.0, xTexelC${x+1}.xy);\n                    }\n                    `:d+=`\n                    xC${x+1} = vec4(xTexelC${x}.zw, xTexelC${x+1}.xy);\n                    `):A===1?d+=`\n                    xC${x+1} = xTexelC${x};\n                    `:d+=`\n                    xCOffset = xC + ${A};\n\n                    if (xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${x+1}Ready == 0) {\n                      xTexelC${x+1} = getX(batch, xR, xCOffset, d1);\n                      if (xCOffset + 1 >= inDims[1]) {\n                        xTexelC${x+1}.zw = vec2(0.0);\n                      }\n                      xTexelC${x+1}Ready = 1;\n                    }\n\n                    xC${x+1} = xTexelC${x+1};\n                    `}}else x<p&&(i%2===1?(d+=`\n                xCOffset = xC + 1 - strides[1];\n                if(xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${x}Ready == 0) {\n                  xTexelC${x} = getX(batch, xR, xCOffset, d1);\n                  // Need to manually clear unused channels in case\n                  // we're reading from recycled texture.\n                  if (xCOffset + 1 >= inDims[1]) {\n                    xTexelC${x}.zw = vec2(0.0);\n                  }\n                  xTexelC${x}Ready = 1;\n                }\n\n                if(xC + 1 >= 0 && xC + 1 < inDims[1] && xTexelC${x+1}Ready == 0) {\n                  xTexelC${x+1} = getX(batch, xR, xC + 1, d1);\n                  // Need to manually clear unused channels in case\n                  // we're reading from recycled texture.\n                  if (xC + 2 >= inDims[1]) {\n                    xTexelC${x+1}.zw = vec2(0.0);\n                  }\n                  xTexelC${x+1}Ready = 1;\n                }\n\n                xC${x} = vec4(xTexelC${x}.zw, xTexelC${x+1}.zw);\n              `,x+1<p&&(d+=`\n                  final = vec4(0.0);\n                  xCOffset = xC + 1 + strides[1];\n                  if(xCOffset >= 0 && xCOffset < inDims[1]) {\n                    final = getX(batch, xR, xCOffset, d1);\n                  }\n                  xC${x+1} = vec4(xTexelC${x+1}.xy, final.xy);\n                `)):(d+=`\n                if(xC >= 0 && xC < inDims[1] && xTexelC${x}Ready == 0) {\n                  xTexelC${x} = getX(batch, xR, xC, d1);\n                  if (xC + 1 >= inDims[1]) {\n                    xTexelC${x}.zw = vec2(0.0);\n                  }\n                  xTexelC${x}Ready = 1;\n                }\n\n                xCOffset = xC + strides[1];\n                if(xCOffset >= 0 && xCOffset < inDims[1] && xTexelC${x+1}Ready == 0) {\n                  xTexelC${x+1} = getX(batch, xR, xCOffset, d1);\n                  if (xCOffset + 1 >= inDims[1]) {\n                    xTexelC${x+1}.zw = vec2(0.);\n                  }\n                  xTexelC${x+1}Ready = 1;\n                }\n\n                xC${x} = vec4(\n                  xTexelC${x}.xy, xTexelC${x+1}.xy);\n              `,x+1<p&&(d+=`\n                  xC${x+1} = vec4(xTexelC${x}.zw, xTexelC${x+1}.zw);\n                `)));x<p&&(d+=`\n            wTexel = getW(r, ${x}, d1, q);\n            dotProd += xC${x} * vec4(wTexel.xz, wTexel.xz);\n          `,x+1<p&&(d+=`\n              wTexel = getW(r, ${x+1}, d1, q);\n              dotProd += xC${x+1} * vec4(wTexel.xz, wTexel.xz);\n            `))}d+=`\n    }\n  `,d+=`\n      }\n    `;let h=\"\",f=\"\";a&&(n?h=`vec4 activation(vec4 a) {\n          vec4 b = getPreluActivationWeightsAtOutCoords();\n          ${a}\n        }`:r?h=`vec4 activation(vec4 a) {\n          vec4 b = getLeakyreluAlphaAtOutCoords();\n          ${a}\n        }`:h=`vec4 activation(vec4 x) {\n          ${a}\n        }`,f=\"result = activation(result);\");let m=t?\"result += getBiasAtOutCoords();\":\"\";t&&this.variableNames.push(\"bias\"),n&&this.variableNames.push(\"preluActivationWeights\"),r&&this.variableNames.push(\"leakyreluAlpha\"),this.userCode=`\n      ${h}\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int batch = coords.x;\n        ivec2 xRCCorner = coords.yz * strides - pads;\n        int d2 = coords.w;\n        int d1 = d2 / ${s};\n        int q = d2 - d1 * ${s};\n        int xRCorner = xRCCorner.x;\n        int xCCorner = xRCCorner.y;\n\n        //intialize dotProd with a small epsilon seems to reduce GPU accuracy loss.\n        vec4 dotProd = vec4(0.000000000000001);\n\n        ${d}\n\n        vec4 result = dotProd - vec4(0.000000000000001);\n        ${m}\n        ${f}\n        setOutput(result);\n      }\n    `}};function Qj(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dilations:l,dimRoundingMode:u}=n,p=l;p==null&&(p=[1,1]),v.assert(T.eitherStridesOrDilationsAreOne(i,p),()=>`Error in depthwiseConv2d: Either strides or dilations must be 1. Got strides ${i} and dilations '${p}'`);let c=T.computeConv2DInfo(r.shape,s.shape,i,p,o,u,!0),d;W().getBool(\"WEBGL_PACK_DEPTHWISECONV\")&&c.strideWidth<=2&&c.outChannels/c.inChannels===1?d=new lv(c):d=new ov(c);let h=[[c.padInfo.top,c.padInfo.left],[c.strideHeight,c.strideWidth],[c.dilationHeight,c.dilationWidth],[c.inHeight,c.inWidth]];return a.runWebGLProgram(d,[r,s],\"float32\",h)}var eq={kernelName:pi,backendName:\"webgl\",kernelFunc:Qj},tq=class{constructor(e){this.variableNames=[\"x\",\"dy\"],this.outputShape=e.filterShape;let t=e.strideHeight,a=e.strideWidth,n=e.padInfo.top,r=e.padInfo.left,s=e.outChannels/e.inChannels;this.userCode=`\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int wR = coords.x;\n        int wC = coords.y;\n        int d1 = coords.z;\n        int dm = coords.w;\n        int d2 = d1 * ${s} + dm;\n\n        float dotProd = 0.0;\n\n        // TO DO: Vec4 over the batch size\n        for (int b = 0; b < ${e.batchSize}; b++) {\n          for (int yR = 0; yR < ${e.outHeight}; yR++) {\n            int xR = wR + yR * ${t} - ${n};\n\n            if (xR < 0 || xR >= ${e.inHeight}) {\n              continue;\n            }\n\n            for (int yC = 0; yC < ${e.outWidth}; yC++) {\n              int xC = wC + yC * ${a} - ${r};\n\n              if (xC < 0 || xC >= ${e.inWidth}) {\n                continue;\n              }\n\n              float dyValue = getDy(b, yR, yC, d2);\n              float xValue = getX(b, xR, xC, d1);\n              dotProd += (xValue * dyValue);\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}},aq=class{constructor(e){this.variableNames=[\"dy\",\"W\"],this.outputShape=e.inShape;let t=e.filterHeight,a=e.filterWidth,n=e.strideHeight,r=e.strideWidth,s=t-1-e.padInfo.top,i=a-1-e.padInfo.left,o=e.outChannels/e.inChannels;this.userCode=`\n      const ivec2 pads = ivec2(${s}, ${i});\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int batch = coords[0];\n        int d1 = coords[3];\n        ivec2 dyCorner = coords.yz - pads;\n        int dyRCorner = dyCorner.x;\n        int dyCCorner = dyCorner.y;\n\n        float dotProd = 0.0;\n\n        for (int wR = 0; wR < ${t}; wR++) {\n          float dyR = float(dyRCorner + wR) / ${n}.0;\n\n          if (dyR < 0.0 || dyR >= ${e.outHeight}.0 || fract(dyR) > 0.0) {\n            continue;\n          }\n          int idyR = int(dyR);\n\n          int wRPerm = ${t} - 1 - wR;\n\n          for (int wC = 0; wC < ${a}; wC++) {\n            float dyC = float(dyCCorner + wC) / ${r}.0;\n\n            if (dyC < 0.0 || dyC >= ${e.outWidth}.0 ||\n                fract(dyC) > 0.0) {\n              continue;\n            }\n            int idyC = int(dyC);\n\n            int wCPerm = ${a} - 1 - wC;\n\n            // TO DO: Vec4 over the channelMul\n            for (int dm = 0; dm < ${o}; dm++) {\n              int d2 = d1 * ${o} + dm;\n              float xValue = getDy(batch, idyR, idyC, d2);\n              float wValue = getW(wRPerm, wCPerm, d1, dm);\n              dotProd += xValue * wValue;\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}};function nq(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,dy:s}=t,{strides:i,dilations:o,pad:l,dimRoundingMode:u,filterShape:p}=n,c=T.computeConv2DInfo(r.shape,p,i,o,l,u,!0),d=new tq(c);return a.runWebGLProgram(d,[r,s],\"float32\")}var rq={kernelName:Yc,backendName:\"webgl\",kernelFunc:nq};function sq(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,filter:s}=t,{strides:i,dilations:o,pad:l,dimRoundingMode:u,inputShape:p}=n,c=T.computeConv2DInfo(p,s.shape,i,o,l,u,!0),d=new aq(c);return a.runWebGLProgram(d,[r,s],\"float32\")}var iq={kernelName:Jc,backendName:\"webgl\",kernelFunc:sq},oq=class{constructor(e){this.variableNames=[\"X\"],this.outputShape=[e,e],this.userCode=`\n      void main() {\n          ivec2 coords = getOutputCoords();\n          float val = coords[0] == coords[1] ? getX(coords[0]) : 0.0;\n          setOutput(val);\n      }\n    `}};function lq(e){let{inputs:t,backend:a}=e,{x:n}=t,r=[...n.shape,...n.shape],s=v.sizeFromShape(n.shape),i=ce({inputs:{x:n},backend:a,attrs:{shape:[s]}}),o=new oq(s),l=a.runWebGLProgram(o,[i],i.dtype),u=ce({inputs:{x:l},backend:a,attrs:{shape:r}});return a.disposeIntermediateTensorInfo(i),a.disposeIntermediateTensorInfo(l),u}var uq={kernelName:Qc,backendName:\"webgl\",kernelFunc:lq},dq=class{constructor(e){this.variableNames=[\"x\",\"W\"],this.outputShape=e.outShape;let{inHeight:t,inWidth:a,padInfo:n,strideHeight:r,strideWidth:s,filterHeight:i,filterWidth:o,dilationHeight:l,dilationWidth:u}=e,{top:p,left:c}=n;this.userCode=`\n      const ivec2 strides = ivec2(${r}, ${s});\n      const ivec2 pads = ivec2(${p}, ${c});\n      const float neg_infinity = -3.4e38;\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int batch = coords.x;\n        int d1 = coords.w;\n        ivec2 outTopLeftCorner =\n            coords.yz * strides - pads;\n        int hBeg = outTopLeftCorner.x;\n        int wBeg = outTopLeftCorner.y;\n\n        float curVal = neg_infinity;\n        for (int h = 0; h < ${i}; h++) {\n          int hIn = hBeg + h * ${l};\n\n          if (hIn >= 0 && hIn < ${t}) {\n            for (int w = 0; w < ${o}; w++) {\n              int wIn = wBeg + w * ${u};\n\n              if (wIn >= 0 && wIn < ${a}) {\n                float xVal = getX(batch, hIn, wIn, d1);\n                float wVal = getW(h, w, d1);\n\n                float val = xVal + wVal;\n                if (val > curVal) {\n                  curVal = val;\n                }\n              }\n            }\n          }\n        }\n\n        float result = curVal;\n        setOutput(result);\n      }\n    `}};function pq(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dilations:l}=n,u=T.computeDilation2DInfo(r.shape,s.shape,i,o,\"NHWC\",l),p,c=new dq(u);p=a.runWebGLProgram(c,[r,s],\"float32\");let d=ce({inputs:{x:p},backend:a,attrs:{shape:u.outShape}});return a.disposeIntermediateTensorInfo(p),d}var cq={kernelName:eh,backendName:\"webgl\",kernelFunc:pq};function hq(e){let{inputs:t,backend:a,attrs:n}=e,{equation:r}=n,s=t,{allDims:i,summedDims:o,idDims:l}=T.decodeEinsumEquation(r,s.length);T.checkEinsumDimSizes(i.length,l,s);let{path:u,steps:p}=T.getEinsumComputePath(o,l),c=p.length,d=null,h=i.length,f=[];for(let m=0;m<c;++m){for(let g of p[m]){let{permutationIndices:x,expandDims:A}=T.getEinsumPermutation(h,l[g]),y;T.isIdentityPermutation(x)?y=s[g]:(y=Ia({inputs:{x:s[g]},backend:a,attrs:{perm:x}}),f.push(y));let b=y.shape.slice();for(let w=0;w<A.length;++w)b.splice(A[w],0,1);v.arraysEqual(y.shape,b)||(y=ce({inputs:{x:y},backend:a,attrs:{shape:b}}),f.push(y)),d===null?d=y:(d=M3({inputs:{a:y,b:d},backend:a}),f.push(d))}m<c-1&&(u[m]>=0&&(d=zh({inputs:{x:d},backend:a,attrs:{axis:u[m]-(i.length-h),keepDims:!1}}),f.push(d)),h--)}for(let m of f)m!==d&&a.disposeIntermediateTensorInfo(m);return d}var fq={kernelName:Cd,backendName:\"webgl\",kernelFunc:hq},mq=\"return (x >= 0.0) ? x : (exp(x) - 1.0);\",gq=`\n  vec4 result;\n\n  result.r = (x.r >= 0.0) ? x.r : (exp(x.r) - 1.0);\n  result.g = (x.g >= 0.0) ? x.g : (exp(x.g) - 1.0);\n  result.b = (x.b >= 0.0) ? x.b : (exp(x.b) - 1.0);\n  result.a = (x.a >= 0.0) ? x.a : (exp(x.a) - 1.0);\n\n  return result;\n`,xq=Qe({opSnippet:mq,packedOpSnippet:gq}),Aq={kernelName:hi,backendName:\"webgl\",kernelFunc:xq},yq=\"return (b >= 1.0) ? a : a * (b + 1.0);\",bq=`\n  vec4 bGTEZero = vec4(greaterThanEqual(b, vec4(0.)));\n  return (bGTEZero * a) + ((vec4(1.0) - bGTEZero) * (a * (b + vec4(1.0))));\n`,vq=e=>{let{inputs:t,backend:a}=e,{dy:n,y:r}=t,s=W().getBool(\"WEBGL_PACK_BINARY_OPERATIONS\")?new cp(bq,n.shape,r.shape):new Al(yq,n.shape,r.shape);return a.runWebGLProgram(s,[n,r],n.dtype)},wq={kernelName:j1,backendName:\"webgl\",kernelFunc:vq},kq=`\n  return vec4(equal(a, b));\n`,Iq=\"return float(a == b);\",Sq=oa({opSnippet:Iq,packedOpSnippet:kq,dtype:\"bool\",cpuKernelImpl:lU}),Tq={kernelName:fi,backendName:\"webgl\",kernelFunc:Sq},Cq=`\n  // Error function is calculated approximately with elementary function.\n  // See \"Handbook of Mathematical Functions with Formulas,\n  // Graphs, and Mathematical Tables\", Abramowitz and Stegun.\n  float p = ${T.ERF_P};\n  float a1 = ${T.ERF_A1};\n  float a2 = ${T.ERF_A2};\n  float a3 = ${T.ERF_A3};\n  float a4 = ${T.ERF_A4};\n  float a5 = ${T.ERF_A5};\n\n  float sign = sign(x);\n  x = abs(x);\n  float t = 1.0 / (1.0 + p * x);\n  return sign * (1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x));\n`,Nq=Qe({opSnippet:Cq}),Eq={kernelName:$l,backendName:\"webgl\",kernelFunc:Nq},Rq=mu+`\n  return exp(x);\n`,Mq=`\n  vec4 result = exp(x);\n  bvec4 isNaN = isnan(x);\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n`,uv=Qe({opSnippet:Rq,packedOpSnippet:Mq,cpuKernelImpl:uU,dtype:\"float32\"}),$q={kernelName:mi,backendName:\"webgl\",kernelFunc:uv};function N1(e){let{inputs:t,attrs:a,backend:n}=e,{dim:r}=a,{input:s}=t,i=s.shape.length,o=s.shape.slice(),l=r;return r<0&&(v.assert(-(i+1)<=r,()=>`Axis must be in the interval [${-(i+1)}, ${i}]`),l=i+r+1),o.splice(l,0,1),ce({inputs:{x:s},backend:n,attrs:{shape:o}})}var _q={kernelName:_l,backendName:\"webgl\",kernelFunc:N1},Ex=\"return exp(x) - 1.0;\",Pq=Qe({opSnippet:Ex,packedOpSnippet:Ex,cpuKernelImpl:dU}),Fq={kernelName:Pl,backendName:\"webgl\",kernelFunc:Pq},Rx=class{constructor(e,t,a){this.variableNames=[\"real\",\"imag\"];let n=t[1];this.outputShape=t;let r=a?`2.0 * ${Math.PI}`:`-2.0 * ${Math.PI}`,s=a?`${n}.0`:\"1.0\",i;if(e===\"real\")i=\"return real * expR - imag * expI;\";else if(e===\"imag\")i=\"return real * expI + imag * expR;\";else throw new Error(`FFT component must be either \"real\" or \"imag\", got ${e}.`);this.userCode=`\n      const float exponentMultiplier = ${r};\n\n      float unaryOpComplex(float real, float expR, float imag, float expI) {\n        ${i}\n      }\n\n      float mulMatDFT(int batch, int index) {\n        float indexRatio = float(index) / float(${n});\n        float exponentMultiplierTimesIndexRatio =\n            exponentMultiplier * indexRatio;\n\n        float result = 0.0;\n\n        for (int i = 0; i < ${n}; i++) {\n          // x = (-2|2 * PI / N) * index * i;\n          float x = exponentMultiplierTimesIndexRatio * float(i);\n          float expR = cos(x);\n          float expI = sin(x);\n          float real = getReal(batch, i);\n          float imag = getImag(batch, i);\n\n          result +=\n              unaryOpComplex(real, expR, imag, expI) / ${s};\n        }\n\n        return result;\n      }\n\n      void main() {\n        ivec2 coords = getOutputCoords();\n        setOutput(mulMatDFT(coords[0], coords[1]));\n      }\n    `}};function dv(e,t,a){let n=a.texData.get(e.dataId),r=v.sizeFromShape(e.shape),s=e.shape[e.shape.length-1],i=r/s,o=ce({inputs:{x:e},backend:a,attrs:{shape:[i,s]}}),l=o.shape,u=new Rx(\"real\",l,t),p=new Rx(\"imag\",l,t),c=[{dataId:n.complexTensorInfos.real.dataId,dtype:n.complexTensorInfos.real.dtype,shape:l},{dataId:n.complexTensorInfos.imag.dataId,dtype:n.complexTensorInfos.imag.dtype,shape:l}],d=a.runWebGLProgram(u,c,\"float32\"),h=a.runWebGLProgram(p,c,\"float32\"),f=ls({inputs:{real:d,imag:h},backend:a});a.disposeIntermediateTensorInfo(d),a.disposeIntermediateTensorInfo(h);let m=ce({inputs:{x:f},backend:a,attrs:{shape:e.shape}});return a.disposeIntermediateTensorInfo(o),a.disposeIntermediateTensorInfo(f),m}function Oq(e){let{inputs:t,backend:a}=e,{input:n}=t;return dv(n,!1,a)}var Dq={kernelName:Nd,backendName:\"webgl\",kernelFunc:Oq},zq=class{constructor(e,t){this.outputShape=[],this.customUniforms=[{name:\"value\",type:\"float\"}],this.variableNames=[\"x\"],this.outputShape=e,this.userCode=`\n      void main() {\n        // Input can be obtained from uniform value.\n        setOutput(value);\n      }\n    `}};function fp(e){let{backend:t,attrs:a}=e,{shape:n,value:r}=a,{dtype:s}=a;if(s=s||v.inferDtype(r),s===\"string\"){let i=v.getArrayFromDType(s,v.sizeFromShape(n));return i.fill(r),t.makeTensorInfo(n,s,i)}else{let i=new zq(n,r),o=[[r]];return t.runWebGLProgram(i,[],s,o)}}var Lq={kernelName:Fl,backendName:\"webgl\",kernelFunc:fp},Bq=class{constructor(e){this.variableNames=[\"Image\"],this.outputShape=[];let t=e[2];this.outputShape=e,this.userCode=`\n        void main() {\n          ivec4 coords = getOutputCoords();\n          int x = coords[2];\n\n          int coordX = ${t} - x - 1;\n          float outputValue;\n          if(coordX >= 0 && coordX < ${t}) {\n            outputValue = getImage(coords[0], coords[1], coordX, coords[3]);\n          } else {\n            outputValue = getImage(coords[0], coords[1], coords[2], coords[3]);\n          }\n          setOutput(outputValue);\n        }\n    `}},Wq={kernelName:gi,backendName:\"webgl\",kernelFunc:({inputs:e,backend:t})=>{let{image:a}=e,n=t,r=new Bq(a.shape);return n.runWebGLProgram(r,[a],a.dtype)}},Mx=\"return floor(x);\",Vq=Qe({opSnippet:Mx,packedOpSnippet:Mx,cpuKernelImpl:pU}),Uq={kernelName:xi,backendName:\"webgl\",kernelFunc:Vq},Gq=`\n  float s = sign(a) * sign(b);\n  int ia = round(a);\n  int ib = round(b);\n  if (ib != 0) {\n    // Windows (D3D) wants guaranteed non-zero int division at compile-time.\n    return float(idiv(ia, ib, s));\n  } else {\n    return NAN;\n  }\n`,Hq=`\n  ivec4 ia = round(a);\n  ivec4 ib = round(b);\n  bvec4 cond = notEqual(ib, ivec4(0));\n  ivec4 result = ivec4(0);\n  vec4 s = sign(a) * sign(b);\n\n  // Windows (D3D) wants guaranteed non-zero int division at compile-time.\n  if (cond[0]) {\n    result[0] = idiv(ia[0], ib[0], s[0]);\n  }\n  if (cond[1]) {\n    result[1] = idiv(ia[1], ib[1], s[1]);\n  }\n  if (cond[2]) {\n    result[2] = idiv(ia[2], ib[2], s[2]);\n  }\n  if (cond[3]) {\n    result[3] = idiv(ia[3], ib[3], s[3]);\n  }\n  return vec4(result);\n`,jq=oa({opSnippet:Gq,packedOpSnippet:Hq,dtype:\"int32\"}),qq={kernelName:Ai,backendName:\"webgl\",kernelFunc:jq},Xq=class{constructor(e){this.variableNames=[\"A\"];let t=Ca(),[a,n]=e;this.outputShape=e,this.userCode=`\n      void main() {\n        ivec3 coords = getOutputCoords();\n        int texR = coords[0];\n        int texC = coords[1];\n        int depth = coords[2];\n        vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${n}.0, ${a}.0);\n\n        vec4 values = ${t.texture2D}(A, uv);\n        float value;\n        if (depth == 0) {\n          value = values.r;\n        } else if (depth == 1) {\n          value = values.g;\n        } else if (depth == 2) {\n          value = values.b;\n        } else if (depth == 3) {\n          value = values.a;\n        }\n\n        setOutput(floor(value * 255.0 + 0.5));\n      }\n    `}},Kq=class{constructor(e){this.variableNames=[\"A\"],this.packedInputs=!1,this.packedOutput=!0;let t=Ca(),[a,n]=e;this.outputShape=e,this.userCode=`\n      void main() {\n        ivec3 coords = getOutputCoords();\n        int texR = coords[0];\n        int texC = coords[1];\n        int depth = coords[2];\n\n        vec4 result = vec4(0.);\n\n        for(int row=0; row<=1; row++) {\n          for(int col=0; col<=1; col++) {\n            texC = coords[1] + row;\n            depth = coords[2] + col;\n\n            vec2 uv = (vec2(texC, texR) + halfCR) /\n                       vec2(${n}.0, ${a}.0);\n            vec4 values = ${t.texture2D}(A, uv);\n            float value;\n            if (depth == 0) {\n              value = values.r;\n            } else if (depth == 1) {\n              value = values.g;\n            } else if (depth == 2) {\n              value = values.b;\n            } else if (depth == 3) {\n              value = values.a;\n            }\n\n            result[row * 2 + col] = floor(value * 255.0 + 0.5);\n          }\n        }\n\n        ${t.output} = result;\n      }\n    `}},Zq={kernelName:rd,backendName:\"webgl\",kernelFunc:Yq},Zo,Lm=W().getBool(\"CANVAS2D_WILL_READ_FREQUENTLY_FOR_GPU\");function Yq(e){let{inputs:t,backend:a,attrs:n}=e,{pixels:r}=t,{numChannels:s}=n,i=typeof HTMLVideoElement!=\"undefined\"&&r instanceof HTMLVideoElement,o=typeof HTMLImageElement!=\"undefined\"&&r instanceof HTMLImageElement,[l,u]=i?[r.videoWidth,r.videoHeight]:[r.width,r.height],p=[u,l],c=[u,l,s];if(o||i){let m=W().getBool(\"CANVAS2D_WILL_READ_FREQUENTLY_FOR_GPU\");(Zo==null||m!==Lm)&&(Lm=m,Zo=document.createElement(\"canvas\").getContext(\"2d\",{willReadFrequently:Lm})),Zo.canvas.width=l,Zo.canvas.height=u,Zo.drawImage(r,0,0,l,u),r=Zo.canvas}let d=a.makeTensorInfo(p,\"int32\");a.texData.get(d.dataId).usage=pn.PIXELS,a.gpgpu.uploadPixelDataToTexture(a.getTexture(d.dataId),r);let h=W().getBool(\"WEBGL_PACK\")?new Kq(c):new Xq(c),f=a.runWebGLProgram(h,[d],\"int32\");return a.disposeData(d.dataId),f}function Jq(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s,bias:i,preluActivationWeights:o}=t,{strides:l,pad:u,dataFormat:p,dilations:c,dimRoundingMode:d,activation:h,leakyreluAlpha:f}=n,m=T.convertConv2DDataFormat(p),g=T.computeConv2DInfo(r.shape,s.shape,l,c,u,d,!1,m),x,A=[],y=i!=null,b=o!=null,w=h===\"leakyrelu\",S=()=>{let E=[r,s],_=($,M)=>{if(M===\"NCHW\"&&$.shape.length===1&&$.shape[0]!==1){let I=ce({inputs:{x:$},backend:a,attrs:{shape:[$.shape[0],1,1]}});return A.push(I),I}return $};if(y&&E.push(_(i,p)),b&&E.push(_(o,p)),w){let $=a.makeTensorInfo([],\"float32\",v.createScalarValue(f,\"float32\"));E.push($),A.push($)}return E};if(g.filterHeight===1&&g.filterWidth===1&&g.dilationHeight===1&&g.dilationWidth===1&&g.strideHeight===1&&g.strideWidth===1&&(g.padInfo.type===\"SAME\"||g.padInfo.type===\"VALID\"))x=rv({x:r,filter:s,convInfo:g,backend:a,bias:i,activation:h,preluActivationWeights:o,leakyreluAlpha:f});else if(g.strideWidth<=2&&m===\"channelsLast\"&&W().getBool(\"WEBGL_EXP_CONV\")){let E=h?gd(h,!0):null,_=new nv(g,y,E,b,w),$=[[g.padInfo.top,g.padInfo.left],[g.strideHeight,g.strideWidth],[g.dilationHeight,g.dilationWidth],[g.inHeight,g.inWidth]],M=S();x=a.runWebGLProgram(_,M,\"float32\",$)}else if(W().getBool(\"WEBGL_CONV_IM2COL\"))x=sv({x:r,filter:s,convInfo:g,backend:a,bias:i,activation:h,preluActivationWeights:o,leakyreluAlpha:f});else{let E=h?gd(h,!1):null,_=new av(g,y,E,b,w),$=S();x=a.runWebGLProgram(_,$,\"float32\")}let C=ce({inputs:{x},backend:a,attrs:{shape:g.outShape}});return A.push(x),A.forEach(E=>a.disposeIntermediateTensorInfo(E)),C}var Qq={kernelName:qr,backendName:\"webgl\",kernelFunc:Jq};function eX(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s,bias:i,preluActivationWeights:o}=t,{strides:l,pad:u,dilations:p,dimRoundingMode:c,activation:d,leakyreluAlpha:h}=n,f=[],m=p;m==null&&(m=[1,1]),v.assert(T.eitherStridesOrDilationsAreOne(l,m),()=>`Error in depthwiseConv2d: Either strides or dilations must be 1. Got strides ${l} and dilations '${m}'`);let g=T.computeConv2DInfo(r.shape,s.shape,l,m,u,c,!0),x=W().getBool(\"WEBGL_PACK_DEPTHWISECONV\")&&g.strideWidth<=2&&g.outChannels/g.inChannels===1,A=d?gd(d,x):null,y=[r,s],b=i!=null,w=o!=null,S=d===\"leakyrelu\";if(b&&y.push(i),w&&y.push(o),S){let $=a.makeTensorInfo([],\"float32\",v.createScalarValue(h,\"float32\"));y.push($),f.push($)}let C;x?C=new lv(g,b,A,w,S):C=new ov(g,b,A,w,S);let E=[[g.padInfo.top,g.padInfo.left],[g.strideHeight,g.strideWidth],[g.dilationHeight,g.dilationWidth],[g.inHeight,g.inWidth]],_=a.runWebGLProgram(C,y,\"float32\",E);return f.forEach($=>a.disposeIntermediateTensorInfo($)),_}var tX={kernelName:Xr,backendName:\"webgl\",kernelFunc:eX},aX=class{constructor(e,t,a,n){this.sliceDim=e,this.strides=t,this.paramsShape=n,this.variableNames=[\"x\",\"indices\"],this.outputShape=a;let r=gt(a.length),s=`\n    int index;`;for(let i=0;i<this.sliceDim;i++)s+=`\n          index = round(getIndices(coords[0], ${i}));\n          out_of_bounds = out_of_bounds || index < 0;\n          out_of_bounds = out_of_bounds || index >= ${this.paramsShape[i]};\n          flattenIndex += index * ${this.strides[i]};`;this.userCode=`\n         void main() {\n          ${r} coords = getOutputCoords();\n          int flattenIndex = 0;\n          bool out_of_bounds = false;\n\n          ${s}\n\n          setOutput(out_of_bounds ? 0.0 : getX(flattenIndex, coords[1]));\n        }\n      `}};function nX(e){let{inputs:t,backend:a}=e,{params:n,indices:r}=t,s=r.shape,i=s[s.length-1],o=v.sizeFromShape(n.shape),[l,u,p,c]=T.prepareAndValidate(n,r),d=ce({inputs:{x:r},backend:a,attrs:{shape:[u,i]}}),h=ce({inputs:{x:n},backend:a,attrs:{shape:[v.sizeFromShape(n.shape)/p,p]}});if(a.shouldExecuteOnCPU([n,r])||n.dtype===\"string\"){let x=a.readSync(r.dataId),A=a.bufferSync(n),y=cU(x,A,n.dtype,u,i,p,c,n.shape,o);return a.makeTensorInfo(l,n.dtype,y.values)}let f=new aX(i,c,[u,p],n.shape),m=a.runWebGLProgram(f,[h,d],h.dtype),g=ce({inputs:{x:m},backend:a,attrs:{shape:l}});return a.disposeIntermediateTensorInfo(d),a.disposeIntermediateTensorInfo(h),a.disposeIntermediateTensorInfo(m),g}var rX={kernelName:bi,backendName:\"webgl\",kernelFunc:nX},sX=class{constructor(e,t){this.variableNames=[\"A\",\"indices\"],this.outputShape=t,this.rank=t.length;let a=gt(this.rank),n=iX(e,2);this.userCode=`\n      void main() {\n        ${a} resRC = getOutputCoords();\n        int index = int(getIndices(resRC.x, resRC.z));\n        float inBounds = (index >= 0) && (index < ${e[2]}) ? 1.0 : 0.0;\n        setOutput(inBounds * getA(${n}));\n      }\n    `}};function iX(e,t){let a=[\"resRC.x\",\"resRC.y\",\"resRC.z\",\"resRC.w\"],n=[];for(let r=0;r<e.length;r++)r===2?n.push(\"index\"):n.push(`${a[r]}`);return n.join()}function pv(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,indices:s}=t,{axis:i,batchDims:o}=n,l=v.parseAxisParam(i,r.shape)[0];if(W().get(\"DEBUG\")){let A=a.readSync(s.dataId),y=r.shape[l];for(let b=0;b<A.length;++b){let w=A[b];v.assert(w<=y-1&&w>=0,()=>`GatherV2: the index value ${w} is not in [0, ${y-1}]`)}}let u=T.segment_util.collectGatherOpShapeInfo(r,s,l,o),p=v.sizeFromShape(s.shape),c=[],d=ce({inputs:{x:r},backend:a,attrs:{shape:[u.batchSize,u.outerSize,u.dimSize,u.sliceSize]}}),h=ce({inputs:{x:s},backend:a,attrs:{shape:[u.batchSize,p/u.batchSize]}});c.push(d),c.push(h);let f=[u.batchSize,u.outerSize,p/u.batchSize,u.sliceSize];if(a.shouldExecuteOnCPU([r,s])||r.dtype===\"string\"){let A=a.bufferSync(h),y=a.bufferSync(d),b=hU(y,A,f);return c.forEach(w=>a.disposeIntermediateTensorInfo(w)),a.makeTensorInfo(u.outputShape,b.dtype,b.values)}let m=new sX(d.shape,f),g=a.runWebGLProgram(m,[d,h],d.dtype);c.push(g);let x=ce({inputs:{x:g},backend:a,attrs:{shape:u.outputShape}});return c.forEach(A=>a.disposeIntermediateTensorInfo(A)),x}var oX={kernelName:Ol,backendName:\"webgl\",kernelFunc:pv},lX=\"return float(a > b);\",uX=`\n  return vec4(greaterThan(a, b));\n`,dX=oa({opSnippet:lX,packedOpSnippet:uX,cpuKernelImpl:fU,dtype:\"bool\"}),pX={kernelName:vi,backendName:\"webgl\",kernelFunc:dX},cX=\"return float(a >= b);\",hX=`\n  return vec4(greaterThanEqual(a, b));\n`,fX=oa({opSnippet:cX,packedOpSnippet:hX,dtype:\"bool\",cpuKernelImpl:mU}),mX={kernelName:wi,backendName:\"webgl\",kernelFunc:fX};function gX(e){let{inputs:t,backend:a}=e,{input:n}=t;return dv(n,!0,a)}var xX={kernelName:Ed,backendName:\"webgl\",kernelFunc:gX},AX=\"return float(!isnan(x) && !isinf(x));\",yX=Qe({opSnippet:AX,dtype:\"bool\"}),bX={kernelName:Dl,backendName:\"webgl\",kernelFunc:yX},vX=\"return float(isinf(x));\",wX=Qe({opSnippet:vX,dtype:\"bool\"}),kX={kernelName:zl,backendName:\"webgl\",kernelFunc:wX},IX=\"return float(isnan(x));\",SX=Qe({opSnippet:IX,dtype:\"bool\"}),TX={kernelName:Ii,backendName:\"webgl\",kernelFunc:SX},CX=\"return float(a < b);\",NX=`\n  return vec4(lessThan(a, b));\n`,EX=oa({opSnippet:CX,packedOpSnippet:NX,cpuKernelImpl:gU,dtype:\"bool\"}),RX={kernelName:Ti,backendName:\"webgl\",kernelFunc:EX},MX=\"return float(a <= b);\",$X=`\n  return vec4(lessThanEqual(a, b));\n`,_X=oa({opSnippet:MX,packedOpSnippet:$X,cpuKernelImpl:xU,dtype:\"bool\"}),PX={kernelName:Ci,backendName:\"webgl\",kernelFunc:_X};function FX(e){let{backend:t,attrs:a}=e,{start:n,stop:r,num:s}=a,i=AU(n,r,s);return t.makeTensorInfo([i.length],\"float32\",i)}var OX={kernelName:th,backendName:\"webgl\",kernelFunc:FX},DX=mu+`\n  return x < 0.0 ? 0./0. : log(x);\n`,zX=`\n  vec4 result = log(x);\n  bvec4 isNaN = isnan(x);\n  result.r = isNaN.r ? x.r : (x.r < 0.0 ? 0./0. : result.r);\n  result.g = isNaN.g ? x.g : (x.g < 0.0 ? 0./0. : result.g);\n  result.b = isNaN.b ? x.b : (x.b < 0.0 ? 0./0. : result.b);\n  result.a = isNaN.a ? x.a : (x.a < 0.0 ? 0./0. : result.a);\n  return result;\n`,LX=Qe({opSnippet:DX,packedOpSnippet:zX,cpuKernelImpl:yU}),BX={kernelName:Ni,backendName:\"webgl\",kernelFunc:LX},WX=mu+`\n  return log(1.0 + x);\n`,VX=Qe({opSnippet:WX}),UX={kernelName:Ll,backendName:\"webgl\",kernelFunc:VX},GX=\"return float(a >= 1.0 && b >= 1.0);\",HX=`\n  return vec4(\n    vec4(greaterThanEqual(a, vec4(1.0))) *\n    vec4(greaterThanEqual(b, vec4(1.0))));\n`,jX=oa({opSnippet:GX,packedOpSnippet:HX,dtype:\"bool\"}),qX={kernelName:Ei,backendName:\"webgl\",kernelFunc:jX},XX=\"return float(!(x >= 1.0));\",KX=Qe({opSnippet:XX}),ZX={kernelName:Ri,backendName:\"webgl\",kernelFunc:KX},YX=\"return float(a >= 1.0 || b >= 1.0);\",JX=`\n  return min(\n    vec4(greaterThanEqual(a, vec4(1.0))) +\n    vec4(greaterThanEqual(b, vec4(1.0))),\n    vec4(1.0));\n`,QX=oa({opSnippet:YX,packedOpSnippet:JX,dtype:\"bool\"}),eK={kernelName:Bl,backendName:\"webgl\",kernelFunc:QX},tK=class{constructor(e,t,a,n,r){this.variableNames=[\"x\"],this.outputShape=[];let s=t,i=e[3]-1;this.outputShape=e;let o,l=`float(${a}) + float(${n}) * sum`;r===.5?o=`inversesqrt(${l})`:r===1?o=`1.0/(${l})`:o=`exp(log(${l}) * float(-${r}));`,this.userCode=`\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int r = coords[1];\n        int c = coords[2];\n        int d = coords[3];\n        float x = getX(b, r, c, d);\n        float sum = 0.0;\n        for (int j = -${s}; j <= ${s}; j++) {\n          int idx = d + j;\n          if (idx >= 0 && idx <=  ${i}) {\n            float z = getX(b, r, c, idx);\n            sum += z * z;\n          }\n        }\n        float val = x * ${o};\n        setOutput(val);\n      }\n    `}},aK=class{constructor(e,t,a,n,r){this.variableNames=[\"x\"],this.outputShape=[],this.packedInputs=!0,this.packedOutput=!0;let s=t,i=e[3]-1;this.outputShape=e;let o,l=`float(${a}) + float(${n}) * sum`;r===.5?o=`inversesqrt(${l})`:r===1?o=`1.0/(${l})`:o=`exp(log(${l}) * float(-${r}));`,this.userCode=`\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords.x;\n        int r = coords.y;\n        int c = coords.z;\n        int d = coords.w;\n\n        bool hasNextCol = d < ${this.outputShape[3]};\n        bool hasNextRow = c < ${this.outputShape[2]};\n\n        vec4 sum = vec4(0.);\n        vec4 xFragAtOutputCoords = getX(b, r, c, d);\n\n        vec4 xAtOutputCoords = vec4(\n          getChannel(xFragAtOutputCoords, vec2(c, d)),\n          hasNextCol ?\n            getChannel(xFragAtOutputCoords, vec2(c, d + 1)) : 0.0,\n          hasNextRow ?\n            getChannel(xFragAtOutputCoords , vec2(c + 1, d)) : 0.0,\n          (hasNextRow && hasNextCol) ?\n            getChannel(xFragAtOutputCoords, vec2(c + 1, d + 1)) : 0.0\n        );\n\n        int firstChannel = d - ${s};\n        vec2 cache = vec2(0.);\n        if(firstChannel >= 0){\n          vec4 firstChannelFrag = getX(b, r, c, firstChannel);\n          cache.x = getChannel(firstChannelFrag, vec2(c, firstChannel));\n            if(hasNextRow){\n              cache.y = getChannel(firstChannelFrag, vec2(c + 1, firstChannel));\n            }\n        }\n\n        ivec2 depth = ivec2(d, d + 1);\n        for (int j = - ${s}; j <= ${s}; j++) {\n          ivec2 idx = depth + j;\n          bvec2 aboveLowerBound = greaterThanEqual(idx, ivec2(0));\n          bvec2 belowUpperBound = lessThanEqual(idx, ivec2(${i}));\n\n          bool depthInRange = aboveLowerBound.x && belowUpperBound.x;\n          bool depthPlusOneInRange = aboveLowerBound.y && belowUpperBound.y;\n\n          if(depthInRange || depthPlusOneInRange){\n            vec4 z = vec4(0.);\n            vec4 xFragAtCurrentDepth;\n            z.xz = cache.xy;\n            if(depthPlusOneInRange && hasNextCol){\n              xFragAtCurrentDepth = idx.y != d ?\n                getX(b, r, c, idx.y) : xFragAtOutputCoords;\n              z.y = getChannel(xFragAtCurrentDepth, vec2(c, idx.y));\n              if(hasNextRow){\n                z.w = getChannel(xFragAtCurrentDepth, vec2(c + 1, idx.y));\n              }\n            }\n            cache.xy = z.yw;\n            sum += z * z;\n          }\n        }\n        vec4 result = xAtOutputCoords * ${o};\n        setOutput(result);\n      }\n    `}},nK=e=>{let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{depthRadius:s,bias:i,alpha:o,beta:l}=n,u=W().getBool(\"WEBGL_PACK_NORMALIZATION\")?new aK(r.shape,s,i,o,l):new tK(r.shape,s,i,o,l);return a.runWebGLProgram(u,[r],r.dtype)},rK={kernelName:ah,backendName:\"webgl\",kernelFunc:nK},sK=class{constructor(e,t,a,n,r){this.variableNames=[\"inputImage\",\"outputImage\",\"dy\"],this.outputShape=[],this.outputShape=e,this.depth=e[3],this.depthRadius=t,this.bias=a,this.alpha=n,this.beta=r,this.userCode=`\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int r = coords[1];\n        int c = coords[2];\n\n        float result = 0.0;\n        for (int d = 0; d < ${this.depth}; ++d) {\n          int depthBegin = int(max(0.0, float(d - ${t})));\n          int depthEnd = int(min(float(${this.depth}),\n              float(d + ${t} + 1)));\n\n          const int MIN_DEPTH_BEGIN = 0;\n          const int MAX_DEPTH_END = ${this.depth};\n\n          float norm = 0.0;\n          for (int k = MIN_DEPTH_BEGIN; k < MAX_DEPTH_END; ++k) {\n            if (k < depthBegin){\n              continue;\n            }\n            else if (k >= depthBegin && k < depthEnd) {\n              norm += getInputImage(b, r, c, k) * getInputImage(b, r, c, k);\n            }\n            else {\n              break;\n            }\n          }\n\n          norm = float(${n}) * norm + float(${a});\n\n          for(int k = MIN_DEPTH_BEGIN; k < MAX_DEPTH_END; ++k){\n            if (k < depthBegin){\n              continue;\n            }\n            else if (k >= depthBegin && k < depthEnd){\n              float dyi = -2.0 * float(${n})\n                * float(${r})\n                * getInputImage(b ,r ,c, k) * getOutputImage(b, r, c, d)\n                / norm;\n              if (k == d) {\n                dyi += pow(norm, -1.0 * ${r});\n              }\n              if (k == coords[3]) {\n                dyi *= getDy(b, r, c, d);\n                result += dyi;\n              }\n            }\n            else {\n              break;\n            }\n          }\n      }\n      setOutput(result);\n      }\n    `}},iK=e=>{let{inputs:t,backend:a,attrs:n}=e,{x:r,y:s,dy:i}=t,{depthRadius:o,bias:l,alpha:u,beta:p}=n,c=new sK(r.shape,o,l,u,p);return a.runWebGLProgram(c,[r,s,i],r.dtype)},oK={kernelName:q1,backendName:\"webgl\",kernelFunc:iK};function lK(e,t,a,n){let r=v.sizeFromShape(t),s=v.sizeFromShape(e.shape)/r,i=ce({inputs:{x:e},attrs:{shape:[s,r]},backend:n}),o=bo(i,e.dtype,\"max\",n),l=ce({inputs:{x:o},attrs:{shape:a},backend:n});return n.disposeIntermediateTensorInfo(i),n.disposeIntermediateTensorInfo(o),l}function cv(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{reductionIndices:s,keepDims:i}=n,o=r.shape.length,l=v.parseAxisParam(s,r.shape),u=l,p=T.getAxesPermutation(u,o),c=p!=null,d=a.shouldExecuteOnCPU([r]),h=r;if(c){if(d){let A=a.texData.get(h.dataId).values,y=new Array(o);for(let S=0;S<y.length;S++)y[S]=r.shape[p[S]];let b=E3(A,r.shape,r.dtype,p,y);h=a.makeTensorInfo(y,r.dtype);let w=a.texData.get(h.dataId);w.values=b}else h=Dh(r,p,a);u=T.getInnerMostAxes(u.length,o)}T.assertAxesAreInnerMostDims(\"max\",u,o);let[f,m]=T.computeOutAndReduceShapes(h.shape,u),g=f;i&&(g=T.expandShapeToKeepDim(f,l));let x;if(d){let A=a.texData.get(h.dataId).values,y=bU(A,v.sizeFromShape(m),g,r.dtype);x=a.makeTensorInfo(g,r.dtype);let b=a.texData.get(x.dataId);b.values=y}else x=lK(h,m,g,a);return c&&a.disposeIntermediateTensorInfo(h),x}var uK={kernelName:Mi,backendName:\"webgl\",kernelFunc:cv},dK=R3+`\n  return max(a, b);\n`,pK=`\n  vec4 result = vec4(max(a, b));\n  bvec4 isNaNA = isnan(a);\n  bvec4 isNaNB = isnan(b);\n  bvec4 isNaN = bvec4(isNaNA.x || isNaNB.x, isNaNA.y || isNaNB.y, isNaNA.z || isNaNB.z, isNaNA.w || isNaNB.w);\n  `+pp+`\n  return result;\n`,cK=oa({opSnippet:dK,packedOpSnippet:pK,cpuKernelImpl:vU}),hK={kernelName:$i,backendName:\"webgl\",kernelFunc:cK};function fK(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t;uu(r,\"maxPool\");let{filterSize:s,strides:i,pad:o,dimRoundingMode:l}=n,u=1;v.assert(T.eitherStridesOrDilationsAreOne(i,u),()=>`Error in maxPool: Either strides or dilations must be 1. Got strides ${i} and dilations '${u}'`);let p=T.computePool2DInfo(r.shape,s,i,u,o,l);if(p.filterWidth===1&&p.filterHeight===1&&v.arraysEqual(p.inShape,p.outShape))return Za({inputs:{x:r},backend:a});let c=new xd(p,\"max\",!1);return a.runWebGLProgram(c,[r],r.dtype)}var mK={kernelName:_i,backendName:\"webgl\",kernelFunc:fK};function gK(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{filterSize:s,strides:i,pad:o,dataFormat:l,dimRoundingMode:u}=n,p=[1,1,1],c=T.computePool3DInfo(r.shape,s,i,p,o,u,l),d=new $3(c,\"max\",!1);return a.runWebGLProgram(d,[r],r.dtype)}var xK={kernelName:nh,backendName:\"webgl\",kernelFunc:gK},AK=class{constructor(e){this.variableNames=[\"dy\",\"maxPos\"],this.outputShape=e.inShape;let t=e.strideHeight,a=e.strideWidth,n=e.dilationHeight,r=e.effectiveFilterHeight,s=e.effectiveFilterWidth,i=r-1-e.padInfo.top,o=s-1-e.padInfo.left,l=r*s-1;this.userCode=`\n      const ivec2 pads = ivec2(${i}, ${o});\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int d = coords[3];\n\n        ivec2 dyRCCorner = coords.yz - pads;\n        int dyRCorner = dyRCCorner.x;\n        int dyCCorner = dyRCCorner.y;\n\n        // Convolve dy(?, ?, d) with pos mask(:, :, d) to get dx(xR, xC, d).\n        // ? = to be determined. : = across all values in that axis.\n        float dotProd = 0.0;\n        for (int wR = 0; wR < ${r};\n          wR += ${n}) {\n          float dyR = float(dyRCorner + wR) / ${t}.0;\n\n          if (dyR < 0.0 || dyR >= ${e.outHeight}.0 || fract(dyR) > 0.0) {\n            continue;\n          }\n          int idyR = int(dyR);\n\n          for (int wC = 0; wC < ${s}; wC++) {\n            float dyC = float(dyCCorner + wC) / ${a}.0;\n\n            if (dyC < 0.0 || dyC >= ${e.outWidth}.0 ||\n                fract(dyC) > 0.0) {\n              continue;\n            }\n            int idyC = int(dyC);\n\n            float dyValue = getDy(b, idyR, idyC, d);\n            int maxPosValue = ${l} - int(getMaxPos(b, idyR, idyC, d));\n\n            // Get the current value, check it against the value from the\n            // position matrix.\n            int curPosValue = wR * ${s} + wC;\n            float mask = float(maxPosValue == curPosValue ? 1.0 : 0.0);\n\n            dotProd += dyValue * mask;\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}},yK=class{constructor(e){this.variableNames=[\"dy\",\"maxPos\"],this.outputShape=e.inShape;let t=e.strideDepth,a=e.strideHeight,n=e.strideWidth,r=e.dilationDepth,s=e.dilationHeight,i=e.dilationWidth,o=e.effectiveFilterDepth,l=e.effectiveFilterHeight,u=e.effectiveFilterWidth,p=o-1-e.padInfo.front,c=l-1-e.padInfo.top,d=u-1-e.padInfo.left,h=o*l*u-1;this.userCode=`\n      const ivec3 pads = ivec3(${p}, ${c}, ${d});\n\n      void main() {\n        ivec5 coords = getOutputCoords();\n        int batch = coords.x;\n        int ch = coords.u;\n\n        ivec3 dyCorner = ivec3(coords.y, coords.z, coords.w) - pads;\n        int dyDCorner = dyCorner.x;\n        int dyRCorner = dyCorner.y;\n        int dyCCorner = dyCorner.z;\n\n        // Convolve dy(?, ?, ?, ch) with pos mask(:, :, :, d) to get\n        // dx(xD, xR, xC, ch).\n        // ? = to be determined. : = across all values in that axis.\n        float dotProd = 0.0;\n\n        for (int wD = 0; wD < ${o};\n           wD += ${r}) {\n          float dyD = float(dyDCorner + wD) / ${t}.0;\n\n          if (dyD < 0.0 || dyD >= ${e.outDepth}.0 || fract(dyD) > 0.0) {\n            continue;\n          }\n          int idyD = int(dyD);\n\n          for (int wR = 0; wR < ${l};\n              wR += ${s}) {\n            float dyR = float(dyRCorner + wR) / ${a}.0;\n\n            if (dyR < 0.0 || dyR >= ${e.outHeight}.0 ||\n                fract(dyR) > 0.0) {\n              continue;\n            }\n            int idyR = int(dyR);\n\n            for (int wC = 0; wC < ${u};\n                wC += ${i}) {\n              float dyC = float(dyCCorner + wC) / ${n}.0;\n\n              if (dyC < 0.0 || dyC >= ${e.outWidth}.0 ||\n                  fract(dyC) > 0.0) {\n                continue;\n              }\n              int idyC = int(dyC);\n\n              float dyValue = getDy(batch, idyD, idyR, idyC, ch);\n              int maxPosValue = ${h} -\n                  int(getMaxPos(batch, idyD, idyR, idyC, ch));\n\n              // Get the current value, check it against the value from the\n              // position matrix.\n              int curPosValue =\n                  wD * ${l} * ${u} +\n                  wR * ${u} + wC;\n              float mask = float(maxPosValue == curPosValue ? 1.0 : 0.0);\n\n              dotProd += dyValue * mask;\n            }\n          }\n        }\n        setOutput(dotProd);\n      }\n    `}};function bK(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,input:s}=t,i=s,{filterSize:o,strides:l,pad:u,dimRoundingMode:p}=n,c=[1,1,1],d=T.computePool3DInfo(i.shape,o,l,c,u,p),h=new $3(d,\"max\",!0),f=a.runWebGLProgram(h,[i],i.dtype),m=new yK(d),g=a.runWebGLProgram(m,[r,f],i.dtype);return a.disposeIntermediateTensorInfo(f),g}var vK={kernelName:K1,backendName:\"webgl\",kernelFunc:bK};function wK(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,input:s,output:i}=t,o=s;uu([s,i],\"maxPoolGrad\");let{filterSize:l,strides:u,pad:p,dimRoundingMode:c}=n,d=T.computePool2DInfo(o.shape,l,u,1,p,c),h=!0,f=new xd(d,\"max\",h),m=a.runWebGLProgram(f,[o],o.dtype),g=new AK(d),x=a.runWebGLProgram(g,[r,m],o.dtype);return a.disposeIntermediateTensorInfo(m),x}var kK={kernelName:X1,backendName:\"webgl\",kernelFunc:wK};function IK(e,t,a,n){let r=new xd(a,\"max\",!1),s=n.runWebGLProgram(r,[e],\"float32\");r=new xd(a,\"max\",!0,!0,t);let i=n.runWebGLProgram(r,[e],\"float32\");return[s,i]}var SK={kernelName:rh,backendName:\"webgl\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{x:n}=e,{filterSize:r,strides:s,pad:i,includeBatchInIndex:o}=t,l=a;v.assert(n.shape.length===4,()=>`Error in maxPool: input must be rank 4 but got rank ${n.shape.length}.`);let u=[1,1];v.assert(T.eitherStridesOrDilationsAreOne(s,u),()=>`Error in maxPool: Either strides or dilations must be 1. Got strides ${s} and dilations '${u}'`);let p=T.computePool2DInfo(n.shape,r,s,u,i),[c,d]=IK(n,o,p,l);return[c,d]}};function TK(e,t,a,n){let r=v.sizeFromShape(t),s=v.sizeFromShape(e.shape)/r,i=ce({inputs:{x:e},attrs:{shape:[s,r]},backend:n}),o=bo(i,\"float32\",\"mean\",n),l=ce({inputs:{x:o},attrs:{shape:a},backend:n});return n.disposeIntermediateTensorInfo(i),n.disposeIntermediateTensorInfo(o),l}var CK={kernelName:Pi,backendName:\"webgl\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{x:n}=e,{keepDims:r,axis:s}=t,i=a,o=n.shape.length,l=v.parseAxisParam(s,n.shape),u=l,p=T.getAxesPermutation(u,o),c=p!=null,d=i.shouldExecuteOnCPU([n]),h=[],f=n;if(c){if(d){let y=i.texData.get(f.dataId).values,b=new Array(o);for(let C=0;C<b.length;C++)b[C]=n.shape[p[C]];let w=E3(y,n.shape,n.dtype,p,b);f=i.makeTensorInfo(b,n.dtype);let S=i.texData.get(f.dataId);S.values=w}else f=Dh(n,p,i);h.push(f),u=T.getInnerMostAxes(u.length,o)}T.assertAxesAreInnerMostDims(\"sum\",u,o);let[m,g]=T.computeOutAndReduceShapes(f.shape,u),x=m;r&&(x=T.expandShapeToKeepDim(m,l));let A=TK(f,g,x,i);for(let y of h)i.disposeIntermediateTensorInfo(y);return A}};function NK(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n,o=r.shape.length,l=v.parseAxisParam(s,r.shape),u=l,p=T.getAxesPermutation(u,o),c=r;p!=null&&(c=Ia({inputs:{x:r},backend:a,attrs:{perm:p}}),u=T.getInnerMostAxes(u.length,r.shape.length)),T.assertAxesAreInnerMostDims(\"min\",u,o);let[d,h]=T.computeOutAndReduceShapes(c.shape,u),f=v.sizeFromShape(h),m=ce({inputs:{x:c},backend:a,attrs:{shape:[-1,f]}}),g=bo(m,m.dtype,\"min\",a),x;if(i){let A=T.expandShapeToKeepDim(d,l);x=ce({inputs:{x:g},backend:a,attrs:{shape:A}})}else x=ce({inputs:{x:g},backend:a,attrs:{shape:d}});return a.disposeIntermediateTensorInfo(m),a.disposeIntermediateTensorInfo(g),p!=null&&a.disposeIntermediateTensorInfo(c),x}var EK={kernelName:Fi,backendName:\"webgl\",kernelFunc:NK},RK=R3+`\n  return min(a, b);\n`,MK=`\n  vec4 result = vec4(min(a, b));\n  bvec4 isNaNA = isnan(a);\n  bvec4 isNaNB = isnan(b);\n  bvec4 isNaN = bvec4(isNaNA.x || isNaNB.x, isNaNA.y || isNaNB.y, isNaNA.z || isNaNB.z, isNaNA.w || isNaNB.w);\n  `+pp+`\n  return result;\n`,$K=oa({opSnippet:RK,packedOpSnippet:MK,cpuKernelImpl:wU}),_K={kernelName:Oi,backendName:\"webgl\",kernelFunc:$K},PK=class{constructor(e,t,a){this.variableNames=[\"x\"],this.outputShape=t.map((u,p)=>u[0]+e[p]+u[1]);let n=e.length,r=gt(n),s=t.map(u=>u[0]).join(\",\"),i=t.map((u,p)=>u[0]+e[p]).join(\",\"),o=[\"coords[0]\",\"coords[1]\",\"coords[2]\",\"coords[3]\"].slice(0,n),l=a===\"reflect\"?0:1;if(n===1){this.userCode=`\n        int start = ${s};\n        int end = ${i};\n\n        void main() {\n          int outC = getOutputCoords();\n          if (outC < start) {\n            outC = start * 2 - outC - ${l};\n          } else if(outC >= end) {\n            outC = (end - 1) * 2 - outC + ${l};\n          }\n          setOutput(getX(outC - start));\n        }\n      `;return}this.userCode=`\n      ${r} start = ${r}(${s});\n      ${r} end = ${r}(${i});\n\n      void main() {\n        ${r} outC = getOutputCoords();\n        for (int i = 0; i < ${n}; i++) {\n          if (outC[i] < start[i]) {\n            outC[i] = start[i] * 2 - outC[i] - ${l};\n          } else if(outC[i] >= end[i]) {\n            outC[i] = (end[i] - 1) * 2 - outC[i] + ${l};\n          }\n        }\n        ${r} coords = outC - start;\n        setOutput(getX(${o}));\n      }\n    `}},FK=class{constructor(e,t,a){this.variableNames=[\"x\"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=t.map((h,f)=>h[0]+e[f]+h[1]);let n=e.length,r=gt(n),s=t.map(h=>h[0]).join(\",\"),i=t.map((h,f)=>h[0]+e[f]).join(\",\"),o=va(\"rc\",n),l=va(\"source\",n),u=`${o[n-1]} < ${this.outputShape[n-1]}`,p=n===1?\"source\":`vec2(${l.slice(-2).join()})`,c=a===\"reflect\"?0:1,d=\"\";if(n===1){let h=`\n        ${r} source = rc;\n        if (source < start) {\n          source = start * 2 - source - ${c};\n        } else if (source >= end) {\n          source = (end - 1) * 2 - source + ${c};\n        }\n        source -= start;\n      `;d=`\n        ${r} rc = outputLoc;\n        ${h}\n        result[0] = getChannel(getX(${l.join()}), ${p});\n        ${o[n-1]} += 1;\n        if(${u}) {\n          ${h}\n          result[1] = getChannel(getX(${l.join()}), ${p});\n        }\n      `}else{let h=`\n        ${r} source = rc;\n        ${r} lt = ${r}(lessThan(source, start));\n        ${r} gte = ${r}(greaterThanEqual(source, end));\n        ${r} orig = 1 - (lt + gte);\n        source = orig * source +\n                lt * (start * 2 - source - ${c}) +\n                gte * ((end - 1) * 2 - source + ${c});\n        source -= start;\n      `;d=`\n        ${r} rc = outputLoc;\n        ${h}\n        result[0] = getChannel(getX(${l.join()}), ${p});\n        ${o[n-1]} += 1;\n        if(${u}) {\n          ${h}\n          result[1] = getChannel(getX(${l.join()}), ${p});\n        }\n        rc = outputLoc;\n        ${o[n-2]} += 1;\n        if(${o[n-2]} < ${this.outputShape[n-2]}) {\n          ${h}\n          result[2] = getChannel(getX(${l.join()}), ${p});\n          ${o[n-1]} += 1;\n          if(${u}) {\n            ${h}\n            result[3] = getChannel(getX(${l.join()}), ${p});\n          }\n        }\n      `}this.userCode=`\n      const ${r} start = ${r}(${s});\n      const ${r} end = ${r}(${i});\n\n      void main() {\n        ${r} outputLoc = getOutputCoords();\n        vec4 result = vec4(0.);\n        ${d}\n        setOutput(result);\n      }\n    `}},OK=({inputs:e,backend:t,attrs:a})=>{let{x:n}=e,{paddings:r,mode:s}=a,i=W().getBool(\"WEBGL_PACK_ARRAY_OPERATIONS\")?new FK(n.shape,r,s):new PK(n.shape,r,s);return t.runWebGLProgram(i,[n],n.dtype)},DK={kernelName:Di,backendName:\"webgl\",kernelFunc:OK},zK=`if (b == 0.0) return NAN;\n  return mod(a, b);`,LK=`\n  vec4 result = mod(a, b);\n  bvec4 isNaN = equal(b, vec4(0.0));\n  `+pp+`\n  return result;\n`,BK=oa({opSnippet:zK,packedOpSnippet:LK}),WK={kernelName:Wl,backendName:\"webgl\",kernelFunc:BK},VK=class{constructor(e,t,a){this.variableNames=[\"probs\"],this.customUniforms=[{name:\"seed\",type:\"float\"}],this.outputShape=[e,a],this.userCode=`\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int batch = coords[0];\n\n        float r = random(seed);\n        float cdf = 0.0;\n\n        for (int i = 0; i < ${t-1}; i++) {\n          cdf += getProbs(batch, i);\n\n          if (r < cdf) {\n            setOutput(float(i));\n            return;\n          }\n        }\n\n        // If no other event happened, last event happened.\n        setOutput(float(${t-1}));\n      }\n    `}},UK=`\nif (a == b) {\n  return 1.0;\n};\nreturn a / b;`,GK=`\n  // vec4 one = vec4(equal(a, b));\n  // return one + (vec4(1.0) - one) * a / b;\n  vec4 result = a / b;\n  if(a.x == b.x) {\n    result.x = 1.;\n  }\n  if(a.y == b.y) {\n    result.y = 1.;\n  }\n  if(a.z == b.z) {\n    result.z = 1.;\n  }\n  if(a.w == b.w) {\n    result.w = 1.;\n  }\n\n  return result;\n`,hv=oa({opSnippet:UK,packedOpSnippet:GK,checkOutOfBounds:!0}),HK={kernelName:ci,backendName:\"webgl\",kernelFunc:hv},$x=\"return a - b;\",fv=oa({opSnippet:$x,packedOpSnippet:$x,supportsComplex:!0,cpuKernelImpl:VU}),jK={kernelName:lo,backendName:\"webgl\",kernelFunc:fv};function mv(e){let{inputs:t,backend:a,attrs:n}=e,{logits:r}=t,{dim:s}=n,i=v.parseAxisParam([s],r.shape),o=cv({inputs:{x:r},backend:a,attrs:{reductionIndices:i,keepDims:!1}}),l=T.expandShapeToKeepDim(o.shape,i),u=ce({inputs:{x:o},backend:a,attrs:{shape:l}}),p=fv({inputs:{a:r,b:u},backend:a}),c=uv({inputs:{x:p},backend:a}),d=zh({inputs:{x:c},backend:a,attrs:{axis:i,keepDims:!1}}),h=ce({inputs:{x:d},backend:a,attrs:{shape:l}}),f=hv({inputs:{a:c,b:h},backend:a});return a.disposeIntermediateTensorInfo(o),a.disposeIntermediateTensorInfo(u),a.disposeIntermediateTensorInfo(p),a.disposeIntermediateTensorInfo(c),a.disposeIntermediateTensorInfo(d),a.disposeIntermediateTensorInfo(h),f}var qK={kernelName:so,backendName:\"webgl\",kernelFunc:mv};function XK(e){let{inputs:t,backend:a,attrs:n}=e,{logits:r}=t,{numSamples:s,seed:i,normalized:o}=n,l=o?r:mv({inputs:{logits:r},backend:a,attrs:{dim:r.shape.length-1}}),u=l.shape[0],p=l.shape[1],c=new VK(u,p,s),d=[[i]],h=a.runWebGLProgram(c,[l],\"int32\",d);return o||a.disposeIntermediateTensorInfo(l),h}var KK={kernelName:sh,backendName:\"webgl\",kernelFunc:XK},ZK=Cn+`\n  return -x;\n`,YK=`\n  vec4 result = -x;\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n`;function JK(e){let{inputs:t,backend:a}=e,{x:n}=t;if(a.shouldExecuteOnCPU([n])){let s=a.texData.get(n.dataId),[i,o]=IU(s.values,n.shape,n.dtype);return a.makeTensorInfo(o,n.dtype,i)}let r;return W().getBool(\"WEBGL_PACK_UNARY_OPERATIONS\")?r=new Vr(n.shape,YK):r=new qn(n.shape,ZK),a.runWebGLProgram(r,[n],n.dtype)}var QK={kernelName:Vl,backendName:\"webgl\",kernelFunc:JK},eZ=Tn.nonMaxSuppressionV3Impl;function tZ(e){T.warn(\"tf.nonMaxSuppression() in webgl locks the UI thread. Call tf.nonMaxSuppressionAsync() instead\");let{inputs:t,backend:a,attrs:n}=e,{boxes:r,scores:s}=t,{maxOutputSize:i,iouThreshold:o,scoreThreshold:l}=n,u=a.readSync(r.dataId),p=a.readSync(s.dataId),{selectedIndices:c}=eZ(u,p,i,o,l);return a.makeTensorInfo([c.length],\"int32\",new Int32Array(c))}var aZ={kernelName:Bi,backendName:\"webgl\",kernelFunc:tZ},nZ=Tn.nonMaxSuppressionV4Impl;function rZ(e){T.warn(\"tf.nonMaxSuppression() in webgl locks the UI thread. Call tf.nonMaxSuppressionAsync() instead\");let{inputs:t,backend:a,attrs:n}=e,{boxes:r,scores:s}=t,{maxOutputSize:i,iouThreshold:o,scoreThreshold:l,padToMaxOutputSize:u}=n,p=a.readSync(r.dataId),c=a.readSync(s.dataId),{selectedIndices:d,validOutputs:h}=nZ(p,c,i,o,l,u);return[a.makeTensorInfo([d.length],\"int32\",new Int32Array(d)),a.makeTensorInfo([],\"int32\",new Int32Array([h]))]}var sZ={kernelName:Ul,backendName:\"webgl\",kernelFunc:rZ},iZ=Tn.nonMaxSuppressionV5Impl;function oZ(e){T.warn(\"tf.nonMaxSuppression() in webgl locks the UI thread. Call tf.nonMaxSuppressionAsync() instead\");let{inputs:t,backend:a,attrs:n}=e,{boxes:r,scores:s}=t,{maxOutputSize:i,iouThreshold:o,scoreThreshold:l,softNmsSigma:u}=n,p=a.readSync(r.dataId),c=a.readSync(s.dataId),d=i,h=o,f=l,m=u,{selectedIndices:g,selectedScores:x}=iZ(p,c,d,h,f,m);return[a.makeTensorInfo([g.length],\"int32\",new Int32Array(g)),a.makeTensorInfo([x.length],\"float32\",new Float32Array(x))]}var lZ={kernelName:Wi,backendName:\"webgl\",kernelFunc:oZ},uZ=class{constructor(e,t,a,n){this.variableNames=[\"indices\"],this.outputShape=[e,t],this.userCode=`\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int index = round(getIndices(coords.x));\n        setOutput(mix(float(${n}), float(${a}),\n                      float(index == coords.y)));\n      }\n    `}},dZ=e=>{let{inputs:t,backend:a,attrs:n}=e,{indices:r}=t,{dtype:s,depth:i,onValue:o,offValue:l}=n,u=v.sizeFromShape(r.shape),p=new uZ(u,i,o,l),c=ce({inputs:{x:r},backend:a,attrs:{shape:[u]}}),d=a.runWebGLProgram(p,[c],s);a.disposeIntermediateTensorInfo(c);let h=[...r.shape,i],f=ce({inputs:{x:d},backend:a,attrs:{shape:h}});return a.disposeIntermediateTensorInfo(d),f},pZ={kernelName:Vi,backendName:\"webgl\",kernelFunc:dZ};function Lc(e){let{inputs:t,backend:a}=e,{x:n}=t;if(n.dtype===\"complex64\"){let r=hp({inputs:{input:n},backend:a}),s=Lc({inputs:{x:r},backend:a}),i=Lh({inputs:{input:n},backend:a}),o=Lc({inputs:{x:i},backend:a}),l=ls({inputs:{real:s,imag:o},backend:a});return a.disposeIntermediateTensorInfo(r),a.disposeIntermediateTensorInfo(s),a.disposeIntermediateTensorInfo(i),a.disposeIntermediateTensorInfo(o),l}else return fp({attrs:{shape:n.shape,dtype:n.dtype,value:n.dtype===\"string\"?\"\":0},backend:a})}var cZ={kernelName:nu,backendName:\"webgl\",kernelFunc:Lc};function gv(e){let{inputs:t,backend:a}=e,{x:n}=t;if(n.dtype===\"string\")throw new Error(\"onesLike is not supported under string dtype\");if(n.dtype===\"complex64\"){let r=hp({inputs:{input:n},backend:a}),s=gv({inputs:{x:r},backend:a}),i=Lh({inputs:{input:n},backend:a}),o=Lc({inputs:{x:i},backend:a}),l=ls({inputs:{real:s,imag:o},backend:a});return a.disposeIntermediateTensorInfo(r),a.disposeIntermediateTensorInfo(s),a.disposeIntermediateTensorInfo(i),a.disposeIntermediateTensorInfo(o),l}else return fp({attrs:{shape:n.shape,dtype:n.dtype,value:1},backend:a})}var hZ={kernelName:Gl,backendName:\"webgl\",kernelFunc:gv};function fZ(e){let{inputs:t,backend:a,attrs:n}=e,{axis:r}=n;if(t.length===1)return N1({inputs:{input:t[0]},backend:a,attrs:{dim:r}});let s=t[0].shape,i=t[0].dtype;t.forEach(p=>{v.assertShapesMatch(s,p.shape,\"All tensors passed to stack must have matching shapes\"),v.assert(i===p.dtype,()=>\"All tensors passed to stack must have matching dtypes\")});let o=[],l=t.map(p=>{let c=N1({inputs:{input:p},backend:a,attrs:{dim:r}});return o.push(c),c}),u=tv({inputs:l,backend:a,attrs:{axis:r}});return o.forEach(p=>a.disposeIntermediateTensorInfo(p)),u}var mZ={kernelName:Hl,backendName:\"webgl\",kernelFunc:fZ},gZ=class{constructor(e,t,a){this.variableNames=[\"x\"],this.customUniforms=[{name:\"value\",type:\"float\"}],this.outputShape=t.map((l,u)=>l[0]+e[u]+l[1]);let n=e.length,r=gt(n),s=t.map(l=>l[0]).join(\",\"),i=t.map((l,u)=>l[0]+e[u]).join(\",\"),o=[\"coords[0]\",\"coords[1]\",\"coords[2]\",\"coords[3]\"].slice(0,n);if(n===1){this.userCode=`\n        int start = ${s};\n        int end = ${i};\n\n        void main() {\n          int outC = getOutputCoords();\n          if (outC < start || outC >= end) {\n            setOutput(value);\n          } else {\n            setOutput(getX(outC - start));\n          }\n        }\n      `;return}this.userCode=`\n      ${r} start = ${r}(${s});\n      ${r} end = ${r}(${i});\n\n      void main() {\n        ${r} outC = getOutputCoords();\n        if (any(lessThan(outC, start)) || any(greaterThanEqual(outC, end))) {\n          setOutput(value);\n        } else {\n          ${r} coords = outC - start;\n          setOutput(getX(${o}));\n        }\n      }\n    `}},xZ=class{constructor(e,t,a){this.variableNames=[\"x\"],this.packedInputs=!0,this.packedOutput=!0,this.customUniforms=[{name:\"value\",type:\"float\"}],this.outputShape=t.map((f,m)=>f[0]+e[m]+f[1]);let n=e.length,r=gt(n),s=t.map(f=>f[0]).join(\",\"),i=t.map((f,m)=>f[0]+e[m]).join(\",\"),o=va(\"rc\",n),l=va(\"source\",n),u=`${o[n-1]} < ${this.outputShape[n-1]}`,p=n===1?\"source\":`vec2(${l.slice(-2).join()})`,c=[`${r} rc = outputLoc;`,`${o[n-1]} += 1;\n       if(${u}) {\n      `,n===1?\"\":`}\n       rc = outputLoc;\n       ${o[n-2]} += 1;\n       if(${o[n-2]} < ${this.outputShape[n-2]}) {`,n===1?\"\":`  ${o[n-1]} += 1;\n         if(${u}) {`],d=n===1?\"rc < start || rc >= end\":\"any(lessThan(rc, start)) || any(greaterThanEqual(rc, end))\",h=\"\";for(let f=0,m=n===1?2:4;f<m;f++)h+=`\n        ${c[f]}\n        if (${d}) {\n          result[${f}] = float(value);\n        } else {\n          ${r} source = rc - start;\n          result[${f}] = getChannel(getX(${l.join()}), ${p});\n        }\n      `;h+=n===1?\"} \":\"}}\",this.userCode=`\n      const ${r} start = ${r}(${s});\n      const ${r} end = ${r}(${i});\n\n      void main() {\n        ${r} outputLoc = getOutputCoords();\n        vec4 result = vec4(0.);\n        ${h}\n        setOutput(result);\n      }\n    `}},xv=e=>{let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{paddings:s,constantValue:i}=n;if(v.sizeFromShape(r.shape)===0){let u=s.map((p,c)=>p[0]+r.shape[c]+p[1]);return fp({backend:a,attrs:{shape:u,value:i,dtype:r.dtype}})}let o=W().getBool(\"WEBGL_PACK_ARRAY_OPERATIONS\")?new xZ(r.shape,s,i):new gZ(r.shape,s,i),l=[[i]];return a.runWebGLProgram(o,[r],r.dtype,l)},AZ={kernelName:Ui,backendName:\"webgl\",kernelFunc:xv},yZ=`\n  if(a < 0.0 && floor(b) < b){\n    return NAN;\n  }\n  if (b == 0.0) {\n    return 1.0;\n  }\n  return (round(mod(b, 2.0)) != 1) ?\n      pow(abs(a), b) : sign(a) * pow(abs(a), b);\n`,bZ=`\n  // isModRound1 has 1 for components with round(mod(b, 2.0)) == 1, 0 otherwise.\n  vec4 isModRound1 = vec4(equal(round(mod(b, 2.0)), ivec4(1)));\n  vec4 multiplier = sign(a) * isModRound1 + (vec4(1.0) - isModRound1);\n  vec4 result = multiplier * pow(abs(a), b);\n\n  // Ensure that a^0 = 1, including 0^0 = 1 as this correspond to TF and JS\n  bvec4 isExpZero = equal(b, vec4(0.0));\n  result.r = isExpZero.r ? 1.0 : result.r;\n  result.g = isExpZero.g ? 1.0 : result.g;\n  result.b = isExpZero.b ? 1.0 : result.b;\n  result.a = isExpZero.a ? 1.0 : result.a;\n\n  bvec4 isNaN1 = lessThan(a, vec4(0.0));\n  bvec4 isNaN2 = lessThan(floor(b), b);\n  bvec4 isNaN = bvec4(isNaN1.x && isNaN2.x, isNaN1.y && isNaN2.y, isNaN1.z && isNaN2.z, isNaN1.w && isNaN2.w);\n  `+pp+`\n  return result;\n`,vZ=oa({opSnippet:yZ,packedOpSnippet:bZ}),wZ={kernelName:Gi,backendName:\"webgl\",kernelFunc:vZ};function kZ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n,o=r.shape.length,l=[],u=v.parseAxisParam(s,r.shape),p=u,c=T.getAxesPermutation(p,o),d=r;c!=null&&(d=Ia({inputs:{x:r},backend:a,attrs:{perm:c}}),p=T.getInnerMostAxes(p.length,o),l.push(d)),T.assertAxesAreInnerMostDims(\"prod\",p,o);let h;if(a.shouldExecuteOnCPU([d])){let f=a.texData.get(d.dataId).values,{outVals:m,outShape:g,outDtype:x}=TU(d.shape,d.dtype,f,p);h=a.makeTensorInfo(g,x,m)}else{let[f,m]=T.computeOutAndReduceShapes(d.shape,p),g=v.sizeFromShape(m),x=ce({inputs:{x:d},backend:a,attrs:{shape:[-1,g]}}),A=Hd(r.dtype),y=bo(x,A,\"prod\",a);h=ce({inputs:{x:y},backend:a,attrs:{shape:f}}),l.push(x),l.push(y)}if(i){l.push(h);let f=T.expandShapeToKeepDim(h.shape,u);h=ce({inputs:{x:h},backend:a,attrs:{shape:f}})}return l.forEach(f=>a.disposeIntermediateTensorInfo(f)),h}var IZ={kernelName:ji,backendName:\"webgl\",kernelFunc:kZ};function SZ(e){let{inputs:t,backend:a,attrs:n}=e,{paramsNestedSplits:r,paramsDenseValues:s,indices:i}=t,{outputRaggedRank:o}=n,l=r.map(x=>a.readSync(x.dataId)),u=r.map(x=>x.shape),p=a.readSync(s.dataId),c=a.readSync(i.dataId),[d,h,f]=CU(l,u,p,s.shape,s.dtype,c,i.shape,o),m=d.map(x=>a.makeTensorInfo([x.length],\"int32\",x)),g=a.makeTensorInfo(f,s.dtype,h);return m.concat([g])}var TZ={kernelName:ih,backendName:\"webgl\",kernelFunc:SZ};function CZ(e){let{inputs:t,backend:a}=e,{starts:n,limits:r,deltas:s}=t,i=a.readSync(n.dataId),o=a.readSync(r.dataId),l=a.readSync(s.dataId),[u,p]=NU(i,n.shape,n.dtype,o,r.shape,l,s.shape),c=a.makeTensorInfo([u.length],\"int32\",u),d=a.makeTensorInfo([p.length],n.dtype,p);return[c,d]}var NZ={kernelName:oh,backendName:\"webgl\",kernelFunc:CZ};function EZ(e){let{inputs:t,backend:a,attrs:n}=e,{shape:r,values:s,defaultValue:i,rowPartitionTensors:o}=t,{rowPartitionTypes:l}=n,u=a.readSync(r.dataId),p=a.readSync(s.dataId),c=a.readSync(i.dataId),d=o.map(g=>a.readSync(g.dataId)),h=o.map(g=>g.shape),[f,m]=EU(u,r.shape,p,s.shape,s.dtype,c,i.shape,d,h,l);return a.makeTensorInfo(f,s.dtype,m)}var RZ={kernelName:lh,backendName:\"webgl\",kernelFunc:EZ},Av=e=>{let{backend:t,attrs:a}=e,{start:n,stop:r,step:s,dtype:i}=a,o=RU(n,r,s,i);return t.makeTensorInfo([o.length],i,o)},MZ={kernelName:jl,backendName:\"webgl\",kernelFunc:Av},$Z=\"return 1.0 / x;\",_Z=Qe({opSnippet:$Z}),PZ={kernelName:qi,backendName:\"webgl\",kernelFunc:_Z},FZ=Cn+`\n  return (x < 0.0) ? 0.0 : x;\n`,OZ=`\n  vec4 result = x * vec4(greaterThanEqual(x, vec4(0.0)));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n`,DZ=Qe({opSnippet:FZ,packedOpSnippet:OZ}),zZ={kernelName:Xi,backendName:\"webgl\",kernelFunc:DZ},LZ=Cn+`\n  return (x < 0.0) ? 0.0 : min(6.0, x);\n`,BZ=`\n  vec4 result = min(x, vec4(6.)) * vec4(greaterThanEqual(x, vec4(0.0)));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n`,WZ=Qe({opSnippet:LZ,packedOpSnippet:BZ}),VZ={kernelName:Yi,backendName:\"webgl\",kernelFunc:WZ},UZ=class{constructor(e,t,a,n,r){this.variableNames=[\"A\"],this.outputShape=[];let[s,i,o,l]=e;this.outputShape=[s,t,a,l];let u=[n&&t>1?i-1:i,n&&a>1?o-1:o],p=[n&&t>1?t-1:t,n&&a>1?a-1:a],c;r?c=\"(vec2(yRC) + vec2(0.5)) * effectiveInputOverOutputRatioRC - vec2(0.5)\":c=\"vec2(yRC) * effectiveInputOverOutputRatioRC\",this.userCode=`\n      const vec2 effectiveInputOverOutputRatioRC = vec2(\n          ${u[0]/p[0]},\n          ${u[1]/p[1]});\n      const vec2 inputShapeRC = vec2(${i}.0, ${o}.0);\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int d = coords[3];\n        ivec2 yRC = coords.yz;\n\n        // Fractional source index.\n        vec2 sourceFracIndexRC = ${c};\n\n        // Compute the four integer indices.\n        ivec2 sourceFloorRC = ivec2(max(sourceFracIndexRC, vec2(0.0)));\n        ivec2 sourceCeilRC = ivec2(\n          min(inputShapeRC - 1.0, ceil(sourceFracIndexRC)));\n\n        float topLeft = getA(b, sourceFloorRC.x, sourceFloorRC.y, d);\n        float bottomLeft = getA(b, sourceCeilRC.x, sourceFloorRC.y, d);\n        float topRight = getA(b, sourceFloorRC.x, sourceCeilRC.y, d);\n        float bottomRight = getA(b, sourceCeilRC.x, sourceCeilRC.y, d);\n\n        vec2 fracRC = sourceFracIndexRC - vec2(sourceFloorRC);\n\n        float top = topLeft + (topRight - topLeft) * fracRC.y;\n        float bottom = bottomLeft + (bottomRight - bottomLeft) * fracRC.y;\n        float newValue = top + (bottom - top) * fracRC.x;\n\n        setOutput(newValue);\n      }\n    `}},GZ=class{constructor(e,t,a,n,r){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=[];let[s,i,o,l]=e;this.outputShape=[s,t,a,l];let u=[n&&t>1?i-1:i,n&&a>1?o-1:o],p=[n&&t>1?t-1:t,n&&a>1?a-1:a],c;r?c=\"(vec3(yRC) + vec3(0.5)) * effectiveInputOverOutputRatioRC - vec3(0.5)\":c=\"vec3(yRC) * effectiveInputOverOutputRatioRC\",this.userCode=`\n      const vec3 effectiveInputOverOutputRatioRC = vec3(\n          ${u[0]/p[0]},\n          ${u[1]/p[1]},\n          ${u[1]/p[1]});\n      const vec3 inputShapeRC = vec3(${i}.0, ${o}.0,\n                                     ${o}.0);\n\n      float getAValue(int b, int r, int c, int d) {\n        return getChannel(getA(b, r, c, d), vec2(c, d));\n      }\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int d = coords[3];\n        // Calculate values for next column in yRC.z.\n        ivec3 yRC = coords.yzz + ivec3(0, 0, 1);\n\n        // Fractional source index.\n        vec3 sourceFracIndexRC = ${c};\n\n        // Compute the four integer indices.\n        ivec3 sourceFloorRC = ivec3(max(sourceFracIndexRC, vec3(0.0)));\n        ivec3 sourceCeilRC = ivec3(\n          min(inputShapeRC - 1.0, ceil(sourceFracIndexRC)));\n\n        // Should we calculate next column and row elements in 2x2 packed cell.\n        bool hasNextCol = d < ${l-1};\n        bool hasNextRow = coords.z < ${a-1};\n\n        // In parallel, construct four corners for all four components in\n        // packed 2x2 cell.\n        vec4 topLeft = vec4(\n          getAValue(b, sourceFloorRC.x, sourceFloorRC.y, d),\n          hasNextCol ? getAValue(b, sourceFloorRC.x, sourceFloorRC.y, d + 1)\n                     : 0.0,\n          hasNextRow ? getAValue(b, sourceFloorRC.x, sourceFloorRC.z, d)\n                     : 0.0,\n          (hasNextRow && hasNextCol) ?\n            getAValue(b, sourceFloorRC.x, sourceFloorRC.z, d + 1) : 0.0);\n\n        vec4 bottomLeft = vec4(\n          getAValue(b, sourceCeilRC.x, sourceFloorRC.y, d),\n          hasNextCol ? getAValue(b, sourceCeilRC.x, sourceFloorRC.y, d + 1)\n                     : 0.0,\n          hasNextRow ? getAValue(b, sourceCeilRC.x, sourceFloorRC.z, d)\n                     : 0.0,\n          (hasNextRow && hasNextCol) ?\n            getAValue(b, sourceCeilRC.x, sourceFloorRC.z, d + 1) : 0.0);\n\n        vec4 topRight = vec4(\n          getAValue(b, sourceFloorRC.x, sourceCeilRC.y, d),\n          hasNextCol ? getAValue(b, sourceFloorRC.x, sourceCeilRC.y, d + 1)\n                     : 0.0,\n          hasNextRow ? getAValue(b, sourceFloorRC.x, sourceCeilRC.z, d)\n                     : 0.0,\n          (hasNextRow && hasNextCol) ?\n            getAValue(b, sourceFloorRC.x, sourceCeilRC.z, d + 1) : 0.0);\n\n        vec4 bottomRight = vec4(\n          getAValue(b, sourceCeilRC.x, sourceCeilRC.y, d),\n          hasNextCol ? getAValue(b, sourceCeilRC.x, sourceCeilRC.y, d + 1)\n                     : 0.0,\n          hasNextRow ? getAValue(b, sourceCeilRC.x, sourceCeilRC.z, d)\n                     : 0.0,\n          (hasNextRow && hasNextCol) ?\n            getAValue(b, sourceCeilRC.x, sourceCeilRC.z, d + 1) : 0.0);\n\n        vec3 fracRC = sourceFracIndexRC - vec3(sourceFloorRC);\n\n        vec4 top = mix(topLeft, topRight, fracRC.yyzz);\n        vec4 bottom = mix(bottomLeft, bottomRight, fracRC.yyzz);\n        vec4 newValue = mix(top, bottom, fracRC.x);\n\n        setOutput(newValue);\n      }\n    `}};function HZ(e){let{inputs:t,backend:a,attrs:n}=e,{images:r}=t,{alignCorners:s,halfPixelCenters:i,size:o}=n,[l,u]=o,p=W().getBool(\"WEBGL_PACK_IMAGE_OPERATIONS\")?new GZ(r.shape,l,u,s,i):new UZ(r.shape,l,u,s,i);return a.runWebGLProgram(p,[r],\"float32\")}var jZ={kernelName:Zi,backendName:\"webgl\",kernelFunc:HZ},qZ=class{constructor(e,t,a){this.variableNames=[\"dy\"],this.outputShape=[],this.outputShape=t;let[,n,r]=t,[,s,i]=e,o=[a&&s>1?n-1:n,a&&i>1?r-1:r],l=[a&&s>1?s-1:s,a&&i>1?i-1:i],u=o[0]/l[0],p=o[1]/l[1],c=1/u,d=1/p,h=Math.ceil(c)*2+2,f=Math.ceil(d)*2+2;this.userCode=`\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int d = coords[3];\n        int r = coords[1];\n        int c = coords[2];\n\n        float accumulator = 0.0;\n\n        const float heightScale = float(${u});\n        const float widthScale = float(${p});\n\n        const float invHeightScale = float(${c});\n        const float invWidthScale = float(${d});\n\n        const int winHeight = int(${h});\n        const int winWidth = int(${f});\n\n        // Compute bounds for where in dy we will look\n        float startRLerp = floor(float(r) * invHeightScale);\n        int startDyR = int(startRLerp - float(winHeight / 2));\n\n        float startCLerp = floor(float(c) * invWidthScale);\n        int startDyC = int(startCLerp - float(winWidth / 2));\n\n        // Loop over dy\n        for (int dyROffset = 0; dyROffset < winHeight; dyROffset++) {\n          int dyR = dyROffset + startDyR;\n\n          // Guard against the window exceeding the bounds of dy\n          if (dyR < 0 || dyR >= ${s}) {\n            continue;\n          }\n\n          for (int dyCOffset = 0; dyCOffset < winWidth; dyCOffset++) {\n            int dyC = dyCOffset + startDyC;\n\n            // Guard against the window exceeding the bounds of dy\n            if (dyC < 0 || dyC >= ${i}) {\n              continue;\n            }\n\n            float dxR = float(dyR) * heightScale;\n            int topDxRIndex = int(floor(dxR));\n            int bottomDxRIndex = int(min(ceil(dxR), ${n-1}.0));\n            float dxRLerp = dxR - float(topDxRIndex);\n            float inverseDxRLerp = 1.0 - dxRLerp;\n\n            float dxC = float(dyC) * widthScale;\n            int leftDxCIndex = int(floor(dxC));\n            int rightDxCIndex = int(min(ceil(dxC), ${r-1}.0));\n            float dxCLerp = dxC - float(leftDxCIndex);\n            float inverseDxCLerp = 1.0 - dxCLerp;\n\n            if (r == topDxRIndex && c == leftDxCIndex) {\n              // topLeft\n              accumulator +=\n                getDy(b, dyR, dyC, d) * inverseDxRLerp * inverseDxCLerp;\n            }\n\n            if (r == topDxRIndex && c == rightDxCIndex) {\n              // topRight\n              accumulator += getDy(b, dyR, dyC, d) * inverseDxRLerp * dxCLerp;\n            }\n\n            if (r == bottomDxRIndex && c == leftDxCIndex) {\n              // bottomLeft\n              accumulator += getDy(b, dyR, dyC, d) * dxRLerp * inverseDxCLerp;\n            }\n\n            if (r == bottomDxRIndex && c == rightDxCIndex) {\n              // bottomRight\n              accumulator += getDy(b, dyR, dyC, d) * dxRLerp * dxCLerp;\n            }\n          }\n        }\n        // End loop over dy\n\n        setOutput(accumulator);\n      }\n    `}};function XZ(e){let{inputs:t,backend:a,attrs:n}=e,{images:r,dy:s}=t,{alignCorners:i}=n,o=new qZ(s.shape,r.shape,i);return a.runWebGLProgram(o,[s],s.dtype)}var KZ={kernelName:Y1,backendName:\"webgl\",kernelFunc:XZ},ZZ=class{constructor(e,t,a,n,r){this.variableNames=[\"A\"],this.outputShape=[];let[s,i,o,l]=e;this.outputShape=[s,t,a,l];let u=[n&&t>1?i-1:i,n&&a>1?o-1:o],p=[n&&t>1?t-1:t,n&&a>1?a-1:a],c=n?\"0.5\":\"0.0\",d;r?d=\"max((vec2(yRC) + vec2(0.5)) * effectiveInputOverOutputRatioRC, vec2(0.0))\":d=\"vec2(yRC) * effectiveInputOverOutputRatioRC\",this.userCode=`\n      const vec2 effectiveInputOverOutputRatioRC = vec2(\n          ${u[0]/p[0]},\n          ${u[1]/p[1]});\n      const vec2 inputShapeRC = vec2(${i}.0, ${o}.0);\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int d = coords[3];\n        ivec2 yRC = coords.yz;\n\n        // Fractional source index.\n        vec2 sourceFracIndexRC = ${d};\n\n        // Compute the coordinators of nearest neighbor point.\n        ivec2 sourceNearestRC = ivec2(\n          min(inputShapeRC - 1.0, floor(sourceFracIndexRC + ${c})));\n        float newValue = getA(b, sourceNearestRC.x, sourceNearestRC.y, d);\n\n        setOutput(newValue);\n      }\n    `}},YZ=class{constructor(e,t,a,n,r){this.variableNames=[\"A\"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=[];let[s,i,o,l]=e;this.outputShape=[s,t,a,l];let u=[n&&t>1?i-1:i,n&&a>1?o-1:o],p=[n&&t>1?t-1:t,n&&a>1?a-1:a],c=n?\"0.5\":\"0.0\",d;r?d=\"max((vec3(yRC) + vec3(0.5)) * effectiveInputOverOutputRatioRC, vec3(0.0))\":d=\"vec3(yRC) * effectiveInputOverOutputRatioRC\",this.userCode=`\n      const vec3 effectiveInputOverOutputRatioRC = vec3(\n          ${u[0]/p[0]},\n          ${u[1]/p[1]},\n          ${u[1]/p[1]});\n      const vec3 inputShapeRC = vec3(${i}.0, ${o}.0,\n                                     ${o}.0);\n\n      float getAValue(int b, int r, int c, int d) {\n        return getChannel(getA(b, r, c, d), vec2(c, d));\n      }\n\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int d = coords[3];\n        // Calculate values for next column in yRC.z.\n        ivec3 yRC = coords.yzz + ivec3(0, 0, 1);\n\n        // Fractional source index.\n        vec3 sourceFracIndexRC = ${d};\n\n        // Compute the coordinators of nearest neighbor point.\n        ivec3 sourceNearestRC = ivec3(\n          min(inputShapeRC - 1.0, floor(sourceFracIndexRC + ${c})));\n\n        // Should we calculate next column and row elements in 2x2 packed cell.\n        bool hasNextCol = d < ${l-1};\n        bool hasNextRow = coords.z < ${a-1};\n\n        vec4 newValue = vec4(\n          getAValue(b, sourceNearestRC.x, sourceNearestRC.y, d),\n          hasNextCol ? getAValue(b, sourceNearestRC.x, sourceNearestRC.y, d + 1)\n                     : 0.0,\n          hasNextRow ? getAValue(b, sourceNearestRC.x, sourceNearestRC.z, d)\n                     : 0.0,\n          (hasNextRow && hasNextCol) ?\n            getAValue(b, sourceNearestRC.x, sourceNearestRC.z, d + 1) : 0.0);\n\n        setOutput(newValue);\n      }\n    `}};function JZ(e){let{inputs:t,backend:a,attrs:n}=e,{images:r}=t,{alignCorners:s,halfPixelCenters:i,size:o}=n,[l,u]=o,p=W().getBool(\"WEBGL_PACK_IMAGE_OPERATIONS\")?new YZ(r.shape,l,u,s,i):new ZZ(r.shape,l,u,s,i);return a.runWebGLProgram(p,[r],r.dtype)}var QZ={kernelName:Ki,backendName:\"webgl\",kernelFunc:JZ},eY=class{constructor(e,t,a){this.variableNames=[\"dy\"],this.outputShape=[],this.outputShape=t;let[,n,r]=t,[,s,i]=e,o=[a&&s>1?n-1:n,a&&i>1?r-1:r],l=[a&&s>1?s-1:s,a&&i>1?i-1:i],u=o[0]/l[0],p=o[1]/l[1],c=1/u,d=1/p,h=Math.ceil(c)*2+2,f=Math.ceil(d)*2+2;this.userCode=`\n      void main() {\n        ivec4 coords = getOutputCoords();\n        int b = coords[0];\n        int d = coords[3];\n        int r = coords[1];\n        int c = coords[2];\n\n        float accumulator = 0.0;\n\n        const float heightScale = float(${u});\n        const float widthScale = float(${p});\n\n        const float invHeightScale = float(${c});\n        const float invWidthScale = float(${d});\n\n        const int winHeight = int(${h});\n        const int winWidth = int(${f});\n\n        // Compute bounds for where in dy we will look\n        float startRLerp = floor(float(r) * invHeightScale);\n        int startDyR = int(floor(startRLerp - float(winHeight / 2)));\n\n        float startCLerp = floor(float(c) * invWidthScale);\n        int startDyC = int(floor(startCLerp - float(winWidth / 2)));\n\n        // Loop over dy\n        for (int dyROffset = 0; dyROffset < winHeight; dyROffset++) {\n          int dyR = dyROffset + startDyR;\n\n          // Guard against the window exceeding the bounds of dy\n          if (dyR < 0 || dyR >= ${s}) {\n            continue;\n          }\n\n          for (int dyCOffset = 0; dyCOffset < winWidth; dyCOffset++) {\n            int dyC = dyCOffset + startDyC;\n\n            // Guard against the window exceeding the bounds of dy\n            if (dyC < 0 || dyC >= ${i}) {\n              continue;\n            }\n\n            float sourceFracRow =\n              float(${o[0]}) *\n                (float(dyR) / float(${l[0]}));\n\n            float sourceFracCol =\n                float(${o[1]}) *\n                  (float(dyC) / float(${l[1]}));\n\n            int sourceNearestRow = int(min(\n                float(int(${n}) - 1),\n                ${a} ? float(round(sourceFracRow)) :\n                                  float(floor(sourceFracRow))));\n\n            int sourceNearestCol = int(min(\n                float(int(${r}) - 1),\n                ${a} ? float(round(sourceFracCol)) :\n                                  float(floor(sourceFracCol))));\n\n            if (r == sourceNearestRow && c == sourceNearestCol) {\n              accumulator += getDy(b, dyR, dyC, d);\n            }\n          }\n        }\n        // End loop over dy\n\n        setOutput(accumulator);\n      }\n    `}};function tY(e){let{inputs:t,backend:a,attrs:n}=e,{images:r,dy:s}=t,{alignCorners:i}=n,o=new eY(s.shape,r.shape,i);return a.runWebGLProgram(o,[s],s.dtype)}var aY={kernelName:Z1,backendName:\"webgl\",kernelFunc:tY},nY=class{constructor(e,t){this.variableNames=[\"x\"];let a=e.length;if(a>4)throw new Error(`WebGL backend: Reverse of rank-${a} tensor is not yet supported`);if(this.outputShape=e,a===1){this.userCode=`\n        void main() {\n          int coord = getOutputCoords();\n          setOutput(getX(${e[0]} - coord - 1));\n        }\n      `;return}let n=i=>t.indexOf(i)!==-1&&e[i]!==1?`${e[i]} - coords[${i}] - 1`:`coords[${i}]`,r=e.map((i,o)=>n(o)).join(\",\"),s=gt(a);this.userCode=`\n      void main() {\n        ${s} coords = getOutputCoords();\n        setOutput(getX(${r}));\n      }\n    `}},rY=class{constructor(e,t){this.variableNames=[\"x\"],this.packedInputs=!0,this.packedOutput=!0;let a=e.length;if(a>4)throw new Error(`WebGL backend: Reverse of rank-${a} tensor is not yet supported`);this.outputShape=e;let n=va(\"rc\",a),r=`${n[a-1]} + 1 < ${this.outputShape[a-1]}`,s=`${n[a-2]} + 1 < ${this.outputShape[a-2]}`,i=gt(a);a===1?this.userCode=`\n        void main(){\n          int rc = getOutputCoords();\n          vec4 result = vec4(0.);\n          result.r = getChannel(getX(${e[0]} - rc - 1),\n            ${e[0]} - rc - 1);\n          if(${r}){\n              result.g = getChannel(getX(${e[0]} - (rc  + 1) - 1),\n                ${e[0]} - (rc  + 1) - 1);\n          }\n          setOutput(result);\n        }\n      `:this.userCode=`\n        void main() {\n          ${i} rc = getOutputCoords();\n          vec4 result = vec4(0.);\n          result.r = ${o(n.slice())};\n          if(${r}){\n            result.g = ${l(n.slice())};\n          }\n          if(${s}) {\n            result.b = ${u(n.slice())};\n            if(${r}) {\n              result.a = ${p(n.slice())};\n            }\n          }\n          setOutput(result);\n        }\n    `;function o(h){return c(h)}function l(h){return h[a-1]=\"(\"+h[a-1]+\" + 1)\",c(h)}function u(h){return h[a-2]=\"(\"+h[a-2]+\" + 1)\",c(h)}function p(h){return h[a-1]=\"(\"+h[a-1]+\" + 1)\",h[a-2]=\"(\"+h[a-2]+\" + 1)\",c(h)}function c(h){let f=e.map((x,A)=>d(A,h)),m=f.join(\",\"),g=f.slice(-2).join(\",\");return`getChannel(getX(${m}), vec2(${g}))`}function d(h,f){return t.indexOf(h)!==-1&&e[h]!==1?`${e[h]} - ${f[h]} - 1`:`${f[h]}`}}};function sY(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{dims:s}=n,i=r.shape.length,o=v.parseAxisParam(s,r.shape);if(i===0)return Za({inputs:{x:r},backend:a});let l=W().getBool(\"WEBGL_PACK_ARRAY_OPERATIONS\")?new rY(r.shape,o):new nY(r.shape,o);return a.runWebGLProgram(l,[r],r.dtype)}var iY={kernelName:Ji,backendName:\"webgl\",kernelFunc:sY},oY=class{constructor(e,t){this.variableNames=[\"Image\"],this.outputShape=[],this.customUniforms=[{name:\"params\",type:\"vec4\"}];let a=e[1],n=e[2];this.outputShape=e;let r=\"\";typeof t==\"number\"?r=`float outputValue = ${t.toFixed(2)};`:r=`\n        vec3 fill = vec3(${t.join(\",\")});\n        float outputValue = fill[coords[3]];`,this.userCode=`\n        void main() {\n          ivec4 coords = getOutputCoords();\n          int x = coords[2];\n          int y = coords[1];\n          float coordXFloat = (float(x) - params[0]) * params[3] -\n            (float(y) - params[1]) * params[2];\n          float coordYFloat = (float(x) - params[0]) * params[2] +\n            (float(y) - params[1]) * params[3];\n          int coordX = int(round(coordXFloat + params[0]));\n          int coordY = int(round(coordYFloat + params[1]));\n          ${r}\n          if(coordX >= 0 && coordX < ${n} && coordY >= 0 && coordY < ${a}) {\n            outputValue = getImage(coords[0], coordY, coordX, coords[3]);\n          }\n          setOutput(outputValue);\n        }\n    `}},lY={kernelName:mo,backendName:\"webgl\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{image:n}=e,{radians:r,fillValue:s,center:i}=t,o=a,l=new oY(n.shape,s),[u,p]=T.getImageCenter(i,n.shape[1],n.shape[2]),c=[[u,p,Math.sin(r),Math.cos(r)]];return o.runWebGLProgram(l,[n],n.dtype,c)}},uY=`\n  // OpenGL ES does not support round function.\n  // The algorithm is based on banker's rounding.\n  float base = floor(x);\n  if ((x - base) < 0.5) {\n    return floor(x);\n  } else if ((x - base) > 0.5) {\n    return ceil(x);\n  } else {\n    if (mod(base, 2.0) == 0.0) {\n      return base;\n    } else {\n      return base + 1.0;\n    }\n  }\n`,dY=Qe({opSnippet:uY}),pY={kernelName:Xl,backendName:\"webgl\",kernelFunc:dY},cY=\"return inversesqrt(x);\",hY=Qe({opSnippet:cY,cpuKernelImpl:MU}),fY={kernelName:Qi,backendName:\"webgl\",kernelFunc:hY},yv=class{constructor(e,t,a,n,r,s,i=!0){this.variableNames=[\"updates\",\"indices\",\"defaultValue\"],this.outputShape=s;let o=gt(r.length),l=gt(s.length),u=\"\";a===1?u=\"i\":a===2&&(u=\"i, j\");let p=`getIndices(${u})`,c=\"\";n===1?c=\"i\":n===2&&(c=\"i, coords[1]\");let d=`getUpdates(${c})`,h=t>1?\"strides[j]\":\"strides\";this.userCode=`\n        ${o} strides = ${o}(${r});\n\n        void main() {\n          ${l} coords = getOutputCoords();\n          float sum = 0.0;\n          bool found = false;\n          for (int i = 0; i < ${e}; i++) {\n            int flattenedIndex = 0;\n            for (int j = 0; j < ${t}; j++) {\n              int index = round(${p});\n              flattenedIndex += index * ${h};\n            }\n            if (flattenedIndex == coords[0]) {\n              sum += ${d};\n              found = true;\n            }\n          }\n          setOutput(mix(getDefaultValue(), sum, float(found)));\n        }\n      `}};function mY(e){let{inputs:t,backend:a,attrs:n}=e,{indices:r,updates:s}=t,{shape:i}=n,{sliceRank:o,numUpdates:l,sliceSize:u,strides:p,outputSize:c}=T.calculateShapes(s,r,i),d=[c/u,u];if(c===0)return a.makeTensorInfo(i,r.dtype);let h=ce({inputs:{x:r},backend:a,attrs:{shape:[l,o]}}),f=ce({inputs:{x:s},backend:a,attrs:{shape:[l,u]}}),m=a.makeTensorInfo([],\"float32\",new Float32Array([0])),g=new yv(l,o,h.shape.length,f.shape.length,p,d),x=a.runWebGLProgram(g,[f,h,m],f.dtype),A=ce({inputs:{x},backend:a,attrs:{shape:i}});return a.disposeIntermediateTensorInfo(h),a.disposeIntermediateTensorInfo(f),a.disposeIntermediateTensorInfo(x),a.disposeIntermediateTensorInfo(m),A}var gY={kernelName:eo,backendName:\"webgl\",kernelFunc:mY},xY=class{constructor(e,t,a,n){this.variableNames=[\"sortedSequence\",\"values\"],this.customUniforms=[{name:\"numInputs\",type:\"int\"}],this.outputShape=[e,a];let r=\"while (left < right) {\",s=`for (int i = 0; i < ${Math.ceil(Math.log2(t+1))}; ++i) { if (left >= right) break;`,i=W().getNumber(\"WEBGL_VERSION\")===2?r:s,o=n===\"left\"?\"<\":\"<=\";this.userCode=`\n       int findBound(int batch, float value) {\n         int left = 0;\n         int right = numInputs;\n         int mid;\n         ${i}\n           mid = (left + right) / 2;\n           if (getSortedSequence(batch, mid) ${o} value) {\n             left = mid + 1;\n           } else {\n             right = mid;\n           }\n         }\n         return right;\n       }\n\n       void main() {\n         ivec2 coords = getOutputCoords();\n         int batch = coords[0];\n         int valueIndex = coords[1];\n\n         float value = getValues(batch, valueIndex);\n\n         setOutput(float(findBound(batch, value)));\n       }\n     `}};function AY(e){let{inputs:t,backend:a,attrs:n}=e,{sortedSequence:r,values:s}=t,{side:i}=n,o=new xY(r.shape[0],r.shape[1],s.shape[1],i),l=[[r.shape[1]]];return a.runWebGLProgram(o,[r,s],\"int32\",l)}var yY={kernelName:$d,backendName:\"webgl\",kernelFunc:AY},bY=class{constructor(e,t,a){this.variableNames=[\"c\",\"a\",\"b\"],this.outputShape=t;let n,r;if(a>4)throw Error(`Where for rank ${a} is not yet supported`);if(a===1)r=\"resRC\",n=\"resRC\";else{let i=[\"resRC.x\",\"resRC.y\",\"resRC.z\",\"resRC.w\"],o=[],l=[];for(let u=0;u<t.length;u++)l.push(`${i[u]}`),u<e&&o.push(`${i[u]}`);n=o.join(),r=l.join()}let s=gt(a);this.userCode=`\n      void main() {\n        ${s} resRC = getOutputCoords();\n        float cVal = getC(${n});\n        if (cVal >= 1.0) {\n          setOutput(getA(${r}));\n        } else {\n          setOutput(getB(${r}));\n        }\n      }\n    `}};function vY(e){let{inputs:t,backend:a}=e,{condition:n,t:r,e:s}=t,i=new bY(n.shape.length,r.shape,r.shape.length);return a.runWebGLProgram(i,[n,r,s],ca(r.dtype,s.dtype))}var wY={kernelName:Kl,backendName:\"webgl\",kernelFunc:vY},kY=`\n  // Stable and Attracting Fixed Point (0, 1) for Normalized Weights.\n  // see: https://arxiv.org/abs/1706.02515\n  float scaleAlpha = ${T.SELU_SCALEALPHA};\n  float scale = ${T.SELU_SCALE};\n  return (x >= 0.0) ? scale * x : scaleAlpha * (exp(x) - 1.0);\n`,IY=Qe({opSnippet:kY}),SY={kernelName:_d,backendName:\"webgl\",kernelFunc:IY},TY=mu+`\n  return 1.0 / (1.0 + exp(-1.0 * x));\n`,CY=`\n  vec4 result = 1.0 / (1.0 + exp(-1.0 * x));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n`,NY=Qe({opSnippet:TY,packedOpSnippet:CY,cpuKernelImpl:_U}),EY={kernelName:ao,backendName:\"webgl\",kernelFunc:NY},RY=`\n  if (isnan(x)) { return 0.0; }\n  return sign(x);\n`,MY=Qe({opSnippet:RY}),$Y={kernelName:Pd,backendName:\"webgl\",kernelFunc:MY},_Y=mu+`\n  return sin(x);\n`,PY=Qe({opSnippet:_Y}),FY={kernelName:to,backendName:\"webgl\",kernelFunc:PY},OY=`\n  float e2x = exp(x);\n  return (e2x - 1.0 / e2x) / 2.0;\n`,DY=Qe({opSnippet:OY}),zY={kernelName:Yl,backendName:\"webgl\",kernelFunc:DY},LY=`\n  float epsilon = 1.1920928955078125e-7;\n  float threshold = log(epsilon) + 2.0;\n\n  bool too_large = x > -threshold;\n  bool too_small = x < threshold;\n\n  float result;\n  float exp_x = exp(x);\n\n  if (too_large){\n    result = x;\n  }\n  else if (too_small){\n    result = exp_x;\n  }\n  else{\n    result = log(exp_x + 1.0);\n  }\n  return result;\n`,BY=Qe({opSnippet:LY}),WY={kernelName:Fd,backendName:\"webgl\",kernelFunc:BY},VY=e=>{let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockShape:s,paddings:i}=n;v.assert(r.shape.length<=4,()=>\"spaceToBatchND for rank > 4 with a WebGL backend not implemented yet\");let o=s.reduce((x,A)=>x*A),l=[[0,0]];l.push(...i);for(let x=1+s.length;x<r.shape.length;++x)l.push([0,0]);let u=[],p=xv({inputs:{x:r},backend:a,attrs:{paddings:l,constantValue:0}}),c=T.getReshaped(p.shape,s,o,!1),d=T.getPermuted(c.length,s.length,!1),h=T.getReshapedPermuted(p.shape,s,o,!1),f=ce({inputs:{x:p},backend:a,attrs:{shape:c}}),m=Ia({inputs:{x:f},backend:a,attrs:{perm:d}}),g=ce({inputs:{x:m},backend:a,attrs:{shape:h}});return u.push(p),u.push(f),u.push(m),u.forEach(x=>a.disposeIntermediateTensorInfo(x)),g},UY={kernelName:Jl,backendName:\"webgl\",kernelFunc:VY};function GY(e){let{inputs:t,backend:a}=e,{indices:n,values:r,denseShape:s,defaultValue:i}=t;if(s.shape.length!==1)throw new Error(`Dense shape must be a vector, saw:\n         ${s.shape}`);if(n.shape.length!==2)throw new Error(`Indices must be a matrix, saw:\n         ${n.shape}`);if(r.shape.length!==1)throw new Error(`Values must be a vector, saw:\n         ${r.shape}`);if(i.shape.length!==0)throw new Error(`Default value must be a scalar, saw:\n        ${i.shape}`);let o=a.readSync(n.dataId),l=a.readSync(r.dataId),u=a.readSync(s.dataId),p=a.readSync(i.dataId)[0],[c,d,h,f,m]=FU(o,n.shape,n.dtype,l,r.dtype,u,p);return[a.makeTensorInfo(d,n.dtype,c),a.makeTensorInfo([d[0]],r.dtype,h),a.makeTensorInfo([f.length],\"bool\",new Uint8Array(f.map(g=>Number(g)))),a.makeTensorInfo([m.length],n.dtype,new Int32Array(m))]}var HY={kernelName:Od,backendName:\"webgl\",kernelFunc:GY};function jY(e){let{inputs:t,backend:a}=e,{inputIndices:n,inputShape:r,newShape:s}=t;if(n.shape.length!==2)throw new Error(`Input indices should be a matrix but received shape ${n.shape}`);if(r.shape.length!==1)throw new Error(`Input shape should be a vector but received shape ${r.shape}`);if(s.shape.length!==1)throw new Error(`Target shape should be a vector but received shape ${s.shape}`);let i=Array.from(a.readSync(r.dataId)),o=a.readSync(n.dataId),l=Array.from(a.readSync(s.dataId)),[u,p,c]=OU(o,n.shape,n.dtype,i,l);return[a.makeTensorInfo(p,n.dtype,u),a.makeTensorInfo([c.length],s.dtype,new Int32Array(c))]}var qY={kernelName:eu,backendName:\"webgl\",kernelFunc:jY};function XY(e){let{inputs:t,backend:a}=e,{data:n,indices:r,segmentIds:s}=t;if(n.shape.length<1)throw new Error(\"Data should be at least 1 dimensional but received scalar\");if(r.shape.length!==1)throw new Error(`Indices should be a vector but received shape\n              ${r.shape}`);if(s.shape.length!==1)throw new Error(`Segment ids should be a vector but received shape\n              ${s.shape}`);let i=a.readSync(n.dataId),o=a.readSync(r.dataId),l=a.readSync(s.dataId),[u,p]=W6(i,n.shape,n.dtype,o,l,!0);return a.makeTensorInfo(p,n.dtype,u)}var KY={kernelName:Dd,backendName:\"webgl\",kernelFunc:XY};function ZY(e){let{inputs:t,backend:a}=e,{data:n,indices:r,segmentIds:s}=t;if(n.shape.length<1)throw new Error(\"Data should be at least 1 dimensional but received scalar\");if(r.shape.length!==1)throw new Error(`Indices should be a vector but received shape\n             ${r.shape}`);if(s.shape.length!==1)throw new Error(`Segment ids should be a vector but received shape\n             ${s.shape}`);let i=a.readSync(n.dataId),o=a.readSync(r.dataId),l=a.readSync(s.dataId),[u,p]=W6(i,n.shape,n.dtype,o,l);return a.makeTensorInfo(p,n.dtype,u)}var YY={kernelName:zd,backendName:\"webgl\",kernelFunc:ZY};function JY(e){let{inputs:t,backend:a,attrs:n}=e,{sparseIndices:r,sparseValues:s,defaultValue:i}=t,{outputShape:o}=n,{sliceRank:l,numUpdates:u,sliceSize:p,strides:c,outputSize:d}=T.calculateShapes(s,r,o),h=!1;if(s.dtype===\"string\"){let x=a.bufferSync(r),A=a.bufferSync(s),y=v.decodeString(a.readSync(i.dataId)[0]),b=$U(x,A,o,d,p,u,l,c,y,h);return a.makeTensorInfo(o,b.dtype,b.values)}let f=new yv(u,l,r.shape.length,s.shape.length,c,[d,1],h),m=a.runWebGLProgram(f,[s,r,i],s.dtype),g=ce({inputs:{x:m},backend:a,attrs:{shape:o}});return a.disposeIntermediateTensorInfo(m),g}var QY={kernelName:Ld,backendName:\"webgl\",kernelFunc:JY};function eJ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{numOrSizeSplits:s,axis:i}=n,o=v.parseAxisParam(i,r.shape)[0],l=T.prepareSplitSize(r,s,o),u=r.shape.length,p=new Array(u).fill(0),c=r.shape.slice();return l.map(d=>{let h=[...c];h[o]=d;let f=gu({inputs:{x:r},backend:a,attrs:{begin:p,size:h}});return p[o]+=d,f})}var tJ={kernelName:Ql,backendName:\"webgl\",kernelFunc:eJ},_x=\"return sqrt(x);\",aJ=Qe({opSnippet:_x,packedOpSnippet:_x,cpuKernelImpl:DU}),nJ={kernelName:no,backendName:\"webgl\",kernelFunc:aJ},rJ=\"return x * x;\",sJ=Qe({opSnippet:rJ}),iJ={kernelName:Bd,backendName:\"webgl\",kernelFunc:sJ},Px=\"return (a - b) * (a - b);\",oJ=oa({opSnippet:Px,packedOpSnippet:Px}),lJ={kernelName:io,backendName:\"webgl\",kernelFunc:oJ};function uJ({inputs:e,attrs:t,backend:a}){let{x:n}=e,r=Cn+`\n    return x > 0.0 ? 1.0 : float(${t.alpha});\n  `,s=new qn(n.shape,r);return a.runWebGLProgram(s,[n],n.dtype)}var dJ={kernelName:fo,backendName:\"webgl\",kernelFunc:uJ},pJ=class{constructor(e,t,a){this.variableNames=[\"x\"],this.outputShape=a;let n=a.length,r=gt(a.length),s=gt(a.length),i=\"\";if(n===1)i=\"coords * strides + begin\";else{let o=0;i=a.map((l,u)=>(o++,a.length===1?`coords * strides[${u}] + begin[${u}]`:`coords[${o-1}] * strides[${u}] + begin[${u}]`)).join(\",\")}this.userCode=`\n      ${r} begin = ${r}(${e});\n      ${r} strides = ${r}(${t});\n\n      void main() {\n        ${s} coords = getOutputCoords();\n        setOutput(getX(${i}));\n      }\n    `}};function cJ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{begin:s,end:i,strides:o,beginMask:l,endMask:u,ellipsisMask:p,newAxisMask:c,shrinkAxisMask:d}=n,{finalShapeSparse:h,finalShape:f,isIdentity:m,sliceDim0:g,isSimpleSlice:x,begin:A,end:y,strides:b}=It.sliceInfo(r.shape,s,i,o,l,u,p,c,d),w;if(m)w=ce({inputs:{x:r},backend:a,attrs:{shape:f}});else if(g||x){v.assert(r.shape.length>=1,()=>`Input must have rank at least 1, got: ${r.shape.length}`);let C=It.computeOutShape(A,y,b),E=gu({inputs:{x:r},backend:a,attrs:{begin:A,size:C}});w=ce({inputs:{x:E},backend:a,attrs:{shape:f}}),a.disposeIntermediateTensorInfo(E)}else if(a.shouldExecuteOnCPU([r])){let C=a.readSync(r.dataId),E=Me(r.shape,r.dtype,C),_=zU(h,E,b,A);w=a.makeTensorInfo(f,r.dtype,_.values)}else{let C=new pJ(A,b,h);w=a.runWebGLProgram(C,[r],r.dtype)}let S=ce({inputs:{x:w},backend:a,attrs:{shape:f}});return a.disposeIntermediateTensorInfo(w),S}var hJ={kernelName:oo,backendName:\"webgl\",kernelFunc:cJ};function fJ(e){let{inputs:t,backend:a,attrs:n}=e,{separator:r,nGramWidths:s,leftPad:i,rightPad:o,padWidth:l,preserveShortSequences:u}=n,{data:p,dataSplits:c}=t,d=a.readSync(p.dataId),h=a.readSync(c.dataId),[f,m]=LU(d,h,r,s,i,o,l,u);return[a.makeTensorInfo([f.length],\"string\",f),a.makeTensorInfo(c.shape,\"int32\",m)]}var mJ={kernelName:tu,backendName:\"webgl\",kernelFunc:fJ};function gJ(e){let{inputs:t,backend:a,attrs:n}=e,{skipEmpty:r}=n,{input:s,delimiter:i}=t;if(s.dtype!==\"string\")throw new Error(\"Input must be of datatype string\");if(s.shape.length!==1)throw new Error(`Input must be a vector, got shape: ${s.shape}`);if(i.shape.length!==0)throw new Error(`Delimiter must be a scalar, got shape: ${i.shape}`);let o=a.readSync(s.dataId),l=a.readSync(i.dataId)[0],[u,p,c]=BU(o,l,r),d=p.length;return[a.makeTensorInfo([d,2],\"int32\",u),a.makeTensorInfo([d],\"string\",p),a.makeTensorInfo([2],\"int32\",new Int32Array(c))]}var xJ={kernelName:Wd,backendName:\"webgl\",kernelFunc:gJ};function AJ(e){let{inputs:t,backend:a,attrs:n}=e,{numBuckets:r}=n,{input:s}=t;if(s.dtype!==\"string\")throw new Error(\"Input must be of datatype string\");if(r<=0)throw new Error(\"Number of buckets must be at least 1\");let i=a.readSync(s.dataId),o=WU(i,r);return a.makeTensorInfo(s.shape,\"int32\",o)}var yJ={kernelName:Vd,backendName:\"webgl\",kernelFunc:AJ},bJ=\"return tan(x);\",vJ=Qe({opSnippet:bJ}),wJ={kernelName:uo,backendName:\"webgl\",kernelFunc:vJ},kJ=`\n  float e2x = exp(-2.0 * abs(x));\n  return sign(x) * (1.0 - e2x) / (1.0 + e2x);\n`,IJ=Qe({opSnippet:kJ}),SJ={kernelName:po,backendName:\"webgl\",kernelFunc:IJ},TJ=class{constructor(e,t){this.variableNames=[\"A\"];let a=new Array(e.length);for(let s=0;s<a.length;s++)a[s]=e[s]*t[s];this.outputShape=a,this.rank=a.length;let n=gt(this.rank),r=CJ(e);this.userCode=`\n      void main() {\n        ${n} resRC = getOutputCoords();\n        setOutput(getA(${r}));\n      }\n    `}};function CJ(e){let t=e.length;if(t>5)throw Error(`Tile for rank ${t} is not yet supported`);if(t===1)return`imod(resRC, ${e[0]})`;let a=[\"resRC.x\",\"resRC.y\",\"resRC.z\",\"resRC.w\",\"resRC.u\"],n=[];for(let r=0;r<e.length;r++)n.push(`imod(${a[r]}, ${e[r]})`);return n.join()}function bv(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{reps:s}=n;if(r.dtype===\"string\"||r.shape.length>5){let o=a.readSync(r.dataId),l=r.dtype===\"string\"?o.map(c=>v.decodeString(c)):o,u=Me(r.shape,r.dtype,l),p=UU(u,s);return a.makeTensorInfo(p.shape,p.dtype,p.values)}let i=new TJ(r.shape,s);return a.runWebGLProgram(i,[r],r.dtype)}var NJ={kernelName:ns,backendName:\"webgl\",kernelFunc:bv},EJ=class{constructor(e){this.variableNames=[\"x\",\"indices\"],this.customUniforms=[{name:\"n\",type:\"int\"},{name:\"firstPass\",type:\"int\"},{name:\"negativeInf\",type:\"float\"},{name:\"dir\",type:\"int\"},{name:\"inc\",type:\"int\"}],this.outputShape=e,this.userCode=`\n       void main() {\n         ivec2 coords = getOutputCoords();\n         int batch = coords[0];\n         int elemIdx = coords[1];\n\n         // We compare elements pair-wise within a group of size 2 * inc.\n         // The comparing rule for each group alternates between ascending\n         // and descending. Within each group, we compare each pair at\n         // positions i and i+inc. To decide whether an element at position i\n         // is x0 or x1, we mod it by 2 * inc, if the result is smaller than\n         // inc, it is in the first half of the group, we denote it as x0,\n         // otherwise we denote it as x1.\n         // For example, as shown in the Bitonic top K paper referenced above,\n         // Figure5(a) shows that element[1] is in the\n         // second half of the group when group size is 2, but it is in the\n         // first half of the group when group size is 4.\n\n         bool isFirstInPair = imod(elemIdx, 2 * inc) < inc;\n         int i = isFirstInPair ? elemIdx : elemIdx - inc;\n\n         int i0 = firstPass == 1 ? i : int(getIndices(batch, i));\n         int i1 = firstPass == 1 ? i + inc : int(getIndices(batch, i + inc));\n         float x0 = i0 < n ? getX(batch, i0) : negativeInf;\n         float x1 = i1 < n ? getX(batch, i1) : negativeInf;\n\n         // Denotes which direction indices are in (ascending or descending).\n         bool reverse = imod(elemIdx, 2 * dir) >= dir;\n         bool isGreater = x0 > x1 || (x0 == x1 && i1 > i0);\n         if (reverse == isGreater) { // Elements in opposite order of direction\n           int iTemp = i0;\n           i0 = i1;\n           i1 = iTemp;\n         }\n         if (isFirstInPair) {\n            setOutput(float(i0));\n         } else {\n            setOutput(float(i1));\n         }\n       }\n     `}},RJ=class{constructor(e){this.variableNames=[\"x\",\"indices\"],this.customUniforms=[{name:\"n\",type:\"int\"},{name:\"firstPass\",type:\"int\"},{name:\"k\",type:\"int\"}],this.outputShape=e,this.userCode=`\n    void main() {\n         // Takes max of indices (0, k), (1, k + 1), (2, k + 2) ...\n         ivec2 coords = getOutputCoords();\n         int batch = coords[0];\n         int elemIdx = coords[1];\n\n         // The output size is half of the previous size.\n         // If the previous sequence is | | | | _ _ _ _  | | | |  _ _ _ _ (k=4),\n         // we only need to output the indices at positions |, the indices at\n         // positions _ can be thrown away, see Figure5(b) After Phase 2\n         // (Merge phase) in the Bitonic Top K paper referenced above.\n         // For example, the paper shows we only need to output the orange bars.\n         // The output sequence should look like this | | | | | | | |.\n         // Because the sequence is halved, to map the output index back\n         // to the previous sequence to find the corresponding value,\n         // we need to double the index. When we double the index,\n         // we basically interpolate a position, so 2i looks like\n         // | _ | _ | _ | _ | _ | _ | _. We move the | to the first k position\n         // of each 2k positions by - elemIdx % k. E.g. for output at\n         // index 4,5,6,7, we want to get the corresponding element at\n         // original index 8,9,10,11, for output at index 8,9,10,11,\n         // we want to get the corresponding element at original index\n         // 16,17,18,19, so on and so forth.\n\n         int i = elemIdx < k ? elemIdx : (elemIdx * 2 - imod(elemIdx, k));\n         int i0 = firstPass == 1 ? i : int(getIndices(batch, i));\n         int i1 = firstPass == 1 ? i + k : int(getIndices(batch, i + k));\n\n         float x0 = getX(batch, i0);\n         float x1 = i1 < n ? getX(batch, i1) : x0;\n\n         setOutput(x0 >= x1 ? float(i0) : float(i1));\n       }\n     `}};function Es(e,t){t!==null&&e.disposeIntermediateTensorInfo(t)}function Fx(e){let t=1;for(;t<e;)t*=2;return t}function MJ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{k:s,sorted:i}=n,o=W().getNumber(\"TOPK_LAST_DIM_CPU_HANDOFF_SIZE_THRESHOLD\"),l=W().getNumber(\"TOPK_K_CPU_HANDOFF_THRESHOLD\"),u=r.shape,p=u[u.length-1];if(a.shouldExecuteOnCPU([r])||p<o||s>l){let _=a.readSync(r.dataId),[$,M]=GU(_,u,r.dtype,s,i);return[a.makeTensorInfo($.shape,$.dtype,$.values),a.makeTensorInfo(M.shape,M.dtype,M.values)]}if(s===0)return u[u.length-1]=0,[a.makeTensorInfo(u,r.dtype,[]),a.makeTensorInfo(u,\"int32\",[])];if(p===1)return[r,fp({attrs:{shape:u,dtype:\"int32\",value:0},backend:a})];let c=a.texData.get(r.dataId),d=c!==null&&c.isPacked,h=d?a.unpackTensor(r):r,f=v.sizeFromShape(u)/p,m=ce({inputs:{x:h},attrs:{shape:[f,p]},backend:a});d&&Es(a,h);let g=Fx(s),x=Fx(p),A=null,y=()=>A===null?[m,m]:[m,A],b=(_,$,M)=>{let I=y(),N=new EJ(M),O=[[p],[A===null?1:0],[Number.NEGATIVE_INFINITY],[_],[$]],L=A;A=a.runWebGLProgram(N,I,\"int32\",O),Es(a,L)};for(let _=1;_<g;_*=2){let $=_*2;for(let M=_;M>=1;M/=2)b($,M,[f,x])}for(let _=x;_>g;_/=2){let $=y(),M=new RJ([f,_/2]),I=[[p],[A===null?1:0],[g]],N=A;A=a.runWebGLProgram(M,$,\"int32\",I),Es(a,N);let O=g/2,L=O*2;for(let B=O;B>=1;B/=2)b(L,B,A.shape)}let w=A;A=gu({inputs:{x:A},backend:a,attrs:{begin:0,size:[f,s]}}),Es(a,w);let S=pv({inputs:{x:m,indices:A},backend:a,attrs:{axis:1,batchDims:1}});Es(a,m);let C=u.slice(0,-1);C.push(s),w=A,A=ce({inputs:{x:A},attrs:{shape:C},backend:a}),Es(a,w);let E=S;return S=ce({inputs:{x:S},attrs:{shape:C},backend:a}),Es(a,E),[S,A]}var $J={kernelName:co,backendName:\"webgl\",kernelFunc:MJ},_J=class{constructor(e,t,a,n,r,s){this.variableNames=[\"Image\",\"Transforms\"],this.outputShape=s;let i=a===\"nearest\"?1:2,o;switch(n){case\"constant\":o=1;break;case\"reflect\":o=2;break;case\"wrap\":o=3;break;case\"nearest\":o=4;break;default:o=1;break}this.userCode=`\n            float mapCoord(float outCoord, float len) {\n              float inCoord = outCoord;\n              if(${o} == 2) {\n                if (inCoord < 0.0) {\n                  if (len <= 1.0) {\n                    inCoord = 0.0;\n                  } else {\n                    float sz2 = 2.0 * len;\n                    if (inCoord < sz2) {\n                      inCoord = sz2 * float(int(float(-inCoord / sz2))) +\n                      inCoord;\n                    }\n                    inCoord = inCoord < -len ? inCoord + sz2 : -inCoord - 1.0;\n                  }\n                } else if (inCoord > len - 1.0) {\n                  if (len <= 1.0) {\n                    inCoord = 0.0;\n                  } else {\n                    float sz2 = 2.0 * len;\n                    inCoord -= sz2 * float(int(float(inCoord / sz2)));\n                    if (inCoord >= len) {\n                      inCoord = sz2 - inCoord - 1.0;\n                    }\n                  }\n                }\n                return clamp(inCoord, 0.0, len - 1.0);\n              } else if (${o} == 3) {\n                if (inCoord < 0.0) {\n                  if (len <= 1.0) {\n                    inCoord = 0.0;\n                  } else {\n                    float sz = len - 1.0;\n                    inCoord += len * (float(int(float(-inCoord / sz))) + 1.0);\n                  }\n                } else if (inCoord > len - 1.0) {\n                  if (len <= 1.0) {\n                    inCoord = 0.0;\n                  } else {\n                    float sz = len - 1.0;\n                    inCoord -= len * float(int(float(inCoord / sz)));\n                  }\n                }\n                return clamp(inCoord, 0.0, len - 1.0);\n              } else if (${o} == 4) {\n                return clamp(outCoord, 0.0, len - 1.0);\n              } else {\n                return outCoord;\n              }\n            }\n\n            float readWithFillValue(int batch, int coordY, int coordX,\n              int channel) {\n              float outputValue;\n              if (0 <= coordY && coordY < ${e} && 0 <= coordX && coordX < ${t}) {\n                  outputValue = getImage(batch, coordY, coordX, channel);\n              } else {\n                outputValue = float(${r});\n              }\n              return outputValue;\n            }\n\n            void main() {\n              ivec4 coords = getOutputCoords();\n              float outputValue;\n              int batch = coords[0];\n              int x = coords[2];\n              int y = coords[1];\n              int channel = coords[3];\n              float xf = float(x);\n              float yf = float(y);\n              float a1 = getTransforms(batch, 0);\n              float a2 = getTransforms(batch, 1);\n              float a3 = getTransforms(batch, 2);\n              float b1 = getTransforms(batch, 3);\n              float b2 = getTransforms(batch, 4);\n              float b3 = getTransforms(batch, 5);\n              float c1 = getTransforms(batch, 6);\n              float c2 = getTransforms(batch, 7);\n              float projection = c1 * xf + c2 * yf + 1.0;\n              if (projection == 0.0) {\n                outputValue = float(${r});\n              } else {\n                float inX = (a1 * xf + a2 * yf + a3) / projection;\n                float inY = (b1 * xf + b2 * yf + b3) / projection;\n                float mapX = mapCoord(inX, float(${t}));\n                float mapY = mapCoord(inY, float(${e}));\n\n                if (${i} == 1) {\n                  int coordY = int(round(mapY));\n                  int coordX = int(round(mapX));\n                  outputValue = readWithFillValue(batch, coordY, coordX,\n                    channel);\n                } else {\n                  float yFloor = floor(mapY);\n                  float xFloor = floor(mapX);\n                  float yCeil = yFloor + 1.0;\n                  float xCeil = xFloor + 1.0;\n                  float valueYFloor = (xCeil - mapX) *\n                  readWithFillValue(batch, int(yFloor), int(xFloor), channel) +\n                  (mapX - xFloor) *\n                  readWithFillValue(batch, int(yFloor), int(xCeil), channel);\n                  float valueYCeil = (xCeil - mapX) *\n                  readWithFillValue(batch, int(yCeil), int(xFloor), channel) +\n                  (mapX - xFloor) *\n                  readWithFillValue(batch, int(yCeil), int(xCeil), channel);\n                  outputValue = (yCeil - mapY) * valueYFloor +\n                  (mapY - yFloor) * valueYCeil;\n                }\n              }\n              setOutput(outputValue);\n            }\n        `}};function PJ(e){let{inputs:t,backend:a,attrs:n}=e,{image:r,transforms:s}=t,{interpolation:i,fillMode:o,fillValue:l,outputShape:u}=n,[p,c,d,h]=r.shape,[f,m]=u!=null?u:[c,d],g=[p,f,m,h],x=new _J(c,d,i,o,l,g);return a.runWebGLProgram(x,[r,s],\"float32\")}var FJ={kernelName:ho,backendName:\"webgl\",kernelFunc:PJ};function OJ(e){let{inputs:t,attrs:a,backend:n}=e,{axis:r}=a,{x:s}=t;uu(s,\"unique\"),console.warn(\"WARNING: \",\"UI might be locked temporarily as data is being downloaded\");let i=n.readSync(s.dataId),{outputValues:o,outputShape:l,indices:u}=HU(i,r,s.shape,s.dtype);return[n.makeTensorInfo(l,s.dtype,o),n.makeTensorInfo([u.length],\"int32\",u)]}var DJ={kernelName:uh,backendName:\"webgl\",kernelFunc:OJ};function zJ(e){let{inputs:t,backend:a,attrs:n}=e,{value:r}=t,{axis:s}=n;s<0&&(s+=r.shape.length);let i=r,o=i.shape.length,l=r.shape[s],u=new Array(o-1),p=0;for(let m=0;m<o;m++)m!==s&&(u[p++]=i.shape[m]);let c=[],d=new Array(o).fill(0),h=i.shape.slice();h[s]=1;let f=new Array(l);for(let m=0;m<f.length;m++){d[s]=m;let g=gu({inputs:{x:i},backend:a,attrs:{begin:d,size:h}}),x=ce({inputs:{x:g},backend:a,attrs:{shape:u}});f[m]=x,c.push(g)}return c.forEach(m=>a.disposeIntermediateTensorInfo(m)),f}var LJ={kernelName:au,backendName:\"webgl\",kernelFunc:zJ},BJ=class{constructor(e,t){this.variableNames=[\"x\",\"segmentIds\"];let a=e.windowSize,n=e.batchSize,r=e.inSize,s=e.numSegments,i=s*Math.ceil(r/a);this.outputShape=[n,i];let o=\"0.0\",l=\"sumValue\",u=Math.floor(a/4)*4,p=a%4,c=`\n        sumValue += dot(values, segFilter);\n    `,d=\"\";r%a>0&&(d=`\n        if (inIdx < 0 || inIdx >= ${r}) {\n          return initializationValue;\n        }\n      `);let h=\"\";r%a>0&&(h=`\n        if (inIdx < 0 || inIdx >= ${r}) {\n          return -1.0;\n        }\n      `),this.userCode=`\n      const float initializationValue = ${o};\n\n      float getValue(int batch, int inIdx) {\n        ${d}\n        return getX(batch, inIdx);\n      }\n\n      float getSegmentIdAtIndex(int inIdx) {\n        ${h}\n        return getSegmentIds(inIdx);\n      }\n\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int batch = coords[0];\n        int outIdx = coords[1];\n        int inOffset = int(floor(float(outIdx) / float(\n          ${s})) * float(${a}));\n        int currentSeg = int(mod(float(outIdx), float(${s})));\n\n        float sumValue = 0.0;\n\n        for (int i = 0; i < ${u}; i += 4) {\n          int inIdx = inOffset + i;\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2),\n            getValue(batch, inIdx + 3)\n          );\n\n          vec4 segFilter = vec4(\n            int(getSegmentIdAtIndex(inIdx)) == currentSeg ? 1 : 0,\n            int(getSegmentIdAtIndex(inIdx + 1)) == currentSeg ? 1 : 0,\n            int(getSegmentIdAtIndex(inIdx + 2)) == currentSeg ? 1 : 0,\n            int(getSegmentIdAtIndex(inIdx + 3)) == currentSeg ? 1 : 0\n          );\n\n          ${c}\n        }\n\n        int inIdx = inOffset + ${u};\n        if (${p===1}) {\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            initializationValue,\n            initializationValue,\n            initializationValue\n          );\n\n          int inIdxSeg = int(getSegmentIdAtIndex(inIdx));\n\n          vec4 segFilter = vec4(\n            int(getSegmentIdAtIndex(inIdx)) == currentSeg ? 1 : 0,\n            0,\n            0,\n            0\n          );\n\n          ${c}\n        } else if (${p===2}) {\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            initializationValue,\n            initializationValue\n          );\n\n          vec4 segFilter = vec4(\n            int(getSegmentIdAtIndex(inIdx)) == currentSeg ? 1 : 0,\n            int(getSegmentIdAtIndex(inIdx + 1)) == currentSeg ? 1 : 0,\n              0,\n              0\n          );\n\n          ${c}\n        } else if (${p===3}) {\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2),\n            initializationValue\n          );\n\n          vec4 segFilter = vec4(\n            int(getSegmentIdAtIndex(inIdx)) == currentSeg ? 1 : 0,\n            int(getSegmentIdAtIndex(inIdx + 1)) == currentSeg ? 1 : 0,\n            int(getSegmentIdAtIndex(inIdx + 2)) == currentSeg ? 1 : 0,\n            0\n          );\n\n          ${c}\n        }\n        setOutput(${l});\n      }\n    `}};function WJ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,segmentIds:s}=t,{numSegments:i}=n,o=r.shape.length,l=[],u=0,p=T.getAxesPermutation([u],o),c=r;p!=null&&(c=Ia({inputs:{x:r},backend:a,attrs:{perm:p}}),l.push(c),u=T.getInnerMostAxes(1,o)[0]);let d=T.segment_util.computeOutShape(c.shape,u,i),h=v.sizeFromShape([c.shape[u]]),f=ce({inputs:{x:c},backend:a,attrs:{shape:[-1,h]}});l.push(f);let m=Hd(r.dtype),g=(b,w,S,C,E)=>{let _=b.shape[0],$=b.shape[1],M=T.segment_util.segOpComputeOptimalWindowSize($,E),I={windowSize:M,inSize:$,batchSize:_,numSegments:E},N=new BJ(I,w),O=a.compileAndRun(N,[b,S],C);if(l.push(O),O.shape[1]===E)return O;let L=Av({backend:a,attrs:{start:0,stop:E,step:1,dtype:\"float32\"}}),B=bv({inputs:{x:L},backend:a,attrs:{reps:[$/M]}});return l.push(L),l.push(B),g(O,w,B,C,E)},x=g(f,\"unsortedSegmentSum\",s,m,i),A=ce({inputs:{x},backend:a,attrs:{shape:d}}),y=A;if(p!=null){l.push(A);let b=T.getUndoAxesPermutation(p);y=Ia({inputs:{x:y},backend:a,attrs:{perm:b}})}return l.forEach(b=>a.disposeIntermediateTensorInfo(b)),y}var VJ={kernelName:dh,backendName:\"webgl\",kernelFunc:WJ},UJ=[zG,BG,UG,jG,XG,YG,QG,tH,sH,oH,dH,hH,gH,bH,kH,SH,CH,MH,_H,FH,LH,jH,XH,ZH,aj,rj,lj,vG,pj,gj,bj,Tj,Nj,Rj,$j,Pj,Dj,Bj,Uj,Hj,qj,Kj,Jj,eq,rq,iq,uq,cq,fq,Aq,wq,Tq,Eq,$q,_q,Fq,Dq,Lq,Wq,Uq,qq,Zq,Qq,tX,rX,oX,pX,mX,bG,xX,fj,bX,kX,TX,kG,RX,PX,OX,BX,UX,qX,ZX,eK,rK,oK,uK,hK,mK,xK,vK,kK,SK,CK,EK,_K,DK,WK,KK,TG,QK,aZ,sZ,lZ,JH,pZ,hZ,mZ,AZ,wZ,SG,IZ,TZ,NZ,RZ,MZ,QH,HK,PZ,zZ,VZ,NG,jZ,KZ,QZ,aY,iY,lY,pY,fY,gY,yY,wY,SY,EY,$Y,FY,zY,GH,qK,WY,UY,HY,qY,KY,YY,QY,tJ,nJ,iJ,lJ,dJ,hJ,mJ,xJ,yJ,jK,FG,wJ,SJ,NJ,$J,FJ,OG,DJ,LJ,VJ,cZ];for(let e of UJ)mn(e);var Tt;(function(e){e[e.float32=0]=\"float32\",e[e.int32=1]=\"int32\",e[e.bool=2]=\"bool\",e[e.string=3]=\"string\",e[e.complex64=4]=\"complex64\"})(Tt||(Tt={}));var yd;(function(e){e[e.linear=0]=\"linear\",e[e.relu=1]=\"relu\",e[e.relu6=2]=\"relu6\",e[e.prelu=3]=\"prelu\",e[e.leakyrelu=4]=\"leakyrelu\",e[e.sigmoid=5]=\"sigmoid\",e[e.elu=6]=\"elu\"})(yd||(yd={}));var vv;function GJ(e){vv=e.wasm.cwrap(jr,null,[\"number\",\"array\",\"number\",\"number\",\"array\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function HJ(e){let{inputs:t,backend:a,attrs:n}=e,{a:r,b:s,bias:i,preluActivationWeights:o}=t;if(r.dtype!==\"float32\"||s.dtype!==\"float32\")throw new Error(\"_FusedMatMul for non non-float32 tensors not yet supported.\");let{transposeA:l,transposeB:u,activation:p,leakyreluAlpha:c}=n,d=a.dataIdMap.get(r.dataId).id,h=a.dataIdMap.get(s.dataId).id,f=0;if(i!=null){let E=a.dataIdMap.get(i.dataId);if(E.shape.length!==1)throw new Error(`_FusedMatMul only supports rank-1 bias but got rank ${E.shape.length}.`);f=E.id}let m=o==null?0:a.dataIdMap.get(o.dataId).id,g=yd[p];if(g==null)throw new Error(`${p} activation not yet supported for FusedConv2D in the wasm backend.`);let x=l?r.shape[2]:r.shape[1],A=u?s.shape[1]:s.shape[2],y=xo.assertAndGetBroadcastShape(r.shape.slice(0,-2),s.shape.slice(0,-2)),b=a.makeOutput([...y,x,A],r.dtype),w=a.dataIdMap.get(b.dataId).id,S=new Uint8Array(new Int32Array(r.shape).buffer),C=new Uint8Array(new Int32Array(s.shape).buffer);return vv(d,S,r.shape.length,h,C,s.shape.length,l,u,g,f,m,c||0,w),b}var jJ={kernelName:jr,backendName:\"wasm\",setupFunc:GJ,kernelFunc:HJ};function Bt(e,t){let a;function n(s){a=s.wasm.cwrap(e,null,[\"number\",\"number\",\"number\"])}function r(s){let{backend:i,inputs:{x:o}}=s,l=i.dataIdMap.get(o.dataId).id,u=i.makeOutput(o.shape,t||o.dtype),p=i.dataIdMap.get(u.dataId).id;return v.sizeFromShape(u.shape)===0||a(l,Tt[o.dtype],p),u}return{kernelName:e,backendName:\"wasm\",setupFunc:n,kernelFunc:r}}var qJ=Bt(wl);function la(e,t,a){let n;function r(i){n=i.wasm.cwrap(e,null,[\"number\",\"array\",\"number\",\"number\",\"array\",\"number\",\"number\",\"number\"])}function s(i){let{backend:o,inputs:l}=i,{a:u,b:p}=l,c=o.dataIdMap.get(u.dataId).id,d=o.dataIdMap.get(p.dataId).id,h=a!=null?a:u.dtype,f=T.assertAndGetBroadcastShape(u.shape,p.shape),m=o.makeOutput(f,h);if(v.sizeFromShape(f)===0)return m;let g=new Uint8Array(new Int32Array(u.shape).buffer),x=new Uint8Array(new Int32Array(p.shape).buffer),A=o.dataIdMap.get(m.dataId).id;return n(c,g,u.shape.length,d,x,p.shape.length,Tt[u.dtype],A),m}return{kernelName:e,backendName:\"wasm\",setupFunc:r,kernelFunc:s}}var XJ=!0,KJ=la(ts,XJ),wv;function ZJ(e){wv=e.wasm.cwrap(Ks,null,[\"array\",\"number\",\"number\",\"number\"])}function YJ(e){let{inputs:t,backend:a}=e,n=a.makeOutput(t[0].shape,t[0].dtype);if(v.sizeFromShape(n.shape)===0)return n;let r=t.map(o=>a.dataIdMap.get(o.dataId).id),s=new Uint8Array(new Int32Array(r).buffer),i=a.dataIdMap.get(n.dataId).id;return wv(s,r.length,Tt[n.dtype],i),n}var JJ={kernelName:Ks,backendName:\"wasm\",setupFunc:ZJ,kernelFunc:YJ};function Bh(e){let{inputs:{x:t},backend:a}=e;if(t.dtype===\"string\")return Be(a.readSync(t.dataId),t.shape,t.dtype);let n=a.makeOutput(t.shape,t.dtype),r=a.typedArrayFromHeap(t);return a.typedArrayFromHeap(n).set(r),n}var QJ={kernelName:ki,backendName:\"wasm\",kernelFunc:Bh},kv;function eQ(e){kv=e.wasm.cwrap(Ar,null,[\"number\",\"array\",\"number\",\"number\",\"number\",\"array\",\"number\"])}function Qr(e){let{inputs:t,backend:a,attrs:n}=e,[r,s]=aQ(t.x.shape,n.perm),i=!0;for(let f=0;f<s.length;f++)s[f]!==f&&(i=!1);let o=tQ(t.x.shape,n.perm),l={dataId:t.x.dataId,shape:r,dtype:t.x.dtype};if(i){let f=Bh({inputs:t,backend:a});return f.shape=o,f}let u=a.makeOutput(o,l.dtype),p=a.dataIdMap.get(l.dataId).id,c=a.dataIdMap.get(u.dataId).id,d=new Uint8Array(new Int32Array(s).buffer),h=new Uint8Array(new Int32Array(l.shape).buffer);return kv(p,h,l.shape.length,Tt[l.dtype],c,d,s.length),u}function tQ(e,t){let a=new Array(e.length);for(let n=0;n<a.length;n++)a[n]=e[t[n]];return a}function aQ(e,t){let a=[],n=[];for(let r=0;r<e.length;++r)e[r]!==1&&a.push(e[r]),e[t[r]]!==1&&n.push(t[r]);for(let r=0;r<n.length;++r){let s=-1;for(let i=0;i<n.length;++i)n[i]>=r&&(s===-1||n[s]>n[i])&&(s=i);n[s]=r}return[a,n]}var nQ={kernelName:Ar,backendName:\"wasm\",kernelFunc:Qr,setupFunc:eQ};function us(e,t,a){let n=e.shape,r=e.shape.length,s=v.parseAxisParam(t,n),i=s,o=T.getAxesPermutation(i,r),l=null,u=!1;if(o!=null){let p=new Array(r);for(let d=0;d<p.length;d++)p[d]=n[o[d]];i=T.getInnerMostAxes(i.length,r),l=Qr({inputs:{x:e},attrs:{perm:o},backend:a});let c=a.dataIdMap.get(e.dataId).id;a.dataIdMap.get(l.dataId).id!==c&&(u=!0)}return{transposed:l,originalAxes:s,axes:i,inputWasTransposed:u}}var Iv;function rQ(e){Iv=e.wasm.cwrap(Zs,null,[\"number, number, number\"])}function sQ(e){let{backend:t,inputs:a,attrs:n}=e,{axis:r,keepDims:s}=n,{x:i}=a,o=t.dataIdMap.get(i.dataId).id,l=i,{transposed:u,axes:p,originalAxes:c,inputWasTransposed:d}=us(i,r,t);if(d){let A=t.dataIdMap.get(u.dataId).id;l=u,o=A}let h=l.shape.length;T.assertAxesAreInnerMostDims(\"all\",p,h);let[f,m]=T.computeOutAndReduceShapes(l.shape,p),g=v.sizeFromShape(m),x=t.makeOutput(f,i.dtype);if(v.sizeFromShape(l.shape)!==0){let A=t.dataIdMap.get(x.dataId).id;Iv(o,g,A)}if(d&&t.disposeData(u.dataId),s){let A=T.expandShapeToKeepDim(x.shape,c);x.shape=A}return x}var iQ={kernelName:Zs,backendName:\"wasm\",setupFunc:rQ,kernelFunc:sQ},Sv;function oQ(e){Sv=e.wasm.cwrap(Ys,null,[\"number, number, number\"])}function lQ(e){let{backend:t,inputs:a,attrs:n}=e,{axis:r,keepDims:s}=n,{x:i}=a,o=t.dataIdMap.get(i.dataId).id,l=i,{transposed:u,axes:p,originalAxes:c,inputWasTransposed:d}=us(i,r,t);if(d){let A=t.dataIdMap.get(u.dataId).id;l=u,o=A}let h=l.shape.length;T.assertAxesAreInnerMostDims(\"any\",p,h);let[f,m]=T.computeOutAndReduceShapes(l.shape,p),g=v.sizeFromShape(m),x=t.makeOutput(f,i.dtype);if(v.sizeFromShape(l.shape)!==0){let A=t.dataIdMap.get(x.dataId).id;Sv(o,g,A)}if(d&&t.disposeData(u.dataId),s){let A=T.expandShapeToKeepDim(x.shape,c);x.shape=A}return x}var uQ={kernelName:Ys,backendName:\"wasm\",setupFunc:oQ,kernelFunc:lQ},Tv;function dQ(e){Tv=e.wasm.cwrap(Js,null,[\"number\",\"number\",\"number\",\"number\",\"number\"])}function pQ(e){let{backend:t,inputs:a,attrs:n}=e,{axis:r}=n,{x:s}=a,i=t.dataIdMap.get(s.dataId).id,o=i,l=s,{transposed:u,axes:p,inputWasTransposed:c}=us(s,r,t);if(c){let x=t.dataIdMap.get(u.dataId).id;x!==i&&(l=u,o=x)}let d=l.shape.slice(0,-1),h=t.makeOutput(d,\"int32\"),f=t.dataIdMap.get(h.dataId).id,m=v.sizeFromShape(h.shape),g=l.shape[p[0]];return Tv(o,Tt[l.dtype],m,g,f),c&&t.disposeData(u.dataId),h}var cQ={kernelName:Js,backendName:\"wasm\",kernelFunc:pQ,setupFunc:dQ},Cv;function hQ(e){Cv=e.wasm.cwrap(Qs,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function fQ(e){let{inputs:t,attrs:a,backend:n}=e,r=t.x,s=n.dataIdMap.get(r.dataId).id,{filterSize:i,strides:o,pad:l,dimRoundingMode:u}=a,p=T.computePool2DInfo(r.shape,i,o,1,l,u),c=p.filterHeight,d=p.filterWidth,h=p.padInfo.top,f=p.padInfo.right,m=p.padInfo.bottom,g=p.padInfo.left,x=p.strideHeight,A=p.strideWidth,y=p.inChannels;if(p.dataFormat!==\"channelsLast\")throw new Error(`wasm backend does not support dataFormat:'${p.dataFormat}'. Please use 'channelsLast'.`);if(p.dilationWidth!==1||p.dilationHeight!==1)throw new Error(`was backend only supports average pooling with dilation = [1, 1], got [${p.dilationHeight}, ${p.dilationWidth}].`);let b=n.makeOutput(p.outShape,\"float32\"),w=n.dataIdMap.get(b.dataId).id;return Cv(s,r.shape[0],r.shape[1],r.shape[2],c,d,h,f,m,g,x,A,y,w),b}var mQ={kernelName:Qs,backendName:\"wasm\",setupFunc:hQ,kernelFunc:fQ};function za(e){let{inputs:t,attrs:a}=e,{x:n}=t,{shape:r}=a,s=v.sizeFromShape(n.shape),i=v.inferFromImplicitShape(r,s);return v.assert(s===v.sizeFromShape(i),()=>`new shape: ${i}, old shape: ${n.shape}. New shape and old shape must have the same number of elements.`),e.backend.incRef(n.dataId),{dataId:n.dataId,shape:i,dtype:n.dtype}}var gQ={kernelName:ql,backendName:\"wasm\",kernelFunc:za},Nv;function xQ(e){Nv=e.wasm.cwrap(ei,null,[\"number\",\"array\",\"number\",\"number\",\"array\",\"number\",\"number\",\"number\",\"number\"])}function AQ(e){let{inputs:t,backend:a,attrs:n}=e,{a:r,b:s}=t,{transposeA:i,transposeB:o}=n;if(r.dtype!==\"float32\"||s.dtype!==\"float32\")throw new Error(\"BatchMatMul for non non-float32 tensors not yet supported.\");let l=r.shape.length,u=s.shape.length,p=i?r.shape[l-2]:r.shape[l-1],c=o?s.shape[u-1]:s.shape[u-2],d=i?r.shape[l-1]:r.shape[l-2],h=o?s.shape[u-2]:s.shape[u-1],f=r.shape.slice(0,-2),m=s.shape.slice(0,-2),g=v.sizeFromShape(f),x=v.sizeFromShape(m),A=xo.assertAndGetBroadcastShape(r.shape.slice(0,-2),s.shape.slice(0,-2)).concat([d,h]);v.assert(p===c,()=>`Error in matMul: inner shapes (${p}) and (${c}) of Tensors with shapes ${r.shape} and ${s.shape} and transposeA=${i} and transposeB=${o} must match.`);let y=i?[g,p,d]:[g,d,p],b=o?[x,h,c]:[x,c,h],w=za({inputs:{x:r},backend:a,attrs:{shape:y}}),S=za({inputs:{x:s},backend:a,attrs:{shape:b}}),C=a.dataIdMap.get(w.dataId).id,E=a.dataIdMap.get(S.dataId).id,_=i?w.shape[2]:w.shape[1],$=o?S.shape[1]:S.shape[2],M=Math.max(g,x),I=a.makeOutput([M,_,$],w.dtype),N=a.dataIdMap.get(I.dataId).id,O=new Uint8Array(new Int32Array(w.shape).buffer),L=new Uint8Array(new Int32Array(S.shape).buffer);return Nv(C,O,w.shape.length,E,L,S.shape.length,i,o,N),a.disposeData(w.dataId),a.disposeData(S.dataId),I.shape=A,I}var yQ={kernelName:ei,backendName:\"wasm\",setupFunc:xQ,kernelFunc:AQ};function qs(e){let{inputs:{x:t},attrs:{begin:a,size:n},backend:r}=e,[s,i]=It.parseSliceParams(t,a,n),o=It.isSliceContinous(t.shape,s,i),l=r.readSync(t.dataId),u=r.makeOutput(i,t.dtype),p=v.computeStrides(t.shape),c=r.dataIdMap.get(u.dataId);if(o){let f=It.computeFlatOffset(s,p);return t.dtype===\"string\"?c.stringBytes=l.slice(f,f+v.sizeFromShape(i)):r.typedArrayFromHeap(u).set(l.subarray(f,f+v.sizeFromShape(i))),u}if(t.dtype===\"string\"){let f=_c(l,s,i,t.shape,t.dtype);return c.stringBytes=f,u}let d=r.typedArrayFromHeap(u),h=t.shape.length;if(h===2)bQ(l,p[0],d,s,i);else if(h===3)vQ(l,p[0],p[1],d,s,i);else if(h===4)wQ(l,p[0],p[1],p[2],d,s,i);else{let f=_c(l,s,i,t.shape,t.dtype);d.set(f)}return u}function bQ(e,t,a,n,r){let s=0,i=n[0],o=n[1],l=i+r[0];for(let u=i;u<l;u++){let p=u*t+o;a.set(e.subarray(p,p+r[1]),s),s+=r[1]}}function vQ(e,t,a,n,r,s){let i=0,o=r[0],l=r[1],u=r[2],p=o+s[0],c=l+s[1];for(let d=o;d<p;d++)for(let h=l;h<c;h++){let f=d*t+h*a+u;n.set(e.subarray(f,f+s[2]),i),i+=s[2]}}function wQ(e,t,a,n,r,s,i){let o=0,l=s[0],u=s[1],p=s[2],c=l+i[0],d=u+i[1],h=p+i[2],f=s[3];for(let m=l;m<c;m++)for(let g=u;g<d;g++)for(let x=p;x<h;x++){let A=m*t+g*a+x*n+f;r.set(e.subarray(A,A+i[3]),o),o+=i[3]}}var kQ={kernelName:Zl,backendName:\"wasm\",kernelFunc:qs};function IQ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockShape:s,crops:i}=n,o=s.reduce((x,A)=>x*A),l=T.getReshaped(r.shape,s,o),u=T.getPermuted(l.length,s.length),p=T.getReshapedPermuted(r.shape,s,o),c=T.getSliceBeginCoords(i,s.length),d=T.getSliceSize(p,i,s.length),h=za({inputs:{x:r},backend:a,attrs:{shape:l}}),f=Qr({inputs:{x:h},backend:a,attrs:{perm:u}}),m=za({inputs:{x:f},backend:a,attrs:{shape:p}}),g=qs({inputs:{x:m},backend:a,attrs:{begin:c,size:d}});return a.disposeData(h.dataId),a.disposeData(f.dataId),a.disposeData(h.dataId),g}var SQ={kernelName:Rl,backendName:\"wasm\",kernelFunc:IQ};function xu(e){let{inputs:{x:t},attrs:{dtype:a},backend:n}=e,r=n.makeOutput(t.shape,a),s=n.typedArrayFromHeap(t);return n.typedArrayFromHeap(r).set(s),r}var TQ={kernelName:ti,backendName:\"wasm\",kernelFunc:xu},CQ=Bt(ai),Ev;function NQ(e){Ev=e.wasm.cwrap(as,null,[\"number\",\"number\",\"number\",\"number\"])}function EQ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{clipValueMin:s,clipValueMax:i}=n,o=a.dataIdMap.get(r.dataId).id,l=a.makeOutput(r.shape,r.dtype),u=a.dataIdMap.get(l.dataId).id;return Ev(o,s,i,u),l}var RQ={kernelName:as,backendName:\"wasm\",setupFunc:NQ,kernelFunc:EQ};function Rv(e){let{inputs:t,backend:a}=e,n=v.parseAxisParam(e.attrs.axis,t[0].shape)[0],r=t.map(h=>h.shape);T.assertParamsConsistent(r,n);let s=T.computeOutShape(t.map(h=>h.shape),n),i=t.filter(h=>v.sizeFromShape(h.shape)>0);if(i.length===1)return Bh({inputs:{x:i[0]},backend:a});let o=a.makeOutput(s,t[0].dtype);if(v.sizeFromShape(s)===0)return o;if(i[0].dtype===\"string\"){let h=i.map(y=>{let b=[-1,v.sizeFromShape(y.shape.slice(n))];return za({inputs:{x:y},backend:a,attrs:{shape:b}})}),f=h.map(y=>({vals:a.readSync(y.dataId),shape:y.shape}));s=T.computeOutShape(h.map(y=>y.shape),1);let m=h[0].shape[0]===1,g=o3(f,s,t[0].dtype,m),x=T.computeOutShape(i.map(y=>y.shape),n);o.shape=x;let A=a.dataIdMap.get(o.dataId);return A.stringBytes=T.fromStringArrayToUint8(g),h.forEach(y=>a.disposeData(y.dataId)),o}let l=v.sizeFromShape(i[0].shape.slice(0,n)),u=0,p=i.map(h=>{let f=v.sizeFromShape(h.shape.slice(n));return u+=f,f}),c=i.map(h=>a.typedArrayFromHeap(h)),d=a.typedArrayFromHeap(o);for(let h=0;h<l;h++){let f=h*u;for(let m=0;m<c.length;m++){let g=p[m],x=h*g,A=c[m].subarray(x,x+g);d.set(A,f),f+=g}}return o}var MQ={kernelName:Ml,backendName:\"wasm\",kernelFunc:Rv},Mv;function $Q(e){Mv=e.wasm.cwrap(ni,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function _Q(e){let{inputs:t,attrs:a,backend:n}=e,{x:r,filter:s}=t,i=n.dataIdMap.get(r.dataId).id,o=n.dataIdMap.get(s.dataId).id,{strides:l,dilations:u,pad:p,dimRoundingMode:c,dataFormat:d}=a,h=T.convertConv2DDataFormat(d),f=T.computeConv2DInfo(r.shape,s.shape,l,u,p,c,!1,h),m=f.filterHeight,g=f.filterWidth,x=f.padInfo.top,A=f.padInfo.right,y=f.padInfo.bottom,b=f.padInfo.left,w=f.dilationHeight,S=f.dilationWidth,C=f.strideHeight,E=f.strideWidth,_=f.inChannels,$=f.outChannels,M=f.padInfo.type===\"SAME\"?1:0;if(f.dataFormat!==\"channelsLast\")throw new Error(`wasm backend Conv2D does not support dataFormat:'${f.dataFormat}'. Please use 'channelsLast'.`);let I=n.makeOutput(f.outShape,\"float32\"),N=n.dataIdMap.get(I.dataId).id;return Mv(i,r.shape[0],r.shape[1],r.shape[2],o,m,g,x,A,y,b,M,w,S,C,E,_,$,N),I}var PQ={kernelName:ni,backendName:\"wasm\",setupFunc:$Q,kernelFunc:_Q},$v;function FQ(e){$v=e.wasm.cwrap(ri,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function OQ(e){let{backend:t,inputs:a,attrs:n}=e,{dy:r,filter:s}=a,{strides:i,pad:o,dataFormat:l,dimRoundingMode:u,inputShape:p}=n,c=1,d=T.convertConv2DDataFormat(l),h=T.computeConv2DInfo(p,s.shape,i,c,o,u,!1,d),{batchSize:f,filterHeight:m,filterWidth:g,inChannels:x,inHeight:A,inWidth:y,outChannels:b,outHeight:w,outWidth:S,strideHeight:C,strideWidth:E}=h,_=m-1-h.padInfo.top,$=g-1-h.padInfo.left,M=h.dataFormat===\"channelsLast\",I=v.computeStrides(h.inShape),N=v.computeStrides(r.shape),[O,L,B]=v.computeStrides(s.shape),G=I[0],j=M?I[1]:I[2],U=M?I[2]:1,H=M?1:I[1],V=N[0],Q=M?N[1]:N[2],Z=M?N[2]:1,re=M?1:N[1],ee=t.makeOutput(h.inShape,\"float32\"),he=t.dataIdMap.get(ee.dataId).id,oe=t.dataIdMap.get(r.dataId).id,Ae=t.dataIdMap.get(s.dataId).id;return $v(oe,Ae,f,m,g,A,y,x,w,S,b,C,E,_,$,O,L,B,G,j,U,H,V,Q,Z,re,he),ee}var DQ={kernelName:ri,backendName:\"wasm\",setupFunc:FQ,kernelFunc:OQ},zQ=Bt(si),LQ=Bt(ii),E1;(function(e){e[e.bilinear=0]=\"bilinear\",e[e.nearest=1]=\"nearest\"})(E1||(E1={}));var _v;function BQ(e){_v=e.wasm.cwrap(ui,null,[\"number\",\"number\",\"number\",\"number\",\"array\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function WQ(e){let{backend:t,inputs:a,attrs:n}=e,{method:r,extrapolationValue:s,cropSize:i}=n,{image:o,boxes:l,boxInd:u}=a,p=l.shape[0],[c,d]=i,h=[p,c,d,o.shape[3]],f=t.dataIdMap.get(o.dataId),m;o.dtype!==\"float32\"&&(m=xu({backend:t,inputs:{x:o},attrs:{dtype:\"float32\"}}),f=t.dataIdMap.get(m.dataId));let g=f.id,x=t.dataIdMap.get(l.dataId).id,A=t.dataIdMap.get(u.dataId).id,y=t.makeOutput(h,\"float32\"),b=t.dataIdMap.get(y.dataId).id,w=new Uint8Array(new Int32Array(o.shape).buffer);return _v(g,x,A,p,w,c,d,E1[r],s,b),m!=null&&t.disposeData(m.dataId),y}var VQ={kernelName:ui,backendName:\"wasm\",setupFunc:BQ,kernelFunc:WQ},Pv;function UQ(e){Pv=e.wasm.cwrap(oi,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function GQ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,exclusive:i,reverse:o}=n,l=r.shape.length;v.assert(r.dtype===\"float32\"||r.dtype===\"int32\",()=>`cumprod does not support ${r.dtype} tensors in the WASM backend`);let u=T.getAxesPermutation([s],l),p=r;u!==null&&(p=Qr({inputs:{x:r},attrs:{perm:u},backend:a}));let c=T.getInnerMostAxes(1,l)[0];T.assertAxesAreInnerMostDims(\"cumprod\",[c],l);let d=a.makeOutput(p.shape,p.dtype),h=p.shape[c],f=a.dataIdMap.get(p.dataId).id,m=a.dataIdMap.get(d.dataId).id;Pv(f,i?1:0,o?1:0,h,m,Tt[r.dtype]);let g=d;if(u!==null){let x=T.getUndoAxesPermutation(u);g=Qr({inputs:{x:d},attrs:{perm:x},backend:a}),a.disposeData(p.dataId),a.disposeData(d.dataId)}return g}var HQ={kernelName:oi,backendName:\"wasm\",setupFunc:UQ,kernelFunc:GQ},Fv;function jQ(e){Fv=e.wasm.cwrap(li,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function qQ(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,exclusive:i,reverse:o}=n,l=r.shape.length;v.assert(r.dtype===\"float32\"||r.dtype===\"int32\",()=>`cumsum does not support ${r.dtype} tensors in the WASM backend`);let u=T.getAxesPermutation([s],l),p=r;u!==null&&(p=Qr({inputs:{x:r},attrs:{perm:u},backend:a}));let c=T.getInnerMostAxes(1,l)[0];T.assertAxesAreInnerMostDims(\"cumsum\",[c],l);let d=a.makeOutput(p.shape,p.dtype),h=p.shape[c],f=a.dataIdMap.get(p.dataId).id,m=a.dataIdMap.get(d.dataId).id;Fv(f,i?1:0,o?1:0,h,m,Tt[r.dtype]);let g=d;if(u!==null){let x=T.getUndoAxesPermutation(u);g=Qr({inputs:{x:d},attrs:{perm:x},backend:a}),a.disposeData(p.dataId),a.disposeData(d.dataId)}return g}var XQ={kernelName:li,backendName:\"wasm\",setupFunc:jQ,kernelFunc:qQ},Ov;function KQ(e){Ov=e.wasm.cwrap(di,null,[\"number\",\"number\",\"number\",\"array\",\"number\",\"array\",\"array\",\"number\",\"number\"])}function ZQ(e){let{backend:t,inputs:a,attrs:n}=e,{x:r}=a,{blockSize:s,dataFormat:i}=n,o=r.shape[0],l=i===\"NHWC\"?r.shape[1]:r.shape[2],u=i===\"NHWC\"?r.shape[2]:r.shape[3],p=i===\"NHWC\"?r.shape[3]:r.shape[1],c=l*s,d=u*s,h=p/(s*s),f=i===\"NHWC\"?[o,c,d,h]:[o,h,c,d],m=t.makeOutput(f,\"float32\"),g=t.dataIdMap.get(r.dataId).id,x=new Uint8Array(new Int32Array(v.computeStrides(r.shape)).buffer),A=new Uint8Array(new Int32Array(f).buffer),y=new Uint8Array(new Int32Array(v.computeStrides(f)).buffer),b=t.dataIdMap.get(m.dataId).id;return Ov(g,s,i===\"NHWC\"?1:0,x,r.shape.length-1,A,y,f.length,b),m}var YQ={kernelName:di,backendName:\"wasm\",setupFunc:KQ,kernelFunc:ZQ},Dv;function JQ(e){Dv=e.wasm.cwrap(pi,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function QQ(e){let{inputs:t,attrs:a,backend:n}=e,{x:r,filter:s}=t,i=n.dataIdMap.get(r.dataId).id,o=n.dataIdMap.get(s.dataId).id,{strides:l,dilations:u,pad:p,dimRoundingMode:c}=a,d=u==null?[1,1]:u,h=T.computeConv2DInfo(r.shape,s.shape,l,d,p,c,!0),f=h.filterHeight,m=h.filterWidth,g=h.padInfo.top,x=h.padInfo.right,A=h.padInfo.bottom,y=h.padInfo.left,b=h.dilationHeight,w=h.dilationWidth,S=h.strideHeight,C=h.strideWidth,E=h.inChannels,_=h.outChannels,$=h.padInfo.type===\"SAME\"?1:0;if(h.dataFormat!==\"channelsLast\")throw new Error(`wasm backend DepthwiseConv2dNative does not support dataFormat:'${h.dataFormat}'. Please use 'channelsLast'.`);let M=n.makeOutput(h.outShape,\"float32\"),I=n.dataIdMap.get(M.dataId).id;return Dv(i,r.shape[0],r.shape[1],r.shape[2],o,f,m,g,x,A,y,$,b,w,S,C,E,_,I),M}var eee={kernelName:pi,backendName:\"wasm\",setupFunc:JQ,kernelFunc:QQ},tee=Bt(hi),aee=!1,nee=la(fi,aee,\"bool\"),ree=Bt(mi,\"float32\");function R1(e){let{inputs:t,attrs:a,backend:n}=e,{input:r}=t,{dim:s}=a,i=r.shape.length,o=r.shape.slice(),l=s;return s<0&&(v.assert(-(i+1)<=s,()=>`Axis must be in the interval [${-(i+1)}, ${i}]`),l=i+s+1),o.splice(l,0,1),za({inputs:{x:r},backend:n,attrs:{shape:o}})}var see={kernelName:_l,backendName:\"wasm\",kernelFunc:R1};function zv(e){let{attrs:{shape:t,value:a,dtype:n},backend:r}=e,s=r.makeOutput(t,n);return r.typedArrayFromHeap(s).fill(a),s}var iee={kernelName:Fl,backendName:\"wasm\",kernelFunc:zv},Lv;function oee(e){Lv=e.wasm.cwrap(gi,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function lee(e){let{inputs:t,backend:a}=e,{image:n}=t,r=a.makeOutput(n.shape,n.dtype),s=a.dataIdMap.get(n.dataId).id,i=a.dataIdMap.get(r.dataId).id,[o,l,u,p]=n.shape;return Lv(s,o,l,u,p,i),r}var uee={kernelName:gi,backendName:\"wasm\",kernelFunc:lee,setupFunc:oee},dee=Bt(xi),pee=!1,cee=la(Ai,pee),Bv;function hee(e){Bv=e.wasm.cwrap(yi,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function fee(e){let{backend:t,inputs:a,attrs:n}=e,{varianceEpsilon:r}=n,{x:s,mean:i,variance:o,offset:l,scale:u}=a,p=t.dataIdMap.get(s.dataId).id,c=t.dataIdMap.get(i.dataId).id,d=t.dataIdMap.get(o.dataId).id,h=l!=null?t.dataIdMap.get(l.dataId).id:0,f=u!=null?t.dataIdMap.get(u.dataId).id:0,m=t.makeOutput(s.shape,s.dtype);if(v.sizeFromShape(s.shape)===0)return m;let g=t.dataIdMap.get(m.dataId).id;return Bv(p,c,d,h,f,r,g),m}var mee={kernelName:yi,backendName:\"wasm\",setupFunc:hee,kernelFunc:fee},Wv;function gee(e){Wv=e.wasm.cwrap(qr,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function xee(e){let{inputs:t,attrs:a,backend:n}=e,{x:r,filter:s,bias:i,preluActivationWeights:o}=t,{strides:l,pad:u,dilations:p,dataFormat:c,dimRoundingMode:d,activation:h,leakyreluAlpha:f}=a,m=T.computeConv2DInfo(r.shape,s.shape,l,p,u,d),g=yd[h];if(g==null)throw new Error(`${h} activation not yet supported for FusedConv2D in the wasm backend.`);let x=n.dataIdMap.get(r.dataId).id,A=n.dataIdMap.get(s.dataId).id,y=m.outChannels,b=0;if(i!=null){let Z=n.dataIdMap.get(i.dataId);if(Z.shape.length!==1)throw new Error(`FusedConv2D only supports rank-1 bias but got rank ${Z.shape.length}.`);if(Z.shape[0]!==y)throw new Error(`FusedConv2D bias shape (${Z.shape}) does not match the number of output channels (${y})`);b=Z.id}let w=m.filterHeight,S=m.filterWidth,C=m.padInfo.top,E=m.padInfo.right,_=m.padInfo.bottom,$=m.padInfo.left,M=m.dilationHeight,I=m.dilationWidth,N=m.strideHeight,O=m.strideWidth,L=m.inChannels,B=m.padInfo.type===\"SAME\"?1:0,G=m.batchSize,j=m.inHeight,U=m.inWidth;if(c!==\"NHWC\")throw new Error(`wasm backend FusedConv2D does not support dataFormat:'${c}'. Please use 'NHWC'.`);let H=n.makeOutput(m.outShape,\"float32\"),V=n.dataIdMap.get(H.dataId).id,Q=o==null?0:n.dataIdMap.get(o.dataId).id;return Wv(x,G,j,U,A,w,S,b,C,E,_,$,B,M,I,N,O,L,y,g,Q,f||0,V),H}var Aee={kernelName:qr,backendName:\"wasm\",setupFunc:gee,kernelFunc:xee},Vv;function yee(e){Vv=e.wasm.cwrap(Xr,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function bee(e){let{inputs:t,attrs:a,backend:n}=e,{x:r,filter:s,bias:i,preluActivationWeights:o}=t,{strides:l,pad:u,dilations:p,dataFormat:c,dimRoundingMode:d,activation:h,leakyreluAlpha:f}=a,m=T.computeConv2DInfo(r.shape,s.shape,l,p,u,d,!0),g=yd[h];if(g==null)throw new Error(`${h} activation not yet supported for FusedDepthwiseConv2D in the wasm backend.`);let x=n.dataIdMap.get(r.dataId).id,A=n.dataIdMap.get(s.dataId).id,y=m.outChannels,b=0;if(i!=null){let Z=n.dataIdMap.get(i.dataId);if(Z.shape.length!==1)throw new Error(`FusedDepthwiseConv2D only supports rank-1 bias but got rank ${Z.shape.length}.`);if(Z.shape[0]!==y)throw new Error(`FusedDepthwiseConv2D bias shape (${Z.shape}) does not match the number of output channels (${y})`);b=Z.id}let w=m.filterHeight,S=m.filterWidth,C=m.padInfo.top,E=m.padInfo.right,_=m.padInfo.bottom,$=m.padInfo.left,M=m.dilationHeight,I=m.dilationWidth,N=m.strideHeight,O=m.strideWidth,L=m.inChannels,B=m.padInfo.type===\"SAME\"?1:0,G=m.batchSize,j=m.inHeight,U=m.inWidth;if(c!==\"NHWC\")throw new Error(`wasm backend FusedDepthwiseConv2D does not support dataFormat:'${c}'. Please use 'NHWC'.`);let H=n.makeOutput(m.outShape,\"float32\"),V=n.dataIdMap.get(H.dataId).id,Q=o==null?0:n.dataIdMap.get(o.dataId).id;return Vv(x,G,j,U,A,w,S,b,C,E,_,$,B,M,I,N,O,L,y,g,Q,f||0,V),H}var vee={kernelName:Xr,backendName:\"wasm\",setupFunc:yee,kernelFunc:bee},Uv;function wee(e){Uv=e.wasm.cwrap(bi,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"array\",\"number\"])}function kee(e){let{backend:t,inputs:a}=e,{params:n,indices:r}=a,[s,i,o,l]=c2.prepareAndValidate(n,r),u=t.makeOutput(s,n.dtype);if(i===0)return u;let p=r.shape,c=p[p.length-1],d=t.dataIdMap.get(n.dataId).id,h=t.dataIdMap.get(r.dataId).id,f=new Uint8Array(new Int32Array(l).buffer),m=t.dataIdMap.get(u.dataId).id;return Uv(d,Tt[n.dtype],h,i,c,o,f,m),u}var Iee={kernelName:bi,backendName:\"wasm\",setupFunc:wee,kernelFunc:kee},Gv;function See(e){Gv=e.wasm.cwrap(\"Gather\",null,[\"number\",\"number\",\"array\",\"number\",\"number\",\"number\",\"array\",\"number\"])}function Tee(e){let{backend:t,inputs:a,attrs:n}=e,{x:r,indices:s}=a,{axis:i,batchDims:o}=n,l=v.parseAxisParam(i,r.shape)[0],u=t.readSync(s.dataId),p=r.shape[l];for(let C=0;C<u.length;++C){let E=u[C];v.assert(E<=p-1&&E>=0,()=>`GatherV2: the index value ${E} is not in [0, ${p-1}]`)}let c=T.segment_util.collectGatherOpShapeInfo(r,s,l,o),d=za({inputs:{x:r},attrs:{shape:[c.batchSize,c.outerSize,c.dimSize,c.sliceSize]},backend:t}),h=v.sizeFromShape(s.shape),f=za({inputs:{x:s},attrs:{shape:[c.batchSize,h/c.batchSize]},backend:t}),m=[c.batchSize,c.outerSize,h/c.batchSize,c.sliceSize],g=t.makeOutput(m,r.dtype);if(v.sizeFromShape(r.shape)===0)return g;let x=d.shape.length-1,A=t.dataIdMap.get(d.dataId).id,y=t.dataIdMap.get(f.dataId).id,b=t.dataIdMap.get(g.dataId).id,w=new Uint8Array(new Int32Array(v.computeStrides(d.shape)).buffer),S=new Uint8Array(new Int32Array(v.computeStrides(m)).buffer);return Gv(A,Tt[r.dtype],w,x,y,c.batchSize,S,b),t.disposeData(d.dataId),t.disposeData(f.dataId),g.shape=c.outputShape,g}var Cee={kernelName:Ol,backendName:\"wasm\",setupFunc:See,kernelFunc:Tee},Nee=!1,Eee=la(vi,Nee,\"bool\"),Ree=!1,Mee=la(wi,Ree,\"bool\"),$ee=Bt(Ii,\"bool\"),Hv;function _ee(e){Hv=e.wasm.cwrap(Si,null,[\"number\",\"number\",\"number\",\"number\"])}function Pee(e){let{inputs:{x:t},attrs:{alpha:a},backend:n}=e,r=n.dataIdMap.get(t.dataId).id,s=n.makeOutput(t.shape,\"float32\");if(v.sizeFromShape(t.shape)!==0){let i=n.dataIdMap.get(s.dataId).id;Hv(r,Tt[t.dtype],a,i)}return s}var Fee={kernelName:Si,backendName:\"wasm\",setupFunc:_ee,kernelFunc:Pee},Oee=!1,Dee=la(Ti,Oee,\"bool\"),zee=!1,Lee=la(Ci,zee,\"bool\"),Bee=Bt(Ni),Wee=!1,Vee=la(Ei,Wee,\"bool\"),Uee=Bt(Ri),Gee=!1,Hee=la(Bl,Gee,\"bool\"),jee=!1,qee=la(xA,jee,\"bool\"),jv;function Xee(e){jv=e.wasm.cwrap(Mi,null,[\"number\",\"number\",\"number\",\"number\"])}function Kee(e){let{backend:t,inputs:a,attrs:n}=e,{reductionIndices:r,keepDims:s}=n,{x:i}=a,o=t.dataIdMap.get(i.dataId).id,l=i,{transposed:u,axes:p,originalAxes:c,inputWasTransposed:d}=us(i,r,t);if(d){let A=t.dataIdMap.get(u.dataId).id;l=u,o=A}let h=l.shape.length;T.assertAxesAreInnerMostDims(\"max\",p,h);let[f,m]=T.computeOutAndReduceShapes(l.shape,p),g=v.sizeFromShape(m),x=t.makeOutput(f,i.dtype);if(v.sizeFromShape(l.shape)!==0){let A=t.dataIdMap.get(x.dataId).id;jv(o,Tt[i.dtype],g,A)}if(d&&t.disposeData(u.dataId),s){let A=T.expandShapeToKeepDim(x.shape,c);x.shape=A}return x}var Zee={kernelName:Mi,backendName:\"wasm\",setupFunc:Xee,kernelFunc:Kee},Yee=!1,Jee=la($i,Yee),qv;function Qee(e){qv=e.wasm.cwrap(_i,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function ete(e){let{inputs:t,attrs:a,backend:n}=e,r=t.x,s=n.dataIdMap.get(r.dataId).id;v.assert(r.dtype===\"float32\",()=>`Error in MaxPool: only float32 input is supported. Got ${r.dtype}.`);let{filterSize:i,strides:o,pad:l,dimRoundingMode:u}=a,p=T.computePool2DInfo(r.shape,i,o,1,l,u),c=p.filterHeight,d=p.filterWidth,h=p.padInfo.top,f=p.padInfo.right,m=p.padInfo.bottom,g=p.padInfo.left,x=p.dilationHeight,A=p.dilationWidth,y=p.strideHeight,b=p.strideWidth,w=p.inChannels,S=p.outChannels;if(p.dataFormat!==\"channelsLast\")throw new Error(`wasm backend does not support dataFormat:'${p.dataFormat}'. Please use 'channelsLast'.`);let C=n.makeOutput(p.outShape,\"float32\"),E=n.dataIdMap.get(C.dataId).id;return qv(s,r.shape[0],r.shape[1],r.shape[2],c,d,h,f,m,g,x,A,y,b,w,S,E),C}var tte={kernelName:_i,backendName:\"wasm\",setupFunc:Qee,kernelFunc:ete},Xv;function ate(e){Xv=e.wasm.cwrap(Pi,null,[\"number, number, number\"])}function nte(e){let{backend:t,inputs:a,attrs:n}=e,{axis:r,keepDims:s}=n,{x:i}=a,o=t.dataIdMap.get(i.dataId).id,l=o,u=i,{transposed:p,axes:c,originalAxes:d,inputWasTransposed:h}=us(i,r,t),f=c;if(h){let b=t.dataIdMap.get(p.dataId).id;b!==o&&(u=p,l=b,f=T.getInnerMostAxes(f.length,u.shape.length))}T.assertAxesAreInnerMostDims(\"mean\",f,u.shape.length);let[m,g]=T.computeOutAndReduceShapes(u.shape,f),x=v.sizeFromShape(g),A=u;u.dtype!==\"float32\"&&(A=xu({backend:t,inputs:{x:u},attrs:{dtype:\"float32\"}}),l=t.dataIdMap.get(A.dataId).id);let y=t.makeOutput(m,\"float32\");if(v.sizeFromShape(u.shape)!==0){let b=t.dataIdMap.get(y.dataId).id;Xv(l,x,b)}if(h&&t.disposeData(p.dataId),s){let b=T.expandShapeToKeepDim(y.shape,d);y.shape=b}return u.dtype!==\"float32\"&&t.disposeData(A.dataId),y}var rte={kernelName:Pi,backendName:\"wasm\",setupFunc:ate,kernelFunc:nte},Kv;function ste(e){Kv=e.wasm.cwrap(Fi,null,[\"number\",\"number\",\"number\",\"number\"])}function ite(e){let{backend:t,inputs:a,attrs:n}=e,{axis:r,keepDims:s}=n,{x:i}=a,o=t.dataIdMap.get(i.dataId).id,l=o,u=i,{transposed:p,axes:c,originalAxes:d,inputWasTransposed:h}=us(i,r,t);if(h){let y=t.dataIdMap.get(p.dataId).id;y!==o&&(u=p,l=y)}let f=u.shape.length;T.assertAxesAreInnerMostDims(\"min\",c,f);let[m,g]=T.computeOutAndReduceShapes(u.shape,c),x=v.sizeFromShape(g),A=t.makeOutput(m,u.dtype);if(v.sizeFromShape(u.shape)!==0){let y=t.dataIdMap.get(A.dataId).id;Kv(l,Tt[i.dtype],x,y)}if(h&&t.disposeData(p.dataId),s){let y=T.expandShapeToKeepDim(A.shape,d);A.shape=y}return A}var ote={kernelName:Fi,backendName:\"wasm\",setupFunc:ste,kernelFunc:ite},lte=!1,ute=la(Oi,lte),M1;(function(e){e[e.reflect=0]=\"reflect\",e[e.symmetric=1]=\"symmetric\"})(M1||(M1={}));var Zv;function dte(e){Zv=e.wasm.cwrap(Di,null,[\"number\",\"array\",\"number\",\"number\",\"array\",\"array\",\"number\",\"number\"])}function pte(e){let{inputs:{x:t},backend:a,attrs:{paddings:n,mode:r}}=e,s=n.map((f,m)=>f[0]+t.shape[m]+f[1]),i=a.dataIdMap.get(t.dataId).id,o=a.makeOutput(s,t.dtype),l=a.dataIdMap.get(o.dataId).id,u=new Uint8Array(new Int32Array(t.shape).buffer),p=n.map(f=>f[0]),c=n.map(f=>f[1]),d=new Uint8Array(new Int32Array(p).buffer),h=new Uint8Array(new Int32Array(c).buffer);return Zv(i,u,t.shape.length,Tt[t.dtype],d,h,M1[r],l),o}var cte={kernelName:Di,backendName:\"wasm\",kernelFunc:pte,setupFunc:dte},hte=!0,fte=la(zi,hte),mte=Bt(Vl);function _3(e,t){let a=new Int32Array(e.wasm.HEAPU8.buffer,t,4),n=a[0],r=a[1],s=a[2],i=a[3];return e.wasm._free(t),{pSelectedIndices:n,selectedSize:r,pSelectedScores:s,pValidOutputs:i}}var Yv;function gte(e){Yv=e.wasm.cwrap(Bi,\"number\",[\"number\",\"number\",\"number\",\"number\",\"number\"])}function xte(e){let{backend:t,inputs:a,attrs:n}=e,{iouThreshold:r,maxOutputSize:s,scoreThreshold:i}=n,{boxes:o,scores:l}=a,u=t.dataIdMap.get(o.dataId).id,p=t.dataIdMap.get(l.dataId).id,c=Yv(u,p,s,r,i),{pSelectedIndices:d,selectedSize:h,pSelectedScores:f,pValidOutputs:m}=_3(t,c);return t.wasm._free(f),t.wasm._free(m),t.makeOutput([h],\"int32\",d)}var Ate={kernelName:Bi,backendName:\"wasm\",setupFunc:gte,kernelFunc:xte},Jv;function yte(e){Jv=e.wasm.cwrap(Ul,\"number\",[\"number\",\"number\",\"number\",\"number\",\"number\",\"bool\"])}function bte(e){let{backend:t,inputs:a,attrs:n}=e,{iouThreshold:r,maxOutputSize:s,scoreThreshold:i,padToMaxOutputSize:o}=n,{boxes:l,scores:u}=a,p=t.dataIdMap.get(l.dataId).id,c=t.dataIdMap.get(u.dataId).id,d=Jv(p,c,s,r,i,o),{pSelectedIndices:h,selectedSize:f,pSelectedScores:m,pValidOutputs:g}=_3(t,d);t.wasm._free(m);let x=t.makeOutput([f],\"int32\",h),A=t.makeOutput([],\"int32\",g);return[x,A]}var vte={kernelName:Ul,backendName:\"wasm\",setupFunc:yte,kernelFunc:bte},Qv;function wte(e){Qv=e.wasm.cwrap(Wi,\"number\",[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function kte(e){let{backend:t,inputs:a,attrs:n}=e,{iouThreshold:r,maxOutputSize:s,scoreThreshold:i,softNmsSigma:o}=n,{boxes:l,scores:u}=a,p=t.dataIdMap.get(l.dataId).id,c=t.dataIdMap.get(u.dataId).id,d=Qv(p,c,s,r,i,o),{pSelectedIndices:h,selectedSize:f,pSelectedScores:m,pValidOutputs:g}=_3(t,d);t.wasm._free(g);let x=t.makeOutput([f],\"int32\",h),A=t.makeOutput([f],\"float32\",m);return[x,A]}var Ite={kernelName:Wi,backendName:\"wasm\",setupFunc:wte,kernelFunc:kte},Ste=!1,Tte=la(Li,Ste,\"bool\"),e8;function Cte(e){e8=e.wasm.cwrap(Vi,null,[\"number\",\"number\",\"number\",\"number\",\"number\"])}function Nte(e){let{inputs:t,backend:a,attrs:n}=e,{indices:r}=t,{dtype:s,depth:i,onValue:o,offValue:l}=n,u=a.makeOutput([...r.shape,i],s),p=a.dataIdMap.get(u.dataId).id,c=a.dataIdMap.get(r.dataId).id;return e8(c,i,o,l,p),u}var Ete={kernelName:Vi,backendName:\"wasm\",setupFunc:Cte,kernelFunc:Nte};function Rte(e){let{inputs:{x:t},backend:a}=e,n=a.makeOutput(t.shape,t.dtype);return a.typedArrayFromHeap(n).fill(1),n}var Mte={kernelName:Gl,backendName:\"wasm\",kernelFunc:Rte};function $te(e){let{inputs:t,backend:a,attrs:n}=e,{axis:r}=n;if(t.length===1)return R1({inputs:{input:t[0]},backend:a,attrs:{dim:r}});let s=t[0].shape,i=t[0].dtype;t.forEach(p=>{v.assertShapesMatch(s,p.shape,\"All tensors passed to stack must have matching shapes\"),v.assert(i===p.dtype,()=>\"All tensors passed to stack must have matching dtypes\")});let o=[],l=t.map(p=>{let c=R1({inputs:{input:p},backend:a,attrs:{dim:r}});return o.push(c),c}),u=Rv({inputs:l,backend:a,attrs:{axis:r}});return o.forEach(p=>a.disposeData(p.dataId)),u}var _te={kernelName:Hl,backendName:\"wasm\",kernelFunc:$te},t8;function Pte(e){t8=e.wasm.cwrap(Ui,null,[\"number\",\"array\",\"number\",\"number\",\"array\",\"array\",\"number\",\"number\"])}function Fte(e){let{inputs:{x:t},backend:a,attrs:{paddings:n,constantValue:r}}=e,s=n.map((f,m)=>f[0]+t.shape[m]+f[1]);if(v.sizeFromShape(t.shape)===0)return zv({backend:a,attrs:{shape:s,value:r,dtype:t.dtype}});let i=a.dataIdMap.get(t.dataId).id,o=a.makeOutput(s,t.dtype),l=a.dataIdMap.get(o.dataId).id,u=new Uint8Array(new Int32Array(t.shape).buffer),p=n.map(f=>f[0]),c=n.map(f=>f[1]),d=new Uint8Array(new Int32Array(p).buffer),h=new Uint8Array(new Int32Array(c).buffer);return t8(i,u,t.shape.length,Tt[t.dtype],d,h,r,l),o}var a8={kernelName:Ui,backendName:\"wasm\",kernelFunc:Fte,setupFunc:Pte},Ote=!1,Dte=la(Gi,Ote),n8;function zte(e){n8=e.wasm.cwrap(Hi,null,[\"number\",\"number\",\"number\"])}function Lte(e){let{inputs:t,backend:a}=e,{x:n,alpha:r}=t,s=a.dataIdMap.get(n.dataId).id,i=a.dataIdMap.get(r.dataId).id,o=s,l=n,u=l;l.dtype!==\"float32\"&&(u=xu({backend:a,inputs:{x:n},attrs:{dtype:\"float32\"}}),o=a.dataIdMap.get(u.dataId).id);let p=a.makeOutput(n.shape,\"float32\"),c=a.dataIdMap.get(p.dataId).id;return n8(o,i,c),l.dtype!==\"float32\"&&a.disposeData(u.dataId),p}var Bte={kernelName:Hi,backendName:\"wasm\",setupFunc:zte,kernelFunc:Lte},r8;function Wte(e){r8=e.wasm.cwrap(ji,null,[\"number\",\"number\",\"number\",\"number\"])}function Vte(e){let{backend:t,inputs:a,attrs:n}=e,{axis:r,keepDims:s}=n,{x:i}=a,o=t.dataIdMap.get(i.dataId).id,l=o,u=i,{transposed:p,axes:c,originalAxes:d,inputWasTransposed:h}=us(i,r,t),f=c;if(h){let y=t.dataIdMap.get(p.dataId).id;y!==o&&(u=p,l=y,f=T.getInnerMostAxes(f.length,u.shape.length))}T.assertAxesAreInnerMostDims(\"prod\",f,u.shape.length);let[m,g]=T.computeOutAndReduceShapes(u.shape,f),x=v.sizeFromShape(g),A=t.makeOutput(m,u.dtype);if(v.sizeFromShape(u.shape)!==0){let y=t.dataIdMap.get(A.dataId).id;r8(l,x,Tt[A.dtype],y)}if(h&&t.disposeData(p.dataId),s){let y=T.expandShapeToKeepDim(A.shape,d);A.shape=y}return A}var Ute={kernelName:ji,backendName:\"wasm\",setupFunc:Wte,kernelFunc:Vte},Gte=e=>{let{backend:t,attrs:a}=e,{start:n,stop:r,step:s,dtype:i}=a,o=d3(n,r,s,i),l=t.makeOutput([o.length],i);return t.typedArrayFromHeap(l).set(o),l},Hte={kernelName:jl,backendName:\"wasm\",kernelFunc:Gte},jte=!0,qte=la(ci,jte),Xte=Bt(qi),Kte=Bt(Xi),Zte=Bt(Yi),s8;function Yte(e){s8=e.wasm.cwrap(Zi,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function Jte(e){let{backend:t,inputs:a,attrs:n}=e,{images:r}=a,{alignCorners:s,halfPixelCenters:i,size:o}=n,[l,u]=o,[p,c,d,h]=r.shape,f=[p,l,u,h],m=t.dataIdMap.get(r.dataId),g;m.dtype!==\"float32\"&&(g=xu({backend:t,inputs:{x:r},attrs:{dtype:\"float32\"}}),m=t.dataIdMap.get(g.dataId));let x=m.id,A=t.makeOutput(f,\"float32\");if(v.sizeFromShape(r.shape)===0)return A;let y=t.dataIdMap.get(A.dataId).id;return s8(x,p,c,d,h,l,u,s?1:0,i?1:0,y),g!=null&&t.disposeData(g.dataId),A}var Qte={kernelName:Zi,backendName:\"wasm\",setupFunc:Yte,kernelFunc:Jte},i8;function eae(e){i8=e.wasm.cwrap(Ki,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function tae(e){let{backend:t,inputs:a,attrs:n}=e,{images:r}=a,{alignCorners:s,halfPixelCenters:i,size:o}=n,[l,u]=o,[p,c,d,h]=r.shape,f=[p,l,u,h],m=t.makeOutput(f,\"float32\");if(v.sizeFromShape(r.shape)===0)return m;let g=t.dataIdMap.get(r.dataId),x;g.dtype!==\"float32\"&&(x=xu({backend:t,inputs:{x:r},attrs:{dtype:\"float32\"}}),g=t.dataIdMap.get(x.dataId));let A=g.id,y=t.dataIdMap.get(m.dataId).id;return i8(A,p,c,d,h,l,u,s?1:0,i?1:0,y),x!=null&&t.disposeData(x.dataId),m}var aae={kernelName:Ki,backendName:\"wasm\",setupFunc:eae,kernelFunc:tae},o8;function nae(e){o8=e.wasm.cwrap(Ji,null,[\"number\",\"array\",\"number\",\"array\",\"number\",\"number\"])}function rae(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{dims:s}=n,i=v.parseAxisParam(s,r.shape);if(r.shape.length===0)return Bh({inputs:{x:r},backend:a});let o=a.makeOutput(r.shape,r.dtype),l=a.dataIdMap.get(r.dataId).id,u=a.dataIdMap.get(o.dataId).id,p=new Uint8Array(new Int32Array(i).buffer),c=new Uint8Array(new Int32Array(r.shape).buffer);o8(l,p,i.length,c,r.shape.length,u);let d=za({inputs:{x:o},attrs:{shape:r.shape},backend:a});return a.disposeData(o.dataId),d}var sae={kernelName:Ji,backendName:\"wasm\",kernelFunc:rae,setupFunc:nae},l8;function iae(e){l8=e.wasm.cwrap(mo,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"array\",\"number\",\"number\"])}function oae(e){let{inputs:t,backend:a,attrs:n}=e,{image:r}=t,{radians:s,fillValue:i,center:o}=n,l=a.makeOutput(r.shape,r.dtype),u=a.dataIdMap.get(r.dataId).id,p=a.dataIdMap.get(l.dataId).id,[c,d,h,f]=r.shape,[m,g]=T.getImageCenter(o,d,h),x=i===0,A=255,y=typeof i==\"number\"?[i,i,i,x?0:A]:[...i,A],b=new Uint8Array(new Int32Array(y).buffer);return l8(u,c,d,h,f,s,m,g,b,y.length,p),l}var lae={kernelName:mo,backendName:\"wasm\",kernelFunc:oae,setupFunc:iae},uae=Bt(Xl),dae=Bt(Qi),u8;function pae(e){u8=e.wasm.cwrap(eo,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"array\",\"number\",\"number\"])}function cae(e){let{backend:t,inputs:a,attrs:n}=e,{indices:r,updates:s}=a,{shape:i}=n,o=t.makeOutput(i,s.dtype);if(v.sizeFromShape(i)===0)return o;let{sliceRank:l,numUpdates:u,sliceSize:p,strides:c,outputSize:d}=h2.calculateShapes(s,r,i),h=t.dataIdMap.get(r.dataId).id,f=t.dataIdMap.get(s.dataId).id,m=new Uint8Array(new Int32Array(c).buffer),g=t.dataIdMap.get(o.dataId).id;return u8(h,f,Tt[s.dtype],l,u,p,m,d,g),o}var hae={kernelName:eo,backendName:\"wasm\",setupFunc:pae,kernelFunc:cae},d8;function fae(e){d8=e.wasm.cwrap(\"SelectV2\",null,[\"number\",\"number\",\"number\",\"number\",\"number\"])}function mae(e){let{inputs:t,backend:a}=e,{condition:n,t:r,e:s}=t,i=a.dataIdMap.get(n.dataId).id,o=a.dataIdMap.get(r.dataId).id,l=a.dataIdMap.get(s.dataId).id,u=a.makeOutput(r.shape,r.dtype),p=a.dataIdMap.get(u.dataId).id,c=n.shape.length,d=r.shape.length,h=c===0||c>1||d===1?1:v.sizeFromShape(r.shape.slice(1));return d8(i,o,l,h,p),u}var gae={kernelName:Kl,backendName:\"wasm\",kernelFunc:mae,setupFunc:fae},p8;function xae(e){p8=e.wasm.cwrap(ao,null,[\"number\",\"number\"])}function Aae(e){let{backend:t,inputs:{x:a}}=e,n=t.dataIdMap.get(a.dataId).id,r=t.makeOutput(a.shape,a.dtype),s=t.dataIdMap.get(r.dataId).id;return v.sizeFromShape(r.shape)===0||p8(n,s),r}var yae={kernelName:\"Sigmoid\",backendName:\"wasm\",setupFunc:xae,kernelFunc:Aae},bae=Bt(to),c8;function vae(e){c8=e.wasm.cwrap(so,null,[\"number\",\"number\",\"number\",\"number\"])}function wae(e){let{backend:t,inputs:{logits:a},attrs:{dim:n}}=e,r=t.dataIdMap.get(a.dataId).id,s=t.makeOutput(a.shape,a.dtype),i=t.dataIdMap.get(s.dataId).id,o=a.shape[n],l=v.sizeFromShape(a.shape)/o;return v.sizeFromShape(s.shape)===0||c8(r,i,o,l),s}var kae={kernelName:so,backendName:\"wasm\",setupFunc:vae,kernelFunc:wae};function Iae(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockShape:s,paddings:i}=n,o=v.sizeFromShape(s),l=[[0,0]];l.push(...i);for(let g=1+s.length;g<r.shape.length;++g)l.push([0,0]);let u=a8.kernelFunc({inputs:{x:r},backend:a,attrs:{paddings:l,constantValue:0}}),p=T.getReshaped(u.shape,s,o,!1),c=T.getPermuted(p.length,s.length,!1),d=T.getReshapedPermuted(u.shape,s,o,!1),h=za({inputs:{x:u},backend:a,attrs:{shape:p}}),f=Qr({inputs:{x:h},backend:a,attrs:{perm:c}}),m=za({inputs:{x:f},backend:a,attrs:{shape:d}});return a.disposeData(u.dataId),a.disposeData(h.dataId),a.disposeData(f.dataId),m}var Sae={kernelName:Jl,backendName:\"wasm\",kernelFunc:Iae},h8;function Tae(e){h8=e.wasm.cwrap(\"SparseFillEmptyRows\",\"number\",[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function Cae(e){let{backend:t,inputs:a}=e,{indices:n,values:r,denseShape:s,defaultValue:i}=a,o=n.shape[0],l=n.shape[1],u=t.readSync(s.dataId)[0],p=[o+u,l],c=t.dataIdMap.get(n.dataId).id,d=t.dataIdMap.get(r.dataId).id,h=t.dataIdMap.get(i.dataId).id,f=t.makeOutput(p,n.dtype),m=t.dataIdMap.get(f.dataId).id,g=t.makeOutput(p.slice(0,1),r.dtype),x=t.dataIdMap.get(g.dataId).id,A=t.makeOutput([u],\"bool\"),y=t.dataIdMap.get(A.dataId).id,b=t.makeOutput([o],n.dtype),w=t.dataIdMap.get(b.dataId).id,S=t.makeOutput([4],\"int32\"),C=t.dataIdMap.get(S.dataId).id,E=h8(c,d,Tt[r.dtype],o,u,l,h,m,x,y,w,C),_=t.readSync(S.dataId),$;switch(_[0]){case 1:{$=T.getSparseFillEmptyRowsIndicesDenseShapeMismatch(_[1]);break}case 2:{$=T.getSparseFillEmptyRowsNegativeIndexErrorMessage(_[1],_[2]);break}case 3:$=T.getSparseFillEmptyRowsOutOfRangeIndexErrorMessage(_[1],_[2],_[3]);break;default:$=\"\"}if(t.disposeData(S.dataId),$)throw t.disposeData(f.dataId),t.disposeData(g.dataId),t.disposeData(A.dataId),t.disposeData(b.dataId),new Error($);let M=f,I=g;return E!==p[0]&&(M=qs({inputs:{x:f},attrs:{begin:0,size:[E,l]},backend:t}),I=qs({inputs:{x:g},attrs:{begin:0,size:E},backend:t}),t.disposeData(f.dataId),t.disposeData(g.dataId)),[M,I,A,b]}var Nae={kernelName:Od,backendName:\"wasm\",setupFunc:Tae,kernelFunc:Cae},f8;function Eae(e){f8=e.wasm.cwrap(eu,null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function Rae(e){let{backend:t,inputs:a}=e,{inputIndices:n,inputShape:r,newShape:s}=a;if(n.shape.length!==2)throw new Error(`Input indices should be a matrix but received shape\n        ${n.shape}`);if(r.shape.length!==1)throw new Error(`Input shape should be a vector but received shape\n        ${r.shape}`);if(s.shape.length!==1)throw new Error(`Target shape should be a vector but received shape ${s.shape}`);let i=t.dataIdMap.get(n.dataId).id,o=t.dataIdMap.get(r.dataId).id,l=t.dataIdMap.get(s.dataId).id,u=n.shape[0],p=v.sizeFromShape(s.shape),c=t.makeOutput([u,p],n.dtype),d=t.dataIdMap.get(c.dataId).id,h=t.makeOutput([p],s.dtype),f=t.dataIdMap.get(h.dataId).id,m=t.makeOutput([3],\"int32\"),g=t.dataIdMap.get(m.dataId).id;f8(i,o,l,u,d,f,g);let x=t.readSync(m.dataId),A;switch(x[0]){case 0:{A=T.getSparseReshapeMultipleNegativeOneOutputDimErrorMessage(x[1],x[2]);break}case 1:{A=T.getSparseReshapeNegativeOutputDimErrorMessage(x[1],x[2]);break}case 2:A=T.getSparseReshapeEmptyTensorZeroOutputDimErrorMessage();break;case 3:{let y=Array.from(t.readSync(r.dataId)),b=Array.from(t.readSync(h.dataId));A=T.getSparseReshapeInputOutputMultipleErrorMessage(y,b);break}case 4:{let y=Array.from(t.readSync(r.dataId)),b=Array.from(t.readSync(h.dataId));A=T.getSparseReshapeInputOutputMismatchErrorMessage(y,b);break}default:A=\"\"}if(t.disposeData(m.dataId),A)throw t.disposeData(c.dataId),t.disposeData(h.dataId),new Error(A);return[c,h]}var Mae={kernelName:eu,backendName:\"wasm\",setupFunc:Eae,kernelFunc:Rae},m8;function g8(e){m8=e.wasm.cwrap(\"SparseSegmentReduction\",null,[\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function x8(e,t){let{backend:a,inputs:n}=e,{data:r,indices:s,segmentIds:i}=n,o=s.shape[0],l=a.readSync(i.dataId,o-1,o)[0],u=o>0?l+1:0;if(u<0)throw new Error(T.getSparseSegmentReductionNegativeSegmentIdsErrorMessage());let p=r.shape.slice();p[0]=u;let c=a.dataIdMap.get(r.dataId).id,d=a.dataIdMap.get(s.dataId).id,h=a.dataIdMap.get(i.dataId).id,f=a.makeOutput(p,r.dtype),m=a.dataIdMap.get(f.dataId).id,g=a.makeOutput([4],\"int32\"),x=a.dataIdMap.get(g.dataId).id;m8(c,Tt[r.dtype],r.shape[0],d,h,m,x,t,0);let A=a.readSync(g.dataId),y;switch(A[0]){case 0:{y=T.getSparseSegmentReductionNegativeSegmentIdsErrorMessage();break}case 1:{y=T.getSparseSegmentReductionNonIncreasingSegmentIdsErrorMessage();break}case 2:y=T.getSparseSegmentReductionSegmentIdOutOfRangeErrorMessage(A[1],A[2]);break;case 3:y=T.getSparseSegmentReductionIndicesOutOfRangeErrorMessage(A[1],A[2],A[3]);break;default:y=\"\"}if(a.disposeData(g.dataId),y)throw a.disposeData(f.dataId),new Error(y);return f}function $ae(e){return x8(e,!0)}var _ae={kernelName:Dd,backendName:\"wasm\",setupFunc:g8,kernelFunc:$ae};function Pae(e){return x8(e,!1)}var Fae={kernelName:zd,backendName:\"wasm\",setupFunc:g8,kernelFunc:Pae};function Oae(e){let{inputs:t,attrs:a,backend:n}=e,{x:r}=t,{numOrSizeSplits:s,axis:i}=a,o=v.parseAxisParam(i,r.shape)[0],l=T.prepareSplitSize(r,s,o),u=new Array(r.shape.length).fill(0),p=r.shape.slice();return l.map(c=>{let d=[...p];d[o]=c;let h=qs({inputs:{x:r},attrs:{begin:u,size:d},backend:n});return u[o]+=c,h})}var Dae={kernelName:Ql,backendName:\"wasm\",kernelFunc:Oae},zae=Bt(no),Lae=Bt(Bd),Bae=!0,Wae=la(io,Bae),A8;function Vae(e){A8=e.wasm.cwrap(fo,null,[\"number\",\"number\",\"number\",\"number\"])}function Uae(e){let{backend:t,inputs:a,attrs:n}=e,{alpha:r}=n,{x:s}=a,i=t.dataIdMap.get(s.dataId).id,o=t.makeOutput(s.shape,s.dtype),l=t.dataIdMap.get(o.dataId).id;return A8(i,r,Tt[s.dtype],l),o}var Gae={kernelName:fo,backendName:\"wasm\",setupFunc:Vae,kernelFunc:Uae},y8;function Hae(e){y8=e.wasm.cwrap(oo,null,[\"number\",\"array\",\"number\",\"array\",\"array\",\"array\",\"array\",\"array\",\"number\",\"number\"])}function jae(e){let{backend:t,inputs:a,attrs:n}=e,{x:r}=a,{begin:s,end:i,strides:o,beginMask:l,endMask:u,ellipsisMask:p,newAxisMask:c,shrinkAxisMask:d}=n,{finalShapeSparse:h,finalShape:f,isIdentity:m,sliceDim0:g,isSimpleSlice:x,begin:A,end:y,strides:b}=It.sliceInfo(r.shape,s,i,o,l,u,p,c,d),w;if(m)w=za({inputs:{x:r},backend:t,attrs:{shape:f}});else if(g||x){v.assert(r.shape.length>=1,()=>`Input must have rank at least 1, got: ${r.shape.length}`);let S=It.computeOutShape(A,y,b),C=qs({inputs:{x:r},backend:t,attrs:{begin:A,size:S}});w=za({inputs:{x:C},backend:t,attrs:{shape:f}}),t.disposeData(C.dataId)}else{let S=t.makeOutput(h,\"float32\"),C=t.dataIdMap.get(r.dataId).id,E=new Uint8Array(new Int32Array(v.computeStrides(r.shape)).buffer),_=new Uint8Array(new Int32Array(A).buffer),$=new Uint8Array(new Int32Array(y).buffer),M=new Uint8Array(new Int32Array(b).buffer),I=new Uint8Array(new Int32Array(h).buffer),N=new Uint8Array(new Int32Array(v.computeStrides(h)).buffer),O=t.dataIdMap.get(S.dataId).id;y8(C,E,r.shape.length,_,$,M,I,N,h.length,O),w=za({inputs:{x:S},backend:t,attrs:{shape:f}}),t.disposeData(S.dataId)}return w}var qae={kernelName:oo,backendName:\"wasm\",setupFunc:Hae,kernelFunc:jae};function Xae(e){let{backend:t,inputs:a,attrs:n}=e,{data:r,dataSplits:s}=a,{separator:i,nGramWidths:o,leftPad:l,rightPad:u,padWidth:p,preserveShortSequences:c}=n,d=t.readSync(r.dataId),h=t.readSync(s.dataId),[f,m]=c3(d,h,i,o,l,u,p,c),g=t.makeOutput([f.length],\"string\"),x=t.dataIdMap.get(g.dataId);x.stringBytes=f;let A=t.makeOutput(s.shape,\"int32\");return t.typedArrayFromHeap(A).set(m),[g,A]}var Kae={kernelName:tu,backendName:\"wasm\",kernelFunc:Xae};function Zae(e){let{backend:t,inputs:a,attrs:n}=e,{input:r,delimiter:s}=a,{skipEmpty:i}=n,o=t.readSync(r.dataId),l=t.readSync(s.dataId),[u,p,c]=h3(o,l[0],i),d=p.length,h=t.makeOutput([d,2],\"int32\");t.typedArrayFromHeap(h).set(u);let f=t.makeOutput([d],\"string\"),m=t.dataIdMap.get(f.dataId);m.stringBytes=p;let g=t.makeOutput([2],\"int32\");return t.typedArrayFromHeap(g).set(c),[h,f,g]}var Yae={kernelName:Wd,backendName:\"wasm\",kernelFunc:Zae};function Jae(e){let{backend:t,inputs:a,attrs:n}=e,{input:r}=a,{numBuckets:s}=n,i=t.readSync(r.dataId),o=f3(i,s),l=t.makeOutput(r.shape,\"int32\");return t.typedArrayFromHeap(l).set(o),l}var Qae={kernelName:Vd,backendName:\"wasm\",kernelFunc:Jae},ene=!0,tne=la(lo,ene),b8;function ane(e){b8=e.wasm.cwrap(ro,null,[\"number\",\"number\",\"number\",\"number\"])}function nne(e){let{backend:t,inputs:a,attrs:n}=e,{axis:r,keepDims:s}=n,{x:i}=a,o=t.dataIdMap.get(i.dataId).id,l=o,u=i,{transposed:p,axes:c,originalAxes:d,inputWasTransposed:h}=us(i,r,t),f=c;if(h){let y=t.dataIdMap.get(p.dataId).id;y!==o&&(u=p,l=y,f=T.getInnerMostAxes(f.length,u.shape.length))}T.assertAxesAreInnerMostDims(\"sum\",f,u.shape.length);let[m,g]=T.computeOutAndReduceShapes(u.shape,f),x=v.sizeFromShape(g),A=t.makeOutput(m,u.dtype);if(v.sizeFromShape(u.shape)!==0){let y=t.dataIdMap.get(A.dataId).id;b8(l,x,Tt[A.dtype],y)}if(h&&t.disposeData(p.dataId),s){let y=T.expandShapeToKeepDim(A.shape,d);A.shape=y}return A}var rne={kernelName:ro,backendName:\"wasm\",setupFunc:ane,kernelFunc:nne},sne=Bt(uo),ine=Bt(po),v8;function one(e){v8=e.wasm.cwrap(ns,null,[\"number\",\"array\",\"number\",\"array\",\"number\",\"number\"])}function lne(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,s=a.dataIdMap.get(r.dataId).id,{reps:i}=n,o=new Array(r.shape.length);for(let d=0;d<o.length;d++)o[d]=r.shape[d]*i[d];let l=new Uint8Array(new Int32Array(r.shape).buffer),u=new Uint8Array(new Int32Array(o).buffer),p=a.makeOutput(o,r.dtype),c=a.dataIdMap.get(p.dataId).id;return v8(s,l,r.shape.length,u,o.length,Tt[p.dtype],c),p}var une={kernelName:ns,backendName:\"wasm\",setupFunc:one,kernelFunc:lne},w8;function dne(e){w8=e.wasm.cwrap(co,null,[\"number\",\"array\",\"number\",\"number\",\"number\",\"bool\",\"number\",\"number\"])}var pne=({inputs:e,backend:t,attrs:a})=>{let{x:n}=e,{k:r,sorted:s}=a,i=t.dataIdMap.get(n.dataId).id,o=new Uint8Array(new Int32Array(n.shape).buffer),l=n.shape.slice();l[l.length-1]=r;let u=t.makeOutput(l,n.dtype),p=t.dataIdMap.get(u.dataId).id,c=t.makeOutput(l,\"int32\"),d=t.dataIdMap.get(c.dataId).id;return w8(i,o,n.shape.length,Tt[n.dtype],r,s,p,d),[u,c]},cne={kernelName:co,backendName:\"wasm\",setupFunc:dne,kernelFunc:pne},k8;function hne(e){k8=e.wasm.cwrap(ho,null,[\"number\",\"number\",\"bool\",\"number\",\"number\",\"number\",\"number\",\"number\",\"number\",\"array\",\"number\",\"array\",\"number\",\"number\",\"number\",\"number\",\"number\"])}function fne(e){let{backend:t,inputs:a,attrs:n}=e,{image:r,transforms:s}=a,{interpolation:i,fillMode:o,fillValue:l,outputShape:u}=n,[p,c,d,h]=r.shape,[f,m]=u!=null?u:[c,d],g=[p,f,m,h],x=new Uint8Array(new Int32Array(v.computeStrides(r.shape)).buffer),A=new Uint8Array(new Int32Array(v.computeStrides(g)).buffer),y=t.makeOutput(g,r.dtype),b=t.dataIdMap.get(y.dataId).id,w=t.dataIdMap.get(r.dataId).id,S=t.dataIdMap.get(s.dataId).id,C=i===\"nearest\"?1:2,E;switch(o){case\"constant\":E=1;break;case\"reflect\":E=2;break;case\"wrap\":E=3;break;case\"nearest\":E=4;break;default:E=1;break}return k8(w,S,s.shape[0]>1,p,f,m,h,d,c,x,r.shape.length-1,A,g.length-1,C,E,l,b),y}var mne={kernelName:ho,backendName:\"wasm\",setupFunc:hne,kernelFunc:fne};function gne(e){let{inputs:t,backend:a,attrs:n}=e,{value:r}=t,{axis:s}=n;s<0&&(s+=r.shape.length);let i=r.shape[s],o=r.shape.length,l=new Array(o-1),u=0;for(let h=0;h<o;h++)h!==s&&(l[u++]=r.shape[h]);let p=new Array(i),c=new Array(o).fill(0),d=r.shape.slice();d[s]=1;for(let h=0;h<p.length;h++)c[s]=h,p[h]=qs({inputs:{x:r},attrs:{begin:c,size:d},backend:a});return p.map(({dataId:h,dtype:f})=>({dataId:h,dtype:f,shape:l}))}var xne={kernelName:au,backendName:\"wasm\",kernelFunc:gne};function Ane(e){let{inputs:{x:t},backend:a}=e,n=a.makeOutput(t.shape,t.dtype);return a.typedArrayFromHeap(n).fill(0),n}var yne={kernelName:nu,backendName:\"wasm\",kernelFunc:Ane},bne=[jJ,qJ,KJ,JJ,iQ,uQ,cQ,mQ,yQ,SQ,TQ,CQ,RQ,MQ,PQ,DQ,zQ,LQ,VQ,HQ,XQ,YQ,eee,tee,nee,ree,see,iee,uee,dee,cee,mee,Aee,vee,Iee,Cee,Eee,Mee,QJ,$ee,Fee,Dee,Lee,Bee,Vee,Uee,Hee,qee,Zee,Jee,tte,rte,ote,ute,cte,fte,mte,Ate,vte,Ite,Tte,Ete,Mte,_te,a8,Dte,Bte,Ute,Hte,qte,Xte,Kte,Zte,gQ,Qte,aae,sae,lae,uae,dae,hae,gae,yae,bae,kQ,kae,Sae,Nae,Mae,_ae,Fae,Dae,zae,Lae,Wae,Gae,qae,Kae,Yae,Qae,tne,rne,sne,ine,une,cne,mne,nQ,xne,yne];for(let e of bne)mn(e);var $1=W();$1.registerFlag(\"WASM_HAS_SIMD_SUPPORT\",async()=>{try{return WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,10,9,1,7,0,65,0,253,15,26,11]))}catch(e){return!1}});$1.registerFlag(\"WASM_HAS_MULTITHREAD_SUPPORT\",async()=>{if($1.get(\"IS_NODE\"))return!1;try{return new MessageChannel().port1.postMessage(new SharedArrayBuffer(1)),WebAssembly.validate(new Uint8Array([0,97,115,109,1,0,0,0,1,4,1,96,0,0,3,2,1,0,5,4,1,3,1,1,10,11,1,9,0,65,0,254,16,2,0,26,11]))}catch(e){return!1}});var Ox=yl(nS()),vne=yl(rS()),Dx=yl(sS()),zx=Ox.default||Ox,wne=Dx.default||Dx,I8=class extends bl{constructor(e){super(),this.wasm=e,this.dataIdNextNumber=1,this.wasm.tfjs.initWithThreadsCount(S8),_1=this.wasm.tfjs.getThreadsCount(),this.dataIdMap=new vd(this,kt())}write(e,t,a){let n={id:this.dataIdNextNumber++};return this.move(n,e,t,a,1),n}numDataIds(){return this.dataIdMap.numDataIds()}async time(e){let t=v.now();return e(),{kernelMs:v.now()-t}}move(e,t,a,n,r){let s=this.dataIdNextNumber++;if(n===\"string\"){let u=t;this.dataIdMap.set(e,{id:s,stringBytes:u,shape:a,dtype:n,memoryOffset:null,refCount:r});return}let i=v.sizeFromShape(a),o=i*v.bytesPerElement(n),l=this.wasm._malloc(o);this.dataIdMap.set(e,{id:s,memoryOffset:l,shape:a,dtype:n,refCount:r}),this.wasm.tfjs.registerTensor(s,i,l),t!=null&&this.wasm.HEAPU8.set(new Uint8Array(t.buffer,t.byteOffset,o),l)}async read(e){return this.readSync(e)}readSync(e,t,a){let{memoryOffset:n,dtype:r,shape:s,stringBytes:i}=this.dataIdMap.get(e);if(r===\"string\")return(t==null||t===0)&&(a==null||a>=i.length)?i:i.slice(t,a);t=t||0,a=a||v.sizeFromShape(s);let o=v.bytesPerElement(r),l=this.wasm.HEAPU8.slice(n+t*o,n+a*o);return Sne(l.buffer,r)}disposeData(e,t=!1){if(this.dataIdMap.has(e)){let a=this.dataIdMap.get(e);if(a.refCount--,!t&&a.refCount>0)return!1;this.wasm._free(a.memoryOffset),this.wasm.tfjs.disposeData(a.id),this.dataIdMap.delete(e)}return!0}refCount(e){return this.dataIdMap.has(e)?this.dataIdMap.get(e).refCount:0}incRef(e){let t=this.dataIdMap.get(e);t!=null&&t.refCount++}floatPrecision(){return 32}getMemoryOffset(e){return this.dataIdMap.get(e).memoryOffset}dispose(){this.wasm.tfjs.dispose(),\"PThread\"in this.wasm&&this.wasm.PThread.terminateAllThreads(),this.wasm=null}memory(){return{unreliable:!1}}makeOutput(e,t,a){let n;if(a==null)n=this.write(null,e,t);else{let r=this.dataIdNextNumber++;n={id:r},this.dataIdMap.set(n,{id:r,memoryOffset:a,shape:e,dtype:t,refCount:1});let s=v.sizeFromShape(e);this.wasm.tfjs.registerTensor(r,s,a)}return{dataId:n,shape:e,dtype:t}}typedArrayFromHeap({shape:e,dtype:t,dataId:a}){let n=this.wasm.HEAPU8.buffer,{memoryOffset:r}=this.dataIdMap.get(a),s=v.sizeFromShape(e);switch(t){case\"float32\":return new Float32Array(n,r,s);case\"int32\":return new Int32Array(n,r,s);case\"bool\":return new Uint8Array(n,r,s);default:throw new Error(`Unknown dtype ${t}`)}}};function kne(e){return(t,a)=>(v.fetch(e,{credentials:\"same-origin\"}).then(n=>{n.ok||t.env.a(`failed to load wasm binary file at '${e}'`),n.arrayBuffer().then(r=>{WebAssembly.instantiate(r,t).then(s=>{a(s.instance,s.module)})})}),{})}function Lx(e,t,a){if(Bc!=null)return Bc;let n=\"tfjs-backend-wasm.wasm\";return e&&t?n=\"tfjs-backend-wasm-threaded-simd.wasm\":e&&(n=\"tfjs-backend-wasm-simd.wasm\"),ed!=null&&ed[n]!=null?ed[n]:a+n}async function Ine(){let[e,t]=await Promise.all([W().getAsync(\"WASM_HAS_SIMD_SUPPORT\"),W().getAsync(\"WASM_HAS_MULTITHREAD_SUPPORT\")]);return new Promise((a,n)=>{let r={};r.locateFile=(o,l)=>{if(o.endsWith(\".worker.js\")){let u=vne.wasmWorkerContents.replace(/\\n/g,\"\\\\n\"),p=new Blob([u],{type:\"application/javascript\"});return URL.createObjectURL(p)}return o.endsWith(\".wasm\")?Lx(e,t,Yu!=null?Yu:l):l+o},P3&&(r.instantiateWasm=kne(Lx(e,t,Yu!=null?Yu:\"\")));let s=!1;r.onAbort=()=>{s||td||(td=!0,n({message:\"Make sure the server can serve the `.wasm` file relative to the bundled js file. For more details see https://github.com/tensorflow/tfjs/blob/master/tfjs-backend-wasm/README.md#using-bundlers\"}))};let i;t&&e&&Bc==null?(r.mainScriptUrlOrBlob=new Blob([\"var WasmBackendModuleThreadedSimd = \"+zx.toString()],{type:\"text/javascript\"}),i=zx(r)):i=wne(r),i.then(o=>{s=!0,td=!1;let l=null;o.tfjs={init:o.cwrap(\"init\",null,[]),initWithThreadsCount:o.cwrap(\"init_with_threads_count\",null,[\"number\"]),getThreadsCount:o.cwrap(\"get_threads_count\",\"number\",[]),registerTensor:o.cwrap(\"register_tensor\",null,[\"number\",\"number\",\"number\"]),disposeData:o.cwrap(\"dispose_data\",l,[\"number\"]),dispose:o.cwrap(\"dispose\",l,[])},a({wasm:o})}).catch(n)})}function Sne(e,t){switch(t){case\"float32\":return new Float32Array(e);case\"int32\":return new Int32Array(e);case\"bool\":return new Uint8Array(e);default:throw new Error(`Unknown dtype ${t}`)}}var Tne=[\"tfjs-backend-wasm.wasm\",\"tfjs-backend-wasm-simd.wasm\",\"tfjs-backend-wasm-threaded-simd.wasm\"],Bc=null,Yu=null,ed={},td=!1,P3=!1;function Cne(e,t=!1){if(l2(\"setWasmPath has been deprecated in favor of setWasmPaths and will be removed in a future release.\"),td)throw new Error(\"The WASM backend was already initialized. Make sure you call `setWasmPath()` before you call `tf.setBackend()` or `tf.ready()`\");Bc=e,P3=t}function Wh(e,t=!1){if(td)throw new Error(\"The WASM backend was already initialized. Make sure you call `setWasmPaths()` before you call `tf.setBackend()` or `tf.ready()`\");if(typeof e==\"string\")Yu=e;else{ed=e;let a=Tne.filter(n=>ed[n]==null);if(a.length>0)throw new Error(`There were no entries found for the following binaries: ${a.join(\",\")}. Please either call setWasmPaths with a map providing a path for each binary, or with a string indicating the directory where all the binaries can be found.`)}P3=t}var S8=-1,_1=-1;function Nne(e){S8=e}function Ene(){if(_1===-1)throw new Error(\"WASM backend not initialized.\");return _1}var Rne=\"4.1.0\",Mne=2;go(\"wasm\",async()=>{let{wasm:e}=await Ine();return new I8(e)},Mne);var zn=W();zn.registerFlag(\"WEBGPU_DEFERRED_SUBMIT_BATCH_SIZE\",()=>15);zn.registerFlag(\"WEBGPU_CPU_FORWARD\",()=>!0);zn.registerFlag(\"WEBGPU_MATMUL_PROGRAM_TYPE\",()=>-1);zn.registerFlag(\"WEBGPU_USE_NAIVE_CONV2D_TRANSPOSE\",()=>!1);zn.registerFlag(\"WEBGPU_USE_LOW_POWER_GPU\",()=>!1);zn.registerFlag(\"WEBGPU_CPU_HANDOFF_SIZE_THRESHOLD\",()=>1e3);zn.registerFlag(\"WEBGPU_USE_PROFILE_TOOL\",()=>!1);zn.registerFlag(\"WEBGPU_IMPORT_EXTERNAL_TEXTURE\",()=>!0);zn.registerFlag(\"WEBGPU_USE_NAIVE_CONV2D_DEBUG\",()=>!1);zn.registerFlag(\"WEBGPU_THRESHOLD_TO_INCREASE_WORKGROUPS_FOR_MATMUL\",()=>0);zn.registerFlag(\"WEBGPU_CONV_SEPARATE_IM2COL_SHADER\",()=>!1);var $ne=class{constructor(e){e&&(this.vendor=e.vendor,this.architecture=e.architecture,this.intelGPUGeneration=this.getIntelGPUGeneration())}getIntelGPUGeneration(){if(this.isIntel()){if(this.architecture.startsWith(\"gen\"))return Number(this.architecture.match(/\\d+/));if(this.architecture.startsWith(\"xe\"))return 12}return 0}isIntel(){return this.vendor===\"intel\"}},_ne=class{constructor(e){this.device=e,this.numUsedBuffers=0,this.numFreeBuffers=0,this.freeBuffers=new Map,this.usedBuffers=new Map,this.numBytesUsed=0,this.numBytesAllocated=0}acquireUploadBuffer(e,t){return this.acquireBuffer(e,t,!0)}acquireBuffer(e,t,a=!1){let n=Bx(e,t);if(this.freeBuffers.has(n)||this.freeBuffers.set(n,[]),this.usedBuffers.has(n)||this.usedBuffers.set(n,[]),this.numBytesUsed+=e,this.numUsedBuffers++,this.freeBuffers.get(n).length>0){this.numFreeBuffers--;let s=this.freeBuffers.get(n).shift();return this.usedBuffers.get(n).push(s),s}this.numBytesAllocated+=e;let r=this.device.createBuffer({size:e,usage:t,mappedAtCreation:a});return this.usedBuffers.get(n).push(r),r}releaseBuffer(e,t,a){if(this.freeBuffers.size===0)return;let n=Bx(t,a);this.freeBuffers.has(n)||this.freeBuffers.set(n,[]),this.freeBuffers.get(n).push(e),this.numFreeBuffers++,this.numUsedBuffers--;let r=this.usedBuffers.get(n),s=r.indexOf(e);if(s<0)throw new Error(\"Cannot release a buffer that was never provided by this buffer manager\");r.splice(s,1),this.numBytesUsed-=t}releaseUploadBuffer(e,t,a){e.mapAsync(GPUMapMode.WRITE).then(()=>{this.releaseBuffer(e,t,a)},n=>{})}getNumUsedBuffers(){return this.numUsedBuffers}getNumFreeBuffers(){return this.numFreeBuffers}dispose(){this.freeBuffers.forEach((e,t)=>{e.forEach(a=>{a.destroy()})}),this.usedBuffers.forEach((e,t)=>{e.forEach(a=>{a.destroy()})}),this.freeBuffers=new Map,this.usedBuffers=new Map,this.numUsedBuffers=0,this.numFreeBuffers=0,this.numBytesUsed=0,this.numBytesAllocated=0}};function Bx(e,t){return`${e}_${t}`}var Pne=class{constructor(e){this.device=e,this.numUsedTextures=0,this.numFreeTextures=0,this.freeTextures=new Map,this.usedTextures=new Map,this.numBytesUsed=0,this.numBytesAllocated=0}acquireTexture(e,t,a,n){let r=Vx(a),s=e*t*r,i=Wx(e,t,a,n);if(this.freeTextures.has(i)||this.freeTextures.set(i,[]),this.usedTextures.has(i)||this.usedTextures.set(i,[]),this.numBytesUsed+=s,this.numUsedTextures++,this.freeTextures.get(i).length>0){this.numFreeTextures--;let l=this.freeTextures.get(i).shift();return this.usedTextures.get(i).push(l),l}this.numBytesAllocated+=s;let o=this.device.createTexture({size:[e,t],format:a,usage:n});return this.usedTextures.get(i).push(o),o}releaseTexture(e,t,a,n,r){if(this.freeTextures.size===0)return;let s=Wx(t,a,n,r);this.freeTextures.has(s)||this.freeTextures.set(s,[]),this.freeTextures.get(s).push(e),this.numFreeTextures++,this.numUsedTextures--;let i=this.usedTextures.get(s),o=i.indexOf(e);if(o<0)throw new Error(\"Cannot release a texture that was never provided by this texture manager\");i.splice(o,1);let l=Vx(n),u=t*a*l;this.numBytesUsed-=u}getNumUsedTextures(){return this.numUsedTextures}getNumFreeTextures(){return this.numFreeTextures}dispose(){this.freeTextures.forEach((e,t)=>{e.forEach(a=>{a.destroy()})}),this.usedTextures.forEach((e,t)=>{e.forEach(a=>{a.destroy()})}),this.freeTextures=new Map,this.usedTextures=new Map,this.numUsedTextures=0,this.numFreeTextures=0,this.numBytesUsed=0,this.numBytesAllocated=0}};function Wx(e,t,a,n){return`${e}_${t}_${a}_${n}`}function Vx(e){if(e===\"rgba8unorm\")return 16;throw new Error(`${e} is not supported!`)}function Fne(e,t){if(Math.max(...e)>3)throw new Error(\"Cannot symbolically compute strides for rank > 4 tensor.\");let a=e.length,n=e.map(s=>`${t}[${s}]`),r=new Array(a-1);r[a-2]=n[a-1];for(let s=a-3;s>=0;--s)r[s]=`(${r[s+1]} * ${n[s+1]})`;return r}var One=(e,t,a,n)=>{let r={dtype:n.dtype,shape:n.shape},s=zne(a,r,t),i=e.createShaderModule({code:s,label:t.constructor.name});return e.createComputePipeline({compute:{module:i,entryPoint:\"_start\"},label:t.constructor.name,layout:\"auto\"})};function ra(e){if(e<=1)return\"i32\";if(e===2)return\"vec2<i32>\";if(e===3)return\"vec3<i32>\";if(e===4)return\"vec4<i32>\";if(e===5)return\"vec5\";if(e===6)return\"vec6\";throw Error(`GPU for rank ${e} is not yet supported`)}function yr(e){if(e===0)return\"x\";if(e===1)return\"y\";if(e===2)return\"z\";if(e===3)return\"w\";if(e===4)return\"u\";if(e===5)return\"v\";throw Error(`Index ${e} is not yet supported`)}function Ce(...e){let t;switch(e.length){case 0:t=`\n        fn main()\n      `;break;case 1:t=`\n        fn main(${e[0]} : i32)\n      `;break;default:throw Error(\"Unreachable\")}return t}function Ux(e){let t;return t=`\n     ${Dne()}\n      fn _start(@builtin(local_invocation_id) LocalId : vec3<u32>,\n                @builtin(global_invocation_id) GlobalId : vec3<u32>,\n                @builtin(local_invocation_index) LocalIndex: u32,\n                @builtin(workgroup_id) WorkgroupId : vec3<u32>,\n                @builtin(num_workgroups) NumWorkgroups : vec3<u32>) {\n        localId = LocalId;\n        localIndex = LocalIndex;\n        globalId = GlobalId;\n        numWorkgroups = NumWorkgroups;\n        workgroupId = WorkgroupId;\n        ${e?\"main(getGlobalIndex());\":\"main();\"};\n      }\n    `,t}function Dne(){return`\n  @compute @workgroup_size(workgroupSizeX, workgroupSizeY, workgroupSizeZ)\n`}function zne(e,t,a){let n=[],r=a.workgroupSize[0]*a.workgroupSize[1]*a.workgroupSize[2];if(n.push(`\n      const workgroupSizeX = ${a.workgroupSize[0]}u;\n      const workgroupSizeY = ${a.workgroupSize[1]}u;\n      const workgroupSizeZ = ${a.workgroupSize[2]}u;\n\n      var<private> localId: vec3<u32>;\n      var<private> localIndex: u32;\n      var<private> globalId: vec3<u32>;\n      var<private> numWorkgroups: vec3<u32>;\n      var<private> workgroupId: vec3<u32>;\n\n      // Only used when the y/z dimension of workgroup size is 1.\n      fn getGlobalIndex() -> i32 {\n        ${T8(a)?\"  return i32(globalId.x);\":`  return i32((workgroupId.z * numWorkgroups.x * numWorkgroups.y +\n                workgroupId.y * numWorkgroups.x + workgroupId.x) * ${r} +\n                localIndex);\n        `}\n      }\n    `),a.isFromPixels){n.push(`\n        struct Uniform {\n          size            : i32,\n          numChannels     : i32,\n          outShapeStrides : vec2<i32>,\n        };\n\n        @group(0) @binding(0) var<storage, read_write> result: array<${ad(t.dtype,a.isVec4)}>;\n        @group(0) @binding(2) var<uniform> uniforms: Uniform;\n      `);let h=jx(a);return[Gx,n.join(`\n`),Hx(t.shape),a.getUserCode(),Ux(h)].join(`\n`)}let s=\"struct Uniforms { NAN : f32, INFINITY : f32, \";a.variableNames.forEach((h,f)=>{let m=ra(e[f].shape.length);s+=`${h.charAt(0).toLowerCase()+h.slice(1)}Shape : ${m}, `});let i=ra(t.shape.length);s+=`outShape : ${i}, `;let o=t.shape.length-1,l=ra(o);s+=`\n         outShapeStrides: ${l}, `,a.size&&(s+=\"size : i32, \"),a.uniforms&&(s+=a.uniforms),s+=\"};\",s=qne(s),n.push(s),a.atomic?n.push(`\n      @group(0) @binding(0) var<storage, read_write> result: array<atomic<i32>>;\n    `):n.push(`\n      @group(0) @binding(0) var<storage, read_write> result: array<${ad(t.dtype,a.isVec4)}>;\n    `),a.variableNames.forEach((h,f)=>{n.push(`\n      @group(0) @binding(${1+f}) var<storage, read> ${h}: array<${a.variableTypes?a.variableTypes[f]:ad(e[f].dtype,a.isVec4)}>;\n        `)}),s!==\"\"&&n.push(`\n      @group(0) @binding(${1+a.variableNames.length}) var<uniform> uniforms: Uniforms;\n      `);let u=Gne(t.shape,a.dispatchLayout),p=[Gx+Bne,n.join(`\n`),Hx(t.shape),u,Hne(t.shape.length)];a.atomic||p.push(jne(t.shape,t.dtype,a.isVec4));let c=e.map((h,f)=>Une(h,t.shape,a.variableTypes?a.variableTypes[f]===\"vec4<f32>\":a.isVec4,a.dispatchLayout.x.length===t.shape.length)).join(`\n`);p.push(c),p.push(a.getUserCode());let d=jx(a);return p.push(Ux(d)),p.join(`\n`)}function Lne(e,t,a,n){let r=e.shaderKey;if(e.isFromPixels)return r;let s=a.map(p=>p.dtype).concat(n.dtype),i=a.map(p=>T.getBroadcastDims(p.shape,n.shape)),o=a.map(p=>v.arraysEqual(p.shape,n.shape)).join(\"_\"),l=i.map(p=>p.join(\"_\")).join(\";\"),u=T8(e)?\"flatDispatch\":\"\";return r+=\"_\"+(e.workgroupSize?e.workgroupSize.join(\",\"):\"\")+t.map(p=>p.length).join(\",\")+s.join(\",\")+e.variableNames.join(\",\")+l+o+u,r}var Gx=`\n  struct vec5 {x: i32, y: i32, z: i32, w: i32, u: i32};\n  struct vec6 {x: i32, y: i32, z: i32, w: i32, u: i32, v: i32};\n\n  // Checks whether coordinates lie within the bounds of the shape.\n  fn coordsInBounds2D(coord : vec2<i32>, shape : vec2<i32>) -> bool {\n    return all(coord >= vec2<i32>(0)) && all(coord < shape);\n  }\n  fn coordsInBounds3D(coord : vec3<i32>, shape : vec3<i32>) -> bool {\n    return all(coord >= vec3<i32>(0)) && all(coord < shape);\n  }\n  fn coordsInBounds4D(coord : vec4<i32>, shape : vec4<i32>) -> bool {\n    return all(coord >= vec4<i32>(0)) && all(coord < shape);\n  }\n\n  fn getIndexFromCoords1D(coord : i32, shape : i32) -> i32 {\n    return coord;\n  }\n  fn getIndexFromCoords2D(coords : vec2<i32>, shape : vec2<i32>) -> i32 {\n    return dot(coords, vec2<i32>(shape.y, 1));\n  }\n  fn getIndexFromCoords3D(coords : vec3<i32>, shape : vec3<i32>) -> i32 {\n    return dot(coords, vec3<i32>(shape.y * shape.z, shape.z, 1));\n  }\n  fn getIndexFromCoords4D(coords : vec4<i32>, shape : vec4<i32>) -> i32 {\n    return dot(coords, vec4<i32>(\n        shape.y * shape.z * shape.w, shape.z * shape.w, shape.w, 1));\n  }\n  fn getIndexFromCoords5D(coords : vec5, shape : vec5) -> i32 {\n    let shapeStrides: vec5 = vec5(shape.y * shape.z * shape.w * shape.u, shape.z * shape.w * shape.u, shape.w * shape.u, shape.u, 1);\n    return coords.x*shapeStrides.x + coords.y*shapeStrides.y + coords.z*shapeStrides.z + coords.w*shapeStrides.w + coords.u*shapeStrides.u;\n  }\n  fn getIndexFromCoords6D(coords : vec6, shape : vec6) -> i32 {\n    let shapeStrides: vec6 = vec6(shape.y * shape.z * shape.w * shape.u * shape.v, shape.z * shape.w * shape.u * shape.v, shape.w * shape.u * shape.v, shape.u * shape.v, shape.v, 1);\n    return coords.x*shapeStrides.x + coords.y*shapeStrides.y + coords.z*shapeStrides.z + coords.w*shapeStrides.w + coords.u*shapeStrides.u + coords.v*shapeStrides.v;\n  }\n\n  fn idiv(a: i32, b: i32, sign: f32) -> i32 {\n    var res: i32 = a / b;\n    let modulo: i32 = a % b;\n    if (sign < 0. && modulo != 0) {\n      res = res - 1;\n    }\n    return res;\n  }\n\n  // NaN defination in IEEE 754-1985 is :\n  //   - sign = either 0 or 1.\n  //   - biased exponent = all 1 bits.\n  //   - fraction = anything except all 0 bits (since all 0 bits represents infinity).\n  // https://en.wikipedia.org/wiki/IEEE_754-1985#Representation_of_non-numbers\n  fn isnan(val: f32) -> bool {\n    let floatToUint: u32 = bitcast<u32>(val);\n    return (floatToUint & 0x7fffffffu) > 0x7f800000u;\n  }\n  fn isnanVec4(val : vec4<f32>) -> vec4<bool> {\n    return vec4<bool>(isnan(val[0]), isnan(val[1]), isnan(val[2]), isnan(val[3]));\n  }\n`,Bne=`\n  fn isinf(val: f32) -> bool {\n    return abs(val) == uniforms.INFINITY;\n  }\n`;function Hx(e){let t=e.length;if(t<=1)return\"fn getCoordsFromIndex(index : i32) -> i32 { return index; }\";let a=v.computeStrides(e),n=ra(t),r=[];for(let i=0;i<t;i++)r.push(`d${i}`);if(a.length===1)return`    fn getCoordsFromIndex(index : i32) -> vec2<i32> {\n      let d0 = index / uniforms.outShapeStrides; let d1 = index - d0 * uniforms.outShapeStrides;\n      return vec2<i32>(d0, d1);\n    }`;let s;return s=\"var index2 = index;\"+a.map((i,o)=>{let l=`let ${r[o]} = index2 / uniforms.outShapeStrides.${yr(o)}`,u=o===a.length-1?`let ${r[o+1]} = index2 - ${r[o]} * uniforms.outShapeStrides.${yr(o)}`:`index2 = index2 - ${r[o]} * uniforms.outShapeStrides.${yr(o)}`;return`${l}; ${u};`}).join(\"\"),`\n    fn getCoordsFromIndex(index : i32) -> ${n} {\n      ${s}\n      return ${n}(${r.join(\",\")});\n    }\n  `}function Wne(e,t){let a=e.name,n=e.shape.length,r=ra(n),s=\"get\"+a.charAt(0).toUpperCase()+a.slice(1),i=[\"d0\",\"d1\",\"d2\",\"d3\",\"d4\",\"d5\"].slice(0,n),o=i.map(p=>`${p} : i32`).join(\", \");if(n<1)return t?`\n        fn ${s}() -> vec4<f32> {\n          return vec4<f32>(${a}[0]);\n        }\n      `:`\n      fn ${s}() ->f32 {\n        return f32(${a}[0]);\n      }\n    `;let l=`uniforms.${a.charAt(0).toLowerCase()+a.slice(1)}Shape`,u=`${n}D`;return n===0&&(u=\"1D\"),t?`\n      fn ${s}(${o}) -> vec4<f32> {\n        return vec4<f32>(${a}[getIndexFromCoords${u}(${r}(${i.join(\",\")}),\n          ${l}) / 4]);\n      }\n      `:`\n    fn ${s}(${o}) -> f32 {\n      return f32(${a}[getIndexFromCoords${u}(${r}(${i.join(\",\")}),\n        ${l})]);\n    }\n   `}function Vne(e,t,a,n){let r=e.name,s=r.charAt(0).toUpperCase()+r.slice(1),i=\"get\"+s+\"ByOutput\",o=e.shape.length,l=t.length,u=ra(l);if(v.arraysEqual(e.shape,t)&&n)return a?`\n      fn ${i}Index(globalIndex : i32) -> vec4<f32> {\n        return vec4<f32>(${r}[globalIndex]);\n      }\n\n      fn ${i}Coords(coords : ${u}) -> vec4<f32> {\n        return vec4<f32>(${r}[${l>1?\"getOutputIndexFromCoords(coords)\":\"coords\"} / 4]);\n      }\n      `:`\n    fn ${i}Index(globalIndex : i32) -> f32 {\n      return f32(${r}[globalIndex]);\n    }\n\n    fn ${i}Coords(coords : ${u}) -> f32 {\n      return f32(${r}[${l>1?\"getOutputIndexFromCoords(coords)\":\"coords\"}]);\n    }\n    `;let p=T.getBroadcastDims(e.shape,t),c=l-o,d=\"\";if(o===0)return a?`\n    fn ${i}Index(globalIndex : i32) -> vec4<f32> {\n      return get${s}();\n    }\n\n    fn ${i}Coords(coords : ${u}) -> vec4<f32> {\n      return get${s}();\n    }\n  `:`\n    fn ${i}Index(globalIndex : i32) -> f32{\n      return get${s}();\n    }\n\n    fn ${i}Coords(coords : ${u}) -> f32{\n      return get${s}();\n    }\n  `;l<2&&p.length>=1?d=\"coords = 0;\":d=p.map(g=>`coords.${yr(g+c)} = 0;`).join(`\n`);let h=\"\";if(l<2&&o>0)h=\"coords\";else if(l>1){let g=ra(o),x=e.shape.map((A,y)=>`coords.${yr(y+c)}`).join(\", \");h=`${g}(${x})`}else h=\"coords\";let f=`uniforms.${r.charAt(0).toLowerCase()+r.slice(1)}Shape`,m=`${o}D`;return a?`\n    fn ${i}Index(globalIndex : i32) -> vec4<f32> {\n      var coords = getCoordsFromIndex(globalIndex);\n      ${d}\n      return ${r}[getIndexFromCoords${m}(${h}, ${f}) / 4];\n    }\n\n    fn ${i}Coords(coordsIn : ${u}) -> vec4<f32> {\n      var coords = coordsIn;\n      ${d}\n      return ${r}[getIndexFromCoords${m}(${h}, ${f}) / 4];\n    }\n  `:`\n  fn ${i}Index(globalIndex : i32) -> f32 {\n    var coords = getCoordsFromIndex(globalIndex);\n    ${d}\n    return f32(${r}[getIndexFromCoords${m}(${h}, ${f})]);\n  }\n\n  fn ${i}Coords(coordsIn : ${u}) -> f32 {\n    var coords = coordsIn;\n    ${d}\n    return f32(${r}[getIndexFromCoords${m}(${h}, ${f})]);\n  }\n`}function Une(e,t,a,n){let r=Wne(e,a);return e.shape.length<=t.length&&(r+=Vne(e,t,a,n)),r}function Gne(e,t){let{x:a,y:n=[],z:r=[]}=t,s=e.length,i=a.length+n.length+r.length;if(i!==s)return\"\";if(a.length===s)return`fn getOutputCoords() -> ${ra(s)}{\n    let globalIndex = getGlobalIndex();\n    return getCoordsFromIndex(globalIndex);\n  }\n  `;let o=\"\",l=[a,n,r];for(let d=0;d<l.length;d++){let h=l[d];if(h.length!==0)if(h.length===1)o+=`let d${h[0]} = i32(globalId[${d}]);`;else{let f=Fne(h,\"uniforms.outShape\");o+=`var index${d} = i32(globalId[${d}]);`;for(let m=0;m<f.length;m++)o+=`let d${h[m]} = index${d} / ${f[m]};`,m===f.length-1?o+=`let d${h[m+1]} = index${d} - d${h[m]} * ${f[m]};`:o+=`index${d} = index${d} - d${h[m]} * ${f[m]};`}}let u=[];for(let d=0;d<i;d++)u.push(`d${d}`);let p=ra(i),c=`fn getOutputCoords() -> ${p} {\n  ${o}\n`;return u.length===0?c+=`return ${p}(0); }`:c+=`return ${p}(${u.join(\",\")}); }`,c}function Hne(e){let t=\"\";switch(e){case 0:case 1:t+=`\n        fn getOutputIndexFromCoords(coords : i32) -> i32 {\n          return coords;\n        }\n        `;break;case 2:t+=`\n        fn getOutputIndexFromCoords(coords : vec2<i32>) -> i32 {\n          return dot(coords, vec2<i32>(uniforms.outShapeStrides, 1));\n        }\n        `;break;case 3:t+=`\n        fn getOutputIndexFromCoords(coords : vec3<i32>) -> i32 {\n          return dot(coords, vec3<i32>(uniforms.outShapeStrides.x, uniforms.outShapeStrides.y, 1));\n        }\n        `;break;case 4:t+=`\n        fn getOutputIndexFromCoords(coords : vec4<i32>) -> i32 {\n          return dot(coords, vec4<i32>(\n            uniforms.outShapeStrides.x, uniforms.outShapeStrides.y, uniforms.outShapeStrides.z, 1));\n        }\n        `;break;case 5:t+=`\n        fn getOutputIndexFromCoords(coords : vec5) -> i32 {\n          return coords.x * uniforms.outShapeStrides.x +\n              coords.y * uniforms.outShapeStrides.y +\n              coords.z * uniforms.outShapeStrides.z +\n              coords.w * uniforms.outShapeStrides.w +\n              coords.u;\n        }\n        `;break;case 6:t+=`\n        fn getOutputIndexFromCoords(coords : vec6) -> i32 {\n          return coords.x * uniforms.outShapeStrides.x +\n              coords.y * uniforms.outShapeStrides.y +\n              coords.z * uniforms.outShapeStrides.z +\n              coords.w * uniforms.outShapeStrides.w +\n              coords.u * uniforms.outShapeStrides.u +\n              coords.v;\n        }\n        `;break;default:v.assert(!1,()=>`Unsupported ${e}D shape`);break}return t}function T8(e){return e.dispatch[1]===1&&e.dispatch[2]===1}function ad(e,t){return e===\"float32\"?t?\"vec4<f32>\":\"f32\":e===\"int32\"||e===\"bool\"?t?\"vec4<i32>\":\"i32\":e}function jne(e,t,a){let n=e.length,r=ad(t,a),s;if(a?s=`fn setOutputAtIndex(flatIndex : i32, value : vec4<f32>) {\n      result[flatIndex] = ${r}(value);\n    }\n    fn setOutputAtIndexI32(flatIndex : i32, value : vec4<i32>) {\n      result[flatIndex] = ${r}(value);\n    }`:s=`fn setOutputAtIndex(flatIndex : i32, value : f32) {\n      result[flatIndex] = ${r}(value);\n    }\n    fn setOutputAtIndexI32(flatIndex : i32, value : i32) {\n      result[flatIndex] = ${r}(value);\n    }`,n>=2){let i=[\"d0\",\"d1\",\"d2\",\"d3\",\"d4\",\"d5\"].slice(0,n),o=ra(n);a?s+=`\n      fn setOutputAtCoords(${i.map(l=>`${l} : i32`).join(\", \")}, value : vec4<f32>) {\n        let flatIndex = getOutputIndexFromCoords(${o}(${i.join(\", \")}));\n        setOutputAtIndex(flatIndex / 4, value);\n      }\n      fn setOutputAtCoordsI32(${i.map(l=>`${l} : i32`).join(\", \")}, value : vec4<i32>) {\n        let flatIndex = getOutputIndexFromCoords(${o}(${i.join(\", \")}));\n        setOutputAtIndexI32(flatIndex / 4, value);\n      }\n    `:s+=`\n      fn setOutputAtCoords(${i.map(l=>`${l} : i32`).join(\", \")}, value : f32) {\n        let flatIndex = getOutputIndexFromCoords(${o}(${i.join(\", \")}));\n        setOutputAtIndex(flatIndex, value);\n      }\n      fn setOutputAtCoordsI32(${i.map(l=>`${l} : i32`).join(\", \")}, value : i32) {\n        let flatIndex = getOutputIndexFromCoords(${o}(${i.join(\", \")}));\n        setOutputAtIndexI32(flatIndex, value);\n      }\n    `}return s}function qne(e){let t=/(\\w+)\\s*:\\s*vec(5|6)/g;e=e.replace(t,n=>\"@align(16) \"+n);let a=/vec(5|6)\\s*,\\s*(\\w+)/g;return e=e.replace(a,(n,r,s)=>`vec${r}, @align(16) ${s}`),e}function jx(e){return!(e.dispatchLayout.hasOwnProperty(\"y\")&&e.dispatchLayout.y.length!==0||e.dispatchLayout.hasOwnProperty(\"z\")&&e.dispatchLayout.z.length!==0)}var C8={};Xe(C8,{ArrayBufferToTypedArray:()=>R8,GPUBytesPerElement:()=>E8,MatMulProgramType:()=>Pn,computeDispatch:()=>Ne,computeWorkPerThreadForConv2d:()=>O3,computeWorkgroupInfoForMatMul:()=>N8,computeWorkgroupSizeForConv2d:()=>F3,flatDispatchLayout:()=>Ve,isWebGPUSupported:()=>D3,tilesFitEvenlyIntoShape:()=>Xne});var Ds=e=>{let t=1;for(let a=0;a<e.length;a++)t*=e[a];return t};function Xne(e,t){if(e.length!==t.length)throw new Error(`Cannot compute whether rank ${e.length} tiles fit evenly into rank ${t.length} shape - ranks must match.`);return t.every((a,n)=>a%e[n]===0)}function Ne(e,t,a=[1,1,1],n=[1,1,1]){let[r,s,i]=[Math.ceil(Ds(e.x.map(o=>t[o]))/(a[0]*n[0])),e.y?Math.ceil(Ds(e.y.map(o=>t[o]))/(a[1]*n[1])):1,e.z?Math.ceil(Ds(e.z.map(o=>t[o]))/(a[2]*n[2])):1];return[r,s,i]}function N8(e,t,a,n=!1){let r=[8,8,1],s=[4,4,1];return n||(e<=8&&(s[1]=1),t<=16&&a<=16&&(r[0]=4)),{workgroupSize:r,elementsPerThread:s}}function F3(e,t,a=!1){if(a)return[8,8,1];let n=Ds(e.x.map(s=>t[s])),r=Ds(e.y.map(s=>t[s]));return n<=4?[4,16,1]:r<=4?[16,4,1]:[16,16,1]}function O3(e,t,a=!1){if(a)return[4,4,1];let n=Ds(e.x.map(s=>t[s])),r=Ds(e.y.map(s=>t[s]));return n<=4?[1,2,1]:r<=4?[2,1,1]:[2,2,1]}function Ve(e){return{x:e.map((t,a)=>a)}}function E8(e){if(e===\"float32\"||e===\"int32\"||e===\"bool\"||e===\"string\")return 4;if(e===\"complex64\")return 8;throw new Error(`Unknown dtype ${e}`)}function R8(e,t){if(t===\"float32\")return new Float32Array(e);if(t===\"int32\")return new Int32Array(e);if(t===\"bool\"||t===\"string\")return Uint8Array.from(new Int32Array(e));throw new Error(`Unknown dtype ${t}`)}function D3(){return(typeof window!=\"undefined\"||typeof WorkerGlobalScope!=\"undefined\")&&!!navigator.gpu}var Pn;(function(e){e[e.MatMulReduceProgram=0]=\"MatMulReduceProgram\",e[e.MatMulSplitKProgram=1]=\"MatMulSplitKProgram\",e[e.MatMulSmallOutputSizeProgram=2]=\"MatMulSmallOutputSizeProgram\",e[e.MatMulPackedProgram=3]=\"MatMulPackedProgram\",e[e.MatMulMax=4]=\"MatMulMax\"})(Pn||(Pn={}));var Kne=W().getNumber(\"WEBGPU_CPU_HANDOFF_SIZE_THRESHOLD\"),Zne=(e,t)=>{let a=e.limits.maxComputeWorkgroupsPerDimension,n=t.dispatchLayout,r=t.dispatch;if(r.every(i=>i<=a))return r;v.assert(r[0]>a&&n.y===void 0&&n.z===void 0,()=>\"Dispatch size exceeds WebGPU limits in Y or Z dimension.\");let s=Math.ceil(Math.sqrt(r[0]));return s>a?(s=Math.ceil(Math.cbrt(r[0])),v.assert(s<=a,()=>\"Total dispatch size exceeds WebGPU maximum.\"),[s,s,s]):[s,s,1]},Vh=class extends bl{constructor(e,t){if(super(),this.commandQueueOwnedIds=new WeakSet,this.dispatchNumberInEncoder=0,this.disposed=!1,this.downloadWaitMs=0,this.tensorDataPendingDisposal=[],this.stagingPendingDisposal=[],this.uniformPendingDisposal=[],this.uploadWaitMs=0,!D3())throw new Error(\"WebGPU is not supported on this device\");this.pipelineCache={},this.device=e,this.queue=e.queue,this.currentCommandEncoder=null,this.currentComputePass=null,this.supportTimeQuery=e.features.has(\"timestamp-query-inside-passes\"),this.adapterInfo=new $ne(t),this.thresholdToIncreaseWorkgroups=this.adapterInfo.intelGPUGeneration>=12?16:8,this.bufferManager=new _ne(this.device),this.textureManager=new Pne(this.device),this.tensorMap=new vd(this,kt()),this.supportTimeQuery&&(this.querySet=this.device.createQuerySet({type:\"timestamp\",count:2})),W().getBool(\"WEBGPU_USE_PROFILE_TOOL\")&&(this.dummyCanvas=document.createElement(\"canvas\"),this.dummyCanvas.width=1,this.dummyCanvas.height=1,this.dummyContext=this.dummyCanvas.getContext(\"webgpu\"),this.dummyContext.configure({device:e,format:\"bgra8unorm\"}),document.body.appendChild(this.dummyCanvas))}nextDataId(){return Vh.nextDataId++}floatPrecision(){return 32}defaultGpuBufferUsage(){return GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST}disposeData(e,t=!1){if(this.tensorDataPendingDisposal.indexOf(e)>=0)return!1;if(!this.tensorMap.has(e))return!0;let a=this.tensorMap.get(e);if(this.decRef(e),!t&&a.refCount>0)return!1;if(this.commandQueueOwnedIds.has(e))return this.tensorDataPendingDisposal.push(e),!1;let{complexTensorInfos:n}=this.tensorMap.get(e);return n!=null&&(this.disposeData(n.real.dataId,t),this.disposeData(n.imag.dataId,t)),this.releaseResource(e),this.tensorMap.delete(e),!0}memory(){return{numBytesInGPU:this.bufferManager.numBytesUsed,numBytesAllocatedInGPU:this.bufferManager.numBytesAllocated,unreliable:!1}}releaseResource(e){let t=this.tensorMap.get(e);if(!(!t||!t.resourceInfo)){if(\"texture\"in t.resourceInfo){let a=t.resourceInfo;a.texture instanceof GPUTexture&&this.textureManager.releaseTexture(a.texture,a.width,a.height,a.format,a.usage),a.texture=null}else{let a=t.resourceInfo;this.bufferManager.releaseBuffer(a.buffer,a.size,a.usage),a.buffer=null}t.resourceInfo=null}}refCount(e){return this.tensorMap.has(e)?this.tensorMap.get(e).refCount:0}incRef(e){let t=this.tensorMap.get(e);t.refCount++}decRef(e){if(this.tensorMap.has(e)){let t=this.tensorMap.get(e);t.refCount--}}write(e,t,a){if(a===\"complex64\"&&e!=null)throw new Error(\"Cannot write to a complex64 dtype. Please use tf.complex(real, imag).\");let n={id:this.nextDataId()};return this.tensorMap.set(n,{dtype:a,shape:t,values:e,refCount:1}),n}move(e,t,a,n,r){if(n===\"complex64\")throw new Error(\"Cannot write to a complex64 dtype. Please use tf.complex(real, imag).\");this.tensorMap.set(e,{dtype:n,shape:a,values:t,refCount:r})}submitQueue(){this.ensureComputePassEnded(),this.queue.submit([this.currentCommandEncoder.finish()]),this.currentCommandEncoder=null,this.dispatchNumberInEncoder=0,this.commandQueueOwnedIds=new WeakSet,this.tensorDataPendingDisposal.forEach(e=>{this.releaseResource(e),this.tensorMap.delete(e)}),this.uniformPendingDisposal.forEach(e=>this.bufferManager.releaseBuffer(e.buffer,e.size,e.usage)),this.stagingPendingDisposal.forEach(e=>this.bufferManager.releaseUploadBuffer(e.buffer,e.size,e.usage)),this.tensorDataPendingDisposal=[],this.uniformPendingDisposal=[],this.stagingPendingDisposal=[]}ensureCommandEncoderReady(){this.currentCommandEncoder||(this.currentCommandEncoder=this.device.createCommandEncoder())}ensureComputePassEnded(){this.currentComputePass&&(this.currentComputePass.end(),this.currentComputePass=null)}getComputePass(){return this.currentComputePass||(this.currentComputePass=this.currentCommandEncoder.beginComputePass()),this.currentComputePass}async getBufferData(e,t){let a=this.bufferManager.acquireBuffer(t,GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ);this.ensureCommandEncoderReady(),this.ensureComputePassEnded(),this.currentCommandEncoder.copyBufferToBuffer(e,0,a,0,t),this.submitQueue(),await a.mapAsync(GPUMapMode.READ);let n=a.getMappedRange().slice(0);return a.unmap(),a!=null&&this.bufferManager.releaseBuffer(a,t,GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ),W().getBool(\"WEBGPU_USE_PROFILE_TOOL\")&&(v.assert(this.dummyContext!==void 0,()=>\"Fail to get context for profiling tool\"),this.dummyContext.getCurrentTexture()),n}convertAndCacheOnCPU(e,t){let a=this.tensorMap.get(e);return this.releaseResource(e),a.values=t,a.values}readSync(e){let t=this.tensorMap.get(e),{values:a}=t;if(a==null)throw new Error(\"WebGPU readSync is only available for CPU-resident tensors.\");return a}async read(e){if(!this.tensorMap.has(e))throw new Error(`Tensor ${e} was not registered!`);let t=this.tensorMap.get(e),{values:a}=t;if(a!=null)return this.convertAndCacheOnCPU(e,a);let n;if(t.dtype===\"complex64\"){let r=await Promise.all([this.read(t.complexTensorInfos.real.dataId),this.read(t.complexTensorInfos.imag.dataId)]),s=r[0],i=r[1];n=T.mergeRealAndImagArrays(s,i)}else{let r=t.resourceInfo,s=await this.getBufferData(r.buffer,r.size);n=R8(s,t.dtype)}return this.convertAndCacheOnCPU(e,n),n}readToGPU(e){let t=this.tensorMap.get(e),{values:a,dtype:n,shape:r,resourceInfo:s}=t;if(n===\"complex64\")throw new Error(\"Does not support reading buffer for complex64 dtype.\");if(s==null)throw a!=null?new Error(\"Data is not on GPU but on CPU.\"):new Error(\"There is no data on GPU or CPU.\");let i=s.size,o=this.bufferManager.acquireBuffer(i,s.usage);this.ensureCommandEncoderReady(),this.ensureComputePassEnded(),this.currentCommandEncoder.copyBufferToBuffer(s.buffer,0,o,0,i),this.submitQueue();let l=this.makeTensorInfo(r,n),u=kt().makeTensorFromTensorInfo(l),p=this.tensorMap.get(l.dataId);return p.resourceInfo={size:i,usage:this.defaultGpuBufferUsage(),buffer:o},{tensorRef:u,buffer:o,bufSize:i}}bufferSync(e){let t=this.readSync(e.dataId);if(e.dtype===\"string\")try{let a=t.map(n=>v.decodeString(n));return Me(e.shape,e.dtype,a)}catch(a){throw new Error(\"Failed to decode encoded string bytes into utf-8\")}return Me(e.shape,e.dtype,t)}async time(e){this.supportTimeQuery||console.warn(\"This device doesn't support timestamp-query-inside-passes extension. Start Chrome browser with flag --disable-dawn-features=disallow_unsafe_apis then try again. Otherwise, zero will be shown for the kernel time when profiling mode is enabled. Using performance.now is not workable for webgpu since it doesn't support synchronous data read from GPU.\");let t=this.activeTimers,a=[],n=!1;this.programTimersStack==null?(this.programTimersStack=a,n=!0):this.activeTimers.push(a),this.activeTimers=a,e();let r=v.flatten(this.activeTimers.map(l=>l.query)).filter(l=>l!=null),s=v.flatten(this.activeTimers.map(l=>l.name)).filter(l=>l!=null);this.activeTimers=t,n&&(this.programTimersStack=null);let i={uploadWaitMs:this.uploadWaitMs,downloadWaitMs:this.downloadWaitMs,kernelMs:null,wallMs:null},o=await Promise.all(r);return i.kernelMs=v.sum(o),i.getExtraProfileInfo=()=>o.map((l,u)=>({name:s[u],ms:l})).map(l=>`${l.name}: ${l.ms}`).join(\", \"),this.uploadWaitMs=0,this.downloadWaitMs=0,i}makeTensorInfo(e,t,a){return t===\"string\"&&a!=null&&a.length>0&&v.isString(a[0])&&(a=a.map(n=>v.encodeString(n))),{dataId:this.write(a,e,t),shape:e,dtype:t}}tensorToBinding(e){if(!e)return null;let t=this.tensorMap.get(e.dataId);if(\"texture\"in t.resourceInfo){let n=t.resourceInfo;return n.texture instanceof GPUExternalTexture?n.texture:n.texture.createView()}let a=t.resourceInfo;return{offset:0,size:a.size,buffer:a.buffer}}async getQueryTime(e){return this.supportTimeQuery?this.getTimeFromQuerySet(e):0}uploadToGPU(e){let t=this.tensorMap.get(e);if(t.resourceInfo)return;let a=E8(t.dtype)*v.sizeFromShape(t.shape),n=this.bufferManager.acquireBuffer(a,this.defaultGpuBufferUsage());if(t.resourceInfo={size:a,usage:this.defaultGpuBufferUsage(),buffer:n},t.values){let r=this.bufferManager.acquireUploadBuffer(a,GPUBufferUsage.MAP_WRITE|GPUBufferUsage.COPY_SRC),s=r.getMappedRange();t.dtype===\"int32\"||t.dtype===\"bool\"?new Int32Array(s).set(t.values):new Float32Array(s).set(t.values),r.unmap(),this.ensureCommandEncoderReady(),this.ensureComputePassEnded(),this.currentCommandEncoder.copyBufferToBuffer(r,0,n,0,a);let i={size:a,usage:GPUBufferUsage.MAP_WRITE|GPUBufferUsage.COPY_SRC,buffer:r};this.stagingPendingDisposal.push(i)}}makeUniforms(e){let t=0,a=0,n=[];e.forEach(o=>{o.data.length===0&&(o.data=[1]);let l;switch(o.data.length){case 1:l=4;break;case 2:l=8;break;case 3:l=16;break;case 4:l=16;break;case 5:l=16;break;case 6:l=16;break;default:v.assert(!1,()=>`Unsupported ${o.data.length}D shape`)}(a===5||a===6)&&(l=16),t=Math.ceil(t/l)*l,a=o.data.length,n.push(t),t+=o.data.length*4});let r=new ArrayBuffer(t);e.forEach((o,l)=>{let u=n[l];o.type===\"int32\"?new Int32Array(r,u,o.data.length).set(o.data):o.type===\"uint32\"?new Uint32Array(r,u,o.data.length).set(o.data):new Float32Array(r,u,o.data.length).set(o.data)});let s=this.bufferManager.acquireBuffer(t,GPUBufferUsage.COPY_DST|GPUBufferUsage.UNIFORM);this.queue.writeBuffer(s,0,r,0,t);let i={size:t,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.UNIFORM,buffer:s};return this.uniformPendingDisposal.push(i),{offset:0,size:t,buffer:s}}runWebGPUProgram(e,t,a,n,r){if(r||(r=this.makeTensorInfo(e.outputShape,a)),v.sizeFromShape(r.shape)===0)return this.tensorMap.get(r.dataId).values=v.getTypedArrayFromDType(r.dtype,0),r;this.uploadToGPU(r.dataId),e.dispatch=Zne(this.device,e);let s=[],i=[];if(!e.isFromPixels){s.push({type:\"float32\",data:[NaN]},{type:\"float32\",data:[1/0]}),i=t.concat(r).map(g=>g.shape);let f=\"int32\";i.map(g=>{s.push({type:f,data:g})});let m=v.computeStrides(r.shape);if(s.push({type:f,data:m}),e.size){let g=v.sizeFromShape(e.outputShape);s.push({type:f,data:[e.isVec4?g/4:g]})}}let o=t.map((f,m)=>{if(f.dtype===\"complex64\")throw new Error(\"GPGPUProgram does not support complex64 input. For complex64 dtypes, please separate the program into real and imaginary parts.\");return this.uploadToGPU(f.dataId),{dtype:this.tensorMap.get(f.dataId).dtype,shape:f.shape,name:e.variableNames[m]}}),l=Lne(e,i,o,r),u;l in this.pipelineCache?u=this.pipelineCache[l]:(u=One(this.device,e,o,r),this.pipelineCache[l]=u),n&&(s=[...s,...n]);let p=[this.tensorToBinding(r),...t.map(f=>this.tensorToBinding(f)),this.makeUniforms(s)],c=this.device.createBindGroup({layout:u.getBindGroupLayout(0),entries:p.map((f,m)=>({binding:m,resource:f}))});this.ensureCommandEncoderReady();let d=this.getComputePass(),h=this.activeTimers!=null;return h&&this.supportTimeQuery&&d.writeTimestamp(this.querySet,0),d.setPipeline(u),d.setBindGroup(0,c),d.dispatchWorkgroups(e.dispatch[0],e.dispatch[1],e.dispatch[2]),h&&this.supportTimeQuery&&d.writeTimestamp(this.querySet,1),this.dispatchNumberInEncoder++,t.forEach(f=>{this.commandQueueOwnedIds.add(f.dataId)}),this.commandQueueOwnedIds.add(r.dataId),W().get(\"WEBGPU_DEFERRED_SUBMIT_BATCH_SIZE\")<=this.dispatchNumberInEncoder&&this.submitQueue(),h&&this.activeTimers.push({name:e.constructor.name,query:this.getQueryTime(this.querySet)}),r}async getTimeFromQuerySet(e){let t=this.bufferManager.acquireBuffer(16,GPUBufferUsage.COPY_SRC|GPUBufferUsage.QUERY_RESOLVE),a=this.bufferManager.acquireBuffer(16,GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST);this.ensureCommandEncoderReady(),this.ensureComputePassEnded(),this.currentCommandEncoder.resolveQuerySet(e,0,2,t,0),this.currentCommandEncoder.copyBufferToBuffer(t,0,a,0,16),this.submitQueue(),await a.mapAsync(GPUMapMode.READ);let n=new BigUint64Array(a.getMappedRange()),r=Number(n[1]-n[0]);return a.unmap(),this.bufferManager.releaseBuffer(a,16,GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST),this.bufferManager.releaseBuffer(t,16,GPUBufferUsage.COPY_SRC|GPUBufferUsage.QUERY_RESOLVE),r/1e6}shouldExecuteOnCPU(e,t=Kne){return W().getBool(\"WEBGPU_CPU_FORWARD\")&&e.every(a=>this.tensorMap.get(a.dataId).resourceInfo==null&&v.sizeFromShape(a.shape)<t)}numDataIds(){return this.tensorMap.numDataIds()-this.tensorDataPendingDisposal.length}dispose(){this.disposed||(this.bufferManager.dispose(),this.textureManager.dispose(),this.disposed=!0)}};Vh.nextDataId=0;D3()&&go(\"webgpu\",async()=>{W().set(\"CHECK_COMPUTATION_FOR_ERRORS\",!1);let e={powerPreference:W().get(\"WEBGPU_USE_LOW_POWER_GPU\")?\"low-power\":\"high-performance\"},t=await navigator.gpu.requestAdapter(e),a={};t.features.has(\"timestamp-query-inside-passes\")&&(a.requiredFeatures=[\"timestamp-query-inside-passes\"]);let n=t.limits;a.requiredLimits={maxComputeWorkgroupStorageSize:n.maxComputeWorkgroupStorageSize,maxComputeWorkgroupsPerDimension:n.maxComputeWorkgroupsPerDimension,maxStorageBufferBindingSize:n.maxStorageBufferBindingSize};let r=await t.requestDevice(a),s=await t.requestAdapterInfo();return new Vh(r,s)},3);var De;(function(e){e[e.ADD=0]=\"ADD\",e[e.ATAN2=1]=\"ATAN2\",e[e.COMPLEX_MULTIPLY_IMAG=2]=\"COMPLEX_MULTIPLY_IMAG\",e[e.COMPLEX_MULTIPLY_REAL=3]=\"COMPLEX_MULTIPLY_REAL\",e[e.DIV=4]=\"DIV\",e[e.EQUAL=5]=\"EQUAL\",e[e.GREATER=6]=\"GREATER\",e[e.GREATER_EQUAL=7]=\"GREATER_EQUAL\",e[e.INT_DIV=8]=\"INT_DIV\",e[e.LESS=9]=\"LESS\",e[e.LESS_EQUAL=10]=\"LESS_EQUAL\",e[e.LOGICAL_AND=11]=\"LOGICAL_AND\",e[e.MAX=12]=\"MAX\",e[e.MIN=13]=\"MIN\",e[e.MOD=14]=\"MOD\",e[e.MUL=15]=\"MUL\",e[e.NOT_EQUAL=16]=\"NOT_EQUAL\",e[e.POW=17]=\"POW\",e[e.PRELU=18]=\"PRELU\",e[e.SQUARED_DIFFERENCE=19]=\"SQUARED_DIFFERENCE\",e[e.SUB=20]=\"SUB\"})(De||(De={}));var M8=`\n  if (isnan(a)) { return a; }\n  if (isnan(b)) { return b; }\n  `,$8=`\n  if (isNaN.r) {\n    resultTemp.r = valueForNaN;\n  }\n  if (isNaN.g) {\n    resultTemp.g = valueForNaN;\n  }\n  if (isNaN.b) {\n    resultTemp.b = valueForNaN;\n  }\n  if (isNaN.a) {\n    resultTemp.a = valueForNaN;\n  }\n  `,z3=`\n  let isNaN = isnanVec4(a) | isnanVec4(b);\n  ${$8}\n  `,Yne=\"return a + b;\",Jne=\"return areal * breal - aimag * bimag;\",Qne=\"return areal * bimag + aimag * breal;\",ere=\"return a / b;\",tre=\"return f32(a == b);\",are=\"return vec4<f32>(a == b);\",nre=\"return f32(a > b);\",rre=\"return vec4<f32>(a > b);\",sre=\"return f32(a >= b);\",ire=\"return vec4<f32>(a >= b);\",ore=`\n  let s = sign(a) * sign(b);\n  let ia = i32(round(a));\n  let ib = i32(round(b));\n  return f32(idiv(ia, ib, s));\n`,lre=`\n  let ia = vec4<i32>(round(a));\n  let ib = vec4<i32>(round(b));\n  let cond = ib != vec4<i32>(0);\n  var resultTemp = vec4<i32>(0);\n  let s = sign(a) * sign(b);\n\n  // Windows (D3D) wants guaranteed non-zero int division at compile-time.\n  if (cond[0]) {\n    resultTemp[0] = idiv(ia[0], ib[0], s[0]);\n  }\n  if (cond[1]) {\n    resultTemp[1] = idiv(ia[1], ib[1], s[1]);\n  }\n  if (cond[2]) {\n    resultTemp[2] = idiv(ia[2], ib[2], s[2]);\n  }\n  if (cond[3]) {\n    resultTemp[3] = idiv(ia[3], ib[3], s[3]);\n  }\n  return vec4<f32>(resultTemp);\n`,ure=\"return f32(a < b);\",dre=\"return vec4<f32>(a < b);\",pre=\"return f32(a <= b);\",cre=\"return vec4<f32>(a <= b);\",hre=\"return f32(f32(a) >= 1.0 && f32(b) >= 1.0);\",fre=`return (vec4<f32>(a >= vec4<f32>(1.0)) *\n  vec4<f32>(b >= vec4<f32>(1.0)));`,mre=`\n  ${M8}\n  if (b == 0.) {\n    return uniforms.NAN;\n  }\n  var resultTemp = a % b;\n  if ((a < 0. && b < 0.) || (a >= 0. && b > 0.)) {\n    return resultTemp;\n  } else {\n    return (resultTemp + b) % b;\n  }\n`,gre=`\n  let valueForNaN = uniforms.NAN;\n  var resultTemp = vec4<f32>(a % b);\n  ${z3}\n\n  if (b[0] == 0.) {\n    resultTemp[0] = uniforms.NAN;\n  }\n  if (b[1] == 0.) {\n    resultTemp[1] = uniforms.NAN;\n  }\n  if (b[2] == 0.) {\n    resultTemp[2] = uniforms.NAN;\n  }\n  if (b[3] == 0.) {\n    resultTemp[3] = uniforms.NAN;\n  }\n\n  if (!((a[0] < 0. && b[0] < 0.) || (a[0] >= 0. && b[0] > 0.))) {\n    resultTemp[0] = (resultTemp[0] + b[0]) % b[0];\n  }\n  if (!((a[1] < 0. && b[1] < 0.) || (a[1] >= 0. && b[1] > 0.))) {\n    resultTemp[1] = (resultTemp[1] + b[1]) % b[1];\n  }\n  if (!((a[2] < 0. && b[2] < 0.) || (a[2] >= 0. && b[2] > 0.))) {\n    resultTemp[2] = (resultTemp[2] + b[2]) % b[2];\n  }\n  if (!((a[3] < 0. && b[3] < 0.) || (a[3] >= 0. && b[3] > 0.))) {\n    resultTemp[3] = (resultTemp[3] + b[3]) % b[3];\n  }\n\n  return resultTemp;\n`,xre=\"return a * b;\",Are=`\n  if (isnan(a) || isnan(b)) {\n    return 1.0;\n  }\n  return f32(a != b);\n`,yre=`\n  var resultTemp = vec4<f32>(a != b);\n  let valueForNaN = 1.0;\n  ${z3}\n\n  return resultTemp;\n`,bre=`\n  if(a < 0.0 && floor(b) < b) {\n    return uniforms.NAN;\n  }\n  if (b == 0.0) {\n    return 1.0;\n  }\n  if (round(abs(b) % 2.0) != 1.0) {\n    return pow(abs(a), b);\n  }\n  return sign(a) * pow(abs(a), b);\n`,vre=`\n  let isModRound1Bool = vec4<i32>(round(abs(b) % vec4<f32>(2.0))) == vec4<i32>(1);\n  let isModRound1 = vec4<f32>(isModRound1Bool);\n  let multiplier = sign(a) * isModRound1 + (vec4<f32>(1.0) - isModRound1);\n  var resultTemp = multiplier * pow(abs(a), b);\n\n  // Ensure that a^0 = 1, including 0^0 = 1 as this correspond to TF and JS\n  let isExpZero = b == vec4<f32>(0.0);\n  if (isExpZero.r) {\n    resultTemp.r = 1.0;\n  }\n  if (isExpZero.g) {\n    resultTemp.g = 1.0;\n  }\n  if (isExpZero.b) {\n    resultTemp.b = 1.0;\n  }\n  if (isExpZero.a) {\n    resultTemp.a = 1.0;\n  }\n  let isNaN = (a < vec4<f32>(0.0)) & (floor(b) < b);\n  let valueForNaN = uniforms.NAN;\n  ${$8}\n  return resultTemp;\n`,wre=\"if (a < 0.0) { return b * a; }  return a;\",kre=`\n  let aLessThanZero = vec4<f32>(a < vec4<f32>(0.0));\n  return (aLessThanZero * (b * a)) + ((vec4<f32>(1.0) - aLessThanZero) * a);\n`,Ire=\"return (a - b) * (a - b);\",Sre=\"return a - b;\";function Bm(e,t,a=\"uniforms.NAN\"){let n=t?z3:M8;return t?`\n    let valueForNaN = ${a};\n    var resultTemp = vec4<f32>(${e}(a, b));\n    `+n+`\n    return resultTemp;\n  `:n+`\n    return ${e}(a, b);\n  `}function L3(e,t){switch(e){case De.ADD:return Yne;case De.ATAN2:return Bm(\"atan2\",t);case De.COMPLEX_MULTIPLY_IMAG:return Qne;case De.COMPLEX_MULTIPLY_REAL:return Jne;case De.DIV:return ere;case De.EQUAL:return t?are:tre;case De.GREATER:return t?rre:nre;case De.GREATER_EQUAL:return t?ire:sre;case De.INT_DIV:return t?lre:ore;case De.LESS:return t?dre:ure;case De.LESS_EQUAL:return t?cre:pre;case De.LOGICAL_AND:return t?fre:hre;case De.MAX:return Bm(\"max\",t);case De.MIN:return Bm(\"min\",t);case De.MOD:return t?gre:mre;case De.MUL:return xre;case De.NOT_EQUAL:return t?yre:Are;case De.POW:return t?vre:bre;case De.PRELU:return t?kre:wre;case De.SQUARED_DIFFERENCE:return Ire;case De.SUB:return Sre;default:throw new Error(`BinaryType ${e} is not implemented!`)}}var de;(function(e){e[e.ABS=0]=\"ABS\",e[e.ACOS=1]=\"ACOS\",e[e.ACOSH=2]=\"ACOSH\",e[e.ASIN=3]=\"ASIN\",e[e.ASINH=4]=\"ASINH\",e[e.ATAN=5]=\"ATAN\",e[e.ATANH=6]=\"ATANH\",e[e.CEIL=7]=\"CEIL\",e[e.COS=8]=\"COS\",e[e.COSH=9]=\"COSH\",e[e.ELU=10]=\"ELU\",e[e.ERF=11]=\"ERF\",e[e.EXP=12]=\"EXP\",e[e.EXPM1=13]=\"EXPM1\",e[e.FLOOR=14]=\"FLOOR\",e[e.IS_FINITE=15]=\"IS_FINITE\",e[e.IS_INF=16]=\"IS_INF\",e[e.IS_NAN=17]=\"IS_NAN\",e[e.LINEAR=18]=\"LINEAR\",e[e.LOG=19]=\"LOG\",e[e.LOG1P=20]=\"LOG1P\",e[e.LOGICAL_NOT=21]=\"LOGICAL_NOT\",e[e.NEG=22]=\"NEG\",e[e.RELU=23]=\"RELU\",e[e.RELU6=24]=\"RELU6\",e[e.LEAKYRELU=25]=\"LEAKYRELU\",e[e.RECIPROCAL=26]=\"RECIPROCAL\",e[e.RSQRT=27]=\"RSQRT\",e[e.SIN=28]=\"SIN\",e[e.SINH=29]=\"SINH\",e[e.SIGMOID=30]=\"SIGMOID\",e[e.SQRT=31]=\"SQRT\",e[e.SQUARE=32]=\"SQUARE\",e[e.TAN=33]=\"TAN\",e[e.TANH=34]=\"TANH\",e[e.TO_INT=35]=\"TO_INT\"})(de||(de={}));var Tre=\"return abs(a);\",Cre=`\n  if (abs(a) > 1.) {\n    return uniforms.NAN;\n  }\n  return acos(a);\n`,Nre=`\n  if (a < 1.) {\n    return uniforms.NAN;\n  }\n  return acosh(a);\n`,Ere=`\n  if (abs(a) > 1.) {\n    return uniforms.NAN;\n  }\n  return asin(a);\n`,Rre=\"return asinh(a);\",Mre=`\n  if (isnan(a)) {\n    return uniforms.NAN;\n  }\n  return atan(a);\n`,$re=`\n  if (abs(a) > 1.) {\n    return uniforms.NAN;\n  }\n  if (a == 1.) {\n    return uniforms.INFINITY;\n  }\n  if (a == -1.) {\n    return -uniforms.INFINITY;\n  }\n  return atanh(a);\n`,_re=\"return ceil(a);\",Pre=\"return cos(a);\",Fre=`\n  let e2x = exp(-a);\n  return (e2x + 1.0 / e2x) / 2.0;\n`,Ore=\"return exp(a) - 1.0;\",Dre=\"if (a >= 0.0) { return a; }  return (exp(a) - 1.0);\",zre=`\n  var resFloat = exp(a) - vec4<f32>(1.0);\n  if (a.r >= 0.0) {\n    resFloat.r = a.r;\n  }\n  if (a.g >= 0.0) {\n    resFloat.g = a.g;\n  }\n  if (a.b >= 0.0) {\n    resFloat.b = a.b;\n  }\n  if (a.a >= 0.0) {\n    resFloat.a = a.a;\n  }\n  return resFloat;\n`,Lre=`\n  // Error function is calculated approximately with elementary function.\n  // See \"Handbook of Mathematical Functions with Formulas,\n  // Graphs, and Mathematical Tables\", Abramowitz and Stegun.\n  let p = ${T.ERF_P};\n  let a1 = ${T.ERF_A1};\n  let a2 = ${T.ERF_A2};\n  let a3 = ${T.ERF_A3};\n  let a4 = ${T.ERF_A4};\n  let a5 = ${T.ERF_A5};\n\n  let sign = sign(a);\n  let absA = abs(a);\n  let t = 1.0 / (1.0 + p * absA);\n  return sign * (1.0 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-absA * absA));\n`,Bre=\"return exp(a);\",Wre=\"return floor(a);\",Vre=\"return f32(!isnan(a) && !isinf(a));\",Ure=\"return f32(isinf(a));\",Gre=\"return f32(isnan(a));\",Hre=\"return a;\",jre=`if (a < 0.0) { return uniforms.NAN; }\n  return log(a);`,qre=`\n  if (isnan(a)) { return a; }\n  return log(1.0 + a);\n`,Xre=\"return f32(!(a >= 1.0));\",Kre=\"return -a;\",Zre=\"if (a < 0.0) { return uniforms.alpha * a; } return a;\",Yre=`\n  let aLessThanZero = vec4<f32>(a < vec4<f32>(0.0));\n  return (aLessThanZero * (uniforms.alpha * a)) + ((vec4<f32>(1.0) - aLessThanZero) * a);\n`,Jre=\"return 1.0 / a;\",Qre=\"return select(a, 0.0, a < 0.0);\",ese=\"return clamp(a, 0.0, 6.0);\",tse=\"return clamp(a, vec4<f32>(0.0, 0.0, 0.0, 0.0), vec4<f32>(6.0, 6.0, 6.0, 6.0));\",ase=`\n  return select(a, vec4<f32>(0.0), a < vec4<f32>(0.0));\n`,nse=\"return inverseSqrt(a);\",rse=\"return 1.0 / (1.0 + exp(-1.0 * a));\",sse=\"return sin(a);\",ise=`\n  let e2x = exp(a);\n  return (e2x - 1.0 / e2x) / 2.0;\n`,ose=\"return sqrt(a);\",lse=\"return a * a;\",use=\"return tan(a);\",dse=`\n  let e2x = exp(-2.0 * abs(a));\n  return sign(a) * (1.0 - e2x) / (1.0 + e2x);\n`,pse=\"return f32(i32((a)));\";function Ms(e,t){switch(e){case de.ABS:return Tre;case de.ACOS:return Cre;case de.ACOSH:return Nre;case de.ASIN:return Ere;case de.ASINH:return Rre;case de.ATAN:return Mre;case de.ATANH:return $re;case de.COS:return Pre;case de.COSH:return Fre;case de.CEIL:return _re;case de.ELU:return t?zre:Dre;case de.ERF:return Lre;case de.EXP:return Bre;case de.EXPM1:return Ore;case de.FLOOR:return Wre;case de.IS_FINITE:return Vre;case de.IS_INF:return Ure;case de.IS_NAN:return Gre;case de.LINEAR:return Hre;case de.LOG:return jre;case de.LOG1P:return qre;case de.LOGICAL_NOT:return Xre;case de.NEG:return Kre;case de.LEAKYRELU:return t?Yre:Zre;case de.RECIPROCAL:return Jre;case de.RELU:return t?ase:Qre;case de.RELU6:return t?tse:ese;case de.RSQRT:return nse;case de.SIGMOID:return rse;case de.SIN:return sse;case de.SINH:return ise;case de.SQRT:return ose;case de.SQUARE:return lse;case de.TAN:return use;case de.TANH:return dse;case de.TO_INT:return pse;default:throw new Error(`BinaryType ${e} is not implemented!`)}}var Mt=e=>{switch(e){case 1:return\"f32\";case 2:return\"vec2<f32>\";case 3:return\"vec3<f32>\";case 4:return\"vec4<f32>\";default:throw new Error(`${e}-component is not supported.`)}};function Tr(e,t=!1,a=!1,n=3){if(e===null)return\"\";let r=\"\";if(e===\"linear\")r=Ms(de.LINEAR);else if(e===\"relu\")r=Ms(de.RELU,a);else if(e===\"elu\")r=Ms(de.ELU,a);else if(e===\"relu6\")r=Ms(de.RELU6,a);else if(e===\"prelu\")r=L3(De.PRELU,a);else if(e===\"sigmoid\")r=Ms(de.SIGMOID,a);else if(e===\"leakyrelu\")r=Ms(de.LEAKYRELU,a);else throw new Error(`Activation ${e} has not been implemented for the WebGPU backend.`);let s=Mt(a?4:1),i=\"\";return t?i=`\n      fn activation(a : ${s}, coords : vec${n}<i32>) -> ${s} {\n        let b = getPreluActivationWeightsByOutputCoords(coords);\n        ${r}\n      }`:i=`\n      fn activation(a : ${s}, coords : vec${n}<i32>) -> ${s} {\n        ${r}\n      }`,i}function vo(e,t){return`\n      ${e?\"value = value + getBiasByOutputCoords(coords);\":\"\"}\n      ${t?\"value = activation(value, coords);\":\"\"}\n      `}function _8(e,t,a,n,r=!1,s=!1,i=!1,o=1){v.assert(a&&o===1||!a,()=>`transposeA ${a} is not compatible with component size ${o}`);let l=`\n      let batch = ${e?\"0\":\"batchIn\"};\n      ${a?\"value = getA(batch, col, row);\":\"value = getA(batch, row, col);\"}\n\n    `,u=n?\"value = getB(batch, col, row);\":\"value = getB(batch, row, col);\";return`\n  fn mm_readA(batchIn: i32, row: i32, colIn: i32) -> ${Mt(o)} {\n    var value = ${Mt(o)}(0.0);\n    let col = colIn * ${o};\n    ${r&&i?l:`\n    ${a?\"if(row < uniforms.dimAOuter && col < uniforms.dimInner)\":\"if(row < uniforms.aShape[1] && col < uniforms.aShape[2])\"}\n    {\n      ${l}\n    }\n    `}\n    return value;\n  }\n\n  fn mm_readB(batchIn: i32, row: i32, colIn: i32) -> ${Mt(o)} {\n    let col = colIn * ${o};\n    let batch = ${t?\"0\":\"batchIn\"};\n    var value = ${Mt(o)}(0.0);\n    ${u}\n    return value;\n  }\n  `}function B3(e,t,a,n,r,s,i=!1,o=!1,l=!1,u=1){return`\n  ${_8(a,n,r,s,i,o,l,u)}\n  fn mm_write(batch: i32, row: i32, colIn: i32, valueIn: ${Mt(u)}) {\n    let col = colIn * ${u};\n    ${i&&o?\"\":\"if (row < uniforms.dimAOuter && col < uniforms.dimBOuter)\"}\n    {\n      var value = valueIn;\n      let coords = vec3<i32>(batch, row, col);\n      ${vo(e,t)}\n      setOutputAtCoords(coords[0], coords[1], coords[2], value);\n    }\n  }\n  `}var cse=e=>e?`\n        mm_Asub[inputRow][inputCol] = mm_readA(batch,\n          kStart + inputRow,\n          globalRowStart / innerElementSize + inputCol);\n        `:`\n        mm_Asub[inputRow][inputCol] = mm_readA(batch,\n          globalRow + innerRow,\n          kStart / innerElementSize + inputCol);\n        `,hse=(e,t)=>e?`\n        let ACached0 = mm_Asub[k * innerElementSize][localRow];\n        let ACached1 = mm_Asub[k * innerElementSize + 1][localRow];\n        let ACached2 = mm_Asub[k * innerElementSize + 2][localRow];\n        ${t===3?\"\":\"let ACached3 = mm_Asub[k * innerElementSize + 3][localRow];\"}\n        for (var i = 0; i < rowPerThread; i = i + 1) {\n          acc[i] = BCached0 * ACached0[i] + acc[i];\n          acc[i] = BCached1 * ACached1[i] + acc[i];\n          acc[i] = BCached2 * ACached2[i] + acc[i];\n          ${t===3?\"\":\"acc[i] = BCached3 * ACached3[i] + acc[i];\"}\n        }`:`\n        for (var i = 0; i < rowPerThread; i = i + 1) {\n          let ACached = mm_Asub[tileRow + i][k];\n          acc[i] = BCached0 * ACached.x + acc[i];\n          acc[i] = BCached1 * ACached.y + acc[i];\n          acc[i] = BCached2 * ACached.z + acc[i];\n          ${t===3?\"\":\"acc[i] = BCached3 * ACached.w + acc[i];\"}\n        }`;function Uh(e,t,a=!1,n=32,r=!1,s=32,i=!1){let o=t[1]*e[1],l=t[0]*e[0],u=a?o:n,p=a?n:o,c=u/t[0],d=n/t[1];return v.assert((a&&c===4&&e[1]===4||!a&&(c===3||c===4))&&u%t[0]===0&&n%t[1]===0&&e[0]===4,()=>`If transposeA ${a} is true, innerElementSize ${c} and workPerThread[1] ${e[1]} must be 4.\n          Otherwise, innerElementSize ${c} must be 3 or 4.\n      tileAWidth ${u} must be divisible by workgroupSize[0]${t[0]}. tileInner ${n} must be divisible by workgroupSize[1] ${t[1]}. colPerThread ${e[0]} must be 4.`),`\n  var<workgroup> mm_Asub : array<array<vec${c}<f32>, ${u/c}>, ${p}>;\n  var<workgroup> mm_Bsub : array<array<vec4<f32>, ${l/e[0]}>, ${n}>;\n\n  const rowPerThread = ${e[1]};\n  const colPerThread = ${e[0]};\n  const innerElementSize = ${c};\n  const tileInner = ${n};\n\n  ${Ce()} {\n    let localRow = i32(localId.y);\n    let tileRow = ${i?\"0\":\"localRow * rowPerThread\"};\n    let tileCol = i32(localId.x);\n\n    let globalRow = ${i?\"0\":\"i32(globalId.y) * rowPerThread\"};\n    let globalCol = i32(globalId.x);\n    let batch = ${r?\"0\":\"i32(globalId.z)\"};\n    let globalRowStart = i32(workgroupId.y) * ${o};\n\n    let numTiles = ${r?`${Math.ceil(s/n)}`:\"(uniforms.dimInner - 1) / tileInner + 1\"};\n    var kStart = ${r?`i32(globalId.z) * ${s}`:\"0\"};\n\n    var acc: array<vec4<f32>, rowPerThread>;\n\n    // Loop over shared dimension.\n    let tileRowB = localRow * ${d};\n    for (var t = 0; t < numTiles; t = t + 1) {\n        // Load one tile of A into local memory.\n        for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n            let inputRow = tileRow + innerRow;\n            let inputCol = tileCol;\n            ${cse(a)}\n        }\n\n        // Load one tile of B into local memory.\n        for (var innerRow = 0; innerRow < ${d}; innerRow = innerRow + 1) {\n            let inputRow = tileRowB + innerRow;\n            let inputCol = tileCol;\n            mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol);\n        }\n        kStart = kStart + tileInner;\n        workgroupBarrier();\n\n        // Compute acc values for a single thread.\n        for (var k = 0; k < tileInner / innerElementSize; k = k + 1) {\n            let BCached0 = mm_Bsub[k * innerElementSize][tileCol];\n            let BCached1 = mm_Bsub[k * innerElementSize + 1][tileCol];\n            let BCached2 = mm_Bsub[k * innerElementSize + 2][tileCol];\n            ${c===3?\"\":\"let BCached3 = mm_Bsub[k * innerElementSize + 3][tileCol];\"}\n\n            ${hse(a,c)}\n        }\n\n        workgroupBarrier();\n    }\n\n    for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n        mm_write(batch, globalRow + innerRow, globalCol, acc[innerRow]);\n    }\n  }`}var qx=e=>e?`\n        mm_Asub[inputRow][inputCol] = mm_readA(batch,\n          kStart + inputRow,\n          globalRowStart + inputCol);\n        `:`\n        mm_Asub[inputRow][inputCol] = mm_readA(batch,\n          globalRowStart + inputRow,\n          kStart + inputCol);\n        `,fse=e=>e?\"let ACached = mm_Asub[k][tileRow + innerRow];\":\"let ACached = mm_Asub[tileRow + innerRow][k];\";function Gh(e,t,a=!1,n=32,r=!1,s=32,i=!1){let o=e[1]*t[1],l=e[0]*t[0],u=a?o:n,p=a?n:o;v.assert(p%t[1]===0&&u%t[0]===0&&n%t[1]===0,()=>`tileAHight ${p} must be divisible by workgroupSize[1]${t[1]}, tileAWidth ${u} must be divisible by workgroupSize[0]${t[0]}, tileInner ${n} must be divisible by workgroupSize[1]${t[1]}`);let c=p/t[1],d=u/t[0],h=n/t[1],f=i?`\n      let localRow = i32(localId.y);\n      let localCol = i32(localId.x);\n      let globalRowStart = i32(workgroupId.y) * ${o};\n      let globalColStart = i32(workgroupId.x) * ${l};\n\n      // Loop over shared dimension.\n      for (var t = 0; t < numTiles; t = t + 1) {\n        // Load one tile of A into local memory.\n        for (var inputRow = localRow; inputRow < ${p}; inputRow = inputRow + ${t[1]}) {\n          for (var inputCol = localCol; inputCol < ${u}; inputCol = inputCol + ${t[0]}) {\n            ${qx(a)}\n          }\n        }\n        // Load one tile of B into local memory.\n        for (var inputRow = localRow; inputRow < ${n}; inputRow = inputRow + ${t[1]}) {\n              for (var inputCol = localCol; inputCol < ${l}; inputCol = inputCol + ${t[0]}) {\n            mm_Bsub[inputRow][inputCol] = mm_readB(batch,\n              kStart + inputRow,\n              globalColStart + inputCol);\n          }\n        }\n        kStart = kStart + tileInner;\n        workgroupBarrier();\n\n        // Compute acc values for a single thread.\n        var BCached : array<f32, colPerThread>;\n        for (var k = 0; k < tileInner; k = k + 1) {\n          for (var inner = 0; inner < colPerThread; inner = inner + 1) {\n            BCached[inner] = mm_Bsub[k][localCol + inner * ${t[0]}];\n          }\n          for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n            let ACached = ${a?`mm_Asub[k][localRow + innerRow * ${t[1]}];`:`mm_Asub[localRow + innerRow * ${t[1]}][k];`}\n            for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n              acc[innerRow][innerCol] = acc[innerRow][innerCol] +\n                  ACached * BCached[innerCol];\n            }\n          }\n        }\n        workgroupBarrier();\n      }\n      for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n        let gRow = globalRowStart + localRow + innerRow * ${t[1]};\n        for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n          let gCol = globalColStart + localCol + innerCol * ${t[0]};\n          mm_write(batch, gRow, gCol, acc[innerRow][innerCol]);\n        }\n      }\n      `:`\n  let tileRow = i32(localId.y) * rowPerThread;\n  let tileCol = i32(localId.x) * colPerThread;\n\n  let globalRow = i32(globalId.y) * rowPerThread;\n  let globalCol = i32(globalId.x) * colPerThread;\n  let globalRowStart = i32(workgroupId.y) * ${o};\n\n  let tileRowA = i32(localId.y) * ${c};\n  let tileColA = i32(localId.x) * ${d};\n  let tileRowB = i32(localId.y) * ${h};\n  // Loop over shared dimension.\n  for (var t = 0; t < numTiles; t = t + 1) {\n    // Load one tile of A into local memory.\n    for (var innerRow = 0; innerRow < ${c}; innerRow = innerRow + 1) {\n      for (var innerCol = 0; innerCol < ${d}; innerCol = innerCol + 1) {\n        let inputRow = tileRowA + innerRow;\n        let inputCol = tileColA + innerCol;\n        ${qx(a)}\n      }\n    }\n\n    // Load one tile of B into local memory.\n    for (var innerRow = 0; innerRow < ${h}; innerRow = innerRow + 1) {\n      for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n        let inputRow = tileRowB + innerRow;\n        let inputCol = tileCol + innerCol;\n        mm_Bsub[inputRow][inputCol] = mm_readB(batch,\n          kStart + inputRow,\n          globalCol + innerCol);\n      }\n    }\n    kStart = kStart + tileInner;\n    workgroupBarrier();\n\n    // Compute acc values for a single thread.\n    var BCached : array<f32, colPerThread>;\n    for (var k = 0; k < tileInner; k = k + 1) {\n      for (var inner = 0; inner < colPerThread; inner = inner + 1) {\n        BCached[inner] = mm_Bsub[k][tileCol + inner];\n      }\n\n      for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n        ${fse(a)}\n        for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n          acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol];\n        }\n      }\n    }\n\n    workgroupBarrier();\n  }\n\n  for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n    for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n      mm_write(batch, globalRow + innerRow, globalCol + innerCol,\n          acc[innerRow][innerCol]);\n    }\n  }\n  `;return`\n    var<workgroup> mm_Asub : array<array<f32, ${u}>, ${p}>;\n    var<workgroup> mm_Bsub : array<array<f32, ${l}>, ${n}>;\n    const rowPerThread = ${e[1]};\n    const colPerThread = ${e[0]};\n    const tileInner = ${n};\n\n    ${Ce()} {\n      let batch = ${r?\"0\":\"i32(globalId.z)\"};\n      let numTiles = ${r?`${Math.ceil(s/n)}`:\"(uniforms.dimInner - 1) / tileInner + 1\"};\n      var kStart = ${r?`i32(globalId.z) * ${s}`:\"0\"};\n\n      var acc : array<array<f32, colPerThread>, rowPerThread>;\n\n      // Without this initialization strange values show up in acc.\n      for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) {\n        for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) {\n          acc[innerRow][innerCol] = 0.0;\n        }\n      }\n      ${f}\n    }\n  `}var mse=e=>e?`\n      mm_readA(batch, colA, globalRow),\n      mm_readA(batch, colA + 1, globalRow),\n      mm_readA(batch, colA + 2, globalRow),\n      mm_readA(batch, colA + 3, globalRow)\n  `:`\n      mm_readA(batch, globalRow, colA),\n      mm_readA(batch, globalRow, colA + 1),\n      mm_readA(batch, globalRow, colA + 2),\n      mm_readA(batch, globalRow, colA + 3)\n  `;function gse(e,t=!1){return v.assert(e[1]===1&&e[2]===1,()=>`A linear work group size is required. But got ${e}.`),`\n    const tileSize = ${e[0]*4};\n    var<workgroup> mm_Asub : array<vec4<f32>, ${e[0]}>;\n\n    ${Ce()} {\n      let tileCol = i32(localId.x);\n      let globalCol = i32(globalId.x);\n      let globalRow = i32(globalId.y);\n\n      let numTiles = (uniforms.dimInner - 1) / tileSize + 1;\n      let batch = i32(globalId.z);\n      // Without this initialization strange values show up in acc.\n      var acc = 0.0;\n\n      // Loop over shared dimension.\n      for (var t = 0; t < numTiles; t = t + 1) {\n        // Load one tile of A into local memory.\n        let colA = t * tileSize + tileCol * 4;\n        mm_Asub[tileCol] = vec4<f32>(${mse(t)});\n        workgroupBarrier();\n\n        // Compute acc values for a single thread.\n        for (var k = 0; k < tileSize / 4; k = k + 1) {\n          let rowB = t * tileSize + k * 4;\n          let BCached = vec4<f32>(mm_readB(batch, rowB, globalCol),\n                              mm_readB(batch, rowB + 1, globalCol),\n                              mm_readB(batch, rowB + 2, globalCol),\n                              mm_readB(batch, rowB + 3, globalCol));\n\n          let ACached = mm_Asub[k];\n          acc = acc + dot(ACached, BCached);\n        }\n\n        workgroupBarrier();\n      }\n\n      mm_write(batch, globalRow, globalCol, acc);\n    }\n  `}var xse=class{constructor(e,t,a,n,r=!1,s=!1,i=null,o=null,l=null,u=!1){this.variableNames=[\"A\",\"B\"],this.uniforms=\"dimAOuter : i32, dimBOuter : i32, dimInner : i32,\",this.outputShape=t,this.dispatchLayout={x:[2],y:[1],z:[0]};let p=r?e[1]:e[2];if(this.isVec4=(p%4===0&&!r||t[1]%4===0&&r)&&t[2]%4===0&&!s,this.isVectorA=t[1]===1&&!r,!this.isVec4&&this.isVectorA)this.elementsPerThread=[1,1,1],this.workgroupSize=[32,1,1];else{let h=N8(t[1],p,t[2],r);this.workgroupSize=h.workgroupSize,this.elementsPerThread=h.elementsPerThread}this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,this.elementsPerThread);let c=i!=null,d=l!=null;c&&this.variableNames.push(\"bias\"),d&&this.variableNames.push(\"preluActivationWeights\"),this.sequentialAccessByThreads=u,this.transposeA=r,this.transposeB=s,this.addBias=c,this.activation=o,this.hasPreluActivationWeights=d,this.batchAEqualOne=a,this.batchBEqualOne=n,[this.fitAOuter,this.fitBOuter,this.fitInner]=this.getShapeFit(t[1],t[2],p),this.shaderKey=`matMulPacked_${this.elementsPerThread}_${r}_${s}_${this.activation}_${this.fitAOuter}_${this.fitBOuter}_${this.fitInner}_${this.isVec4}_${this.isVectorA}_${this.batchAEqualOne}_${this.batchBEqualOne}_${this.sequentialAccessByThreads}`}getShapeFit(e,t,a){let n=this.workgroupSize[1]*this.elementsPerThread[1],r=this.workgroupSize[0]*this.elementsPerThread[0];!this.isVec4&&this.isVectorA?this.tileInner=this.workgroupSize[0]*4:this.tileInner=r;let s=e%n===0,i=t%r===0,o=a%this.tileInner===0;return[s,i,o]}getUserCode(){return`\n      ${Tr(this.activation,this.hasPreluActivationWeights,this.isVec4)}\n      ${B3(this.addBias,this.activation,this.batchAEqualOne,this.batchBEqualOne,!1,this.transposeB,this.fitAOuter,this.fitBOuter,this.fitInner,this.isVec4?4:1)}\n      ${this.isVec4?Uh(this.elementsPerThread,this.workgroupSize,this.transposeA,this.tileInner,!1,null,this.isVectorA):this.isVectorA?gse(this.workgroupSize,this.transposeA):Gh(this.elementsPerThread,this.workgroupSize,this.transposeA,this.tileInner,!1,null,this.sequentialAccessByThreads)}\n    `}};function Ase(){return`\n    var<workgroup> sumValues : array<f32, workgroupSizeX>;\n    ${Ce()} {\n      let coords = getOutputCoords();\n      let batch = coords[0];\n      let row = coords[1];\n      let col = coords[2];\n      var sum = 0.0;\n      let Length = uniforms.dimInner;\n      for (var k = i32(localId.x); k < Length; k = k + i32(workgroupSizeX)) {\n        let dataA = mm_readA(batch, row, k);\n        let dataB = mm_readB(batch, k, col);\n        sum = sum + dataA * dataB;\n      }\n      sumValues[localId.x] = sum;\n      workgroupBarrier();\n\n      for(var currentSize = workgroupSizeX / 2u; currentSize > 1u;\n          currentSize = currentSize / 2u) {\n        if (localId.x < currentSize)\n        {\n          sumValues[localId.x] = sumValues[localId.x] + sumValues[localId.x + currentSize];\n        }\n        workgroupBarrier();\n      }\n\n      if (localId.x == 0u) {\n        sum = sumValues[0] + sumValues[1];\n        mm_write(batch, row, col, sum);\n      }\n    }\n  `}var yse=class{constructor(e,t,a,n=!1,r=!1,s=null,i=null,o=null){this.variableNames=[\"A\",\"B\"],this.uniforms=\"dimAOuter : i32, dimBOuter : i32, dimInner : i32,\",this.workgroupSize=[256,1,1],this.outputShape=e,this.dispatchLayout={x:[],y:[1,2],z:[0]},this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize);let l=s!=null,u=o!=null;l&&this.variableNames.push(\"bias\"),u&&this.variableNames.push(\"preluActivationWeights\"),this.transposeA=n,this.transposeB=r,this.addBias=l,this.activation=i,this.hasPreluActivationWeights=u,this.batchAEqualOne=t,this.batchBEqualOne=a,this.shaderKey=`matMulReduce_${this.activation}_${n}_${r}_${this.batchAEqualOne}_${this.batchBEqualOne}`}getUserCode(){return`\n      ${Tr(this.activation,this.hasPreluActivationWeights)}\n      ${B3(this.addBias,this.activation,this.batchAEqualOne,this.batchBEqualOne,this.transposeA,this.transposeB)}\n      ${Ase()}\n    `}};function bse(e){let t=e[1],a=e[0],n=t>a?t:a;return`\n  var<workgroup> mm_Asub : array<array<f32, ${n}>, ${t}>;\n  var<workgroup> mm_Bsub : array<array<f32, ${a}>, ${n}>;\n\n  // If the output size is small for matrix multiplication, avoid to use vec4\n  // and handle some elements per thread to optimally utilize the ALU.\n  // Read data from global memory to registers firstly, then store them into\n  // shared memory, so it is instruction-Level parallelism for arithmetic\n  // operations and others handle IO operations between barrier api, makes ALU\n  // and load/store units work simultaneously, could improves the performance.\n  ${Ce()} {\n    let tileRow = i32(localId.y);\n    let tileCol = i32(localId.x);\n    let globalRow = i32(globalId.y);\n    let globalCol = i32(globalId.x);\n    let batch = i32(globalId.z);\n\n    // uniforms.dimInner should be greater than 0.\n    let numTiles = (uniforms.dimInner - 1) / ${n} + 1;\n    var acc = 0.0;\n\n    var globalColA = tileCol;\n    var globalRowB = 0;\n    var regA = mm_readA(batch, globalRow, globalColA);\n    var regB0 = mm_readB(batch, globalRowB + 2 * tileRow, globalCol);\n    var regB1 = mm_readB(batch, globalRowB + 2 * tileRow + 1, globalCol);\n    globalColA = globalColA + ${n};\n    globalRowB = globalRowB + ${n};\n\n    for (var t = 0; t < numTiles; t = t + 1) {\n      mm_Asub[tileRow][tileCol] = regA;\n      mm_Bsub[2 * tileRow][tileCol] = regB0;\n      mm_Bsub[2 * tileRow + 1][tileCol] = regB1;\n\n      workgroupBarrier();\n\n      regA = mm_readA(batch, globalRow, globalColA);\n      regB0 = mm_readB(batch, globalRowB + 2 * tileRow, globalCol);\n      regB1 = mm_readB(batch, globalRowB + 2 * tileRow + 1, globalCol);\n      globalColA = globalColA + ${n};\n      globalRowB = globalRowB + ${n};\n\n      for (var k = 0; k < ${n}; k = k + 1) {\n        acc = acc + mm_Asub[tileRow][k] * mm_Bsub[k][tileCol];\n      }\n      workgroupBarrier();\n    }\n\n    mm_write(batch, globalRow, globalCol, acc);\n  }\n  `}var vse=class{constructor(e,t,a,n=!1,r=!1,s=null,i=null,o=null){this.variableNames=[\"A\",\"B\"],this.uniforms=\"dimAOuter : i32, dimBOuter : i32, dimInner : i32,\",this.workgroupSize=[16,8,1],this.outputShape=a,this.dispatchLayout={x:[2],y:[1],z:[0]},this.dispatch=[Math.ceil(a[2]/this.workgroupSize[0]),Math.ceil(a[1]/this.workgroupSize[1]),a[0]];let l=s!=null;l&&this.variableNames.push(\"bias\");let u=o!=null;u&&this.variableNames.push(\"preluActivationWeights\"),this.transposeA=n,this.transposeB=r,this.addBias=l,this.activation=i,this.hasPreluActivationWeights=u,this.batchAEqualOne=e[0]===1,this.batchBEqualOne=t[0]===1,this.shaderKey=`matMulSmallOutputSize_${this.activation}_${n}_${r}_${this.batchAEqualOne}_${this.batchBEqualOne}`}getUserCode(){return`\n      ${Tr(this.activation,this.hasPreluActivationWeights)}\n      ${B3(this.addBias,this.activation,this.batchAEqualOne,this.batchBEqualOne,this.transposeA,this.transposeB)}\n      ${bse(this.workgroupSize)}\n    `}},wse=class{constructor(e,t,a,n,r=!1,s=!1){this.variableNames=[\"A\",\"B\"],this.uniforms=\"dimAOuter : i32, dimBOuter : i32, dimInner : i32,\",this.workgroupSize=[8,8,1],this.atomic=!0,this.isVec4=!1,this.splitedDimInner=128,v.assert(e[0]===1,()=>\"MatMulSplitKProgram only supports batch = 1.\"),this.outputShape=e,this.dispatchLayout={x:[2],y:[1],z:[0,3]},this.isVec4=(r&&this.outputShape[1]%4===0||!r&&t%4===0)&&this.outputShape[2]%4===0,this.elementsPerThread=[4,4,this.splitedDimInner],this.isVec4||(this.outputShape[1]<16&&(this.elementsPerThread[1]=1),this.outputShape[2]<16&&(this.elementsPerThread[0]=1)),this.dispatch=Ne(this.dispatchLayout,[this.outputShape[0],this.outputShape[1],this.outputShape[2],t],this.workgroupSize,this.elementsPerThread),this.transposeA=r,this.transposeB=s,this.batchAEqualOne=a,this.batchBEqualOne=n,this.shaderKey=`matMulSplitK_${r}_${s}_${a}_${n}_${this.elementsPerThread}_${this.isVec4}`}getUserCode(){let e=a=>`\n      for (var i = 0; i < ${a}; i = i + 1)\n      {\n        var oldValue = atomicLoad(&(result[flatIndex + i]));\n        var exchanged = false;\n        for (; !exchanged;) {\n          let newValueF32 = bitcast<f32>(oldValue) + ${a>1?\"value[i]\":\"value\"};\n          let newValue = bitcast<i32>(newValueF32);\n          let res = atomicCompareExchangeWeak(&(result[flatIndex + i]), oldValue, newValue);\n          oldValue = res.old_value;\n          exchanged = res.exchanged;\n        }\n      }\n      `,t=this.isVec4?4:1;return`\n      ${_8(this.batchAEqualOne,this.batchBEqualOne,!1,this.transposeB,!1,!1,!1,t)}\n      fn mm_write(batch: i32, row : i32, colIn : i32, value : ${Mt(t)}) {\n        let col = colIn * ${t};\n        if (row < uniforms.dimAOuter && col < uniforms.dimBOuter) {\n          let coords = vec3<i32>(batch, row, col);\n          let flatIndex = getOutputIndexFromCoords(coords);\n          // The problem is that we should initialize output to zero before using.\n          // Otherwise, the original value will be added to the result.\n          ${e(t)}\n        }\n      }\n      ${this.isVec4?Uh(this.elementsPerThread,this.workgroupSize,this.transposeA,32,!0,this.splitedDimInner):Gh(this.elementsPerThread,this.workgroupSize,this.transposeA,32,!0,this.splitedDimInner)}\n    `}},kse=class{constructor(e,t=null,a=null,n=null){this.uniforms=\"\",this.variableNames=[\"x\"],this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.addBias=t!=null,this.hasPreluActivationWeights=n!=null,this.activation=a,this.addBias&&this.variableNames.push(\"bias\"),this.hasPreluActivationWeights&&this.variableNames.push(\"preluActivationWeights\"),this.shaderKey=`biasActivation_${a}`}getUserCode(){return`\n    ${Tr(this.activation,this.hasPreluActivationWeights)}\n    ${Ce(\"index\")} {\n      if (index < uniforms.size) {\n        let coords = getCoordsFromIndex(index);\n        var value = getXByOutputIndex(index);\n        ${vo(this.addBias,this.activation)}\n        setOutputAtIndex(index, value);\n      }\n    }\n    `}},Ise=class{constructor(e){this.variableNames=[],this.outputShape=[],this.uniforms=\"value : f32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=\"fill\"}getUserCode(){return`\n    ${Ce(\"index\")} {\n      if (index < uniforms.size) {\n        setOutputAtIndex(index, uniforms.value);\n      }\n    }\n  `}};function Cr(e){let{backend:t,attrs:a}=e,{shape:n,value:r}=a,{dtype:s}=a;if(s=s||v.inferDtype(r),s===\"string\"){let i=v.getArrayFromDType(s,v.sizeFromShape(n));return i.fill(r),t.makeTensorInfo(n,s,i)}else{let i=new Ise(n),o=[{type:\"float32\",data:[r]}];return t.runWebGPUProgram(i,[],s,o)}}var Sse={kernelName:Fl,backendName:\"webgpu\",kernelFunc:Cr};function Ie(e){let{inputs:t,attrs:a}=e,{x:n}=t,{shape:r}=a,s=v.sizeFromShape(n.shape),i=v.inferFromImplicitShape(r,s),o=v.sizeFromShape(i);return v.assert(s===o,()=>`The new shape (${i}) has ${o} elements and the old shape (${n.shape}) has ${s} elements. The new shape and old shape must have the same number of elements.`),e.backend.incRef(n.dataId),{dataId:n.dataId,shape:i,dtype:n.dtype}}var Tse={kernelName:ql,backendName:\"webgpu\",kernelFunc:Ie};function Hh({a:e,b:t,transposeA:a,transposeB:n,backend:r,bias:s=null,preluActivationWeights:i=null,leakyreluAlpha:o=0,activation:l=null}){let u=e.shape.length,p=t.shape.length,c=a?e.shape[u-2]:e.shape[u-1],d=n?t.shape[p-1]:t.shape[p-2],h=a?e.shape[u-1]:e.shape[u-2],f=n?t.shape[p-2]:t.shape[p-1],m=e.shape.slice(0,-2),g=t.shape.slice(0,-2),x=v.sizeFromShape(m),A=v.sizeFromShape(g),y=xo.assertAndGetBroadcastShape(e.shape.slice(0,-2),t.shape.slice(0,-2)).concat([h,f]);v.assert(c===d,()=>`Error in matMul: inner shapes (${c}) and (${d}) of Tensors with shapes ${e.shape} and ${t.shape} and transposeA=${a} and transposeB=${n} must match.`);let b=a?[x,c,h]:[x,h,c],w=n?[A,f,d]:[A,d,f],S=Ie({inputs:{x:e},backend:r,attrs:{shape:b}}),C=Ie({inputs:{x:t},backend:r,attrs:{shape:w}}),E=[S,C],_=Math.max(x,A),$=x===1,M=A===1,I=[S,C],N=[{type:\"int32\",data:[h]},{type:\"int32\",data:[f]},{type:\"int32\",data:[c]}],O,L,B=[_,h,f],G=W().get(\"WEBGPU_MATMUL_PROGRAM_TYPE\");if(G<0){let U=W().getNumber(\"WEBGPU_THRESHOLD_TO_INCREASE_WORKGROUPS_FOR_MATMUL\"),H=U>0?U:r.thresholdToIncreaseWorkgroups,V=_*Math.ceil(h/32)*Math.ceil(f/32);V<=H||h<=8&&V<=H*2?_*h*f<=128?G=Pn.MatMulReduceProgram:_===1&&d>=2e3?G=Pn.MatMulSplitKProgram:G=Pn.MatMulSmallOutputSizeProgram:G=Pn.MatMulPackedProgram}switch(G){case Pn.MatMulReduceProgram:O=new yse(B,$,M,a,n,s,l,i);break;case Pn.MatMulSplitKProgram:{if(L=Cr({backend:r,attrs:{shape:B,value:0,dtype:e.dtype}}),O=new wse(B,d,$,M,a,n),s||l){L=r.runWebGPUProgram(O,I,e.dtype,N,L);let H=new kse(L.shape,s,l,i),V=null,Q=[L];s&&Q.push(s),i&&Q.push(i),l===\"leakyrelu\"&&(V=[{type:\"float32\",data:[o]}],H.uniforms+=\" alpha : f32,\");let Z=r.runWebGPUProgram(H,Q,L.dtype,V);E.push(L);let re=Ie({inputs:{x:Z},backend:r,attrs:{shape:y}});E.push(Z);for(let ee of E)r.disposeData(ee.dataId);return re}break}case Pn.MatMulSmallOutputSizeProgram:O=new vse(b,w,B,a,n,s,l,i);break;case Pn.MatMulPackedProgram:let U=r.adapterInfo.isIntel();O=new xse(b,B,$,M,a,n,s,l,i,U);break;default:throw new Error(`Unsupported MatMulProgramType ${G}.`)}s&&I.push(s),i&&I.push(i),l===\"leakyrelu\"&&(N.push({type:\"float32\",data:[o]}),O.uniforms+=\" alpha : f32,\"),L=r.runWebGPUProgram(O,I,e.dtype,N,L);let j=Ie({inputs:{x:L},backend:r,attrs:{shape:y}});E.push(L);for(let U of E)r.disposeData(U.dataId);return j}function Cse(e){let{inputs:t,backend:a,attrs:n}=e,{a:r,b:s,bias:i,preluActivationWeights:o}=t,{transposeA:l,transposeB:u,activation:p,leakyreluAlpha:c}=n;return Hh({a:r,b:s,transposeA:l,transposeB:u,backend:a,bias:i,preluActivationWeights:o,leakyreluAlpha:c,activation:p})}var Nse={kernelName:jr,backendName:\"webgpu\",kernelFunc:Cse},Xx=class{constructor(e,t,a){this.variableNames=[\"AReal\",\"AImag\",\"BReal\",\"BImag\"],this.workgroupSize=[128,1,1],this.size=!0,this.outputShape=T.assertAndGetBroadcastShape(t,a),this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=`binaryOpComplex_${e}`,this.op=e}getUserCode(){return`\n      fn binaryOpComplex(\n          areal : f32, aimag : f32, breal : f32, bimag : f32) -> f32 {\n        ${L3(this.op,!1)}\n      }\n\n      ${Ce(\"index\")} {\n        if(index < uniforms.size) {\n          let areal = getARealByOutputIndex(index);\n          let aimag = getAImagByOutputIndex(index);\n          let breal = getBRealByOutputIndex(index);\n          let bimag = getBImagByOutputIndex(index);\n          setOutputAtIndex(index, binaryOpComplex(areal, aimag, breal, bimag));\n        }\n      }\n    `}},P1=class{constructor(e,t,a){this.size=!0,this.variableNames=[\"A\",\"B\"],this.outputShape=T.assertAndGetBroadcastShape(t,a),this.dispatchLayout=Ve(this.outputShape),this.op=e,this.useSharedMemoryWithA=t.length<=1&&a.length>1&&t[0]<128,this.useSharedMemoryWithB=a.length<=1&&t.length>1&&a[0]<128,this.useSharedMemoryWithA||this.useSharedMemoryWithB?(this.isVec4=!1,this.lastDimensionSize=this.useSharedMemoryWithB?a[0]:t[0],this.shaderKey=`binary_${this.type}_${e}_${this.lastDimensionSize}_${this.useSharedMemoryWithB}`,this.type=\"shared\",this.workgroupSize=[256,1,1],this.workPerThread=1):(v.arraysEqual(t,a)&&v.sizeFromShape(t)%4===0?(this.isVec4=!0,this.type=\"vec4\",this.workPerThread=4):(this.isVec4=!1,this.type=\"plain\",this.workPerThread=1),this.shaderKey=`binary_${this.type}_${e}`,this.workgroupSize=[128,1,1]),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[this.workPerThread,1,1])}getUserCode(){let e,t=this.isVec4?\"vec4<f32>\":\"f32\",a=`\n    fn binaryOperation(a : ${t}, b : ${t}) -> ${t} {\n      ${L3(this.op,this.isVec4)}\n    };\n    `;if(this.type===\"shared\"){let n=this.lastDimensionSize>1?`coords[${this.outputShape.length-1}]`:\"0\",r=this.useSharedMemoryWithB?`let a = getAByOutputIndex(index);\n          let b = sharedBuf[${n}];`:`let a = sharedBuf[${n}];\n          let b = getBByOutputIndex(index);`;e=`\n        ${a}\n        var<workgroup> sharedBuf : array<f32, ${this.lastDimensionSize}>;\n        ${Ce(\"index\")} {\n          // Fill in the shared memory buffer.\n          let localIndex = i32(localId.x);\n          if(localIndex < ${this.lastDimensionSize}) {\n            sharedBuf[localIndex] = f32(${this.useSharedMemoryWithB?\"B\":\"A\"}[localIndex]);\n          }\n          workgroupBarrier();\n\n          if(index < uniforms.size) {\n            let coords = getCoordsFromIndex(index);\n            ${r}\n            setOutputAtIndex(index, binaryOperation(a, b));\n          }\n        }\n        `}else e=`\n       ${a}\n       ${Ce(\"index\")} {\n         if (index < uniforms.size) {\n           let a = getAByOutputIndex(index);\n           let b = getBByOutputIndex(index);\n           setOutputAtIndex(index, binaryOperation(a, b));\n         }\n       }\n       `;return e}};function Ya(e){let{inputs:t}=e,{x:a}=t;return e.backend.incRef(a.dataId),{dataId:a.dataId,shape:a.shape,dtype:a.dtype}}var Ese={kernelName:ki,backendName:\"webgpu\",kernelFunc:Ya};function wo(e){let{inputs:t,backend:a}=e,{real:n,imag:r}=t,s=a.makeTensorInfo(n.shape,\"complex64\"),i=a.tensorMap.get(s.dataId),o=Ya({inputs:{x:n},backend:a}),l=Ya({inputs:{x:r},backend:a});return i.complexTensorInfos={real:o,imag:l},s}var Rse={kernelName:Sd,backendName:\"webgpu\",kernelFunc:wo},mp=class{constructor(e,t){this.variableNames=[\"A\"],this.size=!0;let a=128;this.workgroupSize=[a,1,1],this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.op=t,this.shaderKey=`unary_${t}`}getUserCode(){return`\n      fn unaryOperation(a : f32) -> f32 {\n        ${Ms(this.op,!1)}\n      }\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let a = getAByOutputIndex(index);\n          setOutputAtIndex(index, unaryOperation(a));\n        }\n      }\n      `}};function it({opType:e,cpuKernelImpl:t,dtype:a}){return({inputs:n,backend:r})=>{let{x:s}=n,i=r,o=a||s.dtype;if(i.shouldExecuteOnCPU([s])&&t!=null){let u=i.tensorMap.get(s.dataId),p=t(u.values,o);return i.makeTensorInfo(s.shape,o,p)}let l=new mp(s.shape,e);return i.runWebGPUProgram(l,[s],o)}}function ua({opType:e,cpuKernelImpl:t,supportsComplex:a=!1,dtype:n}){return({inputs:r,backend:s})=>{let{a:i,b:o}=r,l=s;if(a&&i.dtype===\"complex64\"){let c=l.tensorMap.get(i.dataId),d=l.tensorMap.get(o.dataId),h,f;if(e!==De.MUL)[h,f]=[[c.complexTensorInfos.real,d.complexTensorInfos.real],[c.complexTensorInfos.imag,d.complexTensorInfos.imag]].map(g=>{let[x,A]=g,y={dataId:x.dataId,dtype:x.dtype,shape:i.shape},b={dataId:A.dataId,dtype:A.dtype,shape:o.shape},w=new P1(e,i.shape,o.shape);return l.runWebGPUProgram(w,[y,b],ca(x.dtype,A.dtype))});else{let g=new Xx(De.COMPLEX_MULTIPLY_REAL,i.shape,o.shape),x=new Xx(De.COMPLEX_MULTIPLY_IMAG,i.shape,o.shape),A=[{dataId:c.complexTensorInfos.real.dataId,dtype:c.complexTensorInfos.real.dtype,shape:i.shape},{dataId:c.complexTensorInfos.imag.dataId,dtype:c.complexTensorInfos.imag.dtype,shape:i.shape},{dataId:d.complexTensorInfos.real.dataId,dtype:d.complexTensorInfos.real.dtype,shape:o.shape},{dataId:d.complexTensorInfos.imag.dataId,dtype:d.complexTensorInfos.imag.dtype,shape:o.shape}];h=l.runWebGPUProgram(g,A,\"float32\"),f=l.runWebGPUProgram(x,A,\"float32\")}let m=wo({inputs:{real:h,imag:f},backend:l});return l.disposeData(h.dataId),l.disposeData(f.dataId),m}let u=n||ca(i.dtype,o.dtype);if((i.dtype===\"string\"||o.dtype===\"string\"||l.shouldExecuteOnCPU([i,o]))&&t!=null){let c=l.tensorMap.get(i.dataId).values,d=l.tensorMap.get(o.dataId).values,h=i.dtype===\"string\"?T.fromUint8ToStringArray(c):c,f=i.dtype===\"string\"?T.fromUint8ToStringArray(d):d,[m,g]=t(i.shape,o.shape,h,f,u);return l.makeTensorInfo(g,u,m)}let p=new P1(e,i.shape,o.shape);return l.runWebGPUProgram(p,[i,o],u)}}var{addImpl:Mse,castImpl:$se,ceilImpl:_se,concatImpl:Pse,equalImpl:Fse,expImpl:Ose,expm1Impl:Dse,floorImpl:zse,gatherNdImpl:Lse,gatherV2Impl:Bse,greaterEqualImpl:Wse,greaterImpl:Vse,lessEqualImpl:Use,lessImpl:Gse,logImpl:Hse,maxImpl:jse,maximumImpl:qse,minimumImpl:Xse,multiplyImpl:Kse,negImpl:Zse,notEqualImpl:Yse,prodImpl:Jse,rangeImpl:Qse,rsqrtImpl:eie,scatterImpl:tie,simpleAbsImpl:aie,sliceImpl:nie,stridedSliceImpl:rie,stringNGramsImpl:sie,subImpl:iie,tileImpl:oie,topKImpl:lie,transposeImpl:uie,uniqueImpl:I0e}=_h,die=it({opType:de.ABS,cpuKernelImpl:aie}),pie={kernelName:wl,backendName:\"webgpu\",kernelFunc:die},cie=it({opType:de.ACOS}),hie={kernelName:kl,backendName:\"webgpu\",kernelFunc:cie},fie=it({opType:de.ACOSH}),mie={kernelName:Il,backendName:\"webgpu\",kernelFunc:fie},gie=ua({opType:De.ADD,cpuKernelImpl:Mse,supportsComplex:!0}),xie={kernelName:ts,backendName:\"webgpu\",kernelFunc:gie},Aie=class{constructor(e){this.workPerThread=1,this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e[0],this.variableNames=e.map((t,a)=>`T${a}`),this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[this.workPerThread,1,1]),this.shaderKey=\"addN\"}getUserCode(){let e=[];this.variableNames.forEach(a=>{e.push(`let v${a} = get${a}ByOutputCoords(coords);`)});let t=this.variableNames.map(a=>`v${a}`).join(\" + \");return`\n      ${Ce(\"index\")} {\n        for (var i = 0; i < ${this.workPerThread}; i = i + 1) {\n          let flatIndex = index * ${this.workPerThread} + i;\n          if (flatIndex < uniforms.size) {\n            let coords = getCoordsFromIndex(flatIndex);\n            ${e.join(`\n        `)}\n            setOutputAtIndex(flatIndex, ${t});\n          }\n        }\n      }\n    `}};function yie(e){let{inputs:t,backend:a}=e,n=t;if(n.length===1)return Ya({inputs:{x:n[0]},backend:a});let r=n.map(o=>o.dtype).reduce((o,l)=>ca(o,l)),s=n.map(o=>o.shape),i=new Aie(s);return a.runWebGPUProgram(i,n,r)}var bie={kernelName:Ks,backendName:\"webgpu\",kernelFunc:yie},vie=class{constructor(e,t){this.variableNames=[\"A\"],this.workgroupSize=[16,16,1];let a=new Array(e.length);for(let n=0;n<a.length;n++)a[n]=e[t[n]];this.outputShape=a,this.dispatchLayout={x:[0],y:[1]},this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[1,1,1]),this.shaderKey=\"transposeShared\"}getUserCode(){return v.assert(this.workgroupSize[0]===this.workgroupSize[1],()=>`Must be a square tile, current tile shape is ${this.workgroupSize[0]} x ${this.workgroupSize[1]}`),`\n      const tileSize = ${this.workgroupSize[0]};\n      var<workgroup> tile : array<array<f32, ${this.workgroupSize[0]+1}>, ${this.workgroupSize[0]}>;\n      ${Ce()} {\n        var x = i32(workgroupId.x) * tileSize + i32(localId.x);\n        var y = i32(workgroupId.y) * tileSize + i32(localId.y);\n        let width = uniforms.outShape[0];\n        let height = uniforms.outShape[1];\n        if (x < width && y < height) {\n          tile[localId.y][localId.x] = f32(A[y * width + x]);\n        }\n        workgroupBarrier();\n\n        x = i32(workgroupId.y) * tileSize + i32(localId.x);\n        y = i32(workgroupId.x) * tileSize + i32(localId.y);\n        if (x < height && y < width) {\n          setOutputAtIndex((y * height + x), tile[localId.x]\n            [localId.y]);\n        }\n      }\n    `}},wie=class{constructor(e,t){this.variableNames=[\"A\"],this.workPerThread=1,this.workgroupSize=[64,1,1],this.size=!0;let a=new Array(e.length);for(let n=0;n<a.length;n++)a[n]=e[t[n]];this.outputShape=a,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[this.workPerThread,1,1]),this.newDim=t,this.shaderKey=`transpose_${t}`}getUserCode(){let e=ra(this.outputShape.length),t=kie(this.newDim);return`\n      ${Ce(\"index\")} {\n        for(var i = 0; i < ${this.workPerThread}; i = i + 1) {\n          let flatIndex = index * ${this.workPerThread} + i;\n          if(flatIndex < uniforms.size) {\n            let resRC = getCoordsFromIndex(flatIndex);\n            setOutputAtIndex(flatIndex, A[getIndexFromCoords${this.outputShape.length}D(\n              ${e}(${t}), uniforms.aShape)]);\n          }\n        }\n      }\n    `}};function kie(e){let t=e.length;if(t>6)throw Error(`Transpose for rank ${t} is not yet supported`);let a=new Array(t);for(let n=0;n<e.length;n++)a[e[n]]=`resRC.${yr(n)}`;return a.join()}function vr(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{perm:s}=n,i=a,o=r.shape.length,l=new Array(o);for(let p=0;p<l.length;p++)l[p]=r.shape[s[p]];if(a.shouldExecuteOnCPU([r])){let p=i.tensorMap.get(r.dataId).values,c=uie(p,r.shape,r.dtype,s,l);return a.makeTensorInfo(l,r.dtype,c)}if(r.shape.length===2&&v.arraysEqual(s,[1,0])){let p=new vie(r.shape,s);return i.runWebGPUProgram(p,[r],r.dtype)}let u=new wie(r.shape,s);return i.runWebGPUProgram(u,[r],r.dtype)}var Iie={kernelName:Ar,backendName:\"webgpu\",kernelFunc:vr},Sie=class{constructor(e,t){this.workgroupSize=[64,1,1],this.variableNames=[\"x\"],this.uniforms=\"reduceSize : i32,\",this.size=!0,this.inputShape=[e.batchSize,e.inSize];let[a]=T.computeOutAndReduceShapes(this.inputShape,[1]);this.outputShape=a.length===0?[1]:a,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,[1,1,1]),this.reduceType=t,this.shaderKey=`reduce_${t}`}getUserCode(){let e=\"\",t=\"0.0\";this.reduceType===\"min\"||this.reduceType===\"max\"?(e=`\n         if (isnan(candidate)) {\n          bestValue = uniforms.NAN;\n         } else if (!isnan(bestValue) && candidate ${this.reduceType===\"min\"?\"<\":\">\"} bestValue)\n           {  bestValue = candidate; }`,t=\"f32(x[offset])\"):this.reduceType===\"sum\"||this.reduceType===\"mean\"?e=\" bestValue = bestValue + candidate; \":this.reduceType===\"prod\"?(e=\" bestValue = bestValue * candidate; \",t=\"1.0\"):this.reduceType===\"all\"?(e=\" bestValue = f32(bestValue >= 1.0 && candidate >= 1.0); \",t=\"1.0\"):this.reduceType===\"any\"&&(e=\" bestValue = f32(bestValue >= 1.0 || candidate >= 1.0); \",t=\"0.0\");let a=this.reduceType===\"mean\"?\"setOutputAtIndex(outputIndex, bestValue / f32(uniforms.reduceSize));\":\"setOutputAtIndex(outputIndex, bestValue);\";return`\n       fn DIV_CEIL(a : u32, b : u32) -> u32 {\n        return ((a - 1u) / b + 1u);\n       }\n\n       ${`\n         var<workgroup> xBestValues : array<f32, ${this.workgroupSize[0]}>;\n       `}\n       fn getOffset(outputIndex : i32) -> i32 {\n         let outputCoords = getCoordsFromIndex(outputIndex);\n         let offset = ${this.outputShape.length===1?\"outputCoords\":\"outputCoords[0]\"} * uniforms.reduceSize;\n          return offset;\n       }\n       ${Ce(\"index\")} {\n         let outputIndex = index / i32(workgroupSizeX);\n         let offset = getOffset(outputIndex);\n         var bestValue = ${t};\n         let Length = uniforms.reduceSize;\n         let WorkPerThread = DIV_CEIL(u32(Length), workgroupSizeX);\n         for (var k = i32(localId.x); k < Length && outputIndex < uniforms.size;\n             k = k + i32(workgroupSizeX)) {\n           let candidate = f32(x[offset + k]);\n           ${e}\n         }\n         xBestValues[localId.x] = bestValue;\n         workgroupBarrier();\n\n         var reduceSize = min(u32(Length), workgroupSizeX);\n         for (var currentSize = reduceSize / 2u; reduceSize > 1u;\n             currentSize = reduceSize / 2u) {\n           let interval = DIV_CEIL(reduceSize, 2u);\n           if (localId.x < currentSize) {\n            let candidate = xBestValues[localId.x + interval];\n            ${e}\n            xBestValues[localId.x] = bestValue;\n           }\n           reduceSize = interval;\n           workgroupBarrier();\n         }\n\n         if (localId.x == 0u && outputIndex < uniforms.size) {\n          ${a}\n        }\n       }\n     `}};function ko(e,t,a,n,r){let s=e.shape.length,i=[],o=v.parseAxisParam(t,e.shape),l=o,u=T.getAxesPermutation(l,s),p=e;u!=null&&(p=vr({inputs:{x:e},attrs:{perm:u},backend:r}),l=T.getInnerMostAxes(l.length,s),i.push(p)),T.assertAxesAreInnerMostDims(n,l,s);let[c,d]=T.computeOutAndReduceShapes(p.shape,l),h=c;a&&(h=T.expandShapeToKeepDim(c,o));let f;if((n===\"max\"||n===\"prod\")&&r.shouldExecuteOnCPU([p])){let m=r.tensorMap.get(p.dataId).values;switch(n){case\"max\":let g=jse(m,v.sizeFromShape(d),h,e.dtype);f=r.makeTensorInfo(h,e.dtype,g);break;case\"prod\":let{outVals:x,outShape:A,outDtype:y}=Jse(p.shape,p.dtype,m,l);f=r.makeTensorInfo(A,y,x);break;default:throw new Error(`${n} CPU implementation is not yet supported.`)}}else{let m=v.sizeFromShape(d),g=v.sizeFromShape(p.shape)/m,x={windowSize:m,inSize:m,batchSize:g,outSize:1},A=n===\"mean\"?\"float32\":Hd(e.dtype),y=[{type:\"int32\",data:[m]}],b=new Sie(x,n),w=r.runWebGPUProgram(b,[p],A,y);i.push(w),f=Ie({inputs:{x:w},attrs:{shape:h},backend:r})}return i.forEach(m=>r.disposeData(m.dataId)),f}function Tie(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{keepDims:s,axis:i}=n;return ko(r,i,s,\"all\",a)}var Cie={kernelName:Zs,backendName:\"webgpu\",kernelFunc:Tie};function Nie(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{keepDims:s,axis:i}=n;return ko(r,i,s,\"any\",a)}var Eie={kernelName:Ys,backendName:\"webgpu\",kernelFunc:Nie},P8=class{constructor(e,t,a){this.workgroupSize=[64,1,1],this.variableNames=[\"x\"],this.uniforms=\"infinityValue : f32,\",this.size=!0;let n=[t];this.op=a===\"min\"?\"<\":\">\";let[r,s]=T.computeOutAndReduceShapes(e,n);this.outputShape=r.length===0?[1]:r,this.dispatchLayout=Ve(this.outputShape),v.sizeFromShape(s)<32||v.sizeFromShape(r)>1e3?(this.type=\"plain\",this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize)):(this.type=\"shared\",this.dispatch=Ne(this.dispatchLayout,this.outputShape,[1,1,1])),this.inputShape=e,this.shaderKey=`argMinMax_${this.op}_${this.type}`}getUserCode(){let e=()=>this.inputShape.length===1?\"uniforms.xShape\":`uniforms.xShape.${yr(this.inputShape.length-1)}`,t=()=>{let a=\"\";if(this.outputShape.length===1)this.inputShape.length!==1&&(a+=\"outputCoords,\");else for(let n=0;n<this.outputShape.length;n++)a+=`outputCoords.${yr(n)},`;return a};return this.type===\"shared\"?`\n      fn DIV_CEIL(a : u32, b : u32) -> u32 {\n        return ((a - 1u) / b + 1u);\n      }\n\n      ${`\n      var<workgroup> xBestIndices : array<i32, ${this.workgroupSize[0]}>;\n      var<workgroup> xBestValues : array<f32, ${this.workgroupSize[0]}>;\n    `}\n\n      ${Ce(\"index\")} {\n        let outputIndex = index / i32(workgroupSizeX);\n        let reduceLength = ${e()};\n\n        var bestIndex = i32(localId.x);\n        var bestValue = uniforms.infinityValue;\n        let outputCoords = getCoordsFromIndex(outputIndex);\n        for (var k = i32(localId.x); k < reduceLength && outputIndex < uniforms.size;\n            k = k + i32(workgroupSizeX)) {\n          let candidate = getX(${t()} k);\n          if (!isnan(candidate) && candidate ${this.op} bestValue) {\n            bestValue = candidate;\n            bestIndex = k;\n          }\n        }\n        xBestValues[localId.x] = bestValue;\n        xBestIndices[localId.x] = bestIndex;\n        workgroupBarrier();\n\n        var reduceSize = min(u32(reduceLength), workgroupSizeX);\n        for (var currentSize = reduceSize / 2u; reduceSize > 1u;\n            currentSize = reduceSize / 2u) {\n          let interval = DIV_CEIL(reduceSize, 2u);\n          if (localId.x < currentSize) {\n            let candidate = xBestValues[localId.x + interval];\n            if (candidate ${this.op} bestValue) {\n              bestValue = candidate;\n              xBestValues[localId.x] = bestValue;\n              xBestIndices[localId.x] = xBestIndices[localId.x + interval];\n            }\n          }\n          reduceSize = interval;\n          workgroupBarrier();\n        }\n\n        if (localId.x == 0u && outputIndex < uniforms.size) {\n          setOutputAtIndexI32(outputIndex, xBestIndices[localId.x]);\n        }\n      }\n    `:`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let outputCoords = getCoordsFromIndex(index);\n          var bestIndex = 0;\n          var bestValue = getX(${t()} 0);\n          let reduceLength = ${e()};\n          for (var i = 1; i < reduceLength; i++) {\n            let candidate = getX(${t()} i);\n            if (candidate ${this.op} bestValue) {\n              bestValue = candidate;\n              bestIndex = i;\n            }\n          }\n          setOutputAtIndexI32(index, bestIndex);\n        }\n      }\n      `}};function Rie(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s}=n,i=v.parseAxisParam(s,r.shape),o=T.getAxesPermutation(i,r.shape.length),l=r,u=[];o!=null&&(l=vr({inputs:{x:r},backend:a,attrs:{perm:o}}),u.push(l),i=T.getInnerMostAxes(i.length,l.shape.length)),T.assertAxesAreInnerMostDims(\"argMax\",[i[0]],l.shape.length);let p=new P8(l.shape,i[0],\"max\"),c=[{type:\"float32\",data:[Number.NEGATIVE_INFINITY]}],d=a.runWebGPUProgram(p,[l],\"int32\",c);return u.forEach(h=>a.disposeData(h.dataId)),d}var Mie={kernelName:Js,backendName:\"webgpu\",kernelFunc:Rie};function $ie(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s}=n,i=v.parseAxisParam(s,r.shape),o=T.getAxesPermutation(i,r.shape.length),l=r,u=[];o!=null&&(l=vr({inputs:{x:r},backend:a,attrs:{perm:o}}),u.push(l),i=T.getInnerMostAxes(i.length,l.shape.length)),T.assertAxesAreInnerMostDims(\"argMin\",[i[0]],l.shape.length);let p=new P8(l.shape,i[0],\"min\"),c=[{type:\"float32\",data:[Number.POSITIVE_INFINITY]}],d=a.runWebGPUProgram(p,[l],\"int32\",c);return u.forEach(h=>a.disposeData(h.dataId)),d}var _ie={kernelName:kd,backendName:\"webgpu\",kernelFunc:$ie},Pie=it({opType:de.ASIN}),Fie={kernelName:Sl,backendName:\"webgpu\",kernelFunc:Pie},Oie=it({opType:de.ASINH}),Die={kernelName:Tl,backendName:\"webgpu\",kernelFunc:Oie},zie=it({opType:de.ATAN}),Lie={kernelName:Cl,backendName:\"webgpu\",kernelFunc:zie},Bie=ua({opType:De.ATAN2}),Wie={kernelName:El,backendName:\"webgpu\",kernelFunc:Bie},Vie=it({opType:de.ATANH}),Uie={kernelName:Nl,backendName:\"webgpu\",kernelFunc:Vie},Kx=class{constructor(e,t){this.variableNames=[\"x\"],this.uniforms=\"stride : vec2<i32>, pad : vec2<i32>, dilation : vec2<i32>, convDims : vec2<i32>, filterDims : vec2<i32>,\",this.workgroupSize=[128,1,1],this.size=!0,this.outputShape=e.outShape,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=`pool2D_${t}`,this.poolType=t}getUserCode(){let e=\"resultValue = max(value, resultValue);\";this.poolType===\"avg\"&&(e=\"resultValue = resultValue + value; count = count + 1.0;\");let t=\"resultValue\";return this.poolType===\"avg\"&&(t=\"resultValue / count\"),`\n      ${Ce(\"index\")} {\n      if (index < uniforms.size) {\n        let coords = getCoordsFromIndex(index);\n          let batch = coords[0];\n          let xRCCorner = vec2<i32>(coords.yz) * uniforms.stride - uniforms.pad;\n          let xRCorner = xRCCorner.x;\n          let xCCorner = xRCCorner.y;\n\n          var resultValue = ${this.poolType===\"avg\"?\"0.0\":\"-1.0 / pow(10.0, -20.0)\"};\n          var count = 0.0;\n\n          for (var wR = 0; wR < uniforms.filterDims.x; wR = wR + uniforms.dilation.x) {\n            let xR = xRCorner + wR;\n\n            if (xR < 0 || xR >= uniforms.convDims.x) {\n              continue;\n            }\n\n            for (var wC = 0; wC < uniforms.filterDims.y; wC = wC + uniforms.dilation.y) {\n              let xC = xCCorner + wC;\n              if (xC < 0 || xC >= uniforms.convDims.y) {\n                continue;\n              }\n\n              let value = getX(batch, xR, xC, coords[3]);\n              ${e}\n            }\n          }\n\n          setOutputAtIndex(index, ${t});\n        }\n      }\n    `}},Gie=class{constructor(e){this.variableNames=[\"x\"],this.uniforms=\"stride : vec2<i32>,\",this.workgroupSize=[256,1,1],this.size=!0,this.outputShape=e.outShape,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=\"poolWithFilterSizeEqualsOne\"}getUserCode(){return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let coords = getCoordsFromIndex(index);\n          let batch = coords[0];\n          let d = coords[3];\n\n          let xRCCorner = coords.yz * uniforms.stride;\n          let xRCorner = xRCCorner.x;\n          let xCCorner = xRCCorner.y;\n\n          let value = getX(batch, xRCorner, xCCorner, d);\n          setOutputAtIndex(index, value);\n        }\n      }\n    `}};function W3(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{reductionIndices:s,keepDims:i}=n;return ko(r,s,i,\"max\",a)}var Hie={kernelName:Mi,backendName:\"webgpu\",kernelFunc:W3};function F8(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{keepDims:s,axis:i}=n;return ko(r,i,s,\"mean\",a)}var jie={kernelName:Pi,backendName:\"webgpu\",kernelFunc:F8};function O8(e,t,a,n){if(t.filterWidth===1&&t.filterHeight===1&&v.arraysEqual(t.inShape,t.outShape))return Ya({inputs:{x:e},backend:n});if(t.filterWidth===t.inWidth&&t.filterHeight===t.inHeight&&t.batchSize===1&&t.padInfo.type===\"VALID\"){let i=e.shape.length,o=Ie({inputs:{x:e},backend:n,attrs:{shape:[e.shape[i-3]*e.shape[i-2],e.shape[i-1]]}}),l;a===\"avg\"?l=F8({inputs:{x:o},backend:n,attrs:{axis:0,keepDims:!1}}):(v.assert(a===\"max\",()=>`Invalid pool type ${a}`),l=W3({inputs:{x:o},backend:n,attrs:{reductionIndices:0,keepDims:!1}}));let u=Ie({inputs:{x:l},backend:n,attrs:{shape:t.outShape}});return n.disposeData(o.dataId),n.disposeData(l.dataId),u}let r,s=[{type:\"int32\",data:[t.strideHeight,t.strideWidth]}];return t.filterHeight===1&&t.filterWidth===1?r=new Gie(t):(a===\"avg\"?r=new Kx(t,\"avg\"):(v.assert(a===\"max\",()=>`Invalid pool type ${a}`),r=new Kx(t,\"max\")),s.push({type:\"int32\",data:[t.padInfo.top,t.padInfo.left]},{type:\"int32\",data:[t.dilationHeight,t.dilationWidth]},{type:\"int32\",data:[t.inHeight,t.inWidth]},{type:\"int32\",data:[t.effectiveFilterHeight,t.effectiveFilterWidth]})),n.runWebGPUProgram(r,[e],e.dtype,s)}function qie(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{filterSize:s,strides:i,pad:o,dimRoundingMode:l}=n,u=1,p=T.computePool2DInfo(r.shape,s,i,u,o,l);return O8(r,p,\"avg\",a)}var Xie={kernelName:Qs,backendName:\"webgpu\",kernelFunc:qie};function Kie(e){let{inputs:t,backend:a,attrs:n}=e,{a:r,b:s}=t,{transposeA:i,transposeB:o}=n;return Hh({a:r,b:s,transposeA:i,transposeB:o,backend:a})}var Zie={kernelName:ei,backendName:\"webgpu\",kernelFunc:Kie},Yie=class{constructor(e,t){this.variableNames=[\"source\"],this.workPerThread=1,this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=t,this.rank=t.length,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[this.workPerThread,1,1]),this.start=e,this.uniforms=`start : ${ra(e.length)}, `,this.shaderKey=\"slice\"}getUserCode(){let e=ra(this.rank),t=Jie(this.rank),a;return this.start.length===1?a=this.outputShape.map((n,r)=>\"sourceLoc = uniforms.start + coords;\"):a=this.outputShape.map((n,r)=>`sourceLoc.${F1[r]} = uniforms.start.${yr(r)} + coords.${F1[r]};`),`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          var sourceLoc : ${e};\n          let coords = getCoordsFromIndex(index);\n          ${a.join(`\n`)}\n          setOutputAtIndex(index, getSource(${t}));\n        }\n      }\n    `}},F1=[\"x\",\"y\",\"z\",\"w\",\"u\",\"v\"];function Jie(e){if(e===1)return\"sourceLoc\";if(e<=6)return F1.slice(0,e).map(t=>`sourceLoc.${t}`).join(\",\");throw Error(`Slicing for rank ${e} is not yet supported`)}function Au(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{begin:s,size:i}=n,[o,l]=It.parseSliceParams(r,s,i);if(It.assertParamsValid(r,o,l),a.shouldExecuteOnCPU([r])||r.dtype===\"string\"){let c=a.tensorMap.get(r.dataId),d=nie(c.values,o,l,r.shape,r.dtype);return a.makeTensorInfo(l,r.dtype,d)}if(v.sizeFromShape(l)===0)return a.makeTensorInfo(l,r.dtype,[]);let u=new Yie(o,l),p=[{type:\"int32\",data:o}];return a.runWebGPUProgram(u,[r],r.dtype,p)}var Qie={kernelName:Zl,backendName:\"webgpu\",kernelFunc:Au},eoe=e=>{let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockShape:s,crops:i}=n;v.assert(r.shape.length<=4,()=>\"batchToSpaceND for rank > 4 with a WebGPU backend not implemented yet\");let o=s.reduce((A,y)=>A*y),l=T.getReshaped(r.shape,s,o),u=T.getPermuted(l.length,s.length),p=T.getReshapedPermuted(r.shape,s,o),c=T.getSliceBeginCoords(i,s.length),d=T.getSliceSize(p,i,s.length),h=[],f=Ie({inputs:{x:r},backend:a,attrs:{shape:l}}),m=vr({inputs:{x:f},backend:a,attrs:{perm:u}}),g=Ie({inputs:{x:m},backend:a,attrs:{shape:p}}),x=Au({inputs:{x:g},backend:a,attrs:{begin:c,size:d}});return h.push(f),h.push(m),h.push(g),h.forEach(A=>a.disposeData(A.dataId)),x},toe={kernelName:Rl,backendName:\"webgpu\",kernelFunc:eoe},aoe=`\n  fn bincount_write(index: i32, value: f32) {\n    var oldValue = atomicLoad(& (result[index]));\n    var exchanged = false;\n    for (; !exchanged;) {\n      let newValueF32 = bitcast<f32>(oldValue) + value;\n      let newValue = bitcast<i32>(newValueF32);\n      let res = atomicCompareExchangeWeak(\n          &(result[index]), oldValue, newValue);\n      oldValue = res.old_value;\n      exchanged = res.exchanged;\n    }\n  }\n`,noe=`\n  fn bincount_write(index: i32, value: f32) {\n    result[index] = value;\n  }\n`,D8=class{constructor(e,t,a=!1){this.outputShape=[],this.variableNames=[\"x\"],this.uniforms=\"binCountSize : i32,\",this.workgroupSize=[64,1,1],this.atomic=!0,this.hasWeights=!0,this.binaryOutput=!1,this.outputShape=e,this.rank=e.length,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.binaryOutput=a,a&&(this.atomic=!1),this.hasWeights=t,this.hasWeights&&this.variableNames.push(\"w\"),this.shaderKey=`bincount_${this.hasWeights}_${this.binaryOutput}_${this.rank}`}getUserCode(){return`\n    ${this.binaryOutput?noe:aoe}\n  ${Ce(\"index\")} {\n    ${this.rank===1?`if (index < uniforms.xShape) {\n      let indexVal = i32(getX(index));\n      if (indexVal < uniforms.binCountSize) {\n        let value = ${this.binaryOutput?1:this.hasWeights?\"f32(getW(index))\":\"1.\"};\n        bincount_write(indexVal, value);\n      }\n    }`:`let coord = getCoordsFromIndex(index);\n    if (coordsInBounds2D(coord, uniforms.xShape)) {\n      let indexVal = i32(getX(coord[0], coord[1]));\n      if (indexVal < uniforms.binCountSize) {\n        let value = ${this.binaryOutput?1:this.hasWeights?\"f32(getW(coord[0], coord[1]))\":\"1.\"};\n        bincount_write(coord.x * uniforms.binCountSize + indexVal, value);\n      }\n    }`}\n  }\n  `}};function roe(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,weights:s}=t,{size:i}=n,o=v.sizeFromShape(r.shape),l=v.sizeFromShape(s.shape)>0,u=[i],p=s.dtype,c=Cr({backend:a,attrs:{shape:u,value:0,dtype:p}}),d=new D8([o],l),h=[{type:\"int32\",data:[i]}],f=l?[r,s]:[r];return a.runWebGPUProgram(d,f,p,h,c)}var soe={kernelName:Id,backendName:\"webgpu\",kernelFunc:roe},z8=ua({opType:De.NOT_EQUAL,dtype:\"bool\",cpuKernelImpl:Yse}),ioe={kernelName:Li,backendName:\"webgpu\",kernelFunc:z8};function gp(e){let{inputs:t,backend:a}=e,{input:n}=t,r=a.tensorMap.get(n.dataId);return Ya({inputs:{x:r.complexTensorInfos.real},backend:a})}var ooe={kernelName:Md,backendName:\"webgpu\",kernelFunc:gp};function loe(e,t){let a=new mp(e.shape,de.TO_INT),n=t.runWebGPUProgram(a,[e],\"int32\");return{dataId:n.dataId,shape:n.shape,dtype:n.dtype}}function O1(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{dtype:s}=n;if(s===\"complex64\"){if(r.dtype===\"complex64\")return Ya({inputs:{x:r},backend:a});let i=fn(r.shape),o=O1({inputs:{x:r},backend:a,attrs:{dtype:\"float32\"}}),l=wo({inputs:{real:o,imag:i},backend:a});return i.dispose(),a.disposeData(o.dataId),l}if(r.dtype===\"complex64\"){let i=gp({inputs:{input:r},backend:a}),o=O1({inputs:{x:i},backend:a,attrs:{dtype:s}});return a.disposeData(i.dataId),o}if(!v.hasEncodingLoss(r.dtype,s)){let i=Ya({inputs:{x:r},backend:a});return{dataId:i.dataId,shape:i.shape,dtype:s}}if(a.shouldExecuteOnCPU([r])){let i=a.tensorMap.get(r.dataId).values,[o,l,u]=$se(i,r.shape,r.dtype,s);return a.makeTensorInfo(o,l,u)}if(s===\"int32\")return loe(r,a);if(s===\"bool\"){let i=a.makeTensorInfo([],\"bool\",v.getTypedArrayFromDType(\"bool\",1)),o=z8({inputs:{a:r,b:i},backend:a});return a.disposeData(i.dataId),o}throw new Error(`Error in Cast: failed to cast ${r.dtype} to ${s}`)}var uoe={kernelName:ti,backendName:\"webgpu\",kernelFunc:O1},doe=it({opType:de.CEIL,cpuKernelImpl:_se}),poe={kernelName:ai,backendName:\"webgpu\",kernelFunc:doe},coe=class{constructor(e){this.variableNames=[\"A\"],this.uniforms=\"minVal : f32, maxVal : f32,\",this.workPerThread=4,this.workgroupSize=[64,1,1],this.isVec4=!0,this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[this.workPerThread,1,1]),this.shaderKey=\"clipVec4\"}getUserCode(){return`\n      ${Ce(\"index\")} {\n        if(index < uniforms.size) {\n          let value = getAByOutputIndex(index);\n          var clampedValue : vec4<f32>;\n          for (var i = 0; i < 4; i = i + 1) {\n            if (isnan(value[i])) {\n              clampedValue[i] = value[i];\n            } else {\n              clampedValue[i] = clamp(value[i], uniforms.minVal, uniforms.maxVal);\n            }\n          }\n\n          setOutputAtIndex(index, clampedValue);\n        }\n      }\n    `}},hoe=class{constructor(e){this.variableNames=[\"A\"],this.uniforms=\"minVal : f32, maxVal : f32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=\"clip\"}getUserCode(){return`\n      ${Ce(\"index\")} {\n        if(index < uniforms.size) {\n          let value = getAByOutputIndex(index);\n          if (isnan(value)) {\n            setOutputAtIndex(index, value);\n            return;\n          }\n          setOutputAtIndex(index, clamp(value, uniforms.minVal, uniforms.maxVal));\n        }\n      }\n    `}};function foe(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{clipValueMin:s,clipValueMax:i}=n,o,l=[{type:\"float32\",data:[s]},{type:\"float32\",data:[i]}];return v.sizeFromShape(r.shape)%4===0?o=new coe(r.shape):o=new hoe(r.shape),a.runWebGPUProgram(o,[r],r.dtype,l)}var moe={kernelName:as,backendName:\"webgpu\",kernelFunc:foe},goe=class{constructor(e){this.uniforms=\"\",this.workPerThread=1,this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=T.computeOutShape(e,1),this.variableNames=e.map((t,a)=>`T${a}`),this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[this.workPerThread,1,1]),this.offsetLength=e.length-1;for(let t=0;t<this.offsetLength;t++)this.uniforms+=`offset${t} : i32,`;this.shaderKey=\"concat\"}getUserCode(){let e=[];if(this.offsetLength>0){e.push(\"if (yC < uniforms.offset0){ setOutputAtCoords(coords.x, coords.y, getT0(yR, yC)); }\");for(let n=1;n<this.offsetLength;n++)e.push(`else if (yC < uniforms.offset${[n]}){ setOutputAtCoords(coords.x, coords.y, getT${n}(yR, yC - uniforms.offset${n-1})); }`);let t=this.offsetLength,a=this.offsetLength-1;e.push(`else { setOutputAtCoords(coords.x, coords.y, getT${t}(yR, yC - uniforms.offset${a})); }`)}else e.push(\"setOutputAtCoords(coords.x, coords.y, getT0(yR, yC));\");return`\n      ${Ce(\"index\")} {\n        for(var i = 0; i < ${this.workPerThread}; i = i + 1) {\n          let flatIndex = index * ${this.workPerThread} + i;\n          if(flatIndex < uniforms.size) {\n            let coords = getCoordsFromIndex(flatIndex);\n            let yR = coords.x;\n            let yC = coords.y;\n\n            ${e.join(`\n        `)}\n          }\n        }\n      }\n    `}};function jh(e){let{inputs:t,backend:a}=e,{input:n}=t,r=a.tensorMap.get(n.dataId);return Ya({inputs:{x:r.complexTensorInfos.imag},backend:a})}var xoe={kernelName:Rd,backendName:\"webgpu\",kernelFunc:jh};function Ju(e,t,a){let n=e[0].dtype;if(n===\"complex64\"){let f=e.map(y=>gp({inputs:{input:y},backend:a})),m=e.map(y=>jh({inputs:{input:y},backend:a})),g=Ju(f,t,a),x=Ju(m,t,a),A=wo({inputs:{real:g,imag:x},backend:a});return f.forEach(y=>a.disposeData(y.dataId)),m.forEach(y=>a.disposeData(y.dataId)),a.disposeData(g.dataId),a.disposeData(x.dataId),A}let r=a.shouldExecuteOnCPU(e);if(n===\"string\"&&(r=!0),r){let f=e.map(w=>{let S=[-1,v.sizeFromShape(w.shape.slice(t))];return Ie({inputs:{x:w},backend:a,attrs:{shape:S}})}),m=f.map(w=>({vals:a.readSync(w.dataId),shape:w.shape})),g=T.computeOutShape(f.map(w=>w.shape),1),x=f[0].shape[0]===1,A=Pse(m,g,n,x),y=T.computeOutShape(e.map(w=>w.shape),t),b=a.makeTensorInfo(y,n,A);return f.forEach(w=>a.disposeData(w.dataId)),b}let s=a.device.limits.maxStorageBuffersPerShaderStage-1;if(e.length>s){let f=[];for(let g=0;g<e.length;g+=s){let x=e.slice(g,g+s);f.push(Ju(x,t,a))}let m=Ju(f,t,a);for(let g of f)a.disposeData(g.dataId);return m}let{tensors2D:i,outShape:o}=Aoe(e,t,a),l=i.map(f=>f.shape),u=new goe(l),p=[],c=new Array(l.length-1);if(c.length>0){c[0]=l[0][1],p.push({type:\"int32\",data:[c[0]]});for(let f=1;f<c.length;f++)c[f]=c[f-1]+l[f][1],p.push({type:\"int32\",data:[c[f]]})}let d=a.runWebGPUProgram(u,i,i[0].dtype,p);i.forEach(f=>a.disposeData(f.dataId));let h=Ie({inputs:{x:d},backend:a,attrs:{shape:o}});return a.disposeData(d.dataId),h}function Aoe(e,t,a){let n=T.computeOutShape(e.map(r=>r.shape),t);return{tensors2D:e.map(r=>Ie({inputs:{x:r},backend:a,attrs:{shape:[v.sizeFromShape(r.shape.slice(0,t)),v.sizeFromShape(r.shape.slice(t))]}})),outShape:n}}function L8(e){let{inputs:t,backend:a,attrs:n}=e,{axis:r}=n,s=v.parseAxisParam(r,t[0].shape)[0],i=t.map(u=>u.shape);T.assertParamsConsistent(i,s);let o=T.computeOutShape(t.map(u=>u.shape),s);if(v.sizeFromShape(o)===0)return a.makeTensorInfo(o,t[0].dtype,[]);let l=t.filter(u=>v.sizeFromShape(u.shape)>0);return l.length===1?Ya({inputs:{x:l[0]},backend:a}):Ju(l,s,a)}var yoe={kernelName:Ml,backendName:\"webgpu\",kernelFunc:L8};function boe(e,t,a,n,r=!1,s=null,i=!1,o=4,l=4,u=4){let p=E=>{switch(E){case 1:return\"resData = x[xIndex];\";case 3:return\"resData = vec3<f32>(x[xIndex], x[xIndex + 1], x[xIndex + 2]);\";case 4:return\"resData = x[xIndex / 4];\";default:throw new Error(`innerElementSize ${E} is not supported.`)}},c=E=>{switch(E){case 1:return\"return W[row * uniforms.wShape[3] + colIn];\";case 4:return\"return W[row * uniforms.wShape[3] / 4 + colIn];\";default:throw new Error(`innerElementSize ${E} is not supported.`)}},d=e?`\n      let coord = vec4<i32>(batch, xRow, xCol, xCh);\n      `:`\n      let coord = vec4<i32>(batch, xCh, xRow, xCol);\n      `,h=e?`\n      let coords = vec4<i32>(\n        batch,\n        row / outWidth,\n        row % outWidth,\n        col);\n      `:`\n      let coords = vec4<i32>(\n        batch,\n        row,\n        col / outWidth,\n        col % outWidth);\n      `,f=e?\"uniforms.xShape[1]\":\"uniforms.xShape[2]\",m=e?\"uniforms.xShape[2]\":\"uniforms.xShape[3]\",g=e?\"row\":\"col\",x=e?\"col\":\"row\",A=`\n      let inChannels = uniforms.wShape[2];\n      let outWidth = ${e?\"uniforms.outShape[2]\":\"uniforms.outShape[3]\"};\n      let outRow = ${g} / outWidth;\n      let outCol = ${g} % outWidth;\n\n      let WRow = ${x} / (uniforms.filterDims[1] * inChannels);\n      let WCol = ${x} / inChannels % uniforms.filterDims[1];\n      let xRow = outRow * uniforms.stride[0] + uniforms.dilation[0] * WRow - uniforms.pad[0];\n      let xCol = outCol * uniforms.stride[1] + uniforms.dilation[1] * WCol - uniforms.pad[1];\n      let xCh = ${x} % inChannels;\n      var resData = ${Mt(o)}(0.0);\n      // The bounds checking is always needed since we use it to pad zero for\n      // the 'same' padding type.\n      if (xRow >= 0 && xRow < ${f} && xCol >= 0 && xCol < ${m}) {\n        ${d}\n        let xIndex = getIndexFromCoords4D(coord, uniforms.xShape);\n        ${p(o)}\n      }\n      return resData;`,y=e?t&&n?`\n      let col = colIn * ${o};\n      ${A}`:`\n      let col = colIn * ${o};\n      if (row < uniforms.dimAOuter && col < uniforms.dimInner) {\n        ${A}\n      }\n      return ${Mt(o)}(0.0);`:n&&a?`\n      let col = colIn * ${o};\n      ${A}`:`\n      let col = colIn * ${o};\n      if (row < uniforms.dimInner && col < uniforms.dimBOuter) {\n        ${A}\n      }\n      return ${Mt(o)}(0.0);`,b=`${c(l)}`,w=Mt(u),S=Mt(e?o:l),C=Mt(e?l:o);return`\n      ${Tr(s,i,u===4,4)}\n      fn mm_readA(batch: i32, row : i32, colIn : i32) -> ${S} {\n        ${e?y:b}\n      }\n\n      fn mm_readB(batch: i32, row : i32, colIn : i32) -> ${C} {\n        ${e?b:y}\n      }\n\n      fn mm_write(batch: i32, row : i32, colIn : i32, valueIn : ${w}) {\n        let col = colIn * ${u};\n        if (row < uniforms.dimAOuter && col < uniforms.dimBOuter)\n        {\n        var value = valueIn;\n        let outWidth = ${e?\"uniforms.outShape[2]\":\"uniforms.outShape[3]\"};\n        ${h}\n        ${vo(r,s)}\n        setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value);\n        }\n      }`}var voe=class{constructor(e,t,a,n,r=!1,s=null,i=!1,o=!1){this.variableNames=[\"x\",\"W\"],this.uniforms=\"filterDims : vec2<i32>, pad : vec2<i32>, stride : vec2<i32>, dilation : vec2<i32>, dimAOuter : i32, dimBOuter : i32, dimInner : i32,\",this.outputShape=e.outShape,this.isChannelsLast=e.dataFormat===\"channelsLast\",this.isVec4=((e.inChannels%4===0||e.inChannels%3===0)&&this.isChannelsLast||e.outWidth%4===0&&!this.isChannelsLast)&&e.outChannels%4===0,this.dispatchLayout=this.isChannelsLast?{x:[3],y:[1,2],z:[0]}:{x:[2,3],y:[1],z:[0]},this.workgroupSize=F3(this.dispatchLayout,this.outputShape,this.isVec4),this.elementsPerThread=O3(this.dispatchLayout,this.outputShape,this.isVec4),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,this.elementsPerThread),this.isVec4?(this.isChannelsLast&&e.inChannels%4!==0?(this.innerElementSize=3,this.variableTypes=[\"f32\",\"vec4<f32>\"]):(this.innerElementSize=4,this.variableTypes=[\"vec4<f32>\",\"vec4<f32>\"]),r&&(this.variableNames.push(\"bias\"),this.variableTypes.push(\"vec4<f32>\")),i&&(this.variableNames.push(\"preluActivationWeights\"),this.variableTypes.push(\"vec4<f32>\"))):(this.innerElementSize=this.elementsPerThread[0],r&&this.variableNames.push(\"bias\"),i&&this.variableNames.push(\"preluActivationWeights\")),this.sequentialAccessByThreads=o,this.addBias=r,this.activation=s,this.hasPreluActivationWeights=i,this.tileAOuter=this.workgroupSize[1]*this.elementsPerThread[1],this.tileBOuter=this.workgroupSize[0]*this.elementsPerThread[0],this.tileInner=Math.max(this.workgroupSize[0]*this.innerElementSize,this.workgroupSize[1]),this.fitAOuter=t%this.tileAOuter===0,this.fitBOuter=a%this.tileBOuter===0,this.fitInner=n%this.tileInner===0,this.shaderKey=`conv2DMM_${this.elementsPerThread}_${this.activation}}_${this.fitAOuter}_${this.fitBOuter}_${this.fitInner}_${this.isVec4}_${this.innerElementSize}_${this.isChannelsLast}_${this.sequentialAccessByThreads}`}getUserCode(){let e=this.isVec4?Uh(this.elementsPerThread,this.workgroupSize,!this.isChannelsLast,this.tileInner):Gh(this.elementsPerThread,this.workgroupSize,!this.isChannelsLast,this.tileInner,!1,null,this.sequentialAccessByThreads),t=this.isVec4?[this.innerElementSize,4,4]:[1,1,1];return`\n    ${boe(this.isChannelsLast,this.fitAOuter,this.fitBOuter,this.fitInner,this.addBias,this.activation,this.hasPreluActivationWeights,t[0],t[1],t[2])}\n    ${e}\n  `}},woe=class{constructor(e,t=!1,a=null,n=!1){this.variableNames=[\"x\",\"W\"],this.uniforms=\"filterDims: vec2<i32>, pad: vec2<i32>, stride: vec2<i32>, dilation: vec2<i32>,\",this.workgroupSize=[4,4,8],this.outputShape=e.outShape,this.isChannelsLast=e.dataFormat===\"channelsLast\",this.dispatchLayout=this.isChannelsLast?{x:[2],y:[1],z:[0,3]}:{x:[3],y:[2],z:[0,1]},this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.addBias=t,this.activation=a,this.hasPreluActivationWeights=n,t&&this.variableNames.push(\"bias\"),n&&this.variableNames.push(\"preluActivationWeights\"),this.shaderKey=`conv2dnaive_${this.activation}_${this.isChannelsLast}`}getUserCode(){return`\n       ${Tr(this.activation,this.hasPreluActivationWeights,!1,4)}\n       fn readInp(batch : i32, row : i32, col : i32, chan : i32) -> f32{\n         let coords = vec4<i32>(batch, row, col, chan);\n         if (coordsInBounds4D(coords, uniforms.xShape)) {\n           return  getX(batch, row, col, chan);\n         } else {\n          return 0.0;\n         }\n       }\n       fn readFilt(row : i32, col : i32, xChannel : i32, outChannel : i32) -> f32{\n         let coords = vec4<i32>(row, col, xChannel, outChannel);\n         if(coordsInBounds4D(coords, uniforms.wShape)) {\n           return getW(row, col, xChannel, outChannel);\n          } else {\n            return 0.0;\n          }\n       }\n       fn writeResult(batch : i32, row : i32, col : i32, chan : i32, valueIn : f32) {\n         let coords = ${this.isChannelsLast?\"vec4<i32>(batch, row, col, chan);\":\"vec4<i32>(batch, chan, row, col);\"}\n         if (coordsInBounds4D(coords, uniforms.outShape)) {\n           var value = valueIn;\n           ${vo(this.addBias,this.activation)}\n           setOutputAtCoords(coords.x, coords.y, coords.z, coords.w, value);\n         }\n       }\n       ${Ce(\"index\")} {\n         let coords = getOutputCoords();\n         let batch = coords[0];\n         let outChannel = ${this.isChannelsLast?\"coords[3];\":\"coords[1];\"}\n         let outRow = ${this.isChannelsLast?\"coords[1];\":\"coords[2];\"}\n         let outCol = ${this.isChannelsLast?\"coords[2];\":\"coords[3];\"}\n         var acc : f32 = 0.0;\n         for (var row = 0; row < uniforms.filterDims[0]; row = row + 1) {\n           for (var col = 0; col < uniforms.filterDims[1]; col = col + 1) {\n             let xRow = outRow * uniforms.stride[0] + uniforms.dilation[0] * row - uniforms.pad[0];\n             let xCol = outCol * uniforms.stride[1] + uniforms.dilation[1] * col - uniforms.pad[1];\n             for (var xChannel = 0; xChannel < ${this.isChannelsLast?\"uniforms.xShape[3];\":\"uniforms.xShape[1];\"} xChannel = xChannel + 1) {\n               ${this.isChannelsLast?\"let v = readInp(batch, xRow, xCol, xChannel);\":\"let v = readInp(batch, xChannel, xRow, xCol);\"}\n               let f = readFilt(row, col, xChannel, outChannel);\n               acc = acc + v * f;\n             }\n           }\n         }\n         writeResult(batch, outRow, outCol, outChannel, acc);\n       }\n     `}},koe=class{constructor(e,t){this.variableNames=[\"x\"],this.uniforms=`pad : vec2<i32>, stride : vec2<i32>, dilation : vec2<i32>, outWidth : i32, itemsPerBlockRow : i32,\n       inChannels : i32,`,this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.isChannelsLast=t,this.shaderKey=`im2col_${this.isChannelsLast}`}getUserCode(){let e=this.isChannelsLast?1:2,t=this.isChannelsLast?2:3,a=this.isChannelsLast?\"coords[1]\":\"coords[2]\",n=this.isChannelsLast?\"coords[2]\":\"coords[1]\",r=this.isChannelsLast?\"getX(batch, xRow, xCol, ch)\":\"getX(batch, ch, xRow, xCol)\";return`\n    ${Ce(\"index\")} {\n      let coords = getCoordsFromIndex(index);\n      if(index < uniforms.size) {\n        let batch = coords[0];\n        let row = ${a};\n        let col = ${n};\n        let offsetY = (row / uniforms.outWidth) * uniforms.stride[0] - uniforms.pad[0];\n        let xRow = offsetY + uniforms.dilation[0] * (col / uniforms.itemsPerBlockRow);\n        var value = 0.0;\n        if(xRow < uniforms.xShape[${e}] && xRow >= 0) {\n          let offsetX = (row % uniforms.outWidth) * uniforms.stride[1] -\n              uniforms.pad[1];\n          let xCol = offsetX + uniforms.dilation[1] * ((col %\n              uniforms.itemsPerBlockRow) / uniforms.inChannels);\n          let ch = col % uniforms.inChannels;\n          if(xCol < uniforms.xShape[${t}] && xCol >= 0) {\n            value = ${r};\n          }\n        }\n        setOutputAtIndex(index, value);\n      }\n    }\n   `}};function Wc(e,t){let a=e.length;return a>=3?t?[...e.slice(0,-3),e[a-3]*e[a-2],e[a-1]]:[...e.slice(0,-3),e[a-3],e[a-2]*e[a-1]]:!t&&a===1&&e[0]>1?[e[0],1]:null}function Ioe({x:e,filter:t,convInfo:a,backend:n,bias:r=null,preluActivationWeights:s=null,leakyreluAlpha:i=0,activation:o=null}){let l=a.dataFormat===\"channelsLast\",u=!l,p=!1,c=l&&a.filterHeight===a.inHeight&&a.filterWidth===a.inWidth&&a.padInfo.type===\"VALID\",d=[],h,f;if(c){let x=a.inHeight*a.inWidth*a.inChannels;h=Ie({inputs:{x:e},backend:n,attrs:{shape:[1,a.batchSize,x]}}),f=Ie({inputs:{x:t},backend:n,attrs:{shape:[1,x,a.outChannels]}})}else h=Ie({inputs:{x:e},backend:n,attrs:{shape:l?[a.batchSize,a.inHeight*a.inWidth,a.inChannels]:[a.batchSize,a.inChannels,a.inHeight*a.inWidth]}}),f=Ie({inputs:{x:t},backend:n,attrs:{shape:[1,a.inChannels,a.outChannels]}});if(d.push(h),d.push(f),s!=null){let x=Wc(s.shape,l);x!=null&&(s=Ie({inputs:{x:s},backend:n,attrs:{shape:x}}),d.push(s))}if(r!=null){let x=Wc(r.shape,l);x!=null&&(r=Ie({inputs:{x:r},backend:n,attrs:{shape:x}}),d.push(r))}let m=Hh({a:l?h:f,b:l?f:h,transposeA:u,transposeB:p,backend:n,bias:r,activation:o,preluActivationWeights:s,leakyreluAlpha:i}),g=Ie({inputs:{x:m},backend:n,attrs:{shape:a.outShape}});d.push(m);for(let x of d)n.disposeData(x.dataId);return g}function Soe({x:e,filter:t,convInfo:a,backend:n,bias:r=null,preluActivationWeights:s=null,leakyreluAlpha:i=0,activation:o=null}){let{filterWidth:l,filterHeight:u,inChannels:p,strideWidth:c,strideHeight:d,padInfo:h,outWidth:f,outHeight:m,dilationWidth:g,dilationHeight:x,dataFormat:A}=a,y=A===\"channelsLast\",b=l*u*p,w=m*f,S=y?[a.batchSize,w,b]:[a.batchSize,b,w],C=new koe(S,y),E=[{type:\"int32\",data:[h.top,h.left]},{type:\"int32\",data:[d,c]},{type:\"int32\",data:[x,g]},{type:\"int32\",data:[f]},{type:\"int32\",data:[p*l]},{type:\"int32\",data:[p]}],_=n.runWebGPUProgram(C,[e],e.dtype,E),$=[];$.push(_);let M=Ie({inputs:{x:t},backend:n,attrs:{shape:[1,b,-1]}});if($.push(M),s!=null){let O=Wc(s.shape,y);O!=null&&(s=Ie({inputs:{x:s},backend:n,attrs:{shape:O}}),$.push(s))}if(r!=null){let O=Wc(r.shape,y);O!=null&&(r=Ie({inputs:{x:r},backend:n,attrs:{shape:O}}),$.push(r))}let I=Hh({a:y?_:M,b:y?M:_,transposeA:!y,transposeB:!1,backend:n,bias:r,activation:o,preluActivationWeights:s,leakyreluAlpha:i}),N=Ie({inputs:{x:I},backend:n,attrs:{shape:a.outShape}});$.push(I);for(let O of $)n.disposeData(O.dataId);return N}function B8({x:e,filter:t,convInfo:a,backend:n,bias:r=null,preluActivationWeights:s=null,leakyreluAlpha:i=0,activation:o=null}){let l=r!=null,u=s!=null,p=a.dataFormat===\"channelsLast\",c=p&&a.filterHeight===a.inHeight&&a.filterWidth===a.inWidth&&a.padInfo.type===\"VALID\",d=W().getBool(\"WEBGPU_USE_NAIVE_CONV2D_DEBUG\");if(!d&&(c||a.filterHeight===1&&a.filterWidth===1&&a.dilationHeight===1&&a.dilationWidth===1&&a.strideHeight===1&&a.strideWidth===1&&(a.padInfo.type===\"SAME\"||a.padInfo.type===\"VALID\")))return Ioe({x:e,filter:t,convInfo:a,backend:n,bias:r,activation:o,preluActivationWeights:s,leakyreluAlpha:i});let h=W().getNumber(\"WEBGPU_THRESHOLD_TO_INCREASE_WORKGROUPS_FOR_MATMUL\"),f=h>0?h:n.thresholdToIncreaseWorkgroups,m=a.batchSize*Math.ceil(a.outHeight*a.outWidth/32)*Math.ceil(a.outChannels/32);if(W().getBool(\"WEBGPU_CONV_SEPARATE_IM2COL_SHADER\")||m<=f)return Soe({x:e,filter:t,convInfo:a,backend:n,bias:r,preluActivationWeights:s,leakyreluAlpha:i,activation:o});let g,x=[a.padInfo.top,a.padInfo.left],A=[{type:\"int32\",data:[a.filterHeight,a.filterWidth]},{type:\"int32\",data:[...x]},{type:\"int32\",data:[a.strideHeight,a.strideWidth]},{type:\"int32\",data:[a.dilationHeight,a.dilationWidth]}];if(d)g=new woe(a,l,o,u);else{let S=p?a.outHeight*a.outWidth:a.outChannels,C=p?a.outChannels:a.outHeight*a.outWidth,E=a.filterHeight*a.filterWidth*a.inChannels;A.push({type:\"int32\",data:[S]},{type:\"int32\",data:[C]},{type:\"int32\",data:[E]});let _=n.adapterInfo.isIntel();g=new voe(a,S,C,E,l,o,u,_)}let y=[],b=[e,t];l&&(!p&&r.shape.length===1&&(r=Ie({inputs:{x:r},backend:n,attrs:{shape:[r.shape[0],1,1]}}),y.push(r)),b.push(r)),u&&(!p&&s.shape.length===1&&(s=Ie({inputs:{x:s},backend:n,attrs:{shape:[s.shape[0],1,1]}}),y.push(s)),b.push(s)),o===\"leakyrelu\"&&(A.push({type:\"float32\",data:[i]}),g.uniforms+=\" alpha : f32,\");let w=n.runWebGPUProgram(g,b,e.dtype,A);for(let S of y)n.disposeData(S.dataId);return w}function Toe(e){let{inputs:t,attrs:a,backend:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dataFormat:l,dilations:u,dimRoundingMode:p}=a,c=T.convertConv2DDataFormat(l),d=T.computeConv2DInfo(r.shape,s.shape,i,u,o,p,!1,c);return B8({x:r,filter:s,convInfo:d,backend:n})}var Coe={kernelName:ni,backendName:\"webgpu\",kernelFunc:Toe};function Noe(e=4){let t=n=>{switch(n){case 1:return\"return W[getIndexFromCoords4D(coord, uniforms.wShape)];\";case 4:return`\n            let coord1 = vec4<i32>(coordX, coordY, col + 1, rowInner);\n            let coord2 = vec4<i32>(coordX, coordY, col + 2, rowInner);\n            let coord3 = vec4<i32>(coordX, coordY, col + 3, rowInner);\n            let v0 = W[getIndexFromCoords4D(coord, uniforms.wShape)];\n            let v1 = W[getIndexFromCoords4D(coord1, uniforms.wShape)];\n            let v2 = W[getIndexFromCoords4D(coord2, uniforms.wShape)];\n            let v3 = W[getIndexFromCoords4D(coord3, uniforms.wShape)];\n            return vec4<f32>(v0, v1, v2, v3);\n            `;default:throw new Error(`innerElementSize ${n} is not supported.`)}},a=`if (row < uniforms.dimAOuter && col < uniforms.dimInner) {\n        ${`\n      let outRow = row / uniforms.outShape[2];\n      let outCol = row % uniforms.outShape[2];\n\n      let WRow = col / (uniforms.filterDims[1] * uniforms.outBackprop[3]);\n      let WCol = col / uniforms.outBackprop[3] % uniforms.filterDims[1];\n      let xR = f32(outRow - uniforms.pads[0] + WRow) / f32(uniforms.stride[0]);\n      let xC = f32(outCol - uniforms.pads[1] + WCol) / f32(uniforms.stride[1]);\n      if (xR < 0.0 || xR >= f32(uniforms.outBackprop[1]) || fract(xR) > 0.0) {\n        return ${Mt(e)}(0.0);\n      }\n      if (xC < 0.0 || xC >= f32(uniforms.outBackprop[2]) || fract(xC) > 0.0) {\n        return ${Mt(e)}(0.0);\n      }\n      let coord = vec4<i32>(\n          batch,\n          i32(xR),\n          i32(xC),\n          col % uniforms.outBackprop[3]);\n      return x[getIndexFromCoords4D(coord, uniforms.xShape)/${e}];`}\n      }\n      return ${Mt(e)}(0.0);`;return`\n  fn mm_readA(batch: i32, row : i32, colIn : i32) -> ${Mt(e)} {\n    let col = colIn * ${e};\n    ${a}\n  }\n\n  fn mm_readB(batch: i32, row : i32, colIn : i32) -> ${Mt(e)} {\n    let col = colIn * ${e};\n    let coordX = uniforms.filterDims.x - 1 -\n        row / (uniforms.filterDims[1] * uniforms.outBackprop[3]);\n    let coordY = uniforms.filterDims.y - 1 -\n        (row / uniforms.outBackprop[3]) % uniforms.filterDims[1];\n    if (row < uniforms.dimInner && col < uniforms.dimBOuter &&\n        coordX >= 0 && coordY >= 0) {\n      let rowInner = row % uniforms.outBackprop[3];\n      let coord = vec4<i32>(coordX, coordY, col, rowInner);\n      ${t(e)}\n    }\n    return ${Mt(e)}(0.0);\n  }\n\n  fn mm_write(batch: i32, row : i32, colIn : i32, valueInput : ${Mt(e)}) {\n    let col = colIn * ${e};\n    if (row < uniforms.dimAOuter && (col + ${e-1}) < uniforms.dimBOuter) {\n      var value = valueInput;\n      let outCoord = vec4<i32>(\n          batch,\n          row / uniforms.outShape[2],\n          row % uniforms.outShape[2],\n          col);\n      result[getIndexFromCoords4D(outCoord, uniforms.outShape)/${e}] = value;\n    }\n  }`}var Eoe=class{constructor(e){this.variableNames=[\"x\",\"W\"],this.uniforms=\"filterDims : vec2<i32>, pads : vec2<i32>, stride : vec2<i32>, outBackprop : vec4<i32>, dimAOuter : i32, dimBOuter : i32, dimInner : i32,\",this.outputShape=e.inShape,v.assert(e.dataFormat===\"channelsLast\",()=>\"TODO: NCHW is unimplemented\"),this.isVec4=e.inChannels%4===0&&e.outChannels%4===0,this.dispatchLayout={x:[3],y:[1,2],z:[0]},this.workgroupSize=F3(this.dispatchLayout,this.outputShape,this.isVec4),this.elementsPerThread=O3(this.dispatchLayout,this.outputShape,this.isVec4),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,this.elementsPerThread),this.isVec4&&(this.variableTypes=[\"vec4<f32>\",\"f32\"]),this.shaderKey=`conv2DDerInputMM_${this.isVec4}_${this.elementsPerThread}`}getUserCode(){let e=this.isVec4?Uh(this.elementsPerThread,this.workgroupSize):Gh(this.elementsPerThread,this.workgroupSize);return`\n    ${Noe(this.isVec4?4:1)}\n    ${e}\n    `}},Roe=class{constructor(e){this.variableNames=[\"dy\",\"W\"],this.uniforms=\"filterDims : vec2<i32>, pads : vec2<i32>, stride : vec2<i32>, outBackprop : vec4<i32>,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e.inShape,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.isChannelsLast=e.dataFormat===\"channelsLast\",this.shaderKey=`conv2DDerInput_${this.isChannelsLast}`}getUserCode(){let e=this.isChannelsLast?1:2,t=this.isChannelsLast?2:3,a=this.isChannelsLast?3:1;return`\n    ${Ce(\"index\")} {\n      if(index < uniforms.size) {\n        let coords = getCoordsFromIndex(index);\n        let batch = coords[0];\n        let d1 = coords[${a}];\n\n        let dyCorner = vec2<i32>(coords[${e}], coords[${t}]) - uniforms.pads;\n        let dyRCorner = dyCorner.x;\n        let dyCCorner = dyCorner.y;\n\n        // Convolve dy(?, ?, d2) with w(:, :, d1, d2) to compute dx(xR, xC, d1).\n        // ? = to be determined. : = across all values in that axis.\n        var dotProd = 0.0;\n        for (var wR = 0; wR < uniforms.filterDims.x; wR = wR + 1) {\n          let dyR = (f32(dyRCorner) + f32(wR)) / f32(uniforms.stride.x);\n          let wRPerm = uniforms.filterDims.x - 1 - wR;\n          if (dyR < 0.0 || dyR >= f32(uniforms.outBackprop[1]) || fract(dyR) > 0.0 ||\n              wRPerm < 0) {\n            continue;\n          }\n          let idyR = i32(dyR);\n\n          for (var wC = 0; wC < uniforms.filterDims.y; wC = wC + 1) {\n            let dyC = (f32(dyCCorner) + f32(wC)) / f32(uniforms.stride.y);\n            let wCPerm = uniforms.filterDims.y - 1 - wC;\n            if (dyC < 0.0 || dyC >= f32(uniforms.outBackprop[2]) ||\n                fract(dyC) > 0.0 || wCPerm < 0) {\n              continue;\n            }\n            let idyC = i32(dyC);\n\n            for (var d2 = 0; d2 < uniforms.outBackprop[3]; d2 = d2 + 1) {\n              if (${this.isChannelsLast}) {\n                let xValue = getDy(batch, idyR, idyC, d2);\n                let wValue = getW(wRPerm, wCPerm, d1, d2);\n                dotProd = dotProd + xValue * wValue;\n              } else {\n                let xValue = getDy(batch, d2, idyR, idyC);\n                let wValue = getW(wRPerm, wCPerm, d1, d2);\n                dotProd = dotProd + xValue * wValue;\n              }\n\n            }\n          }\n        }\n        setOutputAtIndex(index, dotProd);\n      }\n    }\n  `}};function Moe(e){let{inputs:t,backend:a,attrs:n}=e,{dy:r,filter:s}=t,{inputShape:i,strides:o,pad:l,dataFormat:u,dimRoundingMode:p}=n,c=T.convertConv2DDataFormat(u),d=T.computeConv2DInfo(i,s.shape,o,1,l,p,!1,c),h=[{type:\"int32\",data:[d.filterHeight,d.filterWidth]},{type:\"int32\",data:[d.filterHeight-1-d.padInfo.top,d.filterWidth-1-d.padInfo.left]},{type:\"int32\",data:[d.strideHeight,d.strideWidth]},{type:\"int32\",data:[d.batchSize,d.outHeight,d.outWidth,d.outChannels]}],f;if(W().getBool(\"WEBGPU_USE_NAIVE_CONV2D_TRANSPOSE\")||d.filterHeight<=2&&d.filterWidth<=2&&d.outChannels<=16&&d.inChannels===1)f=new Roe(d);else{f=new Eoe(d);let m=d.inHeight*d.inWidth,g=d.inChannels,x=d.filterHeight*d.filterWidth*d.outChannels;h.push({type:\"uint32\",data:[m]},{type:\"uint32\",data:[g]},{type:\"uint32\",data:[x]})}return a.runWebGPUProgram(f,[r,s],\"float32\",h)}var $oe={kernelName:ri,backendName:\"webgpu\",kernelFunc:Moe},_oe=it({opType:de.COS}),Poe={kernelName:si,backendName:\"webgpu\",kernelFunc:_oe},Foe=it({opType:de.COSH}),Ooe={kernelName:ii,backendName:\"webgpu\",kernelFunc:Foe},Doe=class{constructor(e,t,a,n){this.variableNames=[\"Image\",\"Boxes\",\"BoxInd\"],this.uniforms=\"extrapolationValue : f32,\",this.workgroupSize=[64,1,1],this.size=!0;let[r]=t;this.outputShape=[r,a[0],a[1],e],this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.methodId=n===\"bilinear\"?1:0,this.cropHeightBiggerThan1=this.outputShape[1]>1,this.cropWidthBiggerThan1=this.outputShape[2]>1,this.shaderKey=`cropAndResize_${this.methodId}_${this.cropHeightBiggerThan1}_${this.cropWidthBiggerThan1}`}getUserCode(){let[e,t]=[\"f32(uniforms.imageShape[1] - 1)\",\"f32(uniforms.imageShape[2] - 1)\"],[a,n,r]=this.cropHeightBiggerThan1?[`(${e} / f32(uniforms.outShape[1] - 1))`,\"(y2-y1) * height_ratio\",`y1*${e} + f32(y)*(height_scale)`]:[\"0.0\",\"0.0\",`0.5 * (y1+y2) * ${e}`],[s,i,o]=this.cropWidthBiggerThan1?[`(${t} / f32(uniforms.outShape[2] - 1))`,\"(x2-x1) * width_ratio\",`x1*${t} + f32(x)*(width_scale)`]:[\"0.0\",\"0.0\",`0.5 * (x1+x2) * ${t}`];return`\n    ${Ce(\"index\")} {\n      if (index < uniforms.size) {\n        let coords = getCoordsFromIndex(index);\n        let height_ratio = f32(${a});\n        let width_ratio = f32(${s});\n        let b = coords[0];\n        let y = coords[1];\n        let x = coords[2];\n        let d = coords[3];\n        // get box vals\n        let y1 = getBoxes(b, 0);\n        let x1 = getBoxes(b, 1);\n        let y2 = getBoxes(b, 2);\n        let x2 = getBoxes(b, 3);\n        // get image in batch index\n        let bInd = i32(round(getBoxInd(b)));\n        if(bInd < 0 || bInd >= uniforms.outShape[0]) {\n          return;\n        }\n        let height_scale = ${n};\n        let width_scale = ${i};\n        let in_y = ${r};\n        if( in_y < 0.0 || in_y > ${e} ) {\n          setOutputAtIndex(index, uniforms.extrapolationValue);\n          return;\n        }\n        let in_x = ${o};\n        if( in_x < 0.0 || in_x > ${t} ) {\n          setOutputAtIndex(index, uniforms.extrapolationValue);\n          return;\n        }\n        let sourceFracIndexCR = vec2<f32>(in_x,in_y);\n        if(${this.methodId} == 1) {\n          // Compute the four integer indices.\n          let sourceFloorCR = vec2<i32>(sourceFracIndexCR);\n          let sourceCeilCR = vec2<i32>(ceil(sourceFracIndexCR));\n          let topLeft = getImage(bInd, sourceFloorCR.y, sourceFloorCR.x, d);\n          let bottomLeft = getImage(bInd, sourceCeilCR.y, sourceFloorCR.x, d);\n          let topRight = getImage(bInd, sourceFloorCR.y, sourceCeilCR.x, d);\n          let bottomRight = getImage(bInd, sourceCeilCR.y, sourceCeilCR.x, d);\n          let fracCR = sourceFracIndexCR - vec2<f32>(sourceFloorCR);\n          let top = topLeft + (topRight - topLeft) * fracCR.x;\n          let bottom = bottomLeft + (bottomRight - bottomLeft) * fracCR.x;\n          let newValue = top + (bottom - top) * fracCR.y;\n          setOutputAtIndex(index, newValue);\n        } else {\n          // Compute the coordinators of nearest neighbor point.\n          let sourceNearestCR = vec2<i32>(floor(\n            sourceFracIndexCR + vec2<f32>(0.5,0.5)));\n          let newValue = getImage(\n            bInd, sourceNearestCR.y, sourceNearestCR.x, d);\n          setOutputAtIndex(index, newValue);\n        }\n      }\n    }\n    `}},zoe=e=>{let{inputs:t,backend:a,attrs:n}=e,{image:r,boxes:s,boxInd:i}=t,{cropSize:o,method:l,extrapolationValue:u}=n,p=new Doe(r.shape[3],s.shape,o,l),c=[{type:\"float32\",data:[u]}];return a.runWebGPUProgram(p,[r,s,i],\"float32\",c)},Loe={kernelName:ui,backendName:\"webgpu\",kernelFunc:zoe},bd;(function(e){e.Prod=\"*\",e.Sum=\"+\"})(bd||(bd={}));var Zx=class{constructor(e,t,a,n){this.variableNames=[\"x\"],this.uniforms=\"index : f32,\",this.size=!0,this.workgroupSize=[128,1,1],this.outputShape=t,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.exclusive=a,this.reverse=n,this.op=e,this.shaderKey=`cum_${this.op}_${this.exclusive}_${this.reverse}`}getUserCode(){let e=this.outputShape.length,t=this.op===bd.Prod?\"1.0\":\"0.0\",a=this.exclusive?t:`getX(${Yx(e,\"coords\",this.op)})`,n=this.outputShape[this.outputShape.length-1],r=\"\",s=\"\";return this.exclusive?(r=this.reverse?`end != ${n-1}`:\"end != 0\",s=this.reverse?\"end + 1\":\"end - 1\"):(r=this.reverse?`end + pow2 < ${n}`:\"end >= pow2\",s=this.reverse?\"end + pow2\":\"end - pow2\"),`\n      ${Ce(\"index\")} {\n       if (index < uniforms.size) {\n         var coords = getCoordsFromIndex(index);\n\n         let end = ${Jx(e,\"coords\",this.op)};\n         var val = ${a};\n         let pow2 = i32(pow(2.0, uniforms.index));\n         if (${r}) {\n           let idx = ${s};\n           ${Jx(e,\"coords\",this.op)} = idx;\n           val ${this.op}= getX(${Yx(e,\"coords\",this.op)});\n         }\n         setOutputAtIndex(index, val);\n       }\n      }\n    `}};function Yx(e,t,a){if(e===1)return`${t}`;if(e===2)return`${t}.x, ${t}.y`;if(e===3)return`${t}.x, ${t}.y, ${t}.z`;if(e===4)return`${t}.x, ${t}.y, ${t}.z, ${t}.w`;throw Error(`Cumulative ${a} for rank ${e} is not yet supported`)}function Jx(e,t,a){if(e===1)return`${t}`;if(e===2)return`${t}.y`;if(e===3)return`${t}.z`;if(e===4)return`${t}.w`;throw Error(`Cumulative ${a} for rank ${e} is not yet supported`)}function W8(e,t,a,n,r,s){let i=t.shape.length,o=T.getAxesPermutation([n],i),l=t;o!=null&&(l=vr({inputs:{x:t},backend:a,attrs:{perm:o}}));let u=T.getInnerMostAxes(1,i)[0];if(u!==i-1)throw new Error(`WebGPU cumprod shader expects an inner-most axis=${t.shape.length-1} but got axis=${n}`);let p=l.shape[u],c=Ya({inputs:{x:l},backend:a});for(let d=0;d<=Math.ceil(Math.log2(p))-1;d++){let h=new Zx(e,l.shape,!1,s),f=c,m=[{type:\"float32\",data:[d]}];c=a.runWebGPUProgram(h,[c],c.dtype,m),a.disposeData(f.dataId)}if(r){let d=new Zx(e,l.shape,r,s),h=c,f=[{type:\"float32\",data:[0]}];c=a.runWebGPUProgram(d,[c],c.dtype,f),a.disposeData(h.dataId)}if(o!=null){let d=T.getUndoAxesPermutation(o),h=vr({inputs:{x:c},backend:a,attrs:{perm:d}});return a.disposeData(c.dataId),a.disposeData(l.dataId),h}return c}function Boe(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,exclusive:i,reverse:o}=n;return W8(bd.Prod,r,a,s,i,o)}var Woe={kernelName:oi,backendName:\"webgpu\",kernelFunc:Boe};function Voe(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,exclusive:i,reverse:o}=n;return W8(bd.Sum,r,a,s,i,o)}var Uoe={kernelName:li,backendName:\"webgpu\",kernelFunc:Voe};function Goe(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,weights:s}=t,{size:i,binaryOutput:o}=n,l=r.shape.length===1,u=v.sizeFromShape(s.shape)>0,p=s.dtype,c=l?[r.shape[0]]:[r.shape[0],r.shape[1]],d=l?[i]:[r.shape[0],i],h=Cr({backend:a,attrs:{shape:d,value:0,dtype:p}}),f=new D8(c,u,o),m=[{type:\"int32\",data:[i]}],g=u?[r,s]:[r];return a.runWebGPUProgram(f,g,p,m,h)}var Hoe={kernelName:Td,backendName:\"webgpu\",kernelFunc:Goe},joe=class{constructor(e,t){this.variableNames=[\"x\"],this.workgroupSize=[64,1,1],this.size=!0,this.uniforms=\"blockSize : i32,\",this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=`depthToSpace_${t}`,this.dataFormat=t}getUserCode(){return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let coords = getCoordsFromIndex(index);\n          let b = coords[0];\n          let h = ${this.getHeightCoordString()};\n          let w = ${this.getWidthCoordString()};\n          let d = ${this.getDepthCoordString()};\n\n          let in_h = h / uniforms.blockSize;\n          let offset_h = h % uniforms.blockSize;\n          let in_w = w / uniforms.blockSize;\n          let offset_w = w % uniforms.blockSize;\n          let offset_d = (offset_h * uniforms.blockSize + offset_w) *\n            ${this.getOutputDepthSize()};\n          let in_d = d + offset_d;\n\n          let rlt = ${this.getInputSamplingString()};\n          setOutputAtIndex(index, rlt);\n        }\n      }`}getHeightCoordString(){return this.dataFormat===\"NHWC\"?\"coords[1]\":\"coords[2]\"}getWidthCoordString(){return this.dataFormat===\"NHWC\"?\"coords[2]\":\"coords[3]\"}getDepthCoordString(){return this.dataFormat===\"NHWC\"?\"coords[3]\":\"coords[1]\"}getOutputDepthSize(){return this.dataFormat===\"NHWC\"?\"uniforms.outShape[3]\":\"uniforms.outShape[1]\"}getInputSamplingString(){return this.dataFormat===\"NHWC\"?\"getX(b, in_h, in_w, in_d)\":\"getX(b, in_d, in_h, in_w)\"}};function qoe(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockSize:s,dataFormat:i}=n,o=r.shape[0],l=i===\"NHWC\"?r.shape[1]:r.shape[2],u=i===\"NHWC\"?r.shape[2]:r.shape[3],p=i===\"NHWC\"?r.shape[3]:r.shape[1],c=l*s,d=u*s,h=p/(s*s),f=i===\"NHWC\"?[o,c,d,h]:[o,h,c,d],m=[{type:\"int32\",data:[s]}],g=new joe(f,i);return a.runWebGPUProgram(g,[r],r.dtype,m)}var Xoe={kernelName:di,backendName:\"webgpu\",kernelFunc:qoe},Koe=class{constructor(e,t,a,n=!1,r=null,s=!1){this.variableNames=[\"x\",\"W\"],this.uniforms=\"pad : vec2<i32>, inDims : vec2<i32>,\",this.workgroupSize=[16,16,1],this.outputShape=e,this.dispatchLayout={x:[3],y:[2],z:[0,1]},this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),n&&this.variableNames.push(\"bias\"),s&&this.variableNames.push(\"preluActivationWeights\"),this.addBias=n,this.activation=r,this.hasPreluActivation=s,this.filterHeight=t,this.filterWidth=a,this.shaderKey=`depthwiseNCHW_${this.activation}_${this.filterHeight}_${this.filterWidth}`}getUserCode(){let e=this.filterWidth*this.filterHeight,t=this.workgroupSize[0]*this.workgroupSize[1]*this.workgroupSize[2],a=this.workgroupSize[1]+this.filterHeight-1,n=this.workgroupSize[0]+this.filterWidth-1;return`\n      ${Tr(this.activation,this.hasPreluActivation,!1,4)}\n\n      var<workgroup> mm_Asub : array<array<f32, ${n}>, ${a}>;\n      var<workgroup> mm_Bsub : array<array<f32, ${this.filterWidth}>, ${this.filterHeight}>;\n      fn readX(batch : i32, channel : i32, row : i32, col : i32) -> f32 {\n        var value = 0.0;\n        if (row >=0 && row < uniforms.inDims[0] && col >=0 && col < uniforms.inDims[1])\n        {\n          value = getX(batch, channel, row, col);\n        }\n        return value;\n      }\n\n      ${Ce()} {\n        let coords = getOutputCoords();\n        let batch = coords[0];\n        let xRCCorner = vec2<i32>(coords.zw) - uniforms.pad;\n        let channelMul = uniforms.wShape[3];\n        let d1 = coords[1] / channelMul;\n        let q = coords[1] % channelMul;\n\n        let inputRowStart = xRCCorner.x;\n        let inputColStart = xRCCorner.y;\n\n        let localRow = i32(localId.y);\n        let localCol = i32(localId.x);\n\n        // Load one tile of X into local memory.\n        for (var inputRow = localRow; inputRow < ${a}; inputRow = inputRow + ${this.workgroupSize[1]}) {\n          for (var inputCol = localCol; inputCol < ${n}; inputCol = inputCol + ${this.workgroupSize[0]}) {\n            let rowOffset = inputRow - localRow;\n            let colOffset = inputCol - localCol;\n            mm_Asub[inputRow][inputCol] = readX(batch, d1, inputRowStart + rowOffset, inputColStart + colOffset);\n          }\n        }\n\n        // Load one tile of W into local memory.\n        var wIndex = i32(localIndex);\n        ${e<t?`if (wIndex < ${e})`:`for(; wIndex < ${e}; wIndex = wIndex + ${t})`}\n\n        {\n          let wRow = wIndex / ${this.filterWidth};\n          let wCol = wIndex % ${this.filterWidth};\n          mm_Bsub[wRow][wCol] = getW(wRow, wCol, d1, q);\n        }\n\n        workgroupBarrier();\n\n        var value = 0.0;\n        for (var wR = 0; wR < ${this.filterHeight}; wR = wR + 1) {\n          for (var wC = 0; wC < ${this.filterWidth}; wC = wC + 1) {\n            let xVal = mm_Asub[localRow + wR][localCol + wC];\n            let wVal = mm_Bsub[wR][wC];\n            value = fma(xVal, wVal, value);\n          }\n        }\n        ${vo(this.addBias,this.activation)}\n        if (coordsInBounds4D(coords, uniforms.outShape)) {\n          setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value);\n        }\n      }\n    `}},V8=class{constructor(e,t=!1,a=null,n=!1){this.variableNames=[\"x\",\"W\"],this.uniforms=\"pad : vec2<i32>, inDims : vec2<i32>,\",this.workgroupSize=[4,4,4],this.workPerThread=4,this.isVec4=!0,this.outputShape=e.outShape,this.dispatchLayout={x:[3],y:[2],z:[0,1]},this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[4,this.workPerThread,1]),v.assert(e.dataFormat===\"channelsLast\",()=>\"TODO: NCHW is unimplemented\"),t&&this.variableNames.push(\"bias\"),n&&this.variableNames.push(\"preluActivationWeights\"),this.convInfo=e,this.addBias=t,this.activation=a,this.hasPreluActivation=n,this.shaderKey=`depthwiseVec4_${a}_${this.convInfo.filterHeight}_${this.convInfo.filterWidth}_${this.convInfo.strideHeight}_${this.convInfo.strideWidth}_${this.workPerThread}`}getUserCode(){let e=(this.workPerThread-1)*this.convInfo.strideWidth+this.convInfo.filterWidth;return`\n      ${Tr(this.activation,this.hasPreluActivation,!0,4)}\n      fn readX(batch : i32, row : i32, col : i32, channel : i32) -> vec4<f32> {\n        var value = vec4<f32>(0.0);\n        if (col >=0 && col < uniforms.inDims[1]) {\n          value = getX(batch, row, col, channel);\n        }\n        return value;\n      }\n\n      const strideHeight = ${this.convInfo.strideHeight};\n      const strideWidth = ${this.convInfo.strideWidth};\n      ${Ce()} {\n        let batch = i32(globalId.z) / uniforms.outShape[1];\n        let r = i32(globalId.z) % uniforms.outShape[1];\n        let c = i32(globalId.y) * ${this.workPerThread};\n        let d1 = i32(globalId.x) * 4;\n        let xRCCorner = vec2<i32>(r, c) * vec2<i32>(strideHeight, strideWidth) - uniforms.pad;\n\n        let xRCorner = xRCCorner.x;\n        let xCCorner = xRCCorner.y;\n        var xVals : array<vec4<f32>, ${e}>;\n        var dotProd : array<vec4<f32>, ${this.workPerThread}>;\n        for (var i = 0; i < ${this.workPerThread}; i++) {\n          dotProd[i] = vec4<f32>(0.0);\n        }\n\n        // Use constant instead of uniform can give better performance.\n        for (var wR = 0; wR < ${this.convInfo.filterHeight}; wR = wR + 1) {\n          let xR = xRCorner + wR;\n          if (xR >=0 && xR < uniforms.inDims[0]) {\n            for (var i = 0; i < ${e}; i++) {\n              xVals[i] = readX(batch, xR, xCCorner + i, d1);\n            }\n            for (var wC = 0; wC < ${this.convInfo.filterWidth}; wC = wC + 1) {\n              let wValue = getW(wR, wC, d1, 0);\n              for (var i = 0; i < ${this.workPerThread}; i++) {\n                dotProd[i] = fma(xVals[i * strideWidth + wC], wValue, dotProd[i]);\n              }\n            }\n          }\n        }\n\n        for (var i = 0; i < ${this.workPerThread}; i = i + 1) {\n          let coords = vec4<i32>(batch, r, c + i, d1);\n          if (coordsInBounds4D(coords, uniforms.outShape)) {\n            var value = dotProd[i];\n            ${vo(this.addBias,this.activation)}\n            setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value);\n          }\n        }\n      }\n    `}},U8=class{constructor(e,t=!1,a=null,n=!1){this.variableNames=[\"x\",\"W\"],this.uniforms=`pad : vec2<i32>, inDims : vec2<i32>, filterHeight : i32,\n      filterWidth : i32, stride : vec2<i32>, dilation : vec2<i32>,`,this.workgroupSize=[256,1,1],this.size=!0,this.outputShape=e.outShape,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.isChannelsLast=e.dataFormat===\"channelsLast\",t&&this.variableNames.push(\"bias\"),n&&this.variableNames.push(\"preluActivationWeights\"),this.convInfo=e,this.addBias=t,this.activation=a,this.hasPreluActivation=n,this.shaderKey=`depthwise_${this.activation}_${this.isChannelsLast}`}getUserCode(){let e=this.isChannelsLast?\"getX(batch, xR, xC, d1);\":\"getX(batch, d1, xR, xC);\";return`\n      ${Tr(this.activation,this.hasPreluActivation,!1,4)}\n\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let coords = getOutputCoords();\n          let batch = coords[0];\n          let xRCCorner = vec2<i32>(coords.${this.isChannelsLast?\"yz\":\"zw\"}) * uniforms.stride - uniforms.pad;\n          let d2 = coords[${this.isChannelsLast?3:1}];\n          let channelMul = uniforms.wShape[3];\n          let d1 = d2 / channelMul;\n          let q = d2 % channelMul;\n\n          let inputRowStart = xRCCorner.x;\n          let inputColStart = xRCCorner.y;\n          let inputRowEnd = inputRowStart + uniforms.filterHeight *\n              uniforms.dilation[0];\n          let inputColEnd = inputColStart + uniforms.filterWidth *\n              uniforms.dilation[1];\n\n          // Convolve x(?, ?, d1)|x(d1, ?, ?) with w(:, :, d1, q) to get\n          // y(yR, yC, d2)|y(d2, yR, yC). ? = to be determined. : = across all\n          // values in that axis. x(?, ?, d1) and y(yR, yC, d2) is for NHWC.\n          // x(d1, ?, ?) and y(d2, yR, yC) is for NCHW.\n          var value = 0.0;\n\n          // Extract if checking out of for loop for performance.\n          if (inputRowStart >= 0 && inputColStart >= 0 &&\n            inputRowEnd < uniforms.inDims[0] &&\n                inputColEnd < uniforms.inDims[1]) {\n              for (var wR = 0; wR < uniforms.filterHeight; wR = wR + 1) {\n                let xR = inputRowStart + wR * uniforms.dilation[0];\n\n                for (var wC = 0; wC < uniforms.filterWidth; wC = wC + 1) {\n                  let xC = inputColStart + wC * uniforms.dilation[1];\n\n                  let xVal = ${e};\n                  let wVal = getW(wR, wC, d1, q);\n                  value = value + xVal * wVal;\n                }\n              }\n            } else {\n              for (var wR = 0; wR < uniforms.filterHeight; wR = wR + 1) {\n                let xR = inputRowStart + wR * uniforms.dilation[0];\n\n                if (xR < 0 || xR >= uniforms.inDims[0]) {\n                  continue;\n                }\n\n                for (var wC = 0; wC < uniforms.filterWidth; wC = wC + 1) {\n                  let xC = inputColStart + wC * uniforms.dilation[1];\n\n                  if (xC < 0 || xC >= uniforms.inDims[1]) {\n                    continue;\n                  }\n\n                  let xVal = ${e};\n                  let wVal = getW(wR, wC, d1, q);\n                  value = value + xVal * wVal;\n                }\n              }\n            }\n            ${vo(this.addBias,this.activation)}\n          setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value);\n        }\n      }\n    `}};function Zoe(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s}=t,{strides:i,pad:o,dataFormat:l,dilations:u,dimRoundingMode:p}=n,c=T.convertConv2DDataFormat(l),d=u;d==null&&(d=[1,1]);let h=T.computeConv2DInfo(r.shape,s.shape,i,d,o,p,!0,c),f=[{type:\"int32\",data:[h.padInfo.top,h.padInfo.left]},{type:\"int32\",data:[h.inHeight,h.inWidth]}],m=h.dataFormat===\"channelsLast\",g;return!m&&h.inHeight>16&&h.inWidth>16&&h.strideHeight===1&&h.strideWidth===1&&h.dilationWidth===1&&h.dilationHeight===1&&h.inChannels===h.outChannels?g=new Koe(h.outShape,h.filterHeight,h.filterWidth):m&&h.outHeight>4&&h.outWidth>4&&h.strideWidth<=2&&h.inChannels===h.outChannels&&h.dilationHeight===1&&h.dilationWidth===1&&h.inChannels%4===0?g=new V8(h):(g=new U8(h),f.push({type:\"int32\",data:[h.filterHeight]},{type:\"int32\",data:[h.filterWidth]},{type:\"int32\",data:[h.strideHeight,h.strideWidth]},{type:\"int32\",data:[h.dilationHeight,h.dilationWidth]})),a.runWebGPUProgram(g,[r,s],r.dtype,f)}var Yoe={kernelName:pi,backendName:\"webgpu\",kernelFunc:Zoe},G8=ua({opType:De.MUL,cpuKernelImpl:Kse,supportsComplex:!0}),Joe={kernelName:zi,backendName:\"webgpu\",kernelFunc:G8};function V3(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;return ko(r,s,i,\"sum\",a)}var Qoe={kernelName:ro,backendName:\"webgpu\",kernelFunc:V3};function ele(e){let{inputs:t,backend:a,attrs:n}=e,{equation:r}=n,s=t,{allDims:i,summedDims:o,idDims:l}=T.decodeEinsumEquation(r,s.length);T.checkEinsumDimSizes(i.length,l,s);let{path:u,steps:p}=T.getEinsumComputePath(o,l),c=p.length,d=null,h=i.length,f=[];for(let m=0;m<c;++m){for(let g of p[m]){let{permutationIndices:x,expandDims:A}=T.getEinsumPermutation(h,l[g]),y;T.isIdentityPermutation(x)?y=s[g]:(y=vr({inputs:{x:s[g]},backend:a,attrs:{perm:x}}),f.push(y));let b=y.shape.slice();for(let w=0;w<A.length;++w)b.splice(A[w],0,1);v.arraysEqual(y.shape,b)||(y=Ie({inputs:{x:y},backend:a,attrs:{shape:b}}),f.push(y)),d===null?d=y:(d=G8({inputs:{a:y,b:d},backend:a}),f.push(d))}m<c-1&&(u[m]>=0&&(d=V3({inputs:{x:d},backend:a,attrs:{axis:u[m]-(i.length-h),keepDims:!1}}),f.push(d)),h--)}for(let m of f)m!==d&&a.disposeData(m.dataId);return d}var tle={kernelName:Cd,backendName:\"webgpu\",kernelFunc:ele},ale=it({opType:de.ELU}),nle={kernelName:hi,backendName:\"webgpu\",kernelFunc:ale},rle=ua({opType:De.EQUAL,dtype:\"bool\",cpuKernelImpl:Fse}),sle={kernelName:fi,backendName:\"webgpu\",kernelFunc:rle},ile=it({opType:de.ERF}),ole={kernelName:$l,backendName:\"webgpu\",kernelFunc:ile},H8=it({opType:de.EXP,cpuKernelImpl:Ose,dtype:\"float32\"}),lle={kernelName:mi,backendName:\"webgpu\",kernelFunc:H8};function D1(e){let{inputs:t,attrs:a,backend:n}=e,{dim:r}=a,{input:s}=t,i=s.shape.length,o=s.shape.slice(),l=r;return r<0&&(v.assert(-(i+1)<=r,()=>`Axis must be in the interval [${-(i+1)}, ${i}]`),l=i+r+1),o.splice(l,0,1),Ie({inputs:{x:s},backend:n,attrs:{shape:o}})}var ule={kernelName:_l,backendName:\"webgpu\",kernelFunc:D1},dle=it({opType:de.EXPM1,cpuKernelImpl:Dse}),ple={kernelName:Pl,backendName:\"webgpu\",kernelFunc:dle},Qx=class{constructor(e,t){this.variableNames=[\"real\",\"imag\"],this.outputShape=[],this.uniforms=\"exponentMultiplier : f32, denominator: f32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=t,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.component=e,this.shaderKey=`fft_${e}`}getUserCode(){return`\n    fn unaryOpComplex(real: f32, expR: f32, imag: f32, expI: f32) -> f32 {\n      ${this.component===\"real\"?\"return real * expR - imag * expI;\":\"return real * expI + imag * expR;\"}\n    }\n\n    fn mulMatDFT(batch: i32, index: i32) -> f32 {\n      let indexRatio = f32(index) / f32(uniforms.realShape[1]);\n      let exponentMultiplierTimesIndexRatio =\n          uniforms.exponentMultiplier * indexRatio;\n\n      var result = 0.0;\n\n      for (var i = 0; i < uniforms.realShape[1]; i = i + 1) {\n        // x = (-2|2 * PI / N) * index * i;\n        let x = exponentMultiplierTimesIndexRatio * f32(i);\n        let expR = cos(x);\n        let expI = sin(x);\n        let real = getReal(batch, i);\n        let imag = getImag(batch, i);\n\n        result = result +\n            unaryOpComplex(real, expR, imag, expI) / uniforms.denominator;\n      }\n\n      return result;\n    }\n\n    ${Ce(\"index\")} {\n      if (index < uniforms.size) {\n        let coords = getOutputCoords();\n        setOutputAtIndex(index, mulMatDFT(coords[0], coords[1]));\n      }\n    }\n  `}};function j8(e,t,a){let n=a.tensorMap.get(e.dataId),r=v.sizeFromShape(e.shape),s=e.shape[e.shape.length-1],i=r/s,o=[],l=Ie({inputs:{x:e},backend:a,attrs:{shape:[i,s]}});o.push(l);let u=l.shape,p=new Qx(\"real\",u),c=new Qx(\"imag\",u),d=[{dataId:n.complexTensorInfos.real.dataId,dtype:n.complexTensorInfos.real.dtype,shape:u},{dataId:n.complexTensorInfos.imag.dataId,dtype:n.complexTensorInfos.imag.dtype,shape:u}],h=t?2*Math.PI:-2*Math.PI,f=t?u[1]:1,m=[{type:\"float32\",data:[h]},{type:\"float32\",data:[f]}],g=a.runWebGPUProgram(p,d,\"float32\",m);o.push(g);let x=a.runWebGPUProgram(c,d,\"float32\",m);o.push(x);let A=wo({inputs:{real:g,imag:x},backend:a});o.push(A);let y=Ie({inputs:{x:A},backend:a,attrs:{shape:e.shape}});return o.forEach(b=>a.disposeData(b.dataId)),y}function cle(e){let{inputs:t,backend:a}=e,{input:n}=t;return j8(n,!1,a)}var hle={kernelName:Nd,backendName:\"webgpu\",kernelFunc:cle},fle=class{constructor(e){this.outputShape=[],this.variableNames=[\"x\"],this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=\"flipLeftRight\"}getUserCode(){return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let coords = getCoordsFromIndex(index);\n          let coordX = uniforms.xShape[2] - coords[2] - 1;\n          let outputValue = getX(coords[0], coords[1], coordX, coords[3]);\n          setOutputAtIndex(index, outputValue);\n        }\n      }\n    `}},mle={kernelName:gi,backendName:\"webgpu\",kernelFunc:({inputs:e,backend:t})=>{let{image:a}=e,n=t,r=new fle(a.shape);return n.runWebGPUProgram(r,[a],a.dtype)}},gle=it({opType:de.FLOOR,cpuKernelImpl:zse}),xle={kernelName:xi,backendName:\"webgpu\",kernelFunc:gle},Ale=ua({opType:De.INT_DIV,dtype:\"int32\"}),yle={kernelName:Ai,backendName:\"webgpu\",kernelFunc:Ale},ble=class{constructor(e,t,a=!1){this.isFromPixels=!0,this.outputShape=[0],this.variableNames=[],this.workgroupSize=[256,1,1],this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[t,1,1]),this.importVideo=a,this.shaderKey=`fromPixels_${this.importVideo}`}getUserCode(){let e=this.importVideo?\"textureLoad(src, vec2<i32>(coords.yx));\":\"textureLoad(src, vec2<i32>(coords.yx), 0)\";return`\n      @binding(1) @group(0) var src: ${this.importVideo?\"texture_external\":\"texture_2d<f32>\"};\n      ${Ce(\"index\")} {\n        let flatIndex = index * uniforms.numChannels;\n        if (flatIndex < uniforms.size) {\n          let coords = getCoordsFromIndex(flatIndex);\n          let values = ${e};\n          for (var i = 0; i < uniforms.numChannels; i = i + 1) {\n            result[flatIndex + i] = i32(floor(255.0 * values[i]));\n          }\n        }\n      }\n  `}},vle={kernelName:rd,backendName:\"webgpu\",kernelFunc:wle},Yo,Wm=W().getBool(\"CANVAS2D_WILL_READ_FREQUENTLY_FOR_GPU\"),cc=new Map;function wle(e){let{inputs:t,backend:a,attrs:n}=e,{pixels:r}=t,{numChannels:s}=n;if(r==null)throw new Error(\"pixels passed to tf.browser.fromPixels() can not be null\");let i=typeof HTMLVideoElement!=\"undefined\"&&r instanceof HTMLVideoElement,o=typeof HTMLImageElement!=\"undefined\"&&r instanceof HTMLImageElement,l=typeof HTMLCanvasElement!=\"undefined\"&&r instanceof HTMLCanvasElement||typeof OffscreenCanvas!=\"undefined\"&&r instanceof OffscreenCanvas,u=typeof ImageBitmap!=\"undefined\"&&r instanceof ImageBitmap,[p,c]=i?[r.videoWidth,r.videoHeight]:[r.width,r.height],d=[c,p,s],h=!1,f=i||o;if(u||l||f){let A;if(h){let $=r;if(!cc.has($)||cc.get($).expired){let M={source:$};cc.set($,a.device.importExternalTexture(M))}A={width:p,height:c,format:null,usage:null,texture:cc.get($)}}else{if(f){let N=W().getBool(\"CANVAS2D_WILL_READ_FREQUENTLY_FOR_GPU\");(Yo==null||N!==Wm)&&(Wm=N,Yo=document.createElement(\"canvas\").getContext(\"2d\",{willReadFrequently:Wm})),Yo.canvas.width=p,Yo.canvas.height=c,Yo.drawImage(r,0,0,p,c),r=Yo.canvas}let $=GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING,M=\"rgba8unorm\",I=a.textureManager.acquireTexture(d[1],d[0],M,$);a.queue.copyExternalImageToTexture({source:r},{texture:I},[d[1],d[0]]),A={width:p,height:c,format:M,usage:$,texture:I}}let y=v.sizeFromShape(d),b=v.computeStrides(d),w=new ble(d,s,h),S=[{type:\"uint32\",data:[y]},{type:\"uint32\",data:[s]},{type:\"uint32\",data:[...b]}],C=a.makeTensorInfo([c,p],\"int32\"),E=a.tensorMap.get(C.dataId);E.resourceInfo=A;let _=a.runWebGPUProgram(w,[C],\"int32\",S);return a.disposeData(C.dataId),_}let m=r.data,g=m;if(s!=null&&s!==4){g=new Uint8Array(r.width*r.height*s);let A=m.length,y=0;for(let b=0;b<A;b++)b%4<s&&(g[y++]=m[b])}let x=a.makeTensorInfo(d,\"int32\",new Int32Array(g));return a.uploadToGPU(x.dataId),x}var kle=class{constructor(e,t,a,n,r){this.uniforms=\"varianceEpsilon : f32,\",this.workgroupSize=[128,1,1],this.size=!0,this.variableNames=[\"x\",\"mean\",\"variance\"],T.assertAndGetBroadcastShape(e,t),T.assertAndGetBroadcastShape(e,a),this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),n!=null&&(T.assertAndGetBroadcastShape(e,n),this.variableNames.push(\"offset\")),r!=null&&(T.assertAndGetBroadcastShape(e,r),this.variableNames.push(\"scale\")),this.offsetShape=n,this.scaleShape=r,this.shaderKey=\"batchNorm\"}getUserCode(){let e=\"0.0\";this.offsetShape!=null&&(e=\"getOffsetByOutputIndex(index)\");let t=\"1.0\";return this.scaleShape!=null&&(t=\"getScaleByOutputIndex(index)\"),`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size)\n        {\n          let xValue = getXByOutputIndex(index);\n          let meanValue = getMeanByOutputIndex(index);\n          let varianValue = getVarianceByOutputIndex(index);\n          let offsetValue = ${e};\n          let scaleValue = ${t};\n          let inv = scaleValue * inverseSqrt(varianValue + f32(uniforms.varianceEpsilon));\n          setOutputAtIndex(index,dot(vec3<f32>(xValue, -meanValue, offsetValue), vec3<f32>(inv, inv, 1.0)));\n        }\n      }\n  `}},Ile={kernelName:yi,backendName:\"webgpu\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{x:n,scale:r,offset:s,mean:i,variance:o}=e,{varianceEpsilon:l}=t,u=a,p=[n,i,o],c=null;s!=null&&(c=s.shape,p.push(s));let d=null;r!=null&&(d=r.shape,p.push(r));let h=new kle(n.shape,i.shape,o.shape,c,d),f=[{type:\"float32\",data:[l]}];return u.runWebGPUProgram(h,p,n.dtype,f)}};function Sle(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s,bias:i,preluActivationWeights:o}=t,{strides:l,pad:u,dataFormat:p,dilations:c,dimRoundingMode:d,activation:h,leakyreluAlpha:f}=n,m=T.convertConv2DDataFormat(p),g=T.computeConv2DInfo(r.shape,s.shape,l,c,u,d,!1,m);return B8({x:r,filter:s,convInfo:g,backend:a,bias:i,preluActivationWeights:o,leakyreluAlpha:f,activation:h})}var Tle={kernelName:qr,backendName:\"webgpu\",kernelFunc:Sle};function Cle(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,filter:s,bias:i,preluActivationWeights:o}=t,{strides:l,pad:u,dilations:p,dimRoundingMode:c,activation:d,leakyreluAlpha:h}=n,f=p;f==null&&(f=[1,1]),v.assert(T.eitherStridesOrDilationsAreOne(l,f),()=>`Error in depthwiseConv2d: Either strides or dilations must be 1. Got strides ${l} and dilations '${f}'`);let m=T.computeConv2DInfo(r.shape,s.shape,l,f,u,c,!0),g=[r,s],x=i!=null,A=o!=null;x&&g.push(i),A&&g.push(o);let y=[{type:\"int32\",data:[m.padInfo.top,m.padInfo.left]},{type:\"int32\",data:[m.inHeight,m.inWidth]}],b;return m.outHeight>4&&m.outWidth>4&&m.strideWidth<=2&&m.inChannels===m.outChannels&&m.dilationHeight===1&&m.dilationWidth===1&&m.inChannels%4===0?b=new V8(m,x,d,A):(b=new U8(m,x,d,A),y.push({type:\"int32\",data:[m.filterHeight]},{type:\"int32\",data:[m.filterWidth]},{type:\"int32\",data:[m.strideHeight,m.strideWidth]},{type:\"int32\",data:[m.dilationHeight,m.dilationWidth]})),d===\"leakyrelu\"&&(y.push({type:\"float32\",data:[h]}),b.uniforms+=\" alpha : f32,\"),a.runWebGPUProgram(b,g,\"float32\",y)}var Nle={kernelName:Xr,backendName:\"webgpu\",kernelFunc:Cle},Ele=class{constructor(e,t){this.variableNames=[\"A\",\"indices\"],this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=t,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=`gathernd_${e}`,this.sliceDim=e,this.uniforms=`sliceDim : i32, strides : ${ra(e)},`}getUserCode(){let e;return this.sliceDim>1?e=\"uniforms.strides[j]\":e=\"uniforms.strides\",`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let coords = getCoordsFromIndex(index);\n          var flattenIndex = 0;\n          for (var j = 0; j < uniforms.sliceDim; j = j + 1) {\n            let indexTemp = i32(round(getIndices(coords[0], j)));\n            let strideNum = ${e};\n            flattenIndex = flattenIndex + indexTemp * strideNum;\n          }\n\n          setOutputAtIndex(index, getA(flattenIndex, coords[1]));\n        }\n      }\n      `}};function Rle(e){let{inputs:t,backend:a}=e,{params:n,indices:r}=t,s=r.shape,i=s[s.length-1],o=v.sizeFromShape(n.shape),[l,u,p,c]=T.prepareAndValidate(n,r),d=Ie({inputs:{x:r},backend:a,attrs:{shape:[u,i]}}),h=Ie({inputs:{x:n},backend:a,attrs:{shape:[v.sizeFromShape(n.shape)/p,p]}});if(a.shouldExecuteOnCPU([n,r])||n.dtype===\"string\"){let A=a.readSync(r.dataId),y=a.bufferSync(n),b=Lse(A,y,n.dtype,u,i,p,c,n.shape,o);return a.makeTensorInfo(l,n.dtype,b.values)}let f=new Ele(i,[u,p]),m=[{type:\"int32\",data:[i]},{type:\"int32\",data:c}],g=a.runWebGPUProgram(f,[h,d],h.dtype,m),x=Ie({inputs:{x:g},backend:a,attrs:{shape:l}});return a.disposeData(d.dataId),a.disposeData(h.dataId),a.disposeData(g.dataId),x}var Mle={kernelName:bi,backendName:\"webgpu\",kernelFunc:Rle},$le=class{constructor(e,t){this.variableNames=[\"A\",\"indices\"],this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e.slice(),this.aShape=e,this.outputShape=t,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=\"gather\"}getUserCode(){let e=_le(this.aShape);return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let resRC = getCoordsFromIndex(index);\n          let indexZ = i32(getIndices(resRC.x, resRC.z));\n          let inBounds = select(0.0, 1.0, indexZ >= 0 && indexZ < uniforms.aShape[2]);\n          setOutputAtIndex(index, inBounds * getA(${e}));\n        }\n      }\n    `}};function _le(e){let t=[\"resRC.x\",\"resRC.y\",\"resRC.z\",\"resRC.w\"],a=[];for(let n=0;n<e.length;n++)n===2?a.push(\"indexZ\"):a.push(`${t[n]}`);return a.join()}function q8(e){let{inputs:t,backend:a,attrs:n}=e,{x:r,indices:s}=t,{axis:i,batchDims:o}=n,l=v.parseAxisParam(i,r.shape)[0],u=T.segment_util.collectGatherOpShapeInfo(r,s,l,o),p=v.sizeFromShape(s.shape),c=[],d=Ie({inputs:{x:r},backend:a,attrs:{shape:[u.batchSize,u.outerSize,u.dimSize,u.sliceSize]}}),h=Ie({inputs:{x:s},backend:a,attrs:{shape:[u.batchSize,p/u.batchSize]}});c.push(d),c.push(h);let f=[u.batchSize,u.outerSize,p/u.batchSize,u.sliceSize];if(a.shouldExecuteOnCPU([r,s])){let A=a.tensorMap.get(h.dataId).values,y=Me(h.shape,h.dtype,A),b=a.tensorMap.get(d.dataId).values,w=Me(d.shape,d.dtype,b),S=Bse(w,y,f);return c.forEach(C=>a.disposeData(C.dataId)),a.makeTensorInfo(u.outputShape,S.dtype,S.values)}let m=new $le(d.shape,f),g=a.runWebGPUProgram(m,[d,h],d.dtype);c.push(g);let x=Ie({inputs:{x:g},backend:a,attrs:{shape:u.outputShape}});return c.forEach(A=>a.disposeData(A.dataId)),x}var Ple={kernelName:Ol,backendName:\"webgpu\",kernelFunc:q8},Fle=ua({opType:De.GREATER,cpuKernelImpl:Vse,dtype:\"bool\"}),Ole={kernelName:vi,backendName:\"webgpu\",kernelFunc:Fle},Dle=ua({opType:De.GREATER_EQUAL,dtype:\"bool\",cpuKernelImpl:Wse}),zle={kernelName:wi,backendName:\"webgpu\",kernelFunc:Dle};function Lle(e){let{inputs:t,backend:a}=e,{input:n}=t;return j8(n,!0,a)}var Ble={kernelName:Ed,backendName:\"webgpu\",kernelFunc:Lle},Wle=it({opType:de.IS_FINITE,dtype:\"bool\"}),Vle={kernelName:Dl,backendName:\"webgpu\",kernelFunc:Wle},Ule=it({opType:de.IS_INF,dtype:\"bool\"}),Gle={kernelName:zl,backendName:\"webgpu\",kernelFunc:Ule},Hle=it({opType:de.IS_NAN,dtype:\"bool\"}),jle={kernelName:Ii,backendName:\"webgpu\",kernelFunc:Hle};function qle(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{alpha:s}=n,i=[{type:\"float32\",data:[s]}],o=new mp(r.shape,de.LEAKYRELU);return o.uniforms=\"alpha : f32,\",a.runWebGPUProgram(o,[r],\"float32\",i)}var Xle={kernelName:Si,backendName:\"webgpu\",kernelFunc:qle},Kle=ua({opType:De.LESS,dtype:\"bool\",cpuKernelImpl:Gse}),Zle={kernelName:Ti,backendName:\"webgpu\",kernelFunc:Kle},Yle=ua({opType:De.LESS_EQUAL,dtype:\"bool\",cpuKernelImpl:Use}),Jle={kernelName:Ci,backendName:\"webgpu\",kernelFunc:Yle},Qle=it({opType:de.LOG,cpuKernelImpl:Hse}),eue={kernelName:Ni,backendName:\"webgpu\",kernelFunc:Qle},tue=it({opType:de.LOG1P}),aue={kernelName:Ll,backendName:\"webgpu\",kernelFunc:tue},nue=ua({opType:De.LOGICAL_AND,dtype:\"bool\"}),rue={kernelName:Ei,backendName:\"webgpu\",kernelFunc:nue},sue=it({opType:de.LOGICAL_NOT}),iue={kernelName:Ri,backendName:\"webgpu\",kernelFunc:sue},oue=ua({opType:De.MAX,cpuKernelImpl:qse}),lue={kernelName:$i,backendName:\"webgpu\",kernelFunc:oue};function uue(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{filterSize:s,strides:i,pad:o,dimRoundingMode:l}=n,u=1,p=T.computePool2DInfo(r.shape,s,i,u,o,l);return O8(r,p,\"max\",a)}var due={kernelName:_i,backendName:\"webgpu\",kernelFunc:uue};function pue(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;return ko(r,s,i,\"min\",a)}var cue={kernelName:Fi,backendName:\"webgpu\",kernelFunc:pue},hue=ua({opType:De.MIN,cpuKernelImpl:Xse}),fue={kernelName:Oi,backendName:\"webgpu\",kernelFunc:hue},mue=class{constructor(e,t,a){this.uniforms=\"\",this.variableNames=[\"x\"],this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=t.map((n,r)=>n[0]+e[r]+n[1]),this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.xShape=e,t.map((n,r)=>{this.uniforms+=` pad${r} : vec2<i32>,`}),this.offset=a===\"reflect\"?0:1,this.shaderKey=`mirrorPad_${a}`}getUserCode(){let e=this.xShape.length,t=this.xShape.map((l,u)=>`uniforms.pad${u}[0]`).join(\",\"),a=this.xShape.map((l,u)=>`uniforms.pad${u}[0] + uniforms.xShape${e>1?`[${u}]`:\"\"}`).join(\",\"),n=e===1?\"start\":\"start[i]\",r=e===1?\"end\":\"end[i]\",s=e===1?\"outC\":\"outC[i]\",i=ra(e),o=e>1?[\"coords[0]\",\"coords[1]\",\"coords[2]\",\"coords[3]\"].slice(0,e):\"coords\";return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let start = ${i}(${t});\n          let end = ${i}(${a});\n          var outC = getCoordsFromIndex(index);\n          for (var i = 0; i < ${e}; i = i + 1) {\n            if (${s} < ${n}) {\n              ${s} = ${n} * 2 - ${s} - ${this.offset};\n            } else if(${s} >= ${r}) {\n              ${s} = (${r} - 1) * 2 - ${s} + ${this.offset};\n            }\n          }\n          let coords = outC - start;\n          setOutputAtIndex(index, getX(${o}));\n        }\n      }\n    `}},gue={kernelName:Di,backendName:\"webgpu\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{x:n}=e,{paddings:r,mode:s}=t,i=a,o=r.map(u=>({type:\"int32\",data:[u[0],u[1]]})),l=new mue(n.shape,r,s);return i.runWebGPUProgram(l,[n],n.dtype,o)}},xue=ua({opType:De.MOD}),Aue={kernelName:Wl,backendName:\"webgpu\",kernelFunc:xue};function yue(e){let{inputs:t,backend:a}=e,{x:n}=t;if(a.shouldExecuteOnCPU([n])){let s=a.tensorMap.get(n.dataId),[i,o]=Zse(s.values,n.shape,n.dtype);return a.makeTensorInfo(o,n.dtype,i)}let r=new mp(n.shape,de.NEG);return a.runWebGPUProgram(r,[n],n.dtype)}var bue={kernelName:Vl,backendName:\"webgpu\",kernelFunc:yue};function vue(e){console.warn(\"tf.nonMaxSuppression() in webgpu locks the UI thread. Call tf.nonMaxSuppressionAsync() instead\");let{inputs:t,backend:a,attrs:n}=e,{boxes:r,scores:s}=t,{maxOutputSize:i,iouThreshold:o,scoreThreshold:l}=n,u=a.readSync(r.dataId),p=a.readSync(s.dataId),{selectedIndices:c}=Tn.nonMaxSuppressionV3Impl(u,p,i,o,l);return a.makeTensorInfo([c.length],\"int32\",new Int32Array(c))}var wue={kernelName:Bi,backendName:\"webgpu\",kernelFunc:vue};function kue(e){console.warn(\"tf.nonMaxSuppression() in webgpu locks the UI thread. Call tf.nonMaxSuppressionAsync() instead\");let{inputs:t,backend:a,attrs:n}=e,{boxes:r,scores:s}=t,{maxOutputSize:i,iouThreshold:o,scoreThreshold:l,softNmsSigma:u}=n,p=a.readSync(r.dataId),c=a.readSync(s.dataId),d=i,h=o,f=l,m=u,{selectedIndices:g,selectedScores:x}=Tn.nonMaxSuppressionV5Impl(p,c,d,h,f,m);return[a.makeTensorInfo([g.length],\"int32\",new Int32Array(g)),a.makeTensorInfo([x.length],\"float32\",new Float32Array(x))]}var Iue={kernelName:Wi,backendName:\"webgpu\",kernelFunc:kue},Sue=class{constructor(e,t){this.variableNames=[\"x\"],this.uniforms=\"onValue : f32, offValue : f32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=[e,t],this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=\"onehot\"}getUserCode(){return`\n      ${Ce(\"index\")} {\n        if(index < uniforms.size) {\n          let coords = getCoordsFromIndex(index);\n          setOutputAtIndex(index, mix(uniforms.offValue, uniforms.onValue,\n                                      f32(i32(round(getX(coords.x))) == coords.y)));\n        }\n      }\n    `}};function Tue(e){let{inputs:t,backend:a,attrs:n}=e,{indices:r}=t,{dtype:s,depth:i,onValue:o,offValue:l}=n,u=v.sizeFromShape(r.shape),p=new Sue(u,i),c=Ie({inputs:{x:r},backend:a,attrs:{shape:[u]}}),d=[{type:\"float32\",data:[o]},{type:\"float32\",data:[l]}],h=a.runWebGPUProgram(p,[c],s,d);a.disposeData(c.dataId);let f=[...r.shape,i],m=Ie({inputs:{x:h},backend:a,attrs:{shape:f}});return a.disposeData(h.dataId),m}var Cue={kernelName:Vi,backendName:\"webgpu\",kernelFunc:Tue};function Vc(e){let{inputs:t,backend:a}=e,{x:n}=t;if(n.dtype===\"complex64\"){let r=gp({inputs:{input:n},backend:a}),s=Vc({inputs:{x:r},backend:a}),i=jh({inputs:{input:n},backend:a}),o=Vc({inputs:{x:i},backend:a}),l=wo({inputs:{real:s,imag:o},backend:a});return a.disposeData(r.dataId),a.disposeData(s.dataId),a.disposeData(i.dataId),a.disposeData(o.dataId),l}else return Cr({attrs:{shape:n.shape,dtype:n.dtype,value:n.dtype===\"string\"?\"\":0},backend:a})}var Nue={kernelName:nu,backendName:\"webgpu\",kernelFunc:Vc};function X8(e){let{inputs:t,backend:a}=e,{x:n}=t;if(n.dtype===\"string\")throw new Error(\"onesLike is not supported under string dtype\");if(n.dtype===\"complex64\"){let r=gp({inputs:{input:n},backend:a}),s=X8({inputs:{x:r},backend:a}),i=jh({inputs:{input:n},backend:a}),o=Vc({inputs:{x:i},backend:a}),l=wo({inputs:{real:s,imag:o},backend:a});return a.disposeData(r.dataId),a.disposeData(s.dataId),a.disposeData(i.dataId),a.disposeData(o.dataId),l}else return Cr({attrs:{shape:n.shape,dtype:n.dtype,value:1},backend:a})}var Eue={kernelName:Gl,backendName:\"webgpu\",kernelFunc:X8};function Rue(e){let{inputs:t,backend:a,attrs:n}=e,{axis:r}=n;if(t.length===1)return D1({inputs:{input:t[0]},backend:a,attrs:{dim:r}});let s=t[0].shape,i=t[0].dtype;t.forEach(p=>{v.assertShapesMatch(s,p.shape,\"All tensors passed to stack must have matching shapes\"),v.assert(i===p.dtype,()=>\"All tensors passed to stack must have matching dtypes\")});let o=[],l=t.map(p=>{let c=D1({inputs:{input:p},backend:a,attrs:{dim:r}});return o.push(c),c}),u=L8({inputs:l,backend:a,attrs:{axis:r}});return o.forEach(p=>a.disposeData(p.dataId)),u}var Mue={kernelName:Hl,backendName:\"webgpu\",kernelFunc:Rue},$ue=class{constructor(e,t){this.variableNames=[\"x\"],this.uniforms=\"constantValue : f32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=t.map((a,n)=>a[0]+e[n]+a[1]),this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),t.map((a,n)=>{this.uniforms+=` pad${n} : vec2<i32>,`}),this.xShape=e,this.shaderKey=\"pad\"}getUserCode(){let e=this.xShape.length,t=ra(e),a=this.xShape.map((u,p)=>`uniforms.pad${p}[0]`).join(\",\"),n=this.xShape.map((u,p)=>`uniforms.pad${p}[0] + uniforms.xShape${e>1?`[${p}]`:\"\"}`).join(\",\"),r=e>1?`${t}(${a})`:`${a}`,s=e>1?`${t}(${n})`:`${n}`,i=e>1?\"any(outC < start)\":\"outC < start\",o=e>1?\"any(outC >= end)\":\"outC >= end\",l=e>1?[\"coords[0]\",\"coords[1]\",\"coords[2]\",\"coords[3]\"].slice(0,e):\"coords\";return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let start = ${r};\n          let end = ${s};\n          let outC = getCoordsFromIndex(index);\n\n          if (${i} || ${o}) {\n            setOutputAtIndex(index, uniforms.constantValue);\n          } else {\n            let coords = outC - start;\n            setOutputAtIndex(index, getX(${l}));\n          }\n        }\n      }\n    `}},K8=e=>{let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{paddings:s,constantValue:i}=n;if(s.every(u=>v.arraysEqual(u,[0,0])))return Ya({inputs:{x:r},backend:a});if(v.sizeFromShape(r.shape)===0){let u=s.map((p,c)=>p[0]+r.shape[c]+p[1]);return Cr({backend:a,attrs:{shape:u,value:i,dtype:r.dtype}})}let o=[{type:\"float32\",data:[i]}];s.map(u=>o.push({type:\"int32\",data:[u[0],u[1]]}));let l=new $ue(r.shape,s);return a.runWebGPUProgram(l,[r],r.dtype,o)},_ue={kernelName:Ui,backendName:\"webgpu\",kernelFunc:K8},Pue=ua({opType:De.POW}),Fue={kernelName:Gi,backendName:\"webgpu\",kernelFunc:Pue};function Oue(e){let{inputs:t,backend:a}=e,{x:n,alpha:r}=t,s=new P1(De.PRELU,n.shape,r.shape);return a.runWebGPUProgram(s,[n,r],\"float32\")}var Due={kernelName:Hi,backendName:\"webgpu\",kernelFunc:Oue};function zue(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{axis:s,keepDims:i}=n;return ko(r,s,i,\"prod\",a)}var Lue={kernelName:ji,backendName:\"webgpu\",kernelFunc:zue},Bue=e=>{let{backend:t,attrs:a}=e,{start:n,stop:r,step:s,dtype:i}=a,o=Qse(n,r,s,i);return t.makeTensorInfo([o.length],i,o)},Wue={kernelName:jl,backendName:\"webgpu\",kernelFunc:Bue},Z8=ua({opType:De.DIV}),Vue={kernelName:ci,backendName:\"webgpu\",kernelFunc:Z8},Uue=it({opType:de.RECIPROCAL}),Gue={kernelName:qi,backendName:\"webgpu\",kernelFunc:Uue},Hue=it({opType:de.RELU}),jue={kernelName:Xi,backendName:\"webgpu\",kernelFunc:Hue},que=it({opType:de.RELU6}),Xue={kernelName:Yi,backendName:\"webgpu\",kernelFunc:que},Kue=class{constructor(e,t,a){this.variableNames=[\"x\"],this.uniforms=\"adjustHeightWidth : vec2<f32>, halfPixelCenters : f32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=[e[0],t,a,e[3]],this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=\"resizeBilinear\"}getUserCode(){return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n        let coords = getCoordsFromIndex(index);\n          let b = coords[0];\n          let d = coords[3];\n          let rc = coords.yz;\n\n          let effectiveInSize = vec2<f32>(\n            f32(uniforms.xShape.y) - uniforms.adjustHeightWidth[0],\n            f32(uniforms.xShape.z) - uniforms.adjustHeightWidth[1]);\n\n          let effectiveOutSize = vec2<f32>(\n            f32(uniforms.outShape.y) - uniforms.adjustHeightWidth[0],\n            f32(uniforms.outShape.z) - uniforms.adjustHeightWidth[1]);\n\n          let effectiveInputOverOutputRatioRC =\n              effectiveInSize / effectiveOutSize;\n\n          // Fractional source index\n          let sourceFracIndexRC =\n            (vec2<f32>(rc) + vec2<f32>(uniforms.halfPixelCenters)) *\n            effectiveInputOverOutputRatioRC - vec2<f32>(uniforms.halfPixelCenters);\n\n          // Compute the four integer indices.\n          let sourceFloorRC = vec2<i32>(sourceFracIndexRC);\n          let sourceCeilRC = vec2<i32>(\n            min(vec2<f32>(uniforms.xShape.yz) - vec2<f32>(1.0), ceil(sourceFracIndexRC)));\n\n          let topLeft = getX(b, sourceFloorRC.x, sourceFloorRC.y, d);\n          let bottomLeft = getX(b, sourceCeilRC.x, sourceFloorRC.y, d);\n          let topRight = getX(b, sourceFloorRC.x, sourceCeilRC.y, d);\n          let bottomRight = getX(b, sourceCeilRC.x, sourceCeilRC.y, d);\n\n          let fracRC = sourceFracIndexRC - vec2<f32>(sourceFloorRC);\n\n          let top = topLeft + (topRight - topLeft) * fracRC.y;\n          let bottom = bottomLeft + (bottomRight - bottomLeft) * fracRC.y;\n          let newValue = top + (bottom - top) * fracRC.x;\n\n          setOutputAtIndex(index, newValue);\n        }\n      }\n    `}};function Zue(e){let{inputs:t,backend:a,attrs:n}=e,{images:r}=t,{alignCorners:s,size:i,halfPixelCenters:o}=n,[l,u]=i,p=s&&l>1?1:0,c=s&&u>1?1:0,d=[{type:\"float32\",data:[p,c]},{type:\"float32\",data:[o?.5:0]}],h=new Kue(r.shape,l,u);return a.runWebGPUProgram(h,[r],\"float32\",d)}var Yue={kernelName:Zi,backendName:\"webgpu\",kernelFunc:Zue},Jue=class{constructor(e,t,a,n){this.variableNames=[\"x\"],this.uniforms=\"adjustHeightWidth : vec2<f32>, roundBase : f32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=[e[0],t,a,e[3]],this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.halfPixelCenters=n,this.shaderKey=`resizeNearest_${n}`}getUserCode(){let e;return this.halfPixelCenters?e=\"max((vec2<f32>(rc) + vec2<f32>(0.5)) * effectiveInputOverOutputRatioRC, vec2<f32>(0.0))\":e=\"vec2<f32>(rc) * effectiveInputOverOutputRatioRC\",`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let coords = getCoordsFromIndex(index);\n          let b = coords[0];\n          let d = coords[3];\n          let rc = coords.yz;\n\n          let effectiveInSize = vec2<f32>(\n            f32(uniforms.xShape.y) - uniforms.adjustHeightWidth[0],\n            f32(uniforms.xShape.z) - uniforms.adjustHeightWidth[1]);\n\n          let effectiveOutSize = vec2<f32>(\n            f32(uniforms.outShape.y) - uniforms.adjustHeightWidth[0],\n            f32(uniforms.outShape.z) - uniforms.adjustHeightWidth[1]);\n\n          let effectiveInputOverOutputRatioRC =\n              effectiveInSize / effectiveOutSize;\n\n          // Fractional source index\n          let sourceFracIndexRC = ${e};\n\n          // Compute the coordinators of nearest neighbor point.\n          let inputShapeRC = vec2<f32>(f32(uniforms.xShape.y), f32(uniforms.xShape.z));\n          let sourceNearestRC = vec2<i32>(\n            min(inputShapeRC - 1.0, floor(sourceFracIndexRC + uniforms.roundBase)));\n          let newValue = getX(b, sourceNearestRC.x, sourceNearestRC.y, d);\n\n          setOutputAtIndex(index, newValue);\n        }\n      }\n    `}};function Que(e){let{inputs:t,backend:a,attrs:n}=e,{images:r}=t,{alignCorners:s,halfPixelCenters:i,size:o}=n,[l,u]=o,p=s&&l>1?1:0,c=s&&u>1?1:0,d=[{type:\"float32\",data:[p,c]},{type:\"float32\",data:[s?.5:0]}],h=new Jue(r.shape,l,u,i);return a.runWebGPUProgram(h,[r],r.dtype,d)}var ede={kernelName:Ki,backendName:\"webgpu\",kernelFunc:Que},tde=class{constructor(e){this.variableNames=[\"x\"],this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.uniforms=\" axis : vec4<i32>,\",this.shaderKey=\"reverse\"}getUserCode(){return`\n      \n      // Using uniform variables as judging conditions, so the function has\n      // coherent execution within all threads.\n      fn getReverseCoords(coords : vec4<i32>) -> vec4<i32> {\n        var reverseCoords = coords;\n        if (uniforms.axis[0] == 1) {\n          reverseCoords[0] = uniforms.xShape[0] - coords[0] - 1;\n        }\n        if (uniforms.axis[1] == 1) {\n          reverseCoords[1] = uniforms.xShape[1] - coords[1] - 1;\n        }\n        if (uniforms.axis[2] == 1) {\n          reverseCoords[2] = uniforms.xShape[2] - coords[2] - 1;\n        }\n        if (uniforms.axis[3] == 1) {\n          reverseCoords[3] = uniforms.xShape[3] - coords[3] - 1;\n        }\n\n        return reverseCoords;\n      }\n    \n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let coords = getCoordsFromIndex(index);\n          let reverseCoords = getReverseCoords(coords);\n          setOutputAtIndex(index, getX(reverseCoords[0],\n              reverseCoords[1], reverseCoords[2], reverseCoords[3]));\n        }\n      }\n    `}};function ade(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{dims:s}=n,i=r.shape.length;if(i===0)return Ya({inputs:{x:r},backend:a});let o=r.shape,l=[1,1,1,1];o.forEach((g,x)=>{let A=x+4-i;l[A]=g});let u=v.parseAxisParam(s,r.shape),p=[0,0,0,0];u.forEach(g=>{let x=g+4-i;p[x]=1});let c=[{type:\"int32\",data:p}],d=Ie({inputs:{x:r},backend:a,attrs:{shape:l}}),h=new tde(l),f=a.runWebGPUProgram(h,[d],d.dtype,c);a.disposeData(d.dataId);let m=Ie({inputs:{x:f},backend:a,attrs:{shape:o}});return a.disposeData(f.dataId),m}var nde={kernelName:Ji,backendName:\"webgpu\",kernelFunc:ade},rde=class{constructor(e,t){this.outputShape=[],this.variableNames=[\"x\"],this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.uniforms=`centerX : f32, centerY : f32, sinRadians : f32,\n          cosRadians : f32,`,this.shaderKey=\"rotate\",this.outputShape=e,typeof t==\"number\"?(this.uniforms+=\" fillValue : f32,\",this.fillSnippet=\"var outputValue = uniforms.fillValue;\",this.shaderKey+=\"_float\"):(this.uniforms+=\" fillValue : vec3<f32>,\",this.fillSnippet=\"var outputValue = uniforms.fillValue[coords[3]];\",this.shaderKey+=\"_vec3\")}getUserCode(){return`\n        ${Ce(\"index\")} {\n          if (index < uniforms.size) {\n            let coords = getCoordsFromIndex(index);\n            let coordXFloat = (f32(coords[2]) - uniforms.centerX) *\n                uniforms.cosRadians - (f32(coords[1]) - uniforms.centerY) *\n                uniforms.sinRadians;\n            let coordYFloat = (f32(coords[2]) - uniforms.centerX) *\n                uniforms.sinRadians + (f32(coords[1]) - uniforms.centerY) *\n                uniforms.cosRadians;\n            let coordX = i32(round(coordXFloat + uniforms.centerX));\n            let coordY = i32(round(coordYFloat + uniforms.centerY));\n            ${this.fillSnippet}\n            if(coordX >= 0 && coordX < uniforms.xShape[2] && coordY >= 0 &&\n                coordY < uniforms.xShape[1]) {\n              outputValue = getX(coords[0], coordY, coordX, coords[3]);\n            }\n            setOutputAtIndex(index, outputValue);\n          }\n        }\n      `}},sde={kernelName:mo,backendName:\"webgpu\",kernelFunc:({inputs:e,attrs:t,backend:a})=>{let{image:n}=e,{radians:r,fillValue:s,center:i}=t,o=a,l=new rde(n.shape,s),[u,p]=T.getImageCenter(i,n.shape[1],n.shape[2]),c=[{type:\"float32\",data:[u]},{type:\"float32\",data:[p]},{type:\"float32\",data:[Math.sin(r)]},{type:\"float32\",data:[Math.cos(r)]}];return typeof s==\"number\"?c.push({type:\"float32\",data:[Number.parseFloat(s.toFixed(2))]}):c.push({type:\"float32\",data:s}),o.runWebGPUProgram(l,[n],n.dtype,c)}},ide=it({opType:de.RSQRT,cpuKernelImpl:eie}),ode={kernelName:Qi,backendName:\"webgpu\",kernelFunc:ide},vc=class{constructor(e,t,a,n,r,s,i,o=!0){this.variableNames=[\"updates\",\"indices\"],this.workgroupSize=[64,1,1],this.atomic=!0,this.outputShape=s,this.type=i,this.sumDupeIndices=o,this.dispatchLayout=Ve(e),this.dispatch=Ne(this.dispatchLayout,e,this.workgroupSize),this.sliceDimGreaterThanOne=t>1,this.shaderKey=`scatter_${a}_${n}_${this.sliceDimGreaterThanOne}_${i}_${o}`;let l=ra(r.length);this.uniforms=`sliceDim : i32, strides: ${l}, updatesSize: i32,`,this.updatesRank=n,this.indicesRank=a}getUserCode(){let e=\"\";this.indicesRank===1?e=\"coords[0]\":this.indicesRank===2&&(e=\"coords[0], j\");let t=`getIndices(${e})`,a=this.sliceDimGreaterThanOne?\"uniforms.strides[j]\":\"uniforms.strides\",n=\"\",r=\"\";this.dispatchLayout.x.length===1?(n=\"flattenedIndex\",r=`\n      fn getUpdatesCoordsFromFlatIndex(index : i32) -> i32 {\n        return index;\n      }\n      `):this.dispatchLayout.x.length===2&&(n=\"vec2<i32>(flattenedIndex, coords[1])\",r=`\n      fn getUpdatesCoordsFromFlatIndex(index : i32) -> vec2<i32> {\n        // N.B. |updates| could be a scalar tensor, conceptually representing a\n        // 2D tensor with all values equal to that. By design, its size must be\n        // the same as |outShape[1]| in one dimension, and |indicesShape[0]|\n        // gives the other.\n        let sliceSize = uniforms.outShape[1];\n        let d0 = index / sliceSize;\n        let d1 = index - d0 * sliceSize;\n        return vec2<i32>(d0, d1);\n      }\n      `);let s=`getUpdates(${Array.from({length:this.updatesRank},(o,l)=>`coords[${l}]`).join(\", \")})`,i=(o,l)=>{let u=`atomicAdd(${o}, bitcast<i32>(${l}))`;this.type===\"float32\"&&(u=`\n          {\n            var oldBits = 0;\n            var newBits = bitcast<i32>(${l});\n            loop {\n              let info = atomicCompareExchangeWeak(${o}, oldBits, newBits);\n              if (info.exchanged) {\n                break;\n              }\n              oldBits = info.old_value;\n              let oldValue = bitcast<f32>(oldBits);\n              let newValue = oldValue + (${l});\n              newBits = bitcast<i32>(newValue);\n            }\n          }\n        `);let p=`atomicStore(${o}, bitcast<i32>(${l}));`;return this.sumDupeIndices?u:p};return`\n    ${r}\n\n      ${Ce(\"index\")} {\n        if (index < uniforms.updatesSize) {\n          let coords = getUpdatesCoordsFromFlatIndex(index);\n          var flattenedIndex = 0;\n          for (var j = 0; j < uniforms.sliceDim; j = j + 1) {\n            let indexInside = i32(round(${t}));\n            flattenedIndex = flattenedIndex + indexInside * ${a};\n          }\n          let updateValue =\n              ${ad(this.type,!1)}(${s});\n          let flatIndex = getOutputIndexFromCoords(${n});\n\n          ${i(\"&result[flatIndex]\",\"updateValue\")};\n        }\n      }`}};function lde(e){let{inputs:t,backend:a,attrs:n}=e,{indices:r,updates:s}=t,{shape:i}=n,{sliceRank:o,numUpdates:l,sliceSize:u,strides:p,outputSize:c}=T.calculateShapes(s,r,i),d=[c/u,u];if(c===0)return a.makeTensorInfo(i,r.dtype);let h=Ie({inputs:{x:r},backend:a,attrs:{shape:[l,o]}}),f=Ie({inputs:{x:s},backend:a,attrs:{shape:[l,u]}}),m=f.dtype,g=Cr({backend:a,attrs:{shape:d,value:0,dtype:m}}),x=v.sizeFromShape(f.shape),A=[{type:\"int32\",data:[o]},{type:\"int32\",data:p},{type:\"int32\",data:[x]}],y=new vc(f.shape,o,h.shape.length,f.shape.length,p,d,m),b=a.runWebGPUProgram(y,[f,h],m,A,g),w=Ie({inputs:{x:b},backend:a,attrs:{shape:i}});return a.disposeData(h.dataId),a.disposeData(f.dataId),a.disposeData(b.dataId),w}var ude={kernelName:eo,backendName:\"webgpu\",kernelFunc:lde},dde=class{constructor(e,t){this.outputShape=[],this.variableNames=[\"sortedSequence\",\"values\"],this.uniforms=\"numInputs : i32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.side=t,this.shaderKey=`search_sorted_${t}`}getUserCode(){return`\n      fn findBound(batch: i32, value: f32) -> i32 {\n        var left = i32(0);\n        var right = uniforms.numInputs;\n        while (left < right) {\n          var mid = (left + right) / 2;\n          if (getSortedSequence(batch, mid) ${this.side===\"left\"?\"<\":\"<=\"} value) {\n            left = mid + 1;\n          } else {\n            right = mid;\n          }\n        }\n        return right;\n      }\n\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let coords = getCoordsFromIndex(index);\n          let value = getValuesByOutputIndex(index);\n          setOutputAtIndexI32(index, findBound(coords[0], value));\n        }\n      }\n    `}};function pde(e){let{inputs:t,backend:a,attrs:n}=e,{sortedSequence:r,values:s}=t,{side:i}=n,o=new dde([s.shape[0],s.shape[1]],i),l=[{type:\"int32\",data:[r.shape[1]]}];return a.runWebGPUProgram(o,[r,s],\"int32\",l)}var cde={kernelName:$d,backendName:\"webgpu\",kernelFunc:pde},hde=class{constructor(e,t,a){this.variableNames=[\"c\",\"a\",\"b\"],this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=t,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.cRank=e,this.rank=a,this.shaderKey=\"select\"}getUserCode(){let e,t;if(this.rank>4)throw Error(`Where for rank ${this.rank} is not yet supported`);if(this.rank===1)t=\"resRC\",e=\"resRC\";else{let a=[\"resRC.x\",\"resRC.y\",\"resRC.z\",\"resRC.w\"],n=[],r=[];for(let s=0;s<this.outputShape.length;s++)r.push(`${a[s]}`),s<this.cRank&&n.push(`${a[s]}`);e=n.join(),t=r.join()}return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let resRC = getCoordsFromIndex(index);\n          let cVal = getC(${e});\n          if (cVal >= 1.0) {\n            setOutputAtIndex(index, getA(${t}));\n          } else {\n            setOutputAtIndex(index, getB(${t}));\n          }\n        }\n      }\n    `}};function fde(e){let{inputs:t,backend:a}=e,{condition:n,t:r,e:s}=t,i=new hde(n.shape.length,r.shape,r.shape.length);return a.runWebGPUProgram(i,[n,r,s],ca(r.dtype,s.dtype))}var mde={kernelName:Kl,backendName:\"webgpu\",kernelFunc:fde},gde=it({opType:de.SIGMOID}),xde={kernelName:ao,backendName:\"webgpu\",kernelFunc:gde},Ade=it({opType:de.SIN}),yde={kernelName:to,backendName:\"webgpu\",kernelFunc:Ade},bde=it({opType:de.SINH}),vde={kernelName:Yl,backendName:\"webgpu\",kernelFunc:bde},Y8=ua({opType:De.SUB,cpuKernelImpl:iie,supportsComplex:!0}),wde={kernelName:lo,backendName:\"webgpu\",kernelFunc:Y8};function kde(e){let{inputs:t,backend:a,attrs:n}=e,{logits:r}=t,{dim:s}=n,i=v.parseAxisParam([s],r.shape),o=W3({inputs:{x:r},backend:a,attrs:{reductionIndices:i,keepDims:!1}}),l=T.expandShapeToKeepDim(o.shape,i),u=Ie({inputs:{x:o},backend:a,attrs:{shape:l}}),p=Y8({inputs:{a:r,b:u},backend:a}),c=H8({inputs:{x:p},backend:a}),d=V3({inputs:{x:c},backend:a,attrs:{axis:i,keepDims:!1}}),h=Ie({inputs:{x:d},backend:a,attrs:{shape:l}}),f=Z8({inputs:{a:c,b:h},backend:a});return a.disposeData(o.dataId),a.disposeData(u.dataId),a.disposeData(p.dataId),a.disposeData(c.dataId),a.disposeData(d.dataId),a.disposeData(h.dataId),f}var Ide={kernelName:so,backendName:\"webgpu\",kernelFunc:kde},Sde=e=>{let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{blockShape:s,paddings:i}=n;v.assert(r.shape.length<=4,()=>\"spaceToBatchND for rank > 4 with a WebGPU backend not implemented yet\");let o=s.reduce((x,A)=>x*A),l=[[0,0]];l.push(...i);for(let x=1+s.length;x<r.shape.length;++x)l.push([0,0]);let u=[],p=K8({inputs:{x:r},backend:a,attrs:{paddings:l,constantValue:0}}),c=T.getReshaped(p.shape,s,o,!1),d=T.getPermuted(c.length,s.length,!1),h=T.getReshapedPermuted(p.shape,s,o,!1),f=Ie({inputs:{x:p},backend:a,attrs:{shape:c}}),m=vr({inputs:{x:f},backend:a,attrs:{perm:d}}),g=Ie({inputs:{x:m},backend:a,attrs:{shape:h}});return u.push(p),u.push(f),u.push(m),u.forEach(x=>a.disposeData(x.dataId)),g},Tde={kernelName:Jl,backendName:\"webgpu\",kernelFunc:Sde},Cde=class{constructor(e,t){this.variableNames=[\"A\"],this.workgroupSize=[64,1,1],this.size=!0;let a=new Array(e.length);for(let n=0;n<a.length;n++)a[n]=e[n]*t[n];this.outputShape=a,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.rank=this.outputShape.length,this.shaderKey=\"tile\"}getUserCode(){let e=Nde(this.rank,\"uniforms.\");return`\n      ${Ce(\"index\")} {\n        if (index < uniforms.size) {\n          let resRC = getCoordsFromIndex(index);\n          setOutputAtIndex(index, getA(${e}));\n        }\n      }\n    `}};function Nde(e,t=\"\"){if(e>=5)throw Error(`Tile for rank ${e} is not yet supported`);if(e===1)return`(resRC % ${t}aShape)`;let a=[\"resRC.x\",\"resRC.y\",\"resRC.z\",\"resRC.w\"],n=[];for(let r=0;r<e;r++)n.push(`(${a[r]} % ${t}aShape[${r}])`);return n.join()}function J8(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{reps:s}=n;if(a.shouldExecuteOnCPU([r])||r.dtype===\"string\"||r.shape.length>=5){let o=a.readSync(r.dataId),l=r.dtype===\"string\"?o.map(c=>v.decodeString(c)):o,u=Me(r.shape,r.dtype,l),p=oie(u,s);return a.makeTensorInfo(p.shape,p.dtype,p.values)}let i=new Cde(r.shape,s);return a.runWebGPUProgram(i,[r],r.dtype)}var Ede={kernelName:ns,backendName:\"webgpu\",kernelFunc:J8};function Rde(e){let{inputs:t,backend:a,attrs:n}=e,{sparseIndices:r,sparseValues:s,defaultValue:i}=t,{outputShape:o}=n,{sliceRank:l,numUpdates:u,sliceSize:p,strides:c,outputSize:d}=T.calculateShapes(s,r,o),h=!1;if(s.dtype===\"string\"){let E=a.bufferSync(r),_=a.bufferSync(s),$=v.decodeString(a.readSync(i.dataId)[0]),M=tie(E,_,o,d,p,u,l,c,$,h);return a.makeTensorInfo(o,M.dtype,M.values)}let f=[d/p,p],m=Ie({inputs:{x:r},backend:a,attrs:{shape:[u,l]}}),g=s.shape.length?Ie({inputs:{x:s},backend:a,attrs:{shape:[u,p]}}):Ya({inputs:{x:s},backend:a}),x=g.dtype,A=a.makeTensorInfo([],x,v.makeZerosTypedArray(1,x)),y=Ie({inputs:{x:i},backend:a,attrs:{shape:Array(f.length).fill(1)}}),b=J8({inputs:{x:y},backend:a,attrs:{reps:f}}),w=v.sizeFromShape([u,p]),S=[{type:\"int32\",data:[l]},{type:\"int32\",data:c},{type:\"int32\",data:[w]}];switch(u){case 0:break;case 1:{let E=new vc([u,p],l,m.shape.length,g.shape.length,c,f,x,h);a.runWebGPUProgram(E,[g,m],x,S,b)}break;default:{let E=new vc([u,p],l,m.shape.length,A.shape.length,c,f,x,h);a.runWebGPUProgram(E,[A,m],x,S,b)}{let E=new vc([u,p],l,m.shape.length,g.shape.length,c,f,x);a.runWebGPUProgram(E,[g,m],x,S,b)}}let C=Ie({inputs:{x:b},backend:a,attrs:{shape:o}});return a.disposeData(m.dataId),a.disposeData(g.dataId),a.disposeData(y.dataId),a.disposeData(A.dataId),a.disposeData(b.dataId),C}var Mde={kernelName:Ld,backendName:\"webgpu\",kernelFunc:Rde};function $de(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{numOrSizeSplits:s,axis:i}=n,o=v.parseAxisParam(i,r.shape)[0],l=T.prepareSplitSize(r,s,o),u=r.shape.length,p=new Array(u).fill(0),c=r.shape.slice();return l.map(d=>{let h=[...c];h[o]=d;let f=Au({inputs:{x:r},backend:a,attrs:{begin:p,size:h}});return p[o]+=d,f})}var _de={kernelName:Ql,backendName:\"webgpu\",kernelFunc:$de},Pde=it({opType:de.SQRT}),Fde={kernelName:no,backendName:\"webgpu\",kernelFunc:Pde},Ode={kernelName:Bd,backendName:\"webgpu\",kernelFunc:({inputs:e,backend:t})=>{let{x:a}=e,n=t,r=new mp(a.shape,de.SQUARE);return n.runWebGPUProgram(r,[a],a.dtype)}},Dde=ua({opType:De.SQUARED_DIFFERENCE}),zde={kernelName:io,backendName:\"webgpu\",kernelFunc:Dde},Lde=class{constructor(e){this.variableNames=[\"x\"],this.workPerThread=1,this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize,[this.workPerThread,1,1]);let t=ra(this.outputShape.length);this.uniforms=`begin : ${t},  strides : ${t}, `,this.shaderKey=\"stridedSlice\"}getUserCode(){let e=this.outputShape.length,t=\"\";if(e===1)t=\"coords * uniforms.strides + uniforms.begin\";else{let a=0;t=this.outputShape.map((n,r)=>(a++,this.outputShape.length===1?`coords * uniforms.strides[${r}] + uniforms.begin[${r}]`:`coords[${a-1}] * uniforms.strides[${r}] + uniforms.begin[${r}]`)).join(\",\")}return`\n       ${Ce(\"index\")} {\n         if (index < uniforms.size) {\n           let coords = getCoordsFromIndex(index);\n           setOutputAtIndex(index, getX(${t}));\n         }\n       }\n     `}};function Bde(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{begin:s,end:i,strides:o,beginMask:l,endMask:u,ellipsisMask:p,newAxisMask:c,shrinkAxisMask:d}=n,{finalShapeSparse:h,finalShape:f,isIdentity:m,sliceDim0:g,isSimpleSlice:x,begin:A,end:y,strides:b}=It.sliceInfo(r.shape,s,i,o,l,u,p,c,d),w;if(m)w=Ie({inputs:{x:r},backend:a,attrs:{shape:f}});else if(g||x){v.assert(r.shape.length>=1,()=>`Input must have rank at least 1, got: ${r.shape.length}`);let S=It.computeOutShape(A,y,b),C=Au({inputs:{x:r},backend:a,attrs:{begin:A,size:S}});w=Ie({inputs:{x:C},backend:a,attrs:{shape:f}}),a.disposeData(C.dataId)}else if(a.shouldExecuteOnCPU([r])){let S=a.readSync(r.dataId),C=Me(r.shape,r.dtype,S),E=rie(h,C,b,A);w=a.makeTensorInfo(f,r.dtype,E.values)}else{let S=new Lde(h),C=[{type:\"int32\",data:A},{type:\"int32\",data:b}],E=a.runWebGPUProgram(S,[r],r.dtype,C);w=Ie({inputs:{x:E},backend:a,attrs:{shape:f}}),a.disposeData(E.dataId)}return w}var Wde={kernelName:oo,backendName:\"webgpu\",kernelFunc:Bde};function Vde(e){let{inputs:t,backend:a,attrs:n}=e,{separator:r,nGramWidths:s,leftPad:i,rightPad:o,padWidth:l,preserveShortSequences:u}=n,{data:p,dataSplits:c}=t,d=a.readSync(p.dataId),h=a.readSync(c.dataId),[f,m]=sie(d,h,r,s,i,o,l,u);return[a.makeTensorInfo([f.length],\"string\",f),a.makeTensorInfo(c.shape,\"int32\",m)]}var Ude={kernelName:tu,backendName:\"webgpu\",kernelFunc:Vde},Gde=it({opType:de.TAN}),Hde={kernelName:uo,backendName:\"webgpu\",kernelFunc:Gde},jde=it({opType:de.TANH}),qde={kernelName:po,backendName:\"webgpu\",kernelFunc:jde},Xde=class{constructor(e){this.variableNames=[\"x\",\"indices\"],this.workgroupSize=[256,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.uniforms=`inputSize : i32, firstPass : i32, negativeInf : f32,\n        dir : i32, inc : i32,`,this.shaderKey=\"swap\"}getUserCode(){return`\n        ${Ce(\"index\")} {\n          if (index < uniforms.size) {\n            let outC = getCoordsFromIndex(index);\n            let batch = outC[0];\n            let elemIdx = outC[1];\n            // We compare elements pair-wise within a group of size 2 * inc.\n            // The comparing rule for each group alternates between ascending\n            // and descending. Within each group, we compare each pair at\n            // positions i and i+inc. To decide whether an element at position i\n            // is x0 or x1, we mod it by 2 * inc, if the result is smaller than\n            // inc, it is in the first half of the group, we denote it as x0,\n            // otherwise we denote it as x1.\n            // For example, as shown in the Bitonic top K paper referenced\n            // above, Figure5(a) shows that element[1] is in the second half of\n            // the group when group size is 2, but it is in the first half of\n            // the group when group size is 4.\n            let isFirstInPair = elemIdx % (2 * uniforms.inc) < uniforms.inc;\n            var i = 0;\n            if (isFirstInPair) {\n              i = elemIdx;\n            } else {\n              i = elemIdx - uniforms.inc;\n            }\n\n            var i0 = 0;\n            if (uniforms.firstPass == 1) {\n              i0 = i;\n            } else {\n              i0 = i32(getIndices(batch, i));\n            }\n\n            var i1 = 0;\n            if (uniforms.firstPass == 1) {\n              i1 = i + uniforms.inc;\n            } else {\n              i1 = i32(getIndices(batch, i + uniforms.inc));\n            }\n\n            var x0 = f32(0.0);\n            var x1 = f32(0.0);\n            if (i0 < uniforms.inputSize) {\n              x0 = getX(batch, i0);\n            } else {\n              x0 = uniforms.negativeInf;\n            }\n            if (i1 < uniforms.inputSize) {\n              x1 = getX(batch, i1);\n            } else {\n              x1 = uniforms.negativeInf;\n            }\n\n            let reverse = elemIdx % (2 * uniforms.dir) >= uniforms.dir;\n            let isGreater = x0 > x1 || (x0 == x1 && i1 > i0);\n            if (reverse == isGreater) {\n              // Elements in opposite order of direction\n              let iTemp = i0;\n              i0 = i1;\n              i1 = iTemp;\n            }\n            if (isFirstInPair) {\n              setOutputAtIndex(index, f32(i0));\n            } else {\n              setOutputAtIndex(index, f32(i1));\n            }\n          }\n        }\n      `}},Kde=class{constructor(e){this.variableNames=[\"x\",\"indices\"],this.workgroupSize=[256,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.uniforms=\"inputSize : i32, firstPass : i32, k : i32,\",this.shaderKey=\"merge\"}getUserCode(){return`\n        ${Ce(\"index\")} {\n          if (index < uniforms.size) {\n            let outC = getCoordsFromIndex(index);\n            let batch = outC[0];\n            let elemIdx = outC[1];\n            // The output size is half of the previous size.\n            // If the previous sequence is | | | | _ _ _ _  | | | |  _ _ _ _\n            // (k=4), we only need to output the indices at positions |, the\n            // indices at positions _ can be thrown away, see Figure5(b) After\n            // Phase 2 (Merge phase) in the Bitonic Top K paper referenced\n            // above.\n            // For example, the paper shows we only need to output the orange\n            // bars. The output sequence should look like this | | | | | | | |.\n            // Because the sequence is halved, to map the output index back to\n            // the previous sequence to find the corresponding value, we need\n            // to double the index. When we double the index, we basically\n            // interpolate a position, so 2i looks like\n            // | _ | _ | _ | _ | _ | _ | _. We move the | to the first k\n            // position of each 2k positions by - elemIdx % k. E.g. for output\n            // at index 4,5,6,7, we want to get the corresponding element at\n            // original index 8,9,10,11, for output at index 8,9,10,11,\n            // we want to get the corresponding element at original index\n            // 16,17,18,19, so on and so forth.\n\n            var i = 0;\n            if (elemIdx < uniforms.k) {\n              i = elemIdx;\n            } else {\n              i = elemIdx * 2 - elemIdx % uniforms.k;\n            }\n            var i0 = 0;\n            if (uniforms.firstPass == 1) {\n              i0 = i;\n            } else {\n              i0 = i32(getIndices(batch, i));\n            }\n            var i1 = 0;\n            if (uniforms.firstPass == 1) {\n              i1 = i + uniforms.k;\n            } else {\n              i1 = i32(getIndices(batch, i + uniforms.k));\n            }\n\n            let x0 = getX(batch, i0);\n            var x1 = f32(0.0);\n            if (i1 < uniforms.inputSize) {\n              x1 = getX(batch, i1);\n            } else {\n              x1 = x0;\n            }\n\n            if (x0 >= x1) {\n              setOutputAtIndex(index, f32(i0));\n            } else {\n              setOutputAtIndex(index, f32(i1));\n            }\n          }\n        }\n      `}};function Jo(e,t){t!==null&&e.disposeData(t.dataId)}function eA(e){let t=1;for(;t<e;)t*=2;return t}function Zde(e){let{inputs:t,backend:a,attrs:n}=e,{x:r}=t,{k:s,sorted:i}=n,o=r.shape,l=o[o.length-1];if(a.shouldExecuteOnCPU([r])){let b=a.readSync(r.dataId),[w,S]=lie(b,o,r.dtype,s,i);return[a.makeTensorInfo(w.shape,w.dtype,w.values),a.makeTensorInfo(S.shape,S.dtype,S.values)]}if(s===0)return o[o.length-1]=0,[a.makeTensorInfo(o,r.dtype,[]),a.makeTensorInfo(o,\"int32\",[])];if(l===1)return[r,Cr({attrs:{shape:o,dtype:\"int32\",value:0},backend:a})];let u=v.sizeFromShape(o)/l,p=Ie({inputs:{x:r},attrs:{shape:[u,l]},backend:a}),c=eA(s),d=eA(l),h=null,f=()=>h===null?[p,p]:[p,h],m=(b,w,S)=>{let C=f(),E=new Xde(S),_=[{type:\"int32\",data:[l]},{type:\"int32\",data:[h===null?1:0]},{type:\"float32\",data:[Number.NEGATIVE_INFINITY]},{type:\"int32\",data:[b]},{type:\"int32\",data:[w]}],$=h;h=a.runWebGPUProgram(E,C,\"int32\",_),Jo(a,$)};for(let b=1;b<c;b*=2){let w=b*2;for(let S=b;S>=1;S/=2)m(w,S,[u,d])}for(let b=d;b>c;b/=2){let w=f(),S=new Kde([u,b/2]),C=[{type:\"int32\",data:[l]},{type:\"int32\",data:[h===null?1:0]},{type:\"int32\",data:[c]}],E=h;h=a.runWebGPUProgram(S,w,\"int32\",C),Jo(a,E);let _=c/2,$=_*2;for(let M=_;M>=1;M/=2)m($,M,h.shape)}let g=h;h=Au({inputs:{x:h},backend:a,attrs:{begin:0,size:[u,s]}}),Jo(a,g);let x=q8({inputs:{x:p,indices:h},backend:a,attrs:{axis:1,batchDims:1}});Jo(a,p);let A=o.slice(0,-1);A.push(s),g=h,h=Ie({inputs:{x:h},attrs:{shape:A},backend:a}),Jo(a,g);let y=x;return x=Ie({inputs:{x},attrs:{shape:A},backend:a}),Jo(a,y),[x,h]}var Yde={kernelName:co,backendName:\"webgpu\",kernelFunc:Zde},Jde=class{constructor(e){this.variableNames=[\"Image\",\"Transforms\"],this.uniforms=\"interpolationModeId : i32, fillModeId : i32, fillValue : f32,\",this.workgroupSize=[64,1,1],this.size=!0,this.outputShape=e,this.dispatchLayout=Ve(this.outputShape),this.dispatch=Ne(this.dispatchLayout,this.outputShape,this.workgroupSize),this.shaderKey=\"transform\"}getUserCode(){return`\n          fn mapCoord(outCoord : f32, len : f32) -> f32{\n            var inCoord = outCoord;\n            if(uniforms.fillModeId == 2) {\n              if (inCoord < 0.0) {\n                if (len <= 1.0) {\n                  inCoord = 0.0;\n                } else {\n                  let sz2 = 2.0 * len;\n                  if (inCoord < sz2) {\n                    inCoord = sz2 * f32(i32(f32(-inCoord / sz2))) +\n                    inCoord;\n                  }\n                  if (inCoord < -len) {\n                    inCoord = inCoord + sz2;\n                  } else {\n                    inCoord = -inCoord - 1.0;\n                  }\n                }\n              } else if (inCoord > len - 1.0) {\n                if (len <= 1.0) {\n                  inCoord = 0.0;\n                } else {\n                  let sz2 = 2.0 * len;\n                  inCoord = inCoord - sz2 * f32(i32(f32(inCoord / sz2)));\n                  if (inCoord >= len) {\n                    inCoord = sz2 - inCoord - 1.0;\n                  }\n                }\n              }\n              return clamp(inCoord, 0.0, len - 1.0);\n            } else if (uniforms.fillModeId == 3) {\n              if (inCoord < 0.0) {\n                if (len <= 1.0) {\n                  inCoord = 0.0;\n                } else {\n                  let sz = len - 1.0;\n                  inCoord = inCoord + len * (f32(i32(f32(-inCoord / sz))) + 1.0);\n                }\n              } else if (inCoord > len - 1.0) {\n                if (len <= 1.0) {\n                  inCoord = 0.0;\n                } else {\n                  let sz = len - 1.0;\n                  inCoord = inCoord - len * f32(i32(f32(inCoord / sz)));\n                }\n              }\n              return clamp(inCoord, 0.0, len - 1.0);\n            } else if (uniforms.fillModeId == 4) {\n              return clamp(outCoord, 0.0, len - 1.0);\n            }\n            return outCoord;\n          }\n          fn readWithFillValue(batch : i32, coordY : i32, coordX : i32,\n            channel : i32) -> f32 {\n            var outputValue : f32;\n            if (0 <= coordY && coordY < uniforms.imageShape[1] && 0 <= coordX && coordX < uniforms.imageShape[2]) {\n                outputValue = getImage(batch, coordY, coordX, channel);\n            } else {\n              outputValue = uniforms.fillValue;\n            }\n            return outputValue;\n          }\n\n          ${Ce(\"index\")} {\n            if (index < uniforms.size) {\n              let coords = getCoordsFromIndex(index);\n              var outputValue : f32;\n              let batch = coords[0];\n              let x = coords[2];\n              let y = coords[1];\n              let channel = coords[3];\n              let xf = f32(x);\n              let yf = f32(y);\n              let a1 = getTransforms(batch, 0);\n              let a2 = getTransforms(batch, 1);\n              let a3 = getTransforms(batch, 2);\n              let b1 = getTransforms(batch, 3);\n              let b2 = getTransforms(batch, 4);\n              let b3 = getTransforms(batch, 5);\n              let c1 = getTransforms(batch, 6);\n              let c2 = getTransforms(batch, 7);\n              let projection = c1 * xf + c2 * yf + 1.0;\n              if (projection == 0.0) {\n                outputValue = uniforms.fillValue;\n              } else {\n                let inX = (a1 * xf + a2 * yf + a3) / projection;\n                let inY = (b1 * xf + b2 * yf + b3) / projection;\n                let mapX = mapCoord(inX, f32(uniforms.imageShape[2]));\n                let mapY = mapCoord(inY, f32(uniforms.imageShape[1]));\n\n                if (uniforms.interpolationModeId == 1) {\n                  let coordY = i32(round(mapY));\n                  let coordX = i32(round(mapX));\n                  outputValue = readWithFillValue(batch, coordY, coordX,\n                    channel);\n                } else {\n                  let yFloor = floor(mapY);\n                  let xFloor = floor(mapX);\n                  let yCeil = yFloor + 1.0;\n                  let xCeil = xFloor + 1.0;\n                  let valueYFloor = (xCeil - mapX) *\n                  readWithFillValue(batch, i32(yFloor), i32(xFloor), channel) +\n                  (mapX - xFloor) *\n                  readWithFillValue(batch, i32(yFloor), i32(xCeil), channel);\n                  let valueYCeil = (xCeil - mapX) *\n                  readWithFillValue(batch, i32(yCeil), i32(xFloor), channel) +\n                  (mapX - xFloor) *\n                  readWithFillValue(batch, i32(yCeil), i32(xCeil), channel);\n                  outputValue = (yCeil - mapY) * valueYFloor +\n                  (mapY - yFloor) * valueYCeil;\n                }\n              }\n              setOutputAtIndex(index, outputValue);\n            }\n          }\n        `}};function Qde(e){let{inputs:t,backend:a,attrs:n}=e,{image:r,transforms:s}=t,{interpolation:i,fillMode:o,fillValue:l,outputShape:u}=n,[p,c,d,h]=r.shape,[f,m]=u!=null?u:[c,d],g=[p,f,m,h],x=new Jde(g),A=i===\"nearest\"?1:2,y;switch(o){case\"constant\":y=1;break;case\"reflect\":y=2;break;case\"wrap\":y=3;break;case\"nearest\":y=4;break;default:y=1;break}let b=[{type:\"int32\",data:[A]},{type:\"int32\",data:[y]},{type:\"float32\",data:[l]}];return a.runWebGPUProgram(x,[r,s],\"float32\",b)}var epe={kernelName:ho,backendName:\"webgpu\",kernelFunc:Qde};function tpe(e){let{inputs:t,backend:a,attrs:n}=e,{value:r}=t,{axis:s}=n;s<0&&(s+=r.shape.length);let i=r,o=i.shape.length,l=r.shape[s],u=new Array(o-1),p=0;for(let m=0;m<o;m++)m!==s&&(u[p++]=i.shape[m]);let c=[],d=new Array(o).fill(0),h=i.shape.slice();h[s]=1;let f=new Array(l);for(let m=0;m<f.length;m++){d[s]=m;let g=Au({inputs:{x:i},backend:a,attrs:{begin:d,size:h}}),x=Ie({inputs:{x:g},backend:a,attrs:{shape:u}});f[m]=x,c.push(g)}return c.forEach(m=>a.disposeData(m.dataId)),f}var ape={kernelName:au,backendName:\"webgpu\",kernelFunc:tpe},npe=[Nse,pie,hie,mie,xie,bie,Cie,Eie,Mie,_ie,Fie,Die,Lie,Wie,Uie,Xie,Zie,toe,soe,uoe,poe,moe,Rse,yoe,Coe,$oe,Poe,Ooe,Loe,Woe,Uoe,Hoe,Xoe,Yoe,tle,nle,sle,ole,lle,ule,ple,hle,Sse,mle,vle,xle,yle,Ile,Tle,Nle,Mle,Ple,Ole,zle,Ese,Ble,xoe,Vle,Gle,jle,Xle,Zle,Jle,aue,eue,rue,iue,Hie,lue,due,jie,cue,fue,gue,Aue,Joe,bue,wue,Iue,ioe,Cue,Eue,Mue,_ue,Fue,Due,Lue,Wue,ooe,Vue,Gue,jue,Xue,Tse,Yue,ede,nde,sde,ode,ude,cde,mde,xde,yde,vde,Qie,Wde,Ude,Ide,Tde,Mde,_de,Fde,Ode,zde,wde,Qoe,Hde,qde,Ede,Yde,epe,Iie,ape,Nue];for(let e of npe)mn(e);var tA=\"4.1.0\",rpe=\"4.1.0\",spe=\"4.1.0\",ipe=\"4.1.0\",ope=\"4.1.0\",lpe=\"0.0.1-alpha.16\",xp={tfjs:tA,\"tfjs-core\":tA,\"tfjs-converter\":rpe,\"tfjs-backend-cpu\":spe,\"tfjs-backend-webgl\":ipe,\"tfjs-backend-wasm\":ope,\"tfjs-backend-webgpu\":lpe};function K(...e){let t=new Date,a=`${t.getHours().toString().padStart(2,\"0\")}:${t.getMinutes().toString().padStart(2,\"0\")}:${t.getSeconds().toString().padStart(2,\"0\")}.${t.getMilliseconds().toString().padStart(3,\"0\")}`;e&&console.log(a,\"Human:\",...e)}function Q8(e,t){let a=e.endsWith(\"/\")?\"\":\"/\",r=t.startsWith(\".\")||t.startsWith(\"/\")||t.startsWith(\"http:\")||t.startsWith(\"https:\")||t.startsWith(\"file:\")?`${t}`:`${e}${a}${t}`;if(!r.toLocaleLowerCase().includes(\".json\"))throw new Error(`modelpath error: expecting json file: ${r}`);return r}var te=()=>typeof performance!=\"undefined\"?performance.now():parseInt((Number(process.hrtime.bigint())/1e3/1e3).toString());function U3(e,t,a=\"config\",n=[]){for(let r of Object.keys(t))if(typeof t[r]==\"object\")U3(e[r],t[r],r,n);else{let s=e&&typeof e[r]!=\"undefined\";s||n.push({reason:\"unknown property\",where:`${a}.${r} = ${t[r]}`});let i=e&&typeof e[r]==typeof t[r];s&&!i&&n.push({reason:\"property type mismatch\",where:`${a}.${r} = ${t[r]}`,expected:typeof e[r]})}return t.debug&&a===\"config\"&&n.length>0&&K(\"invalid configuration\",n),n}function Ct(...e){let t=a=>a&&typeof a==\"object\";return e.reduce((a,n)=>(Object.keys(n||{}).forEach(r=>{let s=a[r],i=n[r];Array.isArray(s)&&Array.isArray(i)?a[r]=s.concat(...i):t(s)&&t(i)?a[r]=Ct(s,i):a[r]=i}),a),{})}var Io={backend:\"\",modelBasePath:\"\",cacheModels:!0,validateModels:!0,wasmPath:\"\",wasmPlatformFetch:!1,debug:!1,async:!0,warmup:\"full\",cacheSensitivity:.7,skipAllowed:!1,deallocate:!1,flags:{},softwareKernels:!1,filter:{enabled:!0,equalization:!1,width:0,height:0,flip:!1,return:!0,autoBrightness:!0,brightness:0,contrast:0,sharpness:0,blur:0,saturation:0,hue:0,negative:!1,sepia:!1,vintage:!1,kodachrome:!1,technicolor:!1,polaroid:!1,pixelate:0},gesture:{enabled:!0},face:{enabled:!0,detector:{modelPath:\"blazeface.json\",rotation:!0,maxDetected:1,skipFrames:99,skipTime:2500,minConfidence:.2,iouThreshold:.1,mask:!1,return:!1},mesh:{enabled:!0,modelPath:\"facemesh.json\",keepInvalid:!1},attention:{enabled:!1,modelPath:\"facemesh-attention.json\"},iris:{enabled:!0,modelPath:\"iris.json\"},emotion:{enabled:!0,minConfidence:.1,skipFrames:99,skipTime:1500,modelPath:\"emotion.json\"},description:{enabled:!0,modelPath:\"faceres.json\",skipFrames:99,skipTime:3e3,minConfidence:.1},antispoof:{enabled:!1,skipFrames:99,skipTime:4e3,modelPath:\"antispoof.json\"},liveness:{enabled:!1,skipFrames:99,skipTime:4e3,modelPath:\"liveness.json\"}},body:{enabled:!0,modelPath:\"movenet-lightning.json\",maxDetected:-1,minConfidence:.3,skipFrames:1,skipTime:200},hand:{enabled:!0,rotation:!0,skipFrames:99,skipTime:1e3,minConfidence:.5,iouThreshold:.2,maxDetected:-1,landmarks:!0,detector:{modelPath:\"handtrack.json\"},skeleton:{modelPath:\"handlandmark-lite.json\"}},object:{enabled:!1,modelPath:\"centernet.json\",minConfidence:.2,iouThreshold:.4,maxDetected:10,skipFrames:99,skipTime:2e3},segmentation:{enabled:!1,modelPath:\"rvm.json\",ratio:.5,mode:\"default\"}};var e9=`\n  precision highp float;\n  attribute vec2 pos;\n  attribute vec2 uv;\n  varying vec2 vUv;\n  uniform float flipY;\n  void main(void) {\n    vUv = uv;\n    gl_Position = vec4(pos.x, pos.y*flipY, 0.0, 1.);\n  }\n`;var t9=`\n  precision highp float;\n  varying vec2 vUv;\n  uniform sampler2D texture;\n  uniform float m[20];\n  void main(void) {\n    vec4 c = texture2D(texture, vUv);\n    gl_FragColor.r = m[0] * c.r + m[1] * c.g + m[2] * c.b + m[3] * c.a + m[4];\n    gl_FragColor.g = m[5] * c.r + m[6] * c.g + m[7] * c.b + m[8] * c.a + m[9];\n    gl_FragColor.b = m[10] * c.r + m[11] * c.g + m[12] * c.b + m[13] * c.a + m[14];\n    gl_FragColor.a = m[15] * c.r + m[16] * c.g + m[17] * c.b + m[18] * c.a + m[19];\n  }\n`,a9=`\n  precision highp float;\n  varying vec2 vUv;\n  uniform sampler2D texture;\n  uniform float m[20];\n  void main(void) {\n    vec4 c = texture2D(texture, vUv);\n    gl_FragColor.r = m[0] * c.r + m[1] * c.g + m[2] * c.b + m[4];\n    gl_FragColor.g = m[5] * c.r + m[6] * c.g + m[7] * c.b + m[9];\n    gl_FragColor.b = m[10] * c.r + m[11] * c.g + m[12] * c.b + m[14];\n    gl_FragColor.a = c.a;\n  }\n`,n9=`\n  precision highp float;\n  varying vec2 vUv;\n  uniform vec2 size;\n  uniform sampler2D texture;\n  vec2 pixelate(vec2 coord, vec2 size) {\n    return floor( coord / size ) * size;\n  }\n  void main(void) {\n    gl_FragColor = vec4(0.0);\n    vec2 coord = pixelate(vUv, size);\n    gl_FragColor += texture2D(texture, coord);\n  }\n`,r9=`\n  precision highp float;\n  varying vec2 vUv;\n  uniform sampler2D texture;\n  uniform vec2 px;\n  void main(void) {\n    gl_FragColor = vec4(0.0);\n    gl_FragColor += texture2D(texture, vUv + vec2(-7.0*px.x, -7.0*px.y))*0.0044299121055113265;\n    gl_FragColor += texture2D(texture, vUv + vec2(-6.0*px.x, -6.0*px.y))*0.00895781211794;\n    gl_FragColor += texture2D(texture, vUv + vec2(-5.0*px.x, -5.0*px.y))*0.0215963866053;\n    gl_FragColor += texture2D(texture, vUv + vec2(-4.0*px.x, -4.0*px.y))*0.0443683338718;\n    gl_FragColor += texture2D(texture, vUv + vec2(-3.0*px.x, -3.0*px.y))*0.0776744219933;\n    gl_FragColor += texture2D(texture, vUv + vec2(-2.0*px.x, -2.0*px.y))*0.115876621105;\n    gl_FragColor += texture2D(texture, vUv + vec2(-1.0*px.x, -1.0*px.y))*0.147308056121;\n    gl_FragColor += texture2D(texture, vUv                             )*0.159576912161;\n    gl_FragColor += texture2D(texture, vUv + vec2( 1.0*px.x,  1.0*px.y))*0.147308056121;\n    gl_FragColor += texture2D(texture, vUv + vec2( 2.0*px.x,  2.0*px.y))*0.115876621105;\n    gl_FragColor += texture2D(texture, vUv + vec2( 3.0*px.x,  3.0*px.y))*0.0776744219933;\n    gl_FragColor += texture2D(texture, vUv + vec2( 4.0*px.x,  4.0*px.y))*0.0443683338718;\n    gl_FragColor += texture2D(texture, vUv + vec2( 5.0*px.x,  5.0*px.y))*0.0215963866053;\n    gl_FragColor += texture2D(texture, vUv + vec2( 6.0*px.x,  6.0*px.y))*0.00895781211794;\n    gl_FragColor += texture2D(texture, vUv + vec2( 7.0*px.x,  7.0*px.y))*0.0044299121055113265;\n  }\n`,s9=`\n  precision highp float;\n  varying vec2 vUv;\n  uniform sampler2D texture;\n  uniform vec2 px;\n  uniform float m[9];\n  void main(void) {\n    vec4 c11 = texture2D(texture, vUv - px); // top left\n    vec4 c12 = texture2D(texture, vec2(vUv.x, vUv.y - px.y)); // top center\n    vec4 c13 = texture2D(texture, vec2(vUv.x + px.x, vUv.y - px.y)); // top right\n    vec4 c21 = texture2D(texture, vec2(vUv.x - px.x, vUv.y) ); // mid left\n    vec4 c22 = texture2D(texture, vUv); // mid center\n    vec4 c23 = texture2D(texture, vec2(vUv.x + px.x, vUv.y) ); // mid right\n    vec4 c31 = texture2D(texture, vec2(vUv.x - px.x, vUv.y + px.y) ); // bottom left\n    vec4 c32 = texture2D(texture, vec2(vUv.x, vUv.y + px.y) ); // bottom center\n    vec4 c33 = texture2D(texture, vUv + px ); // bottom right\n    gl_FragColor = \n    c11 * m[0] + c12 * m[1] + c22 * m[2] +\n    c21 * m[3] + c22 * m[4] + c23 * m[5] +\n    c31 * m[6] + c32 * m[7] + c33 * m[8];\n    gl_FragColor.a = c22.a;\n  }\n`;var G3=(e,t,a)=>{let n=new RegExp(\"\\\\b\"+t+\" \\\\w+ (\\\\w+)\",\"ig\");e.replace(n,(r,s)=>(a[s]=0,r))},H3=class{constructor(t,a,n){ue(this,\"uniform\",{});ue(this,\"attribute\",{});ue(this,\"gl\");ue(this,\"id\");ue(this,\"compile\",(t,a)=>{let n=this.gl.createShader(a);return n?(this.gl.shaderSource(n,t),this.gl.compileShader(n),this.gl.getShaderParameter(n,this.gl.COMPILE_STATUS)?n:(K(`filter: gl compile failed: ${this.gl.getShaderInfoLog(n)||\"unknown\"}`),null)):(K(\"filter: could not create shader\"),null)});this.gl=t;let r=this.compile(a,this.gl.VERTEX_SHADER),s=this.compile(n,this.gl.FRAGMENT_SHADER);if(this.id=this.gl.createProgram(),!(!r||!s)){if(!this.id){K(\"filter: could not create webgl program\");return}if(this.gl.attachShader(this.id,r),this.gl.attachShader(this.id,s),this.gl.linkProgram(this.id),!this.gl.getProgramParameter(this.id,this.gl.LINK_STATUS)){K(`filter: gl link failed: ${this.gl.getProgramInfoLog(this.id)||\"unknown\"}`);return}this.gl.useProgram(this.id),G3(a,\"attribute\",this.attribute);for(let i in this.attribute)this.attribute[i]=this.gl.getAttribLocation(this.id,i);G3(a,\"uniform\",this.uniform),G3(n,\"uniform\",this.uniform);for(let i in this.uniform)this.uniform[i]=this.gl.getUniformLocation(this.id,i)}}};function i9(){let e=0,t=null,a=!1,n=-1,r=[null,null],s=[],i=null,o=null,l=Nn(100,100),u={},p={INTERMEDIATE:1},c=l.getContext(\"webgl\");if(!c){K(\"filter: cannot get webgl context\");return}this.gl=c;function d(A,y){if(!(A===l.width&&y===l.height)){if(l.width=A,l.height=y,!i){let b=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,-1,1,0,0,1,-1,1,1,1,1,1,0]);i=c.createBuffer(),c.bindBuffer(c.ARRAY_BUFFER,i),c.bufferData(c.ARRAY_BUFFER,b,c.STATIC_DRAW),c.pixelStorei(c.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0)}c.viewport(0,0,l.width,l.height),r=[null,null]}}function h(A,y){let b=c.createFramebuffer();c.bindFramebuffer(c.FRAMEBUFFER,b);let w=c.createRenderbuffer();c.bindRenderbuffer(c.RENDERBUFFER,w);let S=c.createTexture();return c.bindTexture(c.TEXTURE_2D,S),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,A,y,0,c.RGBA,c.UNSIGNED_BYTE,null),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.LINEAR),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.framebufferTexture2D(c.FRAMEBUFFER,c.COLOR_ATTACHMENT0,c.TEXTURE_2D,S,0),c.bindTexture(c.TEXTURE_2D,null),c.bindFramebuffer(c.FRAMEBUFFER,null),{fbo:b,texture:S}}function f(A){return r[A]=r[A]||h(l.width,l.height),r[A]}function m(A=0){if(!o)return;let y=null,b=null,w=!1;e===0?y=t:y=f(n).texture||null,e++,a&&!(A&p.INTERMEDIATE)?(b=null,w=e%2===0):(n=(n+1)%2,b=f(n).fbo||null),c.bindTexture(c.TEXTURE_2D,y),c.bindFramebuffer(c.FRAMEBUFFER,b),c.uniform1f(o.uniform.flipY,w?-1:1),c.drawArrays(c.TRIANGLES,0,6)}function g(A){if(u[A])return o=u[A],c.useProgram((o?o.id:null)||null),o;if(o=new H3(c,e9,A),!o)return K(\"filter: could not get webgl program\"),null;let y=Float32Array.BYTES_PER_ELEMENT,b=4*y;return c.enableVertexAttribArray(o.attribute.pos),c.vertexAttribPointer(o.attribute.pos,2,c.FLOAT,!1,b,0*y),c.enableVertexAttribArray(o.attribute.uv),c.vertexAttribPointer(o.attribute.uv,2,c.FLOAT,!1,b,2*y),u[A]=o,o}let x={colorMatrix:A=>{let y=new Float32Array(A);y[4]/=255,y[9]/=255,y[14]/=255,y[19]/=255;let b=y[18]===1&&y[3]===0&&y[8]===0&&y[13]===0&&y[15]===0&&y[16]===0&&y[17]===0&&y[19]===0?a9:t9,w=g(b);!w||(c.uniform1fv(w.uniform.m,y),m())},brightness:A=>{let y=(A||0)+1;x.colorMatrix([y,0,0,0,0,0,y,0,0,0,0,0,y,0,0,0,0,0,1,0])},saturation:A=>{let y=(A||0)*2/3+1,b=(y-1)*-.5;x.colorMatrix([y,b,b,0,0,b,y,b,0,0,b,b,y,0,0,0,0,0,1,0])},desaturate:()=>{x.saturation(-1)},contrast:A=>{let y=(A||0)+1,b=-128*(y-1);x.colorMatrix([y,0,0,0,b,0,y,0,0,b,0,0,y,0,b,0,0,0,1,0])},negative:()=>{x.contrast(-2)},hue:A=>{A=(A||0)/180*Math.PI;let y=Math.cos(A),b=Math.sin(A),w=.213,S=.715,C=.072;x.colorMatrix([w+y*(1-w)+b*-w,S+y*-S+b*-S,C+y*-C+b*(1-C),0,0,w+y*-w+b*.143,S+y*(1-S)+b*.14,C+y*-C+b*-.283,0,0,w+y*-w+b*-(1-w),S+y*-S+b*S,C+y*(1-C)+b*C,0,0,0,0,0,1,0])},desaturateLuminance:()=>{x.colorMatrix([.2764723,.929708,.0938197,0,-37.1,.2764723,.929708,.0938197,0,-37.1,.2764723,.929708,.0938197,0,-37.1,0,0,0,1,0])},sepia:()=>{x.colorMatrix([.393,.7689999,.18899999,0,0,.349,.6859999,.16799999,0,0,.272,.5339999,.13099999,0,0,0,0,0,1,0])},brownie:()=>{x.colorMatrix([.5997023498159715,.34553243048391263,-.2708298674538042,0,47.43192855600873,-.037703249837783157,.8609577587992641,.15059552388459913,0,-36.96841498319127,.24113635128153335,-.07441037908422492,.44972182064877153,0,-7.562075277591283,0,0,0,1,0])},vintagePinhole:()=>{x.colorMatrix([.6279345635605994,.3202183420819367,-.03965408211312453,0,9.651285835294123,.02578397704808868,.6441188644374771,.03259127616149294,0,7.462829176470591,.0466055556782719,-.0851232987247891,.5241648018700465,0,5.159190588235296,0,0,0,1,0])},kodachrome:()=>{x.colorMatrix([1.1285582396593525,-.3967382283601348,-.03992559172921793,0,63.72958762196502,-.16404339962244616,1.0835251566291304,-.05498805115633132,0,24.732407896706203,-.16786010706155763,-.5603416277695248,1.6014850761964943,0,35.62982807460946,0,0,0,1,0])},technicolor:()=>{x.colorMatrix([1.9125277891456083,-.8545344976951645,-.09155508482755585,0,11.793603434377337,-.3087833385928097,1.7658908555458428,-.10601743074722245,0,-70.35205161461398,-.231103377548616,-.7501899197440212,1.847597816108189,0,30.950940869491138,0,0,0,1,0])},polaroid:()=>{x.colorMatrix([1.438,-.062,-.062,0,0,-.122,1.378,-.122,0,0,-.016,-.016,1.483,0,0,0,0,0,1,0])},shiftToBGR:()=>{x.colorMatrix([0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0])},convolution:A=>{let y=new Float32Array(A),b=1/l.width,w=1/l.height,S=g(s9);!S||(c.uniform1fv(S.uniform.m,y),c.uniform2f(S.uniform.px,b,w),m())},detectEdges:()=>{x.convolution.call(this,[0,1,0,1,-4,1,0,1,0])},sobelX:()=>{x.convolution.call(this,[-1,0,1,-2,0,2,-1,0,1])},sobelY:()=>{x.convolution.call(this,[-1,-2,-1,0,0,0,1,2,1])},sharpen:A=>{let y=A||1;x.convolution.call(this,[0,-1*y,0,-1*y,1+4*y,-1*y,0,-1*y,0])},emboss:A=>{let y=A||1;x.convolution.call(this,[-2*y,-1*y,0,-1*y,1,1*y,0,1*y,2*y])},blur:A=>{let y=A/7/l.width,b=A/7/l.height,w=g(r9);!w||(c.uniform2f(w.uniform.px,0,b),m(p.INTERMEDIATE),c.uniform2f(w.uniform.px,y,0),m())},pixelate:A=>{let y=A/l.width,b=A/l.height,w=g(n9);!w||(c.uniform2f(w.uniform.size,y,b),m())}};this.add=function(A){let y=Array.prototype.slice.call(arguments,1),b=x[A];s.push({func:b,args:y})},this.reset=function(){s=[]},this.get=function(){return s},this.apply=function(A){d(A.width,A.height),e=0,t||(t=c.createTexture()),c.bindTexture(c.TEXTURE_2D,t),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_S,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_WRAP_T,c.CLAMP_TO_EDGE),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MIN_FILTER,c.NEAREST),c.texParameteri(c.TEXTURE_2D,c.TEXTURE_MAG_FILTER,c.NEAREST),c.texImage2D(c.TEXTURE_2D,0,c.RGBA,c.RGBA,c.UNSIGNED_BYTE,A);for(let y=0;y<s.length;y++){a=y===s.length-1;let b=s[y];b.func.apply(this,b.args||[])}return l},this.draw=function(A){return this.add(\"brightness\",0),this.apply(A)}}async function qh(e){let t=e.shape.length===4?_e(e):e,a=ka(t,3,2),n=[Kr(a[0]),Kr(a[1]),Kr(a[2])],r=[pa(a[0]),pa(a[1]),pa(a[2])],s=await Promise.all(r.map(p=>p.data())),i=Math.max(s[0][0],s[1][0],s[2][0]),l=(i>1?255:1)/i,u;if(l>1){let p=[fe(a[0],n[0]),fe(a[1],n[1]),fe(a[2],n[2])],c=[fe(r[0],n[0]),fe(r[1],n[1]),fe(r[2],n[2])],d=[ae(p[0],l),ae(p[1],l),ae(p[2],l)],h=sa([d[0],d[1],d[2]],2);u=J(h,[1,t.shape[0]||0,t.shape[1]||0,3]),Y([...p,...c,...d])}else u=Gt(t,0);return Y([...a,...n,...r,a,t,e]),u}var Xh=3840,Jt=null,Qt=null,yu=null,xt,gn={inputSum:0,cacheDiff:1,sumMethod:0,inputTensor:void 0};function j3(){gn.inputSum=0,gn.cacheDiff=1,gn.sumMethod=0,gn.inputTensor=void 0}function Nn(e,t){let a;if(ne.browser)if(ne.worker){if(typeof OffscreenCanvas==\"undefined\")throw new Error(\"canvas error: attempted to run in web worker but OffscreenCanvas is not supported\");a=new OffscreenCanvas(e,t)}else{if(typeof document==\"undefined\")throw new Error(\"canvas error: attempted to run in browser but DOM is not defined\");a=document.createElement(\"canvas\"),a.width=e,a.height=t}else typeof ne.Canvas!=\"undefined\"?a=new ne.Canvas(e,t):typeof globalThis.Canvas!=\"undefined\"&&(a=new globalThis.Canvas(e,t));return a}function Kh(e,t){let a=t||Nn(e.width,e.height);return a.getContext(\"2d\").drawImage(e,0,0),a}async function Zh(e,t,a=!0){var d,h,f;if(!e)return t.debug&&K(\"input error: input is missing\"),{tensor:null,canvas:null};if(!(e instanceof pt)&&!(typeof Image!=\"undefined\"&&e instanceof Image)&&!(typeof globalThis.Canvas!=\"undefined\"&&e instanceof globalThis.Canvas)&&!(typeof ImageData!=\"undefined\"&&e instanceof ImageData)&&!(typeof ImageBitmap!=\"undefined\"&&e instanceof ImageBitmap)&&!(typeof HTMLImageElement!=\"undefined\"&&e instanceof HTMLImageElement)&&!(typeof HTMLMediaElement!=\"undefined\"&&e instanceof HTMLMediaElement)&&!(typeof HTMLVideoElement!=\"undefined\"&&e instanceof HTMLVideoElement)&&!(typeof HTMLCanvasElement!=\"undefined\"&&e instanceof HTMLCanvasElement)&&!(typeof OffscreenCanvas!=\"undefined\"&&e instanceof OffscreenCanvas))throw new Error(\"input error: type not recognized\");if(e instanceof pt){let m=null;if(e.isDisposedInternal)throw new Error(\"input error: attempted to use tensor but it is disposed\");if(!e.shape)throw new Error(\"input error: attempted to use tensor without a shape\");if(e.shape.length===3){if(e.shape[2]===3)m=Gt(e,0);else if(e.shape[2]===4){let g=sp(e,[0,0,0],[-1,-1,3]);m=Gt(g,0),Y(g)}}else e.shape.length===4&&(e.shape[3]===3?m=wa(e):e.shape[3]===4&&(m=xh(e,[0,0,0,0],[-1,-1,-1,3])));if(m==null||m.shape.length!==4||m.shape[0]!==1||m.shape[3]!==3)throw new Error(`input error: attempted to use tensor with unrecognized shape: ${e.shape.toString()}`);if(m.dtype===\"int32\"){let g=He(m,\"float32\");Y(m),m=g}return{tensor:m,canvas:t.filter.return?Qt:null}}if(typeof e.readyState!=\"undefined\"&&e.readyState<=2)return t.debug&&K(\"input stream is not ready\"),{tensor:null,canvas:Jt};let n=e.naturalWidth||e.videoWidth||e.width||e.shape&&e.shape[1]>0,r=e.naturalHeight||e.videoHeight||e.height||e.shape&&e.shape[2]>0;if(!n||!r)return t.debug&&K(\"cannot determine input dimensions\"),{tensor:null,canvas:Jt};let s=n,i=r;if(s>Xh&&(s=Xh,i=Math.trunc(s*r/n)),i>Xh&&(i=Xh,s=Math.trunc(i*n/r)),(((d=t.filter)==null?void 0:d.width)||0)>0?s=t.filter.width:(((h=t.filter)==null?void 0:h.height)||0)>0&&(s=n*((t.filter.height||0)/r)),(t.filter.height||0)>0?i=t.filter.height:(t.filter.width||0)>0&&(i=r*((t.filter.width||0)/n)),!s||!i)throw new Error(\"input error: cannot determine dimension\");(!Jt||Jt.width!==s||Jt.height!==i)&&(Jt=Nn(s,i));let o=Jt.getContext(\"2d\");if(typeof ImageData!=\"undefined\"&&e instanceof ImageData?o.putImageData(e,0,0):t.filter.flip&&typeof o.translate!=\"undefined\"?(o.translate(n,0),o.scale(-1,1),o.drawImage(e,0,0,n,r,0,0,Jt.width,Jt.height),o.setTransform(1,0,0,1,0,0)):o.drawImage(e,0,0,n,r,0,0,Jt.width,Jt.height),(!Qt||Jt.width!==Qt.width||Jt.height!==Qt.height)&&(Qt=Nn(Jt.width,Jt.height)),t.filter.enabled&&ne.webgl.supported?(xt||(xt=ne.browser?new i9:null),ne.filter=!!xt,xt!=null&&xt.add?(xt.reset(),t.filter.brightness!==0&&xt.add(\"brightness\",t.filter.brightness),t.filter.contrast!==0&&xt.add(\"contrast\",t.filter.contrast),t.filter.sharpness!==0&&xt.add(\"sharpen\",t.filter.sharpness),t.filter.blur!==0&&xt.add(\"blur\",t.filter.blur),t.filter.saturation!==0&&xt.add(\"saturation\",t.filter.saturation),t.filter.hue!==0&&xt.add(\"hue\",t.filter.hue),t.filter.negative&&xt.add(\"negative\"),t.filter.sepia&&xt.add(\"sepia\"),t.filter.vintage&&xt.add(\"brownie\"),t.filter.sepia&&xt.add(\"sepia\"),t.filter.kodachrome&&xt.add(\"kodachrome\"),t.filter.technicolor&&xt.add(\"technicolor\"),t.filter.polaroid&&xt.add(\"polaroid\"),t.filter.pixelate!==0&&xt.add(\"pixelate\",t.filter.pixelate),((f=xt.get())==null?void 0:f.length)>1?Qt=xt.apply(Jt):Qt=xt.draw(Jt)):(t.debug&&K(\"input process error: cannot initialize filters\"),ne.webgl.supported=!1,t.filter.enabled=!1,Kh(Jt,Qt))):(Kh(Jt,Qt),xt&&(xt=null),ne.filter=!!xt),!a)return{tensor:null,canvas:Qt};if(!Qt)throw new Error(\"canvas error: cannot create output\");let l,u=3;if(typeof ImageData!=\"undefined\"&&e instanceof ImageData||e.data&&e.width&&e.height)if(ne.browser&&wr)l=wr?wr.fromPixels(e):null;else{u=e.data.length/e.height/e.width;let m=new Uint8Array(e.data.buffer);l=Be(m,[e.height,e.width,u],\"int32\")}else if((!yu||Qt.width!==yu.width||Qt.height!==yu.height)&&(yu=Nn(Qt.width,Qt.height)),wr&&ne.browser)t.backend===\"webgl\"||t.backend===\"humangl\"||t.backend===\"webgpu\"?l=wr.fromPixels(Qt):(yu=Kh(Qt),l=wr.fromPixels(yu));else{let x=Kh(Qt).getContext(\"2d\").getImageData(0,0,s,i);u=x.data.length/s/i;let A=new Uint8Array(x.data.buffer);l=Be(A,[s,i,u])}if(u===4){let m=sp(l,[0,0,0],[-1,-1,3]);Y(l),l=m}if(!l)throw new Error(\"input error: cannot create tensor\");let p=He(l,\"float32\"),c=t.filter.equalization?await qh(p):Gt(p,0);if(Y([l,p]),t.filter.autoBrightness){let m=pa(c),g=await m.data();t.filter.brightness=g[0]>1?1-g[0]/255:1-g[0],Y(m)}return{tensor:c,canvas:t.filter.return?Qt:null}}async function o9(e,t){let a=!1;if(e.cacheSensitivity===0||!t.shape||t.shape.length!==4||t.shape[1]>3840||t.shape[2]>2160)return a;if(!gn.inputTensor)gn.inputTensor=wa(t);else if(gn.inputTensor.shape[1]!==t.shape[1]||gn.inputTensor.shape[2]!==t.shape[2])Y(gn.inputTensor),gn.inputTensor=wa(t);else{let n={};n.diff=fe(t,gn.inputTensor),n.squared=ae(n.diff,n.diff),n.sum=tt(n.squared);let s=(await n.sum.data())[0]/(t.shape[1]||1)/(t.shape[2]||1)/255/3;Y([gn.inputTensor,n.diff,n.squared,n.sum]),gn.inputTensor=wa(t),a=s<=(e.cacheSensitivity||0)}return a}async function l9(e,t,a){let n={};if(!t||!a||t.shape.length!==4||t.shape.length!==a.shape.length)return e.debug||K(\"invalid input tensor or tensor shapes do not match:\",t.shape,a.shape),0;if(t.shape[0]!==1||a.shape[0]!==1||t.shape[3]!==3||a.shape[3]!==3)return e.debug||K(\"input tensors must be of shape [1, height, width, 3]:\",t.shape,a.shape),0;n.input1=wa(t),n.input2=t.shape[1]!==a.shape[1]||t.shape[2]!==a.shape[2]?ge.resizeBilinear(a,[t.shape[1],t.shape[2]]):wa(a),n.diff=fe(n.input1,n.input2),n.squared=ae(n.diff,n.diff),n.sum=tt(n.squared);let s=(await n.sum.data())[0]/(t.shape[1]||1)/(t.shape[2]||1)/255/3;return Y([n.input1,n.input2,n.diff,n.squared,n.sum]),s}var yp,bp,vp,Ap=class{constructor(){ue(this,\"browser\");ue(this,\"node\");ue(this,\"worker\");ue(this,\"platform\",\"\");ue(this,\"agent\",\"\");ue(this,\"backends\",[]);ue(this,\"initial\");ue(this,\"filter\");ue(this,\"tfjs\");ue(this,\"offscreen\");ue(this,\"perfadd\",!1);ue(this,\"tensorflow\",{version:void 0,gpu:void 0});ue(this,\"wasm\",{supported:void 0,backend:void 0,simd:void 0,multithread:void 0});ue(this,\"webgl\",{supported:void 0,backend:void 0,version:void 0,renderer:void 0,shader:void 0,vendor:void 0});ue(this,\"webgpu\",{supported:void 0,backend:void 0,adapter:void 0});ue(this,\"cpu\",{model:void 0,flags:[]});ue(this,\"kernels\",[]);Gn(this,yp,void 0);Gn(this,bp,void 0);Gn(this,vp,void 0);if(this.browser=typeof navigator!=\"undefined\",this.node=typeof process!=\"undefined\"&&typeof process.versions!=\"undefined\"&&typeof process.versions.node!=\"undefined\",this.tfjs={version:xp[\"tfjs-core\"]},this.offscreen=typeof OffscreenCanvas!=\"undefined\",this.initial=!0,this.worker=this.browser&&this.offscreen?typeof WorkerGlobalScope!=\"undefined\":void 0,typeof navigator!=\"undefined\"){let t=navigator.userAgent.match(/\\(([^()]+)\\)/g);if(t!=null&&t[0]){let a=t[0].match(/\\(([^()]+)\\)/g);this.platform=a!=null&&a[0]?a[0].replace(/\\(|\\)/g,\"\"):\"\",this.agent=navigator.userAgent.replace(t[0],\"\"),this.platform[1]&&(this.agent=this.agent.replace(t[1],\"\")),this.agent=this.agent.replace(/  /g,\" \")}}else typeof process!=\"undefined\"&&(this.platform=`${process.platform} ${process.arch}`,this.agent=`NodeJS ${process.version}`)}get Canvas(){return Ga(this,yp)}set Canvas(t){fr(this,yp,t),globalThis.Canvas=t}get Image(){return Ga(this,bp)}set Image(t){fr(this,bp,t),globalThis.Image=t}get ImageData(){return Ga(this,vp)}set ImageData(t){fr(this,vp,t),globalThis.ImageData=t}async updateBackend(){this.backends=Object.keys(kt().registryFactory);try{this.tensorflow={version:tr().binding?tr().binding.TF_Version:void 0,gpu:tr().binding?tr().binding.isUsingGpuDevice():void 0}}catch(n){}this.wasm.supported=typeof WebAssembly!=\"undefined\",this.wasm.backend=this.backends.includes(\"wasm\"),this.wasm.supported&&this.wasm.backend&&(this.wasm.simd=await W().getAsync(\"WASM_HAS_SIMD_SUPPORT\"),this.wasm.multithread=await W().getAsync(\"WASM_HAS_MULTITHREAD_SUPPORT\"));let t=Nn(100,100),a=t?t.getContext(\"webgl2\"):void 0;this.webgl.supported=typeof a!=\"undefined\",this.webgl.backend=this.backends.includes(\"webgl\"),this.webgl.supported&&this.webgl.backend&&a&&(this.webgl.version=a.getParameter(a.VERSION),this.webgl.vendor=a.getParameter(a.VENDOR),this.webgl.renderer=a.getParameter(a.RENDERER),this.webgl.shader=a.getParameter(a.SHADING_LANGUAGE_VERSION)),this.webgpu.supported=this.browser&&typeof navigator.gpu!=\"undefined\",this.webgpu.backend=this.backends.includes(\"webgpu\");try{if(this.webgpu.supported){let n=await navigator.gpu.requestAdapter();this.webgpu.adapter=await(n==null?void 0:n.requestAdapterInfo())}}catch(n){this.webgpu.supported=!1}try{this.kernels=Zn(ia()).map(n=>n.kernelName.toLowerCase())}catch(n){}}updateCPU(){let t={model:\"\",flags:[]};this.node&&this.platform.startsWith(\"linux\"),this.cpu?this.cpu=t:Object.defineProperty(this,\"cpu\",{value:t})}};yp=new WeakMap,bp=new WeakMap,vp=new WeakMap;var ne=new Ap;var Jh=class{constructor(){ue(this,\"config\");ue(this,\"element\");ue(this,\"stream\");ue(this,\"devices\",[]);ue(this,\"enumerate\",async()=>{try{let t=await navigator.mediaDevices.enumerateDevices();this.devices=t.filter(a=>a.kind===\"videoinput\")}catch(t){this.devices=[]}return this.devices});ue(this,\"start\",async t=>{var r,s;if(t!=null&&t.debug&&(this.config.debug=t==null?void 0:t.debug),t!=null&&t.crop&&(this.config.crop=t==null?void 0:t.crop),t!=null&&t.mode&&(this.config.mode=t==null?void 0:t.mode),t!=null&&t.width&&(this.config.width=t==null?void 0:t.width),t!=null&&t.height&&(this.config.height=t==null?void 0:t.height),t!=null&&t.id&&(this.config.id=t==null?void 0:t.id),t!=null&&t.element)if(typeof t.element==\"string\"){let i=document.getElementById(t.element);if(i&&i instanceof HTMLVideoElement)this.element=i;else{this.config.debug&&K(\"webcam\",\"cannot get dom element\",t.element);return}}else if(t.element instanceof HTMLVideoElement)this.element=t.element;else{this.config.debug&&K(\"webcam\",\"unknown dom element\",t.element);return}else this.element=document.createElement(\"video\");let a={audio:!1,video:{facingMode:this.config.mode===\"front\"?\"user\":\"environment\",resizeMode:this.config.crop?\"crop-and-scale\":\"none\"}};if(((r=this.config)==null?void 0:r.width)>0&&(a.video.width={ideal:this.config.width}),((s=this.config)==null?void 0:s.height)>0&&(a.video.height={ideal:this.config.height}),this.config.id&&(a.video.deviceId=this.config.id),this.element.addEventListener(\"play\",()=>{this.config.debug&&K(\"webcam\",\"play\")}),this.element.addEventListener(\"pause\",()=>{this.config.debug&&K(\"webcam\",\"pause\")}),this.element.addEventListener(\"click\",async()=>{!this.element||!this.stream||(this.element.paused?await this.element.play():this.element.pause())}),!(navigator!=null&&navigator.mediaDevices)){this.config.debug&&K(\"webcam\",\"no devices\");return}try{this.stream=await navigator.mediaDevices.getUserMedia(a)}catch(i){K(\"webcam\",i);return}if(!this.stream){this.config.debug&&K(\"webcam\",\"no stream\");return}this.element.srcObject=this.stream,await new Promise(i=>{this.element?this.element.onloadeddata=()=>i(!0):i(!1)}),await this.element.play(),this.config.debug&&K(\"webcam\",{width:this.width,height:this.height,label:this.label,stream:this.stream,track:this.track,settings:this.settings,constraints:this.constraints,capabilities:this.capabilities})});ue(this,\"pause\",()=>{this.element&&this.element.pause()});ue(this,\"play\",async()=>{this.element&&await this.element.play()});ue(this,\"stop\",()=>{this.config.debug&&K(\"webcam\",\"stop\"),this.track&&this.track.stop()});this.config={element:void 0,debug:!0,mode:\"front\",crop:!1,width:0,height:0}}get track(){if(!!this.stream)return this.stream.getVideoTracks()[0]}get capabilities(){if(!!this.track)return this.track.getCapabilities?this.track.getCapabilities():void 0}get constraints(){if(!!this.track)return this.track.getConstraints?this.track.getConstraints():void 0}get settings(){if(!this.stream)return;let t=this.stream.getVideoTracks()[0];return t.getSettings?t.getSettings():void 0}get label(){return this.track?this.track.label:\"\"}get paused(){var t;return((t=this.element)==null?void 0:t.paused)||!1}get width(){var t;return((t=this.element)==null?void 0:t.videoWidth)||0}get height(){var t;return((t=this.element)==null?void 0:t.videoHeight)||0}};var q3={};hr(q3,{age:()=>Ipe,\"anti-spoofing\":()=>ece,antispoof:()=>cpe,blazeface:()=>hpe,\"blazeface-back\":()=>Spe,\"blazeface-front\":()=>Tpe,\"blazepose-detector\":()=>Cpe,\"blazepose-full\":()=>Npe,\"blazepose-heavy\":()=>Epe,\"blazepose-lite\":()=>Rpe,centernet:()=>fpe,default:()=>hce,efficientpose:()=>Mpe,\"efficientpose-i-lite\":()=>tce,\"efficientpose-ii-lite\":()=>ace,\"efficientpose-iv\":()=>nce,emotion:()=>mpe,faceboxes:()=>$pe,facemesh:()=>gpe,\"facemesh-attention\":()=>Ppe,\"facemesh-attention-pinto\":()=>_pe,\"facemesh-detection-full\":()=>Fpe,\"facemesh-detection-short\":()=>Ope,faceres:()=>xpe,\"faceres-deep\":()=>Dpe,gear:()=>zpe,gender:()=>Bpe,\"gender-ssrnet-imdb\":()=>Lpe,handdetect:()=>Wpe,\"handlandmark-full\":()=>Vpe,\"handlandmark-lite\":()=>Ape,\"handlandmark-sparse\":()=>Upe,handskeleton:()=>Gpe,handtrack:()=>ype,\"insightface-efficientnet-b0\":()=>rce,\"insightface-ghostnet-strides1\":()=>sce,\"insightface-ghostnet-strides2\":()=>ice,\"insightface-mobilenet-emore\":()=>oce,\"insightface-mobilenet-swish\":()=>lce,iris:()=>bpe,liveness:()=>vpe,meet:()=>Hpe,mobileface:()=>jpe,mobilefacenet:()=>qpe,models:()=>wpe,\"movenet-lightning\":()=>kpe,\"movenet-multipose\":()=>Xpe,\"movenet-thunder\":()=>Kpe,nanodet:()=>Zpe,\"nanodet-e\":()=>uce,\"nanodet-g\":()=>dce,\"nanodet-m\":()=>pce,\"nanodet-t\":()=>cce,posenet:()=>Ype,rvm:()=>Jpe,selfie:()=>Qpe});var cpe=853098,hpe=538928,fpe=4030290,mpe=820516,gpe=1477958,xpe=6978814,Ape=2023432,ype=2964837,bpe=2599092,vpe=592976,wpe=0,kpe=4650216,Ipe=161240,Spe=538928,Tpe=402048,Cpe=5928856,Npe=6339202,Epe=27502466,Rpe=2726402,Mpe=5651240,$pe=2013002,_pe=2387598,Ppe=2382414,Fpe=1026192,Ope=201268,Dpe=13957620,zpe=1498916,Lpe=161236,Bpe=201808,Wpe=3515612,Vpe=5431368,Upe=5286322,Gpe=5502280,Hpe=372228,jpe=2183192,qpe=5171976,Xpe=9448838,Kpe=12477112,Zpe=7574558,Ype=5032780,Jpe=3739355,Qpe=212886,ece=853098,tce=2269064,ace=5651240,nce=25643252,rce=13013224,sce=8093408,ice=8049584,oce=6938536,lce=12168584,uce=12319156,dce=7574558,pce=1887474,cce=5294216,hce={antispoof:cpe,blazeface:hpe,centernet:fpe,emotion:mpe,facemesh:gpe,faceres:xpe,\"handlandmark-lite\":Ape,handtrack:ype,iris:bpe,liveness:vpe,models:wpe,\"movenet-lightning\":kpe,age:Ipe,\"blazeface-back\":Spe,\"blazeface-front\":Tpe,\"blazepose-detector\":Cpe,\"blazepose-full\":Npe,\"blazepose-heavy\":Epe,\"blazepose-lite\":Rpe,efficientpose:Mpe,faceboxes:$pe,\"facemesh-attention-pinto\":_pe,\"facemesh-attention\":Ppe,\"facemesh-detection-full\":Fpe,\"facemesh-detection-short\":Ope,\"faceres-deep\":Dpe,gear:zpe,\"gender-ssrnet-imdb\":Lpe,gender:Bpe,handdetect:Wpe,\"handlandmark-full\":Vpe,\"handlandmark-sparse\":Upe,handskeleton:Gpe,meet:Hpe,mobileface:jpe,mobilefacenet:qpe,\"movenet-multipose\":Xpe,\"movenet-thunder\":Kpe,nanodet:Zpe,posenet:Ype,rvm:Jpe,selfie:Qpe,\"anti-spoofing\":ece,\"efficientpose-i-lite\":tce,\"efficientpose-ii-lite\":ace,\"efficientpose-iv\":nce,\"insightface-efficientnet-b0\":rce,\"insightface-ghostnet-strides1\":sce,\"insightface-ghostnet-strides2\":ice,\"insightface-mobilenet-emore\":oce,\"insightface-mobilenet-swish\":lce,\"nanodet-e\":uce,\"nanodet-g\":dce,\"nanodet-m\":pce,\"nanodet-t\":cce};var Ea={cacheModels:!0,cacheSupported:!0,verbose:!0,debug:!1,modelBasePath:\"\"},ha={};async function fce(e,t){return Ea.debug&&K(\"load model fetch:\",e,t),fetch(e,t)}function u9(e){Ea.cacheModels=e.cacheModels,Ea.verbose=e.debug,Ea.modelBasePath=e.modelBasePath}async function Ee(e){var u,p,c,d;let t=Q8(Ea.modelBasePath,e||\"\");t.toLowerCase().endsWith(\".json\")||(t+=\".json\");let a=t.includes(\"/\")?t.split(\"/\"):t.split(\"\\\\\"),n=a[a.length-1].replace(\".json\",\"\"),r=\"indexeddb://\"+n;ha[n]={name:n,sizeFromManifest:0,sizeLoadedWeights:0,sizeDesired:q3[n],inCache:!1,url:\"\"},Ea.cacheSupported=typeof indexedDB!=\"undefined\";let s={};try{s=Ea.cacheSupported&&Ea.cacheModels?await jn.listModels():{}}catch(h){Ea.cacheSupported=!1}ha[n].inCache=Ea.cacheSupported&&Ea.cacheModels&&Object.keys(s).includes(r),ha[n].url=ha[n].inCache?r:t;let i=typeof fetch==\"undefined\"?{}:{fetchFunc:(h,f)=>fce(h,f)},o=new op(ha[n].url,i),l=!1;try{o.findIOHandler(),Ea.debug&&K(\"model load handler:\",o.handler)}catch(h){K(\"error finding model i/o handler:\",t,h)}try{let h=await((u=o.handler)==null?void 0:u.load())||null;ha[n].sizeFromManifest=((p=h==null?void 0:h.weightData)==null?void 0:p.byteLength)||0,h?o.loadSync(h):o=await r3(ha[n].inCache?r:t,i),ha[n].sizeLoadedWeights=((d=(c=o.artifacts)==null?void 0:c.weightData)==null?void 0:d.byteLength)||0,Ea.verbose&&K(\"load:\",{model:n,url:o.modelUrl,bytes:ha[n].sizeLoadedWeights}),l=!0}catch(h){K(\"error loading model:\",t,h)}if(l&&Ea.cacheModels&&Ea.cacheSupported&&!ha[n].inCache)try{let h=await o.save(r);Ea.debug&&K(\"model saved:\",r,h)}catch(h){K(\"error saving model:\",t,h)}return o}var X3=\"3.0.1\";var vt={name:\"humangl\",priority:999,canvas:null,gl:null,extensions:[],webGLattr:{alpha:!1,antialias:!1,premultipliedAlpha:!1,preserveDrawingBuffer:!1,depth:!1,stencil:!1,failIfMajorPerformanceCaveat:!1,desynchronized:!0}};function xce(){let e=vt.gl;!e||(vt.extensions=e.getSupportedExtensions())}function d9(e){var t;if(e.config.backend===\"humangl\"&&(vt.name in kt().registry&&!((t=vt==null?void 0:vt.gl)!=null&&t.getParameter(vt.gl.VERSION))&&(K(\"humangl error: backend invalid context\"),e.models.reset()),!u2(vt.name))){try{vt.canvas=Nn(100,100)}catch(r){K(\"humangl error: cannot create canvas:\",r);return}try{if(vt.gl=vt.canvas.getContext(\"webgl2\",vt.webGLattr),!vt.gl){K(\"humangl error: cannot get webgl context\");return}if(!vt.gl.getParameter(vt.gl.VERSION).includes(\"2.0\")){K(\"backend override: using fallback webgl backend as webgl 2.0 is not detected\"),e.config.backend=\"webgl\";return}vt.canvas&&(vt.canvas.addEventListener(\"webglcontextlost\",s=>{throw K(\"humangl error:\",s.type),K(\"possible browser memory leak using webgl or conflict with multiple backend registrations\"),e.emit(\"error\"),new Error(\"backend error: webgl context lost\")}),vt.canvas.addEventListener(\"webglcontextrestored\",s=>{K(\"humangl error: context restored:\",s)}),vt.canvas.addEventListener(\"webglcontextcreationerror\",s=>{K(\"humangl error: context create:\",s)}))}catch(r){K(\"humangl error: cannot get webgl context:\",r);return}try{Fh(2,vt.gl)}catch(r){K(\"humangl error: cannot set webgl context:\",r);return}try{let r=new il(vt.gl);go(vt.name,()=>new fu(r),vt.priority)}catch(r){K(\"humangl error: cannot register webgl backend:\",r);return}try{Zn(\"webgl\").forEach(s=>{let i={...s,backendName:vt.name};mn(i)})}catch(r){K(\"humangl error: cannot update webgl backend registration:\",r);return}try{W().flagRegistry.WEBGL_VERSION&&W().set(\"WEBGL_VERSION\",2)}catch(r){K(\"humangl error: cannot set WebGL backend flags:\",r);return}xce();let a=tr(),n=typeof a.gpgpu!=\"undefined\"?a.getGPGPUContext().gl:null;n?e.config.debug&&K(\"humangl backend registered:\",{webgl:n.getParameter(n.VERSION),renderer:n.getParameter(n.RENDERER)}):K(\"humangl error: no current gl context:\",n,vt.gl)}}var ze={tf255:255,tf1:1,tf2:2,tf05:.5,tf127:127.5,rgb:[.2989,.587,.114]};function p9(){ze.tf255=Fe(255,\"float32\"),ze.tf1=Fe(1,\"float32\"),ze.tf2=Fe(2,\"float32\"),ze.tf05=Fe(.5,\"float32\"),ze.tf127=Fe(127.5,\"float32\"),ze.rgb=Ht([.2989,.587,.114],\"float32\")}async function bce(){var e;return await ne.updateBackend(),(e=ne.tensorflow)!=null&&e.version?\"tensorflow\":ne.webgpu.supported&&ne.webgpu.backend?\"webgpu\":ne.webgl.supported&&ne.webgl.backend?\"webgl\":ne.wasm.supported&&ne.wasm.backend?\"wasm\":\"cpu\"}function vce(e){let t=[];if(!ne.kernels.includes(\"mod\")){let a={kernelName:\"Mod\",backendName:ia(),kernelFunc:n=>$e(()=>fe(n.inputs.a,ae(me(n.inputs.a,n.inputs.b),n.inputs.b)))};mn(a),ne.kernels.push(\"mod\"),t.push(\"mod\")}if(!ne.kernels.includes(\"floormod\")){let a={kernelName:\"FloorMod\",backendName:ia(),kernelFunc:n=>$e(()=>be(ae(Yd(n.inputs.a,n.inputs.b),n.inputs.b),su(n.inputs.a,n.inputs.b)))};mn(a),ne.kernels.push(\"floormod\"),t.push(\"floormod\")}if(!ne.kernels.includes(\"rotatewithoffset\")&&e.softwareKernels){let a={kernelName:\"RotateWithOffset\",backendName:ia(),kernelFunc:n=>$e(()=>{let r=ia();Xd(\"cpu\");let s=ge.rotateWithOffset(n.inputs.image,n.attrs.radians,n.attrs.fillValue,n.attrs.center);return Xd(r),s})};mn(a),ne.kernels.push(\"rotatewithoffset\"),t.push(\"rotatewithoffset\")}t.length>0&&e.debug&&K(\"registered kernels:\",t)}var c9={};async function wp(e,t=!1){var a;if(e.state=\"backend\",((a=e.config.backend)==null?void 0:a.length)===0&&(e.config.backend=await bce()),t||ne.initial||e.config.backend&&e.config.backend.length>0&&ia()!==e.config.backend){let n=te();if(e.config.backend&&e.config.backend.length>0){if(typeof window==\"undefined\"&&typeof WorkerGlobalScope!=\"undefined\"&&e.config.debug&&e.config.debug&&K(\"running inside web worker\"),ne.browser&&e.config.backend===\"tensorflow\"&&(e.config.debug&&K(\"override: backend set to tensorflow while running in browser\"),e.config.backend=\"webgl\"),ne.node&&(e.config.backend===\"webgl\"||e.config.backend===\"humangl\")&&(e.config.debug&&K(`override: backend set to ${e.config.backend} while running in nodejs`),e.config.backend=\"tensorflow\"),ne.browser&&e.config.backend===\"webgpu\")if(typeof navigator==\"undefined\"||typeof navigator.gpu==\"undefined\")K(\"override: backend set to webgpu but browser does not support webgpu\"),e.config.backend=\"webgl\";else{let s=await navigator.gpu.requestAdapter();if(e.config.debug&&K(\"enumerated webgpu adapter:\",s),!s)K(\"override: backend set to webgpu but browser reports no available gpu\"),e.config.backend=\"webgl\";else{let i=\"requestAdapterInfo\"in s?await s.requestAdapterInfo():void 0;K(\"webgpu adapter info:\",i)}}let r=Object.keys(kt().registryFactory);if(e.config.backend===\"humangl\"&&!r.includes(\"humangl\")&&(d9(e),r=Object.keys(kt().registryFactory)),e.config.debug&&K(\"available backends:\",r),r.includes(e.config.backend)||(K(`error: backend ${e.config.backend} not found in registry`),e.config.backend=ne.node?\"tensorflow\":\"webgl\",e.config.debug&&K(`override: setting backend ${e.config.backend}`)),e.config.debug&&K(\"setting backend:\",[e.config.backend]),e.config.backend===\"wasm\"){if(W().flagRegistry.CANVAS2D_WILL_READ_FREQUENTLY&&W().set(\"CANVAS2D_WILL_READ_FREQUENTLY\",!0),e.config.debug&&K(\"wasm path:\",e.config.wasmPath),typeof Wh!=\"undefined\")Wh(e.config.wasmPath,e.config.wasmPlatformFetch);else throw new Error(\"backend error: attempting to use wasm backend but wasm path is not set\");let s=!1,i=!1;try{s=await W().getAsync(\"WASM_HAS_MULTITHREAD_SUPPORT\"),i=await W().getAsync(\"WASM_HAS_SIMD_SUPPORT\"),e.config.debug&&K(`wasm execution: ${i?\"simd\":\"no simd\"} ${s?\"multithreaded\":\"singlethreaded\"}`),e.config.debug&&!i&&K(\"warning: wasm simd support is not enabled\")}catch(o){K(\"wasm detection failed\")}}try{await Xd(e.config.backend),await Kd()}catch(s){return K(\"error: cannot set backend:\",e.config.backend,s),!1}e.config.debug&&(c9=JSON.parse(JSON.stringify(W().flags)))}if((ia()===\"humangl\"||ia()===\"webgl\")&&(W().flagRegistry.WEBGL_USE_SHAPES_UNIFORMS&&W().set(\"WEBGL_USE_SHAPES_UNIFORMS\",!0),W().flagRegistry.WEBGL_EXP_CONV&&W().set(\"WEBGL_EXP_CONV\",!0),e.config.debug&&typeof e.config.deallocate!=\"undefined\"&&e.config.deallocate&&(K(\"changing webgl: WEBGL_DELETE_TEXTURE_THRESHOLD:\",!0),W().set(\"WEBGL_DELETE_TEXTURE_THRESHOLD\",0))),ia(),e.config.debug){let r=W().flags,s={};for(let i of Object.keys(r))c9[i]!==r[i]&&(s[i]=r[i]);e.config.debug&&Object.keys(s).length>0&&K(\"backend:\",ia(),\"flags:\",s)}if(e.config.flags&&Object.keys(e.config.flags).length>0){e.config.debug&&K(\"flags:\",e.config.flags);for(let[r,s]of Object.entries(e.config.flags))W().set(r,s)}o2(),p9(),e.performance.initBackend=Math.trunc(te()-n),e.config.backend=ia(),await ne.updateBackend(),vce(e.config),ne.initial=!1}return!0}function Qh(e,t){for(let a of e){let n={kernelName:a,backendName:t.backend,kernelFunc:r=>{var s;return t.debug&&K(\"kernelFunc\",a,t.backend,r),(s=r==null?void 0:r.inputs)==null?void 0:s.info}};mn(n)}ne.kernels=Zn(ia()).map(a=>a.kernelName.toLowerCase())}var s0={};hr(s0,{all:()=>Jce,body:()=>t0,canvas:()=>Yce,face:()=>e0,gesture:()=>r0,hand:()=>a0,init:()=>tg,object:()=>n0,options:()=>$t,person:()=>Zce});var xn=e=>{if(!e)K(\"draw error: invalid canvas\");else if(!e.getContext)K(\"draw error: canvas context not defined\");else{let t=e.getContext(\"2d\");if(!t)K(\"draw error: cannot get canvas context\");else return t}return null},So=e=>Math.round(e*180/Math.PI),ct=(e,t,a)=>e.replace(t,typeof a==\"number\"?a.toFixed(1):a),To=(e,t)=>{if(!t.useDepth||typeof e==\"undefined\")return t.color;let a=Uint8ClampedArray.from([127+2*e,127-2*e,255]);return`rgba(${a[0]}, ${a[1]}, ${a[2]}, ${t.alpha})`};function En(e,t,a,n,r){let s=t.replace(/\\[.*\\]/g,\"\").split(`\n`).map(o=>o.trim()),i=Math.max(0,a);for(let o=s.length-1;o>=0;o--){let l=o*r.lineHeight+n;r.shadowColor&&r.shadowColor!==\"\"&&(e.fillStyle=r.shadowColor,e.fillText(s[o],i+5,l+16)),e.fillStyle=r.labelColor,e.fillText(s[o],i+4,l+15)}}function Nr(e,t,a,n,r){e.fillStyle=To(n,r),e.beginPath(),e.arc(t,a,r.pointSize,0,2*Math.PI),e.fill()}function sr(e,t,a,n,r,s){if(e.beginPath(),e.lineWidth=s.lineWidth,s.useCurves){let i=(t+t+n)/2,o=(a+a+r)/2;e.ellipse(i,o,n/2,r/2,0,0,2*Math.PI)}else e.moveTo(t+s.roundRect,a),e.lineTo(t+n-s.roundRect,a),e.quadraticCurveTo(t+n,a,t+n,a+s.roundRect),e.lineTo(t+n,a+r-s.roundRect),e.quadraticCurveTo(t+n,a+r,t+n-s.roundRect,a+r),e.lineTo(t+s.roundRect,a+r),e.quadraticCurveTo(t,a+r,t,a+r-s.roundRect),e.lineTo(t,a+s.roundRect),e.quadraticCurveTo(t,a,t+s.roundRect,a),e.closePath();e.stroke()}function K3(e,t,a){if(!(t.length<2)){e.beginPath(),e.moveTo(t[0][0],t[0][1]);for(let n of t)e.strokeStyle=To(n[2]||0,a),e.lineTo(Math.trunc(n[0]),Math.trunc(n[1]));e.stroke(),a.fillPolygons&&(e.closePath(),e.fill())}}function f9(e,t,a){if(!(t.length<2)){if(e.lineWidth=a.lineWidth,!a.useCurves||t.length<=2){K3(e,t,a);return}e.moveTo(t[0][0],t[0][1]);for(let n=0;n<t.length-2;n++){let r=(t[n][0]+t[n+1][0])/2,s=(t[n][1]+t[n+1][1])/2;e.quadraticCurveTo(t[n][0],t[n][1],r,s)}e.quadraticCurveTo(t[t.length-2][0],t[t.length-2][1],t[t.length-1][0],t[t.length-1][1]),e.stroke(),a.fillPolygons&&(e.closePath(),e.fill())}}function Z3(e,t,a,n=5){let r,s,i;e.beginPath(),e.moveTo(t[0],t[1]),e.lineTo(a[0],a[1]),r=Math.atan2(a[1]-t[1],a[0]-t[0]),s=n*Math.cos(r)+a[0],i=n*Math.sin(r)+a[1],e.moveTo(s,i),r+=1/3*(2*Math.PI),s=n*Math.cos(r)+a[0],i=n*Math.sin(r)+a[1],e.lineTo(s,i),r+=1/3*(2*Math.PI),s=n*Math.cos(r)+a[0],i=n*Math.sin(r)+a[1],e.lineTo(s,i),e.closePath(),e.stroke(),e.fill()}var $t={color:\"rgba(173, 216, 230, 0.6)\",labelColor:\"rgba(173, 216, 230, 1)\",shadowColor:\"black\",alpha:.5,font:'small-caps 16px \"Segoe UI\"',lineHeight:18,lineWidth:4,pointSize:2,roundRect:8,drawPoints:!1,drawLabels:!0,drawBoxes:!0,drawAttention:!0,drawGestures:!0,drawPolygons:!0,drawGaze:!0,fillPolygons:!1,useDepth:!0,useCurves:!1,faceLabels:\"\",bodyLabels:\"\",bodyPartLabels:\"\",objectLabels:\"\",handLabels:\"\",fingerLabels:\"\",gestureLabels:\"\"};var Rn={silhouette:[10,338,297,332,284,251,389,356,454,323,361,288,397,365,379,378,400,377,152,148,176,149,150,136,172,58,132,93,234,127,162,21,54,103,67,109],lipsUpperOuter:[185,40,39,37,0,267,269,270,409],lipsLowerOuter:[61,146,91,181,84,17,314,405,321,375,291],lipsUpperInner:[191,80,81,82,13,312,311,310,415],lipsLowerInner:[78,95,88,178,87,14,317,402,318,324,308],lipsLowerSemiOuter:[76,77,90,180,85,16,315,404,320,307,306],lipsUpperSemiOuter:[184,74,73,72,11,302,303,304,408],lipsLowerSemiInner:[62,96,89,179,86,15,316,403,319,325,292],lipsUpperSemiInner:[183,42,41,38,12,268,271,272,407],rightEyeUpper0:[246,161,160,159,158,157,173],rightEyeLower0:[33,7,163,144,145,153,154,155,133],rightEyeUpper1:[247,30,29,27,28,56,190],rightEyeLower1:[130,25,110,24,23,22,26,112,243],rightEyeUpper2:[113,225,224,223,222,221,189],rightEyeLower2:[226,31,228,229,230,231,232,233,244],rightEyeLower3:[143,111,117,118,119,120,121,128,245],rightEyebrowUpper:[156,70,63,105,66,107,55,193],rightEyebrowLower:[35,124,46,53,52,65],rightEyeIris:[473,474,475,476,477],leftEyeUpper0:[466,388,387,386,385,384,398],leftEyeLower0:[263,249,390,373,374,380,381,382,362],leftEyeUpper1:[467,260,259,257,258,286,414],leftEyeLower1:[359,255,339,254,253,252,256,341,463],leftEyeUpper2:[342,445,444,443,442,441,413],leftEyeLower2:[446,261,448,449,450,451,452,453,464],leftEyeLower3:[372,340,346,347,348,349,350,357,465],leftEyebrowUpper:[383,300,293,334,296,336,285,417],leftEyebrowLower:[265,353,276,283,282,295],leftEyeIris:[468,469,470,471,472],midwayBetweenEyes:[168],noseTip:[1],noseBottom:[2],noseRightCorner:[98],noseLeftCorner:[327],rightCheek:[205],leftCheek:[425]},Y3={count:468,mouth:13,symmetryLine:[13,Rn.midwayBetweenEyes[0]]},Co={leftEye:0,rightEye:1,nose:2,mouth:3,leftEar:4,rightEar:5,symmetryLine:[3,2]},J3=[{key:\"EyeUpper0\",indices:[9,10,11,12,13,14,15]},{key:\"EyeUpper1\",indices:[25,26,27,28,29,30,31]},{key:\"EyeUpper2\",indices:[41,42,43,44,45,46,47]},{key:\"EyeLower0\",indices:[0,1,2,3,4,5,6,7,8]},{key:\"EyeLower1\",indices:[16,17,18,19,20,21,22,23,24]},{key:\"EyeLower2\",indices:[32,33,34,35,36,37,38,39,40]},{key:\"EyeLower3\",indices:[54,55,56,57,58,59,60,61,62]},{key:\"EyebrowUpper\",indices:[63,64,65,66,67,68,69,70]},{key:\"EyebrowLower\",indices:[48,49,50,51,52,53]}],kp=[[.499976992607117,.652534008026123],[.500025987625122,.547487020492554],[.499974012374878,.602371990680695],[.482113003730774,.471979022026062],[.500150978565216,.527155995368958],[.499909996986389,.498252987861633],[.499523013830185,.40106201171875],[.289712011814117,.380764007568359],[.499954998493195,.312398016452789],[.499987006187439,.269918978214264],[.500023007392883,.107050001621246],[.500023007392883,.666234016418457],[.5000159740448,.679224014282227],[.500023007392883,.692348003387451],[.499976992607117,.695277988910675],[.499976992607117,.70593398809433],[.499976992607117,.719385027885437],[.499976992607117,.737019002437592],[.499967992305756,.781370997428894],[.499816000461578,.562981009483337],[.473773002624512,.573909997940063],[.104906998574734,.254140973091125],[.365929991006851,.409575998783112],[.338757991790771,.41302502155304],[.311120003461838,.409460008144379],[.274657994508743,.389131009578705],[.393361985683441,.403706014156342],[.345234006643295,.344011008739471],[.370094001293182,.346076011657715],[.319321990013123,.347265005111694],[.297903001308441,.353591024875641],[.24779200553894,.410809993743896],[.396889001131058,.842755019664764],[.280097991228104,.375599980354309],[.106310002505779,.399955987930298],[.2099249958992,.391353011131287],[.355807989835739,.534406006336212],[.471751004457474,.65040397644043],[.474155008792877,.680191993713379],[.439785003662109,.657229006290436],[.414617002010345,.66654098033905],[.450374007225037,.680860996246338],[.428770989179611,.682690978050232],[.374971002340317,.727805018424988],[.486716985702515,.547628998756409],[.485300987958908,.527395009994507],[.257764995098114,.314490020275116],[.401223003864288,.455172002315521],[.429818987846375,.548614978790283],[.421351999044418,.533740997314453],[.276895999908447,.532056987285614],[.483370006084442,.499586999416351],[.33721199631691,.282882988452911],[.296391993761063,.293242990970612],[.169294998049736,.193813979625702],[.447580009698868,.302609980106354],[.392390012741089,.353887975215912],[.354490011930466,.696784019470215],[.067304998636246,.730105042457581],[.442739009857178,.572826027870178],[.457098007202148,.584792017936707],[.381974011659622,.694710969924927],[.392388999462128,.694203019142151],[.277076005935669,.271932005882263],[.422551989555359,.563233017921448],[.385919004678726,.281364023685455],[.383103013038635,.255840003490448],[.331431001424789,.119714021682739],[.229923993349075,.232002973556519],[.364500999450684,.189113974571228],[.229622006416321,.299540996551514],[.173287004232407,.278747975826263],[.472878992557526,.666198015213013],[.446828007698059,.668527007102966],[.422762006521225,.673889994621277],[.445307999849319,.580065965652466],[.388103008270264,.693961024284363],[.403039008378983,.706539988517761],[.403629004955292,.693953037261963],[.460041999816895,.557139039039612],[.431158006191254,.692366003990173],[.452181994915009,.692366003990173],[.475387006998062,.692366003990173],[.465828001499176,.779190003871918],[.472328990697861,.736225962638855],[.473087012767792,.717857003211975],[.473122000694275,.704625964164734],[.473033010959625,.695277988910675],[.427942007780075,.695277988910675],[.426479011774063,.703539967536926],[.423162013292313,.711845993995667],[.4183090031147,.720062971115112],[.390094995498657,.639572978019714],[.013953999616206,.560034036636353],[.499913990497589,.58014702796936],[.413199990987778,.69539999961853],[.409626007080078,.701822996139526],[.468080013990402,.601534962654114],[.422728985548019,.585985004901886],[.463079988956451,.593783974647522],[.37211999297142,.47341400384903],[.334562003612518,.496073007583618],[.411671012639999,.546965003013611],[.242175996303558,.14767599105835],[.290776997804642,.201445996761322],[.327338010072708,.256527006626129],[.399509996175766,.748921036720276],[.441727995872498,.261676013469696],[.429764986038208,.187834024429321],[.412198007106781,.108901023864746],[.288955003023148,.398952007293701],[.218936994671822,.435410976409912],[.41278201341629,.398970007896423],[.257135003805161,.355440020561218],[.427684992551804,.437960982322693],[.448339998722076,.536936044692993],[.178560003638268,.45755398273468],[.247308000922203,.457193970680237],[.286267012357712,.467674970626831],[.332827985286713,.460712015628815],[.368755996227264,.447206974029541],[.398963987827301,.432654976844788],[.476410001516342,.405806005001068],[.189241006970406,.523923993110657],[.228962004184723,.348950982093811],[.490725994110107,.562400996685028],[.404670000076294,.485132992267609],[.019469000399113,.401564002037048],[.426243007183075,.420431017875671],[.396993011236191,.548797011375427],[.266469985246658,.376977026462555],[.439121007919312,.51895797252655],[.032313998788595,.644356966018677],[.419054001569748,.387154996395111],[.462783008813858,.505746960639954],[.238978996872902,.779744982719421],[.198220998048782,.831938028335571],[.107550002634525,.540755033493042],[.183610007166862,.740257024765015],[.134409993886948,.333683013916016],[.385764002799988,.883153975009918],[.490967005491257,.579378008842468],[.382384985685349,.508572995662689],[.174399003386497,.397670984268188],[.318785011768341,.39623498916626],[.343364000320435,.400596976280212],[.396100014448166,.710216999053955],[.187885001301765,.588537991046906],[.430987000465393,.944064974784851],[.318993002176285,.898285031318665],[.266247987747192,.869701027870178],[.500023007392883,.190576016902924],[.499976992607117,.954452991485596],[.366169989109039,.398822009563446],[.393207013607025,.39553701877594],[.410373002290726,.391080021858215],[.194993004202843,.342101991176605],[.388664990663528,.362284004688263],[.365961998701096,.355970978736877],[.343364000320435,.355356991291046],[.318785011768341,.35834002494812],[.301414996385574,.363156020641327],[.058132998645306,.319076001644135],[.301414996385574,.387449026107788],[.499987989664078,.618434011936188],[.415838003158569,.624195992946625],[.445681989192963,.566076993942261],[.465844005346298,.620640993118286],[.49992299079895,.351523995399475],[.288718998432159,.819945991039276],[.335278987884521,.852819979190826],[.440512001514435,.902418971061707],[.128294005990028,.791940987110138],[.408771991729736,.373893976211548],[.455606997013092,.451801002025604],[.499877005815506,.908990025520325],[.375436991453171,.924192011356354],[.11421000212431,.615022003650665],[.448662012815475,.695277988910675],[.4480200111866,.704632043838501],[.447111994028091,.715808033943176],[.444831997156143,.730794012546539],[.430011987686157,.766808986663818],[.406787008047104,.685672998428345],[.400738000869751,.681069016456604],[.392399996519089,.677703022956848],[.367855995893478,.663918972015381],[.247923001646996,.601333022117615],[.452769994735718,.420849978923798],[.43639200925827,.359887003898621],[.416164010763168,.368713974952698],[.413385987281799,.692366003990173],[.228018000721931,.683571994304657],[.468268007040024,.352671027183533],[.411361992359161,.804327011108398],[.499989002943039,.469825029373169],[.479153990745544,.442654013633728],[.499974012374878,.439637005329132],[.432112008333206,.493588984012604],[.499886006116867,.866917014122009],[.49991300702095,.821729004383087],[.456548988819122,.819200992584229],[.344549000263214,.745438992977142],[.37890899181366,.574010014533997],[.374292999505997,.780184984207153],[.319687992334366,.570737957954407],[.357154995203018,.604269981384277],[.295284003019333,.621580958366394],[.447750002145767,.862477004528046],[.410986006259918,.508723020553589],[.31395098567009,.775308012962341],[.354128003120422,.812552988529205],[.324548006057739,.703992962837219],[.189096003770828,.646299958229065],[.279776990413666,.71465802192688],[.1338230073452,.682700991630554],[.336768001317978,.644733011722565],[.429883986711502,.466521978378296],[.455527991056442,.548622965812683],[.437114000320435,.558896005153656],[.467287987470627,.529924988746643],[.414712011814117,.335219979286194],[.37704598903656,.322777986526489],[.344107985496521,.320150971412659],[.312875986099243,.32233202457428],[.283526003360748,.333190023899078],[.241245999932289,.382785975933075],[.102986000478268,.468762993812561],[.267612010240555,.424560010433197],[.297879010438919,.433175981044769],[.333433985710144,.433878004550934],[.366427004337311,.426115989685059],[.396012008190155,.416696012020111],[.420121014118195,.41022801399231],[.007561000064015,.480777025222778],[.432949006557465,.569517970085144],[.458638995885849,.479089021682739],[.473466008901596,.545744001865387],[.476087987422943,.563830018043518],[.468472003936768,.555056989192963],[.433990985155106,.582361996173859],[.483518004417419,.562983989715576],[.482482999563217,.57784903049469],[.42645001411438,.389798998832703],[.438998997211456,.39649498462677],[.450067013502121,.400434017181396],[.289712011814117,.368252992630005],[.276670008897781,.363372981548309],[.517862021923065,.471948027610779],[.710287988185883,.380764007568359],[.526226997375488,.573909997940063],[.895093023777008,.254140973091125],[.634069979190826,.409575998783112],[.661242008209229,.41302502155304],[.688880026340485,.409460008144379],[.725341975688934,.389131009578705],[.606630027294159,.40370500087738],[.654766023159027,.344011008739471],[.629905998706818,.346076011657715],[.680678009986877,.347265005111694],[.702096998691559,.353591024875641],[.75221198797226,.410804986953735],[.602918028831482,.842862963676453],[.719901978969574,.375599980354309],[.893692970275879,.399959981441498],[.790081977844238,.391354024410248],[.643998026847839,.534487962722778],[.528249025344849,.65040397644043],[.525849997997284,.680191040039062],[.560214996337891,.657229006290436],[.585384011268616,.66654098033905],[.549625992774963,.680860996246338],[.57122802734375,.682691991329193],[.624852001667023,.72809898853302],[.513050019741058,.547281980514526],[.51509702205658,.527251958847046],[.742246985435486,.314507007598877],[.598631024360657,.454979002475739],[.570338010787964,.548575043678284],[.578631997108459,.533622980117798],[.723087012767792,.532054007053375],[.516445994377136,.499638974666595],[.662801027297974,.282917976379395],[.70362401008606,.293271005153656],[.830704987049103,.193813979625702],[.552385985851288,.302568018436432],[.607609987258911,.353887975215912],[.645429015159607,.696707010269165],[.932694971561432,.730105042457581],[.557260990142822,.572826027870178],[.542901992797852,.584792017936707],[.6180260181427,.694710969924927],[.607590973377228,.694203019142151],[.722943007946014,.271963000297546],[.577413976192474,.563166975975037],[.614082992076874,.281386971473694],[.616907000541687,.255886018276215],[.668509006500244,.119913995265961],[.770092010498047,.232020974159241],[.635536015033722,.189248979091644],[.77039098739624,.299556016921997],[.826722025871277,.278755009174347],[.527121007442474,.666198015213013],[.553171992301941,.668527007102966],[.577238023281097,.673889994621277],[.554691970348358,.580065965652466],[.611896991729736,.693961024284363],[.59696102142334,.706539988517761],[.596370995044708,.693953037261963],[.539958000183105,.557139039039612],[.568841993808746,.692366003990173],[.547818005084991,.692366003990173],[.52461302280426,.692366003990173],[.534089982509613,.779141008853912],[.527670979499817,.736225962638855],[.526912987232208,.717857003211975],[.526877999305725,.704625964164734],[.526966989040375,.695277988910675],[.572058022022247,.695277988910675],[.573521018028259,.703539967536926],[.57683801651001,.711845993995667],[.581691026687622,.720062971115112],[.609944999217987,.639909982681274],[.986046016216278,.560034036636353],[.5867999792099,.69539999961853],[.590372025966644,.701822996139526],[.531915009021759,.601536989212036],[.577268004417419,.585934996604919],[.536915004253387,.593786001205444],[.627542972564697,.473352015018463],[.665585994720459,.495950996875763],[.588353991508484,.546862006187439],[.757824003696442,.14767599105835],[.709249973297119,.201507985591888],[.672684013843536,.256581008434296],[.600408971309662,.74900496006012],[.55826598405838,.261672019958496],[.570303976535797,.187870979309082],[.588165998458862,.109044015407562],[.711045026779175,.398952007293701],[.781069993972778,.435405015945435],[.587247014045715,.398931980133057],[.742869973182678,.355445981025696],[.572156012058258,.437651991844177],[.55186802148819,.536570012569427],[.821442008018494,.457556009292603],[.752701997756958,.457181990146637],[.71375697851181,.467626988887787],[.66711300611496,.460672974586487],[.631101012229919,.447153985500336],[.6008620262146,.432473003864288],[.523481011390686,.405627012252808],[.810747981071472,.523926019668579],[.771045982837677,.348959028720856],[.509127020835876,.562718033790588],[.595292985439301,.485023975372314],[.980530977249146,.401564002037048],[.573499977588654,.420000016689301],[.602994978427887,.548687994480133],[.733529984951019,.376977026462555],[.560611009597778,.519016981124878],[.967685997486115,.644356966018677],[.580985009670258,.387160003185272],[.537728011608124,.505385041236877],[.760966002941132,.779752969741821],[.801778972148895,.831938028335571],[.892440974712372,.54076099395752],[.816350996494293,.740260004997253],[.865594983100891,.333687007427216],[.614073991775513,.883246004581451],[.508952975273132,.579437971115112],[.617941975593567,.508316040039062],[.825608015060425,.397674977779388],[.681214988231659,.39623498916626],[.656635999679565,.400596976280212],[.603900015354156,.710216999053955],[.81208598613739,.588539004325867],[.56801301240921,.944564998149872],[.681007981300354,.898285031318665],[.733752012252808,.869701027870178],[.633830010890961,.398822009563446],[.606792986392975,.39553701877594],[.589659988880157,.391062021255493],[.805015981197357,.342108011245728],[.611334979534149,.362284004688263],[.634037971496582,.355970978736877],[.656635999679565,.355356991291046],[.681214988231659,.35834002494812],[.698584973812103,.363156020641327],[.941866993904114,.319076001644135],[.698584973812103,.387449026107788],[.584177017211914,.624107003211975],[.554318010807037,.566076993942261],[.534153997898102,.62064003944397],[.711217999458313,.819975018501282],[.664629995822906,.852871000766754],[.559099972248077,.902631998062134],[.871706008911133,.791940987110138],[.591234028339386,.373893976211548],[.544341027736664,.451583981513977],[.624562978744507,.924192011356354],[.88577002286911,.615028977394104],[.551338016986847,.695277988910675],[.551980018615723,.704632043838501],[.552887976169586,.715808033943176],[.555167973041534,.730794012546539],[.569944024085999,.767035007476807],[.593203008174896,.685675978660583],[.599261999130249,.681069016456604],[.607599973678589,.677703022956848],[.631937980651855,.663500010967255],[.752032995223999,.601315021514893],[.547226011753082,.420395016670227],[.563543975353241,.359827995300293],[.583841025829315,.368713974952698],[.586614012718201,.692366003990173],[.771915018558502,.683578014373779],[.531597018241882,.352482974529266],[.588370978832245,.804440975189209],[.52079701423645,.442565023899078],[.567984998226166,.493479013442993],[.543282985687256,.819254994392395],[.655317008495331,.745514988899231],[.621008992195129,.574018001556396],[.625559985637665,.78031200170517],[.680198013782501,.570719003677368],[.64276397228241,.604337990283966],[.704662978649139,.621529996395111],[.552012026309967,.862591981887817],[.589071989059448,.508637011051178],[.685944974422455,.775357007980347],[.645735025405884,.812640011310577],[.675342977046967,.703978002071381],[.810858011245728,.646304965019226],[.72012197971344,.714666962623596],[.866151988506317,.682704985141754],[.663187026977539,.644596993923187],[.570082008838654,.466325998306274],[.544561982154846,.548375964164734],[.562758982181549,.558784961700439],[.531987011432648,.530140042304993],[.585271000862122,.335177004337311],[.622952997684479,.32277899980545],[.655896008014679,.320163011550903],[.687132000923157,.322345972061157],[.716481983661652,.333200991153717],[.758756995201111,.382786989212036],[.897013008594513,.468769013881683],[.732392013072968,.424547016620636],[.70211398601532,.433162987232208],[.66652500629425,.433866024017334],[.633504986763,.426087975502014],[.603875994682312,.416586995124817],[.579657971858978,.409945011138916],[.992439985275269,.480777025222778],[.567192018032074,.569419980049133],[.54136598110199,.478899002075195],[.526564002037048,.546118021011353],[.523913025856018,.563830018043518],[.531529009342194,.555056989192963],[.566035985946655,.582329034805298],[.51631098985672,.563053965568542],[.5174720287323,.577877044677734],[.573594987392426,.389806985855103],[.560697972774506,.395331978797913],[.549755990505219,.399751007556915],[.710287988185883,.368252992630005],[.723330020904541,.363372981548309]],No=[127,34,139,11,0,37,232,231,120,72,37,39,128,121,47,232,121,128,104,69,67,175,171,148,157,154,155,118,50,101,73,39,40,9,151,108,48,115,131,194,204,211,74,40,185,80,42,183,40,92,186,230,229,118,202,212,214,83,18,17,76,61,146,160,29,30,56,157,173,106,204,194,135,214,192,203,165,98,21,71,68,51,45,4,144,24,23,77,146,91,205,50,187,201,200,18,91,106,182,90,91,181,85,84,17,206,203,36,148,171,140,92,40,39,193,189,244,159,158,28,247,246,161,236,3,196,54,68,104,193,168,8,117,228,31,189,193,55,98,97,99,126,47,100,166,79,218,155,154,26,209,49,131,135,136,150,47,126,217,223,52,53,45,51,134,211,170,140,67,69,108,43,106,91,230,119,120,226,130,247,63,53,52,238,20,242,46,70,156,78,62,96,46,53,63,143,34,227,173,155,133,123,117,111,44,125,19,236,134,51,216,206,205,154,153,22,39,37,167,200,201,208,36,142,100,57,212,202,20,60,99,28,158,157,35,226,113,160,159,27,204,202,210,113,225,46,43,202,204,62,76,77,137,123,116,41,38,72,203,129,142,64,98,240,49,102,64,41,73,74,212,216,207,42,74,184,169,170,211,170,149,176,105,66,69,122,6,168,123,147,187,96,77,90,65,55,107,89,90,180,101,100,120,63,105,104,93,137,227,15,86,85,129,102,49,14,87,86,55,8,9,100,47,121,145,23,22,88,89,179,6,122,196,88,95,96,138,172,136,215,58,172,115,48,219,42,80,81,195,3,51,43,146,61,171,175,199,81,82,38,53,46,225,144,163,110,246,33,7,52,65,66,229,228,117,34,127,234,107,108,69,109,108,151,48,64,235,62,78,191,129,209,126,111,35,143,163,161,246,117,123,50,222,65,52,19,125,141,221,55,65,3,195,197,25,7,33,220,237,44,70,71,139,122,193,245,247,130,33,71,21,162,153,158,159,170,169,150,188,174,196,216,186,92,144,160,161,2,97,167,141,125,241,164,167,37,72,38,12,145,159,160,38,82,13,63,68,71,226,35,111,158,153,154,101,50,205,206,92,165,209,198,217,165,167,97,220,115,218,133,112,243,239,238,241,214,135,169,190,173,133,171,208,32,125,44,237,86,87,178,85,86,179,84,85,180,83,84,181,201,83,182,137,93,132,76,62,183,61,76,184,57,61,185,212,57,186,214,207,187,34,143,156,79,239,237,123,137,177,44,1,4,201,194,32,64,102,129,213,215,138,59,166,219,242,99,97,2,94,141,75,59,235,24,110,228,25,130,226,23,24,229,22,23,230,26,22,231,112,26,232,189,190,243,221,56,190,28,56,221,27,28,222,29,27,223,30,29,224,247,30,225,238,79,20,166,59,75,60,75,240,147,177,215,20,79,166,187,147,213,112,233,244,233,128,245,128,114,188,114,217,174,131,115,220,217,198,236,198,131,134,177,132,58,143,35,124,110,163,7,228,110,25,356,389,368,11,302,267,452,350,349,302,303,269,357,343,277,452,453,357,333,332,297,175,152,377,384,398,382,347,348,330,303,304,270,9,336,337,278,279,360,418,262,431,304,408,409,310,415,407,270,409,410,450,348,347,422,430,434,313,314,17,306,307,375,387,388,260,286,414,398,335,406,418,364,367,416,423,358,327,251,284,298,281,5,4,373,374,253,307,320,321,425,427,411,421,313,18,321,405,406,320,404,405,315,16,17,426,425,266,377,400,369,322,391,269,417,465,464,386,257,258,466,260,388,456,399,419,284,332,333,417,285,8,346,340,261,413,441,285,327,460,328,355,371,329,392,439,438,382,341,256,429,420,360,364,394,379,277,343,437,443,444,283,275,440,363,431,262,369,297,338,337,273,375,321,450,451,349,446,342,467,293,334,282,458,461,462,276,353,383,308,324,325,276,300,293,372,345,447,382,398,362,352,345,340,274,1,19,456,248,281,436,427,425,381,256,252,269,391,393,200,199,428,266,330,329,287,273,422,250,462,328,258,286,384,265,353,342,387,259,257,424,431,430,342,353,276,273,335,424,292,325,307,366,447,345,271,303,302,423,266,371,294,455,460,279,278,294,271,272,304,432,434,427,272,407,408,394,430,431,395,369,400,334,333,299,351,417,168,352,280,411,325,319,320,295,296,336,319,403,404,330,348,349,293,298,333,323,454,447,15,16,315,358,429,279,14,15,316,285,336,9,329,349,350,374,380,252,318,402,403,6,197,419,318,319,325,367,364,365,435,367,397,344,438,439,272,271,311,195,5,281,273,287,291,396,428,199,311,271,268,283,444,445,373,254,339,263,466,249,282,334,296,449,347,346,264,447,454,336,296,299,338,10,151,278,439,455,292,407,415,358,371,355,340,345,372,390,249,466,346,347,280,442,443,282,19,94,370,441,442,295,248,419,197,263,255,359,440,275,274,300,383,368,351,412,465,263,467,466,301,368,389,380,374,386,395,378,379,412,351,419,436,426,322,373,390,388,2,164,393,370,462,461,164,0,267,302,11,12,374,373,387,268,12,13,293,300,301,446,261,340,385,384,381,330,266,425,426,423,391,429,355,437,391,327,326,440,457,438,341,382,362,459,457,461,434,430,394,414,463,362,396,369,262,354,461,457,316,403,402,315,404,403,314,405,404,313,406,405,421,418,406,366,401,361,306,408,407,291,409,408,287,410,409,432,436,410,434,416,411,264,368,383,309,438,457,352,376,401,274,275,4,421,428,262,294,327,358,433,416,367,289,455,439,462,370,326,2,326,370,305,460,455,254,449,448,255,261,446,253,450,449,252,451,450,256,452,451,341,453,452,413,464,463,441,413,414,258,442,441,257,443,442,259,444,443,260,445,444,467,342,445,459,458,250,289,392,290,290,328,460,376,433,435,250,290,392,411,416,433,341,463,464,453,464,465,357,465,412,343,412,399,360,363,440,437,399,456,420,456,363,401,435,288,372,383,353,339,255,249,448,261,255,133,243,190,133,155,112,33,246,247,33,130,25,398,384,286,362,398,414,362,463,341,263,359,467,263,249,255,466,467,260,75,60,166,238,239,79,162,127,139,72,11,37,121,232,120,73,72,39,114,128,47,233,232,128,103,104,67,152,175,148,173,157,155,119,118,101,74,73,40,107,9,108,49,48,131,32,194,211,184,74,185,191,80,183,185,40,186,119,230,118,210,202,214,84,83,17,77,76,146,161,160,30,190,56,173,182,106,194,138,135,192,129,203,98,54,21,68,5,51,4,145,144,23,90,77,91,207,205,187,83,201,18,181,91,182,180,90,181,16,85,17,205,206,36,176,148,140,165,92,39,245,193,244,27,159,28,30,247,161,174,236,196,103,54,104,55,193,8,111,117,31,221,189,55,240,98,99,142,126,100,219,166,218,112,155,26,198,209,131,169,135,150,114,47,217,224,223,53,220,45,134,32,211,140,109,67,108,146,43,91,231,230,120,113,226,247,105,63,52,241,238,242,124,46,156,95,78,96,70,46,63,116,143,227,116,123,111,1,44,19,3,236,51,207,216,205,26,154,22,165,39,167,199,200,208,101,36,100,43,57,202,242,20,99,56,28,157,124,35,113,29,160,27,211,204,210,124,113,46,106,43,204,96,62,77,227,137,116,73,41,72,36,203,142,235,64,240,48,49,64,42,41,74,214,212,207,183,42,184,210,169,211,140,170,176,104,105,69,193,122,168,50,123,187,89,96,90,66,65,107,179,89,180,119,101,120,68,63,104,234,93,227,16,15,85,209,129,49,15,14,86,107,55,9,120,100,121,153,145,22,178,88,179,197,6,196,89,88,96,135,138,136,138,215,172,218,115,219,41,42,81,5,195,51,57,43,61,208,171,199,41,81,38,224,53,225,24,144,110,105,52,66,118,229,117,227,34,234,66,107,69,10,109,151,219,48,235,183,62,191,142,129,126,116,111,143,7,163,246,118,117,50,223,222,52,94,19,141,222,221,65,196,3,197,45,220,44,156,70,139,188,122,245,139,71,162,145,153,159,149,170,150,122,188,196,206,216,92,163,144,161,164,2,167,242,141,241,0,164,37,11,72,12,144,145,160,12,38,13,70,63,71,31,226,111,157,158,154,36,101,205,203,206,165,126,209,217,98,165,97,237,220,218,237,239,241,210,214,169,140,171,32,241,125,237,179,86,178,180,85,179,181,84,180,182,83,181,194,201,182,177,137,132,184,76,183,185,61,184,186,57,185,216,212,186,192,214,187,139,34,156,218,79,237,147,123,177,45,44,4,208,201,32,98,64,129,192,213,138,235,59,219,141,242,97,97,2,141,240,75,235,229,24,228,31,25,226,230,23,229,231,22,230,232,26,231,233,112,232,244,189,243,189,221,190,222,28,221,223,27,222,224,29,223,225,30,224,113,247,225,99,60,240,213,147,215,60,20,166,192,187,213,243,112,244,244,233,245,245,128,188,188,114,174,134,131,220,174,217,236,236,198,134,215,177,58,156,143,124,25,110,7,31,228,25,264,356,368,0,11,267,451,452,349,267,302,269,350,357,277,350,452,357,299,333,297,396,175,377,381,384,382,280,347,330,269,303,270,151,9,337,344,278,360,424,418,431,270,304,409,272,310,407,322,270,410,449,450,347,432,422,434,18,313,17,291,306,375,259,387,260,424,335,418,434,364,416,391,423,327,301,251,298,275,281,4,254,373,253,375,307,321,280,425,411,200,421,18,335,321,406,321,320,405,314,315,17,423,426,266,396,377,369,270,322,269,413,417,464,385,386,258,248,456,419,298,284,333,168,417,8,448,346,261,417,413,285,326,327,328,277,355,329,309,392,438,381,382,256,279,429,360,365,364,379,355,277,437,282,443,283,281,275,363,395,431,369,299,297,337,335,273,321,348,450,349,359,446,467,283,293,282,250,458,462,300,276,383,292,308,325,283,276,293,264,372,447,346,352,340,354,274,19,363,456,281,426,436,425,380,381,252,267,269,393,421,200,428,371,266,329,432,287,422,290,250,328,385,258,384,446,265,342,386,387,257,422,424,430,445,342,276,422,273,424,306,292,307,352,366,345,268,271,302,358,423,371,327,294,460,331,279,294,303,271,304,436,432,427,304,272,408,395,394,431,378,395,400,296,334,299,6,351,168,376,352,411,307,325,320,285,295,336,320,319,404,329,330,349,334,293,333,366,323,447,316,15,315,331,358,279,317,14,316,8,285,9,277,329,350,253,374,252,319,318,403,351,6,419,324,318,325,397,367,365,288,435,397,278,344,439,310,272,311,248,195,281,375,273,291,175,396,199,312,311,268,276,283,445,390,373,339,295,282,296,448,449,346,356,264,454,337,336,299,337,338,151,294,278,455,308,292,415,429,358,355,265,340,372,388,390,466,352,346,280,295,442,282,354,19,370,285,441,295,195,248,197,457,440,274,301,300,368,417,351,465,251,301,389,385,380,386,394,395,379,399,412,419,410,436,322,387,373,388,326,2,393,354,370,461,393,164,267,268,302,12,386,374,387,312,268,13,298,293,301,265,446,340,380,385,381,280,330,425,322,426,391,420,429,437,393,391,326,344,440,438,458,459,461,364,434,394,428,396,262,274,354,457,317,316,402,316,315,403,315,314,404,314,313,405,313,421,406,323,366,361,292,306,407,306,291,408,291,287,409,287,432,410,427,434,411,372,264,383,459,309,457,366,352,401,1,274,4,418,421,262,331,294,358,435,433,367,392,289,439,328,462,326,94,2,370,289,305,455,339,254,448,359,255,446,254,253,449,253,252,450,252,256,451,256,341,452,414,413,463,286,441,414,286,258,441,258,257,442,257,259,443,259,260,444,260,467,445,309,459,250,305,289,290,305,290,460,401,376,435,309,250,392,376,411,433,453,341,464,357,453,465,343,357,412,437,343,399,344,360,440,420,437,456,360,420,363,361,401,288,265,372,353,390,339,249,339,448,255];var wce=[127,234,132,58,172,150,149,148,152,377,378,379,397,288,361,454,356,70,63,105,66,107,336,296,334,293,300,168,6,195,4,98,97,2,326,327,33,160,158,133,153,144,362,385,387,263,373,380,57,40,37,0,267,270,287,321,314,17,84,91,78,81,13,311,308,402,14,178],kce=[33,133,362,263,1,62,308,159,145,386,374,6,102,331,2,13,14,70,105,107,336,334,300,54,10,284,50,280,234,454,58,288,152],Ice=[33,133,362,263,1,78,308],R2e=wce.map(e=>kp[e]),M2e=kce.map(e=>kp[e]),$2e=Ice.map(e=>kp[e]);function ds(e){let t=e.map(a=>a[0]);return t.push(e[e.length-1][1]),t}var Sce=[[61,146],[146,91],[91,181],[181,84],[84,17],[17,314],[314,405],[405,321],[321,375],[375,291],[61,185],[185,40],[40,39],[39,37],[37,0],[0,267],[267,269],[269,270],[270,409],[409,291],[78,95],[95,88],[88,178],[178,87],[87,14],[14,317],[317,402],[402,318],[318,324],[324,308],[78,191],[191,80],[80,81],[81,82],[82,13],[13,312],[312,311],[311,310],[310,415],[415,308]],Tce=[[263,249],[249,390],[390,373],[373,374],[374,380],[380,381],[381,382],[382,362],[263,466],[466,388],[388,387],[387,386],[386,385],[385,384],[384,398],[398,362]],Cce=[[276,283],[283,282],[282,295],[295,285],[300,293],[293,334],[334,296],[296,336]],Nce=[[474,475],[475,476],[476,477],[477,474]],Ece=[[33,7],[7,163],[163,144],[144,145],[145,153],[153,154],[154,155],[155,133],[33,246],[246,161],[161,160],[160,159],[159,158],[158,157],[157,173],[173,133]],Rce=[[46,53],[53,52],[52,65],[65,55],[70,63],[63,105],[105,66],[66,107]],Mce=[[469,470],[470,471],[471,472],[472,469]],$ce=[[10,338],[338,297],[297,332],[332,284],[284,251],[251,389],[389,356],[356,454],[454,323],[323,361],[361,288],[288,397],[397,365],[365,379],[379,378],[378,400],[400,377],[377,152],[152,148],[148,176],[176,149],[149,150],[150,136],[136,172],[172,58],[58,132],[132,93],[93,234],[234,127],[127,162],[162,21],[21,54],[54,103],[103,67],[67,109],[109,10]],_2e={lips:ds(Sce),leftEye:ds(Tce),leftEyebrow:ds(Cce),leftIris:ds(Nce),rightEye:ds(Ece),rightEyebrow:ds(Rce),rightIris:ds(Mce),faceOval:ds($ce)};var _ce=[[61,146],[146,91],[91,181],[181,84],[84,17],[17,314],[314,405],[405,321],[321,375],[375,291],[61,185],[185,40],[40,39],[39,37],[37,0],[0,267],[267,269],[269,270],[270,409],[409,291],[78,95],[95,88],[88,178],[178,87],[87,14],[14,317],[317,402],[402,318],[318,324],[324,308],[78,191],[191,80],[80,81],[81,82],[82,13],[13,312],[312,311],[311,310],[310,415],[415,308]],Pce=[[263,249],[249,390],[390,373],[373,374],[374,380],[380,381],[381,382],[382,362],[263,466],[466,388],[388,387],[387,386],[386,385],[385,384],[384,398],[398,362]],Fce=[[276,283],[283,282],[282,295],[295,285],[300,293],[293,334],[334,296],[296,336]],Oce=[[474,475],[475,476],[476,477],[477,474]],Dce=[[33,7],[7,163],[163,144],[144,145],[145,153],[153,154],[154,155],[155,133],[33,246],[246,161],[161,160],[160,159],[159,158],[158,157],[157,173],[173,133]],zce=[[46,53],[53,52],[52,65],[65,55],[70,63],[63,105],[105,66],[66,107]],Lce=[[469,470],[470,471],[471,472],[472,469]],Bce=[[10,338],[338,297],[297,332],[332,284],[284,251],[251,389],[389,356],[356,454],[454,323],[323,361],[361,288],[288,397],[397,365],[365,379],[379,378],[378,400],[400,377],[377,152],[152,148],[148,176],[176,149],[149,150],[150,136],[136,172],[172,58],[58,132],[132,93],[93,234],[234,127],[127,162],[162,21],[21,54],[54,103],[103,67],[67,109],[109,10]];function ps(e){let t=e.map(a=>a[0]);return t.push(e[e.length-1][1]),t}var Wce={lips:ps(_ce),leftEye:ps(Pce),leftEyebrow:ps(Fce),leftIris:ps(Oce),rightEye:ps(Dce),rightEyebrow:ps(zce),rightIris:ps(Lce),faceOval:ps(Bce)},Vce=Object.entries(Wce).map(([e,t])=>t.map(a=>[a,e])).flat(),P2e=new Map(Vce),Ip=[61,146,91,181,84,17,314,405,321,375,291,185,40,39,37,0,267,269,270,409,78,95,88,178,87,14,317,402,318,324,308,191,80,81,82,13,312,311,310,415,76,77,90,180,85,16,315,404,320,307,306,184,74,73,72,11,302,303,304,408,62,96,89,179,86,15,316,403,319,325,292,183,42,41,38,12,268,271,272,407],Eo=[33,7,163,144,145,153,154,155,133,246,161,160,159,158,157,173,130,25,110,24,23,22,26,112,243,247,30,29,27,28,56,190,226,31,228,229,230,231,232,233,244,113,225,224,223,222,221,189,35,124,46,53,52,65,143,111,117,118,119,120,121,128,245,156,70,63,105,66,107,55,193],Ro=[263,249,390,373,374,380,381,382,362,466,388,387,386,385,384,398,359,255,339,254,253,252,256,341,463,467,260,259,257,258,286,414,446,261,448,449,450,451,452,453,464,342,445,444,443,442,441,413,265,353,276,283,282,295,372,340,346,347,348,349,350,357,465,383,300,293,334,296,336,285,417];var lt;function Uce(e,t){var n,r,s,i,o,l,u,p,c;if(!lt.drawLabels||((n=lt.faceLabels)==null?void 0:n.length)===0)return;let a=lt.faceLabels.slice();if(e.score&&(a=ct(a,\"[score]\",100*e.score)),e.gender&&(a=ct(a,\"[gender]\",e.gender)),e.genderScore&&(a=ct(a,\"[genderScore]\",100*e.genderScore)),e.age&&(a=ct(a,\"[age]\",e.age)),e.distance&&(a=ct(a,\"[distance]\",100*e.distance)),e.real&&(a=ct(a,\"[real]\",100*e.real)),e.live&&(a=ct(a,\"[live]\",100*e.live)),e.emotion&&e.emotion.length>0){let d=e.emotion.map(h=>`${Math.trunc(100*h.score)}% ${h.emotion}`);d.length>3&&(d.length=3),a=ct(a,\"[emotions]\",d.join(\" \"))}(s=(r=e.rotation)==null?void 0:r.angle)!=null&&s.roll&&(a=ct(a,\"[roll]\",So(e.rotation.angle.roll))),(o=(i=e.rotation)==null?void 0:i.angle)!=null&&o.yaw&&(a=ct(a,\"[yaw]\",So(e.rotation.angle.yaw))),(u=(l=e.rotation)==null?void 0:l.angle)!=null&&u.pitch&&(a=ct(a,\"[pitch]\",So(e.rotation.angle.pitch))),(c=(p=e.rotation)==null?void 0:p.gaze)!=null&&c.bearing&&(a=ct(a,\"[gaze]\",So(e.rotation.gaze.bearing))),En(t,a,e.box[0],e.box[1],lt)}function Gce(e,t){var a,n,r,s;if(((a=e.annotations)==null?void 0:a.leftEyeIris)&&((n=e.annotations)==null?void 0:n.leftEyeIris[0])){t.strokeStyle=lt.useDepth?\"rgba(255, 200, 255, 0.3)\":lt.color,t.beginPath();let i=Math.abs(e.annotations.leftEyeIris[3][0]-e.annotations.leftEyeIris[1][0])/2,o=Math.abs(e.annotations.leftEyeIris[4][1]-e.annotations.leftEyeIris[2][1])/2;t.ellipse(e.annotations.leftEyeIris[0][0],e.annotations.leftEyeIris[0][1],i,o,0,0,2*Math.PI),t.stroke(),lt.fillPolygons&&(t.fillStyle=lt.useDepth?\"rgba(255, 255, 200, 0.3)\":lt.color,t.fill())}if(((r=e.annotations)==null?void 0:r.rightEyeIris)&&((s=e.annotations)==null?void 0:s.rightEyeIris[0])){t.strokeStyle=lt.useDepth?\"rgba(255, 200, 255, 0.3)\":lt.color,t.beginPath();let i=Math.abs(e.annotations.rightEyeIris[3][0]-e.annotations.rightEyeIris[1][0])/2,o=Math.abs(e.annotations.rightEyeIris[4][1]-e.annotations.rightEyeIris[2][1])/2;t.ellipse(e.annotations.rightEyeIris[0][0],e.annotations.rightEyeIris[0][1],i,o,0,0,2*Math.PI),t.stroke(),lt.fillPolygons&&(t.fillStyle=lt.useDepth?\"rgba(255, 255, 200, 0.3)\":lt.color,t.fill())}}function Hce(e,t){var a;if(lt.drawGaze&&((a=e.rotation)==null?void 0:a.angle)&&typeof Path2D!=\"undefined\"){t.strokeStyle=\"pink\";let n=e.box[0]+e.box[2]/2-e.box[3]*So(e.rotation.angle.yaw)/90,r=e.box[1]+e.box[3]/2+e.box[2]*So(e.rotation.angle.pitch)/90,s=new Path2D(`\n      M ${e.box[0]+e.box[2]/2} ${e.box[1]}\n      C\n        ${n} ${e.box[1]},\n        ${n} ${e.box[1]+e.box[3]},\n        ${e.box[0]+e.box[2]/2} ${e.box[1]+e.box[3]}\n    `),i=new Path2D(`\n      M ${e.box[0]} ${e.box[1]+e.box[3]/2}\n      C \n        ${e.box[0]} ${r},\n        ${e.box[0]+e.box[2]} ${r},\n        ${e.box[0]+e.box[2]} ${e.box[1]+e.box[3]/2}\n    `);t.stroke(i),t.stroke(s)}}function jce(e,t){var a;if(lt.drawGaze&&((a=e.rotation)==null?void 0:a.gaze.strength)&&e.rotation.gaze.bearing&&e.annotations.leftEyeIris&&e.annotations.rightEyeIris&&e.annotations.leftEyeIris[0]&&e.annotations.rightEyeIris[0]){t.strokeStyle=\"pink\",t.fillStyle=\"pink\";let n=[e.annotations.leftEyeIris[0][0]+Math.sin(e.rotation.gaze.bearing)*e.rotation.gaze.strength*e.box[3],e.annotations.leftEyeIris[0][1]+Math.cos(e.rotation.gaze.bearing)*e.rotation.gaze.strength*e.box[2]];Z3(t,[e.annotations.leftEyeIris[0][0],e.annotations.leftEyeIris[0][1]],[n[0],n[1]],4);let r=[e.annotations.rightEyeIris[0][0]+Math.sin(e.rotation.gaze.bearing)*e.rotation.gaze.strength*e.box[3],e.annotations.rightEyeIris[0][1]+Math.cos(e.rotation.gaze.bearing)*e.rotation.gaze.strength*e.box[2]];Z3(t,[e.annotations.rightEyeIris[0][0],e.annotations.rightEyeIris[0][1]],[r[0],r[1]],4)}}function qce(e,t){if(lt.drawPolygons&&e.mesh.length>=468){t.lineWidth=1;for(let a=0;a<No.length/3;a++){let n=[No[a*3+0],No[a*3+1],No[a*3+2]].map(r=>e.mesh[r]);K3(t,n,lt)}Gce(e,t)}}function Xce(e,t){if(lt.drawPoints&&e.mesh.length>=468)for(let a=0;a<e.mesh.length;a++)Nr(t,e.mesh[a][0],e.mesh[a][1],e.mesh[a][2],lt),lt.drawAttention&&(Ip.includes(a)&&Nr(t,e.mesh[a][0],e.mesh[a][1],e.mesh[a][2]+127,lt),Eo.includes(a)&&Nr(t,e.mesh[a][0],e.mesh[a][1],e.mesh[a][2]-127,lt),Ro.includes(a)&&Nr(t,e.mesh[a][0],e.mesh[a][1],e.mesh[a][2]-127,lt))}function Kce(e,t){lt.drawBoxes&&sr(t,e.box[0],e.box[1],e.box[2],e.box[3],lt)}function e0(e,t,a){if(lt=Ct($t,a),!t||!e)return;let n=xn(e);if(!!n){n.font=lt.font,n.strokeStyle=lt.color,n.fillStyle=lt.color;for(let r of t)Kce(r,n),Uce(r,n),r.mesh&&r.mesh.length>0&&(Xce(r,n),qce(r,n),Hce(r,n),jce(r,n))}}function t0(e,t,a){var s,i;let n=Ct($t,a);if(!t||!e)return;let r=xn(e);if(!!r){r.lineJoin=\"round\";for(let o=0;o<t.length;o++){if(r.strokeStyle=n.color,r.fillStyle=n.color,r.lineWidth=n.lineWidth,r.font=n.font,n.drawBoxes&&t[o].box&&t[o].box.length===4&&(sr(r,t[o].box[0],t[o].box[1],t[o].box[2],t[o].box[3],n),n.drawLabels&&((s=n.bodyLabels)==null?void 0:s.length)>0)){let l=n.bodyLabels.slice();l=ct(l,\"[score]\",100*t[o].score),En(r,l,t[o].box[0],t[o].box[1],n)}if(n.drawPoints&&t[o].keypoints)for(let l=0;l<t[o].keypoints.length;l++)!t[o].keypoints[l].score||t[o].keypoints[l].score===0||(r.fillStyle=To(t[o].keypoints[l].position[2],n),Nr(r,t[o].keypoints[l].position[0],t[o].keypoints[l].position[1],0,n));if(n.drawLabels&&((i=n.bodyPartLabels)==null?void 0:i.length)>0&&t[o].keypoints){r.font=n.font;for(let l of t[o].keypoints){if(!l.score||l.score===0)continue;let u=n.bodyPartLabels.slice();u=ct(u,\"[label]\",l.part),u=ct(u,\"[score]\",100*l.score),En(r,u,l.position[0],l.position[1],n)}}if(n.drawPolygons&&t[o].keypoints&&t[o].annotations)for(let l of Object.values(t[o].annotations))for(let u of l)f9(r,u,n)}}}function a0(e,t,a){var s,i;let n=Ct($t,a);if(!t||!e)return;let r=xn(e);if(!!r){r.lineJoin=\"round\",r.font=n.font;for(let o of t){if(n.drawBoxes){if(r.strokeStyle=n.color,r.fillStyle=n.color,sr(r,o.box[0],o.box[1],o.box[2],o.box[3],n),n.drawLabels&&((s=n.handLabels)==null?void 0:s.length)>0){let l=n.handLabels.slice();l=ct(l,\"[label]\",o.label),l=ct(l,\"[score]\",100*o.score),En(r,l,o.box[0],o.box[1],n)}r.stroke()}if(n.drawPoints&&o.keypoints&&o.keypoints.length>0)for(let l of o.keypoints)r.fillStyle=To(l[2],n),Nr(r,l[0],l[1],0,n);if(n.drawLabels&&o.annotations&&((i=n.fingerLabels)==null?void 0:i.length)>0)for(let[l,u]of Object.entries(o.annotations)){let p=n.fingerLabels.slice();p=ct(p,\"[label]\",l),En(r,p,u[u.length-1][0],u[u.length-1][1],n)}if(n.drawPolygons&&o.annotations){let l=u=>{if(!(!u||u.length===0||!u[0]))for(let p=0;p<u.length;p++){r.beginPath();let c=u[p][2]||0;r.strokeStyle=To(p*c,n),r.moveTo(u[p>0?p-1:0][0],u[p>0?p-1:0][1]),r.lineTo(u[p][0],u[p][1]),r.stroke()}};r.lineWidth=n.lineWidth,l(o.annotations.index),l(o.annotations.middle),l(o.annotations.ring),l(o.annotations.pinky),l(o.annotations.thumb)}}}}function n0(e,t,a){var s;let n=Ct($t,a);if(!t||!e)return;let r=xn(e);if(!!r){r.lineJoin=\"round\",r.font=n.font;for(let i of t)if(n.drawBoxes){if(r.strokeStyle=n.color,r.fillStyle=n.color,sr(r,i.box[0],i.box[1],i.box[2],i.box[3],n),n.drawLabels&&((s=n.objectLabels)==null?void 0:s.length)>0){let o=n.objectLabels.slice();o=ct(o,\"[label]\",i.label),o=ct(o,\"[score]\",100*i.score),En(r,o,i.box[0],i.box[1],n)}r.stroke()}}}function r0(e,t,a){var r;let n=Ct($t,a);if(!(!t||!e)&&n.drawGestures&&((r=n.gestureLabels)==null?void 0:r.length)>0){let s=xn(e);if(!s)return;s.font=n.font,s.fillStyle=n.color;let i=1;for(let o=0;o<t.length;o++){let[l,u]=Object.entries(t[o]);if(u.length>1&&u[1].length>0){let p=l[1]>0?`#${l[1]}`:\"\",c=n.gestureLabels.slice();c=ct(c,\"[where]\",l[0]),c=ct(c,\"[who]\",p),c=ct(c,\"[what]\",u[1]),En(s,c,8,2+i*n.lineHeight,n),i+=1}}}}var cs={face:`face\n    confidence: [score]%\n    [gender] [genderScore]%\n    age: [age] years\n    distance: [distance]cm\n    real: [real]%\n    live: [live]%\n    [emotions]\n    roll: [roll]\\xB0 yaw:[yaw]\\xB0 pitch:[pitch]\\xB0\n    gaze: [gaze]\\xB0`,body:\"body [score]%\",bodyPart:\"[label] [score]%\",object:\"[label] [score]%\",hand:\"[label] [score]%\",finger:\"[label]\",gesture:\"[where] [who]: [what]\"};var eg=0;function Zce(e,t,a){let n=Ct($t,a);if(!t||!e)return;let r=xn(e);if(!!r){r.lineJoin=\"round\",r.font=n.font;for(let s=0;s<t.length;s++)if(n.drawBoxes){if(r.strokeStyle=n.color,r.fillStyle=n.color,sr(r,t[s].box[0],t[s].box[1],t[s].box[2],t[s].box[3],n),n.drawLabels){let i=`person #${s}`;n.shadowColor&&n.shadowColor!==\"\"&&(r.fillStyle=n.shadowColor,r.fillText(i,t[s].box[0]+3,1+t[s].box[1]+n.lineHeight,t[s].box[2])),r.fillStyle=n.labelColor,r.fillText(i,t[s].box[0]+2,0+t[s].box[1]+n.lineHeight,t[s].box[2])}r.stroke()}}}function Yce(e,t){if(!e||!t)return;let a=xn(t);!a||a.drawImage(e,0,0)}async function Jce(e,t,a){if(!(t!=null&&t.performance)||!e)return null;let n=te(),r=Ct($t,a),s=Promise.all([e0(e,t.face,r),t0(e,t.body,r),a0(e,t.hand,r),n0(e,t.object,r),r0(e,t.gesture,r)]);return eg=ne.perfadd?eg+Math.round(te()-n):Math.round(te()-n),t.performance.draw=eg,s}function tg(){$t.faceLabels=cs.face,$t.bodyLabels=cs.body,$t.bodyPartLabels=cs.bodyPart,$t.handLabels=cs.hand,$t.fingerLabels=cs.finger,$t.objectLabels=cs.object,$t.gestureLabels=cs.gesture}var i0={};hr(i0,{connected:()=>ng,kpt:()=>ag});var ag=[\"nose\",\"leftEyeInside\",\"leftEye\",\"leftEyeOutside\",\"rightEyeInside\",\"rightEye\",\"rightEyeOutside\",\"leftEar\",\"rightEar\",\"leftMouth\",\"rightMouth\",\"leftShoulder\",\"rightShoulder\",\"leftElbow\",\"rightElbow\",\"leftWrist\",\"rightWrist\",\"leftPinky\",\"rightPinky\",\"leftIndex\",\"rightIndex\",\"leftThumb\",\"rightThumb\",\"leftHip\",\"rightHip\",\"leftKnee\",\"rightKnee\",\"leftAnkle\",\"rightAnkle\",\"leftHeel\",\"rightHeel\",\"leftFoot\",\"rightFoot\",\"bodyCenter\",\"bodyTop\",\"leftPalm\",\"leftHand\",\"rightPalm\",\"rightHand\"],ng={shoulders:[\"leftShoulder\",\"rightShoulder\"],hips:[\"rightHip\",\"leftHip\"],mouth:[\"leftMouth\",\"rightMouth\"],leftLegUpper:[\"leftHip\",\"leftKnee\"],leftLegLower:[\"leftKnee\",\"leftAnkle\"],leftFoot:[\"leftAnkle\",\"leftHeel\",\"leftFoot\"],leftTorso:[\"leftShoulder\",\"leftHip\"],leftArmUpper:[\"leftShoulder\",\"leftElbow\"],leftArmLower:[\"leftElbow\",\"leftWrist\"],leftHand:[\"leftWrist\",\"leftPalm\"],leftHandPinky:[\"leftPalm\",\"leftPinky\"],leftHandIndex:[\"leftPalm\",\"leftIndex\"],leftHandThumb:[\"leftPalm\",\"leftThumb\"],leftEyeOutline:[\"leftEyeInside\",\"leftEyeOutside\"],rightLegUpper:[\"rightHip\",\"rightKnee\"],rightLegLower:[\"rightKnee\",\"rightAnkle\"],rightFoot:[\"rightAnkle\",\"rightHeel\",\"rightFoot\"],rightTorso:[\"rightShoulder\",\"rightHip\"],rightArmUpper:[\"rightShoulder\",\"rightElbow\"],rightArmLower:[\"rightElbow\",\"rightWrist\"],rightHand:[\"rightWrist\",\"rightPalm\"],rightHandPinky:[\"rightPalm\",\"rightPinky\"],rightHandIndex:[\"rightPalm\",\"rightIndex\"],rightHandThumb:[\"rightPalm\",\"rightThumb\"],rightEyeOutline:[\"rightEyeInside\",\"rightEyeOutside\"]};var An,Mo=224,x9,Qce=5,o0=[8,16,32,32,32];function ehe(){let e=[],t=0;for(;t<Qce;){let a=0,n=t;for(;n<o0.length&&o0[n]===o0[t];)a+=2,n++;let r=o0[t],s=Math.ceil(Mo/r),i=Math.ceil(Mo/r);for(let o=0;o<s;++o)for(let l=0;l<i;++l)for(let u=0;u<a;++u)e.push({x:(l+.5)/i,y:(o+.5)/s});t=n}x9={x:Ht(e.map(a=>a.x)),y:Ht(e.map(a=>a.y))}}async function A9(e){if(ne.initial&&(An=null),!An&&e.body.detector&&e.body.detector.modelPath){An=await Ee(e.body.detector.modelPath);let t=An!=null&&An.executor?Object.values(An.modelSignature.inputs):void 0;Mo=Array.isArray(t)?parseInt(t[0].tensorShape.dim[1].size):0}else e.debug&&An&&K(\"cached model:\",An.modelUrl);return ehe(),An}var g9=[5,5];function the(e,t){return $e(()=>{let a=ka(e,12,1),n=_e(a[0]),r=_e(a[1]),s=_e(a[2]),i=_e(a[3]);n=be(me(n,Mo),t.x),r=be(me(r,Mo),t.y),s=ae(me(s,Mo),g9[0]),i=ae(me(i,Mo),g9[1]);let o=fe(n,me(s,2)),l=fe(r,me(i,2)),u=be(o,s),p=be(l,i);return sa([o,l,u,p],1)})}async function ahe(e,t,a,n){var u,p;let r=[],s={};s.boxes=the(e,x9),s.scores=Da(t),s.nms=await ge.nonMaxSuppressionAsync(s.boxes,s.scores,1,((u=a.body.detector)==null?void 0:u.minConfidence)||.1,((p=a.body.detector)==null?void 0:p.iouThreshold)||.1);let i=await s.nms.data(),o=await s.scores.data(),l=await s.boxes.array();for(let c of Array.from(i)){let d=o[c],h=l[c],f=[Math.round(h[0]*n[0]),Math.round(h[1]*n[1]),Math.round(h[2]*n[0]),Math.round(h[3]*n[1])],m={score:d,boxRaw:h,box:f};r.push(m)}return Object.keys(s).forEach(c=>Y(s[c])),r}async function y9(e,t,a){let n={};n.res=An==null?void 0:An.execute(e,[\"Identity\"]),n.logitsRaw=Pe(n.res,[0,0,0],[1,-1,1]),n.boxesRaw=Pe(n.res,[0,0,1],[1,-1,-1]),n.logits=_e(n.logitsRaw),n.boxes=_e(n.boxesRaw);let r=await ahe(n.boxes,n.logits,t,a);return Object.keys(n).forEach(s=>Y(n[s])),r}function Er(e,t=[1,1]){let a=[e.map(o=>o[0]),e.map(o=>o[1])],n=[Math.min(...a[0]),Math.min(...a[1])],r=[Math.max(...a[0]),Math.max(...a[1])],s=[n[0],n[1],r[0]-n[0],r[1]-n[1]],i=[s[0]/t[0],s[1]/t[1],s[2]/t[0],s[3]/t[1]];return{box:s,boxRaw:i}}function b9(e,t=[1,1]){let a=[e.map(u=>u[0]),e.map(u=>u[1])],n=[Math.min(...a[0]),Math.min(...a[1])],r=[Math.max(...a[0]),Math.max(...a[1])],s=[(n[0]+r[0])/2,(n[1]+r[1])/2],i=Math.max(s[0]-n[0],s[1]-n[1],-s[0]+r[0],-s[1]+r[1]),o=[Math.trunc(s[0]-i),Math.trunc(s[1]-i),Math.trunc(2*i),Math.trunc(2*i)],l=[o[0]/t[0],o[1]/t[1],o[2]/t[0],o[3]/t[1]];return{box:o,boxRaw:l}}function l0(e,t){let a=[e[2]*t,e[3]*t];return[e[0]-(a[0]-e[2])/2,e[1]-(a[1]-e[3])/2,a[0],a[1]]}var Ba,sg=256,rg=Number.MAX_SAFE_INTEGER,nhe={landmarks:[\"ld_3d\",\"activation_segmentation\",\"activation_heatmap\",\"world_3d\",\"output_poseflag\"],detector:[]},d0=[],hs=[[0,0],[0,0],[0,0],[0,0]],v9=0,w9=e=>1-1/(1+Math.exp(e)),I9=e=>A9(e);async function S9(e){if(ne.initial&&(Ba=null),Ba)e.debug&&K(\"cached model:\",Ba.modelUrl);else{Ba=await Ee(e.body.modelPath);let t=Ba!=null&&Ba.executor?Object.values(Ba.modelSignature.inputs):void 0;sg=Array.isArray(t)?parseInt(t[0].tensorShape.dim[1].size):0}return Ba}function k9(e,t,a){var s,i;let n={};if(!((s=e==null?void 0:e.shape)!=null&&s[1])||!((i=e==null?void 0:e.shape)!=null&&i[2]))return e;let r;if(a&&(n.cropped=ge.cropAndResize(e,[a],[0],[e.shape[1],e.shape[2]])),e.shape[1]!==e.shape[2]){let o=[e.shape[2]>e.shape[1]?Math.trunc((e.shape[2]-e.shape[1])/2):0,e.shape[2]>e.shape[1]?Math.trunc((e.shape[2]-e.shape[1])/2):0],l=[e.shape[1]>e.shape[2]?Math.trunc((e.shape[1]-e.shape[2])/2):0,e.shape[1]>e.shape[2]?Math.trunc((e.shape[1]-e.shape[2])/2):0];hs=[[0,0],o,l,[0,0]],n.pad=rr(n.cropped||e,hs),n.resize=ge.resizeBilinear(n.pad,[t,t]),r=me(n.resize,ze.tf255)}else e.shape[1]!==t?(n.resize=ge.resizeBilinear(n.cropped||e,[t,t]),r=me(n.resize,ze.tf255)):r=me(n.cropped||e,ze.tf255);return Object.keys(n).forEach(o=>Y(n[o])),r}function rhe(e,t,a){for(let n of e)n.position=[Math.trunc(n.position[0]*(t[0]+hs[2][0]+hs[2][1])/t[0]-hs[2][0]),Math.trunc(n.position[1]*(t[1]+hs[1][0]+hs[1][1])/t[1]-hs[1][0]),n.position[2]],n.positionRaw=[n.position[0]/t[0],n.position[1]/t[1],2*n.position[2]/(t[0]+t[1])];if(a){let n=a[2]-a[0],r=a[3]-a[1];for(let s of e)s.positionRaw=[s.positionRaw[0]/r+a[1],s.positionRaw[1]/n+a[0],s.positionRaw[2]],s.position=[Math.trunc(s.positionRaw[0]*t[0]),Math.trunc(s.positionRaw[1]*t[1]),s.positionRaw[2]]}return e}function she(e){let t=e.find(o=>o.part===\"leftPalm\"),a=e.find(o=>o.part===\"leftWrist\"),n=e.find(o=>o.part===\"leftIndex\");t.position[2]=((a.position[2]||0)+(n.position[2]||0))/2;let r=e.find(o=>o.part===\"rightPalm\"),s=e.find(o=>o.part===\"rightWrist\"),i=e.find(o=>o.part===\"rightIndex\");r.position[2]=((s.position[2]||0)+(i.position[2]||0))/2}async function ihe(e,t,a){if(!(Ba!=null&&Ba.executor))return null;let n={};[n.ld,n.segmentation,n.heatmap,n.world,n.poseflag]=Ba==null?void 0:Ba.execute(e,nhe.landmarks);let r=(await n.poseflag.data())[0],s=await n.ld.data(),i=await n.world.data();Object.keys(n).forEach(f=>Y(n[f]));let o=[],l=5;for(let f=0;f<s.length/l;f++){let m=w9(s[l*f+3]),g=w9(s[l*f+4]),x=Math.trunc(100*m*g*r)/100,A=[s[l*f+0]/sg,s[l*f+1]/sg,s[l*f+2]+0],y=[Math.trunc(a[0]*A[0]),Math.trunc(a[1]*A[1]),A[2]],b=[i[l*f+0],i[l*f+1],i[l*f+2]+0];o.push({part:ag[f],positionRaw:A,position:y,distance:b,score:x})}if(r<(t.body.minConfidence||0))return null;she(o);let u=rhe(o,a),p=u.map(f=>f.position),c=Er(p,[a[0],a[1]]),d={};for(let[f,m]of Object.entries(ng)){let g=[];for(let x=0;x<m.length-1;x++){let A=u.find(b=>b.part===m[x]),y=u.find(b=>b.part===m[x+1]);A&&y&&g.push([A.position,y.position])}d[f]=g}return{id:0,score:Math.trunc(100*r)/100,box:c.box,boxRaw:c.boxRaw,keypoints:u,annotations:d}}async function ig(e,t){var s,i,o;let a=[e.shape[2]||0,e.shape[1]||0],n=(t.body.skipTime||0)>te()-v9,r=rg<(t.body.skipFrames||0);if(t.skipAllowed&&n&&r&&d0!==null)rg++;else{let l=[];if((i=(s=t.body)==null?void 0:s.detector)!=null&&i.enabled){let u=k9(e,224);l=await y9(u,t,a),Y(u)}else l=[{box:[0,0,0,0],boxRaw:[0,0,1,1],score:0}];for(let u=0;u<l.length;u++){let p=k9(e,256,(o=l[u])==null?void 0:o.boxRaw);d0.length=0;let c=await ihe(p,t,a);Y(p),c&&(c.id=u,d0.push(c))}v9=te(),rg=0}return d0}var bu=[{class:1,label:\"person\"},{class:2,label:\"bicycle\"},{class:3,label:\"car\"},{class:4,label:\"motorcycle\"},{class:5,label:\"airplane\"},{class:6,label:\"bus\"},{class:7,label:\"train\"},{class:8,label:\"truck\"},{class:9,label:\"boat\"},{class:10,label:\"traffic light\"},{class:11,label:\"fire hydrant\"},{class:12,label:\"stop sign\"},{class:13,label:\"parking meter\"},{class:14,label:\"bench\"},{class:15,label:\"bird\"},{class:16,label:\"cat\"},{class:17,label:\"dog\"},{class:18,label:\"horse\"},{class:19,label:\"sheep\"},{class:20,label:\"cow\"},{class:21,label:\"elephant\"},{class:22,label:\"bear\"},{class:23,label:\"zebra\"},{class:24,label:\"giraffe\"},{class:25,label:\"backpack\"},{class:26,label:\"umbrella\"},{class:27,label:\"handbag\"},{class:28,label:\"tie\"},{class:29,label:\"suitcase\"},{class:30,label:\"frisbee\"},{class:31,label:\"skis\"},{class:32,label:\"snowboard\"},{class:33,label:\"sports ball\"},{class:34,label:\"kite\"},{class:35,label:\"baseball bat\"},{class:36,label:\"baseball glove\"},{class:37,label:\"skateboard\"},{class:38,label:\"surfboard\"},{class:39,label:\"tennis racket\"},{class:40,label:\"bottle\"},{class:41,label:\"wine glass\"},{class:42,label:\"cup\"},{class:43,label:\"fork\"},{class:44,label:\"knife\"},{class:45,label:\"spoon\"},{class:46,label:\"bowl\"},{class:47,label:\"banana\"},{class:48,label:\"apple\"},{class:49,label:\"sandwich\"},{class:50,label:\"orange\"},{class:51,label:\"broccoli\"},{class:52,label:\"carrot\"},{class:53,label:\"hot dog\"},{class:54,label:\"pizza\"},{class:55,label:\"donut\"},{class:56,label:\"cake\"},{class:57,label:\"chair\"},{class:58,label:\"couch\"},{class:59,label:\"potted plant\"},{class:60,label:\"bed\"},{class:61,label:\"dining table\"},{class:62,label:\"toilet\"},{class:63,label:\"tv\"},{class:64,label:\"laptop\"},{class:65,label:\"mouse\"},{class:66,label:\"remote\"},{class:67,label:\"keyboard\"},{class:68,label:\"cell phone\"},{class:69,label:\"microwave\"},{class:70,label:\"oven\"},{class:71,label:\"toaster\"},{class:72,label:\"sink\"},{class:73,label:\"refrigerator\"},{class:74,label:\"book\"},{class:75,label:\"clock\"},{class:76,label:\"vase\"},{class:77,label:\"scissors\"},{class:78,label:\"teddy bear\"},{class:79,label:\"hair drier\"},{class:80,label:\"toothbrush\"}];var Wa,$o=0,og=[],C9=0,lg=Number.MAX_SAFE_INTEGER;async function N9(e){if(ne.initial&&(Wa=null),Wa)e.debug&&K(\"cached model:\",Wa.modelUrl);else{Wa=await Ee(e.object.modelPath);let t=Wa!=null&&Wa.executor?Object.values(Wa.modelSignature.inputs):void 0;$o=Array.isArray(t)?parseInt(t[0].tensorShape.dim[2].size):0}return Wa}async function ohe(e,t,a){if(!e)return[];let n={},r=[],s=await e.array();n.squeeze=_e(e);let i=ka(n.squeeze,6,1);n.stack=sa([i[1],i[0],i[3],i[2]],1),n.boxes=_e(n.stack),n.scores=_e(i[4]),n.classes=_e(i[5]),Y([e,...i]),n.nms=await ge.nonMaxSuppressionAsync(n.boxes,n.scores,a.object.maxDetected||0,a.object.iouThreshold,a.object.minConfidence||0);let o=await n.nms.data(),l=0;for(let u of Array.from(o)){let p=Math.trunc(100*s[0][u][4])/100,c=s[0][u][5];if(Number.isNaN(c))continue;let d=bu[c].label,[h,f]=[s[0][u][0]/$o,s[0][u][1]/$o],m=[h,f,s[0][u][2]/$o-h,s[0][u][3]/$o-f],g=[Math.trunc(m[0]*t[0]),Math.trunc(m[1]*t[1]),Math.trunc(m[2]*t[0]),Math.trunc(m[3]*t[1])];r.push({id:l++,score:p,class:c,label:d,box:g,boxRaw:m})}return Object.keys(n).forEach(u=>Y(n[u])),r}async function ug(e,t){if(!(Wa!=null&&Wa.executor))return[];let a=(t.object.skipTime||0)>te()-C9,n=lg<(t.object.skipFrames||0);return t.skipAllowed&&a&&n&&og.length>0?(lg++,og):(lg=0,new Promise(async r=>{let s=[e.shape[2]||0,e.shape[1]||0],i=ge.resizeBilinear(e,[$o,$o]),o=t.object.enabled?Wa==null?void 0:Wa.execute(i,[\"tower_0/detections\"]):null;C9=te(),Y(i);let l=await ohe(o,s,t);og=l,r(l)}))}var p0={};hr(p0,{connected:()=>pg,kpt:()=>dg});var dg=[\"head\",\"neck\",\"rightShoulder\",\"rightElbow\",\"rightWrist\",\"chest\",\"leftShoulder\",\"leftElbow\",\"leftWrist\",\"bodyCenter\",\"rightHip\",\"rightKnee\",\"rightAnkle\",\"leftHip\",\"leftKnee\",\"leftAnkle\"],pg={leftLeg:[\"leftHip\",\"leftKnee\",\"leftAnkle\"],rightLeg:[\"rightHip\",\"rightKnee\",\"rightAnkle\"],torso:[\"leftShoulder\",\"rightShoulder\",\"rightHip\",\"leftHip\",\"leftShoulder\"],leftArm:[\"leftShoulder\",\"leftElbow\",\"leftWrist\"],rightArm:[\"rightShoulder\",\"rightElbow\",\"rightWrist\"],head:[]};var Nt,R9=0,Ra={id:0,keypoints:[],box:[0,0,0,0],boxRaw:[0,0,0,0],score:0,annotations:{}},cg=Number.MAX_SAFE_INTEGER;async function M9(e){return ne.initial&&(Nt=null),Nt?e.debug&&K(\"cached model:\",Nt.modelUrl):Nt=await Ee(e.body.modelPath),Nt}async function lhe(e,t){let[a,n]=e.shape,r=J(e,[n*a]),s=pa(r,0),i=(await s.data())[0];if(i>t){let o=ar(r,0),l=su(o,a),u=(await l.data())[0],p=me(o,a),c=(await p.data())[0];return Y([r,s,o,l,p]),[u,c,i]}return Y([r,s]),[0,0,i]}async function hg(e,t){if(!(Nt!=null&&Nt.executor)||!(Nt!=null&&Nt.inputs[0].shape))return[];let a=(t.body.skipTime||0)>te()-R9,n=cg<(t.body.skipFrames||0);return t.skipAllowed&&a&&n&&Object.keys(Ra.keypoints).length>0?(cg++,[Ra]):(cg=0,new Promise(async r=>{let s=$e(()=>{var f,m;let c=ge.resizeBilinear(e,[((f=Nt==null?void 0:Nt.inputs[0].shape)==null?void 0:f[2])||0,((m=Nt==null?void 0:Nt.inputs[0].shape)==null?void 0:m[1])||0],!1),d=ae(c,ze.tf2);return fe(d,ze.tf1)}),i;if(t.body.enabled&&(i=Nt==null?void 0:Nt.execute(s)),R9=te(),Y(s),i){Ra.keypoints.length=0;let c=_e(i);Y(i);let d=Ta(c,2);Y(c);for(let h=0;h<d.length;h++){let[f,m,g]=await lhe(d[h],t.body.minConfidence);g>(t.body.minConfidence||0)&&Ra.keypoints.push({score:Math.round(100*g)/100,part:dg[h],positionRaw:[f/Nt.inputs[0].shape[2],m/Nt.inputs[0].shape[1]],position:[Math.round(e.shape[2]*f/Nt.inputs[0].shape[2]),Math.round(e.shape[1]*m/Nt.inputs[0].shape[1])]})}d.forEach(h=>Y(h))}Ra.score=Ra.keypoints.reduce((c,d)=>d.score>c?d.score:c,0);let o=Ra.keypoints.map(c=>c.position[0]),l=Ra.keypoints.map(c=>c.position[1]);Ra.box=[Math.min(...o),Math.min(...l),Math.max(...o)-Math.min(...o),Math.max(...l)-Math.min(...l)];let u=Ra.keypoints.map(c=>c.positionRaw[0]),p=Ra.keypoints.map(c=>c.positionRaw[1]);Ra.boxRaw=[Math.min(...u),Math.min(...p),Math.max(...u)-Math.min(...u),Math.max(...p)-Math.min(...p)];for(let[c,d]of Object.entries(pg)){let h=[];for(let f=0;f<d.length-1;f++){let m=Ra.keypoints.find(x=>x.part===d[f]),g=Ra.keypoints.find(x=>x.part===d[f+1]);m&&g&&m.score>(t.body.minConfidence||0)&&g.score>(t.body.minConfidence||0)&&h.push([m.position,g.position])}Ra.annotations[c]=h}r([Ra])}))}var vu=e=>[Math.abs(e.endPoint[0]-e.startPoint[0]),Math.abs(e.endPoint[1]-e.startPoint[1])],c0=e=>[e.startPoint[0]+(e.endPoint[0]-e.startPoint[0])/2,e.startPoint[1]+(e.endPoint[1]-e.startPoint[1])/2,1],h0=(e,t)=>e?[Math.trunc(Math.max(0,e.startPoint[0])),Math.trunc(Math.max(0,e.startPoint[1])),Math.trunc(Math.min(t.shape[2]||0,e.endPoint[0])-Math.max(0,e.startPoint[0])),Math.trunc(Math.min(t.shape[1]||0,e.endPoint[1])-Math.max(0,e.startPoint[1]))]:[0,0,0,0],f0=(e,t)=>e?[e.startPoint[0]/(t.shape[2]||0),e.startPoint[1]/(t.shape[1]||0),(e.endPoint[0]-e.startPoint[0])/(t.shape[2]||0),(e.endPoint[1]-e.startPoint[1])/(t.shape[1]||0)]:[0,0,0,0],F9=(e,t)=>{let a=[e.startPoint[0]*t[0],e.startPoint[1]*t[1]],n=[e.endPoint[0]*t[0],e.endPoint[1]*t[1]];return{startPoint:a,endPoint:n,landmarks:e.landmarks,confidence:e.confidence}},fg=(e,t,a)=>{let n=t.shape[1],r=t.shape[2],s=[e.startPoint[1]/n,e.startPoint[0]/r,e.endPoint[1]/n,e.endPoint[0]/r],i=ge.cropAndResize(t,[s],[0],a),o=me(i,ze.tf255);return Y(i),o},m0=(e,t)=>{let a=c0(e),n=vu(e),r=[t*n[0]/2,t*n[1]/2];return{startPoint:[a[0]-r[0],a[1]-r[1]],endPoint:[a[0]+r[0],a[1]+r[1]],landmarks:e.landmarks,confidence:e.confidence}},g0=e=>{let t=c0(e),a=vu(e),n=Math.max(...a)/2;return{startPoint:[Math.round(t[0]-n),Math.round(t[1]-n)],endPoint:[Math.round(t[0]+n),Math.round(t[1]+n)],landmarks:e.landmarks,confidence:e.confidence}},O9=e=>{let t=e.map(n=>n[0]),a=e.map(n=>n[1]);return{startPoint:[Math.min(...t),Math.min(...a)],endPoint:[Math.max(...t),Math.max(...a)],landmarks:e}},mg=[[1,0,0],[0,1,0],[0,0,1]],uhe=e=>e-2*Math.PI*Math.floor((e+Math.PI)/(2*Math.PI)),dhe=(e,t)=>uhe(Math.PI/2-Math.atan2(-(t[1]-e[1]),t[0]-e[0]));var _9=(e,t)=>[[1,0,e],[0,1,t],[0,0,1]],_o=(e,t)=>{let a=0;for(let n=0;n<e.length;n++)a+=e[n]*t[n];return a},phe=(e,t)=>{let a=[];for(let n=0;n<e.length;n++)a.push(e[n][t]);return a},P9=(e,t)=>{let a=[],n=e.length;for(let r=0;r<n;r++){a.push([]);for(let s=0;s<n;s++)a[r].push(_o(e[r],phe(t,s)))}return a},D9=(e,t)=>{let a=Math.cos(e),n=Math.sin(e),r=[[a,-n,0],[n,a,0],[0,0,1]],s=_9(t[0],t[1]),i=P9(s,r),o=_9(-t[0],-t[1]);return P9(i,o)},che=e=>{let t=[[e[0][0],e[1][0]],[e[0][1],e[1][1]]],a=[e[0][2],e[1][2]],n=[-_o(t[0],a),-_o(t[1],a)];return[t[0].concat(n[0]),t[1].concat(n[1]),[0,0,1]]},hhe=(e,t)=>[_o(e,t[0]),_o(e,t[1])];function z9(e){let t=e===192?{strides:[4],anchors:[1]}:{strides:[e/16,e/8],anchors:[2,6]},a=[];for(let n=0;n<t.strides.length;n++){let r=t.strides[n],s=Math.floor((e+r-1)/r),i=Math.floor((e+r-1)/r),o=t.anchors[n];for(let l=0;l<s;l++){let u=r*(l+.5);for(let p=0;p<i;p++){let c=r*(p+.5);for(let d=0;d<o;d++)a.push([c,u])}}}return a}function L9(e,t,a,n,r){let s=vu(t),i=e.map(h=>[s[0]/r*(h[0]-r/2),s[1]/r*(h[1]-r/2),h[2]||0]),o=a&&a!==0&&Math.abs(a)>.2,l=o?D9(a,[0,0]):mg,u=o?i.map(h=>[...hhe(h,l),h[2]]):i,p=o?che(n):mg,c=c0(t),d=[_o(c,p[0]),_o(c,p[1])];return u.map(h=>[Math.trunc(h[0]+d[0]),Math.trunc(h[1]+d[1]),Math.trunc(h[2]||0)])}function B9(e,t,a,n){let r=t.landmarks.length>=Y3.count?Y3.symmetryLine:Co.symmetryLine,s=0,i=mg,o;if(e&&ne.kernels.includes(\"rotatewithoffset\"))if(s=dhe(t.landmarks[r[0]],t.landmarks[r[1]]),s&&s!==0&&Math.abs(s)>.2){let u=c0(t),p=[u[0]/a.shape[2],u[1]/a.shape[1]],c=ge.rotateWithOffset(a,s,0,[p[0],p[1]]);i=D9(-s,u),o=fg(t,c,[n,n]),Y(c)}else o=fg(t,a,[n,n]);else o=fg(t,a,[n,n]);return[s,i,o]}var fhe=e=>{let t=e.map(n=>n[0]),a=e.map(n=>n[1]);return[Math.min(...t)+(Math.max(...t)-Math.min(...t))/2,Math.min(...a)+(Math.max(...a)-Math.min(...a))/2]},W9=(e,t)=>{let a=fhe(e),n=vu(t);return{startPoint:[a[0]-n[0]/2,a[1]-n[1]/2],endPoint:[a[0]+n[0]/2,a[1]+n[1]/2]}};var V9=6,mhe=1.4,Ln,xg=null,fs=0,wu=null,ku=()=>fs;async function U9(e){var t;return ne.initial&&(Ln=null),Ln?e.debug&&K(\"cached model:\",Ln.modelUrl):Ln=await Ee((t=e.face.detector)==null?void 0:t.modelPath),fs=Ln.executor&&Ln.inputs[0].shape?Ln.inputs[0].shape[2]:256,wu=Fe(fs,\"int32\"),xg=Kn(z9(fs)),Ln}function ghe(e){if(!xg||!wu)return fn([0,0]);let t={};t.boxStarts=Pe(e,[0,1],[-1,2]),t.centers=be(t.boxStarts,xg),t.boxSizes=Pe(e,[0,3],[-1,2]),t.boxSizesNormalized=me(t.boxSizes,wu),t.centersNormalized=me(t.centers,wu),t.halfBoxSize=me(t.boxSizesNormalized,ze.tf2),t.starts=fe(t.centersNormalized,t.halfBoxSize),t.ends=be(t.centersNormalized,t.halfBoxSize),t.startNormalized=ae(t.starts,wu),t.endNormalized=ae(t.ends,wu);let a=ru([t.startNormalized,t.endNormalized],1);return Object.keys(t).forEach(n=>Y(t[n])),a}async function G9(e,t){var o,l,u,p;if(!e||e.isDisposedInternal||e.shape.length!==4||e.shape[1]<1||e.shape[2]<1)return[];let a={};a.resized=ge.resizeBilinear(e,[fs,fs]),a.div=me(a.resized,ze.tf127),a.normalized=fe(a.div,ze.tf05);let n=Ln==null?void 0:Ln.execute(a.normalized);if(Array.isArray(n)&&n.length>2){let c=n.sort((d,h)=>d.size-h.size);a.concat384=at([c[0],c[2]],2),a.concat512=at([c[1],c[3]],2),a.concat=at([a.concat512,a.concat384],1),a.batch=_e(a.concat,[0])}else Array.isArray(n)?a.batch=_e(n[0]):a.batch=_e(n);Y(n),a.boxes=ghe(a.batch),a.logits=Pe(a.batch,[0,0],[-1,1]),a.sigmoid=Da(a.logits),a.scores=_e(a.sigmoid),a.nms=await ge.nonMaxSuppressionAsync(a.boxes,a.scores,((o=t.face.detector)==null?void 0:o.maxDetected)||0,((l=t.face.detector)==null?void 0:l.iouThreshold)||0,((u=t.face.detector)==null?void 0:u.minConfidence)||0);let r=await a.nms.array(),s=[],i=await a.scores.data();for(let c=0;c<r.length;c++){let d=i[r[c]];if(d>(((p=t.face.detector)==null?void 0:p.minConfidence)||0)){let h={};h.bbox=Pe(a.boxes,[r[c],0],[1,-1]),h.slice=Pe(a.batch,[r[c],V9-1],[1,-1]),h.squeeze=_e(h.slice),h.landmarks=J(h.squeeze,[V9,-1]);let f=await h.bbox.data(),m={startPoint:[f[0],f[1]],endPoint:[f[2],f[3]],landmarks:await h.landmarks.array(),confidence:d},g=F9(m,[(e.shape[2]||0)/fs,(e.shape[1]||0)/fs]),x=m0(g,t.face.scale||mhe),A=g0(x);s.push(A),Object.keys(h).forEach(y=>Y(h[y]))}}return Object.keys(a).forEach(c=>Y(a[c])),s}var Qa,ms=0,xhe=2.3,Ag=Rn.leftEyeLower0,yg=Rn.rightEyeLower0,Iu={leftBounds:[Ag[0],Ag[Ag.length-1]],rightBounds:[yg[0],yg[yg.length-1]]},Su={upperCenter:3,lowerCenter:4,index:71,numCoordinates:76};async function K9(e){var t,a;return ne.initial&&(Qa=null),Qa?e.debug&&K(\"cached model:\",Qa.modelUrl):Qa=await Ee((t=e.face.iris)==null?void 0:t.modelPath),ms=(Qa==null?void 0:Qa.executor)&&((a=Qa.inputs)==null?void 0:a[0].shape)?Qa.inputs[0].shape[2]:0,ms===-1&&(ms=64),Qa}function x0(e,t,a,n){for(let r=0;r<J3.length;r++){let{key:s,indices:i}=J3[r],o=Rn[`${a}${s}`];if(!n||n.includes(s))for(let l=0;l<i.length;l++){let u=i[l];e[o[l]]=[t[u][0],t[u][1],(t[u][2]+e[o[l]][2])/2]}}}var Ahe=e=>{let t=e[Iu.leftBounds[0]][2],a=e[Iu.rightBounds[0]][2];return t-a},j9=(e,t,a,n,r,s=!1)=>{let i=g0(m0(O9([e[a],e[n]]),xhe)),o=vu(i),l=ge.cropAndResize(t,[[i.startPoint[1]/r,i.startPoint[0]/r,i.endPoint[1]/r,i.endPoint[0]/r]],[0],[ms,ms]);if(s&&ne.kernels.includes(\"flipleftright\")){let u=ge.flipLeftRight(l);Y(l),l=u}return{box:i,boxSize:o,crop:l}},q9=(e,t,a,n=!1)=>{let r=[];for(let s=0;s<Su.numCoordinates;s++){let i=e[s*3],o=e[s*3+1],l=e[s*3+2];r.push([(n?1-i/ms:i/ms)*a[0]+t.startPoint[0],o/ms*a[1]+t.startPoint[1],l])}return{rawCoords:r,iris:r.slice(Su.index)}},X9=(e,t,a)=>{let n=e[Rn[`${a}EyeUpper0`][Su.upperCenter]][2],r=e[Rn[`${a}EyeLower0`][Su.lowerCenter]][2],s=(n+r)/2;return t.map((i,o)=>{let l=s;return o===2?l=n:o===4&&(l=r),[i[0],i[1],l]})};async function Z9(e,t,a){if(!(Qa!=null&&Qa.executor))return e;let{box:n,boxSize:r,crop:s}=j9(e,t,Iu.leftBounds[0],Iu.leftBounds[1],a,!0),{box:i,boxSize:o,crop:l}=j9(e,t,Iu.rightBounds[0],Iu.rightBounds[1],a,!0),u=at([s,l]);Y(s),Y(l);let p=Qa.execute(u);Y(u);let c=await p.data();Y(p);let d=c.slice(0,Su.numCoordinates*3),{rawCoords:h,iris:f}=q9(d,n,r,!0),m=c.slice(Su.numCoordinates*3),{rawCoords:g,iris:x}=q9(m,i,o,!1),A=Ahe(e);Math.abs(A)<30?(x0(e,h,\"left\",null),x0(e,g,\"right\",null)):A<1?x0(e,h,\"left\",[\"EyeUpper0\",\"EyeLower0\"]):x0(e,g,\"right\",[\"EyeUpper0\",\"EyeLower0\"]);let y=X9(e,f,\"left\"),b=X9(e,x,\"right\");return e.concat(y).concat(b)}async function J9(e,t){var s,i,o,l,u,p,c,d,h,f;let a={lips:await((i=(s=t.filter(m=>m.size===160))==null?void 0:s[0])==null?void 0:i.data()),irisL:await((l=(o=t.filter(m=>m.size===10))==null?void 0:o[0])==null?void 0:l.data()),eyeL:await((p=(u=t.filter(m=>m.size===142))==null?void 0:u[0])==null?void 0:p.data()),irisR:await((d=(c=t.filter(m=>m.size===10))==null?void 0:c[1])==null?void 0:d.data()),eyeR:await((f=(h=t.filter(m=>m.size===142))==null?void 0:h[1])==null?void 0:f.data())};for(let m of Object.values(a))if(!m)return e;let n=Eo.reduce((m,g)=>m+=e[g][2],0)/Eo.length;for(let m=0;m<a.irisL.length/2;m++)e.push([a.irisL[2*m+0],a.irisL[2*m+1],n]);let r=Ro.reduce((m,g)=>m+=e[g][2],0)/Ro.length;for(let m=0;m<a.irisR.length/2;m++)e.push([a.irisR[2*m+0],a.irisR[2*m+1],r]);for(let m=0;m<a.eyeL.length/2;m++)e[Eo[m]]=[a.eyeL[2*m+0],a.eyeL[2*m+1],e[Eo[m]][2]];for(let m=0;m<a.eyeR.length/2;m++)e[Ro[m]]=[a.eyeR[2*m+0],a.eyeR[2*m+1],e[Ro[m]][2]];for(let m=0;m<a.lips.length/2;m++)e[Ip[m]]=[a.lips[2*m+0],a.lips[2*m+1],e[Ip[m]][2]];return e}var ir={boxes:[],skipped:Number.MAX_SAFE_INTEGER,timestamp:0},wt=null,Sp=0;async function Q9(e,t){var l,u,p,c,d,h,f,m,g,x;if(!(wt!=null&&wt.executor))return[];let a=(((l=t.face.detector)==null?void 0:l.skipTime)||0)>te()-ir.timestamp,n=ir.skipped<(((u=t.face.detector)==null?void 0:u.skipFrames)||0);!t.skipAllowed||!a||!n||ir.boxes.length===0?(ir.boxes=await G9(e,t),ir.timestamp=te(),ir.skipped=0):ir.skipped++;let r=[],s=[],i=0,o=Sp;for(let A=0;A<ir.boxes.length;A++){let y=ir.boxes[A],b=0,w,S={id:i++,mesh:[],meshRaw:[],box:[0,0,0,0],boxRaw:[0,0,0,0],score:0,boxScore:0,faceScore:0,annotations:{}};if([b,w,S.tensor]=B9((p=t.face.detector)==null?void 0:p.rotation,y,e,(c=t.face.mesh)!=null&&c.enabled?Sp:ku()),t.filter.equalization){let C=S.tensor?await qh(S.tensor):void 0;Y(S.tensor),C&&(S.tensor=C)}if(S.boxScore=Math.round(100*y.confidence)/100,(d=t.face.mesh)!=null&&d.enabled)if(!wt)t.debug&&K(\"face mesh detection requested, but model is not loaded\");else{if(((h=t.face.attention)==null?void 0:h.enabled)&&!ne.kernels.includes(\"atan2\"))return t.face.attention.enabled=!1,Y(S.tensor),r;let C=wt.execute(S.tensor),_=await C.find($=>$.shape[$.shape.length-1]===1).data();if(S.faceScore=Math.round(100*_[0])/100,S.faceScore<(((f=t.face.detector)==null?void 0:f.minConfidence)||1)){if(y.confidence=S.faceScore,t.face.mesh.keepInvalid){S.box=h0(y,e),S.boxRaw=f0(y,e),S.score=S.boxScore,S.mesh=y.landmarks.map($=>[(y.startPoint[0]+y.endPoint[0])/2+(y.endPoint[0]+y.startPoint[0])*$[0]/ku(),(y.startPoint[1]+y.endPoint[1])/2+(y.endPoint[1]+y.startPoint[1])*$[1]/ku()]),S.meshRaw=S.mesh.map($=>[$[0]/(e.shape[2]||1),$[1]/(e.shape[1]||1),($[2]||0)/o]);for(let $ of Object.keys(Co))S.annotations[$]=[S.mesh[Co[$]]]}}else{let $=C.find(O=>O.shape[O.shape.length-1]===1404),M=J($,[-1,3]),I=await M.array();Y(M),(m=t.face.attention)!=null&&m.enabled?I=await J9(I,C):(g=t.face.iris)!=null&&g.enabled&&(I=await Z9(I,S.tensor,Sp)),S.mesh=L9(I,y,b,w,Sp),S.meshRaw=S.mesh.map(O=>[O[0]/(e.shape[2]||0),O[1]/(e.shape[1]||0),(O[2]||0)/o]);for(let O of Object.keys(Rn))S.annotations[O]=Rn[O].map(L=>S.mesh[L]);S.score=S.faceScore;let N={...W9(S.mesh,y),confidence:y.confidence,landmarks:y.landmarks};S.box=h0(N,e),S.boxRaw=f0(N,e),s.push(N)}Y(C)}else{S.box=h0(y,e),S.boxRaw=f0(y,e),S.score=S.boxScore,S.mesh=y.landmarks.map(C=>[(y.startPoint[0]+y.endPoint[0])/2+(y.endPoint[0]+y.startPoint[0])*C[0]/ku(),(y.startPoint[1]+y.endPoint[1])/2+(y.endPoint[1]+y.startPoint[1])*C[1]/ku()]),S.meshRaw=S.mesh.map(C=>[C[0]/(e.shape[2]||0),C[1]/(e.shape[1]||0),(C[2]||0)/o]);for(let C of Object.keys(Co))S.annotations[C]=[S.mesh[Co[C]]]}S.score>(((x=t.face.detector)==null?void 0:x.minConfidence)||1)?r.push(S):Y(S.tensor)}return ir.boxes=s,r}async function ew(e){var t,a,n,r,s,i;return ne.initial&&(wt=null),((t=e.face.attention)==null?void 0:t.enabled)&&(wt==null?void 0:wt.signature)&&Object.keys(((a=wt==null?void 0:wt.signature)==null?void 0:a.outputs)||{}).length<6&&(wt=null),wt?e.debug&&K(\"cached model:\",wt.modelUrl):(n=e.face.attention)!=null&&n.enabled?wt=await Ee(e.face.attention.modelPath):wt=await Ee((r=e.face.mesh)==null?void 0:r.modelPath),Sp=wt.executor&&((s=wt==null?void 0:wt.inputs)==null?void 0:s[0].shape)?(i=wt==null?void 0:wt.inputs)==null?void 0:i[0].shape[2]:256,wt}var tw=No,aw=kp;var bhe=[\"angry\",\"disgust\",\"fear\",\"happy\",\"sad\",\"surprise\",\"neutral\"],yn,A0=[],nw=0,rw=0,vg=Number.MAX_SAFE_INTEGER;async function sw(e){var t;return ne.initial&&(yn=null),yn?e.debug&&K(\"cached model:\",yn.modelUrl):yn=await Ee((t=e.face.emotion)==null?void 0:t.modelPath),yn}async function wg(e,t,a,n){var i,o;if(!yn)return[];let r=vg<(((i=t.face.emotion)==null?void 0:i.skipFrames)||0),s=(((o=t.face.emotion)==null?void 0:o.skipTime)||0)>te()-rw;return t.skipAllowed&&s&&r&&nw===n&&A0[a]&&A0[a].length>0?(vg++,A0[a]):(vg=0,new Promise(async l=>{var p;let u=[];if((p=t.face.emotion)!=null&&p.enabled){let c={},d=yn!=null&&yn.inputs[0].shape?yn.inputs[0].shape[2]:0;c.resize=ge.resizeBilinear(e,[d,d],!1),c.channels=ae(c.resize,ze.rgb),c.grayscale=tt(c.channels,3,!0),c.grayscaleSub=fe(c.grayscale,ze.tf05),c.grayscaleMul=ae(c.grayscaleSub,ze.tf2),c.emotion=yn==null?void 0:yn.execute(c.grayscaleMul),rw=te();let h=await c.emotion.data();for(let f=0;f<h.length;f++)h[f]>(t.face.emotion.minConfidence||0)&&u.push({score:Math.min(.99,Math.trunc(100*h[f])/100),emotion:bhe[f]});u.sort((f,m)=>m.score-f.score),Object.keys(c).forEach(f=>Y(c[f]))}A0[a]=u,nw=n,l(u)}))}var fa,gs=[],ow=0,lw=0,kg=Number.MAX_SAFE_INTEGER;async function uw(e){var t;return ne.initial&&(fa=null),fa?e.debug&&K(\"cached model:\",fa.modelUrl):fa=await Ee((t=e.face.description)==null?void 0:t.modelPath),fa}function vhe(e){let t=e.image||e.tensor||e;if(!(fa!=null&&fa.inputs[0].shape))return t;let a=ge.resizeBilinear(t,[fa.inputs[0].shape[2],fa.inputs[0].shape[1]],!1),n=ae(a,ze.tf255);return Y(a),n}async function Ig(e,t,a,n){var o,l,u,p;let r={age:0,gender:\"unknown\",genderScore:0,descriptor:[]};if(!(fa!=null&&fa.executor))return r;let s=kg<(((o=t.face.description)==null?void 0:o.skipFrames)||0),i=(((l=t.face.description)==null?void 0:l.skipTime)||0)>te()-ow;return t.skipAllowed&&s&&i&&lw===n&&((u=gs==null?void 0:gs[a])==null?void 0:u.age)>0&&((p=gs==null?void 0:gs[a])==null?void 0:p.genderScore)>0?(kg++,gs[a]):(kg=0,new Promise(async c=>{var d;if((d=t.face.description)!=null&&d.enabled){let h=vhe(e),f=fa==null?void 0:fa.execute(h);ow=te(),Y(h);let g=await f.find(E=>E.shape[1]===1).data(),x=Math.trunc(200*Math.abs(g[0]-.5))/100;x>(t.face.description.minConfidence||0)&&(r.gender=g[0]<=.5?\"female\":\"male\",r.genderScore=Math.min(.99,x));let A=ar(f.find(E=>E.shape[1]===100),1),y=(await A.data())[0];Y(A);let w=await f.find(E=>E.shape[1]===100).data();r.age=Math.round(w[y-1]>w[y+1]?10*y-100*w[y-1]:10*y+100*w[y+1])/10,(Number.isNaN(g[0])||Number.isNaN(w[0]))&&K(\"faceres error:\",{model:fa,result:f});let S=f.find(E=>E.shape[1]===1024),C=S?await S.data():[];r.descriptor=Array.from(C),f.forEach(E=>Y(E))}gs[a]=r,lw=n,c(r)}))}var Tu=.1,Sg=.5;function whe(e,t,a){let n=!1,r=a.length-1;for(let s=0;s<a.length;r=s++)a[s].y>t!=a[r].y>t&&e<(a[r].x-a[s].x)*(t-a[s].y)/(a[r].y-a[s].y)+a[s].x&&(n=!n);return n}async function pw(e){if(!e.tensor||!e.mesh||e.mesh.length<100)return e.tensor;let t=e.tensor.shape[2]||0,a=e.tensor.shape[1]||0,n=await e.tensor.buffer(),r=[];for(let i of Rn.silhouette)r.push({x:(e.mesh[i][0]-e.box[0])/e.box[2],y:(e.mesh[i][1]-e.box[1])/e.box[3]});Tu&&Tu>0&&(r=r.map(i=>({x:i.x>.5?i.x+Tu:i.x-Tu,y:i.y>.5?i.y+Tu:i.y-Tu})));for(let i=0;i<t;i++)for(let o=0;o<a;o++)whe(i/t,o/t,r)||(n.set(Sg*n.get(0,o,i,0),0,o,i,0),n.set(Sg*n.get(0,o,i,1),0,o,i,1),n.set(Sg*n.get(0,o,i,2),0,o,i,2));return n.toTensor()}var ea,y0=[],Tg=Number.MAX_SAFE_INTEGER,cw=0,hw=0;async function fw(e){var t;return ne.initial&&(ea=null),ea?e.debug&&K(\"cached model:\",ea.modelUrl):ea=await Ee((t=e.face.antispoof)==null?void 0:t.modelPath),ea}async function Cg(e,t,a,n){var i,o;if(!(ea!=null&&ea.executor))return 0;let r=(((i=t.face.antispoof)==null?void 0:i.skipTime)||0)>te()-hw,s=Tg<(((o=t.face.antispoof)==null?void 0:o.skipFrames)||0);return t.skipAllowed&&r&&s&&cw===n&&y0[a]?(Tg++,y0[a]):(Tg=0,new Promise(async l=>{let u=ge.resizeBilinear(e,[ea!=null&&ea.inputs[0].shape?ea.inputs[0].shape[2]:0,ea!=null&&ea.inputs[0].shape?ea.inputs[0].shape[1]:0],!1),p=ea==null?void 0:ea.execute(u),c=(await p.data())[0];y0[a]=Math.round(100*c)/100,cw=n,hw=te(),Y([u,p]),l(y0[a])}))}var ta,b0=[],Ng=Number.MAX_SAFE_INTEGER,gw=0,xw=0;async function Aw(e){var t;return ne.initial&&(ta=null),ta?e.debug&&K(\"cached model:\",ta.modelUrl):ta=await Ee((t=e.face.liveness)==null?void 0:t.modelPath),ta}async function Eg(e,t,a,n){var i,o;if(!(ta!=null&&ta.executor))return 0;let r=(((i=t.face.liveness)==null?void 0:i.skipTime)||0)>te()-xw,s=Ng<(((o=t.face.liveness)==null?void 0:o.skipFrames)||0);return t.skipAllowed&&r&&s&&gw===n&&b0[a]?(Ng++,b0[a]):(Ng=0,new Promise(async l=>{let u=ge.resizeBilinear(e,[ta!=null&&ta.inputs[0].shape?ta.inputs[0].shape[2]:0,ta!=null&&ta.inputs[0].shape?ta.inputs[0].shape[1]:0],!1),p=ta==null?void 0:ta.execute(u),c=(await p.data())[0];b0[a]=Math.round(100*c)/100,gw=n,xw=te(),Y([u,p]),l(b0[a])}))}var Mn,Rg=[],Ihe=[\"white\",\"black\",\"asian\",\"indian\",\"other\"],She=[15,23,28,35.5,45.5,55.5,65],bw=0,vw=0,Mg=Number.MAX_SAFE_INTEGER;async function ww(e){var t;return ne.initial&&(Mn=null),Mn?e.debug&&K(\"cached model:\",Mn.modelUrl):Mn=await Ee((t=e.face.gear)==null?void 0:t.modelPath),Mn}async function $g(e,t,a,n){var i,o;if(!Mn)return{age:0,gender:\"unknown\",genderScore:0,race:[]};let r=Mg<(((i=t.face.gear)==null?void 0:i.skipFrames)||0),s=(((o=t.face.gear)==null?void 0:o.skipTime)||0)>te()-vw;return t.skipAllowed&&s&&r&&bw===n&&Rg[a]?(Mg++,Rg[a]):(Mg=0,new Promise(async l=>{var x,A;if(!(Mn!=null&&Mn.inputs[0].shape))return;let u={},p=[[0,.1,.9,.9]];u.resize=ge.cropAndResize(e,p,[0],[Mn.inputs[0].shape[2],Mn.inputs[0].shape[1]]);let c={age:0,gender:\"unknown\",genderScore:0,race:[]};(x=t.face.gear)!=null&&x.enabled&&([u.age,u.gender,u.race]=Mn.execute(u.resize,[\"age_output\",\"gender_output\",\"race_output\"]));let d=await u.gender.data();c.gender=d[0]>d[1]?\"male\":\"female\",c.genderScore=Math.round(100*(d[0]>d[1]?d[0]:d[1]))/100;let h=await u.race.data();for(let y=0;y<h.length;y++)h[y]>(((A=t.face.gear)==null?void 0:A.minConfidence)||.2)&&c.race.push({score:Math.round(100*h[y])/100,race:Ihe[y]});c.race.sort((y,b)=>b.score-y.score);let m=Array.from(await u.age.data()).map((y,b)=>[She[b],y]).sort((y,b)=>b[1]-y[1]),g=m[0][0];for(let y=1;y<m.length;y++)g+=m[y][1]*(m[y][0]-g);c.age=Math.round(10*g)/10,Object.keys(u).forEach(y=>Y(u[y])),Rg[a]=c,bw=n,vw=te(),l(c)}))}var en,v0=[],Iw=0,Sw=0,_g=Number.MAX_SAFE_INTEGER;async function Tw(e){return ne.initial&&(en=null),en?e.debug&&K(\"cached model:\",en.modelUrl):en=await Ee(e.face.ssrnet.modelPathAge),en}async function Pg(e,t,a,n){var i,o,l,u;if(!en)return{age:0};let r=_g<(((i=t.face.ssrnet)==null?void 0:i.skipFrames)||0),s=(((o=t.face.ssrnet)==null?void 0:o.skipTime)||0)>te()-Sw;return t.skipAllowed&&r&&s&&Iw===n&&((l=v0[a])==null?void 0:l.age)&&((u=v0[a])==null?void 0:u.age)>0?(_g++,v0[a]):(_g=0,new Promise(async p=>{var h;if(!(en!=null&&en.inputs)||!en.inputs[0]||!en.inputs[0].shape)return;let c={};c.resize=ge.resizeBilinear(e,[en.inputs[0].shape[2],en.inputs[0].shape[1]],!1),c.enhance=ae(c.resize,ze.tf255);let d={age:0};if((h=t.face.ssrnet)!=null&&h.enabled&&(c.age=en.execute(c.enhance)),c.age){let f=await c.age.data();d.age=Math.trunc(10*f[0])/10}Object.keys(c).forEach(f=>Y(c[f])),v0[a]=d,Iw=n,Sw=te(),p(d)}))}var $n,w0=[],Nw=0,Ew=0,Fg=Number.MAX_SAFE_INTEGER,Og=[.2989,.587,.114];async function Rw(e){var t;return ne.initial&&($n=null),$n?e.debug&&K(\"cached model:\",$n.modelUrl):$n=await Ee((t=e.face.ssrnet)==null?void 0:t.modelPathGender),$n}async function Dg(e,t,a,n){var i,o,l,u;if(!$n)return{gender:\"unknown\",genderScore:0};let r=Fg<(((i=t.face.ssrnet)==null?void 0:i.skipFrames)||0),s=(((o=t.face.ssrnet)==null?void 0:o.skipTime)||0)>te()-Ew;return t.skipAllowed&&r&&s&&Nw===n&&((l=w0[a])==null?void 0:l.gender)&&((u=w0[a])==null?void 0:u.genderScore)>0?(Fg++,w0[a]):(Fg=0,new Promise(async p=>{var f;if(!($n!=null&&$n.inputs[0].shape))return;let c={};c.resize=ge.resizeBilinear(e,[$n.inputs[0].shape[2],$n.inputs[0].shape[1]],!1),c.enhance=$e(()=>{let[m,g,x]=ka(c.resize,3,3),A=ae(m,Og[0]),y=ae(g,Og[1]),b=ae(x,Og[2]),w=ch([A,y,b]);return ae(fe(w,ze.tf05),2)});let d={gender:\"unknown\",genderScore:0};(f=t.face.ssrnet)!=null&&f.enabled&&(c.gender=$n.execute(c.enhance));let h=await c.gender.data();d.gender=h[0]>h[1]?\"female\":\"male\",d.genderScore=h[0]>h[1]?Math.trunc(100*h[0])/100:Math.trunc(100*h[1])/100,Object.keys(c).forEach(m=>Y(c[m])),w0[a]=d,Nw=n,Ew=te(),p(d)}))}var tn,zg=[],$w=0,_w=0,Pw=Number.MAX_SAFE_INTEGER;async function Fw(e){var t;return ne.initial&&(tn=null),tn?e.debug&&K(\"cached model:\",tn.modelUrl):tn=await Ee((t=e.face.mobilefacenet)==null?void 0:t.modelPath),tn}async function Lg(e,t,a,n){var i,o;if(!(tn!=null&&tn.executor))return[];let r=Pw<(((i=t.face.mobilefacenet)==null?void 0:i.skipFrames)||0),s=(((o=t.face.mobilefacenet)==null?void 0:o.skipTime)||0)>te()-_w;return t.skipAllowed&&s&&r&&$w===n&&zg[a]?(Pw++,zg[a]):new Promise(async l=>{var p;let u=[];if(((p=t.face.mobilefacenet)==null?void 0:p.enabled)&&(tn==null?void 0:tn.inputs[0].shape)){let c={};c.crop=ge.resizeBilinear(e,[tn.inputs[0].shape[2],tn.inputs[0].shape[1]],!1),c.data=tn.execute(c.crop);let d=await c.data.data();u=Array.from(d),Object.keys(c).forEach(h=>Y(c[h]))}zg[a]=u,$w=n,_w=te(),l(u)})}var an,Bg=[],Dw=0,zw=0,Lw=Number.MAX_SAFE_INTEGER;async function Bw(e){return ne.initial&&(an=null),an?e.debug&&K(\"cached model:\",an.modelUrl):an=await Ee(e.face.insightface.modelPath),an}async function Wg(e,t,a,n){var i,o;if(!(an!=null&&an.executor))return[];let r=Lw<(((i=t.face.insightface)==null?void 0:i.skipFrames)||0),s=(((o=t.face.insightface)==null?void 0:o.skipTime)||0)>te()-zw;return t.skipAllowed&&s&&r&&Dw===n&&Bg[a]?(Lw++,Bg[a]):new Promise(async l=>{var p;let u=[];if(((p=t.face.insightface)==null?void 0:p.enabled)&&(an==null?void 0:an.inputs[0].shape)){let c={};c.crop=ge.resizeBilinear(e,[an.inputs[0].shape[2],an.inputs[0].shape[1]],!1),c.data=an.execute(c.crop);let d=await c.data.data();u=Array.from(d),Object.keys(c).forEach(h=>Y(c[h]))}Bg[a]=u,Dw=n,zw=te(),l(u)})}var The=e=>{let t=(c,d)=>Math.atan2(c[1]-d[1],c[0]-d[0]);if(!e.annotations.rightEyeIris||!e.annotations.leftEyeIris)return{bearing:0,strength:0};let a=[0,-.1],n=1,r=(e.mesh[33][2]||0)>(e.mesh[263][2]||0),s=r?e.mesh[473]:e.mesh[468],i=r?[(e.mesh[133][0]+e.mesh[33][0])/2,(e.mesh[133][1]+e.mesh[33][1])/2]:[(e.mesh[263][0]+e.mesh[362][0])/2,(e.mesh[263][1]+e.mesh[362][1])/2],o=r?[e.mesh[133][0]-e.mesh[33][0],e.mesh[23][1]-e.mesh[27][1]]:[e.mesh[263][0]-e.mesh[362][0],e.mesh[253][1]-e.mesh[257][1]],l=[(i[0]-s[0])/o[0]-a[0],n*(s[1]-i[1])/o[1]-a[1]],u=Math.sqrt(l[0]*l[0]+l[1]*l[1]);return u=Math.min(u,e.boxRaw[2]/2,e.boxRaw[3]/2),{bearing:(t([0,0],l)+Math.PI/2)%Math.PI,strength:u}},Vw=(e,t)=>{let a=m=>{let g=Math.sqrt(m[0]*m[0]+m[1]*m[1]+m[2]*m[2]);return m[0]/=g,m[1]/=g,m[2]/=g,m},n=(m,g)=>{let x=m[0]-g[0],A=m[1]-g[1],y=m[2]-g[2];return[x,A,y]},r=(m,g)=>{let x=m[1]*g[2]-m[2]*g[1],A=m[2]*g[0]-m[0]*g[2],y=m[0]*g[1]-m[1]*g[0];return[x,A,y]},s=m=>{let[g,x,A,y,b,w,S,C,E]=m,_,$,M;return y<1?y>-1?(M=Math.asin(y),$=Math.atan2(-S,g),_=Math.atan2(-w,b)):(M=-Math.PI/2,$=-Math.atan2(C,E),_=0):(M=Math.PI/2,$=Math.atan2(C,E),_=0),Number.isNaN(_)&&(_=0),Number.isNaN($)&&($=0),Number.isNaN(M)&&(M=0),{pitch:2*-_,yaw:2*-$,roll:2*-M}},i=e.meshRaw;if(!i||i.length<300)return{angle:{pitch:0,yaw:0,roll:0},matrix:[1,0,0,0,1,0,0,0,1],gaze:{bearing:0,strength:0}};let o=Math.max(e.boxRaw[2]*t[0],e.boxRaw[3]*t[1])/1.5,l=[i[10],i[152],i[234],i[454]].map(m=>[m[0]*t[0]/o,m[1]*t[1]/o,m[2]]),u=a(n(l[1],l[0])),p=a(n(l[3],l[2])),c=a(r(p,u));p=r(u,c);let d=[p[0],p[1],p[2],u[0],u[1],u[2],c[0],c[1],c[2]],h=s(d),f=i.length===478?The(e):{bearing:0,strength:0};return{angle:h,matrix:d,gaze:f}};function Uw(e,t){let a=e==null?void 0:e.annotations;if(!a)return 0;let n=Math.max(Math.abs(a.leftEyeIris[3][0]-a.leftEyeIris[1][0]),Math.abs(a.rightEyeIris[3][0]-a.rightEyeIris[1][0]))/t;return Math.round(1.17/n)/100}var Vg=async(e,t)=>{var f,m,g,x,A,y,b,w,S,C,E,_,$,M,I,N,O,L,B,G,j,U,H;let a=te(),n,r,s,i,o,l,u,p,c,d=[];e.state=\"run:face\";let h=await Q9(t,e.config);if(e.performance.face=ne.perfadd?(e.performance.face||0)+Math.trunc(te()-a):Math.trunc(te()-a),!t.shape||t.shape.length!==4)return[];if(!h)return[];for(let V=0;V<h.length;V++){if(e.analyze(\"Get Face\"),!h[V].tensor||h[V].tensor.isDisposedInternal){K(\"Face object is disposed:\",h[V].tensor);continue}if((f=e.config.face.detector)!=null&&f.mask){let he=await pw(h[V]);Y(h[V].tensor),he&&(h[V].tensor=he)}let Q=h[V].mesh&&h[V].mesh.length>200?Vw(h[V],[t.shape[2],t.shape[1]]):null;e.analyze(\"Start Emotion:\"),e.config.async?i=(m=e.config.face.emotion)!=null&&m.enabled?wg(h[V].tensor||Be([]),e.config,V,h.length):[]:(e.state=\"run:emotion\",a=te(),i=(g=e.config.face.emotion)!=null&&g.enabled?await wg(h[V].tensor||Be([]),e.config,V,h.length):[],e.performance.emotion=ne.perfadd?(e.performance.emotion||0)+Math.trunc(te()-a):Math.trunc(te()-a)),e.analyze(\"End Emotion:\"),e.analyze(\"Start AntiSpoof:\"),e.config.async?u=(x=e.config.face.antispoof)!=null&&x.enabled?Cg(h[V].tensor||Be([]),e.config,V,h.length):0:(e.state=\"run:antispoof\",a=te(),u=(A=e.config.face.antispoof)!=null&&A.enabled?await Cg(h[V].tensor||Be([]),e.config,V,h.length):0,e.performance.antispoof=ne.perfadd?(e.performance.antispoof||0)+Math.trunc(te()-a):Math.trunc(te()-a)),e.analyze(\"End AntiSpoof:\"),e.analyze(\"Start Liveness:\"),e.config.async?p=(y=e.config.face.liveness)!=null&&y.enabled?Eg(h[V].tensor||Be([]),e.config,V,h.length):0:(e.state=\"run:liveness\",a=te(),p=(b=e.config.face.liveness)!=null&&b.enabled?await Eg(h[V].tensor||Be([]),e.config,V,h.length):0,e.performance.liveness=ne.perfadd?(e.performance.antispoof||0)+Math.trunc(te()-a):Math.trunc(te()-a)),e.analyze(\"End Liveness:\"),e.analyze(\"Start GEAR:\"),e.config.async?r=(w=e.config.face.gear)!=null&&w.enabled?$g(h[V].tensor||Be([]),e.config,V,h.length):null:(e.state=\"run:gear\",a=te(),r=(S=e.config.face.gear)!=null&&S.enabled?await $g(h[V].tensor||Be([]),e.config,V,h.length):null,e.performance.gear=Math.trunc(te()-a)),e.analyze(\"End GEAR:\"),e.analyze(\"Start SSRNet:\"),e.config.async?(n=(C=e.config.face.ssrnet)!=null&&C.enabled?Pg(h[V].tensor||Be([]),e.config,V,h.length):null,s=(E=e.config.face.ssrnet)!=null&&E.enabled?Dg(h[V].tensor||Be([]),e.config,V,h.length):null):(e.state=\"run:ssrnet\",a=te(),n=(_=e.config.face.ssrnet)!=null&&_.enabled?await Pg(h[V].tensor||Be([]),e.config,V,h.length):null,s=($=e.config.face.ssrnet)!=null&&$.enabled?await Dg(h[V].tensor||Be([]),e.config,V,h.length):null,e.performance.ssrnet=Math.trunc(te()-a)),e.analyze(\"End SSRNet:\"),e.analyze(\"Start MobileFaceNet:\"),e.config.async?o=(M=e.config.face.mobilefacenet)!=null&&M.enabled?Lg(h[V].tensor||Be([]),e.config,V,h.length):null:(e.state=\"run:mobilefacenet\",a=te(),o=(I=e.config.face.mobilefacenet)!=null&&I.enabled?await Lg(h[V].tensor||Be([]),e.config,V,h.length):null,e.performance.mobilefacenet=Math.trunc(te()-a)),e.analyze(\"End MobileFaceNet:\"),e.analyze(\"Start InsightFace:\"),e.config.async?l=(N=e.config.face.insightface)!=null&&N.enabled?Wg(h[V].tensor||Be([]),e.config,V,h.length):null:(e.state=\"run:mobilefacenet\",a=te(),l=(O=e.config.face.insightface)!=null&&O.enabled?await Wg(h[V].tensor||Be([]),e.config,V,h.length):null,e.performance.mobilefacenet=Math.trunc(te()-a)),e.analyze(\"End InsightFace:\"),e.analyze(\"Start Description:\"),e.config.async?c=Ig(h[V].tensor||Be([]),e.config,V,h.length):(e.state=\"run:description\",a=te(),c=await Ig(h[V].tensor||Be([]),e.config,V,h.length),e.performance.description=ne.perfadd?(e.performance.description||0)+Math.trunc(te()-a):Math.trunc(te()-a)),e.analyze(\"End Description:\"),e.config.async&&([n,s,i,o,l,c,r,u,p]=await Promise.all([n,s,i,o,l,c,r,u,p])),e.analyze(\"Finish Face:\"),((L=e.config.face.ssrnet)==null?void 0:L.enabled)&&n&&s&&(c={...c,age:n.age,gender:s.gender,genderScore:s.genderScore}),((B=e.config.face.gear)==null?void 0:B.enabled)&&r&&(c={...c,age:r.age,gender:r.gender,genderScore:r.genderScore,race:r.race}),((G=e.config.face.mobilefacenet)==null?void 0:G.enabled)&&o&&(c.descriptor=o),((j=e.config.face.insightface)==null?void 0:j.enabled)&&l&&(c.descriptor=l);let Z=(U=e.config.face.iris)!=null&&U.enabled?Uw(h[V],t.shape[2]):0,re=(H=e.config.face.detector)!=null&&H.return?_e(h[V].tensor):null;Y(h[V].tensor),h[V].tensor&&delete h[V].tensor;let ee={...h[V],id:V};c.age&&(ee.age=c.age),c.gender&&(ee.gender=c.gender),c.genderScore&&(ee.genderScore=c.genderScore),c.descriptor&&(ee.embedding=c.descriptor),c.race&&(ee.race=c.race),i&&(ee.emotion=i),u&&(ee.real=u),p&&(ee.live=p),Z>0&&(ee.distance=Z),Q&&(ee.rotation=Q),re&&(ee.tensor=re),d.push(ee),e.analyze(\"End Face\")}return e.analyze(\"End FaceMesh:\"),e.config.async&&(e.performance.face&&delete e.performance.face,e.performance.age&&delete e.performance.age,e.performance.gender&&delete e.performance.gender,e.performance.emotion&&delete e.performance.emotion),d};var Ma={thumb:0,index:1,middle:2,ring:3,pinky:4,all:[0,1,2,3,4],nameMapping:{0:\"thumb\",1:\"index\",2:\"middle\",3:\"ring\",4:\"pinky\"},pointsMapping:{0:[[0,1],[1,2],[2,3],[3,4]],1:[[0,5],[5,6],[6,7],[7,8]],2:[[0,9],[9,10],[10,11],[11,12]],3:[[0,13],[13,14],[14,15],[15,16]],4:[[0,17],[17,18],[18,19],[19,20]]},getName:e=>Ma.nameMapping[e],getPoints:e=>Ma.pointsMapping[e]},As={none:0,half:1,full:2,nameMapping:{0:\"none\",1:\"half\",2:\"full\"},getName:e=>As.nameMapping[e]},Et={verticalUp:0,verticalDown:1,horizontalLeft:2,horizontalRight:3,diagonalUpRight:4,diagonalUpLeft:5,diagonalDownRight:6,diagonalDownLeft:7,nameMapping:{0:\"verticalUp\",1:\"verticalDown\",2:\"horizontalLeft\",3:\"horizontalRight\",4:\"diagonalUpRight\",5:\"diagonalUpLeft\",6:\"diagonalDownRight\",7:\"diagonalDownLeft\"},getName:e=>Et.nameMapping[e]},xs=class{constructor(t){ue(this,\"name\");ue(this,\"curls\");ue(this,\"directions\");ue(this,\"weights\");ue(this,\"weightsRelative\");this.name=t,this.curls={},this.directions={},this.weights=[1,1,1,1,1],this.weightsRelative=[1,1,1,1,1]}curl(t,a,n){typeof this.curls[t]==\"undefined\"&&(this.curls[t]=[]),this.curls[t].push([a,n])}direction(t,a,n){this.directions[t]||(this.directions[t]=[]),this.directions[t].push([a,n])}weight(t,a){this.weights[t]=a;let n=this.weights.reduce((r,s)=>r+s,0);this.weightsRelative=this.weights.map(r=>r*5/n)}matchAgainst(t,a){let n=0;for(let r in t){let s=t[r],i=this.curls[r];if(typeof i==\"undefined\"){n+=this.weightsRelative[r];continue}for(let[o,l]of i)if(s===o){n+=l*this.weightsRelative[r];break}}for(let r in a){let s=a[r],i=this.directions[r];if(typeof i==\"undefined\"){n+=this.weightsRelative[r];continue}for(let[o,l]of i)if(s===o){n+=l*this.weightsRelative[r];break}}return n/10}};var{thumb:Bn,index:Rr,middle:Mr,ring:Po,pinky:Fo}=Ma,{none:Wn,half:Nhe,full:Vn}=As,{verticalUp:Cu,verticalDown:zge,horizontalLeft:Ug,horizontalRight:Ehe,diagonalUpRight:Rhe,diagonalUpLeft:Nu,diagonalDownRight:Lge,diagonalDownLeft:Bge}=Et,ys=new xs(\"thumbs up\");ys.curl(Bn,Wn,1);ys.direction(Bn,Cu,1);ys.direction(Bn,Nu,.25);ys.direction(Bn,Rhe,.25);for(let e of[Ma.index,Ma.middle,Ma.ring,Ma.pinky])ys.curl(e,Vn,1),ys.direction(e,Ug,1),ys.direction(e,Ehe,1);var Wt=new xs(\"victory\");Wt.curl(Bn,Nhe,.5);Wt.curl(Bn,Wn,.5);Wt.direction(Bn,Cu,1);Wt.direction(Bn,Nu,1);Wt.curl(Rr,Wn,1);Wt.direction(Rr,Cu,.75);Wt.direction(Rr,Nu,1);Wt.curl(Mr,Wn,1);Wt.direction(Mr,Cu,1);Wt.direction(Mr,Nu,.75);Wt.curl(Po,Vn,1);Wt.direction(Po,Cu,.2);Wt.direction(Po,Nu,1);Wt.direction(Po,Ug,.2);Wt.curl(Fo,Vn,1);Wt.direction(Fo,Cu,.2);Wt.direction(Fo,Nu,1);Wt.direction(Fo,Ug,.2);Wt.weight(Rr,2);Wt.weight(Mr,2);var bs=new xs(\"point\");bs.curl(Bn,Vn,1);bs.curl(Rr,Wn,.5);bs.curl(Mr,Vn,.5);bs.curl(Po,Vn,.5);bs.curl(Fo,Vn,.5);bs.weight(Rr,2);bs.weight(Mr,2);var vs=new xs(\"middle finger\");vs.curl(Bn,Wn,1);vs.curl(Rr,Vn,.5);vs.curl(Mr,Vn,.5);vs.curl(Po,Vn,.5);vs.curl(Fo,Vn,.5);vs.weight(Rr,2);vs.weight(Mr,2);var Eu=new xs(\"open palm\");Eu.curl(Bn,Wn,.75);Eu.curl(Rr,Wn,.75);Eu.curl(Mr,Wn,.75);Eu.curl(Po,Wn,.75);Eu.curl(Fo,Wn,.75);var Gw=[ys,Wt,bs,vs,Eu];var Mhe=.7,Oo={HALF_CURL_START_LIMIT:60,NO_CURL_START_LIMIT:130,DISTANCE_VOTE_POWER:1.1,SINGLE_ANGLE_VOTE_POWER:.9,TOTAL_ANGLE_VOTE_POWER:1.6};function Hw(e,t,a,n){let r=(t-n)/(e-a),s=Math.atan(r)*180/Math.PI;return s<=0?s=-s:s>0&&(s=180-s),s}function qw(e,t){if(!e||!t)return[0,0];let a=Hw(e[0],e[1],t[0],t[1]);if(e.length===2)return a;let n=Hw(e[1],e[2],t[1],t[2]);return[a,n]}function jw(e,t=1){let a=0,n=0,r=0;return e>=75&&e<=105?a=1*t:e>=25&&e<=155?n=1*t:r=1*t,[a,n,r]}function $he(e,t,a){let n=e[0]-t[0],r=e[0]-a[0],s=t[0]-a[0],i=e[1]-t[1],o=e[1]-a[1],l=t[1]-a[1],u=e[2]-t[2],p=e[2]-a[2],c=t[2]-a[2],d=Math.sqrt(n*n+i*i+u*u),h=Math.sqrt(r*r+o*o+p*p),f=Math.sqrt(s*s+l*l+c*c),m=(f*f+d*d-h*h)/(2*f*d);m>1?m=1:m<-1&&(m=-1);let g=Math.acos(m);g=57.2958*g%180;let x;return g>Oo.NO_CURL_START_LIMIT?x=As.none:g>Oo.HALF_CURL_START_LIMIT?x=As.half:x=As.full,x}function Xw(e,t,a,n){let r;return n===Math.abs(e)?e>0?r=Et.horizontalLeft:r=Et.horizontalRight:n===Math.abs(t)?t>0?r=Et.horizontalLeft:r=Et.horizontalRight:a>0?r=Et.horizontalLeft:r=Et.horizontalRight,r}function Kw(e,t,a,n){let r;return n===Math.abs(e)?e<0?r=Et.verticalDown:r=Et.verticalUp:n===Math.abs(t)?t<0?r=Et.verticalDown:r=Et.verticalUp:a<0?r=Et.verticalDown:r=Et.verticalUp,r}function _he(e,t,a,n,r,s,i,o){let l,u=Kw(e,t,a,n),p=Xw(r,s,i,o);return u===Et.verticalUp?p===Et.horizontalLeft?l=Et.diagonalUpLeft:l=Et.diagonalUpRight:p===Et.horizontalLeft?l=Et.diagonalDownLeft:l=Et.diagonalDownRight,l}function Phe(e,t,a,n){let r=e[0]-t[0],s=e[0]-a[0],i=t[0]-a[0],o=e[1]-t[1],l=e[1]-a[1],u=t[1]-a[1],p=Math.max(Math.abs(r),Math.abs(s),Math.abs(i)),c=Math.max(Math.abs(o),Math.abs(l),Math.abs(u)),d=0,h=0,f=0,m=c/(p+1e-5);m>1.5?d+=Oo.DISTANCE_VOTE_POWER:m>.66?h+=Oo.DISTANCE_VOTE_POWER:f+=Oo.DISTANCE_VOTE_POWER;let g=Math.sqrt(r*r+o*o),x=Math.sqrt(s*s+l*l),A=Math.sqrt(i*i+u*u),y=Math.max(g,x,A),b=e[0],w=e[1],S=a[0],C=a[1];y===g?(S=a[0],C=a[1]):y===A&&(b=t[0],w=t[1]);let $=qw([b,w],[S,C]),M=jw($,Oo.TOTAL_ANGLE_VOTE_POWER);d+=M[0],h+=M[1],f+=M[2];for(let N of n){let O=jw(N,Oo.SINGLE_ANGLE_VOTE_POWER);d+=O[0],h+=O[1],f+=O[2]}let I;return d===Math.max(d,h,f)?I=Kw(l,o,u,c):f===Math.max(h,f)?I=Xw(s,r,i,p):I=_he(l,o,u,c,s,r,i,p),I}function Zw(e){let t=[],a=[],n=[],r=[];if(!e)return{curls:n,directions:r};for(let s of Ma.all){let i=Ma.getPoints(s),o=[],l=[];for(let u of i){let p=e[u[0]],c=e[u[1]],d=qw(p,c),h=d[0],f=d[1];o.push(h),l.push(f)}t.push(o),a.push(l)}for(let s of Ma.all){let i=s===Ma.thumb?1:0,o=Ma.getPoints(s),l=e[o[i][0]],u=e[o[i+1][1]],p=e[o[3][1]],c=$he(l,u,p),d=Phe(l,u,p,t[s].slice(i));n[s]=c,r[s]=d}return{curls:n,directions:r}}function k0(e){if(!e||e.length===0)return null;let t=Zw(e),a={};for(let n of Ma.all)a[Ma.getName(n)]={curl:As.getName(t.curls[n]),direction:Et.getName(t.directions[n])};return a}function Yw(e){let t=[];if(!e||e.length===0)return t;let a=Zw(e);for(let n of Gw){let r=n.matchAgainst(a.curls,a.directions);r>=Mhe&&t.push({name:n.name,confidence:r})}return t}var Jw=e=>{if(!e)return[];let t=[];for(let a=0;a<e.length;a++){let n=e[a].keypoints.find(l=>l.part===\"leftWrist\"),r=e[a].keypoints.find(l=>l.part===\"rightWrist\"),s=e[a].keypoints.find(l=>l.part===\"nose\");s&&n&&r&&n.position[1]<s.position[1]&&r.position[1]<s.position[1]?t.push({body:a,gesture:\"i give up\"}):s&&n&&n.position[1]<s.position[1]?t.push({body:a,gesture:\"raise left hand\"}):s&&r&&r.position[1]<s.position[1]&&t.push({body:a,gesture:\"raise right hand\"});let i=e[a].keypoints.find(l=>l.part===\"leftShoulder\"),o=e[a].keypoints.find(l=>l.part===\"rightShoulder\");i&&o&&Math.abs(i.positionRaw[1]-o.positionRaw[1])>.1&&t.push({body:a,gesture:`leaning ${i.position[1]>o.position[1]?\"left\":\"right\"}`})}return t},Qw=e=>{if(!e)return[];let t=[];for(let a=0;a<e.length;a++)if(e[a].mesh&&e[a].mesh.length>450){let n=(e[a].mesh[33][2]||0)-(e[a].mesh[263][2]||0),r=e[a].mesh[33][0]-e[a].mesh[263][0];Math.abs(n/r)<=.15?t.push({face:a,gesture:\"facing center\"}):t.push({face:a,gesture:`facing ${n<0?\"left\":\"right\"}`}),Math.abs(e[a].mesh[374][1]-e[a].mesh[386][1])/Math.abs(e[a].mesh[443][1]-e[a].mesh[450][1])<.2&&t.push({face:a,gesture:\"blink left eye\"}),Math.abs(e[a].mesh[145][1]-e[a].mesh[159][1])/Math.abs(e[a].mesh[223][1]-e[a].mesh[230][1])<.2&&t.push({face:a,gesture:\"blink right eye\"});let o=Math.min(100,500*Math.abs(e[a].mesh[13][1]-e[a].mesh[14][1])/Math.abs(e[a].mesh[10][1]-e[a].mesh[152][1]));o>10&&t.push({face:a,gesture:`mouth ${Math.trunc(o)}% open`});let l=e[a].mesh[152][2]||0;Math.abs(l)>10&&t.push({face:a,gesture:`head ${l<0?\"up\":\"down\"}`})}return t},ek=e=>{var a,n,r,s;if(!e)return[];let t=[];for(let i=0;i<e.length;i++){if(!((n=(a=e[i].annotations)==null?void 0:a.leftEyeIris)!=null&&n[0])||!((s=(r=e[i].annotations)==null?void 0:r.rightEyeIris)!=null&&s[0]))continue;let o=e[i].annotations.leftEyeIris[3][0]-e[i].annotations.leftEyeIris[1][0],l=e[i].annotations.leftEyeIris[4][1]-e[i].annotations.leftEyeIris[2][1],u=Math.abs(o*l),p=e[i].annotations.rightEyeIris[3][0]-e[i].annotations.rightEyeIris[1][0],c=e[i].annotations.rightEyeIris[4][1]-e[i].annotations.rightEyeIris[2][1],d=Math.abs(p*c),h=!1;Math.abs(u-d)/Math.max(u,d)<.25&&(h=!0,t.push({iris:i,gesture:\"facing center\"}));let m=Math.abs(e[i].mesh[263][0]-e[i].annotations.leftEyeIris[0][0])/e[i].box[2],g=Math.abs(e[i].mesh[33][0]-e[i].annotations.rightEyeIris[0][0])/e[i].box[2];(m>.06||g>.06)&&(h=!1),m>g?m>.05&&t.push({iris:i,gesture:\"looking right\"}):g>.05&&t.push({iris:i,gesture:\"looking left\"});let x=Math.abs(e[i].mesh[145][1]-e[i].annotations.rightEyeIris[0][1])/e[i].box[3],A=Math.abs(e[i].mesh[374][1]-e[i].annotations.leftEyeIris[0][1])/e[i].box[3];(A<.01||x<.01||A>.022||x>.022)&&(h=!1),(A<.01||x<.01)&&t.push({iris:i,gesture:\"looking down\"}),(A>.022||x>.022)&&t.push({iris:i,gesture:\"looking up\"}),h&&t.push({iris:i,gesture:\"looking center\"})}return t},tk=e=>{if(!e)return[];let t=[];for(let a=0;a<e.length;a++){let n=[];if(e[a].annotations)for(let[r,s]of Object.entries(e[a].annotations))r!==\"palmBase\"&&Array.isArray(s)&&s[0]&&n.push({name:r.toLowerCase(),position:s[0]});if(n&&n.length>0){let r=n.reduce((i,o)=>(i.position[2]||0)<(o.position[2]||0)?i:o);t.push({hand:a,gesture:`${r.name} forward`});let s=n.reduce((i,o)=>i.position[1]<o.position[1]?i:o);t.push({hand:a,gesture:`${s.name} up`})}if(e[a].keypoints){let r=Yw(e[a].keypoints);for(let s of r)t.push({hand:a,gesture:s.name})}}return t};function I0(e){return[Math.abs(e.endPoint[0]-e.startPoint[0]),Math.abs(e.endPoint[1]-e.startPoint[1])]}function Tp(e){return[e.startPoint[0]+(e.endPoint[0]-e.startPoint[0])/2,e.startPoint[1]+(e.endPoint[1]-e.startPoint[1])/2]}function rk(e,t,a){let n=t.shape[1],r=t.shape[2],s=[[e.startPoint[1]/n,e.startPoint[0]/r,e.endPoint[1]/n,e.endPoint[0]/r]];return ge.cropAndResize(t,s,[0],a)}function sk(e,t){let a=[e.startPoint[0]*t[0],e.startPoint[1]*t[1]],n=[e.endPoint[0]*t[0],e.endPoint[1]*t[1]],r=e.palmLandmarks.map(s=>[s[0]*t[0],s[1]*t[1]]);return{startPoint:a,endPoint:n,palmLandmarks:r,confidence:e.confidence}}function S0(e,t=1.5){let a=Tp(e),n=I0(e),r=[t*n[0]/2,t*n[1]/2],s=[a[0]-r[0],a[1]-r[1]],i=[a[0]+r[0],a[1]+r[1]];return{startPoint:s,endPoint:i,palmLandmarks:e.palmLandmarks}}function T0(e){let t=Tp(e),a=I0(e),r=Math.max(...a)/2,s=[t[0]-r,t[1]-r],i=[t[0]+r,t[1]+r];return{startPoint:s,endPoint:i,palmLandmarks:e.palmLandmarks}}function Ohe(e){return e-2*Math.PI*Math.floor((e+Math.PI)/(2*Math.PI))}function ik(e,t){let a=Math.PI/2-Math.atan2(-(t[1]-e[1]),t[0]-e[0]);return Ohe(a)}var ak=(e,t)=>[[1,0,e],[0,1,t],[0,0,1]];function ws(e,t){let a=0;for(let n=0;n<e.length;n++)a+=e[n]*t[n];return a}function Dhe(e,t){let a=[];for(let n=0;n<e.length;n++)a.push(e[n][t]);return a}function nk(e,t){let a=[],n=e.length;for(let r=0;r<n;r++){a.push([]);for(let s=0;s<n;s++)a[r].push(ws(e[r],Dhe(t,s)))}return a}function Hg(e,t){let a=Math.cos(e),n=Math.sin(e),r=[[a,-n,0],[n,a,0],[0,0,1]],s=ak(t[0],t[1]),i=nk(s,r),o=ak(-t[0],-t[1]);return nk(i,o)}function ok(e){let t=[[e[0][0],e[1][0]],[e[0][1],e[1][1]]],a=[e[0][2],e[1][2]],n=[-ws(t[0],a),-ws(t[1],a)];return[t[0].concat(n[0]),t[1].concat(n[1]),[0,0,1]]}function jg(e,t){return[ws(e,t[0]),ws(e,t[1])]}var uk=[{x:.015625,y:.015625},{x:.015625,y:.015625},{x:.046875,y:.015625},{x:.046875,y:.015625},{x:.078125,y:.015625},{x:.078125,y:.015625},{x:.109375,y:.015625},{x:.109375,y:.015625},{x:.140625,y:.015625},{x:.140625,y:.015625},{x:.171875,y:.015625},{x:.171875,y:.015625},{x:.203125,y:.015625},{x:.203125,y:.015625},{x:.234375,y:.015625},{x:.234375,y:.015625},{x:.265625,y:.015625},{x:.265625,y:.015625},{x:.296875,y:.015625},{x:.296875,y:.015625},{x:.328125,y:.015625},{x:.328125,y:.015625},{x:.359375,y:.015625},{x:.359375,y:.015625},{x:.390625,y:.015625},{x:.390625,y:.015625},{x:.421875,y:.015625},{x:.421875,y:.015625},{x:.453125,y:.015625},{x:.453125,y:.015625},{x:.484375,y:.015625},{x:.484375,y:.015625},{x:.515625,y:.015625},{x:.515625,y:.015625},{x:.546875,y:.015625},{x:.546875,y:.015625},{x:.578125,y:.015625},{x:.578125,y:.015625},{x:.609375,y:.015625},{x:.609375,y:.015625},{x:.640625,y:.015625},{x:.640625,y:.015625},{x:.671875,y:.015625},{x:.671875,y:.015625},{x:.703125,y:.015625},{x:.703125,y:.015625},{x:.734375,y:.015625},{x:.734375,y:.015625},{x:.765625,y:.015625},{x:.765625,y:.015625},{x:.796875,y:.015625},{x:.796875,y:.015625},{x:.828125,y:.015625},{x:.828125,y:.015625},{x:.859375,y:.015625},{x:.859375,y:.015625},{x:.890625,y:.015625},{x:.890625,y:.015625},{x:.921875,y:.015625},{x:.921875,y:.015625},{x:.953125,y:.015625},{x:.953125,y:.015625},{x:.984375,y:.015625},{x:.984375,y:.015625},{x:.015625,y:.046875},{x:.015625,y:.046875},{x:.046875,y:.046875},{x:.046875,y:.046875},{x:.078125,y:.046875},{x:.078125,y:.046875},{x:.109375,y:.046875},{x:.109375,y:.046875},{x:.140625,y:.046875},{x:.140625,y:.046875},{x:.171875,y:.046875},{x:.171875,y:.046875},{x:.203125,y:.046875},{x:.203125,y:.046875},{x:.234375,y:.046875},{x:.234375,y:.046875},{x:.265625,y:.046875},{x:.265625,y:.046875},{x:.296875,y:.046875},{x:.296875,y:.046875},{x:.328125,y:.046875},{x:.328125,y:.046875},{x:.359375,y:.046875},{x:.359375,y:.046875},{x:.390625,y:.046875},{x:.390625,y:.046875},{x:.421875,y:.046875},{x:.421875,y:.046875},{x:.453125,y:.046875},{x:.453125,y:.046875},{x:.484375,y:.046875},{x:.484375,y:.046875},{x:.515625,y:.046875},{x:.515625,y:.046875},{x:.546875,y:.046875},{x:.546875,y:.046875},{x:.578125,y:.046875},{x:.578125,y:.046875},{x:.609375,y:.046875},{x:.609375,y:.046875},{x:.640625,y:.046875},{x:.640625,y:.046875},{x:.671875,y:.046875},{x:.671875,y:.046875},{x:.703125,y:.046875},{x:.703125,y:.046875},{x:.734375,y:.046875},{x:.734375,y:.046875},{x:.765625,y:.046875},{x:.765625,y:.046875},{x:.796875,y:.046875},{x:.796875,y:.046875},{x:.828125,y:.046875},{x:.828125,y:.046875},{x:.859375,y:.046875},{x:.859375,y:.046875},{x:.890625,y:.046875},{x:.890625,y:.046875},{x:.921875,y:.046875},{x:.921875,y:.046875},{x:.953125,y:.046875},{x:.953125,y:.046875},{x:.984375,y:.046875},{x:.984375,y:.046875},{x:.015625,y:.078125},{x:.015625,y:.078125},{x:.046875,y:.078125},{x:.046875,y:.078125},{x:.078125,y:.078125},{x:.078125,y:.078125},{x:.109375,y:.078125},{x:.109375,y:.078125},{x:.140625,y:.078125},{x:.140625,y:.078125},{x:.171875,y:.078125},{x:.171875,y:.078125},{x:.203125,y:.078125},{x:.203125,y:.078125},{x:.234375,y:.078125},{x:.234375,y:.078125},{x:.265625,y:.078125},{x:.265625,y:.078125},{x:.296875,y:.078125},{x:.296875,y:.078125},{x:.328125,y:.078125},{x:.328125,y:.078125},{x:.359375,y:.078125},{x:.359375,y:.078125},{x:.390625,y:.078125},{x:.390625,y:.078125},{x:.421875,y:.078125},{x:.421875,y:.078125},{x:.453125,y:.078125},{x:.453125,y:.078125},{x:.484375,y:.078125},{x:.484375,y:.078125},{x:.515625,y:.078125},{x:.515625,y:.078125},{x:.546875,y:.078125},{x:.546875,y:.078125},{x:.578125,y:.078125},{x:.578125,y:.078125},{x:.609375,y:.078125},{x:.609375,y:.078125},{x:.640625,y:.078125},{x:.640625,y:.078125},{x:.671875,y:.078125},{x:.671875,y:.078125},{x:.703125,y:.078125},{x:.703125,y:.078125},{x:.734375,y:.078125},{x:.734375,y:.078125},{x:.765625,y:.078125},{x:.765625,y:.078125},{x:.796875,y:.078125},{x:.796875,y:.078125},{x:.828125,y:.078125},{x:.828125,y:.078125},{x:.859375,y:.078125},{x:.859375,y:.078125},{x:.890625,y:.078125},{x:.890625,y:.078125},{x:.921875,y:.078125},{x:.921875,y:.078125},{x:.953125,y:.078125},{x:.953125,y:.078125},{x:.984375,y:.078125},{x:.984375,y:.078125},{x:.015625,y:.109375},{x:.015625,y:.109375},{x:.046875,y:.109375},{x:.046875,y:.109375},{x:.078125,y:.109375},{x:.078125,y:.109375},{x:.109375,y:.109375},{x:.109375,y:.109375},{x:.140625,y:.109375},{x:.140625,y:.109375},{x:.171875,y:.109375},{x:.171875,y:.109375},{x:.203125,y:.109375},{x:.203125,y:.109375},{x:.234375,y:.109375},{x:.234375,y:.109375},{x:.265625,y:.109375},{x:.265625,y:.109375},{x:.296875,y:.109375},{x:.296875,y:.109375},{x:.328125,y:.109375},{x:.328125,y:.109375},{x:.359375,y:.109375},{x:.359375,y:.109375},{x:.390625,y:.109375},{x:.390625,y:.109375},{x:.421875,y:.109375},{x:.421875,y:.109375},{x:.453125,y:.109375},{x:.453125,y:.109375},{x:.484375,y:.109375},{x:.484375,y:.109375},{x:.515625,y:.109375},{x:.515625,y:.109375},{x:.546875,y:.109375},{x:.546875,y:.109375},{x:.578125,y:.109375},{x:.578125,y:.109375},{x:.609375,y:.109375},{x:.609375,y:.109375},{x:.640625,y:.109375},{x:.640625,y:.109375},{x:.671875,y:.109375},{x:.671875,y:.109375},{x:.703125,y:.109375},{x:.703125,y:.109375},{x:.734375,y:.109375},{x:.734375,y:.109375},{x:.765625,y:.109375},{x:.765625,y:.109375},{x:.796875,y:.109375},{x:.796875,y:.109375},{x:.828125,y:.109375},{x:.828125,y:.109375},{x:.859375,y:.109375},{x:.859375,y:.109375},{x:.890625,y:.109375},{x:.890625,y:.109375},{x:.921875,y:.109375},{x:.921875,y:.109375},{x:.953125,y:.109375},{x:.953125,y:.109375},{x:.984375,y:.109375},{x:.984375,y:.109375},{x:.015625,y:.140625},{x:.015625,y:.140625},{x:.046875,y:.140625},{x:.046875,y:.140625},{x:.078125,y:.140625},{x:.078125,y:.140625},{x:.109375,y:.140625},{x:.109375,y:.140625},{x:.140625,y:.140625},{x:.140625,y:.140625},{x:.171875,y:.140625},{x:.171875,y:.140625},{x:.203125,y:.140625},{x:.203125,y:.140625},{x:.234375,y:.140625},{x:.234375,y:.140625},{x:.265625,y:.140625},{x:.265625,y:.140625},{x:.296875,y:.140625},{x:.296875,y:.140625},{x:.328125,y:.140625},{x:.328125,y:.140625},{x:.359375,y:.140625},{x:.359375,y:.140625},{x:.390625,y:.140625},{x:.390625,y:.140625},{x:.421875,y:.140625},{x:.421875,y:.140625},{x:.453125,y:.140625},{x:.453125,y:.140625},{x:.484375,y:.140625},{x:.484375,y:.140625},{x:.515625,y:.140625},{x:.515625,y:.140625},{x:.546875,y:.140625},{x:.546875,y:.140625},{x:.578125,y:.140625},{x:.578125,y:.140625},{x:.609375,y:.140625},{x:.609375,y:.140625},{x:.640625,y:.140625},{x:.640625,y:.140625},{x:.671875,y:.140625},{x:.671875,y:.140625},{x:.703125,y:.140625},{x:.703125,y:.140625},{x:.734375,y:.140625},{x:.734375,y:.140625},{x:.765625,y:.140625},{x:.765625,y:.140625},{x:.796875,y:.140625},{x:.796875,y:.140625},{x:.828125,y:.140625},{x:.828125,y:.140625},{x:.859375,y:.140625},{x:.859375,y:.140625},{x:.890625,y:.140625},{x:.890625,y:.140625},{x:.921875,y:.140625},{x:.921875,y:.140625},{x:.953125,y:.140625},{x:.953125,y:.140625},{x:.984375,y:.140625},{x:.984375,y:.140625},{x:.015625,y:.171875},{x:.015625,y:.171875},{x:.046875,y:.171875},{x:.046875,y:.171875},{x:.078125,y:.171875},{x:.078125,y:.171875},{x:.109375,y:.171875},{x:.109375,y:.171875},{x:.140625,y:.171875},{x:.140625,y:.171875},{x:.171875,y:.171875},{x:.171875,y:.171875},{x:.203125,y:.171875},{x:.203125,y:.171875},{x:.234375,y:.171875},{x:.234375,y:.171875},{x:.265625,y:.171875},{x:.265625,y:.171875},{x:.296875,y:.171875},{x:.296875,y:.171875},{x:.328125,y:.171875},{x:.328125,y:.171875},{x:.359375,y:.171875},{x:.359375,y:.171875},{x:.390625,y:.171875},{x:.390625,y:.171875},{x:.421875,y:.171875},{x:.421875,y:.171875},{x:.453125,y:.171875},{x:.453125,y:.171875},{x:.484375,y:.171875},{x:.484375,y:.171875},{x:.515625,y:.171875},{x:.515625,y:.171875},{x:.546875,y:.171875},{x:.546875,y:.171875},{x:.578125,y:.171875},{x:.578125,y:.171875},{x:.609375,y:.171875},{x:.609375,y:.171875},{x:.640625,y:.171875},{x:.640625,y:.171875},{x:.671875,y:.171875},{x:.671875,y:.171875},{x:.703125,y:.171875},{x:.703125,y:.171875},{x:.734375,y:.171875},{x:.734375,y:.171875},{x:.765625,y:.171875},{x:.765625,y:.171875},{x:.796875,y:.171875},{x:.796875,y:.171875},{x:.828125,y:.171875},{x:.828125,y:.171875},{x:.859375,y:.171875},{x:.859375,y:.171875},{x:.890625,y:.171875},{x:.890625,y:.171875},{x:.921875,y:.171875},{x:.921875,y:.171875},{x:.953125,y:.171875},{x:.953125,y:.171875},{x:.984375,y:.171875},{x:.984375,y:.171875},{x:.015625,y:.203125},{x:.015625,y:.203125},{x:.046875,y:.203125},{x:.046875,y:.203125},{x:.078125,y:.203125},{x:.078125,y:.203125},{x:.109375,y:.203125},{x:.109375,y:.203125},{x:.140625,y:.203125},{x:.140625,y:.203125},{x:.171875,y:.203125},{x:.171875,y:.203125},{x:.203125,y:.203125},{x:.203125,y:.203125},{x:.234375,y:.203125},{x:.234375,y:.203125},{x:.265625,y:.203125},{x:.265625,y:.203125},{x:.296875,y:.203125},{x:.296875,y:.203125},{x:.328125,y:.203125},{x:.328125,y:.203125},{x:.359375,y:.203125},{x:.359375,y:.203125},{x:.390625,y:.203125},{x:.390625,y:.203125},{x:.421875,y:.203125},{x:.421875,y:.203125},{x:.453125,y:.203125},{x:.453125,y:.203125},{x:.484375,y:.203125},{x:.484375,y:.203125},{x:.515625,y:.203125},{x:.515625,y:.203125},{x:.546875,y:.203125},{x:.546875,y:.203125},{x:.578125,y:.203125},{x:.578125,y:.203125},{x:.609375,y:.203125},{x:.609375,y:.203125},{x:.640625,y:.203125},{x:.640625,y:.203125},{x:.671875,y:.203125},{x:.671875,y:.203125},{x:.703125,y:.203125},{x:.703125,y:.203125},{x:.734375,y:.203125},{x:.734375,y:.203125},{x:.765625,y:.203125},{x:.765625,y:.203125},{x:.796875,y:.203125},{x:.796875,y:.203125},{x:.828125,y:.203125},{x:.828125,y:.203125},{x:.859375,y:.203125},{x:.859375,y:.203125},{x:.890625,y:.203125},{x:.890625,y:.203125},{x:.921875,y:.203125},{x:.921875,y:.203125},{x:.953125,y:.203125},{x:.953125,y:.203125},{x:.984375,y:.203125},{x:.984375,y:.203125},{x:.015625,y:.234375},{x:.015625,y:.234375},{x:.046875,y:.234375},{x:.046875,y:.234375},{x:.078125,y:.234375},{x:.078125,y:.234375},{x:.109375,y:.234375},{x:.109375,y:.234375},{x:.140625,y:.234375},{x:.140625,y:.234375},{x:.171875,y:.234375},{x:.171875,y:.234375},{x:.203125,y:.234375},{x:.203125,y:.234375},{x:.234375,y:.234375},{x:.234375,y:.234375},{x:.265625,y:.234375},{x:.265625,y:.234375},{x:.296875,y:.234375},{x:.296875,y:.234375},{x:.328125,y:.234375},{x:.328125,y:.234375},{x:.359375,y:.234375},{x:.359375,y:.234375},{x:.390625,y:.234375},{x:.390625,y:.234375},{x:.421875,y:.234375},{x:.421875,y:.234375},{x:.453125,y:.234375},{x:.453125,y:.234375},{x:.484375,y:.234375},{x:.484375,y:.234375},{x:.515625,y:.234375},{x:.515625,y:.234375},{x:.546875,y:.234375},{x:.546875,y:.234375},{x:.578125,y:.234375},{x:.578125,y:.234375},{x:.609375,y:.234375},{x:.609375,y:.234375},{x:.640625,y:.234375},{x:.640625,y:.234375},{x:.671875,y:.234375},{x:.671875,y:.234375},{x:.703125,y:.234375},{x:.703125,y:.234375},{x:.734375,y:.234375},{x:.734375,y:.234375},{x:.765625,y:.234375},{x:.765625,y:.234375},{x:.796875,y:.234375},{x:.796875,y:.234375},{x:.828125,y:.234375},{x:.828125,y:.234375},{x:.859375,y:.234375},{x:.859375,y:.234375},{x:.890625,y:.234375},{x:.890625,y:.234375},{x:.921875,y:.234375},{x:.921875,y:.234375},{x:.953125,y:.234375},{x:.953125,y:.234375},{x:.984375,y:.234375},{x:.984375,y:.234375},{x:.015625,y:.265625},{x:.015625,y:.265625},{x:.046875,y:.265625},{x:.046875,y:.265625},{x:.078125,y:.265625},{x:.078125,y:.265625},{x:.109375,y:.265625},{x:.109375,y:.265625},{x:.140625,y:.265625},{x:.140625,y:.265625},{x:.171875,y:.265625},{x:.171875,y:.265625},{x:.203125,y:.265625},{x:.203125,y:.265625},{x:.234375,y:.265625},{x:.234375,y:.265625},{x:.265625,y:.265625},{x:.265625,y:.265625},{x:.296875,y:.265625},{x:.296875,y:.265625},{x:.328125,y:.265625},{x:.328125,y:.265625},{x:.359375,y:.265625},{x:.359375,y:.265625},{x:.390625,y:.265625},{x:.390625,y:.265625},{x:.421875,y:.265625},{x:.421875,y:.265625},{x:.453125,y:.265625},{x:.453125,y:.265625},{x:.484375,y:.265625},{x:.484375,y:.265625},{x:.515625,y:.265625},{x:.515625,y:.265625},{x:.546875,y:.265625},{x:.546875,y:.265625},{x:.578125,y:.265625},{x:.578125,y:.265625},{x:.609375,y:.265625},{x:.609375,y:.265625},{x:.640625,y:.265625},{x:.640625,y:.265625},{x:.671875,y:.265625},{x:.671875,y:.265625},{x:.703125,y:.265625},{x:.703125,y:.265625},{x:.734375,y:.265625},{x:.734375,y:.265625},{x:.765625,y:.265625},{x:.765625,y:.265625},{x:.796875,y:.265625},{x:.796875,y:.265625},{x:.828125,y:.265625},{x:.828125,y:.265625},{x:.859375,y:.265625},{x:.859375,y:.265625},{x:.890625,y:.265625},{x:.890625,y:.265625},{x:.921875,y:.265625},{x:.921875,y:.265625},{x:.953125,y:.265625},{x:.953125,y:.265625},{x:.984375,y:.265625},{x:.984375,y:.265625},{x:.015625,y:.296875},{x:.015625,y:.296875},{x:.046875,y:.296875},{x:.046875,y:.296875},{x:.078125,y:.296875},{x:.078125,y:.296875},{x:.109375,y:.296875},{x:.109375,y:.296875},{x:.140625,y:.296875},{x:.140625,y:.296875},{x:.171875,y:.296875},{x:.171875,y:.296875},{x:.203125,y:.296875},{x:.203125,y:.296875},{x:.234375,y:.296875},{x:.234375,y:.296875},{x:.265625,y:.296875},{x:.265625,y:.296875},{x:.296875,y:.296875},{x:.296875,y:.296875},{x:.328125,y:.296875},{x:.328125,y:.296875},{x:.359375,y:.296875},{x:.359375,y:.296875},{x:.390625,y:.296875},{x:.390625,y:.296875},{x:.421875,y:.296875},{x:.421875,y:.296875},{x:.453125,y:.296875},{x:.453125,y:.296875},{x:.484375,y:.296875},{x:.484375,y:.296875},{x:.515625,y:.296875},{x:.515625,y:.296875},{x:.546875,y:.296875},{x:.546875,y:.296875},{x:.578125,y:.296875},{x:.578125,y:.296875},{x:.609375,y:.296875},{x:.609375,y:.296875},{x:.640625,y:.296875},{x:.640625,y:.296875},{x:.671875,y:.296875},{x:.671875,y:.296875},{x:.703125,y:.296875},{x:.703125,y:.296875},{x:.734375,y:.296875},{x:.734375,y:.296875},{x:.765625,y:.296875},{x:.765625,y:.296875},{x:.796875,y:.296875},{x:.796875,y:.296875},{x:.828125,y:.296875},{x:.828125,y:.296875},{x:.859375,y:.296875},{x:.859375,y:.296875},{x:.890625,y:.296875},{x:.890625,y:.296875},{x:.921875,y:.296875},{x:.921875,y:.296875},{x:.953125,y:.296875},{x:.953125,y:.296875},{x:.984375,y:.296875},{x:.984375,y:.296875},{x:.015625,y:.328125},{x:.015625,y:.328125},{x:.046875,y:.328125},{x:.046875,y:.328125},{x:.078125,y:.328125},{x:.078125,y:.328125},{x:.109375,y:.328125},{x:.109375,y:.328125},{x:.140625,y:.328125},{x:.140625,y:.328125},{x:.171875,y:.328125},{x:.171875,y:.328125},{x:.203125,y:.328125},{x:.203125,y:.328125},{x:.234375,y:.328125},{x:.234375,y:.328125},{x:.265625,y:.328125},{x:.265625,y:.328125},{x:.296875,y:.328125},{x:.296875,y:.328125},{x:.328125,y:.328125},{x:.328125,y:.328125},{x:.359375,y:.328125},{x:.359375,y:.328125},{x:.390625,y:.328125},{x:.390625,y:.328125},{x:.421875,y:.328125},{x:.421875,y:.328125},{x:.453125,y:.328125},{x:.453125,y:.328125},{x:.484375,y:.328125},{x:.484375,y:.328125},{x:.515625,y:.328125},{x:.515625,y:.328125},{x:.546875,y:.328125},{x:.546875,y:.328125},{x:.578125,y:.328125},{x:.578125,y:.328125},{x:.609375,y:.328125},{x:.609375,y:.328125},{x:.640625,y:.328125},{x:.640625,y:.328125},{x:.671875,y:.328125},{x:.671875,y:.328125},{x:.703125,y:.328125},{x:.703125,y:.328125},{x:.734375,y:.328125},{x:.734375,y:.328125},{x:.765625,y:.328125},{x:.765625,y:.328125},{x:.796875,y:.328125},{x:.796875,y:.328125},{x:.828125,y:.328125},{x:.828125,y:.328125},{x:.859375,y:.328125},{x:.859375,y:.328125},{x:.890625,y:.328125},{x:.890625,y:.328125},{x:.921875,y:.328125},{x:.921875,y:.328125},{x:.953125,y:.328125},{x:.953125,y:.328125},{x:.984375,y:.328125},{x:.984375,y:.328125},{x:.015625,y:.359375},{x:.015625,y:.359375},{x:.046875,y:.359375},{x:.046875,y:.359375},{x:.078125,y:.359375},{x:.078125,y:.359375},{x:.109375,y:.359375},{x:.109375,y:.359375},{x:.140625,y:.359375},{x:.140625,y:.359375},{x:.171875,y:.359375},{x:.171875,y:.359375},{x:.203125,y:.359375},{x:.203125,y:.359375},{x:.234375,y:.359375},{x:.234375,y:.359375},{x:.265625,y:.359375},{x:.265625,y:.359375},{x:.296875,y:.359375},{x:.296875,y:.359375},{x:.328125,y:.359375},{x:.328125,y:.359375},{x:.359375,y:.359375},{x:.359375,y:.359375},{x:.390625,y:.359375},{x:.390625,y:.359375},{x:.421875,y:.359375},{x:.421875,y:.359375},{x:.453125,y:.359375},{x:.453125,y:.359375},{x:.484375,y:.359375},{x:.484375,y:.359375},{x:.515625,y:.359375},{x:.515625,y:.359375},{x:.546875,y:.359375},{x:.546875,y:.359375},{x:.578125,y:.359375},{x:.578125,y:.359375},{x:.609375,y:.359375},{x:.609375,y:.359375},{x:.640625,y:.359375},{x:.640625,y:.359375},{x:.671875,y:.359375},{x:.671875,y:.359375},{x:.703125,y:.359375},{x:.703125,y:.359375},{x:.734375,y:.359375},{x:.734375,y:.359375},{x:.765625,y:.359375},{x:.765625,y:.359375},{x:.796875,y:.359375},{x:.796875,y:.359375},{x:.828125,y:.359375},{x:.828125,y:.359375},{x:.859375,y:.359375},{x:.859375,y:.359375},{x:.890625,y:.359375},{x:.890625,y:.359375},{x:.921875,y:.359375},{x:.921875,y:.359375},{x:.953125,y:.359375},{x:.953125,y:.359375},{x:.984375,y:.359375},{x:.984375,y:.359375},{x:.015625,y:.390625},{x:.015625,y:.390625},{x:.046875,y:.390625},{x:.046875,y:.390625},{x:.078125,y:.390625},{x:.078125,y:.390625},{x:.109375,y:.390625},{x:.109375,y:.390625},{x:.140625,y:.390625},{x:.140625,y:.390625},{x:.171875,y:.390625},{x:.171875,y:.390625},{x:.203125,y:.390625},{x:.203125,y:.390625},{x:.234375,y:.390625},{x:.234375,y:.390625},{x:.265625,y:.390625},{x:.265625,y:.390625},{x:.296875,y:.390625},{x:.296875,y:.390625},{x:.328125,y:.390625},{x:.328125,y:.390625},{x:.359375,y:.390625},{x:.359375,y:.390625},{x:.390625,y:.390625},{x:.390625,y:.390625},{x:.421875,y:.390625},{x:.421875,y:.390625},{x:.453125,y:.390625},{x:.453125,y:.390625},{x:.484375,y:.390625},{x:.484375,y:.390625},{x:.515625,y:.390625},{x:.515625,y:.390625},{x:.546875,y:.390625},{x:.546875,y:.390625},{x:.578125,y:.390625},{x:.578125,y:.390625},{x:.609375,y:.390625},{x:.609375,y:.390625},{x:.640625,y:.390625},{x:.640625,y:.390625},{x:.671875,y:.390625},{x:.671875,y:.390625},{x:.703125,y:.390625},{x:.703125,y:.390625},{x:.734375,y:.390625},{x:.734375,y:.390625},{x:.765625,y:.390625},{x:.765625,y:.390625},{x:.796875,y:.390625},{x:.796875,y:.390625},{x:.828125,y:.390625},{x:.828125,y:.390625},{x:.859375,y:.390625},{x:.859375,y:.390625},{x:.890625,y:.390625},{x:.890625,y:.390625},{x:.921875,y:.390625},{x:.921875,y:.390625},{x:.953125,y:.390625},{x:.953125,y:.390625},{x:.984375,y:.390625},{x:.984375,y:.390625},{x:.015625,y:.421875},{x:.015625,y:.421875},{x:.046875,y:.421875},{x:.046875,y:.421875},{x:.078125,y:.421875},{x:.078125,y:.421875},{x:.109375,y:.421875},{x:.109375,y:.421875},{x:.140625,y:.421875},{x:.140625,y:.421875},{x:.171875,y:.421875},{x:.171875,y:.421875},{x:.203125,y:.421875},{x:.203125,y:.421875},{x:.234375,y:.421875},{x:.234375,y:.421875},{x:.265625,y:.421875},{x:.265625,y:.421875},{x:.296875,y:.421875},{x:.296875,y:.421875},{x:.328125,y:.421875},{x:.328125,y:.421875},{x:.359375,y:.421875},{x:.359375,y:.421875},{x:.390625,y:.421875},{x:.390625,y:.421875},{x:.421875,y:.421875},{x:.421875,y:.421875},{x:.453125,y:.421875},{x:.453125,y:.421875},{x:.484375,y:.421875},{x:.484375,y:.421875},{x:.515625,y:.421875},{x:.515625,y:.421875},{x:.546875,y:.421875},{x:.546875,y:.421875},{x:.578125,y:.421875},{x:.578125,y:.421875},{x:.609375,y:.421875},{x:.609375,y:.421875},{x:.640625,y:.421875},{x:.640625,y:.421875},{x:.671875,y:.421875},{x:.671875,y:.421875},{x:.703125,y:.421875},{x:.703125,y:.421875},{x:.734375,y:.421875},{x:.734375,y:.421875},{x:.765625,y:.421875},{x:.765625,y:.421875},{x:.796875,y:.421875},{x:.796875,y:.421875},{x:.828125,y:.421875},{x:.828125,y:.421875},{x:.859375,y:.421875},{x:.859375,y:.421875},{x:.890625,y:.421875},{x:.890625,y:.421875},{x:.921875,y:.421875},{x:.921875,y:.421875},{x:.953125,y:.421875},{x:.953125,y:.421875},{x:.984375,y:.421875},{x:.984375,y:.421875},{x:.015625,y:.453125},{x:.015625,y:.453125},{x:.046875,y:.453125},{x:.046875,y:.453125},{x:.078125,y:.453125},{x:.078125,y:.453125},{x:.109375,y:.453125},{x:.109375,y:.453125},{x:.140625,y:.453125},{x:.140625,y:.453125},{x:.171875,y:.453125},{x:.171875,y:.453125},{x:.203125,y:.453125},{x:.203125,y:.453125},{x:.234375,y:.453125},{x:.234375,y:.453125},{x:.265625,y:.453125},{x:.265625,y:.453125},{x:.296875,y:.453125},{x:.296875,y:.453125},{x:.328125,y:.453125},{x:.328125,y:.453125},{x:.359375,y:.453125},{x:.359375,y:.453125},{x:.390625,y:.453125},{x:.390625,y:.453125},{x:.421875,y:.453125},{x:.421875,y:.453125},{x:.453125,y:.453125},{x:.453125,y:.453125},{x:.484375,y:.453125},{x:.484375,y:.453125},{x:.515625,y:.453125},{x:.515625,y:.453125},{x:.546875,y:.453125},{x:.546875,y:.453125},{x:.578125,y:.453125},{x:.578125,y:.453125},{x:.609375,y:.453125},{x:.609375,y:.453125},{x:.640625,y:.453125},{x:.640625,y:.453125},{x:.671875,y:.453125},{x:.671875,y:.453125},{x:.703125,y:.453125},{x:.703125,y:.453125},{x:.734375,y:.453125},{x:.734375,y:.453125},{x:.765625,y:.453125},{x:.765625,y:.453125},{x:.796875,y:.453125},{x:.796875,y:.453125},{x:.828125,y:.453125},{x:.828125,y:.453125},{x:.859375,y:.453125},{x:.859375,y:.453125},{x:.890625,y:.453125},{x:.890625,y:.453125},{x:.921875,y:.453125},{x:.921875,y:.453125},{x:.953125,y:.453125},{x:.953125,y:.453125},{x:.984375,y:.453125},{x:.984375,y:.453125},{x:.015625,y:.484375},{x:.015625,y:.484375},{x:.046875,y:.484375},{x:.046875,y:.484375},{x:.078125,y:.484375},{x:.078125,y:.484375},{x:.109375,y:.484375},{x:.109375,y:.484375},{x:.140625,y:.484375},{x:.140625,y:.484375},{x:.171875,y:.484375},{x:.171875,y:.484375},{x:.203125,y:.484375},{x:.203125,y:.484375},{x:.234375,y:.484375},{x:.234375,y:.484375},{x:.265625,y:.484375},{x:.265625,y:.484375},{x:.296875,y:.484375},{x:.296875,y:.484375},{x:.328125,y:.484375},{x:.328125,y:.484375},{x:.359375,y:.484375},{x:.359375,y:.484375},{x:.390625,y:.484375},{x:.390625,y:.484375},{x:.421875,y:.484375},{x:.421875,y:.484375},{x:.453125,y:.484375},{x:.453125,y:.484375},{x:.484375,y:.484375},{x:.484375,y:.484375},{x:.515625,y:.484375},{x:.515625,y:.484375},{x:.546875,y:.484375},{x:.546875,y:.484375},{x:.578125,y:.484375},{x:.578125,y:.484375},{x:.609375,y:.484375},{x:.609375,y:.484375},{x:.640625,y:.484375},{x:.640625,y:.484375},{x:.671875,y:.484375},{x:.671875,y:.484375},{x:.703125,y:.484375},{x:.703125,y:.484375},{x:.734375,y:.484375},{x:.734375,y:.484375},{x:.765625,y:.484375},{x:.765625,y:.484375},{x:.796875,y:.484375},{x:.796875,y:.484375},{x:.828125,y:.484375},{x:.828125,y:.484375},{x:.859375,y:.484375},{x:.859375,y:.484375},{x:.890625,y:.484375},{x:.890625,y:.484375},{x:.921875,y:.484375},{x:.921875,y:.484375},{x:.953125,y:.484375},{x:.953125,y:.484375},{x:.984375,y:.484375},{x:.984375,y:.484375},{x:.015625,y:.515625},{x:.015625,y:.515625},{x:.046875,y:.515625},{x:.046875,y:.515625},{x:.078125,y:.515625},{x:.078125,y:.515625},{x:.109375,y:.515625},{x:.109375,y:.515625},{x:.140625,y:.515625},{x:.140625,y:.515625},{x:.171875,y:.515625},{x:.171875,y:.515625},{x:.203125,y:.515625},{x:.203125,y:.515625},{x:.234375,y:.515625},{x:.234375,y:.515625},{x:.265625,y:.515625},{x:.265625,y:.515625},{x:.296875,y:.515625},{x:.296875,y:.515625},{x:.328125,y:.515625},{x:.328125,y:.515625},{x:.359375,y:.515625},{x:.359375,y:.515625},{x:.390625,y:.515625},{x:.390625,y:.515625},{x:.421875,y:.515625},{x:.421875,y:.515625},{x:.453125,y:.515625},{x:.453125,y:.515625},{x:.484375,y:.515625},{x:.484375,y:.515625},{x:.515625,y:.515625},{x:.515625,y:.515625},{x:.546875,y:.515625},{x:.546875,y:.515625},{x:.578125,y:.515625},{x:.578125,y:.515625},{x:.609375,y:.515625},{x:.609375,y:.515625},{x:.640625,y:.515625},{x:.640625,y:.515625},{x:.671875,y:.515625},{x:.671875,y:.515625},{x:.703125,y:.515625},{x:.703125,y:.515625},{x:.734375,y:.515625},{x:.734375,y:.515625},{x:.765625,y:.515625},{x:.765625,y:.515625},{x:.796875,y:.515625},{x:.796875,y:.515625},{x:.828125,y:.515625},{x:.828125,y:.515625},{x:.859375,y:.515625},{x:.859375,y:.515625},{x:.890625,y:.515625},{x:.890625,y:.515625},{x:.921875,y:.515625},{x:.921875,y:.515625},{x:.953125,y:.515625},{x:.953125,y:.515625},{x:.984375,y:.515625},{x:.984375,y:.515625},{x:.015625,y:.546875},{x:.015625,y:.546875},{x:.046875,y:.546875},{x:.046875,y:.546875},{x:.078125,y:.546875},{x:.078125,y:.546875},{x:.109375,y:.546875},{x:.109375,y:.546875},{x:.140625,y:.546875},{x:.140625,y:.546875},{x:.171875,y:.546875},{x:.171875,y:.546875},{x:.203125,y:.546875},{x:.203125,y:.546875},{x:.234375,y:.546875},{x:.234375,y:.546875},{x:.265625,y:.546875},{x:.265625,y:.546875},{x:.296875,y:.546875},{x:.296875,y:.546875},{x:.328125,y:.546875},{x:.328125,y:.546875},{x:.359375,y:.546875},{x:.359375,y:.546875},{x:.390625,y:.546875},{x:.390625,y:.546875},{x:.421875,y:.546875},{x:.421875,y:.546875},{x:.453125,y:.546875},{x:.453125,y:.546875},{x:.484375,y:.546875},{x:.484375,y:.546875},{x:.515625,y:.546875},{x:.515625,y:.546875},{x:.546875,y:.546875},{x:.546875,y:.546875},{x:.578125,y:.546875},{x:.578125,y:.546875},{x:.609375,y:.546875},{x:.609375,y:.546875},{x:.640625,y:.546875},{x:.640625,y:.546875},{x:.671875,y:.546875},{x:.671875,y:.546875},{x:.703125,y:.546875},{x:.703125,y:.546875},{x:.734375,y:.546875},{x:.734375,y:.546875},{x:.765625,y:.546875},{x:.765625,y:.546875},{x:.796875,y:.546875},{x:.796875,y:.546875},{x:.828125,y:.546875},{x:.828125,y:.546875},{x:.859375,y:.546875},{x:.859375,y:.546875},{x:.890625,y:.546875},{x:.890625,y:.546875},{x:.921875,y:.546875},{x:.921875,y:.546875},{x:.953125,y:.546875},{x:.953125,y:.546875},{x:.984375,y:.546875},{x:.984375,y:.546875},{x:.015625,y:.578125},{x:.015625,y:.578125},{x:.046875,y:.578125},{x:.046875,y:.578125},{x:.078125,y:.578125},{x:.078125,y:.578125},{x:.109375,y:.578125},{x:.109375,y:.578125},{x:.140625,y:.578125},{x:.140625,y:.578125},{x:.171875,y:.578125},{x:.171875,y:.578125},{x:.203125,y:.578125},{x:.203125,y:.578125},{x:.234375,y:.578125},{x:.234375,y:.578125},{x:.265625,y:.578125},{x:.265625,y:.578125},{x:.296875,y:.578125},{x:.296875,y:.578125},{x:.328125,y:.578125},{x:.328125,y:.578125},{x:.359375,y:.578125},{x:.359375,y:.578125},{x:.390625,y:.578125},{x:.390625,y:.578125},{x:.421875,y:.578125},{x:.421875,y:.578125},{x:.453125,y:.578125},{x:.453125,y:.578125},{x:.484375,y:.578125},{x:.484375,y:.578125},{x:.515625,y:.578125},{x:.515625,y:.578125},{x:.546875,y:.578125},{x:.546875,y:.578125},{x:.578125,y:.578125},{x:.578125,y:.578125},{x:.609375,y:.578125},{x:.609375,y:.578125},{x:.640625,y:.578125},{x:.640625,y:.578125},{x:.671875,y:.578125},{x:.671875,y:.578125},{x:.703125,y:.578125},{x:.703125,y:.578125},{x:.734375,y:.578125},{x:.734375,y:.578125},{x:.765625,y:.578125},{x:.765625,y:.578125},{x:.796875,y:.578125},{x:.796875,y:.578125},{x:.828125,y:.578125},{x:.828125,y:.578125},{x:.859375,y:.578125},{x:.859375,y:.578125},{x:.890625,y:.578125},{x:.890625,y:.578125},{x:.921875,y:.578125},{x:.921875,y:.578125},{x:.953125,y:.578125},{x:.953125,y:.578125},{x:.984375,y:.578125},{x:.984375,y:.578125},{x:.015625,y:.609375},{x:.015625,y:.609375},{x:.046875,y:.609375},{x:.046875,y:.609375},{x:.078125,y:.609375},{x:.078125,y:.609375},{x:.109375,y:.609375},{x:.109375,y:.609375},{x:.140625,y:.609375},{x:.140625,y:.609375},{x:.171875,y:.609375},{x:.171875,y:.609375},{x:.203125,y:.609375},{x:.203125,y:.609375},{x:.234375,y:.609375},{x:.234375,y:.609375},{x:.265625,y:.609375},{x:.265625,y:.609375},{x:.296875,y:.609375},{x:.296875,y:.609375},{x:.328125,y:.609375},{x:.328125,y:.609375},{x:.359375,y:.609375},{x:.359375,y:.609375},{x:.390625,y:.609375},{x:.390625,y:.609375},{x:.421875,y:.609375},{x:.421875,y:.609375},{x:.453125,y:.609375},{x:.453125,y:.609375},{x:.484375,y:.609375},{x:.484375,y:.609375},{x:.515625,y:.609375},{x:.515625,y:.609375},{x:.546875,y:.609375},{x:.546875,y:.609375},{x:.578125,y:.609375},{x:.578125,y:.609375},{x:.609375,y:.609375},{x:.609375,y:.609375},{x:.640625,y:.609375},{x:.640625,y:.609375},{x:.671875,y:.609375},{x:.671875,y:.609375},{x:.703125,y:.609375},{x:.703125,y:.609375},{x:.734375,y:.609375},{x:.734375,y:.609375},{x:.765625,y:.609375},{x:.765625,y:.609375},{x:.796875,y:.609375},{x:.796875,y:.609375},{x:.828125,y:.609375},{x:.828125,y:.609375},{x:.859375,y:.609375},{x:.859375,y:.609375},{x:.890625,y:.609375},{x:.890625,y:.609375},{x:.921875,y:.609375},{x:.921875,y:.609375},{x:.953125,y:.609375},{x:.953125,y:.609375},{x:.984375,y:.609375},{x:.984375,y:.609375},{x:.015625,y:.640625},{x:.015625,y:.640625},{x:.046875,y:.640625},{x:.046875,y:.640625},{x:.078125,y:.640625},{x:.078125,y:.640625},{x:.109375,y:.640625},{x:.109375,y:.640625},{x:.140625,y:.640625},{x:.140625,y:.640625},{x:.171875,y:.640625},{x:.171875,y:.640625},{x:.203125,y:.640625},{x:.203125,y:.640625},{x:.234375,y:.640625},{x:.234375,y:.640625},{x:.265625,y:.640625},{x:.265625,y:.640625},{x:.296875,y:.640625},{x:.296875,y:.640625},{x:.328125,y:.640625},{x:.328125,y:.640625},{x:.359375,y:.640625},{x:.359375,y:.640625},{x:.390625,y:.640625},{x:.390625,y:.640625},{x:.421875,y:.640625},{x:.421875,y:.640625},{x:.453125,y:.640625},{x:.453125,y:.640625},{x:.484375,y:.640625},{x:.484375,y:.640625},{x:.515625,y:.640625},{x:.515625,y:.640625},{x:.546875,y:.640625},{x:.546875,y:.640625},{x:.578125,y:.640625},{x:.578125,y:.640625},{x:.609375,y:.640625},{x:.609375,y:.640625},{x:.640625,y:.640625},{x:.640625,y:.640625},{x:.671875,y:.640625},{x:.671875,y:.640625},{x:.703125,y:.640625},{x:.703125,y:.640625},{x:.734375,y:.640625},{x:.734375,y:.640625},{x:.765625,y:.640625},{x:.765625,y:.640625},{x:.796875,y:.640625},{x:.796875,y:.640625},{x:.828125,y:.640625},{x:.828125,y:.640625},{x:.859375,y:.640625},{x:.859375,y:.640625},{x:.890625,y:.640625},{x:.890625,y:.640625},{x:.921875,y:.640625},{x:.921875,y:.640625},{x:.953125,y:.640625},{x:.953125,y:.640625},{x:.984375,y:.640625},{x:.984375,y:.640625},{x:.015625,y:.671875},{x:.015625,y:.671875},{x:.046875,y:.671875},{x:.046875,y:.671875},{x:.078125,y:.671875},{x:.078125,y:.671875},{x:.109375,y:.671875},{x:.109375,y:.671875},{x:.140625,y:.671875},{x:.140625,y:.671875},{x:.171875,y:.671875},{x:.171875,y:.671875},{x:.203125,y:.671875},{x:.203125,y:.671875},{x:.234375,y:.671875},{x:.234375,y:.671875},{x:.265625,y:.671875},{x:.265625,y:.671875},{x:.296875,y:.671875},{x:.296875,y:.671875},{x:.328125,y:.671875},{x:.328125,y:.671875},{x:.359375,y:.671875},{x:.359375,y:.671875},{x:.390625,y:.671875},{x:.390625,y:.671875},{x:.421875,y:.671875},{x:.421875,y:.671875},{x:.453125,y:.671875},{x:.453125,y:.671875},{x:.484375,y:.671875},{x:.484375,y:.671875},{x:.515625,y:.671875},{x:.515625,y:.671875},{x:.546875,y:.671875},{x:.546875,y:.671875},{x:.578125,y:.671875},{x:.578125,y:.671875},{x:.609375,y:.671875},{x:.609375,y:.671875},{x:.640625,y:.671875},{x:.640625,y:.671875},{x:.671875,y:.671875},{x:.671875,y:.671875},{x:.703125,y:.671875},{x:.703125,y:.671875},{x:.734375,y:.671875},{x:.734375,y:.671875},{x:.765625,y:.671875},{x:.765625,y:.671875},{x:.796875,y:.671875},{x:.796875,y:.671875},{x:.828125,y:.671875},{x:.828125,y:.671875},{x:.859375,y:.671875},{x:.859375,y:.671875},{x:.890625,y:.671875},{x:.890625,y:.671875},{x:.921875,y:.671875},{x:.921875,y:.671875},{x:.953125,y:.671875},{x:.953125,y:.671875},{x:.984375,y:.671875},{x:.984375,y:.671875},{x:.015625,y:.703125},{x:.015625,y:.703125},{x:.046875,y:.703125},{x:.046875,y:.703125},{x:.078125,y:.703125},{x:.078125,y:.703125},{x:.109375,y:.703125},{x:.109375,y:.703125},{x:.140625,y:.703125},{x:.140625,y:.703125},{x:.171875,y:.703125},{x:.171875,y:.703125},{x:.203125,y:.703125},{x:.203125,y:.703125},{x:.234375,y:.703125},{x:.234375,y:.703125},{x:.265625,y:.703125},{x:.265625,y:.703125},{x:.296875,y:.703125},{x:.296875,y:.703125},{x:.328125,y:.703125},{x:.328125,y:.703125},{x:.359375,y:.703125},{x:.359375,y:.703125},{x:.390625,y:.703125},{x:.390625,y:.703125},{x:.421875,y:.703125},{x:.421875,y:.703125},{x:.453125,y:.703125},{x:.453125,y:.703125},{x:.484375,y:.703125},{x:.484375,y:.703125},{x:.515625,y:.703125},{x:.515625,y:.703125},{x:.546875,y:.703125},{x:.546875,y:.703125},{x:.578125,y:.703125},{x:.578125,y:.703125},{x:.609375,y:.703125},{x:.609375,y:.703125},{x:.640625,y:.703125},{x:.640625,y:.703125},{x:.671875,y:.703125},{x:.671875,y:.703125},{x:.703125,y:.703125},{x:.703125,y:.703125},{x:.734375,y:.703125},{x:.734375,y:.703125},{x:.765625,y:.703125},{x:.765625,y:.703125},{x:.796875,y:.703125},{x:.796875,y:.703125},{x:.828125,y:.703125},{x:.828125,y:.703125},{x:.859375,y:.703125},{x:.859375,y:.703125},{x:.890625,y:.703125},{x:.890625,y:.703125},{x:.921875,y:.703125},{x:.921875,y:.703125},{x:.953125,y:.703125},{x:.953125,y:.703125},{x:.984375,y:.703125},{x:.984375,y:.703125},{x:.015625,y:.734375},{x:.015625,y:.734375},{x:.046875,y:.734375},{x:.046875,y:.734375},{x:.078125,y:.734375},{x:.078125,y:.734375},{x:.109375,y:.734375},{x:.109375,y:.734375},{x:.140625,y:.734375},{x:.140625,y:.734375},{x:.171875,y:.734375},{x:.171875,y:.734375},{x:.203125,y:.734375},{x:.203125,y:.734375},{x:.234375,y:.734375},{x:.234375,y:.734375},{x:.265625,y:.734375},{x:.265625,y:.734375},{x:.296875,y:.734375},{x:.296875,y:.734375},{x:.328125,y:.734375},{x:.328125,y:.734375},{x:.359375,y:.734375},{x:.359375,y:.734375},{x:.390625,y:.734375},{x:.390625,y:.734375},{x:.421875,y:.734375},{x:.421875,y:.734375},{x:.453125,y:.734375},{x:.453125,y:.734375},{x:.484375,y:.734375},{x:.484375,y:.734375},{x:.515625,y:.734375},{x:.515625,y:.734375},{x:.546875,y:.734375},{x:.546875,y:.734375},{x:.578125,y:.734375},{x:.578125,y:.734375},{x:.609375,y:.734375},{x:.609375,y:.734375},{x:.640625,y:.734375},{x:.640625,y:.734375},{x:.671875,y:.734375},{x:.671875,y:.734375},{x:.703125,y:.734375},{x:.703125,y:.734375},{x:.734375,y:.734375},{x:.734375,y:.734375},{x:.765625,y:.734375},{x:.765625,y:.734375},{x:.796875,y:.734375},{x:.796875,y:.734375},{x:.828125,y:.734375},{x:.828125,y:.734375},{x:.859375,y:.734375},{x:.859375,y:.734375},{x:.890625,y:.734375},{x:.890625,y:.734375},{x:.921875,y:.734375},{x:.921875,y:.734375},{x:.953125,y:.734375},{x:.953125,y:.734375},{x:.984375,y:.734375},{x:.984375,y:.734375},{x:.015625,y:.765625},{x:.015625,y:.765625},{x:.046875,y:.765625},{x:.046875,y:.765625},{x:.078125,y:.765625},{x:.078125,y:.765625},{x:.109375,y:.765625},{x:.109375,y:.765625},{x:.140625,y:.765625},{x:.140625,y:.765625},{x:.171875,y:.765625},{x:.171875,y:.765625},{x:.203125,y:.765625},{x:.203125,y:.765625},{x:.234375,y:.765625},{x:.234375,y:.765625},{x:.265625,y:.765625},{x:.265625,y:.765625},{x:.296875,y:.765625},{x:.296875,y:.765625},{x:.328125,y:.765625},{x:.328125,y:.765625},{x:.359375,y:.765625},{x:.359375,y:.765625},{x:.390625,y:.765625},{x:.390625,y:.765625},{x:.421875,y:.765625},{x:.421875,y:.765625},{x:.453125,y:.765625},{x:.453125,y:.765625},{x:.484375,y:.765625},{x:.484375,y:.765625},{x:.515625,y:.765625},{x:.515625,y:.765625},{x:.546875,y:.765625},{x:.546875,y:.765625},{x:.578125,y:.765625},{x:.578125,y:.765625},{x:.609375,y:.765625},{x:.609375,y:.765625},{x:.640625,y:.765625},{x:.640625,y:.765625},{x:.671875,y:.765625},{x:.671875,y:.765625},{x:.703125,y:.765625},{x:.703125,y:.765625},{x:.734375,y:.765625},{x:.734375,y:.765625},{x:.765625,y:.765625},{x:.765625,y:.765625},{x:.796875,y:.765625},{x:.796875,y:.765625},{x:.828125,y:.765625},{x:.828125,y:.765625},{x:.859375,y:.765625},{x:.859375,y:.765625},{x:.890625,y:.765625},{x:.890625,y:.765625},{x:.921875,y:.765625},{x:.921875,y:.765625},{x:.953125,y:.765625},{x:.953125,y:.765625},{x:.984375,y:.765625},{x:.984375,y:.765625},{x:.015625,y:.796875},{x:.015625,y:.796875},{x:.046875,y:.796875},{x:.046875,y:.796875},{x:.078125,y:.796875},{x:.078125,y:.796875},{x:.109375,y:.796875},{x:.109375,y:.796875},{x:.140625,y:.796875},{x:.140625,y:.796875},{x:.171875,y:.796875},{x:.171875,y:.796875},{x:.203125,y:.796875},{x:.203125,y:.796875},{x:.234375,y:.796875},{x:.234375,y:.796875},{x:.265625,y:.796875},{x:.265625,y:.796875},{x:.296875,y:.796875},{x:.296875,y:.796875},{x:.328125,y:.796875},{x:.328125,y:.796875},{x:.359375,y:.796875},{x:.359375,y:.796875},{x:.390625,y:.796875},{x:.390625,y:.796875},{x:.421875,y:.796875},{x:.421875,y:.796875},{x:.453125,y:.796875},{x:.453125,y:.796875},{x:.484375,y:.796875},{x:.484375,y:.796875},{x:.515625,y:.796875},{x:.515625,y:.796875},{x:.546875,y:.796875},{x:.546875,y:.796875},{x:.578125,y:.796875},{x:.578125,y:.796875},{x:.609375,y:.796875},{x:.609375,y:.796875},{x:.640625,y:.796875},{x:.640625,y:.796875},{x:.671875,y:.796875},{x:.671875,y:.796875},{x:.703125,y:.796875},{x:.703125,y:.796875},{x:.734375,y:.796875},{x:.734375,y:.796875},{x:.765625,y:.796875},{x:.765625,y:.796875},{x:.796875,y:.796875},{x:.796875,y:.796875},{x:.828125,y:.796875},{x:.828125,y:.796875},{x:.859375,y:.796875},{x:.859375,y:.796875},{x:.890625,y:.796875},{x:.890625,y:.796875},{x:.921875,y:.796875},{x:.921875,y:.796875},{x:.953125,y:.796875},{x:.953125,y:.796875},{x:.984375,y:.796875},{x:.984375,y:.796875},{x:.015625,y:.828125},{x:.015625,y:.828125},{x:.046875,y:.828125},{x:.046875,y:.828125},{x:.078125,y:.828125},{x:.078125,y:.828125},{x:.109375,y:.828125},{x:.109375,y:.828125},{x:.140625,y:.828125},{x:.140625,y:.828125},{x:.171875,y:.828125},{x:.171875,y:.828125},{x:.203125,y:.828125},{x:.203125,y:.828125},{x:.234375,y:.828125},{x:.234375,y:.828125},{x:.265625,y:.828125},{x:.265625,y:.828125},{x:.296875,y:.828125},{x:.296875,y:.828125},{x:.328125,y:.828125},{x:.328125,y:.828125},{x:.359375,y:.828125},{x:.359375,y:.828125},{x:.390625,y:.828125},{x:.390625,y:.828125},{x:.421875,y:.828125},{x:.421875,y:.828125},{x:.453125,y:.828125},{x:.453125,y:.828125},{x:.484375,y:.828125},{x:.484375,y:.828125},{x:.515625,y:.828125},{x:.515625,y:.828125},{x:.546875,y:.828125},{x:.546875,y:.828125},{x:.578125,y:.828125},{x:.578125,y:.828125},{x:.609375,y:.828125},{x:.609375,y:.828125},{x:.640625,y:.828125},{x:.640625,y:.828125},{x:.671875,y:.828125},{x:.671875,y:.828125},{x:.703125,y:.828125},{x:.703125,y:.828125},{x:.734375,y:.828125},{x:.734375,y:.828125},{x:.765625,y:.828125},{x:.765625,y:.828125},{x:.796875,y:.828125},{x:.796875,y:.828125},{x:.828125,y:.828125},{x:.828125,y:.828125},{x:.859375,y:.828125},{x:.859375,y:.828125},{x:.890625,y:.828125},{x:.890625,y:.828125},{x:.921875,y:.828125},{x:.921875,y:.828125},{x:.953125,y:.828125},{x:.953125,y:.828125},{x:.984375,y:.828125},{x:.984375,y:.828125},{x:.015625,y:.859375},{x:.015625,y:.859375},{x:.046875,y:.859375},{x:.046875,y:.859375},{x:.078125,y:.859375},{x:.078125,y:.859375},{x:.109375,y:.859375},{x:.109375,y:.859375},{x:.140625,y:.859375},{x:.140625,y:.859375},{x:.171875,y:.859375},{x:.171875,y:.859375},{x:.203125,y:.859375},{x:.203125,y:.859375},{x:.234375,y:.859375},{x:.234375,y:.859375},{x:.265625,y:.859375},{x:.265625,y:.859375},{x:.296875,y:.859375},{x:.296875,y:.859375},{x:.328125,y:.859375},{x:.328125,y:.859375},{x:.359375,y:.859375},{x:.359375,y:.859375},{x:.390625,y:.859375},{x:.390625,y:.859375},{x:.421875,y:.859375},{x:.421875,y:.859375},{x:.453125,y:.859375},{x:.453125,y:.859375},{x:.484375,y:.859375},{x:.484375,y:.859375},{x:.515625,y:.859375},{x:.515625,y:.859375},{x:.546875,y:.859375},{x:.546875,y:.859375},{x:.578125,y:.859375},{x:.578125,y:.859375},{x:.609375,y:.859375},{x:.609375,y:.859375},{x:.640625,y:.859375},{x:.640625,y:.859375},{x:.671875,y:.859375},{x:.671875,y:.859375},{x:.703125,y:.859375},{x:.703125,y:.859375},{x:.734375,y:.859375},{x:.734375,y:.859375},{x:.765625,y:.859375},{x:.765625,y:.859375},{x:.796875,y:.859375},{x:.796875,y:.859375},{x:.828125,y:.859375},{x:.828125,y:.859375},{x:.859375,y:.859375},{x:.859375,y:.859375},{x:.890625,y:.859375},{x:.890625,y:.859375},{x:.921875,y:.859375},{x:.921875,y:.859375},{x:.953125,y:.859375},{x:.953125,y:.859375},{x:.984375,y:.859375},{x:.984375,y:.859375},{x:.015625,y:.890625},{x:.015625,y:.890625},{x:.046875,y:.890625},{x:.046875,y:.890625},{x:.078125,y:.890625},{x:.078125,y:.890625},{x:.109375,y:.890625},{x:.109375,y:.890625},{x:.140625,y:.890625},{x:.140625,y:.890625},{x:.171875,y:.890625},{x:.171875,y:.890625},{x:.203125,y:.890625},{x:.203125,y:.890625},{x:.234375,y:.890625},{x:.234375,y:.890625},{x:.265625,y:.890625},{x:.265625,y:.890625},{x:.296875,y:.890625},{x:.296875,y:.890625},{x:.328125,y:.890625},{x:.328125,y:.890625},{x:.359375,y:.890625},{x:.359375,y:.890625},{x:.390625,y:.890625},{x:.390625,y:.890625},{x:.421875,y:.890625},{x:.421875,y:.890625},{x:.453125,y:.890625},{x:.453125,y:.890625},{x:.484375,y:.890625},{x:.484375,y:.890625},{x:.515625,y:.890625},{x:.515625,y:.890625},{x:.546875,y:.890625},{x:.546875,y:.890625},{x:.578125,y:.890625},{x:.578125,y:.890625},{x:.609375,y:.890625},{x:.609375,y:.890625},{x:.640625,y:.890625},{x:.640625,y:.890625},{x:.671875,y:.890625},{x:.671875,y:.890625},{x:.703125,y:.890625},{x:.703125,y:.890625},{x:.734375,y:.890625},{x:.734375,y:.890625},{x:.765625,y:.890625},{x:.765625,y:.890625},{x:.796875,y:.890625},{x:.796875,y:.890625},{x:.828125,y:.890625},{x:.828125,y:.890625},{x:.859375,y:.890625},{x:.859375,y:.890625},{x:.890625,y:.890625},{x:.890625,y:.890625},{x:.921875,y:.890625},{x:.921875,y:.890625},{x:.953125,y:.890625},{x:.953125,y:.890625},{x:.984375,y:.890625},{x:.984375,y:.890625},{x:.015625,y:.921875},{x:.015625,y:.921875},{x:.046875,y:.921875},{x:.046875,y:.921875},{x:.078125,y:.921875},{x:.078125,y:.921875},{x:.109375,y:.921875},{x:.109375,y:.921875},{x:.140625,y:.921875},{x:.140625,y:.921875},{x:.171875,y:.921875},{x:.171875,y:.921875},{x:.203125,y:.921875},{x:.203125,y:.921875},{x:.234375,y:.921875},{x:.234375,y:.921875},{x:.265625,y:.921875},{x:.265625,y:.921875},{x:.296875,y:.921875},{x:.296875,y:.921875},{x:.328125,y:.921875},{x:.328125,y:.921875},{x:.359375,y:.921875},{x:.359375,y:.921875},{x:.390625,y:.921875},{x:.390625,y:.921875},{x:.421875,y:.921875},{x:.421875,y:.921875},{x:.453125,y:.921875},{x:.453125,y:.921875},{x:.484375,y:.921875},{x:.484375,y:.921875},{x:.515625,y:.921875},{x:.515625,y:.921875},{x:.546875,y:.921875},{x:.546875,y:.921875},{x:.578125,y:.921875},{x:.578125,y:.921875},{x:.609375,y:.921875},{x:.609375,y:.921875},{x:.640625,y:.921875},{x:.640625,y:.921875},{x:.671875,y:.921875},{x:.671875,y:.921875},{x:.703125,y:.921875},{x:.703125,y:.921875},{x:.734375,y:.921875},{x:.734375,y:.921875},{x:.765625,y:.921875},{x:.765625,y:.921875},{x:.796875,y:.921875},{x:.796875,y:.921875},{x:.828125,y:.921875},{x:.828125,y:.921875},{x:.859375,y:.921875},{x:.859375,y:.921875},{x:.890625,y:.921875},{x:.890625,y:.921875},{x:.921875,y:.921875},{x:.921875,y:.921875},{x:.953125,y:.921875},{x:.953125,y:.921875},{x:.984375,y:.921875},{x:.984375,y:.921875},{x:.015625,y:.953125},{x:.015625,y:.953125},{x:.046875,y:.953125},{x:.046875,y:.953125},{x:.078125,y:.953125},{x:.078125,y:.953125},{x:.109375,y:.953125},{x:.109375,y:.953125},{x:.140625,y:.953125},{x:.140625,y:.953125},{x:.171875,y:.953125},{x:.171875,y:.953125},{x:.203125,y:.953125},{x:.203125,y:.953125},{x:.234375,y:.953125},{x:.234375,y:.953125},{x:.265625,y:.953125},{x:.265625,y:.953125},{x:.296875,y:.953125},{x:.296875,y:.953125},{x:.328125,y:.953125},{x:.328125,y:.953125},{x:.359375,y:.953125},{x:.359375,y:.953125},{x:.390625,y:.953125},{x:.390625,y:.953125},{x:.421875,y:.953125},{x:.421875,y:.953125},{x:.453125,y:.953125},{x:.453125,y:.953125},{x:.484375,y:.953125},{x:.484375,y:.953125},{x:.515625,y:.953125},{x:.515625,y:.953125},{x:.546875,y:.953125},{x:.546875,y:.953125},{x:.578125,y:.953125},{x:.578125,y:.953125},{x:.609375,y:.953125},{x:.609375,y:.953125},{x:.640625,y:.953125},{x:.640625,y:.953125},{x:.671875,y:.953125},{x:.671875,y:.953125},{x:.703125,y:.953125},{x:.703125,y:.953125},{x:.734375,y:.953125},{x:.734375,y:.953125},{x:.765625,y:.953125},{x:.765625,y:.953125},{x:.796875,y:.953125},{x:.796875,y:.953125},{x:.828125,y:.953125},{x:.828125,y:.953125},{x:.859375,y:.953125},{x:.859375,y:.953125},{x:.890625,y:.953125},{x:.890625,y:.953125},{x:.921875,y:.953125},{x:.921875,y:.953125},{x:.953125,y:.953125},{x:.953125,y:.953125},{x:.984375,y:.953125},{x:.984375,y:.953125},{x:.015625,y:.984375},{x:.015625,y:.984375},{x:.046875,y:.984375},{x:.046875,y:.984375},{x:.078125,y:.984375},{x:.078125,y:.984375},{x:.109375,y:.984375},{x:.109375,y:.984375},{x:.140625,y:.984375},{x:.140625,y:.984375},{x:.171875,y:.984375},{x:.171875,y:.984375},{x:.203125,y:.984375},{x:.203125,y:.984375},{x:.234375,y:.984375},{x:.234375,y:.984375},{x:.265625,y:.984375},{x:.265625,y:.984375},{x:.296875,y:.984375},{x:.296875,y:.984375},{x:.328125,y:.984375},{x:.328125,y:.984375},{x:.359375,y:.984375},{x:.359375,y:.984375},{x:.390625,y:.984375},{x:.390625,y:.984375},{x:.421875,y:.984375},{x:.421875,y:.984375},{x:.453125,y:.984375},{x:.453125,y:.984375},{x:.484375,y:.984375},{x:.484375,y:.984375},{x:.515625,y:.984375},{x:.515625,y:.984375},{x:.546875,y:.984375},{x:.546875,y:.984375},{x:.578125,y:.984375},{x:.578125,y:.984375},{x:.609375,y:.984375},{x:.609375,y:.984375},{x:.640625,y:.984375},{x:.640625,y:.984375},{x:.671875,y:.984375},{x:.671875,y:.984375},{x:.703125,y:.984375},{x:.703125,y:.984375},{x:.734375,y:.984375},{x:.734375,y:.984375},{x:.765625,y:.984375},{x:.765625,y:.984375},{x:.796875,y:.984375},{x:.796875,y:.984375},{x:.828125,y:.984375},{x:.828125,y:.984375},{x:.859375,y:.984375},{x:.859375,y:.984375},{x:.890625,y:.984375},{x:.890625,y:.984375},{x:.921875,y:.984375},{x:.921875,y:.984375},{x:.953125,y:.984375},{x:.953125,y:.984375},{x:.984375,y:.984375},{x:.984375,y:.984375},{x:.03125,y:.03125},{x:.03125,y:.03125},{x:.09375,y:.03125},{x:.09375,y:.03125},{x:.15625,y:.03125},{x:.15625,y:.03125},{x:.21875,y:.03125},{x:.21875,y:.03125},{x:.28125,y:.03125},{x:.28125,y:.03125},{x:.34375,y:.03125},{x:.34375,y:.03125},{x:.40625,y:.03125},{x:.40625,y:.03125},{x:.46875,y:.03125},{x:.46875,y:.03125},{x:.53125,y:.03125},{x:.53125,y:.03125},{x:.59375,y:.03125},{x:.59375,y:.03125},{x:.65625,y:.03125},{x:.65625,y:.03125},{x:.71875,y:.03125},{x:.71875,y:.03125},{x:.78125,y:.03125},{x:.78125,y:.03125},{x:.84375,y:.03125},{x:.84375,y:.03125},{x:.90625,y:.03125},{x:.90625,y:.03125},{x:.96875,y:.03125},{x:.96875,y:.03125},{x:.03125,y:.09375},{x:.03125,y:.09375},{x:.09375,y:.09375},{x:.09375,y:.09375},{x:.15625,y:.09375},{x:.15625,y:.09375},{x:.21875,y:.09375},{x:.21875,y:.09375},{x:.28125,y:.09375},{x:.28125,y:.09375},{x:.34375,y:.09375},{x:.34375,y:.09375},{x:.40625,y:.09375},{x:.40625,y:.09375},{x:.46875,y:.09375},{x:.46875,y:.09375},{x:.53125,y:.09375},{x:.53125,y:.09375},{x:.59375,y:.09375},{x:.59375,y:.09375},{x:.65625,y:.09375},{x:.65625,y:.09375},{x:.71875,y:.09375},{x:.71875,y:.09375},{x:.78125,y:.09375},{x:.78125,y:.09375},{x:.84375,y:.09375},{x:.84375,y:.09375},{x:.90625,y:.09375},{x:.90625,y:.09375},{x:.96875,y:.09375},{x:.96875,y:.09375},{x:.03125,y:.15625},{x:.03125,y:.15625},{x:.09375,y:.15625},{x:.09375,y:.15625},{x:.15625,y:.15625},{x:.15625,y:.15625},{x:.21875,y:.15625},{x:.21875,y:.15625},{x:.28125,y:.15625},{x:.28125,y:.15625},{x:.34375,y:.15625},{x:.34375,y:.15625},{x:.40625,y:.15625},{x:.40625,y:.15625},{x:.46875,y:.15625},{x:.46875,y:.15625},{x:.53125,y:.15625},{x:.53125,y:.15625},{x:.59375,y:.15625},{x:.59375,y:.15625},{x:.65625,y:.15625},{x:.65625,y:.15625},{x:.71875,y:.15625},{x:.71875,y:.15625},{x:.78125,y:.15625},{x:.78125,y:.15625},{x:.84375,y:.15625},{x:.84375,y:.15625},{x:.90625,y:.15625},{x:.90625,y:.15625},{x:.96875,y:.15625},{x:.96875,y:.15625},{x:.03125,y:.21875},{x:.03125,y:.21875},{x:.09375,y:.21875},{x:.09375,y:.21875},{x:.15625,y:.21875},{x:.15625,y:.21875},{x:.21875,y:.21875},{x:.21875,y:.21875},{x:.28125,y:.21875},{x:.28125,y:.21875},{x:.34375,y:.21875},{x:.34375,y:.21875},{x:.40625,y:.21875},{x:.40625,y:.21875},{x:.46875,y:.21875},{x:.46875,y:.21875},{x:.53125,y:.21875},{x:.53125,y:.21875},{x:.59375,y:.21875},{x:.59375,y:.21875},{x:.65625,y:.21875},{x:.65625,y:.21875},{x:.71875,y:.21875},{x:.71875,y:.21875},{x:.78125,y:.21875},{x:.78125,y:.21875},{x:.84375,y:.21875},{x:.84375,y:.21875},{x:.90625,y:.21875},{x:.90625,y:.21875},{x:.96875,y:.21875},{x:.96875,y:.21875},{x:.03125,y:.28125},{x:.03125,y:.28125},{x:.09375,y:.28125},{x:.09375,y:.28125},{x:.15625,y:.28125},{x:.15625,y:.28125},{x:.21875,y:.28125},{x:.21875,y:.28125},{x:.28125,y:.28125},{x:.28125,y:.28125},{x:.34375,y:.28125},{x:.34375,y:.28125},{x:.40625,y:.28125},{x:.40625,y:.28125},{x:.46875,y:.28125},{x:.46875,y:.28125},{x:.53125,y:.28125},{x:.53125,y:.28125},{x:.59375,y:.28125},{x:.59375,y:.28125},{x:.65625,y:.28125},{x:.65625,y:.28125},{x:.71875,y:.28125},{x:.71875,y:.28125},{x:.78125,y:.28125},{x:.78125,y:.28125},{x:.84375,y:.28125},{x:.84375,y:.28125},{x:.90625,y:.28125},{x:.90625,y:.28125},{x:.96875,y:.28125},{x:.96875,y:.28125},{x:.03125,y:.34375},{x:.03125,y:.34375},{x:.09375,y:.34375},{x:.09375,y:.34375},{x:.15625,y:.34375},{x:.15625,y:.34375},{x:.21875,y:.34375},{x:.21875,y:.34375},{x:.28125,y:.34375},{x:.28125,y:.34375},{x:.34375,y:.34375},{x:.34375,y:.34375},{x:.40625,y:.34375},{x:.40625,y:.34375},{x:.46875,y:.34375},{x:.46875,y:.34375},{x:.53125,y:.34375},{x:.53125,y:.34375},{x:.59375,y:.34375},{x:.59375,y:.34375},{x:.65625,y:.34375},{x:.65625,y:.34375},{x:.71875,y:.34375},{x:.71875,y:.34375},{x:.78125,y:.34375},{x:.78125,y:.34375},{x:.84375,y:.34375},{x:.84375,y:.34375},{x:.90625,y:.34375},{x:.90625,y:.34375},{x:.96875,y:.34375},{x:.96875,y:.34375},{x:.03125,y:.40625},{x:.03125,y:.40625},{x:.09375,y:.40625},{x:.09375,y:.40625},{x:.15625,y:.40625},{x:.15625,y:.40625},{x:.21875,y:.40625},{x:.21875,y:.40625},{x:.28125,y:.40625},{x:.28125,y:.40625},{x:.34375,y:.40625},{x:.34375,y:.40625},{x:.40625,y:.40625},{x:.40625,y:.40625},{x:.46875,y:.40625},{x:.46875,y:.40625},{x:.53125,y:.40625},{x:.53125,y:.40625},{x:.59375,y:.40625},{x:.59375,y:.40625},{x:.65625,y:.40625},{x:.65625,y:.40625},{x:.71875,y:.40625},{x:.71875,y:.40625},{x:.78125,y:.40625},{x:.78125,y:.40625},{x:.84375,y:.40625},{x:.84375,y:.40625},{x:.90625,y:.40625},{x:.90625,y:.40625},{x:.96875,y:.40625},{x:.96875,y:.40625},{x:.03125,y:.46875},{x:.03125,y:.46875},{x:.09375,y:.46875},{x:.09375,y:.46875},{x:.15625,y:.46875},{x:.15625,y:.46875},{x:.21875,y:.46875},{x:.21875,y:.46875},{x:.28125,y:.46875},{x:.28125,y:.46875},{x:.34375,y:.46875},{x:.34375,y:.46875},{x:.40625,y:.46875},{x:.40625,y:.46875},{x:.46875,y:.46875},{x:.46875,y:.46875},{x:.53125,y:.46875},{x:.53125,y:.46875},{x:.59375,y:.46875},{x:.59375,y:.46875},{x:.65625,y:.46875},{x:.65625,y:.46875},{x:.71875,y:.46875},{x:.71875,y:.46875},{x:.78125,y:.46875},{x:.78125,y:.46875},{x:.84375,y:.46875},{x:.84375,y:.46875},{x:.90625,y:.46875},{x:.90625,y:.46875},{x:.96875,y:.46875},{x:.96875,y:.46875},{x:.03125,y:.53125},{x:.03125,y:.53125},{x:.09375,y:.53125},{x:.09375,y:.53125},{x:.15625,y:.53125},{x:.15625,y:.53125},{x:.21875,y:.53125},{x:.21875,y:.53125},{x:.28125,y:.53125},{x:.28125,y:.53125},{x:.34375,y:.53125},{x:.34375,y:.53125},{x:.40625,y:.53125},{x:.40625,y:.53125},{x:.46875,y:.53125},{x:.46875,y:.53125},{x:.53125,y:.53125},{x:.53125,y:.53125},{x:.59375,y:.53125},{x:.59375,y:.53125},{x:.65625,y:.53125},{x:.65625,y:.53125},{x:.71875,y:.53125},{x:.71875,y:.53125},{x:.78125,y:.53125},{x:.78125,y:.53125},{x:.84375,y:.53125},{x:.84375,y:.53125},{x:.90625,y:.53125},{x:.90625,y:.53125},{x:.96875,y:.53125},{x:.96875,y:.53125},{x:.03125,y:.59375},{x:.03125,y:.59375},{x:.09375,y:.59375},{x:.09375,y:.59375},{x:.15625,y:.59375},{x:.15625,y:.59375},{x:.21875,y:.59375},{x:.21875,y:.59375},{x:.28125,y:.59375},{x:.28125,y:.59375},{x:.34375,y:.59375},{x:.34375,y:.59375},{x:.40625,y:.59375},{x:.40625,y:.59375},{x:.46875,y:.59375},{x:.46875,y:.59375},{x:.53125,y:.59375},{x:.53125,y:.59375},{x:.59375,y:.59375},{x:.59375,y:.59375},{x:.65625,y:.59375},{x:.65625,y:.59375},{x:.71875,y:.59375},{x:.71875,y:.59375},{x:.78125,y:.59375},{x:.78125,y:.59375},{x:.84375,y:.59375},{x:.84375,y:.59375},{x:.90625,y:.59375},{x:.90625,y:.59375},{x:.96875,y:.59375},{x:.96875,y:.59375},{x:.03125,y:.65625},{x:.03125,y:.65625},{x:.09375,y:.65625},{x:.09375,y:.65625},{x:.15625,y:.65625},{x:.15625,y:.65625},{x:.21875,y:.65625},{x:.21875,y:.65625},{x:.28125,y:.65625},{x:.28125,y:.65625},{x:.34375,y:.65625},{x:.34375,y:.65625},{x:.40625,y:.65625},{x:.40625,y:.65625},{x:.46875,y:.65625},{x:.46875,y:.65625},{x:.53125,y:.65625},{x:.53125,y:.65625},{x:.59375,y:.65625},{x:.59375,y:.65625},{x:.65625,y:.65625},{x:.65625,y:.65625},{x:.71875,y:.65625},{x:.71875,y:.65625},{x:.78125,y:.65625},{x:.78125,y:.65625},{x:.84375,y:.65625},{x:.84375,y:.65625},{x:.90625,y:.65625},{x:.90625,y:.65625},{x:.96875,y:.65625},{x:.96875,y:.65625},{x:.03125,y:.71875},{x:.03125,y:.71875},{x:.09375,y:.71875},{x:.09375,y:.71875},{x:.15625,y:.71875},{x:.15625,y:.71875},{x:.21875,y:.71875},{x:.21875,y:.71875},{x:.28125,y:.71875},{x:.28125,y:.71875},{x:.34375,y:.71875},{x:.34375,y:.71875},{x:.40625,y:.71875},{x:.40625,y:.71875},{x:.46875,y:.71875},{x:.46875,y:.71875},{x:.53125,y:.71875},{x:.53125,y:.71875},{x:.59375,y:.71875},{x:.59375,y:.71875},{x:.65625,y:.71875},{x:.65625,y:.71875},{x:.71875,y:.71875},{x:.71875,y:.71875},{x:.78125,y:.71875},{x:.78125,y:.71875},{x:.84375,y:.71875},{x:.84375,y:.71875},{x:.90625,y:.71875},{x:.90625,y:.71875},{x:.96875,y:.71875},{x:.96875,y:.71875},{x:.03125,y:.78125},{x:.03125,y:.78125},{x:.09375,y:.78125},{x:.09375,y:.78125},{x:.15625,y:.78125},{x:.15625,y:.78125},{x:.21875,y:.78125},{x:.21875,y:.78125},{x:.28125,y:.78125},{x:.28125,y:.78125},{x:.34375,y:.78125},{x:.34375,y:.78125},{x:.40625,y:.78125},{x:.40625,y:.78125},{x:.46875,y:.78125},{x:.46875,y:.78125},{x:.53125,y:.78125},{x:.53125,y:.78125},{x:.59375,y:.78125},{x:.59375,y:.78125},{x:.65625,y:.78125},{x:.65625,y:.78125},{x:.71875,y:.78125},{x:.71875,y:.78125},{x:.78125,y:.78125},{x:.78125,y:.78125},{x:.84375,y:.78125},{x:.84375,y:.78125},{x:.90625,y:.78125},{x:.90625,y:.78125},{x:.96875,y:.78125},{x:.96875,y:.78125},{x:.03125,y:.84375},{x:.03125,y:.84375},{x:.09375,y:.84375},{x:.09375,y:.84375},{x:.15625,y:.84375},{x:.15625,y:.84375},{x:.21875,y:.84375},{x:.21875,y:.84375},{x:.28125,y:.84375},{x:.28125,y:.84375},{x:.34375,y:.84375},{x:.34375,y:.84375},{x:.40625,y:.84375},{x:.40625,y:.84375},{x:.46875,y:.84375},{x:.46875,y:.84375},{x:.53125,y:.84375},{x:.53125,y:.84375},{x:.59375,y:.84375},{x:.59375,y:.84375},{x:.65625,y:.84375},{x:.65625,y:.84375},{x:.71875,y:.84375},{x:.71875,y:.84375},{x:.78125,y:.84375},{x:.78125,y:.84375},{x:.84375,y:.84375},{x:.84375,y:.84375},{x:.90625,y:.84375},{x:.90625,y:.84375},{x:.96875,y:.84375},{x:.96875,y:.84375},{x:.03125,y:.90625},{x:.03125,y:.90625},{x:.09375,y:.90625},{x:.09375,y:.90625},{x:.15625,y:.90625},{x:.15625,y:.90625},{x:.21875,y:.90625},{x:.21875,y:.90625},{x:.28125,y:.90625},{x:.28125,y:.90625},{x:.34375,y:.90625},{x:.34375,y:.90625},{x:.40625,y:.90625},{x:.40625,y:.90625},{x:.46875,y:.90625},{x:.46875,y:.90625},{x:.53125,y:.90625},{x:.53125,y:.90625},{x:.59375,y:.90625},{x:.59375,y:.90625},{x:.65625,y:.90625},{x:.65625,y:.90625},{x:.71875,y:.90625},{x:.71875,y:.90625},{x:.78125,y:.90625},{x:.78125,y:.90625},{x:.84375,y:.90625},{x:.84375,y:.90625},{x:.90625,y:.90625},{x:.90625,y:.90625},{x:.96875,y:.90625},{x:.96875,y:.90625},{x:.03125,y:.96875},{x:.03125,y:.96875},{x:.09375,y:.96875},{x:.09375,y:.96875},{x:.15625,y:.96875},{x:.15625,y:.96875},{x:.21875,y:.96875},{x:.21875,y:.96875},{x:.28125,y:.96875},{x:.28125,y:.96875},{x:.34375,y:.96875},{x:.34375,y:.96875},{x:.40625,y:.96875},{x:.40625,y:.96875},{x:.46875,y:.96875},{x:.46875,y:.96875},{x:.53125,y:.96875},{x:.53125,y:.96875},{x:.59375,y:.96875},{x:.59375,y:.96875},{x:.65625,y:.96875},{x:.65625,y:.96875},{x:.71875,y:.96875},{x:.71875,y:.96875},{x:.78125,y:.96875},{x:.78125,y:.96875},{x:.84375,y:.96875},{x:.84375,y:.96875},{x:.90625,y:.96875},{x:.90625,y:.96875},{x:.96875,y:.96875},{x:.96875,y:.96875},{x:.0625,y:.0625},{x:.0625,y:.0625},{x:.0625,y:.0625},{x:.0625,y:.0625},{x:.0625,y:.0625},{x:.0625,y:.0625},{x:.1875,y:.0625},{x:.1875,y:.0625},{x:.1875,y:.0625},{x:.1875,y:.0625},{x:.1875,y:.0625},{x:.1875,y:.0625},{x:.3125,y:.0625},{x:.3125,y:.0625},{x:.3125,y:.0625},{x:.3125,y:.0625},{x:.3125,y:.0625},{x:.3125,y:.0625},{x:.4375,y:.0625},{x:.4375,y:.0625},{x:.4375,y:.0625},{x:.4375,y:.0625},{x:.4375,y:.0625},{x:.4375,y:.0625},{x:.5625,y:.0625},{x:.5625,y:.0625},{x:.5625,y:.0625},{x:.5625,y:.0625},{x:.5625,y:.0625},{x:.5625,y:.0625},{x:.6875,y:.0625},{x:.6875,y:.0625},{x:.6875,y:.0625},{x:.6875,y:.0625},{x:.6875,y:.0625},{x:.6875,y:.0625},{x:.8125,y:.0625},{x:.8125,y:.0625},{x:.8125,y:.0625},{x:.8125,y:.0625},{x:.8125,y:.0625},{x:.8125,y:.0625},{x:.9375,y:.0625},{x:.9375,y:.0625},{x:.9375,y:.0625},{x:.9375,y:.0625},{x:.9375,y:.0625},{x:.9375,y:.0625},{x:.0625,y:.1875},{x:.0625,y:.1875},{x:.0625,y:.1875},{x:.0625,y:.1875},{x:.0625,y:.1875},{x:.0625,y:.1875},{x:.1875,y:.1875},{x:.1875,y:.1875},{x:.1875,y:.1875},{x:.1875,y:.1875},{x:.1875,y:.1875},{x:.1875,y:.1875},{x:.3125,y:.1875},{x:.3125,y:.1875},{x:.3125,y:.1875},{x:.3125,y:.1875},{x:.3125,y:.1875},{x:.3125,y:.1875},{x:.4375,y:.1875},{x:.4375,y:.1875},{x:.4375,y:.1875},{x:.4375,y:.1875},{x:.4375,y:.1875},{x:.4375,y:.1875},{x:.5625,y:.1875},{x:.5625,y:.1875},{x:.5625,y:.1875},{x:.5625,y:.1875},{x:.5625,y:.1875},{x:.5625,y:.1875},{x:.6875,y:.1875},{x:.6875,y:.1875},{x:.6875,y:.1875},{x:.6875,y:.1875},{x:.6875,y:.1875},{x:.6875,y:.1875},{x:.8125,y:.1875},{x:.8125,y:.1875},{x:.8125,y:.1875},{x:.8125,y:.1875},{x:.8125,y:.1875},{x:.8125,y:.1875},{x:.9375,y:.1875},{x:.9375,y:.1875},{x:.9375,y:.1875},{x:.9375,y:.1875},{x:.9375,y:.1875},{x:.9375,y:.1875},{x:.0625,y:.3125},{x:.0625,y:.3125},{x:.0625,y:.3125},{x:.0625,y:.3125},{x:.0625,y:.3125},{x:.0625,y:.3125},{x:.1875,y:.3125},{x:.1875,y:.3125},{x:.1875,y:.3125},{x:.1875,y:.3125},{x:.1875,y:.3125},{x:.1875,y:.3125},{x:.3125,y:.3125},{x:.3125,y:.3125},{x:.3125,y:.3125},{x:.3125,y:.3125},{x:.3125,y:.3125},{x:.3125,y:.3125},{x:.4375,y:.3125},{x:.4375,y:.3125},{x:.4375,y:.3125},{x:.4375,y:.3125},{x:.4375,y:.3125},{x:.4375,y:.3125},{x:.5625,y:.3125},{x:.5625,y:.3125},{x:.5625,y:.3125},{x:.5625,y:.3125},{x:.5625,y:.3125},{x:.5625,y:.3125},{x:.6875,y:.3125},{x:.6875,y:.3125},{x:.6875,y:.3125},{x:.6875,y:.3125},{x:.6875,y:.3125},{x:.6875,y:.3125},{x:.8125,y:.3125},{x:.8125,y:.3125},{x:.8125,y:.3125},{x:.8125,y:.3125},{x:.8125,y:.3125},{x:.8125,y:.3125},{x:.9375,y:.3125},{x:.9375,y:.3125},{x:.9375,y:.3125},{x:.9375,y:.3125},{x:.9375,y:.3125},{x:.9375,y:.3125},{x:.0625,y:.4375},{x:.0625,y:.4375},{x:.0625,y:.4375},{x:.0625,y:.4375},{x:.0625,y:.4375},{x:.0625,y:.4375},{x:.1875,y:.4375},{x:.1875,y:.4375},{x:.1875,y:.4375},{x:.1875,y:.4375},{x:.1875,y:.4375},{x:.1875,y:.4375},{x:.3125,y:.4375},{x:.3125,y:.4375},{x:.3125,y:.4375},{x:.3125,y:.4375},{x:.3125,y:.4375},{x:.3125,y:.4375},{x:.4375,y:.4375},{x:.4375,y:.4375},{x:.4375,y:.4375},{x:.4375,y:.4375},{x:.4375,y:.4375},{x:.4375,y:.4375},{x:.5625,y:.4375},{x:.5625,y:.4375},{x:.5625,y:.4375},{x:.5625,y:.4375},{x:.5625,y:.4375},{x:.5625,y:.4375},{x:.6875,y:.4375},{x:.6875,y:.4375},{x:.6875,y:.4375},{x:.6875,y:.4375},{x:.6875,y:.4375},{x:.6875,y:.4375},{x:.8125,y:.4375},{x:.8125,y:.4375},{x:.8125,y:.4375},{x:.8125,y:.4375},{x:.8125,y:.4375},{x:.8125,y:.4375},{x:.9375,y:.4375},{x:.9375,y:.4375},{x:.9375,y:.4375},{x:.9375,y:.4375},{x:.9375,y:.4375},{x:.9375,y:.4375},{x:.0625,y:.5625},{x:.0625,y:.5625},{x:.0625,y:.5625},{x:.0625,y:.5625},{x:.0625,y:.5625},{x:.0625,y:.5625},{x:.1875,y:.5625},{x:.1875,y:.5625},{x:.1875,y:.5625},{x:.1875,y:.5625},{x:.1875,y:.5625},{x:.1875,y:.5625},{x:.3125,y:.5625},{x:.3125,y:.5625},{x:.3125,y:.5625},{x:.3125,y:.5625},{x:.3125,y:.5625},{x:.3125,y:.5625},{x:.4375,y:.5625},{x:.4375,y:.5625},{x:.4375,y:.5625},{x:.4375,y:.5625},{x:.4375,y:.5625},{x:.4375,y:.5625},{x:.5625,y:.5625},{x:.5625,y:.5625},{x:.5625,y:.5625},{x:.5625,y:.5625},{x:.5625,y:.5625},{x:.5625,y:.5625},{x:.6875,y:.5625},{x:.6875,y:.5625},{x:.6875,y:.5625},{x:.6875,y:.5625},{x:.6875,y:.5625},{x:.6875,y:.5625},{x:.8125,y:.5625},{x:.8125,y:.5625},{x:.8125,y:.5625},{x:.8125,y:.5625},{x:.8125,y:.5625},{x:.8125,y:.5625},{x:.9375,y:.5625},{x:.9375,y:.5625},{x:.9375,y:.5625},{x:.9375,y:.5625},{x:.9375,y:.5625},{x:.9375,y:.5625},{x:.0625,y:.6875},{x:.0625,y:.6875},{x:.0625,y:.6875},{x:.0625,y:.6875},{x:.0625,y:.6875},{x:.0625,y:.6875},{x:.1875,y:.6875},{x:.1875,y:.6875},{x:.1875,y:.6875},{x:.1875,y:.6875},{x:.1875,y:.6875},{x:.1875,y:.6875},{x:.3125,y:.6875},{x:.3125,y:.6875},{x:.3125,y:.6875},{x:.3125,y:.6875},{x:.3125,y:.6875},{x:.3125,y:.6875},{x:.4375,y:.6875},{x:.4375,y:.6875},{x:.4375,y:.6875},{x:.4375,y:.6875},{x:.4375,y:.6875},{x:.4375,y:.6875},{x:.5625,y:.6875},{x:.5625,y:.6875},{x:.5625,y:.6875},{x:.5625,y:.6875},{x:.5625,y:.6875},{x:.5625,y:.6875},{x:.6875,y:.6875},{x:.6875,y:.6875},{x:.6875,y:.6875},{x:.6875,y:.6875},{x:.6875,y:.6875},{x:.6875,y:.6875},{x:.8125,y:.6875},{x:.8125,y:.6875},{x:.8125,y:.6875},{x:.8125,y:.6875},{x:.8125,y:.6875},{x:.8125,y:.6875},{x:.9375,y:.6875},{x:.9375,y:.6875},{x:.9375,y:.6875},{x:.9375,y:.6875},{x:.9375,y:.6875},{x:.9375,y:.6875},{x:.0625,y:.8125},{x:.0625,y:.8125},{x:.0625,y:.8125},{x:.0625,y:.8125},{x:.0625,y:.8125},{x:.0625,y:.8125},{x:.1875,y:.8125},{x:.1875,y:.8125},{x:.1875,y:.8125},{x:.1875,y:.8125},{x:.1875,y:.8125},{x:.1875,y:.8125},{x:.3125,y:.8125},{x:.3125,y:.8125},{x:.3125,y:.8125},{x:.3125,y:.8125},{x:.3125,y:.8125},{x:.3125,y:.8125},{x:.4375,y:.8125},{x:.4375,y:.8125},{x:.4375,y:.8125},{x:.4375,y:.8125},{x:.4375,y:.8125},{x:.4375,y:.8125},{x:.5625,y:.8125},{x:.5625,y:.8125},{x:.5625,y:.8125},{x:.5625,y:.8125},{x:.5625,y:.8125},{x:.5625,y:.8125},{x:.6875,y:.8125},{x:.6875,y:.8125},{x:.6875,y:.8125},{x:.6875,y:.8125},{x:.6875,y:.8125},{x:.6875,y:.8125},{x:.8125,y:.8125},{x:.8125,y:.8125},{x:.8125,y:.8125},{x:.8125,y:.8125},{x:.8125,y:.8125},{x:.8125,y:.8125},{x:.9375,y:.8125},{x:.9375,y:.8125},{x:.9375,y:.8125},{x:.9375,y:.8125},{x:.9375,y:.8125},{x:.9375,y:.8125},{x:.0625,y:.9375},{x:.0625,y:.9375},{x:.0625,y:.9375},{x:.0625,y:.9375},{x:.0625,y:.9375},{x:.0625,y:.9375},{x:.1875,y:.9375},{x:.1875,y:.9375},{x:.1875,y:.9375},{x:.1875,y:.9375},{x:.1875,y:.9375},{x:.1875,y:.9375},{x:.3125,y:.9375},{x:.3125,y:.9375},{x:.3125,y:.9375},{x:.3125,y:.9375},{x:.3125,y:.9375},{x:.3125,y:.9375},{x:.4375,y:.9375},{x:.4375,y:.9375},{x:.4375,y:.9375},{x:.4375,y:.9375},{x:.4375,y:.9375},{x:.4375,y:.9375},{x:.5625,y:.9375},{x:.5625,y:.9375},{x:.5625,y:.9375},{x:.5625,y:.9375},{x:.5625,y:.9375},{x:.5625,y:.9375},{x:.6875,y:.9375},{x:.6875,y:.9375},{x:.6875,y:.9375},{x:.6875,y:.9375},{x:.6875,y:.9375},{x:.6875,y:.9375},{x:.8125,y:.9375},{x:.8125,y:.9375},{x:.8125,y:.9375},{x:.8125,y:.9375},{x:.8125,y:.9375},{x:.8125,y:.9375},{x:.9375,y:.9375},{x:.9375,y:.9375},{x:.9375,y:.9375},{x:.9375,y:.9375},{x:.9375,y:.9375},{x:.9375,y:.9375}];var C0=class{constructor(t){ue(this,\"model\");ue(this,\"anchors\");ue(this,\"anchorsTensor\");ue(this,\"inputSize\");ue(this,\"inputSizeTensor\");ue(this,\"doubleInputSizeTensor\");var a,n,r,s;this.model=t,this.anchors=uk.map(i=>[i.x,i.y]),this.anchorsTensor=Kn(this.anchors),this.inputSize=((s=(r=(n=(a=this==null?void 0:this.model)==null?void 0:a.inputs)==null?void 0:n[0])==null?void 0:r.shape)==null?void 0:s[2])||0,this.inputSizeTensor=Ht([this.inputSize,this.inputSize]),this.doubleInputSizeTensor=Ht([this.inputSize*2,this.inputSize*2])}normalizeBoxes(t){let a={};a.boxOffsets=Pe(t,[0,0],[-1,2]),a.boxSizes=Pe(t,[0,2],[-1,2]),a.div=me(a.boxOffsets,this.inputSizeTensor),a.boxCenterPoints=be(a.div,this.anchorsTensor),a.halfBoxSizes=me(a.boxSizes,this.doubleInputSizeTensor),a.sub=fe(a.boxCenterPoints,a.halfBoxSizes),a.startPoints=ae(a.sub,this.inputSizeTensor),a.add=be(a.boxCenterPoints,a.halfBoxSizes),a.endPoints=ae(a.add,this.inputSizeTensor);let n=ru([a.startPoints,a.endPoints],1);return Object.keys(a).forEach(r=>Y(a[r])),n}normalizeLandmarks(t,a){let n={};n.reshape=J(t,[-1,7,2]),n.div=me(n.reshape,this.inputSizeTensor),n.landmarks=be(n.div,this.anchors[a]?this.anchors[a]:0);let r=ae(n.landmarks,this.inputSizeTensor);return Object.keys(n).forEach(s=>Y(n[s])),r}async predict(t,a){var o;let n={};n.resize=ge.resizeBilinear(t,[this.inputSize,this.inputSize]),n.div=me(n.resize,ze.tf127),n.image=fe(n.div,ze.tf1),n.batched=this.model.execute(n.image),n.predictions=_e(n.batched),n.slice=Pe(n.predictions,[0,0],[-1,1]),n.sigmoid=Da(n.slice),n.scores=_e(n.sigmoid);let r=await n.scores.data();n.boxes=Pe(n.predictions,[0,1],[-1,4]),n.norm=this.normalizeBoxes(n.boxes),n.nms=await ge.nonMaxSuppressionAsync(n.norm,n.scores,3*(((o=a.hand)==null?void 0:o.maxDetected)||1),a.hand.iouThreshold,a.hand.minConfidence);let s=await n.nms.array(),i=[];for(let l of s){let u={};u.box=Pe(n.norm,[l,0],[1,-1]),u.slice=Pe(n.predictions,[l,5],[1,14]),u.norm=this.normalizeLandmarks(u.slice,l),u.palmLandmarks=J(u.norm,[-1,2]);let p=await u.box.data(),c=p.slice(0,2),d=p.slice(2,4),h=await u.palmLandmarks.array(),f={startPoint:c,endPoint:d,palmLandmarks:h,confidence:r[l]},m=sk(f,[(t.shape[2]||1)/this.inputSize,(t.shape[1]||0)/this.inputSize]);i.push(m),Object.keys(u).forEach(g=>Y(u[g]))}return Object.keys(n).forEach(l=>Y(n[l])),i}};var Bhe=5,dk=1.65,pk=[0,5,9,13,17,1,2],Whe=0,Vhe=2,ck=0,N0=class{constructor(t,a){ue(this,\"handDetector\");ue(this,\"handPoseModel\");ue(this,\"inputSize\");ue(this,\"storedBoxes\");ue(this,\"skipped\");ue(this,\"detectedHands\");var n,r,s;this.handDetector=t,this.handPoseModel=a,this.inputSize=((s=(r=(n=this.handPoseModel)==null?void 0:n.inputs)==null?void 0:r[0].shape)==null?void 0:s[2])||0,this.storedBoxes=[],this.skipped=Number.MAX_SAFE_INTEGER,this.detectedHands=0}calculateLandmarksBoundingBox(t){let a=t.map(i=>i[0]),n=t.map(i=>i[1]),r=[Math.min(...a),Math.min(...n)],s=[Math.max(...a),Math.max(...n)];return{startPoint:r,endPoint:s}}getBoxForPalmLandmarks(t,a){let n=t.map(s=>jg([...s,1],a)),r=this.calculateLandmarksBoundingBox(n);return S0(T0(r),Bhe)}getBoxForHandLandmarks(t){let a=this.calculateLandmarksBoundingBox(t),n=S0(T0(a),dk);n.palmLandmarks=[];for(let r=0;r<pk.length;r++)n.palmLandmarks.push(t[pk[r]].slice(0,2));return n}transformRawCoords(t,a,n,r){let s=I0(a),i=[s[0]/this.inputSize,s[1]/this.inputSize,(s[0]+s[1])/this.inputSize/2],o=t.map(h=>[i[0]*(h[0]-this.inputSize/2),i[1]*(h[1]-this.inputSize/2),i[2]*h[2]]),l=Hg(n,[0,0]),u=o.map(h=>[...jg(h,l),h[2]]),p=ok(r),c=[...Tp(a),1],d=[ws(c,p[0]),ws(c,p[1])];return u.map(h=>[Math.trunc(h[0]+d[0]),Math.trunc(h[1]+d[1]),Math.trunc(h[2])])}async estimateHands(t,a){let n=!1,r,s=(a.hand.skipTime||0)>te()-ck,i=this.skipped<(a.hand.skipFrames||0);a.skipAllowed&&s&&i&&(r=await this.handDetector.predict(t,a),this.skipped=0),a.skipAllowed&&this.skipped++,r&&r.length>0&&(r.length!==this.detectedHands&&this.detectedHands!==a.hand.maxDetected||!a.hand.landmarks)&&(this.detectedHands=0,this.storedBoxes=[...r],this.storedBoxes.length>0&&(n=!0));let o=[];for(let l=0;l<this.storedBoxes.length;l++){let u=this.storedBoxes[l];if(!!u)if(a.hand.landmarks){let p=a.hand.rotation?ik(u.palmLandmarks[Whe],u.palmLandmarks[Vhe]):0,c=Tp(u),d=[c[0]/t.shape[2],c[1]/t.shape[1]],h=a.hand.rotation&&ne.kernels.includes(\"rotatewithoffset\")?ge.rotateWithOffset(t,p,0,d):t.clone(),f=Hg(-p,c),m=n?this.getBoxForPalmLandmarks(u.palmLandmarks,f):u,g=rk(m,h,[this.inputSize,this.inputSize]),x=me(g,ze.tf255);Y(g),Y(h);let[A,y]=this.handPoseModel.execute(x);ck=te(),Y(x);let b=(await A.data())[0];if(Y(A),b>=a.hand.minConfidence/4){let w=J(y,[-1,3]),S=await w.array();Y(y),Y(w);let C=this.transformRawCoords(S,m,p,f),E=this.getBoxForHandLandmarks(C);this.storedBoxes[l]={...E,confidence:b};let _={landmarks:C,confidence:b,boxConfidence:u.confidence,fingerConfidence:b,box:{topLeft:E.startPoint,bottomRight:E.endPoint}};o.push(_)}else this.storedBoxes[l]=null;Y(y)}else{let p=S0(T0(u),dk),c={confidence:u.confidence,boxConfidence:u.confidence,fingerConfidence:0,box:{topLeft:p.startPoint,bottomRight:p.endPoint},landmarks:[]};o.push(c)}}return this.storedBoxes=this.storedBoxes.filter(l=>l!==null),this.detectedHands=o.length,o.length>a.hand.maxDetected&&(o.length=a.hand.maxDetected),o}};var hk={thumb:[1,2,3,4],index:[5,6,7,8],middle:[9,10,11,12],ring:[13,14,15,16],pinky:[17,18,19,20],palm:[0]},Do,zo,fk;async function qg(e,t){let a=await fk.estimateHands(e,t);if(!a)return[];let n=[];for(let r=0;r<a.length;r++){let s={};if(a[r].landmarks)for(let p of Object.keys(hk))s[p]=hk[p].map(c=>a[r].landmarks[c]);let i=a[r].landmarks,o=[Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,0,0],l=[0,0,0,0];if(i&&i.length>0){for(let p of i)p[0]<o[0]&&(o[0]=p[0]),p[1]<o[1]&&(o[1]=p[1]),p[0]>o[2]&&(o[2]=p[0]),p[1]>o[3]&&(o[3]=p[1]);o[2]-=o[0],o[3]-=o[1],l=[o[0]/(e.shape[2]||0),o[1]/(e.shape[1]||0),o[2]/(e.shape[2]||0),o[3]/(e.shape[1]||0)]}else o=a[r].box?[Math.trunc(Math.max(0,a[r].box.topLeft[0])),Math.trunc(Math.max(0,a[r].box.topLeft[1])),Math.trunc(Math.min(e.shape[2]||0,a[r].box.bottomRight[0])-Math.max(0,a[r].box.topLeft[0])),Math.trunc(Math.min(e.shape[1]||0,a[r].box.bottomRight[1])-Math.max(0,a[r].box.topLeft[1]))]:[0,0,0,0],l=[a[r].box.topLeft[0]/(e.shape[2]||0),a[r].box.topLeft[1]/(e.shape[1]||0),(a[r].box.bottomRight[0]-a[r].box.topLeft[0])/(e.shape[2]||0),(a[r].box.bottomRight[1]-a[r].box.topLeft[1])/(e.shape[1]||0)];let u=k0(i);n.push({id:r,score:Math.round(100*a[r].confidence)/100,boxScore:Math.round(100*a[r].boxConfidence)/100,fingerScore:Math.round(100*a[r].fingerConfidence)/100,label:\"hand\",box:o,boxRaw:l,keypoints:i,annotations:s,landmarks:u})}return n}async function mk(e){var a,n;ne.initial&&(Do=null,zo=null),!Do||!zo?[Do,zo]=await Promise.all([e.hand.enabled?Ee((a=e.hand.detector)==null?void 0:a.modelPath):null,e.hand.landmarks?Ee((n=e.hand.skeleton)==null?void 0:n.modelPath):null]):(e.debug&&K(\"cached model:\",Do.modelUrl),e.debug&&K(\"cached model:\",zo.modelUrl));let t=Do?new C0(Do):void 0;return t&&zo&&(fk=new N0(t,zo)),[Do,zo]}var Pt=[null,null],Ghe=[\"StatefulPartitionedCall/Postprocessor/Slice\",\"StatefulPartitionedCall/Postprocessor/ExpandDims_1\"],ks=[[0,0],[0,0]],Hhe=[\"hand\",\"fist\",\"pinch\",\"point\",\"face\",\"tip\",\"pinchtip\"],xk=4,Ak=1.6,jhe=512,qhe=1.4,E0=Number.MAX_SAFE_INTEGER,Xg=0,$r=[0,0],_t={boxes:[],hands:[]},yk={thumb:[1,2,3,4],index:[5,6,7,8],middle:[9,10,11,12],ring:[13,14,15,16],pinky:[17,18,19,20],base:[0],palm:[0,17,13,9,5,1,0]};async function bk(e){var t;if(ne.initial&&(Pt[0]=null),Pt[0])e.debug&&K(\"cached model:\",Pt[0].modelUrl);else{Qh([\"tensorlistreserve\",\"enter\",\"tensorlistfromtensor\",\"merge\",\"loopcond\",\"switch\",\"exit\",\"tensorliststack\",\"nextiteration\",\"tensorlistsetitem\",\"tensorlistgetitem\",\"reciprocal\",\"shape\",\"split\",\"where\"],e),Pt[0]=await Ee((t=e.hand.detector)==null?void 0:t.modelPath);let a=Pt[0].executor?Object.values(Pt[0].modelSignature.inputs):void 0;ks[0][0]=Array.isArray(a)?parseInt(a[0].tensorShape.dim[1].size):0,ks[0][1]=Array.isArray(a)?parseInt(a[0].tensorShape.dim[2].size):0}return Pt[0]}async function vk(e){var t;if(ne.initial&&(Pt[1]=null),Pt[1])e.debug&&K(\"cached model:\",Pt[1].modelUrl);else{Pt[1]=await Ee((t=e.hand.skeleton)==null?void 0:t.modelPath);let a=Pt[1].executor?Object.values(Pt[1].modelSignature.inputs):void 0;ks[1][0]=Array.isArray(a)?parseInt(a[0].tensorShape.dim[1].size):0,ks[1][1]=Array.isArray(a)?parseInt(a[0].tensorShape.dim[2].size):0}return Pt[1]}async function Xhe(e,t){let a=[];if(!e||!Pt[0])return a;let n={},r=(e.shape[2]||1)/(e.shape[1]||1),s=Math.min(Math.round((e.shape[1]||0)/8)*8,jhe),i=Math.round(s*r/8)*8;n.resize=ge.resizeBilinear(e,[s,i]),n.cast=He(n.resize,\"int32\"),[n.rawScores,n.rawBoxes]=await Pt[0].executeAsync(n.cast,Ghe),n.boxes=_e(n.rawBoxes,[0,2]),n.scores=_e(n.rawScores,[0]);let o=Ta(n.scores,1);Y(o[xk]),o.splice(xk,1),n.filtered=sa(o,1),Y(o),n.max=pa(n.filtered,1),n.argmax=ar(n.filtered,1);let l=0;n.nms=await ge.nonMaxSuppressionAsync(n.boxes,n.max,(t.hand.maxDetected||0)+1,t.hand.iouThreshold||0,t.hand.minConfidence||1);let u=await n.nms.data(),p=await n.max.data(),c=await n.argmax.data();for(let d of Array.from(u)){let h=Pe(n.boxes,d,1),f=await h.data();Y(h);let m=[f[1],f[0],f[3]-f[1],f[2]-f[0]],g=l0(m,qhe),x=[Math.trunc(m[0]*$r[0]),Math.trunc(m[1]*$r[1]),Math.trunc(m[2]*$r[0]),Math.trunc(m[3]*$r[1])],A=p[d],y=Hhe[c[d]],b={id:l++,score:A,box:x,boxRaw:g,label:y};a.push(b)}return Object.keys(n).forEach(d=>Y(n[d])),a.sort((d,h)=>h.score-d.score),a.length>(t.hand.maxDetected||1)&&(a.length=t.hand.maxDetected||1),a}async function Kg(e,t,a){let n={id:t.id,score:Math.round(100*t.score)/100,boxScore:Math.round(100*t.score)/100,fingerScore:0,box:t.box,boxRaw:t.boxRaw,label:t.label,keypoints:[],landmarks:{},annotations:{}};if(e&&Pt[1]&&a.hand.landmarks&&t.score>(a.hand.minConfidence||0)){let r={},s=[t.boxRaw[1],t.boxRaw[0],t.boxRaw[3]+t.boxRaw[1],t.boxRaw[2]+t.boxRaw[0]];r.crop=ge.cropAndResize(e,[s],[0],[ks[1][0],ks[1][1]],\"bilinear\"),r.div=me(r.crop,ze.tf255),[r.score,r.keypoints]=Pt[1].execute(r.div,[\"Identity_1\",\"Identity\"]);let i=(await r.score.data())[0],o=(100-Math.trunc(100/(1+Math.exp(i))))/100;if(o>=(a.hand.minConfidence||0)){n.fingerScore=o,r.reshaped=J(r.keypoints,[-1,3]);let p=(await r.reshaped.array()).map(c=>[c[0]/ks[1][1],c[1]/ks[1][0],c[2]||0]).map(c=>[c[0]*t.boxRaw[2],c[1]*t.boxRaw[3],c[2]||0]);n.keypoints=p.map(c=>[$r[0]*(c[0]+t.boxRaw[0]),$r[1]*(c[1]+t.boxRaw[1]),c[2]||0]),n.landmarks=k0(n.keypoints);for(let c of Object.keys(yk))n.annotations[c]=yk[c].map(d=>n.landmarks&&n.keypoints[d]?n.keypoints[d]:null)}Object.keys(r).forEach(l=>Y(r[l]))}return n}async function Zg(e,t){var r,s;if(!((r=Pt[0])!=null&&r.executor)||!((s=Pt[1])!=null&&s.executor)||!Pt[0].inputs[0].shape||!Pt[1].inputs[0].shape)return[];$r=[e.shape[2]||0,e.shape[1]||0],E0++;let a=(t.hand.skipTime||0)>te()-Xg,n=E0<(t.hand.skipFrames||0);return t.skipAllowed&&a&&n?_t.hands:new Promise(async i=>{let o=3*(t.hand.skipTime||0)>te()-Xg,l=E0<3*(t.hand.skipFrames||0);t.skipAllowed&&_t.hands.length===t.hand.maxDetected?_t.hands=await Promise.all(_t.boxes.map(p=>Kg(e,p,t))):t.skipAllowed&&o&&l&&_t.hands.length>0?_t.hands=await Promise.all(_t.boxes.map(p=>Kg(e,p,t))):(_t.boxes=await Xhe(e,t),Xg=te(),_t.hands=await Promise.all(_t.boxes.map(p=>Kg(e,p,t))),E0=0);let u=[..._t.boxes];if(_t.boxes.length=0,t.cacheSensitivity>0)for(let p=0;p<_t.hands.length;p++){let c=b9(_t.hands[p].keypoints,$r);if(c.box[2]/(e.shape[2]||1)>.05&&c.box[3]/(e.shape[1]||1)>.05&&_t.hands[p].fingerScore&&_t.hands[p].fingerScore>(t.hand.minConfidence||0)){let d=l0(c.box,Ak),h=l0(c.boxRaw,Ak);_t.boxes.push({...u[p],box:d,boxRaw:h})}}for(let p=0;p<_t.hands.length;p++){let c=Er(_t.hands[p].keypoints,$r);_t.hands[p].box=c.box,_t.hands[p].boxRaw=c.boxRaw}i(_t.hands)})}var or=(e=null)=>({face:[],body:[],hand:[],gesture:[],object:[],persons:[],performance:{},timestamp:0,width:0,height:0,error:e});var Cp={};hr(Cp,{connected:()=>M0,horizontal:()=>Yg,kpt:()=>R0,relative:()=>Qg,vertical:()=>Jg});var R0=[\"nose\",\"leftEye\",\"rightEye\",\"leftEar\",\"rightEar\",\"leftShoulder\",\"rightShoulder\",\"leftElbow\",\"rightElbow\",\"leftWrist\",\"rightWrist\",\"leftHip\",\"rightHip\",\"leftKnee\",\"rightKnee\",\"leftAnkle\",\"rightAnkle\"],Yg=[[\"leftEye\",\"rightEye\"],[\"leftEar\",\"rightEar\"],[\"leftShoulder\",\"rightShoulder\"],[\"leftElbow\",\"rightElbow\"],[\"leftWrist\",\"rightWrist\"],[\"leftHip\",\"rightHip\"],[\"leftKnee\",\"rightKnee\"],[\"leftAnkle\",\"rightAnkle\"]],Jg=[[\"leftKnee\",\"leftShoulder\"],[\"rightKnee\",\"rightShoulder\"],[\"leftAnkle\",\"leftKnee\"],[\"rightAnkle\",\"rightKnee\"]],Qg=[[[\"leftHip\",\"rightHip\"],[\"leftShoulder\",\"rightShoulder\"]],[[\"leftElbow\",\"rightElbow\"],[\"leftShoulder\",\"rightShoulder\"]]],M0={leftLeg:[\"leftHip\",\"leftKnee\",\"leftAnkle\"],rightLeg:[\"rightHip\",\"rightKnee\",\"rightAnkle\"],torso:[\"leftShoulder\",\"rightShoulder\",\"rightHip\",\"leftHip\",\"leftShoulder\"],leftArm:[\"leftShoulder\",\"leftElbow\",\"leftWrist\"],rightArm:[\"rightShoulder\",\"rightElbow\",\"rightWrist\"],head:[]};var xe=or(),e5=0;function kk(e,t){var i,o,l,u,p,c,d,h,f,m,g,x,A,y,b,w,S,C,E,_,$,M,I;let a=te();if(!e)return or();let n=Date.now()-e.timestamp,r=n<1e3?8-Math.log(n+1):1;if(e.canvas&&(xe.canvas=e.canvas),e.error&&(xe.error=e.error),!xe.body||e.body.length!==xe.body.length)xe.body=JSON.parse(JSON.stringify(e.body));else for(let N=0;N<e.body.length;N++){let O=e.body[N].box.map((U,H)=>((r-1)*xe.body[N].box[H]+U)/r),L=e.body[N].boxRaw.map((U,H)=>((r-1)*xe.body[N].boxRaw[H]+U)/r),B=e.body[N].keypoints.map((U,H)=>{var V,Q,Z,re,ee,he,oe,Ae,we;return{score:U.score,part:U.part,position:[xe.body[N].keypoints[H]?((r-1)*(xe.body[N].keypoints[H].position[0]||0)+(U.position[0]||0))/r:U.position[0],xe.body[N].keypoints[H]?((r-1)*(xe.body[N].keypoints[H].position[1]||0)+(U.position[1]||0))/r:U.position[1],xe.body[N].keypoints[H]?((r-1)*(xe.body[N].keypoints[H].position[2]||0)+(U.position[2]||0))/r:U.position[2]],positionRaw:[xe.body[N].keypoints[H]?((r-1)*(xe.body[N].keypoints[H].positionRaw[0]||0)+(U.positionRaw[0]||0))/r:U.positionRaw[0],xe.body[N].keypoints[H]?((r-1)*(xe.body[N].keypoints[H].positionRaw[1]||0)+(U.positionRaw[1]||0))/r:U.positionRaw[1],xe.body[N].keypoints[H]?((r-1)*(xe.body[N].keypoints[H].positionRaw[2]||0)+(U.positionRaw[2]||0))/r:U.positionRaw[2]],distance:[xe.body[N].keypoints[H]?((r-1)*(((V=xe.body[N].keypoints[H].distance)==null?void 0:V[0])||0)+(((Q=U.distance)==null?void 0:Q[0])||0))/r:(Z=U.distance)==null?void 0:Z[0],xe.body[N].keypoints[H]?((r-1)*(((re=xe.body[N].keypoints[H].distance)==null?void 0:re[1])||0)+(((ee=U.distance)==null?void 0:ee[1])||0))/r:(he=U.distance)==null?void 0:he[1],xe.body[N].keypoints[H]?((r-1)*(((oe=xe.body[N].keypoints[H].distance)==null?void 0:oe[2])||0)+(((Ae=U.distance)==null?void 0:Ae[2])||0))/r:(we=U.distance)==null?void 0:we[2]]}}),G={},j={connected:{}};(i=t.body.modelPath)!=null&&i.includes(\"efficientpose\")?j=p0:(o=t.body.modelPath)!=null&&o.includes(\"blazepose\")?j=i0:(l=t.body.modelPath)!=null&&l.includes(\"movenet\")&&(j=Cp);for(let[U,H]of Object.entries(j.connected)){let V=[];for(let Q=0;Q<H.length-1;Q++){let Z=B.find(ee=>ee.part===H[Q]),re=B.find(ee=>ee.part===H[Q+1]);Z&&re&&V.push([Z.position,re.position])}G[U]=V}xe.body[N]={...e.body[N],box:O,boxRaw:L,keypoints:B,annotations:G}}if(!xe.hand||e.hand.length!==xe.hand.length)xe.hand=JSON.parse(JSON.stringify(e.hand));else for(let N=0;N<e.hand.length;N++){let O=e.hand[N].box.map((j,U)=>((r-1)*xe.hand[N].box[U]+j)/r),L=e.hand[N].boxRaw.map((j,U)=>((r-1)*xe.hand[N].boxRaw[U]+j)/r);xe.hand[N].keypoints.length!==e.hand[N].keypoints.length&&(xe.hand[N].keypoints=e.hand[N].keypoints);let B=e.hand[N].keypoints&&e.hand[N].keypoints.length>0?e.hand[N].keypoints.map((j,U)=>j.map((H,V)=>((r-1)*(xe.hand[N].keypoints[U][V]||1)+(H||0))/r)):[],G={};if(Object.keys(xe.hand[N].annotations).length!==Object.keys(e.hand[N].annotations).length)xe.hand[N].annotations=e.hand[N].annotations,G=xe.hand[N].annotations;else if(e.hand[N].annotations)for(let j of Object.keys(e.hand[N].annotations))G[j]=(c=(p=(u=e.hand[N])==null?void 0:u.annotations)==null?void 0:p[j])!=null&&c[0]?e.hand[N].annotations[j].map((U,H)=>U.map((V,Q)=>((r-1)*xe.hand[N].annotations[j][H][Q]+V)/r)):null;xe.hand[N]={...e.hand[N],box:O,boxRaw:L,keypoints:B,annotations:G}}if(!xe.face||e.face.length!==xe.face.length)xe.face=JSON.parse(JSON.stringify(e.face));else for(let N=0;N<e.face.length;N++){let O=e.face[N].box.map((B,G)=>((r-1)*xe.face[N].box[G]+B)/r),L=e.face[N].boxRaw.map((B,G)=>((r-1)*xe.face[N].boxRaw[G]+B)/r);if(e.face[N].rotation){let B={matrix:[0,0,0,0,0,0,0,0,0],angle:{roll:0,yaw:0,pitch:0},gaze:{bearing:0,strength:0}};B.matrix=(d=e.face[N].rotation)==null?void 0:d.matrix,B.angle={roll:((r-1)*(((f=(h=xe.face[N].rotation)==null?void 0:h.angle)==null?void 0:f.roll)||0)+(((g=(m=e.face[N].rotation)==null?void 0:m.angle)==null?void 0:g.roll)||0))/r,yaw:((r-1)*(((A=(x=xe.face[N].rotation)==null?void 0:x.angle)==null?void 0:A.yaw)||0)+(((b=(y=e.face[N].rotation)==null?void 0:y.angle)==null?void 0:b.yaw)||0))/r,pitch:((r-1)*(((S=(w=xe.face[N].rotation)==null?void 0:w.angle)==null?void 0:S.pitch)||0)+(((E=(C=e.face[N].rotation)==null?void 0:C.angle)==null?void 0:E.pitch)||0))/r},B.gaze={bearing:((r-1)*(((_=xe.face[N].rotation)==null?void 0:_.gaze.bearing)||0)+((($=e.face[N].rotation)==null?void 0:$.gaze.bearing)||0))/r,strength:((r-1)*(((M=xe.face[N].rotation)==null?void 0:M.gaze.strength)||0)+(((I=e.face[N].rotation)==null?void 0:I.gaze.strength)||0))/r},xe.face[N]={...e.face[N],rotation:B,box:O,boxRaw:L}}else xe.face[N]={...e.face[N],box:O,boxRaw:L}}if(!xe.object||e.object.length!==xe.object.length)xe.object=JSON.parse(JSON.stringify(e.object));else for(let N=0;N<e.object.length;N++){let O=e.object[N].box.map((B,G)=>((r-1)*xe.object[N].box[G]+B)/r),L=e.object[N].boxRaw.map((B,G)=>((r-1)*xe.object[N].boxRaw[G]+B)/r);xe.object[N]={...e.object[N],box:O,boxRaw:L}}if(e.persons){let N=e.persons;if(!xe.persons||N.length!==xe.persons.length)xe.persons=JSON.parse(JSON.stringify(N));else for(let O=0;O<N.length;O++)xe.persons[O].box=N[O].box.map((L,B)=>((r-1)*xe.persons[O].box[B]+L)/r)}e.gesture&&(xe.gesture=e.gesture),xe.width=e.width,xe.height=e.height;let s=te();return e5=ne.perfadd?e5+Math.round(s-a):Math.round(s-a),e.performance&&(xe.performance={...e.performance,interpolate:e5}),xe}var ma;async function t5(e){return!ma||ne.initial?ma=await Ee(e.segmentation.modelPath):e.debug&&K(\"cached model:\",ma.modelUrl),ma}async function Ik(e,t){var r;if(ma||(ma=await t5(t)),!(ma!=null&&ma.executor)||!((r=ma==null?void 0:ma.inputs)!=null&&r[0].shape))return null;let a={};a.resize=ge.resizeBilinear(e,[ma.inputs[0].shape?ma.inputs[0].shape[1]:0,ma.inputs[0].shape?ma.inputs[0].shape[2]:0],!1),a.norm=me(a.resize,ze.tf255),a.res=ma.execute(a.norm),a.squeeze=_e(a.res,[0]),[a.bgRaw,a.fgRaw]=Ta(a.squeeze,2),a.fg=Ah(a.fgRaw),a.mul=ae(a.fg,ze.tf255),a.expand=Gt(a.mul,2),a.output=ge.resizeBilinear(a.expand,[e.shape[1]||0,e.shape[2]||0]);let n;switch(t.segmentation.mode||\"default\"){case\"default\":a.input=_e(e),a.concat=at([a.input,a.output],-1),n=He(a.concat,\"int32\");break;case\"alpha\":n=He(a.output,\"int32\");break;default:n=Be(0)}return Object.keys(a).forEach(s=>Y(a[s])),n}var $0={};hr($0,{distance:()=>a5,find:()=>Yhe,similarity:()=>Zhe});function a5(e,t,a={order:2,multiplier:25}){if(!e||!e)return Number.MAX_SAFE_INTEGER;let n=0;for(let r=0;r<e.length;r++){let s=!a.order||a.order===2?e[r]-t[r]:Math.abs(e[r]-t[r]);n+=!a.order||a.order===2?s*s:s**a.order}return(a.multiplier||20)*n}var Tk=(e,t,a,n)=>{if(e===0)return 1;let s=(1-(t===2?Math.sqrt(e):e**(1/t))/100-a)/(n-a);return Math.max(Math.min(s,1),0)};function Zhe(e,t,a={order:2,multiplier:25,min:.2,max:.8}){let n=a5(e,t,a);return Tk(n,a.order||2,a.min||0,a.max||1)}function Yhe(e,t,a={order:2,multiplier:25,threshold:0,min:.2,max:.8}){if(!Array.isArray(e)||!Array.isArray(t)||e.length<64||t.length===0)return{index:-1,distance:Number.POSITIVE_INFINITY,similarity:0};let n=Number.MAX_SAFE_INTEGER,r=-1;for(let i=0;i<t.length;i++){let o=t[i].length===e.length?a5(e,t[i],a):Number.MAX_SAFE_INTEGER;if(o<n&&(n=o,r=i),n<(a.threshold||0))break}let s=Tk(n,a.order||2,a.min||0,a.max||1);return{index:r,distance:n,similarity:s}}var x5={};hr(x5,{Models:()=>Rp,validateModel:()=>L0});var Ck=.005,nn={keypoints:[],padding:[[0,0],[0,0],[0,0],[0,0]]};function n5(e){for(let t of Yg){let a=e.keypoints.findIndex(r=>r.part===t[0]),n=e.keypoints.findIndex(r=>r.part===t[1]);if(e.keypoints[a]&&e.keypoints[n]&&e.keypoints[a].position[0]<e.keypoints[n].position[0]){let r=e.keypoints[a];e.keypoints[a]=e.keypoints[n],e.keypoints[n]=r}}for(let t of Jg){let a=e.keypoints.findIndex(r=>r&&r.part===t[0]),n=e.keypoints.findIndex(r=>r&&r.part===t[1]);e.keypoints[a]&&e.keypoints[n]&&e.keypoints[a].position[1]<e.keypoints[n].position[1]&&e.keypoints.splice(a,1)}for(let[t,a]of Qg){let n=e.keypoints.findIndex(u=>u&&u.part===t[0]),r=e.keypoints.findIndex(u=>u&&u.part===t[1]),s=e.keypoints.findIndex(u=>u&&u.part===a[0]),i=e.keypoints.findIndex(u=>u&&u.part===a[1]);if(!e.keypoints[s]||!e.keypoints[i])continue;let o=e.keypoints[n]?[Math.abs(e.keypoints[s].position[0]-e.keypoints[n].position[0]),Math.abs(e.keypoints[i].position[0]-e.keypoints[n].position[0])]:[0,0],l=e.keypoints[r]?[Math.abs(e.keypoints[i].position[0]-e.keypoints[r].position[0]),Math.abs(e.keypoints[s].position[0]-e.keypoints[r].position[0])]:[0,0];if(o[0]>o[1]||l[0]>l[1]){let u=e.keypoints[n];e.keypoints[n]=e.keypoints[r],e.keypoints[r]=u}}}function Nk(e){for(let t=0;t<e.length;t++)if(e[t]&&nn.keypoints[t]){let a=[Math.abs(e[t].positionRaw[0]-nn.keypoints[t].positionRaw[0]),Math.abs(e[t].positionRaw[1]-nn.keypoints[t].positionRaw[1])];a[0]<Ck&&a[1]<Ck?e[t]=nn.keypoints[t]:nn.keypoints[t]=e[t]}else nn.keypoints[t]=e[t];return e}function Ek(e,t){var r,s;let a={};if(!((r=e==null?void 0:e.shape)!=null&&r[1])||!((s=e==null?void 0:e.shape)!=null&&s[2]))return e;nn.padding=[[0,0],[e.shape[2]>e.shape[1]?Math.trunc((e.shape[2]-e.shape[1])/2):0,e.shape[2]>e.shape[1]?Math.trunc((e.shape[2]-e.shape[1])/2):0],[e.shape[1]>e.shape[2]?Math.trunc((e.shape[1]-e.shape[2])/2):0,e.shape[1]>e.shape[2]?Math.trunc((e.shape[1]-e.shape[2])/2):0],[0,0]],a.pad=rr(e,nn.padding),a.resize=ge.resizeBilinear(a.pad,[t,t]);let n=He(a.resize,\"int32\");return Object.keys(a).forEach(i=>Y(a[i])),n}function Rk(e,t){e.keypoints=e.keypoints.filter(n=>n==null?void 0:n.position);for(let n of e.keypoints)n.position=[n.position[0]*(t[0]+nn.padding[2][0]+nn.padding[2][1])/t[0]-nn.padding[2][0],n.position[1]*(t[1]+nn.padding[1][0]+nn.padding[1][1])/t[1]-nn.padding[1][0]],n.positionRaw=[n.position[0]/t[0],n.position[1]/t[1]];let a=Er(e.keypoints.map(n=>n.position),t);return e.box=a.box,e.boxRaw=a.boxRaw,e}var Vt,_0=0,r5=Number.MAX_SAFE_INTEGER,Lo={boxes:[],bodies:[],last:0};async function Mk(e){var t;return ne.initial&&(Vt=null),Vt?e.debug&&K(\"cached model:\",Vt.modelUrl):(Qh([\"size\"],e),Vt=await Ee(e.body.modelPath)),_0=(Vt==null?void 0:Vt.executor)&&((t=Vt==null?void 0:Vt.inputs)==null?void 0:t[0].shape)?Vt.inputs[0].shape[2]:0,_0<64&&(_0=256),Vt}function Qhe(e,t,a){let n=e[0][0],r=[],s=0;for(let p=0;p<n.length;p++)if(s=n[p][2],s>t.body.minConfidence){let c=[n[p][1],n[p][0]];r.push({score:Math.round(100*s)/100,part:R0[p],positionRaw:c,position:[Math.round((a.shape[2]||0)*c[0]),Math.round((a.shape[1]||0)*c[1])]})}s=r.reduce((p,c)=>c.score>p?c.score:p,0);let i=[],o=Er(r.map(p=>p.position),[a.shape[2],a.shape[1]]),l={};for(let[p,c]of Object.entries(M0)){let d=[];for(let h=0;h<c.length-1;h++){let f=r.find(g=>g.part===c[h]),m=r.find(g=>g.part===c[h+1]);f&&m&&f.score>(t.body.minConfidence||0)&&m.score>(t.body.minConfidence||0)&&d.push([f.position,m.position])}l[p]=d}let u={id:0,score:s,box:o.box,boxRaw:o.boxRaw,keypoints:r,annotations:l};return n5(u),i.push(u),i}function e0e(e,t,a){let n=[];for(let r=0;r<e[0].length;r++){let s=e[0][r],i=Math.round(100*s[51+4])/100;if(i>t.body.minConfidence){let o=[];for(let c=0;c<17;c++){let d=s[3*c+2];if(d>t.body.minConfidence){let h=[s[3*c+1],s[3*c+0]];o.push({part:R0[c],score:Math.round(100*d)/100,positionRaw:h,position:[Math.round((a.shape[2]||0)*h[0]),Math.round((a.shape[1]||0)*h[1])]})}}let l=Er(o.map(c=>c.position),[a.shape[2],a.shape[1]]),u={};for(let[c,d]of Object.entries(M0)){let h=[];for(let f=0;f<d.length-1;f++){let m=o.find(x=>x.part===d[f]),g=o.find(x=>x.part===d[f+1]);m&&g&&m.score>(t.body.minConfidence||0)&&g.score>(t.body.minConfidence||0)&&h.push([m.position,g.position])}u[c]=h}let p={id:r,score:i,box:l.box,boxRaw:l.boxRaw,keypoints:[...o],annotations:u};n5(p),n.push(p)}}return n.sort((r,s)=>s.score-r.score),n.length>t.body.maxDetected&&(n.length=t.body.maxDetected),n}async function s5(e,t){var r;if(!(Vt!=null&&Vt.executor)||!((r=Vt==null?void 0:Vt.inputs)!=null&&r[0].shape))return[];t.skipAllowed||(Lo.boxes.length=0),r5++;let a=(t.body.skipTime||0)>te()-Lo.last,n=r5<(t.body.skipFrames||0);return t.skipAllowed&&a&&n?Lo.bodies:new Promise(async s=>{let i={};r5=0,i.input=Ek(e,_0),i.res=Vt==null?void 0:Vt.execute(i.input),Lo.last=te();let o=await i.res.array();Lo.bodies=i.res.shape[2]===17?Qhe(o,t,e):e0e(o,t,e);for(let l of Lo.bodies)Rk(l,[e.shape[2]||1,e.shape[1]||1]),Nk(l.keypoints);Object.keys(i).forEach(l=>Y(i[l])),s(Lo.bodies)})}var _n,P0=[],_k=0,i5=Number.MAX_SAFE_INTEGER,O0=0,F0=2.5;async function Pk(e){if(!_n||ne.initial){_n=await Ee(e.object.modelPath);let t=_n!=null&&_n.executor?Object.values(_n.modelSignature.inputs):void 0;O0=Array.isArray(t)?parseInt(t[0].tensorShape.dim[2].size):416}else e.debug&&K(\"cached model:\",_n.modelUrl);return _n}async function t0e(e,t,a){var u,p;let n=0,r=[],s=O0;for(let c of[1,2,4]){let d=c*13,h=_e(e.find(y=>y.shape[1]===d**2&&(y.shape[2]||0)===bu.length)),f=await h.array(),m=_e(e.find(y=>y.shape[1]===d**2&&(y.shape[2]||0)<bu.length)),g=J(m,[-1,4,(((u=m.shape)==null?void 0:u[1])||0)/4]),x=ar(g,2),A=await x.array();for(let y=0;y<h.shape[0];y++)for(let b=0;b<(((p=h.shape)==null?void 0:p[1])||0);b++){let w=f[y][b];if(w>(a.object.minConfidence||0)&&b!==61){let S=(.5+Math.trunc(y%d))/d,C=(.5+Math.trunc(y/d))/d,E=A[y].map(B=>B*(d/c/s)),[_,$]=[S-F0/c*E[0],C-F0/c*E[1]],[M,I]=[S+F0/c*E[2]-_,C+F0/c*E[3]-$],N=[_,$,M,I];N=N.map(B=>Math.max(0,Math.min(B,1)));let O=[N[0]*t[0],N[1]*t[1],N[2]*t[0],N[3]*t[1]],L={id:n++,score:Math.round(100*w)/100,class:b+1,label:bu[b].label,box:O.map(B=>Math.trunc(B)),boxRaw:N};r.push(L)}}Y([h,m,g,x])}let i=r.map(c=>[c.boxRaw[1],c.boxRaw[0],c.boxRaw[3],c.boxRaw[2]]),o=r.map(c=>c.score),l=[];if(i&&i.length>0){let c=await ge.nonMaxSuppressionAsync(i,o,a.object.maxDetected||0,a.object.iouThreshold,a.object.minConfidence);l=Array.from(await c.data()),Y(c)}return r=r.filter((c,d)=>l.includes(d)).sort((c,d)=>d.score-c.score),r}async function o5(e,t){if(!(_n!=null&&_n.executor))return[];let a=(t.object.skipTime||0)>te()-_k,n=i5<(t.object.skipFrames||0);return t.skipAllowed&&a&&n&&P0.length>0?(i5++,P0):(i5=0,!ne.kernels.includes(\"mod\")||!ne.kernels.includes(\"sparsetodense\")?P0:new Promise(async r=>{let s=[e.shape[2]||0,e.shape[1]||0],i=ge.resizeBilinear(e,[O0,O0],!1),o=me(i,ze.tf255),l=Ws(o,[0,3,1,2]),u;t.object.enabled&&(u=_n.execute(l)),_k=te();let p=await t0e(u,s,t);P0=p,Y([i,o,l,...u]),r(p)}))}var Ep=[\"nose\",\"leftEye\",\"rightEye\",\"leftEar\",\"rightEar\",\"leftShoulder\",\"rightShoulder\",\"leftElbow\",\"rightElbow\",\"leftWrist\",\"rightWrist\",\"leftHip\",\"rightHip\",\"leftKnee\",\"rightKnee\",\"leftAnkle\",\"rightAnkle\"],a0e=Ep.length,Np=Ep.reduce((e,t,a)=>(e[t]=a,e),{}),n0e=[[\"leftHip\",\"leftShoulder\"],[\"leftElbow\",\"leftShoulder\"],[\"leftElbow\",\"leftWrist\"],[\"leftHip\",\"leftKnee\"],[\"leftKnee\",\"leftAnkle\"],[\"rightHip\",\"rightShoulder\"],[\"rightElbow\",\"rightShoulder\"],[\"rightElbow\",\"rightWrist\"],[\"rightHip\",\"rightKnee\"],[\"rightKnee\",\"rightAnkle\"],[\"leftShoulder\",\"rightShoulder\"],[\"leftHip\",\"rightHip\"]],M5e=n0e.map(([e,t])=>[Np[e],Np[t]]),Ok=[[\"nose\",\"leftEye\"],[\"leftEye\",\"leftEar\"],[\"nose\",\"rightEye\"],[\"rightEye\",\"rightEar\"],[\"nose\",\"leftShoulder\"],[\"leftShoulder\",\"leftElbow\"],[\"leftElbow\",\"leftWrist\"],[\"leftShoulder\",\"leftHip\"],[\"leftHip\",\"leftKnee\"],[\"leftKnee\",\"leftAnkle\"],[\"nose\",\"rightShoulder\"],[\"rightShoulder\",\"rightElbow\"],[\"rightElbow\",\"rightWrist\"],[\"rightShoulder\",\"rightHip\"],[\"rightHip\",\"rightKnee\"],[\"rightKnee\",\"rightAnkle\"]];function Dk(e){let t=e.reduce(({maxX:a,maxY:n,minX:r,minY:s},{position:{x:i,y:o}})=>({maxX:Math.max(a,i),maxY:Math.max(n,o),minX:Math.min(r,i),minY:Math.min(s,o)}),{maxX:Number.NEGATIVE_INFINITY,maxY:Number.NEGATIVE_INFINITY,minX:Number.POSITIVE_INFINITY,minY:Number.POSITIVE_INFINITY});return[t.minX,t.minY,t.maxX-t.minX,t.maxY-t.minY]}function zk(e,[t,a],[n,r]){let s=t/n,i=a/r,o=(u,p)=>({id:p,score:u.score,boxRaw:[u.box[0]/r,u.box[1]/n,u.box[2]/r,u.box[3]/n],box:[Math.trunc(u.box[0]*i),Math.trunc(u.box[1]*s),Math.trunc(u.box[2]*i),Math.trunc(u.box[3]*s)],keypoints:u.keypoints.map(({score:c,part:d,position:h})=>({score:c,part:d,position:[Math.trunc(h.x*i),Math.trunc(h.y*s)],positionRaw:[h.x/n,h.y/n]})),annotations:{}});return e.map((u,p)=>o(u,p))}var D0=class{constructor(t,a){ue(this,\"priorityQueue\");ue(this,\"numberOfElements\");ue(this,\"getElementValue\");this.priorityQueue=new Array(t),this.numberOfElements=-1,this.getElementValue=a}enqueue(t){this.priorityQueue[++this.numberOfElements]=t,this.swim(this.numberOfElements)}dequeue(){let t=this.priorityQueue[0];return this.exchange(0,this.numberOfElements--),this.sink(0),this.priorityQueue[this.numberOfElements+1]=null,t}empty(){return this.numberOfElements===-1}size(){return this.numberOfElements+1}all(){return this.priorityQueue.slice(0,this.numberOfElements+1)}max(){return this.priorityQueue[0]}swim(t){for(;t>0&&this.less(Math.floor(t/2),t);)this.exchange(t,Math.floor(t/2)),t=Math.floor(t/2)}sink(t){for(;2*t<=this.numberOfElements;){let a=2*t;if(a<this.numberOfElements&&this.less(a,a+1)&&a++,!this.less(t,a))break;this.exchange(t,a),t=a}}getValueAt(t){return this.getElementValue(this.priorityQueue[t])}less(t,a){return this.getValueAt(t)<this.getValueAt(a)}exchange(t,a){let n=this.priorityQueue[t];this.priorityQueue[t]=this.priorityQueue[a],this.priorityQueue[a]=n}};function l5(e,t,a,n){return{y:n.get(e,t,a),x:n.get(e,t,a+a0e)}}function u5(e,t,a){let{heatmapY:n,heatmapX:r,id:s}=e,{y:i,x:o}=l5(n,r,s,a);return{x:e.heatmapX*t+o,y:e.heatmapY*t+i}}function d5(e,t,a){return e<t?t:e>a?a:e}function Lk(e,t,a,n){let r=a-e,s=n-t;return r*r+s*s}function p5(e,t){return{x:e.x+t.x,y:e.y+t.y}}var rn,s0e=[\"MobilenetV1/offset_2/BiasAdd\",\"MobilenetV1/heatmap_2/BiasAdd\",\"MobilenetV1/displacement_fwd_2/BiasAdd\",\"MobilenetV1/displacement_bwd_2/BiasAdd\"],z0=1,Ru=16,i0e=50**2;function Bk(e,t,a,n,r,s,i=2){let o=x=>({y:s.get(x.y,x.x,e),x:s.get(x.y,x.x,s.shape[2]/2+e)}),l=(x,A,y)=>({y:d5(Math.round(x.y/Ru),0,A-1),x:d5(Math.round(x.x/Ru),0,y-1)}),[u,p]=n.shape,c=l(t.position,u,p),d=o(c),f=p5(t.position,d);for(let x=0;x<i;x++){let A=l(f,u,p),y=l5(A.y,A.x,a,r);f=p5({x:A.x*Ru,y:A.y*Ru},{x:y.x,y:y.y})}let m=l(f,u,p),g=n.get(m.y,m.x,a);return{position:f,part:Ep[a],score:g}}function o0e(e,t,a,n,r){let s=Ok.map(([d,h])=>[Np[d],Np[h]]),i=s.map(([,d])=>d),o=s.map(([d])=>d),l=t.shape[2],u=i.length,p=new Array(l),c=u5(e.part,Ru,a);p[e.part.id]={score:e.score,part:Ep[e.part.id],position:c};for(let d=u-1;d>=0;--d){let h=i[d],f=o[d];p[h]&&!p[f]&&(p[f]=Bk(d,p[h],f,t,a,r))}for(let d=0;d<u;++d){let h=o[d],f=i[d];p[h]&&!p[f]&&(p[f]=Bk(d,p[h],f,t,a,n))}return p}function l0e(e,t,a,n,r){let[s,i]=r.shape,o=!0,l=Math.max(a-z0,0),u=Math.min(a+z0+1,s);for(let p=l;p<u;++p){let c=Math.max(n-z0,0),d=Math.min(n+z0+1,i);for(let h=c;h<d;++h)if(r.get(p,h,e)>t){o=!1;break}if(!o)break}return o}function u0e(e,t){let[a,n,r]=t.shape,s=new D0(a*n*r,({score:i})=>i);for(let i=0;i<a;++i)for(let o=0;o<n;++o)for(let l=0;l<r;++l){let u=t.get(i,o,l);u<e||l0e(l,u,i,o,t)&&s.enqueue({score:u,part:{heatmapY:i,heatmapX:o,id:l}})}return s}function Wk(e,{x:t,y:a},n){return e.some(({keypoints:r})=>{var i;let s=(i=r[n])==null?void 0:i.position;return s?Lk(a,t,s.y,s.x)<=i0e:!1})}function d0e(e,t){return t.reduce((n,{position:r,score:s},i)=>(Wk(e,r,i)||(n+=s),n),0)/t.length}function p0e(e,t,a,n,r,s){let i=[],o=u0e(s,t);for(;i.length<r&&!o.empty();){let l=o.dequeue(),u=u5(l.part,Ru,e);if(Wk(i,u,l.part.id))continue;let p=o0e(l,t,e,a,n);p=p.filter(h=>h.score>s);let c=d0e(i,p),d=Dk(p);c>s&&i.push({keypoints:p,box:d,score:Math.round(100*c)/100})}return i}async function c5(e,t){if(!(rn!=null&&rn.executor))return[];let a=$e(()=>{if(!rn.inputs[0].shape)return[];let i=ge.resizeBilinear(e,[rn.inputs[0].shape[2],rn.inputs[0].shape[1]]),o=fe(me(He(i,\"float32\"),127.5),1),u=rn.execute(o,s0e).map(p=>_e(p,[0]));return u[1]=Da(u[1]),u}),n=await Promise.all(a.map(i=>i.buffer()));for(let i of a)Y(i);let r=p0e(n[0],n[1],n[2],n[3],t.body.maxDetected,t.body.minConfidence);return rn.inputs[0].shape?zk(r,[e.shape[1],e.shape[2]],[rn.inputs[0].shape[2],rn.inputs[0].shape[1]]):[]}async function Vk(e){return!rn||ne.initial?rn=await Ee(e.body.modelPath):e.debug&&K(\"cached model:\",rn.modelUrl),rn}var lr,c0e=[\"fgr\",\"pha\",\"r1o\",\"r2o\",\"r3o\",\"r4o\"],Ut={},f5=0;function Hk(e){Y([Ut.r1i,Ut.r2i,Ut.r3i,Ut.r4i,Ut.downsample_ratio]),Ut.r1i=Be(0),Ut.r2i=Be(0),Ut.r3i=Be(0),Ut.r4i=Be(0),f5=e.segmentation.ratio||.5,Ut.downsample_ratio=Be(f5)}async function m5(e){return!lr||ne.initial?lr=await Ee(e.segmentation.modelPath):e.debug&&K(\"cached model:\",lr.modelUrl),Hk(e),lr}var Gk=e=>$e(()=>{let t=_e(e,[0]),a=ae(t,ze.tf255);return He(a,\"int32\")});function h5(e,t){let a=e?Gk(e):nr([t.shape[1]||0,t.shape[2]||0,3],255,\"int32\"),n=t?Gk(t):nr([e.shape[1]||0,e.shape[2]||0,1],255,\"int32\"),r=at([a,n],-1);return Y([a,n]),r}function h0e(e){return $e(()=>{let t={};return t.unstack=Ta(e,-1),t.concat=at(t.unstack,1),t.split=ka(t.concat,4,1),t.stack=at(t.split,2),t.squeeze=_e(t.stack,[0]),t.expand=Gt(t.squeeze,-1),t.add=be(t.expand,1),t.mul=ae(t.add,127.5),t.cast=He(t.mul,\"int32\"),t.tile=Gr(t.cast,[1,1,3]),t.alpha=nr([t.tile.shape[0]||0,t.tile.shape[1]||0,1],255,\"int32\"),at([t.tile,t.alpha],-1)})}async function jk(e,t){if(lr||(lr=await m5(t)),!(lr!=null&&lr.executor))return null;Ut.src=me(e,255),f5!==t.segmentation.ratio&&Hk(t);let[a,n,r,s,i,o]=await lr.executeAsync(Ut,c0e),l;switch(t.segmentation.mode||\"default\"){case\"default\":l=h5(a,n);break;case\"alpha\":l=h5(null,n);break;case\"foreground\":l=h5(a,null);break;case\"state\":l=h0e(r);break;default:l=Be(0)}return Y([Ut.src,a,n,Ut.r1i,Ut.r2i,Ut.r3i,Ut.r4i]),[Ut.r1i,Ut.r2i,Ut.r3i,Ut.r4i]=[r,s,i,o],l}var ga;async function g5(e){return!ga||ne.initial?ga=await Ee(e.segmentation.modelPath):e.debug&&K(\"cached model:\",ga.modelUrl),ga}async function Xk(e,t){var r;if(ga||(ga=await g5(t)),!(ga!=null&&ga.executor)||!((r=ga==null?void 0:ga.inputs)!=null&&r[0].shape))return null;let a={};a.resize=ge.resizeBilinear(e,[ga.inputs[0].shape?ga.inputs[0].shape[1]:0,ga.inputs[0].shape?ga.inputs[0].shape[2]:0],!1),a.norm=me(a.resize,ze.tf255),a.res=ga.execute(a.norm),a.squeeze=_e(a.res,[0]),a.alpha=ge.resizeBilinear(a.squeeze,[e.shape[1]||0,e.shape[2]||0]),a.mul=ae(a.alpha,ze.tf255);let n;switch(t.segmentation.mode||\"default\"){case\"default\":a.input=_e(e),a.concat=at([a.input,a.mul],-1),n=He(a.concat,\"int32\");break;case\"alpha\":n=He(a.mul,\"int32\");break;default:n=Be(0)}return Object.keys(a).forEach(s=>Y(a[s])),n}function L0(e,t,a){var u,p;if(!t||!((u=e==null?void 0:e.config)!=null&&u.validateModels))return null;let n=[\"const\",\"placeholder\",\"noop\",\"pad\",\"squeeze\",\"add\",\"sub\",\"mul\",\"div\"],r=[\"biasadd\",\"fusedbatchnormv3\",\"matmul\",\"switch\",\"shape\",\"merge\",\"split\",\"broadcastto\"],s=[],i=[],o=t.modelUrl,l=t.executor;if((p=l==null?void 0:l.graph)!=null&&p.nodes)for(let c of Object.values(l.graph.nodes)){let d=c.op.toLowerCase();s.includes(d)||s.push(d)}else!l&&e.config.debug&&K(\"model not loaded\",a);for(let c of s)!n.includes(c)&&!r.includes(c)&&!e.env.kernels.includes(c)&&!e.env.kernels.includes(c.replace(\"_\",\"\"))&&!e.env.kernels.includes(c.replace(\"native\",\"\"))&&!e.env.kernels.includes(c.replace(\"v2\",\"\"))&&i.push(c);return e.config.debug&&i.length>0&&K(\"model validation failed:\",a,i),i.length>0?{name:a,missing:i,ops:s,url:o}:null}var Rp=class{constructor(t){ue(this,\"instance\");ue(this,\"models\",{});this.models={},this.instance=t}stats(){let t=0,a=0,n=0;for(let s of Object.values(ha))t+=s.sizeFromManifest,a+=s.sizeLoadedWeights,n+=s.sizeDesired;let r=n>0?a/n:0;return{numLoadedModels:Object.values(ha).length,numDefinedModels:Object.keys(this.models).length,percentageLoaded:r,totalSizeFromManifest:t,totalSizeWeights:a,totalSizeLoading:n,modelStats:Object.values(ha)}}reset(){for(let t of Object.keys(this.models))this.models[t]=null}async load(t){var n,r,s,i,o,l,u,p,c,d,h,f,m,g,x,A,y,b,w,S,C,E,_,$,M,I,N;ne.initial&&this.reset(),t&&(this.instance=t);let a={};a.blazeface=this.instance.config.face.enabled&&!this.models.blazeface?U9(this.instance.config):null,a.antispoof=this.instance.config.face.enabled&&((n=this.instance.config.face.antispoof)==null?void 0:n.enabled)&&!this.models.antispoof?fw(this.instance.config):null,a.liveness=this.instance.config.face.enabled&&((r=this.instance.config.face.liveness)==null?void 0:r.enabled)&&!this.models.liveness?Aw(this.instance.config):null,a.faceres=this.instance.config.face.enabled&&((s=this.instance.config.face.description)==null?void 0:s.enabled)&&!this.models.faceres?uw(this.instance.config):null,a.emotion=this.instance.config.face.enabled&&((i=this.instance.config.face.emotion)==null?void 0:i.enabled)&&!this.models.emotion?sw(this.instance.config):null,a.iris=this.instance.config.face.enabled&&((o=this.instance.config.face.iris)==null?void 0:o.enabled)&&!((l=this.instance.config.face.attention)!=null&&l.enabled)&&!this.models.iris?K9(this.instance.config):null,a.facemesh=this.instance.config.face.enabled&&((u=this.instance.config.face.mesh)==null?void 0:u.enabled)&&!this.models.facemesh?ew(this.instance.config):null,a.gear=this.instance.config.face.enabled&&((p=this.instance.config.face.gear)==null?void 0:p.enabled)&&!this.models.gear?ww(this.instance.config):null,a.ssrnetage=this.instance.config.face.enabled&&((c=this.instance.config.face.ssrnet)==null?void 0:c.enabled)&&!this.models.ssrnetage?Tw(this.instance.config):null,a.ssrnetgender=this.instance.config.face.enabled&&((d=this.instance.config.face.ssrnet)==null?void 0:d.enabled)&&!this.models.ssrnetgender?Rw(this.instance.config):null,a.mobilefacenet=this.instance.config.face.enabled&&((h=this.instance.config.face.mobilefacenet)==null?void 0:h.enabled)&&!this.models.mobilefacenet?Fw(this.instance.config):null,a.insightface=this.instance.config.face.enabled&&((f=this.instance.config.face.insightface)==null?void 0:f.enabled)&&!this.models.insightface?Bw(this.instance.config):null,a.blazepose=this.instance.config.body.enabled&&!this.models.blazepose&&((m=this.instance.config.body.modelPath)==null?void 0:m.includes(\"blazepose\"))?S9(this.instance.config):null,a.blazeposedetect=this.instance.config.body.enabled&&!this.models.blazeposedetect&&this.instance.config.body.detector&&this.instance.config.body.detector.modelPath?I9(this.instance.config):null,a.efficientpose=this.instance.config.body.enabled&&!this.models.efficientpose&&((g=this.instance.config.body.modelPath)==null?void 0:g.includes(\"efficientpose\"))?M9(this.instance.config):null,a.movenet=this.instance.config.body.enabled&&!this.models.movenet&&((x=this.instance.config.body.modelPath)==null?void 0:x.includes(\"movenet\"))?Mk(this.instance.config):null,a.posenet=this.instance.config.body.enabled&&!this.models.posenet&&((A=this.instance.config.body.modelPath)==null?void 0:A.includes(\"posenet\"))?Vk(this.instance.config):null,a.handtrack=this.instance.config.hand.enabled&&!this.models.handtrack&&((b=(y=this.instance.config.hand.detector)==null?void 0:y.modelPath)==null?void 0:b.includes(\"handtrack\"))?bk(this.instance.config):null,a.handskeleton=this.instance.config.hand.enabled&&this.instance.config.hand.landmarks&&!this.models.handskeleton&&((S=(w=this.instance.config.hand.detector)==null?void 0:w.modelPath)==null?void 0:S.includes(\"handtrack\"))?vk(this.instance.config):null,(E=(C=this.instance.config.hand.detector)==null?void 0:C.modelPath)!=null&&E.includes(\"handdetect\")&&([a.handpose,a.handskeleton]=this.models.handpose?[null,null]:await mk(this.instance.config)),a.centernet=this.instance.config.object.enabled&&!this.models.centernet&&((_=this.instance.config.object.modelPath)==null?void 0:_.includes(\"centernet\"))?N9(this.instance.config):null,a.nanodet=this.instance.config.object.enabled&&!this.models.nanodet&&(($=this.instance.config.object.modelPath)==null?void 0:$.includes(\"nanodet\"))?Pk(this.instance.config):null,a.selfie=this.instance.config.segmentation.enabled&&!this.models.selfie&&((M=this.instance.config.segmentation.modelPath)==null?void 0:M.includes(\"selfie\"))?g5(this.instance.config):null,a.meet=this.instance.config.segmentation.enabled&&!this.models.meet&&((I=this.instance.config.segmentation.modelPath)==null?void 0:I.includes(\"meet\"))?t5(this.instance.config):null,a.rvm=this.instance.config.segmentation.enabled&&!this.models.rvm&&((N=this.instance.config.segmentation.modelPath)==null?void 0:N.includes(\"rvm\"))?m5(this.instance.config):null;for(let[O,L]of Object.entries(a))L!=null&&L.then&&L.then(B=>this.models[O]=B);await Promise.all(Object.values(a))}list(){let t=Object.keys(this.models).map(a=>{var n;return{name:a,loaded:this.models[a]!==null,size:0,url:this.models[a]?(n=this.models[a])==null?void 0:n.modelUrl:null}});for(let a of t){let n=Object.keys(ha).find(r=>r.startsWith(a.name));!n||(a.size=ha[n].sizeLoadedWeights,a.url=ha[n].url)}return t}loaded(){return this.list().filter(n=>n.loaded).map(n=>n.name)}validate(){let t=[];for(let a of Object.keys(this.models)){let n=this.models[a];if(!n)continue;let r=L0(this.instance,n,a);r&&t.push(r)}return t}};function Zk(e,t,a,n,r){var o,l,u,p,c,d;let s=0,i=[];for(let h of e){let f={id:s++,face:h,body:null,hands:{left:null,right:null},gestures:[],box:[0,0,0,0]};for(let b of t)h.box[0]>b.box[0]&&h.box[0]<b.box[0]+b.box[2]&&h.box[1]+h.box[3]>b.box[1]&&h.box[1]+h.box[3]<b.box[1]+b.box[3]&&(f.body=b);if(f.body)for(let b of a)b.box[0]+b.box[2]>f.body.box[0]&&b.box[0]+b.box[2]<f.body.box[0]+f.body.box[2]&&b.box[1]+b.box[3]>f.body.box[1]&&b.box[1]+b.box[3]<f.body.box[1]+f.body.box[3]&&f.hands&&(f.hands.left=b),b.box[0]<f.body.box[0]+f.body.box[2]&&b.box[0]>f.body.box[0]&&b.box[1]+b.box[3]>f.body.box[1]&&b.box[1]+b.box[3]<f.body.box[1]+f.body.box[3]&&f.hands&&(f.hands.right=b);for(let b of n)(b.face!==void 0&&b.face===h.id||b.iris!==void 0&&b.iris===h.id||b.body!==void 0&&b.body===((o=f.body)==null?void 0:o.id)||b.hand!==void 0&&b.hand===((l=f.hands.left)==null?void 0:l.id)||b.hand!==void 0&&b.hand===((u=f.hands.right)==null?void 0:u.id))&&f.gestures.push(b);let m=[],g=[],x=b=>{b&&b.length===4&&(m.push(b[0],b[0]+b[2]),g.push(b[1],b[1]+b[3]))};x(f.face.box),x((p=f.body)==null?void 0:p.box),x((c=f.hands.left)==null?void 0:c.box),x((d=f.hands.right)==null?void 0:d.box);let A=Math.min(...m),y=Math.min(...g);f.box=[A,y,Math.max(...m)-A,Math.max(...g)-y],(r==null?void 0:r[1])&&(r==null?void 0:r[2])&&(f.boxRaw=[f.box[0]/r[2],f.box[1]/r[1],f.box[2]/r[2],f.box[3]/r[1]]),i.push(f)}return i}var B0=`\n/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUA\nAAABAAAARgEoAAMAAAABAAIAAAExAAIAAAARAAAATgAAAAAAAABgAAAAAQAAAGAAAAABcGFpbnQu\nbmV0IDQuMi4xMwAA/9sAQwAGBAUGBQQGBgUGBwcGCAoQCgoJCQoUDg8MEBcUGBgXFBYWGh0lHxob\nIxwWFiAsICMmJykqKRkfLTAtKDAlKCko/9sAQwEHBwcKCAoTCgoTKBoWGigoKCgoKCgoKCgoKCgo\nKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo/8AAEQgBAAEAAwEhAAIRAQMRAf/E\nAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAE\nEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZH\nSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1\ntre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEB\nAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXET\nIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFla\nY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG\nx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A+qaKACigApGOKAML\nXp8xlF5A7V4X8RtYs7PzfNImnx8sa8Kp9z3q2tEgp6angWs62ZZ5CTGoJ6DArGNz5p+UrID6EUrF\nPUlW1EuN0XNW7PQ2L5j3JnoKXN0KijqNP0eYoqXBdgPuuo+ZPeupisWn2Jd4+0r924XgsQOCff3/\nAJ1FzRKxDqGii6m3siiQ8F1XGfXI6YNWLfRbiRQMkcZI9fpTDluT2/h6Qy8gDPbtmtG38JeY480Z\n5zSLUTZg8M28YwYxjAArXtdPt402qgHbpSaLWhma3o0Uqk7Nx9DWLaaVblgPs6qRyds2M/gRSQp9\nzZOni2iWS2hlQ+kjYz9OMGrdjq89vIPPVhj+8M/lQyDq9P1WOYBlMZz1AOD+VdDaTiReOKulK0jO\ntHmi0WDTlr0TyxRVhT8tJjIX+9SUxHXUV553BRQAVBcPhSBTSuxPY86+IGti0s5I7dsORy9fM3i6\n8e8mfDO5P90ZrWWiJicNPpZZtxV/xrW0jQt4DOv6Vk2dEEdTY6BHuB25rpbPSo0QARjP0qTRI17W\nwA/hFaMWmoQMgflQXYsDS142rU9tpqqenfNA7GgtihxkdKuRW6qMY/GkDZY8sY4Ap4hXbyB+VArk\nEtuH4wPyrk/EGkOm+a3jw3suRQLc5i38SX9hJ9nnY+XnBUdPyNdFY6pa3KkkAE9l6f8AfJ/pSJT6\nGhDmI+Zb4ZRycdv6ium0nUhKFydrelTsNnS2829RnrVgV6NKXNG55lWPLIM81Op+WrZkRMfmNNzT\nA7GivPO4KKAEY4XNYWt3vkwPg4OK0giJdjw/xrqhm87Zs8tc7pX5A+leSajf6aHYJ50kn4AZpTep\nrBWRm2Vobm4BXfyehPFdnpmnBFUY5rI2SN63tlToK0YI+KZpFF+3QdavwoKTLtoW0Toaswpk5pCb\nLCxipAhoIuP2dKevHXoaYDylRyxhlwRQI4nxVoCXWZI1GfpXGtbSWjYPGP73+NIGupt6TqMsLruZ\nih4xnP5V09mQ+JLd8gn0xSYJnVaVdkook69K34zuUGunDS3Rx4qOzHVIp4rrOMY3NJQI7GivPO8K\nKAILt9kZrz3xlebYiu8KCCWb0XvW0NFch6ysfO3jLVjfXLIn+pQkKorl7WxNxIPl71g2dUUdpo+l\npBGvHPet23iC8ihFosrxirkHQUFo0IF4FXI1O726CpKLacCrMJoJLYHAPpTwucHpSRJJ5e4AZI9x\nUqpxzVpCuOC8cUpQUMRnXttuB4rjNdsYyeVwfXpmpGmcvcQyafMCFJjPY10eg34BUg4DcZP8jUO4\nHaRq3lLNF+IHet7R7jz7c56rwa2wz9+xhiVeFy/T1PFegeaNPWigDsc0ZrzzvDNIaAM7VpNqdegr\nxL4l6kywyRhseZ19lrdfAZL4jxYg3Fw20d63tJsdrDI5rm3Z3R0R0Mce1eKnQYAplIkWrMJ45oZS\nNO3PHbNXIyfpSGWowSOasxLUiZdjFSqtNEMkUemKlAGKsRJjAppFAiORMjmsTVrNZEO4cfSoZSOD\n1eJ7WXBUzQZ+7nkfSo7e2Ei+ZaMzxntjBX2NSU1Y6/wxqojiEFzkA8KTXYaUoWRyv3W5rSjpNHPX\n+BmpSg8V6J5gUUAdhRXnneFFAGHrTfu5PpXzj8S70/aZtxzztXFbv4DKHxHI+H4GZiz9zxXXW8G3\nGBXMjvLRXAx0oPGPSmMVeOnWrMTYpFI0bcg1fh54xmgovRcD3qxETSIZcRvzp+/BpEkqsBUqsM9K\nq4Em4Gkxk0yRGXrVW6i8yFhkg+tJjRxGsWrxllkUMh9eK5uMz6bcebbnfG33kPcVkay2OntPKuo0\nnhXI67c8qa7Lw3c+adjcEDGK1paSRhVV4s6A0or0jyRRQ1AHX0V553hRQBz+vNtt5z3xXzX8Qbdm\nuic5YnOMdK3l8JnTXvlbwpYl+WySOgrp5YfLOOB9O1c62O7qQkc+9RsKChFPWp4DluOlSykaNruH\nArUgHShFNF2NT1qxGO3NBmyxGcE1N2560CFzjrUysO9JAPDDjFOVuKoQuSRTWouBkazbCa3cd8cV\nwF7IISQccHBzUSWpV9C3o1x5b5GAjdQD1rs9DjC3kckbEhqKfxIzn8LOupRXqnkPccBSkUAzraK8\n87wooA5rxMSI3HqK8B8bQl9Q8sffY5b/AAraXwkUviNrw9pH2W1ViMMRTdRjw4HpWNtDti9TPc4P\nFQs2M5qdyyMHLcfjV63HTAoBGtap0wK0YxigpsuRDtVhVYd6GQydVwwIqdRnqKCR23I5pCMUW6gD\nYNKuetAEise9KTxQBWuFyhrznxNZkXjFeN3I+tTIZg2OqmzmxNF0PO3vXp/g2+hukVl4zyPanTXv\nJmVR+60dpThXpnlPceopWFAbnV0V553hSGgRynjC5FujOey14Ssp1HxNmTnc+a3kvcIpv37HoEYQ\nQmMdVHSsnVbYJF5jVk0dsNzlruVIsl2wKxbjWrVHILjg1CRbZJb+ILHPzyhfStODWLQgFJFYd+el\nUJM27HUIXxhga1Y5lLVLKLkMnoauxnPPrSEx7ShF+Y/n2qrc6xBbhizDAqkK1zJuvG9nbg8ZA681\nly/Ei052RO3uKAsZlx8QGd8xxvt9Aa1NH8dK7AXMcip64zigdkdrZX8F7EJLdwwNXMkrz1qRMRly\nCK4TxmpidWI49felPYSOMmi80NIoOV6qRzXYeA5SskYPfirpfEjGr8LPWVHyD6U4CvQPL3ZItOYc\nUDOoNFeed4Uhpks4H4iE/Z5MeleMeGULeLgjds10S+BGdL+Jc9OSBU2Huc5Nc74yvUtrcDBrJnZF\n63PJdXvLy/lKWw46bvQVz82jXhkLO5Y+9ZlsYthcRnbIjY9R3q3awTRkEM3WmJI6C0ea3dGRsr1x\nXY6TqW9FLHnjrUs0izpLK5DDjofSta3ckH09KRUkZuuTvFGdvPauE1Y3U6Mqbssf/rUxHPTaJPK2\nZmJPbBqzY6DCZh5xJC9s9aBJHU6dpemJjfEmfetJtI0+VPkUr/unFOxdiextHs33W07YHQHk11mk\nXb3KbZ1xIvcd6LEyWho4Nct41sTPYb16ipexCPPZN+wYGCvH1rrPAEJmvkPoc1VL4kZVvgZ6yFwK\ncBXoHkkqinFaVyzo80GuE7WJRQSziPiGdthK5HQV4x4J/wBI8WPIewNdEvgRNL42emO/yj1UHNef\neNpRczbC+I17DvWT2OqJxc0sMK4TCisy41q0hfEkqj8aixdwTXNOlwvmqD9anS9tXH7uVG+hosO4\n/wC0oOhrR0+6G4YNIEzsNEuCxAPNdjZruA4xxUmjINSjURksOlcbqFykbnjFA1sYGoassaknCqO5\nrl7rxhGm7yBnBxuJq0rkSlYpw+NLlsfd5P8AerVsvHEqSBHwPVgcgVpyMyVXU3rXxcHYETAk+hru\n/DWti6ZSTyOKzZqndHaxvvUGq2rQ+dYyqR24qWI8dvbr7LqDxyDAzXpvw6FvIxePGSM06Xxoyr/A\nzviKFHNegeX1J41zUhXioGbuaSuM6wpCaBHG/EcA6HN/exxXjXw2jL67cv8A3Qa6H8CFR+NnoWpO\nI4XI44rxLxrqjQzSEsQM1gdSPM9U1uR1YbmWIdXHf2rmpIb67YS28UrRlsLI3c/jW0VZGUpO5pW1\njfLNOjahawzwReYI5cjzMkDavHJ5/SrVv9uhtPtVxCPLBwzxnlT9KGghLU3tKvvPjHzbl7EGuisJ\nGRxWLOg7nRXJEbDjmvSNK+aFSfSoZr0KutRkphc4NcRrdkVjL9aVio7Hk3iqS8ubhrWzUlsZY9kG\ncZNc5D4aee5MclzJIFTzHAO0MfatqSOWu7bFS1srDUZEis0vIZoUxPvfcC+4/dx2xjr712XiTwXb\nWmlQ6hol3cRhoFd4rlg3zY5wR0GelavQwjq7GD4etdVvSnk2wAB+9v8A8mvcfA2kXiRo0/UdcDis\nZnTTulqeoWqbUAJqWUb42X1FZlnjfjSwlGrr5S/eNdD4RkvLAAQ4yRyaUZcruVKl7TQ9I0G+mnzH\nckFwM8VuIK7ac3KF2eXiKapz5UWYxipNtMyNejNch0jSar3cjR27uoyQCRVRWom9DxTx54gu5fMi\nlbKdMVjfCZPNlv5v9rFbVHpYqjGzbOn8SzFI9o715L4u0r7arYzk+lYdTqSujy7U/C0u4vHk+WwO\nxuh9q3J9dgvbdVukMV1EwbDDgn04rZMwlHoZ+orZ6hfQ3RWVnQYCgZAq+8U0ln5NtBsV2yxYcfgK\nJtW0CnB31LlroVwJ1nQLGDjeP7w+lb0dsFxjrWB0tHS6NuWPJ6A16ToUm63T3Gallr4S7cxiTjrX\nPaxaF7dlVeSMUhxZ5jd+H7qCa4eF3DSE5x3zXN3Wk6jbyeaiFWUY6ZyPStYS5SalPmVipFbX0E4c\nW0alvmPHJrag0rVvEE6LdljGpG2NRtQD+tW5XMI0uU9M8NeFo9PiQhecDIIrtrOMIoG3H4VlJm9t\nC6CB06VPGM1IHLeItGS6uw+ORT7e3jsbQvj7gzUNam0JaWE+HN7NqOqX80n3FO1RXo8YzXdS+BHk\n4z+KyzGPapcU2YIv7qQtiuaxvcaWqG4O6FwfSrS1JbPnrxoxkv7qIfejcitj4V2f2exumI+8+aKn\nxHTT+G5d8Txlm4rjLxMsQwzWT3OiK0Mm6sEkVsAcjFc1d+FEmlGwEDPQVopaEuOpr6f4ZWNAu3tW\nvHpAj5ZQcUFIWaDjGMVUMQ3cVDBmvbhY7QAV2nh+T/R1yeKhlrY31+b61FcQK6nIoJMi401WblRi\nqr6PCw5UYq9y+YgOgWzNkRrx3xWjp+nx2v3FQcelAbmko9anQ4GBUNisPHWr1qMrQhS2K11HvmYV\nhamcxSRZ5xRIqluS/DKAQQXZxyXrvo2FdlL4EeZjH+/ZbjNSZpswLNBrE1Gt7VE4ODVIlnh/j61F\nj4lmeTGyUbq6LwdEqWbeX0YbhSqfEddP4Bddj4JIrhL5d8h7VjI6oLQqKNzelWre3yc4/ClFjaL6\nwqBxxUUxwCKu5BmXRA6c+9ZjP83FSBoQuPs4BrsNBlUW659KmRrDY6G1lyQtW3Hy0lqQ1qVJnAbm\noy3b9KYJCqRj3o4zRctIlhjLHmpSuOBRbQOpLGpPFaES7UqkZzKN1KsEc87/AHUUmvPLTVGv72aQ\nk7WJwKmRrQ3ud74Ltilgz4++2a6iNDXdS0gjyMU71my7GpqTbxSbMki3SViajTTHqkSeR/GeyZmg\nnQHkEE1S+F+oPPavBL96I4/Cia1udVF+4dVrkW+Fq8+v4tjMDWUkdVJ6WM0cNV+F+MVmjUcZgqnP\n1qpNNnkcVRLiZtxIS1UzzIF7mghlxUZpVQdq6nTVdAoAOKzkbQWhvwM6gMM1twOJYx3NOJE11Kt1\nH1/pVVlwBkk+9NocXoOQ45FPj+fkUJFF2NSB700v/hTEty5ZpkjvVyUgcCq6GM9zC14/8Se6GcZQ\n1574Xs5WkI2HBPHFQ1dm1KSSZ7Rotn9l0+KPHIHNacae1dy0Vjxaj5ptlhVp+2s2CJ9ppCKzuWNx\nzSFc1SYrHNeNdIGpaYw25ZeRXmvheyk0jVpEdcLJ0q3ZxNKTa0O3vQHg/DNcHrsJDmsmjspnNzNt\nfFIJ24GazOhC+azDmgZIOOKBsp3J2qSaZodubq58yQ4QAnmhGT3NO18pb7BORmu205LfYpyKVkWp\nOxr5gKYWoIZWgfGfloFq1qTPLubnGO1RPtxg4P0oBAkY/hBz6VNDDkZ6AU0W2WSdqkdKr9ZOaGSj\nVtcLHmnOcgmmYvcz7mBLy3MbdD1q9ouiRK6bUAVeelOC1InPlidSsWMDFOCEdq3uefykqrinYqGy\nrFvApMVka2DAowKAsMkRXQqwyDXn/iWyitNQ3qPl6itIvRoF8RXinW4tQ6HI6GuW8SIVBPalc6qe\n5x9x97r3qruwTjrWZ0ksZ9TUmcDNAmZ9/wAoao63rR0+w22MLPtAzt6mghmfofiB76LdJBJBIp5D\nd/oa7bSdWLIPnpDi9TM8TeKdas51XTbIyxd3J/pXS+E/EFxqNoFu7do5OmD60maHWrnZyDRkn/69\nMlEyOR0xntVoNx+FUgYjPxg4FLCuWDZyKQr2RoRnP0qO+nEFpJITgAUzLqZnhu6+0rknOTXpOmwJ\nFbrt5yMmnHYyr6Oxb2ijaKLnPYMClwKQWK3n0hn+lachHOJ9pNNN0apQFzsY10a4v4hXQh0xpieQ\nMA1XLZNjhK80cT8OdV+3Wl3A7ZZJCw+hrR1qLcjZ/CsbnfHRnFXseHJArOYYbrUs1uPhYbuatqFP\nByfSkMq3UIINYkto+87Tx6GkSxfsDbflGD7CtTw/pk4nzITtPIFMFudsukh4Rxz71paTpKwP5jcn\n0qTRy0NORMDgVCqewoJTJgAoxjntTiTu7fWmFxAcnn1q3EPl+X8KZMi4gKqB1Peob/Tv7Us5bfeU\nyOoq4R5nYxqT5I8xieH9J1DTbvyJELRg8ODwa9Ms5mSFV9BWiptbnNVrKdmif7Q1KLg96XIZc5Is\npNL5pqeUrmMtZs0jzV08phchaY00zH1p2ZNxjS1g+LdJOt6U9ssmxjyGp2urDjLlaZzng/wUPDqz\nTSTmWeTrjpVjVk3Rvjr2rnqQ5dDvo1XUd2cTqSNk9OKxXGCeKxZ1DAxHTr2q5C/y8GokUhsz54qu\nuCxzSQjQ0+FZblR2ro4bZYiMVQ0dBb7Qi5x0qzuG5QOh71LYErDufpSeWrHnimIXbjkUjLkH1Hem\ngGxryc+tXI19KYmWegq9YLiLJ7mtqS945cS7QsWehqxA9dEjz4krPSxyZqbFFhGxUm6smjRM55Lk\nHvSvNxXTY57kLT+9MNwKdhXGm5FIbkU7Bca1wMEVhaiuQcVhXWiZ14R6tHGanGBI2OtYkqEHjgVy\ns9ErEeo6UBsHipKEZs5qpPdRxcbhx70NCSuybTNWihc5brW9Fq6vjMnFSdEIdDRi8RRKygZbHFbu\nm6nb3RA3gMegNJhOm0jbXGOoxTuCc1Rz3FyoGKawz9KaAVcZqeMgCmIkB4FaUTbYwB6V00Fuzixb\n0SFMuDU8Mlbs4UPeXHeiOXkUrDuXYnyKk3cVk0ap6HMxxketSMhrcwRC0dMMZFMQ3yzSeVQAeUaz\n9Vj8uPd271nVV4m+GdpnHX67pCeKyLtBtNcR6xlk9RVeWTb3qRnO6trgttyIfm71z7ai8j7/AJmN\nDNqUVa5Yi1AnjynHuBV+11YJhWWXcP8AZNSzqgmaEerSsf3NtIQP4mGKtRavdRgMIpVI9KjU0a7n\nR6T43uYQI7qN2Tpkqciu503VVuQGAYZHQjFVc4alPlZrpKGAznpTwxOc9+lWjIlUACnM4XApiLNk\nnmvnsK0NvpXZRVonmYqV52GsmanhXitTmFkSiJTSAvwrxUxXIrJ7miOfjf1pzNWxkRlqYWpgJupu\n6gQbuahvIxPA6eo4pNXVioS5WmefakGhndH4INZs5DJXA10PaTurmLO21uKpSZqGMoXGnRzBiyjd\n9Kx5rcQS428fSkjanLoaOliHGZFB56VswW+mtPufcBsGOAfmxz+tFkd8HpoaUx09FAtFY8DO71qb\nSms/Nb7RbecG6AEjFLS5c78t+p0djpVs9wsyQiJAdyr1rW+zqjErzSe559Sbk9S3C+MA1bjbgE1S\nMSXzMVG0vNUI2tPKrAuCMnrVzNd0PhR49W/O2xrHmp4TxVMzQshpIzzQBehqesnuaI5VGzT2bitz\nFEbNTC1ADS1JupgG6l3UAc14s04yR/aYRll+8BXCtLncDXFWjys9TCz5oW7GddH5qqNzWDOgQnC8\nVSuo1kHzAGkPYopEY2+RWxV23Vzj5G/Kg3jWaNazhZuqNXS6TaKhB2c0jR1nJWOlhOxRxU4YkCgx\nY0OQatQyDbyaaFYe8uF4NY3iC9ltbVGj43NTIL3h7WzMihjzXVQXYYDdW9Cf2WcOJpfaRZ3g9KsQ\nmupnCLIabGeaAL0LcVY3cVmzRHIxtUhetzEjZqjLUAIWpN1ArhupwagAfDKQ3Q1594v0c2bm6tx+\n5Y8j+6ayrR5onThp8s7dzkZjuqAAmuBnqC7c0iwgtzSA0rWzjfGRW3ZadDu4AoNYo2rfS4v7orSh\n05UA2r0pDbsTm29KRottBNyJ0wpJ9KhD7f6U0ikNWffIFBz60zVUW52ow4UcUN6EPcx44WsbgOmd\nua7TT5Bd24KHnFKnLlZFSN4koluLdueRWvp14swweG9DXoxldHlTjYtzGoo25qzEvwtUxas2jRPQ\n5CNqkLVsYoYzUzdQA3dSFqBBmnqaBhuqhriCXTpVIzxUz+Fl03aSPI9QTypW2/dz0qKNw3SvOPZR\nMqin8VLKRcs3O4Cuk0w/MDjt1NBtHY6O2IIHY1pxgFaETIRwMkjtVSUEk4570MlFW5bap6dKzWm8\n1tqH8aY+hp2FvGoGayNevVt7/ap4xzUvYjqTLtvLPcvJxSaVcyWsxTnFZlnT2t15xHmCtOBYwQy4\nB9q7cPO+jPPxFO2qLEj5HWo42+aus4HpoX4W4FTF+KlotbHII9SFuK0MUNZqiLUDE3UbqBBupwag\nBc1DefPbyD/ZND2KjujyPWlKzuPesRZjHJXms9lMuw3StjnmphKDSLTJ7OfE3JrpbO4GQc9qlnRA\n3LO82k5NbFvdADkjBoCSHyXIIIzgVQvdRigT7wzjgUzO1jHknlvG7qnp61etYFQDIpCZoqVijzXn\n3iC8EmsOuaCGb/heR/s0ijkVv6fbxy3QMg5xmsnuX0Ldzut3+UYTPWk+2GJSe+M1pFtamcldalmx\n1eO4XaThhWnC+TXqR2PHqL3maUJ4qRjxSEjj42qXdxVmaGs1MJoATfSbqBAG5p6mgAzTJTmNvpQU\ntzzHXY83D/U1zF5FhjgV5r3Pa6FMsV5HWnLe7RhqBRdmTwagN2d2K2rPU1C5LAnPrUs6Iysbdrq6\nf3gK0BrUKj/WClY05iM6xLOcQAj3NT29uznfKSzHuadzNu7NSBFjHNSm5VO9IRnajqoWMhTzXFtA\nbvUfMduSeg702Qz0rS7FbTToQFwzjJqaGTFyfK5PQViyzUuFmuIdgGABya5u/vTaN5cnUHFUmLoZ\nzyskwlgJweSK6zQdUEwVJeGr0aUrxPLxEfe0OrhPAqVjxWhznGRtUwatDK4jNxURbmkAm6jNABup\n6tQAFqhupNtu59qUnZFwV5JHnWsHdIx96w5lz15rzT2uhRmt85xWbcxMnUGmZlB0bdxmrNvFIcfM\n350mWjbs7YkDJY/jW5ZWW4jikWkdNp9mqYJFaJdEHHakUULu/VB1rLn1Ld/FgetMGYd/qWSQmSa0\n/AemS32pfa7piLeLkg9z6UmQtz0W7uQ2cZx0A9BVzR7cAea6j2rPqX0L99KRat5A6Dk1wOoKZ52a\nYfMORTYRLujiGWEq6/NWza2yKQVHNdOHerRy4laJo6TTnbbtb8KuM3Fdh5z3OJjbmpt3FaMxAtUZ\nagBN1GaQBzTwaAAms3VbjERUGsa07RsdeFpuUuY4jUjljWTKK4j02RE4IpJYFk6imQkVl0xWarsO\nmAEcUi0bNnZBR0rWtoguMCkUi21wI161mXuocEKaYXMS4u+pY/hVCSWSY4HT0pEmlouiSahdpEBl\nmOceleiwWcNjClvHgJH97Hc1EmVFFi3Czy7mwIl/WtJbjP7uLgd/apQ2VNVvtsBhiPzdK5S4nAuR\nnqOCaTGi9pcytPlU+XpmumtWII44rah8ZjiNIXRuWeNvvViQ/LXpJWPJbu7nCRvVkNxVsxBmqJmo\nEPiXca0YLMuOlJsuKuPlsSi5IrNuG8s4HWs5VEkbwoOTKsk+FJY4rC1K53k1xTk5O7PSpwVNWRzt\n4cms+WpKICtSLTETQj5q0YeBSGiys23pUguGxQMq3E59ayrm4x3yaAKiRtO2WPHcmhruKFxFajzZ\nScA44qRHoXhuMaLpxaUg6hcDLMf4F9KlhuDeXGASIl+8azZslYma68y48m1+7nFW5rtbRNhb5z1p\niMKbUg0zuW4A4rPgb7VdKXOMmpA7HRbMS7nUYiUda0lkQOBngVrS+JGdbWLRt2bAx5BqeQ/LXpnj\nPQ4GJ+ashuK0MhWaoWcA0AaOmASMK7jRNPWYBmHyiuepO2x10qfcv6vYxCzYqoGK4HVYVTJrmb5l\nc6oaM5TUJ8EgGsG4kLNUHT0M64OaqMMikSRsuKbnFMRLG3zVehOaGNE445NNlnVFpDMu6uie9Vo1\n8z5mOAOST2pDK91cNN+5tsrH3PrW54a06KxT7fdrlh/q1Pc+tJ6IUdZGvHPLezMcnBOWbsPap5r3\nylFtbdT1xUWNWzU0/Zbwlgfmx8zGsHWtRHmMqE59aAMyNifvHPc1f0gtPdqkY5JosJHeNci2tktY\neuPnNY+oXWZEVJNrZ9aun8SIq/CzodHuriIokhDIR1ronbKZr0o6o8ipoz//2Q==`,W0=`\n/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAsICAoIBwsKCQoNDAsNERwSEQ8PESIZGhQcKSQrKigk\nJyctMkA3LTA9MCcnOEw5PUNFSElIKzZPVU5GVEBHSEX/2wBDAQwNDREPESESEiFFLicuRUVFRUVF\nRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUX/wAARCASwBLADASIA\nAhEBAxEB/8QAGwABAAIDAQEAAAAAAAAAAAAAAAEDAgQFBgf/xABDEAEAAgECBAMECQIDBgUFAQAA\nAQIDBBEFEiExE0FRBiJhcRQjMkJSgZGhsWLBJDNyFSVTY3OSNEPR4fAHFjWCokT/xAAYAQEAAwEA\nAAAAAAAAAAAAAAAAAQIDBP/EACARAQEBAQADAQEBAQEBAAAAAAABAhEDITFBEjJRIhP/2gAMAwEA\nAhEDEQA/APqYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAKNTq8OkxzfNkisQC8eb1XtRNbzXT4q7eU2nu0MntRq/D8StMccvW29ZmdvgjsTyvZjxOLj\n+s8WLxn8TFPXs6Oj9oct7c14rkxz22nrB2I49KOdTjelmszfmpMeUxv/AA28OqwZ4icWWtt/SUi4\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmdo3nsPNe0Pt\nFh09Z0+DNWL7+9O/7A3eJcZppsV5raI27esvH6jX5ddM25p79Ilo59VbUZOe2Tm/PeGvfPfT2iKR\nPLv1+DO678XmW/a97U6TtOyzTbTF538/T9WjTNecm9a7126tqk3rSYxY5ta1plRZqZNXGjyZcPXl\nmZmsx+qjBrsuO16xM7eXRt04JrdTltk5OWJnfaWf0a2lty5MdZnfzSn+WOHiOutFpjHa9e8bQ2fp\n+alYy462pk7zXbuxjPesbRS0f6ZZV1ET1tErzXFLHo+A+1ddZf6NrI8PJHa1vN6iJi0bxMTHwfOa\nzhzd61v1846utwniM6DUdb3nBaNrVmd9vjC/ZVePYirBqMWppz4rxaPgtEAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAItaK1m09ojcHnvarjM8P0vh49+a/eY8ng9D\nh1fGM1rxjtGPfvbzdbjuTJxHX48cTPNltM/KsS9Dw7S49Jp6UpHaGe2vjz1y9J7LYK13vHWe7bj2\nex1tvM80ekuxW3RnW3Vm6P5jRx8H0+OYmMcb+bapo8GKPdpC6bQwtdHU8JpWkdJ/JweL6e23iU67\nd4dubSqyVi9Zi0bwIs68XGp36TtEq7ZJmZmevzdbifCKWtbJinkt6eTgZPFw32t+sRurbWVzxs1y\nRv6T8V1NZNPtfq0seTm+Kevr+SZuxXjvaPiV8N4viycto9HseG6+uu08W6Rkj7UPmFck1tE1nlmP\nLd3eA8V8HVVi1pjq6Ma/pnqce/ERMTETHaUrKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAADW19+TQ5p/p2bLS4v04Zmt5VjeQeJ4bjnLqsupv+Ka1+ERLv4reTmcNxcuC\nvy3l0qdI2hlr66sT02ot0ZV7qqrInruzrVZLGSZ37JjqgYTG0K5lbaFVhDT1Ub456RPweY4hixWi\neSdpjvD1eWejz3FNHWYtkpvFo9EIseb3tS3SerOms22rfpPqZKzvvHSYUz70TExG6Gdbs2rljeJ/\nMx5L0vEzPaelnOi98c9J2bFNTFpit47+a+PVUvx9T9nOIfT+GV5p3yY/ds67wvsXqpxau+G09Lx+\nr3TqrEAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADV4ljnLw3U0jvO\nO0fs2lWqyUw6XLkyfYrWZkHldBEV09eveG3Fq1mI3jd4vPrOIaid8G9MP3Y38k6fNrt/rMk9Ou8s\ntfXXn49rGWInuy8SO/k5Gl1E3rG/fzbOe94wTy99mbRvTrMOOvNfJWsesywniukrG/jU6fF43WYN\nTmtEeJtEQ06aSmK2+bNtEd+qfSO17unF9Hmvy1y13XWyVmN4tExLxVK8PmNq5NrT58zawam+m/yc\n0Xj8NpRYSvQZ7xEOdqI3rPozxayNRXe0ct/ON03jmrKB5nV4q1yTO20Obmv4c+cx8HoeI6WZpNoj\nq83niYmYscU0r8aJ6T1n49zeJ+Meqm1drb9J+Kd5p136StGVem9l9TbHxLDFp7W7+sS+q1nesT6w\n+PcAzVjiGHftzQ+v4f8AJpv6On8jH9ZgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAABp8VrW/C9TW0ztOO3b5Nxp8VmI4bn37TWYB8f1HFtTfUfR9FWJmsdZ9I7MtJxDX5s\nd8ta1y0xzteaR2277rcuhycP12SceLxMeWNpjttHwlu8I0mfQ1y+D7k5YmJmY36T36Ka43z/AF1t\ncI1ds+qxVj7/AEej19PCw9HJ4NoK4OIU5Y35YmZdzVTGebVZabx5jJS+Tmns81rNLm1Wrzc9rVw4\nYibbem72mXTTS0w0M3BvEta1bWrM95ie5EanY87wXgNOL6XPfxraXLhra/W28bR/dzYzarBqJxRe\nbzE7Rt5vWU9n8mPHOGmS0Ypnea1naJb+k9ncNLR7u2y/WcxXO4TOoyUrN6zD0FaW5Y3hu49FiwUi\nKxCvLMR0hlW0jn6ukWw3iXjOJzbDlneOj3GaN6zDzfFOH+LE7SRGo83XNSZ2lbG2/WfdlvaT2cy6\nrNFInlrv1mfJ37cK4PwTTxOoidRm2+/2/KFuyMp47XB4LivXiunrH2b2iH2qn2K/J8x4fGDNxTSZ\n9Nh8OviRvTyfT6xtWI+DeXs9MNZubypASqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAOZx6/LoOWPvWiHTcf2hiZ0e8fc2mf1E5+vP/AEeuSd7RC2uKtI6QjHfeINTfwtPf\nJvty9WPfbt/lucP03gxfJf7d/wBoReYpm97zaNeLb4Ims9Nt94auDjem1Wo5PFi1onylS+1o7l8V\nbxvtupjDMdNkYtXS1+Stt+m63xImEJ4xjHER2ZxMUjeUTO3VRmydBbjLJqPi08mbeVOXJPq1sl5Q\nVbkz9+rRy35rxHqzmZlVEe/Ez5LRlW5iyfR6zffaIjq1OSNZps2a21rZInafSPJhxGMl9LStLRWM\nlorM/A4dkrWbYfLZC2W/7K6eubX6b4RzT+W76K8b7G6X62cu3Sten59nsm3j+OXz3/0ANGIAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0OIYfpOHPijvNNo+fdvtXJO18k/\n/OwPFYbz2ls3jx8VqW6xMdWPEdP9D4lkx/dt79flLLHbkxTPwY6nt2512ORTRzE2x4/dpE7cvkme\nE4IrW3hRMxO8THRtU1FKWtvtvK2upx22rzRCtXkqzh2jtF7ZbT122b01ndnpuWuP3Z3+Ky20qDVv\nfauzVy3mejZzNK8dVjqi87KLRLYtXruqvXzkQp7Qoid88R6rcl+WGlW0/Sa22mfhCZOq2x082ix6\njkm822pO8VrPdr4dNObVeDo8XW3uzMbzK+mvxT7szE27cvnu9j7PcNjSaXx8mOIzZevbrEeic5tN\n+SZnpt8J4fHD9HXHO3PPW0x/DeBtJxx29vaAJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAKNRim9Z5e89Nl4DzXtVh5babURHrSf7f3ec1+qnDorWrvvt5Pccb0n0zhmWk\nRvevv1+cPE2rGTFNZU26PFfxwa5dVkjelI2772nZnX6bbrEUq3o0d678u8wmuDL2ittvVjXdneeK\ncGv4jpJ6U56+kS7+j118+GLXpakzHaWlp9NNY3tv+bbiYiNoQy1y30uyZJlrWmZnuym6q1iIJnop\nyW2Te8bdWnnypQqzZOadokiIpSZntWN5lrxki19vNRxrUeBwnNNd+fJEY6/OejXLn3Xe/wDp9wyn\nE8uo4lqqxblv7lJ26T6vpD5X7G8QycKzeBMbzMRM1/FH/wA/h9QwZ6ajDXLitvWzRgsAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeL45w+dDrZvWv1OWd4+E+j2jX\n12jx67TWw5Y6T2nzifU+rZ1y9eHwzDYxxEy18+DJodXfT5o96vafWPVbjyxDn1OOzHudbM0rt2UW\niI69mVtRXZq5tREb9VUoy2iIlRbJ0UX1VZ6btTLrI7V6yk62M2oisT1c7JmtkttVMUyZp6x0beDS\nRWOvdKijDimvWd3G9pNRMfRcNfvZOb9Hpb0itJeP47k/3hgjaZnbaP1XxWW3T0movbNS0W645nbf\n0nrMPpXs3xamoxdJiLbe/X1n8Uf3fKsOTw4jbaXo+EarJhtGTHMxeJ6xH7Sti9Zaj6x3HM4NxXFx\nDS1mtoi8dJrv2l011QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAGjxLhODieOIye7kr9m8d4eM4to9RwjPXFa0ZIvG9bR0fQXmPbDFvTTZPOJmEWS/V8bs9R43NxLL\nG8eFbePg1bajU5/s0l1ceKLx1hbjwRE9mOpx0y2uRTSZsm3PMw2aaKtIjo6kYo9EXpET0hVLXxYK\nxC6MZvyx1lFs0RHfaPiCnU12pLyHGNDbUajBekWma2npWN3p8+opa20e9LSyZLxExTlpM+vdOdcZ\na9tPS8MyUvFrzWlI6727u1pYxYrbVmb7x+TQx6au3Nqcl7/0rcmW9axGnwZJj1novmxnZXV0fFp4\nZxLBPgTGK8xzXr5fOH0bFlpmxVyY7Rato3iYfNuG2x56Wrqa8s2jz+7Lu8O12bS6jkwzN6THNNI6\ntvrN68Y4rxlx1vHa0bskAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAA4XtTTm0OKfTJ/aXdcL2pyRGjwU362yb7fkJz9eTxxyZJjyltRXzUZK7TFtl9Lbwy06YzrHwa+\nfJFd/wCVt8m0bQ0eS2qzcm+1K/an+zNZFL5M1pjFXeI72ky48eGnPkvNp27+TPU6nHpMfLXaIjpE\nerk5dRMxOfN1mPeisfshW1ne1a1577Y6x5R3U0zze31FOWI6ze0byU098kRlzbxM9qrMlPDpyRMR\nMd5Vt/Ihp5898mWZm1pjftE91uCt7fCI7dWeHDEW3t723l6rslqxWZnasR+SYhFbzhnfxJ2jyeq9\nlcGXWZcmW0zWKxHLaI7794eJx5fpfEKabT8t8l5isddo3l9S4VjrwrRUwzSJt3tav3pdOL6Y6dXD\nj8HFWm+/KsU4NRXPvtWazHquWVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAa+fXYNP9u8b+kdZBsDkZOO135cWOZn4y5Wu4xqctbe9y19Kp4njt6vi+PDm8DFMWybbzPlV\n5PiGtz67UxbNbeKTtWIjaIXYpnwuaftT5tXJT3vmi1pMsrU5qIrG1V1a+5DCa7b9GFbRr5J6Wnbt\nCu+Wmk0m8956z8ZWZNorbfzcbX5rZslazPux3hUt41NTntktObJ13+zX1bek01r4/HzVm0bxPXy/\n+bNfDgjVa2uOY92kdfg6ufJOKvLXtttVVSqbcta2vM7zXtHpLQy5ZtMd+vWd+7Zy3mdJHXra3f0c\nvUarw7zFY5rT2hH1Lavnrgx81p3U49Pk4nE5L35MO/StfNRXR5tXnrS8W67WvfyiPSPi7uLHFK1p\njrtSsbR5Lc4RzsXBaYreP4l45esRD2HD9fnw6evvWvO3Tfr0aGk0U55ra0TFInv6uzgrXFXlx0i0\n77RPlC83Yj+JW7oddqr6vHzTTw9/f6dod+L1t9m0T8pcbFSmPHER3892W0zPuz+jSbVvidkcqmfP\nSel7bekrI4n4dZnPWIrHeYnZee2Wpy8dEaml4npNZblw5qzb8M9JbYgAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAABEzFYmZnaI7yCXL1XGa0jJXT0571nbee27DiXEprp8nhbxG20W8\n5cbD0ikfnKO+urTPvjoZdXqctdsmTaPSvRpWmsdZ6yztfaGplvv3lWW1tyRlz1x0vkn7Vo5atTNe\nY0+1o79V2KsZsvX7Ne5mwxnyTNvsx2iGneM/rCdRSuOsTasTt5kRFtpjqmOH4t4nk7estiMNa97R\nHwhna0iuKTEdmGWa4672nZtRele1N59Zlq6vLOSsYorEc07qcW65euzRvtXvPZy52naZ7ujr6fXV\nrWdukREK8+njHgmZmPc67bq6ivVWhxxgxZLztNrT1mZ/SP4VZs0zaOvfp84WUtNsXLvtv3699+rU\nz7+Jtt5qURqMnPpctaR1rMSw4ZoK57eNk6xHaJRh97Ltt7lo5Z+L1HAPZvVauZ2nFTSzMTzeJEz8\nto6xPfvsZntPZ9rXxabmxzefdrv0j1dXh/BcmstW1qxTHHasR3+b0GPhGl+kWmd64dNEVjf73T7X\ny8vy+Ddx6O3iRakxTH5RXrMw1/lX+3Itw2MFIraN48qRHdZi0cUjmmPen9noox1iO0fNzdXEYrTt\nstcmd9aX0bJ+HePmiKTitO8TMLZ1cVjrMfqpz6ys4pjfrPRWZ9rXXptUit6zO+23VyaRHEc05L1/\nw9J9ys/en1ljqdVbwYw452tlnl3jyjzbmmiMeKtYjpEbLeTXPUU8ee/+qjJpsV5rbkrFqzE1tEbT\nDpYNbW21Mnu29fKWna0KbqTdjXXjld0cvQ63ltGHNPSfs2n+HUbS9c2s2UASqAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAOVxPWe99HpP8ArmP4b+r1EabT3yT3iOkesvMVtN7za07zad5l\nXV5GmM9vVfEstvDx0jtaVVMlq+UJ18b5cMRvPeSuK87bUt+i2Z3PtG7zXpjkzXt6R+TXyTMzvM7t\nydHqZ+zhv1+Cv/ZuqvPTHMfOYaTMil1a1K2vHSLTELq2v+KWzThGo84rH5rq8JzedqR+ZeI7WnOS\n34pYTafWXR/2Pln/AMyrKOCWnvmiPyR6O1y9585lhWJvl557Q6eo4T4dYiMvW3b3UanhldHpJtGX\ne09unmjsT7eb1l4trI2t0hsZfrdNO0bzy+nzU20/+NmkzO9esz+TZxWis9dttvPv+Tn21jjaW8zn\n26bTG3mp1M/Wzv3t0jyWXiKZJmsTERaZhXXDbNl8WaztWenxZLstPp5pau8frDtVrNMM5cfTfpMf\n3aunxxbes9d/R09Dp8ebJi09ptFr3jtt2WyrW9wy1Jx132mK+Xq9PotT0iIU19ntLtExa3T47T+q\n6nBaYvsZstZ+cT/LeMnUi0TXffo1s2m8Ws2/OIMWk5Jib5L328rS2t94Sh5TV4ppklpW6PT6rh+P\nNbebTHyas8E081mZy5P2W6OFhjxNTE/hr/LoRO0Kvo9dPqctKzMxEx1la5t3tdnjnMs4noievcrO\nyZjeFF1OSnNV0OG62cn1GWffj7Mz5w05joovzY7xes7TE7w0xrjPeex6Ua+j1UarBFu1o6Wj0lsN\n3JfQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrU5o0+nvlt92P3BxuM6nxNRGCs+7Tv8\n2hToxm1r3m9utrTvMsonqyt7XTmcja0u3O6FMfi5t/u0/lzdJM81p9O3zdvHTwsUR5+bfPqOfX1h\ndqV+3O7bs1+T31oqmI3TEM4rvCdkDGIIhlFd2daboS0NXG2bD6bufxXU1vlmu/u4us/N0+L1tTSx\nkr9qk7w89j1FNZMV3jxLzvaJ8mer+LSOZqK2xZotbvljfr/89U453rXt9lse081xZtNjx7TGKu0t\nDHlrevSevaN5Y6+tJ8c7VRNMt63n3ub+6/R54rERMztDYy4a5omclYmfxKcenrjtHLvtPrCnVmdb\neFe3JXmjy6eS/DrMuLVYsta9Mdt++6qLxO+0dEc8UmInr18iUfReHcXrqccb9Z27Q61Lb13eJ9nc\n1Z35rTvE9avY4bTkpG8xEfB05vYxqybc07R281naGMREdoT5JQqy9mply7Q3bV3iXG1eXw7TWSka\nc258t7+tpT5/BjT7MfHqndz12Z+M4lMMKyziUJJiN1WSu9fku23RaOgKNJqbaTU1t9yelo+D0cTE\nxEx1iXmM1Nt3W4PqvFweDaffx9vjDbGvxz+TP66QDRiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAOJxzU73rp6z296zsZMkYsdr2naKxvLyObNOfNfJbvad1dXkaeOdpvsc2yuZVzfbfqybutwu\ns5s8R92J3dvJb3tnO4HSMegtmt3nfZvYp8SZl0z45NfSK7onH1bNcfRFqnUKJr0Y7dVtq7prjEsK\n0XVpEM6028mW20IHK41aPo3J6zs4ODhdcvPnvExFevNXpMOrxi/PlrTee7PLX6Pwa09uaNlKtHg9\ndM3z5d7ReOu02nu0JzZMfblrv5R5uvrcdImZ26T1mYhxs1Os7RH93PZ7axuafNfLitvbaYU3yZYt\nPXs9NwHhui1HBa5LVicsb81onrEuVqNNSuS8Y67dZ6xPZa59Il9uX41vEitImZme3q2Kxbxora0T\nMd/ROSa4Ztkj7c9OafL5LuGYubmyX3iu/TfbdSfVnpvZLT/XZK233+Mbbva1xRXyiPk8pwbH4N6T\nadq5a71n0tD1WDL4tPe6Xr0tDpz8YVnJHWEXYxbqlBedoef4tW0XraO09HdyztSZcbUz43C+ee9b\nSVMaeOfqq7+jGckQ1Yz7+7v2RN/WXPXZPjci2+2yyJaVMuy+uSJlA2d+pNoVRbeDcSxyTE+TDDlt\npdRXLTynrHrDOyiyZeVFnY9TjvXJjres71tG8MnJ4Nqt4tp7T1jrV1nRL1x2cvABKAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAHJ49qfD09cNZ97JPX5PPw2uI6j6Vrsl/ux7tfk1mWr7dOM8iLdm\nvfebREefRsWldw7SxqNbWbR7lPesrn3Vteo7dYjDpMGCvfbeXQ0uLlxRLRxROfUc34p6fCHYrXlr\nEejqrjY8uzCYW7MZjdVKqK9VlaxCYrsnYExBMRMJRPZA8/xPHtmpP9W2xx76vhWOInvt/C7ike7N\nvwzE9kcapGfhlevTaFbFo8RqJ5vy8/RoW09ek0msxHfp3dzNoLzp4zUmZpMbT8HJyYJi20X2n0lh\nZY1li/RaidBF4w2mK3jrHaFGp1lN+tptPp5IjBkid5mIp16TKu0abBPv33vPlM7z+iPdFNcWXU5I\ntkrNce/b1W5db1nTaf3ax9q0fxDW1ebNk2phty1mOu09VOm8W19orEz23j1TwfSeERFuEYMddptW\nd43dvBn21eKJ75KbW+cf/JcTgMxXTb3nbljz+TpcPmc2uyZO1KRtVtGVdi0bx07qJnllsRO6rNTe\nN4XVamsy8mnvPwc3R2jPwe8TPbdlxXNOPSZfhWWpwO85OFzv57qrODkzeHntSe8Sn6Rv0a3EZ218\n8nXekfr1a0ZLVnqx19dWb6demXybOO7lYMvNMdW9S/VVLo0us7tPHdtUtEwJiZU3jq2Jhham8CVG\nPNODNTJXvWd3qcWSubFXJWd4tG8PK3pPd1OB6veLaa89Y61/u2xfxh5c/rsgNHOAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAANLimq+i6O0xPv392rdeZ4rq/pOqnlnelOkIt5F8Z7Wj27I2I6sb25YY\nV1ImY3dbQ08LRc23vZp2j5OJG+XJWle9p2h6HHtbJXFT7OOIpX+7TxT31j5rycdTh+Dpz+XaG/sw\nw18PHWseULN2trBE9UcrJKBhFU7JAQi0dEomegNDUYovM7x3jb5tO1ZvpbaTLtzRExWfWPJ08kbT\nEx5NXWYYyV5omYtHWJieyeDzuizfRs19Jn6TM7Ru1uMcJxZqTkw+5f4ebqa7SV1MR4tdrx2vEfy1\naxqsNOTLjnLXytVXi3Xj8+nmsxTLM16d5npPyUzpekTtSK+U7vS6vQ/SYmK1vWPS1HOn2dvvvvE/\ntDO5XlcO+LbfHSd/W3o6/BdDOXPTnj3Kz38rS6Wm4FNrRyRzTH3p6RH/AKvR8L4dXSzE3jmtHn5I\nmbfqLV+m4dbLSsZInHjr3iI6zLpYaxS01rHuxHRHiT9mv6s67Vj1aqL6326MrWiYa+/Q54BxPaGe\nXRZpj8MquB4+Xg8zPnB7SX30to379GxpK1xcHiKz5IS8xr8PLPixH2bftLTy05o6dHYyVjLhy0t1\nizjZa3pMVv3iO/qz1G2L+NbSajbNyW7xLsY8kTDz+fJXFqKZN4iZnafi6WHL0iYlStI7OO+7axW2\ncrFl7dW9jvE9ULN+J3ZbdFGOy+AYWpEqN7afNXLj+1Wd23KrJVMvCzseh0+auow1yU7WhY4fCdV4\nOadPefcvPuz6S7jol649Tl4AJVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAV581NPhtkvO0R+4NPi2\nr8DB4dJ9+/7Q83Po2NTqLanNbLfvPaPSFDHV66sZ5ET0hRknyW2lTtMyouz0c8usx2n7s7vScKwx\nzc1vu/y85p+maJh6Th+SOWeveXR4/wDLm8v+nX5mUWa9bbrInolmu5jdTNkxYFk2Isr3TuCzeGMz\n+THdEyDDJO9Ja823rt2XWnya946pGvktDXta0ztWu/ybvLE9dkcoOf4GbJPWK1j49VmLh9JtE33v\nMevb9G7WsW8l1ccREISophiJ2jpDYpijbaOjOuOJ8ujOdqxsgVcsUjaETYvbaFFrgu5lVsm0yUtu\nryg43H5m+GIj1XcJzePoL4pnrWGtxmfchr8JvfHS1622if3QljzTTLes+qrNjrkiYtCzPMxnm095\nYZJ6boS5teB49Tqscza97VtvWvlv8V/FOF34RrIxTM2xXjelp/eHoeA6XnzReY3ivX/0dfivDcfE\n9HbDbaLx1pb0lOs+jO7K8Lis3cN+0NKcd9PmthzV5clJ2mF9J9GHHVL108dm1SznYr/Ft0tuhLb8\nmNohFbMhLWy0mJ3rPXvDvcO1karBG8/WV6Wj+7kWrvDDBlvpdRGSnbzj1hpjX4z8mOx6UYYstc2O\nuSk71tG7Ns5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZ2jeXneJ62dVl5KT9VTt8Z9W9xbWclPo+O\nfft9qfSHEU1pv48ftYST23ZTDC/p0YtlVuvVjMbM5+LCZjYGWGdrTPxiHY4ffaf3cjTxz1v6xMS6\nOlty2iXVj/Dk8n+ndrkhnGRo1v8AFdW3RCrZ5uiYsqrboncSu508yjmZRYQt50TfowYTbYGVrKrT\nuTZjvukQnYhMIGVY2ZxPVWyrHVCWzXpVXkt3TE7Va+W4K7X3jv1auTNy3jdba0RZpamfroQN7Hk3\n6wr1GTaN2OOJiu6Mu98NvgDi8Wy74d/yZ8PiPAiO2zU4nb6qIn1bugjfFE/ASp1ke9u15mbbRDZ1\nMb823kx0Ontn1OOkedoJCvT8I03gaKsz9q/WW+isRWsVjtHRKyrhe0XCfpWL6Vgr9fjjrEfeh5fF\nfeH0V5Dj3DPoOo+k4a/U5J6xH3ZZ7z3228evytOk7NvFbo0cdols47bSybt7HbddHVqUs2aW3Qnq\nxVeu8LILR3SlZw3V/R8nhXn6u0/pLuPMXjeHT4Zruf6jLPvR9mZ8/g1xrvpz+TH7HUAaMAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAABRq9VXSYJyW79qx6yvmdo3l5viGs+maqYrO+OnSvx+KLeLZz2te1rZL2v\ned7WneZYWnZl5K72YV1xEyxmeqJljzIEWlVkszvbZp5soN3h2SJz3pP3odCnuWmPRxuERfJrZmtZ\nmtY96fR28kbX3dXj/wAuTyf6bmK+9YX1s0cNtm3Sd4LFY2K23W1s16StiUJW7bp22RW3RluBuruz\nmWEgrmCGWyNkoExKE1QlPmsqRDKeyBjaejWy2W3ttDUyz1QKslvehVqKTNosyyTvELabXptIJpaP\nB39Ia2mz+JGpr51jdZefDx2hzuHZObNq58poJaGtjxJ2+LoaKP8ADRPo5+T3skx5OhpOmC0fBNQ0\n5yTbn+bt8A0u9raiY6RHLVwY62mI6zMvaaHBGn0mPHt1iN5+aYVsACBXqMFNTgviyxvW0bSsAeE1\nmkvw7V2w5Ote9besJx2er4rw2nEdNNekZa9aW9JeQjnxZLYskTW9Z2mJY7zz26fHrrdpbZsY7NGt\nmxjvso1b9NmUwpx33XRO4K7VUTE1nmrvEx1bVo2VWiJE/XY4frY1WPlt0y17x6/FuPM0m+HJGTHO\n1qu9pNVXVYt46Xj7VfRtnXXL5MfzexsALsgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHM4jxOMFJphmJv529Dq\nZLfjDjPEIx450+K3v2+1MeUOHSOWFc3nJkmZnf4yujpVlqunOeFpV2nctLCZUXRM7MJtsWlRkv3Q\nky5NmpWt9RnrixVm17TtEQnJabXisRMzPSIew9n+CRoccajURvqLx5/chfOest642OGcIpoOG2w7\nROW9d72+LQvXevyejcPUU5M+SvpLeOataraw2a0dLbLqTtK1G3Es4lVWWUSoldFtmcXUbpidgXzK\nGEW3TuCUSncnsDFMMLSms9EC6J6FpVzbZE5ALy0809ZbFr9GtfrEoFMzuuwz0Ueey3HbaBLDXe7i\ntMOfwWnP9I+NZbuttvhs1uBRtXPb4SDm3iIvf57N7Dbl0VrS5+XrltEd+Z1Jx7cNms9N4TURRw3T\n+PrcO3WszEvZOD7P6aYiMlvu16S7y1QAIAABxOPcLnUY/pWCv1tI96I+9DtgmXl68Biy7/NtUu3+\nO8HnFa2s0tfd75KR5fFyMWTdhrPHVnX9R0cd21S3Rzsdm1iuqs256wrmGcT0RYSx5d047X02SMmO\nesd49YRE9WcdSXhZ2O1p89NRji9J+cei1xMc3wXi+KZj1j1dTTaqmor06WjvWW+ddcu8XK8BZmAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAMMmWmKu952UZ9XFZmuP3revlDTtzWnmvO8q3XGmfHb9ZanV3yxtWeWn7y4es\nvPNtDqZJ6Ts5mppvdl/XXRMyfGvSNlu/RVvtOzLfoipLT1VTKbSpvfogRkvtDVyZOhkyvQcA4Dzz\nXV6yvTvTHMfvK+c9U3rkW+zvA/D21urr789cdZ8vi9KDb45rejl8Rry6iJ/FV1HP4vXbBTJEfYt1\n+UpiHM295bXsqrO9l8QkZ0lZEqqLeyBZHZLGvZkhIndADKJ3TMoqWQMZ6pjsxll2jsCLSrmU2lFY\n36gieyu0LJk3jbsga0wdqzK20QpyztQGprL/AFMrOE05NLkt6qdVWZxNrSe5o9vWBLiUjnzXn0vL\nq555dHt8HOwV928/1z/LpzXxbYccRvzTB+jucOwxh0dI22mY3ltIrHLWIjyjZKyoAAAAACJiJjaY\n3iXleM8InR5J1GniZw2n3oj7s/8Ao9Wi9a3rNbRE1mNpifNFnVs65XhcWTdt47bnFuF24dm8TFEz\np7T0/pn0a+HJux1OOrOux08d1ndqY7tillVkzExLOk7yd4YxGwluViJhE45raL0na0dtlWO0+bZr\n1TKi+2zptZGTamT3b/tLacvJjiY3XaTWdYxZZ6/dtPm1zrv1z78fPcbwC7EAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhkyV\nxUm152iAZWtFazNp2iGhm1Vss8uP3aevnKrNntqLdelI7VRHRnrX/HRjx/tZREVjZXeybW6KbWZt\npCZ6S08tN7Nmbb7zCrJtyoS5145bSx5mWafelr3tsKmS/o08uXyhlly7RPV2+AcBnPNdZrK+53pS\nfP4ytnPVda4y4BwHxOXV6uvu96Unz+MvVxG0bQRG0bR2G0nHLb2gCUDX12LxtFmpHeazt82wT1gH\nmMN4tWs+rcr2aEV8DU5sM/cvO3yb+O0csLUTSdrLphRE8tlkZI7Atr2ZMazDJVKTYSCawi7Ksq7z\n1QERvLK3ZGPrKbyCrbdnMcsbeaa18/RhvvM7oGEwTG0JmYYTIML22a2e28xELM19oURPNO4lOem+\nn3ZY5+prVnMc2GYU4/L4A0a15cNf6rz/AC6fC6+NxCPOuOu/5tHJTbHj+F5/l1+BYumXJMd9o3/d\nMRXYASgAAAAAAABhlxUz4rY8lYtS0bTEvH8R4ffhmo6bzhtPu29Pg9mq1Gnx6rDbFmrzVsizq2df\nzXkMWTeIbNL7tbXaHLwzUctvexWn3bmPL8WFnHVL326VZ91MfFVjvvVlz79kLrcf2m7j7bNHH3bl\nJ2SirLQoy4t1++7G0dBC/RanxI8PJPv18/WG241+alovSdrV6w6mDNGfFF4/OPSW2b1zeTPL1aAs\nzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAVZ9RXBTe3WZ7R6iZOpzZq4ac1p+UermZMl89+a/byj0Ra9815ted59PQ32hlrXXRjH\nDpCLX6ML5NlNsm/ZRqstfdXzbsZt06sLZNvNB1Za8RDWyZdo7q8udq5Mu/mIMt4md2lmy7JzZuWJ\ndHgfBL8RvGo1MTXTxPSPx/8AstJ1XWpIs4BwSdbeNVqq/URPu0n73/s9hEREbRG0QUpWlYrWIisR\ntER5JbSccur2gCUAAAAPM8Sry8Uyz67fwuxbzVPGsE49XGbvF42V4M0TEL33ERnktsxpk3sumK2j\nadmFdPFZ33VS2Mdui2J3UU6LYlFSsN2O5NkCyJ6K7T1TEsbAsxdpReerKkTFGMxvYEz0rsqtbbpC\nb2VT1QEzuwtbaGUxspuJU3neWdKoiu8rq12gCI92YatLcublnzbEz1aOptyZqTuDHLfxN6R0+t5X\nqdJhjBp6UiPLeXl9NSMnEKxHa1+bb8nrlvxUAAAAAAAAAAABTqtNj1eC2LLXeto/R43VabJw/VTh\nydY+7b1h7ho8V4dXiGlmvbJXrS3xRZ1fGv5rzeHN02bEW3cys3xZJx5ImtqztMS3MeTeGFjqlb2O\n8btql3NpbZtYsnSBLeiWfdTjtutid+ghherHS5p0+f3vsX6T8Fkw181d4lMvEWdnHaGnw/UeNh5L\nT7+PpPxbjdyWcvAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAo1Oprgr63ntAmTqdRqK4K9etp7Q5d7Wy2m953lNrWyWm953mVd77R0\nZa1104xxlN9lV8qnJl2a9s3xUXX2ybsJyRDWtl3YWydEC+2VRkzeW6q+T4tbJm+KRdfK1cmWZnlr\nvNp7RC/R6HU8SycmCk7ed57Q9ZwvgOn4fEXtHi5/O9o7fJaZ6z1uRyOEezVstq6jiEbV71xevzer\nrWtKxWsRFY6REeSRrJxz22gCUAAAAAANbX6aNVpL0npMRvWfSXlKamsRMVvXm+EvZXjmpaPWHzfL\noNRjzXicfWJ8phfPxFejx72x7xMzK+sXiNoiXlq+Pi6fWV/VfTNqfLJl/WTg9Pji8R70LqvMV1Gq\nj/zcv6yz+lanzzZP1lWpelTET6S81Gp1P/Gyf90s412rjtnyfqql6asREdWM9+jz9eJ6yP8Az7uh\nodZqMt458tpB1JvEViI3/RhzRt13/R1MNaziiZiJn5K9ZNceKZiIiQcu/WekT+iYrWI3lzdTrs+8\n8uW0fJzcur1Np/zsn6g79phVaIeetqNR/wAXJ/3SwnUaj/i5P+6UD0ldonum161h5mNRqP8Ai5P1\nlNtRqJjacuT9Qd22WN5aGeZyZd/KHJy59RHbLf8AVq31Gp/4uT9ZEvS8Lr/vSs2npzRtL1z53wK+\noza/HW2XJNd99pmX0Rb8VAAAAAAAAAAAAAAcHj/C5yV+l4I9+v24jzj1cLFk8nu5jeNpeW41wmdL\nknU6ev1Vp96sfdn/ANFdTrXG+eq1q5F2LLtbZoY8m8d11bbSydErsYsm+zZrO/zcnBm226uhiyRK\nEtrvCrJDOJTeu8A1MWX6Lqq5N/dnpb5O5ExMbx2cPNTeJb/DM/iYPDtPvY+nzhri/jDy5/W6AuwA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAa2p1UYo5adbz+xbxMlvqJ1OqjDHLXree0ejmzNrWm953tPmTPWbWneZ7yoy5YhjrXXTjH8s75N\nmtkyxt0VZM2/m175N1V03yTKubMLXVXybeYLLX2VXy7eam+b0bOg4VquJW+rry4/O9uyZOq3UjVm\n9r25axMzPaIdvhns1kzbZddM0p5Y47z8/R2+HcF03Doi1a8+Xzvbv+TotJnjDXkt+K8ODHp8cY8N\nIpSO0RCwF2YAAAAAAAAACvUZYw6fJkntWN3k8dfHz2vLucdz8mkjFE9bz1+UOZosX1UzPm0nqI/W\nMYo9FlcPNklfFGeH/NshLGun+Cz6PtHZtVZWlRLS+jxPkRpIn7rdoupHTdA5s6SI+7H6Mfo+32Y2\n+To3neSIiZ7A0IjPXpXLePlMotGW3272t85datKzHZjbTVnsDj+FG/2Y/RlGP4R+jo20u7H6N1Ql\no+H8I/REY957R+jpfReiK6eOYHLtj2tttH6KrY/6Y/R2c+kjeJiFVtLG24hxpw7/AHY/RRkw9O37\nO99Hrt1YX0tfOBLjcGp4XF8c+u8fs9c4dcVcGemSI61nd3IneN1orQAAAAAAAAAAAAABFqxes1tE\nTE9JiUgPKcX4RbRXnNgiZwWnrH4XPi28PdXpW9JraImsxtMS8pxXhF9DecuGJtgmf+1TWW2N/la1\nL7N7T5e3Vy6W3hsYcvLbqzbO9jvvCzvDR0+XeO7crO6FmGSvRThy/RtVXJ92elvk2rRvDUzU7pl4\nizsd2J3jeBpcNz+Lg5LT7+Pp+Xk3W7js5eAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs0NTrN96Yp6edkW8Wzm6+LNTq4pvTHO9vOfRoWtt\n1mes95YWvs1s2fZldddOczLPLn2ju0MmebT3YZc2/mpm3qqllN1drsbZIhr3yzvtHf4AsvlYYseb\nV5Yx4KTe0+UQ6nDvZ3UazbJqd8OKeu33peq0eh0+hxcmnxxWPOfOfm0mP+steT/ji8N9mKY9suum\nL37+HHaPm9DSlaVitKxWsdohI0Y22gAgAAAAAAAAAABXnyRhw3yT92Nwef4xm8bVzET0rPJH5d12\nCvLhho3rN9RWs9Z23n5y6O21YhrVYbdGOCfrrLPJRpv863zVS6FS09SvZj3lVZZRdPSqmnSWdrIE\nebOkK4ldTsgW1WKqd1oMZhEVZyRAImOjGI6rJ7IiATNd46qL02bHkiaxaoNGY2n4ImPgtyV2n0Vo\nGvlx7x2beiyTk08RPevSVUxux00+Fn2n7N+n5rRFb4AAAAAAAAAAAAAAACLVres1tETWekxKQHlu\nL8InR2nPp43wz3j8P/s5dLveWrFqzW0bxPeJeV4xwmdFec+CJnDM9Y/CrY1xv8qvTZ+WYdbDk5oh\n5zHk283U0eo3jaZZ2N5XYjrCnLSJhOK+8d1kxvCqzSwZvousrb7k9LfJ3nB1OLeJdLhufx9LEWn3\n6e7LXN9Ofy5/W4AuxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAETaKxMzO0Qi9646Ta07RDmZ9VbPbaOlI7Qi3i+c3TPUaqcu9adKfy0722ZXvFa9\nXO1OrjrESxt66ZJmcjPUanlidmhkzTZVfLN5VWvsC2b7R3U3yqrZZtO1esz2h2+F+zWTUcuXXTNM\nfeKR3n5+iZLVbqRzNJo9TxHLyaekz62ntD1fDOA6fQbZL7Zc/wCKY6R8odLBgxabFGPDSKUjyiFj\nSZkYa3aALKAAAAAAAAAAAAAADQ4pl2pTFH3p3n5Q33E12Tn1eSfKscsLZ+orS00eJqbW+Lfnu1tF\nXaJnZsz3WpCfsyp00fWSvmPdVYOmSUDd8kR3InoQosy7JmUX7MdwZ17ro7KKT1XRPRAsrO0rYndr\n79V1ZBaQiJ6JgCSIJASwrO07MpV2nqBlrv1a1o2bf2qtfLXaQUTO0sb05o3jv3ZXhjS20xEphW5h\nyeJjjf7UdJWNKLziyRePsz0lux1SgAQAAAAAAAAAAAAAADG9K5KTS8Rato2mJZAPIcU4ZbQZuekT\nOC3afT4NXFkmlntc2GmoxWx5K71tG0vHa/RX0GpmlutJ61t6wrY2xr8dXS5uesN+tt4ef0eaa223\n2dnHk3juyreM81OaFGiy/RtZET9jJ7s/2bdutd2jqKeic3iNTsd8a2h1H0jTVtP2o6W+bZbOO+gA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABje9cdJt\nadohGTLXFTmvO0fy52bJfU23t0pHaqLeL5xdK9Rnvqb+cUjtCi94xxvK3JetKuHrdZvaa1ljb10y\ncnIs1Wt3naJc++TmVWvMz1YWybfMGdsm3eWek0mo4jm8PT0mfW3lDf4V7P5tdMZdRviwfvZ6/TaX\nDpMMYsFIpWPTzXmf+steT8jn8L4Dp+HxF77Zc/4pjpHydYGjC3oAAAAAAAAAAAAAAAAADG9opS1p\n7RG7zszN6WtPe0zLua+3Joss/wBOzhzG2OsL5+IrY09dsSyYRijbHEMvOChb7KjF0yS2LQ169Mso\nS24noyrPVXWejNVKbTuw3T3REdQWU6LYlVvsyiUDPfqupPRr79VuOQX1lZEqoZxIMksd0gT2VT0l\nbPZVbuCaW8i8bwr32WxbcGnkjaZa9p2ndv5qbw5+aNugLItF6TEtvTX5sMb969HMpfazc0d9stqe\nvVZDdAQAAAAAAAAAAAAAAAADV1+iprtPOO/2u9bektoB4TJTJpNRbHkja1Z6uto8viVht+0HDvpG\nH6Tjj6zHHvbecONw7Ltfkmeqmo6Ma69DXbbZTkr1mGWO3RneOaGbZRoM30fVzSelMnT83aef1FZ7\nx3h1tBqfpGnjmn369LNc3sc3kzy9bQCzIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAa+q1dNNXr7157VhGp1Xh70x+9f9ocy283m1p5rz3mVbrjXHjt91lz\n5c9+fJ1nyjyhdM8lZlOOIiqrUXikd+kMreunnI5XEdX4dZiZcG+XmtNl/F83PeeWWHDOGanieSKY\nq+5H2rz2hMzWd1Iqx1yajJXHhrNrW6REeb1nCPZumn2z62Ivl7xTyr/6uhwzhGn4Zj2xxzZJ+1kn\nvLoNJnjHW7TbbsAszAAAAAAAAAAAAAAAAAAAAaPFrbaSK/itEOXt0rDf4xb/ACa/GZacRvaF58Q2\nIjasQnzPIhCU92tMbZGzHmotG10C6nZkwpPRmipIllEbMIZIE7solgmJBnCyk9VMM6z1BtVllEqK\nz0WRILYlluriWcSDJVbusV27gwInaSWM9ECyZ3hqamnSWxFmOSOaqRx725bNnSZNs9J+OynVY+WZ\nYYr7TE+nVaIr0Ais81Yn1hKAAAAAAAAAAAAAAAAAABExvG09peU4nov9n66L0j6q/WPg9Y1OJaON\nZpL0+9HWs/EWzeVz9PbmrEtnyc3h9reHy26TWdnSr2YX6657ijLXpLX0+onSamL/AHJ6W+Tbv2aW\nekTv16JzeI1Ox6KJiYiY7Slz+E6jxdN4dp3vj6fl5Og2clnKACAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZ2jeQRMxEbzO0Q08uqtkma4ulfO3r8lefUePMxWf\ncjy9WvlzVxV6T1Z61/x0Y8f7Wc7Ur1lqVy+LqOWJ2hp6rXddon5rOF1tfmz5OkT0qzb8dWbxjp1c\nbiuuilJ5Z6r+IcQrixzEy8zl1E6rNt1tMztFY81sztU1eRucN4ffi2p5esRM72n0h7rS6XFo8FcO\nCkVpX082nwXh3+z9FWLxHi36328vg6TZyW9ABAAAAAAAAAAAAAAAAAAAAAADj8Unm1tK/hqppHvw\ny1k8/EMk+m0GOPeafiFpCZYwolnXspvHvLa9mF46gmnZmwozRUiUCBKYYsoBLOFbKAX0llEqqyzi\nQXRLOJVRLOOwLIljZMEgrlhKyYYTAK5nZPN0RZjugUanHzVlz6xtLq361c+9eXItPpXX0dubTU+E\nbL2lw2++O1fSW6m/VYAISAAAAAAAAAAAAAAAAAp1GbwcfTreelYEydcuMcRrM/L9nnlsV6wqpi2r\ntv133mfWVkRyRtEdGFva7MzkYZNoamWN4bV4mYa9qztKIujhVppxGI8r1mJegeZpknBqKZY+7L0t\nLRekWrO8TG8Ns/HJ5ZypAWZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAADS12fp4VJ6z9qVuq1HgUiI+3bpDl589cOKZmevqprXPTbx477rDJlrhr1nq4+s182tMRP\nRqaziXiZJrWekNG17ZbxWJ336M5LXRbI3dLTJrs07RMY6fan1dHLrowY+X7MVjt6N3R6Kul0EbWm\ns7bz8Z+LnabQX43r7Y53php/mXj+Dnv0f1JO1x/8ZxbUzj02O15mfLtD13AvZqnDds+pmMmo26el\nXX0Wh0/D8EYtNjilY7+s/NstpOOTW7QBKgAAAAAAAAAAAAAAAAAAAAAADG88tLW9I3BwJtz6nNf1\nvK/DHVqYJ3pzT5y3MPZeojOWMQylEKpTVjZnDCwkqzYQyRRICATCITAJZQxhMAshnEq4ZQC2srKq\nqrIBZCWNZZgwswmFloVyCu0dFcx1WyrtCBhv5NTPHXds2U5o3hIz4ffbPt+KHUcTSW5c9Jme0u2v\nVYAKpAAAAAAAAAAAAAAAAYZctcVOa35R6tLrltN795/YvknNqrfhpPLH92V5isd9mWq6fHjk6rn0\nZxG8KK5Jm/wbVZiYZtqrmkqL023bkxvCiY3lJHNyRG81mHS4Rn5sNsNp64+3yaWaNrzOzHBl+i6q\nmT7s9J+S+ay8mex6EIneN47SNXKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAImYiJme0JafEs3h6fkidrZOn5eaLeJk7eOdm1Hi2vmtPTry/CHmOJcUvmvOPF1n09Pm\n6HF9ZGm01qxO3R5vSY7XwzmzTy47zzTEd7en5Mfvt2/PURWdo3tvPrPlKymbktFqTtMTvHzbOLDG\nf63JXbFX7FdnoODcDprZpq9TjiMMTvSn4vj8l5fxnrk91saPSa7i2hpOfbTVt5x1m0fLydzR6PDo\ndPGHBXasd585n1lsRERG0dIF5OOe6tAEqgAAAAAAAAAAAAAAAAAAAAAAADX11+TRZrf0y2Gjxe22\ngtH4piP3TPpXKwxtjhuYo9xq442iIblI2pC1RET2ILd9kxCqRjZmwlCSEohIJAQAAJZISDKGUd2M\nMoBnVbVVCyAWVWeSuqyOwIlXZZKue4MJV2WWYT2QKbKL9YlfdRdIo35b7/Hd3KTzUrPrDh27uxpb\nc2mpPwX/ABX9XAKpAAAAAAAAAAAAAACekTIp1eTwtJmv+GkyJn1oafeazbfpMzLR4jq/o8b823zX\n6XNF8ERCvTcNpxLV5LauvPhx9Irv3lhztdtv8TtaWLicXrt03jzjzb2k1nid56ty3s/w+a7Uwzjn\n1raejlarhmbhl/FpbxMO/fzj5p/ixSeXOvTtRfeI280ZI26tfDm3pWe63LaZx7qtGvniJ6tPLvOK\nfOa9WzbJvTbza02jl3n5SSljscK1MajSxWZ96nSW88xw/VfQ9XMT9nfa3yemid43jtLeXsce88qQ\nEqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADia3UTm1l4j7OP3Y/u\n7Vp2rM+kPJW1PhYcmS0+9MzKm/jbwz31weMzbV8UppazPL9q0/BF4rk1GLDSNqxPWPhCnHmnNrtT\nqPKteWPm6U6OdHaZvO+SaRNvhv12Ub/q3FhtrNVj0uKOt56z6R5y9zix1w4qY6RtWsREOJ7L6OKa\nS2rvX6zNM7T6Vh3mmZyOfya7eACzIAAAAAAAAAAAAAAAAAAAAAAAAAAczjVvqMVfW/8AZ03I41bf\nLp6/OVs/UVrY47NyOzUxd4bUJpEbb3Z7IiOrKIVSjZhMLJYyhKIgmGUQSDESIEbJEgQmCITEAmGU\nIiGUAyhZVhDOoM4Wx2VQtqBKuyyWEgqlhKyyuyBVaGtkbNmvk7A15l1eH2300R6TMORPSXT4ZO+O\n8fFefEX63gEAAAAAAAAAAAAAAAq1WPxdLlp+Kkx+y1Fvsz8gjhaDauGK8sx07y3OE3m1tT6RaP4c\nvU6yMNKUx73zT0ilY3l2eF6a+m0kRl/zbzz3+Ez5M8z26fJruW6wzYq5sV8d43raNpZjRzPPaTmx\n5b6bJ9rHO3zb2WJ8GWPEscY9bgzxH2t62n19GWW0eHOzHU5XbjXZ1x8WTnz2iZ7S2M1IjH2+LX0V\nKTqs8zO9ot0j8nUthi1J3UaOFMTfLFo6xMbS9BwHWTqdHOO8+/hnln5eTjYMFo1WTH5VnePzXcIm\n2k4zlpPSmXy/hfF5eMfJns69OA2cgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAADG/2LfJ874rW845mubliY7bPoto5qzHrDz0+yePNF41OotaJ7RWNtpV1OtfHqZ715fhu\nj8adNpcVfeyzE2/vLuanhOu1nEctIxTTFa/+ZPbZ3eHcF0vDbTfFE2yzG03t32+DokynXl9+leDB\nTTYKYccbUpWIhYCzEAAAAAAAAAAAAAAAAAAAAAAAAAAAAcXjE/4zDH9M/wAu04XF5/3jj/0f3Wz9\nRUYmzDWxS2I7FSyjuzY1ZKpRKEygEwiWUIkGIk2QJNhKQhMIhkCYZQxhlAMoZwwZwgWQshVCyATL\nCWc9ldpBhZXLOVdpQK7NfJPRdaWvknoDVvPvOnwuel4+TlXn3nS4VPvXj4QtEV0wAAAAAAAAAAAA\nAAAAAVV02CmTxK4qRf8AFFeq0AAAanEsfPpZmO9Ji0NDLfkwdOsulrumiyzHlVzJrz4Ovoy26vB8\ncTBa9NffLtMY77Rv8Yegx5ImkKdJoY1HC81Y+3OSbVn0mGGkmbY45u6tnrrTOu2xGO0RxCd+nNVj\nqKxTV1vH2pjaGtnyzXXYdo96ZmGXEMk15b7/AGZiVerWPTYckZcNbx5wzc7hGbnxXxzPWk7x8pdF\n0S9jh1OXgAlUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAcPjEf4/FP9H93ccXjMf4vDP9Mx+62fqKrx+S+GvibEFSsqyYwlVK\nZYsmIMoRKYJQIPIEiQ2ATCUQygCGUIhMAyhnDCGUIFkLIV1ZxIMpVWWSrsCuyqyyyq09ECq8tfJK\n66jJ2Bp5J6upwn7dv9Lk5J951uE/av8AJaIrqAAAAAAAAAAAAAAAAAAAAAAq1Mc2myxPnWf4cmtu\nXT9fR0tffk0WSe28bfq5Wbamm3326MtunwfK6PCv/AxPraZ/dz9PO97/AOqf5dHhdZrw7Dv3mOb9\nXOxRFM+avpe38mvkPHf/AFWlrKba7Tzt99ZxKkfR7euyNXMTrtPHfa0z+zPiM/UR8Zj+Wbdu8HpN\nM2bfzrV13M4dO2pyR61dNvj44/J/oAWZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADj8bj63BPzdhyeNx0wz8ZWz9RWri7Nmv\nVrYu0NmqaRZHZlDGGSiwxZSgCEkCBCQSCQBMJRCYgEsoYx3Z17AlMIhlCBnDOGEM4AlhZZKq4KrK\n7LLKrIFN2vdfZReAaObu6/CO9vk5OePR1uEd7fJeIrqAIAAAAAAAAAAAAAAAAAAAAGtxCk5NFliI\n3mI32+XVyNTyZOHTee946PQKPoeDffw4777eW/yVs60xv+ZxOnr4Okx1t05KRv8Ao41Z5q3yed5m\nXY1szXRZ5jvFJ/hxItP0aOSN9q7yrtr4f2tHFM5+KT16Yq/vK/iGSbXw4vO14UcPx5MGfNbPG18m\n1oj4THRsTw7VanPXVYpi3gzMcnrvCnG11JOupwuN8+a3pEQ6jT4divjxWnJExa09pbjbM5HHu90A\nJUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAHM41H1GOf6nTc/jEf4Ws+lls/UX45uGekNujTwdm5RNIthKIZKLDFlsiQIShIC\nEgCUJ7AmGTGO7IDzZQhMSDJMMYZQgZwzhhDOATuqssmVdgVWVWWyqtCBTeVF19lF+wNLNG7q8I+9\n8nLyupwnt+S8RXUAQAAAAAAAAAAAAAAAAAAAAAAItWL1mto3iY2lyrcLyUxzix2ia2nvPeK+jrCL\nOrTVnxpanhuPPemSs8l6RtE7dJj0ldpNP9GwRSZ3neZmV4cR/Vs4AJQAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHi1d9H\nM+kt5ra+vPoskfDdOfqK4mn7Q3aNHBPZu0W0RdDOGFWcKLCJZeTGQQlCQSgASBsCYZQxhlAJTAmA\nTsmAgGcM4YQyjsgRLC3VnaVcgwsrt3Z2V2QK7tbJ1bN5a9waeWO7p8Knt8nNyebpcK8vkvlFdQBA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK9RXmwZI+ErEWjesx6wQeZwejeo0cccuW8\nelpblJaaRGxVnCuss4ZrMvJEgCAASISCQIBlCYYpieoM0wx8k7gzIRueYM4Z79FcSy3QEsLJmWFp\nBjaVVpZWlXMoGNmvkXXlr3kGtknu6XCf7OXkl1OEdl8orqgIAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAHmskcmtzV/rls0U62OXiWX4zErcc9GmkRfWVkSqqziWayxCPIANwBIhIJSxS\nCRG6dwZwlhEs4BluMdzfqgZxLLdXuy3AmVdpZTKuZBjaVVpWWV2QlhZRdfZRcGpl7urwfrzfJy8r\nrcH61vPyWitdMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHA4nHLxKZ9awnH2ZcY\njbW459aq8fZpfiI2IZwrqzhmsz3Ebm4JN0AMhCQSIASndiAziWUSriWcAyRujc80DM3RCfIETLCW\nUsZEsJYSslXZAwlTddPZTkBp5e7r8Gj6rJPxhx8k9Xa4PG2C8/FaK10QAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAcfjcbZMFvnDWx9m5x2PqcNvS+zSxT7sNPxH62YZQwqzhRZO6UCB\nKUAJTux3SDIRuAncQAmJZRLBMSgZ7iIAZRKd2DICUSlAljLCYWMLIFVukNfI2bNbIDTyT7zu8Ijb\nSz/qcG/2nf4T/wCE/wD2WnxWt4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHL9oL\n+Hw2cm28VvEuPptfgyVj6yIn0no7/FtJfW8NzYMe3PaPd39d3iMug1WktNc2C9dvPbeP1aZ9xF+v\nT471tHu2iflK2HkqWmvaZj5Surqc9Ps5bx+alTHqYHm68S1Vf/NmfnC2vGNTXvyT84Ql6A3cSvHM\nsfaxVn5Ssrxyv3sM/lKB1xza8bwT3pePyWV4tpZ+/MfOEjfGrXiGlt2zV/PotrqcN/s5aT/+wLRj\nFontMSlAlKEgndO6IAZQljDIEgeQljLCzOVdkCu/SGrkbF56NPNeKxMzMRHxENe0+89DwuNtHHzl\n5PJr8NcnLW3Pbf7r1nCZm2gpae8zMrz4i/W6AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAETETG0xukB4HVaeMHEtRi26RedvkyjBSfX9W77QYvC4xz7dMlYlrU7M929dWJLFc6aPK0q\n7YLxPS0S22FlP6q38Zac0yR92s/KVc3tHfFf8tpbcsLRvB/dR/8ALLVnU0r9uL1+dZI1mnmdvGpv\n6TOy6ym+Oto2tWJ+cJ/tW+KLK5KW+zes/KU7tG+h01p64qx8Y6NXNo6Y+uPJlp8rLf0rfG7MXtHa\n0x8pZxqs9e2a8f8A7Oj7HaTHn0+f6RWM23LETfr6vRW4PoL99NT8ui7F4+vEdXXtnt+fVbXjGsr/\nAOZE/OsPS29nuH27YrV+VpeV9pdPXhOtw49NG9Mld55+vXcTPd42I47qo7xSfyWV9oM8d8VJ/VxM\nd8l46xWF9cV7en6o/qLfxp2I9ob+eCv/AHMo9op89P8A/wBORGmyT5R+qfo2X8P7n9Q/jTsx7RR5\n6ef+4/8AuHftg/8A6cWcOSO9J/WEbWr3pY7Efzp2Lcfv5YK/9zWy8d1E/ZpSv5Oba1/+Hb9lc+LP\nbFt87I7E/wAabWbiurvEx4nL/pjZzc2bJkn372t85ZXx55/BX85lucC0vPxnTxlnnjm32mOiZqUu\nLJ2p4TwnVavNWaYbRTfre0bQ99pcH0bT0xb78vmtiIiNojaErMwAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAHnfarF7umzRHaZrLjYrdIen9ocPi8JyTt1xzF4eUw23rCm3R4r6bMy\nwt6kdTaWLdjswmNoZontsCm0K5XWjopnuDC0dGpqG5bs08/daKV672MjbSaif6oh6Z5f2LtvptRX\n0tEvUN3Jfo8f7cYve0eX4zV7B5z20xc/C8eSPuZIRficfXlcPaG7ino08HWIbePpLF2NuiyOyrHK\n3fZFSwuovHVfaVF4QK5YWTM9UT0EKry6Ps1Tn4zjn8NZn9nOtLseydObiWW34cf918fWfk+PYANn\nKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq1WKM+ly4p+/WYeBxTNd6zG0xO0\nvobw3FcP0bi2em20Tbmj5Srr418V9sa2Z7qKyzi07MXUylhaU7yjqhLCeiq3ddaFNxFYW7NLNG8t\nzya+WO6Va9J7FW66mvwidnrXiPY3Ny8RyUn71Jj9Ht3RPjk19HK9pMHj8D1ER3rHN+jqqtTjjNps\nuOe16zAifXzfTz7kNyndpYazS9qT0mszDdoxrsi6m8LazMq6zDOsq1ZEyrt1WWlXaUCqyq0rbKbi\nFdp6PReyFd8uqv8ACsfy83aXrPZHHto89/xX2/SP/dpj6y8vx6EBq5gAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAB5n2q03LfDqqx39y39npmlxbS/TOG5se29tuavzgWzeV4mtui2\nO3RRSY2hdVhqO2MvI36iu9lUsrSrvDHn6spnmSiq5jooyV6tq1VV69RC32byTh43h8otMx+r6I+Z\naK/g8TwX7bXh9Mid4iW+fjl8n1ICWb57xLBOm4zqse20Tbmj8+qKdnS9q8PhcTw5tumSm0/OHMxz\n0Za+uzx3sX1t0Zxurr1ZxvspWiZYWZbsbT0QK7KLrZVZJFaqt5vbezNOTg9J/FaZeJns93wCvLwb\nT/GJn92uGHldIBowAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADuAPA67F9H4l\nqMW20VvO3yRWW97T4fC4rXJHSMtI/WGhVlue3b473K2KzMML4+62tujG9pnozXaOSOVFMnVbmq1t\ntrJRW5E7wwvUxTvCyY6CHOt7moxz6Wh9PxTzYaT61h8x1MbZK/OH0zTf+Fxf6I/htj45vL9WgLMn\nmvbPFvocGWO9L7fq85p5maw9d7VYvE4JkmPu2if3eW0+PasdFNOnxfF1Y2hlykRsmY+LJ0MZjZXa\neq2eyi8oQTO0KLdZWzPRjWu6VaqtHR73g0bcI0sf0Q8Nkq93wqNuFaWP+XDTDDytwBowAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAef9q8HNpcGaI60vtPyl56k9Iew49j8ThGe\nPwxFv0l4zH2U26fDfTYiyJljvsjf4sm6vJ1hrXjq2MkqLdZEVbgbMx0auGdmzNt6iHN1Ub5af6of\nTdPG2nxx6Vj+HzaaTm1+nx/iyVj930ysbViPRrj45vL9SAuyc7j1efguqj+jd4/T33rD3HEcPj8O\n1GP8WOY/Z4TTT7sKadHhbcsZnaCJ3TPZk6VdrKbTutmP0U2nqgrGOsr8deiuI2X09EqKM1dt3uuG\nf/jdN/06/wAPE546S9rwud+Gaaf+XH8NMMPK2wGjAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAABrcRp4nDtRWPPHP8PCYusPoWSvNjtX1iYfPuWaXtX8MzCuvjfw32siu8ptXoxi\n0wy5t4YulReqmazu2skbquURWFInddM7VYRGyL291KFnCcfj8e0le/Lbmn8n0N4b2Ur4nHLWmPsY\n5e5a5+OXyXugBZmiY3iY9Xz7NjnTa3Ph/BeYj5PoTxftFg8Hjk2iOmWkW/Psrr418V5WrWd2faFc\nV2jdnEMXWxntupmN7NiYU27iWML6dVMVnddjgVqMsdHr+CW5uE6f4Rt+7yuSsTDv+zWXn0WTHP3L\n/tK+GHl+O0A1c4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8Dn93W56/wDM\nt/L3z59qp24jn+OS38lnpr4r7ZxHQ2TEstt3PXUrt27K57rr1VT0BjKnJPRbMqMs7QlV2fYvHvrd\nVknyrEfu9m8f7FZI8fVU85iJewbT45NfQBKo817W4eulzxHaZrL0rje09ItwqbfhtBVs3leai8RD\nKLw1sduesL606dWFdsZT1jdhNeq6K9DlhCVUU6s4jZnt1YzAhnM71dH2bycmszY/K1d/0c6OzY4R\nfwuK4p8rTstn6z8k7HrwGzkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHz3\nVxvr80/8y38voTwGpj/F5/8AqT/JfjTx/WVeyY6FPspc9dZPVXaOq2WEwIUTVRmjo2rNfLHRI3vZ\nDJycXtX8dZh7t879nsnhcbwz23tt+r6I2nxyb+gCVBzuPY/E4PqI9K7ui19fTxNBnp60n+Aj5/pJ\n3jZu1aOnnltMNussdfXbm+l3ZM9URHREdZVXTuT1Nk7boQiOkJw28PU47/htEp5eivJPLMTCZ9Vv\nx7mJ3iJ9UqNHk8XR4b+tIXuhxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD\nweqjbWZ4/wCZP8vePCaz/wDIaiP+Zb+UX408f0r9lOxWOifJhXWjfyYWllPRXYQxnrCrJHRd3YZI\n6A1NJecHEsN/S0T+76bE7xE+r5dk93LW3pL6ZpMni6PDf8VIn9m2fjm8s9rgFmQxvHNS0esbMiew\nPnHLyai9fS0w2aNfUTtrs3+uf5bGPqy068fF227KtSsdFlKqNGMV6myyY6sbdIQI8tlOWOi6Jhhk\nj3RD0vA8nicMx9etZmHRcT2Zyb6XNT8N9/2dt0T449T2AJVAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAHhdfG3E9TH9cvdPEcXjk4zqI/q3L8aeP6xr2TsxpLOekMK6mFo6qpXSrm\nOqBixvHSVmzC4OfqK7S9/wAByeLwbTW9K7fo8Fqo6Paeyl+fglI/Da0NcMPK7QC7AAB8313TiOf/\nAKk/y2MHWrX4jG3E9R/1Lfyv0/aFNOrHxuU7LI7MMayGTVlHWUXhNe6Z6wIUsb9d1m20q7dkDpez\nN9tRqKT5xEvRvKez9+Xis1/FSYerb5+OTyf6AFlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAB43j9eXjN/jWJ/Z7J5L2mry8Upb8VIF8f6aGOey2eynHvOy7bowrrYSxZSwQJ2YXZ\n92N4BoanrEvVexmTm4blr+HJ/aHltRHSXofYm/1Wrp5RaJaYY+X49WA0c4AD51xONuKan/qW/lbp\n+0MOLRtxbU/9SU4J7KadWPjep2WQrr2WRPRk1TvsndXMpiRCb9FNu0rbTuqvKBscCjfi9PhWZeue\nV9n434rafTHL1TfPxy+T/QAszAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHmv\navHtfTZfnV6VxPajHzcNrf8ABeJFs/XnMcr4no18c+6vr2YadkY2YM57sEDLyY37Mo7MMnYGlqO0\nvQ+xNfqNVb1tEfs87qZ2rL0/sVX/AHdnt65P7Q0wx8vx6UBo5wAHz/jUbcX1PT78qtO2vaCnJxjP\n8Zif2amnnspp04+OjWejKJ6MKdmcMmyJn4m5ZHzEVPMwtJv0VZLbQDqezcb8RzT6Y/7vUPM+ytZt\nn1OTyiIh6Ztn45N/6AFlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABocbxeLw\nnUR5xXm/Rvq8+OMuDJjntaswEeBxT0bNZ6NatZpNqz3rO0rqsdO3PxlaWEMpY+aqWXkryT0ZT2V3\n7A0dVPuy9f7G124NM/iyT/Z4zWT7sw957MYfB4Fp4/FE2/WWmGHldcBowAAeM9qKcvFeb8VIly9P\n0nq7ntbTbVYL+tJj93CwT76unR4/jo0nozhhTsy3Y1sWljM9Ce7HyQIm3RRlttVbaWrnt0Sh6n2U\nx8vD8mSfv3/h3XN4Bi8Lg2nj8Uc36y6TeOPXugCUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAPD8RxeBxXUU26Tbmj8+quro+02Lw+I4ssdslNvzhzazvDPbq8d7GW7Dfqz2VzG\n0s2qd+iu/Zn5Ksk9BVztX1mI8930zh2LwOHabH+HHWP2fNYp4+vwYvxXiP3fUqxtWIjyjZtj45/L\nfaQFmQADzftfj3w6fJ6WmHmsP23rvaqnNwqLfhvEvIYZ+sV038bo0noy36MK9oZQxrdMyrlnMbMZ\nQKrS1M07zEestq/RRjr4utwY/wAV4j91p9V18fQdJj8LR4ccfdpEfsuREbREJbuMAAAAAAAAAAAA\nBAJAAAAEAJEAJQAJQAJEAJQAJQAJEACUJAQlAJEAJQAJQJAAAEAJEAJBAAAJAABAJEJAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwvanDzaPFmjvjv8A\ntLztJ3h7HjGHx+FainnFeaPnHV4vFbeIU038VbHeGF+kso7Mb9mTdhKnLK3dRm7SIrHhGPxeP6Sv\n9cT/AHfSnz72Zx+J7Q45/BWZ/Z9BbZ+OXyfQBZQABzeP4/E4NqI9Ii36S8Ng/wAx9C4jTxOH6ivr\njn+Hz3B/mQi/GvjdCnWNlsdI2V07LIlg6USrt2ZzZXMoFV+zPhGLxeOaavpbm/RVltEN72Yx+Jxm\nb7dKUmf7L5+s9/HtRA2cqRACRACRACRACUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQCQQCRACRACRCQBCQBCQB\nACRACRACRACRACL1i9LVntMbPATTwdRkxT3pea/u+gPE8Xx+DxrPHlaYt+qNfGvjvtXXsi0dOrKk\ndEXjZg6VMtbP2bMtXUdpEV0/Y2nNxbNf8OP+727xvsXH+N1U/wBEfy9k3nxyb+gCVQAGOWvNivX1\nrMPnGGOXNNfOJ2fSZ6w+dZKeHxDPX8N7R+6L8a+L63KdoZ7q6zvEMpnowdKJ6ywmWUyqvIKM0vQ+\nx+D6rU55+9aKx+TzWa36vbezmDwODYenW+95/Nphj5L6dQBo5wAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAEiAAAEoA\nAAAAAAAAAAAAAEAkEAkRuAkQbgkQAkQAkQAkQAl5T2nx8nEMOT8dNv0l6pwfarHvpcGWPu32/WCr\nYvK4mOem6b9mGKd4Z3idmFdka0y1c892zfpMtLPaNpEV6D2Kj/Eauf6YeweQ9ieuTVz8K/3evbT4\n5NfQBKoAA8FxCvJxrUx/XMvevD8Zry8fz/Haf2RfjTx/6RSOnRMyypHu9kXjowrqVSrvPRnZVl6V\nkK0775MsUjvadn0nT4ow6bFijtSsVfPuFYvpPGtNTy54mfy6vorXDm8l9pEC7JIgBIgBIgBIgBIg\nBIgBIhIAgBIhIAgBIgBIIBIAAhIAhIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAAAAAAAAAAAA\nAAAAAAAAABAJQkAEAAAAAAAAAAjc3BIjdG4Mkbo5kcwMjdhzHMDPc3V8xzAs3N1fMjmBZubq+Y5g\nWbm6vmOYFm5ur5jmBZubq+Y5gWbm6vmOYFm5ur5jmBZubq+Y5gWbm6vmTzAz3N2HMnmBlu5ftFTx\nOEZJ/DMW/d0t2rxKni8N1FPWkiZ9eS08e7Cy8dGGn6UhZaJljXZGnmc3UT3dPP2cnUT78xCIV6j2\nH/8A9c/6f7vXPI+w8bU1U+vL/d63du5NfUiDcVSIAS8b7RV5eOb/AIqRL2TyXtNX/e2KfXH/AHlF\n+NPH/pr4+2xcxx0hFpY11K7R16KM32ZWz3UaidqSgrc9kcPicWyZJjfw6T+727y3sXh2xarN+K0V\nh6lvPjj3e0ASqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJQAAAAAkQAkQAkAAAAAAAAAAAAAAA\nEgAAAAAAAAAAAAAAAAAAAAAgAAABKDcAN0bgkY8xzAyRux5kcwM9zdXNkTcFm6OZXzMeYFvMibKu\nZHMC2bo51U2RuC2bom6rc3BZzom6sBZzI52ADPnOdggFnMc6skFnMc6rc3BbznOp3RzAv50c6nml\nHMC/nOf4qOY5wX85zqOc5wbHOc7X5znBsc6edr85zg2ec52vzpi4NjmY5bROG+/bllVzsNTk5dLl\nn0pP8BHmMHWNmzt0aum8obm08vVjfrtnxztR0mXHzTvaZdjVRMTLkZo6yiFen9iZ2pqY/wBP93rN\n3kPY+/LfPX1rE/u9XzN3HfqzdO6vmTuIZ7m7Hc3Bnu8t7TR/vHBP9E/y9Pu837SV31umn+if5Rfi\n/j/01MMb1hjkrtKzBG0bMsmOZY11tOYamr6Und0LUc7XT7u3rJPqL8er9lcPhcFpbzyWm39v7O00\n+FYvA4Zpsc94xxu227jv1IAgAAAAAAAAABKAAAASgASgBIgBIgBIgBIhIAAAAAAAAAAAAAAAAAAC\nUACUJAAAAAAAAAAAABIAAAAAAAAAAAAAAAAAAAAg3AEbomQZbo3YzLGbAz3RNlc3YzcFs2YzdVN2\nM2Bdzom6nmNwW86JurTAMuY3REJ2BB1ZRVMVBhsbSsiqeUFXLucq3lTygp5TlXcpygp5TlXcpygp\n5TlXcqOUFXKjlXcrGYBXysdlswiYBVMdUTCyY6sZBWxlnMMZgGLGZZSwkDdHMiWO4MuY5mEyjcFn\nN1OdVzHMC3nTzqeY5gX85zqOZPMC+Lqdbk20eb/RKOZr8QybaK/XvtH7iZ9aGlp2luzT3fg19NHS\nOjbmPcYX67XH1XSZ9XIzRvMuzrK7zLkZYmYnciunb9lZ5dTk+OP+71cXeP8AZnJ/ip2nf3J/l6iL\n/Fu5L9bMWZczXi6YuIbEWTzKIuyiwLt3nuO25uI4a/hx7/rLuczg8TicvFLbfdpEK6+NPH/phhjo\nstLGkctUWnoxrrU3j1cnWTzZq1jzl1clo5Zcu8c+txR63iP3Tn6pv4+g4o5cVI9IiGe7CJ2iE7t3\nGyN2O6dwSINwSISAlAAlACRAAlAAlACRACRCQAAAAAAAAAASgASISAAAAAAAAAAAAACQAAAAAAAA\nAAAAAASAAAAAAAAAAAAAAAAIAAAQCAJljuljsCJlhMs9mOwMJYys5TkBVsjZdyHICrZPKt5E8oK4\nqmKrOVOwMIqyirPY2Bjyp2ZbAI2NmSARsbMgEbI2ZAMdjZICNkbMkSCNmOzJEgx2YyzljMAwlhKy\nWEwCuWErJhhMArlhLOWEgxljMpljIImWMyTKJA3N0IBO5vux3NwZbnMx3NwZczT4jf3MdPW27a3a\nfJOq1XNP2KdIRfi+J2trSYfcjeF+Wm1OicVeWIiN9kai8xjY12ORqultnI1Ecsujq79XP1FovWYI\nrTgeq+j8QrWZ+3Mx+r2UXeC0WG2Ti2kiN5mL807eUREvbzbaejefHJv62Iv8WUXa0WTFhVtRdlF2\nrz9WUXBtc7jR9dqc2T1ttHyhvZMvJitb0jdq6XHNcNenWVN3028U99WRj6Kb02be3Tq18/SN2Lpc\n3UdN9nOmZrqKX/DaJ/d0svvTLRzV3jomK6+Pd1vvWJj0ZczT0mXxNJht60hfFnQ4qu3N1cWTEgs3\nTur5k7gz3N2O5uDM3Y7m4MtxBuCQASIASIASAAAAAAACRCQAAAAAAAAEoSAAAAAAAAAAAlAAlCQA\nAAAAAAAAAAASAAAAAAAAAAAAIASgAAAEJAQJQCNkbMgGOyOVnsAw5TlZ7GwMOVPKy2NgY7GzIBGx\nskA2AAAAAAAAAAQkBAEghEskAxYzDPZGwK5hjMLJhjMAqmGEwumrCagomFcw2JqqtUFEsLLrV82F\no7gqljKyYYTGwMZRKUSCAQAboJnaN5Bjkneu0d5W4ccViIiOzHFWbTzNumP1Zarr8eeRMbxDW1Mx\nNO67NbkhzNVnmInqzaOZrL93JyZeV0M1++7S02jvxDWxhxx033tPpC8Z6rrezWjmZyazJG2/u03h\n2vFibTHoqvamiwVwY+nLGzV0+SZ1Mx8G0/45tOhzJ5lXMc3UVXRdlF1HP+iYsDPLPPy49/tz1+Te\npSIr0ho6ak5Ms5J8o2q6NImOrHV7XX488ypzTtHXo0s9t6zG7c1G1qz6ubeZiZ3UatXJG3yauSO7\ncvMTEx5tPLb3prPRMVr0HB8vicNxf0+7+kt+LOJwTJyY/Bnz3tH93X36N58cWvq6LSyiyndMSlC7\nmZcymLJiwLosmJVRLKLAtiU7q4lMSCzc3YxJuDMRuAlKAEgAAAlAkAAAAAABKAEgAAAAAJAAAAAA\nAAAAAAAEgAAAAAAAAAAAAAkAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAhIAAACAAAASgAAAAAAEAAAA\nhGzJAImGMwzQDDZjNVuyNgUTVhNGxysZqDVmiu1G5NN2M4waM0+DCaN2cbGcQNGaMZq3JxMJxA1J\nqx2bU4kU09slorWNwa20z02RXHbJbl26QvtFovbHWkxEdJt5y2MOHlr2U1W3jx+1hiw8vSO63lmI\nXRTaEWmtY6snRHO1VpmJ+DjavpSZl2s8b7y4HFcnh0n0gha5ebJN55KRM2mdoiPN6fh+kpwXh0Wy\nRHj5Otp/s5Ps1p62y31+em9aTMYt/OfVfxTiPjZ52naI7fBrI5t66xz5+a1rW7yx0eSL6iZjtEOX\nqNbSletom3lENjh2fbHzbbWt3iVozruc+5ztWubf4M4ybpQ2Oboyrva0Vjza8WdDR4OkXt3n9ldX\nkaePP9VtYqctYhdvt5oivTeCZ2YOxXk6ubqMfV0b9mrljfqlFcq88k7z2U5axeItDa1OPessuC8P\nya7XRWYnwqdbT/ZMilvIu4dpslNdixXja8Y5tt85djZdbDWnGOesRtXFtuw6T27No5Kx2OrKYQlC\nExKJgBnEpiyvdlEgsizKLKollFgWxLKJVRLKJBbEp3VxLKJBnuMWQJEbpBIAAAJAAAABIAAAAAAA\nlAJAAAAAAAAAAAAAASAAAAAAAAAAAAAJAAAABAJABAlAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAA\nAAABAJQAAAAgAABAAI2EoBGyJhkgGPKxmqxAKpownHC+YRMdN5BrTj67R3bOn01o7p01Iv71u89o\nb9a7LfBTfS1vWI2jf12VfQPSW8KX2mas+NC2iv6xMNfJpMnLtEbuuxtMRCtzF55NR5rPps1N/ctP\ny6uHreE6nXZ4pak48X3rT06fB7fNeI33cbX6mI32R/MWu7XF116aDSRhxbRERs8f499bkyZeeKae\nkzE2mdon81/tfxDLGOunwbzlzbx08oaHBvZHJlx48mrvaa94pu04y617576rNGLRRM0397JEd/lu\n9Dw/S3x4qxffo6mm4NjwUiKY4iI9Ib1dHFY6QIaNabbrYrLfrpJtaK1rMzPZb/s+05IpP59OyLeJ\nk7eNfRaOc1ue32I7fGXYpi5Y77M8OGMeOKxHSFsU3Y29deZMzirl6dlVvhLatCjJHeYQv1rXnps1\n8k9/VsW6qLVmZIi1rzitlvFKRvaZ2h6TSaenC9FFY+3brM+sqeG8Prp4+kZ+lvuxPkr1mqm95nfp\nDXM459676a2q1dsV7XietvNno78+CJn1cjX6mOeIm0bR33dfRU5NJjidt9t5afjG/V6JZ7I2QMNh\nnyo2BhsMuVG3wAhMSbbQRAMolnE+iuGUSCyJZRKuGUSCyJZK4llEgyZMYTuCUsYSCQASISAAAlCQ\nAAAAAAEoASCASAAAAAAAAAAAAlACRACQAAAAAAAAAEgCEoASCAAAAAAAAAAAAAAAAAAAAAAABAAA\nAAAAAAAISAIAAAAAAQAAACASgAAAQJAQAAhIDHZhln3do7z0WS18mWsajHjmes7pg3dNi5aRMNqO\nyvDHTpPRaigHZhN4hHRlaVN59JY3zRENLUavaO+yq0iNVlitJ6vNcR1MVi0zO0era1/Ea0rPvbz5\nPM5MWp45qvo2GZrhmfrsnpHpHzTCseEcM/2vrr8Q1Eb4qzy44nziPN63HpYiIiI7LNHoqabBTFii\nIpSNohuVxrKtWMEejPwY9G1FFmHB4mWJn7MdfnIM9JpIx15to5pbUaas/a6rqViI7MxPxqX0UT1r\nO3wVzpbR2hviP5i03Y5s6a879FNtHljydhExCv8AMTPJXBnRZbz0iG5ptFjwe/l96zctMVamTJtE\nyTMibu1VrdTzRMR0j0ed4lr64MVpm0RERvMz5NvX62uOJ69XhOKX1HH9bHDtFvNYnfJeOy0Z2ojX\n6jjnEq6fRUmccTvN/J9H0eKcOnx45neaxEbubwHgOHg+milI3vP2resu3Wu0JQmITsmISDHZHKz2\nJgFc1RMLJhGwK9iIZ7MZgEdgmAEwyiWCdwWRLKJVxKYsC2JTuriWUSDNlEsIlMAySx3SCRCQSIAS\nAAACRACQAAAAAAASIASAAAAAAAAAAAAAAACRACRACQASIAAAAAAAAAAAAAAAAAAAAAAAAQCUAAAA\nAAAAAAIAAAAAAAAQAAAAAACBICBICAAEJAQJQCJcLjuS2ny6fPG/LWdpd1o8T0X07SXx/e7wCdJx\nWa0jmneHQpxPDMdZmJfNtZm49weZrh0/j4o7VtSZ2+Uw0/8A7o49k92vBLc/ntFohFW9PqGXimOI\n6Tu1L8T3eCx6r2t1O3JwvHjifO99v7t/Bwf2l1PXU6rS6eJ8qUm8x+so5TsekzcSjbvs4mt4rzW5\nK2mbT0itesy2cHsvbvqtbmyz5xERWP2jd1tJwrTaONsOKtZ8585+cnDrzmn4Rq+IZObUROHD32n7\nVv8A0ej0uhxaXFGPFSK1j0bkY4jyZRVZVXFGUVWbGwKsk8mObekNrSW3pWf1a2aYjHbm7bNnQ1id\nPW0TvuDdhJEbQABMsLW2R0ZTMQrvfbz2YWzVhpanUxEd0dWkW5c8R5uXxDX1w4pnfr5Q19XxKuOJ\n2neXltVqtVxbV/RdJ715+1bypANfiOu1HENV9C0MTfNeesx2rD1PAeBYuE6aKx72W3W9/WVnBuB4\neF4dqRzZbdb5J72l160WVK02ZxCYhOwI23TsnY2BGxsnYBjsiYZsZBjMMZZSgGEolMsQDdG6NwZ7\npiVe6YkFsSziVMWZRILolMSriWUSCyJTuwhMSDMRCQSI3SAlACRCQAAEoAEoASAAAAAAAAACUACR\nACQAAAAAAAAAAAAASAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAABAAAAAAAAAAAAACBKAAAAAAAQ\nJQAAAhICEbJAYTWJ7wx8KvpC0BV4ceieWGewDHlNmWwCNjZICNhIDmcZredBecdpiY69FXCOLW+i\nUiZidukulmxxlx2paN4mNng+K4+I8Hy2yaTfl37TXetoCPfRxfp1qi3F48ofKMvtvxak8s6LDv61\nrZji9rPaLUf5PC+bfttS0q8q3p9W/wBrRMdpUZuKdN99nzvFqPbTVz7nD8OKs+do2/mW3h4D7Xaq\nZnPrtNpqz35aRaYOHY9Zk4pNt9rR+rl6zi+OnS+WN57Rv1lXp/YrNaYtruL6zNPnGO3hxP6O5w/2\nf0HDuun09Yv55Le9afznqcOvO4tBreMTHu30unnva0bWt8on+70nDuE4OHYYx4Kbesz3tPrMuhGO\nIjpDOKrK9YVpsyiGUQnYGOyUgI2SlAIEmwMWMs9kTAMJYzDOYRMArmGErZhhMArlHmzmGMwDE3Ts\nbAbs4swj5pgFkSziVcM4BZEsolXDKAZwyhjCYBkACQhIAAAAAAAJAAAAAAAAAAAAAAAAAAAShIAA\nAAAAAAJAAAAAAAAAAAAAABAJEAAAAAAAAAAAAAAAIEoBKAAAAAAAAAAAAAAABAlAAAAAAAIAAAAA\nBAkBAkBAkBAlACEgMZjdjbFW8bWrEx8YWANb6Fp+bfwab+vLDKMFK9qxH5L0bAr8OPRPKz2AY7J2\nSbAjYZAI2E7AIEgIEgIEgMdkSy2NgY7MdlmyNoBXsxmFuyNgVTVjNV3KjlBRNTlXTVHKCrlIqt5T\nlBhEMohlFerLlBjEMohMVTEARDKCITsAk2AEgAAAkAAAAAAAAAAAAAAAAAAAAAAAASAAAAAAAAD/\n2Q==`;async function g0e(e){let t=(r,s=\"application/octet-stream\")=>fetch(`data:${s};base64,${r}`).then(i=>i.blob()),a,n;switch(e.config.warmup){case\"face\":a=await t(B0);break;case\"body\":case\"full\":a=await t(W0);break;default:a=null}if(a){let r=await createImageBitmap(a);n=await e.detect(r,e.config),r.close()}return n}async function x0e(e){return new Promise(t=>{let a;switch(e.config.warmup){case\"face\":a=\"data:image/jpeg;base64,\"+B0;break;case\"full\":case\"body\":a=\"data:image/jpeg;base64,\"+W0;break;default:a=\"\"}let n;if(typeof Image!=\"undefined\")n=new Image;else if(ne.Image)n=new ne.Image;else{t(void 0);return}n.onload=async()=>{let r=Nn(n.naturalWidth,n.naturalHeight);if(!r)K(\"Warmup: Canvas not found\"),t(void 0);else{let s=r.getContext(\"2d\");s&&s.drawImage(n,0,0);let i=await e.image(r,!0),o=i.tensor?await e.detect(i.tensor,e.config):void 0;t(o)}},a?n.src=a:t(void 0)})}async function A0e(e){let t=r=>Buffer.from(r,\"base64\"),a;e.config.warmup===\"face\"?a=t(B0):a=t(W0);let n;if(\"node\"in Ue&&ia()===\"tensorflow\"){let r=(void 0).decodeJpeg(a),s=Gt(r,0);e.tf.dispose(r),n=await e.detect(s,e.config),e.tf.dispose(s)}else e.config.debug&&K(\"Warmup tfjs-node not loaded\");return n}async function y0e(e){let t;return typeof createImageBitmap==\"function\"?t=await g0e(e):typeof Image!=\"undefined\"||ne.Canvas!==void 0?t=await x0e(e):t=await A0e(e),t}async function b0e(e){var o,l,u,p;if(!W().flagRegistry.ENGINE_COMPILE_ONLY)return;let t=ia(),a=tr();if(t!==\"webgl\"&&t!==\"humangl\"||!(a!=null&&a.checkCompileCompletion))return;W().set(\"ENGINE_COMPILE_ONLY\",!0);let n=kt().state.numTensors,r=[];for(let[c,d]of Object.entries(e.models.models)){if(!d)continue;let h=(d==null?void 0:d.modelSignature)&&((l=(o=d==null?void 0:d.inputs)==null?void 0:o[0])==null?void 0:l.shape)?[...d.inputs[0].shape]:[1,64,64,3],f=(d==null?void 0:d.modelSignature)&&((p=(u=d==null?void 0:d.inputs)==null?void 0:u[0])==null?void 0:p.dtype)?d.inputs[0].dtype:\"float32\";for(let g=0;g<h.length;g++)h[g]===-1&&(h[g]=g===0?1:64);let m=fn(h,f);try{let g=d.execute(m);r.push(c),Array.isArray(g)?g.forEach(x=>Y(x)):Y(g)}catch(g){e.config.debug&&K(\"compile fail model:\",c)}Y(m)}let s=await a.checkCompileCompletionAsync();a.getUniformLocations(),e.config.debug&&K(\"compile pass:\",{models:r,kernels:s.length}),W().set(\"ENGINE_COMPILE_ONLY\",!1);let i=kt().state.numTensors;i-n>0&&K(\"tensor leak:\",i-n)}async function Yk(e,t){await wp(e,!1);let a=te();return e.state=\"warmup\",t&&(e.config=Ct(e.config,t)),!e.config.warmup||e.config.warmup.length===0||e.config.warmup===\"none\"?or():new Promise(async n=>{await e.models.load(),await b0e(e);let r=await y0e(e),s=te();e.config.debug&&K(\"warmup\",e.config.warmup,Math.round(s-a),\"ms\"),e.emit(\"warmup\"),n(r)})}var Mu,Mp,$p,V0,Is,A5=class{constructor(t){ue(this,\"version\");ue(this,\"config\");ue(this,\"result\");ue(this,\"state\");ue(this,\"process\");ue(this,\"tf\");ue(this,\"env\",ne);ue(this,\"draw\",s0);ue(this,\"match\",$0);ue(this,\"models\");ue(this,\"events\");ue(this,\"faceTriangulation\");ue(this,\"faceUVMap\");ue(this,\"performance\");Gn(this,Mu,void 0);Gn(this,Mp,void 0);Gn(this,$p,void 0);ue(this,\"analyze\",(...t)=>{if(!Ga(this,Mp))return;let a=this.tf.engine().state.numTensors,n=Ga(this,Mu);fr(this,Mu,a);let r=a-n;r!==0&&K(...t,r)});Gn(this,V0,t=>{if(!Ga(this,$p))return null;if(!t)return\"input is not defined\";if(this.env.node&&!(t instanceof pt))return\"input must be a tensor\";try{this.tf.getBackend()}catch(a){return\"backend not loaded\"}return null});ue(this,\"webcam\",new Jh);ue(this,\"emit\",t=>{var a;(a=this.events)!=null&&a.dispatchEvent&&this.events.dispatchEvent(new Event(t))});Gn(this,Is,{});let a=(xp.tfjs||A2).replace(/-(.*)/,\"\");Io.wasmPath=`https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@${a}/dist/`,Io.modelBasePath=ne.browser?\"../models/\":\"file://models/\",this.version=X3,Object.defineProperty(this,\"version\",{value:X3}),this.config=JSON.parse(JSON.stringify(Io)),Object.seal(this.config),this.config.cacheModels=typeof indexedDB!=\"undefined\",t&&(this.config=Ct(this.config,t)),u9(this.config),this.tf=Ue,this.state=\"idle\",fr(this,Mu,0),fr(this,Mp,!1),fr(this,$p,!1),this.performance={},this.events=typeof EventTarget!=\"undefined\"?new EventTarget:void 0,this.models=new Rp(this),tg(),this.result=or(),this.process={tensor:null,canvas:null},this.faceTriangulation=tw,this.faceUVMap=aw,L0(this,null,\"\"),this.emit(\"create\"),(this.config.debug||this.env.browser)&&K(`version: ${this.version}`),this.config.debug&&K(`tfjs version: ${this.tf.version[\"tfjs-core\"]}`);let n=JSON.parse(JSON.stringify(this.env));delete n.kernels,delete n.initial,delete n.perfadd,this.config.debug&&K(\"environment:\",n)}reset(){let t=this.config.backend;this.config=JSON.parse(JSON.stringify(Io)),this.config.backend=t,j3(),ne.initial=!0}validate(t){let a=U3(Io,t||this.config);return a.length===0&&(this.config=Ct(this.config,t)),a}now(){return te()}image(t,a=!1){return Zh(t,this.config,a)}async segmentation(t,a){var s,i,o;if(a&&(this.config=Ct(this.config,a)),!this.config.segmentation.enabled)return null;let n=await Zh(t,this.config);if(!n.tensor)return null;let r=null;return(s=this.config.segmentation.modelPath)!=null&&s.includes(\"rvm\")&&(r=await jk(n.tensor,this.config)),(i=this.config.segmentation.modelPath)!=null&&i.includes(\"meet\")&&(r=await Ik(n.tensor,this.config)),(o=this.config.segmentation.modelPath)!=null&&o.includes(\"selfie\")&&(r=await Xk(n.tensor,this.config)),Y(n.tensor),r}compare(t,a){return l9(this.config,t,a)}async init(){await wp(this,!0),await this.tf.ready(),j3()}async load(t){this.state=\"load\";let a=te(),n=Object.values(this.models.models).filter(i=>i).length;t&&(this.config=Ct(this.config,t)),this.env.initial&&(await wp(this,!1)||K(\"error: backend check failed\"),await Kd(),this.env.browser&&(this.config.debug&&K(\"configuration:\",this.config),this.config.debug&&K(\"tf flags:\",this.tf.ENV.flags))),await this.models.load(this),this.env.initial&&this.config.debug&&K(\"tf engine state:\",this.tf.engine().state.numBytes,\"bytes\",this.tf.engine().state.numTensors,\"tensors\"),this.env.initial=!1,Object.values(this.models.models).filter(i=>i).length!==n&&(this.models.validate(),this.emit(\"load\"));let s=Math.trunc(te()-a);s>(this.performance.loadModels||0)&&(this.performance.loadModels=this.env.perfadd?(this.performance.loadModels||0)+s:s)}next(t=this.result){return kk(t,this.config)}async warmup(t){let a=te(),n=await Yk(this,t),r=te();return this.performance.warmup=Math.trunc(r-a),n}async profile(t,a){let n=await this.tf.profile(()=>this.detect(t,a)),r={},s=0;for(let o of n.kernels){let l=Number(o.kernelTimeMs)||0;r[o.name]?r[o.name]+=l:r[o.name]=l,s+=l}let i=[];Object.entries(r).forEach(o=>i.push({kernel:o[0],time:o[1],perc:0}));for(let o of i)o.perc=Math.round(1e3*o.time/s)/1e3,o.time=Math.round(1e3*o.time)/1e3;return i.sort((o,l)=>l.time-o.time),i.length=20,i}async detect(t,a){return this.state=\"detect\",new Promise(async n=>{var g,x,A,y,b,w,S,C,E,_,$,M,I,N,O,L,B,G,j,U,H;this.state=\"config\";let r;this.config=Ct(this.config,a),this.state=\"check\";let s=Ga(this,V0).call(this,t);s&&(K(s,t),this.emit(\"error\"),n(or(s)));let i=te();await this.load(),r=te(),this.state=\"image\";let o=await Zh(t,this.config);if(this.process=o,this.performance.inputProcess=this.env.perfadd?(this.performance.inputProcess||0)+Math.trunc(te()-r):Math.trunc(te()-r),this.analyze(\"Get Image:\"),!o.tensor){this.config.debug&&K(\"could not convert input to tensor\"),this.emit(\"error\"),n(or(\"could not convert input to tensor\"));return}this.emit(\"image\"),r=te(),this.config.skipAllowed=await o9(this.config,o.tensor),this.config.filter.autoBrightness=(this.config.filter.autoBrightness||!1)&&this.config.skipAllowed,this.performance.totalFrames||(this.performance.totalFrames=0),this.performance.cachedFrames||(this.performance.cachedFrames=0),this.performance.totalFrames++,this.config.skipAllowed&&this.performance.cachedFrames++,this.performance.cacheCheck=this.env.perfadd?(this.performance.cacheCheck||0)+Math.trunc(te()-r):Math.trunc(te()-r),this.analyze(\"Check Changed:\");let l=[],u=[],p=[],c=[];this.state=\"detect:face\",this.config.async?(l=this.config.face.enabled?Vg(this,o.tensor):[],this.performance.face&&delete this.performance.face):(r=te(),l=this.config.face.enabled?await Vg(this,o.tensor):[],this.performance.face=this.env.perfadd?(this.performance.face||0)+Math.trunc(te()-r):Math.trunc(te()-r)),this.config.async&&(this.config.body.maxDetected===-1||this.config.hand.maxDetected===-1)&&(l=await l),this.analyze(\"Start Body:\"),this.state=\"detect:body\";let d=this.config.body.maxDetected===-1?Ct(this.config,{body:{maxDetected:this.config.face.enabled?1*l.length:1}}):this.config;this.config.async?((g=this.config.body.modelPath)!=null&&g.includes(\"posenet\")?u=this.config.body.enabled?c5(o.tensor,d):[]:(x=this.config.body.modelPath)!=null&&x.includes(\"blazepose\")?u=this.config.body.enabled?ig(o.tensor,d):[]:(A=this.config.body.modelPath)!=null&&A.includes(\"efficientpose\")?u=this.config.body.enabled?hg(o.tensor,d):[]:(y=this.config.body.modelPath)!=null&&y.includes(\"movenet\")&&(u=this.config.body.enabled?s5(o.tensor,d):[]),this.performance.body&&delete this.performance.body):(r=te(),(b=this.config.body.modelPath)!=null&&b.includes(\"posenet\")?u=this.config.body.enabled?await c5(o.tensor,d):[]:(w=this.config.body.modelPath)!=null&&w.includes(\"blazepose\")?u=this.config.body.enabled?await ig(o.tensor,d):[]:(S=this.config.body.modelPath)!=null&&S.includes(\"efficientpose\")?u=this.config.body.enabled?await hg(o.tensor,d):[]:(C=this.config.body.modelPath)!=null&&C.includes(\"movenet\")&&(u=this.config.body.enabled?await s5(o.tensor,d):[]),this.performance.body=this.env.perfadd?(this.performance.body||0)+Math.trunc(te()-r):Math.trunc(te()-r)),this.analyze(\"End Body:\"),this.analyze(\"Start Hand:\"),this.state=\"detect:hand\";let h=this.config.hand.maxDetected===-1?Ct(this.config,{hand:{maxDetected:this.config.face.enabled?2*l.length:1}}):this.config;this.config.async?((_=(E=this.config.hand.detector)==null?void 0:E.modelPath)!=null&&_.includes(\"handdetect\")?p=this.config.hand.enabled?qg(o.tensor,h):[]:(M=($=this.config.hand.detector)==null?void 0:$.modelPath)!=null&&M.includes(\"handtrack\")&&(p=this.config.hand.enabled?Zg(o.tensor,h):[]),this.performance.hand&&delete this.performance.hand):(r=te(),(N=(I=this.config.hand.detector)==null?void 0:I.modelPath)!=null&&N.includes(\"handdetect\")?p=this.config.hand.enabled?await qg(o.tensor,h):[]:(L=(O=this.config.hand.detector)==null?void 0:O.modelPath)!=null&&L.includes(\"handtrack\")&&(p=this.config.hand.enabled?await Zg(o.tensor,h):[]),this.performance.hand=this.env.perfadd?(this.performance.hand||0)+Math.trunc(te()-r):Math.trunc(te()-r)),this.analyze(\"End Hand:\"),this.analyze(\"Start Object:\"),this.state=\"detect:object\",this.config.async?((B=this.config.object.modelPath)!=null&&B.includes(\"nanodet\")?c=this.config.object.enabled?o5(o.tensor,this.config):[]:(G=this.config.object.modelPath)!=null&&G.includes(\"centernet\")&&(c=this.config.object.enabled?ug(o.tensor,this.config):[]),this.performance.object&&delete this.performance.object):(r=te(),(j=this.config.object.modelPath)!=null&&j.includes(\"nanodet\")?c=this.config.object.enabled?await o5(o.tensor,this.config):[]:(U=this.config.object.modelPath)!=null&&U.includes(\"centernet\")&&(c=this.config.object.enabled?await ug(o.tensor,this.config):[]),this.performance.object=this.env.perfadd?(this.performance.object||0)+Math.trunc(te()-r):Math.trunc(te()-r)),this.analyze(\"End Object:\"),this.state=\"detect:await\",this.config.async&&([l,u,p,c]=await Promise.all([l,u,p,c])),this.state=\"detect:gesture\";let f=[];this.config.gesture.enabled&&(r=te(),f=[...Qw(l),...Jw(u),...tk(p),...ek(l)],this.config.async?this.performance.gesture&&delete this.performance.gesture:this.performance.gesture=this.env.perfadd?(this.performance.gesture||0)+Math.trunc(te()-r):Math.trunc(te()-r)),this.performance.total=this.env.perfadd?(this.performance.total||0)+Math.trunc(te()-i):Math.trunc(te()-i);let m=((H=this.process.tensor)==null?void 0:H.shape)||[0,0,0,0];this.result={face:l,body:u,hand:p,gesture:f,object:c,performance:this.performance,canvas:this.process.canvas,timestamp:Date.now(),error:null,width:m[2],height:m[1],get persons(){return Zk(l,u,p,f,m)}},Y(o.tensor),this.emit(\"detect\"),this.state=\"idle\",n(this.result)})}async sleep(t){return new Promise(a=>{setTimeout(a,t)})}async video(t,a=!0,n=0){a?(Ga(this,Is)[t.id]||(this.config.debug&&K(\"video start\",t.id),Ga(this,Is)[t.id]=!0),!t.paused&&Ga(this,Is)[t.id]&&t.readyState>=2&&await this.detect(t),n>0&&await this.sleep(n),Ga(this,Is)[t.id]&&requestAnimationFrame(()=>this.video(t,a,n))):(this.config.debug&&K(\"video stop\",t.id),Ga(this,Is)[t.id]=!1)}};Mu=new WeakMap,Mp=new WeakMap,$p=new WeakMap,V0=new WeakMap,Is=new WeakMap;return OI(w0e);})();\n"
  },
  {
    "path": "extern/human/models/blazeface.json",
    "content": "{\n  \"format\": \"graph-model\",\n  \"generatedBy\": \"https://github.com/google/mediapipe\",\n  \"convertedBy\": \"https://github.com/vladmandic\",\n  \"userDefinedMetadata\":\n  {\n    \"signature\":\n    {\n      \"inputs\":\n      {\n        \"input:0\":{\"name\":\"input:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"256\"},{\"size\":\"256\"},{\"size\":\"3\"}]}}\n      },\n      \"outputs\":\n      {\n        \"Identity_3:0\":{\"name\":\"Identity_3:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"384\"},{\"size\":\"16\"}]}},\"Identity:0\":{\"name\":\"Identity:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"512\"},{\"size\":\"1\"}]}},\n        \"Identity_1:0\":{\"name\":\"Identity_1:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"384\"},{\"size\":\"1\"}]}},\"Identity_2:0\":{\"name\":\"Identity_2:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"512\"},{\"size\":\"16\"}]}}\n      }\n    }\n  },\n  \"modelTopology\":\n  {\n      \"node\":\n      [\n          {\"name\":\"unknown_135\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_136\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"2\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_1/classificators_1/shape\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"unknown_133\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"6\"}]}}}}},\n          {\"name\":\"unknown_134\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"6\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_2/classificators_2/shape\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_INT32\"},\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"}]}}}}},\n          {\"name\":\"unknown_131\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_132\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_1/regressors_1/shape\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"unknown_93\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"48\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_95\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"48\"},{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_96\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_61\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_63\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_64\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_57\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_59\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_60\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_53\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_55\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_56\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_49\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_51\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_52\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown_29\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_31\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_32\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"5\"},{\"size\":\"5\"},{\"size\":\"3\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_0\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_3\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown_4\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_5\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_7\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_8\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown_9\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_11\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_12\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_13\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_15\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown_16\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_17\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_19\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_20\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown_21\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_23\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_24\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown_25\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_27\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_28\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_33\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_35\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown_36\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_37\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_39\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}}}},\n          {\"name\":\"unknown_40\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_41\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_43\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_44\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_45\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"24\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_47\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"24\"},{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_48\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"24\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad/Pad/paddings\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"4\"},{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"unknown_65\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"48\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_67\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"48\"},{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_68\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_69\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"48\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_71\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"48\"},{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_72\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"48\"}]}}}}},\n          {\"name\":\"unknown_73\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"48\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_75\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"48\"},{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_76\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"48\"}]}}}}},\n          {\"name\":\"unknown_77\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"48\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_79\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"48\"},{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_80\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_81\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"48\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_83\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"48\"},{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_84\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"48\"}]}}}}},\n          {\"name\":\"unknown_85\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"48\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_87\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"48\"},{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_88\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"48\"}]}}}}},\n          {\"name\":\"unknown_89\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"48\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_91\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"48\"},{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_92\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"48\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad_1/Pad_1/paddings\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"4\"},{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"unknown_97\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"96\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_99\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}}}},\n          {\"name\":\"unknown_100\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_101\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"96\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_103\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}}}},\n          {\"name\":\"unknown_104\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_105\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"96\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_107\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_108\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_109\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"96\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_111\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_112\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_113\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"96\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_115\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_116\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_117\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"96\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_119\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_120\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}}}},\n          {\"name\":\"unknown_121\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"96\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_123\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_124\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_125\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"96\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_127\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}}}},\n          {\"name\":\"unknown_128\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_129\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"96\"},{\"size\":\"96\"}]}}}}},\n          {\"name\":\"unknown_130\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"96\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_2/regressors_2/shape\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"input\",\"op\":\"Placeholder\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"shape\":{\"shape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"256\"},{\"size\":\"256\"},{\"size\":\"3\"}]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d/Relu\",\"op\":\"_FusedConv2D\",\"input\":[\"input\",\"unknown\",\"unknown_0\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"U0FNRQ==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UmVsdQ==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d/Relu\",\"unknown_1\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_1/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d/depthwise\",\"unknown_3\",\"unknown_4\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_1/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_1/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu/Relu\",\"unknown_5\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_2/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_1/depthwise\",\"unknown_7\",\"unknown_8\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_1/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_2/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_1/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_1/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_2/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_1/Relu\",\"unknown_9\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_3/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_2/depthwise\",\"unknown_11\",\"unknown_12\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_2/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_1/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_3/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_2/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_2/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_3/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_2/Relu\",\"unknown_13\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_4/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_3/depthwise\",\"unknown_15\",\"unknown_16\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_3/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_2/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_4/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_3/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_3/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_4/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_3/Relu\",\"unknown_17\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_5/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_4/depthwise\",\"unknown_19\",\"unknown_20\"],\"device\":\"/device:CPU:0\",\"attr\":{\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_4/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_3/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_5/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_4/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_4/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_5/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_4/Relu\",\"unknown_21\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_6/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_5/depthwise\",\"unknown_23\",\"unknown_24\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_5/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_4/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_6/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_5/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_5/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_6/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_5/Relu\",\"unknown_25\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_7/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_6/depthwise\",\"unknown_27\",\"unknown_28\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_6/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_5/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_7/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_6/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_6/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_7/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_6/Relu\",\"unknown_29\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/max_pooling2d/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_6/Relu\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_8/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_7/depthwise\",\"unknown_31\",\"unknown_32\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_7/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_8/BiasAdd\",\"StatefulPartitionedCall/functional_1/max_pooling2d/MaxPool\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_7/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_7/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_8/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_7/Relu\",\"unknown_33\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_9/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_8/depthwise\",\"unknown_35\",\"unknown_36\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_8/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_7/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_9/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_8/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_8/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_9/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_8/Relu\",\"unknown_37\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_10/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_9/depthwise\",\"unknown_39\",\"unknown_40\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_9/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_8/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_10/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_9/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_9/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_10/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_9/Relu\",\"unknown_41\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_11/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_10/depthwise\",\"unknown_43\",\"unknown_44\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_10/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_9/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_11/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_10/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_10/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_11/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_10/Relu\",\"unknown_45\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_12/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_11/depthwise\",\"unknown_47\",\"unknown_48\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_11/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_10/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_12/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_11/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_11/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_12/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_11/Relu\",\"unknown_49\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_13/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_12/depthwise\",\"unknown_51\",\"unknown_52\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_12/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_13/BiasAdd\",\"StatefulPartitionedCall/functional_1/re_lu_11/Relu\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_12/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_12/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_13/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_12/Relu\",\"unknown_53\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_14/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_13/depthwise\",\"unknown_55\",\"unknown_56\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_13/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_14/BiasAdd\",\"StatefulPartitionedCall/functional_1/re_lu_12/Relu\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_13/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_13/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_14/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_13/Relu\",\"unknown_57\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_15/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_14/depthwise\",\"unknown_59\",\"unknown_60\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_14/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_15/BiasAdd\",\"StatefulPartitionedCall/functional_1/re_lu_13/Relu\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_14/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_14/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_15/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_14/Relu\",\"unknown_61\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/max_pooling2d_1/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_14/Relu\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_16/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_15/depthwise\",\"unknown_63\",\"unknown_64\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad/Pad\",\"op\":\"Pad\",\"input\":[\"StatefulPartitionedCall/functional_1/max_pooling2d_1/MaxPool\",\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad/Pad/paddings\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"Tpaddings\":{\"type\":\"DT_INT32\"},\"_cloned\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_15/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_16/BiasAdd\",\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad/Pad\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_15/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_15/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_16/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_15/Relu\",\"unknown_65\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_17/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_16/depthwise\",\"unknown_67\",\"unknown_68\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_16/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_15/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_17/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_16/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_16/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_17/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_16/Relu\",\"unknown_69\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_18/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_17/depthwise\",\"unknown_71\",\"unknown_72\"],\"device\":\"/device:CPU:0\",\"attr\":{\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_17/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_16/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_18/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_17/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_17/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_18/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_17/Relu\",\"unknown_73\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_19/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_18/depthwise\",\"unknown_75\",\"unknown_76\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_18/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_17/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_19/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_18/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_18/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_19/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_18/Relu\",\"unknown_77\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_20/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_19/depthwise\",\"unknown_79\",\"unknown_80\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_19/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_18/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_20/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_19/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_19/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_20/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_19/Relu\",\"unknown_81\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_21/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_20/depthwise\",\"unknown_83\",\"unknown_84\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_20/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_19/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_21/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_20/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_20/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_21/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_20/Relu\",\"unknown_85\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_22/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_21/depthwise\",\"unknown_87\",\"unknown_88\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_21/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_20/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_22/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_21/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_21/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_22/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_21/Relu\",\"unknown_89\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_23/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_22/depthwise\",\"unknown_91\",\"unknown_92\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_22/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_21/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_23/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_22/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_22/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_23/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_22/Relu\",\"unknown_93\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/max_pooling2d_2/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_22/Relu\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_24/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_23/depthwise\",\"unknown_95\",\"unknown_96\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad_1/Pad_1\",\"op\":\"Pad\",\"input\":[\"StatefulPartitionedCall/functional_1/max_pooling2d_2/MaxPool\",\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad_1/Pad_1/paddings\"],\"attr\":{\"Tpaddings\":{\"type\":\"DT_INT32\"},\"_cloned\":{\"b\":true},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_23/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_24/BiasAdd\",\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad_1/Pad_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_23/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_23/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_24/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_23/Relu\",\"unknown_97\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_25/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_24/depthwise\",\"unknown_99\",\"unknown_100\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_24/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_23/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_25/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_24/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_24/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_25/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_24/Relu\",\"unknown_101\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_26/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_25/depthwise\",\"unknown_103\",\"unknown_104\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_25/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_24/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_26/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_25/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_25/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_26/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_25/Relu\",\"unknown_105\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_27/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_26/depthwise\",\"unknown_107\",\"unknown_108\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_26/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_25/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_27/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_26/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_26/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_27/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_26/Relu\",\"unknown_109\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_28/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_27/depthwise\",\"unknown_111\",\"unknown_112\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_27/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_26/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_28/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_27/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_27/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_28/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_27/Relu\",\"unknown_113\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_29/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_28/depthwise\",\"unknown_115\",\"unknown_116\"],\"device\":\"/device:CPU:0\",\"attr\":{\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_28/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_27/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_29/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_28/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_28/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_29/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_28/Relu\",\"unknown_117\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_30/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_29/depthwise\",\"unknown_119\",\"unknown_120\"],\"device\":\"/device:CPU:0\",\"attr\":{\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_29/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_28/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_30/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_29/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_29/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_30/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_29/Relu\",\"unknown_121\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_31/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_30/depthwise\",\"unknown_123\",\"unknown_124\"],\"device\":\"/device:CPU:0\",\"attr\":{\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/add_30/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_29/Relu\",\"StatefulPartitionedCall/functional_1/conv2d_31/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_30/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/functional_1/add_30/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_33/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_30/Relu\",\"unknown_135\",\"unknown_136\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"U0FNRQ==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_35/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_30/Relu\",\"unknown_131\",\"unknown_132\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"U0FNRQ==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/depthwise_conv2d_31/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_30/Relu\",\"unknown_125\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_1/classificators_1\",\"op\":\"Reshape\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_33/BiasAdd\",\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_1/classificators_1/shape\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"Tshape\":{\"type\":\"DT_INT32\"},\"_cloned\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_1/regressors_1\",\"op\":\"Reshape\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_35/BiasAdd\",\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_1/regressors_1/shape\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"Tshape\":{\"type\":\"DT_INT32\"},\"_cloned\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/re_lu_31/Relu\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/depthwise_conv2d_31/depthwise\",\"unknown_127\",\"unknown_128\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UmVsdQ==\"]}}}},\n          {\"name\":\"Identity\",\"op\":\"Identity\",\"input\":[\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_1/classificators_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"Identity_2\",\"op\":\"Identity\",\"input\":[\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_1/regressors_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_36/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_31/Relu\",\"unknown_129\",\"unknown_130\"],\"device\":\"/device:CPU:0\",\"attr\":{\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/conv2d_34/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/functional_1/re_lu_31/Relu\",\"unknown_133\",\"unknown_134\"],\"device\":\"/device:CPU:0\",\"attr\":{\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"U0FNRQ==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_2/regressors_2\",\"op\":\"Reshape\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_36/BiasAdd\",\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_2/regressors_2/shape\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"Tshape\":{\"type\":\"DT_INT32\"},\"_cloned\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_2/classificators_2\",\"op\":\"Reshape\",\"input\":[\"StatefulPartitionedCall/functional_1/conv2d_34/BiasAdd\",\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_2/classificators_2/shape\"],\"attr\":{\"_cloned\":{\"b\":true},\"T\":{\"type\":\"DT_FLOAT\"},\"Tshape\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"Identity_3\",\"op\":\"Identity\",\"input\":[\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_2/regressors_2\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"Identity_1\",\"op\":\"Identity\",\"input\":[\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_2/classificators_2\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}}\n      ],\n      \"library\": {},\n      \"versions\": {}\n  },\n  \"weightsManifest\":\n  [\n      {\n          \"paths\": [\"blazeface.bin\"],\n          \"weights\": [{\"name\":\"unknown_135\",\"shape\":[1,1,96,2],\"dtype\":\"float32\"},{\"name\":\"unknown_136\",\"shape\":[2],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_1/classificators_1/shape\",\"shape\":[3],\"dtype\":\"int32\"},{\"name\":\"unknown_133\",\"shape\":[1,1,96,6],\"dtype\":\"float32\"},{\"name\":\"unknown_134\",\"shape\":[6],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_classificators_2/classificators_2/shape\",\"shape\":[3],\"dtype\":\"int32\"},{\"name\":\"unknown_131\",\"shape\":[1,1,96,32],\"dtype\":\"float32\"},{\"name\":\"unknown_132\",\"shape\":[32],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_1/regressors_1/shape\",\"shape\":[3],\"dtype\":\"int32\"},{\"name\":\"unknown_93\",\"shape\":[3,3,48,1],\"dtype\":\"float32\"},{\"name\":\"unknown_95\",\"shape\":[1,1,48,96],\"dtype\":\"float32\"},{\"name\":\"unknown_96\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_61\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_63\",\"shape\":[1,1,24,48],\"dtype\":\"float32\"},{\"name\":\"unknown_64\",\"shape\":[48],\"dtype\":\"float32\"},{\"name\":\"unknown_57\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_59\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_60\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_53\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_55\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_56\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_49\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_51\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_52\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_29\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_31\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_32\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown\",\"shape\":[5,5,3,24],\"dtype\":\"float32\"},{\"name\":\"unknown_0\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_1\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_3\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_4\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_5\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_7\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_8\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_9\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_11\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_12\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_13\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_15\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_16\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_17\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_19\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_20\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_21\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_23\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_24\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_25\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_27\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_28\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_33\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_35\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_36\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_37\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_39\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_40\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_41\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_43\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_44\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"unknown_45\",\"shape\":[3,3,24,1],\"dtype\":\"float32\"},{\"name\":\"unknown_47\",\"shape\":[1,1,24,24],\"dtype\":\"float32\"},{\"name\":\"unknown_48\",\"shape\":[24],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad/Pad/paddings\",\"shape\":[4,2],\"dtype\":\"int32\"},{\"name\":\"unknown_65\",\"shape\":[3,3,48,1],\"dtype\":\"float32\"},{\"name\":\"unknown_67\",\"shape\":[1,1,48,48],\"dtype\":\"float32\"},{\"name\":\"unknown_68\",\"shape\":[48],\"dtype\":\"float32\"},{\"name\":\"unknown_69\",\"shape\":[3,3,48,1],\"dtype\":\"float32\"},{\"name\":\"unknown_71\",\"shape\":[1,1,48,48],\"dtype\":\"float32\"},{\"name\":\"unknown_72\",\"shape\":[48],\"dtype\":\"float32\"},{\"name\":\"unknown_73\",\"shape\":[3,3,48,1],\"dtype\":\"float32\"},{\"name\":\"unknown_75\",\"shape\":[1,1,48,48],\"dtype\":\"float32\"},{\"name\":\"unknown_76\",\"shape\":[48],\"dtype\":\"float32\"},{\"name\":\"unknown_77\",\"shape\":[3,3,48,1],\"dtype\":\"float32\"},{\"name\":\"unknown_79\",\"shape\":[1,1,48,48],\"dtype\":\"float32\"},{\"name\":\"unknown_80\",\"shape\":[48],\"dtype\":\"float32\"},{\"name\":\"unknown_81\",\"shape\":[3,3,48,1],\"dtype\":\"float32\"},{\"name\":\"unknown_83\",\"shape\":[1,1,48,48],\"dtype\":\"float32\"},{\"name\":\"unknown_84\",\"shape\":[48],\"dtype\":\"float32\"},{\"name\":\"unknown_85\",\"shape\":[3,3,48,1],\"dtype\":\"float32\"},{\"name\":\"unknown_87\",\"shape\":[1,1,48,48],\"dtype\":\"float32\"},{\"name\":\"unknown_88\",\"shape\":[48],\"dtype\":\"float32\"},{\"name\":\"unknown_89\",\"shape\":[3,3,48,1],\"dtype\":\"float32\"},{\"name\":\"unknown_91\",\"shape\":[1,1,48,48],\"dtype\":\"float32\"},{\"name\":\"unknown_92\",\"shape\":[48],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_Pad_1/Pad_1/paddings\",\"shape\":[4,2],\"dtype\":\"int32\"},{\"name\":\"unknown_97\",\"shape\":[3,3,96,1],\"dtype\":\"float32\"},{\"name\":\"unknown_99\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_100\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_101\",\"shape\":[3,3,96,1],\"dtype\":\"float32\"},{\"name\":\"unknown_103\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_104\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_105\",\"shape\":[3,3,96,1],\"dtype\":\"float32\"},{\"name\":\"unknown_107\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_108\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_109\",\"shape\":[3,3,96,1],\"dtype\":\"float32\"},{\"name\":\"unknown_111\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_112\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_113\",\"shape\":[3,3,96,1],\"dtype\":\"float32\"},{\"name\":\"unknown_115\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_116\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_117\",\"shape\":[3,3,96,1],\"dtype\":\"float32\"},{\"name\":\"unknown_119\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_120\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_121\",\"shape\":[3,3,96,1],\"dtype\":\"float32\"},{\"name\":\"unknown_123\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_124\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_125\",\"shape\":[3,3,96,1],\"dtype\":\"float32\"},{\"name\":\"unknown_127\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_128\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"unknown_129\",\"shape\":[1,1,96,96],\"dtype\":\"float32\"},{\"name\":\"unknown_130\",\"shape\":[96],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/functional_1/tf_op_layer_regressors_2/regressors_2/shape\",\"shape\":[3],\"dtype\":\"int32\"}]\n      }\n  ]\n}"
  },
  {
    "path": "extern/human/models/emotion.json",
    "content": "{\n  \"format\": \"graph-model\",\n  \"generatedBy\": \"https://github.com/oarriaga/face_classification\",\n  \"convertedBy\": \"https://github.com/vladmandic\",\n  \"userDefinedMetadata\":\n  {\n    \"signature\":\n    {\n      \"inputs\":\n      {\n        \"input_1:0\":{\"name\":\"input_1:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"64\"},{\"size\":\"64\"},{\"size\":\"1\"}]}}\n      },\n      \"outputs\":\n      {\n        \"Identity:0\":{\"name\":\"Identity:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"7\"}]}}\n      }\n    }\n  },\n  \"modelTopology\":\n  {\n      \"node\":\n      [\n          {\"name\":\"unknown_26\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_32\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"256\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"unknown_9\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"64\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_15\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"unknown_43\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"256\"},{\"size\":\"7\"}]}}}}},\n          {\"name\":\"unknown_44\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"7\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/global_average_pooling2d_1/Mean/reduction_indices\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"input_1\",\"op\":\"Placeholder\",\"attr\":{\"shape\":{\"shape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"64\"},{\"size\":\"64\"},{\"size\":\"1\"}]}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"64\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_4/separable_conv2d_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"256\"},{\"size\":\"256\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"64\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_4/separable_conv2d_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_1/separable_conv2d_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_1/separable_conv2d_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_2/separable_conv2d_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_2/separable_conv2d_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"256\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_3/separable_conv2d_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"256\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_3/separable_conv2d_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/block1_conv1_act/Relu\",\"op\":\"_FusedConv2D\",\"input\":[\"input_1\",\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UmVsdQ==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"epsilon\":{\"f\":0}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/block1_conv2_act/Relu\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/block1_conv1_act/Relu\",\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UmVsdQ==\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"num_args\":{\"i\":\"1\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_1/separable_conv2d/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/block1_conv2_act/Relu\",\"unknown_9\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_1/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/block1_conv2_act/Relu\",\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"data_format\":{\"s\":\"TkhXQw==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/block2_sepconv2_act/Relu\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/separable_conv2d_1/separable_conv2d/depthwise\",\"StatefulPartitionedCall/model_1/separable_conv2d_1/separable_conv2d_weights\",\"StatefulPartitionedCall/model_1/separable_conv2d_1/separable_conv2d_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"padding\":{\"s\":\"VkFMSUQ=\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"explicit_paddings\":{\"list\":{}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UmVsdQ==\"]}},\"epsilon\":{\"f\":0},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_2/separable_conv2d/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/block2_sepconv2_act/Relu\",\"unknown_15\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/block2_sepconv2_bn/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/separable_conv2d_2/separable_conv2d/depthwise\",\"StatefulPartitionedCall/model_1/separable_conv2d_2/separable_conv2d_weights\",\"StatefulPartitionedCall/model_1/separable_conv2d_2/separable_conv2d_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"explicit_paddings\":{\"list\":{}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"epsilon\":{\"f\":0},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_1/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/block2_sepconv2_bn/FusedBatchNormV3\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"ksize\":{\"list\":{\"i\":[\"1\",\"3\",\"3\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_1/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_1/MaxPool\",\"StatefulPartitionedCall/model_1/batch_normalization_1/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/block3_sepconv1_act/Relu\",\"op\":\"Relu\",\"input\":[\"StatefulPartitionedCall/model_1/add_1/add\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_2/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/add_1/add\",\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"data_format\":{\"s\":\"TkhXQw==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"num_args\":{\"i\":\"1\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_3/separable_conv2d/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/block3_sepconv1_act/Relu\",\"unknown_26\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/block3_sepconv2_act/Relu\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/separable_conv2d_3/separable_conv2d/depthwise\",\"StatefulPartitionedCall/model_1/separable_conv2d_3/separable_conv2d_weights\",\"StatefulPartitionedCall/model_1/separable_conv2d_3/separable_conv2d_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UmVsdQ==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"epsilon\":{\"f\":0}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_4/separable_conv2d/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/block3_sepconv2_act/Relu\",\"unknown_32\"],\"attr\":{\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/block3_sepconv2_bn/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/separable_conv2d_4/separable_conv2d/depthwise\",\"StatefulPartitionedCall/model_1/separable_conv2d_4/separable_conv2d_weights\",\"StatefulPartitionedCall/model_1/separable_conv2d_4/separable_conv2d_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"num_args\":{\"i\":\"1\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"epsilon\":{\"f\":0},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"use_cudnn_on_gpu\":{\"b\":true},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_2/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/block3_sepconv2_bn/FusedBatchNormV3\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"ksize\":{\"list\":{\"i\":[\"1\",\"3\",\"3\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_2/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_2/MaxPool\",\"StatefulPartitionedCall/model_1/batch_normalization_2/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_5/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/add_2/add\",\"unknown_43\",\"unknown_44\"],\"device\":\"/device:CPU:0\",\"attr\":{\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"U0FNRQ==\"},\"num_args\":{\"i\":\"1\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/global_average_pooling2d_1/Mean\",\"op\":\"Mean\",\"input\":[\"StatefulPartitionedCall/model_1/conv2d_5/BiasAdd\",\"StatefulPartitionedCall/model_1/global_average_pooling2d_1/Mean/reduction_indices\"],\"attr\":{\"Tidx\":{\"type\":\"DT_INT32\"},\"T\":{\"type\":\"DT_FLOAT\"},\"keep_dims\":{\"b\":false}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/predictions/Softmax\",\"op\":\"Softmax\",\"input\":[\"StatefulPartitionedCall/model_1/global_average_pooling2d_1/Mean\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"Identity\",\"op\":\"Identity\",\"input\":[\"StatefulPartitionedCall/model_1/predictions/Softmax\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}}\n      ],\n      \"library\": {},\n      \"versions\": {}\n  },\n  \"weightsManifest\":\n  [\n      {\n          \"paths\": [\"emotion.bin\"],\n          \"weights\": [{\"name\":\"unknown_26\",\"shape\":[3,3,128,1],\"dtype\":\"float32\"},{\"name\":\"unknown_32\",\"shape\":[3,3,256,1],\"dtype\":\"float32\"},{\"name\":\"unknown_9\",\"shape\":[3,3,64,1],\"dtype\":\"float32\"},{\"name\":\"unknown_15\",\"shape\":[3,3,128,1],\"dtype\":\"float32\"},{\"name\":\"unknown_43\",\"shape\":[3,3,256,7],\"dtype\":\"float32\"},{\"name\":\"unknown_44\",\"shape\":[7],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/global_average_pooling2d_1/Mean/reduction_indices\",\"shape\":[2],\"dtype\":\"int32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_weights\",\"shape\":[3,3,1,32],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_weights\",\"shape\":[3,3,32,64],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_4/separable_conv2d_weights\",\"shape\":[1,1,256,256],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_bn_offset\",\"shape\":[64],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_weights\",\"shape\":[1,1,64,128],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_4/separable_conv2d_bn_offset\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_1/separable_conv2d_weights\",\"shape\":[1,1,64,128],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_1/separable_conv2d_bn_offset\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_2/separable_conv2d_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_2/separable_conv2d_bn_offset\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_weights\",\"shape\":[1,1,128,256],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_bn_offset\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_3/separable_conv2d_weights\",\"shape\":[1,1,128,256],\"dtype\":\"float32\"},{\"name\":\"StatefulPartitionedCall/model_1/separable_conv2d_3/separable_conv2d_bn_offset\",\"shape\":[256],\"dtype\":\"float32\"}]\n      }\n  ]\n}"
  },
  {
    "path": "extern/human/models/facemesh.json",
    "content": "{\n  \"format\": \"graph-model\",\n  \"generatedBy\": \"https://github.com/google/mediapipe\",\n  \"convertedBy\": \"https://github.com/vladmandic\",\n  \"signature\":\n  {\n      \"inputs\":\n      {\n          \"input_1\": {\"name\":\"input_1:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"192\"},{\"size\":\"192\"},{\"size\":\"3\"}]}}\n      },\n      \"outputs\":\n      {\n          \"output_mesh\": {\"name\":\"Identity_2:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"1404\"}]}},\n          \"output_faceflag\": {\"name\":\"Identity_1:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"1\"}]}},\n          \"output_contours\": {\"name\":\"Identity:0\",\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"266\"}]}}\n      }\n  },\n  \"modelTopology\":\n  {\n      \"node\":\n      [\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_25/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_24/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_23/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_22/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_21/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_19/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_20/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_21/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_22/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_27/Conv2D/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"266\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_27/BiasAdd/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"266\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/output_contours/Const\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_28/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_27/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_26/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_23/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_24/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_31/Conv2D/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_31/BiasAdd/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/output_faceflag/Const\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_20/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_19/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_18/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_17/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_16/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_15/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_14/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_13/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_12/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_11/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_10/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/channel_padding_3/Pad/paddings\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"4\"},{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_9/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_8/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_7/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/channel_padding_2/Pad/paddings\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"4\"},{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_6/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_5/Neg\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_4/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/channel_padding_1/Pad/paddings\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"4\"},{\"size\":\"2\"}]}}},\"dtype\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_3/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"16\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_2/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"16\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_1/Neg\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"16\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_1/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"16\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_2/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"16\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_3/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"16\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_4/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_5/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_6/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_7/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"64\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_8/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"64\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_9/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"64\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_10/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_11/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_12/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_13/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_14/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_15/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_16/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_17/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_18/depthwise/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_21/Conv2D/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1404\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_21/BiasAdd/ReadVariableOp\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1404\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/output_mesh/Const\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_INT32\"},\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"2\"}]}}}}},\n          {\"name\":\"input_1\",\"op\":\"Placeholder\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"shape\":{\"shape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"192\"},{\"size\":\"192\"},{\"size\":\"3\"}]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"16\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"16\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"16\"},{\"size\":\"16\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"16\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"16\"},{\"size\":\"16\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"16\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"16\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_26/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_5/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_5/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_6/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_26/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_6/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_7/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"},{\"size\":\"64\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_7/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"64\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_8/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"},{\"size\":\"64\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_8/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"64\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_9/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"},{\"size\":\"64\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_9/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"64\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_10/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_10/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_11/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_11/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_12/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_12/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_13/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_13/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_14/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_14/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_15/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_15/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_22/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_22/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_28/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_28/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_16/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_20/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_16/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_29/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_29/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_23/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_20/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_23/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_17/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_17/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_30/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"},{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_30/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_24/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_24/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_18/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_18/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_25/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_25/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_19/Conv2D_weights\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_19/Conv2D_bn_offset\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_1/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"input_1\",\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_bn_offset\",\"StatefulPartitionedCall/model_1/p_re_lu_1/Neg\"],\"device\":\"/device:CPU:0\",\"attr\":{\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UHJlbHU=\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"epsilon\":{\"f\":0},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"2\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_1/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/batch_normalization_1/FusedBatchNormV3\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_1/depthwise/ReadVariableOp\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_2/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_1/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"num_args\":{\"i\":\"1\"},\"T\":{\"type\":\"DT_FLOAT\"},\"use_cudnn_on_gpu\":{\"b\":true},\"epsilon\":{\"f\":0},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"VkFMSUQ=\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_1/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/batch_normalization_1/FusedBatchNormV3\",\"StatefulPartitionedCall/model_1/batch_normalization_2/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_2/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_1/add\",\"StatefulPartitionedCall/model_1/p_re_lu_2/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_2/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_2/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_2/depthwise/ReadVariableOp\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_3/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_2/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"epsilon\":{\"f\":0},\"num_args\":{\"i\":\"1\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_2/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_2/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_3/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_3/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_2/add\",\"StatefulPartitionedCall/model_1/p_re_lu_3/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_1/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_3/Relu\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_3/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_3/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_3/depthwise/ReadVariableOp\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/channel_padding_1/Pad\",\"op\":\"Pad\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_1/MaxPool\",\"StatefulPartitionedCall/model_1/channel_padding_1/Pad/paddings\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"Tpaddings\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_4/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_3/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"num_args\":{\"i\":\"1\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"use_cudnn_on_gpu\":{\"b\":true},\"epsilon\":{\"f\":0},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_3/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/channel_padding_1/Pad\",\"StatefulPartitionedCall/model_1/batch_normalization_4/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_4/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_3/add\",\"StatefulPartitionedCall/model_1/p_re_lu_4/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_4/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_4/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_4/depthwise/ReadVariableOp\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_5/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_4/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_5/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_5/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"num_args\":{\"i\":\"1\"},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"use_cudnn_on_gpu\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_4/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_4/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_5/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_5/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_4/add\",\"StatefulPartitionedCall/model_1/p_re_lu_5/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_5/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_5/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_5/depthwise/ReadVariableOp\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_6/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_5/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_6/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_6/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"use_cudnn_on_gpu\":{\"b\":true},\"padding\":{\"s\":\"VkFMSUQ=\"},\"num_args\":{\"i\":\"1\"},\"epsilon\":{\"f\":0},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_5/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_5/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_6/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_6/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_5/add\",\"StatefulPartitionedCall/model_1/p_re_lu_6/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_2/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_6/Relu\"],\"attr\":{\"padding\":{\"s\":\"VkFMSUQ=\"},\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_6/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_6/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_6/depthwise/ReadVariableOp\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/channel_padding_2/Pad\",\"op\":\"Pad\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_2/MaxPool\",\"StatefulPartitionedCall/model_1/channel_padding_2/Pad/paddings\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"Tpaddings\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_7/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_6/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_7/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_7/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"epsilon\":{\"f\":0},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_6/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/channel_padding_2/Pad\",\"StatefulPartitionedCall/model_1/batch_normalization_7/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_7/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_6/add\",\"StatefulPartitionedCall/model_1/p_re_lu_7/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_7/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_7/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_7/depthwise/ReadVariableOp\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_8/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_7/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_8/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_8/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"padding\":{\"s\":\"VkFMSUQ=\"},\"num_args\":{\"i\":\"1\"},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"epsilon\":{\"f\":0},\"explicit_paddings\":{\"list\":{}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_7/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_7/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_8/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_8/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_7/add\",\"StatefulPartitionedCall/model_1/p_re_lu_8/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_8/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_8/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_8/depthwise/ReadVariableOp\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_9/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_8/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_9/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_9/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"epsilon\":{\"f\":0},\"explicit_paddings\":{\"list\":{}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"num_args\":{\"i\":\"1\"},\"use_cudnn_on_gpu\":{\"b\":true},\"padding\":{\"s\":\"VkFMSUQ=\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_8/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_8/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_9/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_9/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_8/add\",\"StatefulPartitionedCall/model_1/p_re_lu_9/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_3/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_9/Relu\"],\"attr\":{\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_9/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_9/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_9/depthwise/ReadVariableOp\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/channel_padding_3/Pad\",\"op\":\"Pad\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_3/MaxPool\",\"StatefulPartitionedCall/model_1/channel_padding_3/Pad/paddings\"],\"attr\":{\"Tpaddings\":{\"type\":\"DT_INT32\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_10/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_9/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_10/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_10/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"1\"},\"use_cudnn_on_gpu\":{\"b\":true},\"padding\":{\"s\":\"VkFMSUQ=\"},\"epsilon\":{\"f\":0}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_9/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/channel_padding_3/Pad\",\"StatefulPartitionedCall/model_1/batch_normalization_10/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_10/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_9/add\",\"StatefulPartitionedCall/model_1/p_re_lu_10/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_10/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_10/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_10/depthwise/ReadVariableOp\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_11/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_10/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_11/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_11/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"use_cudnn_on_gpu\":{\"b\":true},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"num_args\":{\"i\":\"1\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_10/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_10/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_11/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_11/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_10/add\",\"StatefulPartitionedCall/model_1/p_re_lu_11/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_11/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_11/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_11/depthwise/ReadVariableOp\"],\"attr\":{\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_12/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_11/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_12/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_12/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"use_cudnn_on_gpu\":{\"b\":true},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"num_args\":{\"i\":\"1\"},\"T\":{\"type\":\"DT_FLOAT\"},\"epsilon\":{\"f\":0},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_11/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_11/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_12/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_12/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_11/add\",\"StatefulPartitionedCall/model_1/p_re_lu_12/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_4/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_12/Relu\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_12/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_12/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_12/depthwise/ReadVariableOp\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_13/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_12/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_13/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_13/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"num_args\":{\"i\":\"1\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_12/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_4/MaxPool\",\"StatefulPartitionedCall/model_1/batch_normalization_13/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_13/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_12/add\",\"StatefulPartitionedCall/model_1/p_re_lu_13/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_13/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_13/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_13/depthwise/ReadVariableOp\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_14/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_13/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_14/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_14/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"num_args\":{\"i\":\"1\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"epsilon\":{\"f\":0}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_13/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_13/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_14/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_14/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_13/add\",\"StatefulPartitionedCall/model_1/p_re_lu_14/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_14/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_14/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_14/depthwise/ReadVariableOp\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_15/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_14/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_15/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_15/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"use_cudnn_on_gpu\":{\"b\":true},\"padding\":{\"s\":\"VkFMSUQ=\"},\"num_args\":{\"i\":\"1\"},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"epsilon\":{\"f\":0},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_14/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_14/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_15/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_15/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_14/add\",\"StatefulPartitionedCall/model_1/p_re_lu_15/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_6/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_15/Relu\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_19/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_15/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_19/depthwise/ReadVariableOp\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_7/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_15/Relu\"],\"attr\":{\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_23/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_15/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_23/depthwise/ReadVariableOp\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/max_pooling2d_5/MaxPool\",\"op\":\"MaxPool\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_15/Relu\"],\"attr\":{\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"ksize\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_15/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_15/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_15/depthwise/ReadVariableOp\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"U0FNRQ==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_21/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_19/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_22/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_22/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"num_args\":{\"i\":\"1\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"epsilon\":{\"f\":0},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_26/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_23/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_28/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_28/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"num_args\":{\"i\":\"1\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_16/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_15/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_16/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_16/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"padding\":{\"s\":\"VkFMSUQ=\"},\"T\":{\"type\":\"DT_FLOAT\"},\"num_args\":{\"i\":\"1\"},\"use_cudnn_on_gpu\":{\"b\":true},\"epsilon\":{\"f\":0},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_19/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_6/MaxPool\",\"StatefulPartitionedCall/model_1/batch_normalization_21/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_23/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_7/MaxPool\",\"StatefulPartitionedCall/model_1/batch_normalization_26/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_15/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/max_pooling2d_5/MaxPool\",\"StatefulPartitionedCall/model_1/batch_normalization_16/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_21/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_19/add\",\"StatefulPartitionedCall/model_1/p_re_lu_21/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_26/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_23/add\",\"StatefulPartitionedCall/model_1/p_re_lu_26/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_16/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_15/add\",\"StatefulPartitionedCall/model_1/p_re_lu_16/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_20/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_21/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_20/depthwise/ReadVariableOp\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_27/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_26/Relu\",\"StatefulPartitionedCall/model_1/conv2d_29/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_29/Conv2D_bn_offset\",\"StatefulPartitionedCall/model_1/p_re_lu_27/Neg\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"num_args\":{\"i\":\"2\"},\"T\":{\"type\":\"DT_FLOAT\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UHJlbHU=\"]}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_16/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_16/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_16/depthwise/ReadVariableOp\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_22/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_20/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_23/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_23/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"num_args\":{\"i\":\"1\"},\"T\":{\"type\":\"DT_FLOAT\"},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_17/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_16/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_17/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_17/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"epsilon\":{\"f\":0},\"num_args\":{\"i\":\"1\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_20/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_21/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_22/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_16/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_16/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_17/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_22/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_20/add\",\"StatefulPartitionedCall/model_1/p_re_lu_22/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_17/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_16/add\",\"StatefulPartitionedCall/model_1/p_re_lu_17/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_24/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/batch_normalization_27/FusedBatchNormV3\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_24/depthwise/ReadVariableOp\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"U0FNRQ==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_28/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_24/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_30/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_30/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"num_args\":{\"i\":\"1\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"epsilon\":{\"f\":0},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_21/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_22/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_21/depthwise/ReadVariableOp\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_24/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/batch_normalization_27/FusedBatchNormV3\",\"StatefulPartitionedCall/model_1/batch_normalization_28/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_17/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_17/Relu\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_17/depthwise/ReadVariableOp\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_23/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_21/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_24/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_24/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"num_args\":{\"i\":\"1\"},\"use_cudnn_on_gpu\":{\"b\":true},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"epsilon\":{\"f\":0}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_28/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_24/add\",\"StatefulPartitionedCall/model_1/p_re_lu_28/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_18/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_17/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_18/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_18/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"epsilon\":{\"f\":0},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"1\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"VkFMSUQ=\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_21/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_22/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_23/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_17/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_17/Relu\",\"StatefulPartitionedCall/model_1/batch_normalization_18/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_23/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_21/add\",\"StatefulPartitionedCall/model_1/p_re_lu_23/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_18/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_17/add\",\"StatefulPartitionedCall/model_1/p_re_lu_18/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_31/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_28/Relu\",\"StatefulPartitionedCall/model_1/conv2d_31/Conv2D/ReadVariableOp\",\"StatefulPartitionedCall/model_1/conv2d_31/BiasAdd/ReadVariableOp\"],\"device\":\"/device:CPU:0\",\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"3\",\"3\",\"1\"]}},\"padding\":{\"s\":\"VkFMSUQ=\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"num_args\":{\"i\":\"1\"},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"epsilon\":{\"f\":0}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/activation_1/Sigmoid\",\"op\":\"Sigmoid\",\"input\":[\"StatefulPartitionedCall/model_1/conv2d_31/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_24/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_23/Relu\",\"StatefulPartitionedCall/model_1/conv2d_25/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_25/Conv2D_bn_offset\",\"StatefulPartitionedCall/model_1/p_re_lu_24/Neg\"],\"device\":\"/device:CPU:0\",\"attr\":{\"num_args\":{\"i\":\"2\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"padding\":{\"s\":\"VkFMSUQ=\"},\"T\":{\"type\":\"DT_FLOAT\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UHJlbHU=\"]}},\"epsilon\":{\"f\":0},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/output_faceflag/Reshape\",\"op\":\"Reshape\",\"input\":[\"StatefulPartitionedCall/model_1/activation_1/Sigmoid\",\"StatefulPartitionedCall/model_1/output_faceflag/Const\"],\"attr\":{\"Tshape\":{\"type\":\"DT_INT32\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_19/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_18/Relu\",\"StatefulPartitionedCall/model_1/conv2d_19/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_19/Conv2D_bn_offset\",\"StatefulPartitionedCall/model_1/p_re_lu_19/Neg\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"num_args\":{\"i\":\"2\"},\"epsilon\":{\"f\":0},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"VkFMSUQ=\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UHJlbHU=\"]}}}},\n          {\"name\":\"Identity_1\",\"op\":\"Identity\",\"input\":[\"StatefulPartitionedCall/model_1/output_faceflag/Reshape\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_22/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/batch_normalization_24/FusedBatchNormV3\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_22/depthwise/ReadVariableOp\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"U0FNRQ==\"},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_18/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"StatefulPartitionedCall/model_1/batch_normalization_19/FusedBatchNormV3\",\"StatefulPartitionedCall/model_1/depthwise_conv2d_18/depthwise/ReadVariableOp\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_25/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_22/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_26/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_26/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"use_cudnn_on_gpu\":{\"b\":true},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"num_args\":{\"i\":\"1\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/batch_normalization_20/FusedBatchNormV3\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/depthwise_conv2d_18/depthwise\",\"StatefulPartitionedCall/model_1/conv2d_20/Conv2D_weights\",\"StatefulPartitionedCall/model_1/conv2d_20/Conv2D_bn_offset\"],\"device\":\"/device:CPU:0\",\"attr\":{\"padding\":{\"s\":\"VkFMSUQ=\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"num_args\":{\"i\":\"1\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"epsilon\":{\"f\":0},\"T\":{\"type\":\"DT_FLOAT\"},\"use_cudnn_on_gpu\":{\"b\":true},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_22/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/batch_normalization_24/FusedBatchNormV3\",\"StatefulPartitionedCall/model_1/batch_normalization_25/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/add_18/add\",\"op\":\"AddV2\",\"input\":[\"StatefulPartitionedCall/model_1/batch_normalization_19/FusedBatchNormV3\",\"StatefulPartitionedCall/model_1/batch_normalization_20/FusedBatchNormV3\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_25/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_22/add\",\"StatefulPartitionedCall/model_1/p_re_lu_25/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_20/Relu\",\"op\":\"Prelu\",\"input\":[\"StatefulPartitionedCall/model_1/add_18/add\",\"StatefulPartitionedCall/model_1/p_re_lu_20/Neg\"]},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_27/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_25/Relu\",\"StatefulPartitionedCall/model_1/conv2d_27/Conv2D/ReadVariableOp\",\"StatefulPartitionedCall/model_1/conv2d_27/BiasAdd/ReadVariableOp\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"epsilon\":{\"f\":0},\"padding\":{\"s\":\"VkFMSUQ=\"},\"num_args\":{\"i\":\"1\"},\"use_cudnn_on_gpu\":{\"b\":true},\"strides\":{\"list\":{\"i\":[\"1\",\"3\",\"3\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/conv2d_21/BiasAdd\",\"op\":\"_FusedConv2D\",\"input\":[\"StatefulPartitionedCall/model_1/p_re_lu_20/Relu\",\"StatefulPartitionedCall/model_1/conv2d_21/Conv2D/ReadVariableOp\",\"StatefulPartitionedCall/model_1/conv2d_21/BiasAdd/ReadVariableOp\"],\"device\":\"/device:CPU:0\",\"attr\":{\"padding\":{\"s\":\"VkFMSUQ=\"},\"strides\":{\"list\":{\"i\":[\"1\",\"3\",\"3\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"epsilon\":{\"f\":0},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"num_args\":{\"i\":\"1\"},\"use_cudnn_on_gpu\":{\"b\":true}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/output_contours/Reshape\",\"op\":\"Reshape\",\"input\":[\"StatefulPartitionedCall/model_1/conv2d_27/BiasAdd\",\"StatefulPartitionedCall/model_1/output_contours/Const\"],\"attr\":{\"Tshape\":{\"type\":\"DT_INT32\"},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"StatefulPartitionedCall/model_1/output_mesh/Reshape\",\"op\":\"Reshape\",\"input\":[\"StatefulPartitionedCall/model_1/conv2d_21/BiasAdd\",\"StatefulPartitionedCall/model_1/output_mesh/Const\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"Tshape\":{\"type\":\"DT_INT32\"}}},\n          {\"name\":\"Identity\",\"op\":\"Identity\",\"input\":[\"StatefulPartitionedCall/model_1/output_contours/Reshape\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"Identity_2\",\"op\":\"Identity\",\"input\":[\"StatefulPartitionedCall/model_1/output_mesh/Reshape\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}}\n      ],\n      \"library\": {},\n      \"versions\": {}\n  },\n  \"weightsManifest\":\n  [\n      {\n          \"paths\": [\"facemesh.bin\"],\n          \"weights\": [{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_25/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_24/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_23/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_22/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_21/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_19/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_20/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_21/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_22/depthwise/ReadVariableOp\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_27/Conv2D/ReadVariableOp\",\"shape\":[3,3,32,266],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_27/BiasAdd/ReadVariableOp\",\"shape\":[266],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/output_contours/Const\",\"shape\":[2],\"dtype\":\"int32\"},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_28/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_27/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_26/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_23/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_24/depthwise/ReadVariableOp\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_31/Conv2D/ReadVariableOp\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_31/BiasAdd/ReadVariableOp\",\"shape\":[1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/output_faceflag/Const\",\"shape\":[2],\"dtype\":\"int32\"},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_20/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_19/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_18/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_17/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_16/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_15/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_14/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_13/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_12/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_11/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_10/Neg\",\"shape\":[1,1,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/channel_padding_3/Pad/paddings\",\"shape\":[4,2],\"dtype\":\"int32\"},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_9/Neg\",\"shape\":[1,1,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_8/Neg\",\"shape\":[1,1,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_7/Neg\",\"shape\":[1,1,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/channel_padding_2/Pad/paddings\",\"shape\":[4,2],\"dtype\":\"int32\"},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_6/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_5/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_4/Neg\",\"shape\":[1,1,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/channel_padding_1/Pad/paddings\",\"shape\":[4,2],\"dtype\":\"int32\"},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_3/Neg\",\"shape\":[1,1,16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_2/Neg\",\"shape\":[1,1,16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/p_re_lu_1/Neg\",\"shape\":[1,1,16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_1/depthwise/ReadVariableOp\",\"shape\":[3,3,16,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_2/depthwise/ReadVariableOp\",\"shape\":[3,3,16,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_3/depthwise/ReadVariableOp\",\"shape\":[3,3,16,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_4/depthwise/ReadVariableOp\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_5/depthwise/ReadVariableOp\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_6/depthwise/ReadVariableOp\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_7/depthwise/ReadVariableOp\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_8/depthwise/ReadVariableOp\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_9/depthwise/ReadVariableOp\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_10/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_11/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_12/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_13/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_14/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_15/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_16/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_17/depthwise/ReadVariableOp\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/depthwise_conv2d_18/depthwise/ReadVariableOp\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_21/Conv2D/ReadVariableOp\",\"shape\":[3,3,32,1404],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_21/BiasAdd/ReadVariableOp\",\"shape\":[1404],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/output_mesh/Const\",\"shape\":[2],\"dtype\":\"int32\"},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_weights\",\"shape\":[3,3,3,16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_1/Conv2D_bn_offset\",\"shape\":[16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_weights\",\"shape\":[1,1,16,16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_2/Conv2D_bn_offset\",\"shape\":[16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_weights\",\"shape\":[1,1,16,16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_3/Conv2D_bn_offset\",\"shape\":[16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_weights\",\"shape\":[1,1,16,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_26/Conv2D_weights\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_4/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_5/Conv2D_weights\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_5/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_6/Conv2D_weights\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_26/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_6/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_7/Conv2D_weights\",\"shape\":[1,1,32,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_7/Conv2D_bn_offset\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_8/Conv2D_weights\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_8/Conv2D_bn_offset\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_9/Conv2D_weights\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_9/Conv2D_bn_offset\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_10/Conv2D_weights\",\"shape\":[1,1,64,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_10/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_11/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_11/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_12/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_12/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_13/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_13/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_14/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_14/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_15/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_15/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_22/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_22/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_28/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_28/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_16/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_20/Conv2D_weights\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_16/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_29/Conv2D_weights\",\"shape\":[1,1,128,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_29/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_23/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_20/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_23/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_17/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_17/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_30/Conv2D_weights\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_30/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_24/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_24/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_18/Conv2D_weights\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_18/Conv2D_bn_offset\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_25/Conv2D_weights\",\"shape\":[1,1,128,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_25/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_19/Conv2D_weights\",\"shape\":[1,1,128,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"StatefulPartitionedCall/model_1/conv2d_19/Conv2D_bn_offset\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}}]\n      }\n  ]\n}"
  },
  {
    "path": "extern/human/models/faceres.json",
    "content": "{\n  \"format\": \"graph-model\",\n  \"generatedBy\": \"https://github.com/HSE-asavchenko/HSE_FaceRec_tf\",\n  \"convertedBy\": \"https://github.com/vladmandic\",\n  \"signature\":\n  {\n    \"inputs\":\n    {\n      \"input_1\": { \"name\": \"input_1\", \"dtype\": \"DT_FLOAT\", \"tensorShape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"224\"},{\"size\":\"224\"},{\"size\":\"3\"}]} }\n    },\n    \"outputs\":\n    {\n      \"gender_pred/Sigmoid:0\": {\"name\":\"gender_pred/Sigmoid:0\", \"dtype\":\"DT_FLOAT\", \"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"}]} },\n      \"global_pooling/Mean\": {\"name\":\"global_pooling/Mean\", \"dtype\":\"DT_FLOAT\", \"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1024\"}]} },\n      \"age_pred/Softmax:0\": {\"name\":\"age_pred/Softmax:0\", \"dtype\":\"DT_FLOAT\", \"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"100\"}]} }\n    }\n  },\n  \"modelTopology\":\n  {\n      \"node\":\n      [\n          {\"name\":\"age_pred/kernel\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"},{\"size\":\"100\"}]}}}}},\n          {\"name\":\"age_pred/bias\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"100\"}]}}}}},\n          {\"name\":\"feats/kernel\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1024\"},{\"size\":\"256\"}]}}}}},\n          {\"name\":\"feats/bias\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}}}},\n          {\"name\":\"gender_pred/kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"gender_pred/bias\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"}]}}}}},\n          {\"name\":\"conv1/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"}]}}}}},\n          {\"name\":\"conv1_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv1_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv1_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_1/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"32\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_1_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}}}},\n          {\"name\":\"conv_dw_1_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"32\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_1_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_1_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_1/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"32\"},{\"size\":\"64\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_1_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"64\"}]}}}}},\n          {\"name\":\"conv_pw_1_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_1_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_2/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"64\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_2_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"64\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_2_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"64\"}]}}}}},\n          {\"name\":\"conv_dw_2_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_2_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_2/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"64\"},{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_2_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_2_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_2_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_3/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_3_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"conv_dw_3_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_3_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_3_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_3/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"128\"}]}}}}},\n          {\"name\":\"conv_pw_3_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_3_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_3_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_4/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"128\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_4_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"conv_dw_4_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"128\"}]}}}}},\n          {\"name\":\"conv_dw_4_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_4_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_4/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"128\"},{\"size\":\"256\"}]}}}}},\n          {\"name\":\"conv_pw_4_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}}}},\n          {\"name\":\"conv_pw_4_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_4_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"256\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_5_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_5/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"256\"},{\"size\":\"256\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_5_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_5_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_5_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"256\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}}}},\n          {\"name\":\"conv_dw_6_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"256\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_6/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"256\"},{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_pw_6_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_6_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_6_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_7/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"512\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_7/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"512\"},{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_7_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_7_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_7_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_8/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"512\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"conv_dw_8_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_dw_8_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_8_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_8_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_8/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"512\"},{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_8_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_8_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_8_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_9/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"512\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_9_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_dw_9_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_dw_9_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_9_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_9/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"512\"},{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_pw_9_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_9_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_9_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"512\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_dw_10_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_10/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"512\"},{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_pw_10_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_pw_10_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_10_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"512\"},{\"size\":\"1\"}]}}}}},\n          {\"name\":\"conv_dw_11_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_11/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"512\"},{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_11_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_11_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_pw_11_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_12/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"512\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_12_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}}}},\n          {\"name\":\"conv_dw_12_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"512\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_12_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_12_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_12/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"512\"},{\"size\":\"1024\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_12_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1024\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_12_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_12_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_13/depthwise_kernel\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"3\"},{\"size\":\"3\"},{\"size\":\"1024\"},{\"size\":\"1\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_13_bn/batchnorm_1/mul\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1024\"}]}}}}},\n          {\"name\":\"conv_dw_13_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1024\"}]}}}}},\n          {\"name\":\"conv_dw_13_relu/Cast\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"conv_dw_13_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_13/convolution/merged_input\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1\"},{\"size\":\"1\"},{\"size\":\"1024\"},{\"size\":\"1024\"}]}}}}},\n          {\"name\":\"conv_pw_13_bn/batchnorm_1/sub\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{\"dim\":[{\"size\":\"1024\"}]}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_13_relu/Cast\",\"op\":\"Const\",\"attr\":{\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_13_relu/Const_1\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_FLOAT\"},\"value\":{\"tensor\":{\"dtype\":\"DT_FLOAT\",\"tensorShape\":{}}}}},\n          {\"name\":\"global_pooling/Mean/reduction_indices\",\"op\":\"Const\",\"attr\":{\"dtype\":{\"type\":\"DT_INT32\"},\"value\":{\"tensor\":{\"dtype\":\"DT_INT32\",\"tensorShape\":{\"dim\":[{\"size\":\"2\"}]}}}}},\n          {\"name\":\"input_1\",\"op\":\"Placeholder\",\"attr\":{\"shape\":{\"shape\":{\"dim\":[{\"size\":\"-1\"},{\"size\":\"224\"},{\"size\":\"224\"},{\"size\":\"3\"}]}},\"dtype\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv1_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"input_1\",\"conv1/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv1_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv1_bn/batchnorm_1/mul_1\",\"conv1_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv1_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv1_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv1_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv1_relu/Relu\",\"conv1_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv1_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv1_relu/clip_by_value/Minimum\",\"conv1_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_1/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv1_relu/clip_by_value\",\"conv_dw_1/depthwise_kernel\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"conv_dw_1_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_1/depthwise\",\"conv_dw_1_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_1_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_1_bn/batchnorm_1/mul_1\",\"conv_dw_1_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_1_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_1_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_1_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_1_relu/Relu\",\"conv_dw_1_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_1_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_1_relu/clip_by_value/Minimum\",\"conv_dw_1_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_1_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_1_relu/clip_by_value\",\"conv_pw_1/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"conv_pw_1_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_1_bn/batchnorm_1/mul_1\",\"conv_pw_1_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_1_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_1_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_1_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_1_relu/Relu\",\"conv_pw_1_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_1_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_1_relu/clip_by_value/Minimum\",\"conv_pw_1_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_2/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_1_relu/clip_by_value\",\"conv_dw_2/depthwise_kernel\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv_dw_2_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_2/depthwise\",\"conv_dw_2_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_2_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_2_bn/batchnorm_1/mul_1\",\"conv_dw_2_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_2_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_2_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_2_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_2_relu/Relu\",\"conv_dw_2_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_2_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_2_relu/clip_by_value/Minimum\",\"conv_dw_2_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_2_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_2_relu/clip_by_value\",\"conv_pw_2/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv_pw_2_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_2_bn/batchnorm_1/mul_1\",\"conv_pw_2_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_2_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_2_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_2_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_2_relu/Relu\",\"conv_pw_2_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_2_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_2_relu/clip_by_value/Minimum\",\"conv_pw_2_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_3/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_2_relu/clip_by_value\",\"conv_dw_3/depthwise_kernel\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"conv_dw_3_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_3/depthwise\",\"conv_dw_3_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_3_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_3_bn/batchnorm_1/mul_1\",\"conv_dw_3_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_3_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_3_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_3_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_3_relu/Relu\",\"conv_dw_3_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_3_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_3_relu/clip_by_value/Minimum\",\"conv_dw_3_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_3_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_3_relu/clip_by_value\",\"conv_pw_3/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"conv_pw_3_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_3_bn/batchnorm_1/mul_1\",\"conv_pw_3_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_3_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_3_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_3_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_3_relu/Relu\",\"conv_pw_3_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_3_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_3_relu/clip_by_value/Minimum\",\"conv_pw_3_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_4/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_3_relu/clip_by_value\",\"conv_dw_4/depthwise_kernel\"],\"attr\":{\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"conv_dw_4_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_4/depthwise\",\"conv_dw_4_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_4_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_4_bn/batchnorm_1/mul_1\",\"conv_dw_4_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_4_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_4_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_4_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_4_relu/Relu\",\"conv_dw_4_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_4_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_4_relu/clip_by_value/Minimum\",\"conv_dw_4_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_4_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_4_relu/clip_by_value\",\"conv_pw_4/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_4_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_4_bn/batchnorm_1/mul_1\",\"conv_pw_4_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_4_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_4_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_4_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_4_relu/Relu\",\"conv_pw_4_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_4_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_4_relu/clip_by_value/Minimum\",\"conv_pw_4_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_4_relu/clip_by_value\",\"conv_dw_5/depthwise_kernel\"],\"attr\":{\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"conv_dw_5_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_5/depthwise\",\"conv_dw_5_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_5_bn/batchnorm_1/mul_1\",\"conv_dw_5_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_5_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_5_relu/Relu\",\"conv_dw_5_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_5_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_5_relu/clip_by_value/Minimum\",\"conv_dw_5_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_5_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_5_relu/clip_by_value\",\"conv_pw_5/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"conv_pw_5_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_5_bn/batchnorm_1/mul_1\",\"conv_pw_5_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_5_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_5_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_5_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_5_relu/Relu\",\"conv_pw_5_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_5_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_5_relu/clip_by_value/Minimum\",\"conv_pw_5_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_5_relu/clip_by_value\",\"conv_dw_6/depthwise_kernel\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}}}},\n          {\"name\":\"conv_dw_6_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_6/depthwise\",\"conv_dw_6_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_6_bn/batchnorm_1/mul_1\",\"conv_dw_6_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_6_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_6_relu/Relu\",\"conv_dw_6_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_6_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_6_relu/clip_by_value/Minimum\",\"conv_dw_6_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_6_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_6_relu/clip_by_value\",\"conv_pw_6/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"use_cudnn_on_gpu\":{\"b\":true},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv_pw_6_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_6_bn/batchnorm_1/mul_1\",\"conv_pw_6_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_6_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_6_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_6_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_6_relu/Relu\",\"conv_pw_6_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_6_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_6_relu/clip_by_value/Minimum\",\"conv_pw_6_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_6_relu/clip_by_value\",\"conv_dw_7/depthwise_kernel\"],\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"conv_dw_7_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_7/depthwise\",\"conv_dw_7_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_7_bn/batchnorm_1/mul_1\",\"conv_dw_7_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_7_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_7_relu/Relu\",\"conv_dw_7_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_7_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_7_relu/clip_by_value/Minimum\",\"conv_dw_7_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_7_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_7_relu/clip_by_value\",\"conv_pw_7/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv_pw_7_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_7_bn/batchnorm_1/mul_1\",\"conv_pw_7_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_7_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_7_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_7_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_7_relu/Relu\",\"conv_pw_7_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_7_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_7_relu/clip_by_value/Minimum\",\"conv_pw_7_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_8/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_7_relu/clip_by_value\",\"conv_dw_8/depthwise_kernel\"],\"attr\":{\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"}}},\n          {\"name\":\"conv_dw_8_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_8/depthwise\",\"conv_dw_8_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_8_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_8_bn/batchnorm_1/mul_1\",\"conv_dw_8_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_8_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_8_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_8_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_8_relu/Relu\",\"conv_dw_8_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_8_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_8_relu/clip_by_value/Minimum\",\"conv_dw_8_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_8_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_8_relu/clip_by_value\",\"conv_pw_8/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"padding\":{\"s\":\"U0FNRQ==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv_pw_8_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_8_bn/batchnorm_1/mul_1\",\"conv_pw_8_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_8_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_8_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_8_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_8_relu/Relu\",\"conv_pw_8_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_8_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_8_relu/clip_by_value/Minimum\",\"conv_pw_8_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_9/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_8_relu/clip_by_value\",\"conv_dw_9/depthwise_kernel\"],\"attr\":{\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"conv_dw_9_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_9/depthwise\",\"conv_dw_9_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_9_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_9_bn/batchnorm_1/mul_1\",\"conv_dw_9_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_9_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_9_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_9_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_9_relu/Relu\",\"conv_dw_9_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_9_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_9_relu/clip_by_value/Minimum\",\"conv_dw_9_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_9_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_9_relu/clip_by_value\",\"conv_pw_9/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"use_cudnn_on_gpu\":{\"b\":true},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv_pw_9_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_9_bn/batchnorm_1/mul_1\",\"conv_pw_9_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_9_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_9_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_9_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_9_relu/Relu\",\"conv_pw_9_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_9_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_9_relu/clip_by_value/Minimum\",\"conv_pw_9_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_9_relu/clip_by_value\",\"conv_dw_10/depthwise_kernel\"],\"attr\":{\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv_dw_10_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_10/depthwise\",\"conv_dw_10_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_10_bn/batchnorm_1/mul_1\",\"conv_dw_10_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_10_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_10_relu/Relu\",\"conv_dw_10_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_10_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_10_relu/clip_by_value/Minimum\",\"conv_dw_10_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_10_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_10_relu/clip_by_value\",\"conv_pw_10/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"use_cudnn_on_gpu\":{\"b\":true},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}}}},\n          {\"name\":\"conv_pw_10_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_10_bn/batchnorm_1/mul_1\",\"conv_pw_10_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_10_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_10_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_10_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_10_relu/Relu\",\"conv_pw_10_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_10_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_10_relu/clip_by_value/Minimum\",\"conv_pw_10_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_10_relu/clip_by_value\",\"conv_dw_11/depthwise_kernel\"],\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"conv_dw_11_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_11/depthwise\",\"conv_dw_11_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_11_bn/batchnorm_1/mul_1\",\"conv_dw_11_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_11_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_11_relu/Relu\",\"conv_dw_11_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_11_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_11_relu/clip_by_value/Minimum\",\"conv_dw_11_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_11_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_11_relu/clip_by_value\",\"conv_pw_11/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"data_format\":{\"s\":\"TkhXQw==\"},\"use_cudnn_on_gpu\":{\"b\":true}}},\n          {\"name\":\"conv_pw_11_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_11_bn/batchnorm_1/mul_1\",\"conv_pw_11_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_11_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_11_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_11_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_11_relu/Relu\",\"conv_pw_11_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_11_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_11_relu/clip_by_value/Minimum\",\"conv_pw_11_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_12/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_11_relu/clip_by_value\",\"conv_dw_12/depthwise_kernel\"],\"attr\":{\"explicit_paddings\":{\"list\":{}},\"T\":{\"type\":\"DT_FLOAT\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"strides\":{\"list\":{\"i\":[\"1\",\"2\",\"2\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"conv_dw_12_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_12/depthwise\",\"conv_dw_12_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_12_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_12_bn/batchnorm_1/mul_1\",\"conv_dw_12_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_12_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_12_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_12_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_12_relu/Relu\",\"conv_dw_12_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_12_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_12_relu/clip_by_value/Minimum\",\"conv_dw_12_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_12_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_12_relu/clip_by_value\",\"conv_pw_12/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"padding\":{\"s\":\"U0FNRQ==\"},\"use_cudnn_on_gpu\":{\"b\":true},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"},\"explicit_paddings\":{\"list\":{}}}},\n          {\"name\":\"conv_pw_12_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_12_bn/batchnorm_1/mul_1\",\"conv_pw_12_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_12_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_12_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_12_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_12_relu/Relu\",\"conv_pw_12_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_12_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_12_relu/clip_by_value/Minimum\",\"conv_pw_12_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_13/depthwise\",\"op\":\"DepthwiseConv2dNative\",\"input\":[\"conv_pw_12_relu/clip_by_value\",\"conv_dw_13/depthwise_kernel\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"explicit_paddings\":{\"list\":{}},\"padding\":{\"s\":\"U0FNRQ==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"data_format\":{\"s\":\"TkhXQw==\"}}},\n          {\"name\":\"conv_dw_13_bn/batchnorm_1/mul_1\",\"op\":\"Mul\",\"input\":[\"conv_dw_13/depthwise\",\"conv_dw_13_bn/batchnorm_1/mul\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_13_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_dw_13_bn/batchnorm_1/mul_1\",\"conv_dw_13_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_13_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_dw_13_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_13_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_dw_13_relu/Relu\",\"conv_dw_13_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_dw_13_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_dw_13_relu/clip_by_value/Minimum\",\"conv_dw_13_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_13_bn/batchnorm_1/mul_1\",\"op\":\"Conv2D\",\"input\":[\"conv_dw_13_relu/clip_by_value\",\"conv_pw_13/convolution/merged_input\"],\"device\":\"/device:CPU:0\",\"attr\":{\"padding\":{\"s\":\"U0FNRQ==\"},\"T\":{\"type\":\"DT_FLOAT\"},\"explicit_paddings\":{\"list\":{}},\"data_format\":{\"s\":\"TkhXQw==\"},\"dilations\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"strides\":{\"list\":{\"i\":[\"1\",\"1\",\"1\",\"1\"]}},\"use_cudnn_on_gpu\":{\"b\":true}}},\n          {\"name\":\"conv_pw_13_bn/batchnorm_1/add_1\",\"op\":\"Add\",\"input\":[\"conv_pw_13_bn/batchnorm_1/mul_1\",\"conv_pw_13_bn/batchnorm_1/sub\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_13_relu/Relu\",\"op\":\"Relu\",\"input\":[\"conv_pw_13_bn/batchnorm_1/add_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_13_relu/clip_by_value/Minimum\",\"op\":\"Minimum\",\"input\":[\"conv_pw_13_relu/Relu\",\"conv_pw_13_relu/Cast\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"conv_pw_13_relu/clip_by_value\",\"op\":\"Maximum\",\"input\":[\"conv_pw_13_relu/clip_by_value/Minimum\",\"conv_pw_13_relu/Const_1\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"global_pooling/Mean\",\"op\":\"Mean\",\"input\":[\"conv_pw_13_relu/clip_by_value\",\"global_pooling/Mean/reduction_indices\"],\"attr\":{\"Tidx\":{\"type\":\"DT_INT32\"},\"T\":{\"type\":\"DT_FLOAT\"},\"keep_dims\":{\"b\":false}}},\n          {\"name\":\"feats/Relu\",\"op\":\"_FusedMatMul\",\"input\":[\"global_pooling/Mean\",\"feats/kernel\",\"feats/bias\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"T\":{\"type\":\"DT_FLOAT\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\",\"UmVsdQ==\"]}},\"num_args\":{\"i\":\"1\"},\"transpose_a\":{\"b\":false},\"transpose_b\":{\"b\":false}}},\n          {\"name\":\"gender_pred/BiasAdd\",\"op\":\"_FusedMatMul\",\"input\":[\"feats/Relu\",\"gender_pred/kernel\",\"gender_pred/bias\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"transpose_b\":{\"b\":false},\"T\":{\"type\":\"DT_FLOAT\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"num_args\":{\"i\":\"1\"},\"transpose_a\":{\"b\":false}}},\n          {\"name\":\"age_pred/BiasAdd\",\"op\":\"_FusedMatMul\",\"input\":[\"feats/Relu\",\"age_pred/kernel\",\"age_pred/bias\"],\"device\":\"/device:CPU:0\",\"attr\":{\"epsilon\":{\"f\":0},\"T\":{\"type\":\"DT_FLOAT\"},\"fused_ops\":{\"list\":{\"s\":[\"Qmlhc0FkZA==\"]}},\"transpose_b\":{\"b\":false},\"num_args\":{\"i\":\"1\"},\"transpose_a\":{\"b\":false}}},\n          {\"name\":\"gender_pred/Sigmoid\",\"op\":\"Sigmoid\",\"input\":[\"gender_pred/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}},\n          {\"name\":\"age_pred/Softmax\",\"op\":\"Softmax\",\"input\":[\"age_pred/BiasAdd\"],\"attr\":{\"T\":{\"type\":\"DT_FLOAT\"}}}\n      ],\n      \"library\": {},\n      \"versions\": {}\n  },\n  \"weightsManifest\":\n  [\n      {\n          \"paths\": [\"faceres.bin\"],\n          \"weights\": [{\"name\":\"age_pred/kernel\",\"shape\":[256,100],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"age_pred/bias\",\"shape\":[100],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"feats/kernel\",\"shape\":[1024,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"feats/bias\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"gender_pred/kernel\",\"shape\":[256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"gender_pred/bias\",\"shape\":[1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv1/convolution/merged_input\",\"shape\":[3,3,3,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv1_bn/batchnorm_1/sub\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv1_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv1_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_1/depthwise_kernel\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_1_bn/batchnorm_1/mul\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_1_bn/batchnorm_1/sub\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_1_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_1_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_1/convolution/merged_input\",\"shape\":[1,1,32,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_1_bn/batchnorm_1/sub\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_1_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_1_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_2/depthwise_kernel\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_2_bn/batchnorm_1/mul\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_2_bn/batchnorm_1/sub\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_2_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_2_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_2/convolution/merged_input\",\"shape\":[1,1,64,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_2_bn/batchnorm_1/sub\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_2_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_2_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_3/depthwise_kernel\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_3_bn/batchnorm_1/mul\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_3_bn/batchnorm_1/sub\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_3_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_3_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_3/convolution/merged_input\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_3_bn/batchnorm_1/sub\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_3_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_3_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_4/depthwise_kernel\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_4_bn/batchnorm_1/mul\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_4_bn/batchnorm_1/sub\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_4_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_4_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_4/convolution/merged_input\",\"shape\":[1,1,128,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_4_bn/batchnorm_1/sub\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_4_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_4_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_5/depthwise_kernel\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_5_bn/batchnorm_1/mul\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_5_bn/batchnorm_1/sub\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_5_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_5_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_5/convolution/merged_input\",\"shape\":[1,1,256,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_5_bn/batchnorm_1/sub\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_5_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_5_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_6/depthwise_kernel\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_6_bn/batchnorm_1/mul\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_6_bn/batchnorm_1/sub\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_6_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_6_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_6/convolution/merged_input\",\"shape\":[1,1,256,512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_6_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_6_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_6_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_7/depthwise_kernel\",\"shape\":[3,3,512,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_7_bn/batchnorm_1/mul\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_7_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_7_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_7_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_7/convolution/merged_input\",\"shape\":[1,1,512,512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_7_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_7_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_7_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_8/depthwise_kernel\",\"shape\":[3,3,512,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_8_bn/batchnorm_1/mul\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_8_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_8_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_8_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_8/convolution/merged_input\",\"shape\":[1,1,512,512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_8_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_8_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_8_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_9/depthwise_kernel\",\"shape\":[3,3,512,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_9_bn/batchnorm_1/mul\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_9_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_9_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_9_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_9/convolution/merged_input\",\"shape\":[1,1,512,512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_9_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_9_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_9_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_10/depthwise_kernel\",\"shape\":[3,3,512,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_10_bn/batchnorm_1/mul\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_10_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_10_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_10_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_10/convolution/merged_input\",\"shape\":[1,1,512,512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_10_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_10_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_10_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_11/depthwise_kernel\",\"shape\":[3,3,512,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_11_bn/batchnorm_1/mul\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_11_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_11_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_11_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_11/convolution/merged_input\",\"shape\":[1,1,512,512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_11_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_11_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_11_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_12/depthwise_kernel\",\"shape\":[3,3,512,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_12_bn/batchnorm_1/mul\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_12_bn/batchnorm_1/sub\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_12_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_12_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_12/convolution/merged_input\",\"shape\":[1,1,512,1024],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_12_bn/batchnorm_1/sub\",\"shape\":[1024],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_12_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_12_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_13/depthwise_kernel\",\"shape\":[3,3,1024,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_13_bn/batchnorm_1/mul\",\"shape\":[1024],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_13_bn/batchnorm_1/sub\",\"shape\":[1024],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_13_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_dw_13_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_13/convolution/merged_input\",\"shape\":[1,1,1024,1024],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_13_bn/batchnorm_1/sub\",\"shape\":[1024],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_13_relu/Cast\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"conv_pw_13_relu/Const_1\",\"shape\":[],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"float16\",\"original_dtype\":\"float32\"}},{\"name\":\"global_pooling/Mean/reduction_indices\",\"shape\":[2],\"dtype\":\"int32\"}]\n      }\n  ]\n}"
  },
  {
    "path": "extern/khaiii/config.json",
    "content": "{\n  \"class_num\": 500,\n  \"conv_kernels\": [\n    2,\n    3,\n    4,\n    5\n  ],\n  \"embed_dim\": 35,\n  \"hidden_dim\": 320,\n  \"vocab_size\": 5625,\n  \"window\": 4\n}"
  },
  {
    "path": "extern/lang/code.js",
    "content": "var Lang = {};\nLang.category = {\n    name: 'ko',\n};\nLang.type = 'ko';\nLang.fallbackType = 'ko';\nLang.ko = '한국어';\nLang.en = 'English';\nLang.jp = '日本語';\nLang.vn = 'tiếng Việt';\nLang.Command = {\n    1: '장면 추가하기',\n    2: '장면 삭제하기',\n    3: '장면 이름 수정',\n    4: '장면 순서 변경',\n    5: '장면 선택',\n    101: '블록 쓰레드 추가하기',\n    102: '블록 쓰레드 삭제하기',\n    103: '블록 삭제하기',\n    104: '블록 복구하기',\n    105: '블록 끼워넣기',\n    106: '블록 분리하기',\n    107: '블록 이동하기',\n    108: '블록 복제하기',\n    109: '블록 복제 취소하기',\n    110: '스크롤',\n    111: '블록 필드값 수정',\n    117: '블록 쓰레드 추가하기',\n    118: '블록 끼워넣기',\n    119: '블록 이동하기',\n    120: '블록 분리하기',\n    121: '블록 이동하기',\n    122: '블록 끼워넣기',\n    123: '블록 끼워넣기',\n    201: '오브젝트 선택하기',\n    202: '오브젝트 수정 버튼 클릭',\n    203: '오브젝트 그림 추가',\n    204: '오브젝트 그림 삭제',\n    205: '오브젝트 소리 추가',\n    206: '오브젝트 소리 삭제',\n    207: '오브젝트 이름 수정',\n    208: '오브젝트 추가',\n    209: '오브젝트 삭제',\n    210: '오브젝트 추가 버튼 클릭',\n    211: '오브젝트 x 수정',\n    212: '오브젝트 y 수정',\n    213: '오브젝트 size 수정',\n    214: '오브젝트 방향 수정',\n    215: '오브젝트 이동 방향 수정',\n    216: '오브젝트 회전방식 수정',\n    217: '엔터티 모델 동기화',\n    301: 'do',\n    302: 'undo',\n    303: 'redo',\n    401: '그림 수정하기',\n    402: '그림 수정 취소하기',\n    403: '그림 수정하기',\n    404: '그림 수정 취소하기',\n    405: '글상자 수정',\n    501: '시작하기',\n    502: '정지하기',\n    601: '컨테이너 오브젝트 선택하기',\n    701: '모드 바꾸기',\n    702: '모양 추가 버튼 클릭',\n    703: '소리 추가 버튼 클릭',\n    801: '속성 필터 선택하기',\n    802: '변수 추가하기 버튼 클릭',\n    803: '변수 추가하기',\n    804: '변수 삭제하기',\n    805: '변수 이름 설정',\n    806: '신호 이름 설정',\n    807: '신호 추가',\n    808: '신호 삭제',\n    809: '변수 스코프 정하기',\n    810: '변수 글로벌 체크',\n    811: '변수 보이기 체크',\n    812: '변수 기본값 설정',\n    813: '변수 슬라이드로 체크',\n    814: '변수 최솟값 정하기',\n    815: '변수 최댓값 정하기',\n    816: '리스트 추가 버튼 클릭',\n    817: '리스트 추가',\n    818: '리스트 삭제',\n    819: '리스트 이름 정하기',\n    820: '리스트 스코프 정하기',\n    821: '리스트 글로벌 체크',\n    822: '리스트 보이기 체크',\n    823: '리스트 길이 변경',\n    824: '리스트 기본값 설정',\n    825: '메세지 수정 enable',\n    826: '변수 수정 enable',\n    827: '리스트 수정 enable',\n    828: '변수 이름 정하기',\n    829: '리스트 이름 정하기',\n    900: '모달 닫기',\n    1001: '함수 생성 시작',\n    1002: '함수 수정 시작',\n    1003: '함수 수정 취소',\n    1004: '함수 생성',\n    1005: '함수 업데이트',\n};\nLang.CommandTooltip = {\n    101: '블록 쓰레드 추가하기',\n    102: '블록 쓰레드 삭제하기',\n    103: '블록 삭제하기',\n    104: '블록 복구하기',\n    105: '코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    106: '블록 분리하기',\n    107: '블록 이동하기',\n    108: '블록 복제하기',\n    109: '블록 복제 취소하기',\n    110: '스크롤',\n    111: '블록 필드값 수정@@값을 입력하기 위해 이곳을 클릭합니다.$$선택지를 클릭합니다.$$선택지를 클릭합니다.$$&value&을 입력합니다.$$&value&를 선택합니다.$$키보드 &value&를 누릅니다.',\n    117: '블록 쓰레드 추가하기',\n    118: '블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    119: '블록 가져오기@@빈 곳에 블록을 끌어다 놓습니다.',\n    120: '블록 분리하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.',\n    121: '블록 이동하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.',\n    122: '블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    123: '코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    201: '오브젝트 선택하기',\n    301: 'do',\n    302: 'undo',\n    303: 'redo',\n    401: '그림 수정하기',\n    402: '그림 수정 취소하기',\n    403: '그림 수정하기',\n    404: '그림 수정 취소하기',\n    501: '실행하기@@<b>[시작하기]</b>를 누릅니다.',\n    502: '정지하기@@<b>[정지하기]</b>를 누릅니다.',\n    601: '컨테이너 오브젝트 선택하기',\n    701: '모드 바꾸기',\n    702: '모양 추가하기@@<b>모양추가</b>를 클릭합니다.',\n    703: '소리 추가하기@@<b>소리추가</b>를 클릭합니다.',\n    801: '변수 속성창 필터 선택하기',\n    802: '변수 추가하기@@<b>[변수 추가]</b>를 클릭합니다.',\n    803: '변수 추가하기@@<b>[확인]</b>을 클릭합니다.',\n    804: '변수 삭제하기@@이 버튼을 눌러 변수를 삭제합니다.',\n    805: '변수 이름 설정',\n    1101: '확장 블록 추가하기@@<b>확장 블록 블러오기</b>를 클릭합니다.',\n};\nLang.Blocks = {\n    download_guide: '• 연결 안내 다운로드',\n    dictionary: '사전',\n    ai_utilize: '인공지능',\n    date_yesterday: '어제',\n    date_today: '오늘',\n    date_tomorrow: '내일',\n    date_after_2_days: '모레',\n    date_after_3_days: '3일 후',\n    date_after_4_days: '4일 후',\n    date_after_5_days: '5일 후',\n    date_after_6_days: '6일 후',\n    location_entire: '전체',\n    location_seoul: '서울',\n    location_seoul_jongno_gu: '종로구',\n    location_seoul_jung_gu: '중구',\n    location_seoul_yongsan_gu: '용산구',\n    location_seoul_seongdong_gu: '성동구',\n    location_seoul_gwangjin_gu: '광진구',\n    location_seoul_dongdaemun_gu: '동대문구',\n    location_seoul_jungnang_gu: '중랑구',\n    location_seoul_seongbuk_gu: '성북구',\n    location_seoul_gangbuk_gu: '강북구',\n    location_seoul_dobong_gu: '도봉구',\n    location_seoul_nowon_gu: '노원구',\n    location_seoul_eunpyeong_gu: '은평구',\n    location_seoul_seodaemun_gu: '서대문구',\n    location_seoul_mapo_gu: '마포구',\n    location_seoul_yangcheon_gu: '양천구',\n    location_seoul_gangseo_gu: '강서구',\n    location_seoul_guro_gu: '구로구',\n    location_seoul_geumcheon_gu: '금천구',\n    location_seoul_yeongdeungpo_gu: '영등포구',\n    location_seoul_dongjak_gu: '동작구',\n    location_seoul_gwanak_gu: '관악구',\n    location_seoul_seocho_gu: '서초구',\n    location_seoul_gangnam_gu: '강남구',\n    location_seoul_songpa_gu: '송파구',\n    location_seoul_gangdong_gu: '강동구',\n    location_busan: '부산',\n    location_busan_jung_gu: '중구',\n    location_busan_seo_gu: '서구',\n    location_busan_dong_gu: '동구',\n    location_busan_yeongdo_gu: '영도구',\n    location_busan_busanjin_gu: '부산진구',\n    location_busan_dongnae_gu: '동래구',\n    location_busan_nam_gu: '남구',\n    location_busan_buk_gu: '북구',\n    location_busan_haeundae_gu: '해운대구',\n    location_busan_saha_gu: '사하구',\n    location_busan_geumjeong_gu: '금정구',\n    location_busan_gangseo_gu: '강서구',\n    location_busan_yeonje: '연제구',\n    location_busan_suyeong_gu: '수영구',\n    location_busan_sasang_gu: '사상구',\n    location_busan_gijang: '기장군',\n    location_daegu: '대구',\n    location_daegu_jung_gu: '중구',\n    location_daegu_dong_gu: '동구',\n    location_daegu_seo_gu: '서구',\n    location_daegu_nam_gu: '남구',\n    location_daegu_buk_gu: '북구',\n    location_daegu_suseong_gu: '수성구',\n    location_daegu_dalseo_gu: '달서구',\n    location_daegu_dalseong: '달성군',\n    location_incheon: '인천',\n    location_incheon_jung_gu: '중구',\n    location_incheon_dong_gu: '동구',\n    location_incheon_nam_gu: '남구',\n    location_incheon_yeonsu_gu: '연수구',\n    location_incheon_namdong_gu: '남동구',\n    location_incheon_bupyeong_gu: '부평구',\n    location_incheon_gyeyang_gu: '계양구',\n    location_incheon_seo_gu: '서구',\n    location_incheon_ganghwa: '강화군',\n    location_incheon_ongjin_gun: '옹진군',\n    location_gwangju: '광주',\n    location_gwangju_dong_gu: '동구',\n    location_gwangju_seo_gu: '서구',\n    location_gwangju_nam_gu: '남구',\n    location_gwangju_buk_gu: '북구',\n    location_gwangju_gwangsan_gu: '광산구',\n    location_daejeon: '대전',\n    location_daejeon_dong_gu: '동구',\n    location_daejeon_jung_gu: '중구',\n    location_daejeon_seo_gu: '서구',\n    location_daejeon_yuseong_gu: '유성구',\n    location_daejeon_daedeok_gu: '대덕구',\n    location_ulsan: '울산',\n    location_ulsan_jung_gu: '중구',\n    location_ulsan_nam_gu: '남구',\n    location_ulsan_dong_gu: '동구',\n    location_ulsan_buk_gu: '북구',\n    location_ulsan_ulju: '울주군',\n    location_sejong: '세종',\n    location_gyeonggi: '경기',\n    location_gyeonggi_suwon_si: '수원시',\n    location_gyeonggi_seongnam: '성남시',\n    location_gyeonggi_uijeongbu: '의정부시',\n    location_gyeonggi_anyang_si: '안양시',\n    location_gyeonggi_bucheon_si: '부천시',\n    location_gyeonggi_gwangmyeong_si: '광명시',\n    location_gyeonggi_pyeongtaek_si: '평택시',\n    location_gyeonggi_dongducheon_si: '동두천시',\n    location_gyeonggi_ansan_si: '안산시',\n    location_gyeonggi_goyang_si: '고양시',\n    location_gyeonggi_gwacheon_si: '과천시',\n    location_gyeonggi_guri: '구리시',\n    location_gyeonggi_namyangju_si: '남양주시',\n    location_gyeonggi_osan: '오산시',\n    location_gyeonggi_siheung: '시흥시',\n    location_gyeonggi_gunpo_si: '군포시',\n    location_gyeonggi_uiwang_si: '의왕시',\n    location_gyeonggi_hanam: '하남시',\n    location_gyeonggi_yongin_si: '용인시',\n    location_gyeonggi_paju: '파주시',\n    location_gyeonggi_icheon: '이천시',\n    location_gyeonggi_anseong_si: '안성시',\n    location_gyeonggi_gimpo: '김포시',\n    location_gyeonggi_hwaseong_si: '화성시',\n    location_gyeonggi_gwangju: '광주시',\n    location_gyeonggi_yangju_si: '양주시',\n    location_gyeonggi_pocheon: '포천시',\n    location_gyeonggi_yeoju: '여주시',\n    location_gyeonggi_yeoncheon_gun: '연천군',\n    location_gyeonggi_gapyeong_gun: '가평군',\n    location_gyeonggi_yangpyeong: '양평군',\n    location_gangwon: '강원',\n    location_gangwon_chuncheon: '춘천시',\n    location_gangwon_wonju: '원주시',\n    location_gangwon_gangneung_si: '강릉시',\n    location_gangwon_donghae: '동해시',\n    location_gangwon_taebaek_si: '태백시',\n    location_gangwon_sokcho: '속초시',\n    location_gangwon_samcheok_si: '삼척시',\n    location_gangwon_hongcheon: '홍천군',\n    location_gangwon_hoengseong_gun: '횡성군',\n    location_gangwon_yeongwol_gun: '영월군',\n    location_gangwon_pyeongchang: '평창군',\n    location_gangwon_jeongseon: '정선군',\n    location_gangwon_cheolwon: '철원군',\n    location_gangwon_hwacheon: '화천군',\n    location_gangwon_yanggu: '양구군',\n    location_gangwon_inje: '인제군',\n    location_gangwon_goseong: '고성군',\n    location_gangwon_yangyang: '양양군',\n    location_chungcheongbuk: '충북',\n    location_chungcheongbuk_cheongju: '청주시',\n    location_chungcheongbuk_chungju: '충주시',\n    location_chungcheongbuk_jecheon: '제천시',\n    location_chungcheongbuk_boeun: '보은군',\n    location_chungcheongbuk_okcheon: '옥천군',\n    location_chungcheongbuk_yeongdong: '영동군',\n    location_chungcheongbuk_jeungpyeong: '증평군',\n    location_chungcheongbuk_jincheon: '진천군',\n    location_chungcheongbuk_goesan: '괴산군',\n    location_chungcheongbuk_eumseong: '음성군',\n    location_chungcheongbuk_danyang: '단양군',\n    location_chungcheongnam: '충남',\n    location_chungcheongnam_cheonan: '천안시',\n    location_chungcheongnam_gongju: '공주시',\n    location_chungcheongnam_boryeong: '보령시',\n    location_chungcheongnam_asan: '아산시',\n    location_chungcheongnam_seosan: '서산시',\n    location_chungcheongnam_nonsan: '논산시',\n    location_chungcheongnam_gyeryong: '계룡시',\n    location_chungcheongnam_dangjin: '당진시',\n    location_chungcheongnam_geumsan: '금산군',\n    location_chungcheongnam_buyeo: '부여군',\n    location_chungcheongnam_seocheon: '서천군',\n    location_chungcheongnam_cheongyang: '청양군',\n    location_chungcheongnam_hongseong: '홍성군',\n    location_chungcheongnam_yesan: '예산군',\n    location_chungcheongnam_taean: '태안군',\n    location_jeollabuk: '전북',\n    location_jeollabuk_jeonju: '전주시',\n    location_jeollabuk_gunsan_si: '군산시',\n    location_jeollabuk_iksan: '익산시',\n    location_jeollabuk_jeongeup: '정읍시',\n    location_jeollabuk_namwon: '남원시',\n    location_jeollabuk_gimje_si: '김제시',\n    location_jeollabuk_wanju: '완주군',\n    location_jeollabuk_jinan: '진안군',\n    location_jeollabuk_muju: '무주군',\n    location_jeollabuk_jangsu: '장수군',\n    location_jeollabuk_imsil: '임실군',\n    location_jeollabuk_sunchang: '순창군',\n    location_jeollabuk_gochang: '고창군',\n    location_jeollabuk_buan: '부안군',\n    location_jeollanam: '전남',\n    location_jeollanam_mokpo: '목포시',\n    location_jeollanam_yosu: '여수시',\n    location_jeollanam_suncheon_si: '순천시',\n    location_jeollanam_naju: '나주시',\n    location_jeollanam_gwangyang_si: '광양시',\n    location_jeollanam_damyang: '담양군',\n    location_jeollanam_gokseong: '곡성군',\n    location_jeollanam_gurye: '구례군',\n    location_jeollanam_goheung: '고흥군',\n    location_jeollanam_boseong: '보성군',\n    location_jeollanam_hwasun: '화순군',\n    location_jeollanam_jangheung: '장흥군',\n    location_jeollanam_gangjin: '강진군',\n    location_jeollanam_haenam: '해남군',\n    location_jeollanam_yeongam: '영암군',\n    location_jeollanam_jindo: '무안군',\n    location_jeollanam_muan: '함평군',\n    location_jeollanam_hampyeong: '영광군',\n    location_jeollanam_yeonggwang: '장성군',\n    location_jeollanam_jangseong: '완도군',\n    location_jeollanam_wando: '진도군',\n    location_jeollanam_sinan: '신안군',\n    location_gyeongsangbuk: '경북',\n    location_gyeongsangbuk_pohang_si: '포항시',\n    location_gyeongsangbuk_gyeongju_si: '경주시',\n    location_gyeongsangbuk_gimcheon_si: '김천시',\n    location_gyeongsangbuk_andong_si: '안동시',\n    location_gyeongsangbuk_gumi_si: '구미시',\n    location_gyeongsangbuk_yeongju_si: '영주시',\n    location_gyeongsangbuk_yeongcheon_si: '영천시',\n    location_gyeongsangbuk_sangju_si: '상주시',\n    location_gyeongsangbuk_mungyeong_si: '문경시',\n    location_gyeongsangbuk_gyeongsan_si: '경산시',\n    location_gyeongsangbuk_gunwi: '군위군',\n    location_gyeongsangbuk_uiseong: '의성군',\n    location_gyeongsangbuk_cheongsong: '청송군',\n    location_gyeongsangbuk_goryong: '영양군',\n    location_gyeongsangbuk_yeongdeok: '영덕군',\n    location_gyeongsangbuk_cheongdo: '청도군',\n    location_gyeongsangbuk_golyeong: '고령군',\n    location_gyeongsangbuk_seongju: '성주군',\n    location_gyeongsangbuk_chilgok: '칠곡군',\n    location_gyeongsangbuk_yecheon: '예천군',\n    location_gyeongsangbuk_bonghwa: '봉화군',\n    location_gyeongsangbuk_uljin: '울진군',\n    location_gyeongsangbuk_ulleung: '울릉군',\n    location_gyeongsangnam: '경남',\n    location_gyeongsangnam_changwon_si: '창원시',\n    location_gyeongsangnam_jinju: '진주시',\n    location_gyeongsangnam_tongyeong_si: '통영시',\n    location_gyeongsangnam_sacheon_si: '사천시',\n    location_gyeongsangnam_gimhae_si: '김해시',\n    location_gyeongsangnam_miryang_si: '밀양시',\n    location_gyeongsangnam_geoje_si: '거제시',\n    location_gyeongsangnam_yangsan_si: '양산시',\n    location_gyeongsangnam_uiryeong: '의령군',\n    location_gyeongsangnam_haman: '함안군',\n    location_gyeongsangnam_changnyeong: '창녕군',\n    location_gyeongsangnam_goseong: '고성군',\n    location_gyeongsangnam_namhae: '남해군',\n    location_gyeongsangnam_hadong: '하동군',\n    location_gyeongsangnam_sancheong: '산청군',\n    location_gyeongsangnam_hamyang: '함양군',\n    location_gyeongsangnam_geochang: '거창군',\n    location_gyeongsangnam_hapcheon: '합천군',\n    location_jeju: '제주',\n    location_jeju_jeju_si: '제주시',\n    location_jeju_seogwipo: '서귀포시',\n    EXPANSION_WEATHER_sunny: '맑음',\n    EXPANSION_WEATHER_partly_cloudy: '구름조금',\n    EXPANSION_WEATHER_mostly_cloudy: '구름많음',\n    EXPANSION_WEATHER_cloudy: '흐림',\n    EXPANSION_WEATHER_rainy: '비',\n    EXPANSION_WEATHER_sleet: '진눈깨비',\n    EXPANSION_WEATHER_snowy: '눈',\n    EXPANSION_WEATHER_finedust_good: '좋음',\n    EXPANSION_WEATHER_finedust_normal: '보통',\n    EXPANSION_WEATHER_finedust_bad: '나쁨',\n    EXPANSION_WEATHER_finedust_very_bad: '매우나쁨',\n    EXPANSION_WEATHER_lowest_temperature: '최저기온(℃)',\n    EXPANSION_WEATHER_highest_temperature: '최고기온(℃)',\n    EXPANSION_WEATHER_humidity: '습도(%)',\n    EXPANSION_WEATHER_precipitation: '강수량(mm)',\n    EXPANSION_WEATHER_precipitation_probability: '강수확률(%)',\n    EXPANSION_WEATHER_wind_speed: '풍속(m/s)',\n    EXPANSION_WEATHER_temperature: '기온(℃)',\n    EXPANSION_WEATHER_finedust: '미세먼지농도(㎍)',\n    EXPANSION_FESTIVAL_title: '제목',\n    EXPANSION_FESTIVAL_area: '지역',\n    EXPANSION_FESTIVAL_start_date: '시작일',\n    EXPANSION_FESTIVAL_end_date: '종료일',\n    EXPANSION_FESTIVAL_address: '주소',\n    EXPANSION_FESTIVAL_coordinate: '위치',\n    EXPANSION_FESTIVAL_overview: '개요',\n    EXPANSION_FESTIVAL_homepage: '홈페이지',\n    no_data: '정보없음',\n    no_sentence: '문장이 없습니다',\n    sentence_over_20_charactor: '20자까지만 입력할 수 있습니다.',\n    sentence_over_3000_charactor: '3000자까지만 입력할 수 있습니다.',\n    sentence_over_2500_charactor: '2500자까지만 입력할 수 있습니다. ',\n    unknown_sentence: '알 수 없는 문장입니다.',\n    auto: '자동',\n    korean: '한국어',\n    english: '영어',\n    spanish: '스페인어',\n    french: '프랑스어',\n    german: '독일어',\n    russian: '러시아어',\n    portuguese: '포르투갈어',\n    hindi: '힌디어',\n    japan: '일본어',\n    thai: '태국어',\n    vietnamese: '베트남',\n    indonesian: '인도네시아어',\n    chinese_simplified: '중국어간체',\n    chinese_traditional: '중국어번체',\n    italian: '이탈리아어',\n    behaviorConduct01001: '태풍',\n    behaviorConduct01002: '홍수',\n    behaviorConduct01003: '호우',\n    behaviorConduct01004: '강풍',\n    behaviorConduct01005: '대설',\n    behaviorConduct01006: '한파',\n    behaviorConduct01007: '풍랑',\n    behaviorConduct01008: '황사',\n    behaviorConduct01009: '폭염',\n    behaviorConduct01010: '가뭄',\n    behaviorConduct01011: '지진',\n    behaviorConduct01013: '해일',\n    behaviorConduct01014: '산사태',\n    behaviorConduct03002: '응급처치',\n    behaviorConduct03003: '심폐소생술',\n    behaviorConduct03004: '소화기사용법',\n    behaviorConduct03016: '소화전사용법',\n    behaviorConduct03005: '식중독',\n    behaviorConduct03006: '산행안전',\n    behaviorConduct03008: '실종유괴',\n    behaviorConduct03009: '성폭력',\n    behaviorConduct03010: '학교 폭력',\n    behaviorConduct03011: '가정 폭력',\n    behaviorConduct03012: '억류 및 납치',\n    behaviorConduct03013: '교통사고',\n    behaviorConduct03014: '승강기 안전사고',\n    behaviorConduct03015: '미세먼지',\n    behaviorConduct01001001: '태풍이 오기 전',\n    behaviorConduct01001002: '태풍이 왔을 때',\n    behaviorConduct01001003: '태풍이 지나간 후',\n    behaviorConduct01002002: '홍수가 오기 전',\n    behaviorConduct01002003: '홍수가 났을 때',\n    behaviorConduct01002004: '홍수가 지나간 후',\n    behaviorConduct01003002: '큰 비가 오기 전',\n    behaviorConduct01003003: '큰 비가 내릴 때',\n    behaviorConduct01003004: '큰 비가 그친 후',\n    behaviorConduct01004001: '강풍이 오기 전',\n    behaviorConduct01004002: '강풍 발생 시',\n    behaviorConduct01005002: '대설이 오기 전',\n    behaviorConduct01005003: '대설 내일 때',\n    behaviorConduct01005004: '눈이 그친 후',\n    behaviorConduct01006001: '한파가 오기 전',\n    behaviorConduct01006002: '한파 왔을 때',\n    behaviorConduct01007001: '풍랑이 험할 때',\n    behaviorConduct01007002: '풍랑이 오기 전',\n    behaviorConduct01008001: '황사가 오기 전',\n    behaviorConduct01008002: '황사가 왔을 때',\n    behaviorConduct01008003: '황사가 지나간 후',\n    behaviorConduct01009001: '폭염이 오기 전',\n    behaviorConduct01009002: '폭염이 왔을 때',\n    behaviorConduct01010001: '가뭄이 왔을 때',\n    behaviorConduct01011009: '지진이 오기 전',\n    behaviorConduct01011010: '지진이 왔을 때',\n    behaviorConduct01011012: '지진 대피 후',\n    behaviorConduct01013002: '해일이 오기 전',\n    behaviorConduct01013003: '해일이 왔을 때',\n    behaviorConduct01014001: '산사태가 오기 전',\n    behaviorConduct03002002: '화상 처치',\n    behaviorConduct03002003: '고열 예방',\n    behaviorConduct03002004: '뱀에 물렸을 때 처치',\n    behaviorConduct03002005: '벌에 쏘였을 때 처치',\n    behaviorConduct03002006: '과호흡증후군 응급처치',\n    behaviorConduct03003001: '성인 심폐소생술',\n    behaviorConduct03003002: '영유아 심폐소생술',\n    behaviorConduct03003003: '자동제세동기 사용',\n    behaviorConduct03004001: '분말소화기 사용',\n    behaviorConduct03016001: '옥내소화전 사용',\n    behaviorConduct03005001: '식중독 대처',\n    behaviorConduct03006004: '산행 중 유의사항',\n    behaviorConduct03006005: '산에서 안전한 캠핑',\n    behaviorConduct03006002: '구조요청시 알리는',\n    behaviorConduct03006003: '산행사고시 응급조치',\n    behaviorConduct03008001: '실종유괴 예방',\n    behaviorConduct03009001: '성폭력 예방',\n    behaviorConduct03010001: '학교 폭력 예방',\n    behaviorConduct03011001: '가정 폭력 예방',\n    behaviorConduct03012001: '억류 및 납치 시 대처',\n    behaviorConduct03013002: '교통사고 발생 시 대처',\n    behaviorConduct03013005: '차량에서의 구조',\n    behaviorConduct03014001: '승강기 안전 이용',\n    behaviorConduct03014003: '승강기 고장시 대처',\n    behaviorConduct03014004: '에스컬레이터 안전 이용',\n    behaviorConduct03015007: '미세먼지 많은 날 생활',\n    behaviorConduct03015003: '부문별 생활',\n    tts_female: '여성',\n    tts_male: '남성',\n    tts_kind: '친절한',\n    tts_sweet: '감미로운',\n    tts_echo: '울리는',\n    tts_mischievous: '장난스러운',\n    tts_dainty: '앙증맞은',\n    tts_veryslow: '매우 느린',\n    tts_slow: '느린',\n    tts_normal: '보통',\n    tts_fast: '빠른',\n    tts_veryfast: '매우 빠른',\n    tts_verylow: '매우 낮은',\n    tts_low: '낮은',\n    tts_high: '높은',\n    tts_veryhigh: '매우 높은',\n    ARDUINO: '하드웨어',\n    ARDUINO_download_connector: '• 연결 프로그램 다운로드',\n    ARDUINO_open_connector: '연결 프로그램 열기',\n    ARDUINO_download_source: '• Entry Arduino code',\n    ARDUINO_reconnect: 'Connect Hardware',\n    arduino_noti_text: '모바일 기기는 추후 지원 합니다.',\n    arduino_lite_reconnect: '하드웨어 다시 연결',\n    arduino_lite_download_firmware: '펌웨어 다운로드',\n    arduino_lite_download_driver: '드라이버 다운로드',\n    arduino_lite_connect: '브라우저로 연결하기',\n    arduino_lite_disconnect: '하드웨어 선택 취소',\n    arduino_lite_guide: '• 아두이노 연결 가이드',\n    ROBOT_reconnect: '로봇 연결하기',\n    ARDUINO_program: '프로그램 실행하기',\n    ARDUINO_cloud_pc_connector: '클라우드 PC 연결하기',\n    ARDUINO_connected: 'Hardware connected',\n    ARDUINO_connect: '* Connect hardware',\n    ARDUINO_arduino_get_number_1: '신호',\n    ARDUINO_arduino_get_number_2: '의 숫자 결괏값',\n    ARDUINO_arduino_get_sensor_number_0: '0',\n    ARDUINO_arduino_get_sensor_number_1: '1',\n    ARDUINO_arduino_get_sensor_number_2: '2',\n    ARDUINO_arduino_get_sensor_number_3: '3',\n    ARDUINO_arduino_get_sensor_number_4: '4',\n    ARDUINO_arduino_get_sensor_number_5: '5',\n    blacksmith_toggle_on: '켜기',\n    blacksmith_toggle_off: '끄기',\n    blacksmith_lcd_first_line: '첫 번째',\n    blacksmith_lcd_seconds_line: '두 번째',\n    BITBRICK_light: 'light',\n    BITBRICK_IR: 'IR',\n    BITBRICK_touch: 'touch',\n    BITBRICK_potentiometer: 'potentiometer',\n    BITBRICK_MIC: 'MIC',\n    BITBRICK_UserSensor: 'UserSensor',\n    BITBRICK_UserInput: 'UserInput',\n    BITBRICK_dc_direction_ccw: 'CCW',\n    BITBRICK_dc_direction_cw: 'CW',\n    chocopi_control_event_pressed: '누를 때',\n    chocopi_control_event_released: '뗄 때',\n    chocopi_joystick_X: '조이스틱 좌우',\n    chocopi_joystick_Y: '조이스틱 상하',\n    chocopi_motion_photogate_event_blocked: '막았을 때',\n    chocopi_motion_photogate_event_unblocked: '열었을 때',\n    chocopi_motion_photogate_time_blocked: '막은 시간',\n    chocopi_motion_photogate_time_unblocked: '연 시간',\n    chocopi_port: '포트',\n    chocopi_pot: '볼륨',\n    chocopi_touch_event_touch: '만질 때',\n    chocopi_touch_event_untouch: '뗄 때',\n    CODEino_get_sensor_number_0: '0',\n    CODEino_get_sensor_number_1: '1',\n    CODEino_get_sensor_number_2: '2',\n    CODEino_get_sensor_number_3: '3',\n    CODEino_get_sensor_number_4: '4',\n    CODEino_get_sensor_number_5: '5',\n    CODEino_get_sensor_number_6: '6',\n    CODEino_sensor_name_0: 'Sound',\n    CODEino_sensor_name_1: 'Light',\n    CODEino_sensor_name_2: 'Slider',\n    CODEino_sensor_name_3: 'resistance-A',\n    CODEino_sensor_name_4: 'resistance-B',\n    CODEino_sensor_name_5: 'resistance-C',\n    CODEino_sensor_name_6: 'resistance-D',\n    CODEino_string_1: ' Sensor value ',\n    CODEino_string_2: ' Operation ',\n    CODEino_string_3: 'Push button',\n    CODEino_string_4: 'Connected A',\n    CODEino_string_5: 'Connected B',\n    CODEino_string_6: 'Connected C',\n    CODEino_string_7: 'Connected D',\n    CODEino_string_8: ' 3-AXIS Accelerometer ',\n    CODEino_string_9: '-axis value ',\n    CODEino_string_10: 'Sound is ',\n    CODEino_string_11: 'Great',\n    CODEino_string_12: 'Small',\n    CODEino_string_13: 'Light is ',\n    CODEino_string_14: 'Bright',\n    CODEino_string_15: 'Dark',\n    CODEino_string_16: 'Left tilt',\n    CODEino_string_17: 'Right tilt',\n    CODEino_string_18: 'Front tilt',\n    CODEino_string_19: 'Rear tilt',\n    CODEino_string_20: 'Reverse',\n    CODEino_accelerometer_X: 'X',\n    CODEino_accelerometer_Y: 'Y',\n    CODEino_accelerometer_Z: 'Z',\n    CODEino_led_red: '빨강',\n    CODEino_led_green: '초록',\n    CODEino_led_blue: '파랑',\n    iboard_analog_number_0: 'A0',\n    iboard_analog_number_1: 'A1',\n    iboard_analog_number_2: 'A2',\n    iboard_analog_number_3: 'A3',\n    iboard_analog_number_4: 'A4',\n    iboard_analog_number_5: 'A5',\n    iboard_light: '빛센서가 ',\n    iboard_num_pin_1: 'LED 상태를',\n    iboard_num_pin_2: '번 스위치가',\n    iboard_num_pin_3: '아날로그',\n    iboard_num_pin_4: '번 ',\n    iboard_num_pin_5: '센서값',\n    iboard_string_1: '켜짐',\n    iboard_string_2: '꺼짐',\n    iboard_string_3: '밝음',\n    iboard_string_4: '어두움',\n    iboard_string_5: '눌림',\n    iboard_string_6: '열림',\n    iboard_switch: '스위치 ',\n    iboard_tilt: '기울기센서 상태가',\n    dplay_switch: '스위치 ',\n    dplay_light: '빛센서가 ',\n    dplay_tilt: '기울기센서 상태가',\n    dplay_string_1: '켜짐',\n    dplay_string_2: '꺼짐',\n    dplay_string_3: '밝음',\n    dplay_string_4: '어두움',\n    dplay_string_5: '눌림',\n    dplay_string_6: '열림',\n    dplay_num_pin_1: 'LED 상태를',\n    dplay_num_pin_2: '번 스위치가',\n    dplay_num_pin_3: '아날로그',\n    dplay_num_pin_4: '번 ',\n    dplay_num_pin_5: '센서값',\n    dplay_analog_number_0: 'A0',\n    dplay_analog_number_1: 'A1',\n    dplay_analog_number_2: 'A2',\n    dplay_analog_number_3: 'A3',\n    dplay_analog_number_4: 'A4',\n    dplay_analog_number_5: 'A5',\n    ARDUINO_arduino_get_string_1: '신호',\n    ARDUINO_arduino_get_string_2: '의 글자 결괏값',\n    ARDUINO_arduino_send_1: '신호',\n    ARDUINO_arduino_send_2: '보내기',\n    ARDUINO_num_sensor_value_1: '아날로그',\n    ARDUINO_num_sensor_value_2: '번 센서값',\n    ARDUINO_get_digital_value_1: '디지털',\n    ARDUINO_num_pin_1: 'Digital',\n    ARDUINO_num_pin_2: 'Pin',\n    ARDUINO_toggle_pwm_1: 'Digital',\n    ARDUINO_toggle_pwm_2: 'Pin',\n    ARDUINO_toggle_pwm_3: '',\n    ARDUINO_on: 'On',\n    ARDUINO_convert_scale_1: 'Map Value',\n    ARDUINO_convert_scale_2: '',\n    ARDUINO_convert_scale_3: '~',\n    ARDUINO_convert_scale_4: 'to',\n    ARDUINO_convert_scale_5: '~',\n    ARDUINO_convert_scale_6: '',\n    ARDUINO_off: 'Off',\n    EXPANSION: '확장',\n    brightness: '밝기',\n    BRUSH: '붓',\n    BRUSH_brush_erase_all: 'this.brush.removeAll()',\n    BRUSH_change_opacity_1: 'this.brush.opacity +=',\n    BRUSH_change_opacity_2: '',\n    BRUSH_change_thickness_1: 'this.brush.thickness +=',\n    BRUSH_change_thickness_2: '',\n    BRUSH_set_color_1: 'this.brush.color =',\n    BRUSH_set_color_2: '',\n    BRUSH_set_opacity_1: 'this.brush.opacity =',\n    BRUSH_set_opacity_2: '',\n    BRUSH_set_random_color: 'this.brush.color = Entry.getRandomColor()',\n    BRUSH_set_thickness_1: 'this.brush.thickness =',\n    BRUSH_set_thickness_2: '',\n    BRUSH_stamp: 'Stamp',\n    BRUSH_start_drawing: 'this.startDraw()',\n    BRUSH_stop_drawing: 'this.stopDraw()',\n    CALC: '계산',\n    CALC_calc_mod_1: 'Entry.getMod(',\n    CALC_calc_mod_2: ',',\n    CALC_calc_mod_3: ')',\n    CALC_calc_operation_of_1: 'Entry.calculate(',\n    CALC_calc_operation_of_2: ',',\n    CALC_calc_operation_root: '루트',\n    CALC_calc_operation_square: '제곱',\n    CALC_calc_rand_1: 'Entry.getRandomNumber(',\n    CALC_calc_rand_2: ',',\n    CALC_calc_rand_3: ')',\n    CALC_calc_share_1: 'Entry.getShare(',\n    CALC_calc_share_2: ',',\n    CALC_calc_share_3: ')',\n    CALC_coordinate_mouse_1: 'Entry.getMousePosition(',\n    CALC_coordinate_mouse_2: ')',\n    CALC_coordinate_object_1: 'Entry.getPosition(',\n    CALC_coordinate_object_2: ',',\n    CALC_coordinate_object_3: ')',\n    CALC_distance_something_1: 'Entry.getDistance(this,',\n    CALC_distance_something_2: ')',\n    CALC_get_angle: '각도값',\n    CALC_get_date_1: 'Entry.getDate(',\n    CALC_get_date_2: ')',\n    CALC_get_date_day: '일',\n    CALC_get_date_hour: '시각(시)',\n    CALC_get_date_minute: '시각(분)',\n    CALC_get_date_month: '월',\n    CALC_get_date_second: '시각(초)',\n    CALC_get_date_year: '연도',\n    CALC_get_sound_duration_1: 'Entry.getSoundDuration(',\n    CALC_get_sound_duration_2: ')',\n    CALC_get_timer_value: 'Entry.getTimerValue()',\n    CALC_get_x_coordinate: 'this.x',\n    CALC_get_y_coordinate: 'this.y',\n    CALC_timer_reset: 'Entry.resetTimer()',\n    CALC_timer_visible_1: 'Entry.timerVisible(',\n    CALC_timer_visible_2: ')',\n    CALC_timer_visible_show: 'Show',\n    CALC_timer_visible_hide: 'Hide',\n    color: '색깔',\n    FLOW: '흐름',\n    FLOW__if_1: 'if (',\n    FLOW__if_2: ')',\n    FLOW_create_clone_1: 'Entry.createClone(',\n    FLOW_create_clone_2: ')',\n    FLOW_delete_clone: 'Entry.removeClone(this)',\n    FLOW_delete_clone_all: 'Entry.removeAllClone()',\n    FLOW_if_else_1: 'if (',\n    FLOW_if_else_2: ')',\n    FLOW_if_else_3: 'else',\n    FLOW_repeat_basic_1: 'for ( i = 0',\n    FLOW_repeat_basic_2: ')',\n    FLOW_repeat_basic_errorMsg: '',\n    FLOW_repeat_inf: 'while(true)',\n    FLOW_restart: 'Entry.restart()',\n    FLOW_stop_object_1: 'Entry.stop(',\n    FLOW_stop_object_2: ')',\n    FLOW_stop_object_all: '모두',\n    FLOW_stop_object_this_object: 'this.',\n    FLOW_stop_object_this_thread: '이',\n    FLOW_stop_object_other_thread: '자신의 다른',\n    FLOW_stop_object_other_objects: '다른 오브젝트의',\n    FLOW_stop_repeat: 'break',\n    FLOW_stop_run: '프로그램 끝내기',\n    FLOW_wait_second_1: 'Entry.wait(',\n    FLOW_wait_second_2: ')',\n    FLOW_wait_until_true_1: 'while (',\n    FLOW_wait_until_true_2: '!= true) { }',\n    FLOW_when_clone_start: \"Entry.addEventListener('clone_created')\",\n    FUNC: '함수',\n    ANALYSIS: '데이터분석',\n    AI: '인공지능',\n    JUDGEMENT: '판단',\n    JUDGEMENT_boolean_and: '&&',\n    JUDGEMENT_boolean_not_1: 'if (!',\n    JUDGEMENT_boolean_not_2: ')',\n    JUDGEMENT_boolean_or: '||',\n    JUDGEMENT_false: 'false',\n    JUDGEMENT_is_clicked: \"Entry.addEventListener('mouse_clicked')\",\n    JUDGEMENT_is_press_some_key_1: 'Entry.isKeyPressed(',\n    JUDGEMENT_is_press_some_key_2: ')',\n    JUDGEMENT_reach_something_1: 'Entry.isCollide(this,',\n    JUDGEMENT_reach_something_2: ')',\n    JUDGEMENT_true: 'true',\n    LOOKS: '생김새',\n    LOOKS_change_scale_percent_1: 'this.scale +=',\n    LOOKS_change_scale_percent_2: '',\n    LOOKS_change_to_next_shape: 'this.setToNextShape()',\n    LOOKS_change_to_nth_shape_1: 'this.setShape(',\n    LOOKS_change_to_nth_shape_2: ')',\n    LOOKS_change_shape_prev: 'Prev',\n    LOOKS_change_shape_next: 'Next',\n    LOOKS_change_to_near_shape_1: 'this.setTo',\n    LOOKS_change_to_near_shape_2: 'Shape()',\n    LOOKS_dialog_1: 'this.setDialog(',\n    LOOKS_dialog_2: ',',\n    LOOKS_dialog_3: ')',\n    LOOKS_dialog_time_1: 'this.setDialogByTime(',\n    LOOKS_dialog_time_2: ',',\n    LOOKS_dialog_time_3: ',',\n    LOOKS_dialog_time_4: ')',\n    LOOKS_erase_all_effects: 'this.removeAllEffects()',\n    LOOKS_flip_x: \"this.flip('vertical')\",\n    LOOKS_flip_y: \"this.flip('horizontal')\",\n    LOOKS_hide: 'this.hide()',\n    LOOKS_remove_dialog: 'this.removeDialog()',\n    LOOKS_set_effect_1: 'this.setEffect(',\n    LOOKS_set_effect_2: ',',\n    LOOKS_set_effect_3: ')',\n    LOOKS_set_effect_volume_1: 'this.addEffect(',\n    LOOKS_set_effect_volume_2: ',',\n    LOOKS_set_effect_volume_3: ')',\n    LOOKS_set_object_order_1: 'Entry.setLayerOrder(this,',\n    LOOKS_set_object_order_2: ')',\n    LOOKS_set_scale_percent_1: 'this.scale =',\n    LOOKS_set_scale_percent_2: '',\n    LOOKS_show: 'this.show()',\n    mouse_pointer: '마우스포인터',\n    MOVING: '움직임',\n    MOVING_bounce_wall: 'Entry.bounceWall(this)',\n    MOVING_bounce_when_1: '',\n    MOVING_bounce_when_2: '에 닿으면 튕기기',\n    MOVING_flip_arrow_horizontal: '화살표 방향 좌우 뒤집기',\n    MOVING_flip_arrow_vertical: '화살표 방향 상하 뒤집기',\n    MOVING_locate_1: 'this.locateAt(',\n    MOVING_locate_2: ')',\n    MOVING_locate_time_1: '',\n    MOVING_locate_time_2: '초 동안',\n    MOVING_locate_time_3: '위치로 이동하기',\n    MOVING_locate_x_1: 'this.x =',\n    MOVING_locate_x_2: '',\n    MOVING_locate_xy_1: 'this.setXY(',\n    MOVING_locate_xy_2: ',',\n    MOVING_locate_xy_3: ')',\n    MOVING_locate_xy_time_1: 'this.setXYbyTime(',\n    MOVING_locate_xy_time_2: ',',\n    MOVING_locate_xy_time_3: ',',\n    MOVING_locate_xy_time_4: ')',\n    MOVING_locate_y_1: 'this.y =',\n    MOVING_locate_y_2: '',\n    MOVING_move_direction_1: 'Entry.moveToDirection(',\n    MOVING_move_direction_2: ')',\n    MOVING_move_direction_angle_1: 'Entry.moveToDirection(',\n    MOVING_move_direction_angle_2: ',',\n    MOVING_move_direction_angle_3: ')',\n    MOVING_move_x_1: 'this.x +=',\n    MOVING_move_x_2: '',\n    MOVING_move_xy_time_1: 'this.moveXYbyTime(',\n    MOVING_move_xy_time_2: ',',\n    MOVING_move_xy_time_3: ',',\n    MOVING_move_xy_time_4: ')',\n    MOVING_move_y_1: 'this.y +=',\n    MOVING_move_y_2: '',\n    MOVING_rotate_by_angle_1: 'this.rotation +=',\n    MOVING_rotate_by_angle_2: '',\n    MOVING_rotate_by_angle_dropdown_1: '',\n    MOVING_rotate_by_angle_dropdown_2: '만큼 회전하기',\n    MOVING_rotate_by_angle_time_1: 'this.rotateByTime(',\n    MOVING_rotate_by_angle_time_2: ',',\n    MOVING_rotate_by_angle_time_3: ')',\n    MOVING_rotate_direction_1: 'this.direction +=',\n    MOVING_rotate_direction_2: '',\n    MOVING_see_angle_1: 'this.direction =',\n    MOVING_see_angle_2: '',\n    MOVING_see_angle_direction_1: 'this.rotation =',\n    MOVING_see_angle_direction_2: '',\n    MOVING_see_angle_object_1: 'this.setDirectionTo(',\n    MOVING_see_angle_object_2: ')',\n    MOVING_see_direction_1: '',\n    MOVING_see_direction_2: '쪽 보기',\n    MOVING_set_direction_by_angle_1: 'this.rotation =',\n    MOVING_set_direction_by_angle_2: '',\n    MOVING_add_direction_by_angle_1: 'this.rotation =',\n    MOVING_add_direction_by_angle_2: '',\n    MOVING_add_direction_by_angle_time_1: 'this.rotate(',\n    MOVING_add_direction_by_angle_time_2: ',',\n    MOVING_add_direction_by_angle_time_3: ')',\n    no_target: '대상 없음',\n    oneself: '자신',\n    opacity: '투명도',\n    SCENE: '장면',\n    SOUND: '소리',\n    SOUND_sound_silent_all: 'Entry.silentAll()',\n    SOUND_sound_something_1: 'Entry.playSound(',\n    SOUND_sound_something_2: ')',\n    SOUND_sound_something_second_1: 'Entry.playSoundByTime(',\n    SOUND_sound_something_second_2: ',',\n    SOUND_sound_something_second_3: ')',\n    SOUND_sound_something_second_wait_1: 'Entry.playSoundAndWaitByTime(',\n    SOUND_sound_something_second_wait_2: ',',\n    SOUND_sound_something_second_wait_3: ')',\n    SOUND_sound_something_wait_1: 'Entry.playSoundAndWait(',\n    SOUND_sound_something_wait_2: ')',\n    SOUND_sound_volume_change_1: 'Entry.volume +=',\n    SOUND_sound_volume_change_2: '',\n    SOUND_sound_volume_set_1: 'Entry.volume =',\n    SOUND_sound_volume_set_2: '',\n    speak: '말하기',\n    think: '생각하기',\n    START: '시작',\n    START_add_message: '신호 추가하기',\n    START_delete_message: '신호 삭제하기',\n    START_message_cast: '신호 보내기',\n    START_message_cast_1: 'Entry.dispatchEvent(',\n    START_message_cast_2: ')',\n    START_message_cast_wait: ')',\n    START_message_send_wait_1: 'Entry.dispatchEventAndWait(',\n    START_message_send_wait_2: ')',\n    START_mouse_click_cancled: \"Entry.addEventListener('mouseup')\",\n    START_mouse_clicked: \"Entry.addEventListener('mousedown')\",\n    START_press_some_key_1: \"Entry.addEventListener('keydown', key==\",\n    START_press_some_key_2: ')',\n    START_press_some_key_down: '아래쪽 화살표',\n    START_press_some_key_enter: '엔터',\n    START_press_some_key_left: '왼쪽 화살표',\n    START_press_some_key_right: '오른쪽 화살표',\n    START_press_some_key_space: '스페이스',\n    START_press_some_key_up: '위쪽 화살표',\n    START_when_message_cast: '신호를 받았을 때',\n    START_when_message_cast_1: 'Entry.addEventListener(',\n    START_when_message_cast_2: ')',\n    START_when_object_click: \"this.addEventListener('mousedown')\",\n    START_when_object_click_canceled: \"this.addEventListener('mouseup')\",\n    START_when_run_button_click: \"Entry.addEventListener('run')\",\n    START_when_scene_start: '장면이 시작했을때',\n    START_when_some_key_click: '키를 눌렀을 때',\n    TEXT: '글상자',\n    TEXT_text: 'Entry',\n    TEXT_text_append_1: 'Entry.appendText(',\n    TEXT_text_append_2: ')',\n    TEXT_text_flush: 'Entry.clearText()',\n    TEXT_text_prepend_1: 'Entry.insertText(',\n    TEXT_text_prepend_2: ')',\n    TEXT_text_write_1: 'Entry.writeText(',\n    TEXT_text_write_2: ')',\n    VARIABLE: '자료',\n    VARIABLE_add_value_to_list: '항목을 리스트에 추가하기',\n    VARIABLE_add_value_to_list_1: 'Entry.pushValueToList(',\n    VARIABLE_add_value_to_list_2: ',',\n    VARIABLE_add_value_to_list_3: ')',\n    VARIABLE_ask_and_wait_1: 'Entry.askAndWait(',\n    VARIABLE_ask_and_wait_2: ')',\n    VARIABLE_change_value_list_index: '항목을 바꾸기',\n    VARIABLE_change_value_list_index_1: 'Entry.changeValueListAt(',\n    VARIABLE_change_value_list_index_3: ',',\n    VARIABLE_change_value_list_index_2: ',',\n    VARIABLE_change_value_list_index_4: ')',\n    VARIABLE_change_variable: '변수 더하기',\n    VARIABLE_change_variable_1: 'Entry.addValueToVariable(',\n    VARIABLE_change_variable_2: ',',\n    VARIABLE_change_variable_3: ')',\n    VARIABLE_change_variable_name: '변수 이름 바꾸기',\n    VARIABLE_combine_something_1: 'Entry.concat(',\n    VARIABLE_combine_something_2: ',',\n    VARIABLE_combine_something_3: ')',\n    VARIABLE_get_canvas_input_value: 'Entry.getAnswer()',\n    VARIABLE_get_variable: '변수값',\n    VARIABLE_get_variable_1: 'Entry.getVariableValue(',\n    VARIABLE_get_variable_2: ')',\n    VARIABLE_get_y: 'Y 좌푯값',\n    VARIABLE_hide_list: '리스트 숨기기',\n    VARIABLE_hide_list_1: 'Entry.hideList(',\n    VARIABLE_hide_list_2: ')',\n    VARIABLE_hide_variable: '변수값 숨기기',\n    VARIABLE_hide_variable_1: 'Entry.hideVariable(',\n    VARIABLE_hide_variable_2: ')',\n    VARIABLE_insert_value_to_list: '항목을 넣기',\n    VARIABLE_insert_value_to_list_1: 'Entry.pushValueToListAt(',\n    VARIABLE_insert_value_to_list_2: ',',\n    VARIABLE_insert_value_to_list_3: ',',\n    VARIABLE_insert_value_to_list_4: ')',\n    VARIABLE_length_of_list: '리스트의 길이',\n    VARIABLE_length_of_list_1: 'Entry.getLength(',\n    VARIABLE_length_of_list_2: ')',\n    VARIABLE_list: '리스트',\n    VARIABLE_make_variable: '변수 만들기',\n    VARIABLE_list_option_first: 'FIRST',\n    VARIABLE_list_option_last: 'LAST',\n    VARIABLE_list_option_random: 'RANDOM',\n    VARIABLE_remove_value_from_list: '항목을 삭제하기',\n    VARIABLE_remove_value_from_list_1: 'Entry.removeValueListAt(',\n    VARIABLE_remove_value_from_list_2: ',',\n    VARIABLE_remove_value_from_list_3: ')',\n    VARIABLE_remove_variable: '변수 삭제',\n    VARIABLE_set_variable: '변수 정하기',\n    VARIABLE_set_variable_1: 'Entry.setValueVariable(',\n    VARIABLE_set_variable_2: ',',\n    VARIABLE_set_variable_3: ')',\n    VARIABLE_show_list: '리스트 보이기',\n    VARIABLE_show_list_1: 'Entry.showList(',\n    VARIABLE_show_list_2: ')',\n    VARIABLE_show_variable: '변수값 보이기',\n    VARIABLE_show_variable_1: 'Entry.showVariable(',\n    VARIABLE_show_variable_2: ')',\n    VARIABLE_value_of_index_from_list: '리스트 항목의 값',\n    VARIABLE_value_of_index_from_list_1: 'Entry.getListValueAt(',\n    VARIABLE_value_of_index_from_list_2: ',',\n    VARIABLE_value_of_index_from_list_3: ')',\n    HAMSTER_hand_found: 'Entry.Hamster.isHandFound()',\n    HAMSTER_sensor_left_proximity: 'Entry.Hamster.getLeftProximity()',\n    HAMSTER_sensor_right_proximity: 'Entry.Hamster.getRightProximity()',\n    HAMSTER_sensor_left_floor: 'Entry.Hamster.getLeftFloor()',\n    HAMSTER_sensor_right_floor: 'Entry.Hamster.getRightFloor()',\n    HAMSTER_sensor_acceleration_x: 'Entry.Hamster.getAccelerationX()',\n    HAMSTER_sensor_acceleration_y: 'Entry.Hamster.getAccelerationY()',\n    HAMSTER_sensor_acceleration_z: 'Entry.Hamster..getAccelerationZ()',\n    HAMSTER_sensor_light: 'Entry.Hamster.getLight()',\n    HAMSTER_sensor_temperature: 'Entry.Hamster.getTemperature()',\n    HAMSTER_sensor_signal_strength: 'Entry.Hamster.getSignalStrength()',\n    HAMSTER_sensor_input_a: 'Entry.Hamster.getInputA()',\n    HAMSTER_sensor_input_b: 'Entry.Hamster.getInputB()',\n    HAMSTER_move_forward_once: 'Entry.Hamster.moveForwardOnceOnBoard()',\n    HAMSTER_turn_once_1: \"Entry.Hamster.turnOnceOnBoard('\",\n    HAMSTER_turn_once_2: \"')\",\n    HAMSTER_turn_once_left: 'left',\n    HAMSTER_turn_right: 'right',\n    HAMSTER_move_forward: 'move forward',\n    HAMSTER_move_backward: 'move backward',\n    HAMSTER_turn_around_1: 'turn',\n    HAMSTER_turn_around_2: '',\n    HAMSTER_move_forward_for_secs_1: 'move forward for',\n    HAMSTER_move_forward_for_secs_2: 'secs',\n    HAMSTER_move_backward_for_secs_1: 'move backward',\n    HAMSTER_move_backward_for_secs_2: 'secs',\n    HAMSTER_turn_for_secs_1: 'turn',\n    HAMSTER_turn_for_secs_2: 'for',\n    HAMSTER_turn_for_secs_3: 'secs',\n    HAMSTER_change_both_wheels_by_1: 'change wheel by left:',\n    HAMSTER_change_both_wheels_by_2: 'right:',\n    HAMSTER_change_both_wheels_by_3: '',\n    HAMSTER_set_both_wheels_to_1: 'set wheel to left:',\n    HAMSTER_set_both_wheels_to_2: 'right:',\n    HAMSTER_set_both_wheels_to_3: ')',\n    HAMSTER_change_wheel_by_1: \"Entry.Hamster.changeWheelsBy('\",\n    HAMSTER_change_wheel_by_2: \"',\",\n    HAMSTER_change_wheel_by_3: ')',\n    HAMSTER_left_wheel: 'left',\n    HAMSTER_right_wheel: 'right',\n    HAMSTER_both_wheels: 'both',\n    HAMSTER_set_wheel_to_1: \"Entry.Hamster.setWheelsTo('\",\n    HAMSTER_set_wheel_to_2: \"',\",\n    HAMSTER_set_wheel_to_3: ')',\n    HAMSTER_follow_line_using_1: \"Entry.Hamster.followLineUsingFloorSensor('\",\n    HAMSTER_follow_line_using_2: \"','\",\n    HAMSTER_follow_line_using_3: \"')\",\n    HAMSTER_left_floor_sensor: 'left',\n    HAMSTER_right_floor_sensor: 'right',\n    HAMSTER_both_floor_sensors: 'both',\n    HAMSTER_follow_line_until_1: \"Entry.Hamster.followLineUntilIntersection('\",\n    HAMSTER_follow_line_until_2: \"','\",\n    HAMSTER_follow_line_until_3: \"')\",\n    HAMSTER_left_intersection: 'left',\n    HAMSTER_right_intersection: 'right',\n    HAMSTER_front_intersection: 'front',\n    HAMSTER_rear_intersection: 'rear',\n    HAMSTER_set_following_speed_to_1: 'Entry.Hamster.setFollowingSpeedTo(',\n    HAMSTER_set_following_speed_to_2: ')',\n    HAMSTER_front: 'front',\n    HAMSTER_rear: 'rear',\n    HAMSTER_stop: 'stop',\n    HAMSTER_set_led_to_1: \"Entry.Hamster.setLedTo('\",\n    HAMSTER_set_led_to_2: \"','\",\n    HAMSTER_set_led_to_3: \"')\",\n    HAMSTER_left_led: 'left',\n    HAMSTER_right_led: 'right',\n    HAMSTER_both_leds: 'both',\n    HAMSTER_clear_led_1: \"Entry.Hamster.clearLed('\",\n    HAMSTER_clear_led_2: \"')\",\n    HAMSTER_color_cyan: 'sky blue',\n    HAMSTER_color_magenta: 'purple',\n    HAMSTER_color_black: 'black',\n    HAMSTER_color_white: 'white',\n    HAMSTER_color_red: 'red',\n    HAMSTER_color_yellow: 'yellow',\n    HAMSTER_color_green: 'green',\n    HAMSTER_color_blue: 'blue',\n    HAMSTER_beep: 'Entry.Hamster.beep()',\n    HAMSTER_change_buzzer_by_1: 'change buzzer by',\n    HAMSTER_change_buzzer_by_2: '',\n    HAMSTER_set_buzzer_to_1: 'set buzzer to',\n    HAMSTER_set_buzzer_to_2: '',\n    HAMSTER_clear_buzzer: 'clear buzzer',\n    HAMSTER_play_note_for_1: \"Entry.Hamster.playNoteForBeats('\",\n    HAMSTER_play_note_for_2: \"',\",\n    HAMSTER_play_note_for_3: ',',\n    HAMSTER_play_note_for_4: ')',\n    HAMSTER_rest_for_1: 'Entry.Hamster.restForBeats(',\n    HAMSTER_rest_for_2: ')',\n    HAMSTER_change_tempo_by_1: 'Entry.Hamster.changeTempoBy(',\n    HAMSTER_change_tempo_by_2: ')',\n    HAMSTER_set_tempo_to_1: 'Entry.Hamster.setTempoTo(',\n    HAMSTER_set_tempo_to_2: ')',\n    HAMSTER_set_port_to_1: \"Entry.Hamster.setPortTo('\",\n    HAMSTER_set_port_to_2: \"','\",\n    HAMSTER_set_port_to_3: \"')\",\n    HAMSTER_change_output_by_1: \"Entry.Hamster.changeOutputBy('\",\n    HAMSTER_change_output_by_2: \"',\",\n    HAMSTER_change_output_by_3: ')',\n    HAMSTER_set_output_to_1: \"Entry.Hamster.setOutputTo('\",\n    HAMSTER_set_output_to_2: \"',\",\n    HAMSTER_set_output_to_3: ')',\n    HAMSTER_port_a: 'A',\n    HAMSTER_port_b: 'B',\n    HAMSTER_port_ab: 'AB',\n    HAMSTER_analog_input: 'AnalogInput',\n    HAMSTER_digital_input: 'DigitalInput',\n    HAMSTER_servo_output: 'ServoOutput',\n    HAMSTER_pwm_output: 'PwmOutput',\n    HAMSTER_digital_output: 'DigitalOutput',\n    ROBOID_acceleration_x: 'x축 가속도',\n    ROBOID_acceleration_y: 'y축 가속도',\n    ROBOID_acceleration_z: 'z축 가속도',\n    ROBOID_back: '뒤쪽',\n    ROBOID_both: '양쪽',\n    ROBOID_button: '버튼',\n    ROBOID_buzzer: '버저',\n    ROBOID_clicked: '클릭했는가',\n    ROBOID_color_any: '아무 색',\n    ROBOID_color_black: '검은색',\n    ROBOID_color_blue: '파란색',\n    ROBOID_color_green: '초록색',\n    ROBOID_color_number: '색깔 번호',\n    ROBOID_color_orange: '주황색',\n    ROBOID_color_pattern: '색깔 패턴',\n    ROBOID_color_purple: '자주색',\n    ROBOID_color_red: '빨간색',\n    ROBOID_color_sky_blue: '하늘색',\n    ROBOID_color_violet: '보라색',\n    ROBOID_color_white: '하얀색',\n    ROBOID_color_yellow: '노란색',\n    ROBOID_double_clicked: '더블클릭했는가',\n    ROBOID_floor: '바닥 센서',\n    ROBOID_head: '머리',\n    ROBOID_head_color: '머리 색깔',\n    ROBOID_left: '왼쪽',\n    ROBOID_left_wheel: '왼쪽 바퀴',\n    ROBOID_long_pressed: '길게~눌렀는가',\n    ROBOID_note: '음표',\n    ROBOID_right: '오른쪽',\n    ROBOID_right_wheel: '오른쪽 바퀴',\n    ROBOID_sound_beep: '삐',\n    ROBOID_sound_birthday: '생일',\n    ROBOID_sound_dibidibidip: '디비디비딥',\n    ROBOID_sound_engine: '엔진',\n    ROBOID_sound_good_job: '잘 했어요',\n    ROBOID_sound_march: '행진',\n    ROBOID_sound_random_beep: '무작위 삐',\n    ROBOID_sound_robot: '로봇',\n    ROBOID_sound_siren: '사이렌',\n    ROBOID_tail: '꼬리',\n    ROBOID_unit_cm: 'cm',\n    ROBOID_unit_deg: '도',\n    ROBOID_unit_pulse: '펄스',\n    ROBOID_unit_sec: '초',\n    ALBERT_hand_found: 'Entry.Albert.isHandFound()',\n    ALBERT_is_oid_1: \"Entry.Albert.isOidValue('\",\n    ALBERT_is_oid_2: \"',\",\n    ALBERT_is_oid_3: ')',\n    ALBERT_front_oid: 'front',\n    ALBERT_back_oid: 'back',\n    ALBERT_sensor_left_proximity: 'Entry.Albert.getLeftProximity()',\n    ALBERT_sensor_right_proximity: 'Entry.Albert.getRightProximity()',\n    ALBERT_sensor_acceleration_x: 'Entry.Albert.getAccelerationX()',\n    ALBERT_sensor_acceleration_y: 'Entry.Albert.getAccelerationY()',\n    ALBERT_sensor_acceleration_z: 'Entry.Albert.getAccelerationZ()',\n    ALBERT_sensor_light: 'Entry.Albert.getLight()',\n    ALBERT_sensor_temperature: 'Entry.Albert.getTemperature()',\n    ALBERT_sensor_battery: 'Entry.Albert.getBattery()',\n    ALBERT_sensor_signal_strength: 'Entry.Albert.getSignalStrength()',\n    ALBERT_sensor_front_oid: 'Entry.Albert.getFrontOid()',\n    ALBERT_sensor_back_oid: 'Entry.Albert.getBackOid()',\n    ALBERT_sensor_position_x: 'Entry.Albert.getPositionX()',\n    ALBERT_sensor_position_y: 'Entry.Albert.getPositionY()',\n    ALBERT_sensor_orientation: 'Entry.Albert.getOrientation()',\n    ALBERT_move_forward: 'Entry.Albert.moveForward()',\n    ALBERT_move_backward: 'Entry.Albert.moveBackward()',\n    ALBERT_turn_around_1: \"Entry.Albert.turn('\",\n    ALBERT_turn_around_2: \"')\",\n    ALBERT_move_forward_for_secs_1: 'Entry.Albert.moveForwardForSecs(',\n    ALBERT_move_forward_for_secs_2: ')',\n    ALBERT_move_backward_for_secs_1: 'Entry.Albert.moveBackwardForSecs(',\n    ALBERT_move_backward_for_secs_2: ')',\n    ALBERT_turn_for_secs_1: \"Entry.Albert.turnForSecs('\",\n    ALBERT_turn_for_secs_2: \"',\",\n    ALBERT_turn_for_secs_3: ')',\n    ALBERT_turn_left: 'left',\n    ALBERT_turn_right: 'right',\n    ALBERT_change_both_wheels_by_1: 'Entry.Albert.changeWheelsBy(',\n    ALBERT_change_both_wheels_by_2: ',',\n    ALBERT_change_both_wheels_by_3: ')',\n    ALBERT_left_wheel: 'left',\n    ALBERT_right_wheel: 'right',\n    ALBERT_both_wheels: 'both',\n    ALBERT_set_both_wheels_to_1: 'Entry.Albert.setWheelsTo(',\n    ALBERT_set_both_wheels_to_2: ',',\n    ALBERT_set_both_wheels_to_3: ')',\n    ALBERT_change_wheel_by_1: \"Entry.Albert.changeWheelsBy('\",\n    ALBERT_change_wheel_by_2: \"',\",\n    ALBERT_change_wheel_by_3: ')',\n    ALBERT_set_wheel_to_1: \"Entry.Albert.setWheelsTo('\",\n    ALBERT_set_wheel_to_2: \"',\",\n    ALBERT_set_wheel_to_3: ')',\n    ALBERT_stop: 'Entry.Albert.stop()',\n    ALBERT_set_board_size_to_1: 'Entry.Albert.setBoardSizeTo(',\n    ALBERT_set_board_size_to_2: ',',\n    ALBERT_set_board_size_to_3: ')',\n    ALBERT_move_to_x_y_1: 'Entry.Albert.moveToOnBoard(',\n    ALBERT_move_to_x_y_2: ',',\n    ALBERT_move_to_x_y_3: ')',\n    ALBERT_set_orientation_to_1: 'Entry.Albert.setOrientationToOnBoard(',\n    ALBERT_set_orientation_to_2: ')',\n    ALBERT_set_eye_to_1: \"Entry.Albert.setEyeTo('\",\n    ALBERT_set_eye_to_2: \"','\",\n    ALBERT_set_eye_to_3: \"')\",\n    ALBERT_left_eye: 'left',\n    ALBERT_right_eye: 'right',\n    ALBERT_both_eyes: 'both',\n    ALBERT_clear_eye_1: \"Entry.Albert.clearEye('\",\n    ALBERT_clear_eye_2: \"')\",\n    ALBERT_body_led_1: '',\n    ALBERT_body_led_2: 'body led',\n    ALBERT_front_led_1: '',\n    ALBERT_front_led_2: 'front led',\n    ALBERT_color_cyan: 'cyan',\n    ALBERT_color_magenta: 'magenta',\n    ALBERT_color_white: 'white',\n    ALBERT_color_red: 'red',\n    ALBERT_color_yellow: 'yellow',\n    ALBERT_color_green: 'green',\n    ALBERT_color_blue: 'blue',\n    ALBERT_note_c: 'C',\n    ALBERT_note_d: 'D',\n    ALBERT_note_e: 'E',\n    ALBERT_note_f: 'F',\n    ALBERT_note_g: 'G',\n    ALBERT_note_a: 'A',\n    ALBERT_note_b: 'B',\n    ALBERT_turn_body_led_1: \"Entry.Albert.turnBodyLed('\",\n    ALBERT_turn_body_led_2: \"')\",\n    ALBERT_turn_front_led_1: \"Entry.Albert.turnFrontLed('\",\n    ALBERT_turn_front_led_2: \"')'\",\n    ALBERT_turn_on: 'on',\n    ALBERT_turn_off: 'off',\n    ALBERT_beep: 'Entry.Albert.beep()',\n    ALBERT_change_buzzer_by_1: 'Entry.Albert.changeBuzzerBy(',\n    ALBERT_change_buzzer_by_2: ')',\n    ALBERT_set_buzzer_to_1: 'Entry.Albert.setBuzzerTo(',\n    ALBERT_set_buzzer_to_2: ')',\n    ALBERT_clear_buzzer: 'Entry.Albert.clearBuzzer()',\n    ALBERT_play_note_for_1: \"Entry.Albert.playNoteForBeats('\",\n    ALBERT_play_note_for_2: \"',\",\n    ALBERT_play_note_for_3: ',',\n    ALBERT_play_note_for_4: ')',\n    ALBERT_rest_for_1: 'Entry.Albert.restForBeats(',\n    ALBERT_rest_for_2: ')',\n    ALBERT_change_tempo_by_1: 'Entry.Albert.changeTempoBy(',\n    ALBERT_change_tempo_by_2: ')',\n    ALBERT_set_tempo_to_1: 'Entry.Albert.setTempoTo(',\n    ALBERT_set_tempo_to_2: ')',\n    VARIABLE_variable: '변수',\n    wall: '벽',\n    robotis_common_case_01: '(을)를',\n    robotis_common_set: '(으)로 정하기',\n    robotis_common_value: '값',\n    robotis_common_clockwhise: '시계방향',\n    robotis_common_counter_clockwhise: '반시계방향',\n    robotis_common_wheel_mode: '회전모드',\n    robotis_common_joint_mode: '관절모드',\n    robotis_common_red_color: '빨간색',\n    robotis_common_green_color: '녹색',\n    robotis_common_blue_color: '파란색',\n    robotis_common_on: '켜기',\n    robotis_common_off: '끄기',\n    robotis_common_cm: '제어기',\n    robotis_common_port_1: '포트 1',\n    robotis_common_port_2: '포트 2',\n    robotis_common_port_3: '포트 3',\n    robotis_common_port_4: '포트 4',\n    robotis_common_port_5: '포트 5',\n    robotis_common_port_6: '포트 6',\n    robotis_common_play_buzzer: '연주',\n    robotis_common_play_motion: '실행',\n    robotis_common_motion: '모션',\n    robotis_common_index_number: '번',\n    robotis_common_left: '왼쪽',\n    robotis_common_right: '오른쪽',\n    robotis_common_minute: '분',\n    robotis_cm_custom: '직접입력 주소',\n    robotis_cm_spring_left: '왼쪽 접촉 센서',\n    robotis_cm_spring_right: '오른쪽 접촉 센서',\n    robotis_cm_led_left: '왼쪽 LED',\n    robotis_cm_led_right: '오른쪽 LED',\n    robotis_cm_led_both: '양 쪽 LED',\n    robotis_cm_switch: '선택 버튼 상태',\n    robotis_cm_user_button: '사용자 버튼 상태',\n    robotis_cm_sound_detected: '최종 소리 감지 횟수',\n    robotis_cm_sound_detecting: '실시간 소리 감지 횟수',\n    robotis_cm_ir_left: '왼쪽 적외선 센서',\n    robotis_cm_ir_right: '오른쪽 적외선 센서',\n    robotis_cm_calibration_left: '왼쪽 적외선 센서 캘리브레이션 값',\n    robotis_cm_calibration_right: '오른쪽 적외선 센서 캘리브레이션 값',\n    robotis_cm_clear_sound_detected: '최종소리감지횟수 초기화',\n    robotis_cm_buzzer_index: '음계값',\n    robotis_cm_buzzer_melody: '멜로디',\n    robotis_cm_led_1: '1번 LED',\n    robotis_cm_led_4: '4번 LED',\n    robotis_aux_servo_position: '서보모터 위치',\n    robotis_aux_ir: '적외선센서',\n    robotis_aux_touch: '접촉센서',\n    robotis_aux_brightness: '조도센서(CDS)',\n    robotis_aux_hydro_themo_humidity: '온습도센서(습도)',\n    robotis_aux_hydro_themo_temper: '온습도센서(온도)',\n    robotis_aux_temperature: '온도센서',\n    robotis_aux_ultrasonic: '초음파센서',\n    robotis_aux_magnetic: '자석센서',\n    robotis_aux_motion_detection: '동작감지센서',\n    robotis_aux_color: '컬러센서',\n    robotis_aux_custom: '사용자 장치',\n    robotis_carCont_aux_motor_speed_1: '감속모터 속도를',\n    robotis_carCont_aux_motor_speed_2: ', 출력값을',\n    robotis_carCont_calibration_1: '적외선 센서 캘리브레이션 값을',\n    robotis_openCM70_aux_motor_speed_1: '감속모터 속도를',\n    robotis_openCM70_aux_motor_speed_2: ', 출력값을',\n    robotis_openCM70_aux_servo_mode_1: '서보모터 모드를',\n    robotis_openCM70_aux_servo_speed_1: '서보모터 속도를',\n    robotis_openCM70_aux_servo_speed_2: ', 출력값을',\n    robotis_openCM70_aux_servo_position_1: '서보모터 위치를',\n    robotis_openCM70_aux_led_module_1: 'LED 모듈을',\n    robotis_openCM70_aux_custom_1: '사용자 장치를',\n    XBOT_digital: '디지털',\n    XBOT_D2_digitalInput: 'D2 디지털 입력',\n    XBOT_D3_digitalInput: 'D3 디지털 입력',\n    XBOT_D11_digitalInput: 'D11 디지털 입력',\n    XBOT_analog: '아날로그',\n    XBOT_CDS: '광 센서 값',\n    XBOT_MIC: '마이크 센서 값',\n    XBOT_analog0: '아날로그 0번 핀 값',\n    XBOT_analog1: '아날로그 1번 핀 값',\n    XBOT_analog2: '아날로그 2번 핀 값',\n    XBOT_analog3: '아날로그 3번 핀 값',\n    XBOT_Value: '출력 값',\n    XBOT_pin_OutputValue: '핀, 출력 값',\n    XBOT_High: '높음',\n    XBOT_Low: '낮음',\n    XBOT_Servo: '서보 모터',\n    XBOT_Head: '머리(D8)',\n    XBOT_ArmR: '오른 팔(D9)',\n    XBOT_ArmL: '왼 팔(D10)',\n    XBOT_angle: ', 각도',\n    XBOT_DC: '바퀴(DC) 모터',\n    XBOT_rightWheel: '오른쪽',\n    XBOT_leftWheel: '왼쪽',\n    XBOT_bothWheel: '양쪽',\n    XBOT_speed: ', 속도',\n    XBOT_rightSpeed: '바퀴(DC) 모터 오른쪽(2) 속도:',\n    XBOT_leftSpeed: '왼쪽(1) 속도:',\n    XBOT_RGBLED_R: 'RGB LED 켜기 R 값',\n    XBOT_RGBLED_G: 'G 값',\n    XBOT_RGBLED_B: 'B 값',\n    XBOT_RGBLED_color: 'RGB LED 색',\n    XBOT_set: '로 정하기',\n    XBOT_c: '도',\n    XBOT_d: '레',\n    XBOT_e: '미',\n    XBOT_f: '파',\n    XBOT_g: '솔',\n    XBOT_a: '라',\n    XBOT_b: '시',\n    XBOT_melody_ms: '초 연주하기',\n    XBOT_Line: '번째 줄',\n    XBOT_outputValue: '출력 값',\n    roborobo_num_analog_value_1: '아날로그',\n    roborobo_num_analog_value_2: '번 센서값',\n    roborobo_get_digital_value_1: '디지털',\n    roborobo_num_pin_1: '디지털',\n    roborobo_num_pin_2: '번 핀',\n    roborobo_on: '켜기',\n    roborobo_off: '끄기',\n    roborobo_motor1: '모터1',\n    roborobo_motor2: '모터2',\n    roborobo_motor_CW: '정회전',\n    roborobo_motor_CCW: '역회전',\n    roborobo_motor_stop: '정지',\n    roborobo_input_mode: '입력',\n    roborobo_output_mode: '출력',\n    roborobo_pwm_mode: '전류조절(pwm)',\n    roborobo_servo_mode: '서보모터',\n    roborobo_color: '컬러센서',\n    roborobo_color_red: ' 빨간색  ',\n    roborobo_color_green: ' 녹색 ',\n    roborobo_color_blue: ' 파란색 ',\n    roborobo_color_yellow: '노란색 ',\n    roborobo_color_detected: ' 감지 ',\n    roborobo_degree: ' ˚',\n    robotori_D2_Input: '디지털 2번 핀 입력 값',\n    robotori_D3_Input: '디지털 3번 핀 입력 값',\n    robotori_A0_Input: '아날로그 0번 핀 입력 값',\n    robotori_A1_Input: '아날로그 1번 핀 입력 값',\n    robotori_A2_Input: '아날로그 2번 핀 입력 값',\n    robotori_A3_Input: '아날로그 3번 핀 입력 값',\n    robotori_A4_Input: '아날로그 4번 핀 입력 값',\n    robotori_A5_Input: '아날로그 5번 핀 입력 값',\n    robotori_digital: '디지털',\n    robotori_D10_Output: '10번',\n    robotori_D11_Output: '11번',\n    robotori_D12_Output: '12번',\n    robotori_D13_Output: '13번',\n    robotori_pin_OutputValue: '핀, 출력 값',\n    robotori_On: '켜짐',\n    robotori_Off: '꺼짐',\n    robotori_analog: '아날로그',\n    robotori_analog5: '5번 핀 출력 값',\n    robotori_analog6: '6번 핀 출력 값',\n    robotori_analog9: '9번 핀 출력 값',\n    robotori_Servo: '서보모터',\n    robotori_DC: 'DC모터',\n    robotori_DC_rightmotor: '오른쪽',\n    robotori_DC_leftmotor: '왼쪽',\n    robotori_DC_STOP: '정지',\n    robotori_DC_CW: '시계방향',\n    robotori_DC_CCW: '반시계방향',\n    robotori_DC_select: '회전',\n    CALC_rotation_value: 'this.getRotation()',\n    CALC_direction_value: 'this.getDirection()',\n    VARIABLE_is_included_in_list: '리스트에 포함되어 있는가?',\n    VARIABLE_is_included_in_list_1: 'Entry.isExistValueInList(',\n    VARIABLE_is_included_in_list_2: ',',\n    VARIABLE_is_included_in_list_3: ')',\n    SCENE_when_scene_start: \"this.addEventListener('sceneStart')\",\n    SCENE_start_scene_1: 'Scene.changeScene(',\n    SCENE_start_scene_2: ')',\n    SCENE_start_neighbor_scene_1: 'Scene.changeScene(',\n    SCENE_start_neighbor_scene_2: ')',\n    SCENE_start_scene_pre: 'Scene.getPrevious()',\n    SCENE_start_scene_next: 'Scene.getNext()',\n    FUNCTION_explanation_1: '이름',\n    FUNCTION_character_variable: '문자/숫자값',\n    FUNCTION_logical_variable: '판단값',\n    FUNCTION_function: '함수',\n    FUNCTION_define: '함수 정의하기',\n    CALC_calc_operation_sin: 'Math.sin(value)',\n    CALC_calc_operation_cos: 'Math.cos(value)',\n    CALC_calc_operation_tan: 'Math.tan(value)',\n    CALC_calc_operation_floor: 'Math.floor(value)',\n    CALC_calc_operation_ceil: 'Math.ceil(value)',\n    CALC_calc_operation_round: 'Math.round(value)',\n    CALC_calc_operation_factorial: '펙토리얼값',\n    CALC_calc_operation_asin: 'Math.asin(value)',\n    CALC_calc_operation_acos: 'Math.acos(value)',\n    CALC_calc_operation_atan: 'Math.atan(value)',\n    CALC_calc_operation_log: '로그값',\n    CALC_calc_operation_ln: '자연로그값',\n    CALC_calc_operation_natural: 'integer value',\n    CALC_calc_operation_unnatural: '소수점 부분',\n    MOVING_locate_object_time_1: '',\n    MOVING_locate_object_time_2: '초 동안',\n    MOVING_locate_object_time_3: '위치로 이동하기',\n    wall_up: '위쪽 벽',\n    wall_down: '아래쪽 벽',\n    wall_right: '오른쪽 벽',\n    wall_left: '왼쪽 벽',\n    CALC_coordinate_x_value: 'x 좌푯값',\n    CALC_coordinate_y_value: 'y 좌푯값',\n    CALC_coordinate_rotation_value: '방향',\n    CALC_coordinate_direction_value: '이동방향',\n    CALC_picture_index: '모양 번호',\n    CALC_picture_name: '모양 이름',\n    FLOW_repeat_while_true_1: 'Repeat',\n    FLOW_repeat_while_true_2: '',\n    TUT_when_start: \"Entry.addEventListener('run_button_clicked')\",\n    TUT_move_once: 'Entry.moveOnce()',\n    TUT_rotate_left: 'Entry.rotateLeft()',\n    TUT_rotate_right: 'Entry.rotateRight()',\n    TUT_jump_barrier: 'Entry.jumpBarrier()',\n    TUT_repeat_tutorial_1: 'Entry.repeat(',\n    TUT_repeat_tutorial_2: ')',\n    TUT_if_barrier_1: 'if (',\n    TUT_if_barrier_2: ')',\n    TUT_if_conical_1: 'if (',\n    TUT_if_conical_2: ')',\n    TUT_repeat_until: 'while (Entry.reachToPart()) {}',\n    TUT_repeat_until_gold: 'while (Entry.reachToPart()) {}',\n    TUT_declare_function: 'new function()',\n    TUT_call_function: 'call function()',\n    CALC_calc_operation_abs: '절댓값',\n    CONTEXT_COPY_option: '코드 복사',\n    Delete_Blocks: '코드 삭제',\n    Duplication_option: '코드 복사 & 붙여넣기',\n    Paste_blocks: '붙여넣기',\n    add_my_storage: '나의 보관함에 추가하기',\n    export_object: '오브젝트 내보내기',\n    Clear_all_blocks: '모든 코드 삭제하기',\n    add_comment: '메모 추가하기',\n    copy_paste_comment: '메모 복사 & 붙여넣기',\n    copy_comment: '메모 복사하기',\n    delete_comment: '메모 삭제하기',\n    fold_comment: '메모 접기',\n    open_comment: '메모 열기',\n    separate_comment: '메모 분리하기',\n    hide_all_comment: '모든 메모 숨기기',\n    show_all_comment: '모든 메모 보이기',\n    transparency: '투명도',\n    BRUSH_change_brush_transparency_1: 'this.brush.opacity -=',\n    BRUSH_change_brush_transparency_2: '',\n    BRUSH_set_brush_transparency_1: 'this.brush.opacity -=',\n    BRUSH_set_brush_transparency_2: '',\n    CALC_char_at_1: '',\n    CALC_char_at_2: '.charAt(',\n    CALC_char_at_3: ')',\n    CALC_length_of_string_1: '',\n    CALC_length_of_string_2: '.length()',\n    CALC_substring_1: '',\n    CALC_substring_2: '.subString(',\n    CALC_substring_3: ',',\n    length_of_string: '',\n    CALC_substring_4: ')',\n    CALC_replace_string_1: '',\n    CALC_replace_string_2: '.replace(',\n    CALC_replace_string_3: ',',\n    CALC_replace_string_4: ')',\n    CALC_change_string_case_1: '',\n    CALC_change_string_case_2: '',\n    CALC_change_string_case_3: ' ',\n    CALC_change_string_case_sub_1: '.uppercase()',\n    CALC_change_string_case_sub_2: '.lowercase()',\n    CALC_index_of_string_1: '',\n    CALC_index_of_string_2: '.indexOf(',\n    CALC_index_of_string_3: ')',\n    MOVING_add_direction_by_angle_time_explain_1: '',\n    MOVING_direction_relative_duration_1: '',\n    MOVING_direction_relative_duration_2: '',\n    MOVING_direction_relative_duration_3: '',\n    CALC_get_sound_volume: 'Volume',\n    SOUND_sound_from_to_1: '',\n    SOUND_sound_from_to_2: '',\n    SOUND_sound_from_to_3: '',\n    SOUND_sound_from_to_4: '',\n    SOUND_sound_from_to_and_wait_1: '',\n    SOUND_sound_from_to_and_wait_2: '',\n    SOUND_sound_from_to_and_wait_3: '',\n    SOUND_sound_from_to_and_wait_4: '',\n    CALC_quotient_and_mod_1: '',\n    CALC_quotient_and_mod_2: '/',\n    CALC_quotient_and_mod_3: '',\n    CALC_quotient_and_mod_4: ' ',\n    CALC_quotient_and_mod_sub_1: '몫',\n    CALC_quotient_and_mod_sub_2: '나머지',\n    self: '자신',\n    CALC_coordinate_size_value: '크기',\n    CALC_choose_project_timer_action_1: 'Entry.setTimer(',\n    CALC_choose_project_timer_action_2: ')',\n    CALC_choose_project_timer_action_sub_1: '시작하기',\n    CALC_choose_project_timer_action_sub_2: '정지하기',\n    CALC_choose_project_timer_action_sub_3: '초기화하기',\n    LOOKS_change_object_index_1: 'Entry.setLayerOrder(this,',\n    LOOKS_change_object_index_2: ')',\n    LOOKS_change_object_index_sub_1: '맨 앞으로',\n    LOOKS_change_object_index_sub_2: '앞으로',\n    LOOKS_change_object_index_sub_3: '뒤로',\n    LOOKS_change_object_index_sub_4: '맨 뒤로',\n    FLOW_repeat_while_true_until: 'until',\n    FLOW_repeat_while_true_while: 'while',\n    copy_block: '블록 복사',\n    delete_block: '블록 삭제',\n    tidy_up_block: '코드 정리하기',\n    block_hi: '안녕!',\n    entry_bot_name: '엔트리봇',\n    hi_entry: '안녕 엔트리!',\n    hi_entry_en: 'Hello Entry!',\n    bark_dog: '강아지 짖는 소리',\n    walking_entryBot: '엔트리봇_걷기',\n    doggi_bark: '강아지 짖는 소리',\n    entry: '엔트리',\n    hello: '안녕',\n    nice: '반가워',\n    silent: '무음',\n    do_name: '도',\n    do_sharp_name: '도#(레♭)',\n    re_name: '레',\n    re_sharp_name: '레#(미♭)',\n    mi_name: '미',\n    fa_name: '파',\n    fa_sharp_name: '파#(솔♭)',\n    sol_name: '솔',\n    sol_sharp_name: '솔#(라♭)',\n    la_name: '라',\n    la_sharp_name: '라#(시♭)',\n    DUMMY: '더미',\n    coconut_stop_motor: '모터 정지',\n    coconut_move_motor: '움직이기',\n    coconut_turn_motor: '으로 돌기',\n    coconut_move_outmotor: '외부모터',\n    coconut_turn_left: '왼쪽',\n    coconut_turn_right: '오른쪽',\n    coconut_move_forward: '앞으로',\n    coconut_move_backward: '뒤로',\n    coconut_note_c: '도',\n    coconut_note_d: '레',\n    coconut_note_e: '미',\n    coconut_note_f: '파',\n    coconut_note_g: '솔',\n    coconut_note_a: '라',\n    coconut_note_b: '시',\n    coconut_move_speed_1: '0',\n    coconut_move_speed_2: '50',\n    coconut_move_speed_3: '100',\n    coconut_move_speed_4: '150',\n    coconut_move_speed_5: '255',\n    coconut_play_buzzer_hn: '2분음표',\n    coconut_play_buzzer_qn: '4분음표',\n    coconut_play_buzzer_en: '8분음표',\n    coconut_play_buzzer_sn: '16분음표',\n    coconut_play_buzzer_tn: '32분음표',\n    coconut_play_buzzer_wn: '온음표',\n    coconut_play_buzzer_dhn: '점2분음표',\n    coconut_play_buzzer_dqn: '점4분음표',\n    coconut_play_buzzer_den: '점8분음표',\n    coconut_play_buzzer_dsn: '점16분음표',\n    coconut_play_buzzer_dtn: '점32분음표',\n    coconut_rest_buzzer_hr: '2분쉼표',\n    coconut_rest_buzzer_qr: '4분쉼표',\n    coconut_rest_buzzer_er: '8분쉼표',\n    coconut_rest_buzzer_sr: '16분쉼표',\n    coconut_rest_buzzer_tr: '32분쉼표',\n    coconut_rest_buzzer_wr: '온쉼표',\n    coconut_play_midi_1: '반짝반짝 작은별',\n    coconut_play_midi_2: '곰세마리',\n    coconut_play_midi_3: '모차르트 자장가',\n    coconut_play_midi_4: '도레미송',\n    coconut_play_midi_5: '나비야',\n    coconut_floor_sensing_on: '감지',\n    coconut_floor_sensing_off: '미감지',\n    coconut_dotmatrix_set_on: '켜짐',\n    coconut_dotmatrix_set_off: '꺼짐',\n    coconut_dotmatrix_row_0: '모든',\n    coconut_dotmatrix_row_1: '1',\n    coconut_dotmatrix_row_2: '2',\n    coconut_dotmatrix_row_3: '3',\n    coconut_dotmatrix_row_4: '4',\n    coconut_dotmatrix_row_5: '5',\n    coconut_dotmatrix_row_6: '6',\n    coconut_dotmatrix_row_7: '7',\n    coconut_dotmatrix_row_8: '8',\n    coconut_dotmatrix_col_0: '모든',\n    coconut_dotmatrix_col_1: '1',\n    coconut_dotmatrix_col_2: '2',\n    coconut_dotmatrix_col_3: '3',\n    coconut_dotmatrix_col_4: '4',\n    coconut_dotmatrix_col_5: '5',\n    coconut_dotmatrix_col_6: '6',\n    coconut_dotmatrix_col_7: '7',\n    coconut_dotmatrix_col_8: '8',\n    coconut_sensor_left_proximity: '왼쪽 전방 센서',\n    coconut_sensor_right_proximity: '오른쪽 전방 센서',\n    coconut_sensor_both_proximity: '모든',\n    coconut_sensor_left_floor: '왼쪽 바닥센서',\n    coconut_sensor_right_floor: '오른쪽 바닥 센서',\n    coconut_sensor_both_floor: '모든',\n    coconut_sensor_acceleration_x: 'x축 가속도',\n    coconut_sensor_acceleration_y: 'y축 가속도',\n    coconut_sensor_acceleration_z: 'z축 가속도',\n    coconut_sensor_light: '밝기',\n    coconut_sensor_temperature: '온도',\n    coconut_left_led: '왼쪽',\n    coconut_right_led: '오른쪽',\n    coconut_both_leds: '모든',\n    coconut_color_cyan: '하늘색',\n    coconut_color_magenta: '보라색',\n    coconut_color_black: '검은색',\n    coconut_color_white: '흰색',\n    coconut_color_red: '빨간색',\n    coconut_color_yellow: '노란색',\n    coconut_color_green: '초록색',\n    coconut_color_blue: '파란색',\n    coconut_beep: '삐 소리내기',\n    coconut_clear_buzzer: '버저 끄기',\n    coconut_x_axis: 'X축',\n    coconut_y_axis: 'Y축',\n    coconut_z_axis: 'Z축',\n    modi_enviroment_bule: '파랑',\n    modi_enviroment_green: '초록',\n    modi_enviroment_humidity: '습도',\n    modi_enviroment_illuminance: '조도',\n    modi_enviroment_red: '빨강',\n    modi_enviroment_temperature: '온도',\n    modi_gyroscope_xAcceleratior: 'X축 가속',\n    modi_gyroscope_yAcceleratior: 'Y축 가속',\n    modi_gyroscope_zAcceleratior: 'Z축 가속',\n    modi_motor_angle: '각도',\n    modi_motor_speed: '속도',\n    modi_motor_torque: '회전',\n    modi_speaker_F_DO_5: '도5',\n    modi_speaker_F_DO_6: '도6',\n    modi_speaker_F_DO_7: '도7',\n    modi_speaker_F_DO_S_5: '도#5',\n    modi_speaker_F_DO_S_6: '도#6',\n    modi_speaker_F_DO_S_7: '도#7',\n    modi_speaker_F_MI_5: '미5',\n    modi_speaker_F_MI_6: '미6',\n    modi_speaker_F_MI_7: '미7',\n    modi_speaker_F_PA_5: '파5',\n    modi_speaker_F_PA_6: '파6',\n    modi_speaker_F_PA_7: '파7',\n    modi_speaker_F_PA_S_5: '파#5',\n    modi_speaker_F_PA_S_6: '파#6',\n    modi_speaker_F_PA_S_7: '파#7',\n    modi_speaker_F_RA_5: '라5',\n    modi_speaker_F_RA_6: '라6',\n    modi_speaker_F_RA_7: '라7',\n    modi_speaker_F_RA_S_5: '라#5',\n    modi_speaker_F_RA_S_6: '라#6',\n    modi_speaker_F_RA_S_7: '라#7',\n    modi_speaker_F_RE_5: '레5',\n    modi_speaker_F_RE_6: '레6',\n    modi_speaker_F_RE_7: '레7',\n    modi_speaker_F_RE_S_5: '라#5',\n    modi_speaker_F_RE_S_6: '레#6',\n    modi_speaker_F_RE_S_7: '레#7',\n    modi_speaker_F_SOL_5: '솔5',\n    modi_speaker_F_SOL_6: '솔6',\n    modi_speaker_F_SOL_7: '솔7',\n    modi_speaker_F_SOL_S_5: '솔#5',\n    modi_speaker_F_SOL_S_6: '솔#6',\n    modi_speaker_F_SOL_S_7: '솔#7',\n    modi_speaker_F_SO_5: '시5',\n    modi_speaker_F_SO_6: '시6',\n    modi_speaker_F_SO_7: '시7',\n    si_name: '시',\n    ev3_ccw: 'CCW',\n    ev3_cw: 'CW',\n    rokoboard_sensor_name_0: '소리',\n    rokoboard_sensor_name_1: '빛',\n    rokoboard_sensor_name_2: '슬라이더',\n    rokoboard_sensor_name_3: '저항-A',\n    rokoboard_sensor_name_4: '저항-B',\n    rokoboard_sensor_name_5: '저항-C',\n    rokoboard_sensor_name_6: '저항-D',\n    rokoboard_string_1: '버튼을 눌렀는가?',\n    HW_MOTOR: '모터',\n    HW_SENSOR: '센서',\n    HW_LED: '발광다이오드',\n    HW_MELODY: '멜로디',\n    HW_ROBOT: '로봇',\n    ALTINO_ACCX: '가속도 X축',\n    ALTINO_ACCY: '가속도 Y축',\n    ALTINO_ACCZ: '가속도 Z축',\n    ALTINO_BAT: '배터리 잔량 체크',\n    ALTINO_CDS: '밝기',\n    ALTINO_GYROX: '자이로 X축',\n    ALTINO_GYROY: '자이로 Y축',\n    ALTINO_GYROZ: '자이로 Z축',\n    ALTINO_IR1: '1번 거리',\n    ALTINO_IR2: '2번 거리',\n    ALTINO_IR3: '3번 거리',\n    ALTINO_IR4: '4번 거리',\n    ALTINO_IR5: '5번 거리',\n    ALTINO_IR6: '6번 거리',\n    ALTINO_Led_Brake_Light: '브레이크',\n    ALTINO_Led_Forward_Light: '전방',\n    ALTINO_Led_Reverse_Light: '후방',\n    ALTINO_Led_Turn_Left_Light: '왼쪽방향',\n    ALTINO_Led_Turn_Right_Light: '오른쪽방향',\n    ALTINO_Line: '번째 줄',\n    ALTINO_MAGX: '나침판 X축',\n    ALTINO_MAGY: '나침판 Y축',\n    ALTINO_MAGZ: '나침판 Z축',\n    ALTINO_REMOTE: '리모콘 수신 값',\n    ALTINO_STTOR: '조향 토크',\n    ALTINO_STVAR: '조향 가변저항',\n    ALTINO_Steering_Angle_Center: '가운데',\n    ALTINO_Steering_Angle_Left10: '왼쪽10',\n    ALTINO_Steering_Angle_Left15: '왼쪽15',\n    ALTINO_Steering_Angle_Left20: '왼쪽20',\n    ALTINO_Steering_Angle_Left5: '왼쪽5',\n    ALTINO_Steering_Angle_Right10: '오른쪽10',\n    ALTINO_Steering_Angle_Right15: '오른쪽15',\n    ALTINO_Steering_Angle_Right20: '오른쪽20',\n    ALTINO_Steering_Angle_Right5: '오른쪽5',\n    ALTINO_TEM: '온도',\n    ALTINO_TOR1: '오른쪽 토크',\n    ALTINO_TOR2: '왼쪽 토크',\n    ALTINO_Value: '출력 값',\n    ALTINO_a: '라',\n    ALTINO_a2: '라#',\n    ALTINO_b: '시',\n    ALTINO_c: '도',\n    ALTINO_c2: '도#',\n    ALTINO_d: '레',\n    ALTINO_d2: '레#',\n    ALTINO_dot_display_1: '한문자',\n    ALTINO_dot_display_2: '출력하기',\n    ALTINO_e: '미',\n    ALTINO_f: '파',\n    ALTINO_f2: '파#',\n    ALTINO_g: '솔',\n    ALTINO_g2: '솔#',\n    ALTINO_h: '끄기',\n    ALTINO_h2: '켜기',\n    ALTINO_leftWheel: '왼쪽',\n    ALTINO_melody_ms: '연주하기',\n    ALTINO_outputValue: '출력 값',\n    ALTINO_rightWheel: '오른쪽',\n    ALTINO_set: '로 정하기',\n    ardublock_motor_forward: '앞',\n    ardublock_motor_backward: '뒤',\n    jdkit_clockwise: '시계방향',\n    jdkit_counterclockwise: '반시계방향',\n    jdkit_gyro_frontrear: '앞뒤',\n    jdkit_gyro_leftright: '좌우',\n    jdkit_joystick_leftleftright: '왼쪽 좌우',\n    jdkit_joystick_lefttopbottom: '왼쪽 상하',\n    jdkit_joystick_rightleftright: '오른쪽 좌우',\n    jdkit_joystick_righttopbottom: '오른쪽 상하',\n    jdkit_led: 'LED',\n    jdkit_led_color_green: '초록색',\n    jdkit_led_color_orange: '오랜지색',\n    jdkit_led_turnoff: '끄기',\n    jdkit_led_turnon: '켜기',\n    jdkit_motor_leftbottom: '왼쪽아래',\n    jdkit_motor_lefttop: '왼쪽위',\n    jdkit_motor_rightbottom: '오른쪽아래',\n    jdkit_motor_righttop: '오른쪽위',\n    jdkit_tune_do: '도',\n    jdkit_tune_fa: '파',\n    jdkit_tune_la: '라',\n    jdkit_tune_mi: '미',\n    jdkit_tune_re: '레',\n    jdkit_tune_si: '시',\n    jdkit_tune_sol: '솔',\n    FUNBOARD_bt_down: '노랑(B)',\n    FUNBOARD_bt_left: '초록(C)',\n    FUNBOARD_bt_right: '파랑(D)',\n    FUNBOARD_bt_up: '빨강(A)',\n    FUNBOARD_column_tag: '칸',\n    FUNBOARD_do_off: '끄기',\n    FUNBOARD_do_on: '켜기',\n    FUNBOARD_led_color_all: '모두',\n    FUNBOARD_led_color_blue: '파랑',\n    FUNBOARD_led_color_green: '초록',\n    FUNBOARD_led_color_red: '빨강',\n    FUNBOARD_led_color_str: '색',\n    FUNBOARD_led_color_yellow: '노랑',\n    FUNBOARD_led_off_str: 'LED 끄기',\n    FUNBOARD_led_on_str: 'LED 켜기',\n    FUNBOARD_row_tag: '줄',\n    FUNBOARD_scroll_down: '아래쪽으로',\n    FUNBOARD_scroll_left: '왼쪽으로',\n    FUNBOARD_scroll_no: '없음',\n    FUNBOARD_scroll_right: '오른쪽으로',\n    FUNBOARD_scroll_up: '위쪽으로',\n    FUNBOARD_sensor_cds: 'Cds (밝기 감지)',\n    FUNBOARD_sensor_mic: '마이크 (소리 감지)',\n    FUNBOARD_sensor_slide: '슬라이드 (막대 조정)',\n    FUNBOARD_sensor_state_1: '작다',\n    FUNBOARD_sensor_state_2: '크다',\n    FUNBOARD_touchbt_down: '노랑(B)',\n    FUNBOARD_touchbt_enter: '   F',\n    FUNBOARD_touchbt_escape: '   G',\n    FUNBOARD_touchbt_left: '초록(C)',\n    FUNBOARD_touchbt_right: '파랑(D)',\n    FUNBOARD_touchbt_space: '   E',\n    FUNBOARD_touchbt_up: '빨강(A)',\n    funboard_dotmatrix_set_off: '끄기',\n    funboard_dotmatrix_set_on: '켜기',\n    AI_UTILIZE: '인공지능',\n    video_show_video: '보이기',\n    video_hide_video: '숨기기',\n    video_brightness: '밝기',\n    video_transparency: '투명도',\n    video_left_right: '좌우',\n    video_top_bottom: '상하',\n    video_human: '사람',\n    video_face: '얼굴',\n    video_object: '사물',\n    video_start: '시작하기',\n    video_end: '중지하기',\n    video_gender: '성별',\n    video_age: '나이',\n    video_emotion: '감정',\n    video_motion_onself: '자신',\n    video_motion_onscreen: '실행화면',\n    video_motion_scale: '움직임',\n    video_motion_direction_horizontal: '좌우방향',\n    video_motion_direction_vertical: '상하방향',\n    table_row: '행',\n    table_col: '열',\n    table_sum: '합',\n    table_max: '최대',\n    table_min: '최소',\n    table_avg: '평균',\n    table_stdev: '표준편차',\n};\nLang.video_body_coord_params = {\n    left_eye: '왼쪽 눈',\n    right_eye: '오른쪽 눈',\n    nose: '코',\n    left_mouth: '왼쪽 입꼬리',\n    right_mouth: '오른쪽 입꼬리',\n    upper_lip: '윗 입술',\n    lower_lip: '아랫 입술',\n    face: '얼굴',\n    neck: '목',\n    left_ear: '왼쪽 귀',\n    right_ear: '오른쪽 귀',\n    left_shoulder: '왼쪽 어깨',\n    left_elbow: '왼쪽 팔꿈치',\n    left_wrist: '왼쪽 손목',\n    left_hip: '왼쪽 엉덩이',\n    left_knee: '왼쪽 무릎',\n    left_ankle: '왼쪽 발목',\n    right_shoulder: '오른쪽 어깨',\n    right_elbow: '오른쪽 팔꿈치',\n    right_wrist: '오른쪽 손목',\n    right_hip: '오른쪽 엉덩이',\n    right_knee: '오른쪽 무릎',\n    right_ankle: '오른쪽 발목',\n};\nLang.video_emotion_params = {\n    angry: '분노',\n    disgusted: '혐오',\n    fearful: '두려움',\n    happy: '행복',\n    neutral: '무표정',\n    sad: '슬픔',\n    surprised: '놀람',\n};\nLang.video_object_params = {\n    person: '사람',\n    bicycle: '자전거',\n    car: '자동차',\n    motorcycle: '오토바이',\n    airplane: '비행기',\n    bus: '버스',\n    train: '기차',\n    truck: '트럭',\n    boat: '보트',\n    'traffic light': '신호등',\n    'fire hydrant': '소화전',\n    'stop sign': '일단 정지 표지판',\n    'parking meter': '주차요금 계산기',\n    bench: '벤치',\n    bird: '새',\n    cat: '고양이',\n    dog: '강아지',\n    horse: '말',\n    sheep: '양',\n    cow: '소',\n    elephant: '코끼리',\n    bear: '곰',\n    zebra: '얼룩말',\n    giraffe: '기린',\n    backpack: '배낭',\n    umbrella: '우산',\n    handbag: '핸드백',\n    tie: '넥타이',\n    suitcase: '여행 가방',\n    frisbee: '프리즈비 원반',\n    skis: '스키',\n    snowboard: '스노우보드',\n    'sports ball': '공',\n    kite: '연',\n    'baseball bat': '야구 배트',\n    'baseball glove': '야구 글러브',\n    skateboard: '스케이트 보드',\n    surfboard: '서핑 보드',\n    'tennis racket': '테니스 라켓',\n    bottle: '병',\n    'wine glass': '와인 잔',\n    cup: '컵',\n    fork: '포크',\n    knife: '칼',\n    spoon: '숟가락',\n    bowl: '사발',\n    banana: '바나나',\n    apple: '사과',\n    sandwich: '샌드위치',\n    orange: '오렌지',\n    broccoli: '브로콜리',\n    carrot: '당근',\n    'hot dog': '핫도그',\n    pizza: '피자',\n    donut: '도넛',\n    cake: '케이크',\n    chair: '의자',\n    couch: '소파',\n    'potted plant': '식물 화분',\n    bed: '침대',\n    'dining table': '식탁',\n    toilet: '변기',\n    tv: '텔레비젼',\n    laptop: '노트북',\n    mouse: '마우스',\n    remote: '리모콘',\n    keyboard: '키보드',\n    'cell phone': '휴대전화',\n    microwave: '전자렌지',\n    oven: '오븐',\n    toaster: '토스터기',\n    sink: '싱크대',\n    refrigerator: '냉장고',\n    book: '책',\n    clock: '시계',\n    vase: '꽃병',\n    scissors: '가위',\n    'teddy bear': '곰인형',\n    'hair drier': '헤어 드라이기',\n    toothbrush: '칫솔',\n};\nLang.Buttons = {\n    share_policy: '이것만은 꼭!',\n    write_policy: '작성 가이드',\n    lesson_list: '강의 목록',\n    complete_study: '학습 완료하기',\n    show_me: '미리 보기',\n    do_this_for_me: '대신 해주기',\n    previous: '이전',\n    get_started: '시작하기',\n    next_lesson: '다음 내용 학습하기',\n    course_submit: '제출하기',\n    course_done: '확인',\n    mission: '미션 확인하기',\n    basic_guide: '기본 사용 방법',\n    apply: '적용하기',\n    add: '추가하기',\n    cancel: '취소',\n    save: '확인',\n    start: '시작',\n    confirm: '확인',\n    delete: '삭제',\n    create: '학급 만들기',\n    done: '완료',\n    accept: '수락',\n    refuse: '거절',\n    yes: '예',\n    button_no: '아니오',\n    quiz_retry: '다시 풀어보기',\n    discuss_upload: '불러오기',\n    maze_popup_guide: '이용안내',\n    maze_popup_mapHint: '힌트보기',\n    maze_hint_btn_guide: '이용 안내',\n    maze_hint_btn_block: '블록 도움말',\n    maze_hint_btn_map: '힌트 보기',\n    maze_hint_btn_goal: '목표',\n    list_save: '저장하기',\n    duplication: '복사하기',\n    export_to_excel: '엑셀로 내려받기',\n    single_line: '한 줄 쓰기',\n    multi_line: '여러 줄 쓰기',\n    lecture_finish_popup_reset_lecture: '처음부터 다시하기',\n    lecture_finish_popup_show_output: '실습한 코드보기',\n    lecture_view_hints: '잘 모르겠어요!',\n    default_hint_title: '어떻게 만들까?',\n    show_only_vector: '벡터 모아보기',\n};\nLang.Menus = {\n    nothing_to_import: '불러오기 할 항목이 없습니다.',\n    nothing_to_export: '내려받기 할 항목이 없습니다.',\n    content_copied: '내용이 복사되었습니다.',\n    list_import_title: '리스트 불러오기',\n    list_import_placeholder: '예)\\n내용1\\n내용2\\n내용3\\n내용4\\n내용5\\n내용6\\n내용7\\n내용8',\n    verifying_email: '인증 메일 발송하기',\n    list_import_notice_1: '리스트 항목의 내용을 올릴 수 있습니다.',\n    list_import_notice_2: '기존 내용은 새로 저장한 내용으로 변경됩니다.',\n    list_export_title: '리스트 내보내기',\n    list_export_notice: '리스트 항목의 내용을 복사하거나, 엑셀로 내려받을 수 있습니다.',\n    robotis_opencm70: '로보티즈 IoT',\n    cannnot_mark_favorite: '비공개 작품은 관심 작품으로 지정할 수 없습니다.',\n    enterPassword: '비밀번호를 입력해주세요.',\n    enterPassword_update: '변경 내용을 저장하기 위해 비밀번호를 입력해주세요.',\n    enterNewPassword: '새로운 비밀번호를 입력하세요.',\n    reEnterNewPassword: '새로운 비밀번호를 다시 입력하세요.',\n    resign: '회원탈퇴',\n    check_sended_email: '발송된 인증 메일을 확인하여 이메일 주소를 인증해 주세요.',\n    signUpEmail_1: '입력된 이메일 주소로 인증 메일이 발송되었습니다.',\n    signUpEmail_2: '이메일 주소를 인증해주세요.',\n    select_email_unauthenticated_user:\n        '해당 이메일 주소가 아래 계정에 등록되어 있습니다.\\n인증을 원하는 계정을 선택해주세요.',\n    select_user: '계정을 선택해주세요.',\n    enter_password_withdraw: '회원탈퇴 신청을 위해 비밀번호를 입력해주세요.',\n    instruction_agree: '안내 사항에 동의해주세요.',\n    check_instructions: '위 안내 사항에 동의합니다.',\n    deleteAccount_2:\n        '회원탈퇴를 신청하신 30일 이후에는 회원정보와 작품/강의/학급/게시글/댓글/좋아요/관심 정보가 모두 삭제되며 복구가 불가능합니다.',\n    deleteAccount_1:\n        '회원탈퇴를 신청하신 30일 이내에 로그인하시면 회원탈퇴를 취소하실 수 있습니다.',\n    protect_account: '안전한 비밀번호로 내정보를 보호하세요.',\n    please_verify: '인증 메일을 발송하여 이메일 주소를 인증해 주세요.',\n    unverified_email: '이메일 주소가 인증되지 않았습니다.',\n    deleteAccount: '회원탈퇴 신청',\n    corporatePersonal: '개인정보 이전에 동의 합니다',\n    corporateTransferGuide: \"개인정보 양수자('엔트리' 웹사이트 운영자) 안내\",\n    corporateReciever: '개인정보를 이전 받은 자: 재단법인 커넥트',\n    corporateAddress: '커넥트 주소 및 연락처',\n    corporateAddress_1: '서울시 강남구 강남대로 382 메리츠타워 7층',\n    corporateConsent: '개인정보의 이전을 원치 않으시는 경우 ,동의 철회 방법',\n    corporateEmail: '계정에 등록된 이메일로 탈퇴 요청 메일 발송',\n    corporateAddition: '또한 , 영업 양도에 따라 약관 등이 아래와 같이 변경될 예정입니다.',\n    corporateApplicationDate: '적용시기 : 2017년 10월 29일',\n    corporateTargetChanges: '적용대상 및 변경사항 :',\n    corporateTarget: '적용대상',\n    corporateChanges: '변경사항',\n    corporateTerms: '엔트리 이용약관',\n    corporateOperator: '웹사이트 운영자의 명칭 변경',\n    corporateClassroomTerms: '학급 서비스 이용약관',\n    doAgreeWithClassroomTerms: '학급 서비스 이용약관에 동의합니다.',\n    doChangePassword: '나만 알수 있는 비밀번호로 변경해주세요.',\n    corporatePrivacyPolicy: '개인정보 처리방침',\n    corporateConsignment: '웹사이트 운영자의 명칭 변경 및 개인정보 위탁 업체 추가',\n    corporateEntrusted: '수탁업: NHN Technology Service(주)',\n    corporateConsignmentDetails: '위탁업무 내용: 서비스 개발 및 운영',\n    corporatePeriod: '보유기간 : 회원 탈퇴 시 혹은 위탁 계약 종료시 까지',\n    corporateChangeDate: '변경 적용일 : 2017년 10월 29일 부',\n    corporateWarning: '개인정보 이전에 동의해 주세요.',\n    corporateConfirm: '확인',\n    corporateTitle:\n        '안녕하세요. 엔트리교육연구소입니다. <br>“엔트리”를 이용하고 계신 회원 여러분께 깊은 감사의 말씀을 드립니다.<br> 엔트리교육연구소는 그동안 공익 목적으로 운영해오던 “엔트리” 웹사이트의 운영을<br> 네이버가 설립한 비영리 재단인 커넥트재단에 양도하기로 합의하였습니다. <br>앞으로 엔트리는 커넥트재단에서 공익 목적 하에 지속적으로 운영될 수 있도록 <br>할 것이며, 회원 여러분께서는 기존과 동일하게 엔트리를 이용하실 수 있습니다.<br> 웹사이트 제공 주체가 엔트리교육연구소에서 커넥트재단으로 변경됨에 따라 아래와 <br>같이 회원 개인 정보에 대한 이전이 있으며, 본 합의에 의해 실제 개인 정보의 위치가 <br>물리적으로 이동한 것은 아님을 알려드립니다. ',\n    textcoding_numberError_f:\n        '등록된 함수 중에 이름의 첫 글자가 숫자인 함수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1f: '등록된 함수 중에 이름이',\n    textcoding_bookedError_2f: '인 함수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_f:\n        \"등록된 함수 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    textcoding_numberError_v:\n        '등록된 변수 중에 이름의 첫 글자가 숫자인 변수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1v: '등록된 변수 중에 변수 이름이 ',\n    textcoding_bookedError_2v: ' 인 변수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_v:\n        \"등록된 변수 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    textcoding_numberError_l:\n        '등록된 리스트 중에 이름의 첫 글자가 숫자인 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1l: '등록된 리스트 중에 리스트 이름이',\n    textcoding_bookedError_2l: '인 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_l:\n        \"등록된 리스트 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    no_discuss_permission: '글을 읽을 권한이 없습니다',\n    delete_comment: '댓글을 삭제하시겠습니까?',\n    delete_article: '게시물을 삭제하시겠습니까?',\n    discuss_cannot_edit: '본인의 게시물이 아닙니다.',\n    discuss_extention: '실행파일은 첨부하실 수 없습니다.',\n    delete_discuss_picture: '사진을 삭제하시겠습니까?',\n    delete_discuss_file: '파일을 삭제하시겠습니까?',\n    discuss_save_question: '글을 저장하시겠습니까?',\n    discuss_cancle_question: '작성을 취소하시겠습니까?',\n    discuss_saved: '이(가) 저장되었습니다.',\n    discuss_no_write_permission: '현재 로그인된 계정으로는 글을 작성하실 수 없습니다.',\n    discuss_no_project_permission: '현재 로그인된 계정으로는 작품을 게시하실 수 없습니다.',\n    discuss_write_abuse_detected:\n        '짧은 시간안에 여러 글이 작성되었습니다.\\n1분 뒤에 다시 시도해주세요.',\n    contents_abuse_detected: '5분 뒤에 다시 시도해주세요.',\n    contents_abuse_detected_10: '10분 뒤에 다시 시도해주세요.',\n    discuss_new_write_abuse_warn:\n        '짧은 시간안에 새 글을 작성하는 경우 \\n게시글 작성이 제한될 수 있습니다. \\n이용에 주의하시길 바랍니다.',\n    discuss_write_abuse_warn:\n        '짧은 시간안에 여러 댓글을 작성하는 경우 \\n댓글 작성이 제한될 수 있습니다. \\n이용에 주의하시길 바랍니다.',\n    find_not_your_email: '올바른 이메일을 입력해주세요.',\n    search_lang: '검색',\n    search_title: '제목',\n    faq_desc: '엔트리를 이용하면서 궁금한 점들의 답변을 확인해보세요.',\n    faq_all: '전체보기',\n    faq_site: '사이트 이용',\n    faq_project: '작품 만들기',\n    faq_hardware: '하드웨어',\n    faq_offline: '오프라인',\n    faq_copyright: '저작권',\n    faq_title: '자주하는 질문',\n    faq: '자주하는 질문',\n    malicious_warning:\n        '불건전한 사진은 불러올 수 없습니다. 불건전한 사진이 아닌 경우 제안 및 건의에 해당 사진을 첨부하여 신고해주세요.',\n    fword_alert_msg: '욕설이나 불건전한 글은 게시할 수 없습니다.',\n    fword_alert_1: '주제와 무관한 욕설이나 악플은 게시할 수 없습니다.',\n    fword_alert_2: '불건전한 단어가 포함되어 있어, 대체 문장으로 게시 됩니다.',\n    fword_replace_1: '엔트리를 통해 누구나 쉽고 재미있게 소프트웨어를 배울 수 있어요.',\n    fword_replace_2: '소프트웨어 교육의 첫걸음, 엔트리.',\n    fword_replace_3: '재미있게 배우는 학습 공간 엔트리!',\n    fword_replace_4: '엔트리에서 공유와 협업을 통해 멋진 작품을 만들어요.',\n    fword_replace_5:\n        '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있게 개발된 소프트웨어 교육 플랫폼입니다.',\n    fword_replace_6: '엔트리와 함께 건강한 소프트웨어 교육 생태계를 조성해요!',\n    fword_replace_7: '엔트리에서 학습하고, 만들고, 공유하며 같이 성장해요.',\n    solve_quiz: '퀴즈 풀기',\n    submit_homework_first_title: '완성! 과제 제출하기',\n    submit_homework_first_content:\n        '멋진 작품이 완성되었습니다. 과제를 제출하세요. 마감 기한 전까지 다시 제출할 수 있습니다.',\n    submit_homework_again_title: '과제 다시 제출하기',\n    submit_homework_again_content: '이미 제출한 과제입니다.<br>과제를 다시 제출하시겠습니까?',\n    submit_homework_expired_title: '과제 제출 마감',\n    submit_homework_expired_content: '과제 제출이 마감되었습니다.',\n    done_study_title: '완성',\n    done_study_content: '만든 작품을 실행해 봅시다.',\n    featured_courses: '추천 강의 모음',\n    follow_along: '따라하기',\n    follow_along_desc: '차근차근 따라하며 다양한 작품을 만듭니다.',\n    do_quiz: '퀴즈풀기',\n    do_quiz_desc: '학습한 내용을 잘 이해했는지 퀴즈를 통해 확인합니다.',\n    challenge: '도전하기',\n    play: '도전하기',\n    challenge_desc: '주어진 문제를 스스로 해결하며 개념을 익힙니다.',\n    creste_freely: '자유롭게 만들기',\n    creste_freely_desc: '학습한 내용으로 나만의 작품을 자유롭게 만듭니다.',\n    entry_rc_desc:\n        '프로그래밍의 원리를 학습단계에 맞게 배울 수 있는 엔트리 강의 모음! 지금 시작해보세요!<br>따라하고, 도전하며 소프트웨어를 만들다 보면 어렵게 느껴졌던 프로그래밍의 원리도 쉽고 재미있게 다가옵니다!',\n    hw_deadline: '마감 일자',\n    rc_course_desc:\n        '프로그래밍의 원리를 학습단계에 맞게 배울 수 있도록 구성된 엔트리 강의 모음입니다.',\n    rc_course: '추천 강의 모음',\n    entry_rec_course: '엔트리 추천 강의 모음',\n    entry_rec_course_desc:\n        '누구나 쉽게 보고 따라하면서 재미있고 다양한 소프트웨어를 만들 수 있는 엔트리 강의를 소개합니다.',\n    guidance: '안내',\n    wait: '잠깐',\n    hint: '힌트',\n    concept_guide: '개념 톡톡',\n    group_quiz: '우리 반 퀴즈',\n    fail_check_hint: '앗… 실패! 다시 한 번 도전해보세요!<br>어려울 땐 [힌트]를 확인해보세요!',\n    sort_student: '학생별',\n    sort_lesson: '강의별',\n    sort_course: '강의 모음별',\n    student_progress: '우리 반 진도',\n    my_progress: '나의 진도',\n    lec_in_progress: '학습 중',\n    free_modal_asgn_over: '과제 제출이 마감되었습니다.',\n    free_submission_closed: '과제 제출 마감',\n    free_modal_asgn_submit_first:\n        '멋진 작품이 완성되었습니다! 과제를 제출하세요.<br>마감 기한 전까지 다시 제출 할 수 있습니다.',\n    asgn_submit: '완성! 과제 제출하기',\n    free_modal_content_resubmit: '이미 제출한 과제입니다.<br>과제를 다시 제출하시겠습니까?',\n    asgn_resubmit: '과제 다시 제출하기',\n    free_modal_content_complete: '멋진 작품이 완성되었습니다.',\n    guide_modal_content_complete: '만든 작품을 실행해 봅시다.',\n    success: '성공',\n    fail: '실패',\n    mission_modal_content_fail: '<br>어려울 땐 [힌트]를 확인해보세요!',\n    mission_modal_content_success: '만든 작품을 실행해 봅시다.',\n    in_progress: '진행중',\n    completed: '완료',\n    submitted: '제출 완료',\n    submission_closed: '마감',\n    progress: '진행 상황',\n    study_completed: '학습 완료',\n    view_course_desc: '코스웨어 설명 보기',\n    main_entry_starter: '기초부터! 엔트리 스타터',\n    main_entry_booster: '개념탄탄! 엔트리 부스터',\n    main_entry_master: '생각을 펼치는! 엔트리 마스터',\n    no_students_in_classroom:\n        '아직 등록된 학생이 없습니다.<br>학생을 직접 추가하거나, 초대해 보세요!',\n    lectures: '강의',\n    Lectures: '강의',\n    studentHomeworkList: '과제',\n    curriculums: '강의 모음',\n    Curriculums: '강의 모음',\n    quiz: '퀴즈',\n    no_added_group_contents_teacher:\n        '추가된 %1이(가) 없습니다. <br>우리 반 %1을(를) 추가해 주세요.',\n    no_added_group_contents_student:\n        '아직 올라온 %1이(가) 없습니다. 선생님이 %1을(를) 올려주시면, 학습 내용을 확인할 수 있습니다.',\n    side_project: '목표 작품',\n    custom_make_course_1: \"'오픈 강의 만들기> 강의 모음 만들기'에서\",\n    custom_make_course_2: '나만의 강의 모음을 만들어 보세요.',\n    custom_make_lecture_1: \"'오픈 강의 만들기'에서\",\n    custom_make_lecture_2: '나만의 강의를 만들어 보세요',\n    alert_enter_info: '수정할 정보를 입력해주세요.',\n    alert_enter_new_pwd: '기존 비밀번호와 다른 비밀번호를 입력해주세요.',\n    alert_match_pwd: '새로운 비밀번호와 재입력된 비밀번호가 일치하지 않습니다.',\n    alert_check_pwd: '비밀번호를 확인해주세요.',\n    alert_update_complete: '정보가 수정 되었습니다.',\n    no_group_contents_each_prefix: '우리반 ',\n    no_group_contents_each_suffix: ' 이(가) 없습니다.',\n    no_group_contents_all:\n        '학급에 올라온 컨텐츠가 없습니다.<br>학급 공유하기에<br>나만의 작품을 공유해보세요!',\n    hw_closed: '과제 마감',\n    tag_Lecture: '강의',\n    tag_Curriculum: '강의모음',\n    tag_Discuss: '공지',\n    count_ko: '개',\n    no_asgn_within_week: '1주일안에 제출되어야 하는 마감 임박한 과제가 없습니다.',\n    lecture_and_curriculum: '강의 / 강의 모음',\n    assignments_plural: '과제',\n    assignments_singular: '과제',\n    project_plural: '작품',\n    group_news: '새로운 소식',\n    stu_management: '학생 관리',\n    stu_management_camel: '학생 관리',\n    view_all: '전체 보기',\n    view_all_camel: '전체 보기',\n    view_contents_camel: '콘텐츠 보기',\n    view_contents: '콘텐츠 보기',\n    no_updated_news: '나의 학급에 올라온 새로운 소식이 없습니다.',\n    homework_soon_due: '곧 마감 과제',\n    new_homework: '최신 과제',\n    no_new_homework: '새로운 과제가 없습니다.',\n    student_plural: '학생',\n    discuss: '공지',\n    basic_project: '기본 작품',\n    no_permission: '권한이 없습니다.',\n    no_comment_write_permission: '현재 로그인된 계정으로는 답변을 작성하실 수 없습니다.',\n    original_curriculum_deleted: '원본 강의 모음이 삭제되었습니다.',\n    original_curriculum: '원본 강의 모음',\n    save_as_my_lecture: '복사본으로 저장하기 ',\n    delete_confirm: '삭제 알림',\n    lecture_open_as_copied: '오픈 강의 페이지에 올라간 모든 강의는 사본으로 생성되어 공개 됩니다.',\n    curriculum_open_as_copied:\n        '오픈 강의 모음 페이지에 올라간 모든 강의 모음은 사본으로 생성되어 공개 됩니다.',\n    lecture_save_as_copied_group:\n        '우리 반 강의 페이지에 올라간 모든 강의는 사본으로 생성되어 공개 됩니다.',\n    curriculum_save_as_copied_group:\n        '우리 반 강의 모음 페이지에 올라간 모든 강의 모음은 사본으로 생성되어 공개 됩니다.',\n    homework_save_as_copied_group:\n        '우리 반 과제 페이지에 올라간 모든 과제는 사본으로 생성되어 공개 됩니다.',\n    lecture_save_as_copied:\n        '내가 만든 강의 모음 안에 삽입된 구성 강의는 사본으로 생성되어 저장됩니다.',\n    done_project_save_as_copied:\n        '내가 만든 강의 안에 삽입된 완성 작품은 사본으로 생성되어 저장됩니다.',\n    textbook_project_can_not_applied:\n        '교과형 만들기(실과)로 만들어진 작품은 강의로 만들 수 없습니다.',\n    original_lecture_deleted: '원본 강의가 삭제되었습니다.',\n    original_lecture: '원본 강의',\n    lecture_save_as_mine_alert:\n        \"저장되었습니다.\\n저장된 강의는 '마이페이지> 나의 강의'에서 확인할 수 있습니다.\",\n    lecture_save_as_mine: '내 강의로 저장하기',\n    duplicate_username: '이미 입력한 아이디 입니다.',\n    share_your_project: '내가 만든 작품을 공유해 보세요',\n    not_available_student:\n        \"학급에서 발급된 '학급 아이디'입니다.\\n'엔트리 회원 아이디'를 입력해주세요.\",\n    login_instruction: '로그인 안내',\n    login_needed: '로그인 후 이용할 수 있습니다.',\n    login_as_teacher: '선생님 계정으로 로그인 후 이용할 수 있습니다.',\n    remove_my_storage:\n        '나의 보관함에서 삭제하시겠습니까? 삭제한 블록/오브젝트는 복구할 수 없습니다.',\n    submit_hw: '과제 제출하기',\n    success_goal: '목표성공',\n    choseok_final_result: '좋아 , 나만의 작품을 완성했어!',\n    choseok_fail_msg_timeout: '시간이 너무 많이 지나버렸어. 목표를 잘 보고 다시 한번 도전해봐!',\n    choseok_fail_msg_die:\n        '생명이 0이하인데 게임이 끝나지 않았어.\\n아래의 블록을 사용해서 다시 도전해 보는 건 어때?',\n    grade_1: '초급',\n    grade_2: '중급',\n    grade_3: '고급',\n    find_sally_title: '샐리를 찾아서',\n    save_sally_title: '샐리 구하기',\n    exit_sally_title: '샐리 탈출하기',\n    find_sally: '라인 레인저스의 힘을 모아 \\n강력한 악당 메피스토를 물리치고 샐리를 구해주세요!',\n    save_sally:\n        '메피스토 기지에 갇힌 샐리. \\n라인 레인저스가 장애물을 피해 샐리를 찾아갈 수 있도록\\n도와주세요!',\n    exit_sally:\n        '폭파되고 있는 메피스토 기지에서 \\n샐리와 라인 레인저스가 무사히 탈출할 수 있도록\\n도와주세요!',\n    go_next_mission: '다른 미션 도전하기',\n    share_my_project: '내가 만든 작품 공유하기',\n    share_certification: '인증서 공유하기',\n    print_certification: '인증서를 뽐내봐',\n    get_cparty_events: '내가 받은 인증서를 출력해 뽐내면 푸짐한 상품을 받을 수 있어요!',\n    go_cparty_events: '이벤트 참여하러 가기',\n    codingparty2016_blockHelper_1_title: '앞으로 가기',\n    codingparty2016_blockHelper_1_contents: '앞으로 가기',\n    codingparty2016_blockHelper_2_title: '앞으로 가기',\n    codingparty2016_blockHelper_2_contents: '회전하기',\n    codingparty2016_blockHelper_3_title: '앞으로 가기',\n    codingparty2016_blockHelper_3_contents: '돌 부수기',\n    codingparty2016_blockHelper_4_title: '앞으로 가기',\n    codingparty2016_blockHelper_4_contents: '횟수 반복하기',\n    codingparty2016_blockHelper_5_title: '앞으로 가기',\n    codingparty2016_blockHelper_5_contents: '꽃 던지기',\n    codingparty2016_goalHint_1:\n        '샐리를 구하기 위해서는 미네랄이 필요해! 미네랄을 얻으며 목적지까지 가보자!',\n    codingparty2016_goalHint_2: '구불구불한 길이 있네. 회전 블록을 사용하면 어렵지 않을 거야!',\n    codingparty2016_goalHint_3: '앞이 돌로 막혀있잖아? 돌을 부수며 목적지까지 가보자!',\n    codingparty2016_goalHint_4: '복잡한 길이지만 지금까지 배운 것들로 해결할 수 있어!',\n    codingparty2016_goalHint_5:\n        '앞으로 쭉 가는 길이잖아? 반복 블록을 사용하여 간단하게 해결해 보자!',\n    codingparty2016_goalHint_6: '미네랄을 모두 모아오자. 반복블록을 쓰면 쉽게 다녀올 수 있겠어!',\n    codingparty2016_goalHint_7:\n        '친구들이 다치지 않도록 꽃을 던져 거미집을 제거해야 해. 저 멀리 있는 거미집을 제거하고 목적지까지 가 보자.',\n    codingparty2016_goalHint_8:\n        '가는 길에 거미집이 많잖아? 거미집을 모두 제거하고 목적지까지 가 보자.',\n    codingparty2016_goalHint_9: '거미집 뒤쪽에 있는 미네랄을 모두 모아오자!',\n    codingparty2016_guide_1_1_contents:\n        '라인 레인저스 전사들이 샐리를 구할 수 있도록 도와줘! 전사들을 움직이기 위해서는 블록 명령어를 조립해야 해.\\n\\n① 먼저 미션 화면과 목표를 확인하고,\\n② 블록 꾸러미에서 필요한 블록을 가져와 “시작하기를 클릭했을 때“ 블록과 연결해.\\n③ 다 조립되면 ‘시작하기‘ 버튼을 눌러 봐! 블록이 위에서부터 순서대로 실행되며 움직일 거야.',\n    codingparty2016_guide_1_1_title: '라인 레인저스 전사들을 움직이려면?',\n    codingparty2016_guide_1_2_title: '목표 블록의 개수',\n    codingparty2016_guide_1_2_contents:\n        '① [안 칠해진 별]의 개수만큼 블록을 조립해 미션을 해결해보자. 목표 블록보다 더 많은 블록을 사용하면 별이 빨간색으로 바뀌니 정해진 개수 안에서 문제를 해결해 봐!\\n② 필요하지 않은 블록은 휴지통 또는 블록꾸러미에 넣어줘.',\n    codingparty2016_guide_1_3_title: \"'앞으로 가기' 블록을 사용하기\",\n    codingparty2016_guide_1_3_contents:\n        '< 앞으로 가기 > 는 앞으로 한 칸 이동하는 블록이야. \\n\\n여러 칸을 이동하기 위해서는 이 블록을 여러 번 연결해야 해.',\n    codingparty2016_guide_1_4_title: '미네랄 획득하기',\n    codingparty2016_guide_1_4_contents:\n        '[ 미네랄 ]이 있는 곳을 지나가면 미네랄을 획득할 수 있어\\n\\n화면에 있는 미네랄을 모두 획득하고 목적지에 도착해야만 다음 단계로 넘어갈 수 있어.',\n    codingparty2016_guide_1_5_title: '어려울 때 도움을 받으려면?',\n    codingparty2016_guide_1_5_contents:\n        '미션을 수행하다가 어려울 땐 3가지 종류의 도움말 버튼을 눌러 봐.\\n\\n\\n<안내> 지금 이 안내를 다시 보고 싶을 때!\\n<블록 도움말> 블록 하나하나가 어떻게 동작하는지 궁금할 때!\\n<맵 힌트> 이 단계를 해결하기 위한 힌트가 필요할 때!',\n    codingparty2016_guide_2_1_title: '회전 블록 사용하기',\n    codingparty2016_guide_2_1_contents:\n        '<오른쪽으로 돌기>와 <왼쪽으로 돌기>는 \\n제자리에서 90도 회전하는 블록이야. 방향만 회전하는 블록이야. \\n캐릭터가 바라보고 있는 방향을 기준으로 오른쪽인지 왼쪽인지 잘 생각해 봐!\\n',\n    codingparty2016_guide_3_1_title: '(문) 능력 사용하기',\n    codingparty2016_guide_3_1_contents:\n        '라인 레인저스 전사들을 각자의 능력을 가지고 있어.\\n나 [문] 은 <발차기하기> 로 바로 앞에 있는 [돌]을 부술 수 있어.\\n[돌을] 부수고 나면 막힌 길을 지나갈 수 있겠지?\\n화면에 있는 [돌]을 모두 제거해야만 다음 단계로 넘어갈 수 있어.\\n그렇지만 명심해! 아무 것도 없는 곳에 능력을 낭비해서는 안 돼!',\n    codingparty2016_guide_5_1_title: \"'~번 반복하기' 블록 사용하기\",\n    codingparty2016_guide_5_1_contents:\n        '똑같은 일을 반복해서 명령하는 건 매우 귀찮은 일이야.\\n이럴 땐 명령을 사용하면 훨씬 쉽게 명령을 내릴 수 있어.       \\n< [ ? ] 번 반복하기> 블록 안에 반복되는 명령 블록을 넣고  \\n[ ? ] 부분에 횟수를 입력하면 입력한 횟수만큼 같은 명령을 반복하게 돼.',\n    codingparty2016_guide_5_2_title: \"'~번 반복하기' 블록 사용하기\",\n    codingparty2016_guide_5_2_contents:\n        \"'< [ ? ] 번 반복하기>  블록 안에는 여러 개의 명령어를 넣을 수도 있으니 잘 활용해봐! \\n도착지에 도착했더라도 반복하기 블록 안에 있는 블록이 모두 실행돼.\\n 즉, 위 상황에서 목적지에 도착한 후에도 왼쪽으로 돈 다음에야 끝나는 거야!\",\n    codingparty2016_guide_7_1_title: '(코니) 능력 사용하기',\n    codingparty2016_guide_7_1_contents:\n        '나 ‘코니’는 <꽃 던지기>로 먼 거리에서도 앞에 있는 [거미집]을 없앨 수 있어.\\n[거미집]을 없애고 나면 막힌 길을 지나갈 수 있겠지?\\n화면에 있는 [거미집]을 모두 제거해야만 다음 단계로 넘어갈 수 있어.\\n그렇지만 명심해! 아무것도 없는 곳에 능력을 낭비해서는 안 돼!',\n    codingparty2016_guide_9_1_title: '조건 반복 블록 사용하기',\n    codingparty2016_guide_9_1_contents:\n        '반복하는 횟수를 세지 않아도, 어떤 조건을 만족할 때까지 행동을 반복할 수 있어.\\n< [목적지]에 도착할 때까지 반복하기 > 블록 안에 반복되는 명령 블록을 넣으면 [목적지]에 도착할 때까지 명령을 반복해.',\n    codingparty2016_guide_9_2_title: '조건 반복 블록 사용하기',\n    codingparty2016_guide_9_2_contents:\n        '<[목적지]에 도착할 때까지 반복하기> 블록 안에는 여러 개의 명령어를 넣을 수도 있으니 잘 활용해봐!\\n 도착지에 도착했더라도 반복하기 블록 안에 있는 블록이 모두 실행 돼. 즉, 위 상황에서 목적지에 도착한 후에도 왼쪽으로 돈 다음에야 끝나는 거야!',\n    find_interesting_lesson: \"'우리 반 강의'에서 다양한 강의를 만나보세요!\",\n    find_interesting_course: \"'우리 반 강의 모음'에서 다양한 강의를 만나보세요!\",\n    select_share_settings: '공유 공간을 선택해주세요.',\n    faq_banner_title: '자주하는 질문 안내',\n    check_out_faq: '궁금한 점을 확인하세요.',\n    faq_banner_content:\n        '엔트리에 대해 궁금하세요?<br />자주하는 질문을 통해 답변을 드리고 있습니다.<br />지금 바로 확인하세요!',\n    faq_banner_button: '자주하는 질문<br />바로가기',\n    major_updates: '주요 업데이트 안내',\n    check_new_update: '엔트리의 변화를 확인하세요.',\n    major_updates_notification: '엔트리의 주요 변경사항을 공지를 통해 안내해 드리고 있습니다.',\n    find_out_now: '지금 바로 확인하세요!',\n    offline_hw_program: '오프라인 & 하드웨어 연결 프로그램',\n    read_more: '자세히 보기',\n    sample_project: '예시 작품',\n    not_supported_function: '이 기기에서는 지원하지 않는 기능입니다.',\n    offline_download_confirm:\n        '엔트리 오프라인 버전은 PC에서만 이용가능합니다. 다운로드 하시겠습니까?',\n    hardware_download_confirm: '엔트리 하드웨어는 PC에서만 이용가능합니다. 다운로드 하시겠습니까?',\n    copy_text: '텍스트를 복사하세요.',\n    select_openArea_space: '작품 공유 공간을 선택해 주세요',\n    mission_guide: '미션 해결하기 안내',\n    of: ' 의',\n    no_results_found: '검색 결과가 없습니다.',\n    upload_pdf: 'PDF 자료 업로드',\n    select_basic_project: '작품 선택하기',\n    try_it_out: '만들어 보기',\n    go_boardgame: '엔트리봇 보드게임 바로가기',\n    go_cardgame: '엔트리봇 카드게임 바로가기',\n    go_solve: '미션으로 학습하기',\n    go_ws: '엔트리 만들기 바로가기',\n    go_arts: '엔트리 공유하기 바로가기',\n    group_delete_alert:\n        '학급을 삭제하면, 해당 학급에서 발급한 학생임시계정을 포함하여 관련한 모든 자료가 삭제됩니다.\\n정말 삭제하시겠습니까?',\n    view_arts_list: '다른 작품 보기',\n    hw_submit_confirm_alert: '과제가 제출 되었습니다.',\n    hw_submit_alert: '과제를 제출 하시겠습니까? ',\n    hw_submit_alert2: '과제를 제출하시겠습니까? 제출 시 학습 완료한 학습 단계까지만 제출이 됩니다.',\n    hw_submit_cannot: '제출 할 수 없는 과제입니다.',\n    see_other_missions: '다른 미션 보기',\n    project: ' 작품',\n    marked: ' 관심',\n    group: '학급',\n    lecture: '강의',\n    Lecture: '강의',\n    curriculum: '강의 모음',\n    Curriculum: '강의 모음',\n    studying: '학습 중인',\n    open_only_shared_lecture:\n        '<b>오픈 강의</b> 페이지에 <b><공개></b> 한 강의만 불러올 수 있습니다. 불러오고자 하는 <b>강의</b>의 <b>공개여부</b>를 확인해 주세요.',\n    already_exist_group: '이미 존재하는 학급 입니다.',\n    cannot_invite_you: '자기 자신을 초대할 수 없습니다.',\n    apply_original_image: '원본 이미지 그대로 적용하기',\n    draw_new_ques: '새로 그리기 페이지로\\n이동하시겠습니까?',\n    draw_new_ques_1: '그림을 그려 오브젝트로 저장할 수 있습니다.',\n    draw_new_ques_2: '그리기 화면으로 이동하시겠습니까?',\n    draw_new_go: '이동하기',\n    draw_new_stay: '이동하지 않기',\n    file_upload_warn_title_image:\n        '아래와 같은 그림은 이용약관 및 관련 법률에 의해 제재를 받으실 수 있습니다.',\n    file_upload_warn_desc_image:\n        '폭력적이고 잔인한 그림<br>선정적인 신체노출 그림<br>불쾌감을 주거나 혐오감을 일으키는 그림<br>무단 사용이 금지된 저작권의 그림',\n    file_upload_warn_title_sound:\n        '아래와 같은 소리는 이용약관 및 관련 법률에 의해 제재를 받을 수 있습니다.',\n    file_upload_warn_desc_sound:\n        '폭력적이고 잔인한 소리<br>선정적인 내용의 소리<br>불쾌감을 주거나 혐오감을 일으키는 소리<br>무단 사용이 금지된 저작권의 소리',\n    file_upload_warn_title_table:\n        '아래와 같은 데이터는 이용약관 및 관련 법률에 의해 제재를 받으실 수 있습니다.',\n    file_upload_warn_desc_table:\n        '폭력적이고 잔인한 내용의 데이터<br>선정적인 내용의 데이터<br>불쾌감을 주거나 혐오단어가 포함된 데이터<br>무단 사용이 금지된 저작권의 데이터',\n    file_upload_warn_link: '저작권에 대해 알아보기',\n    file_upload_desc_1: '이런 그림은 \\n 안돼요!',\n    file_upload_desc_2: '폭력적이고 잔인한 그림',\n    file_upload_desc_3: '선정적인 신체노출 그림',\n    file_upload_desc_4: '불쾌감을 주거나 혐오감을 일으키는 그림',\n    file_upload_desc_5:\n        '* 위와 같은 내용은 이용약관 및 관련 법률에 의해 제재를 받으실 수 있습니다.',\n    picture_upload_warn_old: '10MB 이하의 jpg, png, bmp 형식의 파일을 추가할 수 있습니다.',\n    sprite_upload_warn_old:\n        '10MB 이하의 jpg, png, bmp 이미지 또는 eo 형식의 오브젝트를 추가할 수 있습니다.',\n    picture_upload_warn_1:\n        '10MB 이하의 jpg, png, bmp, svg 형식의 파일을 추가할 수 있습니다.\\njpg, png, bmp 형식은 비트맵 모드, svg 형식은 벡터 모드로 편집됩니다.',\n    table_upload_warn_1:\n        '10MB 이하의 csv, xls(x) 형식의 파일을 추가할 수 있습니다. xls(x) 형식의 경우, 함수 문장이 그대로 출력됩니다.',\n    sprite_upload_warn:\n        '10MB 이하의 jpg, png, bmp, svg 이미지 또는 eo 형식의 오브젝트를 추가할 수 있습니다.',\n    sound_upload_warn_1: '10MB 이하의 mp3 형식의 파일을 추가할 수 있습니다.',\n    sound_edit_warn: '기다려 주세요!<br>새로운 소리 편집 기능을 연구 중입니다.',\n    file_upload_loading: '로딩중',\n    lesson_by_teacher: '선생님들이 직접 만드는 강의입니다.',\n    delete_group_art: '학급 공유하기 목록에서 삭제 하시겠습니까?',\n    elementary_short: '초등',\n    middle_short: '중등',\n    grade_34: '3-4학년',\n    grade_56: '5-6학년',\n    grade_78: '중등',\n    share_lesson: '강의 공유하기',\n    share_course: '강의 모음 공유하기',\n    from_list_ko: '을(를)',\n    comming_soon: '준비중입니다.',\n    no_class_alert:\n        \"선택된 학급이 없습니다. 학급이 없는경우 '나의 학급' 메뉴에서 학급을 만들어 주세요.\",\n    students_cnt: '명',\n    defult_class_alert_1: '',\n    defult_class_alert_2: '을(를) \\n 기본학급으로 설정하시겠습니까?',\n    default_class: '기본학급입니다.',\n    enter_hw_name: '과제의 제목을 입력해 주세요.',\n    hw_limit_20: '과제는 20개 까지만 만들수 있습니다.',\n    stu_example: '예)\\n 홍길동\\n 홍길동\\n 홍길동',\n    hw_description_limit_200: '생성 과제에 대한 안내 사항을 입력해 주세요. (200자 이내)',\n    hw_title_limit_50: '과제명을 입력해 주세요. (50자 이내)',\n    create_project_class_1: \"'만들기 > 작품 만들기' 에서\",\n    create_project_class_2: '학급에 공유하고 싶은 작품을 만들어 주세요.',\n    create_lesson_assignment_1: \"'만들기> 오픈 강의 만들기'에서 \",\n    create_lesson_assignment_2: '우리 반 과제에 추가하고 싶은 강의를 만들어 주세요.',\n    i_make_lesson: '내가 만드는 강의',\n    lesson_to_class_1: \"'학습하기>오픈 강의'에서 우리반\",\n    lesson_to_class_2: '과제에 추가하고 싶은 강의를 관심강의로 등록해 주세요.',\n    studying_students: '학습자',\n    lessons_count: '강의수',\n    group_out: '나가기',\n    enter_group_code: '학급코드 입력하기',\n    no_group_invite: '학급 초대가 없습니다.',\n    done_create_group: '개설이 완료되었습니다.',\n    set_default_group: '기본학급 설정',\n    edit_group_info: '학급 정보 관리',\n    edit_done: '수정 완료되었습니다.',\n    alert_group_out: '학급을 정말 나가시겠습니까?',\n    lesson_share_cancel: '강의 공유 취소',\n    project_share_cancel: '작품 공유 취소',\n    lesson_share_cancel_alert: '작품을 비공개로 하시겠습니까?',\n    course_share_cancel: '강의 모음 공유 취소',\n    select_lesson_share: '강의 공유 공간 선택',\n    select_project_share: '작품 공유 선택',\n    select_lesson_share_policy_1: '강의를 공유할',\n    select_lesson_share_policyAdd: '공간을 선택해 주세요',\n    select_lesson_share_project_1: '작품을 공유할 공간과',\n    select_lesson_share_policy_2: '저작권 정책을 확인해 주세요.',\n    select_lesson_share_area: '강의 공유 공간을 선택해 주세요',\n    select_project_share_area: '작품 공유 공간을 선택해 주세요',\n    lesson_share_policy: '강의 공유에 따른 엔트리 저작권 정책 동의',\n    project_share_policy: '작품 공유에 따른 엔트리 저작권 정책 동의',\n    alert_agree_share: '공개하려면 엔트리 저작물 정책에 동의하여야 합니다.',\n    alert_agree_all: '모든 항목에 동의해 주세요.',\n    select_course_share: '강의 모음 공유 공간 선택',\n    select_course_share_policy_1: '강의 모음을 공유할',\n    select_course_share_policy_2: '저작권 정책을 확인해 주세요.',\n    select_course_share_area: '강의 모음 공유 공간을 선택해 주세요',\n    course_share_policy: '강의 모음 공유에 따른 엔트리 저작권 정책 동의',\n    issued: '발급',\n    code_expired: \"코드가 만료되었습니다. '코드재발급' 버튼를 누르세요.\",\n    accept_class_invite: '학급초대 수락하기',\n    welcome_class: '학급에 오신것을 환영합니다.',\n    enter_info: '자신의 정보를 입력해주세요.',\n    done_group_signup: '학급 가입이 완료되었습니다.',\n    enter_group_code_stu: '선생님께 받은 코드를 입력해주세요.',\n    text_limit_50: '50글자 이하로 작성해 주세요.',\n    enter_class_name: '학급 이름을 입력해 주세요.',\n    enter_grade: '학년을 입력해 주세요.',\n    enter_class_info: '학급소개를 입력해 주세요.',\n    student_dup: '은(는) 이미 학급에 존재합니다.',\n    select_stu_print: '출력할 학생을 선택하세요.',\n    class_id_not_exist: '학급 ID가 존재하지 않습니다.',\n    error_try_again: '오류 발생. 다시 한 번 시도해 주세요.',\n    error_forbidden: '권한이 없습니다.',\n    code_not_available: '유효하지 않은 코드입니다.',\n    gnb_create_lessons: '오픈 강의 만들기',\n    study_lessons: '강의 학습하기',\n    lecture_help_1:\n        '학습을 시작할 때, 사용할 작품을 선택해 주세요. 선택한 작품으로 학습자가 학습을 시작하게 됩니다.',\n    lecture_help_2: '이도움말을 다시 보시려면 위 버튼을 클릭해 주세요.',\n    lecture_help_3: '오브젝트 추가하기가 없으면새로운 오브젝트를 추가하거나 삭제 할 수 없습니다.',\n    lecture_help_4: '학습도중에 PDF자료보기를 통해 학습에 도움을 받을 수 있습니다.',\n    lecture_help_5: '학습에 필요한 블록들만 선택해주세요. 선택하지 않은 블록은 숨겨집니다.',\n    lecture_help_6: '블록코딩과 엔트리파이선 중에 선택하여 학습환경을 구성할 수 있습니다.',\n    lecture_finish_popup_title: '학습 다시하기',\n    lecture_finish_popup_content_1: '실습완료한 단계를<br>처음부터 다시 실습하시겠습니까?',\n    lecture_finish_popup_content_2: '* 다시 실습해도 실습 완료 상태는 유지됩니다.',\n    lecture_start_title: '학습 시작',\n    lecture_goal_title: '학습 목표',\n    lecture_goal_content: '무엇을 배울지 알아볼까요?',\n    lecture_prepare_title: '학습 준비',\n    lecture_summary_title: '학습 정리',\n    lecture_summary_content: '배운 내용을 정리해 봅시다.',\n    lecture_quiz_title: '확인 문제',\n    lecture_quiz_content: '확인 문제를 통해 배운 내용을 점검해 봅시다.',\n    lecture_quiz_check_answer: '정답확인',\n    default_hint_title: '어떻게 만들까?',\n    only_pdf: '.pdf형식의 파일만 입력 가능합니다.',\n    enter_project_video: '적어도 하나의 작품이나 영상을 입력하세요.',\n    enter_title: '제목을 입력하세요.',\n    enter_recommanded_grade: '추천 학년을 입력하세요.',\n    enter_level_diff: '난이도를 입력하세요.',\n    enter_time_spent: '소요시간을 입력하세요.',\n    enter_shared_area: '적어도 하나의 공유 공간을 선택하세요.',\n    enter_goals: '학습목표를 입력하세요.',\n    enter_lecture_description: '강의 설명을 입력하세요.',\n    enter_curriculum_description: '강의 모음 설명을 입력하세요.',\n    first_page: '처음 입니다.',\n    last_page: '마지막 입니다.',\n    alert_duplicate_lecture: '이미 등록된 강의는 다시 등록할 수 없습니다.',\n    enter_lesson_alert: '하나 이상의 강의를 등록해주세요.',\n    open_edit_lessons: '편집할 강의를 불러오세요.',\n    saved_alert: '이(가) 저장되었습니다.',\n    select_lesson_type: '어떤 학습과정을 만들지 선택해 주세요 ',\n    create_lesson: '강의 만들기',\n    create_lesson_desc_1: '원하는 학습 목표에 맞춰',\n    create_lesson_desc_2: '단일 강의를 만들어',\n    create_lesson_desc_3: '학습에 활용합니다.',\n    create_courseware: '강의 모음 만들기',\n    create_courseware_desc_1: '학습 과정에 맞춰 여러개의 강의를',\n    create_courseware_desc_2: '하나의 코스로 만들어',\n    create_courseware_desc_3: '학습에 활용합니다.',\n    create_open_lesson: '오픈 강의 만들기 ',\n    enter_lesson_info: '강의 정보 입력 ',\n    select_lesson_feature: '학습 기능 선택 ',\n    check_info_entered: '입력 정보 확인 ',\n    enter_lefo_lesson_long: '강의를 구성하는 정보를 입력해 주세요.',\n    lesson_info_desc:\n        '학습자가 학습하기 화면에서 사용할 기능과 작품을 선택함으로써, 학습 목표와 내용에 최적화된 학습환경을 구성할 수 있습니다.',\n    provide_only_used: '완성된 작품에서 사용된 블록만 불러오기',\n    see_help: '도움말 보기',\n    select_done_project_1: '학습자가 목표로 설정할',\n    select_done_project_2: '완성 작품',\n    select_done_project_3: '을 선택해 주세요.',\n    select_project: '나의 작품 또는 관심 작품을 불러옵니다. ',\n    youtube_desc: '유튜브 공유 링크를 통해 원하는 영상을 넣을 수 있습니다.',\n    lesson_video: '강의 영상',\n    lesson_title: '강의 제목',\n    recommended_grade: '추천학년',\n    selection_ko: '선택',\n    selection_en: '',\n    level_of_diff: '난이도',\n    select_level_of_diff: '난이도 선택',\n    enter_lesson_title: '강의 제목을 입력해 주세요(30자 이내)',\n    select_time_spent: '소요시간 선택 ',\n    time_spent: '소요시간',\n    lesson_overview: '강의설명',\n    upload_materials: '학습 자료 업로드',\n    open: '불러오기',\n    cancel: '취소하기',\n    upload_lesson_video: '강의 영상 업로드',\n    youtube_upload_desc: '유튜브 공유링크를 통해 보조영상을 삽입할 수 있습니다. ',\n    cancel_select: '선택 취소하기',\n    select_again: '다시 선택하기',\n    goal_project: '완성작품',\n    upload_study_data:\n        '학습하기 화면에서 볼 수 있는 학습자료를 업로드해주세요. 학습자가 업로드된 학습자료의 내용을 확인하며 학습할 수 있습니다. ',\n    upload_limit_20mb: '20MB 이하의 파일을 올려주세요.',\n    expect_time: '예상 소요 시간',\n    course_videos: '보조 영상',\n    enter_courseware_info: '강의 모음 정보 입력 ',\n    enter_course_info: '강의 모음을 소개하는 정보를 입력해 주세요 ',\n    select_lessons_for_course: '강의 모음을 구성하는 강의를 선택해 주세요.',\n    course_build_desc_1: '강의는',\n    course_build_desc_2: '최대30개',\n    course_build_desc_3: '등록할 수 있습니다.',\n    lseeon_list: '강의 목록 보기',\n    open_lessons: '강의 불러오기',\n    course_title: '강의 모음 제목',\n    title_limit_30: '강의 모음 제목을 입력해 주세요(30자 이내) ',\n    course_overview: '강의 모음 설명',\n    charactert_limit_200: '200자 이내로 작성할 수 있습니다.',\n    edit_lesson: '강의 편집',\n    courseware_by_teacher: '선생님들이 직접 만드는 강의 모음입니다.',\n    select_lessons: '구성 강의 선택',\n    check_course_info: '강의 모음을 구성하는 정보가 올바른지 확인해 주세요.',\n    select_share_area: '공유 공간 선택',\n    upload_sub_project: '목표 작품 업로드',\n    file_download: '첨부파일 다운로드',\n    file_remove: '첨부파일 삭제',\n    check_lesson_info: '강의를 구성하는 정보가 올바른지 확인해 주세요.',\n    share_area: '공유 공간',\n    enter_sub_project: '엔트리 보조 프로젝트를 등록해 주세요.',\n    lms_hw_title: '과제 제목',\n    lms_hw_ready: '준비',\n    lms_hw_progress: '진행중',\n    lms_hw_complete: '완료',\n    lms_hw_not_submit: '미제출',\n    lms_hw_closed: '제출마감',\n    submission_condition: '진행중인 과제만 제출이 가능합니다.',\n    submit_students_only: '학생만 과제를 제출할 수 있습니다.',\n    want_submit_hw: '과제를 제출하시겠습니까?',\n    enter_correct_id: '올바른 아이디를 입력해 주세요.',\n    id_not_exist: '아이디가 존재하지 않습니다. ',\n    agree_class_policy: '학급 서비스 이용약관에 동의해 주세요.',\n    delete_class: '학급 삭제',\n    type_stu_name: '학생 이름을 입력해주세요. ',\n    invite_from_1: '에서',\n    invite_from_2: '님을 초대하였습니다. ',\n    lms_pw_alert_1: '학급에 소속되면, 선생님 권한으로',\n    lms_pw_alert_2: '비밀번호 재발급이 가능합니다.',\n    lms_pw_alert_3: '선생님의 초대가 맞는지 한번 더 확인해주세요.',\n    invitation_accepted: '초대 수락이 완료되었습니다!',\n    cannot_issue_pw: '초대를 수락하지 않았으므로 비밀번호를 발급할 수 없습니다.',\n    start_me_1: '<월간 엔트리>와 함께',\n    start_me_2: 'SW교육을 시작해보세요!',\n    monthly_desc_1: '<월간 엔트리>는 소프트웨어 교육에 익숙하지 않은 선생님들도 쉽고 재미있게',\n    monthly_desc_2: '소프트웨어 교육을 하실 수 있도록 만들어진 SW교육 잡지입니다.',\n    monthly_desc_3: '매월 재미있는 학습만화와 함께 하는 SW 교육 컨텐츠를 만나보세요!',\n    monthly_desc_4: '* 월간엔트리는 2015년 11월 ~ 2016년 5월까지 발행 후 중단되었습니다.',\n    monthly_desc_5: '엔트리의 교육자료는 교육자료 페이지에서 만나보세요.',\n    monthly_entry: '월간 엔트리',\n    me_desc_1: '매월 발간되는 무료 소프트웨어 교육잡지',\n    me_desc_2: '월간엔트리를 만나보세요!',\n    solve_desc_1: '게임을 하듯 미션을 해결하며',\n    solve_desc_2: '소프트웨어의 기본 원리를 배워보세요!',\n    playSw_desc_1: 'EBS 방송영상, 특별영상을 통해',\n    playSw_desc_2: '소프트웨어를 배워보세요!',\n    recommended_lessons: '추천 강의 모음',\n    recommended_lessons_1:\n        '따라하고, 도전하고, 퀴즈도 풀며 재미있게 엔트리 프로그래밍을 배워보세요!',\n    recommended_lessons_2: '추천 강의 모음을 만나보세요!',\n    offline_top_desc_1: '오프라인 버전의 저장 기능이 향상되고 보안이 강화되었습니다.',\n    offline_top_desc_2: '지금 바로 다운받으세요',\n    offline_main_desc: '엔트리 오프라인 에디터 업데이트!!',\n    art_description:\n        '엔트리로 만든 작품을 공유하는 공간입니다. 작품을 만들고 공유에 참여해 보세요.',\n    art_description_1: '엔트리로 총 ',\n    art_description_2: '개의 작품이 만들어졌습니다. 작품을 만들고 공유해 보세요.',\n    study_index:\n        '엔트리에서 제공하는 주제별, 학년별 학습과정을 통해 차근차근 소프트웨어를 배워보세요!',\n    study_for_beginner: '처음 시작하는 사람들을 위한 엔트리 첫걸음',\n    entrybot_desc_3: '안내에 따라 블록 명령어를 조립하여',\n    entrybot_desc_4: '엔트리봇을 학교에 데려다 주세요.',\n    move_entrybot: '엔트리봇 움직이기',\n    can_change_entrybot_1: '블록 명령어로 엔트리봇의 색을 바꾸거나',\n    can_change_entrybot_2: '말을 하게 할 수도 있어요.',\n    learning_process_by_topics: '주제별 학습과정',\n    show_detail: '자세히 보기',\n    solve_mission: '미션 해결하기',\n    solve_mission_desc_1: '게임을 하듯 미션을 해결하며 프로그래밍의 원리를 익혀보세요!',\n    solve_mission_desc_2:\n        '미로 속의 엔트리봇을 목적지까지 움직이며 순차, 반복, 선택, 비교연산 등의 개념을 자연스럽게 익힐 수 있어요.',\n    learning_process_by_grades: '학년별 학습과정',\n    learning_process_by_grades_sub1:\n        '4가지 유형으로 쉽고 재미있게 배우는 프로그래밍의 원리! 지금 시작해보세요!',\n    e3_to_e4: '초등 3-4 학년',\n    e5_to_e6: '초등 5-6 학년',\n    m1_to_m3: '중등 이상',\n    make_using_entry: '엔트리로 만들기',\n    make_using_entry_desc_1: '블록을 쌓아 여러 가지 소프트웨어를 만들어보세요!',\n    make_using_entry_desc_2:\n        '제공되는 교재를 다운받아 차근차근 따라하다보면 애니메이션, 미디어아트, 게임 등 다양한 작품을 만들 수 있어요.',\n    make_through_ebs_1: 'EBS 방송영상으로 소프트웨어를 배워보세요.',\n    make_through_ebs_2:\n        '방송영상은 물론, 차근차근 따라 할 수 있는 특별영상과 함께 누구나 쉽게 다양한 소프트웨어를 만들 수 있어요.',\n    support_block_js: '블록 코딩과 자바스크립트 언어를 모두 지원합니다.',\n    study_ebs_title_1: '순서대로! 차례대로!',\n    study_ebs_desc_1: '[실습] 엔트리봇의 심부름',\n    study_ebs_title_2: '쉽고 간단하게!',\n    study_ebs_desc_2: '[실습] 꽃송이 만들기',\n    study_ebs_title_3: '언제 시작할까?',\n    study_ebs_desc_3: '[실습] 동물가족 소개',\n    study_ebs_title_4: '다른 선택, 다른 결과!',\n    study_ebs_desc_4: '[실습] 텔레파시 게임',\n    study_ebs_title_5: '정보를 담는 그릇',\n    study_ebs_desc_5: '[실습] 덧셈 로봇 만들기',\n    study_ebs_title_6: '요모조모 따져 봐!',\n    study_ebs_desc_6: '[실습] 복불복 룰렛',\n    study_ebs_title_7: '번호로 부르면 편해요!',\n    study_ebs_desc_7: '[실습] 나만의 버킷리스트',\n    study_ebs_title_8: '무작위 프로그램을 만들어라!',\n    study_ebs_desc_8: '[실습] 무작위 캐릭터 만들기',\n    study_ebs_title_9: '어떻게 찾을까?',\n    study_ebs_desc_9: '[실습] 도서관 책 검색',\n    study_ebs_title_10: '줄을 서시오!',\n    study_ebs_desc_10: '[실습] 키 정렬 프로그램',\n    event: '이벤트',\n    divide: '분기',\n    condition: '조건',\n    random_number: '무작위수',\n    search: '탐색',\n    sorting: '정렬',\n    parallel: '병렬',\n    signal: '신호',\n    input_output: '입출력',\n    sequential: '순차',\n    repeat: '반복',\n    choice: '선택',\n    repeat_advanced: '반복(횟수+조건)',\n    function: '함수',\n    compare_operation: '비교연산',\n    arithmetic: '산술연산',\n    entry_recommended_mission: '엔트리 추천 미션',\n    more_mission: '더 많은 미션 보러가기',\n    line_rangers_title: '라인레인저스와\\n샐리 구하기',\n    line_rangers_content: '메피스토 기지에 갇힌\\n샐리를 구해주세요!',\n    pinkbean_title_string_basic: '메이플스토리 초급 헤네시스',\n    pinkbean_title_string_intermediate: '메이플스토리 중급 엘리니아',\n    pinkbean_title_string_advanced: '메이플스토리 고급 엘나스',\n    pinkbean_title: '핑크빈과 함께 신나는\\n메이플 월드로!',\n    pinkbean_content: '핑크빈이 메이플 월드 모험을\\n무사히 마칠 수 있도록 도와주세요.',\n    entrybot_school: '엔트리봇 학교 가는 길',\n    entrybot_school_desc_1: '엔트리봇이 책가방을 챙겨 학교에',\n    entrybot_school_desc_2: '도착할 수 있도록 도와주세요!',\n    robot_factory: '로봇 공장',\n    robot_factory_desc_1: '로봇공장에 갇힌 엔트리봇!',\n    robot_factory_desc_2: '탈출하기 위해 부품을 모두 모아야해요.',\n    electric_car: '전기 자동차',\n    electric_car_desc_1: '엔트리봇 자동차가 계속 앞으로 나아갈 수',\n    electric_car_desc_2: '있도록 연료를 충전해 주세요.',\n    forest_adventure: '숲속 탐험',\n    forest_adventure_desc_1: '엔트리봇 친구가 숲속에 갇혀있네요!',\n    forest_adventure_desc_2: '친구를 도와주세요.',\n    town_adventure: '마을 탐험',\n    town_adventure_desc_1: '배고픈 엔트리봇을 위해 마을에 있는',\n    town_adventure_desc_2: '연료를 찾아주세요.',\n    space_trip: '우주 여행',\n    space_trip_desc_1: '우주탐사를 마친 엔트리봇!',\n    space_trip_desc_2: '지구로 돌아갈 수 있도록 도와주세요.',\n    learn_programming_mission: '미션을 해결하며 배우는 프로그래밍',\n    make_open_lecture: '오픈 강의 만들기',\n    group_created: '만든 학급',\n    group_signup: '가입한 학급',\n    delete_from_list: '을(를) 목록에서 삭제하시겠습니까?',\n    delete_from_list_en: '',\n    lecture_collection: '강의 모음',\n    edit_mypage_profile: '자기소개 정보 관리',\n    main_image: '메인 이미지',\n    edit_profile_success: '반영되었습니다.',\n    no_project_1: '내가 만든 작품이 없습니다.',\n    no_project_2: '지금 작품 만들기를 시작해보세요!',\n    empty_project_1: '아직 만들어진 작품이 없습니다.',\n    no_marked_project_1: '관심 작품이 없습니다.',\n    no_marked_group_project_1: '학급 관심 작품이 없습니다.',\n    no_marked_project_2: \"'작품 공유하기'에서 다양한 작품을 만나보세요!\",\n    no_markedGroup_project_2: \"'학급 공유하기'에서 다양한 작품을 만나보세요!\",\n    view_project_all: '작품 구경하기',\n    no_lecture_1: '내가 만든 강의가 없습니다.',\n    empty_lecture_1: '아직 만들어진 강의가 없습니다.',\n    no_lecture_2: \"'오픈 강의 만들기'에서 강의를 만들어보세요!\",\n    no_marked_lecture_1: '관심 강의가 없습니다.',\n    no_marked_group_lecture_1: '학급 관심 강의가 없습니다.',\n    no_marked_lecture_2: \"'오픈 강의'에서 다양한 강의를 만나보세요!\",\n    view_lecture: '강의 살펴보기',\n    no_studying_lecture_1: '학습 중인 강의가 없습니다.',\n    no_studying_lecture_2: \"'오픈 강의'에서 학습을 시작해보세요!\",\n    no_lecture_collect_1: '내가 만든 강의 모음이 없습니다.',\n    empty_lecture_collect_1: '아직 만들어진 강의 모음이 없습니다.',\n    no_lecture_collect_2: \"'오픈 강의 모음 만들기'에서 강의 모음을 만들어보세요!\",\n    make_lecture_collection: '강의 모음 만들기',\n    no_marked_lecture_collect_1: '관심 강의 모음이 없습니다.',\n    no_marked_lecture_group_collect_1: '학급 관심 강의 모음이 없습니다.',\n    no_marked_lecture_collect_2: \"'오픈 강의'에서 다양한 강의를 만나보세요!\",\n    view_lecture_collection: '강의 모음 살펴보기',\n    no_studying_lecture_collect_1: '학습 중인 강의 모음이 없습니다.',\n    no_studying_lecture_collect_2: \"'오픈 강의'에서 학습을 시작해보세요!\",\n    my_lecture: '나의 강의',\n    markedGroup: '학급 관심',\n    markedGroup_lecture: '학급 관심 강의',\n    markedGroup_curriculum: '학급 관심 강의모음',\n    marked_lecture: '관심 강의',\n    marked_lecture_collection: '나의 관심 강의 모음',\n    marked_marked_curriculum: '관심 강의 모음',\n    studying_lecture: '학습 중인 강의',\n    completed_lecture: '학습 완료 강의',\n    my_lecture_collection: '나의 강의 모음',\n    my: '나의',\n    studying_lecture_collection: '학습 중인 강의 모음',\n    completed_lecture_collection: '학습 완료한 강의 모음',\n    my_curriculum: '나의 강의 모음',\n    studying_curriculum: '학습 중인 강의 모음',\n    completed_curriculum: '학습 완료한 강의 모음',\n    materialCC:\n        '엔트리에서 제공하는 모든 교육 자료는 CC-BY 2.0 라이선스에 따라 자유롭게 이용할 수 있습니다.',\n    materialccby_new:\n        '엔트리의 교육자료는 CC-BY 2.0 라이선스에 따라 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    entry_copyright_info: '엔트리 저작권 가이드 보기',\n    pdf: 'PDF',\n    helper: '도움말',\n    youtube: '영상',\n    tvcast: '영상',\n    goal: '목표',\n    basicproject: '시작단계',\n    hw: '하드웨어',\n    object: '오브젝트',\n    console: '콘솔',\n    download_info: '모든 교육자료는 각각의 제목을 클릭 하시면 다운받으실 수 있습니다.',\n    entry_materials_all: '엔트리 교육자료 모음',\n    entry_material: '엔트리 교육자료',\n    recommand_grade: '추천학년',\n    g3_4_grades: '3-4 학년',\n    g5_6_grades: '5-6 학년',\n    middle_grades: '중학생 이상',\n    entry_go_go: '엔트리 고고!',\n    entry_go_go_desc: '학년별, 난이도 별로 준비된 교재를 만나보세요.',\n    entry_go_go_desc2: '각 과정별로 교육과정, 학습지, 교사용 해설서 3종 세트가 제공됩니다.',\n    stage_beginner: '초급',\n    stage_middle: '중급',\n    stage_high: '고급',\n    middle_school_short: '중등',\n    learn_entry_programming: '따라하며 배우는 엔트리 프로그래밍',\n    entry_programming_desc: '차근차근 따라 하다 보면 어느새 나도 엔트리 고수!',\n    ebs: 'EBS',\n    ebs_material_desc: '방송 영상과 교사용 지도서를 활용하여 수업을 해보세요!',\n    season_1_material: '시즌1 교사용 지도서',\n    season_2_material: '시즌2 교사용 지도서',\n    season_1: '시즌1',\n    playsoftware_ebs: 'EBS 소프트웨어야 놀자!',\n    material_teacher_guide: '교사용 지도서',\n    season_2: '시즌2',\n    compute_think_textbook: '교과서로 배우는 컴퓨팅 사고력',\n    computational_sw:\n        '국어, 수학, 과학, 미술... 학교에서 배우는 다양한 교과와 연계하여 SW를 배워보세요!',\n    python_coding_text: '엔트리파이선',\n    python_coding_textbook: '텍스트 코딩 세계로 떠나는 여행! 엔트리파이선',\n    python_coding_desc: '엔트리파이선으로 텍스트 언어의 구조와 문법을 자연스럽게 배워보세요!',\n    entry_x_hardware_text: '엔트리 X 하드웨어 교육자료',\n    entry_x_hardware: '엔트리 X 하드웨어 교육자료 모음',\n    e_sensor: 'E 센서보드',\n    e_sensor_board: 'E 센서보드',\n    e_sensor_robot: 'E 센서로봇',\n    arduino: '아두이노',\n    arduinoext: '아두이노 Uno 확장모드',\n    arduinonano: '아두이노 Nano',\n    albert: '알버트',\n    orange_board: '오렌지보드',\n    arduino_board: '아두이노',\n    joystick: '조이스틱 센서 쉴드',\n    ardublock: '아두블럭',\n    mkboard: '디지털 몽키보드',\n    mechatro_nano: '메카트로 나노+',\n    mechatro_uno: '메카트로 우노+',\n    memaker: '미메이커',\n    edumaker: '에듀메이커 보드',\n    codingtoolbox: '코딩툴박스',\n    materials_etc_all: '기타 교육자료 모음',\n    materials_teaching: '교원 연수 자료',\n    materials_etc: '기타 참고 자료',\n    materials_etc_resource: '참고 자료',\n    materials_teaching_etc: '교원 연수 및 참고자료',\n    materials_teaching_1: 'SW교육의 필요성과 교육 방법론',\n    materials_teaching_2: '엔트리와 함께하는 언플러그드 활동',\n    materials_teaching_3: '게임하듯 알고리즘을 배우는 엔트리 미션 해결하기',\n    materials_teaching_4: '실생활 문제해결을 위한 엔트리 프로그래밍',\n    materials_teaching_5: '교과연계 SW교육1 (미술,수학,사회)',\n    materials_teaching_6: '교과연계 SW교육2 (국어,과학,음악)',\n    materials_teaching_7: '피지컬 컴퓨팅 실습1(E센서보드)',\n    materials_teaching_8: '피지컬 컴퓨팅 실습2(햄스터)',\n    materials_teaching_9: '수업에 필요한 학급/강의 기능 알아보기',\n    materials_etc_1: '엔트리 첫 사용자를 위한 스타트 가이드',\n    materials_etc_2: '수업에 바로 활용할 수 있는 다양한 콘텐츠 모음집',\n    materials_etc_3: '월간 엔트리',\n    materials_etc_4: '엔트리 설명서',\n    materials_etc_5: '엔트리 소개 자료',\n    materials_etc_6: '엔트리 블록 책받침',\n    materials_etc_7: '엔트리파이선 예제 및 안내',\n    jr_if_1: '만약',\n    jr_if_2: '앞에 있다면',\n    jr_fail_no_pencil: '이런 그곳에는 연필이 없어. 연필이 있는 곳에서 사용해보자~',\n    jr_fail_forgot_pencil: '앗! 책가방에 넣을 연필을 깜빡했어. 연필을 모아서 가자~',\n    jr_fail_much_blocks: '너무많은 블록을 사용했어, 다시 도전해볼래?',\n    cparty_jr_success_1: '좋아! 책가방을 챙겼어!',\n    go_right: '오른쪽',\n    go_down: '  아래쪽',\n    go_up: '  위쪽',\n    go_left: '  왼쪽',\n    go_forward: '앞으로 가기',\n    jr_turn_left: '왼쪽으로 돌기',\n    jr_turn_right: '오른쪽으로 돌기',\n    go_slow: '천천히 가기',\n    repeat_until_reach_1: '만날 때 까지 반복하기',\n    repeat_until_reach_2: '',\n    pick_up_pencil: '연필 줍기',\n    repeat_0: '',\n    repeat_1: '반복',\n    when_start_clicked: '시작 버튼을 눌렀을 때',\n    age_0: '작품체험',\n    create_character: '캐릭터 만들기',\n    age_7_9: '초등 저학년',\n    going_school: '엔트리 학교가기',\n    age_10_12_1: '초등 고학년1',\n    collect_parts: '로봇공장 부품모으기',\n    age_10_12_2: '초등 고학년2',\n    driving_elec_car: '전기자동차 운전하기',\n    age_13: '중등',\n    travel_space: '우주여행하기',\n    people: '사람',\n    all: '전체',\n    life: '일상생활',\n    nature: '자연',\n    animal_insect: '동물/곤충',\n    environment: '자연환경',\n    things: '사물',\n    vehicles: '이동수단',\n    others: '기타',\n    fantasy: '판타지',\n    instrument: '악기',\n    piano: '피아노',\n    marimba: '마림바',\n    drum: '드럼',\n    janggu: '장구',\n    sound_effect: '효과음',\n    others_instrument: '기타타악기',\n    aboutEntryDesc_1: '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있는 플랫폼입니다.',\n    aboutEntryDesc_2: '학생들이 소프트웨어를 쉽고 재미있게 학습하고,',\n    aboutEntryDesc_3: '선생님들은 효과적으로 학생들을 가르칠 수 있습니다.',\n    aboutEntryDesc_4: '엔트리는 공공재와 같이',\n    aboutEntryDesc_5: '비영리로 운영됩니다.',\n    viewProjectTerms: '이용정책 보기',\n    openSourceTitle: '오픈소스를 통한 생태계 조성',\n    openSourceDesc_1: '엔트리의 소스코드 뿐 아니라',\n    openSourceDesc_2: '모든 교육 자료는 CC라이센스를 ',\n    openSourceDesc_3: '적용하여 공개합니다.',\n    viewOpenSource: '오픈소스 보기',\n    eduPlatformTitle: '국내교육 현장에 맞는 교육 플랫폼',\n    eduPlatformDesc_1: '국내 교육 현장에 적합한 교육 도구가',\n    eduPlatformDesc_2: '될 수 있도록 학교 선생님들과 함께',\n    eduPlatformDesc_3: '개발하고 있습니다.',\n    madeWith: '자문단',\n    researchTitle: '다양한 연구를 통한 전문성 강화',\n    researchDesc_1: '대학/학회 등과 함께 다양한 연구를',\n    researchDesc_2: '진행하여 전문성을 강화해나가고',\n    researchDesc_3: '있습니다.',\n    viewResearch: '연구자료 보기',\n    atEntry: '엔트리에서는',\n    entryLearnDesc_1: '재미있게 배우는 학습공간',\n    entryLearnDesc_2: '<학습하기>에서는 엔트리를 학습할 수 있는 콘텐츠가 준비되어 있습니다.',\n    entryLearnDesc_3: '게임을 하듯이 주어진 미션을 프로그래밍으로 해결하고 영상을 시청하며 ',\n    entryLearnDesc_4: '소프트웨어 제작 원리를 학습할 수 있습니다.',\n    entryMakeDesc_1: '<만들기>에서는 미국 MIT에서 개발한 Scratch와 같은 블록형 프로그래밍 언어를',\n    entryMakeDesc_2:\n        '사용하여 프로그래밍을 처음 접하는 사람들도 쉽게 자신만의 창작물을 만들 수 있습니다.',\n    entryMakeDesc_3:\n        \"또한 블록 코딩과 텍스트 코딩의 중간다리 역할을 하는 '엔트리파이선' 모드에서는\",\n    entryMakeDesc_4: '텍스트 언어의 구조와 문법을 자연스럽게 익힐 수 있습니다.',\n    entryMakeDesc_5: '',\n    entryShareDesc_1:\n        '<공유하기>에서는 엔트리를 통해 제작한 작품을 다른 사람들과 공유할 수 있습니다.',\n    entryShareDesc_2:\n        '또한 공유된 작품이 어떻게 구성되었는지 살펴보고 발전시켜 자신만의 작품을 만들 수',\n    entryShareDesc_3:\n        '있습니다. 공동 창작도 가능하여 친구들과 협업해 더 멋진 작품을 만들어 볼 수 있습니다.',\n    entryGroup: '학급기능',\n    entryGroupTitle: '우리 반 학습 공간',\n    entryGroupDesc_1:\n        '<학급기능>은 선생님이 학급별로 학생들을 관리할 수 있는 기능입니다. 학급끼리 학습하고',\n    entryGroupDesc_2: '작품을 공유할 수 있으며 과제를 만들고 학생들의 결과물을 확인할 수 있습니다.',\n    entryGroupDesc_3: '또한 선생님은 강의 기능을 활용하여 학생들의 수준에 맞는 학습환경을',\n    entryGroupDesc_4: '맞춤형으로 제공함으로써 효율적이고 편리하게 수업을 진행할 수 있습니다.',\n    entryGroupDesc_5: '',\n    unpluggedToPhysical: '언플러그드 활동부터 피지컬 컴퓨팅까지',\n    algorithmActivity: '기초 알고리즘',\n    programmignLang: '교육용 프로그래밍 언어',\n    unpluggedDesc_1: '엔트리봇 보드게임과 카드게임을 통해 컴퓨터 없이도',\n    unpluggedDesc_2: '소프트웨어의 기본 개념과 원리(순차, 반복, 선택, 함수)를 익힐 수 있습니다.',\n    entryMaze: '엔트리봇 미로탈출',\n    entryAI: '엔트리봇 우주여행',\n    algorithmDesc_1: '게임을 하듯이 미션을 해결하고 인증서를 받아보세요.',\n    algorithmDesc_2: '소프트웨어의 기본적인 원리를 쉽고 재미있게 배울 수 있습니다.',\n    programmingLangDesc_1: '엔트리에서는 블록을 쌓듯이 프로그래밍을 하기 때문에 누구나 쉽게',\n    programmingLangDesc_2:\n        '자신만의 게임, 애니메이션, 미디어아트와 같은 멋진 작품을 만들고 공유할 수 있어 교육용으로 적합합니다.',\n    viewSupporHwVideo: '하드웨어 가이드 영상 보기',\n    viewSupporHw: '연결되는 하드웨어 보기',\n    supportHwDesc_1:\n        '엔트리와 피지컬 컴퓨팅 도구를 연결하면 현실세계와 상호작용하는 멋진 작품들을 만들어낼 수 있습니다.',\n    supportHwDesc_2: '국내, 외 다양한 하드웨어 연결을 지원하며, 계속적으로 추가될 예정입니다.',\n    entryEduSupport: '엔트리 교육 지원',\n    eduSupportDesc_1:\n        '엔트리에서는 소프트웨어 교육을 위한 다양한 교육 자료를 제작하여 무상으로 배포하고 있습니다.',\n    eduSupportDesc_2: '모든 자료는 교육자료 페이지에서 다운받으실 수 있습니다.',\n    materials_1_title: '수준별 교재',\n    materials_1_desc_1: '학년별 수준에 맞는 교재를 통해 차근차근',\n    materials_1_desc_2: '따라하며 쉽게 엔트리를 익혀보세요!',\n    materials_2_title: 'EBS 방송 연계 교안',\n    materials_2_desc_1: 'EBS 소프트웨어야 놀자 방송과 함께',\n    materials_2_desc_2: '교사용 수업 지도안을 제공합니다.',\n    materials_3_title: '초, 중등 교과 연계 수업자료',\n    materials_3_title_2: '',\n    materials_3_desc_1: '다양한 과목에서 만나는 실생활 문제를',\n    materials_3_desc_2: '컴퓨팅 사고력으로 해결해 보세요.',\n    moreMaterials: '더 많은 교육 자료 보러가기',\n    moreInfoAboutEntry_1: '더 많은 엔트리의 소식들을 확인하고 싶다면 아래의 링크들로 접속해보세요.',\n    moreInfoAboutEntry_2: '교육자료 외에도 다양한 SW 교육과 관련한 정보를 공유하고 있습니다.',\n    material_menu_type_robot: '로봇형',\n    material_menu_type_module: '모듈형',\n    material_menu_type_board: '보드형',\n    blog: '블로그',\n    post: '포스트',\n    tvCast: 'TV캐스트',\n    about_entry_pre: '엔트리',\n    about_youtube: '유튜브',\n    about_facebook: '페이스북',\n    albertSchool: '알버트 스쿨버전',\n    arduinoBoard: '아두이노 정품보드',\n    arduinoCompatible: '아두이노 호환보드',\n    bitBlock: '비트블록',\n    bitbrick: '비트브릭',\n    creamo: '크리모',\n    playcode: '플레이코드',\n    funboard: '펀보드',\n    truerobot: '뚜루뚜루',\n    bingle: '빙글',\n    bingles: '빙글S',\n    codeino: '코드이노',\n    epor: '에뽀',\n    petrone_v2: '페트론V2',\n    petrone_v2_drone: '드론',\n    petrone_v2_car: '자동차',\n    'e-sensor': 'E-센서보드',\n    'e-sensorUsb': 'E-센서보드(유선연결)',\n    'e-sensorBT': 'E-센서보드(무선연결)',\n    mechatronics_4d: '4D 메카트로닉스',\n    esensor_board: 'E - 센서보드',\n    esensor_robot: 'E - 센서로봇',\n    hamster: '햄스터',\n    hummingbird: '허밍버드 듀오',\n    roboid: '로보이드',\n    turtle: '거북이',\n    littlebits: '리틀비츠',\n    orangeBoard: '오렌지 보드',\n    robotis_carcont: '로보티즈 로봇자동차',\n    robotis_IoT: '로보티즈 IoT',\n    robotis_IoT_Wireless: '로보티즈 IoT(무선연결)',\n    dplay: '디플레이',\n    iboard: '아이보드',\n    nemoino: '네모이노',\n    xbot_epor_edge: '엑스봇(원터치 동글/USB)',\n    XbotBT: '엑스봇 에뽀/엣지 블투투스',\n    robotori: '로보토리',\n    rokoboard: '로코보드',\n    neobot: '네오봇',\n    neobot_sensor_theme: '네오봇 센서 테마',\n    mechatro: '메카트로',\n    about: '알아보기',\n    articles: '토론하기',\n    gallery: '구경하기',\n    learn: '학습하기',\n    login: '로그인',\n    logout: '로그아웃',\n    make: '만들기',\n    register: '가입하기',\n    Join: '회원가입',\n    Edit_info: '내 정보 수정',\n    Discuss: '글 나누기',\n    Explore: '구경하기',\n    Load: '불러오기',\n    My_lesson: '오픈 강의',\n    textbook_learning: '교과서 학습하기',\n    Resources: '교육 자료',\n    play_software: '소프트웨어야 놀자!',\n    problem_solve: '엔트리 학습하기',\n    learning_textbook: '교과서 학습하기',\n    context_textbook:\n        '초등 교과서 그대로 선생님은 학교 수업을 학생은 집에서 예습, 복습을 할 수 있어요.',\n    info_banner_textbook: '* 출판사는 가나다순 노출입니다.',\n    banner_textbook: '더욱 다양하고',\n    banner_textbook_2: '재미있는 학습을 하고 싶다면?',\n    banner_textbook_right_banner: '학생용 활동지와 교사용',\n    banner_textbook_right_banner2: '학습 도움 자료가 필요하신가요?',\n    banner_textbook_right_banner_btn: '교과서별 자료 받기',\n    Learn: '학습하기',\n    teaching_tools: '엔트리 교구',\n    about_entry: '엔트리 소개',\n    what_entry: '엔트리는?',\n    create: '만들기',\n    create_new: '새로 만들기',\n    start_programming: '소프트웨어 교육의 첫걸음',\n    Entry: '엔트리',\n    intro_learning: '누구나 쉽고 재밌게 소프트웨어를 배울 수 있어요. ',\n    intro_learning_anyone: '지금 바로 시작해보세요! ',\n    start_now: 'For Free, Forever.',\n    welcome_entry: '엔트리에 오신걸 환영합니다.',\n    student: '학생',\n    non_menber: '일반인',\n    teacher: '선생님',\n    terms_conditions: '이용약관',\n    personal_information: '개인정보 수집 및 이용에 대한 안내',\n    limitation_liability: '책임의 한계와 법적 고지',\n    entry_agree: '엔트리의 이용약관에 동의 합니다.',\n    info_agree: '개인정보 수집 및 이용에 동의합니다.',\n    next: '다음',\n    enter_individual_info: '개인정보 입력',\n    enter_id: '아이디 입력',\n    enter_password: '비밀번호 입력',\n    confirm_password: '비밀번호 확인',\n    enter_password_again: '비밀번호를 한번 더 입력하세요.',\n    validation_password: '5자 이상의 영문/숫자 등을 조합하세요.',\n    validation_id: '4~20자의 영문/숫자를 조합하세요',\n    prev: '이전',\n    born_year: '태어난 연도',\n    select_born: '태어난 연도를 선택 하세요',\n    year: '년',\n    gender: '성별',\n    choose_gender: '성별을 선택 하세요',\n    male: '남성',\n    female: '여성',\n    language: '언어',\n    best_language: '주 언어를 선택 하세요',\n    korean: '한국어',\n    english: '영어',\n    viet: '베트남',\n    japan: '일본어',\n    russia: '러시아어',\n    chinese_simplified: '중국어(간체)',\n    chinese_traditional: '중국어(번체)',\n    option_email: '이메일(선택)',\n    insert_email: '이메일 주소를 입력 하세요',\n    sign_up_complete: '회원 가입이 완료 되었습니다',\n    agree_terms_conditions: '이용약관에 동의해 주세요.',\n    agree_personal_information: '개인정보 수집 및 이용에 대한 안내에 동의해 주세요.',\n    insert_studying_stage: '작품을 공유하고 싶은 학급을 선택해 주세요.',\n    insert_born_year: '태어난 연도를 입력해 주세요.',\n    insert_gender: '성별을 선택지에서 선택해 주세요.',\n    select_language: '언어를 선택해 주세요.',\n    check_email: '이메일 형식을 확인해 주세요.',\n    already_exist_id: '이미 존재하는 아이디 입니다.',\n    id_validation_id: '아이디는 4~20자의 영문/숫자를 조합하세요',\n    password_validate_pwd: '패스워드는 5자 이상의 영문/숫자 등을 조합하세요.',\n    password_validate_pwd_length: '패스워드는 최소 5자 이상으로 입력해 주세요.',\n    neoid_username_same_id: '이미 사용중인 아이디 입니다.(NEOID)',\n    insert_same_pwd: '같은 비밀번호를 입력해 주세요.',\n    studying_stage_group: '작품 공유 학급',\n    studying_stage: '작품을 공유하고 싶은 학급을 선택해 주세요.',\n    password: '비밀번호 입력',\n    save_id: '아이디 저장',\n    auto_login: '자동 로그인',\n    enter_id_pw: '아이디, 비밀번호 입력',\n    forgot_password: '아이디와 비밀번호가 기억나지 않으세요 ?',\n    did_not_join: '아직 엔트리 회원이 아니세요?',\n    go_join: '회원가입하기 ',\n    renew_index_text_00: '엔트리 교과서 학습하기',\n    renew_index_text_01: '교과서로 엔트리를 배워보세요.',\n    renew_index_text_02: '초등학교 교과서 강의를 통해',\n    renew_index_text_02_2: '엔트리를 배워보세요!',\n    renew_index_text_03: '교과서 학습하기',\n    renew_index_text_03_2: '바로가기',\n    renew_index_text_1: '2019년, 엔트리가 바뀝니다',\n    renew_index_text_2: '확 바뀐 작품 만들기',\n    renew_index_text_3: '지금 새로운 기능을 확인하고',\n    renew_index_text_3_2: 'PC와 태블릿으로 작품을 만들어보세요!',\n    renew_index_text_4: '자세히 보기',\n    first_step: '소프트웨어 교육의 첫걸음',\n    entry_content_one: '상상했던 것들을 블록 놀이하듯 하나씩 쌓아보세요.',\n    entry_content_two: '게임, 애니메이션, 미디어아트와 같은 멋진 작품이 완성된답니다!',\n    entry_content_three:\n        '재미있는 놀이로 배우고, 나만의 멋진 작품을 만들어 친구들과 공유할 수 있는 멋진 엔트리의 세상으로 여러분을 초대합니다!',\n    funny_space: '재미있게 배우는 학습공간',\n    in_learn_section: '< 학습하기 > 에서는',\n    learn_problem_solving:\n        '컴퓨터를 활용해 논리적으로 문제를 해결할 수 있는 다양한 학습 콘텐츠가 준비되어 있습니다. 게임을 하듯이 주어진 미션들을 프로그래밍으로 해결해볼 수도 있고 재미있는 동영상으로 소프트웨어의 원리를 배울 수도 있습니다 .',\n    joy_create: '창작의 즐거움',\n    in_make: '< 만들기 > 는',\n    make_contents:\n        '미국 MIT에서 개발한 Scratch와 같은 비주얼 프로그래밍 언어를 사용하여 프로그래밍을 처음 접하는 사람들도 쉽게 나만의 창작물을 만들 수 있습니다. 또 엔트리를 통해 만들 수 있는 컨텐츠의 모습은 무궁무진합니다. 과학 시간에 배운 물리 법칙을 실험해 볼 수도 있고 좋아하는 캐릭터로 애니메이션을 만들거나 직접 게임을 만들어 볼 수 있습니다.',\n    and_content:\n        '또 엔트리를 통해 만들 수 있는 콘텐츠의 모습은 무궁무진합니다. 과학 시간에 배운 물리 법칙을 실험해 볼 수도 있고 좋아하는 캐릭터로 애니메이션을 만들거나 직접 게임을 만들어 볼 수 있습니다.',\n    share_collaborate: '공유와 협업',\n    explore_contents:\n        '< 구경하기 > 에서는 엔트리를 통해 제작한 작품을 다른 사람들과 쉽게 공유할 수 있습니다. 또한 공유된 작품이 어떻게 구성되었는지 살펴볼 수 있고, 이를 발전시켜 자신만의 프로젝트를 만들 수 있습니다. 그리고 엔트리에서는 공동 창작도 가능합니다. 친구들과 협업하여 더 멋진 프로젝트를 만들어볼 수 있습니다.',\n    why_software: '왜 소프트웨어 교육이 필요할까?',\n    speak_obama_contents:\n        '컴퓨터 과학을 배우는 것은 단지 여러분의 미래에만 중요한 일이 아닙니다. 이것은 우리 미국의 미래를 위해 중요한 일 입니다.',\n    obama: '버락 오바마',\n    us_president: '미국 대통령',\n    billgates_contents:\n        '컴퓨터 프로그래밍은 사고의 범위를 넓혀주고 더 나은 생각을 할 수 있게 만들며 분야에 상관없이 모든 문제에 대해 새로운 해결책을 생각할 수 있는 힘을 길러줍니다.',\n    billgates: '빌게이츠',\n    chairman_micro: 'Microsoft 회장',\n    eric_contents:\n        '현재 디지털 혁명은 지구상 대부분의 사람들에게 아직 시작도 안된 수준입니다. 프로그래밍을 통해 향후 10년간 모든 것이 변화할 것 입니다.',\n    eric: '에릭 슈미츠',\n    sandbug_contents:\n        '오늘날 컴퓨터 과학에 대한 이해는 필수가 되었습니다. 우리의 국가 경쟁력은 우리가 아이들에게 이것을 얼마나 잘 가르칠 수 있느냐에 달려있습니다.',\n    sandbug: '쉐릴 샌드버그',\n    view_entry_tools: '엔트리와 함께할 수 있는 교구들을 살펴볼 수 있습니다.',\n    solve_problem: '미션 해결하기',\n    solve_problem_content:\n        '게임을 하듯 미션을 하나 하나 해결하며 소프트웨어의 기본 원리를 배워보세요!',\n    find_extra_title: '엔트리봇 부품 찾기 대작전',\n    all_ages: '전 연령',\n    total: '총',\n    step: '단계',\n    find_extra_contents:\n        '로봇 강아지를 생산하던 루츠 공장에 어느 날 갑자기 일어난 정전 사태로 태어난 특별한 강아지 엔트리 봇. 아직 조립이 덜 된 나머지 부품들을 찾아 공장을 탈출 하도록 도와주면서 소프트웨어의 동작 원리를 익혀보자!',\n    software_play_contents: \"EBS에서 방영한 '소프트웨어야 놀자' 프로그램을 실습해볼 수 있습니다.\",\n    resources_contents: '엔트리를 활용한 다양한 교육자료들을 무료로 제공합니다.',\n    from: ' 출처',\n    sw_camp: '미래부 SW 창의캠프',\n    elementary: '초등학교',\n    middle: '중학교',\n    grades: '학년',\n    lesson: '차시',\n    sw_contents_one:\n        '5차시 분량으로 초등학생이 엔트리와 피지컬 컴퓨팅을 경험할  수 있는 교재입니다. 학생들은 엔트리 사용법을 학습하고, 그림판과 이야기 만들기를 합니다. 마지막에는 아두이노 교구를 활용하여 키보드를 만들어보는 활동을 합니다.',\n    sw_camp_detail: '미래창조과학부 SW창의캠프',\n    sw_contents_two:\n        '5차시 분량으로 중학생이 엔트리와 피지컬 컴퓨팅을 경험할 수 있는 교재입니다. 학생들은 엔트리 사용법을 학습하고, 미로찾기 게임과, 퀴즈 프로그램을 만들어 봅니다. 마지막에는 아두이노 교구를 활용하여 키보드로 자동차를 조종하는 활동을 합니다.',\n    sw_contents_three:\n        \"선생님들이 학교에서 시작할 수 있는 소프트웨어 수업 지도서입니다. 다양한 언플러그드 활동과, '소프트웨어야 놀자' 방송을 활용한 수업 지도안이 담겨 있습니다.\",\n    naver_sw: 'NAVER 소프트웨어야 놀자',\n    teacher_teaching: '교사용지도서 (초등학교 5~6학년 이상)',\n    funny_sw: '즐거운 SW놀이 교실',\n    sw_contents_four:\n        '소프트웨어를 놀이하듯 재미있게 배울 수 있는 교재로 엔트리보드게임을 비롯한 다양한 언플러그드 활동과 엔트리 학습모드로 소프트웨어를 만드는 기본 원리를 배우게 됩니다. 기본 원리를 배웠다면 학생들은 이제 엔트리로 이야기, 게임, 예술작품, 응용프로그램을 만드는 방법을 배우고, 자신이 생각한 소프트웨어를 만들고 발표할 수 있도록 교재가 구성되어 있습니다.',\n    ct_text_5: '교과서와 함께 키우는 컴퓨팅 사고력',\n    teacher_grade_5: '교원 (초등학교 5학년)',\n    ct_text_5_content:\n        '실생활의 문제를 해결하자는 테마로 준비된 총 8개의 학습콘텐츠가 담긴 교사용 지도안입니다. 각 콘텐츠는 개정된 교육과정을 반영한 타교과와의 연계를 통해 다양한 문제를 만나고 해결해볼 수 있도록 설계되었습니다.  아이들이 컴퓨팅 사고력을 갖춘 융합형 인재가 될 수 있도록 지금 적용해보세요!',\n    ct_text_6: '교과서와 함께 키우는 컴퓨팅 사고력',\n    teacher_grade_6: '교원 (초등학교 6학년)',\n    ct_text_6_content:\n        '실생활의 문제를 해결하자는 테마로 준비된 총 8개의 학습콘텐츠가 담긴 교사용 지도안입니다. 각 콘텐츠는 개정된 교육과정을 반영한 타교과와의 연계를 통해 다양한 문제를 만나고 해결해볼 수 있도록 설계되었습니다.  아이들이 컴퓨팅 사고력을 갖춘 융합형 인재가 될 수 있도록 지금 적용해보세요!',\n    sw_use: '모든 교재들은 비영리 목적에 한하여 저작자를 밝히고 자유롭게 이용할 수 있습니다.',\n    title: '제목',\n    writer: '작성자',\n    view: '보기',\n    date: '등록일',\n    find_id_pwd: '아이디와 비밀번호 찾기',\n    send_email: '비밀번호를 잊은 경우 이메일로 비밀번호를 찾을 수 있습니다.',\n    user_not_exist: '존재하지 않는 이메일 주소 입니다.',\n    not_signup: '아직 회원이 아니세요?',\n    send: '발송하기',\n    sensorboard: '엔트리봇 센서보드',\n    physical_computing: '피지컬 컴퓨팅',\n    sensorboard_contents:\n        '아두이노를 사용하기 위해서 더 이상 많은 케이블을 사용해 회로를 구성할 필요가 없습니다. 엔트리 보드는 아두이노 위에 끼우기만 하면 간단하게 LED, 온도센서, 소리센서, 빛, 슬라이더, 스위치를 활용할 수 있습니다. 이제 엔트리 보드를 활용해 누구라도 쉽게 자신만의 특별한 작품을 만들어보세요!',\n    entrybot_boardgame: '엔트리봇 보드게임',\n    unplugged: '언플러그드 활동',\n    unplugged_contents:\n        '재밌는 보드게임을 통해 컴퓨터의 작동 원리를 배워보세요. 로봇강아지인 엔트리봇이 정전된 공장에서 필요한 부품을 찾아 탈출하도록 돕다보면 컴퓨터 전문가처럼 문제를 바라 볼 수  있게됩니다.',\n    entrybot_cardgame: '엔트리봇 카드게임 : 폭탄 대소동',\n    entrybot_cardgame_contents:\n        '갑자기 엔트리도시에 나타난 12종류의 폭탄들! 과연 폭탄들을 안전하게 해체할 수 있을까요? 폭탄들을 하나씩 해체하며 엔트리 블록과 함께 소프트웨어의 원리를 배워봐요!  순차, 반복, 조건을 통해 폭탄을 하나씩 해체하다 보면 엔트리도시를 구한 영웅이 될 수 있답니다!',\n    basic_learn: '엔트리 기본 학습',\n    basic_learn_contents: '엔트리를 활용한 다양한 교육 콘텐츠를 제공합니다.',\n    troubleshooting: '문제해결 학습',\n    playsoftware: '소프트웨어야 놀자',\n    make_own_lesson: '나만의 수업을 만들어 다른 사람과 공유할 수 있습니다.',\n    group_lecture: '우리 반 강의',\n    group_curriculum: '우리 반 강의 모음',\n    group_homework: '우리 반 과제',\n    group_noproject: '전시된 작품이 없습니다.',\n    group_nolecture: '생성된 강의가 없습니다.',\n    group_nocurriculum: '생성된 강의 모음이 없습니다.',\n    lecture_contents: '필요한 기능만 선택하여 나만의 수업을 만들어 볼 수 있습니다.',\n    curriculum_contents:\n        '여러개의 강의를 하나의 강의 모음으로 묶어 차근차근 따라할 수 있는 수업을 만들 수 있습니다.',\n    grade_info: '학년 정보',\n    difficulty: '난이도',\n    usage: '사용요소',\n    learning_concept: '학습개념',\n    related_subject: '연계 교과',\n    show_more: '더보기',\n    close: '닫기',\n    latest: '최신순',\n    viewCount: '조회수',\n    viewer: '조회순',\n    like: '좋아요순',\n    comment: '댓글순',\n    entire_period: '전체기간',\n    today: '오늘',\n    latest_week: '최근 1주일',\n    latest_month: '최근 1개월',\n    latest_three_month: '최근 3개월',\n    current_password: '현재 비밀번호',\n    change_password: '비밀번호 변경',\n    incorrect_password: '비밀번호가 일치하지 않습니다.',\n    incorrect_password_login: '아이디 또는 비밀번호를 잘못 입력하셨습니다.',\n    suspension_user: '이용 정지된 계정입니다.',\n    blocked_user: '승인되지 않은 사용자 입니다.',\n    new_password: '새로운 비밀번호',\n    password_option_1: '영문과 숫자의 조합으로 5자 이상이 필요합니다.',\n    again_new_password: '새로운 비밀번호 재입력',\n    enter_new_pwd: '새로운 비밀번호를 입력하세요.',\n    confirm_new_pwd: '새로운 비밀번호를 확인하세요.',\n    enter_new_pwd_again: '새로운 비밀번호를 다시 입력하세요.',\n    password_match: '비밀번호가 일치하지 않습니다.',\n    incorrect_email: '유효한 이메일이 아닙니다',\n    edit_button: '정보수정',\n    edit_profile: '관리',\n    my_project: '나의 작품',\n    my_group: '나의 학급',\n    mark: '관심 작품',\n    prev_state: '이전',\n    profile_image: '자기소개 이미지',\n    insert_profile_image: '프로필 이미지를 등록해 주세요.',\n    at_least_180: '180 x 180 픽셀의 이미지를 권장합니다.',\n    upload_image: '이미지 업로드',\n    about_me: '자기소개',\n    save_change: '변경사항 저장',\n    basic_image: '기본 이미지',\n    profile_condition: '자기소개를 입력해 주세요. 50자 내외',\n    profile_back: '돌아가기',\n    make_project: '작품 만들기',\n    exhibit_project: '작품 전시하기',\n    art_list_shared: '개인',\n    art_list_group_shared: '학급',\n    gl_mode_boost: '부스트 모드',\n    gl_not_supported:\n        '부스트 모드로 실행할 수 없는 환경입니다.\\n확인을 누르면 기본모드로 실행됩니다.',\n    view_project: '코드 보기',\n    code_view: '코드보기',\n    noResult: '검색 결과가 없습니다.',\n    comment_view: '댓글',\n    upload_project: '올리기',\n    edit: '수정',\n    save_complete: '저장',\n    just_like: '좋아요',\n    share: '공유',\n    who_likes_project: '작품을 좋아하는 사람',\n    people_interest: '작품을 관심있어 하는 사람',\n    none_person: '없음',\n    inserted_date: '등록일',\n    last_modified: '최종 수정일',\n    original_project: '원본 작품',\n    for_someone: '님의',\n    original_project_deleted: '원본 작품이 삭제되었습니다.',\n    delete_project: '삭제',\n    delete_group_project: '목록에서 삭제',\n    currnet_month_time: '월',\n    current_day_time: '일',\n    game: '게임',\n    animation: '애니메이션',\n    media_art: '미디어 아트',\n    physical: '피지컬',\n    etc: '기타',\n    connected_contents: '연계되는 콘텐츠',\n    connected_contents_content:\n        '엔트리와 함께 할 수 있는 다양한 콘텐츠를 만나보세요. 처음 소프트웨어를 배우는 사람이라면 쉽게 즐기는 보드게임부터 아두이노와 같은 피지컬 컴퓨팅을 활용하여 자신만의 고급스러운 창작물을 만들어 볼 수 있습니다.',\n    basic_mission: '기본 미션: 엔트리봇 미로찾기',\n    basic_mission_content:\n        '강아지 로봇을 만드는 공장에서 우연한 정전으로 혼자서 생각할 수 있게 된 엔트리봇! 공장을 탈출하고 자유를 찾을 수 있도록 엔트리봇을 도와주세요!',\n    application_mission: '응용미션: 엔트리봇 우주여행',\n    write_article: '글쓰기',\n    write_contest: '제출하기',\n    view_all_articles: '모든 글 보기',\n    view_own_articles: '내가 쓴 글 보기',\n    view_qna_articles: '답변 없는 글 보기',\n    learning_materials: '교육자료',\n    download_materials: '교육자료 내려받기',\n    download_button: '내려받기',\n    download_all: '모두 내려받기',\n    ebs_software_first:\n        '<소프트웨어야 놀자>는 네이버와 EBS가 함께 만든 교육 콘텐츠입니다. 여기에서는 엔트리를 활용하여 실제로 간단한 프로그램을 만들어보며 소프트웨어의 기초 원리를 배워나갈 수 있습니다. 또한 각 콘텐츠에서는 동영상을 통해 컴퓨터과학에 대한 선행지식이 없더라도 충분히 재미와 호기심을 느끼며 진행할 수 있도록 준비되어있습니다.',\n    go_software: '소프트웨어야 놀자 가기',\n    ebs_context: 'EBS 동영상 가기',\n    ebs_context_hello: 'EBS 가기',\n    category: '카테고리',\n    add_picture: '사진첨부',\n    upload_article: '글 올리기',\n    list: '목록',\n    report: '신고하기',\n    upload: '올리기',\n    staff_picks: '스태프 선정',\n    popular_picks: '인기 작품',\n    lecture_header_more: '더 만들어 보기',\n    lecture_header_reset: '초기화',\n    lecture_header_reset_exec: '초기화 하기',\n    lecture_header_save: '저장',\n    lecture_header_save_content: '학습내용 저장하기',\n    lecture_header_export_project: '내 작품으로 저장하기',\n    lecture_header_undo: '취소',\n    lecture_header_redo: '복원',\n    lecture_er_bugs: '버그신고',\n    lecture_container_tab_object: '오브젝트',\n    lecture_container_tab_video: '강의 동영상',\n    lecture_container_tab_project: '완성된 작품',\n    lecture_container_tab_help: '블록 도움말',\n    illigal: '불법적인 내용 또는 사회질서를 위반하는 활동',\n    verbal: '언어 폭력 또는 개인 정보를 침해하는 활동',\n    commertial: '상업적인 목적을 가지고 활동',\n    explicit: '음란물',\n    other: '기타',\n    check_one_more: '하나이상 표기해주세요.',\n    enter_content: '기타의 내용을 입력해 주세요.',\n    report_result: '결과 회신을 원하시면 메일을 입력해 주세요.',\n    report_success: '신고하기가 정상적으로 처리 되었습니다.',\n    etc_detail:\n        '기타 항목 선택후 입력해주세요. 신고와 무관한 욕설 작성 시 이용이 정지될 수 있습니다.',\n    lecture_play: '강의 보기',\n    list_view_link: '다른 강의 모음 보기',\n    lecture_intro: '강의 소개 보기',\n    study_goal: '학습목표',\n    study_description: '설명',\n    study_created: '등록일',\n    study_last_updated: '최종 수정일',\n    study_remove: '삭제',\n    study_group_lecture_remove: '목록에서 삭제',\n    study_group_curriculum_remove: '목록에서 삭제',\n    study_edit: '강의 모음 수정',\n    study_comments: '댓글',\n    study_comment_post: '올리기',\n    study_comment_remove: '삭제',\n    study_comment_edit: '수정',\n    study_comment_save: '저장',\n    study_guide_video: '안내 영상',\n    study_basic_project: '기본 작품',\n    study_done_project: '완성 작품을 선택하세요.',\n    study_usage_element: '사용요소',\n    study_concept_element: '적용개념',\n    study_subject_element: '연계교과',\n    study_computing_element: '컴퓨팅요소',\n    study_element_none: '없음',\n    study_label_like: '좋아요',\n    study_label_interest: '관심 강의',\n    study_label_share: '공유',\n    study_label_like_people: '강좌를 좋아하는 사람',\n    study_label_interest_people: '강좌를 관심있어 하는 사람',\n    study_related_lectures: '강의 목록',\n    study_expand: '전체보기',\n    study_collapse: '줄이기',\n    aftercopy: '주소가 복사되었습니다.',\n    study_remove_curriculum: '강의 모음을 삭제하시겠습니까?',\n    content_required: '내용을 입력하세요',\n    upload_not_supported_file_msg: '지원하지 않는 형식의 파일입니다.',\n    study_remove_lecture: '강의를 삭제하시겠습니까?',\n    lecture_build: '강의 만들기',\n    lecture_build_step1: '1. 강의를 소개하기 위한 정보를 입력해주세요',\n    lecture_build_step2: '2. 학습에 사용되는 기능들만 선택해주세요',\n    lecture_build_step3: '3. 모든 정보를 올바르게 입력했는지 확인해주세요',\n    lecture_build_choice: '어떤 것을 올리시겠습니까?',\n    lecture_build_project: '엔트리 작품',\n    lecture_build_video: '강의 영상',\n    lecture_build_grade: '추천학년',\n    lecture_build_goals: '학습목표',\n    lecture_build_add_goal: '이곳을 클릭하여 목표를 추가',\n    lecture_build_attach: '파일 첨부',\n    lecture_build_attach_text: '20MB 이내의 파일을 업로드해 주세요.',\n    lecture_build_assist: '보조 영상',\n    lecture_build_youtube_url: 'Youtube 공유 링크를 넣어주세요.',\n    lecture_build_project_done: '완성 작품을 선택하세요.',\n    lecture_build_scene_text1: '장면기능을 끄면 새로운 장면을 추가하거나,',\n    lecture_build_scene_text2: '삭제할 수 없습니다.',\n    lecture_build_object_text:\n        '오브젝트 추가하기를 끄면 새로운 오브젝트를 추가하거나 삭제할 수 없습니다.',\n    lecture_build_blocks_text1: '학습에 필요한 블록들만 선택해주세요.',\n    lecture_build_blocks_text2: '선택하지 않은 블록은 숨겨집니다.',\n    lecture_build_basic1: '학습을 시작할때 사용할 작품을 선택해 주세요.',\n    lecture_build_basic2: '학습자는 선택한 작품을 가지고 학습을 하게 됩니다.',\n    lecture_build_help: '이 도움말을 다시 보시려면 눌러주세요.',\n    lecture_build_help_never: '다시보지 않기',\n    lecture_build_close: '닫기',\n    lecture_build_scene: '장면 1',\n    lecture_build_add_object: '오브젝트 추가하기',\n    lecture_build_start: '시작하기',\n    lecture_build_tab_code: '블록',\n    lecture_build_tab_shape: '모양',\n    lecture_build_tab_sound: '소리',\n    lecture_build_tab_attribute: '속성',\n    lecture_build_tab_table: '테이블',\n    lecture_build_block_category: '블록 카테고리를 선택하세요.',\n    lecture_build_attr_all: '전체',\n    lecture_build_attr_var: '변수',\n    lecture_build_attr_signal: '신호',\n    lecture_build_attr_list: '리스트',\n    lecture_build_attr_func: '함수',\n    lecture_build_edit: '강의 수정',\n    lecture_build_remove: '삭제',\n    curriculum_build: '강의 모음 만들기',\n    curriculum_step1: '1. 강의 모음을 소개하는 정보를 입력해주세요.',\n    curriculum_step2: '2. 강의 모음을 구성하는 강의를 선택해주세요.',\n    curriculum_step3: '3. 올바르게 강의 모음이 구성되었는지 확인해주세요.',\n    curriculum_lecture_upload: '강의 올리기',\n    curriculum_lecture_edit: '강의 편집',\n    curriculum_lecture_open: '불러오기',\n    group_lecture_add: '우리 반 강의 추가하기',\n    group_curriculum_add: '우리 반 강의 모음 추가하기',\n    group_lecture_delete: '삭제',\n    group_curriculum_delete: '삭제',\n    group_select: '',\n    group_studentNo: '학번',\n    group_username: '이름',\n    group_userId: '아이디',\n    group_tempPassword: '비밀번호 수정',\n    group_gender: '성별',\n    group_studentCode: '코드',\n    group_viewWorks: '작품 보기',\n    added_group_lecture: '강의가 삭되었습니다.',\n    added_group_curriculum: '강의 모음이 삭제되었습니다.',\n    deleted_group_lecture: '강의가 삭제되었습니다.',\n    deleted_group_curriculum: '강의 모음이 삭제되었습니다.',\n    modal_my: '나의',\n    modal_interest: '관심',\n    modal_project: '작품',\n    section: '단원',\n    connect_hw: '하드웨어 연결',\n    connect_message: '%1에 연결되었습니다.',\n    connect_fail: '하드웨어 연결에 실패했습니다. 연결프로그램이 켜져 있는지 확인해 주세요.',\n    interest_curriculum: '관심 강의 모음',\n    marked_curriculum: '관심 강의 모음',\n    searchword_required: '검색어를 입력하세요.',\n    file_required: '파일은 필수 입력 항목입니다.',\n    file_name_error: '올바른 파일이름을 입력해 주세요.',\n    file_upload_max_count: '한번에 10개까지 업로드가 가능합니다.',\n    image_file_only: '이미지 파일만 등록이 가능합니다.',\n    file_upload_max_size: '10MB 이하만 업로드가 가능합니다.',\n    curriculum_modal_lectures: '나의 강의',\n    curriculum_modal_interest: '관심 강의',\n    group_curriculum_modal_curriculums: '나의 강의 모음',\n    group_curriculum_modal_interest: '관심 강의 모음',\n    picture_import: '모양 가져오기',\n    picture_select: '모양 선택',\n    lecture_list_view: '다른 강의보기',\n    play_software_2: 'EBS 소프트웨어야 놀자2',\n    play_software_2_content:\n        '네이버와 EBS가 함께 만든 두 번째 이야기, <소프트웨어야 놀자> 시즌2를 만나보세요! 재미있는 동영상 강의를 통해 소프트웨어의 기본 개념을 배워보고, 다양하고 흥미로운 주제로 실생활 문제를 해결해 볼 수 있습니다. 방송영상과 특별영상을 보며 재미있는 프로그램들을 직접 만들어보세요. 소프트웨어 교육을 처음 접하는 친구들도 쉽게 소프트웨어와 친구가 될 수 있답니다!',\n    open_project_to_all: '공개',\n    close_project: '비공개',\n    category_media_art: '미디어 아트',\n    go_further: '더 나아가기',\n    marked_project: '관심 작품',\n    marked_group_project: '학급 관심 작품',\n    basic: '기본',\n    application: '응용',\n    the_great_escape: '탈출 모험기',\n    escape_guide_1:\n        '강아지 로봇을 만드는 공장에서 우연한 정전으로 혼자서 생각할 수 있게 된 엔트리봇! ',\n    escape_guide_1_2: ' 공장을 탈출하고 자유를 찾을 수 있도록 엔트리봇을 도와주세요!',\n    escape_guide_2:\n        '엔트리봇이 먼 길을 가기엔 고쳐야 할 곳이 너무 많아 공장에서 탈출하면서 몸을 수리할 수 있는 부품들을 찾아보자! 아직 몸이 완전하지는 않지만 걷거나 뛰면서, 방향을 바꾸는 정도는 가능할 거야! ',\n    escape_guide_2_2: '학습 목표: 순차적 실행',\n    escape_guide_3:\n        '드디어 공장을 탈출했어! 하지만 마을로 가기 위해서는 아직 가야 할 길이 멀어. 그래도 몸은 어느 정도 고쳐져서 똑같은 일을 많이 해도 무리는 없을 거야! 어? 근데 저 로봇은 뭐지? ',\n    escape_guide_3_2: '학습 목표: 반복문과 조건문',\n    escape_guide_4:\n        '드디어 마을 근처까지 왔어! 아까부터 똑같은 일을 많이 했더니 이제 외울 지경이야! 차라리 쓰일 블록은 이제 기억해뒀다가 쓰면 좋을 것 같아. 여기서 배터리만 충전해 놓으면 이제 평생 자유롭게 살 수 있을 거야.',\n    escape_guide_4_2: '학습 목표: 함수 정의와 호출',\n    space_travel_log: '우주 여행기',\n    space_guide_1:\n        '머나먼 우주를 탐사하기 위해 떠난 엔트리봇. 드디어 탐사 임무를 마치고 고향별인 지구로 돌아오려 하는데 수많은 돌이 지구로 가는 길을 막고 있다!  엔트리봇이 안전하게 지구로 돌아올 수 있도록 도와주세요!',\n    space_guide_2:\n        '드디어 지구에 돌아갈 시간이야! 얼른 지구에 돌아가서 쉬고 싶어!앞에 돌들이 어떻게 되어 있는지 확인하고 언제 어디로 가야 하는지 알려줘! 그러면 내가 가르쳐준 방향으로 움직일게!',\n    space_guide_2_2: '학습 목표: 조건문 중첩과 논리 연산',\n    cfest_mission: '엔트리 체험 미션',\n    maze_1_intro:\n        '안녕 나는 엔트리봇이라고 해. 지금 나는 다친 친구들을 구하려고 하는데 너의 도움이 필요해. 나를 도와서 친구들을 구해줘! 먼저 앞으로 가기 블록을 조립하고 시작을 눌러봐',\n    maze_1_title: '시작 방법',\n    maze_1_content: '엔트리봇은 어떻게 움직이나요?',\n    maze_1_detail:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐 <br> 2. 다 조립했으면, 시작을 눌러봐 <br> 3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_2_intro:\n        '좋아! 덕분에 첫 번째 친구를 무사히 구할 수 있었어! 그럼 다음 친구를 구해볼까? 어! 그런데 앞에 벌집이 있어! 뛰어넘기 블록을 사용해서 벌집을 피하고 친구를 구해보자.',\n    maze_2_title_1: '장애물 뛰어넘기',\n    maze_2_content_1: '장애물이 있으면 어떻게 해야하나요?',\n    maze_2_detail_1:\n        '길을 가다보면 장애물을 만날 수 있어. <br> 장애물이 앞에 있을 때에는 뛰어넘기 블록을 사용해야 해.',\n    maze_2_title_2: '시작 방법',\n    maze_2_content_2: '엔트리봇은 어떻게 움직이나요?',\n    maze_2_detail_2:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐 <br> 2. 다 조립했으면, 시작을 눌러봐 <br> 3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_3_intro:\n        '멋졌어! 이제 또 다른 친구를 구하러 가자~ 이번에는 아까 구한 친구가 준 반복하기 블록을 이용해볼까? 반복하기를 이용하면 똑같은 동작을 쉽게 여러번 할 수 있어! 한 번 반복할 숫자를 바꿔볼래?',\n    maze_3_title: '반복 블록(1)',\n    maze_3_content: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_3_detail:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해. <br> 반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼',\n    maze_4_intro:\n        '훌륭해! 이제 구해야 할 친구 로봇들도 별로 남지 않았어. 벌집에 닿지 않도록 뛰어넘기를 반복하면서 친구에게 갈 수 있게 해줘!',\n    maze_4_title: '반복 블록(1)',\n    maze_4_content: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_4_detail:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해. <br> 반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼',\n    maze_5_intro:\n        '대단해! 이제 반복하기 블록과 만약 블록을 같이 사용해보자~ 만약 블록을 사용하면 앞에 벽이 있을 때 벽이 없는 쪽으로 회전할 수 있어. 그럼 친구를 구해주러 출발해볼까?',\n    maze_5_title_1: '만약 블록',\n    maze_5_content_1: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_5_detail_1:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어. <br> 앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고 <br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_5_title_2: '반복 블록(2)',\n    maze_5_content_2: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_5_detail_2:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어. <br> 반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼. <br> 그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_6_intro:\n        '이제 마지막 친구야! 아까 해본 것처럼만 하면 될거야! 그럼 마지막 친구를 구하러 가볼까?',\n    maze_6_title_1: '만약 블록',\n    maze_6_content_1: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_6_detail_1:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어. <br> 앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고 <br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_6_title_2: '반복 블록(2)',\n    maze_6_content_2: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_6_detail_2:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어. <br> 반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼. <br> 그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_programing_mode_0: '블록 코딩',\n    maze_programing_mode_1: '자바스크립트',\n    maze_operation1_title: '1단계 – 자바스크립트모드 안내',\n    maze_operation1_1_desc:\n        '나는 로봇강아지 엔트리봇이야. 나에게 명령을 내려서 미션을 해결할 수 있게 도와줘! 미션은 시작할 때마다 <span class=\"textShadow\">\\'목표\\'</span>를 통해서 확인할 수 있어!',\n    maze_operation1_2_desc:\n        '미션을 확인했다면 <b>명령</b>을 내려야 해 <span class=\"textUnderline\">\\'명령어 꾸러미\\'</span>는 <b>명령어</b>가 있는 공간이야. <b>마우스</b>와 <b>키보드</b>로 <b>명령</b>을 내릴 수 있어. <span class=\"textShadow\">마우스</span>로는 명령어 꾸러미에 있는 <b>명령어</b>를 클릭하거나, <b>명령어</b>를 <span class=\"textUnderline\">\\'명령어 조립소\\'</span>로 끌고와서 나에게 <b>명령</b>을 내릴 수 있어!',\n    maze_operation1_2_textset_1: '마우스로 명령어를 클릭하는 방법 ',\n    maze_operation1_2_textset_2: '마우스로 명령어를 드래그앤드랍하는 방법 ',\n    maze_operation1_3_desc:\n        '<span class=\"textShadow\">키보드</span>로 명령을 내리려면 \\'명령어 꾸러미\\' 에 있는 <b>명령어를 키보드로 직접 입력하면 돼.</b></br> 명령어를 입력할 때 명령어 끝에 있는 <span class=\"textShadow\">()와 ;</span> 를 빼먹지 않도록 주의해야해!',\n    maze_operation1_4_desc:\n        '미션을 해결하기 위한 명령어를 다 입력했다면 <span class=\"textShadow\">[시작하기]</span>를 누르면 돼.</br> [시작하기]를 누르면 나는 명령을 내린대로 움직일 거야!</br> 각 명령어가 궁금하다면 <span class=\"textShadow\">[명령어 도움말]</span>을 확인해봐!',\n    maze_operation7_title: '7단계 - 반복 명령 알아보기(횟수반복)',\n    maze_operation7_1_desc:\n        '<b>똑같은 일</b>을 반복해서 명령하는건 매우 귀찮은 일이야.</br>이럴땐 <span class=\"textShadow\">반복</span>과 관련된 명령어를 사용하면 훨씬 쉽게 명령을 내릴 수 있어.',\n    maze_operation7_2_desc:\n        '그렇다면 반복되는 명령을 쉽게 내리는 방법을 알아보자.</br>먼저 반복하기 명령어를 클릭한 다음, <span class=\"textShadow\">i<1</span> 의 숫자를 바꿔서 <span class=\"textShadow\">반복횟수</span>를 정하고</br><span class=\"textShadow\">괄호({ })</span> 사이에 반복할 명령어를 넣어주면 돼!',\n    maze_operation7_3_desc:\n        '예를 들어 이 명령어<span class=\"textBadge number1\"></span>은 move(); 를 10번 반복해서 실행해.</br><span class=\"textBadge number2\"></span>명령어와 동일한 명령어지.',\n    maze_operation7_4_desc:\n        '이 명령어를 사용할 때는 <span class=\"textShadow\">{ } 안에 반복할 명령어</span>를 잘 입력했는지,</br><span class=\"textShadow\">`;`</span>는 빠지지 않았는지 잘 살펴봐!</br>이 명령어에 대한 자세한 설명은 [명령어 도움말]에서 볼 수 있어.',\n    maze_operation7_1_textset_1: '똑같은 명령어를 반복해서 사용하는 경우',\n    maze_operation7_1_textset_2: '반복 명령어를 사용하는 경우',\n    maze_operation7_2_textset_1: '반복 횟수',\n    maze_operation7_2_textset_2: '반복할 명령',\n    maze_operation7_4_textset_1: '괄호({})가 빠진 경우',\n    maze_operation7_4_textset_2: '세미콜론(;)이 빠진 경우',\n    study_maze_operation8_title: '8단계 - 반복 명령 알아보기(횟수반복)',\n    study_maze_operation16_title: '4단계 - 반복 명령 알아보기(조건반복)',\n    study_maze_operation1_title: '1단계 - 반복 명령 알아보기(횟수반복)',\n    maze_operation9_title: '9단계 - 반복 명령 알아보기(조건반복)',\n    maze_operation9_1_desc:\n        '앞에서는 몇 번을 반복하는 횟수반복 명령어에 대해 배웠어.</br>이번에는 <span class=\"textShadow\">계속해서 반복하는 명령어</span>를 살펴보자.</br>이 명령어를 사용하면 미션이 끝날 때까지 <b>동일한 행동</b>을 계속 반복하게 돼.</br>이 명령어 역시 괄호({ }) 사이에 반복할 명령어를 넣어 사용할 수 있어!',\n    maze_operation9_2_desc:\n        '예를 들어 이 명령어 <span class=\"textBadge number1\"></span>은 미션을 완료할때까지 반복해서 move(); right()를 실행해.</br><span class=\"textBadge number2\"></span>명령어와 동일한 명령어지.',\n    maze_operation9_3_desc:\n        '이 명령어를 사용할 때도 <span class=\"textShadow\">{ } 안에 반복할 명령어</span>를 잘 입력했는지,</br><span class=\"textShadow\">`true`</span>가 빠지지 않았는지 잘 살펴봐!</br>이 명령어에 대한 자세한 설명은 [명령어 도움말]에서 볼 수 있어.',\n    maze_operation9_1_textset_1: '반복할 명령',\n    maze_operation9_3_textset_1: '괄호({})가 빠진 경우',\n    maze_operation9_3_textset_2: '세미콜론(;)이 빠진 경우',\n    maze_operation9_3_textset_3: 'true가 빠진 경우',\n    study_maze_operation3_title: '3단계 - 반복 명령 알아보기(조건반복)',\n    study_maze_operation4_title: '4단계 - 조건 명령 알아보기',\n    study_ai_operation4_title: '4단계 - 조건 명령과 레이더 알아보기',\n    study_ai_operation6_title: '6단계 - 중첩조건문 알아보기',\n    study_ai_operation7_title: '7단계 - 다양한 비교연산 알아보기',\n    study_ai_operation8_title: '8단계 - 물체 레이더 알아보기',\n    study_ai_operation9_title: '9단계 - 아이템 사용하기',\n    maze_operation10_title: '10단계 - 조건 명령 알아보기',\n    maze_operation10_1_desc:\n        '앞에서는 미션이 끝날 때까지 계속 반복하는 반복 명령어에 대해 배웠어.</br>이번에는 특정한 조건에서만 행동을 하는 <span class=\"textShadow\">조건 명령어</span>를 살펴보자.</br><span class=\"textBadge number2\"></span>에서 보는것처럼 조건 명령어를 사용하면 <b>명령을 보다 효율적으로 잘 내릴 수 있어.</b>',\n    maze_operation10_2_desc:\n        '조건 명령어는 크게 <span class=\"textShadow\">`조건`</span> 과 <span class=\"textShadow\">`조건이 발생했을때 실행되는 명령`</span>으로 나눌수 있어.</br>먼저 <span class=\"textUnderline\">조건</span> 부분을 살펴보자. If 다음에 나오는 <span class=\"textUnderline\">( ) 부분</span>이 조건을 입력하는 부분이야.</br><span class=\"textBadge number1\"></span>과 같은 명령어를 예로 살펴보자. <span class=\"textUnderline\">if(front == \\“wall\\”)</span> 는 만약 내 앞에(front) \"wall(벽)\"이 있다면을 뜻해',\n    maze_operation10_3_desc:\n        '이제 <span class=\"textUnderline\">`조건이 발생했을 때 실행되는 명령`</span>을 살펴보자.</br>이 부분은 <span class=\"textShadow\">괄호{}</span>로 묶여 있고, 조건이 발생했을때 괄호안의 명령을 실행하게 돼!</br>조건이 발생하지 않으면 이 부분은 무시하고 그냥 넘어가게 되지.</br><span class=\"textBadge number1\"></span>의 명령어를 예로 살펴보자. 조건은 만약에 `내 앞에 벽이 있을 때` 이고,</br><b>이 조건이 발생했을 때 나는 괄호안의 명령어 right(); 처럼 오른쪽으로 회전하게 돼!</b>',\n    maze_operation10_4_desc:\n        '<span class=\"textShadow\">조건 명령어</span>는 <span class=\"textShadow\">반복하기 명령어</span>와 함께 쓰이는 경우가 많아.</br>앞으로 쭉 가다가, 벽을 만났을때만 회전하게 하려면</br><span class=\"textUnderline pdb5\"><span class=\"textBadge number1\"></span><span class=\"textBadge number2\"></span><span class=\"textBadge number3\"></span>순서</span>와 같이 명령을 내릴 수 있지!',\n    maze_operation10_1_textset_1: '<b>[일반명령]</b>',\n    maze_operation10_1_textset_2:\n        '<span class=\"textMultiline\">앞으로 2칸 가고</br>오른쪽으로 회전하고,</br>앞으로 3칸가고,</br>오른쪽으로 회전하고, 앞으로...</span>',\n    maze_operation10_1_textset_3: '<b>[조건명령]</b>',\n    maze_operation10_1_textset_4:\n        '<span class=\"textMultiline\">앞으로 계속 가다가</br><span class=\"textEmphasis\">`만약에 벽을 만나면`</span></br>오른쪽으로 회전해~!</span>',\n    maze_operation10_2_textset_1: '조건',\n    maze_operation10_2_textset_2: '조건이 발생했을 때 실행되는 명령',\n    maze_operation10_3_textset_1: '조건',\n    maze_operation10_3_textset_2: '조건이 발생했을 때 실행되는 명령',\n    maze_operation10_4_textset_1:\n        '<span class=\"textMultiline\">미션이 끝날때 까지</br>계속 앞으로 간다.</span>',\n    maze_operation10_4_textset_2:\n        '<span class=\"textMultiline\">계속 앞으로 가다가,</br>만약에 벽을 만나면</span>',\n    maze_operation10_4_textset_3:\n        '<span class=\"textMultiline\">계속 앞으로 가다가,</br>만약에 벽을 만나면</br>오른쪽으로 회전한다.</span>',\n    study_maze_operation18_title: '6단계 - 조건 명령 알아보기',\n    maze_operation15_title: '15단계 - 함수 명령 알아보기',\n    maze_operation15_1_desc:\n        '자주 사용하는 명령어들을 매번 입력하는건 매우 귀찮은 일이야.</br>자주 사용하는 <span class=\"textUnderline\">명령어들을 묶어서 이름</span>을 붙이고,</br><b>필요할 때마다 그 명령어 묶음을 불러온다면 훨씬 편리하게 명령을 내릴 수 있어!</b></br>이런 명령어 묶음을  <span class=\"textShadow\">`함수`</span>라고 해. 이제 함수 명령에 대해 자세히 알아보자.',\n    maze_operation15_2_desc:\n        '함수 명령어는 명령어를 묶는 <b>`함수만들기` 과정</b>과,</br>묶은 명령어를 필요할 때 사용하는 <b>`함수 불러오기` 과정</b>이 있어.</br>먼저 함수만들기 과정을 살펴보자.</br>함수를 만들려면 함수의 이름과, 그 함수에 들어갈 명령어를 입력해야 해.</br><span class=\"textShadow\">function</span>을 입력한 다음 <span class=\"textShadow\">함수의 이름</span>을 정할 수 있어. 여기서는 <span class=\"textShadow\">promise</span>로 만들거야.</br>함수 이름을 만들었으면 <span class=\"textUnderline\">()</span>를 붙여줘. 그 다음 <span class=\"textUnderline\">괄호({})</span>를 입력해.</br>그리고 <span class=\"textUnderline\">이 괄호 안에 함수에 들어갈 명령어들을 입력하면</span> 함수가 만들어져!',\n    maze_operation15_3_desc:\n        '이 명령어를 예로 살펴보자. 나는 <span class=\"textShadow\">promise</span> 라는 함수를 만들었어.</br>이 함수를 불러서 실행하면 <span class=\"textUnderline\">괄호({})</span>안에 있는</br>move();</br>move();</br>left(); 가 실행돼!',\n    maze_operation15_4_desc:\n        '함수를 불러와서 실행하려면 아까 만든 <b>함수의 이름을 입력하고 뒤에 `();`를 붙이면 돼.</b></br>promise 라는 이름으로 함수를 만들었으니 <span class=\"textShadow\">promise();</span> 를 입력하면 앞에서 묶어놓은</br>명령어들이 실행되는거지!</br><span class=\"number1 textBadge\"></span>과 같이 명령을 내리면 <span class=\"number2 textBadge\"></span>처럼 동작하게 돼!</br>함수 명령어를 사용하려면 <span class=\"number1 textBadge\"></span>과 같이 함수를 만들고 함수를 불러와야해!',\n    maze_operation15_1_textset_1: '자주 사용하는 명령어 확인하기',\n    maze_operation15_1_textset_2: '명령어들을 묶어서 이름 붙이기',\n    maze_operation15_1_textset_3: '명령어 묶음 불러오기',\n    maze_operation15_2_textset_1: '명령어 묶음의 이름(함수 이름)',\n    maze_operation15_2_textset_2: '묶을 명령어들',\n    maze_operation15_3_textset_1: '명령어 묶음의 이름(함수 이름)',\n    maze_operation15_3_textset_2: '묶을 명령어들',\n    maze_operation15_4_textset_1: '함수 만들기',\n    maze_operation15_4_textset_2: '함수 불러오기',\n    maze_operation15_4_textset_3: '실제 상황',\n    maze_object_title: '오브젝트 정보',\n    maze_object_parts_box: '부품 상자',\n    maze_object_trap: '함정',\n    maze_object_monster: '몬스터',\n    maze_object_obstacle1: '장애물',\n    maze_object_obstacle2: 'bee',\n    maze_object_obstacle3: 'banana',\n    maze_object_friend: '친구',\n    maze_object_wall1: 'wall',\n    maze_object_wall2: 'wall',\n    maze_object_wall3: 'wall',\n    maze_object_battery: '베터리',\n    maze_command_ex: '예시',\n    maze_command_title: '명령어 도움말',\n    maze_command_move_desc: '엔트리봇을 한 칸 앞으로 이동시킵니다.',\n    maze_command_jump_desc:\n        '아래 이미지와 같은 장애물 앞에서 장애물을 뛰어 넘습니다.</br><div class=\"obstacleSet\"></div>',\n    maze_command_jump_desc_elec:\n        '아래 이미지와 같은 장애물 앞에서 장애물을 뛰어 넘습니다.</br><div class=\"obstacle_elec\"></div>',\n    maze_command_right_desc: '제자리에서 오른쪽으로 90도 회전합니다.',\n    maze_command_left_desc: '제자리에서 왼쪽으로 90도 회전합니다.',\n    maze_command_for_desc:\n        '괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 <span class=\"textShadow\">입력한 횟수</span> 만큼 반복해서 실행합니다.',\n    maze_command_while_desc:\n        '미션이 끝날 때가지 괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 계속 반복해서 실행합니다.',\n    maze_command_slow_desc: '아래 이미지와 같은 방지턱을 넘습니다.</br><div class=\"hump\"></div>',\n    maze_command_if1_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 벽이 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_if2_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 벌집이 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_if3_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 바나나가 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_promise_desc:\n        'promise 라는 <span class=\"textShadow\">함수</span>를 만들고 실행하면 괄호<span class=\"textShadow\">{}</span> 안에</br>있던 명령어가 실행합니다.',\n    perfect: '아주 완벽해!  ',\n    succeeded_using_blocks: ' 개의 블록을 사용해서 성공했어!',\n    succeeded_using_commands: ' 개의 명령어를 사용해서 성공했어!',\n    awesome: '대단한 걸!',\n    succeeded_go_to_next: '개의 블록만으로 성공했어! <br> 다음 단계로 넘어가자.',\n    good: '좋아! ',\n    but: '<br> 하지만, ',\n    try_again: ' 개의 블록만으로 성공하는 방법도 있어. <br> 다시 도전해 보는건 어때?',\n    try_again_commands: ' 개의 명렁어만으로 성공하는 방법도 있어. <br> 다시 도전해 보는건 어때?',\n    cfest_success:\n        '대단한걸! 덕분에 친구들을 구할 수 있었어! <br> 아마도 너는 타고난 프로그래머 인가봐! <br> 나중에 또 만나자~!',\n    succeeded_and_cert: '개의 블록만으로 성공했어! <br>인증서를 받으러 가자.',\n    cause_msgs_1: '에구, 앞으로 갈 수 없는 곳이였어. 다시 해보자.',\n    cause_msgs_2: '히잉. 그냥 길에서는 뛰어 넘을 곳이 없어. 다시 해보자.',\n    cause_msgs_3: '에고고, 아파라. 뛰어 넘었어야 했던 곳이였어. 다시 해보자.',\n    cause_msgs_4: '아쉽지만, 이번 단계에서는 꼭 아래 블록을 써야만 해. <br> 다시 해볼래?',\n    cause_msgs_5: '이런, 실행할 블록들이 다 떨어졌어. 다시 해보자.',\n    cause_msgs_6: '이런, 실행할 명령어들이 다 떨어졌어. 다시 해보자.',\n    close_experience: '체험<br>종료',\n    replay: '다시하기',\n    go_to_next_level: '다음단계 가기',\n    move_forward: '앞으로 한 칸 이동',\n    turn_left: '왼쪽',\n    turn_right: '오른쪽',\n    turn_en: '',\n    turn_ko: '으로 회전',\n    jump_over: '뛰어넘기',\n    when_start_is_pressed: '시작하기를 클릭했을 때',\n    repeat_until_ko: '만날 때 까지 반복',\n    repeat_until_en: '',\n    repeat_until: '만날 때 까지 반복',\n    if_there_is_1: '만약 앞에 ',\n    if_there_is_2: '있다면',\n    used_blocks: '사용 블록',\n    maximum: '목표 블록',\n    used_command: '사용 명령어 갯수',\n    maximum_command: '목표 명령어 갯수',\n    block_box: '블록 꾸러미',\n    block_assembly: '블록 조립소',\n    command_box: '명령어 꾸러미',\n    command_assembly: '명령어 조립소',\n    start: '시작하기',\n    engine_running: '실행중',\n    engine_replay: '돌아가기',\n    goto_show: '보러가기',\n    make_together: '함께 만드는 엔트리',\n    make_together_content:\n        '엔트리는 학교에 계신 선생님들과 학생 친구들이 함께 고민하며 만들어갑니다.',\n    project_nobody_like: \"이 작품이 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    project_nobody_interest: \"'관심 작품'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    lecture_nobody_like: \"이 강의가 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    lecture_nobody_interest: \"'관심 강의'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    course_nobody_like: \"이 강의 모음이 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    course_nobody_interest: \"'관심 강의 모음'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    before_changed: '변경전',\n    after_changed: '변경후',\n    from_changed: '( 2016년 04월 17일 부터 ) ',\n    essential: '필수',\n    access_term_title:\n        '안녕하세요. 엔트리 교육연구소 입니다. <br>  엔트리를 사랑해주시는 여러분께 감사드리며,  <br>  엔트리 교육연구소 웹사이트 이용약관이<br>  2016년 4월 17일 부로 다음과 같이 개정됨을 알려드립니다. ',\n    member_info: '회원 안내',\n    personal_info: '개인정보 수집 및 이용에 동의 합니다.',\n    option: '선택',\n    news: '최신소식',\n    edu_material: '교육자료',\n    latest_news: '최근소식',\n    edu_data: '교육자료',\n    training_program: '연수지원',\n    footer_phrase:\n        '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있게 개발된 비영리 교육 플랫폼입니다.',\n    footer_use_free:\n        '모든 엔트리교육연구소의 저작물은 교육적 목적에 한하여 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    footer_description_1:\n        '엔트리는 비영리 교육 플랫폼으로 모든 엔트리의 저작물은 교육 목적에 한해 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    footer_description_2: '',\n    nonprofit_platform: '비영리 교육 플랫폼',\n    this_is: '입니다.',\n    privacy: '개인정보 처리방침',\n    entry_addr: '경기도 성남시 분당구 불정로 6 NAVER 그린팩토리 16층',\n    entry_addr_additional_phone: '1522-9182',\n    entry_addr_additional_email: 'entry@connect.or.kr',\n    entry_addr_additional_opensource: '오픈소스 라이선스',\n    phone: '전화번호',\n    alert_agree_term: '이용약관에 동의하여 주세요.',\n    alert_private_policy: '개인정보 수집 약관에 동의하여 주세요.',\n    agree: '동의',\n    optional: '선택',\n    start_software: '소프트웨어 교육의 첫걸음',\n    analyze_procedure: '절차',\n    analyze_repeat: '반복',\n    analyze_condition: '분기',\n    analyze_interaction: '상호작용',\n    analyze_dataRepresentation: '데이터 표현',\n    analyze_abstraction: '추상화',\n    analyze_sync: '병렬 및 동기화',\n    jr_intro_1: '안녕! 난 쥬니라고 해! 내 친구 엔트리봇이 오른쪽에 있어! 날 친구에게 데려다 줘!',\n    jr_intro_2: '엔트리봇이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    jr_intro_3: '엔트리봇이 위쪽에 있어! 친구를 만날 수 있도록 도와줘!',\n    jr_intro_4: '어서 엔트리봇을 만나러 가자! 아래쪽으로 가보는거야~ ',\n    jr_intro_5: '우왓! 내 친구가 멀리 떨어져있어. 엔트리봇이 있는 곳까지 안내해줄래? ',\n    jr_intro_6: '저기 엔트리봇이 있어~ 얼른 만나러 가보자.',\n    jr_intro_7: '예쁜 꽃이 있네. 꽃들을 모아 엔트리봇에게 가보자!',\n    jr_intro_8: '가는 길에 꽃이 있어! 꽃을 모아 엔트리봇에게 가보자!',\n    jr_intro_9: '엔트리봇이 멀리 떨어져 있네? 가장 빠른 길로 엔트리봇에게 가 보자.',\n    jr_intro_10: '엔트리봇을 만나러 가는 길에 꽃을 모두 모아서 가보자.',\n    jr_intro_11:\n        '엔트리봇에게 가려면 오른쪽으로 다섯번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    jr_intro_12: '반복하기를 사용해서 엔트리봇을 만나러 가자.',\n    jr_intro_13:\n        '지금 블록으로는 친구에게 갈 수가 없어. 반복 횟수를 바꿔 엔트리봇에게 갈 수 있게 해줘.',\n    jr_intro_14: '반복 블록을 사용하여 엔트리봇에게 데려다 줘.',\n    jr_intro_15:\n        '엔트리봇이 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 엔트리봇에게 갈 수 있을 거야.',\n    jr_whats_ur_name: '내가 받을 인증서에 적힐 이름은?',\n    jr_down_cert: '인증서 받기',\n    jr_popup_prefix_1: '좋아! 엔트리봇을 만났어!',\n    jr_popup_prefix_2:\n        '우왓! 엔트리봇을 만났어! <br> 하지만 엔트리봇을 만나기에는 더 적은 블록을 사용해서도 <br> 만날 수 있는데 다시 해볼래? ',\n    jr_popup_prefix_3: '좋아! 책가방을 챙겼어!',\n    jr_popup_prefix_4:\n        '우왓! 책가방이 있는 곳으로 왔어! 하지만 더 적은 블록을 사용해도 책가방 쪽으로 갈 수 있는데 다시 해볼래?',\n    jr_popup_suffix_1:\n        '고마워~ 덕분에 책가방을 챙겨서 학교에 올 수 있었어~ 다음 학교 가는 길도 함께 가자~',\n    jr_popup_suffix:\n        '고마워~ 덕분에 엔트리봇이랑 재밌게 놀 수 있었어~ <br>다음에 또 엔트리봇이랑 놀자~',\n    jr_fail_dont_go: '에궁, 그 곳으로는 갈 수 없어. 가야하는 길을 다시 알려줘~',\n    jr_fail_dont_know: '어? 이제 어디로 가지? 어디로 가야하는 지 더 알려줘~',\n    jr_fail_no_flower: '이런 그곳에는 꽃이 없어. 꽃이 있는 곳에서 사용해보자~',\n    jr_fail_forgot_flower: '앗! 엔트리봇한테 줄 꽃을 깜빡했어. 꽃을 모아서 가자~',\n    jr_fail_need_repeat: '반복 블록이 없잖아! 반복 블록을 사용해서 해보자~',\n    jr_hint_1: '안녕! 난 쥬니라고 해! 내 친구 엔트리봇이 오른쪽에 있어! 날 친구에게 데려다 줘!',\n    jr_hint_2: '엔트리봇이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    jr_hint_3: '엔트리봇이 위쪽에 있어! 친구를 만날 수 있도록 도와줘!',\n    jr_hint_4: '어서 엔트리봇을 만나러 가자! 아래쪽으로 가보는거야~',\n    jr_hint_5: '우왓! 내 친구가 멀리 떨어져있어. 엔트리봇이 있는 곳까지 안내해줄래?',\n    jr_hint_6:\n        '잘못된 블록들 때문에 친구에게 가지 못하고 있어, 잘못된 블록을 지우고 엔트리봇에게 갈 수 있도록 해줘!',\n    jr_hint_7: '예쁜 꽃이 있네. 꽃들을 모아 엔트리봇에게 가보자!',\n    jr_hint_8: '가는 길에 꽃이 있어! 꽃을 모아 엔트리봇에게 가보자!',\n    jr_hint_9: '엔트리봇이 멀리 떨어져 있네? 가장 빠른 길로 엔트리봇에게 가 보자.',\n    jr_hint_10:\n        '앗, 블록을 잘못 조립해서 제대로 갈 수가 없어. 가는 길에 꽃을 모두 모아 엔트리봇에게 가져다 줄 수 있도록 고쳐 보자.',\n    jr_hint_11:\n        '엔트리봇에게 가려면 오른쪽으로 다섯번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    jr_hint_12: '반복하기를 사용해서 엔트리봇을 만나러 가자.',\n    jr_hint_13:\n        '지금 블록으로는 친구에게 갈 수가 없어. 반복 횟수를 바꿔 엔트리봇에게 갈 수 있게 해줘.',\n    jr_hint_14: '반복 블록을 사용하여 엔트리봇에게 데려다 줘.',\n    jr_hint_15:\n        '엔트리봇이 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 엔트리봇에게 갈 수 있을 거야.',\n    jr_certification: '인증서',\n    jr_congrat: '축하드립니다!',\n    jr_congrat_msg: '문제해결 과정을 성공적으로 마쳤습니다.',\n    jr_share: '공유',\n    go_see_friends: '친구들 만나러 가요~!',\n    junior_naver: '쥬니어 네이버',\n    junior_naver_contents_1: \"의 멋진 곰 '쥬니'가 엔트리를 찾아 왔어요! \",\n    junior_naver_contents_2: '그런데 쥬니는 길을 찾는 것이 아직 어렵나봐요.',\n    junior_naver_contents_3: '쥬니가 엔트리봇을 만날 수 있도록 가야하는 방향을 알려주세요~',\n    basic_content: '기초',\n    jr_help: '도움말',\n    help: '도움말',\n    cparty_robot_intro_1:\n        '안녕 나는 엔트리봇이야. 난 부품을 얻어서 내몸을 고쳐야해. 앞으로 가기 블록으로 부품을 얻게 도와줘!',\n    cparty_robot_intro_2:\n        '좋아! 앞에도 부품이 있는데 이번에는 잘못 가다간 감전되기 쉬울 것 같아. 뛰어넘기 블록을 써서 부품까지 데려다 줘.',\n    cparty_robot_intro_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 회전하기 블록을 쓰면 충분히 갈 수 있을 것 같아! ',\n    cparty_robot_intro_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 회전과 뛰어넘기를 같이 써서 저 부품을 얻어보자! ',\n    cparty_robot_intro_5:\n        '덕분에 몸이 아주 좋아졌어! 이번에도 회전과 뛰어넘기를 같이 써야 할 거야! 어서 가보자!',\n    cparty_robot_intro_6:\n        '멋져! 이제 몸이 많이 좋아져서, 똑같은 일은 여러 번 해도 괜찮을 거야! 한 번 반복하기를 사용해서 가보자!',\n    cparty_robot_intro_7:\n        '어? 중간중간에 뛰어넘어야 할 곳이 있어! 그래도 반복하기로 충분히 갈 수 있을 거야!',\n    cparty_robot_intro_8:\n        '이런! 이번에는 부품이 저기 멀리 떨어져 있어. 그래도 반복하기를 사용하면 쉽게 갈수 있지! 얼른 도와줘!',\n    cparty_robot_intro_9:\n        '우와~ 이제 내 몸이 거의 다 고쳐진 것 같아! 이번에도 반복하기를 이용해서 부품을 구하러 가보자!',\n    cparty_robot_intro_10:\n        '대단해! 이제 마지막 부품만 있으면 내 몸을 완벽하게 고칠 수 있을 거야! 빨리 반복하기로 도와줘!',\n    cparty_car_intro_1:\n        '안녕! 나는 엔트리봇이라고 해, 자동차를 타고 계속 이동하려면 연료가 필요해! 앞에 있는 연료를 얻을 수 있게 도와줄래?',\n    cparty_car_intro_2:\n        '좋아! 그런데 이번에는 길이 직선이 아니네! 왼쪽/오른쪽 돌기 블록으로 잘 운전해서 함께 연료를 얻으러 가볼까?',\n    cparty_car_intro_3:\n        '잘했어! 이번 길 앞에는 과속방지턱이 있어. 빠르게 운전하면 사고가 날 수도 있을 것 같아, 천천히 가기 블록을 써서 연료를 얻으러 가보자!',\n    cparty_car_intro_4:\n        '야호, 이제 운전이 한결 편해졌어! 이 도로에서는 반복하기 블록을 사용해서 연료를 채우러 가볼까?',\n    cparty_car_intro_5:\n        '와 이번 도로는 조금 복잡해 보이지만, 앞으로 가기와 왼쪽/오른쪽 돌기 블록을 반복하면서 가보면 돼! 차분하게 연료까지 가보자',\n    cparty_car_intro_6:\n        '이번에는 도로에 장애물이 있어서 잘 돌아가야 될 것 같아, 만약에 장애물이 앞에 있다면 어떻게 해야 하는지 알려줘!',\n    cparty_car_intro_7:\n        '좋아 잘했어! 한번 더 만약에 블록을 사용해서 장애물을 피해 연료를 얻으러 가보자!',\n    cparty_car_intro_8:\n        '앗 아까 만났던 과속 방지턱이 두 개나 있네, 천천히 가기 블록을 이용해서 안전하게 연료를 채우러 가보자!',\n    cparty_car_intro_9:\n        '복잡해 보이는 길이지만, 앞에서 사용한 반복 블록과 만약에 블록을 잘 이용하면 충분히 운전할 수 있어, 연료를 채울 수 있도록 도와줘!',\n    cparty_car_intro_10:\n        '정말 멋져! 블록의 순서를 잘 나열해서 이제 마지막 남은 연료를 향해 힘을 내어 가보자!',\n    cparty_car_popup_prefix_1: '좋아! 연료를 얻었어!',\n    cparty_car_popup_prefix_2:\n        '우왓! 연료를 얻었어! <br> 하지만 연료를 얻기에는 더 적은 블록을 사용해서도 <br> 얻을 수 있는데 다시 해볼래? ',\n    cparty_car_popup_prefix_2_text:\n        '우왓! 연료를 얻었어! <br> 하지만 연료를 얻기에는 더 적은 명령어 사용해서도 <br> 얻을 수 있는데 다시 해볼래? ',\n    cparty_car_popup_suffix:\n        '고마워~ 덕분에 모든 배터리를 얻을 수 있었어~ <br>다음에 또 나랑 놀자~',\n    all_grade: '모든 학년',\n    grade_e3_e4: '초등 3 ~ 4 학년 이상',\n    grade_e5_e6: '초등 5 ~ 6 학년 이상',\n    grade_m1_m3: '중등 1 ~ 3 학년 이상',\n    entry_first_step: '엔트리 첫걸음',\n    entry_monthly: '월간 엔트리',\n    play_sw_2: 'EBS 소프트웨어야 놀자2',\n    entry_programming: '실전, 프로그래밍!',\n    entry_recommanded_course: '엔트리 추천 코스',\n    introduce_course:\n        '누구나 쉽게 보고 따라하면서 재미있고 다양한 소프트웨어를 만들 수 있는 강의 코스를 소개합니다.',\n    all_free: '*강의 동영상, 만들기, 교재 등이 모두 무료로 제공됩니다.',\n    cparty_result_fail_1: '에궁, 그 곳으로는 갈 수 없어. 가야하는 길을 다시 알려줘~',\n    cparty_result_fail_2: '에고고, 아파라. 뛰어 넘었어야 했던 곳이였어. 다시 해보자.',\n    cparty_result_fail_3:\n        '아이고 힘들다. 아래 블록들을 안 썼더니 너무 힘들어! 아래 블록들로 다시 만들어줘.',\n    cparty_result_fail_4: '어? 이제 어디로 가지? 어디로 가야하는 지 더 알려줘~',\n    cparty_result_fail_5: '앗! 과속방지턱에서는 속도를 줄여야해. 천천히 가기 블록을 사용해보자~',\n    cparty_result_success_1: '좋아! 부품을 얻었어!',\n    cparty_result_success_2:\n        '우왓! 부품을 얻었어! <br>하지만 부품을 얻기에는 더 적은 블록을 사용해서도 얻을 수 있는데 다시 해볼래?',\n    cparty_result_success_2_text:\n        '우왓! 부품을 얻었어! <br>하지만 부품을 얻기에는 더 적은 명령어를 사용해서도 얻을 수 있는데 다시 해볼래?',\n    cparty_result_success_3: '고마워~ 덕분에 내몸이 다 고쳐졌어~ 다음에 또 나랑 놀자~',\n    cparty_insert_name: '이름을 입력하세요.',\n    offline_file: '파일',\n    offline_edit: '편집',\n    offline_undo: '되돌리기',\n    offline_redo: '다시실행',\n    offline_quit: '종료',\n    select_one: '선택해 주세요.',\n    evaluate_challenge: '도전해본 미션의 난이도를 평가해 주세요.',\n    very_easy: '매우쉬움',\n    easy: '쉬움',\n    normal: '보통',\n    difficult: '어려움',\n    very_difficult: '매우 어려움',\n    save_dismiss: '바꾼 내용을 저장하지 않았습니다. 계속 하시겠습니까?',\n    entry_info: '엔트리 정보',\n    actual_size: '실제크기',\n    zoom_in: '확대',\n    zoom_out: '축소',\n    cparty_jr_intro_1:\n        '안녕! 난 엔트리봇 이라고 해! 학교가는 길에 책가방을 챙길 수 있도록 도와줘! ',\n    cparty_jr_intro_2: '책가방이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    cparty_jr_intro_3: '책가방이 위쪽에 있어! 책가방을 챙길 수 있도록 도와줘!',\n    cparty_jr_intro_4: '어서 책가방을 챙기러 가자! 아래쪽으로 가보는 거야~',\n    cparty_jr_intro_5: '우왓! 내 책가방이 멀리 떨어져 있어. 책가방이 있는 곳까지 안내해줄래?',\n    cparty_jr_intro_6: '책가방이 있어! 얼른 가지러 가자~',\n    cparty_jr_intro_7: '길 위에 내 연필이 있네. 연필들을 모아 책가방을 챙기러 가보자!',\n    cparty_jr_intro_8: '학교 가는 길에 연필이 있어! 연필을 모아 책가방을 챙기러 가보자!',\n    cparty_jr_intro_9: '내 책가방이 멀리 떨어져 있네? 가장 빠른 길로 책가방을 챙기러 가 보자.',\n    cparty_jr_intro_10: '가는 길에 연필을 모두 모으고 책가방을 챙기자!',\n    cparty_jr_intro_11:\n        '책가방을 챙기러 가려면 오른쪽으로 다섯 번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    cparty_jr_intro_12: '반복하기를 사용해서 책가방을 챙기러 가자.',\n    cparty_jr_intro_13:\n        '지금 블록으로는 책가방이 있는 쪽으로 갈 수가 없어. 반복 횟수를 바꿔 책가방을 챙기러 갈 수 있게 해줘.',\n    cparty_jr_intro_14: '반복 블록을 사용하여 책가방을 챙기러 가줘.',\n    cparty_jr_intro_15:\n        '학교가 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 학교에 도착 할수 있을 거야.',\n    make_new_project: '새로운 작품 만들기',\n    open_old_project: '저장된 작품 불러오기',\n    offline_download: '엔트리 다운로드',\n    offline_release: '엔트리 오프라인 에디터 출시!',\n    offline_description_1: '엔트리 오프라인 버전은',\n    offline_description_2: '인터넷이 연결되어 있지 않아도 사용할 수 있습니다. ',\n    offline_description_3: '지금 다운받아서 시작해보세요!',\n    sw_week_2015: '2015 소프트웨어교육 체험 주간',\n    cparty_desc: '두근두근 소프트웨어와의 첫만남',\n    entry_offline_download: '엔트리 오프라인 \\n다운로드',\n    entry_download_detail: '다운로드\\n바로가기',\n    offline_desc_1: '엔트리 오프라인 버전은 인터넷이 연결되어 있지 않아도 사용할 수 있습니다.',\n    offline_desc_2: '지금 다운받아서 시작해보세요!',\n    download: '다운로드',\n    version: '버전',\n    file_size: '크기',\n    update: '업데이트',\n    use_range: '사용범위',\n    offline_desc_free: '엔트리 오프라인은 기업과 개인 모두 제한 없이 무료로 사용하실 수 있습니다.',\n    offline_required: '최소 요구사항',\n    offline_required_detail: '디스크 여유 공간 1GB 이상, windows7 혹은 MAC OS 10.8 이상',\n    offline_notice: '설치 전 참고사항',\n    offline_notice_1: '1. 버전',\n    offline_notice_1_1: '에서는 하드웨어 연결 프로그램이 내장되어 있습니다.',\n    offline_notice_2: '2. 별도의 웹브라우져가 필요하지 않습니다.',\n    offline_notice_3: '버전 별 변경 사항 안내',\n    offline_notice_4: '버전별 다운로드',\n    offline_notice_5: '버전별 자세한 변경 사항 보기',\n    hardware_online_badge: '온라인',\n    hardware_title: '엔트리 하드웨어 연결 프로그램 다운로드',\n    hardware_desc:\n        '엔트리 온라인 ‘작품 만들기’에서 하드웨어를 연결하여 엔트리를 이용하는 경우에만 별도로 설치가 필요합니다.',\n    hardware_release:\n        '하드웨어 연결 프로그램의 자세한 변경 사항은 아래 주소에서 확인 할 수 있습니다.',\n    hardware_window_download: 'Windows 다운로드',\n    hardware_osx_download: 'Mac 다운로드',\n    cparty_jr_result_2:\n        '고마워~ 덕분에 책가방을 챙겨서 학교에 올 수 있었어~ <br>다음 학교 가는 길도 함께 가자~ ',\n    cparty_jr_result_3:\n        '우왓! 학교까지 왔어! <br>하지만 더 적은 블록을 사용해도 학교에 갈 수 있는데<br> 다시 해볼래?',\n    cparty_jr_result_4:\n        '우왓! 책가방을 얻었어!<br> 하지만 더 적은 블록을 사용해도 책가방을 얻을 수 있는데 <br>다시 해볼래? ',\n    lms_no_class: '아직 만든 학급이 없습니다.',\n    lms_create_class: '학급을 만들어 주세요.',\n    lms_add_class: '학급 만들기',\n    lms_base_class: '기본',\n    lms_delete_class: '삭제',\n    lms_my_class: '나의 학급',\n    lms_grade_1: '초등 1',\n    lms_grade_2: '초등 2',\n    lms_grade_3: '초등 3',\n    lms_grade_4: '초등 4',\n    lms_grade_5: '초등 5',\n    lms_grade_6: '초등 6',\n    lms_grade_7: '중등 1',\n    lms_grade_8: '중등 2',\n    lms_grade_9: '중등 3',\n    lms_grade_10: '일반',\n    lms_add_groupId_personal: '선생님께 받은 학급 아이디를 입력하여, 회원 정보에 추가하세요.',\n    lms_add_groupId: '학급 아이디 추가하기',\n    lms_add_group_account: '학급 계정 추가',\n    lms_enter_group_info: '발급받은 학급 아이디와 비밀번호를 입력하세요.',\n    lms_group_id: '학급 아이디',\n    lms_group_pw: '비밀번호',\n    lms_group_name: '소속 학급명',\n    personal_pwd_alert: '올바른 비밀번호 양식을 입력해 주세요',\n    personal_form_alert: '양식을 바르게 입력해 주세요',\n    personal_form_alert_2: '모든 양식을 완성해 주세요',\n    personal_no_pwd_alert: '비밀번호를 입력해 주세요',\n    select_gender: '성별을 선택해 주세요',\n    enter_group_id: '학급 아이디를 입력해 주세요',\n    enter_group_pwd: '비밀번호를 입력해 주세요',\n    info_added: '추가되었습니다',\n    no_group_id: '학급 아이디가 존재하지 않습니다',\n    no_group_pwd: '비밀번호가 일치하지 않습니다',\n    lms_please_choice: '선택해 주세요.',\n    group_lesson: '나의 학급 강의',\n    lms_banner_add_group: '학급 기능 도입',\n    lms_banner_entry_group: '엔트리 학급 만들기',\n    lms_banner_desc_1: '우리 반 학생들을 엔트리에 등록하세요!',\n    lms_banner_desc_2: '이제 보다 편리하고 쉽게 우리 반 학생들의 작품을 찾고,',\n    lms_banner_desc_3: '성장하는 모습을 확인할 수 있습니다. ',\n    lms_banner_download_manual: '메뉴얼 다운로드',\n    lms_banner_detail: '자세히 보기',\n    already_exist_email: '이미 존재하는 이메일 입니다.',\n    same_registered_email: '중복된 이메일 입니다.',\n    email_correnctly_please: '양식을 올바르게 입력해주세요.',\n    remove_project: '작품을 삭제하시겠습니까?',\n    study_lesson: '우리 반 학습하기',\n    open_project: '작품 불러오기',\n    make_group: '학급 만들기',\n    project_share: '작품 공유하기',\n    group_project_share: '학급 공유하기',\n    group_discuss: '학급 글 나누기',\n    my_profile: '마이 페이지',\n    search_updated: '최신 작품',\n    search_recent: '최근 조회수 높은 작품',\n    search_complexity: '최근 제작에 공들인 작품',\n    search_staffPicked: '스태프선정 작품 저장소',\n    search_childCnt: '사본이 많은 작품',\n    search_likeCnt: '최근 좋아요가 많은 작품',\n    search_recentLikeCnt: '최근 좋아요가 많은 작품',\n    gnb_share: '공유하기',\n    gnb_community: '커뮤니티',\n    lms_add_lectures: '강의 올리기',\n    lms_add_course: '강의 모음 올리기',\n    lms_add_homework: '과제 올리기',\n    remove_lecture_confirm: '강의를 정말 삭제하시겠습니까?',\n    popup_delete: '삭제하기',\n    remove_course_confirm: '강의 모음을 정말 삭제하시겠습니까?',\n    lms_no_lecture_teacher_1: '추가된 강의가 없습니다.',\n    lms_no_lecture_teacher_2: '우리 반 강의를 추가해 주세요.',\n    gnb_download: '다운로드',\n    lms_no_lecture_student_1: '아직 올라온 강의가 없습니다.',\n    lms_no_lecture_student_2: '선생님이 강의를 올려주시면,',\n    lms_no_lecture_student_3: '학습 내용을 확인할 수 있습니다.',\n    lms_no_class_teacher: '아직 만든 학급이 없습니다.',\n    lms_no_course_teacher_1: '추가된 강의 모음이 없습니다.',\n    lms_no_course_teacher_2: '우리 반 강의 모음을 추가해 주세요.',\n    lms_no_course_student_1: '아직 올라온 강의 모음이 없습니다.',\n    lms_no_course_student_2: '선생님이 강의 모음을  올려주시면,',\n    lms_no_course_student_3: '학습 내용을 확인할 수 있습니다.',\n    lms_no_hw_teacher_1: '추가된 과제가 없습니다.',\n    lms_no_hw_teacher_2: '우리 반 과제를 추가해 주세요.',\n    lms_no_hw_student_1: '아직 올라온 과제가 없습니다.',\n    lms_no_hw_student_2: '선생님이 과제를 올려주시면,',\n    lms_no_hw_student_3: '학습 내용을 확인할 수 있습니다.',\n    modal_edit: '수정하기',\n    modal_deadline: '마감일 설정',\n    modal_hw_desc: '상세설명 (선택)',\n    desc_optional: '',\n    modal_create_hw: '과제 만들기',\n    vol: '회차',\n    hw_title: '과제명',\n    hw_description: '내용',\n    deadline: '마감일',\n    do_homework: '과제하기',\n    hw_progress: '진행 상태',\n    hw_submit: '제출',\n    view_list: '명단보기',\n    view_desc: '내용보기',\n    do_submit: '제출하기',\n    popup_notice: '알림',\n    no_selected_hw: '선택된 과제가 없습니다.',\n    hw_delete_confirm: '선택한 과제를 정말 삭제하시겠습니까?',\n    hw_submitter: '과제 제출자 명단',\n    hw_student_desc_1: \"* '제출하기'를 눌러 제출을 완료하기 전까지 얼마든지 수정이 가능합니다\",\n    hw_student_desc_2: '* 제출 기한이 지나면 과제를 제출할 수 없습니다.',\n    popup_create_class: '학급 만들기',\n    class_name: '학급 이름',\n    image: '이미지',\n    select_class_image: '학급 이미지를 선택해 주세요.',\n    type_class_description: '학급 소개 입력',\n    set_as_primary_group: '기본학급으로 지정',\n    set_primary_group: '지정',\n    not_primary_group: '지정안함',\n    type_class_name: '학급 이름을 입력해주세요. ',\n    type_class_description_long: '학급 소개를 입력해 주세요. 170자 이내',\n    add_students: '학생 추가하기',\n    invite_students: '학생 초대하기',\n    invite_with_class: '1. 학급 코드로 초대하기',\n    invite_code_expiration: '코드 만료시간',\n    generate_code_button: '코드재발급',\n    generate_code_desc: '학생의 학급 코드 입력 방법',\n    generate_code_desc1: '엔트리 홈페이지에서 로그인을 해주세요.',\n    generate_code_desc2: '메뉴바에서<나의 학급>을 선택해주세요.',\n    generate_code_desc3: '<학급코드 입력하기>를 눌러 학급코드를 입력해주세요.',\n    invite_with_url: '2. 학급 URL로 초대하기',\n    copy_invite_url: '복사하기',\n    download_as_pdf: '학급계정 PDF로 내려받기',\n    download_as_excel: '학급계정 엑셀로 내려받기',\n    temp_password: '임시 비밀번호 발급',\n    step_name: '이름 입력',\n    step_info: '정보 추가/수정',\n    preview: '미리보기',\n    type_name_enter: '학급에 추가할 학생의 이름을 입력하고 엔터를 치세요.',\n    multiple_name_possible: '여러명의 이름 입력이 가능합니다.',\n    id_auto_create: '학번은 별도로 수정하지 않으면 자동으로 생성됩니다.',\n    student_id_desc_1: '학급 아이디는 별도의 입력없이 자동으로 생성됩니다.',\n    student_id_desc_2: '단, 엔트리에 이미 가입된 학생을 학급에 추가한다면 학생의 엔트리 아이디를',\n    student_id_desc_3: '입력해주세요. 해당 학생은 로그인 후, 학급 초대를 수락하면 됩니다.',\n    student_number: '학번',\n    temp_password_desc_1: '임시 비밀번호로 로그인 후,',\n    temp_password_desc_2: '신규 비밀번호를 다시 설정할 수 있도록 안내해주세요.',\n    temp_password_desc_3: '*한번 발급된 임시 비밀번호는 다시 볼 수 없습니다.',\n    temp_password_demo: '로그인 불가능한 안내 용 예시 계정입니다.',\n    temp_works: '작품 보기',\n    student_delete_confirm: '학생을 정말 삭제하시겠습니까?',\n    no_student_selected: '선택된 학생이 없습니다.',\n    class_assignment: '학급 과제',\n    class_list: '학급 목록',\n    select_grade: '학년을 선택 하세요.',\n    add_project: '작품 공유하기',\n    no_project_display: '학생들이 전시한 작품이 없습니다.',\n    plz_display_project: '나의 작품을 전시해 주세요.',\n    refuse_confirm: '학급 초대를 정말 거절하시겠습니까?',\n    select_class: '학급 선택',\n    group_already_registered: '이미 가입된 학급입니다.',\n    my_page_entry: '엔트리',\n    my_page_title: '마이페이지',\n    my_classGroup_title: '나의 학급',\n    my_classGroup_title_view: '나의 학급 보기',\n    my_space_area: '나만의 공간',\n    mon: '월',\n    tue: '화',\n    wed: '수',\n    thu: '목',\n    fri: '금',\n    sat: '토',\n    sun: '일',\n    jan: '1월',\n    feb: '2월',\n    mar: '3월',\n    apr: '4월',\n    may: '5월',\n    jun: '6월',\n    jul: '7월',\n    aug: '8월',\n    sep: '9월',\n    oct: '10월',\n    nov: '11월',\n    dec: '12월',\n    plz_select_lecture: '강의를 선택해 주세요.',\n    plz_set_deadline: '마감일을 설정해 주세요.',\n    hide_entry: '엔트리 가리기',\n    hide_others: '기타 가리기',\n    show_all: '모두 보기',\n    lecture_description:\n        '선생님들이 직접 만드는 엔트리 학습 공간입니다. 강의에서 예시작품을 보고 작품을 만들며 배워 보세요.',\n    curriculum_description:\n        '학습 순서와 주제에 따라 여러 강의가 모아진 학습 공간입니다. 강의 모음의 순서에 맞춰 차근차근 배워보세요.',\n    linebreak_off_desc_1: '글상자의 크기가 글자의 크기를 결정합니다.',\n    linebreak_off_desc_2: '내용을 한 줄로만 작성할 수 있습니다.',\n    linebreak_off_desc_3: '새로운 글자가 추가되면 글상자의 좌우 길이가 길어집니다.',\n    linebreak_on_desc_1: '글상자의 크기가 글자가 쓰일 수 있는 영역을 결정합니다.',\n    linebreak_on_desc_2: '내용 작성시 엔터키로 줄바꿈을 할 수 있습니다.',\n    linebreak_on_desc_3:\n        '새로운 글자 추가 시 문장의 길이가 글상자의 가로 영역을 넘어가면 자동으로 줄이 바뀝니다.',\n    not_supported_text: '해당 글씨체는 한자를 지원하지 않습니다.',\n    entry_with: '함께 만드는 엔트리',\n    ebs_season_1: '시즌 1 보러가기',\n    ebs_season_2: '시즌 2 보러가기',\n    hello_ebs: '헬로! EBS 소프트웨어',\n    hello_ebs_desc:\n        '<헬로! EBS 소프트웨어> 엔트리 버전의 양방향 서비스를 만나보세요! \\n <헬로! EBS 소프트웨어>의 동영상 강의를 통해 \\n 소프트웨어 코딩의 기본 개념을 배운 후 양방향 코딩 미션에 도전하세요!\\n 방송에서는 볼 수 없었던 <대.소.동> 친구들의 \\n 비하인드 스토리를 볼 수 있습니다!',\n    hello_ebs_sub_1: 'EBS 중학 엔트리 버전의 양방향 서비스를 ',\n    hello_ebs_sub_2: '만나보세요! ',\n    exhibit_4th_title: '엔트리 4주년 기념',\n    exhibit_4th_subtitle: '엔트리 작품 공모전',\n    exhibit_4th_desc1: '엔트리 탄생 4주년을 기념하여 작품 공모전을 개최합니다.',\n    exhibit_4th_desc2: '‘우리 모두를 위한 소프트웨어’를 주제로',\n    exhibit_4th_desc3: '여러분의 멋진 작품을 뽐내보세요!',\n    exhibit_4th_button: '자세히 보기',\n    visang_edu_entry: '비상교육 엔트리 학습하기',\n    cmass_edu_entry: '씨마스 엔트리 학습하기',\n    chunjae_edu_entry: '천재교과서 엔트리 학습하기',\n    kumsungemt_edu_entry: '금성출판사 엔트리 학습하기',\n    kumsungMid_edu_entry: '금성출판사 엔트리 학습하기',\n    gilbutEdu_edu_entry: '길벗출판사 엔트리 학습하기',\n    miraenCoding_edu_entry: '미래엔 엔트리 학습하기',\n    textbook_help_data: '도움자료',\n    textbook_teaching_activity: '수업 교안&활동지',\n    textbook_kyohacksa: '교학사',\n    textbook_kumsung: '금성출판사',\n    textbook_donga: '동아출판',\n    textbook_chunjae: '천재교과서',\n    textbook_miraen: '미래엔',\n    textbook_visang: '비상교육',\n    partner: '파트너',\n    project_term_popup_title: '작품 공개에 따른 엔트리 저작권 정책 동의',\n    project_term_popup_description_1: '작품 공개를 위해',\n    project_term_popup_description_2: '아래 정책을 확인해주세요.',\n    project_term_popup_description_3: '',\n    project_term_popup_description_4: '',\n    project_term_agree_1_1: '내가 만든 작품과 그 소스코드의 공개를 동의합니다.',\n    project_term_agree_2_1: '다른 사람이 나의 작품을 이용하는 것을 허락합니다.',\n    project_term_agree_2_2: '( 복제 , 배포 , 공중송신 포함 )',\n    project_term_agree_3_1: '다른 사람이 나의 작품을 수정하는 것을 허락합니다.',\n    project_term_agree_3_2: '( 리믹스, 변형, 2차 제작물 작성 포함)',\n    agree_all: '전체 동의',\n    select_login: '로그인 선택',\n    select: '선택하세요',\n    with_login: '로그인 하고',\n    without_login: '로그인 안하고',\n    start_challenge: '미션 도전하기',\n    start_challenge_2: '미션 도전하기',\n    if_not_save_not_login: '* 로그인을 안하고 미션에 참여하시면 진행 상황이 저장되지 않습니다.',\n    if_not_member_yet: '엔트리 회원이 아니라면?',\n    join_entry: '엔트리 회원 가입하기',\n    learned_computing: '기존에 소프트웨어 교육을 받아보셨나요?',\n    cparty_index_description_1: '두근두근 소프트웨어와 첫 만남.',\n    cparty_index_description_2:\n        '소프트웨어랑 재미있게 놀다 보면 소프트웨어의 원리도 배우고,  생각하는 힘도 쑥쑥!',\n    cparty_index_description_3: '엔트리를 통해 코딩 미션에 도전하고 인증서 받으세요.',\n    cparty_index_description_4: '2015 Online Coding Party는',\n    cparty_index_description_5: 'SW교육 체험 주간',\n    cparty_index_description_6: '의 일환으로써,',\n    cparty_index_description_7: '초등컴퓨팅교사협회',\n    cparty_index_description_8: '과 함께 만들어졌습니다.',\n    cparty_index_description_9: '2016 Online Coding Party는',\n    cparty_index_description_10: '2017 Online Coding Party는',\n    cparty_index_description_11: \"'SW교육을 준비하는 선생님들의 모임'\",\n    congratulation: '축하 드립니다!',\n    warm_up: '체험',\n    beginner: '입문',\n    intermediate: '기본',\n    advanced: '발전',\n    applied: '응용',\n    cert_msg_tail: '과정을 성공적으로 마쳤습니다.',\n    cert_msg_head: '',\n    maze_text_content_1:\n        '안녕? 나는 엔트리봇이야. 지금 나는 공장에서 탈출을 해야 해! 탈출하기 위해서 먼저 몸을 고쳐야 할 것 같아. 앞에 있는 부품을 얻을 수 있게 도와줄래? move()',\n    maze_text_content_2:\n        '좋아 아주 잘했어! 덕분에 몸이 한결 가벼워졌어! 이번에도 부품상자까지 나를 이동시켜줘. 그런데 가는길에 장애물이 있어. 장애물 앞에서는 jump()',\n    maze_text_content_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 오른쪽, 왼쪽으로 회전할 수 있는 right(); left(); 명령어를 쓰면 충분히 갈 수 있을것 같아!',\n    maze_text_content_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 지금까지 배운 명령어를 같이 써서 저 부품상자까지 가보자!',\n    maze_text_content_5:\n        '우와 부품이 두 개나 있잖아! 두 개 다 챙겨서 가자! 그러면 몸을 빨리 고칠 수 있을 것 같아!',\n    maze_text_content_6:\n        '이번이 마지막 부품들이야! 저것들만 있으면 내 몸을 다 고칠 수 있을 거야! 이번에도 도와줄 거지?',\n    maze_text_content_7:\n        '덕분에 몸이 아주 좋아졌어! 이제 똑같은 일을 여러 번 반복해도 무리는 없을 거야. 어? 그런데 앞에 있는 저 로봇은 뭐지? 뭔가 도움이 필요한 것 같아! 도와주자! for 명령어를 사용해서 저 친구한테 나를 데려다줘!',\n    maze_text_content_8:\n        '좋아! 덕분에 친구 로봇을 살릴 수 있었어! 하지만 앞에도 도움이 필요한 친구가 있네, 하지만 이번에는 벌집이 있으니까 조심해서 벌집에 안 닿게 뛰어넘어가자! 할 수 있겠지? 이번에도 for 명령어를 사용해서 친구가 있는곳까지 나를 이동시켜줘!',\n    maze_text_content_9:\n        '이번에는 for 명령어 대신 미션이 끝날때까지 같은 일을 반복하도록 하는 while 명령어를 사용해봐! 나를 친구에게 데려다주면 미션이 끝나!',\n    maze_text_content_10:\n        '이번에는 if 명령어가 나왔어! if와 while 명령어를 사용해서 내가 언제 어느 쪽으로 회전해야 하는지 알려줘!',\n    maze_text_content_11:\n        '좋아 아까 했던 것처럼 해볼까? 언제 왼쪽으로 돌아야 하는지 알려줄 수 있겠어?',\n    maze_text_content_12: '이번에는 중간중간 벌집(bee)이 있네? 언제 뛰어넘어가야 할지 알려줄래?',\n    maze_text_content_13: '여기저기 도움이 필요한 친구들이 많이 있네! 모두 가서 도와주자!',\n    maze_text_content_14:\n        '우와 이번에도 도와줘야 할 친구들이 많네. 먼저 조그마한 사각형을 돌도록 명령어를 만들고 만든 걸 반복해서 모든 친구를 구해보자.',\n    maze_text_content_15:\n        '오래 움직이다 보니 벌써 지쳐버렸어. 자주 쓰는 명령어를 function 명령어를 사용해서 함수로 만들어 놓았어! 함수를 사용하여 나를 배터리 까지 이동시켜줘!',\n    maze_text_content_16:\n        '좋아 멋진걸! 그럼 이번에는 함수에 들어갈 명령어들을 넣어서 나를 배터리까지 이동시켜줘!',\n    maze_text_content_17:\n        '좋아 이번에는 함수를 만들고, 함수를 사용해서 배터리를 얻을 수 있도록 도와줘! 함수를 만들때 jump();를 잘 섞어봐!',\n    maze_text_content_18:\n        '이번에는 길이 좀 복잡한걸? 그래도 언제 left();를 쓰고, 언제 right();를 쓰면 되는지 알려만 주면 배터리 까지 갈 수 있겠어!.',\n    maze_text_content_19:\n        '이번에는 함수가 미리 정해져 있어! 그런데 함수만 써서 배터리까지 가기 힘들것 같아. 함수와 다른 명령어들을 섞어 써서 배터리 까지 이동시켜줘!',\n    maze_text_content_20:\n        '좋아! 지금까지 정말 멋지게 잘 해줬어. 덕분에 이제 마지막 배터리만 채우면 앞으로는 충전이 필요 없을 거야. 함수를 이용해서 저 배터리를 얻고 내가 자유롭게 살 수 있도록 도와줘!',\n    maze_content_1:\n        '안녕 나는 엔트리봇이라고 해. 지금 나는 공장에서 탈출하려는데 먼저 몸을 고쳐야 할 것 같아. 앞에 있는 부품을 얻을 수 있게 도와줄래? 앞으로 가기 블록을 조립하고 시작을 눌러봐.',\n    maze_content_2:\n        '좋아 아주 잘했어! 덕분에 몸이 한결 가벼워졌어! 앞에도 부품이 있는데 이번에는 잘못 가다간 감전되기 쉬울 것 같아. 한 번 장애물 뛰어넘기 블록을 써서 부품까지 가볼까?',\n    maze_content_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 회전하기 블록을 쓰면 충분히 갈 수 있을 것 같아! 이번에도 도와줄 거지?',\n    maze_content_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 회전과 뛰어넘기를 같이 써서 저 부품을 얻어보자!',\n    maze_content_5:\n        '우와 부품이 두 개나 있잖아! 두 개 다 챙겨서 가자! 그러면 몸을 빨리 고칠 수 있을 것 같아!',\n    maze_content_6:\n        '이번이 마지막 부품들이야! 저것들만 있으면 내 몸을 다 고칠 수 있을 거야! 이번에도 도와줄 거지?',\n    maze_content_7:\n        '덕분에 몸이 아주 좋아졌어! 이제 똑같은 일을 여러 번 반복해도 무리는 없을 거야. 어? 그런데 앞에 있는 저 로봇은 뭐지? 뭔가 도움이 필요한 것 같아! 도와주자! 얼른 반복하기의 숫자를 바꿔서 저 친구한테 나를 데려다줘!',\n    maze_content_8:\n        '좋아! 덕분에 친구 로봇을 살릴 수 있었어! 하지만 앞에도 도움이 필요한 친구가 있는 것 같아, 하지만 이번에는 벌집이 있으니까 조심해서 벌집에 안 닿게 뛰어넘어가자! 할 수 있겠지? 그럼 아까 했던 것처럼 반복을 써서 친구한테 갈 수 있게 해줄래?',\n    maze_content_9:\n        '이번에는 숫자만큼 반복하는 게 아니라 친구 로봇한테 갈 때까지 똑같은 일을 반복할 수 있어! 이번에도 친구를 구할 수 있도록 도와줘!',\n    maze_content_10:\n        '이번에는 만약 블록이란 게 있어! 만약 블록을 써서 언제 어느 쪽으로 돌아야 하는지 알려줘!',\n    maze_content_11: '좋아 아까 했던 것처럼 해볼까? 언제 왼쪽으로 돌아야 하는지 알려줄 수 있겠어?',\n    maze_content_12: '이번에는 중간중간 벌집이 있네? 언제 뛰어넘어가야 할지 알려줄래?',\n    maze_content_13: '여기저기 도움이 필요한 친구들이 많이 있네! 모두 도와주자!',\n    maze_content_14:\n        '우와 이번에도 도와줘야 할 친구들이 많네. 먼저 조그마한 사각형을 돌도록 블록을 만들고 만든 걸 반복해서 모든 친구를 구해보자.',\n    maze_content_15:\n        '반복을 하도 많이 했더니 자주 쓰는 블록은 외울 수 있을 것 같아! 약속 블록은 지금 내가 외운 블록들이야! 일단은 오래 움직여서 지쳤으니까 배터리를 좀 채울 수 있게 약속 호출 블록을 써서 배터리를 채울 수 있게 해줘!',\n    maze_content_16:\n        '좋아 멋진걸! 그럼 이번에는 네가 자주 쓰일 블록을 나한테 가르쳐줘! 약속 정의 블록 안에 자주 쓰일 블록을 넣어보면 돼!',\n    maze_content_17:\n        '좋아 이번에도 그러면 약속을 이용해서 배터리를 얻을 수 있도록 도와줄 거지? 약속에 뛰어넘기를 잘 섞어봐!',\n    maze_content_18:\n        '이번에는 길이 좀 복잡한걸? 그래도 언제 왼쪽으로 돌고, 언제 오른쪽으로 돌면 되는지 알려만 주면 충전할 수 있을 것 같아.',\n    maze_content_19:\n        '이번에는 약속이 미리 정해져 있어! 그런데 바로 약속을 쓰기에는 안될 것 같아. 내가 갈 길을 보고 약속을 쓰면 배터리를 채울 수 있을 것 같은데 도와줄 거지?',\n    maze_content_20:\n        '좋아! 지금까지 정말 멋지게 잘 해줬어. 덕분에 이제 마지막 배터리만 채우면 앞으로는 충전이 필요 없을 거야. 그러니까 약속을 이용해서 저 배터리를 얻고 내가 자유롭게 살 수 있도록 도와줄래?',\n    maze_content_21:\n        '안녕? 나는 엔트리 봇이야. 지금 많은 친구들이 내 도움을 필요로 하고 있어. 반복하기를 이용해서 친구들을 도울수 있게 데려다 줘!',\n    maze_content_22: '고마워! 이번에는 벌집을 뛰어넘어서 친구를 구하러 갈 수 있게 도와줘!',\n    maze_content_23:\n        '좋아! 이번에는 친구 로봇한테 갈 때까지 반복하기를 이용해서 친구를 도울 수 있게 도와줘!',\n    maze_content_24:\n        '안녕! 나는 엔트리 봇이야. 지금 나는 너무 오래 움직여서 배터리를 채워야 해. 약속 불러오기를 써서 배터리를 채울 수 있도록 도와줘!',\n    maze_content_25: '멋져! 이번에는 여러 약속을 불러와서 배터리가 있는 곳까지 가보자!',\n    maze_content_26:\n        '좋아! 이제 약속할 블록을 나한테 가르쳐줘! 약속하기 블록 안에 자주 쓰일 블록을 넣으면 돼!',\n    maze_content_27:\n        '지금은 미리 약속이 정해져 있어. 그런데, 약속을 쓰기위해서는 내가 갈 방향을 보고 약속을 사용해야해. 도와줄거지?',\n    maze_content_28: '드디어 마지막이야! 약속을 이용하여 마지막 배터리를 얻을 수 있게 도와줘!',\n    ai_content_1:\n        '안녕? 나는 엔트리봇이라고 해. 우주 탐사를 마치고 지구로 돌아가려는데 우주를 떠다니는 돌들 때문에 쉽지 않네. 내가 안전하게 집에 갈 수 있도록 도와줄래? 나의 우주선에는 나의 앞과 위, 아래에 무엇이 어느 정도의 거리에 있는지 알려주는 레이더가 있어 너의 판단을 도와줄 거야!',\n    ai_content_2:\n        '고마워! 덕분에 돌을 쉽게 피할 수 있었어. 그런데 이번엔 더 많은 돌이 있잖아? 블록들을 조립하여 돌들을 이리저리 잘 피해 보자!',\n    ai_content_3:\n        '좋았어! 안전하게 돌을 피했어. 그런데 앞을 봐! 아까보다 더 많은 돌이 있어. 하지만 걱정하지 마. 나에게 반복하기 블록이 있거든. 반복하기 블록 안에 움직이는 블록을 넣으면 목적지에 도착할 때까지 계속 움직일게!',\n    ai_content_4:\n        '대단해! 반복하기 블록을 쓰니 많은 돌을 피하기가 훨씬 수월한걸! 하지만 이렇게 일일이 조종하기는 피곤하다. 나에겐 레이더가 있으니 앞으로 무엇이 나올지 알 수 있어. 앞으로 계속 가다가 앞에 돌이 있으면 피할 수 있도록 해줄래?',\n    ai_content_5:\n        '잘했어! 여기까지 와서 아주 기뻐. 이번에는 레이더가 앞에 있는 물체까지의 거리를 말해줄 거야. 이 기능을 사용하여 돌을 피해 보자! 돌까지의 거리가 멀 때는 앞으로 계속 가다가, 거리가 가까워지면 피할 수 있도록 해줄래?',\n    ai_content_6:\n        '와~ 멋진걸? 레이더를 활용하여 돌을 잘 피해 나가고 있어! 이번에는 여러 개의 레이더를 사용하여 이리저리 돌들을 피해 나갈 수 있게 만들어줄래?',\n    ai_content_7:\n        '휴~ 지구에 점점 가까워지고 있어! 돌을 피할 때 기왕이면 더 안전한 길로 가고 싶어! 아마도 돌이 더 멀리 있는 쪽이 더 안전한 길이겠지? 위쪽 레이더와 아래쪽 레이더를 비교하여 더 안전한 쪽으로 움직이도록 해줄래?',\n    ai_content_8:\n        '좋아! 덕분에 무사히 비행하고 있어. 어? 그런데 저게 뭐지? 저건 내가 아주 위급한 상황에서 사용할 수 있는 특별한 에너지야! 이번에는 저 아이템들을 모두 모으며 움직이자!',\n    ai_content_9:\n        '훌륭해! 이제 지구까지 얼마 안 남았어. 그런데 앞을 보니 돌들로 길이 꽉 막혀서 지나갈 수가 없잖아? 하지만 걱정하지 마. 아이템을 획득해서 사용하면 앞에 있는 꽉 막힌 돌들을 없앨 수 있다고!',\n    ai_content_10:\n        '좋아! 드디어 저기 지구가 보여! 이럴 수가! 이제는 날아오는 돌들을 미리 볼 수가 없잖아? 돌들이 어떻게 날아올지 알지 못해도 지금까지처럼만 움직이면 잘 피할 수 있을 것 같아! 지구까지 가보는 거야!',\n    maze_hints_title_1: '시작 방법',\n    maze_hints_content_1: '엔트리봇은 어떻게 움직이나요?',\n    maze_hints_detail_1:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐<br>2. 다 조립했으면, 시작을 눌러봐<br>3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_hints_title_2: '장애물 뛰어넘기',\n    maze_hints_content_2: '장애물이 있으면 어떻게 해야하나요?',\n    maze_hints_detail_2:\n        '길을 가다보면 장애물을 만날 수 있어.<br>장애물이 앞에 있을 때에는 뛰어넘기 블록을 사용해야 해.',\n    maze_hints_title_3: '반복 블록(1)',\n    maze_hints_content_3: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_hints_detail_3:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해.<br>반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼.',\n    maze_hints_title_4: '반복 블록(2)',\n    maze_hints_content_4: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_hints_detail_4:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어.<br>반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼.<br>그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_hints_title_5: '만약 블록',\n    maze_hints_content_5: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_hints_detail_5:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어.<br>앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고<br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_hints_title_6: '반복 블록(3)',\n    maze_hints_content_6: '모든 ~를 만날 때 까지 블록은 어떻게 동작하나요?',\n    maze_hints_detail_6:\n        '모든 {타일}에 한 번씩 도착할 때까지 그 안에 있는 블록을 반복해서 실행해.<br>모든 {타일}에 한 번씩 도착하면 반복이 멈추게 될 거야.',\n    maze_hints_title_7: '특별 힌트',\n    maze_hints_content_7: '너무 어려워요. 도와주세요.',\n    maze_hints_detail_7:\n        '내가 가야하는 길을 자세히 봐. 작은 사각형 4개가 보여?<br>작은 사각형을 도는 블록을 만들고, 반복하기를 사용해 보는것은 어때?',\n    maze_hints_title_8: '약속',\n    maze_hints_content_8: '약속하기/약속 불러오기 무엇인가요? 어떻게 사용하나요?',\n    maze_hints_detail_8:\n        \"나를 움직이기 위해 자주 쓰는 블록들의 묶음을 '약속하기' 블록 아래에 조립하여 약속으로 만들 수 있어.<br>한번 만들어 놓은 약속은 '약속 불러오기' 블록을 사용하여 여러 번 꺼내 쓸 수 있다구.\",\n    ai_hints_title_1_1: '게임의 목표',\n    ai_hints_content_1_1: '돌을 피해 오른쪽 행성까지 안전하게 이동할 수 있도록 도와주세요.',\n    ai_hints_detail_1_1: '돌을 피해 오른쪽 행성까지 안전하게 이동할 수 있도록 도와주세요.',\n    ai_hints_title_1_2: '시작 방법',\n    ai_hints_content_1_2: '어떻게 시작할 수 있나요?',\n    ai_hints_detail_1_2:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐<br>2. 다 조립했으면, 시작을 눌러봐<br>3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    ai_hints_title_1_3: '움직이게 하기',\n    ai_hints_content_1_3: '엔트리봇은 어떻게 움직이나요?',\n    ai_hints_detail_1_3:\n        '나는 위쪽으로 가거나 앞으로 가거나 아래쪽으로 갈 수 있어.<br>방향을 정할 때에는 돌이 없는 방향으로 안전하게 갈 수 있도록 해줘.<br>나를 화면 밖으로 내보내면 우주미아가 되어버리니 조심해!',\n    ai_hints_title_2_1: '게임의 목표',\n    ai_hints_content_2_1: '반복하기 블록으로 돌들을 피할 수 있도록 도와주세요.',\n    ai_hints_detail_2_1: '반복하기 블록으로 돌들을 피할 수 있도록 도와주세요.',\n    ai_hints_title_2_2: '반복 블록',\n    ai_hints_content_2_2: '반복 블록은 무슨 블록인가요?',\n    ai_hints_detail_2_2:\n        '휴~ 이번에 가야 할 길은 너무 멀어서 하나씩 조립하기는 힘들겠는걸? 반복하기블록을 사용해봐.<br>똑같이 반복되는 블록들을 반복하기 블록으로 묶어주면 아주 긴 블록을 짧게 줄여줄 수 있어!',\n    ai_hints_content_3_1: '만약 블록으로 돌을 피할 수 있도록 도와주세요.',\n    ai_hints_title_3_2: '만약 블록(1)',\n    ai_hints_content_3_2: '만약 ~라면 블록은 어떻게 동작하나요?',\n    ai_hints_detail_3_2:\n        \"만약 앞에 ~가 있다면 / 아니면 블록을 사용하면 내 바로 앞에 돌이 있는지 없는지 확인해서 다르게 움직일 수 있어~<br>만약 내 바로 앞에 돌이 있다면 '만약' 아래에 있는 블록들을 실행하고 돌이 없으면 '아니면' 안에 있는 블록들을 실행할 거야.<br>내 바로 앞에 돌이 있을 때와 없을 때, 어떻게 움직일지 잘 결정해줘~\",\n    ai_hints_content_4_1: '레이더의 사용 방법을 익히고 돌을 피해보세요.',\n    ai_hints_detail_4_1: '레이더의 사용 방법을 익히고 돌을 피해보세요.',\n    ai_hints_title_4_2: '레이더(1)',\n    ai_hints_content_4_2: '레이더란 무엇인가요? 어떻게 활용할 수 있나요?',\n    ai_hints_detail_4_2:\n        \"레이더는 지금 내가 물체와 얼마나 떨어져 있는지 알려주는 기계야.<br>만약 바로 내 앞에 무엇인가 있다면 앞쪽 레이더는 '1'을 보여줘.<br>또, 레이더는 혼자 있을 때 보다 만약 &lt;사실&gt;이라면 / 아니면 블록과<br> 같이 쓰이면 아주 강력하게 쓸 수 있어.<br>예를 들어 내 앞에 물체와의 거리가 1보다 크다면 나는 안전하게 앞으로 갈 수 있겠지만, 아니라면 위나 아래쪽으로 피하도록 할 수 있지.\",\n    ai_hints_title_4_3: '만약 블록(2)',\n    ai_hints_content_4_3: '만약 <사실>이라면 블록은 어떻게 사용하나요?',\n    ai_hints_detail_4_3:\n        \"만약 &lt;사실&gt;이라면 / 아니면 블록은 &lt;사실&gt; 안에 있는 내용이 맞으면 '만약' 아래에 있는 블록을 실행하고, 아니면 '아니면' 아래에 있는 블록을 실행해.<br>어떤 상황에서 다르게 움직이고 싶은 지를 잘 생각해서 &lt;사실&gt; 안에 적절한 판단 조건을 만들어 넣어봐.<br>판단 조건을 만족해서 '만약' 아래에 있는 블록을 실행하고 나면 '아니면' 아래에 있는 블록들은 실행되지 않는다는 걸 기억해!\",\n    ai_hints_content_5_1: '레이더를 활용해 돌을 쉽게 피할 수 있도록 도와주세요.',\n    ai_hints_detail_5_1: '레이더를 활용해 돌을 쉽게 피할 수 있도록 도와주세요.',\n    ai_hints_title_5_2: '만약 블록(3)',\n    ai_hints_content_5_2: '만약 블록이 겹쳐져 있으면 어떻게 동작하나요?',\n    ai_hints_detail_5_2:\n        '만약 ~ / 아니면 블록안에도 만약 ~ / 아니면 블록을 넣을 수 있어! 이렇게 되면 다양한 상황에서 내가 어떻게 행동해야 할지 정할 수 있어.<br>예를 들어 앞에 돌이 길을 막고 있을때와 없을때의 행동을 정한다음, 돌이 있을때의 상황에서도 상황에 따라 위쪽으로 갈지 아래쪽으로 갈지 선택 할 수 있어',\n    ai_hints_title_6_1: '레이더(2)',\n    ai_hints_content_6_1: '위쪽 레이더와 아래쪽 레이더의 값을 비교하고 싶을 땐 어떻게 하나요?',\n    ai_hints_detail_6_1:\n        '([위쪽]레이더) 블록은 위쪽 물체까지의 거리를 뜻하는 블록이야.<br>아래쪽과 위쪽 중에서 어느 쪽에 돌이 더 멀리 있는지 확인하기 위해서 쓸 수 있는 블록이지.<br>돌을 피해가는 길을 선택할 때에는 돌이 멀리 떨어져 있는 쪽으로 피하는게 앞으로 멀리 가는데 유리할거야~',\n    ai_hints_content_7_1: '아이템을 향해 이동하여 돌을 피해보세요.',\n    ai_hints_detail_7_1: '아이템을 향해 이동하여 돌을 피해보세요.',\n    ai_hints_title_7_2: '물체 이름 확인',\n    ai_hints_content_7_2: '앞으로 만날 물체의 이름을 확인해서 무엇을 할 수 있나요?',\n    ai_hints_detail_7_2:\n        '아이템을 얻기위해서는 아이템이 어디에 있는지 확인할 필요가 있어. <br>그럴 때 사용할 수 있는 블록이 [위쪽] 물체는 [아이템]인가? 블록이야.<br>이 블록을 활용하면 아이템이 어느 위치에 있는지 알 수 있고 아이템이 있는 방향으로 움직이도록 블록을 조립할 수 있어.',\n    ai_hints_content_8_1: '아이템을 적절하게 사용해서 돌을 피해보세요.',\n    ai_hints_detail_8_1: '아이템을 적절하게 사용해서 돌을 피해보세요.',\n    ai_hints_title_8_2: '아이템',\n    ai_hints_content_8_2: '아이템은 어떻게 얻고 사용하나요?',\n    ai_hints_detail_8_2:\n        '돌들을 이리저리 잘 피해 나가더라도 앞이 모두 돌들로 꽉 막혀있을 땐 빠져나갈 방법이 없겠지? 그럴 때에는 아이템사용 블럭을 사용해봐. <br>이 블록은 내 앞의 돌들을 모두 없애는 블록이야.<br>단, 아이템이 있어야지만 블록을 사용할 수 있고, 아이템은 이미지를 지나면 얻을 수 있어.',\n    ai_hints_content_9_1: '지금까지 배운 것들을 모두 활용해서 최대한 멀리 가보세요.',\n    ai_hints_detail_9_1: '지금까지 배운 것들을 모두 활용해서 최대한 멀리 가보세요.',\n    ai_hints_title_9_2: '그리고',\n    ai_hints_content_9_2: '그리고 블록은 어떻게 사용하나요?',\n    ai_hints_detail_9_2:\n        '그리고 블록에는 여러개의 조건을 넣을 수 있어, 넣은 모든 조건이 사실일때만 사실이 되어 만약 블록 안에 있는 블록이 실행되고, 하나라도 거짓이 있으면 거짓으로 인식해서 그 안에 있는 블록을 실행하지 않아',\n    maze_text_goal_1: 'move(); 명령어를 사용하여 부품 상자까지 나를 이동시켜줘!',\n    maze_text_goal_2: 'jump(); 명령어로 장애물을 피해 부품 상자까지 나를 이동시켜줘!',\n    maze_text_goal_3: 'left(); right(); 명령어로 부품상자까지 나를 이동시켜줘!',\n    maze_text_goal_4: '여러가지 명령어를 사용하여 부품상자까지 나를 이동시켜줘!',\n    maze_text_goal_5: '두 부품상자에 다 갈 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_6: '두 부품상자에 다 갈 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_7: 'for 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_8: 'for 명령어를 사용하고, 장애물을 피해 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_9: 'while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_10: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_11: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_12: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_13:\n        'while과 for 명령어를 사용하여 모든 친구들을 만날 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_14:\n        'while과 for 명령어를 사용하여 모든 친구들을 만날 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_15: '함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_16: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_17: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_18: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_19: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_20: '함수와 다른명령어들을 섞어 사용하여 배터리까지 나를 이동시켜줘!',\n    maze_attack_range: '공격 가능 횟수',\n    maze_attack: '공격',\n    maze_attack_both_sides: '양 옆 공격',\n    above_radar: '위쪽 레이더',\n    above_radar_text_mode: 'radar_up',\n    bottom_radar: '아래쪽 레이더',\n    bottom_radar_text_mode: 'radar_down',\n    front_radar: '앞쪽 레이더',\n    front_radar_text_mode: 'radar_right',\n    above_object: '위쪽 물체',\n    above_object_text_mode: 'object_up',\n    front_object: '앞쪽 물체',\n    front_object_text_mode: 'object_right',\n    below_object: '아래쪽 물체',\n    below_object_text_mode: 'object_down',\n    destination: '목적지',\n    asteroids: '돌',\n    item: '아이템',\n    wall: '벽',\n    destination_text_mode: 'destination',\n    asteroids_text_mode: 'stone',\n    item_text_mode: 'item',\n    wall_text_mode: 'wall',\n    buy_now: '구매바로가기',\n    goals: '목표',\n    instructions: '이용 안내',\n    object_info: '오브젝트 정보',\n    entry_basic_mission: '엔트리 기본 미션',\n    entry_application_mission: '엔트리 응용 미션',\n    maze_move_forward: '앞으로 한 칸 이동',\n    maze_when_run: '시작하기를 클릭했을때',\n    maze_turn_left: '왼쪽으로 회전',\n    maze_turn_right: '오른쪽으로 회전',\n    maze_repeat_times_1: '',\n    maze_repeat_times_2: '번 반복하기',\n    maze_repeat_until_1: '',\n    maze_repeat_until_2: '을 만날때까지 반복',\n    maze_call_function: '약속 불러오기',\n    maze_function: '약속하기',\n    maze_repeat_until_all_1: '모든',\n    maze_repeat_until_all_2: '만날 때 까지 반복',\n    command_guide: '명령어 도움말',\n    ai_success_msg_1: '덕분에 무사히 지구에 도착할 수 있었어! 고마워!',\n    ai_success_msg_2: '다행이야! 덕분에',\n    ai_success_msg_3:\n        '번 만큼 앞쪽으로 갈 수 있어서 지구에 구조 신호를 보냈어! 이제 지구에서 구조대가 올거야! 고마워!',\n    ai_success_msg_4: '좋았어!',\n    ai_cause_msg_1: '이런, 어떻게 움직여야 할 지 더 말해줄래?',\n    ai_cause_msg_2: '아이쿠! 정말로 위험했어! 다시 도전해보자',\n    ai_cause_msg_3: '우와왓! 가야할 길에서 벗어나버리면 우주 미아가 되버릴꺼야. 다시 도전해보자',\n    ai_cause_msg_4: '너무 복잡해, 이 블록을 써서 움직여볼래?',\n    ai_move_forward: '앞으로 가기',\n    ai_move_above: '위쪽으로 가기',\n    ai_move_under: '아래쪽으로 가기',\n    ai_repeat_until_dest: '목적지에 도달 할 때까지 반복하기',\n    ai_if_front_1: '만약 앞에',\n    ai_if_front_2: '가 있다면',\n    ai_else: '아니면',\n    ai_if_1: '만약',\n    ai_if_2: '이라면',\n    ai_use_item: '아이템 사용',\n    ai_radar: '레이더',\n    ai_above: '위쪽',\n    ai_front: '앞쪽',\n    ai_under: '아래쪽',\n    ai_object_is_1: '',\n    ai_object_is_2: '물체는',\n    challengeMission: '다른 미션 도전하기',\n    nextMission: '다음 미션 도전하기',\n    withTeacher: '함께 만든 선생님들',\n    host: '주최',\n    support: '후원',\n    subjectivity: '주관',\n    learnMore: ' 더 배우고 싶어요',\n    ai_object_is_3: '인가?',\n    stage_is_not_available:\n        '아직 진행할 수 없는 스테이지입니다. 순서대로 스테이지를 진행해 주세요.',\n    progress_not_saved: '진행상황이 저장되지 않습니다.',\n    want_refresh: '이 페이지를 새로고침 하시겠습니까?',\n    monthly_entry_grade: '초등학교 3학년 ~ 중학교 3학년',\n    monthly_entry_contents:\n        '매월 발간되는 월간엔트리와 함께 소프트웨어 교육을 시작해 보세요!  차근차근 따라하며 쉽게 익힐 수 있도록 가볍게 구성되어있습니다. 기본, 응용 콘텐츠와 더 나아가기까지! 매월 업데이트되는 8개의 콘텐츠와 교재를 만나보세요~',\n    monthly_entry_etc1:\n        '*메인 페이지의 월간 엔트리 추천코스를 활용하면 더욱 쉽게 수업을 할 수 있습니다.',\n    monthly_entry_etc2: '*월간엔트리는 학기 중에만 발간됩니다.',\n    group_make_lecture_1: '내가 만든 강의가 없습니다.',\n    group_make_lecture_2: \"'만들기>오픈 강의 만들기'에서\",\n    group_make_lecture_3: '우리반 학습내용에 추가하고 싶은 강의를 만들어 주세요.',\n    group_make_lecture_4: '강의 만들기',\n    group_add_lecture_1: '관심 강의가 없습니다.',\n    group_add_lecture_2: \"'학습하기>오픈 강의> 강의'에서 우리반 학습내용에\",\n    group_add_lecture_3: '추가하고 싶은 강의를 관심강의로 등록해 주세요.',\n    group_add_lecture_4: '강의 보기',\n    group_make_course_1: '내가 만든 강의 모음이 없습니다.',\n    group_make_course_2: \"'만들기 > 오픈 강의 만들기> 강의 모음 만들기'에서\",\n    group_make_course_3: '학습내용에 추가하고 싶은 강의 모음을 만들어 주세요.',\n    group_make_course_4: '강의 모음 만들기',\n    group_add_course_1: '관심 강의 모음이 없습니다.',\n    group_add_course_2: \"'학습하기 > 오픈 강의 > 강의 모음'에서 우리반 학습내용에\",\n    group_add_course_3: '추가하고 싶은 강의 모음을 관심 강의 모음으로 등록해 주세요.',\n    group_add_course_4: '강의 모음 보기',\n    hw_main_title: '프로그램 다운로드',\n    datablock_contest_title: '데이터분석 블록 추가',\n    datablock_content_head: '데이터를 가공하고 표현하기',\n    datablock_content_body1: '생활 속 다양한 데이터를 차트로 표현하고 의미를 찾아',\n    datablock_content_body2: '실생활 문제를 해결해보세요!',\n    campaign_contest_title: '아름다운 인터넷 세상을 만들어요',\n    campaign_content_head: '엔트리 작품 공모전',\n    campaign_content_body1: \"'인터넷윤리'에 대해 알기 쉽고 재미있게\",\n    campaign_content_body2: '작품을 만들어 응모해주세요!',\n    campaign_content_button: '자세히 보기',\n    code_management_1: '엔트리 캠페인 #1 코드 잘 관리하기',\n    code_management_2: '나의 보관함과 메모 활용',\n    code_management_3: '새 기능 나의 보관함과 메모로 하는 코드 관리 비법!',\n    code_management_4: '작품을 더 잘 만들고 쉽게 공유하는 방법을 알아보아요.',\n    code_management_5: '캠페인 보기',\n    shcoolbook_study_1: '교과서 내용 그대로 학습하세요.',\n    shcoolbook_study_2: '교과서 학습하기',\n    shcoolbook_study_3: '선생님은 교실에서 수업 진행을',\n    shcoolbook_study_4: '학생은 집에서 복습을 할 수 있습니다!',\n    shcoolbook_study_5: '학습하기',\n    main_learn_1: '엔트리에 처음 오셨다면',\n    main_learn_2: '엔트리 알아보기',\n    main_learn_3: '영상을 통해 엔트리의 다양한 기능을 알아보고,',\n    main_learn_4: '멋진 작품을 만들어 친구들과 공유해보세요!',\n    main_learn_5: '영상보기',\n    hw_desc_wrapper:\n        '엔트리 하드웨어 연결 프로그램과 오프라인 버전이 \\n서비스를 한층 더 강화해 업그레이드 되었습니다.\\n업데이트 된 프로그램을 설치해주세요!',\n    hw_downolad_link: '하드웨어 연결 \\n프로그램 다운로드',\n    save_as_image_all: '모든 코드 이미지로 저장하기',\n    save_as_image: '이미지로 저장하기',\n    maze_perfect_success: '멋져! 완벽하게 성공했어~',\n    maze_success_many_block_1: '좋아',\n    maze_fail_obstacle_remain:\n        \"친구들이 다치지 않도록 모든 <span class='bitmap_obstacle_spider'></span>을 없애줘.\",\n    maze_fail_item_remain: '샐리 공주를 구하기 위해 모든 미네랄을 모아 와줘.',\n    maple_fail_item_remain:\n        '음식을 다 먹지 못해서 힘이 나지 않아. 모든 음식을 다 먹을 수 있도록 도와줘.',\n    maze_fail_not_found_destory_object: '아무것도 없는 곳에 능력을 낭비하면 안 돼!',\n    maze_fail_not_found_destory_monster: '몬스터가 없는 곳에 공격을 하면 안 돼!',\n    maple_fail_not_found_destory_monster: '공격 블록은 몬스터가 있을 때에만 해야 돼!',\n    maze_fail_more_move: '목적지까지는 좀 더 움직여야 해!',\n    maze_fail_wall_crash: '으앗! 거긴 갈 수 없는 곳이야!',\n    maze_fail_contact_brick: '에구구… 부딪혔다!',\n    maze_fail_contact_iron1: '으앗! 장애물에 부딪혀버렸어',\n    maze_fail_contact_iron2: '으앗! 장애물이 떨어져서 다쳐버렸어. 장애물이 내려오기전에 움직여줘..',\n    maze_fail_fall_hole: '앗, 함정에 빠져 버렸어...',\n    maze_fail_hit_unit:\n        '몬스터에게 당해버렸어! 위험한 몬스터를 물리치기 위해 하트 날리기 블록을 사용해줘!',\n    maze_fail_hit_unit2: '윽, 몬스터에게 공격당했다! 두 칸 떨어진 곳에서 공격해줘!',\n    maze_fail_hit_unit_by_mushroom:\n        \"주황버섯에게 당해버렸어!<br /><img src='/img/assets/maze/icon/mushroom.png' /> 공격하기 블록을 사용해서 나쁜 몬스터를 혼내줘!\",\n    maze_fail_hit_unit_by_lupin:\n        \"루팡에게 당해버렸어!<br /><img src='/img/assets/maze/icon/lupin.png' /> 공격하기 블록을 두 칸 떨어진 곳에서 사용해서 나쁜 몬스터를 혼내줘!\",\n    maze_fail_elnath_fail:\n        '으앗! 나쁜 몬스터가 나를 공격했어.<br/>나쁜 몬스터가 나에게 다가오지 못하게 혼내줘!',\n    maze_fail_pepe: '',\n    maze_fail_yeti:\n        \"그 몬스터는 너무 강해서 <img width='24px' src='/img/assets/week/blocks/yeti.png'/> 공격하기 블록으로는 혼내줄 수 없어<br/><img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> 공격하기 블록을 사용해보자.\",\n    maze_fail_peti:\n        \"그 몬스터에게 <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> 공격하기 블록을 사용하면,<br/>강한 몬스터인 <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/>가 나왔을 때 혼내줄 수 없어<br/><img width='24px' src='/img/assets/week/blocks/yeti.png'/> 공격하기 블록을 사용해보자.\",\n    maze_fail_both_side: '양 옆 공격하기는 양쪽에 몬스터가 있을 때에만 사용해야 돼!',\n    maze_wrong_attack_obstacle:\n        \"이 곳에서는 <img src='/img/assets/maze/icon/lupin.png' /> 공격하기 블록을 사용할 수 없어<br/>주황 버섯에게는 <img src='/img/assets/maze/icon/mushroom.png' /> 공격하기 블록을 사용해보자.\",\n    maze_fail_contact_spider: '거미집에 걸려 움직일 수가 없어...',\n    maze_success_perfect: '멋져! 완벽하게 성공했어~',\n    maze_success_block_excess:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br> 하지만, %2개의 블록만으로 성공하는 방법도 있어. 다시 도전해 보는 건 어때?',\n    maze_success_not_essential:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br>하지만 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maze_success_final_perfect_basic:\n        '좋아! 샐리 공주가 어디 있는지 찾았어! 이제 샐리 공주를 구할 수 있을 거야!',\n    maze_success_final_block_excess_basic:\n        '좋아! 샐리 공주가 어디 있는지 찾았어! 이제 샐리 공주를 구할 수 있을 거야!%1개의 블록을 사용했는데, %2개의 블록만으로 성공하는 방법도 있어. 다시 해볼래?',\n    maze_success_final_perfect_advanced:\n        '샐리 공주가 있는 곳까지 도착했어! 이제 악당 메피스토를 물리치고 샐리를 구하면 돼!',\n    maze_success_final_block_excess_advanced:\n        '샐리 공주가 있는 곳까지 도착했어! 이제 악당 메피스토를 물리치고 샐리를 구하면 돼!%1개의 블록을 사용했는데, %2개의 블록만으로 성공하는 방법도 있어. 다시 해볼래?',\n    maze_success_final_distance:\n        '좋아! 드디어 우리가 샐리 공주를 무사히 구해냈어. 구할 수 있도록 도와줘서 정말 고마워!<br>%1칸 움직였는데 다시 한 번 다시해서 60칸까지 가볼래?',\n    maze_success_final_perfect_ai:\n        '좋았어! 드디어 우리가 샐리 공주를 무사히 구해냈어. 구할 수 있도록 도와줘서 정말 고마워!',\n    maple_success_perfect: '좋아! 완벽하게 성공했어!!',\n    maple_success_block_excess:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br> 그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는건 어때?',\n    maple_success_not_essential:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br>그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_perfect_henesys: '멋져! 헤네시스 모험을 훌륭하게 해냈어.',\n    maple_success_final_perfect_excess_henesys:\n        '멋져! 헤네시스 모험을 잘 해냈어.<br />그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_not_essential_henesys:\n        '멋져! 헤네시스 모험을 잘 해냈어.<br />그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_perfect_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br/>다음 모험도 같이 할거지? ',\n    maple_success_final_perfect_excess_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br />그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_not_essential_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br />그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_fail_fall_hole: '으앗! 빠져버렸어!<br />뛰어넘기 블록을 사용해서 건너가보자.',\n    maple_fail_ladder_fall_hole:\n        '으앗! 빠져버렸어!<br />사다리 타기 블록을 사용해서 다른 길로 가보자.',\n    maple_fail_more_move: '성공하려면 목적지까지 조금 더 움직여야 해!',\n    maple_fail_not_found_ladder:\n        '이런, 여기엔 탈 수 있는 사다리가 없어.<br />사다리 타기 블록은 사다리가 있는 곳에서만 사용 해야해.',\n    maple_fail_not_found_meat:\n        '이런, 여기엔 먹을 수 있는 음식이 없어!<br />음식 먹기 블록은 음식이 있는 곳에서만 사용 해야해.',\n    maple_cert_input_title: '내가 받을 인증서에 적힐 이름은?',\n    maze_distance1: '거리 1',\n    maze_distance2: '거리 2',\n    maze_distance3: '거리 3',\n    ev3: 'EV3',\n    roborobo_roduino: '로두이노',\n    roborobo_schoolkit: '스쿨키트',\n    smartboard: '과학상자 코딩보드',\n    smartboardbt: '과학상자 코딩보드(무선)',\n    codestar: '코드스타',\n    cobl: '코블',\n    cobl_bt: '코블 블루투스',\n    block_coding: '블록코딩',\n    python_coding: '엔트리파이선',\n    dadublock: '다두블럭',\n    dadublock_car: '다두블럭 자동차',\n    blacksmith: '대장장이 보드',\n    course_submit_homework: '과제 제출',\n    course_done_study: '학습 완료',\n    course_show_list: '목록',\n    modi: '모디',\n    chocopi: '초코파이보드',\n    coconut: '코코넛',\n    jdkit: '제이디키트',\n    practical_course: '교과용 만들기',\n    entry_user_policy: '엔트리 이용정책',\n    entry_scholarship_title: '엔트리 학술 자료',\n    entry_scholarship_content:\n        '엔트리는 대학/학회 등과 함께 다양한 연구를 진행하여 전문성을 강화해나가고 있습니다. 엔트리에서 제공하는 연구용 자료를 확인해보세요',\n    entry_scholarship_content_sub:\n        '*엔트리에서 제공하는 데이터는 연구 및 분석에 활용될 수 있도록 온라인코딩파티에 참여한 사용자들이 미션을 해결하는 일련의 과정을 로그 형태로 저장한 데이터 입니다.',\n    entry_scholarship_download: '자료 다운로드',\n    codingparty_2016_title: '2016 온라인 코딩파티',\n    codingparty_2016_content:\n        '미션에 참여한 사용자들의 블록 조립 순서, 성공/실패 유무가 학년, 성별 정보와 함께 제공됩니다.',\n    codingparty_2017_title: '2017 온라인 코딩파티',\n    scholarship_go_mission: '미션 확인하기',\n    scholarship_guide: '자료 활용 방법',\n    scholarship_see_guide: '가이드 보기',\n    scholarship_guide_desc: '연구용 자료를 읽고 활용할 수 있는 방법이 담긴 개발 가이드 입니다. ',\n    scholarship_example: '자료 활용 예시',\n    scholarship_example_desc: '연구용 자료를 활용하여 발표된 논문을 확인 할 수 있습니다.',\n    scholarship_see_example: '논문 다운로드',\n    altino: '알티노',\n    private_project: '비공개 작품입니다.',\n    learn_programming_entry_mission: '\"엔트리봇\"과 함께 미션 해결하기',\n    learn_programming_line_mission: '\"라인레인저스\"와 샐리구하기',\n    learn_programming_choseok: '\"마음의 소리\"의 조석과 게임 만들기',\n    learn_programming_maple: '\"핑크빈\"과 함께 신나는 메이플 월드로!',\n    learn_programming_level_novice: '기초',\n    learn_programming_level_inter: '중급',\n    learn_programming_level_advanced: '고급',\n    line_look_for: '샐리를 찾아서',\n    line_rangers_title_string: '학습하기 : 라인 레인저스',\n    online_codingparty_certificate_string: '온라인 코딩파티',\n    online_codingparty_line_title_string: '라인 레인저스',\n    line_look_for_desc_1:\n        '라인 레인저스의 힘을 모아 강력한 악당 메피스토를 물리치고 샐리를 구해주세요!',\n    line_save: '샐리 구하기',\n    line_save_desc_1:\n        '메피스토 기지에 갇힌 샐리. 라인 레인저스가 장애물을 피해 샐리를 찾아갈 수 있도록 도와주세요!',\n    line_escape: '샐리와 탈출하기',\n    line_escape_desc_1:\n        '폭파되고 있는 메피스토 기지에서 샐리와 라인 레인저스가 무사히 탈출할 수 있도록 도와주세요!',\n    solve_choseok: '가위바위보 만들기',\n    solve_choseok_desc_1: '만화 속 조석이 가위바위보 게임을 만들 수 있도록 도와주세요!',\n    solve_henesys: '헤네시스',\n    solve_ellinia: '엘리니아',\n    solve_elnath: '엘나스',\n    solve_henesys_desc_1:\n        '마을을 모험하며, 배고픈 핑크빈이 음식을 배불리 먹을 수 있도록 도와주세요!',\n    solve_ellinia_desc_1: '숲 속을 탐험하며, 나쁜 몬스터들을 혼내주고 친구 몬스터들을 구해주세요!',\n    solve_elnath_desc_1:\n        '나쁜 몬스터가 점령한 설산을 지나, 새로운 모험을 시작할 수 있는 또 다른 포털을 찾아 떠나보세요 !',\n    save_modified_shape: '수정된 내용을 저장하시겠습니까?',\n    save_modified_table: '테이블에서 수정한 내용을 저장하시겠습니까?',\n    attach_file: '첨부',\n    enter_discuss_title: '제목을 입력해 주세요(40자 이하)',\n    enter_discuss_title_alert: '제목을 입력해 주세요',\n    discuss_upload_warn: '10MB이하의 파일을 올려주세요.',\n    discuss_list: '목록보기',\n    discuss_write_notice: '우리반 공지사항으로 지정하여 게시판 최상단에 노출합니다.',\n    discuss_write_notice_open: '공지사항으로 지정하여 게시판 최상단에 노출합니다.',\n    search_전체: '전체',\n    search_게임: '게임',\n    search_애니메이션: '애니메이션',\n    search_미디어아트: '미디어 아트',\n    search_피지컬: '피지컬',\n    search_기타: '기타',\n    discuss_write_textarea_placeholer:\n        '엔트리 커뮤니티는 우리가 함께 만들어가는 공간입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_qna:\n        '여기는 묻고답하기 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_tips:\n        '여기는 노하우&팁 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_free:\n        '여기는 엔트리 이야기 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_report:\n        '여기는 제안 및 건의 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_contest2019:\n        '※ 아래 양식으로 작성하여 제출해주세요.\\n\\n1. 학년 (예: 초등학교 5학년)\\n\\n2. 작품 URL (‘공유하기 > 작품 공유하기’에 작품을 공유한 다음, 작품 URL을 복사하여 적어주세요.)\\n\\n3. 작품 설명\\n\\n※ 공모전 수상자에게는 이메일이 발송될 예정입니다.\\n엔트리의 ‘내 정보 수정‘에 이메일 정보를 꼭 입력해주세요!',\n    maze_road: '길',\n    account_deletion: '회원탈퇴',\n    bug_report_too_many_request:\n        '신고 내용이 전송 되고 있습니다. 잠시 후에 다시 시도해주시길 바랍니다.',\n    pinkbean_index_title: '핑크빈과 함께 신나는 메이플 월드로!',\n    pinkbean_index_content:\n        '심심함을 참지 못한 핑크빈이 메이플 월드로 모험을 떠났습니다.<br />핑크빈과 함께 신나는 메이플 월드를 탐험하여 모험일지를 채워주세요.<br />각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 마치면 인증서도 얻을 수 있습니다.',\n    rangers_index_title: '라인 레인저스와 함께 샐리를 구하러 출동!',\n    rangers_index_content:\n        '악당 메피스토에게 납치된 샐리를 구하기 위해 라인 레인저스가 뭉쳤습니다.<br />소프트웨어의 원리를 통해 장애물을 극복하고, 샐리를 구출하는 영웅이 되어주세요.<br />각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 마치면 인증서도<br />얻을 수 있습니다.',\n    rangers_replay_button: '영상 다시보기',\n    rangers_start_button: '미션 시작',\n    lms_curriculum_intro: '학습시작',\n    lms_curriculum_goal: '학습목표',\n    lms_curriculum_prepare: '학습준비',\n    lms_curriculum_study: '실습활동',\n    lms_curriculum_summary: '학습정리',\n    lms_curriculum_quiz: '확인문제',\n    lms_curriculum_now_stage: '현재 단계',\n    bug_report_title: '버그 리포트',\n    bug_report_content:\n        '이용 시 발생하는 오류나 버그 신고 및 엔트리를 위한 좋은 제안을 해주세요. 신고나 제안과 무관한 욕설 작성 시 이용이 정지될 수 있습니다.',\n    object_import_syntax_error:\n        '불러오려는 오브젝트에 엔트리파이선 문법과 맞지 않는 블록이 포함되어 있습니다. 블록코딩으로 전환한 뒤 오브젝트를 불러와주세요.',\n    choseok_top_wrapper_panel_title: '조석과 함께 가위바위보 게임을 만들어보세요!',\n    choseok_top_wrapper_panel_des:\n        '마음의 소리 웹툰이 코딩파티 미션으로 탄생했습니다. <br/>만화속 조석이 (가위바위보 게임)을 만들어가는 과정에 참여하여 미션에<br/>도전해 보세요.<br/>각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 모두 마치면</br>인증서와 나만의 게임을 얻을 수 있습니다.<br/>',\n    choseok_mission_statement1: '조석을 움직여보자',\n    choseok_mission_statement2: '가위바위보를 시작해보자',\n    choseok_mission_statement3: '가위바위보 승부를 가려보자',\n    choseok_mission_statement4: '가위바위보 게임을 완성해보자',\n    choseok_mission_statement5: '자유롭게 만들어보자',\n    choseok_mission_statement_top1: '미션 1 : 조석을 움직이기',\n    choseok_mission_statement_top2: '미션 2 : 가위바위보를 시작하기',\n    choseok_mission_statement_top3: '미션 3 : 가위바위보 승패 만들기',\n    choseok_mission_statement_top4: '미션 4 : 가위바위보 결과 보여주기',\n    choseok_mission_statement_top5: '미션 5 : 자유롭게 만들어보기',\n    advisory_title: '엔트리 자문단',\n    advisory_sub_title: '엔트리를 함께 만들어가는 선생님 학생 자문단입니다.',\n    data_table_column: '열',\n    data_table_row: '행',\n    data_table_provider: '제공처',\n    data_table_modifidate: '수정일',\n    draw_new_table_ques_1: '데이터를 직접 입력하여 테이블로 저장할 수 있습니다.',\n    draw_new_table_ques_2: '테이블 화면으로 이동하시겠습니까?',\n};\nLang.Msgs = {\n    microbit_led_erase_all: '모두 지우기',\n    loading_plz_wait: '로딩중입니다. 잠시만 기다려주세요',\n    ai_utilize_audio_listening: '듣고 있어요',\n    upload_error_title: '파일 업로드 안내',\n    upload_error_content: '엔트리 이용정책을 지키지 않는 것으로 의심되는 파일이 제외되었습니다.',\n    monthly_intro_0:\n        '<월간 엔트리>는 소프트웨어 교육에 익숙하지 않은 선생님들도 쉽고 재미있게 소프트웨어 교육을 하실 수 있도록 만들어진 ',\n    monthly_intro_1:\n        'SW교육 잡지입니다. 재미있는 학습만화와 함께 하는 SW 교육 컨텐츠를 만나보세요!',\n    monthly_title_0: '강아지 산책시키기 / 선대칭 도형 그리기',\n    monthly_title_1: '동영상의 원리 / 음악플레이어 만들기',\n    monthly_title_2: '대한민국 지도 퍼즐 / 벚꽃 애니메이션',\n    monthly_title_3: '마우스 졸졸, 물고기 떼 / 태양계 행성',\n    monthly_title_4: '감자 캐기 / 딸기 우유의 진하기',\n    monthly_description_0:\n        '키보드 입력에 따라 움직이는 강아지와 신호와 좌표를 통해 도형을 그리는 작품을 만들어 봅시다.',\n    monthly_description_1: '변수를 활용하여 사진 영상 작품과 음악 플레이어 작품을 만들어 봅시다.',\n    monthly_description_2:\n        '~인 동안 반복하기를 이용한 퍼즐 게임과 복제본, 무작위 수를 이용한 애니메이션 작품을 만들어 봅시다.',\n    monthly_description_3:\n        '계속 반복하기 블록과 수학 연산 블록을 활용하여 물고기 미디어 아트 작품과 태양계를 만들어 봅시다.',\n    monthly_description_4:\n        '신호와 변수, 수학 연산 블록을 활용하여 감자 캐기 작품과 딸기 우유 만들기 작품을 만들어 봅시다.',\n    save_canvas_alert: '저장 중입니다.',\n    feedback_too_many_post: '신고하신 내용이 전송되고 있습니다. 10초 뒤에 다시 시도해주세요.',\n    feedback_duplicated: '이미 신고하였습니다.',\n    usable_object: '사용가능 오브젝트',\n    shared_varaible: '공유 변수',\n    invalid_url: '영상 주소를 다시 확인해 주세요.',\n    auth_only: '인증된 사용자만 이용이 가능합니다.',\n    runtime_error: '실행 오류',\n    to_be_continue: '준비 중입니다.',\n    warn: '경고',\n    error_occured:\n        \"다시 한번 시도해 주세요. 만약 같은 문제가 다시 발생 하면 '제안 및 건의' 게시판에 문의 바랍니다. \",\n    error_forbidden:\n        '로그아웃 상태라 저장을 할 수 없습니다.\\n만약 로그인했다면 다른 창에서 로그아웃 했는지 확인해 주세요.\\n로그인 확인 후 저장이 안 된다면 ‘제안 및 건의’ 게시판에 문의 하세요.',\n    list_can_not_space: '리스트의 이름은 빈 칸이 될 수 없습니다.',\n    sign_can_not_space: '신호의 이름은 빈 칸이 될 수 없습니다.',\n    variable_can_not_space: '변수의 이름은 빈 칸이 될 수 없습니다.',\n    training_top_title: '연수 프로그램',\n    training_top_desc: '엔트리 연수 지원 프로그램을 안내해 드립니다.',\n    training_main_title01: '선생님을 위한 강사 연결 프로그램',\n    training_target01: '교육 대상 l 선생님',\n    training_sub_title01: '“우리 교실에 SW날개를 달자”',\n    training_desc01:\n        '소프트웨어(SW) 교원 연수가 필요한 학교인가요?\\nSW 교원 연수가 필요한 학교에 SW교육 전문 선생님(고투티처) 또는 전문 강사를 연결해드립니다.',\n    training_etc_ment01: '* 강의비 등 연수 비용은 학교에서 지원해주셔야합니다.',\n    training_main_title02: '소프트웨어(SW) 선도학교로 찾아가는 교원연수',\n    training_target02: '교육 대상 l SW 선도, 연구학교',\n    training_sub_title02: '“찾아가, 나누고, 이어가다”',\n    training_desc02:\n        'SW 교원 연수를 신청한 선도학교를 무작위로 추첨하여 상반기(4,5,6월)와\\n하반기(9,10,11월)에 각 지역의 SW교육 전문 선생님(고투티처)께서 알차고\\n재미있는 SW 기초 연수 진행 및 풍부한 교육사례를 공유하기 위해 찾아갑니다.',\n    training_etc_ment02: '',\n    training_main_title03: '학부모와 학생을 위한 연결 프로그램',\n    training_target03: '교육 대상 l 학부모, 학생',\n    training_sub_title03: '“SW를 더 가까이 만나는 시간”',\n    training_desc03:\n        '학부모와 학생들을 대상으로 소프트웨어(SW) 연수가 필요한 학교에 각 지역의 SW교육 전문 선생님(고투티처) 또는 전문 강사를 연결해드립니다.',\n    training_etc_ment03: '* 강의비 등 연수 비용은 학교에서 지원해주셔야합니다.',\n    training_apply: '신청하기',\n    training_ready: '준비중입니다.',\n    new_version_title: '최신 버전 설치 안내',\n    new_version_text1: '하드웨어 연결 프로그램이',\n    new_version_text2: '<strong>최신 버전</strong>이 아닙니다.',\n    new_version_text3: '서비스를 한층 더 강화해 업데이트 된',\n    new_version_text4: '최신 버전의 연결 프로그램을 설치해 주세요.',\n    new_version_download: \"최신 버전 다운로드<span class='download_icon'></span>\",\n    not_install_title: '미설치 안내',\n    hw_download_text1: '하드웨어 연결을 위해서',\n    hw_download_text2: '<strong>하드웨어 연결 프로그램</strong>을 설치해 주세요.',\n    hw_download_text3: '하드웨어 연결 프로그램이 설치되어 있지 않습니다.',\n    hw_download_text4: '최신 버전의 연결 프로그램을 설치해 주세요.',\n    hw_download_btn: \"연결 프로그램 다운로드<span class='download_icon'></span>\",\n    not_support_browser: '지원하지 않는 브라우저입니다.',\n    quiz_complete1: '퀴즈 풀기 완료!',\n    quiz_complete2: '총 {0}문제 중에 {1}문제를 맞췄습니다.',\n    quiz_incorrect: '이런 다시 한 번 생각해보자',\n    quiz_correct: '정답이야!',\n    hw_connection_success: '하드웨어 연결 성공',\n    hw_connection_success_desc: '하드웨어 아이콘을 더블클릭하면, 센서값만 확인할 수 있습니다.',\n    hw_connection_success_desc2: '작품에서 하드웨어를 사용할 수 있습니다.',\n    hw_connection_termination_title: '하드웨어 연결 해제',\n    hw_connection_termination_desc: '하드웨어와 연결이 해제되었습니다.',\n    hw_connection_failed_title: '하드웨어 연결 실패',\n    hw_connection_failed_desc: '작품에서 사용된 하드웨어가\\n연결되어 있는지 확인해 주세요.',\n    ie_page_title: '이 브라우저는<br/>지원하지 않습니다.',\n    ie_page_desc:\n        '엔트리는 인터넷 익스플로러 11 버전 이상 또는 크롬 브라우저에서 이용하실 수 있습니다.<br/>윈도우 업데이트를 진행하시거나, 크롬 브라우저를 설치해주세요.<br/>엔트리 오프라인 버전은 인터넷이 연결되어 있지 않아도 사용할 수 있습니다. 지금 다운받아서 시작해보세요!',\n    ie_page_chrome_download: '크롬 브라우저<br/>다운로드',\n    ie_page_windows_update: '윈도우 최신버전<br>업데이트',\n    ie_page_offline_32bit_download: '엔트리 오프라인 32bit<br>다운로드',\n    ie_page_offline_64bit_download: '엔트리 오프라인 64bit<br>다운로드',\n    ie_page_offline_mac_download: '엔트리 오프라인<br>다운로드',\n    cancel_deletion_your_account: '$1님의<br />회원탈퇴 신청을 취소하시겠습니까?',\n    account_deletion_canceled_complete: '회원탈퇴 신청이 취소되었습니다.',\n    journal_henesys_no1_title: '헤네시스 첫번째 모험일지',\n    journal_henesys_no2_title: '헤네시스 두번째 모험일지',\n    journal_henesys_no1_content:\n        '헤네시스에서 첫 번째 모험 일지야. 오늘 헤네시스 터줏대감이라는 대장장이 집에 가려고 점프를 하다가 떨어질 뻔했어. 그 아저씨는 집 마당 앞에 왜 그렇게 구멍을 크게 만들어 놓는 거지? 나같이 대단한 몬스터가 아니고서야 이런 구멍을 뛰어넘을 수 있는 애들은 없을 거 같은데! 여하튼 정보도 얻었으니 아저씨가 추천한 맛 집으로 가볼까?',\n    journal_henesys_no2_content:\n        '진짜 과식했다. 특히 그 식당의 고기는 정말 맛있었어. 어떻게 그렇게 부드럽게 만들었을까! 그렇지만 그 옆집 빵은 별로였어. 보니까 주방장 아저씨가 요리 수련을 한답시고 맨날 놀러 다니는 거 같더라고. 그럴 시간에 빵 하나라도 더 만들어 보는 게 나을 텐데. 후 이제 배도 채웠으니 본격적인 모험을 시작해볼까!',\n    journal_ellinia_no1_title: '엘리니아 첫번째 모험일지',\n    journal_ellinia_no2_title: '엘리니아 두번째 모험일지',\n    journal_ellinia_no1_content:\n        '휴, 모르고 주황버섯을 깔고 앉아버렸지 뭐야. 걔네가 화날만 하지.. 그래도 그렇게 나에게 다같이 몰려들어 공격할 건 뭐람! 정말 무서운 놈들이야. 슬라임들이 힘들어 할만했어. 하지만 이 핑크빈님께서 다 혼내주었으니깐 걱정 없어. 이제 슬라임들이 친구가 되어주었으니 더욱 신나게 멋진 숲으로 모험을 이어가볼까.',\n    journal_ellinia_no2_content:\n        '모험하면서 만난 친구 로얄패어리가 요즘 엘나스에 흉흉한  소문이 돈다고 했는데, 그게 뭘까? 오늘밤에 친구들이랑 집에서 놀기로 했는데 그때 물어봐야겠어. 완전 궁금한걸!  그런데 뭘 입고 가야하나.. 살이 너무쪄서 입을만 한게 없을거같은데.. 뭐 나는 늘 귀여우니까 어떤걸 입고가도 다들 좋아해줄거라구!',\n    journal_elnath_no1_title: '엘나스 첫번째 모험일지',\n    journal_elnath_no2_title: '엘나스 두번째 모험일지',\n    journal_elnath_no1_content:\n        '세상에! 이게 말로만 듣던 눈인가? 내가 사는 마을은 항상 봄이여서 눈은 처음 봤어. 몬스터들을 혼내주느라 제대로 구경을 못했는데 지금보니 온세상이 이렇게나 하얗고 차갑다니 놀라워! 푹신 푹신하고 반짝거리는게 맛있어 보였는데 맛은 특별히 없네. 그런데 왠지 달콤한 초코 시럽을 뿌려먹으면 맛있을 거 같아. 조금 들고가고 싶은데 방법이 없다니 너무 아쉬운걸.',\n    journal_elnath_no2_content:\n        '에퉤퉤, 실수로 석탄가루를 먹어버렸네. 나쁜 몬스터들! 도망가려면 조용히 도망갈 것이지 석탄을 잔뜩 뿌리면서 도망가버렸어. 덕분에 내 윤기나고 포송포송한 핑크색 피부가 갈수록 더러워지고 있잖아. 어서 여기를 나가서 깨끗하게 목욕부터 해야겠어. 아무리 모험이 좋다지만 이렇게 더럽게 돌아다니는 건 이 핑크빈님 자존심이 허락하지 않지.',\n    bug_report_alert_msg: '소중한 의견 감사합니다.',\n    version_update_msg1: '엔트리 오프라인 새 버전(%1)을\\n사용하실 수 있습니다.',\n    version_update_msg2: '엔트리 하드웨어 새 버전(%1)을\\n사용하실 수 있습니다.',\n    version_update_msg3: '지금 업데이트 하시겠습니까?',\n    select_the_hardware: '수업에 활용할<br />하드웨어를 선택하세요.',\n    select_hardware_button: '하드웨어 선택하기',\n    select_the_expansion_block: '수업에 활용할 확장 블록을 선택하세요.',\n    select_hardware_not_support_info: '오픈강의에는 하드웨어 블록을 사용할 수 없습니다.',\n    select_hardware_not_support_info2: '조금만 기다려주세요.',\n    select_expansion_block_button: '확장 블록 선택하기',\n    expansion_weather_description:\n        '기온, 강수량, 미세먼지 농도 등 한국의 날씨와 관련된 블록 모음입니다. [웨더아이 제공]',\n    expansion_festival_description:\n        '국내 지역별 다양한 행사 및 축제와 관련된 불록 모음 입니다. [한국관광공사 제공]',\n    expansion_translate_description:\n        '파파고를 이용하여 다른 언어로 번역할 수 있는 블록 모음입니다.',\n    expansion_behaviorConductDisaster_description:\n        '자연재난 발생 시 국민이 지켜야하는 기본적인 행동요령에 대한 블록들의 모음입니다. [국민안전처 제공]',\n    expansion_behaviorConductLifeSafety_description:\n        '생활 속 안전을 위해 국민이 지켜야 하는 행동요령에 대한 블록 모음입니다. [국민안전처 제공]',\n    ai_utilize_tts_description:\n        'nVoice 음성합성 기술로 다양한 목소리로 문장을 읽는 블록모음 입니다. ',\n    hardware_need_update_title: '업데이트 안내',\n    hardware_need_update_content:\n        '보안 업데이트로 엔트리 웹버전은\\n하드웨어 1.9.0 버전 이상만 지원합니다.\\n이하 버전일 경우 프로그램을 업데이트 하세요.\\n* 업데이트 후 블록이 보이지 않을 경우,\\n웹브라우저의 캐시를 지워 주세요.',\n    ai_utilize_audio_description:\n        '마이크를 이용하여 소리와 음성을 감지할 수 있는 블록 모음입니다. (IE/Safari/Firefox 브라우저 미지원)',\n    ai_utilize_video_description:\n        '카메라를 이용하여 움직임과 방향 값, 그리고 촬영되는 객체 등을 인식할 수 있는 블록 모음입니다. (IE/Safari/Firefox 브라우저 미지원)',\n};\nLang.Users = {\n    auth_failed: '인증에 실패하였습니다',\n    birth_year: '태어난 해',\n    birth_year_before_1990: '1990년 이전',\n    edit_personal: '정보수정',\n    email: '이메일',\n    email_desc: '새 소식이나 정보를 받을 수 있 이메일 주소',\n    email_inuse: '이미 등록된 메일주소 입니다',\n    email_match: '이메일 주소를 올바르게 입력해 주세요',\n    forgot_password: '암호를 잊으셨습니까?',\n    job: '직업',\n    language: '언어',\n    name: '이름',\n    name_desc: '사이트내에서 표현될 이름 또는 별명',\n    name_not_empty: '이름을 반드시 입력하세요',\n    password: '암호',\n    password_desc: '최소 4자이상 영문자와 숫자, 특수문자',\n    password_invalid: '암호가 틀렸습니다',\n    password_long: '암호는 4~20자 사이의 영문자와 숫자, 특수문자로 입력해 주세요',\n    password_required: '암호는 필수입력 항목입니다',\n    project_list: '작품 조회',\n    regist: '가입 완료',\n    rememberme: '자동 로그인',\n    repeat_password: '암호 확인',\n    repeat_password_desc: '암호를 한번더 입력해 주세요',\n    repeat_password_not_match: '암호가 일치하지 않습니다',\n    sex: '성별',\n    signup_required_for_save: '저장을 하려면 로그인이 필요합니다.',\n    username: '아이디',\n    username_desc: '로그인시 사용할 아이디',\n    username_inuse: '이미 사용중인 아이디 입니다',\n    username_long: '아이디는 4~20자 사이의 영문자로 입력해 주세요',\n    username_unknown: '존재하지 않는 사용자 입니다',\n    already_verified: '이미 인증된 메일 주소입니다.',\n    email_address_unavailable: '유효하지 않은 인증 메일입니다.',\n    email_address_invalid_for_idpw:\n        '유효하지 않은 인증 메일입니다.\\n [아이디와 비밀번호 찾기] 메일 발송하기를\\n 다시 시도해 주세요.',\n    email_address_invalid_for_certification:\n        '유효하지 않은 인증 메일입니다.\\n [인증 메일 발송하기]를 다시 시도해 주세요.',\n    verification_complete: '이메일 주소가 인증되었습니다.',\n    reset_password_mail_sent: '비밀번호 재설정 메일이 발송되었습니다. 메일을 확인해주세요.',\n    email_not_verified:\n        '인증되지 않은 이메일 주소입니다. 인증 메일을 발송하여, 먼저 이메일 주소를 인증해주세요.',\n    verification_email_send_complete: '인증 메일이 발송되었습니다. 먼저 메일 주소를 인증해주세요.',\n    email_send_failed: '전송에 실패했습니다. 다시 한번 시도해주세요.',\n    email_not_exist: '등록되지 않은 이메일 주소입니다.',\n    not_valid_email: '올바른 형식의 이메일 주소를 입력해주세요.',\n};\nLang.Workspace = {\n    picture_rotation: '회전',\n    picture_size: '크기',\n    thickness: '굵기',\n    follow: '따라해보기',\n    SaveWithPicture: '저장되지 않은 그림이 있습니다. 저장하시겠습니까?',\n    RecursiveCallWarningTitle: '함수 호출 제한',\n    RecursiveCallWarningContent:\n        '한 번에 너무 많은 함수가 호출되었습니다. 함수의 호출 횟수를 줄여주세요.',\n    SelectShape: '이동',\n    SelectCut: '자르기',\n    Pencil: '펜',\n    Line: '직선',\n    Rectangle: '사각형',\n    Ellipse: '원',\n    Text: '글상자',\n    Fill: '채우기',\n    Eraser: '지우기',\n    Magnifier: '확대/축소',\n    block_helper: '블록 도움말',\n    new_project: '새 프로젝트',\n    add_object: '오브젝트 추가하기',\n    download_image_name: '엔트리 블록',\n    all: '전체',\n    animal: '동물',\n    arduino_entry: '아두이노 연결 프로그램',\n    arduino_program: '아두이노 프로그램',\n    arduino_sample: '엔트리 연결블록',\n    arduino_driver: '아두이노 드라이버',\n    cannot_add_object: '실행중에는 오브젝트를 추가할 수 없습니다.',\n    cannot_add_picture: '실행중에는 모양을 추가할 수 없습니다.',\n    cannot_add_sound: '실행중에는 소리를 추가할 수 없습니다.',\n    cannot_add_expansion_block: '실행중에는 확장 블럭을 추가할 수 없습니다.',\n    add_object_before_edit: '모양 편집을 위해<br>오브젝트를 추가해주세요.',\n    add_table_before_edit: '테이블을 추가해주세요.',\n    cannot_edit_click_to_stop: '실행 중에는 수정할 수 없습니다.<br>클릭하여 정지하기.',\n    cannot_open_private_project: '비공개 작품은 불러올 수 없습니다. 홈으로 이동합니다.',\n    cannot_save_running_project: '실행 중에는 저장할 수 없습니다.',\n    character_gen: '캐릭터 만들기',\n    check_runtime_error: '빨간색으로 표시된 블록을 확인해 주세요.',\n    check_browser_error: 'IE/Safari 에서는 지원하지 않는 블록입니다.',\n    check_microphone_error: '컴퓨터에 마이크가 연결되어있지 않습니다',\n    check_webcam_error: '컴퓨터에 카메라가 연결되어있지 않습니다',\n    context_download: 'PC에 저장',\n    context_duplicate: '복제',\n    context_remove: '삭제',\n    context_rename: '이름 수정',\n    coordinate: '좌표',\n    create_function: '함수 만들기',\n    direction: '이동 방향',\n    drawing: '직접 그리기',\n    enter_list_name: '새로운 리스트의 이름을 입력하세요(10글자 이하)',\n    enter_name: '새로운 이름을 입력하세요',\n    enter_new_message: '새로운 신호의 이름을 입력하세요.',\n    enter_variable_name: '새로운 변수의 이름을 입력하세요(10글자 이하)',\n    family: '엔트리봇 가족',\n    fantasy: '판타지/기타',\n    file_new: '새로 만들기',\n    file_open: '온라인 작품 불러오기',\n    file_upload: '오프라인 작품 불러오기',\n    file_upload_login_check_msg: '오프라인 작품을 불러오기 위해서는 로그인을 해야 합니다.',\n    file_save: '저장하기',\n    file_save_as: '복사본으로 저장하기',\n    file_save_download: '내 컴퓨터에 저장하기',\n    func: '함수',\n    function_create: '함수 만들기',\n    function_add: '함수 추가하기',\n    interface: '인터페이스',\n    landscape: '배경',\n    list: '리스트',\n    list_add_calcel: '리스트 추가 취소',\n    list_add_calcel_msg: '리스트 추가를 취소하였습니다.',\n    list_add_fail: '리스트 추가 실패',\n    list_add_fail_msg1: '같은 이름의 리스트가 이미 존재합니다.',\n    list_add_fail_msg2: '리스트의 이름이 적절하지 않습니다.',\n    list_add_ok: '리스트 추가 완료',\n    list_add_ok_msg: '을(를) 추가하였습니다.',\n    list_create: '리스트 추가하기',\n    list_create_placeholder: '리스트의 이름을 입력해주세요.',\n    list_dup: '같은 이름의 리스트가 이미 존재합니다.',\n    list_newname: '새로운 이름',\n    list_export: '리스트 내보내기',\n    list_import: '리스트 불러오기',\n    list_remove: '리스트 삭제',\n    list_rename: '리스트 이름 변경',\n    list_rename_failed: '리스트 이름 변경 실패',\n    list_rename_ok: '리스트의 이름이 성공적으로 변경 되었습니다.',\n    list_too_long: '리스트의 이름이 너무 깁니다.',\n    message: '신호',\n    message_add_cancel: '신호 추가 취소',\n    message_add_cancel_msg: '신호 추가를 취소하였습니다.',\n    message_add_fail: '신호 추가 실패',\n    message_add_fail_msg: '같은 이름의 신호가 이미 존재합니다.',\n    message_add_ok: '신호 추가 완료',\n    message_add_ok_msg: '을(를) 추가하였습니다.',\n    message_create: '신호 추가하기',\n    message_create_placeholder: '신호의 이름을 입력해주세요.',\n    message_dup: '같은 이름의 신호가 이미 존재합니다.',\n    message_remove: '신호 삭제',\n    message_remove_canceled: '신호 삭제를 취소하였습니다.',\n    message_rename: '신호 이름을 변경하였습니다.',\n    message_rename_failed: '신호 이름 변경 실패',\n    message_rename_ok: '신호의 이름이 성공적으로 변경 되었습니다.',\n    message_too_long: '신호의 이름이 너무 깁니다.',\n    no_message_to_remove: '삭제할 신호가 없습니다',\n    no_use: '사용되지 않음',\n    no_variable_to_remove: '삭제할 변수가 없습니다.',\n    no_variable_to_rename: '변경할 변수가 없습니다.',\n    object_not_found: '블록에서 지정한 오브젝트가 존재하지 않습니다.',\n    object_not_found_for_paste: '붙여넣기 할 오브젝트가 없습니다.',\n    people: '일반 사람들',\n    picture_add: '모양 추가하기',\n    table_add: '테이블 추가하기',\n    draw_new_table: '새로 만들기',\n    plant: '식물',\n    project: '작품',\n    project_copied: '의 사본',\n    PROJECTDEFAULTNAME: ['멋진', '재밌는', '착한', '큰', '대단한', '잘생긴', '행운의'],\n    remove_object: '오브젝트 삭제',\n    remove_object_msg: '(이)가 삭제되었습니다.',\n    removed_msg: '(이)가 성공적으로 삭제 되었습니다.',\n    rotate_method: '회전방식',\n    rotation: '방향',\n    run: '시작하기',\n    saved: '저장완료',\n    saved_msg: '(이)가 저장되었습니다.',\n    save_failed: '저장시 문제가 발생하였습니다. 다시 시도해 주세요.',\n    select_library: '오브젝트 선택',\n    select_sprite: '적용할 스프라이트를 하나 이상 선택하세요.',\n    shape_remove_fail: '모양 삭제 실패',\n    shape_remove_fail_msg: '적어도 하나 이상의 모양이 존재하여야 합니다.',\n    shape_remove_ok: '모양이 삭제 되었습니다. ',\n    shape_remove_ok_msg: '이(가) 삭제 되었습니다.',\n    load_expansion_block: '확장 블록 불러오기',\n    load_ai_utilize_block: 'AI 블록 불러오기',\n    load_ai_utilize_train_block: '모델 학습',\n    select_expansion_block: '확장블록 선택',\n    deselect_expansion_block_warning: '확장블록이 사용중이므로 삭제할 수 없습니다.',\n    deselect_ai_utilize_block_warning: 'AI블록이 사용중이므로 삭제할 수 없습니다.',\n    sound_add: '소리 추가하기',\n    sound_remove_fail: '소리 삭제 실패',\n    sound_remove_ok: '소리 삭제 완료',\n    sound_remove_ok_msg: '이(가) 삭제 되었습니다.',\n    stop: '정지하기',\n    pause: '일시정지',\n    restart: '다시시작',\n    speed: '속도 조절',\n    tab_attribute: '속성',\n    tab_table: '테이블',\n    tab_code: '블록',\n    tab_picture: '모양',\n    tab_sound: '소리',\n    tab_text: '글상자',\n    textbox: '글상자',\n    textbox_edit: '글상자 편집',\n    textbox_input: '글상자의 내용을 입력해주세요.',\n    things: '물건',\n    textcoding_tooltip1:\n        '블록코딩과 엔트리파이선을<br/>선택하여 자유롭게<br/>코딩을 해볼 수 있습니다.',\n    textcoding_tooltip2:\n        '실제 개발 환경과 동일하게<br/>엔트리파이선 모드의 실행 결과를<br/>확인할 수 있습니다.',\n    textcoding_tooltip3:\n        '엔트리파이선에 대한<br/>기본사항이 안내되어 있습니다.<br/><엔트리파이선 이용안내>를 확인해 주세요!',\n    upload: '파일 올리기',\n    upload_addfile: '파일 올리기',\n    variable: '변수',\n    variable_add_calcel: '변수 추가 취소',\n    variable_add_calcel_msg: '변수 추가를 취소하였습니다.',\n    variable_add_fail: '변수 추가 실패',\n    variable_add_fail_msg1: '같은 이름의 변수가 이미 존재합니다.',\n    variable_add_fail_msg2: '변수의 이름이 적절하지 않습니다.',\n    variable_add_ok: '변수 추가 완료',\n    variable_add_ok_msg: '을(를) 추가하였습니다.',\n    variable_create: '변수 만들기',\n    variable_add: '변수 추가하기',\n    variable_dup: '같은 이름의 변수가 이미 존재합니다.',\n    variable_newname: '새로운 이름',\n    variable_remove: '변수 삭제',\n    variable_remove_canceled: '변수 삭제를 취소하였습니다.',\n    variable_rename: '변수 이름을 변경합니다. ',\n    variable_rename_failed: '변수 이름 변경에 실패하였습니다. ',\n    variable_rename_msg: \"'변수의 이름이 성공적으로 변경 되었습니다.'\",\n    variable_rename_ok: '변수의 이름이 성공적으로 변경 되었습니다.',\n    variable_select: '변수를 선택하세요',\n    variable_too_long: '변수의 이름이 너무 깁니다.',\n    open_analizy_data_import: '데이터 화면 열기',\n    vehicle: '탈것',\n    add_object_alert_msg: '오브젝트를 추가해주세요',\n    add_object_alert: '경고',\n    create_variable_block: '변수 만들기',\n    create_list_block: '리스트 만들기',\n    Variable_Timer: '초시계',\n    Variable_placeholder_name: '변수 이름',\n    Message_placeholder_name: '신호 이름',\n    Variable_property: '변수 속성',\n    Variable_placeholder_content: '변수의 이름을 입력해주세요.',\n    Variable_use_all_objects: '모든 오브젝트에서 사용',\n    Variable_use_this_object: '이 오브젝트에서 사용',\n    Variable_used_at_all_objects: '모든 오브젝트에서 사용되는 변수',\n    variable_create_normal: '일반 변수로 사용\\n(작품에 저장)',\n    variable_create_cloud: '공유 변수로 사용\\n(서버에 저장)',\n    variable_create_real_time: '실시간 변수로 사용\\n(서버에 저장)',\n    Variable_used_at_special_object: '특정 오브젝트에서만 사용되는 변수',\n    Variable_used_objects: '사용된 오브젝트',\n    draw_new: '새로 그리기',\n    draw_new_ebs: '직접 그리기',\n    painter_file: '파일 ▼',\n    painter_file_save: '저장하기',\n    painter_file_saveas: '새 모양으로 저장',\n    new_picture: '새그림',\n    painter_edit: '편집 ▼',\n    get_file: '가져오기',\n    copy_file: '복사하기',\n    cut_picture: '자르기',\n    paste_picture: '붙이기',\n    remove_all: '모두 지우기',\n    flip_horizontal: '좌우뒤집기',\n    flip_vertical: '상하뒤집기',\n    regular: '보통',\n    bold: '굵게',\n    font_underline: '밑줄',\n    font_tilt: '기울임',\n    font_cancel: '취소선',\n    font_color: '글꼴 색상',\n    font_fill: '채우기 색상',\n    font_family: '글꼴',\n    align_left: '왼쪽 정렬',\n    align_center: '가운데 정렬',\n    align_right: '오른쪽 정렬',\n    italic: '기울임',\n    textStyle: '글자',\n    add_picture: '모양 추가',\n    select_picture: '모양 선택',\n    select_table: '테이블 선택',\n    select_sound: '소리 선택',\n    Size: '크기',\n    show_variable: '변수 노출',\n    default_value: '기본값 ',\n    slide: '슬라이드',\n    min_value: '최솟값',\n    max_value: '최댓값',\n    number_of_list: '리스트 항목 수',\n    empty_of_list: '추가된 항목이 없습니다',\n    use_all_objects: '모든 오브젝트에 사용',\n    list_name: '리스트 이름',\n    list_property: '리스트 속성',\n    list_used_specific_objects: '특정 오브젝트에서만 사용되는 리스트',\n    List_used_all_objects: '모든 오브젝트에서 사용되는 리스트',\n    List_used_objects: '사용된 오브젝트',\n    Scene_delete_error: '장면은 최소 하나 이상 존재해야 합니다.',\n    Scene_add_error: '장면은 최대 20개까지 추가 가능합니다.',\n    replica_of_object: '의 복제본',\n    will_you_delete_scene: '장면은 한번 삭제하면 취소가 불가능 합니다. \\n정말 삭제 하시겠습니까?',\n    will_you_delete_function:\n        '함수는 한번 삭제하면 취소가 불가능 합니다. \\n정말 삭제 하시겠습니까?',\n    duplicate_scene: '복제하기',\n    block_explain: '블록 설명 ',\n    block_intro: '블록을 클릭하면 블록에 대한 설명이 나타납니다.',\n    blocks_reference: '블록 설명',\n    hardware_guide: '하드웨어 연결 안내',\n    robot_guide: '로봇 연결 안내',\n    python_guide: '엔트리파이선 이용 안내',\n    show_list_workspace: '리스트 노출',\n    list_create_normal: '일반 리스트로 사용\\n(작품에 저장)',\n    list_create_cloud: '공유 리스트로 사용 \\n(서버에 저장)',\n    list_create_real_time: '실시간 리스트로 사용\\n(서버에 저장)',\n    confirm_quit: '바꾼 내용을 저장하지 않았습니다.',\n    confirm_load_temporary: '저장되지 않은 작품이 있습니다. 여시겠습니까?',\n    login_to_save: '로그인후에 저장 바랍니다.',\n    cannot_save_in_edit_func: '함수 편집중에는 저장할 수 없습니다.',\n    new_object: '새 오브젝트',\n    arduino_connect: '하드웨어 연결',\n    arduino_connect_success: '하드웨어가 연결되었습니다.',\n    confirm_load_header: '작품 복구',\n    uploading_msg: '업로드 중입니다',\n    upload_fail_msg: '업로드에 실패하였습니다.</br>다시 한번 시도해주세요.',\n    upload_not_supported_msg: '지원하지 않는 형식입니다.',\n    upload_not_supported_file_msg: '지원하지 않는 형식의 파일입니다.',\n    file_converting_msg: '파일 변환 중입니다.',\n    file_converting_fail_msg: '파일 변환에 실패하였습니다.',\n    fail_contact_msg: '문제가 계속된다면</br>entry@connect.or.kr 로 문의해주세요.',\n    saving_msg: '저장 중입니다',\n    saving_fail_msg: '저장에 실패하였습니다.</br>다시 한번 시도해주세요.',\n    loading_msg: '불러오는 중입니다',\n    loading_fail_msg: '불러오기에 실패하였습니다.</br>다시 한번 시도해주세요.',\n    restore_project_msg: '정상적으로 저장되지 않은 작품이 있습니다. 해당 작품을 복구하시겠습니까?',\n    quit_stop_msg: '저장 중에는 종료하실 수 없습니다.',\n    ent_drag_and_drop: '업로드 하려면 파일을 놓으세요',\n    not_supported_file_msg: '지원하지 않은 형식의 파일입니다.',\n    broken_file_msg: '파일이 깨졌거나 잘못된 파일을 불러왔습니다.',\n    check_audio_msg: 'mp3 외 오디오 파일은 재생할 수 없습니다.',\n    check_entry_file_msg: 'ENT 파일만 불러오기가 가능합니다.',\n    hardware_version_alert_text:\n        '5월 30일 부터 구버전의 연결프로그램의 사용이 중단 됩니다.\\n하드웨어 연결 프로그램을 최신 버전으로 업데이트 해주시기 바랍니다.',\n    variable_name_auto_edited_title: '변수 이름 자동 변경',\n    variable_name_auto_edited_content: '변수의 이름은 10글자를 넘을 수 없습니다.',\n    list_name_auto_edited_title: '리스트 이름 자동 변경',\n    list_name_auto_edited_content: '리스트의 이름은 10글자를 넘을 수 없습니다.',\n    cloned_scene: '복제본_',\n    default_mode: '기본형',\n    practical_course_mode: '교과형',\n    practical_course: '실과',\n    select_mode: '모드선택',\n    select_mode_popup_title: '엔트리 만들기 환경을 선택해 주세요.',\n    select_mode_popup_lable1: '기본형',\n    select_mode_popup_lable2: '교과형',\n    select_mode_popup_desc1: '엔트리의 모든 기능을 이용하여<br/>자유롭게 작품을 만듭니다.',\n    select_mode_popup_desc2: '실과 교과서에 등장하는 기능만을<br/>이용하여 작품을 만듭니다.',\n    practical_course_notice: '안내',\n    practical_course_desc:\n        \"<span class='practical_cource_title'>교과용 만들기</span>는<br />실과 교과서로 소프트웨어를 배울 때<br />필요한 기능만을 제공합니다.\",\n    practical_course_desc2:\n        '*기본형 작품 만들기를 이용하면 더 많은 기능을<br />이용해 작품을 만들 수 있습니다.',\n    practical_course_tooltip: '모든 기능을 이용하기 위해서는<br/>기본형을 선택해 주세요.',\n    name_already_exists: '이름이 중복 되었습니다.',\n    enter_the_name: '이름을 입력하여 주세요.',\n    object_not_exist_error: '오브젝트가 존재하지 않습니다. 오브젝트를 추가한 후 시도해주세요.',\n    workspace_tutorial_popup_desc:\n        \"<span class='practical_cource_title'>작품 만들기</span>는<br />창의적인 작품을 만들 수 있도록<br /> 다양한 블록과 기능을 제공합니다.\",\n    start_guide_tutorial: '만들기 이용 안내',\n    language: '언어 선택',\n    file: '파일',\n    save: '저장하기',\n    help: '도움말',\n    print: '인쇄',\n    undo: '입력 취소',\n    redo: '다시 실행',\n    workspace_title_tooltip:\n        '기본작품명이 변경되었습니다.\\n작품을 만든 날짜를 통해 어떤 작품인지 쉽게 알 수 있습니다.',\n    workspace_object_tooltip:\n        '오브젝트의 순서는 오브젝트의 대표 이미지를 잡고\\n위아래로 이동하여 변경할 수 있습니다.\\n(모양과 소리탭에서도 동일하게 동작합니다.)',\n    workspace_comment_tooltip: '조립소에 추가한 메모를\\n한꺼번에 숨기거나 보이게 할 수 있습니다.',\n    workspace_zoom_tooltip:\n        '조립소에 추가된 블록의 크기를 바꿀 수 있습니다.\\n가운데 = 아이콘을 누르면 기본 크기로 돌아옵니다.',\n    workspace_image_tooltip: '새로워진\\n작품 만들기를\\n소개합니다.',\n    playground_block_drop: '나의 보관함의 블록을\\n조립소에 추가합니다.',\n    container_object_drop: '나의 보관함의 오브젝트를\\n오브젝트 리스트에 추가합니다.',\n    my_storage_block_drop: '블록을\\n나의 보관함에\\n추가합니다.',\n    my_storage_object_drop: '오브젝트를\\n나의 보관함에\\n추가합니다.',\n    my_storage: '나의 보관함',\n    my_block: '나의 블록',\n    red: '빨강(R)',\n    green: '녹색(G)',\n    blue: '파랑(B)',\n    hue: '색상',\n    saturation: '채도',\n    brightness: '명도',\n    spoid: '스포이드',\n    palette_mode: '팔레트 모드',\n    slider_mode: '슬라이더 모드',\n    toast_error_title_object_center: '주의',\n    toast_error_contents_object_center:\n        '오브젝트 중심점이 오브젝트와 멀리 떨어져 실행화면 밖으로 벗어날 경우, 원위치로 돌아옵니다.',\n    blocks_comming_soon: '열심히 연구 중입니다.\\n조금만 기다려 주세요!',\n    data_table: '테이블',\n    select_all: '모두',\n    now_loading_msg: '로딩 중입니다.\\n잠시만 기다려주세요.',\n};\nLang.code = '코드보기';\nLang.EntryStatic = {\n    event100: '이벤트',\n    groupProject: '학급 공유하기',\n    usage_parallel: '병렬',\n    usage_expansion: '확장',\n    usage_hw: '하드웨어',\n    usage_sequence: '순차',\n    privateProject: '나만보기',\n    privateCurriculum: '나만보기',\n    publicCurriculum: '강의 모음 공유하기',\n    publicProject: '작품 공유하기',\n    group: '학급 공유하기',\n    groupCurriculum: '학급 공유하기',\n    private: '나만보기',\n    public: '강의 공유하기',\n    lecture_is_open_true: '공개',\n    lecture_is_open_false: '비공개',\n    category_all: '모든 작품',\n    category_game: '게임',\n    category_animation: '애니메이션',\n    category_media_art: '미디어 아트',\n    category_physical: '피지컬',\n    category_etc: '기타',\n    category_category_game: '게임',\n    category_category_animation: '애니메이션',\n    category_category_media_art: '미디어 아트',\n    category_category_physical: '피지컬',\n    category_category_etc: '기타',\n    sort_created: '최신순',\n    sort_updated: '최신순',\n    sort_visit: '조회순',\n    sort_likeCnt: '좋아요순',\n    sort_comment: '댓글순',\n    period_all: '전체기간',\n    period_1: '오늘',\n    period_7: '최근 1주일',\n    period_30: '최근 1개월',\n    period_90: '최근 3개월',\n    lecture_required_time_1: ' ~ 15분',\n    lecture_required_time_2: '15분 ~ 30분',\n    lecture_required_time_3: '30분 ~ 45분',\n    lecture_required_time_4: '45 분 ~ 60분',\n    lecture_required_time_5: '1시간 이상',\n    usage_event: '이벤트',\n    usage_signal: '신호보내기',\n    usage_scene: '장면',\n    usage_repeat: '반복',\n    usage_condition_repeat: '조건반복',\n    usage_condition: '선택',\n    usage_clone: '복제본',\n    usage_rotation: '회전',\n    usage_coordinate: '좌표이동',\n    usage_arrow_move: '화살표이동',\n    usage_shape: '모양',\n    usage_speak: '말하기',\n    usage_picture_effect: '그림효과',\n    usage_textBox: '글상자',\n    usage_draw: '그리기',\n    usage_sound: '소리',\n    usage_confirm: '판단',\n    usage_comp_operation: '비교연산',\n    usage_logical_operation: '논리연산',\n    usage_math_operation: '수리연산',\n    usage_random: '무작위수',\n    usage_timer: '초시계',\n    usage_variable: '변수',\n    usage_list: '리스트',\n    usage_ask_answer: '입출력',\n    usage_function: '함수',\n    usage_arduino: '아두이노',\n    concept_resource_analytics: '자료수집/분석/표현',\n    concept_procedual: '알고리즘과 절차',\n    concept_abstractive: '추상화',\n    concept_individual: '문제분해',\n    concept_automation: '자동화',\n    concept_simulation: '시뮬레이션',\n    concept_parallel: '병렬화',\n    subject_korean: '국어',\n    subject_english: '영어',\n    subject_mathmatics: '수학',\n    subject_social: '사회',\n    subject_science: '과학',\n    subject_music: '음악',\n    subject_paint: '미술',\n    subject_athletic: '체육',\n    subject_courtesy: '도덕',\n    subject_progmatic: '실과',\n    lecture_grade_1: '초1',\n    lecture_grade_2: '초2',\n    lecture_grade_3: '초3',\n    lecture_grade_4: '초4',\n    lecture_grade_5: '초5',\n    lecture_grade_6: '초6',\n    lecture_grade_7: '중1',\n    lecture_grade_8: '중2',\n    lecture_grade_9: '중3',\n    lecture_grade_10: '일반',\n    lecture_level_1: '쉬움',\n    lecture_level_2: '중간',\n    lecture_level_3: '어려움',\n    listEnable: '리스트',\n    functionEnable: '함수',\n    messageEnable: '신호',\n    objectEditable: '오브젝트',\n    pictureeditable: '모양',\n    sceneEditable: '장면',\n    soundeditable: '소리',\n    variableEnable: '변수',\n    e_1: '초등 1학년',\n    e_2: '초등 2학년',\n    e_3: '초등 3학년',\n    e_4: '초등 4학년',\n    e_5: '초등 5학년',\n    e_6: '초등 6학년',\n    m_1: '중등 1학년',\n    m_2: '중등 2학년',\n    m_3: '중등 3학년',\n    general: '일반',\n    curriculum_is_open_true: '공개',\n    curriculum_open_false: '비공개',\n    contest2019: '공모전',\n    exhibit: '공모전',\n    notice: '공지사항',\n    qna: '묻고답하기',\n    tips: '노하우&팁',\n    free: '엔트리 이야기',\n    report: '제안 및 건의',\n    art_category_all: '모든 작품',\n    art_category_game: '게임',\n    art_category_animation: '애니메이션',\n    art_category_physical: '피지컬',\n    art_category_etc: '기타',\n    art_category_media: '미디어 아트',\n    art_sort_updated: '최신순',\n    art_sort_visit: '조회순',\n    art_sort_likeCnt: '좋아요순',\n    art_sort_comment: '댓글순',\n    art_period_all: '전체기간',\n    art_period_day: '오늘',\n    art_period_week: '최근 1주일',\n    art_period_month: '최근 1개월',\n    art_period_three_month: '최근 3개월',\n    level_high: '상',\n    level_mid: '중',\n    level_row: '하',\n    discuss_sort_created: '최신순',\n    discuss_sort_visit: '조회순',\n    discuss_sort_likesLength: '좋아요순',\n    discuss_sort_commentsLength: '댓글순',\n    discuss_period_all: '전체기간',\n    discuss_period_day: '오늘',\n    discuss_period_week: '최근 1주일',\n    discuss_period_month: '최근 1개월',\n    discuss_period_three_month: '최근 3개월',\n};\nLang.Helper = {\n    when_run_button_click: '시작하기 버튼을 클릭하면 아래에 연결된 블록들을 실행합니다.',\n    when_some_key_pressed: '선택한 키를 누르면 아래에 연결된 블록들을 실행합니다.',\n    mouse_clicked: '마우스를 클릭했을 때 아래에 연결된 블록들을 실행합니다.',\n    mouse_click_cancled: '마우스 클릭을 해제했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_object_click: '오브젝트를 클릭했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_object_click_canceled: '오브젝트 클릭을 해제했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_message_cast: '선택한 신호를 받으면 아래에 연결된 블록들을 실행합니다.',\n    message_cast: '선택한 신호를 보냅니다.',\n    message_cast_wait:\n        '선택한 신호를 보내고, 해당 신호를 받는 블록들의 실행이 끝날 때 까지 기다립니다.',\n    when_scene_start: '장면이 시작되면 아래에 연결된 블록들을 실행합니다. ',\n    start_scene: '선택한 장면을 시작합니다.',\n    start_neighbor_scene: '이전 또는 다음 장면을 시작합니다.',\n    wait_second: '입력한 시간만큼 기다린 후 다음 블록을 실행합니다.',\n    repeat_basic: '입력한 횟수만큼 감싸고 있는 블록들을 반복 실행합니다.',\n    repeat_inf: '감싸고 있는 블록들을 계속해서 반복 실행합니다.',\n    repeat_while_true:\n        '판단값에 따라 블록의 반복여부를 결정합니다.\\n이 될 때까지: 판단이 참이 될 때까지 감싸고 있는 블록들을 반복 실행합니다.\\n인 동안: 판단이 참인 동안 감싸고 있는 블록들을 반복 실행합니다.',\n    stop_repeat: '이 블록을 감싸는 가장 가까운 반복 블록의 반복을 중단합니다.',\n    _if: '만일 판단이 참이라면, 감싸고 있는 블록들을 실행합니다.',\n    if_else:\n        '만일 판단이 참이라면 첫 번째 감싸고 있는 블록들을 실행하고, 거짓이면 두 번째 감싸고 있는 블록들을 실행합니다.',\n    restart_project: '작품을 처음부터 다시 실행합니다.',\n    stop_object:\n        '블록이 실행을 멈춥니다. 현재 실행중인 동작을 멈추는 블록이며, 프로그램을 종료하지 않습니다.\\n모든 : 작품의 모든 블록이 실행을 멈춥니다. \\n자신 : 해당 오브젝트의 모든 블록이 실행을 멈춥니다.\\n이 코드 : 이 블록이 포함된 블록들이 실행을 멈춥니다.\\n자신의 다른 코드 :  해당 오브젝트 중 이 블록이 포함된 블록들을 제외한 모든 블록이 실행을 멈춥니다.\\n다른 오브젝트의 : 다른 오브젝트의 모든 블록이 실행을 멈춥니다.',\n    wait_until_true: '판단이 참이 될 때까지 실행을 멈추고 기다립니다.',\n    when_clone_start:\n        '해당 오브젝트의 복제본이 새로 생성되었을 때 아래에 연결된 블록들을 실행합니다.',\n    create_clone: '선택한 오브젝트의 복제본을 생성합니다.',\n    delete_clone:\n        '‘복제본이 처음 생성되었을 때’ 블록과 함께 사용되며, 연결된 블록들이 실행되고 있는 복제본을 삭제합니다.',\n    remove_all_clones: '해당 오브젝트의 모든 복제본을 삭제합니다.',\n    move_direction: '입력한 값만큼 오브젝트의 이동 방향 화살표가 가리키는 방향으로 움직입니다.',\n    move_x: '오브젝트의 x 좌표를 입력한 값만큼 바꿉니다. ',\n    move_y: '오브젝트의 y 좌표를 입력한 값만큼 바꿉니다.',\n    move_xy_time: '오브젝트가 입력한 시간에 걸쳐 x와 y 좌표를 입력한 값만큼 바꿉니다.',\n    locate_object_time:\n        '오브젝트가 입력한 시간에 걸쳐 선택한 오브젝트 또는 마우스 포인터의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_x: '오브젝트가 입력한 x 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_y: '오브젝트가 입력한 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy: '오브젝트가 입력한 x와 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_time:\n        '오브젝트가 입력한 시간에 걸쳐 입력한 x와 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate: '오브젝트가 선택한 오브젝트 또는 마우스 포인터의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    rotate_absolute: '오브젝트의 방향을 입력한 각도로 정합니다.',\n    rotate_by_time:\n        '오브젝트의 방향이 입력한 시간에 걸쳐 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_relative:\n        '오브젝트의 방향이 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    direction_absolute: '오브젝트의 이동 방향을 입력한 각도로 정합니다.',\n    direction_relative:\n        '오브젝트의 이동 방향이 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    move_to_angle:\n        '오브젝트가 입력한 각도 방향으로 입력한 값만큼 움직입니다. (실행화면 위쪽이 0도를 나타내며, 시계방향으로 갈수록 각도가 증가합니다.)',\n    see_angle_object:\n        '해당 오브젝트가 방향을 회전하여 선택한 오브젝트 또는 마우스 포인터 쪽을 바라봅니다. ',\n    bounce_wall: '오브젝트가 실행화면 끝에 닿으면 튕겨 나옵니다.',\n    show: '오브젝트를 실행화면에 보이게 합니다.',\n    hide: '오브젝트를 실행화면에 보이지 않게 합니다.',\n    dialog_time:\n        '오브젝트가 입력한 내용을 입력한 시간 동안 말풍선으로 말한 후 다음 블록을 실행합니다.',\n    dialog: '오브젝트가 입력한 내용을 말풍선으로 말하는 동시에 다음 블록을 실행합니다.',\n    remove_dialog: '오브젝트가 말하고 있는 말풍선을 지웁니다.',\n    change_to_some_shape:\n        '오브젝트를 선택한 모양으로 바꿉니다. (내부 블록을 분리하고 모양의 번호를 입력하여 모양을 바꿀 수 있습니다.)',\n    change_to_next_shape: '오브젝트의 모양을 이전 또는 다음 모양으로 바꿉니다.',\n    set_effect_volume: '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.',\n    set_effect_amount: '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.',\n    set_effect:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n색깔 : 0~100을 주기로 반복됩니다.\\n밝기 : -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.)\\n투명도 : 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로, 100 이상은 100으로 처리됩니다.)',\n    set_entity_effect:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n색깔 : 0~100을 주기로 반복됩니다.\\n밝기 : -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.)\\n투명도 : 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로, 100 이상은 100으로 처리됩니다.)',\n    add_effect_amount: '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.',\n    change_effect_amount:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n색깔 : 0~100을 주기로 반복됩니다.\\n밝기 : -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.)\\n투명도 : 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로, 100 이상은 100으로 처리됩니다.)',\n    change_scale_percent: '오브젝트의 크기를 입력한 값만큼 바꿉니다.',\n    set_scale_percent: '오브젝트의 크기를 입력한 값으로 정합니다.',\n    change_scale_size: '오브젝트의 크기를 입력한 값만큼 바꿉니다.',\n    set_scale_size: '오브젝트의 크기를 입력한 값으로 정합니다.',\n    flip_x: '오브젝트의 상하 모양을 뒤집습니다.',\n    flip_y: '오브젝트의 좌우 모양을 뒤집습니다.',\n    change_object_index:\n        '오브젝트가 실행화면에 보이는 순서를 변경합니다.\\n맨 앞으로 : 해당 오브젝트를 실행화면의 가장 앞쪽으로 가져옵니다. \\n앞으로 : 해당 오브젝트를 한 층 앞쪽으로 가져옵니다.\\n뒤로 : 해당 오브젝트를 한 층 뒤쪽으로 보냅니다. \\n맨 뒤로 : 해당 오브젝트를 실행화면의 가장 뒤쪽으로 보냅니다.',\n    set_object_order: '해당 오브젝트가 설정한 순서로 올라옵니다.',\n    brush_stamp: '오브젝트의 모양을 도장처럼 실행화면 위에 찍습니다.',\n    start_drawing:\n        '오브젝트가 이동하는 경로를 따라 선이 그리기 시작합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    stop_drawing: '오브젝트가 선 그리는 것을 멈춥니다.',\n    set_color: '오브젝트가 그리는 선의 색을 선택한 색으로 정합니다.',\n    set_random_color: '오브젝트가 그리는 선의 색을 무작위로 정합니다. ',\n    change_thickness: '오브젝트가 그리는 선의 굵기를 입력한 값만큼 바꿉니다.',\n    set_thickness:\n        '오브젝트가 그리는 선의 굵기를 입력한 값으로 정합니다. 1~무한의 범위로 설정할 수 있습니다. (1 이하는 1로 처리합니다.)',\n    change_opacity: '해당 오브젝트가 그리는 붓의 투명도를 입력한 값만큼 바꿉니다.',\n    change_brush_transparency: '해당 오브젝트가 그리는 붓의 투명도를 입력한 값만큼 바꿉니다.',\n    set_opacity:\n        '해당 오브젝트가 그리는 붓의 투명도를 입력한 값으로 정합니다. 0~100의 범위로 설정할 수 있습니다. (0 이하는 0, 100 이상은 100으로 처리합니다.)',\n    set_brush_tranparency:\n        '해당 오브젝트가 그리는 붓의 투명도를 입력한 값으로 정합니다. 0~100의 범위로 설정할 수 있습니다. (0 이하는 0, 100 이상은 100으로 처리합니다.)',\n    brush_erase_all: '해당 오브젝트가 그린 선과 도장을 모두 지웁니다.',\n    sound_something_with_block:\n        '해당 오브젝트가 선택한 소리를 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_something_second_with_block:\n        '해당 오브젝트가 선택한 소리를 입력한 시간 만큼 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_something_wait_with_block:\n        '해당 오브젝트가 선택한 소리를 재생한 후 다음 블록을 실행합니다.',\n    sound_something_second_wait_with_block:\n        '해당 오브젝트가 선택한 소리를 입력한 시간 만큼 재생한 후 다음 블록을 실행합니다.',\n    sound_volume_change: '작품에서 재생되는 모든 소리의 크기를 입력한 값만큼 바꿉니다.',\n    sound_volume_set: '작품에서 재생되는 모든 소리의 크기를 입력한 값으로 정합니다.',\n    sound_silent_all: '재생 중인 모든 소리를 멈춥니다.',\n    is_clicked: '마우스를 클릭한 경우 ‘참’으로 판단합니다.',\n    is_press_some_key: '선택한 키가 눌려져 있는 경우 ‘참’으로 판단합니다.',\n    reach_something: '해당 오브젝트가 선택한 항목과 닿은 경우 ‘참’으로 판단합니다.',\n    is_included_in_list:\n        \"선택한 리스트가 입력한 값을 가진 항목을 포함하는 경우 '참'으로 판단합니다.\",\n    boolean_basic_operator:\n        \"입력한 두 값을 비교합니다.\\n= : 왼쪽에 위치한 값과 오른쪽에 위치한 값이 같은 경우 '참'으로 판단합니다.\\n> : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 큰 경우 '참'으로 판단합니다.\\n< : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 작은 경우 '참'으로 판단합니다.\\n≥ : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 크거나 같은 경우 '참'으로 판단합니다.\\n≤ : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 작거나 같은 경우 '참'으로 판단합니다.\",\n    function_create:\n        '자주 쓰는 코드를 이 블록 아래에 조립하여 함수로 만듭니다. [함수 정의하기]의 오른쪽 빈칸에 [이름]을 조립하여 함수의 이름을 정할 수 있습니다. 함수를 실행하는 데 입력값이 필요한 경우 빈칸에 [문자/숫자값], [판단값]을 조립하여 매개변수로 사용합니다.',\n    function_field_label: \"함수 정의하기' 블록 안에 조립하며, 함수의 이름을 정합니다. \",\n    function_field_string:\n        \"함수 정의하기' 블록 안에 조립하며, 입력한 문자/숫자값(매개변수)에 따라 함수의 실행 결과가 달라집니다. 이 블록을 분리하여 함수의 코드 중 필요한 부분에 넣어 사용합니다.\",\n    function_field_boolean:\n        \"함수 정의하기' 블록 안에 조립하며, 참 또는 거짓의 판단값에 따라 함수의 실행 결과가 달라집니다. 이 블록을 분리하여 함수의 코드 중 필요한 부분에 넣어 사용합니다.\",\n    function_general: '현재 만들고 있는 함수 블록 또는 지금까지 만들어 둔 함수 블록입니다.',\n    boolean_and: '두 판단이 모두 참인 경우 ‘참’으로 판단합니다.',\n    boolean_or: '두 판단 중 하나라도 참이 있는 경우 ‘참’으로 판단합니다.',\n    boolean_not: '해당 판단이 참이면 거짓, 거짓이면 참으로 만듭니다.',\n    calc_basic:\n        '입력한 두 수의 사칙연산 값입니다.\\n+ : 입력한 두 수를 더한 값입니다.\\n- : 입력한 두 수를 뺀 값입니다.\\n* : 입력한 두 수를 곱한 값입니다.\\n/ : 입력한 두 수를 나눈 값입니다.',\n    calc_rand:\n        '입력한 두 수 사이에서 선택된 무작위 수 값입니다. (두 수 모두 정수를 입력한 경우 정수가, 두 수 중 하나라도 소수를 입력한 경우 소숫점 둘째 자리의 소수 값이 선택됩니다.)',\n    get_x_coordinate: '해당 오브젝트의 x 좌푯값을 의미합니다.',\n    get_y_coordinate: '해당 오브젝트의 y 좌푯값을 의미합니다.',\n    coordinate_mouse: '마우스 포인터의 x 또는 y 좌푯값입니다.',\n    coordinate_object:\n        '선택한 오브젝트의 각종 정보 값입니다. (x 좌표, y 좌표, 방향, 이동방향, 크기, 모양번호, 모양이름)',\n    quotient_and_mod:\n        '입력된 두 수를 나눈 결괏값입니다.\\n몫 : 앞의 수에서 뒤의 수를 나누어 생긴 몫의 값입니다. \\n나머지 : 앞의 수에서 뒤의 수를 나누어 생긴 나머지 값입니다.',\n    get_rotation_direction: '해당 오브젝트의 방향값, 이동 방향값을 의미합니다.',\n    calc_share: '앞 수에서 뒤 수를 나누어 생긴 몫을 의미합니다.',\n    calc_mod: '앞 수에서 뒤 수를 나누어 생긴 나머지를 의미합니다.',\n    calc_operation:\n        '입력한 수에 대한 다양한 수학식의 계산값입니다. (제곱, 루트, 사인값, 코사인값, 탄젠트값, 아크사인값, 아크코사인값, 아크탄젠트값, 로그값, 자연로그값, 소수점 부분, 소수점 버림값, 소수점 올림값, 소수점 반올림값, 펙토리얼값, 절대값)',\n    get_date: '현재 연도, 월, 일, 시각과 같이 시간에 대한 값입니다.',\n    distance_something: '해당 오브젝트와 선택한 오브젝트 또는 마우스 포인터 간의 거릿값입니다.',\n    get_sound_duration: '선택한 소리의 길이(초) 값입니다.',\n    get_user_name: '작품을 실행하고 있는 사용자의 이름값입니다.',\n    get_project_timer_value: '이 블록이 실행되는 순간 초시계에 저장된 값입니다.',\n    choose_project_timer_action:\n        '초시계의 상태를 결정합니다.\\n시작하기: 초시계를 시작합니다. \\n정지하기: 초시계를 정지합니다. \\n초기화하기: 초시계의 값을 0으로 초기화합니다. ',\n    reset_project_timer: '실행되고 있던 타이머를 0으로 초기화합니다.',\n    set_visible_project_timer: '초시계 창을 실행화면에서 숨기거나 보이게 합니다.',\n    ask_and_wait:\n        '오브젝트가 입력한 문자를 말풍선으로 묻고, 대답을 입력받습니다. (이 블록이 실행되면 실행화면에 ‘대답 창’이 생성됩니다.)',\n    get_canvas_input_value: \"사용자가 '대답 창'에 입력한 값입니다.\",\n    set_visible_answer: \"대답 창'을 실행화면에서 숨기거나 보이게 합니다.\",\n    combine_something: '입력한 두 값을 결합한 값입니다.',\n    get_variable: '선택한 변수에 저장된 값입니다.',\n    change_variable: '선택한 변수에 입력한 값을 더합니다.',\n    set_variable: '선택한 변수의 값을 입력한 값으로 정합니다.',\n    robotis_carCont_sensor_value:\n        '왼쪽 접속 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>오른쪽 접촉 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>선택 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.<br/>최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>왼쪽 적외선 센서 : 물체와 가까울 수록 큰 값 입니다.<br/>오른쪽 적외선 센서 : 물체와 가까울 수록 큰 값 값 입니다.<br/>왼쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>오른쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>(*캘리브레이션 값 - 적외선센서 조정 값)',\n    robotis_carCont_cm_led:\n        '4개의 LED 중 1번 또는 4번 LED 를 켜거나 끕니다.<br/>LED 2번과 3번은 동작 지원하지 않습니다.',\n    robotis_carCont_cm_sound_detected_clear: '최종 소리 감지횟 수를 0 으로 초기화 합니다.',\n    robotis_carCont_aux_motor_speed: '감속모터 속도를 0 ~ 1023 의 값(으)로 정합니다.',\n    robotis_carCont_cm_calibration:\n        '적외선센서 조정 값(http://support.robotis.com/ko/: 자동차로봇> 2. B. 적외선 값 조정)을 직접 정합니다.',\n    robotis_openCM70_sensor_value:\n        '최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.',\n    robotis_openCM70_aux_sensor_value:\n        '서보모터 위치 : 0 ~ 1023, 중간 위치의 값은 512 입니다.<br/>적외선센서 :  물체와 가까울 수록 큰 값 입니다.<br/>접촉센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>조도센서(CDS) : 0 ~ 1023, 밝을 수록 큰 값 입니다.<br/>온습도센서(습도) : 0 ~ 100, 습할 수록 큰 값 입니다.<br/>온습도센서(온도) : -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>온도센서 :  -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>초음파센서 : -<br/>자석센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>동작감지센서 : 동작 감지(1), 동작 미감지(0) 값 입니다.<br/>컬러센서 : 알수없음(0), 흰색(1), 검은색(2), 빨간색(3), 녹색(4), 파란색(5), 노란색(6) 값 입니다.<br/>사용자 장치 : 사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_buzzer_index: '음계를 0.1 ~ 5 초 동안 연주 합니다.',\n    robotis_openCM70_cm_buzzer_melody:\n        \"멜로디를 연주 합니다.<br/>멜로디를 연속으로 재생하는 경우, 다음 소리가 재생되지 않으면 '흐름 > X 초 기다리기' 블록을 사용하여 기다린 후 실행합니다.\",\n    robotis_openCM70_cm_sound_detected_clear: '최종 소리 감지횟 수를 0 으로 초기화 합니다.',\n    robotis_openCM70_cm_led: '제어기의 빨간색, 녹색, 파란색 LED 를 켜거나 끕니다.',\n    robotis_openCM70_cm_motion: '제어기에 다운로드 되어있는 모션을 실행합니다.',\n    robotis_openCM70_cm_autodrive_motor: '자율주행 자동차의 모터 포트를 지정합니다.',\n    robotis_openCM70_cm_autodrive_ir: '자율주행 자동차의 적외선 센서 포트를 지정합니다.',\n    robotis_openCM70_cm_autodrive_speed: '차로를 따라 지정한 속도로 자율주행을 수행합니다.',\n    robotis_openCM70_aux_motor_speed: '감속모터 속도를 0 ~ 100% 의 값(으)로 정합니다.',\n    robotis_openCM70_aux_servo_mode:\n        '서보모터를 회전모드 또는 관절모드로 정합니다.<br/>한번 설정된 모드는 계속 적용됩니다.<br/>회전모드는 서보모터 속도를 지정하여 서보모터를 회전 시킵니다.<br/>관절모드는 지정한 서보모터 속도로 서보모터 위치를 이동 시킵니다.',\n    robotis_openCM70_aux_servo_speed: '서보모터 속도를 0 ~ 100% 의 값(으)로 정합니다.',\n    robotis_openCM70_aux_servo_position:\n        '서보모터 위치를 -150도 ~ 150도 의 값(으)로 정합니다.<br/>서보모터 속도와 같이 사용해야 합니다.',\n    robotis_openCM70_aux_led_module: 'LED 모듈의 LED 를 켜거나 끕니다.',\n    robotis_openCM70_aux_custom:\n        '사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_poweroff_timer:\n        '제어기의 자동꺼짐 타이머를 설정합니다.<br/>설정된 만큼의 시간동안 통신이 진행되지 않으면 제어기는 자동으로 꺼집니다.',\n    robotis_openCM70_cm_custom_value:\n        '컨트롤 테이블 주소를 직접 입력하여 값을 확인 합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_custom:\n        '컨트롤 테이블 주소를 직접 입력하여 값을 정합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    show_variable: \"선택한 변수의 '변수 창'을 실행화면에 보이게 합니다.\",\n    hide_variable: \"선택한 변수의 '변수 창'을 실행화면에서 숨깁니다.\",\n    value_of_index_from_list: '선택한 리스트에서 입력한 순서에 있는 항목 값입니다.',\n    add_value_to_list: '입력한 값을 선택한 리스트의 마지막 항목에 추가합니다.',\n    remove_value_from_list: '선택한 리스트의 입력한 순서에 있는 항목을 삭제합니다.',\n    insert_value_to_list:\n        '입력한 값을 선택한 리스트의 입력한 순서의 항목으로 추가합니다. (입력한 항목 뒤에 있는 항목들은 순서가 하나씩 밀려납니다.)',\n    change_value_list_index:\n        '선택한 리스트에서 입력한 순서에 있는 항목의 값을 입력한 값으로 바꿉니다.',\n    length_of_list: '선택한 리스트가 보유한 항목의 개수입니다.',\n    show_list: \"선택한 리스트의 '리스트 창'을 실행화면에 보이게 합니다.\",\n    hide_list: \"선택한 리스트의 '리스트 창'을 실행화면에서 숨깁니다.\",\n    text: '해당 글상자가 표시하고 있는 문자값을 의미합니다.',\n    text_read:\n        '선택한 글상자에 작성된 내용입니다. (내용 안에 줄 바꿈이 있는 경우, 띄어쓰기하여 반환됩니다.)',\n    text_write: '글상자의 내용을 입력한 값으로 고쳐 씁니다.',\n    text_append: '글상자의 내용 뒤에 입력한 값을 추가합니다.',\n    text_prepend: '글상자의 내용 앞에 입력한 값을 추가합니다.',\n    text_flush: '글상자의 내용을 모두 지웁니다.',\n    erase_all_effects: '오브젝트에 적용된 효과를 모두 지웁니다.',\n    char_at: '입력한 값에서 입력한 숫자 번째의 글자 값입니다. (공백을 포함합니다.)',\n    length_of_string: '입력한 값의 공백을 포함한 글자 수입니다.',\n    substring: '입력한 값에서 입력한 범위 내의 글자 값입니다. (공백을 포함합니다.)',\n    replace_string:\n        '입력한 값에서 지정한 값을 찾아 추가로 입력한 값으로 모두 바꾼 값입니다. (영문 입력 시 대소문자를 구분합니다.)',\n    index_of_string:\n        '입력한 값에서 지정한 값이 처음으로 등장하는 위치 값입니다. (공백을 포함합니다.)',\n    change_string_case: '입력한 영문의 모든 알파벳을 대문자 또는 소문자로 바꾼 값입니다.',\n    direction_relative_duration:\n        '오브젝트의 이동 방향이 입력한 시간에 걸쳐 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    get_sound_volume: '작품에 설정된 소리의 크기 값입니다.',\n    sound_from_to:\n        '해당 오브젝트가 선택한 소리를 입력한 구간을 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_from_to_and_wait:\n        '해당 오브젝트가 선택한 소리를 입력한 구간을 재생한 후 다음 블록을 실행합니다.',\n    Block_info: '블록 설명',\n    Block_click_msg: '블록을 클릭하면<br>블록에 대한 설명이 나타납니다.',\n    hamster_beep: '버저 소리를 짧게 냅니다.',\n    hamster_change_both_wheels_by:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    hamster_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    hamster_change_output_by:\n        '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    hamster_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    hamster_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    hamster_clear_buzzer: '버저 소리를 끕니다.',\n    hamster_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n    hamster_follow_line_until:\n        '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n    hamster_follow_line_using:\n        '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n    hamster_hand_found:\n        \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    hamster_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n    hamster_move_forward_for_secs: '입력한 시간(초) 동안 앞으로 이동합니다.',\n    hamster_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n    hamster_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    hamster_rest_for: '입력한 박자만큼 쉽니다.',\n    hamster_set_both_wheels_to:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    hamster_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n    hamster_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    hamster_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n    hamster_set_output_to:\n        '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    hamster_set_port_to: '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n    hamster_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    hamster_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    hamster_stop: '양쪽 바퀴를 정지합니다.',\n    hamster_turn_for_secs: '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    hamster_turn_once: '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n    hamster_value:\n        '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n    roboid_hamster_beep: '버저 소리를 짧게 냅니다.',\n    roboid_hamster_change_both_wheels_by:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_hamster_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    roboid_hamster_change_output_by:\n        '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    roboid_hamster_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    roboid_hamster_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_hamster_clear_buzzer: '버저 소리를 끕니다.',\n    roboid_hamster_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n    roboid_hamster_follow_line_until:\n        '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n    roboid_hamster_follow_line_using:\n        '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n    roboid_hamster_hand_found:\n        \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_hamster_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n    roboid_hamster_move_forward_for_secs: '입력한 시간(초) 동안 앞으로 이동합니다.',\n    roboid_hamster_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n    roboid_hamster_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    roboid_hamster_rest_for: '입력한 박자만큼 쉽니다.',\n    roboid_hamster_set_both_wheels_to:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_hamster_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n    roboid_hamster_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    roboid_hamster_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n    roboid_hamster_set_output_to:\n        '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    roboid_hamster_set_port_to: '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n    roboid_hamster_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    roboid_hamster_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_hamster_stop: '양쪽 바퀴를 정지합니다.',\n    roboid_hamster_turn_for_secs:\n        '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    roboid_hamster_turn_once: '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n    roboid_hamster_value:\n        '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n    roboid_turtle_button_state:\n        \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    roboid_turtle_change_head_led_by_rgb: '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n    roboid_turtle_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    roboid_turtle_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_turtle_change_wheels_by_left_right:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_turtle_clear_head_led: '머리 LED를 끕니다.',\n    roboid_turtle_clear_sound: '소리를 끕니다.',\n    roboid_turtle_cross_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n    roboid_turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n    roboid_turtle_follow_line_until:\n        '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n    roboid_turtle_follow_line_until_black:\n        '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n    roboid_turtle_is_color_pattern:\n        \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n    roboid_turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n    roboid_turtle_pivot_around_wheel_unit_in_direction:\n        '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n    roboid_turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n    roboid_turtle_play_note_for_beats: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    roboid_turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n    roboid_turtle_play_sound_times_until_done:\n        '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n    roboid_turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n    roboid_turtle_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n    roboid_turtle_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    roboid_turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n    roboid_turtle_set_head_led_to_rgb: '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n    roboid_turtle_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    roboid_turtle_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_turtle_set_wheels_to_left_right:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_turtle_stop: '양쪽 바퀴를 정지합니다.',\n    roboid_turtle_touching_color:\n        \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_turn_at_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n    roboid_turtle_turn_unit_in_place:\n        '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    roboid_turtle_turn_unit_with_radius_in_direction:\n        '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n    roboid_turtle_value:\n        '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n    turtle_button_state:\n        \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    turtle_change_head_led_by_rgb: '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n    turtle_change_tempo_by: '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    turtle_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    turtle_change_wheels_by_left_right:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    turtle_clear_head_led: '머리 LED를 끕니다.',\n    turtle_clear_sound: '소리를 끕니다.',\n    turtle_cross_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n    turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n    turtle_follow_line_until:\n        '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n    turtle_follow_line_until_black:\n        '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n    turtle_is_color_pattern:\n        \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n    turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n    turtle_pivot_around_wheel_unit_in_direction:\n        '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n    turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n    turtle_play_note_for_beats: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n    turtle_play_sound_times_until_done:\n        '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n    turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n    turtle_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n    turtle_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n    turtle_set_head_led_to_rgb: '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n    turtle_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    turtle_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    turtle_set_wheels_to_left_right:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    turtle_stop: '양쪽 바퀴를 정지합니다.',\n    turtle_touching_color:\n        \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_turn_at_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n    turtle_turn_unit_in_place:\n        '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    turtle_turn_unit_with_radius_in_direction:\n        '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n    turtle_value:\n        '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n    neobot_sensor_value:\n        'IN1 ~ IN3 포트 및 리모컨에서 입력되는 값 그리고 배터리 정보를 0부터 255의 숫자로 표시합니다.',\n    neobot_sensor_convert_scale:\n        '선택한 포트 입력값의 변화를 특정범위의 값으로 표현범위를 조절할 수 있습니다.',\n    neobot_left_motor: 'L모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.',\n    neobot_stop_left_motor: 'L모터 포트에 연결한 모터를 정지합니다.',\n    neobot_right_motor: 'R모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.',\n    neobot_stop_right_motor: 'R모터 포트에 연결한 모터를 정지합니다.',\n    neobot_all_motor:\n        'L모터 및 R모터 포트에 2개 모터를 연결하여 바퀴로 활용할 때 전, 후, 좌, 우 이동 방향 및 속도, 시간을 설정할 수 있습니다.',\n    neobot_stop_all_motor: 'L모터 및 R모터에 연결한 모터를 모두 정지합니다.',\n    neobot_set_servo:\n        'OUT1 ~ OUT3에 서보모터를 연결했을 때 0도 ~ 180도 범위 내에서 각도를 조절할 수 있습니다.',\n    neobot_set_output:\n        'OUT1 ~ OUT3에 라이팅블록 및 전자회로를 연결했을 때 출력 전압을 설정할 수 있습니다.</br>0은 0V, 1 ~ 255는 2.4 ~ 4.96V의 전압을 나타냅니다.',\n    neobot_set_fnd: 'FND로 0~99 까지의 숫자를 표시할 수 있습니다.',\n    neobot_set_fnd_off: 'FND에 표시한 숫자를 끌 수 있습니다.',\n    neobot_play_note_for:\n        '주파수 발진 방법을 이용해 멜로디에 반음 단위의 멜로디 음을 발생시킬 수 있습니다.',\n    rotate_by_angle_dropdown:\n        '오브젝트의 방향을 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    chocopi_control_button:\n        '버튼이 눌리면 참이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_control_event:\n        '버튼을 누르거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_control_joystick:\n        '조이스틱 좌우, 상하, 볼륨의 값은 0~4095까지 입니다.<br/>따라서 2047 근처가 중간이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_dc_motor:\n        'DC모터 모듈에는 직류전동기 두개를 연결 할 수 있습니다.<br/> 직류 전동기는 최대 5V로 동작하게 됩니다.<br/>값은 100이 최대(100%)이고 음수를 넣으면 반대 방향으로 회전합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_led:\n        'LED번호는 LED블록에 연결된 순서이고 1번부터 시작합니다.<br/>RGB값은 0~255사이의 값입니다.<br/>빨강(Red),녹색(Green), 파랑(Blue)순서로  입력합니다.<br/>밝은 LED를 직접보면 눈이 아프니까 값을 0~5정도로 씁니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_event:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br/>빛센서를 물체로 가리거나 치우면 시작되는 엔트리 블록을 연결합니다<br/>모션 모듈에는 포토게이트 2개를 연결할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_status:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>물체가 빛센서를 가리면 참</b>이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_time:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>이 블록은 물체가 빛센서를 가리거나 벗어난 시간을 가집니다.<br/>1/10000초까지 측정할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_value:\n        '모션 모듈에는 3개의 적외선 센서가 있습니다.<br/>0~4095사이의 값을 가질 수 있는데 물체가 빛을 많이 반사할 수록 작은 값을 가집니다. <br/>거리를 대략적으로 측정할 수 있습니다. <br/>가속도와 각가속도 값의 범위는 -32768~32767 까지입니다.<br/>가속도를 이용해서 센서의 기울기를 측정할 수도 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_sensor:\n        '온도 값은 섭씨 온도입니다.<br/>습도 값은 백분율로 나타낸 상대습도 값입니다.<br/>빛은 로그스케일로 0~4095사이입니다.<br/>아날로그 값은 0~4095사이입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_servo_motor:\n        '서보모터 모듈에는 4개의 서보모터를 연결 할 수 있습니다.<br/>서보모터는 5V로 동작하게 됩니다.<br/>각도는 0~200도까지 지정할 수 있습니다.<br/>연속회전식 서보모터를 연결하면 각도에 따라 속도가 변하게됩니다.<br/>90~100 사이가 중간값입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_event:\n        '터치 모듈에는 1~12번의 연결 패드가 있습니다. <br/>만지거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_status:\n        '터치 모듈의 패드를 만지면 참이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_value:\n        '터치패드에 연결된 물체의 전기용량이 커지면 값이 작아집니다.<br/>여러 명이 손잡고 만지면 더 작은 값이 됩니다.<br/>전기용량이란 물체에 전기를 띈 입자를 얼마나 가지고 있을 수 있는 지를 말합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    boolean_and_or:\n        '그리고 : 두 판단이 모두 참인 경우 ‘참’으로 판단합니다.<br>또는 : 두 판단 중 하나라도 참이 있는 경우 ‘참’으로 판단합니다.',\n    check_weather:\n        '<br>선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈',\n    check_finedust:\n        '<br>선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨',\n    get_weather_data:\n        '<br>선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)',\n    get_current_weather_data:\n        '<br>현재 선택한 지역의 날씨 정보값(기온, 미세먼지농도)입니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 정보: (기온(℃)), 미세먼지농도(㎍)',\n    get_today_temperature:\n        '<br>오늘 선택한 지역과 시간대의 기온을 의미합니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 시간대: 00, 03, 06, 09, 12, 15, 18, 21',\n    check_city_weather:\n        '선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.\\n* 옵션\\n날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후\\n시도: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈',\n    check_city_finedust:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.\\n* 옵션\\n시도: 서울, 강원, 경기, 경남, 경북,광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨',\n    get_city_weather_data:\n        '선택한 날짜와 지역의 각종 날씨 정보입니다.\\n *옵션\\n날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후\\n시도:서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)',\n    get_current_city_weather_data:\n        '현재 선택한 지역의 날씨 정보입니다.\\n*옵션\\n시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n정보: 기온(℃), 미세먼지농도(㎍)',\n    get_today_city_temperature:\n        '오늘 선택한 지역과 시간대의 기온입니다.\\n*옵션\\n시도: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n시간대: 00, 03, 06, 09, 12, 15, 18, 21',\n    count_festival:\n        '선택한 날짜와 지역에서 열리는 행사의 수입니다.\\n* 옵션 \\n지역: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n행사일: 1~12월',\n    get_festival_info:\n        '선택한 날짜와 지역에서 열리는 행사에 대한 정보입니다.\\n* 옵션 \\n지역: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n행사일: 1~12월 \\n정보: 제목, 지역, 시작일, 종료일, 주소, 개요, 홈페이지',\n    get_translated_string:\n        '입력한 문자값을 선택한 언어로 번역합니다. 입력은 3000자까지 가능합니다.\\n*번역 가능한 언어 \\n - 한국어 → 영어, 중국어 간체, 중국어 번체, 베트남어, 스페인어, 인도네시아어, 태국어, 프랑스어\\n - 영어 → 일본어, 프랑스어, 한국어\\n - 중국어 간체, 중국어 번체, 베트남어, 스페인어, 인도네시아어, 태국어, 프랑스어 → 한국어\\n - 일본어 →영어 \\n - 프랑스어 → 영어',\n    check_language: '입력된 문자값의 언어를 감지합니다. 입력은 문장 형태로 3000자까지 가능합니다.',\n    count_disaster_behavior:\n        '선택한 자연재해가 발생했을 때 해야할 행동요령의 수입니다.<br> *옵션<br> 자연재해: 태풍, 홍수, 호우, 강풍, 대설, 한파, 풍랑, 황사, 폭염, 가뭄, 지진, 해일, 산사태<br> 상황: 자연재해에 따라 다름 ',\n    get_disaster_behavior:\n        '선택한 자연재해가 발생했을 때 해야하는 행동요령에 대한 정보입니다.<br> *옵션<br> 자연재해: 태풍, 홍수, 호우, 강풍, 대설, 한파, 풍랑, 황사, 폭염, 가뭄, 지진, 해일, 산사태<br> 상황: 자연재해에 따라 다름',\n    count_lifeSafety_behavior:\n        '선택한 생활 속 문제가 발생했을 때 해야할 행동요령의 수입니다.<br> *옵션<br> 생활 속 문제: 응급처치, 심폐소생술, 소화기·소화전 사용법, 식중독, 산행안전, 실종유괴, 성폭력, 학교폭력, 가정 폭력, 억류 및 납치, 교통사고, 승강기 안전사고, 미세먼지<br> 상황: 생활 속 문제에 따라 다름 ',\n    get_lifeSafety_behavior:\n        '선택한 생활 속 문제가 발생했을 때 해야할 행동요령에 대한 정보입니다.<br> *옵션<br> 생활 속 문제: 응급처치, 심폐소생술, 소화기·소화전 사용법, 식중독, 산행안전, 실종유괴, 성폭력, 학교폭력, 가정 폭력, 억류 및 납치, 교통사고, 승강기 안전사고, 미세먼지<br> 상황: 생활 속 문제에 따라 다름 ',\n    read_text:\n        '입력한 문자값을 설정된 목소리로 읽습니다.<br>입력은 2500자까지 가능합니다.<br>인터넷에 연결되어 있지 않거나 인터넷 환경이 불안할 경우, 해당 블록이 실행되지 않고 다음 블록으로 넘어갈 수 있습니다.',\n    set_tts_property: '선택한 목소리가 선택한 속도와 선택한 음높이로 설정됩니다.',\n    read_text_wait_with_block: '입력한 문자값을 읽어준 후 다음 블록을 실행합니다.',\n    check_microphone:\n        \"컴퓨터에 마이크가 연결되어 있는 경우 '참'으로 판단합니다. (IE/Safari 브라우저 지원하지 않음)\",\n    speech_to_text_convert:\n        '마이크에 입력되는 사람의 목소리를 텍스트로 변환합니다. (IE/Safari 브라우저 지원하지 않음)',\n    get_microphone_volume:\n        '마이크에 입력되는 소리의 크기 값입니다. (IE/Safari 브라우저 지원하지 않음)',\n    speech_to_text_get_value:\n        '사람의 목소리를 문자로 바꾼 값입니다. 목소리가 입력되지 않거나, 음성인식 도중 오류가 발생한 경우 무조건 0 값을 갖습니다. (IE/Safari 브라우저 지원하지 않음)',\n    video_draw_webcam:\n        '컴퓨터에 연결된 카메라에 촬영되는 화면을 실행화면에서 보이게하거나 숨깁니다.',\n    video_check_webcam: \"컴퓨터에 카메라가 연결되어 있는 경우 '참'으로 판단합니다.\",\n    video_set_camera_option:\n        '촬영되는 화면의 효과를 입력한 값으로 정합니다.  밝기: -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.) 투명도: 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로 100 이상은 100으로 처리됩니다.)',\n    video_flip_camera: '촬영되는 화면을 좌우 혹은 상하로 뒤집습니다.',\n    video_toggle_model:\n        '선택한 인식모델을 동작시키거나 중지시킵니다. 얼굴 인식: 사람의 얼굴을 인식하여 눈, 코, 입, 귀의 위치나 예상되는 성별, 나이, 감정을 알 수 있습니다. 사람 인식: 사람의 몸을 인식하여 각 신체부위의 위치 등을 알 수 있습니다. 객체 인식: 인식된 객체의 종류를 알 수 있습니다. (사람이나 물건)',\n    video_toggle_ind: '인식 된 사람 / 얼굴 / 사물 을 화면에 표시하거나 숨깁니다',\n    video_number_detect:\n        '인식된 사람 / 얼굴 / 사물의 숫자입니다 촬영되는 화면에 객체로 인식된 객체의 개수입니다. *인식할 수 있는 사물: 사람, 자전거, 자동차, 오토바이, 비행기, 버스, 기차, 트럭, 보트,교통 신호등, 소화전, 정지 신호, 주차 미터, 벤치, 새, 고양이, 개, 말, 양, 암소, 코끼리, 곰, 얼룩말, 기린, 책가방, 우산, 핸드백, 넥타이, 가방, 프리스비, 스키, 스노보드, 스포츠 볼, 연, 야구 방망이, 야구 글러브, 스케이트 보드, 서핑 보드, 테니스 라켓, 병, 와인 글라스, 컵, 포크, 나이프, 숟가락, 그릇, 바나나, 애플, 샌드위치, 주황색, 브로콜리, 당근, 핫도그, 피자, 도넛, 케이크, 의자, 소파, 화분, 침대, 식사테이블, 화장실, TV 모니터, 노트북, 마우스, 원격, 키보드, 휴대 전화, 전자 레인지, 오븐, 토스터기, 싱크대, 냉장고, 도서, 시계, 꽃병, 가위, 테디베어, 헤어드라이어, 칫솔',\n    video_detected_face_info:\n        '입력한 순서의 얼굴의 선택한 정보의 추정값입니다. 인식이 잘 되지 않는 경우 무조건 0으로 출력됩니다. (성별, 나이, 감정)',\n    video_motion_value:\n        '선택한 오브젝트 혹은 실행화면 위에서 감지되는 움직임 혹은 방향 값입니다. 움직임: 움직임이 크고 빠를 수록 값이 커집니다. 방향: 오른쪽 혹은 위쪽으로 움직일 때 양수, 왼쪽 혹은 아래쪽으로 움직일 때 음수가 됩니다.',\n    video_face_part_coord:\n        '입력한 순서의 얼굴 중 선택된 얼굴 부위의 위치값입니다. 인식이 잘 되지 않는 경우 무조건 0으로 출력됩니다. (왼쪽 눈, 오른쪽 눈, 코, 왼쪽 입꼬리, 오른쪽 입꼬리, 윗 입술, 아랫입술)',\n    video_body_part_coord:\n        '입력한 순서의 사람의 선택한 신체 부위의 위치값입니다. (얼굴, 왼쪽 어깨, 왼쪽 팔꿈치, 왼쪽 손목, 왼쪽 엉덩이, 왼쪽 무릎, 왼쪽 발목, 오른쪽 어깨, 오른쪽 팔꿈치, 오른쪽 손목, 오른쪽 엉덩이, 오른쪽 무릎, 오른쪽 발목)',\n    append_row_to_table:\n        '선택한 테이블의 마지막에 행(열)을 추가합니다. 추가된 행(열)의 모든 열(행) 값은 0입니다.',\n    insert_row_to_table:\n        '선택한 테이블의 입력한 순서에 행(열)을 추가합니다. 추가된 행(열)의 모든 열(행) 값은 0입니다. (입력한 행(열) 뒤에 있는 행들은 순서가 하나씩 밀려납니다.',\n    delete_row_from_table: '선택한 테이블의 입력한 순서에 있는 행(열)을 삭제합니다.',\n    set_value_from_table: '선택한 테이블에서 입력한 순서의 선택된 열값을 입력한 값으로 바꿉니다.',\n    get_table_count: '선택한 테이블이 보유한 행과 열의 개수입니다.',\n    get_value_from_table: '선택한 테이블에서 입력한 순서의 선택된 열 값 입니다.',\n    calc_values_from_table:\n        '선택한 테이블에서 선택한 열들에 대한 계산값입니다. (합, 최댓값, 최솟값, 평균값, 표준편차)',\n    open_table_chart: '선택한 테이블의 차트창을 엽니다.',\n    close_table_chart: '열려있는 테이블 차트창을 닫습니다.',\n    get_coefficient:\n        '선택한 테이블에서 두 속성 사이의 상관계수입니다. 상관계수가 1(-1)에 가까울 수록 강한 양(음)의 선형 상관관계를 갖습니다.',\n};\nLang.Category = {\n    entrybot_friends: '엔트리봇 친구들',\n    people: '사람',\n    animal: '동물',\n    animal_flying: '하늘',\n    animal_land: '땅',\n    animal_water: '물',\n    animal_others: '기타',\n    plant: '식물',\n    plant_flower: '꽃',\n    plant_grass: '풀',\n    plant_tree: '나무',\n    plant_others: '기타',\n    vehicles: '탈것',\n    vehicles_flying: '하늘',\n    vehicles_land: '땅',\n    vehicles_water: '물',\n    vehicles_others: '기타',\n    architect: '건물',\n    architect_building: '건축물',\n    architect_monument: '기념물',\n    architect_others: '기타',\n    food: '음식',\n    food_vegetables: '과일/채소',\n    food_meat: '고기',\n    food_drink: '음료',\n    food_others: '기타',\n    environment: '환경',\n    environment_nature: '자연',\n    environment_space: '우주',\n    environment_others: '기타',\n    stuff: '물건',\n    stuff_living: '생활',\n    stuff_hobby: '취미',\n    stuff_others: '기타',\n    fantasy: '판타지',\n    interface: '인터페이스',\n    interface_website: '웹사이트',\n    interface_game: '게임',\n    interface_others: '기타',\n    background: '배경',\n    background_outdoor: '실외',\n    background_indoor: '실내',\n    background_nature: '자연',\n    background_others: '기타',\n};\nLang.Device = {\n    arduino: '아두이노',\n    hamster: '햄스터',\n    roboid: '로보이드',\n    turtle: '거북이',\n    albert: '알버트',\n    robotis_carCont: '로보티즈 자동차 로봇',\n    robotis_openCM70: '로보티즈 IoT',\n    sensorBoard: '엔트리 센서보드',\n    trueRobot: '뚜루뚜루',\n    CODEino: '코드이노',\n    bitbrick: '비트브릭',\n    creamo: '크리모',\n    playcode: '플레이코드',\n    funboard: '펀보드',\n    bitBlock: '비트블록',\n    xbot_epor_edge: '엑스봇',\n    dplay: '디플레이',\n    iboard: '아이보드',\n    nemoino: '네모이노',\n    ev3: 'EV3',\n    robotori: '로보토리',\n    smartBoard: '스마트보드',\n    chocopi: '초코파이보드',\n    rokoboard: '로코보드',\n    altino: '알티노',\n    mechatro: '메카트로',\n};\nLang.General = {\n    turn_on: '켜기',\n    turn_off: '끄기',\n    left: '왼쪽',\n    right: '오른쪽',\n    param_string: 'string',\n    both: '양쪽',\n    transparent: '투명',\n    black: '검은색',\n    brown: '갈색',\n    red: '빨간색',\n    yellow: '노란색',\n    green: '초록색',\n    skyblue: '하늘색',\n    blue: '파란색',\n    purple: '보라색',\n    white: '하얀색',\n    note_c: '도',\n    note_d: '레',\n    note_e: '미',\n    note_f: '파',\n    note_g: '솔',\n    note_a: '라',\n    note_b: '시',\n    questions: '문제',\n    clock: '시계',\n    counter_clock: '반시계',\n    font_size: '글자 크기',\n    second: '초',\n    alert_title: '알림',\n    confirm_title: '확인',\n    update_title: '업데이트 알림',\n    recent_download: '최신 버전 다운로드',\n    recent_download2: '최신버전 다운로드',\n    latest_version: '최신 버전입니다.',\n    dont_show_again: '다시보지 않기',\n};\nLang.Fonts = {\n    jeju_hallasan: '한라산체',\n    gothic_coding: '코딩고딕체',\n    batang: '바탕체',\n    gothic: '나눔고딕체',\n    myeongjo: '나눔명조',\n    pen_script: '나눔손글씨',\n    square_round: '나눔스퀘어라운드체',\n    jalnan: '잘난체',\n    designhouse: '디자인하우스체',\n    malssami815: '말싸미815체',\n    dunggeunmo: '둥근모꼴체',\n    hs_bombaram: 'HS봄바람체',\n    yisunshin: '이순신체',\n    goyang: '고양체',\n    flower_road: '꽃길체',\n    uhbeemysen: '어비마이센체',\n    sd_comic_stencil: '산돌 코믹스탠실',\n    sd_childfundkorea: '산돌 초록우산 어린이',\n    sd_cinema_theater: '산돌 씨네마극장',\n    sd_mapssi: '산돌 맵씨',\n    sd_shabang: '산돌 별이샤방샤방',\n    sd_woodcarving: '산돌 목각',\n    sd_yongbi: '산돌 용비어천가',\n};\nLang.Hw = {\n    note: '음표',\n    leftWheel: '왼쪽 바퀴',\n    rightWheel: '오른쪽 바퀴',\n    leftEye: '왼쪽 눈',\n    rightEye: '오른쪽 눈',\n    led: '불빛',\n    led_en: 'LED',\n    body: '몸통',\n    front: '앞쪽',\n    port_en: '',\n    port_ko: '번 포트',\n    sensor: '센서',\n    light: '빛',\n    temp: '온도',\n    switch_: '스위치',\n    right_ko: '오른쪽',\n    right_en: '',\n    left_ko: '왼쪽',\n    left_en: '',\n    up_ko: '위쪽',\n    up_en: '',\n    down_ko: '아래쪽',\n    down_en: '',\n    output: '출력',\n    left: '왼쪽',\n    right: '오른쪽',\n    sub: '서보',\n    motor: '모터',\n    '': '',\n    buzzer: '버저',\n    IR: '적외선',\n    acceleration: '가속',\n    analog: '아날로그',\n    angular_acceleration: '각가속',\n    button: '버튼',\n    humidity: '습도',\n    joystick: '조이스틱',\n    port: '포트',\n    potentiometer: '포텐시오미터',\n    servo: '서보',\n};\nLang.template = {\n    albert_hand_found: 'Entry.Albert.isHandFound()',\n    albert_is_oid_value: \"Entry.Albert.isOidValue(' %1 ' , %2 )\",\n    albert_value: '%1',\n    albert_move_forward_for_secs: 'Entry.Albert.moveForwardForSecs( %1 ) %2',\n    albert_move_backward_for_secs: 'Entry.Albert.moveBackwardForSecs( %1 ) %2',\n    albert_turn_for_secs: \"Entry.Albert.turnForSecs(' %1 ', %2 ) %3\",\n    albert_change_both_wheels_by: 'Entry.Albert.changeWheelsBy( %1 , %2 ) %3',\n    albert_set_both_wheels_to: 'Entry.Albert.setWheelsTo( %1 , %2 ) %3',\n    albert_change_wheel_by: \"Entry.Albert.changeWheelsBy(' %1 ', %2 ) %3\",\n    albert_set_wheel_to: \"Entry.Albert.setWheelsTo(' %1 ', %2 ) %3\",\n    albert_stop: 'Entry.Albert.stop() %1',\n    albert_set_pad_size_to: 'Entry.Albert.setBoardSizeTo( %1 , %2 ) %3',\n    albert_move_to_x_y_on_board: 'Entry.Albert.moveToOnBoard( %1 , %2 ) %3',\n    albert_set_orientation_on_board: 'Entry.Albert.setOrientationToOnBoard( %1 )',\n    albert_set_eye_to: \"Entry.Albert.setEyeTo(' %1 ',' %2 ') %3\",\n    albert_clear_eye: \"Entry.Albert.clearEye(' %1 ') %2\",\n    albert_body_led: \"Entry.Albert.turnBodyLed(' %1 ') %2\",\n    albert_front_led: \"Entry.Albert.turnFrontLed(' %1 ') %2\",\n    albert_beep: 'Entry.Albert.beep() %1',\n    albert_change_buzzer_by: 'Entry.Albert.changeBuzzerBy( %1 ) %2',\n    albert_set_buzzer_to: 'Entry.Albert.setBuzzerTo( %1 ) %2',\n    albert_clear_buzzer: 'Entry.Albert.clearBuzzer() %1',\n    albert_play_note_for: \"Entry.Albert.playNoteForBeats(' %1 ', %2 , %3 ) %4\",\n    albert_rest_for: 'Entry.Albert.restForBeats( %1 ) %2',\n    albert_change_tempo_by: 'Entry.Albert.changeTempoBy( %1 ) %2',\n    albert_set_tempo_to: 'Entry.Albert.setTempoTo( %1 ) %2',\n    albert_move_forward: 'move forward %1',\n    albert_move_backward: 'move backward %1',\n    albert_turn_around: 'turn %1 %2',\n    albert_set_led_to: \"Entry.Hamster.setLedTo(' %1 %2 ') %3\",\n    albert_clear_led: \"Entry.Hamster.clearLed(' %1 ') %2\",\n    albert_change_wheels_by: '%1 %2 %3',\n    albert_set_wheels_to: '%1 %2 %3',\n    arduino_text: '%1',\n    arduino_get_sensor_number: '%1  ',\n    arduino_get_port_number: '%1  ',\n    arduino_get_digital_toggle: '%1  ',\n    arduino_get_pwm_port_number: '%1  ',\n    arduino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    arduino_ext_get_analog_value: '아날로그 %1 번 센서값',\n    arduino_ext_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    arduino_ext_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n    arduino_ext_toggle_led: '디지털 %1 번 핀 %2 %3',\n    arduino_ext_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    arduino_ext_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    arduino_ext_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    arduino_ext_get_digital: '디지털 %1 번 센서값',\n    blacksmith_get_analog_value: '아날로그 %1 번 핀 센서 값',\n    blacksmith_get_analog_mapping:\n        '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n    blacksmith_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\n    blacksmith_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n    blacksmith_get_digital_toggle: '디지털 %1 번 핀 센서 값',\n    blacksmith_set_digital_toggle: '디지털 %1 번 핀 %2 %3',\n    blacksmith_set_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    blacksmith_set_digital_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    blacksmith_set_digital_buzzer: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    blacksmith_set_digital_lcd: 'LCD화면 %1 줄에 %2 나타내기 %3',\n    blacksmith_set_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n    dplay_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    nemoino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    sensorBoard_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    truetrue_get_accsensor: '가속도센서 %1 의 값',\n    truetrue_get_bottomcolorsensor: '바닥컬러센서 %1 의 값',\n    truetrue_get_frontcolorsensor: '전면컬러센서 %1 의 값',\n    truetrue_get_linesensor: '라인센서 %1 의 값',\n    truetrue_get_proxisensor: '근접센서 %1 의 값',\n    truetrue_set_colorled: '컬러LED Red %1  Green %2 Blue %3 로 설정 %4',\n    truetrue_set_dualmotor: 'DC모터 좌 %1  우 %2 속도로 %3 초 구동 %4',\n    truetrue_set_led_colorsensor: '%1 조명용 LED %2 %3',\n    truetrue_set_led_linesensor: '라인센서 조명용 LED %1 %2',\n    truetrue_set_led_proxi: '%1 조명용 LED %2 %3',\n    truetrue_set_linetracer: '라인트레이싱 모드 %1 %2',\n    truetrue_set_singlemotor: 'DC모터 %1  속도 %2 로 설정 %3',\n    CODEino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    ardublock_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    arduino_get_digital_value: '디지털 %1 번 센서값  ',\n    dplay_get_digital_value: '디지털 %1 번 센서값  ',\n    nemoino_get_digital_value: '디지털 %1 번 센서값  ',\n    sensorBoard_get_digital_value: '디지털 %1 번 센서값  ',\n    CODEino_get_digital_value: '디지털 %1 핀의 값  ',\n    CODEino_set_digital_value: '디지털 %1 핀의 %2 %3',\n    CODEino_set_pwm_value: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    ardublock_get_digital_value: '디지털 %1 번 센서값  ',\n    arduino_toggle_led: 'Digital %1 Pin %2 %3',\n    dplay_toggle_led: 'Digital %1 Pin %2 %3',\n    nemoino_toggle_led: 'Digital %1 Pin %2 %3',\n    sensorBoard_toggle_led: 'Digital %1 Pin %2 %3',\n    CODEino_toggle_led: 'Digital %1 Pin %2 %3',\n    arduino_toggle_pwm: 'Digital %1 Pin %2 %3',\n    dplay_toggle_pwm: 'Digital %1 Pin %2 %3',\n    nemoino_toggle_pwm: 'Digital %1 Pin %2 %3',\n    sensorBoard_toggle_pwm: 'Digital %1 Pin %2 %3',\n    CODEino_toggle_pwm: 'Digital %1 Pin %2 %3',\n    ardublock_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    arduino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    dplay_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    nemoino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    sensorBoard_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    CODEino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    CODEino_set_rgb_value: '컬러 LED의 %1 색상을 %2 (으)로 정하기 %3',\n    CODEino_set_rgb_add_value: '컬러 LED의 %1 색상에 %2 만큼 더하기 %3',\n    CODEino_set_rgb_off: '컬러 LED 끄기 %1',\n    CODEino_set__led_by_rgb: '컬러 LED 색상을 빨강 %1 초록 %2 파랑 %3 (으)로 정하기 %4',\n    CODEino_rgb_set_color: '컬러 LED의 색상을 %1 (으)로 정하기 %2',\n    CODEino_led_by_value: '컬러 LED 켜기 %1',\n    ardublock_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    joystick_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    joystick_get_digital_value: '디지털 %1 번 센서값  ',\n    joystick_toggle_led: 'Digital %1 Pin %2 %3',\n    joystick_toggle_pwm: 'Digital %1 Pin %2 %3',\n    joystick_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    sensorBoard_get_named_sensor_value: '%1  센서값',\n    sensorBoard_is_button_pressed: '%1  버튼을 눌렀는가?',\n    sensorBoard_led: '%1  LED %2   %3',\n    arduino_download_connector: '%1',\n    download_guide: '%1',\n    arduino_download_source: '%1',\n    arduino_connected: '%1',\n    arduino_connect: '%1',\n    arduino_reconnect: '%1',\n    CODEino_get_sensor_number: '%1  ',\n    CODEino_get_named_sensor_value: '  %1  Sensor value ',\n    CODEino_get_sound_status: 'Sound is  %1  ',\n    CODEino_get_light_status: 'Light is  %1  ',\n    CODEino_is_button_pressed: ' Operation  %1  ',\n    CODEino_get_accelerometer_direction: ' 3-AXIS Accelerometer  %1  ',\n    CODEino_get_accelerometer_value: ' 3-AXIS Accelerometer  %1 -axis value ',\n    CODEino_get_analog_value: '아날로그 %1 센서의 값',\n    iboard_button: '%1  버튼을 눌렀는가?',\n    iboard_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    iboard_get_analog_value: '아날로그 %1 번 센서값  ',\n    iboard_get_analog_value_map: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    iboard_get_digital: '디지털 %1 번 센서값  ',\n    iboard_led: 'LED %1 번을 %2 %3',\n    iboard_motor: '모터를 %2 으로 동작하기 %3',\n    iboard_pwm_led: 'LED %1 번의 밝기를 %2 (으)로 정하기 %3',\n    iboard_rgb_led: 'RGB LED의 %1 LED %2 %3',\n    iboard_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    iboard_toggle_led: '디지털 %1 번 핀 %2 %3',\n    bitbrick_when_button_pressed: '%1 버튼 %2 눌러졌을 때',\n    bitbrick_when_sensor_get_value: '%1 %2 값 %3 %4 일 때',\n    bitbrick_is_touch_pressed: '버튼 %1 이(가) %2 인가?',\n    bitbrick_is_sensor_value_compare: '%1 값 %2 %3 인가?',\n    bitbrick_sensor_value: '%1 값',\n    bitbrick_convert_scale: '변환 %1 값 %2 ~ %3 에서 %4 ~ %5',\n    bitbrick_turn_on_color_led_by_rgb: '엘이디를 빨강 %1 초록 %2 파랑 %3 %4 (으)로 켜기',\n    bitbrick_turn_on_color_led_by_picker: '엘이디를 %1 (으)로 켜기 %2',\n    bitbrick_turn_on_color_led_by_value: '엘이디를 %1 (으)로 켜기 %2',\n    bitbrick_turn_off_color_led: '엘이디 끄기 %1',\n    bitbrick_buzzer: '버저음 %1 내기 %2',\n    bitbrick_servomotor_angle: '서보모터 %1 각도 %2 %3',\n    bitbrick_dc_direction_speed: '디씨모터 %1 방향 %2 속력 %3 %4',\n    bitbrick_dc_speed: '디씨모터 %1 속도 %2 %3',\n    bitbrick_turn_off_all_motors: '모든 모터 멈추기 %1',\n    start_drawing: 'this.startDraw() %1',\n    stop_drawing: 'this.stopDraw() %1',\n    set_color: 'this.brush.color = %1 %2',\n    set_random_color: 'this.brush.color = Entry.getRandomColor() %1',\n    change_thickness: 'this.brush.thickness += %1 %2',\n    set_thickness: 'this.brush.thickness = %1 %2',\n    change_opacity: 'this.brush.opacity += %1 %2',\n    set_opacity: 'this.brush.opacity = %1 %2',\n    brush_erase_all: 'this.brush.removeAll() %1',\n    brush_stamp: 'Stamp %1',\n    change_brush_transparency: 'this.brush.opacity -= %1 %2',\n    set_brush_tranparency: 'this.brush.opacity -= %1 %2',\n    number: '%1',\n    angle: '%1',\n    color: '%1',\n    get_x_coordinate: '%1',\n    get_y_coordinate: '%1',\n    get_angle: '%1',\n    get_rotation_direction: '%1  ',\n    distance_something: '%1 %2 %3',\n    coordinate_mouse: '%1 %2 %3',\n    coordinate_object: '%1 %2 %3 %4',\n    calc_basic: '%1 %2 %3',\n    calc_plus: '%1 %2 %3',\n    calc_minus: '%1 %2 %3',\n    calc_times: '%1 %2 %3',\n    calc_divide: '%1 %2 %3',\n    calc_mod: '%1 %2 %3 %4 %5',\n    calc_share: '%1 %2 %3 %4 %5',\n    calc_operation: '%1 %2 %3 %4  ',\n    calc_rand: '%1 %2 %3 %4 %5',\n    get_date: '%1 %2   %3',\n    get_sound_duration: '%1 %2 %3',\n    get_user_name: '사용자이름',\n    reset_project_timer: '%1',\n    set_visible_project_timer: '%1 %2 %3 %4',\n    timer_variable: '%1 %2',\n    get_project_timer_value: '%1 %2',\n    char_at: '%1 %2 %3 %4 %5',\n    length_of_string: '%1 %2 %3',\n    substring: '%1 %2 %3 %4 %5 %6 %7',\n    replace_string: '%1 %2 %3 %4 %5 %6 %7',\n    change_string_case: '%1 %2 %3 %4 %5',\n    index_of_string: '%1 %2 %3 %4 %5',\n    combine_something: '%1 %2 %3 %4 %5',\n    get_sound_volume: '%1 %2',\n    quotient_and_mod: '%1 %2 %3 %4 %5 %6',\n    choose_project_timer_action: '%1 %2 %3 %4',\n    wait_second: 'Entry.wait( %1 ) %2',\n    repeat_basic: 'for ( i = 0 %1 ) %2',\n    hidden_loop: 'for ( i = 0 %1 ) %2',\n    repeat_inf: 'while(true) %1',\n    stop_repeat: 'break %1',\n    wait_until_true: 'while ( %1 != true) { } %2',\n    _if: 'if ( %1 ) %2',\n    if_else: 'if ( %1 ) %2 %3 else',\n    create_clone: 'Entry.createClone( %1 ) %2',\n    delete_clone: 'Entry.removeClone(this) %1',\n    when_clone_start: \"%1 Entry.addEventListener('clone_created')\",\n    stop_run: '프로그램 끝내기 %1',\n    repeat_while_true: 'Repeat %1 %2 %3',\n    stop_object: 'Entry.stop( %1 ) %2',\n    restart_project: 'Entry.restart() %1',\n    remove_all_clones: 'Entry.removeAllClone() %1',\n    functionAddButton: '%1',\n    function_field_label: '%1%2',\n    function_field_string: '%1%2',\n    function_field_boolean: '%1%2',\n    function_param_string: 'Character/Number',\n    function_param_boolean: 'Judgement',\n    function_create: 'define function %1 %2',\n    function_general: 'function %1',\n    expansionBlockAddButton: '%1',\n    aiUtilizeBlockAddButton: '%1',\n    aiUtilizeModelTrainButton: '%1',\n    weather_title: '%1',\n    check_weather: '%1 %2 의 날씨가 %3인가?',\n    check_finedust: '현재 %1 의 미세먼지 등급이 %2인가?',\n    get_weather_data: '%1 %2 의 %3',\n    get_current_weather_data: '현재 %1 의 %2',\n    get_today_temperature: '오늘 %1의 %2시 기온',\n    check_city_weather: '%1 %2 %3의 날씨가 %4인가?',\n    check_city_finedust: '현재 %1 %2 의 미세먼지 등급이 %3인가?',\n    get_city_weather_data: '%1 %2 %3 의 %4',\n    get_current_city_weather_data: '현재 %1 %2 의 %3',\n    get_today_city_temperature: '오늘 %1 %2의 %3시 기온',\n    translate_title: '%1',\n    get_translated_string: '%1 %2 을(를) %3로 번역한 값',\n    check_language: '%1의 언어',\n    festival_title: '%1',\n    count_festival: '%1 %2 행사의 수',\n    get_festival_info: '%1 %2 행사 %3 번째 항목의 %4',\n    behaviorConductDisaster_title: '%1',\n    count_disaster_behavior: '%1 %2 해야할 행동요령 수',\n    get_disaster_behavior: '자연재난%1 %2 해야할 행동요령 %3 번째 항목',\n    behaviorConductLifeSafety_title: '%1',\n    count_lifeSafety_behavior: '%1 에서 %2 방법의 수',\n    get_lifeSafety_behavior: '%1 에서 %2 방법 %3 번째 항목',\n    tts_title: '%1',\n    audio_title: '%1',\n    video_title: '%1',\n    read_text: '%1 읽어주기 %2',\n    set_tts_property: '%1 목소리를 %2 속도 %3 음높이로 설정하기 %4',\n    read_text_wait_with_block: '%1 읽어주고 기다리기 %2',\n    load_expansion_block: '확장 블록 불러오기',\n    load_ai_utilize_block: 'AI 블록 불러오기',\n    load_ai_utilize_train_block: '모델 학습',\n    expansion_block_descriptions: '확장 블록은 인터넷이 연결되어 있어야 정상적으로 동작합니다.',\n    aiUtilize_block_descriptions: 'AI 활용블록은 인터넷이 연결되어 있어야 정상적으로 동작합니다.',\n    weather_title_text: '날씨',\n    translate_title_text: '번역',\n    festival_title_text: '행사',\n    audio_title_text: '오디오 감지',\n    check_microphone: '마이크가 연결되었는가?',\n    get_microphone_volume: '마이크 소리크기',\n    speech_to_text_convert: '음성 인식하기 %1',\n    speech_to_text_get_value: '음성을 문자로 바꾼 값',\n    video_title_text: '비디오 감지',\n    video_draw_webcam: '비디오 화면 %1 %2',\n    video_check_webcam: '비디오가 연결되었는가?',\n    video_set_camera_opacity_option: '비디오 투명도 효과를 %1 으로 정하기 %2',\n    video_flip_camera: '비디오 화면 %1 뒤집기 %2',\n    video_toggle_model: '%1 인식 %2 %3',\n    video_toggle_ind: '인식된 %1 %2 %3',\n    video_number_detect: '인식된 %1 의 수',\n    video_detected_face_info: '%1 번째 얼굴의 %2',\n    video_motion_value: '%1 에서 감지한 %2 값',\n    video_face_part_coord: '%1 번째 얼굴의 %2 의 %3 좌표',\n    video_body_part_coord: '%1 번째 사람의 %2 의 %3 좌표',\n    behaviorConductDisaster_title_text: '자연재난 국민행동요령',\n    behaviorConductLifeSafety_title_text: '생활안전 국민행동요령',\n    tts_title_text: '읽어주기',\n    hamster_hand_found: 'Entry.Hamster.isHandFound()',\n    hamster_value: '%1',\n    hamster_move_forward_once: 'Entry.Hamster.moveForwardOnceOnBoard() %1',\n    hamster_turn_once: \"Entry.Hamster.turnOnceOnBoard(' %1 ') %2\",\n    hamster_move_forward_for_secs: 'Entry.Hamster.moveForwardForSecs( %1 ) %2',\n    hamster_move_backward_for_secs: 'Entry.Hamster.moveBackwardForSecs( %1 ) %2',\n    hamster_turn_for_secs: \"Entry.Hamster.turnForSecs(' %1 ', %2 ) %3\",\n    hamster_change_both_wheels_by: 'Entry.Hamster.changeWheelsBy( %1, %2 ) %3',\n    hamster_set_both_wheels_to: 'Entry.Hamster.setWheelsTo( %1, %2 ) %3',\n    hamster_change_wheel_by: \"Entry.Hamster.changeWheelsBy(' %1 ', %2 ) %3\",\n    hamster_set_wheel_to: \"Entry.Hamster.setWheelsTo(' %1 ', %2 ) %3\",\n    hamster_follow_line_using: \"Entry.Hamster.followLineUsingFloorSensor(' %1 ',' %2 ') %3\",\n    hamster_follow_line_until: \"Entry.Hamster.followLineUntilIntersection(' %1 ',' %2 ') %3\",\n    hamster_set_following_speed_to: 'Entry.Hamster.setFollowingSpeedTo( %1 ) %2',\n    hamster_stop: 'Entry.Hamster.stop() %1',\n    hamster_set_led_to: \"Entry.Hamster.setLedTo(' %1 ',' %2 ') %3\",\n    hamster_clear_led: \"Entry.Hamster.clearLed(' %1 ') %2\",\n    hamster_beep: 'Entry.Hamster.beep() %1',\n    hamster_change_buzzer_by: 'Entry.Hamster.changeBuzzerBy( %1 ) %2',\n    hamster_set_buzzer_to: 'Entry.Hamster.setBuzzerTo( %1 ) %2',\n    hamster_clear_buzzer: 'Entry.Hamster.clearBuzzer() %1',\n    hamster_play_note_for: \"Entry.Hamster.playNoteForBeats(' %1 ', %2 , %3 ) %4\",\n    hamster_rest_for: 'Entry.Hamster.restForBeats( %1 ) %2',\n    hamster_change_tempo_by: 'Entry.Hamster.changeTempoBy( %1 ) %2',\n    hamster_set_tempo_to: 'Entry.Hamster.setTempoTo( %1 ) %2',\n    hamster_set_port_to: \"Entry.Hamster.setPortTo(' %1 ',' %2 ') %3\",\n    hamster_change_output_by: \"Entry.Hamster.changeOutputBy(' %1 ', %2 ) %3\",\n    hamster_set_output_to: \"Entry.Hamster.setOutputTo(' %1 ', %2 ) %3\",\n    roboid_hamster_beep: '햄스터 %1: 삐 소리내기 %2',\n    roboid_hamster_change_both_wheels_by: '햄스터 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n    roboid_hamster_change_buzzer_by: '햄스터 %1: 버저 음을 %2 만큼 바꾸기 %3',\n    roboid_hamster_change_output_by: '햄스터 %1: 출력 %2 를 %3 만큼 바꾸기 %4',\n    roboid_hamster_change_tempo_by: '햄스터 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n    roboid_hamster_change_wheel_by: '햄스터 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n    roboid_hamster_clear_buzzer: '햄스터 %1: 버저 끄기 %2',\n    roboid_hamster_clear_led: '햄스터 %1: %2 LED 끄기 %3',\n    roboid_hamster_follow_line_until: '햄스터 %1: %2 선을 따라 %3 교차로까지 이동하기 %4',\n    roboid_hamster_follow_line_using: '햄스터 %1: %2 선을 %3 바닥 센서로 따라가기 %4',\n    roboid_hamster_hand_found: '햄스터 %1: 손 찾음?',\n    roboid_hamster_move_backward_for_secs: '햄스터 %1: 뒤로 %2 초 이동하기 %3',\n    roboid_hamster_move_forward_for_secs: '햄스터 %1: 앞으로 %2 초 이동하기 %3',\n    roboid_hamster_move_forward_once: '햄스터 %1: 말판 앞으로 한 칸 이동하기 %2',\n    roboid_hamster_play_note_for: '햄스터 %1: %2 %3 음을 %4 박자 연주하기 %5',\n    roboid_hamster_rest_for: '햄스터 %1: %2 박자 쉬기 %3',\n    roboid_hamster_set_both_wheels_to: '햄스터 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n    roboid_hamster_set_buzzer_to: '햄스터 %1: 버저 음을 %2 (으)로 정하기 %3',\n    roboid_hamster_set_following_speed_to: '햄스터 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n    roboid_hamster_set_led_to: '햄스터 %1: %2 LED를 %3 으로 정하기 %4',\n    roboid_hamster_set_output_to: '햄스터 %1: 출력 %2 를 %3 (으)로 정하기 %4',\n    roboid_hamster_set_port_to: '햄스터 %1: 포트 %2 를 %3 으로 정하기 %4',\n    roboid_hamster_set_tempo_to: '햄스터 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n    roboid_hamster_set_wheel_to: '햄스터 %1: %2 바퀴 %3 (으)로 정하기 %4',\n    roboid_hamster_stop: '햄스터 %1: 정지하기 %2',\n    roboid_hamster_turn_for_secs: '햄스터 %1: %2 으로 %3 초 돌기 %4',\n    roboid_hamster_turn_once: '햄스터 %1: 말판 %2 으로 한 번 돌기 %3',\n    roboid_hamster_value: '햄스터 %1: %2',\n    roboid_turtle_button_state: '거북이 %1: 버튼을 %2 ?',\n    roboid_turtle_change_buzzer_by: '거북이 %1: 버저 음을 %2 만큼 바꾸기 %3',\n    roboid_turtle_change_head_led_by_rgb: '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n    roboid_turtle_change_tempo_by: '거북이 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n    roboid_turtle_change_wheel_by: '거북이 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n    roboid_turtle_change_wheels_by_left_right:\n        '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n    roboid_turtle_clear_head_led: '거북이 %1: 머리 LED 끄기 %2',\n    roboid_turtle_clear_sound: '거북이 %1: 소리 끄기 %2',\n    roboid_turtle_cross_intersection: '거북이 %1: 검은색 교차로 건너가기 %2',\n    roboid_turtle_follow_line: '거북이 %1: %2 선을 따라가기 %3',\n    roboid_turtle_follow_line_until: '거북이 %1: 검은색 선을 따라 %2 까지 이동하기 %3',\n    roboid_turtle_follow_line_until_black: '거북이 %1: %2 선을 따라 검은색까지 이동하기 %3',\n    roboid_turtle_is_color_pattern: '거북이 %1: 색깔 패턴이 %2 %3 인가?',\n    roboid_turtle_move_backward_unit: '거북이 %1: 뒤로 %2 %3 이동하기 %4',\n    roboid_turtle_move_forward_unit: '거북이 %1: 앞으로 %2 %3 이동하기 %4',\n    roboid_turtle_pivot_around_wheel_unit_in_direction:\n        '거북이 %1: %2 바퀴 중심으로 %3 %4 %5 방향으로 돌기 %6',\n    roboid_turtle_play_note: '거북이 %1: %2 %3 음을 연주하기 %4',\n    roboid_turtle_play_note_for_beats: '거북이 %1: %2 %3 음을 %4 박자 연주하기 %5',\n    roboid_turtle_play_sound_times: '거북이 %1: %2 소리 %3 번 재생하기 %4',\n    roboid_turtle_play_sound_times_until_done: '거북이 %1: %2 소리 %3 번 재생하고 기다리기 %4',\n    roboid_turtle_rest_for_beats: '거북이 %1: %2 박자 쉬기 %3',\n    roboid_turtle_set_buzzer_to: '거북이 %1: 버저 음을 %2 (으)로 정하기 %3',\n    roboid_turtle_set_following_speed_to: '거북이 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n    roboid_turtle_set_head_led_to: '거북이 %1: 머리 LED를 %2 으로 정하기 %3',\n    roboid_turtle_set_head_led_to_rgb: '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n    roboid_turtle_set_tempo_to: '거북이 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n    roboid_turtle_set_wheel_to: '거북이 %1: %2 바퀴 %3 (으)로 정하기 %4',\n    roboid_turtle_set_wheels_to_left_right:\n        '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n    roboid_turtle_stop: '거북이 %1: 정지하기 %2',\n    roboid_turtle_touching_color: '거북이 %1: %2 에 닿았는가?',\n    roboid_turtle_turn_at_intersection: '거북이 %1: 검은색 교차로에서 %2 으로 돌기 %3',\n    roboid_turtle_turn_unit_in_place: '거북이 %1: %2 으로 %3 %4 제자리 돌기 %5',\n    roboid_turtle_turn_unit_with_radius_in_direction:\n        '거북이 %1: %2 으로 %3 %4 반지름 %5 cm를 %6 방향으로 돌기 %7',\n    roboid_turtle_value: '거북이 %1: %2',\n    turtle_button_state: '버튼을 %1 ?',\n    turtle_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n    turtle_change_head_led_by_rgb: '머리 LED를 R: %1 G: %2 B: %3 만큼 바꾸기 %4',\n    turtle_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n    turtle_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n    turtle_change_wheels_by_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n    turtle_clear_head_led: '머리 LED 끄기 %1',\n    turtle_clear_sound: '소리 끄기 %1',\n    turtle_cross_intersection: '검은색 교차로 건너가기 %1',\n    turtle_follow_line: '%1 선을 따라가기 %2',\n    turtle_follow_line_until: '검은색 선을 따라 %1 까지 이동하기 %2',\n    turtle_follow_line_until_black: '%1 선을 따라 검은색까지 이동하기 %2',\n    turtle_is_color_pattern: '색깔 패턴이 %1 %2 인가?',\n    turtle_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n    turtle_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n    turtle_pivot_around_wheel_unit_in_direction: '%1 바퀴 중심으로 %2 %3 %4 방향으로 돌기 %5',\n    turtle_play_note: '%1 %2 음을 연주하기 %3',\n    turtle_play_note_for_beats: '%1 %2 음을 %3 박자 연주하기 %4',\n    turtle_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n    turtle_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n    turtle_rest_for_beats: '%1 박자 쉬기 %2',\n    turtle_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n    turtle_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n    turtle_set_head_led_to: '머리 LED를 %1 으로 정하기 %2',\n    turtle_set_head_led_to_rgb: '머리 LED를 R: %1 G: %2 B: %3 (으)로 정하기 %4',\n    turtle_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n    turtle_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n    turtle_set_wheels_to_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n    turtle_stop: '정지하기 %1',\n    turtle_touching_color: '%1 에 닿았는가?',\n    turtle_turn_at_intersection: '검은색 교차로에서 %1 으로 돌기 %2',\n    turtle_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n    turtle_turn_unit_with_radius_in_direction: '%1 으로 %2 %3 반지름 %4 cm를 %5 방향으로 돌기 %6',\n    turtle_value: '%1',\n    is_clicked: '%1',\n    is_press_some_key: '%1 %2',\n    reach_something: '%1 %2 %3',\n    boolean_comparison: '%1 %2 %3',\n    boolean_equal: '%1 %2 %3',\n    boolean_bigger: '%1 %2 %3',\n    boolean_smaller: '%1 %2 %3',\n    boolean_and_or: '%1 %2 %3',\n    boolean_and: '%1 %2 %3',\n    boolean_or: '%1 %2 %3',\n    boolean_not: '%1 %2 %3',\n    true_or_false: '%1',\n    True: '%1  ',\n    False: '%1  ',\n    boolean_basic_operator: '%1 %2 %3',\n    show: 'this.show() %1',\n    hide: 'this.hide() %1',\n    dialog_time: 'this.setDialogByTime( %1 , %2 , %3 ) %4',\n    dialog: 'this.setDialog( %1 , %2 ) %3',\n    remove_dialog: 'this.removeDialog() %1',\n    change_to_nth_shape: 'this.setShape( %1 ) %2',\n    change_to_next_shape: 'this.setTo %1 Shape() %2',\n    set_effect_volume: 'this.addEffect( %1 , %2 ) %3',\n    set_effect: 'this.setEffect( %1 , %2 ) %3',\n    erase_all_effects: 'this.removeAllEffects() %1',\n    change_scale_percent: 'this.scale += %1 %2',\n    set_scale_percent: 'this.scale = %1 %2',\n    change_scale_size: 'this.scale += %1 %2',\n    set_scale_size: 'this.scale = %1 %2',\n    flip_y: \"this.flip('horizontal') %1\",\n    flip_x: \"this.flip('vertical') %1\",\n    set_object_order: 'Entry.setLayerOrder(this, %1 ) %2',\n    get_pictures: '%1  ',\n    change_to_some_shape: 'this.setShape( %1 ) %2',\n    add_effect_amount: 'this.addEffect( %1 , %2 ) %3',\n    change_effect_amount: 'this.setEffect( %1 , %2 ) %3',\n    set_effect_amount: 'this.addEffect( %1 , %2 ) %3',\n    set_entity_effect: 'this.setEffect( %1 , %2 ) %3',\n    change_object_index: 'Entry.setLayerOrder(this, %1 ) %2',\n    move_direction: 'Entry.moveToDirection( %1 ) %2',\n    move_x: 'this.x += %1 %2',\n    move_y: 'this.y += %1 %2',\n    locate_xy_time: 'this.setXYbyTime( %1 , %2 , %3 ) %4',\n    rotate_by_angle: 'this.rotation += %1 %2',\n    rotate_by_angle_dropdown: '%1 만큼 회전하기 %2',\n    see_angle: 'this.direction = %1 %2',\n    see_direction: '%1 쪽 보기 %2',\n    locate_xy: 'this.setXY( %1 , %2 ) %3',\n    locate_x: 'this.x = %1 %2',\n    locate_y: 'this.y = %1 %2',\n    locate: 'this.locateAt( %1 ) %2',\n    move_xy_time: 'this.moveXYbyTime( %1 , %2 , %3 ) %4',\n    rotate_by_angle_time: 'this.rotateByTime( %1 , %2 ) %3',\n    bounce_wall: 'Entry.bounceWall(this) %1',\n    flip_arrow_horizontal: '화살표 방향 좌우 뒤집기 %1',\n    flip_arrow_vertical: '화살표 방향 상하 뒤집기 %1',\n    see_angle_object: 'this.setDirectionTo( %1 ) %2',\n    see_angle_direction: 'this.rotation = %1 %2',\n    rotate_direction: 'this.direction += %1 %2',\n    locate_object_time: '%1 초 동안 %2 위치로 이동하기 %3',\n    rotate_absolute: 'this.rotation = %1 %2',\n    rotate_relative: 'this.rotation = %1 %2',\n    direction_absolute: 'this.direction = %1 %2',\n    direction_relative: 'this.direction += %1 %2',\n    move_to_angle: 'Entry.moveToDirection( %1 , %2 ) %3',\n    rotate_by_time: '%1 , this.rotate( %2 ) %3',\n    direction_relative_duration: '%1 %2 %3',\n    neobot_sensor_value: '%1  값',\n    neobot_turn_left: '왼쪽모터를 %1 %2 회전 %3',\n    neobot_stop_left: '왼쪽모터 정지 %1',\n    neobot_turn_right: '오른쪽모터를 %1 %2 회전 %3',\n    neobot_stop_right: '오른쪽모터 정지 %1',\n    neobot_run_motor: '%1 모터를  %2 초간 %3 %4 %5',\n    neobot_servo_1: 'SERVO1에 연결된 서보모터를 %1 속도로 %2 로 이동 %3',\n    neobot_servo_2: 'SERVO2에 연결된 서보모터를 %1 속도로 %2 로 이동 %3',\n    neobot_play_note_for: '멜로디 %1 을(를) %2 옥타브로 %3 길이만큼 소리내기 %4',\n    neobot_set_sensor_value: '%1 번 포트의 값을 %2 %3',\n    robotis_openCM70_cm_custom_value: '직접입력 주소 ( %1 ) %2 값',\n    robotis_openCM70_sensor_value: '제어기 %1 값',\n    robotis_openCM70_aux_sensor_value: '%1   %2 값',\n    robotis_openCM70_cm_buzzer_index: '제어기 음계값 %1 , %2 , 연주 %3',\n    robotis_openCM70_cm_buzzer_melody: '제어기 멜로디 %1 번 연주 %2',\n    robotis_openCM70_cm_sound_detected_clear: '최종소리감지횟수 초기화 %1',\n    robotis_openCM70_cm_led: '제어기 %1 LED %2 %3',\n    robotis_openCM70_cm_motion: '모션 %1 번 실행 %2',\n    robotis_openCM70_cm_autodrive_motor: '자율주행 자동차 %1모터를 %2 에 연결 %3',\n    robotis_openCM70_cm_autodrive_ir: '자율주행 자동차 %1적외선센서를 %2 에 연결 %3',\n    robotis_openCM70_cm_autodrive_speed: '차로를 따라 %1의 속도로 자율주행 %2',\n    robotis_openCM70_aux_motor_speed: '%1 감속모터 속도를 %2, 출력값을 %3%로 정하기 %4',\n    robotis_openCM70_aux_servo_mode: '%1 서보모터 모드를 %2 (으)로 정하기 %3',\n    robotis_openCM70_aux_servo_speed: '%1 서보모터 속도를 %2, 출력값을 %3%로 정하기 %4',\n    robotis_openCM70_aux_servo_position: '%1 서보모터 위치를 %2도로 정하기 %3',\n    robotis_openCM70_aux_led_module: '%1 LED 모듈을 %2 (으)로 정하기 %3',\n    robotis_openCM70_aux_custom: '%1 사용자 장치를 %2 (으)로 정하기 %3',\n    robotis_openCM70_cm_poweroff_timer: '제어기 자동꺼짐 타이머 %1 %2',\n    robotis_openCM70_cm_custom: '직접입력 주소 ( %1 ) (을)를 %2 (으)로 정하기 %3',\n    robotis_carCont_sensor_value: '%1   값',\n    robotis_carCont_cm_led: '4번 LED %1 ,  1번 LED %2 %3',\n    robotis_carCont_cm_sound_detected_clear: '최종소리감지횟수 초기화 %1',\n    robotis_carCont_aux_motor_speed: '%1 감속모터 속도를 %2 , 출력값을 %3 (으)로 정하기 %4',\n    robotis_carCont_cm_calibration: '%1 적외선 센서 캘리브레이션 값을 %2 (으)로 정하기 %3',\n    roduino_get_analog_number: '%1  ',\n    roduino_get_port_number: '%1  ',\n    roduino_get_analog_value: '아날로그 %1 번 센서값  ',\n    roduino_get_digital_value: '디지털 %1 번 센서값  ',\n    roduino_set_digital: '디지털 %1 번 핀 %2 %3',\n    roduino_motor: '%1 %2 %3',\n    roduino_set_color_pin: '컬러센서 R : %1, G : %2, B : %3 %4',\n    roduino_get_color: '컬러센서 %1 감지',\n    roduino_on_block: ' On ',\n    roduino_off_block: ' Off ',\n    schoolkit_get_in_port_number: '%1  ',\n    schoolkit_get_out_port_number: '%1  ',\n    schoolkit_get_servo_port_number: '%1  ',\n    schoolkit_get_input_value: '디지털 %1 번 센서값  ',\n    schoolkit_set_output: '디지털 %1 번 핀 %2 %3',\n    schoolkit_motor: '%1 속도 %2(으)로 %3 %4',\n    schoolkit_set_servo_value: '서보모터 %1 번 핀 %2˚ %3',\n    schoolkit_on_block: ' On ',\n    schoolkit_off_block: ' Off ',\n    when_scene_start: \"%1 this.addEventListener('sceneStart')\",\n    start_scene: 'Scene.changeScene( %1 ) %2',\n    start_neighbor_scene: 'Scene.changeScene( %1 ) %2',\n    sound_something: 'Entry.playSound( %1 ) %2',\n    sound_something_second: 'Entry.playSoundByTime( %1 , %2 ) %3',\n    sound_something_wait: 'Entry.playSoundAndWait( %1 ) %2',\n    sound_something_second_wait: 'Entry.playSoundAndWaitByTime( %1 , %2 ) %3',\n    sound_volume_change: 'Entry.volume += %1 %2',\n    sound_volume_set: 'Entry.volume = %1 %2',\n    sound_silent_all: 'Entry.silentAll() %1',\n    get_sounds: '%1  ',\n    sound_something_with_block: 'Entry.playSound( %1 ) %2',\n    sound_something_second_with_block: 'Entry.playSoundByTime( %1   , %2 ) %3',\n    sound_something_wait_with_block: 'Entry.playSoundAndWait( %1 ) %2',\n    sound_something_second_wait_with_block: 'Entry.playSoundAndWaitByTime( %1 ,   %2 ) %3',\n    sound_from_to: '%1 %2 %3 %4',\n    sound_from_to_and_wait: '%1 %2 %3 %4',\n    when_run_button_click: \"%1 Entry.addEventListener('run')\",\n    press_some_key: \"%1 Entry.addEventListener('keydown', key== %2 ) %3\",\n    when_some_key_pressed: \"%1 Entry.addEventListener('keydown', key== %2 )\",\n    mouse_clicked: \"%1 Entry.addEventListener('mousedown')\",\n    mouse_click_cancled: \"%1 Entry.addEventListener('mouseup')\",\n    when_object_click: \"%1 this.addEventListener('mousedown')\",\n    when_object_click_canceled: \"%1 this.addEventListener('mouseup')\",\n    when_some_key_click: '%1 키를 눌렀을 때',\n    when_message_cast: '%1 Entry.addEventListener( %2 )',\n    message_cast: 'Entry.dispatchEvent( %1 ) %2',\n    message_cast_wait: 'Entry.dispatchEventAndWait( %1 ) %2',\n    text: '%1',\n    text_read: 'Entry.contents_of_textbox( %1 )',\n    text_write: 'Entry.writeText( %1 ) %2',\n    text_append: 'Entry.appendText( %1 ) %2',\n    text_prepend: 'Entry.insertText( %1 ) %2',\n    text_flush: 'Entry.clearText() %1',\n    analizyDataAddButton: '%1',\n    append_row_to_table: '테이블 %1에 %2 추가하기 %3',\n    insert_row_to_table: '테이블 %1 %2번째에 %3 추가하기 %4',\n    delete_row_from_table: '테이블 %1 %2번째 %3 삭제하기 %4',\n    set_value_from_table: '테이블 %1 %2번째 행의 %3을(를) %4(으)로 바꾸기 %5',\n    get_table_count: '테이블 %1의 %2개수',\n    get_value_from_table: '테이블 %1 %2번째 행의 %3 값',\n    calc_values_from_table: '테이블 %1 %2의 %3',\n    open_table_chart: '테이블 %1의 차트 창 열기 %2',\n    close_table_chart: '테이블 차트 창 닫기 %1',\n    get_coefficient: '테이블 %1 %2과(와) %3의 상관계수',\n    variableAddButton: '%1',\n    listAddButton: '%1',\n    change_variable: 'Entry.addValueToVariable( %1 , %2 ) %3',\n    set_variable: 'Entry.setValueVariable( %1 , %2 ) %3',\n    show_variable: 'Entry.showVariable( %1 ) %2',\n    hide_variable: 'Entry.hideVariable( %1 ) %2',\n    get_variable: 'Entry.getVariableValue( %1 )',\n    ask_and_wait: 'Entry.askAndWait( %1 ) %2',\n    get_canvas_input_value: '%1  ',\n    add_value_to_list: 'Entry.pushValueToList( %1 , %2 ) %3',\n    remove_value_from_list: 'Entry.removeValueListAt( %1 , %2 ) %3',\n    insert_value_to_list: 'Entry.pushValueToListAt( %1 , %2 , %3 ) %4',\n    change_value_list_index: 'Entry.changeValueListAt( %1 , %2 , %3 ) %4',\n    value_of_index_from_list: '%1 %2 %3 %4 %5',\n    length_of_list: '%1 %2 %3',\n    show_list: 'Entry.showList( %1 ) %2',\n    hide_list: 'Entry.hideList( %1 ) %2',\n    options_for_list: '%1  ',\n    set_visible_answer: 'Entry.getAnswer() %1 %2',\n    is_included_in_list: '%1 %2 %3 %4 %5',\n    xbot_digitalInput: '%1',\n    xbot_analogValue: '%1',\n    xbot_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n    xbot_analogOutput: '아날로그 %1 %2 %3',\n    xbot_servo: '서보 모터 %1 , 각도 %2 %3',\n    xbot_oneWheel: '바퀴(DC) 모터 %1 , 속도 %2 %3',\n    xbot_twoWheel: '바퀴(DC) 모터 오른쪽(2) 속도: %1 왼쪽(1) 속도: %2 %3',\n    xbot_rgb: 'RGB LED 켜기 R 값 %1 G 값 %2 B 값 %3 %4',\n    xbot_rgb_picker: 'RGB LED 색 %1 로 정하기 %2',\n    xbot_buzzer: \"Entry.Hamster.playNoteForBeats(' %1   %2 , %3 초 연주하기 %4\",\n    xbot_lcd: 'LCD %1 번째 줄 ,  출력 값 %2 %3',\n    run: '',\n    mutant: 'test mutant block',\n    jr_start: '%1',\n    jr_repeat: '%1 %2 반복',\n    jr_item: '꽃 모으기 %1',\n    cparty_jr_item: '연필 줍기 %1',\n    jr_north: '  위쪽 %1',\n    jr_east: '오른쪽 %1',\n    jr_south: '  아래쪽 %1',\n    jr_west: '  왼쪽 %1',\n    jr_start_basic: '%1 %2',\n    jr_go_straight: '앞으로 가기%1',\n    jr_turn_left: '왼쪽으로 돌기%1',\n    jr_turn_right: '오른쪽으로 돌기%1',\n    jr_go_slow: '천천히 가기 %1',\n    jr_repeat_until_dest: '%1 만날 때까지 반복하기 %2',\n    jr_if_construction: '만약 %1 앞에 있다면 %2',\n    jr_if_speed: '만약 %1 앞에 있다면 %2',\n    maze_step_start: '%1 시작하기를 클릭했을 때',\n    maze_step_jump: '뛰어넘기%1',\n    maze_step_jump2: '뛰어넘기%1',\n    maze_step_jump_pinkbean: '뛰어넘기%1',\n    maze_step_for: '%1 번 반복하기%2',\n    test: '%1 this is test block %2',\n    maze_repeat_until_1: '%1 만날 때 까지 반복%2',\n    maze_repeat_until_2: '모든 %1 만날 때 까지 반복%2',\n    maze_step_if_1: '만약 앞에 %1 있다면%2',\n    maze_step_if_2: '만약 앞에 %1 있다면%2',\n    maze_call_function: '약속 불러오기%1',\n    maze_define_function: '약속하기%1',\n    maze_step_if_3: '만약 앞에 %1 있다면%2',\n    maze_step_if_4: '만약 앞에 %1 있다면%2',\n    maze_step_move_step: '앞으로 한 칸 이동%1',\n    maze_step_rotate_left: '왼쪽으로 회전%1',\n    maze_step_rotate_right: '오른쪽으로 회전%1',\n    maze_step_forward: '앞으로 가기%1',\n    maze_turn_right: '오른쪽 바라보기%1',\n    maze_turn_left: '왼쪽 바라보기%1',\n    maze_ladder_climb: '사다리 타기%1',\n    maze_attack_lupin: '%1공격하기%2',\n    maze_attack_both_side: '양옆 공격하기%1',\n    maze_attack_pepe: '%1 공격하기%2',\n    maze_attack_yeti: '%1 공격하기%2',\n    maze_attack_mushroom: '%1 공격하기%2',\n    maze_attack_peti: '%1 공격하기%2',\n    maze_eat_item: '음식 먹기%1',\n    maze_step_if_mushroom: '만약 한 칸 앞에 %1가 있다면 %2',\n    maze_step_if_yeti: '만약 앞에 %1가 있다면 %2 %3 아니면',\n    maze_step_if_left_monster: '만약 왼쪽 공격범위에 몬스터가 있다면 %1 %2 아니면',\n    maze_step_if_right_monster: '만약 오른쪽 공격범위에 몬스터가 있다면 %1 %2 아니면',\n    maze_step_if_lupin: '만약 두 칸 앞에 %1가 있다면 %2',\n    maze_step_if_else_road: '만약 한 칸 앞에 길이 있다면 %1 %2아니면',\n    maze_step_if_else_mushroom: '만약 한 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_step_if_else_lupin: '만약 두 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_step_if_else_ladder: '만약 한 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_rotate_left: '왼쪽으로 돌기%1',\n    maze_rotate_right: '오른쪽으로 돌기%1',\n    maze_moon_kick: '발차기하기%1',\n    maze_repeat_until_3: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_4: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_5: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_6: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_7: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_goal: '목적지에 도착할 때까지 반복하기%1',\n    maze_repeat_until_beat_monster: '모든 몬스터를 혼내줄 때까지 반복하기%1',\n    maze_radar_check: '%1에 %2이 있다',\n    maze_cony_flower_throw: '꽃 던지기%1',\n    maze_brown_punch: '주먹 날리기%1',\n    maze_iron_switch: '장애물 조종하기%1',\n    maze_james_heart: '하트 날리기%1',\n    maze_step_if_5: '만약 앞에 길이 없다면%2',\n    maze_step_if_6: '만약 앞에 %1이 없다면%2',\n    maze_step_if_7: '만약 앞에 %1이 있다면%2',\n    maze_step_if_8: '만약 %1이라면%2',\n    maze_step_if_else: '만약 %1이라면%2 %3 아니면',\n    test_wrapper: '%1 this is test block %2',\n    basic_button: '%1',\n    ai_move_right: '앞으로 가기 %1',\n    ai_move_up: '위쪽으로 가기 %1',\n    ai_move_down: '아래쪽으로 가기 %1',\n    ai_repeat_until_reach: '목적지에 도달 할 때까지 반복하기 %1',\n    ai_if_else_1: '만약 앞에 %1가 있다면 %2 %3 아니면',\n    ai_boolean_distance: '%1 레이더 %2 %3',\n    ai_distance_value: '%1 레이더',\n    ai_boolean_object: '%1 물체는 %2 인가?',\n    ai_use_item: '아이템 사용 %1',\n    ai_boolean_and: '%1 %2 %3',\n    ai_True: '%1',\n    ai_if_else: 'if ( %1 ) %2 %3 else',\n    smartBoard_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값',\n    smartBoard_get_named_sensor_value: '%1 센서값',\n    smartBoard_is_button_pressed: '%1 버튼을 눌렀는가?',\n    smartBoard_set_dc_motor_direction: '%1 DC 모터를 %2 방향으로 정하기 %3',\n    smartBoard_set_dc_motor_speed: '%1 DC모터를 %2 %3',\n    smartBoard_set_dc_motor_pwm: '%1 DC모터를 %2 속도로 돌리기 %3',\n    smartBoard_set_servo_speed: '%1 번 서보모터의 속도를 %2 %3',\n    smartBoard_set_servo_angle: '%1 번 서보모터를 %2 도 로 움직이기 %3',\n    smartBoard_set_number_eight_pin: '%1 포트를 %2 %3',\n    smartBoard_set_gs1_pwm: 'GS1 포트의 PWM을 %1 로 정하기 %2',\n    robotori_digitalInput: '%1',\n    robotori_analogInput: '%1',\n    robotori_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n    robotori_analogOutput: '아날로그 %1 %2 %3',\n    robotori_servo: '서보모터 각도 %1 %2',\n    robotori_dc_direction: 'DC모터 %1 회전 %2 %3',\n    dadublock_get_analog_value: '아날로그 %1 번 센서값',\n    dadublock_get_analog_value_map:\n        '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값',\n    dadublock_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n    dadublock_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dadublock_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dadublock_set_tone: '디지털 %1 번 핀을 %2 음으로 %3 옥타브로 %4 만큼 연주하기 %5',\n    dadublock_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n    coconut_stop_motor: '모터 정지 %1',\n    coconut_move_motor: '%1 움직이기 %2',\n    coconut_turn_motor: '%1 으로 돌기 %2',\n    coconut_move_for_secs: '%1 %2 초동안 움직이기 %3',\n    coconut_turn_for_secs: '%1 으로 %2 초동안 돌기 %3',\n    coconut_turn_to_led: '%1 으로 회전하는 동안 %2LED 켜기 %3',\n    coconut_move_outmotor: '외부모터 %1(으로) 움직이기 속도 %2 %3',\n    coconut_set_led_to: '%1 LED를 %2 으로 켜기 %3',\n    coconut_clear_led: '%1 LED 끄기 %2',\n    coconut_set_led_clear: '%1 LED %2 끄기 %3',\n    coconut_set_led_time: '%1 LED %2 으로 %3 초동안 켜기 %4',\n    coconut_beep: '버저 켜기 %1',\n    coconut_buzzer_time: '버저음을 %1 초 동안 소리내기 %2',\n    coconut_buzzer_set_hz: '버즈음 %1 Hz를 %2초 동안 소리내기 %3',\n    coconut_clear_buzzer: '버저 끄기 %1',\n    coconut_play_buzzer: '%1 %2 %3 음을 %4 박자로 연주하기 %5',\n    coconut_rest_buzzer: '%1 동안 쉬기 %2',\n    coconut_play_buzzer_led: '%1 %2 %3 음을 %4 박자로 연주하는 동안 %5 LED %6 켜기 %7',\n    coconut_play_midi: '%1 연주하기 %2',\n    coconut_floor_sensor: '%1 바닥센서',\n    coconut_floor_sensing: '%1 바닥센서 %2',\n    coconut_following_line: '선 따라가기 %1',\n    coconut_front_sensor: '%1 전방센서',\n    coconut_front_sensing: '%1 전방센서 %2',\n    coconut_obstruct_sensing: '장애물 감지',\n    coconut_avoid_mode: '어보이드 모드 %1',\n    coconut_dotmatrix_set: '도트매트릭스 %1 ( %2줄, %3칸 ) %4',\n    coconut_dotmatrix_on: '도트매트릭스 모두 켜기 %1',\n    coconut_dotmatrix_off: '도트매트릭스 모두 끄기 %1',\n    coconut_dotmatrix_num: '도트매트릭스 숫자 %1표시 %2',\n    coconut_dotmatrix_small_eng: '도트매트릭스 소문자 %1표시 %2',\n    coconut_dotmatrix_big_eng: '도트매트릭스 대문자 %1표시 %2',\n    coconut_dotmatrix_kor: '도트매트릭스 한글 %1표시 %2',\n    coconut_light_sensor: '밝기',\n    coconut_tem_sensor: '온도',\n    coconut_ac_sensor: '%1 가속도',\n    coconut_outled_sensor: '외부 LED 설정 %1 %2 초동안 켜기 %3',\n    coconut_outspk_sensor: '외부 스피커 설정 %1 %2Hz로 %3초 동안 소리내기 %4',\n    coconut_outspk_sensor_off: '외부 스피커 %1 끄기 %2',\n    coconut_outinfrared_sensor: '외부 적외선센서 %1',\n    coconut_outcds_sensor: '외부 빛센서(Cds) %1',\n    coconut_servomotor_angle: '서보모터 연결 %1 각도 %2 %3',\n    chocopi_control_button: '%1 컨트롤 %2번을 누름',\n    chocopi_control_event: '%1 %2 컨트롤 %3을 %4',\n    chocopi_control_joystick: '%1 컨트롤 %2의 값',\n    chocopi_dc_motor: '%1 DC모터 %2 %3% 세기 %4 방향 %5',\n    chocopi_led: '%1 LED %2 RGB(%3 %4 %5) %6',\n    chocopi_motion_photogate_event: '%1 %2 포토게이트 %3번을 %4',\n    chocopi_motion_photogate_status: '%1 포토게이트 %2번이 막힘',\n    chocopi_motion_photogate_time: '%1 포토게이트%2번을 %3',\n    chocopi_motion_value: '%1 모션 %2의 값',\n    chocopi_sensor: '%1 센서 %2',\n    chocopi_servo_motor: '%1 서보모터 %2번 %3도 %4',\n    chocopi_touch_event: '%1 %2 터치 %3번을 %4',\n    chocopi_touch_status: '%1 터치 %2번을 만짐',\n    chocopi_touch_value: '%1 터치 %2번의 값',\n    dadublock_car_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dadublock_car_get_analog_value: '아날로그 %1 번 센서값',\n    dadublock_car_get_analog_value_map:\n        '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    dadublock_car_get_digital: '디지털 %1 번 센서값',\n    dadublock_car_get_irsensor: '적외선 %1 번 센서값',\n    dadublock_car_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n    dadublock_car_motor: '모터 %1 번을 %2 (으)로 %3 %의 속도로 움직이기 %4',\n    dadublock_car_motor_stop: '모터 %1 번 멈추기 %2',\n    dadublock_car_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n    dadublock_car_set_tone: '디지털 %1 번 핀 을 %2 음으로 %3의 옥타브로 %4 만큼 연주하기 %5',\n    dadublock_car_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dadublock_get_digital: '디지털 %1 번 센서값',\n    ev3_get_sensor_value: '%1 의 값',\n    ev3_touch_sensor: '%1 의 터치센서가 작동되었는가?',\n    ev3_color_sensor: '%1 의  %2 값',\n    ev3_motor_power: '%1 의 값을 %2 으로 출력 %3',\n    ev3_motor_power_on_time: '%1 의 값을 %2 초 동안 %3 으로 출력 %4',\n    ev3_motor_degrees: '%1 의 값을 %2 으로  %3 도 만큼 회전 %4',\n    rokoboard_get_sensor_value_by_name: '%1 의 센서값',\n    ardublock_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    ardublock_get_analog_value: '아날로그 %1 번 센서값',\n    ardublock_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    ardublock_get_digital: '디지털 %1 번 센서값',\n    ardublock_get_left_cds_analog_value: '왼쪽 조도센서 %1 센서값',\n    ardublock_get_right_cds_analog_value: '오른쪽 조도센서 %1 센서값',\n    ardublock_get_sound_analog_value: '사운드(소리) 센서 %1 센서값',\n    ardublock_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    ardublock_set_left_motor: '왼쪽모터를 %1 으로 %2 회전 속도로 정하기 %3',\n    ardublock_set_right_motor: '오른쪽모터를 %1 으로 %2 회전 속도로 정하기 %3',\n    ardublock_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    ardublock_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    ardublock_toggle_led: '디지털 %1 번 핀 %2 %3',\n    ardublock_toggle_left_led: '왼쪽 라이트 %1 번 핀 %2 %3',\n    ardublock_toggle_right_led: '오른쪽 라이트 %1 번 핀 %2 %3',\n    mkboard_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    mkboard_get_analog_value: '아날로그 %1 번 센서값',\n    mkboard_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    mkboard_get_digital: '디지털 %1 번 센서값',\n    mkboard_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    mkboard_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    mkboard_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    mkboard_toggle_led: '디지털 %1 번 핀 %2 %3',\n    mkboard_set_lcd: '1602 문자 LCD %1 행 , %2열에 %3 출력하기 %4',\n    mkboard_lcd_command: '1602 문자 LCD %1 명령실행하기 %2',\n    altino_analogValue: '알티노 %1 센서값',\n    altino_dot_display: '전광판에 %1 글자 표시하기 %2',\n    altino_dot_display_line: '1열 %1 2열 %2 3열 %3 4열 %4 5열 %5 6열 %6 7열 %7 8열 %8 출력하기 %9',\n    altino_light: '%1 등을 %2  %3',\n    altino_rear_wheel: '뒷바퀴 오른쪽 %1 왼쪽 %2 로 정하기 %3',\n    altino_sound: '%1 옥타브 %2 음을 연주하기  %3',\n    altino_steering: '방향을 %1 로 정하기 %2',\n    jdkit_altitude: '드론을 %1 높이만큼 날리기 %2',\n    jdkit_button: '%1번 버튼 값 읽어오기',\n    jdkit_connect: '드론 연결 상태 읽어오기',\n    jdkit_emergency: '드론을 즉시 멈추기 %1',\n    jdkit_gyro: '보드 %1 기울기 값 읽어오기',\n    jdkit_joystick: '조이스틱 %1 읽기',\n    jdkit_led: '%1 LED %2  %3',\n    jdkit_motor: '%1 모터를 %2 세기로 돌리기 %3',\n    jdkit_ready: '드론 비행 준비 상태 읽어오기',\n    jdkit_rollpitch: '드론을 %1 방향 %2 세기로 움직이기 %3',\n    jdkit_throttle: '드론 프로펠러를 %1 만큼 세기로 돌리기 %2',\n    jdkit_tune: '%1 음을  %2 초동안 소리내기 %3',\n    jdkit_ultrasonic: '거리(초음파)값 읽어오기',\n    jdkit_yaw: '드론을 %1 만큼 회전하기 %2',\n    memaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    memaker_get_analog_value: '아날로그 %1 번 센서값',\n    memaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    memaker_get_digital: '디지털 %1 번 센서값',\n    memaker_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    memaker_set_lcd: '1602 문자 LCD %1 행 , %2열에 %3 출력하기 %4',\n    memaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    memaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n    memaker_lcd_command: '1602 문자 LCD %1 명령실행하기 %2',\n    edumaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    edumaker_get_analog_value: '아날로그 %1 번 센서값',\n    edumaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    edumaker_get_digital: '디지털 %1 번 센서값',\n    edumaker_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n    edumaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    edumaker_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    edumaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n    creamo_get_number_sensor_value: '가변저항_블록 %1 번 센서값  ',\n    creamo_get_port_number: '%1',\n    creamo_get_pwm_port_number: '%1  ',\n    creamo_motor_port_number: '%1',\n    creamo_toggle_led: 'LED_블록 %1 번 핀 %2 %3',\n    creamo_toggle_motor: 'Motor_블록 %1 번 핀 %2 %3',\n    creamo_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    mechatro_get_dc_motor_current: '%1모터 사용전류값',\n    mechatro_get_digital: '%1 디지털 값',\n    mechatro_get_sensor_value: '%1 센서값',\n    mechatro_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 의 거리값 [cm]',\n    mechatro_set_blue_pw: '블루투스 비밀번호 : %1%2%3%4로 정하기%5',\n    mechatro_set_dc_motor: '%1모터 속도 %2로 정하기%3',\n    mechatro_set_digital: '%1번 %2 %3',\n    mechatro_set_pwm: '%1PWM을 %2%로 정하기 %3',\n    mechatro_set_servo_position: '%1서보모터 위치 :%2도로 옮기기 %3',\n    mechatro_set_servo_speed: '%1서보모터 속도 : 1초당 %2도로 정하기 %3',\n    mechatro_set_threshold: '%1 센서 감도 : %2로 정하기%3',\n    mechatro_set_tone: '%1버저 %2 %3 음으로 연주 %4',\n    mechatro_set_tone_time: '%1버저 %2 %3 음으로 %4 초 연주 %5',\n    funboard_buzzer_onoff: '버저 %1 %2',\n    funboard_buzzer_second: '버저%1%2초 동안%3',\n    funboard_buzzer_tone_simple: '%1%2음을%3초 연주하기%4',\n    funboard_color_led_on_pwm: '%1색  LED %2 % %3',\n    funboard_color_led_onoff: '%1색  LED %2 %3',\n    funboard_convert_scale: '%1값 %2~%3 에서 %4~%5 으로 변환값',\n    funboard_dotmatrix_1column: '%1칸 %2표시하기 %3',\n    funboard_dotmatrix_1row: '%1줄 %2표시하기 %3',\n    funboard_dotmatrix_1row_1column: '%1%2 %3표시하기 %4',\n    funboard_dotmatrix_64_display: '%1 (8x8)표시하기%2',\n    funboard_dotmatrix_big_eng: '대문자 %1표시하기 %2',\n    funboard_dotmatrix_char_display: '문자%1표시하기%2',\n    funboard_dotmatrix_extra_char: '문자 %1표시하기 %2',\n    funboard_dotmatrix_intensity: '밝기 %1% %2',\n    funboard_dotmatrix_kor: '▦  한글 %1표시하기 %2',\n    funboard_dotmatrix_num: '숫자 %1표시하기 %2',\n    funboard_dotmatrix_onoff: '모두 %1 %2',\n    funboard_dotmatrix_scroll_option: '스크롤 방향%1%2',\n    funboard_dotmatrix_scroll_rapid: '스크롤 속도 %1% %2',\n    funboard_dotmatrix_set: '%1줄 %2칸  %3 %4',\n    funboard_dotmatrix_small_eng: '소문자 %1표시하기 %2',\n    funboard_dotmatrix_string_display: '문자열%1표시하기%2',\n    funboard_dotmatrix_string_display_scroll: '문자열%1표시하기%2스크롤%3',\n    funboard_dotmatrix_symbol: '기호 %1표시하기 %2',\n    funboard_get_analog_sensor_2state: '%1값 %2',\n    funboard_get_digital_button_value: '%1 버튼  값',\n    funboard_get_number_sensor_value: '%1 값',\n    funboard_get_touch_button_value: '%1 터치  값',\n    funboard_set_digital_buzzer: '버저를 %1옥타브 %2음 %3초  연주%4',\n    funboard_what_button_pressed: '%1 버튼  눌림',\n    funboard_what_touch_button_pressed: '%1 터치됨',\n};\nLang.TextCoding = {\n    block_name: '블록명',\n    title_syntax: '문법오류 ',\n    title_converting: '변환오류',\n    message_syntax_default: '문법에 오류가 있습니다',\n    message_syntax_unexpected_token: '문법에 맞지 않는 토큰이 포함되어 있습니다',\n    message_syntax_reserved_token: '사용할 수 없는 변수명입니다.',\n    message_syntax_reserved_token_list: '사용할 수 없는 리스트명입니다.',\n    message_syntax_unexpected_character: '문법에 맞지 않는 문자가 포함되어 있습니다',\n    message_syntax_unexpected_indent: '문법에 맞지 않는 띄어쓰기가 포함되어 있습니다',\n    message_conv_default: '지원하지 않는 코드입니다',\n    message_conv_no_support: '변환될 수 없는 코드입니다',\n    message_conv_no_variable: '변수가 선언되지 않았습니다',\n    message_conv_no_list: '리스트가 선언되지 않았습니다',\n    message_conv_no_object: '객체는 지원되지 않습니다',\n    message_conv_no_function: '함수가 변환될 수 없습니다',\n    message_conv_no_entry_event_function: '엔트리 이벤트 함수는 다른 함수 안에 존재할 수 없습니다.',\n    message_conv_undefined_function:\n        '정의되지 않은 명령어 입니다. 명령어가 올바르게 입력되었는지 확인해주세요.',\n    message_conv_is_expect1: '올바르지 않은 문법입니다. ',\n    message_conv_is_expect2: ' 가 올바르게 입력되었는지 확인해주세요.',\n    message_conv_instead: '올바르지 않은 문법입니다. %1 대신 %2 가 필요합니다.',\n    message_conv_is_wrong1: '올바르지 않은 문법입니다. ',\n    message_conv_is_wrong2: '(은/는) 올 수 없는 위치입니다.',\n    message_conv_or: ' 나 ',\n    subject_syntax_default: '기타',\n    subject_syntax_token: '토큰',\n    subject_syntax_character: '문자',\n    subject_syntax_indent: '띄워쓰기',\n    subject_conv_default: '기타',\n    subject_conv_general: '일반',\n    subject_conv_variable: '변수',\n    subject_conv_list: '리스트',\n    subject_conv_object: '객체',\n    subject_conv_function: '함수',\n    alert_variable_empty_text:\n        '등록된 변수 중에 공백(띄어쓰기)이 포함된 변수가 있으면 모드 변환을 할 수 없습니다.',\n    alert_list_empty_text:\n        '등록된 리스트 중에 공백(띄어쓰기)이 포함된 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_field_multi:\n        '등록된 함수 중에 함수 이름에 [이름] 블록이 두번이상 포함되어 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_disorder:\n        '등록된 함수 중에[이름] 블록이 [문자/숫자값] 또는 [판단값] 블록보다 뒤에 쓰이면 모드 변환을 할 수 없습니다.',\n    alert_function_has_boolean:\n        '엔트리파이선으로 변환 후 다시 블록코딩으로 모드로 변경하면 함수에 사용된 [판단값]은 모두 [문자/숫자형]으로 변환됩니다.',\n    alert_function_editor: '함수 생성 및 편집 중에는 모드 변환을 할 수 없습니다.',\n    alert_function_no_support: '텍스트모드에서는 함수 생성 및 편집을 할 수 없습니다.',\n    alert_list_no_support: '텍스트모드에서는 리스트 생성 및 편집을 할 수 없습니다.',\n    alert_variable_no_support: '텍스트모드에서는 변수 생성 및 편집을 할 수 없습니다.',\n    alert_signal_no_support: '텍스트모드에서는 신호 생성 및 편집을 할 수 없습니다.',\n    alert_legacy_no_support: '전환할 수 없는 블록이 존재하여 모드 변환을 할 수 없습니다.',\n    alert_variable_empty_text_add_change: '변수명 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_list_empty_text_add_change: '리스트명에 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_list_contains_exceed_length_value:\n        '리스트 항목에 15자리 이상의 수가 입력되어 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_empty_text_add_change: '함수명에 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_no_save_on_error: '문법 오류가 존재하여 작품을 저장할 수 없습니다.',\n    alert_api_no_support:\n        '작품에 엔트리파이썬에서 지원하지 않는 \\n블록이 조립되어 있습니다. \\n해당 블록을 삭제하고 만들기 모드를 변경할까요?',\n    warn_unnecessary_arguments:\n        '&(calleeName)(); 는 괄호 사이에 값이 입력될 필요가 없는 명령어 입니다. (line:&(lineNumber))',\n    python_code: ' 오브젝트의 파이선 코드',\n    eof: '줄바꿈',\n    newline: '줄바꿈',\n    indent: '들여쓰기',\n    num: '숫자',\n    string: '문자열',\n    name: '변수명',\n};\nLang.PythonHelper = {\n    when_run_button_click_desc:\n        '[시작하기]버튼을 클릭하면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_run_button_click_exampleCode: 'def when_start():\\n    Entry.print(\"안녕!\")',\n    when_run_button_click_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕!\"이라 말합니다.',\n    when_some_key_pressed_desc:\n        'A키를 누르면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_some_key_pressed_elements:\n        'A-- 아래 선택지 중 하나<br>① 알파벳 : \"A\", \"B\" ~ \"Z\" 등(소문자 가능)<br>② 숫자 : 1, 2, 3, 4 ~ 9, 0<br>③ 특수키 : \"space\", \"enter\"<br>④ 방향키 : \"up\", \"down\", \"right\", \"left\"',\n    when_some_key_pressed_exampleCode:\n        'def when_press_key(\"W\"):\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(1):\\n    Entry.add_size(10)',\n    when_some_key_pressed_exampleDesc:\n        'W키를 누르면 오브젝트가 이동방향으로 10만큼 이동하고, 1키를 누르면 오브젝트의 크기가 10만큼 커집니다.',\n    mouse_clicked_desc:\n        '마우스를 클릭했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    mouse_clicked_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.add_size(10)\\n    Entry.move_to_direction(10)',\n    mouse_clicked_exampleDesc:\n        '마우스를 클릭하면 오브젝트의 크기가 10만큼 커지면서 이동방향으로 10만큼 이동합니다.',\n    mouse_click_cancled_desc:\n        '마우스 클릭을 해제했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    mouse_click_cancled_exampleCode:\n        'def when_click_mouse_off():\\n    Entry.move_to_direction(-10)\\n\\ndef when_click_mouse_on():\\n    Entry.move_to_direction(10)',\n    mouse_click_cancled_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 마우스 클릭을 해제하면 오브젝트가 이동방향으로 -10만큼 이동합니다.',\n    when_object_click_desc:\n        '해당 오브젝트를 클릭했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_object_click_exampleCode:\n        'def when_click_object_on():\\n    Entry.print_for_sec(\"회전!\", 0.5)\\n    Entry.add_rotation(90)',\n    when_object_click_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 \"회전!\"이라 말하고, 90도 만큼 회전합니다.',\n    when_object_click_canceled_desc:\n        '해당 오브젝트 클릭을 해제했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_object_click_canceled_exampleCode:\n        'def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)',\n    when_object_click_canceled_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.',\n    when_message_cast_desc:\n        'A 신호를 받으면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    when_message_cast_elements: 'A-- \"신호 이름\"',\n    when_message_cast_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.send_signal(\"신호\")\\n\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"안녕! 반가워\", 0.5)',\n    when_message_cast_exampleDesc:\n        '마우스를 클릭하면 \"신호\"를 보내고, \"신호\"를 받았을때 \"안녕! 반가워\"라고 0.5초간 말합니다.',\n    message_cast_desc:\n        'A에 입력된 신호를 보냅니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    message_cast_elements: 'A-- \"신호 이름\"',\n    message_cast_exampleCode:\n        '#\"오브젝트1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"안녕! 넌 몇살이니?\", 2)\\n    Entry.send_signal(\"신호\")\\n\\n#\"오브젝트2\"의 파이선 코드\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"안녕? 난 세 살이야.\", 2)',\n    message_cast_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"오브젝트1\"이 \"안녕! 넌 몇살이니?\"라고 2초간 말하고 \"신호를 보냅니다., \"오브젝트2\"가 \"신호\"를 받았을때 \"안녕? 난 세 살이야.\"라고 2초간 말합니다.',\n    message_cast_wait_desc:\n        'A에 입력된 신호를 보내고, 해당 신호를 받는 명령어들의 실행이 끝날 때까지 기다립니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    message_cast_wait_elements: 'A-- \"신호 이름\"',\n    message_cast_wait_exampleCode:\n        '#\"오브젝트1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"숨바꼭질하자!\", 2)\\n    Entry.send_signal_wait(\"신호\")\\n    Entry.hide()\\n\\n#\"오브젝트2\"의 파이선 코드\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"그래!\", 2)',\n    message_cast_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"오브젝트1\"이 \"숨바꼭질하자!\"라고 2초 동안 말하고 \"신호\"를 보낸 후 기다립니다. \"오브젝트2\"가 \"신호\"를 받으면 \"그래!\"를 2초 동안 말합니다. \"오브젝트1\"이 그 후에 모양을 숨깁니다.',\n    when_scene_start_desc:\n        '장면이 시작되면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_scene_start_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"다른 곳으로 가볼까?\", 2)\\n    Entry.start_scene(\"장면 2\")\\n\\n#\"장면 2\"의 파이선 코드\\ndef when_start_scene():\\n    Entry.print(\"여기가 어디지?\")',\n    when_scene_start_exampleDesc:\n        '\"장면 1\"에서 [시작하기]버튼을 클릭하면 \"다른 곳으로 가볼까?\"라고 2초간 말하고, \"장면 2\"가 시작됩니다. \"장면 2\"가 시작되면 오브젝트가 \"여기가 어디지?\"라고 말합니다.',\n    start_scene_desc: 'A 장면을 시작합니다.',\n    start_scene_elements: 'A-- \"장면 이름\"',\n    start_scene_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_click_object_on():\\n    Entry.start_scene(\"장면 2\")',\n    start_scene_exampleDesc: '\"장면 1\"에서 해당 오브젝트를 클릭하면 \"장면 2\"가 시작됩니다.',\n    start_neighbor_scene_desc: 'A에 입력한 다음 또는 이전 장면을 시작합니다.',\n    start_neighbor_scene_elements:\n        'A-- 아래 선택지 중 하나<br>① 다음 장면: \"next\" 또는 \"다음\"<br>② 이전 장면: \"prev\" 또는 \"이전\"',\n    start_neighbor_scene_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_press_key(\"right\"):\\n    Entry.start_scene_of(\"next\")\\n\\n#\"장면 2\"의 파이선 코드\\ndef when_press_key(\"left\"):\\n    Entry.start_scene_of(\"prev\")',\n    start_neighbor_scene_exampleDesc:\n        '\"장면 1\"에서 오른쪽화살표키를 누르면 다음 장면이, \"장면 2\"에서 왼쪽화살표키를 누르면 이전 장면이 시작됩니다.',\n    wait_second_desc: 'A초만큼 기다린 후 다음 블록을 실행합니다.',\n    wait_second_elements: 'A-- 초에 해당하는 수 입력',\n    wait_second_exampleCode:\n        'def when_start():\\n    Entry.add_effect(\"color\", 10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_size(10)',\n    wait_second_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트에 색깔효과를 10만큼 주고, 2초동안 기다린 다음 크기를 10만큼 커지게 합니다.',\n    repeat_basic_desc:\n        '아래 명령어들을 A번 반복하여 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_basic_elements: 'A-- 반복할 횟수 입력',\n    repeat_basic_exampleCode:\n        'def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()',\n    repeat_basic_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.',\n    repeat_inf_desc:\n        'A 판단이 True인 동안 아래 명령어들을 반복 실행합니다. A에 True를 입력하면 계속 반복됩니다. <br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_inf_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    repeat_inf_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()',\n    repeat_inf_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.',\n    repeat_while_true_desc:\n        'A 판단이 True가 될 때까지 아래 명령어들을 반복 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_while_true_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    repeat_while_true_exampleCode:\n        'def when_start():\\n    while not Entry.is_key_pressed(\"space\"):\\n        Entry.add_rotation(90)',\n    repeat_while_true_exampleDesc:\n        '[시작하기]버튼을 클릭하면 스페이스키를 누를때까지 오브젝트가 90도 만큼 회전합니다.',\n    stop_repeat_desc: '이 명령어와 가장 가까운 반복 명령어의 반복을 중단합니다.',\n    stop_repeat_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_key_pressed(\"enter\"):\\n            break',\n    stop_repeat_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 계속 이동합니다. 엔터키를 누르면 반복이 중단됩니다.',\n    _if_desc:\n        'A 부분의 판단이 True이면 if A:아래 명령어들을 실행하고, False이면 실행하지 않습니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    _if_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    _if_exampleCode:\n        'def when_click_mouse_on():\\n    if (Entry.value_of_mouse_pointer(\"x\") > 0):\\n        Entry.print_for_sec(\"오른쪽!\", 0.5)',\n    _if_exampleDesc:\n        '마우스를 클릭했을 때 마우스 x좌표가 0보다 크면 오브젝트가 \"오른쪽!\"이라고 0.5초 동안 말합니다.',\n    if_else_desc:\n        'A 부분의 판단이 True이면 if A: 아래 명령어들을 실행하고, False이면 else: 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    if_else_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    if_else_exampleCode:\n        'def when_click_mouse_on():\\n    if Entry.is_touched(\"mouse_pointer\"):\\n        Entry.print(\"닿았다!\")\\n    else:\\n        Entry.print(\"안 닿았다!\")',\n    if_else_exampleDesc:\n        '마우스를 클릭했을 때 마우스포인터가 오브젝트에 닿았으면 \"닿았다!\"를 그렇지 않으면 \"안 닿았다!\"를 말합니다.',\n    wait_until_true_desc: 'A 부분의 판단이 True가 될 때까지 코드의 실행을 멈추고 기다립니다.',\n    wait_until_true_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    wait_until_true_exampleCode:\n        'def when_start():\\n    Entry.print(\"엔터를 눌러봐!\")\\n    Entry.wait_until(Entry.is_key_pressed(\"enter\"))\\n    Entry.print(\"잘했어!\")',\n    wait_until_true_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"엔터를 눌러봐!\"라 말하고, 엔터키를 누를 때까지 기다립니다. 엔터키를 누르면 \"잘했어!\"라 말합니다.',\n    stop_object_desc: 'A코드의 실행을 중지합니다.',\n    stop_object_elements:\n        'A-- 아래 선택지 중 하나<br>① \"all\":  모든 오브젝트의 모든 코드<br>② \"self\" : 해당 오브젝트의 모든 코드<br>③ \"this\": 이 명령어가 포함된 코드<br>④ \"others\" : 해당 오브젝트의 코드 중 이 명령어가 포함된 코드를 제외한 모든 코드<br/>⑤ \"ohter_objects\" : 이 오브젝트를 제외한 다른 모든 오브젝트의 코드',\n    stop_object_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.stop_code(\"all\")\\n',\n    stop_object_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 마우스포인터 위치로  이동합니다. 스페이스키를 누르면 모든 코드의 실행이 중지됩니다.',\n    restart_project_desc: '작품을 처음부터 다시 실행합니다.',\n    restart_project_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_size(10)\\n\\ndef when_press_key(\"enter\"):\\n    Entry.start_again()',\n    restart_project_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트의 크기가 커집니다. 엔터키를 누르면 작품을 처음부터 다시 실행합니다.',\n    when_clone_start_desc:\n        '해당 오브젝트의 복제본이 새로 생성되었을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_clone_start_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"self\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))',\n    when_clone_start_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.',\n    create_clone_desc: 'A 오브젝트의 복제본을 생성합니다.',\n    create_clone_elements: 'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"self\" 또는 \"자신\"',\n    create_clone_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"self\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))',\n    create_clone_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.',\n    delete_clone_desc: 'Entry.make_clone_of(A) 명령에 의해 생성된 복제본을 삭제합니다.',\n    delete_clone_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"자신\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_click_object_on():\\n    Entry.remove_this_clone()',\n    delete_clone_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 복제본을 클릭하면 클릭된 복제본을 삭제합니다.',\n    remove_all_clones_desc: '해당 오브젝트의 모든 복제본을 삭제합니다.',\n    remove_all_clones_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"자신\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_press_key(\"space\"):\\n    Entry.remove_all_clone()',\n    remove_all_clones_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 스페이스 키를 누르면 모든 복제본을 삭제합니다.',\n    move_direction_desc: 'A만큼 오브젝트의 이동방향 화살표가 가리키는 방향으로 움직입니다.',\n    move_direction_elements: 'A-- 이동할 거리에 해당하는 수',\n    move_direction_exampleCode: 'def when_start():\\n    Entry.move_to_direction(10)',\n    move_direction_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동합니다.',\n    bounce_wall_desc: '오브젝트가 화면 끝에 닿으면 튕겨져 나옵니다.',\n    bounce_wall_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()',\n    bounce_wall_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.',\n    move_x_desc: '오브젝트의 x좌표를 A만큼 바꿉니다.',\n    move_x_elements:\n        'A-- x좌표의 변화 값<br>① 양수: 오브젝트가 오른쪽으로 이동합니다.<br>② 음수: 오브젝트가 왼쪽으로 이동합니다.',\n    move_x_exampleCode:\n        'def when_start():\\n    Entry.add_x(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_x(-10)',\n    move_x_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오른쪽으로 10만큼 이동하고 2초 동안 기다린 후 왼쪽으로 10만큼 이동합니다.',\n    move_y_desc: '오브젝트의 y좌표를 A만큼 바꿉니다.',\n    move_y_elements:\n        'A-- y좌표의 변화 값<br>① 양수: 오브젝트가 위쪽으로 이동합니다.<br>② 음수: 오브젝트가 아래쪽으로 이동합니다.',\n    move_y_exampleCode:\n        'def when_start():\\n    Entry.add_y(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_y(-10)',\n    move_y_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 위쪽으로 10만큼 이동하고 2초 동안 기다린 후 아래쪽으로 10만큼 이동합니다.',\n    move_xy_time_desc: '오브젝트가 x와 y좌표를 각각 A와 B만큼 C초에 걸쳐 서서히 바꿉니다.',\n    move_xy_time_elements:\n        'A-- x좌표의 변화 값<br>① 양수: 오브젝트가 오른쪽으로 이동합니다.<br>② 음수: 오브젝트가 왼쪽으로 이동합니다.%nextB-- y좌표의 변화 값<br>① 양수: 오브젝트가 위쪽으로 이동합니다.<br>② 음수: 오브젝트가 아래쪽으로 이동합니다.%nextC-- 이동하는 시간(초)',\n    move_xy_time_exampleCode:\n        'def when_start():\\n    Entry.add_xy_for_sec(100, 100, 2)\\n    Entry.add_xy_for_sec(-100, -100, 2)',\n    move_xy_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오른쪽 위로 100만큼 2초 동안 이동한 후 왼쪽 아래로 100만큼 2초 동안 이동합니다.',\n    locate_x_desc: '오브젝트의 x좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_x_elements: 'A-- 이동할 x좌표',\n    locate_x_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_x(100)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_x(-100)\\n',\n    locate_x_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 100으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 x좌표를 -100으로 정합니다.',\n    locate_y_desc: '오브젝트의 y좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_y_elements: 'B-- 이동할 y좌표',\n    locate_y_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.set_y(100)\\n\\ndef when_press_key(\"down\"):\\n    Entry.set_y(-100)',\n    locate_y_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 y좌표를 100으로 정하고, 아래쪽화살표키를 누르면 오브젝트의 y좌표를 -100으로 정합니다.',\n    locate_xy_desc: '오브젝트가 좌표(A, B)로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_elements: 'A-- 이동할 x좌표%nextB-- 이동할 y좌표',\n    locate_xy_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_xy(0, 0)\\n\\ndef when_press_key(\"right\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\"up\"):\\n    Entry.add_y(10)',\n    locate_xy_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 오브젝트의 x, y좌표를 0으로 정합니다.',\n    locate_xy_time_desc:\n        '오브젝트가 좌표(A, B)로 C초에 걸쳐 서서히 이동합니다.(오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_time_elements: 'A-- 이동할 x좌표%nextB-- 이동할 y좌표%nextC-- 이동하는 시간',\n    locate_xy_time_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_xy_for_sec(0, 0, 2)\\n\\ndef when_press_key(\"right\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\"up\"):\\n    Entry.add_y(10)',\n    locate_xy_time_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 2초 동안 오브젝트를 x,y 좌표 0으로 이동시킵니다.',\n    locate_desc: '오브젝트가 A의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    locate_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.move_to(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.move_to(\"오브젝트\")',\n    locate_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 마우스포인터 위치로 이동합니다.<br>스페이스키를 누르면 오브젝트가 \"오브젝트\" 위치로 이동합니다.',\n    locate_object_time_desc:\n        '오브젝트가 A의 위치로 B초에 걸쳐 서서히 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_object_time_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\" %nextB-- 이동하는 시간(초)',\n    locate_object_time_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.move_to_for_sec(\"mouse_pointer\", 2)',\n    locate_object_time_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 2초 동안 서서히 마우스포인터 위치로 이동합니다.',\n    rotate_relative_desc:\n        '오브젝트의 방향을 A도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_relative_elements: 'A-- 회전할 각도',\n    rotate_relative_exampleCode:\n        'def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)',\n    rotate_relative_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.',\n    direction_relative_desc: '오브젝트의 이동 방향을 A도만큼 회전합니다.',\n    direction_relative_elements: 'A-- 회전할 각도',\n    direction_relative_exampleCode:\n        'def when_start():\\n    Entry.move_to_direction(50)\\n    Entry.wait_for_sec(0.5)\\n    Entry.add_direction(90)\\n    Entry.wait_for_sec(0.5)\\n    Entry.move_to_direction(50)',\n    direction_relative_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 50만큼 이동한 다음 0.5초간 기다립니다. 그 후 이동방향을 90도 만큼 회전하고 0.5초간 기다린 후 이동방향으로 50만큼 이동합니다.',\n    rotate_by_time_desc:\n        '오브젝트의 방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_by_time_elements: 'A-- 회전할 각도%nextB-- 회전할 시간(초)',\n    rotate_by_time_exampleCode:\n        'def when_start():\\n    Entry.add_rotation_for_sec(90, 2)\\n    Entry.add_rotation_for_sec(-90, 2)',\n    rotate_by_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 2초 동안 90도 만큼 회전하고, 다시 2초 동안 -90도 만큼 회전합니다.',\n    direction_relative_duration_desc:\n        '오브젝트의 이동방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    direction_relative_duration_elements: 'A-- 회전할 각도%nextB-- 회전할 시간(초)',\n    direction_relative_duration_exampleCode:\n        'def when_start():\\n    Entry.add_direction_for_sec(90, 2)\\n\\ndef when_start():\\n    while True:\\n        Entry.move_to_direction(1)',\n    direction_relative_duration_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트의 이동방향을 2초 동안 90도만큼 회전시킵니다. 동시에 오브젝트는 이동방향으로 1만큼 계속 이동합니다.',\n    rotate_absolute_desc: '오브젝트의 방향을 A로 정합니다.',\n    rotate_absolute_elements: 'A-- 설정할 방향',\n    rotate_absolute_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_rotation(90)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_rotation(270)',\n    rotate_absolute_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 방향을 90으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 방향을 270으로 정합니다.',\n    direction_absolute_desc: '오브젝트의 이동방향을 A로 정합니다.',\n    direction_absolute_elements: 'A-- 설정할 이동방향',\n    direction_absolute_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_direction(90)\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_direction(270)\\n    Entry.move_to_direction(10)',\n    direction_absolute_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 이동방향을 90으로 정한 후 해당 쪽으로 10만큼 이동하고, 왼쪽화살표키를 누르면 오브젝트의 이동방향을 270으로 정하고 해당쪽으로 10만큼 이동합니다.',\n    see_angle_object_desc:\n        '오브젝트가 A쪽을 바라봅니다. (이동방향이 A를 향하도록 오브젝트의 방향을 회전해줍니다.)',\n    see_angle_object_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    see_angle_object_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.look_at(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.look_at(\"오브젝트\")',\n    see_angle_object_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 마우스포인터쪽을 바라보고, 스페이스키를 누르면 \"오브젝트\"쪽을 바라봅니다.',\n    move_to_angle_desc: '오브젝트가 A만큼 B방향으로 움직입니다.',\n    move_to_angle_elements:\n        'A-- 이동할 거리에 해당하는 수%nextB-- 이동할 방향(12시 방향이 0도, 시계방향으로 증가)',\n    move_to_angle_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.move_to_degree(10, 0)\\n\\ndef when_press_key(\"down\"):\\n    Entry.move_to_degree(10, 180)',\n    move_to_angle_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트가 0도방향으로 10만큼 이동하고, 아래쪽화살표키를 누르면 오브젝트가 180도방향으로 10만큼 이동합니다.',\n    show_desc: '오브젝트를 화면에 나타냅니다.',\n    show_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()',\n    show_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.',\n    hide_desc: '오브젝트를 화면에서 보이지 않게 합니다.',\n    hide_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()',\n    hide_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.',\n    dialog_time_desc:\n        '오브젝트가 A를 B초 동안 말풍선으로 말한 후 다음 명령어가 실행됩니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.',\n    dialog_time_elements:\n        'A-- 말할 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등%nextB-- 말하는 시간(초)',\n    dialog_time_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(\"안녕! 나는\", 2)\\n    Entry.print_for_sec(16, 2)\\n    Entry.print_for_sec(\"살이야\", 2)',\n    dialog_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"안녕! 나는\", 16, \"살이야\"를 각각 2초 동안 차례대로 말합니다.',\n    dialog_desc: '오브젝트가 A를 말풍선으로 말합니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.',\n    dialog_elements: 'A-- 말할 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    dialog_exampleCode:\n        'def when_start():\\n    Entry.print(\"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\")\\n\\ndef when_press_key(1):\\n    Entry.print(1)\\n\\ndef when_press_key(2):\\n    Entry.print(2)\\n',\n    dialog_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\"를 말하고, 키보드로 1, 2를 누르면 각각 1, 2라 말합니다.',\n    remove_dialog_desc: '오브젝트가 말하고 있는 말풍선을 지웁니다.',\n    remove_dialog_exampleCode:\n        'def when_start():\\n    Entry.print(\"말풍선을 지우려면 엔터를 눌러!\")\\n\\ndef when_press_key(\"enter\"):\\n    Entry.clear_print()',\n    remove_dialog_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"말풍선을 지우려면 엔터를 눌러!\"라 말하고, 엔터키를 누르면 말풍선이 사라집니다.',\n    change_to_some_shape_desc: '오브젝트를 A 모양으로 바꿉니다.',\n    change_to_some_shape_elements:\n        'A-- 아래 선택지 중 하나<br>① 모양 이름 : [속성] 탭의 \"모양 이름\"을 적음<br>② 모양 번호 : [속성] 탭의 모양 번호를 적음',\n    change_to_some_shape_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\"오브젝트모양\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\"오브젝트모양\")',\n    change_to_some_shape_exampleDesc:\n        '[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 \"오브젝트모양\"으로 모양을 바꾸고 0.3초간 기다린 다음 \"오브젝트모양\"모양으로 모양을 바꿉니다.',\n    change_to_next_shape_desc: '오브젝트의 모양을 다음 또는 이전 모양으로 바꿉니다.',\n    change_to_next_shape_elements:\n        'A-- 아래 선택지 중 하나<br>① 다음 모양 : \"next\" 또는 \"다음\" <br>② 이전 모양 : \"pre\" 또는 \"이전\"',\n    change_to_next_shape_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\"next\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\"pre\")',\n    change_to_next_shape_exampleDesc:\n        '[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 모양으로 오브젝트 모양을 바꾸고 0.3초간 기다린 다음 이전 모양으로 오브젝트 모양을 바꿉니다.',\n    add_effect_amount_desc: '오브젝트에 A 효과를 B만큼 줍니다.',\n    add_effect_amount_elements:\n        'A -- 아래 선택지 중 하나<br>① “color” 또는 “색깔“                 <br>② “brightness” 또는 “밝기”                <br>③ “transparency” 또는 “투명도”%nextB-- 효과의 변화 정도',\n    add_effect_amount_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.add_effect(\"color\", 50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\"brightness\", -50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\"transparency\", 50)',\n    add_effect_amount_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔 효과를 50만큼 주고 1초간 기다리고, 밝기 효과를 -50만큼 주고 1초간 기다립니다. 그 후 투명도 효과를 50만큼 줍니다.',\n    change_effect_amount_desc: '오브젝트의 A 효과를 B로 정합니다.',\n    change_effect_amount_elements:\n        'A-- 아래 선택지 중 하나<br>① “color” 또는 “색깔“                 <br>② “brightness” 또는 “밝기”                <br>③ “transparency” 또는 “투명도”%nextB-- 효과의 값<br>① color: 0~100 범위의 수, 100을 주기로 반복됨<br>② brightness: -100~100 사이 범위의 수, -100이하는 -100 으로 100 이상은 100 으로 처리 됨<br>③ transparency: 0~100 사이 범위의 수, 0 이하는 0으로, 100이상은 100으로 처리 됨',\n    change_effect_amount_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_effect(\"color\", 50)\\n    Entry.set_effect(\"brightness\", 50)\\n    Entry.set_effect(\"transparency\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.set_effect(\"color\", 0)\\n    Entry.set_effect(\"brightness\", 0)\\n    Entry.set_effect(\"transparency\", 0)',\n    change_effect_amount_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 각 효과를 0으로 정합니다.',\n    erase_all_effects_desc: '오브젝트에 적용된 효과를 모두 지웁니다.',\n    erase_all_effects_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_effect(\"color\", 50)\\n    Entry.set_effect(\"brightness\", 50)\\n    Entry.set_effect(\"transparency\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.clear_effect()\\n',\n    erase_all_effects_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 오브젝트에 적용된 모든 효과를 지웁니다.',\n    change_scale_size_desc: '오브젝트의 크기를 A만큼 바꿉니다.',\n    change_scale_size_elements: 'A-- 크기 변화 값',\n    change_scale_size_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\"space\"):\\n    Entry.set_size(100)',\n    change_scale_size_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.',\n    set_scale_size_desc: '오브젝트의 크기를 A로 정합니다.',\n    set_scale_size_elements: 'A-- 크기값',\n    set_scale_size_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\"space\"):\\n    Entry.set_size(100)',\n    set_scale_size_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.',\n    flip_x_desc: '오브젝트의 상하 모양을 뒤집습니다.',\n    flip_x_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\"right\"):\\n    Entry.flip_vertical()',\n    flip_x_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.',\n    flip_y_desc: '오브젝트의 좌우 모양을 뒤집습니다.',\n    flip_y_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\"right\"):\\n    Entry.flip_vertical()',\n    flip_y_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.',\n    change_object_index_desc: '오브젝트의 레이어를 A로 가져옵니다.',\n    change_object_index_elements:\n        'A-- 아래 선택지 중 하나<br>① “front\" 또는 “맨 앞“                 <br>② “forward” 또는 “앞”                <br>③ “backward” 또는 “뒤”<br>④ “back” 또는 “맨 뒤”',\n    change_object_index_exampleCode:\n        'def when_start():\\n    Entry.send_layer_to(\"front\")\\n    Entry.wait_for_sec(2)\\n    Entry.send_layer_to(\"backward\")',\n    change_object_index_exampleDesc:\n        '오브젝트가 여러개가 겹쳐 있을 경우 [시작하기]버튼을 클릭하면  해당 오브젝트의 레이어를 가장 앞으로 가져와서 보여줍니다.',\n    brush_stamp_desc: '오브젝트의 모양을 도장처럼 실행화면 위에 찍습니다.',\n    brush_stamp_exampleCode:\n        'def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()',\n    brush_stamp_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.',\n    start_drawing_desc:\n        '오브젝트가 이동하는 경로를 따라 선이 그려지기 시작합니다. (오브젝트의 중심점이 기준)',\n    start_drawing_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    for i in range(10):\\n        Entry.move_to_direction(10)',\n    start_drawing_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 오브젝트가 이동방향으로 10만큼 10번 이동할 때 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    stop_drawing_desc: '오브젝트가 선을 그리는 것을 멈춥니다.',\n    stop_drawing_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n\\ndef when_click_mouse_on():\\n    Entry.stop_drawing()',\n    stop_drawing_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 마우스를 클릭하면 그리는것을 멈춥니다.',\n    set_color_desc: '오브젝트가 그리는 선의 색을 A로 정합니다.',\n    set_color_elements:\n        'A-- 아래 선택지 중 하나<br>① 색상 코드 : \"#FF0000\", \"#FFCC00\", \"#3333FF\", \"#000000\" 등<br>② 색깔명 : \"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"navy\", \"purple\", \"black\", \"white\", \"brown\"',\n    set_color_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_color_to(\"#000099\")\\n    while True:\\n        Entry.move_to_direction(1)',\n    set_color_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 색을 \"#000099\"로 정합니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    set_random_color_desc: '오브젝트가 그리는 선의 색을 무작위로 정합니다.',\n    set_random_color_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n        Entry.set_brush_color_to_random()',\n    set_random_color_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 색깔은 계속해서 무작위로 정해집니다.',\n    change_thickness_desc: '오브젝트가 그리는 선의 굵기를 A만큼 바꿉니다.',\n    change_thickness_elements: 'A-- 굵기 변화 값',\n    change_thickness_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.add_brush_size(1)\\n        Entry.move_to_direction(10)',\n    change_thickness_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 굵기는 계속해서 1씩 커집니다.',\n    set_thickness_desc: '오브젝트가 그리는 선의 굵기를 A로 정합니다.',\n    set_thickness_elements: 'A-- 굵기값(1이상의 수)',\n    set_thickness_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)',\n    set_thickness_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    change_brush_transparency_desc: '오브젝트가 그리는 선의 투명도를 A만큼 바꿉니다.',\n    change_brush_transparency_elements: 'A-- 투명도 변화 값',\n    change_brush_transparency_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.add_brush_transparency(5)',\n    change_brush_transparency_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 투명도는 계속해서 5만큼 바꿉니다.',\n    set_brush_tranparency_desc: '오브젝트가 그리는 선의 투명도를 A로 정합니다.',\n    set_brush_tranparency_elements: 'A-- 투명도값(0~100 의 범위)',\n    set_brush_tranparency_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    Entry.set_brush_transparency(50)\\n    while True:\\n        Entry.move_to_direction(10)',\n    set_brush_tranparency_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로, 선의 투명도를 50으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    brush_erase_all_desc: '오브젝트가 그린 선과 도장을 모두 지웁니다.',\n    brush_erase_all_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(10)\\n\\ndef when_click_mouse_on():\\n    Entry.clear_drawing()',\n    brush_erase_all_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 마우스를 클릭하면 오브젝트가 그린 선을 모두 지웁니다.',\n    text_read_desc:\n        '글상자 A의 내용입니다.<br />(내용 안에 개행이 있는 경우, 띄어쓰기하여 반환됩니다.)',\n    text_read_elements: 'A-- 아래 선택지 중 하나<br />① \"오브젝트(글상자) 이름\" <br />② 자기 자신',\n    text_read_exampleCode: 'def when_start():\\n    Entry.print(Entry.contents_of_textbox(\"A\"))',\n    text_read_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 글상자 \"A\"의 내용을 말합니다.​',\n    text_write_desc: '글상자의 내용을 A로 고쳐씁니다.',\n    text_write_elements:\n        'A-- 글상자의 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    text_write_exampleCode: 'def when_start():\\n    Entry.write_text(\"엔트리\")',\n    text_write_exampleDesc: '[시작하기]버튼을 클릭하면 글상자의 내용을 \"엔트리\"로 바꿉니다.',\n    text_append_desc: '글상자의 내용 뒤에 A를 추가합니다.',\n    text_append_elements:\n        'A-- 글상자의 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    text_append_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"안녕?\")\\n    Entry.wait_for_sec(1)\\n    Entry.append_text(\"엔트리!\")',\n    text_append_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"안녕?\"이 되었다가 1초 뒤에 \"엔트리!\"가 추가되어 \"안녕?엔트리!\"가 됩니다.',\n    text_prepend_desc: '글상자의 내용 앞에 A를 추가합니다.',\n    text_prepend_elements:\n        'A-- 글상자의 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    text_prepend_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"반가워!\")\\n    Entry.wait_for_sec(1)\\n    Entry.prepend_text(\"엔트리!\")',\n    text_prepend_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"반가워!\"가 되었다가 1초 뒤에 \"엔트리!\"가 앞에 추가되어 \"엔트리!반가워!\"가 됩니다.',\n    text_flush_desc: '글상자에 저장된 값을 모두 지웁니다.',\n    text_flush_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"엔트리\")\\n    Entry.wait_for_sec(1)\\n    Entry.clear_text()',\n    text_flush_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"엔트리\"가 되었다가 1초 뒤에 모든 내용이 사라집니다.',\n    sound_something_with_block_desc: '오브젝트가 A 소리를 재생합니다.',\n    sound_something_with_block_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound(\"소리\")\\n    Entry.add_size(50)',\n    sound_something_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 재생하면서 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_second_with_block_desc: '오브젝트가 A소리를 B초 만큼 재생합니다.',\n    sound_something_second_with_block_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_second_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_for_sec(\"소리\", 1)\\n    Entry.add_size(50)',\n    sound_something_second_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 1초 동안 재생하면서, 오브젝트의 크기가 50만큼 커집니다.',\n    sound_from_to_desc: '오브젝트가 A소리를 B초부터 C초까지 재생합니다.',\n    sound_from_to_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_from_to_exampleCode:\n        'def when_start():\\n    Entry.play_sound_from_to(\"소리\", 0.5, 1)\\n    Entry.add_size(50)',\n    sound_from_to_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 0.5초부터 1초 구간까지만 재생하면서, 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_wait_with_block_desc:\n        '오브젝트가 A 소리를 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_something_wait_with_block_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_wait_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_and_wait(\"소리\")\\n    Entry.add_size(50)',\n    sound_something_wait_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_second_wait_with_block_desc:\n        '오브젝트가 A소리를 B초 만큼 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_something_second_wait_with_block_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_second_wait_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_for_sec_and_wait(\"소리\", 1)\\n    Entry.add_size(50)',\n    sound_something_second_wait_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 1초 동안 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_from_to_and_wait_desc:\n        '오브젝트가 A소리를 B초부터 C초까지 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_from_to_and_wait_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_from_to_and_wait_exampleCode:\n        'def when_start():\\n    Entry.play_sound_from_to_and_wait(\"소리\", 0.5, 1)\\n    Entry.add_size(50)',\n    sound_from_to_and_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 0.5초부터 1초 구간까지만 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_volume_change_desc: '작품에서 재생되는 모든 소리의 크기를 A퍼센트만큼 바꿉니다.',\n    sound_volume_change_elements: 'A-- 소리 크기 변화 값',\n    sound_volume_change_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")',\n    sound_volume_change_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\"작아집니다.',\n    sound_volume_set_desc: '작품에서 재생되는 모든 소리의 크기를 A퍼센트로 정합니다.',\n    sound_volume_set_elements: 'A-- 소리 크기값',\n    sound_volume_set_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_press_key(\"enter\"):\\n    Entry.set_sound_volume(100)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")',\n    sound_volume_set_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\"작아집니다. 엔터키를 누르면 소리의 크기를 100\"로 정합니다.',\n    sound_silent_all_desc: '현재 재생 중인 모든 소리를 멈춥니다.',\n    sound_silent_all_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")\\n\\ndef when_press_key(\"enter\"):\\n    Entry.stop_sound()',\n    sound_silent_all_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 엔터키를 누르면 현재 재생 중인 소리를 멈춥니다.',\n    is_clicked_desc: '마우스를 클릭한 경우 True로 판단합니다.',\n    is_clicked_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_mouse_clicked():\\n            Entry.print_for_sec(\"반가워!\", 0.5)',\n    is_clicked_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 마우스를 클릭했는지 확인합니다. 만약 마우스를 클릭하면 오브젝트가 \"반가워!\"라고 0.5초간 말합니다.',\n    is_press_some_key_desc: 'A 키가 눌려져 있는 경우 True로 판단합니다.',\n    is_press_some_key_elements:\n        'A-- 아래 선택지 중 하나<br>① 알파벳 : \"A\", \"B\" ~ \"Z\" 등(소문자 가능)<br>② 숫자: 1, 2, 3, 4 ~ 9, 0<br>③ 특수키: \"space\", \"enter\"<br>④ 방향키 : \"up\", \"down\", \"right\", \"left\"',\n    is_press_some_key_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"space\"):\\n            Entry.move_to_direction(10)',\n    is_press_some_key_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 선택한 키를 눌렀는지 확인합니다. 만약 스페이스 키를 누르면 오브젝트가 이동방향으로 10만큼 이동합니다.',\n    reach_something_desc: '오브젝트가 A와 닿은 경우 True으로 판단합니다.',\n    reach_something_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\"<br>③ \"edge\", \"edge_up\", \"edge_down\", \"edge_right\", \"edge_left\"',\n    reach_something_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_touched(\"edge\"):\\n            Entry.add_rotation(150)',\n    reach_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 만약 오브젝트가 벽에 닿으면 150만큼 회전하게 됩니다.',\n    boolean_basic_operator_desc: 'A와 B를 비교하여 True 또는 False로 판단합니다.',\n    boolean_basic_operator_elements:\n        'A, B-- 비교하고자 하는 숫자값<br>① == : A와 B의 값이 같으면 True, 아니면 False<br>② > : A의 값이 B의 값보다 크면 true, 아니면 False<br>③ < : A의 값이 B의 값보다 작으면 true, 아니면 False<br>④ >= : A의 값이 B의 값보다 크거나 같으면 true, 아니면 False<br>⑤ <= : A의 값이 B의 값보다 작거나 같으면 true, 아니면 False',\n    boolean_basic_operator_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_x(10)\\n        if Entry.value_of_object(\"오브젝트\", \"x\") > 240:\\n            Entry.set_x(0)',\n    boolean_basic_operator_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트 x좌표를 10만큼 바꿉니다. 만약 오브젝트 x좌표가 240보다 크면 오브젝트 x좌표를 0으로 정합니다.',\n    boolean_and_desc: 'A와 B의 판단이 모두 True인 경우 True, 아닌 경우 False로 판단합니다.',\n    boolean_and_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_and_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") and Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_and_exampleDesc:\n        '[시작하기]버튼을 클릭하고 키보드의 \"a\" 와 \"s\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.',\n    boolean_or_desc: 'A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False로 판단합니다.',\n    boolean_or_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_or_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") or Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_or_exampleDesc:\n        '[시작하기]버튼을 클릭하면 키보드의 \"a\"나 \"s\"키 중 무엇이든 하나를 누르면 오브젝트에 색깔 효과를 10만큼 줍니다.',\n    boolean_not_desc: 'A 판단이 True이면 False, False이면 True로 판단합니다.',\n    boolean_not_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_not_exampleCode:\n        'def when_start():\\n    while True:\\n        if not Entry.is_mouse_clicked():\\n            Entry.add_size(1)',\n    boolean_not_exampleDesc:\n        '[시작하기]버튼을 클릭하면 마우스를 클릭하지 않은 동안 크기가 1씩 커집니다.',\n    calc_basic_desc: 'A와 B의 연산값입니다.',\n    calc_basic_elements:\n        'A, B-- 연산하고자 하는 숫자값<br>① + : A와 B를 더한 값<br>② - : A와 B를 뺀 값<br>③ x : A와 B를 곱한 값<br>④ / : A와 B를 나눈 값',\n    calc_basic_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 + 10, 2)\\n    Entry.print_for_sec(10 - 10, 2)\\n    Entry.print_for_sec(10 * 10, 2)\\n    Entry.print_for_sec(10 / 10, 2)',\n    calc_basic_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10과 10을 더한값, 뺀값, 곱한값, 나눈값을 각 2초간 말합니다.',\n    calc_rand_desc:\n        'A와 B 사이에서 선택된 무작위 수의 값입니다. (두 수 모두 정수를 입력한 경우 정수로,두 수 중 하나라도 소수를 입력한 경우 소수로 무작위 수가 선택됩니다.)',\n    calc_rand_elements:\n        'A, B-- 무작위 수를 추출할 범위<br>① random.randint(A, B) : A, B를 정수로 입력하면 정수 범위에서 무작위 수를 추출<br>② random.uniform(A, B) : A, B를 실수로 입력하면 실수 범위에서 무작위 수를 추출',\n    calc_rand_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(random.randint(1, 10), 2)\\n    Entry.print_for_sec(random.uniform(0.1, 2), 2)',\n    calc_rand_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1부터 10사이의 정수중 무작위 수를 뽑아 2초간 말합니다. 그 후 0.1부터 2사이의 실수중 무작위 수를 뽑아 2초간 말합니다.',\n    coordinate_mouse_desc: '마우스 포인터의 A 좌표 값을 의미합니다.',\n    coordinate_mouse_elements: 'A-- 아래 선택지 중 하나<br>① \"x\" 또는 \"X\"<br>② \"y\" 또는 \"Y\"',\n    coordinate_mouse_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_mouse_pointer(\"x\"))',\n    coordinate_mouse_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 마우스 포인터의 x좌표를 계속해서 말합니다.',\n    coordinate_object_desc: 'A에 대한 B정보값입니다.',\n    coordinate_object_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"self\" 또는 \"자신\"%nextB-- 아래 선택지 중 하나<br>① \"x\" 또는 \"X\"<br>② \"y\" 또는 \"Y\"<br>③ \"rotation\" 또는 \"방향\"<br>④ \"direction\" 또는 \"이동 방향\"<br>⑤ \"size\"  또는 \"크기\"<br>⑥ \"shape_number\" 또는 \"모양 번호\"<br>⑦ \"shape_name\" 또는 \"모양 이름\"',\n    coordinate_object_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_x(1)\\n        Entry.print(Entry.value_of_object(\"오브젝트\", \"x\"))\\n',\n    coordinate_object_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트의 x좌표가 1씩 증가하며, \"오브젝트\"의 x좌표를 말합니다.',\n    get_sound_volume_desc: '현재 작품에 설정된 소리의 크기값입니다.',\n    get_sound_volume_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_sound_volume())',\n    get_sound_volume_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 소리의 크기값을 계속해서 말합니다.',\n    quotient_and_mod_desc: 'A와 B의 연산값입니다.',\n    quotient_and_mod_elements:\n        'A, B-- 연산하고자 하는 숫자값<br>① // : A / B의 몫에 해당하는 값<br>② % : A / B의 나머지에 해당하는 값',\n    quotient_and_mod_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 // 3, 2)\\n    Entry.print_for_sec(10 % 3, 2)',\n    quotient_and_mod_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10 / 3의 몫인 3을 2초 동안 말하고, 나머지인 1을 2초 동안 말합니다.',\n    calc_operation_desc: 'A의 연산값입니다.',\n    calc_operation_elements:\n        'A, B-- 연산하고자 하는 숫자값<br>① A ** 2 : A를 제곱한 값<br>② math.sqrt(A): A의 루트값<br>③ math.sin(A): A의 사인값<br>④ math.cos(A): A의 코사인 값<br>⑤ math.tan(A):  A의 탄젠트값 <br>⑥ math.asin(A): A의 아크사인값<br>⑦ math.acos(A): A의 아크코사인값<br>⑧ math.atan(): A의 아크탄젠트값<br>⑨ math.log10(A): A의 로그값<br>⑩ math.log(A): A의 자연로그값<br>⑪ A - math.floor(A): A의 소수점 부분<br>⑫ math.floor(A): A의 소수점 버림값<br>⑬ math.ceil(A): A의 소수점 올림값<br>⑭ math.round(A): A의 소수점 반올림값<br>⑮ math.factorial(A): A의 팩토리얼 값<br>⑯ math.fabs(A): A의 절댓값',\n    calc_operation_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 ** 2, 2)\\n    Entry.print_for_sec(math.sqrt(9), 2)\\n    Entry.print_for_sec(math.sin(90), 2)\\n    Entry.print_for_sec(math.fabs(-10), 2)',\n    calc_operation_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10의 제곱, 9의 루트값, 90의 사인값, -10의 절댓값을 각 2초 동안 말합니다.',\n    get_project_timer_value_desc: '이 명령이 실행되는 순간 초시계에 저장된 값입니다.',\n    get_project_timer_value_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    get_project_timer_value_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    choose_project_timer_action_desc:\n        '초시계의 동작을 A로 정합니다.<br>(이 명령어를 사용하면 실행화면에 ‘초시계 창’이 생성됩니다.)',\n    choose_project_timer_action_elements:\n        'A-- 아래 선택지 중 하나<br>① \"start\" : 초시계를 시작<br>② \"stop\" : 초시계를 정지<br>③ \"reset\" : 초시계를 초기화',\n    choose_project_timer_action_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    choose_project_timer_action_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    set_visible_project_timer_desc: '실행화면의 초시계 창을 A로 설정합니다.',\n    set_visible_project_timer_elements:\n        'A-- 아래 선택지 중 하나<br>① \"hide\" : 초시계창을 숨김<br>② \"show\" : 초시계창을 보임',\n    set_visible_project_timer_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    set_visible_project_timer_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    get_date_desc: '현재 A에 대한 값입니다.',\n    get_date_elements:\n        'A-- 아래 선택지 중 하나<br>① \"year\" : 현재 연도 값<br>② \"month\" : 현재 월 값<br>③ \"day\" : 현재 일 값<br>④ \"hour\" : 현재 시간 값<br>⑤ \"minute\" : 현재 분 값<br>⑥ \"second\" : 현재 초 값',\n    get_date_exampleCode:\n        'def when_start():\\n    Entry.print(Entry.value_of_current_time(\"year\") + \"년\" + Entry.value_of_current_time(\"month\") + \"월\")',\n    get_date_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 현재년도와 월을 말합니다.',\n    distance_something_desc: '자신과 A까지의 거리 값입니다.',\n    distance_something_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    distance_something_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_distance_to(\"mouse_pointer\"))',\n    distance_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 마우스포인터와의 거리를 계속해서 말합니다.',\n    get_sound_duration_desc: '소리 A의 길이(초)값입니다.',\n    get_sound_duration_elements: 'A-- \"소리 이름\"',\n    get_sound_duration_exampleCode:\n        'def when_start():\\n    Entry.print(Entry.value_of_sound_length_of(\"소리\"))',\n    get_sound_duration_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"소리\"의 길이를 말합니다.',\n    get_user_name_desc: '작품을 실행하고 있는 사용자의 이름 값입니다.',\n    get_user_name_exampleCode: 'def when_start():\\n    Entry.print(Entry.value_of_username())',\n    get_user_name_exampleDesc:\n        '[시작하기]버튼을 클릭하면 작품을 실행하고 있는 사용자의 이름 값을 말합니다.',\n    length_of_string_desc: '입력한 문자값의 공백을 포함한 글자 수입니다.',\n    length_of_string_elements: 'A-- \"문자열\"',\n    length_of_string_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(len(\"안녕\"), 2)\\n    Entry.print_for_sec(len(\"엔트리\"), 2)',\n    length_of_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕\"과 \"엔트리\"의 글자 수를 각각 2초 동안 말합니다.',\n    combine_something_desc:\n        'A 문자열과 B 문자열을 결합한 값입니다. (A, B 중 하나가 숫자면 문자열로 바꾸어 처리되고, 둘 다 숫자면 덧셈 연산으로 처리됩니다.)',\n    combine_something_elements: 'A, B-- \"문자열\"',\n    combine_something_exampleCode: 'def when_start():\\n    Entry.print(\"안녕! \" + \"엔트리\")',\n    combine_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕!\"과 \"엔트리\"를 결합한 \"안녕! 엔트리\"를 말합니다.',\n    char_at_desc: 'A 문자열의 B번째의 글자 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    char_at_elements: 'A-- \"문자열\"%nextB-- 찾고자 하는 문자열의 위치',\n    char_at_exampleCode: 'def when_start():\\n    Entry.print(\"안녕 엔트리!\"[0])',\n    char_at_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"의 0번째 글자인 \"안\"을 말합니다.',\n    substring_desc:\n        'A 문자열의 B위치부터 C-1위치까지의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    substring_elements:\n        'A-- \"문자열\"%nextB-- 포함할 문자열의 시작 위치<br>첫 번째 글자는 0부터 시작%nextC-- 문자열을 포함하지 않는 위치',\n    substring_exampleCode: 'def when_start():\\n    Entry.print(\"안녕 엔트리!\"[1:5])',\n    substring_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"의 1에서 4번째 글자인 \"녕 엔트\"를 말합니다.',\n    index_of_string_desc:\n        'A문자열에서 B문자열이 처음으로 등장하는 위치의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    index_of_string_elements: 'A, B-- \"문자열\"',\n    index_of_string_exampleCode:\n        'def when_start():\\n    Entry.print(\"안녕 엔트리!\".find(\"엔트리\"))',\n    index_of_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"에서 \"엔트리\"가 처음으로 등장하는 위치인 3을 말합니다.',\n    replace_string_desc:\n        'A 문자열에서 B문자열을 모두 찾아 C문자열로 바꾼 값입니다.<br>(영문 입력시 대소문자를 구분합니다.)',\n    replace_string_elements: 'A, B, C-- \"문자열\"',\n    replace_string_exampleCode:\n        'def when_start():\\n    Entry.print(\"안녕 엔트리!\".replace( \"안녕\", \"반가워\"))',\n    replace_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"에서 \"안녕\"을 \"반가워\"로 바꾼 \"반가워 엔트리!\"를 말합니다.',\n    change_string_case_desc: 'A의 모든 알파벳을 대문자 또는 소문자로 바꾼 문자값입니다.',\n    change_string_case_elements:\n        'A-- \"문자열\"<br>① A.upper(): A의 모든 알파벳을 대문자로 바꾼 값<br>② A.lower() : A의 모든 알파벳을 소문자로 바꾼 값',\n    change_string_case_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(\"Hello Entry!\".upper(), 2)\\n    Entry.print_for_sec(\"Hello Entry!\".lower(), 2)',\n    change_string_case_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"Hello Entry!\"를 모두 대문자로 바꾼 \"HELLO ENTRY!\"를 2초간 말한 다음 모두 소문자로 바꾼 \"hello entry!\"를 2초간 말합니다.',\n    ask_and_wait_desc:\n        \"오브젝트가 A 내용을 말풍선으로 묻고, 대답을 입력받습니다. 대답은 실행화면 또는 콘솔창에서 입력할 수 있으며 입력된 값은 'Entry.answer()'에 저장됩니다. <br>(이 명령어를 사용하면 실행화면에 ‘대답 창’이 생성됩니다.)\",\n    ask_and_wait_elements: 'A-- \"문자열\"',\n    ask_and_wait_exampleCode:\n        'def when_start():\\n    Entry.input(\"이름을 입력해보세요.\")\\n    Entry.print(Entry.answer() + \" 반가워!\")',\n    ask_and_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"이름을 입력해보세요.\"라고 말풍선으로 묻습니다. 이름을 입력하면 \"(입력한 이름) 반가워!\"라 말합니다.',\n    get_canvas_input_value_desc:\n        'Entry.input(A) 명령에 의해 실행화면 또는 콘솔에서 입력받은 값입니다.',\n    get_canvas_input_value_exampleCode:\n        'def when_start():\\n    Entry.input(\"이름을 입력해보세요.\")\\n    Entry.print(Entry.answer() + \" 반가워!\")',\n    get_canvas_input_value_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"이름을 입력해보세요.\"라고 말풍선으로 묻습니다. 이름을 입력하면 \"(입력한 이름) 반가워!\"라 말합니다.',\n    set_visible_answer_desc: '실행화면의 대답 창을 A로 설정합니다.',\n    set_visible_answer_elements:\n        'A-- 아래 선택지 중 하나<br>① \"hide\" : 대답 창을 숨김<br>② \"show\" : 대답 창을 보임',\n    set_visible_answer_exampleCode:\n        'def when_start():\\n    Entry.answer_view(\"hide\")\\n    Entry.input(\"나이를 입력하세요.\")\\n    Entry.print(Entry.answer())',\n    set_visible_answer_exampleDesc:\n        '[시작하기]버튼을 클릭하면 대답창이 숨겨지고, 오브젝트가 \"나이를 입력하세요.\"라고 말풍선으로 묻습니다. 나이를 입력하면 오브젝트가 입력한 나이를 말합니다.',\n    get_variable_desc: 'A 변수에 저장된 값입니다.',\n    get_variable_elements:\n        'A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A',\n    get_variable_exampleCode: 'age = 16\\n\\ndef when_start():\\n    Entry.print(age)',\n    get_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 말합니다.',\n    change_variable_desc: 'A 변수에 B만큼 더합니다.',\n    change_variable_elements:\n        'A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 숫자값',\n    change_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.print_for_sec(age, 2)\\n    age += 2\\n    Entry.print_for_sec(age, 2)',\n    change_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 2초 동안 말합니다. 그 후 age변수에 2를 더하고 더한값인 \"18\"을 2초 동안 말합니다.',\n    set_variable_desc:\n        'A 변수의 값을 B로 정합니다. 만약 A 변수가 없으면  [속성] 탭에 A 변수가 자동 생성됩니다.',\n    set_variable_elements:\n        'A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 변수에 넣을 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    set_variable_exampleCode: 'age = 16\\n\\ndef when_start():\\n    Entry.print(age)',\n    set_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 말합니다.',\n    show_variable_desc: 'A 변수 창을 실행화면에 보이게 합니다.',\n    show_variable_elements:\n        'A-- \"변수명\"<br>① 모든 오브젝트에서 사용: \"A\"<br>② 이 오브젝트에서 사용: \"self.A\"',\n    show_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\"age\")\\n    Entry.wait_for_sec(2)\\n    age = 20\\n    Entry.show_variable(\"age\")',\n    show_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨깁니다. 2초 후 변수값을 17로 바꾸고 age변수창을 실행화면에 보이게 합니다.',\n    hide_variable_desc: 'A 변수 창을 실행화면에서 숨깁니다.',\n    hide_variable_elements:\n        'A-- \"변수명\"<br>① 모든 오브젝트에서 사용: \"A\"<br>② 이 오브젝트에서 사용: \"self.A\"',\n    hide_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\"age\")\\n    Entry.print_for_sec(age, 2)',\n    hide_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨기고, 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 2초 동안 말합니다.',\n    value_of_index_from_list_desc:\n        'A 리스트에서 B위치의 항목 값을 의미합니다. <br>(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    value_of_index_from_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치',\n    value_of_index_from_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.print(basket[1])\\n',\n    value_of_index_from_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트가 basket 리스트의 1번째 항목인 orange를 말합니다.',\n    add_value_to_list_desc: 'A 리스트의 마지막 항목으로 B값이 추가됩니다.',\n    add_value_to_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트에 넣을 항목 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    add_value_to_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket.append(\"juice\")\\n    Entry.print(basket[4])',\n    add_value_to_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 \"juice\"를 basket의 마지막 항목으로 추가합니다. 오브젝트는 basket의 4번째 항목인 \"juice\"를 말합니다.',\n    remove_value_from_list_desc:\n        'A 리스트의 B위치에 있는 항목을 삭제합니다.<br>(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    remove_value_from_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치값',\n    remove_value_from_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\ndef when_start():\\n    basket.pop(0)\\n    Entry.print(basket[0])',\n    remove_value_from_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 항목인 apple을 삭제합니다. 오브젝트는 새롭게 basket의 0번째 항목이 된 \"orange\"를 말합니다.',\n    insert_value_to_list_desc:\n        'A 리스트의 B위치에 C항목을 끼워 넣습니다. <br>(첫 번째 항목의 위치는 0부터 시작합니다. B위치보다 뒤에 있는 항목들은 순서가 하나씩 밀려납니다.)',\n    insert_value_to_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    insert_value_to_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket.insert(1, \"juice\")\\n    Entry.print(basket[2])',\n    insert_value_to_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 1번째 위치에 항목 \"juice\"를 끼워 넣습니다. 오브젝트는 새롭게 basket의 2번째 항목이 된 \"orange\"를 말합니다.',\n    change_value_list_index_desc:\n        'A 리스트에서 B위치에 있는 항목의 값을 C 값으로 바꿉니다.<br>(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    change_value_list_index_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    change_value_list_index_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket[0] = \"juice\"\\n    Entry.print(basket[0])',\n    change_value_list_index_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 위치의 항목 \"apple\"을 \"juice\"로 바꿉니다. 오브젝트는 바뀐 basket의 0번째 항목 \"juice\"를 말합니다.',\n    length_of_list_desc: 'A 리스트가 보유한 항목 개수 값입니다.',\n    length_of_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A',\n    length_of_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.print(len(basket))',\n    length_of_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트는  basket의 항목 개수인 4를 말합니다.',\n    is_included_in_list_desc: 'A값을 가진 항목이 B리스트에 포함되어 있는지 확인합니다.',\n    is_included_in_list_elements:\n        'A-- 리스트의 항목 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등%nextB-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A',\n    is_included_in_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    if \"apple\" in basket:\\n        Entry.print(\"사과가 있어!\")',\n    is_included_in_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트에 \"apple\"항목이 있는지 확인합니다. \"apple\"항목이 있기 때문에 오브젝트는 \"사과가 있어!\"라 말합니다.',\n    show_list_desc: '선택한 리스트 창을 실행화면에 보이게 합니다.',\n    show_list_elements:\n        'A-- \"리스트명\"<br>① 모든 오브젝트에서 사용: \"A\"<br>② 이 오브젝트에서 사용: \"self.A\"',\n    show_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.hide_list(\"basket\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\"basket\")',\n    show_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.',\n    hide_list_desc: '선택한 리스트 창을 실행화면에서 숨깁니다.',\n    hide_list_elements:\n        'A-- \"리스트명\"<br>① 모든 오브젝트에서 사용: \"A\"<br>② 이 오브젝트에서 사용: \"self.A\"',\n    hide_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.hide_list(\"basket\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\"basket\")',\n    hide_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.',\n    boolean_and_or_desc: 'A와 B의 판단값을 확인하여 True 또는 False로 판단합니다.',\n    boolean_and_or_elements: '② or : A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False',\n    boolean_and_or_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") and Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_and_or_exampleDesc:\n        '[시작하기]버튼을 클릭하고 키보드의 \"a\" 와 \"s\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.',\n    check_weather_desc: 'B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.',\n    check_weather_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"sunny\" : 맑음<br>②    \"partly cloudy\" : 구름조금<br>③    \"mostly cloudy\" : 구름많음<br>④    \"cloudy\" : 흐림<br>⑤    \"rainy\" : 비<br>⑥    \"sleet\" : 진눈깨비<br>⑦    \"snowy\" : 눈%nextB-- 아래 선택지 중 하나<br>①    \"yesterday\" : 어제<br>②    \"today\" : 오늘<br>③    \"tomorrow\" : 내일<br>④    \"After 2 days\" : 모레<br>⑤    \"After 3 days\" : 3일 후<br>⑥    \"After 4 days\" : 4일 후<br>⑦    \"After 5 days\" : 5일 후<br>⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    check_weather_exampleCode:\n        'def when_start():\\n    if Weather.is_condition_sunny(\"today\", \"Seoul\"):\\n        Entry.print(\"오늘 서울의 날씨는 맑습니다.\")',\n    check_weather_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \"오늘 서울의 날씨는 맑습니다.\"라고 말합니다.​',\n    check_finedust_desc:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.',\n    check_finedust_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"good\" : 좋음<br>②    \"normal\" : 보통<br>③    \"bad\" : 나쁨<br>④    \"very bad\" : 매우나쁨%nextB-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    check_finedust_exampleCode:\n        'def when_start():\\n    if Weather.is_current_finedust_grade_good(\"Seoul\"):\\n        Entry.print(\"현재 서울의 미세먼지 등급은 좋음입니다.\")',\n    check_finedust_exampleDesc:\n        '[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​',\n    get_weather_data_desc:\n        '선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.',\n    get_weather_data_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"the lowest temperature\" : 최저기온<br>②    \"the highest temperature\" : 최고기온<br>③    \"humidity\" : 습도<br>④    \"precipitation\" : 강수량<br>⑤    \"precipitation probability\" : 강수확률<br>⑥    \"wind speed\" : 풍속%nextB-- 아래 선택지 중 하나<br>①    \"yesterday\" : 어제<br>②    \"today\" : 오늘<br>③    \"tomorrow\" : 내일<br>④    \"After 2 days\" : 모레<br>⑤    \"After 3 days\" : 3일 후<br>⑥    \"After 4 days\" : 4일 후<br>⑦    \"After 5 days\" : 5일 후<br>⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    get_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\"today\", \"Seoul\"))',\n    get_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​',\n    get_current_weather_data_desc: '현재 B지역의 A 날씨 정보값을 의미합니다.',\n    get_current_weather_data_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나<br>①    \"temperature\" : 기온<br>②    \"concentration of fine dust\" : 미세먼지농도',\n    get_current_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_current_temperature(\"Seoul\"))',\n    get_current_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.',\n    get_today_temperature_desc: '오늘 A지역의 B 시간대 기온 정보값을 의미합니다.',\n    get_today_temperature_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나<br>①    \"00\" : 당일 00시 측정된 기온값<br>②    \"03\" : 당일 03시 측정된 기온값<br>③    \"06\" : 당일 06시 측정된 기온값<br>④    \"09\" : 당일 09시 측정된 기온값<br>⑤    \"12\" : 당일 12시 측정된 기온값<br>⑥    \"15\" : 당일 15시 측정된 기온값<br>⑦    \"18\" : 당일 18시 측정된 기온값<br>⑧    \"21\" : 당일 21시 측정된 기온값',\n    get_today_temperature_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_today_temperature(\"Seoul\", 00))',\n    get_today_temperature_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​',\n    check_city_weather_desc: 'B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.',\n    check_city_weather_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"sunny\" : 맑음<br>②    \"partly cloudy\" : 구름조금<br>③    \"mostly cloudy\" : 구름많음<br>④    \"cloudy\" : 흐림<br>⑤    \"rainy\" : 비<br>⑥    \"sleet\" : 진눈깨비<br>⑦    \"snowy\" : 눈%nextB-- 아래 선택지 중 하나<br>①    \"yesterday\" : 어제<br>②    \"today\" : 오늘<br>③    \"tomorrow\" : 내일<br>④    \"After 2 days\" : 모레<br>⑤    \"After 3 days\" : 3일 후<br>⑥    \"After 4 days\" : 4일 후<br>⑦    \"After 5 days\" : 5일 후<br>⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    check_city_weather_exampleCode:\n        'def when_start():\\n    if Weather.is_condition_sunny(\"today\", \"Seoul\"):\\n        Entry.print(\"오늘 서울의 날씨는 맑습니다.\")',\n    check_city_weather_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \"오늘 서울의 날씨는 맑습니다.\"라고 말합니다.​',\n    check_city_finedust_desc:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.',\n    check_city_finedust_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"good\" : 좋음<br>②    \"normal\" : 보통<br>③    \"bad\" : 나쁨<br>④    \"very bad\" : 매우나쁨%nextB-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    check_city_finedust_exampleCode:\n        'def when_start():\\n    if Weather.is_current_finedust_grade_good(\"Seoul\"):\\n        Entry.print(\"현재 서울의 미세먼지 등급은 좋음입니다.\")',\n    check_city_finedust_exampleDesc:\n        '[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​',\n    get_city_weather_data_desc:\n        '선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.',\n    get_city_weather_data_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"the lowest temperature\" : 최저기온<br>②    \"the highest temperature\" : 최고기온<br>③    \"humidity\" : 습도<br>④    \"precipitation\" : 강수량<br>⑤    \"precipitation probability\" : 강수확률<br>⑥    \"wind speed\" : 풍속%nextB-- 아래 선택지 중 하나<br>①    \"yesterday\" : 어제<br>②    \"today\" : 오늘<br>③    \"tomorrow\" : 내일<br>④    \"After 2 days\" : 모레<br>⑤    \"After 3 days\" : 3일 후<br>⑥    \"After 4 days\" : 4일 후<br>⑦    \"After 5 days\" : 5일 후<br>⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    get_city_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\"today\", \"Seoul\"))',\n    get_city_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​',\n    get_current_city_weather_data_desc: '현재 B지역의 A 날씨 정보값을 의미합니다.',\n    get_current_city_weather_data_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나<br>①    \"temperature\" : 기온<br>②    \"concentration of fine dust\" : 미세먼지농도',\n    get_current_city_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_current_temperature(\"Seoul\"))',\n    get_current_city_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.',\n    get_today_city_temperature_desc: '오늘 A지역의 B 시간대 기온 정보값을 의미합니다.',\n    get_today_city_temperature_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나<br>①    \"00\" : 당일 00시 측정된 기온값<br>②    \"03\" : 당일 03시 측정된 기온값<br>③    \"06\" : 당일 06시 측정된 기온값<br>④    \"09\" : 당일 09시 측정된 기온값<br>⑤    \"12\" : 당일 12시 측정된 기온값<br>⑥    \"15\" : 당일 15시 측정된 기온값<br>⑦    \"18\" : 당일 18시 측정된 기온값<br>⑧    \"21\" : 당일 21시 측정된 기온값',\n    get_today_city_temperature_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_today_city_temperature(\"Seoul\", 00))',\n    get_today_city_temperature_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​',\n};\nLang.Painter = {\n    select_cut: '사각 점선 모양으로 오릴 수 있어요.',\n    thickness_of_eraser: '지우개 굵기',\n    font: '글꼴',\n    font_color: '글꼴 색상',\n    outline_color: '윤곽선 색상',\n    outline_thickness: '윤곽선 굵기',\n    fill_color: '채우기 색상',\n    inversion: '반전',\n    font_size: '글꼴 크기',\n    font_family: '글꼴 스타일',\n    fullscreen: '전체화면',\n    exit_fullscreen: '전체화면 해제',\n    picture_import: '모양 가져오기',\n    edit_way: '편집 방법',\n    line: '직선',\n    vertex: '꼭지점',\n    bitmap: '비트맵',\n    vector: '벡터',\n    forward: '앞으로',\n    backward: '뒤로',\n    front: '맨 앞으로',\n    back: '맨 뒤로',\n    group: '그룹화',\n    ungroup: '그룹 해제',\n    copy_picture: '복사',\n    delete_picture: '삭제',\n    cut_picture: '자르기',\n    paste_picture: '붙여넣기',\n    remove_all: '모두 삭제',\n    new_picture: '새그림',\n    edit: '편집',\n    picture_size: '크기',\n    picture_rotation: '회전',\n    thickness: '굵기',\n    font_fill: '채우기 색상',\n    painter_file_save: '저장하기',\n    painter_file_saveas: '새 모양으로 저장',\n    file: '파일',\n    Pencil: '펜',\n    Line: '직선',\n    Path: '형태',\n    Pan: '이동',\n    Select: '선택',\n    Rectangle: '사각형',\n    Ellipse: '원',\n    Text: '글상자',\n    Fill: '채우기',\n    Eraser: '지우기',\n    get_file: '가져오기',\n    copy_file: '복사하기',\n};\nLang.DataAnalytics = {\n    data_analysis: '데이터분석',\n    create_table: '테이블 만들기',\n    data: '데이터',\n    add_table: '테이블 추가하기',\n    show_chart: '차트 보기',\n    legend: '범례',\n    dashboard: '요약',\n    table: '테이블',\n    chart: '차트',\n    attribute: '열',\n    row: '행',\n    average: '평균',\n    standard_deviation: '표준 편차',\n    maximum: '최댓값',\n    minimum: '최솟값',\n    median: '중간값',\n    average_explain: '해당 열의 모든 값을 더한 후 열의 개수 만큼 나눈 값',\n    standard_deviation_explain:\n        '데이터가 평균을 중심으로 얼마나 퍼져있는지 알려주는 값.\\n0에 가까울 수록 값들이 평균 근처에 집중되어 있다는 것을 의미',\n    maximum_minimum_explain: '해당 열의 가장 큰 값과 가장 작은 값',\n    median_explain: '해당 열의 모든 값을 크기순으로 배열했을 때\\n전체의 중앙에 위치하는 값',\n    add_row_above: '위에 행 추가하기',\n    add_row_below: '아래에 행 추가하기',\n    delete_row: '행 삭제하기',\n    add_property_left: '왼쪽에 열 추가하기',\n    add_property_right: '오른쪽에 열 추가하기',\n    delete_attribute: '열 삭제',\n    data_alert: '숫자가 아닌 값이 포함된 열은 개수만 확인할 수 있습니다.',\n    save: '저장하기',\n    cancel: '취소',\n    confirm: '확인',\n    attribute_count: '개',\n    row_count: '행',\n    cell_count: '개',\n    count: '개수',\n    add_chart_alert: '추가된 차트가 없습니다.\\n차트를 생성해주세요.',\n    enter_attribute_name: '열 이름을 입력해 주세요.(10자 이내)',\n    placeholder_attribute_name: '열 이름',\n    new_attribute: '새로운 열',\n    chart_title: '차트 제목',\n    remove_chart: '차트 삭제하기',\n    add_chart_first: '차트를 먼저 추가해주세요.',\n    bar: '막대',\n    line: '꺾은선',\n    pie: '원형',\n    scatter: '분산형',\n    select_x_axis: '가로축을 선택해주세요.',\n    x_axis: '가로축',\n    y_axis: '세로축',\n    select_y_axis: '세로축을 선택해주세요.',\n    select_y_axis_or_legend: '세로축 혹은 범례를 선택해주세요.',\n    select_legend: '범례를 선택해주세요',\n    cell: '칸',\n    unable_to_express_chart: '차트로 표현할 수 없습니다.',\n    edit_attribute_name: '이름 바꾸기',\n    duplicate_attribute_name_title: '열 이름 변경에 실패하였습니다.',\n    duplicate_attribute_name_content: '같은 이름의 열이 존재합니다.',\n    fail_save_table: '테이블 저장에 실패하였습니다.',\n    duplicate_table_name_content: '같은 이름의 테이블이 존재합니다.',\n    saved_table_title: '저장되었습니다.',\n    saved_table_content: '테이블과 차트의 정보가 저장되었습니다.',\n    empty_table_name_content: '테이블 이름은 빈 칸이 될 수 없습니다',\n    do_not_delete_row: '행을 삭제할 수 없습니다.',\n    rows_cannot_less_one: '테이블에는 한 개 이상의 행이 있어야합니다.',\n};\nLang.SharePolicy = {\n    title: '엔트리 작품/게시물 공유 가이드',\n};\n\nLang.Support = ['ko', 'en', 'vn', 'jp'];\nif (typeof exports == 'object') exports.Lang = Lang;\n"
  },
  {
    "path": "extern/lang/ebs.js",
    "content": "var Lang = {};\nLang.category = {\n    name: 'ko',\n};\nLang.type = 'ko';\nLang.fallbackType = 'ko';\nLang.ko = '한국어';\nLang.en = 'English';\nLang.jp = '日本語';\nLang.vn = 'tiếng Việt';\nLang.Command = {\n    1: '장면 추가하기',\n    2: '장면 삭제하기',\n    3: '장면 이름 수정',\n    4: '장면 순서 변경',\n    5: '장면 선택',\n    101: '블록 쓰레드 추가하기',\n    102: '블록 쓰레드 삭제하기',\n    103: '블록 삭제하기',\n    104: '블록 복구하기',\n    105: '블록 끼워넣기',\n    106: '블록 분리하기',\n    107: '블록 이동하기',\n    108: '블록 복제하기',\n    109: '블록 복제 취소하기',\n    110: '스크롤',\n    111: '블록 필드값 수정',\n    117: '블록 쓰레드 추가하기',\n    118: '블록 끼워넣기',\n    119: '블록 이동하기',\n    120: '블록 분리하기',\n    121: '블록 이동하기',\n    122: '블록 끼워넣기',\n    123: '블록 끼워넣기',\n    201: '오브젝트 선택하기',\n    202: '오브젝트 수정 버튼 클릭',\n    203: '오브젝트 그림 추가',\n    204: '오브젝트 그림 삭제',\n    205: '오브젝트 소리 추가',\n    206: '오브젝트 소리 삭제',\n    207: '오브젝트 이름 수정',\n    208: '오브젝트 추가',\n    209: '오브젝트 삭제',\n    210: '오브젝트 추가 버튼 클릭',\n    211: '오브젝트 x 수정',\n    212: '오브젝트 y 수정',\n    213: '오브젝트 size 수정',\n    214: '오브젝트 방향 수정',\n    215: '오브젝트 이동 방향 수정',\n    216: '오브젝트 회전방식 수정',\n    217: '엔터티 모델 동기화',\n    301: 'do',\n    302: 'undo',\n    303: 'redo',\n    401: '그림 수정하기',\n    402: '그림 수정 취소하기',\n    403: '그림 수정하기',\n    404: '그림 수정 취소하기',\n    405: '글상자 수정',\n    501: '시작하기',\n    502: '정지하기',\n    601: '컨테이너 오브젝트 선택하기',\n    701: '모드 바꾸기',\n    702: '모양 추가 버튼 클릭',\n    703: '소리 추가 버튼 클릭',\n    801: '속성 필터 선택하기',\n    802: '변수 추가하기 버튼 클릭',\n    803: '변수 추가하기',\n    804: '변수 삭제하기',\n    805: '변수 이름 설정',\n    806: '신호 이름 설정',\n    807: '신호 추가',\n    808: '신호 삭제',\n    809: '변수 스코프 정하기',\n    810: '변수 글로벌 체크',\n    811: '변수 보이기 체크',\n    812: '변수 기본값 설정',\n    813: '변수 슬라이드로 체크',\n    814: '변수 최솟값 정하기',\n    815: '변수 최댓값 정하기',\n    816: '리스트 추가 버튼 클릭',\n    817: '리스트 추가',\n    818: '리스트 삭제',\n    819: '리스트 이름 정하기',\n    820: '리스트 스코프 정하기',\n    821: '리스트 글로벌 체크',\n    822: '리스트 보이기 체크',\n    823: '리스트 길이 변경',\n    824: '리스트 기본값 설정',\n    825: '메세지 수정 enable',\n    826: '변수 수정 enable',\n    827: '리스트 수정 enable',\n    828: '변수 이름 정하기',\n    829: '리스트 이름 정하기',\n    900: '모달 닫기',\n    1001: '함수 생성 시작',\n    1002: '함수 수정 시작',\n    1003: '함수 수정 취소',\n    1004: '함수 생성',\n    1005: '함수 업데이트',\n};\nLang.CommandTooltip = {\n    101: '블록 쓰레드 추가하기',\n    102: '블록 쓰레드 삭제하기',\n    103: '블록 삭제하기',\n    104: '블록 복구하기',\n    105: '코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    106: '블록 분리하기',\n    107: '블록 이동하기',\n    108: '블록 복제하기',\n    109: '블록 복제 취소하기',\n    110: '스크롤',\n    111: '블록 필드값 수정@@값을 입력하기 위해 이곳을 클릭합니다.$$선택지를 클릭합니다.$$선택지를 클릭합니다.$$&value&을 입력합니다.$$&value&를 선택합니다.$$키보드 &value&를 누릅니다.',\n    117: '블록 쓰레드 추가하기',\n    118: '블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    119: '블록 가져오기@@빈 곳에 블록을 끌어다 놓습니다.',\n    120: '블록 분리하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.',\n    121: '블록 이동하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.',\n    122: '블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    123: '코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    201: '오브젝트 선택하기',\n    301: 'do',\n    302: 'undo',\n    303: 'redo',\n    401: '그림 수정하기',\n    402: '그림 수정 취소하기',\n    403: '그림 수정하기',\n    404: '그림 수정 취소하기',\n    501: '실행하기@@<b>[시작하기]</b>를 누릅니다.',\n    502: '정지하기@@<b>[정지하기]</b>를 누릅니다.',\n    601: '컨테이너 오브젝트 선택하기',\n    701: '모드 바꾸기',\n    702: '모양 추가하기@@<b>모양추가</b>를 클릭합니다.',\n    703: '소리 추가하기@@<b>소리추가</b>를 클릭합니다.',\n    801: '변수 속성창 필터 선택하기',\n    802: '변수 추가하기@@<b>[변수 추가]</b>를 클릭합니다.',\n    803: '변수 추가하기@@<b>[확인]</b>을 클릭합니다.',\n    804: '변수 삭제하기@@이 버튼을 눌러 변수를 삭제합니다.',\n    805: '변수 이름 설정',\n    1101: '확장 블록 추가하기@@<b>확장 블록 블러오기</b>를 클릭합니다.',\n};\nLang.Blocks = {\n    download_guide: '• 연결 안내 다운로드',\n    dictionary: '사전',\n    ai_utilize: '인공지능',\n    date_yesterday: '어제',\n    date_today: '오늘',\n    date_tomorrow: '내일',\n    date_after_2_days: '모레',\n    date_after_3_days: '3일 후',\n    date_after_4_days: '4일 후',\n    date_after_5_days: '5일 후',\n    date_after_6_days: '6일 후',\n    location_entire: '전체',\n    location_seoul: '서울',\n    location_seoul_jongno_gu: '종로구',\n    location_seoul_jung_gu: '중구',\n    location_seoul_yongsan_gu: '용산구',\n    location_seoul_seongdong_gu: '성동구',\n    location_seoul_gwangjin_gu: '광진구',\n    location_seoul_dongdaemun_gu: '동대문구',\n    location_seoul_jungnang_gu: '중랑구',\n    location_seoul_seongbuk_gu: '성북구',\n    location_seoul_gangbuk_gu: '강북구',\n    location_seoul_dobong_gu: '도봉구',\n    location_seoul_nowon_gu: '노원구',\n    location_seoul_eunpyeong_gu: '은평구',\n    location_seoul_seodaemun_gu: '서대문구',\n    location_seoul_mapo_gu: '마포구',\n    location_seoul_yangcheon_gu: '양천구',\n    location_seoul_gangseo_gu: '강서구',\n    location_seoul_guro_gu: '구로구',\n    location_seoul_geumcheon_gu: '금천구',\n    location_seoul_yeongdeungpo_gu: '영등포구',\n    location_seoul_dongjak_gu: '동작구',\n    location_seoul_gwanak_gu: '관악구',\n    location_seoul_seocho_gu: '서초구',\n    location_seoul_gangnam_gu: '강남구',\n    location_seoul_songpa_gu: '송파구',\n    location_seoul_gangdong_gu: '강동구',\n    location_busan: '부산',\n    location_busan_jung_gu: '중구',\n    location_busan_seo_gu: '서구',\n    location_busan_dong_gu: '동구',\n    location_busan_yeongdo_gu: '영도구',\n    location_busan_busanjin_gu: '부산진구',\n    location_busan_dongnae_gu: '동래구',\n    location_busan_nam_gu: '남구',\n    location_busan_buk_gu: '북구',\n    location_busan_haeundae_gu: '해운대구',\n    location_busan_saha_gu: '사하구',\n    location_busan_geumjeong_gu: '금정구',\n    location_busan_gangseo_gu: '강서구',\n    location_busan_yeonje: '연제구',\n    location_busan_suyeong_gu: '수영구',\n    location_busan_sasang_gu: '사상구',\n    location_busan_gijang: '기장군',\n    location_daegu: '대구',\n    location_daegu_jung_gu: '중구',\n    location_daegu_dong_gu: '동구',\n    location_daegu_seo_gu: '서구',\n    location_daegu_nam_gu: '남구',\n    location_daegu_buk_gu: '북구',\n    location_daegu_suseong_gu: '수성구',\n    location_daegu_dalseo_gu: '달서구',\n    location_daegu_dalseong: '달성군',\n    location_incheon: '인천',\n    location_incheon_jung_gu: '중구',\n    location_incheon_dong_gu: '동구',\n    location_incheon_nam_gu: '남구',\n    location_incheon_yeonsu_gu: '연수구',\n    location_incheon_namdong_gu: '남동구',\n    location_incheon_bupyeong_gu: '부평구',\n    location_incheon_gyeyang_gu: '계양구',\n    location_incheon_seo_gu: '서구',\n    location_incheon_ganghwa: '강화군',\n    location_incheon_ongjin_gun: '옹진군',\n    location_gwangju: '광주',\n    location_gwangju_dong_gu: '동구',\n    location_gwangju_seo_gu: '서구',\n    location_gwangju_nam_gu: '남구',\n    location_gwangju_buk_gu: '북구',\n    location_gwangju_gwangsan_gu: '광산구',\n    location_daejeon: '대전',\n    location_daejeon_dong_gu: '동구',\n    location_daejeon_jung_gu: '중구',\n    location_daejeon_seo_gu: '서구',\n    location_daejeon_yuseong_gu: '유성구',\n    location_daejeon_daedeok_gu: '대덕구',\n    location_ulsan: '울산',\n    location_ulsan_jung_gu: '중구',\n    location_ulsan_nam_gu: '남구',\n    location_ulsan_dong_gu: '동구',\n    location_ulsan_buk_gu: '북구',\n    location_ulsan_ulju: '울주군',\n    location_sejong: '세종',\n    location_gyeonggi: '경기',\n    location_gyeonggi_suwon_si: '수원시',\n    location_gyeonggi_seongnam: '성남시',\n    location_gyeonggi_uijeongbu: '의정부시',\n    location_gyeonggi_anyang_si: '안양시',\n    location_gyeonggi_bucheon_si: '부천시',\n    location_gyeonggi_gwangmyeong_si: '광명시',\n    location_gyeonggi_pyeongtaek_si: '평택시',\n    location_gyeonggi_dongducheon_si: '동두천시',\n    location_gyeonggi_ansan_si: '안산시',\n    location_gyeonggi_goyang_si: '고양시',\n    location_gyeonggi_gwacheon_si: '과천시',\n    location_gyeonggi_guri: '구리시',\n    location_gyeonggi_namyangju_si: '남양주시',\n    location_gyeonggi_osan: '오산시',\n    location_gyeonggi_siheung: '시흥시',\n    location_gyeonggi_gunpo_si: '군포시',\n    location_gyeonggi_uiwang_si: '의왕시',\n    location_gyeonggi_hanam: '하남시',\n    location_gyeonggi_yongin_si: '용인시',\n    location_gyeonggi_paju: '파주시',\n    location_gyeonggi_icheon: '이천시',\n    location_gyeonggi_anseong_si: '안성시',\n    location_gyeonggi_gimpo: '김포시',\n    location_gyeonggi_hwaseong_si: '화성시',\n    location_gyeonggi_gwangju: '광주시',\n    location_gyeonggi_yangju_si: '양주시',\n    location_gyeonggi_pocheon: '포천시',\n    location_gyeonggi_yeoju: '여주시',\n    location_gyeonggi_yeoncheon_gun: '연천군',\n    location_gyeonggi_gapyeong_gun: '가평군',\n    location_gyeonggi_yangpyeong: '양평군',\n    location_gangwon: '강원',\n    location_gangwon_chuncheon: '춘천시',\n    location_gangwon_wonju: '원주시',\n    location_gangwon_gangneung_si: '강릉시',\n    location_gangwon_donghae: '동해시',\n    location_gangwon_taebaek_si: '태백시',\n    location_gangwon_sokcho: '속초시',\n    location_gangwon_samcheok_si: '삼척시',\n    location_gangwon_hongcheon: '홍천군',\n    location_gangwon_hoengseong_gun: '횡성군',\n    location_gangwon_yeongwol_gun: '영월군',\n    location_gangwon_pyeongchang: '평창군',\n    location_gangwon_jeongseon: '정선군',\n    location_gangwon_cheolwon: '철원군',\n    location_gangwon_hwacheon: '화천군',\n    location_gangwon_yanggu: '양구군',\n    location_gangwon_inje: '인제군',\n    location_gangwon_goseong: '고성군',\n    location_gangwon_yangyang: '양양군',\n    location_chungcheongbuk: '충북',\n    location_chungcheongbuk_cheongju: '청주시',\n    location_chungcheongbuk_chungju: '충주시',\n    location_chungcheongbuk_jecheon: '제천시',\n    location_chungcheongbuk_boeun: '보은군',\n    location_chungcheongbuk_okcheon: '옥천군',\n    location_chungcheongbuk_yeongdong: '영동군',\n    location_chungcheongbuk_jeungpyeong: '증평군',\n    location_chungcheongbuk_jincheon: '진천군',\n    location_chungcheongbuk_goesan: '괴산군',\n    location_chungcheongbuk_eumseong: '음성군',\n    location_chungcheongbuk_danyang: '단양군',\n    location_chungcheongnam: '충남',\n    location_chungcheongnam_cheonan: '천안시',\n    location_chungcheongnam_gongju: '공주시',\n    location_chungcheongnam_boryeong: '보령시',\n    location_chungcheongnam_asan: '아산시',\n    location_chungcheongnam_seosan: '서산시',\n    location_chungcheongnam_nonsan: '논산시',\n    location_chungcheongnam_gyeryong: '계룡시',\n    location_chungcheongnam_dangjin: '당진시',\n    location_chungcheongnam_geumsan: '금산군',\n    location_chungcheongnam_buyeo: '부여군',\n    location_chungcheongnam_seocheon: '서천군',\n    location_chungcheongnam_cheongyang: '청양군',\n    location_chungcheongnam_hongseong: '홍성군',\n    location_chungcheongnam_yesan: '예산군',\n    location_chungcheongnam_taean: '태안군',\n    location_jeollabuk: '전북',\n    location_jeollabuk_jeonju: '전주시',\n    location_jeollabuk_gunsan_si: '군산시',\n    location_jeollabuk_iksan: '익산시',\n    location_jeollabuk_jeongeup: '정읍시',\n    location_jeollabuk_namwon: '남원시',\n    location_jeollabuk_gimje_si: '김제시',\n    location_jeollabuk_wanju: '완주군',\n    location_jeollabuk_jinan: '진안군',\n    location_jeollabuk_muju: '무주군',\n    location_jeollabuk_jangsu: '장수군',\n    location_jeollabuk_imsil: '임실군',\n    location_jeollabuk_sunchang: '순창군',\n    location_jeollabuk_gochang: '고창군',\n    location_jeollabuk_buan: '부안군',\n    location_jeollanam: '전남',\n    location_jeollanam_mokpo: '목포시',\n    location_jeollanam_yosu: '여수시',\n    location_jeollanam_suncheon_si: '순천시',\n    location_jeollanam_naju: '나주시',\n    location_jeollanam_gwangyang_si: '광양시',\n    location_jeollanam_damyang: '담양군',\n    location_jeollanam_gokseong: '곡성군',\n    location_jeollanam_gurye: '구례군',\n    location_jeollanam_goheung: '고흥군',\n    location_jeollanam_boseong: '보성군',\n    location_jeollanam_hwasun: '화순군',\n    location_jeollanam_jangheung: '장흥군',\n    location_jeollanam_gangjin: '강진군',\n    location_jeollanam_haenam: '해남군',\n    location_jeollanam_yeongam: '영암군',\n    location_jeollanam_jindo: '무안군',\n    location_jeollanam_muan: '함평군',\n    location_jeollanam_hampyeong: '영광군',\n    location_jeollanam_yeonggwang: '장성군',\n    location_jeollanam_jangseong: '완도군',\n    location_jeollanam_wando: '진도군',\n    location_jeollanam_sinan: '신안군',\n    location_gyeongsangbuk: '경북',\n    location_gyeongsangbuk_pohang_si: '포항시',\n    location_gyeongsangbuk_gyeongju_si: '경주시',\n    location_gyeongsangbuk_gimcheon_si: '김천시',\n    location_gyeongsangbuk_andong_si: '안동시',\n    location_gyeongsangbuk_gumi_si: '구미시',\n    location_gyeongsangbuk_yeongju_si: '영주시',\n    location_gyeongsangbuk_yeongcheon_si: '영천시',\n    location_gyeongsangbuk_sangju_si: '상주시',\n    location_gyeongsangbuk_mungyeong_si: '문경시',\n    location_gyeongsangbuk_gyeongsan_si: '경산시',\n    location_gyeongsangbuk_gunwi: '군위군',\n    location_gyeongsangbuk_uiseong: '의성군',\n    location_gyeongsangbuk_cheongsong: '청송군',\n    location_gyeongsangbuk_goryong: '영양군',\n    location_gyeongsangbuk_yeongdeok: '영덕군',\n    location_gyeongsangbuk_cheongdo: '청도군',\n    location_gyeongsangbuk_golyeong: '고령군',\n    location_gyeongsangbuk_seongju: '성주군',\n    location_gyeongsangbuk_chilgok: '칠곡군',\n    location_gyeongsangbuk_yecheon: '예천군',\n    location_gyeongsangbuk_bonghwa: '봉화군',\n    location_gyeongsangbuk_uljin: '울진군',\n    location_gyeongsangbuk_ulleung: '울릉군',\n    location_gyeongsangnam: '경남',\n    location_gyeongsangnam_changwon_si: '창원시',\n    location_gyeongsangnam_jinju: '진주시',\n    location_gyeongsangnam_tongyeong_si: '통영시',\n    location_gyeongsangnam_sacheon_si: '사천시',\n    location_gyeongsangnam_gimhae_si: '김해시',\n    location_gyeongsangnam_miryang_si: '밀양시',\n    location_gyeongsangnam_geoje_si: '거제시',\n    location_gyeongsangnam_yangsan_si: '양산시',\n    location_gyeongsangnam_uiryeong: '의령군',\n    location_gyeongsangnam_haman: '함안군',\n    location_gyeongsangnam_changnyeong: '창녕군',\n    location_gyeongsangnam_goseong: '고성군',\n    location_gyeongsangnam_namhae: '남해군',\n    location_gyeongsangnam_hadong: '하동군',\n    location_gyeongsangnam_sancheong: '산청군',\n    location_gyeongsangnam_hamyang: '함양군',\n    location_gyeongsangnam_geochang: '거창군',\n    location_gyeongsangnam_hapcheon: '합천군',\n    location_jeju: '제주',\n    location_jeju_jeju_si: '제주시',\n    location_jeju_seogwipo: '서귀포시',\n    EXPANSION_WEATHER_sunny: '맑음',\n    EXPANSION_WEATHER_partly_cloudy: '구름조금',\n    EXPANSION_WEATHER_mostly_cloudy: '구름많음',\n    EXPANSION_WEATHER_cloudy: '흐림',\n    EXPANSION_WEATHER_rainy: '비',\n    EXPANSION_WEATHER_sleet: '진눈깨비',\n    EXPANSION_WEATHER_snowy: '눈',\n    EXPANSION_WEATHER_finedust_good: '좋음',\n    EXPANSION_WEATHER_finedust_normal: '보통',\n    EXPANSION_WEATHER_finedust_bad: '나쁨',\n    EXPANSION_WEATHER_finedust_very_bad: '매우나쁨',\n    EXPANSION_WEATHER_lowest_temperature: '최저기온(℃)',\n    EXPANSION_WEATHER_highest_temperature: '최고기온(℃)',\n    EXPANSION_WEATHER_humidity: '습도(%)',\n    EXPANSION_WEATHER_precipitation: '강수량(mm)',\n    EXPANSION_WEATHER_precipitation_probability: '강수확률(%)',\n    EXPANSION_WEATHER_wind_speed: '풍속(m/s)',\n    EXPANSION_WEATHER_temperature: '기온(℃)',\n    EXPANSION_WEATHER_finedust: '미세먼지농도(㎍)',\n    EXPANSION_FESTIVAL_title: '제목',\n    EXPANSION_FESTIVAL_area: '지역',\n    EXPANSION_FESTIVAL_start_date: '시작일',\n    EXPANSION_FESTIVAL_end_date: '종료일',\n    EXPANSION_FESTIVAL_address: '주소',\n    EXPANSION_FESTIVAL_coordinate: '위치',\n    EXPANSION_FESTIVAL_overview: '개요',\n    EXPANSION_FESTIVAL_homepage: '홈페이지',\n    no_data: '정보없음',\n    no_sentence: '문장이 없습니다',\n    sentence_over_20_charactor: '20자까지만 입력할 수 있습니다.',\n    sentence_over_3000_charactor: '3000자까지만 입력할 수 있습니다.',\n    sentence_over_2500_charactor: '2500자까지만 입력할 수 있습니다. ',\n    unknown_sentence: '알 수 없는 문장입니다.',\n    auto: '자동',\n    korean: '한국어',\n    english: '영어',\n    spanish: '스페인어',\n    french: '프랑스어',\n    german: '독일어',\n    russian: '러시아어',\n    portuguese: '포르투갈어',\n    hindi: '힌디어',\n    japan: '일본어',\n    thai: '태국어',\n    vietnamese: '베트남',\n    indonesian: '인도네시아어',\n    chinese_simplified: '중국어간체',\n    chinese_traditional: '중국어번체',\n    italian: '이탈리아어',\n    behaviorConduct01001: '태풍',\n    behaviorConduct01002: '홍수',\n    behaviorConduct01003: '호우',\n    behaviorConduct01004: '강풍',\n    behaviorConduct01005: '대설',\n    behaviorConduct01006: '한파',\n    behaviorConduct01007: '풍랑',\n    behaviorConduct01008: '황사',\n    behaviorConduct01009: '폭염',\n    behaviorConduct01010: '가뭄',\n    behaviorConduct01011: '지진',\n    behaviorConduct01013: '해일',\n    behaviorConduct01014: '산사태',\n    behaviorConduct03002: '응급처치',\n    behaviorConduct03003: '심폐소생술',\n    behaviorConduct03004: '소화기사용법',\n    behaviorConduct03016: '소화전사용법',\n    behaviorConduct03005: '식중독',\n    behaviorConduct03006: '산행안전',\n    behaviorConduct03008: '실종유괴',\n    behaviorConduct03009: '성폭력',\n    behaviorConduct03010: '학교 폭력',\n    behaviorConduct03011: '가정 폭력',\n    behaviorConduct03012: '억류 및 납치',\n    behaviorConduct03013: '교통사고',\n    behaviorConduct03014: '승강기 안전사고',\n    behaviorConduct03015: '미세먼지',\n    behaviorConduct01001001: '태풍이 오기 전',\n    behaviorConduct01001002: '태풍이 왔을 때',\n    behaviorConduct01001003: '태풍이 지나간 후',\n    behaviorConduct01002002: '홍수가 오기 전',\n    behaviorConduct01002003: '홍수가 났을 때',\n    behaviorConduct01002004: '홍수가 지나간 후',\n    behaviorConduct01003002: '큰 비가 오기 전',\n    behaviorConduct01003003: '큰 비가 내릴 때',\n    behaviorConduct01003004: '큰 비가 그친 후',\n    behaviorConduct01004001: '강풍이 오기 전',\n    behaviorConduct01004002: '강풍 발생 시',\n    behaviorConduct01005002: '대설이 오기 전',\n    behaviorConduct01005003: '대설 내일 때',\n    behaviorConduct01005004: '눈이 그친 후',\n    behaviorConduct01006001: '한파가 오기 전',\n    behaviorConduct01006002: '한파 왔을 때',\n    behaviorConduct01007001: '풍랑이 험할 때',\n    behaviorConduct01007002: '풍랑이 오기 전',\n    behaviorConduct01008001: '황사가 오기 전',\n    behaviorConduct01008002: '황사가 왔을 때',\n    behaviorConduct01008003: '황사가 지나간 후',\n    behaviorConduct01009001: '폭염이 오기 전',\n    behaviorConduct01009002: '폭염이 왔을 때',\n    behaviorConduct01010001: '가뭄이 왔을 때',\n    behaviorConduct01011009: '지진이 오기 전',\n    behaviorConduct01011010: '지진이 왔을 때',\n    behaviorConduct01011012: '지진 대피 후',\n    behaviorConduct01013002: '해일이 오기 전',\n    behaviorConduct01013003: '해일이 왔을 때',\n    behaviorConduct01014001: '산사태가 오기 전',\n    behaviorConduct03002002: '화상 처치',\n    behaviorConduct03002003: '고열 예방',\n    behaviorConduct03002004: '뱀에 물렸을 때 처치',\n    behaviorConduct03002005: '벌에 쏘였을 때 처치',\n    behaviorConduct03002006: '과호흡증후군 응급처치',\n    behaviorConduct03003001: '성인 심폐소생술',\n    behaviorConduct03003002: '영유아 심폐소생술',\n    behaviorConduct03003003: '자동제세동기 사용',\n    behaviorConduct03004001: '분말소화기 사용',\n    behaviorConduct03016001: '옥내소화전 사용',\n    behaviorConduct03005001: '식중독 대처',\n    behaviorConduct03006004: '산행 중 유의사항',\n    behaviorConduct03006005: '산에서 안전한 캠핑',\n    behaviorConduct03006002: '구조요청시 알리는',\n    behaviorConduct03006003: '산행사고시 응급조치',\n    behaviorConduct03008001: '실종유괴 예방',\n    behaviorConduct03009001: '성폭력 예방',\n    behaviorConduct03010001: '학교 폭력 예방',\n    behaviorConduct03011001: '가정 폭력 예방',\n    behaviorConduct03012001: '억류 및 납치 시 대처',\n    behaviorConduct03013002: '교통사고 발생 시 대처',\n    behaviorConduct03013005: '차량에서의 구조',\n    behaviorConduct03014001: '승강기 안전 이용',\n    behaviorConduct03014003: '승강기 고장시 대처',\n    behaviorConduct03014004: '에스컬레이터 안전 이용',\n    behaviorConduct03015007: '미세먼지 많은 날 생활',\n    behaviorConduct03015003: '부문별 생활',\n    tts_female: '여성',\n    tts_male: '남성',\n    tts_kind: '친절한',\n    tts_sweet: '감미로운',\n    tts_echo: '울리는',\n    tts_mischievous: '장난스러운',\n    tts_dainty: '앙증맞은',\n    tts_veryslow: '매우 느린',\n    tts_slow: '느린',\n    tts_normal: '보통',\n    tts_fast: '빠른',\n    tts_veryfast: '매우 빠른',\n    tts_verylow: '매우 낮은',\n    tts_low: '낮은',\n    tts_high: '높은',\n    tts_veryhigh: '매우 높은',\n    ARDUINO: '하드웨어',\n    ARDUINO_download_connector: '• 연결 프로그램 다운로드',\n    ARDUINO_open_connector: '연결 프로그램 열기',\n    ARDUINO_download_source: '• 엔트리 아두이노 소스',\n    ARDUINO_reconnect: '하드웨어 연결하기',\n    arduino_noti_text: '모바일 기기는 추후 지원 합니다.',\n    arduino_lite_reconnect: '하드웨어 다시 연결',\n    arduino_lite_download_firmware: '펌웨어 다운로드',\n    arduino_lite_download_driver: '드라이버 다운로드',\n    arduino_lite_connect: '브라우저로 연결하기',\n    arduino_lite_disconnect: '하드웨어 선택 취소',\n    arduino_lite_guide: '• 아두이노 연결 가이드',\n    ROBOT_reconnect: '로봇 연결하기',\n    ARDUINO_program: '프로그램 실행하기',\n    ARDUINO_cloud_pc_connector: '클라우드 PC 연결하기',\n    ARDUINO_connected: '하드웨어가 연결되었습니다. ',\n    ARDUINO_connect: '* 하드웨어를 연결하세요.',\n    ARDUINO_arduino_get_number_1: '신호',\n    ARDUINO_arduino_get_number_2: '의 숫자 결괏값',\n    ARDUINO_arduino_get_sensor_number_0: 'A0',\n    ARDUINO_arduino_get_sensor_number_1: 'A1',\n    ARDUINO_arduino_get_sensor_number_2: 'A2',\n    ARDUINO_arduino_get_sensor_number_3: 'A3',\n    ARDUINO_arduino_get_sensor_number_4: 'A4',\n    ARDUINO_arduino_get_sensor_number_5: 'A5',\n    blacksmith_toggle_on: '켜기',\n    blacksmith_toggle_off: '끄기',\n    blacksmith_lcd_first_line: '첫 번째',\n    blacksmith_lcd_seconds_line: '두 번째',\n    BITBRICK_light: '밝기 센서',\n    BITBRICK_IR: '적외선 센서',\n    BITBRICK_touch: '버튼',\n    BITBRICK_potentiometer: '가변저항',\n    BITBRICK_MIC: '소리 센서',\n    BITBRICK_UserSensor: '사용자 입력',\n    BITBRICK_UserInput: '사용자 입력',\n    BITBRICK_dc_direction_ccw: '반시계',\n    BITBRICK_dc_direction_cw: '시계',\n    chocopi_control_event_pressed: '누를 때',\n    chocopi_control_event_released: '뗄 때',\n    chocopi_joystick_X: '조이스틱 좌우',\n    chocopi_joystick_Y: '조이스틱 상하',\n    chocopi_motion_photogate_event_blocked: '막았을 때',\n    chocopi_motion_photogate_event_unblocked: '열었을 때',\n    chocopi_motion_photogate_time_blocked: '막은 시간',\n    chocopi_motion_photogate_time_unblocked: '연 시간',\n    chocopi_port: '포트',\n    chocopi_pot: '볼륨',\n    chocopi_touch_event_touch: '만질 때',\n    chocopi_touch_event_untouch: '뗄 때',\n    CODEino_get_sensor_number_0: '0',\n    CODEino_get_sensor_number_1: '1',\n    CODEino_get_sensor_number_2: '2',\n    CODEino_get_sensor_number_3: '3',\n    CODEino_get_sensor_number_4: '4',\n    CODEino_get_sensor_number_5: '5',\n    CODEino_get_sensor_number_6: '6',\n    CODEino_sensor_name_0: '소리',\n    CODEino_sensor_name_1: '빛',\n    CODEino_sensor_name_2: '슬라이더',\n    CODEino_sensor_name_3: '저항-A',\n    CODEino_sensor_name_4: '저항-B',\n    CODEino_sensor_name_5: '저항-C',\n    CODEino_sensor_name_6: '저항-D',\n    CODEino_string_1: ' 센서값 ',\n    CODEino_string_2: ' 보드의 ',\n    CODEino_string_3: '버튼누름',\n    CODEino_string_4: 'A 연결됨',\n    CODEino_string_5: 'B 연결됨',\n    CODEino_string_6: 'C 연결됨',\n    CODEino_string_7: 'D 연결됨',\n    CODEino_string_8: ' 3축 가속도센서 ',\n    CODEino_string_9: '축의 센서값 ',\n    CODEino_string_10: '소리센서 ',\n    CODEino_string_11: '소리큼',\n    CODEino_string_12: '소리작음',\n    CODEino_string_13: '빛센서 ',\n    CODEino_string_14: '밝음',\n    CODEino_string_15: '어두움',\n    CODEino_string_16: '왼쪽 기울임',\n    CODEino_string_17: '오른쪽 기울임',\n    CODEino_string_18: '위쪽 기울임',\n    CODEino_string_19: '아래쪽 기울임',\n    CODEino_string_20: '뒤집힘',\n    CODEino_accelerometer_X: 'X',\n    CODEino_accelerometer_Y: 'Y',\n    CODEino_accelerometer_Z: 'Z',\n    CODEino_led_red: '빨강',\n    CODEino_led_green: '초록',\n    CODEino_led_blue: '파랑',\n    iboard_analog_number_0: 'A0',\n    iboard_analog_number_1: 'A1',\n    iboard_analog_number_2: 'A2',\n    iboard_analog_number_3: 'A3',\n    iboard_analog_number_4: 'A4',\n    iboard_analog_number_5: 'A5',\n    iboard_light: '빛센서가 ',\n    iboard_num_pin_1: 'LED 상태를',\n    iboard_num_pin_2: '번 스위치가',\n    iboard_num_pin_3: '아날로그',\n    iboard_num_pin_4: '번 ',\n    iboard_num_pin_5: '센서값',\n    iboard_string_1: '켜짐',\n    iboard_string_2: '꺼짐',\n    iboard_string_3: '밝음',\n    iboard_string_4: '어두움',\n    iboard_string_5: '눌림',\n    iboard_string_6: '열림',\n    iboard_switch: '스위치 ',\n    iboard_tilt: '기울기센서 상태가',\n    dplay_switch: '스위치 ',\n    dplay_light: '빛센서가 ',\n    dplay_tilt: '기울기센서 상태가',\n    dplay_string_1: '켜짐',\n    dplay_string_2: '꺼짐',\n    dplay_string_3: '밝음',\n    dplay_string_4: '어두움',\n    dplay_string_5: '눌림',\n    dplay_string_6: '열림',\n    dplay_num_pin_1: 'LED 상태를',\n    dplay_num_pin_2: '번 스위치가',\n    dplay_num_pin_3: '아날로그',\n    dplay_num_pin_4: '번 ',\n    dplay_num_pin_5: '센서값',\n    dplay_analog_number_0: 'A0',\n    dplay_analog_number_1: 'A1',\n    dplay_analog_number_2: 'A2',\n    dplay_analog_number_3: 'A3',\n    dplay_analog_number_4: 'A4',\n    dplay_analog_number_5: 'A5',\n    ARDUINO_arduino_get_string_1: '신호',\n    ARDUINO_arduino_get_string_2: '의 글자 결괏값',\n    ARDUINO_arduino_send_1: '신호',\n    ARDUINO_arduino_send_2: '보내기',\n    ARDUINO_num_sensor_value_1: '',\n    ARDUINO_num_sensor_value_2: '번 센서값',\n    ARDUINO_get_digital_value_1: '',\n    ARDUINO_num_pin_1: '',\n    ARDUINO_num_pin_2: '번 LED',\n    ARDUINO_toggle_pwm_1: '',\n    ARDUINO_toggle_pwm_2: '번 Pin',\n    ARDUINO_toggle_pwm_3: '',\n    ARDUINO_on: '켜기',\n    ARDUINO_convert_scale_1: '',\n    ARDUINO_convert_scale_2: '값의 범위를',\n    ARDUINO_convert_scale_3: '~',\n    ARDUINO_convert_scale_4: '에서',\n    ARDUINO_convert_scale_5: '~',\n    ARDUINO_convert_scale_6: '(으)로 바꾼값',\n    ARDUINO_off: '끄기',\n    EXPANSION: '확장',\n    brightness: '밝기',\n    BRUSH: '붓',\n    BRUSH_brush_erase_all: '모든 붓 지우기',\n    BRUSH_change_opacity_1: '붓의 투명도를',\n    BRUSH_change_opacity_2: '% 만큼 바꾸기',\n    BRUSH_change_thickness_1: '붓의 굵기를',\n    BRUSH_change_thickness_2: '만큼 바꾸기',\n    BRUSH_set_color_1: '붓의 색을',\n    BRUSH_set_color_2: '(으)로 정하기',\n    BRUSH_set_opacity_1: '붓의 투명도를',\n    BRUSH_set_opacity_2: '% 로 정하기',\n    BRUSH_set_random_color: '붓의 색을 무작위로 정하기',\n    BRUSH_set_thickness_1: '붓의 굵기를',\n    BRUSH_set_thickness_2: '로 정하기',\n    BRUSH_stamp: '도장 찍기',\n    BRUSH_start_drawing: '그리기 시작하기',\n    BRUSH_stop_drawing: '그리기 멈추기',\n    CALC: '계산',\n    CALC_calc_mod_1: '',\n    CALC_calc_mod_2: '/',\n    CALC_calc_mod_3: '의 나머지',\n    CALC_calc_operation_of_1: '',\n    CALC_calc_operation_of_2: '의',\n    CALC_calc_operation_root: '루트',\n    CALC_calc_operation_square: '제곱',\n    CALC_calc_rand_1: '',\n    CALC_calc_rand_2: '부터',\n    CALC_calc_rand_3: '사이에서의 무작위 수',\n    CALC_calc_share_1: '',\n    CALC_calc_share_2: '/',\n    CALC_calc_share_3: '의 몫',\n    CALC_coordinate_mouse_1: '마우스',\n    CALC_coordinate_mouse_2: '좌표',\n    CALC_coordinate_object_1: '',\n    CALC_coordinate_object_2: '의',\n    CALC_coordinate_object_3: '',\n    CALC_distance_something_1: '',\n    CALC_distance_something_2: '까지의 거리',\n    CALC_get_angle: '각도값',\n    CALC_get_date_1: ' 현재',\n    CALC_get_date_2: '',\n    CALC_get_date_day: '일',\n    CALC_get_date_hour: '시각(시)',\n    CALC_get_date_minute: '시각(분)',\n    CALC_get_date_month: '월',\n    CALC_get_date_second: '시각(초)',\n    CALC_get_date_day_of_week: '요일',\n    CALC_get_date_year: '연도',\n    CALC_get_sound_duration_1: '',\n    CALC_get_sound_duration_2: '소리의 길이',\n    CALC_get_timer_value: ' 초시계 값',\n    CALC_get_x_coordinate: 'X 좌푯값',\n    CALC_get_y_coordinate: 'Y 좌푯값',\n    CALC_timer_reset: '초시계 초기화',\n    CALC_timer_visible_1: '초시계',\n    CALC_timer_visible_2: '',\n    CALC_timer_visible_show: '보이기',\n    CALC_timer_visible_hide: '숨기기',\n    color: '색깔',\n    FLOW: '흐름',\n    FLOW__if_1: '만일',\n    FLOW__if_2: '이라면',\n    FLOW_create_clone_1: '',\n    FLOW_create_clone_2: '의 복제본 만들기',\n    FLOW_delete_clone: '이 복제본 삭제하기',\n    FLOW_delete_clone_all: '모든 복제본 삭제하기',\n    FLOW_if_else_1: '만일',\n    FLOW_if_else_2: '이라면',\n    FLOW_if_else_3: '아니면',\n    FLOW_repeat_basic_1: '',\n    FLOW_repeat_basic_2: '번 반복하기',\n    FLOW_repeat_basic_errorMsg: '반복 횟수는 0보다 같거나 커야 합니다.',\n    FLOW_repeat_inf: '무한 반복하기',\n    FLOW_restart: '처음부터 다시 실행하기',\n    FLOW_stop_object_1: '',\n    FLOW_stop_object_2: '멈추기',\n    FLOW_stop_object_all: '모두',\n    FLOW_stop_object_this_object: '자신',\n    FLOW_stop_object_this_thread: '이',\n    FLOW_stop_object_other_thread: '자신의 다른',\n    FLOW_stop_object_other_objects: '다른 오브젝트의',\n    FLOW_stop_repeat: '반복 중단하기',\n    FLOW_stop_run: '프로그램 끝내기',\n    FLOW_wait_second_1: '',\n    FLOW_wait_second_2: '초 기다리기',\n    FLOW_wait_until_true_1: '',\n    FLOW_wait_until_true_2: '이 될 때까지 기다리기',\n    FLOW_when_clone_start: '복제본이 처음 생성되었을때',\n    FUNC: '함수',\n    ANALYSIS: '데이터분석',\n    AI: '인공지능',\n    JUDGEMENT: '판단',\n    JUDGEMENT_boolean_and: '그리고',\n    JUDGEMENT_boolean_not_1: '',\n    JUDGEMENT_boolean_not_2: '(이)가 아니다',\n    JUDGEMENT_boolean_or: '또는',\n    JUDGEMENT_false: ' 거짓 ',\n    JUDGEMENT_is_clicked: '마우스를 클릭했는가?',\n    JUDGEMENT_is_object_clicked: '오브젝트를 클릭했는가?',\n    JUDGEMENT_is_press_some_key_1: '',\n    JUDGEMENT_is_press_some_key_2: '키가 눌러져 있는가?',\n    JUDGEMENT_reach_something_1: '',\n    JUDGEMENT_reach_something_2: '에 닿았는가?',\n    JUDGEMENT_is_type_1: '(이)가',\n    JUDGEMENT_is_type_2: '인가?',\n    is_type_number: '숫자',\n    JUDGEMENT_true: ' 참 ',\n    LOOKS: '생김새',\n    LOOKS_change_scale_percent_1: '크기를',\n    LOOKS_change_scale_percent_2: '만큼 바꾸기',\n    LOOKS_change_to_next_shape: '다음 모양으로 바꾸기',\n    LOOKS_change_to_nth_shape_1: '',\n    LOOKS_change_to_nth_shape_2: '모양으로 바꾸기',\n    LOOKS_change_shape_prev: '이전',\n    LOOKS_change_shape_next: '다음',\n    LOOKS_change_to_near_shape_1: '',\n    LOOKS_change_to_near_shape_2: '모양으로 바꾸기',\n    LOOKS_dialog_1: '',\n    LOOKS_dialog_2: '을(를)',\n    LOOKS_dialog_3: '',\n    LOOKS_dialog_time_1: '',\n    LOOKS_dialog_time_2: '을(를)',\n    LOOKS_dialog_time_3: '초 동안',\n    LOOKS_dialog_time_4: '',\n    LOOKS_erase_all_effects: '효과 모두 지우기',\n    LOOKS_flip_x: '상하 모양 뒤집기',\n    LOOKS_flip_y: '좌우 모양 뒤집기',\n    LOOKS_hide: '모양 숨기기',\n    LOOKS_remove_dialog: '말하기 지우기',\n    LOOKS_set_effect_1: '',\n    LOOKS_set_effect_2: '효과를',\n    LOOKS_set_effect_3: '로 정하기',\n    LOOKS_set_effect_volume_1: '',\n    LOOKS_set_effect_volume_2: '효과를',\n    LOOKS_set_effect_volume_3: '만큼 주기',\n    LOOKS_set_object_order_1: '',\n    LOOKS_set_object_order_2: '번째로 올라오기',\n    LOOKS_set_scale_percent_1: '크기를',\n    LOOKS_set_scale_percent_2: ' 로 정하기',\n    LOOKS_show: '모양 보이기',\n    mouse_pointer: '마우스포인터',\n    MOVING: '움직임',\n    MOVING_bounce_wall: '화면 끝에 닿으면 튕기기',\n    MOVING_bounce_when_1: '',\n    MOVING_bounce_when_2: '에 닿으면 튕기기',\n    MOVING_flip_arrow_horizontal: '화살표 방향 좌우 뒤집기',\n    MOVING_flip_arrow_vertical: '화살표 방향 상하 뒤집기',\n    MOVING_locate_1: '',\n    MOVING_locate_2: '위치로 이동하기',\n    MOVING_locate_time_1: '',\n    MOVING_locate_time_2: '초 동안',\n    MOVING_locate_time_3: '위치로 이동하기',\n    MOVING_locate_x_1: 'x:',\n    MOVING_locate_x_2: '위치로 이동하기',\n    MOVING_locate_xy_1: 'x:',\n    MOVING_locate_xy_2: 'y:',\n    MOVING_locate_xy_3: '위치로 이동하기',\n    MOVING_locate_xy_time_1: '',\n    MOVING_locate_xy_time_2: '초 동안 x:',\n    MOVING_locate_xy_time_3: 'y:',\n    MOVING_locate_xy_time_4: '위치로 이동하기',\n    MOVING_locate_y_1: 'y:',\n    MOVING_locate_y_2: '위치로 이동하기',\n    MOVING_move_direction_1: '이동 방향으로',\n    MOVING_move_direction_2: '만큼 움직이기',\n    MOVING_move_direction_angle_1: '',\n    MOVING_move_direction_angle_2: '방향으로',\n    MOVING_move_direction_angle_3: '만큼 움직이기',\n    MOVING_move_x_1: 'x 좌표를',\n    MOVING_move_x_2: '만큼 바꾸기',\n    MOVING_move_xy_time_1: '',\n    MOVING_move_xy_time_2: '초 동안 x:',\n    MOVING_move_xy_time_3: 'y:',\n    MOVING_move_xy_time_4: '만큼 움직이기',\n    MOVING_move_y_1: 'y 좌표를',\n    MOVING_move_y_2: '만큼 바꾸기',\n    MOVING_rotate_by_angle_1: '오브젝트를',\n    MOVING_rotate_by_angle_2: '만큼 회전하기',\n    MOVING_rotate_by_angle_dropdown_1: '',\n    MOVING_rotate_by_angle_dropdown_2: '만큼 회전하기',\n    MOVING_rotate_by_angle_time_1: '오브젝트를',\n    MOVING_rotate_by_angle_time_2: '초 동안',\n    MOVING_rotate_by_angle_time_3: '만큼 회전하기',\n    MOVING_rotate_direction_1: '이동 방향을',\n    MOVING_rotate_direction_2: '만큼 회전하기',\n    MOVING_see_angle_1: '이동 방향을',\n    MOVING_see_angle_2: '(으)로 정하기',\n    MOVING_see_angle_direction_1: '오브젝트를',\n    MOVING_see_angle_direction_2: '(으)로 정하기',\n    MOVING_see_angle_object_1: '',\n    MOVING_see_angle_object_2: '쪽 바라보기',\n    MOVING_see_direction_1: '',\n    MOVING_see_direction_2: '쪽 보기',\n    MOVING_set_direction_by_angle_1: '방향을',\n    MOVING_set_direction_by_angle_2: '(으)로 정하기',\n    MOVING_add_direction_by_angle_1: '방향을',\n    MOVING_add_direction_by_angle_2: '만큼 회전하기',\n    MOVING_add_direction_by_angle_time_1: '방향을',\n    MOVING_add_direction_by_angle_time_2: '초 동안',\n    MOVING_add_direction_by_angle_time_3: '만큼 회전하기',\n    no_target: '대상 없음',\n    oneself: '자신',\n    opacity: '투명도',\n    SCENE: '장면',\n    SOUND: '소리',\n    SOUND_sound_silent_all: '모든 소리 멈추기',\n    SOUND_sound_something_1: '소리',\n    SOUND_sound_something_2: '재생하기',\n    SOUND_sound_something_second_1: '소리',\n    SOUND_sound_something_second_2: '',\n    SOUND_sound_something_second_3: '초 재생하기',\n    SOUND_sound_something_second_wait_1: '소리',\n    SOUND_sound_something_second_wait_2: '',\n    SOUND_sound_something_second_wait_3: '초 재생하고 기다리기',\n    SOUND_sound_something_wait_1: '소리',\n    SOUND_sound_something_wait_2: '재생하고 기다리기',\n    SOUND_sound_volume_change_1: '소리 크기를',\n    SOUND_sound_volume_change_2: '% 만큼 바꾸기',\n    SOUND_sound_volume_set_1: '소리 크기를',\n    SOUND_sound_volume_set_2: '% 로 정하기',\n    speak: '말하기',\n    think: '생각하기',\n    START: '시작',\n    START_add_message: '신호 추가하기',\n    START_delete_message: '신호 삭제하기',\n    START_message_cast: '신호 보내기',\n    START_message_cast_1: '',\n    START_message_cast_2: '신호 보내기',\n    START_message_cast_wait: '신호 보내고 기다리기',\n    START_message_send_wait_1: '',\n    START_message_send_wait_2: '신호 보내고 기다리기',\n    START_mouse_click_cancled: '마우스 클릭을 해제했을 때',\n    START_mouse_clicked: '마우스를 클릭했을 때',\n    START_press_some_key_1: '',\n    START_press_some_key_2: '키를 눌렀을 때',\n    START_press_some_key_down: '아래쪽 화살표',\n    START_press_some_key_enter: '엔터',\n    START_press_some_key_left: '왼쪽 화살표',\n    START_press_some_key_right: '오른쪽 화살표',\n    START_press_some_key_space: '스페이스',\n    START_press_some_key_up: '위쪽 화살표',\n    START_when_message_cast: '신호를 받았을 때',\n    START_when_message_cast_1: '',\n    START_when_message_cast_2: '신호를 받았을 때',\n    START_when_object_click: '오브젝트를 클릭했을 때',\n    START_when_object_click_canceled: '오브젝트 클릭을 해제했을 때',\n    START_when_run_button_click: '시작하기 버튼을 클릭했을 때',\n    START_when_scene_start: '장면이 시작했을때',\n    START_when_some_key_click: '키를 눌렀을 때',\n    TEXT: '글상자',\n    TEXT_text: '엔트리',\n    TEXT_text_append_1: '',\n    TEXT_text_append_2: '라고 뒤에 이어쓰기',\n    TEXT_text_flush: '텍스트 모두 지우기',\n    TEXT_text_prepend_1: '',\n    TEXT_text_prepend_2: '라고 앞에 추가하기',\n    TEXT_text_write_1: '',\n    TEXT_text_write_2: '라고 글쓰기',\n    VARIABLE: '변수',\n    VARIABLE_add_value_to_list: '',\n    VARIABLE_add_value_to_list_1: '',\n    VARIABLE_add_value_to_list_2: '항목을',\n    VARIABLE_add_value_to_list_3: '에 추가하기',\n    VARIABLE_ask_and_wait_1: '',\n    VARIABLE_ask_and_wait_2: '을(를) 묻고 기다리기',\n    VARIABLE_change_value_list_index: '',\n    VARIABLE_change_value_list_index_1: '',\n    VARIABLE_change_value_list_index_3: '번째 항목을',\n    VARIABLE_change_value_list_index_2: '',\n    VARIABLE_change_value_list_index_4: '(으)로 바꾸기',\n    VARIABLE_change_variable: '변수 더하기',\n    VARIABLE_change_variable_1: '',\n    VARIABLE_change_variable_2: '에',\n    VARIABLE_change_variable_3: '만큼 더하기',\n    VARIABLE_change_variable_name: '변수 이름 바꾸기',\n    VARIABLE_combine_something_1: '',\n    VARIABLE_combine_something_2: '과(와)',\n    VARIABLE_combine_something_3: '결합하기',\n    VARIABLE_get_canvas_input_value: ' 대답 ',\n    VARIABLE_get_variable: '변수',\n    VARIABLE_get_variable_1: '값',\n    VARIABLE_get_variable_2: '값',\n    VARIABLE_get_y: 'Y 좌푯값',\n    VARIABLE_hide_list: '',\n    VARIABLE_hide_list_1: '리스트',\n    VARIABLE_hide_list_2: '숨기기',\n    VARIABLE_hide_variable: '변수값 숨기기',\n    VARIABLE_hide_variable_1: '',\n    VARIABLE_hide_variable_2: '숨기기',\n    VARIABLE_insert_value_to_list: '',\n    VARIABLE_insert_value_to_list_1: '',\n    VARIABLE_insert_value_to_list_2: '을(를)',\n    VARIABLE_insert_value_to_list_3: '의',\n    VARIABLE_insert_value_to_list_4: '번째에 넣기',\n    VARIABLE_length_of_list: '',\n    VARIABLE_length_of_list_1: '',\n    VARIABLE_length_of_list_2: '의 길이',\n    VARIABLE_list: '리스트',\n    VARIABLE_make_variable: '변수 만들기',\n    VARIABLE_list_option_first: '첫번째',\n    VARIABLE_list_option_last: '마지막',\n    VARIABLE_list_option_random: '무작위',\n    VARIABLE_remove_value_from_list: '',\n    VARIABLE_remove_value_from_list_1: '',\n    VARIABLE_remove_value_from_list_2: '번째 항목을',\n    VARIABLE_remove_value_from_list_3: '에서 삭제하기',\n    VARIABLE_remove_variable: '변수 삭제',\n    VARIABLE_set_variable: '변수 정하기',\n    VARIABLE_set_variable_1: '',\n    VARIABLE_set_variable_2: '를',\n    VARIABLE_set_variable_3: '로 정하기',\n    VARIABLE_show_list: '',\n    VARIABLE_show_list_1: '리스트',\n    VARIABLE_show_list_2: '보이기',\n    VARIABLE_show_variable: '변수값 보이기',\n    VARIABLE_show_variable_1: '',\n    VARIABLE_show_variable_2: '보이기',\n    VARIABLE_value_of_index_from_list: '',\n    VARIABLE_value_of_index_from_list_1: '',\n    VARIABLE_value_of_index_from_list_2: '의',\n    VARIABLE_value_of_index_from_list_3: '번째 항목',\n    HAMSTER_hand_found: '손 찾음?',\n    HAMSTER_sensor_left_proximity: '왼쪽 근접 센서',\n    HAMSTER_sensor_right_proximity: '오른쪽 근접 센서',\n    HAMSTER_sensor_left_floor: '왼쪽 바닥 센서',\n    HAMSTER_sensor_right_floor: '오른쪽 바닥 센서',\n    HAMSTER_sensor_acceleration_x: 'x축 가속도',\n    HAMSTER_sensor_acceleration_y: 'y축 가속도',\n    HAMSTER_sensor_acceleration_z: 'z축 가속도',\n    HAMSTER_sensor_light: '밝기',\n    HAMSTER_sensor_temperature: '온도',\n    HAMSTER_sensor_signal_strength: '신호 세기',\n    HAMSTER_sensor_input_a: '입력 A',\n    HAMSTER_sensor_input_b: '입력 B',\n    HAMSTER_move_forward_once: '말판 앞으로 한 칸 이동하기',\n    HAMSTER_turn_once_1: '말판',\n    HAMSTER_turn_once_2: '으로 한 번 돌기',\n    HAMSTER_turn_once_left: '왼쪽',\n    HAMSTER_turn_right: '오른쪽',\n    HAMSTER_move_forward: '앞으로 이동하기',\n    HAMSTER_move_backward: '뒤로 이동하기',\n    HAMSTER_turn_around_1: '',\n    HAMSTER_turn_around_2: '으로 돌기',\n    HAMSTER_move_forward_for_secs_1: '앞으로',\n    HAMSTER_move_forward_for_secs_2: '초 이동하기',\n    HAMSTER_move_backward_for_secs_1: '뒤로',\n    HAMSTER_move_backward_for_secs_2: '초 이동하기',\n    HAMSTER_turn_for_secs_1: '',\n    HAMSTER_turn_for_secs_2: '으로',\n    HAMSTER_turn_for_secs_3: '초 돌기',\n    HAMSTER_change_both_wheels_by_1: '왼쪽 바퀴',\n    HAMSTER_change_both_wheels_by_2: '오른쪽 바퀴',\n    HAMSTER_change_both_wheels_by_3: '만큼 바꾸기',\n    HAMSTER_set_both_wheels_to_1: '왼쪽 바퀴',\n    HAMSTER_set_both_wheels_to_2: '오른쪽 바퀴',\n    HAMSTER_set_both_wheels_to_3: '(으)로 정하기',\n    HAMSTER_change_wheel_by_1: '',\n    HAMSTER_change_wheel_by_2: '바퀴',\n    HAMSTER_change_wheel_by_3: '만큼 바꾸기',\n    HAMSTER_left_wheel: '왼쪽',\n    HAMSTER_right_wheel: '오른쪽',\n    HAMSTER_both_wheels: '양쪽',\n    HAMSTER_set_wheel_to_1: '',\n    HAMSTER_set_wheel_to_2: '바퀴',\n    HAMSTER_set_wheel_to_3: '(으)로 정하기',\n    HAMSTER_follow_line_using_1: '',\n    HAMSTER_follow_line_using_2: '선을',\n    HAMSTER_follow_line_using_3: '바닥 센서로 따라가기',\n    HAMSTER_left_floor_sensor: '왼쪽',\n    HAMSTER_right_floor_sensor: '오른쪽',\n    HAMSTER_both_floor_sensors: '양쪽',\n    HAMSTER_follow_line_until_1: '',\n    HAMSTER_follow_line_until_2: '선을 따라',\n    HAMSTER_follow_line_until_3: '교차로까지 이동하기',\n    HAMSTER_left_intersection: '왼쪽',\n    HAMSTER_right_intersection: '오른쪽',\n    HAMSTER_front_intersection: '앞쪽',\n    HAMSTER_rear_intersection: '뒤쪽',\n    HAMSTER_set_following_speed_to_1: '선 따라가기 속도를',\n    HAMSTER_set_following_speed_to_2: '(으)로 정하기',\n    HAMSTER_front: '앞쪽',\n    HAMSTER_rear: '뒤쪽',\n    HAMSTER_stop: '정지하기',\n    HAMSTER_set_led_to_1: '',\n    HAMSTER_set_led_to_2: 'LED를',\n    HAMSTER_set_led_to_3: '으로 정하기',\n    HAMSTER_left_led: '왼쪽',\n    HAMSTER_right_led: '오른쪽',\n    HAMSTER_both_leds: '양쪽',\n    HAMSTER_clear_led_1: '',\n    HAMSTER_clear_led_2: 'LED 끄기',\n    HAMSTER_color_cyan: '하늘색',\n    HAMSTER_color_magenta: '자주색',\n    HAMSTER_color_black: '검은색',\n    HAMSTER_color_white: '하얀색',\n    HAMSTER_color_red: '빨간색',\n    HAMSTER_color_yellow: '노란색',\n    HAMSTER_color_green: '초록색',\n    HAMSTER_color_blue: '파란색',\n    HAMSTER_beep: '삐 소리내기',\n    HAMSTER_change_buzzer_by_1: '버저 음을',\n    HAMSTER_change_buzzer_by_2: '만큼 바꾸기',\n    HAMSTER_set_buzzer_to_1: '버저 음을',\n    HAMSTER_set_buzzer_to_2: '(으)로 하기',\n    HAMSTER_clear_buzzer: '버저 끄기',\n    HAMSTER_play_note_for_1: '',\n    HAMSTER_play_note_for_2: '',\n    HAMSTER_play_note_for_3: '음을',\n    HAMSTER_play_note_for_4: '박자 연주하기',\n    HAMSTER_rest_for_1: '',\n    HAMSTER_rest_for_2: '박자 쉬기',\n    HAMSTER_change_tempo_by_1: '연주 속도를',\n    HAMSTER_change_tempo_by_2: '만큼 바꾸기',\n    HAMSTER_set_tempo_to_1: '연주 속도를 분당',\n    HAMSTER_set_tempo_to_2: '박자로 정하기',\n    HAMSTER_set_port_to_1: '포트',\n    HAMSTER_set_port_to_2: '를',\n    HAMSTER_set_port_to_3: '으로 정하기',\n    HAMSTER_change_output_by_1: '출력',\n    HAMSTER_change_output_by_2: '를',\n    HAMSTER_change_output_by_3: '만큼 바꾸기',\n    HAMSTER_set_output_to_1: '출력',\n    HAMSTER_set_output_to_2: '를',\n    HAMSTER_set_output_to_3: '(으)로 정하기',\n    HAMSTER_port_a: 'A',\n    HAMSTER_port_b: 'B',\n    HAMSTER_port_ab: 'A와 B',\n    HAMSTER_analog_input: '아날로그 입력',\n    HAMSTER_digital_input: '디지털 입력',\n    HAMSTER_servo_output: '서보 출력',\n    HAMSTER_pwm_output: 'PWM 출력',\n    HAMSTER_digital_output: '디지털 출력',\n    ROBOID_acceleration_x: 'x축 가속도',\n    ROBOID_acceleration_y: 'y축 가속도',\n    ROBOID_acceleration_z: 'z축 가속도',\n    ROBOID_back: '뒤쪽',\n    ROBOID_both: '양쪽',\n    ROBOID_button: '버튼',\n    ROBOID_buzzer: '버저',\n    ROBOID_clicked: '클릭했는가',\n    ROBOID_color_any: '아무 색',\n    ROBOID_color_black: '검은색',\n    ROBOID_color_blue: '파란색',\n    ROBOID_color_green: '초록색',\n    ROBOID_color_number: '색깔 번호',\n    ROBOID_color_orange: '주황색',\n    ROBOID_color_pattern: '색깔 패턴',\n    ROBOID_color_purple: '자주색',\n    ROBOID_color_red: '빨간색',\n    ROBOID_color_sky_blue: '하늘색',\n    ROBOID_color_violet: '보라색',\n    ROBOID_color_white: '하얀색',\n    ROBOID_color_yellow: '노란색',\n    ROBOID_double_clicked: '더블클릭했는가',\n    ROBOID_floor: '바닥 센서',\n    ROBOID_head: '머리',\n    ROBOID_head_color: '머리 색깔',\n    ROBOID_left: '왼쪽',\n    ROBOID_left_wheel: '왼쪽 바퀴',\n    ROBOID_long_pressed: '길게~눌렀는가',\n    ROBOID_note: '음표',\n    ROBOID_right: '오른쪽',\n    ROBOID_right_wheel: '오른쪽 바퀴',\n    ROBOID_sound_beep: '삐',\n    ROBOID_sound_birthday: '생일',\n    ROBOID_sound_dibidibidip: '디비디비딥',\n    ROBOID_sound_engine: '엔진',\n    ROBOID_sound_good_job: '잘 했어요',\n    ROBOID_sound_march: '행진',\n    ROBOID_sound_random_beep: '무작위 삐',\n    ROBOID_sound_robot: '로봇',\n    ROBOID_sound_siren: '사이렌',\n    ROBOID_tail: '꼬리',\n    ROBOID_unit_cm: 'cm',\n    ROBOID_unit_deg: '도',\n    ROBOID_unit_pulse: '펄스',\n    ROBOID_unit_sec: '초',\n    ALBERT_hand_found: '손 찾음?',\n    ALBERT_is_oid_1: '',\n    ALBERT_is_oid_2: 'OID 값이',\n    ALBERT_is_oid_3: '인가?',\n    ALBERT_front_oid: '앞쪽',\n    ALBERT_back_oid: '뒤쪽',\n    ALBERT_sensor_left_proximity: '왼쪽 근접 센서',\n    ALBERT_sensor_right_proximity: '오른쪽 근접 센서',\n    ALBERT_sensor_acceleration_x: 'x축 가속도',\n    ALBERT_sensor_acceleration_y: 'y축 가속도',\n    ALBERT_sensor_acceleration_z: 'z축 가속도',\n    ALBERT_sensor_light: '밝기',\n    ALBERT_sensor_temperature: '온도',\n    ALBERT_sensor_battery: '배터리',\n    ALBERT_sensor_signal_strength: '신호 세기',\n    ALBERT_sensor_front_oid: '앞쪽 OID',\n    ALBERT_sensor_back_oid: '뒤쪽 OID',\n    ALBERT_sensor_position_x: 'x 위치',\n    ALBERT_sensor_position_y: 'y 위치',\n    ALBERT_sensor_orientation: '방향',\n    ALBERT_move_forward: '앞으로 이동하기',\n    ALBERT_move_backward: '뒤로 이동하기',\n    ALBERT_turn_around_1: '',\n    ALBERT_turn_around_2: '으로 돌기',\n    ALBERT_move_forward_for_secs_1: '앞으로',\n    ALBERT_move_forward_for_secs_2: '초 이동하기',\n    ALBERT_move_backward_for_secs_1: '뒤로',\n    ALBERT_move_backward_for_secs_2: '초 이동하기',\n    ALBERT_turn_for_secs_1: '',\n    ALBERT_turn_for_secs_2: '으로',\n    ALBERT_turn_for_secs_3: '초 돌기',\n    ALBERT_turn_left: '왼쪽',\n    ALBERT_turn_right: '오른쪽',\n    ALBERT_change_both_wheels_by_1: '왼쪽 바퀴',\n    ALBERT_change_both_wheels_by_2: '오른쪽 바퀴',\n    ALBERT_change_both_wheels_by_3: '만큼 바꾸기',\n    ALBERT_left_wheel: '왼쪽',\n    ALBERT_right_wheel: '오른쪽',\n    ALBERT_both_wheels: '양쪽',\n    ALBERT_set_both_wheels_to_1: '왼쪽 바퀴',\n    ALBERT_set_both_wheels_to_2: '오른쪽 바퀴',\n    ALBERT_set_both_wheels_to_3: '(으)로 정하기',\n    ALBERT_change_wheel_by_1: '',\n    ALBERT_change_wheel_by_2: '바퀴',\n    ALBERT_change_wheel_by_3: '만큼 바꾸기',\n    ALBERT_set_wheel_to_1: '',\n    ALBERT_set_wheel_to_2: '바퀴',\n    ALBERT_set_wheel_to_3: '(으)로 정하기',\n    ALBERT_stop: '정지하기',\n    ALBERT_set_board_size_to_1: '말판 크기를 폭',\n    ALBERT_set_board_size_to_2: '높이',\n    ALBERT_set_board_size_to_3: '(으)로 정하기',\n    ALBERT_move_to_x_y_1: '말판 x:',\n    ALBERT_move_to_x_y_2: 'y:',\n    ALBERT_move_to_x_y_3: '위치로 이동하기',\n    ALBERT_set_orientation_to_1: '말판',\n    ALBERT_set_orientation_to_2: '방향으로 바라보기',\n    ALBERT_set_eye_to_1: '',\n    ALBERT_set_eye_to_2: '눈을',\n    ALBERT_set_eye_to_3: '으로 정하기',\n    ALBERT_left_eye: '왼쪽',\n    ALBERT_right_eye: '오른쪽',\n    ALBERT_both_eyes: '양쪽',\n    ALBERT_clear_eye_1: '',\n    ALBERT_clear_eye_2: '눈 끄기',\n    ALBERT_body_led_1: '몸통 LED',\n    ALBERT_body_led_2: '',\n    ALBERT_front_led_1: '앞쪽 LED',\n    ALBERT_front_led_2: '',\n    ALBERT_color_cyan: '하늘색',\n    ALBERT_color_magenta: '보라색',\n    ALBERT_color_white: '하얀색',\n    ALBERT_color_red: '빨간색',\n    ALBERT_color_yellow: '노란색',\n    ALBERT_color_green: '초록색',\n    ALBERT_color_blue: '파란색',\n    ALBERT_note_c: '도',\n    ALBERT_note_d: '레',\n    ALBERT_note_e: '미',\n    ALBERT_note_f: '파',\n    ALBERT_note_g: '솔',\n    ALBERT_note_a: '라',\n    ALBERT_note_b: '시',\n    ALBERT_turn_body_led_1: '몸통 LED',\n    ALBERT_turn_body_led_2: '',\n    ALBERT_turn_front_led_1: '앞쪽 LED',\n    ALBERT_turn_front_led_2: '',\n    ALBERT_turn_on: '켜기',\n    ALBERT_turn_off: '끄기',\n    ALBERT_beep: '삐 소리내기',\n    ALBERT_change_buzzer_by_1: '버저 음을',\n    ALBERT_change_buzzer_by_2: '만큼 바꾸기',\n    ALBERT_set_buzzer_to_1: '버저 음을',\n    ALBERT_set_buzzer_to_2: '(으)로 정하기',\n    ALBERT_clear_buzzer: '버저 끄기',\n    ALBERT_play_note_for_1: '',\n    ALBERT_play_note_for_2: '',\n    ALBERT_play_note_for_3: '음을',\n    ALBERT_play_note_for_4: '박자 연주하기',\n    ALBERT_rest_for_1: '',\n    ALBERT_rest_for_2: '박자 쉬기',\n    ALBERT_change_tempo_by_1: '연주 속도를',\n    ALBERT_change_tempo_by_2: '만큼 바꾸기',\n    ALBERT_set_tempo_to_1: '연주 속도를 분당',\n    ALBERT_set_tempo_to_2: '박자로 정하기',\n    VARIABLE_variable: '변수',\n    wall: '벽',\n    robotis_common_case_01: '(을)를',\n    robotis_common_set: '(으)로 정하기',\n    robotis_common_value: '값',\n    robotis_common_clockwhise: '시계방향',\n    robotis_common_counter_clockwhise: '반시계방향',\n    robotis_common_wheel_mode: '회전모드',\n    robotis_common_joint_mode: '관절모드',\n    robotis_common_red_color: '빨간색',\n    robotis_common_green_color: '녹색',\n    robotis_common_blue_color: '파란색',\n    robotis_common_on: '켜기',\n    robotis_common_off: '끄기',\n    robotis_common_cm: '제어기',\n    robotis_common_port_1: '포트 1',\n    robotis_common_port_2: '포트 2',\n    robotis_common_port_3: '포트 3',\n    robotis_common_port_4: '포트 4',\n    robotis_common_port_5: '포트 5',\n    robotis_common_port_6: '포트 6',\n    robotis_common_play_buzzer: '연주',\n    robotis_common_play_motion: '실행',\n    robotis_common_motion: '모션',\n    robotis_common_index_number: '번',\n    robotis_common_left: '왼쪽',\n    robotis_common_right: '오른쪽',\n    robotis_common_minute: '분',\n    robotis_cm_custom: '직접입력 주소',\n    robotis_cm_spring_left: '왼쪽 접촉 센서',\n    robotis_cm_spring_right: '오른쪽 접촉 센서',\n    robotis_cm_led_left: '왼쪽 LED',\n    robotis_cm_led_right: '오른쪽 LED',\n    robotis_cm_led_both: '양 쪽 LED',\n    robotis_cm_switch: '선택 버튼 상태',\n    robotis_cm_user_button: '사용자 버튼 상태',\n    robotis_cm_sound_detected: '최종 소리 감지 횟수',\n    robotis_cm_sound_detecting: '실시간 소리 감지 횟수',\n    robotis_cm_ir_left: '왼쪽 적외선 센서',\n    robotis_cm_ir_right: '오른쪽 적외선 센서',\n    robotis_cm_calibration_left: '왼쪽 적외선 센서 캘리브레이션 값',\n    robotis_cm_calibration_right: '오른쪽 적외선 센서 캘리브레이션 값',\n    robotis_cm_clear_sound_detected: '최종소리감지횟수 초기화',\n    robotis_cm_buzzer_index: '음계값',\n    robotis_cm_buzzer_melody: '멜로디',\n    robotis_cm_led_1: '1번 LED',\n    robotis_cm_led_4: '4번 LED',\n    robotis_aux_servo_position: '서보모터 위치',\n    robotis_aux_ir: '적외선센서',\n    robotis_aux_touch: '접촉센서',\n    robotis_aux_brightness: '조도센서(CDS)',\n    robotis_aux_hydro_themo_humidity: '온습도센서(습도)',\n    robotis_aux_hydro_themo_temper: '온습도센서(온도)',\n    robotis_aux_temperature: '온도센서',\n    robotis_aux_ultrasonic: '초음파센서',\n    robotis_aux_magnetic: '자석센서',\n    robotis_aux_motion_detection: '동작감지센서',\n    robotis_aux_color: '컬러센서',\n    robotis_aux_custom: '사용자 장치',\n    robotis_carCont_aux_motor_speed_1: '감속모터 속도를',\n    robotis_carCont_aux_motor_speed_2: ', 출력값을',\n    robotis_carCont_calibration_1: '적외선 센서 캘리브레이션 값을',\n    robotis_openCM70_aux_motor_speed_1: '감속모터 속도를',\n    robotis_openCM70_aux_motor_speed_2: ', 출력값을',\n    robotis_openCM70_aux_servo_mode_1: '서보모터 모드를',\n    robotis_openCM70_aux_servo_speed_1: '서보모터 속도를',\n    robotis_openCM70_aux_servo_speed_2: ', 출력값을',\n    robotis_openCM70_aux_servo_position_1: '서보모터 위치를',\n    robotis_openCM70_aux_led_module_1: 'LED 모듈을',\n    robotis_openCM70_aux_custom_1: '사용자 장치를',\n    XBOT_digital: '디지털',\n    XBOT_D2_digitalInput: 'D2 디지털 입력',\n    XBOT_D3_digitalInput: 'D3 디지털 입력',\n    XBOT_D11_digitalInput: 'D11 디지털 입력',\n    XBOT_analog: '아날로그',\n    XBOT_CDS: '광 센서 값',\n    XBOT_MIC: '마이크 센서 값',\n    XBOT_analog0: '아날로그 0번 핀 값',\n    XBOT_analog1: '아날로그 1번 핀 값',\n    XBOT_analog2: '아날로그 2번 핀 값',\n    XBOT_analog3: '아날로그 3번 핀 값',\n    XBOT_Value: '출력 값',\n    XBOT_pin_OutputValue: '핀, 출력 값',\n    XBOT_High: '높음',\n    XBOT_Low: '낮음',\n    XBOT_Servo: '서보 모터',\n    XBOT_Head: '머리(D8)',\n    XBOT_ArmR: '오른 팔(D9)',\n    XBOT_ArmL: '왼 팔(D10)',\n    XBOT_angle: ', 각도',\n    XBOT_DC: '바퀴(DC) 모터',\n    XBOT_rightWheel: '오른쪽',\n    XBOT_leftWheel: '왼쪽',\n    XBOT_bothWheel: '양쪽',\n    XBOT_speed: ', 속도',\n    XBOT_rightSpeed: '바퀴(DC) 모터 오른쪽(2) 속도:',\n    XBOT_leftSpeed: '왼쪽(1) 속도:',\n    XBOT_RGBLED_R: 'RGB LED 켜기 R 값',\n    XBOT_RGBLED_G: 'G 값',\n    XBOT_RGBLED_B: 'B 값',\n    XBOT_RGBLED_color: 'RGB LED 색',\n    XBOT_set: '로 정하기',\n    XBOT_c: '도',\n    XBOT_d: '레',\n    XBOT_e: '미',\n    XBOT_f: '파',\n    XBOT_g: '솔',\n    XBOT_a: '라',\n    XBOT_b: '시',\n    XBOT_melody_ms: '초 연주하기',\n    XBOT_Line: '번째 줄',\n    XBOT_outputValue: '출력 값',\n    roborobo_num_analog_value_1: '아날로그',\n    roborobo_num_analog_value_2: '번 센서값',\n    roborobo_get_digital_value_1: '디지털',\n    roborobo_num_pin_1: '디지털',\n    roborobo_num_pin_2: '번 핀',\n    roborobo_on: '켜기',\n    roborobo_off: '끄기',\n    roborobo_motor1: '모터1',\n    roborobo_motor2: '모터2',\n    roborobo_motor_CW: '정회전',\n    roborobo_motor_CCW: '역회전',\n    roborobo_motor_stop: '정지',\n    roborobo_input_mode: '입력',\n    roborobo_output_mode: '출력',\n    roborobo_pwm_mode: '전류조절(pwm)',\n    roborobo_servo_mode: '서보모터',\n    roborobo_color: '컬러센서',\n    roborobo_color_red: ' 빨간색  ',\n    roborobo_color_green: ' 녹색 ',\n    roborobo_color_blue: ' 파란색 ',\n    roborobo_color_yellow: ' 노란색 ',\n    roborobo_color_detected: ' 감지 ',\n    roborobo_degree: ' ˚',\n    robotori_D2_Input: '디지털 2번 핀 입력 값',\n    robotori_D3_Input: '디지털 3번 핀 입력 값',\n    robotori_A0_Input: '아날로그 0번 핀 입력 값',\n    robotori_A1_Input: '아날로그 1번 핀 입력 값',\n    robotori_A2_Input: '아날로그 2번 핀 입력 값',\n    robotori_A3_Input: '아날로그 3번 핀 입력 값',\n    robotori_A4_Input: '아날로그 4번 핀 입력 값',\n    robotori_A5_Input: '아날로그 5번 핀 입력 값',\n    robotori_digital: '디지털',\n    robotori_D10_Output: '10번',\n    robotori_D11_Output: '11번',\n    robotori_D12_Output: '12번',\n    robotori_D13_Output: '13번',\n    robotori_pin_OutputValue: '핀, 출력 값',\n    robotori_On: '켜짐',\n    robotori_Off: '꺼짐',\n    robotori_analog: '아날로그',\n    robotori_analog5: '5번 핀 출력 값',\n    robotori_analog6: '6번 핀 출력 값',\n    robotori_analog9: '9번 핀 출력 값',\n    robotori_Servo: '서보모터',\n    robotori_DC: 'DC모터',\n    robotori_DC_rightmotor: '오른쪽',\n    robotori_DC_leftmotor: '왼쪽',\n    robotori_DC_STOP: '정지',\n    robotori_DC_CW: '시계방향',\n    robotori_DC_CCW: '반시계방향',\n    robotori_DC_select: '회전',\n    CALC_rotation_value: '방향값',\n    CALC_direction_value: '이동 방향값',\n    VARIABLE_is_included_in_list: '',\n    VARIABLE_is_included_in_list_1: '',\n    VARIABLE_is_included_in_list_2: '에',\n    VARIABLE_is_included_in_list_3: '이 포함되어 있는가?',\n    SCENE_when_scene_start: '장면이 시작되었을 때',\n    SCENE_start_scene_1: '',\n    SCENE_start_scene_2: '시작하기',\n    SCENE_start_neighbor_scene_1: '',\n    SCENE_start_neighbor_scene_2: '장면 시작하기',\n    SCENE_start_scene_pre: '이전',\n    SCENE_start_scene_next: '다음',\n    FUNCTION_explanation_1: '이름',\n    FUNCTION_character_variable: '문자/숫자값',\n    FUNCTION_logical_variable: '판단값',\n    FUNCTION_function: '함수',\n    FUNCTION_define: '함수 정의하기',\n    CALC_calc_operation_sin: '사인값',\n    CALC_calc_operation_cos: '코사인값',\n    CALC_calc_operation_tan: '탄젠트값',\n    CALC_calc_operation_floor: '소수점 버림값',\n    CALC_calc_operation_ceil: '소수점 올림값',\n    CALC_calc_operation_round: '소수점 반올림값',\n    CALC_calc_operation_factorial: '펙토리얼값',\n    CALC_calc_operation_asin: '아크사인값',\n    CALC_calc_operation_acos: '아크코사인값',\n    CALC_calc_operation_atan: '아크탄젠트값',\n    CALC_calc_operation_log: '로그값',\n    CALC_calc_operation_ln: '자연로그값',\n    CALC_calc_operation_natural: '정수 부분',\n    CALC_calc_operation_unnatural: '소수점 부분',\n    MOVING_locate_object_time_1: '',\n    MOVING_locate_object_time_2: '초 동안',\n    MOVING_locate_object_time_3: '위치로 이동하기',\n    wall_up: '위쪽 벽',\n    wall_down: '아래쪽 벽',\n    wall_right: '오른쪽 벽',\n    wall_left: '왼쪽 벽',\n    CALC_coordinate_x_value: 'x 좌푯값',\n    CALC_coordinate_y_value: 'y 좌푯값',\n    CALC_coordinate_rotation_value: '방향',\n    CALC_coordinate_direction_value: '이동방향',\n    CALC_picture_index: '모양 번호',\n    CALC_picture_name: '모양 이름',\n    FLOW_repeat_while_true_1: '',\n    FLOW_repeat_while_true_2: ' 반복하기',\n    TUT_when_start: '프로그램 실행을 클릭했을때',\n    TUT_move_once: '앞으로 한 칸 이동',\n    TUT_rotate_left: '왼쪽으로 회전',\n    TUT_rotate_right: '오른쪽으로 회전',\n    TUT_jump_barrier: '장애물 뛰어넘기',\n    TUT_repeat_tutorial_1: '',\n    TUT_repeat_tutorial_2: '번 반복',\n    TUT_if_barrier_1: '만약 앞에',\n    TUT_if_barrier_2: ' 이 있다면',\n    TUT_if_conical_1: '만약 앞에',\n    TUT_if_conical_2: ' 이 있다면',\n    TUT_repeat_until: '부품에 도달할 때 까지 반복',\n    TUT_repeat_until_gold: '부품에 도달할 때 까지 반복',\n    TUT_declare_function: '함수 선언',\n    TUT_call_function: '함수 호출',\n    CALC_calc_operation_abs: '절댓값',\n    CONTEXT_COPY_option: '코드 복사',\n    Delete_Blocks: '코드 삭제',\n    Duplication_option: '코드 복사 & 붙여넣기',\n    Paste_blocks: '붙여넣기',\n    add_my_storage: '나의 보관함에 추가하기',\n    export_object: '오브젝트 내보내기',\n    Clear_all_blocks: '모든 코드 삭제하기',\n    add_comment: '메모 추가하기',\n    copy_paste_comment: '메모 복사 & 붙여넣기',\n    copy_comment: '메모 복사하기',\n    delete_comment: '메모 삭제하기',\n    fold_comment: '메모 접기',\n    open_comment: '메모 열기',\n    separate_comment: '메모 분리하기',\n    hide_all_comment: '모든 메모 숨기기',\n    show_all_comment: '모든 메모 보이기',\n    transparency: '투명도',\n    BRUSH_change_brush_transparency_1: '붓의 투명도를',\n    BRUSH_change_brush_transparency_2: '% 만큼 바꾸기',\n    BRUSH_set_brush_transparency_1: '붓의 투명도를',\n    BRUSH_set_brush_transparency_2: '% 로 정하기',\n    CALC_char_at_1: '',\n    CALC_char_at_2: '의',\n    CALC_char_at_3: '번째 글자',\n    CALC_length_of_string_1: '',\n    CALC_length_of_string_2: '의 글자 수',\n    CALC_reverse_of_string_1: '',\n    CALC_reverse_of_string_2: '을(를) 뒤집은 값',\n    CALC_substring_1: '',\n    CALC_substring_2: '의',\n    CALC_substring_3: '번째 글자부터',\n    length_of_string: '번째 글자부터',\n    CALC_substring_4: '번째 글자까지의 글자',\n    CALC_replace_string_1: '',\n    CALC_replace_string_2: '의',\n    CALC_replace_string_3: '을(를)',\n    CALC_replace_string_4: '로 바꾸기',\n    CALC_change_string_case_1: '',\n    CALC_change_string_case_2: '의',\n    CALC_change_string_case_3: ' ',\n    CALC_change_string_case_sub_1: '대문자',\n    CALC_change_string_case_sub_2: '소문자',\n    CALC_count_match_string_1: '에서',\n    CALC_count_match_string_2: '의 글자 수',\n    CALC_index_of_string_1: '',\n    CALC_index_of_string_2: '에서',\n    CALC_index_of_string_3: '의 시작 위치',\n    MOVING_add_direction_by_angle_time_explain_1: '',\n    MOVING_direction_relative_duration_1: '',\n    MOVING_direction_relative_duration_2: '초 동안 이동 방향',\n    MOVING_direction_relative_duration_3: '만큼 회전하기',\n    CALC_get_sound_volume: ' 소리 크기',\n    SOUND_sound_from_to_1: '소리',\n    SOUND_sound_from_to_2: '',\n    SOUND_sound_from_to_3: '초 부터',\n    SOUND_sound_from_to_4: '초까지 재생하기',\n    SOUND_sound_from_to_and_wait_1: '소리',\n    SOUND_sound_from_to_and_wait_2: '',\n    SOUND_sound_from_to_and_wait_3: '초 부터',\n    SOUND_sound_from_to_and_wait_4: '초까지 재생하고 기다리기',\n    CALC_quotient_and_mod_1: '',\n    CALC_quotient_and_mod_2: '/',\n    CALC_quotient_and_mod_3: '의',\n    CALC_quotient_and_mod_4: '',\n    CALC_quotient_and_mod_sub_1: '몫',\n    CALC_quotient_and_mod_sub_2: '나머지',\n    self: '자신',\n    CALC_coordinate_size_value: '크기',\n    CALC_choose_project_timer_action_1: '초시계',\n    CALC_choose_project_timer_action_2: '',\n    CALC_choose_project_timer_action_sub_1: '시작하기',\n    CALC_choose_project_timer_action_sub_2: '정지하기',\n    CALC_choose_project_timer_action_sub_3: '초기화하기',\n    LOOKS_change_object_index_1: '',\n    LOOKS_change_object_index_2: '보내기',\n    LOOKS_change_object_index_sub_1: '맨 앞으로',\n    LOOKS_change_object_index_sub_2: '앞으로',\n    LOOKS_change_object_index_sub_3: '뒤로',\n    LOOKS_change_object_index_sub_4: '맨 뒤로',\n    FLOW_repeat_while_true_until: '',\n    FLOW_repeat_while_true_while: '',\n    copy_block: '',\n    delete_block: '',\n    tidy_up_block: '코드 정리하기',\n    block_hi: '안녕!',\n    entry_bot_name: '엔트리봇',\n    hi_entry: '',\n    hi_entry_en: '',\n    bark_dog: '',\n    walking_entryBot: '엔트리봇_걷기',\n    doggi_bark: '강아지 짖는 소리',\n    entry: '엔트리',\n    hello: '',\n    nice: '',\n    silent: '무음',\n    do_name: '도',\n    do_sharp_name: '도#(레♭)',\n    re_name: '레',\n    re_sharp_name: '레#(미♭)',\n    mi_name: '미',\n    fa_name: '파',\n    fa_sharp_name: '파#(솔♭)',\n    sol_name: '솔',\n    sol_sharp_name: '솔#(라♭)',\n    la_name: '라',\n    la_sharp_name: '라#(시♭)',\n    DUMMY: '더미',\n    coconut_stop_motor: '모터 정지',\n    coconut_move_motor: '움직이기',\n    coconut_turn_motor: '으로 돌기',\n    coconut_move_outmotor: '외부모터',\n    coconut_turn_left: '왼쪽',\n    coconut_turn_right: '오른쪽',\n    coconut_move_forward: '앞으로',\n    coconut_move_backward: '뒤로',\n    coconut_note_c: '도',\n    coconut_note_d: '레',\n    coconut_note_e: '미',\n    coconut_note_f: '파',\n    coconut_note_g: '솔',\n    coconut_note_a: '라',\n    coconut_note_b: '시',\n    coconut_move_speed_1: '0',\n    coconut_move_speed_2: '50',\n    coconut_move_speed_3: '100',\n    coconut_move_speed_4: '150',\n    coconut_move_speed_5: '255',\n    coconut_play_buzzer_hn: '2분음표',\n    coconut_play_buzzer_qn: '4분음표',\n    coconut_play_buzzer_en: '8분음표',\n    coconut_play_buzzer_sn: '16분음표',\n    coconut_play_buzzer_tn: '32분음표',\n    coconut_play_buzzer_wn: '온음표',\n    coconut_play_buzzer_dhn: '점2분음표',\n    coconut_play_buzzer_dqn: '점4분음표',\n    coconut_play_buzzer_den: '점8분음표',\n    coconut_play_buzzer_dsn: '점16분음표',\n    coconut_play_buzzer_dtn: '점32분음표',\n    coconut_rest_buzzer_hr: '2분쉼표',\n    coconut_rest_buzzer_qr: '4분쉼표',\n    coconut_rest_buzzer_er: '8분쉼표',\n    coconut_rest_buzzer_sr: '16분쉼표',\n    coconut_rest_buzzer_tr: '32분쉼표',\n    coconut_rest_buzzer_wr: '온쉼표',\n    coconut_play_midi_1: '반짝반짝 작은별',\n    coconut_play_midi_2: '곰세마리',\n    coconut_play_midi_3: '모차르트 자장가',\n    coconut_play_midi_4: '도레미송',\n    coconut_play_midi_5: '나비야',\n    coconut_floor_sensing_on: '감지',\n    coconut_floor_sensing_off: '미감지',\n    coconut_dotmatrix_set_on: '켜짐',\n    coconut_dotmatrix_set_off: '꺼짐',\n    coconut_dotmatrix_row_0: '모든',\n    coconut_dotmatrix_row_1: '1',\n    coconut_dotmatrix_row_2: '2',\n    coconut_dotmatrix_row_3: '3',\n    coconut_dotmatrix_row_4: '4',\n    coconut_dotmatrix_row_5: '5',\n    coconut_dotmatrix_row_6: '6',\n    coconut_dotmatrix_row_7: '7',\n    coconut_dotmatrix_row_8: '8',\n    coconut_dotmatrix_col_0: '모든',\n    coconut_dotmatrix_col_1: '1',\n    coconut_dotmatrix_col_2: '2',\n    coconut_dotmatrix_col_3: '3',\n    coconut_dotmatrix_col_4: '4',\n    coconut_dotmatrix_col_5: '5',\n    coconut_dotmatrix_col_6: '6',\n    coconut_dotmatrix_col_7: '7',\n    coconut_dotmatrix_col_8: '8',\n    coconut_sensor_left_proximity: '왼쪽 전방 센서',\n    coconut_sensor_right_proximity: '오른쪽 전방 센서',\n    coconut_sensor_both_proximity: '모든',\n    coconut_sensor_left_floor: '왼쪽 바닥센서',\n    coconut_sensor_right_floor: '오른쪽 바닥 센서',\n    coconut_sensor_both_floor: '모든',\n    coconut_sensor_acceleration_x: 'x축 가속도',\n    coconut_sensor_acceleration_y: 'y축 가속도',\n    coconut_sensor_acceleration_z: 'z축 가속도',\n    coconut_sensor_light: '밝기',\n    coconut_sensor_temperature: '온도',\n    coconut_left_led: '왼쪽',\n    coconut_right_led: '오른쪽',\n    coconut_both_leds: '모든',\n    coconut_color_cyan: '하늘색',\n    coconut_color_magenta: '보라색',\n    coconut_color_black: '검은색',\n    coconut_color_white: '흰색',\n    coconut_color_red: '빨간색',\n    coconut_color_yellow: '노란색',\n    coconut_color_green: '초록색',\n    coconut_color_blue: '파란색',\n    coconut_beep: '삐 소리내기',\n    coconut_clear_buzzer: '버저 끄기',\n    coconut_x_axis: 'X축',\n    coconut_y_axis: 'Y축',\n    coconut_z_axis: 'Z축',\n    modi_enviroment_bule: '파랑',\n    modi_enviroment_green: '초록',\n    modi_enviroment_humidity: '습도',\n    modi_enviroment_illuminance: '조도',\n    modi_enviroment_red: '빨강',\n    modi_enviroment_temperature: '온도',\n    modi_gyroscope_xAcceleratior: 'X축 가속',\n    modi_gyroscope_yAcceleratior: 'Y축 가속',\n    modi_gyroscope_zAcceleratior: 'Z축 가속',\n    modi_motor_angle: '각도',\n    modi_motor_speed: '속도',\n    modi_motor_torque: '회전',\n    modi_speaker_F_DO_5: '도5',\n    modi_speaker_F_DO_6: '도6',\n    modi_speaker_F_DO_7: '도7',\n    modi_speaker_F_DO_S_5: '도#5',\n    modi_speaker_F_DO_S_6: '도#6',\n    modi_speaker_F_DO_S_7: '도#7',\n    modi_speaker_F_MI_5: '미5',\n    modi_speaker_F_MI_6: '미6',\n    modi_speaker_F_MI_7: '미7',\n    modi_speaker_F_PA_5: '파5',\n    modi_speaker_F_PA_6: '파6',\n    modi_speaker_F_PA_7: '파7',\n    modi_speaker_F_PA_S_5: '파#5',\n    modi_speaker_F_PA_S_6: '파#6',\n    modi_speaker_F_PA_S_7: '파#7',\n    modi_speaker_F_RA_5: '라5',\n    modi_speaker_F_RA_6: '라6',\n    modi_speaker_F_RA_7: '라7',\n    modi_speaker_F_RA_S_5: '라#5',\n    modi_speaker_F_RA_S_6: '라#6',\n    modi_speaker_F_RA_S_7: '라#7',\n    modi_speaker_F_RE_5: '레5',\n    modi_speaker_F_RE_6: '레6',\n    modi_speaker_F_RE_7: '레7',\n    modi_speaker_F_RE_S_5: '라#5',\n    modi_speaker_F_RE_S_6: '레#6',\n    modi_speaker_F_RE_S_7: '레#7',\n    modi_speaker_F_SOL_5: '솔5',\n    modi_speaker_F_SOL_6: '솔6',\n    modi_speaker_F_SOL_7: '솔7',\n    modi_speaker_F_SOL_S_5: '솔#5',\n    modi_speaker_F_SOL_S_6: '솔#6',\n    modi_speaker_F_SOL_S_7: '솔#7',\n    modi_speaker_F_SO_5: '시5',\n    modi_speaker_F_SO_6: '시6',\n    modi_speaker_F_SO_7: '시7',\n    si_name: '시',\n    ev3_ccw: '반시계',\n    ev3_cw: '시계',\n    rokoboard_sensor_name_0: '소리',\n    rokoboard_sensor_name_1: '빛',\n    rokoboard_sensor_name_2: '슬라이더',\n    rokoboard_sensor_name_3: '저항-A',\n    rokoboard_sensor_name_4: '저항-B',\n    rokoboard_sensor_name_5: '저항-C',\n    rokoboard_sensor_name_6: '저항-D',\n    rokoboard_string_1: '버튼을 눌렀는가?',\n    HW_MOTOR: '모터',\n    HW_SENSOR: '센서',\n    HW_LED: '발광다이오드',\n    HW_MELODY: '멜로디',\n    HW_ROBOT: '로봇',\n    ALTINO_ACCX: '가속도 X축',\n    ALTINO_ACCY: '가속도 Y축',\n    ALTINO_ACCZ: '가속도 Z축',\n    ALTINO_BAT: '배터리 잔량 체크',\n    ALTINO_CDS: '밝기',\n    ALTINO_GYROX: '자이로 X축',\n    ALTINO_GYROY: '자이로 Y축',\n    ALTINO_GYROZ: '자이로 Z축',\n    ALTINO_IR1: '1번 거리',\n    ALTINO_IR2: '2번 거리',\n    ALTINO_IR3: '3번 거리',\n    ALTINO_IR4: '4번 거리',\n    ALTINO_IR5: '5번 거리',\n    ALTINO_IR6: '6번 거리',\n    ALTINO_Led_Brake_Light: '브레이크',\n    ALTINO_Led_Forward_Light: '전방',\n    ALTINO_Led_Reverse_Light: '후방',\n    ALTINO_Led_Turn_Left_Light: '왼쪽방향',\n    ALTINO_Led_Turn_Right_Light: '오른쪽방향',\n    ALTINO_Line: '번째 줄',\n    ALTINO_MAGX: '나침판 X축',\n    ALTINO_MAGY: '나침판 Y축',\n    ALTINO_MAGZ: '나침판 Z축',\n    ALTINO_REMOTE: '리모콘 수신 값',\n    ALTINO_STTOR: '조향 토크',\n    ALTINO_STVAR: '조향 가변저항',\n    ALTINO_Steering_Angle_Center: '가운데',\n    ALTINO_Steering_Angle_Left10: '왼쪽10',\n    ALTINO_Steering_Angle_Left15: '왼쪽15',\n    ALTINO_Steering_Angle_Left20: '왼쪽20',\n    ALTINO_Steering_Angle_Left5: '왼쪽5',\n    ALTINO_Steering_Angle_Right10: '오른쪽10',\n    ALTINO_Steering_Angle_Right15: '오른쪽15',\n    ALTINO_Steering_Angle_Right20: '오른쪽20',\n    ALTINO_Steering_Angle_Right5: '오른쪽5',\n    ALTINO_TEM: '온도',\n    ALTINO_TOR1: '오른쪽 토크',\n    ALTINO_TOR2: '왼쪽 토크',\n    ALTINO_Value: '출력 값',\n    ALTINO_a: '라',\n    ALTINO_a2: '라#',\n    ALTINO_b: '시',\n    ALTINO_c: '도',\n    ALTINO_c2: '도#',\n    ALTINO_d: '레',\n    ALTINO_d2: '레#',\n    ALTINO_dot_display_1: '한문자',\n    ALTINO_dot_display_2: '출력하기',\n    ALTINO_e: '미',\n    ALTINO_f: '파',\n    ALTINO_f2: '파#',\n    ALTINO_g: '솔',\n    ALTINO_g2: '솔#',\n    ALTINO_h: '끄기',\n    ALTINO_h2: '켜기',\n    ALTINO_leftWheel: '왼쪽',\n    ALTINO_melody_ms: '연주하기',\n    ALTINO_outputValue: '출력 값',\n    ALTINO_rightWheel: '오른쪽',\n    ALTINO_set: '로 정하기',\n    ardublock_motor_forward: '앞',\n    ardublock_motor_backward: '뒤',\n    jdkit_clockwise: '시계방향',\n    jdkit_counterclockwise: '반시계방향',\n    jdkit_gyro_frontrear: '앞뒤',\n    jdkit_gyro_leftright: '좌우',\n    jdkit_joystick_leftleftright: '왼쪽 좌우',\n    jdkit_joystick_lefttopbottom: '왼쪽 상하',\n    jdkit_joystick_rightleftright: '오른쪽 좌우',\n    jdkit_joystick_righttopbottom: '오른쪽 상하',\n    jdkit_led: 'LED',\n    jdkit_led_color_green: '초록색',\n    jdkit_led_color_orange: '오랜지색',\n    jdkit_led_turnoff: '끄기',\n    jdkit_led_turnon: '켜기',\n    jdkit_motor_leftbottom: '왼쪽아래',\n    jdkit_motor_lefttop: '왼쪽위',\n    jdkit_motor_rightbottom: '오른쪽아래',\n    jdkit_motor_righttop: '오른쪽위',\n    jdkit_tune_do: '도',\n    jdkit_tune_fa: '파',\n    jdkit_tune_la: '라',\n    jdkit_tune_mi: '미',\n    jdkit_tune_re: '레',\n    jdkit_tune_si: '시',\n    jdkit_tune_sol: '솔',\n    FUNBOARD_bt_down: '노랑(B)',\n    FUNBOARD_bt_left: '초록(C)',\n    FUNBOARD_bt_right: '파랑(D)',\n    FUNBOARD_bt_up: '빨강(A)',\n    FUNBOARD_column_tag: '칸',\n    FUNBOARD_do_off: '끄기',\n    FUNBOARD_do_on: '켜기',\n    FUNBOARD_led_color_all: '모두',\n    FUNBOARD_led_color_blue: '파랑',\n    FUNBOARD_led_color_green: '초록',\n    FUNBOARD_led_color_red: '빨강',\n    FUNBOARD_led_color_str: '색',\n    FUNBOARD_led_color_yellow: '노랑',\n    FUNBOARD_led_off_str: 'LED 끄기',\n    FUNBOARD_led_on_str: 'LED 켜기',\n    FUNBOARD_row_tag: '줄',\n    FUNBOARD_scroll_down: '아래쪽으로',\n    FUNBOARD_scroll_left: '왼쪽으로',\n    FUNBOARD_scroll_no: '없음',\n    FUNBOARD_scroll_right: '오른쪽으로',\n    FUNBOARD_scroll_up: '위쪽으로',\n    FUNBOARD_sensor_cds: 'Cds (밝기 감지)',\n    FUNBOARD_sensor_mic: '마이크 (소리 감지)',\n    FUNBOARD_sensor_slide: '슬라이드 (막대 조정)',\n    FUNBOARD_sensor_state_1: '작다',\n    FUNBOARD_sensor_state_2: '크다',\n    FUNBOARD_touchbt_down: '노랑(B)',\n    FUNBOARD_touchbt_enter: '   F',\n    FUNBOARD_touchbt_escape: '   G',\n    FUNBOARD_touchbt_left: '초록(C)',\n    FUNBOARD_touchbt_right: '파랑(D)',\n    FUNBOARD_touchbt_space: '   E',\n    FUNBOARD_touchbt_up: '빨강(A)',\n    funboard_dotmatrix_set_off: '끄기',\n    funboard_dotmatrix_set_on: '켜기',\n    AI_UTILIZE: '인공지능',\n    video_show_video: '보이기',\n    video_hide_video: '숨기기',\n    video_brightness: '밝기',\n    video_transparency: '투명도',\n    video_left_right: '좌우',\n    video_top_bottom: '상하',\n    video_human: '사람',\n    video_face: '얼굴',\n    video_object: '사물',\n    video_start: '시작하기',\n    video_end: '중지하기',\n    video_gender: '성별',\n    video_age: '나이',\n    video_emotion: '감정',\n    video_motion_onself: '자신',\n    video_motion_onscreen: '실행화면',\n    video_motion_scale: '움직임',\n    video_motion_direction_horizontal: '좌우방향',\n    video_motion_direction_vertical: '상하방향',\n    table_row: '행',\n    table_col: '열',\n    table_sum: '합',\n    table_max: '최대',\n    table_min: '최소',\n    table_avg: '평균',\n    table_stdev: '표준편차',\n};\nLang.video_body_coord_params = {\n    left_eye: '왼쪽 눈',\n    right_eye: '오른쪽 눈',\n    nose: '코',\n    left_mouth: '왼쪽 입꼬리',\n    right_mouth: '오른쪽 입꼬리',\n    upper_lip: '윗 입술',\n    lower_lip: '아랫 입술',\n    face: '얼굴',\n    neck: '목',\n    left_ear: '왼쪽 귀',\n    right_ear: '오른쪽 귀',\n    left_shoulder: '왼쪽 어깨',\n    left_elbow: '왼쪽 팔꿈치',\n    left_wrist: '왼쪽 손목',\n    left_hip: '왼쪽 엉덩이',\n    left_knee: '왼쪽 무릎',\n    left_ankle: '왼쪽 발목',\n    right_shoulder: '오른쪽 어깨',\n    right_elbow: '오른쪽 팔꿈치',\n    right_wrist: '오른쪽 손목',\n    right_hip: '오른쪽 엉덩이',\n    right_knee: '오른쪽 무릎',\n    right_ankle: '오른쪽 발목',\n};\nLang.video_emotion_params = {\n    angry: '분노',\n    disgusted: '혐오',\n    fearful: '두려움',\n    happy: '행복',\n    neutral: '무표정',\n    sad: '슬픔',\n    surprised: '놀람',\n};\nLang.video_object_params = {\n    person: '사람',\n    bicycle: '자전거',\n    car: '자동차',\n    motorcycle: '오토바이',\n    airplane: '비행기',\n    bus: '버스',\n    train: '기차',\n    truck: '트럭',\n    boat: '보트',\n    'traffic light': '신호등',\n    'fire hydrant': '소화전',\n    'stop sign': '일단 정지 표지판',\n    'parking meter': '주차요금 계산기',\n    bench: '벤치',\n    bird: '새',\n    cat: '고양이',\n    dog: '강아지',\n    horse: '말',\n    sheep: '양',\n    cow: '소',\n    elephant: '코끼리',\n    bear: '곰',\n    zebra: '얼룩말',\n    giraffe: '기린',\n    backpack: '배낭',\n    umbrella: '우산',\n    handbag: '핸드백',\n    tie: '넥타이',\n    suitcase: '여행 가방',\n    frisbee: '프리즈비 원반',\n    skis: '스키',\n    snowboard: '스노우보드',\n    'sports ball': '공',\n    kite: '연',\n    'baseball bat': '야구 배트',\n    'baseball glove': '야구 글러브',\n    skateboard: '스케이트 보드',\n    surfboard: '서핑 보드',\n    'tennis racket': '테니스 라켓',\n    bottle: '병',\n    'wine glass': '와인 잔',\n    cup: '컵',\n    fork: '포크',\n    knife: '칼',\n    spoon: '숟가락',\n    bowl: '사발',\n    banana: '바나나',\n    apple: '사과',\n    sandwich: '샌드위치',\n    orange: '오렌지',\n    broccoli: '브로콜리',\n    carrot: '당근',\n    'hot dog': '핫도그',\n    pizza: '피자',\n    donut: '도넛',\n    cake: '케이크',\n    chair: '의자',\n    couch: '소파',\n    'potted plant': '식물 화분',\n    bed: '침대',\n    'dining table': '식탁',\n    toilet: '변기',\n    tv: '텔레비젼',\n    laptop: '노트북',\n    mouse: '마우스',\n    remote: '리모콘',\n    keyboard: '키보드',\n    'cell phone': '휴대전화',\n    microwave: '전자렌지',\n    oven: '오븐',\n    toaster: '토스터기',\n    sink: '싱크대',\n    refrigerator: '냉장고',\n    book: '책',\n    clock: '시계',\n    vase: '꽃병',\n    scissors: '가위',\n    'teddy bear': '곰인형',\n    'hair drier': '헤어 드라이기',\n    toothbrush: '칫솔',\n};\nLang.Buttons = {\n    share_policy: '이것만은 꼭!',\n    write_policy: '작성 가이드',\n    lesson_list: '강의 목록',\n    complete_study: '학습 완료하기',\n    show_me: '미리 보기',\n    do_this_for_me: '대신 해주기',\n    previous: '이전',\n    get_started: '시작하기',\n    next_lesson: '다음 내용 학습하기',\n    course_submit: '제출하기',\n    course_done: '확인',\n    mission: '미션 확인하기',\n    basic_guide: '기본 사용 방법',\n    apply: '적용하기',\n    add: '추가하기',\n    cancel: '취소',\n    save: '확인',\n    start: '시작',\n    confirm: '확인',\n    delete: '삭제',\n    create: '학급 만들기',\n    done: '완료',\n    accept: '수락',\n    refuse: '거절',\n    yes: '예',\n    button_no: '아니오',\n    quiz_retry: '다시 풀어보기',\n    discuss_upload: '불러오기',\n    maze_popup_guide: '이용안내',\n    maze_popup_mapHint: '힌트보기',\n    maze_hint_btn_guide: '이용 안내',\n    maze_hint_btn_block: '블록 도움말',\n    maze_hint_btn_map: '힌트 보기',\n    maze_hint_btn_goal: '목표',\n    list_save: '저장하기',\n    duplication: '복사하기',\n    export_to_excel: '엑셀로 내려받기',\n    single_line: '한 줄 쓰기',\n    multi_line: '여러 줄 쓰기',\n    lecture_finish_popup_reset_lecture: '처음부터 다시하기',\n    lecture_finish_popup_show_output: '실습한 코드보기',\n    lecture_view_hints: '잘 모르겠어요!',\n    default_hint_title: '어떻게 만들까?',\n    show_only_vector: '벡터 모아보기',\n};\nLang.Menus = {\n    nothing_to_import: '불러오기 할 항목이 없습니다.',\n    nothing_to_export: '내려받기 할 항목이 없습니다.',\n    content_copied: '내용이 복사되었습니다.',\n    list_import_title: '리스트 불러오기',\n    list_import_placeholder: '예)\\n내용1\\n내용2\\n내용3\\n내용4\\n내용5\\n내용6\\n내용7\\n내용8',\n    verifying_email: '인증 메일 발송하기',\n    list_import_notice_1: '리스트 항목의 내용을 올릴 수 있습니다.',\n    list_import_notice_2: '기존 내용은 새로 저장한 내용으로 변경됩니다.',\n    list_export_title: '리스트 내보내기',\n    list_export_notice: '리스트 항목의 내용을 복사하거나, 엑셀로 내려받을 수 있습니다.',\n    robotis_opencm70: '로보티즈 IoT',\n    cannnot_mark_favorite: '비공개 작품은 관심 작품으로 지정할 수 없습니다.',\n    enterPassword: '비밀번호를 입력해주세요.',\n    enterPassword_update: '변경 내용을 저장하기 위해 비밀번호를 입력해주세요.',\n    enterNewPassword: '새로운 비밀번호를 입력하세요.',\n    reEnterNewPassword: '새로운 비밀번호를 다시 입력하세요.',\n    resign: '회원탈퇴',\n    check_sended_email: '발송된 인증 메일을 확인하여 이메일 주소를 인증해 주세요.',\n    signUpEmail_1: '입력된 이메일 주소로 인증 메일이 발송되었습니다.',\n    signUpEmail_2: '이메일 주소를 인증해주세요.',\n    select_email_unauthenticated_user:\n        '해당 이메일 주소가 아래 계정에 등록되어 있습니다.\\n인증을 원하는 계정을 선택해주세요.',\n    select_user: '계정을 선택해주세요.',\n    enter_password_withdraw: '회원탈퇴 신청을 위해 비밀번호를 입력해주세요.',\n    instruction_agree: '안내 사항에 동의해주세요.',\n    check_instructions: '위 안내 사항에 동의합니다.',\n    deleteAccount_2:\n        '회원탈퇴를 신청하신 30일 이후에는 회원정보와 작품/강의/학급/게시글/댓글/좋아요/관심 정보가 모두 삭제되며 복구가 불가능합니다.',\n    deleteAccount_1:\n        '회원탈퇴를 신청하신 30일 이내에 로그인하시면 회원탈퇴를 취소하실 수 있습니다.',\n    protect_account: '안전한 비밀번호로 내정보를 보호하세요.',\n    please_verify: '인증 메일을 발송하여 이메일 주소를 인증해 주세요.',\n    unverified_email: '이메일 주소가 인증되지 않았습니다.',\n    deleteAccount: '회원탈퇴 신청',\n    corporatePersonal: '개인정보 이전에 동의 합니다',\n    corporateTransferGuide: \"개인정보 양수자('엔트리' 웹사이트 운영자) 안내\",\n    corporateReciever: '개인정보를 이전 받은 자: 재단법인 커넥트',\n    corporateAddress: '커넥트 주소 및 연락처',\n    corporateAddress_1: '서울시 강남구 강남대로 382 메리츠타워 7층',\n    corporateConsent: '개인정보의 이전을 원치 않으시는 경우 ,동의 철회 방법',\n    corporateEmail: '계정에 등록된 이메일로 탈퇴 요청 메일 발송',\n    corporateAddition: '또한 , 영업 양도에 따라 약관 등이 아래와 같이 변경될 예정입니다.',\n    corporateApplicationDate: '적용시기 : 2017년 10월 29일',\n    corporateTargetChanges: '적용대상 및 변경사항 :',\n    corporateTarget: '적용대상',\n    corporateChanges: '변경사항',\n    corporateTerms: '엔트리 이용약관',\n    corporateOperator: '웹사이트 운영자의 명칭 변경',\n    corporateClassroomTerms: '학급 서비스 이용약관',\n    doAgreeWithClassroomTerms: '학급 서비스 이용약관에 동의합니다.',\n    doChangePassword: '나만 알수 있는 비밀번호로 변경해주세요.',\n    corporatePrivacyPolicy: '개인정보 처리방침',\n    corporateConsignment: '웹사이트 운영자의 명칭 변경 및 개인정보 위탁 업체 추가',\n    corporateEntrusted: '수탁업: NHN Technology Service(주)',\n    corporateConsignmentDetails: '위탁업무 내용: 서비스 개발 및 운영',\n    corporatePeriod: '보유기간 : 회원 탈퇴 시 혹은 위탁 계약 종료시 까지',\n    corporateChangeDate: '변경 적용일 : 2017년 10월 29일 부',\n    corporateWarning: '개인정보 이전에 동의해 주세요.',\n    corporateConfirm: '확인',\n    corporateTitle:\n        '안녕하세요. 엔트리교육연구소입니다. <br>“엔트리”를 이용하고 계신 회원 여러분께 깊은 감사의 말씀을 드립니다.<br> 엔트리교육연구소는 그동안 공익 목적으로 운영해오던 “엔트리” 웹사이트의 운영을<br> 네이버가 설립한 비영리 재단인 커넥트재단에 양도하기로 합의하였습니다. <br>앞으로 엔트리는 커넥트재단에서 공익 목적 하에 지속적으로 운영될 수 있도록 <br>할 것이며, 회원 여러분께서는 기존과 동일하게 엔트리를 이용하실 수 있습니다.<br> 웹사이트 제공 주체가 엔트리교육연구소에서 커넥트재단으로 변경됨에 따라 아래와 <br>같이 회원 개인 정보에 대한 이전이 있으며, 본 합의에 의해 실제 개인 정보의 위치가 <br>물리적으로 이동한 것은 아님을 알려드립니다. ',\n    textcoding_numberError_f:\n        '등록된 함수 중에 이름의 첫 글자가 숫자인 함수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1f: '등록된 함수 중에 이름이',\n    textcoding_bookedError_2f: '인 함수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_f:\n        \"등록된 함수 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    textcoding_numberError_v:\n        '등록된 변수 중에 이름의 첫 글자가 숫자인 변수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1v: '등록된 변수 중에 변수 이름이 ',\n    textcoding_bookedError_2v: ' 인 변수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_v:\n        \"등록된 변수 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    textcoding_numberError_l:\n        '등록된 리스트 중에 이름의 첫 글자가 숫자인 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1l: '등록된 리스트 중에 리스트 이름이',\n    textcoding_bookedError_2l: '인 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_l:\n        \"등록된 리스트 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    no_discuss_permission: '글을 읽을 권한이 없습니다',\n    delete_comment: '댓글을 삭제하시겠습니까?',\n    delete_article: '게시물을 삭제하시겠습니까?',\n    discuss_cannot_edit: '본인의 게시물이 아닙니다.',\n    discuss_extention: '실행파일은 첨부하실 수 없습니다.',\n    delete_discuss_picture: '사진을 삭제하시겠습니까?',\n    delete_discuss_file: '파일을 삭제하시겠습니까?',\n    discuss_save_question: '글을 저장하시겠습니까?',\n    discuss_cancle_question: '작성을 취소하시겠습니까?',\n    discuss_saved: '이(가) 저장되었습니다.',\n    discuss_no_write_permission: '현재 로그인된 계정으로는 글을 작성하실 수 없습니다.',\n    discuss_no_project_permission: '현재 로그인된 계정으로는 작품을 게시하실 수 없습니다.',\n    discuss_write_abuse_detected:\n        '짧은 시간안에 여러 글이 작성되었습니다.\\n1분 뒤에 다시 시도해주세요.',\n    contents_abuse_detected: '5분 뒤에 다시 시도해주세요.',\n    contents_abuse_detected_10: '10분 뒤에 다시 시도해주세요.',\n    discuss_new_write_abuse_warn:\n        '짧은 시간안에 새 글을 작성하는 경우 \\n게시글 작성이 제한될 수 있습니다. \\n이용에 주의하시길 바랍니다.',\n    discuss_write_abuse_warn:\n        '짧은 시간안에 여러 댓글을 작성하는 경우 \\n댓글 작성이 제한될 수 있습니다. \\n이용에 주의하시길 바랍니다.',\n    find_not_your_email: '올바른 이메일을 입력해주세요.',\n    search_lang: '검색',\n    search_title: '제목',\n    faq_desc: '엔트리를 이용하면서 궁금한 점들의 답변을 확인해보세요.',\n    faq_all: '전체보기',\n    faq_site: '사이트 이용',\n    faq_project: '작품 만들기',\n    faq_hardware: '하드웨어',\n    faq_offline: '오프라인',\n    faq_copyright: '저작권',\n    faq_title: '자주하는 질문',\n    faq: '자주하는 질문',\n    malicious_warning:\n        '불건전한 사진은 불러올 수 없습니다. 불건전한 사진이 아닌 경우 제안 및 건의에 해당 사진을 첨부하여 신고해주세요.',\n    fword_alert_msg: '욕설이나 불건전한 글은 게시할 수 없습니다.',\n    fword_alert_1: '주제와 무관한 욕설이나 악플은 게시할 수 없습니다.',\n    fword_alert_2: '불건전한 단어가 포함되어 있어, 대체 문장으로 게시 됩니다.',\n    fword_replace_1: '엔트리를 통해 누구나 쉽고 재미있게 소프트웨어를 배울 수 있어요.',\n    fword_replace_2: '소프트웨어 교육의 첫걸음, 엔트리.',\n    fword_replace_3: '재미있게 배우는 학습 공간 엔트리!',\n    fword_replace_4: '엔트리에서 공유와 협업을 통해 멋진 작품을 만들어요.',\n    fword_replace_5:\n        '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있게 개발된 소프트웨어 교육 플랫폼입니다.',\n    fword_replace_6: '엔트리와 함께 건강한 소프트웨어 교육 생태계를 조성해요!',\n    fword_replace_7: '엔트리에서 학습하고, 만들고, 공유하며 같이 성장해요.',\n    solve_quiz: '퀴즈 풀기',\n    submit_homework_first_title: '완성! 과제 제출하기',\n    submit_homework_first_content:\n        '멋진 작품이 완성되었습니다. 과제를 제출하세요. 마감 기한 전까지 다시 제출할 수 있습니다.',\n    submit_homework_again_title: '과제 다시 제출하기',\n    submit_homework_again_content: '이미 제출한 과제입니다.<br>과제를 다시 제출하시겠습니까?',\n    submit_homework_expired_title: '과제 제출 마감',\n    submit_homework_expired_content: '과제 제출이 마감되었습니다.',\n    done_study_title: '완성',\n    done_study_content: '만든 작품을 실행해 봅시다.',\n    featured_courses: '추천 강의 모음',\n    follow_along: '따라하기',\n    follow_along_desc: '차근차근 따라하며 다양한 작품을 만듭니다.',\n    do_quiz: '퀴즈풀기',\n    do_quiz_desc: '학습한 내용을 잘 이해했는지 퀴즈를 통해 확인합니다.',\n    challenge: '도전하기',\n    play: '도전하기',\n    challenge_desc: '주어진 문제를 스스로 해결하며 개념을 익힙니다.',\n    creste_freely: '자유롭게 만들기',\n    creste_freely_desc: '학습한 내용으로 나만의 작품을 자유롭게 만듭니다.',\n    entry_rc_desc:\n        '프로그래밍의 원리를 학습단계에 맞게 배울 수 있는 엔트리 강의 모음! 지금 시작해보세요!<br>따라하고, 도전하며 소프트웨어를 만들다 보면 어렵게 느껴졌던 프로그래밍의 원리도 쉽고 재미있게 다가옵니다!',\n    hw_deadline: '마감 일자',\n    rc_course_desc:\n        '프로그래밍의 원리를 학습단계에 맞게 배울 수 있도록 구성된 엔트리 강의 모음입니다.',\n    rc_course: '추천 강의 모음',\n    entry_rec_course: '엔트리 추천 강의 모음',\n    entry_rec_course_desc:\n        '누구나 쉽게 보고 따라하면서 재미있고 다양한 소프트웨어를 만들 수 있는 엔트리 강의를 소개합니다.',\n    guidance: '안내',\n    wait: '잠깐',\n    hint: '힌트',\n    concept_guide: '개념 톡톡',\n    group_quiz: '우리 반 퀴즈',\n    fail_check_hint: '앗… 실패! 다시 한 번 도전해보세요!<br>어려울 땐 [힌트]를 확인해보세요!',\n    sort_student: '학생별',\n    sort_lesson: '강의별',\n    sort_course: '강의 모음별',\n    student_progress: '우리 반 진도',\n    my_progress: '나의 진도',\n    lec_in_progress: '학습 중',\n    free_modal_asgn_over: '과제 제출이 마감되었습니다.',\n    free_submission_closed: '과제 제출 마감',\n    free_modal_asgn_submit_first:\n        '멋진 작품이 완성되었습니다! 과제를 제출하세요.<br>마감 기한 전까지 다시 제출 할 수 있습니다.',\n    asgn_submit: '완성! 과제 제출하기',\n    free_modal_content_resubmit: '이미 제출한 과제입니다.<br>과제를 다시 제출하시겠습니까?',\n    asgn_resubmit: '과제 다시 제출하기',\n    free_modal_content_complete: '멋진 작품이 완성되었습니다.',\n    guide_modal_content_complete: '만든 작품을 실행해 봅시다.',\n    success: '성공',\n    fail: '실패',\n    mission_modal_content_fail: '<br>어려울 땐 [힌트]를 확인해보세요!',\n    mission_modal_content_success: '만든 작품을 실행해 봅시다.',\n    in_progress: '진행중',\n    completed: '완료',\n    submitted: '제출 완료',\n    submission_closed: '마감',\n    progress: '진행 상황',\n    study_completed: '학습 완료',\n    view_course_desc: '코스웨어 설명 보기',\n    main_entry_starter: '기초부터! 엔트리 스타터',\n    main_entry_booster: '개념탄탄! 엔트리 부스터',\n    main_entry_master: '생각을 펼치는! 엔트리 마스터',\n    no_students_in_classroom:\n        '아직 등록된 학생이 없습니다.<br>학생을 직접 추가하거나, 초대해 보세요!',\n    lectures: '강의',\n    Lectures: '강의',\n    studentHomeworkList: '과제',\n    curriculums: '강의 모음',\n    Curriculums: '강의 모음',\n    quiz: '퀴즈',\n    no_added_group_contents_teacher:\n        '추가된 %1이(가) 없습니다. <br>우리 반 %1을(를) 추가해 주세요.',\n    no_added_group_contents_student:\n        '아직 올라온 %1이(가) 없습니다. 선생님이 %1을(를) 올려주시면, 학습 내용을 확인할 수 있습니다.',\n    side_project: '목표 작품',\n    custom_make_course_1: \"'오픈 강의 만들기> 강의 모음 만들기'에서\",\n    custom_make_course_2: '나만의 강의 모음을 만들어 보세요.',\n    custom_make_lecture_1: \"'오픈 강의 만들기'에서\",\n    custom_make_lecture_2: '나만의 강의를 만들어 보세요',\n    alert_enter_info: '수정할 정보를 입력해주세요.',\n    alert_enter_new_pwd: '기존 비밀번호와 다른 비밀번호를 입력해주세요.',\n    alert_match_pwd: '새로운 비밀번호와 재입력된 비밀번호가 일치하지 않습니다.',\n    alert_check_pwd: '비밀번호를 확인해주세요.',\n    alert_update_complete: '정보가 수정 되었습니다.',\n    no_group_contents_each_prefix: '우리반 ',\n    no_group_contents_each_suffix: ' 이(가) 없습니다.',\n    no_group_contents_all:\n        '학급에 올라온 컨텐츠가 없습니다.<br>학급 공유하기에<br>나만의 작품을 공유해보세요!',\n    hw_closed: '과제 마감',\n    tag_Lecture: '강의',\n    tag_Curriculum: '강의모음',\n    tag_Discuss: '공지',\n    count_ko: '개',\n    no_asgn_within_week: '1주일안에 제출되어야 하는 마감 임박한 과제가 없습니다.',\n    lecture_and_curriculum: '강의 / 강의 모음',\n    assignments_plural: '과제',\n    assignments_singular: '과제',\n    project_plural: '작품',\n    group_news: '새로운 소식',\n    stu_management: '학생 관리',\n    stu_management_camel: '학생 관리',\n    view_all: '전체 보기',\n    view_all_camel: '전체 보기',\n    view_contents_camel: '콘텐츠 보기',\n    view_contents: '콘텐츠 보기',\n    no_updated_news: '나의 학급에 올라온 새로운 소식이 없습니다.',\n    homework_soon_due: '곧 마감 과제',\n    new_homework: '최신 과제',\n    no_new_homework: '새로운 과제가 없습니다.',\n    student_plural: '학생',\n    discuss: '공지',\n    basic_project: '기본 작품',\n    no_permission: '권한이 없습니다.',\n    no_comment_write_permission: '현재 로그인된 계정으로는 답변을 작성하실 수 없습니다.',\n    original_curriculum_deleted: '원본 강의 모음이 삭제되었습니다.',\n    original_curriculum: '원본 강의 모음',\n    save_as_my_lecture: '복사본으로 저장하기 ',\n    delete_confirm: '삭제 알림',\n    lecture_open_as_copied: '오픈 강의 페이지에 올라간 모든 강의는 사본으로 생성되어 공개 됩니다.',\n    curriculum_open_as_copied:\n        '오픈 강의 모음 페이지에 올라간 모든 강의 모음은 사본으로 생성되어 공개 됩니다.',\n    lecture_save_as_copied_group:\n        '우리 반 강의 페이지에 올라간 모든 강의는 사본으로 생성되어 공개 됩니다.',\n    curriculum_save_as_copied_group:\n        '우리 반 강의 모음 페이지에 올라간 모든 강의 모음은 사본으로 생성되어 공개 됩니다.',\n    homework_save_as_copied_group:\n        '우리 반 과제 페이지에 올라간 모든 과제는 사본으로 생성되어 공개 됩니다.',\n    lecture_save_as_copied:\n        '내가 만든 강의 모음 안에 삽입된 구성 강의는 사본으로 생성되어 저장됩니다.',\n    done_project_save_as_copied:\n        '내가 만든 강의 안에 삽입된 완성 작품은 사본으로 생성되어 저장됩니다.',\n    textbook_project_can_not_applied:\n        '교과형 만들기(실과)로 만들어진 작품은 강의로 만들 수 없습니다.',\n    original_lecture_deleted: '원본 강의가 삭제되었습니다.',\n    original_lecture: '원본 강의',\n    lecture_save_as_mine_alert:\n        \"저장되었습니다.\\n저장된 강의는 '마이페이지> 나의 강의'에서 확인할 수 있습니다.\",\n    lecture_save_as_mine: '내 강의로 저장하기',\n    duplicate_username: '이미 입력한 아이디 입니다.',\n    share_your_project: '내가 만든 작품을 공유해 보세요',\n    not_available_student:\n        \"학급에서 발급된 '학급 아이디'입니다.\\n'엔트리 회원 아이디'를 입력해주세요.\",\n    login_instruction: '로그인 안내',\n    login_needed: '로그인 후 이용할 수 있습니다.',\n    login_as_teacher: '선생님 계정으로 로그인 후 이용할 수 있습니다.',\n    remove_my_storage:\n        '나의 보관함에서 삭제하시겠습니까? 삭제한 블록/오브젝트는 복구할 수 없습니다.',\n    submit_hw: '과제 제출하기',\n    success_goal: '목표성공',\n    choseok_final_result: '좋아 , 나만의 작품을 완성했어!',\n    choseok_fail_msg_timeout: '시간이 너무 많이 지나버렸어. 목표를 잘 보고 다시 한번 도전해봐!',\n    choseok_fail_msg_die:\n        '생명이 0이하인데 게임이 끝나지 않았어.\\n아래의 블록을 사용해서 다시 도전해 보는 건 어때?',\n    grade_1: '초급',\n    grade_2: '중급',\n    grade_3: '고급',\n    find_sally_title: '샐리를 찾아서',\n    save_sally_title: '샐리 구하기',\n    exit_sally_title: '샐리 탈출하기',\n    find_sally: '라인 레인저스의 힘을 모아 \\n강력한 악당 메피스토를 물리치고 샐리를 구해주세요!',\n    save_sally:\n        '메피스토 기지에 갇힌 샐리. \\n라인 레인저스가 장애물을 피해 샐리를 찾아갈 수 있도록\\n도와주세요!',\n    exit_sally:\n        '폭파되고 있는 메피스토 기지에서 \\n샐리와 라인 레인저스가 무사히 탈출할 수 있도록\\n도와주세요!',\n    go_next_mission: '다른 미션 도전하기',\n    share_my_project: '내가 만든 작품 공유하기',\n    share_certification: '인증서 공유하기',\n    print_certification: '인증서를 뽐내봐',\n    get_cparty_events: '내가 받은 인증서를 출력해 뽐내면 푸짐한 상품을 받을 수 있어요!',\n    go_cparty_events: '이벤트 참여하러 가기',\n    codingparty2016_blockHelper_1_title: '앞으로 가기',\n    codingparty2016_blockHelper_1_contents: '앞으로 가기',\n    codingparty2016_blockHelper_2_title: '앞으로 가기',\n    codingparty2016_blockHelper_2_contents: '회전하기',\n    codingparty2016_blockHelper_3_title: '앞으로 가기',\n    codingparty2016_blockHelper_3_contents: '돌 부수기',\n    codingparty2016_blockHelper_4_title: '앞으로 가기',\n    codingparty2016_blockHelper_4_contents: '횟수 반복하기',\n    codingparty2016_blockHelper_5_title: '앞으로 가기',\n    codingparty2016_blockHelper_5_contents: '꽃 던지기',\n    codingparty2016_goalHint_1:\n        '샐리를 구하기 위해서는 미네랄이 필요해! 미네랄을 얻으며 목적지까지 가보자!',\n    codingparty2016_goalHint_2: '구불구불한 길이 있네. 회전 블록을 사용하면 어렵지 않을 거야!',\n    codingparty2016_goalHint_3: '앞이 돌로 막혀있잖아? 돌을 부수며 목적지까지 가보자!',\n    codingparty2016_goalHint_4: '복잡한 길이지만 지금까지 배운 것들로 해결할 수 있어!',\n    codingparty2016_goalHint_5:\n        '앞으로 쭉 가는 길이잖아? 반복 블록을 사용하여 간단하게 해결해 보자!',\n    codingparty2016_goalHint_6: '미네랄을 모두 모아오자. 반복블록을 쓰면 쉽게 다녀올 수 있겠어!',\n    codingparty2016_goalHint_7:\n        '친구들이 다치지 않도록 꽃을 던져 거미집을 제거해야 해. 저 멀리 있는 거미집을 제거하고 목적지까지 가 보자.',\n    codingparty2016_goalHint_8:\n        '가는 길에 거미집이 많잖아? 거미집을 모두 제거하고 목적지까지 가 보자.',\n    codingparty2016_goalHint_9: '거미집 뒤쪽에 있는 미네랄을 모두 모아오자!',\n    codingparty2016_guide_1_1_contents:\n        '라인 레인저스 전사들이 샐리를 구할 수 있도록 도와줘! 전사들을 움직이기 위해서는 블록 명령어를 조립해야 해.\\n\\n① 먼저 미션 화면과 목표를 확인하고,\\n② 블록 꾸러미에서 필요한 블록을 가져와 “시작하기를 클릭했을 때“ 블록과 연결해.\\n③ 다 조립되면 ‘시작하기‘ 버튼을 눌러 봐! 블록이 위에서부터 순서대로 실행되며 움직일 거야.',\n    codingparty2016_guide_1_1_title: '라인 레인저스 전사들을 움직이려면?',\n    codingparty2016_guide_1_2_title: '목표 블록의 개수',\n    codingparty2016_guide_1_2_contents:\n        '① [안 칠해진 별]의 개수만큼 블록을 조립해 미션을 해결해보자. 목표 블록보다 더 많은 블록을 사용하면 별이 빨간색으로 바뀌니 정해진 개수 안에서 문제를 해결해 봐!\\n② 필요하지 않은 블록은 휴지통 또는 블록꾸러미에 넣어줘.',\n    codingparty2016_guide_1_3_title: \"'앞으로 가기' 블록을 사용하기\",\n    codingparty2016_guide_1_3_contents:\n        '< 앞으로 가기 > 는 앞으로 한 칸 이동하는 블록이야. \\n\\n여러 칸을 이동하기 위해서는 이 블록을 여러 번 연결해야 해.',\n    codingparty2016_guide_1_4_title: '미네랄 획득하기',\n    codingparty2016_guide_1_4_contents:\n        '[ 미네랄 ]이 있는 곳을 지나가면 미네랄을 획득할 수 있어\\n\\n화면에 있는 미네랄을 모두 획득하고 목적지에 도착해야만 다음 단계로 넘어갈 수 있어.',\n    codingparty2016_guide_1_5_title: '어려울 때 도움을 받으려면?',\n    codingparty2016_guide_1_5_contents:\n        '미션을 수행하다가 어려울 땐 3가지 종류의 도움말 버튼을 눌러 봐.\\n\\n\\n<안내> 지금 이 안내를 다시 보고 싶을 때!\\n<블록 도움말> 블록 하나하나가 어떻게 동작하는지 궁금할 때!\\n<맵 힌트> 이 단계를 해결하기 위한 힌트가 필요할 때!',\n    codingparty2016_guide_2_1_title: '회전 블록 사용하기',\n    codingparty2016_guide_2_1_contents:\n        '<오른쪽으로 돌기>와 <왼쪽으로 돌기>는 \\n제자리에서 90도 회전하는 블록이야. 방향만 회전하는 블록이야. \\n캐릭터가 바라보고 있는 방향을 기준으로 오른쪽인지 왼쪽인지 잘 생각해 봐!\\n',\n    codingparty2016_guide_3_1_title: '(문) 능력 사용하기',\n    codingparty2016_guide_3_1_contents:\n        '라인 레인저스 전사들을 각자의 능력을 가지고 있어.\\n나 [문] 은 <발차기하기> 로 바로 앞에 있는 [돌]을 부술 수 있어.\\n[돌을] 부수고 나면 막힌 길을 지나갈 수 있겠지?\\n화면에 있는 [돌]을 모두 제거해야만 다음 단계로 넘어갈 수 있어.\\n그렇지만 명심해! 아무 것도 없는 곳에 능력을 낭비해서는 안 돼!',\n    codingparty2016_guide_5_1_title: \"'~번 반복하기' 블록 사용하기\",\n    codingparty2016_guide_5_1_contents:\n        '똑같은 일을 반복해서 명령하는 건 매우 귀찮은 일이야.\\n이럴 땐 명령을 사용하면 훨씬 쉽게 명령을 내릴 수 있어.       \\n< [ ? ] 번 반복하기> 블록 안에 반복되는 명령 블록을 넣고  \\n[ ? ] 부분에 횟수를 입력하면 입력한 횟수만큼 같은 명령을 반복하게 돼.',\n    codingparty2016_guide_5_2_title: \"'~번 반복하기' 블록 사용하기\",\n    codingparty2016_guide_5_2_contents:\n        \"'< [ ? ] 번 반복하기>  블록 안에는 여러 개의 명령어를 넣을 수도 있으니 잘 활용해봐! \\n도착지에 도착했더라도 반복하기 블록 안에 있는 블록이 모두 실행돼.\\n 즉, 위 상황에서 목적지에 도착한 후에도 왼쪽으로 돈 다음에야 끝나는 거야!\",\n    codingparty2016_guide_7_1_title: '(코니) 능력 사용하기',\n    codingparty2016_guide_7_1_contents:\n        '나 ‘코니’는 <꽃 던지기>로 먼 거리에서도 앞에 있는 [거미집]을 없앨 수 있어.\\n[거미집]을 없애고 나면 막힌 길을 지나갈 수 있겠지?\\n화면에 있는 [거미집]을 모두 제거해야만 다음 단계로 넘어갈 수 있어.\\n그렇지만 명심해! 아무것도 없는 곳에 능력을 낭비해서는 안 돼!',\n    codingparty2016_guide_9_1_title: '조건 반복 블록 사용하기',\n    codingparty2016_guide_9_1_contents:\n        '반복하는 횟수를 세지 않아도, 어떤 조건을 만족할 때까지 행동을 반복할 수 있어.\\n< [목적지]에 도착할 때까지 반복하기 > 블록 안에 반복되는 명령 블록을 넣으면 [목적지]에 도착할 때까지 명령을 반복해.',\n    codingparty2016_guide_9_2_title: '조건 반복 블록 사용하기',\n    codingparty2016_guide_9_2_contents:\n        '<[목적지]에 도착할 때까지 반복하기> 블록 안에는 여러 개의 명령어를 넣을 수도 있으니 잘 활용해봐!\\n 도착지에 도착했더라도 반복하기 블록 안에 있는 블록이 모두 실행 돼. 즉, 위 상황에서 목적지에 도착한 후에도 왼쪽으로 돈 다음에야 끝나는 거야!',\n    find_interesting_lesson: \"'우리 반 강의'에서 다양한 강의를 만나보세요!\",\n    find_interesting_course: \"'우리 반 강의 모음'에서 다양한 강의를 만나보세요!\",\n    select_share_settings: '공유 공간을 선택해주세요.',\n    faq_banner_title: '자주하는 질문 안내',\n    check_out_faq: '궁금한 점을 확인하세요.',\n    faq_banner_content:\n        '엔트리에 대해 궁금하세요?<br />자주하는 질문을 통해 답변을 드리고 있습니다.<br />지금 바로 확인하세요!',\n    faq_banner_button: '자주하는 질문<br />바로가기',\n    major_updates: '주요 업데이트 안내',\n    check_new_update: '엔트리의 변화를 확인하세요.',\n    major_updates_notification: '엔트리의 주요 변경사항을 공지를 통해 안내해 드리고 있습니다.',\n    find_out_now: '지금 바로 확인하세요!',\n    offline_hw_program: '오프라인 & 하드웨어 연결 프로그램',\n    read_more: '자세히 보기',\n    sample_project: '예시 작품',\n    not_supported_function: '이 기기에서는 지원하지 않는 기능입니다.',\n    offline_download_confirm:\n        '엔트리 오프라인 버전은 PC에서만 이용가능합니다. 다운로드 하시겠습니까?',\n    hardware_download_confirm: '엔트리 하드웨어는 PC에서만 이용가능합니다. 다운로드 하시겠습니까?',\n    copy_text: '텍스트를 복사하세요.',\n    select_openArea_space: '작품 공유 공간을 선택해 주세요',\n    mission_guide: '미션 해결하기 안내',\n    of: ' 의',\n    no_results_found: '검색 결과가 없습니다.',\n    upload_pdf: 'PDF 자료 업로드',\n    select_basic_project: '작품 선택하기',\n    try_it_out: '만들어 보기',\n    go_boardgame: '엔트리봇 보드게임 바로가기',\n    go_cardgame: '엔트리봇 카드게임 바로가기',\n    go_solve: '미션으로 학습하기',\n    go_ws: '엔트리 만들기 바로가기',\n    go_arts: '엔트리 공유하기 바로가기',\n    group_delete_alert:\n        '학급을 삭제하면, 해당 학급에서 발급한 학생임시계정을 포함하여 관련한 모든 자료가 삭제됩니다.\\n정말 삭제하시겠습니까?',\n    view_arts_list: '다른 작품 보기',\n    hw_submit_confirm_alert: '과제가 제출 되었습니다.',\n    hw_submit_alert: '과제를 제출 하시겠습니까? ',\n    hw_submit_alert2: '과제를 제출하시겠습니까? 제출 시 학습 완료한 학습 단계까지만 제출이 됩니다.',\n    hw_submit_cannot: '제출 할 수 없는 과제입니다.',\n    see_other_missions: '다른 미션 보기',\n    project: ' 작품',\n    marked: ' 관심',\n    group: '학급',\n    lecture: '강의',\n    Lecture: '강의',\n    curriculum: '강의 모음',\n    Curriculum: '강의 모음',\n    studying: '학습 중인',\n    open_only_shared_lecture:\n        '<b>오픈 강의</b> 페이지에 <b><공개></b> 한 강의만 불러올 수 있습니다. 불러오고자 하는 <b>강의</b>의 <b>공개여부</b>를 확인해 주세요.',\n    already_exist_group: '이미 존재하는 학급 입니다.',\n    cannot_invite_you: '자기 자신을 초대할 수 없습니다.',\n    apply_original_image: '원본 이미지 그대로 적용하기',\n    draw_new_ques: '새로 그리기 페이지로\\n이동하시겠습니까?',\n    draw_new_ques_1: '그림을 그려 오브젝트로 저장할 수 있습니다.',\n    draw_new_ques_2: '그리기 화면으로 이동하시겠습니까?',\n    draw_new_go: '이동하기',\n    draw_new_stay: '이동하지 않기',\n    file_upload_warn_title_image:\n        '아래와 같은 그림은 이용약관 및 관련 법률에 의해 제재를 받으실 수 있습니다.',\n    file_upload_warn_desc_image:\n        '폭력적이고 잔인한 그림<br>선정적인 신체노출 그림<br>불쾌감을 주거나 혐오감을 일으키는 그림<br>무단 사용이 금지된 저작권의 그림',\n    file_upload_warn_title_sound:\n        '아래와 같은 소리는 이용약관 및 관련 법률에 의해 제재를 받을 수 있습니다.',\n    file_upload_warn_desc_sound:\n        '폭력적이고 잔인한 소리<br>선정적인 내용의 소리<br>불쾌감을 주거나 혐오감을 일으키는 소리<br>무단 사용이 금지된 저작권의 소리',\n    file_upload_warn_title_table:\n        '아래와 같은 데이터는 이용약관 및 관련 법률에 의해 제재를 받으실 수 있습니다.',\n    file_upload_warn_desc_table:\n        '폭력적이고 잔인한 내용의 데이터<br>선정적인 내용의 데이터<br>불쾌감을 주거나 혐오단어가 포함된 데이터<br>무단 사용이 금지된 저작권의 데이터',\n    file_upload_warn_link: '저작권에 대해 알아보기',\n    file_upload_desc_1: '이런 그림은 \\n 안돼요!',\n    file_upload_desc_2: '폭력적이고 잔인한 그림',\n    file_upload_desc_3: '선정적인 신체노출 그림',\n    file_upload_desc_4: '불쾌감을 주거나 혐오감을 일으키는 그림',\n    file_upload_desc_5:\n        '* 위와 같은 내용은 이용약관 및 관련 법률에 의해 제재를 받으실 수 있습니다.',\n    picture_upload_warn_old: '10MB 이하의 jpg, png, bmp 형식의 파일을 추가할 수 있습니다.',\n    sprite_upload_warn_old:\n        '10MB 이하의 jpg, png, bmp 이미지 또는 eo 형식의 오브젝트를 추가할 수 있습니다.',\n    picture_upload_warn_1:\n        '10MB 이하의 jpg, png, bmp, svg 형식의 파일을 추가할 수 있습니다.\\njpg, png, bmp 형식은 비트맵 모드, svg 형식은 벡터 모드로 편집됩니다.',\n    table_upload_warn_1:\n        '10MB 이하의 csv, xls(x) 형식의 파일을 추가할 수 있습니다. xls(x) 형식의 경우, 함수 문장이 그대로 출력됩니다.',\n    sprite_upload_warn:\n        '10MB 이하의 jpg, png, bmp, svg 이미지 또는 eo 형식의 오브젝트를 추가할 수 있습니다.',\n    sound_upload_warn_1: '10MB 이하의 mp3 형식의 파일을 추가할 수 있습니다.',\n    sound_edit_warn: '기다려 주세요!<br>새로운 소리 편집 기능을 연구 중입니다.',\n    file_upload_loading: '로딩중',\n    lesson_by_teacher: '선생님들이 직접 만드는 강의입니다.',\n    delete_group_art: '학급 공유하기 목록에서 삭제 하시겠습니까?',\n    elementary_short: '초등',\n    middle_short: '중등',\n    grade_34: '3-4학년',\n    grade_56: '5-6학년',\n    grade_78: '중등',\n    share_lesson: '강의 공유하기',\n    share_course: '강의 모음 공유하기',\n    from_list_ko: '을(를)',\n    comming_soon: '준비중입니다.',\n    no_class_alert:\n        \"선택된 학급이 없습니다. 학급이 없는경우 '나의 학급' 메뉴에서 학급을 만들어 주세요.\",\n    students_cnt: '명',\n    defult_class_alert_1: '',\n    defult_class_alert_2: '을(를) \\n 기본학급으로 설정하시겠습니까?',\n    default_class: '기본학급입니다.',\n    enter_hw_name: '과제의 제목을 입력해 주세요.',\n    hw_limit_20: '과제는 20개 까지만 만들수 있습니다.',\n    stu_example: '예)\\n 홍길동\\n 홍길동\\n 홍길동',\n    hw_description_limit_200: '생성 과제에 대한 안내 사항을 입력해 주세요. (200자 이내)',\n    hw_title_limit_50: '과제명을 입력해 주세요. (50자 이내)',\n    create_project_class_1: \"'만들기 > 작품 만들기' 에서\",\n    create_project_class_2: '학급에 공유하고 싶은 작품을 만들어 주세요.',\n    create_lesson_assignment_1: \"'만들기> 오픈 강의 만들기'에서 \",\n    create_lesson_assignment_2: '우리 반 과제에 추가하고 싶은 강의를 만들어 주세요.',\n    i_make_lesson: '내가 만드는 강의',\n    lesson_to_class_1: \"'학습하기>오픈 강의'에서 우리반\",\n    lesson_to_class_2: '과제에 추가하고 싶은 강의를 관심강의로 등록해 주세요.',\n    studying_students: '학습자',\n    lessons_count: '강의수',\n    group_out: '나가기',\n    enter_group_code: '학급코드 입력하기',\n    no_group_invite: '학급 초대가 없습니다.',\n    done_create_group: '개설이 완료되었습니다.',\n    set_default_group: '기본학급 설정',\n    edit_group_info: '학급 정보 관리',\n    edit_done: '수정 완료되었습니다.',\n    alert_group_out: '학급을 정말 나가시겠습니까?',\n    lesson_share_cancel: '강의 공유 취소',\n    project_share_cancel: '작품 공유 취소',\n    lesson_share_cancel_alert: '작품을 비공개로 하시겠습니까?',\n    course_share_cancel: '강의 모음 공유 취소',\n    select_lesson_share: '강의 공유 공간 선택',\n    select_project_share: '작품 공유 선택',\n    select_lesson_share_policy_1: '강의를 공유할',\n    select_lesson_share_policyAdd: '공간을 선택해 주세요',\n    select_lesson_share_project_1: '작품을 공유할 공간과',\n    select_lesson_share_policy_2: '저작권 정책을 확인해 주세요.',\n    select_lesson_share_area: '강의 공유 공간을 선택해 주세요',\n    select_project_share_area: '작품 공유 공간을 선택해 주세요',\n    lesson_share_policy: '강의 공유에 따른 엔트리 저작권 정책 동의',\n    project_share_policy: '작품 공유에 따른 엔트리 저작권 정책 동의',\n    alert_agree_share: '공개하려면 엔트리 저작물 정책에 동의하여야 합니다.',\n    alert_agree_all: '모든 항목에 동의해 주세요.',\n    select_course_share: '강의 모음 공유 공간 선택',\n    select_course_share_policy_1: '강의 모음을 공유할',\n    select_course_share_policy_2: '저작권 정책을 확인해 주세요.',\n    select_course_share_area: '강의 모음 공유 공간을 선택해 주세요',\n    course_share_policy: '강의 모음 공유에 따른 엔트리 저작권 정책 동의',\n    issued: '발급',\n    code_expired: \"코드가 만료되었습니다. '코드재발급' 버튼를 누르세요.\",\n    accept_class_invite: '학급초대 수락하기',\n    welcome_class: '학급에 오신것을 환영합니다.',\n    enter_info: '자신의 정보를 입력해주세요.',\n    done_group_signup: '학급 가입이 완료되었습니다.',\n    enter_group_code_stu: '선생님께 받은 코드를 입력해주세요.',\n    text_limit_50: '50글자 이하로 작성해 주세요.',\n    enter_class_name: '학급 이름을 입력해 주세요.',\n    enter_grade: '학년을 입력해 주세요.',\n    enter_class_info: '학급소개를 입력해 주세요.',\n    student_dup: '은(는) 이미 학급에 존재합니다.',\n    select_stu_print: '출력할 학생을 선택하세요.',\n    class_id_not_exist: '학급 ID가 존재하지 않습니다.',\n    error_try_again: '오류 발생. 다시 한 번 시도해 주세요.',\n    error_forbidden: '권한이 없습니다.',\n    code_not_available: '유효하지 않은 코드입니다.',\n    gnb_create_lessons: '오픈 강의 만들기',\n    study_lessons: '강의 학습하기',\n    lecture_help_1:\n        '학습을 시작할 때, 사용할 작품을 선택해 주세요. 선택한 작품으로 학습자가 학습을 시작하게 됩니다.',\n    lecture_help_2: '이도움말을 다시 보시려면 위 버튼을 클릭해 주세요.',\n    lecture_help_3: '오브젝트 추가하기가 없으면새로운 오브젝트를 추가하거나 삭제 할 수 없습니다.',\n    lecture_help_4: '학습도중에 PDF자료보기를 통해 학습에 도움을 받을 수 있습니다.',\n    lecture_help_5: '학습에 필요한 블록들만 선택해주세요. 선택하지 않은 블록은 숨겨집니다.',\n    lecture_help_6: '블록코딩과 엔트리파이선 중에 선택하여 학습환경을 구성할 수 있습니다.',\n    lecture_finish_popup_title: '학습 다시하기',\n    lecture_finish_popup_content_1: '실습완료한 단계를<br>처음부터 다시 실습하시겠습니까?',\n    lecture_finish_popup_content_2: '* 다시 실습해도 실습 완료 상태는 유지됩니다.',\n    lecture_start_title: '학습 시작',\n    lecture_goal_title: '학습 목표',\n    lecture_goal_content: '무엇을 배울지 알아볼까요?',\n    lecture_prepare_title: '학습 준비',\n    lecture_summary_title: '학습 정리',\n    lecture_summary_content: '배운 내용을 정리해 봅시다.',\n    lecture_quiz_title: '확인 문제',\n    lecture_quiz_content: '확인 문제를 통해 배운 내용을 점검해 봅시다.',\n    lecture_quiz_check_answer: '정답확인',\n    default_hint_title: '어떻게 만들까?',\n    only_pdf: '.pdf형식의 파일만 입력 가능합니다.',\n    enter_project_video: '적어도 하나의 작품이나 영상을 입력하세요.',\n    enter_title: '제목을 입력하세요.',\n    enter_recommanded_grade: '추천 학년을 입력하세요.',\n    enter_level_diff: '난이도를 입력하세요.',\n    enter_time_spent: '소요시간을 입력하세요.',\n    enter_shared_area: '적어도 하나의 공유 공간을 선택하세요.',\n    enter_goals: '학습목표를 입력하세요.',\n    enter_lecture_description: '강의 설명을 입력하세요.',\n    enter_curriculum_description: '강의 모음 설명을 입력하세요.',\n    first_page: '처음 입니다.',\n    last_page: '마지막 입니다.',\n    alert_duplicate_lecture: '이미 등록된 강의는 다시 등록할 수 없습니다.',\n    enter_lesson_alert: '하나 이상의 강의를 등록해주세요.',\n    open_edit_lessons: '편집할 강의를 불러오세요.',\n    saved_alert: '이(가) 저장되었습니다.',\n    select_lesson_type: '어떤 학습과정을 만들지 선택해 주세요 ',\n    create_lesson: '강의 만들기',\n    create_lesson_desc_1: '원하는 학습 목표에 맞춰',\n    create_lesson_desc_2: '단일 강의를 만들어',\n    create_lesson_desc_3: '학습에 활용합니다.',\n    create_courseware: '강의 모음 만들기',\n    create_courseware_desc_1: '학습 과정에 맞춰 여러개의 강의를',\n    create_courseware_desc_2: '하나의 코스로 만들어',\n    create_courseware_desc_3: '학습에 활용합니다.',\n    create_open_lesson: '오픈 강의 만들기 ',\n    enter_lesson_info: '강의 정보 입력 ',\n    select_lesson_feature: '학습 기능 선택 ',\n    check_info_entered: '입력 정보 확인 ',\n    enter_lefo_lesson_long: '강의를 구성하는 정보를 입력해 주세요.',\n    lesson_info_desc:\n        '학습자가 학습하기 화면에서 사용할 기능과 작품을 선택함으로써, 학습 목표와 내용에 최적화된 학습환경을 구성할 수 있습니다.',\n    provide_only_used: '완성된 작품에서 사용된 블록만 불러오기',\n    see_help: '도움말 보기',\n    select_done_project_1: '학습자가 목표로 설정할',\n    select_done_project_2: '완성 작품',\n    select_done_project_3: '을 선택해 주세요.',\n    select_project: '나의 작품 또는 관심 작품을 불러옵니다. ',\n    youtube_desc: '유튜브 공유 링크를 통해 원하는 영상을 넣을 수 있습니다.',\n    lesson_video: '강의 영상',\n    lesson_title: '강의 제목',\n    recommended_grade: '추천학년',\n    selection_ko: '선택',\n    selection_en: '',\n    level_of_diff: '난이도',\n    select_level_of_diff: '난이도 선택',\n    enter_lesson_title: '강의 제목을 입력해 주세요(30자 이내)',\n    select_time_spent: '소요시간 선택 ',\n    time_spent: '소요시간',\n    lesson_overview: '강의설명',\n    upload_materials: '학습 자료 업로드',\n    open: '불러오기',\n    cancel: '취소하기',\n    upload_lesson_video: '강의 영상 업로드',\n    youtube_upload_desc: '유튜브 공유링크를 통해 보조영상을 삽입할 수 있습니다. ',\n    cancel_select: '선택 취소하기',\n    select_again: '다시 선택하기',\n    goal_project: '완성작품',\n    upload_study_data:\n        '학습하기 화면에서 볼 수 있는 학습자료를 업로드해주세요. 학습자가 업로드된 학습자료의 내용을 확인하며 학습할 수 있습니다. ',\n    upload_limit_20mb: '20MB 이하의 파일을 올려주세요.',\n    expect_time: '예상 소요 시간',\n    course_videos: '보조 영상',\n    enter_courseware_info: '강의 모음 정보 입력 ',\n    enter_course_info: '강의 모음을 소개하는 정보를 입력해 주세요 ',\n    select_lessons_for_course: '강의 모음을 구성하는 강의를 선택해 주세요.',\n    course_build_desc_1: '강의는',\n    course_build_desc_2: '최대30개',\n    course_build_desc_3: '등록할 수 있습니다.',\n    lseeon_list: '강의 목록 보기',\n    open_lessons: '강의 불러오기',\n    course_title: '강의 모음 제목',\n    title_limit_30: '강의 모음 제목을 입력해 주세요(30자 이내) ',\n    course_overview: '강의 모음 설명',\n    charactert_limit_200: '200자 이내로 작성할 수 있습니다.',\n    edit_lesson: '강의 편집',\n    courseware_by_teacher: '선생님들이 직접 만드는 강의 모음입니다.',\n    select_lessons: '구성 강의 선택',\n    check_course_info: '강의 모음을 구성하는 정보가 올바른지 확인해 주세요.',\n    select_share_area: '공유 공간 선택',\n    upload_sub_project: '목표 작품 업로드',\n    file_download: '첨부파일 다운로드',\n    file_remove: '첨부파일 삭제',\n    check_lesson_info: '강의를 구성하는 정보가 올바른지 확인해 주세요.',\n    share_area: '공유 공간',\n    enter_sub_project: '엔트리 보조 프로젝트를 등록해 주세요.',\n    lms_hw_title: '과제 제목',\n    lms_hw_ready: '준비',\n    lms_hw_progress: '진행중',\n    lms_hw_complete: '완료',\n    lms_hw_not_submit: '미제출',\n    lms_hw_closed: '제출마감',\n    submission_condition: '진행중인 과제만 제출이 가능합니다.',\n    submit_students_only: '학생만 과제를 제출할 수 있습니다.',\n    want_submit_hw: '과제를 제출하시겠습니까?',\n    enter_correct_id: '올바른 아이디를 입력해 주세요.',\n    id_not_exist: '아이디가 존재하지 않습니다. ',\n    agree_class_policy: '학급 서비스 이용약관에 동의해 주세요.',\n    delete_class: '학급 삭제',\n    type_stu_name: '학생 이름을 입력해주세요. ',\n    invite_from_1: '에서',\n    invite_from_2: '님을 초대하였습니다. ',\n    lms_pw_alert_1: '학급에 소속되면, 선생님 권한으로',\n    lms_pw_alert_2: '비밀번호 재발급이 가능합니다.',\n    lms_pw_alert_3: '선생님의 초대가 맞는지 한번 더 확인해주세요.',\n    invitation_accepted: '초대 수락이 완료되었습니다!',\n    cannot_issue_pw: '초대를 수락하지 않았으므로 비밀번호를 발급할 수 없습니다.',\n    start_me_1: '<월간 엔트리>와 함께',\n    start_me_2: 'SW교육을 시작해보세요!',\n    monthly_desc_1: '<월간 엔트리>는 소프트웨어 교육에 익숙하지 않은 선생님들도 쉽고 재미있게',\n    monthly_desc_2: '소프트웨어 교육을 하실 수 있도록 만들어진 SW교육 잡지입니다.',\n    monthly_desc_3: '매월 재미있는 학습만화와 함께 하는 SW 교육 컨텐츠를 만나보세요!',\n    monthly_desc_4: '* 월간엔트리는 2015년 11월 ~ 2016년 5월까지 발행 후 중단되었습니다.',\n    monthly_desc_5: '엔트리의 교육자료는 교육자료 페이지에서 만나보세요.',\n    monthly_entry: '월간 엔트리',\n    me_desc_1: '매월 발간되는 무료 소프트웨어 교육잡지',\n    me_desc_2: '월간엔트리를 만나보세요!',\n    solve_desc_1: '게임을 하듯 미션을 해결하며',\n    solve_desc_2: '소프트웨어의 기본 원리를 배워보세요!',\n    playSw_desc_1: 'EBS 방송영상, 특별영상을 통해',\n    playSw_desc_2: '소프트웨어를 배워보세요!',\n    recommended_lessons: '추천 강의 모음',\n    recommended_lessons_1:\n        '따라하고, 도전하고, 퀴즈도 풀며 재미있게 엔트리 프로그래밍을 배워보세요!',\n    recommended_lessons_2: '추천 강의 모음을 만나보세요!',\n    offline_top_desc_1: '오프라인 버전의 저장 기능이 향상되고 보안이 강화되었습니다.',\n    offline_top_desc_2: '지금 바로 다운받으세요',\n    offline_main_desc: '엔트리 오프라인 에디터 업데이트!!',\n    art_description:\n        '엔트리로 만든 작품을 공유하는 공간입니다. 작품을 만들고 공유에 참여해 보세요.',\n    art_description_1: '엔트리로 총 ',\n    art_description_2: '개의 작품이 만들어졌습니다. 작품을 만들고 공유해 보세요.',\n    study_index:\n        '엔트리에서 제공하는 주제별, 학년별 학습과정을 통해 차근차근 소프트웨어를 배워보세요!',\n    study_for_beginner: '처음 시작하는 사람들을 위한 엔트리 첫걸음',\n    entrybot_desc_3: '안내에 따라 블록 명령어를 조립하여',\n    entrybot_desc_4: '엔트리봇을 학교에 데려다 주세요.',\n    move_entrybot: '엔트리봇 움직이기',\n    can_change_entrybot_1: '블록 명령어로 엔트리봇의 색을 바꾸거나',\n    can_change_entrybot_2: '말을 하게 할 수도 있어요.',\n    learning_process_by_topics: '주제별 학습과정',\n    show_detail: '자세히 보기',\n    solve_mission: '미션 해결하기',\n    solve_mission_desc_1: '게임을 하듯 미션을 해결하며 프로그래밍의 원리를 익혀보세요!',\n    solve_mission_desc_2:\n        '미로 속의 엔트리봇을 목적지까지 움직이며 순차, 반복, 선택, 비교연산 등의 개념을 자연스럽게 익힐 수 있어요.',\n    learning_process_by_grades: '학년별 학습과정',\n    learning_process_by_grades_sub1:\n        '4가지 유형으로 쉽고 재미있게 배우는 프로그래밍의 원리! 지금 시작해보세요!',\n    e3_to_e4: '초등 3-4 학년',\n    e5_to_e6: '초등 5-6 학년',\n    m1_to_m3: '중등 이상',\n    make_using_entry: '엔트리로 만들기',\n    make_using_entry_desc_1: '블록을 쌓아 여러 가지 소프트웨어를 만들어보세요!',\n    make_using_entry_desc_2:\n        '제공되는 교재를 다운받아 차근차근 따라하다보면 애니메이션, 미디어아트, 게임 등 다양한 작품을 만들 수 있어요.',\n    make_through_ebs_1: 'EBS 방송영상으로 소프트웨어를 배워보세요.',\n    make_through_ebs_2:\n        '방송영상은 물론, 차근차근 따라 할 수 있는 특별영상과 함께 누구나 쉽게 다양한 소프트웨어를 만들 수 있어요.',\n    support_block_js: '블록 코딩과 자바스크립트 언어를 모두 지원합니다.',\n    study_ebs_title_1: '순서대로! 차례대로!',\n    study_ebs_desc_1: '[실습] 엔트리봇의 심부름',\n    study_ebs_title_2: '쉽고 간단하게!',\n    study_ebs_desc_2: '[실습] 꽃송이 만들기',\n    study_ebs_title_3: '언제 시작할까?',\n    study_ebs_desc_3: '[실습] 동물가족 소개',\n    study_ebs_title_4: '다른 선택, 다른 결과!',\n    study_ebs_desc_4: '[실습] 텔레파시 게임',\n    study_ebs_title_5: '정보를 담는 그릇',\n    study_ebs_desc_5: '[실습] 덧셈 로봇 만들기',\n    study_ebs_title_6: '요모조모 따져 봐!',\n    study_ebs_desc_6: '[실습] 복불복 룰렛',\n    study_ebs_title_7: '번호로 부르면 편해요!',\n    study_ebs_desc_7: '[실습] 나만의 버킷리스트',\n    study_ebs_title_8: '무작위 프로그램을 만들어라!',\n    study_ebs_desc_8: '[실습] 무작위 캐릭터 만들기',\n    study_ebs_title_9: '어떻게 찾을까?',\n    study_ebs_desc_9: '[실습] 도서관 책 검색',\n    study_ebs_title_10: '줄을 서시오!',\n    study_ebs_desc_10: '[실습] 키 정렬 프로그램',\n    event: '이벤트',\n    divide: '분기',\n    condition: '조건',\n    random_number: '무작위수',\n    search: '탐색',\n    sorting: '정렬',\n    parallel: '병렬',\n    signal: '신호',\n    input_output: '입출력',\n    sequential: '순차',\n    repeat: '반복',\n    choice: '선택',\n    repeat_advanced: '반복(횟수+조건)',\n    function: '함수',\n    compare_operation: '비교연산',\n    arithmetic: '산술연산',\n    entry_recommended_mission: '엔트리 추천 미션',\n    more_mission: '더 많은 미션 보러가기',\n    line_rangers_title: '라인레인저스와\\n샐리 구하기',\n    line_rangers_content: '메피스토 기지에 갇힌\\n샐리를 구해주세요!',\n    pinkbean_title_string_basic: '메이플스토리 초급 헤네시스',\n    pinkbean_title_string_intermediate: '메이플스토리 중급 엘리니아',\n    pinkbean_title_string_advanced: '메이플스토리 고급 엘나스',\n    pinkbean_title: '핑크빈과 함께 신나는\\n메이플 월드로!',\n    pinkbean_content: '핑크빈이 메이플 월드 모험을\\n무사히 마칠 수 있도록 도와주세요.',\n    entrybot_school: '엔트리봇 학교 가는 길',\n    entrybot_school_desc_1: '엔트리봇이 책가방을 챙겨 학교에',\n    entrybot_school_desc_2: '도착할 수 있도록 도와주세요!',\n    robot_factory: '로봇 공장',\n    robot_factory_desc_1: '로봇공장에 갇힌 엔트리봇!',\n    robot_factory_desc_2: '탈출하기 위해 부품을 모두 모아야해요.',\n    electric_car: '전기 자동차',\n    electric_car_desc_1: '엔트리봇 자동차가 계속 앞으로 나아갈 수',\n    electric_car_desc_2: '있도록 연료를 충전해 주세요.',\n    forest_adventure: '숲속 탐험',\n    forest_adventure_desc_1: '엔트리봇 친구가 숲속에 갇혀있네요!',\n    forest_adventure_desc_2: '친구를 도와주세요.',\n    town_adventure: '마을 탐험',\n    town_adventure_desc_1: '배고픈 엔트리봇을 위해 마을에 있는',\n    town_adventure_desc_2: '연료를 찾아주세요.',\n    space_trip: '우주 여행',\n    space_trip_desc_1: '우주탐사를 마친 엔트리봇!',\n    space_trip_desc_2: '지구로 돌아갈 수 있도록 도와주세요.',\n    learn_programming_mission: '미션을 해결하며 배우는 프로그래밍',\n    make_open_lecture: '오픈 강의 만들기',\n    group_created: '만든 학급',\n    group_signup: '가입한 학급',\n    delete_from_list: '을(를) 목록에서 삭제하시겠습니까?',\n    delete_from_list_en: '',\n    lecture_collection: '강의 모음',\n    edit_mypage_profile: '자기소개 정보 관리',\n    main_image: '메인 이미지',\n    edit_profile_success: '반영되었습니다.',\n    no_project_1: '내가 만든 작품이 없습니다.',\n    no_project_2: '지금 작품 만들기를 시작해보세요!',\n    empty_project_1: '아직 만들어진 작품이 없습니다.',\n    no_marked_project_1: '관심 작품이 없습니다.',\n    no_marked_group_project_1: '학급 관심 작품이 없습니다.',\n    no_marked_project_2: \"'작품 공유하기'에서 다양한 작품을 만나보세요!\",\n    no_markedGroup_project_2: \"'학급 공유하기'에서 다양한 작품을 만나보세요!\",\n    view_project_all: '작품 구경하기',\n    no_lecture_1: '내가 만든 강의가 없습니다.',\n    empty_lecture_1: '아직 만들어진 강의가 없습니다.',\n    no_lecture_2: \"'오픈 강의 만들기'에서 강의를 만들어보세요!\",\n    no_marked_lecture_1: '관심 강의가 없습니다.',\n    no_marked_group_lecture_1: '학급 관심 강의가 없습니다.',\n    no_marked_lecture_2: \"'오픈 강의'에서 다양한 강의를 만나보세요!\",\n    view_lecture: '강의 살펴보기',\n    no_studying_lecture_1: '학습 중인 강의가 없습니다.',\n    no_studying_lecture_2: \"'오픈 강의'에서 학습을 시작해보세요!\",\n    no_lecture_collect_1: '내가 만든 강의 모음이 없습니다.',\n    empty_lecture_collect_1: '아직 만들어진 강의 모음이 없습니다.',\n    no_lecture_collect_2: \"'오픈 강의 모음 만들기'에서 강의 모음을 만들어보세요!\",\n    make_lecture_collection: '강의 모음 만들기',\n    no_marked_lecture_collect_1: '관심 강의 모음이 없습니다.',\n    no_marked_lecture_group_collect_1: '학급 관심 강의 모음이 없습니다.',\n    no_marked_lecture_collect_2: \"'오픈 강의'에서 다양한 강의를 만나보세요!\",\n    view_lecture_collection: '강의 모음 살펴보기',\n    no_studying_lecture_collect_1: '학습 중인 강의 모음이 없습니다.',\n    no_studying_lecture_collect_2: \"'오픈 강의'에서 학습을 시작해보세요!\",\n    my_lecture: '나의 강의',\n    markedGroup: '학급 관심',\n    markedGroup_lecture: '학급 관심 강의',\n    markedGroup_curriculum: '학급 관심 강의모음',\n    marked_lecture: '관심 강의',\n    marked_lecture_collection: '나의 관심 강의 모음',\n    marked_marked_curriculum: '관심 강의 모음',\n    studying_lecture: '학습 중인 강의',\n    completed_lecture: '학습 완료 강의',\n    my_lecture_collection: '나의 강의 모음',\n    my: '나의',\n    studying_lecture_collection: '학습 중인 강의 모음',\n    completed_lecture_collection: '학습 완료한 강의 모음',\n    my_curriculum: '나의 강의 모음',\n    studying_curriculum: '학습 중인 강의 모음',\n    completed_curriculum: '학습 완료한 강의 모음',\n    materialCC:\n        '엔트리에서 제공하는 모든 교육 자료는 CC-BY 2.0 라이선스에 따라 자유롭게 이용할 수 있습니다.',\n    materialccby_new:\n        '엔트리의 교육자료는 CC-BY 2.0 라이선스에 따라 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    entry_copyright_info: '엔트리 저작권 가이드 보기',\n    pdf: 'PDF',\n    helper: '도움말',\n    youtube: '영상',\n    tvcast: '영상',\n    goal: '목표',\n    basicproject: '시작단계',\n    hw: '하드웨어',\n    object: '오브젝트',\n    console: '콘솔',\n    download_info: '모든 교육자료는 각각의 제목을 클릭 하시면 다운받으실 수 있습니다.',\n    entry_materials_all: '엔트리 교육자료 모음',\n    entry_material: '엔트리 교육자료',\n    recommand_grade: '추천학년',\n    g3_4_grades: '3-4 학년',\n    g5_6_grades: '5-6 학년',\n    middle_grades: '중학생 이상',\n    entry_go_go: '엔트리 고고!',\n    entry_go_go_desc: '학년별, 난이도 별로 준비된 교재를 만나보세요.',\n    entry_go_go_desc2: '각 과정별로 교육과정, 학습지, 교사용 해설서 3종 세트가 제공됩니다.',\n    stage_beginner: '초급',\n    stage_middle: '중급',\n    stage_high: '고급',\n    middle_school_short: '중등',\n    learn_entry_programming: '따라하며 배우는 엔트리 프로그래밍',\n    entry_programming_desc: '차근차근 따라 하다 보면 어느새 나도 엔트리 고수!',\n    ebs: 'EBS',\n    ebs_material_desc: '방송 영상과 교사용 지도서를 활용하여 수업을 해보세요!',\n    season_1_material: '시즌1 교사용 지도서',\n    season_2_material: '시즌2 교사용 지도서',\n    season_1: '시즌1',\n    playsoftware_ebs: 'EBS 소프트웨어야 놀자!',\n    material_teacher_guide: '교사용 지도서',\n    season_2: '시즌2',\n    compute_think_textbook: '교과서로 배우는 컴퓨팅 사고력',\n    computational_sw:\n        '국어, 수학, 과학, 미술... 학교에서 배우는 다양한 교과와 연계하여 SW를 배워보세요!',\n    python_coding_text: '엔트리파이선',\n    python_coding_textbook: '텍스트 코딩 세계로 떠나는 여행! 엔트리파이선',\n    python_coding_desc: '엔트리파이선으로 텍스트 언어의 구조와 문법을 자연스럽게 배워보세요!',\n    entry_x_hardware_text: '엔트리 X 하드웨어 교육자료',\n    entry_x_hardware: '엔트리 X 하드웨어 교육자료 모음',\n    e_sensor: 'E 센서보드',\n    e_sensor_board: 'E 센서보드',\n    e_sensor_robot: 'E 센서로봇',\n    arduino: '아두이노',\n    arduinoext: '아두이노 Uno 확장모드',\n    arduinonano: '아두이노 Nano',\n    albert: '알버트',\n    orange_board: '오렌지보드',\n    arduino_board: '아두이노',\n    joystick: '조이스틱 센서 쉴드',\n    ardublock: '아두블럭',\n    mkboard: '디지털 몽키보드',\n    mechatro_nano: '메카트로 나노+',\n    mechatro_uno: '메카트로 우노+',\n    memaker: '미메이커',\n    edumaker: '에듀메이커 보드',\n    codingtoolbox: '코딩툴박스',\n    materials_etc_all: '기타 교육자료 모음',\n    materials_teaching: '교원 연수 자료',\n    materials_etc: '기타 참고 자료',\n    materials_etc_resource: '참고 자료',\n    materials_teaching_etc: '교원 연수 및 참고자료',\n    materials_teaching_1: 'SW교육의 필요성과 교육 방법론',\n    materials_teaching_2: '엔트리와 함께하는 언플러그드 활동',\n    materials_teaching_3: '게임하듯 알고리즘을 배우는 엔트리 미션 해결하기',\n    materials_teaching_4: '실생활 문제해결을 위한 엔트리 프로그래밍',\n    materials_teaching_5: '교과연계 SW교육1 (미술,수학,사회)',\n    materials_teaching_6: '교과연계 SW교육2 (국어,과학,음악)',\n    materials_teaching_7: '피지컬 컴퓨팅 실습1(E센서보드)',\n    materials_teaching_8: '피지컬 컴퓨팅 실습2(햄스터)',\n    materials_teaching_9: '수업에 필요한 학급/강의 기능 알아보기',\n    materials_etc_1: '엔트리 첫 사용자를 위한 스타트 가이드',\n    materials_etc_2: '수업에 바로 활용할 수 있는 다양한 콘텐츠 모음집',\n    materials_etc_3: '월간 엔트리',\n    materials_etc_4: '엔트리 설명서',\n    materials_etc_5: '엔트리 소개 자료',\n    materials_etc_6: '엔트리 블록 책받침',\n    materials_etc_7: '엔트리파이선 예제 및 안내',\n    jr_if_1: '만약',\n    jr_if_2: '앞에 있다면',\n    jr_fail_no_pencil: '이런 그곳에는 연필이 없어. 연필이 있는 곳에서 사용해보자~',\n    jr_fail_forgot_pencil: '앗! 책가방에 넣을 연필을 깜빡했어. 연필을 모아서 가자~',\n    jr_fail_much_blocks: '너무많은 블록을 사용했어, 다시 도전해볼래?',\n    cparty_jr_success_1: '좋아! 책가방을 챙겼어!',\n    go_right: '오른쪽',\n    go_down: '  아래쪽',\n    go_up: '  위쪽',\n    go_left: '  왼쪽',\n    go_forward: '앞으로 가기',\n    jr_turn_left: '왼쪽으로 돌기',\n    jr_turn_right: '오른쪽으로 돌기',\n    go_slow: '천천히 가기',\n    repeat_until_reach_1: '만날 때 까지 반복하기',\n    repeat_until_reach_2: '',\n    pick_up_pencil: '연필 줍기',\n    repeat_0: '',\n    repeat_1: '반복',\n    when_start_clicked: '시작 버튼을 눌렀을 때',\n    age_0: '작품체험',\n    create_character: '캐릭터 만들기',\n    age_7_9: '초등 저학년',\n    going_school: '엔트리 학교가기',\n    age_10_12_1: '초등 고학년1',\n    collect_parts: '로봇공장 부품모으기',\n    age_10_12_2: '초등 고학년2',\n    driving_elec_car: '전기자동차 운전하기',\n    age_13: '중등',\n    travel_space: '우주여행하기',\n    people: '사람',\n    all: '전체',\n    life: '일상생활',\n    nature: '자연',\n    animal_insect: '동물/곤충',\n    environment: '자연환경',\n    things: '사물',\n    vehicles: '이동수단',\n    others: '기타',\n    fantasy: '판타지',\n    instrument: '악기',\n    piano: '피아노',\n    marimba: '마림바',\n    drum: '드럼',\n    janggu: '장구',\n    sound_effect: '효과음',\n    others_instrument: '기타타악기',\n    aboutEntryDesc_1: '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있는 플랫폼입니다.',\n    aboutEntryDesc_2: '학생들이 소프트웨어를 쉽고 재미있게 학습하고,',\n    aboutEntryDesc_3: '선생님들은 효과적으로 학생들을 가르칠 수 있습니다.',\n    aboutEntryDesc_4: '엔트리는 공공재와 같이',\n    aboutEntryDesc_5: '비영리로 운영됩니다.',\n    viewProjectTerms: '이용정책 보기',\n    openSourceTitle: '오픈소스를 통한 생태계 조성',\n    openSourceDesc_1: '엔트리의 소스코드 뿐 아니라',\n    openSourceDesc_2: '모든 교육 자료는 CC라이센스를 ',\n    openSourceDesc_3: '적용하여 공개합니다.',\n    viewOpenSource: '오픈소스 보기',\n    eduPlatformTitle: '국내교육 현장에 맞는 교육 플랫폼',\n    eduPlatformDesc_1: '국내 교육 현장에 적합한 교육 도구가',\n    eduPlatformDesc_2: '될 수 있도록 학교 선생님들과 함께',\n    eduPlatformDesc_3: '개발하고 있습니다.',\n    madeWith: '자문단',\n    researchTitle: '다양한 연구를 통한 전문성 강화',\n    researchDesc_1: '대학/학회 등과 함께 다양한 연구를',\n    researchDesc_2: '진행하여 전문성을 강화해나가고',\n    researchDesc_3: '있습니다.',\n    viewResearch: '연구자료 보기',\n    atEntry: '엔트리에서는',\n    entryLearnDesc_1: '재미있게 배우는 학습공간',\n    entryLearnDesc_2: '<학습하기>에서는 엔트리를 학습할 수 있는 콘텐츠가 준비되어 있습니다.',\n    entryLearnDesc_3: '게임을 하듯이 주어진 미션을 프로그래밍으로 해결하고 영상을 시청하며 ',\n    entryLearnDesc_4: '소프트웨어 제작 원리를 학습할 수 있습니다.',\n    entryMakeDesc_1: '<만들기>에서는 미국 MIT에서 개발한 Scratch와 같은 블록형 프로그래밍 언어를',\n    entryMakeDesc_2:\n        '사용하여 프로그래밍을 처음 접하는 사람들도 쉽게 자신만의 창작물을 만들 수 있습니다.',\n    entryMakeDesc_3:\n        \"또한 블록 코딩과 텍스트 코딩의 중간다리 역할을 하는 '엔트리파이선' 모드에서는\",\n    entryMakeDesc_4: '텍스트 언어의 구조와 문법을 자연스럽게 익힐 수 있습니다.',\n    entryMakeDesc_5: '',\n    entryShareDesc_1:\n        '<공유하기>에서는 엔트리를 통해 제작한 작품을 다른 사람들과 공유할 수 있습니다.',\n    entryShareDesc_2:\n        '또한 공유된 작품이 어떻게 구성되었는지 살펴보고 발전시켜 자신만의 작품을 만들 수',\n    entryShareDesc_3:\n        '있습니다. 공동 창작도 가능하여 친구들과 협업해 더 멋진 작품을 만들어 볼 수 있습니다.',\n    entryGroup: '학급기능',\n    entryGroupTitle: '우리 반 학습 공간',\n    entryGroupDesc_1:\n        '<학급기능>은 선생님이 학급별로 학생들을 관리할 수 있는 기능입니다. 학급끼리 학습하고',\n    entryGroupDesc_2: '작품을 공유할 수 있으며 과제를 만들고 학생들의 결과물을 확인할 수 있습니다.',\n    entryGroupDesc_3: '또한 선생님은 강의 기능을 활용하여 학생들의 수준에 맞는 학습환경을',\n    entryGroupDesc_4: '맞춤형으로 제공함으로써 효율적이고 편리하게 수업을 진행할 수 있습니다.',\n    entryGroupDesc_5: '',\n    unpluggedToPhysical: '언플러그드 활동부터 피지컬 컴퓨팅까지',\n    algorithmActivity: '기초 알고리즘',\n    programmignLang: '교육용 프로그래밍 언어',\n    unpluggedDesc_1: '엔트리봇 보드게임과 카드게임을 통해 컴퓨터 없이도',\n    unpluggedDesc_2: '소프트웨어의 기본 개념과 원리(순차, 반복, 선택, 함수)를 익힐 수 있습니다.',\n    entryMaze: '엔트리봇 미로탈출',\n    entryAI: '엔트리봇 우주여행',\n    algorithmDesc_1: '게임을 하듯이 미션을 해결하고 인증서를 받아보세요.',\n    algorithmDesc_2: '소프트웨어의 기본적인 원리를 쉽고 재미있게 배울 수 있습니다.',\n    programmingLangDesc_1: '엔트리에서는 블록을 쌓듯이 프로그래밍을 하기 때문에 누구나 쉽게',\n    programmingLangDesc_2:\n        '자신만의 게임, 애니메이션, 미디어아트와 같은 멋진 작품을 만들고 공유할 수 있어 교육용으로 적합합니다.',\n    viewSupporHwVideo: '하드웨어 가이드 영상 보기',\n    viewSupporHw: '연결되는 하드웨어 보기',\n    supportHwDesc_1:\n        '엔트리와 피지컬 컴퓨팅 도구를 연결하면 현실세계와 상호작용하는 멋진 작품들을 만들어낼 수 있습니다.',\n    supportHwDesc_2: '국내, 외 다양한 하드웨어 연결을 지원하며, 계속적으로 추가될 예정입니다.',\n    entryEduSupport: '엔트리 교육 지원',\n    eduSupportDesc_1:\n        '엔트리에서는 소프트웨어 교육을 위한 다양한 교육 자료를 제작하여 무상으로 배포하고 있습니다.',\n    eduSupportDesc_2: '모든 자료는 교육자료 페이지에서 다운받으실 수 있습니다.',\n    materials_1_title: '수준별 교재',\n    materials_1_desc_1: '학년별 수준에 맞는 교재를 통해 차근차근',\n    materials_1_desc_2: '따라하며 쉽게 엔트리를 익혀보세요!',\n    materials_2_title: 'EBS 방송 연계 교안',\n    materials_2_desc_1: 'EBS 소프트웨어야 놀자 방송과 함께',\n    materials_2_desc_2: '교사용 수업 지도안을 제공합니다.',\n    materials_3_title: '초, 중등 교과 연계 수업자료',\n    materials_3_title_2: '',\n    materials_3_desc_1: '다양한 과목에서 만나는 실생활 문제를',\n    materials_3_desc_2: '컴퓨팅 사고력으로 해결해 보세요.',\n    moreMaterials: '더 많은 교육 자료 보러가기',\n    moreInfoAboutEntry_1: '더 많은 엔트리의 소식들을 확인하고 싶다면 아래의 링크들로 접속해보세요.',\n    moreInfoAboutEntry_2: '교육자료 외에도 다양한 SW 교육과 관련한 정보를 공유하고 있습니다.',\n    material_menu_type_robot: '로봇형',\n    material_menu_type_module: '모듈형',\n    material_menu_type_board: '보드형',\n    blog: '블로그',\n    post: '포스트',\n    tvCast: 'TV캐스트',\n    about_entry_pre: '엔트리',\n    about_youtube: '유튜브',\n    about_facebook: '페이스북',\n    albertSchool: '알버트 스쿨버전',\n    arduinoBoard: '아두이노 정품보드',\n    arduinoCompatible: '아두이노 호환보드',\n    bitBlock: '비트블록',\n    bitbrick: '비트브릭',\n    creamo: '크리모',\n    playcode: '플레이코드',\n    funboard: '펀보드',\n    truerobot: '뚜루뚜루',\n    bingle: '빙글',\n    bingles: '빙글S',\n    codeino: '코드이노',\n    epor: '에뽀',\n    petrone_v2: '페트론V2',\n    petrone_v2_drone: '드론',\n    petrone_v2_car: '자동차',\n    'e-sensor': 'E-센서보드',\n    'e-sensorUsb': 'E-센서보드(유선연결)',\n    'e-sensorBT': 'E-센서보드(무선연결)',\n    mechatronics_4d: '4D 메카트로닉스',\n    esensor_board: 'E - 센서보드',\n    esensor_robot: 'E - 센서로봇',\n    hamster: '햄스터',\n    hummingbird: '허밍버드 듀오',\n    roboid: '로보이드',\n    turtle: '거북이',\n    littlebits: '리틀비츠',\n    orangeBoard: '오렌지 보드',\n    robotis_carcont: '로보티즈 로봇자동차',\n    robotis_IoT: '로보티즈 IoT',\n    robotis_IoT_Wireless: '로보티즈 IoT(무선연결)',\n    dplay: '디플레이',\n    iboard: '아이보드',\n    nemoino: '네모이노',\n    xbot_epor_edge: '엑스봇(원터치 동글/USB)',\n    XbotBT: '엑스봇 에뽀/엣지 블투투스',\n    robotori: '로보토리',\n    rokoboard: '로코보드',\n    neobot: '네오봇',\n    neobot_sensor_theme: '네오봇 센서 테마',\n    mechatro: '메카트로',\n    about: '알아보기',\n    articles: '토론하기',\n    gallery: '구경하기',\n    learn: '학습하기',\n    login: '로그인',\n    logout: '로그아웃',\n    make: '만들기',\n    register: '가입하기',\n    Join: '회원가입',\n    Edit_info: '내 정보 수정',\n    Discuss: '글 나누기',\n    Explore: '구경하기',\n    Load: '불러오기',\n    My_lesson: '오픈 강의',\n    textbook_learning: '교과서 학습하기',\n    Resources: '교육 자료',\n    play_software: '소프트웨어야 놀자!',\n    problem_solve: '엔트리 학습하기',\n    learning_textbook: '교과서 학습하기',\n    context_textbook:\n        '초등 교과서 그대로 선생님은 학교 수업을 학생은 집에서 예습, 복습을 할 수 있어요.',\n    info_banner_textbook: '* 출판사는 가나다순 노출입니다.',\n    banner_textbook: '더욱 다양하고',\n    banner_textbook_2: '재미있는 학습을 하고 싶다면?',\n    banner_textbook_right_banner: '학생용 활동지와 교사용',\n    banner_textbook_right_banner2: '학습 도움 자료가 필요하신가요?',\n    banner_textbook_right_banner_btn: '교과서별 자료 받기',\n    Learn: '학습하기',\n    teaching_tools: '엔트리 교구',\n    about_entry: '엔트리 소개',\n    what_entry: '엔트리는?',\n    create: '만들기',\n    create_new: '새로 만들기',\n    start_programming: '소프트웨어 교육의 첫걸음',\n    Entry: '엔트리',\n    intro_learning: '누구나 쉽고 재밌게 소프트웨어를 배울 수 있어요. ',\n    intro_learning_anyone: '지금 바로 시작해보세요! ',\n    start_now: 'For Free, Forever.',\n    welcome_entry: '엔트리에 오신걸 환영합니다.',\n    student: '학생',\n    non_menber: '일반인',\n    teacher: '선생님',\n    terms_conditions: '이용약관',\n    personal_information: '개인정보 수집 및 이용에 대한 안내',\n    limitation_liability: '책임의 한계와 법적 고지',\n    entry_agree: '엔트리의 이용약관에 동의 합니다.',\n    info_agree: '개인정보 수집 및 이용에 동의합니다.',\n    next: '다음',\n    enter_individual_info: '개인정보 입력',\n    enter_id: '아이디 입력',\n    enter_password: '비밀번호 입력',\n    confirm_password: '비밀번호 확인',\n    enter_password_again: '비밀번호를 한번 더 입력하세요.',\n    validation_password: '5자 이상의 영문/숫자 등을 조합하세요.',\n    validation_id: '4~20자의 영문/숫자를 조합하세요',\n    prev: '이전',\n    born_year: '태어난 연도',\n    select_born: '태어난 연도를 선택 하세요',\n    year: '년',\n    gender: '성별',\n    choose_gender: '성별을 선택 하세요',\n    male: '남성',\n    female: '여성',\n    language: '언어',\n    best_language: '주 언어를 선택 하세요',\n    korean: '한국어',\n    english: '영어',\n    viet: '베트남',\n    japan: '일본어',\n    russia: '러시아어',\n    chinese_simplified: '중국어(간체)',\n    chinese_traditional: '중국어(번체)',\n    option_email: '이메일(선택)',\n    insert_email: '이메일 주소를 입력 하세요',\n    sign_up_complete: '회원 가입이 완료 되었습니다',\n    agree_terms_conditions: '이용약관에 동의해 주세요.',\n    agree_personal_information: '개인정보 수집 및 이용에 대한 안내에 동의해 주세요.',\n    insert_studying_stage: '작품을 공유하고 싶은 학급을 선택해 주세요.',\n    insert_born_year: '태어난 연도를 입력해 주세요.',\n    insert_gender: '성별을 선택지에서 선택해 주세요.',\n    select_language: '언어를 선택해 주세요.',\n    check_email: '이메일 형식을 확인해 주세요.',\n    already_exist_id: '이미 존재하는 아이디 입니다.',\n    id_validation_id: '아이디는 4~20자의 영문/숫자를 조합하세요',\n    password_validate_pwd: '패스워드는 5자 이상의 영문/숫자 등을 조합하세요.',\n    password_validate_pwd_length: '패스워드는 최소 5자 이상으로 입력해 주세요.',\n    neoid_username_same_id: '이미 사용중인 아이디 입니다.(NEOID)',\n    insert_same_pwd: '같은 비밀번호를 입력해 주세요.',\n    studying_stage_group: '작품 공유 학급',\n    studying_stage: '작품을 공유하고 싶은 학급을 선택해 주세요.',\n    password: '비밀번호 입력',\n    save_id: '아이디 저장',\n    auto_login: '자동 로그인',\n    enter_id_pw: '아이디, 비밀번호 입력',\n    forgot_password: '아이디와 비밀번호가 기억나지 않으세요 ?',\n    did_not_join: '아직 엔트리 회원이 아니세요?',\n    go_join: '회원가입하기 ',\n    renew_index_text_00: '엔트리 교과서 학습하기',\n    renew_index_text_01: '교과서로 엔트리를 배워보세요.',\n    renew_index_text_02: '초등학교 교과서 강의를 통해',\n    renew_index_text_02_2: '엔트리를 배워보세요!',\n    renew_index_text_03: '교과서 학습하기',\n    renew_index_text_03_2: '바로가기',\n    renew_index_text_1: '2019년, 엔트리가 바뀝니다',\n    renew_index_text_2: '확 바뀐 작품 만들기',\n    renew_index_text_3: '지금 새로운 기능을 확인하고',\n    renew_index_text_3_2: 'PC와 태블릿으로 작품을 만들어보세요!',\n    renew_index_text_4: '자세히 보기',\n    first_step: '소프트웨어 교육의 첫걸음',\n    entry_content_one: '상상했던 것들을 블록 놀이하듯 하나씩 쌓아보세요.',\n    entry_content_two: '게임, 애니메이션, 미디어아트와 같은 멋진 작품이 완성된답니다!',\n    entry_content_three:\n        '재미있는 놀이로 배우고, 나만의 멋진 작품을 만들어 친구들과 공유할 수 있는 멋진 엔트리의 세상으로 여러분을 초대합니다!',\n    funny_space: '재미있게 배우는 학습공간',\n    in_learn_section: '< 학습하기 > 에서는',\n    learn_problem_solving:\n        '컴퓨터를 활용해 논리적으로 문제를 해결할 수 있는 다양한 학습 콘텐츠가 준비되어 있습니다. 게임을 하듯이 주어진 미션들을 프로그래밍으로 해결해볼 수도 있고 재미있는 동영상으로 소프트웨어의 원리를 배울 수도 있습니다 .',\n    joy_create: '창작의 즐거움',\n    in_make: '< 만들기 > 는',\n    make_contents:\n        '미국 MIT에서 개발한 Scratch와 같은 비주얼 프로그래밍 언어를 사용하여 프로그래밍을 처음 접하는 사람들도 쉽게 나만의 창작물을 만들 수 있습니다. 또 엔트리를 통해 만들 수 있는 컨텐츠의 모습은 무궁무진합니다. 과학 시간에 배운 물리 법칙을 실험해 볼 수도 있고 좋아하는 캐릭터로 애니메이션을 만들거나 직접 게임을 만들어 볼 수 있습니다.',\n    and_content:\n        '또 엔트리를 통해 만들 수 있는 콘텐츠의 모습은 무궁무진합니다. 과학 시간에 배운 물리 법칙을 실험해 볼 수도 있고 좋아하는 캐릭터로 애니메이션을 만들거나 직접 게임을 만들어 볼 수 있습니다.',\n    share_collaborate: '공유와 협업',\n    explore_contents:\n        '< 구경하기 > 에서는 엔트리를 통해 제작한 작품을 다른 사람들과 쉽게 공유할 수 있습니다. 또한 공유된 작품이 어떻게 구성되었는지 살펴볼 수 있고, 이를 발전시켜 자신만의 프로젝트를 만들 수 있습니다. 그리고 엔트리에서는 공동 창작도 가능합니다. 친구들과 협업하여 더 멋진 프로젝트를 만들어볼 수 있습니다.',\n    why_software: '왜 소프트웨어 교육이 필요할까?',\n    speak_obama_contents:\n        '컴퓨터 과학을 배우는 것은 단지 여러분의 미래에만 중요한 일이 아닙니다. 이것은 우리 미국의 미래를 위해 중요한 일 입니다.',\n    obama: '버락 오바마',\n    us_president: '미국 대통령',\n    billgates_contents:\n        '컴퓨터 프로그래밍은 사고의 범위를 넓혀주고 더 나은 생각을 할 수 있게 만들며 분야에 상관없이 모든 문제에 대해 새로운 해결책을 생각할 수 있는 힘을 길러줍니다.',\n    billgates: '빌게이츠',\n    chairman_micro: 'Microsoft 회장',\n    eric_contents:\n        '현재 디지털 혁명은 지구상 대부분의 사람들에게 아직 시작도 안된 수준입니다. 프로그래밍을 통해 향후 10년간 모든 것이 변화할 것 입니다.',\n    eric: '에릭 슈미츠',\n    sandbug_contents:\n        '오늘날 컴퓨터 과학에 대한 이해는 필수가 되었습니다. 우리의 국가 경쟁력은 우리가 아이들에게 이것을 얼마나 잘 가르칠 수 있느냐에 달려있습니다.',\n    sandbug: '쉐릴 샌드버그',\n    view_entry_tools: '엔트리와 함께할 수 있는 교구들을 살펴볼 수 있습니다.',\n    solve_problem: '미션 해결하기',\n    solve_problem_content:\n        '게임을 하듯 미션을 하나 하나 해결하며 소프트웨어의 기본 원리를 배워보세요!',\n    find_extra_title: '엔트리봇 부품 찾기 대작전',\n    all_ages: '전 연령',\n    total: '총',\n    step: '단계',\n    find_extra_contents:\n        '로봇 강아지를 생산하던 루츠 공장에 어느 날 갑자기 일어난 정전 사태로 태어난 특별한 강아지 엔트리 봇. 아직 조립이 덜 된 나머지 부품들을 찾아 공장을 탈출 하도록 도와주면서 소프트웨어의 동작 원리를 익혀보자!',\n    software_play_contents: \"EBS에서 방영한 '소프트웨어야 놀자' 프로그램을 실습해볼 수 있습니다.\",\n    resources_contents: '엔트리를 활용한 다양한 교육자료들을 무료로 제공합니다.',\n    from: ' 출처',\n    sw_camp: '미래부 SW 창의캠프',\n    elementary: '초등학교',\n    middle: '중학교',\n    grades: '학년',\n    lesson: '차시',\n    sw_contents_one:\n        '5차시 분량으로 초등학생이 엔트리와 피지컬 컴퓨팅을 경험할  수 있는 교재입니다. 학생들은 엔트리 사용법을 학습하고, 그림판과 이야기 만들기를 합니다. 마지막에는 아두이노 교구를 활용하여 키보드를 만들어보는 활동을 합니다.',\n    sw_camp_detail: '미래창조과학부 SW창의캠프',\n    sw_contents_two:\n        '5차시 분량으로 중학생이 엔트리와 피지컬 컴퓨팅을 경험할 수 있는 교재입니다. 학생들은 엔트리 사용법을 학습하고, 미로찾기 게임과, 퀴즈 프로그램을 만들어 봅니다. 마지막에는 아두이노 교구를 활용하여 키보드로 자동차를 조종하는 활동을 합니다.',\n    sw_contents_three:\n        \"선생님들이 학교에서 시작할 수 있는 소프트웨어 수업 지도서입니다. 다양한 언플러그드 활동과, '소프트웨어야 놀자' 방송을 활용한 수업 지도안이 담겨 있습니다.\",\n    naver_sw: 'NAVER 소프트웨어야 놀자',\n    teacher_teaching: '교사용지도서 (초등학교 5~6학년 이상)',\n    funny_sw: '즐거운 SW놀이 교실',\n    sw_contents_four:\n        '소프트웨어를 놀이하듯 재미있게 배울 수 있는 교재로 엔트리보드게임을 비롯한 다양한 언플러그드 활동과 엔트리 학습모드로 소프트웨어를 만드는 기본 원리를 배우게 됩니다. 기본 원리를 배웠다면 학생들은 이제 엔트리로 이야기, 게임, 예술작품, 응용프로그램을 만드는 방법을 배우고, 자신이 생각한 소프트웨어를 만들고 발표할 수 있도록 교재가 구성되어 있습니다.',\n    ct_text_5: '교과서와 함께 키우는 컴퓨팅 사고력',\n    teacher_grade_5: '교원 (초등학교 5학년)',\n    ct_text_5_content:\n        '실생활의 문제를 해결하자는 테마로 준비된 총 8개의 학습콘텐츠가 담긴 교사용 지도안입니다. 각 콘텐츠는 개정된 교육과정을 반영한 타교과와의 연계를 통해 다양한 문제를 만나고 해결해볼 수 있도록 설계되었습니다.  아이들이 컴퓨팅 사고력을 갖춘 융합형 인재가 될 수 있도록 지금 적용해보세요!',\n    ct_text_6: '교과서와 함께 키우는 컴퓨팅 사고력',\n    teacher_grade_6: '교원 (초등학교 6학년)',\n    ct_text_6_content:\n        '실생활의 문제를 해결하자는 테마로 준비된 총 8개의 학습콘텐츠가 담긴 교사용 지도안입니다. 각 콘텐츠는 개정된 교육과정을 반영한 타교과와의 연계를 통해 다양한 문제를 만나고 해결해볼 수 있도록 설계되었습니다.  아이들이 컴퓨팅 사고력을 갖춘 융합형 인재가 될 수 있도록 지금 적용해보세요!',\n    sw_use: '모든 교재들은 비영리 목적에 한하여 저작자를 밝히고 자유롭게 이용할 수 있습니다.',\n    title: '제목',\n    writer: '작성자',\n    view: '보기',\n    date: '등록일',\n    find_id_pwd: '아이디와 비밀번호 찾기',\n    send_email: '비밀번호를 잊은 경우 이메일로 비밀번호를 찾을 수 있습니다.',\n    user_not_exist: '존재하지 않는 이메일 주소 입니다.',\n    not_signup: '아직 회원이 아니세요?',\n    send: '발송하기',\n    sensorboard: '엔트리봇 센서보드',\n    physical_computing: '피지컬 컴퓨팅',\n    sensorboard_contents:\n        '아두이노를 사용하기 위해서 더 이상 많은 케이블을 사용해 회로를 구성할 필요가 없습니다. 엔트리 보드는 아두이노 위에 끼우기만 하면 간단하게 LED, 온도센서, 소리센서, 빛, 슬라이더, 스위치를 활용할 수 있습니다. 이제 엔트리 보드를 활용해 누구라도 쉽게 자신만의 특별한 작품을 만들어보세요!',\n    entrybot_boardgame: '엔트리봇 보드게임',\n    unplugged: '언플러그드 활동',\n    unplugged_contents:\n        '재밌는 보드게임을 통해 컴퓨터의 작동 원리를 배워보세요. 로봇강아지인 엔트리봇이 정전된 공장에서 필요한 부품을 찾아 탈출하도록 돕다보면 컴퓨터 전문가처럼 문제를 바라 볼 수  있게됩니다.',\n    entrybot_cardgame: '엔트리봇 카드게임 : 폭탄 대소동',\n    entrybot_cardgame_contents:\n        '갑자기 엔트리도시에 나타난 12종류의 폭탄들! 과연 폭탄들을 안전하게 해체할 수 있을까요? 폭탄들을 하나씩 해체하며 엔트리 블록과 함께 소프트웨어의 원리를 배워봐요!  순차, 반복, 조건을 통해 폭탄을 하나씩 해체하다 보면 엔트리도시를 구한 영웅이 될 수 있답니다!',\n    basic_learn: '엔트리 기본 학습',\n    basic_learn_contents: '엔트리를 활용한 다양한 교육 콘텐츠를 제공합니다.',\n    troubleshooting: '문제해결 학습',\n    playsoftware: '소프트웨어야 놀자',\n    make_own_lesson: '나만의 수업을 만들어 다른 사람과 공유할 수 있습니다.',\n    group_lecture: '우리 반 강의',\n    group_curriculum: '우리 반 강의 모음',\n    group_homework: '우리 반 과제',\n    group_noproject: '전시된 작품이 없습니다.',\n    group_nolecture: '생성된 강의가 없습니다.',\n    group_nocurriculum: '생성된 강의 모음이 없습니다.',\n    lecture_contents: '필요한 기능만 선택하여 나만의 수업을 만들어 볼 수 있습니다.',\n    curriculum_contents:\n        '여러개의 강의를 하나의 강의 모음으로 묶어 차근차근 따라할 수 있는 수업을 만들 수 있습니다.',\n    grade_info: '학년 정보',\n    difficulty: '난이도',\n    usage: '사용요소',\n    learning_concept: '학습개념',\n    related_subject: '연계 교과',\n    show_more: '더보기',\n    close: '닫기',\n    latest: '최신순',\n    viewCount: '조회수',\n    viewer: '조회순',\n    like: '좋아요순',\n    comment: '댓글순',\n    entire_period: '전체기간',\n    today: '오늘',\n    latest_week: '최근 1주일',\n    latest_month: '최근 1개월',\n    latest_three_month: '최근 3개월',\n    current_password: '현재 비밀번호',\n    change_password: '비밀번호 변경',\n    incorrect_password: '비밀번호가 일치하지 않습니다.',\n    incorrect_password_login: '아이디 또는 비밀번호를 잘못 입력하셨습니다.',\n    suspension_user: '이용 정지된 계정입니다.',\n    blocked_user: '승인되지 않은 사용자 입니다.',\n    new_password: '새로운 비밀번호',\n    password_option_1: '영문과 숫자의 조합으로 5자 이상이 필요합니다.',\n    again_new_password: '새로운 비밀번호 재입력',\n    enter_new_pwd: '새로운 비밀번호를 입력하세요.',\n    confirm_new_pwd: '새로운 비밀번호를 확인하세요.',\n    enter_new_pwd_again: '새로운 비밀번호를 다시 입력하세요.',\n    password_match: '비밀번호가 일치하지 않습니다.',\n    incorrect_email: '유효한 이메일이 아닙니다',\n    edit_button: '정보수정',\n    edit_profile: '관리',\n    my_project: '나의 작품',\n    my_group: '나의 학급',\n    mark: '관심 작품',\n    prev_state: '이전',\n    profile_image: '자기소개 이미지',\n    insert_profile_image: '프로필 이미지를 등록해 주세요.',\n    at_least_180: '180 x 180 픽셀의 이미지를 권장합니다.',\n    upload_image: '이미지 업로드',\n    about_me: '자기소개',\n    save_change: '변경사항 저장',\n    basic_image: '기본 이미지',\n    profile_condition: '자기소개를 입력해 주세요. 50자 내외',\n    profile_back: '돌아가기',\n    make_project: '작품 만들기',\n    exhibit_project: '작품 전시하기',\n    art_list_shared: '개인',\n    art_list_group_shared: '학급',\n    gl_mode_boost: '부스트 모드',\n    gl_not_supported:\n        '부스트 모드로 실행할 수 없는 환경입니다.\\n확인을 누르면 기본모드로 실행됩니다.',\n    view_project: '코드 보기',\n    code_view: '코드보기',\n    noResult: '검색 결과가 없습니다.',\n    comment_view: '댓글',\n    upload_project: '올리기',\n    edit: '수정',\n    save_complete: '저장',\n    just_like: '좋아요',\n    share: '공유',\n    who_likes_project: '작품을 좋아하는 사람',\n    people_interest: '작품을 관심있어 하는 사람',\n    none_person: '없음',\n    inserted_date: '등록일',\n    last_modified: '최종 수정일',\n    original_project: '원본 작품',\n    for_someone: '님의',\n    original_project_deleted: '원본 작품이 삭제되었습니다.',\n    delete_project: '삭제',\n    delete_group_project: '목록에서 삭제',\n    currnet_month_time: '월',\n    current_day_time: '일',\n    game: '게임',\n    animation: '애니메이션',\n    media_art: '미디어 아트',\n    physical: '피지컬',\n    etc: '기타',\n    connected_contents: '연계되는 콘텐츠',\n    connected_contents_content:\n        '엔트리와 함께 할 수 있는 다양한 콘텐츠를 만나보세요. 처음 소프트웨어를 배우는 사람이라면 쉽게 즐기는 보드게임부터 아두이노와 같은 피지컬 컴퓨팅을 활용하여 자신만의 고급스러운 창작물을 만들어 볼 수 있습니다.',\n    basic_mission: '기본 미션: 엔트리봇 미로찾기',\n    basic_mission_content:\n        '강아지 로봇을 만드는 공장에서 우연한 정전으로 혼자서 생각할 수 있게 된 엔트리봇! 공장을 탈출하고 자유를 찾을 수 있도록 엔트리봇을 도와주세요!',\n    application_mission: '응용미션: 엔트리봇 우주여행',\n    write_article: '글쓰기',\n    write_contest: '제출하기',\n    view_all_articles: '모든 글 보기',\n    view_own_articles: '내가 쓴 글 보기',\n    view_qna_articles: '답변 없는 글 보기',\n    learning_materials: '교육자료',\n    download_materials: '교육자료 내려받기',\n    download_button: '내려받기',\n    download_all: '모두 내려받기',\n    ebs_software_first:\n        '<소프트웨어야 놀자>는 네이버와 EBS가 함께 만든 교육 콘텐츠입니다. 여기에서는 엔트리를 활용하여 실제로 간단한 프로그램을 만들어보며 소프트웨어의 기초 원리를 배워나갈 수 있습니다. 또한 각 콘텐츠에서는 동영상을 통해 컴퓨터과학에 대한 선행지식이 없더라도 충분히 재미와 호기심을 느끼며 진행할 수 있도록 준비되어있습니다.',\n    go_software: '소프트웨어야 놀자 가기',\n    ebs_context: 'EBS 동영상 가기',\n    ebs_context_hello: 'EBS 가기',\n    category: '카테고리',\n    add_picture: '사진첨부',\n    upload_article: '글 올리기',\n    list: '목록',\n    report: '신고하기',\n    upload: '올리기',\n    staff_picks: '스태프 선정',\n    popular_picks: '인기 작품',\n    lecture_header_more: '더 만들어 보기',\n    lecture_header_reset: '초기화',\n    lecture_header_reset_exec: '초기화 하기',\n    lecture_header_save: '저장',\n    lecture_header_save_content: '학습내용 저장하기',\n    lecture_header_export_project: '내 작품으로 저장하기',\n    lecture_header_undo: '취소',\n    lecture_header_redo: '복원',\n    lecture_er_bugs: '버그신고',\n    lecture_container_tab_object: '오브젝트',\n    lecture_container_tab_video: '강의 동영상',\n    lecture_container_tab_project: '완성된 작품',\n    lecture_container_tab_help: '블록 도움말',\n    illigal: '불법적인 내용 또는 사회질서를 위반하는 활동',\n    verbal: '언어 폭력 또는 개인 정보를 침해하는 활동',\n    commertial: '상업적인 목적을 가지고 활동',\n    explicit: '음란물',\n    other: '기타',\n    check_one_more: '하나이상 표기해주세요.',\n    enter_content: '기타의 내용을 입력해 주세요.',\n    report_result: '결과 회신을 원하시면 메일을 입력해 주세요.',\n    report_success: '신고하기가 정상적으로 처리 되었습니다.',\n    etc_detail:\n        '기타 항목 선택후 입력해주세요. 신고와 무관한 욕설 작성 시 이용이 정지될 수 있습니다.',\n    lecture_play: '강의 보기',\n    list_view_link: '다른 강의 모음 보기',\n    lecture_intro: '강의 소개 보기',\n    study_goal: '학습목표',\n    study_description: '설명',\n    study_created: '등록일',\n    study_last_updated: '최종 수정일',\n    study_remove: '삭제',\n    study_group_lecture_remove: '목록에서 삭제',\n    study_group_curriculum_remove: '목록에서 삭제',\n    study_edit: '강의 모음 수정',\n    study_comments: '댓글',\n    study_comment_post: '올리기',\n    study_comment_remove: '삭제',\n    study_comment_edit: '수정',\n    study_comment_save: '저장',\n    study_guide_video: '안내 영상',\n    study_basic_project: '기본 작품',\n    study_done_project: '완성 작품을 선택하세요.',\n    study_usage_element: '사용요소',\n    study_concept_element: '적용개념',\n    study_subject_element: '연계교과',\n    study_computing_element: '컴퓨팅요소',\n    study_element_none: '없음',\n    study_label_like: '좋아요',\n    study_label_interest: '관심 강의',\n    study_label_share: '공유',\n    study_label_like_people: '강좌를 좋아하는 사람',\n    study_label_interest_people: '강좌를 관심있어 하는 사람',\n    study_related_lectures: '강의 목록',\n    study_expand: '전체보기',\n    study_collapse: '줄이기',\n    aftercopy: '주소가 복사되었습니다.',\n    study_remove_curriculum: '강의 모음을 삭제하시겠습니까?',\n    content_required: '내용을 입력하세요',\n    upload_not_supported_file_msg: '지원하지 않는 형식의 파일입니다.',\n    study_remove_lecture: '강의를 삭제하시겠습니까?',\n    lecture_build: '강의 만들기',\n    lecture_build_step1: '1. 강의를 소개하기 위한 정보를 입력해주세요',\n    lecture_build_step2: '2. 학습에 사용되는 기능들만 선택해주세요',\n    lecture_build_step3: '3. 모든 정보를 올바르게 입력했는지 확인해주세요',\n    lecture_build_choice: '어떤 것을 올리시겠습니까?',\n    lecture_build_project: '엔트리 작품',\n    lecture_build_video: '강의 영상',\n    lecture_build_grade: '추천학년',\n    lecture_build_goals: '학습목표',\n    lecture_build_add_goal: '이곳을 클릭하여 목표를 추가',\n    lecture_build_attach: '파일 첨부',\n    lecture_build_attach_text: '20MB 이내의 파일을 업로드해 주세요.',\n    lecture_build_assist: '보조 영상',\n    lecture_build_youtube_url: 'Youtube 공유 링크를 넣어주세요.',\n    lecture_build_project_done: '완성 작품을 선택하세요.',\n    lecture_build_scene_text1: '장면기능을 끄면 새로운 장면을 추가하거나,',\n    lecture_build_scene_text2: '삭제할 수 없습니다.',\n    lecture_build_object_text:\n        '오브젝트 추가하기를 끄면 새로운 오브젝트를 추가하거나 삭제할 수 없습니다.',\n    lecture_build_blocks_text1: '학습에 필요한 블록들만 선택해주세요.',\n    lecture_build_blocks_text2: '선택하지 않은 블록은 숨겨집니다.',\n    lecture_build_basic1: '학습을 시작할때 사용할 작품을 선택해 주세요.',\n    lecture_build_basic2: '학습자는 선택한 작품을 가지고 학습을 하게 됩니다.',\n    lecture_build_help: '이 도움말을 다시 보시려면 눌러주세요.',\n    lecture_build_help_never: '다시보지 않기',\n    lecture_build_close: '닫기',\n    lecture_build_scene: '장면 1',\n    lecture_build_add_object: '오브젝트 추가하기',\n    lecture_build_start: '시작하기',\n    lecture_build_tab_code: '블록',\n    lecture_build_tab_shape: '모양',\n    lecture_build_tab_sound: '소리',\n    lecture_build_tab_attribute: '속성',\n    lecture_build_tab_table: '테이블',\n    lecture_build_block_category: '블록 카테고리를 선택하세요.',\n    lecture_build_attr_all: '전체',\n    lecture_build_attr_var: '변수',\n    lecture_build_attr_signal: '신호',\n    lecture_build_attr_list: '리스트',\n    lecture_build_attr_func: '함수',\n    lecture_build_edit: '강의 수정',\n    lecture_build_remove: '삭제',\n    curriculum_build: '강의 모음 만들기',\n    curriculum_step1: '1. 강의 모음을 소개하는 정보를 입력해주세요.',\n    curriculum_step2: '2. 강의 모음을 구성하는 강의를 선택해주세요.',\n    curriculum_step3: '3. 올바르게 강의 모음이 구성되었는지 확인해주세요.',\n    curriculum_lecture_upload: '강의 올리기',\n    curriculum_lecture_edit: '강의 편집',\n    curriculum_lecture_open: '불러오기',\n    group_lecture_add: '우리 반 강의 추가하기',\n    group_curriculum_add: '우리 반 강의 모음 추가하기',\n    group_lecture_delete: '삭제',\n    group_curriculum_delete: '삭제',\n    group_select: '',\n    group_studentNo: '학번',\n    group_username: '이름',\n    group_userId: '아이디',\n    group_tempPassword: '비밀번호 수정',\n    group_gender: '성별',\n    group_studentCode: '코드',\n    group_viewWorks: '작품 보기',\n    added_group_lecture: '강의가 삭되었습니다.',\n    added_group_curriculum: '강의 모음이 삭제되었습니다.',\n    deleted_group_lecture: '강의가 삭제되었습니다.',\n    deleted_group_curriculum: '강의 모음이 삭제되었습니다.',\n    modal_my: '나의',\n    modal_interest: '관심',\n    modal_project: '작품',\n    section: '단원',\n    connect_hw: '하드웨어 연결',\n    connect_message: '%1에 연결되었습니다.',\n    connect_fail: '하드웨어 연결에 실패했습니다. 연결프로그램이 켜져 있는지 확인해 주세요.',\n    interest_curriculum: '관심 강의 모음',\n    marked_curriculum: '관심 강의 모음',\n    searchword_required: '검색어를 입력하세요.',\n    file_required: '파일은 필수 입력 항목입니다.',\n    file_name_error: '올바른 파일이름을 입력해 주세요.',\n    file_upload_max_count: '한번에 10개까지 업로드가 가능합니다.',\n    image_file_only: '이미지 파일만 등록이 가능합니다.',\n    file_upload_max_size: '10MB 이하만 업로드가 가능합니다.',\n    curriculum_modal_lectures: '나의 강의',\n    curriculum_modal_interest: '관심 강의',\n    group_curriculum_modal_curriculums: '나의 강의 모음',\n    group_curriculum_modal_interest: '관심 강의 모음',\n    picture_import: '모양 가져오기',\n    picture_select: '모양 선택',\n    lecture_list_view: '다른 강의보기',\n    play_software_2: 'EBS 소프트웨어야 놀자2',\n    play_software_2_content:\n        '네이버와 EBS가 함께 만든 두 번째 이야기, <소프트웨어야 놀자> 시즌2를 만나보세요! 재미있는 동영상 강의를 통해 소프트웨어의 기본 개념을 배워보고, 다양하고 흥미로운 주제로 실생활 문제를 해결해 볼 수 있습니다. 방송영상과 특별영상을 보며 재미있는 프로그램들을 직접 만들어보세요. 소프트웨어 교육을 처음 접하는 친구들도 쉽게 소프트웨어와 친구가 될 수 있답니다!',\n    open_project_to_all: '공개',\n    close_project: '비공개',\n    category_media_art: '미디어 아트',\n    go_further: '더 나아가기',\n    marked_project: '관심 작품',\n    marked_group_project: '학급 관심 작품',\n    basic: '기본',\n    application: '응용',\n    the_great_escape: '탈출 모험기',\n    escape_guide_1:\n        '강아지 로봇을 만드는 공장에서 우연한 정전으로 혼자서 생각할 수 있게 된 엔트리봇! ',\n    escape_guide_1_2: ' 공장을 탈출하고 자유를 찾을 수 있도록 엔트리봇을 도와주세요!',\n    escape_guide_2:\n        '엔트리봇이 먼 길을 가기엔 고쳐야 할 곳이 너무 많아 공장에서 탈출하면서 몸을 수리할 수 있는 부품들을 찾아보자! 아직 몸이 완전하지는 않지만 걷거나 뛰면서, 방향을 바꾸는 정도는 가능할 거야! ',\n    escape_guide_2_2: '학습 목표: 순차적 실행',\n    escape_guide_3:\n        '드디어 공장을 탈출했어! 하지만 마을로 가기 위해서는 아직 가야 할 길이 멀어. 그래도 몸은 어느 정도 고쳐져서 똑같은 일을 많이 해도 무리는 없을 거야! 어? 근데 저 로봇은 뭐지? ',\n    escape_guide_3_2: '학습 목표: 반복문과 조건문',\n    escape_guide_4:\n        '드디어 마을 근처까지 왔어! 아까부터 똑같은 일을 많이 했더니 이제 외울 지경이야! 차라리 쓰일 블록은 이제 기억해뒀다가 쓰면 좋을 것 같아. 여기서 배터리만 충전해 놓으면 이제 평생 자유롭게 살 수 있을 거야.',\n    escape_guide_4_2: '학습 목표: 함수 정의와 호출',\n    space_travel_log: '우주 여행기',\n    space_guide_1:\n        '머나먼 우주를 탐사하기 위해 떠난 엔트리봇. 드디어 탐사 임무를 마치고 고향별인 지구로 돌아오려 하는데 수많은 돌이 지구로 가는 길을 막고 있다!  엔트리봇이 안전하게 지구로 돌아올 수 있도록 도와주세요!',\n    space_guide_2:\n        '드디어 지구에 돌아갈 시간이야! 얼른 지구에 돌아가서 쉬고 싶어!앞에 돌들이 어떻게 되어 있는지 확인하고 언제 어디로 가야 하는지 알려줘! 그러면 내가 가르쳐준 방향으로 움직일게!',\n    space_guide_2_2: '학습 목표: 조건문 중첩과 논리 연산',\n    cfest_mission: '엔트리 체험 미션',\n    maze_1_intro:\n        '안녕 나는 엔트리봇이라고 해. 지금 나는 다친 친구들을 구하려고 하는데 너의 도움이 필요해. 나를 도와서 친구들을 구해줘! 먼저 앞으로 가기 블록을 조립하고 시작을 눌러봐',\n    maze_1_title: '시작 방법',\n    maze_1_content: '엔트리봇은 어떻게 움직이나요?',\n    maze_1_detail:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐 <br> 2. 다 조립했으면, 시작을 눌러봐 <br> 3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_2_intro:\n        '좋아! 덕분에 첫 번째 친구를 무사히 구할 수 있었어! 그럼 다음 친구를 구해볼까? 어! 그런데 앞에 벌집이 있어! 뛰어넘기 블록을 사용해서 벌집을 피하고 친구를 구해보자.',\n    maze_2_title_1: '장애물 뛰어넘기',\n    maze_2_content_1: '장애물이 있으면 어떻게 해야하나요?',\n    maze_2_detail_1:\n        '길을 가다보면 장애물을 만날 수 있어. <br> 장애물이 앞에 있을 때에는 뛰어넘기 블록을 사용해야 해.',\n    maze_2_title_2: '시작 방법',\n    maze_2_content_2: '엔트리봇은 어떻게 움직이나요?',\n    maze_2_detail_2:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐 <br> 2. 다 조립했으면, 시작을 눌러봐 <br> 3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_3_intro:\n        '멋졌어! 이제 또 다른 친구를 구하러 가자~ 이번에는 아까 구한 친구가 준 반복하기 블록을 이용해볼까? 반복하기를 이용하면 똑같은 동작을 쉽게 여러번 할 수 있어! 한 번 반복할 숫자를 바꿔볼래?',\n    maze_3_title: '반복 블록(1)',\n    maze_3_content: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_3_detail:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해. <br> 반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼',\n    maze_4_intro:\n        '훌륭해! 이제 구해야 할 친구 로봇들도 별로 남지 않았어. 벌집에 닿지 않도록 뛰어넘기를 반복하면서 친구에게 갈 수 있게 해줘!',\n    maze_4_title: '반복 블록(1)',\n    maze_4_content: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_4_detail:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해. <br> 반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼',\n    maze_5_intro:\n        '대단해! 이제 반복하기 블록과 만약 블록을 같이 사용해보자~ 만약 블록을 사용하면 앞에 벽이 있을 때 벽이 없는 쪽으로 회전할 수 있어. 그럼 친구를 구해주러 출발해볼까?',\n    maze_5_title_1: '만약 블록',\n    maze_5_content_1: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_5_detail_1:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어. <br> 앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고 <br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_5_title_2: '반복 블록(2)',\n    maze_5_content_2: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_5_detail_2:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어. <br> 반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼. <br> 그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_6_intro:\n        '이제 마지막 친구야! 아까 해본 것처럼만 하면 될거야! 그럼 마지막 친구를 구하러 가볼까?',\n    maze_6_title_1: '만약 블록',\n    maze_6_content_1: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_6_detail_1:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어. <br> 앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고 <br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_6_title_2: '반복 블록(2)',\n    maze_6_content_2: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_6_detail_2:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어. <br> 반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼. <br> 그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_programing_mode_0: '블록 코딩',\n    maze_programing_mode_1: '자바스크립트',\n    maze_operation1_title: '1단계 – 자바스크립트모드 안내',\n    maze_operation1_1_desc:\n        '나는 로봇강아지 엔트리봇이야. 나에게 명령을 내려서 미션을 해결할 수 있게 도와줘! 미션은 시작할 때마다 <span class=\"textShadow\">\\'목표\\'</span>를 통해서 확인할 수 있어!',\n    maze_operation1_2_desc:\n        '미션을 확인했다면 <b>명령</b>을 내려야 해 <span class=\"textUnderline\">\\'명령어 꾸러미\\'</span>는 <b>명령어</b>가 있는 공간이야. <b>마우스</b>와 <b>키보드</b>로 <b>명령</b>을 내릴 수 있어. <span class=\"textShadow\">마우스</span>로는 명령어 꾸러미에 있는 <b>명령어</b>를 클릭하거나, <b>명령어</b>를 <span class=\"textUnderline\">\\'명령어 조립소\\'</span>로 끌고와서 나에게 <b>명령</b>을 내릴 수 있어!',\n    maze_operation1_2_textset_1: '마우스로 명령어를 클릭하는 방법 ',\n    maze_operation1_2_textset_2: '마우스로 명령어를 드래그앤드랍하는 방법 ',\n    maze_operation1_3_desc:\n        '<span class=\"textShadow\">키보드</span>로 명령을 내리려면 \\'명령어 꾸러미\\' 에 있는 <b>명령어를 키보드로 직접 입력하면 돼.</b></br> 명령어를 입력할 때 명령어 끝에 있는 <span class=\"textShadow\">()와 ;</span> 를 빼먹지 않도록 주의해야해!',\n    maze_operation1_4_desc:\n        '미션을 해결하기 위한 명령어를 다 입력했다면 <span class=\"textShadow\">[시작하기]</span>를 누르면 돼.</br> [시작하기]를 누르면 나는 명령을 내린대로 움직일 거야!</br> 각 명령어가 궁금하다면 <span class=\"textShadow\">[명령어 도움말]</span>을 확인해봐!',\n    maze_operation7_title: '7단계 - 반복 명령 알아보기(횟수반복)',\n    maze_operation7_1_desc:\n        '<b>똑같은 일</b>을 반복해서 명령하는건 매우 귀찮은 일이야.</br>이럴땐 <span class=\"textShadow\">반복</span>과 관련된 명령어를 사용하면 훨씬 쉽게 명령을 내릴 수 있어.',\n    maze_operation7_2_desc:\n        '그렇다면 반복되는 명령을 쉽게 내리는 방법을 알아보자.</br>먼저 반복하기 명령어를 클릭한 다음, <span class=\"textShadow\">i<1</span> 의 숫자를 바꿔서 <span class=\"textShadow\">반복횟수</span>를 정하고</br><span class=\"textShadow\">괄호({ })</span> 사이에 반복할 명령어를 넣어주면 돼!',\n    maze_operation7_3_desc:\n        '예를 들어 이 명령어<span class=\"textBadge number1\"></span>은 move(); 를 10번 반복해서 실행해.</br><span class=\"textBadge number2\"></span>명령어와 동일한 명령어지.',\n    maze_operation7_4_desc:\n        '이 명령어를 사용할 때는 <span class=\"textShadow\">{ } 안에 반복할 명령어</span>를 잘 입력했는지,</br><span class=\"textShadow\">`;`</span>는 빠지지 않았는지 잘 살펴봐!</br>이 명령어에 대한 자세한 설명은 [명령어 도움말]에서 볼 수 있어.',\n    maze_operation7_1_textset_1: '똑같은 명령어를 반복해서 사용하는 경우',\n    maze_operation7_1_textset_2: '반복 명령어를 사용하는 경우',\n    maze_operation7_2_textset_1: '반복 횟수',\n    maze_operation7_2_textset_2: '반복할 명령',\n    maze_operation7_4_textset_1: '괄호({})가 빠진 경우',\n    maze_operation7_4_textset_2: '세미콜론(;)이 빠진 경우',\n    study_maze_operation8_title: '8단계 - 반복 명령 알아보기(횟수반복)',\n    study_maze_operation16_title: '4단계 - 반복 명령 알아보기(조건반복)',\n    study_maze_operation1_title: '1단계 - 반복 명령 알아보기(횟수반복)',\n    maze_operation9_title: '9단계 - 반복 명령 알아보기(조건반복)',\n    maze_operation9_1_desc:\n        '앞에서는 몇 번을 반복하는 횟수반복 명령어에 대해 배웠어.</br>이번에는 <span class=\"textShadow\">계속해서 반복하는 명령어</span>를 살펴보자.</br>이 명령어를 사용하면 미션이 끝날 때까지 <b>동일한 행동</b>을 계속 반복하게 돼.</br>이 명령어 역시 괄호({ }) 사이에 반복할 명령어를 넣어 사용할 수 있어!',\n    maze_operation9_2_desc:\n        '예를 들어 이 명령어 <span class=\"textBadge number1\"></span>은 미션을 완료할때까지 반복해서 move(); right()를 실행해.</br><span class=\"textBadge number2\"></span>명령어와 동일한 명령어지.',\n    maze_operation9_3_desc:\n        '이 명령어를 사용할 때도 <span class=\"textShadow\">{ } 안에 반복할 명령어</span>를 잘 입력했는지,</br><span class=\"textShadow\">`true`</span>가 빠지지 않았는지 잘 살펴봐!</br>이 명령어에 대한 자세한 설명은 [명령어 도움말]에서 볼 수 있어.',\n    maze_operation9_1_textset_1: '반복할 명령',\n    maze_operation9_3_textset_1: '괄호({})가 빠진 경우',\n    maze_operation9_3_textset_2: '세미콜론(;)이 빠진 경우',\n    maze_operation9_3_textset_3: 'true가 빠진 경우',\n    study_maze_operation3_title: '3단계 - 반복 명령 알아보기(조건반복)',\n    study_maze_operation4_title: '4단계 - 조건 명령 알아보기',\n    study_ai_operation4_title: '4단계 - 조건 명령과 레이더 알아보기',\n    study_ai_operation6_title: '6단계 - 중첩조건문 알아보기',\n    study_ai_operation7_title: '7단계 - 다양한 비교연산 알아보기',\n    study_ai_operation8_title: '8단계 - 물체 레이더 알아보기',\n    study_ai_operation9_title: '9단계 - 아이템 사용하기',\n    maze_operation10_title: '10단계 - 조건 명령 알아보기',\n    maze_operation10_1_desc:\n        '앞에서는 미션이 끝날 때까지 계속 반복하는 반복 명령어에 대해 배웠어.</br>이번에는 특정한 조건에서만 행동을 하는 <span class=\"textShadow\">조건 명령어</span>를 살펴보자.</br><span class=\"textBadge number2\"></span>에서 보는것처럼 조건 명령어를 사용하면 <b>명령을 보다 효율적으로 잘 내릴 수 있어.</b>',\n    maze_operation10_2_desc:\n        '조건 명령어는 크게 <span class=\"textShadow\">`조건`</span> 과 <span class=\"textShadow\">`조건이 발생했을때 실행되는 명령`</span>으로 나눌수 있어.</br>먼저 <span class=\"textUnderline\">조건</span> 부분을 살펴보자. If 다음에 나오는 <span class=\"textUnderline\">( ) 부분</span>이 조건을 입력하는 부분이야.</br><span class=\"textBadge number1\"></span>과 같은 명령어를 예로 살펴보자. <span class=\"textUnderline\">if(front == \\“wall\\”)</span> 는 만약 내 앞에(front) \"wall(벽)\"이 있다면을 뜻해',\n    maze_operation10_3_desc:\n        '이제 <span class=\"textUnderline\">`조건이 발생했을 때 실행되는 명령`</span>을 살펴보자.</br>이 부분은 <span class=\"textShadow\">괄호{}</span>로 묶여 있고, 조건이 발생했을때 괄호안의 명령을 실행하게 돼!</br>조건이 발생하지 않으면 이 부분은 무시하고 그냥 넘어가게 되지.</br><span class=\"textBadge number1\"></span>의 명령어를 예로 살펴보자. 조건은 만약에 `내 앞에 벽이 있을 때` 이고,</br><b>이 조건이 발생했을 때 나는 괄호안의 명령어 right(); 처럼 오른쪽으로 회전하게 돼!</b>',\n    maze_operation10_4_desc:\n        '<span class=\"textShadow\">조건 명령어</span>는 <span class=\"textShadow\">반복하기 명령어</span>와 함께 쓰이는 경우가 많아.</br>앞으로 쭉 가다가, 벽을 만났을때만 회전하게 하려면</br><span class=\"textUnderline pdb5\"><span class=\"textBadge number1\"></span><span class=\"textBadge number2\"></span><span class=\"textBadge number3\"></span>순서</span>와 같이 명령을 내릴 수 있지!',\n    maze_operation10_1_textset_1: '<b>[일반명령]</b>',\n    maze_operation10_1_textset_2:\n        '<span class=\"textMultiline\">앞으로 2칸 가고</br>오른쪽으로 회전하고,</br>앞으로 3칸가고,</br>오른쪽으로 회전하고, 앞으로...</span>',\n    maze_operation10_1_textset_3: '<b>[조건명령]</b>',\n    maze_operation10_1_textset_4:\n        '<span class=\"textMultiline\">앞으로 계속 가다가</br><span class=\"textEmphasis\">`만약에 벽을 만나면`</span></br>오른쪽으로 회전해~!</span>',\n    maze_operation10_2_textset_1: '조건',\n    maze_operation10_2_textset_2: '조건이 발생했을 때 실행되는 명령',\n    maze_operation10_3_textset_1: '조건',\n    maze_operation10_3_textset_2: '조건이 발생했을 때 실행되는 명령',\n    maze_operation10_4_textset_1:\n        '<span class=\"textMultiline\">미션이 끝날때 까지</br>계속 앞으로 간다.</span>',\n    maze_operation10_4_textset_2:\n        '<span class=\"textMultiline\">계속 앞으로 가다가,</br>만약에 벽을 만나면</span>',\n    maze_operation10_4_textset_3:\n        '<span class=\"textMultiline\">계속 앞으로 가다가,</br>만약에 벽을 만나면</br>오른쪽으로 회전한다.</span>',\n    study_maze_operation18_title: '6단계 - 조건 명령 알아보기',\n    maze_operation15_title: '15단계 - 함수 명령 알아보기',\n    maze_operation15_1_desc:\n        '자주 사용하는 명령어들을 매번 입력하는건 매우 귀찮은 일이야.</br>자주 사용하는 <span class=\"textUnderline\">명령어들을 묶어서 이름</span>을 붙이고,</br><b>필요할 때마다 그 명령어 묶음을 불러온다면 훨씬 편리하게 명령을 내릴 수 있어!</b></br>이런 명령어 묶음을  <span class=\"textShadow\">`함수`</span>라고 해. 이제 함수 명령에 대해 자세히 알아보자.',\n    maze_operation15_2_desc:\n        '함수 명령어는 명령어를 묶는 <b>`함수만들기` 과정</b>과,</br>묶은 명령어를 필요할 때 사용하는 <b>`함수 불러오기` 과정</b>이 있어.</br>먼저 함수만들기 과정을 살펴보자.</br>함수를 만들려면 함수의 이름과, 그 함수에 들어갈 명령어를 입력해야 해.</br><span class=\"textShadow\">function</span>을 입력한 다음 <span class=\"textShadow\">함수의 이름</span>을 정할 수 있어. 여기서는 <span class=\"textShadow\">promise</span>로 만들거야.</br>함수 이름을 만들었으면 <span class=\"textUnderline\">()</span>를 붙여줘. 그 다음 <span class=\"textUnderline\">괄호({})</span>를 입력해.</br>그리고 <span class=\"textUnderline\">이 괄호 안에 함수에 들어갈 명령어들을 입력하면</span> 함수가 만들어져!',\n    maze_operation15_3_desc:\n        '이 명령어를 예로 살펴보자. 나는 <span class=\"textShadow\">promise</span> 라는 함수를 만들었어.</br>이 함수를 불러서 실행하면 <span class=\"textUnderline\">괄호({})</span>안에 있는</br>move();</br>move();</br>left(); 가 실행돼!',\n    maze_operation15_4_desc:\n        '함수를 불러와서 실행하려면 아까 만든 <b>함수의 이름을 입력하고 뒤에 `();`를 붙이면 돼.</b></br>promise 라는 이름으로 함수를 만들었으니 <span class=\"textShadow\">promise();</span> 를 입력하면 앞에서 묶어놓은</br>명령어들이 실행되는거지!</br><span class=\"number1 textBadge\"></span>과 같이 명령을 내리면 <span class=\"number2 textBadge\"></span>처럼 동작하게 돼!</br>함수 명령어를 사용하려면 <span class=\"number1 textBadge\"></span>과 같이 함수를 만들고 함수를 불러와야해!',\n    maze_operation15_1_textset_1: '자주 사용하는 명령어 확인하기',\n    maze_operation15_1_textset_2: '명령어들을 묶어서 이름 붙이기',\n    maze_operation15_1_textset_3: '명령어 묶음 불러오기',\n    maze_operation15_2_textset_1: '명령어 묶음의 이름(함수 이름)',\n    maze_operation15_2_textset_2: '묶을 명령어들',\n    maze_operation15_3_textset_1: '명령어 묶음의 이름(함수 이름)',\n    maze_operation15_3_textset_2: '묶을 명령어들',\n    maze_operation15_4_textset_1: '함수 만들기',\n    maze_operation15_4_textset_2: '함수 불러오기',\n    maze_operation15_4_textset_3: '실제 상황',\n    maze_object_title: '오브젝트 정보',\n    maze_object_parts_box: '부품 상자',\n    maze_object_trap: '함정',\n    maze_object_monster: '몬스터',\n    maze_object_obstacle1: '장애물',\n    maze_object_obstacle2: 'bee',\n    maze_object_obstacle3: 'banana',\n    maze_object_friend: '친구',\n    maze_object_wall1: 'wall',\n    maze_object_wall2: 'wall',\n    maze_object_wall3: 'wall',\n    maze_object_battery: '베터리',\n    maze_command_ex: '예시',\n    maze_command_title: '명령어 도움말',\n    maze_command_move_desc: '엔트리봇을 한 칸 앞으로 이동시킵니다.',\n    maze_command_jump_desc:\n        '아래 이미지와 같은 장애물 앞에서 장애물을 뛰어 넘습니다.</br><div class=\"obstacleSet\"></div>',\n    maze_command_jump_desc_elec:\n        '아래 이미지와 같은 장애물 앞에서 장애물을 뛰어 넘습니다.</br><div class=\"obstacle_elec\"></div>',\n    maze_command_right_desc: '제자리에서 오른쪽으로 90도 회전합니다.',\n    maze_command_left_desc: '제자리에서 왼쪽으로 90도 회전합니다.',\n    maze_command_for_desc:\n        '괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 <span class=\"textShadow\">입력한 횟수</span> 만큼 반복해서 실행합니다.',\n    maze_command_while_desc:\n        '미션이 끝날 때가지 괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 계속 반복해서 실행합니다.',\n    maze_command_slow_desc: '아래 이미지와 같은 방지턱을 넘습니다.</br><div class=\"hump\"></div>',\n    maze_command_if1_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 벽이 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_if2_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 벌집이 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_if3_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 바나나가 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_promise_desc:\n        'promise 라는 <span class=\"textShadow\">함수</span>를 만들고 실행하면 괄호<span class=\"textShadow\">{}</span> 안에</br>있던 명령어가 실행합니다.',\n    perfect: '아주 완벽해!  ',\n    succeeded_using_blocks: ' 개의 블록을 사용해서 성공했어!',\n    succeeded_using_commands: ' 개의 명령어를 사용해서 성공했어!',\n    awesome: '대단한 걸!',\n    succeeded_go_to_next: '개의 블록만으로 성공했어! <br> 다음 단계로 넘어가자.',\n    good: '좋아! ',\n    but: '<br> 하지만, ',\n    try_again: ' 개의 블록만으로 성공하는 방법도 있어. <br> 다시 도전해 보는건 어때?',\n    try_again_commands: ' 개의 명렁어만으로 성공하는 방법도 있어. <br> 다시 도전해 보는건 어때?',\n    cfest_success:\n        '대단한걸! 덕분에 친구들을 구할 수 있었어! <br> 아마도 너는 타고난 프로그래머 인가봐! <br> 나중에 또 만나자~!',\n    succeeded_and_cert: '개의 블록만으로 성공했어! <br>인증서를 받으러 가자.',\n    cause_msgs_1: '에구, 앞으로 갈 수 없는 곳이였어. 다시 해보자.',\n    cause_msgs_2: '히잉. 그냥 길에서는 뛰어 넘을 곳이 없어. 다시 해보자.',\n    cause_msgs_3: '에고고, 아파라. 뛰어 넘었어야 했던 곳이였어. 다시 해보자.',\n    cause_msgs_4: '아쉽지만, 이번 단계에서는 꼭 아래 블록을 써야만 해. <br> 다시 해볼래?',\n    cause_msgs_5: '이런, 실행할 블록들이 다 떨어졌어. 다시 해보자.',\n    cause_msgs_6: '이런, 실행할 명령어들이 다 떨어졌어. 다시 해보자.',\n    close_experience: '체험<br>종료',\n    replay: '다시하기',\n    go_to_next_level: '다음단계 가기',\n    move_forward: '앞으로 한 칸 이동',\n    turn_left: '왼쪽',\n    turn_right: '오른쪽',\n    turn_en: '',\n    turn_ko: '으로 회전',\n    jump_over: '뛰어넘기',\n    when_start_is_pressed: '시작하기를 클릭했을 때',\n    repeat_until_ko: '만날 때 까지 반복',\n    repeat_until_en: '',\n    repeat_until: '만날 때 까지 반복',\n    if_there_is_1: '만약 앞에 ',\n    if_there_is_2: '있다면',\n    used_blocks: '사용 블록',\n    maximum: '목표 블록',\n    used_command: '사용 명령어 갯수',\n    maximum_command: '목표 명령어 갯수',\n    block_box: '블록 꾸러미',\n    block_assembly: '블록 조립소',\n    command_box: '명령어 꾸러미',\n    command_assembly: '명령어 조립소',\n    start: '시작하기',\n    engine_running: '실행중',\n    engine_replay: '돌아가기',\n    goto_show: '보러가기',\n    make_together: '함께 만드는 엔트리',\n    make_together_content:\n        '엔트리는 학교에 계신 선생님들과 학생 친구들이 함께 고민하며 만들어갑니다.',\n    project_nobody_like: \"이 작품이 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    project_nobody_interest: \"'관심 작품'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    lecture_nobody_like: \"이 강의가 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    lecture_nobody_interest: \"'관심 강의'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    course_nobody_like: \"이 강의 모음이 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    course_nobody_interest: \"'관심 강의 모음'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    before_changed: '변경전',\n    after_changed: '변경후',\n    from_changed: '( 2016년 04월 17일 부터 ) ',\n    essential: '필수',\n    access_term_title:\n        '안녕하세요. 엔트리 교육연구소 입니다. <br>  엔트리를 사랑해주시는 여러분께 감사드리며,  <br>  엔트리 교육연구소 웹사이트 이용약관이<br>  2016년 4월 17일 부로 다음과 같이 개정됨을 알려드립니다. ',\n    member_info: '회원 안내',\n    personal_info: '개인정보 수집 및 이용에 동의 합니다.',\n    option: '선택',\n    news: '최신소식',\n    edu_material: '교육자료',\n    latest_news: '최근소식',\n    edu_data: '교육자료',\n    training_program: '연수지원',\n    footer_phrase:\n        '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있게 개발된 비영리 교육 플랫폼입니다.',\n    footer_use_free:\n        '모든 엔트리교육연구소의 저작물은 교육적 목적에 한하여 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    footer_description_1:\n        '엔트리는 비영리 교육 플랫폼으로 모든 엔트리의 저작물은 교육 목적에 한해 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    footer_description_2: '',\n    nonprofit_platform: '비영리 교육 플랫폼',\n    this_is: '입니다.',\n    privacy: '개인정보 처리방침',\n    entry_addr: '경기도 성남시 분당구 불정로 6 NAVER 그린팩토리 16층',\n    entry_addr_additional_phone: '1522-9182',\n    entry_addr_additional_email: 'entry@connect.or.kr',\n    entry_addr_additional_opensource: '오픈소스 라이선스',\n    phone: '전화번호',\n    alert_agree_term: '이용약관에 동의하여 주세요.',\n    alert_private_policy: '개인정보 수집 약관에 동의하여 주세요.',\n    agree: '동의',\n    optional: '선택',\n    start_software: '소프트웨어 교육의 첫걸음',\n    analyze_procedure: '절차',\n    analyze_repeat: '반복',\n    analyze_condition: '분기',\n    analyze_interaction: '상호작용',\n    analyze_dataRepresentation: '데이터 표현',\n    analyze_abstraction: '추상화',\n    analyze_sync: '병렬 및 동기화',\n    jr_intro_1: '안녕! 난 쥬니라고 해! 내 친구 엔트리봇이 오른쪽에 있어! 날 친구에게 데려다 줘!',\n    jr_intro_2: '엔트리봇이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    jr_intro_3: '엔트리봇이 위쪽에 있어! 친구를 만날 수 있도록 도와줘!',\n    jr_intro_4: '어서 엔트리봇을 만나러 가자! 아래쪽으로 가보는거야~ ',\n    jr_intro_5: '우왓! 내 친구가 멀리 떨어져있어. 엔트리봇이 있는 곳까지 안내해줄래? ',\n    jr_intro_6: '저기 엔트리봇이 있어~ 얼른 만나러 가보자.',\n    jr_intro_7: '예쁜 꽃이 있네. 꽃들을 모아 엔트리봇에게 가보자!',\n    jr_intro_8: '가는 길에 꽃이 있어! 꽃을 모아 엔트리봇에게 가보자!',\n    jr_intro_9: '엔트리봇이 멀리 떨어져 있네? 가장 빠른 길로 엔트리봇에게 가 보자.',\n    jr_intro_10: '엔트리봇을 만나러 가는 길에 꽃을 모두 모아서 가보자.',\n    jr_intro_11:\n        '엔트리봇에게 가려면 오른쪽으로 다섯번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    jr_intro_12: '반복하기를 사용해서 엔트리봇을 만나러 가자.',\n    jr_intro_13:\n        '지금 블록으로는 친구에게 갈 수가 없어. 반복 횟수를 바꿔 엔트리봇에게 갈 수 있게 해줘.',\n    jr_intro_14: '반복 블록을 사용하여 엔트리봇에게 데려다 줘.',\n    jr_intro_15:\n        '엔트리봇이 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 엔트리봇에게 갈 수 있을 거야.',\n    jr_whats_ur_name: '내가 받을 인증서에 적힐 이름은?',\n    jr_down_cert: '인증서 받기',\n    jr_popup_prefix_1: '좋아! 엔트리봇을 만났어!',\n    jr_popup_prefix_2:\n        '우왓! 엔트리봇을 만났어! <br> 하지만 엔트리봇을 만나기에는 더 적은 블록을 사용해서도 <br> 만날 수 있는데 다시 해볼래? ',\n    jr_popup_prefix_3: '좋아! 책가방을 챙겼어!',\n    jr_popup_prefix_4:\n        '우왓! 책가방이 있는 곳으로 왔어! 하지만 더 적은 블록을 사용해도 책가방 쪽으로 갈 수 있는데 다시 해볼래?',\n    jr_popup_suffix_1:\n        '고마워~ 덕분에 책가방을 챙겨서 학교에 올 수 있었어~ 다음 학교 가는 길도 함께 가자~',\n    jr_popup_suffix:\n        '고마워~ 덕분에 엔트리봇이랑 재밌게 놀 수 있었어~ <br>다음에 또 엔트리봇이랑 놀자~',\n    jr_fail_dont_go: '에궁, 그 곳으로는 갈 수 없어. 가야하는 길을 다시 알려줘~',\n    jr_fail_dont_know: '어? 이제 어디로 가지? 어디로 가야하는 지 더 알려줘~',\n    jr_fail_no_flower: '이런 그곳에는 꽃이 없어. 꽃이 있는 곳에서 사용해보자~',\n    jr_fail_forgot_flower: '앗! 엔트리봇한테 줄 꽃을 깜빡했어. 꽃을 모아서 가자~',\n    jr_fail_need_repeat: '반복 블록이 없잖아! 반복 블록을 사용해서 해보자~',\n    jr_hint_1: '안녕! 난 쥬니라고 해! 내 친구 엔트리봇이 오른쪽에 있어! 날 친구에게 데려다 줘!',\n    jr_hint_2: '엔트리봇이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    jr_hint_3: '엔트리봇이 위쪽에 있어! 친구를 만날 수 있도록 도와줘!',\n    jr_hint_4: '어서 엔트리봇을 만나러 가자! 아래쪽으로 가보는거야~',\n    jr_hint_5: '우왓! 내 친구가 멀리 떨어져있어. 엔트리봇이 있는 곳까지 안내해줄래?',\n    jr_hint_6:\n        '잘못된 블록들 때문에 친구에게 가지 못하고 있어, 잘못된 블록을 지우고 엔트리봇에게 갈 수 있도록 해줘!',\n    jr_hint_7: '예쁜 꽃이 있네. 꽃들을 모아 엔트리봇에게 가보자!',\n    jr_hint_8: '가는 길에 꽃이 있어! 꽃을 모아 엔트리봇에게 가보자!',\n    jr_hint_9: '엔트리봇이 멀리 떨어져 있네? 가장 빠른 길로 엔트리봇에게 가 보자.',\n    jr_hint_10:\n        '앗, 블록을 잘못 조립해서 제대로 갈 수가 없어. 가는 길에 꽃을 모두 모아 엔트리봇에게 가져다 줄 수 있도록 고쳐 보자.',\n    jr_hint_11:\n        '엔트리봇에게 가려면 오른쪽으로 다섯번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    jr_hint_12: '반복하기를 사용해서 엔트리봇을 만나러 가자.',\n    jr_hint_13:\n        '지금 블록으로는 친구에게 갈 수가 없어. 반복 횟수를 바꿔 엔트리봇에게 갈 수 있게 해줘.',\n    jr_hint_14: '반복 블록을 사용하여 엔트리봇에게 데려다 줘.',\n    jr_hint_15:\n        '엔트리봇이 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 엔트리봇에게 갈 수 있을 거야.',\n    jr_certification: '인증서',\n    jr_congrat: '축하드립니다!',\n    jr_congrat_msg: '문제해결 과정을 성공적으로 마쳤습니다.',\n    jr_share: '공유',\n    go_see_friends: '친구들 만나러 가요~!',\n    junior_naver: '쥬니어 네이버',\n    junior_naver_contents_1: \"의 멋진 곰 '쥬니'가 엔트리를 찾아 왔어요! \",\n    junior_naver_contents_2: '그런데 쥬니는 길을 찾는 것이 아직 어렵나봐요.',\n    junior_naver_contents_3: '쥬니가 엔트리봇을 만날 수 있도록 가야하는 방향을 알려주세요~',\n    basic_content: '기초',\n    jr_help: '도움말',\n    help: '도움말',\n    cparty_robot_intro_1:\n        '안녕 나는 엔트리봇이야. 난 부품을 얻어서 내몸을 고쳐야해. 앞으로 가기 블록으로 부품을 얻게 도와줘!',\n    cparty_robot_intro_2:\n        '좋아! 앞에도 부품이 있는데 이번에는 잘못 가다간 감전되기 쉬울 것 같아. 뛰어넘기 블록을 써서 부품까지 데려다 줘.',\n    cparty_robot_intro_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 회전하기 블록을 쓰면 충분히 갈 수 있을 것 같아! ',\n    cparty_robot_intro_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 회전과 뛰어넘기를 같이 써서 저 부품을 얻어보자! ',\n    cparty_robot_intro_5:\n        '덕분에 몸이 아주 좋아졌어! 이번에도 회전과 뛰어넘기를 같이 써야 할 거야! 어서 가보자!',\n    cparty_robot_intro_6:\n        '멋져! 이제 몸이 많이 좋아져서, 똑같은 일은 여러 번 해도 괜찮을 거야! 한 번 반복하기를 사용해서 가보자!',\n    cparty_robot_intro_7:\n        '어? 중간중간에 뛰어넘어야 할 곳이 있어! 그래도 반복하기로 충분히 갈 수 있을 거야!',\n    cparty_robot_intro_8:\n        '이런! 이번에는 부품이 저기 멀리 떨어져 있어. 그래도 반복하기를 사용하면 쉽게 갈수 있지! 얼른 도와줘!',\n    cparty_robot_intro_9:\n        '우와~ 이제 내 몸이 거의 다 고쳐진 것 같아! 이번에도 반복하기를 이용해서 부품을 구하러 가보자!',\n    cparty_robot_intro_10:\n        '대단해! 이제 마지막 부품만 있으면 내 몸을 완벽하게 고칠 수 있을 거야! 빨리 반복하기로 도와줘!',\n    cparty_car_intro_1:\n        '안녕! 나는 엔트리봇이라고 해, 자동차를 타고 계속 이동하려면 연료가 필요해! 앞에 있는 연료를 얻을 수 있게 도와줄래?',\n    cparty_car_intro_2:\n        '좋아! 그런데 이번에는 길이 직선이 아니네! 왼쪽/오른쪽 돌기 블록으로 잘 운전해서 함께 연료를 얻으러 가볼까?',\n    cparty_car_intro_3:\n        '잘했어! 이번 길 앞에는 과속방지턱이 있어. 빠르게 운전하면 사고가 날 수도 있을 것 같아, 천천히 가기 블록을 써서 연료를 얻으러 가보자!',\n    cparty_car_intro_4:\n        '야호, 이제 운전이 한결 편해졌어! 이 도로에서는 반복하기 블록을 사용해서 연료를 채우러 가볼까?',\n    cparty_car_intro_5:\n        '와 이번 도로는 조금 복잡해 보이지만, 앞으로 가기와 왼쪽/오른쪽 돌기 블록을 반복하면서 가보면 돼! 차분하게 연료까지 가보자',\n    cparty_car_intro_6:\n        '이번에는 도로에 장애물이 있어서 잘 돌아가야 될 것 같아, 만약에 장애물이 앞에 있다면 어떻게 해야 하는지 알려줘!',\n    cparty_car_intro_7:\n        '좋아 잘했어! 한번 더 만약에 블록을 사용해서 장애물을 피해 연료를 얻으러 가보자!',\n    cparty_car_intro_8:\n        '앗 아까 만났던 과속 방지턱이 두 개나 있네, 천천히 가기 블록을 이용해서 안전하게 연료를 채우러 가보자!',\n    cparty_car_intro_9:\n        '복잡해 보이는 길이지만, 앞에서 사용한 반복 블록과 만약에 블록을 잘 이용하면 충분히 운전할 수 있어, 연료를 채울 수 있도록 도와줘!',\n    cparty_car_intro_10:\n        '정말 멋져! 블록의 순서를 잘 나열해서 이제 마지막 남은 연료를 향해 힘을 내어 가보자!',\n    cparty_car_popup_prefix_1: '좋아! 연료를 얻었어!',\n    cparty_car_popup_prefix_2:\n        '우왓! 연료를 얻었어! <br> 하지만 연료를 얻기에는 더 적은 블록을 사용해서도 <br> 얻을 수 있는데 다시 해볼래? ',\n    cparty_car_popup_prefix_2_text:\n        '우왓! 연료를 얻었어! <br> 하지만 연료를 얻기에는 더 적은 명령어 사용해서도 <br> 얻을 수 있는데 다시 해볼래? ',\n    cparty_car_popup_suffix:\n        '고마워~ 덕분에 모든 배터리를 얻을 수 있었어~ <br>다음에 또 나랑 놀자~',\n    all_grade: '모든 학년',\n    grade_e3_e4: '초등 3 ~ 4 학년 이상',\n    grade_e5_e6: '초등 5 ~ 6 학년 이상',\n    grade_m1_m3: '중등 1 ~ 3 학년 이상',\n    entry_first_step: '엔트리 첫걸음',\n    entry_monthly: '월간 엔트리',\n    play_sw_2: 'EBS 소프트웨어야 놀자2',\n    entry_programming: '실전, 프로그래밍!',\n    entry_recommanded_course: '엔트리 추천 코스',\n    introduce_course:\n        '누구나 쉽게 보고 따라하면서 재미있고 다양한 소프트웨어를 만들 수 있는 강의 코스를 소개합니다.',\n    all_free: '*강의 동영상, 만들기, 교재 등이 모두 무료로 제공됩니다.',\n    cparty_result_fail_1: '에궁, 그 곳으로는 갈 수 없어. 가야하는 길을 다시 알려줘~',\n    cparty_result_fail_2: '에고고, 아파라. 뛰어 넘었어야 했던 곳이였어. 다시 해보자.',\n    cparty_result_fail_3:\n        '아이고 힘들다. 아래 블록들을 안 썼더니 너무 힘들어! 아래 블록들로 다시 만들어줘.',\n    cparty_result_fail_4: '어? 이제 어디로 가지? 어디로 가야하는 지 더 알려줘~',\n    cparty_result_fail_5: '앗! 과속방지턱에서는 속도를 줄여야해. 천천히 가기 블록을 사용해보자~',\n    cparty_result_success_1: '좋아! 부품을 얻었어!',\n    cparty_result_success_2:\n        '우왓! 부품을 얻었어! <br>하지만 부품을 얻기에는 더 적은 블록을 사용해서도 얻을 수 있는데 다시 해볼래?',\n    cparty_result_success_2_text:\n        '우왓! 부품을 얻었어! <br>하지만 부품을 얻기에는 더 적은 명령어를 사용해서도 얻을 수 있는데 다시 해볼래?',\n    cparty_result_success_3: '고마워~ 덕분에 내몸이 다 고쳐졌어~ 다음에 또 나랑 놀자~',\n    cparty_insert_name: '이름을 입력하세요.',\n    offline_file: '파일',\n    offline_edit: '편집',\n    offline_undo: '되돌리기',\n    offline_redo: '다시실행',\n    offline_quit: '종료',\n    select_one: '선택해 주세요.',\n    evaluate_challenge: '도전해본 미션의 난이도를 평가해 주세요.',\n    very_easy: '매우쉬움',\n    easy: '쉬움',\n    normal: '보통',\n    difficult: '어려움',\n    very_difficult: '매우 어려움',\n    save_dismiss: '바꾼 내용을 저장하지 않았습니다. 계속 하시겠습니까?',\n    entry_info: '엔트리 정보',\n    actual_size: '실제크기',\n    zoom_in: '확대',\n    zoom_out: '축소',\n    cparty_jr_intro_1:\n        '안녕! 난 엔트리봇 이라고 해! 학교가는 길에 책가방을 챙길 수 있도록 도와줘! ',\n    cparty_jr_intro_2: '책가방이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    cparty_jr_intro_3: '책가방이 위쪽에 있어! 책가방을 챙길 수 있도록 도와줘!',\n    cparty_jr_intro_4: '어서 책가방을 챙기러 가자! 아래쪽으로 가보는 거야~',\n    cparty_jr_intro_5: '우왓! 내 책가방이 멀리 떨어져 있어. 책가방이 있는 곳까지 안내해줄래?',\n    cparty_jr_intro_6: '책가방이 있어! 얼른 가지러 가자~',\n    cparty_jr_intro_7: '길 위에 내 연필이 있네. 연필들을 모아 책가방을 챙기러 가보자!',\n    cparty_jr_intro_8: '학교 가는 길에 연필이 있어! 연필을 모아 책가방을 챙기러 가보자!',\n    cparty_jr_intro_9: '내 책가방이 멀리 떨어져 있네? 가장 빠른 길로 책가방을 챙기러 가 보자.',\n    cparty_jr_intro_10: '가는 길에 연필을 모두 모으고 책가방을 챙기자!',\n    cparty_jr_intro_11:\n        '책가방을 챙기러 가려면 오른쪽으로 다섯 번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    cparty_jr_intro_12: '반복하기를 사용해서 책가방을 챙기러 가자.',\n    cparty_jr_intro_13:\n        '지금 블록으로는 책가방이 있는 쪽으로 갈 수가 없어. 반복 횟수를 바꿔 책가방을 챙기러 갈 수 있게 해줘.',\n    cparty_jr_intro_14: '반복 블록을 사용하여 책가방을 챙기러 가줘.',\n    cparty_jr_intro_15:\n        '학교가 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 학교에 도착 할수 있을 거야.',\n    make_new_project: '새로운 작품 만들기',\n    open_old_project: '저장된 작품 불러오기',\n    offline_download: '엔트리 다운로드',\n    offline_release: '엔트리 오프라인 에디터 출시!',\n    offline_description_1: '엔트리 오프라인 버전은',\n    offline_description_2: '인터넷이 연결되어 있지 않아도 사용할 수 있습니다. ',\n    offline_description_3: '지금 다운받아서 시작해보세요!',\n    sw_week_2015: '2015 소프트웨어교육 체험 주간',\n    cparty_desc: '두근두근 소프트웨어와의 첫만남',\n    entry_offline_download: '엔트리 오프라인 \\n다운로드',\n    entry_download_detail: '다운로드\\n바로가기',\n    offline_desc_1: '엔트리 오프라인 버전은 인터넷이 연결되어 있지 않아도 사용할 수 있습니다.',\n    offline_desc_2: '지금 다운받아서 시작해보세요!',\n    download: '다운로드',\n    version: '버전',\n    file_size: '크기',\n    update: '업데이트',\n    use_range: '사용범위',\n    offline_desc_free: '엔트리 오프라인은 기업과 개인 모두 제한 없이 무료로 사용하실 수 있습니다.',\n    offline_required: '최소 요구사항',\n    offline_required_detail: '디스크 여유 공간 1GB 이상, windows7 혹은 MAC OS 10.8 이상',\n    offline_notice: '설치 전 참고사항',\n    offline_notice_1: '1. 버전',\n    offline_notice_1_1: '에서는 하드웨어 연결 프로그램이 내장되어 있습니다.',\n    offline_notice_2: '2. 별도의 웹브라우져가 필요하지 않습니다.',\n    offline_notice_3: '버전 별 변경 사항 안내',\n    offline_notice_4: '버전별 다운로드',\n    offline_notice_5: '버전별 자세한 변경 사항 보기',\n    hardware_online_badge: '온라인',\n    hardware_title: '엔트리 하드웨어 연결 프로그램 다운로드',\n    hardware_desc:\n        '엔트리 온라인 ‘작품 만들기’에서 하드웨어를 연결하여 엔트리를 이용하는 경우에만 별도로 설치가 필요합니다.',\n    hardware_release:\n        '하드웨어 연결 프로그램의 자세한 변경 사항은 아래 주소에서 확인 할 수 있습니다.',\n    hardware_window_download: 'Windows 다운로드',\n    hardware_osx_download: 'Mac 다운로드',\n    cparty_jr_result_2:\n        '고마워~ 덕분에 책가방을 챙겨서 학교에 올 수 있었어~ <br>다음 학교 가는 길도 함께 가자~ ',\n    cparty_jr_result_3:\n        '우왓! 학교까지 왔어! <br>하지만 더 적은 블록을 사용해도 학교에 갈 수 있는데<br> 다시 해볼래?',\n    cparty_jr_result_4:\n        '우왓! 책가방을 얻었어!<br> 하지만 더 적은 블록을 사용해도 책가방을 얻을 수 있는데 <br>다시 해볼래? ',\n    lms_no_class: '아직 만든 학급이 없습니다.',\n    lms_create_class: '학급을 만들어 주세요.',\n    lms_add_class: '학급 만들기',\n    lms_base_class: '기본',\n    lms_delete_class: '삭제',\n    lms_my_class: '나의 학급',\n    lms_grade_1: '초등 1',\n    lms_grade_2: '초등 2',\n    lms_grade_3: '초등 3',\n    lms_grade_4: '초등 4',\n    lms_grade_5: '초등 5',\n    lms_grade_6: '초등 6',\n    lms_grade_7: '중등 1',\n    lms_grade_8: '중등 2',\n    lms_grade_9: '중등 3',\n    lms_grade_10: '일반',\n    lms_add_groupId_personal: '선생님께 받은 학급 아이디를 입력하여, 회원 정보에 추가하세요.',\n    lms_add_groupId: '학급 아이디 추가하기',\n    lms_add_group_account: '학급 계정 추가',\n    lms_enter_group_info: '발급받은 학급 아이디와 비밀번호를 입력하세요.',\n    lms_group_id: '학급 아이디',\n    lms_group_pw: '비밀번호',\n    lms_group_name: '소속 학급명',\n    personal_pwd_alert: '올바른 비밀번호 양식을 입력해 주세요',\n    personal_form_alert: '양식을 바르게 입력해 주세요',\n    personal_form_alert_2: '모든 양식을 완성해 주세요',\n    personal_no_pwd_alert: '비밀번호를 입력해 주세요',\n    select_gender: '성별을 선택해 주세요',\n    enter_group_id: '학급 아이디를 입력해 주세요',\n    enter_group_pwd: '비밀번호를 입력해 주세요',\n    info_added: '추가되었습니다',\n    no_group_id: '학급 아이디가 존재하지 않습니다',\n    no_group_pwd: '비밀번호가 일치하지 않습니다',\n    lms_please_choice: '선택해 주세요.',\n    group_lesson: '나의 학급 강의',\n    lms_banner_add_group: '학급 기능 도입',\n    lms_banner_entry_group: '엔트리 학급 만들기',\n    lms_banner_desc_1: '우리 반 학생들을 엔트리에 등록하세요!',\n    lms_banner_desc_2: '이제 보다 편리하고 쉽게 우리 반 학생들의 작품을 찾고,',\n    lms_banner_desc_3: '성장하는 모습을 확인할 수 있습니다. ',\n    lms_banner_download_manual: '메뉴얼 다운로드',\n    lms_banner_detail: '자세히 보기',\n    already_exist_email: '이미 존재하는 이메일 입니다.',\n    same_registered_email: '중복된 이메일 입니다.',\n    email_correnctly_please: '양식을 올바르게 입력해주세요.',\n    remove_project: '작품을 삭제하시겠습니까?',\n    study_lesson: '우리 반 학습하기',\n    open_project: '작품 불러오기',\n    make_group: '학급 만들기',\n    project_share: '작품 공유하기',\n    group_project_share: '학급 공유하기',\n    group_discuss: '학급 글 나누기',\n    my_profile: '마이 페이지',\n    search_updated: '최신 작품',\n    search_recent: '최근 조회수 높은 작품',\n    search_complexity: '최근 제작에 공들인 작품',\n    search_staffPicked: '스태프선정 작품 저장소',\n    search_childCnt: '사본이 많은 작품',\n    search_likeCnt: '최근 좋아요가 많은 작품',\n    search_recentLikeCnt: '최근 좋아요가 많은 작품',\n    gnb_share: '공유하기',\n    gnb_community: '커뮤니티',\n    lms_add_lectures: '강의 올리기',\n    lms_add_course: '강의 모음 올리기',\n    lms_add_homework: '과제 올리기',\n    remove_lecture_confirm: '강의를 정말 삭제하시겠습니까?',\n    popup_delete: '삭제하기',\n    remove_course_confirm: '강의 모음을 정말 삭제하시겠습니까?',\n    lms_no_lecture_teacher_1: '추가된 강의가 없습니다.',\n    lms_no_lecture_teacher_2: '우리 반 강의를 추가해 주세요.',\n    gnb_download: '다운로드',\n    lms_no_lecture_student_1: '아직 올라온 강의가 없습니다.',\n    lms_no_lecture_student_2: '선생님이 강의를 올려주시면,',\n    lms_no_lecture_student_3: '학습 내용을 확인할 수 있습니다.',\n    lms_no_class_teacher: '아직 만든 학급이 없습니다.',\n    lms_no_course_teacher_1: '추가된 강의 모음이 없습니다.',\n    lms_no_course_teacher_2: '우리 반 강의 모음을 추가해 주세요.',\n    lms_no_course_student_1: '아직 올라온 강의 모음이 없습니다.',\n    lms_no_course_student_2: '선생님이 강의 모음을  올려주시면,',\n    lms_no_course_student_3: '학습 내용을 확인할 수 있습니다.',\n    lms_no_hw_teacher_1: '추가된 과제가 없습니다.',\n    lms_no_hw_teacher_2: '우리 반 과제를 추가해 주세요.',\n    lms_no_hw_student_1: '아직 올라온 과제가 없습니다.',\n    lms_no_hw_student_2: '선생님이 과제를 올려주시면,',\n    lms_no_hw_student_3: '학습 내용을 확인할 수 있습니다.',\n    modal_edit: '수정하기',\n    modal_deadline: '마감일 설정',\n    modal_hw_desc: '상세설명 (선택)',\n    desc_optional: '',\n    modal_create_hw: '과제 만들기',\n    vol: '회차',\n    hw_title: '과제명',\n    hw_description: '내용',\n    deadline: '마감일',\n    do_homework: '과제하기',\n    hw_progress: '진행 상태',\n    hw_submit: '제출',\n    view_list: '명단보기',\n    view_desc: '내용보기',\n    do_submit: '제출하기',\n    popup_notice: '알림',\n    no_selected_hw: '선택된 과제가 없습니다.',\n    hw_delete_confirm: '선택한 과제를 정말 삭제하시겠습니까?',\n    hw_submitter: '과제 제출자 명단',\n    hw_student_desc_1: \"* '제출하기'를 눌러 제출을 완료하기 전까지 얼마든지 수정이 가능합니다\",\n    hw_student_desc_2: '* 제출 기한이 지나면 과제를 제출할 수 없습니다.',\n    popup_create_class: '학급 만들기',\n    class_name: '학급 이름',\n    image: '이미지',\n    select_class_image: '학급 이미지를 선택해 주세요.',\n    type_class_description: '학급 소개 입력',\n    set_as_primary_group: '기본학급으로 지정',\n    set_primary_group: '지정',\n    not_primary_group: '지정안함',\n    type_class_name: '학급 이름을 입력해주세요. ',\n    type_class_description_long: '학급 소개를 입력해 주세요. 170자 이내',\n    add_students: '학생 추가하기',\n    invite_students: '학생 초대하기',\n    invite_with_class: '1. 학급 코드로 초대하기',\n    invite_code_expiration: '코드 만료시간',\n    generate_code_button: '코드재발급',\n    generate_code_desc: '학생의 학급 코드 입력 방법',\n    generate_code_desc1: '엔트리 홈페이지에서 로그인을 해주세요.',\n    generate_code_desc2: '메뉴바에서<나의 학급>을 선택해주세요.',\n    generate_code_desc3: '<학급코드 입력하기>를 눌러 학급코드를 입력해주세요.',\n    invite_with_url: '2. 학급 URL로 초대하기',\n    copy_invite_url: '복사하기',\n    download_as_pdf: '학급계정 PDF로 내려받기',\n    download_as_excel: '학급계정 엑셀로 내려받기',\n    temp_password: '임시 비밀번호 발급',\n    step_name: '이름 입력',\n    step_info: '정보 추가/수정',\n    preview: '미리보기',\n    type_name_enter: '학급에 추가할 학생의 이름을 입력하고 엔터를 치세요.',\n    multiple_name_possible: '여러명의 이름 입력이 가능합니다.',\n    id_auto_create: '학번은 별도로 수정하지 않으면 자동으로 생성됩니다.',\n    student_id_desc_1: '학급 아이디는 별도의 입력없이 자동으로 생성됩니다.',\n    student_id_desc_2: '단, 엔트리에 이미 가입된 학생을 학급에 추가한다면 학생의 엔트리 아이디를',\n    student_id_desc_3: '입력해주세요. 해당 학생은 로그인 후, 학급 초대를 수락하면 됩니다.',\n    student_number: '학번',\n    temp_password_desc_1: '임시 비밀번호로 로그인 후,',\n    temp_password_desc_2: '신규 비밀번호를 다시 설정할 수 있도록 안내해주세요.',\n    temp_password_desc_3: '*한번 발급된 임시 비밀번호는 다시 볼 수 없습니다.',\n    temp_password_demo: '로그인 불가능한 안내 용 예시 계정입니다.',\n    temp_works: '작품 보기',\n    student_delete_confirm: '학생을 정말 삭제하시겠습니까?',\n    no_student_selected: '선택된 학생이 없습니다.',\n    class_assignment: '학급 과제',\n    class_list: '학급 목록',\n    select_grade: '학년을 선택 하세요.',\n    add_project: '작품 공유하기',\n    no_project_display: '학생들이 전시한 작품이 없습니다.',\n    plz_display_project: '나의 작품을 전시해 주세요.',\n    refuse_confirm: '학급 초대를 정말 거절하시겠습니까?',\n    select_class: '학급 선택',\n    group_already_registered: '이미 가입된 학급입니다.',\n    my_page_entry: '엔트리',\n    my_page_title: '마이페이지',\n    my_classGroup_title: '나의 학급',\n    my_classGroup_title_view: '나의 학급 보기',\n    my_space_area: '나만의 공간',\n    mon: '월',\n    tue: '화',\n    wed: '수',\n    thu: '목',\n    fri: '금',\n    sat: '토',\n    sun: '일',\n    jan: '1월',\n    feb: '2월',\n    mar: '3월',\n    apr: '4월',\n    may: '5월',\n    jun: '6월',\n    jul: '7월',\n    aug: '8월',\n    sep: '9월',\n    oct: '10월',\n    nov: '11월',\n    dec: '12월',\n    plz_select_lecture: '강의를 선택해 주세요.',\n    plz_set_deadline: '마감일을 설정해 주세요.',\n    hide_entry: '엔트리 가리기',\n    hide_others: '기타 가리기',\n    show_all: '모두 보기',\n    lecture_description:\n        '선생님들이 직접 만드는 엔트리 학습 공간입니다. 강의에서 예시작품을 보고 작품을 만들며 배워 보세요.',\n    curriculum_description:\n        '학습 순서와 주제에 따라 여러 강의가 모아진 학습 공간입니다. 강의 모음의 순서에 맞춰 차근차근 배워보세요.',\n    linebreak_off_desc_1: '글상자의 크기가 글자의 크기를 결정합니다.',\n    linebreak_off_desc_2: '내용을 한 줄로만 작성할 수 있습니다.',\n    linebreak_off_desc_3: '새로운 글자가 추가되면 글상자의 좌우 길이가 길어집니다.',\n    linebreak_on_desc_1: '글상자의 크기가 글자가 쓰일 수 있는 영역을 결정합니다.',\n    linebreak_on_desc_2: '내용 작성시 엔터키로 줄바꿈을 할 수 있습니다.',\n    linebreak_on_desc_3:\n        '새로운 글자 추가 시 문장의 길이가 글상자의 가로 영역을 넘어가면 자동으로 줄이 바뀝니다.',\n    not_supported_text: '해당 글씨체는 한자를 지원하지 않습니다.',\n    entry_with: '함께 만드는 엔트리',\n    ebs_season_1: '시즌 1 보러가기',\n    ebs_season_2: '시즌 2 보러가기',\n    hello_ebs: '헬로! EBS 소프트웨어',\n    hello_ebs_desc:\n        '<헬로! EBS 소프트웨어> 엔트리 버전의 양방향 서비스를 만나보세요! \\n <헬로! EBS 소프트웨어>의 동영상 강의를 통해 \\n 소프트웨어 코딩의 기본 개념을 배운 후 양방향 코딩 미션에 도전하세요!\\n 방송에서는 볼 수 없었던 <대.소.동> 친구들의 \\n 비하인드 스토리를 볼 수 있습니다!',\n    hello_ebs_sub_1: 'EBS 중학 엔트리 버전의 양방향 서비스를 ',\n    hello_ebs_sub_2: '만나보세요! ',\n    exhibit_4th_title: '엔트리 4주년 기념',\n    exhibit_4th_subtitle: '엔트리 작품 공모전',\n    exhibit_4th_desc1: '엔트리 탄생 4주년을 기념하여 작품 공모전을 개최합니다.',\n    exhibit_4th_desc2: '‘우리 모두를 위한 소프트웨어’를 주제로',\n    exhibit_4th_desc3: '여러분의 멋진 작품을 뽐내보세요!',\n    exhibit_4th_button: '자세히 보기',\n    visang_edu_entry: '비상교육 엔트리 학습하기',\n    cmass_edu_entry: '씨마스 엔트리 학습하기',\n    chunjae_edu_entry: '천재교과서 엔트리 학습하기',\n    kumsungemt_edu_entry: '금성출판사 엔트리 학습하기',\n    kumsungMid_edu_entry: '금성출판사 엔트리 학습하기',\n    gilbutEdu_edu_entry: '길벗출판사 엔트리 학습하기',\n    miraenCoding_edu_entry: '미래엔 엔트리 학습하기',\n    textbook_help_data: '도움자료',\n    textbook_teaching_activity: '수업 교안&활동지',\n    textbook_kyohacksa: '교학사',\n    textbook_kumsung: '금성출판사',\n    textbook_donga: '동아출판',\n    textbook_chunjae: '천재교과서',\n    textbook_miraen: '미래엔',\n    textbook_visang: '비상교육',\n    partner: '파트너',\n    project_term_popup_title: '작품 공개에 따른 엔트리 저작권 정책 동의',\n    project_term_popup_description_1: '작품 공개를 위해',\n    project_term_popup_description_2: '아래 정책을 확인해주세요.',\n    project_term_popup_description_3: '',\n    project_term_popup_description_4: '',\n    project_term_agree_1_1: '내가 만든 작품과 그 소스코드의 공개를 동의합니다.',\n    project_term_agree_2_1: '다른 사람이 나의 작품을 이용하는 것을 허락합니다.',\n    project_term_agree_2_2: '( 복제 , 배포 , 공중송신 포함 )',\n    project_term_agree_3_1: '다른 사람이 나의 작품을 수정하는 것을 허락합니다.',\n    project_term_agree_3_2: '( 리믹스, 변형, 2차 제작물 작성 포함)',\n    agree_all: '전체 동의',\n    select_login: '로그인 선택',\n    select: '선택하세요',\n    with_login: '로그인 하고',\n    without_login: '로그인 안하고',\n    start_challenge: '미션 도전하기',\n    start_challenge_2: '미션 도전하기',\n    if_not_save_not_login: '* 로그인을 안하고 미션에 참여하시면 진행 상황이 저장되지 않습니다.',\n    if_not_member_yet: '엔트리 회원이 아니라면?',\n    join_entry: '엔트리 회원 가입하기',\n    learned_computing: '기존에 소프트웨어 교육을 받아보셨나요?',\n    cparty_index_description_1: '두근두근 소프트웨어와 첫 만남.',\n    cparty_index_description_2:\n        '소프트웨어랑 재미있게 놀다 보면 소프트웨어의 원리도 배우고,  생각하는 힘도 쑥쑥!',\n    cparty_index_description_3: '엔트리를 통해 코딩 미션에 도전하고 인증서 받으세요.',\n    cparty_index_description_4: '2015 Online Coding Party는',\n    cparty_index_description_5: 'SW교육 체험 주간',\n    cparty_index_description_6: '의 일환으로써,',\n    cparty_index_description_7: '초등컴퓨팅교사협회',\n    cparty_index_description_8: '과 함께 만들어졌습니다.',\n    cparty_index_description_9: '2016 Online Coding Party는',\n    cparty_index_description_10: '2017 Online Coding Party는',\n    cparty_index_description_11: \"'SW교육을 준비하는 선생님들의 모임'\",\n    congratulation: '축하 드립니다!',\n    warm_up: '체험',\n    beginner: '입문',\n    intermediate: '기본',\n    advanced: '발전',\n    applied: '응용',\n    cert_msg_tail: '과정을 성공적으로 마쳤습니다.',\n    cert_msg_head: '',\n    maze_text_content_1:\n        '안녕? 나는 엔트리봇이야. 지금 나는 공장에서 탈출을 해야 해! 탈출하기 위해서 먼저 몸을 고쳐야 할 것 같아. 앞에 있는 부품을 얻을 수 있게 도와줄래? move()',\n    maze_text_content_2:\n        '좋아 아주 잘했어! 덕분에 몸이 한결 가벼워졌어! 이번에도 부품상자까지 나를 이동시켜줘. 그런데 가는길에 장애물이 있어. 장애물 앞에서는 jump()',\n    maze_text_content_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 오른쪽, 왼쪽으로 회전할 수 있는 right(); left(); 명령어를 쓰면 충분히 갈 수 있을것 같아!',\n    maze_text_content_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 지금까지 배운 명령어를 같이 써서 저 부품상자까지 가보자!',\n    maze_text_content_5:\n        '우와 부품이 두 개나 있잖아! 두 개 다 챙겨서 가자! 그러면 몸을 빨리 고칠 수 있을 것 같아!',\n    maze_text_content_6:\n        '이번이 마지막 부품들이야! 저것들만 있으면 내 몸을 다 고칠 수 있을 거야! 이번에도 도와줄 거지?',\n    maze_text_content_7:\n        '덕분에 몸이 아주 좋아졌어! 이제 똑같은 일을 여러 번 반복해도 무리는 없을 거야. 어? 그런데 앞에 있는 저 로봇은 뭐지? 뭔가 도움이 필요한 것 같아! 도와주자! for 명령어를 사용해서 저 친구한테 나를 데려다줘!',\n    maze_text_content_8:\n        '좋아! 덕분에 친구 로봇을 살릴 수 있었어! 하지만 앞에도 도움이 필요한 친구가 있네, 하지만 이번에는 벌집이 있으니까 조심해서 벌집에 안 닿게 뛰어넘어가자! 할 수 있겠지? 이번에도 for 명령어를 사용해서 친구가 있는곳까지 나를 이동시켜줘!',\n    maze_text_content_9:\n        '이번에는 for 명령어 대신 미션이 끝날때까지 같은 일을 반복하도록 하는 while 명령어를 사용해봐! 나를 친구에게 데려다주면 미션이 끝나!',\n    maze_text_content_10:\n        '이번에는 if 명령어가 나왔어! if와 while 명령어를 사용해서 내가 언제 어느 쪽으로 회전해야 하는지 알려줘!',\n    maze_text_content_11:\n        '좋아 아까 했던 것처럼 해볼까? 언제 왼쪽으로 돌아야 하는지 알려줄 수 있겠어?',\n    maze_text_content_12: '이번에는 중간중간 벌집(bee)이 있네? 언제 뛰어넘어가야 할지 알려줄래?',\n    maze_text_content_13: '여기저기 도움이 필요한 친구들이 많이 있네! 모두 가서 도와주자!',\n    maze_text_content_14:\n        '우와 이번에도 도와줘야 할 친구들이 많네. 먼저 조그마한 사각형을 돌도록 명령어를 만들고 만든 걸 반복해서 모든 친구를 구해보자.',\n    maze_text_content_15:\n        '오래 움직이다 보니 벌써 지쳐버렸어. 자주 쓰는 명령어를 function 명령어를 사용해서 함수로 만들어 놓았어! 함수를 사용하여 나를 배터리 까지 이동시켜줘!',\n    maze_text_content_16:\n        '좋아 멋진걸! 그럼 이번에는 함수에 들어갈 명령어들을 넣어서 나를 배터리까지 이동시켜줘!',\n    maze_text_content_17:\n        '좋아 이번에는 함수를 만들고, 함수를 사용해서 배터리를 얻을 수 있도록 도와줘! 함수를 만들때 jump();를 잘 섞어봐!',\n    maze_text_content_18:\n        '이번에는 길이 좀 복잡한걸? 그래도 언제 left();를 쓰고, 언제 right();를 쓰면 되는지 알려만 주면 배터리 까지 갈 수 있겠어!.',\n    maze_text_content_19:\n        '이번에는 함수가 미리 정해져 있어! 그런데 함수만 써서 배터리까지 가기 힘들것 같아. 함수와 다른 명령어들을 섞어 써서 배터리 까지 이동시켜줘!',\n    maze_text_content_20:\n        '좋아! 지금까지 정말 멋지게 잘 해줬어. 덕분에 이제 마지막 배터리만 채우면 앞으로는 충전이 필요 없을 거야. 함수를 이용해서 저 배터리를 얻고 내가 자유롭게 살 수 있도록 도와줘!',\n    maze_content_1:\n        '안녕 나는 엔트리봇이라고 해. 지금 나는 공장에서 탈출하려는데 먼저 몸을 고쳐야 할 것 같아. 앞에 있는 부품을 얻을 수 있게 도와줄래? 앞으로 가기 블록을 조립하고 시작을 눌러봐.',\n    maze_content_2:\n        '좋아 아주 잘했어! 덕분에 몸이 한결 가벼워졌어! 앞에도 부품이 있는데 이번에는 잘못 가다간 감전되기 쉬울 것 같아. 한 번 장애물 뛰어넘기 블록을 써서 부품까지 가볼까?',\n    maze_content_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 회전하기 블록을 쓰면 충분히 갈 수 있을 것 같아! 이번에도 도와줄 거지?',\n    maze_content_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 회전과 뛰어넘기를 같이 써서 저 부품을 얻어보자!',\n    maze_content_5:\n        '우와 부품이 두 개나 있잖아! 두 개 다 챙겨서 가자! 그러면 몸을 빨리 고칠 수 있을 것 같아!',\n    maze_content_6:\n        '이번이 마지막 부품들이야! 저것들만 있으면 내 몸을 다 고칠 수 있을 거야! 이번에도 도와줄 거지?',\n    maze_content_7:\n        '덕분에 몸이 아주 좋아졌어! 이제 똑같은 일을 여러 번 반복해도 무리는 없을 거야. 어? 그런데 앞에 있는 저 로봇은 뭐지? 뭔가 도움이 필요한 것 같아! 도와주자! 얼른 반복하기의 숫자를 바꿔서 저 친구한테 나를 데려다줘!',\n    maze_content_8:\n        '좋아! 덕분에 친구 로봇을 살릴 수 있었어! 하지만 앞에도 도움이 필요한 친구가 있는 것 같아, 하지만 이번에는 벌집이 있으니까 조심해서 벌집에 안 닿게 뛰어넘어가자! 할 수 있겠지? 그럼 아까 했던 것처럼 반복을 써서 친구한테 갈 수 있게 해줄래?',\n    maze_content_9:\n        '이번에는 숫자만큼 반복하는 게 아니라 친구 로봇한테 갈 때까지 똑같은 일을 반복할 수 있어! 이번에도 친구를 구할 수 있도록 도와줘!',\n    maze_content_10:\n        '이번에는 만약 블록이란 게 있어! 만약 블록을 써서 언제 어느 쪽으로 돌아야 하는지 알려줘!',\n    maze_content_11: '좋아 아까 했던 것처럼 해볼까? 언제 왼쪽으로 돌아야 하는지 알려줄 수 있겠어?',\n    maze_content_12: '이번에는 중간중간 벌집이 있네? 언제 뛰어넘어가야 할지 알려줄래?',\n    maze_content_13: '여기저기 도움이 필요한 친구들이 많이 있네! 모두 도와주자!',\n    maze_content_14:\n        '우와 이번에도 도와줘야 할 친구들이 많네. 먼저 조그마한 사각형을 돌도록 블록을 만들고 만든 걸 반복해서 모든 친구를 구해보자.',\n    maze_content_15:\n        '반복을 하도 많이 했더니 자주 쓰는 블록은 외울 수 있을 것 같아! 약속 블록은 지금 내가 외운 블록들이야! 일단은 오래 움직여서 지쳤으니까 배터리를 좀 채울 수 있게 약속 호출 블록을 써서 배터리를 채울 수 있게 해줘!',\n    maze_content_16:\n        '좋아 멋진걸! 그럼 이번에는 네가 자주 쓰일 블록을 나한테 가르쳐줘! 약속 정의 블록 안에 자주 쓰일 블록을 넣어보면 돼!',\n    maze_content_17:\n        '좋아 이번에도 그러면 약속을 이용해서 배터리를 얻을 수 있도록 도와줄 거지? 약속에 뛰어넘기를 잘 섞어봐!',\n    maze_content_18:\n        '이번에는 길이 좀 복잡한걸? 그래도 언제 왼쪽으로 돌고, 언제 오른쪽으로 돌면 되는지 알려만 주면 충전할 수 있을 것 같아.',\n    maze_content_19:\n        '이번에는 약속이 미리 정해져 있어! 그런데 바로 약속을 쓰기에는 안될 것 같아. 내가 갈 길을 보고 약속을 쓰면 배터리를 채울 수 있을 것 같은데 도와줄 거지?',\n    maze_content_20:\n        '좋아! 지금까지 정말 멋지게 잘 해줬어. 덕분에 이제 마지막 배터리만 채우면 앞으로는 충전이 필요 없을 거야. 그러니까 약속을 이용해서 저 배터리를 얻고 내가 자유롭게 살 수 있도록 도와줄래?',\n    maze_content_21:\n        '안녕? 나는 엔트리 봇이야. 지금 많은 친구들이 내 도움을 필요로 하고 있어. 반복하기를 이용해서 친구들을 도울수 있게 데려다 줘!',\n    maze_content_22: '고마워! 이번에는 벌집을 뛰어넘어서 친구를 구하러 갈 수 있게 도와줘!',\n    maze_content_23:\n        '좋아! 이번에는 친구 로봇한테 갈 때까지 반복하기를 이용해서 친구를 도울 수 있게 도와줘!',\n    maze_content_24:\n        '안녕! 나는 엔트리 봇이야. 지금 나는 너무 오래 움직여서 배터리를 채워야 해. 약속 불러오기를 써서 배터리를 채울 수 있도록 도와줘!',\n    maze_content_25: '멋져! 이번에는 여러 약속을 불러와서 배터리가 있는 곳까지 가보자!',\n    maze_content_26:\n        '좋아! 이제 약속할 블록을 나한테 가르쳐줘! 약속하기 블록 안에 자주 쓰일 블록을 넣으면 돼!',\n    maze_content_27:\n        '지금은 미리 약속이 정해져 있어. 그런데, 약속을 쓰기위해서는 내가 갈 방향을 보고 약속을 사용해야해. 도와줄거지?',\n    maze_content_28: '드디어 마지막이야! 약속을 이용하여 마지막 배터리를 얻을 수 있게 도와줘!',\n    ai_content_1:\n        '안녕? 나는 엔트리봇이라고 해. 우주 탐사를 마치고 지구로 돌아가려는데 우주를 떠다니는 돌들 때문에 쉽지 않네. 내가 안전하게 집에 갈 수 있도록 도와줄래? 나의 우주선에는 나의 앞과 위, 아래에 무엇이 어느 정도의 거리에 있는지 알려주는 레이더가 있어 너의 판단을 도와줄 거야!',\n    ai_content_2:\n        '고마워! 덕분에 돌을 쉽게 피할 수 있었어. 그런데 이번엔 더 많은 돌이 있잖아? 블록들을 조립하여 돌들을 이리저리 잘 피해 보자!',\n    ai_content_3:\n        '좋았어! 안전하게 돌을 피했어. 그런데 앞을 봐! 아까보다 더 많은 돌이 있어. 하지만 걱정하지 마. 나에게 반복하기 블록이 있거든. 반복하기 블록 안에 움직이는 블록을 넣으면 목적지에 도착할 때까지 계속 움직일게!',\n    ai_content_4:\n        '대단해! 반복하기 블록을 쓰니 많은 돌을 피하기가 훨씬 수월한걸! 하지만 이렇게 일일이 조종하기는 피곤하다. 나에겐 레이더가 있으니 앞으로 무엇이 나올지 알 수 있어. 앞으로 계속 가다가 앞에 돌이 있으면 피할 수 있도록 해줄래?',\n    ai_content_5:\n        '잘했어! 여기까지 와서 아주 기뻐. 이번에는 레이더가 앞에 있는 물체까지의 거리를 말해줄 거야. 이 기능을 사용하여 돌을 피해 보자! 돌까지의 거리가 멀 때는 앞으로 계속 가다가, 거리가 가까워지면 피할 수 있도록 해줄래?',\n    ai_content_6:\n        '와~ 멋진걸? 레이더를 활용하여 돌을 잘 피해 나가고 있어! 이번에는 여러 개의 레이더를 사용하여 이리저리 돌들을 피해 나갈 수 있게 만들어줄래?',\n    ai_content_7:\n        '휴~ 지구에 점점 가까워지고 있어! 돌을 피할 때 기왕이면 더 안전한 길로 가고 싶어! 아마도 돌이 더 멀리 있는 쪽이 더 안전한 길이겠지? 위쪽 레이더와 아래쪽 레이더를 비교하여 더 안전한 쪽으로 움직이도록 해줄래?',\n    ai_content_8:\n        '좋아! 덕분에 무사히 비행하고 있어. 어? 그런데 저게 뭐지? 저건 내가 아주 위급한 상황에서 사용할 수 있는 특별한 에너지야! 이번에는 저 아이템들을 모두 모으며 움직이자!',\n    ai_content_9:\n        '훌륭해! 이제 지구까지 얼마 안 남았어. 그런데 앞을 보니 돌들로 길이 꽉 막혀서 지나갈 수가 없잖아? 하지만 걱정하지 마. 아이템을 획득해서 사용하면 앞에 있는 꽉 막힌 돌들을 없앨 수 있다고!',\n    ai_content_10:\n        '좋아! 드디어 저기 지구가 보여! 이럴 수가! 이제는 날아오는 돌들을 미리 볼 수가 없잖아? 돌들이 어떻게 날아올지 알지 못해도 지금까지처럼만 움직이면 잘 피할 수 있을 것 같아! 지구까지 가보는 거야!',\n    maze_hints_title_1: '시작 방법',\n    maze_hints_content_1: '엔트리봇은 어떻게 움직이나요?',\n    maze_hints_detail_1:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐<br>2. 다 조립했으면, 시작을 눌러봐<br>3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_hints_title_2: '장애물 뛰어넘기',\n    maze_hints_content_2: '장애물이 있으면 어떻게 해야하나요?',\n    maze_hints_detail_2:\n        '길을 가다보면 장애물을 만날 수 있어.<br>장애물이 앞에 있을 때에는 뛰어넘기 블록을 사용해야 해.',\n    maze_hints_title_3: '반복 블록(1)',\n    maze_hints_content_3: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_hints_detail_3:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해.<br>반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼.',\n    maze_hints_title_4: '반복 블록(2)',\n    maze_hints_content_4: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_hints_detail_4:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어.<br>반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼.<br>그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_hints_title_5: '만약 블록',\n    maze_hints_content_5: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_hints_detail_5:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어.<br>앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고<br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_hints_title_6: '반복 블록(3)',\n    maze_hints_content_6: '모든 ~를 만날 때 까지 블록은 어떻게 동작하나요?',\n    maze_hints_detail_6:\n        '모든 {타일}에 한 번씩 도착할 때까지 그 안에 있는 블록을 반복해서 실행해.<br>모든 {타일}에 한 번씩 도착하면 반복이 멈추게 될 거야.',\n    maze_hints_title_7: '특별 힌트',\n    maze_hints_content_7: '너무 어려워요. 도와주세요.',\n    maze_hints_detail_7:\n        '내가 가야하는 길을 자세히 봐. 작은 사각형 4개가 보여?<br>작은 사각형을 도는 블록을 만들고, 반복하기를 사용해 보는것은 어때?',\n    maze_hints_title_8: '약속',\n    maze_hints_content_8: '약속하기/약속 불러오기 무엇인가요? 어떻게 사용하나요?',\n    maze_hints_detail_8:\n        \"나를 움직이기 위해 자주 쓰는 블록들의 묶음을 '약속하기' 블록 아래에 조립하여 약속으로 만들 수 있어.<br>한번 만들어 놓은 약속은 '약속 불러오기' 블록을 사용하여 여러 번 꺼내 쓸 수 있다구.\",\n    ai_hints_title_1_1: '게임의 목표',\n    ai_hints_content_1_1: '돌을 피해 오른쪽 행성까지 안전하게 이동할 수 있도록 도와주세요.',\n    ai_hints_detail_1_1: '돌을 피해 오른쪽 행성까지 안전하게 이동할 수 있도록 도와주세요.',\n    ai_hints_title_1_2: '시작 방법',\n    ai_hints_content_1_2: '어떻게 시작할 수 있나요?',\n    ai_hints_detail_1_2:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐<br>2. 다 조립했으면, 시작을 눌러봐<br>3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    ai_hints_title_1_3: '움직이게 하기',\n    ai_hints_content_1_3: '엔트리봇은 어떻게 움직이나요?',\n    ai_hints_detail_1_3:\n        '나는 위쪽으로 가거나 앞으로 가거나 아래쪽으로 갈 수 있어.<br>방향을 정할 때에는 돌이 없는 방향으로 안전하게 갈 수 있도록 해줘.<br>나를 화면 밖으로 내보내면 우주미아가 되어버리니 조심해!',\n    ai_hints_title_2_1: '게임의 목표',\n    ai_hints_content_2_1: '반복하기 블록으로 돌들을 피할 수 있도록 도와주세요.',\n    ai_hints_detail_2_1: '반복하기 블록으로 돌들을 피할 수 있도록 도와주세요.',\n    ai_hints_title_2_2: '반복 블록',\n    ai_hints_content_2_2: '반복 블록은 무슨 블록인가요?',\n    ai_hints_detail_2_2:\n        '휴~ 이번에 가야 할 길은 너무 멀어서 하나씩 조립하기는 힘들겠는걸? 반복하기블록을 사용해봐.<br>똑같이 반복되는 블록들을 반복하기 블록으로 묶어주면 아주 긴 블록을 짧게 줄여줄 수 있어!',\n    ai_hints_content_3_1: '만약 블록으로 돌을 피할 수 있도록 도와주세요.',\n    ai_hints_title_3_2: '만약 블록(1)',\n    ai_hints_content_3_2: '만약 ~라면 블록은 어떻게 동작하나요?',\n    ai_hints_detail_3_2:\n        \"만약 앞에 ~가 있다면 / 아니면 블록을 사용하면 내 바로 앞에 돌이 있는지 없는지 확인해서 다르게 움직일 수 있어~<br>만약 내 바로 앞에 돌이 있다면 '만약' 아래에 있는 블록들을 실행하고 돌이 없으면 '아니면' 안에 있는 블록들을 실행할 거야.<br>내 바로 앞에 돌이 있을 때와 없을 때, 어떻게 움직일지 잘 결정해줘~\",\n    ai_hints_content_4_1: '레이더의 사용 방법을 익히고 돌을 피해보세요.',\n    ai_hints_detail_4_1: '레이더의 사용 방법을 익히고 돌을 피해보세요.',\n    ai_hints_title_4_2: '레이더(1)',\n    ai_hints_content_4_2: '레이더란 무엇인가요? 어떻게 활용할 수 있나요?',\n    ai_hints_detail_4_2:\n        \"레이더는 지금 내가 물체와 얼마나 떨어져 있는지 알려주는 기계야.<br>만약 바로 내 앞에 무엇인가 있다면 앞쪽 레이더는 '1'을 보여줘.<br>또, 레이더는 혼자 있을 때 보다 만약 &lt;사실&gt;이라면 / 아니면 블록과<br> 같이 쓰이면 아주 강력하게 쓸 수 있어.<br>예를 들어 내 앞에 물체와의 거리가 1보다 크다면 나는 안전하게 앞으로 갈 수 있겠지만, 아니라면 위나 아래쪽으로 피하도록 할 수 있지.\",\n    ai_hints_title_4_3: '만약 블록(2)',\n    ai_hints_content_4_3: '만약 <사실>이라면 블록은 어떻게 사용하나요?',\n    ai_hints_detail_4_3:\n        \"만약 &lt;사실&gt;이라면 / 아니면 블록은 &lt;사실&gt; 안에 있는 내용이 맞으면 '만약' 아래에 있는 블록을 실행하고, 아니면 '아니면' 아래에 있는 블록을 실행해.<br>어떤 상황에서 다르게 움직이고 싶은 지를 잘 생각해서 &lt;사실&gt; 안에 적절한 판단 조건을 만들어 넣어봐.<br>판단 조건을 만족해서 '만약' 아래에 있는 블록을 실행하고 나면 '아니면' 아래에 있는 블록들은 실행되지 않는다는 걸 기억해!\",\n    ai_hints_content_5_1: '레이더를 활용해 돌을 쉽게 피할 수 있도록 도와주세요.',\n    ai_hints_detail_5_1: '레이더를 활용해 돌을 쉽게 피할 수 있도록 도와주세요.',\n    ai_hints_title_5_2: '만약 블록(3)',\n    ai_hints_content_5_2: '만약 블록이 겹쳐져 있으면 어떻게 동작하나요?',\n    ai_hints_detail_5_2:\n        '만약 ~ / 아니면 블록안에도 만약 ~ / 아니면 블록을 넣을 수 있어! 이렇게 되면 다양한 상황에서 내가 어떻게 행동해야 할지 정할 수 있어.<br>예를 들어 앞에 돌이 길을 막고 있을때와 없을때의 행동을 정한다음, 돌이 있을때의 상황에서도 상황에 따라 위쪽으로 갈지 아래쪽으로 갈지 선택 할 수 있어',\n    ai_hints_title_6_1: '레이더(2)',\n    ai_hints_content_6_1: '위쪽 레이더와 아래쪽 레이더의 값을 비교하고 싶을 땐 어떻게 하나요?',\n    ai_hints_detail_6_1:\n        '([위쪽]레이더) 블록은 위쪽 물체까지의 거리를 뜻하는 블록이야.<br>아래쪽과 위쪽 중에서 어느 쪽에 돌이 더 멀리 있는지 확인하기 위해서 쓸 수 있는 블록이지.<br>돌을 피해가는 길을 선택할 때에는 돌이 멀리 떨어져 있는 쪽으로 피하는게 앞으로 멀리 가는데 유리할거야~',\n    ai_hints_content_7_1: '아이템을 향해 이동하여 돌을 피해보세요.',\n    ai_hints_detail_7_1: '아이템을 향해 이동하여 돌을 피해보세요.',\n    ai_hints_title_7_2: '물체 이름 확인',\n    ai_hints_content_7_2: '앞으로 만날 물체의 이름을 확인해서 무엇을 할 수 있나요?',\n    ai_hints_detail_7_2:\n        '아이템을 얻기위해서는 아이템이 어디에 있는지 확인할 필요가 있어. <br>그럴 때 사용할 수 있는 블록이 [위쪽] 물체는 [아이템]인가? 블록이야.<br>이 블록을 활용하면 아이템이 어느 위치에 있는지 알 수 있고 아이템이 있는 방향으로 움직이도록 블록을 조립할 수 있어.',\n    ai_hints_content_8_1: '아이템을 적절하게 사용해서 돌을 피해보세요.',\n    ai_hints_detail_8_1: '아이템을 적절하게 사용해서 돌을 피해보세요.',\n    ai_hints_title_8_2: '아이템',\n    ai_hints_content_8_2: '아이템은 어떻게 얻고 사용하나요?',\n    ai_hints_detail_8_2:\n        '돌들을 이리저리 잘 피해 나가더라도 앞이 모두 돌들로 꽉 막혀있을 땐 빠져나갈 방법이 없겠지? 그럴 때에는 아이템사용 블럭을 사용해봐. <br>이 블록은 내 앞의 돌들을 모두 없애는 블록이야.<br>단, 아이템이 있어야지만 블록을 사용할 수 있고, 아이템은 이미지를 지나면 얻을 수 있어.',\n    ai_hints_content_9_1: '지금까지 배운 것들을 모두 활용해서 최대한 멀리 가보세요.',\n    ai_hints_detail_9_1: '지금까지 배운 것들을 모두 활용해서 최대한 멀리 가보세요.',\n    ai_hints_title_9_2: '그리고',\n    ai_hints_content_9_2: '그리고 블록은 어떻게 사용하나요?',\n    ai_hints_detail_9_2:\n        '그리고 블록에는 여러개의 조건을 넣을 수 있어, 넣은 모든 조건이 사실일때만 사실이 되어 만약 블록 안에 있는 블록이 실행되고, 하나라도 거짓이 있으면 거짓으로 인식해서 그 안에 있는 블록을 실행하지 않아',\n    maze_text_goal_1: 'move(); 명령어를 사용하여 부품 상자까지 나를 이동시켜줘!',\n    maze_text_goal_2: 'jump(); 명령어로 장애물을 피해 부품 상자까지 나를 이동시켜줘!',\n    maze_text_goal_3: 'left(); right(); 명령어로 부품상자까지 나를 이동시켜줘!',\n    maze_text_goal_4: '여러가지 명령어를 사용하여 부품상자까지 나를 이동시켜줘!',\n    maze_text_goal_5: '두 부품상자에 다 갈 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_6: '두 부품상자에 다 갈 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_7: 'for 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_8: 'for 명령어를 사용하고, 장애물을 피해 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_9: 'while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_10: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_11: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_12: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_13:\n        'while과 for 명령어를 사용하여 모든 친구들을 만날 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_14:\n        'while과 for 명령어를 사용하여 모든 친구들을 만날 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_15: '함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_16: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_17: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_18: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_19: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_20: '함수와 다른명령어들을 섞어 사용하여 배터리까지 나를 이동시켜줘!',\n    maze_attack_range: '공격 가능 횟수',\n    maze_attack: '공격',\n    maze_attack_both_sides: '양 옆 공격',\n    above_radar: '위쪽 레이더',\n    above_radar_text_mode: 'radar_up',\n    bottom_radar: '아래쪽 레이더',\n    bottom_radar_text_mode: 'radar_down',\n    front_radar: '앞쪽 레이더',\n    front_radar_text_mode: 'radar_right',\n    above_object: '위쪽 물체',\n    above_object_text_mode: 'object_up',\n    front_object: '앞쪽 물체',\n    front_object_text_mode: 'object_right',\n    below_object: '아래쪽 물체',\n    below_object_text_mode: 'object_down',\n    destination: '목적지',\n    asteroids: '돌',\n    item: '아이템',\n    wall: '벽',\n    destination_text_mode: 'destination',\n    asteroids_text_mode: 'stone',\n    item_text_mode: 'item',\n    wall_text_mode: 'wall',\n    buy_now: '구매바로가기',\n    goals: '목표',\n    instructions: '이용 안내',\n    object_info: '오브젝트 정보',\n    entry_basic_mission: '엔트리 기본 미션',\n    entry_application_mission: '엔트리 응용 미션',\n    maze_move_forward: '앞으로 한 칸 이동',\n    maze_when_run: '시작하기를 클릭했을때',\n    maze_turn_left: '왼쪽으로 회전',\n    maze_turn_right: '오른쪽으로 회전',\n    maze_repeat_times_1: '',\n    maze_repeat_times_2: '번 반복하기',\n    maze_repeat_until_1: '',\n    maze_repeat_until_2: '을 만날때까지 반복',\n    maze_call_function: '약속 불러오기',\n    maze_function: '약속하기',\n    maze_repeat_until_all_1: '모든',\n    maze_repeat_until_all_2: '만날 때 까지 반복',\n    command_guide: '명령어 도움말',\n    ai_success_msg_1: '덕분에 무사히 지구에 도착할 수 있었어! 고마워!',\n    ai_success_msg_2: '다행이야! 덕분에',\n    ai_success_msg_3:\n        '번 만큼 앞쪽으로 갈 수 있어서 지구에 구조 신호를 보냈어! 이제 지구에서 구조대가 올거야! 고마워!',\n    ai_success_msg_4: '좋았어!',\n    ai_cause_msg_1: '이런, 어떻게 움직여야 할 지 더 말해줄래?',\n    ai_cause_msg_2: '아이쿠! 정말로 위험했어! 다시 도전해보자',\n    ai_cause_msg_3: '우와왓! 가야할 길에서 벗어나버리면 우주 미아가 되버릴꺼야. 다시 도전해보자',\n    ai_cause_msg_4: '너무 복잡해, 이 블록을 써서 움직여볼래?',\n    ai_move_forward: '앞으로 가기',\n    ai_move_above: '위쪽으로 가기',\n    ai_move_under: '아래쪽으로 가기',\n    ai_repeat_until_dest: '목적지에 도달 할 때까지 반복하기',\n    ai_if_front_1: '만약 앞에',\n    ai_if_front_2: '가 있다면',\n    ai_else: '아니면',\n    ai_if_1: '만약',\n    ai_if_2: '이라면',\n    ai_use_item: '아이템 사용',\n    ai_radar: '레이더',\n    ai_above: '위쪽',\n    ai_front: '앞쪽',\n    ai_under: '아래쪽',\n    ai_object_is_1: '',\n    ai_object_is_2: '물체는',\n    challengeMission: '다른 미션 도전하기',\n    nextMission: '다음 미션 도전하기',\n    withTeacher: '함께 만든 선생님들',\n    host: '주최',\n    support: '후원',\n    subjectivity: '주관',\n    learnMore: ' 더 배우고 싶어요',\n    ai_object_is_3: '인가?',\n    stage_is_not_available:\n        '아직 진행할 수 없는 스테이지입니다. 순서대로 스테이지를 진행해 주세요.',\n    progress_not_saved: '진행상황이 저장되지 않습니다.',\n    want_refresh: '이 페이지를 새로고침 하시겠습니까?',\n    monthly_entry_grade: '초등학교 3학년 ~ 중학교 3학년',\n    monthly_entry_contents:\n        '매월 발간되는 월간엔트리와 함께 소프트웨어 교육을 시작해 보세요!  차근차근 따라하며 쉽게 익힐 수 있도록 가볍게 구성되어있습니다. 기본, 응용 콘텐츠와 더 나아가기까지! 매월 업데이트되는 8개의 콘텐츠와 교재를 만나보세요~',\n    monthly_entry_etc1:\n        '*메인 페이지의 월간 엔트리 추천코스를 활용하면 더욱 쉽게 수업을 할 수 있습니다.',\n    monthly_entry_etc2: '*월간엔트리는 학기 중에만 발간됩니다.',\n    group_make_lecture_1: '내가 만든 강의가 없습니다.',\n    group_make_lecture_2: \"'만들기>오픈 강의 만들기'에서\",\n    group_make_lecture_3: '우리반 학습내용에 추가하고 싶은 강의를 만들어 주세요.',\n    group_make_lecture_4: '강의 만들기',\n    group_add_lecture_1: '관심 강의가 없습니다.',\n    group_add_lecture_2: \"'학습하기>오픈 강의> 강의'에서 우리반 학습내용에\",\n    group_add_lecture_3: '추가하고 싶은 강의를 관심강의로 등록해 주세요.',\n    group_add_lecture_4: '강의 보기',\n    group_make_course_1: '내가 만든 강의 모음이 없습니다.',\n    group_make_course_2: \"'만들기 > 오픈 강의 만들기> 강의 모음 만들기'에서\",\n    group_make_course_3: '학습내용에 추가하고 싶은 강의 모음을 만들어 주세요.',\n    group_make_course_4: '강의 모음 만들기',\n    group_add_course_1: '관심 강의 모음이 없습니다.',\n    group_add_course_2: \"'학습하기 > 오픈 강의 > 강의 모음'에서 우리반 학습내용에\",\n    group_add_course_3: '추가하고 싶은 강의 모음을 관심 강의 모음으로 등록해 주세요.',\n    group_add_course_4: '강의 모음 보기',\n    hw_main_title: '프로그램 다운로드',\n    datablock_contest_title: '데이터분석 블록 추가',\n    datablock_content_head: '데이터를 가공하고 표현하기',\n    datablock_content_body1: '생활 속 다양한 데이터를 차트로 표현하고 의미를 찾아',\n    datablock_content_body2: '실생활 문제를 해결해보세요!',\n    campaign_contest_title: '아름다운 인터넷 세상을 만들어요',\n    campaign_content_head: '엔트리 작품 공모전',\n    campaign_content_body1: \"'인터넷윤리'에 대해 알기 쉽고 재미있게\",\n    campaign_content_body2: '작품을 만들어 응모해주세요!',\n    campaign_content_button: '자세히 보기',\n    code_management_1: '엔트리 캠페인 #1 코드 잘 관리하기',\n    code_management_2: '나의 보관함과 메모 활용',\n    code_management_3: '새 기능 나의 보관함과 메모로 하는 코드 관리 비법!',\n    code_management_4: '작품을 더 잘 만들고 쉽게 공유하는 방법을 알아보아요.',\n    code_management_5: '캠페인 보기',\n    shcoolbook_study_1: '교과서 내용 그대로 학습하세요.',\n    shcoolbook_study_2: '교과서 학습하기',\n    shcoolbook_study_3: '선생님은 교실에서 수업 진행을',\n    shcoolbook_study_4: '학생은 집에서 복습을 할 수 있습니다!',\n    shcoolbook_study_5: '학습하기',\n    main_learn_1: '엔트리에 처음 오셨다면',\n    main_learn_2: '엔트리 알아보기',\n    main_learn_3: '영상을 통해 엔트리의 다양한 기능을 알아보고,',\n    main_learn_4: '멋진 작품을 만들어 친구들과 공유해보세요!',\n    main_learn_5: '영상보기',\n    hw_desc_wrapper:\n        '엔트리 하드웨어 연결 프로그램과 오프라인 버전이 \\n서비스를 한층 더 강화해 업그레이드 되었습니다.\\n업데이트 된 프로그램을 설치해주세요!',\n    hw_downolad_link: '하드웨어 연결 \\n프로그램 다운로드',\n    save_as_image_all: '모든 코드 이미지로 저장하기',\n    save_as_image: '이미지로 저장하기',\n    maze_perfect_success: '멋져! 완벽하게 성공했어~',\n    maze_success_many_block_1: '좋아',\n    maze_fail_obstacle_remain:\n        \"친구들이 다치지 않도록 모든 <span class='bitmap_obstacle_spider'></span>을 없애줘.\",\n    maze_fail_item_remain: '샐리 공주를 구하기 위해 모든 미네랄을 모아 와줘.',\n    maple_fail_item_remain:\n        '음식을 다 먹지 못해서 힘이 나지 않아. 모든 음식을 다 먹을 수 있도록 도와줘.',\n    maze_fail_not_found_destory_object: '아무것도 없는 곳에 능력을 낭비하면 안 돼!',\n    maze_fail_not_found_destory_monster: '몬스터가 없는 곳에 공격을 하면 안 돼!',\n    maple_fail_not_found_destory_monster: '공격 블록은 몬스터가 있을 때에만 해야 돼!',\n    maze_fail_more_move: '목적지까지는 좀 더 움직여야 해!',\n    maze_fail_wall_crash: '으앗! 거긴 갈 수 없는 곳이야!',\n    maze_fail_contact_brick: '에구구… 부딪혔다!',\n    maze_fail_contact_iron1: '으앗! 장애물에 부딪혀버렸어',\n    maze_fail_contact_iron2: '으앗! 장애물이 떨어져서 다쳐버렸어. 장애물이 내려오기전에 움직여줘..',\n    maze_fail_fall_hole: '앗, 함정에 빠져 버렸어...',\n    maze_fail_hit_unit:\n        '몬스터에게 당해버렸어! 위험한 몬스터를 물리치기 위해 하트 날리기 블록을 사용해줘!',\n    maze_fail_hit_unit2: '윽, 몬스터에게 공격당했다! 두 칸 떨어진 곳에서 공격해줘!',\n    maze_fail_hit_unit_by_mushroom:\n        \"주황버섯에게 당해버렸어!<br /><img src='/img/assets/maze/icon/mushroom.png' /> 공격하기 블록을 사용해서 나쁜 몬스터를 혼내줘!\",\n    maze_fail_hit_unit_by_lupin:\n        \"루팡에게 당해버렸어!<br /><img src='/img/assets/maze/icon/lupin.png' /> 공격하기 블록을 두 칸 떨어진 곳에서 사용해서 나쁜 몬스터를 혼내줘!\",\n    maze_fail_elnath_fail:\n        '으앗! 나쁜 몬스터가 나를 공격했어.<br/>나쁜 몬스터가 나에게 다가오지 못하게 혼내줘!',\n    maze_fail_pepe: '',\n    maze_fail_yeti:\n        \"그 몬스터는 너무 강해서 <img width='24px' src='/img/assets/week/blocks/yeti.png'/> 공격하기 블록으로는 혼내줄 수 없어<br/><img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> 공격하기 블록을 사용해보자.\",\n    maze_fail_peti:\n        \"그 몬스터에게 <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> 공격하기 블록을 사용하면,<br/>강한 몬스터인 <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/>가 나왔을 때 혼내줄 수 없어<br/><img width='24px' src='/img/assets/week/blocks/yeti.png'/> 공격하기 블록을 사용해보자.\",\n    maze_fail_both_side: '양 옆 공격하기는 양쪽에 몬스터가 있을 때에만 사용해야 돼!',\n    maze_wrong_attack_obstacle:\n        \"이 곳에서는 <img src='/img/assets/maze/icon/lupin.png' /> 공격하기 블록을 사용할 수 없어<br/>주황 버섯에게는 <img src='/img/assets/maze/icon/mushroom.png' /> 공격하기 블록을 사용해보자.\",\n    maze_fail_contact_spider: '거미집에 걸려 움직일 수가 없어...',\n    maze_success_perfect: '멋져! 완벽하게 성공했어~',\n    maze_success_block_excess:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br> 하지만, %2개의 블록만으로 성공하는 방법도 있어. 다시 도전해 보는 건 어때?',\n    maze_success_not_essential:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br>하지만 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maze_success_final_perfect_basic:\n        '좋아! 샐리 공주가 어디 있는지 찾았어! 이제 샐리 공주를 구할 수 있을 거야!',\n    maze_success_final_block_excess_basic:\n        '좋아! 샐리 공주가 어디 있는지 찾았어! 이제 샐리 공주를 구할 수 있을 거야!%1개의 블록을 사용했는데, %2개의 블록만으로 성공하는 방법도 있어. 다시 해볼래?',\n    maze_success_final_perfect_advanced:\n        '샐리 공주가 있는 곳까지 도착했어! 이제 악당 메피스토를 물리치고 샐리를 구하면 돼!',\n    maze_success_final_block_excess_advanced:\n        '샐리 공주가 있는 곳까지 도착했어! 이제 악당 메피스토를 물리치고 샐리를 구하면 돼!%1개의 블록을 사용했는데, %2개의 블록만으로 성공하는 방법도 있어. 다시 해볼래?',\n    maze_success_final_distance:\n        '좋아! 드디어 우리가 샐리 공주를 무사히 구해냈어. 구할 수 있도록 도와줘서 정말 고마워!<br>%1칸 움직였는데 다시 한 번 다시해서 60칸까지 가볼래?',\n    maze_success_final_perfect_ai:\n        '좋았어! 드디어 우리가 샐리 공주를 무사히 구해냈어. 구할 수 있도록 도와줘서 정말 고마워!',\n    maple_success_perfect: '좋아! 완벽하게 성공했어!!',\n    maple_success_block_excess:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br> 그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는건 어때?',\n    maple_success_not_essential:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br>그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_perfect_henesys: '멋져! 헤네시스 모험을 훌륭하게 해냈어.',\n    maple_success_final_perfect_excess_henesys:\n        '멋져! 헤네시스 모험을 잘 해냈어.<br />그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_not_essential_henesys:\n        '멋져! 헤네시스 모험을 잘 해냈어.<br />그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_perfect_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br/>다음 모험도 같이 할거지? ',\n    maple_success_final_perfect_excess_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br />그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_not_essential_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br />그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_fail_fall_hole: '으앗! 빠져버렸어!<br />뛰어넘기 블록을 사용해서 건너가보자.',\n    maple_fail_ladder_fall_hole:\n        '으앗! 빠져버렸어!<br />사다리 타기 블록을 사용해서 다른 길로 가보자.',\n    maple_fail_more_move: '성공하려면 목적지까지 조금 더 움직여야 해!',\n    maple_fail_not_found_ladder:\n        '이런, 여기엔 탈 수 있는 사다리가 없어.<br />사다리 타기 블록은 사다리가 있는 곳에서만 사용 해야해.',\n    maple_fail_not_found_meat:\n        '이런, 여기엔 먹을 수 있는 음식이 없어!<br />음식 먹기 블록은 음식이 있는 곳에서만 사용 해야해.',\n    maple_cert_input_title: '내가 받을 인증서에 적힐 이름은?',\n    maze_distance1: '거리 1',\n    maze_distance2: '거리 2',\n    maze_distance3: '거리 3',\n    ev3: 'EV3',\n    roborobo_roduino: '로두이노',\n    roborobo_schoolkit: '스쿨키트',\n    smartboard: '과학상자 코딩보드',\n    smartboardbt: '과학상자 코딩보드(무선)',\n    codestar: '코드스타',\n    cobl: '코블',\n    cobl_bt: '코블 블루투스',\n    block_coding: '블록코딩',\n    python_coding: '엔트리파이선',\n    dadublock: '다두블럭',\n    dadublock_car: '다두블럭 자동차',\n    blacksmith: '대장장이 보드',\n    course_submit_homework: '과제 제출',\n    course_done_study: '학습 완료',\n    course_show_list: '목록',\n    modi: '모디',\n    chocopi: '초코파이보드',\n    coconut: '코코넛',\n    jdkit: '제이디키트',\n    practical_course: '교과용 만들기',\n    entry_user_policy: '엔트리 이용정책',\n    entry_scholarship_title: '엔트리 학술 자료',\n    entry_scholarship_content:\n        '엔트리는 대학/학회 등과 함께 다양한 연구를 진행하여 전문성을 강화해나가고 있습니다. 엔트리에서 제공하는 연구용 자료를 확인해보세요',\n    entry_scholarship_content_sub:\n        '*엔트리에서 제공하는 데이터는 연구 및 분석에 활용될 수 있도록 온라인코딩파티에 참여한 사용자들이 미션을 해결하는 일련의 과정을 로그 형태로 저장한 데이터 입니다.',\n    entry_scholarship_download: '자료 다운로드',\n    codingparty_2016_title: '2016 온라인 코딩파티',\n    codingparty_2016_content:\n        '미션에 참여한 사용자들의 블록 조립 순서, 성공/실패 유무가 학년, 성별 정보와 함께 제공됩니다.',\n    codingparty_2017_title: '2017 온라인 코딩파티',\n    scholarship_go_mission: '미션 확인하기',\n    scholarship_guide: '자료 활용 방법',\n    scholarship_see_guide: '가이드 보기',\n    scholarship_guide_desc: '연구용 자료를 읽고 활용할 수 있는 방법이 담긴 개발 가이드 입니다. ',\n    scholarship_example: '자료 활용 예시',\n    scholarship_example_desc: '연구용 자료를 활용하여 발표된 논문을 확인 할 수 있습니다.',\n    scholarship_see_example: '논문 다운로드',\n    altino: '알티노',\n    private_project: '비공개 작품입니다.',\n    learn_programming_entry_mission: '\"엔트리봇\"과 함께 미션 해결하기',\n    learn_programming_line_mission: '\"라인레인저스\"와 샐리구하기',\n    learn_programming_choseok: '\"마음의 소리\"의 조석과 게임 만들기',\n    learn_programming_maple: '\"핑크빈\"과 함께 신나는 메이플 월드로!',\n    learn_programming_level_novice: '기초',\n    learn_programming_level_inter: '중급',\n    learn_programming_level_advanced: '고급',\n    line_look_for: '샐리를 찾아서',\n    line_rangers_title_string: '학습하기 : 라인 레인저스',\n    online_codingparty_certificate_string: '온라인 코딩파티',\n    online_codingparty_line_title_string: '라인 레인저스',\n    line_look_for_desc_1:\n        '라인 레인저스의 힘을 모아 강력한 악당 메피스토를 물리치고 샐리를 구해주세요!',\n    line_save: '샐리 구하기',\n    line_save_desc_1:\n        '메피스토 기지에 갇힌 샐리. 라인 레인저스가 장애물을 피해 샐리를 찾아갈 수 있도록 도와주세요!',\n    line_escape: '샐리와 탈출하기',\n    line_escape_desc_1:\n        '폭파되고 있는 메피스토 기지에서 샐리와 라인 레인저스가 무사히 탈출할 수 있도록 도와주세요!',\n    solve_choseok: '가위바위보 만들기',\n    solve_choseok_desc_1: '만화 속 조석이 가위바위보 게임을 만들 수 있도록 도와주세요!',\n    solve_henesys: '헤네시스',\n    solve_ellinia: '엘리니아',\n    solve_elnath: '엘나스',\n    solve_henesys_desc_1:\n        '마을을 모험하며, 배고픈 핑크빈이 음식을 배불리 먹을 수 있도록 도와주세요!',\n    solve_ellinia_desc_1: '숲 속을 탐험하며, 나쁜 몬스터들을 혼내주고 친구 몬스터들을 구해주세요!',\n    solve_elnath_desc_1:\n        '나쁜 몬스터가 점령한 설산을 지나, 새로운 모험을 시작할 수 있는 또 다른 포털을 찾아 떠나보세요 !',\n    save_modified_shape: '수정된 내용을 저장하시겠습니까?',\n    save_modified_table: '테이블에서 수정한 내용을 저장하시겠습니까?',\n    attach_file: '첨부',\n    enter_discuss_title: '제목을 입력해 주세요(40자 이하)',\n    enter_discuss_title_alert: '제목을 입력해 주세요',\n    discuss_upload_warn: '10MB이하의 파일을 올려주세요.',\n    discuss_list: '목록보기',\n    discuss_write_notice: '우리반 공지사항으로 지정하여 게시판 최상단에 노출합니다.',\n    discuss_write_notice_open: '공지사항으로 지정하여 게시판 최상단에 노출합니다.',\n    search_전체: '전체',\n    search_게임: '게임',\n    search_애니메이션: '애니메이션',\n    search_미디어아트: '미디어 아트',\n    search_피지컬: '피지컬',\n    search_기타: '기타',\n    discuss_write_textarea_placeholer:\n        '엔트리 커뮤니티는 우리가 함께 만들어가는 공간입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_qna:\n        '여기는 묻고답하기 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_tips:\n        '여기는 노하우&팁 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_free:\n        '여기는 엔트리 이야기 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_report:\n        '여기는 제안 및 건의 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_contest2019:\n        '※ 아래 양식으로 작성하여 제출해주세요.\\n\\n1. 학년 (예: 초등학교 5학년)\\n\\n2. 작품 URL (‘공유하기 > 작품 공유하기’에 작품을 공유한 다음, 작품 URL을 복사하여 적어주세요.)\\n\\n3. 작품 설명\\n\\n※ 공모전 수상자에게는 이메일이 발송될 예정입니다.\\n엔트리의 ‘내 정보 수정‘에 이메일 정보를 꼭 입력해주세요!',\n    maze_road: '길',\n    account_deletion: '회원탈퇴',\n    bug_report_too_many_request:\n        '신고 내용이 전송 되고 있습니다. 잠시 후에 다시 시도해주시길 바랍니다.',\n    pinkbean_index_title: '핑크빈과 함께 신나는 메이플 월드로!',\n    pinkbean_index_content:\n        '심심함을 참지 못한 핑크빈이 메이플 월드로 모험을 떠났습니다.<br />핑크빈과 함께 신나는 메이플 월드를 탐험하여 모험일지를 채워주세요.<br />각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 마치면 인증서도 얻을 수 있습니다.',\n    rangers_index_title: '라인 레인저스와 함께 샐리를 구하러 출동!',\n    rangers_index_content:\n        '악당 메피스토에게 납치된 샐리를 구하기 위해 라인 레인저스가 뭉쳤습니다.<br />소프트웨어의 원리를 통해 장애물을 극복하고, 샐리를 구출하는 영웅이 되어주세요.<br />각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 마치면 인증서도<br />얻을 수 있습니다.',\n    rangers_replay_button: '영상 다시보기',\n    rangers_start_button: '미션 시작',\n    lms_curriculum_intro: '학습시작',\n    lms_curriculum_goal: '학습목표',\n    lms_curriculum_prepare: '학습준비',\n    lms_curriculum_study: '실습활동',\n    lms_curriculum_summary: '학습정리',\n    lms_curriculum_quiz: '확인문제',\n    lms_curriculum_now_stage: '현재 단계',\n    bug_report_title: '버그 리포트',\n    bug_report_content:\n        '이용 시 발생하는 오류나 버그 신고 및 엔트리를 위한 좋은 제안을 해주세요. 신고나 제안과 무관한 욕설 작성 시 이용이 정지될 수 있습니다.',\n    object_import_syntax_error:\n        '불러오려는 오브젝트에 엔트리파이선 문법과 맞지 않는 블록이 포함되어 있습니다. 블록코딩으로 전환한 뒤 오브젝트를 불러와주세요.',\n    choseok_top_wrapper_panel_title: '조석과 함께 가위바위보 게임을 만들어보세요!',\n    choseok_top_wrapper_panel_des:\n        '마음의 소리 웹툰이 코딩파티 미션으로 탄생했습니다. <br/>만화속 조석이 (가위바위보 게임)을 만들어가는 과정에 참여하여 미션에<br/>도전해 보세요.<br/>각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 모두 마치면</br>인증서와 나만의 게임을 얻을 수 있습니다.<br/>',\n    choseok_mission_statement1: '조석을 움직여보자',\n    choseok_mission_statement2: '가위바위보를 시작해보자',\n    choseok_mission_statement3: '가위바위보 승부를 가려보자',\n    choseok_mission_statement4: '가위바위보 게임을 완성해보자',\n    choseok_mission_statement5: '자유롭게 만들어보자',\n    choseok_mission_statement_top1: '미션 1 : 조석을 움직이기',\n    choseok_mission_statement_top2: '미션 2 : 가위바위보를 시작하기',\n    choseok_mission_statement_top3: '미션 3 : 가위바위보 승패 만들기',\n    choseok_mission_statement_top4: '미션 4 : 가위바위보 결과 보여주기',\n    choseok_mission_statement_top5: '미션 5 : 자유롭게 만들어보기',\n    advisory_title: '엔트리 자문단',\n    advisory_sub_title: '엔트리를 함께 만들어가는 선생님 학생 자문단입니다.',\n    data_table_column: '열',\n    data_table_row: '행',\n    data_table_provider: '제공처',\n    data_table_modifidate: '수정일',\n    draw_new_table_ques_1: '데이터를 직접 입력하여 테이블로 저장할 수 있습니다.',\n    draw_new_table_ques_2: '테이블 화면으로 이동하시겠습니까?',\n};\nLang.Msgs = {\n    microbit_led_erase_all: '모두 지우기',\n    loading_plz_wait: '로딩중입니다. 잠시만 기다려주세요',\n    ai_utilize_audio_listening: '듣고 있어요',\n    upload_error_title: '파일 업로드 안내',\n    upload_error_content: '엔트리 이용정책을 지키지 않는 것으로 의심되는 파일이 제외되었습니다.',\n    monthly_intro_0:\n        '<월간 엔트리>는 소프트웨어 교육에 익숙하지 않은 선생님들도 쉽고 재미있게 소프트웨어 교육을 하실 수 있도록 만들어진 ',\n    monthly_intro_1:\n        'SW교육 잡지입니다. 재미있는 학습만화와 함께 하는 SW 교육 컨텐츠를 만나보세요!',\n    monthly_title_0: '강아지 산책시키기 / 선대칭 도형 그리기',\n    monthly_title_1: '동영상의 원리 / 음악플레이어 만들기',\n    monthly_title_2: '대한민국 지도 퍼즐 / 벚꽃 애니메이션',\n    monthly_title_3: '마우스 졸졸, 물고기 떼 / 태양계 행성',\n    monthly_title_4: '감자 캐기 / 딸기 우유의 진하기',\n    monthly_description_0:\n        '키보드 입력에 따라 움직이는 강아지와 신호와 좌표를 통해 도형을 그리는 작품을 만들어 봅시다.',\n    monthly_description_1: '변수를 활용하여 사진 영상 작품과 음악 플레이어 작품을 만들어 봅시다.',\n    monthly_description_2:\n        '~인 동안 반복하기를 이용한 퍼즐 게임과 복제본, 무작위 수를 이용한 애니메이션 작품을 만들어 봅시다.',\n    monthly_description_3:\n        '계속 반복하기 블록과 수학 연산 블록을 활용하여 물고기 미디어 아트 작품과 태양계를 만들어 봅시다.',\n    monthly_description_4:\n        '신호와 변수, 수학 연산 블록을 활용하여 감자 캐기 작품과 딸기 우유 만들기 작품을 만들어 봅시다.',\n    save_canvas_alert: '저장 중입니다.',\n    feedback_too_many_post: '신고하신 내용이 전송되고 있습니다. 10초 뒤에 다시 시도해주세요.',\n    feedback_duplicated: '이미 신고하였습니다.',\n    usable_object: '사용가능 오브젝트',\n    shared_varaible: '공유 변수',\n    invalid_url: '영상 주소를 다시 확인해 주세요.',\n    auth_only: '인증된 사용자만 이용이 가능합니다.',\n    runtime_error: '실행 오류',\n    to_be_continue: '준비 중입니다.',\n    warn: '경고',\n    error_occured:\n        \"다시 한번 시도해 주세요. 만약 같은 문제가 다시 발생 하면 '제안 및 건의' 게시판에 문의 바랍니다. \",\n    error_forbidden:\n        '로그아웃 상태라 저장을 할 수 없습니다.\\n만약 로그인했다면 다른 창에서 로그아웃 했는지 확인해 주세요.\\n로그인 확인 후 저장이 안 된다면 ‘제안 및 건의’ 게시판에 문의 하세요.',\n    list_can_not_space: '리스트의 이름은 빈 칸이 될 수 없습니다.',\n    sign_can_not_space: '신호의 이름은 빈 칸이 될 수 없습니다.',\n    variable_can_not_space: '변수의 이름은 빈 칸이 될 수 없습니다.',\n    training_top_title: '연수 프로그램',\n    training_top_desc: '엔트리 연수 지원 프로그램을 안내해 드립니다.',\n    training_main_title01: '선생님을 위한 강사 연결 프로그램',\n    training_target01: '교육 대상 l 선생님',\n    training_sub_title01: '“우리 교실에 SW날개를 달자”',\n    training_desc01:\n        '소프트웨어(SW) 교원 연수가 필요한 학교인가요?\\nSW 교원 연수가 필요한 학교에 SW교육 전문 선생님(고투티처) 또는 전문 강사를 연결해드립니다.',\n    training_etc_ment01: '* 강의비 등 연수 비용은 학교에서 지원해주셔야합니다.',\n    training_main_title02: '소프트웨어(SW) 선도학교로 찾아가는 교원연수',\n    training_target02: '교육 대상 l SW 선도, 연구학교',\n    training_sub_title02: '“찾아가, 나누고, 이어가다”',\n    training_desc02:\n        'SW 교원 연수를 신청한 선도학교를 무작위로 추첨하여 상반기(4,5,6월)와\\n하반기(9,10,11월)에 각 지역의 SW교육 전문 선생님(고투티처)께서 알차고\\n재미있는 SW 기초 연수 진행 및 풍부한 교육사례를 공유하기 위해 찾아갑니다.',\n    training_etc_ment02: '',\n    training_main_title03: '학부모와 학생을 위한 연결 프로그램',\n    training_target03: '교육 대상 l 학부모, 학생',\n    training_sub_title03: '“SW를 더 가까이 만나는 시간”',\n    training_desc03:\n        '학부모와 학생들을 대상으로 소프트웨어(SW) 연수가 필요한 학교에 각 지역의 SW교육 전문 선생님(고투티처) 또는 전문 강사를 연결해드립니다.',\n    training_etc_ment03: '* 강의비 등 연수 비용은 학교에서 지원해주셔야합니다.',\n    training_apply: '신청하기',\n    training_ready: '준비중입니다.',\n    new_version_title: '최신 버전 설치 안내',\n    new_version_text1: '하드웨어 연결 프로그램이',\n    new_version_text2: '<strong>최신 버전</strong>이 아닙니다.',\n    new_version_text3: '서비스를 한층 더 강화해 업데이트 된',\n    new_version_text4: '최신 버전의 연결 프로그램을 설치해 주세요.',\n    new_version_download: \"최신 버전 다운로드<span class='download_icon'></span>\",\n    not_install_title: '미설치 안내',\n    hw_download_text1: '하드웨어 연결을 위해서',\n    hw_download_text2: '<strong>하드웨어 연결 프로그램</strong>을 설치해 주세요.',\n    hw_download_text3: '하드웨어 연결 프로그램이 설치되어 있지 않습니다.',\n    hw_download_text4: '최신 버전의 연결 프로그램을 설치해 주세요.',\n    hw_download_btn: \"연결 프로그램 다운로드<span class='download_icon'></span>\",\n    not_support_browser: '지원하지 않는 브라우저입니다.',\n    quiz_complete1: '퀴즈 풀기 완료!',\n    quiz_complete2: '총 {0}문제 중에 {1}문제를 맞췄습니다.',\n    quiz_incorrect: '이런 다시 한 번 생각해보자',\n    quiz_correct: '정답이야!',\n    hw_connection_success: '하드웨어 연결 성공',\n    hw_connection_success_desc: '하드웨어 아이콘을 더블클릭하면, 센서값만 확인할 수 있습니다.',\n    hw_connection_success_desc2: '작품에서 하드웨어를 사용할 수 있습니다.',\n    hw_connection_termination_title: '하드웨어 연결 해제',\n    hw_connection_termination_desc: '하드웨어와 연결이 해제되었습니다.',\n    hw_connection_failed_title: '하드웨어 연결 실패',\n    hw_connection_failed_desc: '작품에서 사용된 하드웨어가\\n연결되어 있는지 확인해 주세요.',\n    ie_page_title: '이 브라우저는<br/>지원하지 않습니다.',\n    ie_page_desc:\n        '엔트리는 인터넷 익스플로러 11 버전 이상 또는 크롬 브라우저에서 이용하실 수 있습니다.<br/>윈도우 업데이트를 진행하시거나, 크롬 브라우저를 설치해주세요.<br/>엔트리 오프라인 버전은 인터넷이 연결되어 있지 않아도 사용할 수 있습니다. 지금 다운받아서 시작해보세요!',\n    ie_page_chrome_download: '크롬 브라우저<br/>다운로드',\n    ie_page_windows_update: '윈도우 최신버전<br>업데이트',\n    ie_page_offline_32bit_download: '엔트리 오프라인 32bit<br>다운로드',\n    ie_page_offline_64bit_download: '엔트리 오프라인 64bit<br>다운로드',\n    ie_page_offline_mac_download: '엔트리 오프라인<br>다운로드',\n    cancel_deletion_your_account: '$1님의<br />회원탈퇴 신청을 취소하시겠습니까?',\n    account_deletion_canceled_complete: '회원탈퇴 신청이 취소되었습니다.',\n    journal_henesys_no1_title: '헤네시스 첫번째 모험일지',\n    journal_henesys_no2_title: '헤네시스 두번째 모험일지',\n    journal_henesys_no1_content:\n        '헤네시스에서 첫 번째 모험 일지야. 오늘 헤네시스 터줏대감이라는 대장장이 집에 가려고 점프를 하다가 떨어질 뻔했어. 그 아저씨는 집 마당 앞에 왜 그렇게 구멍을 크게 만들어 놓는 거지? 나같이 대단한 몬스터가 아니고서야 이런 구멍을 뛰어넘을 수 있는 애들은 없을 거 같은데! 여하튼 정보도 얻었으니 아저씨가 추천한 맛 집으로 가볼까?',\n    journal_henesys_no2_content:\n        '진짜 과식했다. 특히 그 식당의 고기는 정말 맛있었어. 어떻게 그렇게 부드럽게 만들었을까! 그렇지만 그 옆집 빵은 별로였어. 보니까 주방장 아저씨가 요리 수련을 한답시고 맨날 놀러 다니는 거 같더라고. 그럴 시간에 빵 하나라도 더 만들어 보는 게 나을 텐데. 후 이제 배도 채웠으니 본격적인 모험을 시작해볼까!',\n    journal_ellinia_no1_title: '엘리니아 첫번째 모험일지',\n    journal_ellinia_no2_title: '엘리니아 두번째 모험일지',\n    journal_ellinia_no1_content:\n        '휴, 모르고 주황버섯을 깔고 앉아버렸지 뭐야. 걔네가 화날만 하지.. 그래도 그렇게 나에게 다같이 몰려들어 공격할 건 뭐람! 정말 무서운 놈들이야. 슬라임들이 힘들어 할만했어. 하지만 이 핑크빈님께서 다 혼내주었으니깐 걱정 없어. 이제 슬라임들이 친구가 되어주었으니 더욱 신나게 멋진 숲으로 모험을 이어가볼까.',\n    journal_ellinia_no2_content:\n        '모험하면서 만난 친구 로얄패어리가 요즘 엘나스에 흉흉한  소문이 돈다고 했는데, 그게 뭘까? 오늘밤에 친구들이랑 집에서 놀기로 했는데 그때 물어봐야겠어. 완전 궁금한걸!  그런데 뭘 입고 가야하나.. 살이 너무쪄서 입을만 한게 없을거같은데.. 뭐 나는 늘 귀여우니까 어떤걸 입고가도 다들 좋아해줄거라구!',\n    journal_elnath_no1_title: '엘나스 첫번째 모험일지',\n    journal_elnath_no2_title: '엘나스 두번째 모험일지',\n    journal_elnath_no1_content:\n        '세상에! 이게 말로만 듣던 눈인가? 내가 사는 마을은 항상 봄이여서 눈은 처음 봤어. 몬스터들을 혼내주느라 제대로 구경을 못했는데 지금보니 온세상이 이렇게나 하얗고 차갑다니 놀라워! 푹신 푹신하고 반짝거리는게 맛있어 보였는데 맛은 특별히 없네. 그런데 왠지 달콤한 초코 시럽을 뿌려먹으면 맛있을 거 같아. 조금 들고가고 싶은데 방법이 없다니 너무 아쉬운걸.',\n    journal_elnath_no2_content:\n        '에퉤퉤, 실수로 석탄가루를 먹어버렸네. 나쁜 몬스터들! 도망가려면 조용히 도망갈 것이지 석탄을 잔뜩 뿌리면서 도망가버렸어. 덕분에 내 윤기나고 포송포송한 핑크색 피부가 갈수록 더러워지고 있잖아. 어서 여기를 나가서 깨끗하게 목욕부터 해야겠어. 아무리 모험이 좋다지만 이렇게 더럽게 돌아다니는 건 이 핑크빈님 자존심이 허락하지 않지.',\n    bug_report_alert_msg: '소중한 의견 감사합니다.',\n    version_update_msg1: '엔트리 오프라인 새 버전(%1)을\\n사용하실 수 있습니다.',\n    version_update_msg2: '엔트리 하드웨어 새 버전(%1)을\\n사용하실 수 있습니다.',\n    version_update_msg3: '지금 업데이트 하시겠습니까?',\n    select_the_hardware: '수업에 활용할<br />하드웨어를 선택하세요.',\n    select_hardware_button: '하드웨어 선택하기',\n    select_the_expansion_block: '수업에 활용할 확장 블록을 선택하세요.',\n    select_hardware_not_support_info: '오픈강의에는 하드웨어 블록을 사용할 수 없습니다.',\n    select_hardware_not_support_info2: '조금만 기다려주세요.',\n    select_expansion_block_button: '확장 블록 선택하기',\n    expansion_weather_description:\n        '기온, 강수량, 미세먼지 농도 등 한국의 날씨와 관련된 블록 모음입니다. [웨더아이 제공]',\n    expansion_festival_description:\n        '국내 지역별 다양한 행사 및 축제와 관련된 불록 모음 입니다. [한국관광공사 제공]',\n    expansion_translate_description:\n        '파파고를 이용하여 다른 언어로 번역할 수 있는 블록 모음입니다.',\n    expansion_behaviorConductDisaster_description:\n        '자연재난 발생 시 국민이 지켜야하는 기본적인 행동요령에 대한 블록들의 모음입니다. [국민안전처 제공]',\n    expansion_behaviorConductLifeSafety_description:\n        '생활 속 안전을 위해 국민이 지켜야 하는 행동요령에 대한 블록 모음입니다. [국민안전처 제공]',\n    ai_utilize_tts_description:\n        'nVoice 음성합성 기술로 다양한 목소리로 문장을 읽는 블록모음 입니다. ',\n    hardware_need_update_title: '업데이트 안내',\n    hardware_need_update_content:\n        '보안 업데이트로 엔트리 웹버전은\\n하드웨어 1.9.0 버전 이상만 지원합니다.\\n이하 버전일 경우 프로그램을 업데이트 하세요.\\n* 업데이트 후 블록이 보이지 않을 경우,\\n웹브라우저의 캐시를 지워 주세요.',\n    ai_utilize_audio_description:\n        '마이크를 이용하여 소리와 음성을 감지할 수 있는 블록 모음입니다. (IE/Safari/Firefox 브라우저 미지원)',\n    ai_utilize_video_description:\n        '카메라를 이용하여 움직임과 방향 값, 그리고 촬영되는 객체 등을 인식할 수 있는 블록 모음입니다. (IE/Safari/Firefox 브라우저 미지원)',\n};\nLang.Users = {\n    auth_failed: '인증에 실패하였습니다',\n    birth_year: '태어난 해',\n    birth_year_before_1990: '1990년 이전',\n    edit_personal: '정보수정',\n    email: '이메일',\n    email_desc: '새 소식이나 정보를 받을 수 있 이메일 주소',\n    email_inuse: '이미 등록된 메일주소 입니다',\n    email_match: '이메일 주소를 올바르게 입력해 주세요',\n    forgot_password: '암호를 잊으셨습니까?',\n    job: '직업',\n    language: '언어',\n    name: '이름',\n    name_desc: '사이트내에서 표현될 이름 또는 별명',\n    name_not_empty: '이름을 반드시 입력하세요',\n    password: '암호',\n    password_desc: '최소 4자이상 영문자와 숫자, 특수문자',\n    password_invalid: '암호가 틀렸습니다',\n    password_long: '암호는 4~20자 사이의 영문자와 숫자, 특수문자로 입력해 주세요',\n    password_required: '암호는 필수입력 항목입니다',\n    project_list: '작품 조회',\n    regist: '가입 완료',\n    rememberme: '자동 로그인',\n    repeat_password: '암호 확인',\n    repeat_password_desc: '암호를 한번더 입력해 주세요',\n    repeat_password_not_match: '암호가 일치하지 않습니다',\n    sex: '성별',\n    signup_required_for_save: '저장을 하려면 로그인이 필요합니다.',\n    username: '아이디',\n    username_desc: '로그인시 사용할 아이디',\n    username_inuse: '이미 사용중인 아이디 입니다',\n    username_long: '아이디는 4~20자 사이의 영문자로 입력해 주세요',\n    username_unknown: '존재하지 않는 사용자 입니다',\n    already_verified: '이미 인증된 메일 주소입니다.',\n    email_address_unavailable: '유효하지 않은 인증 메일입니다.',\n    email_address_invalid_for_idpw:\n        '유효하지 않은 인증 메일입니다.\\n [아이디와 비밀번호 찾기] 메일 발송하기를\\n 다시 시도해 주세요.',\n    email_address_invalid_for_certification:\n        '유효하지 않은 인증 메일입니다.\\n [인증 메일 발송하기]를 다시 시도해 주세요.',\n    verification_complete: '이메일 주소가 인증되었습니다.',\n    reset_password_mail_sent: '비밀번호 재설정 메일이 발송되었습니다. 메일을 확인해주세요.',\n    email_not_verified:\n        '인증되지 않은 이메일 주소입니다. 인증 메일을 발송하여, 먼저 이메일 주소를 인증해주세요.',\n    verification_email_send_complete: '인증 메일이 발송되었습니다. 먼저 메일 주소를 인증해주세요.',\n    email_send_failed: '전송에 실패했습니다. 다시 한번 시도해주세요.',\n    email_not_exist: '등록되지 않은 이메일 주소입니다.',\n    not_valid_email: '올바른 형식의 이메일 주소를 입력해주세요.',\n};\nLang.Workspace = {\n    picture_rotation: '회전',\n    picture_size: '크기',\n    thickness: '굵기',\n    follow: '따라해보기',\n    SaveWithPicture: '저장되지 않은 그림이 있습니다. 저장하시겠습니까?',\n    RecursiveCallWarningTitle: '함수 호출 제한',\n    RecursiveCallWarningContent:\n        '한 번에 너무 많은 함수가 호출되었습니다. 함수의 호출 횟수를 줄여주세요.',\n    SelectShape: '이동',\n    SelectCut: '자르기',\n    Pencil: '펜',\n    Line: '직선',\n    Rectangle: '사각형',\n    Ellipse: '원',\n    Text: '글상자',\n    Fill: '채우기',\n    Eraser: '지우기',\n    Magnifier: '확대/축소',\n    block_helper: '블록 도움말',\n    new_project: '새 프로젝트',\n    add_object: '오브젝트 추가하기',\n    download_image_name: '엔트리 블록',\n    all: '전체',\n    animal: '동물',\n    arduino_entry: '아두이노 연결 프로그램',\n    arduino_program: '아두이노 프로그램',\n    arduino_sample: '엔트리 연결블록',\n    arduino_driver: '아두이노 드라이버',\n    cannot_add_object: '실행중에는 오브젝트를 추가할 수 없습니다.',\n    cannot_add_picture: '실행중에는 모양을 추가할 수 없습니다.',\n    cannot_add_sound: '실행중에는 소리를 추가할 수 없습니다.',\n    cannot_add_expansion_block: '실행중에는 확장 블럭을 추가할 수 없습니다.',\n    add_object_before_edit: '모양 편집을 위해<br>오브젝트를 추가해주세요.',\n    add_table_before_edit: '테이블을 추가해주세요.',\n    cannot_edit_click_to_stop: '실행 중에는 수정할 수 없습니다.<br>클릭하여 정지하기.',\n    cannot_open_private_project: '비공개 작품은 불러올 수 없습니다. 홈으로 이동합니다.',\n    cannot_save_running_project: '실행 중에는 저장할 수 없습니다.',\n    character_gen: '캐릭터 만들기',\n    check_runtime_error: '빨간색으로 표시된 블록을 확인해 주세요.',\n    check_browser_error: 'IE/Safari 에서는 지원하지 않는 블록입니다.',\n    check_microphone_error: '컴퓨터에 마이크가 연결되어있지 않습니다',\n    check_webcam_error: '컴퓨터에 카메라가 연결되어있지 않습니다',\n    context_download: 'PC에 저장',\n    context_duplicate: '복제',\n    context_remove: '삭제',\n    context_rename: '이름 수정',\n    coordinate: '좌표',\n    create_function: '함수 만들기',\n    direction: '이동 방향',\n    drawing: '직접 그리기',\n    enter_list_name: '새로운 리스트의 이름을 입력하세요(10글자 이하)',\n    enter_name: '새로운 이름을 입력하세요',\n    enter_new_message: '새로운 신호의 이름을 입력하세요.',\n    enter_variable_name: '새로운 변수의 이름을 입력하세요(10글자 이하)',\n    family: '엔트리봇 가족',\n    fantasy: '판타지/기타',\n    file_new: '새로 만들기',\n    file_open: '온라인 작품 불러오기',\n    file_upload: '오프라인 작품 불러오기',\n    file_upload_login_check_msg: '오프라인 작품을 불러오기 위해서는 로그인을 해야 합니다.',\n    file_save: '저장하기',\n    file_save_as: '복사본으로 저장하기',\n    file_save_download: '내 컴퓨터에 저장하기',\n    func: '함수',\n    function_create: '함수 만들기',\n    function_add: '함수 추가하기',\n    interface: '인터페이스',\n    landscape: '배경',\n    list: '리스트',\n    list_add_calcel: '리스트 추가 취소',\n    list_add_calcel_msg: '리스트 추가를 취소하였습니다.',\n    list_add_fail: '리스트 추가 실패',\n    list_add_fail_msg1: '같은 이름의 리스트가 이미 존재합니다.',\n    list_add_fail_msg2: '리스트의 이름이 적절하지 않습니다.',\n    list_add_ok: '리스트 추가 완료',\n    list_add_ok_msg: '을(를) 추가하였습니다.',\n    list_create: '리스트 추가하기',\n    list_create_placeholder: '리스트의 이름을 입력해주세요.',\n    list_dup: '같은 이름의 리스트가 이미 존재합니다.',\n    list_newname: '새로운 이름',\n    list_export: '리스트 내보내기',\n    list_import: '리스트 불러오기',\n    list_remove: '리스트 삭제',\n    list_rename: '리스트 이름 변경',\n    list_rename_failed: '리스트 이름 변경 실패',\n    list_rename_ok: '리스트의 이름이 성공적으로 변경 되었습니다.',\n    list_too_long: '리스트의 이름이 너무 깁니다.',\n    message: '신호',\n    message_add_cancel: '신호 추가 취소',\n    message_add_cancel_msg: '신호 추가를 취소하였습니다.',\n    message_add_fail: '신호 추가 실패',\n    message_add_fail_msg: '같은 이름의 신호가 이미 존재합니다.',\n    message_add_ok: '신호 추가 완료',\n    message_add_ok_msg: '을(를) 추가하였습니다.',\n    message_create: '신호 추가하기',\n    message_create_placeholder: '신호의 이름을 입력해주세요.',\n    message_dup: '같은 이름의 신호가 이미 존재합니다.',\n    message_remove: '신호 삭제',\n    message_remove_canceled: '신호 삭제를 취소하였습니다.',\n    message_rename: '신호 이름을 변경하였습니다.',\n    message_rename_failed: '신호 이름 변경 실패',\n    message_rename_ok: '신호의 이름이 성공적으로 변경 되었습니다.',\n    message_too_long: '신호의 이름이 너무 깁니다.',\n    no_message_to_remove: '삭제할 신호가 없습니다',\n    no_use: '사용되지 않음',\n    no_variable_to_remove: '삭제할 변수가 없습니다.',\n    no_variable_to_rename: '변경할 변수가 없습니다.',\n    object_not_found: '블록에서 지정한 오브젝트가 존재하지 않습니다.',\n    object_not_found_for_paste: '붙여넣기 할 오브젝트가 없습니다.',\n    people: '일반 사람들',\n    picture_add: '모양 추가하기',\n    table_add: '테이블 추가하기',\n    draw_new_table: '새로 만들기',\n    plant: '식물',\n    project: '작품',\n    project_copied: '의 사본',\n    PROJECTDEFAULTNAME: ['멋진', '재밌는', '착한', '큰', '대단한', '잘생긴', '행운의'],\n    remove_object: '오브젝트 삭제',\n    remove_object_msg: '(이)가 삭제되었습니다.',\n    removed_msg: '(이)가 성공적으로 삭제 되었습니다.',\n    rotate_method: '회전방식',\n    rotation: '방향',\n    run: '시작하기',\n    saved: '저장완료',\n    saved_msg: '(이)가 저장되었습니다.',\n    save_failed: '저장시 문제가 발생하였습니다. 다시 시도해 주세요.',\n    select_library: '오브젝트 선택',\n    select_sprite: '적용할 스프라이트를 하나 이상 선택하세요.',\n    shape_remove_fail: '모양 삭제 실패',\n    shape_remove_fail_msg: '적어도 하나 이상의 모양이 존재하여야 합니다.',\n    shape_remove_ok: '모양이 삭제 되었습니다. ',\n    shape_remove_ok_msg: '이(가) 삭제 되었습니다.',\n    load_expansion_block: '확장 블록 불러오기',\n    load_ai_utilize_block: 'AI 블록 불러오기',\n    load_ai_utilize_train_block: '모델 학습',\n    select_expansion_block: '확장블록 선택',\n    deselect_expansion_block_warning: '확장블록이 사용중이므로 삭제할 수 없습니다.',\n    deselect_ai_utilize_block_warning: 'AI블록이 사용중이므로 삭제할 수 없습니다.',\n    sound_add: '소리 추가하기',\n    sound_remove_fail: '소리 삭제 실패',\n    sound_remove_ok: '소리 삭제 완료',\n    sound_remove_ok_msg: '이(가) 삭제 되었습니다.',\n    stop: '정지하기',\n    pause: '일시정지',\n    restart: '다시시작',\n    speed: '속도 조절',\n    tab_attribute: '속성',\n    tab_table: '테이블',\n    tab_code: '블록',\n    tab_picture: '모양',\n    tab_sound: '소리',\n    tab_text: '글상자',\n    textbox: '글상자',\n    textbox_edit: '글상자 편집',\n    textbox_input: '글상자의 내용을 입력해주세요.',\n    things: '물건',\n    textcoding_tooltip1:\n        '블록코딩과 엔트리파이선을<br/>선택하여 자유롭게<br/>코딩을 해볼 수 있습니다.',\n    textcoding_tooltip2:\n        '실제 개발 환경과 동일하게<br/>엔트리파이선 모드의 실행 결과를<br/>확인할 수 있습니다.',\n    textcoding_tooltip3:\n        '엔트리파이선에 대한<br/>기본사항이 안내되어 있습니다.<br/><엔트리파이선 이용안내>를 확인해 주세요!',\n    upload: '파일 올리기',\n    upload_addfile: '파일 올리기',\n    variable: '변수',\n    variable_add_calcel: '변수 추가 취소',\n    variable_add_calcel_msg: '변수 추가를 취소하였습니다.',\n    variable_add_fail: '변수 추가 실패',\n    variable_add_fail_msg1: '같은 이름의 변수가 이미 존재합니다.',\n    variable_add_fail_msg2: '변수의 이름이 적절하지 않습니다.',\n    variable_add_ok: '변수 추가 완료',\n    variable_add_ok_msg: '을(를) 추가하였습니다.',\n    variable_create: '변수 만들기',\n    variable_add: '변수 추가하기',\n    variable_dup: '같은 이름의 변수가 이미 존재합니다.',\n    variable_newname: '새로운 이름',\n    variable_remove: '변수 삭제',\n    variable_remove_canceled: '변수 삭제를 취소하였습니다.',\n    variable_rename: '변수 이름을 변경합니다. ',\n    variable_rename_failed: '변수 이름 변경에 실패하였습니다. ',\n    variable_rename_msg: \"'변수의 이름이 성공적으로 변경 되었습니다.'\",\n    variable_rename_ok: '변수의 이름이 성공적으로 변경 되었습니다.',\n    variable_select: '변수를 선택하세요',\n    variable_too_long: '변수의 이름이 너무 깁니다.',\n    open_analizy_data_import: '데이터 화면 열기',\n    vehicle: '탈것',\n    add_object_alert_msg: '오브젝트를 추가해주세요',\n    add_object_alert: '경고',\n    create_variable_block: '변수 만들기',\n    create_list_block: '리스트 만들기',\n    Variable_Timer: '초시계',\n    Variable_placeholder_name: '변수 이름',\n    Message_placeholder_name: '신호 이름',\n    Variable_property: '변수 속성',\n    Variable_placeholder_content: '변수의 이름을 입력해주세요.',\n    Variable_use_all_objects: '모든 오브젝트에서 사용',\n    Variable_use_this_object: '이 오브젝트에서 사용',\n    Variable_used_at_all_objects: '모든 오브젝트에서 사용되는 변수',\n    variable_create_normal: '일반 변수로 사용\\n(작품에 저장)',\n    variable_create_cloud: '공유 변수로 사용\\n(서버에 저장)',\n    variable_create_real_time: '실시간 변수로 사용\\n(서버에 저장)',\n    Variable_used_at_special_object: '특정 오브젝트에서만 사용되는 변수',\n    Variable_used_objects: '사용된 오브젝트',\n    draw_new: '새로 그리기',\n    draw_new_ebs: '직접 그리기',\n    painter_file: '파일 ▼',\n    painter_file_save: '저장하기',\n    painter_file_saveas: '새 모양으로 저장',\n    new_picture: '새그림',\n    painter_edit: '편집 ▼',\n    get_file: '가져오기',\n    copy_file: '복사하기',\n    cut_picture: '자르기',\n    paste_picture: '붙이기',\n    remove_all: '모두 지우기',\n    flip_horizontal: '좌우뒤집기',\n    flip_vertical: '상하뒤집기',\n    regular: '보통',\n    bold: '굵게',\n    font_underline: '밑줄',\n    font_tilt: '기울임',\n    font_cancel: '취소선',\n    font_color: '글꼴 색상',\n    font_fill: '채우기 색상',\n    font_family: '글꼴',\n    align_left: '왼쪽 정렬',\n    align_center: '가운데 정렬',\n    align_right: '오른쪽 정렬',\n    italic: '기울임',\n    textStyle: '글자',\n    add_picture: '모양 추가',\n    select_picture: '모양 선택',\n    select_table: '테이블 선택',\n    select_sound: '소리 선택',\n    Size: '크기',\n    show_variable: '변수 노출',\n    default_value: '기본값 ',\n    slide: '슬라이드',\n    min_value: '최솟값',\n    max_value: '최댓값',\n    number_of_list: '리스트 항목 수',\n    empty_of_list: '추가된 항목이 없습니다',\n    use_all_objects: '모든 오브젝트에 사용',\n    list_name: '리스트 이름',\n    list_property: '리스트 속성',\n    list_used_specific_objects: '특정 오브젝트에서만 사용되는 리스트',\n    List_used_all_objects: '모든 오브젝트에서 사용되는 리스트',\n    List_used_objects: '사용된 오브젝트',\n    Scene_delete_error: '장면은 최소 하나 이상 존재해야 합니다.',\n    Scene_add_error: '장면은 최대 20개까지 추가 가능합니다.',\n    replica_of_object: '의 복제본',\n    will_you_delete_scene: '장면은 한번 삭제하면 취소가 불가능 합니다. \\n정말 삭제 하시겠습니까?',\n    will_you_delete_function:\n        '함수는 한번 삭제하면 취소가 불가능 합니다. \\n정말 삭제 하시겠습니까?',\n    duplicate_scene: '복제하기',\n    block_explain: '블록 설명 ',\n    block_intro: '블록을 클릭하면 블록에 대한 설명이 나타납니다.',\n    blocks_reference: '블록 설명',\n    hardware_guide: '하드웨어 연결 안내',\n    robot_guide: '로봇 연결 안내',\n    python_guide: '엔트리파이선 이용 안내',\n    show_list_workspace: '리스트 노출',\n    list_create_normal: '일반 리스트로 사용\\n(작품에 저장)',\n    list_create_cloud: '공유 리스트로 사용 \\n(서버에 저장)',\n    list_create_real_time: '실시간 리스트로 사용\\n(서버에 저장)',\n    confirm_quit: '바꾼 내용을 저장하지 않았습니다.',\n    confirm_load_temporary: '저장되지 않은 작품이 있습니다. 여시겠습니까?',\n    login_to_save: '로그인후에 저장 바랍니다.',\n    cannot_save_in_edit_func: '함수 편집중에는 저장할 수 없습니다.',\n    new_object: '새 오브젝트',\n    arduino_connect: '하드웨어 연결',\n    arduino_connect_success: '하드웨어가 연결되었습니다.',\n    confirm_load_header: '작품 복구',\n    uploading_msg: '업로드 중입니다',\n    upload_fail_msg: '업로드에 실패하였습니다.</br>다시 한번 시도해주세요.',\n    upload_not_supported_msg: '지원하지 않는 형식입니다.',\n    upload_not_supported_file_msg: '지원하지 않는 형식의 파일입니다.',\n    file_converting_msg: '파일 변환 중입니다.',\n    file_converting_fail_msg: '파일 변환에 실패하였습니다.',\n    fail_contact_msg: '문제가 계속된다면</br>entry@connect.or.kr 로 문의해주세요.',\n    saving_msg: '저장 중입니다',\n    saving_fail_msg: '저장에 실패하였습니다.</br>다시 한번 시도해주세요.',\n    loading_msg: '불러오는 중입니다',\n    loading_fail_msg: '불러오기에 실패하였습니다.</br>다시 한번 시도해주세요.',\n    restore_project_msg: '정상적으로 저장되지 않은 작품이 있습니다. 해당 작품을 복구하시겠습니까?',\n    quit_stop_msg: '저장 중에는 종료하실 수 없습니다.',\n    ent_drag_and_drop: '업로드 하려면 파일을 놓으세요',\n    not_supported_file_msg: '지원하지 않은 형식의 파일입니다.',\n    broken_file_msg: '파일이 깨졌거나 잘못된 파일을 불러왔습니다.',\n    check_audio_msg: 'mp3 외 오디오 파일은 재생할 수 없습니다.',\n    check_entry_file_msg: 'ENT 파일만 불러오기가 가능합니다.',\n    hardware_version_alert_text:\n        '5월 30일 부터 구버전의 연결프로그램의 사용이 중단 됩니다.\\n하드웨어 연결 프로그램을 최신 버전으로 업데이트 해주시기 바랍니다.',\n    variable_name_auto_edited_title: '변수 이름 자동 변경',\n    variable_name_auto_edited_content: '변수의 이름은 10글자를 넘을 수 없습니다.',\n    list_name_auto_edited_title: '리스트 이름 자동 변경',\n    list_name_auto_edited_content: '리스트의 이름은 10글자를 넘을 수 없습니다.',\n    cloned_scene: '복제본_',\n    default_mode: '기본형',\n    practical_course_mode: '교과형',\n    practical_course: '실과',\n    select_mode: '모드선택',\n    select_mode_popup_title: '엔트리 만들기 환경을 선택해 주세요.',\n    select_mode_popup_lable1: '기본형',\n    select_mode_popup_lable2: '교과형',\n    select_mode_popup_desc1: '엔트리의 모든 기능을 이용하여<br/>자유롭게 작품을 만듭니다.',\n    select_mode_popup_desc2: '실과 교과서에 등장하는 기능만을<br/>이용하여 작품을 만듭니다.',\n    practical_course_notice: '안내',\n    practical_course_desc:\n        \"<span class='practical_cource_title'>교과용 만들기</span>는<br />실과 교과서로 소프트웨어를 배울 때<br />필요한 기능만을 제공합니다.\",\n    practical_course_desc2:\n        '*기본형 작품 만들기를 이용하면 더 많은 기능을<br />이용해 작품을 만들 수 있습니다.',\n    practical_course_tooltip: '모든 기능을 이용하기 위해서는<br/>기본형을 선택해 주세요.',\n    name_already_exists: '이름이 중복 되었습니다.',\n    enter_the_name: '이름을 입력하여 주세요.',\n    object_not_exist_error: '오브젝트가 존재하지 않습니다. 오브젝트를 추가한 후 시도해주세요.',\n    workspace_tutorial_popup_desc:\n        \"<span class='practical_cource_title'>작품 만들기</span>는<br />창의적인 작품을 만들 수 있도록<br /> 다양한 블록과 기능을 제공합니다.\",\n    start_guide_tutorial: '만들기 이용 안내',\n    language: '언어 선택',\n    file: '파일',\n    save: '저장하기',\n    help: '도움말',\n    print: '인쇄',\n    undo: '입력 취소',\n    redo: '다시 실행',\n    workspace_title_tooltip:\n        '기본작품명이 변경되었습니다.\\n작품을 만든 날짜를 통해 어떤 작품인지 쉽게 알 수 있습니다.',\n    workspace_object_tooltip:\n        '오브젝트의 순서는 오브젝트의 대표 이미지를 잡고\\n위아래로 이동하여 변경할 수 있습니다.\\n(모양과 소리탭에서도 동일하게 동작합니다.)',\n    workspace_comment_tooltip: '조립소에 추가한 메모를\\n한꺼번에 숨기거나 보이게 할 수 있습니다.',\n    workspace_zoom_tooltip:\n        '조립소에 추가된 블록의 크기를 바꿀 수 있습니다.\\n가운데 = 아이콘을 누르면 기본 크기로 돌아옵니다.',\n    workspace_image_tooltip: '새로워진\\n작품 만들기를\\n소개합니다.',\n    playground_block_drop: '나의 보관함의 블록을\\n조립소에 추가합니다.',\n    container_object_drop: '나의 보관함의 오브젝트를\\n오브젝트 리스트에 추가합니다.',\n    my_storage_block_drop: '블록을\\n나의 보관함에\\n추가합니다.',\n    my_storage_object_drop: '오브젝트를\\n나의 보관함에\\n추가합니다.',\n    my_storage: '나의 보관함',\n    my_block: '나의 블록',\n    red: '빨강(R)',\n    green: '녹색(G)',\n    blue: '파랑(B)',\n    hue: '색상',\n    saturation: '채도',\n    brightness: '명도',\n    spoid: '스포이드',\n    palette_mode: '팔레트 모드',\n    slider_mode: '슬라이더 모드',\n    toast_error_title_object_center: '주의',\n    toast_error_contents_object_center:\n        '오브젝트 중심점이 오브젝트와 멀리 떨어져 실행화면 밖으로 벗어날 경우, 원위치로 돌아옵니다.',\n    blocks_comming_soon: '열심히 연구 중입니다.\\n조금만 기다려 주세요!',\n    data_table: '테이블',\n    select_all: '모두',\n    now_loading_msg: '로딩 중입니다.\\n잠시만 기다려주세요.',\n};\nLang.code = '코드보기';\nLang.EntryStatic = {\n    event100: '이벤트',\n    groupProject: '학급 공유하기',\n    usage_parallel: '병렬',\n    usage_expansion: '확장',\n    usage_hw: '하드웨어',\n    usage_sequence: '순차',\n    privateProject: '나만보기',\n    privateCurriculum: '나만보기',\n    publicCurriculum: '강의 모음 공유하기',\n    publicProject: '작품 공유하기',\n    group: '학급 공유하기',\n    groupCurriculum: '학급 공유하기',\n    private: '나만보기',\n    public: '강의 공유하기',\n    lecture_is_open_true: '공개',\n    lecture_is_open_false: '비공개',\n    category_all: '모든 작품',\n    category_game: '게임',\n    category_animation: '애니메이션',\n    category_media_art: '미디어 아트',\n    category_physical: '피지컬',\n    category_etc: '기타',\n    category_category_game: '게임',\n    category_category_animation: '애니메이션',\n    category_category_media_art: '미디어 아트',\n    category_category_physical: '피지컬',\n    category_category_etc: '기타',\n    sort_created: '최신순',\n    sort_updated: '최신순',\n    sort_visit: '조회순',\n    sort_likeCnt: '좋아요순',\n    sort_comment: '댓글순',\n    period_all: '전체기간',\n    period_1: '오늘',\n    period_7: '최근 1주일',\n    period_30: '최근 1개월',\n    period_90: '최근 3개월',\n    lecture_required_time_1: ' ~ 15분',\n    lecture_required_time_2: '15분 ~ 30분',\n    lecture_required_time_3: '30분 ~ 45분',\n    lecture_required_time_4: '45 분 ~ 60분',\n    lecture_required_time_5: '1시간 이상',\n    usage_event: '이벤트',\n    usage_signal: '신호보내기',\n    usage_scene: '장면',\n    usage_repeat: '반복',\n    usage_condition_repeat: '조건반복',\n    usage_condition: '선택',\n    usage_clone: '복제본',\n    usage_rotation: '회전',\n    usage_coordinate: '좌표이동',\n    usage_arrow_move: '화살표이동',\n    usage_shape: '모양',\n    usage_speak: '말하기',\n    usage_picture_effect: '그림효과',\n    usage_textBox: '글상자',\n    usage_draw: '그리기',\n    usage_sound: '소리',\n    usage_confirm: '판단',\n    usage_comp_operation: '비교연산',\n    usage_logical_operation: '논리연산',\n    usage_math_operation: '수리연산',\n    usage_random: '무작위수',\n    usage_timer: '초시계',\n    usage_variable: '변수',\n    usage_list: '리스트',\n    usage_ask_answer: '입출력',\n    usage_function: '함수',\n    usage_arduino: '아두이노',\n    concept_resource_analytics: '자료수집/분석/표현',\n    concept_procedual: '알고리즘과 절차',\n    concept_abstractive: '추상화',\n    concept_individual: '문제분해',\n    concept_automation: '자동화',\n    concept_simulation: '시뮬레이션',\n    concept_parallel: '병렬화',\n    subject_korean: '국어',\n    subject_english: '영어',\n    subject_mathmatics: '수학',\n    subject_social: '사회',\n    subject_science: '과학',\n    subject_music: '음악',\n    subject_paint: '미술',\n    subject_athletic: '체육',\n    subject_courtesy: '도덕',\n    subject_progmatic: '실과',\n    lecture_grade_1: '초1',\n    lecture_grade_2: '초2',\n    lecture_grade_3: '초3',\n    lecture_grade_4: '초4',\n    lecture_grade_5: '초5',\n    lecture_grade_6: '초6',\n    lecture_grade_7: '중1',\n    lecture_grade_8: '중2',\n    lecture_grade_9: '중3',\n    lecture_grade_10: '일반',\n    lecture_level_1: '쉬움',\n    lecture_level_2: '중간',\n    lecture_level_3: '어려움',\n    listEnable: '리스트',\n    functionEnable: '함수',\n    messageEnable: '신호',\n    objectEditable: '오브젝트',\n    pictureeditable: '모양',\n    sceneEditable: '장면',\n    soundeditable: '소리',\n    variableEnable: '변수',\n    e_1: '초등 1학년',\n    e_2: '초등 2학년',\n    e_3: '초등 3학년',\n    e_4: '초등 4학년',\n    e_5: '초등 5학년',\n    e_6: '초등 6학년',\n    m_1: '중등 1학년',\n    m_2: '중등 2학년',\n    m_3: '중등 3학년',\n    general: '일반',\n    curriculum_is_open_true: '공개',\n    curriculum_open_false: '비공개',\n    contest2019: '공모전',\n    exhibit: '공모전',\n    notice: '공지사항',\n    qna: '묻고답하기',\n    tips: '노하우&팁',\n    free: '엔트리 이야기',\n    report: '제안 및 건의',\n    art_category_all: '모든 작품',\n    art_category_game: '게임',\n    art_category_animation: '애니메이션',\n    art_category_physical: '피지컬',\n    art_category_etc: '기타',\n    art_category_media: '미디어 아트',\n    art_sort_updated: '최신순',\n    art_sort_visit: '조회순',\n    art_sort_likeCnt: '좋아요순',\n    art_sort_comment: '댓글순',\n    art_period_all: '전체기간',\n    art_period_day: '오늘',\n    art_period_week: '최근 1주일',\n    art_period_month: '최근 1개월',\n    art_period_three_month: '최근 3개월',\n    level_high: '상',\n    level_mid: '중',\n    level_row: '하',\n    discuss_sort_created: '최신순',\n    discuss_sort_visit: '조회순',\n    discuss_sort_likesLength: '좋아요순',\n    discuss_sort_commentsLength: '댓글순',\n    discuss_period_all: '전체기간',\n    discuss_period_day: '오늘',\n    discuss_period_week: '최근 1주일',\n    discuss_period_month: '최근 1개월',\n    discuss_period_three_month: '최근 3개월',\n};\nLang.Helper = {\n    when_run_button_click: '시작하기 버튼을 클릭하면 아래에 연결된 블록들을 실행합니다.',\n    when_some_key_pressed: '선택한 키를 누르면 아래에 연결된 블록들을 실행합니다.',\n    mouse_clicked: '마우스를 클릭했을 때 아래에 연결된 블록들을 실행합니다.',\n    mouse_click_cancled: '마우스 클릭을 해제했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_object_click: '오브젝트를 클릭했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_object_click_canceled: '오브젝트 클릭을 해제했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_message_cast: '선택한 신호를 받으면 아래에 연결된 블록들을 실행합니다.',\n    message_cast: '선택한 신호를 보냅니다.',\n    message_cast_wait:\n        '선택한 신호를 보내고, 해당 신호를 받는 블록들의 실행이 끝날 때 까지 기다립니다.',\n    when_scene_start: '장면이 시작되면 아래에 연결된 블록들을 실행합니다. ',\n    start_scene: '선택한 장면을 시작합니다.',\n    start_neighbor_scene: '이전 또는 다음 장면을 시작합니다.',\n    wait_second: '입력한 시간만큼 기다린 후 다음 블록을 실행합니다.',\n    repeat_basic: '입력한 횟수만큼 감싸고 있는 블록들을 반복 실행합니다.',\n    repeat_inf: '감싸고 있는 블록들을 계속해서 반복 실행합니다.',\n    repeat_while_true:\n        '판단값에 따라 블록의 반복여부를 결정합니다.\\n이 될 때까지: 판단이 참이 될 때까지 감싸고 있는 블록들을 반복 실행합니다.\\n인 동안: 판단이 참인 동안 감싸고 있는 블록들을 반복 실행합니다.',\n    stop_repeat: '이 블록을 감싸는 가장 가까운 반복 블록의 반복을 중단합니다.',\n    _if: '만일 판단이 참이라면, 감싸고 있는 블록들을 실행합니다.',\n    if_else:\n        '만일 판단이 참이라면 첫 번째 감싸고 있는 블록들을 실행하고, 거짓이면 두 번째 감싸고 있는 블록들을 실행합니다.',\n    restart_project: '작품을 처음부터 다시 실행합니다.',\n    stop_object:\n        '블록이 실행을 멈춥니다. 현재 실행중인 동작을 멈추는 블록이며, 프로그램을 종료하지 않습니다.\\n모든 : 작품의 모든 블록이 실행을 멈춥니다. \\n자신 : 해당 오브젝트의 모든 블록이 실행을 멈춥니다.\\n이 코드 : 이 블록이 포함된 블록들이 실행을 멈춥니다.\\n자신의 다른 코드 :  해당 오브젝트 중 이 블록이 포함된 블록들을 제외한 모든 블록이 실행을 멈춥니다.\\n다른 오브젝트의 : 다른 오브젝트의 모든 블록이 실행을 멈춥니다.',\n    wait_until_true: '판단이 참이 될 때까지 실행을 멈추고 기다립니다.',\n    when_clone_start:\n        '해당 오브젝트의 복제본이 새로 생성되었을 때 아래에 연결된 블록들을 실행합니다.',\n    create_clone: '선택한 오브젝트의 복제본을 생성합니다.',\n    delete_clone:\n        '‘복제본이 처음 생성되었을 때’ 블록과 함께 사용되며, 연결된 블록들이 실행되고 있는 복제본을 삭제합니다.',\n    remove_all_clones: '해당 오브젝트의 모든 복제본을 삭제합니다.',\n    move_direction: '입력한 값만큼 오브젝트의 이동 방향 화살표가 가리키는 방향으로 움직입니다.',\n    move_x: '오브젝트의 x 좌표를 입력한 값만큼 바꿉니다. ',\n    move_y: '오브젝트의 y 좌표를 입력한 값만큼 바꿉니다.',\n    move_xy_time: '오브젝트가 입력한 시간에 걸쳐 x와 y 좌표를 입력한 값만큼 바꿉니다.',\n    locate_object_time:\n        '오브젝트가 입력한 시간에 걸쳐 선택한 오브젝트 또는 마우스 포인터의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_x: '오브젝트가 입력한 x 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_y: '오브젝트가 입력한 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy: '오브젝트가 입력한 x와 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_time:\n        '오브젝트가 입력한 시간에 걸쳐 입력한 x와 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate: '오브젝트가 선택한 오브젝트 또는 마우스 포인터의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    rotate_absolute: '오브젝트의 방향을 입력한 각도로 정합니다.',\n    rotate_by_time:\n        '오브젝트의 방향이 입력한 시간에 걸쳐 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_relative:\n        '오브젝트의 방향이 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    direction_absolute: '오브젝트의 이동 방향을 입력한 각도로 정합니다.',\n    direction_relative:\n        '오브젝트의 이동 방향이 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    move_to_angle:\n        '오브젝트가 입력한 각도 방향으로 입력한 값만큼 움직입니다. (실행화면 위쪽이 0도를 나타내며, 시계방향으로 갈수록 각도가 증가합니다.)',\n    see_angle_object:\n        '해당 오브젝트가 방향을 회전하여 선택한 오브젝트 또는 마우스 포인터 쪽을 바라봅니다. ',\n    bounce_wall: '오브젝트가 실행화면 끝에 닿으면 튕겨 나옵니다.',\n    show: '오브젝트를 실행화면에 보이게 합니다.',\n    hide: '오브젝트를 실행화면에 보이지 않게 합니다.',\n    dialog_time:\n        '오브젝트가 입력한 내용을 입력한 시간 동안 말풍선으로 말한 후 다음 블록을 실행합니다.',\n    dialog: '오브젝트가 입력한 내용을 말풍선으로 말하는 동시에 다음 블록을 실행합니다.',\n    remove_dialog: '오브젝트가 말하고 있는 말풍선을 지웁니다.',\n    change_to_some_shape:\n        '오브젝트를 선택한 모양으로 바꿉니다. (내부 블록을 분리하고 모양의 번호를 입력하여 모양을 바꿀 수 있습니다.)',\n    change_to_next_shape: '오브젝트의 모양을 이전 또는 다음 모양으로 바꿉니다.',\n    set_effect_volume: '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.',\n    set_effect_amount: '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.',\n    set_effect:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n색깔 : 0~100을 주기로 반복됩니다.\\n밝기 : -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.)\\n투명도 : 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로, 100 이상은 100으로 처리됩니다.)',\n    set_entity_effect:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n색깔 : 0~100을 주기로 반복됩니다.\\n밝기 : -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.)\\n투명도 : 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로, 100 이상은 100으로 처리됩니다.)',\n    add_effect_amount: '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.',\n    change_effect_amount:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n색깔 : 0~100을 주기로 반복됩니다.\\n밝기 : -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.)\\n투명도 : 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로, 100 이상은 100으로 처리됩니다.)',\n    change_scale_percent: '오브젝트의 크기를 입력한 값만큼 바꿉니다.',\n    set_scale_percent: '오브젝트의 크기를 입력한 값으로 정합니다.',\n    change_scale_size: '오브젝트의 크기를 입력한 값만큼 바꿉니다.',\n    set_scale_size: '오브젝트의 크기를 입력한 값으로 정합니다.',\n    flip_x: '오브젝트의 상하 모양을 뒤집습니다.',\n    flip_y: '오브젝트의 좌우 모양을 뒤집습니다.',\n    change_object_index:\n        '오브젝트가 실행화면에 보이는 순서를 변경합니다.\\n맨 앞으로 : 해당 오브젝트를 실행화면의 가장 앞쪽으로 가져옵니다. \\n앞으로 : 해당 오브젝트를 한 층 앞쪽으로 가져옵니다.\\n뒤로 : 해당 오브젝트를 한 층 뒤쪽으로 보냅니다. \\n맨 뒤로 : 해당 오브젝트를 실행화면의 가장 뒤쪽으로 보냅니다.',\n    set_object_order: '해당 오브젝트가 설정한 순서로 올라옵니다.',\n    brush_stamp: '오브젝트의 모양을 도장처럼 실행화면 위에 찍습니다.',\n    start_drawing:\n        '오브젝트가 이동하는 경로를 따라 선이 그리기 시작합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    stop_drawing: '오브젝트가 선 그리는 것을 멈춥니다.',\n    set_color: '오브젝트가 그리는 선의 색을 선택한 색으로 정합니다.',\n    set_random_color: '오브젝트가 그리는 선의 색을 무작위로 정합니다. ',\n    change_thickness: '오브젝트가 그리는 선의 굵기를 입력한 값만큼 바꿉니다.',\n    set_thickness:\n        '오브젝트가 그리는 선의 굵기를 입력한 값으로 정합니다. 1~무한의 범위로 설정할 수 있습니다. (1 이하는 1로 처리합니다.)',\n    change_opacity: '해당 오브젝트가 그리는 붓의 투명도를 입력한 값만큼 바꿉니다.',\n    change_brush_transparency: '해당 오브젝트가 그리는 붓의 투명도를 입력한 값만큼 바꿉니다.',\n    set_opacity:\n        '해당 오브젝트가 그리는 붓의 투명도를 입력한 값으로 정합니다. 0~100의 범위로 설정할 수 있습니다. (0 이하는 0, 100 이상은 100으로 처리합니다.)',\n    set_brush_tranparency:\n        '해당 오브젝트가 그리는 붓의 투명도를 입력한 값으로 정합니다. 0~100의 범위로 설정할 수 있습니다. (0 이하는 0, 100 이상은 100으로 처리합니다.)',\n    brush_erase_all: '해당 오브젝트가 그린 선과 도장을 모두 지웁니다.',\n    sound_something_with_block:\n        '해당 오브젝트가 선택한 소리를 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_something_second_with_block:\n        '해당 오브젝트가 선택한 소리를 입력한 시간 만큼 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_something_wait_with_block:\n        '해당 오브젝트가 선택한 소리를 재생한 후 다음 블록을 실행합니다.',\n    sound_something_second_wait_with_block:\n        '해당 오브젝트가 선택한 소리를 입력한 시간 만큼 재생한 후 다음 블록을 실행합니다.',\n    sound_volume_change: '작품에서 재생되는 모든 소리의 크기를 입력한 값만큼 바꿉니다.',\n    sound_volume_set: '작품에서 재생되는 모든 소리의 크기를 입력한 값으로 정합니다.',\n    sound_silent_all: '재생 중인 모든 소리를 멈춥니다.',\n    is_clicked: '마우스를 클릭한 경우 ‘참’으로 판단합니다.',\n    is_object_clicked: '오브젝트를 클릭한 경우 ‘참’으로 판단합니다.',\n    is_press_some_key: '선택한 키가 눌려져 있는 경우 ‘참’으로 판단합니다.',\n    reach_something: '해당 오브젝트가 선택한 항목과 닿은 경우 ‘참’으로 판단합니다.',\n    is_type: '입력한 값이 숫자라면 ‘참’으로 판단합니다.',\n    is_included_in_list:\n        \"선택한 리스트가 입력한 값을 가진 항목을 포함하는 경우 '참'으로 판단합니다.\",\n    boolean_basic_operator:\n        \"입력한 두 값을 비교합니다.\\n= : 왼쪽에 위치한 값과 오른쪽에 위치한 값이 같은 경우 '참'으로 판단합니다.\\n> : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 큰 경우 '참'으로 판단합니다.\\n< : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 작은 경우 '참'으로 판단합니다.\\n≥ : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 크거나 같은 경우 '참'으로 판단합니다.\\n≤ : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 작거나 같은 경우 '참'으로 판단합니다.\",\n    function_create:\n        '자주 쓰는 코드를 이 블록 아래에 조립하여 함수로 만듭니다. [함수 정의하기]의 오른쪽 빈칸에 [이름]을 조립하여 함수의 이름을 정할 수 있습니다. 함수를 실행하는 데 입력값이 필요한 경우 빈칸에 [문자/숫자값], [판단값]을 조립하여 매개변수로 사용합니다.',\n    function_field_label: \"함수 정의하기' 블록 안에 조립하며, 함수의 이름을 정합니다. \",\n    function_field_string:\n        \"함수 정의하기' 블록 안에 조립하며, 입력한 문자/숫자값(매개변수)에 따라 함수의 실행 결과가 달라집니다. 이 블록을 분리하여 함수의 코드 중 필요한 부분에 넣어 사용합니다.\",\n    function_field_boolean:\n        \"함수 정의하기' 블록 안에 조립하며, 참 또는 거짓의 판단값에 따라 함수의 실행 결과가 달라집니다. 이 블록을 분리하여 함수의 코드 중 필요한 부분에 넣어 사용합니다.\",\n    function_general: '현재 만들고 있는 함수 블록 또는 지금까지 만들어 둔 함수 블록입니다.',\n    boolean_and: '두 판단이 모두 참인 경우 ‘참’으로 판단합니다.',\n    boolean_or: '두 판단 중 하나라도 참이 있는 경우 ‘참’으로 판단합니다.',\n    boolean_not: '해당 판단이 참이면 거짓, 거짓이면 참으로 만듭니다.',\n    calc_basic:\n        '입력한 두 수의 사칙연산 값입니다.\\n+ : 입력한 두 수를 더한 값입니다.\\n- : 입력한 두 수를 뺀 값입니다.\\n* : 입력한 두 수를 곱한 값입니다.\\n/ : 입력한 두 수를 나눈 값입니다.',\n    calc_rand:\n        '입력한 두 수 사이에서 선택된 무작위 수 값입니다. (두 수 모두 정수를 입력한 경우 정수가, 두 수 중 하나라도 소수를 입력한 경우 소숫점 둘째 자리의 소수 값이 선택됩니다.)',\n    get_x_coordinate: '해당 오브젝트의 x 좌푯값을 의미합니다.',\n    get_y_coordinate: '해당 오브젝트의 y 좌푯값을 의미합니다.',\n    coordinate_mouse: '마우스 포인터의 x 또는 y 좌푯값입니다.',\n    coordinate_object:\n        '선택한 오브젝트의 각종 정보 값입니다. (x 좌표, y 좌표, 방향, 이동방향, 크기, 모양번호, 모양이름)',\n    quotient_and_mod:\n        '입력된 두 수를 나눈 결괏값입니다.\\n몫 : 앞의 수에서 뒤의 수를 나누어 생긴 몫의 값입니다. \\n나머지 : 앞의 수에서 뒤의 수를 나누어 생긴 나머지 값입니다.',\n    get_rotation_direction: '해당 오브젝트의 방향값, 이동 방향값을 의미합니다.',\n    calc_share: '앞 수에서 뒤 수를 나누어 생긴 몫을 의미합니다.',\n    calc_mod: '앞 수에서 뒤 수를 나누어 생긴 나머지를 의미합니다.',\n    calc_operation:\n        '입력한 수에 대한 다양한 수학식의 계산값입니다. (제곱, 루트, 사인값, 코사인값, 탄젠트값, 아크사인값, 아크코사인값, 아크탄젠트값, 로그값, 자연로그값, 소수점 부분, 소수점 버림값, 소수점 올림값, 소수점 반올림값, 펙토리얼값, 절대값)',\n    get_date: '현재 연도, 월, 일, 요일, 시각과 같이 시간에 대한 값입니다.',\n    distance_something: '해당 오브젝트와 선택한 오브젝트 또는 마우스 포인터 간의 거릿값입니다.',\n    get_sound_duration: '선택한 소리의 길이(초) 값입니다.',\n    get_user_name: '작품을 실행하고 있는 사용자의 이름값입니다.',\n    get_project_timer_value: '이 블록이 실행되는 순간 초시계에 저장된 값입니다.',\n    choose_project_timer_action:\n        '초시계의 상태를 결정합니다.\\n시작하기: 초시계를 시작합니다. \\n정지하기: 초시계를 정지합니다. \\n초기화하기: 초시계의 값을 0으로 초기화합니다. ',\n    reset_project_timer: '실행되고 있던 타이머를 0으로 초기화합니다.',\n    set_visible_project_timer: '초시계 창을 실행화면에서 숨기거나 보이게 합니다.',\n    ask_and_wait:\n        '오브젝트가 입력한 문자를 말풍선으로 묻고, 대답을 입력받습니다. (이 블록이 실행되면 실행화면에 ‘대답 창’이 생성됩니다.)',\n    get_canvas_input_value: \"사용자가 '대답 창'에 입력한 값입니다.\",\n    set_visible_answer: \"대답 창'을 실행화면에서 숨기거나 보이게 합니다.\",\n    combine_something: '입력한 두 값을 결합한 값입니다.',\n    reverse_of_string: '입력한 값을 뒤집은 값입니다.',\n    get_variable: '선택한 변수에 저장된 값입니다.',\n    change_variable: '선택한 변수에 입력한 값을 더합니다.',\n    set_variable: '선택한 변수의 값을 입력한 값으로 정합니다.',\n    robotis_carCont_sensor_value:\n        '왼쪽 접속 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>오른쪽 접촉 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>선택 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.<br/>최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>왼쪽 적외선 센서 : 물체와 가까울 수록 큰 값 입니다.<br/>오른쪽 적외선 센서 : 물체와 가까울 수록 큰 값 값 입니다.<br/>왼쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>오른쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>(*캘리브레이션 값 - 적외선센서 조정 값)',\n    robotis_carCont_cm_led:\n        '4개의 LED 중 1번 또는 4번 LED 를 켜거나 끕니다.<br/>LED 2번과 3번은 동작 지원하지 않습니다.',\n    robotis_carCont_cm_sound_detected_clear: '최종 소리 감지횟 수를 0 으로 초기화 합니다.',\n    robotis_carCont_aux_motor_speed: '감속모터 속도를 0 ~ 1023 의 값(으)로 정합니다.',\n    robotis_carCont_cm_calibration:\n        '적외선센서 조정 값(http://support.robotis.com/ko/: 자동차로봇> 2. B. 적외선 값 조정)을 직접 정합니다.',\n    robotis_openCM70_sensor_value:\n        '최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.',\n    robotis_openCM70_aux_sensor_value:\n        '서보모터 위치 : 0 ~ 1023, 중간 위치의 값은 512 입니다.<br/>적외선센서 :  물체와 가까울 수록 큰 값 입니다.<br/>접촉센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>조도센서(CDS) : 0 ~ 1023, 밝을 수록 큰 값 입니다.<br/>온습도센서(습도) : 0 ~ 100, 습할 수록 큰 값 입니다.<br/>온습도센서(온도) : -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>온도센서 :  -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>초음파센서 : -<br/>자석센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>동작감지센서 : 동작 감지(1), 동작 미감지(0) 값 입니다.<br/>컬러센서 : 알수없음(0), 흰색(1), 검은색(2), 빨간색(3), 녹색(4), 파란색(5), 노란색(6) 값 입니다.<br/>사용자 장치 : 사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_buzzer_index: '음계를 0.1 ~ 5 초 동안 연주 합니다.',\n    robotis_openCM70_cm_buzzer_melody:\n        \"멜로디를 연주 합니다.<br/>멜로디를 연속으로 재생하는 경우, 다음 소리가 재생되지 않으면 '흐름 > X 초 기다리기' 블록을 사용하여 기다린 후 실행합니다.\",\n    robotis_openCM70_cm_sound_detected_clear: '최종 소리 감지횟 수를 0 으로 초기화 합니다.',\n    robotis_openCM70_cm_led: '제어기의 빨간색, 녹색, 파란색 LED 를 켜거나 끕니다.',\n    robotis_openCM70_cm_motion: '제어기에 다운로드 되어있는 모션을 실행합니다.',\n    robotis_openCM70_cm_autodrive_motor: '자율주행 자동차의 모터 포트를 지정합니다.',\n    robotis_openCM70_cm_autodrive_ir: '자율주행 자동차의 적외선 센서 포트를 지정합니다.',\n    robotis_openCM70_cm_autodrive_speed: '지정한 속도로 자율주행을 수행합니다.',\n    robotis_openCM70_aux_car_move: '로봇을 지정한 속도와 방향으로 움직이도록 합니다.',\n    robotis_openCM70_aux_motor_speed: '감속모터 속도를 0 ~ 100% 의 값으로 정합니다.',\n    robotis_openCM70_aux_servo_mode:\n        '서보모터를 회전모드 또는 관절모드로 정합니다.<br/>한번 설정된 모드는 계속 적용됩니다.<br/>회전모드는 서보모터 속도를 지정하여 서보모터를 회전 시킵니다.<br/>관절모드는 지정한 서보모터 속도로 서보모터 위치를 이동 시킵니다.',\n    robotis_openCM70_aux_servo_speed: '서보모터 속도를 0 ~ 100% 의 값으로 정합니다.',\n    robotis_openCM70_aux_servo_position:\n        '서보모터 위치를 -150도 ~ 150도 의 값(으)로 정합니다.<br/>서보모터 속도와 같이 사용해야 합니다.',\n    robotis_openCM70_aux_led_module: 'LED 모듈의 LED 를 켜거나 끕니다.',\n    robotis_openCM70_aux_custom:\n        '사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_poweroff_timer:\n        '제어기의 자동꺼짐 타이머를 설정합니다.<br/>설정된 만큼의 시간동안 통신이 진행되지 않으면 제어기는 자동으로 꺼집니다.',\n    robotis_openCM70_cm_custom_value:\n        '컨트롤 테이블 주소를 직접 입력하여 값을 확인 합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_custom:\n        '컨트롤 테이블 주소를 직접 입력하여 값을 정합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    show_variable: \"선택한 변수의 '변수 창'을 실행화면에 보이게 합니다.\",\n    hide_variable: \"선택한 변수의 '변수 창'을 실행화면에서 숨깁니다.\",\n    value_of_index_from_list: '선택한 리스트에서 입력한 순서에 있는 항목 값입니다.',\n    add_value_to_list: '입력한 값을 선택한 리스트의 마지막 항목에 추가합니다.',\n    remove_value_from_list: '선택한 리스트의 입력한 순서에 있는 항목을 삭제합니다.',\n    insert_value_to_list:\n        '입력한 값을 선택한 리스트의 입력한 순서의 항목으로 추가합니다. (입력한 항목 뒤에 있는 항목들은 순서가 하나씩 밀려납니다.)',\n    change_value_list_index:\n        '선택한 리스트에서 입력한 순서에 있는 항목의 값을 입력한 값으로 바꿉니다.',\n    length_of_list: '선택한 리스트가 보유한 항목의 개수입니다.',\n    show_list: \"선택한 리스트의 '리스트 창'을 실행화면에 보이게 합니다.\",\n    hide_list: \"선택한 리스트의 '리스트 창'을 실행화면에서 숨깁니다.\",\n    text: '해당 글상자가 표시하고 있는 문자값을 의미합니다.',\n    text_read:\n        '선택한 글상자에 작성된 내용입니다. (내용 안에 줄 바꿈이 있는 경우, 띄어쓰기하여 반환됩니다.)',\n    text_write: '글상자의 내용을 입력한 값으로 고쳐 씁니다.',\n    text_append: '글상자의 내용 뒤에 입력한 값을 추가합니다.',\n    text_prepend: '글상자의 내용 앞에 입력한 값을 추가합니다.',\n    text_flush: '글상자의 내용을 모두 지웁니다.',\n    erase_all_effects: '오브젝트에 적용된 효과를 모두 지웁니다.',\n    char_at: '입력한 값에서 입력한 숫자 번째의 글자 값입니다. (공백을 포함합니다.)',\n    length_of_string: '입력한 값의 공백을 포함한 글자 수입니다.',\n    substring: '입력한 값에서 입력한 범위 내의 글자 값입니다. (공백을 포함합니다.)',\n    count_match_string:\n        '입력한 값에서 지정한 값의 글자 수이며, 영문의 경우 대문자와 소문자를 구분하여 수를 셉니다.',\n    replace_string:\n        '입력한 값에서 지정한 값을 찾아 추가로 입력한 값으로 모두 바꾼 값입니다. (영문 입력 시 대소문자를 구분합니다.)',\n    index_of_string:\n        '입력한 값에서 지정한 값이 처음으로 등장하는 위치 값입니다. (공백을 포함합니다.)',\n    change_string_case: '입력한 영문의 모든 알파벳을 대문자 또는 소문자로 바꾼 값입니다.',\n    direction_relative_duration:\n        '오브젝트의 이동 방향이 입력한 시간에 걸쳐 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    get_sound_volume: '작품에 설정된 소리의 크기 값입니다.',\n    sound_from_to:\n        '해당 오브젝트가 선택한 소리를 입력한 구간을 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_from_to_and_wait:\n        '해당 오브젝트가 선택한 소리를 입력한 구간을 재생한 후 다음 블록을 실행합니다.',\n    Block_info: '블록 설명',\n    Block_click_msg: '블록을 클릭하면<br>블록에 대한 설명이 나타납니다.',\n    hamster_beep: '버저 소리를 짧게 냅니다.',\n    hamster_change_both_wheels_by:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    hamster_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    hamster_change_output_by:\n        '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    hamster_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    hamster_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    hamster_clear_buzzer: '버저 소리를 끕니다.',\n    hamster_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n    hamster_follow_line_until:\n        '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n    hamster_follow_line_using:\n        '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n    hamster_hand_found:\n        \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    hamster_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n    hamster_move_forward_for_secs: '입력한 시간(초) 동안 앞으로 이동합니다.',\n    hamster_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n    hamster_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    hamster_rest_for: '입력한 박자만큼 쉽니다.',\n    hamster_set_both_wheels_to:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    hamster_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n    hamster_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    hamster_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n    hamster_set_output_to:\n        '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    hamster_set_port_to: '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n    hamster_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    hamster_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    hamster_stop: '양쪽 바퀴를 정지합니다.',\n    hamster_turn_for_secs: '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    hamster_turn_once: '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n    hamster_value:\n        '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n    roboid_hamster_beep: '버저 소리를 짧게 냅니다.',\n    roboid_hamster_change_both_wheels_by:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_hamster_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    roboid_hamster_change_output_by:\n        '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    roboid_hamster_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    roboid_hamster_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_hamster_clear_buzzer: '버저 소리를 끕니다.',\n    roboid_hamster_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n    roboid_hamster_follow_line_until:\n        '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n    roboid_hamster_follow_line_using:\n        '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n    roboid_hamster_hand_found:\n        \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_hamster_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n    roboid_hamster_move_forward_for_secs: '입력한 시간(초) 동안 앞으로 이동합니다.',\n    roboid_hamster_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n    roboid_hamster_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    roboid_hamster_rest_for: '입력한 박자만큼 쉽니다.',\n    roboid_hamster_set_both_wheels_to:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_hamster_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n    roboid_hamster_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    roboid_hamster_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n    roboid_hamster_set_output_to:\n        '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    roboid_hamster_set_port_to: '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n    roboid_hamster_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    roboid_hamster_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_hamster_stop: '양쪽 바퀴를 정지합니다.',\n    roboid_hamster_turn_for_secs:\n        '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    roboid_hamster_turn_once: '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n    roboid_hamster_value:\n        '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n    roboid_turtle_button_state:\n        \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    roboid_turtle_change_head_led_by_rgb: '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n    roboid_turtle_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    roboid_turtle_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_turtle_change_wheels_by_left_right:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_turtle_clear_head_led: '머리 LED를 끕니다.',\n    roboid_turtle_clear_sound: '소리를 끕니다.',\n    roboid_turtle_cross_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n    roboid_turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n    roboid_turtle_follow_line_until:\n        '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n    roboid_turtle_follow_line_until_black:\n        '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n    roboid_turtle_is_color_pattern:\n        \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n    roboid_turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n    roboid_turtle_pivot_around_wheel_unit_in_direction:\n        '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n    roboid_turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n    roboid_turtle_play_note_for_beats: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    roboid_turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n    roboid_turtle_play_sound_times_until_done:\n        '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n    roboid_turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n    roboid_turtle_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n    roboid_turtle_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    roboid_turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n    roboid_turtle_set_head_led_to_rgb: '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n    roboid_turtle_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    roboid_turtle_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_turtle_set_wheels_to_left_right:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_turtle_stop: '양쪽 바퀴를 정지합니다.',\n    roboid_turtle_touching_color:\n        \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_turn_at_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n    roboid_turtle_turn_unit_in_place:\n        '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    roboid_turtle_turn_unit_with_radius_in_direction:\n        '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n    roboid_turtle_value:\n        '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n    turtle_button_state:\n        \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    turtle_change_head_led_by_rgb: '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n    turtle_change_tempo_by: '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    turtle_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    turtle_change_wheels_by_left_right:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    turtle_clear_head_led: '머리 LED를 끕니다.',\n    turtle_clear_sound: '소리를 끕니다.',\n    turtle_cross_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n    turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n    turtle_follow_line_until:\n        '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n    turtle_follow_line_until_black:\n        '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n    turtle_is_color_pattern:\n        \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n    turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n    turtle_pivot_around_wheel_unit_in_direction:\n        '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n    turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n    turtle_play_note_for_beats: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n    turtle_play_sound_times_until_done:\n        '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n    turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n    turtle_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n    turtle_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n    turtle_set_head_led_to_rgb: '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n    turtle_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    turtle_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    turtle_set_wheels_to_left_right:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    turtle_stop: '양쪽 바퀴를 정지합니다.',\n    turtle_touching_color:\n        \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_turn_at_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n    turtle_turn_unit_in_place:\n        '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    turtle_turn_unit_with_radius_in_direction:\n        '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n    turtle_value:\n        '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n    neobot_sensor_value:\n        'IN1 ~ IN3 포트 및 리모컨에서 입력되는 값 그리고 배터리 정보를 0부터 255의 숫자로 표시합니다.',\n    neobot_sensor_convert_scale:\n        '선택한 포트 입력값의 변화를 특정범위의 값으로 표현범위를 조절할 수 있습니다.',\n    neobot_left_motor: 'L모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.',\n    neobot_stop_left_motor: 'L모터 포트에 연결한 모터를 정지합니다.',\n    neobot_right_motor: 'R모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.',\n    neobot_stop_right_motor: 'R모터 포트에 연결한 모터를 정지합니다.',\n    neobot_all_motor:\n        'L모터 및 R모터 포트에 2개 모터를 연결하여 바퀴로 활용할 때 전, 후, 좌, 우 이동 방향 및 속도, 시간을 설정할 수 있습니다.',\n    neobot_stop_all_motor: 'L모터 및 R모터에 연결한 모터를 모두 정지합니다.',\n    neobot_set_servo:\n        'OUT1 ~ OUT3에 서보모터를 연결했을 때 0도 ~ 180도 범위 내에서 각도를 조절할 수 있습니다.',\n    neobot_set_output:\n        'OUT1 ~ OUT3에 라이팅블록 및 전자회로를 연결했을 때 출력 전압을 설정할 수 있습니다.</br>0은 0V, 1 ~ 255는 2.4 ~ 4.96V의 전압을 나타냅니다.',\n    neobot_set_fnd: 'FND로 0~99 까지의 숫자를 표시할 수 있습니다.',\n    neobot_set_fnd_off: 'FND에 표시한 숫자를 끌 수 있습니다.',\n    neobot_play_note_for:\n        '주파수 발진 방법을 이용해 멜로디에 반음 단위의 멜로디 음을 발생시킬 수 있습니다.',\n    rotate_by_angle_dropdown:\n        '오브젝트의 방향을 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    chocopi_control_button:\n        '버튼이 눌리면 참이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_control_event:\n        '버튼을 누르거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_control_joystick:\n        '조이스틱 좌우, 상하, 볼륨의 값은 0~4095까지 입니다.<br/>따라서 2047 근처가 중간이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_dc_motor:\n        'DC모터 모듈에는 직류전동기 두개를 연결 할 수 있습니다.<br/> 직류 전동기는 최대 5V로 동작하게 됩니다.<br/>값은 100이 최대(100%)이고 음수를 넣으면 반대 방향으로 회전합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_led:\n        'LED번호는 LED블록에 연결된 순서이고 1번부터 시작합니다.<br/>RGB값은 0~255사이의 값입니다.<br/>빨강(Red),녹색(Green), 파랑(Blue)순서로  입력합니다.<br/>밝은 LED를 직접보면 눈이 아프니까 값을 0~5정도로 씁니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_event:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br/>빛센서를 물체로 가리거나 치우면 시작되는 엔트리 블록을 연결합니다<br/>모션 모듈에는 포토게이트 2개를 연결할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_status:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>물체가 빛센서를 가리면 참</b>이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_time:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>이 블록은 물체가 빛센서를 가리거나 벗어난 시간을 가집니다.<br/>1/10000초까지 측정할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_value:\n        '모션 모듈에는 3개의 적외선 센서가 있습니다.<br/>0~4095사이의 값을 가질 수 있는데 물체가 빛을 많이 반사할 수록 작은 값을 가집니다. <br/>거리를 대략적으로 측정할 수 있습니다. <br/>가속도와 각가속도 값의 범위는 -32768~32767 까지입니다.<br/>가속도를 이용해서 센서의 기울기를 측정할 수도 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_sensor:\n        '온도 값은 섭씨 온도입니다.<br/>습도 값은 백분율로 나타낸 상대습도 값입니다.<br/>빛은 로그스케일로 0~4095사이입니다.<br/>아날로그 값은 0~4095사이입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_servo_motor:\n        '서보모터 모듈에는 4개의 서보모터를 연결 할 수 있습니다.<br/>서보모터는 5V로 동작하게 됩니다.<br/>각도는 0~200도까지 지정할 수 있습니다.<br/>연속회전식 서보모터를 연결하면 각도에 따라 속도가 변하게됩니다.<br/>90~100 사이가 중간값입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_event:\n        '터치 모듈에는 1~12번의 연결 패드가 있습니다. <br/>만지거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_status:\n        '터치 모듈의 패드를 만지면 참이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_value:\n        '터치패드에 연결된 물체의 전기용량이 커지면 값이 작아집니다.<br/>여러 명이 손잡고 만지면 더 작은 값이 됩니다.<br/>전기용량이란 물체에 전기를 띈 입자를 얼마나 가지고 있을 수 있는 지를 말합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    boolean_and_or:\n        '그리고 : 두 판단이 모두 참인 경우 ‘참’으로 판단합니다.<br>또는 : 두 판단 중 하나라도 참이 있는 경우 ‘참’으로 판단합니다.',\n    check_weather:\n        '<br>선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈',\n    check_finedust:\n        '<br>선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨',\n    get_weather_data:\n        '<br>선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)',\n    get_current_weather_data:\n        '<br>현재 선택한 지역의 날씨 정보값(기온, 미세먼지농도)입니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 정보: (기온(℃)), 미세먼지농도(㎍)',\n    get_today_temperature:\n        '<br>오늘 선택한 지역과 시간대의 기온을 의미합니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 시간대: 00, 03, 06, 09, 12, 15, 18, 21',\n    check_city_weather:\n        '선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.\\n* 옵션\\n날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후\\n시도: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈',\n    check_city_finedust:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.\\n* 옵션\\n시도: 서울, 강원, 경기, 경남, 경북,광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨',\n    get_city_weather_data:\n        '선택한 날짜와 지역의 각종 날씨 정보입니다.\\n *옵션\\n날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후\\n시도:서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)',\n    get_current_city_weather_data:\n        '현재 선택한 지역의 날씨 정보입니다.\\n*옵션\\n시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n정보: 기온(℃), 미세먼지농도(㎍)',\n    get_today_city_temperature:\n        '오늘 선택한 지역과 시간대의 기온입니다.\\n*옵션\\n시도: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n시간대: 00, 03, 06, 09, 12, 15, 18, 21',\n    count_festival:\n        '선택한 날짜와 지역에서 열리는 행사의 수입니다.\\n* 옵션 \\n지역: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n행사일: 1~12월',\n    get_festival_info:\n        '선택한 날짜와 지역에서 열리는 행사에 대한 정보입니다.\\n* 옵션 \\n지역: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n행사일: 1~12월 \\n정보: 제목, 지역, 시작일, 종료일, 주소, 개요, 홈페이지',\n    get_translated_string:\n        '입력한 문자값을 선택한 언어로 번역합니다. 입력은 3000자까지 가능합니다.\\n*번역 가능한 언어 \\n - 한국어 → 영어, 중국어 간체, 중국어 번체, 베트남어, 스페인어, 인도네시아어, 태국어, 프랑스어\\n - 영어 → 일본어, 프랑스어, 한국어\\n - 중국어 간체, 중국어 번체, 베트남어, 스페인어, 인도네시아어, 태국어, 프랑스어 → 한국어\\n - 일본어 →영어 \\n - 프랑스어 → 영어',\n    check_language: '입력된 문자값의 언어를 감지합니다. 입력은 문장 형태로 3000자까지 가능합니다.',\n    count_disaster_behavior:\n        '선택한 자연재해가 발생했을 때 해야할 행동요령의 수입니다.<br> *옵션<br> 자연재해: 태풍, 홍수, 호우, 강풍, 대설, 한파, 풍랑, 황사, 폭염, 가뭄, 지진, 해일, 산사태<br> 상황: 자연재해에 따라 다름 ',\n    get_disaster_behavior:\n        '선택한 자연재해가 발생했을 때 해야하는 행동요령에 대한 정보입니다.<br> *옵션<br> 자연재해: 태풍, 홍수, 호우, 강풍, 대설, 한파, 풍랑, 황사, 폭염, 가뭄, 지진, 해일, 산사태<br> 상황: 자연재해에 따라 다름',\n    count_lifeSafety_behavior:\n        '선택한 생활 속 문제가 발생했을 때 해야할 행동요령의 수입니다.<br> *옵션<br> 생활 속 문제: 응급처치, 심폐소생술, 소화기·소화전 사용법, 식중독, 산행안전, 실종유괴, 성폭력, 학교폭력, 가정 폭력, 억류 및 납치, 교통사고, 승강기 안전사고, 미세먼지<br> 상황: 생활 속 문제에 따라 다름 ',\n    get_lifeSafety_behavior:\n        '선택한 생활 속 문제가 발생했을 때 해야할 행동요령에 대한 정보입니다.<br> *옵션<br> 생활 속 문제: 응급처치, 심폐소생술, 소화기·소화전 사용법, 식중독, 산행안전, 실종유괴, 성폭력, 학교폭력, 가정 폭력, 억류 및 납치, 교통사고, 승강기 안전사고, 미세먼지<br> 상황: 생활 속 문제에 따라 다름 ',\n    read_text:\n        '입력한 문자값을 설정된 목소리로 읽습니다.<br>입력은 2500자까지 가능합니다.<br>인터넷에 연결되어 있지 않거나 인터넷 환경이 불안할 경우, 해당 블록이 실행되지 않고 다음 블록으로 넘어갈 수 있습니다.',\n    set_tts_property: '선택한 목소리가 선택한 속도와 선택한 음높이로 설정됩니다.',\n    read_text_wait_with_block: '입력한 문자값을 읽어준 후 다음 블록을 실행합니다.',\n    check_microphone:\n        \"컴퓨터에 마이크가 연결되어 있는 경우 '참'으로 판단합니다. (IE/Safari 브라우저 지원하지 않음)\",\n    speech_to_text_convert:\n        '마이크에 입력되는 사람의 목소리를 텍스트로 변환합니다. (IE/Safari 브라우저 지원하지 않음)',\n    get_microphone_volume:\n        '마이크에 입력되는 소리의 크기 값입니다. (IE/Safari 브라우저 지원하지 않음)',\n    speech_to_text_get_value:\n        '사람의 목소리를 문자로 바꾼 값입니다. 목소리가 입력되지 않거나, 음성인식 도중 오류가 발생한 경우 무조건 0 값을 갖습니다. (IE/Safari 브라우저 지원하지 않음)',\n    video_draw_webcam:\n        '컴퓨터에 연결된 카메라에 촬영되는 화면을 실행화면에서 보이게하거나 숨깁니다.',\n    video_check_webcam: \"컴퓨터에 카메라가 연결되어 있는 경우 '참'으로 판단합니다.\",\n    video_set_camera_option:\n        '촬영되는 화면의 효과를 입력한 값으로 정합니다.  밝기: -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.) 투명도: 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로 100 이상은 100으로 처리됩니다.)',\n    video_flip_camera: '촬영되는 화면을 좌우 혹은 상하로 뒤집습니다.',\n    video_toggle_model:\n        '선택한 인식모델을 동작시키거나 중지시킵니다. 얼굴 인식: 사람의 얼굴을 인식하여 눈, 코, 입, 귀의 위치나 예상되는 성별, 나이, 감정을 알 수 있습니다. 사람 인식: 사람의 몸을 인식하여 각 신체부위의 위치 등을 알 수 있습니다. 객체 인식: 인식된 객체의 종류를 알 수 있습니다. (사람이나 물건)',\n    video_toggle_ind: '인식 된 사람 / 얼굴 / 사물 을 화면에 표시하거나 숨깁니다',\n    video_number_detect:\n        '인식된 사람 / 얼굴 / 사물의 숫자입니다 촬영되는 화면에 객체로 인식된 객체의 개수입니다. *인식할 수 있는 사물: 사람, 자전거, 자동차, 오토바이, 비행기, 버스, 기차, 트럭, 보트,교통 신호등, 소화전, 정지 신호, 주차 미터, 벤치, 새, 고양이, 개, 말, 양, 암소, 코끼리, 곰, 얼룩말, 기린, 책가방, 우산, 핸드백, 넥타이, 가방, 프리스비, 스키, 스노보드, 스포츠 볼, 연, 야구 방망이, 야구 글러브, 스케이트 보드, 서핑 보드, 테니스 라켓, 병, 와인 글라스, 컵, 포크, 나이프, 숟가락, 그릇, 바나나, 애플, 샌드위치, 주황색, 브로콜리, 당근, 핫도그, 피자, 도넛, 케이크, 의자, 소파, 화분, 침대, 식사테이블, 화장실, TV 모니터, 노트북, 마우스, 원격, 키보드, 휴대 전화, 전자 레인지, 오븐, 토스터기, 싱크대, 냉장고, 도서, 시계, 꽃병, 가위, 테디베어, 헤어드라이어, 칫솔',\n    video_detected_face_info:\n        '입력한 순서의 얼굴의 선택한 정보의 추정값입니다. 인식이 잘 되지 않는 경우 무조건 0으로 출력됩니다. (성별, 나이, 감정)',\n    video_motion_value:\n        '선택한 오브젝트 혹은 실행화면 위에서 감지되는 움직임 혹은 방향 값입니다. 움직임: 움직임이 크고 빠를 수록 값이 커집니다. 방향: 오른쪽 혹은 위쪽으로 움직일 때 양수, 왼쪽 혹은 아래쪽으로 움직일 때 음수가 됩니다.',\n    video_face_part_coord:\n        '입력한 순서의 얼굴 중 선택된 얼굴 부위의 위치값입니다. 인식이 잘 되지 않는 경우 무조건 0으로 출력됩니다. (왼쪽 눈, 오른쪽 눈, 코, 왼쪽 입꼬리, 오른쪽 입꼬리, 윗 입술, 아랫입술)',\n    video_body_part_coord:\n        '입력한 순서의 사람의 선택한 신체 부위의 위치값입니다. (얼굴, 왼쪽 어깨, 왼쪽 팔꿈치, 왼쪽 손목, 왼쪽 엉덩이, 왼쪽 무릎, 왼쪽 발목, 오른쪽 어깨, 오른쪽 팔꿈치, 오른쪽 손목, 오른쪽 엉덩이, 오른쪽 무릎, 오른쪽 발목)',\n    append_row_to_table:\n        '선택한 테이블의 마지막에 행(열)을 추가합니다. 추가된 행(열)의 모든 열(행) 값은 0입니다.',\n    insert_row_to_table:\n        '선택한 테이블의 입력한 순서에 행(열)을 추가합니다. 추가된 행(열)의 모든 열(행) 값은 0입니다. (입력한 행(열) 뒤에 있는 행들은 순서가 하나씩 밀려납니다.',\n    delete_row_from_table: '선택한 테이블의 입력한 순서에 있는 행(열)을 삭제합니다.',\n    set_value_from_table: '선택한 테이블에서 입력한 순서의 선택된 열값을 입력한 값으로 바꿉니다.',\n    get_table_count: '선택한 테이블이 보유한 행과 열의 개수입니다.',\n    get_value_from_table: '선택한 테이블에서 입력한 순서의 선택된 열 값 입니다.',\n    calc_values_from_table:\n        '선택한 테이블에서 선택한 열들에 대한 계산값입니다. (합, 최댓값, 최솟값, 평균값, 표준편차)',\n    open_table_chart: '선택한 테이블의 차트창을 엽니다.',\n    close_table_chart: '열려있는 테이블 차트창을 닫습니다.',\n    get_coefficient:\n        '선택한 테이블에서 두 속성 사이의 상관계수입니다. 상관계수가 1(-1)에 가까울 수록 강한 양(음)의 선형 상관관계를 갖습니다.',\n};\nLang.Category = {\n    entrybot_friends: '엔트리봇 친구들',\n    people: '사람',\n    animal: '동물',\n    animal_flying: '하늘',\n    animal_land: '땅',\n    animal_water: '물',\n    animal_others: '기타',\n    plant: '식물',\n    plant_flower: '꽃',\n    plant_grass: '풀',\n    plant_tree: '나무',\n    plant_others: '기타',\n    vehicles: '탈것',\n    vehicles_flying: '하늘',\n    vehicles_land: '땅',\n    vehicles_water: '물',\n    vehicles_others: '기타',\n    architect: '건물',\n    architect_building: '건축물',\n    architect_monument: '기념물',\n    architect_others: '기타',\n    food: '음식',\n    food_vegetables: '과일/채소',\n    food_meat: '고기',\n    food_drink: '음료',\n    food_others: '기타',\n    environment: '환경',\n    environment_nature: '자연',\n    environment_space: '우주',\n    environment_others: '기타',\n    stuff: '물건',\n    stuff_living: '생활',\n    stuff_hobby: '취미',\n    stuff_others: '기타',\n    fantasy: '판타지',\n    interface: '인터페이스',\n    interface_website: '웹사이트',\n    interface_game: '게임',\n    interface_others: '기타',\n    background: '배경',\n    background_outdoor: '실외',\n    background_indoor: '실내',\n    background_nature: '자연',\n    background_others: '기타',\n};\nLang.Device = {\n    arduino: '아두이노',\n    hamster: '햄스터',\n    roboid: '로보이드',\n    turtle: '거북이',\n    albert: '알버트',\n    robotis_carCont: '로보티즈 자동차 로봇',\n    robotis_openCM70: '로보티즈 IoT',\n    sensorBoard: '엔트리 센서보드',\n    trueRobot: '뚜루뚜루',\n    CODEino: '코드이노',\n    bitbrick: '비트브릭',\n    creamo: '크리모',\n    playcode: '플레이코드',\n    funboard: '펀보드',\n    bitBlock: '비트블록',\n    xbot_epor_edge: '엑스봇',\n    dplay: '디플레이',\n    iboard: '아이보드',\n    nemoino: '네모이노',\n    ev3: 'EV3',\n    robotori: '로보토리',\n    smartBoard: '스마트보드',\n    chocopi: '초코파이보드',\n    rokoboard: '로코보드',\n    altino: '알티노',\n    mechatro: '메카트로',\n};\nLang.General = {\n    turn_on: '켜기',\n    turn_off: '끄기',\n    left: '왼쪽',\n    right: '오른쪽',\n    param_string: '문자값',\n    both: '양쪽',\n    transparent: '투명',\n    black: '검은색',\n    brown: '갈색',\n    red: '빨간색',\n    yellow: '노란색',\n    green: '초록색',\n    skyblue: '하늘색',\n    blue: '파란색',\n    purple: '보라색',\n    white: '하얀색',\n    note_c: '도',\n    note_d: '레',\n    note_e: '미',\n    note_f: '파',\n    note_g: '솔',\n    note_a: '라',\n    note_b: '시',\n    questions: '문제',\n    clock: '시계',\n    counter_clock: '반시계',\n    font_size: '글자 크기',\n    second: '초',\n    alert_title: '알림',\n    confirm_title: '확인',\n    update_title: '업데이트 알림',\n    recent_download: '최신 버전 다운로드',\n    recent_download2: '최신버전 다운로드',\n    latest_version: '최신 버전입니다.',\n    dont_show_again: '다시보지 않기',\n};\nLang.Fonts = {\n    jeju_hallasan: '한라산체',\n    gothic_coding: '코딩고딕체',\n    batang: '바탕체',\n    gothic: '나눔고딕체',\n    myeongjo: '나눔명조',\n    pen_script: '나눔손글씨',\n    square_round: '나눔스퀘어라운드체',\n    jalnan: '잘난체',\n    designhouse: '디자인하우스체',\n    malssami815: '말싸미815체',\n    dunggeunmo: '둥근모꼴체',\n    hs_bombaram: 'HS봄바람체',\n    yisunshin: '이순신체',\n    goyang: '고양체',\n    flower_road: '꽃길체',\n    uhbeemysen: '어비마이센체',\n    sd_comic_stencil: '산돌 코믹스탠실',\n    sd_childfundkorea: '산돌 초록우산 어린이',\n    sd_cinema_theater: '산돌 씨네마극장',\n    sd_mapssi: '산돌 맵씨',\n    sd_shabang: '산돌 별이샤방샤방',\n    sd_woodcarving: '산돌 목각',\n    sd_yongbi: '산돌 용비어천가',\n};\nLang.Hw = {\n    note: '음표',\n    leftWheel: '왼쪽 바퀴',\n    rightWheel: '오른쪽 바퀴',\n    leftEye: '왼쪽 눈',\n    rightEye: '오른쪽 눈',\n    led: '불빛',\n    led_en: 'LED',\n    body: '몸통',\n    front: '앞쪽',\n    port_en: '',\n    port_ko: '번 포트',\n    sensor: '센서',\n    light: '빛',\n    temp: '온도',\n    switch_: '스위치',\n    right_ko: '오른쪽',\n    right_en: '',\n    left_ko: '왼쪽',\n    left_en: '',\n    up_ko: '위쪽',\n    up_en: '',\n    down_ko: '아래쪽',\n    down_en: '',\n    output: '출력',\n    left: '왼쪽',\n    right: '오른쪽',\n    sub: '서보',\n    motor: '모터',\n    '': '',\n    buzzer: '버저',\n    IR: '적외선',\n    acceleration: '가속',\n    analog: '아날로그',\n    angular_acceleration: '각가속',\n    button: '버튼',\n    humidity: '습도',\n    joystick: '조이스틱',\n    port: '포트',\n    potentiometer: '포텐시오미터',\n    servo: '서보',\n};\nLang.template = {\n    albert_hand_found: '손 찾음?',\n    albert_is_oid_value: ' %1 OID 값이 %2 인가? ',\n    albert_value: '%1',\n    albert_move_forward_for_secs: '앞으로 %1 초 이동하기 %2',\n    albert_move_backward_for_secs: '뒤로 %1 초 이동하기 %2',\n    albert_turn_for_secs: '%1 으로 %2 초 돌기 %3',\n    albert_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n    albert_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n    albert_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n    albert_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n    albert_stop: '정지하기 %1',\n    albert_set_pad_size_to: '말판 크기를 폭 %1 높이 %2 (으)로 정하기 %3',\n    albert_move_to_x_y_on_board: '밑판 x: %1 y: %2 위치로 이동하기 %3',\n    albert_set_orientation_on_board: '말판 %1도 방향으로 바라보기 %2',\n    albert_set_eye_to: '%1 눈을 %2 으로 정하기 %3',\n    albert_clear_eye: '%1 눈 끄기 %2',\n    albert_body_led: '몸통 LED %1 %2',\n    albert_front_led: '앞쪽 LED %1 %2',\n    albert_beep: '삐 소리내기 %1',\n    albert_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n    albert_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n    albert_clear_buzzer: '버저 끄기 %1',\n    albert_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n    albert_rest_for: '%1 박자 쉬기 %2',\n    albert_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n    albert_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n    albert_move_forward: '앞으로 이동하기 %1',\n    albert_move_backward: '뒤로 이동하기 %1',\n    albert_turn_around: '%1 으로 돌기 %2',\n    albert_set_led_to: '%1 %2 으로 정하기 %3',\n    albert_clear_led: '%1 %2',\n    albert_change_wheels_by: '%1 %2 %3',\n    albert_set_wheels_to: '%1 %2 %3',\n    arduino_text: '%1',\n    arduino_get_sensor_number: '%1  ',\n    arduino_get_port_number: '%1  ',\n    arduino_get_digital_toggle: '%1  ',\n    arduino_get_pwm_port_number: '%1  ',\n    arduino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    arduino_ext_get_analog_value: '아날로그 %1 번 센서값',\n    arduino_ext_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    arduino_ext_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n    arduino_ext_toggle_led: '디지털 %1 번 핀 %2 %3',\n    arduino_ext_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    arduino_ext_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    arduino_ext_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    arduino_ext_get_digital: '디지털 %1 번 센서값',\n    blacksmith_get_analog_value: '아날로그 %1 번 핀 센서 값',\n    blacksmith_get_analog_mapping:\n        '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n    blacksmith_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\n    blacksmith_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n    blacksmith_get_digital_toggle: '디지털 %1 번 핀 센서 값',\n    blacksmith_set_digital_toggle: '디지털 %1 번 핀 %2 %3',\n    blacksmith_set_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    blacksmith_set_digital_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    blacksmith_set_digital_buzzer: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    blacksmith_set_digital_lcd: 'LCD화면 %1 줄에 %2 나타내기 %3',\n    blacksmith_set_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n    dplay_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    nemoino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    sensorBoard_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    truetrue_get_accsensor: '가속도센서 %1 의 값',\n    truetrue_get_bottomcolorsensor: '바닥컬러센서 %1 의 값',\n    truetrue_get_frontcolorsensor: '전면컬러센서 %1 의 값',\n    truetrue_get_linesensor: '라인센서 %1 의 값',\n    truetrue_get_proxisensor: '근접센서 %1 의 값',\n    truetrue_set_colorled: '컬러LED Red %1  Green %2 Blue %3 로 설정 %4',\n    truetrue_set_dualmotor: 'DC모터 좌 %1  우 %2 속도로 %3 초 구동 %4',\n    truetrue_set_led_colorsensor: '%1 조명용 LED %2 %3',\n    truetrue_set_led_linesensor: '라인센서 조명용 LED %1 %2',\n    truetrue_set_led_proxi: '%1 조명용 LED %2 %3',\n    truetrue_set_linetracer: '라인트레이싱 모드 %1 %2',\n    truetrue_set_singlemotor: 'DC모터 %1  속도 %2 로 설정 %3',\n    CODEino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    ardublock_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    arduino_get_digital_value: '디지털 %1 번 센서값  ',\n    dplay_get_digital_value: '디지털 %1 번 센서값  ',\n    nemoino_get_digital_value: '디지털 %1 번 센서값  ',\n    sensorBoard_get_digital_value: '디지털 %1 번 센서값  ',\n    CODEino_get_digital_value: '디지털 %1 핀의 값  ',\n    CODEino_set_digital_value: '디지털 %1 핀의 %2 %3',\n    CODEino_set_pwm_value: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    ardublock_get_digital_value: '디지털 %1 번 센서값  ',\n    arduino_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dplay_toggle_led: '디지털 %1 번 핀 %2 %3',\n    nemoino_toggle_led: '디지털 %1 번 핀 %2 %3',\n    sensorBoard_toggle_led: '디지털 %1 번 핀 %2 %3',\n    CODEino_toggle_led: '디지털 %1 번 핀 %2 %3',\n    arduino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dplay_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    nemoino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    sensorBoard_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    CODEino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    ardublock_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    arduino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    dplay_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    nemoino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    sensorBoard_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    CODEino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    CODEino_set_rgb_value: '컬러 LED의 %1 색상을 %2 (으)로 정하기 %3',\n    CODEino_set_rgb_add_value: '컬러 LED의 %1 색상에 %2 만큼 더하기 %3',\n    CODEino_set_rgb_off: '컬러 LED 끄기 %1',\n    CODEino_set__led_by_rgb: '컬러 LED 색상을 빨강 %1 초록 %2 파랑 %3 (으)로 정하기 %4',\n    CODEino_rgb_set_color: '컬러 LED의 색상을 %1 (으)로 정하기 %2',\n    CODEino_led_by_value: '컬러 LED 켜기 %1',\n    ardublock_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    joystick_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    joystick_get_digital_value: '디지털 %1 번 센서값  ',\n    joystick_toggle_led: '디지털 %1 번 핀 %2 %3',\n    joystick_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    joystick_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    sensorBoard_get_named_sensor_value: '%1  센서값',\n    sensorBoard_is_button_pressed: '%1  버튼을 눌렀는가?',\n    sensorBoard_led: '%1  LED %2   %3',\n    arduino_download_connector: '%1',\n    download_guide: '%1',\n    arduino_download_source: '%1',\n    arduino_connected: '%1',\n    arduino_connect: '%1',\n    arduino_reconnect: '%1',\n    CODEino_get_sensor_number: '%1  ',\n    CODEino_get_named_sensor_value: '  %1  센서값 ',\n    CODEino_get_sound_status: '소리센서  %1  ',\n    CODEino_get_light_status: '빛센서  %1  ',\n    CODEino_is_button_pressed: ' 보드의  %1  ',\n    CODEino_get_accelerometer_direction: ' 3축 가속도센서  %1  ',\n    CODEino_get_accelerometer_value: ' 3축 가속도센서  %1 축의 센서값 ',\n    CODEino_get_analog_value: '아날로그 %1 센서의 값',\n    iboard_button: '%1  버튼을 눌렀는가?',\n    iboard_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    iboard_get_analog_value: '아날로그 %1 번 센서값  ',\n    iboard_get_analog_value_map: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    iboard_get_digital: '디지털 %1 번 센서값  ',\n    iboard_led: 'LED %1 번을 %2 %3',\n    iboard_motor: '모터를 %2 으로 동작하기 %3',\n    iboard_pwm_led: 'LED %1 번의 밝기를 %2 (으)로 정하기 %3',\n    iboard_rgb_led: 'RGB LED의 %1 LED %2 %3',\n    iboard_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    iboard_toggle_led: '디지털 %1 번 핀 %2 %3',\n    bitbrick_when_button_pressed: '%1 버튼 %2 눌러졌을 때',\n    bitbrick_when_sensor_get_value: '%1 %2 값 %3 %4 일 때',\n    bitbrick_is_touch_pressed: '버튼 %1 이(가) %2 인가?',\n    bitbrick_is_sensor_value_compare: '%1 값 %2 %3 인가?',\n    bitbrick_sensor_value: '%1 값',\n    bitbrick_convert_scale: '변환 %1 값 %2 ~ %3 에서 %4 ~ %5',\n    bitbrick_turn_on_color_led_by_rgb: '엘이디를 빨강 %1 초록 %2 파랑 %3 %4 (으)로 켜기',\n    bitbrick_turn_on_color_led_by_picker: '엘이디를 %1 (으)로 켜기 %2',\n    bitbrick_turn_on_color_led_by_value: '엘이디를 %1 (으)로 켜기 %2',\n    bitbrick_turn_off_color_led: '엘이디 끄기 %1',\n    bitbrick_buzzer: '버저음 %1 내기 %2',\n    bitbrick_servomotor_angle: '서보모터 %1 각도 %2 %3',\n    bitbrick_dc_direction_speed: '디씨모터 %1 방향 %2 속력 %3 %4',\n    bitbrick_dc_speed: '디씨모터 %1 속도 %2 %3',\n    bitbrick_turn_off_all_motors: '모든 모터 멈추기 %1',\n    start_drawing: '그리기 시작하기 %1',\n    stop_drawing: '그리기 멈추기 %1',\n    set_color: '붓의 색을 %1 (으)로 정하기 %2',\n    set_random_color: '붓의 색을 무작위로 정하기 %1',\n    change_thickness: '붓의 굵기를 %1 만큼 바꾸기 %2',\n    set_thickness: '붓의 굵기를 %1 (으)로 정하기 %2',\n    change_opacity: '붓의 불투명도를 %1 % 만큼 바꾸기 %2',\n    set_opacity: '붓의 불투명도를 %1 % 로 정하기 %2',\n    brush_erase_all: '모든 붓 지우기 %1',\n    brush_stamp: '도장 찍기 %1',\n    change_brush_transparency: '붓의 투명도를 %1 % 만큼 바꾸기 %2',\n    set_brush_tranparency: '붓의 투명도를 %1 % 로 정하기 %2',\n    number: '%1',\n    angle: '%1',\n    get_x_coordinate: '%1',\n    get_y_coordinate: '%1',\n    get_angle: '%1',\n    get_rotation_direction: '%1  ',\n    distance_something: '%1 %2 %3',\n    coordinate_mouse: '%1 %2 %3',\n    coordinate_object: '%1 %2 %3 %4',\n    calc_basic: '%1 %2 %3',\n    calc_plus: '%1 %2 %3',\n    calc_minus: '%1 %2 %3',\n    calc_times: '%1 %2 %3',\n    calc_divide: '%1 %2 %3',\n    calc_mod: '%1 %2 %3 %4',\n    calc_share: '%1 %2 %3 %4',\n    calc_operation: '%1 %2 %3 %4',\n    calc_rand: '%1 %2 %3 %4 %5',\n    get_date: '%1 %2 %3',\n    get_sound_duration: '%1 %2 %3',\n    get_user_name: '사용자이름',\n    reset_project_timer: '%1',\n    set_visible_project_timer: '%1 %2 %3 %4',\n    timer_variable: '%1 %2',\n    get_project_timer_value: '%1 %2',\n    char_at: '%1 %2 %3 %4 %5',\n    length_of_string: '%1 %2 %3',\n    reverse_of_string: '%1 %2 %3',\n    substring: '%1 %2 %3 %4 %5 %6 %7',\n    replace_string: '%1 %2 %3 %4 %5 %6 %7',\n    change_string_case: '%1 %2 %3 %4 %5',\n    index_of_string: '%1 %2 %3 %4 %5',\n    count_match_string: '%1 %2 %3 %4',\n    combine_something: '%1 %2 %3 %4 %5',\n    get_sound_volume: '%1 %2',\n    quotient_and_mod: '%1 %2 %3 %4 %5 %6',\n    choose_project_timer_action: '%1 %2 %3 %4',\n    wait_second: '%1 초 기다리기 %2',\n    repeat_basic: '%1 번 반복하기 %2',\n    hidden_loop: '%1 번 반복하기 %2',\n    repeat_inf: '계속 반복하기 %1',\n    stop_repeat: '반복 중단하기 %1',\n    wait_until_true: '%1 이(가) 될 때까지 기다리기 %2',\n    _if: '만일 %1 (이)라면 %2',\n    if_else: '만일 %1 (이)라면 %2 %3 아니면',\n    create_clone: '%1 의 복제본 만들기 %2',\n    delete_clone: '이 복제본 삭제하기 %1',\n    when_clone_start: '%1 복제본이 처음 생성되었을때',\n    stop_run: '프로그램 끝내기 %1',\n    repeat_while_true: '%1 %2  반복하기 %3',\n    stop_object: '%1 코드 멈추기 %2',\n    restart_project: '처음부터 다시 실행하기 %1',\n    remove_all_clones: '모든 복제본 삭제하기 %1',\n    functionAddButton: '%1',\n    function_field_label: '%1%2',\n    function_field_string: '%1%2',\n    function_field_boolean: '%1%2',\n    function_param_string: '문자/숫자값',\n    function_param_boolean: '판단값',\n    function_create: '함수 정의하기 %1 %2',\n    function_general: '함수 %1',\n    expansionBlockAddButton: '%1',\n    aiUtilizeBlockAddButton: '%1',\n    aiUtilizeModelTrainButton: '%1',\n    weather_title: '%1',\n    check_weather: '%1 %2 의 날씨가 %3인가?',\n    check_finedust: '현재 %1 의 미세먼지 등급이 %2인가?',\n    get_weather_data: '%1 %2 의 %3',\n    get_current_weather_data: '현재 %1 의 %2',\n    get_today_temperature: '오늘 %1의 %2시 기온',\n    check_city_weather: '%1 %2 %3의 날씨가 %4인가?',\n    check_city_finedust: '현재 %1 %2 의 미세먼지 등급이 %3인가?',\n    get_city_weather_data: '%1 %2 %3 의 %4',\n    get_current_city_weather_data: '현재 %1 %2 의 %3',\n    get_today_city_temperature: '오늘 %1 %2의 %3시 기온',\n    translate_title: '%1',\n    get_translated_string: '%1 %2 을(를) %3로 번역한 값',\n    check_language: '%1의 언어',\n    festival_title: '%1',\n    count_festival: '%1 %2 행사의 수',\n    get_festival_info: '%1 %2 행사 %3 번째 항목의 %4',\n    behaviorConductDisaster_title: '%1',\n    count_disaster_behavior: '%1 %2 해야할 행동요령 수',\n    get_disaster_behavior: '자연재난%1 %2 해야할 행동요령 %3 번째 항목',\n    behaviorConductLifeSafety_title: '%1',\n    count_lifeSafety_behavior: '%1 에서 %2 방법의 수',\n    get_lifeSafety_behavior: '%1 에서 %2 방법 %3 번째 항목',\n    tts_title: '%1',\n    audio_title: '%1',\n    video_title: '%1',\n    read_text: '%1 읽어주기 %2',\n    set_tts_property: '%1 목소리를 %2 속도 %3 음높이로 설정하기 %4',\n    read_text_wait_with_block: '%1 읽어주고 기다리기 %2',\n    load_expansion_block: '확장 블록 불러오기',\n    load_ai_utilize_block: 'AI 블록 불러오기',\n    load_ai_utilize_train_block: '모델 학습',\n    expansion_block_descriptions: '확장 블록은 인터넷이 연결되어 있어야 정상적으로 동작합니다.',\n    aiUtilize_block_descriptions: 'AI 활용블록은 인터넷이 연결되어 있어야 정상적으로 동작합니다.',\n    weather_title_text: '날씨',\n    translate_title_text: '번역',\n    festival_title_text: '행사',\n    audio_title_text: '오디오 감지',\n    check_microphone: '마이크가 연결되었는가?',\n    get_microphone_volume: '마이크 소리크기',\n    speech_to_text_convert: '음성 인식하기 %1',\n    speech_to_text_get_value: '음성을 문자로 바꾼 값',\n    video_title_text: '비디오 감지',\n    video_draw_webcam: '비디오 화면 %1 %2',\n    video_check_webcam: '비디오가 연결되었는가?',\n    video_set_camera_opacity_option: '비디오 투명도 효과를 %1 으로 정하기 %2',\n    video_flip_camera: '비디오 화면 %1 뒤집기 %2',\n    video_toggle_model: '%1 인식 %2 %3',\n    video_toggle_ind: '인식된 %1 %2 %3',\n    video_number_detect: '인식된 %1 의 수',\n    video_detected_face_info: '%1 번째 얼굴의 %2',\n    video_motion_value: '%1 에서 감지한 %2 값',\n    video_face_part_coord: '%1 번째 얼굴의 %2 의 %3 좌표',\n    video_body_part_coord: '%1 번째 사람의 %2 의 %3 좌표',\n    behaviorConductDisaster_title_text: '자연재난 국민행동요령',\n    behaviorConductLifeSafety_title_text: '생활안전 국민행동요령',\n    tts_title_text: '읽어주기',\n    hamster_hand_found: '손 찾음?',\n    hamster_value: '%1',\n    hamster_move_forward_once: '말판 앞으로 한 칸 이동하기 %1',\n    hamster_turn_once: '말판 %1 으로 한 번 돌기 %2',\n    hamster_move_forward_for_secs: '앞으로 %1 초 이동하기 %2',\n    hamster_move_backward_for_secs: '뒤로 %1 초 이동하기 %2',\n    hamster_turn_for_secs: '%1 으로 %2 초 돌기 %3',\n    hamster_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n    hamster_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n    hamster_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n    hamster_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n    hamster_follow_line_using: '%1 선을 %2 바닥 센서로 따라가기 %3',\n    hamster_follow_line_until: '%1 선을 따라 %2 교차로까지 이동하기 %3',\n    hamster_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n    hamster_stop: '정지하기 %1',\n    hamster_set_led_to: '%1 LED를 %2 으로 정하기 %3',\n    hamster_clear_led: '%1 LED 끄기 %2',\n    hamster_beep: '삐 소리내기 %1',\n    hamster_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n    hamster_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n    hamster_clear_buzzer: '버저 끄기 %1',\n    hamster_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n    hamster_rest_for: '%1 박자 쉬기 %2',\n    hamster_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n    hamster_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n    hamster_set_port_to: '포트 %1 를 %2 으로 정하기 %3',\n    hamster_change_output_by: '출력 %1 를 %2 만큼 바꾸기 %3',\n    hamster_set_output_to: '출력 %1 를 %2 (으)로 정하기 %3',\n    roboid_hamster_beep: '햄스터 %1: 삐 소리내기 %2',\n    roboid_hamster_change_both_wheels_by: '햄스터 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n    roboid_hamster_change_buzzer_by: '햄스터 %1: 버저 음을 %2 만큼 바꾸기 %3',\n    roboid_hamster_change_output_by: '햄스터 %1: 출력 %2 를 %3 만큼 바꾸기 %4',\n    roboid_hamster_change_tempo_by: '햄스터 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n    roboid_hamster_change_wheel_by: '햄스터 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n    roboid_hamster_clear_buzzer: '햄스터 %1: 버저 끄기 %2',\n    roboid_hamster_clear_led: '햄스터 %1: %2 LED 끄기 %3',\n    roboid_hamster_follow_line_until: '햄스터 %1: %2 선을 따라 %3 교차로까지 이동하기 %4',\n    roboid_hamster_follow_line_using: '햄스터 %1: %2 선을 %3 바닥 센서로 따라가기 %4',\n    roboid_hamster_hand_found: '햄스터 %1: 손 찾음?',\n    roboid_hamster_move_backward_for_secs: '햄스터 %1: 뒤로 %2 초 이동하기 %3',\n    roboid_hamster_move_forward_for_secs: '햄스터 %1: 앞으로 %2 초 이동하기 %3',\n    roboid_hamster_move_forward_once: '햄스터 %1: 말판 앞으로 한 칸 이동하기 %2',\n    roboid_hamster_play_note_for: '햄스터 %1: %2 %3 음을 %4 박자 연주하기 %5',\n    roboid_hamster_rest_for: '햄스터 %1: %2 박자 쉬기 %3',\n    roboid_hamster_set_both_wheels_to: '햄스터 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n    roboid_hamster_set_buzzer_to: '햄스터 %1: 버저 음을 %2 (으)로 정하기 %3',\n    roboid_hamster_set_following_speed_to: '햄스터 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n    roboid_hamster_set_led_to: '햄스터 %1: %2 LED를 %3 으로 정하기 %4',\n    roboid_hamster_set_output_to: '햄스터 %1: 출력 %2 를 %3 (으)로 정하기 %4',\n    roboid_hamster_set_port_to: '햄스터 %1: 포트 %2 를 %3 으로 정하기 %4',\n    roboid_hamster_set_tempo_to: '햄스터 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n    roboid_hamster_set_wheel_to: '햄스터 %1: %2 바퀴 %3 (으)로 정하기 %4',\n    roboid_hamster_stop: '햄스터 %1: 정지하기 %2',\n    roboid_hamster_turn_for_secs: '햄스터 %1: %2 으로 %3 초 돌기 %4',\n    roboid_hamster_turn_once: '햄스터 %1: 말판 %2 으로 한 번 돌기 %3',\n    roboid_hamster_value: '햄스터 %1: %2',\n    roboid_turtle_button_state: '거북이 %1: 버튼을 %2 ?',\n    roboid_turtle_change_buzzer_by: '거북이 %1: 버저 음을 %2 만큼 바꾸기 %3',\n    roboid_turtle_change_head_led_by_rgb: '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n    roboid_turtle_change_tempo_by: '거북이 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n    roboid_turtle_change_wheel_by: '거북이 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n    roboid_turtle_change_wheels_by_left_right:\n        '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n    roboid_turtle_clear_head_led: '거북이 %1: 머리 LED 끄기 %2',\n    roboid_turtle_clear_sound: '거북이 %1: 소리 끄기 %2',\n    roboid_turtle_cross_intersection: '거북이 %1: 검은색 교차로 건너가기 %2',\n    roboid_turtle_follow_line: '거북이 %1: %2 선을 따라가기 %3',\n    roboid_turtle_follow_line_until: '거북이 %1: 검은색 선을 따라 %2 까지 이동하기 %3',\n    roboid_turtle_follow_line_until_black: '거북이 %1: %2 선을 따라 검은색까지 이동하기 %3',\n    roboid_turtle_is_color_pattern: '거북이 %1: 색깔 패턴이 %2 %3 인가?',\n    roboid_turtle_move_backward_unit: '거북이 %1: 뒤로 %2 %3 이동하기 %4',\n    roboid_turtle_move_forward_unit: '거북이 %1: 앞으로 %2 %3 이동하기 %4',\n    roboid_turtle_pivot_around_wheel_unit_in_direction:\n        '거북이 %1: %2 바퀴 중심으로 %3 %4 %5 방향으로 돌기 %6',\n    roboid_turtle_play_note: '거북이 %1: %2 %3 음을 연주하기 %4',\n    roboid_turtle_play_note_for_beats: '거북이 %1: %2 %3 음을 %4 박자 연주하기 %5',\n    roboid_turtle_play_sound_times: '거북이 %1: %2 소리 %3 번 재생하기 %4',\n    roboid_turtle_play_sound_times_until_done: '거북이 %1: %2 소리 %3 번 재생하고 기다리기 %4',\n    roboid_turtle_rest_for_beats: '거북이 %1: %2 박자 쉬기 %3',\n    roboid_turtle_set_buzzer_to: '거북이 %1: 버저 음을 %2 (으)로 정하기 %3',\n    roboid_turtle_set_following_speed_to: '거북이 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n    roboid_turtle_set_head_led_to: '거북이 %1: 머리 LED를 %2 으로 정하기 %3',\n    roboid_turtle_set_head_led_to_rgb: '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n    roboid_turtle_set_tempo_to: '거북이 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n    roboid_turtle_set_wheel_to: '거북이 %1: %2 바퀴 %3 (으)로 정하기 %4',\n    roboid_turtle_set_wheels_to_left_right:\n        '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n    roboid_turtle_stop: '거북이 %1: 정지하기 %2',\n    roboid_turtle_touching_color: '거북이 %1: %2 에 닿았는가?',\n    roboid_turtle_turn_at_intersection: '거북이 %1: 검은색 교차로에서 %2 으로 돌기 %3',\n    roboid_turtle_turn_unit_in_place: '거북이 %1: %2 으로 %3 %4 제자리 돌기 %5',\n    roboid_turtle_turn_unit_with_radius_in_direction:\n        '거북이 %1: %2 으로 %3 %4 반지름 %5 cm를 %6 방향으로 돌기 %7',\n    roboid_turtle_value: '거북이 %1: %2',\n    turtle_button_state: '버튼을 %1 ?',\n    turtle_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n    turtle_change_head_led_by_rgb: '머리 LED를 R: %1 G: %2 B: %3 만큼 바꾸기 %4',\n    turtle_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n    turtle_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n    turtle_change_wheels_by_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n    turtle_clear_head_led: '머리 LED 끄기 %1',\n    turtle_clear_sound: '소리 끄기 %1',\n    turtle_cross_intersection: '검은색 교차로 건너가기 %1',\n    turtle_follow_line: '%1 선을 따라가기 %2',\n    turtle_follow_line_until: '검은색 선을 따라 %1 까지 이동하기 %2',\n    turtle_follow_line_until_black: '%1 선을 따라 검은색까지 이동하기 %2',\n    turtle_is_color_pattern: '색깔 패턴이 %1 %2 인가?',\n    turtle_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n    turtle_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n    turtle_pivot_around_wheel_unit_in_direction: '%1 바퀴 중심으로 %2 %3 %4 방향으로 돌기 %5',\n    turtle_play_note: '%1 %2 음을 연주하기 %3',\n    turtle_play_note_for_beats: '%1 %2 음을 %3 박자 연주하기 %4',\n    turtle_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n    turtle_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n    turtle_rest_for_beats: '%1 박자 쉬기 %2',\n    turtle_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n    turtle_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n    turtle_set_head_led_to: '머리 LED를 %1 으로 정하기 %2',\n    turtle_set_head_led_to_rgb: '머리 LED를 R: %1 G: %2 B: %3 (으)로 정하기 %4',\n    turtle_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n    turtle_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n    turtle_set_wheels_to_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n    turtle_stop: '정지하기 %1',\n    turtle_touching_color: '%1 에 닿았는가?',\n    turtle_turn_at_intersection: '검은색 교차로에서 %1 으로 돌기 %2',\n    turtle_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n    turtle_turn_unit_with_radius_in_direction: '%1 으로 %2 %3 반지름 %4 cm를 %5 방향으로 돌기 %6',\n    turtle_value: '%1',\n    is_clicked: '%1',\n    is_object_clicked: '%1',\n    is_press_some_key: '%1 %2',\n    reach_something: '%1 %2 %3',\n    is_type: '%1 %2 %3 %4',\n    boolean_comparison: '%1 %2 %3',\n    boolean_equal: '%1 %2 %3',\n    boolean_bigger: '%1 %2 %3',\n    boolean_smaller: '%1 %2 %3',\n    boolean_and_or: '%1 %2 %3',\n    boolean_and: '%1 %2 %3',\n    boolean_or: '%1 %2 %3',\n    boolean_not: '%1 %2 %3',\n    true_or_false: '%1',\n    True: '%1  ',\n    False: '%1  ',\n    boolean_basic_operator: '%1 %2 %3',\n    show: '모양 보이기 %1',\n    hide: '모양 숨기기 %1',\n    dialog_time: '%1 을(를) %2 초 동안 %3 %4',\n    dialog: '%1 을(를) %2 %3',\n    remove_dialog: '말하기 지우기 %1',\n    change_to_nth_shape: '%1 모양으로 바꾸기 %2',\n    change_to_next_shape: '%1 모양으로 바꾸기 %2',\n    set_effect_volume: '%1 효과를 %2 만큼 주기 %3',\n    set_effect: '%1 효과를 %2 (으)로 정하기 %3',\n    erase_all_effects: '효과 모두 지우기 %1',\n    change_scale_percent: '크기를 %1 만큼 바꾸기 %2',\n    set_scale_percent: '크기를 %1  (으)로 정하기 %2',\n    change_scale_size: '크기를 %1 만큼 바꾸기 %2',\n    set_scale_size: '크기를 %1  (으)로 정하기 %2',\n    flip_y: '좌우 모양 뒤집기 %1',\n    flip_x: '상하 모양 뒤집기 %1',\n    set_object_order: '%1 번째로 올라오기 %2',\n    get_pictures: '%1  ',\n    change_to_some_shape: '%1 모양으로 바꾸기 %2',\n    add_effect_amount: '%1 효과를 %2 만큼 주기 %3',\n    change_effect_amount: '%1 효과를 %2 (으)로 정하기 %3',\n    set_effect_amount: '%1 효과를 %2 만큼 주기 %3',\n    set_entity_effect: '%1 효과를 %2 (으)로 정하기 %3',\n    change_object_index: '%1 보내기 %2',\n    move_direction: '이동 방향으로 %1 만큼 움직이기 %2',\n    move_x: 'x 좌표를 %1 만큼 바꾸기 %2',\n    move_y: 'y 좌표를 %1 만큼 바꾸기 %2',\n    locate_xy_time: '%1 초 동안 x: %2 y: %3 위치로 이동하기 %4',\n    rotate_by_angle: '오브젝트를 %1 만큼 회전하기 %2',\n    rotate_by_angle_dropdown: '%1 만큼 회전하기 %2',\n    see_angle: '이동 방향을 %1 (으)로 정하기 %2',\n    see_direction: '%1 쪽 보기 %2',\n    locate_xy: 'x: %1 y: %2 위치로 이동하기 %3',\n    locate_x: 'x: %1 위치로 이동하기 %2',\n    locate_y: 'y: %1 위치로 이동하기 %2',\n    locate: '%1 위치로 이동하기 %2',\n    move_xy_time: '%1 초 동안 x: %2 y: %3 만큼 움직이기 %4',\n    rotate_by_angle_time: '오브젝트를 %1 초 동안 %2 만큼 회전하기 %3',\n    bounce_wall: '화면 끝에 닿으면 튕기기 %1',\n    flip_arrow_horizontal: '화살표 방향 좌우 뒤집기 %1',\n    flip_arrow_vertical: '화살표 방향 상하 뒤집기 %1',\n    see_angle_object: '%1 쪽 바라보기 %2',\n    see_angle_direction: '오브젝트를 %1 (으)로 정하기 %2',\n    rotate_direction: '이동 방향을 %1 만큼 회전하기 %2',\n    locate_object_time: '%1 초 동안 %2 위치로 이동하기 %3',\n    rotate_absolute: '방향을 %1 (으)로 정하기 %2',\n    rotate_relative: '방향을 %1 만큼 회전하기 %2',\n    direction_absolute: '이동 방향을 %1 (으)로 정하기 %2',\n    direction_relative: '이동 방향을 %1 만큼 회전하기 %2',\n    move_to_angle: '%1 방향으로 %2 만큼 움직이기 %3',\n    rotate_by_time: '%1 초 동안 방향을 %2 만큼 회전하기 %3',\n    direction_relative_duration: '%1 초 동안 이동 방향 %2 만큼 회전하기 %3',\n    neobot_sensor_value: '%1  값',\n    neobot_turn_left: '왼쪽모터를 %1 %2 회전 %3',\n    neobot_stop_left: '왼쪽모터 정지 %1',\n    neobot_turn_right: '오른쪽모터를 %1 %2 회전 %3',\n    neobot_stop_right: '오른쪽모터 정지 %1',\n    neobot_run_motor: '%1 모터를  %2 초간 %3 %4 %5',\n    neobot_servo_1: 'SERVO1에 연결된 서보모터를 %1 속도로 %2 로 이동 %3',\n    neobot_servo_2: 'SERVO2에 연결된 서보모터를 %1 속도로 %2 로 이동 %3',\n    neobot_play_note_for: '멜로디 %1 을(를) %2 옥타브로 %3 길이만큼 소리내기 %4',\n    neobot_set_sensor_value: '%1 번 포트의 값을 %2 %3',\n    robotis_openCM70_cm_custom_value: '직접입력 주소 ( %1 ) %2 값',\n    robotis_openCM70_sensor_value: '제어기 %1 값',\n    robotis_openCM70_aux_sensor_value: '%1   %2 값',\n    robotis_openCM70_cm_buzzer_index: '제어기 음계값 %1 을(를) %2 초 동안 연주 %3',\n    robotis_openCM70_cm_buzzer_melody: '제어기 멜로디 %1 번 연주 %2',\n    robotis_openCM70_cm_sound_detected_clear: '최종소리감지횟수 초기화 %1',\n    robotis_openCM70_cm_led: '제어기 %1 LED %2 %3',\n    robotis_openCM70_cm_motion: '모션 %1 번 실행 %2',\n    robotis_openCM70_cm_autodrive_motor: '자율주행 자동차 %1 모터를 %2 에 연결 %3',\n    robotis_openCM70_cm_autodrive_ir: '자율주행 자동차 %1 적외선센서를 %2 에 연결 %3',\n    robotis_openCM70_cm_autodrive_speed: '차로를 따라 %1의 속도로 자율주행 %2',\n    robotis_openCM70_aux_car_move: '로봇을 %1% 의 속도로 %2 %3',\n    robotis_openCM70_aux_motor_speed: '%1 감속모터 속도를 %2 , 출력값을 %3%로 정하기 %4',\n    robotis_openCM70_aux_servo_mode: '%1 서보모터 모드를 %2 (으)로 정하기 %3',\n    robotis_openCM70_aux_servo_speed: '%1 서보모터 속도를 %2 , 출력값을 %3%로 정하기 %4',\n    robotis_openCM70_aux_servo_position: '%1 서보모터 위치를 %2도로 정하기 %3',\n    robotis_openCM70_aux_led_module: '%1 LED 모듈을 %2 (으)로 정하기 %3',\n    robotis_openCM70_aux_custom: '%1 사용자 장치를 %2 (으)로 정하기 %3',\n    robotis_openCM70_cm_poweroff_timer: '제어기 자동꺼짐 타이머 %1 %2',\n    robotis_openCM70_cm_custom: '직접입력 주소 ( %1 ) (을)를 %2 (으)로 정하기 %3',\n    robotis_carCont_sensor_value: '%1   값',\n    robotis_carCont_cm_led: '4번 LED %1 ,  1번 LED %2 %3',\n    robotis_carCont_cm_sound_detected_clear: '최종소리감지횟수 초기화 %1',\n    robotis_carCont_aux_motor_speed: '%1 감속모터 속도를 %2 , 출력값을 %3 (으)로 정하기 %4',\n    robotis_carCont_cm_calibration: '%1 적외선 센서 캘리브레이션 값을 %2 (으)로 정하기 %3',\n    roduino_get_analog_number: '%1  ',\n    roduino_get_port_number: '%1  ',\n    roduino_get_analog_value: '아날로그 %1 번 센서값  ',\n    roduino_get_digital_value: '디지털 %1 번 센서값  ',\n    roduino_set_digital: '디지털 %1 번 핀 %2 %3',\n    roduino_motor: '%1 %2 %3',\n    roduino_set_color_pin: '컬러센서 R : %1, G : %2, B : %3 %4',\n    roduino_get_color: '컬러센서 %1 감지',\n    roduino_on_block: ' On ',\n    roduino_off_block: ' Off ',\n    schoolkit_get_in_port_number: '%1  ',\n    schoolkit_get_out_port_number: '%1  ',\n    schoolkit_get_servo_port_number: '%1  ',\n    schoolkit_get_input_value: '디지털 %1 번 센서값  ',\n    schoolkit_set_output: '디지털 %1 번 핀 %2 %3',\n    schoolkit_motor: '%1 속도 %2(으)로 %3 %4',\n    schoolkit_set_servo_value: '서보모터 %1 번 핀 %2˚ %3',\n    schoolkit_on_block: ' On ',\n    schoolkit_off_block: ' Off ',\n    when_scene_start: '%1 장면이 시작되었을 때',\n    start_scene: '%1 시작하기 %2',\n    start_neighbor_scene: '%1 장면 시작하기 %2',\n    sound_something: '소리 %1 재생하기 %2',\n    sound_something_second: '소리 %1 %2 초 재생하기 %3',\n    sound_something_wait: '소리  %1 재생하고 기다리기 %2',\n    sound_something_second_wait: '소리 %1 %2 초 재생하고 기다리기 %3',\n    sound_volume_change: '소리 크기를 %1 % 만큼 바꾸기 %2',\n    sound_volume_set: '소리 크기를 %1 % 로 정하기 %2',\n    sound_silent_all: '모든 소리 멈추기 %1',\n    get_sounds: '%1  ',\n    sound_something_with_block: '소리 %1 재생하기 %2',\n    sound_something_second_with_block: '소리 %1   %2 초 재생하기 %3',\n    sound_something_wait_with_block: '소리  %1 재생하고 기다리기 %2',\n    sound_something_second_wait_with_block: '소리 %1   %2 초 재생하고 기다리기 %3',\n    sound_from_to: '소리 %1 %2 초 부터 %3 초까지 재생하기 %4',\n    sound_from_to_and_wait: '소리 %1 %2 초 부터 %3 초까지 재생하고 기다리기 %4',\n    when_run_button_click: '%1 시작하기 버튼을 클릭했을 때',\n    press_some_key: '%1 %2 키를 눌렀을 때 %3',\n    when_some_key_pressed: '%1 %2 키를 눌렀을 때',\n    mouse_clicked: '%1 마우스를 클릭했을 때',\n    mouse_click_cancled: '%1 마우스 클릭을 해제했을 때',\n    when_object_click: '%1 오브젝트를 클릭했을 때',\n    when_object_click_canceled: '%1 오브젝트 클릭을 해제했을 때',\n    when_some_key_click: '%1 키를 눌렀을 때',\n    when_message_cast: '%1 %2 신호를 받았을 때',\n    message_cast: '%1 신호 보내기 %2',\n    message_cast_wait: '%1 신호 보내고 기다리기 %2',\n    text: '%1',\n    text_read: '글상자 %1의 내용',\n    text_write: '%1 라고 글쓰기 %2',\n    text_append: '%1 라고 뒤에 이어쓰기 %2',\n    text_prepend: '%1 라고 앞에 추가하기 %2',\n    text_flush: '텍스트 모두 지우기 %1',\n    analizyDataAddButton: '%1',\n    append_row_to_table: '테이블 %1에 %2 추가하기 %3',\n    insert_row_to_table: '테이블 %1 %2번째에 %3 추가하기 %4',\n    delete_row_from_table: '테이블 %1 %2번째 %3 삭제하기 %4',\n    set_value_from_table: '테이블 %1 %2번째 행의 %3을(를) %4(으)로 바꾸기 %5',\n    get_table_count: '테이블 %1의 %2개수',\n    get_value_from_table: '테이블 %1 %2번째 행의 %3 값',\n    calc_values_from_table: '테이블 %1 %2의 %3',\n    open_table_chart: '테이블 %1의 차트 창 열기 %2',\n    close_table_chart: '테이블 차트 창 닫기 %1',\n    get_coefficient: '테이블 %1 %2과(와) %3의 상관계수',\n    variableAddButton: '%1',\n    listAddButton: '%1',\n    change_variable: '%1 에 %2 만큼 더하기 %3',\n    set_variable: '%1 를 %2 (으)로 정하기 %3',\n    show_variable: '변수 %1 보이기 %2',\n    hide_variable: '변수 %1 숨기기 %2',\n    get_variable: '%1 %2',\n    ask_and_wait: '%1 을(를) 묻고 대답 기다리기 %2',\n    get_canvas_input_value: '%1  ',\n    add_value_to_list: '%1 항목을 %2 에 추가하기 %3',\n    remove_value_from_list: '%1 번째 항목을 %2 에서 삭제하기 %3',\n    insert_value_to_list: '%1 을(를) %2 의 %3 번째에 넣기 %4',\n    change_value_list_index: '%1    %2 번째 항목을 %3 (으)로 바꾸기 %4',\n    value_of_index_from_list: '%1 %2 %3 %4 %5',\n    length_of_list: '%1 %2 %3',\n    show_list: '리스트 %1 보이기 %2',\n    hide_list: '리스트 %1 숨기기 %2',\n    options_for_list: '%1  ',\n    set_visible_answer: '대답 %1 %2',\n    is_included_in_list: '%1 %2 %3 %4 %5',\n    xbot_digitalInput: '%1',\n    xbot_analogValue: '%1',\n    xbot_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n    xbot_analogOutput: '아날로그 %1 %2 %3',\n    xbot_servo: '서보 모터 %1 , 각도 %2 %3',\n    xbot_oneWheel: '바퀴(DC) 모터 %1 , 속도 %2 %3',\n    xbot_twoWheel: '바퀴(DC) 모터 오른쪽(2) 속도: %1 왼쪽(1) 속도: %2 %3',\n    xbot_rgb: 'RGB LED 켜기 R 값 %1 G 값 %2 B 값 %3 %4',\n    xbot_rgb_picker: 'RGB LED 색 %1 로 정하기 %2',\n    xbot_buzzer: '%1   %2 음을 %3 초 연주하기 %4',\n    xbot_lcd: 'LCD %1 번째 줄 ,  출력 값 %2 %3',\n    run: '',\n    mutant: 'test mutant block',\n    jr_start: '%1',\n    jr_repeat: '%1 %2 반복',\n    jr_item: '꽃 모으기 %1',\n    cparty_jr_item: '연필 줍기 %1',\n    jr_north: '  위쪽 %1',\n    jr_east: '오른쪽 %1',\n    jr_south: '  아래쪽 %1',\n    jr_west: '  왼쪽 %1',\n    jr_start_basic: '%1 %2',\n    jr_go_straight: '앞으로 가기%1',\n    jr_turn_left: '왼쪽으로 돌기%1',\n    jr_turn_right: '오른쪽으로 돌기%1',\n    jr_go_slow: '천천히 가기 %1',\n    jr_repeat_until_dest: '%1 만날 때까지 반복하기 %2',\n    jr_if_construction: '만약 %1 앞에 있다면 %2',\n    jr_if_speed: '만약 %1 앞에 있다면 %2',\n    maze_step_start: '%1 시작하기를 클릭했을 때',\n    maze_step_jump: '뛰어넘기%1',\n    maze_step_jump2: '뛰어넘기%1',\n    maze_step_jump_pinkbean: '뛰어넘기%1',\n    maze_step_for: '%1 번 반복하기%2',\n    test: '%1 this is test block %2',\n    maze_repeat_until_1: '%1 만날 때 까지 반복%2',\n    maze_repeat_until_2: '모든 %1 만날 때 까지 반복%2',\n    maze_step_if_1: '만약 앞에 %1 있다면%2',\n    maze_step_if_2: '만약 앞에 %1 있다면%2',\n    maze_call_function: '약속 불러오기%1',\n    maze_define_function: '약속하기%1',\n    maze_step_if_3: '만약 앞에 %1 있다면%2',\n    maze_step_if_4: '만약 앞에 %1 있다면%2',\n    maze_step_move_step: '앞으로 한 칸 이동%1',\n    maze_step_rotate_left: '왼쪽으로 회전%1',\n    maze_step_rotate_right: '오른쪽으로 회전%1',\n    maze_step_forward: '앞으로 가기%1',\n    maze_turn_right: '오른쪽 바라보기%1',\n    maze_turn_left: '왼쪽 바라보기%1',\n    maze_ladder_climb: '사다리 타기%1',\n    maze_attack_lupin: '%1공격하기%2',\n    maze_attack_both_side: '양옆 공격하기%1',\n    maze_attack_pepe: '%1 공격하기%2',\n    maze_attack_yeti: '%1 공격하기%2',\n    maze_attack_mushroom: '%1 공격하기%2',\n    maze_attack_peti: '%1 공격하기%2',\n    maze_eat_item: '음식 먹기%1',\n    maze_step_if_mushroom: '만약 한 칸 앞에 %1가 있다면 %2',\n    maze_step_if_yeti: '만약 앞에 %1가 있다면 %2 %3 아니면',\n    maze_step_if_left_monster: '만약 왼쪽 공격범위에 몬스터가 있다면 %1 %2 아니면',\n    maze_step_if_right_monster: '만약 오른쪽 공격범위에 몬스터가 있다면 %1 %2 아니면',\n    maze_step_if_lupin: '만약 두 칸 앞에 %1가 있다면 %2',\n    maze_step_if_else_road: '만약 한 칸 앞에 길이 있다면 %1 %2아니면',\n    maze_step_if_else_mushroom: '만약 한 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_step_if_else_lupin: '만약 두 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_step_if_else_ladder: '만약 한 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_rotate_left: '왼쪽으로 돌기%1',\n    maze_rotate_right: '오른쪽으로 돌기%1',\n    maze_moon_kick: '발차기하기%1',\n    maze_repeat_until_3: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_4: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_5: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_6: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_7: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_goal: '목적지에 도착할 때까지 반복하기%1',\n    maze_repeat_until_beat_monster: '모든 몬스터를 혼내줄 때까지 반복하기%1',\n    maze_radar_check: '%1에 %2이 있다',\n    maze_cony_flower_throw: '꽃 던지기%1',\n    maze_brown_punch: '주먹 날리기%1',\n    maze_iron_switch: '장애물 조종하기%1',\n    maze_james_heart: '하트 날리기%1',\n    maze_step_if_5: '만약 앞에 길이 없다면%2',\n    maze_step_if_6: '만약 앞에 %1이 없다면%2',\n    maze_step_if_7: '만약 앞에 %1이 있다면%2',\n    maze_step_if_8: '만약 %1이라면%2',\n    maze_step_if_else: '만약 %1이라면%2 %3 아니면',\n    test_wrapper: '%1 this is test block %2',\n    basic_button: '%1',\n    ai_move_right: '앞으로 가기 %1',\n    ai_move_up: '위쪽으로 가기 %1',\n    ai_move_down: '아래쪽으로 가기 %1',\n    ai_repeat_until_reach: '목적지에 도달 할 때까지 반복하기 %1',\n    ai_if_else_1: '만약 앞에 %1가 있다면 %2 %3 아니면',\n    ai_boolean_distance: '%1 레이더 %2 %3',\n    ai_distance_value: '%1 레이더',\n    ai_boolean_object: '%1 물체는 %2 인가?',\n    ai_use_item: '아이템 사용 %1',\n    ai_boolean_and: '%1 %2 %3',\n    ai_True: '%1',\n    ai_if_else: '만일 %1 (이)라면 %2 %3 아니면',\n    smartBoard_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값',\n    smartBoard_get_named_sensor_value: '%1 센서값',\n    smartBoard_is_button_pressed: '%1 버튼을 눌렀는가?',\n    smartBoard_set_dc_motor_direction: '%1 DC 모터를 %2 방향으로 정하기 %3',\n    smartBoard_set_dc_motor_speed: '%1 DC모터를 %2 %3',\n    smartBoard_set_dc_motor_pwm: '%1 DC모터를 %2 속도로 돌리기 %3',\n    smartBoard_set_servo_speed: '%1 번 서보모터의 속도를 %2 %3',\n    smartBoard_set_servo_angle: '%1 번 서보모터를 %2 도 로 움직이기 %3',\n    smartBoard_set_number_eight_pin: '%1 포트를 %2 %3',\n    smartBoard_set_gs1_pwm: 'GS1 포트의 PWM을 %1 로 정하기 %2',\n    robotori_digitalInput: '%1',\n    robotori_analogInput: '%1',\n    robotori_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n    robotori_analogOutput: '아날로그 %1 %2 %3',\n    robotori_servo: '서보모터 각도 %1 %2',\n    robotori_dc_direction: 'DC모터 %1 회전 %2 %3',\n    dadublock_get_analog_value: '아날로그 %1 번 센서값',\n    dadublock_get_analog_value_map:\n        '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값',\n    dadublock_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n    dadublock_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dadublock_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dadublock_set_tone: '디지털 %1 번 핀을 %2 음으로 %3 옥타브로 %4 만큼 연주하기 %5',\n    dadublock_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n    coconut_stop_motor: '모터 정지 %1',\n    coconut_move_motor: '%1 움직이기 %2',\n    coconut_turn_motor: '%1 으로 돌기 %2',\n    coconut_move_for_secs: '%1 %2 초동안 움직이기 %3',\n    coconut_turn_for_secs: '%1 으로 %2 초동안 돌기 %3',\n    coconut_turn_to_led: '%1 으로 회전하는 동안 %2LED 켜기 %3',\n    coconut_move_outmotor: '외부모터 %1(으로) 움직이기 속도 %2 %3',\n    coconut_set_led_to: '%1 LED를 %2 으로 켜기 %3',\n    coconut_clear_led: '%1 LED 끄기 %2',\n    coconut_set_led_clear: '%1 LED %2 끄기 %3',\n    coconut_set_led_time: '%1 LED %2 으로 %3 초동안 켜기 %4',\n    coconut_beep: '버저 켜기 %1',\n    coconut_buzzer_time: '버저음을 %1 초 동안 소리내기 %2',\n    coconut_buzzer_set_hz: '버즈음 %1 Hz를 %2초 동안 소리내기 %3',\n    coconut_clear_buzzer: '버저 끄기 %1',\n    coconut_play_buzzer: '%1 %2 %3 음을 %4 박자로 연주하기 %5',\n    coconut_rest_buzzer: '%1 동안 쉬기 %2',\n    coconut_play_buzzer_led: '%1 %2 %3 음을 %4 박자로 연주하는 동안 %5 LED %6 켜기 %7',\n    coconut_play_midi: '%1 연주하기 %2',\n    coconut_floor_sensor: '%1 바닥센서',\n    coconut_floor_sensing: '%1 바닥센서 %2',\n    coconut_following_line: '선 따라가기 %1',\n    coconut_front_sensor: '%1 전방센서',\n    coconut_front_sensing: '%1 전방센서 %2',\n    coconut_obstruct_sensing: '장애물 감지',\n    coconut_avoid_mode: '어보이드 모드 %1',\n    coconut_dotmatrix_set: '도트매트릭스 %1 ( %2줄, %3칸 ) %4',\n    coconut_dotmatrix_on: '도트매트릭스 모두 켜기 %1',\n    coconut_dotmatrix_off: '도트매트릭스 모두 끄기 %1',\n    coconut_dotmatrix_num: '도트매트릭스 숫자 %1표시 %2',\n    coconut_dotmatrix_small_eng: '도트매트릭스 소문자 %1표시 %2',\n    coconut_dotmatrix_big_eng: '도트매트릭스 대문자 %1표시 %2',\n    coconut_dotmatrix_kor: '도트매트릭스 한글 %1표시 %2',\n    coconut_light_sensor: '밝기',\n    coconut_tem_sensor: '온도',\n    coconut_ac_sensor: '%1 가속도',\n    coconut_outled_sensor: '외부 LED 설정 %1 %2 초동안 켜기 %3',\n    coconut_outspk_sensor: '외부 스피커 설정 %1 %2Hz로 %3초 동안 소리내기 %4',\n    coconut_outspk_sensor_off: '외부 스피커 %1 끄기 %2',\n    coconut_outinfrared_sensor: '외부 적외선센서 %1',\n    coconut_outcds_sensor: '외부 빛센서(Cds) %1',\n    coconut_servomotor_angle: '서보모터 연결 %1 각도 %2 %3',\n    chocopi_control_button: '%1 컨트롤 %2번을 누름',\n    chocopi_control_event: '%1 %2 컨트롤 %3을 %4',\n    chocopi_control_joystick: '%1 컨트롤 %2의 값',\n    chocopi_dc_motor: '%1 DC모터 %2 %3% 세기 %4 방향 %5',\n    chocopi_led: '%1 LED %2 RGB(%3 %4 %5) %6',\n    chocopi_motion_photogate_event: '%1 %2 포토게이트 %3번을 %4',\n    chocopi_motion_photogate_status: '%1 포토게이트 %2번이 막힘',\n    chocopi_motion_photogate_time: '%1 포토게이트%2번을 %3',\n    chocopi_motion_value: '%1 모션 %2의 값',\n    chocopi_sensor: '%1 센서 %2',\n    chocopi_servo_motor: '%1 서보모터 %2번 %3도 %4',\n    chocopi_touch_event: '%1 %2 터치 %3번을 %4',\n    chocopi_touch_status: '%1 터치 %2번을 만짐',\n    chocopi_touch_value: '%1 터치 %2번의 값',\n    dadublock_car_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dadublock_car_get_analog_value: '아날로그 %1 번 센서값',\n    dadublock_car_get_analog_value_map:\n        '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    dadublock_car_get_digital: '디지털 %1 번 센서값',\n    dadublock_car_get_irsensor: '적외선 %1 번 센서값',\n    dadublock_car_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n    dadublock_car_motor: '모터 %1 번을 %2 (으)로 %3 %의 속도로 움직이기 %4',\n    dadublock_car_motor_stop: '모터 %1 번 멈추기 %2',\n    dadublock_car_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n    dadublock_car_set_tone: '디지털 %1 번 핀 을 %2 음으로 %3의 옥타브로 %4 만큼 연주하기 %5',\n    dadublock_car_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dadublock_get_digital: '디지털 %1 번 센서값',\n    ev3_get_sensor_value: '%1 의 값',\n    ev3_touch_sensor: '%1 의 터치센서가 작동되었는가?',\n    ev3_color_sensor: '%1 의  %2 값',\n    ev3_motor_power: '%1 의 값을 %2 으로 출력 %3',\n    ev3_motor_power_on_time: '%1 의 값을 %2 초 동안 %3 으로 출력 %4',\n    ev3_motor_degrees: '%1 의 값을 %2 으로  %3 도 만큼 회전 %4',\n    rokoboard_get_sensor_value_by_name: '%1 의 센서값',\n    ardublock_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    ardublock_get_analog_value: '아날로그 %1 번 센서값',\n    ardublock_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    ardublock_get_digital: '디지털 %1 번 센서값',\n    ardublock_get_left_cds_analog_value: '왼쪽 조도센서 %1 센서값',\n    ardublock_get_right_cds_analog_value: '오른쪽 조도센서 %1 센서값',\n    ardublock_get_sound_analog_value: '사운드(소리) 센서 %1 센서값',\n    ardublock_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    ardublock_set_left_motor: '왼쪽모터를 %1 으로 %2 회전 속도로 정하기 %3',\n    ardublock_set_right_motor: '오른쪽모터를 %1 으로 %2 회전 속도로 정하기 %3',\n    ardublock_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    ardublock_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    ardublock_toggle_led: '디지털 %1 번 핀 %2 %3',\n    ardublock_toggle_left_led: '왼쪽 라이트 %1 번 핀 %2 %3',\n    ardublock_toggle_right_led: '오른쪽 라이트 %1 번 핀 %2 %3',\n    mkboard_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    mkboard_get_analog_value: '아날로그 %1 번 센서값',\n    mkboard_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    mkboard_get_digital: '디지털 %1 번 센서값',\n    mkboard_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    mkboard_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    mkboard_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    mkboard_toggle_led: '디지털 %1 번 핀 %2 %3',\n    mkboard_set_lcd: '1602 문자 LCD %1 행 , %2열에 %3 출력하기 %4',\n    mkboard_lcd_command: '1602 문자 LCD %1 명령실행하기 %2',\n    altino_analogValue: '알티노 %1 센서값',\n    altino_dot_display: '전광판에 %1 글자 표시하기 %2',\n    altino_dot_display_line: '1열 %1 2열 %2 3열 %3 4열 %4 5열 %5 6열 %6 7열 %7 8열 %8 출력하기 %9',\n    altino_light: '%1 등을 %2  %3',\n    altino_rear_wheel: '뒷바퀴 오른쪽 %1 왼쪽 %2 로 정하기 %3',\n    altino_sound: '%1 옥타브 %2 음을 연주하기  %3',\n    altino_steering: '방향을 %1 로 정하기 %2',\n    jdkit_altitude: '드론을 %1 높이만큼 날리기 %2',\n    jdkit_button: '%1번 버튼 값 읽어오기',\n    jdkit_connect: '드론 연결 상태 읽어오기',\n    jdkit_emergency: '드론을 즉시 멈추기 %1',\n    jdkit_gyro: '보드 %1 기울기 값 읽어오기',\n    jdkit_joystick: '조이스틱 %1 읽기',\n    jdkit_led: '%1 LED %2  %3',\n    jdkit_motor: '%1 모터를 %2 세기로 돌리기 %3',\n    jdkit_ready: '드론 비행 준비 상태 읽어오기',\n    jdkit_rollpitch: '드론을 %1 방향 %2 세기로 움직이기 %3',\n    jdkit_throttle: '드론 프로펠러를 %1 만큼 세기로 돌리기 %2',\n    jdkit_tune: '%1 음을  %2 초동안 소리내기 %3',\n    jdkit_ultrasonic: '거리(초음파)값 읽어오기',\n    jdkit_yaw: '드론을 %1 만큼 회전하기 %2',\n    memaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    memaker_get_analog_value: '아날로그 %1 번 센서값',\n    memaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    memaker_get_digital: '디지털 %1 번 센서값',\n    memaker_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    memaker_set_lcd: '1602 문자 LCD %1 행 , %2열에 %3 출력하기 %4',\n    memaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    memaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n    memaker_lcd_command: '1602 문자 LCD %1 명령실행하기 %2',\n    edumaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    edumaker_get_analog_value: '아날로그 %1 번 센서값',\n    edumaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    edumaker_get_digital: '디지털 %1 번 센서값',\n    edumaker_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n    edumaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    edumaker_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    edumaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n    creamo_get_number_sensor_value: '가변저항_블록 %1 번 센서값  ',\n    creamo_get_port_number: '%1',\n    creamo_get_pwm_port_number: '%1  ',\n    creamo_motor_port_number: '%1',\n    creamo_toggle_led: 'LED_블록 %1 번 핀 %2 %3',\n    creamo_toggle_motor: 'Motor_블록 %1 번 핀 %2 %3',\n    creamo_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    mechatro_get_dc_motor_current: '%1모터 사용전류값',\n    mechatro_get_digital: '%1 디지털 값',\n    mechatro_get_sensor_value: '%1 센서값',\n    mechatro_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 의 거리값 [cm]',\n    mechatro_set_blue_pw: '블루투스 비밀번호 : %1%2%3%4로 정하기%5',\n    mechatro_set_dc_motor: '%1모터 속도 %2로 정하기%3',\n    mechatro_set_digital: '%1번 %2 %3',\n    mechatro_set_pwm: '%1PWM을 %2%로 정하기 %3',\n    mechatro_set_servo_position: '%1서보모터 위치 :%2도로 옮기기 %3',\n    mechatro_set_servo_speed: '%1서보모터 속도 : 1초당 %2도로 정하기 %3',\n    mechatro_set_threshold: '%1 센서 감도 : %2로 정하기%3',\n    mechatro_set_tone: '%1버저 %2 %3 음으로 연주 %4',\n    mechatro_set_tone_time: '%1버저 %2 %3 음으로 %4 초 연주 %5',\n    funboard_buzzer_onoff: '버저 %1 %2',\n    funboard_buzzer_second: '버저%1%2초 동안%3',\n    funboard_buzzer_tone_simple: '%1%2음을%3초 연주하기%4',\n    funboard_color_led_on_pwm: '%1색  LED %2 % %3',\n    funboard_color_led_onoff: '%1색  LED %2 %3',\n    funboard_convert_scale: '%1값 %2~%3 에서 %4~%5 으로 변환값',\n    funboard_dotmatrix_1column: '%1칸 %2표시하기 %3',\n    funboard_dotmatrix_1row: '%1줄 %2표시하기 %3',\n    funboard_dotmatrix_1row_1column: '%1%2 %3표시하기 %4',\n    funboard_dotmatrix_64_display: '%1 (8x8)표시하기%2',\n    funboard_dotmatrix_big_eng: '대문자 %1표시하기 %2',\n    funboard_dotmatrix_char_display: '문자%1표시하기%2',\n    funboard_dotmatrix_extra_char: '문자 %1표시하기 %2',\n    funboard_dotmatrix_intensity: '밝기 %1% %2',\n    funboard_dotmatrix_kor: '▦  한글 %1표시하기 %2',\n    funboard_dotmatrix_num: '숫자 %1표시하기 %2',\n    funboard_dotmatrix_onoff: '모두 %1 %2',\n    funboard_dotmatrix_scroll_option: '스크롤 방향%1%2',\n    funboard_dotmatrix_scroll_rapid: '스크롤 속도 %1% %2',\n    funboard_dotmatrix_set: '%1줄 %2칸  %3 %4',\n    funboard_dotmatrix_small_eng: '소문자 %1표시하기 %2',\n    funboard_dotmatrix_string_display: '문자열%1표시하기%2',\n    funboard_dotmatrix_string_display_scroll: '문자열%1표시하기%2스크롤%3',\n    funboard_dotmatrix_symbol: '기호 %1표시하기 %2',\n    funboard_get_analog_sensor_2state: '%1값 %2',\n    funboard_get_digital_button_value: '%1 버튼  값',\n    funboard_get_number_sensor_value: '%1 값',\n    funboard_get_touch_button_value: '%1 터치  값',\n    funboard_set_digital_buzzer: '버저를 %1옥타브 %2음 %3초  연주%4',\n    funboard_what_button_pressed: '%1 버튼  눌림',\n    funboard_what_touch_button_pressed: '%1 터치됨',\n};\nLang.TextCoding = {\n    block_name: '블록명',\n    title_syntax: '문법오류 ',\n    title_converting: '변환오류',\n    message_syntax_default: '문법에 오류가 있습니다',\n    message_syntax_unexpected_token: '문법에 맞지 않는 토큰이 포함되어 있습니다',\n    message_syntax_reserved_token: '사용할 수 없는 변수명입니다.',\n    message_syntax_reserved_token_list: '사용할 수 없는 리스트명입니다.',\n    message_syntax_unexpected_character: '문법에 맞지 않는 문자가 포함되어 있습니다',\n    message_syntax_unexpected_indent: '문법에 맞지 않는 띄어쓰기가 포함되어 있습니다',\n    message_conv_default: '지원하지 않는 코드입니다',\n    message_conv_no_support: '변환될 수 없는 코드입니다',\n    message_conv_no_variable: '변수가 선언되지 않았습니다',\n    message_conv_no_list: '리스트가 선언되지 않았습니다',\n    message_conv_no_object: '객체는 지원되지 않습니다',\n    message_conv_no_function: '함수가 변환될 수 없습니다',\n    message_conv_no_entry_event_function: '엔트리 이벤트 함수는 다른 함수 안에 존재할 수 없습니다.',\n    message_conv_undefined_function:\n        '정의되지 않은 명령어 입니다. 명령어가 올바르게 입력되었는지 확인해주세요.',\n    message_conv_is_expect1: '올바르지 않은 문법입니다. ',\n    message_conv_is_expect2: ' 가 올바르게 입력되었는지 확인해주세요.',\n    message_conv_instead: '올바르지 않은 문법입니다. %1 대신 %2 가 필요합니다.',\n    message_conv_is_wrong1: '올바르지 않은 문법입니다. ',\n    message_conv_is_wrong2: '(은/는) 올 수 없는 위치입니다.',\n    message_conv_or: ' 나 ',\n    subject_syntax_default: '기타',\n    subject_syntax_token: '토큰',\n    subject_syntax_character: '문자',\n    subject_syntax_indent: '띄워쓰기',\n    subject_conv_default: '기타',\n    subject_conv_general: '일반',\n    subject_conv_variable: '변수',\n    subject_conv_list: '리스트',\n    subject_conv_object: '객체',\n    subject_conv_function: '함수',\n    alert_variable_empty_text:\n        '등록된 변수 중에 공백(띄어쓰기)이 포함된 변수가 있으면 모드 변환을 할 수 없습니다.',\n    alert_list_empty_text:\n        '등록된 리스트 중에 공백(띄어쓰기)이 포함된 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_field_multi:\n        '등록된 함수 중에 함수 이름에 [이름] 블록이 두번이상 포함되어 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_disorder:\n        '등록된 함수 중에[이름] 블록이 [문자/숫자값] 또는 [판단값] 블록보다 뒤에 쓰이면 모드 변환을 할 수 없습니다.',\n    alert_function_has_boolean:\n        '엔트리파이선으로 변환 후 다시 블록코딩으로 모드로 변경하면 함수에 사용된 [판단값]은 모두 [문자/숫자형]으로 변환됩니다.',\n    alert_function_editor: '함수 생성 및 편집 중에는 모드 변환을 할 수 없습니다.',\n    alert_function_no_support: '텍스트모드에서는 함수 생성 및 편집을 할 수 없습니다.',\n    alert_list_no_support: '텍스트모드에서는 리스트 생성 및 편집을 할 수 없습니다.',\n    alert_variable_no_support: '텍스트모드에서는 변수 생성 및 편집을 할 수 없습니다.',\n    alert_signal_no_support: '텍스트모드에서는 신호 생성 및 편집을 할 수 없습니다.',\n    alert_legacy_no_support: '전환할 수 없는 블록이 존재하여 모드 변환을 할 수 없습니다.',\n    alert_variable_empty_text_add_change: '변수명 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_list_empty_text_add_change: '리스트명에 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_list_contains_exceed_length_value:\n        '리스트 항목에 15자리 이상의 수가 입력되어 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_empty_text_add_change: '함수명에 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_no_save_on_error: '문법 오류가 존재하여 작품을 저장할 수 없습니다.',\n    alert_api_no_support:\n        '작품에 엔트리파이썬에서 지원하지 않는 \\n블록이 조립되어 있습니다. \\n해당 블록을 삭제하고 만들기 모드를 변경할까요?',\n    warn_unnecessary_arguments:\n        '&(calleeName)(); 는 괄호 사이에 값이 입력될 필요가 없는 명령어 입니다. (line:&(lineNumber))',\n    python_code: ' 오브젝트의 파이선 코드',\n    eof: '줄바꿈',\n    newline: '줄바꿈',\n    indent: '들여쓰기',\n    num: '숫자',\n    string: '문자열',\n    name: '변수명',\n};\nLang.PythonHelper = {\n    when_run_button_click_desc:\n        '[시작하기]버튼을 클릭하면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_run_button_click_exampleCode: 'def when_start():\\n    Entry.print(\"안녕!\")',\n    when_run_button_click_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕!\"이라 말합니다.',\n    when_some_key_pressed_desc:\n        'A키를 누르면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_some_key_pressed_elements:\n        'A-- 아래 선택지 중 하나<br>① 알파벳 : \"A\", \"B\" ~ \"Z\" 등(소문자 가능)<br>② 숫자 : 1, 2, 3, 4 ~ 9, 0<br>③ 특수키 : \"space\", \"enter\"<br>④ 방향키 : \"up\", \"down\", \"right\", \"left\"',\n    when_some_key_pressed_exampleCode:\n        'def when_press_key(\"W\"):\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(1):\\n    Entry.add_size(10)',\n    when_some_key_pressed_exampleDesc:\n        'W키를 누르면 오브젝트가 이동방향으로 10만큼 이동하고, 1키를 누르면 오브젝트의 크기가 10만큼 커집니다.',\n    mouse_clicked_desc:\n        '마우스를 클릭했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    mouse_clicked_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.add_size(10)\\n    Entry.move_to_direction(10)',\n    mouse_clicked_exampleDesc:\n        '마우스를 클릭하면 오브젝트의 크기가 10만큼 커지면서 이동방향으로 10만큼 이동합니다.',\n    mouse_click_cancled_desc:\n        '마우스 클릭을 해제했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    mouse_click_cancled_exampleCode:\n        'def when_click_mouse_off():\\n    Entry.move_to_direction(-10)\\n\\ndef when_click_mouse_on():\\n    Entry.move_to_direction(10)',\n    mouse_click_cancled_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 마우스 클릭을 해제하면 오브젝트가 이동방향으로 -10만큼 이동합니다.',\n    when_object_click_desc:\n        '해당 오브젝트를 클릭했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_object_click_exampleCode:\n        'def when_click_object_on():\\n    Entry.print_for_sec(\"회전!\", 0.5)\\n    Entry.add_rotation(90)',\n    when_object_click_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 \"회전!\"이라 말하고, 90도 만큼 회전합니다.',\n    when_object_click_canceled_desc:\n        '해당 오브젝트 클릭을 해제했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_object_click_canceled_exampleCode:\n        'def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)',\n    when_object_click_canceled_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.',\n    when_message_cast_desc:\n        'A 신호를 받으면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    when_message_cast_elements: 'A-- \"신호 이름\"',\n    when_message_cast_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.send_signal(\"신호\")\\n\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"안녕! 반가워\", 0.5)',\n    when_message_cast_exampleDesc:\n        '마우스를 클릭하면 \"신호\"를 보내고, \"신호\"를 받았을때 \"안녕! 반가워\"라고 0.5초간 말합니다.',\n    message_cast_desc:\n        'A에 입력된 신호를 보냅니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    message_cast_elements: 'A-- \"신호 이름\"',\n    message_cast_exampleCode:\n        '#\"오브젝트1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"안녕! 넌 몇살이니?\", 2)\\n    Entry.send_signal(\"신호\")\\n\\n#\"오브젝트2\"의 파이선 코드\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"안녕? 난 세 살이야.\", 2)',\n    message_cast_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"오브젝트1\"이 \"안녕! 넌 몇살이니?\"라고 2초간 말하고 \"신호를 보냅니다., \"오브젝트2\"가 \"신호\"를 받았을때 \"안녕? 난 세 살이야.\"라고 2초간 말합니다.',\n    message_cast_wait_desc:\n        'A에 입력된 신호를 보내고, 해당 신호를 받는 명령어들의 실행이 끝날 때까지 기다립니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    message_cast_wait_elements: 'A-- \"신호 이름\"',\n    message_cast_wait_exampleCode:\n        '#\"오브젝트1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"숨바꼭질하자!\", 2)\\n    Entry.send_signal_wait(\"신호\")\\n    Entry.hide()\\n\\n#\"오브젝트2\"의 파이선 코드\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"그래!\", 2)',\n    message_cast_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"오브젝트1\"이 \"숨바꼭질하자!\"라고 2초 동안 말하고 \"신호\"를 보낸 후 기다립니다. \"오브젝트2\"가 \"신호\"를 받으면 \"그래!\"를 2초 동안 말합니다. \"오브젝트1\"이 그 후에 모양을 숨깁니다.',\n    when_scene_start_desc:\n        '장면이 시작되면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_scene_start_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"다른 곳으로 가볼까?\", 2)\\n    Entry.start_scene(\"장면 2\")\\n\\n#\"장면 2\"의 파이선 코드\\ndef when_start_scene():\\n    Entry.print(\"여기가 어디지?\")',\n    when_scene_start_exampleDesc:\n        '\"장면 1\"에서 [시작하기]버튼을 클릭하면 \"다른 곳으로 가볼까?\"라고 2초간 말하고, \"장면 2\"가 시작됩니다. \"장면 2\"가 시작되면 오브젝트가 \"여기가 어디지?\"라고 말합니다.',\n    start_scene_desc: 'A 장면을 시작합니다.',\n    start_scene_elements: 'A-- \"장면 이름\"',\n    start_scene_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_click_object_on():\\n    Entry.start_scene(\"장면 2\")',\n    start_scene_exampleDesc: '\"장면 1\"에서 해당 오브젝트를 클릭하면 \"장면 2\"가 시작됩니다.',\n    start_neighbor_scene_desc: 'A에 입력한 다음 또는 이전 장면을 시작합니다.',\n    start_neighbor_scene_elements:\n        'A-- 아래 선택지 중 하나<br>① 다음 장면: \"next\" 또는 \"다음\"<br>② 이전 장면: \"prev\" 또는 \"이전\"',\n    start_neighbor_scene_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_press_key(\"right\"):\\n    Entry.start_scene_of(\"next\")\\n\\n#\"장면 2\"의 파이선 코드\\ndef when_press_key(\"left\"):\\n    Entry.start_scene_of(\"prev\")',\n    start_neighbor_scene_exampleDesc:\n        '\"장면 1\"에서 오른쪽화살표키를 누르면 다음 장면이, \"장면 2\"에서 왼쪽화살표키를 누르면 이전 장면이 시작됩니다.',\n    wait_second_desc: 'A초만큼 기다린 후 다음 블록을 실행합니다.',\n    wait_second_elements: 'A-- 초에 해당하는 수 입력',\n    wait_second_exampleCode:\n        'def when_start():\\n    Entry.add_effect(\"color\", 10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_size(10)',\n    wait_second_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트에 색깔효과를 10만큼 주고, 2초동안 기다린 다음 크기를 10만큼 커지게 합니다.',\n    repeat_basic_desc:\n        '아래 명령어들을 A번 반복하여 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_basic_elements: 'A-- 반복할 횟수 입력',\n    repeat_basic_exampleCode:\n        'def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()',\n    repeat_basic_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.',\n    repeat_inf_desc:\n        'A 판단이 True인 동안 아래 명령어들을 반복 실행합니다. A에 True를 입력하면 계속 반복됩니다. <br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_inf_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    repeat_inf_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()',\n    repeat_inf_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.',\n    repeat_while_true_desc:\n        'A 판단이 True가 될 때까지 아래 명령어들을 반복 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_while_true_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    repeat_while_true_exampleCode:\n        'def when_start():\\n    while not Entry.is_key_pressed(\"space\"):\\n        Entry.add_rotation(90)',\n    repeat_while_true_exampleDesc:\n        '[시작하기]버튼을 클릭하면 스페이스키를 누를때까지 오브젝트가 90도 만큼 회전합니다.',\n    stop_repeat_desc: '이 명령어와 가장 가까운 반복 명령어의 반복을 중단합니다.',\n    stop_repeat_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_key_pressed(\"enter\"):\\n            break',\n    stop_repeat_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 계속 이동합니다. 엔터키를 누르면 반복이 중단됩니다.',\n    _if_desc:\n        'A 부분의 판단이 True이면 if A:아래 명령어들을 실행하고, False이면 실행하지 않습니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    _if_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    _if_exampleCode:\n        'def when_click_mouse_on():\\n    if (Entry.value_of_mouse_pointer(\"x\") > 0):\\n        Entry.print_for_sec(\"오른쪽!\", 0.5)',\n    _if_exampleDesc:\n        '마우스를 클릭했을 때 마우스 x좌표가 0보다 크면 오브젝트가 \"오른쪽!\"이라고 0.5초 동안 말합니다.',\n    if_else_desc:\n        'A 부분의 판단이 True이면 if A: 아래 명령어들을 실행하고, False이면 else: 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    if_else_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    if_else_exampleCode:\n        'def when_click_mouse_on():\\n    if Entry.is_touched(\"mouse_pointer\"):\\n        Entry.print(\"닿았다!\")\\n    else:\\n        Entry.print(\"안 닿았다!\")',\n    if_else_exampleDesc:\n        '마우스를 클릭했을 때 마우스포인터가 오브젝트에 닿았으면 \"닿았다!\"를 그렇지 않으면 \"안 닿았다!\"를 말합니다.',\n    wait_until_true_desc: 'A 부분의 판단이 True가 될 때까지 코드의 실행을 멈추고 기다립니다.',\n    wait_until_true_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    wait_until_true_exampleCode:\n        'def when_start():\\n    Entry.print(\"엔터를 눌러봐!\")\\n    Entry.wait_until(Entry.is_key_pressed(\"enter\"))\\n    Entry.print(\"잘했어!\")',\n    wait_until_true_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"엔터를 눌러봐!\"라 말하고, 엔터키를 누를 때까지 기다립니다. 엔터키를 누르면 \"잘했어!\"라 말합니다.',\n    stop_object_desc: 'A코드의 실행을 중지합니다.',\n    stop_object_elements:\n        'A-- 아래 선택지 중 하나<br>① \"all\":  모든 오브젝트의 모든 코드<br>② \"self\" : 해당 오브젝트의 모든 코드<br>③ \"this\": 이 명령어가 포함된 코드<br>④ \"others\" : 해당 오브젝트의 코드 중 이 명령어가 포함된 코드를 제외한 모든 코드<br/>⑤ \"ohter_objects\" : 이 오브젝트를 제외한 다른 모든 오브젝트의 코드',\n    stop_object_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.stop_code(\"all\")\\n',\n    stop_object_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 마우스포인터 위치로  이동합니다. 스페이스키를 누르면 모든 코드의 실행이 중지됩니다.',\n    restart_project_desc: '작품을 처음부터 다시 실행합니다.',\n    restart_project_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_size(10)\\n\\ndef when_press_key(\"enter\"):\\n    Entry.start_again()',\n    restart_project_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트의 크기가 커집니다. 엔터키를 누르면 작품을 처음부터 다시 실행합니다.',\n    when_clone_start_desc:\n        '해당 오브젝트의 복제본이 새로 생성되었을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_clone_start_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"self\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))',\n    when_clone_start_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.',\n    create_clone_desc: 'A 오브젝트의 복제본을 생성합니다.',\n    create_clone_elements: 'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"self\" 또는 \"자신\"',\n    create_clone_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"self\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))',\n    create_clone_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.',\n    delete_clone_desc: 'Entry.make_clone_of(A) 명령에 의해 생성된 복제본을 삭제합니다.',\n    delete_clone_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"자신\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_click_object_on():\\n    Entry.remove_this_clone()',\n    delete_clone_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 복제본을 클릭하면 클릭된 복제본을 삭제합니다.',\n    remove_all_clones_desc: '해당 오브젝트의 모든 복제본을 삭제합니다.',\n    remove_all_clones_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"자신\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_press_key(\"space\"):\\n    Entry.remove_all_clone()',\n    remove_all_clones_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 스페이스 키를 누르면 모든 복제본을 삭제합니다.',\n    move_direction_desc: 'A만큼 오브젝트의 이동방향 화살표가 가리키는 방향으로 움직입니다.',\n    move_direction_elements: 'A-- 이동할 거리에 해당하는 수',\n    move_direction_exampleCode: 'def when_start():\\n    Entry.move_to_direction(10)',\n    move_direction_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동합니다.',\n    bounce_wall_desc: '오브젝트가 화면 끝에 닿으면 튕겨져 나옵니다.',\n    bounce_wall_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()',\n    bounce_wall_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.',\n    move_x_desc: '오브젝트의 x좌표를 A만큼 바꿉니다.',\n    move_x_elements:\n        'A-- x좌표의 변화 값<br>① 양수: 오브젝트가 오른쪽으로 이동합니다.<br>② 음수: 오브젝트가 왼쪽으로 이동합니다.',\n    move_x_exampleCode:\n        'def when_start():\\n    Entry.add_x(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_x(-10)',\n    move_x_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오른쪽으로 10만큼 이동하고 2초 동안 기다린 후 왼쪽으로 10만큼 이동합니다.',\n    move_y_desc: '오브젝트의 y좌표를 A만큼 바꿉니다.',\n    move_y_elements:\n        'A-- y좌표의 변화 값<br>① 양수: 오브젝트가 위쪽으로 이동합니다.<br>② 음수: 오브젝트가 아래쪽으로 이동합니다.',\n    move_y_exampleCode:\n        'def when_start():\\n    Entry.add_y(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_y(-10)',\n    move_y_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 위쪽으로 10만큼 이동하고 2초 동안 기다린 후 아래쪽으로 10만큼 이동합니다.',\n    move_xy_time_desc: '오브젝트가 x와 y좌표를 각각 A와 B만큼 C초에 걸쳐 서서히 바꿉니다.',\n    move_xy_time_elements:\n        'A-- x좌표의 변화 값<br>① 양수: 오브젝트가 오른쪽으로 이동합니다.<br>② 음수: 오브젝트가 왼쪽으로 이동합니다.%nextB-- y좌표의 변화 값<br>① 양수: 오브젝트가 위쪽으로 이동합니다.<br>② 음수: 오브젝트가 아래쪽으로 이동합니다.%nextC-- 이동하는 시간(초)',\n    move_xy_time_exampleCode:\n        'def when_start():\\n    Entry.add_xy_for_sec(100, 100, 2)\\n    Entry.add_xy_for_sec(-100, -100, 2)',\n    move_xy_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오른쪽 위로 100만큼 2초 동안 이동한 후 왼쪽 아래로 100만큼 2초 동안 이동합니다.',\n    locate_x_desc: '오브젝트의 x좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_x_elements: 'A-- 이동할 x좌표',\n    locate_x_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_x(100)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_x(-100)\\n',\n    locate_x_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 100으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 x좌표를 -100으로 정합니다.',\n    locate_y_desc: '오브젝트의 y좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_y_elements: 'B-- 이동할 y좌표',\n    locate_y_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.set_y(100)\\n\\ndef when_press_key(\"down\"):\\n    Entry.set_y(-100)',\n    locate_y_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 y좌표를 100으로 정하고, 아래쪽화살표키를 누르면 오브젝트의 y좌표를 -100으로 정합니다.',\n    locate_xy_desc: '오브젝트가 좌표(A, B)로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_elements: 'A-- 이동할 x좌표%nextB-- 이동할 y좌표',\n    locate_xy_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_xy(0, 0)\\n\\ndef when_press_key(\"right\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\"up\"):\\n    Entry.add_y(10)',\n    locate_xy_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 오브젝트의 x, y좌표를 0으로 정합니다.',\n    locate_xy_time_desc:\n        '오브젝트가 좌표(A, B)로 C초에 걸쳐 서서히 이동합니다.(오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_time_elements: 'A-- 이동할 x좌표%nextB-- 이동할 y좌표%nextC-- 이동하는 시간',\n    locate_xy_time_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_xy_for_sec(0, 0, 2)\\n\\ndef when_press_key(\"right\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\"up\"):\\n    Entry.add_y(10)',\n    locate_xy_time_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 2초 동안 오브젝트를 x,y 좌표 0으로 이동시킵니다.',\n    locate_desc: '오브젝트가 A의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    locate_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.move_to(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.move_to(\"오브젝트\")',\n    locate_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 마우스포인터 위치로 이동합니다.<br>스페이스키를 누르면 오브젝트가 \"오브젝트\" 위치로 이동합니다.',\n    locate_object_time_desc:\n        '오브젝트가 A의 위치로 B초에 걸쳐 서서히 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_object_time_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\" %nextB-- 이동하는 시간(초)',\n    locate_object_time_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.move_to_for_sec(\"mouse_pointer\", 2)',\n    locate_object_time_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 2초 동안 서서히 마우스포인터 위치로 이동합니다.',\n    rotate_relative_desc:\n        '오브젝트의 방향을 A도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_relative_elements: 'A-- 회전할 각도',\n    rotate_relative_exampleCode:\n        'def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)',\n    rotate_relative_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.',\n    direction_relative_desc: '오브젝트의 이동 방향을 A도만큼 회전합니다.',\n    direction_relative_elements: 'A-- 회전할 각도',\n    direction_relative_exampleCode:\n        'def when_start():\\n    Entry.move_to_direction(50)\\n    Entry.wait_for_sec(0.5)\\n    Entry.add_direction(90)\\n    Entry.wait_for_sec(0.5)\\n    Entry.move_to_direction(50)',\n    direction_relative_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 50만큼 이동한 다음 0.5초간 기다립니다. 그 후 이동방향을 90도 만큼 회전하고 0.5초간 기다린 후 이동방향으로 50만큼 이동합니다.',\n    rotate_by_time_desc:\n        '오브젝트의 방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_by_time_elements: 'A-- 회전할 각도%nextB-- 회전할 시간(초)',\n    rotate_by_time_exampleCode:\n        'def when_start():\\n    Entry.add_rotation_for_sec(90, 2)\\n    Entry.add_rotation_for_sec(-90, 2)',\n    rotate_by_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 2초 동안 90도 만큼 회전하고, 다시 2초 동안 -90도 만큼 회전합니다.',\n    direction_relative_duration_desc:\n        '오브젝트의 이동방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    direction_relative_duration_elements: 'A-- 회전할 각도%nextB-- 회전할 시간(초)',\n    direction_relative_duration_exampleCode:\n        'def when_start():\\n    Entry.add_direction_for_sec(90, 2)\\n\\ndef when_start():\\n    while True:\\n        Entry.move_to_direction(1)',\n    direction_relative_duration_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트의 이동방향을 2초 동안 90도만큼 회전시킵니다. 동시에 오브젝트는 이동방향으로 1만큼 계속 이동합니다.',\n    rotate_absolute_desc: '오브젝트의 방향을 A로 정합니다.',\n    rotate_absolute_elements: 'A-- 설정할 방향',\n    rotate_absolute_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_rotation(90)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_rotation(270)',\n    rotate_absolute_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 방향을 90으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 방향을 270으로 정합니다.',\n    direction_absolute_desc: '오브젝트의 이동방향을 A로 정합니다.',\n    direction_absolute_elements: 'A-- 설정할 이동방향',\n    direction_absolute_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_direction(90)\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_direction(270)\\n    Entry.move_to_direction(10)',\n    direction_absolute_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 이동방향을 90으로 정한 후 해당 쪽으로 10만큼 이동하고, 왼쪽화살표키를 누르면 오브젝트의 이동방향을 270으로 정하고 해당쪽으로 10만큼 이동합니다.',\n    see_angle_object_desc:\n        '오브젝트가 A쪽을 바라봅니다. (이동방향이 A를 향하도록 오브젝트의 방향을 회전해줍니다.)',\n    see_angle_object_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    see_angle_object_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.look_at(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.look_at(\"오브젝트\")',\n    see_angle_object_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 마우스포인터쪽을 바라보고, 스페이스키를 누르면 \"오브젝트\"쪽을 바라봅니다.',\n    move_to_angle_desc: '오브젝트가 A만큼 B방향으로 움직입니다.',\n    move_to_angle_elements:\n        'A-- 이동할 거리에 해당하는 수%nextB-- 이동할 방향(12시 방향이 0도, 시계방향으로 증가)',\n    move_to_angle_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.move_to_degree(10, 0)\\n\\ndef when_press_key(\"down\"):\\n    Entry.move_to_degree(10, 180)',\n    move_to_angle_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트가 0도방향으로 10만큼 이동하고, 아래쪽화살표키를 누르면 오브젝트가 180도방향으로 10만큼 이동합니다.',\n    show_desc: '오브젝트를 화면에 나타냅니다.',\n    show_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()',\n    show_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.',\n    hide_desc: '오브젝트를 화면에서 보이지 않게 합니다.',\n    hide_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()',\n    hide_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.',\n    dialog_time_desc:\n        '오브젝트가 A를 B초 동안 말풍선으로 말한 후 다음 명령어가 실행됩니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.',\n    dialog_time_elements:\n        'A-- 말할 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등%nextB-- 말하는 시간(초)',\n    dialog_time_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(\"안녕! 나는\", 2)\\n    Entry.print_for_sec(16, 2)\\n    Entry.print_for_sec(\"살이야\", 2)',\n    dialog_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"안녕! 나는\", 16, \"살이야\"를 각각 2초 동안 차례대로 말합니다.',\n    dialog_desc: '오브젝트가 A를 말풍선으로 말합니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.',\n    dialog_elements: 'A-- 말할 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    dialog_exampleCode:\n        'def when_start():\\n    Entry.print(\"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\")\\n\\ndef when_press_key(1):\\n    Entry.print(1)\\n\\ndef when_press_key(2):\\n    Entry.print(2)\\n',\n    dialog_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\"를 말하고, 키보드로 1, 2를 누르면 각각 1, 2라 말합니다.',\n    remove_dialog_desc: '오브젝트가 말하고 있는 말풍선을 지웁니다.',\n    remove_dialog_exampleCode:\n        'def when_start():\\n    Entry.print(\"말풍선을 지우려면 엔터를 눌러!\")\\n\\ndef when_press_key(\"enter\"):\\n    Entry.clear_print()',\n    remove_dialog_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"말풍선을 지우려면 엔터를 눌러!\"라 말하고, 엔터키를 누르면 말풍선이 사라집니다.',\n    change_to_some_shape_desc: '오브젝트를 A 모양으로 바꿉니다.',\n    change_to_some_shape_elements:\n        'A-- 아래 선택지 중 하나<br>① 모양 이름 : [속성] 탭의 \"모양 이름\"을 적음<br>② 모양 번호 : [속성] 탭의 모양 번호를 적음',\n    change_to_some_shape_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\"오브젝트모양\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\"오브젝트모양\")',\n    change_to_some_shape_exampleDesc:\n        '[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 \"오브젝트모양\"으로 모양을 바꾸고 0.3초간 기다린 다음 \"오브젝트모양\"모양으로 모양을 바꿉니다.',\n    change_to_next_shape_desc: '오브젝트의 모양을 다음 또는 이전 모양으로 바꿉니다.',\n    change_to_next_shape_elements:\n        'A-- 아래 선택지 중 하나<br>① 다음 모양 : \"next\" 또는 \"다음\" <br>② 이전 모양 : \"pre\" 또는 \"이전\"',\n    change_to_next_shape_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\"next\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\"pre\")',\n    change_to_next_shape_exampleDesc:\n        '[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 모양으로 오브젝트 모양을 바꾸고 0.3초간 기다린 다음 이전 모양으로 오브젝트 모양을 바꿉니다.',\n    add_effect_amount_desc: '오브젝트에 A 효과를 B만큼 줍니다.',\n    add_effect_amount_elements:\n        'A -- 아래 선택지 중 하나<br>① “color” 또는 “색깔“                 <br>② “brightness” 또는 “밝기”                <br>③ “transparency” 또는 “투명도”%nextB-- 효과의 변화 정도',\n    add_effect_amount_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.add_effect(\"color\", 50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\"brightness\", -50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\"transparency\", 50)',\n    add_effect_amount_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔 효과를 50만큼 주고 1초간 기다리고, 밝기 효과를 -50만큼 주고 1초간 기다립니다. 그 후 투명도 효과를 50만큼 줍니다.',\n    change_effect_amount_desc: '오브젝트의 A 효과를 B로 정합니다.',\n    change_effect_amount_elements:\n        'A-- 아래 선택지 중 하나<br>① “color” 또는 “색깔“                 <br>② “brightness” 또는 “밝기”                <br>③ “transparency” 또는 “투명도”%nextB-- 효과의 값<br>① color: 0~100 범위의 수, 100을 주기로 반복됨<br>② brightness: -100~100 사이 범위의 수, -100이하는 -100 으로 100 이상은 100 으로 처리 됨<br>③ transparency: 0~100 사이 범위의 수, 0 이하는 0으로, 100이상은 100으로 처리 됨',\n    change_effect_amount_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_effect(\"color\", 50)\\n    Entry.set_effect(\"brightness\", 50)\\n    Entry.set_effect(\"transparency\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.set_effect(\"color\", 0)\\n    Entry.set_effect(\"brightness\", 0)\\n    Entry.set_effect(\"transparency\", 0)',\n    change_effect_amount_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 각 효과를 0으로 정합니다.',\n    erase_all_effects_desc: '오브젝트에 적용된 효과를 모두 지웁니다.',\n    erase_all_effects_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_effect(\"color\", 50)\\n    Entry.set_effect(\"brightness\", 50)\\n    Entry.set_effect(\"transparency\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.clear_effect()\\n',\n    erase_all_effects_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 오브젝트에 적용된 모든 효과를 지웁니다.',\n    change_scale_size_desc: '오브젝트의 크기를 A만큼 바꿉니다.',\n    change_scale_size_elements: 'A-- 크기 변화 값',\n    change_scale_size_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\"space\"):\\n    Entry.set_size(100)',\n    change_scale_size_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.',\n    set_scale_size_desc: '오브젝트의 크기를 A로 정합니다.',\n    set_scale_size_elements: 'A-- 크기값',\n    set_scale_size_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\"space\"):\\n    Entry.set_size(100)',\n    set_scale_size_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.',\n    flip_x_desc: '오브젝트의 상하 모양을 뒤집습니다.',\n    flip_x_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\"right\"):\\n    Entry.flip_vertical()',\n    flip_x_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.',\n    flip_y_desc: '오브젝트의 좌우 모양을 뒤집습니다.',\n    flip_y_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\"right\"):\\n    Entry.flip_vertical()',\n    flip_y_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.',\n    change_object_index_desc: '오브젝트의 레이어를 A로 가져옵니다.',\n    change_object_index_elements:\n        'A-- 아래 선택지 중 하나<br>① “front\" 또는 “맨 앞“                 <br>② “forward” 또는 “앞”                <br>③ “backward” 또는 “뒤”<br>④ “back” 또는 “맨 뒤”',\n    change_object_index_exampleCode:\n        'def when_start():\\n    Entry.send_layer_to(\"front\")\\n    Entry.wait_for_sec(2)\\n    Entry.send_layer_to(\"backward\")',\n    change_object_index_exampleDesc:\n        '오브젝트가 여러개가 겹쳐 있을 경우 [시작하기]버튼을 클릭하면  해당 오브젝트의 레이어를 가장 앞으로 가져와서 보여줍니다.',\n    brush_stamp_desc: '오브젝트의 모양을 도장처럼 실행화면 위에 찍습니다.',\n    brush_stamp_exampleCode:\n        'def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()',\n    brush_stamp_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.',\n    start_drawing_desc:\n        '오브젝트가 이동하는 경로를 따라 선이 그려지기 시작합니다. (오브젝트의 중심점이 기준)',\n    start_drawing_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    for i in range(10):\\n        Entry.move_to_direction(10)',\n    start_drawing_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 오브젝트가 이동방향으로 10만큼 10번 이동할 때 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    stop_drawing_desc: '오브젝트가 선을 그리는 것을 멈춥니다.',\n    stop_drawing_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n\\ndef when_click_mouse_on():\\n    Entry.stop_drawing()',\n    stop_drawing_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 마우스를 클릭하면 그리는것을 멈춥니다.',\n    set_color_desc: '오브젝트가 그리는 선의 색을 A로 정합니다.',\n    set_color_elements:\n        'A-- 아래 선택지 중 하나<br>① 색상 코드 : \"#FF0000\", \"#FFCC00\", \"#3333FF\", \"#000000\" 등<br>② 색깔명 : \"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"navy\", \"purple\", \"black\", \"white\", \"brown\"',\n    set_color_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_color_to(\"#000099\")\\n    while True:\\n        Entry.move_to_direction(1)',\n    set_color_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 색을 \"#000099\"로 정합니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    set_random_color_desc: '오브젝트가 그리는 선의 색을 무작위로 정합니다.',\n    set_random_color_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n        Entry.set_brush_color_to_random()',\n    set_random_color_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 색깔은 계속해서 무작위로 정해집니다.',\n    change_thickness_desc: '오브젝트가 그리는 선의 굵기를 A만큼 바꿉니다.',\n    change_thickness_elements: 'A-- 굵기 변화 값',\n    change_thickness_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.add_brush_size(1)\\n        Entry.move_to_direction(10)',\n    change_thickness_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 굵기는 계속해서 1씩 커집니다.',\n    set_thickness_desc: '오브젝트가 그리는 선의 굵기를 A로 정합니다.',\n    set_thickness_elements: 'A-- 굵기값(1이상의 수)',\n    set_thickness_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)',\n    set_thickness_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    change_brush_transparency_desc: '오브젝트가 그리는 선의 투명도를 A만큼 바꿉니다.',\n    change_brush_transparency_elements: 'A-- 투명도 변화 값',\n    change_brush_transparency_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.add_brush_transparency(5)',\n    change_brush_transparency_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 투명도는 계속해서 5만큼 바꿉니다.',\n    set_brush_tranparency_desc: '오브젝트가 그리는 선의 투명도를 A로 정합니다.',\n    set_brush_tranparency_elements: 'A-- 투명도값(0~100 의 범위)',\n    set_brush_tranparency_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    Entry.set_brush_transparency(50)\\n    while True:\\n        Entry.move_to_direction(10)',\n    set_brush_tranparency_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로, 선의 투명도를 50으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    brush_erase_all_desc: '오브젝트가 그린 선과 도장을 모두 지웁니다.',\n    brush_erase_all_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(10)\\n\\ndef when_click_mouse_on():\\n    Entry.clear_drawing()',\n    brush_erase_all_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 마우스를 클릭하면 오브젝트가 그린 선을 모두 지웁니다.',\n    text_read_desc:\n        '글상자 A의 내용입니다.<br />(내용 안에 개행이 있는 경우, 띄어쓰기하여 반환됩니다.)',\n    text_read_elements: 'A-- 아래 선택지 중 하나<br />① \"오브젝트(글상자) 이름\" <br />② 자기 자신',\n    text_read_exampleCode: 'def when_start():\\n    Entry.print(Entry.contents_of_textbox(\"A\"))',\n    text_read_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 글상자 \"A\"의 내용을 말합니다.​',\n    text_write_desc: '글상자의 내용을 A로 고쳐씁니다.',\n    text_write_elements:\n        'A-- 글상자의 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    text_write_exampleCode: 'def when_start():\\n    Entry.write_text(\"엔트리\")',\n    text_write_exampleDesc: '[시작하기]버튼을 클릭하면 글상자의 내용을 \"엔트리\"로 바꿉니다.',\n    text_append_desc: '글상자의 내용 뒤에 A를 추가합니다.',\n    text_append_elements:\n        'A-- 글상자의 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    text_append_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"안녕?\")\\n    Entry.wait_for_sec(1)\\n    Entry.append_text(\"엔트리!\")',\n    text_append_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"안녕?\"이 되었다가 1초 뒤에 \"엔트리!\"가 추가되어 \"안녕?엔트리!\"가 됩니다.',\n    text_prepend_desc: '글상자의 내용 앞에 A를 추가합니다.',\n    text_prepend_elements:\n        'A-- 글상자의 내용<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    text_prepend_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"반가워!\")\\n    Entry.wait_for_sec(1)\\n    Entry.prepend_text(\"엔트리!\")',\n    text_prepend_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"반가워!\"가 되었다가 1초 뒤에 \"엔트리!\"가 앞에 추가되어 \"엔트리!반가워!\"가 됩니다.',\n    text_flush_desc: '글상자에 저장된 값을 모두 지웁니다.',\n    text_flush_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"엔트리\")\\n    Entry.wait_for_sec(1)\\n    Entry.clear_text()',\n    text_flush_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"엔트리\"가 되었다가 1초 뒤에 모든 내용이 사라집니다.',\n    sound_something_with_block_desc: '오브젝트가 A 소리를 재생합니다.',\n    sound_something_with_block_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound(\"소리\")\\n    Entry.add_size(50)',\n    sound_something_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 재생하면서 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_second_with_block_desc: '오브젝트가 A소리를 B초 만큼 재생합니다.',\n    sound_something_second_with_block_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_second_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_for_sec(\"소리\", 1)\\n    Entry.add_size(50)',\n    sound_something_second_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 1초 동안 재생하면서, 오브젝트의 크기가 50만큼 커집니다.',\n    sound_from_to_desc: '오브젝트가 A소리를 B초부터 C초까지 재생합니다.',\n    sound_from_to_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_from_to_exampleCode:\n        'def when_start():\\n    Entry.play_sound_from_to(\"소리\", 0.5, 1)\\n    Entry.add_size(50)',\n    sound_from_to_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 0.5초부터 1초 구간까지만 재생하면서, 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_wait_with_block_desc:\n        '오브젝트가 A 소리를 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_something_wait_with_block_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_wait_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_and_wait(\"소리\")\\n    Entry.add_size(50)',\n    sound_something_wait_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_second_wait_with_block_desc:\n        '오브젝트가 A소리를 B초 만큼 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_something_second_wait_with_block_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_second_wait_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_for_sec_and_wait(\"소리\", 1)\\n    Entry.add_size(50)',\n    sound_something_second_wait_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 1초 동안 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_from_to_and_wait_desc:\n        '오브젝트가 A소리를 B초부터 C초까지 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_from_to_and_wait_elements:\n        'A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_from_to_and_wait_exampleCode:\n        'def when_start():\\n    Entry.play_sound_from_to_and_wait(\"소리\", 0.5, 1)\\n    Entry.add_size(50)',\n    sound_from_to_and_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 0.5초부터 1초 구간까지만 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_volume_change_desc: '작품에서 재생되는 모든 소리의 크기를 A퍼센트만큼 바꿉니다.',\n    sound_volume_change_elements: 'A-- 소리 크기 변화 값',\n    sound_volume_change_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")',\n    sound_volume_change_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\"작아집니다.',\n    sound_volume_set_desc: '작품에서 재생되는 모든 소리의 크기를 A퍼센트로 정합니다.',\n    sound_volume_set_elements: 'A-- 소리 크기값',\n    sound_volume_set_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_press_key(\"enter\"):\\n    Entry.set_sound_volume(100)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")',\n    sound_volume_set_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\"작아집니다. 엔터키를 누르면 소리의 크기를 100\"로 정합니다.',\n    sound_silent_all_desc: '현재 재생 중인 모든 소리를 멈춥니다.',\n    sound_silent_all_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")\\n\\ndef when_press_key(\"enter\"):\\n    Entry.stop_sound()',\n    sound_silent_all_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 엔터키를 누르면 현재 재생 중인 소리를 멈춥니다.',\n    is_clicked_desc: '마우스를 클릭한 경우 True로 판단합니다.',\n    is_clicked_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_mouse_clicked():\\n            Entry.print_for_sec(\"반가워!\", 0.5)',\n    is_clicked_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 마우스를 클릭했는지 확인합니다. 만약 마우스를 클릭하면 오브젝트가 \"반가워!\"라고 0.5초간 말합니다.',\n    is_press_some_key_desc: 'A 키가 눌려져 있는 경우 True로 판단합니다.',\n    is_press_some_key_elements:\n        'A-- 아래 선택지 중 하나<br>① 알파벳 : \"A\", \"B\" ~ \"Z\" 등(소문자 가능)<br>② 숫자: 1, 2, 3, 4 ~ 9, 0<br>③ 특수키: \"space\", \"enter\"<br>④ 방향키 : \"up\", \"down\", \"right\", \"left\"',\n    is_press_some_key_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"space\"):\\n            Entry.move_to_direction(10)',\n    is_press_some_key_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 선택한 키를 눌렀는지 확인합니다. 만약 스페이스 키를 누르면 오브젝트가 이동방향으로 10만큼 이동합니다.',\n    reach_something_desc: '오브젝트가 A와 닿은 경우 True으로 판단합니다.',\n    reach_something_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\"<br>③ \"edge\", \"edge_up\", \"edge_down\", \"edge_right\", \"edge_left\"',\n    reach_something_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_touched(\"edge\"):\\n            Entry.add_rotation(150)',\n    reach_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 만약 오브젝트가 벽에 닿으면 150만큼 회전하게 됩니다.',\n    boolean_basic_operator_desc: 'A와 B를 비교하여 True 또는 False로 판단합니다.',\n    boolean_basic_operator_elements:\n        'A, B-- 비교하고자 하는 숫자값<br>① == : A와 B의 값이 같으면 True, 아니면 False<br>② > : A의 값이 B의 값보다 크면 true, 아니면 False<br>③ < : A의 값이 B의 값보다 작으면 true, 아니면 False<br>④ >= : A의 값이 B의 값보다 크거나 같으면 true, 아니면 False<br>⑤ <= : A의 값이 B의 값보다 작거나 같으면 true, 아니면 False',\n    boolean_basic_operator_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_x(10)\\n        if Entry.value_of_object(\"오브젝트\", \"x\") > 240:\\n            Entry.set_x(0)',\n    boolean_basic_operator_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트 x좌표를 10만큼 바꿉니다. 만약 오브젝트 x좌표가 240보다 크면 오브젝트 x좌표를 0으로 정합니다.',\n    boolean_and_desc: 'A와 B의 판단이 모두 True인 경우 True, 아닌 경우 False로 판단합니다.',\n    boolean_and_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_and_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") and Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_and_exampleDesc:\n        '[시작하기]버튼을 클릭하고 키보드의 \"a\" 와 \"s\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.',\n    boolean_or_desc: 'A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False로 판단합니다.',\n    boolean_or_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_or_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") or Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_or_exampleDesc:\n        '[시작하기]버튼을 클릭하면 키보드의 \"a\"나 \"s\"키 중 무엇이든 하나를 누르면 오브젝트에 색깔 효과를 10만큼 줍니다.',\n    boolean_not_desc: 'A 판단이 True이면 False, False이면 True로 판단합니다.',\n    boolean_not_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_not_exampleCode:\n        'def when_start():\\n    while True:\\n        if not Entry.is_mouse_clicked():\\n            Entry.add_size(1)',\n    boolean_not_exampleDesc:\n        '[시작하기]버튼을 클릭하면 마우스를 클릭하지 않은 동안 크기가 1씩 커집니다.',\n    calc_basic_desc: 'A와 B의 연산값입니다.',\n    calc_basic_elements:\n        'A, B-- 연산하고자 하는 숫자값<br>① + : A와 B를 더한 값<br>② - : A와 B를 뺀 값<br>③ x : A와 B를 곱한 값<br>④ / : A와 B를 나눈 값',\n    calc_basic_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 + 10, 2)\\n    Entry.print_for_sec(10 - 10, 2)\\n    Entry.print_for_sec(10 * 10, 2)\\n    Entry.print_for_sec(10 / 10, 2)',\n    calc_basic_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10과 10을 더한값, 뺀값, 곱한값, 나눈값을 각 2초간 말합니다.',\n    calc_rand_desc:\n        'A와 B 사이에서 선택된 무작위 수의 값입니다. (두 수 모두 정수를 입력한 경우 정수로,두 수 중 하나라도 소수를 입력한 경우 소수로 무작위 수가 선택됩니다.)',\n    calc_rand_elements:\n        'A, B-- 무작위 수를 추출할 범위<br>① random.randint(A, B) : A, B를 정수로 입력하면 정수 범위에서 무작위 수를 추출<br>② random.uniform(A, B) : A, B를 실수로 입력하면 실수 범위에서 무작위 수를 추출',\n    calc_rand_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(random.randint(1, 10), 2)\\n    Entry.print_for_sec(random.uniform(0.1, 2), 2)',\n    calc_rand_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1부터 10사이의 정수중 무작위 수를 뽑아 2초간 말합니다. 그 후 0.1부터 2사이의 실수중 무작위 수를 뽑아 2초간 말합니다.',\n    coordinate_mouse_desc: '마우스 포인터의 A 좌표 값을 의미합니다.',\n    coordinate_mouse_elements: 'A-- 아래 선택지 중 하나<br>① \"x\" 또는 \"X\"<br>② \"y\" 또는 \"Y\"',\n    coordinate_mouse_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_mouse_pointer(\"x\"))',\n    coordinate_mouse_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 마우스 포인터의 x좌표를 계속해서 말합니다.',\n    coordinate_object_desc: 'A에 대한 B정보값입니다.',\n    coordinate_object_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"self\" 또는 \"자신\"%nextB-- 아래 선택지 중 하나<br>① \"x\" 또는 \"X\"<br>② \"y\" 또는 \"Y\"<br>③ \"rotation\" 또는 \"방향\"<br>④ \"direction\" 또는 \"이동 방향\"<br>⑤ \"size\"  또는 \"크기\"<br>⑥ \"shape_number\" 또는 \"모양 번호\"<br>⑦ \"shape_name\" 또는 \"모양 이름\"',\n    coordinate_object_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_x(1)\\n        Entry.print(Entry.value_of_object(\"오브젝트\", \"x\"))\\n',\n    coordinate_object_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트의 x좌표가 1씩 증가하며, \"오브젝트\"의 x좌표를 말합니다.',\n    get_sound_volume_desc: '현재 작품에 설정된 소리의 크기값입니다.',\n    get_sound_volume_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_sound_volume())',\n    get_sound_volume_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 소리의 크기값을 계속해서 말합니다.',\n    quotient_and_mod_desc: 'A와 B의 연산값입니다.',\n    quotient_and_mod_elements:\n        'A, B-- 연산하고자 하는 숫자값<br>① // : A / B의 몫에 해당하는 값<br>② % : A / B의 나머지에 해당하는 값',\n    quotient_and_mod_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 // 3, 2)\\n    Entry.print_for_sec(10 % 3, 2)',\n    quotient_and_mod_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10 / 3의 몫인 3을 2초 동안 말하고, 나머지인 1을 2초 동안 말합니다.',\n    calc_operation_desc: 'A의 연산값입니다.',\n    calc_operation_elements:\n        'A, B-- 연산하고자 하는 숫자값<br>① A ** 2 : A를 제곱한 값<br>② math.sqrt(A): A의 루트값<br>③ math.sin(A): A의 사인값<br>④ math.cos(A): A의 코사인 값<br>⑤ math.tan(A):  A의 탄젠트값 <br>⑥ math.asin(A): A의 아크사인값<br>⑦ math.acos(A): A의 아크코사인값<br>⑧ math.atan(): A의 아크탄젠트값<br>⑨ math.log10(A): A의 로그값<br>⑩ math.log(A): A의 자연로그값<br>⑪ A - math.floor(A): A의 소수점 부분<br>⑫ math.floor(A): A의 소수점 버림값<br>⑬ math.ceil(A): A의 소수점 올림값<br>⑭ math.round(A): A의 소수점 반올림값<br>⑮ math.factorial(A): A의 팩토리얼 값<br>⑯ math.fabs(A): A의 절댓값',\n    calc_operation_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 ** 2, 2)\\n    Entry.print_for_sec(math.sqrt(9), 2)\\n    Entry.print_for_sec(math.sin(90), 2)\\n    Entry.print_for_sec(math.fabs(-10), 2)',\n    calc_operation_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10의 제곱, 9의 루트값, 90의 사인값, -10의 절댓값을 각 2초 동안 말합니다.',\n    get_project_timer_value_desc: '이 명령이 실행되는 순간 초시계에 저장된 값입니다.',\n    get_project_timer_value_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    get_project_timer_value_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    choose_project_timer_action_desc:\n        '초시계의 동작을 A로 정합니다.<br>(이 명령어를 사용하면 실행화면에 ‘초시계 창’이 생성됩니다.)',\n    choose_project_timer_action_elements:\n        'A-- 아래 선택지 중 하나<br>① \"start\" : 초시계를 시작<br>② \"stop\" : 초시계를 정지<br>③ \"reset\" : 초시계를 초기화',\n    choose_project_timer_action_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    choose_project_timer_action_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    set_visible_project_timer_desc: '실행화면의 초시계 창을 A로 설정합니다.',\n    set_visible_project_timer_elements:\n        'A-- 아래 선택지 중 하나<br>① \"hide\" : 초시계창을 숨김<br>② \"show\" : 초시계창을 보임',\n    set_visible_project_timer_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    set_visible_project_timer_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    get_date_desc: '현재 A에 대한 값입니다.',\n    get_date_elements:\n        'A-- 아래 선택지 중 하나<br>① \"year\" : 현재 연도 값<br>② \"month\" : 현재 월 값<br>③ \"day\" : 현재 일 값<br>④ \"hour\" : 현재 시간 값<br>⑤ \"minute\" : 현재 분 값<br>⑥ \"second\" : 현재 초 값',\n    get_date_exampleCode:\n        'def when_start():\\n    Entry.print(Entry.value_of_current_time(\"year\") + \"년\" + Entry.value_of_current_time(\"month\") + \"월\")',\n    get_date_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 현재년도와 월을 말합니다.',\n    distance_something_desc: '자신과 A까지의 거리 값입니다.',\n    distance_something_elements:\n        'A-- 아래 선택지 중 하나<br>① \"오브젝트 이름\"<br>② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    distance_something_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_distance_to(\"mouse_pointer\"))',\n    distance_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 마우스포인터와의 거리를 계속해서 말합니다.',\n    get_sound_duration_desc: '소리 A의 길이(초)값입니다.',\n    get_sound_duration_elements: 'A-- \"소리 이름\"',\n    get_sound_duration_exampleCode:\n        'def when_start():\\n    Entry.print(Entry.value_of_sound_length_of(\"소리\"))',\n    get_sound_duration_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"소리\"의 길이를 말합니다.',\n    get_user_name_desc: '작품을 실행하고 있는 사용자의 이름 값입니다.',\n    get_user_name_exampleCode: 'def when_start():\\n    Entry.print(Entry.value_of_username())',\n    get_user_name_exampleDesc:\n        '[시작하기]버튼을 클릭하면 작품을 실행하고 있는 사용자의 이름 값을 말합니다.',\n    length_of_string_desc: '입력한 문자값의 공백을 포함한 글자 수입니다.',\n    length_of_string_elements: 'A-- \"문자열\"',\n    length_of_string_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(len(\"안녕\"), 2)\\n    Entry.print_for_sec(len(\"엔트리\"), 2)',\n    length_of_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕\"과 \"엔트리\"의 글자 수를 각각 2초 동안 말합니다.',\n    combine_something_desc:\n        'A 문자열과 B 문자열을 결합한 값입니다. (A, B 중 하나가 숫자면 문자열로 바꾸어 처리되고, 둘 다 숫자면 덧셈 연산으로 처리됩니다.)',\n    combine_something_elements: 'A, B-- \"문자열\"',\n    combine_something_exampleCode: 'def when_start():\\n    Entry.print(\"안녕! \" + \"엔트리\")',\n    combine_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕!\"과 \"엔트리\"를 결합한 \"안녕! 엔트리\"를 말합니다.',\n    char_at_desc: 'A 문자열의 B번째의 글자 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    char_at_elements: 'A-- \"문자열\"%nextB-- 찾고자 하는 문자열의 위치',\n    char_at_exampleCode: 'def when_start():\\n    Entry.print(\"안녕 엔트리!\"[0])',\n    char_at_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"의 0번째 글자인 \"안\"을 말합니다.',\n    substring_desc:\n        'A 문자열의 B위치부터 C-1위치까지의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    substring_elements:\n        'A-- \"문자열\"%nextB-- 포함할 문자열의 시작 위치<br>첫 번째 글자는 0부터 시작%nextC-- 문자열을 포함하지 않는 위치',\n    substring_exampleCode: 'def when_start():\\n    Entry.print(\"안녕 엔트리!\"[1:5])',\n    substring_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"의 1에서 4번째 글자인 \"녕 엔트\"를 말합니다.',\n    index_of_string_desc:\n        'A문자열에서 B문자열이 처음으로 등장하는 위치의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    index_of_string_elements: 'A, B-- \"문자열\"',\n    index_of_string_exampleCode:\n        'def when_start():\\n    Entry.print(\"안녕 엔트리!\".find(\"엔트리\"))',\n    index_of_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"에서 \"엔트리\"가 처음으로 등장하는 위치인 3을 말합니다.',\n    replace_string_desc:\n        'A 문자열에서 B문자열을 모두 찾아 C문자열로 바꾼 값입니다.<br>(영문 입력시 대소문자를 구분합니다.)',\n    replace_string_elements: 'A, B, C-- \"문자열\"',\n    replace_string_exampleCode:\n        'def when_start():\\n    Entry.print(\"안녕 엔트리!\".replace( \"안녕\", \"반가워\"))',\n    replace_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"에서 \"안녕\"을 \"반가워\"로 바꾼 \"반가워 엔트리!\"를 말합니다.',\n    change_string_case_desc: 'A의 모든 알파벳을 대문자 또는 소문자로 바꾼 문자값입니다.',\n    change_string_case_elements:\n        'A-- \"문자열\"<br>① A.upper(): A의 모든 알파벳을 대문자로 바꾼 값<br>② A.lower() : A의 모든 알파벳을 소문자로 바꾼 값',\n    change_string_case_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(\"Hello Entry!\".upper(), 2)\\n    Entry.print_for_sec(\"Hello Entry!\".lower(), 2)',\n    change_string_case_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"Hello Entry!\"를 모두 대문자로 바꾼 \"HELLO ENTRY!\"를 2초간 말한 다음 모두 소문자로 바꾼 \"hello entry!\"를 2초간 말합니다.',\n    ask_and_wait_desc:\n        \"오브젝트가 A 내용을 말풍선으로 묻고, 대답을 입력받습니다. 대답은 실행화면 또는 콘솔창에서 입력할 수 있으며 입력된 값은 'Entry.answer()'에 저장됩니다. <br>(이 명령어를 사용하면 실행화면에 ‘대답 창’이 생성됩니다.)\",\n    ask_and_wait_elements: 'A-- \"문자열\"',\n    ask_and_wait_exampleCode:\n        'def when_start():\\n    Entry.input(\"이름을 입력해보세요.\")\\n    Entry.print(Entry.answer() + \" 반가워!\")',\n    ask_and_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"이름을 입력해보세요.\"라고 말풍선으로 묻습니다. 이름을 입력하면 \"(입력한 이름) 반가워!\"라 말합니다.',\n    get_canvas_input_value_desc:\n        'Entry.input(A) 명령에 의해 실행화면 또는 콘솔에서 입력받은 값입니다.',\n    get_canvas_input_value_exampleCode:\n        'def when_start():\\n    Entry.input(\"이름을 입력해보세요.\")\\n    Entry.print(Entry.answer() + \" 반가워!\")',\n    get_canvas_input_value_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"이름을 입력해보세요.\"라고 말풍선으로 묻습니다. 이름을 입력하면 \"(입력한 이름) 반가워!\"라 말합니다.',\n    set_visible_answer_desc: '실행화면의 대답 창을 A로 설정합니다.',\n    set_visible_answer_elements:\n        'A-- 아래 선택지 중 하나<br>① \"hide\" : 대답 창을 숨김<br>② \"show\" : 대답 창을 보임',\n    set_visible_answer_exampleCode:\n        'def when_start():\\n    Entry.answer_view(\"hide\")\\n    Entry.input(\"나이를 입력하세요.\")\\n    Entry.print(Entry.answer())',\n    set_visible_answer_exampleDesc:\n        '[시작하기]버튼을 클릭하면 대답창이 숨겨지고, 오브젝트가 \"나이를 입력하세요.\"라고 말풍선으로 묻습니다. 나이를 입력하면 오브젝트가 입력한 나이를 말합니다.',\n    get_variable_desc: 'A 변수에 저장된 값입니다.',\n    get_variable_elements:\n        'A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A',\n    get_variable_exampleCode: 'age = 16\\n\\ndef when_start():\\n    Entry.print(age)',\n    get_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 말합니다.',\n    change_variable_desc: 'A 변수에 B만큼 더합니다.',\n    change_variable_elements:\n        'A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 숫자값',\n    change_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.print_for_sec(age, 2)\\n    age += 2\\n    Entry.print_for_sec(age, 2)',\n    change_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 2초 동안 말합니다. 그 후 age변수에 2를 더하고 더한값인 \"18\"을 2초 동안 말합니다.',\n    set_variable_desc:\n        'A 변수의 값을 B로 정합니다. 만약 A 변수가 없으면  [속성] 탭에 A 변수가 자동 생성됩니다.',\n    set_variable_elements:\n        'A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 변수에 넣을 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    set_variable_exampleCode: 'age = 16\\n\\ndef when_start():\\n    Entry.print(age)',\n    set_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 말합니다.',\n    show_variable_desc: 'A 변수 창을 실행화면에 보이게 합니다.',\n    show_variable_elements:\n        'A-- \"변수명\"<br>① 모든 오브젝트에서 사용: \"A\"<br>② 이 오브젝트에서 사용: \"self.A\"',\n    show_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\"age\")\\n    Entry.wait_for_sec(2)\\n    age = 20\\n    Entry.show_variable(\"age\")',\n    show_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨깁니다. 2초 후 변수값을 17로 바꾸고 age변수창을 실행화면에 보이게 합니다.',\n    hide_variable_desc: 'A 변수 창을 실행화면에서 숨깁니다.',\n    hide_variable_elements:\n        'A-- \"변수명\"<br>① 모든 오브젝트에서 사용: \"A\"<br>② 이 오브젝트에서 사용: \"self.A\"',\n    hide_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\"age\")\\n    Entry.print_for_sec(age, 2)',\n    hide_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨기고, 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 2초 동안 말합니다.',\n    value_of_index_from_list_desc:\n        'A 리스트에서 B위치의 항목 값을 의미합니다. <br>(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    value_of_index_from_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치',\n    value_of_index_from_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.print(basket[1])\\n',\n    value_of_index_from_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트가 basket 리스트의 1번째 항목인 orange를 말합니다.',\n    add_value_to_list_desc: 'A 리스트의 마지막 항목으로 B값이 추가됩니다.',\n    add_value_to_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트에 넣을 항목 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    add_value_to_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket.append(\"juice\")\\n    Entry.print(basket[4])',\n    add_value_to_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 \"juice\"를 basket의 마지막 항목으로 추가합니다. 오브젝트는 basket의 4번째 항목인 \"juice\"를 말합니다.',\n    remove_value_from_list_desc:\n        'A 리스트의 B위치에 있는 항목을 삭제합니다.<br>(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    remove_value_from_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치값',\n    remove_value_from_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\ndef when_start():\\n    basket.pop(0)\\n    Entry.print(basket[0])',\n    remove_value_from_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 항목인 apple을 삭제합니다. 오브젝트는 새롭게 basket의 0번째 항목이 된 \"orange\"를 말합니다.',\n    insert_value_to_list_desc:\n        'A 리스트의 B위치에 C항목을 끼워 넣습니다. <br>(첫 번째 항목의 위치는 0부터 시작합니다. B위치보다 뒤에 있는 항목들은 순서가 하나씩 밀려납니다.)',\n    insert_value_to_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    insert_value_to_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket.insert(1, \"juice\")\\n    Entry.print(basket[2])',\n    insert_value_to_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 1번째 위치에 항목 \"juice\"를 끼워 넣습니다. 오브젝트는 새롭게 basket의 2번째 항목이 된 \"orange\"를 말합니다.',\n    change_value_list_index_desc:\n        'A 리스트에서 B위치에 있는 항목의 값을 C 값으로 바꿉니다.<br>(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    change_value_list_index_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등',\n    change_value_list_index_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket[0] = \"juice\"\\n    Entry.print(basket[0])',\n    change_value_list_index_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 위치의 항목 \"apple\"을 \"juice\"로 바꿉니다. 오브젝트는 바뀐 basket의 0번째 항목 \"juice\"를 말합니다.',\n    length_of_list_desc: 'A 리스트가 보유한 항목 개수 값입니다.',\n    length_of_list_elements:\n        'A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A',\n    length_of_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.print(len(basket))',\n    length_of_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트는  basket의 항목 개수인 4를 말합니다.',\n    is_included_in_list_desc: 'A값을 가진 항목이 B리스트에 포함되어 있는지 확인합니다.',\n    is_included_in_list_elements:\n        'A-- 리스트의 항목 값<br>① 문자 : \"안녕!\", \"엔트리\" 등 <br>② 숫자 : 0, 10, 35 등%nextB-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A',\n    is_included_in_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    if \"apple\" in basket:\\n        Entry.print(\"사과가 있어!\")',\n    is_included_in_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트에 \"apple\"항목이 있는지 확인합니다. \"apple\"항목이 있기 때문에 오브젝트는 \"사과가 있어!\"라 말합니다.',\n    show_list_desc: '선택한 리스트 창을 실행화면에 보이게 합니다.',\n    show_list_elements:\n        'A-- \"리스트명\"<br>① 모든 오브젝트에서 사용: \"A\"<br>② 이 오브젝트에서 사용: \"self.A\"',\n    show_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.hide_list(\"basket\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\"basket\")',\n    show_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.',\n    hide_list_desc: '선택한 리스트 창을 실행화면에서 숨깁니다.',\n    hide_list_elements:\n        'A-- \"리스트명\"<br>① 모든 오브젝트에서 사용: \"A\"<br>② 이 오브젝트에서 사용: \"self.A\"',\n    hide_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.hide_list(\"basket\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\"basket\")',\n    hide_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.',\n    boolean_and_or_desc: 'A와 B의 판단값을 확인하여 True 또는 False로 판단합니다.',\n    boolean_and_or_elements: '② or : A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False',\n    boolean_and_or_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") and Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_and_or_exampleDesc:\n        '[시작하기]버튼을 클릭하고 키보드의 \"a\" 와 \"s\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.',\n    check_weather_desc: 'B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.',\n    check_weather_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"sunny\" : 맑음<br>②    \"partly cloudy\" : 구름조금<br>③    \"mostly cloudy\" : 구름많음<br>④    \"cloudy\" : 흐림<br>⑤    \"rainy\" : 비<br>⑥    \"sleet\" : 진눈깨비<br>⑦    \"snowy\" : 눈%nextB-- 아래 선택지 중 하나<br>①    \"yesterday\" : 어제<br>②    \"today\" : 오늘<br>③    \"tomorrow\" : 내일<br>④    \"After 2 days\" : 모레<br>⑤    \"After 3 days\" : 3일 후<br>⑥    \"After 4 days\" : 4일 후<br>⑦    \"After 5 days\" : 5일 후<br>⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    check_weather_exampleCode:\n        'def when_start():\\n    if Weather.is_condition_sunny(\"today\", \"Seoul\"):\\n        Entry.print(\"오늘 서울의 날씨는 맑습니다.\")',\n    check_weather_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \"오늘 서울의 날씨는 맑습니다.\"라고 말합니다.​',\n    check_finedust_desc:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.',\n    check_finedust_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"good\" : 좋음<br>②    \"normal\" : 보통<br>③    \"bad\" : 나쁨<br>④    \"very bad\" : 매우나쁨%nextB-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    check_finedust_exampleCode:\n        'def when_start():\\n    if Weather.is_current_finedust_grade_good(\"Seoul\"):\\n        Entry.print(\"현재 서울의 미세먼지 등급은 좋음입니다.\")',\n    check_finedust_exampleDesc:\n        '[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​',\n    get_weather_data_desc:\n        '선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.',\n    get_weather_data_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"the lowest temperature\" : 최저기온<br>②    \"the highest temperature\" : 최고기온<br>③    \"humidity\" : 습도<br>④    \"precipitation\" : 강수량<br>⑤    \"precipitation probability\" : 강수확률<br>⑥    \"wind speed\" : 풍속%nextB-- 아래 선택지 중 하나<br>①    \"yesterday\" : 어제<br>②    \"today\" : 오늘<br>③    \"tomorrow\" : 내일<br>④    \"After 2 days\" : 모레<br>⑤    \"After 3 days\" : 3일 후<br>⑥    \"After 4 days\" : 4일 후<br>⑦    \"After 5 days\" : 5일 후<br>⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    get_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\"today\", \"Seoul\"))',\n    get_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​',\n    get_current_weather_data_desc: '현재 B지역의 A 날씨 정보값을 의미합니다.',\n    get_current_weather_data_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나<br>①    \"temperature\" : 기온<br>②    \"concentration of fine dust\" : 미세먼지농도',\n    get_current_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_current_temperature(\"Seoul\"))',\n    get_current_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.',\n    get_today_temperature_desc: '오늘 A지역의 B 시간대 기온 정보값을 의미합니다.',\n    get_today_temperature_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나<br>①    \"00\" : 당일 00시 측정된 기온값<br>②    \"03\" : 당일 03시 측정된 기온값<br>③    \"06\" : 당일 06시 측정된 기온값<br>④    \"09\" : 당일 09시 측정된 기온값<br>⑤    \"12\" : 당일 12시 측정된 기온값<br>⑥    \"15\" : 당일 15시 측정된 기온값<br>⑦    \"18\" : 당일 18시 측정된 기온값<br>⑧    \"21\" : 당일 21시 측정된 기온값',\n    get_today_temperature_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_today_temperature(\"Seoul\", 00))',\n    get_today_temperature_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​',\n    check_city_weather_desc: 'B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.',\n    check_city_weather_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"sunny\" : 맑음<br>②    \"partly cloudy\" : 구름조금<br>③    \"mostly cloudy\" : 구름많음<br>④    \"cloudy\" : 흐림<br>⑤    \"rainy\" : 비<br>⑥    \"sleet\" : 진눈깨비<br>⑦    \"snowy\" : 눈%nextB-- 아래 선택지 중 하나<br>①    \"yesterday\" : 어제<br>②    \"today\" : 오늘<br>③    \"tomorrow\" : 내일<br>④    \"After 2 days\" : 모레<br>⑤    \"After 3 days\" : 3일 후<br>⑥    \"After 4 days\" : 4일 후<br>⑦    \"After 5 days\" : 5일 후<br>⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    check_city_weather_exampleCode:\n        'def when_start():\\n    if Weather.is_condition_sunny(\"today\", \"Seoul\"):\\n        Entry.print(\"오늘 서울의 날씨는 맑습니다.\")',\n    check_city_weather_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \"오늘 서울의 날씨는 맑습니다.\"라고 말합니다.​',\n    check_city_finedust_desc:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.',\n    check_city_finedust_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"good\" : 좋음<br>②    \"normal\" : 보통<br>③    \"bad\" : 나쁨<br>④    \"very bad\" : 매우나쁨%nextB-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    check_city_finedust_exampleCode:\n        'def when_start():\\n    if Weather.is_current_finedust_grade_good(\"Seoul\"):\\n        Entry.print(\"현재 서울의 미세먼지 등급은 좋음입니다.\")',\n    check_city_finedust_exampleDesc:\n        '[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​',\n    get_city_weather_data_desc:\n        '선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.',\n    get_city_weather_data_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"the lowest temperature\" : 최저기온<br>②    \"the highest temperature\" : 최고기온<br>③    \"humidity\" : 습도<br>④    \"precipitation\" : 강수량<br>⑤    \"precipitation probability\" : 강수확률<br>⑥    \"wind speed\" : 풍속%nextB-- 아래 선택지 중 하나<br>①    \"yesterday\" : 어제<br>②    \"today\" : 오늘<br>③    \"tomorrow\" : 내일<br>④    \"After 2 days\" : 모레<br>⑤    \"After 3 days\" : 3일 후<br>⑥    \"After 4 days\" : 4일 후<br>⑦    \"After 5 days\" : 5일 후<br>⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북',\n    get_city_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\"today\", \"Seoul\"))',\n    get_city_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​',\n    get_current_city_weather_data_desc: '현재 B지역의 A 날씨 정보값을 의미합니다.',\n    get_current_city_weather_data_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나<br>①    \"temperature\" : 기온<br>②    \"concentration of fine dust\" : 미세먼지농도',\n    get_current_city_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_current_temperature(\"Seoul\"))',\n    get_current_city_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.',\n    get_today_city_temperature_desc: '오늘 A지역의 B 시간대 기온 정보값을 의미합니다.',\n    get_today_city_temperature_elements:\n        'A-- 아래 선택지 중 하나<br>①    \"Seoul\" : 서울<br>②    \"Gangwon-do\" : 강원<br>③    \"Gyeonggi-do\" : 경기<br>④    \"Gyeongsangnam-do\" : 경남<br>⑤    \"Gyeongsangbuk-do\" : 경북<br>⑥    \"Gwangju\" : 광주<br>⑦    \"Daegu\" : 대구<br>⑧    \"Daejeon\" : 대전<br>⑨    \"Busan\" : 부산<br>⑩    \"Sejong\" : 세종<br>⑪    \"Ulsan\" : 울산<br>⑫    \"Incheon\" : 인천<br>⑬    \"Jeollanam-do\" : 전남<br>⑭    \"Jeollabuk-do\" : 전북<br>⑮    \"Jeju\" : 제주<br>Ⓐ \"Chungcheongnam-do\" : 충남<br>Ⓑ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나<br>①    \"00\" : 당일 00시 측정된 기온값<br>②    \"03\" : 당일 03시 측정된 기온값<br>③    \"06\" : 당일 06시 측정된 기온값<br>④    \"09\" : 당일 09시 측정된 기온값<br>⑤    \"12\" : 당일 12시 측정된 기온값<br>⑥    \"15\" : 당일 15시 측정된 기온값<br>⑦    \"18\" : 당일 18시 측정된 기온값<br>⑧    \"21\" : 당일 21시 측정된 기온값',\n    get_today_city_temperature_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_today_city_temperature(\"Seoul\", 00))',\n    get_today_city_temperature_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​',\n};\nLang.Painter = {\n    select_cut: '사각 점선 모양으로 오릴 수 있어요.',\n    thickness_of_eraser: '지우개 굵기',\n    font: '글꼴',\n    font_color: '글꼴 색상',\n    outline_color: '윤곽선 색상',\n    outline_thickness: '윤곽선 굵기',\n    fill_color: '채우기 색상',\n    inversion: '반전',\n    font_size: '글꼴 크기',\n    font_family: '글꼴 스타일',\n    fullscreen: '전체화면',\n    exit_fullscreen: '전체화면 해제',\n    picture_import: '모양 가져오기',\n    edit_way: '편집 방법',\n    line: '직선',\n    vertex: '꼭지점',\n    bitmap: '비트맵',\n    vector: '벡터',\n    forward: '앞으로',\n    backward: '뒤로',\n    front: '맨 앞으로',\n    back: '맨 뒤로',\n    group: '그룹화',\n    ungroup: '그룹 해제',\n    copy_picture: '복사',\n    delete_picture: '삭제',\n    cut_picture: '자르기',\n    paste_picture: '붙여넣기',\n    remove_all: '모두 삭제',\n    new_picture: '새그림',\n    edit: '편집',\n    picture_size: '크기',\n    picture_rotation: '회전',\n    thickness: '굵기',\n    font_fill: '채우기 색상',\n    painter_file_save: '저장하기',\n    painter_file_saveas: '새 모양으로 저장',\n    file: '파일',\n    Pencil: '펜',\n    Line: '직선',\n    Path: '형태',\n    Pan: '이동',\n    Select: '선택',\n    Rectangle: '사각형',\n    Ellipse: '원',\n    Text: '글상자',\n    Fill: '채우기',\n    Eraser: '지우기',\n    get_file: '가져오기',\n    copy_file: '복사하기',\n};\nLang.DataAnalytics = {\n    data_analysis: '데이터분석',\n    create_table: '테이블 만들기',\n    data: '데이터',\n    add_table: '테이블 추가하기',\n    show_chart: '차트 보기',\n    legend: '범례',\n    dashboard: '요약',\n    table: '테이블',\n    chart: '차트',\n    attribute: '열',\n    row: '행',\n    average: '평균',\n    standard_deviation: '표준 편차',\n    maximum: '최댓값',\n    minimum: '최솟값',\n    median: '중간값',\n    average_explain: '해당 열의 모든 값을 더한 후 열의 개수 만큼 나눈 값',\n    standard_deviation_explain:\n        '데이터가 평균을 중심으로 얼마나 퍼져있는지 알려주는 값.\\n0에 가까울 수록 값들이 평균 근처에 집중되어 있다는 것을 의미',\n    maximum_minimum_explain: '해당 열의 가장 큰 값과 가장 작은 값',\n    median_explain: '해당 열의 모든 값을 크기순으로 배열했을 때\\n전체의 중앙에 위치하는 값',\n    add_row_above: '위에 행 추가하기',\n    add_row_below: '아래에 행 추가하기',\n    delete_row: '행 삭제하기',\n    add_property_left: '왼쪽에 열 추가하기',\n    add_property_right: '오른쪽에 열 추가하기',\n    delete_attribute: '열 삭제',\n    data_alert: '숫자가 아닌 값이 포함된 열은 개수만 확인할 수 있습니다.',\n    save: '저장하기',\n    cancel: '취소',\n    confirm: '확인',\n    attribute_count: '개',\n    row_count: '행',\n    cell_count: '개',\n    count: '개수',\n    add_chart_alert: '추가된 차트가 없습니다.\\n차트를 생성해주세요.',\n    enter_attribute_name: '열 이름을 입력해 주세요.(10자 이내)',\n    placeholder_attribute_name: '열 이름',\n    new_attribute: '새로운 열',\n    chart_title: '차트 제목',\n    remove_chart: '차트 삭제하기',\n    add_chart_first: '차트를 먼저 추가해주세요.',\n    bar: '막대',\n    line: '꺾은선',\n    pie: '원형',\n    scatter: '분산형',\n    select_x_axis: '가로축을 선택해주세요.',\n    x_axis: '가로축',\n    y_axis: '세로축',\n    select_y_axis: '세로축을 선택해주세요.',\n    select_y_axis_or_legend: '세로축 혹은 범례를 선택해주세요.',\n    select_legend: '범례를 선택해주세요',\n    cell: '칸',\n    unable_to_express_chart: '차트로 표현할 수 없습니다.',\n    edit_attribute_name: '이름 바꾸기',\n    duplicate_attribute_name_title: '열 이름 변경에 실패하였습니다.',\n    duplicate_attribute_name_content: '같은 이름의 열이 존재합니다.',\n    fail_save_table: '테이블 저장에 실패하였습니다.',\n    duplicate_table_name_content: '같은 이름의 테이블이 존재합니다.',\n    saved_table_title: '저장되었습니다.',\n    saved_table_content: '테이블과 차트의 정보가 저장되었습니다.',\n    empty_table_name_content: '테이블 이름은 빈 칸이 될 수 없습니다',\n    do_not_delete_row: '행을 삭제할 수 없습니다.',\n    rows_cannot_less_one: '테이블에는 한 개 이상의 행이 있어야합니다.',\n};\nLang.SharePolicy = {\n    title: '엔트리 작품/게시물 공유 가이드',\n};\n\nLang.Support = ['ko', 'en', 'vn', 'jp'];\nif (typeof exports == 'object') exports.Lang = Lang;\n"
  },
  {
    "path": "extern/lang/en.js",
    "content": "var Lang = {};\nLang.category = {\n    name: 'en',\n};\nLang.type = 'en';\nLang.fallbackType = 'ko';\nLang.ko = '한국어';\nLang.en = 'English';\nLang.jp = '日本語';\nLang.vn = 'tiếng Việt';\nLang.Command = {\n    1: '장면 추가하기',\n    2: '장면 삭제하기',\n    3: '장면 이름 수정',\n    4: '장면 순서 변경',\n    5: '장면 선택',\n    101: '블록 쓰레드 추가하기',\n    102: '블록 쓰레드 삭제하기',\n    103: '블록 삭제하기',\n    104: '블록 복구하기',\n    105: '블록 끼워넣기',\n    106: '블록 분리하기',\n    107: '블록 이동하기',\n    108: '블록 복제하기',\n    109: '블록 복제 취소하기',\n    110: '스크롤',\n    111: '블록 필드값 수정',\n    117: '블록 쓰레드 추가하기',\n    118: '블록 끼워넣기',\n    119: '블록 이동하기',\n    120: '블록 분리하기',\n    121: '블록 이동하기',\n    122: '블록 끼워넣기',\n    123: '블록 끼워넣기',\n    201: '오브젝트 선택하기',\n    202: '오브젝트 수정 버튼 클릭',\n    203: '오브젝트 그림 추가',\n    204: '오브젝트 그림 삭제',\n    205: '오브젝트 소리 추가',\n    206: '오브젝트 소리 삭제',\n    207: '오브젝트 이름 수정',\n    208: '오브젝트 추가',\n    209: '오브젝트 삭제',\n    210: '오브젝트 추가 버튼 클릭',\n    211: '오브젝트 x 수정',\n    212: '오브젝트 y 수정',\n    213: '오브젝트 size 수정',\n    214: '오브젝트 방향 수정',\n    215: '오브젝트 이동 방향 수정',\n    216: '오브젝트 회전방식 수정',\n    217: '엔터티 모델 동기화',\n    301: 'do',\n    302: 'undo',\n    303: 'redo',\n    401: '그림 수정하기',\n    402: '그림 수정 취소하기',\n    403: '그림 수정하기',\n    404: '그림 수정 취소하기',\n    405: '글상자 수정',\n    501: '시작하기',\n    502: '정지하기',\n    601: '컨테이너 오브젝트 선택하기',\n    701: '모드 바꾸기',\n    702: '모양 추가 버튼 클릭',\n    703: '소리 추가 버튼 클릭',\n    801: '속성 필터 선택하기',\n    802: '변수 추가하기 버튼 클릭',\n    803: '변수 추가하기',\n    804: '변수 삭제하기',\n    805: '변수 이름 설정',\n    806: '신호 이름 설정',\n    807: '신호 추가',\n    808: '신호 삭제',\n    809: '변수 스코프 정하기',\n    810: '변수 글로벌 체크',\n    811: '변수 보이기 체크',\n    812: '변수 기본값 설정',\n    813: '변수 슬라이드로 체크',\n    814: '변수 최솟값 정하기',\n    815: '변수 최댓값 정하기',\n    816: '리스트 추가 버튼 클릭',\n    817: '리스트 추가',\n    818: '리스트 삭제',\n    819: '리스트 이름 정하기',\n    820: '리스트 스코프 정하기',\n    821: '리스트 글로벌 체크',\n    822: '리스트 보이기 체크',\n    823: '리스트 길이 변경',\n    824: '리스트 기본값 설정',\n    825: '메세지 수정 enable',\n    826: '변수 수정 enable',\n    827: '리스트 수정 enable',\n    828: '변수 이름 정하기',\n    829: '리스트 이름 정하기',\n    900: '모달 닫기',\n    1001: '함수 생성 시작',\n    1002: '함수 수정 시작',\n    1003: '함수 수정 취소',\n    1004: '함수 생성',\n    1005: '함수 업데이트',\n};\nLang.CommandTooltip = {\n    101: '블록 쓰레드 추가하기',\n    102: '블록 쓰레드 삭제하기',\n    103: '블록 삭제하기',\n    104: '블록 복구하기',\n    105: '코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    106: '블록 분리하기',\n    107: '블록 이동하기',\n    108: '블록 복제하기',\n    109: '블록 복제 취소하기',\n    110: '스크롤',\n    111: '블록 필드값 수정@@값을 입력하기 위해 이곳을 클릭합니다.$$선택지를 클릭합니다.$$선택지를 클릭합니다.$$&value&을 입력합니다.$$&value&를 선택합니다.$$키보드 &value&를 누릅니다.',\n    117: '블록 쓰레드 추가하기',\n    118: '블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    119: '블록 가져오기@@빈 곳에 블록을 끌어다 놓습니다.',\n    120: '블록 분리하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.',\n    121: '블록 이동하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.',\n    122: '블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    123: '코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    201: '오브젝트 선택하기',\n    301: 'do',\n    302: 'undo',\n    303: 'redo',\n    401: '그림 수정하기',\n    402: '그림 수정 취소하기',\n    403: '그림 수정하기',\n    404: '그림 수정 취소하기',\n    501: '실행하기@@<b>[시작하기]</b>를 누릅니다.',\n    502: '정지하기@@<b>[정지하기]</b>를 누릅니다.',\n    601: '컨테이너 오브젝트 선택하기',\n    701: '모드 바꾸기',\n    702: '모양 추가하기@@<b>모양추가</b>를 클릭합니다.',\n    703: '소리 추가하기@@<b>소리추가</b>를 클릭합니다.',\n    801: '변수 속성창 필터 선택하기',\n    802: '변수 추가하기@@<b>[변수 추가]</b>를 클릭합니다.',\n    803: '변수 추가하기@@<b>[확인]</b>을 클릭합니다.',\n    804: '변수 삭제하기@@이 버튼을 눌러 변수를 삭제합니다.',\n    805: '변수 이름 설정',\n    1101: '확장 블록 추가하기@@<b>확장 블록 블러오기</b>를 클릭합니다.',\n};\nLang.Blocks = {\n    START_when_object_click: 'When object clicked',\n    START_when_object_click_canceled: 'When object click released',\n    START_when_run_button_click: 'When run',\n    START_when_scene_start: 'When scene was started',\n    START_when_some_key_click: 'When press some key',\n    TEXT_text: 'Entry',\n    TEXT_text_append_1: 'After writing that',\n    TEXT_text_append_2: '',\n    TEXT_text_flush: 'Remove all text',\n    TEXT_text_prepend_1: 'Add',\n    TEXT_text_prepend_2: 'in front of that',\n    TEXT_text_write_1: 'Writing that',\n    TEXT_text_write_2: '',\n    VARIABLE_add_value_to_list: '',\n    VARIABLE_add_value_to_list_3: '',\n    VARIABLE_ask_and_wait_1: 'Ask',\n    VARIABLE_ask_and_wait_2: 'and wait',\n    VARIABLE_change_value_list_index: '',\n    VARIABLE_change_value_list_index_2: '',\n    VARIABLE_change_value_list_index_4: '',\n    VARIABLE_change_variable_1: 'Plus to',\n    VARIABLE_change_variable_2: 'by',\n    VARIABLE_change_variable_3: '',\n    VARIABLE_change_variable_name: 'Rename variable',\n    VARIABLE_get_variable_2: '',\n    VARIABLE_get_y: 'Y Coordinate',\n    VARIABLE_hide_list: '',\n    VARIABLE_hide_list_2: '',\n    VARIABLE_hide_variable_1: 'Hide variable',\n    VARIABLE_hide_variable_2: 'value',\n    VARIABLE_insert_value_to_list: '',\n    VARIABLE_insert_value_to_list_3: '',\n    VARIABLE_length_of_list: '',\n    VARIABLE_length_of_list_2: '',\n    VARIABLE_list: '',\n    VARIABLE_make_variable: 'Make variable',\n    VARIABLE_list_option_first: 'First',\n    VARIABLE_list_option_last: 'Last',\n    VARIABLE_list_option_random: 'Randomly',\n    VARIABLE_remove_value_from_list: '',\n    VARIABLE_remove_value_from_list_3: '',\n    VARIABLE_remove_variable: 'Remove variable',\n    VARIABLE_set_variable_1: 'Set',\n    VARIABLE_set_variable_2: 'to',\n    VARIABLE_set_variable_3: '',\n    VARIABLE_show_list: '',\n    VARIABLE_show_list_2: '',\n    VARIABLE_show_variable_1: 'Show variable',\n    VARIABLE_show_variable_2: 'value',\n    VARIABLE_value_of_index_from_list: '',\n    VARIABLE_value_of_index_from_list_2: '',\n    HAMSTER_hand_found: 'hand found?',\n    HAMSTER_move_forward_once: 'move forward once on board',\n    HAMSTER_turn_once_1: 'turn',\n    HAMSTER_turn_once_2: 'once on board',\n    HAMSTER_move_forward: 'move forward',\n    HAMSTER_move_backward: 'move backward',\n    HAMSTER_turn_around_1: 'turn',\n    HAMSTER_turn_around_2: '',\n    HAMSTER_move_forward_for_secs_1: 'move forward for',\n    HAMSTER_move_forward_for_secs_2: 'secs',\n    HAMSTER_move_backward_for_secs_1: 'move backward',\n    HAMSTER_move_backward_for_secs_2: 'secs',\n    HAMSTER_turn_for_secs_1: 'turn',\n    HAMSTER_turn_for_secs_2: 'for',\n    HAMSTER_turn_for_secs_3: 'secs',\n    HAMSTER_change_both_wheels_by_1: 'change wheel by left:',\n    HAMSTER_change_both_wheels_by_2: 'right:',\n    HAMSTER_change_both_wheels_by_3: '',\n    HAMSTER_set_both_wheels_to_1: 'set wheel to left:',\n    HAMSTER_set_both_wheels_to_2: 'right:',\n    HAMSTER_set_both_wheels_to_3: '',\n    HAMSTER_change_wheel_by_1: 'change',\n    HAMSTER_change_wheel_by_2: 'wheel by',\n    HAMSTER_change_wheel_by_3: '',\n    HAMSTER_set_wheel_to_1: 'set',\n    HAMSTER_set_wheel_to_2: 'wheel to',\n    HAMSTER_set_wheel_to_3: '',\n    HAMSTER_follow_line_using_1: 'follow',\n    HAMSTER_follow_line_using_2: 'line using',\n    HAMSTER_follow_line_using_3: 'floor sensor',\n    HAMSTER_follow_line_until_1: 'follow',\n    HAMSTER_follow_line_until_2: 'line until',\n    HAMSTER_follow_line_until_3: 'intersection',\n    HAMSTER_left_intersection: 'left',\n    HAMSTER_right_intersection: 'right',\n    HAMSTER_front_intersection: 'front',\n    HAMSTER_rear_intersection: 'rear',\n    HAMSTER_set_following_speed_to_1: 'set following speed to',\n    HAMSTER_set_following_speed_to_2: '',\n    HAMSTER_stop: 'stop',\n    HAMSTER_set_led_to_1: 'set',\n    HAMSTER_set_led_to_2: 'led to',\n    HAMSTER_set_led_to_3: '',\n    HAMSTER_clear_led_1: 'clear',\n    HAMSTER_clear_led_2: 'led',\n    HAMSTER_beep: 'beep',\n    HAMSTER_change_buzzer_by_1: 'change buzzer by',\n    HAMSTER_change_buzzer_by_2: '',\n    HAMSTER_set_buzzer_to_1: 'set buzzer to',\n    HAMSTER_set_buzzer_to_2: '',\n    HAMSTER_clear_buzzer: 'clear buzzer',\n    HAMSTER_play_note_for_1: 'play note',\n    HAMSTER_play_note_for_2: '',\n    HAMSTER_play_note_for_3: 'for',\n    HAMSTER_play_note_for_4: 'beats',\n    HAMSTER_rest_for_1: 'rest for',\n    HAMSTER_rest_for_2: 'beats',\n    HAMSTER_change_tempo_by_1: 'change tempo by',\n    HAMSTER_change_tempo_by_2: '',\n    HAMSTER_set_tempo_to_1: 'set tempo to',\n    HAMSTER_set_tempo_to_2: 'bpm',\n    HAMSTER_set_port_to_1: 'set port',\n    HAMSTER_set_port_to_2: 'to',\n    HAMSTER_set_port_to_3: '',\n    HAMSTER_change_output_by_1: 'change output',\n    HAMSTER_change_output_by_2: 'by',\n    HAMSTER_change_output_by_3: '',\n    HAMSTER_set_output_to_1: 'set output',\n    HAMSTER_set_output_to_2: 'to',\n    HAMSTER_set_output_to_3: '',\n    ROBOID_buzzer: 'buzzer',\n    ROBOID_color_pattern: 'color pattern',\n    ROBOID_head_color: 'head color',\n    ROBOID_left_wheel: 'left wheel',\n    ROBOID_note: 'note',\n    ROBOID_right_wheel: 'right wheel',\n    ALBERT_hand_found: 'hand found?',\n    ALBERT_is_oid_1: 'oid is',\n    ALBERT_is_oid_2: '',\n    ALBERT_is_oid_3: '?',\n    ALBERT_front_oid: 'front',\n    ALBERT_back_oid: 'back',\n    ALBERT_sensor_battery: 'battery',\n    ALBERT_move_forward: 'move forward',\n    ALBERT_move_backward: 'move backward',\n    ALBERT_turn_around_1: 'turn',\n    ALBERT_turn_around_2: '',\n    ALBERT_move_forward_for_secs_1: 'move forward for',\n    ALBERT_move_forward_for_secs_2: 'secs',\n    ALBERT_move_backward_for_secs_1: 'move backward for',\n    ALBERT_move_backward_for_secs_2: 'secs',\n    ALBERT_turn_for_secs_1: 'turn',\n    ALBERT_turn_for_secs_2: 'for',\n    ALBERT_turn_for_secs_3: 'secs',\n    ALBERT_turn_left: 'left',\n    ALBERT_turn_right: 'right',\n    ALBERT_change_both_wheels_by_1: 'change wheels by left:',\n    ALBERT_change_both_wheels_by_2: 'right:',\n    ALBERT_change_both_wheels_by_3: '',\n    ALBERT_left_wheel: 'left',\n    ALBERT_right_wheel: 'right',\n    ALBERT_both_wheels: 'both',\n    ALBERT_set_both_wheels_to_1: 'set wheels to left:',\n    ALBERT_set_both_wheels_to_2: 'right:',\n    ALBERT_set_both_wheels_to_3: '',\n    ALBERT_change_wheel_by_1: 'change',\n    ALBERT_change_wheel_by_2: 'wheel by',\n    ALBERT_change_wheel_by_3: '',\n    ALBERT_set_wheel_to_1: 'set',\n    ALBERT_set_wheel_to_2: 'wheel to',\n    ALBERT_set_wheel_to_3: '',\n    ALBERT_stop: 'stop',\n    ALBERT_set_board_size_to_1: 'set board size to width:',\n    ALBERT_set_board_size_to_2: 'height:',\n    ALBERT_set_board_size_to_3: '',\n    ALBERT_move_to_x_y_1: 'move to x:',\n    ALBERT_move_to_x_y_2: 'y:',\n    ALBERT_move_to_x_y_3: 'on board',\n    ALBERT_set_orientation_to_1: 'set orientation to',\n    ALBERT_set_orientation_to_2: 'degrees on board',\n    ALBERT_set_eye_to_1: 'set',\n    ALBERT_set_eye_to_2: 'eye to',\n    ALBERT_set_eye_to_3: '',\n    ALBERT_left_eye: 'left',\n    ALBERT_right_eye: 'right',\n    ALBERT_both_eyes: 'both',\n    ALBERT_clear_eye_1: 'clear',\n    ALBERT_clear_eye_2: 'eye',\n    ALBERT_body_led_1: 'turn',\n    ALBERT_body_led_2: 'body led',\n    ALBERT_front_led_1: 'turn',\n    ALBERT_front_led_2: 'front led',\n    ALBERT_color_cyan: 'cyan',\n    ALBERT_color_magenta: 'magenta',\n    ALBERT_color_white: 'white',\n    ALBERT_color_red: 'red',\n    ALBERT_color_yellow: 'yellow',\n    ALBERT_color_green: 'green',\n    ALBERT_color_blue: 'blue',\n    ALBERT_turn_body_led_1: 'turn',\n    ALBERT_turn_body_led_2: 'body led',\n    ALBERT_turn_front_led_1: 'turn',\n    ALBERT_turn_front_led_2: 'front led',\n    ALBERT_turn_on: 'on',\n    ALBERT_turn_off: 'off',\n    ALBERT_beep: 'beep',\n    ALBERT_change_buzzer_by_1: 'change buzzer by',\n    ALBERT_change_buzzer_by_2: '',\n    ALBERT_set_buzzer_to_1: 'set buzzer to',\n    ALBERT_set_buzzer_to_2: '',\n    ALBERT_clear_buzzer: 'clear buzzer',\n    ALBERT_play_note_for_1: 'play note',\n    ALBERT_play_note_for_2: \"',\",\n    ALBERT_play_note_for_3: 'for',\n    ALBERT_play_note_for_4: 'beats',\n    ALBERT_rest_for_1: 'rest for',\n    ALBERT_rest_for_2: 'beats',\n    ALBERT_change_tempo_by_1: 'change tempo by',\n    ALBERT_change_tempo_by_2: '',\n    ALBERT_set_tempo_to_1: 'set tempo to',\n    ALBERT_set_tempo_to_2: 'bpm',\n    VARIABLE_variable: 'variable',\n    robotis_common_case_01: '(을)를',\n    robotis_common_set: 'the output value',\n    robotis_common_value: 'Value',\n    robotis_common_cm: 'Controller',\n    robotis_common_play_buzzer: 'Play',\n    robotis_common_play_motion: 'Play',\n    robotis_common_motion: 'Motion',\n    robotis_common_index_number: 'Number',\n    robotis_common_left: 'Left',\n    robotis_common_right: 'Right',\n    robotis_common_minute: 'minute(s)',\n    robotis_cm_custom: 'Custom address',\n    robotis_cm_clear_sound_detected: 'Initialize the final number of sound detection',\n    robotis_cm_buzzer_index: 'Scale index',\n    robotis_cm_buzzer_melody: 'Melody',\n    robotis_cm_led_1: 'LED 1',\n    robotis_cm_led_4: 'LED 4',\n    robotis_carCont_aux_motor_speed_1: 'Speed of decelerating motor',\n    robotis_carCont_aux_motor_speed_2: ', the output value',\n    robotis_carCont_calibration_1: 'Value of the infrared sensor calibration ',\n    robotis_openCM70_aux_motor_speed_1: 'Speed of decelerating motor',\n    robotis_openCM70_aux_motor_speed_2: ', Set as',\n    robotis_openCM70_aux_servo_mode_1: 'Servo motor mode',\n    robotis_openCM70_aux_servo_speed_1: 'Servo motor speed',\n    robotis_openCM70_aux_servo_speed_2: ', the output value',\n    robotis_openCM70_aux_servo_position_1: 'Position of servo motor',\n    robotis_openCM70_aux_led_module_1: 'LED module',\n    robotis_openCM70_aux_custom_1: 'User device',\n    XBOT_digital: 'Digital',\n    XBOT_analog: 'Analog',\n    XBOT_Value: 'Ouput Value',\n    XBOT_pin_OutputValue: 'PIN, Ouput Value',\n    XBOT_Servo: 'Servo Motor',\n    XBOT_angle: ', Angle',\n    XBOT_DC: 'Wheel(DC) Motor',\n    XBOT_speed: ', Speed',\n    XBOT_rightSpeed: 'Wheel(DC) Motor Right(2) Speed:',\n    XBOT_leftSpeed: 'Left(1) Speed:',\n    XBOT_RGBLED_R: 'RGB LED Color from Red',\n    XBOT_RGBLED_G: 'Green',\n    XBOT_RGBLED_B: 'Blue',\n    XBOT_RGBLED_color: 'RGB LED Color from',\n    XBOT_set: ' ',\n    XBOT_melody_ms: 'sec of Melody Playing',\n    XBOT_Line: 'th Line',\n    XBOT_outputValue: 'Text',\n    roborobo_num_analog_value_1: 'Analog',\n    roborobo_num_analog_value_2: 'Sensor Value',\n    roborobo_get_digital_value_1: 'Digital',\n    roborobo_num_pin_1: 'Digital',\n    roborobo_num_pin_2: 'Pin',\n    roborobo_input_mode: 'Input',\n    roborobo_output_mode: 'Output',\n    roborobo_pwm_mode: 'PWM',\n    roborobo_servo_mode: 'Servo',\n    roborobo_color: 'Color Sensor ',\n    roborobo_color_detected: ' Detected ',\n    roborobo_degree: ' ˚',\n    robotori_digital: 'Digital',\n    robotori_pin_OutputValue: 'Output Value',\n    robotori_analog: 'Analog',\n    robotori_Servo: 'Servo Motor',\n    robotori_DC: 'DC Motor',\n    robotori_DC_select: 'direction',\n    VARIABLE_is_included_in_list: '',\n    VARIABLE_is_included_in_list_3: '',\n    CALC_calc_operation_natural: 'integer value',\n    MOVING_locate_object_time_1: 'factorial value',\n    MOVING_locate_object_time_2: 'seconds to the',\n    MOVING_locate_object_time_3: '',\n    FLOW_repeat_while_true_1: 'Repeat',\n    FLOW_repeat_while_true_2: ' ',\n    TUT_when_start: '',\n    TUT_move_once: '',\n    TUT_rotate_left: '',\n    TUT_rotate_right: '',\n    TUT_jump_barrier: '',\n    TUT_repeat_tutorial_1: '',\n    TUT_repeat_tutorial_2: '',\n    TUT_if_barrier_1: '',\n    TUT_if_barrier_2: '',\n    TUT_if_conical_1: '',\n    TUT_if_conical_2: '',\n    TUT_repeat_until: '',\n    TUT_repeat_until_gold: '',\n    TUT_declare_function: '',\n    TUT_call_function: '',\n    BRUSH_change_brush_transparency_1: 'Change transparency by',\n    BRUSH_change_brush_transparency_2: '%',\n    BRUSH_set_brush_transparency_1: 'Set transparency to',\n    BRUSH_set_brush_transparency_2: '%',\n    CALC_char_at_3: '',\n    CALC_length_of_string_2: '',\n    CALC_reverse_of_string_2: '',\n    CALC_substring_4: '',\n    CALC_replace_string_4: '',\n    CALC_change_string_case_1: '',\n    CALC_index_of_string_3: '',\n    MOVING_add_direction_by_angle_time_explain_1: 'For',\n    MOVING_direction_relative_duration_1: 'For',\n    MOVING_direction_relative_duration_2: 'secs set direction to',\n    MOVING_direction_relative_duration_3: '',\n    SOUND_sound_from_to_1: 'Play',\n    SOUND_sound_from_to_2: 'sound from',\n    SOUND_sound_from_to_3: 'to',\n    SOUND_sound_from_to_4: 'secs',\n    SOUND_sound_from_to_and_wait_1: 'Play',\n    SOUND_sound_from_to_and_wait_2: 'sound from',\n    SOUND_sound_from_to_and_wait_3: 'to',\n    SOUND_sound_from_to_and_wait_4: 'secs and wait',\n    CALC_quotient_and_mod_1: '',\n    CALC_quotient_and_mod_4: ' ',\n    CALC_choose_project_timer_action_1: '',\n    LOOKS_change_object_index_1: 'bring to',\n    LOOKS_change_object_index_2: '',\n    copy_block: 'copy block(s)',\n    delete_block: 'delete block(s)',\n    bark_dog: 'dog barking',\n    DUMMY: '더미',\n    coconut_stop_motor: 'stop motor',\n    coconut_move_motor: 'move motor',\n    coconut_turn_motor: 'turn',\n    coconut_move_outmotor: 'external motor',\n    coconut_move_speed_1: '0',\n    coconut_move_speed_2: '50',\n    coconut_move_speed_3: '100',\n    coconut_move_speed_4: '150',\n    coconut_move_speed_5: '255',\n    coconut_color_black: 'Black',\n    coconut_beep: 'buzzer on',\n    coconut_clear_buzzer: 'buzzer off',\n    modi_speaker_F_DO_5: 'DO 5',\n    modi_speaker_F_DO_S_5: 'DO #5',\n    modi_speaker_F_MI_5: 'MI 5',\n    modi_speaker_F_PA_7: 'FA 7',\n    modi_speaker_F_PA_S_7: 'FA #7',\n    modi_speaker_F_RA_7: 'LA 7',\n    modi_speaker_F_RA_S_7: 'LA #7',\n    modi_speaker_F_RE_5: 'RE 5',\n    modi_speaker_F_RE_S_5: 'LA #5',\n    modi_speaker_F_SOL_7: 'SOL 7',\n    modi_speaker_F_SOL_S_7: 'SOL #7',\n    modi_speaker_F_SO_7: 'TI 7',\n    ALTINO_Line: 'line',\n    ALTINO_REMOTE: 'remote control',\n    ALTINO_STVAR: 'steering potentiometer',\n    ALTINO_Value: 'output value',\n    ALTINO_dot_display_1: 'one char',\n    ALTINO_dot_display_2: 'display',\n    ALTINO_leftWheel: 'left',\n    ALTINO_melody_ms: 'play',\n    ALTINO_outputValue: 'output',\n    ALTINO_rightWheel: 'right',\n    ALTINO_set: ' display',\n    FUNBOARD_led_color_str: 'color  ',\n    FUNBOARD_led_off_str: 'Turn off the LED',\n    FUNBOARD_led_on_str: 'Turn on the LED',\n    funboard_dotmatrix_set_off: 'off',\n    funboard_dotmatrix_set_on: 'on',\n    copy_paste_comment: 'Copy & paste the memo',\n    copy_comment: 'Copy the memo',\n    delete_comment: 'Delete the memo',\n    fold_comment: 'Hide the memo',\n    open_comment: 'Show the memo',\n    separate_comment: 'Take the memo off',\n    video_pose_model: 'Human model',\n    video_face_model: 'Face model',\n    video_object_model: 'Object model',\n    ALBERT_sensor_acceleration_x: 'x acceleration',\n    ALBERT_sensor_acceleration_y: 'y acceleration',\n    ALBERT_sensor_acceleration_z: 'z acceleration',\n    ALBERT_sensor_front_oid: 'front oid',\n    ALBERT_sensor_back_oid: 'back oid',\n    ALBERT_sensor_position_x: 'x position',\n    ALBERT_sensor_position_y: 'y position',\n    ALBERT_sensor_orientation: 'orientation',\n    ALBERT_sensor_temperature: 'temperature',\n    ALBERT_sensor_signal_strength: 'signal strength',\n    ALBERT_sensor_left_proximity: 'left proximity',\n    ALBERT_sensor_right_proximity: 'right proximity',\n    ALBERT_sensor_light: 'light',\n    chocopi_port: 'P',\n    coconut_sensor_temperature: 'temperature',\n    coconut_sensor_acceleration_x: 'X-Axis Accelerometer',\n    coconut_sensor_acceleration_y: 'Y-Axis Accelerometer',\n    coconut_sensor_acceleration_z: 'Z-Axis Accelerometer',\n    coconut_sensor_left_proximity: 'left IR distance',\n    coconut_sensor_right_proximity: 'right IR distance',\n    coconut_sensor_left_floor: 'left line tracer',\n    coconut_sensor_right_floor: 'right line tracer',\n    coconut_sensor_light: 'light sensor',\n    HAMSTER_sensor_temperature: 'temperature',\n    HAMSTER_sensor_input_a: 'input A',\n    HAMSTER_sensor_input_b: 'input B',\n    HAMSTER_sensor_acceleration_x: 'x acceleration',\n    HAMSTER_sensor_acceleration_y: 'y acceleration',\n    HAMSTER_sensor_acceleration_z: 'z acceleration',\n    HAMSTER_sensor_left_proximity: 'left proximity',\n    HAMSTER_sensor_right_proximity: 'right proximity',\n    HAMSTER_sensor_left_floor: 'left floor',\n    HAMSTER_sensor_right_floor: 'right floor',\n    HAMSTER_sensor_light: 'light',\n    jdkit_joystick_leftleftright: '왼쪽 좌우',\n    jdkit_joystick_lefttopbottom: '왼쪽 상하',\n    jdkit_joystick_rightleftright: '오른쪽 좌우',\n    jdkit_joystick_righttopbottom: '오른쪽 상하',\n    ROBOID_color_number: 'color number',\n    ROBOID_floor: 'floor',\n    ROBOID_button: 'button',\n    ROBOID_acceleration_x: 'x acceleration',\n    ROBOID_acceleration_y: 'y acceleration',\n    ROBOID_acceleration_z: 'z acceleration',\n    learn_popup_title: 'Input Data',\n    arduino_noti_text:\n        'HW connection is\\nonly supported on desktop.\\n \\nPlease contact HW\\nmanufacturer for tablet.',\n    arduino_lite_alert:\n        'Device not found.\\nPlease check if firmware\\nis installed on device,\\nor if PC and device are connected.',\n    arduino_lite_reconnect: 'Retry',\n    arduino_lite_download_firmware: 'Download firmware',\n    arduino_lite_download_driver: 'Download Driver',\n    arduino_lite_connect: 'Connect through web',\n    arduino_lite_disconnect: 'Cancel',\n    arduino_lite_guide: '• connection guide',\n    arduino_lite_connected_noti: 'Please save the project\\nwith the device selected.',\n    ARDUINO_download_connector: '• Download Connector',\n    download_guide: '• Download Guide',\n    ARDUINO_download_source: '• Entry Arduino code',\n    ARDUINO_connected: 'Hardware connected',\n    ARDUINO_connect: '* Connect hardware',\n    ARDUINO_reconnect: 'Connect HW',\n    hardware_connect_helper: 'Help (Korean Only)',\n    hardware_noti_installed: 'When using connection program',\n    hardware_noti_not_installed: 'When using web browser',\n    hardware_device_name_title: 'Name:',\n    hardware_device_name_title_robot: 'Name:',\n    hardware_device_name_content: 'None',\n    hardware_program_download: 'Download program',\n    hardware_connected_noti: 'Please check connection program.',\n    ROBOT_reconnect: 'Connect Robot',\n    ARDUINO_open_connector: 'Open program',\n    ARDUINO_cloud_pc_connector: 'Connect to Cloud PC',\n    CALC_get_x_coordinate: 'X Coordinate',\n    CALC_get_y_coordinate: 'Y Coordinate',\n    CALC_get_angle: 'Angle value',\n    CALC_rotation_value: 'rotation value',\n    CALC_direction_value: 'direction value',\n    CALC_calc_mod_3: 'the rest of',\n    CALC_timer_visible_1: '',\n    CALC_timer_visible_show: 'Show',\n    CALC_timer_visible_hide: 'Hide',\n    CALC_timer_visible_2: 'Timer',\n    FUNC: 'Function',\n    color: 'color',\n    brightness: 'brightness',\n    opacity: 'Opacity',\n    transparency: 'transparency',\n    JUDGEMENT_boolean_and: 'AND',\n    JUDGEMENT_boolean_or: 'OR',\n    JUDGEMENT_true: 'True',\n    JUDGEMENT_false: 'False',\n    wall: 'wall',\n    START_press_some_key_up: 'Up',\n    START_press_some_key_down: 'Down',\n    START_press_some_key_right: 'Right',\n    START_press_some_key_left: 'Left',\n    START_press_some_key_space: 'Space',\n    START_press_some_key_enter: 'Enter',\n    START_press_some_key_back_space: 'Backspace',\n    START_press_some_key_back_slash: 'Backslash',\n    SCENE_when_scene_start: 'When scene started',\n    SCENE_start_scene_1: 'Start',\n    SCENE_start_scene_2: 'scene',\n    SCENE_start_neighbor_scene_1: 'Start',\n    SCENE_start_neighbor_scene_2: 'scene',\n    SCENE_start_scene_pre: 'prev',\n    SCENE_start_scene_next: 'next',\n    FUNCTION_explanation_1: 'name',\n    FUNCTION_character_variable: 'string/number',\n    FUNCTION_logical_variable: 'logical variable',\n    FUNCTION_function: 'function',\n    FUNCTION_define: 'Define function',\n    FLOW_repeat_while_true_until: 'until',\n    FLOW_repeat_while_true_while: 'while',\n    FLOW_stop_object_all: 'All objects',\n    FLOW_stop_object_this_object: 'This',\n    FLOW_stop_object_this_thread: 'This code',\n    FLOW_stop_object_other_thread: 'Other block of this object',\n    FLOW_stop_object_other_objects: 'Other object',\n    speak: 'Speak',\n    think: 'Think',\n    block_hi: 'Hi',\n    LOOKS_change_shape_next: 'next',\n    LOOKS_change_shape_prev: 'previous',\n    LOOKS_change_object_index_sub_1: 'front',\n    LOOKS_change_object_index_sub_2: 'forward',\n    LOOKS_change_object_index_sub_3: 'backward',\n    LOOKS_change_object_index_sub_4: 'back',\n    entry: 'Entry',\n    JUDGEMENT_is_clicked: 'mouse clicked?',\n    JUDGEMENT_is_object_clicked: 'object clicked?',\n    JUDGEMENT_is_type_1: 'is',\n    JUDGEMENT_is_type_2: '?',\n    is_type_number: 'number',\n    JUDGEMENT_is_press_some_key_2: 'key pressed?',\n    JUDGEMENT_reach_something_1: 'touching',\n    JUDGEMENT_reach_something_2: '?',\n    JUDGEMENT_boolean_not_1: 'is not',\n    JUDGEMENT_boolean_not_2: '',\n    JUDGEMENT_is_boost_mode: 'is the boost mode on?',\n    CALC_calc_rand_1: 'random number between',\n    CALC_calc_rand_2: 'and',\n    CALC_calc_rand_3: '',\n    CALC_coordinate_mouse_1: 'mouse pointer',\n    CALC_coordinate_mouse_2: 'coordinate',\n    CALC_coordinate_object_1: '',\n    CALC_coordinate_object_2: 'of',\n    CALC_coordinate_x_value: 'x coordinate',\n    CALC_coordinate_y_value: 'y coordinate',\n    CALC_coordinate_rotation_value: 'rotation',\n    CALC_coordinate_direction_value: 'direction',\n    CALC_coordinate_size_value: 'size',\n    CALC_picture_index: 'shape number',\n    CALC_picture_name: 'shape name',\n    CALC_get_sound_volume: 'Volume',\n    CALC_quotient_and_mod_1: '',\n    CALC_quotient_and_mod_2: 'of',\n    CALC_quotient_and_mod_3: '/',\n    CALC_quotient_and_mod_sub_1: 'quotient',\n    CALC_quotient_and_mod_sub_2: 'remainder',\n    CALC_calc_operation_of_1: '',\n    CALC_calc_operation_of_2: 'of',\n    CALC_calc_operation_square: 'square',\n    CALC_calc_operation_root: 'root',\n    CALC_calc_operation_sin: 'sin',\n    CALC_calc_operation_cos: 'cos',\n    CALC_calc_operation_tan: 'tan',\n    CALC_calc_operation_asin: 'asin',\n    CALC_calc_operation_acos: 'acos',\n    CALC_calc_operation_atan: 'atan',\n    CALC_calc_operation_log: 'log',\n    CALC_calc_operation_ln: 'natural log',\n    CALC_calc_operation_unnatural: 'decimal value',\n    CALC_calc_operation_floor: 'floor value',\n    CALC_calc_operation_ceil: 'ceil value',\n    CALC_calc_operation_round: 'round value',\n    CALC_calc_operation_factorial: 'factorial value',\n    CALC_calc_operation_abs: 'absolute value',\n    CALC_get_timer_value: 'timer value',\n    CALC_choose_project_timer_action_sub_1: 'Start',\n    CALC_choose_project_timer_action_sub_2: 'Stop',\n    CALC_choose_project_timer_action_sub_3: 'Reset',\n    CALC_choose_project_timer_action_2: 'timer',\n    CALC_get_date_1: 'current',\n    CALC_get_date_year: 'year',\n    CALC_get_date_month: 'month',\n    CALC_get_date_day: 'day',\n    CALC_get_date_hour: 'time(hour)',\n    CALC_get_date_minute: 'time(minutes)',\n    CALC_get_date_second: 'time(seconds)',\n    CALC_get_date_day_of_week: 'day of week',\n    CALC_get_date_2: '',\n    CALC_distance_something_1: 'distance to',\n    CALC_distance_something_2: '',\n    CALC_get_sound_duration_1: 'Length of',\n    CALC_get_sound_duration_2: 'sound',\n    CALC_length_of_string_1: 'length of',\n    CALC_reverse_of_string_1: 'reverse',\n    VARIABLE_combine_something_1: 'join',\n    VARIABLE_combine_something_2: 'and',\n    VARIABLE_combine_something_3: '',\n    CALC_char_at_1: '',\n    CALC_char_at_2: 'th letter of',\n    hi_entry: 'Hello Entry!',\n    hi_entry_en: 'Hello Entry!',\n    CALC_substring_1: 'substring of',\n    CALC_substring_2: 'from',\n    CALC_substring_3: 'to',\n    CALC_count_match_string_1: 'count of',\n    CALC_count_match_string_2: 'in',\n    CALC_index_of_string_1: 'index of',\n    CALC_index_of_string_2: 'in',\n    CALC_replace_string_1: 'replace',\n    CALC_replace_string_2: 'in',\n    CALC_replace_string_3: 'with',\n    hello: 'Hello',\n    nice: 'nice to meet you',\n    CALC_change_string_case_2: 'to',\n    CALC_change_string_case_sub_1: 'uppercase',\n    CALC_change_string_case_sub_2: 'lowercase',\n    CALC_change_string_case_3: ' ',\n    VARIABLE_get_canvas_input_value: 'response',\n    VARIABLE_get_variable_1: 'Value of',\n    VARIABLE_value_of_index_from_list_1: 'value of',\n    VARIABLE_value_of_index_from_list_3: 'th element',\n    VARIABLE_length_of_list_1: 'length of',\n    VARIABLE_is_included_in_list_1: 'is included in',\n    VARIABLE_is_included_in_list_2: 'value',\n    table_row: 'row',\n    table_col: 'column',\n    table_sum: 'sum',\n    table_max: 'max',\n    table_min: 'min',\n    table_avg: 'average',\n    table_stdev: 'standard deviation',\n    table_median: 'median',\n    date_yesterday: 'yesterday',\n    date_today: 'today',\n    date_tomorrow: 'tomorrow',\n    date_after_2_days: 'after 2 days',\n    date_after_3_days: 'after 3 days',\n    date_after_4_days: 'after 4 days',\n    date_after_5_days: 'after 5 days',\n    date_after_6_days: 'after 6 days',\n    tts_kind: 'kind',\n    tts_sweet: 'sweet',\n    tts_echo: 'echo',\n    tts_mischievous: 'mischievous',\n    tts_dainty: 'dainty',\n    tts_sabina: 'Witch',\n    tts_mammon: 'Demon',\n    tts_kitty: 'Kitty',\n    tts_doggy: 'Doggy',\n    tts_veryslow: 'very slow',\n    tts_slow: 'slow',\n    tts_normal: 'normal',\n    tts_fast: 'fast',\n    tts_veryfast: 'very fast',\n    tts_verylow: 'very low',\n    tts_low: 'low',\n    tts_high: 'high',\n    tts_veryhigh: 'very high',\n    korean: 'Korean',\n    english: 'English',\n    japan: 'Japanese',\n    korean_s: 'korean',\n    english_s: 'english',\n    japan_s: 'japanese',\n    chinese_simplified: 'Simplified Chinese',\n    chinese_traditional: 'Traditional Chinese',\n    spanish: 'Spanish',\n    french: 'French',\n    german: 'German',\n    russian: 'Russian',\n    portuguese: 'Portuguese',\n    thai: 'Thai',\n    vietnamese: 'Vietnamese',\n    indonesian: 'Indonesian',\n    hindi: 'Hindi',\n    AI_UTILIZE: 'AI',\n    video_show_video: 'Show',\n    video_hide_video: 'Hide',\n    video_brightness: 'brightness',\n    video_transparency: 'transparency',\n    video_left_right: 'horizontally',\n    video_top_bottom: 'vertically',\n    video_human: 'Human',\n    video_face: 'Face',\n    video_object: 'object',\n    video_start: 'Start',\n    video_end: 'Stop',\n    video_gender: 'gender',\n    video_age: 'age',\n    video_emotion: 'emotion',\n    video_motion_onself: 'this object',\n    video_motion_onscreen: 'screen',\n    video_motion_scale: 'Motion',\n    video_motion_direction_horizontal: 'X direction',\n    video_motion_direction_vertical: 'Y direction',\n    ALTINO_Steering_Angle_Left10: 'left10',\n    ALTINO_Steering_Angle_Left15: 'left15',\n    ALTINO_Steering_Angle_Left20: 'left20',\n    ALTINO_Steering_Angle_Right5: 'right5',\n    ALTINO_Steering_Angle_Right10: 'right10',\n    ALTINO_Steering_Angle_Right15: 'right15',\n    XBOT_D2_digitalInput: 'D2 Digital Input',\n    XBOT_D3_digitalInput: 'D3 Digital Input',\n    XBOT_D11_digitalInput: 'D11 Digital Input',\n    XBOT_CDS: 'Light Sensor Value',\n    XBOT_MIC: 'Mic Sensor Value',\n    XBOT_analog0: 'Analog PIN0 Value',\n    ALTINO_Steering_Angle_Right20: 'right20',\n    XBOT_analog1: 'Analog PIN1 Value',\n    XBOT_analog2: 'Analog PIN2 Value',\n    XBOT_analog3: 'Analog PIN3 Value',\n    XBOT_High: 'HI',\n    XBOT_Low: 'LO',\n    ALTINO_h: 'off',\n    XBOT_Head: 'Head(D8)',\n    ALTINO_c: 'do',\n    XBOT_ArmR: 'Right Arm(D9)',\n    XBOT_ArmL: 'Left Arm(D10)',\n    XBOT_rightWheel: 'Right',\n    ALTINO_c2: 'do#',\n    ALTINO_d: 're',\n    ALTINO_d2: 're#',\n    ALTINO_e: 'mi',\n    EXPANSION_WEATHER_sunny: 'sunny',\n    ALTINO_f: 'fa',\n    XBOT_leftWheel: 'Left',\n    ALTINO_f2: 'fa#',\n    XBOT_bothWheel: 'Both',\n    XBOT_c: 'C',\n    XBOT_d: 'D',\n    XBOT_e: 'E',\n    XBOT_f: 'F',\n    XBOT_g: 'G',\n    XBOT_a: 'A',\n    XBOT_b: 'B',\n    EXPANSION_WEATHER_partly_cloudy: 'partly cloudy',\n    EXPANSION_WEATHER_mostly_cloudy: 'mostly cloudy',\n    EXPANSION_WEATHER_cloudy: 'cloudy',\n    ALTINO_g: 'sol',\n    EXPANSION_WEATHER_rainy: 'rainy',\n    EXPANSION_WEATHER_sleet: 'sleet',\n    EXPANSION_WEATHER_snowy: 'snowy',\n    ALTINO_g2: 'sol#',\n    EXPANSION_WEATHER_finedust_good: 'good',\n    ALTINO_a: 'la',\n    EXPANSION_WEATHER_finedust_normal: 'normal',\n    ALTINO_a2: 'la#',\n    EXPANSION_WEATHER_finedust_bad: 'bad',\n    ALTINO_b: 'si',\n    EXPANSION_WEATHER_finedust_very_bad: 'very bad',\n    ALTINO_Led_Forward_Light: 'forward',\n    EXPANSION_WEATHER_lowest_temperature: 'the lowest temperature(℃)',\n    ALTINO_Led_Turn_Left_Light: 'left direction',\n    EXPANSION_WEATHER_highest_temperature: 'the highest temperature(℃)',\n    ALTINO_Led_Turn_Right_Light: 'right direction',\n    EXPANSION_WEATHER_humidity: 'humidity(%)',\n    ALTINO_Led_Brake_Light: 'brake',\n    EXPANSION_WEATHER_precipitation: 'precipitation(mm)',\n    ALTINO_Led_Reverse_Light: 'backward',\n    EXPANSION_WEATHER_precipitation_probability: 'precipitation probability(%)',\n    ALTINO_h2: 'on',\n    EXPANSION_WEATHER_wind_speed: 'wind speed(m/s)',\n    EXPANSION_WEATHER_temperature: 'temperature(℃)',\n    EXPANSION_WEATHER_finedust: 'concentration of fine dust(㎍)',\n    ardublock_motor_forward: 'Forward',\n    ardublock_motor_backward: 'Backward',\n    ARDUINO_on: 'Turn on',\n    ARDUINO_off: 'Turn off',\n    EXPANSION_FESTIVAL_title: 'Title',\n    EXPANSION_FESTIVAL_area: 'area',\n    EXPANSION_FESTIVAL_start_date: 'start date',\n    EXPANSION_FESTIVAL_end_date: 'end date',\n    EXPANSION_FESTIVAL_address: 'address',\n    EXPANSION_FESTIVAL_overview: 'overview',\n    EXPANSION_FESTIVAL_homepage: 'homepage',\n    behaviorConduct01001: 'Typhoon',\n    behaviorConduct01002: 'Flood',\n    behaviorConduct01003: 'Heavy rain',\n    behaviorConduct01004: 'Gale',\n    behaviorConduct01005: 'Heavy snow',\n    behaviorConduct01006: 'Cold wave',\n    behaviorConduct01007: 'Storm',\n    behaviorConduct01008: 'Dust storm',\n    behaviorConduct01009: 'Heatwave',\n    behaviorConduct01010: 'Drought',\n    behaviorConduct01011: 'Earthquake',\n    behaviorConduct01013: 'Tsunami',\n    behaviorConduct01014: 'Landslide',\n    behaviorConduct03002: 'First aid',\n    behaviorConduct03003: 'CPR',\n    behaviorConduct03004: 'Fire extinguishers use',\n    behaviorConduct03016: 'Fireplug use',\n    ROBOID_head: 'head',\n    behaviorConduct03005: 'Food poisoning',\n    behaviorConduct03006: 'Climbing safety',\n    behaviorConduct03008: 'Kidnapping·Missing',\n    behaviorConduct03009: 'SAE',\n    behaviorConduct03010: 'School violence',\n    behaviorConduct03011: 'Domestic Violence',\n    behaviorConduct03012: 'Detention and abduction',\n    behaviorConduct03013: 'Traffic Accident',\n    behaviorConduct03014: 'Elevator accident',\n    behaviorConduct03015: 'Fine dust',\n    behaviorConduct01001001: 'Before the typhoon comes',\n    behaviorConduct01001002: 'When the typhoon warning occurs',\n    behaviorConduct01001003: 'After the typhoon has passed',\n    behaviorConduct01002002: 'When the flood forecast occurs',\n    behaviorConduct01002003: 'When the water is pushed',\n    behaviorConduct01002004: 'After the water ir removed',\n    behaviorConduct01003002: 'When the heavy rain forecast occurs',\n    behaviorConduct01003003: 'When the heavy rain warning occurs',\n    behaviorConduct01003004: 'After the heavy rain has passed',\n    behaviorConduct01004001: 'Before the gale comes',\n    behaviorConduct01004002: 'When the gale occurs',\n    behaviorConduct01005002: 'Before the heavy snow comes',\n    behaviorConduct01005003: 'When the heavy snow occurs',\n    behaviorConduct01005004: 'After the heavy snow has passed',\n    behaviorConduct01006001: 'Before the cold wave comes',\n    behaviorConduct01006002: 'When the cold wave occurs',\n    behaviorConduct01007001: 'When the storm warning occurs',\n    behaviorConduct01007002: 'Before the storm comes',\n    behaviorConduct01008001: 'When the dust storm forecast occurs',\n    behaviorConduct01008002: 'When the dust storm occurs',\n    behaviorConduct01008003: 'After the dust storm has passed',\n    behaviorConduct01009001: 'Before the heatwave comes',\n    behaviorConduct01009002: 'When the heatwave watch occurs',\n    behaviorConduct01010001: 'When the drought occurs',\n    behaviorConduct01011009: 'Before the earthquakes comes',\n    behaviorConduct01011010: 'When the earthquake occurs',\n    behaviorConduct01011012: 'After the earthquake evacuation',\n    behaviorConduct01013002: 'Before the tsunami comes',\n    behaviorConduct01013003: 'When the tsunami occurs',\n    behaviorConduct01014001: 'When the landslide watch occurs',\n    behaviorConduct03002002: 'treat burns',\n    behaviorConduct03002003: 'prevent fever',\n    behaviorConduct03002004: 'treat when bitten by a snake',\n    behaviorConduct03002005: 'treat when shot by bee',\n    behaviorConduct03002006: 'do first aid hyperventilation syndrome',\n    behaviorConduct03003001: 'do adult CPR',\n    behaviorConduct03003002: 'do infant CPR',\n    behaviorConduct03003003: 'use an automatic defibrillator',\n    behaviorConduct03004001: 'use a powder fire extinguisher',\n    behaviorConduct03016001: 'use a indoor fire hydrants',\n    behaviorConduct03005001: 'treat food poisoning',\n    behaviorConduct03006004: 'climb the mountain safely',\n    behaviorConduct03006005: 'In the mountain safe camping',\n    behaviorConduct03006002: 'notify information on a rescue request',\n    behaviorConduct03006003: 'do first aid in mountain accident',\n    behaviorConduct03008001: 'prevent kidnapping∙missing',\n    behaviorConduct03009001: 'prevent harassment',\n    behaviorConduct03010001: 'prevent school violence',\n    behaviorConduct03011001: 'prevent domestic violence',\n    behaviorConduct03012001: 'handle detention∙abduction',\n    behaviorConduct03013002: 'handle traffic accidents',\n    behaviorConduct03013005: 'rescue from a vehicle',\n    behaviorConduct03014001: 'use elevator safely',\n    behaviorConduct03014003: 'handle elevator malfunction',\n    behaviorConduct03014004: 'use escalator safely',\n    behaviorConduct03015007: 'live on fine dusty day',\n    behaviorConduct03015003: 'live by sector',\n    emergencyActionGuidelines01001: 'typhoon',\n    emergencyActionGuidelines01001001: '태풍 예보 시',\n    emergencyActionGuidelines01001002: '태풍 특보 시',\n    emergencyActionGuidelines01001003: '태풍 이후',\n    emergencyActionGuidelines01002: 'flood',\n    emergencyActionGuidelines01002001: '홍수 예·경보 시',\n    emergencyActionGuidelines01002002: '홍수 우려 때',\n    emergencyActionGuidelines01002003: '물이 밀려들 때',\n    emergencyActionGuidelines01002004: '물이 빠진 후에',\n    emergencyActionGuidelines01003: 'heavy rain',\n    emergencyActionGuidelines01003001: '호우 대비',\n    emergencyActionGuidelines01003002: '호우 예보 시',\n    emergencyActionGuidelines01003003: '호우 특보 중',\n    emergencyActionGuidelines01003004: '호우 이후',\n    emergencyActionGuidelines01004: 'strong wind',\n    emergencyActionGuidelines01004001: '강풍 대비',\n    emergencyActionGuidelines01004002: '강풍 발생 시',\n    emergencyActionGuidelines01004003: '강풍 관련',\n    emergencyActionGuidelines01005: 'heavy snow',\n    emergencyActionGuidelines01005001: '대설 대비',\n    emergencyActionGuidelines01005002: '대설 예보 시',\n    emergencyActionGuidelines01005003: '대설 특보 시',\n    emergencyActionGuidelines01005004: '대설 이후',\n    emergencyActionGuidelines01006: 'cold wave',\n    emergencyActionGuidelines01006001: '한파 대비',\n    emergencyActionGuidelines01006002: '한파 발생 시',\n    emergencyActionGuidelines01007: 'rough seas',\n    emergencyActionGuidelines01007001: '풍랑 특보 시',\n    emergencyActionGuidelines01008: 'yellow dust',\n    emergencyActionGuidelines01008001: '황사 대비',\n    emergencyActionGuidelines01008002: '황사 발생 시',\n    emergencyActionGuidelines01008003: '황사 이후',\n    emergencyActionGuidelines01008003: '황사 관련',\n    emergencyActionGuidelines01009: 'heat wave',\n    emergencyActionGuidelines01009001: '폭염 대비',\n    emergencyActionGuidelines01009002: '폭염 발생 시',\n    emergencyActionGuidelines01009003: '폭염 관련',\n    emergencyActionGuidelines01010: 'drought',\n    emergencyActionGuidelines01010001: '가뭄 시 생활',\n    emergencyActionGuidelines01010002: '가뭄 시 농촌',\n    emergencyActionGuidelines01011: 'earthquake',\n    emergencyActionGuidelines01011007: '지진 발생 시 상황별',\n    emergencyActionGuidelines01011008: '지진 발생 시 장소별',\n    emergencyActionGuidelines01011009: '지진 대비',\n    emergencyActionGuidelines01011010: '지진 발생 시',\n    emergencyActionGuidelines01011011: '지진 장소별',\n    emergencyActionGuidelines01011012: '지진 대피 후',\n    emergencyActionGuidelines01012: 'tsunami',\n    emergencyActionGuidelines01012005: '발생 시 (선박 위)',\n    emergencyActionGuidelines01012006: '발생 시 (지상 대피)',\n    emergencyActionGuidelines01013: 'tidal wave',\n    emergencyActionGuidelines01013001: '해일 대비',\n    emergencyActionGuidelines01013002: '해일 때',\n    emergencyActionGuidelines01013003: '해일 발생 때',\n    emergencyActionGuidelines01013004: '미쳐 대피 못한 때',\n    emergencyActionGuidelines01013005: '폭풍해일',\n    emergencyActionGuidelines01014: 'landslide',\n    emergencyActionGuidelines01014001: '산사태 취약 지역 (주의보)',\n    emergencyActionGuidelines01014002: '산사태 취약 지역 (경보)',\n    emergencyActionGuidelines01014003: '일반 지역 (주의보)',\n    emergencyActionGuidelines01014004: '일반 지역 (경보)',\n    emergencyActionGuidelines01015: 'volcanic eruption',\n    emergencyActionGuidelines01015001: '화산재 낙하 대비',\n    emergencyActionGuidelines01015002: '화산재 낙하 시',\n    emergencyActionGuidelines01015003: '화산재 제거 이유',\n    emergencyActionGuidelines02001: 'marine pollution',\n    emergencyActionGuidelines02001001: '발생 전',\n    emergencyActionGuidelines02001002: '발생 시',\n    emergencyActionGuidelines02001003: '조치 완료 후',\n    emergencyActionGuidelines02002: 'large-scale water pollution',\n    emergencyActionGuidelines02002001: '사고 시',\n    emergencyActionGuidelines02002002: '구별 방법',\n    emergencyActionGuidelines02003: 'water shortage',\n    emergencyActionGuidelines02003001: '급수중단 발령 시',\n    emergencyActionGuidelines02003002: 'Ⅰ급상황 발생 시',\n    emergencyActionGuidelines02003003: 'Ⅱ급상황 발생 시',\n    emergencyActionGuidelines02004: 'utility tunnel disaster',\n    emergencyActionGuidelines02004001: '발생 우려 시',\n    emergencyActionGuidelines02004002: '발생 시',\n    emergencyActionGuidelines02005: 'livestock disease',\n    emergencyActionGuidelines02005001: '구제역 발생 시',\n    emergencyActionGuidelines02005002: '조류인플루엔자(AI) 발생 시',\n    emergencyActionGuidelines02005003: '발생 방지 대책',\n    emergencyActionGuidelines02005004: '발생 의심 시',\n    emergencyActionGuidelines02005005: '발생 확인 시',\n    emergencyActionGuidelines02006: 'infectious disease',\n    emergencyActionGuidelines02006001: '예방 대책',\n    emergencyActionGuidelines02006002: '증상이 나타날 때',\n    emergencyActionGuidelines02006003: '중동호흡기증후군(MERS)',\n    emergencyActionGuidelines02007: 'railway and subway',\n    emergencyActionGuidelines02007001: '지하철 화재 발생 시',\n    emergencyActionGuidelines02007002: '고속철도 화재 발생 시',\n    emergencyActionGuidelines02007003: '사고 및 테러(독가스) 발생 시',\n    emergencyActionGuidelines02008: 'financial IT system',\n    emergencyActionGuidelines02008001: '보이스피싱 피해금 지급 정지',\n    emergencyActionGuidelines02008002: '보이스피싱 피해 예방',\n    emergencyActionGuidelines02009: 'nuclear power plant accident',\n    emergencyActionGuidelines02009001: '국민보호조치 발표 시',\n    emergencyActionGuidelines02009002: '방사능구름 통과 시',\n    emergencyActionGuidelines02009003: '옥내 대피 및 소개 시',\n    emergencyActionGuidelines02010: 'chemical accident',\n    emergencyActionGuidelines02010001: '화학물질 유출 시',\n    emergencyActionGuidelines02010002: '니트로글리세린 누출 시',\n    emergencyActionGuidelines02010003: '트리니트로톨루엔 누출 시',\n    emergencyActionGuidelines02010004: '화학유해물질(독성가스) 누출 시',\n    emergencyActionGuidelines02011: 'fire',\n    emergencyActionGuidelines02011001: '일반',\n    emergencyActionGuidelines02011002: '예방 대책',\n    emergencyActionGuidelines02011003: '화재 발생 후',\n    emergencyActionGuidelines02011004: '화재 시',\n    emergencyActionGuidelines02011005: '화재 시 긴급 대피',\n    emergencyActionGuidelines02011006: '화재 시 피해 복구',\n    emergencyActionGuidelines02011007: '가정에서의 안전',\n    emergencyActionGuidelines02011008: '연기 관련 정보',\n    emergencyActionGuidelines02011009: '아파트 화재 시',\n    emergencyActionGuidelines02011010: '아파트 화재 대비',\n    emergencyActionGuidelines02011011: '도로 터널 화재',\n    emergencyActionGuidelines02011012: '대형 화재',\n    emergencyActionGuidelines02011013: '고층 건물 화재',\n    emergencyActionGuidelines02011014: '지하상가 화재 안전수칙',\n    emergencyActionGuidelines02011015: '지하철 화재 발생 시',\n    emergencyActionGuidelines02012: 'wildfire',\n    emergencyActionGuidelines02012001: '주택가 산불 확산 시',\n    emergencyActionGuidelines02012002: '산불 방지',\n    emergencyActionGuidelines02012003: '봄철 산불 관련',\n    emergencyActionGuidelines02012004: '산불 예방',\n    emergencyActionGuidelines02012005: '산불 발생 후',\n    emergencyActionGuidelines02012006: '산불 대피',\n    emergencyActionGuidelines02012007: '산불 피해 지역 가축 관리',\n    emergencyActionGuidelines02013: 'building collapse',\n    emergencyActionGuidelines02013001: '사고 발생 시',\n    emergencyActionGuidelines02013002: '징조를 느낄 때',\n    emergencyActionGuidelines02013003: '건물 내부에 있을 때',\n    emergencyActionGuidelines02013004: '건물 외부에 있을 때',\n    emergencyActionGuidelines02013005: '붕괴, 매몰된 경우',\n    emergencyActionGuidelines02013007: '도로 공사장 붕괴',\n    emergencyActionGuidelines02013008: '상수도 공사장 붕괴',\n    emergencyActionGuidelines02013009: '아파트 공사장 붕괴',\n    emergencyActionGuidelines02013010: '지하철 공사장 붕괴',\n    emergencyActionGuidelines02014: 'dam collapse',\n    emergencyActionGuidelines02014001: '붕괴 우려 시',\n    emergencyActionGuidelines02014002: '붕괴 발생 시',\n    emergencyActionGuidelines02014003: '물이 빠진 후',\n    emergencyActionGuidelines02015: 'explosion',\n    emergencyActionGuidelines02015001: '가스 폭발 시',\n    emergencyActionGuidelines02015004: '폭발 현장',\n    emergencyActionGuidelines02016: 'aircraft accident',\n    emergencyActionGuidelines02016001: '항공기 사고 예방',\n    emergencyActionGuidelines02017: 'CBRN incident',\n    emergencyActionGuidelines02017001: '사고 발생 시',\n    emergencyActionGuidelines02018: 'power outage',\n    emergencyActionGuidelines02018001: '정전 시',\n    emergencyActionGuidelines02018002: '정전 발생 시',\n    emergencyActionGuidelines02018003: '정전 상황별',\n    emergencyActionGuidelines02019: 'electricity·gas',\n    emergencyActionGuidelines02019001: '전기사고 예방',\n    emergencyActionGuidelines02019002: '침수지역 감전 사고 예방',\n    emergencyActionGuidelines02019003: '대피 명령 시 전기설비 조치',\n    emergencyActionGuidelines02019004: '정전 발생 시 조치',\n    emergencyActionGuidelines02019005: '야외 주의 사항',\n    emergencyActionGuidelines02019006: '가스사고 예방',\n    emergencyActionGuidelines02019007: '가스사고 발생 시',\n    emergencyActionGuidelines02019008: 'LPG 응급조치',\n    emergencyActionGuidelines02019009: '도시가스(LNG) 응급조치',\n    emergencyActionGuidelines02019010: '이동식 부탄가스 안전점검',\n    emergencyActionGuidelines02019011: '가스 사용 시 안전점검',\n    emergencyActionGuidelines02019012: '가스 누출 발생 시 대피',\n    emergencyActionGuidelines02019013: '배관 등에서 대량 누출 시',\n    emergencyActionGuidelines02019014: '기타 사항',\n    emergencyActionGuidelines02019015: '암모니아가스 인체 접촉 시',\n    emergencyActionGuidelines02019016: '염소가스 누출 시',\n    emergencyActionGuidelines02020: 'passenger ship',\n    emergencyActionGuidelines02020001: '이용객 금지 행위',\n    emergencyActionGuidelines02020002: '사고 발생 시',\n    emergencyActionGuidelines02021: 'water accident',\n    emergencyActionGuidelines02021001: '하천이나 계곡물',\n    emergencyActionGuidelines02021002: '무릎 이상의 깊은 급류',\n    emergencyActionGuidelines02021003: '물에 빠졌을 때',\n    emergencyActionGuidelines02021004: '파도가 높아져 위험할 때',\n    emergencyActionGuidelines02021005: '수초에 감겼을 때',\n    emergencyActionGuidelines02021006: '의식 없는 사고자를 구했을 때',\n    emergencyActionGuidelines02021007: '고립 지역',\n    emergencyActionGuidelines02021008: '계곡에서 야영지를 선택 시',\n    emergencyActionGuidelines02021009: '보트 전복 등에 따른 대처',\n    emergencyActionGuidelines02021010: '갯바위 등 바다낚시 사고 예방',\n    emergencyActionGuidelines02021011: '갯벌 해루질 사고 예방',\n    emergencyActionGuidelines02022: 'terrorism',\n    emergencyActionGuidelines02022007: '신고 요령',\n    emergencyActionGuidelines02022008: '대형, 고층건물 재난 시',\n    emergencyActionGuidelines02022009: '폭발물 발견 시',\n    emergencyActionGuidelines02022010: '화학 테러(독가스 등) 발생 시',\n    emergencyActionGuidelines02022011: '생물 테러 발생 시',\n    emergencyActionGuidelines02022012: '방사능 테러 발생 시',\n    emergencyActionGuidelines02022013: '화재 발생 시',\n    emergencyActionGuidelines02022014: '총격 현장',\n    emergencyActionGuidelines02022015: '매몰, 붕괴 시',\n    emergencyActionGuidelines02022016: '억류, 납치 시',\n    emergencyActionGuidelines02022017: '테러범·의심물체 등',\n    emergencyActionGuidelines02023: 'power shortage',\n    emergencyActionGuidelines02023001: '단계별',\n    emergencyActionGuidelines03002: 'first aid',\n    emergencyActionGuidelines03002001: '일반',\n    emergencyActionGuidelines03002002: '화상',\n    emergencyActionGuidelines03002003: '온열질환',\n    emergencyActionGuidelines03002004: '뱀에 물렸을 때',\n    emergencyActionGuidelines03002005: '벌에 쏘였을 때',\n    emergencyActionGuidelines03002006: '과호흡증후군',\n    emergencyActionGuidelines03002007: '상비약',\n    emergencyActionGuidelines03003: 'CPR',\n    emergencyActionGuidelines03003001: '성인',\n    emergencyActionGuidelines03003002: '영유아',\n    emergencyActionGuidelines03003003: '자동제세동기',\n    emergencyActionGuidelines03004: 'fire extinguisher',\n    emergencyActionGuidelines03004001: '분말 소화기',\n    emergencyActionGuidelines03004002: '투척용 소화기',\n    emergencyActionGuidelines03004003: '설치/취급 및 사용법',\n    emergencyActionGuidelines03004004: '소화기의 종류',\n    emergencyActionGuidelines03005: 'food poisoning',\n    emergencyActionGuidelines03005001: '일반',\n    emergencyActionGuidelines03005002: '음식점/급식소 운영자',\n    emergencyActionGuidelines03006: 'hiking',\n    emergencyActionGuidelines03006001: '위급 상황 시',\n    emergencyActionGuidelines03006002: '구조 요청 시',\n    emergencyActionGuidelines03006003: '응급조치',\n    emergencyActionGuidelines03007: \"children's playground\",\n    emergencyActionGuidelines03007001: '탑승 대기',\n    emergencyActionGuidelines03007002: '안전 이용',\n    emergencyActionGuidelines03007003: '탑승 제한',\n    emergencyActionGuidelines03007004: '어린이 탑승',\n    emergencyActionGuidelines03007005: '탑승 시 주의',\n    emergencyActionGuidelines03007006: '운행 중 자세',\n    emergencyActionGuidelines03007007: '탑승 완료 후 퇴장',\n    emergencyActionGuidelines03008: 'missing·kidnapping',\n    emergencyActionGuidelines03008001: '예방 방법',\n    emergencyActionGuidelines03009: 'sexual violence',\n    emergencyActionGuidelines03009001: '예방 방법',\n    emergencyActionGuidelines03010: 'school violence',\n    emergencyActionGuidelines03010001: '예방 방법',\n    emergencyActionGuidelines03011: 'domestic violence',\n    emergencyActionGuidelines03011001: '예방 방법',\n    emergencyActionGuidelines03012: 'detention·abduction',\n    emergencyActionGuidelines03012001: '대처 요령',\n    emergencyActionGuidelines03013: 'traffic accident',\n    emergencyActionGuidelines03013001: '사고 예방',\n    emergencyActionGuidelines03013002: '발생 시',\n    emergencyActionGuidelines03013003: '상황 판단',\n    emergencyActionGuidelines03013004: '구출',\n    emergencyActionGuidelines03013005: '차량에서의 구조',\n    emergencyActionGuidelines03014: 'elevator',\n    emergencyActionGuidelines03014001: '안전 이용',\n    emergencyActionGuidelines03014002: '안전 문화',\n    emergencyActionGuidelines03014003: '고장 시 안전 구조',\n    emergencyActionGuidelines03014004: '에스컬레이터 안전 수칙',\n    emergencyActionGuidelines03014005: '엘리베이터 사고 예방',\n    emergencyActionGuidelines03014006: '에스컬레이터 및 무빙워크 사고 예방',\n    emergencyActionGuidelines03015: 'fine dust',\n    emergencyActionGuidelines03015001: '특성',\n    emergencyActionGuidelines03015002: '미세먼지 예보 등급별',\n    emergencyActionGuidelines03015003: '부문별 생활 수칙',\n    emergencyActionGuidelines03015004: '인체에 미치는 영향',\n    emergencyActionGuidelines03015005: '미세먼지 정보',\n    emergencyActionGuidelines03015006: '미세먼지 발생 시',\n    emergencyActionGuidelines03015007: '미세먼지 많은 날',\n    emergencyActionGuidelines03016: 'fire hydrant',\n    emergencyActionGuidelines03016001: '옥내소화전 사용법',\n    emergencyActionGuidelines03016002: '경보 설비',\n    emergencyActionGuidelines03017: 'home safety inspection',\n    emergencyActionGuidelines03017001: '안전점검의 날 준비',\n    emergencyActionGuidelines03017002: '계절별 대비',\n    tts_female: 'female',\n    tts_male: 'male',\n    ROBOID_tail: 'tail',\n    SCENE: 'Scene',\n    entry_bot_name: 'Entrybot',\n    doggi_bark: \"Doggi's Bark\",\n    walking_entryBot: 'Walking Entrybot',\n    silent: 'Silent',\n    do_name: 'Do',\n    do_sharp_name: 'Do#(Re♭)',\n    re_name: 'Re',\n    re_sharp_name: 'Re(Mi♭)',\n    BITBRICK_dc_direction_cw: 'CW',\n    BITBRICK_dc_direction_ccw: 'CCW',\n    blacksmith_toggle_on: 'on',\n    blacksmith_toggle_off: 'off',\n    blacksmith_lcd_first_line: 'first',\n    show_all_comment: 'show all memos',\n    blacksmith_lcd_seconds_line: 'seconds',\n    mi_name: 'Mi',\n    fa_name: 'Fa',\n    fa_sharp_name: 'Fa#(Sol♭)',\n    sol_name: 'Sol',\n    sol_sharp_name: 'Sol#(La♭)',\n    la_name: 'La',\n    la_sharp_name: 'La#(Si♭)',\n    si_name: 'Si',\n    ROBOID_color_black: 'black',\n    ROBOID_clicked: 'clicked',\n    ROBOID_double_clicked: 'double-clicked',\n    ROBOID_long_pressed: 'long-pressed',\n    ROBOID_color_any: 'any color',\n    ROBOID_back: 'back',\n    START: 'Start',\n    FLOW: 'Flow',\n    MOVING: 'Motion',\n    LOOKS: 'Looks',\n    BRUSH: 'Brush',\n    ROBOID_sound_dibidibidip: 'dibidibidip',\n    TEXT: 'Text',\n    ROBOID_sound_good_job: 'good job',\n    SOUND: 'Sound',\n    JUDGEMENT: 'Decision',\n    CALC: 'Figures',\n    VARIABLE: 'Variable',\n    ANALYSIS: 'Table',\n    EXPANSION: 'Extension',\n    ARDUINO: 'Hardware',\n    ROBOID_sound_march: 'march',\n    ROBOID_sound_birthday: 'birthday',\n    no_target: 'No Target',\n    Paste_blocks: 'paste code(s)',\n    tidy_up_block: 'tidy up the blocks',\n    Clear_all_blocks: 'remove all codes',\n    add_comment: 'add a memo',\n    hide_all_comment: 'hide all memos',\n    ROBOID_left: 'left',\n    ROBOID_right: 'right',\n    ROBOID_both: 'both',\n    ROBOID_color_red: 'red',\n    ROBOID_color_yellow: 'yellow',\n    ROBOID_color_green: 'green',\n    ROBOID_color_sky_blue: 'sky blue',\n    ROBOID_color_blue: 'blue',\n    ROBOID_color_purple: 'purple',\n    ROBOID_color_white: 'white',\n    ROBOID_unit_cm: 'cm',\n    oneself: 'Self',\n    ROBOID_unit_sec: 'seconds',\n    ROBOID_unit_pulse: 'pulses',\n    ROBOID_unit_deg: 'degrees',\n    ROBOID_color_orange: 'orange',\n    ROBOID_color_violet: 'violet',\n    ROBOID_sound_beep: 'beep',\n    ROBOID_sound_random_beep: 'random beep',\n    ROBOID_sound_siren: 'siren',\n    ROBOID_sound_engine: 'engine',\n    ROBOID_sound_robot: 'robot',\n    ALTINO_CDS: 'light',\n    ALTINO_ACCX: 'acceleration X axis',\n    ALTINO_ACCY: 'acceleration Y axis',\n    ALTINO_ACCZ: 'acceleration Z axis',\n    ALTINO_MAGX: 'geomagnetic X axis',\n    ALTINO_MAGY: 'geomagnetic Y axis',\n    ALTINO_MAGZ: 'geomagnetic Z axis',\n    ALTINO_GYROX: 'gyro X axis',\n    ALTINO_GYROY: 'gyro Y axis',\n    ALTINO_GYROZ: 'gyro Z axis',\n    ALTINO_IR1: '1 distance',\n    ALTINO_IR2: '2 distance',\n    ALTINO_IR3: '3 distance',\n    ALTINO_IR4: '4 distance',\n    ALTINO_IR5: '5 distance',\n    ALTINO_IR6: '6 distance',\n    ALTINO_TEM: 'temperature',\n    ALTINO_TOR2: 'left torque',\n    ALTINO_TOR1: 'right torque',\n    ALTINO_STTOR: 'steering torque',\n    ALTINO_BAT: 'battery check',\n    ALTINO_Steering_Angle_Center: 'center',\n    ALTINO_Steering_Angle_Left5: 'left5',\n    mouse_pointer: 'mouse cursor',\n    self: 'self',\n    wall_up: 'upper wall',\n    wall_down: 'down wall',\n    wall_right: 'right wall',\n    wall_left: 'left wall',\n    length_of_string: 'to',\n    auto: 'auto',\n    chocopi_touch_event_touch: 'touched',\n    chocopi_touch_event_untouch: 'untouched',\n    chocopi_control_event_pressed: 'pressed',\n    chocopi_control_event_released: 'released',\n    chocopi_joystick_X: 'joystick X',\n    chocopi_joystick_Y: 'joystick Y',\n    chocopi_pot: 'potentiometer',\n    chocopi_motion_photogate_time_unblocked: 'unblocked',\n    chocopi_motion_photogate_time_blocked: 'blocked',\n    chocopi_motion_photogate_event_unblocked: 'unblocked',\n    chocopi_motion_photogate_event_blocked: 'blocked',\n    coconut_move_forward: 'forward',\n    coconut_move_backward: 'backward',\n    coconut_turn_left: 'left',\n    coconut_turn_right: 'right',\n    coconut_color_red: 'Red',\n    coconut_color_yellow: 'Yellow',\n    coconut_color_green: 'Green',\n    coconut_color_cyan: 'Cyan',\n    coconut_color_blue: 'Blue',\n    coconut_color_magenta: 'Magenta',\n    coconut_color_white: 'White',\n    coconut_left_led: 'left led',\n    coconut_right_led: 'right led',\n    coconut_both_leds: 'both led',\n    coconut_note_c: 'note_c',\n    coconut_note_d: 'note_d',\n    coconut_note_e: 'note_e',\n    coconut_note_f: 'note_f',\n    coconut_note_g: 'note_g',\n    coconut_note_a: 'note_a',\n    coconut_note_b: 'note_b',\n    coconut_play_buzzer_hn: 'Half',\n    coconut_play_buzzer_qn: 'Quater',\n    coconut_play_buzzer_en: 'Eighth',\n    coconut_play_buzzer_sn: 'Sixteenth',\n    coconut_play_buzzer_tn: 'Thirty-second',\n    coconut_play_buzzer_wn: 'Whole',\n    coconut_play_buzzer_dhn: 'Dotted half',\n    coconut_play_buzzer_dqn: 'Dotted quarter',\n    coconut_play_buzzer_den: 'Dotted eighth',\n    coconut_play_buzzer_dsn: 'Dotted sixteenth',\n    coconut_play_buzzer_dtn: 'Dotted thirty-second',\n    coconut_rest_buzzer_hr: 'Half_rest',\n    coconut_rest_buzzer_qr: 'Quater_rest',\n    coconut_rest_buzzer_er: 'Eighth_rest',\n    coconut_rest_buzzer_sr: 'Sixteenth_rest',\n    coconut_rest_buzzer_tr: 'Thirty-second rest',\n    coconut_rest_buzzer_wr: 'Whole_rest',\n    ALBERT_note_c: 'C',\n    ALBERT_note_d: 'D',\n    ALBERT_note_e: 'E',\n    ALBERT_note_f: 'F',\n    ALBERT_note_g: 'G',\n    ALBERT_note_a: 'A',\n    ALBERT_note_b: 'B',\n    coconut_play_midi_1: 'Twinkle Twinkle little star',\n    coconut_play_midi_2: 'Three bears',\n    coconut_play_midi_3: \"Mozart's Lullaby\",\n    coconut_play_midi_4: 'Do-Re-Mi',\n    coconut_play_midi_5: 'Butterfly',\n    coconut_sensor_both_floor: 'both line tracer',\n    coconut_floor_sensing_on: 'detect',\n    coconut_floor_sensing_off: 'not detect',\n    coconut_sensor_both_proximity: 'both IR distance',\n    coconut_dotmatrix_set_on: 'on',\n    coconut_dotmatrix_set_off: 'off',\n    coconut_dotmatrix_row_0: 'all',\n    coconut_dotmatrix_row_1: '1',\n    coconut_dotmatrix_row_2: '2',\n    coconut_dotmatrix_row_3: '3',\n    coconut_dotmatrix_row_4: '4',\n    coconut_dotmatrix_row_5: '5',\n    coconut_dotmatrix_row_6: '6',\n    coconut_dotmatrix_row_7: '7',\n    coconut_dotmatrix_row_8: '8',\n    coconut_dotmatrix_col_0: 'all',\n    coconut_dotmatrix_col_1: '1',\n    coconut_dotmatrix_col_2: '2',\n    coconut_dotmatrix_col_3: '3',\n    coconut_dotmatrix_col_4: '4',\n    coconut_dotmatrix_col_5: '5',\n    coconut_dotmatrix_col_6: '6',\n    coconut_dotmatrix_col_7: '7',\n    coconut_dotmatrix_col_8: '8',\n    coconut_x_axis: 'X-Axis',\n    coconut_y_axis: 'Y-Axis',\n    coconut_z_axis: 'Z-Axis',\n    CODEino_sensor_name_0: 'Sound',\n    CODEino_sensor_name_1: 'Light',\n    CODEino_sensor_name_2: 'Slider',\n    CODEino_sensor_name_3: 'resistance-A',\n    CODEino_sensor_name_4: 'resistance-B',\n    CODEino_sensor_name_5: 'resistance-C',\n    CODEino_sensor_name_6: 'resistance-D',\n    CODEino_string_11: 'Great',\n    CODEino_string_12: 'Small',\n    CODEino_string_14: 'Bright',\n    CODEino_string_15: 'Dark',\n    CODEino_string_3: 'Push button',\n    CODEino_string_4: 'Connected A',\n    CODEino_string_5: 'Connected B',\n    CODEino_string_6: 'Connected C',\n    CODEino_string_7: 'Connected D',\n    CODEino_string_16: 'Left tilt',\n    CODEino_string_17: 'Right tilt',\n    CODEino_string_18: 'Front tilt',\n    CODEino_string_19: 'Rear tilt',\n    CODEino_string_20: 'Reverse',\n    CODEino_led_red: 'Red',\n    CODEino_led_green: 'Green',\n    CODEino_led_blue: 'Blue',\n    jdkit_led_turnon: 'Turn on',\n    jdkit_led_turnoff: 'Turn off',\n    jdkit_led: 'LED',\n    ev3_cw: 'CW',\n    ev3_ccw: 'CCW',\n    roborobo_motor_stop: 'Stop',\n    roborobo_motor_CW: 'ClockWise',\n    roborobo_motor_CCW: 'CounterClockWise',\n    FUNBOARD_bt_up: 'red(A)',\n    FUNBOARD_bt_down: 'yellow(B)',\n    FUNBOARD_bt_left: 'green(C)',\n    FUNBOARD_bt_right: 'blue(D)',\n    FUNBOARD_touchbt_up: 'red(A)',\n    FUNBOARD_touchbt_down: 'yellow(B)',\n    FUNBOARD_touchbt_left: 'green(C)',\n    FUNBOARD_touchbt_right: 'blue(D)',\n    FUNBOARD_touchbt_space: '   E',\n    FUNBOARD_touchbt_enter: '   F',\n    FUNBOARD_touchbt_escape: '   G',\n    FUNBOARD_sensor_slide: 'potentiometer',\n    FUNBOARD_sensor_cds: 'light sensor',\n    FUNBOARD_sensor_mic: 'microphone sensor',\n    FUNBOARD_sensor_state_1: 'low',\n    FUNBOARD_sensor_state_2: 'high',\n    FUNBOARD_led_color_red: 'red',\n    FUNBOARD_led_color_yellow: 'yellow',\n    FUNBOARD_led_color_green: 'green',\n    FUNBOARD_led_color_blue: 'blue',\n    FUNBOARD_led_color_all: 'all',\n    FUNBOARD_do_on: 'on',\n    FUNBOARD_do_off: 'off',\n    FUNBOARD_row_tag: 'row',\n    FUNBOARD_column_tag: 'column',\n    FUNBOARD_scroll_no: 'no',\n    FUNBOARD_scroll_left: 'leftward',\n    FUNBOARD_scroll_right: 'rightward',\n    FUNBOARD_scroll_up: 'upwards',\n    FUNBOARD_scroll_down: 'downward',\n    HAMSTER_sensor_signal_strength: 'signal strength',\n    HAMSTER_turn_once_left: 'left',\n    HAMSTER_turn_right: 'right',\n    HAMSTER_left_wheel: 'left',\n    HAMSTER_right_wheel: 'right',\n    HAMSTER_both_wheels: 'both',\n    HAMSTER_color_black: 'black',\n    HAMSTER_color_white: 'white',\n    HAMSTER_left_floor_sensor: 'left',\n    HAMSTER_right_floor_sensor: 'right',\n    HAMSTER_both_floor_sensors: 'both',\n    HAMSTER_front: 'front',\n    HAMSTER_rear: 'rear',\n    HAMSTER_left_led: 'left',\n    HAMSTER_right_led: 'right',\n    HAMSTER_both_leds: 'both',\n    HAMSTER_color_red: 'red',\n    HAMSTER_color_yellow: 'yellow',\n    HAMSTER_color_green: 'green',\n    HAMSTER_color_cyan: 'sky blue',\n    HAMSTER_color_blue: 'blue',\n    HAMSTER_color_magenta: 'purple',\n    HAMSTER_port_a: 'A',\n    HAMSTER_port_b: 'B',\n    HAMSTER_port_ab: 'A and B',\n    HAMSTER_analog_input: 'analog input',\n    HAMSTER_digital_input: 'digital input',\n    HAMSTER_servo_output: 'servo output',\n    HW_MOTOR: 'Motor',\n    HW_MELODY: 'Melody',\n    HW_SENSOR: 'Sensor',\n    HW_LED: 'Led',\n    HW_ROBOT: 'Robot',\n    HAMSTER_pwm_output: 'pwm output',\n    HAMSTER_digital_output: 'digital output',\n    jdkit_clockwise: '시계방향',\n    jdkit_counterclockwise: '반시계방향',\n    jdkit_motor_lefttop: '왼쪽위',\n    jdkit_motor_leftbottom: '왼쪽아래',\n    jdkit_motor_righttop: '오른쪽위',\n    jdkit_motor_rightbottom: '오른쪽아래',\n    jdkit_gyro_frontrear: '앞뒤',\n    jdkit_gyro_leftright: '좌우',\n    jdkit_led_color_green: '초록색',\n    jdkit_led_color_orange: '오랜지색',\n    jdkit_tune_do: '도',\n    jdkit_tune_re: '레',\n    jdkit_tune_mi: '미',\n    jdkit_tune_fa: '파',\n    jdkit_tune_sol: '솔',\n    jdkit_tune_la: '라',\n    jdkit_tune_si: '시',\n    modi_enviroment_temperature: 'Temparature',\n    modi_enviroment_humidity: 'Humidity',\n    modi_enviroment_illuminance: 'Illuminance',\n    modi_enviroment_red: 'Red',\n    modi_enviroment_bule: 'Blue',\n    modi_enviroment_green: 'Green',\n    modi_gyroscope_xAcceleratior: 'X-axis acceleration',\n    modi_gyroscope_yAcceleratior: 'Y-axis acceleration',\n    modi_gyroscope_zAcceleratior: 'Z-axis acceleration',\n    modi_motor_angle: 'Angle',\n    modi_motor_speed: 'Speed',\n    modi_motor_torque: 'Torque',\n    modi_speaker_F_PA_5: 'FA 5',\n    modi_speaker_F_SOL_5: 'SOL 5',\n    modi_speaker_F_RA_5: 'LA 5',\n    modi_speaker_F_SO_5: 'TI 5',\n    modi_speaker_F_PA_S_5: 'FA #5',\n    modi_speaker_F_SOL_S_5: 'SOL #5',\n    modi_speaker_F_RA_S_5: 'LA #5',\n    modi_speaker_F_DO_6: 'DO 6',\n    modi_speaker_F_RE_6: 'RE 6',\n    modi_speaker_F_MI_6: 'MI 6',\n    modi_speaker_F_PA_6: 'FA 6',\n    modi_speaker_F_SOL_6: 'SOL 6',\n    modi_speaker_F_RA_6: 'LA 6',\n    modi_speaker_F_SO_6: 'TI 6',\n    modi_speaker_F_DO_S_6: 'DO #6',\n    modi_speaker_F_RE_S_6: 'RE #6',\n    modi_speaker_F_PA_S_6: 'FA #6',\n    modi_speaker_F_SOL_S_6: 'SOL #6',\n    modi_speaker_F_RA_S_6: 'LA #6',\n    modi_speaker_F_DO_7: 'DO 7',\n    modi_speaker_F_RE_7: 'RE 7',\n    modi_speaker_F_MI_7: 'MI 7',\n    modi_speaker_F_DO_S_7: 'DO #7',\n    modi_speaker_F_RE_S_7: 'RE #7',\n    roborobo_color_red: ' Red ',\n    roborobo_color_green: ' Green ',\n    roborobo_color_blue: ' Blue ',\n    roborobo_color_yellow: ' Yellow ',\n    roborobo_on: 'On',\n    roborobo_off: 'Off',\n    roborobo_motor1: 'motor1',\n    roborobo_motor2: 'motor2',\n    robotis_cm_spring_left: 'Left contact sensor',\n    robotis_cm_spring_right: 'Right contact sensor',\n    robotis_cm_switch: 'Status of the switch',\n    robotis_cm_sound_detected: 'Final number of sound detection ',\n    robotis_cm_sound_detecting: 'Number of live sound detection ',\n    robotis_cm_ir_left: 'Left infrared sensor',\n    robotis_cm_ir_right: 'Right infrared sensor',\n    robotis_cm_calibration_left: 'Value of the left infrared sensor calibration ',\n    robotis_cm_calibration_right: 'Value of the right infrared sensor calibration ',\n    robotis_common_on: 'Turn on',\n    robotis_common_off: 'Turn off',\n    robotis_common_clockwhise: 'Clockwise',\n    robotis_common_counter_clockwhise: 'Counterclockwise',\n    robotis_cm_user_button: 'Status of user button',\n    robotis_aux_servo_position: 'Position of servo motor',\n    robotis_aux_ir: 'Infrared sensor',\n    robotis_aux_touch: 'Contact sensor',\n    robotis_aux_brightness: 'CDS',\n    robotis_aux_hydro_themo_humidity: 'Temperature-humidity sensor (humidity)',\n    robotis_aux_hydro_themo_temper: 'Temperature-humidity sensor (temperature)',\n    robotis_aux_temperature: 'Temperature sensor',\n    robotis_aux_ultrasonic: 'Ultrasonic sensor',\n    robotis_aux_magnetic: 'Magnetic sensor',\n    robotis_aux_motion_detection: 'Motion detector',\n    robotis_aux_color: 'Color sensor',\n    robotis_aux_custom: 'User device',\n    robotis_common_red_color: 'Red',\n    robotis_common_green_color: 'Green',\n    robotis_common_blue_color: 'Blue',\n    robotis_common_port_1: 'Port 1',\n    robotis_common_port_2: 'Port 2',\n    robotis_common_port_3: 'Port 3',\n    robotis_common_port_4: 'Port 4',\n    robotis_common_port_5: 'Port 5',\n    robotis_common_port_6: 'Port 6',\n    robotis_common_wheel_mode: 'Wheel mode',\n    robotis_common_joint_mode: 'Joint mode',\n    robotis_cm_led_both: 'Both LED',\n    robotis_cm_led_right: 'Right LED',\n    robotis_cm_led_left: 'Left LED',\n    robotori_D2_Input: 'Digital Pin 2 Input Value',\n    robotori_D3_Input: 'Digital Pin 3 Input Value',\n    robotori_A0_Input: 'Analog Pin 0 Input Value',\n    robotori_A1_Input: 'Analog Pin 1 Input Value',\n    robotori_A2_Input: 'Analog Pin 2 Input Value',\n    robotori_A3_Input: 'Analog Pin 3 Input Value',\n    robotori_A4_Input: 'Analog Pin 4 Input Value',\n    robotori_A5_Input: 'Analog Pin 5 Input Value',\n    robotori_D10_Output: 'Pin 10',\n    robotori_D11_Output: 'Pin 11',\n    robotori_D12_Output: 'Pin 12',\n    robotori_D13_Output: 'Pin 13',\n    robotori_On: 'On',\n    robotori_Off: 'Off',\n    robotori_analog5: 'Pin 5 Output Value',\n    robotori_analog6: 'Pin 6 Output Value',\n    robotori_analog9: 'Pin 9 Output Value',\n    robotori_DC_rightmotor: 'Right',\n    robotori_DC_leftmotor: 'Left',\n    robotori_DC_STOP: 'Stop',\n    robotori_DC_CW: 'clockwise',\n    robotori_DC_CCW: 'anticlockwise',\n    rokoboard_sensor_name_1: 'Light',\n    rokoboard_sensor_name_0: 'Sound',\n    rokoboard_sensor_name_2: 'Slider',\n    rokoboard_sensor_name_3: 'resistance-A',\n    rokoboard_sensor_name_4: 'resistance-B',\n    rokoboard_sensor_name_5: 'resistance-C',\n    rokoboard_sensor_name_6: 'resistance-D',\n    rokoboard_string_1: 'Button Pressed',\n    VARIABLE_change_variable: 'Adding variable',\n    VARIABLE_get_variable: 'Value of variable',\n    VARIABLE_set_variable: 'Set variable',\n    VARIABLE_show_variable: 'Show variable',\n    VARIABLE_hide_variable: 'Hide variable',\n    VARIABLE_add_value_to_list_1: 'add',\n    VARIABLE_add_value_to_list_2: 'to the list',\n    VARIABLE_remove_value_from_list_1: 'remove',\n    VARIABLE_remove_value_from_list_2: 'th element from',\n    VARIABLE_insert_value_to_list_1: 'insert',\n    VARIABLE_insert_value_to_list_2: 'to',\n    VARIABLE_insert_value_to_list_4: 'th position',\n    VARIABLE_change_value_list_index_1: 'change',\n    VARIABLE_change_value_list_index_3: 'th element to',\n    VARIABLE_show_list_1: 'Show list',\n    VARIABLE_hide_list_1: 'Hide list',\n    START_when_message_cast: 'When message received',\n    START_when_message_cast_1: 'When',\n    START_when_message_cast_2: 'message received',\n    START_message_cast: 'Send message',\n    START_message_cast_1: 'Send',\n    START_message_cast_2: 'message',\n    START_message_cast_wait: 'message and wait',\n    START_message_send_wait_1: 'Send',\n    START_message_send_wait_2: ' message and wait',\n    Duplication_option: 'Duplicate',\n    cut_blocks: 'Cut',\n    AI_analyze_option: 'AI Analyze',\n    CONTEXT_COPY_option: 'Copy',\n    Delete_Blocks: 'Remove',\n    add_my_storage: 'add to my storage',\n    export_object: 'Export Object',\n    this_project: 'this project',\n    this_object: 'this object',\n    right_hand: 'Right hand',\n    left_hand: 'Left hand',\n    thumb: 'thumb',\n    index_finger: 'index finger',\n    middle_finger: 'middle finger',\n    ring_finger: 'ring finger',\n    little_finger: 'little finger',\n    wrist: 'wrist',\n    tip: 'TIP',\n    dip: 'DIP',\n    pip: 'PIP',\n    none: 'NONE',\n    media_pipe_title_text: 'Video Detection',\n    pose_landmarker_title_text: 'Human Detection',\n    face_landmarker_title_text: 'Face Detection',\n    object_detector_title_text: 'Object Detection',\n    hand_detection_title_text: 'Hand Detection',\n    unknown: 'Unknown',\n    is_type_en: 'alphabet',\n    is_type_ko: 'hangeul',\n    location_entire: 'all',\n    location_seoul: 'Seoul',\n    location_seoul_jongno_gu: 'Jongno-gu',\n    location_seoul_jung_gu: 'Jung-gu',\n    location_seoul_yongsan_gu: 'Yongsan-gu',\n    location_seoul_seongdong_gu: 'Seongdong-gu',\n    location_seoul_gwangjin_gu: 'Gwangjin-gu',\n    location_seoul_dongdaemun_gu: 'Dongdaemun-gu',\n    location_seoul_jungnang_gu: 'Jungrang-gu',\n    location_seoul_seongbuk_gu: 'Seongbuk-gu',\n    location_seoul_gangbuk_gu: 'Gangbuk-gu',\n    location_seoul_dobong_gu: 'Dobong-gu',\n    location_seoul_nowon_gu: 'Nowon-gu',\n    location_seoul_eunpyeong_gu: 'Eunpyeong-gu',\n    location_seoul_seodaemun_gu: 'Seodaemun-gu',\n    location_seoul_mapo_gu: 'Mapo-gu',\n    location_seoul_yangcheon_gu: 'Yangcheon-gu',\n    location_seoul_gangseo_gu: 'Gangseo-gu',\n    location_seoul_guro_gu: 'Guro-gu',\n    location_seoul_geumcheon_gu: 'Geumcheon-gu',\n    location_seoul_yeongdeungpo_gu: 'Yeongdeungpo-gu',\n    location_seoul_dongjak_gu: 'Dongjak-gu',\n    location_seoul_gwanak_gu: 'Gwanak-gu',\n    location_seoul_seocho_gu: 'Seocho-gu',\n    location_seoul_gangnam_gu: 'Gangnam-gu',\n    location_seoul_songpa_gu: 'Songpa-gu',\n    location_seoul_gangdong_gu: 'Gangdong-gu',\n    location_gangwon: 'Gangwon-do',\n    location_gangwon_chuncheon: 'Chuncheon-si',\n    location_gangwon_wonju: 'Wonju-si',\n    location_gangwon_gangneung_si: 'Gangneung-si',\n    location_gangwon_donghae: 'Donghae-si',\n    location_gangwon_taebaek_si: 'Taebaek-si',\n    location_gangwon_sokcho: 'Sokcho-si',\n    location_gangwon_samcheok_si: 'Samcheok-si',\n    location_gangwon_hongcheon: 'Hongcheon-gun',\n    location_gangwon_hoengseong_gun: 'Hoengseong-gun',\n    location_gangwon_yeongwol_gun: 'Yeongwol-gun',\n    location_gangwon_pyeongchang: 'Pyeongchang-gun',\n    location_gangwon_jeongseon: 'Jeongseon-gun',\n    location_gangwon_cheolwon: 'Cheorwon-gun',\n    location_gangwon_hwacheon: 'Hwacheon-gun',\n    location_gangwon_yanggu: 'Yanggu-gun',\n    location_gangwon_inje: 'Inje-gun',\n    location_gangwon_goseong: 'Goseong-gun',\n    location_gangwon_yangyang: 'Yangyang-gun',\n    location_gyeonggi: 'Gyeonggi-do',\n    location_gyeonggi_suwon_si: 'Suwon-si',\n    location_gyeonggi_seongnam: 'Seongnam-si',\n    location_gyeonggi_uijeongbu: 'Uijeongbu-si',\n    location_gyeonggi_anyang_si: 'Anyang-si',\n    location_gyeonggi_bucheon_si: 'Bucheon-si',\n    location_gyeonggi_gwangmyeong_si: 'Gwangmyeong-si',\n    location_gyeonggi_pyeongtaek_si: 'Pyeongtaek-si',\n    location_gyeonggi_dongducheon_si: 'Dongducheon-si',\n    location_gyeonggi_ansan_si: 'Ansan-si',\n    location_gyeonggi_goyang_si: 'Goyang-si',\n    location_gyeonggi_gwacheon_si: 'Gwacheon-si',\n    location_gyeonggi_guri: 'Guri-si',\n    location_gyeonggi_namyangju_si: 'Namyangju-si',\n    location_gyeonggi_osan: 'Osan-si',\n    location_jeollanam_goheung: 'Goheung-gun',\n    location_gyeonggi_siheung: 'Siheung-si',\n    location_jeollanam_boseong: 'Boseong-gun',\n    location_jeollanam_hwasun: 'Hwasun-gun',\n    location_gyeonggi_gunpo_si: 'Gunpo-si',\n    location_jeollanam_jangheung: 'Jangheung-gun',\n    location_gyeonggi_uiwang_si: 'Uiwang-si',\n    location_jeollanam_gangjin: 'Gangjin-gun',\n    location_gyeonggi_hanam: 'Hanam-si',\n    location_jeollanam_haenam: 'Haenam-gun',\n    location_gyeonggi_yongin_si: 'Yongin-si',\n    location_jeollanam_yeongam: 'Yeongam-gun',\n    location_gyeonggi_paju: 'Paju-si',\n    location_jeollanam_jindo: 'Muan-gun',\n    location_gyeonggi_icheon: 'Icheon-si',\n    location_jeollanam_muan: 'Hampyeong-gun',\n    location_jeollanam_hampyeong: 'Yeonggwang-gun',\n    location_gyeonggi_anseong_si: 'Anseong-si',\n    location_jeollanam_yeonggwang: 'Jangseong-gun',\n    location_gyeonggi_gimpo: 'Gimpo-si',\n    location_jeollanam_jangseong: 'Wando-gun',\n    location_gyeonggi_hwaseong_si: 'Hwaseong-si',\n    location_jeollanam_wando: 'Jindo-gun',\n    location_gyeonggi_gwangju: 'Guangju-si',\n    location_jeollanam_sinan: 'Shinan-gun',\n    location_jeollabuk: 'Jeonbuk-do',\n    location_gyeonggi_yangju_si: 'Yangju-si',\n    location_jeollabuk_jeonju: 'Jeonju-si',\n    location_gyeonggi_pocheon: 'Pocheon-si',\n    location_jeollabuk_gunsan_si: 'Gunsan-si',\n    location_gyeonggi_yeoju: 'Yeoju-si',\n    location_jeollabuk_iksan: 'Iksan-si',\n    location_gyeonggi_yeoncheon_gun: 'Yeoncheon-gun',\n    location_gyeonggi_gapyeong_gun: 'Gapyeong-gun',\n    location_jeollabuk_jeongeup: 'Jeongeup-si',\n    location_gyeonggi_yangpyeong: 'Yangpyeong-gun',\n    location_jeollabuk_namwon: 'Namwon-si',\n    location_gyeongsangnam: 'Gyeongsangnam-do',\n    location_jeollabuk_gimje_si: 'Gimje-si',\n    location_gyeongsangnam_changwon_si: 'Changwon-si',\n    location_jeollabuk_wanju: 'Wanju-gun',\n    location_gyeongsangnam_jinju: 'Jinju-si',\n    location_jeollabuk_jinan: 'Jinan-gun',\n    location_gyeongsangnam_tongyeong_si: 'Tongyeong-si',\n    location_jeollabuk_muju: 'Muju-gun',\n    location_gyeongsangnam_sacheon_si: 'Sacheon-si',\n    location_jeollabuk_jangsu: 'Jangsu-gun',\n    location_gyeongsangnam_gimhae_si: 'Gimhae-si',\n    location_jeollabuk_imsil: 'Imsil-gun',\n    location_gyeongsangnam_miryang_si: 'Miryang-si',\n    location_jeollabuk_sunchang: 'Sunchang-gun',\n    location_gyeongsangnam_geoje_si: 'Geoje-si',\n    location_jeollabuk_gochang: 'Gochang-gun',\n    location_gyeongsangnam_yangsan_si: 'Yangsan-si',\n    location_jeollabuk_buan: 'Buan-gun',\n    location_gyeongsangnam_uiryeong: 'Uiryeong-gun',\n    location_jeju: 'Jeju-do',\n    location_gyeongsangnam_haman: 'Haman-gun',\n    location_jeju_jeju_si: 'Jeju-si',\n    location_gyeongsangnam_changnyeong: 'Changnyeong-gun',\n    location_jeju_seogwipo: 'Seogwipo-si',\n    location_gyeongsangnam_goseong: 'Goseong-gun',\n    location_gyeongsangnam_namhae: 'Namhae-gun',\n    location_chungcheongnam: 'Chungcheongnam-do',\n    location_gyeongsangnam_hadong: 'Hadong-gun',\n    location_chungcheongnam_cheonan: 'Cheonan-si',\n    location_gyeongsangnam_sancheong: 'Sancheong-gun',\n    location_chungcheongnam_gongju: 'Gongju-si',\n    location_gyeongsangnam_hamyang: 'Hamyang-gun',\n    location_gyeongsangnam_geochang: 'Geochang-gun',\n    location_chungcheongnam_boryeong: 'Boryeong-si',\n    location_gyeongsangnam_hapcheon: 'Hapcheon-gun',\n    location_chungcheongnam_asan: 'Asan-si',\n    location_gyeongsangbuk: 'Gyeongsangbuk-do',\n    location_chungcheongnam_seosan: 'Seosan-si',\n    location_gyeongsangbuk_pohang_si: 'Pohang-si',\n    location_gyeongsangbuk_gyeongju_si: 'Gyeongju-si',\n    location_chungcheongnam_nonsan: 'Nonsan-si',\n    location_gyeongsangbuk_gimcheon_si: 'Gimcheon-si',\n    location_chungcheongnam_gyeryong: 'Gyeryong-si',\n    location_gyeongsangbuk_andong_si: 'Andong-si',\n    location_chungcheongnam_dangjin: 'Dangjin-si',\n    location_gyeongsangbuk_gumi_si: 'Gumi-si',\n    location_gyeongsangbuk_yeongju_si: 'Yeongju-si',\n    location_chungcheongnam_geumsan: 'Geumsan-gun',\n    location_chungcheongnam_buyeo: 'Buyeo-gun',\n    location_gyeongsangbuk_yeongcheon_si: 'Yeongcheon-si',\n    location_chungcheongnam_seocheon: 'Seocheon-gun',\n    location_gyeongsangbuk_sangju_si: 'Sangju-si',\n    location_chungcheongnam_cheongyang: 'Cheongyang-gun',\n    location_gyeongsangbuk_mungyeong_si: 'Mungyeong-si',\n    location_gyeongsangbuk_gyeongsan_si: 'Gyeongsan-si',\n    location_chungcheongnam_hongseong: 'Hongseong-gun',\n    location_gyeongsangbuk_gunwi: 'Gunwi-gun',\n    location_chungcheongnam_yesan: 'Yesan-gun',\n    location_gyeongsangbuk_uiseong: 'Uiseong-gun',\n    location_chungcheongnam_taean: 'Taean-gun',\n    location_gyeongsangbuk_cheongsong: 'Cheongsong-gun',\n    location_chungcheongbuk: 'Chungcheongbuk-do',\n    location_gyeongsangbuk_goryong: 'Yeongyang-gun',\n    location_chungcheongbuk_cheongju: 'Cheongju-si',\n    location_gyeongsangbuk_yeongdeok: 'Yeongdeok-gun',\n    location_gyeongsangbuk_cheongdo: 'Cheongdo-gun',\n    location_chungcheongbuk_chungju: 'Chungju-si',\n    location_gyeongsangbuk_golyeong: 'Goryeong-gun',\n    location_chungcheongbuk_jecheon: 'Jecheon-si',\n    location_gyeongsangbuk_seongju: 'Seongju-gun',\n    location_chungcheongbuk_boeun: 'Boeun-gun',\n    location_gyeongsangbuk_chilgok: 'Chilgok-gun',\n    location_chungcheongbuk_okcheon: 'Okcheon-gun',\n    location_gyeongsangbuk_yecheon: 'Yecheon-gun',\n    location_chungcheongbuk_yeongdong: 'Yeongdong-gun',\n    location_gyeongsangbuk_bonghwa: 'Bonghwa-gun',\n    location_chungcheongbuk_jeungpyeong: 'Jeungpyeong-gun',\n    location_gyeongsangbuk_uljin: 'Uljin-gun',\n    location_chungcheongbuk_jincheon: 'Jincheon-gun',\n    location_gyeongsangbuk_ulleung: 'Ulleung-gun',\n    location_chungcheongbuk_goesan: 'Goesan-gun',\n    location_gwangju: 'Gwangju',\n    location_chungcheongbuk_eumseong: 'Eumseong-gun',\n    location_gwangju_dong_gu: 'Dong-gu',\n    location_chungcheongbuk_danyang: 'Danyang-gun',\n    location_gwangju_seo_gu: 'Seo-gu',\n    location_gwangju_nam_gu: 'Nam-gu',\n    location_gwangju_buk_gu: 'Buk-gu',\n    location_gwangju_gwangsan_gu: 'Gwangsan-gu',\n    location_daegu: 'Daegu',\n    location_daegu_jung_gu: 'Jung-gu',\n    location_daegu_dong_gu: 'Dong-gu',\n    location_daegu_seo_gu: 'Seo-gu',\n    location_daegu_nam_gu: 'Nam-gu',\n    location_daegu_buk_gu: 'Buk-gu',\n    location_daegu_suseong_gu: 'Suseong-gu',\n    location_daegu_dalseo_gu: 'Dalseo-gu',\n    location_daegu_dalseong: 'Dalseong-gun',\n    location_daegu_gunwi: 'Gunwi-gun',\n    location_daejeon: 'Daejeon',\n    location_daejeon_dong_gu: 'Dong-gu',\n    location_daejeon_jung_gu: 'Jung-gu',\n    location_daejeon_seo_gu: 'Seo-gu',\n    location_daejeon_yuseong_gu: 'Yuseong-gu',\n    location_daejeon_daedeok_gu: 'Daedeok-gu',\n    location_busan: 'Busan',\n    location_busan_jung_gu: 'Jung-gu',\n    location_busan_seo_gu: 'Seo-gu',\n    location_busan_dong_gu: 'Dong-gu',\n    location_busan_yeongdo_gu: 'Yeongdo-gu',\n    location_busan_busanjin_gu: 'Busanjin-gu',\n    location_busan_dongnae_gu: 'Dongnae-gu',\n    location_busan_nam_gu: 'Nam-gu',\n    location_busan_buk_gu: 'Buk-gu',\n    location_busan_haeundae_gu: 'Haeundae-gu',\n    location_busan_saha_gu: 'Saha-gu',\n    location_busan_geumjeong_gu: 'Geumjeong-gu',\n    location_busan_gangseo_gu: 'Gangseo-gu',\n    location_busan_yeonje: 'Yeonje-gu',\n    location_busan_suyeong_gu: 'Suyoung-gu',\n    location_busan_sasang_gu: 'Sasang-gu',\n    location_busan_gijang: 'Gijang-gun',\n    location_sejong: 'Sejong-si',\n    location_ulsan: 'Ulsan',\n    location_ulsan_jung_gu: 'Jung-gu',\n    location_ulsan_nam_gu: 'Nam-gu',\n    location_ulsan_dong_gu: 'Dong-gu',\n    location_ulsan_buk_gu: 'Buk-gu',\n    location_ulsan_ulju: 'Ulju-gun',\n    location_incheon: 'Incheon',\n    location_incheon_jung_gu: 'Jung-gu',\n    location_incheon_dong_gu: 'Dong-gu',\n    location_incheon_nam_gu: 'Michuhol-gu',\n    location_incheon_yeonsu_gu: 'Yeonsu-gu',\n    location_incheon_namdong_gu: 'Namdong-gu',\n    location_incheon_bupyeong_gu: 'Bupyeong-gu',\n    location_incheon_gyeyang_gu: 'Gyeyang-gu',\n    location_incheon_seo_gu: 'Seo-gu',\n    location_incheon_ganghwa: 'Ganghwa-gun',\n    location_incheon_ongjin_gun: 'Ongjin-gun',\n    location_jeollanam: 'Jeollanam-do',\n    location_jeollanam_mokpo: 'Mokpo-si',\n    location_jeollanam_yosu: 'Yeosu-si',\n    location_jeollanam_suncheon_si: 'Suncheon-si',\n    location_jeollanam_naju: 'Naju-si',\n    location_jeollanam_gwangyang_si: 'Gwangyang-si',\n    location_jeollanam_damyang: 'Damyang-gun',\n    location_jeollanam_gokseong: 'Gokseong-gun',\n    location_jeollanam_gurye: 'Gurye-gun',\n    width: 'width',\n    height: 'height',\n    desktop: 'desktop',\n    tablet: 'tablet',\n    smartphone: 'smartphone',\n};\nLang.video_body_coord_params = {\n    left_eye: 'left eye',\n    right_eye: 'right eye',\n    nose: 'nose',\n    left_mouth: 'left corner of lips',\n    right_mouth: 'right corner of lips',\n    upper_lip: 'upper lip',\n    lower_lip: 'lower lip',\n    face: 'face',\n    neck: 'neck',\n    left_ear: 'left ear',\n    right_ear: 'right ear',\n    left_shoulder: 'left shoulder',\n    left_elbow: 'left elbow',\n    left_wrist: 'left wrist',\n    left_hip: 'left hip',\n    left_knee: 'left knee',\n    left_ankle: 'left ankle',\n    right_shoulder: 'right shoulder',\n    right_elbow: 'right elbow',\n    right_wrist: 'right wrist',\n    right_hip: 'right hip',\n    right_knee: 'right knee',\n    right_ankle: 'right ankle',\n};\nLang.video_gender = {\n    male: 'Male',\n    female: 'Female',\n};\nLang.video_emotion_params = {\n    angry: 'Anger',\n    disgusted: 'Disgust',\n    fearful: 'Fearful',\n    happy: 'Happiness',\n    neutral: 'Neutral',\n    sad: 'Sadness',\n    surprised: 'Surprised',\n    disgust: 'Disgust',\n    fear: 'Fearful',\n    surprise: 'Surprised',\n};\nLang.video_object_params = {\n    person: 'Person',\n    bicycle: 'Bicycle',\n    car: 'Car',\n    motorcycle: 'Motorcycle',\n    airplane: 'Airplane',\n    bus: 'Bus',\n    train: 'Train',\n    truck: 'Truck',\n    boat: 'Boat',\n    'traffic light': 'Traffic light',\n    'fire hydrant': 'Fire hydrant',\n    'stop sign': 'Stop sign',\n    'parking meter': 'Parking meter',\n    bench: 'Bench',\n    bird: 'Bird',\n    cat: 'Cat',\n    dog: 'Dog',\n    horse: 'Horse',\n    sheep: 'Sheep',\n    cow: 'Cow',\n    elephant: 'Elephant',\n    bear: 'Bear',\n    zebra: 'Zebra',\n    giraffe: 'Giraffe',\n    backpack: 'Backpack',\n    umbrella: 'Umbrella',\n    handbag: 'Handbag',\n    tie: 'Tie',\n    suitcase: 'Suitcase',\n    frisbee: 'Frisbee',\n    skis: 'Skis',\n    snowboard: 'Snowboard',\n    'sports ball': 'Sports ball',\n    kite: 'Kite',\n    'baseball bat': 'Baseball bat',\n    'baseball glove': 'Baseball glove',\n    skateboard: 'Skateboard',\n    surfboard: 'Surfboard',\n    'tennis racket': 'Tennis racket',\n    bottle: 'Bottle',\n    'wine glass': 'Wine glass',\n    cup: 'Cup',\n    fork: 'Fork',\n    knife: 'Knife',\n    spoon: 'Spoon',\n    bowl: 'Bowl',\n    banana: 'Banana',\n    apple: 'Apple',\n    sandwich: 'Sandwich',\n    orange: 'Orange',\n    broccoli: 'Broccoli',\n    carrot: 'Carrot',\n    'hot dog': 'Hot dog',\n    pizza: 'Pizza',\n    donut: 'Donut',\n    cake: 'Cake',\n    chair: 'Chair',\n    couch: 'Couch',\n    'potted plant': 'Potted plant',\n    bed: 'Bed',\n    'dining table': 'Dining table',\n    toilet: 'Toilet',\n    tv: 'Tv',\n    laptop: 'Laptop',\n    mouse: 'Mouse',\n    remote: 'Remote',\n    keyboard: 'Keyboard',\n    'cell phone': 'Cell phone',\n    microwave: 'Microwave',\n    oven: 'Oven',\n    toaster: 'Toaster',\n    sink: 'Sink',\n    refrigerator: 'Refrigerator',\n    book: 'Book',\n    clock: 'Clock',\n    vase: 'Vase',\n    scissors: 'Scissors',\n    'teddy bear': 'Teddy bear',\n    'hair drier': 'Hair dryer',\n    toothbrush: 'Toothbrush',\n};\nLang.Buttons = {\n    share_policy: 'Share Guide',\n    write_policy: 'Write Guide',\n    lesson_list: 'List',\n    complete_study: 'Complete',\n    show_me: 'Show Me',\n    do_this_for_me: 'Do This For Me',\n    previous: 'Previous ',\n    get_started: 'Get Started',\n    next_lesson: 'Next lesson',\n    course_submit: 'Submit',\n    course_done: 'OK',\n    mission: 'Introduction ',\n    basic_guide: 'User Guide',\n    apply: 'Apply',\n    add: 'Add',\n    cancel: 'Cancel',\n    save: 'Save',\n    start: 'Start',\n    confirm: 'OK',\n    delete: 'Delete',\n    create: 'Create Class',\n    done: 'Done',\n    accept: 'Accept',\n    select: 'Select',\n    refuse: 'Refuse',\n    yes: 'Yes',\n    button_no: 'No',\n    quiz_retry: 'Try Again',\n    discuss_upload: 'Upload',\n    maze_popup_guide: 'User Guide',\n    maze_popup_mapHint: 'Hint',\n    maze_hint_btn_guide: 'User Guide',\n    maze_hint_btn_block: 'Block Help',\n    maze_hint_btn_map: 'Map Hint',\n    maze_hint_btn_goal: 'goal',\n    list_save: 'Upload',\n    duplication: 'Copy',\n    export_to_excel: 'Download',\n    convert_table: 'Export to table',\n    single_line: 'Single line',\n    multi_line: 'Multi line',\n    lecture_finish_popup_reset_lecture: 'Do it again',\n    lecture_finish_popup_show_output: 'See the exercised',\n    lecture_view_hints: 'View hints',\n    default_hint_title: 'How do you make it?',\n    show_only_vector: 'Only Vector',\n    sound_menu_trim: 'Trim',\n    sound_menu_adjust: 'Adjust',\n    sound_button_reset: 'Reset',\n    sound_button_save: 'Save',\n    back: 'Go back',\n    add2: 'Add',\n    load: 'Load',\n    move: 'Move',\n    create_new_table: 'Create',\n    add_variable: 'Add variable',\n    add_list: 'Add list',\n    add_message: 'Add Message',\n};\nLang.Menus = {\n    nothing_to_import: 'There is no content to upload.',\n    nothing_to_export: 'There is no content to download.',\n    content_copied: 'The data is copied.',\n    list_import_title: 'Import',\n    list_import_placeholder: 'Example)\\nData1\\nData2\\nData3',\n    verifying_email: 'Verifying email',\n    list_import_notice_1: 'You can enter items and default values in a list at once.',\n    list_import_notice_2: 'The items and default values entered here are saved as a list.',\n    list_export_title: 'Export',\n    list_export_notice1: 'You can copy the items in the list directly or',\n    list_export_notice2: 'export them to a file or table.',\n    list_export_notice: 'You can copy or download the data in the list.',\n    robotis_opencm70: 'Robotis Open CM70',\n    cannnot_mark_favorite: 'Private project cannot be marked as a favorite.',\n    enterPassword: 'Enter password.',\n    enterPassword_update: 'Please enter your password to save your changes.',\n    enterNewPassword: 'Enter new password.',\n    reEnterNewPassword: 'Re-enter new password.',\n    resign: 'Account deletion',\n    check_sended_email: 'Please check your inbox to verify your email.',\n    signUpEmail_1: 'Verification mail has been sent. ',\n    signUpEmail_2: 'Please verify your email.',\n    select_email_unauthenticated_user:\n        'The email address is registered to the IDs below.\\nPlease choose the right one.',\n    select_user: 'Please choose the ID.',\n    enter_password_withdraw: 'Enter password to delete your account',\n    instruction_agree: 'Please check instruction and agree.',\n    check_instructions: 'I check instructions and agree.',\n    deleteAccount_2:\n        'After 30 days, every data that you created in Entry such as project/lecture/class/post/comment/like/favourite will be deleted and cannot be restored.',\n    deleteAccount_1: 'If you sign in again within 30 days, you can withdraw account deletion.',\n    protect_account: 'Protect your account with a safe password.',\n    please_verify: \"Please verify your email to click 'Verifying email'\",\n    unverified_email: 'Unverified email',\n    deleteAccount: 'Delete account',\n    corporatePersonal: 'Agree to the transfer of personal information.',\n    corporateTransferGuide: 'Personal Information transfer guide',\n    corporateReciever: 'Information reciever : Connect Foundation',\n    corporateAddress: 'Connect Foundation Address&Contact',\n    corporateAddress_1: 'Meritz Tower 7, Seoul Gangnam-gu Gangnam-daero 382, Seoul, Korea',\n    corporateConsent:\n        'If you do not want to transfer your information, you may withdraw the consent.',\n    corporateEmail: 'For withdraw the consent, send an email to',\n    corporateAddition:\n        'In addition, the terms and conditions of the agreement will be changed, depending on the transfer.',\n    corporateApplicationDate: 'Application date : From October 29, 2017',\n    corporateTargetChanges: 'Application Targets and Changes : ',\n    corporateTarget: 'Targets',\n    corporateChanges: 'Changes',\n    corporateTerms: 'Terms',\n    corporateOperator: 'The name of the ‘Entry’ operator',\n    corporateClassroomTerms: 'Classroom Service Terms of Use',\n    doAgreeWithClassroomTerms: 'Agree to the Classroom Service Terms of Use.',\n    doChangePassword: 'Please change the password into the one that only you can know.',\n    corporatePrivacyPolicy: 'Privacy Policy',\n    corporateConsignment:\n        'The name of the ‘Entry’ operator. And consignment of personal information',\n    corporateEntrusted: 'Entrusted Company : NHN Technology Services Corporation.',\n    corporateConsignmentDetails: 'Details of Consignment : Service operation.',\n    corporatePeriod:\n        'Consignment Period : Until the member cancels membership or the consignment contract ends.',\n    corporateChangeDate: 'Date of change : October 29, 2017',\n    corporateWarning: 'Please Agree to the transfer of personal information.',\n    corporateConfirm: 'Confirm',\n    corporateTitle:\n        \"Hello. This is EntryLabs.<br> We are very grateful to you who are using 'Entry'. <br>Recently we have agreed to transfer the ownership of Entry web site, which has been operated for public interest purposes, to the 'Connect Foundation'.<br>Connect Foundation is a non-profit foundation founded by Naver. 'Entry' will be continuously operated under public interest purpose by 'Connect Foundation'. Therefore, All of “Entry” users will be guaranteed to use the entry exactly as same as before.<br>Since the website provider has changed from the 'EntryLabs' to the 'Connect Foundation', there is a transfer of personal information as below. However, this doesn’t mean that your information will be physically moved.<br>\",\n    textcoding_numberError_f:\n        \"You can't convert into the text mode if there is function names start with a number.\",\n    textcoding_bookedError_1f: \"You can't convert into the text mode if there is function named \",\n    textcoding_bookedError_2f: '.',\n    textcoding_specialCharError_f:\n        \"You can't convert into the text mode if there is function names include special character except for underscore.\",\n    textcoding_numberError_v:\n        \"You can't convert into the text mode if there is variable names start with a number.\",\n    textcoding_bookedError_1v: \"You can't convert into the text mode if there is variable named \",\n    textcoding_bookedError_2v: '.',\n    textcoding_specialCharError_v:\n        \"You can't convert into the text mode if there is variable names include special character except for underscore.\",\n    textcoding_numberError_l:\n        \"You can't convert into the text mode if there is list names start with a number.\",\n    textcoding_bookedError_1l: \"You can't convert into the text mode if there is list named \",\n    textcoding_bookedError_2l: '.',\n    textcoding_specialCharError_l:\n        \"You can't convert into the text mode if there is list names include special character except for underscore.\",\n    no_discuss_permission: \"You don't have permission to view this post.\",\n    delete_comment: 'Are you sure you want to delete commnet',\n    delete_article: 'Are you sure you want to delete article',\n    discuss_cannot_edit: 'You cannot edit this post',\n    discuss_extention: 'You cannot upload files with that extension',\n    delete_discuss_picture: 'Do you want to delete the photo?',\n    delete_discuss_file: 'Do you want to delete the file?',\n    discuss_save_question: 'Do you want save your post?',\n    discuss_cancle_question: 'Do you want to leave without saving?',\n    discuss_saved: 'is saved',\n    discuss_no_write_permission: 'Cannot be saved with the current login account.',\n    discuss_no_project_permission: 'Cannot be saved with the current login account.',\n    discuss_write_abuse_detected:\n        'Several articles have been written within a \\nshort period of time. \\nPlease try again in 1 minutes.',\n    contents_abuse_detected: 'Please try again in 5 minutes.',\n    contents_abuse_detected_10: 'Please try again in 10 minutes.',\n    discuss_new_write_abuse_warn:\n        'Posting multiple comments within a \\nshort period of time may limit the post \\nof comments.\\nBe careful of your use.',\n    discuss_write_abuse_warn:\n        'Posting multiple comments within a \\nshort period of time may limit the post \\nof comments.\\nBe careful of your use.',\n    find_not_your_email: 'Please enter a valid email.',\n    search_lang: 'search',\n    search_title: 'title',\n    faq_desc: 'Check the answers for the questions you had while using the Entry.',\n    faq_all: 'Total',\n    faq_site: 'Site guide',\n    faq_project: 'Project',\n    faq_hardware: 'Hardware',\n    faq_offline: 'Offline editor',\n    faq_copyright: 'Copyright',\n    faq_title: 'FAQ',\n    faq: 'FAQ',\n    malicious_warning:\n        \"You cannot attach an unwholesome image. If the image doesn't unwholesome, please report it.\",\n    fword_alert_msg: 'You can not post abusive or malicious sentences.',\n    fword_alert_1: 'You can not post abusive comments or malicious comments',\n    fword_alert_2:\n        'Your post will be replaced alternative sentence because it contains unhealthy words.',\n    fword_replace_1: 'Entry is an education platform created to help anyone learn to code.',\n    fword_replace_2: 'Entry is an education platform created to help anyone learn to code.',\n    fword_replace_3: 'Entry is an education platform created to help anyone learn to code.',\n    fword_replace_4: 'Entry is an education platform created to help anyone learn to code.',\n    fword_replace_5: 'Entry is an education platform created to help anyone learn to code.',\n    fword_replace_6: 'Entry is an education platform created to help anyone learn to code.',\n    fword_replace_7: 'Entry is an education platform created to help anyone learn to code.',\n    solve_quiz: 'Quiz',\n    submit_homework_first_title: 'Complete! Submit an assignment',\n    submit_homework_first_content:\n        'Great work is done! Submit your assignment.<br>You may resubmit your assignment before the deadline.',\n    submit_homework_again_title: 'Resubmit',\n    submit_homework_again_content:\n        'This project has been submitted already.<br>Would you like to resubmit?',\n    submit_homework_expired_title: 'Submission Closed',\n    submit_homework_expired_content: 'Assignment deadline is over.',\n    done_study_title: 'Complete',\n    done_study_content: 'Fabulous project is complete',\n    featured_courses: 'Featured Courses',\n    follow_along: 'Follow Along',\n    follow_along_desc: 'Create various projects as you follow along step by step.',\n    do_quiz: 'Quiz',\n    do_quiz_desc: 'Check your knowledge through quizzes.',\n    challenge: 'Challenge',\n    play: 'Play',\n    challenge_desc: 'Learn programming concepts by solving problems.',\n    creste_freely: 'Create freely',\n    creste_freely_desc: \"Create your projects using what you've learned.\",\n    entry_rc_desc: 'Learn programming concepts in steps with Entry lectures! Start now!',\n    hw_deadline: 'Deadline',\n    rc_course_desc: 'Lecture collection created for learning programming concepts level by level',\n    rc_course: 'Entry Recommended Courses',\n    entry_rec_course: 'Entry Recommended Courses',\n    entry_rec_course_desc:\n        'Anyone can follow along and easily create projects with Entry Lectures.',\n    guidance: 'Guidance',\n    wait: 'Wait',\n    hint: 'Hint',\n    concept_guide: 'Concept Guide',\n    group_quiz: 'Quiz',\n    fail_check_hint: 'Oh no! Try again!<br>Check [Hint] if you are stuck!',\n    sort_student: 'Student',\n    sort_lesson: 'Lesson',\n    sort_course: 'Course',\n    student_progress: 'Student Progress',\n    my_progress: 'Progress',\n    lec_in_progress: 'in progress',\n    free_modal_asgn_over: 'Assignment deadline is over.',\n    free_submission_closed: 'Submission Closed',\n    free_modal_asgn_submit_first:\n        'Great work is done! Submit your assignment.<br>You may resubmit your assignment before the deadline.',\n    asgn_submit: 'Complete! Submit an assignment.',\n    free_modal_content_resubmit:\n        'This project has been submitted already.<br>Would you like to resubmit?',\n    asgn_resubmit: 'Resubmit',\n    free_modal_content_complete: 'Fabulous Project is complete.',\n    guide_modal_content_complete: \"Let's run the program\",\n    success: 'Success',\n    fail: 'Fail',\n    mission_modal_content_fail: '<br>Check [Hint] if you are stuck!',\n    mission_modal_content_success: \"Let's run the program\",\n    in_progress: 'in progress',\n    completed: 'Completed',\n    submitted: 'submitted',\n    submission_closed: 'Submission Closed',\n    progress: 'Progress',\n    study_completed: 'completed',\n    view_course_desc: 'View Description',\n    main_entry_starter: 'From basics! Entry Starter',\n    main_entry_booster: 'Concepts! Entry Booster',\n    main_entry_master: 'Ideas unfold! Entry Master',\n    no_students_in_classroom: 'No students yet.<br>Please add or invite students.',\n    lectures: 'lessons',\n    Lectures: 'Lessons',\n    studentHomeworkList: 'assignment',\n    curriculums: 'courseware',\n    Curriculums: 'Courseware',\n    quiz: 'quiz',\n    no_added_group_contents_teacher: 'There is no %1. <br>Please create a %1.',\n    no_added_group_contents_student: 'There is no %1.',\n    side_project: 'Goal project',\n    custom_make_course_1: 'Create courseware from',\n    custom_make_course_2: \"'Create lessons > Create Courseware'\",\n    custom_make_lecture_1: \"Create lessons from 'open lessons'\",\n    custom_make_lecture_2: '',\n    alert_enter_info: 'Please enter your information',\n    alert_enter_new_pwd: 'Enter new password',\n    alert_match_pwd: \"Password doesn't match the confirmation\",\n    alert_check_pwd: 'Please check your password',\n    alert_update_complete: 'Edit complete',\n    no_group_contents_each_prefix: 'There is no ',\n    no_group_contents_each_suffix: ' in our classroom.',\n    no_group_contents_all: 'There is no new content.<br>Share projects in My Classroom gallery.',\n    hw_closed: 'submission closed',\n    tag_Lecture: 'Lessons',\n    tag_Curriculum: 'Courseware',\n    tag_Discuss: 'Discuss',\n    count_ko: '.',\n    no_asgn_within_week: 'There is no assignment due within a week',\n    lecture_and_curriculum: 'Open Lessons',\n    assignments_plural: 'Assignments',\n    assignments_singular: 'Assignment',\n    project_plural: 'Projects',\n    group_news: 'News',\n    stu_management: 'Student management',\n    stu_management_camel: 'Student Management',\n    view_all: 'View all',\n    view_all_camel: 'View All',\n    view_contents_camel: 'View All',\n    view_contents: 'Contents',\n    no_updated_news: 'There is no update',\n    homework_soon_due: 'Assignment soon due',\n    new_homework: 'New Assignment',\n    no_new_homework: 'There is no new Assignment',\n    student_plural: 'Students',\n    discuss: 'notice',\n    basic_project: 'Basic Project',\n    no_permission: 'You have no permission.',\n    no_comment_write_permission: 'Cannot write comments with the currently logged in account.',\n    original_curriculum_deleted: 'The original courseware was deleted',\n    original_curriculum: 'Original courseware',\n    save_as_my_lecture: 'Save as My Lecture',\n    delete_confirm: 'Confirm',\n    lecture_open_as_copied: 'All lectures in Open Lesson are saved as copy and open to public view',\n    curriculum_open_as_copied:\n        'All Courseware listed under Open Lesson are saved as copy and open to public view',\n    lecture_save_as_copied_group:\n        'All lectures in My Class Lecture are saved as copy and open to public view',\n    curriculum_save_as_copied_group:\n        'All Lecture Collection listed under My Class Lecture Collection are saved as copy and open to public view',\n    homework_save_as_copied_group:\n        'All Assignments listed under Class Assignment page are saved as copy and open to public view',\n    lecture_save_as_copied: 'Lecture inserted in the Lecture collection is saved as a copy.',\n    done_project_save_as_copied: 'Completed project inserted in the Lecture is saved as a copy.',\n    textbook_project_can_not_applied: '',\n    original_lecture_deleted: 'The original lecture was deleted',\n    original_lecture: 'Original lecture',\n    lecture_save_as_mine_alert: \"Saved.\\nnSaved Lecture is listed under 'My Page > My Lecture'\",\n    lecture_save_as_mine: 'Save as My Lecture',\n    duplicate_username: 'The ID you entered is already in use',\n    share_your_project: '',\n    not_available_student:\n        \"ID entered is class issued 'Class ID'. \\nPlease enter 'Entry Member ID'.\",\n    login_instruction: 'Log-in instructions',\n    login_needed: 'Service is available after log-in',\n    login_as_teacher: 'Log in as Teacher to use the service',\n    remove_my_storage:\n        'Are you sure to remove it from my storage? Deleted blocks/objects cannot be recovered.',\n    submit_hw: 'submit',\n    success_goal: 'Success',\n    choseok_final_result: 'Great! I completed my own project!',\n    choseok_fail_msg_timeout: '시간이 너무 많이 지나버렸어. 목표를 잘 보고 다시 한번 도전해봐!',\n    choseok_fail_msg_die:\n        '생명이 0이하인데 게임이 끝나지 않았어.\\n아래의 블록을 사용해서 다시 도전해 보는 건 어때?',\n    grade_1: 'Basic',\n    grade_2: 'Intermediate',\n    grade_3: 'Advanced',\n    find_sally_title: 'Finding Sally',\n    save_sally_title: 'Saving Sally',\n    exit_sally_title: 'Escaping',\n    find_sally:\n        'Combine the power of the LINE Rangers\\nand defeat the powerful villain Mephisto\\nand save Sally!',\n    save_sally:\n        \"Sally is trapped at Mephisto's base.\\nHelp the LINE Rangers get to Sally by avoiding\\nobstacles!\",\n    exit_sally: 'Help Sally and LINE Rangers escape safely\\nfrom the exploding Mephisto base!',\n    go_next_mission: '다른 미션 도전하기',\n    share_my_project: '내가 만든 작품 공유하기',\n    share_certification: '인증서 공유하기',\n    print_certification: '인증서를 뽐내봐',\n    get_cparty_events: '내가 받은 인증서를 출력해 뽐내면 푸짐한 상품을 받을 수 있어요!',\n    go_cparty_events: '이벤트 참여하러 가기',\n    codingparty2016_blockHelper_1_title: '',\n    codingparty2016_blockHelper_1_contents: '',\n    codingparty2016_blockHelper_2_title: '',\n    codingparty2016_blockHelper_2_contents: '',\n    codingparty2016_blockHelper_3_title: '',\n    codingparty2016_blockHelper_3_contents: '',\n    codingparty2016_blockHelper_4_title: '',\n    codingparty2016_blockHelper_4_contents: '',\n    codingparty2016_blockHelper_5_title: '',\n    codingparty2016_blockHelper_5_contents: '',\n    codingparty2016_goalHint_1: '',\n    codingparty2016_goalHint_2: '',\n    codingparty2016_goalHint_3: '',\n    codingparty2016_goalHint_4: '',\n    codingparty2016_goalHint_5: '',\n    codingparty2016_goalHint_6: '',\n    codingparty2016_goalHint_7: '',\n    codingparty2016_goalHint_8: '',\n    codingparty2016_goalHint_9: '',\n    codingparty2016_guide_1_1_contents: '',\n    codingparty2016_guide_1_1_title: '',\n    codingparty2016_guide_1_2_title: '',\n    codingparty2016_guide_1_2_contents: '',\n    codingparty2016_guide_1_3_title: '',\n    codingparty2016_guide_1_3_contents: '',\n    codingparty2016_guide_1_4_title: '',\n    codingparty2016_guide_1_4_contents: '',\n    codingparty2016_guide_1_5_title: '',\n    codingparty2016_guide_1_5_contents: '',\n    codingparty2016_guide_2_1_title: '',\n    codingparty2016_guide_2_1_contents: '',\n    codingparty2016_guide_3_1_title: '',\n    codingparty2016_guide_3_1_contents: '',\n    codingparty2016_guide_5_1_title: '',\n    codingparty2016_guide_5_1_contents: '',\n    codingparty2016_guide_5_2_title: '',\n    codingparty2016_guide_5_2_contents: '',\n    codingparty2016_guide_7_1_title: '',\n    codingparty2016_guide_7_1_contents: '',\n    codingparty2016_guide_9_1_title: '',\n    codingparty2016_guide_9_1_contents: '',\n    codingparty2016_guide_9_2_title: '',\n    codingparty2016_guide_9_2_contents: '',\n    find_interesting_lesson: \"Browse through 'Class lessons’ section to find interesting lessons!\",\n    find_interesting_course:\n        \"Browse through 'Class courseware’ section to find interesting courseware!\",\n    select_share_settings: 'Select share settings',\n    faq_banner_title: 'FAQ',\n    check_out_faq: 'Check out Entry’s FAQ',\n    faq_banner_content:\n        'Do you have any question about Entry?<br />We give you the answer in FAQ.<br />Find out now!',\n    faq_banner_button: 'Go to FAQ',\n    major_updates: 'Major updates',\n    check_new_update: \"Check out\\nEntry's new updates\",\n    major_updates_notification: \"Entry's major updates are announced by notification. \",\n    find_out_now: 'Find out now!',\n    offline_hw_program: 'Offline and Hardware Connection Program',\n    read_more: 'read more',\n    sample_project: 'Sample Project',\n    not_supported_function: 'This tablet does not support this feature.',\n    offline_download_confirm:\n        'Entry Offline Editor is available for PC. Would you like to download?',\n    hardware_download_confirm:\n        'Entry Hardware Program is available for PC. Would you like to download?',\n    copy_text: 'Copy text.',\n    select_openArea_space: 'Select share settings',\n    mission_guide: 'Mission guide',\n    of: \" 's  \",\n    no_results_found: 'No results found',\n    upload_pdf: 'Upload PDF materials',\n    select_basic_project: 'Select Project',\n    try_it_out: 'TRY IT OUT',\n    go_boardgame: 'ENTRY-Bot Board Game',\n    go_cardgame: 'ENTRY Bot Card game',\n    go_solve: 'Learn programming',\n    go_ws: 'Entry Create',\n    go_arts: 'Entry Share',\n    group_delete_alert:\n        'Once you delete this class, all data including temporary student accounts will be deleted.\\nAre you sure you want to delete?',\n    view_arts_list: 'list',\n    hw_submit_confirm_alert: 'Assignment submitted',\n    hw_submit_alert: 'Would you like to submit your assignment?',\n    hw_submit_alert2:\n        \"Would you like to submit your assignment? Submission will only submit what you've completed.\",\n    hw_submit_cannot: 'You cannot submit this assignment',\n    see_other_missions: 'See other missions',\n    project: 'Project',\n    marked: 'favorite',\n    group: 'Group',\n    lecture: 'Lessons',\n    Lecture: 'Lessons',\n    curriculum: 'Courseware',\n    Curriculum: 'Courseware',\n    studying: 'studying',\n    open_only_shared_lecture:\n        '<b>오픈 강의</b> 페이지에 <b><공개></b> 한 강의만 불러올 수 있습니다. 불러오고자 하는 <b>강의</b>의 <b>공개여부</b>를 확인해 주세요.',\n    already_exist_group: 'group already exists',\n    cannot_invite_you: \"Can't invite by yourself\",\n    apply_original_image: 'Save original image',\n    draw_new_ques: \"Are you sure you want to go to \\n'Draw new object' page?\",\n    draw_new_ques_1: 'You can draw an object and save it.',\n    draw_new_ques_2: 'Do you want to move to draw?',\n    draw_new_go: 'Move',\n    draw_new_stay: 'No, Stay',\n    file_upload_warn_title_image:\n        'The following pictures are subject to the Terms of Use and related laws.',\n    file_upload_warn_desc_image:\n        'Violent and brutal picture, Sacred body exposure picture, Offensive or disgusting picture, Picture of copyright prohibited from unauthorized use',\n    file_upload_warn_title_sound:\n        'The following sounds are subject to the Terms of Use and related laws.',\n    file_upload_warn_desc_sound:\n        'Violent and cruel sound, Suggestive sound, Offensive or disgusting sound, Sound of copyright prohibited from unauthorized use',\n    file_upload_warn_title_table:\n        'The following datas are subject to the Terms of Use and related laws.',\n    file_upload_warn_desc_table:\n        'Violent and brutal data, Sacred body exposure data, Offensive or disgusting data, Data of copyright prohibited from unauthorized use',\n    file_upload_warn_link: 'Learn about copyright',\n    file_upload_desc_1: \"Make sure you don't upload\",\n    file_upload_desc_2: 'Violent and brutal picture',\n    file_upload_desc_3: 'Sacred body exposure picture',\n    file_upload_desc_4: 'Offensive or disgusting picture',\n    file_upload_desc_5:\n        '* Uploading of above contents may be restricted under user policy and related laws.',\n    picture_upload_warn_old: 'You can only upload jpg, png, bmp files that are less than 10MB.',\n    sprite_upload_warn_old:\n        'You can only upload images in jpg, png, bmp format or objects in eo format that are less than 10MB.',\n    picture_upload_warn_1:\n        'You can only upload jpg, png, bmp, svg files that are less than 5MB.\\nThe jpg, png, and bmp images are edited in bitmap mode and the svg image is in vector mode.',\n    table_upload_warn_1: 'You can only upload csv, xls(x) files that are less than 10MB.',\n    sprite_upload_warn:\n        'You can only upload images in jpg, png, bmp, svg format or objects in eo format that are less than 5MB.',\n    sound_upload_warn_1: 'You can only upload mp3 files that are less than 10MB.',\n    sound_edit_warn: \"Please wait!\\nWe're working on the Sound Editing function.\",\n    file_upload_loading: 'Loading',\n    lesson_by_teacher: 'Teacher created lesson',\n    delete_group_art: 'from the list?',\n    elementary_short: 'elementary',\n    middle_short: 'middle school',\n    grade_34: '3-4th',\n    grade_56: '5-6th',\n    grade_78: '7+',\n    share_lesson: 'sharing lesson',\n    share_course: 'sharing courseware',\n    from_list_ko: '',\n    comming_soon: 'Coming soon',\n    no_class_alert:\n        \"Class selected does not exist. To create a class, go to 'My Class' to create a class.\",\n    students_cnt: '',\n    defult_class_alert_1: 'Do you want to set ',\n    defult_class_alert_2: '\\n as default class?',\n    default_class: 'Default classroom',\n    enter_hw_name: 'Enter Assignment name.',\n    hw_limit_20: 'You can created up to 20 assignments',\n    stu_example: 'Example)\\n John Doe\\n John Doe\\n John Doe',\n    hw_description_limit_200: 'Add assignment description. (within 200 characters)',\n    hw_title_limit_50: 'Enter Assignment name. (within 50 characters)',\n    create_project_class_1: 'Create projects you want to share ',\n    create_project_class_2: \"with the class from 'Create> Create Project'\",\n    create_lesson_assignment_1: 'Create lessons you want to add as',\n    create_lesson_assignment_2: \"course assignment from 'Create > Create lessons'\",\n    i_make_lesson: 'Create lessons',\n    lesson_to_class_1: \"'Favorite lessons you want to add as\",\n    lesson_to_class_2: \"course assignment from 'Learn > Open lessons'\",\n    studying_students: 'Student',\n    lessons_count: 'Number of Lessons',\n    group_out: 'Leave',\n    enter_group_code: 'Enter class code',\n    no_group_invite: 'There is no class invitation',\n    done_create_group: 'Class is created',\n    set_default_group: 'Set as default classroom',\n    edit_group_info: 'Modify class information',\n    edit_done: 'Edit complete',\n    alert_group_out: 'Do you want to leave the class?',\n    lesson_share_cancel: 'Cancel Sharing Lesson',\n    project_share_cancel: 'Cancel Sharing Project',\n    lesson_share_cancel_alert: 'Are you sure to change it?',\n    course_share_cancel: 'Cancel Sharing Courseware',\n    select_lesson_share: 'Select lesson to share',\n    select_project_share: 'Select project to share',\n    select_lesson_share_policy_1: 'Please check share settings',\n    select_lesson_share_policyAdd: 'Please check share settings',\n    select_lesson_share_project_1: 'Please check share settings',\n    select_lesson_share_policy_2: 'and copyright policies',\n    select_lesson_share_area: 'Select share settings',\n    select_project_share_area: 'Select share settings',\n    lesson_share_policy: \"I agree to Entry's Copyright Policies.\",\n    project_share_policy: \"I agree to Entry's Copyright Policies.\",\n    alert_agree_share: \"To share publicly, you must agree to Entry's copyright policies\",\n    alert_agree_all: 'Agree to all items',\n    select_course_share: 'Select courseware to share',\n    select_course_share_policy_1: 'Please check share settings',\n    select_course_share_policy_2: 'and copyright policies',\n    select_course_share_area: 'Select share settings',\n    course_share_policy: \"I agree to Entry's Copyright Policies.\",\n    issued: 'Issued',\n    code_expired: \"Code has expired. Press 'Reissue Code' button\",\n    accept_class_invite: 'Accept class invitation',\n    welcome_class: 'Welcome to the class.',\n    enter_info: 'Please enter your information.',\n    done_group_signup: 'You have successfully enrolled to this class',\n    enter_group_code_stu: 'Enter the class code sent from your teacher',\n    text_limit_50: 'Enter 50 characters or less.',\n    enter_class_name: 'Please enter your class name',\n    enter_grade: 'Please enter your  grade',\n    enter_class_info: 'Please enter your class introduction',\n    student_dup: 'exits in this class already.',\n    select_stu_print: 'Select student to print',\n    class_id_not_exist: 'The class ID does not exist',\n    error_try_again: 'Error occured. Please try again',\n    error_forbidden: 'You have no permission',\n    code_not_available: 'The code is not valid',\n    gnb_create_lessons: 'Create lessons',\n    study_lessons: 'Learn Lesson',\n    lecture_help_1:\n        'Select the base project that the learner will start building his/her project on.',\n    lecture_help_2: 'To see this help message again, click the button above.',\n    lecture_help_3: \"If 'add object' is not shown, adding or deleting object is not possible.\",\n    lecture_help_4: 'See PDF attachment to get help',\n    lecture_help_5: 'Select blocks needed to create project. Unselected blocks will be hidden.',\n    lecture_help_6:\n        'choose between block Coding and Entry Python to organize your learning environment.',\n    lecture_finish_popup_title: 'Re-learn',\n    lecture_finish_popup_content_1:\n        'Practice Completion Do you want to practice one step from the beginning?',\n    lecture_finish_popup_content_2: '* The practice completion status is maintained',\n    lecture_start_title: 'Start',\n    lecture_goal_title: 'Goal',\n    lecture_goal_content: 'Goal',\n    lecture_prepare_title: 'Prepare',\n    lecture_summary_title: 'Summary',\n    lecture_summary_content: \"Let's summarize what we learned.\",\n    lecture_quiz_title: 'Quiz',\n    lecture_quiz_content: \"Let's check what we learned through the verification problem.\",\n    lecture_quiz_check_answer: 'Check the answer',\n    default_hint_title: 'How do you make it?',\n    only_pdf: 'Only pdf file is uploadable',\n    enter_project_video: 'Enter at least one project or video',\n    enter_title: 'Enter title.',\n    enter_recommanded_grade: 'Enter recommanded grade.',\n    enter_level_diff: 'Enter level of difficulty.',\n    enter_time_spent: 'Enter time spent.',\n    enter_shared_area: 'Select at least one sharing space',\n    enter_goals: 'Enter goals',\n    enter_lecture_description: 'Enter lecture information',\n    enter_curriculum_description: 'Enter courseware information',\n    first_page: '처음 입니다.',\n    last_page: '마지막 입니다.',\n    alert_duplicate_lecture: 'The lesson is already registered',\n    enter_lesson_alert: 'Register one or more lessons',\n    open_edit_lessons: 'Open lesson to be edited',\n    saved_alert: 'was successfully saved.',\n    select_lesson_type: 'Select type of lesson you want to create.',\n    create_lesson: 'create lesson',\n    create_lesson_desc_1: 'create a lesson',\n    create_lesson_desc_2: 'according to learning objectives',\n    create_lesson_desc_3: 'for your course.',\n    create_courseware: 'Create courseware',\n    create_courseware_desc_1: 'put multiple lessons together',\n    create_courseware_desc_2: 'to create a courseware',\n    create_courseware_desc_3: '',\n    create_open_lesson: 'Create open lesson',\n    enter_lesson_info: 'Enter lesson information',\n    select_lesson_feature: 'Select lesson feature',\n    check_info_entered: 'Check information entered',\n    enter_lefo_lesson_long: 'Enter information about the lesson.',\n    lesson_info_desc:\n        'Select features and projects that learners will use to create optimal learning environment.',\n    provide_only_used: 'Only provide blocks used in the goal project',\n    see_help: 'See help',\n    select_done_project_1: 'Select',\n    select_done_project_2: 'the goal project',\n    select_done_project_3: 'that the learner is to create',\n    select_project: 'Select my project or my favorite project',\n    youtube_desc: 'Enter Youtube links',\n    lesson_video: 'Lesson video',\n    lesson_title: 'Lesson title',\n    recommended_grade: 'grade level',\n    selection_ko: '',\n    selection_en: 'Select',\n    level_of_diff: 'difficulty',\n    select_level_of_diff: 'Select difficulty',\n    enter_lesson_title: 'enter lesson title (in 30 characters or less)',\n    select_time_spent: 'Select time',\n    time_spent: 'time',\n    lesson_overview: 'Lesson Overview',\n    upload_materials: 'Upload course materials',\n    open: 'Open',\n    cancel: 'Cancel',\n    upload_lesson_video: 'Upload lesson video',\n    youtube_upload_desc: 'Insert Youtube link for course videos',\n    cancel_select: 'Undo select',\n    select_again: 'Select again',\n    goal_project: 'Goal',\n    upload_study_data:\n        'Upload learning materials that learners can view while building the project.',\n    upload_limit_20mb: 'Upload up to 20MB',\n    expect_time: 'Time spent',\n    course_videos: 'course videos',\n    enter_courseware_info: 'Enter courseware information',\n    enter_course_info: 'Enter courseware information',\n    select_lessons_for_course: 'Select lessons to create a courseware.',\n    course_build_desc_1: '',\n    course_build_desc_2: 'Up to 30 lessons',\n    course_build_desc_3: 'allowed.',\n    lseeon_list: 'show lesson List',\n    open_lessons: 'Open lessons',\n    course_title: 'Courseware title',\n    title_limit_30: 'Enter courseware title(within 30 characters)',\n    course_overview: 'Courseware Overview',\n    charactert_limit_200: 'Enter within 200 characters',\n    edit_lesson: 'Edit lesson',\n    courseware_by_teacher: 'Teacher created lesson collections',\n    select_lessons: 'Select lessons',\n    check_course_info: 'Check if the lesson collection information is correct',\n    select_share_area: 'Select sharing space',\n    upload_sub_project: 'Goal project upload',\n    file_download: 'Download file',\n    file_remove: 'Remove file',\n    check_lesson_info: 'Check if the lesson information is correct',\n    share_area: 'Sharing space',\n    enter_sub_project: 'Register side project',\n    lms_hw_title: 'Title',\n    lms_hw_ready: 'Ready',\n    lms_hw_progress: 'In progress',\n    lms_hw_complete: 'Complete',\n    lms_hw_not_submit: 'Unfinished',\n    lms_hw_closed: 'Closed',\n    submission_condition: 'Submission is allowed only for assignments in progress',\n    submit_students_only: 'Only students are allowed to submit assignments',\n    want_submit_hw: 'Are you sure you want to submit your assignment?',\n    enter_correct_id: 'Enter correct ID',\n    id_not_exist: 'The ID does not exist.',\n    agree_class_policy: 'Agree to class service usage policy.',\n    delete_class: 'Delete classs',\n    type_stu_name: 'Please enter the student name.',\n    invite_from_1: 'is invited to',\n    invite_from_2: '',\n    lms_pw_alert_1: 'Once you enter class,',\n    lms_pw_alert_2: 'teacher is allowed to reissue your login password.',\n    lms_pw_alert_3: 'Make sure that the invitation is from your teacher.',\n    invitation_accepted: 'Invitation Accepted!',\n    cannot_issue_pw: 'Password cannot be issued because invitation has not been accepted',\n    start_me_1: 'Start coding education',\n    start_me_2: 'with <Monthly Entry>!',\n    monthly_desc_1: 'Monthly Entry is a monthly distributed magazine created ',\n    monthly_desc_2: 'to help teachers learn to teach programming in fun and easy way.',\n    monthly_desc_3: 'Check out the fun cartoons and programming contents every month!',\n    monthly_desc_4: '* The Monthly Entry has ceased publication.',\n    monthly_desc_5: 'Download educational materials from the Educational Materials page.',\n    monthly_entry: 'Monthly Entry',\n    me_desc_1: 'Meet Monthly Entry magazine distributed monthly!',\n    me_desc_2: '',\n    solve_desc_1: 'Learn the basics of',\n    solve_desc_2: 'software programming by solving',\n    playSw_desc_1: 'Learn to code by watching EBS TV Series and special tutorial videos!',\n    playSw_desc_2: '',\n    recommended_lessons: 'Recommendations',\n    recommended_lessons_1:\n        'Follow along, challenge, solve quizzes and learn to program with Entry!',\n    recommended_lessons_2: '',\n    offline_top_desc_1: \"Offline Editor's Save Feature has improved as well as security.\",\n    offline_top_desc_2: 'Download now',\n    offline_main_desc: 'Update Entry Offline Editor',\n    art_description: 'This is a project sharing space. Create your own project and share.',\n    art_description_1: '',\n    art_description_2: 'projects created. Create your own project and share.',\n    study_index: \"Learn to code with Entry's coursewares by topic and grade levels\",\n    study_for_beginner: 'Entry First Steps for Starters',\n    entrybot_desc_3: 'Take Entrybot to school',\n    entrybot_desc_4: 'by assembling command blocks',\n    move_entrybot: 'Control Entrybot',\n    can_change_entrybot_1: \"Change Entrybot's color, make it talk\",\n    can_change_entrybot_2: 'using block commands',\n    learning_process_by_topics: 'Courseware by topic',\n    show_detail: 'See Details',\n    solve_mission: 'Solve Mission',\n    solve_mission_desc_1: 'Learn to code while playing games and solving missions!',\n    solve_mission_desc_2:\n        'Control Entrybot move through the maze so it can reach its destination while learning the concepts of sequence, repeat, select and comparison.',\n    learning_process_by_grades: 'Courseware by grade levels',\n    learning_process_by_grades_sub1:\n        'Learn programming concepts in steps with Entry lectures! Start now!',\n    e3_to_e4: 'Elementary 3-4th grade',\n    e5_to_e6: 'Elementary 5-6th grade',\n    m1_to_m3: '7th+ and above',\n    make_using_entry: 'Create projects with Entry',\n    make_using_entry_desc_1: 'Assemble block to create your own program!',\n    make_using_entry_desc_2:\n        'Download and follow along the learning materials to create animation, media art, game and other fun programs.',\n    make_through_ebs_1: 'Learn to code by watching EBS TV Series.',\n    make_through_ebs_2:\n        'The fun TV Series are accompanied by step-by-step tutorial videos so anyone can easily create programs.',\n    support_block_js: 'Block code and javascript are supported',\n    study_ebs_title_1: '순서대로! 차례대로!',\n    study_ebs_desc_1: '[실습] 엔트리봇의 심부름',\n    study_ebs_title_2: '쉽고 간단하게!',\n    study_ebs_desc_2: '[실습] 꽃송이 만들기',\n    study_ebs_title_3: '언제 시작할까?',\n    study_ebs_desc_3: '[실습] 동물가족 소개',\n    study_ebs_title_4: '다른 선택, 다른 결과!',\n    study_ebs_desc_4: '[실습] 텔레파시 게임',\n    study_ebs_title_5: '정보를 담는 그릇',\n    study_ebs_desc_5: '[실습] 덧셈 로봇 만들기',\n    study_ebs_title_6: '요모조 따져 봐!',\n    study_ebs_desc_6: '[실습] 복불복 룰렛',\n    study_ebs_title_7: '번호로 부르면 편해요!',\n    study_ebs_desc_7: '[실습] 나만의 버킷리스트',\n    study_ebs_title_8: '무작위 프로그램을 만들어라!',\n    study_ebs_desc_8: '[실습] 무작위 캐릭터 만들기',\n    study_ebs_title_9: '어떻게 찾을까?',\n    study_ebs_desc_9: '[실습] 도서관 책 검색',\n    study_ebs_title_10: '줄을 서시오!',\n    study_ebs_desc_10: '[실습] 키 정렬 프로그램',\n    event: '이벤트',\n    divide: '분기',\n    condition: 'conditionals',\n    random_number: '무작위수',\n    search: '탐색',\n    sorting: '정렬',\n    parallel: '병렬',\n    signal: '신호',\n    input_output: '입출력',\n    sequential: 'sequence',\n    repeat: 'repeat',\n    choice: 'selection',\n    repeat_advanced: 'repeat(sequence+condition)',\n    function: 'Function',\n    compare_operation: 'comparison',\n    arithmetic: '산술연산',\n    entry_recommended_mission: 'Entry Recommended Mission',\n    more_mission: 'More Mission',\n    line_rangers_title: 'Saving Sally with\\nLINE Rangers',\n    line_rangers_content: 'Save Sally trapped\\nin the Mepisto base.',\n    pinkbean_title_string_basic: 'Maple Story Basic Henesys',\n    pinkbean_title_string_intermediate: 'Maple Story Intermediate Ellinia',\n    pinkbean_title_string_advanced: 'Maple Story Advanced Elnath',\n    pinkbean_title: 'To the Maple World\\nwith PINK BEAN!',\n    pinkbean_content: 'Help Pinkbean to finish\\nhis Maple World adventure.',\n    entrybot_school: 'Go to school',\n    entrybot_school_desc_1: 'Help Entrybot to get backpack and go to school',\n    entrybot_school_desc_2: '',\n    robot_factory: 'Robot Factory',\n    robot_factory_desc_1: 'Entrybot is trapped in a robot factory!',\n    robot_factory_desc_2: 'Collect all parts to escape the factory.',\n    electric_car: 'Electric Car',\n    electric_car_desc_1: \"Help Entrybot's car move forward \",\n    electric_car_desc_2: 'by making sure it has enough fuel.',\n    forest_adventure: 'Forest Adventures',\n    forest_adventure_desc_1: \"Entrybot's friends are trapped in the forest!\",\n    forest_adventure_desc_2: \"Help Entrybot's friends escape.\",\n    town_adventure: 'Village Adventures',\n    town_adventure_desc_1: 'Help Entrybot find fuel',\n    town_adventure_desc_2: 'in the village.',\n    space_trip: 'Space Travels',\n    space_trip_desc_1: 'Entrybot just completed its space exploration.',\n    space_trip_desc_2: 'Help Entrybot return to Earth.',\n    learn_programming_mission: 'Learn programming by playing challenges',\n    make_open_lecture: 'Create open lessons',\n    group_created: 'Class created',\n    group_signup: 'Class enrolled',\n    delete_from_list: 'from the list?',\n    delete_from_list_en: 'Are you sure you want to delete',\n    lecture_collection: 'Courseware',\n    edit_mypage_profile: 'Managae my info',\n    main_image: 'Main image',\n    edit_profile_success: 'Applied.',\n    no_project_1: 'There are no projects to show.',\n    no_project_2: 'How about creating your project now?',\n    empty_project_1: 'There is no work made yet.',\n    no_marked_project_1: 'There is no favorite project at this moment.',\n    no_marked_group_project_1: 'There is no favorite class project at this moment.',\n    no_marked_project_2: \"'Browse through 'Share' section to find interesting projects! \",\n    no_markedGroup_project_2: \"Browse through 'Class share' section to find interesting projects!\",\n    view_project_all: 'Browse project',\n    no_lecture_1: 'There are no lessons to show.',\n    empty_lecture_1: 'There is no lecture made yet.',\n    no_lecture_2: \"Create lessons from 'open lessons'\",\n    no_marked_lecture_1: 'There is no favorite lesson to show.',\n    no_marked_group_lecture_1: 'There is no favorite class lesson to show.',\n    no_marked_lecture_2: \"Browse through 'Open lessons' to see various lessons!\",\n    view_lecture: 'Browse lessons',\n    no_studying_lecture_1: 'There are no lessons to show.',\n    no_studying_lecture_2: \"Start learning from 'Open lessons' section!\",\n    no_lecture_collect_1: 'There are no courseware to show.',\n    empty_lecture_collect_1: 'There is no courseware made yet.',\n    no_lecture_collect_2: \"Create courseware from 'Create open courseware'\",\n    make_lecture_collection: 'Create courseware',\n    no_marked_lecture_collect_1: 'There is no favorite courseware to show.',\n    no_marked_lecture_group_collect_1: 'There is no favorite class courseware to show.',\n    no_marked_lecture_collect_2: \"Browse through 'Open lessons' to see various lessons!\",\n    view_lecture_collection: 'Browse courseware',\n    no_studying_lecture_collect_1: 'There are no courseware to show.',\n    no_studying_lecture_collect_2: \"Start learning from 'Open lessons' section!\",\n    my_lecture: 'My lessons',\n    markedGroup: 'Favorite group',\n    markedGroup_lecture: 'Favorite group lessons',\n    markedGroup_curriculum: 'Favorite group curriculum',\n    marked_lecture: 'Favorite lessons',\n    marked_lecture_collection: 'My courseware',\n    marked_marked_curriculum: 'My courseware',\n    studying_lecture: 'Lessons in progress',\n    completed_lecture: 'Lessons completed',\n    my_lecture_collection: 'My courseware',\n    my: 'My',\n    studying_lecture_collection: 'Courseware in progress',\n    completed_lecture_collection: 'Courseware completed',\n    my_curriculum: 'My Courses',\n    studying_curriculum: 'Courseware in progress',\n    completed_curriculum: 'Courseware completed',\n    materialCC: 'All contents provided are released under Creative Commons CC-BY 2.0 License.',\n    materialccby_new:\n        'All contents provided are released under Creative Commons CC-BY 2.0 License.',\n    entry_copyright_info: 'ENTRY copyright guide',\n    pdf: 'PDF',\n    helper: 'helper',\n    youtube: 'vedio',\n    tvcast: 'vedio',\n    goal: 'goal',\n    basicproject: 'basic',\n    hw: 'hardware',\n    object: 'object',\n    console: 'Console',\n    download_info: 'Click on the title to download resource',\n    entry_materials_all: 'Entry Educational Materials',\n    entry_material: 'Learning Entry',\n    recommand_grade: 'Grade levels',\n    g3_4_grades: '3-4th',\n    g5_6_grades: '5-6th',\n    middle_grades: '7th+',\n    entry_go_go: 'Entry Go Go!',\n    entry_go_go_desc: \"Explore a set of courseware, student activity book and teacher's guide\",\n    entry_go_go_desc2: 'ndevided by grade and difficulty.',\n    stage_beginner: 'Basic',\n    stage_middle: 'Advanced',\n    stage_high: 'Expert',\n    middle_school_short: '7th+',\n    learn_entry_programming: 'Follow along step by step.',\n    entry_programming_desc: 'Entry Programming: Become an Entry expert!',\n    ebs: '',\n    ebs_material_desc: \"Teach using the EBS TV Series and Teacher's Guide!\",\n    season_1_material: \"Season 1 Teacher's Guide\",\n    season_2_material: \"Season 2 Teacher's Guide\",\n    season_1: 'Season 1',\n    playsoftware_ebs: 'EBS Let’s play, SW!',\n    material_teacher_guide: \"Teacher's Guide\",\n    season_2: 'Season 2',\n    compute_think_textbook: 'Improve computational thinking skills',\n    computational_sw: 'Learn to code for subjects such as language arts, math, science, fine arts!',\n    python_coding_text: 'Entry Python',\n    python_coding_textbook: 'Travel to the text coding world! Entry Python',\n    python_coding_desc: 'Learn the structure and grammar of text coding with Entry Python!',\n    entry_x_hardware_text: 'Entry X Hardware',\n    entry_x_hardware: 'Entry Hardware Educational Materials',\n    e_sensor: 'E Sensorboard',\n    e_sensor_board: 'E Sensor-board',\n    e_sensor_robot: 'E Sensor-robot',\n    arduino: 'Arduino',\n    arduinoext: 'ArduinoExt Uno',\n    arduinonano: 'Arduino Nano',\n    albert: 'albert',\n    orange_board: 'orangeBoard',\n    arduino_board: 'Arduino',\n    joystick: 'joystick sensor shield',\n    ardublock: 'ardublock',\n    mkboard: 'digital monkeyboard',\n    mechatro_nano: 'Mechatro Nano+',\n    mechatro_uno: 'Mechatro Uno+',\n    memaker: 'memaker',\n    edumaker: 'EduMaker Board',\n    codingtoolbox: 'codingtoolbox',\n    materials_etc_all: 'Other Educational Materials',\n    materials_teaching: 'For Teacher Education',\n    materials_etc: 'Other Resources',\n    materials_etc_resource: 'Resources',\n    materials_teaching_etc: 'Teacher training',\n    materials_teaching_1: 'Why Coding?',\n    materials_teaching_2: 'Unplugged Acitivies with Entry',\n    materials_teaching_3: 'Learn by playing in Entry Coding Missions',\n    materials_teaching_4: 'Entry for Real World Problem Solving',\n    materials_teaching_5: 'Interdisciplinary Coding(Art,Math,Social)',\n    materials_teaching_6: 'Interdisciplinary Coding(Korean,Science,Music)',\n    materials_teaching_7: 'Physical Computing 1 (E-Sensorboard)',\n    materials_teaching_8: 'Physical Computing 2 (Hamster Robot)',\n    materials_teaching_9: 'Learn to use Entry LMS effectively ',\n    materials_etc_1: 'Getting Started Guide',\n    materials_etc_2: 'Contents for Classroom Use',\n    materials_etc_3: 'Monthly Entry',\n    materials_etc_4: 'About Entry',\n    materials_etc_5: 'Introducing Entry',\n    materials_etc_6: 'Entry Block Catalogue',\n    materials_etc_7: 'Entry Python Guide',\n    jr_if_1: 'if',\n    jr_if_2: 'in front',\n    jr_fail_no_pencil: \"There is no pencil. Use 'pencil block' at the pencil!\",\n    jr_fail_forgot_pencil: \"Oh no! I forgot my pencil. Let's pick up the pencil.\",\n    jr_fail_much_blocks: '너무많은 블록을 사용했어, 다시 도전해볼래?',\n    cparty_jr_success_1: 'Hooray! I got my backpack!',\n    go_right: 'go right',\n    go_down: 'go down',\n    go_up: 'go up',\n    go_left: 'go left',\n    go_forward: 'Go forward',\n    jr_turn_left: 'Turn left',\n    jr_turn_right: 'Turn right',\n    go_slow: 'Go slow',\n    repeat_until_reach_1: '',\n    repeat_until_reach_2: 'Repeat until reach',\n    pick_up_pencil: 'Pick up',\n    repeat_0: 'Repeat',\n    repeat_1: '',\n    when_start_clicked: 'When start button clicked',\n    age_0: 'Age 0+',\n    create_character: 'Creating Character',\n    age_7_9: 'Age 7~9',\n    going_school: 'Going to School',\n    age_10_12_1: 'Age 10~12',\n    collect_parts: 'Collecting Parts',\n    age_10_12_2: 'Age 10~12',\n    driving_elec_car: 'Driving Electric Car',\n    age_13: 'Age 13+',\n    travel_space: 'Traveling Space',\n    people: 'Person',\n    all: 'All',\n    life: 'Life',\n    nature: 'Nature',\n    animal_insect: 'Animal/Insect',\n    environment: 'Environment',\n    things: 'Things',\n    vehicles: 'Vehicles',\n    others: 'Others',\n    fantasy: 'Fantasy',\n    instrument: 'Instrument',\n    piano: 'Piano',\n    marimba: 'Marimba',\n    drum: 'Drum',\n    janggu: 'Janggu',\n    sound_effect: 'Sound',\n    others_instrument: 'Others',\n    aboutEntryDesc_1: 'Entry is an education platform created to help anyone learn to code.',\n    aboutEntryDesc_2: 'Students are able to learn to code while playing,',\n    aboutEntryDesc_3: 'teachers are able to teach effectively.',\n    aboutEntryDesc_4: 'Entry is a non-profit service.',\n    aboutEntryDesc_5: '',\n    viewProjectTerms: 'See usage policy',\n    openSourceTitle: 'Promoting open source culture',\n    openSourceDesc_1: \"Entry's source code and \",\n    openSourceDesc_2: 'all educational materials',\n    openSourceDesc_3: 'are open to public',\n    viewOpenSource: 'See open source code',\n    eduPlatformTitle: 'Entry for Classroom Use',\n    eduPlatformDesc_1: 'Entry is developed with teachers ',\n    eduPlatformDesc_2: 'to promote learning',\n    eduPlatformDesc_3: 'in classroom settings.',\n    madeWith: 'Advisory group',\n    researchTitle: 'Continuous improvement through research',\n    researchDesc_1: 'Entry collaborates with researchers to strengthen learning effectiveness',\n    researchDesc_2: '',\n    researchDesc_3: '',\n    viewResearch: 'See research materials',\n    atEntry: 'Entry provides',\n    entryLearnDesc_1: 'learn while playing',\n    entryLearnDesc_2: '< Learn > section provides various coursewares and learning materials.',\n    entryLearnDesc_3: 'Watch videos, solve problems and learn while playing.',\n    entryLearnDesc_4: '',\n    entryMakeDesc_1: '<Create> section provides block-based coding tool which enables',\n    entryMakeDesc_2: 'even first time learners to easily create programs.',\n    entryMakeDesc_3: 'And also provides ‘entry phython’ mode which is between block-based coding',\n    entryMakeDesc_4: 'and text-based coding to help you understand the structure and grammar',\n    entryMakeDesc_5: 'of programming languages.',\n    entryShareDesc_1: '<Share> section allows users to share his or her project with others.',\n    entryShareDesc_2: 'Explore how the shared projects are created, make improvements,',\n    entryShareDesc_3: 'collaborate with friends to make even cooler projects.',\n    entryGroup: 'Learning Management Tool',\n    entryGroupTitle: 'My Class',\n    entryGroupDesc_1:\n        '<Learning Management Tool> is created to help teachers easily manage students.',\n    entryGroupDesc_2: 'Create your own class, assign homework,',\n    entryGroupDesc_3: 'share project within the class, and check student progress.',\n    entryGroupDesc_4:\n        'And teacher can lead the class effectively by providing more suitable coursewares',\n    entryGroupDesc_5: 'according to the students’ level.',\n    unpluggedToPhysical: 'From Unplugged Activity to Physical Computing',\n    algorithmActivity: 'Basic Algorithm',\n    programmignLang: 'Block-based Coding',\n    unpluggedDesc_1: 'Learn the basics of programming such as sequence, repetition,',\n    unpluggedDesc_2: 'selection and function by playing Entry Boardgame and Cardgame.',\n    entryMaze: 'Entrybot Maze Escape',\n    entryAI: 'Space Travels',\n    algorithmDesc_1: 'Earn a certificate by completing the coding missions.',\n    algorithmDesc_2: 'Learn to code while playing.',\n    programmingLangDesc_1: 'Coding is made easy with Entry.',\n    programmingLangDesc_2: 'Create your own games, animation, media art and much more.',\n    viewSupporHwVideo: 'See the hardware guide videos',\n    viewSupporHw: 'see which hardware connects',\n    supportHwDesc_1: 'Entry connects to many physical computing devices to create awesome projects',\n    supportHwDesc_2: 'that interacts with the physical world. More devices are continuously added!',\n    entryEduSupport: 'Entry Education Support',\n    eduSupportDesc_1: 'Entry Labs provides educational materials for free.',\n    eduSupportDesc_2: 'Download educational materials from the Educational Materials page.',\n    materials_1_title: 'Textbook by grade levels',\n    materials_1_desc_1: 'Improve coding skills step by step',\n    materials_1_desc_2: '',\n    materials_2_title: \"EBS TV program and teacher's guide\",\n    materials_2_desc_1: 'EBS TV series are accompanied',\n    materials_2_desc_2: \"by teacher's guide\",\n    materials_3_title: 'Educational materials',\n    materials_3_title_2: 'for elementary and mid to high school',\n    materials_3_desc_1: 'Improve computational thinking skills.',\n    materials_3_desc_2: '',\n    moreMaterials: 'See more educational materials',\n    moreInfoAboutEntry_1: \"Click on the links below to get Entry's latest updates.\",\n    moreInfoAboutEntry_2: 'Educational materials as well as exciting news are shared.',\n    material_menu_type_robot: 'Robot\\nType',\n    material_menu_type_module: 'Module\\nType',\n    material_menu_type_board: 'Board\\nType',\n    blog: 'Blog',\n    post: 'Post',\n    tvCast: 'TVCast',\n    about_entry_pre: 'Entry',\n    about_youtube: 'Youtube',\n    about_facebook: 'Facebook',\n    albertSchool: 'Albert',\n    arduinoBoard: 'Arduino certified',\n    arduinoCompatible: 'non-certified',\n    bitBlock: 'BitBlock',\n    bitbrick: 'Bitbrick',\n    creamo: 'creamo',\n    playcode: 'playcode',\n    funboard: 'funboard',\n    truerobot: 'TrueTrue',\n    bingle: 'BINGLE',\n    bingles: 'BINGLE · S',\n    codeino: 'CODEino',\n    epor: 'EPOR',\n    petrone_v2: 'Petrone V2',\n    petrone_v2_drone: 'flight',\n    petrone_v2_car: 'drive',\n    'e-sensor': 'E-Sensorboard',\n    'e-sensorUsb': 'E-Sensor board',\n    'e-sensorBT': 'E-Sensor board(Bluetooth)',\n    mechatronics_4d: '4D Mechatronics',\n    esensor_board: 'E-Sensor Board',\n    esensor_robot: 'E-Sensor Robot',\n    hamster: 'Hamster',\n    hummingbird: 'Hummingbird Duo',\n    roboid: 'Roboid',\n    turtle: 'Turtle',\n    littlebits: 'Littlebits',\n    orangeBoard: 'OrangeBoard',\n    robotis_carcont: 'Robotis Robot Car',\n    robotis_IoT: 'Robotis IoT',\n    robotis_IoT_Wireless: 'Robotis IoT(Wireless)',\n    dplay: 'DPLAY',\n    iboard: 'iboard',\n    nemoino: 'NEMOino',\n    xbot_epor_edge: 'XBOT(OneTouch Dongle/USB)',\n    XbotBT: 'XBOT EPOR and EDGE Bluetooth',\n    robotori: 'robotori',\n    rokoboard: 'rokoboard',\n    neobot: 'NEOBOT',\n    neobot_sensor_theme: 'NEOBOT Senosor Theme',\n    mechatro: 'mechatro',\n    about: 'About',\n    articles: 'Articles',\n    gallery: 'Gallery',\n    learn: 'Learn',\n    login: 'Sign In',\n    logout: 'Sign Out',\n    make: 'Create',\n    register: 'Sign Up',\n    Join: 'Join',\n    Edit_info: 'Edit Info',\n    Discuss: 'Discuss',\n    Explore: 'Explore',\n    Load: 'Load',\n    My_lesson: 'Open Lessons',\n    textbook_learning: 'Learning Text book',\n    Resources: 'Resources',\n    play_software: 'EBS Let’s play, SW!',\n    problem_solve: 'Entry Learn',\n    learning_textbook: 'Learning Text book',\n    context_textbook:\n        'Teachers can teach the school class and students can prepare and review at home with the same content as their textbooks.',\n    info_banner_textbook: ' ',\n    banner_textbook: 'Do you want to learn more',\n    banner_textbook_2: 'diverse and interesting things?',\n    banner_textbook_right_banner: 'Do you need educational ',\n    banner_textbook_right_banner2: 'materials for teachers?',\n    banner_textbook_right_banner_btn: 'Download material',\n    Learn: 'Learn',\n    teaching_tools: 'Teaching Tools',\n    about_entry: 'About ENTRY',\n    what_entry: 'What is Entry?',\n    create: 'Create',\n    create_new: 'Create new',\n    start_programming: 'First Step for Software Education',\n    Entry: 'Entry',\n    intro_learning: 'Learn to code in fun and easy way.',\n    intro_learning_anyone: 'Start now with Entry!',\n    start_now: 'For Free, Forever.',\n    welcome_entry: 'Welcome to ENTRY',\n    student: 'Student',\n    non_menber: 'General',\n    teacher: 'Teacher',\n    terms_conditions: 'Terms and Conditions',\n    personal_information: 'Information about the collection and use of personal information ',\n    limitation_liability: 'Limitation of Liability',\n    entry_agree: 'Agree to ENTRY’s Terms of Use',\n    info_agree: '',\n    next: 'Next',\n    enter_individual_info: 'Enter personal information',\n    enter_id: 'Enter ID',\n    enter_password: 'Enter Password',\n    confirm_password: 'Confirm Password',\n    enter_password_again: 'Enter  your password again',\n    validation_password: 'Please use at least 5 letters and/or numbers',\n    validation_id: 'Please use 4-20 letters and/or numbers.',\n    prev: 'Back',\n    born_year: 'Year born ',\n    select_born: 'Select the year you were born.',\n    year: 'years',\n    gender: 'Gender',\n    choose_gender: 'Choose gender',\n    male: 'Male',\n    female: 'Female',\n    language: 'Language',\n    best_language: 'Select your best language',\n    korean: 'Korean',\n    english: 'English',\n    viet: 'Vietnamese',\n    japan: 'Japanese',\n    russia: 'russia',\n    korean_s: 'korean',\n    english_s: 'english',\n    japan_s: 'japanese',\n    chinese_simplified: 'Chinese(Simplified)',\n    chinese_traditional: 'Chinese(Traditional)',\n    option_email: 'Email (optional)',\n    insert_email: 'Enter your email address',\n    sign_up_complete: 'Sign up complete!',\n    agree_terms_conditions: 'Please agree Terms and Conditions',\n    agree_personal_information: 'Please agree to the collection and use of personal information.',\n    insert_studying_stage: 'Please select the group you want to share your project .',\n    insert_born_year: 'Insert the year you were born',\n    insert_gender: 'Please select gender from the options.',\n    select_language: 'select language',\n    check_email: \"Check email's format\",\n    already_exist_id: 'ID already exists',\n    id_validation_id: 'ID use 4-20 letters and/or numbers.',\n    password_validate_pwd: 'Password use at least 5 letters and/or numbers',\n    password_validate_pwd_length: 'Please use at least 5 numbers.',\n    neoid_username_same_id: 'Username already taken (NEOID)',\n    insert_same_pwd: 'Insert same password',\n    studying_stage_group: 'Sharing class',\n    studying_stage: 'Please select the group you want to share.',\n    password: 'Password',\n    save_id: 'Save ID',\n    auto_login: 'Keep me sign in',\n    enter_id_pw: 'Entry ID, Password',\n    forgot_password: 'Forgot your ID or password?',\n    did_not_join: 'Haven’t signed up yet?',\n    go_join: 'Go to join',\n    renew_index_text_00: 'Learn textbook',\n    renew_index_text_01: \"Let's learn Entry with textbook.\",\n    renew_index_text_02: 'Through elementry textbook lectures,',\n    renew_index_text_02_2: 'learn Entry!',\n    renew_index_text_03: 'Go to',\n    renew_index_text_03_2: 'learn textbook',\n    renew_index_text_1: '2019, Meet the changed Entry',\n    renew_index_text_2: \"The brand new 'Create Project'\",\n    renew_index_text_3: \"Go to the 'Create Project'\",\n    renew_index_text_3_2: 'and find out the new functions!',\n    renew_index_text_4: 'View Details',\n    first_step: 'First Step for Software Education',\n    entry_content_one: 'Bring your imagination to life with ENTRY.',\n    entry_content_two: 'Create games, animations, media art, and other cool projects!',\n    entry_content_three:\n        'Create projects and share with your friends. Enter the exciting world of ENTRY!',\n    funny_space: 'A Fun Learning Space',\n    in_learn_section: 'In < Learn > section,',\n    learn_problem_solving:\n        'Various learning contents and mini challenges are available for you in the < Learn > section. Solve mini challenges by coding. Watch fun videos and learn to program.',\n    joy_create: 'A Creative Space',\n    in_make: 'In < Create > section',\n    make_contents:\n        'In the <Create> section, create your own program with block-based programming language. Create simulation programs to test laws of Physics. Create animation program with your favorite characters. Bring your imagination to life with Entry. ',\n    and_content:\n        'There is no limit to what you can create. You can experiment physical laws you’ve learned in science class, create animations featuring your favorite characters, and even make your own games. ',\n    share_collaborate: 'A Sharing Space',\n    explore_contents:\n        'The <Explore> section, showcases thousands of projects created and shared by the Entry community. Try out the fun and creative projects, see how they are coded, and improve them. You can also cooperate with your peers to create exciting projects.',\n    why_software: 'Why is learning to code important?',\n    speak_obama_contents:\n        'Learning these skills isn’t just important for your future. It’s important for our country’s future.',\n    obama: 'Barack Obama',\n    us_president: 'U.S President',\n    billgates_contents:\n        'Learning to write programs stretches your mind, and helps you think better, creates a way of thinking about things that I think is helpful in all domains.',\n    billgates: 'Bill Gates',\n    chairman_micro: 'Chairman, Microsoft',\n    eric_contents:\n        \"For most people on Earth, the digital revolution hasn't even started yet. Within the next 10 years, all that will change. Let's get the whole world coding!\",\n    eric: 'Eric Schmidt',\n    sandbug_contents:\n        'An understanding of computer science is becoming increasingly essential in today’s world. Our national competitiveness depends upon our ability to educate our children—and that includes our girls—in this critical field.',\n    sandbug: 'sheryl Sandberg',\n    view_entry_tools: 'Introducing Entry’s unplugged games for teaching programming.',\n    solve_problem: 'Solve Mission',\n    solve_problem_content: 'Mini challenges will help you learn the basics of programming.',\n    find_extra_title: 'ENTRY Bot part finding extravaganza',\n    all_ages: 'For all ages',\n    total: 'Total',\n    step: 'steps',\n    find_extra_contents:\n        'Entry bot is special robot created one day at the Rutz Robot Toy Factory during a blackout. Help him find his missing parts and escape the factory while learning to code.',\n    software_play_contents:\n        'Watch ‘Let’s Play Software’ , follow along the tutorials and learn to create fun programs.',\n    resources_contents: 'Get various Entry educational materials for free',\n    from: 'From',\n    sw_camp: 'Software Creativity Camp, Ministry of Science, ICT and Future Planning',\n    elementary: 'Elementary',\n    middle: 'Middle school',\n    grades: 'Grades',\n    lesson: 'Lessons',\n    sw_contents_one:\n        'This guidebook is for elementary students learn physical computing over a 5-lesson course. Students learn to use Entry and create images and stoires. In the final section, students use Arduino to create a musical keyboard',\n    sw_camp_detail: 'Ministry of Science, ICT and Future Planning Software Creation Camp',\n    sw_contents_two:\n        'This textbook allows middle school students to experience ENTRY and physical computing over a 5-lesson course. Students learn how to use ENTRY, and create a maze game and quiz program. In the final section, students use Arduino and keyboard to steer a car.',\n    sw_contents_three:\n        'This is a teacher’s guide for starting computing classes in schools.  It contains a variety of unplugged activities and lesson plans using clips from ‘Let’s play, Software!’broadcasts. ',\n    naver_sw: 'NAVER Let’s play, Software!',\n    teacher_teaching: 'Teacher’s Guide (for elementary grades 5-6 and above)',\n    funny_sw: 'Have Fun with Software',\n    sw_contents_four:\n        'This textbook allows students to learn about computing in a fun and playful way through a variety of unplugged activities such as ENTRY Board, and teaches students the basic principles of programming via ENTRY Course Mode. Once they have got down the basics, students learn how to create stories, games, artistic works, and applications using ENTRY. The textbook allows students to create and present their own software. ',\n    ct_text_5: 'Grow computational thinking with skills.',\n    teacher_grade_5: '교원 (초등학교 5학년)',\n    ct_text_5_content:\n        \"This teacher's guide contains 8 problem solving tasks. Each task is designed to reflect the revised National Curriculum and contains interdisciplinary themes. Cultivate computational thinking skills.\",\n    ct_text_6: '교과서와 함께 키우는 컴퓨팅 사고력',\n    teacher_grade_6: '교원 (초등학교 6학년)',\n    ct_text_6_content:\n        '실생활의 문제를 해결하자는 테마로 준비된 총 8개의 학습콘텐츠가 담긴 교사용 지도안입니다. 각 콘텐츠는 개정된 교육과정을 반영한 타교과와의 연계를 통해 다양한 문제를 만나고 해결해볼 수 있도록 설계되었습니다.  아이들이 컴퓨팅 사고력을 갖춘 융합형 인재가 될 수 있도록 지금 적용해보세요!',\n    sw_use: 'All textbooks are for non-commercial use only, and can be used freely so long as the author is credited. ',\n    title: 'Title',\n    writer: 'By',\n    view: 'View',\n    date: 'Date',\n    find_id_pwd: 'Find ID or Password',\n    send_email: 'A link to change your password has been sent to you by email.',\n    user_not_exist: 'This email does not exist.',\n    not_signup: \"Haven't signed up yet?\",\n    send: 'Send',\n    sensorboard: 'ENTRY Sensor Board',\n    physical_computing: 'Physical Computing',\n    sensorboard_contents:\n        'Using Arduino no longer requires building a circuit using lots of wires. With ENTRY Board, you can use LED lights, temperature, sound, light sensors, a slider, and switches by simply mounting it onto an Arduino board. Now anyone can easily create their own unique projects using ENTRY Board!',\n    entrybot_boardgame: 'ENTRY-Bot Board Game',\n    unplugged: 'Unplugged Activities',\n    unplugged_contents:\n        'Learn the principles of programming through Entry-bot Board Game. By helping Entrybot escape the factory, you can learn to think like a computer scientist.',\n    entrybot_cardgame: 'ENTRY Bot Cardgame : Bomb Tempest',\n    entrybot_cardgame_contents:\n        '12 different types of bombs appear at the city of Entry! Dismantle the bombs one at a time and learn the basics of programming. By using the concepts of sequence, repetition and conditionals, save the City and become a hero!',\n    basic_learn: 'Entry Basics',\n    basic_learn_contents: 'Learn to program with Entry’s coursewares',\n    troubleshooting: 'Problem Solving',\n    playsoftware: \"Let's play, Software!\",\n    make_own_lesson: 'Create your own lessons and share them with everyone.',\n    group_lecture: 'Lessons',\n    group_curriculum: 'Courseware',\n    group_homework: 'Assignment',\n    group_noproject: 'No Project',\n    group_nolecture: 'No Lessons',\n    group_nocurriculum: 'No Courseware',\n    lecture_contents: 'Create customized lessons with limited blocks.',\n    curriculum_contents: 'Create a course by putting together series of lessons.',\n    grade_info: 'Grades information',\n    difficulty: 'Difficulty',\n    usage: 'Usages',\n    learning_concept: 'Learning concepts',\n    related_subject: 'Related subjects',\n    show_more: 'Show more',\n    close: 'Close',\n    latest: 'By Latest',\n    viewCount: 'view count',\n    viewer: 'By Viewers',\n    like: 'By Likes',\n    comment: 'By Comments',\n    entire_period: 'Entire period',\n    today: 'Today',\n    latest_week: 'Latest 1 week',\n    latest_month: 'Latest 1 month',\n    latest_three_month: 'Latest 3 months',\n    current_password: 'Current password',\n    change_password: 'Change password',\n    incorrect_password: 'Incorrect! Try again.',\n    incorrect_password_login: 'The Username or Password you entered is incorrect.',\n    suspension_user: 'The login of the account is prohibited.',\n    blocked_user: 'Blocked!!',\n    new_password: 'New password',\n    password_option_1: 'Please use at least 5 letters and/or numbers.',\n    again_new_password: 'Confirm new password',\n    enter_new_pwd: 'Enter new password.',\n    confirm_new_pwd: 'Confirm new password.',\n    enter_new_pwd_again: 'Enter new password again.',\n    password_match: 'Passwords do not match.',\n    incorrect_email: 'Incorrect email. Try again.',\n    edit_button: 'Edit info',\n    edit_profile: 'Edit',\n    my_project: 'My projects',\n    my_group: 'My Class',\n    mark: 'Marking',\n    prev_state: 'Back',\n    profile_image: 'Profile image',\n    insert_profile_image: 'Please upload a profile image.',\n    at_least_180: 'At least 180x180 pixels is recommended.',\n    upload_image: 'Upload image',\n    about_me: 'About me',\n    save_change: 'Save changes',\n    basic_image: 'Basic Image',\n    profile_condition: 'Enter something about yourself. (in 50 characters)',\n    profile_back: 'Go back',\n    make_project: 'Create project',\n    exhibit_project: 'Exhibit Project',\n    art_list_shared: 'Shared',\n    art_list_group_shared: 'Group',\n    gl_mode_boost: 'Boost Mode',\n    gl_not_supported: 'Can not run in boost mode.\\nClick OK to run in default mode.',\n    view_project: 'View Code',\n    code_view: 'View Code',\n    noResult: 'No results found',\n    comment_view: 'Comment',\n    upload_project: 'Upload',\n    edit: 'Edit',\n    save_complete: 'Save',\n    just_like: 'Like',\n    share: 'Share',\n    who_likes_project: 'Who likes the projects',\n    people_interest: 'People interested projects',\n    none_person: 'Nobody',\n    inserted_date: 'Date',\n    last_modified: 'Last Modified',\n    original_project: 'Original project',\n    for_someone: \"'s\",\n    original_project_deleted: 'The original project was deleted',\n    delete_project: 'Delete',\n    delete_group_project: 'Delete From List',\n    currnet_month_time: 'months',\n    current_day_time: 'days',\n    game: 'Game',\n    animation: 'Animation',\n    media_art: 'Media Arts',\n    physical: 'Physical',\n    etc: 'ETC',\n    connected_contents: 'Linking content',\n    connected_contents_content:\n        \"Discover the variety of content that can be done with the entry . If you're new software to learn easily from person to enjoy board games , you can take advantage of the Arduino and physical computing , such as creating a luxurious view of your own creation .\",\n    basic_mission: 'Basic mission : Entry bot Maze',\n    basic_mission_content:\n        'A power outage at a toy robot factory magically enabled Entrybot to come to life. Help Entrybot escape the factory and find freedom!',\n    application_mission: \"Application mission: Entry bot's Space Odyssey\",\n    write_article: 'Write',\n    write_contest: 'Submit',\n    view_all_articles: 'View all posts',\n    view_own_articles: 'View my posts',\n    view_qna_articles: 'View no answered posts',\n    learning_materials: 'Learning materials',\n    download_materials: 'Learning materials download',\n    download_button: 'download',\n    download_all: 'download all',\n    ebs_software_first:\n        \"<Let's Play Software> is a TV series created by Naver, EBS and Entry Labs. Learn the basic principles of programming. Watch the show, follow along the video tutorials, and learn to code!\",\n    go_software: \"Visit Let's play software!\",\n    ebs_context: 'Visit EBS',\n    ebs_context_hello: 'Visit EBS',\n    category: 'Category',\n    add_picture: 'Add Picture',\n    upload_article: 'Upload article',\n    list: 'List',\n    report: 'Report',\n    upload: 'Upload',\n    staff_picks: 'Staff Picks',\n    popular_picks: 'Popular Projects',\n    lecture_header_more: 'More Projects',\n    lecture_header_reset: 'Reset',\n    lecture_header_reset_exec: 'Reset to basic project',\n    lecture_header_save: 'Save',\n    lecture_header_save_content: 'Save current lecture',\n    lecture_header_export_project: 'Export to my project',\n    lecture_header_undo: 'Undo',\n    lecture_header_redo: 'Redo',\n    lecture_er_bugs: 'Feedback',\n    lecture_container_tab_object: 'Objects',\n    lecture_container_tab_video: 'Video',\n    lecture_container_tab_project: 'Final project',\n    lecture_container_tab_help: 'Help',\n    illigal: 'Illegal or inappropriate behavior',\n    verbal: 'Verbal abuse or posting personal information',\n    commertial: 'Posting for commercial purposes',\n    explicit: 'Explicit content',\n    other: 'Other',\n    check_one_more: 'Please select the reason more than one.',\n    enter_content: 'Please enter the reason for your report.',\n    report_result: 'Please enter email address to be informed of report results. ',\n    report_success: 'Your report was submitted successfully.',\n    etc_detail: 'Please give details',\n    lecture_play: 'Play',\n    list_view_link: 'List',\n    lecture_intro: 'Introduction Lessons',\n    study_goal: 'Goals',\n    study_description: 'Description',\n    study_created: 'Created',\n    study_last_updated: 'Updated',\n    study_remove: 'Remove',\n    study_group_lecture_remove: 'Remove From List',\n    study_group_curriculum_remove: 'Remove From List',\n    study_edit: 'Edit',\n    study_comments: 'Comments',\n    study_comment_post: 'Post',\n    study_comment_remove: 'Remove',\n    study_comment_edit: 'Edit',\n    study_comment_save: 'Save',\n    study_guide_video: 'Guide Video',\n    study_basic_project: 'Initial Project',\n    study_done_project: 'Complete Project',\n    study_usage_element: 'Usage',\n    study_concept_element: 'Concept',\n    study_subject_element: 'Related',\n    study_computing_element: 'Computational Thinking',\n    study_element_none: 'None',\n    study_label_like: 'Like',\n    study_label_interest: 'Interest',\n    study_label_share: 'Share',\n    study_label_like_people: 'People who liked this lecture',\n    study_label_interest_people: 'People who interested this lecture',\n    study_related_lectures: 'Related lectures',\n    study_expand: 'Show all',\n    study_collapse: 'Collapse',\n    aftercopy: 'Copied to clipboard',\n    study_remove_curriculum: 'Are you sure to remove this course?',\n    content_required: ' Please enter the contents.',\n    upload_not_supported_file_msg: 'Not supported file type.',\n    study_remove_lecture: 'Are you sure to remove this lesson?',\n    lecture_build: 'Make a lesson',\n    lecture_build_step1: '1. Enter basic lesson information',\n    lecture_build_step2: '2. Selecte required functions',\n    lecture_build_step3: '3. Confirm all of information correctly.',\n    lecture_build_choice: 'What is main content?',\n    lecture_build_project: 'Entry Project',\n    lecture_build_video: 'Lessons Video',\n    lecture_build_grade: 'Grades',\n    lecture_build_goals: 'Goals',\n    lecture_build_add_goal: 'Add a goal',\n    lecture_build_attach: 'Attachment',\n    lecture_build_attach_text: 'Less than 20MB',\n    lecture_build_assist: 'Additional',\n    lecture_build_youtube_url: 'Paste a Youtube share link',\n    lecture_build_project_done: 'Select a completed project.',\n    lecture_build_scene_text1: 'Using scene function or not',\n    lecture_build_scene_text2: '',\n    lecture_build_object_text: 'Using Object add function or not',\n    lecture_build_blocks_text1: 'Select required blocks only.',\n    lecture_build_blocks_text2: '',\n    lecture_build_basic1: 'Select a project.',\n    lecture_build_basic2: 'User start with this project.',\n    lecture_build_help: '',\n    lecture_build_help_never: 'Close permanently',\n    lecture_build_close: 'Close',\n    lecture_build_scene: 'Scene 1',\n    lecture_build_add_object: 'Add Object',\n    lecture_build_start: 'Start',\n    lecture_build_tab_code: 'Block',\n    lecture_build_tab_shape: 'Shape',\n    lecture_build_tab_sound: 'Sound',\n    lecture_build_tab_attribute: 'Attribute',\n    lecture_build_tab_table: 'Table',\n    lecture_build_block_category: 'Select block category.',\n    lecture_build_attr_all: 'All',\n    lecture_build_attr_var: 'Variable',\n    lecture_build_attr_signal: 'Signal',\n    lecture_build_attr_list: 'List',\n    lecture_build_attr_func: 'Function',\n    lecture_build_edit: 'Edit',\n    lecture_build_remove: 'Remove',\n    curriculum_build: 'Create a courseware',\n    curriculum_step1: 'Fill information about this course.',\n    curriculum_step2: 'Select lessons for this course.',\n    curriculum_step3: 'Confirm information.',\n    curriculum_lecture_upload: 'Upload',\n    curriculum_lecture_edit: 'Edit',\n    curriculum_lecture_open: 'Open',\n    group_lecture_add: 'Add my group lessons',\n    group_curriculum_add: 'Add my group curriculum',\n    group_lecture_delete: 'Delete',\n    group_curriculum_delete: 'Delete',\n    group_select: '',\n    group_studentNo: 'Student No',\n    group_username: 'Name',\n    group_userId: 'ID',\n    group_tempPassword: 'Modify PW',\n    group_gender: 'Gender',\n    group_studentCode: 'Code',\n    file_load_web_table_title: 'Import table from the Google Sheets',\n    file_load_web_table_sub_title: 'You can import table from Google Sheets documents.',\n    file_input_sheet_id: 'Google Sheets ID',\n    file_input_sheet_id_require: 'Required',\n    file_input_sheet_id_placeholder: 'Please enter Google Sheets ID.',\n    file_input_sheet_name: 'Sheet name',\n    file_input_sheet_name_placeholder: 'Please enter sheet name.',\n    file_load_web_warn_title_1:\n        \"You can import the contents of a Google Sheets document and add them to the table.\\nThis can only be imported if the access rights are set to 'Anyone with link'\",\n    file_load_web_warn_title_2:\n        'The following datas are subject to the Terms of Use and related laws.',\n    file_load_web_warn_desc_2_1:\n        'Violent and brutal data, Sacred body exposure data, Offensive or disgusting data, \\nData of copyright prohibited from unauthorized use',\n    file_load_web_error_sheet_id_1: 'Google Sheets ID is not entered.',\n    file_load_web_error_sheet_id_2: 'Invalid Google Sheets ID.',\n    group_viewWorks: 'View Works',\n    added_group_lecture: 'lessons deleted',\n    added_group_curriculum: 'Course deleted',\n    deleted_group_lecture: 'lessons deleted',\n    deleted_group_curriculum: 'Course deleted',\n    modal_my: 'My',\n    modal_interest: 'Marked',\n    modal_project: 'Project',\n    section: 'Sections',\n    connect_hw: 'connect hardware',\n    connect_message: 'Connected to %1',\n    connect_fail: 'Connect fail',\n    interest_curriculum: 'Interest',\n    marked_curriculum: 'Interest Curriculum',\n    searchword_required: 'Please enter your search keyword.',\n    file_required: 'File is required.',\n    file_name_error: 'please insert correct file name',\n    file_upload_max_count: 'You can only upload 10 files at a time.',\n    image_file_only: 'You can only upload jpg, png, bmp files.',\n    file_upload_max_size: 'You can only upload less than 10MB in file size.',\n    curriculum_modal_lectures: 'My Lessons',\n    curriculum_modal_interest: 'Interest',\n    group_curriculum_modal_curriculums: 'My Courses',\n    group_curriculum_modal_interest: 'Interest',\n    picture_import: 'Import a picture',\n    picture_select: 'Select a picture',\n    lecture_list_view: 'list',\n    play_software_2: 'Let’s play, Software2!',\n    play_software_2_content:\n        \"<Let's Play Software> is a TV series created by Naver, EBS and Entry Labs. Learn the basic principles of programming. Watch the show, follow along the video tutorials, and learn to code!\",\n    open_project_to_all: 'Open',\n    close_project: 'Close',\n    category_media_art: 'Media Art',\n    go_further: 'Go further',\n    marked_project: 'Bookmark Project',\n    marked_group_project: 'Favorite group project',\n    basic: 'Basic',\n    application: 'Application',\n    the_great_escape: 'The Great Escape',\n    escape_guide_1:\n        'ENTRY Bot suddenly began to think for himself during a power failure at the robot dog factory! ',\n    escape_guide_1_2: ' Help ENTRY Bot escape the factory and find his freedom!',\n    escape_guide_2:\n        'ENTRY Bot is missing too many parts to make it far. Help him find his parts as he makes his way out the factory!',\n    escape_guide_2_2: 'Objectives: Sequential Execution',\n    escape_guide_3:\n        'I’ve finally escaped the factory! But it’s still a long way to the village. I think I’m fixed up enough to make it there without too much difficulty. Hey, what’s that robot?',\n    escape_guide_3_2: 'Objectives: Repetitive and Conditional Statements',\n    escape_guide_4:\n        'We’re finally getting close to the village! I’m starting to really get the hang of this! I think it might be better to just use the blocks from memory. If I just recharge my battery here, I’ll be able to live free forever.',\n    escape_guide_4_2: 'Objectives: Definitions of Function and Function Call',\n    space_travel_log: 'Space Travel Log',\n    space_guide_1:\n        'ENTRY Bot has finally completed his exploration of distant space. He’s trying to make his way back home to Earth, but his path is being blocked by a bunch of space rocks! Help ENTRY Bot make it back to Earth safely!',\n    space_guide_2:\n        'It’s finally time to return to Earth! I can’t wait to get back and rest! Tell me the positions of the rocks ahead so I can navigate through them! I’ll go the way you tell me to!',\n    space_guide_2_2: 'Objective: Reiterating IF Statements and Logical Operation',\n    cfest_mission: 'ENTRY Experiential Mission',\n    maze_1_intro:\n        'Hi. I’m ENTRY Bot. I’m about to save my injured friends and I need your help. Help me save my friends! First, set up the ‘Move forward one space’ block and press ‘Start’.',\n    maze_1_title: 'How to Start',\n    maze_1_content: 'How do I move ENTRY Bot?',\n    maze_1_detail:\n        '1. Take a block from the Block Box and connect it with the ‘When Start is pressed’ block. <br> 2. Press Start once you have finished assembling. <br> 3. I will move in the order of your assembled blocks from top to bottom. ',\n    maze_2_intro:\n        'Alright! You’ve saved the first of my friends! Now let’s save my next friend. Oh! There’s a beehive in the way! Use the Jump Over block to avoid the beehive and save my friend!',\n    maze_2_title_1: 'Jump Over',\n    maze_2_content_1: 'How do I get around obstacles?',\n    maze_2_detail_1:\n        'Sometimes your path may be blocked by an obstacle. <br> When there’s an obstacle in your path, you need to use the ‘Jump Over’ block.',\n    maze_2_title_2: 'How to Start',\n    maze_2_content_2: 'How do I move ENTRY Bot?',\n    maze_2_detail_2:\n        '1. Take a block from the Block Box and connect it with the ‘When Start is pressed’ block. <br> 2. Press Start once you have finished assembling. <br> 3. I will move in the order of your assembled blocks from top to bottom. ',\n    maze_3_intro:\n        'Awesome! Now let’s go save another friend! How about we use the ‘Repeat’ block that my other friend gave use? You can easily repeat the same movements over again using the ‘Repeat’ block! Try changing the number of times to repeat. ',\n    maze_3_title: 'Repeat Block (1)',\n    maze_3_content: 'How do I use the ‘Repeat (3)’ block?',\n    maze_3_detail:\n        'To perform the same action/s more than once, you need to use the ‘Repeat’ block. <br> Put the blocks that you want to repeat inside the Repeat box and select the number of times you want to repeat.',\n    maze_4_intro:\n        'Super! Not too many robot friends left to save now. Take us to my friend by using the ‘Jump Over’ block on repeat while also evading the beehive!',\n    maze_4_title: 'Repeat Block (1)',\n    maze_4_content: 'How do I use the ‘Repeat (3)’ block?',\n    maze_4_detail:\n        'To perform the same action/s more than once, you need to use the ‘Repeat’ block. <br> Put the blocks that you want to repeat inside the Repeat box and select the number of times you want to repeat.',\n    maze_5_intro:\n        'Cool! Now let’s try using the ‘Repeat’ block and ‘IF’ block together! Using the ‘IF’ block, you can turn in a direction where there are no walls when you come across a wall. Well then, shall we set off to save my friend?',\n    maze_5_title_1: 'IF block',\n    maze_5_content_1: 'How does the ‘IF’ block work?',\n    maze_5_detail_1:\n        'You can determine what action to take when you come across a {IMAGE}. <br> The blocks are used only when you come across a {IMAGE}. <br> If there is none, the block is not used.',\n    maze_5_title_2: 'Repeat Block (2)',\n    maze_5_content_2: 'How do I use the ‘Repeat until’block?',\n    maze_5_detail_2:\n        'Using the ‘Repeat until’block, you can determine until when a specified action is repeated. <br> Just put the blocks you want to repeat inside the ‘Repeat until’ block. <br> Then, the repetition will stop when you reach the space where the {IMAGE} is located. ',\n    maze_6_intro:\n        'Only one friend left! Just do as we’ve practiced and you’ll succeed! Now, let’s go save him!',\n    maze_6_title_1: 'IF block',\n    maze_6_content_1: 'How does the ‘IF’ block work?',\n    maze_6_detail_1:\n        'You can determine what action to take when you come across a {IMAGE}. <br> The blocks are used only when you come across a {IMAGE}. <br> If there is none, the block is not used.',\n    maze_6_title_2: 'Repeat Block (2)',\n    maze_6_content_2: 'How do I use the ‘Repeat until’block?',\n    maze_6_detail_2:\n        'Using the ‘Repeat until’block, you can determine until when a specified action is repeated. <br> Just put the blocks you want to repeat inside the ‘Repeat until’ block. <br> Then, the repetition will stop when you reach the space where the {IMAGE} is located. ',\n    maze_programing_mode_0: 'Block Coding',\n    maze_programing_mode_1: 'Javascript',\n    maze_operation1_title: 'STEP 1 – Javascript mode guide',\n    maze_operation1_1_desc:\n        \"Hi, I'm Entrybot, the robot dog. Give me commands to reach the mission goals. You can learn about the mission when you begin under <span class=\\\"textShadow\\\">'Goals.'</span>\",\n    maze_operation1_2_desc:\n        'Once you learn your goal, you need to give me <b>commands</b>. <span class=\"textUnderline\">’Command Box’</span> is where the <b>commands</b> reside. You can create <b>commands</b> using <b>mouse</b> and <b>keyboard.</b> With the <span class=\"textShadow\">mouse</span>, you can click or drag the <b>commands</b> to create instructions.',\n    maze_operation1_2_textset_1: 'How to click on the commands',\n    maze_operation1_2_textset_2: 'How to drag and drop commands',\n    maze_operation1_3_desc:\n        'If you want to use the <span class=\"textShadow\">keyboard</span> to give commands, <b>type in the commands</b> in the ’Command Box.’<br>When you type in the commands, be careful not to ommit <span class=\"textShadow\">() and ;</span>',\n    maze_operation1_4_desc:\n        'Once you have finished inputting the commands, click <span class=\"textShadow\">[Run.]</span></br>I will move according to your code once you click [Run.]</br>If you want to know more about each command, check out the <span class=\"textShadow\">[Command guide.]</span>',\n    maze_operation7_title: 'STEP 7 - How repeat works (repeat number of times)',\n    maze_operation7_1_desc:\n        'Repeating the <b>same command</b> over and over is a cumbersome task.<br>Simplify the command using the <span class=\"textShadow\">repeat</span> commands.',\n    maze_operation7_2_desc:\n        'Then let\\'s look at how we can simplify commands that repeat.</br>First, click the repeat command. Then change the <span class=\"textShadow\">number</span> in<span class=\"textShadow\">i<1</span></br>Then insert the commands to repeat within  <span class=\"textShadow\"> { }</span>',\n    maze_operation7_3_desc:\n        'For example, this command executes <span class=\"textBadge number1\"></span>move(); 10 times.<br>It is the same as command <span class=\"textBadge number2\"></span>',\n    maze_operation7_4_desc:\n        'When using commands, make sure to spell the  <span class=\"textShadow\">commands correctly within { } </span></br>and that you don\\'t forget <span class=\"textShadow\">’;\\'</span>.</br>Learn more about the commands in the \\'command guide\\'',\n    maze_operation7_1_textset_1: 'When using commands repeatedly',\n    maze_operation7_1_textset_2: 'When using repeat command',\n    maze_operation7_2_textset_1: 'Number of times to repeat',\n    maze_operation7_2_textset_2: 'Commands to repeat',\n    maze_operation7_4_textset_1: 'When ({}) is missing',\n    maze_operation7_4_textset_2: 'When semicolon(;) is missing',\n    study_maze_operation8_title: 'STEP 4 - How repeat works (repeat number of times)',\n    study_maze_operation16_title: 'STEP 4 - How repeat works (repeat number of times)',\n    study_maze_operation1_title: 'STEP 1 - How repeat works (repeat number of times)',\n    maze_operation9_title: 'STEP 9 - How repeat works(Conditional loop)',\n    maze_operation9_1_desc:\n        'We learned about repeating for set number of times.</br>This time, let\\'s explore <span class=\"textShadow\">commands for repeating continuously.</span></br>When you use this command, the action will be executed until end of the mission.</br>Insert commands to be repeated within ({ }).',\n    maze_operation9_2_desc:\n        '<span class=\"textBadge number1\"></span> move(); right(); until end of mission.<br>It is the same as command <span class=\"textBadge number2\"></span>',\n    maze_operation9_3_desc:\n        'Make sure to spell the <span class=\"textShadow\">commands correctly within { }</span><br>and make sure <span class=\"textShadow\">‘true\\'</span> isn\\'t missing!<br>You can learn more about this command in the \\'command guide\\'',\n    maze_operation9_1_textset_1: 'Commands to repeat',\n    maze_operation9_3_textset_1: 'When ({}) is missing',\n    maze_operation9_3_textset_2: 'When semicolon(;) is missing',\n    maze_operation9_3_textset_3: 'When semicolon(;) is missing',\n    study_maze_operation3_title: 'STEP 3 - How repeat works(Conditional loop)',\n    study_maze_operation4_title: 'STEP 4 – How condition works',\n    study_ai_operation4_title: 'STEP 4 – How condition works',\n    study_ai_operation6_title: 'STEP 6 – How condition works',\n    study_ai_operation7_title: 'STEP 7 – How condition works',\n    study_ai_operation8_title: 'STEP 8 – How condition works',\n    study_ai_operation9_title: 'STEP 9 – How condition works',\n    maze_operation10_title: 'STEP 10 – How condition works',\n    maze_operation10_1_desc:\n        'We learned about repeating commands until end of the mission.</br>This time, let\\'s explore the <span class=\"textShadow\">commands that are only executed under certain conditions.</span></br>As you can see in <span class=\"textBadge number2\"></span>, using conditional statement can make commands <b>more efficient.</b>',\n    maze_operation10_2_desc:\n        'conditional statement can be split into  <span class=\"textShadow\">condition</span> and commands to be <span class=\"textShadow\">executed when met with the condition.</span></br>First, let\\'s look at the <span class=\"textUnderline\">conditions.</span> Insert the condition within <span class=\"textUnderline\">( )</span> that follows ‘if\\'.</br>For example <span class=\"textBadge number1\"></span> <span class=\"textUnderline\">if(front == ‘wall\\')</span> means, ’if there is a wall in front of me.’',\n    maze_operation10_3_desc:\n        'Now let\\'s explore  <span class=\"textUnderline\">commands to execute when met with the condition.</span> These commands are tied within curly <span class=\"textShadow\">braces {}</span> and are executed when met with the given condition.When condition is not met, the commands are ignored.Let\\'s look at an example <span class=\"textBadge number1\"></span>. If the condition is \\'when a wall is in front of me\\', and the condition is met, then <b>I execute the commands within the braces and turn right following the command right();</b>',\n    maze_operation10_4_desc:\n        'The <span class=\"textShadow\">conditional statements</span> are often used with <span class=\"textShadow\">repeat commands.</span></br>Go straight and turn only when met with a wall. </br>I can create commands in the <span class=\"textUnderline pdb5\">order of <span class=\"textBadge number1\"></span><span class=\"textBadge number2\"></span><span class=\"textBadge number3\"></span></span>',\n    maze_operation10_1_textset_1: '<b>[commands]</b>',\n    maze_operation10_1_textset_2:\n        '<span class=\"textMultiline\">move 2 forward</br>turn right,</br>move 3 forward</br>turn right, move forward…</span>',\n    maze_operation10_1_textset_3: '<b>[conditional statements]</b>',\n    maze_operation10_1_textset_4:\n        '<span class=\"textMultiline\">Go forward </br><span class=\"textEmphasis\">\\'when met with a wall’</span></br>turn right!</span>',\n    maze_operation10_2_textset_1: 'condition',\n    maze_operation10_2_textset_2: 'commands to execute when condition is met',\n    maze_operation10_3_textset_1: 'condition',\n    maze_operation10_3_textset_2: 'commands to execute when condition is met',\n    maze_operation10_4_textset_1:\n        '<span class=\"textMultiline\">Go forward </br>until end of mission</span>',\n    maze_operation10_4_textset_2:\n        '<span class=\"textMultiline\">Go forward </br>until met with a wall</span>',\n    maze_operation10_4_textset_3:\n        '<span class=\"textMultiline\">Go forward </br>until met with a wall </br>then turn right</span>',\n    study_maze_operation18_title: 'STEP 6 – How condition works',\n    maze_operation15_title: 'STEP 15 – How function works',\n    maze_operation15_1_desc:\n        'It is a cumbersome task to type out the commands that are used often.</br><span class=\"textUnderline\">Give a name to the set of commands</span> that are used often.</br><b>Then call the set of commands by its name to create commands conveniently.</b></br>These sets commands are called <span class=\"textShadow\">\\'functions\\'.</span> Now let\\'s explore what functions are.',\n    maze_operation15_2_desc:\n        'Using a function involves <b>process of creating a function</b> by grouping a set of functions, and calling the set of commands by <b>\\'call function’.</b></br>Let\\'s take a look at the process of defining a function.To define a function, give a function name and set of commands to execute.</br>First input <span class=\"textShadow\">‘function\\'</span> and then give the <span class=\"textShadow\">function name.</span> This time, I\\'ll call it <span class=\"textShadow\">promise.</span></br>Once you\\'ve given it a name, insert <span class=\"textUnderline\">().</span> Then type in <span class=\"textUnderline\">({ })</span>.<span class=\"textUnderline\">Once you insert the commands within these brackets,</span> you have finished defining a function!',\n    maze_operation15_3_desc:\n        'Take a look at this command. I created a function called  <span class=\"textShadow\">promise</span></br>When I call this function, then the commands within the <span class=\"textUnderline\">brackets({})</span> will execute</br>move();</br>move();</br>left();</br>',\n    maze_operation15_4_desc:\n        'To call and execute functions, <b>input the name of the functions, then add \\'();\\' behind it.</b></br>So to call a function called \\'promise\\', I need to type <span class=”textShadow\">promise();</span> </br>to execute the function.</br>When I make commands like <span class=\"number1 textBadge\"></span>, the program will execute as that of <span class=\"number2 textBadge\"></span></br>To use the function, define function as <span class=\"number1 textBadge\"></span> and call it.',\n    maze_operation15_1_textset_1: 'Checking the commands that are used often',\n    maze_operation15_1_textset_2: 'Giving a name for set of commands',\n    maze_operation15_1_textset_3: 'Calling a set of commands',\n    maze_operation15_2_textset_1: 'Name of the command set (function name)',\n    maze_operation15_2_textset_2: 'commads to group as a set',\n    maze_operation15_3_textset_1: 'Name of the command set (function name)',\n    maze_operation15_3_textset_2: 'commads to group as a set',\n    maze_operation15_4_textset_1: 'Defining function',\n    maze_operation15_4_textset_2: 'Calling function',\n    maze_operation15_4_textset_3: 'Real situation',\n    maze_object_title: 'Object info',\n    maze_object_parts_box: 'Tool box',\n    maze_object_trap: 'trap',\n    maze_object_monster: 'monster',\n    maze_object_obstacle1: 'obstacle',\n    maze_object_obstacle2: 'bee',\n    maze_object_obstacle3: 'banana',\n    maze_object_friend: 'friend',\n    maze_object_wall1: 'wall',\n    maze_object_wall2: 'wall',\n    maze_object_wall3: 'wall',\n    maze_object_battery: 'battery',\n    maze_command_ex: 'example',\n    maze_command_title: 'command guide',\n    maze_command_move_desc: 'moves entrybot one forward',\n    maze_command_jump_desc:\n        'jumps over obstacles like the image below.</br><div class=\"obstacleSet\"></div>',\n    maze_command_jump_desc_elec:\n        'jumps over obstacles like the image below.</br><div class=\"obstacle_elec\"></div>',\n    maze_command_right_desc: 'turn 90 degrees right in place.',\n    maze_command_left_desc: 'turn 90 degrees left in place.',\n    maze_command_for_desc:\n        'repeat commands within curly braces <span class=\"textShadow\">{}</span> for <span class=\"textShadow\">given number</span> of times.',\n    maze_command_while_desc:\n        'repeat commands within curly braces <span class=\"textShadow\">{}</span> until end of mission',\n    maze_command_slow_desc:\n        'When condition <span class=\"textShadow\">\\'when met with a wall’</span> is fulfilled, </br>execute commands within curly braces <span class=\"textShadow\">{}</span>',\n    maze_command_if1_desc:\n        'When condition <span class=\"textShadow\">\\'when met with a wall’</span> is fulfilled, </br>execute commands within curly braces <span class=\"textShadow\">{}</span>',\n    maze_command_if2_desc:\n        'When condition <span class=\"textShadow\">\\'when met with a beehive’</span> is fulfilled,</br>execute commands within curly braces <span class=\"textShadow\">{}</span>',\n    maze_command_if3_desc:\n        'When condition <span class=\"textShadow\">\\'when met with a banana’</span> is fulfilled,</br>execute commands within curly braces <span class=\"textShadow\">{}</span>',\n    maze_command_promise_desc:\n        'when a <span class=\"textShadow\">function</span> called \\'promise\\' is defined and executed, </br>then the functions within the curly braces <span class=\"textShadow\">{}</span> will execute. ',\n    perfect: 'Perfect! You succeeded using ',\n    succeeded_using_blocks: '  blocks!',\n    succeeded_using_commands: '  commands!',\n    awesome: 'Awesome! You succeeded using just',\n    succeeded_go_to_next: '  blocks!',\n    good: 'Good!',\n    but: '<br> But, there is a way to succeed using just ',\n    try_again: '  blocks. <br>Why don’t you try again?',\n    try_again_commands: '  commands. <br>Why don’t you try again?',\n    cfest_success:\n        'Awesome! You helped save my friends! <br> Looks like you’re a natural born programmer! <br> See you again soon!',\n    succeeded_and_cert: 'blocks!<br> My certificate of completion is ready!',\n    cause_msgs_1: 'Oh dear, it’s a dead end. Try again.',\n    cause_msgs_2: 'Oops. There’s nothing to jump over. Try again.',\n    cause_msgs_3: 'Ouch! That hurt. You should have jumped over this. Try again.',\n    cause_msgs_4:\n        'Sorry, but you need to use the below blocks in this level. <br> Do you want to try again?',\n    cause_msgs_5: 'Uh oh… You’ve run out of blocks. Try again.',\n    cause_msgs_6: 'Uh oh… You’ve run out of commands. Try again.',\n    close_experience: 'The<br>End',\n    replay: 'Replay',\n    go_to_next_level: 'Next',\n    move_forward: 'Move forward',\n    turn_left: 'Left',\n    turn_right: 'Right',\n    turn_en: 'Turn ',\n    turn_ko: '',\n    jump_over: 'Jump Over',\n    when_start_is_pressed: 'When Start is pressed',\n    repeat_until_ko: '',\n    repeat_until_en: 'Repeat until',\n    repeat_until: 'Repeat until',\n    if_there_is_1: 'If there is a ',\n    if_there_is_2: '',\n    used_blocks: 'Blocks used',\n    maximum: 'Maximum',\n    used_command: 'Command used',\n    maximum_command: 'Maximum command',\n    block_box: 'Block Box',\n    block_assembly: 'Block Assembly',\n    command_box: 'Command Box',\n    command_assembly: 'Command Assembly',\n    start: 'Start',\n    engine_running: 'Play',\n    engine_replay: 'Replay',\n    goto_show: 'Learn more',\n    make_together: \"Let's build  together!\",\n    make_together_content: 'Entry is created with teachers and students',\n    project_nobody_like: \"Click 'Like', if you like it!\",\n    project_nobody_interest: \"Click 'Mark' to keep it on your blog.\",\n    lecture_nobody_like: \"Click 'Like', if you like it!\",\n    lecture_nobody_interest: \"Click 'Mark' to keep it on your blog.\",\n    course_nobody_like: \"Click 'Like', if you like it!\",\n    course_nobody_interest: \"Click 'Mark' to keep it on your blog.\",\n    before_changed: 'before changed',\n    after_changed: 'after changed',\n    from_changed: '( From 17 Apr 2016 ) ',\n    essential: 'essential',\n    access_term_title:\n        'Hello we are an educational institute Entry . <br> Thank you for loving your entry <br>From April 17, 2016 Entry Training Institute Website Terms and Conditions <br>  is amended to read as follows:',\n    member_info: 'Member information',\n    personal_info: 'Agree to the transfer of personal information.',\n    option: 'select one',\n    news: 'news',\n    edu_material: 'materials',\n    latest_news: 'Latest news',\n    edu_data: 'Educational',\n    training_program: 'Training',\n    footer_phrase:\n        'Entry is a nonprofit education platform powered by Naver and CONNECT Foundation',\n    footer_use_free:\n        'All materials created by Entry Labs may be used freely for educational purposes as long as the original source is credited.',\n    footer_description_1: 'Entry is a nonprofit education platform.',\n    footer_description_2:\n        'All materials created by Entry Labs may be used freely for educational purposes as long as the original source is credited.',\n    nonprofit_platform: 'nonprofit educational platform',\n    this_is: 'powered by Naver and CONNECT Foundation',\n    privacy: 'Privacy policy',\n    entry_addr: '16F, 6, Buljeong-ro, Bundang-gu, Seongnam-si, Gyeonggi-do',\n    entry_addr_additional_phone: '1522-9182',\n    entry_addr_additional_email: 'entry@connect.or.kr',\n    entry_addr_additional_opensource: 'Open Source License',\n    phone: 'phone',\n    alert_agree_term: 'Please agree to ENTRY’s Terms of Use',\n    alert_private_policy: 'Please agree to the collection and use of personal information.',\n    agree: 'Agree',\n    optional: 'option',\n    start_software: 'first step of software education',\n    analyze_procedure: '절차',\n    analyze_repeat: '반복',\n    analyze_condition: '분기',\n    analyze_interaction: '상호작용',\n    analyze_dataRepresentation: '데이터 표현',\n    analyze_abstraction: '추상화',\n    analyze_sync: '병렬 및 동기화',\n    jr_intro_1:\n        'Hi! My name is Juny! My friend Entry-Bot is by my right side. Please take me to him! ',\n    jr_intro_2: \"Entry-Bot is by my left! Let's go the left side. \",\n    jr_intro_3: 'Entry-Bot is by my top side. Please help me meet my friend. ',\n    jr_intro_4: \"Come on! Let's meet Entry-Bot! He is by my bottom side. \",\n    jr_intro_5: 'Wow! My friend is far away from me. Can you guide me so I can meet Entry-Bot ',\n    jr_intro_6:\n        \"Entry-Bot is really far away from here! But It's okay. If we use repeat block, we could reach the Entry-Bot easily.\",\n    jr_intro_7: \"There are beautiful flowers here! Let's give it to my friend!\",\n    jr_intro_8: \"On a way to my friend, you can see the flower. Let's give it to my friend.\",\n    jr_intro_9: \"Oh, my friend is far away from me. Let's find a fastest way to him!\",\n    jr_intro_10: \"There are flowers! Let's pick it up! \",\n    jr_intro_11:\n        \"We should go right side exactly 5 times! Let's use repeat block so we can reach there more easily\",\n    jr_intro_12: \"Let's meet my friend Entry-Bot using repeat block.\",\n    jr_intro_13:\n        \"With this misplaced block, I can't reach my friend. Please change the input number of repeat block.\",\n    jr_intro_14: 'Please take me to my friend Entry-Bot using repeat block.',\n    jr_intro_15:\n        \"Entry-Bot is really far away from here! But It's okay. If we use repeat block, we could reach the Entry-Bot easily.\",\n    jr_whats_ur_name: 'What is your name to be showned on certification.',\n    jr_down_cert: 'Certification',\n    jr_popup_prefix_1: 'Hooray! I met Entry-Bot!',\n    jr_popup_prefix_2:\n        'Nice! I met Entry-Bot! But we can make it with fewer blocks. How about try again?',\n    jr_popup_prefix_3: 'Hooray! I got my backpack!',\n    jr_popup_prefix_4:\n        'Great! I have my backpack! But we can make it with fewer blocks. How about we try again?',\n    jr_popup_suffix_1: 'Thank you! I had so much fun with you. See you around!',\n    jr_popup_suffix: 'Thanks to you! I had fun time with Entry-Bot. See you around~',\n    jr_fail_dont_go: \"Oops, I can't go there. Please guide me again~\",\n    jr_fail_dont_know: 'Hmm. Where should I go? Please guide me more~',\n    jr_fail_no_flower: \"There is no flower. Use 'flower block' at the flower!\",\n    jr_fail_forgot_flower: \"I need more flowers for Entry-Bot. Let's try again.\",\n    jr_fail_need_repeat: \"Uh? I should use 'repeat block' ! Let's try again with the block~\",\n    jr_hint_1:\n        'Hi! My name is Juny! My friend Entry-Bot is by my right side. Please take me to him!',\n    jr_hint_2: \"Entry-Bot is by my left! Let's go the left side.\",\n    jr_hint_3: 'Entry-Bot is by my top side. Please help me meet my friend.',\n    jr_hint_4: \"Come on! Let's meet Entry-Bot! He is by my bottom side.\",\n    jr_hint_5: 'Wow! My friend is far away from me. Can you guide me so I can meet Entry-Bot?',\n    jr_hint_6:\n        \"Because of the blocks that put together by mistake, I can't reach my friend. Please fix it for me so I can reach my friend Entry-Bot!\",\n    jr_hint_7: \"There are beautiful flowers here! Let's give it to my friend!\",\n    jr_hint_8: \"On a way to my friend, you can see the flower. Let's give it to my friend.\",\n    jr_hint_9: \"Oh, my friend is far away from me. Let's find a fastest way to him!\",\n    jr_hint_10:\n        \"Oops, I can't reach to my friend because of misplaced blocks. Please fix it so I can give all of flowers to my friend.\",\n    jr_hint_11:\n        \"We should go right side exactly 5 times! Let's use repeat block so we can reach there more easily.\",\n    jr_hint_12: \"Let's meet my friend Entry-Bot using repeat block.\",\n    jr_hint_13:\n        \"With this misplaced block, I can't reach my friend. Please change the input number of repeat block.\",\n    jr_hint_14: 'Please take me to my friend Entry-Bot using repeat block.',\n    jr_hint_15:\n        \"Entry-Bot is really far away from here! But It's okay. If we use repeat block, we could reach the Entry-Bot easily.\",\n    jr_certification: 'Certification',\n    jr_congrat: 'Congratulation!',\n    jr_congrat_msg: 'Successfully completed for problem solving courses.',\n    jr_share: 'Share',\n    go_see_friends: 'Let us see your friends~!',\n    junior_naver: 'Junior Naver',\n    junior_naver_contents_1: \"'s  cool bear ,  Juni  came looking for entries! \",\n    junior_naver_contents_2: \"But Juni' is difficult to find a way yet. \",\n    junior_naver_contents_3: 'Please tell Juni to go , so he can meet entrybot.',\n    basic_content: 'Basic',\n    jr_help: 'Help',\n    help: 'Help',\n    cparty_robot_intro_1:\n        \"Hi, My name is Entry-bot. I need to to fix myself. Please help me get my parts with 'move forward' block.\",\n    cparty_robot_intro_2:\n        \"Great! My part is right in front of me but I need to be careful not to get electrocuted. Use 'jump over' block to get to the part.\",\n    cparty_robot_intro_3:\n        \"Great! There's my part! The path is challenging but using the 'turn' block I can get there easily! Will you help?\",\n    cparty_robot_intro_4:\n        \"Nice! I feel a lot better! Try using the 'turn' block and 'jump over' block to get the parts!\",\n    cparty_robot_intro_5:\n        \"Thanks to you, I'm feeling great! Make sure to use 'turn' and 'jump over' to get the part!\",\n    cparty_robot_intro_6: 'Great! I feel like I can repeat! Use repeat to get to the part!',\n    cparty_robot_intro_7:\n        \"Watch out! There are dangerous holes to jump over but no worries! Let's use repeat to get to the part.\",\n    cparty_robot_intro_8:\n        'Oh no! The part is far from here. Using repeat can get me there easily. Help me! ',\n    cparty_robot_intro_9: \"Wow~ I'm almost complete! Let's use 'repeat' to get to the part!\",\n    cparty_robot_intro_10:\n        \"Cool! The last part will make me complete! Let's use 'repeat' to get to my last part! \",\n    cparty_car_intro_1:\n        'Hi, My name is Entry-bot. I need battery pack to travel! Can you me get to the battery pack?',\n    cparty_car_intro_2:\n        \"Good! We can't go straight this time! Let's use the 'turn left/right' block to get to the battery pack.\",\n    cparty_car_intro_3:\n        \"Great! There's a speed bump on our way. It'll be dangerous to drive fast. Let's use the 'go slow' block to get to the battery pack.\",\n    cparty_car_intro_4:\n        \"Yeah! The drive doesn't look easy but using the move forward, 'turn left/ right' block\",\n    cparty_car_intro_5:\n        \"The road looks challenging but we can safely get to the battery pack by repeating 'turn left/ right' blocks\",\n    cparty_car_intro_6: 'There are obstacles on our way so let me know how to get around one!',\n    cparty_car_intro_7:\n        \"Great! Let's use the 'if' block to get around obastacles and get to the battery pack.\",\n    cparty_car_intro_8:\n        \"There are two speed bumps this time! Use 'go slow' block to safely travel to the battery pack.\",\n    cparty_car_intro_9:\n        \"The road looks challenging but using the 'repeat' block and 'if' block, we can make it! Help me get to the battery pack!\",\n    cparty_car_intro_10: \"Awesome! We're almost there. Let's get that last battery pack!\",\n    cparty_car_popup_prefix_1: 'Hooray! I got a battery!',\n    cparty_car_popup_prefix_2:\n        'Nice! I got a battery! But we can make it with fewer blocks. How about try again?',\n    cparty_car_popup_prefix_2_text:\n        'Nice! I got a battery! But we can make it with fewer commands How about try again?',\n    cparty_car_popup_suffix: \"Thanks to you! I've got all the battery. See you around~\",\n    all_grade: 'All grades',\n    grade_e3_e4: 'Elementary 3~4th grade & up',\n    grade_e5_e6: 'Elementary 5~6th grade & up',\n    grade_m1_m3: 'Middle School 1~3rd grade & up',\n    entry_first_step: 'Entry First Steps',\n    entry_monthly: 'Monthly Entry',\n    play_sw_2: \"Let's Play  Software 2\",\n    entry_programming: \"Let's Program!\",\n    entry_recommanded_course: 'Entry Recommended Courses',\n    introduce_course: 'Follow along and create various projects made easy and fun for everyone!',\n    all_free: '*Course videos, customized projects, and resources are provided for free.  ',\n    cparty_result_fail_1: \"Oops, I can't go there. Please guide me again~\",\n    cparty_result_fail_2: 'Ouch! That hurt. You should have jumped over this. Try again.',\n    cparty_result_fail_3: \"I'm worn out! Try using the blocks below and make the travel easier.\",\n    cparty_result_fail_4: 'Hmm... Where should I go? Please give me further instructions.',\n    cparty_result_fail_5:\n        \"Oh no! You need to slow down at the speed bump. Try using the 'go slow' block.\",\n    cparty_result_success_1: 'Hooray! I got a parts',\n    cparty_result_success_2:\n        'Nice! I got a parts! But we can make it with fewer blocks. How about we try again?',\n    cparty_result_success_2_text:\n        'Nice! I got a parts! But we can make it with fewer commands How about we try again?',\n    cparty_result_success_3: \"Thanks to you! I've fixed all~ See you around~\",\n    cparty_insert_name: 'insert your name',\n    offline_file: 'File',\n    offline_edit: 'Edit',\n    offline_undo: 'Un-do',\n    offline_redo: 'Re-do',\n    offline_quit: 'Quit',\n    select_one: 'Please select one.',\n    evaluate_challenge: 'please evaluate the level of difficulty of the mission challenged.',\n    very_easy: 'very easy',\n    easy: 'easy',\n    normal: 'normal',\n    difficult: 'difficult',\n    very_difficult: 'very difficult',\n    save_dismiss: \"You didn't saved your changes. Are you sure want to continue?\",\n    entry_info: 'About Entry',\n    actual_size: 'Actual Size',\n    zoom_in: 'Zoom In',\n    zoom_out: 'Zoom Out',\n    cparty_jr_intro_1:\n        'Hi! My name is Entry-Bot! Please help me get my backpack on my way to school.',\n    cparty_jr_intro_2: \"My backpack to my left! Let's go left.\",\n    cparty_jr_intro_3: 'My backpack is located above. Please help me to get my backpack.',\n    cparty_jr_intro_4: \"Come on! Let's pick up the backpack by going downwards.\",\n    cparty_jr_intro_5: 'Wow! My backpack is far away from me. Could you take me to my backpack?',\n    cparty_jr_intro_6: \"There is backpack! Let's pick it up!\",\n    cparty_jr_intro_7:\n        \"There are pencils along the way. Let's pick them up on our way to the backpack.\",\n    cparty_jr_intro_8:\n        \"A pencil on our way to school! Let's pick up the pencil on our way to the backpack.\",\n    cparty_jr_intro_9: \"Oh, my backpack is far away. Let's find the fastest path to it!\",\n    cparty_jr_intro_10: \"Let's pick up the pencils on my way to the backpack!\",\n    cparty_jr_intro_11:\n        \"We should go right exactly 5 times! Let's use the repeat block so we can get there more easily\",\n    cparty_jr_intro_12: \"Let's pick up the backpack using the repeat block.\",\n    cparty_jr_intro_13:\n        \"I can't reach my backpack with this misplaced block. Please change the number of repeats.\",\n    cparty_jr_intro_14: 'Please take me to my backpack using the repeat blocks.',\n    cparty_jr_intro_15:\n        \"School is really far from here! But that's okay. If we use the repeat block, we can get to school easily.\",\n    make_new_project: 'Create New Project',\n    open_old_project: 'Open Project',\n    offline_download: 'Entry Download',\n    offline_release: 'Download Entry Offline Editor!',\n    offline_description_1: 'Install and use Entry Offline Editor',\n    offline_description_2: 'without internet connection.',\n    offline_description_3: 'Download and try it out!',\n    sw_week_2015: '2015 소프트웨어교육 체험 주간',\n    cparty_desc: '두근두근 소프트웨어와의 첫만남',\n    entry_offline_download: 'Download \\nOffline Editor',\n    entry_download_detail: 'Download\\nVeiw Details',\n    offline_desc_1: 'Install and use Entry Offline Editor without internet connection.',\n    offline_desc_2: 'Download and try it out!',\n    download: 'download',\n    version: 'version',\n    file_size: 'size',\n    update: 'update',\n    use_range: 'Scope of use',\n    offline_desc_free: 'Entry Offline Editor is free for both individual and corporate use.',\n    offline_required: 'System Requirement',\n    offline_required_detail:\n        'Minimum 1GB disk space is required, Windows7 and above or, Mac OS 10.8 and above',\n    offline_notice: 'Side notes',\n    offline_notice_1: '1. Version',\n    offline_notice_1_1: 'does not support installation of all-in-one hardware connection program',\n    offline_notice_2: '2. Web browser is not needed.',\n    offline_notice_3: 'Release note',\n    offline_notice_4: 'Download by version',\n    offline_notice_5: 'Release note',\n    hardware_online_badge: 'Online',\n    hardware_title: 'Entry Hardware Connector Program Download',\n    hardware_desc:\n        \"In order to connect to hardware projects and 'Create Project' online, download and install Entry Hardware Connector Program.\",\n    hardware_release:\n        'Details on Hardware Connector Program updates are available in the link below.',\n    hardware_window_download: 'Windows Download',\n    hardware_osx_download: 'Mac Download',\n    cparty_jr_result_2: 'Thank you! I had so much fun with you.<br> See you around!',\n    cparty_jr_result_3:\n        \"Great! I've arrived school! But we can make it with fewer blocks.<br> How about we try again? \",\n    cparty_jr_result_4: '',\n    lms_no_class: 'There is no class.',\n    lms_create_class: 'Please create a class.',\n    lms_add_class: 'Create class',\n    lms_base_class: 'Default',\n    lms_delete_class: 'Delete',\n    lms_my_class: 'My Class',\n    lms_grade_1: 'elementary school 1',\n    lms_grade_2: 'elementary school 2',\n    lms_grade_3: 'elementary school 3',\n    lms_grade_4: 'elementary school 4',\n    lms_grade_5: 'elementary school 5',\n    lms_grade_6: 'elementary school 6',\n    lms_grade_7: 'middle school 1',\n    lms_grade_8: 'middle school 2',\n    lms_grade_9: 'middle school 3',\n    lms_grade_10: 'general',\n    lms_add_groupId_personal: 'Add classroom ID to your member profile.',\n    lms_add_groupId: 'Add Classroom ID',\n    lms_add_group_account: 'Add Classroom ID',\n    lms_enter_group_info: 'Enter classroom ID and password',\n    lms_group_id: 'Classroom ID',\n    lms_group_pw: 'Password',\n    lms_group_name: 'Class Name',\n    personal_pwd_alert: 'Enter correct password',\n    personal_form_alert: '양식을 바르게 입력해 주세요',\n    personal_form_alert_2: '모든 양식을 완성해 주세요',\n    personal_no_pwd_alert: 'Enter password',\n    select_gender: 'Please enter your gender',\n    enter_group_id: 'Enter classroom ID',\n    enter_group_pwd: 'Enter password',\n    info_added: '추가되었습니다',\n    no_group_id: 'The Class ID does not exist',\n    no_group_pwd: '비밀번호가 일치하지 않습니다',\n    lms_please_choice: 'Choose',\n    group_lesson: '나의 학급 강의',\n    lms_banner_add_group: 'Learning Management System is now available',\n    lms_banner_entry_group: 'Create Entry class ',\n    lms_banner_desc_1: 'Add your students',\n    lms_banner_desc_2: \"Manage your student's projects\",\n    lms_banner_desc_3: 'and track their growth.',\n    lms_banner_download_manual: 'Manual Download',\n    lms_banner_detail: 'Try it out!',\n    already_exist_email: 'email already exists',\n    same_registered_email: 'Registered email.',\n    email_correnctly_please: 'Please enter a valid email',\n    remove_project: 'Are you sure to remove this project?',\n    study_lesson: 'Class Lessons',\n    open_project: 'Open projects',\n    make_group: 'Create Class',\n    project_share: 'Project share',\n    group_project_share: 'Class Share',\n    group_discuss: 'Class Discuss',\n    my_profile: 'My page',\n    search_updated: 'Recent Project',\n    search_recent: 'Project with most views',\n    search_complexity: 'Project with most effort',\n    search_staffPicked: 'Staff pick project save area',\n    search_childCnt: 'Project with most copies',\n    search_likeCnt: 'Project with most likes',\n    search_recentLikeCnt: 'Project with most likes',\n    gnb_share: 'Share',\n    gnb_community: 'Community',\n    lms_add_lectures: 'Add Lessons',\n    lms_add_course: 'Add Courseware',\n    lms_add_homework: 'Add Assignment',\n    remove_lecture_confirm: 'Are you sure you want to delete?',\n    popup_delete: 'Delete',\n    remove_course_confirm: 'Are you sure you want to delete?',\n    lms_no_lecture_teacher_1: 'There is no lessons.',\n    lms_no_lecture_teacher_2: 'Please create a lessons.',\n    gnb_download: 'Download',\n    lms_no_lecture_student_1: '',\n    lms_no_lecture_student_2: 'There is no lessons.',\n    lms_no_lecture_student_3: '',\n    lms_no_class_teacher: 'There is no class.',\n    lms_no_course_teacher_1: 'There is no courseware.',\n    lms_no_course_teacher_2: 'Please create a courseware.',\n    lms_no_course_student_1: '',\n    lms_no_course_student_2: 'There is no courseware.',\n    lms_no_course_student_3: '',\n    lms_no_hw_teacher_1: 'There is no assignment.',\n    lms_no_hw_teacher_2: 'Please create a assignment.',\n    lms_no_hw_student_1: '',\n    lms_no_hw_student_2: 'There is no assignment.',\n    lms_no_hw_student_3: '',\n    modal_edit: 'edit',\n    modal_deadline: 'Deadline',\n    modal_hw_desc: 'Description',\n    desc_optional: '(optional)',\n    modal_create_hw: 'Create Assignment',\n    vol: 'Vol.',\n    hw_title: 'Title',\n    hw_description: 'Description',\n    deadline: 'Deadline',\n    do_homework: 'Do Assignment',\n    hw_progress: 'Progress',\n    hw_submit: 'submit',\n    view_list: 'Submitter',\n    view_desc: 'content',\n    do_submit: 'submit',\n    popup_notice: 'Alert',\n    no_selected_hw: 'No Assignment is selected',\n    hw_delete_confirm: 'Are you sure you want to delete?',\n    hw_submitter: 'List of Assignment submissions',\n    hw_student_desc_1:\n        \"* You may edit the project until 'Submit' button completes the submission process.\",\n    hw_student_desc_2: '* Once submission period is over, project cannot be submitted.',\n    popup_create_class: 'Create Class',\n    class_name: 'Class name',\n    image: 'Image',\n    select_class_image: 'Please select a class image.',\n    type_class_description: 'Class Introduction.',\n    set_as_primary_group: 'Set as default classroom',\n    set_primary_group: 'assign',\n    not_primary_group: 'not assigned',\n    type_class_name: 'Please enter the class name.',\n    type_class_description_long: 'Please enter the class introduction.',\n    add_students: 'Add students',\n    invite_students: 'Invite students',\n    invite_with_class: '1. Invite with class code',\n    invite_code_expiration: 'Code expiration time',\n    generate_code_button: 'reissue code',\n    generate_code_desc: 'Student instructions for entering class code',\n    generate_code_desc1: 'Log in at playentry.org',\n    generate_code_desc2: 'Select <my class> from the menu.',\n    generate_code_desc3: 'Click <Enter class code> then paste in the class code.',\n    invite_with_url: '2. Invite using class URL',\n    copy_invite_url: 'Copy',\n    download_as_pdf: 'Download code as PDF file',\n    download_as_excel: 'Download code as Excel file',\n    temp_password: 'Temporary password',\n    step_name: 'Name',\n    step_info: 'Additional Information',\n    preview: 'Preview',\n    type_name_enter: 'To add student, type in the student name and hit enter. ',\n    multiple_name_possible: 'Adding multiple student names is possible.',\n    id_auto_create: 'Student number is automatically created if not edited',\n    student_id_desc_1: 'Class ID is created automatically without manual input',\n    student_id_desc_2:\n        'If student account already exists, add student information. When the student logs in,',\n    student_id_desc_3:\n        'class invitation is sent. No extra step for sharing account information is necessary.',\n    student_number: 'Student number',\n    temp_password_desc_1: 'After logging in with temporary password,',\n    temp_password_desc_2: 'guide the students to reset the password.',\n    temp_password_desc_3: '*You cannot see temporary password once issued',\n    temp_password_demo: 'This is an informational account that can not log in.',\n    temp_works: 'View works',\n    student_delete_confirm: 'Are you sure you want to delete?',\n    no_student_selected: 'No student is selected',\n    class_assignment: 'Class Assignments',\n    class_list: 'Class List',\n    select_grade: 'Please select the grade.',\n    add_project: 'sharing Project',\n    no_project_display: 'There is no project to display.',\n    plz_display_project: 'Please display a project.',\n    refuse_confirm: 'Are you sure you want to refuse?',\n    select_class: '학급 선택',\n    group_already_registered: 'Already registered.',\n    my_page_entry: 'Entry',\n    my_page_title: 'My Page',\n    my_classGroup_title: 'My Class',\n    my_classGroup_title_view: 'view my class',\n    my_space_area: 'my own space',\n    mon: 'MON',\n    tue: 'TUE',\n    wed: 'WED',\n    thu: 'THU',\n    fri: 'FRI',\n    sat: 'SAT',\n    sun: 'SUN',\n    jan: 'Jan',\n    feb: 'Feb',\n    mar: 'Mar',\n    apr: 'Apr',\n    may: 'May',\n    jun: 'Jun',\n    jul: 'Jul',\n    aug: 'Aug',\n    sep: 'Sep',\n    oct: 'Oct',\n    nov: 'Nov',\n    dec: 'Dec',\n    plz_select_lecture: 'Please select a lessons.',\n    plz_set_deadline: 'Please set the deadline.',\n    hide_entry: 'Hide Entry',\n    hide_others: 'Hide Others',\n    show_all: 'Show All',\n    lecture_description:\n        'Lessons are listed by topics and levels. Follow along in step-by-step order.',\n    curriculum_description:\n        'Teacher created Entry learning space. See example projects and try creating them.',\n    linebreak_off_desc_1: 'The size of textbox determines the font size.',\n    linebreak_off_desc_2: 'Your content can only be written in one line.',\n    linebreak_off_desc_3:\n        'The left and the right sides of the textbox will lengthen when you add extra words.',\n    linebreak_on_desc_1: 'The size of textbox determines how much you can write.',\n    linebreak_on_desc_2: \"You can change the line by pressing the 'Enter' key.\",\n    linebreak_on_desc_3:\n        'Your content will automatically go to the next line if the length exceeds the width of the textbox, when writing or adding new words.',\n    not_supported_text: 'Current font does not support Chinese characters',\n    entry_with: 'Entry is Created With Teachers',\n    ebs_season_1: 'Visit Season 1',\n    ebs_season_2: 'Visit Season 2',\n    hello_ebs: 'Hello! EBS software',\n    hello_ebs_desc:\n        'Learn the basic principles of programming. \\n Watch the show, follow along the video tutorials, \\n and learn to code!',\n    hello_ebs_sub_1: \"Meet EBS's interactive middle \",\n    hello_ebs_sub_2: 'school age program.',\n    exhibit_4th_title: '4th Anniversary of Entry',\n    exhibit_4th_subtitle: 'Entry Project Contest',\n    exhibit_4th_desc1: 'We hold an Entry Project Contest ',\n    exhibit_4th_desc2: 'to celebrate the 4th anniversary of entry.',\n    exhibit_4th_desc3: 'Show off your great project!',\n    exhibit_4th_button: 'View Details',\n    visang_edu_entry: '비상교육 엔트리 학습하기',\n    cmass_edu_entry: '씨마스 엔트리 학습하기',\n    chunjae_edu_entry: '천재교과서 엔트리 학습하기',\n    kumsungemt_edu_entry: '금성출판사 엔트리 학습하기',\n    kumsungMid_edu_entry: '금성출판사 엔트리 학습하기',\n    gilbutEdu_edu_entry: '길벗출판사 엔트리 학습하기',\n    miraenCoding_edu_entry: '미래엔 엔트리 학습하기',\n    textbook_help_data: 'Help data',\n    textbook_teaching_activity: 'teaching and activity',\n    textbook_kyohacksa: 'Kyohaksa',\n    textbook_kumsung: 'Kumsung Publishing',\n    textbook_donga: 'Dong-a Publishing',\n    textbook_chunjae: 'Chunjae Education',\n    textbook_miraen: 'Mirae-n',\n    textbook_visang: 'Visang',\n    partner: 'Our Partners',\n    project_term_popup_title: 'Copyright policy',\n    project_term_popup_description_1: 'Please review the Entry ',\n    project_term_popup_description_2: 'copyright policy ',\n    project_term_popup_description_3: 'to allow public viewing ',\n    project_term_popup_description_4: 'of the project.',\n    project_term_agree_1_1: 'I agree to the release of my work itself and its source code.',\n    project_term_agree_2_1: 'I permit others to use it.',\n    project_term_agree_2_2: '(includes copy, distribution, and transmission through airwaves)',\n    project_term_agree_3_1: 'I permit others to make modifications to it.',\n    project_term_agree_3_2: '(includes remixes, modifications, and derivative works)',\n    agree_all: 'I agree to all conditions.',\n    select_login: 'Log in',\n    select: 'Please select',\n    with_login: 'Log in and',\n    without_login: 'Start Challenge',\n    start_challenge: 'Start Challenge',\n    start_challenge_2: 'without Logging in',\n    if_not_save_not_login: '* Your progress will not be saved if not logged in.',\n    if_not_member_yet: \"If you aren't a member yet,\",\n    join_entry: 'Join Entry',\n    learned_computing: 'Have you learned computing before?',\n    cparty_index_description_1: 'My first computing.',\n    cparty_index_description_2:\n        'Learn programming concepts and develop your thinking skills while playing Entry. ',\n    cparty_index_description_3:\n        'Challenge yourself to exciting mission stages and earn certificates.',\n    cparty_index_description_4: '2015 Online Coding Party is part of',\n    cparty_index_description_5: 'Software Programming Experience Week',\n    cparty_index_description_6: 'prepared with',\n    cparty_index_description_7: 'Association of Teachers for Computing.',\n    cparty_index_description_8: '',\n    cparty_index_description_9: '2016 Online Coding Party is part of',\n    cparty_index_description_10: '2017 Online Coding Party is part of',\n    cparty_index_description_11: 'Association of Teachers for Computing.',\n    congratulation: 'Congratulation!',\n    warm_up: 'warm-up',\n    beginner: 'beginner',\n    intermediate: 'intermediate',\n    advanced: 'advanced',\n    applied: 'applied',\n    cert_msg_tail: 'track.',\n    cert_msg_head: 'You have successfully completed the',\n    maze_text_content_1: ' 명령어를 사용해서 나를 부품 상자까지 이동시켜줘!',\n    maze_text_content_2: ' 명령어를 사용해서 장애물을 뛰어넘어야해!',\n    maze_text_content_3:\n        \"Nice! I see another part over there. The path is twisted but I can get there using the 'right();', 'left();' commands. \",\n    maze_text_content_4:\n        \"I can move smoothly now. Take me to my parts using the commands we've learned so far.\",\n    maze_text_content_5: \"Wow! Two parts! Let's collect them both so I can recover faster.\",\n    maze_text_content_6:\n        \"Last part! I'll recover fully with that last piece. You'll help me, right?\",\n    maze_text_content_7:\n        \"I'm feeling great! I can repeat tasks without stress now. Oh no! What is that robot in front of us? I think it needs help! Use 'for' command to get to the friend!\",\n    maze_text_content_8:\n        \"Excellent! I was able to rescue my robot friend thanks to you. I see another friend over there. Be careful. There are beehives to avoid. You can do it! Let's use the 'for' command to get to my friend.\",\n    maze_text_content_9:\n        \"Use 'while' instead of 'for' to repeat until we've accomplished our goal. Take me to my friend.\",\n    maze_text_content_10:\n        \"Now we have 'if' command. Use 'if' and 'while' to let me know which way to turn.\",\n    maze_text_content_11: \"Great! Let's do this once more. Tell me when to turn left.\",\n    maze_text_content_12: 'There are beehives scattered in the pathway. Tell me when to jump over.',\n    maze_text_content_13: \"So many friends need help! Let's go help them\",\n    maze_text_content_14:\n        \"More friends to rescue! Let's first try going around those square blocks and repeat to get to all of my friends.\",\n    maze_text_content_15:\n        \"I'm tired from moving so much. I've grouped the commands that are often used into 'functions'. Use functions to get me to my battery!\",\n    maze_text_content_16: 'Excellent! Create functions and take me to my battery!',\n    maze_text_content_17: \"Great job! Let's create functions with 'jump()\",\n    maze_text_content_18:\n        \"The pathway is complex this time. But no worries! Just tell me when to use 'left()\",\n    maze_text_content_19:\n        \"The functions are already defined! However, it seems difficult to get to the battery using only the functions. Let's try mixing functions and commands to get to the battery.\",\n    maze_text_content_20:\n        \"You've done a fantastic job so far! After I retrieve that last battery, I will no longer need charging. Help me get to the battery using the functions so I can live free forever!\",\n    maze_content_1:\n        \"Hi, I'm Entrybot. I'm trying to escape from this factory but first, I have to fix myself. Will you help me fetch my parts? Assemble 'Move forward' block and press Start. \",\n    maze_content_2:\n        \"Very good! I'm feeling much better! I see my part over there but I might get electrocuted if I don't be careful. Let's use 'jump over obstacle' block to get to the part.\",\n    maze_content_3:\n        \"Great! My part is right over there. The path is a bit twisted but I can get there using 'rotate' blocks. You'll help me, right?\",\n    maze_content_4:\n        \"Nice! I can almost move freely now. Let's get the part using 'rotate' and 'jump' blocks.\",\n    maze_content_5: \"Wow! Two parts! Let's get them both so I can restore my health faster.\",\n    maze_content_6:\n        \"Thanks to you I'm feeling much better! I'm able to get better with those parts. You'll help me, right?\",\n    maze_content_7:\n        \"I'm feeling great! I can repeat the same task without trouble now. Oh! Do you see the robot over there? I think she might need help. Let's go help her out. Bring me to her by changing the number of 'repeat's\",\n    maze_content_8:\n        \"Excellent! I was able to rescue my pal! It looks like another one of my friends need help. Be careful there are beehives. Be sure to jump over the beehives! Can you do it? Help me reach her using the 'repeat' block. \",\n    maze_content_9:\n        'Instead of repeating a task for set number of times, I can repeat until I reach my robot pal instead! Help me save my friend!',\n    maze_content_10:\n        \"Now we can use the 'if' block. Help me use the 'if' block to turn at right timing.\",\n    maze_content_11: \"Let's try it again! Let me know when to turn left.\",\n    maze_content_12: 'There are beehives all over the place. Tell me when to jump!',\n    maze_content_13: \"My friends need help! Let's go help them!\",\n    maze_content_14:\n        \"More friends need rescue! Let's first go around the small square and repeat it to rescue all my friends.\",\n    maze_content_15:\n        \"Now I can memorize blocks that are used repeatedly. Promise blocks are the ones that I was able to memorize. I'm a bit tired from moving so much. Help me refill my battery using the Promise feature!\",\n    maze_content_16:\n        'Great! Tell me which blocks are used often and put them under the Promise block!',\n    maze_content_17:\n        \"Nice! Use Promise blocks to help me get my battery. Make sure to insert 'Jump' blocks in the Promise block.\",\n    maze_content_18:\n        'The path looks complex! We can get through this if we turn left and right at the right time.',\n    maze_content_19:\n        \"The 'Promise' if already set for us! However, we can't use the Promise blocks as is. I'll need to use the Promise blocks at the right timing to get the battery.\",\n    maze_content_20:\n        \"Excellent! You've done great so far! After the final battery, I won't need to charge any more. So help me get the last battery using the Promise so I can live forever free!\",\n    maze_content_21:\n        '안녕? 나는 엔트리 봇이야. 지금 많은 친구들이 내 도움을 필요로 하고 있어. 반복하기를 이용해서 친구들을 도울수 있게 데려다 줘!',\n    maze_content_22: '고마워! 이번에는 벌집을 뛰어넘어서 친구를 구하러 갈 수 있게 도와줘!',\n    maze_content_23:\n        '좋아! 이번에는 친구 로봇한테 갈 때까지 반복하기를 이용해서 친구를 도울 수 있게 도와줘!',\n    maze_content_24:\n        '안녕! 나는 엔트리 봇이야. 지금 나는 너무 오래 움직여서 배터리를 채워야 해. 약속 불러오기를 써서 배터리를 채울 수 있도록 도와줘!',\n    maze_content_25: '멋져! 이번에는 여러 약속을 불러와서 배터리가 있는 곳까지 가보자!',\n    maze_content_26:\n        '좋아! 이제 약속할 블록을 나한테 가르쳐줘! 약속하기 블록 안에 자주 쓰일 블록을 넣으면 돼!',\n    maze_content_27:\n        '지금은 미리 약속이 정해져 있어. 그런데, 약속을 쓰기위해서는 내가 갈 방향을 보고 약속을 사용해야해. 도와줄거지?',\n    maze_content_28: '드디어 마지막이야! 약속을 이용하여 마지막 배터리를 얻을 수 있게 도와줘!',\n    ai_content_1:\n        \"Hi! I'm Entrybot. I just completed the space exploration mission and I need to return to Earth but it's not easy because of the asteroids. Could you help me return home? I have radars on top, front and back of the spaceship to detect how far an obstacle exists. It'll help you make smart decisions.\",\n    ai_content_2:\n        \"Thank you! I was able to avoid the asteroids without trouble. There are more asteroids this time. Let's try avoiding them!\",\n    ai_content_3:\n        \"Great! I was able to safely avoid the asteroids! There are more asteroids now! Don't worry though! I have the 'repeat' block. Place blocks in the 'repeat' block so we can get to the destination!\",\n    ai_content_4:\n        \"Excellent! It's so much more easier to avoid the asteroids using the repeat blocks! However, it's tiring driving the spaceship at all times! I can use the radar to sense what's coming. Help avoid the asteroids using the radar.\",\n    ai_content_5:\n        \"Nice! I'm so glad we've come this far. The radar will tell how far an object exists. Let's use the radar to avoid the asteroids! Move forward until we come close to an asteroid then avoid!\",\n    ai_content_6:\n        \"Great job! You're using radar to avoid tha asteroids. Use multiple radars to avoid the asteroids.\",\n    ai_content_7:\n        \"We're getting close to Earth! I want to go in a safer path if possible. It must be safer to move farther from the asteroids, right? Compare the distance to the obstacle using the radar on the top and bottom of the spaceship to move to a safer direction.\",\n    ai_content_8:\n        \"Excellent! We're safely cruising through space. Oh! What is that? That's looks like my special energy! Let's collect the special energy on our way!\",\n    ai_content_9:\n        \"Very good! We're almost there. The path is filled with asteroid. But don’t worry! We can get rid of the obstacles using the special item.\",\n    ai_content_10:\n        \"Good! I can see Earth! But now it's impossible to see the asteroids ahead! I'm not worried though. We can avoid the asteroids with more caution. Let's go home!\",\n    maze_hints_title_1: 'How to start',\n    maze_hints_content_1: 'How do I move Entrybot?',\n    maze_hints_detail_1:\n        \"1. Drag the block you want to use and place it under 'When Run'<br>2. Once finished, click 'Run'<br>3. I will follow the block instructions step by step, reading them from top to bottom\",\n    maze_hints_title_2: 'Jumping over obstacles',\n    maze_hints_content_2: 'What do I do when I come across an obstacle?',\n    maze_hints_detail_2:\n        \"On your pathway, you might come across obstacles.<br>Use 'jump over' block to jump over the obstacle. \",\n    maze_hints_title_3: 'Repeat block(1)',\n    maze_hints_content_3: 'How do I use repeat (3) times block?',\n    maze_hints_detail_3:\n        \"If you want to repeat an action multiple times, use 'repeat ~times' block. <br>Place the blocks you want to repeat within the 'repeat ~times' block and input how many times to repeat.\",\n    maze_hints_title_4: 'Repeat block(2)',\n    maze_hints_content_4: \"How do I use 'repeat until ~' block?\",\n    maze_hints_detail_4:\n        \"Use 'repeat until~do' block to set until when an action should be performed. <br>Place the blocks you want to repeat within 'repeat until~' block.<br>Then once met with {image}, repeat will stop.\",\n    maze_hints_title_5: 'If block',\n    maze_hints_content_5: \"How do I use 'if~' block?\",\n    maze_hints_detail_5:\n        \"Using 'If {image}' block, you can designate what action should follow when met with {image}.<br>Blocks within the 'If {image}' will only execute when met with {image}.\",\n    maze_hints_title_6: 'Repeat block(3)',\n    maze_hints_content_6: \"How does 'Until met with all ~' block work?\",\n    maze_hints_detail_6:\n        \"Repeat blocks within 'Until met with all ~' block until met with all {tile}.<br> Once met with all {tile} repeat will stop.\",\n    maze_hints_title_7: 'Special Hint',\n    maze_hints_content_7: \"It's too difficult. Help!\",\n    maze_hints_detail_7:\n        'Look at the path that I should travel. See the 4 small squares?<br>First create blocks that will take me around the square and repeat.',\n    maze_hints_title_8: 'Function',\n    maze_hints_content_8: \"What is 'Functions/ Call Functions'? How do I use them?\",\n    maze_hints_detail_8:\n        \"Put the most often used sets of blocks under 'Function'. <br>Once you create functions, use 'Call Function' to use it as often as needed.\",\n    ai_hints_title_1_1: 'Goal of the game',\n    ai_hints_content_1_1: 'Avoid asteroids and help me get to Earth',\n    ai_hints_detail_1_1: 'Avoid asteroids and help me get to Earth',\n    ai_hints_title_1_2: 'Instructions',\n    ai_hints_content_1_2: 'How do I begin?',\n    ai_hints_detail_1_2:\n        \"1. Drag out blocks from the block box and connect is with the 'when run' block<br>2. Once finished assembling blocks, click 'Run'<br>3. I'll move according to your block instructions.\",\n    ai_hints_title_1_3: 'To move',\n    ai_hints_content_1_3: 'How do I move the entrybot?',\n    ai_hints_detail_1_3:\n        'I can move up, forward or below.<br>When creating instructions, make sure I avoid the asteroids.<br>If you send me out of the screen, I can be lost in space forever! So be careful.',\n    ai_hints_title_2_1: 'Goal of the game',\n    ai_hints_content_2_1: 'Use repeat blocks to avoid the asteroids.',\n    ai_hints_detail_2_1: 'Use repeat blocks to avoid the asteroids.',\n    ai_hints_title_2_2: 'Repeat block',\n    ai_hints_content_2_2: 'What is a repeat block?',\n    ai_hints_detail_2_2:\n        \"Geez! It's a long way home so putting blocks together one by one is too tiresome. Let's try using the repeat block.<br>Once you group the blocks under the repeat block, you can shorten the length of the blocks!\",\n    ai_hints_content_3_1: \"Help me avoid the asteroids using the 'if' block\",\n    ai_hints_title_3_2: 'if block(1)',\n    ai_hints_content_3_2: \"How does 'if ~' block work? \",\n    ai_hints_detail_3_2:\n        \"Using 'if~ in front/ else' block can help me check if there are asteroids in front of me and help me avoid them.<br>If there's an asteroid in front of me, then blocks under 'if' will execute or if there isn't an asteroid, the blocks under 'else' will execute.<br>Tell me which way to go depending on whether there's an asteroid to avoid or not.\",\n    ai_hints_content_4_1: 'Learn to use the radar to avoid the asteroids.',\n    ai_hints_detail_4_1: 'Learn to use the radar to avoid the asteroids.',\n    ai_hints_title_4_2: 'radar(1)',\n    ai_hints_content_4_2: 'What is a radar and how can I use it?',\n    ai_hints_detail_4_2:\n        \"Radar tells me how far an object exists from where I am located. <br>If there is an object in front of me, the front radar will show '1'.<br>Also, radar can become a powerful tool when used with 'if &lt;true&gt;/else' block.<br>For example, when the distance to an object in front of me shows value greater than 1, then I am able to move forward safely.<br> However, if not, then I can go above or under to avoid it.\",\n    ai_hints_title_4_3: 'if block(2)',\n    ai_hints_content_4_3: \"How do I use 'if <true>' block?\",\n    ai_hints_detail_4_3:\n        \"if &lt;true&gt; block/ else' block executes blocks under 'if' when condition is met and executes blocks under 'else' when condition is not met.<br>Think about how you want to move at different situations and create a condition within &lt;true&gt; block.<br>Remember that when condition is met and blocks under 'if' are executed, then the blocks under 'else' will be ignored.\",\n    ai_hints_content_5_1: 'Use the radar to help me avoid the asteroids.',\n    ai_hints_detail_5_1: 'Use the radar to help me avoid the asteroids.',\n    ai_hints_title_5_2: 'if block(3)',\n    ai_hints_content_5_2: 'How does nested if blocks work?',\n    ai_hints_detail_5_2:\n        \"I can nest 'if ~/else' block within 'if ~/else' block. This will help me make smart decisions in various situations.<br>For example, I can act according to whether an asteroid is in my path or not, then when I'm met with and asteroid, I can decide whether to go under or above.\",\n    ai_hints_title_6_1: 'Radar(2)',\n    ai_hints_content_6_1: 'How do I compare the values given by radar above and radar below?',\n    ai_hints_detail_6_1:\n        \"([above]radar) block shows distance to an object above.<br>You can use this block to check which asteroid above or below exist further away.<br>When deciding which way to avoid the asteroid, it'll be a smarter move to go in the direction where the asteroid is further away.\",\n    ai_hints_content_7_1: 'Use the item to avoid the asteroids.',\n    ai_hints_detail_7_1: 'Use the item to avoid the asteroids.',\n    ai_hints_title_7_2: 'Checking object name',\n    ai_hints_content_7_2: 'What can I do by checking the object name in front of me?',\n    ai_hints_detail_7_2:\n        \"To gain a special item, you need to check where the item is located.<br>Use 'object [above] is [item]' block.<br>By using this block, you can figure out where the item is located and move towards it.\",\n    ai_hints_content_8_1: 'Use the item to help me avoid the asteroids.',\n    ai_hints_detail_8_1: 'Use the item to help me avoid the asteroids.',\n    ai_hints_title_8_2: 'Item',\n    ai_hints_content_8_2: 'How do I gain special item and use it?',\n    ai_hints_detail_8_2:\n        \"Even though you succeed in avoiding the asteroids, when the pathway is lined with asteroids, there is no way to avoid them. In this case, use the 'use item' block.<br>It will get rid of all blocks in front.<br>However, you can only use this block when you've gained the item by passing through the item.\",\n    ai_hints_content_9_1: 'Use all your skills and knowledge to go as far as you can.',\n    ai_hints_detail_9_1: 'Use all your skills and knowledge to go as far as you can.',\n    ai_hints_title_9_2: 'and',\n    ai_hints_content_9_2: \"How do I use the 'and' block?\",\n    ai_hints_detail_9_2:\n        \"and' block can fit in many conditions. When all conditions in the 'and' block is met, then the blocks will be executed. If one of them is false, the whole 'and' statement will be false and the blocks will not be executed.\",\n    maze_text_goal_1: 'Use move();  command to move me to the part box!',\n    maze_text_goal_2: 'Use jump();  command to avoid obstacles.',\n    maze_text_goal_3: 'Use left(); right(); command to take me to my parts.',\n    maze_text_goal_4: 'Use various commands to take me to my parts.',\n    maze_text_goal_5: 'Move me so I can collect both of my part boxes.',\n    maze_text_goal_6: 'Move me so I can collect both of my part boxes.',\n    maze_text_goal_7: 'Use for command to take me to my friend!',\n    maze_text_goal_8: 'Use for command and avoid obstacles to take me to my friend!',\n    maze_text_goal_9: 'Use while command to take me to my friend.',\n    maze_text_goal_10: 'Use if and while commands to take me to all my friends.',\n    maze_text_goal_11: 'Use if and while commands to take me to all my friends.',\n    maze_text_goal_12: 'Use if and while commands to take me to all my friends.',\n    maze_text_goal_13: 'Call function to take me to my battery',\n    maze_text_goal_14: 'Call function to take me to my battery',\n    maze_text_goal_15:\n        'Insert commands within function. Then call the function to take me to my battery',\n    maze_text_goal_16:\n        'Insert commands under a function. Then call the function to move me to the battery!',\n    maze_text_goal_17:\n        'Insert commands under a function. Then call the function to move me to the battery!',\n    maze_text_goal_18:\n        'Insert commands under a function. Then call the function to move me to the battery!',\n    maze_text_goal_19:\n        'Insert commands under a function. Then call the function to move me to the battery!',\n    maze_text_goal_20:\n        'Call the function and mix it with other commands and take me to my battery.',\n    maze_attack_range: 'Attack range',\n    maze_attack: 'Attack',\n    maze_attack_both_sides: 'Attack both sides',\n    above_radar: 'above radar',\n    above_radar_text_mode: 'radar_up',\n    bottom_radar: 'bottom radar',\n    bottom_radar_text_mode: 'radar_down',\n    front_radar: 'front radar',\n    front_radar_text_mode: 'radar_right',\n    above_object: 'object above',\n    above_object_text_mode: 'object_up',\n    front_object: 'object in front',\n    front_object_text_mode: 'object_right',\n    below_object: 'object below',\n    below_object_text_mode: 'object_down',\n    destination: 'destination',\n    asteroids: 'asteroids',\n    item: 'item',\n    wall: 'wall',\n    destination_text_mode: 'destination',\n    asteroids_text_mode: 'stone',\n    item_text_mode: 'item',\n    wall_text_mode: 'wall',\n    buy_now: 'Buy now',\n    goals: 'Goal',\n    instructions: 'Instructions',\n    object_info: 'Object info',\n    entry_basic_mission: 'Entry basic mission',\n    entry_application_mission: 'Entry application mission',\n    maze_move_forward: 'move one forward',\n    maze_when_run: 'when Run',\n    maze_turn_left: 'turn left',\n    maze_turn_right: 'turn right',\n    maze_repeat_times_1: 'repeat',\n    maze_repeat_times_2: 'times',\n    maze_repeat_until_1: 'repeat until',\n    maze_repeat_until_2: '',\n    maze_call_function: 'call function',\n    maze_function: 'function',\n    maze_repeat_until_all_1: 'repeat until all of',\n    maze_repeat_until_all_2: '',\n    command_guide: 'Command guide',\n    ai_success_msg_1: \"Thanks to you I've safely arrived home!\",\n    ai_success_msg_2: 'Phew! I was able to travel ',\n    ai_success_msg_3:\n        'distance  enough to send a rescue signal to Earth! The rescue crew is on its way! Thank you!',\n    ai_success_msg_4: 'Great! You succeeded using ',\n    ai_cause_msg_1: 'Oh no. Tell me which way to go.',\n    ai_cause_msg_2: \"Yikes! That was close! Let's try again.\",\n    ai_cause_msg_3: \"Yikes! I might get lost in space if I go off the path. Let's try again.\",\n    ai_cause_msg_4: \"It's too complicated. Try this block to move.\",\n    ai_move_forward: 'move forward',\n    ai_move_above: 'go above',\n    ai_move_under: 'go under',\n    ai_repeat_until_dest: 'repeat until destination',\n    ai_if_front_1: 'if',\n    ai_if_front_2: 'in front',\n    ai_else: 'else',\n    ai_if_1: 'if',\n    ai_if_2: '',\n    ai_use_item: 'use item',\n    ai_radar: 'radar',\n    ai_above: 'above',\n    ai_front: 'front',\n    ai_under: 'under',\n    ai_object_is_1: 'is',\n    ai_object_is_2: 'object',\n    challengeMission: 'back',\n    nextMission: 'next',\n    withTeacher: 'Advisory teachers',\n    host: 'Host',\n    support: 'Support',\n    subjectivity: 'Subjectivity',\n    learnMore: 'Learn more ',\n    ai_object_is_3: '?',\n    stage_is_not_available:\n        \"The stage isn't available yet. Please enter the stages in the given order.\",\n    progress_not_saved: 'Your progress will not be saved.',\n    want_refresh: 'Do you still want to refresh the page?',\n    monthly_entry_grade: 'Elementary 3rd - Middle school 3rd grade',\n    monthly_entry_contents:\n        'Learn to program with Monthly Entry. This monthly digest provides project tutorials, tips and tricks and fun comics. ',\n    monthly_entry_etc1:\n        \"*The Monthly Entry project templates are provided in the main page's recommended course\",\n    monthly_entry_etc2: '* Monthly Entry is published during school semesters only',\n    group_make_lecture_1: 'There are no lessons to show.',\n    group_make_lecture_2: ' Create lessons for your class from ',\n    group_make_lecture_3: \"'Create > Create lessons'\",\n    group_make_lecture_4: 'Create a lessons',\n    group_add_lecture_1: 'Favorite Lesson does not exist.',\n    group_add_lecture_2: \"'학습하기>오픈 강의> 강의'에서 우리반 학습내용에\",\n    group_add_lecture_3: '추가하고 싶은 강의를 관심강의로 등록해 주세요.',\n    group_add_lecture_4: 'See Lesson',\n    group_make_course_1: 'My courseware is not exist.',\n    group_make_course_2: 'Create courseware for your class from',\n    group_make_course_3: \"'Create > Create lessons > Create Courseware'\",\n    group_make_course_4: 'Create courseware',\n    group_add_course_1: 'Favorite Courseware does not exist.',\n    group_add_course_2: 'Favorite lessons you want to add as course assignment from',\n    group_add_course_3: \"'Learn > Open Lessons > Courseware\",\n    group_add_course_4: 'Browse courseware',\n    hw_main_title: 'Download Program',\n    datablock_contest_title: 'Data Analysis Block',\n    datablock_content_head: 'Process and Represent the Data',\n    datablock_content_body1: 'Find meaning by charting various data in your life',\n    datablock_content_body2: 'and solve real-life problems with it!',\n    campaign_contest_title: \"Let's make a beautiful internet world\",\n    campaign_content_head: 'Entry Project Contest',\n    campaign_content_body1: \"Create an originative project about 'internet ethics'\",\n    campaign_content_body2: 'and apply for the contest!',\n    campaign_content_button: 'View details',\n    code_management_1: 'Entry campaign #1 How to manage code',\n    code_management_2: 'My Storage and Memo',\n    code_management_3: 'Code management secret using my storage and memo!',\n    code_management_4: 'Learn how to make your project better and share it easily.',\n    code_management_5: 'View Campaigns',\n    shcoolbook_study_1: 'Learn the contents of the textbook in entry.',\n    shcoolbook_study_2: 'Learning Textbook',\n    shcoolbook_study_3: 'Teachers can teach in the classroom',\n    shcoolbook_study_4: 'and students can review at home!',\n    shcoolbook_study_5: 'Learn now',\n    main_learn_1: 'If you are new to Entry',\n    main_learn_2: 'Learn about Entry',\n    main_learn_3: 'Watch the video to learn about the various functions of Entry,',\n    main_learn_4: 'create and share your project!',\n    main_learn_5: 'Watch the video',\n    hw_desc_wrapper: 'Install the Upgraded \\nEntry Hardware Connection Program\\nand Offline Editor',\n    hw_downolad_link: 'Download Hardware Connection Program',\n    save_as_image_all: 'Save code as image',\n    save_as_image: 'Save as image',\n    maze_perfect_success: 'Awesome! That is perfect!',\n    maze_success_many_block_1: '좋아',\n    maze_fail_obstacle_remain: 'Get rid of all obstacles to keep your friends from getting hurt.',\n    maze_fail_item_remain: 'Collect all the Minerals to save Princess Sally.',\n    maple_fail_item_remain:\n        \"I can't use my strength because I didn’t take all the food.<br />Help me to take all the food.\",\n    maze_fail_not_found_destory_object: \"Don't waste your power on an empty space!\",\n    maze_fail_not_found_destory_monster: \"Don't attack an empty space!\",\n    maple_fail_not_found_destory_monster:\n        'You should use the attack blocks only when there are monsters!',\n    maze_fail_more_move: 'You have to move to the destination a little bit more!',\n    maze_fail_wall_crash: \"Ow! You can't go there!\",\n    maze_fail_contact_brick: 'Ouch... you ran into something!',\n    maze_fail_contact_iron1: 'Ow! I hit an obstacle',\n    maze_fail_contact_iron2:\n        'Ow! I was hurt because an obstacle fell on me. Move before an obstacle falls down.',\n    maze_fail_fall_hole: 'I fell into a trap...',\n    maze_fail_hit_unit:\n        '몬스터에게 당해버렸어! 위험한 몬스터를 물리치기 위해 하트 날리기 블록을 사용해줘!',\n    maze_fail_hit_unit2: 'Ow, I was attacked by a monster! You have to attack from two cells away!',\n    maze_fail_hit_unit_by_mushroom:\n        \"The Orange Mushroom got me!<br />Use the Attack <img src='/img/assets/maze/icon/mushroom.png' /> block to defeat the bad monsters!\",\n    maze_fail_hit_unit_by_lupin:\n        \"I got hit by Lupin! <br />Use the Attack <img src='/img/assets/maze/icon/lupin.png' /> block two spaces away to defeat the bad monster!\",\n    maze_fail_elnath_fail:\n        'Oww! A bad monster attacked me.<br />Defeat the bad monsters to keep them from reaching me!',\n    maze_fail_pepe: '',\n    maze_fail_yeti:\n        \"That monster is so strong that you can't defeat it with the Attack <img width='24px' src='/img/assets/week/blocks/yeti.png'/> block.<br />Let's use the Attack <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> block.\",\n    maze_fail_peti:\n        \"If you use the Attack <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> block to attack that monster, you can't defeat the strong monsters <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> when they spawn.<br />Let's use the Attack <img width='24px' src='/img/assets/week/blocks/yeti.png'/> block.\",\n    maze_fail_both_side:\n        'You should only use the Attack on both sides if there are monsters on both sides! ',\n    maze_wrong_attack_obstacle:\n        \"You can't use the Attack <img src='/img/assets/maze/icon/lupin.png' /> block here.<br />Let's use the Attack <img src='/img/assets/maze/icon/mushroom.png' /> block for Orange Mushrooms.\",\n    maze_fail_contact_spider: \"You're caught on a cobweb and can't move...\",\n    maze_success_perfect: 'Awesome! That is perfect!',\n    maze_success_block_excess:\n        'Great! You succeeded using %1 blocks! <br> But you can actually get there by only using %2 blocks! How about another go at it?',\n    maze_success_not_essential:\n        'Great! You succeeded using %1 blocks! <br>But using this block makes it easier to solve. How about another go at it?',\n    maze_success_final_perfect_basic:\n        'Okay, we found where Princess Sally is! Now you can save Princess Sally!',\n    maze_success_final_block_excess_basic:\n        'Great! We found where Princess Sally is! Now you can save Princess Sally! You used %1 blocks, but you can actually succeed by only using %2 blocks! Wanna try again?',\n    maze_success_final_perfect_advanced:\n        \"You've reached the place where Princess Sally is! Now defeat the villain Mephisto and save Sally!\",\n    maze_success_final_block_excess_advanced:\n        \"You've reached the place where Princess Sally is! Now defeat the villain Mephisto and save Sally! You used %1 blocks, but you can actually succeed by only using %2 blocks! Wanna try again?\",\n    maze_success_final_distance:\n        'Great! We finally saved Princess Sally safe and sound. Thank you so much for helping!<br/> You moved %1 cells. Wanna try again and aim for 60 cells?',\n    maze_success_final_perfect_ai:\n        'There you go! We finally saved Princess Sally safe and sound. Thank you so much for helping!',\n    maple_success_perfect: 'Great! That was perfect!',\n    maple_success_block_excess:\n        'Great! You’ve succeeded using %1 blocks!<br />But there is a way to succeed with %2 blocks. Why don’t you try again?',\n    maple_success_not_essential:\n        \"Great! You’ve succeeded using %1 blocks!<br />But using this block will make it easier. Why don't you try again?\",\n    maple_success_final_perfect_henesys: 'Awesome! You’ve completed the Henesys Adventure.',\n    maple_success_final_perfect_excess_henesys:\n        'Awesome! You’ve completed the Henesys Adventure.<br />But there is a way to succeed with %2 blocks. Would you like to try again?',\n    maple_success_final_not_essential_henesys:\n        'Awesome! You’ve completed the Henesys Adventure.<br />But using this block will make it easier. Would you like to try again?',\n    maple_success_final_perfect_ellinia:\n        \"Wow! That was a really fun adventure!<br />You're going to come back for another adventure, right?\",\n    maple_success_final_perfect_excess_ellinia:\n        'Wow! That was a really fun adventure!<br />But there is a way to succeed with %2 blocks. Would you like to try again?',\n    maple_success_final_not_essential_ellinia:\n        'Wow! That was a really fun adventure!<br />But using this block will make it easier. Would you like to try again?',\n    maple_fail_fall_hole: \"Oww! You’ve fallen down!<br/>Let's skip using the Jump block.\",\n    maple_fail_ladder_fall_hole:\n        \"Oww! You’ve fallen down!<br />Let's go the other way using the Climb ladder block.\",\n    maple_fail_more_move: 'To succeed, we have to move a little bit further to the destination!',\n    maple_fail_not_found_ladder:\n        \"Oh, there's no ladder to climb here.<br />You should only use the Climb ladder block where there is a ladder.\",\n    maple_fail_not_found_meat:\n        \"Oh, there's no food to take here.<br />You should only use Take food block where there is food.\",\n    maple_cert_input_title: 'What name do you want in the certificate?',\n    maze_distance1: 'distance 1',\n    maze_distance2: 'distance 2',\n    maze_distance3: 'distance 3',\n    ev3: 'EV3',\n    roborobo_roduino: 'Roduino',\n    roborobo_schoolkit: 'School Kit',\n    smartboard: 'Sciencebox Codingboard',\n    smartboardbt: 'Sciencebox Codingboard(Bluetooth)',\n    codestar: 'Codestar',\n    cobl: 'Cobl',\n    cobl_bt: 'Cobl BT',\n    block_coding: 'Block Coding',\n    python_coding: 'Entry Python',\n    dadublock: 'DaduBlock',\n    dadublock_car: 'DaduBlock Car',\n    blacksmith: 'Blacksmith Board',\n    course_submit_homework: 'Submit',\n    course_done_study: 'Complete',\n    course_show_list: 'List',\n    modi: 'MODI',\n    chocopi: 'ChocoPi',\n    coconut: 'coconut',\n    jdkit: 'JDKit',\n    practical_course: 'Textbook',\n    entry_user_policy: 'Entry usage policy',\n    entry_scholarship_title: 'Entry scholarly data',\n    entry_scholarship_content:\n        'Entry collaborates with researchers to strengthen learning effectiveness. Check out our data.',\n    entry_scholarship_content_sub:\n        '*We provide data which is saved in the form of a sequence of processes by users participating in the Online coding party to assist in study and analysis.',\n    entry_scholarship_download: 'Data download',\n    codingparty_2016_title: '2016 Online coding party',\n    codingparty_2016_content:\n        \"We provide user's active log, who played a coding mission, with whether he/she has succeeded or not, and user age, gender\",\n    codingparty_2017_title: '2017 Online coding party',\n    scholarship_go_mission: 'Coding mission',\n    scholarship_guide: 'Guide',\n    scholarship_see_guide: 'Guide',\n    scholarship_guide_desc: \"It's a guide for how to read and use data.\",\n    scholarship_example: 'Example',\n    scholarship_example_desc: 'Check out our paper by using scholarly data.',\n    scholarship_see_example: 'Download',\n    altino: 'Altino',\n    private_project: 'This is a private project',\n    learn_programming_entry_mission: 'Solving missions with EntryBot',\n    learn_programming_line_mission: 'Saving Sally with LINE Rangers',\n    learn_programming_choseok: 'Making a game with Cho Seok, author of \"The Sound of Your Heart\"',\n    learn_programming_maple: 'Going to the Maple World with \"PINK BEAN\"',\n    learn_programming_level_novice: 'easy',\n    learn_programming_level_inter: 'normal',\n    learn_programming_level_advanced: 'hard',\n    line_look_for: 'Finding Sally',\n    line_rangers_title_string: 'Learning: Line Rangers',\n    online_codingparty_certificate_string: 'Online coding party',\n    online_codingparty_line_title_string: 'Line Rangers',\n    line_look_for_desc_1:\n        'Combine the power of the LINE Rangers and defeat the powerful villain Mephisto and save Sally!',\n    line_save: 'Saving Sally',\n    line_save_desc_1:\n        \"Sally is trapped at Mephisto's base. Help the LINE Rangers get to Sally by avoiding obstacles!\",\n    line_escape: 'Escaping with Sally',\n    line_escape_desc_1:\n        'Help Sally and LINE Rangers escape safely from the exploding Mephisto base!',\n    solve_choseok: 'rock-paper-scissors',\n    solve_choseok_desc_1: 'Help Cho Seok create a rock-paper-scissors game!',\n    solve_henesys: 'HENESYS',\n    solve_ellinia: 'ELLINIA',\n    solve_elnath: 'ELNATH',\n    solve_henesys_desc_1: 'Venture into the town, and help PINK BEAN to have enough food!',\n    solve_ellinia_desc_1:\n        'Venture into the forest, and fight against the bad monsters to save the good monsters!',\n    solve_elnath_desc_1:\n        'Passing through the snow mountain occupied by bad monsters, go find another portal to start a new adventure!',\n    save_modified_shape: 'You have unsaved changes.\\nDo you want to save?',\n    save_modified_table: 'Do you want to save the modified table?',\n    attach_file: 'File',\n    enter_discuss_title: 'Please enter the title(in 40 characters or less)',\n    enter_discuss_title_alert: 'Please enter the title',\n    discuss_upload_warn: 'You can only upload less than 10MB in file size',\n    discuss_list: 'list',\n    discuss_write_notice: 'Select this post as a notice and show it first.',\n    discuss_write_notice_open: 'Select this post as a notice and show it first.',\n    search_전체: 'All',\n    search_게임: 'Game',\n    search_애니메이션: 'Animation',\n    search_미디어아트: 'Media Art',\n    search_피지컬: 'Physical',\n    search_기타: 'ETC',\n    discuss_write_textarea_placeholer:\n        \"Entry community is a space we make together.\\nLet's make a fun community with consideration for each other.\",\n    discuss_write_textarea_placeholer_qna:\n        \"This community is for Q&A.\\nLet's make a fun community with consideration for each other!\",\n    discuss_write_textarea_placeholer_tips:\n        \"This community is for Tips&Tricks.\\nLet's make a fun community with consideration for each other!\",\n    discuss_write_textarea_placeholer_free:\n        \"This community is for Discussion.\\nLet's make a fun community with consideration for each other!\",\n    discuss_write_textarea_placeholer_report:\n        \"This community is for Suggestions.\\nLet's make a fun community with consideration for each other!\",\n    discuss_write_textarea_placeholer_contest2019:\n        '※ 아래 양식으로 작성하여 제출해주세요.\\n\\n1. 학년 (예: 초등학교 5학년)\\n\\n2. 작품 URL (‘공유하기 > 작품 공유하기’에 작품을 공유한 다음, 작품 URL을 복사하여 적어주세요.)\\n\\n3. 작품 설명\\n\\n※ 공모전 수상자에게는 이메일이 발송될 예정입니다.\\n엔트리의 ‘내 정보 수정‘에 이메일 정보를 꼭 입력해주세요!',\n    maze_road: 'road',\n    account_deletion: 'Account deletion',\n    bug_report_too_many_request: 'Your report is being sent. Please try again later.',\n    pinkbean_index_title: 'Let’s head to the exciting Maple World with Pink Bean!',\n    pinkbean_index_content:\n        'Pink Bean, who couldn’t stand boredom, has ventured into Maple World.<br />Explore the exciting Maple World with Pink Bean and fill the adventure journal.<br />You can learn the software while passing through each step, and you can get a certificate after you complete the mission.',\n    rangers_index_title: 'Saving Sally with LINE Rangers!',\n    rangers_index_content:\n        'LINE Rangers are combined to defeat the powerful villain Mephisto and save Sally.<br />Be the hero by avoiding obstacles and saving Sally through the principle of software.<br />You can learn about software passing through each steps and get the licence<br />after finishing the mission.',\n    rangers_replay_button: 'Replay',\n    rangers_start_button: 'Start',\n    lms_curriculum_intro: '',\n    lms_curriculum_goal: '',\n    lms_curriculum_prepare: '',\n    lms_curriculum_study: '',\n    lms_curriculum_summary: '',\n    lms_curriculum_quiz: '',\n    lms_curriculum_now_stage: '',\n    bug_report_title: 'Bug Report',\n    bug_report_content:\n        'Please tell us about errors or good suggestions that you find when you use Entry.',\n    object_import_syntax_error:\n        'Since the object has syntax error blocks, it cannot be loaded. Please convert into block mode to load the object.',\n    choseok_top_wrapper_panel_title: '조석과 함께 가위바위보 게임을 만들어보세요!',\n    choseok_top_wrapper_panel_des:\n        '마음의 소리 웹툰이 코딩파티 미션으로 탄생했습니다. <br/>만화속 조석이 (가위바위보 게임)을 만들어가는 과정에 참여하여 미션에<br/>도전해 보세요.<br/>각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 모두 마치면</br>인증서와 나만의 게임을 얻을 수 있습니다.<br/>',\n    choseok_mission_statement1: '조석을 움직여보자',\n    choseok_mission_statement2: '가위바위보를 시작해보자',\n    choseok_mission_statement3: '가위바위보 승부를 가려보자',\n    choseok_mission_statement4: '가위바위보 게임을 완성해보자',\n    choseok_mission_statement5: '자유롭게 만들어보자',\n    choseok_mission_statement_top1: '미션 1 : 조석을 움직이기',\n    choseok_mission_statement_top2: '미션 2 : 가위바위보를 시작하기',\n    choseok_mission_statement_top3: '미션 3 : 가위바위보 승패 만들기',\n    choseok_mission_statement_top4: '미션 4 : 가위바위보 결과 보여주기',\n    choseok_mission_statement_top5: '미션 5 : 자유롭게 만들어보기',\n    advisory_title: 'Entry Advisory Group',\n    advisory_sub_title:\n        'This is an advisory group including teachers and students who make Entry together.',\n    data_table_column: 'column',\n    data_table_row: 'row',\n    data_table_provider: 'Source',\n    data_table_modifidate: 'modify',\n    draw_new_table_ques_1: 'You can enter data and save to table.',\n    draw_new_table_ques_2: 'Do you want to move to enter data?',\n    file_upload: 'Upload file',\n    no_marked_project: 'There are no projects to show.',\n    temp_save_project_study: 'Temporary save',\n    in_progress2: 'Studying',\n    file_upload_table_title: 'Add new table',\n    file_upload_table_sub_title: 'You can create a table by entering data directly.',\n    file_upload_warn_desc_table_1:\n        'Violent and brutal data, Sacred body exposure data, Offensive or disgusting data,',\n    file_upload_warn_desc_table_2: 'Data of copyright prohibited from unauthorized use',\n    table_drag_upload_title: 'Drag-and-drop or click to upload a file',\n    table_drag_upload_desc: 'You can drag and drop CSV, XLS(X) files here or click to upload them.',\n    upload_select_file: 'Select file',\n    file_upload_add: 'Add',\n    file_upload_max_size_image: 'You can only upload less than 5MB in file size.',\n    realtime: 'Realtime',\n    cloud: 'Cloud',\n};\nLang.Msgs = {\n    microbit_led_erase_all: 'Reset',\n    loading_plz_wait: 'Now Loading. Please Wait.',\n    ai_utilize_audio_listening: 'Listening',\n    ai_utilize_audio_progress: 'Recognizing',\n    upload_error_title: 'File rejected',\n    upload_error_content: 'Files not complying with the entry usage policy are excluded',\n    monthly_intro_0:\n        'Monthly entry is an SW training magazine designed to help teachers who are unfamiliar with SW.',\n    monthly_intro_1: 'Meet the Learning contents with fun learning cartoon!',\n    monthly_title_0: 'Taking a dog walk / Drawing diagram',\n    monthly_title_1: 'Create a video / Music player',\n    monthly_title_2: 'South Korea map puzzle / Cosmos animation',\n    monthly_title_3: 'Following fishes / Planets',\n    monthly_title_4: 'Harvesting potatoes / Strawberry milk',\n    monthly_description_0:\n        \"Let's make the dog that moved by your keyboard, and paint drawing project using signal and coordinate.\",\n    monthly_description_1: \"Let's make the photo-movie project and music player using variable.\",\n    monthly_description_2:\n        \"Let's make the puzzle game that made of 'while' statement, and animation project using clone and random.\",\n    monthly_description_3:\n        \"Let's make fish-art and solar system using loop, math calculation blocks.\",\n    monthly_description_4:\n        \"Let's make the potato-digging and strawberry milk project using signal, variable and math calculation blocks.\",\n    save_canvas_alert: 'Currently saving.',\n    feedback_too_many_post: 'Message sending. Please try after 10 seconds.',\n    feedback_duplicated: 'It is already reported.',\n    usable_object: 'Usable Object',\n    shared_varaible: 'Shared Variable',\n    invalid_url: 'Video URL is invalid.',\n    auth_only: 'Authenticated users only',\n    runtime_error: 'Runtime Error',\n    to_be_continue: 'Still not working',\n    warn: 'Warning',\n    error_occured:\n        \"Oops, something went wrong. Why don't you try again? If you see this more than once, please let us know by Proposal board!\",\n    error_forbidden:\n        'Can not save because you are not signed in.\\nPlease make sure if you haven’t signed out in another tab.\\nIf you still can not save after sign in, please leave a message via ‘Suggestion’.',\n    list_can_not_space: \"List's name can't be space\",\n    sign_can_not_space: \"Sign's name can't be space\",\n    variable_can_not_space: \"Variable's name can't be space\",\n    training_top_title: 'Programs',\n    training_top_desc: 'Introducing Professional Development Programs',\n    training_main_title01: 'Instructors for your Professional Development Seminar',\n    training_target01: 'For l Teachers',\n    training_sub_title01: '“Give a Boost to your Classroom”',\n    training_desc01:\n        'Are you looking for instructors to train your teachers?\\nWe will match you with excellent instructors with knowledge and experience.',\n    training_etc_ment01: '* Seminar are hosted and paid for by the requesting schools',\n    training_main_title02: 'Teacher Development Program for Lead Schools',\n    training_target02: 'For l Lead and Research Schools',\n    training_sub_title02: '“Go, Share, and Connect”',\n    training_desc02:\n        'We randomly select schools from the Lead and Research schools and provide Development Seminars for free.\\nSeminars are taught by Go-to-Teacher Program teachers.',\n    training_etc_ment02: '',\n    training_main_title03: 'Experienced Instructors for Parent and Student seminars',\n    training_target03: 'For l Parents, Students',\n    training_sub_title03: '“Time to Explore Software Education”',\n    training_desc03:\n        'Need instructors to introduce coding to parents and students?\\nWe will match you with our instructors with knowledge and experience. ',\n    training_etc_ment03: '* Seminar are hosted and paid for by the requesting schools',\n    training_apply: 'Apply',\n    training_ready: 'Ready',\n    new_version_title: 'Install the latest version',\n    new_version_text1: 'Current Hardware Connection Program',\n    new_version_text2: 'is not the most updated version.',\n    new_version_text3: 'Please install the latest version.',\n    new_version_text4: '',\n    new_version_download: \"Download<span class='download_icon'></span>\",\n    not_install_title: 'Uninstalled',\n    hw_download_text1: 'Install to connect hardware.',\n    hw_download_text2: '',\n    hw_download_text3: 'Hardware Connector Program is not installed.',\n    hw_download_text4: 'Please install the latest version.',\n    hw_download_btn: \"Download<span class='download_icon'></span>\",\n    not_support_browser: 'Your browser is not supported.',\n    quiz_complete1: 'Quiz is finished',\n    quiz_complete2: \"You've got {1} correct out of {0} problems\",\n    quiz_incorrect: \"Let's think again\",\n    quiz_correct: \"That's the answer\",\n    hw_connection_success: 'Connection Successful',\n    hw_connection_success_desc: 'Double click the hardware icon to check sensor values',\n    hw_connection_success_desc2: 'You can use the device in the project.',\n    hw_connection_termination_title: 'Disconnected',\n    hw_connection_termination_desc: 'The device has been disconnected.',\n    hw_connection_failed_title: 'Connection Failed',\n    hw_connection_failed_desc:\n        'Please make sure that\\nthe device used in the project is connected.',\n    ie_page_title: 'This browser is not supported',\n    ie_page_desc:\n        'Entry is available in Internet Explorer 10 or higher or in Chrome browser.<br/>Please update the Windows or install a Chrome browser.<br/>Offline versions are available even though the internet is not connected. Get download now!',\n    ie_page_chrome_download: 'Chrome<br/>download',\n    ie_page_windows_update: 'Windows<br/>update',\n    ie_page_offline_32bit_download: 'Windows 32bit<br/>download',\n    ie_page_offline_64bit_download: 'Windows 64bit<br/>download',\n    ie_page_offline_mac_download: 'Mac<br/>download',\n    cancel_deletion_your_account: 'Do you want to cancel the deletion of your account?',\n    account_deletion_canceled_complete: 'Account deletion has been canceled.',\n    journal_henesys_no1_title: 'Henesys Adventure Journal No. 1',\n    journal_henesys_no2_title: 'Henesys Adventure Journal No. 2',\n    journal_henesys_no1_content:\n        \"This is the first journal for Henesys. Today, I almost fell trying to jump on the way to the blacksmith’s house. He’s important in Henesys. Why did he make such a big hole in front of his yard? I don't think there’s anyone who can jump through these holes unless it's a great monster like me! let’s go to that restaurant. It’s supposed to be good!\",\n    journal_henesys_no2_content:\n        'I really did eat too much. The meat in that restaurant was really delicious. How could it be so tender? But the bread next door wasn’t great. The chef seemed to be always playing around, saying he’s “learning how to cook better.” He should use that time to get some more practice. Now that I’ve filled my belly, time to start a full-scale adventure!',\n    journal_ellinia_no1_title: 'Ellinia Adventure Journal No. 1',\n    journal_ellinia_no2_title: 'Ellinia Adventure Journal No. 2',\n    journal_ellinia_no1_content:\n        'Phew, I sat on an Orange Mushroom without even knowing. I guess that’s a good reason to get mad... But piling on me was too much! They’re a scary bunch. No wonder the slimes had a hard time. No need to worry, though! Yours truly took care of it! Now that the slimes are my friends, I’m gonna continue the adventure into this gorgeous forest.',\n    journal_ellinia_no2_content:\n        'My adventurous friend, Royal Fairy, told me there are some scary rumors going on around Elnath. I wonder what that is? I’m supposed to play with my friends at home tonight, so I’ll ask then. I can’t wait!  But what should I wear ... I don’t think anything is going to fit because I got bigger... Well, I’m always cute, so no matter what I wear, everyone will love it!',\n    journal_elnath_no1_title: 'Elnath Adventure Journal No. 1',\n    journal_elnath_no2_title: 'Elnath Adventure Journal No. 2',\n    journal_elnath_no1_content:\n        \"Oh, my gosh! So this is \\\"snow\\\" I heard so much about, huh? It's always spring where I live, so this is my first snow. I wasn't paying much attention because I was busy fighting the monsters, but now I see the whole world is so white and cold! I thought it’d be tasty, but it's flavorless. I wish I can bring some back, but there's no way. Oh, too bad.\",\n    journal_elnath_no2_content:\n        'Eww, I accidentally ate coal dust! Those bad monsters! Least they could do is run away quietly, but they just had to spread coal all over. Thanks to them, my shiny, fluffy pink skin is getting dirtier. I need to get out of here and take a clean bath. Adventure is nice, but no self-respecting monster should walk around looking this dirty.',\n    bug_report_alert_msg: 'Thank you for the report.',\n    version_update_msg1: 'You can use the latest Entry Offline version(%1).',\n    version_update_msg2: 'You can use the latest Entry Hardware version(%1).',\n    version_update_msg3: 'Do you want to update now?',\n    select_the_hardware: 'Select the hardware<br />that you would use in the lesson.',\n    select_hardware_button: 'Select',\n    select_the_expansion_block: 'Select the expansion block that you would use in the lesson.',\n    select_hardware_not_support_info: 'Hardware blocks are not available for open classes.',\n    select_hardware_not_support_info2: 'Please wait a little bit.',\n    select_expansion_block_button: 'Select',\n    expansion_weather_description:\n        'It is a collection of blocks related to weather in Korea such as temperature, precipitation, and fine dust concentration.',\n    expansion_festival_description:\n        'It is a collection of blocks related to various events and festivals by local area.',\n    expansion_translate_description:\n        'It is a collection of blocks that can translate into other languages using the Papago.',\n    expansion_behaviorConductDisaster_description:\n        'It is a collection of blocks about behavior-guidelines that the public should follow when natural disasters occur. (Provided by MPSS)',\n    expansion_behaviorConductLifeSafety_description:\n        'It is a collection of blocks about basic behavior-guidelines that the public should follow for safty in life. (Provided by MPSS)',\n    expansion_emergencyActionGuidelines_description:\n        'It is a collection of blocks about emergency action guidelines for citizens to follow in order to stay safe during natural and social disasters, as well as in everyday life.',\n    ai_utilize_tts_description:\n        'It is a collection of blocks that can read text in a variety of voice using the Clova.',\n    hardware_need_update_title: 'Entry HW update',\n    hardware_need_update_content:\n        \"Please update to the latest version,\\nif you are using below version.\\nEntry website only supported v1.9.73 or later.\\nPlease remove the web browser cache,\\nif any block doesn't appear after updating.\",\n    ai_utilize_audio_description:\n        'It is a collection of blocks that recognize speech using microphone.',\n    ai_utilize_video_description:\n        'It is a collection of blocks that can recognize movement, direction and object to be shot by using camera. (IE / iOS Not Supported)',\n    cannot_delete_function:\n        'Function already in use.\\nTo change the return value setting,\\nthere must be no object with a function block.',\n    local_variable_deletion_warning:\n        'If you have a local variable in use,\\nthe associated block may be deleted.\\nDo you really want to change it?',\n    warning_function_aleady_being_edited:\n        \"To add a new function,\\nclick 'Save' or 'Cancel' to exit\\nthe Add function screen.\",\n    ai_utilize_pose_landmarker_description:\n        'It is a collection of blocks that detect human bodies using camera.',\n    ai_utilize_face_landmarker_description:\n        'It is a collection of blocks that detect human faces using camera.',\n    ai_utilize_object_detector_description:\n        'It is a collection of blocks that detect objects using camera.',\n    ai_utilize_gesture_recognition_description:\n        'It is a collection of blocks that detect human hands using camera.',\n    sound_empty1: 'Click [Add Sound] to add sound.',\n    sound_empty2: 'How to add sound',\n    sound_empty3: \"On the 'Select sound' tab, select the default sound provided by the Entry.\",\n    sound_empty4: \"On the 'Upload files' tab, upload the MP3 file directly.\",\n    sound_empty5:\n        \"You can cut only the parts you need in the 'Trim' mode, or adjust the volume, speed and pitch in the 'Adjust' mode.\",\n    sound_loading: 'Loading sound',\n    parameter_can_not_space: \"Value can't be blank.\",\n    ai_utilize_train_pop_error: 'The model applied to the project has been deactivated or deleted.',\n    video_model_load_success: 'Load Success',\n    video_model_load_completed: 'Video sensing enabled',\n    ai_utilize_video_loading: 'video sensing block is now loading.<br/> It takes up to 1 minute',\n};\nLang.Users = {\n    auth_failed: 'Authentication failed',\n    birth_year: 'Birth Year',\n    birth_year_before_1990: 'Before 1990s',\n    edit_personal: 'Edit Personal',\n    email: 'Email',\n    email_desc: 'Enter your Email address to receive newsletters',\n    email_inuse: 'E-mail address is already in-use',\n    email_match: 'Please enter a valid email',\n    forgot_password: 'Forgot your password?',\n    job: 'Job',\n    language: 'Language',\n    name: 'Full Name',\n    name_desc: 'Enter your name',\n    name_not_empty: 'You must enter your name',\n    password: 'Password',\n    password_desc: '',\n    password_invalid: 'Invalid Password',\n    password_long: 'Password must be between 4-20 characters long',\n    password_required: 'Password can not be blank',\n    project_list: 'Project List',\n    regist: 'Signup Complete',\n    rememberme: 'Remember me',\n    repeat_password: 'Repeat Password',\n    repeat_password_desc: 'Repeat Password',\n    repeat_password_not_match: 'Passwords do not match',\n    sex: 'Sex',\n    signup_required_for_save: 'Signin required for saving a project.',\n    username: 'Username',\n    username_desc: 'Enter your unique name for signin',\n    username_inuse: 'Username already taken',\n    username_long: 'Username must be between 4-20 characters long',\n    username_unknown: 'Unknown user',\n    already_verified: 'Already verified',\n    email_address_unavailable: 'The email address is unavailable.',\n    email_address_invalid_for_idpw:\n        \"The email address is not available.\\n Please try 'Find ID or Password' again to resend. \",\n    email_address_invalid_for_certification:\n        'The email address is not available.\\n Please verify your email again.',\n    verification_complete: 'Verification has been completed.',\n    reset_password_mail_sent:\n        'Email for password resetting has been sent. Please check your email.',\n    email_not_verified:\n        \"This email is not verified. Please verify your email to click 'Verifying email' first.\",\n    verification_email_send_complete:\n        'Verifying email has been sent. Please verify your email first.',\n    email_send_failed: 'Sending email was failed. Please try again.',\n    email_not_exist: 'This email does not exist.',\n    not_valid_email: 'Please enter a correct type of email.',\n};\nLang.Workspace = {\n    picture_rotation: 'Rotation',\n    picture_size: 'Size',\n    thickness: 'thickness',\n    follow: 'Follow',\n    SaveWithPicture: 'You have a unsaved drawing. Do you want to save it?',\n    RecursiveCallWarningTitle: 'Limitation of function call',\n    RecursiveCallWarningContent:\n        'Too many functions were called at once. Please reduce the function calls.',\n    check_result_value: 'Return a value',\n    check_local_variable: 'Use local variable',\n    local_variable: 'Local variable',\n    local_variable_dup: 'The local variable name changed automatically because it already exists.',\n    local_variable_rename: 'Rename completed',\n    local_variable_rename_failed: 'Rename failed',\n    local_variable_rename_ok: 'The local variable has been renamed.',\n    use_block_objects1: 'Object using the function ({0} block(s))',\n    use_block_objects2: 'Object using the function ({0})',\n    message_too_long: 'Message name too long.',\n    use_block_function: 'Assembled inside the function.',\n    use_block_project: 'Block : {0}',\n    use_blocks_project: 'Blocks : {0}',\n    pose_landmarker_title_text: 'Human detection',\n    face_landmarker_title_text: 'Face Detection',\n    object_detector_title_text: 'Object detection',\n    gesture_recognition_title_text: 'Hand detection',\n    sound_start_point: 'Start point',\n    sound_end_point: 'End point',\n    sound_selection: 'Selection',\n    sound_volume: 'Volume',\n    sound_speed: 'Speed',\n    sound_pitch: 'Pitch',\n    SelectShape: 'Move',\n    SelectCut: 'Cut',\n    Pencil: 'Pen',\n    Line: 'Line',\n    Rectangle: 'Rectangle',\n    Ellipse: 'Ellipse',\n    Text: 'Text Box',\n    Fill: 'Fill',\n    Eraser: 'Eraser',\n    Magnifier: 'Zoom in/out',\n    block_helper: 'Block helper',\n    new_project: 'New Project',\n    add_object: 'Add objects',\n    download_image_name: 'entry block',\n    all: 'All',\n    animal: 'Animal',\n    arduino_entry: 'Program for connect to Arduino',\n    arduino_program: 'Arduino program',\n    arduino_sample: 'Sample code for Arduino',\n    arduino_driver: 'Driver for arduino',\n    cannot_add_object: 'Cannot add objects while running a project.',\n    cannot_add_picture: 'Cannot add picture while running a project.',\n    cannot_add_sound: 'Cannot add sound while running a project.',\n    cannot_add_expansion_block: 'Cannot add expansion block while running a project.',\n    add_object_before_edit: 'Add object firstly,\\nto edit the shape.',\n    add_table_before_edit: 'Add table.',\n    cannot_edit_click_to_stop: 'Can not modify a project.\\nClick to stop',\n    cannot_open_private_project:\n        \"You cannot view the code of the unshared projects. Click 'OK' to move to the previous page.\",\n    cannot_save_running_project: 'Can not save while running a project.',\n    character_gen: 'Make an avarta',\n    check_runtime_error: 'Please check the block marked with red.',\n    check_browser_error: 'This block is not compatible to IE/Safari',\n    check_microphone_error: 'There is no microphone connected to the computer',\n    check_webcam_error: 'There is no camera connected to the computer',\n    context_download: 'Download to PC',\n    context_duplicate: 'Duplicate',\n    context_remove: 'Remove',\n    context_rename: 'Rename',\n    coordinate: 'Coord',\n    create_function: 'Create Function',\n    direction: 'Direction',\n    drawing: 'Paint',\n    enter_list_name: '',\n    enter_name: 'Enter a new name',\n    enter_new_message: 'Enter new message name.',\n    enter_variable_name: 'Enter the new variable name (less than 10)',\n    family: 'Family',\n    fantasy: 'Fantasy/etc',\n    file_new: 'New Project',\n    file_open: 'Open project',\n    file_upload: 'Upload my project',\n    file_upload_login_check_msg: 'For the uploading your project you have to sign in',\n    file_save: 'Save',\n    file_save_as: 'Save as clone',\n    file_save_download: 'Download project',\n    func: 'Function',\n    function_create: 'Add function',\n    function_add: 'Add function',\n    interface: 'Interface',\n    landscape: 'Landscape',\n    list: 'List',\n    list_add_calcel: '',\n    list_add_calcel_msg: '',\n    list_add_fail: '',\n    list_add_fail_msg1: '',\n    list_add_fail_msg2: '',\n    list_add_ok: '',\n    list_add_ok_msg: '',\n    list_create: 'Add list',\n    list_create_placeholder: 'Input the name of the list.',\n    list_dup: 'The name has been changed automatically.',\n    list_newname: 'New name',\n    list_export: 'Export',\n    list_import: 'Import',\n    list_remove: 'Remove list',\n    list_rename: 'Rename list',\n    list_rename_failed: 'Rename list failed',\n    list_rename_ok: 'The name has been changed successfully.',\n    list_too_long: 'The name cannot exceed 10 characters.',\n    message: 'Signal',\n    message_add_cancel: 'Canceled',\n    message_add_cancel_msg: 'Add a message was canceled.',\n    message_add_fail: 'Failed',\n    message_add_fail_msg: 'Message name conflicted.',\n    message_add_ok: 'Message added',\n    message_add_ok_msg: 'was successfully added.',\n    message_create: 'Add Signal',\n    message_add: 'Add Signal',\n    message_create_placeholder: 'Input the name of the signal',\n    message_dup: 'Message name conflicted.',\n    message_remove: 'Remove a message',\n    message_remove_canceled: 'Remove a message was canceled',\n    message_rename: 'Rename a message',\n    message_rename_failed: 'Rename message failed',\n    message_rename_ok: 'Successfully rename message.',\n    no_message_to_remove: 'There is no message to remove.',\n    no_use: 'Not assembled on object.',\n    no_variable_to_remove: '',\n    no_variable_to_rename: 'There is no varibale to remove',\n    object_not_found: 'No object is specified in the block.',\n    object_not_found_for_paste: 'There is no object to paste.',\n    people: 'People',\n    picture_add: 'Add Shape',\n    table_add: 'Add Table',\n    draw_new_table: 'New Table',\n    plant: 'Plant',\n    project: 'Project',\n    project_copied: 'Copy',\n    PROJECTDEFAULTNAME: ['Cool', 'Funny', 'Nice', 'Huge', 'Great', 'Handsome', 'Lucky'],\n    remove_object: 'Remove Object',\n    remove_object_msg: 'remove was successfully completed.',\n    removed_msg: 'was successfully removed',\n    rotate_method: 'Rotate',\n    rotation: 'Rotation',\n    run: 'Run',\n    saved: 'Saved',\n    saved_msg: 'was successfully saved.',\n    save_failed: 'Problem occurred while saving a project. Please try again.',\n    select_library: 'Select object',\n    select_sprite: 'Please select at least one sprite to apply.',\n    shape_remove_fail: 'Remove a shape was failed.',\n    shape_remove_fail_msg: 'At least one or more shapes required.',\n    shape_remove_ok: 'Shape Removed',\n    shape_remove_ok_msg: 'was removed.',\n    load_expansion_block: 'Load Expansion Block',\n    load_ai_utilize_block: 'Load AI Block',\n    load_ai_utilize_train_block: 'Train Model',\n    select_expansion_block: 'Select block',\n    deselect_expansion_block_warning:\n        \"The extension block can't be deselected because it is assembled to the project.\",\n    deselect_ai_utilize_block_warning:\n        \"The AI block can't be deselected because it is assembled to the project.\",\n    sound_add: 'Add Sound',\n    sound_remove_fail: 'Remove a sound was failed.',\n    sound_remove_ok: 'Sound Removed',\n    sound_remove_ok_msg: 'was removed.',\n    stop: 'Stop',\n    pause: 'Pause',\n    restart: 'Restart',\n    speed: 'Speed',\n    tab_attribute: 'Attribute',\n    tab_table: 'Table',\n    tab_code: 'Block',\n    tab_picture: 'Shape',\n    tab_sound: 'Sound',\n    tab_text: 'TextBox',\n    textbox: 'Textbox',\n    textbox_edit: 'Edit Textbox',\n    textbox_input: 'Please input text for apply.',\n    things: 'Things',\n    textcoding_tooltip1: \"Instructions for 'Entry Python'<br/>is available. Check out !\",\n    textcoding_tooltip2: 'Code with blocks or by Python<br/>whichever you prefer.',\n    textcoding_tooltip3: 'See Python code execution results.',\n    upload: 'Upload files',\n    upload_addfile: 'Add a file',\n    variable: 'Variable',\n    variable_add_calcel: 'Canceled',\n    variable_add_calcel_msg: 'Add a variable was canceled.',\n    variable_add_fail: 'Failed',\n    variable_add_fail_msg1: 'Variable name conflicted.',\n    variable_add_fail_msg2: 'Variable name is not proper.',\n    variable_add_ok: 'Variable added',\n    variable_add_ok_msg: 'was successfully added.',\n    variable_create: 'Add variable',\n    variable_add: 'Add variable',\n    variable_dup: 'Variable name was already exists.',\n    variable_newname: 'New Name',\n    variable_remove: 'Remove variable',\n    variable_remove_canceled: 'Remove a variable was canceled',\n    variable_rename: 'Rename variable name',\n    variable_rename_failed: 'Failed',\n    variable_rename_msg: \"'Rename variable was successfully completed.'\",\n    variable_rename_ok: 'Rename variabled was successfully completed.',\n    variable_select: 'Select a variable',\n    variable_too_long: 'Variable name too long.',\n    open_analizy_data_import: 'Load Data Table',\n    vehicle: 'Vehicles',\n    add_object_alert_msg: 'Object does not exist. Please add object and try again.',\n    add_object_alert: 'Alert',\n    create_variable_block: 'Create variable',\n    create_list_block: 'Add list',\n    Variable_Timer: 'timer',\n    Variable_placeholder_name: 'variable name',\n    Message_placeholder_name: 'Signal name',\n    Variable_property: 'Attribute of the variable',\n    Variable_placeholder_content: 'Input the name of the variable.',\n    Variable_use_all_objects: 'Use for all objects',\n    Variable_use_this_object: 'Use for this object',\n    Variable_used_at_all_objects: 'variable used at all objects',\n    variable_create_normal: 'Use for variable\\n(Stored in Project)',\n    variable_create_cloud: 'Use for shared variable\\n(Stored in Server)',\n    variable_create_real_time: 'Use for real-time variable\\n(Stored in Server)',\n    Variable_used_at_special_object: 'variable used at special object',\n    Variable_used_objects: 'Object used for the variable',\n    draw_new: 'Draw new',\n    draw_new_ebs: 'Draw new',\n    painter_file: 'File ▼',\n    painter_file_save: 'Save',\n    painter_file_saveas: 'Save as a new shape',\n    new_picture: 'New shape',\n    painter_edit: 'Edit ▼',\n    get_file: 'get',\n    copy_file: 'Copy',\n    cut_picture: 'cut',\n    paste_picture: 'paste',\n    remove_all: 'remove all',\n    flip_horizontal: 'flip horizontal',\n    flip_vertical: 'flip vertical',\n    regular: 'Regular',\n    bold: 'Bold',\n    font_underline: 'underline',\n    font_tilt: 'tilt',\n    font_cancel: 'cancel',\n    font_color: 'font color',\n    font_fill: 'Fill',\n    font_family: 'Font',\n    align_left: 'left align ',\n    align_center: 'center align',\n    align_right: 'right align',\n    italic: 'Italic',\n    textStyle: 'text',\n    add_picture: 'Add Shape',\n    select_picture: 'Select Library',\n    select_table: 'Select Table',\n    load_web: 'Import table',\n    select_sound: 'Select sound',\n    Size: 'Size',\n    show_variable: ' Show variable',\n    default_value: 'default',\n    slide: 'slide',\n    min_value: 'min',\n    max_value: 'max',\n    number_of_list: 'number of list items',\n    empty_of_list: 'No items added.',\n    use_all_objects: 'Use for all objects',\n    list_name: 'List name',\n    list_property: 'Attribute of the list',\n    list_used_specific_objects: 'List used for specific object',\n    List_used_all_objects: 'List used for all objects',\n    List_used_objects: 'Object used for the list',\n    Scene_delete_error: 'The scene is, there should be at least one.',\n    Scene_add_error: 'The scene is up to 20.',\n    replica_of_object: \"'s replicas\",\n    will_you_delete_scene:\n        'Deleting scene can not be restored.\\nAre you sure you want to delete scene?',\n    will_you_delete_function:\n        'Deleting function can not be restored.\\nAre you sure you want to delete function?',\n    duplicate_scene: 'Duplicate',\n    block_explain: 'Block description ',\n    block_intro: 'Clicking on the block comes the description of the block . ',\n    blocks_reference: 'Blocks Reference',\n    hardware_guide: 'Hardware Guide',\n    robot_guide: 'Robot Guide',\n    python_guide: 'Entry Python Guide',\n    show_list_workspace: 'Show list',\n    list_create_normal: 'Use for list\\n(Stored in Project)',\n    list_create_cloud: 'Use for shared list \\n(Stored in Server)',\n    list_create_real_time: 'Use for real-time list\\n(Stored in Server)',\n    confirm_quit: \"You didn't saved your changes.\",\n    confirm_load_temporary: 'You have unsaved project. Do you want to open it?',\n    login_to_save: 'Try to save after login.',\n    cannot_save_in_edit_func: 'Can not save while editing function.',\n    new_object: 'New object',\n    arduino_connect: '',\n    arduino_connect_success: '',\n    confirm_load_header: 'Project Recovery',\n    uploading_msg: 'Uploading',\n    upload_fail_msg: 'Upload failed. Please try again.',\n    upload_not_supported_msg: 'Not supported file type.',\n    upload_not_supported_file_msg: 'Not supported file type.',\n    file_converting_msg: '​File converting in process',\n    file_converting_fail_msg: '​File conversion has failed',\n    fail_contact_msg: 'If the problem persists,</br>contact entry@connect.or.kr',\n    saving_msg: 'Saving',\n    saving_fail_msg: 'Save failed. Please try again.',\n    loading_msg: 'Loading',\n    loading_fail_msg: 'Load failed. Please try again.',\n    restore_project_msg: 'Project is not saved properly. Would you like to restore this project?',\n    quit_stop_msg: 'Program cannot be closed during save.',\n    ent_drag_and_drop: 'Drag and drop the file to upload',\n    not_supported_file_msg: 'This file format is not supported',\n    broken_file_msg: 'File is corrupt or wrong file is loaded',\n    check_audio_msg: 'Not supported file type.',\n    check_entry_file_msg: 'Only ENT files are loadable',\n    hardware_version_alert_text: 'Please update your hardware connector to the latest version.',\n    variable_name_auto_edited_title: 'variable name auto-edited',\n    variable_name_auto_edited_content: 'variable name cannot exceed 10 characters',\n    list_name_auto_edited_title: 'list name auto-edited',\n    list_name_auto_edited_content: 'list name cannot exceed 10 characters',\n    list_cant_add_item: 'Warning',\n    list_max_length_exceeded: 'You can add up to 5,000 items to a list.',\n    list_truncated_on_load:\n        'The number of list items in this project exceeds 5,000, so some may not be displayed.\\n\\nFor stable use,\\nplease reduce the list to 5,000 or fewer.',\n    list_truncated_on_load_title: 'Notice',\n    cloned_scene: 'Cloned_',\n    default_mode: 'Standard',\n    practical_course_mode: 'Textbook',\n    practical_course: 'practical course',\n    select_mode: 'Mode',\n    select_mode_popup_title: \"Choose 'Create' option\",\n    select_mode_popup_lable1: 'Standard',\n    select_mode_popup_lable2: 'Textbook(Practical Course)',\n    select_mode_popup_desc1: 'Create projects with<br/>unlimited Entry features',\n    select_mode_popup_desc2: \"Create projects using<br/>'Practical Course' features\",\n    practical_course_notice: 'Notice',\n    practical_course_desc:\n        \"<span class='practical_cource_title'>교과용 만들기</span>는<br />실과 교과서로 소프트웨어를 배울 때<br />필요한 기능만을 제공합니다.\",\n    practical_course_desc2:\n        '*기본형 작품 만들기를 이용하면 더 많은 기능을<br />이용해 작품을 만들 수 있습니다.',\n    practical_course_tooltip: '모든 기능을 이용하기 위해서는<br/>기본형을 선택해 주세요.',\n    name_already_exists: 'The name already exists.',\n    enter_the_name: 'Please enter the name.',\n    object_not_exist_error: 'Object does not exist. Please add object and try again.',\n    workspace_tutorial_popup_desc:\n        \"<span class='practical_cource_title'>작품 만들기</span>는<br />창의적인 작품을 만들 수 있도록<br /> 다양한 블록과 기능을 제공합니다.\",\n    start_guide_tutorial: 'Creating Guide',\n    language: 'language',\n    file: 'file',\n    save: 'save',\n    help: 'help',\n    print: 'print',\n    undo: 'undo',\n    redo: 'redo',\n    workspace_title_tooltip:\n        'The default project name has changed. You can\\nrecognize what project is through the date you create in\\nthe project name.',\n    workspace_object_tooltip:\n        'You can change the order of the object by\\ndragging the image of the object. (It is the same\\nin the ‘Shape’ and ‘Sound’ sections.)',\n    workspace_comment_tooltip: 'You can hide or show all the memos\\nadded.',\n    workspace_zoom_tooltip:\n        'You can zoom in/out the blocks. If you click ‘=’\\nthe block will be back to original size.',\n    workspace_image_tooltip: 'Create your own\\nproject with new\\nfunctions!',\n    playground_block_drop: 'Add the blocks in my storage\\nto assembly station',\n    container_object_drop: 'Add the object in my storage\\nto object list',\n    my_storage_block_drop: 'Add\\nthe blocks\\nto my storage',\n    my_storage_object_drop: 'Add\\nthe object\\nto my storage',\n    my_storage: 'My storage',\n    my_block: 'My Block',\n    red: 'Red',\n    green: 'Green',\n    blue: 'Blue',\n    hue: 'Hue',\n    saturation: 'Saturation',\n    brightness: 'Brightness',\n    spoid: 'Spoid',\n    palette_mode: 'Palette mode',\n    slider_mode: 'Slider mode',\n    toast_error_title_object_center: 'Caution',\n    toast_error_contents_object_center:\n        'If the center point is far from the object and goes out of the canvas, it returns to its original position.',\n    blocks_comming_soon: \"I'm working hard.\\nPlease wait a little longer!\",\n    data_table: 'table',\n    select_all: 'Select all',\n    now_loading_msg: 'Now Loading.\\nPlease Wait.',\n    font_textblock_strikethrough: 'Strikethrough',\n    font_textblock_underline: 'Underline',\n    font_textblock_italic: 'Italic',\n    font_textblock_bold: 'Bold',\n    function_attribute: 'Attribute',\n    variable_default_value: 'Default value',\n    list_default_value: 'Default value',\n    func_property: 'Attribute of the function',\n    bring_forward: 'Bring Forward',\n    send_backward: 'Send Backward',\n    upload_error_msg: 'Unable to upload as image is suspected of violating usage policy.',\n    confirm_firmware_hwlite_block_title: 'Verify firmware Installation',\n    confirm_firmware_hwlite_block_msg: 'To use %1 in Entry,\\n please install the firmware first.',\n    confirm_firmware_hwlite_block_pass: 'Already installed',\n    confirm_firmware_hwlite_block_download: 'Install firmware',\n    confirm_firmware_hwlite_block_usb_connect: 'USB connect',\n    progress_firmware_hwlite_title: 'Install firmware',\n    progress_firmware_hwlite_step1_title: 'Check USB port',\n    progress_firmware_hwlite_step1_content1: 'Connect the device and PC with USB.',\n    progress_firmware_hwlite_step1_content2:\n        'Select the device to connect.\\nWait for a USB connection.',\n    progress_firmware_hwlite_step1_content3: 'USB connection detected.',\n    progress_firmware_hwlite_step2_title: 'Install firmware',\n    progress_firmware_hwlite_step2_content1: 'Installing firmware.\\nPlease wait.',\n    progress_firmware_hwlite_step2_content_complete: 'Installation is complete.',\n    progress_firmware_hwlite_step2_content_fail: 'Firmware installation failed.',\n    progress_firmware_hwlite_step2_content_select: 'Select the firmware version to install.',\n    progress_firmware_hwlite_button_select: 'Check',\n    progress_firmware_hwlite_button_reselect: 'Retry',\n    progress_firmware_hwlite_button_install: 'Install firmware',\n    progress_firmware_hwlite_button_connect_device: 'Connect device',\n    progress_firmware_hwlite_button_retry: 'Retry',\n    usbconnect_fail_alert: \"USB connection failed. Check the connection status and click 'Retry'.\",\n    select_hwlite_block_duplicated: 'Please select only one hardware device.',\n    select_hwlite_block_none: 'Please select the hardware device to connect.',\n    select_firmware_hwlite_title: 'Download Firmware',\n    select_firmware_hwlite_content:\n        'Please download and install the appropriate firmware \\n for your hardware version.',\n    select_flash_firmware_hwlite_title: 'Select firmware to install',\n    select_flash_firmware_hwlite_content:\n        'Please select the version of\\n the Microbit you want to connect to.\\n When the installation is complete,\\n a message is displayed.',\n    flash_firmware_success: 'Firmware installation is complete.',\n    flash_firmware_failed: 'Firmware installation failed. Please try again.',\n};\nLang.code = 'view code';\nLang.EntryStatic = {\n    event100: 'Event',\n    groupProject: 'open group',\n    usage_parallel: 'Parallel',\n    usage_expansion: 'Expansion',\n    usage_hw: 'Hardware',\n    usage_sequence: 'Sequence',\n    privateProject: 'only owner',\n    privateCurriculum: 'only owner',\n    publicCurriculum: 'curriculum share',\n    publicProject: 'project share',\n    group: 'share to group',\n    groupCurriculum: 'open group',\n    private: 'only owner',\n    public: 'open lessons',\n    lecture_is_open_true: 'open',\n    lecture_is_open_false: 'closed',\n    category_all: 'All Categories',\n    category_game: 'Game',\n    category_animation: 'Animation',\n    category_media_art: 'Media Art',\n    category_physical: 'Physical',\n    category_etc: 'etc',\n    category_category_game: 'Game',\n    category_category_animation: 'Animation',\n    category_category_media_art: 'Media Art',\n    category_category_physical: 'Physical',\n    category_category_etc: 'etc',\n    sort_created: 'By Latest',\n    sort_updated: 'By Latest',\n    sort_visit: 'By Viewers',\n    sort_likeCnt: 'By Likes',\n    sort_comment: 'By Comments',\n    period_all: 'Entire period',\n    period_1: 'Today',\n    period_7: 'Latest 1 week',\n    period_30: 'Latest 1 month',\n    period_90: 'Latest 3 months',\n    lecture_required_time_1: 'Less than 15 min.',\n    lecture_required_time_2: '15  to 30 min.',\n    lecture_required_time_3: '30 to 45 min.',\n    lecture_required_time_4: '45 to 60 min',\n    lecture_required_time_5: 'over 1 hour',\n    usage_event: 'Event',\n    usage_signal: 'Signal',\n    usage_scene: 'Scene',\n    usage_repeat: 'Repeat',\n    usage_condition_repeat: 'Condition repeat',\n    usage_condition: 'Condition',\n    usage_clone: 'Cloned Object',\n    usage_rotation: 'Rotation',\n    usage_coordinate: 'Coordinate',\n    usage_arrow_move: 'Arrow move',\n    usage_shape: 'Shape',\n    usage_speak: 'Speak',\n    usage_picture_effect: 'Effect',\n    usage_textBox: 'Textbox',\n    usage_draw: 'Draw',\n    usage_sound: 'Sound',\n    usage_confirm: 'Confirm',\n    usage_comp_operation: 'Compare operation',\n    usage_logical_operation: 'Logical operation',\n    usage_math_operation: 'Math operation',\n    usage_random: 'Random',\n    usage_timer: 'Timer',\n    usage_variable: 'Variable',\n    usage_list: 'List',\n    usage_ask_answer: ' Input/Output',\n    usage_function: 'Function',\n    usage_arduino: 'Arduino',\n    concept_resource_analytics: 'Procedual Thinking',\n    concept_procedual: 'Abstractive Thinking',\n    concept_abstractive: 'Korean',\n    concept_individual: 'English',\n    concept_automation: 'Automation',\n    concept_simulation: 'Simulation',\n    concept_parallel: 'Parallel',\n    subject_korean: 'Korean',\n    subject_english: 'English',\n    subject_mathmatics: 'Mathmatics',\n    subject_social: 'Social',\n    subject_science: 'Science',\n    subject_music: 'Music',\n    subject_paint: 'Paint',\n    subject_athletic: 'Athletics',\n    subject_courtesy: 'Courtesy',\n    subject_progmatic: 'Progmatic',\n    lecture_grade_1: '1 th',\n    lecture_grade_2: '2 th',\n    lecture_grade_3: '3 th',\n    lecture_grade_4: '4 th',\n    lecture_grade_5: '5 th',\n    lecture_grade_6: '6 th',\n    lecture_grade_7: '7 th',\n    lecture_grade_8: '8 th',\n    lecture_grade_9: '9 th',\n    lecture_grade_10: 'Graduated',\n    lecture_level_1: 'Low',\n    lecture_level_2: 'Middle',\n    lecture_level_3: 'High',\n    listEnable: 'list',\n    functionEnable: 'function',\n    messageEnable: 'message',\n    objectEditable: 'object',\n    pictureeditable: 'shape',\n    sceneEditable: 'scene',\n    soundeditable: 'sound',\n    variableEnable: 'variable',\n    e_1: 'elementary school 1',\n    e_2: 'elementary school 2',\n    e_3: 'elementary school 3',\n    e_4: 'elementary school 4',\n    e_5: 'elementary school 5',\n    e_6: 'elementary school 6',\n    m_1: 'middle school 1',\n    m_2: 'middle school 2',\n    m_3: 'middle school 3',\n    general: 'general',\n    curriculum_is_open_true: 'open',\n    curriculum_open_false: 'closed',\n    contest2019: 'Contest',\n    exhibit: 'Contest',\n    notice: 'Notice',\n    qna: 'Q&A',\n    tips: 'Tips & Tricks',\n    free: 'Discussions',\n    report: 'Suggestions',\n    art_category_all: 'All projects',\n    art_category_game: 'Games',\n    art_category_animation: 'Animation',\n    art_category_physical: 'Physical',\n    art_category_etc: 'etc',\n    art_category_media: 'media art',\n    art_sort_updated: 'Most Recent',\n    art_sort_visit: 'Views',\n    art_sort_likeCnt: 'Likes',\n    art_sort_comment: 'Comments',\n    art_period_all: 'All',\n    art_period_day: 'Today',\n    art_period_week: 'Recent week',\n    art_period_month: 'Recent month',\n    art_period_three_month: 'Recent three month',\n    level_high: 'Row',\n    level_mid: 'Middle',\n    level_row: 'High',\n    discuss_sort_created: 'Most Recent',\n    discuss_sort_visit: 'Views',\n    discuss_sort_likesLength: 'Likes',\n    discuss_sort_commentsLength: 'Comments',\n    discuss_period_all: 'All',\n    discuss_period_day: 'Today',\n    discuss_period_week: 'Recent week',\n    discuss_period_month: 'Recent month',\n    discuss_period_three_month: 'Recent three month',\n    art_category_living: 'Living Supplies',\n    art_category_storytelling: 'Storytelling',\n    art_category_arts: 'Arts',\n    art_category_knowledge: 'Knowledges',\n    art_period_today: 'Today',\n    art_period_quarter: 'Recent 3 months',\n};\nLang.Helper = {\n    when_run_button_click: 'When the Start button is clicked, the connected blocks below will run.',\n    when_some_key_pressed: 'When the assigned key is pressed, the connected blocks below will run.',\n    mouse_clicked: 'When the mouse is clicked, the connected blocks below will run.',\n    mouse_click_cancled: 'When the mouse click is released, the connected blocks below will run.',\n    when_object_click: 'When the object is clicked, the connected blocks below will run.',\n    when_object_click_canceled:\n        'When the object click is released, the connect blocks below will run.',\n    when_message_cast: 'When the signal is received, the connected blocks below will run.',\n    message_cast: 'Sends signal selected from the list',\n    message_cast_wait:\n        'Sends signal selected from the list, and wait util the blocks finish running.',\n    when_scene_start: 'When the scene starts, the connected blocks below will run.',\n    start_scene: 'Selected scene starts.',\n    start_neighbor_scene: 'The previous or the next scene starts.',\n    wait_second: 'Runs the next block after waiting for the entered amount of time.',\n    repeat_basic: 'Repeats the blocks inside for the entered number of times.',\n    repeat_inf: 'Repeats the blocks inside infinitely.',\n    repeat_while_true: 'Repeats the blocks inside until/while the condition is True/False. ',\n    stop_repeat:\n        \"Stops the closest block that encloses this block.\\n It works with various C-shaped blocks like 'repeat' block.\",\n    continue_repeat: 'Skip this repeat and run it from the beginning of the next repeat.',\n    _if: 'If the condition is True/False, run the blocks inside.',\n    if_else:\n        \"If the condition is True/False, run the blocks inside the 'if' section.\\nIf not, run the blocks inside the 'else' section.\",\n    restart_project: 'The project restarts.',\n    stop_object:\n        'All objects : Stops all the blocks of all the objects.\\nThis : Stop all the blcoks of this object.\\nThis code : Stop all the blocks that includes this block.\\nOther block of this object : Stop the blocks not connected to the blocks of this object.\\nOther object : Stop all the blocks of the other objects.',\n    wait_until_true: 'Stops running and wait until the condition is True/False.',\n    when_clone_start:\n        'When the new clone of the object is created, the connected blocks below will run.',\n    create_clone:\n        'Self : Create the clone of this object.\\nEntrybot : Create the clone of Entrybot.',\n    delete_clone: \"Removes the clone of this object using with 'When clone is created'.\",\n    remove_all_clones: 'Removes all the clones of this object.',\n    move_direction: 'Moves in the direction of the arrow by input value.',\n    move_x: 'Changes the x-postion of the object by the input value.',\n    move_y: 'Changes the y-postion of the object by the input value.',\n    move_xy_time: 'Changes the x and y-postion of the object by input value for the input seconds.',\n    locate_object_time:\n        'Moves the object to the position of the selected object for the input seconds.',\n    locate_x: 'Moves the object to the entered x-position.',\n    locate_y: 'Moves the object to the entered y-position.',\n    locate_xy: 'Moves the object to the entered x and y-position.',\n    locate_xy_time: 'Moves the object to the entered x and y-position for the input seconds.',\n    locate: 'Moves the object to the position of the selected object.',\n    rotate_absolute: 'Sets the rotation of the object at an angle of the input degrees.',\n    rotate_by_time: 'Rotates the object at an angle of the input degrees for the input seconds.',\n    rotate_relative: 'Rotates the object at an angle of the input degrees.',\n    direction_absolute: 'Sets the direction of the object at an angle of the input degrees.',\n    direction_relative: 'Changes the direction of the object at an angle of the input degrees.',\n    move_to_angle: 'Moves the object by the input value in the direction of the input degrees.',\n    see_angle_object: 'Turns the object toward the selected object.',\n    bounce_wall: 'When object touches the edge of the screen, it bounces back.',\n    show: 'Makes the object show on the screen.',\n    hide: 'Hides the object from the screen.',\n    dialog_time:\n        'Runs the next block after the object speaks the input content for the input seconds.',\n    dialog: 'Runs the next block after the object speaks the input content.',\n    remove_dialog: 'Removes the speech bubble spoken and thought by the object.',\n    change_to_some_shape:\n        'Changes the object to the selected shape.\\nYou can select shape by entering shape name or shape number.',\n    change_to_next_shape: 'Changes the object to the next/previous shape.',\n    set_effect_volume: 'Applies the selected effect to the object by the input value.',\n    set_effect_amount: 'Applies the selected effect to the object by the input value.',\n    set_effect: 'Sets the selected effect to the object by the input value.',\n    set_entity_effect: 'Sets the selected effect to the object by the input value.',\n    add_effect_amount:\n        'Applies the selected effect to the object by the input value.\\n\\n- Color: 1~100.\\n- Brightness: It can be set it in the range of -100 to 100.\\n- Transparency: It can be set in the range of 0 to 100.',\n    change_effect_amount:\n        'Sets the selected effect to the object by the input value.\\n\\n- Color: 1~100.\\n- Brightness: It can be set it in the range of -100 to 100.\\n- Transparency: It can be set in the range of 0 to 100.',\n    change_scale_percent: 'Changes the size of the object by the input value.',\n    set_scale_percent: 'Sets the size of the object to the input value.',\n    change_scale_size: 'Changes the size of the object by the input value.',\n    set_scale_size: 'Sets the size of the object to the input value.',\n    stretch_scale_size: 'Stretches the width/length of the object by the input value.',\n    reset_scale_size: 'Resets the object to its original size.',\n    flip_x: 'Flips the object vertically. ',\n    flip_y: 'Flips the object horizontally.',\n    change_object_index:\n        'Brings objects forward or backward on the screen.\\n- Front : Bring object to the very front.\\n- Forward : Bring object one layer front.\\n- Backward : Send object one layer back.\\n- Back : Send object the very back.',\n    set_object_order: 'Shows the object in the set order.',\n    brush_stamp: 'Clones the object on stage like a stamp.',\n    start_drawing: 'Starts drawing along the path of the object.',\n    stop_drawing: \"Stops object's drawing.\",\n    start_fill: 'Starts filling along the path of the object.',\n    stop_fill: 'Stops filling.',\n    set_color: 'Sets the brush color of the object to the selected color.',\n    set_random_color: 'Sets the brush color of the object to random.',\n    set_fill_color: 'Sets the fill color of the object to the selected color.',\n    change_thickness: 'Changes the brush thickness of the object to the input value.',\n    set_thickness: 'Sets the brush thickness of the object to the input value.',\n    change_opacity: 'Changes the brush transparency of the object to the input value.',\n    change_brush_transparency: 'Changes the brush transparency of the object to the input value.',\n    set_opacity: 'Sets the brush transparency of the object to the input value.',\n    set_brush_tranparency: 'Sets the brush transparency of the object to the input value.',\n    brush_erase_all: 'Removes all the brush effects on the object.',\n    sound_something_with_block: \"Plays object's selected sound while the next block runs.\",\n    sound_something_second_with_block:\n        \"Plays object's selected sound for input seconds while the next block runs.\",\n    sound_something_wait_with_block: \"Plays object's selected sound and then runs the next block.\",\n    sound_something_second_wait_with_block:\n        \"Plays object's selected sound for the input seconds and then runs the next block.\",\n    sound_volume_change: 'Changes the volume of all sounds by the input value.',\n    sound_volume_set: 'Sets the volume of all sounds to the input value.',\n    get_sound_speed: 'Reports the sound speed.',\n    sound_speed_change: 'Changes the speed of all sounds by the input value.',\n    sound_speed_set: 'Sets the speed of all sounds to the input value.',\n    sound_silent_all: 'Stops the selected sound.',\n    play_bgm: 'Plays selected sound as background music while the next block runs.',\n    stop_bgm: 'Stops background music',\n    is_clicked: 'Checks whether mouse is clicked.',\n    is_object_clicked: 'Checks whether object is clicked.',\n    is_press_some_key: 'Checks whether the selected key is pressed.',\n    reach_something:\n        \"Checks whether the object touches the selected item. If the object touches the selected item, it is judged as 'True'.\",\n    is_type:\n        'Checks whether the input text consists of the selected characters. If the input text consists of the selected characters, it is judged as `True`.',\n    is_included_in_list: 'Checks whether selected list contains the input value.',\n    boolean_basic_operator:\n        \"Compare the two values entered.\\n= : If the value on the left and the value on the right are the same, it is judged as 'true'.\\n!= : If the value on the left and the value on the right are not the same, it is judged as 'true'.\\n> : If the value on the left is more than the value on the right, it is judged as 'true'.\\n< : If the value on the left is less than the value on the right, it is judged as 'true'.\\n≥ : If the value on the left is more than or equal to the value on the right, it is judged as 'true'\\n.≤ : If the value on the left is less than or equal to the value on the right, it is judged as 'true'.\",\n    function_create:\n        'Define a function by placing frequently used sets of blocks under this block. Place [name] next to [Define function] to give function a name. Pass on number of text values by placing [numeric/text value] block. Pass on boolean value of true or false by placing the [boolean value] block.',\n    function_field_label: 'Place inside the [Define function] block and gives function a name.',\n    function_field_string:\n        'Place inside the [Define function] block and the result depends on the input numeric/text value. Grab/copy the [numberic/text value] block in the [Define function] block and use its value in function.',\n    function_field_boolean:\n        'Place inside the [Define function] block and the result depends on the boolean value of true or false. Grab/copy the [numberic/text value] block in the [Define function] block and use its value in function.',\n    function_general: 'This is current function block or function blocks created so far.',\n    boolean_and: 'Checks whether both conditions are true.',\n    boolean_or: 'Checks whether at least one of the two conditions is true.',\n    boolean_not:\n        \"Changes the input conditions to its opposite.\\n(If the input condition is true, it returns 'False'. And if the input condition is false, it returns 'True'.)\",\n    is_boost_mode:\n        \"Checks whether the boost mode is turned on or not.\\nIf the boost mode is on, it is judged as 'True'.\",\n    is_current_device_type:\n        \"If the device that runs the project is the selected device, it is judged as 'true'.\",\n    is_touch_supported:\n        \"If the device that runs the project is a touch screen, it is judged as 'true'.\",\n    calc_basic:\n        'Reports the value of the two input numbers of quadratic operations.\\n+ : Adds two input numbers.\\n- : Subtracts two input numbers.\\n* : Multiplies two input numbers.\\n/ : Divides two input numbers.',\n    calc_rand:\n        'Selects a random value between the two input numbers. (If both of the input numbers are integers, an integer between the two numbers is selected. If either the input number is a decimal value a number up to the second decimal place is selected.)',\n    get_x_coordinate: 'Reports the x-position value of the object.',\n    get_y_coordinate: 'Reports the y-position value of the object.',\n    coordinate_mouse: 'Reports either the x/y coordinate value of the mouse pointer.',\n    coordinate_object:\n        'Reports the x/y coordinate value or various information (rotation, direction, size, etc.) of the object.',\n    quotient_and_mod:\n        'Reports the result of dividing the two input numbers.\\n- Quotient: The answer after dividing the first input number by the second input number.\\n- Remainder: The amount left over after division.',\n    get_rotation_direction: 'Reports the object’s value of direction and value of movement.',\n    calc_share: 'Reports the quotient occurring from first number divided by the second number. ',\n    calc_mod: 'Reports the remainder occurring from the first number divided by the second number.',\n    calc_operation:\n        'Reports calculated values of a variety of equations relating to input numbers.\\n(Square, Root, Sine, Cosine, Tangent, Arcsine, Arccosine, Arctangent, Log, Natural log, Decimal value, Floor value, Ceil value, Round value, Factorial value, Absolute value)',\n    get_date:\n        'Reports the values regarding the current year, month, day, day of the week and time.\\n- Year: Returns the current year.\\n- Month: Returns the current month.\\n- Day: Returns the current day.\\n- Day of the week: Returns the current day of the week as a number.\\nReturns Sunday, Monday, Tuesdays, Wednesdays, Thursdays, Fridays, Saturdays as 0, 1, 2, 3, 4, 5, 6 in turn.\\n- Time: Returns the current time in hours, minutes, and seconds, respectively.',\n    distance_something: 'Reports the distance between the object and the selected object.',\n    get_sound_duration: 'Reports the time length of the selected sound.',\n    get_user_name: 'Reports the user ID who runs the project.\\nThe value is masked for privacy.',\n    get_nickname: 'Reports the user nickname who runs the project.',\n    get_project_timer_value: 'Reports how many seconds have passed since the project started.',\n    choose_project_timer_action:\n        'Sets the status of the timer.\\n- Start : The timer starts.\\n- Stop : The timer stops.\\n- Reset : The timer resets to 0.',\n    reset_project_timer: 'Resets the timer to 0.',\n    set_visible_project_timer: 'Shows or hides the timer.',\n    ask_and_wait: 'The object asks the input text, and then receives an answer as a response.',\n    get_canvas_input_value: 'Reports the answer which is taken after the object asked.',\n    set_visible_answer: 'Hide or show the response window.',\n    combine_something: 'Combines two input texts.',\n    reverse_of_string: 'Reports the text that reversed input text.',\n    get_variable: 'Reports the value of the selected variable.',\n    change_variable: 'Adds the input value to the selected variable.',\n    set_variable: 'Sets the value of the selected variable to the input value.',\n    robotis_carCont_sensor_value:\n        \"Left connected sensor : the value of contact (1), non-contact (0).<br/>Right contact sensor: the value of contact (1), non-contact (0).<br/>Final number of sound detection : the value of the number of last live sound detection.<br/>Number of live sound detection : increases by 1 when it detects the next sound within 1 second.<br/>Right infrared sensor: the value is larger when it's closer to an object.<br/>Value of left infrared sensor calibration : the calibration value of the infrared sensor.<br/>Value of right infrared sensor calibration : the calibration value of the infrared sensor.<br/>(*Calibration value - control value of infrared sensor)\",\n    robotis_carCont_cm_led:\n        'Turns LED 1 or LED 4 among the 4 LEDs on or off. <br/>Not applicable to LED 2 and LED 3.',\n    robotis_carCont_cm_sound_detected_clear: 'Initializes the final amount of detected sound to 0.',\n    robotis_carCont_aux_motor_speed: 'Sets the speed of decelerating motor to the value of 0-1023.',\n    robotis_carCont_cm_calibration:\n        'Sets the controlling value of infrared sensor (http://support.robotis.com/ko/: automobile robot> 2. B. control infrared value).',\n    robotis_openCM70_sensor_value:\n        'Final number of sound detection : the value of the final detected sound times.<br/>Number of live sound detection : increases by 1 when it detects the next sound within 1 second.<br/>Status of user button: the value of contact (1), non-contact (0).Final number of sound detection : the value of the number of last live sound detection.<br/>Number of live sound detection : increases by 1 when it detects the next sound within 1 second.<br/>Status of user button : the value of contact (1), non-contact (0).',\n    robotis_openCM70_aux_sensor_value:\n        \"Position of servo motor: 0-1023, the value of the middle is 512.<br/>Infrared sensor : the value is larger when it's close to an object.<br/>Contact sensor: the value of contact(1), non-contact(0).<br/>CDS: 0-1023, the value is larger when it's brighter.<br/>Temperature-humidity sensor (humidity) : 0-100, the value is larger when it's more humid.<br/>Temperature-humidity sensor (temperature) : -20 - 100, the value is larger when it's higher in temperature.<br/>Temperature sensor : -20 - 100, the value is larger when it's higher in temperature.<br/>Ultrasound sensor: -<br/>Magnetic sensor : the value of contact(1), non-contact(0).<br/>Motion detector: the value of detected motion(1), non-detected motion(0).<br/>Color sensor: the value of unknown(0), white(1), black(2), red(3), green(4), blue(5), yellow(6).<br/>User device: please refer to ROBOTIS e-manual (http://support.robotis.com/ko/) for the explanation on user sensor production.\",\n    robotis_openCM70_cm_buzzer_index: 'Plays the scale for 0.1 to 5 seconds.',\n    robotis_openCM70_cm_buzzer_melody:\n        \"Plays melody.<br/>If the following sound doesn't play when repeatedly playing melodies, use the block 'flow > wait for X seconds' and execute it again.\",\n    robotis_openCM70_cm_sound_detected_clear: 'Final number of sound detection ',\n    robotis_openCM70_cm_led: 'Turns the red, green, blue LED of the device on or off.',\n    robotis_openCM70_cm_motion: 'Executes the motion downloaded on the device.',\n    robotis_openCM70_cm_autodrive_motor: 'Specifies the motor port of the autonomous driving car.',\n    robotis_openCM70_cm_autodrive_ir: 'Specifies the IR sensor port of the autonomous driving car.',\n    robotis_openCM70_cm_autodrive_speed:\n        'Perform autonomous driving at the specified speed along the lane.',\n    robotis_openCM70_aux_car_move: 'Make the robot move at the specified speed and direction.',\n    robotis_openCM70_aux_motor_speed:\n        'Sets the speed of decelerating motor to the value of 0 - 100%.',\n    robotis_openCM70_aux_servo_mode:\n        \"Sets the servo motor as wheel mode or joint mode.<br/>The same mode continues to apply once it's set.<br/>Wheel mode designates the servo motor's speed, and spins the servo motor.<br/>Joint mode moves the servo motor's position with the set servo motor speed.\",\n    robotis_openCM70_aux_servo_speed: \"Sets servo motor's speed to the value of 0 - 1023.\",\n    robotis_openCM70_aux_servo_position:\n        \"Sets servo motor's position to the value of -150 - 150 degree.<br/>Use as servo motor speed\",\n    robotis_openCM70_aux_led_module: 'Turns the LED of LED module on or off.',\n    robotis_openCM70_aux_custom:\n        'Please refer to the ROBOTIS e-manual (http://support.robotis.com/ko/) for the explanation of user sensor production.',\n    robotis_openCM70_cm_poweroff_timer:\n        \"Set the controller's auto-off timer.<br/>If there is no communication for the set amount of time, the controller will automatically turn off.\",\n    robotis_openCM70_cm_custom_value:\n        'Checks the value by directly inputting the control table address.<br/>Please refer to the ROBOTIS e-manual (http://support.robotis.com/ko/) for the explanation about control table.',\n    robotis_openCM70_cm_custom:\n        'Checks the value by directly inputting the control table address.<br/>Please refer to the ROBOTIS e-manual (http://support.robotis.com/ko/) for the explanation about control table.',\n    show_variable: 'Shows the value of the selected variable on the stage.',\n    hide_variable: 'Hides the value of the selected variable from the stage.',\n    value_of_index_from_list:\n        'Reports the item at the location of the input value on the selected list.',\n    add_value_to_list: 'Adds the input item to the end location of the selected list.',\n    remove_value_from_list:\n        'Deletes the item at the location of the input value from the selected list. ',\n    insert_value_to_list:\n        'Inserts the input item at the location of the input value on the selected list.',\n    change_value_list_index:\n        'Replaces the item at the location of the input value to the input text.',\n    length_of_list: 'Reports the number of items contained on the selected list.',\n    show_list: 'Shows the selected list on the stage.',\n    hide_list: 'Hides the selected list from the stage.',\n    text: 'Reports the text in the text box. ',\n    text_read:\n        'Reports the content of the text box or the text box itself.\\n(If there is a line break in the content, it will be returned as a space.)',\n    text_write: 'Changes the content of the text box into the input text.',\n    text_append: 'Adds the input text behind the text box.',\n    text_prepend: 'Adds the input text in front of the text box.',\n    text_flush: 'Removes all saved text in the text box.',\n    erase_all_effects: 'Removes all the effects on the object.',\n    char_at: 'Reports the letter of the input text.',\n    length_of_string: 'Reports the length of input text including space.',\n    substring:\n        'Reports the text extracted from the input text between two specified indices. (includes space)',\n    count_match_string:\n        'Reports the number of letters in a specific text in the input text case sensitively.',\n    replace_string:\n        'Reports the text where the specific text has been replaced with the input text. (distinguishes uppercase and lowercase)',\n    index_of_string: 'Reports the index of first input text in second input text. (includes space)',\n    change_string_case: 'Reports the text that converted to uppercase or lowercase.',\n    get_block_count:\n        'Reports the number of blocks used by the selected item.\\nCounts based on the blocks assembled to the start block.\\n- this project: Counts all the blocks of this project\\n- this object: Counts the blocks of this object\\n- (object): Counts the blocks of the selected object\\n- (scene): Counts the blocks of the selected scene',\n    get_boolean_value: 'Returns boolean to string.',\n    direction_relative_duration:\n        'Rotates the direction of the object at an angle of the input degrees for the input seconds.',\n    get_sound_volume: 'Reports the sound volume.',\n    sound_from_to:\n        \"Plays object's selected sound between the input seconds while the next block runs.\",\n    sound_from_to_and_wait:\n        \"Plays object's selected sound between the input seconds and then runs the next block.\",\n    Block_info: 'Block Info ',\n    Block_click_msg: 'Clicking on the block comes the description of the block . ',\n    hamster_beep: 'Plays beep sound.',\n    hamster_change_both_wheels_by:\n        'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n    hamster_change_buzzer_by:\n        'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n    hamster_change_output_by:\n        'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n    hamster_change_tempo_by:\n        'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n    hamster_change_wheel_by:\n        'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n    hamster_clear_buzzer: 'Turns off buzzer sound.',\n    hamster_clear_led: 'Turns off the left/right/both LEDs.',\n    hamster_follow_line_until:\n        'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n    hamster_follow_line_using:\n        'Moves along the black/white line by using the left/right/both floor sensors.',\n    hamster_hand_found:\n        'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n    hamster_move_backward_for_secs: 'Moves backward for the number of seconds entered.',\n    hamster_move_forward_for_secs: 'Moves forward for the number of seconds entered.',\n    hamster_move_forward_once: 'Moves one space forward on the board.',\n    hamster_play_note_for:\n        'It sounds the selected tone and octave as much as the beat you entered.',\n    hamster_rest_for: 'Rests as much as the beat you entered.',\n    hamster_set_both_wheels_to:\n        'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n    hamster_set_buzzer_to:\n        'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n    hamster_set_following_speed_to:\n        'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n    hamster_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n    hamster_set_output_to:\n        'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n    hamster_set_port_to: 'Sets the io mode of the selected external port to the selected mode.',\n    hamster_set_tempo_to:\n        'Sets the playing or resting speed to the entered BPM (beats per minute).',\n    hamster_set_wheel_to:\n        'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n    hamster_stop: 'Stops both wheels.',\n    hamster_turn_for_secs: 'Turns left/right for the number of seconds entered.',\n    hamster_turn_once: 'Turns left/right 90 degrees on the board.',\n    hamster_value:\n        'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n    roboid_hamster_beep: 'Plays beep sound.',\n    roboid_hamster_change_both_wheels_by:\n        'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n    roboid_hamster_change_buzzer_by:\n        'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n    roboid_hamster_change_output_by:\n        'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n    roboid_hamster_change_tempo_by:\n        'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n    roboid_hamster_change_wheel_by:\n        'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n    roboid_hamster_clear_buzzer: 'Turns off buzzer sound.',\n    roboid_hamster_clear_led: 'Turns off the left/right/both LEDs.',\n    roboid_hamster_follow_line_until:\n        'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n    roboid_hamster_follow_line_using:\n        'Moves along the black/white line by using the left/right/both floor sensors.',\n    roboid_hamster_hand_found:\n        'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n    roboid_hamster_move_backward_for_secs: 'Moves backward for the number of seconds entered.',\n    roboid_hamster_move_forward_for_secs: 'Moves forward for the number of seconds entered.',\n    roboid_hamster_move_forward_once: 'Moves one space forward on the board.',\n    roboid_hamster_play_note_for:\n        'It sounds the selected tone and octave as much as the beat you entered.',\n    roboid_hamster_rest_for: 'Rests as much as the beat you entered.',\n    roboid_hamster_set_both_wheels_to:\n        'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n    roboid_hamster_set_buzzer_to:\n        'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n    roboid_hamster_set_following_speed_to:\n        'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n    roboid_hamster_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n    roboid_hamster_set_output_to:\n        'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n    roboid_hamster_set_port_to:\n        'Sets the io mode of the selected external port to the selected mode.',\n    roboid_hamster_set_tempo_to:\n        'Sets the playing or resting speed to the entered BPM (beats per minute).',\n    roboid_hamster_set_wheel_to:\n        'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n    roboid_hamster_stop: 'Stops both wheels.',\n    roboid_hamster_turn_for_secs: 'Turns left/right for the number of seconds entered.',\n    roboid_hamster_turn_once: 'Turns left/right 90 degrees on the board.',\n    roboid_hamster_value:\n        'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n    roboid_turtle_button_state:\n        'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n    roboid_turtle_change_buzzer_by:\n        'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n    roboid_turtle_change_head_led_by_rgb:\n        'Adds the entered values to the current R, G, B values of the head LED, respectively.',\n    roboid_turtle_change_tempo_by:\n        'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n    roboid_turtle_change_wheel_by:\n        'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n    roboid_turtle_change_wheels_by_left_right:\n        'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n    roboid_turtle_clear_head_led: 'Turns off the head LED.',\n    roboid_turtle_clear_sound: 'Turns off sound.',\n    roboid_turtle_cross_intersection:\n        'Moves forward for a moment at the black intersection, then finds the black line and moves again.',\n    roboid_turtle_follow_line: 'Moves along the selected color line on a white background.',\n    roboid_turtle_follow_line_until:\n        'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n    roboid_turtle_follow_line_until_black:\n        'Moves along the selected color line on a white background and stops when the color sensor detects black.',\n    roboid_turtle_is_color_pattern:\n        'If the color sensor detects the selected color pattern, true, otherwise false.',\n    roboid_turtle_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n    roboid_turtle_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n    roboid_turtle_pivot_around_wheel_unit_in_direction:\n        'Pivots around the left/right wheel in the head/tail direction for the number of degrees/seconds/pulses entered.',\n    roboid_turtle_play_note: 'It sounds the selected tone and octave.',\n    roboid_turtle_play_note_for_beats:\n        'It sounds the selected tone and octave as much as the beat you entered.',\n    roboid_turtle_play_sound_times: 'Plays the selected sound as many times as entered.',\n    roboid_turtle_play_sound_times_until_done:\n        'Plays the selected sound as many times as entered, and waits for completion.',\n    roboid_turtle_rest_for_beats: 'Rests as much as the beat you entered.',\n    roboid_turtle_set_buzzer_to:\n        'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n    roboid_turtle_set_following_speed_to:\n        'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n    roboid_turtle_set_head_led_to: 'Turns the head LED to the selected color.',\n    roboid_turtle_set_head_led_to_rgb:\n        'Sets the R, G, B values of the head LED to the entered values.',\n    roboid_turtle_set_tempo_to:\n        'Sets the playing or resting speed to the entered BPM (beats per minute).',\n    roboid_turtle_set_wheel_to:\n        'Sets the speed of the left/right/both wheels to the entered value (-400 to 400%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n    roboid_turtle_set_wheels_to_left_right:\n        'Sets the speed of the left and right wheels to the entered values (-400 to 400%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n    roboid_turtle_stop: 'Stops both wheels.',\n    roboid_turtle_touching_color:\n        'If the color sensor detects the selected color, true, otherwise false.',\n    roboid_turtle_turn_at_intersection:\n        'Moves forward for a moment at the black intersection, then turns left/right/back in place, finds the black line and moves again.',\n    roboid_turtle_turn_unit_in_place:\n        'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n    roboid_turtle_turn_unit_with_radius_in_direction:\n        'Turns left/right drawing the circle of the entered radius in the head/tail direction for the number of degrees/seconds/pulses entered.',\n    roboid_turtle_value:\n        'color number: color number detected by the color sensor (range: -1 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1) <br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.',\n    turtle_button_state:\n        'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n    turtle_change_buzzer_by:\n        'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n    turtle_change_head_led_by_rgb:\n        'Adds the entered values to the current R, G, B values of the head LED, respectively.',\n    turtle_change_tempo_by:\n        'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n    turtle_change_wheel_by:\n        'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n    turtle_change_wheels_by_left_right:\n        'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n    turtle_clear_head_led: 'Turns off the head LED.',\n    turtle_clear_sound: 'Turns off sound.',\n    turtle_cross_intersection:\n        'Moves forward for a moment at the black intersection, then finds the black line and moves again.',\n    turtle_follow_line: 'Moves along the selected color line on a white background.',\n    turtle_follow_line_until:\n        'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n    turtle_follow_line_until_black:\n        'Moves along the selected color line on a white background and stops when the color sensor detects black.',\n    turtle_is_color_pattern:\n        'If the color sensor detects the selected color pattern, true, otherwise false.',\n    turtle_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n    turtle_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n    turtle_pivot_around_wheel_unit_in_direction:\n        'Pivots around the left/right wheel in the head/tail direction for the number of degrees/seconds/pulses entered.',\n    turtle_play_note: 'It sounds the selected tone and octave.',\n    turtle_play_note_for_beats:\n        'It sounds the selected tone and octave as much as the beat you entered.',\n    turtle_play_sound_times: 'Plays the selected sound as many times as entered.',\n    turtle_play_sound_times_until_done:\n        'Plays the selected sound as many times as entered, and waits for completion.',\n    turtle_rest_for_beats: 'Rests as much as the beat you entered.',\n    turtle_set_buzzer_to:\n        'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n    turtle_set_following_speed_to:\n        'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n    turtle_set_head_led_to: 'Turns the head LED to the selected color.',\n    turtle_set_head_led_to_rgb: 'Sets the R, G, B values of the head LED to the entered values.',\n    turtle_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n    turtle_set_wheel_to:\n        'Sets the speed of the left/right/both wheels to the entered value (-400 to 400%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n    turtle_set_wheels_to_left_right:\n        'Sets the speed of the left and right wheels to the entered values (-400 to 400%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n    turtle_stop: 'Stops both wheels.',\n    turtle_touching_color: 'If the color sensor detects the selected color, true, otherwise false.',\n    turtle_turn_at_intersection:\n        'Moves forward for a moment at the black intersection, then turns left/right/back in place, finds the black line and moves again.',\n    turtle_turn_unit_in_place:\n        'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n    turtle_turn_unit_with_radius_in_direction:\n        'Turns left/right drawing the circle of the entered radius in the head/tail direction for the number of degrees/seconds/pulses entered.',\n    turtle_value:\n        'color number: color number detected by the color sensor (range: -1 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1) <br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.',\n    neobot_sensor_value:\n        'Indicates the input value from ports IN1 - IN3 and the battery information as number from 0 to 255.',\n    neobot_sensor_convert_scale:\n        \"The expressed scale of the selected port's change of input value as the value of a particular scale can be adjusted.\",\n    neobot_left_motor: 'Sets the wheel direction and speed of the motor connected to L motor port.',\n    neobot_stop_left_motor: 'Stops the motor connected to L motor port.',\n    neobot_right_motor:\n        'Sets the wheel direction and speed of the motor connected to R motor port.',\n    neobot_stop_right_motor: 'Stops the motor connected to R motor port.',\n    neobot_all_motor:\n        'The speed, time, and direction towards front, back, left and right, when connecting 2 motors to L and R motor ports can be set and used as wheels. ',\n    neobot_stop_all_motor: 'Stops the motor connected to both L and R motor ports.',\n    neobot_set_servo:\n        'The angle within 0 - 180 degrees when connecting servo motor to OUT1 - OUT3 can be adjusted',\n    neobot_set_output:\n        'The output voltage when connecting lighting block and electronic circuit to OUT1 - OUT3 can be set.</br>0 indicates 0V, and 1 ~ 255 indicates 2.4 ~ 4.96V.',\n    neobot_set_fnd: 'Numbers from 0 to 99 with FND can be indicated.',\n    neobot_set_fnd_off: 'Number indicated on FND can be turned off.',\n    neobot_play_note_for:\n        'Notes in semitone units of the melody can be played by utilizing frequency oscillation. ',\n    rotate_by_angle_dropdown: 'Rotates the object by the input number of degrees.',\n    chocopi_control_button:\n        'This block will be true if the button is pressed.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n    chocopi_control_event:\n        'You can attach blocks to process when the button is pressed or released <br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n    chocopi_control_joystick:\n        'Joystick X,Y and potentiometer has range of  0~4095.<br/>so, around 2047 will be center value.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n    chocopi_dc_motor:\n        \"Two DC motors can be connected to 'DC motor' module<br/> The motor will be supplied with maximum 5V.<br/>Maximum value is 100 (100%), is negative value is used then it will rotate opposite direction.<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n    chocopi_led:\n        'LED number start from 1 and is the connecting order from the LED module.<br/>You can assign RGB values from 0 to 255<br/>RGB(Red Green Blue) order<br/>To watch an LED with bright light can be painful,<br/>so, please use small number like 0 to 5.<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n    chocopi_motion_photogate_event:\n        \"Two photogates can be connected to 'Motion' module<br/>A photogate is a device with light sensor facing light source in opposite side<br/>You can attach blocks when an object blocks or unblocks light sensor<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n    chocopi_motion_photogate_status:\n        \"Two photogates can be connected to 'Motion' module<br/>A photogate is a device with light sensor facing light source in opposite side<br/>This block will be <b>true if an object blocks sensor</b><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n    chocopi_motion_photogate_time:\n        \"Two photogates can be connected to 'Motion' module<br/>A photogate is a device with light sensor facing light source in opposite side<br/>This block will have the time when an object blocked or unblocked the sensor<br/>It can measure time with resolution of 1/10000 sec<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n    chocopi_motion_value:\n        \"'Motion' module has three infrared sensors<br/>The value has range of 0~4095, the more reflection from object, the smaller the value is<br/>It can be used to measure approximate distance between the sensor and an object <br/>Acceleration and angular acceleration value ranges from -32768 to 32767.<br/>You can measure inclination of the sensor using these values.<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n    chocopi_sensor:\n        'Temperature value is Celsius.<br/>Relative humidity value ranges from 0 to 100%.<br/>Light value ranges 0~4095 in log scale.<br/>Analog value ranges from 0 to 4095.<br/><br/>Port number(P1~P8) is automatically selected internally.<br>It is needed only when multiple modules with the same kind are used',\n    chocopi_servo_motor:\n        \"'Servo' module can be connected to four servo motors<br/>Servo motors are provided with 5V<br/>You can assign 0~200 in degree unit.<br/>If a contineous rotational servo motor is connected, it's speed is determined by the degree value.<br/>Center value is from 90 to 100 varying by motor model.<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n    chocopi_touch_event:\n        'Touch module has #1~12 connecting pads.<br/>You can attach block to process when these pads are touched or untouched.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n    chocopi_touch_status:\n        'It will be true if the pad is touched.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n    chocopi_touch_value:\n        \"The value will be smaller if the capacitance of the obeject is larger.<br/>If many people hold each other's hand and touch, the value will be smaller<br/>'Capacitance' means how many electric particles the object can hold.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n    boolean_and_or:\n        'AND: Checks whether both conditions are true.\\nOR: Checks whether at least one of the two conditions is true.',\n    check_weather:\n        '\\nChecks whether the weather information of the selected date and region matches the actual weather conditions.',\n    check_finedust:\n        '\\nChecks whether the current fine dust information of the selected region matches the actual fine dust grade.',\n    get_weather_data:\n        '\\nReports various weather information values (the lowest temperature, the highest temperature, humidity, precipitation, precipitation probability, wind speed) of the selected date and region.',\n    get_current_weather_data:\n        '\\nReports the current weather information (temperature, fine dust grade) of the selected region.',\n    get_today_temperature: '\\nReports the today temperature of selected area and time zone.',\n    check_city_weather:\n        'Checks whether the weather information of the selected date and region matches the actual weather conditions.',\n    check_city_finedust:\n        'Checks whether the current fine dust information of the selected region matches the actual fine dust grade.',\n    get_city_weather_data:\n        'Reports various weather information values (the lowest temperature, the highest temperature, humidity, precipitation, precipitation probability, wind speed) of the selected date and region.',\n    get_current_city_weather_data:\n        'Reports the current weather information (temperature, fine dust grade) of the selected region.',\n    get_today_city_temperature: 'Report the today temperature of selected area and time zone.',\n    get_cur_weather: '\\nReports the current weather in the selected area.',\n    get_cur_wind: '\\nReports the current wind direction in the selected area.',\n    get_cur_weather_data:\n        '\\nReports the current weather information in the selected area.\\n- Weather information : temperature(℃), fine dust concentration(PM10, ㎍)',\n    check_cur_weather:\n        \"\\nChecks whether the current weather in the selected area matches the selected weather conditions. If so, it is judged as 'True'.\",\n    check_cur_finddust:\n        \"\\nChecks whether the current fine dust grade in the selected area matches the selected fine dust grade. If so, it is judged as 'True'.\",\n    get_day_weather: '\\nReports the daily weather in the selected area.',\n    get_day_weather_data:\n        '\\nReports the daily weather information in the selected area.\\n- Weather information: the lowest temperature(℃), the highest temperature(℃), humidity(%), precipitation(mm), precipitation probability(%), wind speed(m/s)',\n    check_day_weather:\n        \"\\nChecks whether the daily weather in the selected area matches the selected weather conditions. If so, it is judged as 'True'. \",\n    get_time_weather: '\\nReports the weather by hour(every 3 hours) in the selected area.',\n    get_time_weather_data:\n        '\\nReports the weather information by hour(every 3 hours) in the selected area.\\n- Weather information: the lowest temperature(℃), the highest temperature(℃), humidity(%), precipitation(mm), precipitation probability(%), wind speed(m/s)',\n    check_time_weather:\n        \"\\nChecks whether the weather by hour in the selected area matches the selected weather conditions. If so, it is judged as 'True'. \",\n    count_festival:\n        'Translate the input text into the selected language. You can enter up to 20 charactors. ',\n    get_festival_info: 'Detects the language of the input text. You can enter up to 20 charactors.',\n    get_translated_string: 'The number of events held on the selected date and region.',\n    check_language:\n        'Reports the information(Title, area, start date, end date, address, overview, homepage) about events held on the selected date and region.',\n    count_disaster_behavior:\n        \"\\nThe number of behavior-guideline's when selected natural disaster occurs.\",\n    get_disaster_behavior:\n        '\\nReports the information about behavior-guidelines when selected natural disaster occurs.',\n    count_lifeSafety_behavior:\n        \"\\nThe number of behavior-guideline's when selected life problem occurs.\",\n    get_lifeSafety_behavior:\n        '\\nReports the information about behavior-guidelines when selected life problem occurs.',\n    count_disaster_guideline:\n        'The number of guidelines in the selected natural disaster.\\n\\n- Natural disaster: typhoon, flood, heavy rain, strong wind, heavy snow, cold wave, rough seas, yellow dust, heat wave, drought, earthquake, tsunami, tidal wave, landslide, volcanic eruption',\n    get_disaster_guideline:\n        'Reports the information about the guidelines of the selected natural disaster.\\n\\n- Natural disaster: typhoon, flood, heavy rain, strong wind, heavy snow, cold wave, rough seas, yellow dust, heat wave, drought, earthquake, tsunami, tidal wave, landslide, volcanic eruption',\n    count_social_disaster_guideline:\n        'Reports the information about the guidelines of the selected social disaster.\\n\\n- Social disaster: marine pollution, large-scale water pollution, water shortage, utility tunnel disaster, livestock disease, infectious disease, railway and subway, financial IT system, nuclear power plant accident, chemical accident, fire, wildfire, building collapse, dam collapse, explosion, aircraft accident, CBRN incident, power outage, electricity·gas, passenger ship, water accident, terrorism, power shortage',\n    get_social_disaster_guideline:\n        'Reports the information about the guidelines of the selected social disaster.\\n\\n- Social disaster: marine pollution, large-scale water pollution, water shortage, utility tunnel disaster, livestock disease, infectious disease, railway and subway, financial IT system, nuclear power plant accident, chemical accident, fire, wildfire, building collapse, dam collapse, explosion, aircraft accident, CBRN incident, power outage, electricity·gas, passenger ship, water accident, terrorism, power shortage\"',\n    count_safety_accident_guideline:\n        \"The number of methods in the selected life safety accident.\\n\\n- Life safety accidents: first aid, CPR, fire extinguisher, food poisoning, hiking, children's playground, missing·kidnapping, sexual violence, school violence, domestic violence, detention·abduction, traffic accident, elevator, fine dust, fire hydrant, home safety inspection\",\n    get_safety_accident_guideline:\n        \"first aid, CPR, fire extinguisher, food poisoning, hiking, children's playground, missing·kidnapping, sexual violence, school violence, domestic violence, detention·abduction, traffic accident, elevator, fine dust, fire hydrant, home safety inspection\",\n    read_text: 'Read the entered text in setted voice.',\n    set_tts_property:\n        'Set the selected voice to selected speed and selected pitch. \\n The selected voice will be set up to selected speed and selected pitch.',\n    read_text_wait_with_block:\n        'Read the entered text in setted voice then the next block runs after the reading finished.',\n    check_microphone: \"If the microphone is connected to the computer, it is judged as 'True'.\",\n    speech_to_text_convert: 'Recognizes speech recorded through the microphone.',\n    timed_speech_to_text_convert:\n        'Recognizes speech recorded through the microphone for the input seconds.',\n    set_visible_speech_to_text: 'Shows or hides the recognized speech on the screen.',\n    speech_to_text_get_value:\n        \"Reports the value of the person's speech to text. If no speech is input or an error occurs during recognition, it will report null values.\",\n    get_microphone_volume: 'Reports the volume of sound input through microphone.',\n    video_draw_webcam: 'Show or hide the video screen. (IE / iOS Not Supported)',\n    video_check_webcam:\n        'Check whether video is connected with the computer. (IE / iOS Not Supported)',\n    video_set_camera_option: 'Set the selected effect to the video screen by the input value.',\n    video_flip_camera:\n        'Flips the video screen horizontally or vertically. (IE / iOS Not Supported)',\n    video_toggle_model:\n        \"Start or stop the selected recognition model. Face Recognition: Recognizes a person's face to know where the eyes, nose, mouth, and ear are located, or the expected gender, age, and emotion. Human Recognition: Recognizes a person's body to know where each part is located Object Recognition: Shows the recognized object type. (Person or thing) (IE / iOS Not Supported)\",\n    video_toggle_ind:\n        'Show location and index of the detected humans/faces/objects on the screen. (IE / iOS Not Supported)',\n    video_number_detect:\n        'Reports number of humans/faces/objects detected on the video screen. (IE / iOS Not Supported)',\n    video_detected_face_info:\n        'Reports the estimated value of the selected face area among the faces in the input order. If it is not recognized, it is outputted as 0 unconditionally. (Gender, Age, Emotion)  (IE / iOS Not Supported)',\n    video_motion_value:\n        'Reports the motion or direction value detected on the selected object or screen.  (IE / iOS Not Supported)',\n    video_face_part_coord:\n        'Reports the position value of the selected face area among the faces in the input order. If it is not recognized, it is outputted as 0 unconditionally. (Left eye, Right eye, Nose, Left mouse, Right mouse, Top Lip, Bottom Lip)  (IE / iOS Not Supported)',\n    video_body_part_coord:\n        'Reports number of human detected on the video screen. (Face, Right shoulder, Right elbow, Right wrist, Left shoulder, Left elbow, Left wrist, Right hip, Right knee, Right ankle, Left hip, Left knee, Left ankle)  (IE / iOS Not Supported)',\n    append_row_to_table:\n        'Adds a row(column) to the end of the selected table. All cell values ​​in the added row(column) are 0.',\n    insert_row_to_table:\n        'Adds a row(column) to the entered order of the selected table. All cell values ​​in the added row(column) are 0. The rows(columns) after the added row(column) are pushed back one by one.',\n    delete_row_from_table: 'Deletes the row(column) in the entered order of the selected table.',\n    set_value_from_table:\n        'Replaces the attribute of the entered row with the values ​​entered in the selected table.',\n    save_current_table:\n        'Save the table as it is. Even if you stop the project, your changes in the table are maintained.',\n    get_table_count: 'The number of rows(columns) in the selected table.',\n    get_value_from_table:\n        'The selected attribute value of the entered row in the selected table. Instead of an attribute value block, you can also combine a value block (meaning a column).',\n    get_value_from_last_row:\n        'The selected attribute value of the last row in the selected table. Instead of an attribute value block, you can also combine a value block (meaning a column).',\n    calc_values_from_table:\n        'Reports calculated value of the selected attributes in the selected table. (Sum, Maximum, Minimum, Average, Standard deviation, Median)',\n    open_table: 'Open the window of the selected table.',\n    open_table_wait: 'Open the window of the selected table for the seconds entered.',\n    open_table_chart: 'Opens the chart of the selected table.',\n    close_table_chart: 'Close the table chart.',\n    get_coefficient:\n        'Correlation coefficient between two attributes in the selected table.\u000bThe closer the correlation coefficient is to 1 (-1), the stronger the positive (negative) linear correlation.',\n    set_value_from_cell: 'Replaces the cell with the values ​​entered in the selected table.',\n    get_value_from_cell: 'The cell value in the selected table.',\n    get_value_v_lookup:\n        'Searches for a value in selected column of a table and returns a corresponding value from a specified column in the same row.',\n    change_rgb_to_hex:\n        'Reports the value of the entered red, green, and blue values converted to HEX value.',\n    change_hex_to_rgb: 'Reports the HEX value entered converted to either red, green, or blue.',\n    media_pipe_video_screen: 'Shows or hides the video screen.',\n    media_pipe_switch_camera: 'Switches the camera that films the video.',\n    check_connected_camera: \"If the camera is connected to the computer, it is judged as 'True'.\",\n    media_pipe_flip_camera: 'Flips the video screen horizontally or vertically.',\n    media_pipe_set_opacity_camera:\n        'Sets the transparency effect of video screen to the input value. It can be set in the range from 0 to 100.\\n(The default value is 50. Values under 0 is treated as 0 and over 100 is treated as 100.)',\n    media_pipe_motion_value:\n        'Reports the motion or direction value detected on the selected object or screen.\\n- Motion: The larger and faster the movement, the larger the value.\\n- Direction: Positive when moving right or up, and negative when moving left or down',\n    when_pose_landmarker: 'When human detected, the connected blocks below will run.',\n    pose_landmarker:\n        'Start or stop the human detection model.\\n- Human Detection: Detects a human and determines where each body parts are located.',\n    draw_detected_pose:\n        'Shows or hides the location and order of the detected humans on the screen.',\n    check_detected_pose: \"If the human is detected, it is judged as 'True'.\",\n    count_detected_pose: 'Reports the number of the humans detected on the video screen.',\n    locate_to_pose: 'Moves the object to the position of the selected body part.',\n    locate_time_to_pose:\n        'Moves the object to the position of the selected body part for the input seconds.',\n    axis_detected_pose:\n        'Reports the location value of the selected body part of the human in the order entered.\\n(Body parts: nose, left eye (inner), left eye, left eye (outer), right eye (inner), right eye, right eye (outer), left ear, right ear, mouth (left), mouth (right), left shoulder, right shoulder, left elbow, right elbow, left wrist, right wrist, left pinky, right pinky, left index, right index, left thumb, right thumb, left hip, right hip, left knee, right knee, left ankle, right ankle, left heel, right heel, left foot index, right foot index)',\n    when_face_landmarker: 'When face detected, the connected blocks below will run.',\n    face_landmarker:\n        \"Start or stop the face detection model.\\n- Face Detection: Detects a human's face and determines where the eyes, nose, mouth, and ear are located.\",\n    draw_detected_face:\n        'Shows or hides the location and order of the detected faces on the screen.',\n    check_detected_face: \"If the face is detected, it is judged as 'True'.\",\n    count_detected_face: 'Reports the number of the faces detected on the video screen.',\n    locate_to_face: 'Moves the object to the position of the selected face part.',\n    locate_time_to_face:\n        'Moves the object to the position of the selected body part for the input seconds.',\n    check_detected_gender: \"If the selected face is the selected gender, it is judged as 'True'.\",\n    check_compare_age:\n        \"If the age of the selected face matches the formula, it is judged as 'True'.\",\n    check_detected_emotion: \"If the selected face is the selected emotion, it is judged as 'True'.\",\n    axis_detected_face:\n        'Reports the location value of the selected face area of the face in the order entered. (Face area: left eye, right eye, nose, left corner of lips, right corner of lips, upper lip, lower lip)',\n    get_detected_face_value:\n        'Reports the estimated value of the gender/age/emotion of the face in the order entered. If it is not detected, it returns 0.',\n    when_object_detector: 'When object detected, the connected blocks below will run.',\n    object_detector:\n        'Start or stop the object detection model.\\n- Object Detection: Detects the type of object.',\n    draw_detected_object:\n        'Shows or hides the location and order of the detected object on the screen.',\n    check_detected_object: \"If the object is detected, it is judged as 'True'.\",\n    count_detected_object: 'Reports the number of the objects detected on the video screen.',\n    is_detected_among_objects: \"If the selected object is detected, it is judged as 'True'.\",\n    when_hand_detection: 'When hand detected, the connected blocks below will run.',\n    hand_detection:\n        'Start or stop hand detection model.\\n- Hand Detection: Detects a human’s hand and determines where each hand parts are located.',\n    draw_detected_hand: 'Shows or hides the location of the hand on the screen.',\n    check_detected_hand: \"If the hand is detected, it is judged as 'True'.\",\n    count_detected_hand: 'Reports the number of hand detected on the video screen.',\n    locate_to_hand: 'Moves the object to the position of the selected part of the hand.',\n    locate_time_to_hand:\n        'Moves the object to the position of the selected part of the hand for the input seconds.',\n    axis_detected_hand:\n        'Reports the location value of the selected part of the hand in the order entered.',\n    is_which_hand:\n        \"If the hand in the order you entered is the selected hand, it is judged as 'True'.\",\n    get_which_hand: 'Reports the value of the hand in the order you entered.',\n    is_which_gesture:\n        \"If the hand in the order you entered is the gesture you selected, it is judged as 'True'.\",\n    get_which_gesture: 'Reports the gesture of the hand in the order you entered.',\n    text_change_effect: 'Applies the selected text effect in the text box.',\n    text_change_font: 'Changes the text of the box to the selected font.',\n    text_change_font_color: 'Changes the text in the box to the selected color.',\n    text_change_bg_color: 'Changes the text box to the selected background color.',\n    insert_data_for_test: 'Enter data and recognize it as a trained model.',\n    video_capture_for_image_test:\n        'Classifies or stops image data taken through the camera to the model you learned.',\n    insert_text_block_for_test: 'Enter data and recognize it as a trained model.',\n    test_result:\n        'The value of the result that the model recognizes the data entered. The value is expressed by the class name (text) of the model.',\n    accuracy_of_result:\n        'The reliability value for the selected class of the data entered. The value is expressed as a probability (number).',\n    is_group:\n        \"Determine 'True' if the recognition result of the data entered is the selected class.\",\n    model_is_trained:\n        \"If the model has trained, it is determined as 'True'. If the model is being trained or hasn't trained, it is determined as 'False'.\",\n    set_train_visible: 'Shows or hides the window displaying the state of the model on the screen.',\n    set_train_chart:\n        'Opens or closes a chart window showing the entered data and clusters of learned models in a two-dimensional coordinate plane.',\n    set_regression_option:\n        \"Change the learning conditions of the model. The changed learning conditions take effect when the model is re-learned with the 'Re-learn Model' block.\",\n    get_regression_predict_1:\n        'Returns the value predicted by the model with the key properties entered.',\n    get_regression_predict_2:\n        'Returns the value predicted by the model with the key properties entered.',\n    get_regression_predict_3:\n        'Returns the value predicted by the model with the key properties entered.',\n    get_regression_predict_4:\n        'Returns the value predicted by the model with the key properties entered.',\n    get_regression_predict_5:\n        'Returns the value predicted by the model with the key properties entered.',\n    get_regression_predict_6:\n        'Returns the value predicted by the model with the key properties entered.',\n    get_regression_accuracy: \"Returns the model's coefficient of determination as a value.\",\n    set_cluster_option_k:\n        \"Sets the number of clusters to the entered value. The number of clusters changed will take effect when the model is re-learned with the 'Re-learn Model' block.\",\n    set_cluster_option_centroids:\n        \"Replace the cluster's initial center point criteria with the selected criteria. The center point criteria that you changed will take effect when you re-learn the model with the 'Re-learn Model' block.\",\n    get_cluster_centriod_count: 'Returns the number of clusters in the model as values.',\n    get_cluster_centriod_value:\n        'Returns the core properties for the center point of the specified cluster. If you have multiple core properties, you can select them from the list box.',\n    get_cluster_centriod_index_1:\n        'Returns which cluster the model belongs to, if any, to, the core property entered. Values are represented by text (cluster name).',\n    get_cluster_centriod_index_2:\n        'Returns which cluster the model belongs to, if any, to, the core property entered. Values are represented by text (cluster name).',\n    get_cluster_centriod_index_3:\n        'Returns which cluster the model belongs to, if any, to, the core property entered. Values are represented by text (cluster name).',\n    get_cluster_centriod_index_4:\n        'Returns which cluster the model belongs to, if any, to, the core property entered. Values are represented by text (cluster name).',\n    get_cluster_centriod_index_5:\n        'Returns which cluster the model belongs to, if any, to, the core property entered. Values are represented by text (cluster name).',\n    get_cluster_centriod_index_6:\n        'Returns which cluster the model belongs to, if any, to, the core property entered. Values are represented by text (cluster name).',\n    set_number_learning_option_k:\n        \"Sets the number of neighbors to the entered value. The number of neighbors changed will take effect when the model is re-learned with the 'Re-learn Model' block.\",\n    get_number_learning_predict_1:\n        'The value that classifies the entered data in the model. The value is represented by the class name (text) of the model.',\n    get_number_learning_predict_2:\n        'The value that classifies the entered data in the model. The value is represented by the class name (text) of the model.',\n    get_number_learning_predict_3:\n        'The value that classifies the entered data in the model. The value is represented by the class name (text) of the model.',\n    get_number_learning_predict_4:\n        'The value that classifies the entered data in the model. The value is represented by the class name (text) of the model.',\n    get_number_learning_predict_5:\n        'The value that classifies the entered data in the model. The value is represented by the class name (text) of the model.',\n    get_number_learning_predict_6:\n        'The value that classifies the entered data in the model. The value is represented by the class name (text) of the model.',\n    get_number_learning_predict_param_1:\n        'The classification confidence value for the selected class of data entered. Values are expressed numerically.',\n    get_number_learning_predict_param_2:\n        'The classification confidence value for the selected class of data entered. Values are expressed numerically.',\n    get_number_learning_predict_param_3:\n        'The classification confidence value for the selected class of data entered. Values are expressed numerically.',\n    get_number_learning_predict_param_4:\n        'The classification confidence value for the selected class of data entered. Values are expressed numerically.',\n    get_number_learning_predict_param_5:\n        'The classification confidence value for the selected class of data entered. Values are expressed numerically.',\n    get_number_learning_predict_param_6:\n        'The classification confidence value for the selected class of data entered. Values are expressed numerically.',\n    is_number_learning_group_1:\n        'If the classification result of the entered data is a class of your choice, determine True.',\n    is_number_learning_group_2:\n        'If the classification result of the entered data is a class of your choice, determine True.',\n    is_number_learning_group_3:\n        'If the classification result of the entered data is a class of your choice, determine True.',\n    is_number_learning_group_4:\n        'If the classification result of the entered data is a class of your choice, determine True.',\n    is_number_learning_group_5:\n        'If the classification result of the entered data is a class of your choice, determine True.',\n    is_number_learning_group_6:\n        'If the classification result of the entered data is a class of your choice, determine True.',\n    video_change_cam: 'Change the camera you are filming.',\n    video_set_camera_opacity_option:\n        'Set the transparency effect to the video screen by the input value.(IE / iOS Not Supported)',\n    video_is_model_loaded: 'Check whether human/face/object is detected. (IE / iOS Not Supported)',\n    video_object_detected: 'Check whether selected object is recognized. (IE / iOS Not Supported)',\n    target_project: 'Target project',\n    study_goal: 'Learning objectives',\n    show_hint: 'Hints',\n};\nLang.AiLearning = {\n    equation: 'Equation',\n    predict: 'Predict',\n    cluster_number: 'Cluster',\n    centriod: 'Centriod',\n    class: 'Class',\n    show: 'Show',\n    hide: 'Hide',\n    open: 'Open',\n    close: 'Close',\n    start: 'Start',\n    stop: 'Stop',\n    probability: 'Reliability',\n    neighbor_count: 'Neighbor count',\n    cluster_option_centroids_kmpp: 'Furthest',\n    cluster_option_centroids_random: 'Random',\n    model_attr_str: 'Property',\n    model_status_0: 'Status: Ready',\n    model_status_1: 'Status: Training',\n    model_status_2: 'Status: Trained',\n    model_status_3: 'Status: No Model',\n    train_param_learningRate: 'Learning Rate',\n    train_param_epochs: 'Epoch',\n    train_param_validationRate: 'Validation Rate',\n    chart_title: 'Model chart',\n    trained_table_postfix: 'Trained',\n    train_param_error: 'If table column information has changed, re-learning is not possible.',\n};\nLang.Category = {\n    entrybot_friends: 'Entrybot friends',\n    people: 'People',\n    animal: 'Animal',\n    animal_flying: 'Flying',\n    animal_land: 'Land',\n    animal_water: 'Water',\n    animal_others: 'Others',\n    plant: 'Plant',\n    plant_flower: 'Flowers',\n    plant_grass: 'Grass',\n    plant_tree: 'Tree',\n    plant_others: 'Others',\n    vehicles: 'Vehicles',\n    vehicles_flying: 'Flying',\n    vehicles_land: 'Land',\n    vehicles_water: 'Water',\n    vehicles_others: 'Others',\n    architect: 'Building',\n    architect_building: 'Structure',\n    architect_monument: 'Monument',\n    architect_others: 'Others',\n    food: 'Food',\n    food_vegetables: 'Fruits/Vegetables',\n    food_meat: 'Meat',\n    food_drink: 'Drink',\n    food_others: 'Others',\n    environment: 'Environment',\n    environment_nature: 'Nature',\n    environment_space: 'Space',\n    environment_others: 'Others',\n    stuff: 'Things',\n    stuff_living: 'Living',\n    stuff_hobby: 'Hobby',\n    stuff_others: 'Others',\n    fantasy: 'Fantasy',\n    interface: 'Interface',\n    interface_website: 'Website',\n    interface_game: 'Game',\n    interface_others: 'Others',\n    background: 'Background',\n    background_outdoor: 'Outdoor',\n    background_indoor: 'Indoor',\n    background_nature: 'Nature',\n    background_others: 'Others',\n};\nLang.Device = {\n    arduino: 'arduino',\n    hamster: 'hamster',\n    roboid: 'roboid',\n    turtle: 'turtle',\n    albert: 'albert',\n    robotis_carCont: '',\n    robotis_openCM70: '',\n    sensorBoard: 'Entry Sensor Board',\n    trueRobot: 'TrueTrueRobot',\n    CODEino: 'CODEino',\n    bitbrick: 'bitbrick',\n    creamo: 'creamo',\n    playcode: 'playcode',\n    funboard: 'funboard',\n    bitBlock: 'bitBlock',\n    xbot_epor_edge: 'XBOT',\n    dplay: 'DPLAY',\n    iboard: 'iboard',\n    nemoino: 'NEMOino',\n    ev3: 'EV3',\n    robotori: 'robotori',\n    smartBoard: 'smartBoard',\n    chocopi: 'ChocoPi',\n    rokoboard: 'rokoboard',\n    altino: 'altino',\n    mechatro: 'mechatro',\n};\nLang.General = {\n    turn_on: 'turn on',\n    turn_off: 'turn off',\n    left: 'left',\n    right: 'right',\n    param_string: 'string',\n    both: 'both',\n    transparent: 'transparent',\n    black: 'black',\n    brown: 'brown',\n    red: 'red',\n    yellow: 'yellow',\n    green: 'green',\n    skyblue: 'sykblue',\n    blue: 'blue',\n    purple: 'purple',\n    white: 'white',\n    note_c: 'C',\n    note_d: 'D',\n    note_e: 'E',\n    note_f: 'F',\n    note_g: 'G',\n    note_a: 'A',\n    note_b: 'B',\n    questions: 'Question',\n    clock: 'clock',\n    counter_clock: 'counterclock',\n    font_size: 'font size',\n    second: '&quot;',\n    alert_title: 'Alert',\n    confirm_title: 'Confirm',\n    update_title: 'Alert',\n    recent_download: 'Download',\n    recent_download2: 'Download the latest version',\n    latest_version: 'You are running the latest version.',\n    dont_show_again: 'Do not show this again',\n    apply: 'Apply',\n    clear: 'Clear',\n};\nLang.Fonts = {\n    jeju_hallasan: 'Hallasan',\n    gothic_coding: 'GothicCoding',\n    batang: 'Batang',\n    gothic: 'NanumGothic',\n    myeongjo: 'NanumMyeongjo',\n    pen_script: 'NanumPenScript',\n    square_round: 'NanumSquareRound',\n    jalnan: 'Jalnan',\n    designhouse: 'Designhouse',\n    malssami815: 'Malssami815',\n    dunggeunmo: 'DungGeunMo',\n    hs_bombaram: 'HS Bombaram',\n    yisunshin: 'YiSunShin',\n    goyang: 'Goyang',\n    flower_road: 'SangSangFlowerRoad',\n    uhbeemysen: 'UhBeemysen',\n    sd_comic_stencil: 'SD Comicstencil',\n    sd_childfundkorea: 'SD Childfundkorea',\n    sd_cinema_theater: 'SD CinemaTheater',\n    sd_mapssi: 'SD Mapssi',\n    sd_shabang: 'SD Shabang',\n    sd_woodcarving: 'SD Woodcarving',\n    sd_yongbi: 'SD Yongbi',\n    maruburi: 'MaruBuri',\n    nanumbarunpen: 'NanumBarunpen.',\n    notosans: 'NotoSans',\n    d2coding: 'D2Coding',\n};\nLang.Hw = {\n    note: 'note',\n    leftWheel: 'left wheel',\n    rightWheel: 'right wheel',\n    leftEye: 'left eye',\n    rightEye: 'right eye',\n    led: 'LED',\n    led_en: 'LED',\n    body: 'body',\n    front: ' front',\n    port_en: 'port',\n    port_ko: '',\n    sensor: 'sensor',\n    light: 'light',\n    temp: 'temp',\n    switch_: 'sw_',\n    right_ko: '',\n    right_en: 'R',\n    left_ko: '',\n    left_en: 'L',\n    up_ko: '',\n    up_en: 'U',\n    down_ko: '',\n    down_en: 'D',\n    output: 'output',\n    left: 'left',\n    right: 'right',\n    sub: 'servo',\n    motor: 'motor',\n    '': '',\n    buzzer: 'buzzer',\n    IR: 'infrared',\n    acceleration: 'acceleration',\n    analog: 'analog',\n    angular_acceleration: 'angular acceleration',\n    button: 'button',\n    humidity: 'humidity',\n    joystick: 'joystick',\n    port: 'port',\n    potentiometer: 'potentiometer',\n    servo: 'servo',\n};\nLang.template = {\n    albert_hand_found: 'hand found?',\n    albert_is_oid_value: '%1 oid %2?',\n    albert_value: '%1',\n    albert_move_forward_for_secs: 'move forward for %1 secs %2',\n    albert_move_backward_for_secs: 'move backward for %1 secs %2',\n    albert_turn_for_secs: 'turn %1 for %2 secs %3',\n    albert_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n    albert_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n    albert_change_wheel_by: 'change %1 wheel by %2 %3',\n    albert_set_wheel_to: 'set %1 wheel to %2 %3',\n    albert_stop: 'stop %1',\n    albert_set_pad_size_to: 'set board size to width: %1 height: %2 %3',\n    albert_move_to_x_y_on_board: 'move to x: %1 y: %2 on board %3',\n    albert_set_orientation_on_board: 'set orientation to %1 degrees on board %2',\n    albert_set_eye_to: 'set %1 eye to %2 %3',\n    albert_clear_eye: 'clear %1 eye %2',\n    albert_body_led: 'turn %1 body led %2',\n    albert_front_led: 'turn %1 front led %2',\n    albert_beep: 'beep %1',\n    albert_change_buzzer_by: 'change buzzer by %1 %2',\n    albert_set_buzzer_to: 'set buzzer to %1 %2',\n    albert_clear_buzzer: 'clear buzzer %1',\n    albert_play_note_for: 'play note %1 %2 for %3 beats %4',\n    albert_rest_for: 'rest for %1 beats %2',\n    albert_change_tempo_by: 'change tempo by %1 %2',\n    albert_set_tempo_to: 'set tempo to %1 bpm %2',\n    albert_move_forward: 'move forward %1',\n    albert_move_backward: 'move backward %1',\n    albert_turn_around: 'turn %1 %2',\n    albert_set_led_to: 'set %1 led %2 %3',\n    albert_clear_led: 'clear %1 led %2',\n    albert_change_wheels_by: '%1 %2 %3',\n    albert_set_wheels_to: '%1 %2 %3',\n    arduino_text: '%1',\n    arduino_get_sensor_number: '%1  ',\n    arduino_get_port_number: '%1  ',\n    arduino_get_digital_toggle: '%1  ',\n    arduino_get_pwm_port_number: '%1  ',\n    arduino_get_number_sensor_value: 'Analog %1 Sensor value  ',\n    arduino_ext_get_analog_value: 'Analog %1 Sensor value',\n    arduino_ext_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n    arduino_ext_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n    arduino_ext_toggle_led: 'Digital %1 Pin %2 %3',\n    arduino_ext_digital_pwm: 'Digital %1 Pin %2 %3',\n    arduino_ext_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n    arduino_ext_set_servo: 'Set servo pin %1 angle as %2 %3',\n    arduino_ext_get_digital: 'Digital %1 Sensor value',\n    blacksmith_get_analog_value: 'Read analog %1 pin sensor value',\n    blacksmith_get_analog_mapping: 'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\n    blacksmith_get_digital_bluetooth: 'Bluetooth RX 2 value',\n    blacksmith_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n    blacksmith_get_digital_toggle: 'Digital %1 pin sensor value',\n    blacksmith_set_digital_toggle: 'Digital %1 pin %2 %3',\n    blacksmith_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n    blacksmith_set_digital_servo: 'Set servo pin %1 angle as %2 %3',\n    blacksmith_set_digital_buzzer: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n    blacksmith_set_digital_lcd: 'LCD %1 line %2 appear %3',\n    blacksmith_set_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\n    dplay_get_number_sensor_value: 'Analog %1 Sensor value  ',\n    nemoino_get_number_sensor_value: 'Analog %1 Sensor value  ',\n    sensorBoard_get_number_sensor_value: 'Analog %1 Sensor value  ',\n    truetrue_get_accsensor: '3-AXIS Accelerometer %1 Sensor value',\n    truetrue_get_bottomcolorsensor: 'Bottom Color %1 Sensor value',\n    truetrue_get_frontcolorsensor: 'Front Color %1 Sensor value',\n    truetrue_get_linesensor: 'Line %1 Sensor value',\n    truetrue_get_proxisensor: 'Proximity %1 Sensor value',\n    truetrue_set_colorled: 'Set Color LED Red %1  Green %2 Blue %3 %4',\n    truetrue_set_dualmotor: 'Set DC motor left %1  right %2 during %3 seconds %4',\n    truetrue_set_led_colorsensor: 'LED for %1 color sensor %2 %3',\n    truetrue_set_led_linesensor: 'LED for line sensor %1 %2',\n    truetrue_set_led_proxi: 'LED for %1 proximity sensor %2 %3',\n    truetrue_set_linetracer: 'Line tracing mode %1 %2',\n    truetrue_set_singlemotor: 'Set DC motor %1  speed %2 %3',\n    CODEino_get_number_sensor_value: 'Analog %1 Sensor value  ',\n    ardublock_get_number_sensor_value: 'Analog %1 Sensor value  ',\n    arduino_get_digital_value: 'Digital %1 Sensor value  ',\n    dplay_get_digital_value: 'Digital %1 Sensor value  ',\n    nemoino_get_digital_value: 'Digital %1 Sensor value  ',\n    sensorBoard_get_digital_value: 'Digital %1 Sensor value  ',\n    CODEino_get_digital_value: 'Digital %1 Pin value  ',\n    CODEino_set_digital_value: 'Digital %1 Pin %2 %3',\n    CODEino_set_pwm_value: 'Digital %1 Pin %2 %3',\n    ardublock_get_digital_value: 'Digital %1 Sensor value  ',\n    arduino_toggle_led: 'Digital %1 Pin %2 %3',\n    dplay_toggle_led: 'Digital %1 Pin %2 %3',\n    nemoino_toggle_led: 'Digital %1 Pin %2 %3',\n    sensorBoard_toggle_led: 'Digital %1 Pin %2 %3',\n    CODEino_toggle_led: 'Digital %1 Pin %2 %3',\n    arduino_toggle_pwm: 'Digital %1 Pin %2 %3',\n    dplay_toggle_pwm: 'Digital %1 Pin %2 %3',\n    nemoino_toggle_pwm: 'Digital %1 Pin %2 %3',\n    sensorBoard_toggle_pwm: 'Digital %1 Pin %2 %3',\n    CODEino_toggle_pwm: 'Digital %1 Pin %2 %3',\n    ardublock_toggle_pwm: 'Digital %1 Pin %2 %3',\n    arduino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    dplay_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    nemoino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    sensorBoard_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    CODEino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    CODEino_set_rgb_value: 'Set color LED %1 by %2 %3',\n    CODEino_set_rgb_add_value: 'Add color LED %1 by %2 %3',\n    CODEino_set_rgb_off: 'Turn off LED %1',\n    CODEino_set__led_by_rgb: 'Turn on color LED, Red %1 Green %2 Blue %3 %4',\n    CODEino_rgb_set_color: 'Select %1 for color LED %2',\n    CODEino_led_by_value: 'Turn on LED %1',\n    ardublock_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    joystick_get_number_sensor_value: 'Analog %1 Sensor value  ',\n    joystick_get_digital_value: 'Digital %1 Sensor value  ',\n    joystick_toggle_led: 'Digital %1 Pin %2 %3',\n    joystick_toggle_pwm: 'Digital %1 Pin %2 %3',\n    joystick_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    sensorBoard_get_named_sensor_value: '%1  Sensor value',\n    sensorBoard_is_button_pressed: 'Pressed %1 button?',\n    sensorBoard_led: '%1  LED %2   %3',\n    arduino_download_connector: '%1',\n    download_guide: '%1',\n    arduino_download_source: '%1',\n    arduino_connected: '%1',\n    arduino_connect: '%1',\n    arduino_reconnect: '%1',\n    CODEino_get_sensor_number: '%1  ',\n    CODEino_get_named_sensor_value: '  %1  Sensor value ',\n    CODEino_get_sound_status: 'Sound is  %1  ',\n    CODEino_get_light_status: 'Light is  %1  ',\n    CODEino_is_button_pressed: ' Operation  %1  ',\n    CODEino_get_accelerometer_direction: ' 3-AXIS Accelerometer  %1  ',\n    CODEino_get_accelerometer_value: ' 3-AXIS Accelerometer  %1 -axis value ',\n    CODEino_get_analog_value: 'Analog %1 Sensor value',\n    iboard_button: 'Pressed %1 button?',\n    iboard_digital_pwm: 'Digital %1 Pin %2 %3',\n    iboard_get_analog_value: 'Analog %1 Sensor value  ',\n    iboard_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    iboard_get_digital: 'Digital %1 Sensor value  ',\n    iboard_led: 'Digital %1 Pin %2 %3',\n    iboard_motor: 'Digital %1 Pin %2 %3',\n    iboard_pwm_led: 'Digital %1 Pin %2 %3',\n    iboard_rgb_led: ' %1 LED %2 %3',\n    iboard_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n    iboard_toggle_led: 'Digital %1 Pin %2 %3',\n    bitbrick_when_button_pressed: '%1 when button %2',\n    bitbrick_when_sensor_get_value: '%1 when %2 value %3 %4',\n    bitbrick_is_touch_pressed: 'button %1 %2?',\n    bitbrick_is_sensor_value_compare: '%1 %2 %3?',\n    bitbrick_sensor_value: '%1 value',\n    bitbrick_convert_scale: 'map %1 value from %2 ~ %3 to %4 ~ %5',\n    bitbrick_turn_on_color_led_by_rgb: 'set LED color to Red %1 Green %2 Blue %3 %4',\n    bitbrick_turn_on_color_led_by_picker: 'set LED color to %1 %2',\n    bitbrick_turn_on_color_led_by_value: 'set LED color %1 %2',\n    bitbrick_turn_off_color_led: 'turn off LED %1',\n    bitbrick_buzzer: 'buzz note %1 %2',\n    bitbrick_servomotor_angle: 'servo motor %1 degree %2 %3',\n    bitbrick_dc_direction_speed: 'dc motor %1 direction %2 speed %3 %4',\n    bitbrick_dc_speed: 'dc motor %1 velocity %2 %3',\n    bitbrick_turn_off_all_motors: 'stop all motors %1',\n    start_drawing: 'Start drawing %1',\n    stop_drawing: 'Stop drawing %1',\n    start_fill: 'Start filling %1',\n    stop_fill: 'Stop filling %1',\n    set_color: 'Set brush color to %1 %2',\n    set_random_color: 'Set brush color to random %1',\n    set_fill_color: 'Set fill color to %1 %2',\n    change_thickness: 'Change thickness by %1 %2',\n    set_thickness: 'Set thickness to %1 %2',\n    change_opacity: 'Change opacity by %1 % %2',\n    set_opacity: 'Set opacity to %1 % %2',\n    brush_erase_all: 'Erase all brush %1',\n    brush_stamp: 'Stamp %1',\n    change_brush_transparency: 'Change transparency by %1 % %2',\n    set_brush_tranparency: 'Set transparency to %1 % %2',\n    number: '%1',\n    angle: '%1',\n    color: '%1',\n    get_x_coordinate: '%1',\n    get_y_coordinate: '%1',\n    get_angle: '%1',\n    get_rotation_direction: '%1  ',\n    distance_something: '%1 %2 %3',\n    coordinate_mouse: '%1 %2 %3',\n    coordinate_object: '%1 %4 %3 %2',\n    calc_basic: '%1 %2 %3',\n    calc_plus: '%1 %2 %3',\n    calc_minus: '%1 %2 %3',\n    calc_times: '%1 %2 %3',\n    calc_divide: '%1 %2 %3',\n    calc_mod: '%1 %2 %3',\n    calc_share: '%1 %2 %3',\n    calc_operation: '%1 %4 %3 %2',\n    calc_rand: '%1 %2 %3 %4',\n    get_date: '%1 %2 %3',\n    get_sound_duration: '%1 %2 %3',\n    get_user_name: 'username',\n    get_nickname: 'nickname',\n    reset_project_timer: '%1',\n    set_visible_project_timer: '%1 %2 %3 %4',\n    timer_variable: '%1 %2',\n    get_project_timer_value: '%1 %2',\n    char_at: '%4 %3 %2',\n    length_of_string: '%1 %2',\n    reverse_of_string: '%1 %2',\n    combine_something: '%1 %2 %3 %4',\n    substring: '%1 %2 %3 %4 %5 %6',\n    replace_string: '%1 %4 %3 %6 %5 %2',\n    change_string_case: '%2 %3 %4',\n    count_match_string: '%2 %3 %4 %1',\n    index_of_string: '%1 %4 %3 %2',\n    get_sound_volume: '%1 %2',\n    quotient_and_mod: ' %1 %6 %3 %2 %5 %4',\n    choose_project_timer_action: '%1 %2 %3 %4',\n    wait_second: 'Wait %1 seconds %2',\n    repeat_basic: 'Repeat   %1 times %2',\n    hidden_loop: 'Repeat   %1 times %2',\n    repeat_inf: 'Repeat infinitely %1',\n    stop_repeat: 'Stop repeat %1',\n    continue_repeat: 'Skip this repeat %1',\n    wait_until_true: 'Wait until %1 %2',\n    _if: 'If %1 then %2',\n    if_else: 'If %1 then %2 %3 else',\n    create_clone: \"Create %1 's clone %2\",\n    delete_clone: 'Remove this clone %1',\n    when_clone_start: '%1 When clone is created',\n    stop_run: 'Exit program %1',\n    repeat_while_true: 'Repeat %2 %1 %3',\n    stop_object: 'Stop %1 %2',\n    restart_project: 'Restart Project %1',\n    remove_all_clones: 'Remove all clone %1',\n    functionAddButton: '%1',\n    function_field_label: '%1%2',\n    function_field_string: '%1%2',\n    function_field_boolean: '%1%2',\n    get_block_count: 'number of blocks in %1',\n    get_boolean_value: 'string %1',\n    change_rgb_to_hex: 'HEX value of R: %1 G: %2 B: %3',\n    change_hex_to_rgb: '%2 value of HEX %1',\n    function_param_string: 'Character/Number',\n    function_param_boolean: 'Judgement',\n    function_create: 'define function %1 %2',\n    function_general: 'function %1',\n    expansionBlockAddButton: '%1',\n    aiUtilizeBlockAddButton: '%1',\n    aiUtilizeModelTrainButton: '%1',\n    weather_title: '%1',\n    check_weather: \"%1 %2's weather is %3?\",\n    check_finedust: \"Current %1's fine dust grade is %2?\",\n    get_weather_data: \"%1 %2's %3\",\n    get_current_weather_data: \"Current %1's %2\",\n    get_today_temperature: \"Today %1's %2h temperature(℃)\",\n    check_city_weather: \"%1 %2 %3's weather is %4?\",\n    check_city_finedust: \"Current %1 %2's fine dust grade is %3?\",\n    get_city_weather_data: \"%1 %2 %3's %4\",\n    get_current_city_weather_data: \"Current %1 %2's %3\",\n    get_today_city_temperature: \"Today %1 %2's %3h temperature(℃)\",\n    get_cur_weather: 'Current weather in %1',\n    get_cur_wind: 'Current wind direction in %1',\n    get_cur_weather_data: 'Current %2 in %1',\n    check_cur_weather: 'Is current weather in %1 %2?',\n    check_cur_finddust: 'Is current fine dust grade in %1 %2?',\n    get_day_weather: 'Weather in %2 %3 %1',\n    get_day_weather_data: '%3 in %2 %1',\n    check_day_weather: 'Is %1 weather in %2 %3?',\n    get_time_weather: \"%2 o'clock weather in %1\",\n    get_time_weather_data: \"%2 o'clock %3 in %1\",\n    check_time_weather: \"Is %2 o'clock weather in %1 %3?\",\n    translate_title: '%1',\n    get_translated_string: 'Translate %1 %2 into %3',\n    check_language: 'language of %1',\n    festival_title: '%1',\n    count_festival: \"%1 %2's number of events\",\n    get_festival_info: '%4 of item %3 of event in %1 %2',\n    behaviorConductDisaster_title: '%1',\n    count_disaster_behavior: \"%1 %2 behavior-guidelines's number\",\n    get_disaster_behavior: 'value of item %3 of %1 %2 behavior-guidelines',\n    behaviorConductLifeSafety_title: '%1',\n    count_lifeSafety_behavior: \"%1 %2 behavior-guidelines's number\",\n    get_lifeSafety_behavior: 'value of item %3 of %1 how to %2',\n    tts_title: '%1',\n    audio_title: '%1',\n    video_title: '%1',\n    read_text: 'read %1 %2',\n    set_tts_property: 'set in a %1 voice at %2 speed and %3 pitch %4',\n    read_text_wait_with_block: 'read %1 and wait %2',\n    load_expansion_block: 'Add extention',\n    load_ai_utilize_block: 'Load AI Block',\n    load_ai_utilize_train_block: 'Training Model',\n    expansion_block_descriptions:\n        'The expansion block works normally when the Internet is connected.',\n    aiUtilize_block_descriptions:\n        'The A.I. Utilization block works normally when the Internet is connected.',\n    weather_title_text: 'Weather',\n    translate_title_text: 'Translate',\n    festival_title_text: 'Festival',\n    audio_title_text: 'Audio sensing',\n    voice_title_text: 'Speech recognition',\n    check_microphone: 'connected to microphone?',\n    get_microphone_volume: 'microphone volume value',\n    speech_to_text_title: '%1',\n    speech_to_text_convert: 'Recognize %1 speech %2',\n    timed_speech_to_text_convert: 'For %1 secs recognize %2 speech %3',\n    set_visible_speech_to_text: '%1 recognized speech %2',\n    speech_to_text_get_value: 'speech-to-text value',\n    video_title_text: 'Video detection',\n    video_draw_webcam: '%1 the camera screen',\n    video_check_webcam: 'connected with video?',\n    video_set_camera_opacity_option: 'Set video transparency effect to %1 %2',\n    video_flip_camera: 'Flip camera screen %1 %2',\n    video_toggle_model: '%1 recognition %2 %3',\n    video_toggle_ind: '%2 detected %1 %3',\n    video_number_detect: 'Number of detected %1',\n    video_detected_face_info: '%2 of %1 th face',\n    video_motion_value: 'Camera %2 value on %1',\n    video_face_part_coord: '%3 coordinate of %2 in %1 th face',\n    video_body_part_coord: \"%3 coordinate of %1 th human's %2\",\n    behaviorConductDisaster_title_text: 'Disaster',\n    behaviorConductLifeSafety_title_text: 'LifeSafety',\n    emergencyActionGuidelines_title_text: 'Emergency action guidelines',\n    count_disaster_guideline: 'number of guidelines in natural disaster %1 %2',\n    get_disaster_guideline: '%3 th item of guidelines in natural disaster %1 %2',\n    count_social_disaster_guideline: 'number of guidelines in social disaster %1 %2',\n    get_social_disaster_guideline: '%3 th item of guidelines in social disaster %1 %2',\n    count_safety_accident_guideline: 'number of guidelines in life safety accident %1 %2',\n    get_safety_accident_guideline: '%3 th item of guidelines in life safety accident %1 %2',\n    tts_title_text: 'Read',\n    hamster_hand_found: 'hand found?',\n    hamster_value: '%1',\n    hamster_move_forward_once: 'move forward once on board %1',\n    hamster_turn_once: 'turn %1 once on board %2',\n    hamster_move_forward_for_secs: 'move forward for %1 secs %2',\n    hamster_move_backward_for_secs: 'move backward for %1 secs %2',\n    hamster_turn_for_secs: 'turn %1 for %2 secs %3',\n    hamster_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n    hamster_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n    hamster_change_wheel_by: 'change %1 wheel by %2 %3',\n    hamster_set_wheel_to: 'set %1 wheel to %2 %3',\n    hamster_follow_line_using: 'follow %1 line using %2 floor sensor %3',\n    hamster_follow_line_until: 'follow %1 line until %2 intersection %3',\n    hamster_set_following_speed_to: 'set following speed to %1 %2',\n    hamster_stop: 'stop %1',\n    hamster_set_led_to: 'set %1 led to %2 %3',\n    hamster_clear_led: 'clear %1 led %2',\n    hamster_beep: 'beep %1',\n    hamster_change_buzzer_by: 'change buzzer by %1 %2',\n    hamster_set_buzzer_to: 'set buzzer to %1 %2',\n    hamster_clear_buzzer: 'clear buzzer %1',\n    hamster_play_note_for: 'play note %1 %2 for %3 beats %4',\n    hamster_rest_for: 'rest for %1 beats %2',\n    hamster_change_tempo_by: 'change tempo by %1 %2',\n    hamster_set_tempo_to: 'set tempo to %1 bpm %2',\n    hamster_set_port_to: 'set port %1 to %2 %3',\n    hamster_change_output_by: 'change output %1 by %2 %3',\n    hamster_set_output_to: 'set output %1 to %2 %3',\n    roboid_hamster_beep: 'Hamster %1: beep %2',\n    roboid_hamster_change_both_wheels_by: 'Hamster %1: change wheels by left: %2 right: %3 %4',\n    roboid_hamster_change_buzzer_by: 'Hamster %1: change buzzer by %2 %3',\n    roboid_hamster_change_output_by: 'Hamster %1: change output %2 by %3 %4',\n    roboid_hamster_change_tempo_by: 'Hamster %1: change tempo by %2 %3',\n    roboid_hamster_change_wheel_by: 'Hamster %1: change %2 wheel by %3 %4',\n    roboid_hamster_clear_buzzer: 'Hamster %1: clear buzzer %2',\n    roboid_hamster_clear_led: 'Hamster %1: clear %2 led %3',\n    roboid_hamster_follow_line_until: 'Hamster %1: follow %2 line until %3 intersection %4',\n    roboid_hamster_follow_line_using: 'Hamster %1: follow %2 line using %3 floor sensor %4',\n    roboid_hamster_hand_found: 'Hamster %1: hand found?',\n    roboid_hamster_move_backward_for_secs: 'Hamster %1: move backward for %2 secs %3',\n    roboid_hamster_move_forward_for_secs: 'Hamster %1: move forward for %2 secs %3',\n    roboid_hamster_move_forward_once: 'Hamster %1: move forward once on board %2',\n    roboid_hamster_play_note_for: 'Hamster %1: play note %2 %3 for %4 beats %5',\n    roboid_hamster_rest_for: 'Hamster %1: rest for %2 beats %3',\n    roboid_hamster_set_both_wheels_to: 'Hamster %1: set wheels to left: %2 right: %3 %4',\n    roboid_hamster_set_buzzer_to: 'Hamster %1: set buzzer to %2 %3',\n    roboid_hamster_set_following_speed_to: 'Hamster %1: set following speed to %2 %3',\n    roboid_hamster_set_led_to: 'Hamster %1: set %2 led to %3 %4',\n    roboid_hamster_set_output_to: 'Hamster %1: set output %2 to %3 %4',\n    roboid_hamster_set_port_to: 'Hamster %1: set port %2 to %3 %4',\n    roboid_hamster_set_tempo_to: 'Hamster %1: set tempo to %2 bpm %3',\n    roboid_hamster_set_wheel_to: 'Hamster %1: set %2 wheel to %3 %4',\n    roboid_hamster_stop: 'Hamster %1: stop %2',\n    roboid_hamster_turn_for_secs: 'Hamster %1: turn %2 for %3 secs %4',\n    roboid_hamster_turn_once: 'Hamster %1: turn %2 once on board %3',\n    roboid_hamster_value: 'Hamster %1: %2',\n    roboid_turtle_button_state: 'Turtle %1: button %2 ?',\n    roboid_turtle_change_buzzer_by: 'Turtle %1: change buzzer by %2 %3',\n    roboid_turtle_change_head_led_by_rgb: 'Turtle %1: change head led by r: %2 g: %3 b: %4 %5',\n    roboid_turtle_change_tempo_by: 'Turtle %1: change tempo by %2 %3',\n    roboid_turtle_change_wheel_by: 'Turtle %1: change %2 wheel by %3 %4',\n    roboid_turtle_change_wheels_by_left_right: 'Turtle %1: change wheels by left: %2 right: %3 %4',\n    roboid_turtle_clear_head_led: 'Turtle %1: clear head led %2',\n    roboid_turtle_clear_sound: 'Turtle %1: clear sound %2',\n    roboid_turtle_cross_intersection: 'Turtle %1: cross black intersection %2',\n    roboid_turtle_follow_line: 'Turtle %1: follow %2 line %3',\n    roboid_turtle_follow_line_until: 'Turtle %1: follow black line until %2 %3',\n    roboid_turtle_follow_line_until_black: 'Turtle %1: follow %2 line until black %3',\n    roboid_turtle_is_color_pattern: 'Turtle %1: color pattern %2 %3 ?',\n    roboid_turtle_move_backward_unit: 'Turtle %1: move backward %2 %3 %4',\n    roboid_turtle_move_forward_unit: 'Turtle %1: move forward %2 %3 %4',\n    roboid_turtle_pivot_around_wheel_unit_in_direction:\n        'Turtle %1: pivot around %2 wheel %3 %4 in %5 direction %6',\n    roboid_turtle_play_note: 'Turtle %1: play note %2 %3 %4',\n    roboid_turtle_play_note_for_beats: 'Turtle %1: play note %2 %3 for %4 beats %5',\n    roboid_turtle_play_sound_times: 'Turtle %1: play sound %2 %3 times %4',\n    roboid_turtle_play_sound_times_until_done: 'Turtle %1: play sound %2 %3 times until done %4',\n    roboid_turtle_rest_for_beats: 'Turtle %1: rest for %2 beats %3',\n    roboid_turtle_set_buzzer_to: 'Turtle %1: set buzzer to %2 %3',\n    roboid_turtle_set_following_speed_to: 'Turtle %1: set following speed to %2 %3',\n    roboid_turtle_set_head_led_to: 'Turtle %1: set head led to %2 %3',\n    roboid_turtle_set_head_led_to_rgb: 'Turtle %1: set head led to r: %2 g: %3 b: %4 %5',\n    roboid_turtle_set_tempo_to: 'Turtle %1: set tempo to %2 bpm %3',\n    roboid_turtle_set_wheel_to: 'Turtle %1: set %2 wheel to %3 %4',\n    roboid_turtle_set_wheels_to_left_right: 'Turtle %1: set wheels to left: %2 right: %3 %4',\n    roboid_turtle_stop: 'Turtle %1: stop %2',\n    roboid_turtle_touching_color: 'Turtle %1: touching %2 ?',\n    roboid_turtle_turn_at_intersection: 'Turtle %1: turn %2 at black intersection %3',\n    roboid_turtle_turn_unit_in_place: 'Turtle %1: turn %2 %3 %4 in place %5',\n    roboid_turtle_turn_unit_with_radius_in_direction:\n        'Turtle %1: turn %2 %3 %4 with radius %5 cm in %6 direction %7',\n    roboid_turtle_value: 'Turtle %1: %2',\n    turtle_button_state: 'button %1 ?',\n    turtle_change_buzzer_by: 'change buzzer by %1 %2',\n    turtle_change_head_led_by_rgb: 'change head led by r: %1 g: %2 b: %3 %4',\n    turtle_change_tempo_by: 'change tempo by %1 %2',\n    turtle_change_wheel_by: 'change %1 wheel by %2 %3',\n    turtle_change_wheels_by_left_right: 'change wheels by left: %1 right: %2 %3',\n    turtle_clear_head_led: 'clear head led %1',\n    turtle_clear_sound: 'clear sound %1',\n    turtle_cross_intersection: 'cross black intersection %1',\n    turtle_follow_line: 'follow %1 line %2',\n    turtle_follow_line_until: 'follow black line until %1 %2',\n    turtle_follow_line_until_black: 'follow %1 line until black %2',\n    turtle_is_color_pattern: 'color pattern %1 %2 ?',\n    turtle_move_backward_unit: 'move backward %1 %2 %3',\n    turtle_move_forward_unit: 'move forward %1 %2 %3',\n    turtle_pivot_around_wheel_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n    turtle_play_note: 'play note %1 %2 %3',\n    turtle_play_note_for_beats: 'play note %1 %2 for %3 beats %4',\n    turtle_play_sound_times: 'play sound %1 %2 times %3',\n    turtle_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n    turtle_rest_for_beats: 'rest for %1 beats %2',\n    turtle_set_buzzer_to: 'set buzzer to %1 %2',\n    turtle_set_following_speed_to: 'set following speed to %1 %2',\n    turtle_set_head_led_to: 'set head led to %1 %2',\n    turtle_set_head_led_to_rgb: 'set head led to r: %1 g: %2 b: %3 %4',\n    turtle_set_tempo_to: 'set tempo to %1 bpm %2',\n    turtle_set_wheel_to: 'set %1 wheel to %2 %3',\n    turtle_set_wheels_to_left_right: 'set wheels to left: %1 right: %2 %3',\n    turtle_stop: 'stop %1',\n    turtle_touching_color: 'touching %1 ?',\n    turtle_turn_at_intersection: 'turn %1 at black intersection %2',\n    turtle_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n    turtle_turn_unit_with_radius_in_direction: 'turn %1 %2 %3 with radius %4 cm in %5 direction %6',\n    turtle_value: '%1',\n    is_clicked: '%1',\n    is_object_clicked: '%1',\n    is_press_some_key: '%1 %2',\n    reach_something: '%1 %2 %3',\n    is_type: '%1 %2 %3 %4',\n    boolean_comparison: '%1 %2 %3',\n    boolean_equal: '%1 %2 %3',\n    boolean_bigger: '%1 %2 %3',\n    boolean_smaller: '%1 %2 %3',\n    boolean_and_or: '%1 %2 %3',\n    boolean_and: '%1 %2 %3',\n    boolean_or: '%1 %2 %3',\n    boolean_not: '%1 %2 %3',\n    is_boost_mode: '%1',\n    is_current_device_type: 'is the project running on %1 ?',\n    is_touch_supported: 'touch screen?',\n    true_or_false: '%1',\n    True: '%1  ',\n    False: '%1  ',\n    boolean_basic_operator: '%1 %2 %3',\n    show: 'Show shape %1',\n    hide: 'Hide shape %1',\n    dialog_time: '%3 %1 for %2 second(s) %4',\n    dialog: '%2 %1 %3',\n    remove_dialog: 'Remove speech bubble %1',\n    change_to_nth_shape: 'Change shape to %1 %2',\n    change_to_next_shape: 'Change to %1 shape %2',\n    set_effect_volume: 'Change %1 effect by %2 %3',\n    set_effect: 'Set %1 effect to %2 %3',\n    erase_all_effects: 'Remove all effects %1',\n    change_scale_percent: 'Change scale by %1 %2',\n    set_scale_percent: 'Set scale to %1 %2',\n    change_scale_size: 'Change size by %1 %2',\n    set_scale_size: 'Set size to %1 %2',\n    stretch_scale_size: 'Stretch %1 by %2 %3',\n    reset_scale_size: 'Reset size %1',\n    flip_y: 'Flip horizontally %1',\n    flip_x: 'Flip vertically %1',\n    set_object_order: 'go to %1 th layer %2',\n    get_pictures: '%1  ',\n    change_to_some_shape: 'Change shape to %1 %2',\n    add_effect_amount: 'Apply %1 effect by %2 %3',\n    change_effect_amount: 'Set %1 effect to %2 %3',\n    set_effect_amount: 'Change %1 effect by %2 %3',\n    set_entity_effect: 'Set %1 effect to %2 %3',\n    change_object_index: 'Bring (to) %1 %2',\n    move_direction: 'Move %1 forward %2',\n    move_x: 'Change X by %1 %2',\n    move_y: 'Change Y by %1 %2',\n    locate_xy_time: 'Moving while %1 seconds to x: %2 y: %3 %4',\n    rotate_by_angle: 'Rotate by %1 degree %2',\n    rotate_by_angle_dropdown: 'Rotate by %1 degree %2',\n    see_angle: 'Set direction to %1 %2',\n    see_direction: 'Rotate to the %1 %2',\n    locate_xy: 'Move to the X: %1 Y: %2 %3',\n    locate_x: 'Move to the X: %1 %2',\n    locate_y: 'Move to the Y: %1 %2',\n    locate: 'Move to %1 %2',\n    move_xy_time: 'For %1 secs move to X: %2 Y: %3 %4',\n    rotate_by_angle_time: 'Rotate while %1 seconds by %2 degree %3',\n    bounce_wall: 'if on edge, bounce %1',\n    flip_arrow_horizontal: 'Flip horizontally by arrow direction %1',\n    flip_arrow_vertical: 'Flip vertically by arrow direction %1',\n    see_angle_object: 'Turn towards %1 %2',\n    see_angle_direction: 'See angle to %1 degree %2',\n    rotate_direction: 'Change direction by  %1 %2',\n    locate_object_time: 'for %1 secs move to %2 %3',\n    rotate_absolute: 'Set rotation to %1 %2',\n    rotate_relative: 'Rotate %1 %2',\n    direction_absolute: 'Set direction to %1 %2',\n    direction_relative: 'Change direction by  %1 %2',\n    move_to_angle: 'Rotate %1 and move %2 %3',\n    rotate_by_time: 'For %1 secs rotate %2 %3',\n    direction_relative_duration: 'For %1 secs set direction to %2 %3',\n    neobot_sensor_value: '%1  값',\n    neobot_turn_left: 'Rotate left motor %1 %2 %3',\n    neobot_stop_left: 'Stop left motor %1',\n    neobot_turn_right: 'Rotate right motor %1 %2 %3',\n    neobot_stop_right: 'Stop right motor %1',\n    neobot_run_motor: 'Run %1 motor for %2 secs',\n    neobot_servo_1: 'Move the servo motor connected to SERVO1 to %2 with the speed of %1 %3',\n    neobot_servo_2: 'Move the servo motor connected to SERVO2 to %2 with the speed of %1 %3',\n    neobot_play_note_for: 'Play %1 melody to octave %2 as long as %3 %4',\n    neobot_set_sensor_value: '%1 value of the port to %2 %3',\n    robotis_openCM70_cm_custom_value: 'Custom address ( %1 ) value %2',\n    robotis_openCM70_sensor_value: 'Controller value %1',\n    robotis_openCM70_aux_sensor_value: 'Value %1   %2',\n    robotis_openCM70_cm_buzzer_index: 'Play %1 controller scale value for %2 seconds %3 ',\n    robotis_openCM70_cm_buzzer_melody: 'Play controller melody %1 times %2',\n    robotis_openCM70_cm_sound_detected_clear: 'Initialize the final number of sound detection  %1',\n    robotis_openCM70_cm_led: 'Controller %1 LED %2 %3',\n    robotis_openCM70_cm_motion: 'Play the motion %1 times',\n    robotis_openCM70_cm_autodrive_motor: 'Autonomous driving car %1 motor uses %2 %3',\n    robotis_openCM70_cm_autodrive_ir: 'Autonomous driving car %1 IR sensor uses %2 %3',\n    robotis_openCM70_cm_autodrive_speed: 'Perform autonomous driving at the speed of %1 %2',\n    robotis_openCM70_aux_car_move: 'Make the robot %2 at a speed of %1% %3',\n    robotis_openCM70_aux_motor_speed:\n        'Set the speed of decelerating motor of %1 to %2 , and the output value to %3%  %4',\n    robotis_openCM70_aux_servo_mode: 'Set the mode of %1 servo motor to %2  %3',\n    robotis_openCM70_aux_servo_speed:\n        'Set the speed of servo motor of %1 to %2 , and the output value to %3%  %4',\n    robotis_openCM70_aux_servo_position: 'Set the position of %1 servo motor to %2 degree %3',\n    robotis_openCM70_aux_led_module: 'Set the LED module of %1 as %2  %3',\n    robotis_openCM70_aux_custom: 'Set the user device of %1 as %2  %3',\n    robotis_openCM70_cm_poweroff_timer: 'Set auto-off timer as %1 %2',\n    robotis_openCM70_cm_custom: 'Set the custom address ( %1 ) as %2  %3',\n    robotis_carCont_sensor_value: 'Value   %1',\n    robotis_carCont_cm_led: '%1 LED 4,  %2 LED %3',\n    robotis_carCont_cm_sound_detected_clear: 'Initialize the final number of sound detection  %1',\n    robotis_carCont_aux_motor_speed:\n        'Set the speed of decelerating motor of %1 to %2, and the output value to %3  %4',\n    robotis_carCont_cm_calibration: 'Set %1 value of infrared sensor calibration to %2  %3',\n    roduino_get_analog_number: '%1  ',\n    roduino_get_port_number: '%1  ',\n    roduino_get_analog_value: 'Analog %1 Sensor value  ',\n    roduino_get_digital_value: 'Digital %1 Sensor value  ',\n    roduino_set_digital: 'Digital %1 Pin %2 %3',\n    roduino_motor: '%1 %2 %3',\n    roduino_set_color_pin: 'Color Sensor R : %1, G : %2, B : %3 %4',\n    roduino_get_color: 'Color Sensor %1 Detected ',\n    roduino_on_block: ' On ',\n    roduino_off_block: ' Off ',\n    schoolkit_get_in_port_number: '%1  ',\n    schoolkit_get_out_port_number: '%1  ',\n    schoolkit_get_servo_port_number: '%1  ',\n    schoolkit_get_input_value: 'Digital %1 Sensor value  ',\n    schoolkit_set_output: 'Digital %1 Pin %2 %3',\n    schoolkit_motor: '%1 Speed %2 %3 %4',\n    schoolkit_set_servo_value: 'Servo %1 Pin %2˚ %3',\n    schoolkit_on_block: ' On ',\n    schoolkit_off_block: ' Off ',\n    when_scene_start: '%1 When scene started',\n    start_scene: 'Start %1 scene %2',\n    start_neighbor_scene: 'Start %1 scene %2',\n    sound_something: 'Play %1 Sound %2',\n    sound_something_second: 'Play %1 sound for %2 secs %3',\n    sound_something_wait: 'Play %1 Sound and wait %2',\n    sound_something_second_wait: 'Play %1 Sound for %2 secs and wait %3',\n    sound_volume_change: 'Change volume by %1 %2',\n    sound_volume_set: 'Set volume to %1 % %2',\n    get_sound_speed: 'Speed',\n    sound_speed_change: 'Change speed by %1 %2',\n    sound_speed_set: 'Set speed at %1 times %2',\n    sound_silent_all: 'Stop sound of %1 %2',\n    play_bgm: 'Play %1 as background music %2',\n    stop_bgm: 'Stop background music %1',\n    get_sounds: '%1  ',\n    sound_something_with_block: 'Play %1 sound %2',\n    sound_something_second_with_block: 'Play %1 sound for %2 secs %3',\n    sound_something_wait_with_block: 'Play %1 sound and wait %2',\n    sound_something_second_wait_with_block: 'Play %1 sound for %2 secs and wait %3',\n    sound_from_to: 'Play %1 sound from %2 to %3 secs %4',\n    sound_from_to_and_wait: 'Play %1 sound from %2 to %3 secs and wait %4',\n    messageAddButton: '%1',\n    when_run_button_click: '%1 When run',\n    press_some_key: '%1 When key %2 pressed %3',\n    when_some_key_pressed: '%1 When key %2 pressed',\n    mouse_clicked: '%1 When mouse clicked',\n    mouse_click_cancled: '%1 When mouse click released',\n    when_object_click: '%1 When object clicked',\n    when_object_click_canceled: '%1 When object click released',\n    when_some_key_click: '%1 When press some key',\n    when_message_cast: '%1 When %2 message received',\n    message_cast: 'Send %1 message %2',\n    message_cast_wait: 'Send %1  message and wait %2',\n    text: '%1',\n    text_read: 'Textbox %1’s contents',\n    text_write: 'Writing that %1 %2',\n    text_append: 'After writing that %1 %2',\n    text_prepend: 'Add %1 in front of that %2',\n    text_flush: 'Remove all text %1',\n    analizyDataAddButton: '%1',\n    append_row_to_table: 'Add a %2 to table %1 %3',\n    insert_row_to_table: 'Insert %3 to %2 th row in table %1 %4',\n    delete_row_from_table: 'Remove %2 th %3 in table %1 %4',\n    set_value_from_table: 'Change %3 in table %1 %2 th row to %4 %5',\n    save_current_table: 'Save table %1 as it is %2',\n    get_table_count: 'number of %2 in table %1',\n    get_value_from_table: '%3 value of %2 th row in table %1',\n    get_value_from_last_row: '%2 value of the last row in table %1',\n    calc_values_from_table: '%3 of %2 in table %1',\n    open_table: 'Open table %1 window %2',\n    open_table_wait: 'Open table %1 window for %2 second(s) %3',\n    open_table_chart: 'Open chart %2 of table %1 %3',\n    close_table_chart: 'Close table chart %1',\n    get_coefficient: 'correlation coefficient between %2 and %3 in table %1',\n    set_value_from_cell: 'Change %2 cell in table %1 to %3 %4',\n    get_value_from_cell: 'value of %2 cell in table %1',\n    get_value_v_lookup: '%4 value of the row that %2 is %3 in table %1',\n    variableAddButton: '%1',\n    listAddButton: '%1',\n    change_variable: 'Plus to %1 by %2 %3',\n    set_variable: 'Set %1 to %2 %3',\n    show_variable: 'Show variable %1 value %2',\n    hide_variable: 'Hide variable %1 value %2',\n    get_variable: '%2 %1',\n    ask_and_wait: 'Ask %1 and wait %2',\n    get_canvas_input_value: '%1  ',\n    add_value_to_list: 'add %1 to the list %2 %3',\n    remove_value_from_list: 'remove %1 th element from %2 %3',\n    insert_value_to_list: 'insert %1 to %2 %3 th position %4',\n    change_value_list_index: 'change %1 %2 th element to %3 %4',\n    value_of_index_from_list: '%1 %2 %3 %4 %5',\n    length_of_list: '%1 %2 %3',\n    show_list: 'Show list %1 %2',\n    hide_list: 'Hide list %1 %2',\n    options_for_list: '%1  ',\n    set_visible_answer: 'response %1 %2',\n    is_included_in_list: '%1 %2 %3 %4 %5',\n    xbot_digitalInput: '%1',\n    xbot_analogValue: '%1',\n    xbot_digitalOutput: 'Digital %1 PIN, Ouput Value %2 %3',\n    xbot_analogOutput: 'Analog %1 %2 %3',\n    xbot_servo: 'Servo Motor %1 , Angle %2 %3',\n    xbot_oneWheel: 'Wheel(DC) Motor %1 , Speed %2 %3',\n    xbot_twoWheel: 'Wheel(DC) Motor Right(2) Speed: %1 Left(1) Speed: %2 %3',\n    xbot_rgb: 'RGB LED Color from Red %1 Green %2 Blue %3 %4',\n    xbot_rgb_picker: 'RGB LED Color from %1   %2',\n    xbot_buzzer: 'play note %1   %2 for %3 sec of Melody Playing %4',\n    xbot_lcd: 'LCD %1 th Line ,  Text %2 %3',\n    run: '',\n    mutant: 'test mutant block',\n    jr_start: '%1',\n    jr_repeat: 'Repeat %1 %2',\n    jr_item: 'Gather flower %1',\n    cparty_jr_item: 'Pick up %1',\n    jr_north: 'Up %1',\n    jr_east: 'Right %1',\n    jr_south: 'Down %1',\n    jr_west: 'Left %1',\n    jr_start_basic: '%1 %2',\n    jr_go_straight: 'Go forward %1',\n    jr_turn_left: 'Turn left %1',\n    jr_turn_right: 'Turn right %1',\n    jr_go_slow: 'Go slow %1',\n    jr_repeat_until_dest: 'Repeat until meeting up with %1 %2',\n    jr_if_construction: 'If %1 in front %2',\n    jr_if_speed: 'If %1 in front %2',\n    maze_step_start: '%1 When Run',\n    maze_step_jump: 'Skip%1',\n    maze_step_jump2: 'Jump%1',\n    maze_step_jump_pinkbean: 'Jump%1',\n    maze_step_for: 'Repeat %1 times %2',\n    test: '%1 this is test block %2',\n    maze_repeat_until_1: 'Repeat until meeting up with %1  %2',\n    maze_repeat_until_2: 'Repeat until meeting up with all %1  %2',\n    maze_step_if_1: 'If %1 is in front %2',\n    maze_step_if_2: 'If %1 is in front %2',\n    maze_call_function: 'Import promise %1',\n    maze_define_function: 'Promise %1',\n    maze_step_if_3: 'If %1 is in front %2',\n    maze_step_if_4: 'If %1 is in front %2',\n    maze_step_move_step: 'Move one step forward %1',\n    maze_step_rotate_left: 'Turn to the left %1',\n    maze_step_rotate_right: 'Turn to the right %1',\n    maze_step_forward: 'Go forward %1',\n    maze_turn_right: 'look right side %1',\n    maze_turn_left: 'look left side %1',\n    maze_ladder_climb: 'Climb ladder%1',\n    maze_attack_lupin: 'Attack %1 %2',\n    maze_attack_both_side: 'Attack both sides%1',\n    maze_attack_pepe: 'Attack %1 %2',\n    maze_attack_yeti: 'Attack %1 %2',\n    maze_attack_mushroom: 'Attack %1 %2',\n    maze_attack_peti: 'Attack %1 %2',\n    maze_eat_item: 'Take food%1',\n    maze_step_if_mushroom: 'If there is %1 one space forward %2',\n    maze_step_if_yeti: 'If there is %1 in front %2 %3 else',\n    maze_step_if_left_monster: 'If there is a monster in the left side attack range %1 %2 else',\n    maze_step_if_right_monster: 'If there is a monster in the right side attack range %1 %2 else',\n    maze_step_if_lupin: 'If there is %1 two spaces forward %2',\n    maze_step_if_else_road: 'If there is road one space forward %1 %2else',\n    maze_step_if_else_mushroom: 'If there is %1 one space forward %2 %3 else',\n    maze_step_if_else_lupin: 'If there is %1 two spaces forward %2 %3 else',\n    maze_step_if_else_ladder: 'If there is %1 one space forward %2 %3 else',\n    maze_rotate_left: 'Spin to the left %1',\n    maze_rotate_right: 'Spin to the right %1',\n    maze_moon_kick: 'Kick %1',\n    maze_repeat_until_3: 'Repeat until meeting up with %1  %2',\n    maze_repeat_until_4: 'Repeat until meeting up with %1  %2',\n    maze_repeat_until_5: 'Repeat until meeting up with %1  %2',\n    maze_repeat_until_6: 'Repeat until arriving to %1  %2',\n    maze_repeat_until_7: 'Repeat until reaching %1 %2',\n    maze_repeat_until_goal: 'Repeat until arrival to destination%1',\n    maze_repeat_until_beat_monster: 'Repeat until all monsters are defeated %1',\n    maze_radar_check: '%2 is in %1',\n    maze_cony_flower_throw: 'Throw flower %1',\n    maze_brown_punch: 'Punch %1',\n    maze_iron_switch: 'Control obstacles %1',\n    maze_james_heart: 'Toss cakes %1',\n    maze_step_if_5: 'If there is no road in front %2',\n    maze_step_if_6: \"If %1 isn't in front %2\",\n    maze_step_if_7: 'If %1 is in front %2',\n    maze_step_if_8: 'If it is %1  %2',\n    maze_step_if_else: 'If it is %1  %2  %3 or',\n    test_wrapper: '%1 this is test block %2',\n    basic_button: '%1',\n    ai_move_right: 'move forward %1',\n    ai_move_up: 'go above %1',\n    ai_move_down: 'go under %1',\n    ai_repeat_until_reach: 'repeat until destination %1',\n    ai_if_else_1: 'if %1 in front %2 %3 else',\n    ai_boolean_distance: '%1 radar %2 %3',\n    ai_distance_value: '%1 radar',\n    ai_boolean_object: 'is %1 object %2 ?',\n    ai_use_item: 'use item %1',\n    ai_boolean_and: '%1 %2 %3',\n    ai_True: '%1',\n    ai_if_else: 'If %1 then %2 %3 else',\n    smartBoard_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n    smartBoard_get_named_sensor_value: '%1 Sensor value',\n    smartBoard_is_button_pressed: 'Pressed %1 button?',\n    smartBoard_set_dc_motor_direction: '%1 DC Motor change direction %2 %3',\n    smartBoard_set_dc_motor_speed: '%1 DC Motor %2 %3',\n    smartBoard_set_dc_motor_pwm: '%1 DC Motor set speed %2 %3',\n    smartBoard_set_servo_speed: '%1 RC Servo Motor Speed %2 %3',\n    smartBoard_set_servo_angle: '%1 RC Servo Motor set angle %2 %3',\n    smartBoard_set_number_eight_pin: '%1 port %2 %3',\n    smartBoard_set_gs1_pwm: 'GS1 port %1 %2',\n    robotori_digitalInput: '%1',\n    robotori_analogInput: '%1',\n    robotori_digitalOutput: 'Digital %1 PIN, Output Value %2 %3',\n    robotori_analogOutput: 'Analog %1 %2 %3',\n    robotori_servo: 'Servo Motor Angle %1 %2',\n    robotori_dc_direction: 'DC Motor %1 Direction %2 %3',\n    dadublock_get_analog_value: 'Analog %1 Sensor value',\n    dadublock_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n    dadublock_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n    dadublock_toggle_led: 'Digital %1 Pin %2 %3',\n    dadublock_digital_pwm: 'Digital %1 Pin %2 %3',\n    dadublock_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n    dadublock_set_servo: 'Set servo pin %1 angle as %2 %3',\n    coconut_stop_motor: 'stop motor %1',\n    coconut_move_motor: 'move %1 %2',\n    coconut_turn_motor: 'turn %1 %2',\n    coconut_move_for_secs: 'move %1 for time %2 %3',\n    coconut_turn_for_secs: 'turn %1 for %2 secs %3',\n    coconut_turn_to_led: 'turn %1 RGB %2 %3',\n    coconut_move_outmotor: 'external Motor %1 speed %2 %3',\n    coconut_set_led_to: 'turn on RGB %1 %2 %3',\n    coconut_clear_led: 'turn off RGB %1 %2',\n    coconut_set_led_clear: 'turn off RGB %1 %2 %3',\n    coconut_set_led_time: 'turn on RGB %1 %2 for time %3 %4',\n    coconut_beep: 'buzzer on %1',\n    coconut_buzzer_time: 'play buzzer for time %1 %2',\n    coconut_buzzer_set_hz: 'play buzzer on frequency %1 Hz for time %2 %3',\n    coconut_clear_buzzer: 'buzzer off %1',\n    coconut_play_buzzer: 'play buzzer on note %1 octave %2 %3 beat %4 %5',\n    coconut_rest_buzzer: 'rest beat %1 %2',\n    coconut_play_buzzer_led: 'play buzzer on note %1 octave %2 %3 beat %4 RGB %5 %6 %7',\n    coconut_play_midi: 'play melody %1 %2',\n    coconut_floor_sensor: 'line tracer %1',\n    coconut_floor_sensing: 'line tracer detect %1 %2',\n    coconut_following_line: 'follow the line %1',\n    coconut_front_sensor: 'IR distance sensor %1',\n    coconut_front_sensing: 'detecting obstacle %1 %2',\n    coconut_obstruct_sensing: 'detecting obstacle',\n    coconut_avoid_mode: 'avoid mode %1',\n    coconut_dotmatrix_set: 'LED Matrix %1 ( ROW %2, COL %3 ) %4',\n    coconut_dotmatrix_on: 'turn on all LED Matrix %1',\n    coconut_dotmatrix_off: 'LED Matrix clear all %1',\n    coconut_dotmatrix_num: 'LED Matrix show %1 %2',\n    coconut_dotmatrix_small_eng: 'LED Matrix show small letter %1 %2',\n    coconut_dotmatrix_big_eng: 'LED Matrix show capital letters %1 %2',\n    coconut_dotmatrix_kor: 'LED Matrix show Korean %1 %2',\n    coconut_light_sensor: 'light sensor',\n    coconut_tem_sensor: 'temperature',\n    coconut_ac_sensor: '3-Axis Accelerometer %1 angle',\n    coconut_outled_sensor: 'set external LED pin %1 for time %2 %3',\n    coconut_outspk_sensor: 'set Speaker pin %1 frequency %2 (Hz) duration %3 seconds %4',\n    coconut_outspk_sensor_off: 'stop Speaker pin %1 %2',\n    coconut_outinfrared_sensor: 'external IR sensor %1',\n    coconut_outcds_sensor: 'external Cds sensor %1',\n    coconut_servomotor_angle: 'set servo pin %1 angle as %2 %3',\n    chocopi_control_button: '%1 controller %2 is pressed',\n    chocopi_control_event: '%1 When %2 controller %3 is %4',\n    chocopi_control_joystick: '%1 controller %2 value',\n    chocopi_dc_motor: '%1 DC motor #%2  %3 % direction %4 %5',\n    chocopi_led: '%1 LED #%2 RGB(%3 %4 %5) %6',\n    chocopi_motion_photogate_event: '%1 When %2 photogate %3 is %4',\n    chocopi_motion_photogate_status: '%1 photogate #%2 is blocked',\n    chocopi_motion_photogate_time: 'time when %1 photogate %2 was %3',\n    chocopi_motion_value: '%1 motion %2 value',\n    chocopi_sensor: '%1 sensor %2',\n    chocopi_servo_motor: '%1 set servo motor #%2 %3 degree %4',\n    chocopi_touch_event: '%1 When %2 touch pad%3 is %4',\n    chocopi_touch_status: '%1 touch pad%2 is touched',\n    chocopi_touch_value: '%1 touch pad%2 value',\n    dadublock_car_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dadublock_car_get_analog_value: '아날로그 %1 번 센서값',\n    dadublock_car_get_analog_value_map:\n        '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    dadublock_car_get_digital: '디지털 %1 번 센서값',\n    dadublock_car_get_irsensor: '적외선 %1 번 센서값',\n    dadublock_car_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n    dadublock_car_motor: '모터 %1 번을 %2 (으)로 %3 %의 속도로 움직이기 %4',\n    dadublock_car_motor_stop: '모터 %1 번 멈추기 %2',\n    dadublock_car_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n    dadublock_car_set_tone: '디지털 %1 번 핀 을 %2 음으로 %3의 옥타브로 %4 만큼 연주하기 %5',\n    dadublock_car_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dadublock_get_digital: '디지털 %1 번 센서값',\n    ev3_get_sensor_value: \"%1's value\",\n    ev3_touch_sensor: \"%1's touch sensor activted?\",\n    ev3_color_sensor: \"%1's %2 value\",\n    ev3_motor_power: \"%1's value print as %2 %3\",\n    ev3_motor_power_on_time: \"%1's value for %2seconds %3 printed %4\",\n    ev3_motor_degrees: \"%1's value in %2 direction turn %3 degrees %4\",\n    rokoboard_get_sensor_value_by_name: '%1 value',\n    ardublock_digital_pwm: 'Digital %1 Pin %2 %3',\n    ardublock_get_analog_value: 'Analog %1 Sensor value',\n    ardublock_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n    ardublock_get_digital: 'Digital %1 Sensor value',\n    ardublock_get_left_cds_analog_value: 'Left CDS %1 Sensor value',\n    ardublock_get_right_cds_analog_value: 'Left CDS  %1 Sensor value',\n    ardublock_get_sound_analog_value: 'Analog Sound %1 Sensor value',\n    ardublock_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n    ardublock_set_left_motor: 'Left motor direction to %1 speed %2 set %3',\n    ardublock_set_right_motor: 'Right motor direction to %1 speed %2 set %3',\n    ardublock_set_servo: 'Set servo pin %1 angle as %2 %3',\n    ardublock_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n    ardublock_toggle_led: 'Digital %1 Pin %2 %3',\n    ardublock_toggle_left_led: 'Left Light %1 Pin %2 %3',\n    ardublock_toggle_right_led: 'Right Light %1 Pin %2 %3',\n    mkboard_digital_pwm: 'Digital %1 Pin %2 %3',\n    mkboard_get_analog_value: 'Analog %1 Sensor value',\n    mkboard_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n    mkboard_get_digital: 'Digital %1 Sensor value',\n    mkboard_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n    mkboard_set_servo: 'Set servo pin %1 angle as %2 %3',\n    mkboard_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n    mkboard_toggle_led: 'Digital %1 Pin %2 %3',\n    mkboard_set_lcd: '1602 LCD Row %1, Column %2 Value %3 %4',\n    mkboard_lcd_command: '1602 LCD Command %1 execute %2',\n    altino_analogValue: 'altino %1 sensor value',\n    altino_dot_display: 'electronic scoreboard %1 display %2',\n    altino_dot_display_line:\n        '1col %1 2col %2 3col %3 4col %4 5col %5 6col %6 7col %7 8col %8 display %9',\n    altino_light: '%1 light %2  %3',\n    altino_rear_wheel: 'rear motor right %1 left %2 setting %3',\n    altino_sound: '%1 octave %2 play  %3',\n    altino_steering: 'direction %1 setting %2',\n    jdkit_altitude: '드론을 %1 높이만큼 날리기 %2',\n    jdkit_button: '%1번 버튼 값 읽어오기',\n    jdkit_connect: '드론 연결 상태 읽어오기',\n    jdkit_emergency: '드론을 즉시 멈추기 %1',\n    jdkit_gyro: '보드 %1 기울기 값 읽어오기',\n    jdkit_joystick: '조이스틱 %1 읽기',\n    jdkit_led: '%1 LED %2  %3',\n    jdkit_motor: '%1 모터를 %2 세기로 돌리기 %3',\n    jdkit_ready: '드론 비행 준비 상태 읽어오기',\n    jdkit_rollpitch: '드론을 %1 방향 %2 세기로 움직이기 %3',\n    jdkit_throttle: '드론 프로펠러를 %1 만큼 세기로 돌리기 %2',\n    jdkit_tune: '%1 음을  %2 초동안 소리내기 %3',\n    jdkit_ultrasonic: '거리(초음파)값 읽어오기',\n    jdkit_yaw: '드론을 %1 만큼 회전하기 %2',\n    memaker_digital_pwm: 'Digital %1 Pin %2 %3',\n    memaker_get_analog_value: 'Analog %1 Sensor value',\n    memaker_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n    memaker_get_digital: 'Digital %1 Sensor value',\n    memaker_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n    memaker_set_lcd: '1602 LCD Row %1, Column %2 Value %3 %4',\n    memaker_set_servo: 'Set servo pin %1 angle as %3',\n    memaker_toggle_led: 'Digital %1 Pin %2 %3',\n    memaker_lcd_command: '1602 LCD Command %1 execute %2',\n    edumaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    edumaker_get_analog_value: '아날로그 %1 번 센서값',\n    edumaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    edumaker_get_digital: '디지털 %1 번 센서값',\n    edumaker_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n    edumaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    edumaker_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    edumaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n    creamo_get_number_sensor_value: 'PWM_Block %1 Sensor value',\n    creamo_get_port_number: '%1',\n    creamo_get_pwm_port_number: '%1',\n    creamo_motor_port_number: '%1',\n    creamo_toggle_led: 'LED_Block %1 Pin %2 %3',\n    creamo_toggle_motor: 'Motor_Block %1 pin %2 %3',\n    creamo_toggle_pwm: 'Digital %1 Pin %2 %3',\n    mechatro_get_dc_motor_current: 'Get 1%motor current',\n    mechatro_get_digital: '%1',\n    mechatro_get_sensor_value: 'Analog %1 Sensor value',\n    mechatro_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n    mechatro_set_blue_pw: 'Change PW of Bluetooth to %1%2%3%4 %5',\n    mechatro_set_dc_motor: 'Set %1 motor speed to %2 %3',\n    mechatro_set_digital: 'Digital %1 Pin %2 %3',\n    mechatro_set_pwm: 'Digital %1 Pin %2 %3',\n    mechatro_set_servo_position: 'Set servo pin %1 angle as %2 %3',\n    mechatro_set_servo_speed: 'Set servo pin %1 speed %2 degree per second %3',\n    mechatro_set_threshold: 'Set %1 threshold : %2%3',\n    mechatro_set_tone: 'Play tone pin %1 on note %2 octave %3 %4',\n    mechatro_set_tone_time: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n    funboard_buzzer_onoff: 'buzzer %1 %2',\n    funboard_buzzer_second: 'buzzer%1%2seconds%3',\n    funboard_buzzer_tone_simple: 'play note%1%2,%3sec of Melody Playing%4',\n    funboard_color_led_on_pwm: '%1COLOR  LED %2 % %3',\n    funboard_color_led_onoff: '%1COLOR  LED %2 %3',\n    funboard_convert_scale: 'Convert %1 value from %2~%3 to %4~%5',\n    funboard_dotmatrix_1column: '%1column %2set %3',\n    funboard_dotmatrix_1row: '%1row %2set %3',\n    funboard_dotmatrix_1row_1column: '%1%2 %3set %4',\n    funboard_dotmatrix_64_display: '%1 (8x8)display%2',\n    funboard_dotmatrix_big_eng: 'capital letters %1 %2',\n    funboard_dotmatrix_char_display: 'char%1display%2',\n    funboard_dotmatrix_extra_char: 'char %1 %2',\n    funboard_dotmatrix_intensity: 'Intensity %1% %2',\n    funboard_dotmatrix_kor: '∷∷  korean %1 %2',\n    funboard_dotmatrix_num: 'number %1 %2',\n    funboard_dotmatrix_onoff: 'turn all %1 %2',\n    funboard_dotmatrix_scroll_option: 'scroll direction%1%2',\n    funboard_dotmatrix_scroll_rapid: 'scroll rapid %1% %2',\n    funboard_dotmatrix_set: '%1row %2column  %3 %4',\n    funboard_dotmatrix_small_eng: 'small letter %1 %2',\n    funboard_dotmatrix_string_display: 'string%1display%2',\n    funboard_dotmatrix_string_display_scroll: 'string%1display%2scroll%3',\n    funboard_dotmatrix_symbol: 'symbol %1 %2',\n    funboard_get_analog_sensor_2state: '%1 value %2',\n    funboard_get_digital_button_value: '%1 button value',\n    funboard_get_number_sensor_value: '%1 value',\n    funboard_get_touch_button_value: '%1 touch button value',\n    funboard_set_digital_buzzer: 'Play tone octave %1 note %2 beat %3 %4',\n    funboard_what_button_pressed: '%1 button pressed.',\n    funboard_what_touch_button_pressed: '%1 touch button pressed.',\n    media_pipe_title: '%1',\n    media_pipe_video_screen: '%1 video screen %2',\n    media_pipe_switch_camera: 'Switch to %1 camera %2',\n    check_connected_camera: 'Connected to camera?',\n    media_pipe_flip_camera: 'Flip video screen %1 %2',\n    media_pipe_set_opacity_camera: 'Set video transparency effect to %1 %2',\n    media_pipe_motion_value: '%2 value detected on %1',\n    pose_landmarker_title: '%1',\n    when_pose_landmarker: '%1 When human detected',\n    pose_landmarker: '%1 human detection %2',\n    draw_detected_pose: '%1 detected human %2',\n    check_detected_pose: 'Detected human?',\n    count_detected_pose: 'Number of detected human',\n    locate_to_pose: 'Go to %2 of %1 th human %3',\n    locate_time_to_pose: 'For %1 secs go to %3 of %2 th human %4',\n    axis_detected_pose: \"%3 coordinate of %1 th human's %2\",\n    face_landmarker_title: '%1',\n    when_face_landmarker: '%1 When face detected',\n    face_landmarker: '%1 face detection %2',\n    draw_detected_face: '%1 detected face %2',\n    check_detected_face: 'Detected face?',\n    count_detected_face: 'Number of detected face',\n    locate_to_face: 'Go to %2 of %1 th face %3',\n    locate_time_to_face: 'For %1 secs go to %3 of %2 th face %4',\n    check_detected_gender: 'Is the gender of %1 th face %2?',\n    check_compare_age: 'Is the age of %1 th face %2 %3?',\n    check_detected_emotion: 'Is the emotion of %1 th face %2?',\n    axis_detected_face: '%3 coordinate of %1 the face`s %2',\n    get_detected_face_value: '%2 of %1 th face',\n    object_detector_title: '%1',\n    when_object_detector: '%1 When object detected',\n    object_detector: '%1 object detection %2',\n    draw_detected_object: '%1 detected object %2',\n    check_detected_object: 'Detected object?',\n    count_detected_object: 'Number of detected object',\n    is_detected_among_objects: '%1 detected among the objects?',\n    hand_detection_title: '%1',\n    when_hand_detection: '%1 When hand detected',\n    hand_detection: '%1 hand detection %2',\n    draw_detected_hand: '%1 detected hand %2',\n    check_detected_hand: 'Detected hand?',\n    count_detected_hand: 'Number of detected hand',\n    locate_to_hand: 'Go to %3 of %2 of in %1 th hand %4',\n    locate_time_to_hand: 'For %1 secs go to %4 of %3 of in %2 th hand %5',\n    axis_detected_hand: '%4 coordinate of %3 of %2 in %1 th hand',\n    is_which_hand: 'Is %1 th hand %2?',\n    is_which_gesture: 'Is the gesture of %1 th hand %2 ?',\n    get_which_hand: '%1 th hand',\n    get_which_gesture: 'The gesture of %1 th hand',\n    function_create_value: 'Define function %1 %2 %3 Return %4',\n    learning_title_image_str: 'Trained image classification model',\n    learning_title_speech_str: 'Trained speech classification model',\n    learning_title_text_str: 'Trained text classification model',\n    learning_title_number_str: 'Trained number classification model',\n    learning_title_regression_str: 'Trained regression model',\n    learning_title_cluster_str: 'Trained clustering model',\n    text_change_effect: '%2 %1 effect to text box %3',\n    text_change_font: 'Change font to %1 %2',\n    text_change_font_color: 'Change text color to %1 %2',\n    text_change_bg_color: 'Change background color to %1 %2',\n    learning_title_image: '%1',\n    learning_title_speech: '%1',\n    learning_title_text: '%1',\n    learning_title_number: '%1',\n    learning_title_regression: '%1',\n    learning_title_cluster: '%1',\n    insert_data_for_test: 'Classify with the trained model %1',\n    video_capture_for_image_test: '%1 classifying camera screen with the trained model ',\n    insert_text_block_for_test: 'Classify %1 with trained model %2',\n    test_result: 'Classification result',\n    accuracy_of_result: 'Reliability of %1',\n    is_group: 'Is the classification result %1?',\n    retrain_model: 'Retrain model %1',\n    model_is_trained: 'Has the model trained?',\n    set_train_visible: '%1 model %2',\n    set_train_chart: '%1 model chart window %2',\n    set_regression_option: 'Change %1 training condition to %2 %3',\n    get_regression_predict_1: 'Predicted value of %1 %2',\n    get_regression_predict_2: 'Predicted value of %1 %2 %3 %4',\n    get_regression_predict_3: 'Predicted value of %1 %2 %3 %4 %5 %6',\n    get_regression_predict_4: 'Predicted value of %1 %2 %3 %4 %5 %6 %7 %8',\n    get_regression_predict_5: 'Predicted value of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n    get_regression_predict_6: 'Predicted value of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12',\n    get_regression_accuracy: 'Coefficient of determination',\n    set_cluster_option_k: 'Change the number of clusters to %1 %2',\n    set_cluster_option_centroids: 'Change centroid standard to %1 %2',\n    get_cluster_centriod_count: 'Number of clusters',\n    get_cluster_centriod_value: 'Value of %2 of cluster %1 centroid',\n    get_cluster_centriod_index_1: 'Cluster of %1 %2',\n    get_cluster_centriod_index_2: 'Cluster of %1 %2 %3 %4',\n    get_cluster_centriod_index_3: 'Cluster of %1 %2 %3 %4 %5 %6',\n    get_cluster_centriod_index_4: 'Cluster of %1 %2 %3 %4 %5 %6 %7 %8',\n    get_cluster_centriod_index_5: 'Cluster of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n    get_cluster_centriod_index_6: 'Cluster of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12',\n    set_number_learning_option_k: 'Change the number of neighbors to %1 %2',\n    get_number_learning_predict_1: 'Classification result of %1 %2',\n    get_number_learning_predict_2: 'Classification result of %1 %2 %3 %4',\n    get_number_learning_predict_3: 'Classification result of %1 %2 %3 %4 %5 %6',\n    get_number_learning_predict_4: 'Classification result of %1 %2 %3 %4 %5 %6 %7 %8',\n    get_number_learning_predict_5: 'Classification result of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n    get_number_learning_predict_6:\n        'Classification result of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12',\n    get_number_learning_predict_param_1: '%4 for %3 of %1 %2',\n    get_number_learning_predict_param_2: '%6 for %5 of %1 %2 %3 %4',\n    get_number_learning_predict_param_3: '%8 for %5 of %1 %2 %3 %4 %5 %6',\n    get_number_learning_predict_param_4: '%8 for %5 of %1 %2 %3 %4 %5 %6 %7 %8',\n    get_number_learning_predict_param_5: '%8 for %5 of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n    get_number_learning_predict_param_6: '%8 for %5 of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12',\n    is_number_learning_group_1: 'Is the classification result of %1 %2 %3?',\n    is_number_learning_group_2: 'Is the classification result of %1 %2 %3 %4 %5?',\n    is_number_learning_group_3: 'Is the classification result of %1 %2 %3 %4 %5 %6 %7?',\n    is_number_learning_group_4: 'Is the classification result of %1 %2 %3 %4 %5 %6 %7 %8 %9?',\n    is_number_learning_group_5:\n        'Is the classification result of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11?',\n    is_number_learning_group_6:\n        'Is the classification result of %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13?',\n    video_change_cam: 'Switch to %1 camera %2',\n    video_is_model_loaded: 'detected %1?',\n    video_object_detected: 'Is %1 recognized among objects?',\n    function_value: 'Function',\n};\nLang.TextCoding = {\n    block_name: 'Block Name',\n    title_syntax: 'Syntax Error',\n    title_converting: 'Converting Error',\n    message_syntax_default: 'Syntax error occured',\n    message_syntax_unexpected_token: 'Unexpected token exist',\n    message_syntax_reserved_token: 'Unavailable variable name.',\n    message_syntax_reserved_token_list: 'Unavailable list name.',\n    message_syntax_unexpected_character: 'Unexpected characters exist',\n    message_syntax_unexpected_indent: 'Unexpected indent exist',\n    message_conv_default: 'Unsupported code exists',\n    message_conv_no_support: 'Unconvertable code exists',\n    message_conv_no_variable: 'Variable did not declare',\n    message_conv_no_list: 'List did not declare',\n    message_conv_no_object: \"Object can't convert\",\n    message_conv_no_function: \"Function can't convert\",\n    message_conv_no_entry_event_function:\n        \"Entry Event Function can't exist within other functions.\",\n    message_conv_undefined_function:\n        'Undefined instruction. Please make sure you instruction correctly.',\n    message_conv_is_expect1: 'Syntax error. Please make sure you type ',\n    message_conv_is_expect2: ' correctly.',\n    message_conv_instead: 'Syntax error. It should be %2 instead of %1.',\n    message_conv_is_wrong1: 'Syntax error. ',\n    message_conv_is_wrong2: ' are not allowed to be there.',\n    message_conv_or: ' or ',\n    subject_syntax_default: 'ETC',\n    subject_syntax_token: 'Token',\n    subject_syntax_character: 'Character',\n    subject_syntax_indent: 'Indent',\n    subject_conv_default: 'ETC',\n    subject_conv_general: 'General',\n    subject_conv_variable: 'Variable',\n    subject_conv_list: 'List',\n    subject_conv_object: 'Object',\n    subject_conv_function: 'Function',\n    alert_variable_empty_text:\n        \"You can't convert into the text mode if there is empty text among registered variables.\",\n    alert_list_empty_text:\n        \"You can't convert into the text mode if there is empty text among registered lists.\",\n    alert_function_name_field_multi:\n        \"You can't convert into the text mode if there is name field block over two times among registered functions.\",\n    alert_function_name_disorder:\n        \"You can't convert into the text mode if name field is behind than string/number or judgement param field among registered functions.\",\n    alert_function_has_boolean:\n        'If you convert into the text mode and then back to block coding, the [Judgment] used in the function is converted to [Character/Number].',\n    alert_function_editor:\n        \"Youn can't convert into the text mode in the middle of function creation or editing.\",\n    alert_function_no_support: \"Youn can't use the function creation or editing in the text mode.\",\n    alert_list_no_support: \"Youn can't use the list creation or editing in the text mode.\",\n    alert_variable_no_support: \"Youn can't use the variable creation or editing in the text mode.\",\n    alert_signal_no_support: \"Youn can't use the signal creation or editing in the text mode.\",\n    alert_legacy_no_support: 'Mode switch is not allowed due to inconvertible blocks',\n    alert_variable_empty_text_add_change: \"The empty text can't be included in variable name.\",\n    alert_list_empty_text_add_change: \"The empty text can't be included in list name.\",\n    alert_list_contains_exceed_length_value:\n        \"You can't convert into the text mode if more than 15 digits are entered in the list item.\",\n    alert_function_name_empty_text_add_change: \"The empty text can't be included in function name.\",\n    alert_no_save_on_error: \"The code with an error can't save.\",\n    alert_api_no_support:\n        'The project contains blocks \\nthat are not supported by Entry-Python. \\nDelete all those blocks and \\nchange to Entry-Python mode?',\n    warn_unnecessary_arguments:\n        \"&(calleeName)(); command doesn't require value within parentheses. (line:&(lineNumber))\",\n    python_code: \"'s python code\",\n    eof: 'line change',\n    newline: 'line change',\n    indent: 'indentation',\n    num: 'number',\n    string: 'string',\n    name: 'variable name',\n};\nLang.PythonHelper = {\n    when_run_button_click_desc:\n        '[시작하기]버튼을 클릭하면 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_run_button_click_exampleCode: 'def when_start():\\n    Entry.print(\"안녕!\")',\n    when_run_button_click_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕!\"이라 말합니다.',\n    when_some_key_pressed_desc:\n        'A키를 누르면 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_some_key_pressed_elements:\n        'A-- 아래 선택지 중 하나\\n① 알파벳 : \"A\", \"B\" ~ \"Z\" 등(소문자 가능)\\n② 숫자 : 1, 2, 3, 4 ~ 9, 0\\n③ 특수키 : \"space\", \"enter\"\\n④ 방향키 : \"up\", \"down\", \"right\", \"left\"',\n    when_some_key_pressed_exampleCode:\n        'def when_press_key(\"W\"):\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(1):\\n    Entry.add_size(10)',\n    when_some_key_pressed_exampleDesc:\n        'W키를 누르면 오브젝트가 이동방향으로 10만큼 이동하고, 1키를 누르면 오브젝트의 크기가 10만큼 커집니다.',\n    mouse_clicked_desc:\n        '마우스를 클릭했을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    mouse_clicked_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.add_size(10)\\n    Entry.move_to_direction(10)',\n    mouse_clicked_exampleDesc:\n        '마우스를 클릭하면 오브젝트의 크기가 10만큼 커지면서 이동방향으로 10만큼 이동합니다.',\n    mouse_click_cancled_desc:\n        '마우스 클릭을 해제했을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    mouse_click_cancled_exampleCode:\n        'def when_click_mouse_off():\\n    Entry.move_to_direction(-10)\\n\\ndef when_click_mouse_on():\\n    Entry.move_to_direction(10)',\n    mouse_click_cancled_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 마우스 클릭을 해제하면 오브젝트가 이동방향으로 -10만큼 이동합니다.',\n    when_object_click_desc:\n        '해당 오브젝트를 클릭했을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_object_click_exampleCode:\n        'def when_click_object_on():\\n    Entry.print_for_sec(\"회전!\", 0.5)\\n    Entry.add_rotation(90)',\n    when_object_click_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 \"회전!\"이라 말하고, 90도 만큼 회전합니다.',\n    when_object_click_canceled_desc:\n        '해당 오브젝트 클릭을 해제했을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_object_click_canceled_exampleCode:\n        'def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)',\n    when_object_click_canceled_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.',\n    when_message_cast_desc:\n        'A 신호를 받으면 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\\n만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    when_message_cast_elements: 'A-- \"신호 이름\"',\n    when_message_cast_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.send_signal(\"신호\")\\n\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"안녕! 반가워\", 0.5)',\n    when_message_cast_exampleDesc:\n        '마우스를 클릭하면 \"신호\"를 보내고, \"신호\"를 받았을때 \"안녕! 반가워\"라고 0.5초간 말합니다.',\n    message_cast_desc:\n        'A에 입력된 신호를 보냅니다.\\n만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    message_cast_elements: 'A-- \"신호 이름\"',\n    message_cast_exampleCode:\n        '#\"오브젝트1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"안녕! 넌 몇살이니?\", 2)\\n    Entry.send_signal(\"신호\")\\n\\n#\"오브젝트2\"의 파이선 코드\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"안녕? 난 세 살이야.\", 2)',\n    message_cast_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"오브젝트1\"이 \"안녕! 넌 몇살이니?\"라고 2초간 말하고 \"신호를 보냅니다., \"오브젝트2\"가 \"신호\"를 받았을때 \"안녕? 난 세 살이야.\"라고 2초간 말합니다.',\n    message_cast_wait_desc:\n        'A에 입력된 신호를 보내고, 해당 신호를 받는 명령어들의 실행이 끝날 때까지 기다립니다.\\n만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    message_cast_wait_elements: 'A-- \"신호 이름\"',\n    message_cast_wait_exampleCode:\n        '#\"오브젝트1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"숨바꼭질하자!\", 2)\\n    Entry.send_signal_wait(\"신호\")\\n    Entry.hide()\\n\\n#\"오브젝트2\"의 파이선 코드\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"그래!\", 2)',\n    message_cast_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"오브젝트1\"이 \"숨바꼭질하자!\"라고 2초 동안 말하고 \"신호\"를 보낸 후 기다립니다. \"오브젝트2\"가 \"신호\"를 받으면 \"그래!\"를 2초 동안 말합니다. \"오브젝트1\"이 그 후에 모양을 숨깁니다.',\n    when_scene_start_desc:\n        '장면이 시작되면 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_scene_start_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"다른 곳으로 가볼까?\", 2)\\n    Entry.start_scene(\"장면 2\")\\n\\n#\"장면 2\"의 파이선 코드\\ndef when_start_scene():\\n    Entry.print(\"여기가 어디지?\")',\n    when_scene_start_exampleDesc:\n        '\"장면 1\"에서 [시작하기]버튼을 클릭하면 \"다른 곳으로 가볼까?\"라고 2초간 말하고, \"장면 2\"가 시작됩니다. \"장면 2\"가 시작되면 오브젝트가 \"여기가 어디지?\"라고 말합니다.',\n    start_scene_desc: 'A 장면을 시작합니다.',\n    start_scene_elements: 'A-- \"장면 이름\"',\n    start_scene_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_click_object_on():\\n    Entry.start_scene(\"장면 2\")',\n    start_scene_exampleDesc: '\"장면 1\"에서 해당 오브젝트를 클릭하면 \"장면 2\"가 시작됩니다.',\n    start_neighbor_scene_desc: 'A에 입력한 다음 또는 이전 장면을 시작합니다.',\n    start_neighbor_scene_elements:\n        'A-- 아래 선택지 중 하나\\n① 다음 장면: \"next\" 또는 \"다음\"\\n② 이전 장면: \"prev\" 또는 \"이전\"',\n    start_neighbor_scene_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_press_key(\"right\"):\\n    Entry.start_scene_of(\"next\")\\n\\n#\"장면 2\"의 파이선 코드\\ndef when_press_key(\"left\"):\\n    Entry.start_scene_of(\"prev\")',\n    start_neighbor_scene_exampleDesc:\n        '\"장면 1\"에서 오른쪽화살표키를 누르면 다음 장면이, \"장면 2\"에서 왼쪽화살표키를 누르면 이전 장면이 시작됩니다.',\n    wait_second_desc: 'A초만큼 기다린 후 다음 블록을 실행합니다.',\n    wait_second_elements: 'A-- 초에 해당하는 수 입력',\n    wait_second_exampleCode:\n        'def when_start():\\n    Entry.add_effect(\"color\", 10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_size(10)',\n    wait_second_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트에 색깔효과를 10만큼 주고, 2초동안 기다린 다음 크기를 10만큼 커지게 합니다.',\n    repeat_basic_desc:\n        '아래 명령어들을 A번 반복하여 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_basic_elements: 'A-- 반복할 횟수 입력',\n    repeat_basic_exampleCode:\n        'def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()',\n    repeat_basic_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.',\n    repeat_inf_desc:\n        'A 판단이 True인 동안 아래 명령어들을 반복 실행합니다. A에 True를 입력하면 계속 반복됩니다. \\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_inf_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    repeat_inf_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()',\n    repeat_inf_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.',\n    repeat_while_true_desc:\n        'A 판단이 True가 될 때까지 아래 명령어들을 반복 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_while_true_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    repeat_while_true_exampleCode:\n        'def when_start():\\n    while not Entry.is_key_pressed(\"space\"):\\n        Entry.add_rotation(90)',\n    repeat_while_true_exampleDesc:\n        '[시작하기]버튼을 클릭하면 스페이스키를 누를때까지 오브젝트가 90도 만큼 회전합니다.',\n    stop_repeat_desc:\n        \"Stops the closest block that encloses this block.\\n         It works with various C-shaped blocks like 'repeat' block.\",\n    stop_repeat_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_key_pressed(\"enter\"):\\n            break',\n    stop_repeat_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 계속 이동합니다. 엔터키를 누르면 반복이 중단됩니다.',\n    _if_desc:\n        'A 부분의 판단이 True이면 if A:아래 명령어들을 실행하고, False이면 실행하지 않습니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    _if_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    _if_exampleCode:\n        'def when_click_mouse_on():\\n    if (Entry.value_of_mouse_pointer(\"x\") > 0):\\n        Entry.print_for_sec(\"오른쪽!\", 0.5)',\n    _if_exampleDesc:\n        '마우스를 클릭했을 때 마우스 x좌표가 0보다 크면 오브젝트가 \"오른쪽!\"이라고 0.5초 동안 말합니다.',\n    if_else_desc:\n        'A 부분의 판단이 True이면 if A: 아래 명령어들을 실행하고, False이면 else: 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    if_else_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    if_else_exampleCode:\n        'def when_click_mouse_on():\\n    if Entry.is_touched(\"mouse_pointer\"):\\n        Entry.print(\"닿았다!\")\\n    else:\\n        Entry.print(\"안 닿았다!\")',\n    if_else_exampleDesc:\n        '마우스를 클릭했을 때 마우스포인터가 오브젝트에 닿았으면 \"닿았다!\"를 그렇지 않으면 \"안 닿았다!\"를 말합니다.',\n    wait_until_true_desc: 'A 부분의 판단이 True가 될 때까지 코드의 실행을 멈추고 기다립니다.',\n    wait_until_true_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    wait_until_true_exampleCode:\n        'def when_start():\\n    Entry.print(\"엔터를 눌러봐!\")\\n    Entry.wait_until(Entry.is_key_pressed(\"enter\"))\\n    Entry.print(\"잘했어!\")',\n    wait_until_true_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"엔터를 눌러봐!\"라 말하고, 엔터키를 누를 때까지 기다립니다. 엔터키를 누르면 \"잘했어!\"라 말합니다.',\n    stop_object_desc: 'A코드의 실행을 중지합니다.',\n    stop_object_elements:\n        'A-- 아래 선택지 중 하나\\n① \"all\":  모든 오브젝트의 모든 코드\\n② \"self\" : 해당 오브젝트의 모든 코드\\n③ \"this\": 이 명령어가 포함된 코드\\n④ \"others\" : 해당 오브젝트의 코드 중 이 명령어가 포함된 코드를 제외한 모든 코드\\n⑤ \"ohter_objects\" : 이 오브젝트를 제외한 다른 모든 오브젝트의 코드',\n    stop_object_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.stop_code(\"all\")\\n',\n    stop_object_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 마우스포인터 위치로  이동합니다. 스페이스키를 누르면 모든 코드의 실행이 중지됩니다.',\n    restart_project_desc: '작품을 처음부터 다시 실행합니다.',\n    restart_project_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_size(10)\\n\\ndef when_press_key(\"enter\"):\\n    Entry.start_again()',\n    restart_project_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트의 크기가 커집니다. 엔터키를 누르면 작품을 처음부터 다시 실행합니다.',\n    when_clone_start_desc:\n        '해당 오브젝트의 복제본이 새로 생성되었을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_clone_start_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"self\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))',\n    when_clone_start_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.',\n    create_clone_desc: 'A 오브젝트의 복제본을 생성합니다.',\n    create_clone_elements: 'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"self\" 또는 \"자신\"',\n    create_clone_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"self\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))',\n    create_clone_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.',\n    delete_clone_desc: 'Entry.make_clone_of(A) 명령에 의해 생성된 복제본을 삭제합니다.',\n    delete_clone_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"자신\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_click_object_on():\\n    Entry.remove_this_clone()',\n    delete_clone_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 복제본을 클릭하면 클릭된 복제본을 삭제합니다.',\n    remove_all_clones_desc: '해당 오브젝트의 모든 복제본을 삭제합니다.',\n    remove_all_clones_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"자신\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_press_key(\"space\"):\\n    Entry.remove_all_clone()',\n    remove_all_clones_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 스페이스 키를 누르면 모든 복제본을 삭제합니다.',\n    move_direction_desc: 'A만큼 오브젝트의 이동방향 화살표가 가리키는 방향으로 움직입니다.',\n    move_direction_elements: 'A-- 이동할 거리에 해당하는 수',\n    move_direction_exampleCode: 'def when_start():\\n    Entry.move_to_direction(10)',\n    move_direction_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동합니다.',\n    bounce_wall_desc: '오브젝트가 화면 끝에 닿으면 튕겨져 나옵니다.',\n    bounce_wall_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()',\n    bounce_wall_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.',\n    move_x_desc: '오브젝트의 x좌표를 A만큼 바꿉니다.',\n    move_x_elements:\n        'A-- x좌표의 변화 값\\n① 양수: 오브젝트가 오른쪽으로 이동합니다.\\n② 음수: 오브젝트가 왼쪽으로 이동합니다.',\n    move_x_exampleCode:\n        'def when_start():\\n    Entry.add_x(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_x(-10)',\n    move_x_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오른쪽으로 10만큼 이동하고 2초 동안 기다린 후 왼쪽으로 10만큼 이동합니다.',\n    move_y_desc: '오브젝트의 y좌표를 A만큼 바꿉니다.',\n    move_y_elements:\n        'A-- y좌표의 변화 값\\n① 양수: 오브젝트가 위쪽으로 이동합니다.\\n② 음수: 오브젝트가 아래쪽으로 이동합니다.',\n    move_y_exampleCode:\n        'def when_start():\\n    Entry.add_y(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_y(-10)',\n    move_y_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 위쪽으로 10만큼 이동하고 2초 동안 기다린 후 아래쪽으로 10만큼 이동합니다.',\n    move_xy_time_desc: '오브젝트가 x와 y좌표를 각각 A와 B만큼 C초에 걸쳐 서서히 바꿉니다.',\n    move_xy_time_elements:\n        'A-- x좌표의 변화 값\\n① 양수: 오브젝트가 오른쪽으로 이동합니다.\\n② 음수: 오브젝트가 왼쪽으로 이동합니다.%nextB-- y좌표의 변화 값\\n① 양수: 오브젝트가 위쪽으로 이동합니다.\\n② 음수: 오브젝트가 아래쪽으로 이동합니다.%nextC-- 이동하는 시간(초)',\n    move_xy_time_exampleCode:\n        'def when_start():\\n    Entry.add_xy_for_sec(100, 100, 2)\\n    Entry.add_xy_for_sec(-100, -100, 2)',\n    move_xy_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오른쪽 위로 100만큼 2초 동안 이동한 후 왼쪽 아래로 100만큼 2초 동안 이동합니다.',\n    locate_x_desc: '오브젝트의 x좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_x_elements: 'A-- 이동할 x좌표',\n    locate_x_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_x(100)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_x(-100)\\n',\n    locate_x_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 100으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 x좌표를 -100으로 정합니다.',\n    locate_y_desc: '오브젝트의 y좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_y_elements: 'B-- 이동할 y좌표',\n    locate_y_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.set_y(100)\\n\\ndef when_press_key(\"down\"):\\n    Entry.set_y(-100)',\n    locate_y_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 y좌표를 100으로 정하고, 아래쪽화살표키를 누르면 오브젝트의 y좌표를 -100으로 정합니다.',\n    locate_xy_desc: '오브젝트가 좌표(A, B)로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_elements: 'A-- 이동할 x좌표%nextB-- 이동할 y좌표',\n    locate_xy_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_xy(0, 0)\\n\\ndef when_press_key(\"right\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\"up\"):\\n    Entry.add_y(10)',\n    locate_xy_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 오브젝트의 x, y좌표를 0으로 정합니다.',\n    locate_xy_time_desc:\n        '오브젝트가 좌표(A, B)로 C초에 걸쳐 서서히 이동합니다.(오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_time_elements: 'A-- 이동할 x좌표%nextB-- 이동할 y좌표%nextC-- 이동하는 시간',\n    locate_xy_time_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_xy_for_sec(0, 0, 2)\\n\\ndef when_press_key(\"right\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\"up\"):\\n    Entry.add_y(10)',\n    locate_xy_time_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 2초 동안 오브젝트를 x,y 좌표 0으로 이동시킵니다.',\n    locate_desc: '오브젝트가 A의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    locate_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.move_to(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.move_to(\"오브젝트\")',\n    locate_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 마우스포인터 위치로 이동합니다.\\n스페이스키를 누르면 오브젝트가 \"오브젝트\" 위치로 이동합니다.',\n    locate_object_time_desc:\n        '오브젝트가 A의 위치로 B초에 걸쳐 서서히 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_object_time_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\" %nextB-- 이동하는 시간(초)',\n    locate_object_time_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.move_to_for_sec(\"mouse_pointer\", 2)',\n    locate_object_time_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 2초 동안 서서히 마우스포인터 위치로 이동합니다.',\n    rotate_relative_desc:\n        '오브젝트의 방향을 A도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_relative_elements: 'A-- 회전할 각도',\n    rotate_relative_exampleCode:\n        'def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)',\n    rotate_relative_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.',\n    direction_relative_desc: '오브젝트의 이동 방향을 A도만큼 회전합니다.',\n    direction_relative_elements: 'A-- 회전할 각도',\n    direction_relative_exampleCode:\n        'def when_start():\\n    Entry.move_to_direction(50)\\n    Entry.wait_for_sec(0.5)\\n    Entry.add_direction(90)\\n    Entry.wait_for_sec(0.5)\\n    Entry.move_to_direction(50)',\n    direction_relative_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 50만큼 이동한 다음 0.5초간 기다립니다. 그 후 이동방향을 90도 만큼 회전하고 0.5초간 기다린 후 이동방향으로 50만큼 이동합니다.',\n    rotate_by_time_desc:\n        '오브젝트의 방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_by_time_elements: 'A-- 회전할 각도%nextB-- 회전할 시간(초)',\n    rotate_by_time_exampleCode:\n        'def when_start():\\n    Entry.add_rotation_for_sec(90, 2)\\n    Entry.add_rotation_for_sec(-90, 2)',\n    rotate_by_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 2초 동안 90도 만큼 회전하고, 다시 2초 동안 -90도 만큼 회전합니다.',\n    direction_relative_duration_desc:\n        '오브젝트의 이동방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    direction_relative_duration_elements: 'A-- 회전할 각도%nextB-- 회전할 시간(초)',\n    direction_relative_duration_exampleCode:\n        'def when_start():\\n    Entry.add_direction_for_sec(90, 2)\\n\\ndef when_start():\\n    while True:\\n        Entry.move_to_direction(1)',\n    direction_relative_duration_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트의 이동방향을 2초 동안 90도만큼 회전시킵니다. 동시에 오브젝트는 이동방향으로 1만큼 계속 이동합니다.',\n    rotate_absolute_desc: '오브젝트의 방향을 A로 정합니다.',\n    rotate_absolute_elements: 'A-- 설정할 방향',\n    rotate_absolute_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_rotation(90)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_rotation(270)',\n    rotate_absolute_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 방향을 90으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 방향을 270으로 정합니다.',\n    direction_absolute_desc: '오브젝트의 이동방향을 A로 정합니다.',\n    direction_absolute_elements: 'A-- 설정할 이동방향',\n    direction_absolute_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_direction(90)\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_direction(270)\\n    Entry.move_to_direction(10)',\n    direction_absolute_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 이동방향을 90으로 정한 후 해당 쪽으로 10만큼 이동하고, 왼쪽화살표키를 누르면 오브젝트의 이동방향을 270으로 정하고 해당쪽으로 10만큼 이동합니다.',\n    see_angle_object_desc:\n        '오브젝트가 A쪽을 바라봅니다. (이동방향이 A를 향하도록 오브젝트의 방향을 회전해줍니다.)',\n    see_angle_object_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    see_angle_object_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.look_at(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.look_at(\"오브젝트\")',\n    see_angle_object_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 마우스포인터쪽을 바라보고, 스페이스키를 누르면 \"오브젝트\"쪽을 바라봅니다.',\n    move_to_angle_desc: '오브젝트가 A만큼 B방향으로 움직입니다.',\n    move_to_angle_elements:\n        'A-- 이동할 거리에 해당하는 수%nextB-- 이동할 방향(12시 방향이 0도, 시계방향으로 증가)',\n    move_to_angle_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.move_to_degree(10, 0)\\n\\ndef when_press_key(\"down\"):\\n    Entry.move_to_degree(10, 180)',\n    move_to_angle_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트가 0도방향으로 10만큼 이동하고, 아래쪽화살표키를 누르면 오브젝트가 180도방향으로 10만큼 이동합니다.',\n    show_desc: '오브젝트를 화면에 나타냅니다.',\n    show_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()',\n    show_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.',\n    hide_desc: '오브젝트를 화면에서 보이지 않게 합니다.',\n    hide_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()',\n    hide_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.',\n    dialog_time_desc:\n        '오브젝트가 A를 B초 동안 말풍선으로 말한 후 다음 명령어가 실행됩니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.',\n    dialog_time_elements:\n        'A-- 말할 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등%nextB-- 말하는 시간(초)',\n    dialog_time_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(\"안녕! 나는\", 2)\\n    Entry.print_for_sec(16, 2)\\n    Entry.print_for_sec(\"살이야\", 2)',\n    dialog_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"안녕! 나는\", 16, \"살이야\"를 각각 2초 동안 차례대로 말합니다.',\n    dialog_desc: '오브젝트가 A를 말풍선으로 말합니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.',\n    dialog_elements: 'A-- 말할 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    dialog_exampleCode:\n        'def when_start():\\n    Entry.print(\"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\")\\n\\ndef when_press_key(1):\\n    Entry.print(1)\\n\\ndef when_press_key(2):\\n    Entry.print(2)\\n',\n    dialog_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\"를 말하고, 키보드로 1, 2를 누르면 각각 1, 2라 말합니다.',\n    remove_dialog_desc: '오브젝트가 말하고 있는 말풍선을 지웁니다.',\n    remove_dialog_exampleCode:\n        'def when_start():\\n    Entry.print(\"말풍선을 지우려면 엔터를 눌러!\")\\n\\ndef when_press_key(\"enter\"):\\n    Entry.clear_print()',\n    remove_dialog_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"말풍선을 지우려면 엔터를 눌러!\"라 말하고, 엔터키를 누르면 말풍선이 사라집니다.',\n    change_to_some_shape_desc: '오브젝트를 A 모양으로 바꿉니다.',\n    change_to_some_shape_elements:\n        'A-- 아래 선택지 중 하나\\n① 모양 이름 : [속성] 탭의 \"모양 이름\"을 적음\\n② 모양 번호 : [속성] 탭의 모양 번호를 적음',\n    change_to_some_shape_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\"오브젝트모양\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\"오브젝트모양\")',\n    change_to_some_shape_exampleDesc:\n        '[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 \"오브젝트모양\"으로 모양을 바꾸고 0.3초간 기다린 다음 \"오브젝트모양\"모양으로 모양을 바꿉니다.',\n    change_to_next_shape_desc: '오브젝트의 모양을 다음 또는 이전 모양으로 바꿉니다.',\n    change_to_next_shape_elements:\n        'A-- 아래 선택지 중 하나\\n① 다음 모양 : \"next\" 또는 \"다음\" \\n② 이전 모양 : \"pre\" 또는 \"이전\"',\n    change_to_next_shape_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\"next\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\"pre\")',\n    change_to_next_shape_exampleDesc:\n        '[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 모양으로 오브젝트 모양을 바꾸고 0.3초간 기다린 다음 이전 모양으로 오브젝트 모양을 바꿉니다.',\n    add_effect_amount_desc: '오브젝트에 A 효과를 B만큼 줍니다.',\n    add_effect_amount_elements:\n        'A -- 아래 선택지 중 하나\\n① “color” 또는 “색깔“                 \\n② “brightness” 또는 “밝기”                \\n③ “transparency” 또는 “투명도”%nextB-- 효과의 변화 정도',\n    add_effect_amount_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.add_effect(\"color\", 50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\"brightness\", -50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\"transparency\", 50)',\n    add_effect_amount_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔 효과를 50만큼 주고 1초간 기다리고, 밝기 효과를 -50만큼 주고 1초간 기다립니다. 그 후 투명도 효과를 50만큼 줍니다.',\n    change_effect_amount_desc: '오브젝트의 A 효과를 B로 정합니다.',\n    change_effect_amount_elements:\n        'A-- 아래 선택지 중 하나\\n① “color” 또는 “색깔“                 \\n② “brightness” 또는 “밝기”                \\n③ “transparency” 또는 “투명도”%nextB-- 효과의 값\\n① color: 0~100 범위의 수, 100을 주기로 반복됨\\n② brightness: -100~100 사이 범위의 수, -100이하는 -100 으로 100 이상은 100 으로 처리 됨\\n③ transparency: 0~100 사이 범위의 수, 0 이하는 0으로, 100이상은 100으로 처리 됨',\n    change_effect_amount_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_effect(\"color\", 50)\\n    Entry.set_effect(\"brightness\", 50)\\n    Entry.set_effect(\"transparency\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.set_effect(\"color\", 0)\\n    Entry.set_effect(\"brightness\", 0)\\n    Entry.set_effect(\"transparency\", 0)',\n    change_effect_amount_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 각 효과를 0으로 정합니다.',\n    erase_all_effects_desc: '오브젝트에 적용된 효과를 모두 지웁니다.',\n    erase_all_effects_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_effect(\"color\", 50)\\n    Entry.set_effect(\"brightness\", 50)\\n    Entry.set_effect(\"transparency\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.clear_effect()\\n',\n    erase_all_effects_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 오브젝트에 적용된 모든 효과를 지웁니다.',\n    change_scale_size_desc: '오브젝트의 크기를 A만큼 바꿉니다.',\n    change_scale_size_elements: 'A-- 크기 변화 값',\n    change_scale_size_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\"space\"):\\n    Entry.set_size(100)',\n    change_scale_size_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.',\n    set_scale_size_desc: '오브젝트의 크기를 A로 정합니다.',\n    set_scale_size_elements: 'A-- 크기값',\n    set_scale_size_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\"space\"):\\n    Entry.set_size(100)',\n    set_scale_size_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.',\n    flip_x_desc: '오브젝트의 상하 모양을 뒤집습니다.',\n    flip_x_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\"right\"):\\n    Entry.flip_vertical()',\n    flip_x_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.',\n    flip_y_desc: '오브젝트의 좌우 모양을 뒤집습니다.',\n    flip_y_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\"right\"):\\n    Entry.flip_vertical()',\n    flip_y_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.',\n    change_object_index_desc: '오브젝트의 레이어를 A로 가져옵니다.',\n    change_object_index_elements:\n        'A-- 아래 선택지 중 하나\\n① “front\" 또는 “맨 앞“                 \\n② “forward” 또는 “앞”                \\n③ “backward” 또는 “뒤”\\n④ “back” 또는 “맨 뒤”',\n    change_object_index_exampleCode:\n        'def when_start():\\n    Entry.send_layer_to(\"front\")\\n    Entry.wait_for_sec(2)\\n    Entry.send_layer_to(\"backward\")',\n    change_object_index_exampleDesc:\n        '오브젝트가 여러개가 겹쳐 있을 경우 [시작하기]버튼을 클릭하면  해당 오브젝트의 레이어를 가장 앞으로 가져와서 보여줍니다.',\n    brush_stamp_desc: '오브젝트의 모양을 도장처럼 실행화면 위에 찍습니다.',\n    brush_stamp_exampleCode:\n        'def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()',\n    brush_stamp_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.',\n    start_drawing_desc:\n        '오브젝트가 이동하는 경로를 따라 선이 그려지기 시작합니다. (오브젝트의 중심점이 기준)',\n    start_drawing_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    for i in range(10):\\n        Entry.move_to_direction(10)',\n    start_drawing_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 오브젝트가 이동방향으로 10만큼 10번 이동할 때 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    stop_drawing_desc: '오브젝트가 선을 그리는 것을 멈춥니다.',\n    stop_drawing_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n\\ndef when_click_mouse_on():\\n    Entry.stop_drawing()',\n    stop_drawing_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 마우스를 클릭하면 그리는것을 멈춥니다.',\n    set_color_desc: '오브젝트가 그리는 선의 색을 A로 정합니다.',\n    set_color_elements:\n        'A-- 아래 선택지 중 하나\\n① 색상 코드 : \"#FF0000\", \"#FFCC00\", \"#3333FF\", \"#000000\" 등\\n② 색깔명 : \"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"navy\", \"purple\", \"black\", \"white\", \"brown\"',\n    set_color_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_color_to(\"#000099\")\\n    while True:\\n        Entry.move_to_direction(1)',\n    set_color_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 색을 \"#000099\"로 정합니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    set_random_color_desc: '오브젝트가 그리는 선의 색을 무작위로 정합니다.',\n    set_random_color_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n        Entry.set_brush_color_to_random()',\n    set_random_color_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 색깔은 계속해서 무작위로 정해집니다.',\n    change_thickness_desc: '오브젝트가 그리는 선의 굵기를 A만큼 바꿉니다.',\n    change_thickness_elements: 'A-- 굵기 변화 값',\n    change_thickness_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.add_brush_size(1)\\n        Entry.move_to_direction(10)',\n    change_thickness_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 굵기는 계속해서 1씩 커집니다.',\n    set_thickness_desc: '오브젝트가 그리는 선의 굵기를 A로 정합니다.',\n    set_thickness_elements: 'A-- 굵기값(1이상의 수)',\n    set_thickness_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)',\n    set_thickness_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    change_brush_transparency_desc: '오브젝트가 그리는 선의 투명도를 A만큼 바꿉니다.',\n    change_brush_transparency_elements: 'A-- 투명도 변화 값',\n    change_brush_transparency_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.add_brush_transparency(5)',\n    change_brush_transparency_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 투명도는 계속해서 5만큼 바꿉니다.',\n    set_brush_tranparency_desc: '오브젝트가 그리는 선의 투명도를 A로 정합니다.',\n    set_brush_tranparency_elements: 'A-- 투명도값(0~100 의 범위)',\n    set_brush_tranparency_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    Entry.set_brush_transparency(50)\\n    while True:\\n        Entry.move_to_direction(10)',\n    set_brush_tranparency_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로, 선의 투명도를 50으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    brush_erase_all_desc: '오브젝트가 그린 선과 도장을 모두 지웁니다.',\n    brush_erase_all_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(10)\\n\\ndef when_click_mouse_on():\\n    Entry.clear_drawing()',\n    brush_erase_all_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 마우스를 클릭하면 오브젝트가 그린 선을 모두 지웁니다.',\n    text_read_desc:\n        '글상자 A의 내용입니다.\\n(내용 안에 개행이 있는 경우, 띄어쓰기하여 반환됩니다.)',\n    text_read_elements: 'A-- 아래 선택지 중 하나\\n① \"오브젝트(글상자) 이름\" \\n② 자기 자신',\n    text_read_exampleCode: 'def when_start():\\n    Entry.print(Entry.contents_of_textbox(\"A\"))',\n    text_read_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 글상자 \"A\"의 내용을 말합니다.​',\n    text_write_desc: '글상자의 내용을 A로 고쳐씁니다.',\n    text_write_elements: 'A-- 글상자의 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    text_write_exampleCode: 'def when_start():\\n    Entry.write_text(\"엔트리\")',\n    text_write_exampleDesc: '[시작하기]버튼을 클릭하면 글상자의 내용을 \"엔트리\"로 바꿉니다.',\n    text_append_desc: '글상자의 내용 뒤에 A를 추가합니다.',\n    text_append_elements:\n        'A-- 글상자의 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    text_append_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"안녕?\")\\n    Entry.wait_for_sec(1)\\n    Entry.append_text(\"엔트리!\")',\n    text_append_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"안녕?\"이 되었다가 1초 뒤에 \"엔트리!\"가 추가되어 \"안녕?엔트리!\"가 됩니다.',\n    text_prepend_desc: '글상자의 내용 앞에 A를 추가합니다.',\n    text_prepend_elements:\n        'A-- 글상자의 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    text_prepend_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"반가워!\")\\n    Entry.wait_for_sec(1)\\n    Entry.prepend_text(\"엔트리!\")',\n    text_prepend_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"반가워!\"가 되었다가 1초 뒤에 \"엔트리!\"가 앞에 추가되어 \"엔트리!반가워!\"가 됩니다.',\n    text_flush_desc: '글상자에 저장된 값을 모두 지웁니다.',\n    text_flush_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"엔트리\")\\n    Entry.wait_for_sec(1)\\n    Entry.clear_text()',\n    text_flush_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"엔트리\"가 되었다가 1초 뒤에 모든 내용이 사라집니다.',\n    sound_something_with_block_desc: '오브젝트가 A 소리를 재생합니다.',\n    sound_something_with_block_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound(\"소리\")\\n    Entry.add_size(50)',\n    sound_something_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 재생하면서 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_second_with_block_desc: '오브젝트가 A소리를 B초 만큼 재생합니다.',\n    sound_something_second_with_block_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_second_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_for_sec(\"소리\", 1)\\n    Entry.add_size(50)',\n    sound_something_second_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 1초 동안 재생하면서, 오브젝트의 크기가 50만큼 커집니다.',\n    sound_from_to_desc: '오브젝트가 A소리를 B초부터 C초까지 재생합니다.',\n    sound_from_to_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_from_to_exampleCode:\n        'def when_start():\\n    Entry.play_sound_from_to(\"소리\", 0.5, 1)\\n    Entry.add_size(50)',\n    sound_from_to_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 0.5초부터 1초 구간까지만 재생하면서, 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_wait_with_block_desc:\n        '오브젝트가 A 소리를 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_something_wait_with_block_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_wait_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_and_wait(\"소리\")\\n    Entry.add_size(50)',\n    sound_something_wait_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_second_wait_with_block_desc:\n        '오브젝트가 A소리를 B초 만큼 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_something_second_wait_with_block_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_second_wait_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_for_sec_and_wait(\"소리\", 1)\\n    Entry.add_size(50)',\n    sound_something_second_wait_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 1초 동안 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_from_to_and_wait_desc:\n        '오브젝트가 A소리를 B초부터 C초까지 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_from_to_and_wait_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_from_to_and_wait_exampleCode:\n        'def when_start():\\n    Entry.play_sound_from_to_and_wait(\"소리\", 0.5, 1)\\n    Entry.add_size(50)',\n    sound_from_to_and_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 0.5초부터 1초 구간까지만 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_volume_change_desc: '작품에서 재생되는 모든 소리의 크기를 A퍼센트만큼 바꿉니다.',\n    sound_volume_change_elements: 'A-- 소리 크기 변화 값',\n    sound_volume_change_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")',\n    sound_volume_change_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\"작아집니다.',\n    sound_volume_set_desc: '작품에서 재생되는 모든 소리의 크기를 A퍼센트로 정합니다.',\n    sound_volume_set_elements: 'A-- 소리 크기값',\n    sound_volume_set_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_press_key(\"enter\"):\\n    Entry.set_sound_volume(100)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")',\n    sound_volume_set_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\"작아집니다. 엔터키를 누르면 소리의 크기를 100\"로 정합니다.',\n    sound_silent_all_desc: '현재 재생 중인 모든 소리를 멈춥니다.',\n    sound_silent_all_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")\\n\\ndef when_press_key(\"enter\"):\\n    Entry.stop_sound()',\n    sound_silent_all_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 엔터키를 누르면 현재 재생 중인 소리를 멈춥니다.',\n    is_clicked_desc: '마우스를 클릭한 경우 True로 판단합니다.',\n    is_clicked_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_mouse_clicked():\\n            Entry.print_for_sec(\"반가워!\", 0.5)',\n    is_clicked_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 마우스를 클릭했는지 확인합니다. 만약 마우스를 클릭하면 오브젝트가 \"반가워!\"라고 0.5초간 말합니다.',\n    is_press_some_key_desc: 'A 키가 눌려져 있는 경우 True로 판단합니다.',\n    is_press_some_key_elements:\n        'A-- 아래 선택지 중 하나\\n① 알파벳 : \"A\", \"B\" ~ \"Z\" 등(소문자 가능)\\n② 숫자: 1, 2, 3, 4 ~ 9, 0\\n③ 특수키: \"space\", \"enter\"\\n④ 방향키 : \"up\", \"down\", \"right\", \"left\"',\n    is_press_some_key_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"space\"):\\n            Entry.move_to_direction(10)',\n    is_press_some_key_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 선택한 키를 눌렀는지 확인합니다. 만약 스페이스 키를 누르면 오브젝트가 이동방향으로 10만큼 이동합니다.',\n    reach_something_desc: '오브젝트가 A와 닿은 경우 True으로 판단합니다.',\n    reach_something_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\"\\n③ \"edge\", \"edge_up\", \"edge_down\", \"edge_right\", \"edge_left\"',\n    reach_something_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_touched(\"edge\"):\\n            Entry.add_rotation(150)',\n    reach_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 만약 오브젝트가 벽에 닿으면 150만큼 회전하게 됩니다.',\n    boolean_basic_operator_desc: 'A와 B를 비교하여 True 또는 False로 판단합니다.',\n    boolean_basic_operator_elements:\n        'A, B 비교하고자 하는 숫자값\\n① == : A와 B의 값이 같으면 True, 아니면 False\\n② != : A와 B의 값이 다르면 True, 아니면 False\\n③ > : A의 값이 B의 값보다 크면 true, 아니면 False\\n④ < : A의 값이 B의 값보다 작으면 true, 아니면 False\\n⑤ >= : A의 값이 B의 값보다 크거나 같으면 true, 아니면 False\\n⑥ <= : A의 값이 B의 값보다 작거나 같으면 true, 아니면 False',\n    boolean_basic_operator_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_x(10)\\n        if Entry.value_of_object(\"오브젝트\", \"x\") > 240:\\n            Entry.set_x(0)',\n    boolean_basic_operator_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트 x좌표를 10만큼 바꿉니다. 만약 오브젝트 x좌표가 240보다 크면 오브젝트 x좌표를 0으로 정합니다.',\n    boolean_and_desc: 'A와 B의 판단이 모두 True인 경우 True, 아닌 경우 False로 판단합니다.',\n    boolean_and_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_and_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") and Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_and_exampleDesc:\n        '[시작하기]버튼을 클릭하고 키보드의 \"a\" 와 \"s\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.',\n    boolean_or_desc: 'A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False로 판단합니다.',\n    boolean_or_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_or_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") or Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_or_exampleDesc:\n        '[시작하기]버튼을 클릭하면 키보드의 \"a\"나 \"s\"키 중 무엇이든 하나를 누르면 오브젝트에 색깔 효과를 10만큼 줍니다.',\n    boolean_not_desc: 'A 판단이 True이면 False, False이면 True로 판단합니다.',\n    boolean_not_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_not_exampleCode:\n        'def when_start():\\n    while True:\\n        if not Entry.is_mouse_clicked():\\n            Entry.add_size(1)',\n    boolean_not_exampleDesc:\n        '[시작하기]버튼을 클릭하면 마우스를 클릭하지 않은 동안 크기가 1씩 커집니다.',\n    calc_basic_desc: 'A와 B의 연산값입니다.',\n    calc_basic_elements:\n        'A, B-- 연산하고자 하는 숫자값\\n① + : A와 B를 더한 값\\n② - : A와 B를 뺀 값\\n③ x : A와 B를 곱한 값\\n④ / : A와 B를 나눈 값',\n    calc_basic_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 + 10, 2)\\n    Entry.print_for_sec(10 - 10, 2)\\n    Entry.print_for_sec(10 * 10, 2)\\n    Entry.print_for_sec(10 / 10, 2)',\n    calc_basic_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10과 10을 더한값, 뺀값, 곱한값, 나눈값을 각 2초간 말합니다.',\n    calc_rand_desc:\n        'A와 B 사이에서 선택된 무작위 수의 값입니다. (두 수 모두 정수를 입력한 경우 정수로,두 수 중 하나라도 소수를 입력한 경우 소수로 무작위 수가 선택됩니다.)',\n    calc_rand_elements:\n        'A, B-- 무작위 수를 추출할 범위\\n① random.randint(A, B) : A, B를 정수로 입력하면 정수 범위에서 무작위 수를 추출\\n② random.uniform(A, B) : A, B를 실수로 입력하면 실수 범위에서 무작위 수를 추출',\n    calc_rand_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(random.randint(1, 10), 2)\\n    Entry.print_for_sec(random.uniform(0.1, 2), 2)',\n    calc_rand_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1부터 10사이의 정수중 무작위 수를 뽑아 2초간 말합니다. 그 후 0.1부터 2사이의 실수중 무작위 수를 뽑아 2초간 말합니다.',\n    coordinate_mouse_desc: '마우스 포인터의 A 좌표 값을 의미합니다.',\n    coordinate_mouse_elements: 'A-- 아래 선택지 중 하나\\n① \"x\" 또는 \"X\"\\n② \"y\" 또는 \"Y\"',\n    coordinate_mouse_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_mouse_pointer(\"x\"))',\n    coordinate_mouse_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 마우스 포인터의 x좌표를 계속해서 말합니다.',\n    coordinate_object_desc: 'A에 대한 B정보값입니다.',\n    coordinate_object_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"self\" 또는 \"자신\"%nextB-- 아래 선택지 중 하나\\n① \"x\" 또는 \"X\"\\n② \"y\" 또는 \"Y\"\\n③ \"rotation\" 또는 \"방향\"\\n④ \"direction\" 또는 \"이동 방향\"\\n⑤ \"size\"  또는 \"크기\"\\n⑥ \"shape_number\" 또는 \"모양 번호\"\\n⑦ \"shape_name\" 또는 \"모양 이름\"',\n    coordinate_object_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_x(1)\\n        Entry.print(Entry.value_of_object(\"오브젝트\", \"x\"))\\n',\n    coordinate_object_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트의 x좌표가 1씩 증가하며, \"오브젝트\"의 x좌표를 말합니다.',\n    get_sound_volume_desc: '현재 작품에 설정된 소리의 크기값입니다.',\n    get_sound_volume_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_sound_volume())',\n    get_sound_volume_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 소리의 크기값을 계속해서 말합니다.',\n    quotient_and_mod_desc: 'A와 B의 연산값입니다.',\n    quotient_and_mod_elements:\n        'A, B-- 연산하고자 하는 숫자값\\n① // : A / B의 몫에 해당하는 값\\n② % : A / B의 나머지에 해당하는 값',\n    quotient_and_mod_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 // 3, 2)\\n    Entry.print_for_sec(10 % 3, 2)',\n    quotient_and_mod_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10 / 3의 몫인 3을 2초 동안 말하고, 나머지인 1을 2초 동안 말합니다.',\n    calc_operation_desc: 'A의 연산값입니다.',\n    calc_operation_elements:\n        'A, B-- 연산하고자 하는 숫자값\\n① A ** 2 : A를 제곱한 값\\n② math.sqrt(A): A의 루트값\\n③ math.sin(A): A의 사인값\\n④ math.cos(A): A의 코사인 값\\n⑤ math.tan(A):  A의 탄젠트값 \\n⑥ math.asin(A): A의 아크사인값\\n⑦ math.acos(A): A의 아크코사인값\\n⑧ math.atan(): A의 아크탄젠트값\\n⑨ math.log10(A): A의 로그값\\n⑩ math.log(A): A의 자연로그값\\n⑪ A - math.floor(A): A의 소수점 부분\\n⑫ math.floor(A): A의 소수점 버림값\\n⑬ math.ceil(A): A의 소수점 올림값\\n⑭ math.round(A): A의 소수점 반올림값\\n⑮ math.factorial(A): A의 팩토리얼 값\\n⑯ math.fabs(A): A의 절댓값',\n    calc_operation_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 ** 2, 2)\\n    Entry.print_for_sec(math.sqrt(9), 2)\\n    Entry.print_for_sec(math.sin(90), 2)\\n    Entry.print_for_sec(math.fabs(-10), 2)',\n    calc_operation_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10의 제곱, 9의 루트값, 90의 사인값, -10의 절댓값을 각 2초 동안 말합니다.',\n    get_project_timer_value_desc: '이 명령이 실행되는 순간 초시계에 저장된 값입니다.',\n    get_project_timer_value_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    get_project_timer_value_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    choose_project_timer_action_desc:\n        '초시계의 동작을 A로 정합니다.\\n(이 명령어를 사용하면 실행화면에 ‘초시계 창’이 생성됩니다.)',\n    choose_project_timer_action_elements:\n        'A-- 아래 선택지 중 하나\\n① \"start\" : 초시계를 시작\\n② \"stop\" : 초시계를 정지\\n③ \"reset\" : 초시계를 초기화',\n    choose_project_timer_action_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    choose_project_timer_action_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    set_visible_project_timer_desc: '실행화면의 초시계 창을 A로 설정합니다.',\n    set_visible_project_timer_elements:\n        'A-- 아래 선택지 중 하나\\n① \"hide\" : 초시계창을 숨김\\n② \"show\" : 초시계창을 보임',\n    set_visible_project_timer_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    set_visible_project_timer_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    get_date_desc: '현재 A에 대한 값입니다.',\n    get_date_elements:\n        'A-- 아래 선택지 중 하나\\n① \"year\" : 현재 연도 값\\n② \"month\" : 현재 월 값\\n③ \"day\" : 현재 일 값\\n④ \"hour\" : 현재 시간 값\\n⑤ \"minute\" : 현재 분 값\\n⑥ \"second\" : 현재 초 값',\n    get_date_exampleCode:\n        'def when_start():\\n    Entry.print(Entry.value_of_current_time(\"year\") + \"년\" + Entry.value_of_current_time(\"month\") + \"월\")',\n    get_date_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 현재년도와 월을 말합니다.',\n    distance_something_desc: '자신과 A까지의 거리 값입니다.',\n    distance_something_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    distance_something_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_distance_to(\"mouse_pointer\"))',\n    distance_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 마우스포인터와의 거리를 계속해서 말합니다.',\n    get_sound_duration_desc: '소리 A의 길이(초)값입니다.',\n    get_sound_duration_elements: 'A-- \"소리 이름\"',\n    get_sound_duration_exampleCode:\n        'def when_start():\\n    Entry.print(Entry.value_of_sound_length_of(\"소리\"))',\n    get_sound_duration_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"소리\"의 길이를 말합니다.',\n    get_user_name_desc:\n        'Reports the user ID who runs the project.\\nThe value is masked for privacy.',\n    get_user_name_exampleCode: 'def when_start():\\n    Entry.print(Entry.value_of_username())',\n    get_user_name_exampleDesc:\n        '[시작하기]버튼을 클릭하면 작품을 실행하고 있는 사용자의 이름 값을 말합니다.',\n    get_nickname_desc: '작품을 실행하고 있는 사용자의 닉네임 값입니다.',\n    get_nickname_exampleCode: 'def when_start():\\n    Entry.print(Entry.value_of_nickname())',\n    get_nickname_exampleDesc:\n        '[시작하기]버튼을 클릭하면 작품을 실행하고 있는 사용자의 닉네임 값을 말합니다.',\n    length_of_string_desc: '입력한 문자값의 공백을 포함한 글자 수입니다.',\n    length_of_string_elements: 'A-- \"문자열\"',\n    length_of_string_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(len(\"안녕\"), 2)\\n    Entry.print_for_sec(len(\"엔트리\"), 2)',\n    length_of_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕\"과 \"엔트리\"의 글자 수를 각각 2초 동안 말합니다.',\n    combine_something_desc:\n        'A 문자열과 B 문자열을 결합한 값입니다. (A, B 중 하나가 숫자면 문자열로 바꾸어 처리되고, 둘 다 숫자면 덧셈 연산으로 처리됩니다.)',\n    combine_something_elements: 'A, B-- \"문자열\"',\n    combine_something_exampleCode: 'def when_start():\\n    Entry.print(\"안녕! \" + \"엔트리\")',\n    combine_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕!\"과 \"엔트리\"를 결합한 \"안녕! 엔트리\"를 말합니다.',\n    char_at_desc: 'A 문자열의 B번째의 글자 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    char_at_elements: 'A-- \"문자열\"%nextB-- 찾고자 하는 문자열의 위치',\n    char_at_exampleCode: 'def when_start():\\n    Entry.print(\"안녕 엔트리!\"[0])',\n    char_at_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"의 0번째 글자인 \"안\"을 말합니다.',\n    substring_desc:\n        'A 문자열의 B위치부터 C-1위치까지의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    substring_elements:\n        'A-- \"문자열\"%nextB-- 포함할 문자열의 시작 위치\\n첫 번째 글자는 0부터 시작%nextC-- 문자열을 포함하지 않는 위치',\n    substring_exampleCode: 'def when_start():\\n    Entry.print(\"안녕 엔트리!\"[1:5])',\n    substring_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"의 1에서 4번째 글자인 \"녕 엔트\"를 말합니다.',\n    index_of_string_desc:\n        'A문자열에서 B문자열이 처음으로 등장하는 위치의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    index_of_string_elements: 'A, B-- \"문자열\"',\n    index_of_string_exampleCode:\n        'def when_start():\\n    Entry.print(\"안녕 엔트리!\".find(\"엔트리\"))',\n    index_of_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"에서 \"엔트리\"가 처음으로 등장하는 위치인 3을 말합니다.',\n    replace_string_desc:\n        'A 문자열에서 B문자열을 모두 찾아 C문자열로 바꾼 값입니다.\\n(영문 입력시 대소문자를 구분합니다.)',\n    replace_string_elements: 'A, B, C-- \"문자열\"',\n    replace_string_exampleCode:\n        'def when_start():\\n    Entry.print(\"안녕 엔트리!\".replace( \"안녕\", \"반가워\"))',\n    replace_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"에서 \"안녕\"을 \"반가워\"로 바꾼 \"반가워 엔트리!\"를 말합니다.',\n    change_string_case_desc: 'A의 모든 알파벳을 대문자 또는 소문자로 바꾼 문자값입니다.',\n    change_string_case_elements:\n        'A-- \"문자열\"\\n① A.upper(): A의 모든 알파벳을 대문자로 바꾼 값\\n② A.lower() : A의 모든 알파벳을 소문자로 바꾼 값',\n    change_string_case_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(\"Hello Entry!\".upper(), 2)\\n    Entry.print_for_sec(\"Hello Entry!\".lower(), 2)',\n    change_string_case_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"Hello Entry!\"를 모두 대문자로 바꾼 \"HELLO ENTRY!\"를 2초간 말한 다음 모두 소문자로 바꾼 \"hello entry!\"를 2초간 말합니다.',\n    ask_and_wait_desc:\n        \"오브젝트가 A 내용을 말풍선으로 묻고, 대답을 입력받습니다. 대답은 실행화면 또는 콘솔창에서 입력할 수 있으며 입력된 값은 'Entry.answer()'에 저장됩니다. \\n(이 명령어를 사용하면 실행화면에 ‘대답 창’이 생성됩니다.)\",\n    ask_and_wait_elements: 'A-- \"문자열\"',\n    ask_and_wait_exampleCode:\n        'def when_start():\\n    Entry.input(\"이름을 입력해보세요.\")\\n    Entry.print(Entry.answer() + \" 반가워!\")',\n    ask_and_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"이름을 입력해보세요.\"라고 말풍선으로 묻습니다. 이름을 입력하면 \"(입력한 이름) 반가워!\"라 말합니다.',\n    get_canvas_input_value_desc:\n        'Entry.input(A) 명령에 의해 실행화면 또는 콘솔에서 입력받은 값입니다.',\n    get_canvas_input_value_exampleCode:\n        'def when_start():\\n    Entry.input(\"이름을 입력해보세요.\")\\n    Entry.print(Entry.answer() + \" 반가워!\")',\n    get_canvas_input_value_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"이름을 입력해보세요.\"라고 말풍선으로 묻습니다. 이름을 입력하면 \"(입력한 이름) 반가워!\"라 말합니다.',\n    set_visible_answer_desc: '실행화면의 대답 창을 A로 설정합니다.',\n    set_visible_answer_elements:\n        'A-- 아래 선택지 중 하나\\n① \"hide\" : 대답 창을 숨김\\n② \"show\" : 대답 창을 보임',\n    set_visible_answer_exampleCode:\n        'def when_start():\\n    Entry.answer_view(\"hide\")\\n    Entry.input(\"나이를 입력하세요.\")\\n    Entry.print(Entry.answer())',\n    set_visible_answer_exampleDesc:\n        '[시작하기]버튼을 클릭하면 대답창이 숨겨지고, 오브젝트가 \"나이를 입력하세요.\"라고 말풍선으로 묻습니다. 나이를 입력하면 오브젝트가 입력한 나이를 말합니다.',\n    get_variable_desc: 'A 변수에 저장된 값입니다.',\n    get_variable_elements:\n        'A-- 변수명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A',\n    get_variable_exampleCode: 'age = 16\\n\\ndef when_start():\\n    Entry.print(age)',\n    get_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 말합니다.',\n    change_variable_desc: 'A 변수에 B만큼 더합니다.',\n    change_variable_elements:\n        'A-- 변수명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 숫자값',\n    change_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.print_for_sec(age, 2)\\n    age += 2\\n    Entry.print_for_sec(age, 2)',\n    change_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 2초 동안 말합니다. 그 후 age변수에 2를 더하고 더한값인 \"18\"을 2초 동안 말합니다.',\n    set_variable_desc:\n        'A 변수의 값을 B로 정합니다. 만약 A 변수가 없으면  [속성] 탭에 A 변수가 자동 생성됩니다.',\n    set_variable_elements:\n        'A-- 변수명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 변수에 넣을 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    set_variable_exampleCode: 'age = 16\\n\\ndef when_start():\\n    Entry.print(age)',\n    set_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 말합니다.',\n    show_variable_desc: 'A 변수 창을 실행화면에 보이게 합니다.',\n    show_variable_elements:\n        'A-- \"변수명\"\\n① 모든 오브젝트에서 사용: \"A\"\\n② 이 오브젝트에서 사용: \"self.A\"',\n    show_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\"age\")\\n    Entry.wait_for_sec(2)\\n    age = 20\\n    Entry.show_variable(\"age\")',\n    show_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨깁니다. 2초 후 변수값을 17로 바꾸고 age변수창을 실행화면에 보이게 합니다.',\n    hide_variable_desc: 'A 변수 창을 실행화면에서 숨깁니다.',\n    hide_variable_elements:\n        'A-- \"변수명\"\\n① 모든 오브젝트에서 사용: \"A\"\\n② 이 오브젝트에서 사용: \"self.A\"',\n    hide_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\"age\")\\n    Entry.print_for_sec(age, 2)',\n    hide_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨기고, 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 2초 동안 말합니다.',\n    value_of_index_from_list_desc:\n        'A 리스트에서 B위치의 항목 값을 의미합니다. \\n(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    value_of_index_from_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치',\n    value_of_index_from_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.print(basket[1])\\n',\n    value_of_index_from_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트가 basket 리스트의 1번째 항목인 orange를 말합니다.',\n    add_value_to_list_desc: 'A 리스트의 마지막 항목으로 B값이 추가됩니다.',\n    add_value_to_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트에 넣을 항목 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    add_value_to_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket.append(\"juice\")\\n    Entry.print(basket[4])',\n    add_value_to_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 \"juice\"를 basket의 마지막 항목으로 추가합니다. 오브젝트는 basket의 4번째 항목인 \"juice\"를 말합니다.',\n    remove_value_from_list_desc:\n        'A 리스트의 B위치에 있는 항목을 삭제합니다.\\n(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    remove_value_from_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치값',\n    remove_value_from_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\ndef when_start():\\n    basket.pop(0)\\n    Entry.print(basket[0])',\n    remove_value_from_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 항목인 apple을 삭제합니다. 오브젝트는 새롭게 basket의 0번째 항목이 된 \"orange\"를 말합니다.',\n    insert_value_to_list_desc:\n        'A 리스트의 B위치에 C항목을 끼워 넣습니다. \\n(첫 번째 항목의 위치는 0부터 시작합니다. B위치보다 뒤에 있는 항목들은 순서가 하나씩 밀려납니다.)',\n    insert_value_to_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    insert_value_to_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket.insert(1, \"juice\")\\n    Entry.print(basket[2])',\n    insert_value_to_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 1번째 위치에 항목 \"juice\"를 끼워 넣습니다. 오브젝트는 새롭게 basket의 2번째 항목이 된 \"orange\"를 말합니다.',\n    change_value_list_index_desc:\n        'A 리스트에서 B위치에 있는 항목의 값을 C 값으로 바꿉니다.\\n(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    change_value_list_index_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    change_value_list_index_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket[0] = \"juice\"\\n    Entry.print(basket[0])',\n    change_value_list_index_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 위치의 항목 \"apple\"을 \"juice\"로 바꿉니다. 오브젝트는 바뀐 basket의 0번째 항목 \"juice\"를 말합니다.',\n    length_of_list_desc: 'A 리스트가 보유한 항목 개수 값입니다.',\n    length_of_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A',\n    length_of_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.print(len(basket))',\n    length_of_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트는  basket의 항목 개수인 4를 말합니다.',\n    is_included_in_list_desc: 'A값을 가진 항목이 B리스트에 포함되어 있는지 확인합니다.',\n    is_included_in_list_elements:\n        'A-- 리스트의 항목 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등%nextB-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A',\n    is_included_in_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    if \"apple\" in basket:\\n        Entry.print(\"사과가 있어!\")',\n    is_included_in_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트에 \"apple\"항목이 있는지 확인합니다. \"apple\"항목이 있기 때문에 오브젝트는 \"사과가 있어!\"라 말합니다.',\n    show_list_desc: '선택한 리스트 창을 실행화면에 보이게 합니다.',\n    show_list_elements:\n        'A-- \"리스트명\"\\n① 모든 오브젝트에서 사용: \"A\"\\n② 이 오브젝트에서 사용: \"self.A\"',\n    show_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.hide_list(\"basket\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\"basket\")',\n    show_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.',\n    hide_list_desc: '선택한 리스트 창을 실행화면에서 숨깁니다.',\n    hide_list_elements:\n        'A-- \"리스트명\"\\n① 모든 오브젝트에서 사용: \"A\"\\n② 이 오브젝트에서 사용: \"self.A\"',\n    hide_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.hide_list(\"basket\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\"basket\")',\n    hide_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.',\n    boolean_and_or_desc: 'A와 B의 판단값을 확인하여 True 또는 False로 판단합니다.',\n    boolean_and_or_elements: '② or : A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False',\n    boolean_and_or_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") and Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_and_or_exampleDesc:\n        '[시작하기]버튼을 클릭하고 키보드의 \"a\" 와 \"s\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.',\n    check_weather_desc: 'B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.',\n    check_weather_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"sunny\" : 맑음\\n②    \"partly cloudy\" : 구름조금\\n③    \"mostly cloudy\" : 구름많음\\n④    \"cloudy\" : 흐림\\n⑤    \"rainy\" : 비\\n⑥    \"sleet\" : 진눈깨비\\n⑦    \"snowy\" : 눈%nextB-- 아래 선택지 중 하나\\n①    \"yesterday\" : 어제\\n②    \"today\" : 오늘\\n③    \"tomorrow\" : 내일\\n④    \"After 2 days\" : 모레\\n⑤    \"After 3 days\" : 3일 후\\n⑥    \"After 4 days\" : 4일 후\\n⑦    \"After 5 days\" : 5일 후\\n⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    check_weather_exampleCode:\n        'def when_start():\\n    if Weather.is_condition_sunny(\"today\", \"Seoul\"):\\n        Entry.print(\"오늘 서울의 날씨는 맑습니다.\")',\n    check_weather_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \"오늘 서울의 날씨는 맑습니다.\"라고 말합니다.​',\n    check_finedust_desc:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.',\n    check_finedust_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"good\" : 좋음\\n②    \"normal\" : 보통\\n③    \"bad\" : 나쁨\\n④    \"very bad\" : 매우나쁨%nextB-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    check_finedust_exampleCode:\n        'def when_start():\\n    if Weather.is_current_finedust_grade_good(\"Seoul\"):\\n        Entry.print(\"현재 서울의 미세먼지 등급은 좋음입니다.\")',\n    check_finedust_exampleDesc:\n        '[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​',\n    get_weather_data_desc:\n        '선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.',\n    get_weather_data_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"the lowest temperature\" : 최저기온\\n②    \"the highest temperature\" : 최고기온\\n③    \"humidity\" : 습도\\n④    \"precipitation\" : 강수량\\n⑤    \"precipitation probability\" : 강수확률\\n⑥    \"wind speed\" : 풍속%nextB-- 아래 선택지 중 하나\\n①    \"yesterday\" : 어제\\n②    \"today\" : 오늘\\n③    \"tomorrow\" : 내일\\n④    \"After 2 days\" : 모레\\n⑤    \"After 3 days\" : 3일 후\\n⑥    \"After 4 days\" : 4일 후\\n⑦    \"After 5 days\" : 5일 후\\n⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    get_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\"today\", \"Seoul\"))',\n    get_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​',\n    get_current_weather_data_desc: '현재 B지역의 A 날씨 정보값을 의미합니다.',\n    get_current_weather_data_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나\\n①    \"temperature\" : 기온\\n②    \"concentration of fine dust\" : 미세먼지농도',\n    get_current_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_current_temperature(\"Seoul\"))',\n    get_current_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.',\n    get_today_temperature_desc: '오늘 A지역의 B 시간대 기온 정보값을 의미합니다.',\n    get_today_temperature_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나\\n①    \"00\" : 당일 00시 측정된 기온값\\n②    \"03\" : 당일 03시 측정된 기온값\\n③    \"06\" : 당일 06시 측정된 기온값\\n④    \"09\" : 당일 09시 측정된 기온값\\n⑤    \"12\" : 당일 12시 측정된 기온값\\n⑥    \"15\" : 당일 15시 측정된 기온값\\n⑦    \"18\" : 당일 18시 측정된 기온값\\n⑧    \"21\" : 당일 21시 측정된 기온값',\n    get_today_temperature_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_today_temperature(\"Seoul\", 00))',\n    get_today_temperature_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​',\n    check_city_weather_desc: 'B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.',\n    check_city_weather_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"sunny\" : 맑음\\n②    \"partly cloudy\" : 구름조금\\n③    \"mostly cloudy\" : 구름많음\\n④    \"cloudy\" : 흐림\\n⑤    \"rainy\" : 비\\n⑥    \"sleet\" : 진눈깨비\\n⑦    \"snowy\" : 눈%nextB-- 아래 선택지 중 하나\\n①    \"yesterday\" : 어제\\n②    \"today\" : 오늘\\n③    \"tomorrow\" : 내일\\n④    \"After 2 days\" : 모레\\n⑤    \"After 3 days\" : 3일 후\\n⑥    \"After 4 days\" : 4일 후\\n⑦    \"After 5 days\" : 5일 후\\n⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    check_city_weather_exampleCode:\n        'def when_start():\\n    if Weather.is_condition_sunny(\"today\", \"Seoul\"):\\n        Entry.print(\"오늘 서울의 날씨는 맑습니다.\")',\n    check_city_weather_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \"오늘 서울의 날씨는 맑습니다.\"라고 말합니다.​',\n    check_city_finedust_desc:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.',\n    check_city_finedust_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"good\" : 좋음\\n②    \"normal\" : 보통\\n③    \"bad\" : 나쁨\\n④    \"very bad\" : 매우나쁨%nextB-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    check_city_finedust_exampleCode:\n        'def when_start():\\n    if Weather.is_current_finedust_grade_good(\"Seoul\"):\\n        Entry.print(\"현재 서울의 미세먼지 등급은 좋음입니다.\")',\n    check_city_finedust_exampleDesc:\n        '[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​',\n    get_city_weather_data_desc:\n        '선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.',\n    get_city_weather_data_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"the lowest temperature\" : 최저기온\\n②    \"the highest temperature\" : 최고기온\\n③    \"humidity\" : 습도\\n④    \"precipitation\" : 강수량\\n⑤    \"precipitation probability\" : 강수확률\\n⑥    \"wind speed\" : 풍속%nextB-- 아래 선택지 중 하나\\n①    \"yesterday\" : 어제\\n②    \"today\" : 오늘\\n③    \"tomorrow\" : 내일\\n④    \"After 2 days\" : 모레\\n⑤    \"After 3 days\" : 3일 후\\n⑥    \"After 4 days\" : 4일 후\\n⑦    \"After 5 days\" : 5일 후\\n⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    get_city_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\"today\", \"Seoul\"))',\n    get_city_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​',\n    get_current_city_weather_data_desc: '현재 B지역의 A 날씨 정보값을 의미합니다.',\n    get_current_city_weather_data_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나\\n①    \"temperature\" : 기온\\n②    \"concentration of fine dust\" : 미세먼지농도',\n    get_current_city_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_current_temperature(\"Seoul\"))',\n    get_current_city_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.',\n    get_today_city_temperature_desc: '오늘 A지역의 B 시간대 기온 정보값을 의미합니다.',\n    get_today_city_temperature_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeonbuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나\\n①    \"00\" : 당일 00시 측정된 기온값\\n②    \"03\" : 당일 03시 측정된 기온값\\n③    \"06\" : 당일 06시 측정된 기온값\\n④    \"09\" : 당일 09시 측정된 기온값\\n⑤    \"12\" : 당일 12시 측정된 기온값\\n⑥    \"15\" : 당일 15시 측정된 기온값\\n⑦    \"18\" : 당일 18시 측정된 기온값\\n⑧    \"21\" : 당일 21시 측정된 기온값',\n    get_today_city_temperature_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_today_city_temperature(\"Seoul\", 00))',\n    get_today_city_temperature_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​',\n};\nLang.Painter = {\n    select_cut: 'You can cut with a square dotted line.',\n    thickness_of_eraser: 'Thickness of eraser',\n    font: 'Font',\n    font_color: 'Font color',\n    outline_color: 'Outline color',\n    outline_thickness: 'Outline thickness',\n    fill_color: 'Fill',\n    inversion: 'Inversion',\n    font_size: 'Font size',\n    font_family: 'Font family',\n    fullscreen: 'Full screen',\n    exit_fullscreen: 'Exit full screen',\n    picture_import: 'Import a shape',\n    edit_way: 'Convert',\n    line: 'Line',\n    vertex: 'Vertex',\n    bitmap: 'Bitmap',\n    vector: 'Vector',\n    forward: 'forward',\n    backward: 'backward',\n    front: 'front',\n    back: 'back',\n    group: 'group',\n    ungroup: 'ungroup',\n    copy_picture: 'copy',\n    delete_picture: 'delete',\n    cut_picture: 'cut',\n    paste_picture: 'paste',\n    remove_all: 'clear',\n    new_picture: 'New shape',\n    edit: 'Edit',\n    picture_size: 'Size',\n    picture_rotation: 'Rotation',\n    thickness: 'thickness',\n    font_fill: 'Fill',\n    painter_file_save: 'Save',\n    painter_file_saveas: 'Save as a new shape',\n    file: 'File',\n    Pencil: 'Pen',\n    Line: 'Line',\n    Path: 'Path',\n    Pan: 'Move',\n    Select: 'Select',\n    Rectangle: 'Rectangle',\n    Ellipse: 'Ellipse',\n    Text: 'Text box',\n    Fill: 'Fill',\n    Eraser: 'Eraser',\n    get_file: 'get',\n    copy_file: 'copy',\n};\nLang.DataAnalytics = {\n    data_analysis: 'Data Analysis',\n    create_table: 'Add Table',\n    data: 'Data Analysis',\n    add_table: 'Add Table',\n    show_chart: 'Show Chart',\n    legend: 'Legend',\n    dashboard: 'Dashboard',\n    table: 'Table',\n    chart: 'Chart',\n    attribute: 'Column',\n    row: 'Row',\n    average: 'Average',\n    standard_deviation: 'Standard Deviation',\n    maximum: 'Maximum',\n    minimum: 'Minimum',\n    median: 'Median',\n    average_explain:\n        'The result that add all values of that property and divide the total by number of the property.',\n    standard_deviation_explain:\n        'A value that tells how spread out the data are from the average.\\nCloser to zero means that the values are concentrated near the average.',\n    maximum_minimum_explain: 'Largest and Smallest values for the property',\n    median_explain:\n        'The value located at the center of the whole when all the values of the property are arranged in size order.',\n    add_row_above: 'Add row above',\n    add_row_below: 'Add row below',\n    delete_row: 'Delete Row',\n    add_property_left: 'Add Property to left',\n    add_property_right: 'Add Property to right',\n    delete_attribute: 'Delete Attribute',\n    data_alert: 'You can only see counts for attributes that contain non-numeric values.',\n    save: 'Save',\n    cancel: 'Cancel',\n    confirm: 'OK',\n    attribute_count: '.',\n    row_count: 'row',\n    cell_count: 'cell',\n    count: 'count',\n    add_chart_alert: 'No chart in table.\\nAdd table.',\n    enter_attribute_name: 'Please enter a column name(with less than 10 characters).',\n    placeholder_attribute_name: 'Column name',\n    new_attribute: 'New column',\n    chart_title: 'Chart title',\n    remove_chart: 'Delete chart',\n    add_chart_first: 'No chart in table. \\nAdd table.',\n    bar: 'Bar',\n    line: 'Line',\n    pie: 'Pie',\n    scatter: 'Scatter',\n    bar_sub: 'Bar graph',\n    line_sub: 'Line graph',\n    pie_sub: 'Pie chart',\n    scatter_sub: 'Scatter plot',\n    select_x_axis: 'Select the x-axis.',\n    x_axis: 'x-axis',\n    y_axis: 'y-axis',\n    select_y_axis: 'Select the y-axis.',\n    select_y_axis_or_legend: 'Select the y-axis or legends.',\n    select_legend: 'Select the legends.',\n    cell: 'Cell',\n    unable_to_express_chart: 'This cannot be expressed in charts.',\n    edit_attribute_name: 'Change name',\n    duplicate_attribute_name_title: 'Failed to change column name.',\n    duplicate_attribute_name_content: 'A column with the same name exists.',\n    fail_save_table: 'Failed to save table.',\n    duplicate_table_name_content: 'A table with the same name exists.',\n    saved_table_title: 'Saved successfully.',\n    saved_table_content: 'The information of table and charts was successfully saved.',\n    empty_table_name_content: \"Table's name can't be space.\",\n    do_not_delete_row: 'The row cannot be deleted.',\n    rows_cannot_less_one: 'Tables must have at least one row.',\n    and: 'and',\n    other: 'other(s)',\n    stop: 'Project Stop',\n    restart: 'Project Resume',\n    pause: 'Project Pause',\n    max_row_count_error_title: 'Caution',\n    max_row_count_error:\n        'If the table has more than 5000 rows, When you edit a table or add a chart, your browser might stop.\\nIf there is a problem, please adjust the number of rows.',\n    attributes_text: '%1 and %2 other(s)',\n    duplicate: 'Duplicate',\n    copy: 'Copy',\n    delete: 'Delete',\n    paste: 'Paste',\n    cut: 'Cut',\n    download: 'Download',\n    download_table: 'Download as an Excel file',\n    confirm_content: 'Should I save the changed tables and charts?',\n    please_add_table: 'Please add a table first.',\n    load_data_analytics: 'Load table',\n    summary_table_description: 'Basic statistics based on columns in the table.',\n    not_exist_chart: 'No charts have been added.',\n    please_add_chart: 'Please add the chart first.',\n    chart_name: 'Chart name',\n    remove_confirm_content: 'Should I delete the table?',\n    not_editable_content:\n        'The table has more than 30,000 cells,\\r\\nso it cannot be edited in the entry.',\n    limit_cell_count_title: 'Limit of rows/columns',\n    limit_cell_count_content:\n        'You can no longer add rows or columns.\\r\\nEntry only allows editing of tables\\r\\nup to 30,000 cells.',\n    must_have_one_row_content: 'The table must have more than one row and column.',\n    number_of_bins: 'Number of bins',\n    bin_width: 'Bin width',\n    bin_boundary: 'Bin boundary',\n    left_closed: 'Left closed',\n    right_closed: 'Right closed',\n    ascending: 'Ascending',\n    default: 'Default',\n    quantity: 'Quantity',\n    in_order: 'In order',\n    not_distinguished: 'Not distinguished',\n    select_table: 'Click [Add Table] to add table.',\n    select_table_title: 'How to add table',\n    select_table_des1:\n        \"1. On the 'Select table' tab, select the default table provided by the Entry.\",\n    select_table_des2: \"2. On the 'Upload files' tab, upload the CSV, XLS(X) file directly.\",\n    select_table_des3: \"3. On the 'New table' tab, add an empty table and enter the data directly.\",\n    statistic: 'Representative value',\n    provider: 'Source',\n    description: 'Description',\n    field_info: 'Field Info',\n    show_all_points: 'Show All Points',\n    coefficient: 'Coefficient',\n    scatter_matrix: 'Scatter Matrix',\n    show_table: 'Show Table',\n    value: 'Value',\n    summary: 'Summary',\n    column_name: 'Column Name',\n    total: 'Total',\n    histogram: 'Histogram',\n    select_legend2: 'Select at least 2 legends.',\n};\n\nLang.SharePolicy = {\n    title: 'Entry Project/Post share Guide',\n};\n\nLang.pose_list = {\n    nose: 'nose',\n    left_eye_inner: 'left eye (inner)',\n    left_eye: 'left eye',\n    left_eye_outer: 'left eye (outer)',\n    right_eye_inner: 'right eye (inner)',\n    right_eye: 'right eye',\n    right_eye_outer: 'right eye (outer)',\n    left_ear: 'left ear',\n    right_ear: 'right ear',\n    mouth_left: 'mouth (left)',\n    mouth_right: 'mouth (right)',\n    left_shoulder: 'left shoulder',\n    right_shoulder: 'right shoulder',\n    left_elbow: 'left elbow',\n    right_elbow: 'right elbow',\n    left_wrist: 'left wrist',\n    right_wrist: 'right wrist',\n    left_pinky: 'left pinky',\n    right_pinky: 'right pinky',\n    left_index: 'left index',\n    right_index: 'right index',\n    left_thumb: 'left thumb',\n    right_thumb: 'right thumb',\n    left_hip: 'left hip',\n    right_hip: 'right hip',\n    left_knee: 'left knee',\n    right_knee: 'right knee',\n    left_ankle: 'left ankle',\n    right_ankle: 'right ankle',\n    left_heel: 'left heel',\n    right_heel: 'right heel',\n    left_foot_index: 'left foot index',\n    right_foot_index: 'right foot index',\n};\n\nLang.gesture_list = {\n    closed_fist: 'Closed Fist',\n    open_palm: 'Open Palm',\n    pointing_up: 'Pointing Up',\n    thumb_down: 'Thumb Down',\n    thumb_up: 'Thumb Up',\n    victory: 'Victory',\n    iloveyou: 'I Love You',\n    none: 'Unknown',\n};\n\nLang.Support = ['ko', 'en', 'vn', 'jp'];\nif (typeof exports == 'object') exports.Lang = Lang;\n"
  },
  {
    "path": "extern/lang/jp.js",
    "content": "var Lang = {};\nLang.category = {\n    \"name\": \"en\"\n};\nLang.type = \"jp\";\nLang.fallbackType = \"en\";\nLang.ko = \"한국어\";\nLang.en = \"English\";\nLang.jp = \"日本語\";\nLang.vn = \"tiếng Việt\";\nLang.Command = {\n    \"1\": \"장면 추가하기\",\n    \"2\": \"장면 삭제하기\",\n    \"3\": \"장면 이름 수정\",\n    \"4\": \"장면 순서 변경\",\n    \"5\": \"장면 선택\",\n    \"101\": \"ブロックスレッドを追加する\",\n    \"102\": \"ブロックスレッドを削除する\",\n    \"103\": \"ブロックを削除する\",\n    \"104\": \"ブロックを復旧する\",\n    \"105\": \"ブロックを挿入する\",\n    \"106\": \"ブロックを分離する\",\n    \"107\": \"ブロックを移動する\",\n    \"108\": \"ブロックをコピーする\",\n    \"109\": \"ブロックのコピーを取り消す\",\n    \"110\": \"スクロール\",\n    \"111\": \"ブロックフィールド値を修正\",\n    \"117\": \"ブロックスレッドを追加する\",\n    \"118\": \"ブロックを挿入する\",\n    \"119\": \"ブロックを移動する\",\n    \"120\": \"ブロックを分離する\",\n    \"121\": \"ブロックを移動する\",\n    \"122\": \"ブロックを挿入する\",\n    \"123\": \"ブロックを挿入する\",\n    \"201\": \"オブジェクトを選択する\",\n    \"202\": \"오브젝트 수정 버튼 클릭\",\n    \"203\": \"오브젝트 그림 추가\",\n    \"204\": \"오브젝트 그림 삭제\",\n    \"205\": \"오브젝트 소리 추가\",\n    \"206\": \"오브젝트 소리 삭제\",\n    \"207\": \"오브젝트 이름 수정\",\n    \"208\": \"오브젝트 추가\",\n    \"209\": \"오브젝트 삭제\",\n    \"210\": \"오브젝트 추가 버튼 클릭\",\n    \"211\": \"오브젝트 x 수정\",\n    \"212\": \"오브젝트 y 수정\",\n    \"213\": \"오브젝트 size 수정\",\n    \"214\": \"오브젝트 방향 수정\",\n    \"215\": \"오브젝트 이동 방향 수정\",\n    \"216\": \"오브젝트 회전방식 수정\",\n    \"217\": \"엔터티 모델 동기화\",\n    \"301\": \"do\",\n    \"302\": \"undo\",\n    \"303\": \"redo\",\n    \"401\": \"図を修正する\",\n    \"402\": \"図の修正を取り消す\",\n    \"403\": \"図を修正する\",\n    \"404\": \"図の修正を取り消す\",\n    \"405\": \"글상자 수정\",\n    \"501\": \"スタート\",\n    \"502\": \"停止する\",\n    \"601\": \"コンテナーオブジェクトを選択する\",\n    \"701\": \"モード変換 \",\n    \"702\": \"模様追加ボタンをクリック\",\n    \"703\": \"サウンド追加ボタンをクリック\",\n    \"801\": \"変数属性ウィンドウフィルターを選択する\",\n    \"802\": \"変数を追加するボタンをクリック\",\n    \"803\": \"変数を追加する\",\n    \"804\": \"変数を削除する\",\n    \"805\": \"変数名設定\",\n    \"806\": \"신호 이름 설정\",\n    \"807\": \"신호 추가\",\n    \"808\": \"신호 삭제\",\n    \"809\": \"변수 스코프 정하기\",\n    \"810\": \"변수 글로벌 체크\",\n    \"811\": \"변수 보이기 체크\",\n    \"812\": \"변수 기본값 설정\",\n    \"813\": \"변수 슬라이드로 체크\",\n    \"814\": \"변수 최솟값 정하기\",\n    \"815\": \"변수 최댓값 정하기\",\n    \"816\": \"리스트 추가 버튼 클릭\",\n    \"817\": \"리스트 추가\",\n    \"818\": \"리스트 삭제\",\n    \"819\": \"리스트 이름 정하기\",\n    \"820\": \"리스트 스코프 정하기\",\n    \"821\": \"리스트 글로벌 체크\",\n    \"822\": \"리스트 보이기 체크\",\n    \"823\": \"리스트 길이 변경\",\n    \"824\": \"리스트 기본값 설정\",\n    \"825\": \"메세지 수정 enable\",\n    \"826\": \"변수 수정 enable\",\n    \"827\": \"리스트 수정 enable\",\n    \"828\": \"변수 이름 정하기\",\n    \"829\": \"리스트 이름 정하기\",\n    \"900\": \"모달 닫기\",\n    \"1001\": \"함수 생성 시작\",\n    \"1002\": \"함수 수정 시작\",\n    \"1003\": \"함수 수정 취소\",\n    \"1004\": \"함수 생성\",\n    \"1005\": \"함수 업데이트\"\n};\nLang.CommandTooltip = {\n    \"101\": \"ブロックスレッドを追加する\",\n    \"102\": \"ブロックスレッドを削除する\",\n    \"103\": \"ブロックを削除する\",\n    \"104\": \"ブロックを復旧する\",\n    \"105\": \"コードを分離する$$コードを連結する@@このコードの一番上にあるブロックを掴んで分離しドラッグします。$$ここにコードを連結します。$$ここにブロックの左端を挿入します。\",\n    \"106\": \"ブロックを分離する\",\n    \"107\": \"ブロックを移動する\",\n    \"108\": \"ブロックをコピーする\",\n    \"109\": \"ブロックのコピーを取り消す\",\n    \"110\": \"スクロール\",\n    \"111\": \"ブロックフィールド値を修正@@値を入力するためここをクリックします。$$選択肢をクリックします。$$選択肢をクリックします。$$&value&を入力します。$$&value&を選択します。$$キーボード &value&を押します。\",\n    \"117\": \"ブロックスレッドを追加する\",\n    \"118\": \"ブロックを連結する@@ここにブロックを連結します。$$ここにブロックの左端を挿入します。\",\n    \"119\": \"ブロックをインポートする@@空いている場所にブロックをドラッグ＆ドロップします。\",\n    \"120\": \"ブロックを分離する$$ブロックを削除する@@必要のないコードを<b>ゴミ箱</b>にドラッグします。$$ここにコードを捨てます。\",\n    \"121\": \"ブロックを移動する$$ブロックを削除する@@必要のないコードを<b>ゴミ箱</b>にドラッグします。$$ここにコードを捨てます。\",\n    \"122\": \"ブロックを連結する@@ここにブロックを連結します。$$ここにブロックの左端を挿入します。\",\n    \"123\": \"コードを分離する$$コードを連結する@@このコードの一番上にあるブロックを掴んで分離しドラッグします。$$ここにコードを連結します。$$ここにブロックの左端を挿入します。\",\n    \"201\": \"オブジェクトを削除する\",\n    \"301\": \"do\",\n    \"302\": \"undo\",\n    \"303\": \"redo\",\n    \"401\": \"図を修正する\",\n    \"402\": \"図の修正を取り消す\",\n    \"403\": \"図を修正する\",\n    \"404\": \"図の修正を取り消す\",\n    \"501\": \"実行する@@<b>[スタート]</b>を押します。\",\n    \"502\": \"停止する@@<b>[停止する]</b>を押します。\",\n    \"601\": \"コンテナーオブジェクトを削除する\",\n    \"701\": \"モード変換 \",\n    \"702\": \"模様を追加する@@<b>模様追加</b>をクリックします。\",\n    \"703\": \"サウンドを追加する@@<b>サウンド追加</b>をクリックします。\",\n    \"801\": \"変数属性ウィンドウフィルターを選択する\",\n    \"802\": \"変数を追加する@@<b>[変数追加]</b>をクリックします。\",\n    \"803\": \"変数を追加する@@<b>[確認]</b>をクリックします。\",\n    \"804\": \"変数を削除する@@このボタンを押して変数を削除します。\",\n    \"805\": \"変数名設定\",\n    \"1101\": \"サウンドを追加する@@<b>サウンド追加</b>をクリックします。\"\n};\nLang.Blocks = {\n    \"download_guide\": \"• 接続ガイドをダウンロード\",\n    \"dictionary\": \"dictionary\",\n    \"ai_utilize\": \"AI\",\n    \"date_yesterday\": \"昨日\",\n    \"date_today\": \"今日\",\n    \"date_tomorrow\": \"明日\",\n    \"date_after_2_days\": \"明後日\",\n    \"date_after_3_days\": \"明々後日\",\n    \"date_after_4_days\": \"４日後\",\n    \"date_after_5_days\": \"５日後\",\n    \"date_after_6_days\": \"６日後\",\n    \"location_entire\": \"全体\",\n    \"location_seoul\": \"ソウル\",\n    \"location_seoul_jongno_gu\": \"鍾路区\",\n    \"location_seoul_jung_gu\": \"中区\",\n    \"location_seoul_yongsan_gu\": \"龍山区\",\n    \"location_seoul_seongdong_gu\": \"城東区\",\n    \"location_seoul_gwangjin_gu\": \"広津区\",\n    \"location_seoul_dongdaemun_gu\": \"東大門区\",\n    \"location_seoul_jungnang_gu\": \"中浪区\",\n    \"location_seoul_seongbuk_gu\": \"城北区\",\n    \"location_seoul_gangbuk_gu\": \"江北区\",\n    \"location_seoul_dobong_gu\": \"道峰区\",\n    \"location_seoul_nowon_gu\": \"蘆原区\",\n    \"location_seoul_eunpyeong_gu\": \"恩平区\",\n    \"location_seoul_seodaemun_gu\": \"西大門区\",\n    \"location_seoul_mapo_gu\": \"麻浦区\",\n    \"location_seoul_yangcheon_gu\": \"陽川区\",\n    \"location_seoul_gangseo_gu\": \"江西区\",\n    \"location_seoul_guro_gu\": \"九老区\",\n    \"location_seoul_geumcheon_gu\": \"衿川区\",\n    \"location_seoul_yeongdeungpo_gu\": \"永登浦区\",\n    \"location_seoul_dongjak_gu\": \"銅雀区\",\n    \"location_seoul_gwanak_gu\": \"冠岳区\",\n    \"location_seoul_seocho_gu\": \"瑞草区\",\n    \"location_seoul_gangnam_gu\": \"江南区\",\n    \"location_seoul_songpa_gu\": \"松坡区\",\n    \"location_seoul_gangdong_gu\": \"江東区\",\n    \"location_busan\": \"プサン\",\n    \"location_busan_jung_gu\": \"中区\",\n    \"location_busan_seo_gu\": \"西区\",\n    \"location_busan_dong_gu\": \"東区\",\n    \"location_busan_yeongdo_gu\": \"影島区\",\n    \"location_busan_busanjin_gu\": \"鎮区\",\n    \"location_busan_dongnae_gu\": \"東莱区\",\n    \"location_busan_nam_gu\": \"南区\",\n    \"location_busan_buk_gu\": \"北区\",\n    \"location_busan_haeundae_gu\": \"海雲台区\",\n    \"location_busan_saha_gu\": \"沙下区\",\n    \"location_busan_geumjeong_gu\": \"金井区\",\n    \"location_busan_gangseo_gu\": \"江西区\",\n    \"location_busan_yeonje\": \"蓮堤区\",\n    \"location_busan_suyeong_gu\": \"水営区\",\n    \"location_busan_sasang_gu\": \"沙上区\",\n    \"location_busan_gijang\": \"機張郡\",\n    \"location_daegu\": \"テグ\",\n    \"location_daegu_jung_gu\": \"中区\",\n    \"location_daegu_dong_gu\": \"東区\",\n    \"location_daegu_seo_gu\": \"西区\",\n    \"location_daegu_nam_gu\": \"南区\",\n    \"location_daegu_buk_gu\": \"北区\",\n    \"location_daegu_suseong_gu\": \"寿城区\",\n    \"location_daegu_dalseo_gu\": \"達西区\",\n    \"location_daegu_dalseong\": \"達城郡\",\n    \"location_incheon\": \"インチョン\",\n    \"location_incheon_jung_gu\": \"中区\",\n    \"location_incheon_dong_gu\": \"東区\",\n    \"location_incheon_nam_gu\": \"南区\",\n    \"location_incheon_yeonsu_gu\": \"延寿区\",\n    \"location_incheon_namdong_gu\": \"南洞区\",\n    \"location_incheon_bupyeong_gu\": \"富平区\",\n    \"location_incheon_gyeyang_gu\": \"桂陽区\",\n    \"location_incheon_seo_gu\": \"西区\",\n    \"location_incheon_ganghwa\": \"江華郡\",\n    \"location_incheon_ongjin_gun\": \"甕津郡\",\n    \"location_gwangju\": \"クヮンジュ\",\n    \"location_gwangju_dong_gu\": \"東区\",\n    \"location_gwangju_seo_gu\": \"西区\",\n    \"location_gwangju_nam_gu\": \"南区\",\n    \"location_gwangju_buk_gu\": \"北区\",\n    \"location_gwangju_gwangsan_gu\": \"光山区\",\n    \"location_daejeon\": \"テジョン\",\n    \"location_daejeon_dong_gu\": \"東区\",\n    \"location_daejeon_jung_gu\": \"中区\",\n    \"location_daejeon_seo_gu\": \"西区\",\n    \"location_daejeon_yuseong_gu\": \"儒城区\",\n    \"location_daejeon_daedeok_gu\": \"大徳区\",\n    \"location_ulsan\": \"ウルサン\",\n    \"location_ulsan_jung_gu\": \"中区\",\n    \"location_ulsan_nam_gu\": \"南区\",\n    \"location_ulsan_dong_gu\": \"東区\",\n    \"location_ulsan_buk_gu\": \"北区\",\n    \"location_ulsan_ulju\": \"蔚州郡\",\n    \"location_sejong\": \"セジョン\",\n    \"location_gyeonggi\": \"キョンギ道\",\n    \"location_gyeonggi_suwon_si\": \"水原市\",\n    \"location_gyeonggi_seongnam\": \"城南市\",\n    \"location_gyeonggi_uijeongbu\": \"議政府市\",\n    \"location_gyeonggi_anyang_si\": \"安養市\",\n    \"location_gyeonggi_bucheon_si\": \"富川市\",\n    \"location_gyeonggi_gwangmyeong_si\": \"光明市\",\n    \"location_gyeonggi_pyeongtaek_si\": \"平沢市\",\n    \"location_gyeonggi_dongducheon_si\": \"東豆川市\",\n    \"location_gyeonggi_ansan_si\": \"安山市\",\n    \"location_gyeonggi_goyang_si\": \"高陽市\",\n    \"location_gyeonggi_gwacheon_si\": \"果川市\",\n    \"location_gyeonggi_guri\": \"九里市\",\n    \"location_gyeonggi_namyangju_si\": \"南楊州市\",\n    \"location_gyeonggi_osan\": \"烏山市\",\n    \"location_gyeonggi_siheung\": \"始興市\",\n    \"location_gyeonggi_gunpo_si\": \"軍浦市\",\n    \"location_gyeonggi_uiwang_si\": \"義王市\",\n    \"location_gyeonggi_hanam\": \"河南市\",\n    \"location_gyeonggi_yongin_si\": \"龍仁市\",\n    \"location_gyeonggi_paju\": \"坡州市\",\n    \"location_gyeonggi_icheon\": \"利川市\",\n    \"location_gyeonggi_anseong_si\": \"安城市\",\n    \"location_gyeonggi_gimpo\": \"金浦市\",\n    \"location_gyeonggi_hwaseong_si\": \"華城市\",\n    \"location_gyeonggi_gwangju\": \"光州市\",\n    \"location_gyeonggi_yangju_si\": \"揚州市\",\n    \"location_gyeonggi_pocheon\": \"抱川市\",\n    \"location_gyeonggi_yeoju\": \"驪州市\",\n    \"location_gyeonggi_yeoncheon_gun\": \"漣川郡\",\n    \"location_gyeonggi_gapyeong_gun\": \"加平郡\",\n    \"location_gyeonggi_yangpyeong\": \"楊平郡\",\n    \"location_gangwon\": \"カンウォン道\",\n    \"location_gangwon_chuncheon\": \"春川市\",\n    \"location_gangwon_wonju\": \"原州市\",\n    \"location_gangwon_gangneung_si\": \"江陵市\",\n    \"location_gangwon_donghae\": \"東海市\",\n    \"location_gangwon_taebaek_si\": \"太白市\",\n    \"location_gangwon_sokcho\": \"束草市\",\n    \"location_gangwon_samcheok_si\": \"三陟市\",\n    \"location_gangwon_hongcheon\": \"洪川郡\",\n    \"location_gangwon_hoengseong_gun\": \"横城郡\",\n    \"location_gangwon_yeongwol_gun\": \"寧越郡\",\n    \"location_gangwon_pyeongchang\": \"平昌郡\",\n    \"location_gangwon_jeongseon\": \"旌善郡\",\n    \"location_gangwon_cheolwon\": \"鉄原郡\",\n    \"location_gangwon_hwacheon\": \"華川郡\",\n    \"location_gangwon_yanggu\": \"楊口郡\",\n    \"location_gangwon_inje\": \"麟蹄郡\",\n    \"location_gangwon_goseong\": \"高城郡\",\n    \"location_gangwon_yangyang\": \"襄陽郡\",\n    \"location_chungcheongbuk\": \"チュンチョンブク道\",\n    \"location_chungcheongbuk_cheongju\": \"清州市\",\n    \"location_chungcheongbuk_chungju\": \"忠州市\",\n    \"location_chungcheongbuk_jecheon\": \"堤川市\",\n    \"location_chungcheongbuk_boeun\": \"報恩郡\",\n    \"location_chungcheongbuk_okcheon\": \"沃川郡\",\n    \"location_chungcheongbuk_yeongdong\": \"永同郡\",\n    \"location_chungcheongbuk_jeungpyeong\": \"曽坪郡\",\n    \"location_chungcheongbuk_jincheon\": \"鎮川郡\",\n    \"location_chungcheongbuk_goesan\": \"槐山郡\",\n    \"location_chungcheongbuk_eumseong\": \"陰城郡\",\n    \"location_chungcheongbuk_danyang\": \"丹陽郡\",\n    \"location_chungcheongnam\": \"チュンチョンナム道\",\n    \"location_chungcheongnam_cheonan\": \"天安市\",\n    \"location_chungcheongnam_gongju\": \"公州市\",\n    \"location_chungcheongnam_boryeong\": \"保寧市\",\n    \"location_chungcheongnam_asan\": \"牙山市\",\n    \"location_chungcheongnam_seosan\": \"瑞山市\",\n    \"location_chungcheongnam_nonsan\": \"論山市\",\n    \"location_chungcheongnam_gyeryong\": \"鶏龍市\",\n    \"location_chungcheongnam_dangjin\": \"唐津市\",\n    \"location_chungcheongnam_geumsan\": \"錦山郡\",\n    \"location_chungcheongnam_buyeo\": \"扶余郡\",\n    \"location_chungcheongnam_seocheon\": \"舒川郡\",\n    \"location_chungcheongnam_cheongyang\": \"青陽郡\",\n    \"location_chungcheongnam_hongseong\": \"洪城郡\",\n    \"location_chungcheongnam_yesan\": \"礼山郡\",\n    \"location_chungcheongnam_taean\": \"泰安郡\",\n    \"location_jeollabuk\": \"チョンラブク道\",\n    \"location_jeollabuk_jeonju\": \"全州市\",\n    \"location_jeollabuk_gunsan_si\": \"群山市\",\n    \"location_jeollabuk_iksan\": \"益山市\",\n    \"location_jeollabuk_jeongeup\": \"井邑市\",\n    \"location_jeollabuk_namwon\": \"南原市\",\n    \"location_jeollabuk_gimje_si\": \"金堤市\",\n    \"location_jeollabuk_wanju\": \"完州郡\",\n    \"location_jeollabuk_jinan\": \"鎮安郡\",\n    \"location_jeollabuk_muju\": \"茂朱郡\",\n    \"location_jeollabuk_jangsu\": \"長水郡\",\n    \"location_jeollabuk_imsil\": \"任實郡\",\n    \"location_jeollabuk_sunchang\": \"淳昌郡\",\n    \"location_jeollabuk_gochang\": \"高敞郡\",\n    \"location_jeollabuk_buan\": \"扶安郡\",\n    \"location_jeollanam\": \"チョンラナム道\",\n    \"location_jeollanam_mokpo\": \"木浦市\",\n    \"location_jeollanam_yosu\": \"麗水市\",\n    \"location_jeollanam_suncheon_si\": \"順天市\",\n    \"location_jeollanam_naju\": \"羅州市\",\n    \"location_jeollanam_gwangyang_si\": \"光陽市\",\n    \"location_jeollanam_damyang\": \"潭陽郡\",\n    \"location_jeollanam_gokseong\": \"谷城郡\",\n    \"location_jeollanam_gurye\": \"求礼郡\",\n    \"location_jeollanam_goheung\": \"高興郡\",\n    \"location_jeollanam_boseong\": \"宝城郡\",\n    \"location_jeollanam_hwasun\": \"和順郡\",\n    \"location_jeollanam_jangheung\": \"長興郡\",\n    \"location_jeollanam_gangjin\": \"康津郡\",\n    \"location_jeollanam_haenam\": \"海南郡\",\n    \"location_jeollanam_yeongam\": \"霊岩郡\",\n    \"location_jeollanam_jindo\": \"務安郡\",\n    \"location_jeollanam_muan\": \"咸平郡\",\n    \"location_jeollanam_hampyeong\": \"霊光郡\",\n    \"location_jeollanam_yeonggwang\": \"長城郡\",\n    \"location_jeollanam_jangseong\": \"莞島郡\",\n    \"location_jeollanam_wando\": \"珍島郡\",\n    \"location_jeollanam_sinan\": \"新安郡\",\n    \"location_gyeongsangbuk\": \"キョンサンブク道\",\n    \"location_gyeongsangbuk_pohang_si\": \"浦項市\",\n    \"location_gyeongsangbuk_gyeongju_si\": \"慶州市\",\n    \"location_gyeongsangbuk_gimcheon_si\": \"金泉市\",\n    \"location_gyeongsangbuk_andong_si\": \"安東市\",\n    \"location_gyeongsangbuk_gumi_si\": \"亀尾市\",\n    \"location_gyeongsangbuk_yeongju_si\": \"栄州市\",\n    \"location_gyeongsangbuk_yeongcheon_si\": \"永川市\",\n    \"location_gyeongsangbuk_sangju_si\": \"尚州市\",\n    \"location_gyeongsangbuk_mungyeong_si\": \"聞慶市\",\n    \"location_gyeongsangbuk_gyeongsan_si\": \"慶山市\",\n    \"location_gyeongsangbuk_gunwi\": \"軍威郡\",\n    \"location_gyeongsangbuk_uiseong\": \"義城郡\",\n    \"location_gyeongsangbuk_cheongsong\": \"青松郡\",\n    \"location_gyeongsangbuk_goryong\": \"英陽郡\",\n    \"location_gyeongsangbuk_yeongdeok\": \"盈徳郡\",\n    \"location_gyeongsangbuk_cheongdo\": \"清道郡\",\n    \"location_gyeongsangbuk_golyeong\": \"高靈郡\",\n    \"location_gyeongsangbuk_seongju\": \"星州郡\",\n    \"location_gyeongsangbuk_chilgok\": \"漆谷郡\",\n    \"location_gyeongsangbuk_yecheon\": \"醴泉郡\",\n    \"location_gyeongsangbuk_bonghwa\": \"奉化郡\",\n    \"location_gyeongsangbuk_uljin\": \"蔚珍郡\",\n    \"location_gyeongsangbuk_ulleung\": \"鬱陵郡\",\n    \"location_gyeongsangnam\": \"キョンサンナム道\",\n    \"location_gyeongsangnam_changwon_si\": \"昌原市\",\n    \"location_gyeongsangnam_jinju\": \"晋州市\",\n    \"location_gyeongsangnam_tongyeong_si\": \"統営市\",\n    \"location_gyeongsangnam_sacheon_si\": \"泗川市\",\n    \"location_gyeongsangnam_gimhae_si\": \"金海市\",\n    \"location_gyeongsangnam_miryang_si\": \"密陽市\",\n    \"location_gyeongsangnam_geoje_si\": \"巨済市\",\n    \"location_gyeongsangnam_yangsan_si\": \"梁山市\",\n    \"location_gyeongsangnam_uiryeong\": \"宜寧郡\",\n    \"location_gyeongsangnam_haman\": \"咸安郡\",\n    \"location_gyeongsangnam_changnyeong\": \"昌寧郡\",\n    \"location_gyeongsangnam_goseong\": \"高城郡\",\n    \"location_gyeongsangnam_namhae\": \"南海郡\",\n    \"location_gyeongsangnam_hadong\": \"河東郡\",\n    \"location_gyeongsangnam_sancheong\": \"山清郡\",\n    \"location_gyeongsangnam_hamyang\": \"咸陽郡\",\n    \"location_gyeongsangnam_geochang\": \"居昌郡\",\n    \"location_gyeongsangnam_hapcheon\": \"陜川郡\",\n    \"location_jeju\": \"チェジュ\",\n    \"location_jeju_jeju_si\": \"済州市\",\n    \"location_jeju_seogwipo\": \"西帰浦市\",\n    \"EXPANSION_WEATHER_sunny\": \"快晴\",\n    \"EXPANSION_WEATHER_partly_cloudy\": \"晴れぎみ\",\n    \"EXPANSION_WEATHER_mostly_cloudy\": \"くもりぎみ\",\n    \"EXPANSION_WEATHER_cloudy\": \"くもり\",\n    \"EXPANSION_WEATHER_rainy\": \"雨\",\n    \"EXPANSION_WEATHER_sleet\": \"みぞれ\",\n    \"EXPANSION_WEATHER_snowy\": \"雪\",\n    \"EXPANSION_WEATHER_finedust_good\": \"良い\",\n    \"EXPANSION_WEATHER_finedust_normal\": \"普通\",\n    \"EXPANSION_WEATHER_finedust_bad\": \"悪い\",\n    \"EXPANSION_WEATHER_finedust_very_bad\": \"とても悪い\",\n    \"EXPANSION_WEATHER_lowest_temperature\": \"最低気温(℃)\",\n    \"EXPANSION_WEATHER_highest_temperature\": \"最高気温(℃)\",\n    \"EXPANSION_WEATHER_humidity\": \"湿度(%)\",\n    \"EXPANSION_WEATHER_precipitation\": \"降水量(mm)\",\n    \"EXPANSION_WEATHER_precipitation_probability\": \"降水確率(%)\",\n    \"EXPANSION_WEATHER_wind_speed\": \"風速(m/s)\",\n    \"EXPANSION_WEATHER_temperature\": \"気温(℃)\",\n    \"EXPANSION_WEATHER_finedust\": \"PM10濃度(㎍)\",\n    \"EXPANSION_FESTIVAL_title\": \"タイトル\",\n    \"EXPANSION_FESTIVAL_area\": \"エリア\",\n    \"EXPANSION_FESTIVAL_start_date\": \"開始日\",\n    \"EXPANSION_FESTIVAL_end_date\": \"終了日\",\n    \"EXPANSION_FESTIVAL_address\": \"アドレス\",\n    \"EXPANSION_FESTIVAL_coordinate\": \"座標\",\n    \"EXPANSION_FESTIVAL_overview\": \"概要\",\n    \"EXPANSION_FESTIVAL_homepage\": \"ホームページ\",\n    \"no_data\": \"情報なし\",\n    \"no_sentence\": \"テキストなし\",\n    \"sentence_over_20_charactor\": \"20字のみ入力できます。\",\n    \"sentence_over_3000_charactor\": \"3000字のみ入力できます。\",\n    \"sentence_over_2500_charactor\": \"2500文字のみ入力できます。\",\n    \"unknown_sentence\": \"認識不可能なテキストです。\",\n    \"auto\": \"自動\",\n    \"korean\": \"韓国語\",\n    \"english\": \"英語\",\n    \"spanish\": \"スペイン語\",\n    \"french\": \"フランス語\",\n    \"german\": \"ドイツ語\",\n    \"russian\": \"ロシア語\",\n    \"portuguese\": \"ポルトガル語\",\n    \"hindi\": \"ヒンディー語\",\n    \"japan\": \"日本語\",\n    \"thai\": \"タイ語\",\n    \"vietnamese\": \"ベトナム語\",\n    \"indonesian\": \"インドネシア語\",\n    \"chinese_simplified\": \"簡体字中国語\",\n    \"chinese_traditional\": \"繁体字中国語\",\n    \"italian\": \"イタリア語\",\n    \"behaviorConduct01001\": \"台風\",\n    \"behaviorConduct01002\": \"洪水\",\n    \"behaviorConduct01003\": \"豪雨\",\n    \"behaviorConduct01004\": \"強風\",\n    \"behaviorConduct01005\": \"大雪\",\n    \"behaviorConduct01006\": \"寒波\",\n    \"behaviorConduct01007\": \"波浪\",\n    \"behaviorConduct01008\": \"黄砂\",\n    \"behaviorConduct01009\": \"猛暑\",\n    \"behaviorConduct01010\": \"干ばつ\",\n    \"behaviorConduct01011\": \"地震\",\n    \"behaviorConduct01013\": \"津波\",\n    \"behaviorConduct01014\": \"地滑り\",\n    \"behaviorConduct03002\": \"応急処置\",\n    \"behaviorConduct03003\": \"心肺蘇生法\",\n    \"behaviorConduct03004\": \"消火栓の使い方\",\n    \"behaviorConduct03016\": \"消火器の使い方\",\n    \"behaviorConduct03005\": \"食中毒\",\n    \"behaviorConduct03006\": \"山の安全対策\",\n    \"behaviorConduct03008\": \"失踪と誘拐\",\n    \"behaviorConduct03009\": \"性暴力\",\n    \"behaviorConduct03010\": \"学校暴力\",\n    \"behaviorConduct03011\": \"家庭内暴力\",\n    \"behaviorConduct03012\": \"抑留および拉致\",\n    \"behaviorConduct03013\": \"交通事故\",\n    \"behaviorConduct03014\": \"エレベーター事故\",\n    \"behaviorConduct03015\": \"浮遊粒子状物質\",\n    \"behaviorConduct01001001\": \"台風が来る前\",\n    \"behaviorConduct01001002\": \"台風警報が出された時\",\n    \"behaviorConduct01001003\": \"台風が通り過ぎた後\",\n    \"behaviorConduct01002002\": \"洪水予報時\",\n    \"behaviorConduct01002003\": \"水が押し寄せる時\",\n    \"behaviorConduct01002004\": \"水が抜けた後\",\n    \"behaviorConduct01003002\": \"大雨予報時\",\n    \"behaviorConduct01003003\": \"大雨注意報∙警報が出された時\",\n    \"behaviorConduct01003004\": \"大雨が過ぎ去った後\",\n    \"behaviorConduct01004001\": \"強風が来る前\",\n    \"behaviorConduct01004002\": \"強風発生時\",\n    \"behaviorConduct01005002\": \"大雪が来る前\",\n    \"behaviorConduct01005003\": \"大雪発生時\",\n    \"behaviorConduct01005004\": \"大雪が通り過ぎた後\",\n    \"behaviorConduct01006001\": \"寒波が押し寄せる前\",\n    \"behaviorConduct01006002\": \"寒波発生時\",\n    \"behaviorConduct01007001\": \"波浪注意報・警報時\",\n    \"behaviorConduct01007002\": \"波浪が押し寄せる前\",\n    \"behaviorConduct01008001\": \"黄砂予報時\",\n    \"behaviorConduct01008002\": \"黄砂発生時\",\n    \"behaviorConduct01008003\": \"黄砂が過ぎ去った後\",\n    \"behaviorConduct01009001\": \"猛暑が来る前\",\n    \"behaviorConduct01009002\": \"猛暑注意報時\",\n    \"behaviorConduct01010001\": \"干ばつが来る前\",\n    \"behaviorConduct01011009\": \"地震が来る前\",\n    \"behaviorConduct01011010\": \"地震発生時\",\n    \"behaviorConduct01011012\": \"地震避難後\",\n    \"behaviorConduct01013002\": \"津波が来る前\",\n    \"behaviorConduct01013003\": \"津波発生時\",\n    \"behaviorConduct01014001\": \"地滑り注意報時\",\n    \"behaviorConduct03002002\": \"やけどの処置\",\n    \"behaviorConduct03002003\": \"高熱の予防\",\n    \"behaviorConduct03002004\": \"ヘビにかまれたときの処置\",\n    \"behaviorConduct03002005\": \"ハチにさされたときの処置\",\n    \"behaviorConduct03002006\": \"過呼吸症候群の応急処置\",\n    \"behaviorConduct03003001\": \"成人の心肺蘇生法\",\n    \"behaviorConduct03003002\": \"乳幼児の心肺蘇生法\",\n    \"behaviorConduct03003003\": \"自動体外式除細動器(AED)を使用\",\n    \"behaviorConduct03004001\": \"粉末消火器を使用\",\n    \"behaviorConduct03016001\": \"屋内消火栓の使用\",\n    \"behaviorConduct03005001\": \"食中毒の対処\",\n    \"behaviorConduct03006004\": \"登山中の注意事項\",\n    \"behaviorConduct03006005\": \"山での安全なキャンピング\",\n    \"behaviorConduct03006002\": \"救助要請の際に知らせること\",\n    \"behaviorConduct03006003\": \"登山事故時の緊急措置\",\n    \"behaviorConduct03008001\": \"失踪・誘拐の予防\",\n    \"behaviorConduct03009001\": \"性暴力の防止\",\n    \"behaviorConduct03010001\": \"学校暴力の予防\",\n    \"behaviorConduct03011001\": \"家庭内暴力の予防\",\n    \"behaviorConduct03012001\": \"抑留と拉致時の措置\",\n    \"behaviorConduct03013002\": \"交通事故発生時の措置\",\n    \"behaviorConduct03013005\": \"自動車での救助\",\n    \"behaviorConduct03014001\": \"エレベーターの安全利用\",\n    \"behaviorConduct03014003\": \"エレベーターの故障時の措置\",\n    \"behaviorConduct03014004\": \"エスカレーターの安全利用\",\n    \"behaviorConduct03015007\": \"浮遊粒子状物質の多い日の生活\",\n    \"behaviorConduct03015003\": \"カテゴリー別の生活\",\n    \"tts_female\": \"女性の\",\n    \"tts_male\": \"男性の\",\n    \"tts_kind\": \"やさしい\",\n    \"tts_sweet\": \"あまい\",\n    \"tts_echo\": \"響く\",\n    \"tts_mischievous\": \"いたずらっぽい\",\n    \"tts_dainty\": \"かわいらしい\",\n    \"tts_veryslow\": \"とてもゆっくりに\",\n    \"tts_slow\": \"ゆっくりに\",\n    \"tts_normal\": \"普通\",\n    \"tts_fast\": \"速く\",\n    \"tts_veryfast\": \"とても速く\",\n    \"tts_verylow\": \"とても低く\",\n    \"tts_low\": \"低く\",\n    \"tts_high\": \"高く\",\n    \"tts_veryhigh\": \"とても高く\",\n    \"ARDUINO\": \"Hardware\",\n    \"ARDUINO_download_connector\": \"• 接続ソフトをダウンロード\",\n    \"ARDUINO_open_connector\": \"接続ソフトを開く\",\n    \"ARDUINO_download_source\": \"• ENTRYのArduinoコード\",\n    \"ARDUINO_reconnect\": \"ハードウェアに接続する\",\n    \"arduino_noti_text\": \"モバイル機器でのハードウェア\\n    接続は今後対応予定です。\",\n    \"ROBOT_reconnect\": \"ロボットを連結する\",\n    \"ARDUINO_program\": \"Run the program\",\n    \"ARDUINO_cloud_pc_connector\": \"Connect to Cloud PC\",\n    \"ARDUINO_connected\": \"Hardware connected\",\n    \"ARDUINO_connect\": \"* Connect hardware\",\n    \"ARDUINO_arduino_get_number_1\": \"number result of signal\",\n    \"ARDUINO_arduino_get_number_2\": \"\",\n    \"ARDUINO_arduino_get_sensor_number_0\": \"0\",\n    \"ARDUINO_arduino_get_sensor_number_1\": \"1\",\n    \"ARDUINO_arduino_get_sensor_number_2\": \"2\",\n    \"ARDUINO_arduino_get_sensor_number_3\": \"3\",\n    \"ARDUINO_arduino_get_sensor_number_4\": \"4\",\n    \"ARDUINO_arduino_get_sensor_number_5\": \"5\",\n    \"arduino_lite_connected_noti\": \"ハードウェアを選択した状態で\\n作品を保存してください。\",\n    \"blacksmith_toggle_on\": \"on\",\n    \"blacksmith_toggle_off\": \"off\",\n    \"blacksmith_lcd_first_line\": \"first\",\n    \"blacksmith_lcd_seconds_line\": \"seconds\",\n    \"BITBRICK_light\": \"light\",\n    \"BITBRICK_IR\": \"IR\",\n    \"BITBRICK_touch\": \"touch\",\n    \"BITBRICK_potentiometer\": \"potentiometer\",\n    \"BITBRICK_MIC\": \"MIC\",\n    \"BITBRICK_UserSensor\": \"UserSensor\",\n    \"BITBRICK_UserInput\": \"UserInput\",\n    \"BITBRICK_dc_direction_ccw\": \"CCW\",\n    \"BITBRICK_dc_direction_cw\": \"CW\",\n    \"chocopi_control_event_pressed\": \"pressed\",\n    \"chocopi_control_event_released\": \"released\",\n    \"chocopi_joystick_X\": \"joystick X\",\n    \"chocopi_joystick_Y\": \"joystick Y\",\n    \"chocopi_motion_photogate_event_blocked\": \"blocked\",\n    \"chocopi_motion_photogate_event_unblocked\": \"unblocked\",\n    \"chocopi_motion_photogate_time_blocked\": \"blocked\",\n    \"chocopi_motion_photogate_time_unblocked\": \"unblocked\",\n    \"chocopi_port\": \"P\",\n    \"chocopi_pot\": \"potentiometer\",\n    \"chocopi_touch_event_touch\": \"touched\",\n    \"chocopi_touch_event_untouch\": \"untouched\",\n    \"CODEino_get_sensor_number_0\": \"0\",\n    \"CODEino_get_sensor_number_1\": \"1\",\n    \"CODEino_get_sensor_number_2\": \"2\",\n    \"CODEino_get_sensor_number_3\": \"3\",\n    \"CODEino_get_sensor_number_4\": \"4\",\n    \"CODEino_get_sensor_number_5\": \"5\",\n    \"CODEino_get_sensor_number_6\": \"6\",\n    \"CODEino_sensor_name_0\": \"Sound\",\n    \"CODEino_sensor_name_1\": \"Light\",\n    \"CODEino_sensor_name_2\": \"Slider\",\n    \"CODEino_sensor_name_3\": \"resistance-A\",\n    \"CODEino_sensor_name_4\": \"resistance-B\",\n    \"CODEino_sensor_name_5\": \"resistance-C\",\n    \"CODEino_sensor_name_6\": \"resistance-D\",\n    \"CODEino_string_1\": \" Sensor value \",\n    \"CODEino_string_2\": \" Operation \",\n    \"CODEino_string_3\": \"Push button\",\n    \"CODEino_string_4\": \"Connected A\",\n    \"CODEino_string_5\": \"Connected B\",\n    \"CODEino_string_6\": \"Connected C\",\n    \"CODEino_string_7\": \"Connected D\",\n    \"CODEino_string_8\": \" 3-AXIS Accelerometer \",\n    \"CODEino_string_9\": \"-axis value \",\n    \"CODEino_string_10\": \"Sound is \",\n    \"CODEino_string_11\": \"Great\",\n    \"CODEino_string_12\": \"Small\",\n    \"CODEino_string_13\": \"Light is \",\n    \"CODEino_string_14\": \"Bright\",\n    \"CODEino_string_15\": \"Dark\",\n    \"CODEino_string_16\": \"Left tilt\",\n    \"CODEino_string_17\": \"Right tilt\",\n    \"CODEino_string_18\": \"Front tilt\",\n    \"CODEino_string_19\": \"Rear tilt\",\n    \"CODEino_string_20\": \"Reverse\",\n    \"CODEino_accelerometer_X\": \"X\",\n    \"CODEino_accelerometer_Y\": \"Y\",\n    \"CODEino_accelerometer_Z\": \"Z\",\n    \"CODEino_led_red\": \"Red\",\n    \"CODEino_led_green\": \"Green\",\n    \"CODEino_led_blue\": \"Blue\",\n    \"iboard_analog_number_0\": \"A0\",\n    \"iboard_analog_number_1\": \"A1\",\n    \"iboard_analog_number_2\": \"A2\",\n    \"iboard_analog_number_3\": \"A3\",\n    \"iboard_analog_number_4\": \"A4\",\n    \"iboard_analog_number_5\": \"A5\",\n    \"iboard_light\": \"Light sensor is \",\n    \"iboard_num_pin_1\": \"LED status\",\n    \"iboard_num_pin_2\": \"switch\",\n    \"iboard_num_pin_3\": \"analogue\",\n    \"iboard_num_pin_4\": \" \",\n    \"iboard_num_pin_5\": \"sensor value\",\n    \"iboard_string_1\": \"on\",\n    \"iboard_string_2\": \"off\",\n    \"iboard_string_3\": \"bright\",\n    \"iboard_string_4\": \"dark\",\n    \"iboard_string_5\": \"pressed\",\n    \"iboard_string_6\": \"opened\",\n    \"iboard_switch\": \"switch \",\n    \"iboard_tilt\": \"Slope sensor status is\",\n    \"dplay_switch\": \"스위치 \",\n    \"dplay_light\": \"Light sensor is \",\n    \"dplay_tilt\": \"Slope sensor status is\",\n    \"dplay_string_1\": \"켜짐\",\n    \"dplay_string_2\": \"꺼짐\",\n    \"dplay_string_3\": \"bright\",\n    \"dplay_string_4\": \"dark\",\n    \"dplay_string_5\": \"pressed\",\n    \"dplay_string_6\": \"opened\",\n    \"dplay_num_pin_1\": \"LED status\",\n    \"dplay_num_pin_2\": \"switch\",\n    \"dplay_num_pin_3\": \"analogue\",\n    \"dplay_num_pin_4\": \"번 \",\n    \"dplay_num_pin_5\": \"sensor value\",\n    \"dplay_analog_number_0\": \"A0\",\n    \"dplay_analog_number_1\": \"A1\",\n    \"dplay_analog_number_2\": \"A2\",\n    \"dplay_analog_number_3\": \"A3\",\n    \"dplay_analog_number_4\": \"A4\",\n    \"dplay_analog_number_5\": \"A5\",\n    \"ARDUINO_arduino_get_string_1\": \"string result of signal\",\n    \"ARDUINO_arduino_get_string_2\": \"\",\n    \"ARDUINO_arduino_send_1\": \"Send signal\",\n    \"ARDUINO_arduino_send_2\": \"\",\n    \"ARDUINO_num_sensor_value_1\": \"Analog\",\n    \"ARDUINO_num_sensor_value_2\": \"Sensor value\",\n    \"ARDUINO_get_digital_value_1\": \"Digital\",\n    \"ARDUINO_num_pin_1\": \"Digital\",\n    \"ARDUINO_num_pin_2\": \"Pin\",\n    \"ARDUINO_toggle_pwm_1\": \"Digital\",\n    \"ARDUINO_toggle_pwm_2\": \"Pin\",\n    \"ARDUINO_toggle_pwm_3\": \"\",\n    \"ARDUINO_on\": \"On\",\n    \"ARDUINO_convert_scale_1\": \"Map Value\",\n    \"ARDUINO_convert_scale_2\": \"\",\n    \"ARDUINO_convert_scale_3\": \"~\",\n    \"ARDUINO_convert_scale_4\": \"to\",\n    \"ARDUINO_convert_scale_5\": \"~\",\n    \"ARDUINO_convert_scale_6\": \"\",\n    \"ARDUINO_off\": \"Off\",\n    \"EXPANSION\": \"拡張\",\n    \"brightness\": \"明度\",\n    \"BRUSH\": \"筆\",\n    \"BRUSH_brush_erase_all\": \"すべての筆のあとを消す\",\n    \"BRUSH_change_opacity_1\": \"筆の不透明度を\",\n    \"BRUSH_change_opacity_2\": \"%に変更\",\n    \"BRUSH_change_thickness_1\": \"筆の太さを\",\n    \"BRUSH_change_thickness_2\": \"変更する\",\n    \"BRUSH_set_color_1\": \"筆の色を\",\n    \"BRUSH_set_color_2\": \"にする\",\n    \"BRUSH_set_opacity_1\": \"筆の不透明度を\",\n    \"BRUSH_set_opacity_2\": \"%にする\",\n    \"BRUSH_set_random_color\": \"筆の色をランダムにする\",\n    \"BRUSH_set_thickness_1\": \"筆の太さを\",\n    \"BRUSH_set_thickness_2\": \"にする\",\n    \"BRUSH_stamp\": \"スタンプを押す\",\n    \"BRUSH_start_drawing\": \"描画スタート\",\n    \"BRUSH_stop_drawing\": \"描画をやめる\",\n    \"CALC\": \"計算\",\n    \"CALC_calc_mod_1\": \" \",\n    \"CALC_calc_mod_2\": \"/\",\n    \"CALC_calc_mod_3\": \"あまり\",\n    \"CALC_calc_operation_of_1\": \" \",\n    \"CALC_calc_operation_of_2\": \"の\",\n    \"CALC_calc_operation_root\": \"ルート\",\n    \"CALC_calc_operation_square\": \"乗\",\n    \"CALC_calc_rand_1\": \" \",\n    \"CALC_calc_rand_2\": \"から\",\n    \"CALC_calc_rand_3\": \"間の乱数\",\n    \"CALC_calc_share_1\": \" \",\n    \"CALC_calc_share_2\": \"/\",\n    \"CALC_calc_share_3\": \"の商\",\n    \"CALC_coordinate_mouse_1\": \"マウスの\",\n    \"CALC_coordinate_mouse_2\": \"座標\",\n    \"CALC_coordinate_object_1\": \" \",\n    \"CALC_coordinate_object_2\": \"の\",\n    \"CALC_coordinate_object_3\": \" \",\n    \"CALC_distance_something_1\": \" \",\n    \"CALC_distance_something_2\": \"までの距離\",\n    \"CALC_get_angle\": \"角度値\",\n    \"CALC_get_date_1\": \" 現在の\",\n    \"CALC_get_date_2\": \" \",\n    \"CALC_get_date_day\": \"日\",\n    \"CALC_get_date_hour\": \"時刻(時)\",\n    \"CALC_get_date_minute\": \"時刻(分)\",\n    \"CALC_get_date_month\": \"月\",\n    \"CALC_get_date_second\": \"時刻(秒)\",\n    \"CALC_get_date_year\": \"年度\",\n    \"CALC_get_sound_duration_1\": \" \",\n    \"CALC_get_sound_duration_2\": \"音の長さ\",\n    \"CALC_get_timer_value\": \" ストップウォッチの値\",\n    \"CALC_get_x_coordinate\": \"X座標値\",\n    \"CALC_get_y_coordinate\": \"Y座標値\",\n    \"CALC_timer_reset\": \"ストップウォッチ初期化\",\n    \"CALC_timer_visible_1\": \"ストップウォッチを\",\n    \"CALC_timer_visible_2\": \" \",\n    \"CALC_timer_visible_show\": \"見せる\",\n    \"CALC_timer_visible_hide\": \"隠す\",\n    \"color\": \"色\",\n    \"FLOW\": \"フロー \",\n    \"FLOW__if_1\": \"もし\",\n    \"FLOW__if_2\": \"なら\",\n    \"FLOW_create_clone_1\": \" \",\n    \"FLOW_create_clone_2\": \"のコピーを作る\",\n    \"FLOW_delete_clone\": \"このコピーを削除する\",\n    \"FLOW_delete_clone_all\": \"すべてのコピーを削除する\",\n    \"FLOW_if_else_1\": \"もし\",\n    \"FLOW_if_else_2\": \"なら\",\n    \"FLOW_if_else_3\": \"そうでなければ\",\n    \"FLOW_repeat_basic_1\": \" \",\n    \"FLOW_repeat_basic_2\": \"回繰り返す\",\n    \"FLOW_repeat_basic_errorMsg\": \"反復回数は0と同じまたは大きい必要があります。\",\n    \"FLOW_repeat_inf\": \"ずっと繰り返す\",\n    \"FLOW_restart\": \"最初から再実行する\",\n    \"FLOW_stop_object_1\": \" \",\n    \"FLOW_stop_object_2\": \"やめる\",\n    \"FLOW_stop_object_all\": \"すべての\",\n    \"FLOW_stop_object_this_object\": \"自分の\",\n    \"FLOW_stop_object_this_thread\": \"この\",\n    \"FLOW_stop_object_other_thread\": \"自分の他の\",\n    \"FLOW_stop_object_other_objects\": \"他のオブジェクトの\",\n    \"FLOW_stop_repeat\": \"繰り返しをやめる\",\n    \"FLOW_stop_run\": \"プログラムを終了する\",\n    \"FLOW_wait_second_1\": \" \",\n    \"FLOW_wait_second_2\": \"秒待つ\",\n    \"FLOW_wait_until_true_1\": \" \",\n    \"FLOW_wait_until_true_2\": \"になるまで待つ\",\n    \"FLOW_when_clone_start\": \"コピーが最初に作成された時\",\n    \"FUNC\": \"関数\",\n    \"ANALYSIS\": \"データ分析\",\n    \"AI\": \"人工知能\",\n    \"JUDGEMENT\": \"判断\",\n    \"JUDGEMENT_boolean_and\": \"そして\",\n    \"JUDGEMENT_boolean_not_1\": \" \",\n    \"JUDGEMENT_boolean_not_2\": \"ではない\",\n    \"JUDGEMENT_boolean_or\": \"または\",\n    \"JUDGEMENT_false\": \" false\",\n    \"JUDGEMENT_is_clicked\": \"マウスをクリックしたか?\",\n    \"JUDGEMENT_is_press_some_key_1\": \" \",\n    \"JUDGEMENT_is_press_some_key_2\": \"キーを押しているか？\",\n    \"JUDGEMENT_reach_something_1\": \" \",\n    \"JUDGEMENT_reach_something_2\": \"に着いたか？\",\n    \"JUDGEMENT_true\": \" true\",\n    \"JUDGEMENT_is_boost_mode\": \"ブーストモードがオンになっているか？\",\n    \"LOOKS\": \"見た目\",\n    \"LOOKS_change_scale_percent_1\": \"サイズを\",\n    \"LOOKS_change_scale_percent_2\": \"分変更する\",\n    \"LOOKS_change_to_next_shape\": \"次の模様に変更する\",\n    \"LOOKS_change_to_nth_shape_1\": \" \",\n    \"LOOKS_change_to_nth_shape_2\": \"模様に変更する\",\n    \"LOOKS_change_shape_prev\": \"前の\",\n    \"LOOKS_change_shape_next\": \"次の\",\n    \"LOOKS_change_to_near_shape_1\": \" \",\n    \"LOOKS_change_to_near_shape_2\": \"模様に変更する\",\n    \"LOOKS_dialog_1\": \" \",\n    \"LOOKS_dialog_2\": \"を\",\n    \"LOOKS_dialog_3\": \" \",\n    \"LOOKS_dialog_time_1\": \" \",\n    \"LOOKS_dialog_time_2\": \"を\",\n    \"LOOKS_dialog_time_3\": \"秒間\",\n    \"LOOKS_dialog_time_4\": \" \",\n    \"LOOKS_erase_all_effects\": \"効果をすべて削除する\",\n    \"LOOKS_flip_x\": \"上下の模様を入れ替える\",\n    \"LOOKS_flip_y\": \"左右の模様を入れ替える\",\n    \"LOOKS_hide\": \"模様非表示\",\n    \"LOOKS_remove_dialog\": \"会話を削除する\",\n    \"LOOKS_set_effect_1\": \" \",\n    \"LOOKS_set_effect_2\": \"効果を\",\n    \"LOOKS_set_effect_3\": \"にする\",\n    \"LOOKS_set_effect_volume_1\": \" \",\n    \"LOOKS_set_effect_volume_2\": \"効果を\",\n    \"LOOKS_set_effect_volume_3\": \"加える\",\n    \"LOOKS_set_object_order_1\": \" \",\n    \"LOOKS_set_object_order_2\": \"番目に上げる\",\n    \"LOOKS_set_scale_percent_1\": \"サイズを\",\n    \"LOOKS_set_scale_percent_2\": \" にする\",\n    \"LOOKS_show\": \"模様表示\",\n    \"mouse_pointer\": \"マウスポインター\",\n    \"MOVING\": \"動き\",\n    \"MOVING_bounce_wall\": \"壁に着いたら、跳ね返る\",\n    \"MOVING_bounce_when_1\": \" \",\n    \"MOVING_bounce_when_2\": \"に到達した場合弾く\",\n    \"MOVING_flip_arrow_horizontal\": \"矢印の方向を左右入れ替える\",\n    \"MOVING_flip_arrow_vertical\": \"矢印の方向を上下入れ替える\",\n    \"MOVING_locate_1\": \" \",\n    \"MOVING_locate_2\": \"位置に移動する\",\n    \"MOVING_locate_time_1\": \" \",\n    \"MOVING_locate_time_2\": \"秒間\",\n    \"MOVING_locate_time_3\": \"位置に移動する\",\n    \"MOVING_locate_x_1\": \"x:\",\n    \"MOVING_locate_x_2\": \"位置に移動する\",\n    \"MOVING_locate_xy_1\": \"x:\",\n    \"MOVING_locate_xy_2\": \"y:\",\n    \"MOVING_locate_xy_3\": \"位置に移動する\",\n    \"MOVING_locate_xy_time_1\": \" \",\n    \"MOVING_locate_xy_time_2\": \"秒間x:\",\n    \"MOVING_locate_xy_time_3\": \"y:\",\n    \"MOVING_locate_xy_time_4\": \"位置に移動する\",\n    \"MOVING_locate_y_1\": \"y:\",\n    \"MOVING_locate_y_2\": \"位置に移動する\",\n    \"MOVING_move_direction_1\": \"移動方向に\",\n    \"MOVING_move_direction_2\": \"動かす\",\n    \"MOVING_move_direction_angle_1\": \" \",\n    \"MOVING_move_direction_angle_2\": \"方向に\",\n    \"MOVING_move_direction_angle_3\": \"動かす\",\n    \"MOVING_move_x_1\": \"x 座標を\",\n    \"MOVING_move_x_2\": \"分変更する\",\n    \"MOVING_move_xy_time_1\": \" \",\n    \"MOVING_move_xy_time_2\": \"秒間x:\",\n    \"MOVING_move_xy_time_3\": \"y:\",\n    \"MOVING_move_xy_time_4\": \"分動かす\",\n    \"MOVING_move_y_1\": \"y座標を\",\n    \"MOVING_move_y_2\": \"分変更する\",\n    \"MOVING_rotate_by_angle_1\": \"オブジェクトを\",\n    \"MOVING_rotate_by_angle_2\": \"回転する\",\n    \"MOVING_rotate_by_angle_dropdown_1\": \" \",\n    \"MOVING_rotate_by_angle_dropdown_2\": \"回転する\",\n    \"MOVING_rotate_by_angle_time_1\": \"オブジェクトを\",\n    \"MOVING_rotate_by_angle_time_2\": \"秒間\",\n    \"MOVING_rotate_by_angle_time_3\": \"分回転する\",\n    \"MOVING_rotate_direction_1\": \"移動方向を\",\n    \"MOVING_rotate_direction_2\": \"分回転する\",\n    \"MOVING_see_angle_1\": \"移動方向を\",\n    \"MOVING_see_angle_2\": \"にする\",\n    \"MOVING_see_angle_direction_1\": \"オブジェクトを\",\n    \"MOVING_see_angle_direction_2\": \"にする\",\n    \"MOVING_see_angle_object_1\": \" \",\n    \"MOVING_see_angle_object_2\": \"側を向く\",\n    \"MOVING_see_direction_1\": \" \",\n    \"MOVING_see_direction_2\": \"側にターンする\",\n    \"MOVING_set_direction_by_angle_1\": \"方向を\",\n    \"MOVING_set_direction_by_angle_2\": \"にする\",\n    \"MOVING_add_direction_by_angle_1\": \"方向を\",\n    \"MOVING_add_direction_by_angle_2\": \"回転する\",\n    \"MOVING_add_direction_by_angle_time_1\": \"方向を\",\n    \"MOVING_add_direction_by_angle_time_2\": \"秒間\",\n    \"MOVING_add_direction_by_angle_time_3\": \"回転する\",\n    \"no_target\": \"対象なし\",\n    \"oneself\": \"自分\",\n    \"opacity\": \"不透明度\",\n    \"SCENE\": \"シーン\",\n    \"SOUND\": \"音\",\n    \"SOUND_sound_silent_all\": \"すべてのサウンドを中断する\",\n    \"SOUND_sound_something_1\": \"サウンド\",\n    \"SOUND_sound_something_2\": \"再生する\",\n    \"SOUND_sound_something_second_1\": \"サウンド\",\n    \"SOUND_sound_something_second_2\": \" \",\n    \"SOUND_sound_something_second_3\": \"秒再生する\",\n    \"SOUND_sound_something_second_wait_1\": \"サウンド\",\n    \"SOUND_sound_something_second_wait_2\": \" \",\n    \"SOUND_sound_something_second_wait_3\": \"秒再生して待つ\",\n    \"SOUND_sound_something_wait_1\": \"サウンド\",\n    \"SOUND_sound_something_wait_2\": \"再生して待つ\",\n    \"SOUND_sound_volume_change_1\": \"音の大きさを\",\n    \"SOUND_sound_volume_change_2\": \"%に変更\",\n    \"SOUND_sound_volume_set_1\": \"音の大きさを\",\n    \"SOUND_sound_volume_set_2\": \"%にする\",\n    \"speak\": \"言う\",\n    \"think\": \"思う\",\n    \"START\": \"はじめ\",\n    \"START_add_message\": \"信号を追加する\",\n    \"START_delete_message\": \"信号を削除する\",\n    \"START_message_cast\": \"信号を送る\",\n    \"START_message_cast_1\": \" \",\n    \"START_message_cast_2\": \"信号を送る\",\n    \"START_message_cast_wait\": \"信号を送って待機\",\n    \"START_message_send_wait_1\": \" \",\n    \"START_message_send_wait_2\": \"信号を送って待機\",\n    \"START_mouse_click_cancled\": \"マウスをクリックして離した時\",\n    \"START_mouse_clicked\": \"マウスをクリックした時\",\n    \"START_press_some_key_1\": \" \",\n    \"START_press_some_key_2\": \"キーを押した時\",\n    \"START_press_some_key_down\": \"下矢印\",\n    \"START_press_some_key_enter\": \"エンター\",\n    \"START_press_some_key_left\": \"左矢印\",\n    \"START_press_some_key_right\": \"右矢印\",\n    \"START_press_some_key_space\": \"スペース\",\n    \"START_press_some_key_up\": \"上矢印\",\n    \"START_when_message_cast\": \"信号を受け取った時\",\n    \"START_when_message_cast_1\": \" \",\n    \"START_when_message_cast_2\": \"信号を受け取った時\",\n    \"START_when_object_click\": \"オブジェクトをクリックした時\",\n    \"START_when_object_click_canceled\": \"オブジェクトをクリックして離した時\",\n    \"START_when_run_button_click\": \"スタートボタンをクリックした時\",\n    \"START_when_scene_start\": \"シーンが始まった時\",\n    \"START_when_some_key_click\": \"キーを押した時\",\n    \"TEXT\": \"テキストボックス\",\n    \"TEXT_text\": \"エントリー\",\n    \"TEXT_text_append_1\": \" \",\n    \"TEXT_text_append_2\": \"と後ろに続けて書く\",\n    \"TEXT_text_flush\": \"テキストをすべて削除する\",\n    \"TEXT_text_prepend_1\": \" \",\n    \"TEXT_text_prepend_2\": \"と前に追加する\",\n    \"TEXT_text_write_1\": \" \",\n    \"TEXT_text_write_2\": \"と書く\",\n    \"VARIABLE\": \"データ\",\n    \"VARIABLE_add_value_to_list\": \"項目をリストに追加する\",\n    \"VARIABLE_add_value_to_list_1\": \" \",\n    \"VARIABLE_add_value_to_list_2\": \"項目を\",\n    \"VARIABLE_add_value_to_list_3\": \"に追加する\",\n    \"VARIABLE_ask_and_wait_1\": \" \",\n    \"VARIABLE_ask_and_wait_2\": \"を尋ねて回答を待機\",\n    \"VARIABLE_change_value_list_index\": \"項目を変更する\",\n    \"VARIABLE_change_value_list_index_1\": \" \",\n    \"VARIABLE_change_value_list_index_3\": \"番目の項目を\",\n    \"VARIABLE_change_value_list_index_2\": \" \",\n    \"VARIABLE_change_value_list_index_4\": \"に変更する\",\n    \"VARIABLE_change_variable\": \"変数を加える\",\n    \"VARIABLE_change_variable_1\": \" \",\n    \"VARIABLE_change_variable_2\": \"に\",\n    \"VARIABLE_change_variable_3\": \"加える\",\n    \"VARIABLE_change_variable_name\": \"変数名を変更する\",\n    \"VARIABLE_combine_something_1\": \" \",\n    \"VARIABLE_combine_something_2\": \"と\",\n    \"VARIABLE_combine_something_3\": \"をつなげる\",\n    \"VARIABLE_get_canvas_input_value\": \"答え\",\n    \"VARIABLE_get_variable\": \"変数\",\n    \"VARIABLE_get_variable_1\": \"の値\",\n    \"VARIABLE_get_variable_2\": \"値\",\n    \"VARIABLE_get_y\": \"Y座標値\",\n    \"VARIABLE_hide_list\": \"リスト非表示\",\n    \"VARIABLE_hide_list_1\": \"リスト\",\n    \"VARIABLE_hide_list_2\": \"非表示\",\n    \"VARIABLE_hide_variable\": \"変数値非表示\",\n    \"VARIABLE_hide_variable_1\": \"変数\",\n    \"VARIABLE_hide_variable_2\": \"非表示\",\n    \"VARIABLE_insert_value_to_list\": \"項目を挿入する\",\n    \"VARIABLE_insert_value_to_list_1\": \" \",\n    \"VARIABLE_insert_value_to_list_2\": \"を\",\n    \"VARIABLE_insert_value_to_list_3\": \"の\",\n    \"VARIABLE_insert_value_to_list_4\": \"番目に入れる\",\n    \"VARIABLE_length_of_list\": \"リストの長さ\",\n    \"VARIABLE_length_of_list_1\": \" \",\n    \"VARIABLE_length_of_list_2\": \" の項目数\",\n    \"VARIABLE_list\": \"リスト\",\n    \"VARIABLE_make_variable\": \"変数を作成する\",\n    \"VARIABLE_list_option_first\": \"最初\",\n    \"VARIABLE_list_option_last\": \"最後\",\n    \"VARIABLE_list_option_random\": \"ランダム\",\n    \"VARIABLE_remove_value_from_list\": \"項目を削除する\",\n    \"VARIABLE_remove_value_from_list_1\": \" \",\n    \"VARIABLE_remove_value_from_list_2\": \"番目の項目を\",\n    \"VARIABLE_remove_value_from_list_3\": \"から削除する\",\n    \"VARIABLE_remove_variable\": \"変数削除\",\n    \"VARIABLE_set_variable\": \"変数を定める\",\n    \"VARIABLE_set_variable_1\": \" \",\n    \"VARIABLE_set_variable_2\": \"を\",\n    \"VARIABLE_set_variable_3\": \"にする\",\n    \"VARIABLE_show_list\": \"リスト表示\",\n    \"VARIABLE_show_list_1\": \"リスト\",\n    \"VARIABLE_show_list_2\": \"表示\",\n    \"VARIABLE_show_variable\": \"変数値表示\",\n    \"VARIABLE_show_variable_1\": \"変数\",\n    \"VARIABLE_show_variable_2\": \"表示\",\n    \"VARIABLE_value_of_index_from_list\": \"リスト項目の値\",\n    \"VARIABLE_value_of_index_from_list_1\": \" \",\n    \"VARIABLE_value_of_index_from_list_2\": \"の\",\n    \"VARIABLE_value_of_index_from_list_3\": \"番目の項目\",\n    \"HAMSTER_hand_found\": \"hand found?\",\n    \"HAMSTER_sensor_left_proximity\": \"left proximity\",\n    \"HAMSTER_sensor_right_proximity\": \"right proximity\",\n    \"HAMSTER_sensor_left_floor\": \"left floor\",\n    \"HAMSTER_sensor_right_floor\": \"right floor\",\n    \"HAMSTER_sensor_acceleration_x\": \"x acceleration\",\n    \"HAMSTER_sensor_acceleration_y\": \"y acceleration\",\n    \"HAMSTER_sensor_acceleration_z\": \"z acceleration\",\n    \"HAMSTER_sensor_light\": \"light\",\n    \"HAMSTER_sensor_temperature\": \"temperature\",\n    \"HAMSTER_sensor_signal_strength\": \"signal strength\",\n    \"HAMSTER_sensor_input_a\": \"input A\",\n    \"HAMSTER_sensor_input_b\": \"input B\",\n    \"HAMSTER_move_forward_once\": \"move forward once on board\",\n    \"HAMSTER_turn_once_1\": \"turn\",\n    \"HAMSTER_turn_once_2\": \"once on board\",\n    \"HAMSTER_turn_once_left\": \"left\",\n    \"HAMSTER_turn_right\": \"right\",\n    \"HAMSTER_move_forward\": \"move forward\",\n    \"HAMSTER_move_backward\": \"move backward\",\n    \"HAMSTER_turn_around_1\": \"turn\",\n    \"HAMSTER_turn_around_2\": \"\",\n    \"HAMSTER_move_forward_for_secs_1\": \"move forward for\",\n    \"HAMSTER_move_forward_for_secs_2\": \"secs\",\n    \"HAMSTER_move_backward_for_secs_1\": \"move backward\",\n    \"HAMSTER_move_backward_for_secs_2\": \"secs\",\n    \"HAMSTER_turn_for_secs_1\": \"turn\",\n    \"HAMSTER_turn_for_secs_2\": \"for\",\n    \"HAMSTER_turn_for_secs_3\": \"secs\",\n    \"HAMSTER_change_both_wheels_by_1\": \"change wheel by left:\",\n    \"HAMSTER_change_both_wheels_by_2\": \"right:\",\n    \"HAMSTER_change_both_wheels_by_3\": \"\",\n    \"HAMSTER_set_both_wheels_to_1\": \"set wheel to left:\",\n    \"HAMSTER_set_both_wheels_to_2\": \"right:\",\n    \"HAMSTER_set_both_wheels_to_3\": \"\",\n    \"HAMSTER_change_wheel_by_1\": \"change\",\n    \"HAMSTER_change_wheel_by_2\": \"wheel by\",\n    \"HAMSTER_change_wheel_by_3\": \"\",\n    \"HAMSTER_left_wheel\": \"left\",\n    \"HAMSTER_right_wheel\": \"right\",\n    \"HAMSTER_both_wheels\": \"both\",\n    \"HAMSTER_set_wheel_to_1\": \"set\",\n    \"HAMSTER_set_wheel_to_2\": \"wheel to\",\n    \"HAMSTER_set_wheel_to_3\": \"\",\n    \"HAMSTER_follow_line_using_1\": \"follow\",\n    \"HAMSTER_follow_line_using_2\": \"line using\",\n    \"HAMSTER_follow_line_using_3\": \"floor sensor\",\n    \"HAMSTER_left_floor_sensor\": \"left\",\n    \"HAMSTER_right_floor_sensor\": \"right\",\n    \"HAMSTER_both_floor_sensors\": \"both\",\n    \"HAMSTER_follow_line_until_1\": \"follow\",\n    \"HAMSTER_follow_line_until_2\": \"line until\",\n    \"HAMSTER_follow_line_until_3\": \"intersection\",\n    \"HAMSTER_left_intersection\": \"left\",\n    \"HAMSTER_right_intersection\": \"right\",\n    \"HAMSTER_front_intersection\": \"front\",\n    \"HAMSTER_rear_intersection\": \"rear\",\n    \"HAMSTER_set_following_speed_to_1\": \"set following speed to\",\n    \"HAMSTER_set_following_speed_to_2\": \"\",\n    \"HAMSTER_front\": \"front\",\n    \"HAMSTER_rear\": \"rear\",\n    \"HAMSTER_stop\": \"stop\",\n    \"HAMSTER_set_led_to_1\": \"set\",\n    \"HAMSTER_set_led_to_2\": \"led to\",\n    \"HAMSTER_set_led_to_3\": \"\",\n    \"HAMSTER_left_led\": \"left\",\n    \"HAMSTER_right_led\": \"right\",\n    \"HAMSTER_both_leds\": \"both\",\n    \"HAMSTER_clear_led_1\": \"clear\",\n    \"HAMSTER_clear_led_2\": \"led\",\n    \"HAMSTER_color_cyan\": \"sky blue\",\n    \"HAMSTER_color_magenta\": \"purple\",\n    \"HAMSTER_color_black\": \"black\",\n    \"HAMSTER_color_white\": \"white\",\n    \"HAMSTER_color_red\": \"red\",\n    \"HAMSTER_color_yellow\": \"yellow\",\n    \"HAMSTER_color_green\": \"green\",\n    \"HAMSTER_color_blue\": \"blue\",\n    \"HAMSTER_beep\": \"beep\",\n    \"HAMSTER_change_buzzer_by_1\": \"change buzzer by\",\n    \"HAMSTER_change_buzzer_by_2\": \"\",\n    \"HAMSTER_set_buzzer_to_1\": \"set buzzer to\",\n    \"HAMSTER_set_buzzer_to_2\": \"\",\n    \"HAMSTER_clear_buzzer\": \"clear buzzer\",\n    \"HAMSTER_play_note_for_1\": \"play note\",\n    \"HAMSTER_play_note_for_2\": \"\",\n    \"HAMSTER_play_note_for_3\": \"for\",\n    \"HAMSTER_play_note_for_4\": \"beats\",\n    \"HAMSTER_rest_for_1\": \"rest for\",\n    \"HAMSTER_rest_for_2\": \"beats\",\n    \"HAMSTER_change_tempo_by_1\": \"change tempo by\",\n    \"HAMSTER_change_tempo_by_2\": \"\",\n    \"HAMSTER_set_tempo_to_1\": \"set tempo to\",\n    \"HAMSTER_set_tempo_to_2\": \"bpm\",\n    \"HAMSTER_set_port_to_1\": \"set port\",\n    \"HAMSTER_set_port_to_2\": \"to\",\n    \"HAMSTER_set_port_to_3\": \"\",\n    \"HAMSTER_change_output_by_1\": \"change output\",\n    \"HAMSTER_change_output_by_2\": \"by\",\n    \"HAMSTER_change_output_by_3\": \"\",\n    \"HAMSTER_set_output_to_1\": \"set output\",\n    \"HAMSTER_set_output_to_2\": \"to\",\n    \"HAMSTER_set_output_to_3\": \"\",\n    \"HAMSTER_port_a\": \"A\",\n    \"HAMSTER_port_b\": \"B\",\n    \"HAMSTER_port_ab\": \"A and B\",\n    \"HAMSTER_analog_input\": \"analog input\",\n    \"HAMSTER_digital_input\": \"digital input\",\n    \"HAMSTER_servo_output\": \"servo output\",\n    \"HAMSTER_pwm_output\": \"pwm output\",\n    \"HAMSTER_digital_output\": \"digital output\",\n    \"ROBOID_acceleration_x\": \"x軸加速度\",\n    \"ROBOID_acceleration_y\": \"y軸加速度\",\n    \"ROBOID_acceleration_z\": \"z軸加速度\",\n    \"ROBOID_back\": \"後ろ\",\n    \"ROBOID_both\": \"両側\",\n    \"ROBOID_button\": \"ボタン\",\n    \"ROBOID_buzzer\": \"ブザー\",\n    \"ROBOID_clicked\": \"クリックしたか\",\n    \"ROBOID_color_any\": \"何の色\",\n    \"ROBOID_color_black\": \"黒\",\n    \"ROBOID_color_blue\": \"青\",\n    \"ROBOID_color_green\": \"緑\",\n    \"ROBOID_color_number\": \"色番号\",\n    \"ROBOID_color_orange\": \"オレンジ\",\n    \"ROBOID_color_pattern\": \"色パターン\",\n    \"ROBOID_color_purple\": \"赤紫色\",\n    \"ROBOID_color_red\": \"赤\",\n    \"ROBOID_color_sky_blue\": \"水色\",\n    \"ROBOID_color_violet\": \"紫\",\n    \"ROBOID_color_white\": \"白\",\n    \"ROBOID_color_yellow\": \"黄色\",\n    \"ROBOID_double_clicked\": \"ダブルクリックしたか\",\n    \"ROBOID_floor\": \"床センサー\",\n    \"ROBOID_head\": \"髪\",\n    \"ROBOID_head_color\": \"髪色\",\n    \"ROBOID_left\": \"左側\",\n    \"ROBOID_left_wheel\": \"左車輪\",\n    \"ROBOID_long_pressed\": \"長く~押したか\",\n    \"ROBOID_note\": \"音符\",\n    \"ROBOID_right\": \"右側\",\n    \"ROBOID_right_wheel\": \"右車輪\",\n    \"ROBOID_sound_beep\": \"ピー音\",\n    \"ROBOID_sound_birthday\": \"誕生日\",\n    \"ROBOID_sound_dibidibidip\": \"ディビディビディープ\",\n    \"ROBOID_sound_engine\": \"エンジン\",\n    \"ROBOID_sound_good_job\": \"すごいです\",\n    \"ROBOID_sound_march\": \"行進\",\n    \"ROBOID_sound_random_beep\": \"ランダムのピー音\",\n    \"ROBOID_sound_robot\": \"ロボット\",\n    \"ROBOID_sound_siren\": \"サイレン\",\n    \"ROBOID_tail\": \"尾\",\n    \"ROBOID_unit_cm\": \"cm\",\n    \"ROBOID_unit_deg\": \"度\",\n    \"ROBOID_unit_pulse\": \"パルス\",\n    \"ROBOID_unit_sec\": \"秒\",\n    \"ALBERT_hand_found\": \"hand found?\",\n    \"ALBERT_is_oid_1\": \"oid is\",\n    \"ALBERT_is_oid_2\": \"\",\n    \"ALBERT_is_oid_3\": \"?\",\n    \"ALBERT_front_oid\": \"front\",\n    \"ALBERT_back_oid\": \"back\",\n    \"ALBERT_sensor_left_proximity\": \"left proximity\",\n    \"ALBERT_sensor_right_proximity\": \"right proximity\",\n    \"ALBERT_sensor_acceleration_x\": \"x acceleration\",\n    \"ALBERT_sensor_acceleration_y\": \"y acceleration\",\n    \"ALBERT_sensor_acceleration_z\": \"z acceleration\",\n    \"ALBERT_sensor_light\": \"light\",\n    \"ALBERT_sensor_temperature\": \"temperature\",\n    \"ALBERT_sensor_battery\": \"battery\",\n    \"ALBERT_sensor_signal_strength\": \"signal strength\",\n    \"ALBERT_sensor_front_oid\": \"front oid\",\n    \"ALBERT_sensor_back_oid\": \"back oid\",\n    \"ALBERT_sensor_position_x\": \"x position\",\n    \"ALBERT_sensor_position_y\": \"y position\",\n    \"ALBERT_sensor_orientation\": \"orientation\",\n    \"ALBERT_move_forward\": \"move forward\",\n    \"ALBERT_move_backward\": \"move backward\",\n    \"ALBERT_turn_around_1\": \"turn\",\n    \"ALBERT_turn_around_2\": \"\",\n    \"ALBERT_move_forward_for_secs_1\": \"move forward for\",\n    \"ALBERT_move_forward_for_secs_2\": \"secs\",\n    \"ALBERT_move_backward_for_secs_1\": \"move backward for\",\n    \"ALBERT_move_backward_for_secs_2\": \"secs\",\n    \"ALBERT_turn_for_secs_1\": \"turn\",\n    \"ALBERT_turn_for_secs_2\": \"for\",\n    \"ALBERT_turn_for_secs_3\": \"secs\",\n    \"ALBERT_turn_left\": \"left\",\n    \"ALBERT_turn_right\": \"right\",\n    \"ALBERT_change_both_wheels_by_1\": \"change wheels by left:\",\n    \"ALBERT_change_both_wheels_by_2\": \"right:\",\n    \"ALBERT_change_both_wheels_by_3\": \"\",\n    \"ALBERT_left_wheel\": \"left\",\n    \"ALBERT_right_wheel\": \"right\",\n    \"ALBERT_both_wheels\": \"both\",\n    \"ALBERT_set_both_wheels_to_1\": \"set wheels to left:\",\n    \"ALBERT_set_both_wheels_to_2\": \"right:\",\n    \"ALBERT_set_both_wheels_to_3\": \"\",\n    \"ALBERT_change_wheel_by_1\": \"change\",\n    \"ALBERT_change_wheel_by_2\": \"wheel by\",\n    \"ALBERT_change_wheel_by_3\": \"\",\n    \"ALBERT_set_wheel_to_1\": \"set\",\n    \"ALBERT_set_wheel_to_2\": \"wheel to\",\n    \"ALBERT_set_wheel_to_3\": \"\",\n    \"ALBERT_stop\": \"stop\",\n    \"ALBERT_set_board_size_to_1\": \"set board size to width:\",\n    \"ALBERT_set_board_size_to_2\": \"height:\",\n    \"ALBERT_set_board_size_to_3\": \"\",\n    \"ALBERT_move_to_x_y_1\": \"move to x:\",\n    \"ALBERT_move_to_x_y_2\": \"y:\",\n    \"ALBERT_move_to_x_y_3\": \"on board\",\n    \"ALBERT_set_orientation_to_1\": \"set orientation to\",\n    \"ALBERT_set_orientation_to_2\": \"degrees on board\",\n    \"ALBERT_set_eye_to_1\": \"set\",\n    \"ALBERT_set_eye_to_2\": \"eye to\",\n    \"ALBERT_set_eye_to_3\": \"\",\n    \"ALBERT_left_eye\": \"left\",\n    \"ALBERT_right_eye\": \"right\",\n    \"ALBERT_both_eyes\": \"both\",\n    \"ALBERT_clear_eye_1\": \"clear\",\n    \"ALBERT_clear_eye_2\": \"eye\",\n    \"ALBERT_body_led_1\": \"turn\",\n    \"ALBERT_body_led_2\": \"body led\",\n    \"ALBERT_front_led_1\": \"turn\",\n    \"ALBERT_front_led_2\": \"front led\",\n    \"ALBERT_color_cyan\": \"cyan\",\n    \"ALBERT_color_magenta\": \"magenta\",\n    \"ALBERT_color_white\": \"white\",\n    \"ALBERT_color_red\": \"red\",\n    \"ALBERT_color_yellow\": \"yellow\",\n    \"ALBERT_color_green\": \"green\",\n    \"ALBERT_color_blue\": \"blue\",\n    \"ALBERT_note_c\": \"C\",\n    \"ALBERT_note_d\": \"D\",\n    \"ALBERT_note_e\": \"E\",\n    \"ALBERT_note_f\": \"F\",\n    \"ALBERT_note_g\": \"G\",\n    \"ALBERT_note_a\": \"A\",\n    \"ALBERT_note_b\": \"B\",\n    \"ALBERT_turn_body_led_1\": \"turn\",\n    \"ALBERT_turn_body_led_2\": \"body led\",\n    \"ALBERT_turn_front_led_1\": \"turn\",\n    \"ALBERT_turn_front_led_2\": \"front led\",\n    \"ALBERT_turn_on\": \"on\",\n    \"ALBERT_turn_off\": \"off\",\n    \"ALBERT_beep\": \"beep\",\n    \"ALBERT_change_buzzer_by_1\": \"change buzzer by\",\n    \"ALBERT_change_buzzer_by_2\": \"\",\n    \"ALBERT_set_buzzer_to_1\": \"set buzzer to\",\n    \"ALBERT_set_buzzer_to_2\": \"\",\n    \"ALBERT_clear_buzzer\": \"clear buzzer\",\n    \"ALBERT_play_note_for_1\": \"play note\",\n    \"ALBERT_play_note_for_2\": \"',\",\n    \"ALBERT_play_note_for_3\": \"for\",\n    \"ALBERT_play_note_for_4\": \"beats\",\n    \"ALBERT_rest_for_1\": \"rest for\",\n    \"ALBERT_rest_for_2\": \"beats\",\n    \"ALBERT_change_tempo_by_1\": \"change tempo by\",\n    \"ALBERT_change_tempo_by_2\": \"\",\n    \"ALBERT_set_tempo_to_1\": \"set tempo to\",\n    \"ALBERT_set_tempo_to_2\": \"bpm\",\n    \"VARIABLE_variable\": \"変数\",\n    \"wall\": \"壁\",\n    \"robotis_common_case_01\": \"を\",\n    \"robotis_common_set\": \"にする\",\n    \"robotis_common_value\": \"値\",\n    \"robotis_common_clockwhise\": \"時計方向\",\n    \"robotis_common_counter_clockwhise\": \"反時計方向\",\n    \"robotis_common_wheel_mode\": \"回転モード\",\n    \"robotis_common_joint_mode\": \"関節モード\",\n    \"robotis_common_red_color\": \"赤\",\n    \"robotis_common_green_color\": \"緑\",\n    \"robotis_common_blue_color\": \"青\",\n    \"robotis_common_on\": \"ON\",\n    \"robotis_common_off\": \"OFF\",\n    \"robotis_common_cm\": \"コントローラー\",\n    \"robotis_common_port_1\": \"ポート1\",\n    \"robotis_common_port_2\": \"ポート2\",\n    \"robotis_common_port_3\": \"ポート3\",\n    \"robotis_common_port_4\": \"ポート4\",\n    \"robotis_common_port_5\": \"ポート5\",\n    \"robotis_common_port_6\": \"ポート6\",\n    \"robotis_common_play_buzzer\": \"演奏\",\n    \"robotis_common_play_motion\": \"実行\",\n    \"robotis_common_motion\": \"モーション\",\n    \"robotis_common_index_number\": \"回\",\n    \"robotis_common_left\": \"左\",\n    \"robotis_common_right\": \"右\",\n    \"robotis_common_minute\": \"分\",\n    \"robotis_cm_custom\": \"直接入力アドレス\",\n    \"robotis_cm_spring_left\": \"左側接触センサー\",\n    \"robotis_cm_spring_right\": \"右側接触センサー\",\n    \"robotis_cm_led_left\": \"左側LED\",\n    \"robotis_cm_led_right\": \"右側LED\",\n    \"robotis_cm_led_both\": \"両側LED\",\n    \"robotis_cm_switch\": \"選択ボタンの状態\",\n    \"robotis_cm_user_button\": \"ユーザーボタンの状態\",\n    \"robotis_cm_sound_detected\": \"最終サウンド検知回数\",\n    \"robotis_cm_sound_detecting\": \"リアルタイムサウンド検知回数\",\n    \"robotis_cm_ir_left\": \"左側赤外線センサー\",\n    \"robotis_cm_ir_right\": \"右側赤外線センサー\",\n    \"robotis_cm_calibration_left\": \"左側赤外線センサー較正値\",\n    \"robotis_cm_calibration_right\": \"右側赤外線センサー較正値\",\n    \"robotis_cm_clear_sound_detected\": \"最終サウンド検知回数初期化\",\n    \"robotis_cm_buzzer_index\": \"音階値\",\n    \"robotis_cm_buzzer_melody\": \"メロディ\",\n    \"robotis_cm_led_1\": \"1番LED\",\n    \"robotis_cm_led_4\": \"4番LED\",\n    \"robotis_aux_servo_position\": \"サーボモーター位置\",\n    \"robotis_aux_ir\": \"赤外線センサー\",\n    \"robotis_aux_touch\": \"接触センサー\",\n    \"robotis_aux_brightness\": \"照度センサー(CDS)\",\n    \"robotis_aux_hydro_themo_humidity\": \"温湿度センサー(湿度)\",\n    \"robotis_aux_hydro_themo_temper\": \"温湿度センサー(温度)\",\n    \"robotis_aux_temperature\": \"温度センサー\",\n    \"robotis_aux_ultrasonic\": \"超音波センサー\",\n    \"robotis_aux_magnetic\": \"磁石センサー\",\n    \"robotis_aux_motion_detection\": \"動作検知センサー\",\n    \"robotis_aux_color\": \"カラーセンサー\",\n    \"robotis_aux_custom\": \"ユーザー装置\",\n    \"robotis_carCont_aux_motor_speed_1\": \"Speed of decelerating motor\",\n    \"robotis_carCont_aux_motor_speed_2\": \", the output value\",\n    \"robotis_carCont_calibration_1\": \"Value of the infrared sensor calibration \",\n    \"robotis_openCM70_aux_motor_speed_1\": \"Speed of decelerating motor\",\n    \"robotis_openCM70_aux_motor_speed_2\": \", Set as\",\n    \"robotis_openCM70_aux_servo_mode_1\": \"Servo motor mode\",\n    \"robotis_openCM70_aux_servo_speed_1\": \"Servo motor speed\",\n    \"robotis_openCM70_aux_servo_speed_2\": \", the output value\",\n    \"robotis_openCM70_aux_servo_position_1\": \"Position of servo motor\",\n    \"robotis_openCM70_aux_led_module_1\": \"LED module\",\n    \"robotis_openCM70_aux_custom_1\": \"User device\",\n    \"XBOT_digital\": \"Digital\",\n    \"XBOT_D2_digitalInput\": \"D2 Digital Input\",\n    \"XBOT_D3_digitalInput\": \"D3 Digital Input\",\n    \"XBOT_D11_digitalInput\": \"D11 Digital Input\",\n    \"XBOT_analog\": \"Analog\",\n    \"XBOT_CDS\": \"Light Sensor Value\",\n    \"XBOT_MIC\": \"Mic Sensor Value\",\n    \"XBOT_analog0\": \"Analog PIN0 Value\",\n    \"XBOT_analog1\": \"Analog PIN1 Value\",\n    \"XBOT_analog2\": \"Analog PIN2 Value\",\n    \"XBOT_analog3\": \"Analog PIN3 Value\",\n    \"XBOT_Value\": \"Ouput Value\",\n    \"XBOT_pin_OutputValue\": \"PIN, Ouput Value\",\n    \"XBOT_High\": \"HI\",\n    \"XBOT_Low\": \"LO\",\n    \"XBOT_Servo\": \"Servo Motor\",\n    \"XBOT_Head\": \"Head(D8)\",\n    \"XBOT_ArmR\": \"Right Arm(D9)\",\n    \"XBOT_ArmL\": \"Left Arm(D10)\",\n    \"XBOT_angle\": \", Angle\",\n    \"XBOT_DC\": \"Wheel(DC) Motor\",\n    \"XBOT_rightWheel\": \"Right\",\n    \"XBOT_leftWheel\": \"Left\",\n    \"XBOT_bothWheel\": \"Both\",\n    \"XBOT_speed\": \", Speed\",\n    \"XBOT_rightSpeed\": \"Wheel(DC) Motor Right(2) Speed:\",\n    \"XBOT_leftSpeed\": \"Left(1) Speed:\",\n    \"XBOT_RGBLED_R\": \"RGB LED Color from Red\",\n    \"XBOT_RGBLED_G\": \"Green\",\n    \"XBOT_RGBLED_B\": \"Blue\",\n    \"XBOT_RGBLED_color\": \"RGB LED Color from\",\n    \"XBOT_set\": \" \",\n    \"XBOT_c\": \"C\",\n    \"XBOT_d\": \"D\",\n    \"XBOT_e\": \"E\",\n    \"XBOT_f\": \"F\",\n    \"XBOT_g\": \"G\",\n    \"XBOT_a\": \"A\",\n    \"XBOT_b\": \"B\",\n    \"XBOT_melody_ms\": \"sec of Melody Playing\",\n    \"XBOT_Line\": \"th Line\",\n    \"XBOT_outputValue\": \"Text\",\n    \"roborobo_num_analog_value_1\": \"アナログ\",\n    \"roborobo_num_analog_value_2\": \"番センサー値\",\n    \"roborobo_get_digital_value_1\": \"デジタル\",\n    \"roborobo_num_pin_1\": \"デジタル\",\n    \"roborobo_num_pin_2\": \"番ピン\",\n    \"roborobo_on\": \"ON\",\n    \"roborobo_off\": \"OFF\",\n    \"roborobo_motor1\": \"モーター1\",\n    \"roborobo_motor2\": \"モーター2\",\n    \"roborobo_motor_CW\": \"正転\",\n    \"roborobo_motor_CCW\": \"逆回転\",\n    \"roborobo_motor_stop\": \"停止\",\n    \"roborobo_input_mode\": \"入力\",\n    \"roborobo_output_mode\": \"出力\",\n    \"roborobo_pwm_mode\": \"電流調節(pwm)\",\n    \"roborobo_servo_mode\": \"サーボモーター\",\n    \"roborobo_color\": \"カラーセンサー\",\n    \"roborobo_color_red\": \" 赤色\",\n    \"roborobo_color_green\": \" 緑 \",\n    \"roborobo_color_blue\": \" 青 \",\n    \"roborobo_color_yellow\": \" 黄色 \",\n    \"roborobo_color_detected\": \" 検知\",\n    \"roborobo_degree\": \" ˚\",\n    \"robotori_D2_Input\": \"Digital Pin 2 Input Value\",\n    \"robotori_D3_Input\": \"Digital Pin 3 Input Value\",\n    \"robotori_A0_Input\": \"Analog Pin 0 Input Value\",\n    \"robotori_A1_Input\": \"Analog Pin 1 Input Value\",\n    \"robotori_A2_Input\": \"Analog Pin 2 Input Value\",\n    \"robotori_A3_Input\": \"Analog Pin 3 Input Value\",\n    \"robotori_A4_Input\": \"Analog Pin 4 Input Value\",\n    \"robotori_A5_Input\": \"Analog Pin 5 Input Value\",\n    \"robotori_digital\": \"Digital\",\n    \"robotori_D10_Output\": \"Pin 10\",\n    \"robotori_D11_Output\": \"Pin 11\",\n    \"robotori_D12_Output\": \"Pin 12\",\n    \"robotori_D13_Output\": \"Pin 13\",\n    \"robotori_pin_OutputValue\": \"Output Value\",\n    \"robotori_On\": \"On\",\n    \"robotori_Off\": \"Off\",\n    \"robotori_analog\": \"Analog\",\n    \"robotori_analog5\": \"Pin 5 Output Value\",\n    \"robotori_analog6\": \"Pin 6 Output Value\",\n    \"robotori_analog9\": \"Pin 9 Output Value\",\n    \"robotori_Servo\": \"Servo Motor\",\n    \"robotori_DC\": \"DC Motor\",\n    \"robotori_DC_rightmotor\": \"Right\",\n    \"robotori_DC_leftmotor\": \"Left\",\n    \"robotori_DC_STOP\": \"Stop\",\n    \"robotori_DC_CW\": \"clockwise\",\n    \"robotori_DC_CCW\": \"anticlockwise\",\n    \"robotori_DC_select\": \"direction\",\n    \"CALC_rotation_value\": \"方向値\",\n    \"CALC_direction_value\": \"移動方向値\",\n    \"VARIABLE_is_included_in_list\": \"リストに含まれているか?\",\n    \"VARIABLE_is_included_in_list_1\": \" \",\n    \"VARIABLE_is_included_in_list_2\": \"に\",\n    \"VARIABLE_is_included_in_list_3\": \"が含まれているか?\",\n    \"SCENE_when_scene_start\": \"シーンが始まった時\",\n    \"SCENE_start_scene_1\": \" \",\n    \"SCENE_start_scene_2\": \"スタート\",\n    \"SCENE_start_neighbor_scene_1\": \" \",\n    \"SCENE_start_neighbor_scene_2\": \"シーンをスタート\",\n    \"SCENE_start_scene_pre\": \"前の\",\n    \"SCENE_start_scene_next\": \"次の\",\n    \"FUNCTION_explanation_1\": \"関数の名前\",\n    \"FUNCTION_character_variable\": \"文字／数字の値\",\n    \"FUNCTION_logical_variable\": \"判断値\",\n    \"FUNCTION_function\": \"関数\",\n    \"FUNCTION_define\": \"関数を定義する\",\n    \"CALC_calc_operation_sin\": \"サイン値\",\n    \"CALC_calc_operation_cos\": \"コサイン値\",\n    \"CALC_calc_operation_tan\": \"タンジェント値\",\n    \"CALC_calc_operation_floor\": \"小数点以下切り捨て値\",\n    \"CALC_calc_operation_ceil\": \"小数点以下切り上げ値\",\n    \"CALC_calc_operation_round\": \"四捨五入値\",\n    \"CALC_calc_operation_factorial\": \"階乗値\",\n    \"CALC_calc_operation_asin\": \"アークサイン値\",\n    \"CALC_calc_operation_acos\": \"アークコサイン値\",\n    \"CALC_calc_operation_atan\": \"アークタンジェント値\",\n    \"CALC_calc_operation_log\": \"ログ値\",\n    \"CALC_calc_operation_ln\": \"自然ログ値\",\n    \"CALC_calc_operation_natural\": \"整数部分\",\n    \"CALC_calc_operation_unnatural\": \"小数点部分\",\n    \"MOVING_locate_object_time_1\": \" \",\n    \"MOVING_locate_object_time_2\": \"秒間\",\n    \"MOVING_locate_object_time_3\": \"位置に移動する\",\n    \"wall_up\": \"上側の壁\",\n    \"wall_down\": \"下の壁\",\n    \"wall_right\": \"右の壁\",\n    \"wall_left\": \"左の壁\",\n    \"CALC_coordinate_x_value\": \"x座標値\",\n    \"CALC_coordinate_y_value\": \"y座標値\",\n    \"CALC_coordinate_rotation_value\": \"方向\",\n    \"CALC_coordinate_direction_value\": \"移動方向\",\n    \"CALC_picture_index\": \"模様番号\",\n    \"CALC_picture_name\": \"模様名\",\n    \"FLOW_repeat_while_true_1\": \" \",\n    \"FLOW_repeat_while_true_2\": \" 繰り返す\",\n    \"TUT_when_start\": \"プログラム実行をクリックした時\",\n    \"TUT_move_once\": \"前に1マス移動\",\n    \"TUT_rotate_left\": \"左側に回転\",\n    \"TUT_rotate_right\": \"右側に回転\",\n    \"TUT_jump_barrier\": \"障害物をジャンプする\",\n    \"TUT_repeat_tutorial_1\": \" \",\n    \"TUT_repeat_tutorial_2\": \"～回繰り返す\",\n    \"TUT_if_barrier_1\": \"もし前に\",\n    \"TUT_if_barrier_2\": \" があるなら\",\n    \"TUT_if_conical_1\": \"もし前に\",\n    \"TUT_if_conical_2\": \" があるなら\",\n    \"TUT_repeat_until\": \"パーツに到達するまで繰り返す\",\n    \"TUT_repeat_until_gold\": \"パーツに到達するまで繰り返す\",\n    \"TUT_declare_function\": \"関数宣言\",\n    \"TUT_call_function\": \"関数呼び出し\",\n    \"CALC_calc_operation_abs\": \"絶対値\",\n    \"CONTEXT_COPY_option\": \"コードコピー\",\n    \"Delete_Blocks\": \"コード削除\",\n    \"Duplication_option\": \"コードをコピー&ペースト\",\n    \"Paste_blocks\": \"ペースト\",\n    \"add_my_storage\": \"マイボックスに追加する\",\n    \"export_object\": \"Export Object\",\n    \"Clear_all_blocks\": \"すべてのコードを削除する\",\n    \"add_comment\": \"メモを追加する\",\n    \"copy_paste_comment\": \"メモをコピー＆貼り付けする\",\n    \"copy_comment\": \"メモをコピーする\",\n    \"delete_comment\": \"メモを削除する\",\n    \"fold_comment\": \"メモを折りたたむ\",\n    \"open_comment\": \"メモを展開する\",\n    \"separate_comment\": \"メモを分ける\",\n    \"hide_all_comment\": \"すべてのメモを非表示にする\",\n    \"show_all_comment\": \"すべてのメモを表示する\",\n    \"transparency\": \"透明度\",\n    \"BRUSH_change_brush_transparency_1\": \"筆の透明度を\",\n    \"BRUSH_change_brush_transparency_2\": \"%大きくする\",\n    \"BRUSH_set_brush_transparency_1\": \"筆の透明度を\",\n    \"BRUSH_set_brush_transparency_2\": \"%にする\",\n    \"CALC_char_at_1\": \" \",\n    \"CALC_char_at_2\": \"の\",\n    \"CALC_char_at_3\": \"番目の文字\",\n    \"CALC_length_of_string_1\": \" \",\n    \"CALC_length_of_string_2\": \"の文字数\",\n    \"CALC_substring_1\": \" \",\n    \"CALC_substring_2\": \"の\",\n    \"CALC_substring_3\": \"番目の文字から\",\n    \"length_of_string\": \"番目の文字から\",\n    \"CALC_substring_4\": \"番目の文字までの文字\",\n    \"CALC_replace_string_1\": \" \",\n    \"CALC_replace_string_2\": \"の\",\n    \"CALC_replace_string_3\": \"を\",\n    \"CALC_replace_string_4\": \"に変える\",\n    \"CALC_change_string_case_1\": \" \",\n    \"CALC_change_string_case_2\": \"の\",\n    \"CALC_change_string_case_3\": \" \",\n    \"CALC_change_string_case_sub_1\": \"大文字\",\n    \"CALC_change_string_case_sub_2\": \"小文字\",\n    \"CALC_index_of_string_1\": \" \",\n    \"CALC_index_of_string_2\": \"から\",\n    \"CALC_index_of_string_3\": \"ではじまる位置\",\n    \"MOVING_add_direction_by_angle_time_explain_1\": \" \",\n    \"MOVING_direction_relative_duration_1\": \" \",\n    \"MOVING_direction_relative_duration_2\": \"秒間移動方向\",\n    \"MOVING_direction_relative_duration_3\": \"分回転する\",\n    \"CALC_get_sound_volume\": \"音の値\",\n    \"SOUND_sound_from_to_1\": \"サウンド\",\n    \"SOUND_sound_from_to_2\": \" \",\n    \"SOUND_sound_from_to_3\": \"秒から\",\n    \"SOUND_sound_from_to_4\": \"秒まで再生する\",\n    \"SOUND_sound_from_to_and_wait_1\": \"サウンド\",\n    \"SOUND_sound_from_to_and_wait_2\": \" \",\n    \"SOUND_sound_from_to_and_wait_3\": \"秒から\",\n    \"SOUND_sound_from_to_and_wait_4\": \"秒まで再生して待つ\",\n    \"CALC_quotient_and_mod_1\": \" \",\n    \"CALC_quotient_and_mod_2\": \"/\",\n    \"CALC_quotient_and_mod_3\": \"の\",\n    \"CALC_quotient_and_mod_4\": \" \",\n    \"CALC_quotient_and_mod_sub_1\": \"商\",\n    \"CALC_quotient_and_mod_sub_2\": \"あまり\",\n    \"self\": \"自分\",\n    \"CALC_coordinate_size_value\": \"サイズ\",\n    \"CALC_choose_project_timer_action_1\": \"ストップウォッチ\",\n    \"CALC_choose_project_timer_action_2\": \" \",\n    \"CALC_choose_project_timer_action_sub_1\": \"スタート\",\n    \"CALC_choose_project_timer_action_sub_2\": \"停止する\",\n    \"CALC_choose_project_timer_action_sub_3\": \"初期化する\",\n    \"LOOKS_change_object_index_1\": \" \",\n    \"LOOKS_change_object_index_2\": \"送る\",\n    \"LOOKS_change_object_index_sub_1\": \"一番前に\",\n    \"LOOKS_change_object_index_sub_2\": \"前に\",\n    \"LOOKS_change_object_index_sub_3\": \"後ろに\",\n    \"LOOKS_change_object_index_sub_4\": \"一番後ろに\",\n    \"FLOW_repeat_while_true_until\": \"になるまで\",\n    \"FLOW_repeat_while_true_while\": \"の間\",\n    \"copy_block\": \"ブロックコピー\",\n    \"delete_block\": \"ブロック削除\",\n    \"tidy_up_block\": \"コードを整理する\",\n    \"block_hi\": \"やあ!\",\n    \"entry_bot_name\": \"Entrybot\",\n    \"hi_entry\": \"やあ、エントリー!\",\n    \"hi_entry_en\": \"Hello Entry!\",\n    \"bark_dog\": \"犬が吠えるサウンド\",\n    \"walking_entryBot\": \"Walking Entrybot\",\n    \"doggi_bark\": \"Doggi's Bark\",\n    \"entry\": \"エントリー\",\n    \"hello\": \"やあ\",\n    \"nice\": \"嬉しいな\",\n    \"silent\": \"無音\",\n    \"do_name\": \"ド\",\n    \"do_sharp_name\": \"ド#(レ♭)\",\n    \"re_name\": \"レ\",\n    \"re_sharp_name\": \"レ#(ミ♭)\",\n    \"mi_name\": \"ミ\",\n    \"fa_name\": \"ファ\",\n    \"fa_sharp_name\": \"ファ#(ソ♭)\",\n    \"sol_name\": \"ソ\",\n    \"sol_sharp_name\": \"ソ#(ラ♭)\",\n    \"la_name\": \"ラ\",\n    \"la_sharp_name\": \"ラ#(シ♭)\",\n    \"DUMMY\": \"ダミー\",\n    \"coconut_stop_motor\": \"stop motor\",\n    \"coconut_move_motor\": \"move motor\",\n    \"coconut_turn_motor\": \"turn\",\n    \"coconut_move_outmotor\": \"external motor\",\n    \"coconut_turn_left\": \"left\",\n    \"coconut_turn_right\": \"right\",\n    \"coconut_move_forward\": \"forward\",\n    \"coconut_move_backward\": \"backward\",\n    \"coconut_note_c\": \"note_c\",\n    \"coconut_note_d\": \"note_d\",\n    \"coconut_note_e\": \"note_e\",\n    \"coconut_note_f\": \"note_f\",\n    \"coconut_note_g\": \"note_g\",\n    \"coconut_note_a\": \"note_a\",\n    \"coconut_note_b\": \"note_b\",\n    \"coconut_move_speed_1\": \"0\",\n    \"coconut_move_speed_2\": \"50\",\n    \"coconut_move_speed_3\": \"100\",\n    \"coconut_move_speed_4\": \"150\",\n    \"coconut_move_speed_5\": \"255\",\n    \"coconut_play_buzzer_hn\": \"Half\",\n    \"coconut_play_buzzer_qn\": \"Quater\",\n    \"coconut_play_buzzer_en\": \"Eighth\",\n    \"coconut_play_buzzer_sn\": \"Sixteenth\",\n    \"coconut_play_buzzer_tn\": \"Thirty-second\",\n    \"coconut_play_buzzer_wn\": \"Whole\",\n    \"coconut_play_buzzer_dhn\": \"Dotted half\",\n    \"coconut_play_buzzer_dqn\": \"Dotted quarter\",\n    \"coconut_play_buzzer_den\": \"Dotted eighth\",\n    \"coconut_play_buzzer_dsn\": \"Dotted sixteenth\",\n    \"coconut_play_buzzer_dtn\": \"Dotted thirty-second\",\n    \"coconut_rest_buzzer_hr\": \"Half_rest\",\n    \"coconut_rest_buzzer_qr\": \"Quater_rest\",\n    \"coconut_rest_buzzer_er\": \"Eighth_rest\",\n    \"coconut_rest_buzzer_sr\": \"Sixteenth_rest\",\n    \"coconut_rest_buzzer_tr\": \"Thirty-second rest\",\n    \"coconut_rest_buzzer_wr\": \"Whole_rest\",\n    \"coconut_play_midi_1\": \"Twinkle Twinkle little star\",\n    \"coconut_play_midi_2\": \"Three bears\",\n    \"coconut_play_midi_3\": \"Mozart's Lullaby\",\n    \"coconut_play_midi_4\": \"Do-Re-Mi\",\n    \"coconut_play_midi_5\": \"Butterfly\",\n    \"coconut_floor_sensing_on\": \"detect\",\n    \"coconut_floor_sensing_off\": \"not detect\",\n    \"coconut_dotmatrix_set_on\": \"on\",\n    \"coconut_dotmatrix_set_off\": \"off\",\n    \"coconut_dotmatrix_row_0\": \"all\",\n    \"coconut_dotmatrix_row_1\": \"1\",\n    \"coconut_dotmatrix_row_2\": \"2\",\n    \"coconut_dotmatrix_row_3\": \"3\",\n    \"coconut_dotmatrix_row_4\": \"4\",\n    \"coconut_dotmatrix_row_5\": \"5\",\n    \"coconut_dotmatrix_row_6\": \"6\",\n    \"coconut_dotmatrix_row_7\": \"7\",\n    \"coconut_dotmatrix_row_8\": \"8\",\n    \"coconut_dotmatrix_col_0\": \"all\",\n    \"coconut_dotmatrix_col_1\": \"1\",\n    \"coconut_dotmatrix_col_2\": \"2\",\n    \"coconut_dotmatrix_col_3\": \"3\",\n    \"coconut_dotmatrix_col_4\": \"4\",\n    \"coconut_dotmatrix_col_5\": \"5\",\n    \"coconut_dotmatrix_col_6\": \"6\",\n    \"coconut_dotmatrix_col_7\": \"7\",\n    \"coconut_dotmatrix_col_8\": \"8\",\n    \"coconut_sensor_left_proximity\": \"left IR distance\",\n    \"coconut_sensor_right_proximity\": \"right IR distance\",\n    \"coconut_sensor_both_proximity\": \"both IR distance\",\n    \"coconut_sensor_left_floor\": \"left line tracer\",\n    \"coconut_sensor_right_floor\": \"right line tracer\",\n    \"coconut_sensor_both_floor\": \"both line tracer\",\n    \"coconut_sensor_acceleration_x\": \"X-Axis Accelerometer\",\n    \"coconut_sensor_acceleration_y\": \"Y-Axis Accelerometer\",\n    \"coconut_sensor_acceleration_z\": \"Z-Axis Accelerometer\",\n    \"coconut_sensor_light\": \"light sensor\",\n    \"coconut_sensor_temperature\": \"temperature\",\n    \"coconut_left_led\": \"left led\",\n    \"coconut_right_led\": \"right led\",\n    \"coconut_both_leds\": \"both led\",\n    \"coconut_color_cyan\": \"Cyan\",\n    \"coconut_color_magenta\": \"Magenta\",\n    \"coconut_color_black\": \"Black\",\n    \"coconut_color_white\": \"White\",\n    \"coconut_color_red\": \"Red\",\n    \"coconut_color_yellow\": \"Yellow\",\n    \"coconut_color_green\": \"Green\",\n    \"coconut_color_blue\": \"Blue\",\n    \"coconut_beep\": \"buzzer on\",\n    \"coconut_clear_buzzer\": \"buzzer off\",\n    \"coconut_x_axis\": \"X-Axis\",\n    \"coconut_y_axis\": \"Y-Axis\",\n    \"coconut_z_axis\": \"Z-Axis\",\n    \"modi_enviroment_bule\": \"Blue\",\n    \"modi_enviroment_green\": \"Green\",\n    \"modi_enviroment_humidity\": \"Humidity\",\n    \"modi_enviroment_illuminance\": \"Illuminance\",\n    \"modi_enviroment_red\": \"Red\",\n    \"modi_enviroment_temperature\": \"Temparature\",\n    \"modi_gyroscope_xAcceleratior\": \"X-axis acceleration\",\n    \"modi_gyroscope_yAcceleratior\": \"Y-axis acceleration\",\n    \"modi_gyroscope_zAcceleratior\": \"Z-axis acceleration\",\n    \"modi_motor_angle\": \"Angle\",\n    \"modi_motor_speed\": \"Speed\",\n    \"modi_motor_torque\": \"Torque\",\n    \"modi_speaker_F_DO_5\": \"DO 5\",\n    \"modi_speaker_F_DO_6\": \"DO 6\",\n    \"modi_speaker_F_DO_7\": \"DO 7\",\n    \"modi_speaker_F_DO_S_5\": \"DO #5\",\n    \"modi_speaker_F_DO_S_6\": \"DO #6\",\n    \"modi_speaker_F_DO_S_7\": \"DO #7\",\n    \"modi_speaker_F_MI_5\": \"MI 5\",\n    \"modi_speaker_F_MI_6\": \"MI 6\",\n    \"modi_speaker_F_MI_7\": \"MI 7\",\n    \"modi_speaker_F_PA_5\": \"FA 5\",\n    \"modi_speaker_F_PA_6\": \"FA 6\",\n    \"modi_speaker_F_PA_7\": \"FA 7\",\n    \"modi_speaker_F_PA_S_5\": \"FA #5\",\n    \"modi_speaker_F_PA_S_6\": \"FA #6\",\n    \"modi_speaker_F_PA_S_7\": \"FA #7\",\n    \"modi_speaker_F_RA_5\": \"LA 5\",\n    \"modi_speaker_F_RA_6\": \"LA 6\",\n    \"modi_speaker_F_RA_7\": \"LA 7\",\n    \"modi_speaker_F_RA_S_5\": \"LA #5\",\n    \"modi_speaker_F_RA_S_6\": \"LA #6\",\n    \"modi_speaker_F_RA_S_7\": \"LA #7\",\n    \"modi_speaker_F_RE_5\": \"RE 5\",\n    \"modi_speaker_F_RE_6\": \"RE 6\",\n    \"modi_speaker_F_RE_7\": \"RE 7\",\n    \"modi_speaker_F_RE_S_5\": \"LA #5\",\n    \"modi_speaker_F_RE_S_6\": \"RE #6\",\n    \"modi_speaker_F_RE_S_7\": \"RE #7\",\n    \"modi_speaker_F_SOL_5\": \"SOL 5\",\n    \"modi_speaker_F_SOL_6\": \"SOL 6\",\n    \"modi_speaker_F_SOL_7\": \"SOL 7\",\n    \"modi_speaker_F_SOL_S_5\": \"SOL #5\",\n    \"modi_speaker_F_SOL_S_6\": \"SOL #6\",\n    \"modi_speaker_F_SOL_S_7\": \"SOL #7\",\n    \"modi_speaker_F_SO_5\": \"TI 5\",\n    \"modi_speaker_F_SO_6\": \"TI 6\",\n    \"modi_speaker_F_SO_7\": \"TI 7\",\n    \"si_name\": \"シ\",\n    \"ev3_ccw\": \"CCW\",\n    \"ev3_cw\": \"CW\",\n    \"rokoboard_sensor_name_0\": \"Sound\",\n    \"rokoboard_sensor_name_1\": \"Light\",\n    \"rokoboard_sensor_name_2\": \"Slider\",\n    \"rokoboard_sensor_name_3\": \"resistance-A\",\n    \"rokoboard_sensor_name_4\": \"resistance-B\",\n    \"rokoboard_sensor_name_5\": \"resistance-C\",\n    \"rokoboard_sensor_name_6\": \"resistance-D\",\n    \"rokoboard_string_1\": \"Button Pressed\",\n    \"HW_MOTOR\": \"モーター\",\n    \"HW_SENSOR\": \"センサー\",\n    \"HW_LED\": \"発光ダイオード\",\n    \"HW_MELODY\": \"メロディ\",\n    \"HW_ROBOT\": \"ロボット\",\n    \"ALTINO_ACCX\": \"acceleration X axis\",\n    \"ALTINO_ACCY\": \"acceleration Y axis\",\n    \"ALTINO_ACCZ\": \"acceleration Z axis\",\n    \"ALTINO_BAT\": \"battery check\",\n    \"ALTINO_CDS\": \"light\",\n    \"ALTINO_GYROX\": \"gyro X axis\",\n    \"ALTINO_GYROY\": \"gyro Y axis\",\n    \"ALTINO_GYROZ\": \"gyro Z axis\",\n    \"ALTINO_IR1\": \"1 distance\",\n    \"ALTINO_IR2\": \"2 distance\",\n    \"ALTINO_IR3\": \"3 distance\",\n    \"ALTINO_IR4\": \"4 distance\",\n    \"ALTINO_IR5\": \"5 distance\",\n    \"ALTINO_IR6\": \"6 distance\",\n    \"ALTINO_Led_Brake_Light\": \"brake\",\n    \"ALTINO_Led_Forward_Light\": \"forward\",\n    \"ALTINO_Led_Reverse_Light\": \"backward\",\n    \"ALTINO_Led_Turn_Left_Light\": \"left direction\",\n    \"ALTINO_Led_Turn_Right_Light\": \"right direction\",\n    \"ALTINO_Line\": \"line\",\n    \"ALTINO_MAGX\": \"geomagnetic X axis\",\n    \"ALTINO_MAGY\": \"geomagnetic Y axis\",\n    \"ALTINO_MAGZ\": \"geomagnetic Z axis\",\n    \"ALTINO_REMOTE\": \"remote control\",\n    \"ALTINO_STTOR\": \"steering torque\",\n    \"ALTINO_STVAR\": \"steering potentiometer\",\n    \"ALTINO_Steering_Angle_Center\": \"center\",\n    \"ALTINO_Steering_Angle_Left10\": \"left10\",\n    \"ALTINO_Steering_Angle_Left15\": \"left15\",\n    \"ALTINO_Steering_Angle_Left20\": \"left20\",\n    \"ALTINO_Steering_Angle_Left5\": \"left5\",\n    \"ALTINO_Steering_Angle_Right10\": \"right10\",\n    \"ALTINO_Steering_Angle_Right15\": \"right15\",\n    \"ALTINO_Steering_Angle_Right20\": \"right20\",\n    \"ALTINO_Steering_Angle_Right5\": \"right5\",\n    \"ALTINO_TEM\": \"temperature\",\n    \"ALTINO_TOR1\": \"right torque\",\n    \"ALTINO_TOR2\": \"left torque\",\n    \"ALTINO_Value\": \"output value\",\n    \"ALTINO_a\": \"la\",\n    \"ALTINO_a2\": \"la#\",\n    \"ALTINO_b\": \"si\",\n    \"ALTINO_c\": \"do\",\n    \"ALTINO_c2\": \"do#\",\n    \"ALTINO_d\": \"re\",\n    \"ALTINO_d2\": \"re#\",\n    \"ALTINO_dot_display_1\": \"one char\",\n    \"ALTINO_dot_display_2\": \"display\",\n    \"ALTINO_e\": \"mi\",\n    \"ALTINO_f\": \"fa\",\n    \"ALTINO_f2\": \"fa#\",\n    \"ALTINO_g\": \"sol\",\n    \"ALTINO_g2\": \"sol#\",\n    \"ALTINO_h\": \"off\",\n    \"ALTINO_h2\": \"on\",\n    \"ALTINO_leftWheel\": \"left\",\n    \"ALTINO_melody_ms\": \"play\",\n    \"ALTINO_outputValue\": \"output\",\n    \"ALTINO_rightWheel\": \"right\",\n    \"ALTINO_set\": \" display\",\n    \"ardublock_motor_forward\": \"Forward\",\n    \"ardublock_motor_backward\": \"Backward\",\n    \"jdkit_clockwise\": \"시계방향\",\n    \"jdkit_counterclockwise\": \"반시계방향\",\n    \"jdkit_gyro_frontrear\": \"앞뒤\",\n    \"jdkit_gyro_leftright\": \"좌우\",\n    \"jdkit_joystick_leftleftright\": \"왼쪽 좌우\",\n    \"jdkit_joystick_lefttopbottom\": \"왼쪽 상하\",\n    \"jdkit_joystick_rightleftright\": \"오른쪽 좌우\",\n    \"jdkit_joystick_righttopbottom\": \"오른쪽 상하\",\n    \"jdkit_led\": \"LED\",\n    \"jdkit_led_color_green\": \"초록색\",\n    \"jdkit_led_color_orange\": \"오랜지색\",\n    \"jdkit_led_turnoff\": \"끄기\",\n    \"jdkit_led_turnon\": \"켜기\",\n    \"jdkit_motor_leftbottom\": \"왼쪽아래\",\n    \"jdkit_motor_lefttop\": \"왼쪽위\",\n    \"jdkit_motor_rightbottom\": \"오른쪽아래\",\n    \"jdkit_motor_righttop\": \"오른쪽위\",\n    \"jdkit_tune_do\": \"도\",\n    \"jdkit_tune_fa\": \"파\",\n    \"jdkit_tune_la\": \"라\",\n    \"jdkit_tune_mi\": \"미\",\n    \"jdkit_tune_re\": \"레\",\n    \"jdkit_tune_si\": \"시\",\n    \"jdkit_tune_sol\": \"솔\",\n    \"FUNBOARD_bt_down\": \"yellow(B)\",\n    \"FUNBOARD_bt_left\": \"green(C)\",\n    \"FUNBOARD_bt_right\": \"blue(D)\",\n    \"FUNBOARD_bt_up\": \"red(A)\",\n    \"FUNBOARD_column_tag\": \"column\",\n    \"FUNBOARD_do_off\": \"off\",\n    \"FUNBOARD_do_on\": \"on\",\n    \"FUNBOARD_led_color_all\": \"모두\",\n    \"FUNBOARD_led_color_blue\": \"blue\",\n    \"FUNBOARD_led_color_green\": \"green\",\n    \"FUNBOARD_led_color_red\": \"red\",\n    \"FUNBOARD_led_color_str\": \"color  \",\n    \"FUNBOARD_led_color_yellow\": \"yellow\",\n    \"FUNBOARD_led_off_str\": \"Turn off the LED\",\n    \"FUNBOARD_led_on_str\": \"Turn on the LED\",\n    \"FUNBOARD_row_tag\": \"row\",\n    \"FUNBOARD_scroll_down\": \"downward\",\n    \"FUNBOARD_scroll_left\": \"leftward\",\n    \"FUNBOARD_scroll_no\": \"no\",\n    \"FUNBOARD_scroll_right\": \"rightward\",\n    \"FUNBOARD_scroll_up\": \"upwards\",\n    \"FUNBOARD_sensor_cds\": \"light sensor\",\n    \"FUNBOARD_sensor_mic\": \"microphone sensor\",\n    \"FUNBOARD_sensor_slide\": \"potentiometer\",\n    \"FUNBOARD_sensor_state_1\": \"low\",\n    \"FUNBOARD_sensor_state_2\": \"high\",\n    \"FUNBOARD_touchbt_down\": \"yellow(B)\",\n    \"FUNBOARD_touchbt_enter\": \"   F\",\n    \"FUNBOARD_touchbt_escape\": \"   G\",\n    \"FUNBOARD_touchbt_left\": \"green(C)\",\n    \"FUNBOARD_touchbt_right\": \"blue(D)\",\n    \"FUNBOARD_touchbt_space\": \"   E\",\n    \"FUNBOARD_touchbt_up\": \"red(A)\",\n    \"funboard_dotmatrix_set_off\": \"off\",\n    \"funboard_dotmatrix_set_on\": \"on\",\n    \"AI_UTILIZE\": \"AI\",\n    \"video_show_video\": \"表示\",\n    \"video_hide_video\": \"非表示\",\n    \"video_brightness\": \"明度\",\n    \"video_transparency\": \"透明度\",\n    \"video_left_right\": \"右反\",\n    \"video_top_bottom\": \"上下\",\n    \"video_human\": \"体\",\n    \"video_face\": \"顔\",\n    \"video_object\": \"物\",\n    \"video_start\": \"始める\",\n    \"video_end\": \"止める\",\n    \"video_gender\": \"性別\",\n    \"video_age\": \"年齢\",\n    \"video_emotion\": \"感情\",\n    \"video_motion_onself\": \"自分\",\n    \"video_motion_onscreen\": \"画面\",\n    \"video_motion_scale\": \"モーション\",\n    \"video_motion_direction_horizontal\": \"x 方向\",\n    \"video_motion_direction_vertical\": \"y 方向\",\n    \"table_row\": \"行\",\n    \"table_col\": \"列\",\n    \"table_sum\": \"sum\",\n    \"table_max\": \"max\",\n    \"table_min\": \"min\",\n    \"table_avg\": \"average\",\n    \"table_stdev\": \"standard deviation\",\n    \"arduino_lite_reconnect\": \"再接続する\",\n    \"arduino_lite_download_firmware\": \"ファームウェア\",\n    \"arduino_lite_download_driver\": \"ドライバー\",\n    \"arduino_lite_connect\": \"ブラウザーで接続\",\n    \"arduino_lite_disconnect\": \"キャンセル\",\n    \"arduino_lite_guide\": \"• connection guide\",\n};\nLang.video_body_coord_params = {\n    \"left_eye\": \"左眼\",\n    \"right_eye\": \"右眼\",\n    \"nose\": \"鼻\",\n    \"left_mouth\": \"左口\",\n    \"right_mouth\": \"右口\",\n    \"upper_lip\": \"上口\",\n    \"lower_lip\": \"下口\",\n    \"face\": \"顔\",\n    \"neck\": \"首\",\n    \"left_ear\": \"左耳\",\n    \"right_ear\": \"右耳\",\n    \"left_shoulder\": \"左肩\",\n    \"left_elbow\": \"左肘\",\n    \"left_wrist\": \"左手首\",\n    \"left_hip\": \"左尻\",\n    \"left_knee\": \"左膝\",\n    \"left_ankle\": \"左足首\",\n    \"right_shoulder\": \"右肩\",\n    \"right_elbow\": \"右肘\",\n    \"right_wrist\": \"右手首\",\n    \"right_hip\": \"右尻\",\n    \"right_knee\": \"右膝\",\n    \"right_ankle\": \"右足首\"\n};\nLang.video_emotion_params = {\n    \"angry\": \"怒り\",\n    \"disgusted\": \"嫌悪\",\n    \"fearful\": \"恐怖\",\n    \"happy\": \"幸せ\",\n    \"neutral\": \"無表情\",\n    \"sad\": \"悲しみ\",\n    \"surprised\": \"驚き\"\n};\nLang.video_object_params = {\n    \"person\": \"人\",\n    \"bicycle\": \"自転車\",\n    \"car\": \"車\",\n    \"motorcycle\": \"オートバイ\",\n    \"airplane\": \"飛行機\",\n    \"bus\": \"バス\",\n    \"train\": \"列車\",\n    \"truck\": \"トラック\",\n    \"boat\": \"ボート\",\n    \"traffic light\": \"信号機\",\n    \"fire hydrant\": \"消火栓\",\n    \"stop sign\": \"一時停止標識\",\n    \"parking meter\": \"パーキングメーター\",\n    \"bench\": \"ベンチ\",\n    \"bird\": \"鳥\",\n    \"cat\": \"ネコ\",\n    \"dog\": \"犬\",\n    \"horse\": \"うま\",\n    \"sheep\": \"羊\",\n    \"cow\": \"牛\",\n    \"elephant\": \"象\",\n    \"bear\": \"くま\",\n    \"zebra\": \"シマウマ\",\n    \"giraffe\": \"キリン\",\n    \"backpack\": \"バックパック\",\n    \"umbrella\": \"傘\",\n    \"handbag\": \"ハンドバッグ\",\n    \"tie\": \"ネクタイ\",\n    \"suitcase\": \"スーツケース\",\n    \"frisbee\": \"フリスビー\",\n    \"skis\": \"スキー板\",\n    \"snowboard\": \"snowboard\",\n    \"sports ball\": \"スポーツボール\",\n    \"kite\": \"カイト\",\n    \"baseball bat\": \"野球用バット\",\n    \"baseball glove\": \"野球グローブ\",\n    \"skateboard\": \"スケートボード\",\n    \"surfboard\": \"サーフボード\",\n    \"tennis racket\": \"テニスラケット\",\n    \"bottle\": \"ボトル\",\n    \"wine glass\": \"ワイングラス\",\n    \"cup\": \"カップ\",\n    \"fork\": \"フォーク\",\n    \"knife\": \"ナイフ\",\n    \"spoon\": \"スプーン\",\n    \"bowl\": \"丼鉢\",\n    \"banana\": \"バナナ\",\n    \"apple\": \"林檎\",\n    \"sandwich\": \"サンドイッチ\",\n    \"orange\": \"オレンジ\",\n    \"broccoli\": \"ブロッコリ\",\n    \"carrot\": \"にんじん\",\n    \"hot dog\": \"ホットドッグ\",\n    \"pizza\": \"ピザ\",\n    \"donut\": \"ドーナツ\",\n    \"cake\": \"ケーキ\",\n    \"chair\": \"椅子\",\n    \"couch\": \"ソファー\",\n    \"potted plant\": \"鉢植え\",\n    \"bed\": \"ベッド\",\n    \"dining table\": \"食卓\",\n    \"toilet\": \"トイレ\",\n    \"tv\": \"テレビ\",\n    \"laptop\": \"ラップトップ\",\n    \"mouse\": \"マウス\",\n    \"remote\": \"リモコン\",\n    \"keyboard\": \"キーボード\",\n    \"cell phone\": \"携帯電話\",\n    \"microwave\": \"電子レンジ\",\n    \"oven\": \"オーブン\",\n    \"toaster\": \"トースター\",\n    \"sink\": \"シンク\",\n    \"refrigerator\": \"冷蔵庫\",\n    \"book\": \"本\",\n    \"clock\": \"時計\",\n    \"vase\": \"花瓶\",\n    \"scissors\": \"はさみ\",\n    \"teddy bear\": \"テディベア\",\n    \"hair drier\": \"ヘアドライヤー\",\n    \"toothbrush\": \"歯ブラシ\"\n};\nLang.Buttons = {\n    \"share_policy\": \"Share Guide\",\n    \"write_policy\": \"Write Guide\",\n    \"lesson_list\": \"講義リスト\",\n    \"complete_study\": \"学習を完了する\",\n    \"show_me\": \"プレビュー\",\n    \"do_this_for_me\": \"代わりに行う\",\n    \"previous\": \"前\",\n    \"get_started\": \"スタート\",\n    \"next_lesson\": \"次の内容を学習する\",\n    \"course_submit\": \"提出する\",\n    \"course_done\": \"確認\",\n    \"mission\": \"ミッションを確認する\",\n    \"basic_guide\": \"基本的な使用方法\",\n    \"apply\": \"適用する\",\n    \"add\": \"追加する\",\n    \"cancel\": \"取消\",\n    \"save\": \"確認\",\n    \"start\": \"はじめ\",\n    \"confirm\": \"確認\",\n    \"delete\": \"削除\",\n    \"create\": \"クラス作成\",\n    \"done\": \"完了\",\n    \"accept\": \"応答\",\n    \"refuse\": \"拒否\",\n    \"yes\": \"はい\",\n    \"button_no\": \"いいえ\",\n    \"quiz_retry\": \"もう一度解く\",\n    \"discuss_upload\": \"読み込む\",\n    \"maze_popup_guide\": \"利用案内\",\n    \"maze_popup_mapHint\": \"ヒントを見る\",\n    \"maze_hint_btn_guide\": \"利用案内\",\n    \"maze_hint_btn_block\": \"ブロックヘルプ\",\n    \"maze_hint_btn_map\": \"ヒントを見る\",\n    \"maze_hint_btn_goal\": \"目標\",\n    \"list_save\": \"保存する\",\n    \"duplication\": \"コピーする\",\n    \"export_to_excel\": \"ダウンロード\",\n    \"single_line\": \"一行で書く\",\n    \"multi_line\": \"改行して書く\",\n    \"lecture_finish_popup_reset_lecture\": \"처음부터 다시하기\",\n    \"lecture_finish_popup_show_output\": \"실습한 코드보기\",\n    \"lecture_view_hints\": \"View hints\",\n    \"default_hint_title\": \"どのように作るか\",\n    \"show_only_vector\": \"Only Vector\"\n};\nLang.Menus = {\n    \"nothing_to_import\": \"読み込みできる項目がありません。\",\n    \"nothing_to_export\": \"書き出しできる項目がありません。\",\n    \"content_copied\": \"内容がコピーされました。\",\n    \"list_import_title\": \"読み込む\",\n    \"list_import_placeholder\": \"例）\\n内容1\\n内容2\\n内容3\\n内容4\\n内容5\\n内容6\\n内容7\\n内容8\",\n    \"verifying_email\": \"認証メール送信\",\n    \"list_import_notice_1\": \"複数の項目の内容を一度に登録することができます。\",\n    \"list_import_notice_2\": \"既存の内容は、新しく保存する内容に上書きされます。\",\n    \"list_export_title\": \"リストを書き出す\",\n    \"list_export_notice\": \"リストの項目の内容をコピーしたり、Excelでダウンロードすることができます。\",\n    \"robotis_opencm70\": \"Robotis Open CM70\",\n    \"cannnot_mark_favorite\": \"非公開の作品は関心作品に指定できません。\",\n    \"enterPassword\": \"パスワードを入力してください。\",\n    \"enterPassword_update\": \"変更を保存するためにパスワードを入力してください。\",\n    \"enterNewPassword\": \"新しいパスワードを入力してください。\",\n    \"reEnterNewPassword\": \"新しいパスワードを再入力してください。\",\n    \"resign\": \"会員退会\",\n    \"check_sended_email\": \"送信された認証メールを確認し、メールアドレスを認証してください。\",\n    \"signUpEmail_1\": \"入力されたメールアドレスに認証メールを送信しました。\",\n    \"signUpEmail_2\": \"メールアドレスを認証してください。\",\n    \"select_email_unauthenticated_user\": \"The email address is registered to the IDs below.\\nPlease choose the right one.\",\n    \"select_user\": \"Please choose the ID.\",\n    \"enter_password_withdraw\": \"会員退会手続きのため、パスワードを入力してください。\",\n    \"instruction_agree\": \"次の内容に同意してください。\",\n    \"check_instructions\": \"上記の内容に同意します。\",\n    \"deleteAccount_2\": \"会員退会手続きから30日後に会員情報と作品/講義/クラス/投稿/コメント/いいね/関心情報はすべて削除され、復元できなくなります。\",\n    \"deleteAccount_1\": \"会員退会手続きから30日以内にログインすると、会員退会を取り消すことができます。\",\n    \"protect_account\": \"安全なパスワードであなたの情報を保護してください。\",\n    \"please_verify\": \"認証メールを送信し、メールアドレスを認証してください。\",\n    \"unverified_email\": \"メールアドレス認証に失敗しました。\",\n    \"deleteAccount\": \"会員退会手続き\",\n    \"corporatePersonal\": \"個人情報の移転に同意します。\",\n    \"corporateTransferGuide\": \"個人情報譲受人(「エントリー」ウェブサイト運営者)について\",\n    \"corporateReciever\": \"個人情報の移転を受ける者: 財団法人CONNECT\",\n    \"corporateAddress\": \"CONNECTの住所及び連絡先\",\n    \"corporateAddress_1\": \"ソウル市江南区江南大路382 メリッツタワー7階\",\n    \"corporateConsent\": \"個人情報の移転を希望しない場合の同意撤回方法\",\n    \"corporateEmail\": \"アカウントに登録されたメールアドレスで退会手続きのメールを送信\",\n    \"corporateAddition\": \"併せまして、営業譲渡に伴い規約等が次のように変更になります。\",\n    \"corporateApplicationDate\": \"適用時期 : 2017年10月29日\",\n    \"corporateTargetChanges\": \"適用対象及び変更内容:\",\n    \"corporateTarget\": \"適用対象\",\n    \"corporateChanges\": \"変更内容\",\n    \"corporateTerms\": \"エントリー利用規約\",\n    \"corporateOperator\": \"ウェブサイト運営者の名称変更\",\n    \"corporateClassroomTerms\": \"クラスサービス利用規約\",\n    \"doAgreeWithClassroomTerms\": \"クラスサービス利用規約に同意します。\",\n    \"doChangePassword\": \"他人に分かりにくいパスワードに変更してください。\",\n    \"corporatePrivacyPolicy\": \"プライバシーポリシー\",\n    \"corporateConsignment\": \"ウェブサイト運営者の名称変更及び個人情報委託企業を追加\",\n    \"corporateEntrusted\": \"受諾業: NHN Technology Service(株)\",\n    \"corporateConsignmentDetails\": \"委託業務の内容: サービス開発及び運営\",\n    \"corporatePeriod\": \"保有期間 : 会員退会時または委託契約終了時まで\",\n    \"corporateChangeDate\": \"変更適用日 : 2017年10月29日付\",\n    \"corporateWarning\": \"個人情報の移転に同意してください。\",\n    \"corporateConfirm\": \"確認\",\n    \"corporateTitle\": \"平素よりエントリー教育研究所をご愛顧頂きまして誠にありがとうございます。<br>「エントリー」をご利用中の会員の皆様に心より感謝申し上げます。<br>エントリー教育研究所はこれまで公的な目的で運営してまいりました「エントリー」ウェブサイトの運営を<br>NAVERが設立した非営利財団であるCONNECT財団に譲渡することで合意いたしました。<br>今後、エントリーはCONNECT財団において公益目的で継続的に運営される<br>予定であり、会員の皆様はこれまでと同様にエントリーをご利用いただけます。<br>ウェブサイト提供主体がエントリー教育研究所からCONNECT財団に変更されるため、以下の<br>ような会員個人情報に関する移転がございますが、本合意により実際の個人情報の位置が<br>物理的に移動したわけではございません。\",\n    \"textcoding_numberError_f\": \"登録された関数の中に名前の一文字目が数字の関数があるとモード変換できません。\",\n    \"textcoding_bookedError_1f\": \"登録された関数の中に関数名が\",\n    \"textcoding_bookedError_2f\": \"の関数があるとモード変換できません。\",\n    \"textcoding_specialCharError_f\": \"登録された関数の中の名前に「_」を除く記号がある場合、モード変換できません。\",\n    \"textcoding_numberError_v\": \"登録された変数の中に名前の一文字目が数字の変数があるとモード変換できません。\",\n    \"textcoding_bookedError_1v\": \"登録された変数の中に変数名が\",\n    \"textcoding_bookedError_2v\": \" の変数があるとモード変換できません。\",\n    \"textcoding_specialCharError_v\": \"登録された変数の中の名前に「_」を除く記号がある場合、モード変換できません。\",\n    \"textcoding_numberError_l\": \"登録されたリストの中に名前の一文字目が数字であるリストがあるとモード変換できません。\",\n    \"textcoding_bookedError_1l\": \"登録されたリストの中にリスト名が\",\n    \"textcoding_bookedError_2l\": \"のリストがあるとモード変換できません。\",\n    \"textcoding_specialCharError_l\": \"登録されたリストの中に名前に「_」を除く記号がある場合、モード変換できません。\",\n    \"no_discuss_permission\": \"投稿を閲覧するための権限がありません。\",\n    \"delete_comment\": \"コメントを削除しますか?\",\n    \"delete_article\": \"投稿を削除しますか?\",\n    \"discuss_cannot_edit\": \"自分の投稿ではありません。\",\n    \"discuss_extention\": \"実行ファイルは添付できません。\",\n    \"delete_discuss_picture\": \"写真を削除しますか?\",\n    \"delete_discuss_file\": \"ファイルを削除しますか?\",\n    \"discuss_save_question\": \"投稿を保存しますか?\",\n    \"discuss_cancle_question\": \"作成を取消しますか?\",\n    \"discuss_saved\": \"が保存されました。\",\n    \"discuss_no_write_permission\": \"現在ログイン中のアカウントでは投稿を作成できません。\",\n    \"discuss_no_project_permission\": \"現在ログイン中のアカウントでは作品を掲示できません。\",\n    \"discuss_write_abuse_detected\": \"短時間に複数の投稿が作成されました。\\n1分後にやり直してください。\",\n    \"contents_abuse_detected\": \"5分後にやり直してください。\",\n    \"contents_abuse_detected_10\": \"10分後にやり直してください。\",\n    \"discuss_new_write_abuse_warn\": \"短時間に複数のコメントを作成した場合、\\nコメントの作成が制限されることがあります。\\nあらかじめご注意ください。\",\n    \"discuss_write_abuse_warn\": \"短時間に複数のコメントを作成した場合、\\nコメントの作成が制限されることがあります。\\nあらかじめご注意ください。\",\n    \"find_not_your_email\": \"メールアドレスが正しくありません\",\n    \"search_lang\": \"検索\",\n    \"search_title\": \"タイトル\",\n    \"faq_desc\": \"エントリー利用中に不明な点がございましたら、回答を確認してみてください。\",\n    \"faq_all\": \"すべて表示\",\n    \"faq_site\": \"サイトのご利用について\",\n    \"faq_project\": \"作品を作る\",\n    \"faq_hardware\": \"ハードウェア\",\n    \"faq_offline\": \"オフライン\",\n    \"faq_copyright\": \"著作権\",\n    \"faq_title\": \"よくある質問\",\n    \"faq\": \"よくある質問\",\n    \"malicious_warning\": \"不健全な写真は読み込むことができません。不健全な写真でない場合は「提案と意見」に写真を添付してお知らせください。\",\n    \"fword_alert_msg\": \"悪口や不健全な投稿は掲示できません。\",\n    \"fword_alert_1\": \"テーマに関係のない悪口や悪意のあるコメントは掲示できません。\",\n    \"fword_alert_2\": \"不健全な単語が含まれているため、代替テキストが掲示されます。\",\n    \"fword_replace_1\": \"エントリーを通して、誰でも簡単に楽しくソフトウェアについて学ぶことができます。\",\n    \"fword_replace_2\": \"ソフトウェア教育の第一歩、エントリー。\",\n    \"fword_replace_3\": \"楽しく学べる学習スペース、エントリー!\",\n    \"fword_replace_4\": \"エントリーで共有と協業を行い、素晴らしい作品を作りましょう。\",\n    \"fword_replace_5\": \"エントリーは誰でも無料でソフトウェア教育を受けることができるよう開発されたソフトウェア教育プラットフォームです。\",\n    \"fword_replace_6\": \"エントリーと一緒に健全なソフトウェア教育環境を作りましょう!\",\n    \"fword_replace_7\": \"エントリーで学び、作り、共有しながら一緒に成長しましょう。\",\n    \"solve_quiz\": \"クイズに挑戦する\",\n    \"submit_homework_first_title\": \"完成! 課題を提出する\",\n    \"submit_homework_first_content\": \"素晴らしい作品が完成しました。課題を提出してください。締切期限前まで再提出できます。\",\n    \"submit_homework_again_title\": \"課題を再提出する\",\n    \"submit_homework_again_content\": \"すでに提出した課題です。<br>課題を再提出しますか?\",\n    \"submit_homework_expired_title\": \"課題提出締切\",\n    \"submit_homework_expired_content\": \"課題の提出が締め切られました。\",\n    \"done_study_title\": \"完成\",\n    \"done_study_content\": \"作成した作品を実行してみましょう。\",\n    \"featured_courses\": \"オススメ講義集\",\n    \"follow_along\": \"やってみる\",\n    \"follow_along_desc\": \"少しずつ進めながらバラエティ豊かな作品を制作します。\",\n    \"do_quiz\": \"クイズに挑戦する\",\n    \"do_quiz_desc\": \"学習した内容を十分理解できているか、クイズを通して確認します。\",\n    \"challenge\": \"挑戦する\",\n    \"play\": \"挑戦する\",\n    \"challenge_desc\": \"与えられた問題を自ら解決し、概念を身に着けます。\",\n    \"creste_freely\": \"自由に作る\",\n    \"creste_freely_desc\": \"学習した内容で自分だけの作品を自由に制作します。\",\n    \"entry_rc_desc\": \"プログラミングの原理を学習レベルに合わせて学べるエントリー講義集! 今すぐ始めてみましょう!<br>お手本にしながら挑戦してソフトウェアを制作すれば、難しく感じられたプログラミングの原理も楽しく簡単に身につきます!\",\n    \"hw_deadline\": \"締切日\",\n    \"rc_course_desc\": \"プログラミングの原理を学習レベルに合わせて学べるよう構成されたエントリー講義集です。\",\n    \"rc_course\": \"オススメ講義集\",\n    \"entry_rec_course\": \"エントリーオススメ講義集\",\n    \"entry_rec_course_desc\": \"誰でも簡単に、真似をしながら楽しくバラエティ豊かなソフトウェアを制作できるエントリー講義を紹介します。\",\n    \"guidance\": \"案内\",\n    \"wait\": \"ストップ！\",\n    \"hint\": \"ヒント\",\n    \"concept_guide\": \"概念バッチリ\",\n    \"group_quiz\": \"クラスクイズ\",\n    \"fail_check_hint\": \"あっ…失敗! もう一度挑戦してみてください!<br>難しい時は[ヒント]を確認してください!\",\n    \"sort_student\": \"学生別\",\n    \"sort_lesson\": \"講義別\",\n    \"sort_course\": \"講義集別\",\n    \"student_progress\": \"クラスの進度\",\n    \"my_progress\": \"自分の進度\",\n    \"lec_in_progress\": \"学習中\",\n    \"free_modal_asgn_over\": \"課題の提出が締め切られました。\",\n    \"free_submission_closed\": \"課題提出締切\",\n    \"free_modal_asgn_submit_first\": \"素晴らしい作品が完成しました! 課題を提出してください。<br>締切期限前まで再提出できます。\",\n    \"asgn_submit\": \"完成! 課題を提出する\",\n    \"free_modal_content_resubmit\": \"すでに提出した課題です。<br>課題を再提出しますか?\",\n    \"asgn_resubmit\": \"課題を再提出する\",\n    \"free_modal_content_complete\": \"素晴らしい作品が完成しました。\",\n    \"guide_modal_content_complete\": \"制作した作品を実行してみましょう。\",\n    \"success\": \"成功\",\n    \"fail\": \"失敗\",\n    \"mission_modal_content_fail\": \"<br>難しい時は[ヒント]を確認してください!\",\n    \"mission_modal_content_success\": \"作った作品を実行してみましょう。\",\n    \"in_progress\": \"進行中\",\n    \"completed\": \"完了\",\n    \"submitted\": \"提出完了\",\n    \"submission_closed\": \"締切\",\n    \"progress\": \"進行状況\",\n    \"study_completed\": \"学習完了\",\n    \"view_course_desc\": \"コースウェアの説明を見る\",\n    \"main_entry_starter\": \"基礎から! エントリースターター\",\n    \"main_entry_booster\": \"概念固め! エントリーブースター\",\n    \"main_entry_master\": \"思考を広げる! エントリーマスター\",\n    \"no_students_in_classroom\": \"まだ登録された学生がいません。<br>学生を直接追加するか招待してください!\",\n    \"lectures\": \"講義\",\n    \"Lectures\": \"講義\",\n    \"studentHomeworkList\": \"課題\",\n    \"curriculums\": \"講義集\",\n    \"Curriculums\": \"講義集\",\n    \"quiz\": \"クイズ\",\n    \"no_added_group_contents_teacher\": \"追加された%1がありません。<br>クラス%1を追加してください。\",\n    \"no_added_group_contents_student\": \"まだアップロードされた%1がありません。先生が%1をアップロードすると、学習内容を確認できます。\",\n    \"side_project\": \"サブプロジェクト\",\n    \"custom_make_course_1\": \"「オープン講義を作成する>講義集を作成する」で\",\n    \"custom_make_course_2\": \"自分だけの講義集を作成してみてください。\",\n    \"custom_make_lecture_1\": \"「オープン講義を作成する」で\",\n    \"custom_make_lecture_2\": \"自分だけの講義を作成してみてください。\",\n    \"alert_enter_info\": \"修正したい情報を入力してください。\",\n    \"alert_enter_new_pwd\": \"既存のパスワードと違うパスワードを入力してください。\",\n    \"alert_match_pwd\": \"新しいパスワードと再入力されたパスワードが一致しません。\",\n    \"alert_check_pwd\": \"パスワードを確認してください。\",\n    \"alert_update_complete\": \"修正が完了しました。\",\n    \"no_group_contents_each_prefix\": \"クラス\",\n    \"no_group_contents_each_suffix\": \" がありません。\",\n    \"no_group_contents_all\": \"クラスにアップロードされたコンテンツがありません。<br>「クラスで共有する」に<br>自分の作品を共有してみてください!\",\n    \"hw_closed\": \"課題締切\",\n    \"tag_Lecture\": \"講義\",\n    \"tag_Curriculum\": \"講義集\",\n    \"tag_Discuss\": \"お知らせ\",\n    \"count_ko\": \"件\",\n    \"no_asgn_within_week\": \"1週間以内に提出する必要のある、締切間近の課題はありません。\",\n    \"lecture_and_curriculum\": \"講義/講義集\",\n    \"assignments_plural\": \"課題\",\n    \"assignments_singular\": \"課題\",\n    \"project_plural\": \"作品\",\n    \"group_news\": \"新しいニュース\",\n    \"stu_management\": \"学生管理\",\n    \"stu_management_camel\": \"学生管理\",\n    \"view_all\": \"すべて表示\",\n    \"view_all_camel\": \"すべて表示\",\n    \"view_contents_camel\": \"コンテンツを見る\",\n    \"view_contents\": \"コンテンツを見る\",\n    \"no_updated_news\": \"自分のクラスにアップロードされた新しいニュースはありません。\",\n    \"homework_soon_due\": \"締切間近の課題\",\n    \"new_homework\": \"最新の課題\",\n    \"no_new_homework\": \"新しい課題はありません。\",\n    \"student_plural\": \"学生\",\n    \"discuss\": \"お知らせ\",\n    \"basic_project\": \"基本作品\",\n    \"no_permission\": \"権限がありません。\",\n    \"no_comment_write_permission\": \"現在ログイン中のアカウントではコメントを作成できません。\",\n    \"original_curriculum_deleted\": \"講義原本集が削除されました。\",\n    \"original_curriculum\": \"講義原本集\",\n    \"save_as_my_lecture\": \"コピーで保存する\",\n    \"delete_confirm\": \"削除通知\",\n    \"lecture_open_as_copied\": \"オープン講義ページにアップロードされたすべての講義はコピーを作成して公開されます。\",\n    \"curriculum_open_as_copied\": \"オープン講義集ページにアップロードされたすべての講義集はコピーを作成して公開されます。\",\n    \"lecture_save_as_copied_group\": \"クラス講義ページにアップロードされたすべての講義はコピーを作成して公開されます。\",\n    \"curriculum_save_as_copied_group\": \"クラス講義集ページにアップロードされたすべての講義集はコピーを作成して公開されます。\",\n    \"homework_save_as_copied_group\": \"クラス課題ページにアップロードされたすべての課題はコピーを作成して公開されます。\",\n    \"lecture_save_as_copied\": \"自分が作った講義集内に挿入された構成講義はコピーを作成して保存されます。\",\n    \"done_project_save_as_copied\": \"自分が作った講義案に挿入された完成作品はコピーを作成して保存されます。\",\n    \"textbook_project_can_not_applied\": \"\",\n    \"original_lecture_deleted\": \"講義原本が削除されました。\",\n    \"original_lecture\": \"講義原本\",\n    \"lecture_save_as_mine_alert\": \"保存されました。\\n保存された講義は「マイページ> 自分の講義」で確認できます。\",\n    \"lecture_save_as_mine\": \"自分の講義に保存する\",\n    \"duplicate_username\": \"すでに入力したIDです。\",\n    \"share_your_project\": \"あなたが作った作品を共有してみてください\",\n    \"not_available_student\": \"クラスで発行された「クラスID」です。\\n「エントリー会員ID」を入力してください。\",\n    \"login_instruction\": \"ログインについて\",\n    \"login_needed\": \"ログインしてからご利用いただけます。\",\n    \"login_as_teacher\": \"教師アカウントでログインしてからご利用いただけます。\",\n    \"remove_my_storage\": \"マイボックスから削除しますか？削除したブロック／オブジェクトは元に戻せません。\",\n    \"submit_hw\": \"課題を提出する\",\n    \"success_goal\": \"目標達成\",\n    \"choseok_final_result\": \"よし、自分だけの作品を完成したぞ!\",\n    \"choseok_fail_msg_timeout\": \"タイムオーバーだぜ。目標をよく見てもう一度チャレンジしてみようぜ!\",\n    \"choseok_fail_msg_die\": \"ライフが0以下なのにまだゲームが終ってないぞ。\\n下のブロックを使ってもう一度チャレンジしてみないか?\",\n    \"grade_1\": \"初級\",\n    \"grade_2\": \"中級\",\n    \"grade_3\": \"上級\",\n    \"find_sally_title\": \"サリーを探せ\",\n    \"save_sally_title\": \"サリーを救え\",\n    \"exit_sally_title\": \"サリーと脱出\",\n    \"find_sally\": \"LINEレンジャーの力を一つに合わせて\\n最強ボス・メフィストを倒し、サリーを救ってください!\",\n    \"save_sally\": \"メフィストの基地に閉じ込められたサリー。\\nLINEレンジャーが障害物を避けてサリーを探し出せる\\nように手伝ってください!\",\n    \"exit_sally\": \"爆破されたメフィストの基地から\\nサリーとLINEレンジャーが無事脱出できるように\\n手伝ってください!\",\n    \"go_next_mission\": \"他のミッションに挑戦する\",\n    \"share_my_project\": \"自分が作った作品を共有する\",\n    \"share_certification\": \"証明書を共有する\",\n    \"print_certification\": \"証明書を自慢しよう\",\n    \"get_cparty_events\": \"自分が受け取った証明書を出力して自慢すると、豪華賞品を獲得できます!\",\n    \"go_cparty_events\": \"イベントに参加する\",\n    \"codingparty2016_blockHelper_1_title\": \"前に進む\",\n    \"codingparty2016_blockHelper_1_contents\": \"前に進む\",\n    \"codingparty2016_blockHelper_2_title\": \"前に進む\",\n    \"codingparty2016_blockHelper_2_contents\": \"回転する\",\n    \"codingparty2016_blockHelper_3_title\": \"前に進む\",\n    \"codingparty2016_blockHelper_3_contents\": \"石を砕く\",\n    \"codingparty2016_blockHelper_4_title\": \"前に進む\",\n    \"codingparty2016_blockHelper_4_contents\": \"回繰り返す\",\n    \"codingparty2016_blockHelper_5_title\": \"前に進む\",\n    \"codingparty2016_blockHelper_5_contents\": \"花を投げる\",\n    \"codingparty2016_goalHint_1\": \"サリーを救うためにはミネラルが必要だ!ミネラルを獲得しながら目的地まで行ってみよう!\",\n    \"codingparty2016_goalHint_2\": \"曲がり道があるね。ターンブロックを使えば大丈夫だよ!\",\n    \"codingparty2016_goalHint_3\": \"道が石で塞がれているね。石を砕きながら目的地まで行ってみよう!\",\n    \"codingparty2016_goalHint_4\": \"ややこしい道だけど、これまで覚えたテクニックを使えば解決できるはずだよ!\",\n    \"codingparty2016_goalHint_5\": \"長く続く道だね。リピートブロックを使って簡単に解決してみよう!\",\n    \"codingparty2016_goalHint_6\": \"ミネラルを全部集めよう。リピートブロックを使えば簡単にできそうだよ!\",\n    \"codingparty2016_goalHint_7\": \"みんながケガをしないように花を投げてクモの巣を取り除かないと!遠くにあるクモの巣を取り除いて目的地まで行ってみよう。\",\n    \"codingparty2016_goalHint_8\": \"道にクモの巣が多いね。クモの巣を全部取り除いて目的地まで行ってみよう。\",\n    \"codingparty2016_goalHint_9\": \"クモの巣の後ろに隠れているミネラルを全部集めよう!\",\n    \"codingparty2016_guide_1_1_contents\": \"LINEレンジャーたちがサリーを救い出せるように手伝ってあげて! ブロックコマンドを組み合わせれば、レンジャーたちを動かすことができるよ。\\n\\n① まず、ミッション画面と目標を確認して、\\n② ブロックリストから必要なブロックを引っ張ってきて「スタートボタンを押した時」のブロックにつなげてね。\\n③ 組み合わせ終わったら「スタート」ボタンを押してみよう!ブロックコマンドが上から順に実行されて、レンジャーたちが動くはずだよ。\",\n    \"codingparty2016_guide_1_1_title\": \"LINEレンジャーたちを動かすためには?\",\n    \"codingparty2016_guide_1_2_title\": \"目標ブロック数\",\n    \"codingparty2016_guide_1_2_contents\": \"① [色が塗られていない星]の数だけブロックコマンドを組み合わせてミッションを解決してみよう。目標ブロック数より多くブロックを使うと星の色が赤に代わるから、決められた数で問題を解決してみてね!\\n② 要らないブロックはゴミ箱やブロックリストに戻してね。\",\n    \"codingparty2016_guide_1_3_title\": \"「前に進む」ブロックを使う\",\n    \"codingparty2016_guide_1_3_contents\": \"< 前に進む >は、前に1マス移動するブロックだよ。\\n\\nもっと移動したいときはこのブロックを必要な数だけつなげよう。\",\n    \"codingparty2016_guide_1_4_title\": \"ミネラルを獲得する\",\n    \"codingparty2016_guide_1_4_contents\": \"[ミネラル]があるマスを通り過ぎるとミネラルを獲得できるよ。\\n\\n画面にあるミネラルを全部獲得して目的地に到着しないと、次のステップに進めないからね。\",\n    \"codingparty2016_guide_1_5_title\": \"行き詰ったときは?\",\n    \"codingparty2016_guide_1_5_contents\": \"行き詰った時は下の3つのヘルプボタンを押してみよう。\\n\\n\\n<案内> 今読んでいるこの利用案内をもう一度確認したいとき!\\n<ブロックヘルプ> 一つ一つのブロックコマンドがどう実行されるか知りたいとき!\\n<マップヒント> このステップを解決するためのヒントが必要なとき!\",\n    \"codingparty2016_guide_2_1_title\": \"ターンブロックを使う\",\n    \"codingparty2016_guide_2_1_contents\": \"<右に回転する>と<左に回転する>は、\\nその場で方向だけ90度回転させるブロックだよ。方向だけ回転させるブロックなんだ。\\nキャラクターから向かって右か左か、よく考えて使ってね!!\\n\",\n    \"codingparty2016_guide_3_1_title\": \"「ムーン」のスキルを使う\",\n    \"codingparty2016_guide_3_1_contents\": \"LINEレンジャーたちはそれぞれ特殊なスキルを持っているんだ。\\n僕、[ムーン]は<キックする>で手前にある[石]を砕くことができるよ。\\n[石]を砕けば前に進めるようになるよね。\\n画面にある[石]を全部取り除かないと次のステップに進めないからね。\\nでも忘れないでね!何もないマスで無駄にスキルを使っちゃダメだよ!\",\n    \"codingparty2016_guide_5_1_title\": \"「～回繰り返す」ブロックを使う\",\n    \"codingparty2016_guide_5_1_contents\": \"同じブロックを何個もつなげるのは本当に面倒くさいよね。\\nそんな時はリピートコマンドを使えばもっと簡単に解決できるんだ。\\n<[ ? ] ～回繰り返す>ブロックの中に繰り返されるアクションのブロックを入れて\\n[ ? ]の部分に回数を入力すれば、入力した回数だけ同じコマンドを繰り返し実行させることができるよ。\",\n    \"codingparty2016_guide_5_2_title\": \"<～回繰り返す>ブロックを使う\",\n    \"codingparty2016_guide_5_2_contents\": \"<[ ? ]回繰り返す>ブロックの中にはブロックを複数組み合わせて入れることもできるから、うまく活用してみてね!\\n目的地に着いてからもリピートブロックの中にあるブロックコマンドは全て実行されるよ。\\n上の状況だと、目的地に着いた後、左にターンしてから終わるということ!\",\n    \"codingparty2016_guide_7_1_title\": \"(コニー)のスキルを使う\",\n    \"codingparty2016_guide_7_1_contents\": \"私「コニー」は<花を投げる>で遠くからでも前にある[クモの巣]を取り除くことができるよ。\\n[クモの巣]を取り除けば前に進めるようになるよね?\\n画面にある[クモの巣]を全部取り除かないと次のステップに進めないからね。\\nでも忘れないでね!何もないマスで無駄にスキルを使っちゃダメだよ!\",\n    \"codingparty2016_guide_9_1_title\": \"条件リピートブロックを使う\",\n    \"codingparty2016_guide_9_1_contents\": \"何回繰り返せばいいか考えなくても、特定の条件を満たすまでそのアクションを繰り返すことができるよ。\\n<[目的地]に到着するまで繰り返す>ブロックの中に繰り返されるブロックを入れると[目的地]に到着するまでコマンドを繰り返し実行するよ。\",\n    \"codingparty2016_guide_9_2_title\": \"条件リピートブロックを使う\",\n    \"codingparty2016_guide_9_2_contents\": \"<[目的地]に到着するまで繰り返す>ブロックの中にはコマンドを複数入れることもできるからうまく活用してみて! \\n目的地に着いてからもリピートブロックの中にあるブロックコマンドは全て実行されるよ。上の状況だと、目的地に着いた後、左にターンしてから終わるということ!\",\n    \"find_interesting_lesson\": \"「クラス講義」でバラエティ豊かな講義をお楽しみください!\",\n    \"find_interesting_course\": \"「クラス講義集」でバラエティ豊かな講義をお楽しみください!\",\n    \"select_share_settings\": \"共有スペースを選択してください。\",\n    \"faq_banner_title\": \"よくある質問について\",\n    \"check_out_faq\": \"質問に答えます！\",\n    \"faq_banner_content\": \"エントリーについて分からないことがありますか?<br />よくある質問でご回答させていただいています。<br />今すぐ確認してください!\",\n    \"faq_banner_button\": \"よくある質問<br />へ移動\",\n    \"major_updates\": \"主なアップデートのご案内\",\n    \"check_new_update\": \"エントリーの変化を確認してください。\",\n    \"major_updates_notification\": \"エントリーの主な変更内容はお知らせでご案内しております。\",\n    \"find_out_now\": \"今すぐ確認してください!\",\n    \"offline_hw_program\": \"オフライン&ハードウェア結合プログラム\",\n    \"read_more\": \"詳しく見る\",\n    \"sample_project\": \"例示作品\",\n    \"not_supported_function\": \"この端末ではサポートされていない機能です。\",\n    \"offline_download_confirm\": \"エントリーのオフラインバージョンはPCでのみご利用いただけます。ダウンロードしますか?\",\n    \"hardware_download_confirm\": \"エントリーのハードウェアはPCでのみご利用いただけます。ダウンロードしますか?\",\n    \"copy_text\": \"テキストをコピーしてください。\",\n    \"select_openArea_space\": \"作品共有スペースを選択してください\",\n    \"mission_guide\": \"「ミッションを解決する」について\",\n    \"of\": \" の\",\n    \"no_results_found\": \"検索結果がありません。\",\n    \"upload_pdf\": \"PDF資料アップロード\",\n    \"select_basic_project\": \"作品を選択する\",\n    \"try_it_out\": \"作成してみる\",\n    \"go_boardgame\": \"エントリーボットボードゲームに移動\",\n    \"go_cardgame\": \"エントリーボットカードゲームに移動\",\n    \"go_solve\": \"ミッションで学習する\",\n    \"go_ws\": \"「エントリーを作成する」に移動\",\n    \"go_arts\": \"「エントリーを共有する」に移動\",\n    \"group_delete_alert\": \"クラスを削除すると、そのクラスで発行した学生用臨時アカウントを含む関連資料がすべて削除されます。\\n本当に削除しますか?\",\n    \"view_arts_list\": \"他の作品を見る\",\n    \"hw_submit_confirm_alert\": \"課題が提出されました。\",\n    \"hw_submit_alert\": \"課題を提出しますか? \",\n    \"hw_submit_alert2\": \"課題を提出しますか? 提出時に学習が完了した学習レベルまでのみ提出されます。\",\n    \"hw_submit_cannot\": \"提出できない課題です。\",\n    \"see_other_missions\": \"他のミッションを見る\",\n    \"project\": \" 作品\",\n    \"marked\": \" 関心\",\n    \"group\": \"クラス\",\n    \"lecture\": \"講義\",\n    \"Lecture\": \"講義\",\n    \"curriculum\": \"講義集\",\n    \"Curriculum\": \"講義集\",\n    \"studying\": \"学習中の\",\n    \"open_only_shared_lecture\": \"<b>オープン講義</b> ページに<b><公開></b>した講義のみ読み込むことができます。読み込む<b>講義</b>の<b>公開状況</b>を確認してください。\",\n    \"already_exist_group\": \"このクラスがすでに存在します。\",\n    \"cannot_invite_you\": \"自分は招待できません。\",\n    \"apply_original_image\": \"オリジナル画像をそのまま適用する\",\n    \"draw_new_ques\": \"「新しく描画する」ページに\\n移動しますか?\",\n    \"draw_new_ques_1\": \"絵を描いてオブジェクトとして保存できます。\",\n    \"draw_new_ques_2\": \"描く画面に移動しますか\",\n    \"draw_new_go\": \"移動する\",\n    \"draw_new_stay\": \"移動しない\",\n    \"file_upload_warn_title_image\": \"下のような画像は、利用規約および関連の法律によって制裁を受けることがあります。\",\n    \"file_upload_warn_desc_image\": \"暴力的で残酷な画像<br>性的に体の部位が露出している画像<br>不快感を与えたり、嫌悪感を与える画像<br>無断使用が禁止された画像\",\n    \"file_upload_warn_title_sound\": \"下記のようなサウンドは、利用規約および関連の法律によって制裁措置される場合があります。\",\n    \"file_upload_warn_desc_sound\": \"暴力的で残酷なサウンド<br>性的なサウンド<br>不快感や嫌悪感を与えるサウンド<br>無断使用が禁止されたサウンド\",\n    \"file_upload_warn_title_table\": \"下のような画像は、利用規約および関連の法律によって制裁を受けることがあります。\",\n    \"file_upload_warn_desc_table\": \"暴力的で残酷な画像<br>性的に体の部位が露出している画像<br>不快感を与えたり、嫌悪感を与える画像<br>無断使用が禁止された画像\",\n    \"file_upload_warn_link\": \"著作権について\",\n    \"file_upload_desc_1\": \"こういう画像は\\nNGです!\",\n    \"file_upload_desc_2\": \"暴力的で残酷な画像\",\n    \"file_upload_desc_3\": \"性的に体の部位が露出している画像\",\n    \"file_upload_desc_4\": \"不快感を与えたり、嫌悪感を与える画像\",\n    \"file_upload_desc_5\": \"* 上のような内容は、利用規約および関連法律により制裁を受けることがあります。\",\n    \"picture_upload_warn_old\": \"10MB以下のjpg,png,bmp形式の画像ファイルのみアップロードできます。\",\n    \"sprite_upload_warn_old\": \"10MB以下のjpg,png,bmp形式の画像やeo形式のオブジェクトファイルのみアップロードできます。\",\n    \"picture_upload_warn_1\": \"10MB以下のjpg,png,bmp,svg形式の画像ファイルのみアップロードできます。\\njpg,png,bmp形式はビットマップモードで,svg形式はベクターモードで編集されます。\",\n    \"table_upload_warn_1\": \"10MB以下のcsv,xls(x)形式の画像ファイルのみアップロードできます。\",\n    \"sprite_upload_warn\": \"10MB以下のjpg,png,bmp,svg形式の画像やeo形式のオブジェクトファイルのみアップロードできます。\",\n    \"sound_upload_warn_1\": \"10MB以下のmp3形式のファイルを追加できます。\",\n    \"sound_edit_warn\": \"お待ちください。<br>ただいま、新しい音の編集機能を研究中です。\",\n    \"file_upload_loading\": \"ローディング中\",\n    \"lesson_by_teacher\": \"先生方が直接作成する講義です。\",\n    \"delete_group_art\": \"「クラスで共有する」リストから削除しますか?\",\n    \"elementary_short\": \"小学校\",\n    \"middle_short\": \"中学校\",\n    \"grade_34\": \"3-4学校\",\n    \"grade_56\": \"5-6学校\",\n    \"grade_78\": \"中学校\",\n    \"share_lesson\": \"講義を共有する\",\n    \"share_course\": \"講義集を共有する\",\n    \"from_list_ko\": \"は\",\n    \"comming_soon\": \"準備中です。\",\n    \"no_class_alert\": \"選択されたクラスがありません。クラスがない場合、「自分のクラス」メニューでクラスを作成してください。\",\n    \"students_cnt\": \"人\",\n    \"defult_class_alert_1\": \" \",\n    \"defult_class_alert_2\": \"を\\n基本クラスに設定しますか?\",\n    \"default_class\": \"基本クラスです。\",\n    \"enter_hw_name\": \"課題のタイトルを入力してください。\",\n    \"hw_limit_20\": \"課題の作成上限は20件です。\",\n    \"stu_example\": \"例)\\n 山田太郎\\n山田太郎\\n山田太郎\",\n    \"hw_description_limit_200\": \"作成課題に関する案内事項を入力してください。(200文字以内)\",\n    \"hw_title_limit_50\": \"課題名を入力してください。(50文字以内)\",\n    \"create_project_class_1\": \"「作る」>「作品を作る」で\",\n    \"create_project_class_2\": \"クラスで共有したい作品を制作してください。\",\n    \"create_lesson_assignment_1\": \"「作る> オープン講義を作成する」で\",\n    \"create_lesson_assignment_2\": \"クラス課題に追加したい講義を作成してください。\",\n    \"i_make_lesson\": \"自分が作成した講義\",\n    \"lesson_to_class_1\": \"「学習する>オープン講義」でクラスの\",\n    \"lesson_to_class_2\": \"課題に追加したい講義を関心講義に登録してください。\",\n    \"studying_students\": \"学習者\",\n    \"lessons_count\": \"講義数\",\n    \"group_out\": \"退出する\",\n    \"enter_group_code\": \"クラスコードを入力する\",\n    \"no_group_invite\": \"クラス招待がありません。\",\n    \"done_create_group\": \"開設に成功しました。\",\n    \"set_default_group\": \"基本クラス設定\",\n    \"edit_group_info\": \"クラス情報管理\",\n    \"edit_done\": \"修正が完了しました。\",\n    \"alert_group_out\": \"クラスから本当に退出しますか?\",\n    \"lesson_share_cancel\": \"講義共有取消\",\n    \"project_share_cancel\": \"作品共有取消\",\n    \"lesson_share_cancel_alert\": \"続けますか?\",\n    \"course_share_cancel\": \"講義集共有取消\",\n    \"select_lesson_share\": \"講義共有スペース選択\",\n    \"select_project_share\": \"作品共有選択\",\n    \"select_lesson_share_policy_1\": \"講義を共有したい\",\n    \"select_lesson_share_policyAdd\": \"スペースを選択してください\",\n    \"select_lesson_share_project_1\": \"作品を共有するスペースと\",\n    \"select_lesson_share_policy_2\": \"著作権ポリシーを確認してください。\",\n    \"select_lesson_share_area\": \"講義共有スペースを選択してください\",\n    \"select_project_share_area\": \"作品共有スペースを選択してください\",\n    \"lesson_share_policy\": \"講義共有に伴うエントリーの著作権ポリシーに同意\",\n    \"project_share_policy\": \"作品共有に伴うエントリーの著作権ポリシーに同意\",\n    \"alert_agree_share\": \"公開するためには、エントリーの著作物ポリシーに同意する必要があります。\",\n    \"alert_agree_all\": \"すべての項目に同意してください。\",\n    \"select_course_share\": \"講義集共有スペースを選択\",\n    \"select_course_share_policy_1\": \"講義集を共有する\",\n    \"select_course_share_policy_2\": \"著作権ポリシーを確認してください。\",\n    \"select_course_share_area\": \"講義集共有スペースを選択してください\",\n    \"course_share_policy\": \"講義集共有に伴うエントリーの著作権ポリシーに同意\",\n    \"issued\": \"発行\",\n    \"code_expired\": \"コードの期限が切れました。「コード再発行」ボタンを押してください。\",\n    \"accept_class_invite\": \"クラス招待を承認する\",\n    \"welcome_class\": \"クラスへようこそ。\",\n    \"enter_info\": \"あなたの情報を入力してください。\",\n    \"done_group_signup\": \"クラスへ参加しました。\",\n    \"enter_group_code_stu\": \"先生から受け取ったコードを入力してください。\",\n    \"text_limit_50\": \"50文字以下で作成してください。\",\n    \"enter_class_name\": \"クラス名を入力してください。\",\n    \"enter_grade\": \"学年を入力してください。\",\n    \"enter_class_info\": \"クラス紹介を入力してください。\",\n    \"student_dup\": \"はすでにクラスに存在します。\",\n    \"select_stu_print\": \"出力する学生を選択してください。\",\n    \"class_id_not_exist\": \"クラスIDが存在しません。\",\n    \"error_try_again\": \"エラー発生。もう一度やり直してください。\",\n    \"error_forbidden\": \"権限がありません。\",\n    \"code_not_available\": \"このコードは無効です。\",\n    \"gnb_create_lessons\": \"オープン講義作成\",\n    \"study_lessons\": \"講義で学習する\",\n    \"lecture_help_1\": \"学習開始時に使用する作品を選択してください。選択した作品で学習者が学習を開始します。\",\n    \"lecture_help_2\": \"このヘルプをもう一度確認したい時は、上のボタンをクリックしてください。\",\n    \"lecture_help_3\": \"「オブジェクトを追加する」がない場合、新しいオブジェクトを追加または削除することができません。\",\n    \"lecture_help_4\": \"学習途中に「PDF資料を見る」を利用して学習を手伝ってもらうことができます。\",\n    \"lecture_help_5\": \"学習に必要なブロックのみ選択してください。選択しないブロックは非表示になります。\",\n    \"lecture_help_6\": \"ブロックコーディングとエントリーパイソンの中から選択し、学習環境を構成できます。\",\n    \"lecture_finish_popup_title\": \"학습 다시하기\",\n    \"lecture_finish_popup_content_1\": \"실습완료한 단계를<br>처음부터 다시 실습하시겠습니까?\",\n    \"lecture_finish_popup_content_2\": \"* 다시 실습해도 실습 완료 상태는 유지됩니다.\",\n    \"lecture_start_title\": \"Start\",\n    \"lecture_goal_title\": \"Goal\",\n    \"lecture_goal_content\": \"Goal\",\n    \"lecture_prepare_title\": \"Prepare\",\n    \"lecture_summary_title\": \"Summary\",\n    \"lecture_summary_content\": \"Let's summarize what we learned.\",\n    \"lecture_quiz_title\": \"Quiz\",\n    \"lecture_quiz_content\": \"Let's check what we learned through the verification problem.\",\n    \"lecture_quiz_check_answer\": \"Check the answer\",\n    \"default_hint_title\": \"どのように作るか\",\n    \"only_pdf\": \".pdf形式のファイルのみ入力できます。\",\n    \"enter_project_video\": \"最低1件の作品、または映像を入力してください。\",\n    \"enter_title\": \"タイトルを入力してください。\",\n    \"enter_recommanded_grade\": \"推奨学年を入力してください。\",\n    \"enter_level_diff\": \"難易度を入力してください。\",\n    \"enter_time_spent\": \"所要時間を入力してください。\",\n    \"enter_shared_area\": \"最低1件の共有スペースを選択してください。\",\n    \"enter_goals\": \"学習目標を入力してください。\",\n    \"enter_lecture_description\": \"講義説明を入力してください。\",\n    \"enter_curriculum_description\": \"講義集説明を入力してください。\",\n    \"first_page\": \"最初です。\",\n    \"last_page\": \"最後です。\",\n    \"alert_duplicate_lecture\": \"すでに登録されている講義は再登録できません。\",\n    \"enter_lesson_alert\": \"1つ以上の講義を登録してください。\",\n    \"open_edit_lessons\": \"編集したい講義を読み込んでください。\",\n    \"saved_alert\": \"が保存されました。\",\n    \"select_lesson_type\": \"どのような学習課程を作成するかを選択してください \",\n    \"create_lesson\": \"講義を作成する\",\n    \"create_lesson_desc_1\": \"希望する学習目標に合わせ\",\n    \"create_lesson_desc_2\": \"ひとつの講義を作成して\",\n    \"create_lesson_desc_3\": \"学習に活用します。\",\n    \"create_courseware\": \"講義集を作成する\",\n    \"create_courseware_desc_1\": \"学習課程に合わせて複数の講義を\",\n    \"create_courseware_desc_2\": \"ひとつのコースとして作成し\",\n    \"create_courseware_desc_3\": \"学習に活用します。\",\n    \"create_open_lesson\": \"オープン講義を作成する \",\n    \"enter_lesson_info\": \"講義情報入力\",\n    \"select_lesson_feature\": \"学習機能選択 \",\n    \"check_info_entered\": \"入力情報確認 \",\n    \"enter_lefo_lesson_long\": \"講義を構成する情報を入力してください。\",\n    \"lesson_info_desc\": \"学習者が「学習する」画面で使用したい機能と作品を選択することで、学習目標や内容に最適化された学習環境を構成できます。\",\n    \"provide_only_used\": \"完成された作品で使用されたブロックだけを読み込む\",\n    \"see_help\": \"ヘルプを見る\",\n    \"select_done_project_1\": \"学習者が目標に設定したい\",\n    \"select_done_project_2\": \"完成作品\",\n    \"select_done_project_3\": \"を選択してください。\",\n    \"select_project\": \"自分の作品または関心作品を読み込みます。\",\n    \"youtube_desc\": \"YouTube共有リンクを利用して映像を挿入できます。\",\n    \"lesson_video\": \"講義映像\",\n    \"lesson_title\": \"講義タイトル\",\n    \"recommended_grade\": \"推奨学年\",\n    \"selection_ko\": \"選択\",\n    \"selection_en\": \" \",\n    \"level_of_diff\": \"難易度\",\n    \"select_level_of_diff\": \"難易度選択\",\n    \"enter_lesson_title\": \"講義タイトルを入力してください(30文字以内)\",\n    \"select_time_spent\": \"所要時間選択 \",\n    \"time_spent\": \"所要時間\",\n    \"lesson_overview\": \"講義説明\",\n    \"upload_materials\": \"学習資料アップロード\",\n    \"open\": \"読み込む\",\n    \"cancel\": \"取り消す\",\n    \"upload_lesson_video\": \"講義映像アップロード\",\n    \"youtube_upload_desc\": \"YouTube共有リンクを利用していサブ映像を挿入できます。\",\n    \"cancel_select\": \"選択を取り消す\",\n    \"select_again\": \"再選択する\",\n    \"goal_project\": \"完成作品\",\n    \"upload_study_data\": \"「学習する」画面で閲覧できる学習資料をアップロードしてください。学習者がアップロードされた学習資料の内容を確認して学習できます。\",\n    \"upload_limit_20mb\": \"20MB以下のファイルをアップロードしてください。\",\n    \"expect_time\": \"予想所要時間\",\n    \"course_videos\": \"サブ映像\",\n    \"enter_courseware_info\": \"講義集情報入力\",\n    \"enter_course_info\": \"講義集を紹介する情報を入力してください \",\n    \"select_lessons_for_course\": \"講義集を構成する講義を選択してください。\",\n    \"course_build_desc_1\": \"講義は\",\n    \"course_build_desc_2\": \"最大30件まで\",\n    \"course_build_desc_3\": \"登録できます。\",\n    \"lseeon_list\": \"講義リストを見る\",\n    \"open_lessons\": \"講義を読み込む\",\n    \"course_title\": \"講義集タイトル\",\n    \"title_limit_30\": \"講義集タイトルを入力してください(30文字以内) \",\n    \"course_overview\": \"講義集説明\",\n    \"charactert_limit_200\": \"200文字以内で作成できます。\",\n    \"edit_lesson\": \"講義編集\",\n    \"courseware_by_teacher\": \"先生方が直接作成する講義集です。\",\n    \"select_lessons\": \"構成講義選択\",\n    \"check_course_info\": \"講義集を構成する情報が正しいか確認してください。\",\n    \"select_share_area\": \"共有スペース選択\",\n    \"upload_sub_project\": \"サブプロジェクトアップロード\",\n    \"file_download\": \"添付ファイルダウンロード\",\n    \"file_remove\": \"添付ファイル\",\n    \"check_lesson_info\": \"講義を構成する情報が正しいか確認してください。\",\n    \"share_area\": \"共有スペース\",\n    \"enter_sub_project\": \"エントリーのサブプロジェクトを登録してください。\",\n    \"lms_hw_title\": \"課題のタイトル\",\n    \"lms_hw_ready\": \"準備\",\n    \"lms_hw_progress\": \"進行中\",\n    \"lms_hw_complete\": \"完了\",\n    \"lms_hw_not_submit\": \"未提出\",\n    \"lms_hw_closed\": \"提出締切\",\n    \"submission_condition\": \"進行中の課題のみ提出できます。\",\n    \"submit_students_only\": \"学生のみ課題を提出できます。\",\n    \"want_submit_hw\": \"課題を提出しますか?\",\n    \"enter_correct_id\": \"IDを正しく入力してください。\",\n    \"id_not_exist\": \"IDが存在しません。\",\n    \"agree_class_policy\": \"クラスサービスの利用規約に同意してください。\",\n    \"delete_class\": \"クラス削除\",\n    \"type_stu_name\": \"学生名を入力してください。\",\n    \"invite_from_1\": \"で\",\n    \"invite_from_2\": \"さんを招待しました。\",\n    \"lms_pw_alert_1\": \"クラスに所属すると、先生の権限で\",\n    \"lms_pw_alert_2\": \"パスワードを再発行することができます。\",\n    \"lms_pw_alert_3\": \"先生の招待が正しいかもう一度確認してください。\",\n    \"invitation_accepted\": \"招待承認が完了しました!\",\n    \"cannot_issue_pw\": \"招待を承認していないため、パスワードを発行できません。\",\n    \"start_me_1\": \"<月刊エントリー>と共に\",\n    \"start_me_2\": \"SW教育をはじめましょう!\",\n    \"monthly_desc_1\": \"<月刊エントリー>はソフトウェア教育に不慣れな先生でも簡単かつ楽しく\",\n    \"monthly_desc_2\": \"ソフトウェア教育ができるように制作されたSW教育雑誌です。\",\n    \"monthly_desc_3\": \"毎月楽しい学習漫画と共にお送りするSW教育コンテンツをお楽しみください!\",\n    \"monthly_desc_4\": \"* 月刊エントリーは2015年11月~2016年5月まで発行後、中止されました。\",\n    \"monthly_desc_5\": \"エントリーの教育資料は教育資料ページでご覧いただけます。\",\n    \"monthly_entry\": \"月刊エントリー\",\n    \"me_desc_1\": \"毎月発刊される無料ソフトウェア教育雑誌\",\n    \"me_desc_2\": \"月刊エントリーをご購読ください!\",\n    \"solve_desc_1\": \"ゲーム感覚でミッションを解決し、\",\n    \"solve_desc_2\": \"ソフトウェアの基本原理を学んでみましょう!\",\n    \"playSw_desc_1\": \"EBS放送映像や特別映像を通して\",\n    \"playSw_desc_2\": \"ソフトウェアを学んでみましょう!\",\n    \"recommended_lessons\": \"オススメ講義集\",\n    \"recommended_lessons_1\": \"お手本にして挑戦したり、クイズも解きながら、楽しくエントリープログラミングを学んでみましょう!\",\n    \"recommended_lessons_2\": \"オススメ講義集をご覧ください!\",\n    \"offline_top_desc_1\": \"オフラインバージョンの保存機能が向上し、セキュリティが強化されました。\",\n    \"offline_top_desc_2\": \"今すぐダウンロードしてください\",\n    \"offline_main_desc\": \"エントリーのオフラインエディターアップデート!!\",\n    \"art_description\": \"エントリーで制作された作品を共有するスペースです。作品を制作して共有に参加してみてください。\",\n    \"art_description_1\": \"\",\n    \"art_description_2\": \"projects created. Create your own project and share.\",\n    \"study_index\": \"エントリーで提供するテーマ別・学年別の学習課程を通して少しずつソフトウェアを学んでいきましょう!\",\n    \"study_for_beginner\": \"初心者のためのエントリーへの第一歩\",\n    \"entrybot_desc_3\": \"案内に従ってブロックコマンドを並べて\",\n    \"entrybot_desc_4\": \"エントリーボットを学校に連れていってください。\",\n    \"move_entrybot\": \"エントリーボットを動かす\",\n    \"can_change_entrybot_1\": \"ブロックコマンドでエントリーボットの色を変えたり\",\n    \"can_change_entrybot_2\": \"おしゃべりさせることもできます。\",\n    \"learning_process_by_topics\": \"テーマ別学習課程\",\n    \"show_detail\": \"詳しく見る\",\n    \"solve_mission\": \"ミッションを解決する\",\n    \"solve_mission_desc_1\": \"ゲーム感覚でミッションを解決し、プログラミングの原理を身に着けてください!\",\n    \"solve_mission_desc_2\": \"迷路の中にいるエントリーボットを目的地まで動かして、順次、反復、条件、比較演算などの概念を自然に身に着けることができます。\",\n    \"learning_process_by_grades\": \"学年別学習課程\",\n    \"learning_process_by_grades_sub1\": \"4つのタイプで楽しく簡単に学ぶプログラミングの原理! 今すぐ始めてみましょう!\",\n    \"e3_to_e4\": \"小学校3-4年生\",\n    \"e5_to_e6\": \"小学校5-6年生\",\n    \"m1_to_m3\": \"中学生以上\",\n    \"make_using_entry\": \"エントリーで作る\",\n    \"make_using_entry_desc_1\": \"ブロックを積み重ねて様々なソフトウェアを制作してみてください!\",\n    \"make_using_entry_desc_2\": \"提供される教材をダウンロードして少しずつ進めると、アニメーション、メディアアート、ゲームなどのバラエティ豊かな作品を制作できます。\",\n    \"make_through_ebs_1\": \"EBS放送映像でソフトウェアを学習してみてください。\",\n    \"make_through_ebs_2\": \"放送映像はもちろん、少しずつ進められる特別映像を見ながら誰でも簡単にバラエティ豊かなソフトウェアを制作できます。\",\n    \"support_block_js\": \"ブロックコーディングとJavaScript言語すべてに対応しています。\",\n    \"study_ebs_title_1\": \"順序通りに! 順番通りに!\",\n    \"study_ebs_desc_1\": \"[実習] エントリーボットのおつかい\",\n    \"study_ebs_title_2\": \"楽々簡単に!\",\n    \"study_ebs_desc_2\": \"[実習] 花房を作る\",\n    \"study_ebs_title_3\": \"いつ始める?\",\n    \"study_ebs_desc_3\": \"[実習] 動物家族の紹介\",\n    \"study_ebs_title_4\": \"異なる選択、違う結果!\",\n    \"study_ebs_desc_4\": \"[実習] テレパシーゲーム\",\n    \"study_ebs_title_5\": \"情報を含んだ器\",\n    \"study_ebs_desc_5\": \"[実習] 足し算ロボットを作る\",\n    \"study_ebs_title_6\": \"あれこれ確かめてみよう!\",\n    \"study_ebs_desc_6\": \"[実習] ラッキールーレット\",\n    \"study_ebs_title_7\": \"番号で呼ぶと楽です!\",\n    \"study_ebs_desc_7\": \"[実習] 自分だけのバケットリスト\",\n    \"study_ebs_title_8\": \"ランダムプログラムを作成せよ!\",\n    \"study_ebs_desc_8\": \"[実習] ランダムキャラクターを作る\",\n    \"study_ebs_title_9\": \"どうやって見つける?\",\n    \"study_ebs_desc_9\": \"[実習] 図書館の書籍を検索する\",\n    \"study_ebs_title_10\": \"お並びください!\",\n    \"study_ebs_desc_10\": \"[実習] キー整列プログラム\",\n    \"event\": \"イベント\",\n    \"divide\": \"分岐\",\n    \"condition\": \"条件\",\n    \"random_number\": \"乱数\",\n    \"search\": \"探索\",\n    \"sorting\": \"整列\",\n    \"parallel\": \"並列\",\n    \"signal\": \"信号\",\n    \"input_output\": \"入出力\",\n    \"sequential\": \"順次\",\n    \"repeat\": \"反復\",\n    \"choice\": \"選択\",\n    \"repeat_advanced\": \"反復(回数+条件)\",\n    \"function\": \"関数\",\n    \"compare_operation\": \"比較演算\",\n    \"arithmetic\": \"算術演算\",\n    \"entry_recommended_mission\": \"エントリーのオススメミッション\",\n    \"more_mission\": \"ミッションをもっと見る\",\n    \"line_rangers_title\": \"LINEレンジャーと\\nサリーを救え\",\n    \"line_rangers_content\": \"メフィストの基地に閉じ込められた\\nサリーを救ってください!\",\n    \"pinkbean_title_string_basic\": \"メイプルスト一リ一 初級 ヘネシス\",\n    \"pinkbean_title_string_intermediate\": \"メイプルスト一リ一 中級 エリニア\",\n    \"pinkbean_title_string_advanced\": \"メイプルスト一リ一 上級 エルナス\",\n    \"pinkbean_title\": \"ピンクビーンと一緒に楽しい\\nメイプルワールドへ!\",\n    \"pinkbean_content\": \"ピンクビーンがメイプルワールドでの冒険を\\n無事に終わらせられるように手伝ってください。\",\n    \"entrybot_school\": \"エントリーボットの通学路\",\n    \"entrybot_school_desc_1\": \"エントリーボットがカバンを持って学校に\",\n    \"entrybot_school_desc_2\": \"到着できるように手伝ってください!\",\n    \"robot_factory\": \"ロボット工場\",\n    \"robot_factory_desc_1\": \"ロボット工場に閉じ込められたエントリーボット!\",\n    \"robot_factory_desc_2\": \"脱出するためには、パーツをすべて集めなければなりません。\",\n    \"electric_car\": \"電気自動車\",\n    \"electric_car_desc_1\": \"エントリーボットの自動車が前に進み続けられる\",\n    \"electric_car_desc_2\": \"よう燃料をチャージしてください。\",\n    \"forest_adventure\": \"森の中を探検\",\n    \"forest_adventure_desc_1\": \"エントリーボットが森の中に閉じ込められています!\",\n    \"forest_adventure_desc_2\": \"友達を助けてください。\",\n    \"town_adventure\": \"村を探検\",\n    \"town_adventure_desc_1\": \"お腹が空いていいるエントリーボットのために村にある\",\n    \"town_adventure_desc_2\": \"燃料を探してください。\",\n    \"space_trip\": \"宇宙旅行\",\n    \"space_trip_desc_1\": \"宇宙探査を終えたエントリーボット!\",\n    \"space_trip_desc_2\": \"地球に戻れるように手伝ってください。\",\n    \"learn_programming_mission\": \"ミッションを解決しながら学ぶプログラミング\",\n    \"make_open_lecture\": \"オープン講義作成\",\n    \"group_created\": \"作成したクラス\",\n    \"group_signup\": \"参加したクラス\",\n    \"delete_from_list\": \"をリストから削除しますか?\",\n    \"delete_from_list_en\": \" \",\n    \"lecture_collection\": \"講義集\",\n    \"edit_mypage_profile\": \"自己紹介情報管理\",\n    \"main_image\": \"メイン画像\",\n    \"edit_profile_success\": \"反映されました。\",\n    \"no_project_1\": \"自分が作った作品がありません。\",\n    \"no_project_2\": \"作品作りを開始してください!\",\n    \"empty_project_1\": \"まだ作られた作品がありません。\",\n    \"no_marked_project_1\": \"関心作品がありません。\",\n    \"no_marked_group_project_1\": \"クラスの関心作品がありません。\",\n    \"no_marked_project_2\": \"「作品を共有する」でたくさんの作品に触れてみてください!\",\n    \"no_markedGroup_project_2\": \"「クラスで共有する」でたくさんの作品に触れてみてください!\",\n    \"view_project_all\": \"作品を観覧する\",\n    \"no_lecture_1\": \"自分が作った講義がありません。\",\n    \"empty_lecture_1\": \"まだ作られた講義がありません。\",\n    \"no_lecture_2\": \"「オープン講義を作成する」で講義を作成してみてください!\",\n    \"no_marked_lecture_1\": \"関心講義がありません。\",\n    \"no_marked_group_lecture_1\": \"クラスの関心講義がありません。\",\n    \"no_marked_lecture_2\": \"「オープン講義」でバラエティ豊かな講義をお楽しみください!\",\n    \"view_lecture\": \"講義を確認する\",\n    \"no_studying_lecture_1\": \"学習中の講義がありません。\",\n    \"no_studying_lecture_2\": \"「オープン講義」で学習をスタートしてください!\",\n    \"no_lecture_collect_1\": \"自分が作った講義集がありません。\",\n    \"empty_lecture_collect_1\": \"まだ作られた講義集がありません。\",\n    \"no_lecture_collect_2\": \"「オープン講義集を作成する」で講義集を作成してみてください!\",\n    \"make_lecture_collection\": \"講義集を作成する\",\n    \"no_marked_lecture_collect_1\": \"関心講義 講義集がありません。\",\n    \"no_marked_lecture_group_collect_1\": \"クラスの関心講義 講義集がありません。\",\n    \"no_marked_lecture_collect_2\": \"「オープン講義」でバラエティ豊かな講義をお楽しみください!\",\n    \"view_lecture_collection\": \"講義集を確認する\",\n    \"no_studying_lecture_collect_1\": \"学習中の講義集がありません。\",\n    \"no_studying_lecture_collect_2\": \"「オープン講義」で学習をスタートしてください!\",\n    \"my_lecture\": \"自分の講義\",\n    \"markedGroup\": \"クラスの関心\",\n    \"markedGroup_lecture\": \"クラスの関心講義\",\n    \"markedGroup_curriculum\": \"クラスの関心講義集\",\n    \"marked_lecture\": \"関心講義\",\n    \"marked_lecture_collection\": \"自分の関心講義集\",\n    \"marked_marked_curriculum\": \"関心講義集\",\n    \"studying_lecture\": \"学習中の講義\",\n    \"completed_lecture\": \"学習完了講義\",\n    \"my_lecture_collection\": \"自分の講義集\",\n    \"my\": \"自分の\",\n    \"studying_lecture_collection\": \"学習中の講義集\",\n    \"completed_lecture_collection\": \"学習が完了した講義集\",\n    \"my_curriculum\": \"自分の講義集\",\n    \"studying_curriculum\": \"学習中の講義集\",\n    \"completed_curriculum\": \"学習が完了した講義集\",\n    \"materialCC\": \"エントリーで提供するすべての教育資料は、CC-BY 2.0ライセンスにより自由に利用できます。\",\n    \"materialccby_new\": \"エントリーで提供するすべての教育資料は、CC-BY 2.0ライセンスにより自由に利用できます。\",\n    \"entry_copyright_info\": \"エントリー著作権ガイド表示\",\n    \"pdf\": \"PDF\",\n    \"helper\": \"ヘルプ\",\n    \"youtube\": \"映像\",\n    \"tvcast\": \"映像\",\n    \"goal\": \"目標\",\n    \"basicproject\": \"開始レベル\",\n    \"hw\": \"ハードウェア\",\n    \"object\": \"オブジェクト\",\n    \"console\": \"コンソール\",\n    \"download_info\": \"すべての教育資料はそれぞれのタイトルをクリックするとダウンロードできます。\",\n    \"entry_materials_all\": \"エントリーの教育資料集\",\n    \"entry_material\": \"エントリーの教育資料\",\n    \"recommand_grade\": \"推奨学年\",\n    \"g3_4_grades\": \"3-4年生\",\n    \"g5_6_grades\": \"5-6年生\",\n    \"middle_grades\": \"中学生以上\",\n    \"entry_go_go\": \"エントリーゴーゴー!\",\n    \"entry_go_go_desc\": \"学年別・難易度別に用意された教材をぜひご活用ください！\",\n    \"entry_go_go_desc2\": \"各課程別に教育課程・学習指導・教師用指導資料の3点セットを提供しております。\",\n    \"stage_beginner\": \"初級\",\n    \"stage_middle\": \"中級\",\n    \"stage_high\": \"上級\",\n    \"middle_school_short\": \"中等\",\n    \"learn_entry_programming\": \"お手本にして学ぶエントリープログラミング\",\n    \"entry_programming_desc\": \"少しずつ進めれば、いつの間にかあなたもエントリーの達人に!\",\n    \"ebs\": \"EBS\",\n    \"ebs_material_desc\": \"放送映像と教師用指導書を活用して授業を進めてください!\",\n    \"season_1_material\": \"シーズン1 教師用指導書\",\n    \"season_2_material\": \"シーズン2 教師用指導書\",\n    \"season_1\": \"シーズン1\",\n    \"playsoftware_ebs\": \"EBS ソフトウェア、遊ぼう!\",\n    \"material_teacher_guide\": \"教師用指導書\",\n    \"season_2\": \"シーズン2\",\n    \"compute_think_textbook\": \"教科書で学ぶコンピューター的思考力\",\n    \"computational_sw\": \"国語、数学、科学、美術…学校で学ぶ様々な教科と連携してSWを学んでください!\",\n    \"python_coding_text\": \"エントリーパイソン\",\n    \"python_coding_textbook\": \"テキスト·コーディングの世界へ旅立つ旅\",\n    \"python_coding_desc\": \"エントリーファイアでテキスト言語の構造と文法を自然に学んでみてください!\",\n    \"entry_x_hardware_text\": \"エントリーXハードウェア教育資料\",\n    \"entry_x_hardware\": \"エントリーXハードウェア教育資料集\",\n    \"e_sensor\": \"Eセンサーボード\",\n    \"e_sensor_board\": \"Eセンサーボード\",\n    \"e_sensor_robot\": \"Eセンサーロボット\",\n    \"arduino\": \"Arduino\",\n    \"arduinoext\": \"ArduinoExt Uno\",\n    \"arduinonano\": \"Arduino Nano\",\n    \"albert\": \"albert\",\n    \"orange_board\": \"オレンジボード\",\n    \"arduino_board\": \"Arduino\",\n    \"joystick\": \"joystick sensor shield\",\n    \"ardublock\": \"ardublock\",\n    \"mkboard\": \"digital monkeyboard\",\n    \"mechatro_nano\": \"Mechatro Nano+\",\n    \"mechatro_uno\": \"Mechatro Uno+\",\n    \"memaker\": \"memaker\",\n    \"edumaker\": \"EduMaker Board\",\n    \"codingtoolbox\": \"コーディングツールボックス\",\n    \"materials_etc_all\": \"その他の教育資料集\",\n    \"materials_teaching\": \"教員研修資料\",\n    \"materials_etc\": \"その他の参考資料\",\n    \"materials_etc_resource\": \"参考資料\",\n    \"materials_teaching_etc\": \"教員研修資とその他の参考資\",\n    \"materials_teaching_1\": \"SW教育の必要性と教育方法論\",\n    \"materials_teaching_2\": \"エントリーと共に行うアンプラグド活動\",\n    \"materials_teaching_3\": \"ゲーム感覚でアルゴリズムが学べるエントリーミッションを解決する\",\n    \"materials_teaching_4\": \"実生活の問題解決のためのエントリープログラミング\",\n    \"materials_teaching_5\": \"教科連携SW教育1(美術、数学、社会)\",\n    \"materials_teaching_6\": \"教科連携SW教育2(国語、科学、音楽)\",\n    \"materials_teaching_7\": \"フィジカルコンピューティング実習1(Eセンサーボード)\",\n    \"materials_teaching_8\": \"フィジカルコンピューティング実習2(ハムスター)\",\n    \"materials_teaching_9\": \"授業に必要なクラス/講義機能を調べる\",\n    \"materials_etc_1\": \"エントリー初心者ユーザーのためのスタートガイド\",\n    \"materials_etc_2\": \"授業にすぐ活用できるバラエティ豊かなコンテンツ集\",\n    \"materials_etc_3\": \"月刊エントリー\",\n    \"materials_etc_4\": \"エントリー説明書\",\n    \"materials_etc_5\": \"エントリー紹介資料\",\n    \"materials_etc_6\": \"エントリーブロック下敷き\",\n    \"materials_etc_7\": \"エントリーパイソンの例題と案内\",\n    \"jr_if_1\": \"もし\",\n    \"jr_if_2\": \"前にあるなら\",\n    \"jr_fail_no_pencil\": \"こんな場所に鉛筆はないよ。鉛筆がある場所で使ってみよう~\",\n    \"jr_fail_forgot_pencil\": \"あっ! カバンに入れる鉛筆を忘れちゃった。鉛筆を集めに行こう~\",\n    \"jr_fail_much_blocks\": \"ブロックをたくさん使いすぎたな。もう一度チャレンジしてみようか?\",\n    \"cparty_jr_success_1\": \"やった! カバンを準備したよ!\",\n    \"go_right\": \"右\",\n    \"go_down\": \"  下\",\n    \"go_up\": \"  上\",\n    \"go_left\": \"  左\",\n    \"go_forward\": \"前に進む\",\n    \"jr_turn_left\": \"左に回転する\",\n    \"jr_turn_right\": \"右に回転する\",\n    \"go_slow\": \"ゆっくり進む\",\n    \"repeat_until_reach_1\": \"会うまで繰り返す\",\n    \"repeat_until_reach_2\": \" \",\n    \"pick_up_pencil\": \"鉛筆を拾う\",\n    \"repeat_0\": \" \",\n    \"repeat_1\": \"繰り返す\",\n    \"when_start_clicked\": \"スタートボタンを押した時\",\n    \"age_0\": \"作品体験\",\n    \"create_character\": \"キャラクターを作成する\",\n    \"age_7_9\": \"小学校低学年\",\n    \"going_school\": \"エントリー学校に行く\",\n    \"age_10_12_1\": \"小学校高学年1\",\n    \"collect_parts\": \"ロボット工場でパーツを集める\",\n    \"age_10_12_2\": \"小学校高学年2\",\n    \"driving_elec_car\": \"電気自動車を運転する\",\n    \"age_13\": \"中学\",\n    \"travel_space\": \"宇宙を旅行する\",\n    \"people\": \"人\",\n    \"all\": \"すべて\",\n    \"life\": \"日常生活\",\n    \"nature\": \"自然\",\n    \"animal_insect\": \"動物/昆虫\",\n    \"environment\": \"自然環境\",\n    \"things\": \"事物\",\n    \"vehicles\": \"移動手段\",\n    \"others\": \"その他\",\n    \"fantasy\": \"ファンタジー\",\n    \"instrument\": \"楽器\",\n    \"piano\": \"ピアノ\",\n    \"marimba\": \"マリンバ\",\n    \"drum\": \"ドラム\",\n    \"janggu\": \"太鼓\",\n    \"sound_effect\": \"効果音\",\n    \"others_instrument\": \"その他の打楽器\",\n    \"aboutEntryDesc_1\": \"エントリーは、誰でも無料で使えるプログラミング教育プラットフォームです。\",\n    \"aboutEntryDesc_2\": \"生徒はプログラミングを簡単に楽しく学習し、\",\n    \"aboutEntryDesc_3\": \"先生は効果的に生徒を教えることができます。\",\n    \"aboutEntryDesc_4\": \"エントリーは公共財のように\",\n    \"aboutEntryDesc_5\": \"非営利で運営されています。\",\n    \"viewProjectTerms\": \"利用ポリシーを見る\",\n    \"openSourceTitle\": \"オープンソースによる環境造成\",\n    \"openSourceDesc_1\": \"エントリーのソースコードのほか、\",\n    \"openSourceDesc_2\": \"すべての教育資料はCCライセンスを\",\n    \"openSourceDesc_3\": \"適用して公開しています。\",\n    \"viewOpenSource\": \"オープンソースを見る\",\n    \"eduPlatformTitle\": \"教育に適したプラットフォーム\",\n    \"eduPlatformDesc_1\": \"教育現場に適した教育ツールを\",\n    \"eduPlatformDesc_2\": \"目指し、学校の先生方と\",\n    \"eduPlatformDesc_3\": \"共同開発しています。\",\n    \"madeWith\": \"諮問団\",\n    \"researchTitle\": \"多様な研究による専門性の強化\",\n    \"researchDesc_1\": \"大学/学会などと共に多様な研究を行い、\",\n    \"researchDesc_2\": \"専門性を強化し続けて\",\n    \"researchDesc_3\": \"います。\",\n    \"viewResearch\": \"研究資料を見る\",\n    \"atEntry\": \"エントリーでは\",\n    \"entryLearnDesc_1\": \"楽しく学べる学習スペース\",\n    \"entryLearnDesc_2\": \"< 学習する >には、コンピューターを活用して論理的に問題を解決できるバラエティ豊かな学習\",\n    \"entryLearnDesc_3\": \"コンテンツが用意されています。ゲーム感覚で楽しく与えられたミッションをプログラミングで\",\n    \"entryLearnDesc_4\": \"解決することができ、役立つ動画を通してソフトウェアの原理を学ぶことができます。\",\n    \"entryMakeDesc_1\": \"< 作る >では、米MITで開発したScratchのようなブロック型プログラミング言語を\",\n    \"entryMakeDesc_2\": \"使用し、初めてプログラミングに触れる人でも簡単に自分だけの創作物を制作できます。\",\n    \"entryMakeDesc_3\": \"さらに、ブロックコーディングとテキストコーディングの橋渡し役をする「エントリーパイソン」モードでは、\",\n    \"entryMakeDesc_4\": \"テキスト言語の構造と文法を自然に身につけることができます。\",\n    \"entryMakeDesc_5\": \" \",\n    \"entryShareDesc_1\": \"< 共有する >では、エントリーを通して制作した作品を他の人と共有することができます。\",\n    \"entryShareDesc_2\": \"また、共有された作品がどのように構成されているのかを調べることができ、これを発展させて自分だけの作品を制作\",\n    \"entryShareDesc_3\": \"できます。共同創作もできますので、友達と力を合わせてもっと良い作品を制作することもできます。\",\n    \"entryGroup\": \"クラス機能\",\n    \"entryGroupTitle\": \"クラス学習スペース\",\n    \"entryGroupDesc_1\": \"< クラス機能 >は、教師がクラスごとに学生たちを管理できる機能です。クラスの学生同士で学習して\",\n    \"entryGroupDesc_2\": \"作品を共有することができ、課題を作り学生たちの成果物を確認できます。\",\n    \"entryGroupDesc_3\": \"また、教師は、講義機能を活用して学生たちのレベルにあった学習環境を\",\n    \"entryGroupDesc_4\": \"カスタマイズして提供することで、効率的かつ楽に授業を進めることができます・\",\n    \"entryGroupDesc_5\": \" \",\n    \"unpluggedToPhysical\": \"アンプラグド活動から、フィジカルコンピューティングまで\",\n    \"algorithmActivity\": \"基礎アルゴリズム\",\n    \"programmignLang\": \"教育用プログラミング言語\",\n    \"unpluggedDesc_1\": \"エントリーボットのボードゲームとカードゲームで、コンピューターがなくても\",\n    \"unpluggedDesc_2\": \"ソフトウェアの基本概念と原理(順次、反復、選択、関数)を身に着けることができます。\",\n    \"entryMaze\": \"エントリーボット迷路脱出\",\n    \"entryAI\": \"エントリーボット宇宙旅行\",\n    \"algorithmDesc_1\": \"ゲーム感覚でミッションを解決し、証明書を手に入れてください。\",\n    \"algorithmDesc_2\": \"ソフトウェアの基本的な原理を簡単かつ楽しく学ぶことができます。\",\n    \"programmingLangDesc_1\": \"エントリーではブロックを積み上げるようにプログラミングを行うため、誰でも簡単に\",\n    \"programmingLangDesc_2\": \"自分だけのゲーム、アニメーション、メディアアートといった素晴らしい作品を制作して共有できる教育用に適合しています。\",\n    \"viewSupporHwVideo\": \"See the hardware guide videos\",\n    \"viewSupporHw\": \"結合されるハードウェアを見る\",\n    \"supportHwDesc_1\": \"エントリーとフィジカルコンピューティングツールを結合すると、現実世界とインタラクションする素晴らしい作品を作り出すことができます。\",\n    \"supportHwDesc_2\": \"国内外の様々なハードウェア結合に対応しており、今後も順次追加される予定です。\",\n    \"entryEduSupport\": \"エントリー教育支援\",\n    \"eduSupportDesc_1\": \"エントリーでは、ソフトウェア教育のための様々な教育資料を制作し無償で配布しています。\",\n    \"eduSupportDesc_2\": \"資料はすべてエントリー公式サイトでダウンロードできます。\",\n    \"materials_1_title\": \"レベル別教材\",\n    \"materials_1_desc_1\": \"各学年のレベルに合う教材を使って、少しずつ\",\n    \"materials_1_desc_2\": \"進めながら簡単にエントリーに慣れてください！\",\n    \"materials_2_title\": \"EBS放送連携教案\",\n    \"materials_2_desc_1\": \"EBS「ソフトウェア、遊ぼう」放送と共に\",\n    \"materials_2_desc_2\": \"教師用授業指導案を提供しています。\",\n    \"materials_3_title\": \"小・中学校用の教科連携授業資料\",\n    \"materials_3_title_2\": \" \",\n    \"materials_3_desc_1\": \"様々な科目で遭遇する実生活での問題を\",\n    \"materials_3_desc_2\": \"コンピューター的思考力で解決してみてください。\",\n    \"moreMaterials\": \"より多くの教育資料を確認する\",\n    \"moreInfoAboutEntry_1\": \"エントリーのニュースをもっと確認したいなら、次のリンクにアクセスしてください。\",\n    \"moreInfoAboutEntry_2\": \"教育資料のほかにもバラエティ豊かなSW教育関連情報を共有しています。\",\n    \"material_menu_type_robot\": \"Robot\\nType\",\n    \"material_menu_type_module\": \"Module\\nType\",\n    \"material_menu_type_board\": \"Board\\nType\",\n    \"blog\": \"ブログ\",\n    \"post\": \"ポスト\",\n    \"tvCast\": \"TVキャスト\",\n    \"about_entry_pre\": \" \",\n    \"about_youtube\": \"Youtube\",\n    \"about_facebook\": \"Facebook\",\n    \"albertSchool\": \"Albert\",\n    \"arduinoBoard\": \"Arduino certified\",\n    \"arduinoCompatible\": \"non-certified\",\n    \"bitBlock\": \"ビットブロック\",\n    \"bitbrick\": \"Bitbrick\",\n    \"creamo\": \"creamo\",\n    \"playcode\": \"playcode\",\n    \"funboard\": \"funboard\",\n    \"truerobot\": \"TrueTrue\",\n    \"bingle\": \"BINGLE\",\n    \"bingles\": \"BINGLE · S\",\n    \"codeino\": \"CODEino\",\n    \"epor\": \"EPOR\",\n    \"petrone_v2\": \"Petrone V2\",\n    \"petrone_v2_drone\": \"flight\",\n    \"petrone_v2_car\": \"drive\",\n    \"e-sensor\": \"E-センサーボード\",\n    \"e-sensorUsb\": \"E-センサーボード(有線連結)\",\n    \"e-sensorBT\": \"E-センサーボード(無線連結)\",\n    \"mechatronics_4d\": \"4Dメカトロニクス\",\n    \"esensor_board\": \"E-Sensor Board\",\n    \"esensor_robot\": \"E-Sensor Robot\",\n    \"hamster\": \"Hamster\",\n    \"hummingbird\": \"Hummingbird Duo\",\n    \"roboid\": \"ロボイド\",\n    \"turtle\": \"Turtle\",\n    \"littlebits\": \"リトルビッツ\",\n    \"orangeBoard\": \"OrangeBoard\",\n    \"robotis_carcont\": \"Robotis Robot Car\",\n    \"robotis_IoT\": \"ロボティズIoT\",\n    \"robotis_IoT_Wireless\": \"ロボティズIoT(無線連結)\",\n    \"dplay\": \"DPLAY\",\n    \"iboard\": \"iboard\",\n    \"nemoino\": \"NEMOino\",\n    \"xbot_epor_edge\": \"XBOT(OneTouch Dongle/USB)\",\n    \"XbotBT\": \"XBOT EPOR and EDGE Bluetooth\",\n    \"robotori\": \"robotori\",\n    \"rokoboard\": \"rokoboard\",\n    \"neobot\": \"NEOBOT\",\n    \"neobot_sensor_theme\": \"NEOBOT Senosor Theme\",\n    \"mechatro\": \"mechatro\",\n    \"about\": \"を調べる\",\n    \"articles\": \"討論する\",\n    \"gallery\": \"観覧する\",\n    \"learn\": \"学習する\",\n    \"login\": \"ログイン\",\n    \"logout\": \"ログアウト\",\n    \"make\": \"作る\",\n    \"register\": \"登録する\",\n    \"Join\": \"会員登録\",\n    \"Edit_info\": \"自分の情報を修正\",\n    \"Discuss\": \"投稿する\",\n    \"Explore\": \"観覧する\",\n    \"Load\": \"読み込む\",\n    \"My_lesson\": \"オープン講義\",\n    \"textbook_learning\": \"教科書で学習する\",\n    \"Resources\": \"教育資料\",\n    \"play_software\": \"ソフトウェア、遊ぼう!\",\n    \"problem_solve\": \"エントリー学習\",\n    \"learning_textbook\": \"教科書で学習する\",\n    \"context_textbook\": \"初等学校の教科書のまま、先生は学校の授業を、生徒は家で予習・復習することができます。\",\n    \"info_banner_textbook\": \" \",\n    \"banner_textbook\": \"もっと多彩で\",\n    \"banner_textbook_2\": \"楽しい学習をしたいなら?\",\n    \"banner_textbook_right_banner\": \"教師用の教育資料が必要ですか?\",\n    \"banner_textbook_right_banner2\": \"  \",\n    \"banner_textbook_right_banner_btn\": \"教育資料ダウンロード\",\n    \"Learn\": \"学習する\",\n    \"teaching_tools\": \"エントリー教具\",\n    \"about_entry\": \"エントリー紹介\",\n    \"what_entry\": \"エントリーは?\",\n    \"create\": \"作る\",\n    \"create_new\": \"新しく作る\",\n    \"start_programming\": \"ソフトウェア教育の第一歩\",\n    \"Entry\": \"エントリー\",\n    \"intro_learning\": \"誰でも簡単かつ楽しくソフトウェアを学ぶことができます。\",\n    \"intro_learning_anyone\": \"今すぐ始めてましょう! \",\n    \"start_now\": \"For Free, Forever.\",\n    \"welcome_entry\": \"エントリーへようこそ。\",\n    \"student\": \"学生\",\n    \"non_menber\": \"一般人\",\n    \"teacher\": \"先生\",\n    \"terms_conditions\": \"利用規約\",\n    \"personal_information\": \"個人情報の取り扱いに関するご案内\",\n    \"limitation_liability\": \"責任の限界と法的告知\",\n    \"entry_agree\": \"エントリーの利用規約に同意します。\",\n    \"info_agree\": \"個人情報の取り扱いに同意します。\",\n    \"next\": \"次\",\n    \"enter_individual_info\": \"個人情報入力\",\n    \"enter_id\": \"ID入力\",\n    \"enter_password\": \"パスワード入力\",\n    \"confirm_password\": \"パスワード確認\",\n    \"enter_password_again\": \"パスワードをもう一度入力してください。\",\n    \"validation_password\": \"5文字以上の英数字を組み合わせてください。\",\n    \"validation_id\": \"4~20文字の英数字を組み合わせてください。\",\n    \"prev\": \"前\",\n    \"born_year\": \"生年\",\n    \"select_born\": \"生年を選択してください\",\n    \"year\": \"年\",\n    \"gender\": \"性別\",\n    \"choose_gender\": \"性別を選択 してください\",\n    \"male\": \"男性\",\n    \"female\": \"女性\",\n    \"language\": \"言語\",\n    \"best_language\": \"主言語を選択してください\",\n    \"korean\": \"韓国語\",\n    \"english\": \"英語\",\n    \"viet\": \"ベトナム\",\n    \"japan\": \"japan\",\n    \"russia\": \"russia\",\n    \"chinese_simplified\": \"Chinese(Simplified)\",\n    \"chinese_traditional\": \"Chinese(Traditional)\",\n    \"option_email\": \"メール(選択)\",\n    \"insert_email\": \"メールアドレスを入力してください\",\n    \"sign_up_complete\": \"会員登録を完了しました。\",\n    \"agree_terms_conditions\": \"利用規約に同意してください。\",\n    \"agree_personal_information\": \"「個人情報の取り扱いに関するご案内」に同意してください。\",\n    \"insert_studying_stage\": \"作品を共有したいクラスを選択してください。\",\n    \"insert_born_year\": \"生年を入力してください。\",\n    \"insert_gender\": \"性別をオプションから選択してください。\",\n    \"select_language\": \"言語を選択してください。\",\n    \"check_email\": \"メール形式を確認してください。\",\n    \"already_exist_id\": \"すでに存在するIDです。\",\n    \"id_validation_id\": \"IDは4~20文字の英数字を組み合わせてください。\",\n    \"password_validate_pwd\": \"パスワードは5文字以上の英数字を組み合わせてください。\",\n    \"password_validate_pwd_length\": \"文字を5文字以上組み合わせる必要があります。\",\n    \"neoid_username_same_id\": \"すでに使用中のIDです (NEOID)\",\n    \"insert_same_pwd\": \"同じパスワードを入力してください。\",\n    \"studying_stage_group\": \"作品共有クラス\",\n    \"studying_stage\": \"作品を共有したいクラスを選択してください。\",\n    \"password\": \"パスワード入力\",\n    \"save_id\": \"ID保存\",\n    \"auto_login\": \"自動ログイン\",\n    \"enter_id_pw\": \"ID,パスワード入力\",\n    \"forgot_password\": \"IDとパスワードを忘れましたか?\",\n    \"did_not_join\": \"まだエントリー会員ではありませんか?\",\n    \"go_join\": \"会員登録する\",\n    \"renew_index_text_00\": \"教科書で学ぶ\",\n    \"renew_index_text_01\": \"教科書でエントリーを学んでみましょう。\",\n    \"renew_index_text_02\": \"初等学校の教科書の講義で\",\n    \"renew_index_text_02_2\": \"エントリーを学んでみましょう！\",\n    \"renew_index_text_03\": \"教科書で\",\n    \"renew_index_text_03_2\": \"学習する\",\n    \"renew_index_text_1\": \"2019年、ENTRYが変わります。\",\n    \"renew_index_text_2\": \"新しくなった作品作り\",\n    \"renew_index_text_3\": \"今すぐ新しい機能を確認して\",\n    \"renew_index_text_3_2\": \"PCとタブレットで作品を作ってみましょう。\",\n    \"renew_index_text_4\": \"詳しくはこちら\",\n    \"first_step\": \"ソフトウェア教育の第一歩\",\n    \"entry_content_one\": \"想像していたことをブロックで遊び感覚で1つずつ積み上げてみてください。\",\n    \"entry_content_two\": \"ゲーム、アニメーション、メディアアートといった素晴らしい作品を完成できます!\",\n    \"entry_content_three\": \"楽しいゲームで学び、自分だけの素晴らしい作品を制作して友達と共有できる素晴らしいエントリーの世界に皆さんをご招待します!\",\n    \"funny_space\": \"楽しく学べる学習スペース\",\n    \"in_learn_section\": \"< 学習する >には、\",\n    \"learn_problem_solving\": \"コンピューターを活用して論理的に問題を解決できるバラエティ豊かな学習コンテンツが用意されています。ゲーム感覚で楽しく、与えられたミッションをプログラミングで解決したり、楽しい動画でソフトウェアの原理を学ぶことができます。\",\n    \"joy_create\": \"創作の楽しさ\",\n    \"in_make\": \"< 作る >では、\",\n    \"make_contents\": \"米MITで開発したScratchのようなビジュアルプログラミング言語を使用し、初めてプログラミングに触れる人も簡単に自分だけの創作物を制作できます。また、エントリーを通して制作できるコンテンツは無限大です。科学の授業で学んだ物理の法則を実験して、好きなキャラクターでアニメーションを制作したり直接ゲームを制作することができます。\",\n    \"and_content\": \"また、エントリーを通して制作できるコンテンツは無限大です。科学の授業で学んだ物理の法則を実験して、好きなキャラクターでアニメーションを制作したり直接ゲームを制作することができます。\",\n    \"share_collaborate\": \"共有と協業\",\n    \"explore_contents\": \"< 共有する >では、エントリーを通して制作した作品を他の人と共有することができます。また、共有された作品がどのように構成されているのかを調べることができ、これを発展させて自分だけのプロジェクトを制作することができます。さらに、エントリーでは共同創作も可能です。友達と協業することでより良いプロジェクトを制作することができます。\",\n    \"why_software\": \"何故ソフトウェア教育が必要なのか?\",\n    \"speak_obama_contents\": \"コンピューター科学を学ぶことは、単に皆さんの未来のために必要なことではありません。これは、我らがアメリカの未来のために必要なことなのです。\",\n    \"obama\": \"バラク・オバマ\",\n    \"us_president\": \"米国大統領\",\n    \"billgates_contents\": \"コンピュータープログラミングは思考の範囲を広げてより優れた思考ができるようにサポートし、分野に関係なくすべての問題について新しい解決策を生み出せる力を養ってくれます。\",\n    \"billgates\": \"ビル・ゲイツ\",\n    \"chairman_micro\": \"Microsoft会長\",\n    \"eric_contents\": \"現在、デジタル革命は地球上のほとんどの人々においてまだ始まっていないレベルにあります。プログラミングにより今後10年間ですべてのことが変化することでしょう。\",\n    \"eric\": \"エリック・シュミット\",\n    \"sandbug_contents\": \"今日、コンピューター科学に対する理解は必須となりました。我が国の競争力は、子どもたちにこれをどれだけうまく教えられるかにかかっています。\",\n    \"sandbug\": \"シェリル・サンドバーグ\",\n    \"view_entry_tools\": \"エントリーと一緒にできる教具を確認できます。\",\n    \"solve_problem\": \"ミッションを解決する\",\n    \"solve_problem_content\": \"ゲーム感覚でミッションを1つ1つ解決し、ソフトウェアの基本原理を学んでみてください!\",\n    \"find_extra_title\": \"エントリーボットパーツ探し大作戦\",\n    \"all_ages\": \"全年齢\",\n    \"total\": \"合計\",\n    \"step\": \"ステップ\",\n    \"find_extra_contents\": \"ロボット犬を生産していたルッツ工場にある日突然起こった停電により生まれた特別な犬・エントリーボット。まだ組立が終わっていない残りのパーツを見つけて工場から脱出できるように手伝いながらソフトウェアの動作原理を身に着けよう!\",\n    \"software_play_contents\": \"EBSで放送された番組「ソフトウェア、遊ぼう」の内容を実習することができます。\",\n    \"resources_contents\": \"エントリーを活用したバラエティ豊かな教育資料を無料で提供しています。\",\n    \"from\": \" 出処\",\n    \"sw_camp\": \"未来創造科学部のSW創造力キャンプ\",\n    \"elementary\": \"小学校\",\n    \"middle\": \"中学校\",\n    \"grades\": \"学年\",\n    \"lesson\": \"回分\",\n    \"sw_contents_one\": \"5回分の内容で小学生がエントリーとフィジカルコンピューティングを体験できる教材です。生徒たちはエントリーの使用方法を学習し、イラストボードとストーリーの作成を行います。最後にはアドイノ教具を活用してキーボードを作成する活動を行います。\",\n    \"sw_camp_detail\": \"未来創造科学部のSW創造力キャンプ\",\n    \"sw_contents_two\": \"5回分の内容で中学生がエントリーとフィジカルコンピューティングを体験できる教材です。学生たちはエントリーの使用方法を学習し、迷路探しゲームとクイズプログラムを制作します。最後にはアドイノ教具を活用してキーボードで自動車を操縦する活動を行います。\",\n    \"sw_contents_three\": \"先生方が学校で始められるソフトウェア授業指導書です。バラエティ豊かなアンプラグド活動やTV番組「ソフトウェア、遊ぼう」を活用した授業指導案が入っています。\",\n    \"naver_sw\": \"NAVER ソフトウェア、遊ぼう\",\n    \"teacher_teaching\": \"教師用指導書 (小学校 5~6年生以上)\",\n    \"funny_sw\": \"楽しいSW遊び教室\",\n    \"sw_contents_four\": \"ソフトウェアを遊び感覚で楽しく学べる教材で、エントリーボードゲームをはじめバラエティ豊かなアンプラグド活動とエントリー学習モードでソフトウェアを制作する基本原理を学びます。基本原理の学習後、学生たちはエントリーでストーリー、ゲーム、芸術作品、応用プログラムを制作する方法を学び、自分が考えたソフトウェアを制作して発表することができる構成になっています。\",\n    \"ct_text_5\": \"教科書と共に育てるコンピューター的思考力\",\n    \"teacher_grade_5\": \"教員(小学校5年生)\",\n    \"ct_text_5_content\": \"実生活の問題を解決しようというテーマで用意された8種類の学習コンテンツが入っている教師用指導案です。各コンテンツは改正された教育課程を反映した他教科との連携により、様々な問題に遭遇しても解決できるように設計されました。子どもたちがコンピューター的思考力を備えた融合型人材になれるよう、今すぐ適用してください!\",\n    \"ct_text_6\": \"教科書と一緒に養うコンピューター的思考力\",\n    \"teacher_grade_6\": \"教員(小学校6年生)\",\n    \"ct_text_6_content\": \"実生活の問題を解決しようというテーマで用意された8種類の学習コンテンツが入っている教師用指導案です。各コンテンツは改正された教育課程を反映した他教科との連携により、様々な問題に遭遇しても解決できるように設計されました。子どもたちがコンピューター的思考力を備えた融合型人材になれるよう、今すぐ適用してください!\",\n    \"sw_use\": \"すべての教材は、非営利目的に限り著作者を明らかにして自由に利用できます。\",\n    \"title\": \"タイトル\",\n    \"writer\": \"作成者\",\n    \"view\": \"見る\",\n    \"date\": \"登録日\",\n    \"find_id_pwd\": \"IDとパスワードを忘れた場合\",\n    \"send_email\": \"メールアドレスにパスワード変更のためのリンクを送信いたしました。\",\n    \"user_not_exist\": \"存在しないメールアドレスです。\",\n    \"not_signup\": \"まだ会員ではありませんか?\",\n    \"send\": \"送信する\",\n    \"sensorboard\": \"ENTRY Sensor Board\",\n    \"physical_computing\": \"フィジカルコンピューティング\",\n    \"sensorboard_contents\": \"Using Arduino no longer requires building a circuit using lots of wires. With ENTRY Board, you can use LED lights, temperature, sound, light sensors, a slider, and switches by simply mounting it onto an Arduino board. Now anyone can easily create their own unique projects using ENTRY Board!\",\n    \"entrybot_boardgame\": \"エントリーボットボードゲーム\",\n    \"unplugged\": \"アンプラグド活動\",\n    \"unplugged_contents\": \"楽しいボードゲームでコンピューターの作動原理を学習してみてください。ロボット犬のエントリーボットが停電した工場で必要なパーツを探して脱出できるように手伝う過程で、コンピューター専門家のように問題をとらえることができるようになります。\",\n    \"entrybot_cardgame\": \"エントリーボットカードゲーム : 爆弾大騒動\",\n    \"entrybot_cardgame_contents\": \"エントリーシティに突如現れた12種類の爆弾! 全ての爆弾を無事に解体することはできるでしょうか? 爆弾を1つずつ解体し、エントリーブロックと一緒にソフトウェアの原理を学んでみましょう!  順次、反復、条件を通して爆弾を1つずつ解体していけば、エントリーシティを救ったヒーローになれますよ!\",\n    \"basic_learn\": \"エントリー基本学習\",\n    \"basic_learn_contents\": \"エントリーを活用したバラエティ豊かな教育コンテンツを提供しています。\",\n    \"troubleshooting\": \"問題解決学習\",\n    \"playsoftware\": \"ソフトウェア、遊ぼう\",\n    \"make_own_lesson\": \"自分だけの授業を作成し、他の人と共有できます。\",\n    \"group_lecture\": \"クラス講義\",\n    \"group_curriculum\": \"クラス講義集\",\n    \"group_homework\": \"クラス課題\",\n    \"group_noproject\": \"展示された作品がありません。\",\n    \"group_nolecture\": \"作成された講義がありません。\",\n    \"group_nocurriculum\": \"作成された講義集がありません。\",\n    \"lecture_contents\": \"必要な機能のみ選択して、自分だけの授業を作成できます。\",\n    \"curriculum_contents\": \"複数の講義を1つの講義集としてまとめ、少しずつ進めて行ける授業を作成することができます。\",\n    \"grade_info\": \"学年情報\",\n    \"difficulty\": \"難易度\",\n    \"usage\": \"使用要素\",\n    \"learning_concept\": \"学習概念\",\n    \"related_subject\": \"連携教科\",\n    \"show_more\": \"もっと見る\",\n    \"close\": \"閉じる\",\n    \"latest\": \"最新順\",\n    \"viewCount\": \"照会数\",\n    \"viewer\": \"照会順\",\n    \"like\": \"いいね順\",\n    \"comment\": \"コメント順\",\n    \"entire_period\": \"すべての期間\",\n    \"today\": \"今日\",\n    \"latest_week\": \"1週間以内\",\n    \"latest_month\": \"1か月以内\",\n    \"latest_three_month\": \"3か月以内\",\n    \"current_password\": \"現在のパスワード\",\n    \"change_password\": \"パスワード変更\",\n    \"incorrect_password\": \"パスワードが一致しません。\",\n    \"incorrect_password_login\": \"IDまたはパスワードが違います。\",\n    \"suspension_user\": \"このアカウントは利用を停止されています。\",\n    \"blocked_user\": \"承認されていないユーザーです。\",\n    \"new_password\": \"新しいパスワード\",\n    \"password_option_1\": \"英数字を5文字以上組み合わせる必要があります。\",\n    \"again_new_password\": \"新しいパスワード再入力\",\n    \"enter_new_pwd\": \"新しいパスワードを入力してください。\",\n    \"confirm_new_pwd\": \"新しいパスワードを確認してください。\",\n    \"enter_new_pwd_again\": \"新しいパスワードを再入力してください。\",\n    \"password_match\": \"パスワードが一致しません。\",\n    \"incorrect_email\": \"このメールアドレスは無効です。\",\n    \"edit_button\": \"情報修正\",\n    \"edit_profile\": \"管理\",\n    \"my_project\": \"自分の作品\",\n    \"my_group\": \"自分のクラス\",\n    \"mark\": \"関心作品\",\n    \"prev_state\": \"前\",\n    \"profile_image\": \"自己紹介画像\",\n    \"insert_profile_image\": \"プロフィール画像を登録してください。\",\n    \"at_least_180\": \"180×180pxの画像を推奨します。\",\n    \"upload_image\": \"画像アップロード\",\n    \"about_me\": \"自己紹介\",\n    \"save_change\": \"変更内容を保存\",\n    \"basic_image\": \"デフォルト画像\",\n    \"profile_condition\": \"自己紹介を入力してください。50文字前後\",\n    \"profile_back\": \"戻る\",\n    \"make_project\": \"作品を作る\",\n    \"exhibit_project\": \"作品を展示する\",\n    \"art_list_shared\": \"個人\",\n    \"art_list_group_shared\": \"クラス\",\n    \"gl_mode_boost\": \"ブーストモード\",\n    \"gl_not_supported\": \"ブーストモードで実行できない環境です。\\n確認をクリックすると基本モードで実行されます。\",\n    \"view_project\": \"コードを見る\",\n    \"code_view\": \"コード詳細\",\n    \"noResult\": \"検索結果がありません。\",\n    \"comment_view\": \"コメント\",\n    \"upload_project\": \"コメントする\",\n    \"edit\": \"修正\",\n    \"save_complete\": \"保存\",\n    \"just_like\": \"いいね!\",\n    \"share\": \"共有\",\n    \"who_likes_project\": \"作品にいいね!した人\",\n    \"people_interest\": \"作品を関心に登録した人\",\n    \"none_person\": \"なし\",\n    \"inserted_date\": \"登録日\",\n    \"last_modified\": \"Last Modified\",\n    \"original_project\": \"オリジナル作品\",\n    \"for_someone\": \"さんの\",\n    \"original_project_deleted\": \"オリジナル作品が削除されました。\",\n    \"delete_project\": \"削除\",\n    \"delete_group_project\": \"リストから削除\",\n    \"currnet_month_time\": \"月\",\n    \"current_day_time\": \"日\",\n    \"game\": \"ゲーム\",\n    \"animation\": \"アニメーション\",\n    \"media_art\": \"メディアアート\",\n    \"physical\": \"フィジカル\",\n    \"etc\": \"その他\",\n    \"connected_contents\": \"連携コンテンツ\",\n    \"connected_contents_content\": \"エントリーと一緒に進められるバラエティ豊かなコンテンツをお楽しみください。初めてソフトウェアを学ぶ人の場合、楽しく簡単なボードゲームから、アドイノのようなフィジカルコンピューティングを活用した自分だけのハイクオリティな創作物を制作することができます。\",\n    \"basic_mission\": \"基本ミッション: エントリーボットの迷路ゲーム\",\n    \"basic_mission_content\": \"ロボット犬を作る工場で偶然停電が起き、1人で考えることができるようになったエントリーボット! 工場を脱出して自由の身になれるよう、エントリーボットを手伝ってあげてください!\",\n    \"application_mission\": \"応用ミッション: エントリーボットの宇宙旅行\",\n    \"write_article\": \"投稿する\",\n    \"write_contest\": \"Submit\",\n    \"view_all_articles\": \"すべての投稿を見る\",\n    \"view_own_articles\": \"自分の投稿を見る\",\n    \"view_qna_articles\": \"レスのないスレッド一覧\",\n    \"learning_materials\": \"教育資料\",\n    \"download_materials\": \"教育資料ダウンロード\",\n    \"download_button\": \"ダウンロード\",\n    \"download_all\": \"すべてダウンロード\",\n    \"ebs_software_first\": \"<ソフトウェア、遊ぼう>は、NAVERとEBSが共同制作した教育コンテンツです。ここではエントリーを活用して実際に簡単なプログラムを作成しながらソフトウェアの基礎原理を学ぶことができます。さらに、コンピューター科学に関する先行知識がなくても、動画を通して十分に楽しさと好奇心を感じながら進められるコンテンツが用意されています。\",\n    \"go_software\": \"「ソフトウェア、遊ぼう」へ移動\",\n    \"ebs_context\": \"EBS動画へ移動\",\n    \"ebs_context_hello\": \"EBSへ移動\",\n    \"category\": \"カテゴリー\",\n    \"add_picture\": \"画像添付\",\n    \"upload_article\": \"投稿をコメントする\",\n    \"list\": \"リスト\",\n    \"report\": \"通報する\",\n    \"upload\": \"コメントする\",\n    \"staff_picks\": \"スタッフのピックアップ\",\n    \"popular_picks\": \"人気作品\",\n    \"lecture_header_more\": \"もっと作ってみる\",\n    \"lecture_header_reset\": \"初期化\",\n    \"lecture_header_reset_exec\": \"初期化する\",\n    \"lecture_header_save\": \"保存\",\n    \"lecture_header_save_content\": \"学習内容を保存する\",\n    \"lecture_header_export_project\": \"自分の作品に保存する\",\n    \"lecture_header_undo\": \"取消\",\n    \"lecture_header_redo\": \"復元\",\n    \"lecture_er_bugs\": \"エラー報告\",\n    \"lecture_container_tab_object\": \"オブジェクト\",\n    \"lecture_container_tab_video\": \"講義動画\",\n    \"lecture_container_tab_project\": \"完成された作品\",\n    \"lecture_container_tab_help\": \"ブロックに関するヘルプ\",\n    \"illigal\": \"違法な内容または公序良俗に違反する活動\",\n    \"verbal\": \"暴言または個人情報を侵害する活動\",\n    \"commertial\": \"商業的な目的のある活動\",\n    \"explicit\": \"わいせつ物\",\n    \"other\": \"その他\",\n    \"check_one_more\": \"1つ以上表記してください。\",\n    \"enter_content\": \"その他の内容を入力してください。\",\n    \"report_result\": \"結果に対する回答をご希望の場合、メールアドレスを入力してください。\",\n    \"report_success\": \"通報が正常に処理されました。\",\n    \"etc_detail\": \"その他の項目を選択してから入力してください。\",\n    \"lecture_play\": \"講義を見る\",\n    \"list_view_link\": \"他の講義集を見る\",\n    \"lecture_intro\": \"講義紹介を見る\",\n    \"study_goal\": \"学習目標\",\n    \"study_description\": \"説明\",\n    \"study_created\": \"登録日\",\n    \"study_last_updated\": \"最終修正日\",\n    \"study_remove\": \"削除\",\n    \"study_group_lecture_remove\": \"リストから削除\",\n    \"study_group_curriculum_remove\": \"リストから削除\",\n    \"study_edit\": \"講義集修正\",\n    \"study_comments\": \"コメント\",\n    \"study_comment_post\": \"コメントする\",\n    \"study_comment_remove\": \"削除\",\n    \"study_comment_edit\": \"修正\",\n    \"study_comment_save\": \"保存\",\n    \"study_guide_video\": \"案内映像\",\n    \"study_basic_project\": \"基本作品\",\n    \"study_done_project\": \"完成作品を選択してください。\",\n    \"study_usage_element\": \"使用要素\",\n    \"study_concept_element\": \"適用概念\",\n    \"study_subject_element\": \"連携教科\",\n    \"study_computing_element\": \"コンピューティング要素\",\n    \"study_element_none\": \"なし\",\n    \"study_label_like\": \"いいね!\",\n    \"study_label_interest\": \"関心講義\",\n    \"study_label_share\": \"共有\",\n    \"study_label_like_people\": \"講座にいいね!した人\",\n    \"study_label_interest_people\": \"講座を関心に登録した人\",\n    \"study_related_lectures\": \"講義リスト\",\n    \"study_expand\": \"すべて見る\",\n    \"study_collapse\": \"減らす\",\n    \"aftercopy\": \"URLがコピーされました。\",\n    \"study_remove_curriculum\": \"講義集を削除しますか?\",\n    \"content_required\": \"内容を入力してください\",\n    \"upload_not_supported_file_msg\": \"このファイル形式には対応していません。\",\n    \"study_remove_lecture\": \"講義を削除しますか?\",\n    \"lecture_build\": \"講義を作成する\",\n    \"lecture_build_step1\": \"1. 講義を紹介するための情報を入力してください\",\n    \"lecture_build_step2\": \"2. 学習に使用される機能のみ選択してください\",\n    \"lecture_build_step3\": \"3. 情報がすべて正しく入力されているか確認してください\",\n    \"lecture_build_choice\": \"何をアップロードしますか?\",\n    \"lecture_build_project\": \"エントリー作品\",\n    \"lecture_build_video\": \"講義映像\",\n    \"lecture_build_grade\": \"推奨学年\",\n    \"lecture_build_goals\": \"学習目標\",\n    \"lecture_build_add_goal\": \"ここをクリックして目標を追加\",\n    \"lecture_build_attach\": \"ファイル添付\",\n    \"lecture_build_attach_text\": \"20MB以内のファイルをアップロードしてください。\",\n    \"lecture_build_assist\": \"サブ映像\",\n    \"lecture_build_youtube_url\": \"Youtube共有リンクを挿入してください。\",\n    \"lecture_build_project_done\": \"完成作品を選択してください。\",\n    \"lecture_build_scene_text1\": \"シーン機能をOFFにすると新しいシーンを追加したり\",\n    \"lecture_build_scene_text2\": \"削除することができません。\",\n    \"lecture_build_object_text\": \"「オブジェクトを追加する」をOFFにすると新しいオブジェクトを追加したり削除することができません。\",\n    \"lecture_build_blocks_text1\": \"学習に必要なブロックのみ選択してください。\",\n    \"lecture_build_blocks_text2\": \"選択しないブロックは非表示になります。\",\n    \"lecture_build_basic1\": \"学習を開始する際に使用したい作品を選択してください。\",\n    \"lecture_build_basic2\": \"学習者は選択した作品で学習を進めます。\",\n    \"lecture_build_help\": \"このヘルプをもう一度見たい時は押してください。\",\n    \"lecture_build_help_never\": \"今後表示しない\",\n    \"lecture_build_close\": \"閉じる\",\n    \"lecture_build_scene\": \"シーン1\",\n    \"lecture_build_add_object\": \"オブジェクトを追加する\",\n    \"lecture_build_start\": \"スタート\",\n    \"lecture_build_tab_code\": \"ブロック\",\n    \"lecture_build_tab_shape\": \"形\",\n    \"lecture_build_tab_sound\": \"サウンド\",\n    \"lecture_build_tab_attribute\": \"属性\",\n    \"lecture_build_tab_table\": \"Table\",\n    \"lecture_build_block_category\": \"ブロックカテゴリーを選択してください。\",\n    \"lecture_build_attr_all\": \"すべて\",\n    \"lecture_build_attr_var\": \"変数\",\n    \"lecture_build_attr_signal\": \"信号\",\n    \"lecture_build_attr_list\": \"リスト\",\n    \"lecture_build_attr_func\": \"関数\",\n    \"lecture_build_edit\": \"講義修正\",\n    \"lecture_build_remove\": \"削除\",\n    \"curriculum_build\": \"講義集を作成する\",\n    \"curriculum_step1\": \"1. 講義集を紹介する情報を入力してください。\",\n    \"curriculum_step2\": \"2. 講義集を構成する講義を選択してください。\",\n    \"curriculum_step3\": \"3. 講義集が正しく構成されているか確認してください。\",\n    \"curriculum_lecture_upload\": \"講義をコメントする\",\n    \"curriculum_lecture_edit\": \"講義編集\",\n    \"curriculum_lecture_open\": \"読み込む\",\n    \"group_lecture_add\": \"クラス講義を追加する\",\n    \"group_curriculum_add\": \"クラス講義集を追加する\",\n    \"group_lecture_delete\": \"削除\",\n    \"group_curriculum_delete\": \"削除\",\n    \"group_select\": \" \",\n    \"group_studentNo\": \"学籍番号\",\n    \"group_username\": \"名前\",\n    \"group_userId\": \"ID\",\n    \"group_tempPassword\": \"パスワード修正\",\n    \"group_gender\": \"性別\",\n    \"group_studentCode\": \"コード\",\n    \"group_viewWorks\": \"作品を見る\",\n    \"added_group_lecture\": \"講義が削除されました。\",\n    \"added_group_curriculum\": \"講義集が削除されました。\",\n    \"deleted_group_lecture\": \"講義が削除されました。\",\n    \"deleted_group_curriculum\": \"講義集が削除されました。\",\n    \"modal_my\": \"自分の\",\n    \"modal_interest\": \"関心\",\n    \"modal_project\": \"作品\",\n    \"section\": \"Chapter\",\n    \"connect_hw\": \"ハードウェア結合\",\n    \"connect_message\": \"%1に結合されました。\",\n    \"connect_fail\": \"ハードウェアの結合に失敗しました。結合プログラムがONになっているか確認してください。\",\n    \"interest_curriculum\": \"関心講義集\",\n    \"marked_curriculum\": \"関心講義集\",\n    \"searchword_required\": \"キーワードを入力してください。\",\n    \"file_required\": \"ファイルは必須入力項目です。\",\n    \"file_name_error\": \"正しいファイル名を入力してください。\",\n    \"file_upload_max_count\": \"1回につき、合計10件までアップロードできます。\",\n    \"image_file_only\": \"画像ファイルのみ登録できます。\",\n    \"file_upload_max_size\": \"10MB以下のみアップロードできます。\",\n    \"curriculum_modal_lectures\": \"自分の講義\",\n    \"curriculum_modal_interest\": \"関心講義\",\n    \"group_curriculum_modal_curriculums\": \"自分の講義集\",\n    \"group_curriculum_modal_interest\": \"関心講義集\",\n    \"picture_import\": \"模様インポート\",\n    \"picture_select\": \"模様選択\",\n    \"lecture_list_view\": \"他の講義を見る\",\n    \"play_software_2\": \"EBS「ソフトウェア、遊ぼう2」\",\n    \"play_software_2_content\": \"NAVERとEBSが共同制作した新たなストーリー、<ソフトウェア、遊ぼう>シーズン2をお楽しみください! 楽しい動画講義を通してソフトウェアの基本概念を学び、バラエティ豊かで興味深いテーマに沿って実生活の問題を解決することができます。放送映像と特別映像を見ながら楽しいプログラムを直接制作してみてください。ソフトウェア教育に初めてチャレンジする場合でも、簡単にソフトウェアと親しくなれますよ!\",\n    \"open_project_to_all\": \"公開\",\n    \"close_project\": \"非公開\",\n    \"category_media_art\": \"メディアアート\",\n    \"go_further\": \"さらに進む\",\n    \"marked_project\": \"関心作品\",\n    \"marked_group_project\": \"クラスの関心作品\",\n    \"basic\": \"基本\",\n    \"application\": \"応用\",\n    \"the_great_escape\": \"脱出冒険記\",\n    \"escape_guide_1\": \"ロボット犬を作る工場で偶然停電が起き、1人で考えることができるようになったエントリーボット! \",\n    \"escape_guide_1_2\": \" 工場を脱出して自由の身になれるようエントリーボットを手伝ってあげてください!\",\n    \"escape_guide_2\": \"エントリーボットが遠くまで行くには、修理しないといけない部分がたくさんあるよ。工場を脱出しながら体を修理するために必要なパーツを探してみよう! まだ体は完全じゃないけど、歩いたり走りながら方向を変えるぐらいはできるからね!\",\n    \"escape_guide_2_2\": \"学習目標: 順次的実行\",\n    \"escape_guide_3\": \"やっと工場から脱出したよ! だけど、村まではまだ遠いんだ。でも、体はある程度修理できてるから、同じことを繰り返しても壊れないはずだよ! ん? あのロボットは何だろ?\",\n    \"escape_guide_3_2\": \"学習目標: 反復文と条件文\",\n    \"escape_guide_4\": \"とうとう村の近くまで来たよ! さっきから同じことを何度も繰り返してたから、もう覚えちゃいそうだよ! これからは使うブロックを覚えておいて使うのがよさそうだね。ここでバッテリーさえ充電しておけば、これからはずっと自由に生きられるはずだよ。\",\n    \"escape_guide_4_2\": \"学習目標: 関数定義と呼び出し\",\n    \"space_travel_log\": \"宇宙旅行記\",\n    \"space_guide_1\": \"はるか遠い宇宙を探査するために旅立ったエントリーボット。ついに探査任務を終え故郷の星の地球に戻ろうとしているが、たくさんの石が地球に向かう道をふさいでいる!  エントリーボットが無事に地球に戻れるように手伝ってあげてください!\",\n    \"space_guide_2\": \"そろそろ地球に戻る時間だよ! 早く地球に帰って休みたいなあ!　前にある石がどうなっているのか確認して、どこに行けばいいのか教えてね! そしたら、僕は教えてくれた方向に動くからね!\",\n    \"space_guide_2_2\": \"学習目標: 条件文重複と論理演算\",\n    \"cfest_mission\": \"エントリー体験ミッション\",\n    \"maze_1_intro\": \"やあ、僕はエントリーボットだよ。ケガをした友達を救助したいんだけど、君の助けが必要なんだ。僕をサポートして友達を救助してほしい! まず、前に進むブロックを組み立ててからスタートを押してね\",\n    \"maze_1_title\": \"はじめ方\",\n    \"maze_1_content\": \"エントリーボットはどうすれば動きますか?\",\n    \"maze_1_detail\": \"1. ブロックリストからブロックを取り出して、「スタートをクリックしたとき」ブロックと繋げてみてね <br> 2. 全部組み立てたら、スタートを押してみて <br> 3. 僕は君が組み立てたブロックどおりに上から順番に動くからね\",\n    \"maze_2_intro\": \"おかげで最初の友達を無事に助けることができたよ! じゃあ、次の友達を助けてみようか? あっ! 前に蜂の巣があるよ! ジャンプするブロックを使って蜂の巣を避けて友達を助けよう。\",\n    \"maze_2_title_1\": \"障害物をジャンプする\",\n    \"maze_2_content_1\": \"障害物がある時はどうすればいいですか?\",\n    \"maze_2_detail_1\": \"道の途中では障害物に遭遇することがあるよ。<br>障害物が前にある時は、ジャンプするブロックを使う必要があるからね。\",\n    \"maze_2_title_2\": \"はじめ方\",\n    \"maze_2_content_2\": \"エントリーボットはどうすれば動きますか?\",\n    \"maze_2_detail_2\": \"1. ブロックリストからブロックを取り出して、「スタートをクリックした時」ブロックと繋げてみてね  <br> 2. 全部組み立てたら、スタートを押してみて <br> 3. 僕は君が組み立てたブロックどおりに上から順番に動くからね\",\n    \"maze_3_intro\": \"すごいね! 今から他の友達を助けに行こう~。今度はさっき助けた友達がくれたリピートブロックを使ってみようか? 「繰り返す」を使うと、同じ動作を簡単に繰り返すことができるよ! とりあえず繰り返す数字を変えてみる?\",\n    \"maze_3_title\": \"リピートブロック(1)\",\n    \"maze_3_content\": \"(3)「～回繰り返す」ブロックはどうやって使いますか?\",\n    \"maze_3_detail\": \"同じ行動を何度か繰り返すには、「~回繰り返す」ブロックを使えばいいよ。<br> 繰り返したいブロックを「～回繰り返す」の中に入れて反復回数を入力すればOKだよ\",\n    \"maze_4_intro\": \"やったね! もう助けなくちゃいけない友達ロボットも少なくなってきたよ。蜂の巣に触れないように「ジャンプする」を繰り返しながら友達のところに行けるようにしてね!\",\n    \"maze_4_title\": \"リピートブロック(1)\",\n    \"maze_4_content\": \"(3)「～回繰り返す」ブロックはどうやって使いますか?\",\n    \"maze_4_detail\": \"同じ行動を何度か繰り返すには、「~回繰り返す」ブロックを使えばいいよ。<br> 繰り返したいブロックを「～回繰り返す」の中に入れて反復回数を入力すればOKだよ\",\n    \"maze_5_intro\": \"すごいね! 今からはリピートブロックともしブロックを一緒に使ってみよう~。もしブロックを使うと、前に壁がある時に壁のない方向に回転できるよ。じゃあ、友達を助けに出発しようか?\",\n    \"maze_5_title_1\": \"もしブロック\",\n    \"maze_5_content_1\": \"もし~ならブロックはどのように動作しますか?\",\n    \"maze_5_detail_1\": \"「もし前に{画像}があるなら」ブロックを使うと、前に{画像}がある時にどんな行動をするのか決めることができるよ。<br>前に{画像}がある時だけブロックの中のブロックを実行して、<br>そうでない時は実行しないようになるんだ。\",\n    \"maze_5_title_2\": \"リピートブロック(2)\",\n    \"maze_5_content_2\": \"「~に会うまで繰り返す」ブロックはどうやって使いますか?\",\n    \"maze_5_detail_2\": \"「~まで繰り返す」を使うと、同じ行動をいつまで繰り返すかを決められるよ。<br> 繰り返したいブロックを「~まで繰り返す」の中に入れればOKだよ。<br>すると、{画像}みたいにタイルの上にいる場合、繰り返しがストップするからね。\",\n    \"maze_6_intro\": \"もう最後の友達だよ! さっきやったみたいにやれば、うまくいくはず! じゃあ、最後の友達を助けに行こうか?\",\n    \"maze_6_title_1\": \"もしブロック\",\n    \"maze_6_content_1\": \"もし~ならブロックはどのように動作しますか?\",\n    \"maze_6_detail_1\": \"「もし前に{画像}があるなら」ブロックを使うと、前に{画像}がある時にどんな行動をするのか決めることができるよ。<br>前に{画像}がある時だけブロックの中のブロックを実行して、<br>そうでない時は実行しないようになるんだ。\",\n    \"maze_6_title_2\": \"リピートブロック(2)\",\n    \"maze_6_content_2\": \"「~に会うまで繰り返す」ブロックはどうやって使いますか?\",\n    \"maze_6_detail_2\": \"「~まで繰り返す」を使うと、同じ行動をいつまで繰り返すかを決められるよ。<br> 繰り返したいブロックを「~まで繰り返す」の中に入れればOKだよ。<br>すると、{画像}みたいにタイルの上にいる場合、繰り返しがストップするからね。\",\n    \"maze_programing_mode_0\": \"ブロックコーディング\",\n    \"maze_programing_mode_1\": \"JavaScript\",\n    \"maze_operation1_title\": \"ステップ1 – JavaScriptモードについて\",\n    \"maze_operation1_1_desc\": \"僕はロボット犬のエントリーボットだよ。僕にコマンドしてミッションを解決できるように手伝ってね! ミッションは開始するたびに<span class=\\\"textShadow\\\">\\'目標\\'</span>から確認できるよ!\",\n    \"maze_operation1_2_desc\": \"ミッションを確認したら、<b>コマンド</b>をする必要があるよ <span class=\\\"textUnderline\\\">\\'コマンドリスト\\'</span>は、<b>コマンド</b>があるスペースだよ。<b>マウス</b>と<b>キーボード</b>で<b>コマンド</b>できるよ。<span class=\\\"textShadow\\\">マウス</span>ではコマンドリストにある<b>コマンド</b>をクリックしたり、<b>コマンド</b>を<span class=\\\"textUnderline\\\">\\'コマンド組立所\\'</span>に引きずって、僕に<b>コマンド</b>できるよ!\",\n    \"maze_operation1_2_textset_1\": \"マウスでコマンドをクリックする方法\",\n    \"maze_operation1_2_textset_2\": \"マウスでコマンドをドラッグ＆ドロップする方法\",\n    \"maze_operation1_3_desc\": \"<span class=\\\"textShadow\\\">キーボード</span>でコマンドするには、\\'コマンドリスト\\'にある<b>コマンドをキーボードで直接入力すればOKだよ。</b></br> コマンドを入力する時、コマンドの最後にある<span class=\\\"textShadow\\\">()と;</span>を忘れないように注意してね!\",\n    \"maze_operation1_4_desc\": \"ミッションを解決するためのコマンドを全部入力したら、<span class=\\\"textShadow\\\">[スタート]</span>を押せばOKだよ。</br> [スタート]を押すと、僕はコマンドどおりに動くからね!</br> それぞれのコマンドを知りたいなら、<span class=\\\"textShadow\\\">[コマンドヘルプ]</span>を確認してみてね!\",\n    \"maze_operation7_title\": \"7段階 - リピートコマンドについて(回数反復)\",\n    \"maze_operation7_1_desc\": \"<b>同じこと</b>を繰り返すのは本当に面倒くさいよね。</br>そんな時は<span class=\\\"textShadow\\\">反復</span>に関するコマンドを使えばもっと簡単にコマンドできるよ。\",\n    \"maze_operation7_2_desc\": \"では、繰り返されるコマンドを簡単に行う方法を見てみよう。</br>まず、リピートコマンドをクリックしてから<span class=\\\"textShadow\\\">i<1</span>の数字を変えて<span class=\\\"textShadow\\\">反復回数</span>を決めてから</br><span class=\\\"textShadow\\\">括弧({ })</span>の間にリピートコマンドを挿入すればOKだよ!\",\n    \"maze_operation7_3_desc\": \"例えば、このコマンド<span class=\\\"textBadge number1\\\"></span>はmove(); を10回繰り返して実行するんだ。</br><span class=\\\"textBadge number2\\\"></span>コマンドと同じコマンドだよ。\",\n    \"maze_operation7_4_desc\": \"このコマンドを使う時は<span class=\\\"textShadow\\\">{ }の中にリピートコマンド</span>がきちんと入力されているか、</br><span class=\\\"textShadow\\\">`;`</span>が抜けてないかをちゃんと確認してね!</br>このコマンドに関する詳しい説明は[コマンドヘルプ]で確認できるよ。\",\n    \"maze_operation7_1_textset_1\": \"同じコマンドを繰り返して使用する場合\",\n    \"maze_operation7_1_textset_2\": \"リピートコマンドを使用する場合\",\n    \"maze_operation7_2_textset_1\": \"反復回数\",\n    \"maze_operation7_2_textset_2\": \"リピートコマンド\",\n    \"maze_operation7_4_textset_1\": \"括弧({})がない場合\",\n    \"maze_operation7_4_textset_2\": \"セミコロン(;)がない場合\",\n    \"study_maze_operation8_title\": \"ステップ8 - リピートコマンドについて(回数繰り返し)\",\n    \"study_maze_operation16_title\": \"ステップ4 - リピートコマンドについて(条件繰り返し)\",\n    \"study_maze_operation1_title\": \"ステップ1 - リピートコマンドについて(回数繰り返し)\",\n    \"maze_operation9_title\": \"ステップ9 - リピートコマンドについて(条件繰り返し)\",\n    \"maze_operation9_1_desc\": \"前回は回数分繰り返すリピートコマンドについて学んだね。</br>今度は<span class=\\\"textShadow\\\">続けて繰り返すコマンド</span>を見てみよう。</br>このコマンドを使うとミッションが終了するまで<b>同じ行動</b>を続けて繰り返すようになるよ。</br>このコマンドも同じように括弧({ })の間にリピートコマンドを入れて使えるよ!\",\n    \"maze_operation9_2_desc\": \"例えば、このコマンド<span class=\\\"textBadge number1\\\"></span>はミッションを完了する時まで繰り返してmove(); right()を実行するんだ。</br><span class=\\\"textBadge number2\\\"></span>コマンドと同じコマンドだよ。\",\n    \"maze_operation9_3_desc\": \"このコマンドを使用する時も<span class=\\\"textShadow\\\">{ }の中にリピートコマンド</span>がきちんと入力されているか、</br><span class=\\\"textShadow\\\">`true`</span>が抜けてないかをきちんと確認してね!</br>このコマンドに関する詳しい説明は[コマンドヘルプ]で確認できるよ。\",\n    \"maze_operation9_1_textset_1\": \"リピートコマンド\",\n    \"maze_operation9_3_textset_1\": \"括弧({})がない場合\",\n    \"maze_operation9_3_textset_2\": \"セミコロン(;)がない場合\",\n    \"maze_operation9_3_textset_3\": \"trueがない場合\",\n    \"study_maze_operation3_title\": \"ステップ3 - リピートコマンドについて(条件繰り返し)\",\n    \"study_maze_operation4_title\": \"ステップ4 - 条件コマンドについて\",\n    \"study_ai_operation4_title\": \"ステップ4 - 条件コマンドとレーダーについて\",\n    \"study_ai_operation6_title\": \"ステップ6 - 重複条件文について\",\n    \"study_ai_operation7_title\": \"ステップ7 - 様々な比較演算について\",\n    \"study_ai_operation8_title\": \"ステップ8 - 物体レーダーについて\",\n    \"study_ai_operation9_title\": \"ステップ9 - アイテムを使用する\",\n    \"maze_operation10_title\": \"ステップ10 - 条件コマンドについて\",\n    \"maze_operation10_1_desc\": \"前回はミッションが終了するまで続けて繰り返すリピートコマンドについて学んだよね。</br>今度は特定の条件でのみ行動する<span class=\\\"textShadow\\\">条件コマンド</span>を見てみよう。</br><span class=\\\"textBadge number2\\\"></span>で見たように、条件コマンドを使うと<b>より効率的にコマンドすることができるよ。</b>\",\n    \"maze_operation10_2_desc\": \"条件コマンドは大きく<span class=\\\"textShadow\\\">「条件」</span>と<span class=\\\"textShadow\\\">「条件が発生した時に実行されるコマンド」</span>に分かれるんだ。</br>まず、<span class=\\\"textUnderline\\\">条件</span>部分を見てみよう。Ifの次に出てくる<span class=\\\"textUnderline\\\">( )部分</span>が条件を入力する部分だよ。</br><span class=\\\"textBadge number1\\\"></span>と同じコマンドを例として見てみよう。<span class=\\\"textUnderline\\\">if(front == \\“wall\\”)</span>は、もし自分の前に(front) \\\"wall(壁)\\\"があるならを意味するよ\",\n    \"maze_operation10_3_desc\": \"今から<span class=\\\"textUnderline\\\">`条件が発生した時に実行されるコマンド`</span>を見てみよう。</br>この部分は<span class=\\\"textShadow\\\">括弧{}</span>でくくられていて、条件が発生した時に括弧内のコマンドを実行するようになるよ!</br>条件が発生しなかった場合、この部分は無視して実行しないんだ。</br><span class=\\\"textBadge number1\\\"></span>のコマンドを例として見てみよう。条件はもし「自分の前に壁があるとき」で、</br><b>この条件が発生した時、僕は括弧内のコマンドright();のように右側に回転するよ!</b>\",\n    \"maze_operation10_4_desc\": \"<span class=\\\"textShadow\\\">条件コマンド</span>は、<span class=\\\"textShadow\\\">リピートコマンド</span>と一緒に使われる時が多いよ。</br>前にまっすぐ進み続け、壁が出てきた時にだけ回転したいなら、</br><span class=\\\"textUnderline pdb5\\\"><span class=\\\"textBadge number1\\\"></span><span class=\\\"textBadge number2\\\"></span><span class=\\\"textBadge number3\\\"></span>順序</span>のようにコマンドできるよ!\",\n    \"maze_operation10_1_textset_1\": \"<b>[一般コマンド]</b>\",\n    \"maze_operation10_1_textset_2\": \"<span class=\\\"textMultiline\\\">前に2マス進んで</br>右側に回転し、</br>前に3マス進んで</br>右側に回転し、前に…</span>\",\n    \"maze_operation10_1_textset_3\": \"<b>[条件コマンド]</b>\",\n    \"maze_operation10_1_textset_4\": \"<span class=\\\"textMultiline\\\">前に進み続け、</br><span class=\\\"textEmphasis\\\">「もし壁が出てきたら」</span></br>右側に回転するんだ~!</span>\",\n    \"maze_operation10_2_textset_1\": \"条件\",\n    \"maze_operation10_2_textset_2\": \"条件が発生した時に実行されるコマンド\",\n    \"maze_operation10_3_textset_1\": \"条件\",\n    \"maze_operation10_3_textset_2\": \"条件が発生した時に実行されるコマンド\",\n    \"maze_operation10_4_textset_1\": \"<span class=\\\"textMultiline\\\">ミッションが終了するまで</br>前に進み続ける。</span>\",\n    \"maze_operation10_4_textset_2\": \"<span class=\\\"textMultiline\\\">前に進み続け、</br>もし壁が出てきたら</span>\",\n    \"maze_operation10_4_textset_3\": \"<span class=\\\"textMultiline\\\">前に進み続け、</br>もし壁が出てきたら</br>右に回転する。</span>\",\n    \"study_maze_operation18_title\": \"ステップ6 - 条件コマンドについて\",\n    \"maze_operation15_title\": \"ステップ15 - 関数コマンドについて\",\n    \"maze_operation15_1_desc\": \"よく使うコマンドを毎回入力するのは本当に面倒くさいよね。</br>よく使う<span class=\\\"textUnderline\\\">コマンドをくくって名前</span>を付けて、</br><b>必要な時にそのコマンドリストを読み込めばずっと楽にコマンドできるよ!</b></br>こんなコマンドリストを<span class=\\\"textShadow\\\">`関数`</span>っていうんだ。今から関数コマンドについて詳しく見ていこう。\",\n    \"maze_operation15_2_desc\": \"関数コマンドはコマンドをくくる<b>「関数を作成する」過程</b>と</br>くくったコマンドを必要な時に使用する<b>「関数を読み込む」過程</b>があるんだ。</br>まず、関数を作成する過程を見てみよう。</br>関数を作るには、関数名とその関数に入るコマンドを入力する必要があるよ。</br><span class=\\\"textShadow\\\">function</span>を入力してから<span class=\\\"textShadow\\\">関数名</span>を決められるよ。ここでは<span class=\\\"textShadow\\\">promise</span>で作るよ。</br>関数名を作ったら、<span class=\\\"textUnderline\\\">()</span>を付けてね。その次に<span class=\\\"textUnderline\\\">括弧({})</span>を入力してね。</br>それから<span class=\\\"textUnderline\\\">この括弧の中に関数に入るコマンドを入力すれば</span>関数が作られるよ!\",\n    \"maze_operation15_3_desc\": \"このコマンドを見てみよう。僕は<span class=\\\"textShadow\\\">promise</span>という関数を作ったよ。</br>この関数を呼び出して実行すると、<span class=\\\"textUnderline\\\">括弧({})</span>の中にある</br>move();</br>move();</br>left();が実行されるんだ!\",\n    \"maze_operation15_4_desc\": \"関数を呼び出して実行するには、さっき作った<b>関数の名前を入力して、後に`();`を付ければOKだよ。</b></br>promise という名前で関数を作ったから、<span class=\\\"textShadow\\\">promise();</span>を入力すると前にくくっておいた</br>コマンドが実行されるんだ!</br><span class=\\\"number1 textBadge\\\"></span>のようにコマンドすると、<span class=\\\"number2 textBadge\\\"></span>のように動作するようになるよ!</br>関数コマンドを使用するには、<span class=\\\"number1 textBadge\\\"></span>のように関数を作成して関数を読み込む必要があるんだ!\",\n    \"maze_operation15_1_textset_1\": \"よく使うコマンドを確認する\",\n    \"maze_operation15_1_textset_2\": \"コマンドをくくって名前を付ける\",\n    \"maze_operation15_1_textset_3\": \"コマンドリストを読み込む\",\n    \"maze_operation15_2_textset_1\": \"コマンドリストの名前(関数名)\",\n    \"maze_operation15_2_textset_2\": \"くくるコマンド\",\n    \"maze_operation15_3_textset_1\": \"コマンドリストの名前(関数名)\",\n    \"maze_operation15_3_textset_2\": \"くくるコマンド\",\n    \"maze_operation15_4_textset_1\": \"関数を作成する\",\n    \"maze_operation15_4_textset_2\": \"関数を読み込む\",\n    \"maze_operation15_4_textset_3\": \"実際の状況\",\n    \"maze_object_title\": \"オブジェクト情報\",\n    \"maze_object_parts_box\": \"パーツボックス\",\n    \"maze_object_trap\": \"落とし穴\",\n    \"maze_object_monster\": \"モンスター\",\n    \"maze_object_obstacle1\": \"障害物\",\n    \"maze_object_obstacle2\": \"bee\",\n    \"maze_object_obstacle3\": \"banana\",\n    \"maze_object_friend\": \"友達\",\n    \"maze_object_wall1\": \"wall\",\n    \"maze_object_wall2\": \"wall\",\n    \"maze_object_wall3\": \"wall\",\n    \"maze_object_battery\": \"バッテリー\",\n    \"maze_command_ex\": \"例\",\n    \"maze_command_title\": \"コマンドヘルプ\",\n    \"maze_command_move_desc\": \"エントリーボットを1マス前に移動させます。\",\n    \"maze_command_jump_desc\": \"下の画像のような障害物の前で障害物をジャンプします。</br><div class=\\\"obstacleSet\\\"></div>\",\n    \"maze_command_jump_desc_elec\": \"下の画像のような障害物の前で障害物をジャンプします。</br><div class=\\\"obstacle_elec\\\"></div>\",\n    \"maze_command_right_desc\": \"現在位置から右側に90度回転します。\",\n    \"maze_command_left_desc\": \"現在位置から左側に90度回転します。\",\n    \"maze_command_for_desc\": \"括弧<span class=\\\"textShadow\\\">{}</span>内にあるコマンドを<span class=\\\"textShadow\\\">入力した回数</span>だけ繰り返して実行します。\",\n    \"maze_command_while_desc\": \"ミッションが終了するまで括弧<span class=\\\"textShadow\\\">{}</span>内にあるコマンドを続けて繰り返して実行します。\",\n    \"maze_command_slow_desc\": \"下の画像のようなスピードバンプをジャンプします。</br><div class=\\\"hump\\\"></div>\",\n    \"maze_command_if1_desc\": \"条件<span class=\\\"textShadow\\\">「目の前に壁があるとき」</span>が発生した際、</br>括弧<span class=\\\"textShadow\\\">{}</span>内にあるコマンドを実行します。\",\n    \"maze_command_if2_desc\": \"条件<span class=\\\"textShadow\\\">「目の前に蜂の巣があるとき」</span>が発生した際、</br>括弧<span class=\\\"textShadow\\\">{}</span>内にあるコマンドを実行します。\",\n    \"maze_command_if3_desc\": \"条件<span class=\\\"textShadow\\\">「目の前にバナナがあるとき」</span>が発生した際、</br>括弧<span class=\\\"textShadow\\\">{}</span>内にあるコマンドを実行します。\",\n    \"maze_command_promise_desc\": \"promise という<span class=\\\"textShadow\\\">関数</span>を作成して実行すると、括弧<span class=\\\"textShadow\\\">{}</span>内に</br>あったコマンドを実行します。\",\n    \"perfect\": \"わぁ、完璧だよ!  \",\n    \"succeeded_using_blocks\": \" 個のブロックを使用して成功したよ!\",\n    \"succeeded_using_commands\": \" のコマンドを使用して成功したよ!\",\n    \"awesome\": \"すごいね!\",\n    \"succeeded_go_to_next\": \"個のブロックだけで成功したよ! <br> 次のステップに行こう。\",\n    \"good\": \"よし! \",\n    \"but\": \"<br>けどね、\",\n    \"try_again\": \"　個のブロックだけで成功させる方法もあるよ。<br>もう一度チャレンジしてみない?\",\n    \"try_again_commands\": \" のコマンドだけで成功する方法もあるよ。<br>もう一度チャレンジしてみない?\",\n    \"cfest_success\": \"すごいね! おかげで友達を助けることができたよ! <br>おそらく君は優れたプログラマーなんだね! <br> また後で会おう~!\",\n    \"succeeded_and_cert\": \"個のブロックだけで成功したよ! <br>証明書をもらいに行こう。\",\n    \"cause_msgs_1\": \"うわっ、前に進めない場所だったよ。やり直そう。\",\n    \"cause_msgs_2\": \"うわーん。ただの道にはジャンプする場所がないよ。やり直そう。\",\n    \"cause_msgs_3\": \"あいたたた、痛い。ジャンプしなくちゃいけない場所だったよ。やり直そう。\",\n    \"cause_msgs_4\": \"残念だけど、今回のステップでは絶対に下のブロックを使わなくちゃいけないんだ。<br>やり直してみる?\",\n    \"cause_msgs_5\": \"大変だ、実行するブロックが全部なくなっちゃったよ。やり直そう。\",\n    \"cause_msgs_6\": \"大変だ、実行するコマンドが全部なくなっちゃったよ。やり直そう。\",\n    \"close_experience\": \"体験<br>終了\",\n    \"replay\": \"やり直す\",\n    \"go_to_next_level\": \"次の段階へ\",\n    \"move_forward\": \"前に1マス移動\",\n    \"turn_left\": \"左側\",\n    \"turn_right\": \"右側\",\n    \"turn_en\": \" \",\n    \"turn_ko\": \"に回転\",\n    \"jump_over\": \"ジャンプする\",\n    \"when_start_is_pressed\": \"スタートをクリックしたとき\",\n    \"repeat_until_ko\": \"出会うまで繰り返す\",\n    \"repeat_until_en\": \" \",\n    \"repeat_until\": \"出会うまで繰り返す\",\n    \"if_there_is_1\": \"もし前に\",\n    \"if_there_is_2\": \"あるなら\",\n    \"used_blocks\": \"使用ブロック\",\n    \"maximum\": \"目標ブロック\",\n    \"used_command\": \"使用コマンド数\",\n    \"maximum_command\": \"目標コマンド数\",\n    \"block_box\": \"ブロックリスト\",\n    \"block_assembly\": \"ブロック組立所\",\n    \"command_box\": \"コマンドリスト\",\n    \"command_assembly\": \"コマンド組立所\",\n    \"start\": \"スタート\",\n    \"engine_running\": \"実行中\",\n    \"engine_replay\": \"戻る\",\n    \"goto_show\": \"見に行く\",\n    \"make_together\": \"共に制作するエントリー\",\n    \"make_together_content\": \"エントリーは学校の先生方と学生たちが一緒に考えながら作成していきます。\",\n    \"project_nobody_like\": \"この作品が気に入ったら、「いいね!」を押してください。\",\n    \"project_nobody_interest\": \"「関心作品」を押すと、マイページで閲覧することができます。\",\n    \"lecture_nobody_like\": \"この講義が気に入ったら、「いいね!」を押してください。\",\n    \"lecture_nobody_interest\": \"「関心講義」を押すと、マイページで閲覧することができます。\",\n    \"course_nobody_like\": \"この講義集が気に入ったら、「いいね」を押してください。\",\n    \"course_nobody_interest\": \"「関心講義集」を押すと、マイページで閲覧することができます。\",\n    \"before_changed\": \"変更前\",\n    \"after_changed\": \"変更後\",\n    \"from_changed\": \"(2016年4月17日より ) \",\n    \"essential\": \"必須\",\n    \"access_term_title\": \"こんにちは。エントリー教育研究所です。 <br>エントリーをご愛顧いただいている皆様に御礼申し上げます。<br>エントリー教育研究所ウェブサイトの利用規約が<br> 2016年4月17日付で以下のように改定されましたのでご報告いたします。 \",\n    \"member_info\": \"会員案内\",\n    \"personal_info\": \"個人情報の取り扱いに同意します。\",\n    \"option\": \"選択\",\n    \"news\": \"最新情報\",\n    \"edu_material\": \"教育資料\",\n    \"latest_news\": \"最近のニュース\",\n    \"edu_data\": \"教育資料\",\n    \"training_program\": \"研修支援\",\n    \"footer_phrase\": \"エントリーは、誰でも無料でソフトウェア教育を受けられるように開発された非営利教育プラットフォームです。\",\n    \"footer_use_free\": \"エントリー教育研究所のすべての著作物は、教育的目的に限り出処を明らかにして自由に利用できます。\",\n    \"footer_description_1\": \"エントリーは非営利教育プラットフォームであり、エントリー内の著作物はすべて教育的目的に限り出処を明らかにして自由に利用できます。\",\n    \"footer_description_2\": \" \",\n    \"nonprofit_platform\": \"非営利教育プラットフォーム\",\n    \"this_is\": \"です。\",\n    \"privacy\": \"プライバシーポリシー\",\n    \"entry_addr\": \"京畿道 城南市 盆唐區 佛亭路 6 NAVER グリーンファクトリー16階\",\n    \"entry_addr_additional_phone\": \"02-6202-9783\",\n    \"entry_addr_additional_email\": \"entry@connect.or.kr\",\n    \"entry_addr_additional_opensource\": \"Open Source License\",\n    \"phone\": \"電話番号\",\n    \"alert_agree_term\": \"利用規約に同意してください。\",\n    \"alert_private_policy\": \"個人情報の取り扱い規約に同意してください。\",\n    \"agree\": \"同意\",\n    \"optional\": \"選択\",\n    \"start_software\": \"ソフトウェア教育の第一歩\",\n    \"analyze_procedure\": \"手順\",\n    \"analyze_repeat\": \"反復\",\n    \"analyze_condition\": \"分岐\",\n    \"analyze_interaction\": \"相互作用\",\n    \"analyze_dataRepresentation\": \"データ表現\",\n    \"analyze_abstraction\": \"抽象化\",\n    \"analyze_sync\": \"並列及び同期化\",\n    \"jr_intro_1\": \"やあ! 僕はジュニだよ! 僕の友達のエントリーボットが右にいるんだ! 僕を友達のところに連れて行ってね!\",\n    \"jr_intro_2\": \"エントリーボットが左にいるよ! 左に行ってみよう。\",\n    \"jr_intro_3\": \"エントリーボットが上にいるよ! 友達に会えるように手伝って!\",\n    \"jr_intro_4\": \"早くエントリーボットに会いに行こう! 下の方向に行ってね~ \",\n    \"jr_intro_5\": \"わっ! 友達が遠く離れたところにいるよ。エントリーボットがいる場所まで案内してもらえるかな? \",\n    \"jr_intro_6\": \"あそこにエントリーボットがいるね。早く会いに行こう。\",\n    \"jr_intro_7\": \"きれいな花があるね。花を集めてエントリーボットのところに行こう!\",\n    \"jr_intro_8\": \"途中に花があるね! 花を集めてエントリーボットのところに行こう!\",\n    \"jr_intro_9\": \"エントリーボットが遠いところにいるね。一番早いルートでエントリーボットのところに行こう。\",\n    \"jr_intro_10\": \"エントリーボットに会いに行く途中、花を全部集めながら行こう。\",\n    \"jr_intro_11\": \"エントリーボットのところに行くには、右に5回も行かなきゃいけないよね? リピートブロックを使ってもっと簡単に行ってみよう。\",\n    \"jr_intro_12\": \"「繰り返す」を使ってエントリーボットに会いに行こう。\",\n    \"jr_intro_13\": \"今のブロックだと友達のところには行けないよ。繰り返す回数を変えてエントリーボットのところに行けるようにしてね。\",\n    \"jr_intro_14\": \"リピートブロックを使ってエントリーボットのところに連れて行ってね。\",\n    \"jr_intro_15\": \"エントリーボットがとても遠くにいるよね? でも、リピートブロックを使えば簡単にエントリーボットのところに行けるはずだよ。\",\n    \"jr_whats_ur_name\": \"証明書に記入する、きみのお名前は？\",\n    \"jr_down_cert\": \"証明書を受け取る\",\n    \"jr_popup_prefix_1\": \"よし! エントリーボットに会えたよ!\",\n    \"jr_popup_prefix_2\": \"わっ! エントリーボットに会えたよ! <br> でもね、もっと少ないブロックを使ってもエントリーボットに<br>会えるんだけど、もう一度やってみる? \",\n    \"jr_popup_prefix_3\": \"やった! カバンを準備したよ!\",\n    \"jr_popup_prefix_4\": \"わっ! カバンのある場所に来たよ! でもね、もっと少ないブロックを使ってもカバンの方に行けるんだけど、もう一度やってみる?\",\n    \"jr_popup_suffix_1\": \"ありがとう~。おかげでカバンを持って学校に行けたよ~。次に学校に行くときも一緒に行こうね~\",\n    \"jr_popup_suffix\": \"ありがとう~。おかげでエントリーボットと楽しく遊べたよ~。<br>次またエントリーボットと遊ぼうね~\",\n    \"jr_fail_dont_go\": \"わわっ、そこには行けないよ。行く道をもう一度教えて~\",\n    \"jr_fail_dont_know\": \"ん? 今からどこに行くの? どこに行くのかもっと教えて~\",\n    \"jr_fail_no_flower\": \"ここには花はないよ。花のある場所で使ってみよう~\",\n    \"jr_fail_forgot_flower\": \"あっ! エントリーボットにあげる花を忘れちゃったよ。花を集めてから行こう~\",\n    \"jr_fail_need_repeat\": \"リピートブロックがないよ! リピートブロックを使ってみよう~\",\n    \"jr_hint_1\": \"やあ! 僕はジュニだよ! 僕の友達のエントリーボットが右にいるんだ! 僕を友達のところに連れて行ってね!\",\n    \"jr_hint_2\": \"エントリーボットが左にいるよ! 左に行ってみよう。\",\n    \"jr_hint_3\": \"エントリーボットが上にいるよ! 友達に会えるように手伝って!\",\n    \"jr_hint_4\": \"早くエントリーボットに会いに行こう! 下の方向に行ってね~\",\n    \"jr_hint_5\": \"わっ! 友達が遠く離れたところにいるよ。エントリーボットがいる場所まで案内してもらえるかな?\",\n    \"jr_hint_6\": \"間違ったブロックのせいで友達に会いに行けないよ! 間違ったブロックを消してエントリーボットのところに行けるように手伝って!\",\n    \"jr_hint_7\": \"きれいな花があるね。花を集めてエントリーボットのところに行こう!\",\n    \"jr_hint_8\": \"途中に花があるね! 花を集めてエントリーボットのところに行こう!\",\n    \"jr_hint_9\": \"エントリーボットが遠いところにいるね。一番早いルートでエントリーボットのところに行こう。\",\n    \"jr_hint_10\": \"あっ、ブロックを間違って組み立てちゃったからうまく行けないね。途中で花を全部集めてエントリーボットに持っていけるように直してみよう。\",\n    \"jr_hint_11\": \"エントリーボットのところに行くには、右に5回も行かなきゃいけないよね? リピートブロックを使ってもっと簡単に行ってみよう。\",\n    \"jr_hint_12\": \"「繰り返す」を使ってエントリーボットに会いに行こう。\",\n    \"jr_hint_13\": \"今のブロックだと友達のところには行けないよ。反復回数を変えてエントリーボットのところに行けるようにしてね。\",\n    \"jr_hint_14\": \"リピートブロックを使ってエントリーボットのところに連れて行ってね。\",\n    \"jr_hint_15\": \"エントリーボットがすごく遠くにいるよね? でも、リピートブロックを使えば簡単にエントリーボットのところに行けるはずだよ。\",\n    \"jr_certification\": \"証明書\",\n    \"jr_congrat\": \"おめでとうございます!\",\n    \"jr_congrat_msg\": \"問題解決課程を無事修了しました。\",\n    \"jr_share\": \"共有\",\n    \"go_see_friends\": \"友達に会いに行きましょう~!\",\n    \"junior_naver\": \"JUNIOR NAVER\",\n    \"junior_naver_contents_1\": \"のオシャレなクマの「ジュニ」がエントリーに遊びにきました! \",\n    \"junior_naver_contents_2\": \"ですが、ジュニは道を探すのがまだ難しいみたいです。\",\n    \"junior_naver_contents_3\": \"ジュニがエントリーボットに会えるように進む方向を教えてください~\",\n    \"basic_content\": \"基礎\",\n    \"jr_help\": \"ヘルプ\",\n    \"help\": \"ヘルプ\",\n    \"cparty_robot_intro_1\": \"やあ、僕はエントリーボットだよ。僕はパーツを手に入れて体を直さなくちゃいけないんだ。前に進むブロックでパーツを手に入れられるように手伝ってくれ!\",\n    \"cparty_robot_intro_2\": \"よし! 前にもパーツがあるけど、今度は間違って行ってしまうと感電しちゃうみたいだね。ジャンプするブロックを使ってパーツのところまで連れて行ってくれ。\",\n    \"cparty_robot_intro_3\": \"すごい! あそこにもパーツがあるよ! 道はちょっと曲がりくねってるけど、回転するブロックを使えば十分行けるはず! \",\n    \"cparty_robot_intro_4\": \"よし、もう動くのはだいぶ楽になったよ! 今度は回転とジャンプを一緒に使ってあのパーツを手に入れよう! \",\n    \"cparty_robot_intro_5\": \"おかげで体がすごくよくなったよ! 今度は回転とジャンプを一緒に使う必要があるよ! さあ、行ってみよう!\",\n    \"cparty_robot_intro_6\": \"すごいね! もうかなり体がよくなったから、同じことを何回やっても大丈夫なはず! 一度繰り返すを使って進んでみよう!\",\n    \"cparty_robot_intro_7\": \"ん? 行く途中にジャンプしなくちゃいけない場所があるね! でも、繰り返すで十分に行けるはずだよ!\",\n    \"cparty_robot_intro_8\": \"そんな! 今度はパーツがずっと遠くにあるよ。でも、繰り返すを使えば簡単に行けるんだ! 早く手伝って!\",\n    \"cparty_robot_intro_9\": \"わあ~、体はもうほとんど直ったみたいだよ! 今度は繰り返すを利用してパーツを手に入れに行こう!\",\n    \"cparty_robot_intro_10\": \"すごいよ! もう最後のパーツさえあれば僕の体を完璧に直すことができるはず! 早く、繰り返すで手伝って!\",\n    \"cparty_car_intro_1\": \"やあ! 僕はエントリーボットだよ。車に乗って移動し続けるには燃料が必要なんだ! 前にある燃料を手に入れられるように手伝ってくれないかな?\",\n    \"cparty_car_intro_2\": \"よし! だけど、今度は道がまっすぐじゃないね! 左/右に回転するブロックでうまく運転して、一緒に燃料を手に入れに行こうか?\",\n    \"cparty_car_intro_3\": \"うまいね! 今度の道の前にはスピードバンプがあるよ。スピードを出して運転すると事故が起こるかもしれないから、ゆっくり進むブロックを使って燃料を手に入れに行こう!\",\n    \"cparty_car_intro_4\": \"やっほー、もう運転はだいぶ楽になったよ! この道路ではリピートブロックを使って燃料を補給しに行ってみようか?\",\n    \"cparty_car_intro_5\": \"わぁ、今度の道路はちょっと複雑そうだけど、前に進むと左/右に回転するブロックを繰り返しながら行けばOKだよ! 落ち着いて燃料のところまで行ってみよう\",\n    \"cparty_car_intro_6\": \"今度は道路に障害物があるから、うまく回らないといけなさそうだね。もし障害物が前にあったらどのようにすればいいか教えてね!\",\n    \"cparty_car_intro_7\": \"うん、うまいね! もう一度もしブロックを使って障害物を避けながら燃料を手に入れに行こう!\",\n    \"cparty_car_intro_8\": \"あっ、さっき見かけたスピードバンプが2つもあるよ。ゆっくり進むブロックを利用して安全に燃料を補給しに行こう!\",\n    \"cparty_car_intro_9\": \"複雑そうな道だけど、前に使ったリピートブロックともしブロックをうまく利用すれば十分運転できるよ。燃料を補給できるように手伝って!\",\n    \"cparty_car_intro_10\": \"本当にすごいね! ブロックの順序をうまく並べて、今から最後に残った燃料に向かって頑張って進んで行こう!\",\n    \"cparty_car_popup_prefix_1\": \"よし! 燃料を手に入れたよ!\",\n    \"cparty_car_popup_prefix_2\": \"わあ! 燃料を手に入れたよ! <br> でもね、もっと少ないブロックを使っても<br>燃料を手に入れられるんだけど、もう一度やってみる? \",\n    \"cparty_car_popup_prefix_2_text\": \"わあ! 燃料を手に入れたよ! <br> でもね、もっと少ないコマンドを使っても<br>燃料を手に入れられるんだけど、もう一度やってみる? \",\n    \"cparty_car_popup_suffix\": \"ありがとう~。おかげでバッテリーを全部手に入れることができたよ~。<br>また一緒に遊んでね~\",\n    \"all_grade\": \"全学年\",\n    \"grade_e3_e4\": \"小学校3 ~ 4年生以上\",\n    \"grade_e5_e6\": \"小学校5 ~ 6年生以上\",\n    \"grade_m1_m3\": \"中学校1 ~ 3年生以上\",\n    \"entry_first_step\": \"エントリーの第一歩\",\n    \"entry_monthly\": \"月刊エントリー\",\n    \"play_sw_2\": \"EBS ソフトウェア、遊ぼう2\",\n    \"entry_programming\": \"実践、プログラミング!\",\n    \"entry_recommanded_course\": \"エントリーのオススメコース\",\n    \"introduce_course\": \"誰でも簡単に見て真似しながら様々なソフトウェアを楽しく制作できる講義コースを紹介します。\",\n    \"all_free\": \"*講義動画、作る、教材などをすべて無料で提供しています。\",\n    \"cparty_result_fail_1\": \"わわっ、そこには行けないよ。道をもう一度教えて~\",\n    \"cparty_result_fail_2\": \"あいたたた、痛い。ジャンプしなくちゃいけない場所だったよ。やり直そう。\",\n    \"cparty_result_fail_3\": \"わあ、大変だ。下のブロックを使わなかったらとっても大変だね! 下のブロックで作り直してね。\",\n    \"cparty_result_fail_4\": \"ん? どこに進めばいいの? どこに進めばいいのかもっと教えてよ~\",\n    \"cparty_result_fail_5\": \"あっ! スピードバンプでは速度を落とさないといけないよ。ゆっくり進むブロックを使ってみてね~\",\n    \"cparty_result_success_1\": \"よし! パーツを手に入れたよ!\",\n    \"cparty_result_success_2\": \"わあ! 燃料を手に入れたよ! <br>でもね、もっと少ないブロックを使っても燃料を手に入れられるんだけど、もう一度やってみる? \",\n    \"cparty_result_success_2_text\": \"わあ! パーツを手に入れたよ! <br>でもねもっと少ないコマンドを使っても燃料を手に入れられるんだけど、もう一度やってみる? \",\n    \"cparty_result_success_3\": \"ありがとう~。おかげで体が完全に直ったよ~。また一緒に遊んでね~\",\n    \"cparty_insert_name\": \"名前を入力してください。\",\n    \"offline_file\": \"ファイル\",\n    \"offline_edit\": \"編集\",\n    \"offline_undo\": \"戻す\",\n    \"offline_redo\": \"再実行\",\n    \"offline_quit\": \"終了\",\n    \"select_one\": \"選択してください。\",\n    \"evaluate_challenge\": \"挑戦したミッションの難易度を評価してください。\",\n    \"very_easy\": \"とても簡単\",\n    \"easy\": \"簡単\",\n    \"normal\": \"普通\",\n    \"difficult\": \"難しい\",\n    \"very_difficult\": \"とても難しい\",\n    \"save_dismiss\": \"変更内容を保存していません。続けますか?\",\n    \"entry_info\": \"エントリー情報\",\n    \"actual_size\": \"実際のサイズ\",\n    \"zoom_in\": \"拡大\",\n    \"zoom_out\": \"縮小\",\n    \"cparty_jr_intro_1\": \"やあ! 僕はエントリーボットだよ! 学校にカバンを持っていけるように手伝って! \",\n    \"cparty_jr_intro_2\": \"カバンが僕の左にあるよ! 左に行ってみよう。\",\n    \"cparty_jr_intro_3\": \"カバンが上にあるよ! カバンを持っていけるように手伝ってね!\",\n    \"cparty_jr_intro_4\": \"早くカバンを取りに行こう! 下に行くんだよ~\",\n    \"cparty_jr_intro_5\": \"わっ! カバンが遠く離れた場所にあるよ。カバンがある場所まで案内してくれないかな?\",\n    \"cparty_jr_intro_6\": \"カバンがあるよ! 早く取りに行こう~\",\n    \"cparty_jr_intro_7\": \"道の上に鉛筆があるね。鉛筆を集めてカバンを取りに行こう!\",\n    \"cparty_jr_intro_8\": \"学校に行く途中に鉛筆があるよ! 鉛筆を集めてカバンを取りに行こう!\",\n    \"cparty_jr_intro_9\": \"カバンが遠く離れた場所にあるね。一番早いルートでカバンを取りに行こう。\",\n    \"cparty_jr_intro_10\": \"途中にある鉛筆をすべて集めてカバンを持っていこう!\",\n    \"cparty_jr_intro_11\": \"カバンを手に入れるには、右に5回も行かなくちゃいけないよね? リピートブロックを使ってもっと簡単に行ってみよう。\",\n    \"cparty_jr_intro_12\": \"「繰り返す」を使ってカバンを取りに行こう。\",\n    \"cparty_jr_intro_13\": \"今のブロックだと友達のところには行けないよ。反復回数を変えてエントリーボットのところに行けるようにしてね。\",\n    \"cparty_jr_intro_14\": \"リピートブロックを使ってカバンを取りに行ってね。\",\n    \"cparty_jr_intro_15\": \"学校がとーっても遠くにあるよね? でも、リピートブロックを使うと簡単に学校に到着できるんだ。\",\n    \"make_new_project\": \"新しい作品を作る\",\n    \"open_old_project\": \"保存された作品を読み込む\",\n    \"offline_download\": \"エントリーダウンロード\",\n    \"offline_release\": \"エントリーのオフラインエディターリリース!\",\n    \"offline_description_1\": \"エントリーのオフラインバージョンは\",\n    \"offline_description_2\": \"インターネットに接続されていない状態でも使用できます。\",\n    \"offline_description_3\": \"今すぐダウンロードして始めてください!\",\n    \"sw_week_2015\": \"2015ソフトウェア教育体験ウィーク\",\n    \"cparty_desc\": \"ワクワクするソフトウェアとの初対面\",\n    \"entry_offline_download\": \"エントリーオフライン\\nダウンロード\",\n    \"entry_download_detail\": \"ダウンロード\\nへ移動\",\n    \"offline_desc_1\": \"インターネットに接続せずに、エントリーを利用することができるオフラインバージョンです。\",\n    \"offline_desc_2\": \"今すぐダウンロードして始めてください!\",\n    \"download\": \"ダウンロード\",\n    \"version\": \"バージョン\",\n    \"file_size\": \"サイズ\",\n    \"update\": \"アップデート\",\n    \"use_range\": \"使用範囲\",\n    \"offline_desc_free\": \"エントリーオフラインは、企業と個人の方すべてが制限なく無料でご利用いただけます。\",\n    \"offline_required\": \"システム要件\",\n    \"offline_required_detail\": \"ハードディスクの空き容量1GB以上、Windows7またはMac OS 10.8以上\",\n    \"offline_notice\": \"インストールの前にお読みください\",\n    \"offline_notice_1\": \"1. バージョン\",\n    \"offline_notice_1_1\": \"ハードウェア接続ソフトが内蔵されています。\",\n    \"offline_notice_2\": \"2. ウェブブラウザは別途必要ありません。\",\n    \"offline_notice_3\": \"各バージョンの変更内容について\",\n    \"offline_notice_4\": \"各バージョンをダウンロード\",\n    \"offline_notice_5\": \"各バージョンの変更内容の詳細について\",\n    \"hardware_online_badge\": \"オンライン\",\n    \"hardware_title\": \"エントリーハードウェア接続ソフトをダウンロード\",\n    \"hardware_desc\": \"エントリーオンラインの「作品を作る」でハードウェアを接続してエントリーを利用する場合のみ、別途インストールする必要があります。\",\n    \"hardware_release\": \"ハードウェア接続ソフト変更内容の詳細は、次のアドレスで確認できます。\",\n    \"hardware_window_download\": \"Windows<br />ダウンロード\",\n    \"hardware_osx_download\": \"Mac<br />ダウンロード\",\n    \"cparty_jr_result_2\": \"ありがとう~。おかげでカバンを持って学校に来ることができたよ~ <br>次に学校に行くときも一緒に行こうね~\",\n    \"cparty_jr_result_3\": \"わあ! 学校まで来れたよ! <br>でももっと少ないブロックを使っても学校に行けるんだけど、<br>もう一度やってみる?\",\n    \"cparty_jr_result_4\": \"わっ! カバンを手に入れたよ!<br> でももっと少ないブロックを使ってもカバンを手に入れられるんだけど、<br>もう一度やってみる? \",\n    \"lms_no_class\": \"まだ作成したクラスがありません。\",\n    \"lms_create_class\": \"クラスを作成してください\",\n    \"lms_add_class\": \"クラス作成\",\n    \"lms_base_class\": \"基本\",\n    \"lms_delete_class\": \"削除\",\n    \"lms_my_class\": \"自分の\",\n    \"lms_grade_1\": \"小学校1\",\n    \"lms_grade_2\": \"小学校2\",\n    \"lms_grade_3\": \"小学校3\",\n    \"lms_grade_4\": \"小学校4\",\n    \"lms_grade_5\": \"小学校5\",\n    \"lms_grade_6\": \"小学校6\",\n    \"lms_grade_7\": \"中学校1\",\n    \"lms_grade_8\": \"中学校2\",\n    \"lms_grade_9\": \"中学校3\",\n    \"lms_grade_10\": \"一般\",\n    \"lms_add_groupId_personal\": \"先生から受け取ったクラスIDを入力して会員情報に追加してください。\",\n    \"lms_add_groupId\": \"クラスIDを追加する\",\n    \"lms_add_group_account\": \"クラスアカウント追加\",\n    \"lms_enter_group_info\": \"発行されたクラスIDとパスワードを入力してください。\",\n    \"lms_group_id\": \"クラスID\",\n    \"lms_group_pw\": \"パスワード\",\n    \"lms_group_name\": \"所属クラス名\",\n    \"personal_pwd_alert\": \"正しいパスワード形式を入力してください\",\n    \"personal_form_alert\": \"正しい形式で入力してください\",\n    \"personal_form_alert_2\": \"すべての入力フォームを作成してください\",\n    \"personal_no_pwd_alert\": \"パスワードを入力してください\",\n    \"select_gender\": \"性別を選択してください\",\n    \"enter_group_id\": \"クラスIDを入力してください\",\n    \"enter_group_pwd\": \"パスワードを入力してください\",\n    \"info_added\": \"追加されました\",\n    \"no_group_id\": \"クラスIDが存在しません\",\n    \"no_group_pwd\": \"パスワードが一致しません\",\n    \"lms_please_choice\": \"選択してください。\",\n    \"group_lesson\": \"自分のクラス講義\",\n    \"lms_banner_add_group\": \"クラス機能導入\",\n    \"lms_banner_entry_group\": \"エントリークラスを作成する\",\n    \"lms_banner_desc_1\": \"クラスの学生たちをエントリーに登録してください!\",\n    \"lms_banner_desc_2\": \"もっと簡単かつ便利にクラスの学生たちの作品を検索し、\",\n    \"lms_banner_desc_3\": \"成長する姿を確認できます。\",\n    \"lms_banner_download_manual\": \"マニュアルダウンロード\",\n    \"lms_banner_detail\": \"詳細\",\n    \"already_exist_email\": \"メールアドレスはすでに存在します。\",\n    \"same_registered_email\": \"メールアドレスはすでに存在します。\",\n    \"email_correnctly_please\": \"メールアドレスを正しく入力してください\",\n    \"remove_project\": \"作品を削除しますか?\",\n    \"study_lesson\": \"クラスで学習する\",\n    \"open_project\": \"作品を読み込む\",\n    \"make_group\": \"クラス作成\",\n    \"project_share\": \"作品を共有する\",\n    \"group_project_share\": \"クラスで共有する\",\n    \"group_discuss\": \"クラスに投稿する\",\n    \"my_profile\": \"マイページ\",\n    \"search_updated\": \"最新作品\",\n    \"search_recent\": \"照会数の多い最新作品\",\n    \"search_complexity\": \"制作に力を入れた最新作品\",\n    \"search_staffPicked\": \"スタッフのピックアップ作品\",\n    \"search_childCnt\": \"コピーが多い作品\",\n    \"search_likeCnt\": \"いいね!が多い最新作品\",\n    \"search_recentLikeCnt\": \"いいね!が多い最新作品\",\n    \"gnb_share\": \"共有する\",\n    \"gnb_community\": \"コミュニティ\",\n    \"lms_add_lectures\": \"講義をコメントする\",\n    \"lms_add_course\": \"講義集をコメントする\",\n    \"lms_add_homework\": \"課題をコメントする\",\n    \"remove_lecture_confirm\": \"講義を本当に削除しますか?\",\n    \"popup_delete\": \"削除する\",\n    \"remove_course_confirm\": \"講義集を本当に削除しますか?\",\n    \"lms_no_lecture_teacher_1\": \"追加された講義がありません。\",\n    \"lms_no_lecture_teacher_2\": \"クラス講義を追加してください。\",\n    \"gnb_download\": \"ダウンロード\",\n    \"lms_no_lecture_student_1\": \"まだアップロードされた講義がありません。\",\n    \"lms_no_lecture_student_2\": \"先生が講義をアップロードすると、\",\n    \"lms_no_lecture_student_3\": \"学習内容を確認できます。\",\n    \"lms_no_class_teacher\": \"まだ作成したクラスがありません。\",\n    \"lms_no_course_teacher_1\": \"追加された講義集がありません。\",\n    \"lms_no_course_teacher_2\": \"クラス講義集を追加してください。\",\n    \"lms_no_course_student_1\": \"まだアップロードされた講義集がありません。\",\n    \"lms_no_course_student_2\": \"先生が講義集をアップロードすると、\",\n    \"lms_no_course_student_3\": \"学習内容を確認できます。\",\n    \"lms_no_hw_teacher_1\": \"追加された課題がありません。\",\n    \"lms_no_hw_teacher_2\": \"クラス課題を追加してください。\",\n    \"lms_no_hw_student_1\": \"まだアップロードされた課題がありません。\",\n    \"lms_no_hw_student_2\": \"先生が課題をアップロードすると、\",\n    \"lms_no_hw_student_3\": \"学習内容を確認できます。\",\n    \"modal_edit\": \"修正する\",\n    \"modal_deadline\": \"締切日設定\",\n    \"modal_hw_desc\": \"詳細説明(選択)\",\n    \"desc_optional\": \" \",\n    \"modal_create_hw\": \"課題を作成する\",\n    \"vol\": \"回目\",\n    \"hw_title\": \"課題名\",\n    \"hw_description\": \"内容\",\n    \"deadline\": \"締切日\",\n    \"do_homework\": \"課題をする\",\n    \"hw_progress\": \"進行状況\",\n    \"hw_submit\": \"提出\",\n    \"view_list\": \"名簿を見る\",\n    \"view_desc\": \"内容を見る\",\n    \"do_submit\": \"提出する\",\n    \"popup_notice\": \"通知\",\n    \"no_selected_hw\": \"選択された課題がありません。\",\n    \"hw_delete_confirm\": \"選択した課題を本当に削除しますか?\",\n    \"hw_submitter\": \"課題提出者名簿\",\n    \"hw_student_desc_1\": \"*「提出する」を押して提出を完了するまでは何度でも修正できます。\",\n    \"hw_student_desc_2\": \"* 提出期限が過ぎると課題を提出できません。\",\n    \"popup_create_class\": \"クラス作成\",\n    \"class_name\": \"クラス名\",\n    \"image\": \"画像\",\n    \"select_class_image\": \"クラスの画像を選択してください。\",\n    \"type_class_description\": \"クラス紹介を入力\",\n    \"set_as_primary_group\": \"基本クラスに指定\",\n    \"set_primary_group\": \"指定\",\n    \"not_primary_group\": \"指定しない\",\n    \"type_class_name\": \"クラス名を入力してください。\",\n    \"type_class_description_long\": \"クラス紹介を入力してください。170文字以内\",\n    \"add_students\": \"学生を追加する\",\n    \"invite_students\": \"学生を招待する\",\n    \"invite_with_class\": \"1. クラスコードで招待する\",\n    \"invite_code_expiration\": \"コード有効期限\",\n    \"generate_code_button\": \"コード再発行\",\n    \"generate_code_desc\": \"学生のクラスコード入力方法\",\n    \"generate_code_desc1\": \"エントリーのホームページでログインしてください。\",\n    \"generate_code_desc2\": \"メニューバーで<自分のクラス>を選択してください。\",\n    \"generate_code_desc3\": \"<クラスコードを入力する>を押してクラスコードを入力してください。\",\n    \"invite_with_url\": \"2. クラスURLで招待する\",\n    \"copy_invite_url\": \"コピーする\",\n    \"download_as_pdf\": \"クラスアカウントをPDFでダウンロード\",\n    \"download_as_excel\": \"クラスアカウントをExcelでダウンロード\",\n    \"temp_password\": \"ワンタイムパスワード発行\",\n    \"step_name\": \"名前入力\",\n    \"step_info\": \"情報追加/修正\",\n    \"preview\": \"プレビュー\",\n    \"type_name_enter\": \"クラスに追加する学生の名前を入力してエンターキーを押してください。\",\n    \"multiple_name_possible\": \"複数の名前を入力できます。\",\n    \"id_auto_create\": \"学籍番号を別途修正しない場合、自動で作成されます。\",\n    \"student_id_desc_1\": \"クラスIDは別途入力する必要なく自動で作成されます。\",\n    \"student_id_desc_2\": \"ただし、エントリーにすでに会員登録している学生をクラスに追加する場合、学生のエントリーIDを\",\n    \"student_id_desc_3\": \"入力してください。その学生は、ログイン後にクラス招待を承認すると追加されます。\",\n    \"student_number\": \"学籍番号\",\n    \"temp_password_desc_1\": \"ワンタイムパスワードでログインした後、\",\n    \"temp_password_desc_2\": \"新規パスワードを再設定できるように案内してください。\",\n    \"temp_password_desc_3\": \"*発行されたワンタイムパスワードは一度しか確認できません。\",\n    \"temp_password_demo\": \"ログインできない案内用の例示アカウントです。\",\n    \"temp_works\": \"作品を見る\",\n    \"student_delete_confirm\": \"学生を本当に削除しますか?\",\n    \"no_student_selected\": \"選択された学生がいません。\",\n    \"class_assignment\": \"クラス課題\",\n    \"class_list\": \"クラスリスト\",\n    \"select_grade\": \"学年を選択してください。\",\n    \"add_project\": \"作品を共有する\",\n    \"no_project_display\": \"学生たちが展示している作品がありません。\",\n    \"plz_display_project\": \"自分の作品を展示してください。\",\n    \"refuse_confirm\": \"クラス招待を本当に拒否しますか?\",\n    \"select_class\": \"クラス選択\",\n    \"group_already_registered\": \"すでに入っているクラスです。\",\n    \"my_page_entry\": \"ENTRY\",\n    \"my_page_title\": \"マイページ -\",\n    \"my_classGroup_title\": \"私のクラス\",\n    \"my_classGroup_title_view\": \"自分のクラスを確認する\",\n    \"my_space_area\": \"自分だけのスペース\",\n    \"mon\": \"月\",\n    \"tue\": \"火\",\n    \"wed\": \"水\",\n    \"thu\": \"木\",\n    \"fri\": \"金\",\n    \"sat\": \"土\",\n    \"sun\": \"日\",\n    \"jan\": \"1月\",\n    \"feb\": \"2月\",\n    \"mar\": \"3月\",\n    \"apr\": \"4月\",\n    \"may\": \"5月\",\n    \"jun\": \"6月\",\n    \"jul\": \"7月\",\n    \"aug\": \"8月\",\n    \"sep\": \"9月\",\n    \"oct\": \"10月\",\n    \"nov\": \"11月\",\n    \"dec\": \"12月\",\n    \"plz_select_lecture\": \"講義を選択してください。\",\n    \"plz_set_deadline\": \"締切日を設定してください。\",\n    \"hide_entry\": \"エントリーを表示しない\",\n    \"hide_others\": \"その他を表示しない\",\n    \"show_all\": \"すべて見る\",\n    \"lecture_description\": \"先生方が直接作成するエントリーの学習スペースです。講義で作品例を見て作品を制作しながら学んでください。\",\n    \"curriculum_description\": \"学習の順番とテーマに沿って複数の講義が集められている学習スペースです。講義集の順番に合わせて少しずつ学んでください。\",\n    \"linebreak_off_desc_1\": \"テキストボックスのサイズが文字のサイズを決定します。\",\n    \"linebreak_off_desc_2\": \"内容は1行のみ作成できます。\",\n    \"linebreak_off_desc_3\": \"新しい文字が追加されると、テキストボックスの左右の長さが長くなります。\",\n    \"linebreak_on_desc_1\": \"テキストボックスのサイズが文字を入力できるスペースを決定します。\",\n    \"linebreak_on_desc_2\": \"内容を作成する時、エンターキーで改行できます。\",\n    \"linebreak_on_desc_3\": \"内容を作成または新しい文字を追加する時、長さがテキストボックスの横幅を超えると自動的に改行されます。\",\n    \"not_supported_text\": \"この書体は漢字に対応していません。\",\n    \"entry_with\": \"一緒に作るエントリー\",\n    \"ebs_season_1\": \"シーズン1を見に行く\",\n    \"ebs_season_2\": \"シーズン2を見に行く\",\n    \"hello_ebs\": \"ハロー! EBS ソフトウェア\",\n    \"hello_ebs_desc\": \"<ハロー! EBSソフトウェア> エントリーバージョンの両方向サービスをお楽しみください! \\n <ハロー! EBSソフトウェア>の動画講義を通して\\n ソフトウェアコーディングの基本概念を学習した後、両方向コーディングミッションにチャレンジしてください!\\n 放送では見られなかった<大.騒.動>友達の\\n裏話も見ることができます!\",\n    \"hello_ebs_sub_1\": \"EBS中学エントリーバージョンの両方向サービスを\",\n    \"hello_ebs_sub_2\": \"お楽しみください! \",\n    \"exhibit_4th_title\": \"4th Anniversary of Entry\",\n    \"exhibit_4th_subtitle\": \"Entry Project Contest\",\n    \"exhibit_4th_desc1\": \"We hold an Entry Project Contest \",\n    \"exhibit_4th_desc2\": \"to celebrate the 4th anniversary of entry.\",\n    \"exhibit_4th_desc3\": \"Show off your great project!\",\n    \"exhibit_4th_button\": \"View Details\",\n    \"visang_edu_entry\": \"ビサン教育　エントリーを学習する\",\n    \"cmass_edu_entry\": \"CMAS　エントリーを学習する\",\n    \"chunjae_edu_entry\": \"天才教科書　エントリーを学習する\",\n    \"kumsungemt_edu_entry\": \"ギムソン出版社 エントリーを学習する\",\n    \"kumsungMid_edu_entry\": \"ギムソン出版社 エントリーを学習する\",\n    \"gilbutEdu_edu_entry\": \"ギルバート出版社 エントリーを学習する\",\n    \"miraenCoding_edu_entry\": \"ミライエン エントリーを学習する\",\n    \"textbook_help_data\": \"助力資料\",\n    \"textbook_teaching_activity\": \"授業教案&活動誌\",\n    \"textbook_kyohacksa\": \"Kyohaksa\",\n    \"textbook_kumsung\": \"Kumsung Publishing\",\n    \"textbook_donga\": \"Dong-a Publishing\",\n    \"textbook_chunjae\": \"Chunjae Education\",\n    \"textbook_miraen\": \"Mirae-n\",\n    \"textbook_visang\": \"Visang\",\n    \"partner\": \"パートナー\",\n    \"project_term_popup_title\": \"作品公開に伴うエントリー著作権ポリシーに同意\",\n    \"project_term_popup_description_1\": \"作品公開のため\",\n    \"project_term_popup_description_2\": \"以下のポリシーを確認してください。\",\n    \"project_term_popup_description_3\": \" \",\n    \"project_term_popup_description_4\": \" \",\n    \"project_term_agree_1_1\": \"自分が作った作品及びそのソースコードの公開に同意します。\",\n    \"project_term_agree_2_1\": \"他人が自分の作品を利用することを許可します。\",\n    \"project_term_agree_2_2\": \"(コピー、配布、公衆送信を含む)\",\n    \"project_term_agree_3_1\": \"他人が自分の作品を修正することを許可します。\",\n    \"project_term_agree_3_2\": \"(リミックス、変形、2次著作物作成を含む)\",\n    \"agree_all\": \"すべて同意\",\n    \"select_login\": \"ログイン選択\",\n    \"select\": \"選択してください\",\n    \"with_login\": \"ログインして\",\n    \"without_login\": \"ログインせずに\",\n    \"start_challenge\": \"ミッションにチャレンジする\",\n    \"start_challenge_2\": \"ミッションにチャレンジする\",\n    \"if_not_save_not_login\": \"* ログインせずにミッションに参加すると、進行状況が保存されません。\",\n    \"if_not_member_yet\": \"エントリー会員でない場合は?\",\n    \"join_entry\": \"エントリー会員登録\",\n    \"learned_computing\": \"これまでソフトウェア教育を受けたことがありますか?\",\n    \"cparty_index_description_1\": \"ワクワクするソフトウェアとの初対面。\",\n    \"cparty_index_description_2\": \"ソフトウェアと楽しく遊んでいるうちにソフトウェアの原理も学べる上、考える力もグンとUP!\",\n    \"cparty_index_description_3\": \"エントリーを通してコーディングミッションにチャレンジし、証明書を受け取ってください。\",\n    \"cparty_index_description_4\": \"2015 Online Coding Partyは\",\n    \"cparty_index_description_5\": \"SW教育体験ウィーク\",\n    \"cparty_index_description_6\": \"の一環として、\",\n    \"cparty_index_description_7\": \"小学校コンピューティング教師協会\",\n    \"cparty_index_description_8\": \"と共同制作されました。\",\n    \"cparty_index_description_9\": \"2016 Online Coding Partyは\",\n    \"cparty_index_description_10\": \"2017 Online Coding Partyは\",\n    \"cparty_index_description_11\": \"「SW教育を準備する先生たちの会」\",\n    \"congratulation\": \"おめでとうございます!\",\n    \"warm_up\": \"体験\",\n    \"beginner\": \"入門\",\n    \"intermediate\": \"基本\",\n    \"advanced\": \"発展\",\n    \"applied\": \"応用\",\n    \"cert_msg_tail\": \"課程が無事修了しました。\",\n    \"cert_msg_head\": \" \",\n    \"maze_text_content_1\": \"やあ。僕はエントリーボットだよ。いま僕は工場から脱出しなくちゃいけないんだ! 脱出するには先に体を直さなくちゃいけなさそうだ。前にあるパーツを手に入れられるよう手伝ってくれないかな? move()\",\n    \"maze_text_content_2\": \"うん、とっても上手だね! おかげで体がだいぶ軽くなったよ! 今度もパーツボックスまで僕を移動させてね。だけど、途中に障害物もあるよ。障害物の前ではjump()\",\n    \"maze_text_content_3\": \"すごいよ! あそこにもパーツがあるね! 道はちょっと曲がりくねってるけど、右や左に回転できるright(); left(); コマンドを使えば十分行けるはず! \",\n    \"maze_text_content_4\": \"よし、もう動くのがだいぶ楽になったよ! 今度は今まで学んだコマンドを併せて使ってあのパーツボックスまで行ってみよう!\",\n    \"maze_text_content_5\": \"わあ、パーツが2つもあるね! 2つとも手に入れて行こう! そうすれば体を早く直せると思うよ!\",\n    \"maze_text_content_6\": \"今度が最後のパーツになるよ! あれさえあれば僕の体を完璧に直すことができるはず! 今回も手伝ってくれるよね?\",\n    \"maze_text_content_7\": \"おかげで体がとても良くなったよ! 今から同じことを数回繰り返しても大丈夫なはず。ん? ところで、前にいるあのロボットは何だろ? 手伝ってあげる必要がありそうだよ!　助けてあげよう! for コマンドを使ってあの友達のところに僕を連れて行って!\",\n    \"maze_text_content_8\": \"よし! おかげで友達ロボットを助け出せたよ! だけど、前にも助けが必要な友達がいるね。でも、今度は蜂の巣があるから気を付けて蜂の巣に触れないようにジャンプして行こう! できるよね? 今度もforコマンドを使って友達がいる場所まで僕を移動させてね!\",\n    \"maze_text_content_9\": \"今度はforコマンドの代わりにミッションが終了するまで同じことを繰り返すようにするwhileコマンドを使ってみて! 僕を友達のところに連れて行けばミッション完了だよ!\",\n    \"maze_text_content_10\": \"今度はifコマンドが出てきたね! Ifとwhileコマンドを使って僕がいつ、どの方向に回転するのか教えてね!\",\n    \"maze_text_content_11\": \"よし、さっきみたいにやってみようか? いつ左に回転するのか教えてほしいな。\",\n    \"maze_text_content_12\": \"今度は途中に蜂の巣(bee)があるね? いつジャンプすればいいのか教えてくれるかな?\",\n    \"maze_text_content_13\": \"あちこちに手助けが必要な友達がたくさんいるね! 全員のところに行って助けてあげよう!\",\n    \"maze_text_content_14\": \"わあ、今度も手助けが必要な友達がたくさんいるね。まず小さな四角形をターンするようにコマンドを作成して、作ったものを繰り返して友達全員を助けてあげよう。\",\n    \"maze_text_content_15\": \"長い間動いていたらもう疲れちゃったよ。よく使うコマンドをfunctionコマンドを使って関数として作成しておいたよ! 関数を使って僕をバッテリーのところまで移動させてね!\",\n    \"maze_text_content_16\": \"よし、いいね! じゃあ今度は関数に入るコマンドを挿入して僕をバッテリーのところまで移動させてね!\",\n    \"maze_text_content_17\": \"よし、今度は関数を作ってからそれを使ってバッテリーを手に入れるように助けてね! 関数を作る時はjump();をうまく混ぜてね!\",\n    \"maze_text_content_18\": \"今度は道が少し複雑だね。でも、いつleft();を使って、いつright();を使えばいいのかさえ教えてくれれば、バッテリーのところまで行けるはずだよ!\",\n    \"maze_text_content_19\": \"今度は関数があらかじめ決められているよ! でも関数だけ使ってバッテリーのところに行くのは難しいと思うよ。関数と他のコマンドを混ぜ合わせてバッテリーまで移動させてね!\",\n    \"maze_text_content_20\": \"よし! 今まで本当によく頑張ってくれたね。おかげで最後のバッテリーを補充さえすればこれからは充電する必要はなさそうだよ。関数を利用してあのバッテリーを手に入れて、僕が自由の身になれるように手伝って!\",\n    \"maze_content_1\": \"やあ! 僕はエントリーボットだよ。いま僕は工場から脱出しようとしてるんだけど、まずは体を直す必要がありそうなんだ。前にあるパーツを手に入れたいんだけど、手伝ってくれないかな? 前に進むブロックを組み立ててからスタートを押してみて。\",\n    \"maze_content_2\": \"うん、とっても上手だね! おかげで体がだいぶ軽くなったよ! 前にもパーツがあるけど、今度は道を間違えちゃうと感電しちゃいそうだね。障害物をジャンプするブロックを使ってパーツまで行ってみようか?\",\n    \"maze_content_3\": \"すごいよ! あそこにもパーツがあるね! 道はちょっと曲がりくねってるけど、回転するブロックを使えば十分行けるはず!  今度も手伝ってくれるよね?\",\n    \"maze_content_4\": \"よし、もう動くのはだいぶ楽になったよ! 今度は回転とジャンプを一緒に使ってあのパーツを手に入れよう! \",\n    \"maze_content_5\": \"わあ、パーツが2つもあるね! 2つとも手に入れて行こう! そうすれば体を早く直せると思うよ!\",\n    \"maze_content_6\": \"今度が最後のパーツになるよ! あれさえあれば僕の体を完璧に直すことができるはず! 今回も手伝ってくれるよね?\",\n    \"maze_content_7\": \"おかげで体がとても良くなったよ! 今からは同じことを数回繰り返しても大丈夫なはずだよ。ん? だけど、前にいるあのロボットは何だろ? 手伝ってあげる必要がありそうだよ!　助けてあげよう! 早く繰り返す数字を変えて、あの友達のところに僕を連れて行って!\",\n    \"maze_content_8\": \"よし! おかげで友達ロボットを助け出せたよ! だけど、前にも手助けが必要な友達がいるね。でも、今度は蜂の巣があるから気を付けて蜂の巣に触れないようにジャンプして行こう! できるよね?  じゃあ、さっきやったように繰り返すを使って友達のところに僕を連れて行ってくれるかな?\",\n    \"maze_content_9\": \"今度は数字だけ繰り返すのではなく、友達ロボットのところに行く時まで同じことを繰り返すことができるよ! 今回も友達を助けられるよう手伝ってね!\",\n    \"maze_content_10\": \"今度はもしブロックというのがあるね! もしブロックを使っていつ、どの方向に回転するのか教えてね!\",\n    \"maze_content_11\": \"よし、さっきみたいにやってみようか? いつ左に回転するのか教えてほしいな。\",\n    \"maze_content_12\": \"今度は途中に蜂の巣があるね? いつジャンプすればいいのか教えてくれるかな?\",\n    \"maze_content_13\": \"あちこちに手助けが必要な友達がたくさんいるね! 全員のところに行って助けてあげよう!\",\n    \"maze_content_14\": \"わあ、今回も手伝う必要のある友達がたくさんいるね。まず小さな四角をターンするようにコマンドを作成して、作ったものを繰り返して友達全員を助けてあげよう。\",\n    \"maze_content_15\": \"繰り返すを何度も繰り返してたから、よく使うブロックは覚えられそうだよ! 約束ブロックはいま僕が覚えたブロックだよ! ひとまず、ずっと動き回って疲れちゃったから、バッテリーを補充できるように「約束呼び出し」ブロックを使ってバッテリーを補充できるようにしてね!\",\n    \"maze_content_16\": \"よし、いいね! じゃあ今度は君がよく使うブロックを僕に教えてね! 約束定義ブロックの中によく使うブロックを入れておけばOKだよ!\",\n    \"maze_content_17\": \"よし、今回も約束を利用してバッテリーを手に入れるように助けてくれるよね? 約束にジャンプするをうまく混ぜてね!\",\n    \"maze_content_18\": \"今度は道が少し複雑だね。でもいつ左に回って、いつ右に回ればいいかを教えてくれれば充電できそうだよ。\",\n    \"maze_content_19\": \"今度は約束があらかじめ決められているよ! だけどすぐに約束を使うのはダメみたいだね。僕が行く道を見て約束を使えばバッテリーを補充できるみたいだけど、手伝ってくれるよね?\",\n    \"maze_content_20\": \"よし! 今まで本当によく頑張ってくれたね。おかげで最後のバッテリーを補充さえすればこれからは充電する必要はなさそうだよ。約束を利用してあのバッテリーを手に入れて、自由の身になれるように手伝ってくれるよね?\",\n    \"maze_content_21\": \"やあ、僕はエントリーボットだよ。たくさんの友達が僕の助けを必要としてるんだ。繰り返すを利用して友達を助けられるよう連れていってね!\",\n    \"maze_content_22\": \"ありがとう! 今度は蜂の巣をジャンプして友達を助けに行けるように手伝って!\",\n    \"maze_content_23\": \"よし! 今度は友達ロボットのところに行くまで繰り返すを利用して友達を助けられるよう手伝って!\",\n    \"maze_content_24\": \"やあ! 僕はエントリーボットだよ。動きすぎちゃってバッテリーを補充しなくちゃいけないんだ。約束を読み込むを使ってバッテリーを補充できるように手伝って!\",\n    \"maze_content_25\": \"いいね! 今度は約束をいくつか読み込んでバッテリーがある場所まで行ってみよう!\",\n    \"maze_content_26\": \"よし! 今から約束するブロックを僕に教えてね! 約束するブロックの中によく使われるブロックを入れればOKだよ!\",\n    \"maze_content_27\": \"今はあらかじめ約束が決められているよ。だけど、約束を使うには僕が行く方向を見て約束を使う必要があるんだ。手伝ってくれるよね?\",\n    \"maze_content_28\": \"ついに最後だよ! 約束を利用して最後のバッテリーを手に入れられるように手伝って!\",\n    \"ai_content_1\": \"やあ! 僕はエントリーボットだよ。宇宙探査を終えて地球に戻ろうとしているんだけど、宇宙をさまよう石のせいでなかなか難しいね。僕が無事に家に帰れるように手伝ってくれないかな? 僕の宇宙船には僕の前と上、それと下に何がどれくらいの距離にいるのかを教えてくれるレーダーがあるんだ。君の判断に役立つはずだよ!\",\n    \"ai_content_2\": \"ありがとう! おかげで石を簡単に避けられたよ。だけど、今度はもっとたくさんの石があるよね? ブロックを並べて石をあちこちに避けてみよう!\",\n    \"ai_content_3\": \"いいね! 無事に石を避けられたよ。でも前を見て! さっきよりずっとたくさんの石があるよ。だけど心配する必要はないんだ。僕にはリピートブロックがあるからね。リピートブロックの中に動くブロックを入れれば目的地に到着するまで動き続けるからね!\",\n    \"ai_content_4\": \"すごいね! リピートブロックを使ったらたくさんの石を避けるのがずっと楽になったよ! だけど、こうやっていちいち操るのは疲れるね。僕にはレーダーがあるから、前に何が出てくるか分かるんだ。前に進んでいるときに前に石があったら避けられるようにしてくれるかな?\",\n    \"ai_content_5\": \"うまいね! ここまで来れてとっても嬉しいな。今度はレーダーが前にある物体までの距離を話してくれるよ。この機能を使って石を避けてみよう! 石までの距離が遠い時は前に進み続けて、距離が近づくと避けるようにしてくれるかな?\",\n    \"ai_content_6\": \"わ~すごいね! レーダーを活用して石をうまく避けているよ! 今度はいくつかのレーダーを使って、石をあちこちに避けながら進めるようにしてくれるかな?\",\n    \"ai_content_7\": \"ふ~。地球にだんだん近づいているね! 石を避ける時、できれば安全な道に行きたいな! 石がもっと遠くにある道がもっと安全なんだよね? 上方向レーダーと下方向レーダーを比較してもっと安全な方角に動くようにしてくれるかな?\",\n    \"ai_content_8\": \"無事に飛行できてるよ。ん?　ところであれは何だろ?　あれは僕がとても危険な状況で使える特別なエネルギーだよ! 今度はあのアイテムをすべて集めながら進もう!\",\n    \"ai_content_9\": \"すごいよ! 地球までもうすぐだよ。だけど、前を見ると石で道が完全に塞がれてて先に行けないよね?　でも心配する必要はないよ。アイテムをゲットして使うと、前にある塞いでいる石をなくすことができるんだ!\",\n    \"ai_content_10\": \"とうとうあそこに地球が見えたよ!　そ、そんな!　飛んでくる石を前もって見ることができないじゃん! 石がどうやって飛んでくるのか分からなくても今までみたいに動けばうまく避けられるはずだよ!　地球まで行くんだ!\",\n    \"maze_hints_title_1\": \"はじめ方\",\n    \"maze_hints_content_1\": \"エントリーボットはどうすれば動きますか?\",\n    \"maze_hints_detail_1\": \"1. ブロックリストからブロックを取り出して「スタートをクリックしたとき」にブロックを繋げてみてね <br> 2. 全部組み立てたら、スタートを押してみて <br> 3.僕は君が組み立てたブロックどおりに上から順番に動くからね\",\n    \"maze_hints_title_2\": \"障害物をジャンプする\",\n    \"maze_hints_content_2\": \"障害物がある時はどうすればいいですか?\",\n    \"maze_hints_detail_2\": \"道の途中で障害物と遭遇することがあるよ。<br>障害物が前にある時にはジャンプするブロックを使う必要があるよ。\",\n    \"maze_hints_title_3\": \"リピートブロック(1)\",\n    \"maze_hints_content_3\": \"(3)回リピートブロックはどうやって使いますか?\",\n    \"maze_hints_detail_3\": \"同じ行動を複数回繰り返すには、~回繰り返すブロックを使う必要があるよ。<br>繰り返したいブロックを～回繰り返すの中に入れて反復回数を入力すればOKだよ。\",\n    \"maze_hints_title_4\": \"リピートブロック(2)\",\n    \"maze_hints_content_4\": \"「~に会うまで繰り返す」ブロックはどうやって使いますか?\",\n    \"maze_hints_detail_4\": \"「~まで繰り返す」を使うと、同じ行動をいつまで繰り返すのか決められるよ。<br>繰り返したいブロックを~まで繰り返すの中に入れればOKだよ。<br>そうすれば、{画像}みたいにタイルの上にいる場合、繰り返しがストップするからね。\",\n    \"maze_hints_title_5\": \"もしブロック\",\n    \"maze_hints_content_5\": \"もし~ならブロックはどのように動作しますか?\",\n    \"maze_hints_detail_5\": \"「前に{画像}があるなら」ブロックを使うと、前に{画像}がある時にどんな行動をするのか決めることができるよ。<br>前に{画像}がある時だけブロックの中のブロックを実行して、<br>そうでない時は実行しないようになるんだ。\",\n    \"maze_hints_title_6\": \"リピートブロック(3)\",\n    \"maze_hints_content_6\": \"すべての~に会う時までブロックはどのように動作しますか?\",\n    \"maze_hints_detail_6\": \"すべての{タイル}に一度ずつ到着するまでその中にあるブロックを繰り返して実行するよ。<br>すべての{タイル}に一度ずつ到着すると繰り返しがストップするからね。\",\n    \"maze_hints_title_7\": \"特別ヒント\",\n    \"maze_hints_content_7\": \"難しすぎます。助けてください。\",\n    \"maze_hints_detail_7\": \"僕が行かなくちゃいけない道を詳しく見てみて。小さな四角が4つ見えるよね?<br>小さな四角を回るブロックを作って、繰り返すを使ってみたらどうかな?\",\n    \"maze_hints_title_8\": \"約束\",\n    \"maze_hints_content_8\": \"「約束する/約束を読み込む」は何ですか? どうやって使いますか?\",\n    \"maze_hints_detail_8\": \"僕を動かすためによく使うブロックのリストを「約束する」ブロックの下に並べて約束として作成できるよ。<br>一度作っておいた約束は「約束を読み込む」ブロックを使って何度も取り出して使えるんだ。\",\n    \"ai_hints_title_1_1\": \"ゲームの目標\",\n    \"ai_hints_content_1_1\": \"石を避けて右の惑星まで無事に移動できるように手伝ってください。\",\n    \"ai_hints_detail_1_1\": \"石を避けて右の惑星まで無事に移動できるように手伝ってください。\",\n    \"ai_hints_title_1_2\": \"はじめ方\",\n    \"ai_hints_content_1_2\": \"どうすれば始められますか?\",\n    \"ai_hints_detail_1_2\": \"1. ブロックリストからブロックを取り出して「スタートをクリックしたとき」にブロックを繋げてみてね <br> 2. 全部組み立てたら、スタートを押してみて <br> 3.僕は君が組み立てたブロックどおりに上から順番に動くからね\",\n    \"ai_hints_title_1_3\": \"動かす\",\n    \"ai_hints_content_1_3\": \"エントリーボットはどうすれば動きますか?\",\n    \"ai_hints_detail_1_3\": \"僕は上に行ったり、前や下に行ったりできるよ。<br>方向を決める時は、石のない方向に安全に行けるようにしてね。<br>僕を画面の外に行かせてしまうと宇宙の迷子になっちゃうから気を付けて!\",\n    \"ai_hints_title_2_1\": \"ゲームの目標\",\n    \"ai_hints_content_2_1\": \"リピートブロックで石を避けられるように手伝ってください。\",\n    \"ai_hints_detail_2_1\": \"リピートブロックで石を避けられるように手伝ってください。\",\n    \"ai_hints_title_2_2\": \"リピートブロック\",\n    \"ai_hints_content_2_2\": \"リピートブロックはどんなブロックですか?\",\n    \"ai_hints_detail_2_2\": \"ふ～。遠くまで行かなくちゃいけないのに、1つずつ組み立てるのは大変そうだね。リピートブロックを使用してみよう。<br>同じように繰り返されるブロックをリピートブロックでくくっておけば、とても長いブロックを短くすることができるよ!\",\n    \"ai_hints_content_3_1\": \"もしブロックで石を避けられるように手伝ってください。\",\n    \"ai_hints_title_3_2\": \"もしブロック(1)\",\n    \"ai_hints_content_3_2\": \"もし~ならブロックはどのように動作しますか?\",\n    \"ai_hints_detail_3_2\": \"もし前に~があるなら/そうでなければブロックを使うと、自分の目の前に石があるのか確認して違う動きができるよ~。<br>もし自分の目の前に石があるなら「もし」の下にあるブロックを実行して、石がないなら「そうでなければ」の中にあるブロックを実行するんだ。<br>僕の目の前に石がある時とない時でどう動くのかをちゃんと決めてね~\",\n    \"ai_hints_content_4_1\": \"レーダーの使用方法を身に着けて石を避けてみてください。\",\n    \"ai_hints_detail_4_1\": \"レーダーの使用方法を身に着けて石を避けてみてください。\",\n    \"ai_hints_title_4_2\": \"レーダー(1)\",\n    \"ai_hints_content_4_2\": \"レーダーとは何ですか? どうすれば活用できますか?\",\n    \"ai_hints_detail_4_2\": \"レーダーは、物体と自分が今どれだけ離れているかを教えてくれる機械だよ。<br>もし自分の前に何かがあるなら、前方向レーダーは'1'を表示するよ。<br>それと、レーダーは１人でいる時、もし&lt;true&gt;なら/そうでなければブロック<br>のように使えばとっても強力な道具になるんだ。<br>例えば、僕の前にある物体との距離が1より大きい時は安全に前に行けるけど、そうでなければ上と下、どちらかに避けることもできるよね。\",\n    \"ai_hints_title_4_3\": \"もしブロック(2)\",\n    \"ai_hints_content_4_3\": \"もし<true>ならブロックはどうやって使いますか?\",\n    \"ai_hints_detail_4_3\": \"もし&lt;true&gt;なら/ そうでなければブロックは&lt;true&gt;の中にある内容が合っていれば、「もし」の下にあるブロックを実行して、違うなら「そうでなければ」の下にあるブロックを実行するんだ。<br>どんな状況で違う動きをしたいのかをよく考えて、&lt;true&gt;の中に適切な判断条件を作成して入れてみてね。<br>判断条件を満たして「もし」の下にあるブロックを実行すると、「そうでなければ」の下にあるブロックは実行されないから覚えておいてね!\",\n    \"ai_hints_content_5_1\": \"レーダーを活用して石を簡単に避けられるように手伝ってください。\",\n    \"ai_hints_detail_5_1\": \"レーダーを活用して石を簡単に避けられるように手伝ってください。\",\n    \"ai_hints_title_5_2\": \"もしブロック(3)\",\n    \"ai_hints_content_5_2\": \"もしブロックが重なっている時はどのように動作しますか?\",\n    \"ai_hints_detail_5_2\": \"もし~ / そうでなければブロックの中にも、もし~/そうでなければブロックを入れられるよ! こうすれば、様々な状況で自分がどのように行動すればいいか決めることができるんだ。<br>例えば、前に石が道をふさいでいる時とそうでない時の行動を決めると、石がある時の状況でも状況に応じて上と下、どちらに行くのかを選択できるようになるよ\",\n    \"ai_hints_title_6_1\": \"レーダー(2)\",\n    \"ai_hints_content_6_1\": \"上方向レーダーと下方向レーダーの値を比較したい時はどうすればいいですか?\",\n    \"ai_hints_detail_6_1\": \"([上方向]レーダー)ブロックは、上の物体までの距離を意味するブロックだよ。<br>上と下のどちらが石からもっと遠いのかを確認する時に使えるブロックなんだ。<br>石を避ける道を選択する時は、遠く離れている方に避けるのが遠くまで行く時に有利なはずだよ~\",\n    \"ai_hints_content_7_1\": \"アイテムに向かって移動し、石を避けてください。\",\n    \"ai_hints_detail_7_1\": \"アイテムに向かって移動し、石を避けてください。\",\n    \"ai_hints_title_7_2\": \"物体名確認\",\n    \"ai_hints_content_7_2\": \"前に遭遇する物体の名前を確認すると何ができますか?\",\n    \"ai_hints_detail_7_2\": \"アイテムを獲得するためには、アイテムがどこにあるのか確認する必要があるよ。<br>そんな時に使えるブロックが[上]の物体は[アイテム]か?ブロックだよ。<br>このブロックを使うとアイテムがどの位置にあるかが分かるから、アイテムのある方向に動くようにブロックを組み立てられるよ。\",\n    \"ai_hints_content_8_1\": \"適切なアイテムを使って石を避けてみてください。\",\n    \"ai_hints_detail_8_1\": \"適切なアイテムを使って石を避けてみてください。\",\n    \"ai_hints_title_8_2\": \"アイテム\",\n    \"ai_hints_content_8_2\": \"アイテムはどのように手に入れて使いますか?\",\n    \"ai_hints_detail_8_2\": \"石をあちこちにうまく避けていても、前が石で全部ふさがれてしまっている…こんな時に抜け出す方法はないのかな? こんな時は、アイテム使用ブロックを使ってみてね。<br>このブロックは自分の前の石をすべて消すブロックだよ。<br>ただし、アイテムがなければブロックを使うことはできないよ。アイテムは画像を通過するとゲットできるんだ。\",\n    \"ai_hints_content_9_1\": \"今まで学んできたことをすべて生かして、できる限り遠くまで行ってください。\",\n    \"ai_hints_detail_9_1\": \"今まで学んできたことをすべて生かして、できる限り遠くまで行ってください。\",\n    \"ai_hints_title_9_2\": \"そして\",\n    \"ai_hints_content_9_2\": \"そしてブロックはどうやって使いますか?\",\n    \"ai_hints_detail_9_2\": \"そしてブロックには複数の条件を入れることができるよ。入れたすべての条件がtrueの時だけtrueになって、もしブロックの中にあるブロックが実行されるよ。1つでもfalseがあるとfalseと認識してその中にあるブロックは実行しないんだ\",\n    \"maze_text_goal_1\": \"move(); コマンドを使って、パーツボックスまで僕を移動させてね!\",\n    \"maze_text_goal_2\": \"jump(); コマンドで障害物を避けてパーツボックスまで僕を移動させてね!\",\n    \"maze_text_goal_3\": \"left(); right(); コマンドでパーツボックスまで僕を移動させてね!\",\n    \"maze_text_goal_4\": \"いろんなコマンドを使って、パーツボックスまで僕を移動させてね!\",\n    \"maze_text_goal_5\": \"2つのパーツボックス両方に行けるように僕を移動させてね!\",\n    \"maze_text_goal_6\": \"2つのパーツボックス両方に行けるように僕を移動させてね!\",\n    \"maze_text_goal_7\": \"for コマンドを使って、友達がいる場所まで僕を移動させてね!\",\n    \"maze_text_goal_8\": \"for コマンドを使って、障害物を避けながら友達がいる場所まで僕を移動させてね!\",\n    \"maze_text_goal_9\": \"whileコマンドを使って、友達がいる場所まで僕を移動させてね!\",\n    \"maze_text_goal_10\": \"ifとwhileコマンドを使って、友達がいる場所まで僕を移動させてね!\",\n    \"maze_text_goal_11\": \"ifとwhileコマンドを使って、友達がいる場所まで僕を移動させてね!\",\n    \"maze_text_goal_12\": \"ifとwhileコマンドを使って、友達がいる場所まで僕を移動させてね!\",\n    \"maze_text_goal_13\": \"whileとforコマンドを使って、友達全員に会えるように僕を移動させてね!\",\n    \"maze_text_goal_14\": \"whileとfor コマンドを使って、友達全員に会えるように僕を移動させてね!\",\n    \"maze_text_goal_15\": \"関数を呼び出してバッテリーまで僕を移動させてね!\",\n    \"maze_text_goal_16\": \"関数にコマンドを入れ、関数を呼び出してバッテリーまで僕を移動させてね!\",\n    \"maze_text_goal_17\": \"関数にコマンドを入れ、関数を呼び出してバッテリーまで僕を移動させてね!\",\n    \"maze_text_goal_18\": \"関数にコマンドを入れ、関数を呼び出してバッテリーまで僕を移動させてね!\",\n    \"maze_text_goal_19\": \"関数にコマンドを入れ、関数を呼び出してバッテリーまで僕を移動させてね!\",\n    \"maze_text_goal_20\": \"関数と他のコマンドを混ぜて使って、バッテリーまで僕を移動させてね!\",\n    \"maze_attack_range\": \"攻撃可能回数\",\n    \"maze_attack\": \"攻撃\",\n    \"maze_attack_both_sides\": \"両側攻撃\",\n    \"above_radar\": \"上方向レーダー\",\n    \"above_radar_text_mode\": \"radar_up\",\n    \"bottom_radar\": \"下方向レーダー\",\n    \"bottom_radar_text_mode\": \"radar_down\",\n    \"front_radar\": \"前方向レーダー\",\n    \"front_radar_text_mode\": \"radar_right\",\n    \"above_object\": \"上の物体\",\n    \"above_object_text_mode\": \"object_up\",\n    \"front_object\": \"前の物体\",\n    \"front_object_text_mode\": \"object_right\",\n    \"below_object\": \"下の物体\",\n    \"below_object_text_mode\": \"object_down\",\n    \"destination\": \"目的地\",\n    \"asteroids\": \"石\",\n    \"item\": \"アイテム\",\n    \"wall\": \"壁\",\n    \"destination_text_mode\": \"destination\",\n    \"asteroids_text_mode\": \"stone\",\n    \"item_text_mode\": \"item\",\n    \"wall_text_mode\": \"wall\",\n    \"buy_now\": \"購入へ移動\",\n    \"goals\": \"目標\",\n    \"instructions\": \"利用案内\",\n    \"object_info\": \"オブジェクト情報\",\n    \"entry_basic_mission\": \"エントリー基本ミッション\",\n    \"entry_application_mission\": \"エントリー応用ミッション\",\n    \"maze_move_forward\": \"前に1マス移動\",\n    \"maze_when_run\": \"スタートをクリックしたとき\",\n    \"maze_turn_left\": \"左側に回転\",\n    \"maze_turn_right\": \"右側に回転\",\n    \"maze_repeat_times_1\": \" \",\n    \"maze_repeat_times_2\": \"回繰り返す\",\n    \"maze_repeat_until_1\": \" \",\n    \"maze_repeat_until_2\": \"に会うまで繰り返す\",\n    \"maze_call_function\": \"約束を読み込む\",\n    \"maze_function\": \"約束する\",\n    \"maze_repeat_until_all_1\": \"すべて\",\n    \"maze_repeat_until_all_2\": \"会うまで繰り返す\",\n    \"command_guide\": \"コマンドヘルプ\",\n    \"ai_success_msg_1\": \"おかげで無事に地球に到着できたよ! ありがとう!\",\n    \"ai_success_msg_2\": \"よかった! おかげで\",\n    \"ai_success_msg_3\": \"回前に進むことができたから地球に救助信号を送ったよ! 今から地球から救助隊が来るはずだよ! ありがとう!\",\n    \"ai_success_msg_4\": \"いいね!\",\n    \"ai_cause_msg_1\": \"大変だ、どう動くべきなのかもっと話してもらえるかな?\",\n    \"ai_cause_msg_2\": \"うわっ! 本当に危なかったよ! もう一度チャレンジしてみよう\",\n    \"ai_cause_msg_3\": \"わわっ! 行くべき道から外れると宇宙の迷子になっちゃうよ。もう一度チャレンジしてみよう\",\n    \"ai_cause_msg_4\": \"すごく複雑だね。このブロックを使って動かしてみる?\",\n    \"ai_move_forward\": \"前に進む\",\n    \"ai_move_above\": \"上に行く\",\n    \"ai_move_under\": \"下に行く\",\n    \"ai_repeat_until_dest\": \"目的地に到達するまで繰り返す\",\n    \"ai_if_front_1\": \"もし前に\",\n    \"ai_if_front_2\": \"があるなら\",\n    \"ai_else\": \"そうでなければ\",\n    \"ai_if_1\": \"もし\",\n    \"ai_if_2\": \"なら\",\n    \"ai_use_item\": \"アイテム使用\",\n    \"ai_radar\": \"レーダー\",\n    \"ai_above\": \"上方向\",\n    \"ai_front\": \"前方向\",\n    \"ai_under\": \"下方向\",\n    \"ai_object_is_1\": \" \",\n    \"ai_object_is_2\": \"物体は\",\n    \"challengeMission\": \"他のミッションにチャレンジする\",\n    \"nextMission\": \"次のミッションにチャレンジする\",\n    \"withTeacher\": \"一緒に制作した先生方\",\n    \"host\": \"主催\",\n    \"support\": \"後援\",\n    \"subjectivity\": \"主管\",\n    \"learnMore\": \" もっと学びたいです\",\n    \"ai_object_is_3\": \"なのか?\",\n    \"stage_is_not_available\": \"このステージはまだ進められません。順番にステージを進めてください。\",\n    \"progress_not_saved\": \"進行状況は保存されません。\",\n    \"want_refresh\": \"このページを更新しますか?\",\n    \"monthly_entry_grade\": \"小学校3学年 ~ 中学校3学年\",\n    \"monthly_entry_contents\": \"毎月発刊される月刊エントリーと共にソフトウェア教育を始めてみましょう! 少しずつ進めて行けば簡単に身に着けられるよう、ライトに構成されています。基本、応用コンテンツに加え、さらにその先まで! 毎月アップデートされる8つのコンテンツと教材をお楽しみください~\",\n    \"monthly_entry_etc1\": \"*メインページの月刊エントリーオススメコースを活用すれば、もっと簡単に授業を進めることができます。\",\n    \"monthly_entry_etc2\": \"*月刊エントリーは学期中にのみ発刊されます。\",\n    \"group_make_lecture_1\": \"自分が作った講義がありません。\",\n    \"group_make_lecture_2\": \"「作成する>オープン講義を作成する」で\",\n    \"group_make_lecture_3\": \"クラスの学習内容に追加したい講義を作成してください。\",\n    \"group_make_lecture_4\": \"講義を作成する\",\n    \"group_add_lecture_1\": \"関心講義がありません。\",\n    \"group_add_lecture_2\": \"「学習する>オープン講義>講義」でクラスの学習内容に\",\n    \"group_add_lecture_3\": \"追加したい講義を関心講義に登録してください。\",\n    \"group_add_lecture_4\": \"講義を見る\",\n    \"group_make_course_1\": \"自分が作った講義集がありません。\",\n    \"group_make_course_2\": \"「作る > オープン講義を作成する>講義集を作成する」で\",\n    \"group_make_course_3\": \"学習内容に追加したい講義集を作成してください。\",\n    \"group_make_course_4\": \"講義集を作成する\",\n    \"group_add_course_1\": \"関心講義集がありません。\",\n    \"group_add_course_2\": \"「学習する > オープン講義>講義集」でクラスの学習内容に\",\n    \"group_add_course_3\": \"追加したい講義集を関心講義集に登録してください。\",\n    \"group_add_course_4\": \"講義集を見る\",\n    \"hw_main_title\": \"プログラムダウンロード\",\n    \"datablock_contest_title\": \"データ分析ブロック\",\n    \"datablock_content_head\": \"データを加工して表現しよう\",\n    \"datablock_content_body1\": \"生活の中で出会う色んなデータをチャートで表現して意味を探し、\",\n    \"datablock_content_body2\": \"実際の問題を解決してみよう！\",\n    \"campaign_contest_title\": \"Let's make a beautiful internet world\",\n    \"campaign_content_head\": \"Entry Project Contest\",\n    \"campaign_content_body1\": \"Create an originative project about 'internet ethics'\",\n    \"campaign_content_body2\": \"and apply for the contest!\",\n    \"campaign_content_button\": \"View details\",\n    \"code_management_1\": \"ENTRYキャンペーン#1 コードを上手に管理しよう\",\n    \"code_management_2\": \"マイボックスとメモの活用\",\n    \"code_management_3\": \"新しい機能と一緒にコードを管理し、\",\n    \"code_management_4\": \"作品を作って共有する方法について知りましょう。\",\n    \"code_management_5\": \"キャンペーンを見る\",\n    \"shcoolbook_study_1\": \"教科書の内容をそのまま\",\n    \"shcoolbook_study_2\": \"教科書で学ぶ\",\n    \"shcoolbook_study_3\": \"先生は教室で授業を、\",\n    \"shcoolbook_study_4\": \"生徒は家で復習することができます！\",\n    \"shcoolbook_study_5\": \"学ぶ\",\n    \"main_learn_1\": \"エントリーが初めてなら\",\n    \"main_learn_2\": \"エントリーについて知ろう\",\n    \"main_learn_3\": \"動画でエントリーのさまざまな機能を学び,\",\n    \"main_learn_4\": \"ステキな作品を作って友だちと共有してみましょう！\",\n    \"main_learn_5\": \"動画を見る\",\n    \"hw_desc_wrapper\": \"ハードウェア結合プログラムとオフ\\nラインバージョンが\\より一層レベルアップしてアップグ\\nレードされました。\",\n    \"hw_downolad_link\": \"ハードウェア結合\\nプログラムダウンロード\",\n    \"save_as_image_all\": \"すべてのコードを画像で保存する\",\n    \"save_as_image\": \"画像で保存する\",\n    \"maze_perfect_success\": \"さすが！完璧だったね~\",\n    \"maze_success_many_block_1\": \"よし\",\n    \"maze_fail_obstacle_remain\": \"みんなが怪我をしないよう、すべての<span class='bitmap_obstacle_spider'></span>をなくそう。\",\n    \"maze_fail_item_remain\": \"サリー姫を救出できるようにミネラルを全部集めよう。サリー姫を救出できるようにミネラルを全部集めよう。\",\n    \"maple_fail_item_remain\": \"食べ物が全部食べられなかったから力が出ないよ。食べ物を全部食べられるように手伝って。\",\n    \"maze_fail_not_found_destory_object\": \"何もないマスで無駄にスキルを使っちゃダメだよ!\",\n    \"maze_fail_not_found_destory_monster\": \"モンスターがいないマスでは攻撃しちゃダメだよ!\",\n    \"maple_fail_not_found_destory_monster\": \"攻撃ブロックはモンスターがある時だけ使うんだよ!\",\n    \"maze_fail_more_move\": \"目的地に着くには、もっと進まないと!\",\n    \"maze_fail_wall_crash\": \"うわ! そこは突き当たりだよ!\",\n    \"maze_fail_contact_brick\": \"あいたたた…ぶつかっちゃったよ!\",\n    \"maze_fail_contact_iron1\": \"うわ! 障害物にぶつかっちゃったね\",\n    \"maze_fail_contact_iron2\": \"うわ! 障害物が落ちてきてぶつかっちゃったよ。障害物が落ちてくる前に動いてね…\",\n    \"maze_fail_fall_hole\": \"あぁ、落とし穴に落ちちゃったね…\",\n    \"maze_fail_hit_unit\": \"モンスターにやられてしまった! 危険なモンスターをやっつける<ハートを飛ばす>ブロックを使ってね!\",\n    \"maze_fail_hit_unit2\": \"くぅ、モンスターにやられてしまった! 2マス離れたところから攻撃してね!\",\n    \"maze_fail_hit_unit_by_mushroom\": \"メイプルキノコにやられてしまった!<br /><img src='/img/assets/maze/icon/mushroom.png' />攻略するブロックを使って悪いモンスターをこやっつけよう!\",\n    \"maze_fail_hit_unit_by_lupin\": \"ルパンにやられてしまった!<br /><img src='/img/assets/maze/icon/lupin.png' />攻略するブロックを2マス離れたところで使って、悪いモンスターをやっつけよう!\",\n    \"maze_fail_elnath_fail\": \"うわっ！悪いモンスターから攻撃されちゃった！<br/>悪いモンスターが近づかないようにやっつけて！\",\n    \"maze_fail_pepe\": \" \",\n    \"maze_fail_yeti\": \"そのモンスターはとても強いから、<img width='24px' src='/img/assets/week/blocks/yeti.png'/>攻攻撃するブロックではやっつけられないよ！<br/><img width='24px' src='/img/assets/week/blocks/bigYeti.png'/>攻略するブロックを使ってみよう。\",\n    \"maze_fail_peti\": \"そのモンスターに<img width='24px' src='/img/assets/week/blocks/bigYeti.png'/>攻略するブロックを使うと、<br/>強いモンスターの<img width='24px' src='/img/assets/week/blocks/bigYeti.png'/>がが現れたときにやっつけられないよ！<br/><img width='24px' src='/img/assets/week/blocks/yeti.png'/>攻略するブロックを使ってみよう。\",\n    \"maze_fail_both_side\": \"両隣を攻撃するブロックは両隣にモンスターがいるときしか使っちゃダメだよ！\",\n    \"maze_wrong_attack_obstacle\": \"ここからは<img src='/img/assets/maze/icon/lupin.png' />攻撃するブロックは使えないよ！<br/>メイプルキノコには<img src='/img/assets/maze/icon/mushroom.png' />攻撃するブロックを使ってみよう。\",\n    \"maze_fail_contact_spider\": \"クモの巣に引っかかって動けないぃ…\",\n    \"maze_success_perfect\": \"さすが!完璧だったね~\",\n    \"maze_success_block_excess\": \"よし! %1個のブロックを使って成功させたね!<br>でも%2個のブロックだけで成功させる方法もあるよ。もう一度チャレンジしてみない?\",\n    \"maze_success_not_essential\": \"よし! %1個のブロックを使って成功させたね!<br>でもこのブロックを使えば、もっと簡単に解決できるよ。もう一度チャレンジしてみない?\",\n    \"maze_success_final_perfect_basic\": \"よし!サリー姫の居場所が確認できたよ!これでサリー姫が救えるはず!\",\n    \"maze_success_final_block_excess_basic\": \"よし!サリー姫の居場所が確認できたよ!これでサリー姫が救えるはず!%1個のブロックを使ったけど、%2個のブロックだけで成功させる方法もあるよ。もう一度チャレンジしてみない?\",\n    \"maze_success_final_perfect_advanced\": \"サリー姫の居場所に着いたよ!さあ、メフィストを倒してサリーを救おう!\",\n    \"maze_success_final_block_excess_advanced\": \"サリー姫の居場所に着いたよ!さあ、メフィストを倒してサリーを救おう!%1個のブロックを使ったけど、%2個のブロックだけで成功させる方法もあるよ。もう一度チャレンジしてみない?\",\n    \"maze_success_final_distance\": \"よし!ついにみんなでサリー姫を無事に救出できたよ。手伝ってくれて本当にありがとう! <br>%1マス動いて成功させたけど、もう一度チャレンジして60マスまで行ってみない?\",\n    \"maze_success_final_perfect_ai\": \"よし!ついにみんなでサリー姫を無事に救出できたよ。手伝ってくれて本当にありがとう! \",\n    \"maple_success_perfect\": \"さすが!完璧だったね~!!\",\n    \"maple_success_block_excess\": \"よし!( )個のブロックを使って成功させたね! <br> でも、%2個のブロックだけで成功させる方法もあるよ。もう一度チャレンジしてみない?\",\n    \"maple_success_not_essential\": \"よし! %1個のブロックを使って成功させたね! <br>でも、このブロックを使えばもっと簡単に解決できるよ。もう一度チャレンジしてみない?\",\n    \"maple_success_final_perfect_henesys\": \"素晴らしい！見事にヘネシスの冒険を成功させたね！\",\n    \"maple_success_final_perfect_excess_henesys\": \"素晴らしい！見事にヘネシスの冒険を成功させたね！<br />でも、%2個のブロックだけで成功させる方法もあるよ。もう一度チャレンジしてみない?\",\n    \"maple_success_final_not_essential_henesys\": \"素晴らしい！見事にヘネシスの冒険を成功させたね！<br />でも、このブロックを使えばもっと簡単に解決できるよ。もう一度チャレンジしてみない?\",\n    \"maple_success_final_perfect_ellinia\": \"ここでの冒険は本当に楽しかったよ！<br/>次の冒険にも付き合ってくれるよね?\",\n    \"maple_success_final_perfect_excess_ellinia\": \"ここでの冒険は本当に楽しかったよ！<br />でも、%2個のブロックだけで成功させる方法もあるよ。もう一度チャレンジしてみない?\",\n    \"maple_success_final_not_essential_ellinia\": \"ここでの冒険は本当に楽しかったよ！<br />でも、このブロックを使えばもっと簡単に解決できるよ。もう一度チャレンジしてみない?\",\n    \"maple_fail_fall_hole\": \"うわっ！落ちちゃったね…<br />ジャンプするブロックを使ってジャンプしてみよう。\",\n    \"maple_fail_ladder_fall_hole\": \"うわっ！落ちちゃったね…<br />はしごを使うブロックを使って他の道に行ってみよう.\",\n    \"maple_fail_more_move\": \"成功するには、目的地までもっと進まないと!\",\n    \"maple_fail_not_found_ladder\": \"残念！ここには登れるはしごがないよ。<br />はしごを使うブロックははしごがある場所でしか使っちゃダメだよ。\",\n    \"maple_fail_not_found_meat\": \"残念！ここには食べられる食べ物がないよ!<br />食べ物を食べるブロックは食べ物がある場所でしか使っちゃダメだよ。\",\n    \"maple_cert_input_title\": \"証明書に記入する、きみのお名前は？\",\n    \"maze_distance1\": \"距離1\",\n    \"maze_distance2\": \"距離2\",\n    \"maze_distance3\": \"距離3\",\n    \"ev3\": \"EV3\",\n    \"roborobo_roduino\": \"Roduino\",\n    \"roborobo_schoolkit\": \"School Kit\",\n    \"smartboard\": \"Sciencebox Codingboard\",\n    \"smartboardbt\": \"Sciencebox Codingboard(Bluetooth)\",\n    \"codestar\": \"Codestar\",\n    \"cobl\": \"Cobl\",\n    \"cobl_bt\": \"Cobl BT\",\n    \"block_coding\": \"ブロック\",\n    \"python_coding\": \"エントリーパイソン\",\n    \"dadublock\": \"DaduBlock\",\n    \"dadublock_car\": \"DaduBlock Car\",\n    \"blacksmith\": \"Blacksmith Board\",\n    \"course_submit_homework\": \"課題提出\",\n    \"course_done_study\": \"学習完了\",\n    \"course_show_list\": \"リスト\",\n    \"modi\": \"MODI\",\n    \"chocopi\": \"ChocoPi\",\n    \"coconut\": \"coconut\",\n    \"jdkit\": \"JDKit\",\n    \"practical_course\": \"教科用を作成する\",\n    \"entry_user_policy\": \"エントリー利用ポリシー\",\n    \"entry_scholarship_title\": \"エントリー学術資料\",\n    \"entry_scholarship_content\": \"エントリーは大学/学会などと共に多様な研究を行い、専門性を強化し続けています。エントリーで提供している研究用資料を確認してみてください。\",\n    \"entry_scholarship_content_sub\": \"*エントリーで提供するデータは、研究及び分析に活用されるようオンラインコーディングパーティーに参加したユーザーたちがミッションを解決する一連の過程をログ形式で保存したデータです。\",\n    \"entry_scholarship_download\": \"資料ダウンロード\",\n    \"codingparty_2016_title\": \"2016オンラインコーディングパーティー\",\n    \"codingparty_2016_content\": \"ミッションに参加したユーザーたちのブロック組み立て順、成功/失敗状況が学年、性別情報と共に提供されます。\",\n    \"codingparty_2017_title\": \"2017 Online coding party\",\n    \"scholarship_go_mission\": \"ミッションを確認する\",\n    \"scholarship_guide\": \"資料活用方法\",\n    \"scholarship_see_guide\": \"ガイドを見る\",\n    \"scholarship_guide_desc\": \"研究用資料を読み、活用できる方法が書かれている開発ガイドです。\",\n    \"scholarship_example\": \"資料活用例\",\n    \"scholarship_example_desc\": \"研究用資料を活用して発表された論文を確認できます。\",\n    \"scholarship_see_example\": \"論文ダウンロード\",\n    \"altino\": \"Altino\",\n    \"private_project\": \"非公開作品です。\",\n    \"learn_programming_entry_mission\": \"「エントリーボット」と一緒にミッションを解決する\",\n    \"learn_programming_line_mission\": \"「LINEレンジャー」と一緒にサリーを救え\",\n    \"learn_programming_choseok\": \"「ココロの声」のジョソクとゲームを作る\",\n    \"learn_programming_maple\": \"「ピンクビーン」と一緒に楽しいメイプルワールドへ!\",\n    \"learn_programming_level_novice\": \"基礎\",\n    \"learn_programming_level_inter\": \"中級\",\n    \"learn_programming_level_advanced\": \"上級\",\n    \"line_look_for\": \"サリーを探して\",\n    \"line_rangers_title_string\": \"学習する : ライン・レンジャーズ\",\n    \"online_codingparty_certificate_string\": \"オンラインコーディングパーティー\",\n    \"online_codingparty_line_title_string\": \"ライン・レンジャーズ\",\n    \"line_look_for_desc_1\": \"LINEレンジャーの力を一つに合わせ、最強ボス・メフィストを倒してサリーを救ってください!\",\n    \"line_save\": \"サリーを救え\",\n    \"line_save_desc_1\": \"メフィストの基地に閉じ込められたサリー。LINEレンジャーが障害物を避けてサリーを探し出せるように手伝ってください!\",\n    \"line_escape\": \"サリーと脱出する\",\n    \"line_escape_desc_1\": \"爆破されたメフィスト基地からサリーとLINEレンジャーが無事に脱出できるよう、手伝ってください!\",\n    \"solve_choseok\": \"じゃんけんゲームを作ろう\",\n    \"solve_choseok_desc_1\": \"漫画キャラクターのジョソクがじゃんけんゲームを作れるよう手伝ってください!\",\n    \"solve_henesys\": \"ヘネシス\",\n    \"solve_ellinia\": \"エリニア\",\n    \"solve_elnath\": \"エルナス\",\n    \"solve_henesys_desc_1\": \"村を冒険し、お腹をすかせたピンクビーンが食べ物をお腹いっぱい食べられるように手伝ってください!\",\n    \"solve_ellinia_desc_1\": \"森の中を探検し、悪いモンスターたちをやっつけて友達モンスターを助けてください!\",\n    \"solve_elnath_desc_1\": \"悪いモンスターが占領した雪山を越えて新しい冒険をスタートできるように、違うポータルを求めて旅立ってください!\",\n    \"save_modified_shape\": \"Do you want to save the modified shape?\",\n    \"save_modified_table\": \"修正したテーブルを保存しますか？\",\n    \"attach_file\": \"添付\",\n    \"enter_discuss_title\": \"タイトルを入力してください(40文字以下)\",\n    \"enter_discuss_title_alert\": \"タイトルを入力してください\",\n    \"discuss_upload_warn\": \"10MB以下のファイルをアップロードしてください。\",\n    \"discuss_list\": \"リストを見る\",\n    \"discuss_write_notice\": \"クラスのお知らせに設定し、掲示板の最上段に表示します。\",\n    \"discuss_write_notice_open\": \"お知らせに設定し、掲示板の最上段に表示します。\",\n    \"search_전체\": \"すべて\",\n    \"search_게임\": \"ゲーム\",\n    \"search_애니메이션\": \"アニメーション\",\n    \"search_미디어아트\": \"メディアアート\",\n    \"search_피지컬\": \"フィジカル\",\n    \"search_기타\": \"その他\",\n    \"discuss_write_textarea_placeholer\": \"ENTRYコミュニティは、みんなでいっしょにきずいていく空間です。\\n互いに気づかう言葉で楽しいコミュニティにしましょう！\",\n    \"discuss_write_textarea_placeholer_qna\": \"このページはQ&Aの掲示板です。\\nお互い思いやる言葉を使って楽しいコミュニティにしましょう。\",\n    \"discuss_write_textarea_placeholer_tips\": \"このページはノウハウ＆ティップの掲示板です。\\nお互い思いやる言葉を使って楽しいコミュニティにしましょう。\",\n    \"discuss_write_textarea_placeholer_free\": \"このページはENTRYストーリー掲示板です。\\nお互い思いやる言葉を使って楽しいコミュニティにしましょう。\",\n    \"discuss_write_textarea_placeholer_report\": \"このページは提案＆意見掲示板です。\\nお互い思いやる言葉を使って楽しいコミュニティにしましょう。\",\n    \"discuss_write_textarea_placeholer_contest2019\": \"※ 아래 양식으로 작성하여 제출해주세요.\\n\\n1. 학년 (예: 초등학교 5학년)\\n\\n2. 작품 URL (‘공유하기 > 작품 공유하기’에 작품을 공유한 다음, 작품 URL을 복사하여 적어주세요.)\\n\\n3. 작품 설명\\n\\n※ 공모전 수상자에게는 이메일이 발송될 예정입니다.\\n엔트리의 ‘내 정보 수정‘에 이메일 정보를 꼭 입력해주세요!\",\n    \"maze_road\": \"道\",\n    \"account_deletion\": \"会員退会\",\n    \"bug_report_too_many_request\": \"通報内容を送信しています。しばらくしてからやり直してください。\",\n    \"pinkbean_index_title\": \"ピンクビーンと一緒に楽しいメイプルワールドへ!\",\n    \"pinkbean_index_content\": \"退屈に耐えられなかったピンクビーンはメイプルワールドへの冒険に出ることにしました。<br />ピンクビーンと一緒に楽しいメイプルワールドを冒険しながら冒険日記を書いてください。<br />各ステージをクリアしながら自然にソフトウェアについて学ぶことができ、ミッションをすべてクリアすれば証明書ももらえます。\",\n    \"rangers_index_title\": \"LINEレンジャーと一緒にサリーを救いに出発!\",\n    \"rangers_index_content\": \"最強ボス・メフィストに連れ去られたサリーを救うため、LINEレンジャーが一つになりました。<br/>プログラミングの原理で障害物を克服し、サリーを救うヒーローになってください。各ステップを<br/>進むと自然にプログラミングを学ぶことができ、ミッションを終えたら証明書ももらえます。\",\n    \"rangers_replay_button\": \"動画を見る\",\n    \"rangers_start_button\": \"スタート\",\n    \"lms_curriculum_intro\": \"\",\n    \"lms_curriculum_goal\": \"\",\n    \"lms_curriculum_prepare\": \"\",\n    \"lms_curriculum_study\": \"\",\n    \"lms_curriculum_summary\": \"\",\n    \"lms_curriculum_quiz\": \"\",\n    \"lms_curriculum_now_stage\": \"\",\n    \"bug_report_title\": \"バグ報告\",\n    \"bug_report_content\": \"利用中に発生するエラーやバグの報告のほか、エントリーのためにすばらしい意見をお寄せ下さい。\",\n    \"object_import_syntax_error\": \"Since the object has syntax error blocks, it cannot be loaded. Please convert into block mode to load the object.\",\n    \"choseok_top_wrapper_panel_title\": \"ジョソクと一緒にじゃんけんゲームを作ってみよう!\",\n    \"choseok_top_wrapper_panel_des\": \"ウェブ漫画「ココロの声」がコーディングパーティーのミッションとして登場しました。<br/>漫画の中でジョソクが(じゃんけんゲーム)を作っていく過程に参加し、<br/>ミッションにチャレンジしてみてください。<br/>各ステップをクリアしていくことでソフトウェアについて学ぶことができ、<br/>ミッションを全てクリアすると<br/>証明書と共に自分だけのゲームを手に入れることができます。\",\n    \"choseok_mission_statement1\": \"ジョソクを動かす\",\n    \"choseok_mission_statement2\": \"じゃんけん対決スタート\",\n    \"choseok_mission_statement3\": \"じゃんけんで勝負を決める\",\n    \"choseok_mission_statement4\": \"じゃんけん対決の結果を表示する\",\n    \"choseok_mission_statement5\": \"自由に作ってみる\",\n    \"choseok_mission_statement_top1\": \"ミッション1：ジョソクを動かす\",\n    \"choseok_mission_statement_top2\": \"ミッション2：じゃんけん対決スタート\",\n    \"choseok_mission_statement_top3\": \"ミッション3：じゃんけんで勝負を決める\",\n    \"choseok_mission_statement_top4\": \"ミッション4：じゃんけん対決の結果を表示する\",\n    \"choseok_mission_statement_top5\": \"ミッション5：自由に作ってみる\",\n    \"advisory_title\": \"Entry Advisory Group\",\n    \"advisory_sub_title\": \"This is an advisory group including teachers and students who make Entry together.\",\n    \"data_table_column\": \"列\",\n    \"data_table_row\": \"行\",\n    \"data_table_provider\": \"提供\",\n    \"data_table_modifidate\": \"修正日\",\n    \"draw_new_table_ques_1\": \"データを直接入力してテーブルで保存ができます。\",\n    \"draw_new_table_ques_2\": \"テーブルの画面に移動しますか?\"\n};\nLang.Msgs = {\n    \"microbit_led_erase_all\": \"初期化\",\n    \"loading_plz_wait\": \"読み込んでいます。しばらくお待ちください\",\n    \"ai_utilize_audio_listening\": \"聞いている\",\n    \"upload_error_title\": \"ファイルが拒否されました\",\n    \"upload_error_content\": \"使用ポリシーに準拠していないファイルは除外されます。\",\n    \"monthly_intro_0\": \"<月刊エントリー>は、ソフトウェア教育に不慣れな先生でも簡単かつ楽しくソフトウェア教育ができるように作成された \",\n    \"monthly_intro_1\": \"SW教育雑誌です。面白い学習漫画と共にお送りするSW教育コンテンツをお楽しみください!\",\n    \"monthly_title_0\": \"犬を散歩させる / 線対称図形描画\",\n    \"monthly_title_1\": \"動画の原理 / 音楽プレイヤー作成する\",\n    \"monthly_title_2\": \"大韓民国地図パズル / 桜の花アニメーション\",\n    \"monthly_title_3\": \"マウスゾロゾロ、魚の群れ / 太陽系惑星\",\n    \"monthly_title_4\": \"ジャガイモ堀り / いちご牛乳の濃さ\",\n    \"monthly_description_0\": \"キーボード入力に沿って動く犬と、信号と座標を通して図形を描く作品を制作します。\",\n    \"monthly_description_1\": \"変数を活用して、写真映像作品や音楽プレイヤー作品を制作します。\",\n    \"monthly_description_2\": \"~の間繰り返すを利用したパズルゲームとコピー、乱数を利用したアニメーション作品を制作します。\",\n    \"monthly_description_3\": \"続けて繰り返すブロックと数学演算ブロックを使って、魚のメディアアート作品と太陽系を制作します。\",\n    \"monthly_description_4\": \"信号と変数、数学演算ブロックを活用してジャガイモを堀る作品といちご牛乳を作る作品を制作します。\",\n    \"save_canvas_alert\": \"保存中です。\",\n    \"feedback_too_many_post\": \"通報した内容を送信しています。10秒後にもう一度やり直してください。\",\n    \"feedback_duplicated\": \"既に通報されています\",\n    \"usable_object\": \"使用可能オブジェクト\",\n    \"shared_varaible\": \"共有変数\",\n    \"invalid_url\": \"映像URLを再確認してください。\",\n    \"auth_only\": \"認証済みのユーザーのみ利用できます。\",\n    \"runtime_error\": \"実行エラー\",\n    \"to_be_continue\": \"準備中です。\",\n    \"warn\": \"警告\",\n    \"error_occured\": \"もう一度やり直してください。同じ問題が再度発生する時は、「提案と意見」掲示板にお問い合わせください。\",\n    \"error_forbidden\": \"ログアウト状態であるため、作品を保存することができません。\\n他のタブでログアウントされているか確認してください。\\nログインの確認ができても、保存ができなければ”提案と意見”にてお問い合わせください。\",\n    \"list_can_not_space\": \"リスト名のセルを空白にすることはできません。\",\n    \"sign_can_not_space\": \"信号の名前のセルを空白にすることはできません。\",\n    \"variable_can_not_space\": \"変数の名前のセルを空白にすることはできません。\",\n    \"training_top_title\": \"研修プログラム\",\n    \"training_top_desc\": \"エントリー研修支援プログラムについてご案内いたします。\",\n    \"training_main_title01\": \"教師のための講師紹介プログラム\",\n    \"training_target01\": \"教育対象 l 教師\",\n    \"training_sub_title01\": \"“うちのクラスにSWの翼をつけよう”\",\n    \"training_desc01\": \"ソフトウェア(SW)教員研修が必要な学校ですか?\\nSW教員研修が必要な学校に、SW教育専門教師(ゴートゥーティーチャー)または専門講師をご紹介いたします。\",\n    \"training_etc_ment01\": \"*講義費などの研修費用は学校側で負担していただく必要があります。\",\n    \"training_main_title02\": \"ソフトウェア(SW)リード校に訪問する教員研修\",\n    \"training_target02\": \"教育対象 l SWリード、研究学校\",\n    \"training_sub_title02\": \"“訪ねて、教えて、つないでいく”\",\n    \"training_desc02\": \"SW教員研修にお申込みいただいたリード校を抽選でランダムに選び、上半期(4・5・6月)と\\n下半期(9・10・11月)に各地域のSW教育専門教師(ゴートゥーティーチャー)が充実した内容の\\n楽しいSW基礎研修実施と豊富な教育事例を共有するために訪ねます。\",\n    \"training_etc_ment02\": \" \",\n    \"training_main_title03\": \"保護者と学生のための紹介プログラム\",\n    \"training_target03\": \"教育対象 l 保護者、学生\",\n    \"training_sub_title03\": \"“SWともっと近くで触れ合えるチャンス”\",\n    \"training_desc03\": \"保護者と学生たちを対象に、ソフトウェア(SW)研修が必要な学校に各地域のSW教育専門教師(ゴートゥーティーチャー)または専門講師をご紹介いたします。\",\n    \"training_etc_ment03\": \"*講義費などの研修費用は学校側で負担していただく必要があります。\",\n    \"training_apply\": \"申し込み\",\n    \"training_ready\": \"準備中です。\",\n    \"new_version_title\": \"最新バージョンインストールのご案内\",\n    \"new_version_text1\": \"ハードウェア結合プログラムがインストールされていません。\",\n    \"new_version_text2\": \"<strong>最新バージョン</strong>ではありません。\",\n    \"new_version_text3\": \"サービスをより一層レベルアップしてアップデートされた\",\n    \"new_version_text4\": \"最新バージョンの結合プログラムをインストールしてください。\",\n    \"new_version_download\": \"最新バージョンダウンロード<span class='download_icon'></span>\",\n    \"not_install_title\": \"未インストールのご案内\",\n    \"hw_download_text1\": \"ハードウェア結合のために\",\n    \"hw_download_text2\": \"<strong>ハードウェア結合プログラム</strong>をインストールしてください。\",\n    \"hw_download_text3\": \"ハードウェア結合プログラムがインストールされていません。\",\n    \"hw_download_text4\": \"最新バージョンの連結プログラムをインストールしてください。\",\n    \"hw_download_btn\": \"連結プログラムダウンロード<span class='download_icon'></span>\",\n    \"not_support_browser\": \"このブラウザには対応していません。\",\n    \"quiz_complete1\": \"クイズ終了!\",\n    \"quiz_complete2\": \"全{0}問のうち{1}問に正解しました。\",\n    \"quiz_incorrect\": \"わわっ。もう一度考えてみよう。\",\n    \"quiz_correct\": \"正解だよ!\",\n    \"hw_connection_success\": \"ハードウェア結合成功\",\n    \"hw_connection_success_desc\": \"ハードウェアアイコンをダブルクリックすると、センサー値のみ確認できます。\",\n    \"hw_connection_success_desc2\": \"作品でハードウェアを使うことができます。\",\n    \"hw_connection_termination_title\": \"ハードウェア接続解除\",\n    \"hw_connection_termination_desc\": \"ハードウェアと接続が解除されました。\",\n    \"hw_connection_failed_title\": \"ハードウェア接続失敗\",\n    \"hw_connection_failed_desc\": \"作品で使われたハードウェアが\\n接続されているか確認してください。\",\n    \"ie_page_title\": \"このブラウザには<br/>対応していません。\",\n    \"ie_page_desc\": \"エントリーはIE 10以上またはchromeでご利用いただけます。<br/>Windowsアップデートを行うか、chromeをインストールしてください。<br/>エントリーオフラインバージョンはインターネットに接続されていない状態でも使用できます。今すぐダウンロードして始めてください!\",\n    \"ie_page_chrome_download\": \"chrome<br/>をダウンロード\",\n    \"ie_page_windows_update\": \"Windowsの最新バージョン<br>をアップデート\",\n    \"ie_page_offline_32bit_download\": \"エントリーオフライン32bit<br>をダウンロード\",\n    \"ie_page_offline_64bit_download\": \"エントリーオフライン64bit<br>をダウンロード\",\n    \"ie_page_offline_mac_download\": \"エントリーオフライン<br>をダウンロード\",\n    \"cancel_deletion_your_account\": \"$1さんの<br />会員退会申請を取消しますか?\",\n    \"account_deletion_canceled_complete\": \"会員退会申請が取消されました。\",\n    \"journal_henesys_no1_title\": \"ヘネシス冒険日記　その1\",\n    \"journal_henesys_no2_title\": \"ヘネシス冒険日記　その2\",\n    \"journal_henesys_no1_content\": \"ヘネシスで書くはじめての冒険日記だね。今日はヘネシスで一番の古株だと言われている鍛冶屋の家に行こうと思ってジャンプしたら危うく落ちそうになったの。あのおじさん、どうして家の庭にあんなに大きな穴を作ってるんだろう？私ほど強いモンスターじゃない限り、この穴を飛び越えられるような子はあまりいないと思うんだけどね！とりあえず情報ももらえたし、おじさんがおすすめしてくれた食堂にでも行ってみようかな！\",\n    \"journal_henesys_no2_content\": \"食べ過ぎちゃった… 特に、あの食堂のお肉がすごく美味しかったね。どうすればあんなに柔らかくできるんだろう？！でも、その隣の店のパンはイマイチだったよ。どうやらパティシエさんが食べ物の修練を言い訳に毎日遊び回ってるみたい。そういう時間があるならもっとパンを作ってみるのがいいんじゃないかな。まぁ、お腹もいっぱいになったことだし、本格的に冒険をはじめてみようかな！\",\n    \"journal_ellinia_no1_title\": \"エリニア冒険日記 その1\",\n    \"journal_ellinia_no2_title\": \"エリニア冒険日記 その2\",\n    \"journal_ellinia_no1_content\": \"知らないうちにメイプルキノコを組み敷いてしまったよ… 怒られて当然だよね。 でもさ、だからといって一斉で攻撃してくることないんじゃない？ 本当に怖いやつらだよ。スライムたちが苦戦するのも分かっちゃうなぁ。 でも、このピンクビーン様がやっつけたからもう心配要らないよ！スライムたちも仲間に加わったことだし、もっとテンション上げて素敵な森を冒険してみよう！\",\n    \"journal_ellinia_no2_content\": \"冒険中に出会った友だち、ロイヤルフェアリーから最近エルナスに怖い噂が出回ってるって聞いたんだけど、なんだろう？今夜は友だちと家で遊ぶことになってるからその時に聞いてみよう。だって気になるんだもん～！ しかし、何を着ていけばいいんだろう…最近太りすぎて着れる洋服がないんだよね… まぁ、私はいつでも可愛いからどんな洋服を着てもみんな喜ぶだろうけどね！\",\n    \"journal_elnath_no1_title\": \"エルナス冒険日記 その1\",\n    \"journal_elnath_no2_title\": \"エルナス冒険日記 その2\",\n    \"journal_elnath_no1_content\": \"うわー！ これが噂の雪ってやつかな？私が住んでいる村はいつでも春だから、雪を見るのは初めてなんだ。モンスターたちのせいでちゃんと見る余裕がなかったんだけど、今見たら世界中がこんなにも真っ白で冷たくなってるなんてビックリだよ！ふわふわでキラキラしてるから美味しそうだなぁと思ったんだけど、特に味はなかった… でもね、甘いチョコシロップをかけて食べたら美味しそうじゃない？少しだけ持っていきたいんだけど持っていける方法がなくて残念だね。\",\n    \"journal_elnath_no2_content\": \"ペッペッペッ、間違えて石炭の粉を食べてしまったよ。あれもこれも全部悪いモンスターたちのせいだよ！逃げるなら静かに逃げればいいのに、石炭の粉を撒き散らしながら逃げるなんてね！おかげさまで私のツヤツヤで綺麗なピンク色の肌が汚れてちゃったじゃない！早くここを抜け出してお風呂に入りたい… いくら冒険が好きだと行っても、こんなに汚い格好をしたまま歩き回るのはこのピンクビーン様のプライドが許さないよ…\",\n    \"bug_report_alert_msg\": \"貴重なご意見ありがとうございます。\",\n    \"version_update_msg1\": \"最新バージョン(%1)を\\nご利用いただけます。\",\n    \"version_update_msg2\": \"エントリーハードウェアの最新バージョン(%1)を\\nご使用いただけます。\",\n    \"version_update_msg3\": \"いまアップデートしますか?\",\n    \"select_the_hardware\": \"Select the hardware<br />that you would use in the lesson.\",\n    \"select_hardware_button\": \"Select\",\n    \"select_the_expansion_block\": \"Select the expansion block that you would use in the lesson.\",\n    \"select_hardware_not_support_info\": \"ハードウェアブロックはオープンクラスに使用できない。\",\n    \"select_hardware_not_support_info2\": \"少々お待ちください。\",\n    \"select_expansion_block_button\": \"Select\",\n    \"expansion_weather_description\": \"気温、降水量、PM10濃度など韓国の天気と関連したブロックをまとめたものです。\",\n    \"expansion_festival_description\": \"国内地地方の様々な行事や祭りに関連するブロックをまとめたものです。\",\n    \"expansion_translate_description\": \"Papagoを使って他の言語に翻訳できるブロックをまとめたものです。\",\n    \"expansion_behaviorConductDisaster_description\": \"自然災害の発生時に国民が守らなければならない基本的な行動要領（国民安全処からの提供）\",\n    \"expansion_behaviorConductLifeSafety_description\": \"生活安全のため、国民が守らなければならない基本的な行動要領（国民安全処からの提供）\",\n    \"ai_utilize_tts_description\": \"nVoiceを使って色んな音声で文章を読むことができるブロックのまとめです。\",\n    \"hardware_need_update_title\": \"ハードウエア接続ソフトアップデート\",\n    \"hardware_need_update_content\": \"セキュリティアップデートに伴い、\\nバージョン1.76以上をサポートしています。\\nバージョンが1.76以下の場合は、\\n「接続ソフトをダウンロード」から\\nアップデートしてください。\",\n    \"ai_utilize_audio_description\": \"マイクを利用して、音と音声を検出することができるブロックのコレクションです。\",\n    \"ai_utilize_video_description\": \"カメラを利用して動きと方向値、そして撮影されるオブジェクトなどを認識できるブロック集です。\"\n};\nLang.Users = {\n    \"auth_failed\": \"認証に失敗しました。\",\n    \"birth_year\": \"生年\",\n    \"birth_year_before_1990\": \"1990年以前\",\n    \"edit_personal\": \"情報修正\",\n    \"email\": \"メールアドレス\",\n    \"email_desc\": \"新しいニュースや情報を得られるメールアドレス\",\n    \"email_inuse\": \"すでに登録されたメールアドレスです\",\n    \"email_match\": \"メールアドレスを正しく入力してください\",\n    \"forgot_password\": \"パスワードをお忘れですか?\",\n    \"job\": \"職業\",\n    \"language\": \"言語\",\n    \"name\": \"名前\",\n    \"name_desc\": \"サイト内で表示される名前またはニックネーム\",\n    \"name_not_empty\": \"名前を必ず入力してください\",\n    \"password\": \"パスワード\",\n    \"password_desc\": \"最低4文字以上の英数字、記号\",\n    \"password_invalid\": \"パスワードが正しくありません\",\n    \"password_long\": \"パスワードは4~20文字の英数字、記号で入力してください\",\n    \"password_required\": \"パスワードは必須入力項目です\",\n    \"project_list\": \"作品照会\",\n    \"regist\": \"登録完了\",\n    \"rememberme\": \"自動ログイン\",\n    \"repeat_password\": \"パスワード確認\",\n    \"repeat_password_desc\": \"パスワードをもう一度入力してください\",\n    \"repeat_password_not_match\": \"パスワードが一致しません\",\n    \"sex\": \"性別\",\n    \"signup_required_for_save\": \"保存するには、ログインが必要です。\",\n    \"username\": \"ID\",\n    \"username_desc\": \"ログイン時に使用するID\",\n    \"username_inuse\": \"すでに使用中のIDです\",\n    \"username_long\": \"IDは4~20文字のアルファベットで入力してください\",\n    \"username_unknown\": \"このユーザーは存在しません\",\n    \"already_verified\": \"すでに認証済みのメールアドレスです。\",\n    \"email_address_unavailable\": \"この認証メールは無効です。\",\n    \"email_address_invalid_for_idpw\": \"無効なメールアドレスです。\\n ID確認／パスワード再登録のメールを再発送してみて下さい。\",\n    \"email_address_invalid_for_certification\": \"無効なメールアドレスです。\\n 認証メールを再送して下さい。\",\n    \"verification_complete\": \"メールアドレスの認証に成功しました。\",\n    \"reset_password_mail_sent\": \"Email for password resetting has been sent. Please check your email.\",\n    \"email_not_verified\": \"This email is not verified. Please verify your email to click 'Verifying email' first.\",\n    \"verification_email_send_complete\": \"Verifying email has been sent. Please verify your email first.\",\n    \"email_send_failed\": \"Sending email was failed. Please try again.\",\n    \"email_not_exist\": \"This email does not exist.\",\n    \"not_valid_email\": \"Please enter a correct type of email.\"\n};\nLang.Workspace = {\n    \"picture_rotation\": \"回転\",\n    \"picture_size\": \"サイズ\",\n    \"thickness\": \"太さ\",\n    \"follow\": \"やってみる\",\n    \"SaveWithPicture\": \"保存されていない図があります。保存しますか?\",\n    \"RecursiveCallWarningTitle\": \"関数呼び出し制限\",\n    \"RecursiveCallWarningContent\": \"一度に多くの関数が呼び出されました。関数の呼び出し回数を減らしてください。\",\n    \"SelectShape\": \"移動\",\n    \"SelectCut\": \"切り取り\",\n    \"Pencil\": \"ペン\",\n    \"Line\": \"直線\",\n    \"Rectangle\": \"四角形\",\n    \"Ellipse\": \"円\",\n    \"Text\": \"テキストボックス\",\n    \"Fill\": \"塗りつぶし\",\n    \"Eraser\": \"クリア\",\n    \"Magnifier\": \"拡大/縮小\",\n    \"block_helper\": \"ブロックヘルプ\",\n    \"new_project\": \"新しいプロジェクト\",\n    \"add_object\": \"オブジェクトを追加する\",\n    \"download_image_name\": \"entry_ブロック\",\n    \"all\": \"すべて\",\n    \"animal\": \"動物\",\n    \"arduino_entry\": \"Program for connect to Arduino\",\n    \"arduino_program\": \"Arduino program\",\n    \"arduino_sample\": \"Sample code for Arduino\",\n    \"arduino_driver\": \"Driver for arduino\",\n    \"cannot_add_object\": \"実行中にはオブジェクトを追加できません。\",\n    \"cannot_add_picture\": \"実行中には模様を追加できません。\",\n    \"cannot_add_sound\": \"実行中にはサウンドを追加できません。\",\n    \"cannot_add_expansion_block\": \"Cannot add expansion block while running a project.\",\n    \"add_object_before_edit\": \"模様編集のために<br>オブジェクトを追加してください\",\n    \"add_table_before_edit\": \"テーブルを追加してください。\",\n    \"cannot_edit_click_to_stop\": \"実行中には修正できません。<br>クリックして停止する。\",\n    \"cannot_open_private_project\": \"非公開作品は読み込めません。ホームに移動します。\",\n    \"cannot_save_running_project\": \"実行中には保存できません。\",\n    \"character_gen\": \"キャラクターを作成する\",\n    \"check_runtime_error\": \"赤色で表示されたブロックを確認してください。\",\n    \"check_browser_error\": \"IE/Safariではサポートしていないブロックです。\",\n    \"check_microphone_error\": \"コンピューターにマイクが接続されていません\",\n    \"check_webcam_error\": \"コンピューターにカメラが接続されていません\",\n    \"context_download\": \"PCに保存\",\n    \"context_duplicate\": \"コピー\",\n    \"context_remove\": \"削除\",\n    \"context_rename\": \"名前修正\",\n    \"coordinate\": \"座標\",\n    \"create_function\": \"関数を作成する\",\n    \"direction\": \"移動方向(°)\",\n    \"drawing\": \"直接描画\",\n    \"enter_list_name\": \"新しいリストの名前を入力してください(10文字以下)\",\n    \"enter_name\": \"新しい名前を入力してください\",\n    \"enter_new_message\": \"新しい信号の名前を入力してください\",\n    \"enter_variable_name\": \"新しい変数の名前を入力してください(10文字以下)\",\n    \"family\": \"エントリーボットの家族\",\n    \"fantasy\": \"ファンタジー/その他\",\n    \"file_new\": \"新規\",\n    \"file_open\": \"オンラインの作品を読み込む\",\n    \"file_upload\": \"オフラインの作品を読み込む\",\n    \"file_upload_login_check_msg\": \"オフライン作品を読み込むにはログインする必要があります。\",\n    \"file_save\": \"保存する\",\n    \"file_save_as\": \"コピーで保存する\",\n    \"file_save_download\": \"マイコンピューターに保存する\",\n    \"func\": \"関数\",\n    \"function_create\": \"関数を作成する\",\n    \"function_add\": \"関数追加\",\n    \"interface\": \"インターフェイス\",\n    \"landscape\": \"背景\",\n    \"list\": \"リスト\",\n    \"list_add_calcel\": \"リスト追加取消\",\n    \"list_add_calcel_msg\": \"リスト追加を取り消しました。\",\n    \"list_add_fail\": \"リスト追加失敗\",\n    \"list_add_fail_msg1\": \"同名のリストがすでに存在します。\",\n    \"list_add_fail_msg2\": \"リストの名前が適切ではありません。\",\n    \"list_add_ok\": \"リスト追加完了\",\n    \"list_add_ok_msg\": \"を追加しました。\",\n    \"list_create\": \"リスト追加\",\n    \"list_create_placeholder\": \"リスト名を入力してください。\",\n    \"list_dup\": \"同名のリストがすでに存在します。\",\n    \"list_newname\": \"新しい名前\",\n    \"list_export\": \"書き出し\",\n    \"list_import\": \"読み込み\",\n    \"list_remove\": \"リスト削除\",\n    \"list_rename\": \"リスト名変更\",\n    \"list_rename_failed\": \"リスト名変更失敗\",\n    \"list_rename_ok\": \"リストの名前の変更に成功しました。\",\n    \"list_too_long\": \"リストの名前が長すぎます。\",\n    \"message\": \"信号\",\n    \"message_add_cancel\": \"信号追加取消\",\n    \"message_add_cancel_msg\": \"信号追加を取り消しました。\",\n    \"message_add_fail\": \"信号追加失敗\",\n    \"message_add_fail_msg\": \"同名の信号がすでに存在します。\",\n    \"message_add_ok\": \"信号追加完了\",\n    \"message_add_ok_msg\": \"を追加しました。\",\n    \"message_create\": \"信号追加\",\n    \"message_create_placeholder\": \"信号名を入力してください。\",\n    \"message_dup\": \"同名の信号がすでに存在します。\",\n    \"message_remove\": \"信号削除\",\n    \"message_remove_canceled\": \"信号削除を取り消しました。\",\n    \"message_rename\": \"信号名を変更しました。\",\n    \"message_rename_failed\": \"信号名の変更に失敗しました。\",\n    \"message_rename_ok\": \"信号の名前の変更に成功しました。\",\n    \"message_too_long\": \"信号の名前が長すぎます。\",\n    \"no_message_to_remove\": \"削除する信号がありません。\",\n    \"no_use\": \"使われていません。\",\n    \"no_variable_to_remove\": \"削除する変数がありません。\",\n    \"no_variable_to_rename\": \"変更する変数がありません。\",\n    \"object_not_found\": \"ブロックで指定したオブジェクトが存在しません。\",\n    \"object_not_found_for_paste\": \"ペーストするオブジェクトがありません。\",\n    \"people\": \"一般人\",\n    \"picture_add\": \"模様追加\",\n    \"table_add\": \"テーブルを追加する\",\n    \"draw_new_table\": \"新しいテーブル\",\n    \"plant\": \"植物\",\n    \"project\": \"作品\",\n    \"project_copied\": \"のコピー\",\n    \"PROJECTDEFAULTNAME\": ['おしゃれな', '面白い', '善良な', '大きい', '立派な', 'イケメンな', '幸運の'],\n    \"remove_object\": \"オブジェクト削除\",\n    \"remove_object_msg\": \"が削除されました。\",\n    \"removed_msg\": \"の削除に成功しました。\",\n    \"rotate_method\": \"回転方式\",\n    \"rotation\": \"方向(°)\",\n    \"run\": \"スタート\",\n    \"saved\": \"保存完了\",\n    \"saved_msg\": \"が保存されました。\",\n    \"save_failed\": \"保存中に問題が発生しました。もう一度やり直してください。\",\n    \"select_library\": \"オブジェクト選択\",\n    \"select_sprite\": \"適用するスプライトを1つ以上選択してください。\",\n    \"shape_remove_fail\": \"模様削除失敗\",\n    \"shape_remove_fail_msg\": \"最低1つ以上の模様がなければなりません。\",\n    \"shape_remove_ok\": \"模様が削除されました。\",\n    \"shape_remove_ok_msg\": \"が削除されました。\",\n    \"load_expansion_block\": \"拡張ブロック追加する\",\n    \"load_ai_utilize_block\": \"AIブロックの読み込み\",\n    \"load_ai_utilize_train_block\": \"鉄道模型\",\n    \"select_expansion_block\": \"Select block\",\n    \"deselect_expansion_block_warning\": \"The selected block cannot be deleted. \\nThe specified block is currently in use.\",\n    \"deselect_ai_utilize_block_warning\": \"The selected block cannot be deleted. \\nThe specified block is currently in use.\",\n    \"sound_add\": \"サウンド追加\",\n    \"sound_remove_fail\": \"サウンド削除失敗\",\n    \"sound_remove_ok\": \"サウンド削除完了\",\n    \"sound_remove_ok_msg\": \"が削除されました。\",\n    \"stop\": \"停止する\",\n    \"pause\": \"一時停止\",\n    \"restart\": \"再スタート\",\n    \"speed\": \"速度を調節する\",\n    \"tab_attribute\": \"属性\",\n    \"tab_table\": \"テーブル\",\n    \"tab_code\": \"ブロック\",\n    \"tab_picture\": \"形\",\n    \"tab_sound\": \"サウンド\",\n    \"tab_text\": \"テキストボックス\",\n    \"textbox\": \"テキストボックス\",\n    \"textbox_edit\": \"テキストボックス編集\",\n    \"textbox_input\": \"テキストボックスの内容を入力してください。\",\n    \"things\": \"物\",\n    \"textcoding_tooltip1\": \"ブロックコーディングとエントリーパイソンを<br/>選択して自由に<br/>コーディングに挑戦することができます。\",\n    \"textcoding_tooltip2\": \"実際の開発環境と同様に<br/>エントリーパイソンモードの実行結果を<br/>確認できます。\",\n    \"textcoding_tooltip3\": \"エントリーパイソンに対する<br/>基本的な内容を案内しています<br/><エントリーパイソン利用案内>を確認してください!\",\n    \"upload\": \"ファイルアップロード\",\n    \"upload_addfile\": \"ファイル追加\",\n    \"variable\": \"変数\",\n    \"variable_add_calcel\": \"変数追加取消\",\n    \"variable_add_calcel_msg\": \"変数追加を取り消しました。\",\n    \"variable_add_fail\": \"変数追加失敗\",\n    \"variable_add_fail_msg1\": \"同名の変数がすでに存在します。\",\n    \"variable_add_fail_msg2\": \"変数の名前が適切ではありません。\",\n    \"variable_add_ok\": \"変数追加完了\",\n    \"variable_add_ok_msg\": \"を追加しました。\",\n    \"variable_create\": \"変数を作成する\",\n    \"variable_add\": \"変数追加\",\n    \"variable_dup\": \"同名の変数がすでに存在します。\",\n    \"variable_newname\": \"新しい名前\",\n    \"variable_remove\": \"変数削除\",\n    \"variable_remove_canceled\": \"変数削除を取り消しました。\",\n    \"variable_rename\": \"変数名を変更します。\",\n    \"variable_rename_failed\": \"変数名の変更に失敗しました。\",\n    \"variable_rename_msg\": \"「変数の名前の変更に成功しました。」\",\n    \"variable_rename_ok\": \"変数の名前の変更に成功しました。\",\n    \"variable_select\": \"変数を選択してください\",\n    \"variable_too_long\": \"変数の名前が長すぎます。\",\n    \"open_analizy_data_import\": \"データ画面を開く\",\n    \"vehicle\": \"乗り物\",\n    \"add_object_alert_msg\": \"オブジェクトを追加してください\",\n    \"add_object_alert\": \"警告\",\n    \"create_variable_block\": \"変数を作成する\",\n    \"create_list_block\": \"リストを作成する\",\n    \"Variable_Timer\": \"ストップウォッチ\",\n    \"Variable_placeholder_name\": \"変数名\",\n    \"Message_placeholder_name\": \"Signal name\",\n    \"Variable_property\": \"変数の属性\",\n    \"Variable_placeholder_content\": \"変数名を入力してください。\",\n    \"Variable_use_all_objects\": \"すべてのオブジェクトで使用\",\n    \"Variable_use_this_object\": \"このオブジェクトで使用\",\n    \"Variable_used_at_all_objects\": \"すべてのオブジェクトで使われている変数\",\n    \"variable_create_normal\": \"일반 변수로 사용\\n(작품에 저장)\",\n    \"variable_create_cloud\": \"共有変数として使用\\n(サーバーに保存)\",\n    \"variable_create_real_time\": \"リアルタイム変数として使用\\n(サーバーに保存)\",\n    \"Variable_used_at_special_object\": \"特定のオブジェクトでのみ使われている変数\",\n    \"Variable_used_objects\": \"使用されたオブジェクト\",\n    \"draw_new\": \"新しく描画\",\n    \"draw_new_ebs\": \"直接描画\",\n    \"painter_file\": \"ファイル▼\",\n    \"painter_file_save\": \"保存する\",\n    \"painter_file_saveas\": \"新しい模様で保存\",\n    \"new_picture\": \"新しい図\",\n    \"painter_edit\": \"編集 ▼\",\n    \"get_file\": \"インポート\",\n    \"copy_file\": \"コピーする\",\n    \"cut_picture\": \"切り取り\",\n    \"paste_picture\": \"貼り付け\",\n    \"remove_all\": \"すべて削除\",\n    \"flip_horizontal\": \"左右反転\",\n    \"flip_vertical\": \"上下反転\",\n    \"regular\": \"普通\",\n    \"bold\": \"太字\",\n    \"font_underline\": \"下線\",\n    \"font_tilt\": \"斜線\",\n    \"font_cancel\": \"取り消し線\",\n    \"font_color\": \"文字の色\",\n    \"font_fill\": \"背景色\",\n    \"font_family\": \"フォント\",\n    \"align_left\": \"左揃え\",\n    \"align_center\": \"中央揃え\",\n    \"align_right\": \"右揃え\",\n    \"italic\": \"斜体\",\n    \"textStyle\": \"文字\",\n    \"add_picture\": \"模様追加\",\n    \"select_picture\": \"模様選択\",\n    \"select_table\": \"テーブルを選択\",\n    \"select_sound\": \"サウンド選択\",\n    \"Size\": \"サイズ\",\n    \"show_variable\": \"変数表示\",\n    \"default_value\": \"基本値 \",\n    \"slide\": \"スライド\",\n    \"min_value\": \"最小値\",\n    \"max_value\": \"最大値\",\n    \"number_of_list\": \"リスト項目数\",\n    \"empty_of_list\": \"項目が追加されていません。\",\n    \"use_all_objects\": \"すべてのオブジェクトに使用\",\n    \"list_name\": \"リスト名\",\n    \"list_property\": \"リストの属性\",\n    \"list_used_specific_objects\": \"特定のオブジェクトでのみ使われているリスト\",\n    \"List_used_all_objects\": \"すべてのオブジェクトで使われているリスト\",\n    \"List_used_objects\": \"使用されたオブジェクト\",\n    \"Scene_delete_error\": \"シーンは最低1つ以上なければなりません。\",\n    \"Scene_add_error\": \"シーンは最大20件まで追加できます。\",\n    \"replica_of_object\": \"のコピー\",\n    \"will_you_delete_scene\": \"シーンは一度削除すると取り消すことができません。\\n本当に削除しますか?\",\n    \"will_you_delete_function\": \"関数は一度削除すると取り消すことができません。\\n本当に削除しますか?\",\n    \"duplicate_scene\": \"コピーする\",\n    \"block_explain\": \"ブロック説明 \",\n    \"block_intro\": \"ブロックをクリックすると、ブロックに関する説明が表示されます。\",\n    \"blocks_reference\": \"ブロック説明\",\n    \"hardware_guide\": \"ハードウェア結合案内\",\n    \"robot_guide\": \"ロボット連結案内\",\n    \"python_guide\": \"エントリーパイソン利用案内\",\n    \"show_list_workspace\": \"リスト表示\",\n    \"list_create_normal\": \"リストとして使用\\n(作品に保存)\",\n    \"list_create_cloud\": \"共有リストとして使用\\n(サーバーに保存されます)\",\n    \"list_create_real_time\": \"リアルタイムリストとして使用\\n(サーバーに保存)\",\n    \"confirm_quit\": \"変更した内容を保存しませんでした。\",\n    \"confirm_load_temporary\": \"保存されていない作品があります。開きますか?\",\n    \"login_to_save\": \"ログイン後に保存してください。\",\n    \"cannot_save_in_edit_func\": \"関数編集中には保存できません。\",\n    \"new_object\": \"新しいオブジェクト\",\n    \"arduino_connect\": \"\",\n    \"arduino_connect_success\": \"\",\n    \"confirm_load_header\": \"作品復旧\",\n    \"uploading_msg\": \"アップロード中です。\",\n    \"upload_fail_msg\": \"アップロードに失敗しました。</br>もう一度やり直してください。\",\n    \"upload_not_supported_msg\": \"この形式には対応していません。\",\n    \"upload_not_supported_file_msg\": \"このファイル形式には対応していません。\",\n    \"file_converting_msg\": \"ファイル変換中です。\",\n    \"file_converting_fail_msg\": \"ファイル変換に失敗しました。\",\n    \"fail_contact_msg\": \"続けて問題が発生する場合は</br>entry@connect.or.krにお問い合わせください。\",\n    \"saving_msg\": \"保存中です。\",\n    \"saving_fail_msg\": \"保存に失敗しました。</br>もう一度やり直してください。\",\n    \"loading_msg\": \"読み込み中です。\",\n    \"loading_fail_msg\": \"読み込みに失敗しました。</br>もう一度やり直してください。\",\n    \"restore_project_msg\": \"正常に保存されていない作品があります。この作品を復旧しますか?\",\n    \"quit_stop_msg\": \"保存中は終了できません。\",\n    \"ent_drag_and_drop\": \"アップロードしたいファイルをドロップしてください。\",\n    \"not_supported_file_msg\": \"このファイル形式には対応していません。\",\n    \"broken_file_msg\": \"ファイルが壊れているか間違ったファイルを読み込みました。\",\n    \"check_audio_msg\": \"mp3以外のオーディオファイルはプレイできません。\",\n    \"check_entry_file_msg\": \"ENTファイルのみ読み込むことができます。\",\n    \"hardware_version_alert_text\": \"5月30日から旧バージョンの結合プログラムの使用が中止されます。\\nハードウェア結合プログラムを最新バージョンにアップデートしてください。\",\n    \"variable_name_auto_edited_title\": \"変数名自動変更\",\n    \"variable_name_auto_edited_content\": \"変数名は10文字を超過できません。\",\n    \"list_name_auto_edited_title\": \"リスト名自動変更\",\n    \"list_name_auto_edited_content\": \"リスト名は10文字を超過できません。\",\n    \"cloned_scene\": \"コピー_\",\n    \"default_mode\": \"基本型\",\n    \"practical_course_mode\": \"教科型\",\n    \"practical_course\": \"実科\",\n    \"select_mode\": \"モード選択\",\n    \"select_mode_popup_title\": \"エントリーを作成する環境を選択してください。\",\n    \"select_mode_popup_lable1\": \"基本型\",\n    \"select_mode_popup_lable2\": \"教科型\",\n    \"select_mode_popup_desc1\": \"エントリーのすべての機能を利用して<br/>自由に作品を制作します。\",\n    \"select_mode_popup_desc2\": \"実科の教科書に登場する機能のみを<br/>利用して作品を制作します。\",\n    \"practical_course_notice\": \"案内\",\n    \"practical_course_desc\": \"<span class='practical_cource_title'>教科用を作成する</span>は<br />実科の教科書でソフトウェアを学ぶ時に<br />必要な機能のみを提供します。\",\n    \"practical_course_desc2\": \"*「基本型の作品を作る」を利用すると、さらに多くの機能を<br />使用して作品を作ることができます。\",\n    \"practical_course_tooltip\": \"すべての機能を利用するには<br/>基本型を選択してください。\",\n    \"name_already_exists\": \"名前が重複しています。\",\n    \"enter_the_name\": \"名前を入力してください。\",\n    \"object_not_exist_error\": \"オブジェクトが存在しません。オブジェクトを追加してからやり直してください。\",\n    \"workspace_tutorial_popup_desc\": \"<span class='practical_cource_title'>作品を作る</span>では<br />クリエイティブな作品づくりができるように<br /> いろんなブロックを用意しています。\",\n    \"start_guide_tutorial\": \"「作る」利用案内\",\n    \"language\": \"言語選択\",\n    \"file\": \"ファイル\",\n    \"save\": \"保存する\",\n    \"help\": \"ヘルプ\",\n    \"print\": \"印刷\",\n    \"undo\": \"元に戻す\",\n    \"redo\": \"やり直し\",\n    \"workspace_title_tooltip\": \"The default project name has changed. You can\\nrecognize what project is through the date you create in\\nthe project name.\",\n    \"workspace_object_tooltip\": \"You can change the order of the object by\\ndragging the image of the object. (It is the same\\nin the ‘Shape’ and ‘Sound’ sections.)\",\n    \"workspace_comment_tooltip\": \"You can hide or show all the memos\\nadded.\",\n    \"workspace_zoom_tooltip\": \"You can zoom in/out the blocks. If you click ‘=’\\nthe block will be back to original size.\",\n    \"workspace_image_tooltip\": \"Create your own\\nproject with new\\nfunctions!\",\n    \"playground_block_drop\": \"マイボックスのブロックを\\nブロック組み立て所に追加します。\",\n    \"container_object_drop\": \"マイボックスのオブジェクトを\\nオブジェクトリストに追加します。\",\n    \"my_storage_block_drop\": \"ブロックを\\nマイボックスに\\n追加します。\",\n    \"my_storage_object_drop\": \"オブジェクトを\\nマイボックスに\\n追加します。\",\n    \"my_storage\": \"マイボックス\",\n    \"my_block\": \"マイブロック\",\n    \"red\": \"赤(R)\",\n    \"green\": \"緑(G)\",\n    \"blue\": \"青(B)\",\n    \"hue\": \"色相\",\n    \"saturation\": \"彩度\",\n    \"brightness\": \"明度\",\n    \"spoid\": \"スポイト\",\n    \"palette_mode\": \"パレットモード\",\n    \"slider_mode\": \"スライダーモード\",\n    \"toast_error_title_object_center\": \"注意！\",\n    \"toast_error_contents_object_center\": \"キャラクターの中心点がキャラクターから離れすぎため、修正しました。\",\n    \"blocks_comming_soon\": \"熱心に研究中です。\\nちょっと待ってください!\",\n    \"data_table\": \"table\",\n    \"select_all\": \"모두\",\n    \"now_loading_msg\": \"読み込んでいます。\\nしばらくお待ちください。\"\n};\nLang.code = \"コードを見る\";\nLang.EntryStatic = {\n    \"event100\": \"イベント\",\n    \"groupProject\": \"クラスを共有する\",\n    \"usage_parallel\": \"並列\",\n    \"usage_expansion\": \"Expansion\",\n    \"usage_hw\": \"ハードウェア\",\n    \"usage_sequence\": \"順次\",\n    \"privateProject\": \"自分だけ見る\",\n    \"privateCurriculum\": \"自分だけ見る\",\n    \"publicCurriculum\": \"講義集を共有する\",\n    \"publicProject\": \"作品を共有する\",\n    \"group\": \"クラスを共有する\",\n    \"groupCurriculum\": \"クラスを共有する\",\n    \"private\": \"自分だけ見る\",\n    \"public\": \"講義を共有する\",\n    \"lecture_is_open_true\": \"公開\",\n    \"lecture_is_open_false\": \"非公開\",\n    \"category_all\": \"すべての作品\",\n    \"category_game\": \"ゲーム\",\n    \"category_animation\": \"アニメーション\",\n    \"category_media_art\": \"メディアアート\",\n    \"category_physical\": \"フィジカル\",\n    \"category_etc\": \"その他\",\n    \"category_category_game\": \"ゲーム\",\n    \"category_category_animation\": \"アニメーション\",\n    \"category_category_media_art\": \"メディアアート\",\n    \"category_category_physical\": \"フィジカル\",\n    \"category_category_etc\": \"その他\",\n    \"sort_created\": \"最新順\",\n    \"sort_updated\": \"最新順\",\n    \"sort_visit\": \"照会順\",\n    \"sort_likeCnt\": \"いいね!順\",\n    \"sort_comment\": \"コメント順\",\n    \"period_all\": \"すべての期間\",\n    \"period_1\": \"今日\",\n    \"period_7\": \"1週間以内\",\n    \"period_30\": \"1か月以内\",\n    \"period_90\": \"3か月以内\",\n    \"lecture_required_time_1\": \" ~ 15分\",\n    \"lecture_required_time_2\": \"15分 ~ 30分\",\n    \"lecture_required_time_3\": \"30分 ~ 45分\",\n    \"lecture_required_time_4\": \"45分 ~ 60分\",\n    \"lecture_required_time_5\": \"1時間以上\",\n    \"usage_event\": \"イベント\",\n    \"usage_signal\": \"信号を送る\",\n    \"usage_scene\": \"シーン\",\n    \"usage_repeat\": \"繰り返す\",\n    \"usage_condition_repeat\": \"条件繰り返し\",\n    \"usage_condition\": \"選択\",\n    \"usage_clone\": \"コピー\",\n    \"usage_rotation\": \"回転\",\n    \"usage_coordinate\": \"座標移動\",\n    \"usage_arrow_move\": \"矢印移動\",\n    \"usage_shape\": \"模様\",\n    \"usage_speak\": \"話す\",\n    \"usage_picture_effect\": \"図の効果\",\n    \"usage_textBox\": \"テキストボックス\",\n    \"usage_draw\": \"描画\",\n    \"usage_sound\": \"サウンド\",\n    \"usage_confirm\": \"判断\",\n    \"usage_comp_operation\": \"比較演算\",\n    \"usage_logical_operation\": \"論理演算\",\n    \"usage_math_operation\": \"数理演算\",\n    \"usage_random\": \"乱数\",\n    \"usage_timer\": \"ストップウォッチ\",\n    \"usage_variable\": \"変数\",\n    \"usage_list\": \"リスト\",\n    \"usage_ask_answer\": \"入出力\",\n    \"usage_function\": \"関数\",\n    \"usage_arduino\": \"Arduino\",\n    \"concept_resource_analytics\": \"資料収集/分析/表現\",\n    \"concept_procedual\": \"アルゴリズムと手順\",\n    \"concept_abstractive\": \"抽象化\",\n    \"concept_individual\": \"問題分解\",\n    \"concept_automation\": \"自動化\",\n    \"concept_simulation\": \"シミュレーション\",\n    \"concept_parallel\": \"並列化\",\n    \"subject_korean\": \"国語\",\n    \"subject_english\": \"英語\",\n    \"subject_mathmatics\": \"数学\",\n    \"subject_social\": \"社会\",\n    \"subject_science\": \"科学\",\n    \"subject_music\": \"音楽\",\n    \"subject_paint\": \"美術\",\n    \"subject_athletic\": \"体育\",\n    \"subject_courtesy\": \"道徳\",\n    \"subject_progmatic\": \"実科\",\n    \"lecture_grade_1\": \"小1\",\n    \"lecture_grade_2\": \"小2\",\n    \"lecture_grade_3\": \"小3\",\n    \"lecture_grade_4\": \"小4\",\n    \"lecture_grade_5\": \"小5\",\n    \"lecture_grade_6\": \"小6\",\n    \"lecture_grade_7\": \"中1\",\n    \"lecture_grade_8\": \"中2\",\n    \"lecture_grade_9\": \"中3\",\n    \"lecture_grade_10\": \"一般\",\n    \"lecture_level_1\": \"簡単\",\n    \"lecture_level_2\": \"普通\",\n    \"lecture_level_3\": \"難しい\",\n    \"listEnable\": \"リスト\",\n    \"functionEnable\": \"関数\",\n    \"messageEnable\": \"信号\",\n    \"objectEditable\": \"オブジェクト\",\n    \"pictureeditable\": \"模様\",\n    \"sceneEditable\": \"シーン\",\n    \"soundeditable\": \"サウンド\",\n    \"variableEnable\": \"変数\",\n    \"e_1\": \"小学校1年生\",\n    \"e_2\": \"小学校2年生\",\n    \"e_3\": \"小学校3年生\",\n    \"e_4\": \"小学校4年生\",\n    \"e_5\": \"小学校5年生\",\n    \"e_6\": \"小学校6年生\",\n    \"m_1\": \"中学校1年生\",\n    \"m_2\": \"中学校2年生\",\n    \"m_3\": \"中学校3年生\",\n    \"general\": \"一般\",\n    \"curriculum_is_open_true\": \"公開\",\n    \"curriculum_open_false\": \"非公開\",\n    \"contest2019\": \"Contest\",\n    \"exhibit\": \"Contest\",\n    \"notice\": \"お知らせ\",\n    \"qna\": \"Q＆A\",\n    \"tips\": \"ノウハウ&TIP\",\n    \"free\": \"自由掲示板\",\n    \"report\": \"提案と意見\",\n    \"art_category_all\": \"すべての作品\",\n    \"art_category_game\": \"ゲーム\",\n    \"art_category_animation\": \"アニメーション\",\n    \"art_category_physical\": \"フィジカル\",\n    \"art_category_etc\": \"その他\",\n    \"art_category_media\": \"メディアアート\",\n    \"art_sort_updated\": \"最新順\",\n    \"art_sort_visit\": \"照会順\",\n    \"art_sort_likeCnt\": \"いいね!順\",\n    \"art_sort_comment\": \"コメント順\",\n    \"art_period_all\": \"すべての期間\",\n    \"art_period_day\": \"今日\",\n    \"art_period_week\": \"1週間以内\",\n    \"art_period_month\": \"1か月以内\",\n    \"art_period_three_month\": \"3か月以内\",\n    \"level_high\": \"上\",\n    \"level_mid\": \"中\",\n    \"level_row\": \"下\",\n    \"discuss_sort_created\": \"最新順\",\n    \"discuss_sort_visit\": \"照会順\",\n    \"discuss_sort_likesLength\": \"いいね!順\",\n    \"discuss_sort_commentsLength\": \"コメント順\",\n    \"discuss_period_all\": \"すべての期間\",\n    \"discuss_period_day\": \"今日\",\n    \"discuss_period_week\": \"1週間以内\",\n    \"discuss_period_month\": \"1か月以内\",\n    \"discuss_period_three_month\": \"3か月以内\"\n};\nLang.Helper = {\n    \"when_run_button_click\": \"スタートボタンをクリックすると、下に連結されたブロックを実行します。\",\n    \"when_some_key_pressed\": \"指定されたキーを押すと、下に連結されたブロックを実行します\",\n    \"mouse_clicked\": \"マウスをクリックした時、下に連結されたブロックを実行します。\",\n    \"mouse_click_cancled\": \"マウスクリックを解除した時、下に連結されたブロックを実行します。\",\n    \"when_object_click\": \"当該オブジェクトをクリックした時、下に連結されたブロックを実行します。\",\n    \"when_object_click_canceled\": \"当該オブジェクトクリックを解除した時、下に連結されたブロックを実行します。\",\n    \"when_message_cast\": \"当該信号を受け取ると、連結されたブロックを実行します。\",\n    \"message_cast\": \"リストに選択された信号を送ります。\",\n    \"message_cast_wait\": \"リストに選択された信号を送り、その信号を受け取るブロックの実行が終わるまで待機します。\",\n    \"when_scene_start\": \"シーンが始まると下に連結されたブロックを実行します。\",\n    \"start_scene\": \"選択したシーンを始めます。\",\n    \"start_neighbor_scene\": \"前のシーンまたは次のシーンを始めます。\",\n    \"wait_second\": \"設定した時間だけ待機した後、次のブロックを実行します。\",\n    \"repeat_basic\": \"設定した回数だけ包んであるブロックを繰り返し実行します。\",\n    \"repeat_inf\": \"包んであるブロックを続けて繰り返し実行します。\",\n    \"repeat_while_true\": \"判断がtrueの間、包んであるブロックを繰り返し実行します。\",\n    \"stop_repeat\": \"このブロックを包む最も近いリピートブロックの繰り返しを中断します。\",\n    \"_if\": \"もし判断がtrueの場合、包んであるブロックを実行します。\",\n    \"if_else\": \"判断がtrueの場合、最初の包んであるブロックを実行し、Falseなら2番目の包んであるブロックを実行します。\",\n    \"restart_project\": \"すべてのオブジェクトを最初から再実行します。\",\n    \"stop_object\": \"すべての: すべてのオブジェクトが直ちに実行を中断します。<br> 自分 : 当該オブジェクトのすべてのブロックを中断します。<br> このコード: このブロックが含まれるコードが直ちに実行を中断します。<br> 自分の他のコード:  当該オブジェクトのうち、このブロックが含まれるコードを除くすべてのコードが直ちに実行を中断します。<br/>他のオブジェクトの: 他のオブジェクトのすべてのブロックを中断します。\",\n    \"wait_until_true\": \"判断がtrueになるまで実行を中断して待機します。\",\n    \"when_clone_start\": \"当該オブジェクトのコピーが新しく作成された時、下に連結されたブロックを実行します。\",\n    \"create_clone\": \"選択したオブジェクトのコピーを作成します。\",\n    \"delete_clone\": \"「コピーが最初に作成された時」ブロックを一緒に使用して作成されたコピーを削除します。\",\n    \"remove_all_clones\": \"当該オブジェクトのすべてのコピーを削除します。\",\n    \"move_direction\": \"設定した値だけオブジェクトの移動方向矢印が示す方向に動きます。\",\n    \"move_x\": \"オブジェクトのX座標を設定した値だけ変更します。\",\n    \"move_y\": \"オブジェクトのY座標を設定した値だけ変更します。\",\n    \"move_xy_time\": \"オブジェクトが入力した時間に渡り、xとy座標を設定した値だけ変更します。\",\n    \"locate_object_time\": \"オブジェクトが入力した時間に渡り、選択したオブジェクトまたはマウスポインターの位置に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate_x\": \"オブジェクトが入力したx座標に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate_y\": \"オブジェクトが入力したy座標に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate_xy\": \"オブジェクトが入力したxとy座標に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate_xy_time\": \"オブジェクトが入力した時間に渡り、指定したx, y座標に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate\": \"オブジェクトが選択したオブジェクトまたはマウスポインターの位置に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"rotate_absolute\": \"当該オブジェクトの方向を入力した角度にします。\",\n    \"rotate_by_time\": \"オブジェクトの方向を入力した時間に渡り、入力した角度だけ時計方向に回転します。(オブジェクトの中心点を基準に回転します。)\",\n    \"rotate_relative\": \"オブジェクトの方向を入力した角度だけ時計方向に回転します。(オブジェクトの中心点を基準に回転します。)\",\n    \"direction_absolute\": \"当該オブジェクトの移動方向を入力した角度にします。\",\n    \"direction_relative\": \"オブジェクトの移動方向を入力した角度だけ回転します。\",\n    \"move_to_angle\": \"設定した角度方向に入力した値だけ動きます。(実行画面の上側が0度、時計方向に行くたびに角度増加)\",\n    \"see_angle_object\": \"当該オブジェクトが他のオブジェクトまたはマウスポインターの方向を向きます。オブジェクトの移動方向が選択された項目を向くようにオブジェクトの方向を回転させます。\",\n    \"bounce_wall\": \"当該オブジェクトが画面の端に到達すると弾かれます。\",\n    \"show\": \"当該オブジェクトを画面に表示します。\",\n    \"hide\": \"当該オブジェクトを画面から非表示にします。\",\n    \"dialog_time\": \"オブジェクトが入力した内容を入力した時間中吹き出しで話した後、次のブロックが実行されます。\",\n    \"dialog\": \"オブジェクトが入力した内容を吹き出しで話すと同時に次のブロックが実行されます。\",\n    \"remove_dialog\": \"オブジェクトが話している吹き出しを消します。\",\n    \"change_to_some_shape\": \"オブジェクトを選択した模様に変更します。(内部ブロックを分離すれば模様の番号を使用して模様を選択できます)\",\n    \"change_to_next_shape\": \"オブジェクトの模様を次の模様に変更します。\",\n    \"set_effect_volume\": \"当該オブジェクトで選択した効果を入力した値だけ加えます。\",\n    \"set_effect_amount\": \"色 : オブジェクトに色効果を入力した値だけ加えます。(0~100を周期に反復)<br>明度 : オブジェクトに明度効果を入力した値だけ加えます。(-100~100の範囲。-100以下は-100で、100以上は100で処理) <br> 透明度 : オブジェクトに透明度効果を入力した値だけ加えます。(0~100の範囲。0以下は0で、100以上は100で処理)\",\n    \"set_effect\": \"当該オブジェクトの値を選択した効果を入力した値にします。\",\n    \"set_entity_effect\": \"当該オブジェクトの値を選択した効果を入力した値にします。\",\n    \"add_effect_amount\": \"当該オブジェクトに対し選択した効果を入力した値だけ加えます。\",\n    \"change_effect_amount\": \"色 : オブジェクトの色効果を入力した値にします。(0~100を周期として反復) <br> 明度 : オブジェクトの明度効果を入力した値にします。(-100~100の間の範囲。-100以下は-100で、100以上は100で処理) <br> 透明度 : オブジェクトの透明度効果を入力した値にします。(0~100の間の範囲。0以下は0で、100以上は100で処理)\",\n    \"change_scale_percent\": \"当該オブジェクトのサイズを入力した値だけ変更します。\",\n    \"set_scale_percent\": \"当該オブジェクトのサイズを入力した値にします。\",\n    \"change_scale_size\": \"当該オブジェクトのサイズを入力した値だけ変更します。\",\n    \"set_scale_size\": \"当該オブジェクトのサイズを入力した値にします。\",\n    \"flip_x\": \"当該オブジェクトの上下の模様を入れ替えます。\",\n    \"flip_y\": \"当該オブジェクトの左右の模様を入れ替えます。\",\n    \"change_object_index\": \"一番前に : 当該オブジェクトを画面の一番前に移動させます。<br> 前に : 当該オブジェクトを1レイヤー前に移動させます。<br> 後ろに : 当該オブジェクトを1レイヤー後ろに移動させます。<br> 一番後ろに : 当該オブジェクトを画面の一番後ろに移動させます。\",\n    \"set_object_order\": \"当該オブジェクトが設定した順序で上がります。\",\n    \"brush_stamp\": \"オブジェクトの模様を実行画面上にスタンプのように押します。\",\n    \"start_drawing\": \"オブジェクトが移動する経路に沿って線を引きます。(オブジェクトの中心点が基準)\",\n    \"stop_drawing\": \"オブジェクトが線を描くのを中断します。\",\n    \"set_color\": \"オブジェクトが描く線の色を選択した色にします。\",\n    \"set_random_color\": \"オブジェクトが描く線の色をランダムにします。\",\n    \"change_thickness\": \"オブジェクトが描く線の太さを入力した値に変更します。(1~無限の範囲。1以下は1で処理)\",\n    \"set_thickness\": \"オブジェクトが描く線の太さを入力した値にします。(1~無限の範囲。1以下は1で処理)\",\n    \"change_opacity\": \"当該オブジェクトが描く筆の透明度を入力した値だけ変更します。\",\n    \"change_brush_transparency\": \"当該オブジェクトが描く筆の透明度を入力した値だけ変更します。(0~100の範囲。0以下は0、100以上は100で処理)\",\n    \"set_opacity\": \"当該オブジェクトが描く筆の透明度を入力した値にします。\",\n    \"set_brush_tranparency\": \"当該オブジェクトが描く筆の透明度を入力した値にします。(0~100の範囲。0以下は0、100以上は100で処理)\",\n    \"brush_erase_all\": \"当該オブジェクトが描いた線とスタンプをすべて削除します。\",\n    \"sound_something_with_block\": \"当該オブジェクトが選択したサウンドを再生すると同時に、次のブロックを実行します。\",\n    \"sound_something_second_with_block\": \"当該オブジェクトが選択したサウンドを入力した時間だけ再生すると同時に、次のブロックを実行します。\",\n    \"sound_something_wait_with_block\": \"当該オブジェクトが選択したサウンドを再生し、サウンドの再生が終わると次のブロックを実行します。\",\n    \"sound_something_second_wait_with_block\": \"当該オブジェクトが選択したサウンドを入力した時間だけ再生し、サウンドの再生が終わると次のブロックを実行します。\",\n    \"sound_volume_change\": \"作品で再生されるすべてのサウンドのボリュームを入力したパーセント分変更します。\",\n    \"sound_volume_set\": \"作品で再生されるすべてのサウンドのボリュームを入力したパーセントにします。\",\n    \"sound_silent_all\": \"現在再生中のすべてのサウンドをストップします。\",\n    \"is_clicked\": \"マウスをクリックした場合、「true」と判断します。\",\n    \"is_press_some_key\": \"選択したキーが押されている場合、「true」と判断します。\",\n    \"reach_something\": \"当該オブジェクトが選択した項目に触れた場合、「true」と判断します。\",\n    \"is_included_in_list\": \"選択したリストに入力した値を持つ項目が含まれているか確認します。\",\n    \"boolean_basic_operator\": \"= : 左側に位置する値と右側に位置する値が同じなら「true」と判断します。<br>> : 左側に位置する値が右側に位置する値より大きいなら「true」と判断します。<br>< : 左側に位置する値が右側に位置する値より小さいなら「true」と判断します。<br>≥ : 左側に位置する値が右側に位置する値より大きいか同じなら「true」と判断します。<br>≤ : 左側に位置する値が右側に位置する値より小さいか同じなら「true」と判断します。\",\n    \"function_create\": \"よく使うコードをこのブロック下に並べて組み立てて関数として作成します。[関数を定義する]の右側の空白セルに[名前]を並べて関数名を決めることができます。関数を実行する際に入力値が必要な場合、空白セルに[文字/数字値]、[判断値]を並べて媒介変数として使用します。\",\n    \"function_field_label\": \"「関数を定義する」の空白セル中に組み立て、名前を入力して関数名を決定します。\",\n    \"function_field_string\": \"当該関数を実行するにあたり文字/数字値が必要な場合、空白セルの中に並べて媒介変数として使用します。このブロック内部の[文字/数字値]を分離して関数のコードのうち必要な部分に入れて使用します。\",\n    \"function_field_boolean\": \"当該関数を実行するにあたりtrueまたはfalseの判断が必要な場合、空白セルの中に並べて媒介変数として使用します。このブロック内部の[判断値]を分離して関数のコードのうち必要な部分に入れて使用します。\",\n    \"function_general\": \"現在作成している関数ブロックまたは今まで作成しておいた関数ブロックです。\",\n    \"boolean_and\": \"2つの判断がすべてtrueの場合、「true」と判断します。\",\n    \"boolean_or\": \"2つの判断のうち1つでもtrueがある場合、「true」と判断します。\",\n    \"boolean_not\": \"判断がTrueならfalse、Falseならtrueにします。\",\n    \"is_boost_mode\": \"ブーストモードがオンになっている場合は「正しい」で判断します。\",\n    \"calc_basic\": \"+ : 入力した2つの数を足した値です。<br>- : 入力した2つの数を引いた値です。<br>X : 入力した2つの数をかけた値です。<br>/ : 入力した2つの数を割った値です。\",\n    \"calc_rand\": \"入力した2つの数の間から選択された乱数の値です。(2つの数とも整数を入力した場合は整数が、2つの数のうち1つでも少数を入力した場合は少数が乱数として選択されます。)\",\n    \"get_x_coordinate\": \"当該オブジェクトのx座標値を表します。\",\n    \"get_y_coordinate\": \"当該オブジェクトのy座標値を表します。\",\n    \"coordinate_mouse\": \"マウスポインターのxまたはyの座標値を表します。\",\n    \"coordinate_object\": \"選択したオブジェクトまたは自分の各種情報値(x座標、y座標、方向、移動方向、サイズ、模様番号、模様名)です。\",\n    \"quotient_and_mod\": \"商 : 前の数で後ろの数を割って得られた商の値です。<br> あまり : 前の数で後ろの数を割って得られたあまりの値です。\",\n    \"get_rotation_direction\": \"当該オブジェクトの方向値、移動方向値を表します。\",\n    \"calc_share\": \"前の数で後ろの数を割って得られた商を表します。\",\n    \"calc_mod\": \"前の数で後ろの数を割って得られたあまりを表します。\",\n    \"calc_operation\": \"入力した数に関する様々な数学式の計算値です。\",\n    \"get_date\": \"現在の年度、月、日、時刻などの時間に関する値です。\",\n    \"distance_something\": \"自分と選択したオブジェクトまたはマウスポインター間の距離の値です。\",\n    \"get_sound_duration\": \"選択したサウンドの長さ(秒)の値です。\",\n    \"get_user_name\": \"作品を実行しているユーザーのIDの値です。\",\n    \"get_nickname\": \"作品をプレーしているユーザーのニックネーム値です。\",\n    \"get_project_timer_value\": \"このブロックが実行された瞬間、ストップウォッチに保存された値です。\",\n    \"choose_project_timer_action\": \"スタート: ストップウォッチを始めます。<br> 停止する: ストップウォッチを停止します。<br> 初期化する: ストップウォッチの値を0に初期化します。<br> (このブロックをブロック組立所に持っていくと、実行画面に「ストップウォッチウィンドウ」が作成されます。)\",\n    \"reset_project_timer\": \"実行されていたタイマーを0に初期化します。\",\n    \"set_visible_project_timer\": \"ストップウォッチウィンドウを画面で表示または非表示にします。\",\n    \"ask_and_wait\": \"当該オブジェクトが入力した文字を吹き出しで尋ね、回答の入力を受けます。(このブロックをブロック組立所に持っていくと、実行画面に「回答ウィンドウ」が作成されます。)\",\n    \"get_canvas_input_value\": \"尋ねて待機により入力された値です。\",\n    \"set_visible_answer\": \"実行画面にある「回答ウィンドウ」を表示または非表示にできます。\",\n    \"combine_something\": \"入力した2つの資料を結合した値です。\",\n    \"get_variable\": \"選択された変数に保存された値です。\",\n    \"change_variable\": \"選択した変数に入力した値を足します。\",\n    \"set_variable\": \"選択した変数の値を入力した値にします。\",\n    \"robotis_carCont_sensor_value\": \"왼쪽 접속 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>오른쪽 접촉 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>선택 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.<br/>최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>왼쪽 적외선 센서 : 물체와 가까울 수록 큰 값 입니다.<br/>오른쪽 적외선 센서 : 물체와 가까울 수록 큰 값 값 입니다.<br/>왼쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>오른쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>(*캘리브레이션 값 - 적외선센서 조정 값)\",\n    \"robotis_carCont_cm_led\": \"4개의 LED 중 1번 또는 4번 LED 를 켜거나 끕니다.<br/>LED 2번과 3번은 동작 지원하지 않습니다.\",\n    \"robotis_carCont_cm_sound_detected_clear\": \"최종 소리 감지횟 수를 0 으로 초기화 합니다.\",\n    \"robotis_carCont_aux_motor_speed\": \"감속모터 속도를 0 ~ 1023 의 값(으)로 정합니다.\",\n    \"robotis_carCont_cm_calibration\": \"적외선센서 조정 값(http://support.robotis.com/ko/: 자동차로봇> 2. B. 적외선 값 조정)을 직접 정합니다.\",\n    \"robotis_openCM70_sensor_value\": \"최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.\",\n    \"robotis_openCM70_aux_sensor_value\": \"서보모터 위치 : 0 ~ 1023, 중간 위치의 값은 512 입니다.<br/>적외선센서 :  물체와 가까울 수록 큰 값 입니다.<br/>접촉센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>조도센서(CDS) : 0 ~ 1023, 밝을 수록 큰 값 입니다.<br/>온습도센서(습도) : 0 ~ 100, 습할 수록 큰 값 입니다.<br/>온습도센서(온도) : -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>온도센서 :  -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>초음파센서 : -<br/>자석센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>동작감지센서 : 동작 감지(1), 동작 미감지(0) 값 입니다.<br/>컬러센서 : 알수없음(0), 흰색(1), 검은색(2), 빨간색(3), 녹색(4), 파란색(5), 노란색(6) 값 입니다.<br/>사용자 장치 : 사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.\",\n    \"robotis_openCM70_cm_buzzer_index\": \"음계를 0.1 ~ 5 초 동안 연주 합니다.\",\n    \"robotis_openCM70_cm_buzzer_melody\": \"멜로디를 연주 합니다.<br/>멜로디를 연속으로 재생하는 경우, 다음 소리가 재생되지 않으면 '흐름 > X 초 기다리기' 블록을 사용하여 기다린 후 실행합니다.\",\n    \"robotis_openCM70_cm_sound_detected_clear\": \"최종 소리 감지횟 수를 0 으로 초기화 합니다.\",\n    \"robotis_openCM70_cm_led\": \"제어기의 빨간색, 녹색, 파란색 LED 를 켜거나 끕니다.\",\n    \"robotis_openCM70_cm_motion\": \"제어기에 다운로드 되어있는 모션을 실행합니다.\",\n    \"robotis_openCM70_cm_autodrive_motor\": \"자율주행 자동차의 모터 포트를 지정합니다.\",\n    \"robotis_openCM70_cm_autodrive_ir\": \"자율주행 자동차의 적외선 센서 포트를 지정합니다.\",\n    \"robotis_openCM70_cm_autodrive_speed\": \"지정한 속도로 자율주행을 수행합니다.\",\n    \"robotis_openCM70_aux_car_move\": \"로봇을 지정한 속도와 방향으로 움직이도록 합니다.\",\n    \"robotis_openCM70_aux_motor_speed\": \"감속모터 속도를 0 ~ 100% 의 값으로 정합니다.\",\n    \"robotis_openCM70_aux_servo_mode\": \"서보모터를 회전모드 또는 관절모드로 정합니다.<br/>한번 설정된 모드는 계속 적용됩니다.<br/>회전모드는 서보모터 속도를 지정하여 서보모터를 회전 시킵니다.<br/>관절모드는 지정한 서보모터 속도로 서보모터 위치를 이동 시킵니다.\",\n    \"robotis_openCM70_aux_servo_speed\": \"서보모터 속도를 0 ~ 100% 의 값으로 정합니다.\",\n    \"robotis_openCM70_aux_servo_position\": \"서보모터 위치를 -150도 ~ 150도 의 값(으)로 정합니다.<br/>서보모터 속도와 같이 사용해야 합니다.\",\n    \"robotis_openCM70_aux_led_module\": \"LED 모듈의 LED 를 켜거나 끕니다.\",\n    \"robotis_openCM70_aux_custom\": \"사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.\",\n    \"robotis_openCM70_cm_poweroff_timer\": \"제어기의 자동꺼짐 타이머를 설정합니다.<br/>설정된 만큼의 시간동안 통신이 진행되지 않으면 제어기는 자동으로 꺼집니다.\",\n    \"robotis_openCM70_cm_custom_value\": \"컨트롤 테이블 주소를 직접 입력하여 값을 확인 합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.\",\n    \"robotis_openCM70_cm_custom\": \"컨트롤 테이블 주소를 직접 입력하여 값을 정합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.\",\n    \"show_variable\": \"選択した変数ウィンドウを実行画面に表示します。\",\n    \"hide_variable\": \"選択した変数ウィンドウを実行画面で非表示にします。\",\n    \"value_of_index_from_list\": \"選択したリストで選択した値の順序にある項目値を表します。(内部ブロックを分離すると順序を数字で入力できます)\",\n    \"add_value_to_list\": \"入力した値が選択したリストの最後の項目に追加されます。\",\n    \"remove_value_from_list\": \"選択したリストの入力した順序にある項目を削除します。\",\n    \"insert_value_to_list\": \"選択したリストの入力した順序の位置に入力した項目を挿入します。(入力した項目の後にある各項目の順番は1つずつずれます。)\",\n    \"change_value_list_index\": \"選択したリストで入力した順序にある項目の値を入力した値に変更します。\",\n    \"length_of_list\": \"選択したリストが保有した項目の個数の値です。\",\n    \"show_list\": \"選択したリストを実行画面に表示します。\",\n    \"hide_list\": \"選択したリストを実行画面で非表示にします。\",\n    \"text\": \"当該テキストボックスが表示している文字値を表します。\",\n    \"text_read\": \"선택한 글상자 또는 글상자 자신의 내용입니다.<br />(내용 안에 줄바꿈이 있는 경우, 띄어쓰기하여 반환됩니다.)\",\n    \"text_write\": \"テキストボックスの内容を入力した値に書き換えます。\",\n    \"text_append\": \"テキストボックスの内容の後に入力した値を追加します。\",\n    \"text_prepend\": \"テキストボックスの内容の前に入力した値を追加します。\",\n    \"text_flush\": \"テキストボックスに保存された値をすべて削除します。\",\n    \"erase_all_effects\": \"当該オブジェクトに適用された効果をすべて削除します。\",\n    \"char_at\": \"入力した文字/数字値のうち入力した数字の 番目の文字値です。\",\n    \"length_of_string\": \"入力した文字値のスペースを含む文字数です。\",\n    \"substring\": \"入力した文字/数字値で入力した範囲内の文字/数字値です。\",\n    \"replace_string\": \"入力した文字/数字値で指定した文字/数字値を探し、追加入力した文字/数字値にすべて置き換えた値です。(英文字で入力する場合、大文字と小文字を区別します。)\",\n    \"index_of_string\": \"入力した文字/数字値で指定した文字/数字値が最初に登場する位置の値です。(やあ、エントリー!でエントリーの開始位置は5)\",\n    \"change_string_case\": \"入力した英文字のすべてのアルファベットを大文字または小文字に置き換えた文字値を表します。\",\n    \"direction_relative_duration\": \"当該オブジェクトの移動方向を入力した時間に渡り、入力した角度だけ時計方向に回転します。\",\n    \"get_sound_volume\": \"現在、作品に設定されているサウンドのボリューム値を表します。\",\n    \"sound_from_to\": \"当該オブジェクトが選択したサウンドを入力した時間部分だけ再生すると同時に次のブロックを実行します。\",\n    \"sound_from_to_and_wait\": \"当該オブジェクトが選択したサウンドを入力した時間部分だけ再生し、サウンドの再生が終わると次のブロックを実行します。\",\n    \"Block_info\": \"ブロック説明\",\n    \"Block_click_msg\": \"ブロックをクリックすると、ブロックに関する説明が表示されます。\",\n    \"hamster_beep\": \"버저 소리를 짧게 냅니다.\",\n    \"hamster_change_both_wheels_by\": \"왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"hamster_change_buzzer_by\": \"버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.\",\n    \"hamster_change_output_by\": \"선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH\",\n    \"hamster_change_tempo_by\": \"연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.\",\n    \"hamster_change_wheel_by\": \"왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"hamster_clear_buzzer\": \"버저 소리를 끕니다.\",\n    \"hamster_clear_led\": \"왼쪽/오른쪽/양쪽 LED를 끕니다.\",\n    \"hamster_follow_line_until\": \"왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.\",\n    \"hamster_follow_line_using\": \"왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.\",\n    \"hamster_hand_found\": \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"hamster_move_backward_for_secs\": \"입력한 시간(초) 동안 뒤로 이동합니다.\",\n    \"hamster_move_forward_for_secs\": \"입력한 시간(초) 동안 앞으로 이동합니다.\",\n    \"hamster_move_forward_once\": \"말판 위에서 한 칸 앞으로 이동합니다.\",\n    \"hamster_play_note_for\": \"선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.\",\n    \"hamster_rest_for\": \"입력한 박자만큼 쉽니다.\",\n    \"hamster_set_both_wheels_to\": \"왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"hamster_set_buzzer_to\": \"버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.\",\n    \"hamster_set_following_speed_to\": \"선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.\",\n    \"hamster_set_led_to\": \"왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.\",\n    \"hamster_set_output_to\": \"선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH\",\n    \"hamster_set_port_to\": \"선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.\",\n    \"hamster_set_tempo_to\": \"연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.\",\n    \"hamster_set_wheel_to\": \"왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"hamster_stop\": \"양쪽 바퀴를 정지합니다.\",\n    \"hamster_turn_for_secs\": \"입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.\",\n    \"hamster_turn_once\": \"말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.\",\n    \"hamster_value\": \"왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)\",\n    \"roboid_hamster_beep\": \"버저 소리를 짧게 냅니다.\",\n    \"roboid_hamster_change_both_wheels_by\": \"왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"roboid_hamster_change_buzzer_by\": \"버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.\",\n    \"roboid_hamster_change_output_by\": \"선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH\",\n    \"roboid_hamster_change_tempo_by\": \"연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.\",\n    \"roboid_hamster_change_wheel_by\": \"왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"roboid_hamster_clear_buzzer\": \"버저 소리를 끕니다.\",\n    \"roboid_hamster_clear_led\": \"왼쪽/오른쪽/양쪽 LED를 끕니다.\",\n    \"roboid_hamster_follow_line_until\": \"왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.\",\n    \"roboid_hamster_follow_line_using\": \"왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.\",\n    \"roboid_hamster_hand_found\": \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"roboid_hamster_move_backward_for_secs\": \"입력한 시간(초) 동안 뒤로 이동합니다.\",\n    \"roboid_hamster_move_forward_for_secs\": \"입력한 시간(초) 동안 앞으로 이동합니다.\",\n    \"roboid_hamster_move_forward_once\": \"말판 위에서 한 칸 앞으로 이동합니다.\",\n    \"roboid_hamster_play_note_for\": \"선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.\",\n    \"roboid_hamster_rest_for\": \"입력한 박자만큼 쉽니다.\",\n    \"roboid_hamster_set_both_wheels_to\": \"왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"roboid_hamster_set_buzzer_to\": \"버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.\",\n    \"roboid_hamster_set_following_speed_to\": \"선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.\",\n    \"roboid_hamster_set_led_to\": \"왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.\",\n    \"roboid_hamster_set_output_to\": \"선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH\",\n    \"roboid_hamster_set_port_to\": \"선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.\",\n    \"roboid_hamster_set_tempo_to\": \"연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.\",\n    \"roboid_hamster_set_wheel_to\": \"왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"roboid_hamster_stop\": \"양쪽 바퀴를 정지합니다.\",\n    \"roboid_hamster_turn_for_secs\": \"입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.\",\n    \"roboid_hamster_turn_once\": \"말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.\",\n    \"roboid_hamster_value\": \"왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)\",\n    \"roboid_turtle_button_state\": \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"roboid_turtle_change_buzzer_by\": \"버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.\",\n    \"roboid_turtle_change_head_led_by_rgb\": \"머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.\",\n    \"roboid_turtle_change_tempo_by\": \"연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.\",\n    \"roboid_turtle_change_wheel_by\": \"왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"roboid_turtle_change_wheels_by_left_right\": \"왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"roboid_turtle_clear_head_led\": \"머리 LED를 끕니다.\",\n    \"roboid_turtle_clear_sound\": \"소리를 끕니다.\",\n    \"roboid_turtle_cross_intersection\": \"검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.\",\n    \"roboid_turtle_follow_line\": \"하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.\",\n    \"roboid_turtle_follow_line_until\": \"하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.\",\n    \"roboid_turtle_follow_line_until_black\": \"하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.\",\n    \"roboid_turtle_is_color_pattern\": \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"roboid_turtle_move_backward_unit\": \"입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.\",\n    \"roboid_turtle_move_forward_unit\": \"입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.\",\n    \"roboid_turtle_pivot_around_wheel_unit_in_direction\": \"왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.\",\n    \"roboid_turtle_play_note\": \"선택한 계이름과 옥타브의 음을 계속 소리 냅니다.\",\n    \"roboid_turtle_play_note_for_beats\": \"선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.\",\n    \"roboid_turtle_play_sound_times\": \"선택한 소리를 입력한 횟수만큼 재생합니다.\",\n    \"roboid_turtle_play_sound_times_until_done\": \"선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.\",\n    \"roboid_turtle_rest_for_beats\": \"입력한 박자만큼 쉽니다.\",\n    \"roboid_turtle_set_buzzer_to\": \"버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.\",\n    \"roboid_turtle_set_following_speed_to\": \"선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.\",\n    \"roboid_turtle_set_head_led_to\": \"머리 LED를 선택한 색깔로 켭니다.\",\n    \"roboid_turtle_set_head_led_to_rgb\": \"머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.\",\n    \"roboid_turtle_set_tempo_to\": \"연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.\",\n    \"roboid_turtle_set_wheel_to\": \"왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"roboid_turtle_set_wheels_to_left_right\": \"왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"roboid_turtle_stop\": \"양쪽 바퀴를 정지합니다.\",\n    \"roboid_turtle_touching_color\": \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"roboid_turtle_turn_at_intersection\": \"검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.\",\n    \"roboid_turtle_turn_unit_in_place\": \"입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.\",\n    \"roboid_turtle_turn_unit_with_radius_in_direction\": \"입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.\",\n    \"roboid_turtle_value\": \"색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.\",\n    \"turtle_button_state\": \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"turtle_change_buzzer_by\": \"버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.\",\n    \"turtle_change_head_led_by_rgb\": \"머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.\",\n    \"turtle_change_tempo_by\": \"연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.\",\n    \"turtle_change_wheel_by\": \"왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"turtle_change_wheels_by_left_right\": \"왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"turtle_clear_head_led\": \"머리 LED를 끕니다.\",\n    \"turtle_clear_sound\": \"소리를 끕니다.\",\n    \"turtle_cross_intersection\": \"검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.\",\n    \"turtle_follow_line\": \"하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.\",\n    \"turtle_follow_line_until\": \"하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.\",\n    \"turtle_follow_line_until_black\": \"하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.\",\n    \"turtle_is_color_pattern\": \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"turtle_move_backward_unit\": \"입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.\",\n    \"turtle_move_forward_unit\": \"입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.\",\n    \"turtle_pivot_around_wheel_unit_in_direction\": \"왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.\",\n    \"turtle_play_note\": \"선택한 계이름과 옥타브의 음을 계속 소리 냅니다.\",\n    \"turtle_play_note_for_beats\": \"선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.\",\n    \"turtle_play_sound_times\": \"선택한 소리를 입력한 횟수만큼 재생합니다.\",\n    \"turtle_play_sound_times_until_done\": \"선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.\",\n    \"turtle_rest_for_beats\": \"입력한 박자만큼 쉽니다.\",\n    \"turtle_set_buzzer_to\": \"버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.\",\n    \"turtle_set_following_speed_to\": \"선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.\",\n    \"turtle_set_head_led_to\": \"머리 LED를 선택한 색깔로 켭니다.\",\n    \"turtle_set_head_led_to_rgb\": \"머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.\",\n    \"turtle_set_tempo_to\": \"연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.\",\n    \"turtle_set_wheel_to\": \"왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"turtle_set_wheels_to_left_right\": \"왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"turtle_stop\": \"양쪽 바퀴를 정지합니다.\",\n    \"turtle_touching_color\": \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"turtle_turn_at_intersection\": \"검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.\",\n    \"turtle_turn_unit_in_place\": \"입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.\",\n    \"turtle_turn_unit_with_radius_in_direction\": \"입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.\",\n    \"turtle_value\": \"색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.\",\n    \"neobot_sensor_value\": \"IN1 ~ IN3 포트 및 리모컨에서 입력되는 값 그리고 배터리 정보를 0부터 255의 숫자로 표시합니다.\",\n    \"neobot_sensor_convert_scale\": \"선택한 포트 입력값의 변화를 특정범위의 값으로 표현범위를 조절할 수 있습니다.\",\n    \"neobot_left_motor\": \"L모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.\",\n    \"neobot_stop_left_motor\": \"L모터 포트에 연결한 모터를 정지합니다.\",\n    \"neobot_right_motor\": \"R모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.\",\n    \"neobot_stop_right_motor\": \"R모터 포트에 연결한 모터를 정지합니다.\",\n    \"neobot_all_motor\": \"L모터 및 R모터 포트에 2개 모터를 연결하여 바퀴로 활용할 때 전, 후, 좌, 우 이동 방향 및 속도, 시간을 설정할 수 있습니다.\",\n    \"neobot_stop_all_motor\": \"L모터 및 R모터에 연결한 모터를 모두 정지합니다.\",\n    \"neobot_set_servo\": \"OUT1 ~ OUT3에 서보모터를 연결했을 때 0도 ~ 180도 범위 내에서 각도를 조절할 수 있습니다.\",\n    \"neobot_set_output\": \"OUT1 ~ OUT3에 라이팅블록 및 전자회로를 연결했을 때 출력 전압을 설정할 수 있습니다.</br>0은 0V, 1 ~ 255는 2.4 ~ 4.96V의 전압을 나타냅니다.\",\n    \"neobot_set_fnd\": \"FND로 0~99 까지의 숫자를 표시할 수 있습니다.\",\n    \"neobot_set_fnd_off\": \"FND에 표시한 숫자를 끌 수 있습니다.\",\n    \"neobot_play_note_for\": \"주파수 발진 방법을 이용해 멜로디에 반음 단위의 멜로디 음을 발생시킬 수 있습니다.\",\n    \"rotate_by_angle_dropdown\": \"オブジェクトの方向を入力した角度だけ時計方向に回転します。(オブジェクトの中心点を基準に回転します。)\",\n    \"chocopi_control_button\": \"버튼이 눌리면 참이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_control_event\": \"버튼을 누르거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_control_joystick\": \"조이스틱 좌우, 상하, 볼륨의 값은 0~4095까지 입니다.<br/>따라서 2047 근처가 중간이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_dc_motor\": \"DC모터 모듈에는 직류전동기 두개를 연결 할 수 있습니다.<br/> 직류 전동기는 최대 5V로 동작하게 됩니다.<br/>값은 100이 최대(100%)이고 음수를 넣으면 반대 방향으로 회전합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_led\": \"LED번호는 LED블록에 연결된 순서이고 1번부터 시작합니다.<br/>RGB값은 0~255사이의 값입니다.<br/>빨강(Red),녹색(Green), 파랑(Blue)순서로  입력합니다.<br/>밝은 LED를 직접보면 눈이 아프니까 값을 0~5정도로 씁니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_motion_photogate_event\": \"포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br/>빛센서를 물체로 가리거나 치우면 시작되는 엔트리 블록을 연결합니다<br/>모션 모듈에는 포토게이트 2개를 연결할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_motion_photogate_status\": \"포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>물체가 빛센서를 가리면 참</b>이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_motion_photogate_time\": \"포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>이 블록은 물체가 빛센서를 가리거나 벗어난 시간을 가집니다.<br/>1/10000초까지 측정할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_motion_value\": \"모션 모듈에는 3개의 적외선 센서가 있습니다.<br/>0~4095사이의 값을 가질 수 있는데 물체가 빛을 많이 반사할 수록 작은 값을 가집니다. <br/>거리를 대략적으로 측정할 수 있습니다. <br/>가속도와 각가속도 값의 범위는 -32768~32767 까지입니다.<br/>가속도를 이용해서 센서의 기울기를 측정할 수도 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_sensor\": \"온도 값은 섭씨 온도입니다.<br/>습도 값은 백분율로 나타낸 상대습도 값입니다.<br/>빛은 로그스케일로 0~4095사이입니다.<br/>아날로그 값은 0~4095사이입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_servo_motor\": \"서보모터 모듈에는 4개의 서보모터를 연결 할 수 있습니다.<br/>서보모터는 5V로 동작하게 됩니다.<br/>각도는 0~200도까지 지정할 수 있습니다.<br/>연속회전식 서보모터를 연결하면 각도에 따라 속도가 변하게됩니다.<br/>90~100 사이가 중간값입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_touch_event\": \"터치 모듈에는 1~12번의 연결 패드가 있습니다. <br/>만지거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_touch_status\": \"터치 모듈의 패드를 만지면 참이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_touch_value\": \"터치패드에 연결된 물체의 전기용량이 커지면 값이 작아집니다.<br/>여러 명이 손잡고 만지면 더 작은 값이 됩니다.<br/>전기용량이란 물체에 전기를 띈 입자를 얼마나 가지고 있을 수 있는 지를 말합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"boolean_and_or\": \"そして : 2つの判断がすべてtrueの場合、「true」と判断します。<br>または: 2つの判断のうち1つでもtrueがある場合、「true」と判断します。\",\n    \"check_weather\": \"<br>선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈\",\n    \"check_finedust\": \"<br>선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨\",\n    \"get_weather_data\": \"<br>선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)\",\n    \"get_current_weather_data\": \"<br>현재 선택한 지역의 날씨 정보값(기온, 미세먼지농도)입니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 정보: (기온(℃)), 미세먼지농도(㎍)\",\n    \"get_today_temperature\": \"<br>오늘 선택한 지역과 시간대의 기온을 의미합니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 시간대: 00, 03, 06, 09, 12, 15, 18, 21\",\n    \"check_city_weather\": \"<br>선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈\",\n    \"check_city_finedust\": \"<br>선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨\",\n    \"get_city_weather_data\": \"<br>선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)\",\n    \"get_current_city_weather_data\": \"<br>현재 선택한 지역의 날씨 정보값(기온, 미세먼지농도)입니다.<br> * 옵션<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 정보: (기온(℃)), 미세먼지농도(㎍)\",\n    \"get_today_city_temperature\": \"<br>오늘 선택한 지역과 시간대의 기온을 의미합니다.<br> * 옵션<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 시간대: 00, 03, 06, 09, 12, 15, 18, 21\",\n    \"count_festival\": \"<br>選択した日付と地域で開催されるイベントの数です。\",\n    \"get_festival_info\": \"<br>選択した日付と地域で開催されるイベントの情報です。\",\n    \"get_translated_string\": \"<br>入力されたテキストを選択した言語に翻訳します。テキストは3000字まで入力可能です。\",\n    \"check_language\": \"<br>入力されたテキストの言語を検出します。テキストは文章の形で、3000字まで入力可能です。\",\n    \"count_disaster_behavior\": \"<br>選択した自然災害が発生した時に取るべき行動要領の数です。\",\n    \"get_disaster_behavior\": \"<br>選択した自然災害が発生した時に取るべき行動要領についての情報です。\",\n    \"count_lifeSafety_behavior\": \"<br>選択した、生活トラブルが生じた時に取るべき行動要領の数です。\",\n    \"get_lifeSafety_behavior\": \"<br>選択した、生活トラブルが生じた時に取るべき行動要領についての情報です。\",\n    \"read_text\": \"入力した文字列を設定した音声で読み上げます。\",\n    \"set_tts_property\": \"選択した音声が選択した速度と選択したピッチで設定されます。\",\n    \"read_text_wait_with_block\": \"入力した文字列を設定した音声で読み上げし、読み上げが終わると次のブロックを実行します。\",\n    \"check_microphone\": \"コンピューターにマイクが接続されている場合、「正」と判断します。\",\n    \"speech_to_text_convert\": \"マイクへの音声入力をテキストに変換します。\",\n    \"get_microphone_volume\": \"マイクに入力される音の大きさです。\",\n    \"speech_to_text_get_value\": \"音声をテキストに変換した値を報告します。 音声が入力されない場合、または音声認識中にエラーが発生した場合、値は0になります。\",\n    \"video_draw_webcam\": \"コンピューターに接続されたカメラの撮影画面を実行画面で表示または非表示にします。\",\n    \"video_check_webcam\": \"コンピューターにカメラが接続されている場合、「正」と判断します。\",\n    \"video_set_camera_option\": \"撮影画面の効果を入力した値に決めます。 明度：-100～100の間の範囲で設定できます。(-100以下は-100で、100以上は100で処理されます) 透明度：0～100の間の範囲で設定できます。(0以下は0で、100以上は100で処理されます)\",\n    \"video_flip_camera\": \"撮影画面を左右または上下に反転させます。\",\n    \"video_toggle_model\": \"選んだ認識モデールの作動を始めたり、止めたりします。 顔を認識: 人の顔を認識して、目、鼻、口、耳の位置や人の予想性別、歳、感情を分析します。 体を認識: 人の体を認識して、それぞれの身体部位などを分析します。 物を認識: 認識された物の種類を分析します。(人や物)\",\n    \"video_toggle_ind\": \"認識され 人 / た顔 / 物事 の位置と順番を実行画面に表示または非表示にします。\",\n    \"video_number_detect\": \"撮影画面にオブジェクトとして認識されたオブジェクトの数です。認識できるオブジェクト：人、自転車、自動車、オートバイ、飛行機、バス、電車、トラック、ボート、信号機、消火栓、停止信号、駐車メーター、ベンチ、鳥、猫、犬、馬、羊、雌牛、ゾウ、クマ、シマウマ、キリン、リュック、傘、ハンドバック、ネクタイ、かばん、フリスビー、スキー、スノーボード、スポーツボール、凧、野球バット、野球グローブ、スケートボード、サーフボード、テニスラケット、瓶、ワイングラス、コップ、フォーク、ナイフ、スプーン、皿、バナナ、アップル、サンドイッチ、オレンジ色、ブロッコリー、にんじん、ホットドッグ、ピザ、ドーナツ、ケーキ、椅子、ソファ、鉢植え、ベッド、食事テーブル、トイレ、テレビモニター、ノートパソコン、マウス、リモコン、キーボード、携帯電話、電子レンジ、オーブン、トースター、シンク、冷蔵庫、図書、時計、花瓶、はさみ、テディベア、ヘアドライヤー、歯ブラシ\",\n    \"video_detected_face_info\": \"入力した順番の顔に関する選択した情報の推定値です。上手く認識できない場合、必ず0で出力されます。(性別、年齢、感情)\",\n    \"video_motion_value\": \"選択したオブジェクトまたは実行画面上で感知されるモーション、もしくは方向値です。 モーション：動きが大きく速いほど値が大きくなります。 方向：右側もしくは上側に動くときは陽数、左側もしくは下側に動くときは陰数になります。\",\n    \"video_face_part_coord\": \"入力した順番の顔の中で、選択した顔の部位の位置値です。上手く認識できない場合、必ず0で出力されます。(左眼、右眼、鼻、左口、右口,上唇,下唇)\",\n    \"video_body_part_coord\": \"入力した順番の人に関して選択した身体部位の位置値です。(顔、左肩、左肘、左手首、左尻、左膝、左足首、右肩、右肘、右手首、右尻、右膝、右足首)\",\n    \"append_row_to_table\": \"Adds a row(col) to the end location of the selected table.\",\n    \"insert_row_to_table\": \"Inserts a row(col) to the location of the input value on the selected table.\",\n    \"delete_row_from_table\": \"Deletes the row(col) at the location of input value from the selected table.\",\n    \"set_value_from_table\": \"Replaces value of selected attribute at the location of the input value to the input value.\",\n    \"get_table_count\": \"Reports the number of rows or attribute on the selected table.\",\n    \"get_value_from_table\": \"Reports the value of selected attribute at the location of the input value from the selected table.\",\n    \"calc_values_from_table\": \"Reports calculated value of the selected attributes in the selected table. (sum, maximum, minimum, average, standard deviation)\",\n    \"open_table_chart\": \"Open the chart of the selected table.\",\n    \"close_table_chart\": \"Close the table chart.\",\n    \"get_coefficient\": \"Correlation coefficient between two attributes in the selected table. The closer the correlation coefficient is to 1(-1), the stronger the positive (negative) linear correlation.\"\n};\nLang.Category = {\n    \"entrybot_friends\": \"エントリーボットの友達\",\n    \"people\": \"人\",\n    \"animal\": \"動物\",\n    \"animal_flying\": \"空\",\n    \"animal_land\": \"地\",\n    \"animal_water\": \"水\",\n    \"animal_others\": \"その他\",\n    \"plant\": \"植物\",\n    \"plant_flower\": \"花\",\n    \"plant_grass\": \"草\",\n    \"plant_tree\": \"木\",\n    \"plant_others\": \"その他\",\n    \"vehicles\": \"乗り物\",\n    \"vehicles_flying\": \"空\",\n    \"vehicles_land\": \"地\",\n    \"vehicles_water\": \"水\",\n    \"vehicles_others\": \"その他\",\n    \"architect\": \"建物\",\n    \"architect_building\": \"建築物\",\n    \"architect_monument\": \"記念物\",\n    \"architect_others\": \"その他\",\n    \"food\": \"食べ物\",\n    \"food_vegetables\": \"果物/野菜\",\n    \"food_meat\": \"肉\",\n    \"food_drink\": \"飲み物\",\n    \"food_others\": \"その他\",\n    \"environment\": \"環境\",\n    \"environment_nature\": \"自然\",\n    \"environment_space\": \"宇宙\",\n    \"environment_others\": \"その他\",\n    \"stuff\": \"物\",\n    \"stuff_living\": \"生活\",\n    \"stuff_hobby\": \"趣味\",\n    \"stuff_others\": \"その他\",\n    \"fantasy\": \"ファンタジー\",\n    \"interface\": \"インターフェイス\",\n    \"interface_website\": \"ウェブサイト\",\n    \"interface_game\": \"ゲーム\",\n    \"interface_others\": \"その他\",\n    \"background\": \"背景\",\n    \"background_outdoor\": \"室外\",\n    \"background_indoor\": \"室内\",\n    \"background_nature\": \"自然\",\n    \"background_others\": \"その他\"\n};\nLang.Device = {\n    \"arduino\": \"arduino\",\n    \"hamster\": \"hamster\",\n    \"roboid\": \"ロボイド\",\n    \"turtle\": \"turtle\",\n    \"albert\": \"albert\",\n    \"robotis_carCont\": \"\",\n    \"robotis_openCM70\": \"\",\n    \"sensorBoard\": \"Entry Sensor Board\",\n    \"trueRobot\": \"TrueTrueRobot\",\n    \"CODEino\": \"CODEino\",\n    \"bitbrick\": \"bitbrick\",\n    \"creamo\": \"creamo\",\n    \"playcode\": \"playcode\",\n    \"funboard\": \"funboard\",\n    \"bitBlock\": \"ビットブロック\",\n    \"xbot_epor_edge\": \"XBOT\",\n    \"dplay\": \"DPLAY\",\n    \"iboard\": \"iboard\",\n    \"nemoino\": \"NEMOino\",\n    \"ev3\": \"EV3\",\n    \"robotori\": \"robotori\",\n    \"smartBoard\": \"smartBoard\",\n    \"chocopi\": \"ChocoPi\",\n    \"rokoboard\": \"rokoboard\",\n    \"altino\": \"알티노\",\n    \"mechatro\": \"mechatro\"\n};\nLang.General = {\n    \"turn_on\": \"ON\",\n    \"turn_off\": \"OFF\",\n    \"left\": \"左側\",\n    \"right\": \"右側\",\n    \"param_string\": \"文字値\",\n    \"both\": \"両側\",\n    \"transparent\": \"透明\",\n    \"black\": \"黒\",\n    \"brown\": \"茶色\",\n    \"red\": \"赤\",\n    \"yellow\": \"黄色\",\n    \"green\": \"緑\",\n    \"skyblue\": \"水色\",\n    \"blue\": \"青\",\n    \"purple\": \"紫\",\n    \"white\": \"白\",\n    \"note_c\": \"ド\",\n    \"note_d\": \"レ\",\n    \"note_e\": \"ミ\",\n    \"note_f\": \"ファ\",\n    \"note_g\": \"ソ\",\n    \"note_a\": \"ラ\",\n    \"note_b\": \"シ\",\n    \"questions\": \"問題\",\n    \"clock\": \"時計\",\n    \"counter_clock\": \"反時計\",\n    \"font_size\": \"文字サイズ\",\n    \"second\": \"秒\",\n    \"alert_title\": \"通知\",\n    \"confirm_title\": \"確認\",\n    \"update_title\": \"アップデート通知\",\n    \"recent_download\": \"今すぐアップデート\",\n    \"recent_download2\": \"最新バージョンをダウンロード\",\n    \"latest_version\": \"最新バージョンです。\",\n    \"dont_show_again\": \"今後、この通知を表示しない\"\n};\nLang.Fonts = {\n    \"jeju_hallasan\": \"漢拏山体\",\n    \"gothic_coding\": \"コーディングゴシック体\",\n    \"batang\": \"パタン体\",\n    \"gothic\": \"ナヌムゴシック体\",\n    \"myeongjo\": \"ナヌム明朝\",\n    \"pen_script\": \"ナヌム手書き\",\n    \"square_round\": \"ナヌム角丸体\",\n    \"jalnan\": \"ジャルナン体\",\n    \"designhouse\": \"デザインハウス体\",\n    \"malssami815\": \"マルサミ８１５体\",\n    \"dunggeunmo\": \"丸文字体\",\n    \"hs_bombaram\": \"HSボムバラム体\",\n    \"yisunshin\": \"イスンシン体\",\n    \"goyang\": \"ゴヤン体\",\n    \"flower_road\": \"サンサンフラワーロード体\",\n    \"uhbeemysen\": \"アビーマイセン体\",\n    \"sd_comic_stencil\": \"Sandoll コミックステンシル\",\n    \"sd_childfundkorea\": \"Sandoll コドモノタメニ\",\n    \"sd_cinema_theater\": \"Sandoll シネマゲキジョウ\",\n    \"sd_mapssi\": \"Sandoll メッシ\",\n    \"sd_shabang\": \"Sandoll ホシガキラキラ\",\n    \"sd_woodcarving\": \"Sandoll キボリ\",\n    \"sd_yongbi\": \"Sandoll ヨンビ\"\n};\nLang.Hw = {\n    \"note\": \"音符\",\n    \"leftWheel\": \"左車輪\",\n    \"rightWheel\": \"右車輪\",\n    \"leftEye\": \"左目\",\n    \"rightEye\": \"右目\",\n    \"led\": \"光\",\n    \"led_en\": \"LED\",\n    \"body\": \"本体\",\n    \"front\": \"前\",\n    \"port_en\": \" \",\n    \"port_ko\": \"番ポート\",\n    \"sensor\": \"センサー\",\n    \"light\": \"光\",\n    \"temp\": \"温度\",\n    \"switch_\": \"スイッチ\",\n    \"right_ko\": \"右側\",\n    \"right_en\": \" \",\n    \"left_ko\": \"左側\",\n    \"left_en\": \" \",\n    \"up_ko\": \"上\",\n    \"up_en\": \" \",\n    \"down_ko\": \"下\",\n    \"down_en\": \" \",\n    \"output\": \"出力\",\n    \"left\": \"左側\",\n    \"right\": \"右側\",\n    \"sub\": \"サーボ\",\n    \"motor\": \"モーター\",\n    \"\": \"\",\n    \"buzzer\": \"ブーザー\",\n    \"IR\": \"赤外線\",\n    \"acceleration\": \"加速\",\n    \"analog\": \"アナログ\",\n    \"angular_acceleration\": \"角加速\",\n    \"button\": \"ボタン\",\n    \"humidity\": \"湿度\",\n    \"joystick\": \"joystick\",\n    \"port\": \"ポート\",\n    \"potentiometer\": \"ポテンショメータ\",\n    \"servo\": \"サーボ\"\n};\nLang.template = {\n    \"albert_hand_found\": \"hand found?\",\n    \"albert_is_oid_value\": \"%1 oid %2?\",\n    \"albert_value\": \"%1\",\n    \"albert_move_forward_for_secs\": \"move forward for %1 secs %2\",\n    \"albert_move_backward_for_secs\": \"move backward for %1 secs %2\",\n    \"albert_turn_for_secs\": \"turn %1 for %2 secs %3\",\n    \"albert_change_both_wheels_by\": \"change wheels by left: %1 right: %2 %3\",\n    \"albert_set_both_wheels_to\": \"set wheels to left: %1 right: %2 %3\",\n    \"albert_change_wheel_by\": \"change %1 wheel by %2 %3\",\n    \"albert_set_wheel_to\": \"set %1 wheel to %2 %3\",\n    \"albert_stop\": \"stop %1\",\n    \"albert_set_pad_size_to\": \"set board size to width: %1 height: %2 %3\",\n    \"albert_move_to_x_y_on_board\": \"move to x: %1 y: %2 on board %3\",\n    \"albert_set_orientation_on_board\": \"set orientation to %1 degrees on board %2\",\n    \"albert_set_eye_to\": \"set %1 eye to %2 %3\",\n    \"albert_clear_eye\": \"clear %1 eye %2\",\n    \"albert_body_led\": \"turn %1 body led %2\",\n    \"albert_front_led\": \"turn %1 front led %2\",\n    \"albert_beep\": \"beep %1\",\n    \"albert_change_buzzer_by\": \"change buzzer by %1 %2\",\n    \"albert_set_buzzer_to\": \"set buzzer to %1 %2\",\n    \"albert_clear_buzzer\": \"clear buzzer %1\",\n    \"albert_play_note_for\": \"play note %1 %2 for %3 beats %4\",\n    \"albert_rest_for\": \"rest for %1 beats %2\",\n    \"albert_change_tempo_by\": \"change tempo by %1 %2\",\n    \"albert_set_tempo_to\": \"set tempo to %1 bpm %2\",\n    \"albert_move_forward\": \"move forward %1\",\n    \"albert_move_backward\": \"move backward %1\",\n    \"albert_turn_around\": \"turn %1 %2\",\n    \"albert_set_led_to\": \"set %1 led %2 %3\",\n    \"albert_clear_led\": \"clear %1 led %2\",\n    \"albert_change_wheels_by\": \"%1 %2 %3\",\n    \"albert_set_wheels_to\": \"%1 %2 %3\",\n    \"arduino_text\": \"%1\",\n    \"arduino_get_sensor_number\": \"%1  \",\n    \"arduino_get_port_number\": \"%1  \",\n    \"arduino_get_digital_toggle\": \"%1  \",\n    \"arduino_get_pwm_port_number\": \"%1  \",\n    \"arduino_get_number_sensor_value\": \"Analog %1 Sensor value  \",\n    \"arduino_ext_get_analog_value\": \"Analog %1 Sensor value\",\n    \"arduino_ext_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"arduino_ext_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"arduino_ext_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"arduino_ext_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"arduino_ext_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"arduino_ext_set_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"arduino_ext_get_digital\": \"Digital %1 Sensor value\",\n    \"blacksmith_get_analog_value\": \"Read analog %1 pin sensor value\",\n    \"blacksmith_get_analog_mapping\": \"Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5\",\n    \"blacksmith_get_digital_bluetooth\": \"Bluetooth RX 2 value\",\n    \"blacksmith_get_digital_ultrasonic\": \"Read ultrasonic Trig %1 Echo %2 sensor value\",\n    \"blacksmith_get_digital_toggle\": \"Digital %1 pin sensor value\",\n    \"blacksmith_set_digital_toggle\": \"Digital %1 pin %2 %3\",\n    \"blacksmith_set_digital_pwm\": \"Digital pwm %1 Pin %2 %3\",\n    \"blacksmith_set_digital_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"blacksmith_set_digital_buzzer\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"blacksmith_set_digital_lcd\": \"LCD %1 line %2 appear %3\",\n    \"blacksmith_set_digital_bluetooth\": \"Bluetooth TX 3 Pin %1 data send %2\",\n    \"dplay_get_number_sensor_value\": \"Analog %1 Sensor value  \",\n    \"nemoino_get_number_sensor_value\": \"Analog %1 Sensor value  \",\n    \"sensorBoard_get_number_sensor_value\": \"Analog %1 Sensor value  \",\n    \"truetrue_get_accsensor\": \"加速度センサー%1の値\",\n    \"truetrue_get_bottomcolorsensor\": \"床面カラーセンサー%1の値\",\n    \"truetrue_get_frontcolorsensor\": \"全面カラーセンサー%1の値\",\n    \"truetrue_get_linesensor\": \"ラインセンサー%1の値\",\n    \"truetrue_get_proxisensor\": \"近接センサー%1の値\",\n    \"truetrue_set_colorled\": \"カラーLED Red %1  Green %2 Blue %3 に設定 %4\",\n    \"truetrue_set_dualmotor\": \"DCモーター左 %1  右 %2速度で%3秒駆動%4\",\n    \"truetrue_set_led_colorsensor\": \"%1照明用LED %2 %3\",\n    \"truetrue_set_led_linesensor\": \"ラインセンサー照明用LED %1 %2\",\n    \"truetrue_set_led_proxi\": \"%1照明用LED %2 %3\",\n    \"truetrue_set_linetracer\": \"ライントレーシングモード%1 %2\",\n    \"truetrue_set_singlemotor\": \"DCモーター %1 速度 %2 に設定 %3\",\n    \"CODEino_get_number_sensor_value\": \"Analog %1 Sensor value  \",\n    \"ardublock_get_number_sensor_value\": \"Analog %1 Sensor value  \",\n    \"arduino_get_digital_value\": \"Digital %1 Sensor value  \",\n    \"dplay_get_digital_value\": \"Digital %1 Sensor value  \",\n    \"nemoino_get_digital_value\": \"Digital %1 Sensor value  \",\n    \"sensorBoard_get_digital_value\": \"Digital %1 Sensor value  \",\n    \"CODEino_get_digital_value\": \"Digital %1 Pin value  \",\n    \"CODEino_set_digital_value\": \"Digital %1 Pin %2 %3\",\n    \"CODEino_set_pwm_value\": \"Digital %1 Pin %2 %3\",\n    \"ardublock_get_digital_value\": \"Digital %1 Sensor value  \",\n    \"arduino_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"dplay_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"nemoino_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"sensorBoard_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"CODEino_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"arduino_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"dplay_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"nemoino_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"sensorBoard_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"CODEino_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"ardublock_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"arduino_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"dplay_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"nemoino_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"sensorBoard_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"CODEino_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"CODEino_set_rgb_value\": \"Set color LED %1 by %2 %3\",\n    \"CODEino_set_rgb_add_value\": \"Add color LED %1 by %2 %3\",\n    \"CODEino_set_rgb_off\": \"Turn off LED %1\",\n    \"CODEino_set__led_by_rgb\": \"Turn on color LED, Red %1 Green %2 Blue %3 %4\",\n    \"CODEino_rgb_set_color\": \"Select %1 for color LED %2\",\n    \"CODEino_led_by_value\": \"Turn on LED %1\",\n    \"ardublock_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"joystick_get_number_sensor_value\": \"Analog %1 Sensor value  \",\n    \"joystick_get_digital_value\": \"Digital %1 Sensor value  \",\n    \"joystick_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"joystick_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"joystick_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"sensorBoard_get_named_sensor_value\": \"%1  Sensor value\",\n    \"sensorBoard_is_button_pressed\": \"Pressed %1 button?\",\n    \"sensorBoard_led\": \"%1  LED %2   %3\",\n    \"arduino_download_connector\": \"%1\",\n    \"download_guide\": \"%1\",\n    \"arduino_download_source\": \"%1\",\n    \"arduino_connected\": \"%1\",\n    \"arduino_connect\": \"%1\",\n    \"arduino_reconnect\": \"%1\",\n    \"CODEino_get_sensor_number\": \"%1  \",\n    \"CODEino_get_named_sensor_value\": \"  %1  Sensor value \",\n    \"CODEino_get_sound_status\": \"Sound is  %1  \",\n    \"CODEino_get_light_status\": \"Light is  %1  \",\n    \"CODEino_is_button_pressed\": \" Operation  %1  \",\n    \"CODEino_get_accelerometer_direction\": \" 3-AXIS Accelerometer  %1  \",\n    \"CODEino_get_accelerometer_value\": \" 3-AXIS Accelerometer  %1 -axis value \",\n    \"CODEino_get_analog_value\": \"Analog %1 Sensor value\",\n    \"iboard_button\": \"Pressed %1 button?\",\n    \"iboard_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"iboard_get_analog_value\": \"Analog %1 Sensor value  \",\n    \"iboard_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"iboard_get_digital\": \"Digital %1 Sensor value  \",\n    \"iboard_led\": \"Digital %1 Pin %2 %3\",\n    \"iboard_motor\": \"Digital %1 Pin %2 %3\",\n    \"iboard_pwm_led\": \"Digital %1 Pin %2 %3\",\n    \"iboard_rgb_led\": \" %1 LED %2 %3\",\n    \"iboard_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"iboard_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"bitbrick_when_button_pressed\": \"%1 when button %2\",\n    \"bitbrick_when_sensor_get_value\": \"%1 when %2 value %3 %4\",\n    \"bitbrick_is_touch_pressed\": \"button %1 %2?\",\n    \"bitbrick_is_sensor_value_compare\": \"%1 %2 %3?\",\n    \"bitbrick_sensor_value\": \"%1 value\",\n    \"bitbrick_convert_scale\": \"map %1 value from %2 ~ %3 to %4 ~ %5\",\n    \"bitbrick_turn_on_color_led_by_rgb\": \"set LED color to Red %1 Green %2 Blue %3 %4\",\n    \"bitbrick_turn_on_color_led_by_picker\": \"set LED color to %1 %2\",\n    \"bitbrick_turn_on_color_led_by_value\": \"set LED color %1 %2\",\n    \"bitbrick_turn_off_color_led\": \"turn off LED %1\",\n    \"bitbrick_buzzer\": \"buzz note %1 %2\",\n    \"bitbrick_servomotor_angle\": \"servo motor %1 degree %2 %3\",\n    \"bitbrick_dc_direction_speed\": \"dc motor %1 direction %2 speed %3 %4\",\n    \"bitbrick_dc_speed\": \"dc motor %1 velocity %2 %3\",\n    \"bitbrick_turn_off_all_motors\": \"stop all motors %1\",\n    \"start_drawing\": \"描きはじめる %1\",\n    \"stop_drawing\": \"描きおえる %1\",\n    \"set_color\": \"筆の色を%1にする %2\",\n    \"set_random_color\": \"筆の色をランダムにする %1\",\n    \"change_thickness\": \"筆の太さを %1 だけ変える %2\",\n    \"set_thickness\": \"筆の太さを%1にする %2\",\n    \"change_opacity\": \"筆の不透明度を%1 %大きくする %2\",\n    \"set_opacity\": \"筆の不透明度を%1 %にする %2\",\n    \"brush_erase_all\": \"すべての筆のあとを消す %1\",\n    \"brush_stamp\": \"スタンプを押す %1\",\n    \"change_brush_transparency\": \"筆の透明度を%1 %だけ変える %2\",\n    \"set_brush_tranparency\": \"筆の透明度を%1 %にする %2\",\n    \"number\": \"%1\",\n    \"angle\": \"%1\",\n    \"color\": \"%1\",\n    \"get_x_coordinate\": \"%1\",\n    \"get_y_coordinate\": \"%1\",\n    \"get_angle\": \"%1\",\n    \"get_rotation_direction\": \"%1\",\n    \"distance_something\": \"%1 %2 %3\",\n    \"coordinate_mouse\": \"%1 %2 %3\",\n    \"coordinate_object\": \"%1 %2 %3 %4\",\n    \"calc_basic\": \"%1 %2 %3\",\n    \"calc_plus\": \"%1 %2 %3\",\n    \"calc_minus\": \"%1 %2 %3\",\n    \"calc_times\": \"%1 %2 %3\",\n    \"calc_divide\": \"%1 %2 %3\",\n    \"calc_mod\": \"%1 %2 %3 %4\",\n    \"calc_share\": \"%1 %2 %3 %4\",\n    \"calc_operation\": \"%1 %2 %3 %4\",\n    \"calc_rand\": \"%1 %2 %3 %4 %5\",\n    \"get_date\": \"%1 %2 %3\",\n    \"get_sound_duration\": \"%1 %2 %3\",\n    \"get_user_name\": \"ユーザーID\",\n    \"get_nickname\": \"ニックネーム\",\n    \"reset_project_timer\": \"%1\",\n    \"set_visible_project_timer\": \"%1 %2 %3 %4\",\n    \"timer_variable\": \"%1 %2\",\n    \"get_project_timer_value\": \"%1 %2\",\n    \"char_at\": \"%1 %2 %3 %4 %5\",\n    \"length_of_string\": \"%1 %2 %3\",\n    \"substring\": \"%1 %2 %3 %4 %5 %6 %7\",\n    \"replace_string\": \"%1 %2 %3 %4 %5 %6 %7\",\n    \"change_string_case\": \"%1 %2 %3 %4 %5\",\n    \"index_of_string\": \"%1 %2 %3 %4 %5\",\n    \"combine_something\": \"%1 %2 %3 %4 %5\",\n    \"get_sound_volume\": \"%1 %2\",\n    \"quotient_and_mod\": \"%1 %2 %3 %4 %5 %6\",\n    \"choose_project_timer_action\": \"%1 %2 %3 %4\",\n    \"wait_second\": \"%1 秒待つ %2\",\n    \"repeat_basic\": \"%1回繰り返す %2\",\n    \"hidden_loop\": \"%1回繰り返す %2\",\n    \"repeat_inf\": \"ずっと繰り返す %1\",\n    \"stop_repeat\": \"繰り返しをやめる %1\",\n    \"wait_until_true\": \"%1 になるまで待つ %2\",\n    \"_if\": \"もし%1なら %2\",\n    \"if_else\": \"もし%1なら %2 %3でなければ\",\n    \"create_clone\": \"%1のコピーを作る %2\",\n    \"delete_clone\": \"このコピーを削除する %1\",\n    \"when_clone_start\": \"%1 初めてコピーされた時\",\n    \"stop_run\": \"プログラムを終了する %1\",\n    \"repeat_while_true\": \"%1 %2  繰り返す %3\",\n    \"stop_object\": \"%1 コードの実行を止める %2\",\n    \"restart_project\": \"最初から再スタートする %1\",\n    \"remove_all_clones\": \"すべてのコピーを削除する %1\",\n    \"functionAddButton\": \"%1\",\n    \"function_field_label\": \"%1%2\",\n    \"function_field_string\": \"%1%2\",\n    \"function_field_boolean\": \"%1%2\",\n    \"function_param_string\": \"文字/数字の値\",\n    \"function_param_boolean\": \"判断値\",\n    \"function_create\": \"関数を定義する %1 %2\",\n    \"function_general\": \"関数%1\",\n    \"expansionBlockAddButton\": \"%1\",\n    \"aiUtilizeBlockAddButton\": \"%1\",\n    \"aiUtilizeModelTrainButton\": \"%1\",\n    \"weather_title\": \"%1\",\n    \"check_weather\": \"%1 %2の天気が%3か？\",\n    \"check_finedust\": \"現在%1のPM10のレベルが%2か？\",\n    \"get_weather_data\": \"%1 %2の %3\",\n    \"get_current_weather_data\": \"現在%1の %2\",\n    \"get_today_temperature\": \"今日%1の %2時の気温\",\n    \"check_city_weather\": \"%1 %2 %3の天気が%4か？\",\n    \"check_city_finedust\": \"現在%1 %2のPM10のレベルが%3か？\",\n    \"get_city_weather_data\": \"%1 %2 %3の %4\",\n    \"get_current_city_weather_data\": \"現在%1 %2の %3\",\n    \"get_today_city_temperature\": \"今日%1 %2の %3時の気温\",\n    \"translate_title\": \"%1\",\n    \"get_translated_string\": \"%1 %2を %3に翻訳する\",\n    \"check_language\": \"%1の言語\",\n    \"festival_title\": \"%1\",\n    \"count_festival\": \"%1 %2 のイベント数\",\n    \"get_festival_info\": \"%1 %2 のイベント中 %3 番目の項目の %4\",\n    \"behaviorConductDisaster_title\": \"%1\",\n    \"count_disaster_behavior\": \"%1 %2 に取るべき行動要領数\",\n    \"get_disaster_behavior\": \"自然災害の %1 %2 に取るべき行動要領で %3番目の項目\",\n    \"behaviorConductLifeSafety_title\": \"%1\",\n    \"count_lifeSafety_behavior\": \"%1 の中の %2方法の数\",\n    \"get_lifeSafety_behavior\": \"%1の中の %2方法で %3番目の項目\",\n    \"tts_title\": \"%1\",\n    \"audio_title\": \"%1\",\n    \"video_title\": \"%1\",\n    \"read_text\": \"%1 を読み上げる %2\",\n    \"set_tts_property\": \"%1 音声で速さを%2、ピッチを%3に設定する。%4\",\n    \"read_text_wait_with_block\": \"%1 を読み上げて待つ %2\",\n    \"load_expansion_block\": \"追加する\",\n    \"load_ai_utilize_block\": \"AIブロックの読み込み\",\n    \"load_ai_utilize_train_block\": \"鉄道模型\",\n    \"expansion_block_descriptions\": \"拡張ブロックが正常に動作するには、インターネット接続が必要です。\",\n    \"aiUtilize_block_descriptions\": \"A.I.活用ブロックは、インターネット接続が必要です。\",\n    \"weather_title_text\": \"天気\",\n    \"translate_title_text\": \"翻訳\",\n    \"festival_title_text\": \"イベント\",\n    \"audio_title_text\": \"オーディオ検出\",\n    \"check_microphone\": \"マイクが接続されているか?\",\n    \"get_microphone_volume\": \"マイク音量\",\n    \"speech_to_text_convert\": \"音声の大井 %1\",\n    \"speech_to_text_get_value\": \"音声を文字に変えた値\",\n    \"video_title_text\": \"ビデオ検出\",\n    \"video_draw_webcam\": \"ビデオ画面 %1 %2\",\n    \"video_check_webcam\": \"ビデオが接続されているか？\",\n    \"video_set_camera_opacity_option\": \"ビデオの透明度効果を %1 に決める %2\",\n    \"video_flip_camera\": \"ビデオ画面 %1 %2\",\n    \"video_toggle_model\": \"%1 認識を %2 %3\",\n    \"video_toggle_ind\": \"認識された %1 %2 %3\",\n    \"video_number_detect\": \"認識された %1 の数\",\n    \"video_detected_face_info\": \"%1 番目の顔の %2\",\n    \"video_motion_value\": \"%1 で感知した %2 値\",\n    \"video_face_part_coord\": \"%1 番目の顔 %2 の %3 座標\",\n    \"video_body_part_coord\": \"%1 番目の人の %2 の %3 座標\",\n    \"behaviorConductDisaster_title_text\": \"自然災害\",\n    \"behaviorConductLifeSafety_title_text\": \"生活安全\",\n    \"tts_title_text\": \"音声読み上げ\",\n    \"hamster_hand_found\": \"hand found?\",\n    \"hamster_value\": \"%1\",\n    \"hamster_move_forward_once\": \"move forward once on board %1\",\n    \"hamster_turn_once\": \"turn %1 once on board %2\",\n    \"hamster_move_forward_for_secs\": \"move forward for %1 secs %2\",\n    \"hamster_move_backward_for_secs\": \"move backward for %1 secs %2\",\n    \"hamster_turn_for_secs\": \"turn %1 for %2 secs %3\",\n    \"hamster_change_both_wheels_by\": \"change wheels by left: %1 right: %2 %3\",\n    \"hamster_set_both_wheels_to\": \"set wheels to left: %1 right: %2 %3\",\n    \"hamster_change_wheel_by\": \"change %1 wheel by %2 %3\",\n    \"hamster_set_wheel_to\": \"set %1 wheel to %2 %3\",\n    \"hamster_follow_line_using\": \"follow %1 line using %2 floor sensor %3\",\n    \"hamster_follow_line_until\": \"follow %1 line until %2 intersection %3\",\n    \"hamster_set_following_speed_to\": \"set following speed to %1 %2\",\n    \"hamster_stop\": \"stop %1\",\n    \"hamster_set_led_to\": \"set %1 led to %2 %3\",\n    \"hamster_clear_led\": \"clear %1 led %2\",\n    \"hamster_beep\": \"beep %1\",\n    \"hamster_change_buzzer_by\": \"change buzzer by %1 %2\",\n    \"hamster_set_buzzer_to\": \"set buzzer to %1 %2\",\n    \"hamster_clear_buzzer\": \"clear buzzer %1\",\n    \"hamster_play_note_for\": \"play note %1 %2 for %3 beats %4\",\n    \"hamster_rest_for\": \"rest for %1 beats %2\",\n    \"hamster_change_tempo_by\": \"change tempo by %1 %2\",\n    \"hamster_set_tempo_to\": \"set tempo to %1 bpm %2\",\n    \"hamster_set_port_to\": \"set port %1 to %2 %3\",\n    \"hamster_change_output_by\": \"change output %1 by %2 %3\",\n    \"hamster_set_output_to\": \"set output %1 to %2 %3\",\n    \"roboid_hamster_beep\": \"Hamster %1: beep %2\",\n    \"roboid_hamster_change_both_wheels_by\": \"Hamster %1: change wheels by left: %2 right: %3 %4\",\n    \"roboid_hamster_change_buzzer_by\": \"Hamster %1: change buzzer by %2 %3\",\n    \"roboid_hamster_change_output_by\": \"Hamster %1: change output %2 by %3 %4\",\n    \"roboid_hamster_change_tempo_by\": \"Hamster %1: change tempo by %2 %3\",\n    \"roboid_hamster_change_wheel_by\": \"Hamster %1: change %2 wheel by %3 %4\",\n    \"roboid_hamster_clear_buzzer\": \"Hamster %1: clear buzzer %2\",\n    \"roboid_hamster_clear_led\": \"Hamster %1: clear %2 led %3\",\n    \"roboid_hamster_follow_line_until\": \"Hamster %1: follow %2 line until %3 intersection %4\",\n    \"roboid_hamster_follow_line_using\": \"Hamster %1: follow %2 line using %3 floor sensor %4\",\n    \"roboid_hamster_hand_found\": \"Hamster %1: hand found?\",\n    \"roboid_hamster_move_backward_for_secs\": \"Hamster %1: move backward for %2 secs %3\",\n    \"roboid_hamster_move_forward_for_secs\": \"Hamster %1: move forward for %2 secs %3\",\n    \"roboid_hamster_move_forward_once\": \"Hamster %1: move forward once on board %2\",\n    \"roboid_hamster_play_note_for\": \"Hamster %1: play note %2 %3 for %4 beats %5\",\n    \"roboid_hamster_rest_for\": \"Hamster %1: rest for %2 beats %3\",\n    \"roboid_hamster_set_both_wheels_to\": \"Hamster %1: set wheels to left: %2 right: %3 %4\",\n    \"roboid_hamster_set_buzzer_to\": \"Hamster %1: set buzzer to %2 %3\",\n    \"roboid_hamster_set_following_speed_to\": \"Hamster %1: set following speed to %2 %3\",\n    \"roboid_hamster_set_led_to\": \"Hamster %1: set %2 led to %3 %4\",\n    \"roboid_hamster_set_output_to\": \"Hamster %1: set output %2 to %3 %4\",\n    \"roboid_hamster_set_port_to\": \"Hamster %1: set port %2 to %3 %4\",\n    \"roboid_hamster_set_tempo_to\": \"Hamster %1: set tempo to %2 bpm %3\",\n    \"roboid_hamster_set_wheel_to\": \"Hamster %1: set %2 wheel to %3 %4\",\n    \"roboid_hamster_stop\": \"Hamster %1: stop %2\",\n    \"roboid_hamster_turn_for_secs\": \"Hamster %1: turn %2 for %3 secs %4\",\n    \"roboid_hamster_turn_once\": \"Hamster %1: turn %2 once on board %3\",\n    \"roboid_hamster_value\": \"Hamster %1: %2\",\n    \"roboid_turtle_button_state\": \"Turtle %1: button %2 ?\",\n    \"roboid_turtle_change_buzzer_by\": \"Turtle %1: change buzzer by %2 %3\",\n    \"roboid_turtle_change_head_led_by_rgb\": \"Turtle %1: change head led by r: %2 g: %3 b: %4 %5\",\n    \"roboid_turtle_change_tempo_by\": \"Turtle %1: change tempo by %2 %3\",\n    \"roboid_turtle_change_wheel_by\": \"Turtle %1: change %2 wheel by %3 %4\",\n    \"roboid_turtle_change_wheels_by_left_right\": \"Turtle %1: change wheels by left: %2 right: %3 %4\",\n    \"roboid_turtle_clear_head_led\": \"Turtle %1: clear head led %2\",\n    \"roboid_turtle_clear_sound\": \"Turtle %1: clear sound %2\",\n    \"roboid_turtle_cross_intersection\": \"Turtle %1: cross black intersection %2\",\n    \"roboid_turtle_follow_line\": \"Turtle %1: follow %2 line %3\",\n    \"roboid_turtle_follow_line_until\": \"Turtle %1: follow black line until %2 %3\",\n    \"roboid_turtle_follow_line_until_black\": \"Turtle %1: follow %2 line until black %3\",\n    \"roboid_turtle_is_color_pattern\": \"Turtle %1: color pattern %2 %3 ?\",\n    \"roboid_turtle_move_backward_unit\": \"Turtle %1: move backward %2 %3 %4\",\n    \"roboid_turtle_move_forward_unit\": \"Turtle %1: move forward %2 %3 %4\",\n    \"roboid_turtle_pivot_around_wheel_unit_in_direction\": \"Turtle %1: pivot around %2 wheel %3 %4 in %5 direction %6\",\n    \"roboid_turtle_play_note\": \"Turtle %1: play note %2 %3 %4\",\n    \"roboid_turtle_play_note_for_beats\": \"Turtle %1: play note %2 %3 for %4 beats %5\",\n    \"roboid_turtle_play_sound_times\": \"Turtle %1: play sound %2 %3 times %4\",\n    \"roboid_turtle_play_sound_times_until_done\": \"Turtle %1: play sound %2 %3 times until done %4\",\n    \"roboid_turtle_rest_for_beats\": \"Turtle %1: rest for %2 beats %3\",\n    \"roboid_turtle_set_buzzer_to\": \"Turtle %1: set buzzer to %2 %3\",\n    \"roboid_turtle_set_following_speed_to\": \"Turtle %1: set following speed to %2 %3\",\n    \"roboid_turtle_set_head_led_to\": \"Turtle %1: set head led to %2 %3\",\n    \"roboid_turtle_set_head_led_to_rgb\": \"Turtle %1: set head led to r: %2 g: %3 b: %4 %5\",\n    \"roboid_turtle_set_tempo_to\": \"Turtle %1: set tempo to %2 bpm %3\",\n    \"roboid_turtle_set_wheel_to\": \"Turtle %1: set %2 wheel to %3 %4\",\n    \"roboid_turtle_set_wheels_to_left_right\": \"Turtle %1: set wheels to left: %2 right: %3 %4\",\n    \"roboid_turtle_stop\": \"Turtle %1: stop %2\",\n    \"roboid_turtle_touching_color\": \"Turtle %1: touching %2 ?\",\n    \"roboid_turtle_turn_at_intersection\": \"Turtle %1: turn %2 at black intersection %3\",\n    \"roboid_turtle_turn_unit_in_place\": \"Turtle %1: turn %2 %3 %4 in place %5\",\n    \"roboid_turtle_turn_unit_with_radius_in_direction\": \"Turtle %1: turn %2 %3 %4 with radius %5 cm in %6 direction %7\",\n    \"roboid_turtle_value\": \"Turtle %1: %2\",\n    \"turtle_button_state\": \"button %1 ?\",\n    \"turtle_change_buzzer_by\": \"change buzzer by %1 %2\",\n    \"turtle_change_head_led_by_rgb\": \"change head led by r: %1 g: %2 b: %3 %4\",\n    \"turtle_change_tempo_by\": \"change tempo by %1 %2\",\n    \"turtle_change_wheel_by\": \"change %1 wheel by %2 %3\",\n    \"turtle_change_wheels_by_left_right\": \"change wheels by left: %1 right: %2 %3\",\n    \"turtle_clear_head_led\": \"clear head led %1\",\n    \"turtle_clear_sound\": \"clear sound %1\",\n    \"turtle_cross_intersection\": \"cross black intersection %1\",\n    \"turtle_follow_line\": \"follow %1 line %2\",\n    \"turtle_follow_line_until\": \"follow black line until %1 %2\",\n    \"turtle_follow_line_until_black\": \"follow %1 line until black %2\",\n    \"turtle_is_color_pattern\": \"color pattern %1 %2 ?\",\n    \"turtle_move_backward_unit\": \"move backward %1 %2 %3\",\n    \"turtle_move_forward_unit\": \"move forward %1 %2 %3\",\n    \"turtle_pivot_around_wheel_unit_in_direction\": \"pivot around %1 wheel %2 %3 in %4 direction %5\",\n    \"turtle_play_note\": \"play note %1 %2 %3\",\n    \"turtle_play_note_for_beats\": \"play note %1 %2 for %3 beats %4\",\n    \"turtle_play_sound_times\": \"play sound %1 %2 times %3\",\n    \"turtle_play_sound_times_until_done\": \"play sound %1 %2 times until done %3\",\n    \"turtle_rest_for_beats\": \"rest for %1 beats %2\",\n    \"turtle_set_buzzer_to\": \"set buzzer to %1 %2\",\n    \"turtle_set_following_speed_to\": \"set following speed to %1 %2\",\n    \"turtle_set_head_led_to\": \"set head led to %1 %2\",\n    \"turtle_set_head_led_to_rgb\": \"set head led to r: %1 g: %2 b: %3 %4\",\n    \"turtle_set_tempo_to\": \"set tempo to %1 bpm %2\",\n    \"turtle_set_wheel_to\": \"set %1 wheel to %2 %3\",\n    \"turtle_set_wheels_to_left_right\": \"set wheels to left: %1 right: %2 %3\",\n    \"turtle_stop\": \"stop %1\",\n    \"turtle_touching_color\": \"touching %1 ?\",\n    \"turtle_turn_at_intersection\": \"turn %1 at black intersection %2\",\n    \"turtle_turn_unit_in_place\": \"turn %1 %2 %3 in place %4\",\n    \"turtle_turn_unit_with_radius_in_direction\": \"turn %1 %2 %3 with radius %4 cm in %5 direction %6\",\n    \"turtle_value\": \"%1\",\n    \"is_clicked\": \"%1\",\n    \"is_press_some_key\": \"%1 %2\",\n    \"reach_something\": \"%1 %2 %3\",\n    \"boolean_comparison\": \"%1 %2 %3\",\n    \"boolean_equal\": \"%1 %2 %3\",\n    \"boolean_bigger\": \"%1 %2 %3\",\n    \"boolean_smaller\": \"%1 %2 %3\",\n    \"boolean_and_or\": \"%1 %2 %3\",\n    \"boolean_and\": \"%1 %2 %3\",\n    \"boolean_or\": \"%1 %2 %3\",\n    \"boolean_not\": \"%1 %2 %3\",\n    \"is_boost_mode\": \"%1\",\n    \"true_or_false\": \"%1\",\n    \"True\": \"%1\",\n    \"False\": \"%1\",\n    \"boolean_basic_operator\": \"%1 %2 %3\",\n    \"show\": \"形を見せる %1\",\n    \"hide\": \"形を隠す %1\",\n    \"dialog_time\": \"%1を%2秒間 %3 %4\",\n    \"dialog\": \"%1を%2 %3\",\n    \"remove_dialog\": \"言った言葉を削除する %1\",\n    \"change_to_nth_shape\": \"%1 の形に変える %2\",\n    \"change_to_next_shape\": \"%1 の形に変える %2\",\n    \"set_effect_volume\": \"%1 効果を %2 だけ加える %3\",\n    \"set_effect\": \"%1 効果を%2 にする %3\",\n    \"erase_all_effects\": \"効果をすべて削除する %1\",\n    \"change_scale_percent\": \"サイズを%1だけ変更%2\",\n    \"set_scale_percent\": \"サイズを%1 にする %2\",\n    \"change_scale_size\": \"サイズを %1 だけ変える %2\",\n    \"set_scale_size\": \"サイズを%1 にする %2\",\n    \"flip_y\": \"形を左右反対にする %1\",\n    \"flip_x\": \"形を上下反対にする %1\",\n    \"set_object_order\": \"%1番目に上げる %2\",\n    \"get_pictures\": \"%1\",\n    \"change_to_some_shape\": \"%1 の形に変える %2\",\n    \"add_effect_amount\": \"%1 効果を%2だけ加える %3\",\n    \"change_effect_amount\": \"%1 効果を%2にする %3\",\n    \"set_effect_amount\": \"%1 効果を%2だけ加える %3\",\n    \"set_entity_effect\": \"%1 効果を%2にする %3\",\n    \"change_object_index\": \"%1 送る %2\",\n    \"move_direction\": \"移動方向に %1 だけ動く %2\",\n    \"move_x\": \"x座標を %1 だけ変える %2\",\n    \"move_y\": \"y座標を%1だけ変える%2\",\n    \"locate_xy_time\": \"%1秒間 x: %2 y: %3 の位置に移動する %4\",\n    \"rotate_by_angle\": \"オブジェクトを%1分回転する %2\",\n    \"rotate_by_angle_dropdown\": \"%1分回転する %2\",\n    \"see_angle\": \"移動方向を%1にする %2\",\n    \"see_direction\": \"%1側を見る %2\",\n    \"locate_xy\": \"x: %1 y: %2 の位置に移動する %3\",\n    \"locate_x\": \"x: %1 の位置に移動する %2\",\n    \"locate_y\": \"y: %1 の位置に移動する %2\",\n    \"locate\": \"%1 の位置に移動する %2\",\n    \"move_xy_time\": \"%1秒間 x: %2 y: %3 の分だけ動く %4\",\n    \"rotate_by_angle_time\": \"オブジェクトを%1 秒間%2だけ回転する %3\",\n    \"bounce_wall\": \"壁に着いたら、跳ね返る %1\",\n    \"flip_arrow_horizontal\": \"矢印方向を左右入れ替える %1\",\n    \"flip_arrow_vertical\": \"矢印方向を上下入れ替える %1\",\n    \"see_angle_object\": \"%1 の方向へ向く %2\",\n    \"see_angle_direction\": \"オブジェクトを%1にする %2\",\n    \"rotate_direction\": \"移動方向を%1 だけ回転させる %2\",\n    \"locate_object_time\": \"%1秒間%2 の位置に移動する %3\",\n    \"rotate_absolute\": \"方向を%1にする %2\",\n    \"rotate_relative\": \"向きを%1だけ回転させる %2\",\n    \"direction_absolute\": \"移動方向を%1にする %2\",\n    \"direction_relative\": \"移動方向を %1 だけ回転させる %2\",\n    \"move_to_angle\": \"%1 の方向に %2 だけ動く %3\",\n    \"rotate_by_time\": \"%1 秒間、向きを%2 だけ回転させる %3\",\n    \"direction_relative_duration\": \"%1秒間、移動方向を %2 だけ回転させる %3\",\n    \"neobot_sensor_value\": \"%1  값\",\n    \"neobot_turn_left\": \"Rotate left motor %1 %2 %3\",\n    \"neobot_stop_left\": \"Stop left motor %1\",\n    \"neobot_turn_right\": \"Rotate right motor %1 %2 %3\",\n    \"neobot_stop_right\": \"Stop right motor %1\",\n    \"neobot_run_motor\": \"Run %1 motor for %2 secs\",\n    \"neobot_servo_1\": \"Move the servo motor connected to SERVO1 to %2 with the speed of %1 %3\",\n    \"neobot_servo_2\": \"Move the servo motor connected to SERVO2 to %2 with the speed of %1 %3\",\n    \"neobot_play_note_for\": \"Play %1 melody to octave %2 as long as %3 %4\",\n    \"neobot_set_sensor_value\": \"%1 value of the port to %2 %3\",\n    \"robotis_openCM70_cm_custom_value\": \"Custom address ( %1 ) value %2\",\n    \"robotis_openCM70_sensor_value\": \"Controller value %1\",\n    \"robotis_openCM70_aux_sensor_value\": \"Value %1   %2\",\n    \"robotis_openCM70_cm_buzzer_index\": \"Play %1 controller scale value for %2 seconds %3 \",\n    \"robotis_openCM70_cm_buzzer_melody\": \"Play controller melody %1 times %2\",\n    \"robotis_openCM70_cm_sound_detected_clear\": \"Initialize the final number of sound detection  %1\",\n    \"robotis_openCM70_cm_led\": \"Controller %1 LED %2 %3\",\n    \"robotis_openCM70_cm_motion\": \"Play the motion %1 times\",\n    \"robotis_openCM70_cm_autodrive_motor\": \"Autonomous driving car %1 motor uses %2 %3\",\n    \"robotis_openCM70_cm_autodrive_ir\": \"Autonomous driving car %1 IR sensor uses %2 %3\",\n    \"robotis_openCM70_cm_autodrive_speed\": \"Perform autonomous driving at the speed of %1 %2\",\n    \"robotis_openCM70_aux_car_move\": \"Make the robot %2 at a speed of %1% %3\",\n    \"robotis_openCM70_aux_motor_speed\": \"Set the speed of decelerating motor of %1 to %2 , and the output value to %3%  %4\",\n    \"robotis_openCM70_aux_servo_mode\": \"Set the mode of %1 servo motor to %2  %3\",\n    \"robotis_openCM70_aux_servo_speed\": \"Set the speed of servo motor of %1 to %2 , and the output value to %3%  %4\",\n    \"robotis_openCM70_aux_servo_position\": \"Set the position of %1 servo motor to %2 degree %3\",\n    \"robotis_openCM70_aux_led_module\": \"Set the LED module of %1 as %2  %3\",\n    \"robotis_openCM70_aux_custom\": \"Set the user device of %1 as %2  %3\",\n    \"robotis_openCM70_cm_poweroff_timer\": \"Set auto-off timer as %1 %2\",\n    \"robotis_openCM70_cm_custom\": \"Set the custom address ( %1 ) as %2  %3\",\n    \"robotis_carCont_sensor_value\": \"Value   %1\",\n    \"robotis_carCont_cm_led\": \"%1 LED 4,  %2 LED %3\",\n    \"robotis_carCont_cm_sound_detected_clear\": \"Initialize the final number of sound detection  %1\",\n    \"robotis_carCont_aux_motor_speed\": \"Set the speed of decelerating motor of %1 to %2, and the output value to %3  %4\",\n    \"robotis_carCont_cm_calibration\": \"Set %1 value of infrared sensor calibration to %2  %3\",\n    \"roduino_get_analog_number\": \"%1\",\n    \"roduino_get_port_number\": \"%1\",\n    \"roduino_get_analog_value\": \"アナログ %1回センサー値  \",\n    \"roduino_get_digital_value\": \"デジタル %1回センサー値  \",\n    \"roduino_set_digital\": \"デジタル %1番ピン %2 %3\",\n    \"roduino_motor\": \"%1 %2 %3\",\n    \"roduino_set_color_pin\": \"カラーセンサー R : %1, G : %2, B : %3 %4\",\n    \"roduino_get_color\": \"カラーセンサー%1 感知\",\n    \"roduino_on_block\": \" On \",\n    \"roduino_off_block\": \" Off \",\n    \"schoolkit_get_in_port_number\": \"%1\",\n    \"schoolkit_get_out_port_number\": \"%1\",\n    \"schoolkit_get_servo_port_number\": \"%1\",\n    \"schoolkit_get_input_value\": \"デジタル %1番センサー値  \",\n    \"schoolkit_set_output\": \"デジタル %1番ピン %2 %3\",\n    \"schoolkit_motor\": \"%1速度%2で %3 %4\",\n    \"schoolkit_set_servo_value\": \"サーボモーター %1番ピン %2˚ %3\",\n    \"schoolkit_on_block\": \" On \",\n    \"schoolkit_off_block\": \" Off \",\n    \"when_scene_start\": \"%1 シーンが始まった時\",\n    \"start_scene\": \"%1 スタート%2\",\n    \"start_neighbor_scene\": \"%1 シーンスタート%2\",\n    \"sound_something\": \"音 %1 を再生する %2\",\n    \"sound_something_second\": \"音 %1 を %2秒再生する %3\",\n    \"sound_something_wait\": \"音 %1 を再生して待つ %2\",\n    \"sound_something_second_wait\": \"音 %1 を %2秒再生して待つ %3\",\n    \"sound_volume_change\": \"音の大きさを %1 %大きくする %2\",\n    \"sound_volume_set\": \"音の大きさを %1 %にする %2\",\n    \"sound_silent_all\": \"すべての音を止める %1\",\n    \"get_sounds\": \"%1\",\n    \"sound_something_with_block\": \"音 %1 を再生する %2\",\n    \"sound_something_second_with_block\": \"音 %1 を %2秒再生する %3\",\n    \"sound_something_wait_with_block\": \"音 %1 を再生して待つ %2\",\n    \"sound_something_second_wait_with_block\": \"音 %1 を %2 秒再生して待つ %3\",\n    \"sound_from_to\": \"音 %1 を %2秒から%3秒まで再生する %4\",\n    \"sound_from_to_and_wait\": \"音 %1 を %2秒から%3秒まで再生して待つ %4\",\n    \"when_run_button_click\": \"%1 スタートボタンをクリックした時\",\n    \"press_some_key\": \"%1 %2 キーを押した時 %3\",\n    \"when_some_key_pressed\": \"%1 %2 キーを押した時\",\n    \"mouse_clicked\": \"%1 マウスをクリックした時\",\n    \"mouse_click_cancled\": \"%1 マウスをクリックして離した時\",\n    \"when_object_click\": \"%1 オブジェクトをクリックした時\",\n    \"when_object_click_canceled\": \"%1 オブジェクトをクリックして離した時\",\n    \"when_some_key_click\": \"%1 キーを押した時\",\n    \"when_message_cast\": \"%1 %2 信号を受け取った時\",\n    \"message_cast\": \"%1 信号を送る %2\",\n    \"message_cast_wait\": \"%1 信号を送って待つ %2\",\n    \"text\": \"%1\",\n    \"text_read\": \"Textbox %1’s contents\",\n    \"text_write\": \"%1と書く %2\",\n    \"text_append\": \"%1と後ろに続けて書く %2\",\n    \"text_prepend\": \"%1と前に追加する %2\",\n    \"text_flush\": \"テキストをすべて削除する %1\",\n    \"analizyDataAddButton\": \"%1\",\n    \"append_row_to_table\": \"Add a %2 to the table %1 %3\",\n    \"insert_row_to_table\": \"Insert %3 to %2th row from the %1 %4\",\n    \"delete_row_from_table\": \"Remove %2th %3 from table %1 %4\",\n    \"set_value_from_table\": \"Change %3 in the %1 %2th row to %4 %5\",\n    \"get_table_count\": \"length of %2 in the %1\",\n    \"get_value_from_table\": \"value of the %3 in %2th row of the %1\",\n    \"calc_values_from_table\": \"%3 of the %2 in the %1\",\n    \"open_table_chart\": \"Open the chart of the %1 %2\",\n    \"close_table_chart\": \"Close the table chart\",\n    \"get_coefficient\": 'Correlation coefficient between %2and %3 in table %1',\n    \"variableAddButton\": \"%1\",\n    \"listAddButton\": \"%1\",\n    \"change_variable\": \"%1 に %2 だけ足す %3\",\n    \"set_variable\": \"%1を%2にする %3\",\n    \"show_variable\": \"変数 %1 を見せる %2\",\n    \"hide_variable\": \"変数 %1 を隠す %2\",\n    \"get_variable\": \"%1 %2\",\n    \"ask_and_wait\": \"%1 を聞いて答えを待つ %2\",\n    \"get_canvas_input_value\": \"%1\",\n    \"add_value_to_list\": \"%1 を %2 に追加する %3\",\n    \"remove_value_from_list\": \"%1番目の項目を%2 から削除する %3\",\n    \"insert_value_to_list\": \"%1を%2の%3番目に入れる %4\",\n    \"change_value_list_index\": \"%1 の %2番目の項目を%3に変更する %4\",\n    \"value_of_index_from_list\": \"%1 %2 %3 %4 %5\",\n    \"length_of_list\": \"%1 %2 %3\",\n    \"show_list\": \"リスト %1 を見せる %2\",\n    \"hide_list\": \"リスト %1 を隠す %2\",\n    \"options_for_list\": \"%1\",\n    \"set_visible_answer\": \"答えを %1 %2\",\n    \"is_included_in_list\": \"%1 %2 %3 %4 %5\",\n    \"xbot_digitalInput\": \"%1\",\n    \"xbot_analogValue\": \"%1\",\n    \"xbot_digitalOutput\": \"Digital %1 PIN, Ouput Value %2 %3\",\n    \"xbot_analogOutput\": \"Analog %1 %2 %3\",\n    \"xbot_servo\": \"Servo Motor %1 , Angle %2 %3\",\n    \"xbot_oneWheel\": \"Wheel(DC) Motor %1 , Speed %2 %3\",\n    \"xbot_twoWheel\": \"Wheel(DC) Motor Right(2) Speed: %1 Left(1) Speed: %2 %3\",\n    \"xbot_rgb\": \"RGB LED Color from Red %1 Green %2 Blue %3 %4\",\n    \"xbot_rgb_picker\": \"RGB LED Color from %1   %2\",\n    \"xbot_buzzer\": \"play note %1   %2 for %3 sec of Melody Playing %4\",\n    \"xbot_lcd\": \"LCD %1 th Line ,  Text %2 %3\",\n    \"run\": \" \",\n    \"mutant\": \"test mutant block\",\n    \"jr_start\": \"%1\",\n    \"jr_repeat\": \"%1 %2繰り返す\",\n    \"jr_item\": \"花を集める %1\",\n    \"cparty_jr_item\": \"鉛筆を拾う %1\",\n    \"jr_north\": \"  上 %1\",\n    \"jr_east\": \"右側%1\",\n    \"jr_south\": \"  下 %1\",\n    \"jr_west\": \"  左 %1\",\n    \"jr_start_basic\": \"%1 %2\",\n    \"jr_go_straight\": \"前に進む%1\",\n    \"jr_turn_left\": \"左に回転する%1\",\n    \"jr_turn_right\": \"右に回転する%1\",\n    \"jr_go_slow\": \"ゆっくり進む %1\",\n    \"jr_repeat_until_dest\": \"%1会うまで繰り返す %2\",\n    \"jr_if_construction\": \"もし%1前にあるなら %2\",\n    \"jr_if_speed\": \"もし%1前にあるなら %2\",\n    \"maze_step_start\": \"%1 スタートをクリックした時\",\n    \"maze_step_jump\": \"ジャンプする%1\",\n    \"maze_step_jump2\": \"ジャンプする%1\",\n    \"maze_step_jump_pinkbean\": \"ジャンプする%1\",\n    \"maze_step_for\": \"%1回繰り返す%2\",\n    \"test\": \"%1 this is test block %2\",\n    \"maze_repeat_until_1\": \"%1 会うまで繰り返す%2\",\n    \"maze_repeat_until_2\": \"すべての%1 会うまで繰り返す%2\",\n    \"maze_step_if_1\": \"もし前に%1があるなら%2\",\n    \"maze_step_if_2\": \"もし前に%1があるなら%2\",\n    \"maze_call_function\": \"約束を読み込む%1\",\n    \"maze_define_function\": \"約束する%1\",\n    \"maze_step_if_3\": \"もし前に%1があるなら%2\",\n    \"maze_step_if_4\": \"もし前に%1があるなら%2\",\n    \"maze_step_move_step\": \"前に1マス移動%1\",\n    \"maze_step_rotate_left\": \"左側に回転%1\",\n    \"maze_step_rotate_right\": \"右側に回転%1\",\n    \"maze_step_forward\": \"前に進む%1\",\n    \"maze_turn_right\": \"右側を眺める%1\",\n    \"maze_turn_left\": \"左側を眺める%1\",\n    \"maze_ladder_climb\": \"はしごを使う%1\",\n    \"maze_attack_lupin\": \"%1攻撃する%2\",\n    \"maze_attack_both_side\": \"両隣を攻撃する%1\",\n    \"maze_attack_pepe\": \"%1攻略する%2\",\n    \"maze_attack_yeti\": \"%1攻略する%2\",\n    \"maze_attack_mushroom\": \"%1攻略する%2\",\n    \"maze_attack_peti\": \"%1攻略する%2\",\n    \"maze_eat_item\": \"食べ物を食べる%1\",\n    \"maze_step_if_mushroom\": \"もし1マス前に%1があるなら%2\",\n    \"maze_step_if_yeti\": \"もし前に%1があるなら%2 %3そうでなければ\",\n    \"maze_step_if_left_monster\": \"もし左側の攻撃範囲にモンスターがいるなら%1 %2そうでなければ\",\n    \"maze_step_if_right_monster\": \"もし右側の攻撃範囲にモンスターがいるなら%1 %2そうでなければ\",\n    \"maze_step_if_lupin\": \"もし2マス前に%1があるなら %2\",\n    \"maze_step_if_else_road\": \"もし1マス前に道があるなら %1 %2ないなら\",\n    \"maze_step_if_else_mushroom\": \"もし1マス前に%1があるなら%2 %3そうでなければ\",\n    \"maze_step_if_else_lupin\": \"もし2マス前に%1があるなら%2 %3そうでなければ\",\n    \"maze_step_if_else_ladder\": \"もし1マス前に%1があるなら%2 %3そうでなければ\",\n    \"maze_rotate_left\": \"左に回転する%1\",\n    \"maze_rotate_right\": \"右に回転する%1\",\n    \"maze_moon_kick\": \"キックする%1\",\n    \"maze_repeat_until_3\": \"%1に到着するまで繰り返す%2\",\n    \"maze_repeat_until_4\": \"%1に到着するまで繰り返す%2\",\n    \"maze_repeat_until_5\": \"%1に到着するまで繰り返す%2\",\n    \"maze_repeat_until_6\": \"%1に到着するまで繰り返す%2\",\n    \"maze_repeat_until_7\": \"%1に到着するまで繰り返す%2\",\n    \"maze_repeat_until_goal\": \"目的地に到着するまで繰り返す%1\",\n    \"maze_repeat_until_beat_monster\": \"すべてのモンスターをやっつけるまで繰り返す%1\",\n    \"maze_radar_check\": \"%1に%2がある\",\n    \"maze_cony_flower_throw\": \"花を投げる%1\",\n    \"maze_brown_punch\": \"パンチを飛ばす%1\",\n    \"maze_iron_switch\": \"障害物を動かす%1\",\n    \"maze_james_heart\": \"ハートを飛ばす%1\",\n    \"maze_step_if_5\": \"もし前に道がないなら%2\",\n    \"maze_step_if_6\": \"もし前に%1がないなら%2\",\n    \"maze_step_if_7\": \"もし前に%1があるなら%2\",\n    \"maze_step_if_8\": \"もし%1なら%2\",\n    \"maze_step_if_else\": \"もし%1なら%2 %3そうでなければ\",\n    \"test_wrapper\": \"%1 this is test block %2\",\n    \"basic_button\": \"%1\",\n    \"ai_move_right\": \"前に進む %1\",\n    \"ai_move_up\": \"上に行く %1\",\n    \"ai_move_down\": \"下に行く %1\",\n    \"ai_repeat_until_reach\": \"目的地に到達するまで繰り返す %1\",\n    \"ai_if_else_1\": \"前に%1があるなら%2 %3そうでなければ\",\n    \"ai_boolean_distance\": \"%1 レーダー%2 %3\",\n    \"ai_distance_value\": \"%1 レーダー\",\n    \"ai_boolean_object\": \"%1物体は%2か?\",\n    \"ai_use_item\": \"アイテム使用 %1\",\n    \"ai_boolean_and\": \"%1 %2 %3\",\n    \"ai_True\": \"%1\",\n    \"ai_if_else\": \"もし%1なら%2 %3そうでなければ\",\n    \"smartBoard_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"smartBoard_get_named_sensor_value\": \"%1 Sensor value\",\n    \"smartBoard_is_button_pressed\": \"Pressed %1 button?\",\n    \"smartBoard_set_dc_motor_direction\": \"%1 DC Motor change direction %2 %3\",\n    \"smartBoard_set_dc_motor_speed\": \"%1 DC Motor %2 %3\",\n    \"smartBoard_set_dc_motor_pwm\": \"%1 DC Motor set speed %2 %3\",\n    \"smartBoard_set_servo_speed\": \"%1 RC Servo Motor Speed %2 %3\",\n    \"smartBoard_set_servo_angle\": \"%1 RC Servo Motor set angle %2 %3\",\n    \"smartBoard_set_number_eight_pin\": \"%1 port %2 %3\",\n    \"smartBoard_set_gs1_pwm\": \"GS1 port %1 %2\",\n    \"robotori_digitalInput\": \"%1\",\n    \"robotori_analogInput\": \"%1\",\n    \"robotori_digitalOutput\": \"Digital %1 PIN, Output Value %2 %3\",\n    \"robotori_analogOutput\": \"Analog %1 %2 %3\",\n    \"robotori_servo\": \"Servo Motor Angle %1 %2\",\n    \"robotori_dc_direction\": \"DC Motor %1 Direction %2 %3\",\n    \"dadublock_get_analog_value\": \"Analog %1 Sensor value\",\n    \"dadublock_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"dadublock_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"dadublock_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"dadublock_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"dadublock_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"dadublock_set_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"coconut_stop_motor\": \"stop motor %1\",\n    \"coconut_move_motor\": \"move %1 %2\",\n    \"coconut_turn_motor\": \"turn %1 %2\",\n    \"coconut_move_for_secs\": \"move %1 for time %2 %3\",\n    \"coconut_turn_for_secs\": \"turn %1 for %2 secs %3\",\n    \"coconut_turn_to_led\": \"turn %1 RGB %2 %3\",\n    \"coconut_move_outmotor\": \"external Motor %1 speed %2 %3\",\n    \"coconut_set_led_to\": \"turn on RGB %1 %2 %3\",\n    \"coconut_clear_led\": \"turn off RGB %1 %2\",\n    \"coconut_set_led_clear\": \"turn off RGB %1 %2 %3\",\n    \"coconut_set_led_time\": \"turn on RGB %1 %2 for time %3 %4\",\n    \"coconut_beep\": \"buzzer on %1\",\n    \"coconut_buzzer_time\": \"play buzzer for time %1 %2\",\n    \"coconut_buzzer_set_hz\": \"play buzzer on frequency %1 Hz for time %2 %3\",\n    \"coconut_clear_buzzer\": \"buzzer off %1\",\n    \"coconut_play_buzzer\": \"play buzzer on note %1 octave %2 %3 beat %4 %5\",\n    \"coconut_rest_buzzer\": \"rest beat %1 %2\",\n    \"coconut_play_buzzer_led\": \"play buzzer on note %1 octave %2 %3 beat %4 RGB %5 %6 %7\",\n    \"coconut_play_midi\": \"play melody %1 %2\",\n    \"coconut_floor_sensor\": \"line tracer %1\",\n    \"coconut_floor_sensing\": \"line tracer detect %1 %2\",\n    \"coconut_following_line\": \"follow the line %1\",\n    \"coconut_front_sensor\": \"IR distance sensor %1\",\n    \"coconut_front_sensing\": \"detecting obstacle %1 %2\",\n    \"coconut_obstruct_sensing\": \"detecting obstacle\",\n    \"coconut_avoid_mode\": \"avoid mode %1\",\n    \"coconut_dotmatrix_set\": \"LED Matrix %1 ( ROW %2, COL %3 ) %4\",\n    \"coconut_dotmatrix_on\": \"turn on all LED Matrix %1\",\n    \"coconut_dotmatrix_off\": \"LED Matrix clear all %1\",\n    \"coconut_dotmatrix_num\": \"LED Matrix show %1 %2\",\n    \"coconut_dotmatrix_small_eng\": \"LED Matrix show small letter %1 %2\",\n    \"coconut_dotmatrix_big_eng\": \"LED Matrix show capital letters %1 %2\",\n    \"coconut_dotmatrix_kor\": \"LED Matrix show Korean %1 %2\",\n    \"coconut_light_sensor\": \"light sensor\",\n    \"coconut_tem_sensor\": \"temperature\",\n    \"coconut_ac_sensor\": \"3-Axis Accelerometer %1 angle\",\n    \"coconut_outled_sensor\": \"set external LED pin %1 for time %2 %3\",\n    \"coconut_outspk_sensor\": \"set Speaker pin %1 frequency %2 (Hz) duration %3 seconds %4\",\n    \"coconut_outspk_sensor_off\": \"stop Speaker pin %1 %2\",\n    \"coconut_outinfrared_sensor\": \"external IR sensor %1\",\n    \"coconut_outcds_sensor\": \"external Cds sensor %1\",\n    \"coconut_servomotor_angle\": \"set servo pin %1 angle as %2 %3\",\n    \"chocopi_control_button\": \"%1 controller %2 is pressed\",\n    \"chocopi_control_event\": \"%1 When %2 controller %3 is %4\",\n    \"chocopi_control_joystick\": \"%1 controller %2 value\",\n    \"chocopi_dc_motor\": \"%1 DC motor #%2  %3 % direction %4 %5\",\n    \"chocopi_led\": \"%1 LED #%2 RGB(%3 %4 %5) %6\",\n    \"chocopi_motion_photogate_event\": \"%1 When %2 photogate %3 is %4\",\n    \"chocopi_motion_photogate_status\": \"%1 photogate #%2 is blocked\",\n    \"chocopi_motion_photogate_time\": \"time when %1 photogate %2 was %3\",\n    \"chocopi_motion_value\": \"%1 motion %2 value\",\n    \"chocopi_sensor\": \"%1 sensor %2\",\n    \"chocopi_servo_motor\": \"%1 set servo motor #%2 %3 degree %4\",\n    \"chocopi_touch_event\": \"%1 When %2 touch pad%3 is %4\",\n    \"chocopi_touch_status\": \"%1 touch pad%2 is touched\",\n    \"chocopi_touch_value\": \"%1 touch pad%2 value\",\n    \"dadublock_car_digital_pwm\": \"디지털 %1 번 핀을 %2 (으)로 정하기 %3\",\n    \"dadublock_car_get_analog_value\": \"아날로그 %1 번 센서값\",\n    \"dadublock_car_get_analog_value_map\": \"아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  \",\n    \"dadublock_car_get_digital\": \"디지털 %1 번 센서값\",\n    \"dadublock_car_get_irsensor\": \"적외선 %1 번 센서값\",\n    \"dadublock_car_get_ultrasonic_value\": \"울트라소닉 Trig %1번핀 Echo %2번핀 센서값\",\n    \"dadublock_car_motor\": \"모터 %1 번을 %2 (으)로 %3 %의 속도로 움직이기 %4\",\n    \"dadublock_car_motor_stop\": \"모터 %1 번 멈추기 %2\",\n    \"dadublock_car_set_servo\": \"서보모터 %1 번 핀을 %2 의 각도로 정하기 %3\",\n    \"dadublock_car_set_tone\": \"디지털 %1 번 핀 을 %2 음으로 %3의 옥타브로 %4 만큼 연주하기 %5\",\n    \"dadublock_car_toggle_led\": \"디지털 %1 번 핀 %2 %3\",\n    \"dadublock_get_digital\": \"디지털 %1 번 센서값\",\n    \"ev3_get_sensor_value\": \"%1's value\",\n    \"ev3_touch_sensor\": \"%1's touch sensor activted?\",\n    \"ev3_color_sensor\": \"%1's %2 value\",\n    \"ev3_motor_power\": \"%1's value print as %2 %3\",\n    \"ev3_motor_power_on_time\": \"%1's value for %2seconds %3 printed %4\",\n    \"ev3_motor_degrees\": \"%1's value in %2 direction turn %3 degrees %4\",\n    \"rokoboard_get_sensor_value_by_name\": \"%1 value\",\n    \"ardublock_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"ardublock_get_analog_value\": \"Analog %1 Sensor value\",\n    \"ardublock_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"ardublock_get_digital\": \"Digital %1 Sensor value\",\n    \"ardublock_get_left_cds_analog_value\": \"Left CDS %1 Sensor value\",\n    \"ardublock_get_right_cds_analog_value\": \"Left CDS  %1 Sensor value\",\n    \"ardublock_get_sound_analog_value\": \"Analog Sound %1 Sensor value\",\n    \"ardublock_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"ardublock_set_left_motor\": \"Left motor direction to %1 speed %2 set %3\",\n    \"ardublock_set_right_motor\": \"Right motor direction to %1 speed %2 set %3\",\n    \"ardublock_set_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"ardublock_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"ardublock_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"ardublock_toggle_left_led\": \"Left Light %1 Pin %2 %3\",\n    \"ardublock_toggle_right_led\": \"Right Light %1 Pin %2 %3\",\n    \"mkboard_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"mkboard_get_analog_value\": \"Analog %1 Sensor value\",\n    \"mkboard_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"mkboard_get_digital\": \"Digital %1 Sensor value\",\n    \"mkboard_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"mkboard_set_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"mkboard_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"mkboard_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"mkboard_set_lcd\": \"1602 LCD Row %1, Column %2 Value %3 %4\",\n    \"mkboard_lcd_command\": \"1602 LCD Command %1 execute %2\",\n    \"altino_analogValue\": \"altino %1 sensor value\",\n    \"altino_dot_display\": \"electronic scoreboard %1 display %2\",\n    \"altino_dot_display_line\": \"1col %1 2col %2 3col %3 4col %4 5col %5 6col %6 7col %7 8col %8 display %9\",\n    \"altino_light\": \"%1 light %2  %3\",\n    \"altino_rear_wheel\": \"rear motor right %1 left %2 setting %3\",\n    \"altino_sound\": \"%1 octave %2 play  %3\",\n    \"altino_steering\": \"direction %1 setting %2\",\n    \"jdkit_altitude\": \"드론을 %1 높이만큼 날리기 %2\",\n    \"jdkit_button\": \"%1번 버튼 값 읽어오기\",\n    \"jdkit_connect\": \"드론 연결 상태 읽어오기\",\n    \"jdkit_emergency\": \"드론을 즉시 멈추기 %1\",\n    \"jdkit_gyro\": \"보드 %1 기울기 값 읽어오기\",\n    \"jdkit_joystick\": \"조이스틱 %1 읽기\",\n    \"jdkit_led\": \"%1 LED %2  %3\",\n    \"jdkit_motor\": \"%1 모터를 %2 세기로 돌리기 %3\",\n    \"jdkit_ready\": \"드론 비행 준비 상태 읽어오기\",\n    \"jdkit_rollpitch\": \"드론을 %1 방향 %2 세기로 움직이기 %3\",\n    \"jdkit_throttle\": \"드론 프로펠러를 %1 만큼 세기로 돌리기 %2\",\n    \"jdkit_tune\": \"%1 음을  %2 초동안 소리내기 %3\",\n    \"jdkit_ultrasonic\": \"거리(초음파)값 읽어오기\",\n    \"jdkit_yaw\": \"드론을 %1 만큼 회전하기 %2\",\n    \"memaker_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"memaker_get_analog_value\": \"Analog %1 Sensor value\",\n    \"memaker_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"memaker_get_digital\": \"Digital %1 Sensor value\",\n    \"memaker_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"memaker_set_lcd\": \"1602 LCD Row %1, Column %2 Value %3 %4\",\n    \"memaker_set_servo\": \"Set servo pin %1 angle as %3\",\n    \"memaker_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"memaker_lcd_command\": \"1602 LCD Command %1 execute %2\",\n    \"edumaker_digital_pwm\": \"디지털 %1 번 핀을 %2 (으)로 정하기 %3\",\n    \"edumaker_get_analog_value\": \"아날로그 %1 번 센서값\",\n    \"edumaker_get_analog_value_map\": \"%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값\",\n    \"edumaker_get_digital\": \"디지털 %1 번 센서값\",\n    \"edumaker_get_ultrasonic_value\": \"울트라소닉 Trig %1 Echo %2 센서값\",\n    \"edumaker_set_servo\": \"디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3\",\n    \"edumaker_set_tone\": \"디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5\",\n    \"edumaker_toggle_led\": \"디지털 %1 번 핀 %2 %3\",\n    \"creamo_get_number_sensor_value\": \"PWM_Block %1 Sensor value\",\n    \"creamo_get_port_number\": \"%1\",\n    \"creamo_get_pwm_port_number\": \"%1\",\n    \"creamo_motor_port_number\": \"%1\",\n    \"creamo_toggle_led\": \"LED_Block %1 Pin %2 %3\",\n    \"creamo_toggle_motor\": \"Motor_Block %1 pin %2 %3\",\n    \"creamo_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"mechatro_get_dc_motor_current\": \"Get 1%motor current\",\n    \"mechatro_get_digital\": \"%1\",\n    \"mechatro_get_sensor_value\": \"Analog %1 Sensor value\",\n    \"mechatro_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"mechatro_set_blue_pw\": \"Change PW of Bluetooth to %1%2%3%4 %5\",\n    \"mechatro_set_dc_motor\": \"Set %1 motor speed to %2 %3\",\n    \"mechatro_set_digital\": \"Digital %1 Pin %2 %3\",\n    \"mechatro_set_pwm\": \"Digital %1 Pin %2 %3\",\n    \"mechatro_set_servo_position\": \"Set servo pin %1 angle as %2 %3\",\n    \"mechatro_set_servo_speed\": \"Set servo pin %1 speed %2 degree per second %3\",\n    \"mechatro_set_threshold\": \"Set %1 threshold : %2%3\",\n    \"mechatro_set_tone\": \"Play tone pin %1 on note %2 octave %3 %4\",\n    \"mechatro_set_tone_time\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"funboard_buzzer_onoff\": \"buzzer %1 %2\",\n    \"funboard_buzzer_second\": \"buzzer%1%2seconds%3\",\n    \"funboard_buzzer_tone_simple\": \"play note%1%2,%3sec of Melody Playing%4\",\n    \"funboard_color_led_on_pwm\": \"%1COLOR  LED %2 % %3\",\n    \"funboard_color_led_onoff\": \"%1COLOR  LED %2 %3\",\n    \"funboard_convert_scale\": \"Convert %1 value from %2~%3 to %4~%5\",\n    \"funboard_dotmatrix_1column\": \"%1column %2set %3\",\n    \"funboard_dotmatrix_1row\": \"%1row %2set %3\",\n    \"funboard_dotmatrix_1row_1column\": \"%1%2 %3set %4\",\n    \"funboard_dotmatrix_64_display\": \"%1 (8x8)display%2\",\n    \"funboard_dotmatrix_big_eng\": \"capital letters %1 %2\",\n    \"funboard_dotmatrix_char_display\": \"char%1display%2\",\n    \"funboard_dotmatrix_extra_char\": \"char %1 %2\",\n    \"funboard_dotmatrix_intensity\": \"Intensity %1% %2\",\n    \"funboard_dotmatrix_kor\": \"∷∷  korean %1 %2\",\n    \"funboard_dotmatrix_num\": \"number %1 %2\",\n    \"funboard_dotmatrix_onoff\": \"turn all %1 %2\",\n    \"funboard_dotmatrix_scroll_option\": \"scroll direction%1%2\",\n    \"funboard_dotmatrix_scroll_rapid\": \"scroll rapid %1% %2\",\n    \"funboard_dotmatrix_set\": \"%1row %2column  %3 %4\",\n    \"funboard_dotmatrix_small_eng\": \"small letter %1 %2\",\n    \"funboard_dotmatrix_string_display\": \"string%1display%2\",\n    \"funboard_dotmatrix_string_display_scroll\": \"string%1display%2scroll%3\",\n    \"funboard_dotmatrix_symbol\": \"symbol %1 %2\",\n    \"funboard_get_analog_sensor_2state\": \"%1 value %2\",\n    \"funboard_get_digital_button_value\": \"%1 button value\",\n    \"funboard_get_number_sensor_value\": \"%1 value\",\n    \"funboard_get_touch_button_value\": \"%1 touch button value\",\n    \"funboard_set_digital_buzzer\": \"Play tone octave %1 note %2 beat %3 %4\",\n    \"funboard_what_button_pressed\": \"%1 button pressed.\",\n    \"funboard_what_touch_button_pressed\": \"%1 touch button pressed.\"\n};\nLang.TextCoding = {\n    \"block_name\": \"ブロック名\",\n    \"title_syntax\": \"文法エラー\",\n    \"title_converting\": \"変換エラー\",\n    \"message_syntax_default\": \"文法にエラーがあります\",\n    \"message_syntax_unexpected_token\": \"文法に合わないトークンが含まれています\",\n    \"message_syntax_reserved_token\": \"使用できない変数名です。\",\n    \"message_syntax_reserved_token_list\": \"使用できないリスト名です。\",\n    \"message_syntax_unexpected_character\": \"文法に合わない文字が含まれています\",\n    \"message_syntax_unexpected_indent\": \"文法に合わない分かち書きが含まれています\",\n    \"message_conv_default\": \"このコードには対応していません\",\n    \"message_conv_no_support\": \"変換できないコードです\",\n    \"message_conv_no_variable\": \"変数が宣言されませんでした\",\n    \"message_conv_no_list\": \"リストが宣言されませんでした\",\n    \"message_conv_no_object\": \"オブジェクトには対応していません\",\n    \"message_conv_no_function\": \"関数は変換できません。\",\n    \"message_conv_no_entry_event_function\": \"エントリーイベント関数は他の関数の中に存在できません。\",\n    \"message_conv_undefined_function\": \"定義されていない命令です。命令が正しく入力されているか確認してください。\",\n    \"message_conv_is_expect1\": \"正しくない文法です。\",\n    \"message_conv_is_expect2\": \" が正しく入力されているか確認してください。\",\n    \"message_conv_instead\": \"正しくない文法です。%1の代わりに%2が必要です。\",\n    \"message_conv_is_wrong1\": \"正しくない文法です。\",\n    \"message_conv_is_wrong2\": \"は来られない位置です。\",\n    \"message_conv_or\": \" 私\",\n    \"subject_syntax_default\": \"その他\",\n    \"subject_syntax_token\": \"トークン\",\n    \"subject_syntax_character\": \"文字\",\n    \"subject_syntax_indent\": \"分かち書き\",\n    \"subject_conv_default\": \"その他\",\n    \"subject_conv_general\": \"一般\",\n    \"subject_conv_variable\": \"変数\",\n    \"subject_conv_list\": \"リスト\",\n    \"subject_conv_object\": \"オブジェクト\",\n    \"subject_conv_function\": \"関数\",\n    \"alert_variable_empty_text\": \"登録された変数の中にスペース(分かち書き)が含まれる変数がある場合、モード変換できません。\",\n    \"alert_list_empty_text\": \"登録されたリストの中にスペース(分かち書き)が含まれるリストがある場合、モード変換できません。\",\n    \"alert_function_name_field_multi\": \"登録された関数の中に関数名に[名前]ブロックが2回以上含まれている場合、モード変換できません。\",\n    \"alert_function_name_disorder\": \"登録された関数の中で[名前]ブロックが[文字/数字値]または[判断値]ブロックより後に書かれる場合、モード変換できません。\",\n    \"alert_function_has_boolean\": \"エントリーパイソンに変換後、再びブロックモードに切り替えると関数に使われた「判断値」はすべて「文字／数字の値」に変わります。\",\n    \"alert_function_editor\": \"関数作成及び編集中にはモード変換できません。\",\n    \"alert_function_no_support\": \"テキストモードでは関数を作成・編集することができません。\",\n    \"alert_list_no_support\": \"テキストモードではリストを作成・編集することができません。\",\n    \"alert_variable_no_support\": \"テキストモードでは変数を作成・編集することができません。\",\n    \"alert_signal_no_support\": \"テキストモードでは信号を作成・編集することができません。\",\n    \"alert_legacy_no_support\": \"切り替えられないブロックが存在するため、モード変換できません。\",\n    \"alert_variable_empty_text_add_change\": \"変数名にスペース(分かち書き)を含めることはできません。\",\n    \"alert_list_empty_text_add_change\": \"リスト名にスペース(分かち書き)を含めることはできません。\",\n    \"alert_list_contains_exceed_length_value\": \"リスト項目に15桁の以上の数が入力されている場合、モード変換できません。\",\n    \"alert_function_name_empty_text_add_change\": \"関数名にスペース(分かち書き)を含めることはできません。\",\n    \"alert_no_save_on_error\": \"文法エラーが存在しているため作品を保存できません。\",\n    \"alert_api_no_support\": \"作品に拡張ブロックが使用されている場合には、エントリーパイソンモードに変更することができません。\",\n    \"warn_unnecessary_arguments\": \"&(calleeName)();は括弧の間に値が入力される必要がないコマンドです。(line:&(lineNumber))\",\n    \"python_code\": \" オブジェクトのパイソンコード\",\n    \"eof\": \"改行\",\n    \"newline\": \"改行\",\n    \"indent\": \"インデント\",\n    \"num\": \"数字\",\n    \"string\": \"文字列\",\n    \"name\": \"変数名\"\n};\nLang.PythonHelper = {\n    \"when_run_button_click_desc\": \"[スタート]ボタンをクリックすると下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"when_run_button_click_exampleCode\": \"def when_start():\\n    Entry.print(\\\"やあ!\\\")\",\n    \"when_run_button_click_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"やあ!\\\"と話します。\",\n    \"when_some_key_pressed_desc\": \"Aキーを押すと下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"when_some_key_pressed_elements\": \"A-- 次の選択肢のうち一つ<br>① アルファベット : \\\"A\\\", \\\"B\\\" ~ \\\"Z\\\"など(小文字可能)<br>② 数字: 1, 2, 3, 4 ~ 9, 0<br>③ 特殊キー: \\\"space\\\", \\\"enter\\\"<br>④ 方向キー : \\\"up\\\", \\\"down\\\", \\\"right\\\", \\\"left\\\"\",\n    \"when_some_key_pressed_exampleCode\": \"def when_press_key(\\\"W\\\"):\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(1):\\n    Entry.add_size(10)\",\n    \"when_some_key_pressed_exampleDesc\": \"Wキーを押すとオブジェクトが移動方向に10移動し、1キーを押すとオブジェクトのサイズが10大きくなります。\",\n    \"mouse_clicked_desc\": \"マウスをクリックした時、下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"mouse_clicked_exampleCode\": \"def when_click_mouse_on():\\n    Entry.add_size(10)\\n    Entry.move_to_direction(10)\",\n    \"mouse_clicked_exampleDesc\": \"マウスをクリックすると、オブジェクトのサイズが10だけ大きくなり、移動方向に10移動します。\",\n    \"mouse_click_cancled_desc\": \"マウスクリックを解除した時、下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"mouse_click_cancled_exampleCode\": \"def when_click_mouse_off():\\n    Entry.move_to_direction(-10)\\n\\ndef when_click_mouse_on():\\n    Entry.move_to_direction(10)\",\n    \"mouse_click_cancled_exampleDesc\": \"マウスをクリックするとオブジェクトが移動方向に10移動し、マウスクリックを解除するとオブジェクトが移動方向に-10移動します。\",\n    \"when_object_click_desc\": \"当該オブジェクトをクリックした時、下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"when_object_click_exampleCode\": \"def when_click_object_on():\\n    Entry.print_for_sec(\\\"回転!\\\", 0.5)\\n    Entry.add_rotation(90)\",\n    \"when_object_click_exampleDesc\": \"オブジェクトをクリックすると、オブジェクトが\\\"回転!\\\"と話し、90度回転します。\",\n    \"when_object_click_canceled_desc\": \"当該オブジェクトクリックを解除した時、下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"when_object_click_canceled_exampleCode\": \"def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)\",\n    \"when_object_click_canceled_exampleDesc\": \"オブジェクトをクリックするとオブジェクトが90度回転し、オブジェクトクリックを解除するとオブジェクトが-90度回転します。\",\n    \"when_message_cast_desc\": \"A信号を受信すると下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。<br>もしA信号がなければ[属性]タブにA信号が自動作成されます。\",\n    \"when_message_cast_elements\": \"A-- \\\"信号名\\\"\",\n    \"when_message_cast_exampleCode\": \"def when_click_mouse_on():\\n    Entry.send_signal(\\\"信号\\\")\\n\\ndef when_get_signal(\\\"信号\\\"):\\n    Entry.print_for_sec(\\\"やあ! 嬉しいな\\\", 0.5)\",\n    \"when_message_cast_exampleDesc\": \"マウスをクリックすると\\\"信号\\\"を送り、\\\"信号\\\"を受信した時、\\\"やあ! 嬉しいな\\\"と0.5秒間話します。\",\n    \"message_cast_desc\": \"Aに入力された信号を送ります。<br>もしA信号がなければ[属性]タブにA信号が自動作成されます。\",\n    \"message_cast_elements\": \"A-- \\\"信号名\\\"\",\n    \"message_cast_exampleCode\": \"#\\\"オブジェクト1\\\"のパイソンコード\\ndef when_start():\\n    Entry.print_for_sec(\\\"やあ! 君は何歳なの?\\\", 2)\\n    Entry.send_signal(\\\"信号\\\")\\n\\n#\\\"オブジェクト2\\\"のパイソンコード\\ndef when_get_signal(\\\"信号\\\"):\\n    Entry.print_for_sec(\\\"やあ。僕は3歳だよ。\\\", 2)\",\n    \"message_cast_exampleDesc\": \"[スタート]ボタンをクリックすると\\\"オブジェクト1\\\"が\\\"やあ! 君は何歳なの?\\\"と2秒間話し\\\"信号を送ります。, \\\"オブジェクト2\\\"が\\\"信号\\\"を受信した時、\\\"やあ。僕は3歳だよ。\\\"と2秒間話します。\",\n    \"message_cast_wait_desc\": \"Aに入力された信号を送り、その信号を受信したコマンドの実行が終了するまで待機します。<br>もしA信号がなければ[属性]タブにA信号が自動作成されます。\",\n    \"message_cast_wait_elements\": \"A-- \\\"信号名\\\"\",\n    \"message_cast_wait_exampleCode\": \"#\\\"オブジェクト1\\\"のパイソンコード\\ndef when_start():\\n    Entry.print_for_sec(\\\"かくれんぼしようよ!\\\", 2)\\n    Entry.send_signal_wait(\\\"信号\\\")\\n    Entry.hide()\\n\\n#\\\"オブジェクト2\\\"のパイソンコード\\ndef when_get_signal(\\\"信号\\\"):\\n    Entry.print_for_sec(\\\"いいよ!\\\", 2)\",\n    \"message_cast_wait_exampleDesc\": \"[スタート]ボタンをクリックすると\\\"オブジェクト1\\\"が\\\"かくれんぼしようよ!\\\"と2秒間話して\\\"信号\\\"を送信してから待機します。\\\"オブジェクト2\\\"が\\\"信号\\\"を受信すると\\\"いいよ!\\\"を2秒間話します。\\\"オブジェクト1\\\"がその後に模様を隠します。\",\n    \"when_scene_start_desc\": \"シーンが始まると下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"when_scene_start_exampleCode\": \"#\\\"シーン 1\\\"のパイソンコード\\ndef when_start():\\n    Entry.print_for_sec(\\\"他の場所に行こうか?\\\", 2)\\n    Entry.start_scene(\\\"シーン 2\\\")\\n\\n#\\\"シーン 2\\\"のパイソンコード\\ndef when_start_scene():\\n    Entry.print(\\\"ここはどこだろう?\\\")\",\n    \"when_scene_start_exampleDesc\": \"\\\"シーン1\\\"で[スタート]ボタンをクリックすると\\\"他の場所に行こうか?\\\"と2秒間話し、\\\"シーン2\\\"が始まります。\\\"シーン2\\\"が始まるとオブジェクトが\\\"ここはどこだろう?\\\"と話します。\",\n    \"start_scene_desc\": \"A シーンを始めます。\",\n    \"start_scene_elements\": \"A-- \\\"シーン名\\\"\",\n    \"start_scene_exampleCode\": \"#\\\"シーン1\\\"のパイソンコード\\ndef when_click_object_on():\\n    Entry.start_scene(\\\"シーン2\\\")\",\n    \"start_scene_exampleDesc\": \"\\\"シーン1\\\"で当該オブジェクトをクリックすると、\\\"シーン 2\\\"が始まります。\",\n    \"start_neighbor_scene_desc\": \"Aに入力した次または前のシーンを始めます。\",\n    \"start_neighbor_scene_elements\": \"A-- 次の選択肢のうち一つ<br>① 次のシーン: \\\"next\\\"または\\\"次\\\"<br>② 前のシーン: \\\"prev\\\"または\\\"前\\\"\",\n    \"start_neighbor_scene_exampleCode\": \"#\\\"シーン 1\\\"のパイソンコード\\ndef when_press_key(\\\"right\\\"):\\n    Entry.start_scene_of(\\\"next\\\")\\n\\n#\\\"シーン 2\\\"のパイソンコード\\ndef when_press_key(\\\"left\\\"):\\n    Entry.start_scene_of(\\\"prev\\\")\",\n    \"start_neighbor_scene_exampleDesc\": \"\\\"シーン 1\\\"で右方向キーを押すと次のシーンが、\\\"シーン2\\\"で左方向キーを押すと前のシーンが始まります。\",\n    \"wait_second_desc\": \"A秒待機後、次のブロックを実行します。\",\n    \"wait_second_elements\": \"A-- 秒に該当する数を入力\",\n    \"wait_second_exampleCode\": \"def when_start():\\n    Entry.add_effect(\\\"color\\\", 10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_size(10)\",\n    \"wait_second_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトに色効果を10だけ与え、2秒間待機した後にサイズを10だけ大きくします。\",\n    \"repeat_basic_desc\": \"下のコマンドをA回繰り返して実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"repeat_basic_elements\": \"A-- 繰り返し回数入力\",\n    \"repeat_basic_exampleCode\": \"def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()\",\n    \"repeat_basic_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが移動方向に10移動し、スタンプを押す行動を10回繰り返します。\",\n    \"repeat_inf_desc\": \"A 判断がTrueの間、下のコマンドを繰り返し実行します。AにTrueを入力すると続けて繰り返されます。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"repeat_inf_elements\": \"A-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10など<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\")など\",\n    \"repeat_inf_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()\",\n    \"repeat_inf_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトが続けて移動方向に10移動し、壁にぶつかると弾かれます。\",\n    \"repeat_while_true_desc\": \"A判断がTrueになるまで下のコマンドを繰り返し実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"repeat_while_true_elements\": \"A-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10など<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\")など\",\n    \"repeat_while_true_exampleCode\": \"def when_start():\\n    while not Entry.is_key_pressed(\\\"space\\\"):\\n        Entry.add_rotation(90)\",\n    \"repeat_while_true_exampleDesc\": \"[スタート]ボタンをクリックすると、スペースキーを押す時までオブジェクトが90度回転します。\",\n    \"stop_repeat_desc\": \"このコマンドと最も近いリピートコマンドの繰り返しを中断します。\",\n    \"stop_repeat_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_key_pressed(\\\"enter\\\"):\\n            break\",\n    \"stop_repeat_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトが移動方向に10だけ継けて移動します。エンターキーを押すと繰り返しが中断されます。\",\n    \"_if_desc\": \"A部分の判断がTrueならif A:下のコマンドを実行し、Falseなら実行しません。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"_if_elements\": \"A-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10など<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\")など\",\n    \"_if_exampleCode\": \"def when_click_mouse_on():\\n    if (Entry.value_of_mouse_pointer(\\\"x\\\") > 0):\\n        Entry.print_for_sec(\\\"右側!\\\", 0.5)\",\n    \"_if_exampleDesc\": \"マウスをクリックした時、マウスのx座標が0より大きければオブジェクトが\\\"右側!\\\"と0.5秒間話します。\",\n    \"if_else_desc\": \"A部分の判断がTrueならif A: 下のコマンドを実行し、Falseならelse: 下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"if_else_elements\": \"A-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10など<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\")など\",\n    \"if_else_exampleCode\": \"def when_click_mouse_on():\\n    if Entry.is_touched(\\\"mouse_pointer\\\"):\\n        Entry.print(\\\"触れた!\\\")\\n    else:\\n        Entry.print(\\\"触れなかった!\\\")\",\n    \"if_else_exampleDesc\": \"マウスをクリックした時マウスポインターがオブジェクトに触れると\\\"触れた!\\\"を、そうでない時は\\\"触れなかった!\\\"と話します。\",\n    \"wait_until_true_desc\": \"A部分の判断がTrueになるまでコードの実行を中断して待機します。\",\n    \"wait_until_true_elements\": \"A-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10など<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\")など\",\n    \"wait_until_true_exampleCode\": \"def when_start():\\n    Entry.print(\\\"エンターを押してみて!\\\")\\n    Entry.wait_until(Entry.is_key_pressed(\\\"enter\\\"))\\n    Entry.print(\\\"うまいね!\\\")\",\n    \"wait_until_true_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトが\\\"エンターを押してみて!\\\"と話し、エンターキーを押す時まで待機します。エンターキーを押すと\\\"うまいね!\\\"と話します。\",\n    \"stop_object_desc\": \"Aコードの実行を中断します。\",\n    \"stop_object_elements\": \"A-- 次の選択肢のうち1つ<br>① \\\"all\\\":  すべてのオブジェクトのすべてのコード<br>② \\\"self\\\" : 当該オブジェクトのすべてのコード<br>③ \\\"this\\\": このコマンドが含まれたコード<br>④ \\\"others\\\" : 当該オブジェクトのコードのうち、このコマンドが含まれたコードを除くすべてのコード<br/>⑤ \\\"ohter_objects\\\" : このオブジェクトを除く他のすべてのオブジェクトのコード\",\n    \"stop_object_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to(\\\"mouse_pointer\\\")\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.stop_code(\\\"all\\\")\\n\",\n    \"stop_object_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトが続けてマウスポインターの位置に移動します。スペースキーを押すと、すべてのコードの実行が中断されます。\",\n    \"restart_project_desc\": \"作品を最初から再実行します。\",\n    \"restart_project_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.add_size(10)\\n\\ndef when_press_key(\\\"enter\\\"):\\n    Entry.start_again()\",\n    \"restart_project_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトのサイズが続けてアップします。エンターキーを押すと作品を最初から再実行します。\",\n    \"when_clone_start_desc\": \"当該オブジェクトのコピーが新しく作成された時、下のコマンドを実行します。<br>下のコマンドは[Tab]キーを用いてインデントを作成します。\",\n    \"when_clone_start_exampleCode\": \"def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\\\"self\\\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\",\n    \"when_clone_start_exampleDesc\": \"[スタート]ボタンをクリックすると自分のコピーを5つ作成します。コピーが新しく作成された際、コピーのx座標を-200から200の間の乱数にします。\",\n    \"create_clone_desc\": \"A オブジェクトのコピーを作成します。\",\n    \"create_clone_elements\": \"A-- 次の選択肢のうち一つ<br>① \\\"オブジェクト名\\\"<br>② \\\"self\\\"または\\\"自分\\\"\",\n    \"create_clone_exampleCode\": \"def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\\\"self\\\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\",\n    \"create_clone_exampleDesc\": \"[スタート]ボタンをクリックすると、自分のコピーを5つ作成します。コピーが新しく作成された際、コピーのx座標を-200から200までの乱数にします。\",\n    \"delete_clone_desc\": \"Entry.make_clone_of(A) コマンドにより作成されたコピーを削除します。\",\n    \"delete_clone_exampleCode\": \"def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\\\"自分\\\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_click_object_on():\\n    Entry.remove_this_clone()\",\n    \"delete_clone_exampleDesc\": \"[スタート]ボタンをクリックすると自分のコピーを5つ作成します。コピーが新しく作成された際、コピーのx座標を-200から200までの乱数にします。コピーをクリックするとクリックされたコピーを削除します。\",\n    \"remove_all_clones_desc\": \"当該オブジェクトのすべてのコピーを削除します。\",\n    \"remove_all_clones_exampleCode\": \"def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\\\"自分\\\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.remove_all_clone()\",\n    \"remove_all_clones_exampleDesc\": \"[スタート]ボタンをクリックすると自分のコピーを5つ作成します。コピーが新しく作成された際、コピーのx座標を-200から200までの乱数にします。スペースキーを押すとすべてのコピーを削除します。\",\n    \"move_direction_desc\": \"オブジェクトの移動方向矢印が示す方向にAだけ動きます。\",\n    \"move_direction_elements\": \"A-- 移動する距離に該当する数\",\n    \"move_direction_exampleCode\": \"def when_start():\\n    Entry.move_to_direction(10)\",\n    \"move_direction_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが移動方向に10移動します。\",\n    \"bounce_wall_desc\": \"オブジェクトが画面の端に到達すると弾かれます。\",\n    \"bounce_wall_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()\",\n    \"bounce_wall_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが続けて移動方向に10移動し、壁にぶつかると弾かれます。\",\n    \"move_x_desc\": \"オブジェクトのx座標をAだけ変更します。\",\n    \"move_x_elements\": \"A-- x座標の変化値<br>① 正数: オブジェクトが右側に移動します。<br>② 負数: オブジェクトが左側に移動します。\",\n    \"move_x_exampleCode\": \"def when_start():\\n    Entry.add_x(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_x(-10)\",\n    \"move_x_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトが右に10移動し、2秒間待機後、左に10移動します。\",\n    \"move_y_desc\": \"オブジェクトのy座標をAだけ変更します。\",\n    \"move_y_elements\": \"A-- y座標の変化値<br>① 正数: オブジェクトが上に移動します。<br>② 負数: オブジェクトが下に移動します。\",\n    \"move_y_exampleCode\": \"def when_start():\\n    Entry.add_y(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_y(-10)\",\n    \"move_y_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトが上に10移動し、2秒間待機した後、下に10移動します。\",\n    \"move_xy_time_desc\": \"オブジェクトがxとy座標をそれぞれAとBだけC秒に渡り徐々に変更します。\",\n    \"move_xy_time_elements\": \"A-- x座標の変化値<br>① 正数: オブジェクトが右側に移動します。<br>② 負数: オブジェクトが左側に移動します。%nextB-- y座標の変化値<br>① 陽数: オブジェクトが上に移動します。<br>② 負数: オブジェクトが下に移動します。%nextC-- 移動する時間(秒)\",\n    \"move_xy_time_exampleCode\": \"def when_start():\\n    Entry.add_xy_for_sec(100, 100, 2)\\n    Entry.add_xy_for_sec(-100, -100, 2)\",\n    \"move_xy_time_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが右上に100だけ2秒間移動した後、左下に100だけ2秒間移動します。\",\n    \"locate_x_desc\": \"オブジェクトのx座標をAにします。(オブジェクトの中心点が基準になります。)\",\n    \"locate_x_elements\": \"A-- 移動するx座標\",\n    \"locate_x_exampleCode\": \"def when_press_key(\\\"right\\\"):\\n    Entry.set_x(100)\\n\\ndef when_press_key(\\\"left\\\"):\\n    Entry.set_x(-100)\\n\",\n    \"locate_x_exampleDesc\": \"右方向キーを押すとオブジェクトのx座標を100にし、左方向キーを押すとオブジェクトのx座標を-100にします。\",\n    \"locate_y_desc\": \"オブジェクトのy座標をAにします。(オブジェクトの中心点が基準になります。)\",\n    \"locate_y_elements\": \"B-- 移動するy座標\",\n    \"locate_y_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.set_y(100)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.set_y(-100)\",\n    \"locate_y_exampleDesc\": \"上方向キーを押すとオブジェクトのy座標を100にし、下方向キーを押すとオブジェクトのy座標を-100にします。\",\n    \"locate_xy_desc\": \"オブジェクトが座標(A, B)に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate_xy_elements\": \"A-- 移動するx座標%nextB-- 移動するy座標\",\n    \"locate_xy_exampleCode\": \"def when_click_mouse_on():\\n    Entry.set_xy(0, 0)\\n\\ndef when_press_key(\\\"right\\\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\\\"up\\\"):\\n    Entry.add_y(10)\",\n    \"locate_xy_exampleDesc\": \"右方向キーを押すとオブジェクトのx座標を10だけ変更し、上方向キーを押すとオブジェクトのy座標を10だけ変更します。マウスをクリックすると、オブジェクトのx, y座標を0にします。\",\n    \"locate_xy_time_desc\": \"オブジェクトが座標(A, B)に、C秒に渡り徐々に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate_xy_time_elements\": \"A-- 移動するx座標%nextB-- 移動するy座標%nextC-- 移動する時間\",\n    \"locate_xy_time_exampleCode\": \"def when_click_mouse_on():\\n    Entry.set_xy_for_sec(0, 0, 2)\\n\\ndef when_press_key(\\\"right\\\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\\\"up\\\"):\\n    Entry.add_y(10)\",\n    \"locate_xy_time_exampleDesc\": \"右方向キーを押すとオブジェクトのx座標を10だけ変更し、上方向キーを押すとオブジェクトのy座標を10だけ変更します。マウスをクリックすると、2秒間オブジェクトをx,y 座標0に移動させます。\",\n    \"locate_desc\": \"オブジェクトがAの位置に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate_elements\": \"A-- 次の選択肢のうち一つ<br>① \\\"オブジェクト名\\\"<br>② \\\"mouse_pointer\\\"または\\\"マウスポインター\\\"\",\n    \"locate_exampleCode\": \"def when_click_mouse_on():\\n    Entry.move_to(\\\"mouse_pointer\\\")\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.move_to(\\\"オブジェクト\\\")\",\n    \"locate_exampleDesc\": \"マウスをクリックすると、オブジェクトがマウスポインターの位置に移動します。<br>スペースキーを押すとオブジェクトが\\\"オブジェクト\\\"位置に移動します。\",\n    \"locate_object_time_desc\": \"オブジェクトがAの位置にB秒に渡り徐々に移動します。(オブジェクトの中心点が基準になります。)\",\n    \"locate_object_time_elements\": \"A-- 次の選択肢のうち一つ<br>① \\\"オブジェクト名\\\"<br>② \\\"mouse_pointer\\\"または\\\"マウスポインター\\\" %nextB-- 移動する時間(秒)\",\n    \"locate_object_time_exampleCode\": \"def when_click_mouse_on():\\n    Entry.move_to_for_sec(\\\"mouse_pointer\\\", 2)\",\n    \"locate_object_time_exampleDesc\": \"マウスをクリックすると、オブジェクトが2秒間徐々にマウスポインターの位置に移動します。\",\n    \"rotate_relative_desc\": \"オブジェクトの方向をA度だけ時計方向に回転します。(オブジェクトの中心点を基準に回転します。)\",\n    \"rotate_relative_elements\": \"A-- 回転する角度\",\n    \"rotate_relative_exampleCode\": \"def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)\",\n    \"rotate_relative_exampleDesc\": \"オブジェクトをクリックするとオブジェクトが90度だけ回転し、オブジェクトクリックを解除するとオブジェクトが-90度だけ回転します。\",\n    \"direction_relative_desc\": \"オブジェクトの移動方向をA度だけ回転します。\",\n    \"direction_relative_elements\": \"A-- 回転する角度\",\n    \"direction_relative_exampleCode\": \"def when_start():\\n    Entry.move_to_direction(50)\\n    Entry.wait_for_sec(0.5)\\n    Entry.add_direction(90)\\n    Entry.wait_for_sec(0.5)\\n    Entry.move_to_direction(50)\",\n    \"direction_relative_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが移動方向に50移動した後、0.5秒間待機します。その後、移動方向を90度だけ回転して0.5秒間待機した後、移動方向に50移動します。\",\n    \"rotate_by_time_desc\": \"オブジェクトの方向を時計方向にA度だけB秒に渡り回転します。(オブジェクトの中心点を基準に回転します。)\",\n    \"rotate_by_time_elements\": \"A-- 回転する角度%nextB-- 回転する時間(秒)\",\n    \"rotate_by_time_exampleCode\": \"def when_start():\\n    Entry.add_rotation_for_sec(90, 2)\\n    Entry.add_rotation_for_sec(-90, 2)\",\n    \"rotate_by_time_exampleDesc\": \"[スタート]ボタンをクリックするとオブジェクトが2秒間90度回転し、再び2秒間-90度回転します。\",\n    \"direction_relative_duration_desc\": \"オブジェクトの移動方向を時計方向にA度だけB秒に渡り回転します。(オブジェクトの中心点を基準に回転します。)\",\n    \"direction_relative_duration_elements\": \"A-- 回転する角度%nextB-- 回転する時間(秒)\",\n    \"direction_relative_duration_exampleCode\": \"def when_start():\\n    Entry.add_direction_for_sec(90, 2)\\n\\ndef when_start():\\n    while True:\\n        Entry.move_to_direction(1)\",\n    \"direction_relative_duration_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトの移動方向を2秒間90度回転させます。同時にオブジェクトは移動方向に1ずつ継続して移動します。\",\n    \"rotate_absolute_desc\": \"オブジェクトの方向をAにします。\",\n    \"rotate_absolute_elements\": \"A-- 設定する方向\",\n    \"rotate_absolute_exampleCode\": \"def when_press_key(\\\"right\\\"):\\n    Entry.set_rotation(90)\\n\\ndef when_press_key(\\\"left\\\"):\\n    Entry.set_rotation(270)\",\n    \"rotate_absolute_exampleDesc\": \"右方向キーを押すとオブジェクトの方向を90にし、左方向キーを押すとオブジェクトの方向を270にします。\",\n    \"direction_absolute_desc\": \"オブジェクトの移動方向をAにします。\",\n    \"direction_absolute_elements\": \"A-- 設定する移動方向\",\n    \"direction_absolute_exampleCode\": \"def when_press_key(\\\"right\\\"):\\n    Entry.set_direction(90)\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(\\\"left\\\"):\\n    Entry.set_direction(270)\\n    Entry.move_to_direction(10)\",\n    \"direction_absolute_exampleDesc\": \"右方向キーを押すとオブジェクトの移動方向を90にした後、その方向に10移動し、左方向キーを押すとオブジェクトの移動方向を270にしてその方向に10移動します。\",\n    \"see_angle_object_desc\": \"オブジェクトがAの方向を向きます。(移動方向がAを向くようにオブジェクトの方向を回転させます。)\",\n    \"see_angle_object_elements\": \"A-- 次の選択肢のうち一つ<br>① \\\"オブジェクト名\\\"<br>② \\\"mouse_pointer\\\"または\\\"マウスポインター\\\"\",\n    \"see_angle_object_exampleCode\": \"def when_click_mouse_on():\\n    Entry.look_at(\\\"mouse_pointer\\\")\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.look_at(\\\"オブジェクト\\\")\",\n    \"see_angle_object_exampleDesc\": \"マウスをクリックするとオブジェクトがマウスポインターの方向を向き、スペースキーを押すと\\\"オブジェクト\\\"の方向を向きます。\",\n    \"move_to_angle_desc\": \"オブジェクトがAだけB方向に動きます。\",\n    \"move_to_angle_elements\": \"A-- 移動する距離に該当する数%nextB-- 移動する方向(12時方向が0度、時計方向に増加)\",\n    \"move_to_angle_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.move_to_degree(10, 0)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.move_to_degree(10, 180)\",\n    \"move_to_angle_exampleDesc\": \"上方向キーを押すとオブジェクトが0度方向に10移動し、下方向キーを押すとオブジェクトが180度方向に10移動します。\",\n    \"show_desc\": \"オブジェクトを画面に表示します。\",\n    \"show_exampleCode\": \"def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()\",\n    \"show_exampleDesc\": \"[スタート]ボタンをクリックすると、1秒後にオブジェクト模様が非表示になり、次の1秒後にオブジェクト模様が表示されます。\",\n    \"hide_desc\": \"オブジェクトを画面で非表示にします。\",\n    \"hide_exampleCode\": \"def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()\",\n    \"hide_exampleDesc\": \"[スタート]ボタンをクリックすると、1秒後にオブジェクト模様が非表示になり、次の1秒後にオブジェクト模様が表示されます。\",\n    \"dialog_time_desc\": \"オブジェクトがAをB秒間吹き出しで話した後、次のコマンドが実行されます。コンソールウィンドウでも実行結果を確認できます。\",\n    \"dialog_time_elements\": \"A-- 話す内容<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など%nextB-- 話す時間(秒)\",\n    \"dialog_time_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(\\\"やあ! 僕は\\\", 2)\\n    Entry.print_for_sec(16, 2)\\n    Entry.print_for_sec(\\\"歳だよ\\\", 2)\",\n    \"dialog_time_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"やあ! 僕は\\\", 16, \\\"歳だよ\\\"をそれぞれ2秒間順番どおりに話します。\",\n    \"dialog_desc\": \"オブジェクトがAを吹き出しで話します。コンソールウィンドウでも実行結果を確認できます。\",\n    \"dialog_elements\": \"A-- 話す内容<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など\",\n    \"dialog_exampleCode\": \"def when_start():\\n    Entry.print(\\\"キーボードで数字の1、2を押したら数字を言ってみるね\\\")\\n\\ndef when_press_key(1):\\n    Entry.print(1)\\n\\ndef when_press_key(2):\\n    Entry.print(2)\\n\",\n    \"dialog_exampleDesc\": \"[スタート]ボタンをクリックすると\\\"キーボードで数字の1、2を押したら、数字を言ってみるね\\\"と話し、キーボードで1、2を押すとそれぞれ1、2と話します。\",\n    \"remove_dialog_desc\": \"オブジェクトが話している吹き出しを消します。\",\n    \"remove_dialog_exampleCode\": \"def when_start():\\n    Entry.print(\\\"吹き出しを消すにはエンターを押して!\\\")\\n\\ndef when_press_key(\\\"enter\\\"):\\n    Entry.clear_print()\",\n    \"remove_dialog_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"吹き出しを消すにはエンターを押して!\\\"と話し、エンターキーを押すと吹き出しが消えます。\",\n    \"change_to_some_shape_desc\": \"オブジェクトをA模様に変更します。\",\n    \"change_to_some_shape_elements\": \"A-- 次の選択肢のうち1つ<br>① 模様名 : [属性] タブの\\\"模様名\\\"を記載<br>② 模様番号 : [属性] タブの模様番号を記載\",\n    \"change_to_some_shape_exampleCode\": \"def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\\\"オブジェクト模様\\\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\\\"オブジェクト模様\\\")\",\n    \"change_to_some_shape_exampleDesc\": \"[スタート]ボタンをクリックすると、0.3秒間待機した後に\\\"オブジェクト模様\\\"に模様を変更し、0.3秒間待機した後に\\\"オブジェクト模様\\\"模様に模様を変更します。\",\n    \"change_to_next_shape_desc\": \"オブジェクトの模様を次または前の模様に変更します。\",\n    \"change_to_next_shape_elements\": \"A-- 次の選択肢のうち一つ<br>① 次の模様: \\\"next\\\"または\\\"次\\\" <br>② 前の模様: \\\"pre\\\"または\\\"前\\\"\",\n    \"change_to_next_shape_exampleCode\": \"def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\\\"next\\\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\\\"pre\\\")\",\n    \"change_to_next_shape_exampleDesc\": \"[スタート]ボタンをクリックすると、0.3秒間待機した後に次のオブジェクト模様に変更し、0.3秒間待機した後に前の模様にオブジェクト模様を変更します。\",\n    \"add_effect_amount_desc\": \"オブジェクトにA効果をBだけ加えます。\",\n    \"add_effect_amount_elements\": \"A -- 次の選択肢のうち一つ<br>① “color”または“色“                 <br>② “brightness”または“明度”                <br>③ “transparency”または“透明度”%nextB-- 効果の変化の程度\",\n    \"add_effect_amount_exampleCode\": \"def when_click_mouse_on():\\n    Entry.add_effect(\\\"color\\\", 50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\\\"brightness\\\", -50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\\\"transparency\\\", 50)\",\n    \"add_effect_amount_exampleDesc\": \"マウスをクリックすると、オブジェクトに色効果を50与えて1秒間待機し、明度効果を-50加えて1秒間待機します。その後、透明度効果を50加えます。\",\n    \"change_effect_amount_desc\": \"オブジェクトのA効果をBにします。\",\n    \"change_effect_amount_elements\": \"A-- 次の選択肢のうち一つ<br>① “color”または“色“                 <br>② “brightness”または“明度”                <br>③ “transparency”または“透明度”%nextB-- 効果の値<br>① color: 0~100範囲の数、100を周期として繰り返す<br>② brightness: -100~100間の範囲の数、-100以下は-100で、100以上は100で処理される<br>③ transparency: 0~100間の範囲の数、0以下は0に、100以上は100で処理される\",\n    \"change_effect_amount_exampleCode\": \"def when_click_mouse_on():\\n    Entry.set_effect(\\\"color\\\", 50)\\n    Entry.set_effect(\\\"brightness\\\", 50)\\n    Entry.set_effect(\\\"transparency\\\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.set_effect(\\\"color\\\", 0)\\n    Entry.set_effect(\\\"brightness\\\", 0)\\n    Entry.set_effect(\\\"transparency\\\", 0)\",\n    \"change_effect_amount_exampleDesc\": \"マウスをクリックすると、オブジェクトに色、明度、透明度効果を50にし、マウスクリックを解除するとそれぞれの効果を0にします。\",\n    \"erase_all_effects_desc\": \"オブジェクトに適用された効果をすべて削除します。\",\n    \"erase_all_effects_exampleCode\": \"def when_click_mouse_on():\\n    Entry.set_effect(\\\"color\\\", 50)\\n    Entry.set_effect(\\\"brightness\\\", 50)\\n    Entry.set_effect(\\\"transparency\\\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.clear_effect()\\n\",\n    \"erase_all_effects_exampleDesc\": \"マウスをクリックするとオブジェクトに色、明度、透明度効果を50にし、マウスクリックを解除するとオブジェクトに適用されたすべての効果を消します。\",\n    \"change_scale_size_desc\": \"オブジェクトのサイズをAだけ変更します。\",\n    \"change_scale_size_elements\": \"A-- サイズ変化値\",\n    \"change_scale_size_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.set_size(100)\",\n    \"change_scale_size_exampleDesc\": \"上方向キーを押すとオブジェクトのサイズが10大きくなり、下方向キーを押すとオブジェクトのサイズが10だけ小さくなります。スペースキーを押すとオブジェクトのサイズを100にします。\",\n    \"set_scale_size_desc\": \"オブジェクトのサイズをAにします。\",\n    \"set_scale_size_elements\": \"A-- サイズ値\",\n    \"set_scale_size_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.set_size(100)\",\n    \"set_scale_size_exampleDesc\": \"上方向キーを押すとオブジェクトのサイズが10だけ大きくなり、下方向キーを押すとオブジェクトのサイズが10だけ小さくなります。スペースキーを押すとオブジェクトのサイズを100にします。\",\n    \"flip_x_desc\": \"オブジェクトの上下の模様を入れ替えます。\",\n    \"flip_x_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\\\"right\\\"):\\n    Entry.flip_vertical()\",\n    \"flip_x_exampleDesc\": \"上方向キーを押すとオブジェクトの上下の模様を入れ替え、右方向キーを押すとオブジェクトの左右の模様を入れ替えます。\",\n    \"flip_y_desc\": \"オブジェクトの左右の模様を入れ替えます。\",\n    \"flip_y_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\\\"right\\\"):\\n    Entry.flip_vertical()\",\n    \"flip_y_exampleDesc\": \"上方向キーを押すとオブジェクトの上下の模様を入れ替え、右方向キーを押すとオブジェクトの左右の模様を入れ替えます。\",\n    \"change_object_index_desc\": \"オブジェクトのレイヤーをAに移動させます。\",\n    \"change_object_index_elements\": \"A-- 次の選択肢のうち一つ<br>① “front\\\"または“一番前“                 <br>② “forward”または“前”                <br>③ “backward”または“後ろ”<br>④ “back”または“一番後ろ”\",\n    \"change_object_index_exampleCode\": \"def when_start():\\n    Entry.send_layer_to(\\\"front\\\")\\n    Entry.wait_for_sec(2)\\n    Entry.send_layer_to(\\\"backward\\\")\",\n    \"change_object_index_exampleDesc\": \"オブジェクトが複数重なっている場合、[スタート]ボタンをクリックすると当該オブジェクトのレイヤーを一番前に移動させて表示します。\",\n    \"brush_stamp_desc\": \"オブジェクトの模様をスタンプのように実行画面上に押します。\",\n    \"brush_stamp_exampleCode\": \"def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()\",\n    \"brush_stamp_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが移動方向に10移動し、スタンプを押す行動を10回繰り返します。\",\n    \"start_drawing_desc\": \"オブジェクトが移動する経路に沿って線を引きます。(オブジェクトの中心点が基準)\",\n    \"start_drawing_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    for i in range(10):\\n        Entry.move_to_direction(10)\",\n    \"start_drawing_exampleDesc\": \"[スタート]ボタンをクリックすると描画がスタートし、オブジェクトが移動方向に10だけ10回移動するとき、オブジェクトの移動経路に沿って線が引かれます。\",\n    \"stop_drawing_desc\": \"オブジェクトが線を描くのを中断します。\",\n    \"stop_drawing_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n\\ndef when_click_mouse_on():\\n    Entry.stop_drawing()\",\n    \"stop_drawing_exampleDesc\": \"[スタート]ボタンをクリックすると描画が始まり、続けてオブジェクトが移動方向に10移動します。マウスをクリックすると、描画を中断します。\",\n    \"set_color_desc\": \"オブジェクトが描く線の色をAにします。\",\n    \"set_color_elements\": \"A-- 次の選択肢のうち一つ<br>① カラーコード: \\\"#FF0000\\\", \\\"#FFCC00\\\", \\\"#3333FF\\\", \\\"#000000\\\"など<br>② 色 : \\\"red\\\", \\\"orange\\\", \\\"yellow\\\", \\\"green\\\", \\\"blue\\\", \\\"navy\\\", \\\"purple\\\", \\\"black\\\", \\\"white\\\", \\\"brown\\\"\",\n    \"set_color_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_color_to(\\\"#000099\\\")\\n    while True:\\n        Entry.move_to_direction(1)\",\n    \"set_color_exampleDesc\": \"[スタート]ボタンをクリックすると描画がスタートし、線の色を\\\"#000099\\\"にします。オブジェクトは続けて移動方向に1だけ動き、オブジェクトの移動経路に沿って線が引かれます。\",\n    \"set_random_color_desc\": \"オブジェクトが描く線の色をランダムにします。\",\n    \"set_random_color_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n        Entry.set_brush_color_to_random()\",\n    \"set_random_color_exampleDesc\": \"[スタート]ボタンをクリックすると描画がスタートします。オブジェクトは続けて移動方向に1だけ動き、オブジェクトの移動経路に沿って線が引かれます。線の色は続けてランダムで決まります。\",\n    \"change_thickness_desc\": \"オブジェクトが描く線の太さをAだけ変更します。\",\n    \"change_thickness_elements\": \"A-- 太さ変化値\",\n    \"change_thickness_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.add_brush_size(1)\\n        Entry.move_to_direction(10)\",\n    \"change_thickness_exampleDesc\": \"[スタート]ボタンをクリックすると描画がスタートします。オブジェクトは続けて移動方向に10だけ動き、オブジェクトの移動経路に沿って線が引かれます。線の太さは続けて1ずつ大きくなります。\",\n    \"set_thickness_desc\": \"オブジェクトが描く線の太さをAにします。\",\n    \"set_thickness_elements\": \"A-- 太さ値(1以上の数)\",\n    \"set_thickness_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)\",\n    \"set_thickness_exampleDesc\": \"[スタート]ボタンをクリックすると描画がスタートし、線の太さを10にします。オブジェクトは続けて移動方向に10動き、オブジェクトの移動経路に沿って線が引かれます。\",\n    \"change_brush_transparency_desc\": \"オブジェクトが描く線の透明度をAだけ変更します。\",\n    \"change_brush_transparency_elements\": \"A-- 透明度変化値\",\n    \"change_brush_transparency_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.add_brush_transparency(5)\",\n    \"change_brush_transparency_exampleDesc\": \"[スタート]ボタンをクリックすると描画がスタートし、線の太さを10にします。オブジェクトは続けて移動方向に10動き、オブジェクトの移動経路に沿って線が引かれます。線の透明度は続けて5だけ変更します。\",\n    \"set_brush_tranparency_desc\": \"オブジェクトが描く線の透明度をAにします。\",\n    \"set_brush_tranparency_elements\": \"A-- 透明度値(0~100の範囲)\",\n    \"set_brush_tranparency_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    Entry.set_brush_transparency(50)\\n    while True:\\n        Entry.move_to_direction(10)\",\n    \"set_brush_tranparency_exampleDesc\": \"[スタート]ボタンをクリックすると描画がスタートし、線の太さを10に、線の透明度を50にします。オブジェクトは続けて移動方向に10だけ動き、オブジェクトの移動経路に沿って線が引かれます。\",\n    \"brush_erase_all_desc\": \"オブジェクトが描いた線とスタンプをすべて削除します。\",\n    \"brush_erase_all_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(10)\\n\\ndef when_click_mouse_on():\\n    Entry.clear_drawing()\",\n    \"brush_erase_all_exampleDesc\": \"[スタート]ボタンをクリックすると描画がスタートします。オブジェクトは続けて移動方向に10だけ動き、オブジェクトの移動経路に沿って線が引かれます。マウスをクリックするとオブジェクトが描いた線をすべて削除します。\",\n    \"text_read_desc\": \"글상자 A의 내용입니다.<br />(내용 안에 개행이 있는 경우, 띄어쓰기하여 반환됩니다.)\",\n    \"text_read_elements\": \"A-- 아래 선택지 중 하나<br />① \\\"오브젝트(글상자) 이름\\\" <br />② 자기 자신\",\n    \"text_read_exampleCode\": \"def when_start():\\n    Entry.print(Entry.contents_of_textbox(\\\"A\\\"))\",\n    \"text_read_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 글상자 \\\"A\\\"의 내용을 말합니다.​\",\n    \"text_write_desc\": \"テキストボックスの内容をAに書き換えます。\",\n    \"text_write_elements\": \"A-- テキストボックスの内容<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など\",\n    \"text_write_exampleCode\": \"def when_start():\\n    Entry.write_text(\\\"エントリー\\\")\",\n    \"text_write_exampleDesc\": \"[スタート]ボタンをクリックすると、テキストボックスの内容を\\\"エントリー\\\"に変更します。\",\n    \"text_append_desc\": \"テキストボックスの内容の後にAを追加します。\",\n    \"text_append_elements\": \"A-- テキストボックスの内容<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など\",\n    \"text_append_exampleCode\": \"def when_start():\\n    Entry.write_text(\\\"やあ!\\\")\\n    Entry.wait_for_sec(1)\\n    Entry.append_text(\\\"エントリー!\\\")\",\n    \"text_append_exampleDesc\": \"[スタート]ボタンをクリックすると、テキストボックスの内容の\\\"やあ!\\\"に1秒後に\\\"エントリー!\\\"が追加され、\\\"やあ!エントリー!\\\"になります。\",\n    \"text_prepend_desc\": \"テキストボックスの内容の前にAを追加します。\",\n    \"text_prepend_elements\": \"A-- テキストボックスの内容<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など\",\n    \"text_prepend_exampleCode\": \"def when_start():\\n    Entry.write_text(\\\"嬉しいな!\\\")\\n    Entry.wait_for_sec(1)\\n    Entry.prepend_text(\\\"エントリー!\\\")\",\n    \"text_prepend_exampleDesc\": \"[スタート]ボタンをクリックすると、テキストボックスの内容が\\\"嬉しいな!\\\"になってから、1秒後に\\\"エントリー!\\\"が前に追加され\\\"エントリー!嬉しいな!\\\"になります。\",\n    \"text_flush_desc\": \"テキストボックスに保存された値をすべて削除します。\",\n    \"text_flush_exampleCode\": \"def when_start():\\n    Entry.write_text(\\\"エントリー\\\")\\n    Entry.wait_for_sec(1)\\n    Entry.clear_text()\",\n    \"text_flush_exampleDesc\": \"[スタート]ボタンをクリックすると、テキストボックスの内容が\\\"エントリー\\\"になってから、1秒後にすべての内容が消えます。\",\n    \"sound_something_with_block_desc\": \"オブジェクトがAサウンドを再生します。\",\n    \"sound_something_with_block_elements\": \"A-- 次の選択肢のうち一つ<br>① サウンド名 : [属性] タブの\\\"サウンド名\\\"を記載<br>② サウンド番号: [属性] タブのサウンド番号を記載\",\n    \"sound_something_with_block_exampleCode\": \"def when_start():\\n    Entry.play_sound(\\\"サウンド\\\")\\n    Entry.add_size(50)\",\n    \"sound_something_with_block_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"サウンド\\\"を再生しながらオブジェクトのサイズが50大きくなります。\",\n    \"sound_something_second_with_block_desc\": \"オブジェクトがAサウンドをB秒間再生します。\",\n    \"sound_something_second_with_block_elements\": \"A-- 次の選択肢のうち一つ<br>① サウンド名 : [属性] タブの\\\"サウンド名\\\"を記載<br>② サウンド番号: [属性] タブのサウンド番号を記載\",\n    \"sound_something_second_with_block_exampleCode\": \"def when_start():\\n    Entry.play_sound_for_sec(\\\"サウンド\\\", 1)\\n    Entry.add_size(50)\",\n    \"sound_something_second_with_block_exampleDesc\": \"[スタート]ボタンをクリックすると\\\"サウンド\\\"を1秒間再生しながら、オブジェクトのサイズが50程度大きくなります。\",\n    \"sound_from_to_desc\": \"オブジェクトがAサウンドをB秒からC秒まで再生します。\",\n    \"sound_from_to_elements\": \"A-- 次の選択肢のうち1つ<br>① サウンド名 : [属性] タブの\\\"サウンド名\\\"を記載<br>② サウンド番号: [属性] タブのサウンド番号を記載\",\n    \"sound_from_to_exampleCode\": \"def when_start():\\n    Entry.play_sound_from_to(\\\"サウンド\\\", 0.5, 1)\\n    Entry.add_size(50)\",\n    \"sound_from_to_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"サウンド\\\"を0.5秒から1秒区間までのみ再生しながら、オブジェクトのサイズが50程度大きくなります。\",\n    \"sound_something_wait_with_block_desc\": \"オブジェクトがAサウンドを再生し、再生が終わると次のコマンドを実行します。\",\n    \"sound_something_wait_with_block_elements\": \"A-- 次の選択肢のうち1つ<br>① サウンド名 : [属性]タブの\\\"サウンド名\\\"を記載<br>② サウンド番号: [属性]タブのサウンド番号を記載\",\n    \"sound_something_wait_with_block_exampleCode\": \"def when_start():\\n    Entry.play_sound_and_wait(\\\"サウンド\\\")\\n    Entry.add_size(50)\",\n    \"sound_something_wait_with_block_exampleDesc\": \"[スタート]ボタンをクリックすると\\\"サウンド\\\"を再生し、再生が終わるとオブジェクトのサイズが50大きくなります。\",\n    \"sound_something_second_wait_with_block_desc\": \"オブジェクトがAサウンドをB秒再生し、再生が終わると次のコマンドを実行します。\",\n    \"sound_something_second_wait_with_block_elements\": \"A-- 次の選択肢のうち1つ<br>① サウンド名 : [属性]タブの\\\"サウンド名\\\"を記載<br>② サウンド番号: [属性]タブのサウンド番号を記載\",\n    \"sound_something_second_wait_with_block_exampleCode\": \"def when_start():\\n    Entry.play_sound_for_sec_and_wait(\\\"サウンド\\\", 1)\\n    Entry.add_size(50)\",\n    \"sound_something_second_wait_with_block_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"サウンド\\\"を1秒間再生し、再生が終わるとオブジェクトのサイズが50大きくなります。\",\n    \"sound_from_to_and_wait_desc\": \"オブジェクトがAサウンドをB秒からC秒まで再生し、再生が終わると次のコマンドを実行します。\",\n    \"sound_from_to_and_wait_elements\": \"A-- 次の選択肢のうち1つ<br>① サウンド名 : [属性]タブの\\\"サウンド名\\\"を記載<br>② サウンド番号: [属性]タブのサウンド番号を記載\",\n    \"sound_from_to_and_wait_exampleCode\": \"def when_start():\\n    Entry.play_sound_from_to_and_wait(\\\"サウンド\\\", 0.5, 1)\\n    Entry.add_size(50)\",\n    \"sound_from_to_and_wait_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"サウンド\\\"を0.5秒から1秒区間までのみ再生し、再生が終わるとオブジェクトのサイズが50大きくなります。\",\n    \"sound_volume_change_desc\": \"作品で再生されるすべての サウンドのボリュームをA％分変更します。\",\n    \"sound_volume_change_elements\": \"A-- ボリュームの大きさ変化値\",\n    \"sound_volume_change_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\\\"サウンド\\\")\",\n    \"sound_volume_change_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"サウンド\\\"を続けて再生します。上方向キーを押すとサウンドのサイズが10\\\"大きくなり、下方向キーを押すとサウンドのサイズが10\\\"小さくなります。\",\n    \"sound_volume_set_desc\": \"作品で再生されるすべての サウンドのボリュームをA％にします。\",\n    \"sound_volume_set_elements\": \"A-- ボリュームの大きさ値\",\n    \"sound_volume_set_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_press_key(\\\"enter\\\"):\\n    Entry.set_sound_volume(100)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\\\"サウンド\\\")\",\n    \"sound_volume_set_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"サウンド\\\"を続けて再生します。上方向キーを押すとサウンドのサイズが10\\\"大きくなり、下方向キーを押すとサウンドのサイズが10\\\"小さくなります。エンターキーを押すとサウンドのボリュームを100\\\"にします。\",\n    \"sound_silent_all_desc\": \"現在再生中のすべてのサウンドを止めます。\",\n    \"sound_silent_all_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\\\"サウンド\\\")\\n\\ndef when_press_key(\\\"enter\\\"):\\n    Entry.stop_sound()\",\n    \"sound_silent_all_exampleDesc\": \"[スタート]ボタンをクリックすると、\\\"サウンド\\\"を続けて再生します。エンターキーを押すと現在再生中のサウンドを止めます。\",\n    \"is_clicked_desc\": \"マウスをクリックした場合、Trueと判断します。\",\n    \"is_clicked_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_mouse_clicked():\\n            Entry.print_for_sec(\\\"嬉しいな!\\\", 0.5)\",\n    \"is_clicked_exampleDesc\": \"[スタート]ボタンをクリックすると、続けてマウスをクリックしたか確認します。もしマウスをクリックしたら、オブジェクトが\\\"嬉しいな!\\\"と0.5秒間話します。\",\n    \"is_press_some_key_desc\": \"A キーが押されている場合、Trueと判断します。\",\n    \"is_press_some_key_elements\": \"A-- 次の選択肢のうち一つ<br>① アルファベット : \\\"A\\\", \\\"B\\\" ~ \\\"Z\\\"など(小文字可能)<br>② 数字: 1, 2, 3, 4 ~ 9, 0<br>③ 特殊キー: \\\"space\\\", \\\"enter\\\"<br>④ 方向キー : \\\"up\\\", \\\"down\\\", \\\"right\\\", \\\"left\\\"\",\n    \"is_press_some_key_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\\\"space\\\"):\\n            Entry.move_to_direction(10)\",\n    \"is_press_some_key_exampleDesc\": \"[スタート]ボタンをクリックすると、続けて選択したキーを押したか確認します。もしスペースキーを押したらオブジェクトが移動方向に10移動します。\",\n    \"reach_something_desc\": \"オブジェクトがAに触れた場合、Trueと判断します。\",\n    \"reach_something_elements\": \"A-- 次の選択肢のうち1つ<br>① \\\"オブジェクト名\\\"<br>② \\\"mouse_pointer\\\"または\\\"マウスポインター\\\"<br>③ \\\"edge\\\", \\\"edge_up\\\", \\\"edge_down\\\", \\\"edge_right\\\", \\\"edge_left\\\"\",\n    \"reach_something_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_touched(\\\"edge\\\"):\\n            Entry.add_rotation(150)\",\n    \"reach_something_exampleDesc\": \"[スタート]ボタンをクリックすると、続けてオブジェクトが移動方向に10移動します。オブジェクトが壁に触れると150だけ回転します。\",\n    \"boolean_basic_operator_desc\": \"AとBを比較してTrueまたはFalseと判断します。\",\n    \"boolean_basic_operator_elements\": \"A, B-- 比較したい数字値<br>① == : AとBの値が同じならTrue、そうでなければFalse<br>② > : Aの値がBの値より大きいならtrue、そうでなければFalse<br>③ < : Aの値がBの値より小さいならtrue、そうでなければFalse<br>④ >= : Aの値がBの値より大きいか同じならtrue、そうでなければFalse<br>⑤ <= : Aの値がBの値より小さいか同じならtrue、そうでなければFalse\",\n    \"boolean_basic_operator_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.add_x(10)\\n        if Entry.value_of_object(\\\"オブジェクト\\\", \\\"x\\\") > 240:\\n            Entry.set_x(0)\",\n    \"boolean_basic_operator_exampleDesc\": \"[スタート]ボタンをクリックすると、続けてオブジェクトx座標を10変更します。もしオブジェクトx座標が240より大きければオブジェクトx座標を0にします。\",\n    \"boolean_and_desc\": \"AとBの判断がすべてTrueの場合はTrue、そうじゃない場合はFalseと判断します。\",\n    \"boolean_and_elements\": \"A, B-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10など<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\")など\",\n    \"boolean_and_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\\\"a\\\") and Entry.is_key_pressed(\\\"s\\\"):\\n            Entry.add_effect(\\\"color\\\", 10)\",\n    \"boolean_and_exampleDesc\": \"[スタート]ボタンをクリックしてキーボードの\\\"a\\\"と\\\"s\\\"キーを同時に押した時、色効果を10だけ加えます。\",\n    \"boolean_or_desc\": \"AとBの判断のうち1つでもTrueの場合はTrue, そうじゃない場合はFalseと判断します。\",\n    \"boolean_or_elements\": \"A, B-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10など<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\")など\",\n    \"boolean_or_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\\\"a\\\") or Entry.is_key_pressed(\\\"s\\\"):\\n            Entry.add_effect(\\\"color\\\", 10)\",\n    \"boolean_or_exampleDesc\": \"[スタート]ボタンをクリックすると、キーボードの\\\"a\\\"や\\\"s\\\"キーのうち何でも1つを押した時、オブジェクトに色効果を10加えます。\",\n    \"boolean_not_desc\": \"A 判断がTrueならFalse、FalseならTrueと判断します。\",\n    \"boolean_not_elements\": \"A-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10など<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\")など\",\n    \"boolean_not_exampleCode\": \"def when_start():\\n    while True:\\n        if not Entry.is_mouse_clicked():\\n            Entry.add_size(1)\",\n    \"boolean_not_exampleDesc\": \"[スタート]ボタンをクリックすると、マウスをクリックしない間サイズが1ずつ大きくなります。\",\n    \"calc_basic_desc\": \"AとBの演算値です。\",\n    \"calc_basic_elements\": \"A, B-- 演算したい数字値<br>① + : AとBを加えた値<br>② - : AとBを引いた値<br>③ x : AとBをかけた値<br>④ / : AとBを割った値\",\n    \"calc_basic_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(10 + 10, 2)\\n    Entry.print_for_sec(10 - 10, 2)\\n    Entry.print_for_sec(10 * 10, 2)\\n    Entry.print_for_sec(10 / 10, 2)\",\n    \"calc_basic_exampleDesc\": \"[スタート]ボタンをクリックすると、10と10を足した値、引いた値、かけた値、割った値をそれぞれ2秒間話します。\",\n    \"calc_rand_desc\": \"AとBの間で選択された乱数の値です。(2つの数をすべて整数を入力した場合整数が、2つの数のうち1つでも少数を入力した場合は少数が乱数として選択されます。)\",\n    \"calc_rand_elements\": \"A, B-- 乱数を抽出する範囲<br>① random.randint(A, B) : A, Bを整数で入力すると整数の範囲で乱数を抽出<br>② random.uniform(A, B) : A, Bを実数で入力すると実数範囲で乱数を抽出\",\n    \"calc_rand_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(random.randint(1, 10), 2)\\n    Entry.print_for_sec(random.uniform(0.1, 2), 2)\",\n    \"calc_rand_exampleDesc\": \"[スタート]ボタンをクリックすると、1から10の間の整数のうち乱数を選び2秒間話します。その後、0.1から2の間の実数のうち乱数を選び2秒間話します。\",\n    \"coordinate_mouse_desc\": \"マウスポインターのA座標値を表します。\",\n    \"coordinate_mouse_elements\": \"A-- 次の選択肢のうち一つ<br>① \\\"x\\\"または\\\"X\\\"<br>② \\\"y\\\"または\\\"Y\\\"\",\n    \"coordinate_mouse_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_mouse_pointer(\\\"x\\\"))\",\n    \"coordinate_mouse_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトがマウスポインターのx座標を続けて話します。\",\n    \"coordinate_object_desc\": \"Aに関するB情報値です。\",\n    \"coordinate_object_elements\": \"A-- 次の選択肢のうち1つ<br>① \\\"オブジェクト名\\\"<br>② \\\"self\\\"または\\\"自分\\\"%nextB-- 次の選択肢のうち一つ<br>① \\\"x\\\"または\\\"X\\\"<br>② \\\"y\\\"または\\\"Y\\\"<br>③ \\\"rotation\\\"または\\\"方向\\\"<br>④ \\\"direction\\\"または\\\"移動方向\\\"<br>⑤ \\\"size\\\" または\\\"サイズ\\\"<br>⑥ \\\"shape_number\\\"または\\\"模様番号\\\"<br>⑦ \\\"shape_name\\\"または\\\"模様名\\\"\",\n    \"coordinate_object_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.add_x(1)\\n        Entry.print(Entry.value_of_object(\\\"オブジェクト\\\", \\\"x\\\"))\\n\",\n    \"coordinate_object_exampleDesc\": \"[スタート]ボタンをクリックすると続けてオブジェクトのx座標が1ずつ増加し、\\\"オブジェクト\\\"のx座標を話します。\",\n    \"get_sound_volume_desc\": \"現在、作品に設定されているサウンドのサイズ値です。\",\n    \"get_sound_volume_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_sound_volume())\",\n    \"get_sound_volume_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトがサウンドのサイズ値を続けて話します。\",\n    \"quotient_and_mod_desc\": \"AとBの演算値です。\",\n    \"quotient_and_mod_elements\": \"A, B-- 演算したい数字値<br>① // : A / Bの商に該当する値<br>② % : A / Bのあまりに該当する値\",\n    \"quotient_and_mod_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(10 // 3, 2)\\n    Entry.print_for_sec(10 % 3, 2)\",\n    \"quotient_and_mod_exampleDesc\": \"[スタート]ボタンをクリックすると、10 / 3の商である3を2秒間話し、あまりである1を2秒間話します。\",\n    \"calc_operation_desc\": \"Aの演算値です。\",\n    \"calc_operation_elements\": \"A, B-- 演算したい数字値<br>① A ** 2 : Aを乗じた値<br>② math.sqrt(A): Aのルート値<br>③ math.sin(A): Aのサイン値<br>④ math.cos(A): Aのコサイン値<br>⑤ math.tan(A):  Aのタンジェント値 <br>⑥ math.asin(A): Aのアークサイン値<br>⑦ math.acos(A): Aのアークコサイン値<br>⑧ math.atan(): Aのアークタンジェント値<br>⑨ math.log10(A): Aのログ値<br>⑩ math.log(A): Aの自然ログ値<br>⑪ A - math.floor(A): Aの小数点部分<br>⑫ math.floor(A): Aの小数点以下切り捨て値<br>⑬ math.ceil(A): Aの小数点以下切り上げ値<br>⑭ math.round(A): Aの四捨五入値<br>⑮ math.factorial(A): Aの階乗値<br>⑯ math.fabs(A): Aの絶対値\",\n    \"calc_operation_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(10 ** 2, 2)\\n    Entry.print_for_sec(math.sqrt(9), 2)\\n    Entry.print_for_sec(math.sin(90), 2)\\n    Entry.print_for_sec(math.fabs(-10), 2)\",\n    \"calc_operation_exampleDesc\": \"[スタート]ボタンをクリックすると、10の乗, 9のルート値, 90のサイン値, -10の絶対値をそれぞれ2秒間話します。\",\n    \"get_project_timer_value_desc\": \"このコマンドが実行された瞬間、ストップウォッチに保存された値です。\",\n    \"get_project_timer_value_exampleCode\": \"def when_start():\\n    Entry.timer(\\\"start\\\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\\\"stop\\\")\\n    Entry.timer_view(\\\"hide\\\")\\n    Entry.print(Entry.value_of_timer())\",\n    \"get_project_timer_value_exampleDesc\": \"[スタート]ボタンをクリックするとストップウォッチを開始します。3秒後にストップウォッチを停止してストップウォッチウィンドウを隠します。その後、ストップウォッチ値を話します。\",\n    \"choose_project_timer_action_desc\": \"ストップウォッチの動作をAにします。<br>(このコマンドを使うと実行画面に「ストップウォッチウィンドウ」が作成されます。)\",\n    \"choose_project_timer_action_elements\": \"A-- 次の選択肢のうち一つ<br>① \\\"start\\\" : ストップウォッチを開始<br>② \\\"stop\\\" : ストップウォッチを停止<br>③ \\\"reset\\\" : ストップウォッチを初期化\",\n    \"choose_project_timer_action_exampleCode\": \"def when_start():\\n    Entry.timer(\\\"start\\\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\\\"stop\\\")\\n    Entry.timer_view(\\\"hide\\\")\\n    Entry.print(Entry.value_of_timer())\",\n    \"choose_project_timer_action_exampleDesc\": \"[スタート]ボタンをクリックすると、ストップウォッチを開始します。3秒後にストップウォッチを停止してストップウォッチウィンドウを隠します。その後、ストップウォッチ値を話します。\",\n    \"set_visible_project_timer_desc\": \"実行画面のストップウォッチウィンドウをAに設定します。\",\n    \"set_visible_project_timer_elements\": \"A-- 次の選択肢のうち一つ<br>① \\\"hide\\\" : ストップウォッチウィンドウを非表示<br>② \\\"show\\\" : ストップウォッチウィンドウを表示\",\n    \"set_visible_project_timer_exampleCode\": \"def when_start():\\n    Entry.timer(\\\"start\\\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\\\"stop\\\")\\n    Entry.timer_view(\\\"hide\\\")\\n    Entry.print(Entry.value_of_timer())\",\n    \"set_visible_project_timer_exampleDesc\": \"[スタート]ボタンをクリックすると、ストップウォッチを開始します。3秒後にストップウォッチを停止してストップウォッチウィンドウを隠します。その後、ストップウォッチ値を話します。\",\n    \"get_date_desc\": \"現在のAに関する値です。\",\n    \"get_date_elements\": \"A-- 次の選択肢のうち1つ<br>① \\\"year\\\" : 現在の年度値<br>② \\\"month\\\" : 現在の月値<br>③ \\\"day\\\" : 現在の日値<br>④ \\\"hour\\\" : 現在の時間値<br>⑤ \\\"minute\\\" : 現在の分値<br>⑥ \\\"second\\\" : 現在の秒値\",\n    \"get_date_exampleCode\": \"def when_start():\\n    Entry.print(Entry.value_of_current_time(\\\"year\\\") + \\\"年\\\" + Entry.value_of_current_time(\\\"month\\\") + \\\"月\\\")\",\n    \"get_date_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが現在の年度と月を話します。\",\n    \"distance_something_desc\": \"自分とAまでの距離値です。\",\n    \"distance_something_elements\": \"A-- 次の選択肢のうち一つ<br>① \\\"オブジェクト名\\\"<br>② \\\"mouse_pointer\\\"または\\\"マウスポインター\\\"\",\n    \"distance_something_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_distance_to(\\\"mouse_pointer\\\"))\",\n    \"distance_something_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトがマウスポインターとの距離を続けて話します。\",\n    \"get_sound_duration_desc\": \"サウンドAの長さ(秒)値です。\",\n    \"get_sound_duration_elements\": \"A-- \\\"サウンド名\\\"\",\n    \"get_sound_duration_exampleCode\": \"def when_start():\\n    Entry.print(Entry.value_of_sound_length_of(\\\"サウンド\\\"))\",\n    \"get_sound_duration_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"サウンド\\\"の長さを話します。\",\n    \"get_user_name_desc\": \"作品を実行しているユーザーのIDの値です。\",\n    \"get_user_name_exampleCode\": \"def when_start():\\n    Entry.print(Entry.value_of_username())\",\n    \"get_user_name_exampleDesc\": \"[スタート]ボタンをクリックすると、作品を実行しているユーザーのID値を話します。\",\n    \"get_nickname_desc\": \"作品をプレーしているユーザーのニックネーム値です。\",\n    \"get_nickname_exampleCode\": \"def when_start():\\n    Entry.print(Entry.value_of_nickname())\",\n    \"get_nickname_exampleDesc\": \"[スタート]ボタンをクリックすると、作品をプレーしているユーザーのニックネーム値を話します。\",\n    \"length_of_string_desc\": \"入力した文字値のスペースを含む文字数です。\",\n    \"length_of_string_elements\": \"A-- \\\"文字列\\\"\",\n    \"length_of_string_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(len(\\\"やあ\\\"), 2)\\n    Entry.print_for_sec(len(\\\"エントリー\\\"), 2)\",\n    \"length_of_string_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"やあ\\\"と\\\"エントリー\\\"の文字数をそれぞれ2秒間話します。\",\n    \"combine_something_desc\": \"A 文字列とB 文字列を結合した値です。(A、Bのうち1つが数字なら文字列に変えて処理され、2つとも数字なら加法演算で処理されます。)\",\n    \"combine_something_elements\": \"A, B-- \\\"文字列\\\"\",\n    \"combine_something_exampleCode\": \"def when_start():\\n    Entry.print(\\\"やあ! \\\" + \\\"エントリー\\\")\",\n    \"combine_something_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"やあ!\\\"と\\\"エントリー\\\"が結合した\\\"やあ! エントリー\\\"を話します。\",\n    \"char_at_desc\": \"A 文字列のB番目の文字値です。(最初の文字の位置は0から始まります。)\",\n    \"char_at_elements\": \"A-- \\\"文字列\\\"%nextB-- 検索したい文字列の位置\",\n    \"char_at_exampleCode\": \"def when_start():\\n    Entry.print(\\\"やあ、エントリー!\\\"[0])\",\n    \"char_at_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"やあ、エントリー!\\\"の0番目の文字である\\\"や\\\"を話します。\",\n    \"substring_desc\": \"A 文字列の B位置から C-1位置までの値です。(最初の文字の位置は0から始まります。)\",\n    \"substring_elements\": \"A-- \\\"文字列\\\"%nextB-- 含まれる文字列の開始位置<br>最初の文字は0から開始%nextC-- 文字列を含まない位置\",\n    \"substring_exampleCode\": \"def when_start():\\n    Entry.print(\\\"やあ、エントリー!\\\"[1:5])\",\n    \"substring_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"やあ、エントリー!\\\"の1から4番目の文字である\\\"あ、エント\\\"を話します。\",\n    \"index_of_string_desc\": \"A文字列でB文字列が最初に登場する位置の値です。(最初の文字の位置は0から始まります。)\",\n    \"index_of_string_elements\": \"A, B-- \\\"文字列\\\"\",\n    \"index_of_string_exampleCode\": \"def when_start():\\n    Entry.print(\\\"やあ、エントリー!\\\".find(\\\"エントリー\\\"))\",\n    \"index_of_string_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"やあ、エントリー!\\\"で \\\"エントリー\\\"が最初に登場する位置の3を話します。\",\n    \"replace_string_desc\": \"A文字列からB文字列をすべて探し、C文字列に置き換えた値です。<br>(アルファベット入力時、大文字と小文字を区別します。)\",\n    \"replace_string_elements\": \"A, B, C-- \\\"文字列\\\"\",\n    \"replace_string_exampleCode\": \"def when_start():\\n    Entry.print(\\\"やあ、エントリー!\\\".replace( \\\"やあ\\\", \\\"嬉しいな\\\"))\",\n    \"replace_string_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"やあ、エントリー!\\\"で\\\"やあ\\\"を\\\"嬉しいな\\\"に置き換えた\\\"嬉しいな、エントリー!\\\"を話します。\",\n    \"change_string_case_desc\": \"Aのすべてのアルファベットを大文字または小文字に置き換えた文字値です。\",\n    \"change_string_case_elements\": \"A-- \\\"文字列\\\"<br>① A.upper(): Aのすべてのアルファベットを大文字に置き換えた値<br>② A.lower() : Aのすべてのアルファベットを小文字に置き換えた値\",\n    \"change_string_case_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(\\\"Hello Entry!\\\".upper(), 2)\\n    Entry.print_for_sec(\\\"Hello Entry!\\\".lower(), 2)\",\n    \"change_string_case_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"Hello Entry!\\\"をすべて大文字に置き換えた\\\"HELLO ENTRY!\\\"を2秒間話した後、すべて小文字に置き換えた\\\"hello entry!\\\"を2秒間話します。\",\n    \"ask_and_wait_desc\": \"オブジェクトがAの内容を吹き出しで尋ね、回答の入力を受けます。回答は実行画面またはコンソールウィンドウで入力でき、入力された値は'Entry.answer()'に保存されます。<br>(このコマンドを使うと実行画面に「回答ウィンドウ」が作成されます。)\",\n    \"ask_and_wait_elements\": \"A-- \\\"文字列\\\"\",\n    \"ask_and_wait_exampleCode\": \"def when_start():\\n    Entry.input(\\\"名前を入力してみてください。\\\")\\n    Entry.print(Entry.answer() + \\\" 嬉しいな!\\\")\",\n    \"ask_and_wait_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"名前を入力してみてください。\\\"と吹き出しで尋ねます。名前を入力すると\\\"(入力した名前) 嬉しいな!\\\"と話します。\",\n    \"get_canvas_input_value_desc\": \"Entry.input(A) コマンドにより実行画面またはコンソールで入力された値です。\",\n    \"get_canvas_input_value_exampleCode\": \"def when_start():\\n    Entry.input(\\\"名前を入力してみてください。\\\")\\n    Entry.print(Entry.answer() + \\\" 嬉しいな!\\\")\",\n    \"get_canvas_input_value_exampleDesc\": \"[スタート]ボタンをクリックすると、オブジェクトが\\\"名前を入力してみてください。\\\"と吹き出しで尋ねます。名前を入力すると\\\"(入力した名前)嬉しいな!\\\"と話します。\",\n    \"set_visible_answer_desc\": \"実行画面の回答ウィンドウをAに設定します。\",\n    \"set_visible_answer_elements\": \"A-- 次の選択肢のうち1つ<br>① \\\"hide\\\" : 回答ウィンドウを非表示<br>② \\\"show\\\" : 回答ウィンドウを表示\",\n    \"set_visible_answer_exampleCode\": \"def when_start():\\n    Entry.answer_view(\\\"hide\\\")\\n    Entry.input(\\\"年齢を入力してください。\\\")\\n    Entry.print(Entry.answer())\",\n    \"set_visible_answer_exampleDesc\": \"[スタート]ボタンをクリックすると回答ウィンドウが非表示になり、オブジェクトが\\\"年齢を入力してください。\\\"と吹き出しで尋ねます。年齢を入力するとオブジェクトが入力した年齢を話します。\",\n    \"get_variable_desc\": \"A 変数に保存された値です。\",\n    \"get_variable_elements\": \"A-- 変数名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A\",\n    \"get_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.print(age)\",\n    \"get_variable_exampleDesc\": \"ageという変数を作成してその値を16にします。[スタート]ボタンをクリックすると、オブジェクトがage変数に入っている値である\\\"16\\\"を話します。\",\n    \"change_variable_desc\": \"A変数にBだけ足します。\",\n    \"change_variable_elements\": \"A-- 変数名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A%nextB-- 数字値\",\n    \"change_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.print_for_sec(age, 2)\\n    age += 2\\n    Entry.print_for_sec(age, 2)\",\n    \"change_variable_exampleDesc\": \"ageという変数を作成してその値を16にします。[スタート]ボタンをクリックすると、オブジェクトがage変数に入っている値である\\\"16\\\"を2秒間話します。その後、age変数に2を足し、足した値である\\\"18\\\"を2秒間話します。\",\n    \"set_variable_desc\": \"A変数の値をBにします。もしA変数がない場合、[属性]タブにA変数が自動作成されます。\",\n    \"set_variable_elements\": \"A-- 変数名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A%nextB-- 変数に入れる値<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など\",\n    \"set_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.print(age)\",\n    \"set_variable_exampleDesc\": \"ageという変数を作成してその値を16にします。[スタート]ボタンをクリックすると、オブジェクトがage変数に入っている値である\\\"16\\\"を話します。\",\n    \"show_variable_desc\": \"A 変数ウィンドウを実行画面に表示させます。\",\n    \"show_variable_elements\": \"A-- \\\"変数名\\\"<br>① すべてのオブジェクトで使用: \\\"A\\\"<br>② このオブジェクトで使用: \\\"self.A\\\"\",\n    \"show_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\\\"age\\\")\\n    Entry.wait_for_sec(2)\\n    age = 20\\n    Entry.show_variable(\\\"age\\\")\",\n    \"show_variable_exampleDesc\": \"ageという変数を作成してその値を16にします。[スタート]ボタンをクリックすると、age変数ウィンドウを実行画面で非表示にします。2秒後に変数値を17に変更し、age変数ウィンドウを実行画面に表示させます。\",\n    \"hide_variable_desc\": \"A 変数ウィンドウを実行画面で非表示にします。\",\n    \"hide_variable_elements\": \"A-- \\\"変数名\\\"<br>① すべてのオブジェクトで使用: \\\"A\\\"<br>② このオブジェクトで使用: \\\"self.A\\\"\",\n    \"hide_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\\\"age\\\")\\n    Entry.print_for_sec(age, 2)\",\n    \"hide_variable_exampleDesc\": \"ageという変数を作成してその値を16にします。[スタート]ボタンをクリックするとage変数ウィンドウを実行画面で非表示にし、オブジェクトがage変数に入っている値である\\\"16\\\"を2秒間話します。\",\n    \"value_of_index_from_list_desc\": \"A リストでB位置の項目値を表します。<br>(最初の項目の位置は0から始まります。)\",\n    \"value_of_index_from_list_elements\": \"A-- リスト名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A%nextB-- リスト項目の位置\",\n    \"value_of_index_from_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    Entry.print(basket[1])\\n\",\n    \"value_of_index_from_list_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、オブジェクトがbasketリストの1番目の項目であるorangeを話します。\",\n    \"add_value_to_list_desc\": \"A リストの最後の項目にB値が追加されます。\",\n    \"add_value_to_list_elements\": \"A-- リスト名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A%nextB-- リストに入れる項目値<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など\",\n    \"add_value_to_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    basket.append(\\\"juice\\\")\\n    Entry.print(basket[4])\",\n    \"add_value_to_list_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、\\\"juice\\\"をbasketの最後の項目に追加します。オブジェクトはbasketの4番目の項目である\\\"juice\\\"を話します。\",\n    \"remove_value_from_list_desc\": \"A リストのB位置にある項目を削除します。<br>(最初の項目の位置は0から始まります。)\",\n    \"remove_value_from_list_elements\": \"A-- リスト名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A%nextB-- リスト項目の位置値\",\n    \"remove_value_from_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\ndef when_start():\\n    basket.pop(0)\\n    Entry.print(basket[0])\",\n    \"remove_value_from_list_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、basketの0番目の項目であるappleを削除します。オブジェクトは新しくbasketの0番目の項目になった\\\"orange\\\"を話します。\",\n    \"insert_value_to_list_desc\": \"A リストのB位置にC項目を挿入します。<br>(最初の項目の位置は0から始まります。B位置より後にある各項目の順番は1つずつずれます。)\",\n    \"insert_value_to_list_elements\": \"A-- リスト名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A%nextB-- リスト項目の位置%nextC-- リストに入れる項目値<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など\",\n    \"insert_value_to_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    basket.insert(1, \\\"juice\\\")\\n    Entry.print(basket[2])\",\n    \"insert_value_to_list_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、basketの最初の位置に項目 \\\"juice\\\"を入れます。オブジェクトは新しくbasketの2番目の項目になった\\\"orange\\\"を話します。\",\n    \"change_value_list_index_desc\": \"AリストでB位置にある項目の値をC値に変更します。<br>(最初の項目の位置は0から始まります。)\",\n    \"change_value_list_index_elements\": \"A-- リスト名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A%nextB-- リスト項目の位置%nextC-- リストに入れる項目値<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など\",\n    \"change_value_list_index_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    basket[0] = \\\"juice\\\"\\n    Entry.print(basket[0])\",\n    \"change_value_list_index_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、basketの0番目の位置の項目 \\\"apple\\\"を\\\"juice\\\"に変更します。オブジェクトは変更されたbasketの0番目の項目 \\\"juice\\\"を話します。\",\n    \"length_of_list_desc\": \"A リストが保有した項目の個数値です。\",\n    \"length_of_list_elements\": \"A-- リスト名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A\",\n    \"length_of_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    Entry.print(len(basket))\",\n    \"length_of_list_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、オブジェクトは basketの項目個数である4を話します。\",\n    \"is_included_in_list_desc\": \"A値を持つ項目がBリストに含まれているか確認します。\",\n    \"is_included_in_list_elements\": \"A-- リストの項目値<br>① 文字: \\\"やあ!\\\", \\\"エントリー\\\"など<br>② 数字: 0, 10, 35など%nextB-- リスト名<br>① すべてのオブジェクトで使用: A<br>② このオブジェクトで使用: self.A\",\n    \"is_included_in_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    if \\\"apple\\\" in basket:\\n        Entry.print(\\\"リンゴがあるよ!\\\")\",\n    \"is_included_in_list_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、basket リストに\\\"apple\\\"項目があるかを確認します。\\\"apple\\\"項目があるため、オブジェクトは\\\"リンゴがあるよ!\\\"と話します。\",\n    \"show_list_desc\": \"選択したリストウィンドウを実行画面に表示させます。\",\n    \"show_list_elements\": \"A-- \\\"リスト名\\\"<br>① すべてのオブジェクトで使用: \\\"A\\\"<br>② このオブジェクトで使用: \\\"self.A\\\"\",\n    \"show_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    Entry.hide_list(\\\"basket\\\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\\\"basket\\\")\",\n    \"show_list_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、basket リストを2秒間非表示にした後で表示します。\",\n    \"hide_list_desc\": \"選択したリストウィンドウを実行画面で非表示にします。\",\n    \"hide_list_elements\": \"A-- \\\"リスト名\\\"<br>① すべてのオブジェクトで使用: \\\"A\\\"<br>② このオブジェクトで使用: \\\"self.A\\\"\",\n    \"hide_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    Entry.hide_list(\\\"basket\\\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\\\"basket\\\")\",\n    \"hide_list_exampleDesc\": \"basketというリストを作成して4つの項目を挿入します。[スタート]ボタンをクリックすると、basketリストを2秒間非表示にした後で表示します。\",\n    \"boolean_and_or_desc\": \"AとBの判断値を確認してTrueまたはFalseと判断します。\",\n    \"boolean_and_or_elements\": \"A, B-- TrueまたはFalseと判断できるコマンド入力(判断カテゴリーのコマンド)<br>① and : AとBの判断がすべてTrueの場合はTrue、そうじゃない場合はFalse<br>② or : AとBの判断のうち1つでもTrueの場合True、そうじゃない場合はFalse\",\n    \"boolean_and_or_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\\\"a\\\") and Entry.is_key_pressed(\\\"s\\\"):\\n            Entry.add_effect(\\\"color\\\", 10)\",\n    \"boolean_and_or_exampleDesc\": \"[スタート]ボタンをクリックし、キーボードの\\\"a\\\"と\\\"s\\\"キーを同時に押した時に色効果を10加えます。\",\n    \"check_weather_desc\": \"B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.\",\n    \"check_weather_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"sunny\\\" : 맑음<br>②    \\\"partly cloudy\\\" : 구름조금<br>③    \\\"mostly cloudy\\\" : 구름많음<br>④    \\\"cloudy\\\" : 흐림<br>⑤    \\\"rainy\\\" : 비<br>⑥    \\\"sleet\\\" : 진눈깨비<br>⑦    \\\"snowy\\\" : 눈%nextB-- 아래 선택지 중 하나<br>①    \\\"yesterday\\\" : 어제<br>②    \\\"today\\\" : 오늘<br>③    \\\"tomorrow\\\" : 내일<br>④    \\\"After 2 days\\\" : 모레<br>⑤    \\\"After 3 days\\\" : 3일 후<br>⑥    \\\"After 4 days\\\" : 4일 후<br>⑦    \\\"After 5 days\\\" : 5일 후<br>⑧    \\\"After 6 days\\\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"check_weather_exampleCode\": \"def when_start():\\n    if Weather.is_condition_sunny(\\\"today\\\", \\\"Seoul\\\"):\\n        Entry.print(\\\"오늘 서울의 날씨는 맑습니다.\\\")\",\n    \"check_weather_exampleDesc\": \"[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \\\"오늘 서울의 날씨는 맑습니다.\\\"라고 말합니다.​\",\n    \"check_finedust_desc\": \"선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.\",\n    \"check_finedust_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"good\\\" : 좋음<br>②    \\\"normal\\\" : 보통<br>③    \\\"bad\\\" : 나쁨<br>④    \\\"very bad\\\" : 매우나쁨%nextB-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"check_finedust_exampleCode\": \"def when_start():\\n    if Weather.is_current_finedust_grade_good(\\\"Seoul\\\"):\\n        Entry.print(\\\"현재 서울의 미세먼지 등급은 좋음입니다.\\\")\",\n    \"check_finedust_exampleDesc\": \"[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​\",\n    \"get_weather_data_desc\": \"선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.\",\n    \"get_weather_data_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"the lowest temperature\\\" : 최저기온<br>②    \\\"the highest temperature\\\" : 최고기온<br>③    \\\"humidity\\\" : 습도<br>④    \\\"precipitation\\\" : 강수량<br>⑤    \\\"precipitation probability\\\" : 강수확률<br>⑥    \\\"wind speed\\\" : 풍속%nextB-- 아래 선택지 중 하나<br>①    \\\"yesterday\\\" : 어제<br>②    \\\"today\\\" : 오늘<br>③    \\\"tomorrow\\\" : 내일<br>④    \\\"After 2 days\\\" : 모레<br>⑤    \\\"After 3 days\\\" : 3일 후<br>⑥    \\\"After 4 days\\\" : 4일 후<br>⑦    \\\"After 5 days\\\" : 5일 후<br>⑧    \\\"After 6 days\\\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"get_weather_data_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\\\"today\\\", \\\"Seoul\\\"))\",\n    \"get_weather_data_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​\",\n    \"get_current_weather_data_desc\": \"현재 B지역의 A 날씨 정보값을 의미합니다.\",\n    \"get_current_weather_data_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북%nextB-- 아래 선택지 중 하나<br>①    \\\"temperature\\\" : 기온<br>②    \\\"concentration of fine dust\\\" : 미세먼지농도\",\n    \"get_current_weather_data_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_current_temperature(\\\"Seoul\\\"))\",\n    \"get_current_weather_data_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.\",\n    \"get_today_temperature_desc\": \"오늘 A지역의 B 시간대 기온 정보값을 의미합니다.\",\n    \"get_today_temperature_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북%nextB-- 아래 선택지 중 하나<br>①    \\\"00\\\" : 당일 00시 측정된 기온값<br>②    \\\"03\\\" : 당일 03시 측정된 기온값<br>③    \\\"06\\\" : 당일 06시 측정된 기온값<br>④    \\\"09\\\" : 당일 09시 측정된 기온값<br>⑤    \\\"12\\\" : 당일 12시 측정된 기온값<br>⑥    \\\"15\\\" : 당일 15시 측정된 기온값<br>⑦    \\\"18\\\" : 당일 18시 측정된 기온값<br>⑧    \\\"21\\\" : 당일 21시 측정된 기온값\",\n    \"get_today_temperature_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_today_temperature(\\\"Seoul\\\", 00))\",\n    \"get_today_temperature_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​\",\n    \"check_city_weather_desc\": \"B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.\",\n    \"check_city_weather_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"sunny\\\" : 맑음<br>②    \\\"partly cloudy\\\" : 구름조금<br>③    \\\"mostly cloudy\\\" : 구름많음<br>④    \\\"cloudy\\\" : 흐림<br>⑤    \\\"rainy\\\" : 비<br>⑥    \\\"sleet\\\" : 진눈깨비<br>⑦    \\\"snowy\\\" : 눈%nextB-- 아래 선택지 중 하나<br>①    \\\"yesterday\\\" : 어제<br>②    \\\"today\\\" : 오늘<br>③    \\\"tomorrow\\\" : 내일<br>④    \\\"After 2 days\\\" : 모레<br>⑤    \\\"After 3 days\\\" : 3일 후<br>⑥    \\\"After 4 days\\\" : 4일 후<br>⑦    \\\"After 5 days\\\" : 5일 후<br>⑧    \\\"After 6 days\\\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"check_city_weather_exampleCode\": \"def when_start():\\n    if Weather.is_condition_sunny(\\\"today\\\", \\\"Seoul\\\"):\\n        Entry.print(\\\"오늘 서울의 날씨는 맑습니다.\\\")\",\n    \"check_city_weather_exampleDesc\": \"[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \\\"오늘 서울의 날씨는 맑습니다.\\\"라고 말합니다.​\",\n    \"check_city_finedust_desc\": \"선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.\",\n    \"check_city_finedust_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"good\\\" : 좋음<br>②    \\\"normal\\\" : 보통<br>③    \\\"bad\\\" : 나쁨<br>④    \\\"very bad\\\" : 매우나쁨%nextB-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"check_city_finedust_exampleCode\": \"def when_start():\\n    if Weather.is_current_finedust_grade_good(\\\"Seoul\\\"):\\n        Entry.print(\\\"현재 서울의 미세먼지 등급은 좋음입니다.\\\")\",\n    \"check_city_finedust_exampleDesc\": \"[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​\",\n    \"get_city_weather_data_desc\": \"선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.\",\n    \"get_city_weather_data_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"the lowest temperature\\\" : 최저기온<br>②    \\\"the highest temperature\\\" : 최고기온<br>③    \\\"humidity\\\" : 습도<br>④    \\\"precipitation\\\" : 강수량<br>⑤    \\\"precipitation probability\\\" : 강수확률<br>⑥    \\\"wind speed\\\" : 풍속%nextB-- 아래 선택지 중 하나<br>①    \\\"yesterday\\\" : 어제<br>②    \\\"today\\\" : 오늘<br>③    \\\"tomorrow\\\" : 내일<br>④    \\\"After 2 days\\\" : 모레<br>⑤    \\\"After 3 days\\\" : 3일 후<br>⑥    \\\"After 4 days\\\" : 4일 후<br>⑦    \\\"After 5 days\\\" : 5일 후<br>⑧    \\\"After 6 days\\\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"get_city_weather_data_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\\\"today\\\", \\\"Seoul\\\"))\",\n    \"get_city_weather_data_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​\",\n    \"get_current_city_weather_data_desc\": \"현재 B지역의 A 날씨 정보값을 의미합니다.\",\n    \"get_current_city_weather_data_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북%nextB-- 아래 선택지 중 하나<br>①    \\\"temperature\\\" : 기온<br>②    \\\"concentration of fine dust\\\" : 미세먼지농도\",\n    \"get_current_city_weather_data_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_current_temperature(\\\"Seoul\\\"))\",\n    \"get_current_city_weather_data_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.\",\n    \"get_today_city_temperature_desc\": \"오늘 A지역의 B 시간대 기온 정보값을 의미합니다.\",\n    \"get_today_city_temperature_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북%nextB-- 아래 선택지 중 하나<br>①    \\\"00\\\" : 당일 00시 측정된 기온값<br>②    \\\"03\\\" : 당일 03시 측정된 기온값<br>③    \\\"06\\\" : 당일 06시 측정된 기온값<br>④    \\\"09\\\" : 당일 09시 측정된 기온값<br>⑤    \\\"12\\\" : 당일 12시 측정된 기온값<br>⑥    \\\"15\\\" : 당일 15시 측정된 기온값<br>⑦    \\\"18\\\" : 당일 18시 측정된 기온값<br>⑧    \\\"21\\\" : 당일 21시 측정된 기온값\",\n    \"get_today_city_temperature_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_today_city_temperature(\\\"Seoul\\\", 00))\",\n    \"get_today_city_temperature_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​\"\n};\nLang.Painter = {\n    \"select_cut\": \"点線の四角形に沿って切り取ることができます。\",\n    \"thickness_of_eraser\": \"消しゴムの太さ\",\n    \"font\": \"フォント\",\n    \"font_color\": \"文字の色\",\n    \"outline_color\": \"輪郭線の色\",\n    \"outline_thickness\": \"枠線の太さ\",\n    \"fill_color\": \"塗りつぶしの色\",\n    \"inversion\": \"反転\",\n    \"font_size\": \"サイズ\",\n    \"font_family\": \"スタイル\",\n    \"fullscreen\": \"全画面\",\n    \"exit_fullscreen\": \"全画面を終了\",\n    \"picture_import\": \"模様インポート\",\n    \"edit_way\": \"編集方法\",\n    \"line\": \"直線\",\n    \"vertex\": \"頂点\",\n    \"bitmap\": \"ビットマップ\",\n    \"vector\": \"ベクター\",\n    \"forward\": \"前に\",\n    \"backward\": \"後ろに\",\n    \"front\": \"一番前に\",\n    \"back\": \"一番後ろに\",\n    \"group\": \"ｸﾞﾙｰﾌﾟ\",\n    \"ungroup\": \"ｸﾞﾙｰﾌﾟ 解除\",\n    \"copy_picture\": \"コピー\",\n    \"delete_picture\": \"削除\",\n    \"cut_picture\": \"切り取り\",\n    \"paste_picture\": \"貼り付け\",\n    \"remove_all\": \"全て削除\",\n    \"new_picture\": \"新しい図\",\n    \"edit\": \"編集\",\n    \"picture_size\": \"サイズ\",\n    \"picture_rotation\": \"回転\",\n    \"thickness\": \"太さ\",\n    \"font_fill\": \"背景色\",\n    \"painter_file_save\": \"保存する\",\n    \"painter_file_saveas\": \"新しい模様で保存\",\n    \"file\": \"ファイル\",\n    \"Pencil\": \"ペン\",\n    \"Line\": \"直線\",\n    \"Path\": \"形を変える\",\n    \"Pan\": \"移動\",\n    \"Select\": \"選択\",\n    \"Rectangle\": \"四角形\",\n    \"Ellipse\": \"円\",\n    \"Text\": \"テキストボックス\",\n    \"Fill\": \"塗りつぶし\",\n    \"Eraser\": \"クリア\",\n    \"get_file\": \"インポート\",\n    \"copy_file\": \"コピーする\"\n};\nLang.DataAnalytics = {\n    \"data_analysis\": \"データ分析\",\n    \"create_table\": \"テーブル作成\",\n    \"data\": \"データ\",\n    \"add_table\": \"テーブルを追加する\",\n    \"show_chart\": \"チャート表示\",\n    \"legend\": \"凡例\",\n    \"dashboard\": \"要約\",\n    \"table\": \"テーブル\",\n    \"chart\": \"チャート\",\n    \"attribute\": \"列\",\n    \"row\": \"行\",\n    \"average\": \"平均\",\n    \"standard_deviation\": \"標準偏差\",\n    \"maximum\": \"最大値\",\n    \"minimum\": \"最小値\",\n    \"median\": \"中間値\",\n    \"average_explain\": \"当該する列のすべての値を加えた後、列の個数分で割った値\",\n    \"standard_deviation_explain\": \"データが平均を中心に、どれくらい広がっているか確認できる値。\\n0に近いほど値が平均付近に集中しているという意味\",\n    \"maximum_minimum_explain\": \"当該する列の最大値と最小値\",\n    \"median_explain\": \"当該する列のすべての値を大きい順に並べ替えた場合、全体の中央に位置する値\",\n    \"add_row_above\": \"上に行を追加する\",\n    \"add_row_below\": \"下に行を追加する\",\n    \"delete_row\": \"行を削除する\",\n    \"add_property_left\": \"左に列を追加する\",\n    \"add_property_right\": \"右に列を追加する\",\n    \"delete_attribute\": \"列を削除する\",\n    \"data_alert\": \"数字ではない値が含まれた列は、個数のみ確認できます。\",\n    \"save\": \"保存する\",\n    \"cancel\": \"キャンセル\",\n    \"confirm\": \"確認\",\n    \"attribute_count\": \"件\",\n    \"row_count\": \"件\",\n    \"cell_count\": \"件\",\n    \"count\": \"件\",\n    \"add_chart_alert\": \"追加されたチャートがありません。\\nチャートを作成してください。\",\n    \"enter_attribute_name\": \"列の名前を入力してください。(10文字以内)\",\n    \"placeholder_attribute_name\": \"列の名前\",\n    \"new_attribute\": \"新しい列\",\n    \"chart_title\": \"チャートのタイトル\",\n    \"remove_chart\": \"チャートを削除する\",\n    \"add_chart_first\": \"チャートを先に作成してください。\",\n    \"bar\": \"棒グラフ\",\n    \"line\": \"線グラフ\",\n    \"pie\": \"円グラフ\",\n    \"scatter\": \"散布図\",\n    \"select_x_axis\": \"横軸にするものを選択してください。\",\n    \"x_axis\": \"横軸\",\n    \"y_axis\": \"縦軸\",\n    \"select_y_axis\": \"縦軸にするものを選択してください。\",\n    \"select_y_axis_or_legend\": \"縦軸、または判例を選択してください。\",\n    \"select_legend\": \"判例を選択してください。\",\n    \"cell\": \"間\",\n    \"unable_to_express_chart\": \"チャートで表現ができません。\",\n    \"edit_attribute_name\": \"名前を変更する\",\n    \"duplicate_attribute_name_title\": \"列の名前変更に失敗しました。\",\n    \"duplicate_attribute_name_content\": \"同じ名前の列がすでにあります。\",\n    \"fail_save_table\": \"テーブルの保存に失敗しました。\",\n    \"duplicate_table_name_content\": \"同じ名前のテーブルがすでにあります。\",\n    \"saved_table_title\": \"保存しました。\",\n    \"saved_table_content\": \"テーブルとチャートの情報を保存しました。\",\n    \"empty_table_name_content\": \"テーブルの名前で空白で設定できません。\",\n    \"do_not_delete_row\": \"行の削除ができません。\",\n    \"rows_cannot_less_one\": \"テーブルには一個以上の行が必須です。\"\n};\nLang.SharePolicy = {\n    \"title\": \"Entry Project/Post share Guide\"\n};\n\nLang.Support = [\"ko\", \"en\", \"vn\", \"jp\"];\nif (typeof exports == \"object\")\n    exports.Lang = Lang;\n"
  },
  {
    "path": "extern/lang/ko.js",
    "content": "var Lang = {};\nLang.category = {\n    name: 'ko',\n};\nLang.type = 'ko';\nLang.fallbackType = 'ko';\nLang.ko = '한국어';\nLang.en = 'English';\nLang.jp = '日本語';\nLang.vn = 'tiếng Việt';\nLang.Command = {\n    1: '장면 추가하기',\n    2: '장면 삭제하기',\n    3: '장면 이름 수정',\n    4: '장면 순서 변경',\n    5: '장면 선택',\n    101: '블록 쓰레드 추가하기',\n    102: '블록 쓰레드 삭제하기',\n    103: '블록 삭제하기',\n    104: '블록 복구하기',\n    105: '블록 끼워넣기',\n    106: '블록 분리하기',\n    107: '블록 이동하기',\n    108: '블록 복제하기',\n    109: '블록 복제 취소하기',\n    110: '스크롤',\n    111: '블록 필드값 수정',\n    117: '블록 쓰레드 추가하기',\n    118: '블록 끼워넣기',\n    119: '블록 이동하기',\n    120: '블록 분리하기',\n    121: '블록 이동하기',\n    122: '블록 끼워넣기',\n    123: '블록 끼워넣기',\n    201: '오브젝트 선택하기',\n    202: '오브젝트 수정 버튼 클릭',\n    203: '오브젝트 그림 추가',\n    204: '오브젝트 그림 삭제',\n    205: '오브젝트 소리 추가',\n    206: '오브젝트 소리 삭제',\n    207: '오브젝트 이름 수정',\n    208: '오브젝트 추가',\n    209: '오브젝트 삭제',\n    210: '오브젝트 추가 버튼 클릭',\n    211: '오브젝트 x 수정',\n    212: '오브젝트 y 수정',\n    213: '오브젝트 size 수정',\n    214: '오브젝트 방향 수정',\n    215: '오브젝트 이동 방향 수정',\n    216: '오브젝트 회전방식 수정',\n    217: '엔터티 모델 동기화',\n    301: 'do',\n    302: 'undo',\n    303: 'redo',\n    401: '그림 수정하기',\n    402: '그림 수정 취소하기',\n    403: '그림 수정하기',\n    404: '그림 수정 취소하기',\n    405: '글상자 수정',\n    501: '시작하기',\n    502: '정지하기',\n    601: '컨테이너 오브젝트 선택하기',\n    701: '모드 바꾸기',\n    702: '모양 추가 버튼 클릭',\n    703: '소리 추가 버튼 클릭',\n    801: '속성 필터 선택하기',\n    802: '변수 추가하기 버튼 클릭',\n    803: '변수 추가하기',\n    804: '변수 삭제하기',\n    805: '변수 이름 설정',\n    806: '신호 이름 설정',\n    807: '신호 추가',\n    808: '신호 삭제',\n    809: '변수 스코프 정하기',\n    810: '변수 글로벌 체크',\n    811: '변수 보이기 체크',\n    812: '변수 기본값 설정',\n    813: '변수 슬라이드로 체크',\n    814: '변수 최솟값 정하기',\n    815: '변수 최댓값 정하기',\n    816: '리스트 추가 버튼 클릭',\n    817: '리스트 추가',\n    818: '리스트 삭제',\n    819: '리스트 이름 정하기',\n    820: '리스트 스코프 정하기',\n    821: '리스트 글로벌 체크',\n    822: '리스트 보이기 체크',\n    823: '리스트 길이 변경',\n    824: '리스트 기본값 설정',\n    825: '메세지 수정 enable',\n    826: '변수 수정 enable',\n    827: '리스트 수정 enable',\n    828: '변수 이름 정하기',\n    829: '리스트 이름 정하기',\n    900: '모달 닫기',\n    1001: '함수 생성 시작',\n    1002: '함수 수정 시작',\n    1003: '함수 수정 취소',\n    1004: '함수 생성',\n    1005: '함수 업데이트',\n};\nLang.CommandTooltip = {\n    101: '블록 쓰레드 추가하기',\n    102: '블록 쓰레드 삭제하기',\n    103: '블록 삭제하기',\n    104: '블록 복구하기',\n    105: '코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    106: '블록 분리하기',\n    107: '블록 이동하기',\n    108: '블록 복제하기',\n    109: '블록 복제 취소하기',\n    110: '스크롤',\n    111: '블록 필드값 수정@@값을 입력하기 위해 이곳을 클릭합니다.$$선택지를 클릭합니다.$$선택지를 클릭합니다.$$&value&을 입력합니다.$$&value&를 선택합니다.$$키보드 &value&를 누릅니다.',\n    117: '블록 쓰레드 추가하기',\n    118: '블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    119: '블록 가져오기@@빈 곳에 블록을 끌어다 놓습니다.',\n    120: '블록 분리하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.',\n    121: '블록 이동하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.',\n    122: '블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    123: '코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.',\n    201: '오브젝트 선택하기',\n    301: 'do',\n    302: 'undo',\n    303: 'redo',\n    401: '그림 수정하기',\n    402: '그림 수정 취소하기',\n    403: '그림 수정하기',\n    404: '그림 수정 취소하기',\n    501: '실행하기@@<b>[시작하기]</b>를 누릅니다.',\n    502: '정지하기@@<b>[정지하기]</b>를 누릅니다.',\n    601: '컨테이너 오브젝트 선택하기',\n    701: '모드 바꾸기',\n    702: '모양 추가하기@@<b>모양추가</b>를 클릭합니다.',\n    703: '소리 추가하기@@<b>소리추가</b>를 클릭합니다.',\n    801: '변수 속성창 필터 선택하기',\n    802: '변수 추가하기@@<b>[변수 추가]</b>를 클릭합니다.',\n    803: '변수 추가하기@@<b>[확인]</b>을 클릭합니다.',\n    804: '변수 삭제하기@@이 버튼을 눌러 변수를 삭제합니다.',\n    805: '변수 이름 설정',\n    1101: '확장 블록 추가하기@@<b>확장 블록 블러오기</b>를 클릭합니다.',\n};\nLang.Blocks = {\n    download_guide: '• 연결 안내 다운로드',\n    dictionary: '사전',\n    ai_utilize: '인공지능',\n    date_yesterday: '어제',\n    date_today: '오늘',\n    date_tomorrow: '내일',\n    date_after_2_days: '모레',\n    date_after_3_days: '3일 후',\n    date_after_4_days: '4일 후',\n    date_after_5_days: '5일 후',\n    date_after_6_days: '6일 후',\n    EXPANSION_WEATHER_sunny: '맑음',\n    EXPANSION_WEATHER_partly_cloudy: '구름조금',\n    EXPANSION_WEATHER_mostly_cloudy: '구름많음',\n    EXPANSION_WEATHER_cloudy: '흐림',\n    EXPANSION_WEATHER_rainy: '비',\n    EXPANSION_WEATHER_sleet: '진눈깨비',\n    EXPANSION_WEATHER_snowy: '눈',\n    EXPANSION_WEATHER_finedust_good: '좋음',\n    EXPANSION_WEATHER_finedust_normal: '보통',\n    EXPANSION_WEATHER_finedust_bad: '나쁨',\n    EXPANSION_WEATHER_finedust_very_bad: '매우나쁨',\n    EXPANSION_WEATHER_lowest_temperature: '최저기온(℃)',\n    EXPANSION_WEATHER_highest_temperature: '최고기온(℃)',\n    EXPANSION_WEATHER_humidity: '습도(%)',\n    EXPANSION_WEATHER_precipitation: '강수량(mm)',\n    EXPANSION_WEATHER_precipitation_probability: '강수확률(%)',\n    EXPANSION_WEATHER_wind_speed: '풍속(m/s)',\n    EXPANSION_WEATHER_temperature: '기온(℃)',\n    EXPANSION_WEATHER_finedust: '미세먼지농도(㎍)',\n    EXPANSION_FESTIVAL_title: '제목',\n    EXPANSION_FESTIVAL_area: '지역',\n    EXPANSION_FESTIVAL_start_date: '시작일',\n    EXPANSION_FESTIVAL_end_date: '종료일',\n    EXPANSION_FESTIVAL_address: '주소',\n    EXPANSION_FESTIVAL_coordinate: '위치',\n    EXPANSION_FESTIVAL_overview: '개요',\n    EXPANSION_FESTIVAL_homepage: '홈페이지',\n    learn_type_image: '이미지',\n    learn_type_sound: '사운드',\n    learn_type_text: '글자',\n    learn_popup_title: '데이터 입력',\n    learn_no_result: '인식된 결과가 없습니다.',\n    no_data: '정보없음',\n    no_sentence: '문장이 없습니다',\n    sentence_over_20_charactor: '20자까지만 입력할 수 있습니다.',\n    sentence_over_3000_charactor: '3000자까지만 입력할 수 있습니다.',\n    sentence_over_2500_charactor: '2500자까지만 입력할 수 있습니다. ',\n    unknown_sentence: '알 수 없는 문장입니다.',\n    auto: '자동',\n    korean: '한국어',\n    english: '영어',\n    spanish: '스페인어',\n    french: '프랑스어',\n    german: '독일어',\n    russian: '러시아어',\n    korean_s: '한국어',\n    english_s: '영어',\n    japan_s: '일본어',\n    portuguese: '포르투갈어',\n    hindi: '힌디어',\n    japan: '일본어',\n    thai: '태국어',\n    vietnamese: '베트남',\n    indonesian: '인도네시아어',\n    chinese_simplified: '중국어간체',\n    chinese_traditional: '중국어번체',\n    italian: '이탈리아어',\n    behaviorConduct01001: '태풍',\n    behaviorConduct01002: '홍수',\n    behaviorConduct01003: '호우',\n    behaviorConduct01004: '강풍',\n    behaviorConduct01005: '대설',\n    behaviorConduct01006: '한파',\n    behaviorConduct01007: '풍랑',\n    behaviorConduct01008: '황사',\n    behaviorConduct01009: '폭염',\n    behaviorConduct01010: '가뭄',\n    behaviorConduct01011: '지진',\n    behaviorConduct01013: '해일',\n    behaviorConduct01014: '산사태',\n    behaviorConduct03002: '응급처치',\n    behaviorConduct03003: '심폐소생술',\n    behaviorConduct03004: '소화기사용법',\n    behaviorConduct03016: '소화전사용법',\n    behaviorConduct03005: '식중독',\n    behaviorConduct03006: '산행안전',\n    behaviorConduct03008: '실종유괴',\n    behaviorConduct03009: '성폭력',\n    behaviorConduct03010: '학교 폭력',\n    behaviorConduct03011: '가정 폭력',\n    behaviorConduct03012: '억류 및 납치',\n    behaviorConduct03013: '교통사고',\n    behaviorConduct03014: '승강기 안전사고',\n    behaviorConduct03015: '미세먼지',\n    behaviorConduct01001001: '태풍이 오기 전',\n    behaviorConduct01001002: '태풍이 왔을 때',\n    behaviorConduct01001003: '태풍이 지나간 후',\n    behaviorConduct01002002: '홍수가 오기 전',\n    behaviorConduct01002003: '홍수가 났을 때',\n    behaviorConduct01002004: '홍수가 지나간 후',\n    behaviorConduct01003002: '큰 비가 오기 전',\n    behaviorConduct01003003: '큰 비가 내릴 때',\n    behaviorConduct01003004: '큰 비가 그친 후',\n    behaviorConduct01004001: '강풍이 오기 전',\n    behaviorConduct01004002: '강풍 발생 시',\n    behaviorConduct01005002: '대설이 오기 전',\n    behaviorConduct01005003: '대설 내릴 때',\n    behaviorConduct01005004: '눈이 그친 후',\n    behaviorConduct01006001: '한파가 오기 전',\n    behaviorConduct01006002: '한파 왔을 때',\n    behaviorConduct01007001: '풍랑이 험할 때',\n    behaviorConduct01007002: '풍랑이 오기 전',\n    behaviorConduct01008001: '황사가 오기 전',\n    behaviorConduct01008002: '황사가 왔을 때',\n    behaviorConduct01008003: '황사가 지나간 후',\n    behaviorConduct01009001: '폭염이 오기 전',\n    behaviorConduct01009002: '폭염이 왔을 때',\n    behaviorConduct01010001: '가뭄이 왔을 때',\n    behaviorConduct01011009: '지진이 오기 전',\n    behaviorConduct01011010: '지진이 왔을 때',\n    behaviorConduct01011012: '지진 대피 후',\n    behaviorConduct01013002: '해일이 오기 전',\n    behaviorConduct01013003: '해일이 왔을 때',\n    behaviorConduct01014001: '산사태가 오기 전',\n    behaviorConduct03002002: '화상 처치',\n    behaviorConduct03002003: '고열 예방',\n    behaviorConduct03002004: '뱀에 물렸을 때 처치',\n    behaviorConduct03002005: '벌에 쏘였을 때 처치',\n    behaviorConduct03002006: '과호흡증후군 응급처치',\n    behaviorConduct03003001: '성인 심폐소생술',\n    behaviorConduct03003002: '영유아 심폐소생술',\n    behaviorConduct03003003: '자동제세동기 사용',\n    behaviorConduct03004001: '분말소화기 사용',\n    behaviorConduct03016001: '옥내소화전 사용',\n    behaviorConduct03005001: '식중독 대처',\n    behaviorConduct03006004: '산행 중 유의사항',\n    behaviorConduct03006005: '산에서 안전한 캠핑',\n    behaviorConduct03006002: '구조요청시 알리는',\n    behaviorConduct03006003: '산행사고시 응급조치',\n    behaviorConduct03008001: '실종유괴 예방',\n    behaviorConduct03009001: '성폭력 예방',\n    behaviorConduct03010001: '학교 폭력 예방',\n    behaviorConduct03011001: '가정 폭력 예방',\n    behaviorConduct03012001: '억류 및 납치 시 대처',\n    behaviorConduct03013002: '교통사고 발생 시 대처',\n    behaviorConduct03013005: '차량에서의 구조',\n    behaviorConduct03014001: '승강기 안전 이용',\n    behaviorConduct03014003: '승강기 고장시 대처',\n    behaviorConduct03014004: '에스컬레이터 안전 이용',\n    behaviorConduct03015007: '미세먼지 많은 날 생활',\n    behaviorConduct03015003: '부문별 생활',\n    emergencyActionGuidelines01001: '태풍',\n    emergencyActionGuidelines01001001: '태풍 예보 시',\n    emergencyActionGuidelines01001002: '태풍 특보 시',\n    emergencyActionGuidelines01001003: '태풍 이후',\n    emergencyActionGuidelines01002: '홍수',\n    emergencyActionGuidelines01002001: '홍수 예·경보 시',\n    emergencyActionGuidelines01002002: '홍수 우려 때',\n    emergencyActionGuidelines01002003: '물이 밀려들 때',\n    emergencyActionGuidelines01002004: '물이 빠진 후에',\n    emergencyActionGuidelines01003: '호우',\n    emergencyActionGuidelines01003001: '호우 대비',\n    emergencyActionGuidelines01003002: '호우 예보 시',\n    emergencyActionGuidelines01003003: '호우 특보 중',\n    emergencyActionGuidelines01003004: '호우 이후',\n    emergencyActionGuidelines01004: '강풍',\n    emergencyActionGuidelines01004001: '강풍 대비',\n    emergencyActionGuidelines01004002: '강풍 발생 시',\n    emergencyActionGuidelines01004003: '강풍 관련',\n    emergencyActionGuidelines01005: '대설',\n    emergencyActionGuidelines01005001: '대설 대비',\n    emergencyActionGuidelines01005002: '대설 예보 시',\n    emergencyActionGuidelines01005003: '대설 특보 시',\n    emergencyActionGuidelines01005004: '대설 이후',\n    emergencyActionGuidelines01006: '한파',\n    emergencyActionGuidelines01006001: '한파 대비',\n    emergencyActionGuidelines01006002: '한파 발생 시',\n    emergencyActionGuidelines01007: '풍랑',\n    emergencyActionGuidelines01007001: '풍랑 특보 시',\n    emergencyActionGuidelines01008: '황사',\n    emergencyActionGuidelines01008001: '황사 대비',\n    emergencyActionGuidelines01008002: '황사 발생 시',\n    emergencyActionGuidelines01008003: '황사 이후',\n    emergencyActionGuidelines01008003: '황사 관련',\n    emergencyActionGuidelines01009: '폭염',\n    emergencyActionGuidelines01009001: '폭염 대비',\n    emergencyActionGuidelines01009002: '폭염 발생 시',\n    emergencyActionGuidelines01009003: '폭염 관련',\n    emergencyActionGuidelines01010: '가뭄',\n    emergencyActionGuidelines01010001: '가뭄 시 생활',\n    emergencyActionGuidelines01010002: '가뭄 시 농촌',\n    emergencyActionGuidelines01011: '지진',\n    emergencyActionGuidelines01011007: '지진 발생 시 상황별',\n    emergencyActionGuidelines01011008: '지진 발생 시 장소별',\n    emergencyActionGuidelines01011009: '지진 대비',\n    emergencyActionGuidelines01011010: '지진 발생 시',\n    emergencyActionGuidelines01011011: '지진 장소별',\n    emergencyActionGuidelines01011012: '지진 대피 후',\n    emergencyActionGuidelines01012: '지진해일',\n    emergencyActionGuidelines01012005: '발생 시 (선박 위)',\n    emergencyActionGuidelines01012006: '발생 시 (지상 대피)',\n    emergencyActionGuidelines01013: '해일',\n    emergencyActionGuidelines01013001: '해일 대비',\n    emergencyActionGuidelines01013002: '해일 때',\n    emergencyActionGuidelines01013003: '해일 발생 때',\n    emergencyActionGuidelines01013004: '미쳐 대피 못한 때',\n    emergencyActionGuidelines01013005: '폭풍해일',\n    emergencyActionGuidelines01014: '산사태',\n    emergencyActionGuidelines01014001: '산사태 취약 지역 (주의보)',\n    emergencyActionGuidelines01014002: '산사태 취약 지역 (경보)',\n    emergencyActionGuidelines01014003: '일반 지역 (주의보)',\n    emergencyActionGuidelines01014004: '일반 지역 (경보)',\n    emergencyActionGuidelines01015: '화산폭발',\n    emergencyActionGuidelines01015001: '화산재 낙하 대비',\n    emergencyActionGuidelines01015002: '화산재 낙하 시',\n    emergencyActionGuidelines01015003: '화산재 제거 이유',\n    emergencyActionGuidelines02001: '해양오염',\n    emergencyActionGuidelines02001001: '발생 전',\n    emergencyActionGuidelines02001002: '발생 시',\n    emergencyActionGuidelines02001003: '조치 완료 후',\n    emergencyActionGuidelines02002: '대규모 수질오염',\n    emergencyActionGuidelines02002001: '사고 시',\n    emergencyActionGuidelines02002002: '구별 방법',\n    emergencyActionGuidelines02003: '식용수',\n    emergencyActionGuidelines02003001: '급수중단 발령 시',\n    emergencyActionGuidelines02003002: 'Ⅰ급상황 발생 시',\n    emergencyActionGuidelines02003003: 'Ⅱ급상황 발생 시',\n    emergencyActionGuidelines02004: '공동구 재난',\n    emergencyActionGuidelines02004001: '발생 우려 시',\n    emergencyActionGuidelines02004002: '발생 시',\n    emergencyActionGuidelines02005: '가축질병',\n    emergencyActionGuidelines02005001: '구제역 발생 시',\n    emergencyActionGuidelines02005002: '조류인플루엔자(AI) 발생 시',\n    emergencyActionGuidelines02005003: '발생 방지 대책',\n    emergencyActionGuidelines02005004: '발생 의심 시',\n    emergencyActionGuidelines02005005: '발생 확인 시',\n    emergencyActionGuidelines02006: '감염병',\n    emergencyActionGuidelines02006001: '예방 대책',\n    emergencyActionGuidelines02006002: '증상이 나타날 때',\n    emergencyActionGuidelines02006003: '중동호흡기증후군(MERS)',\n    emergencyActionGuidelines02007: '철도·지하철',\n    emergencyActionGuidelines02007001: '지하철 화재 발생 시',\n    emergencyActionGuidelines02007002: '고속철도 화재 발생 시',\n    emergencyActionGuidelines02007003: '사고 및 테러(독가스) 발생 시',\n    emergencyActionGuidelines02008: '금융전산',\n    emergencyActionGuidelines02008001: '보이스피싱 피해금 지급 정지',\n    emergencyActionGuidelines02008002: '보이스피싱 피해 예방',\n    emergencyActionGuidelines02009: '원전사고',\n    emergencyActionGuidelines02009001: '국민보호조치 발표 시',\n    emergencyActionGuidelines02009002: '방사능구름 통과 시',\n    emergencyActionGuidelines02009003: '옥내 대피 및 소개 시',\n    emergencyActionGuidelines02010: '화학물질',\n    emergencyActionGuidelines02010001: '화학물질 유출 시',\n    emergencyActionGuidelines02010002: '니트로글리세린 누출 시',\n    emergencyActionGuidelines02010003: '트리니트로톨루엔 누출 시',\n    emergencyActionGuidelines02010004: '화학유해물질(독성가스) 누출 시',\n    emergencyActionGuidelines02011: '화재',\n    emergencyActionGuidelines02011001: '일반',\n    emergencyActionGuidelines02011002: '예방 대책',\n    emergencyActionGuidelines02011003: '화재 발생 후',\n    emergencyActionGuidelines02011004: '화재 시',\n    emergencyActionGuidelines02011005: '화재 시 긴급 대피',\n    emergencyActionGuidelines02011006: '화재 시 피해 복구',\n    emergencyActionGuidelines02011007: '가정에서의 안전',\n    emergencyActionGuidelines02011008: '연기 관련 정보',\n    emergencyActionGuidelines02011009: '아파트 화재 시',\n    emergencyActionGuidelines02011010: '아파트 화재 대비',\n    emergencyActionGuidelines02011011: '도로 터널 화재',\n    emergencyActionGuidelines02011012: '대형 화재',\n    emergencyActionGuidelines02011013: '고층 건물 화재',\n    emergencyActionGuidelines02011014: '지하상가 화재 안전수칙',\n    emergencyActionGuidelines02011015: '지하철 화재 발생 시',\n    emergencyActionGuidelines02012: '산불',\n    emergencyActionGuidelines02012001: '주택가 산불 확산 시',\n    emergencyActionGuidelines02012002: '산불 방지',\n    emergencyActionGuidelines02012003: '봄철 산불 관련',\n    emergencyActionGuidelines02012004: '산불 예방',\n    emergencyActionGuidelines02012005: '산불 발생 후',\n    emergencyActionGuidelines02012006: '산불 대피',\n    emergencyActionGuidelines02012007: '산불 피해 지역 가축 관리',\n    emergencyActionGuidelines02013: '건축물 붕괴',\n    emergencyActionGuidelines02013001: '사고 발생 시',\n    emergencyActionGuidelines02013002: '징조를 느낄 때',\n    emergencyActionGuidelines02013003: '건물 내부에 있을 때',\n    emergencyActionGuidelines02013004: '건물 외부에 있을 때',\n    emergencyActionGuidelines02013005: '붕괴, 매몰된 경우',\n    emergencyActionGuidelines02013007: '도로 공사장 붕괴',\n    emergencyActionGuidelines02013008: '상수도 공사장 붕괴',\n    emergencyActionGuidelines02013009: '아파트 공사장 붕괴',\n    emergencyActionGuidelines02013010: '지하철 공사장 붕괴',\n    emergencyActionGuidelines02014: '댐 붕괴',\n    emergencyActionGuidelines02014001: '붕괴 우려 시',\n    emergencyActionGuidelines02014002: '붕괴 발생 시',\n    emergencyActionGuidelines02014003: '물이 빠진 후',\n    emergencyActionGuidelines02015: '폭발',\n    emergencyActionGuidelines02015001: '가스 폭발 시',\n    emergencyActionGuidelines02015004: '폭발 현장',\n    emergencyActionGuidelines02016: '항공기',\n    emergencyActionGuidelines02016001: '항공기 사고 예방',\n    emergencyActionGuidelines02017: '화생방',\n    emergencyActionGuidelines02017001: '사고 발생 시',\n    emergencyActionGuidelines02018: '정전 및 전력부족',\n    emergencyActionGuidelines02018001: '정전 시',\n    emergencyActionGuidelines02018002: '정전 발생 시',\n    emergencyActionGuidelines02018003: '정전 상황별',\n    emergencyActionGuidelines02019: '전기·가스',\n    emergencyActionGuidelines02019001: '전기사고 예방',\n    emergencyActionGuidelines02019002: '침수지역 감전 사고 예방',\n    emergencyActionGuidelines02019003: '대피 명령 시 전기설비 조치',\n    emergencyActionGuidelines02019004: '정전 발생 시 조치',\n    emergencyActionGuidelines02019005: '야외 주의 사항',\n    emergencyActionGuidelines02019006: '가스사고 예방',\n    emergencyActionGuidelines02019007: '가스사고 발생 시',\n    emergencyActionGuidelines02019008: 'LPG 응급조치',\n    emergencyActionGuidelines02019009: '도시가스(LNG) 응급조치',\n    emergencyActionGuidelines02019010: '이동식 부탄가스 안전점검',\n    emergencyActionGuidelines02019011: '가스 사용 시 안전점검',\n    emergencyActionGuidelines02019012: '가스 누출 발생 시 대피',\n    emergencyActionGuidelines02019013: '배관 등에서 대량 누출 시',\n    emergencyActionGuidelines02019014: '기타 사항',\n    emergencyActionGuidelines02019015: '암모니아가스 인체 접촉 시',\n    emergencyActionGuidelines02019016: '염소가스 누출 시',\n    emergencyActionGuidelines02020: '유도선',\n    emergencyActionGuidelines02020001: '이용객 금지 행위',\n    emergencyActionGuidelines02020002: '사고 발생 시',\n    emergencyActionGuidelines02021: '수난사고',\n    emergencyActionGuidelines02021001: '하천이나 계곡물',\n    emergencyActionGuidelines02021002: '무릎 이상의 깊은 급류',\n    emergencyActionGuidelines02021003: '물에 빠졌을 때',\n    emergencyActionGuidelines02021004: '파도가 높아져 위험할 때',\n    emergencyActionGuidelines02021005: '수초에 감겼을 때',\n    emergencyActionGuidelines02021006: '의식 없는 사고자를 구했을 때',\n    emergencyActionGuidelines02021007: '고립 지역',\n    emergencyActionGuidelines02021008: '계곡에서 야영지를 선택 시',\n    emergencyActionGuidelines02021009: '보트 전복 등에 따른 대처',\n    emergencyActionGuidelines02021010: '갯바위 등 바다낚시 사고 예방',\n    emergencyActionGuidelines02021011: '갯벌 해루질 사고 예방',\n    emergencyActionGuidelines02022: '테러',\n    emergencyActionGuidelines02022007: '신고 요령',\n    emergencyActionGuidelines02022008: '대형, 고층건물 재난 시',\n    emergencyActionGuidelines02022009: '폭발물 발견 시',\n    emergencyActionGuidelines02022010: '화학 테러(독가스 등) 발생 시',\n    emergencyActionGuidelines02022011: '생물 테러 발생 시',\n    emergencyActionGuidelines02022012: '방사능 테러 발생 시',\n    emergencyActionGuidelines02022013: '화재 발생 시',\n    emergencyActionGuidelines02022014: '총격 현장',\n    emergencyActionGuidelines02022015: '매몰, 붕괴 시',\n    emergencyActionGuidelines02022016: '억류, 납치 시',\n    emergencyActionGuidelines02022017: '테러범·의심물체 등',\n    emergencyActionGuidelines02023: '전력수급',\n    emergencyActionGuidelines02023001: '단계별',\n    emergencyActionGuidelines03002: '응급처치',\n    emergencyActionGuidelines03002001: '일반',\n    emergencyActionGuidelines03002002: '화상',\n    emergencyActionGuidelines03002003: '온열질환',\n    emergencyActionGuidelines03002004: '뱀에 물렸을 때',\n    emergencyActionGuidelines03002005: '벌에 쏘였을 때',\n    emergencyActionGuidelines03002006: '과호흡증후군',\n    emergencyActionGuidelines03002007: '상비약',\n    emergencyActionGuidelines03003: '심폐소생술',\n    emergencyActionGuidelines03003001: '성인',\n    emergencyActionGuidelines03003002: '영유아',\n    emergencyActionGuidelines03003003: '자동제세동기',\n    emergencyActionGuidelines03004: '소화기',\n    emergencyActionGuidelines03004001: '분말 소화기',\n    emergencyActionGuidelines03004002: '투척용 소화기',\n    emergencyActionGuidelines03004003: '설치/취급 및 사용법',\n    emergencyActionGuidelines03004004: '소화기의 종류',\n    emergencyActionGuidelines03005: '식중독',\n    emergencyActionGuidelines03005001: '일반',\n    emergencyActionGuidelines03005002: '음식점/급식소 운영자',\n    emergencyActionGuidelines03006: '산행',\n    emergencyActionGuidelines03006001: '위급 상황 시',\n    emergencyActionGuidelines03006002: '구조 요청 시',\n    emergencyActionGuidelines03006003: '응급조치',\n    emergencyActionGuidelines03007: '어린이 놀이시설',\n    emergencyActionGuidelines03007001: '탑승 대기',\n    emergencyActionGuidelines03007002: '안전 이용',\n    emergencyActionGuidelines03007003: '탑승 제한',\n    emergencyActionGuidelines03007004: '어린이 탑승',\n    emergencyActionGuidelines03007005: '탑승 시 주의',\n    emergencyActionGuidelines03007006: '운행 중 자세',\n    emergencyActionGuidelines03007007: '탑승 완료 후 퇴장',\n    emergencyActionGuidelines03008: '실종유괴',\n    emergencyActionGuidelines03008001: '예방 방법',\n    emergencyActionGuidelines03009: '성폭력',\n    emergencyActionGuidelines03009001: '예방 방법',\n    emergencyActionGuidelines03010: '학교폭력',\n    emergencyActionGuidelines03010001: '예방 방법',\n    emergencyActionGuidelines03011: '가정폭력',\n    emergencyActionGuidelines03011001: '예방 방법',\n    emergencyActionGuidelines03012: '억류 및 납치',\n    emergencyActionGuidelines03012001: '대처 요령',\n    emergencyActionGuidelines03013: '교통사고',\n    emergencyActionGuidelines03013001: '사고 예방',\n    emergencyActionGuidelines03013002: '발생 시',\n    emergencyActionGuidelines03013003: '상황 판단',\n    emergencyActionGuidelines03013004: '구출',\n    emergencyActionGuidelines03013005: '차량에서의 구조',\n    emergencyActionGuidelines03014: '승강기',\n    emergencyActionGuidelines03014001: '안전 이용',\n    emergencyActionGuidelines03014002: '안전 문화',\n    emergencyActionGuidelines03014003: '고장 시 안전 구조',\n    emergencyActionGuidelines03014004: '에스컬레이터 안전 수칙',\n    emergencyActionGuidelines03014005: '엘리베이터 사고 예방',\n    emergencyActionGuidelines03014006: '에스컬레이터 및 무빙워크 사고 예방',\n    emergencyActionGuidelines03015: '미세먼지',\n    emergencyActionGuidelines03015001: '특성',\n    emergencyActionGuidelines03015002: '미세먼지 예보 등급별',\n    emergencyActionGuidelines03015003: '부문별 생활 수칙',\n    emergencyActionGuidelines03015004: '인체에 미치는 영향',\n    emergencyActionGuidelines03015005: '미세먼지 정보',\n    emergencyActionGuidelines03015006: '미세먼지 발생 시',\n    emergencyActionGuidelines03015007: '미세먼지 많은 날',\n    emergencyActionGuidelines03016: '소화전',\n    emergencyActionGuidelines03016001: '옥내소화전 사용법',\n    emergencyActionGuidelines03016002: '경보 설비',\n    emergencyActionGuidelines03017: '가정 안전점검',\n    emergencyActionGuidelines03017001: '안전점검의 날 준비',\n    emergencyActionGuidelines03017002: '계절별 대비',\n    tts_female: '여성',\n    tts_male: '남성',\n    tts_kind: '친절한',\n    tts_sweet: '감미로운',\n    tts_echo: '울리는',\n    tts_mischievous: '장난스러운',\n    tts_dainty: '앙증맞은',\n    tts_veryslow: '매우 느린',\n    tts_slow: '느린',\n    tts_normal: '보통',\n    tts_fast: '빠른',\n    tts_veryfast: '매우 빠른',\n    tts_verylow: '매우 낮은',\n    tts_low: '낮은',\n    tts_high: '높은',\n    tts_veryhigh: '매우 높은',\n    ARDUINO: '하드웨어',\n    ARDUINO_download_connector: '• 연결 프로그램 다운로드',\n    ARDUINO_open_connector: '연결 프로그램 열기',\n    ARDUINO_download_source: '• 엔트리 아두이노 소스',\n    ARDUINO_reconnect: '하드웨어 연결하기',\n    hardware_connect_helper: '하드웨어 연결 도움말',\n    hardware_noti_installed: '프로그램을 설치해 연결할 때',\n    hardware_noti_not_installed: '프로그램 설치 없이 연결할 때',\n    hardware_program_download: '연결 프로그램 다운로드',\n    hardware_device_name_title: '연결한 하드웨어:',\n    hardware_device_name_title_robot: '연결한 로봇:',\n    hardware_device_name_content: '없음',\n    hardware_connected_noti: '하드웨어 연결 프로그램을\\n확인해 주세요.',\n    arduino_noti_text:\n        '하드웨어 연결은\\n데스크톱 PC에서만 지원됩니다.\\n \\n태블릿 PC 연결 지원에 대해서는 \\n하드웨어 제조사에 문의해 주세요.',\n    arduino_lite_alert:\n        '하드웨어를 찾을 수 없습니다.\\n하드웨어에 펌웨어가 설치되었는지,\\nPC와 하드웨어가 연결되어 있는지 \\n다시 확인해 주세요.',\n    arduino_lite_reconnect: '하드웨어 다시 연결',\n    arduino_lite_download_firmware: '펌웨어 다운로드',\n    arduino_lite_download_driver: '드라이버 다운로드',\n    arduino_lite_connect: '브라우저로 연결하기',\n    arduino_lite_disconnect: '하드웨어 선택 취소',\n    arduino_lite_guide: '• 아두이노 연결 가이드',\n    arduino_lite_connected_noti: '하드웨어를 선택한 상태에서\\n작품을 저장해 주세요.',\n    ARDUINO_LITE: '하드웨어 라이트',\n    ROBOT_connect_helper: '로봇 연결 도움말',\n    ROBOT_reconnect: '로봇 연결하기',\n    ARDUINO_program: '프로그램 실행하기',\n    ARDUINO_cloud_pc_connector: '클라우드 PC 연결하기',\n    ARDUINO_connected: '하드웨어가 연결되었습니다. ',\n    ARDUINO_connect: '* 하드웨어를 연결하세요.',\n    ARDUINO_arduino_get_number_1: '신호',\n    ARDUINO_arduino_get_number_2: '의 숫자 결과값',\n    ARDUINO_arduino_get_sensor_number_0: '0',\n    ARDUINO_arduino_get_sensor_number_1: '1',\n    ARDUINO_arduino_get_sensor_number_2: '2',\n    ARDUINO_arduino_get_sensor_number_3: '3',\n    ARDUINO_arduino_get_sensor_number_4: '4',\n    ARDUINO_arduino_get_sensor_number_5: '5',\n    blacksmith_toggle_on: '켜기',\n    blacksmith_toggle_off: '끄기',\n    blacksmith_lcd_first_line: '첫 번째',\n    blacksmith_lcd_seconds_line: '두 번째',\n    BITBRICK_light: '밝기 센서',\n    BITBRICK_IR: '적외선 센서',\n    BITBRICK_touch: '버튼',\n    BITBRICK_potentiometer: '가변저항',\n    BITBRICK_MIC: '소리 센서',\n    BITBRICK_UserSensor: '사용자 입력',\n    BITBRICK_UserInput: '사용자 입력',\n    BITBRICK_dc_direction_ccw: '반시계',\n    BITBRICK_dc_direction_cw: '시계',\n    chocopi_control_event_pressed: '누를 때',\n    chocopi_control_event_released: '뗄 때',\n    chocopi_joystick_X: '조이스틱 좌우',\n    chocopi_joystick_Y: '조이스틱 상하',\n    chocopi_motion_photogate_event_blocked: '막았을 때',\n    chocopi_motion_photogate_event_unblocked: '열었을 때',\n    chocopi_motion_photogate_time_blocked: '막은 시간',\n    chocopi_motion_photogate_time_unblocked: '연 시간',\n    chocopi_port: '포트',\n    chocopi_pot: '볼륨',\n    chocopi_touch_event_touch: '만질 때',\n    chocopi_touch_event_untouch: '뗄 때',\n    CODEino_get_sensor_number_0: '0',\n    CODEino_get_sensor_number_1: '1',\n    CODEino_get_sensor_number_2: '2',\n    CODEino_get_sensor_number_3: '3',\n    CODEino_get_sensor_number_4: '4',\n    CODEino_get_sensor_number_5: '5',\n    CODEino_get_sensor_number_6: '6',\n    CODEino_sensor_name_0: '소리',\n    CODEino_sensor_name_1: '빛',\n    CODEino_sensor_name_2: '슬라이더',\n    CODEino_sensor_name_3: '저항-A',\n    CODEino_sensor_name_4: '저항-B',\n    CODEino_sensor_name_5: '저항-C',\n    CODEino_sensor_name_6: '저항-D',\n    CODEino_string_1: ' 센서값 ',\n    CODEino_string_2: ' 보드의 ',\n    CODEino_string_3: '버튼누름',\n    CODEino_string_4: 'A 연결됨',\n    CODEino_string_5: 'B 연결됨',\n    CODEino_string_6: 'C 연결됨',\n    CODEino_string_7: 'D 연결됨',\n    CODEino_string_8: ' 3축 가속도센서 ',\n    CODEino_string_9: '축의 센서값 ',\n    CODEino_string_10: '소리센서 ',\n    CODEino_string_11: '소리큼',\n    CODEino_string_12: '소리작음',\n    CODEino_string_13: '빛센서 ',\n    CODEino_string_14: '밝음',\n    CODEino_string_15: '어두움',\n    CODEino_string_16: '왼쪽 기울임',\n    CODEino_string_17: '오른쪽 기울임',\n    CODEino_string_18: '위쪽 기울임',\n    CODEino_string_19: '아래쪽 기울임',\n    CODEino_string_20: '뒤집힘',\n    CODEino_accelerometer_X: 'X',\n    CODEino_accelerometer_Y: 'Y',\n    CODEino_accelerometer_Z: 'Z',\n    CODEino_led_red: '빨강',\n    CODEino_led_green: '초록',\n    CODEino_led_blue: '파랑',\n    iboard_analog_number_0: 'A0',\n    iboard_analog_number_1: 'A1',\n    iboard_analog_number_2: 'A2',\n    iboard_analog_number_3: 'A3',\n    iboard_analog_number_4: 'A4',\n    iboard_analog_number_5: 'A5',\n    iboard_light: '빛센서가 ',\n    iboard_num_pin_1: 'LED 상태를',\n    iboard_num_pin_2: '번 스위치가',\n    iboard_num_pin_3: '아날로그',\n    iboard_num_pin_4: '번 ',\n    iboard_num_pin_5: '센서값',\n    iboard_string_1: '켜짐',\n    iboard_string_2: '꺼짐',\n    iboard_string_3: '밝음',\n    iboard_string_4: '어두움',\n    iboard_string_5: '눌림',\n    iboard_string_6: '열림',\n    iboard_switch: '스위치 ',\n    iboard_tilt: '기울기센서 상태가',\n    dplay_switch: '스위치 ',\n    dplay_light: '빛센서가 ',\n    dplay_tilt: '기울기센서 상태가',\n    dplay_string_1: '켜짐',\n    dplay_string_2: '꺼짐',\n    dplay_string_3: '밝음',\n    dplay_string_4: '어두움',\n    dplay_string_5: '눌림',\n    dplay_string_6: '열림',\n    dplay_num_pin_1: 'LED 상태를',\n    dplay_num_pin_2: '번 스위치가',\n    dplay_num_pin_3: '아날로그',\n    dplay_num_pin_4: '번 ',\n    dplay_num_pin_5: '센서값',\n    dplay_analog_number_0: 'A0',\n    dplay_analog_number_1: 'A1',\n    dplay_analog_number_2: 'A2',\n    dplay_analog_number_3: 'A3',\n    dplay_analog_number_4: 'A4',\n    dplay_analog_number_5: 'A5',\n    ARDUINO_arduino_get_string_1: '신호',\n    ARDUINO_arduino_get_string_2: '의 글자 결과값',\n    ARDUINO_arduino_send_1: '신호',\n    ARDUINO_arduino_send_2: '보내기',\n    ARDUINO_num_sensor_value_1: '아날로그',\n    ARDUINO_num_sensor_value_2: '번 센서값',\n    ARDUINO_get_digital_value_1: '디지털',\n    ARDUINO_num_pin_1: '디지털',\n    ARDUINO_num_pin_2: '번 핀',\n    ARDUINO_toggle_pwm_1: '디지털',\n    ARDUINO_toggle_pwm_2: '번 핀을',\n    ARDUINO_toggle_pwm_3: '(으)로 정하기',\n    ARDUINO_on: '켜기',\n    ARDUINO_convert_scale_1: '',\n    ARDUINO_convert_scale_2: '값의 범위를',\n    ARDUINO_convert_scale_3: '~',\n    ARDUINO_convert_scale_4: '에서',\n    ARDUINO_convert_scale_5: '~',\n    ARDUINO_convert_scale_6: '(으)로 바꾼값',\n    ARDUINO_off: '끄기',\n    EXPANSION: '확장',\n    brightness: '밝기',\n    BRUSH: '붓',\n    BRUSH_brush_erase_all: '모든 붓 지우기',\n    BRUSH_change_opacity_1: '붓의 불투명도를',\n    BRUSH_change_opacity_2: '% 만큼 바꾸기',\n    BRUSH_change_thickness_1: '붓의 굵기를',\n    BRUSH_change_thickness_2: '만큼 바꾸기',\n    BRUSH_set_color_1: '붓의 색을',\n    BRUSH_set_color_2: '(으)로 정하기',\n    BRUSH_set_opacity_1: '붓의 불투명도를',\n    BRUSH_set_opacity_2: '% 로 정하기',\n    BRUSH_set_random_color: '붓의 색을 무작위로 정하기',\n    BRUSH_set_thickness_1: '붓의 굵기를',\n    BRUSH_set_thickness_2: '(으)로 정하기',\n    BRUSH_stamp: '도장 찍기',\n    BRUSH_start_drawing: '그리기 시작하기',\n    BRUSH_stop_drawing: '그리기 멈추기',\n    CALC: '계산',\n    CALC_calc_mod_1: '',\n    CALC_calc_mod_2: '/',\n    CALC_calc_mod_3: '의 나머지',\n    CALC_calc_operation_of_1: '',\n    CALC_calc_operation_of_2: '의',\n    CALC_calc_operation_root: '루트',\n    CALC_calc_operation_square: '제곱',\n    CALC_calc_rand_1: '',\n    CALC_calc_rand_2: '부터',\n    CALC_calc_rand_3: '사이의 무작위 수',\n    CALC_calc_share_1: '',\n    CALC_calc_share_2: '/',\n    CALC_calc_share_3: '의 몫',\n    CALC_coordinate_mouse_1: '마우스',\n    CALC_coordinate_mouse_2: '좌푯값',\n    CALC_coordinate_object_1: '',\n    CALC_coordinate_object_2: '의',\n    CALC_coordinate_object_3: '',\n    CALC_distance_something_1: '',\n    CALC_distance_something_2: '까지의 거리',\n    CALC_get_angle: '각도값',\n    CALC_get_date_1: ' 현재',\n    CALC_get_date_2: '',\n    CALC_get_date_day: '일',\n    CALC_get_date_hour: '시각(시)',\n    CALC_get_date_minute: '시각(분)',\n    CALC_get_date_day_of_week: '요일',\n    CALC_get_date_month: '월',\n    CALC_get_date_second: '시각(초)',\n    CALC_get_date_year: '연도',\n    CALC_get_sound_duration_1: '',\n    CALC_get_sound_duration_2: '소리의 길이',\n    CALC_get_timer_value: ' 초시계 값',\n    CALC_get_x_coordinate: 'X 좌푯값',\n    CALC_get_y_coordinate: 'Y 좌푯값',\n    CALC_timer_reset: '초시계 초기화',\n    CALC_timer_visible_1: '초시계',\n    CALC_timer_visible_2: '',\n    CALC_timer_visible_show: '보이기',\n    CALC_timer_visible_hide: '숨기기',\n    color: '색깔',\n    FLOW: '흐름',\n    FLOW__if_1: '만일',\n    FLOW__if_2: '이라면',\n    FLOW_create_clone_1: '',\n    FLOW_create_clone_2: '의 복제본 만들기',\n    FLOW_delete_clone: '이 복제본 삭제하기',\n    FLOW_delete_clone_all: '모든 복제본 삭제하기',\n    FLOW_if_else_1: '만일',\n    FLOW_if_else_2: '이라면',\n    FLOW_if_else_3: '아니면',\n    FLOW_repeat_basic_1: '',\n    FLOW_repeat_basic_2: '번 반복하기',\n    FLOW_repeat_basic_errorMsg: '반복 횟수는 0보다 같거나 커야 합니다.',\n    FLOW_repeat_inf: '계속 반복하기',\n    FLOW_restart: '처음부터 다시 실행하기',\n    FLOW_stop_object_1: '',\n    FLOW_stop_object_2: '멈추기',\n    FLOW_stop_object_all: '모든',\n    FLOW_stop_object_this_object: '자신의',\n    FLOW_stop_object_this_thread: '이',\n    FLOW_stop_object_other_thread: '자신의 다른',\n    FLOW_stop_object_other_objects: '다른 오브젝트의',\n    FLOW_stop_repeat: '반복 중단하기',\n    FLOW_stop_run: '프로그램 끝내기',\n    FLOW_wait_second_1: '',\n    FLOW_wait_second_2: '초 기다리기',\n    FLOW_wait_until_true_1: '',\n    FLOW_wait_until_true_2: '이(가) 될 때까지 기다리기',\n    FLOW_when_clone_start: '복제본이 처음 생성되었을때',\n    FUNC: '함수',\n    ANALYSIS: '데이터분석',\n    AI: '인공지능',\n    JUDGEMENT: '판단',\n    JUDGEMENT_boolean_and: '그리고',\n    JUDGEMENT_boolean_not_1: '',\n    JUDGEMENT_boolean_not_2: '(이)가 아니다',\n    JUDGEMENT_boolean_or: '또는',\n    JUDGEMENT_false: ' 거짓 ',\n    JUDGEMENT_is_clicked: '마우스를 클릭했는가?',\n    JUDGEMENT_is_object_clicked: '오브젝트를 클릭했는가?',\n    JUDGEMENT_is_press_some_key_1: '',\n    JUDGEMENT_is_press_some_key_2: '키가 눌러져 있는가?',\n    JUDGEMENT_reach_something_1: '',\n    JUDGEMENT_reach_something_2: '에 닿았는가?',\n    JUDGEMENT_is_type_1: '(이)가',\n    JUDGEMENT_is_type_2: '인가?',\n    JUDGEMENT_true: ' 참 ',\n    JUDGEMENT_is_boost_mode: '부스트모드가 켜져 있는가?',\n    is_type_number: '숫자',\n    LOOKS: '생김새',\n    LOOKS_change_scale_percent_1: '크기를',\n    LOOKS_change_scale_percent_2: '만큼 바꾸기',\n    LOOKS_change_to_next_shape: '다음 모양으로 바꾸기',\n    LOOKS_change_to_nth_shape_1: '',\n    LOOKS_change_to_nth_shape_2: '모양으로 바꾸기',\n    LOOKS_change_shape_prev: '이전',\n    LOOKS_change_shape_next: '다음',\n    LOOKS_change_to_near_shape_1: '',\n    LOOKS_change_to_near_shape_2: '모양으로 바꾸기',\n    LOOKS_dialog_1: '',\n    LOOKS_dialog_2: '을(를)',\n    LOOKS_dialog_3: '',\n    LOOKS_dialog_time_1: '',\n    LOOKS_dialog_time_2: '을(를)',\n    LOOKS_dialog_time_3: '초 동안',\n    LOOKS_dialog_time_4: '',\n    LOOKS_erase_all_effects: '효과 모두 지우기',\n    LOOKS_flip_x: '상하 모양 뒤집기',\n    LOOKS_flip_y: '좌우 모양 뒤집기',\n    LOOKS_hide: '모양 숨기기',\n    LOOKS_remove_dialog: '말하기 지우기',\n    LOOKS_set_effect_1: '',\n    LOOKS_set_effect_2: '효과를',\n    LOOKS_set_effect_3: '(으)로 정하기',\n    LOOKS_set_effect_volume_1: '',\n    LOOKS_set_effect_volume_2: '효과를',\n    LOOKS_set_effect_volume_3: '만큼 주기',\n    LOOKS_set_object_order_1: '',\n    LOOKS_set_object_order_2: '번째로 올라오기',\n    LOOKS_set_scale_percent_1: '크기를',\n    LOOKS_set_scale_percent_2: ' (으)로 정하기',\n    LOOKS_show: '모양 보이기',\n    mouse_pointer: '마우스포인터',\n    MOVING: '움직임',\n    MOVING_bounce_wall: '화면 끝에 닿으면 튕기기',\n    MOVING_bounce_when_1: '',\n    MOVING_bounce_when_2: '에 닿으면 튕기기',\n    MOVING_flip_arrow_horizontal: '화살표 방향 좌우 뒤집기',\n    MOVING_flip_arrow_vertical: '화살표 방향 상하 뒤집기',\n    MOVING_locate_1: '',\n    MOVING_locate_2: '위치로 이동하기',\n    MOVING_locate_time_1: '',\n    MOVING_locate_time_2: '초 동안',\n    MOVING_locate_time_3: '위치로 이동하기',\n    MOVING_locate_x_1: 'x:',\n    MOVING_locate_x_2: '위치로 이동하기',\n    MOVING_locate_xy_1: 'x:',\n    MOVING_locate_xy_2: 'y:',\n    MOVING_locate_xy_3: '위치로 이동하기',\n    MOVING_locate_xy_time_1: '',\n    MOVING_locate_xy_time_2: '초 동안 x:',\n    MOVING_locate_xy_time_3: 'y:',\n    MOVING_locate_xy_time_4: '위치로 이동하기',\n    MOVING_locate_y_1: 'y:',\n    MOVING_locate_y_2: '위치로 이동하기',\n    MOVING_move_direction_1: '이동 방향으로',\n    MOVING_move_direction_2: '만큼 움직이기',\n    MOVING_move_direction_angle_1: '',\n    MOVING_move_direction_angle_2: '방향으로',\n    MOVING_move_direction_angle_3: '만큼 움직이기',\n    MOVING_move_x_1: 'x 좌표를',\n    MOVING_move_x_2: '만큼 바꾸기',\n    MOVING_move_xy_time_1: '',\n    MOVING_move_xy_time_2: '초 동안 x:',\n    MOVING_move_xy_time_3: 'y:',\n    MOVING_move_xy_time_4: '만큼 움직이기',\n    MOVING_move_y_1: 'y 좌표를',\n    MOVING_move_y_2: '만큼 바꾸기',\n    MOVING_rotate_by_angle_1: '오브젝트를',\n    MOVING_rotate_by_angle_2: '만큼 회전하기',\n    MOVING_rotate_by_angle_dropdown_1: '',\n    MOVING_rotate_by_angle_dropdown_2: '만큼 회전하기',\n    MOVING_rotate_by_angle_time_1: '오브젝트를',\n    MOVING_rotate_by_angle_time_2: '초 동안',\n    MOVING_rotate_by_angle_time_3: '만큼 회전하기',\n    MOVING_rotate_direction_1: '이동 방향을',\n    MOVING_rotate_direction_2: '만큼 회전하기',\n    MOVING_see_angle_1: '이동 방향을',\n    MOVING_see_angle_2: '(으)로 정하기',\n    MOVING_see_angle_direction_1: '오브젝트를',\n    MOVING_see_angle_direction_2: '(으)로 정하기',\n    MOVING_see_angle_object_1: '',\n    MOVING_see_angle_object_2: '쪽 바라보기',\n    MOVING_see_direction_1: '',\n    MOVING_see_direction_2: '쪽 보기',\n    MOVING_set_direction_by_angle_1: '방향을',\n    MOVING_set_direction_by_angle_2: '(으)로 정하기',\n    MOVING_add_direction_by_angle_1: '방향을',\n    MOVING_add_direction_by_angle_2: '만큼 회전하기',\n    MOVING_add_direction_by_angle_time_1: '방향을',\n    MOVING_add_direction_by_angle_time_2: '초 동안',\n    MOVING_add_direction_by_angle_time_3: '만큼 회전하기',\n    no_target: '대상 없음',\n    oneself: '자신',\n    opacity: '불투명도',\n    SCENE: '장면',\n    SOUND: '소리',\n    SOUND_sound_silent_all: '모든 소리 멈추기',\n    SOUND_sound_something_1: '소리',\n    SOUND_sound_something_2: '재생하기',\n    SOUND_sound_something_second_1: '소리',\n    SOUND_sound_something_second_2: '',\n    SOUND_sound_something_second_3: '초 재생하기',\n    SOUND_sound_something_second_wait_1: '소리',\n    SOUND_sound_something_second_wait_2: '',\n    SOUND_sound_something_second_wait_3: '초 재생하고 기다리기',\n    SOUND_sound_something_wait_1: '소리 ',\n    SOUND_sound_something_wait_2: '재생하고 기다리기',\n    SOUND_sound_volume_change_1: '소리 크기를',\n    SOUND_sound_volume_change_2: '% 만큼 바꾸기',\n    SOUND_sound_volume_set_1: '소리 크기를',\n    SOUND_sound_volume_set_2: '% 로 정하기',\n    speak: '말하기',\n    think: '생각하기',\n    START: '시작',\n    START_add_message: '신호 추가하기',\n    START_delete_message: '신호 삭제하기',\n    START_message_cast: '신호 보내기',\n    START_message_cast_1: '',\n    START_message_cast_2: '신호 보내기',\n    START_message_cast_wait: '신호 보내고 기다리기',\n    START_message_send_wait_1: '',\n    START_message_send_wait_2: '신호 보내고 기다리기',\n    START_mouse_click_cancled: '마우스 클릭을 해제했을 때',\n    START_mouse_clicked: '마우스를 클릭했을 때',\n    START_press_some_key_1: '',\n    START_press_some_key_2: '키를 눌렀을 때',\n    START_press_some_key_down: '아래쪽 화살표',\n    START_press_some_key_enter: '엔터',\n    START_press_some_key_left: '왼쪽 화살표',\n    START_press_some_key_right: '오른쪽 화살표',\n    START_press_some_key_space: '스페이스',\n    START_press_some_key_up: '위쪽 화살표',\n    START_press_some_key_back_space: '백스페이스',\n    START_press_some_key_back_slash: '백슬래시',\n    START_when_message_cast: '신호를 받았을 때',\n    START_when_message_cast_1: '',\n    START_when_message_cast_2: '신호를 받았을 때',\n    START_when_object_click: '오브젝트를 클릭했을 때',\n    START_when_object_click_canceled: '오브젝트 클릭을 해제했을 때',\n    START_when_run_button_click: '시작하기 버튼을 클릭했을 때',\n    START_when_scene_start: '장면이 시작했을때',\n    START_when_some_key_click: '키를 눌렀을 때',\n    TEXT: '글상자',\n    TEXT_text: '엔트리',\n    TEXT_text_append_1: '',\n    TEXT_text_append_2: '라고 뒤에 이어쓰기',\n    TEXT_text_flush: '텍스트 모두 지우기',\n    TEXT_text_prepend_1: '',\n    TEXT_text_prepend_2: '라고 앞에 추가하기',\n    TEXT_text_write_1: '',\n    TEXT_text_write_2: '라고 글쓰기',\n    VARIABLE: '자료',\n    VARIABLE_add_value_to_list: '항목을 리스트에 추가하기',\n    VARIABLE_add_value_to_list_1: '',\n    VARIABLE_add_value_to_list_2: '항목을',\n    VARIABLE_add_value_to_list_3: '에 추가하기',\n    VARIABLE_ask_and_wait_1: '',\n    VARIABLE_ask_and_wait_2: '을(를) 묻고 대답 기다리기',\n    VARIABLE_change_value_list_index: '항목을 바꾸기',\n    VARIABLE_change_value_list_index_1: '',\n    VARIABLE_change_value_list_index_3: '번째 항목을',\n    VARIABLE_change_value_list_index_2: '  ',\n    VARIABLE_change_value_list_index_4: '(으)로 바꾸기',\n    VARIABLE_change_variable: '변수 더하기',\n    VARIABLE_change_variable_1: '',\n    VARIABLE_change_variable_2: '에',\n    VARIABLE_change_variable_3: '만큼 더하기',\n    VARIABLE_change_variable_name: '변수 이름 바꾸기',\n    VARIABLE_combine_something_1: '',\n    VARIABLE_combine_something_2: '과(와)',\n    VARIABLE_combine_something_3: '을(를) 합친 값',\n    VARIABLE_get_canvas_input_value: ' 대답 ',\n    VARIABLE_get_variable: '변수',\n    VARIABLE_get_variable_1: '값',\n    VARIABLE_get_variable_2: '값',\n    VARIABLE_get_y: 'Y 좌푯값',\n    VARIABLE_hide_list: '리스트 숨기기',\n    VARIABLE_hide_list_1: '리스트',\n    VARIABLE_hide_list_2: '숨기기',\n    VARIABLE_hide_variable: '변수값 숨기기',\n    VARIABLE_hide_variable_1: '변수',\n    VARIABLE_hide_variable_2: '숨기기',\n    VARIABLE_insert_value_to_list: '항목을 넣기',\n    VARIABLE_insert_value_to_list_1: '',\n    VARIABLE_insert_value_to_list_2: '을(를)',\n    VARIABLE_insert_value_to_list_3: '의',\n    VARIABLE_insert_value_to_list_4: '번째에 넣기',\n    VARIABLE_length_of_list: '리스트의 길이',\n    VARIABLE_length_of_list_1: '',\n    VARIABLE_length_of_list_2: ' 항목 수',\n    VARIABLE_list: '리스트',\n    VARIABLE_make_variable: '변수 만들기',\n    VARIABLE_list_option_first: '첫번째',\n    VARIABLE_list_option_last: '마지막',\n    VARIABLE_list_option_random: '무작위',\n    VARIABLE_remove_value_from_list: '항목을 삭제하기',\n    VARIABLE_remove_value_from_list_1: '',\n    VARIABLE_remove_value_from_list_2: '번째 항목을',\n    VARIABLE_remove_value_from_list_3: '에서 삭제하기',\n    VARIABLE_remove_variable: '변수 삭제',\n    VARIABLE_set_variable: '변수 정하기',\n    VARIABLE_set_variable_1: '',\n    VARIABLE_set_variable_2: '를',\n    VARIABLE_set_variable_3: '로 정하기',\n    VARIABLE_show_list: '리스트 보이기',\n    VARIABLE_show_list_1: '리스트',\n    VARIABLE_show_list_2: '보이기',\n    VARIABLE_show_variable: '변수값 보이기',\n    VARIABLE_show_variable_1: '변수',\n    VARIABLE_show_variable_2: '보이기',\n    VARIABLE_value_of_index_from_list: '리스트 항목의 값',\n    VARIABLE_value_of_index_from_list_1: '',\n    VARIABLE_value_of_index_from_list_2: '의',\n    VARIABLE_value_of_index_from_list_3: '번째 항목',\n    HAMSTER_hand_found: '손 찾음?',\n    HAMSTER_sensor_left_proximity: '왼쪽 근접 센서',\n    HAMSTER_sensor_right_proximity: '오른쪽 근접 센서',\n    HAMSTER_sensor_left_floor: '왼쪽 바닥 센서',\n    HAMSTER_sensor_right_floor: '오른쪽 바닥 센서',\n    HAMSTER_sensor_acceleration_x: 'x축 가속도',\n    HAMSTER_sensor_acceleration_y: 'y축 가속도',\n    HAMSTER_sensor_acceleration_z: 'z축 가속도',\n    HAMSTER_sensor_light: '밝기',\n    HAMSTER_sensor_temperature: '온도',\n    HAMSTER_sensor_signal_strength: '신호 세기',\n    HAMSTER_sensor_input_a: '입력 A',\n    HAMSTER_sensor_input_b: '입력 B',\n    HAMSTER_move_forward_once: '말판 앞으로 한 칸 이동하기',\n    HAMSTER_turn_once_1: '말판',\n    HAMSTER_turn_once_2: '으로 한 번 돌기',\n    HAMSTER_turn_once_left: '왼쪽',\n    HAMSTER_turn_right: '오른쪽',\n    HAMSTER_move_forward: '앞으로 이동하기',\n    HAMSTER_move_backward: '뒤로 이동하기',\n    HAMSTER_turn_around_1: '',\n    HAMSTER_turn_around_2: '으로 돌기',\n    HAMSTER_move_forward_for_secs_1: '앞으로',\n    HAMSTER_move_forward_for_secs_2: '초 이동하기',\n    HAMSTER_move_backward_for_secs_1: '뒤로',\n    HAMSTER_move_backward_for_secs_2: '초 이동하기',\n    HAMSTER_turn_for_secs_1: '',\n    HAMSTER_turn_for_secs_2: '으로',\n    HAMSTER_turn_for_secs_3: '초 돌기',\n    HAMSTER_change_both_wheels_by_1: '왼쪽 바퀴',\n    HAMSTER_change_both_wheels_by_2: '오른쪽 바퀴',\n    HAMSTER_change_both_wheels_by_3: '만큼 바꾸기',\n    HAMSTER_set_both_wheels_to_1: '왼쪽 바퀴',\n    HAMSTER_set_both_wheels_to_2: '오른쪽 바퀴',\n    HAMSTER_set_both_wheels_to_3: '(으)로 정하기',\n    HAMSTER_change_wheel_by_1: '',\n    HAMSTER_change_wheel_by_2: '바퀴',\n    HAMSTER_change_wheel_by_3: '만큼 바꾸기',\n    HAMSTER_left_wheel: '왼쪽',\n    HAMSTER_right_wheel: '오른쪽',\n    HAMSTER_both_wheels: '양쪽',\n    HAMSTER_set_wheel_to_1: '',\n    HAMSTER_set_wheel_to_2: '바퀴',\n    HAMSTER_set_wheel_to_3: '(으)로 정하기',\n    HAMSTER_follow_line_using_1: '',\n    HAMSTER_follow_line_using_2: '선을',\n    HAMSTER_follow_line_using_3: '바닥 센서로 따라가기',\n    HAMSTER_left_floor_sensor: '왼쪽',\n    HAMSTER_right_floor_sensor: '오른쪽',\n    HAMSTER_both_floor_sensors: '양쪽',\n    HAMSTER_follow_line_until_1: '',\n    HAMSTER_follow_line_until_2: '선을 따라',\n    HAMSTER_follow_line_until_3: '교차로까지 이동하기',\n    HAMSTER_left_intersection: '왼쪽',\n    HAMSTER_right_intersection: '오른쪽',\n    HAMSTER_front_intersection: '앞쪽',\n    HAMSTER_rear_intersection: '뒤쪽',\n    HAMSTER_set_following_speed_to_1: '선 따라가기 속도를',\n    HAMSTER_set_following_speed_to_2: '(으)로 정하기',\n    HAMSTER_front: '앞쪽',\n    HAMSTER_rear: '뒤쪽',\n    HAMSTER_stop: '정지하기',\n    HAMSTER_set_led_to_1: '',\n    HAMSTER_set_led_to_2: 'LED를',\n    HAMSTER_set_led_to_3: '으로 정하기',\n    HAMSTER_left_led: '왼쪽',\n    HAMSTER_right_led: '오른쪽',\n    HAMSTER_both_leds: '양쪽',\n    HAMSTER_clear_led_1: '',\n    HAMSTER_clear_led_2: 'LED 끄기',\n    HAMSTER_color_cyan: '하늘색',\n    HAMSTER_color_magenta: '자주색',\n    HAMSTER_color_black: '검은색',\n    HAMSTER_color_white: '하얀색',\n    HAMSTER_color_red: '빨간색',\n    HAMSTER_color_yellow: '노란색',\n    HAMSTER_color_green: '초록색',\n    HAMSTER_color_blue: '파란색',\n    HAMSTER_beep: '삐 소리내기',\n    HAMSTER_change_buzzer_by_1: '버저 음을',\n    HAMSTER_change_buzzer_by_2: '만큼 바꾸기',\n    HAMSTER_set_buzzer_to_1: '버저 음을',\n    HAMSTER_set_buzzer_to_2: '(으)로 정하기',\n    HAMSTER_clear_buzzer: '버저 끄기',\n    HAMSTER_play_note_for_1: '',\n    HAMSTER_play_note_for_2: '',\n    HAMSTER_play_note_for_3: '음을',\n    HAMSTER_play_note_for_4: '박자 연주하기',\n    HAMSTER_rest_for_1: '',\n    HAMSTER_rest_for_2: '박자 쉬기',\n    HAMSTER_change_tempo_by_1: '연주 속도를',\n    HAMSTER_change_tempo_by_2: '만큼 바꾸기',\n    HAMSTER_set_tempo_to_1: '연주 속도를 분당',\n    HAMSTER_set_tempo_to_2: '박자로 정하기',\n    HAMSTER_set_port_to_1: '포트',\n    HAMSTER_set_port_to_2: '를',\n    HAMSTER_set_port_to_3: '으로 정하기',\n    HAMSTER_change_output_by_1: '출력',\n    HAMSTER_change_output_by_2: '를',\n    HAMSTER_change_output_by_3: '만큼 바꾸기',\n    HAMSTER_set_output_to_1: '출력',\n    HAMSTER_set_output_to_2: '를',\n    HAMSTER_set_output_to_3: '(으)로 정하기',\n    HAMSTER_port_a: 'A',\n    HAMSTER_port_b: 'B',\n    HAMSTER_port_ab: 'A와 B',\n    HAMSTER_analog_input: '아날로그 입력',\n    HAMSTER_digital_input: '디지털 입력',\n    HAMSTER_servo_output: '서보 출력',\n    HAMSTER_pwm_output: 'PWM 출력',\n    HAMSTER_digital_output: '디지털 출력',\n    ROBOID_acceleration_x: 'x축 가속도',\n    ROBOID_acceleration_y: 'y축 가속도',\n    ROBOID_acceleration_z: 'z축 가속도',\n    ROBOID_back: '뒤쪽',\n    ROBOID_both: '양쪽',\n    ROBOID_button: '버튼',\n    ROBOID_buzzer: '버저',\n    ROBOID_clicked: '클릭했는가',\n    ROBOID_color_any: '아무 색',\n    ROBOID_color_black: '검은색',\n    ROBOID_color_blue: '파란색',\n    ROBOID_color_green: '초록색',\n    ROBOID_color_number: '색깔 번호',\n    ROBOID_color_orange: '주황색',\n    ROBOID_color_pattern: '색깔 패턴',\n    ROBOID_color_purple: '자주색',\n    ROBOID_color_red: '빨간색',\n    ROBOID_color_sky_blue: '하늘색',\n    ROBOID_color_violet: '보라색',\n    ROBOID_color_white: '하얀색',\n    ROBOID_color_yellow: '노란색',\n    ROBOID_double_clicked: '더블클릭했는가',\n    ROBOID_floor: '바닥 센서',\n    ROBOID_head: '머리',\n    ROBOID_head_color: '머리 색깔',\n    ROBOID_left: '왼쪽',\n    ROBOID_left_wheel: '왼쪽 바퀴',\n    ROBOID_long_pressed: '길게~눌렀는가',\n    ROBOID_note: '음표',\n    ROBOID_right: '오른쪽',\n    ROBOID_right_wheel: '오른쪽 바퀴',\n    ROBOID_sound_beep: '삐',\n    ROBOID_sound_birthday: '생일',\n    ROBOID_sound_dibidibidip: '디비디비딥',\n    ROBOID_sound_engine: '엔진',\n    ROBOID_sound_good_job: '잘 했어요',\n    ROBOID_sound_march: '행진',\n    ROBOID_sound_random_beep: '무작위 삐',\n    ROBOID_sound_robot: '로봇',\n    ROBOID_sound_siren: '사이렌',\n    ROBOID_tail: '꼬리',\n    ROBOID_unit_cm: 'cm',\n    ROBOID_unit_deg: '도',\n    ROBOID_unit_pulse: '펄스',\n    ROBOID_unit_sec: '초',\n    ALBERT_hand_found: '손 찾음?',\n    ALBERT_is_oid_1: '',\n    ALBERT_is_oid_2: 'OID 값이',\n    ALBERT_is_oid_3: '인가?',\n    ALBERT_front_oid: '앞쪽',\n    ALBERT_back_oid: '뒤쪽',\n    ALBERT_sensor_left_proximity: '왼쪽 근접 센서',\n    ALBERT_sensor_right_proximity: '오른쪽 근접 센서',\n    ALBERT_sensor_acceleration_x: 'x축 가속도',\n    ALBERT_sensor_acceleration_y: 'y축 가속도',\n    ALBERT_sensor_acceleration_z: 'z축 가속도',\n    ALBERT_sensor_light: '밝기',\n    ALBERT_sensor_temperature: '온도',\n    ALBERT_sensor_battery: '배터리',\n    ALBERT_sensor_signal_strength: '신호 세기',\n    ALBERT_sensor_front_oid: '앞쪽 OID',\n    ALBERT_sensor_back_oid: '뒤쪽 OID',\n    ALBERT_sensor_position_x: 'x 위치',\n    ALBERT_sensor_position_y: 'y 위치',\n    ALBERT_sensor_orientation: '방향',\n    ALBERT_move_forward: '앞으로 이동하기',\n    ALBERT_move_backward: '뒤로 이동하기',\n    ALBERT_turn_around_1: '',\n    ALBERT_turn_around_2: '으로 돌기',\n    ALBERT_move_forward_for_secs_1: '앞으로',\n    ALBERT_move_forward_for_secs_2: '초 이동하기',\n    ALBERT_move_backward_for_secs_1: '뒤로',\n    ALBERT_move_backward_for_secs_2: '초 이동하기',\n    ALBERT_turn_for_secs_1: '',\n    ALBERT_turn_for_secs_2: '으로',\n    ALBERT_turn_for_secs_3: '초 돌기',\n    ALBERT_turn_left: '왼쪽',\n    ALBERT_turn_right: '오른쪽',\n    ALBERT_change_both_wheels_by_1: '왼쪽 바퀴',\n    ALBERT_change_both_wheels_by_2: '오른쪽 바퀴',\n    ALBERT_change_both_wheels_by_3: '만큼 바꾸기',\n    ALBERT_left_wheel: '왼쪽',\n    ALBERT_right_wheel: '오른쪽',\n    ALBERT_both_wheels: '양쪽',\n    ALBERT_set_both_wheels_to_1: '왼쪽 바퀴',\n    ALBERT_set_both_wheels_to_2: '오른쪽 바퀴',\n    ALBERT_set_both_wheels_to_3: '(으)로 정하기',\n    ALBERT_change_wheel_by_1: '',\n    ALBERT_change_wheel_by_2: '바퀴',\n    ALBERT_change_wheel_by_3: '만큼 바꾸기',\n    ALBERT_set_wheel_to_1: '',\n    ALBERT_set_wheel_to_2: '바퀴',\n    ALBERT_set_wheel_to_3: '(으)로 정하기',\n    ALBERT_stop: '정지하기',\n    ALBERT_set_board_size_to_1: '말판 크기를 폭',\n    ALBERT_set_board_size_to_2: '높이',\n    ALBERT_set_board_size_to_3: '(으)로 정하기',\n    ALBERT_move_to_x_y_1: '말판 x:',\n    ALBERT_move_to_x_y_2: 'y:',\n    ALBERT_move_to_x_y_3: '위치로 이동하기',\n    ALBERT_set_orientation_to_1: '말판',\n    ALBERT_set_orientation_to_2: '방향으로 바라보기',\n    ALBERT_set_eye_to_1: '',\n    ALBERT_set_eye_to_2: '눈을',\n    ALBERT_set_eye_to_3: '으로 정하기',\n    ALBERT_left_eye: '왼쪽',\n    ALBERT_right_eye: '오른쪽',\n    ALBERT_both_eyes: '양쪽',\n    ALBERT_clear_eye_1: '',\n    ALBERT_clear_eye_2: '눈 끄기',\n    ALBERT_body_led_1: '몸통 LED',\n    ALBERT_body_led_2: '',\n    ALBERT_front_led_1: '앞쪽 LED',\n    ALBERT_front_led_2: '',\n    ALBERT_color_cyan: '하늘색',\n    ALBERT_color_magenta: '보라색',\n    ALBERT_color_white: '하얀색',\n    ALBERT_color_red: '빨간색',\n    ALBERT_color_yellow: '노란색',\n    ALBERT_color_green: '초록색',\n    ALBERT_color_blue: '파란색',\n    ALBERT_note_c: '도',\n    ALBERT_note_d: '레',\n    ALBERT_note_e: '미',\n    ALBERT_note_f: '파',\n    ALBERT_note_g: '솔',\n    ALBERT_note_a: '라',\n    ALBERT_note_b: '시',\n    ALBERT_turn_body_led_1: '몸통 LED',\n    ALBERT_turn_body_led_2: '',\n    ALBERT_turn_front_led_1: '앞쪽 LED',\n    ALBERT_turn_front_led_2: '',\n    ALBERT_turn_on: '켜기',\n    ALBERT_turn_off: '끄기',\n    ALBERT_beep: '삐 소리내기',\n    ALBERT_change_buzzer_by_1: '버저 음을',\n    ALBERT_change_buzzer_by_2: '만큼 바꾸기',\n    ALBERT_set_buzzer_to_1: '버저 음을',\n    ALBERT_set_buzzer_to_2: '(으)로 정하기',\n    ALBERT_clear_buzzer: '버저 끄기',\n    ALBERT_play_note_for_1: '',\n    ALBERT_play_note_for_2: '',\n    ALBERT_play_note_for_3: '음을',\n    ALBERT_play_note_for_4: '박자 연주하기',\n    ALBERT_rest_for_1: '',\n    ALBERT_rest_for_2: '박자 쉬기',\n    ALBERT_change_tempo_by_1: '연주 속도를',\n    ALBERT_change_tempo_by_2: '만큼 바꾸기',\n    ALBERT_set_tempo_to_1: '연주 속도를 분당',\n    ALBERT_set_tempo_to_2: '박자로 정하기',\n    VARIABLE_variable: '변수',\n    wall: '벽',\n    robotis_common_case_01: '(을)를',\n    robotis_common_set: '(으)로 정하기',\n    robotis_common_value: '값',\n    robotis_common_clockwhise: '시계방향',\n    robotis_common_counter_clockwhise: '반시계방향',\n    robotis_common_wheel_mode: '회전모드',\n    robotis_common_joint_mode: '관절모드',\n    robotis_common_red_color: '빨간색',\n    robotis_common_green_color: '녹색',\n    robotis_common_blue_color: '파란색',\n    robotis_common_on: '켜기',\n    robotis_common_off: '끄기',\n    robotis_common_cm: '제어기',\n    robotis_common_port_1: '포트 1',\n    robotis_common_port_2: '포트 2',\n    robotis_common_port_3: '포트 3',\n    robotis_common_port_4: '포트 4',\n    robotis_common_port_5: '포트 5',\n    robotis_common_port_6: '포트 6',\n    robotis_common_play_buzzer: '연주',\n    robotis_common_play_motion: '실행',\n    robotis_common_motion: '모션',\n    robotis_common_index_number: '번',\n    robotis_common_left: '왼쪽',\n    robotis_common_right: '오른쪽',\n    robotis_common_minute: '분',\n    robotis_cm_custom: '직접입력 주소',\n    robotis_cm_spring_left: '왼쪽 접촉 센서',\n    robotis_cm_spring_right: '오른쪽 접촉 센서',\n    robotis_cm_led_left: '왼쪽 LED',\n    robotis_cm_led_right: '오른쪽 LED',\n    robotis_cm_led_both: '양 쪽 LED',\n    robotis_cm_switch: '선택 버튼 상태',\n    robotis_cm_user_button: '사용자 버튼 상태',\n    robotis_cm_sound_detected: '최종 소리 감지 횟수',\n    robotis_cm_sound_detecting: '실시간 소리 감지 횟수',\n    robotis_cm_ir_left: '왼쪽 적외선 센서',\n    robotis_cm_ir_right: '오른쪽 적외선 센서',\n    robotis_cm_calibration_left: '왼쪽 적외선 센서 캘리브레이션 값',\n    robotis_cm_calibration_right: '오른쪽 적외선 센서 캘리브레이션 값',\n    robotis_cm_clear_sound_detected: '최종소리감지횟수 초기화',\n    robotis_cm_buzzer_index: '음계값',\n    robotis_cm_buzzer_melody: '멜로디',\n    robotis_cm_led_1: '1번 LED',\n    robotis_cm_led_4: '4번 LED',\n    robotis_aux_servo_position: '서보모터 위치',\n    robotis_aux_ir: '적외선센서',\n    robotis_aux_touch: '접촉센서',\n    robotis_aux_brightness: '조도센서(CDS)',\n    robotis_aux_hydro_themo_humidity: '온습도센서(습도)',\n    robotis_aux_hydro_themo_temper: '온습도센서(온도)',\n    robotis_aux_temperature: '온도센서',\n    robotis_aux_ultrasonic: '초음파센서',\n    robotis_aux_magnetic: '자석센서',\n    robotis_aux_motion_detection: '동작감지센서',\n    robotis_aux_color: '컬러센서',\n    robotis_aux_custom: '사용자 장치',\n    robotis_carCont_aux_motor_speed_1: '감속모터 속도를',\n    robotis_carCont_aux_motor_speed_2: ', 출력값을',\n    robotis_carCont_calibration_1: '적외선 센서 캘리브레이션 값을',\n    robotis_openCM70_aux_motor_speed_1: '감속모터 속도를',\n    robotis_openCM70_aux_motor_speed_2: ', 출력값을',\n    robotis_openCM70_aux_servo_mode_1: '서보모터 모드를',\n    robotis_openCM70_aux_servo_speed_1: '서보모터 속도를',\n    robotis_openCM70_aux_servo_speed_2: ', 출력값을',\n    robotis_openCM70_aux_servo_position_1: '서보모터 위치를',\n    robotis_openCM70_aux_led_module_1: 'LED 모듈을',\n    robotis_openCM70_aux_custom_1: '사용자 장치를',\n    XBOT_digital: '디지털',\n    XBOT_D2_digitalInput: 'D2 디지털 입력',\n    XBOT_D3_digitalInput: 'D3 디지털 입력',\n    XBOT_D11_digitalInput: 'D11 디지털 입력',\n    XBOT_analog: '아날로그',\n    XBOT_CDS: '광 센서 값',\n    XBOT_MIC: '마이크 센서 값',\n    XBOT_analog0: '아날로그 0번 핀 값',\n    XBOT_analog1: '아날로그 1번 핀 값',\n    XBOT_analog2: '아날로그 2번 핀 값',\n    XBOT_analog3: '아날로그 3번 핀 값',\n    XBOT_Value: '출력 값',\n    XBOT_pin_OutputValue: '핀, 출력 값',\n    XBOT_High: '높음',\n    XBOT_Low: '낮음',\n    XBOT_Servo: '서보 모터',\n    XBOT_Head: '머리(D8)',\n    XBOT_ArmR: '오른 팔(D9)',\n    XBOT_ArmL: '왼 팔(D10)',\n    XBOT_angle: ', 각도',\n    XBOT_DC: '바퀴(DC) 모터',\n    XBOT_rightWheel: '오른쪽',\n    XBOT_leftWheel: '왼쪽',\n    XBOT_bothWheel: '양쪽',\n    XBOT_speed: ', 속도',\n    XBOT_rightSpeed: '바퀴(DC) 모터 오른쪽(2) 속도:',\n    XBOT_leftSpeed: '왼쪽(1) 속도:',\n    XBOT_RGBLED_R: 'RGB LED 켜기 R 값',\n    XBOT_RGBLED_G: 'G 값',\n    XBOT_RGBLED_B: 'B 값',\n    XBOT_RGBLED_color: 'RGB LED 색',\n    XBOT_set: '로 정하기',\n    XBOT_c: '도',\n    XBOT_d: '레',\n    XBOT_e: '미',\n    XBOT_f: '파',\n    XBOT_g: '솔',\n    XBOT_a: '라',\n    XBOT_b: '시',\n    XBOT_melody_ms: '초 연주하기',\n    XBOT_Line: '번째 줄',\n    XBOT_outputValue: '출력 값',\n    roborobo_num_analog_value_1: '아날로그',\n    roborobo_num_analog_value_2: '번 센서값',\n    roborobo_get_digital_value_1: '디지털',\n    roborobo_num_pin_1: '디지털',\n    roborobo_num_pin_2: '번 핀',\n    roborobo_on: '켜기',\n    roborobo_off: '끄기',\n    roborobo_motor1: '모터1',\n    roborobo_motor2: '모터2',\n    roborobo_motor_CW: '정회전',\n    roborobo_motor_CCW: '역회전',\n    roborobo_motor_stop: '정지',\n    roborobo_input_mode: '입력',\n    roborobo_output_mode: '출력',\n    roborobo_pwm_mode: '전류조절(pwm)',\n    roborobo_servo_mode: '서보모터',\n    roborobo_color: '컬러센서',\n    roborobo_color_red: ' 빨간색  ',\n    roborobo_color_green: ' 녹색 ',\n    roborobo_color_blue: ' 파란색 ',\n    roborobo_color_yellow: ' 노란색 ',\n    roborobo_color_detected: ' 감지 ',\n    roborobo_degree: ' ˚',\n    robotori_D2_Input: '디지털 2번 핀 입력 값',\n    robotori_D3_Input: '디지털 3번 핀 입력 값',\n    robotori_A0_Input: '아날로그 0번 핀 입력 값',\n    robotori_A1_Input: '아날로그 1번 핀 입력 값',\n    robotori_A2_Input: '아날로그 2번 핀 입력 값',\n    robotori_A3_Input: '아날로그 3번 핀 입력 값',\n    robotori_A4_Input: '아날로그 4번 핀 입력 값',\n    robotori_A5_Input: '아날로그 5번 핀 입력 값',\n    robotori_digital: '디지털',\n    robotori_D10_Output: '10번',\n    robotori_D11_Output: '11번',\n    robotori_D12_Output: '12번',\n    robotori_D13_Output: '13번',\n    robotori_pin_OutputValue: '핀, 출력 값',\n    robotori_On: '켜짐',\n    robotori_Off: '꺼짐',\n    robotori_analog: '아날로그',\n    robotori_analog5: '5번 핀 출력 값',\n    robotori_analog6: '6번 핀 출력 값',\n    robotori_analog9: '9번 핀 출력 값',\n    robotori_Servo: '서보모터',\n    robotori_DC: 'DC모터',\n    robotori_DC_rightmotor: '오른쪽',\n    robotori_DC_leftmotor: '왼쪽',\n    robotori_DC_STOP: '정지',\n    robotori_DC_CW: '시계방향',\n    robotori_DC_CCW: '반시계방향',\n    robotori_DC_select: '회전',\n    CALC_rotation_value: '방향값',\n    CALC_direction_value: '이동 방향값',\n    VARIABLE_is_included_in_list: '리스트에 포함되어 있는가?',\n    VARIABLE_is_included_in_list_1: '',\n    VARIABLE_is_included_in_list_2: '에',\n    VARIABLE_is_included_in_list_3: '이 포함되어 있는가?',\n    SCENE_when_scene_start: '장면이 시작되었을 때',\n    SCENE_start_scene_1: '',\n    SCENE_start_scene_2: '시작하기',\n    SCENE_start_neighbor_scene_1: '',\n    SCENE_start_neighbor_scene_2: '장면 시작하기',\n    SCENE_start_scene_pre: '이전',\n    SCENE_start_scene_next: '다음',\n    FUNCTION_explanation_1: '이름',\n    FUNCTION_character_variable: '문자/숫자값',\n    FUNCTION_logical_variable: '판단값',\n    FUNCTION_function: '함수',\n    FUNCTION_define: '함수 정의하기',\n    CALC_calc_operation_sin: '사인',\n    CALC_calc_operation_cos: '코사인',\n    CALC_calc_operation_tan: '탄젠트',\n    CALC_calc_operation_asin: '아크사인',\n    CALC_calc_operation_acos: '아크코사인',\n    CALC_calc_operation_atan: '아크탄젠트',\n    CALC_calc_operation_log: '로그',\n    CALC_calc_operation_ln: '자연로그',\n    CALC_calc_operation_natural: '정수 부분',\n    CALC_calc_operation_unnatural: '소수점 부분',\n    CALC_calc_operation_floor: '소수점 버림값',\n    CALC_calc_operation_ceil: '소수점 올림값',\n    CALC_calc_operation_round: '소수점 반올림값',\n    CALC_calc_operation_factorial: '팩토리얼',\n    CALC_calc_operation_abs: '절댓값',\n    MOVING_locate_object_time_1: '',\n    MOVING_locate_object_time_2: '초 동안',\n    MOVING_locate_object_time_3: '위치로 이동하기',\n    wall_up: '위쪽 벽',\n    wall_down: '아래쪽 벽',\n    wall_right: '오른쪽 벽',\n    wall_left: '왼쪽 벽',\n    CALC_coordinate_x_value: 'x 좌푯값',\n    CALC_coordinate_y_value: 'y 좌푯값',\n    CALC_coordinate_rotation_value: '방향',\n    CALC_coordinate_direction_value: '이동방향',\n    CALC_picture_index: '모양 번호',\n    CALC_picture_name: '모양 이름',\n    FLOW_repeat_while_true_1: '',\n    FLOW_repeat_while_true_2: ' 반복하기',\n    TUT_when_start: '프로그램 실행을 클릭했을때',\n    TUT_move_once: '앞으로 한 칸 이동',\n    TUT_rotate_left: '왼쪽으로 회전',\n    TUT_rotate_right: '오른쪽으로 회전',\n    TUT_jump_barrier: '장애물 뛰어넘기',\n    TUT_repeat_tutorial_1: '',\n    TUT_repeat_tutorial_2: '번 반복',\n    TUT_if_barrier_1: '만약 앞에',\n    TUT_if_barrier_2: ' 이 있다면',\n    TUT_if_conical_1: '만약 앞에',\n    TUT_if_conical_2: ' 이 있다면',\n    TUT_repeat_until: '부품에 도달할 때 까지 반복',\n    TUT_repeat_until_gold: '부품에 도달할 때 까지 반복',\n    TUT_declare_function: '함수 선언',\n    TUT_call_function: '함수 호출',\n    AI_analyze_option: 'AI로  코드 분석하기',\n    CONTEXT_COPY_option: '코드 복사하기',\n    Delete_Blocks: '코드 삭제하기',\n    Duplication_option: '코드 복제하기',\n    cut_blocks: '코드 잘라내기',\n    Paste_blocks: '붙여넣기',\n    add_my_storage: '나의 보관함에 추가하기',\n    export_object: '오브젝트 파일로 내보내기',\n    Clear_all_blocks: '모든 코드 삭제하기',\n    add_comment: '메모 추가하기',\n    copy_paste_comment: '메모 복사 & 붙여넣기',\n    copy_comment: '메모 복사하기',\n    delete_comment: '메모 삭제하기',\n    fold_comment: '메모 접기',\n    open_comment: '메모 열기',\n    separate_comment: '메모 분리하기',\n    hide_all_comment: '모든 메모 숨기기',\n    show_all_comment: '모든 메모 보이기',\n    transparency: '투명도',\n    BRUSH_change_brush_transparency_1: '붓의 투명도를',\n    BRUSH_change_brush_transparency_2: '% 만큼 바꾸기',\n    BRUSH_set_brush_transparency_1: '붓의 투명도를',\n    BRUSH_set_brush_transparency_2: '% 로 정하기',\n    CALC_char_at_1: '',\n    CALC_char_at_2: '의',\n    CALC_char_at_3: '번째 글자',\n    CALC_length_of_string_1: '',\n    CALC_length_of_string_2: '의 글자 수',\n    CALC_reverse_of_string_1: '',\n    CALC_reverse_of_string_2: '을(를) 뒤집은 값',\n    CALC_substring_1: '',\n    CALC_substring_2: '의',\n    CALC_substring_3: '번째 글자부터',\n    length_of_string: '번째 글자부터',\n    CALC_substring_4: '번째 글자까지의 글자',\n    CALC_replace_string_1: '',\n    CALC_replace_string_2: '의',\n    CALC_replace_string_3: '을(를)',\n    CALC_replace_string_4: '(으)로 바꾼 값',\n    CALC_change_string_case_1: '을(를)',\n    CALC_change_string_case_2: '로 바꾼 값',\n    CALC_change_string_case_sub_1: '대문자',\n    CALC_change_string_case_sub_2: '소문자',\n    CALC_count_match_string_1: '에서',\n    CALC_count_match_string_2: '의 글자 수',\n    CALC_index_of_string_1: '',\n    CALC_index_of_string_2: '에서',\n    CALC_index_of_string_3: '의 시작 위치',\n    MOVING_add_direction_by_angle_time_explain_1: '',\n    MOVING_direction_relative_duration_1: '',\n    MOVING_direction_relative_duration_2: '초 동안 이동 방향',\n    MOVING_direction_relative_duration_3: '만큼 회전하기',\n    CALC_get_sound_volume: ' 소리 크기',\n    SOUND_sound_from_to_1: '소리',\n    SOUND_sound_from_to_2: '',\n    SOUND_sound_from_to_3: '초 부터',\n    SOUND_sound_from_to_4: '초까지 재생하기',\n    SOUND_sound_from_to_and_wait_1: '소리',\n    SOUND_sound_from_to_and_wait_2: '',\n    SOUND_sound_from_to_and_wait_3: '초 부터',\n    SOUND_sound_from_to_and_wait_4: '초까지 재생하고 기다리기',\n    CALC_quotient_and_mod_1: '',\n    CALC_quotient_and_mod_2: '/',\n    CALC_quotient_and_mod_3: '의',\n    CALC_quotient_and_mod_4: '',\n    CALC_quotient_and_mod_sub_1: '몫',\n    CALC_quotient_and_mod_sub_2: '나머지',\n    self: '자신',\n    CALC_coordinate_size_value: '크기',\n    CALC_choose_project_timer_action_1: '초시계',\n    CALC_choose_project_timer_action_2: '',\n    CALC_choose_project_timer_action_sub_1: '시작하기',\n    CALC_choose_project_timer_action_sub_2: '정지하기',\n    CALC_choose_project_timer_action_sub_3: '초기화하기',\n    LOOKS_change_object_index_1: '',\n    LOOKS_change_object_index_2: '보내기',\n    LOOKS_change_object_index_sub_1: '맨 앞으로',\n    LOOKS_change_object_index_sub_2: '앞으로',\n    LOOKS_change_object_index_sub_3: '뒤로',\n    LOOKS_change_object_index_sub_4: '맨 뒤로',\n    FLOW_repeat_while_true_until: '이 될 때까지',\n    FLOW_repeat_while_true_while: '인 동안',\n    copy_block: '블록 복사',\n    delete_block: '블록 삭제',\n    tidy_up_block: '코드 정리하기',\n    block_hi: '안녕!',\n    entry_bot_name: '엔트리봇',\n    hi_entry: '안녕 엔트리!',\n    hi_entry_en: 'Hello Entry!',\n    bark_dog: '강아지 짖는 소리',\n    walking_entryBot: '엔트리봇_걷기',\n    doggi_bark: '강아지 짖는 소리',\n    entry: '엔트리',\n    hello: '안녕',\n    nice: '반가워',\n    silent: '무음',\n    do_name: '도',\n    do_sharp_name: '도#(레♭)',\n    re_name: '레',\n    re_sharp_name: '레#(미♭)',\n    mi_name: '미',\n    fa_name: '파',\n    fa_sharp_name: '파#(솔♭)',\n    sol_name: '솔',\n    sol_sharp_name: '솔#(라♭)',\n    la_name: '라',\n    la_sharp_name: '라#(시♭)',\n    DUMMY: '더미',\n    coconut_stop_motor: '모터 정지',\n    coconut_move_motor: '움직이기',\n    coconut_turn_motor: '으로 돌기',\n    coconut_move_outmotor: '외부모터',\n    coconut_turn_left: '왼쪽',\n    coconut_turn_right: '오른쪽',\n    coconut_move_forward: '앞으로',\n    coconut_move_backward: '뒤로',\n    coconut_note_c: '도',\n    coconut_note_d: '레',\n    coconut_note_e: '미',\n    coconut_note_f: '파',\n    coconut_note_g: '솔',\n    coconut_note_a: '라',\n    coconut_note_b: '시',\n    coconut_move_speed_1: '0',\n    coconut_move_speed_2: '50',\n    coconut_move_speed_3: '100',\n    coconut_move_speed_4: '150',\n    coconut_move_speed_5: '255',\n    coconut_play_buzzer_hn: '2분음표',\n    coconut_play_buzzer_qn: '4분음표',\n    coconut_play_buzzer_en: '8분음표',\n    coconut_play_buzzer_sn: '16분음표',\n    coconut_play_buzzer_tn: '32분음표',\n    coconut_play_buzzer_wn: '온음표',\n    coconut_play_buzzer_dhn: '점2분음표',\n    coconut_play_buzzer_dqn: '점4분음표',\n    coconut_play_buzzer_den: '점8분음표',\n    coconut_play_buzzer_dsn: '점16분음표',\n    coconut_play_buzzer_dtn: '점32분음표',\n    coconut_rest_buzzer_hr: '2분쉼표',\n    coconut_rest_buzzer_qr: '4분쉼표',\n    coconut_rest_buzzer_er: '8분쉼표',\n    coconut_rest_buzzer_sr: '16분쉼표',\n    coconut_rest_buzzer_tr: '32분쉼표',\n    coconut_rest_buzzer_wr: '온쉼표',\n    coconut_play_midi_1: '반짝반짝 작은별',\n    coconut_play_midi_2: '곰세마리',\n    coconut_play_midi_3: '모차르트 자장가',\n    coconut_play_midi_4: '도레미송',\n    coconut_play_midi_5: '나비야',\n    coconut_floor_sensing_on: '감지',\n    coconut_floor_sensing_off: '미감지',\n    coconut_dotmatrix_set_on: '켜짐',\n    coconut_dotmatrix_set_off: '꺼짐',\n    coconut_dotmatrix_row_0: '모든',\n    coconut_dotmatrix_row_1: '1',\n    coconut_dotmatrix_row_2: '2',\n    coconut_dotmatrix_row_3: '3',\n    coconut_dotmatrix_row_4: '4',\n    coconut_dotmatrix_row_5: '5',\n    coconut_dotmatrix_row_6: '6',\n    coconut_dotmatrix_row_7: '7',\n    coconut_dotmatrix_row_8: '8',\n    coconut_dotmatrix_col_0: '모든',\n    coconut_dotmatrix_col_1: '1',\n    coconut_dotmatrix_col_2: '2',\n    coconut_dotmatrix_col_3: '3',\n    coconut_dotmatrix_col_4: '4',\n    coconut_dotmatrix_col_5: '5',\n    coconut_dotmatrix_col_6: '6',\n    coconut_dotmatrix_col_7: '7',\n    coconut_dotmatrix_col_8: '8',\n    coconut_sensor_left_proximity: '왼쪽 전방 센서',\n    coconut_sensor_right_proximity: '오른쪽 전방 센서',\n    coconut_sensor_both_proximity: '모든',\n    coconut_sensor_left_floor: '왼쪽 바닥센서',\n    coconut_sensor_right_floor: '오른쪽 바닥 센서',\n    coconut_sensor_both_floor: '모든',\n    coconut_sensor_acceleration_x: 'x축 가속도',\n    coconut_sensor_acceleration_y: 'y축 가속도',\n    coconut_sensor_acceleration_z: 'z축 가속도',\n    coconut_sensor_light: '밝기',\n    coconut_sensor_temperature: '온도',\n    coconut_left_led: '왼쪽',\n    coconut_right_led: '오른쪽',\n    coconut_both_leds: '모든',\n    coconut_color_cyan: '하늘색',\n    coconut_color_magenta: '보라색',\n    coconut_color_black: '검은색',\n    coconut_color_white: '흰색',\n    coconut_color_red: '빨간색',\n    coconut_color_yellow: '노란색',\n    coconut_color_green: '초록색',\n    coconut_color_blue: '파란색',\n    coconut_beep: '삐 소리내기',\n    coconut_clear_buzzer: '버저 끄기',\n    coconut_x_axis: 'X축',\n    coconut_y_axis: 'Y축',\n    coconut_z_axis: 'Z축',\n    modi_enviroment_bule: '파랑',\n    modi_enviroment_green: '초록',\n    modi_enviroment_humidity: '습도',\n    modi_enviroment_illuminance: '조도',\n    modi_enviroment_red: '빨강',\n    modi_enviroment_temperature: '온도',\n    modi_gyroscope_xAcceleratior: 'X축 가속',\n    modi_gyroscope_yAcceleratior: 'Y축 가속',\n    modi_gyroscope_zAcceleratior: 'Z축 가속',\n    modi_motor_angle: '각도',\n    modi_motor_speed: '속도',\n    modi_motor_torque: '회전',\n    modi_speaker_F_DO_5: '도5',\n    modi_speaker_F_DO_6: '도6',\n    modi_speaker_F_DO_7: '도7',\n    modi_speaker_F_DO_S_5: '도#5',\n    modi_speaker_F_DO_S_6: '도#6',\n    modi_speaker_F_DO_S_7: '도#7',\n    modi_speaker_F_MI_5: '미5',\n    modi_speaker_F_MI_6: '미6',\n    modi_speaker_F_MI_7: '미7',\n    modi_speaker_F_PA_5: '파5',\n    modi_speaker_F_PA_6: '파6',\n    modi_speaker_F_PA_7: '파7',\n    modi_speaker_F_PA_S_5: '파#5',\n    modi_speaker_F_PA_S_6: '파#6',\n    modi_speaker_F_PA_S_7: '파#7',\n    modi_speaker_F_RA_5: '라5',\n    modi_speaker_F_RA_6: '라6',\n    modi_speaker_F_RA_7: '라7',\n    modi_speaker_F_RA_S_5: '라#5',\n    modi_speaker_F_RA_S_6: '라#6',\n    modi_speaker_F_RA_S_7: '라#7',\n    modi_speaker_F_RE_5: '레5',\n    modi_speaker_F_RE_6: '레6',\n    modi_speaker_F_RE_7: '레7',\n    modi_speaker_F_RE_S_5: '라#5',\n    modi_speaker_F_RE_S_6: '레#6',\n    modi_speaker_F_RE_S_7: '레#7',\n    modi_speaker_F_SOL_5: '솔5',\n    modi_speaker_F_SOL_6: '솔6',\n    modi_speaker_F_SOL_7: '솔7',\n    modi_speaker_F_SOL_S_5: '솔#5',\n    modi_speaker_F_SOL_S_6: '솔#6',\n    modi_speaker_F_SOL_S_7: '솔#7',\n    modi_speaker_F_SO_5: '시5',\n    modi_speaker_F_SO_6: '시6',\n    modi_speaker_F_SO_7: '시7',\n    si_name: '시',\n    ev3_ccw: '반시계',\n    ev3_cw: '시계',\n    rokoboard_sensor_name_0: '소리',\n    rokoboard_sensor_name_1: '빛',\n    rokoboard_sensor_name_2: '슬라이더',\n    rokoboard_sensor_name_3: '저항-A',\n    rokoboard_sensor_name_4: '저항-B',\n    rokoboard_sensor_name_5: '저항-C',\n    rokoboard_sensor_name_6: '저항-D',\n    rokoboard_string_1: '버튼을 눌렀는가?',\n    HW_MOTOR: '모터',\n    HW_SENSOR: '센서',\n    HW_LED: '발광다이오드',\n    HW_MELODY: '멜로디',\n    HW_ROBOT: '로봇',\n    ALTINO_ACCX: '가속도 X축',\n    ALTINO_ACCY: '가속도 Y축',\n    ALTINO_ACCZ: '가속도 Z축',\n    ALTINO_BAT: '배터리 잔량 체크',\n    ALTINO_CDS: '밝기',\n    ALTINO_GYROX: '자이로 X축',\n    ALTINO_GYROY: '자이로 Y축',\n    ALTINO_GYROZ: '자이로 Z축',\n    ALTINO_IR1: '1번 거리',\n    ALTINO_IR2: '2번 거리',\n    ALTINO_IR3: '3번 거리',\n    ALTINO_IR4: '4번 거리',\n    ALTINO_IR5: '5번 거리',\n    ALTINO_IR6: '6번 거리',\n    ALTINO_Led_Brake_Light: '브레이크',\n    ALTINO_Led_Forward_Light: '전방',\n    ALTINO_Led_Reverse_Light: '후방',\n    ALTINO_Led_Turn_Left_Light: '왼쪽방향',\n    ALTINO_Led_Turn_Right_Light: '오른쪽방향',\n    ALTINO_Line: '번째 줄',\n    ALTINO_MAGX: '나침판 X축',\n    ALTINO_MAGY: '나침판 Y축',\n    ALTINO_MAGZ: '나침판 Z축',\n    ALTINO_REMOTE: '리모콘 수신 값',\n    ALTINO_STTOR: '조향 토크',\n    ALTINO_STVAR: '조향 가변저항',\n    ALTINO_Steering_Angle_Center: '가운데',\n    ALTINO_Steering_Angle_Left10: '왼쪽10',\n    ALTINO_Steering_Angle_Left15: '왼쪽15',\n    ALTINO_Steering_Angle_Left20: '왼쪽20',\n    ALTINO_Steering_Angle_Left5: '왼쪽5',\n    ALTINO_Steering_Angle_Right10: '오른쪽10',\n    ALTINO_Steering_Angle_Right15: '오른쪽15',\n    ALTINO_Steering_Angle_Right20: '오른쪽20',\n    ALTINO_Steering_Angle_Right5: '오른쪽5',\n    ALTINO_TEM: '온도',\n    ALTINO_TOR1: '오른쪽 토크',\n    ALTINO_TOR2: '왼쪽 토크',\n    ALTINO_Value: '출력 값',\n    ALTINO_a: '라',\n    ALTINO_a2: '라#',\n    ALTINO_b: '시',\n    ALTINO_c: '도',\n    ALTINO_c2: '도#',\n    ALTINO_d: '레',\n    ALTINO_d2: '레#',\n    ALTINO_dot_display_1: '한문자',\n    ALTINO_dot_display_2: '출력하기',\n    ALTINO_e: '미',\n    ALTINO_f: '파',\n    ALTINO_f2: '파#',\n    ALTINO_g: '솔',\n    ALTINO_g2: '솔#',\n    ALTINO_h: '끄기',\n    ALTINO_h2: '켜기',\n    ALTINO_leftWheel: '왼쪽',\n    ALTINO_melody_ms: '연주하기',\n    ALTINO_outputValue: '출력 값',\n    ALTINO_rightWheel: '오른쪽',\n    ALTINO_set: '로 정하기',\n    ardublock_motor_forward: '앞',\n    ardublock_motor_backward: '뒤',\n    jdkit_clockwise: '시계방향',\n    jdkit_counterclockwise: '반시계방향',\n    jdkit_gyro_frontrear: '앞뒤',\n    jdkit_gyro_leftright: '좌우',\n    jdkit_joystick_leftleftright: '왼쪽 좌우',\n    jdkit_joystick_lefttopbottom: '왼쪽 상하',\n    jdkit_joystick_rightleftright: '오른쪽 좌우',\n    jdkit_joystick_righttopbottom: '오른쪽 상하',\n    jdkit_led: 'LED',\n    jdkit_led_color_green: '초록색',\n    jdkit_led_color_orange: '오랜지색',\n    jdkit_led_turnoff: '끄기',\n    jdkit_led_turnon: '켜기',\n    jdkit_motor_leftbottom: '왼쪽아래',\n    jdkit_motor_lefttop: '왼쪽위',\n    jdkit_motor_rightbottom: '오른쪽아래',\n    jdkit_motor_righttop: '오른쪽위',\n    jdkit_tune_do: '도',\n    jdkit_tune_fa: '파',\n    jdkit_tune_la: '라',\n    jdkit_tune_mi: '미',\n    jdkit_tune_re: '레',\n    jdkit_tune_si: '시',\n    jdkit_tune_sol: '솔',\n    FUNBOARD_bt_down: '노랑(B)',\n    FUNBOARD_bt_left: '초록(C)',\n    FUNBOARD_bt_right: '파랑(D)',\n    FUNBOARD_bt_up: '빨강(A)',\n    FUNBOARD_column_tag: '칸',\n    FUNBOARD_do_off: '끄기',\n    FUNBOARD_do_on: '켜기',\n    FUNBOARD_led_color_all: '모두',\n    FUNBOARD_led_color_blue: '파랑',\n    FUNBOARD_led_color_green: '초록',\n    FUNBOARD_led_color_red: '빨강',\n    FUNBOARD_led_color_str: '색',\n    FUNBOARD_led_color_yellow: '노랑',\n    FUNBOARD_led_off_str: 'LED 끄기',\n    FUNBOARD_led_on_str: 'LED 켜기',\n    FUNBOARD_row_tag: '줄',\n    FUNBOARD_scroll_down: '아래쪽으로',\n    FUNBOARD_scroll_left: '왼쪽으로',\n    FUNBOARD_scroll_no: '없음',\n    FUNBOARD_scroll_right: '오른쪽으로',\n    FUNBOARD_scroll_up: '위쪽으로',\n    FUNBOARD_sensor_cds: 'Cds (밝기 감지)',\n    FUNBOARD_sensor_mic: '마이크 (소리 감지)',\n    FUNBOARD_sensor_slide: '슬라이드 (막대 조정)',\n    FUNBOARD_sensor_state_1: '작다',\n    FUNBOARD_sensor_state_2: '크다',\n    FUNBOARD_touchbt_down: '노랑(B)',\n    FUNBOARD_touchbt_enter: '   F',\n    FUNBOARD_touchbt_escape: '   G',\n    FUNBOARD_touchbt_left: '초록(C)',\n    FUNBOARD_touchbt_right: '파랑(D)',\n    FUNBOARD_touchbt_space: '   E',\n    FUNBOARD_touchbt_up: '빨강(A)',\n    funboard_dotmatrix_set_off: '끄기',\n    funboard_dotmatrix_set_on: '켜기',\n    AI_UTILIZE: '인공지능',\n    video_show_video: '보이기',\n    video_hide_video: '숨기기',\n    video_brightness: '밝기',\n    video_transparency: '투명도',\n    video_left_right: '좌우',\n    video_top_bottom: '상하',\n    video_human: '사람',\n    video_face: '얼굴',\n    video_object: '사물',\n    video_pose_model: '사람 모델',\n    video_face_model: '얼굴 모델',\n    video_object_model: '사물 모델',\n    video_start: '시작하기',\n    video_end: '중지하기',\n    video_gender: '성별',\n    video_age: '나이',\n    video_emotion: '감정',\n    video_motion_onself: '자신',\n    video_motion_onscreen: '실행 화면',\n    video_motion_scale: '움직임',\n    video_motion_direction_horizontal: '좌우방향',\n    video_motion_direction_vertical: '상하방향',\n    table_row: '행',\n    table_col: '열',\n    table_sum: '합',\n    table_max: '최대',\n    table_min: '최소',\n    table_avg: '평균',\n    table_stdev: '표준편차',\n    table_median: '중앙값',\n    this_project: '모든',\n    this_object: '자신',\n    right_hand: '오른손',\n    left_hand: '왼손',\n    thumb: '엄지',\n    index_finger: '검지',\n    middle_finger: '중지',\n    ring_finger: '약지',\n    little_finger: '소지',\n    wrist: '손목',\n    tip: '끝',\n    dip: '첫째 마디',\n    pip: '둘째 마디',\n    none: '없음',\n    media_pipe_title_text: '비디오 감지',\n    pose_landmarker_title_text: '사람 인식',\n    face_landmarker_title_text: '얼굴 인식',\n    object_detector_title_text: '사물 인식',\n    hand_detection_title_text: '손 인식',\n    unknown: '알 수 없음',\n    CALC_timer_visible_2: '',\n    SCENE_start_scene_1: '',\n    SCENE_start_neighbor_scene_1: '',\n    yell: '외치기',\n    JUDGEMENT_reach_something_1: '',\n    JUDGEMENT_boolean_not_1: '',\n    is_type_en: '영문',\n    is_type_ko: '한글',\n    CALC_calc_rand_1: '',\n    CALC_coordinate_object_1: '',\n    CALC_quotient_and_mod_1: '',\n    CALC_calc_operation_of_1: '',\n    CALC_choose_project_timer_action_2: '',\n    CALC_get_date_2: '',\n    CALC_distance_something_1: '',\n    CALC_get_sound_duration_1: '',\n    CALC_length_of_string_1: '',\n    CALC_reverse_of_string_1: '',\n    VARIABLE_combine_something_1: '',\n    CALC_char_at_1: '',\n    CALC_substring_1: '',\n    CALC_index_of_string_1: '',\n    CALC_replace_string_1: '',\n    CALC_change_string_case_1: '',\n    VARIABLE_value_of_index_from_list_1: '',\n    VARIABLE_length_of_list_1: '',\n    VARIABLE_is_included_in_list_1: '',\n    tts_sabina: '마녀',\n    tts_mammon: '악마',\n    tts_kitty: '야옹이',\n    tts_doggy: '멍멍이',\n    location_entire: '전체',\n    location_seoul: '서울',\n    location_seoul_jongno_gu: '종로구',\n    location_seoul_jung_gu: '중구',\n    location_seoul_yongsan_gu: '용산구',\n    location_seoul_seongdong_gu: '성동구',\n    location_seoul_gwangjin_gu: '광진구',\n    location_seoul_dongdaemun_gu: '동대문구',\n    location_seoul_jungnang_gu: '중랑구',\n    location_seoul_seongbuk_gu: '성북구',\n    location_seoul_gangbuk_gu: '강북구',\n    location_seoul_dobong_gu: '도봉구',\n    location_seoul_nowon_gu: '노원구',\n    location_seoul_eunpyeong_gu: '은평구',\n    location_seoul_seodaemun_gu: '서대문구',\n    location_seoul_mapo_gu: '마포구',\n    location_seoul_yangcheon_gu: '양천구',\n    location_seoul_gangseo_gu: '강서구',\n    location_seoul_guro_gu: '구로구',\n    location_seoul_geumcheon_gu: '금천구',\n    location_seoul_yeongdeungpo_gu: '영등포구',\n    location_seoul_dongjak_gu: '동작구',\n    location_seoul_gwanak_gu: '관악구',\n    location_seoul_seocho_gu: '서초구',\n    location_seoul_gangnam_gu: '강남구',\n    location_seoul_songpa_gu: '송파구',\n    location_seoul_gangdong_gu: '강동구',\n    location_gangwon: '강원',\n    location_gangwon_chuncheon: '춘천시',\n    location_gangwon_wonju: '원주시',\n    location_gangwon_gangneung_si: '강릉시',\n    location_gangwon_donghae: '동해시',\n    location_gangwon_taebaek_si: '태백시',\n    location_gangwon_sokcho: '속초시',\n    location_gangwon_samcheok_si: '삼척시',\n    location_gangwon_hongcheon: '홍천군',\n    location_gangwon_hoengseong_gun: '횡성군',\n    location_gangwon_yeongwol_gun: '영월군',\n    location_gangwon_pyeongchang: '평창군',\n    location_gangwon_jeongseon: '정선군',\n    location_gangwon_cheolwon: '철원군',\n    location_gangwon_hwacheon: '화천군',\n    location_gangwon_yanggu: '양구군',\n    location_gangwon_inje: '인제군',\n    location_gangwon_goseong: '고성군',\n    location_gangwon_yangyang: '양양군',\n    location_gyeonggi: '경기',\n    location_gyeonggi_suwon_si: '수원시',\n    location_gyeonggi_seongnam: '성남시',\n    location_gyeonggi_uijeongbu: '의정부시',\n    location_gyeonggi_anyang_si: '안양시',\n    location_gyeonggi_bucheon_si: '부천시',\n    location_gyeonggi_gwangmyeong_si: '광명시',\n    location_gyeonggi_pyeongtaek_si: '평택시',\n    location_gyeonggi_dongducheon_si: '동두천시',\n    location_gyeonggi_ansan_si: '안산시',\n    location_gyeonggi_goyang_si: '고양시',\n    location_gyeonggi_gwacheon_si: '과천시',\n    location_gyeonggi_guri: '구리시',\n    location_gyeonggi_namyangju_si: '남양주시',\n    location_gyeonggi_osan: '오산시',\n    location_jeollanam_goheung: '고흥군',\n    location_gyeonggi_siheung: '시흥시',\n    location_jeollanam_boseong: '보성군',\n    location_jeollanam_hwasun: '화순군',\n    location_gyeonggi_gunpo_si: '군포시',\n    location_jeollanam_jangheung: '장흥군',\n    location_gyeonggi_uiwang_si: '의왕시',\n    location_jeollanam_gangjin: '강진군',\n    location_gyeonggi_hanam: '하남시',\n    location_jeollanam_haenam: '해남군',\n    location_gyeonggi_yongin_si: '용인시',\n    location_jeollanam_yeongam: '영암군',\n    location_gyeonggi_paju: '파주시',\n    location_jeollanam_jindo: '무안군',\n    location_gyeonggi_icheon: '이천시',\n    location_jeollanam_muan: '함평군',\n    location_jeollanam_hampyeong: '영광군',\n    location_gyeonggi_anseong_si: '안성시',\n    location_jeollanam_yeonggwang: '장성군',\n    location_gyeonggi_gimpo: '김포시',\n    location_jeollanam_jangseong: '완도군',\n    location_gyeonggi_hwaseong_si: '화성시',\n    location_jeollanam_wando: '진도군',\n    location_gyeonggi_gwangju: '광주시',\n    location_jeollanam_sinan: '신안군',\n    location_jeollabuk: '전북',\n    location_gyeonggi_yangju_si: '양주시',\n    location_jeollabuk_jeonju: '전주시',\n    location_gyeonggi_pocheon: '포천시',\n    location_jeollabuk_gunsan_si: '군산시',\n    location_gyeonggi_yeoju: '여주시',\n    location_jeollabuk_iksan: '익산시',\n    location_gyeonggi_yeoncheon_gun: '연천군',\n    location_gyeonggi_gapyeong_gun: '가평군',\n    location_jeollabuk_jeongeup: '정읍시',\n    location_gyeonggi_yangpyeong: '양평군',\n    location_jeollabuk_namwon: '남원시',\n    location_gyeongsangnam: '경남',\n    location_jeollabuk_gimje_si: '김제시',\n    location_gyeongsangnam_changwon_si: '창원시',\n    location_jeollabuk_wanju: '완주군',\n    location_gyeongsangnam_jinju: '진주시',\n    location_jeollabuk_jinan: '진안군',\n    location_gyeongsangnam_tongyeong_si: '통영시',\n    location_jeollabuk_muju: '무주군',\n    location_gyeongsangnam_sacheon_si: '사천시',\n    location_jeollabuk_jangsu: '장수군',\n    location_gyeongsangnam_gimhae_si: '김해시',\n    location_jeollabuk_imsil: '임실군',\n    location_gyeongsangnam_miryang_si: '밀양시',\n    location_jeollabuk_sunchang: '순창군',\n    location_gyeongsangnam_geoje_si: '거제시',\n    location_jeollabuk_gochang: '고창군',\n    location_gyeongsangnam_yangsan_si: '양산시',\n    location_jeollabuk_buan: '부안군',\n    location_gyeongsangnam_uiryeong: '의령군',\n    location_jeju: '제주',\n    location_gyeongsangnam_haman: '함안군',\n    location_jeju_jeju_si: '제주시',\n    location_gyeongsangnam_changnyeong: '창녕군',\n    location_jeju_seogwipo: '서귀포시',\n    location_gyeongsangnam_goseong: '고성군',\n    location_gyeongsangnam_namhae: '남해군',\n    location_chungcheongnam: '충남',\n    location_gyeongsangnam_hadong: '하동군',\n    location_chungcheongnam_cheonan: '천안시',\n    location_gyeongsangnam_sancheong: '산청군',\n    location_chungcheongnam_gongju: '공주시',\n    location_gyeongsangnam_hamyang: '함양군',\n    location_gyeongsangnam_geochang: '거창군',\n    location_chungcheongnam_boryeong: '보령시',\n    location_gyeongsangnam_hapcheon: '합천군',\n    location_chungcheongnam_asan: '아산시',\n    location_gyeongsangbuk: '경북',\n    location_chungcheongnam_seosan: '서산시',\n    location_gyeongsangbuk_pohang_si: '포항시',\n    location_gyeongsangbuk_gyeongju_si: '경주시',\n    location_chungcheongnam_nonsan: '논산시',\n    location_gyeongsangbuk_gimcheon_si: '김천시',\n    location_chungcheongnam_gyeryong: '계룡시',\n    location_gyeongsangbuk_andong_si: '안동시',\n    location_chungcheongnam_dangjin: '당진시',\n    location_gyeongsangbuk_gumi_si: '구미시',\n    location_gyeongsangbuk_yeongju_si: '영주시',\n    location_chungcheongnam_geumsan: '금산군',\n    location_chungcheongnam_buyeo: '부여군',\n    location_gyeongsangbuk_yeongcheon_si: '영천시',\n    location_chungcheongnam_seocheon: '서천군',\n    location_gyeongsangbuk_sangju_si: '상주시',\n    location_chungcheongnam_cheongyang: '청양군',\n    location_gyeongsangbuk_mungyeong_si: '문경시',\n    location_gyeongsangbuk_gyeongsan_si: '경산시',\n    location_chungcheongnam_hongseong: '홍성군',\n    location_chungcheongnam_yesan: '예산군',\n    location_gyeongsangbuk_uiseong: '의성군',\n    location_chungcheongnam_taean: '태안군',\n    location_gyeongsangbuk_cheongsong: '청송군',\n    location_chungcheongbuk: '충북',\n    location_gyeongsangbuk_goryong: '영양군',\n    location_chungcheongbuk_cheongju: '청주시',\n    location_gyeongsangbuk_yeongdeok: '영덕군',\n    location_gyeongsangbuk_cheongdo: '청도군',\n    location_chungcheongbuk_chungju: '충주시',\n    location_gyeongsangbuk_golyeong: '고령군',\n    location_chungcheongbuk_jecheon: '제천시',\n    location_gyeongsangbuk_seongju: '성주군',\n    location_chungcheongbuk_boeun: '보은군',\n    location_gyeongsangbuk_chilgok: '칠곡군',\n    location_chungcheongbuk_okcheon: '옥천군',\n    location_gyeongsangbuk_yecheon: '예천군',\n    location_chungcheongbuk_yeongdong: '영동군',\n    location_gyeongsangbuk_bonghwa: '봉화군',\n    location_chungcheongbuk_jeungpyeong: '증평군',\n    location_gyeongsangbuk_uljin: '울진군',\n    location_chungcheongbuk_jincheon: '진천군',\n    location_gyeongsangbuk_ulleung: '울릉군',\n    location_chungcheongbuk_goesan: '괴산군',\n    location_gwangju: '광주',\n    location_chungcheongbuk_eumseong: '음성군',\n    location_gwangju_dong_gu: '동구',\n    location_chungcheongbuk_danyang: '단양군',\n    location_gwangju_seo_gu: '서구',\n    location_gwangju_nam_gu: '남구',\n    location_gwangju_buk_gu: '북구',\n    location_gwangju_gwangsan_gu: '광산구',\n    location_daegu: '대구',\n    location_daegu_jung_gu: '중구',\n    location_daegu_dong_gu: '동구',\n    location_daegu_seo_gu: '서구',\n    location_daegu_nam_gu: '남구',\n    location_daegu_buk_gu: '북구',\n    location_daegu_suseong_gu: '수성구',\n    location_daegu_dalseo_gu: '달서구',\n    location_daegu_dalseong: '달성군',\n    location_daegu_gunwi: '군위군',\n    location_daejeon: '대전',\n    location_daejeon_dong_gu: '동구',\n    location_daejeon_jung_gu: '중구',\n    location_daejeon_seo_gu: '서구',\n    location_daejeon_yuseong_gu: '유성구',\n    location_daejeon_daedeok_gu: '대덕구',\n    location_busan: '부산',\n    location_busan_jung_gu: '중구',\n    location_busan_seo_gu: '서구',\n    location_busan_dong_gu: '동구',\n    location_busan_yeongdo_gu: '영도구',\n    location_busan_busanjin_gu: '부산진구',\n    location_busan_dongnae_gu: '동래구',\n    location_busan_nam_gu: '남구',\n    location_busan_buk_gu: '북구',\n    location_busan_haeundae_gu: '해운대구',\n    location_busan_saha_gu: '사하구',\n    location_busan_geumjeong_gu: '금정구',\n    location_busan_gangseo_gu: '강서구',\n    location_busan_yeonje: '연제구',\n    location_busan_suyeong_gu: '수영구',\n    location_busan_sasang_gu: '사상구',\n    location_busan_gijang: '기장군',\n    location_sejong: '세종',\n    location_ulsan: '울산',\n    location_ulsan_jung_gu: '중구',\n    location_ulsan_nam_gu: '남구',\n    location_ulsan_dong_gu: '동구',\n    location_ulsan_buk_gu: '북구',\n    location_ulsan_ulju: '울주군',\n    location_incheon: '인천',\n    location_incheon_jung_gu: '중구',\n    location_incheon_dong_gu: '동구',\n    location_incheon_nam_gu: '미추홀구',\n    location_incheon_yeonsu_gu: '연수구',\n    location_incheon_namdong_gu: '남동구',\n    location_incheon_bupyeong_gu: '부평구',\n    location_incheon_gyeyang_gu: '계양구',\n    location_incheon_seo_gu: '서구',\n    location_incheon_ganghwa: '강화군',\n    location_incheon_ongjin_gun: '옹진군',\n    location_jeollanam: '전남',\n    location_jeollanam_mokpo: '목포시',\n    location_jeollanam_yosu: '여수시',\n    location_jeollanam_suncheon_si: '순천시',\n    location_jeollanam_naju: '나주시',\n    location_jeollanam_gwangyang_si: '광양시',\n    location_jeollanam_damyang: '담양군',\n    location_jeollanam_gokseong: '곡성군',\n    location_jeollanam_gurye: '구례군',\n    width: '가로',\n    height: '세로',\n    desktop: '데스크톱',\n    tablet: '태블릿',\n    smartphone: '스마트폰',\n};\nLang.video_body_coord_params = {\n    left_eye: '왼쪽 눈',\n    right_eye: '오른쪽 눈',\n    nose: '코',\n    left_mouth: '왼쪽 입꼬리',\n    right_mouth: '오른쪽 입꼬리',\n    upper_lip: '윗 입술',\n    lower_lip: '아랫 입술',\n    face: '얼굴',\n    neck: '목',\n    left_ear: '왼쪽 귀',\n    right_ear: '오른쪽 귀',\n    left_shoulder: '왼쪽 어깨',\n    left_elbow: '왼쪽 팔꿈치',\n    left_wrist: '왼쪽 손목',\n    left_hip: '왼쪽 엉덩이',\n    left_knee: '왼쪽 무릎',\n    left_ankle: '왼쪽 발목',\n    right_shoulder: '오른쪽 어깨',\n    right_elbow: '오른쪽 팔꿈치',\n    right_wrist: '오른쪽 손목',\n    right_hip: '오른쪽 엉덩이',\n    right_knee: '오른쪽 무릎',\n    right_ankle: '오른쪽 발목',\n};\nLang.video_gender = {\n    male: '남성',\n    female: '여성',\n};\nLang.video_emotion_params = {\n    angry: '분노',\n    disgusted: '혐오',\n    fearful: '두려움',\n    happy: '행복',\n    neutral: '무표정',\n    sad: '슬픔',\n    surprised: '놀람',\n    disgust: '혐오',\n    fear: '두려움',\n    surprise: '놀람',\n};\nLang.video_object_params = {\n    person: '사람',\n    bicycle: '자전거',\n    car: '자동차',\n    motorcycle: '오토바이',\n    airplane: '비행기',\n    bus: '버스',\n    train: '기차',\n    truck: '트럭',\n    boat: '보트',\n    'traffic light': '신호등',\n    'fire hydrant': '소화전',\n    'stop sign': '정지 표지판',\n    'parking meter': '주차 미터기',\n    bench: '벤치',\n    bird: '새',\n    cat: '고양이',\n    dog: '개',\n    horse: '말',\n    sheep: '양',\n    cow: '소',\n    elephant: '코끼리',\n    bear: '곰',\n    zebra: '얼룩말',\n    giraffe: '기린',\n    backpack: '배낭',\n    umbrella: '우산',\n    handbag: '핸드백',\n    tie: '넥타이',\n    suitcase: '여행 가방',\n    frisbee: '원반',\n    skis: '스키',\n    snowboard: '스노우보드',\n    'sports ball': '공',\n    kite: '연',\n    'baseball bat': '야구 배트',\n    'baseball glove': '야구 글러브',\n    skateboard: '스케이트보드',\n    surfboard: '서프보드',\n    'tennis racket': '테니스 라켓',\n    bottle: '병',\n    'wine glass': '와인잔',\n    cup: '컵',\n    fork: '포크',\n    knife: '나이프',\n    spoon: '숟가락',\n    bowl: '그릇',\n    banana: '바나나',\n    apple: '사과',\n    sandwich: '샌드위치',\n    orange: '오렌지',\n    broccoli: '브로콜리',\n    carrot: '당근',\n    'hot dog': '핫도그',\n    pizza: '피자',\n    donut: '도넛',\n    cake: '케이크',\n    chair: '의자',\n    couch: '소파',\n    'potted plant': '화분',\n    bed: '침대',\n    'dining table': '식탁',\n    toilet: '변기',\n    tv: 'TV',\n    laptop: '노트북',\n    mouse: '마우스',\n    remote: '리모컨',\n    keyboard: '키보드',\n    'cell phone': '핸드폰',\n    microwave: '전자레인지',\n    oven: '오븐',\n    toaster: '토스터',\n    sink: '싱크대',\n    refrigerator: '냉장고',\n    book: '책',\n    clock: '시계',\n    vase: '꽃병',\n    scissors: '가위',\n    'teddy bear': '테디베어',\n    'hair drier': '헤어드라이어',\n    toothbrush: '칫솔',\n};\nLang.Buttons = {\n    share_policy: '이것만은 꼭!',\n    write_policy: '작성 가이드',\n    lesson_list: '강의 목록',\n    complete_study: '학습 완료하기',\n    show_me: '미리 보기',\n    do_this_for_me: '대신 해주기',\n    previous: '이전',\n    get_started: '시작하기',\n    next_lesson: '다음 내용 학습하기',\n    course_submit: '제출하기',\n    course_done: '확인',\n    mission: '미션 확인하기',\n    basic_guide: '기본 사용 방법',\n    apply: '적용하기',\n    add: '추가',\n    cancel: '취소',\n    save: '저장',\n    start: '시작',\n    confirm: '확인',\n    delete: '삭제',\n    create: '학급 만들기',\n    done: '완료',\n    accept: '수락',\n    refuse: '거절',\n    yes: '예',\n    button_no: '아니오',\n    quiz_retry: '다시 풀어보기',\n    discuss_upload: '불러오기',\n    maze_popup_guide: '이용안내',\n    maze_popup_mapHint: '힌트보기',\n    maze_hint_btn_guide: '이용 안내',\n    maze_hint_btn_block: '블록 도움말',\n    maze_hint_btn_map: '힌트 보기',\n    maze_hint_btn_goal: '목표',\n    list_save: '저장하기',\n    duplication: '복사하기',\n    export_to_excel: '엑셀로 내려받기',\n    convert_table: '테이블로 만들기',\n    single_line: '한 줄 쓰기',\n    multi_line: '여러 줄 쓰기',\n    lecture_finish_popup_reset_lecture: '처음부터 다시하기',\n    lecture_finish_popup_show_output: '실습한 코드보기',\n    lecture_view_hints: '잘 모르겠어요!',\n    default_hint_title: '어떻게 만들까?',\n    show_only_vector: '벡터 모아보기',\n    sound_menu_trim: '다듬기',\n    sound_menu_adjust: '조정하기',\n    sound_button_reset: '원래대로',\n    sound_button_save: '저장하기',\n    back: '뒤로가기',\n    add2: '추가하기',\n    load: '불러오기',\n    move: '이동하기',\n    create_new_table: '테이블 새로 만들기',\n    add_variable: '변수 추가',\n    add_list: '리스트 추가',\n    add_message: '신호 추가',\n};\nLang.Menus = {\n    ask_captcha: '아래 이미지를 보이는 대로 입력해주세요.',\n    refresh: '새로고침',\n    check_image_captcha: '이미지로 보기',\n    check_sound_captcha: '음성으로 듣기',\n    nothing_to_import: '불러오기 할 항목이 없습니다.',\n    nothing_to_export: '내려받기 할 항목이 없습니다.',\n    content_copied: '내용이 복사되었습니다.',\n    list_import_title: '리스트 불러오기',\n    list_import_placeholder: '예)\\r\\n항목1\\r\\n항목2\\r\\n항목3',\n    verifying_email: '인증 메일 발송하기',\n    list_import_notice_1: '리스트의 항목과 내용(기본값)을 한꺼번에 작성할 수 있습니다.',\n    list_import_notice_2: '기존 내용은 사라지고 여기서 작성한 내용만 저장됩니다.',\n    list_export_title: '리스트 내보내기',\n    list_export_notice1: '아래에서 리스트의 내용을 직접 복사하거나,',\n    list_export_notice2: '파일로 내보내거나,작품의 테이블로 만들 수 있습니다.',\n    list_export_notice: '리스트 항목의 내용을 복사하거나, 엑셀로 내려받을 수 있습니다.',\n    robotis_opencm70: '로보티즈 IoT',\n    cannnot_mark_favorite: '비공개 작품은 관심 작품으로 지정할 수 없습니다.',\n    enterPassword: '비밀번호를 입력해주세요.',\n    enterPassword_update: '변경 내용을 저장하기 위해 비밀번호를 입력해주세요.',\n    enterNewPassword: '새로운 비밀번호를 입력하세요.',\n    reEnterNewPassword: '새로운 비밀번호를 다시 입력하세요.',\n    resign: '회원탈퇴',\n    check_sended_email: '발송된 인증 메일을 확인하여 이메일 주소를 인증해 주세요.',\n    signUpEmail_1: '입력된 이메일 주소로 인증 메일이 발송되었습니다.',\n    signUpEmail_2: '이메일 주소를 인증해주세요.',\n    select_email_unauthenticated_user:\n        '해당 이메일 주소가 아래 계정에 등록되어 있습니다.\\n인증을 원하는 계정을 선택해주세요.',\n    select_user: '계정을 선택해주세요.',\n    enter_password_withdraw: '회원탈퇴 신청을 위해 비밀번호를 입력해주세요.',\n    instruction_agree: '안내 사항에 동의해주세요.',\n    check_instructions: '위 안내 사항에 동의합니다.',\n    deleteAccount_2:\n        '회원탈퇴를 신청하신 30일 이후에는 회원정보와 작품/강의/학급/게시글/댓글/좋아요/관심 정보가 모두 삭제되며 복구가 불가능합니다.',\n    deleteAccount_1:\n        '회원탈퇴를 신청하신 30일 이내에 로그인하시면 회원탈퇴를 취소하실 수 있습니다.',\n    protect_account: '안전한 비밀번호로 내정보를 보호하세요.',\n    please_verify: '인증 메일을 발송하여 이메일 주소를 인증해 주세요.',\n    unverified_email: '이메일 주소가 인증되지 않았습니다.',\n    deleteAccount: '회원탈퇴 신청',\n    corporatePersonal: '개인정보 이전에 동의 합니다',\n    corporateTransferGuide: \"개인정보 양수자('엔트리' 웹사이트 운영자) 안내\",\n    corporateReciever: '개인정보를 이전 받은 자: 재단법인 커넥트',\n    corporateAddress: '커넥트 주소 및 연락처',\n    corporateAddress_1: '서울시 강남구 강남대로 382 메리츠타워 7층',\n    corporateConsent: '개인정보의 이전을 원치 않으시는 경우 ,동의 철회 방법',\n    corporateEmail: '계정에 등록된 이메일로 탈퇴 요청 메일 발송',\n    corporateAddition: '또한 , 영업 양도에 따라 약관 등이 아래와 같이 변경될 예정입니다.',\n    corporateApplicationDate: '적용시기 : 2017년 10월 29일',\n    corporateTargetChanges: '적용대상 및 변경사항 :',\n    corporateTarget: '적용대상',\n    corporateChanges: '변경사항',\n    corporateTerms: '엔트리 이용약관',\n    corporateOperator: '웹사이트 운영자의 명칭 변경',\n    corporateClassroomTerms: '학급 서비스 이용약관',\n    doAgreeWithClassroomTerms: '학급 서비스 이용약관에 동의합니다.',\n    doChangePassword: '나만 알수 있는 비밀번호로 변경해주세요.',\n    corporatePrivacyPolicy: '개인정보 처리방침',\n    corporateConsignment: '웹사이트 운영자의 명칭 변경 및 개인정보 위탁 업체 추가',\n    corporateEntrusted: '수탁업: NHN Technology Service(주)',\n    corporateConsignmentDetails: '위탁업무 내용: 서비스 개발 및 운영',\n    corporatePeriod: '보유기간 : 회원 탈퇴 시 혹은 위탁 계약 종료시 까지',\n    corporateChangeDate: '변경 적용일 : 2017년 10월 29일 부',\n    corporateWarning: '개인정보 이전에 동의해 주세요.',\n    corporateConfirm: '확인',\n    corporateTitle:\n        '안녕하세요. 엔트리교육연구소입니다. <br>“엔트리”를 이용하고 계신 회원 여러분께 깊은 감사의 말씀을 드립니다.<br> 엔트리교육연구소는 그동안 공익 목적으로 운영해오던 “엔트리” 웹사이트의 운영을<br> 네이버가 설립한 비영리 재단인 커넥트재단에 양도하기로 합의하였습니다. <br>앞으로 엔트리는 커넥트재단에서 공익 목적 하에 지속적으로 운영될 수 있도록 <br>할 것이며, 회원 여러분께서는 기존과 동일하게 엔트리를 이용하실 수 있습니다.<br> 웹사이트 제공 주체가 엔트리교육연구소에서 커넥트재단으로 변경됨에 따라 아래와 <br>같이 회원 개인 정보에 대한 이전이 있으며, 본 합의에 의해 실제 개인 정보의 위치가 <br>물리적으로 이동한 것은 아님을 알려드립니다. ',\n    textcoding_numberError_f:\n        '등록된 함수 중에 이름의 첫 글자가 숫자인 함수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1f: '등록된 함수 중에 이름이 ',\n    textcoding_bookedError_2f: '인 함수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_f:\n        \"등록된 함수 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    textcoding_numberError_v:\n        '등록된 변수 중에 이름의 첫 글자가 숫자인 변수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1v: '등록된 변수 중에 변수 이름이 ',\n    textcoding_bookedError_2v: '인 변수가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_v:\n        \"등록된 변수 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    textcoding_numberError_l:\n        '등록된 리스트 중에 이름의 첫 글자가 숫자인 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_bookedError_1l: '등록된 리스트 중에 리스트 이름이 ',\n    textcoding_bookedError_2l: '인 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    textcoding_specialCharError_l:\n        \"등록된 리스트 중 이름에 '_' 를 제외한 특수 문자가 있으면 모드 변환을 할 수 없습니다.\",\n    no_discuss_permission: '글을 읽을 권한이 없습니다',\n    delete_comment: '댓글을 삭제하시겠습니까?',\n    delete_article: '게시물을 삭제하시겠습니까?',\n    discuss_cannot_edit: '본인의 게시물이 아닙니다.',\n    discuss_extention: '실행파일은 첨부하실 수 없습니다.',\n    delete_discuss_picture: '사진을 삭제하시겠습니까?',\n    delete_discuss_file: '파일을 삭제하시겠습니까?',\n    discuss_save_question: '글을 저장하시겠습니까?',\n    discuss_cancle_question: '작성을 취소하시겠습니까?',\n    discuss_saved: '이(가) 저장되었습니다.',\n    discuss_no_write_permission: '현재 로그인된 계정으로는 글을 작성하실 수 없습니다.',\n    discuss_no_project_permission: '현재 로그인된 계정으로는 작품을 게시하실 수 없습니다.',\n    discuss_write_abuse_detected:\n        '짧은 시간안에 여러 글이 작성되었습니다.\\n1분 뒤에 다시 시도해주세요.',\n    contents_abuse_detected: '5분 뒤에 다시 시도해주세요.',\n    contents_abuse_detected_10: '10분 뒤에 다시 시도해주세요.',\n    discuss_new_write_abuse_warn:\n        '짧은 시간안에 새 글을 작성하는 경우 \\n게시글 작성이 제한될 수 있습니다. \\n이용에 주의하시길 바랍니다.',\n    discuss_write_abuse_warn:\n        '짧은 시간안에 여러 댓글을 작성하는 경우 \\n댓글 작성이 제한될 수 있습니다. \\n이용에 주의하시길 바랍니다.',\n    find_not_your_email: '올바른 이메일을 입력해주세요.',\n    search_lang: '검색',\n    search_title: '제목',\n    faq_desc: '엔트리를 이용하면서 궁금한 점들의 답변을 확인해보세요.',\n    faq_all: '전체보기',\n    faq_site: '사이트 이용',\n    faq_project: '작품 만들기',\n    faq_hardware: '하드웨어',\n    faq_offline: '오프라인',\n    faq_copyright: '저작권',\n    faq_title: '자주하는 질문',\n    faq: '자주하는 질문',\n    malicious_warning:\n        '불건전한 사진은 불러올 수 없습니다. 불건전한 사진이 아닌 경우 제안 및 건의에 해당 사진을 첨부하여 신고해주세요.',\n    fword_alert_msg: '욕설이나 불건전한 글은 게시할 수 없습니다.',\n    fword_alert_1: '주제와 무관한 욕설이나 악플은 게시할 수 없습니다.',\n    fword_alert_2: '불건전한 단어가 포함되어 있어, 대체 문장으로 게시 됩니다.',\n    fword_replace_1: '엔트리를 통해 누구나 쉽고 재미있게 소프트웨어를 배울 수 있어요.',\n    fword_replace_2: '소프트웨어 교육의 첫걸음, 엔트리.',\n    fword_replace_3: '재미있게 배우는 학습 공간 엔트리!',\n    fword_replace_4: '엔트리에서 공유와 협업을 통해 멋진 작품을 만들어요.',\n    fword_replace_5:\n        '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있게 개발된 소프트웨어 교육 플랫폼입니다.',\n    fword_replace_6: '엔트리와 함께 건강한 소프트웨어 교육 생태계를 조성해요!',\n    fword_replace_7: '엔트리에서 학습하고, 만들고, 공유하며 같이 성장해요.',\n    solve_quiz: '퀴즈 풀기',\n    submit_homework_first_title: '완성! 과제 제출하기',\n    submit_homework_first_content:\n        '멋진 작품이 완성되었습니다. 과제를 제출하세요. 마감 기한 전까지 다시 제출할 수 있습니다.',\n    submit_homework_again_title: '과제 다시 제출하기',\n    submit_homework_again_content: '이미 제출한 과제입니다.<br>과제를 다시 제출하시겠습니까?',\n    submit_homework_expired_title: '과제 제출 마감',\n    submit_homework_expired_content: '과제 제출이 마감되었습니다.',\n    done_study_title: '완성',\n    done_study_content: '만든 작품을 실행해 봅시다.',\n    featured_courses: '추천 강의 모음',\n    follow_along: '따라하기',\n    follow_along_desc: '차근차근 따라하며 다양한 작품을 만듭니다.',\n    do_quiz: '퀴즈풀기',\n    do_quiz_desc: '학습한 내용을 잘 이해했는지 퀴즈를 통해 확인합니다.',\n    challenge: '도전하기',\n    play: '도전하기',\n    challenge_desc: '주어진 문제를 스스로 해결하며 개념을 익힙니다.',\n    creste_freely: '자유롭게 만들기',\n    creste_freely_desc: '학습한 내용으로 나만의 작품을 자유롭게 만듭니다.',\n    entry_rc_desc:\n        '프로그래밍의 원리를 학습단계에 맞게 배울 수 있는 엔트리 강의 모음! 지금 시작해보세요!<br>따라하고, 도전하며 소프트웨어를 만들다 보면 어렵게 느껴졌던 프로그래밍의 원리도 쉽고 재미있게 다가옵니다!',\n    hw_deadline: '마감 일자',\n    rc_course_desc:\n        '프로그래밍의 원리를 학습단계에 맞게 배울 수 있도록 구성된 엔트리 강의 모음입니다.',\n    rc_course: '추천 강의 모음',\n    entry_rec_course: '엔트리 추천 강의 모음',\n    entry_rec_course_desc:\n        '누구나 쉽게 보고 따라하면서 재미있고 다양한 소프트웨어를 만들 수 있는 엔트리 강의를 소개합니다.',\n    guidance: '안내',\n    wait: '잠깐',\n    hint: '힌트',\n    concept_guide: '개념 톡톡',\n    group_quiz: '우리 반 퀴즈',\n    fail_check_hint: '앗… 실패! 다시 한 번 도전해보세요!<br>어려울 땐 [힌트]를 확인해보세요!',\n    sort_student: '학생별',\n    sort_lesson: '강의별',\n    sort_course: '강의 모음별',\n    student_progress: '우리 반 진도',\n    my_progress: '나의 진도',\n    lec_in_progress: '학습 중',\n    free_modal_asgn_over: '과제 제출이 마감되었습니다.',\n    free_submission_closed: '과제 제출 마감',\n    free_modal_asgn_submit_first:\n        '멋진 작품이 완성되었습니다! 과제를 제출하세요.<br>마감 기한 전까지 다시 제출 할 수 있습니다.',\n    asgn_submit: '완성! 과제 제출하기',\n    free_modal_content_resubmit: '이미 제출한 과제입니다.<br>과제를 다시 제출하시겠습니까?',\n    asgn_resubmit: '과제 다시 제출하기',\n    free_modal_content_complete: '멋진 작품이 완성되었습니다.',\n    guide_modal_content_complete: '만든 작품을 실행해 봅시다.',\n    success: '성공',\n    fail: '실패',\n    mission_modal_content_fail: '<br>어려울 땐 [힌트]를 확인해보세요!',\n    mission_modal_content_success: '만든 작품을 실행해 봅시다.',\n    in_progress: '진행중',\n    completed: '완료',\n    basic2: '미학습',\n    in_progress2: '학습중',\n    submitted: '제출 완료',\n    submission_closed: '마감',\n    lecture_progress_describe: '강의명을 누르면 해당 강의로 이동합니다.',\n    progress: '진행 상황',\n    study_completed: '학습 완료',\n    view_course_desc: '코스웨어 설명 보기',\n    main_entry_starter: '기초부터! 엔트리 스타터',\n    main_entry_booster: '개념탄탄! 엔트리 부스터',\n    main_entry_master: '생각을 펼치는! 엔트리 마스터',\n    no_students_in_classroom:\n        '아직 등록된 학생이 없습니다.<br>학생을 직접 추가하거나, 초대해 보세요!',\n    lectures: '강의',\n    Lectures: '강의',\n    studentHomeworkList: '과제',\n    curriculums: '강의 모음',\n    Curriculums: '강의 모음',\n    quiz: '퀴즈',\n    no_added_group_contents_teacher:\n        '추가된 %1이(가) 없습니다. <br>우리 반 %1을(를) 추가해 주세요.',\n    no_added_group_contents_student:\n        '아직 올라온 %1이(가) 없습니다. 선생님이 %1을(를) 올려주시면, 학습 내용을 확인할 수 있습니다.',\n    side_project: '목표 작품',\n    custom_make_course_1: \"'오픈 강의 만들기> 강의 모음 만들기'에서\",\n    custom_make_course_2: '나만의 강의 모음을 만들어 보세요.',\n    custom_make_lecture_1: \"'오픈 강의 만들기'에서\",\n    custom_make_lecture_2: '나만의 강의를 만들어 보세요',\n    alert_enter_info: '수정할 정보를 입력해주세요.',\n    alert_enter_new_pwd: '기존 비밀번호와 다른 비밀번호를 입력해주세요.',\n    alert_match_pwd: '새로운 비밀번호와 재입력된 비밀번호가 일치하지 않습니다.',\n    alert_check_pwd: '비밀번호를 확인해주세요.',\n    alert_update_complete: '정보가 수정 되었습니다.',\n    no_group_contents_each_prefix: '우리반 ',\n    no_group_contents_each_suffix: ' 이(가) 없습니다.',\n    no_group_contents_all:\n        '학급에 올라온 컨텐츠가 없습니다.<br>학급 공유하기에<br>나만의 작품을 공유해보세요!',\n    hw_closed: '과제 마감',\n    tag_Lecture: '강의',\n    tag_Curriculum: '강의모음',\n    tag_Discuss: '공지',\n    count_ko: '개',\n    no_asgn_within_week: '1주일안에 제출되어야 하는 마감 임박한 과제가 없습니다.',\n    lecture_and_curriculum: '강의 / 강의 모음',\n    assignments_plural: '과제',\n    assignments_singular: '과제',\n    project_plural: '작품',\n    group_news: '새로운 소식',\n    stu_management: '학생 관리',\n    stu_management_camel: '학생 관리',\n    view_all: '전체 보기',\n    view_all_camel: '전체 보기',\n    view_contents_camel: '콘텐츠 보기',\n    view_contents: '콘텐츠 보기',\n    no_updated_news: '나의 학급에 올라온 새로운 소식이 없습니다.',\n    homework_soon_due: '곧 마감 과제',\n    new_homework: '최신 과제',\n    no_new_homework: '새로운 과제가 없습니다.',\n    student_plural: '학생',\n    discuss: '공지',\n    basic_project: '기본 작품',\n    no_permission: '권한이 없습니다.',\n    no_comment_write_permission: '현재 로그인된 계정으로는 답변을 작성하실 수 없습니다.',\n    original_curriculum_deleted: '원본 강의 모음이 삭제되었습니다.',\n    original_curriculum: '원본 강의 모음',\n    save_as_my_lecture: '복사본으로 저장하기 ',\n    delete_confirm: '삭제 알림',\n    lecture_open_as_copied: '오픈 강의 페이지에 올라간 모든 강의는 사본으로 생성되어 공개 됩니다.',\n    curriculum_open_as_copied:\n        '오픈 강의 모음 페이지에 올라간 모든 강의 모음은 사본으로 생성되어 공개 됩니다.',\n    lecture_save_as_copied_group:\n        '우리 반 강의 페이지에 올라간 모든 강의는 사본으로 생성되어 공개 됩니다.',\n    curriculum_save_as_copied_group:\n        '우리 반 강의 모음 페이지에 올라간 모든 강의 모음은 사본으로 생성되어 공개 됩니다.',\n    homework_save_as_copied_group:\n        '우리 반 과제 페이지에 올라간 모든 과제는 사본으로 생성되어 공개 됩니다.',\n    lecture_save_as_copied:\n        '내가 만든 강의 모음 안에 삽입된 구성 강의는 사본으로 생성되어 저장됩니다.',\n    done_project_save_as_copied:\n        '내가 만든 강의 안에 삽입된 완성 작품은 사본으로 생성되어 저장됩니다.',\n    textbook_project_can_not_applied:\n        '교과형 만들기(실과)로 만들어진 작품은 강의로 만들 수 없습니다.',\n    original_lecture_deleted: '원본 강의가 삭제되었습니다.',\n    original_lecture: '원본 강의',\n    lecture_save_as_mine_alert:\n        \"저장되었습니다.\\n저장된 강의는 '마이페이지> 나의 강의'에서 확인할 수 있습니다.\",\n    lecture_save_as_mine: '내 강의로 저장하기',\n    duplicate_username: '이미 입력한 아이디 입니다.',\n    share_your_project: '내가 만든 작품을 공유해 보세요',\n    not_available_student:\n        \"학급에서 발급된 '학급 아이디'입니다.\\n'엔트리 회원 아이디'를 입력해주세요.\",\n    login_instruction: '로그인 안내',\n    login_needed: '로그인 후 이용할 수 있습니다.',\n    go_login: '로그인 하기',\n    login_as_teacher: '선생님 계정으로 로그인 후 이용할 수 있습니다.',\n    remove_my_storage:\n        '나의 보관함에서 삭제하시겠습니까? 삭제한 블록/오브젝트는 복구할 수 없습니다.',\n    submit_hw: '과제 제출하기',\n    success_goal: '목표성공',\n    choseok_final_result: '좋아 , 나만의 작품을 완성했어!',\n    choseok_fail_msg_timeout: '시간이 너무 많이 지나버렸어. 목표를 잘 보고 다시 한번 도전해봐!',\n    choseok_fail_msg_die:\n        '생명이 0이하인데 게임이 끝나지 않았어.\\n아래의 블록을 사용해서 다시 도전해 보는 건 어때?',\n    grade_1: '초급',\n    grade_2: '중급',\n    grade_3: '고급',\n    find_sally_title: '샐리를 찾아서',\n    save_sally_title: '샐리 구하기',\n    exit_sally_title: '샐리 탈출하기',\n    find_sally: '라인 레인저스의 힘을 모아 \\n강력한 악당 메피스토를 물리치고 샐리를 구해주세요!',\n    save_sally:\n        '메피스토 기지에 갇힌 샐리. \\n라인 레인저스가 장애물을 피해 샐리를 찾아갈 수 있도록\\n도와주세요!',\n    exit_sally:\n        '폭파되고 있는 메피스토 기지에서 \\n샐리와 라인 레인저스가 무사히 탈출할 수 있도록\\n도와주세요!',\n    go_next_mission: '다른 미션 도전하기',\n    share_my_project: '내가 만든 작품 공유하기',\n    share_certification: '인증서 공유하기',\n    print_certification: '인증서를 뽐내봐',\n    get_cparty_events: '내가 받은 인증서를 출력해 뽐내면 푸짐한 상품을 받을 수 있어요!',\n    go_cparty_events: '이벤트 참여하러 가기',\n    codingparty2016_blockHelper_1_title: '앞으로 가기',\n    codingparty2016_blockHelper_1_contents: '앞으로 가기',\n    codingparty2016_blockHelper_2_title: '앞으로 가기',\n    codingparty2016_blockHelper_2_contents: '회전하기',\n    codingparty2016_blockHelper_3_title: '앞으로 가기',\n    codingparty2016_blockHelper_3_contents: '돌 부수기',\n    codingparty2016_blockHelper_4_title: '앞으로 가기',\n    codingparty2016_blockHelper_4_contents: '횟수 반복하기',\n    codingparty2016_blockHelper_5_title: '앞으로 가기',\n    codingparty2016_blockHelper_5_contents: '꽃 던지기',\n    codingparty2016_goalHint_1:\n        '샐리를 구하기 위해서는 미네랄이 필요해! 미네랄을 얻으며 목적지까지 가보자!',\n    codingparty2016_goalHint_2: '구불구불한 길이 있네. 회전 블록을 사용하면 어렵지 않을 거야!',\n    codingparty2016_goalHint_3: '앞이 돌로 막혀있잖아? 돌을 부수며 목적지까지 가보자!',\n    codingparty2016_goalHint_4: '복잡한 길이지만 지금까지 배운 것들로 해결할 수 있어!',\n    codingparty2016_goalHint_5:\n        '앞으로 쭉 가는 길이잖아? 반복 블록을 사용하여 간단하게 해결해 보자!',\n    codingparty2016_goalHint_6: '미네랄을 모두 모아오자. 반복블록을 쓰면 쉽게 다녀올 수 있겠어!',\n    codingparty2016_goalHint_7:\n        '친구들이 다치지 않도록 꽃을 던져 거미집을 제거해야 해. 저 멀리 있는 거미집을 제거하고 목적지까지 가 보자.',\n    codingparty2016_goalHint_8:\n        '가는 길에 거미집이 많잖아? 거미집을 모두 제거하고 목적지까지 가 보자.',\n    codingparty2016_goalHint_9: '거미집 뒤쪽에 있는 미네랄을 모두 모아오자!',\n    codingparty2016_guide_1_1_contents:\n        '라인 레인저스 전사들이 샐리를 구할 수 있도록 도와줘! 전사들을 움직이기 위해서는 블록 명령어를 조립해야 해.\\n\\n① 먼저 미션 화면과 목표를 확인하고,\\n② 블록 꾸러미에서 필요한 블록을 가져와 “시작하기를 클릭했을 때“ 블록과 연결해.\\n③ 다 조립되면 ‘시작하기‘ 버튼을 눌러 봐! 블록이 위에서부터 순서대로 실행되며 움직일 거야.',\n    codingparty2016_guide_1_1_title: '라인 레인저스 전사들을 움직이려면?',\n    codingparty2016_guide_1_2_title: '목표 블록의 개수',\n    codingparty2016_guide_1_2_contents:\n        '① [안 칠해진 별]의 개수만큼 블록을 조립해 미션을 해결해보자. 목표 블록보다 더 많은 블록을 사용하면 별이 빨간색으로 바뀌니 정해진 개수 안에서 문제를 해결해 봐!\\n② 필요하지 않은 블록은 휴지통 또는 블록꾸러미에 넣어줘.',\n    codingparty2016_guide_1_3_title: \"'앞으로 가기' 블록을 사용하기\",\n    codingparty2016_guide_1_3_contents:\n        '< 앞으로 가기 > 는 앞으로 한 칸 이동하는 블록이야. \\n\\n여러 칸을 이동하기 위해서는 이 블록을 여러 번 연결해야 해.',\n    codingparty2016_guide_1_4_title: '미네랄 획득하기',\n    codingparty2016_guide_1_4_contents:\n        '[ 미네랄 ]이 있는 곳을 지나가면 미네랄을 획득할 수 있어\\n\\n화면에 있는 미네랄을 모두 획득하고 목적지에 도착해야만 다음 단계로 넘어갈 수 있어.',\n    codingparty2016_guide_1_5_title: '어려울 때 도움을 받으려면?',\n    codingparty2016_guide_1_5_contents:\n        '미션을 수행하다가 어려울 땐 3가지 종류의 도움말 버튼을 눌러 봐.\\n\\n\\n<안내> 지금 이 안내를 다시 보고 싶을 때!\\n<블록 도움말> 블록 하나하나가 어떻게 동작하는지 궁금할 때!\\n<맵 힌트> 이 단계를 해결하기 위한 힌트가 필요할 때!',\n    codingparty2016_guide_2_1_title: '회전 블록 사용하기',\n    codingparty2016_guide_2_1_contents:\n        '<오른쪽으로 돌기>와 <왼쪽으로 돌기>는 \\n제자리에서 90도 회전하는 블록이야. 방향만 회전하는 블록이야. \\n캐릭터가 바라보고 있는 방향을 기준으로 오른쪽인지 왼쪽인지 잘 생각해 봐!\\n',\n    codingparty2016_guide_3_1_title: '(문) 능력 사용하기',\n    codingparty2016_guide_3_1_contents:\n        '라인 레인저스 전사들을 각자의 능력을 가지고 있어.\\n나 [문] 은 <발차기하기> 로 바로 앞에 있는 [돌]을 부술 수 있어.\\n[돌을] 부수고 나면 막힌 길을 지나갈 수 있겠지?\\n화면에 있는 [돌]을 모두 제거해야만 다음 단계로 넘어갈 수 있어.\\n그렇지만 명심해! 아무 것도 없는 곳에 능력을 낭비해서는 안 돼!',\n    codingparty2016_guide_5_1_title: \"'~번 반복하기' 블록 사용하기\",\n    codingparty2016_guide_5_1_contents:\n        '똑같은 일을 반복해서 명령하는 건 매우 귀찮은 일이야.\\n이럴 땐 명령을 사용하면 훨씬 쉽게 명령을 내릴 수 있어.       \\n< [ ? ] 번 반복하기> 블록 안에 반복되는 명령 블록을 넣고  \\n[ ? ] 부분에 횟수를 입력하면 입력한 횟수만큼 같은 명령을 반복하게 돼.',\n    codingparty2016_guide_5_2_title: \"'~번 반복하기' 블록 사용하기\",\n    codingparty2016_guide_5_2_contents:\n        \"'< [ ? ] 번 반복하기>  블록 안에는 여러 개의 명령어를 넣을 수도 있으니 잘 활용해봐! \\n도착지에 도착했더라도 반복하기 블록 안에 있는 블록이 모두 실행돼.\\n 즉, 위 상황에서 목적지에 도착한 후에도 왼쪽으로 돈 다음에야 끝나는 거야!\",\n    codingparty2016_guide_7_1_title: '(코니) 능력 사용하기',\n    codingparty2016_guide_7_1_contents:\n        '나 ‘코니’는 <꽃 던지기>로 먼 거리에서도 앞에 있는 [거미집]을 없앨 수 있어.\\n[거미집]을 없애고 나면 막힌 길을 지나갈 수 있겠지?\\n화면에 있는 [거미집]을 모두 제거해야만 다음 단계로 넘어갈 수 있어.\\n그렇지만 명심해! 아무것도 없는 곳에 능력을 낭비해서는 안 돼!',\n    codingparty2016_guide_9_1_title: '조건 반복 블록 사용하기',\n    codingparty2016_guide_9_1_contents:\n        '반복하는 횟수를 세지 않아도, 어떤 조건을 만족할 때까지 행동을 반복할 수 있어.\\n< [목적지]에 도착할 때까지 반복하기 > 블록 안에 반복되는 명령 블록을 넣으면 [목적지]에 도착할 때까지 명령을 반복해.',\n    codingparty2016_guide_9_2_title: '조건 반복 블록 사용하기',\n    codingparty2016_guide_9_2_contents:\n        '<[목적지]에 도착할 때까지 반복하기> 블록 안에는 여러 개의 명령어를 넣을 수도 있으니 잘 활용해봐!\\n 도착지에 도착했더라도 반복하기 블록 안에 있는 블록이 모두 실행 돼. 즉, 위 상황에서 목적지에 도착한 후에도 왼쪽으로 돈 다음에야 끝나는 거야!',\n    find_interesting_lesson: \"'우리 반 강의'에서 다양한 강의를 만나보세요!\",\n    find_interesting_course: \"'우리 반 강의 모음'에서 다양한 강의를 만나보세요!\",\n    select_share_settings: '공유 공간을 선택해주세요.',\n    faq_banner_title: '자주하는 질문 안내',\n    check_out_faq: '궁금한 점을 확인하세요.',\n    faq_banner_content:\n        '엔트리에 대해 궁금하세요?<br />자주하는 질문을 통해 답변을 드리고 있습니다.<br />지금 바로 확인하세요!',\n    faq_banner_button: '자주하는 질문<br />바로가기',\n    major_updates: '주요 업데이트 안내',\n    check_new_update: '엔트리의 변화를 확인하세요.',\n    major_updates_notification: '엔트리의 주요 변경사항을 공지를 통해 안내해 드리고 있습니다.',\n    find_out_now: '지금 바로 확인하세요!',\n    offline_hw_program: '오프라인 & 하드웨어 연결 프로그램',\n    read_more: '자세히 보기',\n    sample_project: '예시 작품 확인하기',\n    not_supported_function: '이 기기에서는 지원하지 않는 기능입니다.',\n    offline_download_confirm:\n        '엔트리 오프라인 버전은 PC에서만 이용가능합니다. 다운로드 하시겠습니까?',\n    hardware_download_confirm: '엔트리 하드웨어는 PC에서만 이용가능합니다. 다운로드 하시겠습니까?',\n    copy_text: '텍스트를 복사하세요.',\n    select_openArea_space: '작품 공유 공간을 선택해 주세요',\n    mission_guide: '미션 해결하기 안내',\n    of: ' 의',\n    no_results_found: '검색 결과가 없습니다.',\n    upload_pdf: 'PDF 자료 업로드',\n    select_basic_project: '작품 선택하기',\n    try_it_out: '만들어 보기',\n    go_boardgame: '엔트리봇 보드게임 바로가기',\n    go_cardgame: '엔트리봇 카드게임 바로가기',\n    go_solve: '미션으로 학습하기',\n    go_ws: '엔트리 만들기 바로가기',\n    go_arts: '엔트리 공유하기 바로가기',\n    group_delete_alert:\n        '학급을 삭제하면, 해당 학급에서 발급한 학생임시계정을 포함하여 관련한 모든 자료가 삭제됩니다.\\n정말 삭제하시겠습니까?',\n    view_arts_list: '다른 작품 보기',\n    hw_submit_confirm_alert: '과제가 제출 되었습니다.',\n    hw_submit_alert: '과제를 제출 하시겠습니까? ',\n    hw_submit_alert2: '과제를 제출하시겠습니까? 제출 시 학습 완료한 학습 단계까지만 제출이 됩니다.',\n    hw_submit_cannot: '제출 할 수 없는 과제입니다.',\n    see_other_missions: '다른 미션 보기',\n    project: ' 작품',\n    marked: ' 관심',\n    group: '학급',\n    lecture: '강의',\n    Lecture: '강의',\n    curriculum: '강의 모음',\n    Curriculum: '강의 모음',\n    studying: '학습 중인',\n    open_only_shared_lecture:\n        '<b>오픈 강의</b> 페이지에 <b><공개></b> 한 강의만 불러올 수 있습니다. 불러오고자 하는 <b>강의</b>의 <b>공개여부</b>를 확인해 주세요.',\n    already_exist_group: '이미 존재하는 학급 입니다.',\n    cannot_invite_you: '자기 자신을 초대할 수 없습니다.',\n    apply_original_image: '원본 이미지 그대로 적용하기',\n    draw_new_ques: '새로 그리기 페이지로\\n이동하시겠습니까?',\n    draw_new_ques_1: '그림을 직접 그려서 추가할 수 있습니다.',\n    draw_new_ques_2: '그리기 화면으로 이동할까요?',\n    draw_new_go: '이동',\n    draw_new_stay: '이동하지 않기',\n    file_upload_warn_title_image:\n        '아래와 같은 그림은 이용약관 및 관련 법률에 의해 제재를 받으실 수 있습니다.',\n    file_upload_warn_desc_image:\n        '폭력적이고 잔인한 그림, 선정적인 신체노출 그림, 불쾌감을 주거나 혐오감을 일으키는 그림, 무단 사용이 금지된 저작권의 그림',\n    file_upload_warn_title_sound:\n        '아래와 같은 소리는 이용약관 및 관련 법률에 의해 제재를 받을 수 있습니다.',\n    file_upload_warn_desc_sound:\n        '폭력적이고 잔인한 소리, 선정적인 내용의 소리, 불쾌감을 주거나 혐오감을 일으키는 소리, 무단 사용이 금지된 저작권의 소리',\n    file_upload_warn_title_table:\n        '아래와 같은 데이터는 이용약관 및 관련 법률에 의해 제재를 받을 수 있습니다.',\n    file_upload_warn_desc_table:\n        '폭력적이고 잔인한 데이터, 선정적인 내용의 데이터, 불쾌감을 주거나 혐오단어가 포함된 데이터,<br>본인 또는 타인의 개인정보를 침해할 수 있는 내용의 데이터, 무단 사용이 금지된 저작권의 데이터',\n    file_upload_warn_link: '저작권에 대해 알아보기',\n    file_upload_desc_1: '이런 그림은 \\n 안돼요!',\n    file_upload_desc_2: '폭력적이고 잔인한 그림',\n    file_upload_desc_3: '선정적인 신체노출 그림',\n    file_upload_desc_4: '불쾌감을 주거나 혐오감을 일으키는 그림',\n    file_upload_desc_5:\n        '* 위와 같은 내용은 이용약관 및 관련 법률에 의해 제재를 받으실 수 있습니다.',\n    picture_upload_warn_old: '10MB 이하의 jpg, png, bmp 형식의 파일을 추가할 수 있습니다.',\n    sprite_upload_warn_old:\n        '10MB 이하의 jpg, png, bmp 이미지 또는 eo 형식의 오브젝트를 추가할 수 있습니다.',\n    picture_upload_warn_1:\n        '5MB 이하의 jpg, png, bmp, svg 형식의 파일을 추가할 수 있습니다.\\njpg, png, bmp 형식은 비트맵 모드, svg 형식은 벡터 모드로 편집됩니다.',\n    table_upload_warn_1:\n        '10MB 이하의 CSV, XLS(X) 형식의 파일을 추가할 수 있습니다. 엑셀 파일의 경우, 함수 문장이 그대로 출력됩니다.',\n    sprite_upload_warn:\n        '5MB 이하의 jpg, png, bmp, svg 이미지 또는 eo 형식의 오브젝트를 추가할 수 있습니다.',\n    sound_upload_warn_1: '10MB 이하의 mp3 형식의 파일을 추가할 수 있습니다.',\n    sound_edit_warn: '기다려 주세요!\\n새로운 소리 편집 기능을 연구 중입니다.',\n    file_upload_loading: '로딩중',\n    lesson_by_teacher: '선생님들이 직접 만드는 강의입니다.',\n    delete_group_art: '학급 공유하기 목록에서 삭제 하시겠습니까?',\n    elementary_short: '초등',\n    middle_short: '중등',\n    grade_34: '3-4학년',\n    grade_56: '5-6학년',\n    grade_78: '중등',\n    share_lesson: '강의 공유하기',\n    share_course: '강의 모음 공유하기',\n    from_list_ko: '을(를)',\n    comming_soon: '준비중입니다.',\n    no_class_alert:\n        \"선택된 학급이 없습니다. 학급이 없는경우 '나의 학급' 메뉴에서 학급을 만들어 주세요.\",\n    students_cnt: '명',\n    defult_class_alert_1: '',\n    defult_class_alert_2: '을(를) \\n 기본학급으로 설정하시겠습니까?',\n    default_class: '기본학급입니다.',\n    enter_hw_name: '과제의 제목을 입력해 주세요.',\n    hw_limit_100: '과제는 100개 까지만 만들수 있습니다.',\n    stu_example: '예)\\n 홍길동\\n 홍길동\\n 홍길동',\n    hw_description_limit_200: '생성 과제에 대한 안내 사항을 입력해 주세요. (200자 이내)',\n    hw_title_limit_50: '과제명을 입력해 주세요. (50자 이내)',\n    create_project_class_1: \"'만들기 > 작품 만들기' 에서\",\n    create_project_class_2: '학급에 공유하고 싶은 작품을 만들어 주세요.',\n    create_lesson_assignment_1: \"'만들기> 오픈 강의 만들기'에서 \",\n    create_lesson_assignment_2: '우리 반 과제에 추가하고 싶은 강의를 만들어 주세요.',\n    i_make_lesson: '내가 만드는 강의',\n    lesson_to_class_1: \"'학습하기>오픈 강의'에서 우리반\",\n    lesson_to_class_2: '과제에 추가하고 싶은 강의를 관심강의로 등록해 주세요.',\n    studying_students: '학습자',\n    lessons_count: '강의수',\n    group_out: '나가기',\n    enter_group_code: '학급코드 입력하기',\n    no_group_invite: '학급 초대가 없습니다.',\n    done_create_group: '개설이 완료되었습니다.',\n    set_default_group: '기본학급 설정',\n    edit_group_info: '학급 정보 관리',\n    edit_done: '수정 완료되었습니다.',\n    alert_group_out: '학급을 정말 나가시겠습니까?',\n    lesson_share_cancel: '강의 공유 취소',\n    project_share_cancel: '작품 공유 취소',\n    lesson_share_cancel_alert: '작품을 비공개로 하시겠습니까?',\n    course_share_cancel: '강의 모음 공유 취소',\n    select_lesson_share: '강의 공유 공간 선택',\n    select_project_share: '작품 공유 선택',\n    select_lesson_share_policy_1: '강의를 공유할',\n    select_lesson_share_policyAdd: '공간을 선택해 주세요',\n    select_lesson_share_project_1: '작품을 공유할 공간과',\n    select_lesson_share_policy_2: '저작권 정책을 확인해 주세요.',\n    select_lesson_share_area: '강의 공유 공간을 선택해 주세요',\n    select_project_share_area: '작품 공유 공간을 선택해 주세요',\n    lesson_share_policy: '강의 공유에 따른 엔트리 저작권 정책 동의',\n    project_share_policy: '작품 공유에 따른 엔트리 저작권 정책 동의',\n    alert_agree_share: '공개하려면 엔트리 저작물 정책에 동의하여야 합니다.',\n    alert_agree_all: '모든 항목에 동의해 주세요.',\n    select_course_share: '강의 모음 공유 공간 선택',\n    select_course_share_policy_1: '강의 모음을 공유할',\n    select_course_share_policy_2: '저작권 정책을 확인해 주세요.',\n    select_course_share_area: '강의 모음 공유 공간을 선택해 주세요',\n    course_share_policy: '강의 모음 공유에 따른 엔트리 저작권 정책 동의',\n    issued: '발급',\n    code_expired: \"코드가 만료되었습니다. '코드재발급' 버튼를 누르세요.\",\n    accept_class_invite: '학급초대 수락하기',\n    welcome_class: '학급에 오신것을 환영합니다.',\n    enter_info: '자신의 정보를 입력해주세요.',\n    done_group_signup: '학급 가입이 완료되었습니다.',\n    enter_group_code_stu: '선생님께 받은 코드를 입력해주세요.',\n    text_limit_50: '50글자 이하로 작성해 주세요.',\n    enter_class_name: '학급 이름을 입력해 주세요.',\n    enter_grade: '학년을 입력해 주세요.',\n    enter_class_info: '학급소개를 입력해 주세요.',\n    student_dup: '은(는) 이미 학급에 존재합니다.',\n    select_stu_print: '출력할 학생을 선택하세요.',\n    class_id_not_exist: '학급 ID가 존재하지 않습니다.',\n    error_try_again: '오류 발생. 다시 한 번 시도해 주세요.',\n    error_forbidden: '권한이 없습니다.',\n    code_not_available: '유효하지 않은 코드입니다.',\n    gnb_create_lessons: '오픈 강의 만들기',\n    study_lessons: '강의 학습하기',\n    lecture_help_1:\n        '학습을 시작할 때, 사용할 작품을 선택해 주세요. 선택한 작품으로 학습자가 학습을 시작하게 됩니다.',\n    lecture_help_2: '이도움말을 다시 보시려면 위 버튼을 클릭해 주세요.',\n    lecture_help_3: '오브젝트 추가하기가 없으면새로운 오브젝트를 추가하거나 삭제 할 수 없습니다.',\n    lecture_help_4: '학습도중에 PDF자료보기를 통해 학습에 도움을 받을 수 있습니다.',\n    lecture_help_5: '학습에 필요한 블록들만 선택해주세요. 선택하지 않은 블록은 숨겨집니다.',\n    lecture_help_6: '블록코딩과 엔트리파이선 중에 선택하여 학습환경을 구성할 수 있습니다.',\n    lecture_finish_popup_title: '학습 다시하기',\n    lecture_finish_popup_content_1: '실습완료한 단계를<br>처음부터 다시 실습하시겠습니까?',\n    lecture_finish_popup_content_2: '* 다시 실습해도 실습 완료 상태는 유지됩니다.',\n    lecture_start_title: '학습 시작',\n    lecture_goal_title: '학습 목표',\n    lecture_goal_content: '무엇을 배울지 알아볼까요?',\n    lecture_prepare_title: '학습 준비',\n    lecture_summary_title: '학습 정리',\n    lecture_summary_content: '배운 내용을 정리해 봅시다.',\n    lecture_quiz_title: '확인 문제',\n    lecture_quiz_content: '확인 문제를 통해 배운 내용을 점검해 봅시다.',\n    lecture_quiz_check_answer: '정답확인',\n    default_hint_title: '어떻게 만들까?',\n    only_pdf: '.pdf형식의 파일만 입력 가능합니다.',\n    enter_project_video: '적어도 하나의 작품이나 영상을 입력하세요.',\n    enter_title: '제목을 입력하세요.',\n    enter_recommanded_grade: '추천 학년을 입력하세요.',\n    enter_level_diff: '난이도를 입력하세요.',\n    enter_time_spent: '소요시간을 입력하세요.',\n    enter_shared_area: '적어도 하나의 공유 공간을 선택하세요.',\n    enter_goals: '학습목표를 입력하세요.',\n    enter_lecture_description: '강의 설명을 입력하세요.',\n    enter_curriculum_description: '강의 모음 설명을 입력하세요.',\n    first_page: '처음 입니다.',\n    last_page: '마지막 입니다.',\n    alert_duplicate_lecture: '이미 등록된 강의는 다시 등록할 수 없습니다.',\n    enter_lesson_alert: '하나 이상의 강의를 등록해주세요.',\n    open_edit_lessons: '편집할 강의를 불러오세요.',\n    saved_alert: '이(가) 저장되었습니다.',\n    select_lesson_type: '어떤 학습과정을 만들지 선택해 주세요 ',\n    create_lesson: '강의 만들기',\n    create_lesson_desc_1: '원하는 학습 목표에 맞춰',\n    create_lesson_desc_2: '단일 강의를 만들어',\n    create_lesson_desc_3: '학습에 활용합니다.',\n    create_courseware: '강의 모음 만들기',\n    create_courseware_desc_1: '학습 과정에 맞춰 여러개의 강의를',\n    create_courseware_desc_2: '하나의 코스로 만들어',\n    create_courseware_desc_3: '학습에 활용합니다.',\n    create_open_lesson: '오픈 강의 만들기 ',\n    enter_lesson_info: '강의 정보 입력 ',\n    select_lesson_feature: '학습 기능 선택 ',\n    check_info_entered: '입력 정보 확인 ',\n    enter_lefo_lesson_long: '강의를 구성하는 정보를 입력해 주세요.',\n    lesson_info_desc:\n        '학습자가 학습하기 화면에서 사용할 기능과 작품을 선택함으로써, 학습 목표와 내용에 최적화된 학습환경을 구성할 수 있습니다.',\n    provide_only_used: '완성된 작품에서 사용된 블록만 불러오기',\n    see_help: '도움말 보기',\n    select_done_project_1: '학습자가 목표로 설정할',\n    select_done_project_2: '완성 작품',\n    select_done_project_3: '을 선택해 주세요.',\n    select_project: '나의 작품 또는 관심 작품을 불러옵니다. ',\n    youtube_desc: '유튜브 공유 링크를 통해 원하는 영상을 넣을 수 있습니다.',\n    lesson_video: '강의 영상',\n    lesson_title: '강의 제목',\n    recommended_grade: '추천학년',\n    selection_ko: '선택',\n    selection_en: '',\n    level_of_diff: '난이도',\n    select_level_of_diff: '난이도 선택',\n    enter_lesson_title: '강의 제목을 입력해 주세요(45자 이내)',\n    select_time_spent: '소요시간 선택 ',\n    time_spent: '소요시간',\n    lesson_overview: '강의설명',\n    upload_materials: '학습 자료 업로드',\n    open: '불러오기',\n    cancel: '취소하기',\n    upload_lesson_video: '강의 영상 업로드',\n    youtube_upload_desc: '유튜브 공유링크를 통해 보조영상을 삽입할 수 있습니다. ',\n    cancel_select: '선택 취소하기',\n    select_again: '다시 선택하기',\n    goal_project: '완성작품',\n    upload_study_data:\n        '학습하기 화면에서 볼 수 있는 학습자료를 업로드해주세요. 학습자가 업로드된 학습자료의 내용을 확인하며 학습할 수 있습니다. ',\n    upload_limit_20mb: '20MB 이하의 파일을 올려주세요.',\n    expect_time: '예상 소요 시간',\n    course_videos: '보조 영상',\n    enter_courseware_info: '강의 모음 정보 입력 ',\n    enter_course_info: '강의 모음을 소개하는 정보를 입력해 주세요 ',\n    select_lessons_for_course: '강의 모음을 구성하는 강의를 선택해 주세요.',\n    course_build_desc_1: '강의는',\n    course_build_desc_2: '최대30개',\n    course_build_desc_3: '등록할 수 있습니다.',\n    lseeon_list: '강의 목록 보기',\n    open_lessons: '강의 불러오기',\n    course_title: '강의 모음 제목',\n    title_limit_30: '강의 모음 제목을 입력해 주세요(30자 이내) ',\n    course_overview: '강의 모음 설명',\n    charactert_limit_200: '200자 이내로 작성할 수 있습니다.',\n    edit_lesson: '강의 편집',\n    courseware_by_teacher: '선생님들이 직접 만드는 강의 모음입니다.',\n    select_lessons: '구성 강의 선택',\n    check_course_info: '강의 모음을 구성하는 정보가 올바른지 확인해 주세요.',\n    select_share_area: '공유 공간 선택',\n    upload_sub_project: '목표 작품 업로드',\n    file_download: '첨부파일 다운로드',\n    file_remove: '첨부파일 삭제',\n    check_lesson_info: '강의를 구성하는 정보가 올바른지 확인해 주세요.',\n    share_area: '공유 공간',\n    enter_sub_project: '엔트리 보조 프로젝트를 등록해 주세요.',\n    lms_hw_title: '과제 제목',\n    lms_hw_ready: '준비',\n    lms_hw_progress: '진행중',\n    lms_hw_complete: '완료',\n    lms_hw_not_submit: '미제출',\n    lms_hw_closed: '제출마감',\n    submission_condition: '진행중인 과제만 제출이 가능합니다.',\n    submit_students_only: '학생만 과제를 제출할 수 있습니다.',\n    want_submit_hw: '과제를 제출하시겠습니까?',\n    enter_correct_id: '올바른 아이디를 입력해 주세요.',\n    id_not_exist: '아이디가 존재하지 않습니다. ',\n    agree_class_policy: '학급 서비스 이용약관에 동의해 주세요.',\n    delete_class: '학급 삭제',\n    type_stu_name: '학생 이름을 입력해주세요. ',\n    invite_from_1: '에서',\n    invite_from_2: '님을 초대하였습니다. ',\n    lms_pw_alert_1: '님이 개설한',\n    lms_pw_alert_2: '학급의 초대입니다.',\n    lms_pw_alert_3: '선생님의 초대가 맞는지 한번 더 확인해주세요.',\n    invitation_accepted: '초대 수락이 완료되었습니다!',\n    cannot_issue_pw: '초대를 수락하지 않았으므로 비밀번호를 발급할 수 없습니다.',\n    start_me_1: '<월간 엔트리>와 함께',\n    start_me_2: 'SW교육을 시작해보세요!',\n    monthly_desc_1: '<월간 엔트리>는 소프트웨어 교육에 익숙하지 않은 선생님들도 쉽고 재미있게',\n    monthly_desc_2: '소프트웨어 교육을 하실 수 있도록 만들어진 SW교육 잡지입니다.',\n    monthly_desc_3: '매월 재미있는 학습만화와 함께 하는 SW 교육 컨텐츠를 만나보세요!',\n    monthly_desc_4: '* 월간엔트리는 2015년 11월 ~ 2016년 5월까지 발행 후 중단되었습니다.',\n    monthly_desc_5: '엔트리의 교육자료는 교육자료 페이지에서 만나보세요.',\n    monthly_entry: '월간 엔트리',\n    me_desc_1: '매월 발간되는 무료 소프트웨어 교육잡지',\n    me_desc_2: '월간엔트리를 만나보세요!',\n    solve_desc_1: '게임을 하듯 미션을 해결하며',\n    solve_desc_2: '소프트웨어의 기본 원리를 배워보세요!',\n    playSw_desc_1: 'EBS 방송영상, 특별영상을 통해',\n    playSw_desc_2: '소프트웨어를 배워보세요!',\n    recommended_lessons: '추천 강의 모음',\n    recommended_lessons_1:\n        '따라하고, 도전하고, 퀴즈도 풀며 재미있게 엔트리 프로그래밍을 배워보세요!',\n    recommended_lessons_2: '추천 강의 모음을 만나보세요!',\n    offline_top_desc_1: '오프라인 버전의 저장 기능이 향상되고 보안이 강화되었습니다.',\n    offline_top_desc_2: '지금 바로 다운받으세요',\n    offline_main_desc: '엔트리 오프라인 에디터 업데이트!!',\n    art_description:\n        '엔트리로 만든 작품을 공유하는 공간입니다. 작품을 만들고 공유에 참여해 보세요.',\n    art_description_1: '엔트리로 총 ',\n    art_description_2: '개의 작품이 만들어졌습니다. 작품을 만들고 공유해 보세요.',\n    study_index:\n        '엔트리에서 제공하는 주제별, 학년별 학습과정을 통해 차근차근 소프트웨어를 배워보세요!',\n    study_for_beginner: '처음 시작하는 사람들을 위한 엔트리 첫걸음',\n    entrybot_desc_3: '안내에 따라 블록 명령어를 조립하여',\n    entrybot_desc_4: '엔트리봇을 학교에 데려다 주세요.',\n    move_entrybot: '엔트리봇 움직이기',\n    can_change_entrybot_1: '블록 명령어로 엔트리봇의 색을 바꾸거나',\n    can_change_entrybot_2: '말을 하게 할 수도 있어요.',\n    learning_process_by_topics: '주제별 학습과정',\n    show_detail: '자세히 보기',\n    solve_mission: '미션 해결하기',\n    solve_mission_desc_1: '게임을 하듯 미션을 해결하며 프로그래밍의 원리를 익혀보세요!',\n    solve_mission_desc_2:\n        '미로 속의 엔트리봇을 목적지까지 움직이며 순차, 반복, 선택, 비교연산 등의 개념을 자연스럽게 익힐 수 있어요.',\n    learning_process_by_grades: '학년별 학습과정',\n    learning_process_by_grades_sub1:\n        '4가지 유형으로 쉽고 재미있게 배우는 프로그래밍의 원리! 지금 시작해보세요!',\n    e3_to_e4: '초등 3-4 학년',\n    e5_to_e6: '초등 5-6 학년',\n    m1_to_m3: '중등 이상',\n    make_using_entry: '엔트리로 만들기',\n    make_using_entry_desc_1: '블록을 쌓아 여러 가지 소프트웨어를 만들어보세요!',\n    make_using_entry_desc_2:\n        '제공되는 교재를 다운받아 차근차근 따라하다보면 애니메이션, 미디어아트, 게임 등 다양한 작품을 만들 수 있어요.',\n    make_through_ebs_1: 'EBS 방송영상으로 소프트웨어를 배워보세요.',\n    make_through_ebs_2:\n        '방송영상은 물론, 차근차근 따라 할 수 있는 특별영상과 함께 누구나 쉽게 다양한 소프트웨어를 만들 수 있어요.',\n    support_block_js: '블록 코딩과 자바스크립트 언어를 모두 지원합니다.',\n    study_ebs_title_1: '순서대로! 차례대로!',\n    study_ebs_desc_1: '[실습] 엔트리봇의 심부름',\n    study_ebs_title_2: '쉽고 간단하게!',\n    study_ebs_desc_2: '[실습] 꽃송이 만들기',\n    study_ebs_title_3: '언제 시작할까?',\n    study_ebs_desc_3: '[실습] 동물가족 소개',\n    study_ebs_title_4: '다른 선택, 다른 결과!',\n    study_ebs_desc_4: '[실습] 텔레파시 게임',\n    study_ebs_title_5: '정보를 담는 그릇',\n    study_ebs_desc_5: '[실습] 덧셈 로봇 만들기',\n    study_ebs_title_6: '요모조모 따져 봐!',\n    study_ebs_desc_6: '[실습] 복불복 룰렛',\n    study_ebs_title_7: '번호로 부르면 편해요!',\n    study_ebs_desc_7: '[실습] 나만의 버킷리스트',\n    study_ebs_title_8: '무작위 프로그램을 만들어라!',\n    study_ebs_desc_8: '[실습] 무작위 캐릭터 만들기',\n    study_ebs_title_9: '어떻게 찾을까?',\n    study_ebs_desc_9: '[실습] 도서관 책 검색',\n    study_ebs_title_10: '줄을 서시오!',\n    study_ebs_desc_10: '[실습] 키 정렬 프로그램',\n    event: '이벤트',\n    divide: '분기',\n    condition: '조건',\n    random_number: '무작위수',\n    search: '탐색',\n    sorting: '정렬',\n    parallel: '병렬',\n    signal: '신호',\n    input_output: '입출력',\n    sequential: '순차',\n    repeat: '반복',\n    choice: '선택',\n    repeat_advanced: '반복(횟수+조건)',\n    function: '함수',\n    compare_operation: '비교연산',\n    arithmetic: '산술연산',\n    entry_recommended_mission: '엔트리 추천 미션',\n    more_mission: '더 많은 미션 보러가기',\n    line_rangers_title: '라인레인저스와\\n샐리 구하기',\n    line_rangers_content: '메피스토 기지에 갇힌\\n샐리를 구해주세요!',\n    pinkbean_title_string_basic: '메이플스토리 초급 헤네시스',\n    pinkbean_title_string_intermediate: '메이플스토리 중급 엘리니아',\n    pinkbean_title_string_advanced: '메이플스토리 고급 엘나스',\n    pinkbean_title: '핑크빈과 함께 신나는\\n메이플 월드로!',\n    pinkbean_content: '핑크빈이 메이플 월드 모험을\\n무사히 마칠 수 있도록 도와주세요.',\n    entrybot_school: '엔트리봇 학교 가는 길',\n    entrybot_school_desc_1: '엔트리봇이 책가방을 챙겨 학교에',\n    entrybot_school_desc_2: '도착할 수 있도록 도와주세요!',\n    robot_factory: '로봇 공장',\n    robot_factory_desc_1: '로봇공장에 갇힌 엔트리봇!',\n    robot_factory_desc_2: '탈출하기 위해 부품을 모두 모아야해요.',\n    electric_car: '전기 자동차',\n    electric_car_desc_1: '엔트리봇 자동차가 계속 앞으로 나아갈 수',\n    electric_car_desc_2: '있도록 연료를 충전해 주세요.',\n    forest_adventure: '숲속 탐험',\n    forest_adventure_desc_1: '엔트리봇 친구가 숲속에 갇혀있네요!',\n    forest_adventure_desc_2: '친구를 도와주세요.',\n    town_adventure: '마을 탐험',\n    town_adventure_desc_1: '배고픈 엔트리봇을 위해 마을에 있는',\n    town_adventure_desc_2: '연료를 찾아주세요.',\n    space_trip: '우주 여행',\n    space_trip_desc_1: '우주탐사를 마친 엔트리봇!',\n    space_trip_desc_2: '지구로 돌아갈 수 있도록 도와주세요.',\n    learn_programming_mission: '미션을 해결하며 배우는 프로그래밍',\n    make_open_lecture: '오픈 강의 만들기',\n    group_created: '만든 학급',\n    group_signup: '가입한 학급',\n    delete_from_list: '을(를) 목록에서 삭제하시겠습니까?',\n    delete_from_list_en: '',\n    lecture_collection: '강의 모음',\n    edit_mypage_profile: '자기소개 정보 관리',\n    main_image: '메인 이미지',\n    edit_profile_success: '반영되었습니다.',\n    no_project_1: '내가 만든 작품이 없습니다.',\n    no_project_2: '지금 작품 만들기를 시작해보세요!',\n    empty_project_1: '아직 만들어진 작품이 없습니다.',\n    no_marked_project_1: '관심 작품이 없습니다.',\n    no_marked_group_project_1: '학급 관심 작품이 없습니다.',\n    no_marked_project_2: \"'작품 공유하기'에서 다양한 작품을 만나보세요!\",\n    no_markedGroup_project_2: \"'학급 공유하기'에서 다양한 작품을 만나보세요!\",\n    view_project_all: '작품 구경하기',\n    no_lecture_1: '내가 만든 강의가 없습니다.',\n    empty_lecture_1: '아직 만들어진 강의가 없습니다.',\n    no_lecture_2: \"'오픈 강의 만들기'에서 강의를 만들어보세요!\",\n    no_marked_lecture_1: '관심 강의가 없습니다.',\n    no_marked_group_lecture_1: '학급 관심 강의가 없습니다.',\n    no_marked_lecture_2: \"'오픈 강의'에서 다양한 강의를 만나보세요!\",\n    view_lecture: '강의 살펴보기',\n    no_studying_lecture_1: '학습 중인 강의가 없습니다.',\n    no_studying_lecture_2: \"'오픈 강의'에서 학습을 시작해보세요!\",\n    no_lecture_collect_1: '내가 만든 강의 모음이 없습니다.',\n    empty_lecture_collect_1: '아직 만들어진 강의 모음이 없습니다.',\n    no_lecture_collect_2: \"'오픈 강의 모음 만들기'에서 강의 모음을 만들어보세요!\",\n    make_lecture_collection: '강의 모음 만들기',\n    no_marked_lecture_collect_1: '관심 강의 모음이 없습니다.',\n    no_marked_lecture_group_collect_1: '학급 관심 강의 모음이 없습니다.',\n    no_marked_lecture_collect_2: \"'오픈 강의'에서 다양한 강의를 만나보세요!\",\n    view_lecture_collection: '강의 모음 살펴보기',\n    no_studying_lecture_collect_1: '학습 중인 강의 모음이 없습니다.',\n    no_studying_lecture_collect_2: \"'오픈 강의'에서 학습을 시작해보세요!\",\n    my_lecture: '나의 강의',\n    markedGroup: '학급 관심',\n    markedGroup_lecture: '학급 관심 강의',\n    markedGroup_curriculum: '학급 관심 강의모음',\n    marked_lecture: '관심 강의',\n    marked_lecture_collection: '나의 관심 강의 모음',\n    marked_marked_curriculum: '관심 강의 모음',\n    studying_lecture: '학습 중인 강의',\n    completed_lecture: '학습 완료 강의',\n    my_lecture_collection: '나의 강의 모음',\n    my: '나의',\n    studying_lecture_collection: '학습 중인 강의 모음',\n    completed_lecture_collection: '학습 완료한 강의 모음',\n    my_curriculum: '나의 강의 모음',\n    studying_curriculum: '학습 중인 강의 모음',\n    completed_curriculum: '학습 완료한 강의 모음',\n    materialCC:\n        '엔트리에서 제공하는 모든 교육 자료는 CC-BY 2.0 라이선스에 따라 자유롭게 이용할 수 있습니다.',\n    materialccby_new:\n        '엔트리의 교육자료는 CC-BY 2.0 라이선스에 따라 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    entry_copyright_info: '엔트리 저작권 가이드 보기',\n    pdf: 'PDF',\n    helper: '도움말',\n    youtube: '영상',\n    tvcast: '영상',\n    goal: '목표',\n    basicproject: '시작단계',\n    hw: '하드웨어',\n    object: '오브젝트',\n    console: '콘솔',\n    download_info: '모든 교육자료는 각각의 제목을 클릭 하시면 다운받으실 수 있습니다.',\n    entry_materials_all: '엔트리 교육자료 모음',\n    entry_material: '엔트리 교육자료',\n    recommand_grade: '추천학년',\n    g3_4_grades: '3-4 학년',\n    g5_6_grades: '5-6 학년',\n    middle_grades: '중학생 이상',\n    entry_go_go: '엔트리 고고!',\n    entry_go_go_desc: '학년별, 난이도 별로 준비된 교재를 만나보세요.',\n    entry_go_go_desc2: '각 과정별로 교육과정, 학습지, 교사용 해설서 3종 세트가 제공됩니다.',\n    stage_beginner: '초급',\n    stage_middle: '중급',\n    stage_high: '고급',\n    middle_school_short: '중등',\n    learn_entry_programming: '따라하며 배우는 엔트리 프로그래밍',\n    entry_programming_desc: '차근차근 따라 하다 보면 어느새 나도 엔트리 고수!',\n    ebs: 'EBS',\n    ebs_material_desc: '방송 영상과 교사용 지도서를 활용하여 수업을 해보세요!',\n    season_1_material: '시즌1 교사용 지도서',\n    season_2_material: '시즌2 교사용 지도서',\n    season_1: '시즌1',\n    playsoftware_ebs: 'EBS 소프트웨어야 놀자!',\n    material_teacher_guide: '교사용 지도서',\n    season_2: '시즌2',\n    compute_think_textbook: '교과서로 배우는 컴퓨팅 사고력',\n    computational_sw:\n        '국어, 수학, 과학, 미술... 학교에서 배우는 다양한 교과와 연계하여 SW를 배워보세요!',\n    python_coding_text: '엔트리파이선',\n    python_coding_textbook: '텍스트 코딩 세계로 떠나는 여행! 엔트리파이선',\n    python_coding_desc: '엔트리파이선으로 텍스트 언어의 구조와 문법을 자연스럽게 배워보세요!',\n    entry_x_hardware_text: '엔트리 X 하드웨어 교육자료',\n    entry_x_hardware: '엔트리 X 하드웨어 교육자료 모음',\n    e_sensor: 'E 센서보드',\n    e_sensor_board: 'E 센서보드',\n    e_sensor_robot: 'E 센서로봇',\n    arduino: '아두이노',\n    arduinoext: '아두이노 Uno 확장모드',\n    arduinonano: '아두이노 Nano',\n    albert: '알버트',\n    orange_board: '오렌지보드',\n    arduino_board: '아두이노',\n    joystick: '조이스틱 센서 쉴드',\n    ardublock: '아두블럭',\n    mkboard: '디지털 몽키보드',\n    mechatro_nano: '메카트로 나노+',\n    mechatro_uno: '메카트로 우노+',\n    memaker: '미메이커',\n    edumaker: '에듀메이커 보드',\n    codingtoolbox: '코딩툴박스',\n    materials_etc_all: '기타 교육자료 모음',\n    materials_teaching: '교원 연수 자료',\n    materials_etc: '기타 참고 자료',\n    materials_etc_resource: '참고 자료',\n    materials_teaching_etc: '교원 연수 및 참고자료',\n    materials_teaching_1: 'SW교육의 필요성과 교육 방법론',\n    materials_teaching_2: '엔트리와 함께하는 언플러그드 활동',\n    materials_teaching_3: '게임하듯 알고리즘을 배우는 엔트리 미션 해결하기',\n    materials_teaching_4: '실생활 문제해결을 위한 엔트리 프로그래밍',\n    materials_teaching_5: '교과연계 SW교육1 (미술,수학,사회)',\n    materials_teaching_6: '교과연계 SW교육2 (국어,과학,음악)',\n    materials_teaching_7: '피지컬 컴퓨팅 실습1(E센서보드)',\n    materials_teaching_8: '피지컬 컴퓨팅 실습2(햄스터)',\n    materials_teaching_9: '수업에 필요한 학급/강의 기능 알아보기',\n    materials_etc_1: '엔트리 첫 사용자를 위한 스타트 가이드',\n    materials_etc_2: '수업에 바로 활용할 수 있는 다양한 콘텐츠 모음집',\n    materials_etc_3: '월간 엔트리',\n    materials_etc_4: '엔트리 설명서',\n    materials_etc_5: '엔트리 소개 자료',\n    materials_etc_6: '엔트리 블록 책받침',\n    materials_etc_7: '엔트리파이선 예제 및 안내',\n    jr_if_1: '만약',\n    jr_if_2: '앞에 있다면',\n    jr_fail_no_pencil: '이런 그곳에는 연필이 없어. 연필이 있는 곳에서 사용해보자~',\n    jr_fail_forgot_pencil: '앗! 책가방에 넣을 연필을 깜빡했어. 연필을 모아서 가자~',\n    jr_fail_much_blocks: '너무많은 블록을 사용했어, 다시 도전해볼래?',\n    cparty_jr_success_1: '좋아! 책가방을 챙겼어!',\n    go_right: '오른쪽',\n    go_down: '  아래쪽',\n    go_up: '  위쪽',\n    go_left: '  왼쪽',\n    go_forward: '앞으로 가기',\n    jr_turn_left: '왼쪽으로 돌기',\n    jr_turn_right: '오른쪽으로 돌기',\n    go_slow: '천천히 가기',\n    repeat_until_reach_1: '만날 때 까지 반복하기',\n    repeat_until_reach_2: '',\n    pick_up_pencil: '연필 줍기',\n    repeat_0: '',\n    repeat_1: '반복',\n    when_start_clicked: '시작 버튼을 눌렀을 때',\n    age_0: '작품체험',\n    create_character: '캐릭터 만들기',\n    age_7_9: '초등 저학년',\n    going_school: '엔트리 학교가기',\n    age_10_12_1: '초등 고학년1',\n    collect_parts: '로봇공장 부품모으기',\n    age_10_12_2: '초등 고학년2',\n    driving_elec_car: '전기자동차 운전하기',\n    age_13: '중등',\n    travel_space: '우주여행하기',\n    people: '사람',\n    all: '전체',\n    life: '일상생활',\n    nature: '자연',\n    animal_insect: '동물/곤충',\n    environment: '자연환경',\n    things: '사물',\n    vehicles: '이동수단',\n    others: '기타',\n    fantasy: '판타지',\n    instrument: '악기',\n    piano: '피아노',\n    marimba: '마림바',\n    drum: '드럼',\n    janggu: '장구',\n    sound_effect: '효과음',\n    others_instrument: '기타타악기',\n    aboutEntryDesc_1: '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있는 플랫폼입니다.',\n    aboutEntryDesc_2: '학생들이 소프트웨어를 쉽고 재미있게 학습하고,',\n    aboutEntryDesc_3: '선생님들은 효과적으로 학생들을 가르칠 수 있습니다.',\n    aboutEntryDesc_4: '엔트리는 공공재와 같이',\n    aboutEntryDesc_5: '비영리로 운영됩니다.',\n    viewProjectTerms: '이용정책 보기',\n    openSourceTitle: '오픈소스를 통한 생태계 조성',\n    openSourceDesc_1: '엔트리의 소스코드 뿐 아니라',\n    openSourceDesc_2: '모든 교육 자료는 CC라이센스를 ',\n    openSourceDesc_3: '적용하여 공개합니다.',\n    viewOpenSource: '오픈소스 보기',\n    eduPlatformTitle: '국내교육 현장에 맞는 교육 플랫폼',\n    eduPlatformDesc_1: '국내 교육 현장에 적합한 교육 도구가',\n    eduPlatformDesc_2: '될 수 있도록 학교 선생님들과 함께',\n    eduPlatformDesc_3: '개발하고 있습니다.',\n    madeWith: '자문단',\n    researchTitle: '다양한 연구를 통한 전문성 강화',\n    researchDesc_1: '대학/학회 등과 함께 다양한 연구를',\n    researchDesc_2: '진행하여 전문성을 강화해나가고',\n    researchDesc_3: '있습니다.',\n    viewResearch: '연구자료 보기',\n    atEntry: '엔트리에서는',\n    entryLearnDesc_1: '재미있게 배우는 학습공간',\n    entryLearnDesc_2: '<학습하기>에서는 엔트리를 학습할 수 있는 콘텐츠가 준비되어 있습니다.',\n    entryLearnDesc_3: '게임을 하듯이 주어진 미션을 프로그래밍으로 해결하고 영상을 시청하며 ',\n    entryLearnDesc_4: '소프트웨어 제작 원리를 학습할 수 있습니다.',\n    entryMakeDesc_1: '<만들기>에서는 미국 MIT에서 개발한 Scratch와 같은 블록형 프로그래밍 언어를',\n    entryMakeDesc_2:\n        '사용하여 프로그래밍을 처음 접하는 사람들도 쉽게 자신만의 창작물을 만들 수 있습니다.',\n    entryMakeDesc_3:\n        \"또한 블록 코딩과 텍스트 코딩의 중간다리 역할을 하는 '엔트리파이선' 모드에서는\",\n    entryMakeDesc_4: '텍스트 언어의 구조와 문법을 자연스럽게 익힐 수 있습니다.',\n    entryMakeDesc_5: '',\n    entryShareDesc_1:\n        '<공유하기>에서는 엔트리를 통해 제작한 작품을 다른 사람들과 공유할 수 있습니다.',\n    entryShareDesc_2:\n        '또한 공유된 작품이 어떻게 구성되었는지 살펴보고 발전시켜 자신만의 작품을 만들 수',\n    entryShareDesc_3:\n        '있습니다. 공동 창작도 가능하여 친구들과 협업해 더 멋진 작품을 만들어 볼 수 있습니다.',\n    entryGroup: '학급기능',\n    entryGroupTitle: '우리 반 학습 공간',\n    entryGroupDesc_1:\n        '<학급기능>은 선생님이 학급별로 학생들을 관리할 수 있는 기능입니다. 학급끼리 학습하고',\n    entryGroupDesc_2: '작품을 공유할 수 있으며 과제를 만들고 학생들의 결과물을 확인할 수 있습니다.',\n    entryGroupDesc_3: '또한 선생님은 강의 기능을 활용하여 학생들의 수준에 맞는 학습환경을',\n    entryGroupDesc_4: '맞춤형으로 제공함으로써 효율적이고 편리하게 수업을 진행할 수 있습니다.',\n    entryGroupDesc_5: '',\n    unpluggedToPhysical: '언플러그드 활동부터 피지컬 컴퓨팅까지',\n    algorithmActivity: '기초 알고리즘',\n    programmignLang: '교육용 프로그래밍 언어',\n    unpluggedDesc_1: '엔트리봇 보드게임과 카드게임을 통해 컴퓨터 없이도',\n    unpluggedDesc_2: '소프트웨어의 기본 개념과 원리(순차, 반복, 선택, 함수)를 익힐 수 있습니다.',\n    entryMaze: '엔트리봇 미로탈출',\n    entryAI: '엔트리봇 우주여행',\n    algorithmDesc_1: '게임을 하듯이 미션을 해결하고 인증서를 받아보세요.',\n    algorithmDesc_2: '소프트웨어의 기본적인 원리를 쉽고 재미있게 배울 수 있습니다.',\n    programmingLangDesc_1: '엔트리에서는 블록을 쌓듯이 프로그래밍을 하기 때문에 누구나 쉽게',\n    programmingLangDesc_2:\n        '자신만의 게임, 애니메이션, 미디어아트와 같은 멋진 작품을 만들고 공유할 수 있어 교육용으로 적합합니다.',\n    viewSupporHwVideo: '하드웨어 가이드 영상 보기',\n    viewSupporHw: '연결되는 하드웨어 보기',\n    supportHwDesc_1:\n        '엔트리와 피지컬 컴퓨팅 도구를 연결하면 현실세계와 상호작용하는 멋진 작품들을 만들어낼 수 있습니다.',\n    supportHwDesc_2: '국내, 외 다양한 하드웨어 연결을 지원하며, 계속적으로 추가될 예정입니다.',\n    entryEduSupport: '엔트리 교육 지원',\n    eduSupportDesc_1:\n        '엔트리에서는 소프트웨어 교육을 위한 다양한 교육 자료를 제작하여 무상으로 배포하고 있습니다.',\n    eduSupportDesc_2: '모든 자료는 교육자료 페이지에서 다운받으실 수 있습니다.',\n    materials_1_title: '수준별 교재',\n    materials_1_desc_1: '학년별 수준에 맞는 교재를 통해 차근차근',\n    materials_1_desc_2: '따라하며 쉽게 엔트리를 익혀보세요!',\n    materials_2_title: 'EBS 방송 연계 교안',\n    materials_2_desc_1: 'EBS 소프트웨어야 놀자 방송과 함께',\n    materials_2_desc_2: '교사용 수업 지도안을 제공합니다.',\n    materials_3_title: '초, 중등 교과 연계 수업자료',\n    materials_3_title_2: '',\n    materials_3_desc_1: '다양한 과목에서 만나는 실생활 문제를',\n    materials_3_desc_2: '컴퓨팅 사고력으로 해결해 보세요.',\n    moreMaterials: '더 많은 교육 자료 보러가기',\n    moreInfoAboutEntry_1: '더 많은 엔트리의 소식들을 확인하고 싶다면 아래의 링크들로 접속해보세요.',\n    moreInfoAboutEntry_2: '교육자료 외에도 다양한 SW 교육과 관련한 정보를 공유하고 있습니다.',\n    material_menu_type_robot: '로봇형',\n    material_menu_type_module: '모듈형',\n    material_menu_type_board: '보드형',\n    blog: '블로그',\n    post: '포스트',\n    tvCast: 'TV캐스트',\n    about_entry_pre: '엔트리',\n    about_youtube: '유튜브',\n    about_facebook: '페이스북',\n    albertSchool: '알버트 스쿨버전',\n    arduinoBoard: '아두이노 정품보드',\n    arduinoCompatible: '아두이노 호환보드',\n    bitBlock: '비트블록',\n    bitbrick: '비트브릭',\n    creamo: '크리모',\n    playcode: '플레이코드',\n    funboard: '펀보드',\n    truerobot: '뚜루뚜루',\n    bingle: '빙글',\n    bingles: '빙글S',\n    codeino: '코드이노',\n    epor: '에뽀',\n    petrone_v2: '페트론V2',\n    petrone_v2_drone: '드론',\n    petrone_v2_car: '자동차',\n    'e-sensor': 'E-센서보드',\n    'e-sensorUsb': 'E-센서보드(유선연결)',\n    'e-sensorBT': 'E-센서보드(무선연결)',\n    mechatronics_4d: '4D 메카트로닉스',\n    esensor_board: 'E - 센서보드',\n    esensor_robot: 'E - 센서로봇',\n    awesomebot: '어썸봇',\n    hamster: '햄스터',\n    hummingbird: '허밍버드 듀오',\n    roboid: '로보이드',\n    turtle: '거북이',\n    littlebits: '리틀비츠',\n    orangeBoard: '오렌지 보드',\n    robotis_carcont: '로보티즈 로봇자동차',\n    robotis_IoT: '로보티즈 IoT',\n    robotis_IoT_Wireless: '로보티즈 IoT(무선연결)',\n    dplay: '디플레이',\n    iboard: '아이보드',\n    nemoino: '네모이노',\n    xbot_epor_edge: '엑스봇(원터치 동글/USB)',\n    XbotBT: '엑스봇 에뽀/엣지 블투투스',\n    robotori: '로보토리',\n    rokoboard: '로코보드',\n    neobot: '네오봇',\n    neobot_sensor_theme: '네오봇 센서 테마',\n    mechatro: '메카트로',\n    about: '알아보기',\n    articles: '토론하기',\n    gallery: '구경하기',\n    learn: '학습하기',\n    login: '로그인',\n    logout: '로그아웃',\n    make: '만들기',\n    register: '가입하기',\n    Join: '회원가입',\n    Edit_info: '내 정보 수정',\n    Discuss: '글 나누기',\n    Explore: '구경하기',\n    Load: '불러오기',\n    My_lesson: '오픈 강의',\n    textbook_learning: '교과서 학습하기',\n    Resources: '교육 자료',\n    play_software: '소프트웨어야 놀자!',\n    problem_solve: '엔트리 학습하기',\n    learning_textbook: '교과서 학습하기',\n    context_textbook:\n        '초등 교과서 그대로 선생님은 학교 수업을 학생은 집에서 예습, 복습을 할 수 있어요.',\n    info_banner_textbook: '* 출판사는 가나다순 노출입니다.',\n    banner_textbook: '더욱 다양하고',\n    banner_textbook_2: '재미있는 학습을 하고 싶다면?',\n    banner_textbook_right_banner: '학생용 활동지와 교사용',\n    banner_textbook_right_banner2: '학습 도움 자료가 필요하신가요?',\n    banner_textbook_right_banner_btn: '교과서별 자료 받기',\n    Learn: '학습하기',\n    teaching_tools: '엔트리 교구',\n    about_entry: '엔트리 소개',\n    what_entry: '엔트리는?',\n    create: '만들기',\n    create_new: '새로 만들기',\n    start_programming: '소프트웨어 교육의 첫걸음',\n    Entry: '엔트리',\n    intro_learning: '누구나 쉽고 재밌게 소프트웨어를 배울 수 있어요. ',\n    intro_learning_anyone: '지금 바로 시작해보세요! ',\n    start_now: 'For Free, Forever.',\n    welcome_entry: '엔트리에 오신걸 환영합니다.',\n    student: '학생',\n    non_menber: '일반인',\n    teacher: '선생님',\n    terms_conditions: '이용약관',\n    personal_information: '개인정보 수집 및 이용에 대한 안내',\n    limitation_liability: '책임의 한계와 법적 고지',\n    entry_agree: '엔트리의 이용약관에 동의 합니다.',\n    info_agree: '개인정보 수집 및 이용에 동의합니다.',\n    next: '다음',\n    enter_individual_info: '개인정보 입력',\n    enter_id: '아이디 입력',\n    enter_password: '비밀번호 입력',\n    confirm_password: '비밀번호 확인',\n    enter_password_again: '비밀번호를 한번 더 입력하세요.',\n    validation_password: '5자 이상의 영문/숫자 등을 조합하세요.',\n    validation_id: '4~20자의 영문/숫자를 조합하세요',\n    prev: '이전',\n    born_year: '태어난 연도',\n    select_born: '태어난 연도를 선택 하세요',\n    year: '년',\n    gender: '성별',\n    choose_gender: '성별을 선택 하세요',\n    male: '남성',\n    female: '여성',\n    language: '언어',\n    best_language: '주 언어를 선택 하세요',\n    korean: '한국어',\n    english: '영어',\n    viet: '베트남',\n    japan: '일본어',\n    russia: '러시아어',\n    korean_s: '한국어',\n    english_s: '영어',\n    japan_s: '일본어',\n    chinese_simplified: '중국어(간체)',\n    chinese_traditional: '중국어(번체)',\n    option_email: '이메일(선택)',\n    insert_email: '이메일 주소를 입력 하세요',\n    sign_up_complete: '회원 가입이 완료 되었습니다',\n    agree_terms_conditions: '이용약관에 동의해 주세요.',\n    agree_personal_information: '개인정보 수집 및 이용에 대한 안내에 동의해 주세요.',\n    insert_studying_stage: '작품을 공유하고 싶은 학급을 선택해 주세요.',\n    insert_born_year: '태어난 연도를 입력해 주세요.',\n    insert_gender: '성별을 선택지에서 선택해 주세요.',\n    select_language: '언어를 선택해 주세요.',\n    check_email: '이메일 형식을 확인해 주세요.',\n    already_exist_id: '이미 존재하는 아이디 입니다.',\n    id_validation_id: '아이디는 4~20자의 영문/숫자를 조합하세요',\n    password_validate_pwd: '패스워드는 5자 이상의 영문/숫자 등을 조합하세요.',\n    password_validate_pwd_length: '패스워드는 최소 5자 이상으로 입력해 주세요.',\n    neoid_username_same_id: '이미 사용중인 아이디 입니다.(NEOID)',\n    captcha_error: '자동입력 방지문자가 올바르지 않습니다.',\n    captcha_try_after_10min: '10분뒤에 다시 시도해주세요',\n    captcha_limit: '새로고침 제한 횟수에 도달했습니다.',\n    insert_same_pwd: '같은 비밀번호를 입력해 주세요.',\n    studying_stage_group: '작품 공유 학급',\n    studying_stage: '작품을 공유하고 싶은 학급을 선택해 주세요.',\n    password: '비밀번호 입력',\n    save_id: '아이디 저장',\n    auto_login: '자동 로그인',\n    enter_id_pw: '아이디, 비밀번호 입력',\n    forgot_password: '아이디와 비밀번호가 기억나지 않으세요 ?',\n    did_not_join: '아직 엔트리 회원이 아니세요?',\n    go_join: '회원가입하기 ',\n    renew_index_text_00: '엔트리 교과서 학습하기',\n    renew_index_text_01: '교과서로 엔트리를 배워보세요.',\n    renew_index_text_02: '초등학교 교과서 강의를 통해',\n    renew_index_text_02_2: '엔트리를 배워보세요!',\n    renew_index_text_03: '교과서 학습하기',\n    renew_index_text_03_2: '바로가기',\n    renew_index_text_1: '2019년, 엔트리가 바뀝니다',\n    renew_index_text_2: '확 바뀐 작품 만들기',\n    renew_index_text_3: '지금 새로운 기능을 확인하고',\n    renew_index_text_3_2: 'PC와 태블릿으로 작품을 만들어보세요!',\n    renew_index_text_4: '자세히 보기',\n    first_step: '소프트웨어 교육의 첫걸음',\n    entry_content_one: '상상했던 것들을 블록 놀이하듯 하나씩 쌓아보세요.',\n    entry_content_two: '게임, 애니메이션, 미디어아트와 같은 멋진 작품이 완성된답니다!',\n    entry_content_three:\n        '재미있는 놀이로 배우고, 나만의 멋진 작품을 만들어 친구들과 공유할 수 있는 멋진 엔트리의 세상으로 여러분을 초대합니다!',\n    funny_space: '재미있게 배우는 학습공간',\n    in_learn_section: '< 학습하기 > 에서는',\n    learn_problem_solving:\n        '컴퓨터를 활용해 논리적으로 문제를 해결할 수 있는 다양한 학습 콘텐츠가 준비되어 있습니다. 게임을 하듯이 주어진 미션들을 프로그래밍으로 해결해볼 수도 있고 재미있는 동영상으로 소프트웨어의 원리를 배울 수도 있습니다 .',\n    joy_create: '창작의 즐거움',\n    in_make: '< 만들기 > 는',\n    make_contents:\n        '미국 MIT에서 개발한 Scratch와 같은 비주얼 프로그래밍 언어를 사용하여 프로그래밍을 처음 접하는 사람들도 쉽게 나만의 창작물을 만들 수 있습니다. 또 엔트리를 통해 만들 수 있는 컨텐츠의 모습은 무궁무진합니다. 과학 시간에 배운 물리 법칙을 실험해 볼 수도 있고 좋아하는 캐릭터로 애니메이션을 만들거나 직접 게임을 만들어 볼 수 있습니다.',\n    and_content:\n        '또 엔트리를 통해 만들 수 있는 콘텐츠의 모습은 무궁무진합니다. 과학 시간에 배운 물리 법칙을 실험해 볼 수도 있고 좋아하는 캐릭터로 애니메이션을 만들거나 직접 게임을 만들어 볼 수 있습니다.',\n    share_collaborate: '공유와 협업',\n    explore_contents:\n        '< 구경하기 > 에서는 엔트리를 통해 제작한 작품을 다른 사람들과 쉽게 공유할 수 있습니다. 또한 공유된 작품이 어떻게 구성되었는지 살펴볼 수 있고, 이를 발전시켜 자신만의 프로젝트를 만들 수 있습니다. 그리고 엔트리에서는 공동 창작도 가능합니다. 친구들과 협업하여 더 멋진 프로젝트를 만들어볼 수 있습니다.',\n    why_software: '왜 소프트웨어 교육이 필요할까?',\n    speak_obama_contents:\n        '컴퓨터 과학을 배우는 것은 단지 여러분의 미래에만 중요한 일이 아닙니다. 이것은 우리 미국의 미래를 위해 중요한 일 입니다.',\n    obama: '버락 오바마',\n    us_president: '미국 대통령',\n    billgates_contents:\n        '컴퓨터 프로그래밍은 사고의 범위를 넓혀주고 더 나은 생각을 할 수 있게 만들며 분야에 상관없이 모든 문제에 대해 새로운 해결책을 생각할 수 있는 힘을 길러줍니다.',\n    billgates: '빌게이츠',\n    chairman_micro: 'Microsoft 회장',\n    eric_contents:\n        '현재 디지털 혁명은 지구상 대부분의 사람들에게 아직 시작도 안된 수준입니다. 프로그래밍을 통해 향후 10년간 모든 것이 변화할 것 입니다.',\n    eric: '에릭 슈미츠',\n    sandbug_contents:\n        '오늘날 컴퓨터 과학에 대한 이해는 필수가 되었습니다. 우리의 국가 경쟁력은 우리가 아이들에게 이것을 얼마나 잘 가르칠 수 있느냐에 달려있습니다.',\n    sandbug: '쉐릴 샌드버그',\n    view_entry_tools: '엔트리와 함께할 수 있는 교구들을 살펴볼 수 있습니다.',\n    solve_problem: '미션 해결하기',\n    solve_problem_content:\n        '게임을 하듯 미션을 하나 하나 해결하며 소프트웨어의 기본 원리를 배워보세요!',\n    find_extra_title: '엔트리봇 부품 찾기 대작전',\n    all_ages: '전 연령',\n    total: '총',\n    step: '단계',\n    find_extra_contents:\n        '로봇 강아지를 생산하던 루츠 공장에 어느 날 갑자기 일어난 정전 사태로 태어난 특별한 강아지 엔트리 봇. 아직 조립이 덜 된 나머지 부품들을 찾아 공장을 탈출 하도록 도와주면서 소프트웨어의 동작 원리를 익혀보자!',\n    software_play_contents: \"EBS에서 방영한 '소프트웨어야 놀자' 프로그램을 실습해볼 수 있습니다.\",\n    resources_contents: '엔트리를 활용한 다양한 교육자료들을 무료로 제공합니다.',\n    from: ' 출처',\n    sw_camp: '미래부 SW 창의캠프',\n    elementary: '초등학교',\n    middle: '중학교',\n    grades: '학년',\n    lesson: '차시',\n    sw_contents_one:\n        '5차시 분량으로 초등학생이 엔트리와 피지컬 컴퓨팅을 경험할  수 있는 교재입니다. 학생들은 엔트리 사용법을 학습하고, 그림판과 이야기 만들기를 합니다. 마지막에는 아두이노 교구를 활용하여 키보드를 만들어보는 활동을 합니다.',\n    sw_camp_detail: '미래창조과학부 SW창의캠프',\n    sw_contents_two:\n        '5차시 분량으로 중학생이 엔트리와 피지컬 컴퓨팅을 경험할 수 있는 교재입니다. 학생들은 엔트리 사용법을 학습하고, 미로찾기 게임과, 퀴즈 프로그램을 만들어 봅니다. 마지막에는 아두이노 교구를 활용하여 키보드로 자동차를 조종하는 활동을 합니다.',\n    sw_contents_three:\n        \"선생님들이 학교에서 시작할 수 있는 소프트웨어 수업 지도서입니다. 다양한 언플러그드 활동과, '소프트웨어야 놀자' 방송을 활용한 수업 지도안이 담겨 있습니다.\",\n    naver_sw: 'NAVER 소프트웨어야 놀자',\n    teacher_teaching: '교사용지도서 (초등학교 5~6학년 이상)',\n    funny_sw: '즐거운 SW놀이 교실',\n    sw_contents_four:\n        '소프트웨어를 놀이하듯 재미있게 배울 수 있는 교재로 엔트리보드게임을 비롯한 다양한 언플러그드 활동과 엔트리 학습모드로 소프트웨어를 만드는 기본 원리를 배우게 됩니다. 기본 원리를 배웠다면 학생들은 이제 엔트리로 이야기, 게임, 예술작품, 응용프로그램을 만드는 방법을 배우고, 자신이 생각한 소프트웨어를 만들고 발표할 수 있도록 교재가 구성되어 있습니다.',\n    ct_text_5: '교과서와 함께 키우는 컴퓨팅 사고력',\n    teacher_grade_5: '교원 (초등학교 5학년)',\n    ct_text_5_content:\n        '실생활의 문제를 해결하자는 테마로 준비된 총 8개의 학습콘텐츠가 담긴 교사용 지도안입니다. 각 콘텐츠는 개정된 교육과정을 반영한 타교과와의 연계를 통해 다양한 문제를 만나고 해결해볼 수 있도록 설계되었습니다.  아이들이 컴퓨팅 사고력을 갖춘 융합형 인재가 될 수 있도록 지금 적용해보세요!',\n    ct_text_6: '교과서와 함께 키우는 컴퓨팅 사고력',\n    teacher_grade_6: '교원 (초등학교 6학년)',\n    ct_text_6_content:\n        '실생활의 문제를 해결하자는 테마로 준비된 총 8개의 학습콘텐츠가 담긴 교사용 지도안입니다. 각 콘텐츠는 개정된 교육과정을 반영한 타교과와의 연계를 통해 다양한 문제를 만나고 해결해볼 수 있도록 설계되었습니다.  아이들이 컴퓨팅 사고력을 갖춘 융합형 인재가 될 수 있도록 지금 적용해보세요!',\n    sw_use: '모든 교재들은 비영리 목적에 한하여 저작자를 밝히고 자유롭게 이용할 수 있습니다.',\n    title: '제목',\n    writer: '작성자',\n    view: '보기',\n    date: '등록일',\n    find_id_pwd: '아이디와 비밀번호 찾기',\n    send_email: '비밀번호를 잊은 경우 이메일로 비밀번호를 찾을 수 있습니다.',\n    user_not_exist: '존재하지 않는 이메일 주소 입니다.',\n    not_signup: '아직 회원이 아니세요?',\n    send: '발송하기',\n    sensorboard: '엔트리봇 센서보드',\n    physical_computing: '피지컬 컴퓨팅',\n    sensorboard_contents:\n        '아두이노를 사용하기 위해서 더 이상 많은 케이블을 사용해 회로를 구성할 필요가 없습니다. 엔트리 보드는 아두이노 위에 끼우기만 하면 간단하게 LED, 온도센서, 소리센서, 빛, 슬라이더, 스위치를 활용할 수 있습니다. 이제 엔트리 보드를 활용해 누구라도 쉽게 자신만의 특별한 작품을 만들어보세요!',\n    entrybot_boardgame: '엔트리봇 보드게임',\n    unplugged: '언플러그드 활동',\n    unplugged_contents:\n        '재밌는 보드게임을 통해 컴퓨터의 작동 원리를 배워보세요. 로봇강아지인 엔트리봇이 정전된 공장에서 필요한 부품을 찾아 탈출하도록 돕다보면 컴퓨터 전문가처럼 문제를 바라 볼 수  있게됩니다.',\n    entrybot_cardgame: '엔트리봇 카드게임 : 폭탄 대소동',\n    entrybot_cardgame_contents:\n        '갑자기 엔트리도시에 나타난 12종류의 폭탄들! 과연 폭탄들을 안전하게 해체할 수 있을까요? 폭탄들을 하나씩 해체하며 엔트리 블록과 함께 소프트웨어의 원리를 배워봐요!  순차, 반복, 조건을 통해 폭탄을 하나씩 해체하다 보면 엔트리도시를 구한 영웅이 될 수 있답니다!',\n    basic_learn: '엔트리 기본 학습',\n    basic_learn_contents: '엔트리를 활용한 다양한 교육 콘텐츠를 제공합니다.',\n    troubleshooting: '문제해결 학습',\n    playsoftware: '소프트웨어야 놀자',\n    make_own_lesson: '나만의 수업을 만들어 다른 사람과 공유할 수 있습니다.',\n    group_lecture: '우리 반 강의',\n    group_curriculum: '우리 반 강의 모음',\n    group_homework: '우리 반 과제',\n    group_noproject: '전시된 작품이 없습니다.',\n    group_nolecture: '생성된 강의가 없습니다.',\n    group_nocurriculum: '생성된 강의 모음이 없습니다.',\n    lecture_contents: '필요한 기능만 선택하여 나만의 수업을 만들어 볼 수 있습니다.',\n    curriculum_contents:\n        '여러개의 강의를 하나의 강의 모음으로 묶어 차근차근 따라할 수 있는 수업을 만들 수 있습니다.',\n    grade_info: '학년 정보',\n    difficulty: '난이도',\n    usage: '사용요소',\n    learning_concept: '학습개념',\n    related_subject: '연계 교과',\n    show_more: '더보기',\n    close: '닫기',\n    latest: '최신순',\n    viewCount: '조회수',\n    viewer: '조회순',\n    like: '좋아요순',\n    comment: '댓글순',\n    entire_period: '전체기간',\n    today: '오늘',\n    latest_week: '최근 1주일',\n    latest_month: '최근 1개월',\n    latest_three_month: '최근 3개월',\n    current_password: '현재 비밀번호',\n    change_password: '비밀번호 변경',\n    incorrect_password: '비밀번호가 일치하지 않습니다.',\n    incorrect_password_login: '아이디 또는 비밀번호를 잘못 입력하셨습니다.',\n    suspension_user: '이용 정지된 계정입니다.',\n    blocked_user: '승인되지 않은 사용자 입니다.',\n    new_password: '새로운 비밀번호',\n    password_option_1: '영문과 숫자의 조합으로 5자 이상이 필요합니다.',\n    again_new_password: '새로운 비밀번호 재입력',\n    enter_new_pwd: '새로운 비밀번호를 입력하세요.',\n    confirm_new_pwd: '새로운 비밀번호를 확인하세요.',\n    enter_new_pwd_again: '새로운 비밀번호를 다시 입력하세요.',\n    password_match: '비밀번호가 일치하지 않습니다.',\n    incorrect_email: '유효한 이메일이 아닙니다',\n    edit_button: '정보수정',\n    edit_profile: '관리',\n    my_project: '나의 작품',\n    my_group: '나의 학급',\n    mark: '관심 작품',\n    prev_state: '이전',\n    profile_image: '자기소개 이미지',\n    insert_profile_image: '프로필 이미지를 등록해 주세요.',\n    at_least_180: '180 x 180 픽셀의 이미지를 권장합니다.',\n    upload_image: '이미지 업로드',\n    about_me: '자기소개',\n    save_change: '변경사항 저장',\n    basic_image: '기본 이미지',\n    profile_condition: '자기소개를 입력해 주세요. 50자 내외',\n    profile_back: '돌아가기',\n    make_project: '작품 만들기',\n    exhibit_project: '작품 전시하기',\n    art_list_shared: '개인',\n    art_list_group_shared: '학급',\n    gl_mode_boost: '부스트 모드',\n    gl_not_supported:\n        '부스트 모드로 실행할 수 없는 환경입니다.\\n확인을 누르면 기본모드로 실행됩니다.',\n    view_project: '코드 보기',\n    code_view: '코드보기',\n    noResult: '검색 결과가 없습니다.',\n    comment_view: '댓글',\n    upload_project: '올리기',\n    edit: '수정',\n    save_complete: '저장',\n    just_like: '좋아요',\n    share: '공유',\n    who_likes_project: '작품을 좋아하는 사람',\n    people_interest: '작품을 관심있어 하는 사람',\n    none_person: '없음',\n    inserted_date: '등록일',\n    last_modified: '최종 수정일',\n    original_project: '원본 작품',\n    for_someone: '님의',\n    original_project_deleted: '원본 작품이 삭제되었습니다.',\n    delete_project: '삭제',\n    delete_group_project: '목록에서 삭제',\n    currnet_month_time: '월',\n    current_day_time: '일',\n    game: '게임',\n    animation: '애니메이션',\n    media_art: '미디어 아트',\n    physical: '피지컬',\n    etc: '기타',\n    connected_contents: '연계되는 콘텐츠',\n    connected_contents_content:\n        '엔트리와 함께 할 수 있는 다양한 콘텐츠를 만나보세요. 처음 소프트웨어를 배우는 사람이라면 쉽게 즐기는 보드게임부터 아두이노와 같은 피지컬 컴퓨팅을 활용하여 자신만의 고급스러운 창작물을 만들어 볼 수 있습니다.',\n    basic_mission: '기본 미션: 엔트리봇 미로찾기',\n    basic_mission_content:\n        '강아지 로봇을 만드는 공장에서 우연한 정전으로 혼자서 생각할 수 있게 된 엔트리봇! 공장을 탈출하고 자유를 찾을 수 있도록 엔트리봇을 도와주세요!',\n    application_mission: '응용미션: 엔트리봇 우주여행',\n    write_article: '글쓰기',\n    write_contest: '제출하기',\n    view_all_articles: '모든 글 보기',\n    view_own_articles: '내가 쓴 글 보기',\n    view_qna_articles: '답변 없는 글 보기',\n    learning_materials: '교육자료',\n    download_materials: '교육자료 내려받기',\n    download_button: '내려받기',\n    download_all: '모두 내려받기',\n    ebs_software_first:\n        '<소프트웨어야 놀자>는 네이버와 EBS가 함께 만든 교육 콘텐츠입니다. 여기에서는 엔트리를 활용하여 실제로 간단한 프로그램을 만들어보며 소프트웨어의 기초 원리를 배워나갈 수 있습니다. 또한 각 콘텐츠에서는 동영상을 통해 컴퓨터과학에 대한 선행지식이 없더라도 충분히 재미와 호기심을 느끼며 진행할 수 있도록 준비되어있습니다.',\n    go_software: '소프트웨어야 놀자 가기',\n    ebs_context: 'EBS 동영상 가기',\n    ebs_context_hello: 'EBS 가기',\n    category: '카테고리',\n    add_picture: '사진첨부',\n    upload_article: '글 올리기',\n    list: '목록',\n    report: '신고하기',\n    upload: '올리기',\n    staff_picks: '스태프 선정',\n    popular_picks: '인기 작품',\n    lecture_header_more: '더 만들어 보기',\n    lecture_header_reset: '초기화',\n    lecture_header_reset_exec: '초기화 하기',\n    lecture_header_restart_button: '다시 시작',\n    lecture_header_save: '저장',\n    lecture_header_save_content: '학습내용 저장하기',\n    lecture_header_export_project: '내 작품으로 저장하기',\n    lecture_header_undo: '취소',\n    lecture_header_redo: '복원',\n    lecture_er_bugs: '버그신고',\n    lecture_container_tab_object: '오브젝트',\n    lecture_container_tab_video: '강의 동영상',\n    lecture_container_tab_project: '완성된 작품',\n    lecture_container_tab_help: '블록 도움말',\n    illigal: '불법적인 내용 또는 사회질서를 위반하는 활동',\n    verbal: '언어 폭력 또는 개인 정보를 침해하는 활동',\n    commertial: '상업적인 목적을 가지고 활동',\n    explicit: '음란물',\n    other: '기타',\n    check_one_more: '하나이상 표기해주세요.',\n    enter_content: '기타의 내용을 입력해 주세요.',\n    report_result: '결과 회신을 원하시면 메일을 입력해 주세요.',\n    report_success: '신고하기가 정상적으로 처리 되었습니다.',\n    etc_detail:\n        '기타 항목 선택후 입력해주세요. 신고와 무관한 욕설 작성 시 이용이 정지될 수 있습니다.',\n    lecture_play: '강의 보기',\n    list_view_link: '다른 강의 모음 보기',\n    lecture_intro: '강의 소개 보기',\n    study_goal: '학습목표',\n    study_description: '설명',\n    study_created: '등록일',\n    study_last_updated: '최종 수정일',\n    study_remove: '삭제',\n    study_group_lecture_remove: '목록에서 삭제',\n    study_group_curriculum_remove: '목록에서 삭제',\n    study_edit: '강의 모음 수정',\n    study_comments: '댓글',\n    study_comment_post: '올리기',\n    study_comment_remove: '삭제',\n    study_comment_edit: '수정',\n    study_comment_save: '저장',\n    study_guide_video: '안내 영상',\n    study_basic_project: '기본 작품',\n    study_done_project: '완성 작품을 선택하세요.',\n    study_usage_element: '사용요소',\n    study_concept_element: '적용개념',\n    study_subject_element: '연계교과',\n    study_computing_element: '컴퓨팅요소',\n    study_element_none: '없음',\n    study_label_like: '좋아요',\n    study_label_interest: '관심 강의',\n    study_label_share: '공유',\n    study_label_like_people: '강좌를 좋아하는 사람',\n    study_label_interest_people: '강좌를 관심있어 하는 사람',\n    study_related_lectures: '강의 목록',\n    study_expand: '전체보기',\n    study_collapse: '줄이기',\n    aftercopy: '주소가 복사되었습니다.',\n    study_remove_curriculum: '강의 모음을 삭제하시겠습니까?',\n    content_required: '내용을 입력하세요',\n    upload_not_supported_file_msg: '지원하지 않는 형식의 파일입니다.',\n    study_remove_lecture: '강의를 삭제하시겠습니까?',\n    lecture_build: '강의 만들기',\n    lecture_build_step1: '1. 강의를 소개하기 위한 정보를 입력해주세요',\n    lecture_build_step2: '2. 학습에 사용되는 기능들만 선택해주세요',\n    lecture_build_step3: '3. 모든 정보를 올바르게 입력했는지 확인해주세요',\n    lecture_build_choice: '어떤 것을 올리시겠습니까?',\n    lecture_build_project: '엔트리 작품',\n    lecture_build_video: '강의 영상',\n    lecture_build_grade: '추천학년',\n    lecture_build_goals: '학습목표',\n    lecture_build_add_goal: '이곳을 클릭하여 목표를 추가',\n    lecture_build_attach: '파일 첨부',\n    lecture_build_attach_text: '20MB 이내의 파일을 업로드해 주세요.',\n    lecture_build_assist: '보조 영상',\n    lecture_build_youtube_url: 'Youtube 공유 링크를 넣어주세요.',\n    lecture_build_project_done: '완성 작품을 선택하세요.',\n    lecture_build_scene_text1: '장면기능을 끄면 새로운 장면을 추가하거나,',\n    lecture_build_scene_text2: '삭제할 수 없습니다.',\n    lecture_build_object_text:\n        '오브젝트 추가하기를 끄면 새로운 오브젝트를 추가하거나 삭제할 수 없습니다.',\n    lecture_build_blocks_text1: '학습에 필요한 블록들만 선택해주세요.',\n    lecture_build_blocks_text2: '선택하지 않은 블록은 숨겨집니다.',\n    lecture_build_basic1: '학습을 시작할때 사용할 작품을 선택해 주세요.',\n    lecture_build_basic2: '학습자는 선택한 작품을 가지고 학습을 하게 됩니다.',\n    lecture_build_help: '이 도움말을 다시 보시려면 눌러주세요.',\n    lecture_build_help_never: '다시보지 않기',\n    lecture_build_close: '닫기',\n    lecture_build_scene: '장면 1',\n    lecture_build_add_object: '오브젝트 추가하기',\n    lecture_build_start: '시작하기',\n    lecture_build_tab_code: '블록',\n    lecture_build_tab_shape: '모양',\n    lecture_build_tab_sound: '소리',\n    lecture_build_tab_attribute: '속성',\n    lecture_build_tab_table: '테이블',\n    lecture_build_block_category: '블록 카테고리를 선택하세요.',\n    lecture_build_attr_all: '전체',\n    lecture_build_attr_var: '변수',\n    lecture_build_attr_signal: '신호',\n    lecture_build_attr_list: '리스트',\n    lecture_build_attr_func: '함수',\n    lecture_build_edit: '강의 수정',\n    lecture_build_remove: '삭제',\n    curriculum_build: '강의 모음 만들기',\n    curriculum_step1: '1. 강의 모음을 소개하는 정보를 입력해주세요.',\n    curriculum_step2: '2. 강의 모음을 구성하는 강의를 선택해주세요.',\n    curriculum_step3: '3. 올바르게 강의 모음이 구성되었는지 확인해주세요.',\n    curriculum_lecture_upload: '강의 올리기',\n    curriculum_lecture_edit: '강의 편집',\n    curriculum_lecture_open: '불러오기',\n    group_lecture_add: '우리 반 강의 추가하기',\n    group_curriculum_add: '우리 반 강의 모음 추가하기',\n    group_lecture_delete: '삭제',\n    group_curriculum_delete: '삭제',\n    group_select: '',\n    group_studentNo: '학번',\n    group_username: '이름',\n    group_userId: '아이디',\n    group_tempPassword: '비밀번호 수정',\n    group_gender: '성별',\n    group_studentCode: '코드',\n    file_load_web_table_title: '테이블을 웹에서 가져오기',\n    file_load_web_table_sub_title: 'Google 스프레드시트 문서로 작성된 테이블을 가져올 수 있어요.',\n    file_input_sheet_id: '스프레드시트 문서 ID',\n    file_input_sheet_id_require: '필수',\n    file_input_sheet_id_placeholder: '불러올 스프레드시트 문서의 ID를 입력해 주세요.',\n    file_input_sheet_name: '시트 이름',\n    file_input_sheet_name_placeholder: '불러올 시트 이름을 입력해 주세요.',\n    file_load_web_warn_title_1:\n        \"Google 스프레드시트 문서의 내용을 가져와 엔트리의 테이블로 추가할 수 있습니다.\\n스프레드시트의 액세스 권한이 '링크가 있는 모든 사용자'로 설정되어 있어야 가져올 수 있습니다.\",\n    file_load_web_warn_title_2:\n        '아래와 같은 데이터는 이용약관 및 관련 법률에 의해 제재를 받을 수 있습니다.',\n    file_load_web_warn_desc_2_1:\n        '폭력적이고 잔인한 데이터, 선정적인 내용의 데이터, 불쾌감을 주거나 혐오단어가 포함된 데이터, 본인 또는 타인의 개인정보를 침해할 수 있는 내용의 데이터, \\n무단 사용이 금지된 저작권의 데이터',\n    file_load_web_error_sheet_id_1: '문서 ID가 입력되지 않았습니다.',\n    file_load_web_error_sheet_id_2: '올바르지 않은 문서 ID입니다.',\n    group_viewWorks: '작품 보기',\n    added_group_lecture: '강의가 삭되었습니다.',\n    added_group_curriculum: '강의 모음이 삭제되었습니다.',\n    deleted_group_lecture: '강의가 삭제되었습니다.',\n    deleted_group_curriculum: '강의 모음이 삭제되었습니다.',\n    modal_my: '나의',\n    modal_interest: '관심',\n    modal_project: '작품',\n    section: '단원',\n    connect_hw: '하드웨어 연결',\n    connect_message: '%1에 연결되었습니다.',\n    connect_fail: '하드웨어 연결에 실패했습니다. 연결프로그램이 켜져 있는지 확인해 주세요.',\n    interest_curriculum: '관심 강의 모음',\n    marked_curriculum: '관심 강의 모음',\n    searchword_required: '검색어를 입력하세요.',\n    file_required: '파일은 필수 입력 항목입니다.',\n    file_name_error: '올바른 파일이름을 입력해 주세요.',\n    file_upload_max_count: '한번에 10개까지 업로드가 가능합니다.',\n    image_file_only: '이미지 파일만 등록이 가능합니다.',\n    file_upload_max_size: '10MB 이하만 업로드가 가능합니다.',\n    curriculum_modal_lectures: '나의 강의',\n    curriculum_modal_interest: '관심 강의',\n    group_curriculum_modal_curriculums: '나의 강의 모음',\n    group_curriculum_modal_interest: '관심 강의 모음',\n    picture_import: '모양 가져오기',\n    picture_select: '모양 선택',\n    lecture_list_view: '다른 강의보기',\n    play_software_2: 'EBS 소프트웨어야 놀자2',\n    play_software_2_content:\n        '네이버와 EBS가 함께 만든 두 번째 이야기, <소프트웨어야 놀자> 시즌2를 만나보세요! 재미있는 동영상 강의를 통해 소프트웨어의 기본 개념을 배워보고, 다양하고 흥미로운 주제로 실생활 문제를 해결해 볼 수 있습니다. 방송영상과 특별영상을 보며 재미있는 프로그램들을 직접 만들어보세요. 소프트웨어 교육을 처음 접하는 친구들도 쉽게 소프트웨어와 친구가 될 수 있답니다!',\n    open_project_to_all: '공개',\n    close_project: '비공개',\n    category_media_art: '미디어 아트',\n    go_further: '더 나아가기',\n    marked_project: '북마크 작품',\n    marked_group_project: '학급 관심 작품',\n    basic: '기본',\n    application: '응용',\n    the_great_escape: '탈출 모험기',\n    escape_guide_1:\n        '강아지 로봇을 만드는 공장에서 우연한 정전으로 혼자서 생각할 수 있게 된 엔트리봇! ',\n    escape_guide_1_2: ' 공장을 탈출하고 자유를 찾을 수 있도록 엔트리봇을 도와주세요!',\n    escape_guide_2:\n        '엔트리봇이 먼 길을 가기엔 고쳐야 할 곳이 너무 많아 공장에서 탈출하면서 몸을 수리할 수 있는 부품들을 찾아보자! 아직 몸이 완전하지는 않지만 걷거나 뛰면서, 방향을 바꾸는 정도는 가능할 거야! ',\n    escape_guide_2_2: '학습 목표: 순차적 실행',\n    escape_guide_3:\n        '드디어 공장을 탈출했어! 하지만 마을로 가기 위해서는 아직 가야 할 길이 멀어. 그래도 몸은 어느 정도 고쳐져서 똑같은 일을 많이 해도 무리는 없을 거야! 어? 근데 저 로봇은 뭐지? ',\n    escape_guide_3_2: '학습 목표: 반복문과 조건문',\n    escape_guide_4:\n        '드디어 마을 근처까지 왔어! 아까부터 똑같은 일을 많이 했더니 이제 외울 지경이야! 차라리 쓰일 블록은 이제 기억해뒀다가 쓰면 좋을 것 같아. 여기서 배터리만 충전해 놓으면 이제 평생 자유롭게 살 수 있을 거야.',\n    escape_guide_4_2: '학습 목표: 함수 정의와 호출',\n    space_travel_log: '우주 여행기',\n    space_guide_1:\n        '머나먼 우주를 탐사하기 위해 떠난 엔트리봇. 드디어 탐사 임무를 마치고 고향별인 지구로 돌아오려 하는데 수많은 돌이 지구로 가는 길을 막고 있다!  엔트리봇이 안전하게 지구로 돌아올 수 있도록 도와주세요!',\n    space_guide_2:\n        '드디어 지구에 돌아갈 시간이야! 얼른 지구에 돌아가서 쉬고 싶어!앞에 돌들이 어떻게 되어 있는지 확인하고 언제 어디로 가야 하는지 알려줘! 그러면 내가 가르쳐준 방향으로 움직일게!',\n    space_guide_2_2: '학습 목표: 조건문 중첩과 논리 연산',\n    cfest_mission: '엔트리 체험 미션',\n    maze_1_intro:\n        '안녕 나는 엔트리봇이라고 해. 지금 나는 다친 친구들을 구하려고 하는데 너의 도움이 필요해. 나를 도와서 친구들을 구해줘! 먼저 앞으로 가기 블록을 조립하고 시작을 눌러봐',\n    maze_1_title: '시작 방법',\n    maze_1_content: '엔트리봇은 어떻게 움직이나요?',\n    maze_1_detail:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐 <br> 2. 다 조립했으면, 시작을 눌러봐 <br> 3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_2_intro:\n        '좋아! 덕분에 첫 번째 친구를 무사히 구할 수 있었어! 그럼 다음 친구를 구해볼까? 어! 그런데 앞에 벌집이 있어! 뛰어넘기 블록을 사용해서 벌집을 피하고 친구를 구해보자.',\n    maze_2_title_1: '장애물 뛰어넘기',\n    maze_2_content_1: '장애물이 있으면 어떻게 해야하나요?',\n    maze_2_detail_1:\n        '길을 가다보면 장애물을 만날 수 있어. <br> 장애물이 앞에 있을 때에는 뛰어넘기 블록을 사용해야 해.',\n    maze_2_title_2: '시작 방법',\n    maze_2_content_2: '엔트리봇은 어떻게 움직이나요?',\n    maze_2_detail_2:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐 <br> 2. 다 조립했으면, 시작을 눌러봐 <br> 3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_3_intro:\n        '멋졌어! 이제 또 다른 친구를 구하러 가자~ 이번에는 아까 구한 친구가 준 반복하기 블록을 이용해볼까? 반복하기를 이용하면 똑같은 동작을 쉽게 여러번 할 수 있어! 한 번 반복할 숫자를 바꿔볼래?',\n    maze_3_title: '반복 블록(1)',\n    maze_3_content: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_3_detail:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해. <br> 반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼',\n    maze_4_intro:\n        '훌륭해! 이제 구해야 할 친구 로봇들도 별로 남지 않았어. 벌집에 닿지 않도록 뛰어넘기를 반복하면서 친구에게 갈 수 있게 해줘!',\n    maze_4_title: '반복 블록(1)',\n    maze_4_content: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_4_detail:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해. <br> 반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼',\n    maze_5_intro:\n        '대단해! 이제 반복하기 블록과 만약 블록을 같이 사용해보자~ 만약 블록을 사용하면 앞에 벽이 있을 때 벽이 없는 쪽으로 회전할 수 있어. 그럼 친구를 구해주러 출발해볼까?',\n    maze_5_title_1: '만약 블록',\n    maze_5_content_1: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_5_detail_1:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어. <br> 앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고 <br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_5_title_2: '반복 블록(2)',\n    maze_5_content_2: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_5_detail_2:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어. <br> 반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼. <br> 그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_6_intro:\n        '이제 마지막 친구야! 아까 해본 것처럼만 하면 될거야! 그럼 마지막 친구를 구하러 가볼까?',\n    maze_6_title_1: '만약 블록',\n    maze_6_content_1: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_6_detail_1:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어. <br> 앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고 <br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_6_title_2: '반복 블록(2)',\n    maze_6_content_2: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_6_detail_2:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어. <br> 반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼. <br> 그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_programing_mode_0: '블록 코딩',\n    maze_programing_mode_1: '자바스크립트',\n    maze_operation1_title: '1단계 – 자바스크립트모드 안내',\n    maze_operation1_1_desc:\n        '나는 로봇강아지 엔트리봇이야. 나에게 명령을 내려서 미션을 해결할 수 있게 도와줘! 미션은 시작할 때마다 <span class=\"textShadow\">\\'목표\\'</span>를 통해서 확인할 수 있어!',\n    maze_operation1_2_desc:\n        '미션을 확인했다면 <b>명령</b>을 내려야 해 <span class=\"textUnderline\">\\'명령어 꾸러미\\'</span>는 <b>명령어</b>가 있는 공간이야. <b>마우스</b>와 <b>키보드</b>로 <b>명령</b>을 내릴 수 있어. <span class=\"textShadow\">마우스</span>로는 명령어 꾸러미에 있는 <b>명령어</b>를 클릭하거나, <b>명령어</b>를 <span class=\"textUnderline\">\\'명령어 조립소\\'</span>로 끌고와서 나에게 <b>명령</b>을 내릴 수 있어!',\n    maze_operation1_2_textset_1: '마우스로 명령어를 클릭하는 방법 ',\n    maze_operation1_2_textset_2: '마우스로 명령어를 드래그앤드랍하는 방법 ',\n    maze_operation1_3_desc:\n        '<span class=\"textShadow\">키보드</span>로 명령을 내리려면 \\'명령어 꾸러미\\' 에 있는 <b>명령어를 키보드로 직접 입력하면 돼.</b></br> 명령어를 입력할 때 명령어 끝에 있는 <span class=\"textShadow\">()와 ;</span> 를 빼먹지 않도록 주의해야해!',\n    maze_operation1_4_desc:\n        '미션을 해결하기 위한 명령어를 다 입력했다면 <span class=\"textShadow\">[시작하기]</span>를 누르면 돼.</br> [시작하기]를 누르면 나는 명령을 내린대로 움직일 거야!</br> 각 명령어가 궁금하다면 <span class=\"textShadow\">[명령어 도움말]</span>을 확인해봐!',\n    maze_operation7_title: '7단계 - 반복 명령 알아보기(횟수반복)',\n    maze_operation7_1_desc:\n        '<b>똑같은 일</b>을 반복해서 명령하는건 매우 귀찮은 일이야.</br>이럴땐 <span class=\"textShadow\">반복</span>과 관련된 명령어를 사용하면 훨씬 쉽게 명령을 내릴 수 있어.',\n    maze_operation7_2_desc:\n        '그렇다면 반복되는 명령을 쉽게 내리는 방법을 알아보자.</br>먼저 반복하기 명령어를 클릭한 다음, <span class=\"textShadow\">i<1</span> 의 숫자를 바꿔서 <span class=\"textShadow\">반복횟수</span>를 정하고</br><span class=\"textShadow\">괄호({ })</span> 사이에 반복할 명령어를 넣어주면 돼!',\n    maze_operation7_3_desc:\n        '예를 들어 이 명령어<span class=\"textBadge number1\"></span>은 move(); 를 10번 반복해서 실행해.</br><span class=\"textBadge number2\"></span>명령어와 동일한 명령어지.',\n    maze_operation7_4_desc:\n        '이 명령어를 사용할 때는 <span class=\"textShadow\">{ } 안에 반복할 명령어</span>를 잘 입력했는지,</br><span class=\"textShadow\">`;`</span>는 빠지지 않았는지 잘 살펴봐!</br>이 명령어에 대한 자세한 설명은 [명령어 도움말]에서 볼 수 있어.',\n    maze_operation7_1_textset_1: '똑같은 명령어를 반복해서 사용하는 경우',\n    maze_operation7_1_textset_2: '반복 명령어를 사용하는 경우',\n    maze_operation7_2_textset_1: '반복 횟수',\n    maze_operation7_2_textset_2: '반복할 명령',\n    maze_operation7_4_textset_1: '괄호({})가 빠진 경우',\n    maze_operation7_4_textset_2: '세미콜론(;)이 빠진 경우',\n    study_maze_operation8_title: '8단계 - 반복 명령 알아보기(횟수반복)',\n    study_maze_operation16_title: '4단계 - 반복 명령 알아보기(조건반복)',\n    study_maze_operation1_title: '1단계 - 반복 명령 알아보기(횟수반복)',\n    maze_operation9_title: '9단계 - 반복 명령 알아보기(조건반복)',\n    maze_operation9_1_desc:\n        '앞에서는 몇 번을 반복하는 횟수반복 명령어에 대해 배웠어.</br>이번에는 <span class=\"textShadow\">계속해서 반복하는 명령어</span>를 살펴보자.</br>이 명령어를 사용하면 미션이 끝날 때까지 <b>동일한 행동</b>을 계속 반복하게 돼.</br>이 명령어 역시 괄호({ }) 사이에 반복할 명령어를 넣어 사용할 수 있어!',\n    maze_operation9_2_desc:\n        '예를 들어 이 명령어 <span class=\"textBadge number1\"></span>은 미션을 완료할때까지 반복해서 move(); right()를 실행해.</br><span class=\"textBadge number2\"></span>명령어와 동일한 명령어지.',\n    maze_operation9_3_desc:\n        '이 명령어를 사용할 때도 <span class=\"textShadow\">{ } 안에 반복할 명령어</span>를 잘 입력했는지,</br><span class=\"textShadow\">`true`</span>가 빠지지 않았는지 잘 살펴봐!</br>이 명령어에 대한 자세한 설명은 [명령어 도움말]에서 볼 수 있어.',\n    maze_operation9_1_textset_1: '반복할 명령',\n    maze_operation9_3_textset_1: '괄호({})가 빠진 경우',\n    maze_operation9_3_textset_2: '세미콜론(;)이 빠진 경우',\n    maze_operation9_3_textset_3: 'true가 빠진 경우',\n    study_maze_operation3_title: '3단계 - 반복 명령 알아보기(조건반복)',\n    study_maze_operation4_title: '4단계 - 조건 명령 알아보기',\n    study_ai_operation4_title: '4단계 - 조건 명령과 레이더 알아보기',\n    study_ai_operation6_title: '6단계 - 중첩조건문 알아보기',\n    study_ai_operation7_title: '7단계 - 다양한 비교연산 알아보기',\n    study_ai_operation8_title: '8단계 - 물체 레이더 알아보기',\n    study_ai_operation9_title: '9단계 - 아이템 사용하기',\n    maze_operation10_title: '10단계 - 조건 명령 알아보기',\n    maze_operation10_1_desc:\n        '앞에서는 미션이 끝날 때까지 계속 반복하는 반복 명령어에 대해 배웠어.</br>이번에는 특정한 조건에서만 행동을 하는 <span class=\"textShadow\">조건 명령어</span>를 살펴보자.</br><span class=\"textBadge number2\"></span>에서 보는것처럼 조건 명령어를 사용하면 <b>명령을 보다 효율적으로 잘 내릴 수 있어.</b>',\n    maze_operation10_2_desc:\n        '조건 명령어는 크게 <span class=\"textShadow\">`조건`</span> 과 <span class=\"textShadow\">`조건이 발생했을때 실행되는 명령`</span>으로 나눌수 있어.</br>먼저 <span class=\"textUnderline\">조건</span> 부분을 살펴보자. If 다음에 나오는 <span class=\"textUnderline\">( ) 부분</span>이 조건을 입력하는 부분이야.</br><span class=\"textBadge number1\"></span>과 같은 명령어를 예로 살펴보자. <span class=\"textUnderline\">if(front == “wall”)</span> 는 만약 내 앞에(front) \"wall(벽)\"이 있다면을 뜻해',\n    maze_operation10_3_desc:\n        '이제 <span class=\"textUnderline\">`조건이 발생했을 때 실행되는 명령`</span>을 살펴보자.</br>이 부분은 <span class=\"textShadow\">괄호{}</span>로 묶여 있고, 조건이 발생했을때 괄호안의 명령을 실행하게 돼!</br>조건이 발생하지 않으면 이 부분은 무시하고 그냥 넘어가게 되지.</br><span class=\"textBadge number1\"></span>의 명령어를 예로 살펴보자. 조건은 만약에 `내 앞에 벽이 있을 때` 이고,</br><b>이 조건이 발생했을 때 나는 괄호안의 명령어 right(); 처럼 오른쪽으로 회전하게 돼!</b>',\n    maze_operation10_4_desc:\n        '<span class=\"textShadow\">조건 명령어</span>는 <span class=\"textShadow\">반복하기 명령어</span>와 함께 쓰이는 경우가 많아.</br>앞으로 쭉 가다가, 벽을 만났을때만 회전하게 하려면</br><span class=\"textUnderline pdb5\"><span class=\"textBadge number1\"></span><span class=\"textBadge number2\"></span><span class=\"textBadge number3\"></span>순서</span>와 같이 명령을 내릴 수 있지!',\n    maze_operation10_1_textset_1: '<b>[일반명령]</b>',\n    maze_operation10_1_textset_2:\n        '<span class=\"textMultiline\">앞으로 2칸 가고</br>오른쪽으로 회전하고,</br>앞으로 3칸가고,</br>오른쪽으로 회전하고, 앞으로...</span>',\n    maze_operation10_1_textset_3: '<b>[조건명령]</b>',\n    maze_operation10_1_textset_4:\n        '<span class=\"textMultiline\">앞으로 계속 가다가</br><span class=\"textEmphasis\">`만약에 벽을 만나면`</span></br>오른쪽으로 회전해~!</span>',\n    maze_operation10_2_textset_1: '조건',\n    maze_operation10_2_textset_2: '조건이 발생했을 때 실행되는 명령',\n    maze_operation10_3_textset_1: '조건',\n    maze_operation10_3_textset_2: '조건이 발생했을 때 실행되는 명령',\n    maze_operation10_4_textset_1:\n        '<span class=\"textMultiline\">미션이 끝날때 까지</br>계속 앞으로 간다.</span>',\n    maze_operation10_4_textset_2:\n        '<span class=\"textMultiline\">계속 앞으로 가다가,</br>만약에 벽을 만나면</span>',\n    maze_operation10_4_textset_3:\n        '<span class=\"textMultiline\">계속 앞으로 가다가,</br>만약에 벽을 만나면</br>오른쪽으로 회전한다.</span>',\n    study_maze_operation18_title: '6단계 - 조건 명령 알아보기',\n    maze_operation15_title: '15단계 - 함수 명령 알아보기',\n    maze_operation15_1_desc:\n        '자주 사용하는 명령어들을 매번 입력하는건 매우 귀찮은 일이야.</br>자주 사용하는 <span class=\"textUnderline\">명령어들을 묶어서 이름</span>을 붙이고,</br><b>필요할 때마다 그 명령어 묶음을 불러온다면 훨씬 편리하게 명령을 내릴 수 있어!</b></br>이런 명령어 묶음을  <span class=\"textShadow\">`함수`</span>라고 해. 이제 함수 명령에 대해 자세히 알아보자.',\n    maze_operation15_2_desc:\n        '함수 명령어는 명령어를 묶는 <b>`함수만들기` 과정</b>과,</br>묶은 명령어를 필요할 때 사용하는 <b>`함수 불러오기` 과정</b>이 있어.</br>먼저 함수만들기 과정을 살펴보자.</br>함수를 만들려면 함수의 이름과, 그 함수에 들어갈 명령어를 입력해야 해.</br><span class=\"textShadow\">function</span>을 입력한 다음 <span class=\"textShadow\">함수의 이름</span>을 정할 수 있어. 여기서는 <span class=\"textShadow\">promise</span>로 만들거야.</br>함수 이름을 만들었으면 <span class=\"textUnderline\">()</span>를 붙여줘. 그 다음 <span class=\"textUnderline\">괄호({})</span>를 입력해.</br>그리고 <span class=\"textUnderline\">이 괄호 안에 함수에 들어갈 명령어들을 입력하면</span> 함수가 만들어져!',\n    maze_operation15_3_desc:\n        '이 명령어를 예로 살펴보자. 나는 <span class=\"textShadow\">promise</span> 라는 함수를 만들었어.</br>이 함수를 불러서 실행하면 <span class=\"textUnderline\">괄호({})</span>안에 있는</br>move();</br>move();</br>left(); 가 실행돼!',\n    maze_operation15_4_desc:\n        '함수를 불러와서 실행하려면 아까 만든 <b>함수의 이름을 입력하고 뒤에 `();`를 붙이면 돼.</b></br>promise 라는 이름으로 함수를 만들었으니 <span class=\"textShadow\">promise();</span> 를 입력하면 앞에서 묶어놓은</br>명령어들이 실행되는거지!</br><span class=\"number1 textBadge\"></span>과 같이 명령을 내리면 <span class=\"number2 textBadge\"></span>처럼 동작하게 돼!</br>함수 명령어를 사용하려면 <span class=\"number1 textBadge\"></span>과 같이 함수를 만들고 함수를 불러와야해!',\n    maze_operation15_1_textset_1: '자주 사용하는 명령어 확인하기',\n    maze_operation15_1_textset_2: '명령어들을 묶어서 이름 붙이기',\n    maze_operation15_1_textset_3: '명령어 묶음 불러오기',\n    maze_operation15_2_textset_1: '명령어 묶음의 이름(함수 이름)',\n    maze_operation15_2_textset_2: '묶을 명령어들',\n    maze_operation15_3_textset_1: '명령어 묶음의 이름(함수 이름)',\n    maze_operation15_3_textset_2: '묶을 명령어들',\n    maze_operation15_4_textset_1: '함수 만들기',\n    maze_operation15_4_textset_2: '함수 불러오기',\n    maze_operation15_4_textset_3: '실제 상황',\n    maze_object_title: '오브젝트 정보',\n    maze_object_parts_box: '부품 상자',\n    maze_object_trap: '함정',\n    maze_object_monster: '몬스터',\n    maze_object_obstacle1: '장애물',\n    maze_object_obstacle2: 'bee',\n    maze_object_obstacle3: 'banana',\n    maze_object_friend: '친구',\n    maze_object_wall1: 'wall',\n    maze_object_wall2: 'wall',\n    maze_object_wall3: 'wall',\n    maze_object_battery: '베터리',\n    maze_command_ex: '예시',\n    maze_command_title: '명령어 도움말',\n    maze_command_move_desc: '엔트리봇을 한 칸 앞으로 이동시킵니다.',\n    maze_command_jump_desc:\n        '아래 이미지와 같은 장애물 앞에서 장애물을 뛰어 넘습니다.</br><div class=\"obstacleSet\"></div>',\n    maze_command_jump_desc_elec:\n        '아래 이미지와 같은 장애물 앞에서 장애물을 뛰어 넘습니다.</br><div class=\"obstacle_elec\"></div>',\n    maze_command_right_desc: '제자리에서 오른쪽으로 90도 회전합니다.',\n    maze_command_left_desc: '제자리에서 왼쪽으로 90도 회전합니다.',\n    maze_command_for_desc:\n        '괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 <span class=\"textShadow\">입력한 횟수</span> 만큼 반복해서 실행합니다.',\n    maze_command_while_desc:\n        '미션이 끝날 때가지 괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 계속 반복해서 실행합니다.',\n    maze_command_slow_desc: '아래 이미지와 같은 방지턱을 넘습니다.</br><div class=\"hump\"></div>',\n    maze_command_if1_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 벽이 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_if2_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 벌집이 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_if3_desc:\n        '조건 <span class=\"textShadow\">`바로 앞에 바나나가 있을때`</span>이 발생했을 때,</br>괄호<span class=\"textShadow\">{}</span> 안에 있는 명령을 실행합니다.',\n    maze_command_promise_desc:\n        'promise 라는 <span class=\"textShadow\">함수</span>를 만들고 실행하면 괄호<span class=\"textShadow\">{}</span> 안에</br>있던 명령어가 실행합니다.',\n    perfect: '아주 완벽해!  ',\n    succeeded_using_blocks: ' 개의 블록을 사용해서 성공했어!',\n    succeeded_using_commands: ' 개의 명령어를 사용해서 성공했어!',\n    awesome: '대단한 걸!',\n    succeeded_go_to_next: '개의 블록만으로 성공했어! <br> 다음 단계로 넘어가자.',\n    good: '좋아! ',\n    but: '<br> 하지만, ',\n    try_again: ' 개의 블록만으로 성공하는 방법도 있어. <br> 다시 도전해 보는건 어때?',\n    try_again_commands: ' 개의 명렁어만으로 성공하는 방법도 있어. <br> 다시 도전해 보는건 어때?',\n    cfest_success:\n        '대단한걸! 덕분에 친구들을 구할 수 있었어! <br> 아마도 너는 타고난 프로그래머 인가봐! <br> 나중에 또 만나자~!',\n    succeeded_and_cert: '개의 블록만으로 성공했어! <br>인증서를 받으러 가자.',\n    cause_msgs_1: '에구, 앞으로 갈 수 없는 곳이였어. 다시 해보자.',\n    cause_msgs_2: '히잉. 그냥 길에서는 뛰어 넘을 곳이 없어. 다시 해보자.',\n    cause_msgs_3: '에고고, 아파라. 뛰어 넘었어야 했던 곳이였어. 다시 해보자.',\n    cause_msgs_4: '아쉽지만, 이번 단계에서는 꼭 아래 블록을 써야만 해. <br> 다시 해볼래?',\n    cause_msgs_5: '이런, 실행할 블록들이 다 떨어졌어. 다시 해보자.',\n    cause_msgs_6: '이런, 실행할 명령어들이 다 떨어졌어. 다시 해보자.',\n    close_experience: '체험<br>종료',\n    replay: '다시하기',\n    go_to_next_level: '다음단계 가기',\n    move_forward: '앞으로 한 칸 이동',\n    turn_left: '왼쪽',\n    turn_right: '오른쪽',\n    turn_en: '',\n    turn_ko: '으로 회전',\n    jump_over: '뛰어넘기',\n    when_start_is_pressed: '시작하기를 클릭했을 때',\n    repeat_until_ko: '만날 때 까지 반복',\n    repeat_until_en: '',\n    repeat_until: '만날 때 까지 반복',\n    if_there_is_1: '만약 앞에 ',\n    if_there_is_2: '있다면',\n    used_blocks: '사용 블록',\n    maximum: '목표 블록',\n    used_command: '사용 명령어 갯수',\n    maximum_command: '목표 명령어 갯수',\n    block_box: '블록 꾸러미',\n    block_assembly: '블록 조립소',\n    command_box: '명령어 꾸러미',\n    command_assembly: '명령어 조립소',\n    start: '시작하기',\n    engine_running: '실행중',\n    engine_replay: '돌아가기',\n    goto_show: '보러가기',\n    make_together: '함께 만드는 엔트리',\n    make_together_content:\n        '엔트리는 학교에 계신 선생님들과 학생 친구들이 함께 고민하며 만들어갑니다.',\n    project_nobody_like: \"이 작품이 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    project_nobody_interest: \"'관심 작품'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    lecture_nobody_like: \"이 강의가 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    lecture_nobody_interest: \"'관심 강의'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    course_nobody_like: \"이 강의 모음이 마음에 든다면 '좋아요'를 눌러 주세요.\",\n    course_nobody_interest: \"'관심 강의 모음'을 누르면 마이 페이지에서 볼 수 있어요.\",\n    before_changed: '변경전',\n    after_changed: '변경후',\n    from_changed: '( 2016년 04월 17일 부터 ) ',\n    essential: '필수',\n    access_term_title:\n        '안녕하세요. 엔트리 교육연구소 입니다. <br>  엔트리를 사랑해주시는 여러분께 감사드리며,  <br>  엔트리 교육연구소 웹사이트 이용약관이<br>  2016년 4월 17일 부로 다음과 같이 개정됨을 알려드립니다. ',\n    member_info: '회원 안내',\n    personal_info: '개인정보 수집 및 이용에 동의 합니다.',\n    option: '선택',\n    news: '최신소식',\n    edu_material: '교육자료',\n    latest_news: '최근소식',\n    edu_data: '교육자료',\n    training_program: '연수지원',\n    footer_phrase:\n        '엔트리는 누구나 무료로 소프트웨어 교육을 받을 수 있게 개발된 비영리 교육 플랫폼입니다.',\n    footer_use_free:\n        '모든 엔트리교육연구소의 저작물은 교육적 목적에 한하여 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    footer_description_1:\n        '엔트리는 비영리 교육 플랫폼으로 모든 엔트리의 저작물은 교육 목적에 한해 출처를 밝히고 자유롭게 이용할 수 있습니다.',\n    footer_description_2: '',\n    nonprofit_platform: '비영리 교육 플랫폼',\n    this_is: '입니다.',\n    privacy: '개인정보 처리방침',\n    entry_addr: '경기도 성남시 분당구 불정로 6 NAVER 그린팩토리 16층',\n    entry_addr_additional_phone: '1522-9182',\n    entry_addr_additional_email: 'entry@connect.or.kr',\n    entry_addr_additional_opensource: '오픈소스 라이선스',\n    phone: '전화번호',\n    alert_agree_term: '이용약관에 동의하여 주세요.',\n    alert_private_policy: '개인정보 수집 약관에 동의하여 주세요.',\n    agree: '동의',\n    optional: '선택',\n    start_software: '소프트웨어 교육의 첫걸음',\n    analyze_procedure: '절차',\n    analyze_repeat: '반복',\n    analyze_condition: '분기',\n    analyze_interaction: '상호작용',\n    analyze_dataRepresentation: '데이터 표현',\n    analyze_abstraction: '추상화',\n    analyze_sync: '병렬 및 동기화',\n    jr_intro_1: '안녕! 난 쥬니라고 해! 내 친구 엔트리봇이 오른쪽에 있어! 날 친구에게 데려다 줘!',\n    jr_intro_2: '엔트리봇이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    jr_intro_3: '엔트리봇이 위쪽에 있어! 친구를 만날 수 있도록 도와줘!',\n    jr_intro_4: '어서 엔트리봇을 만나러 가자! 아래쪽으로 가보는거야~ ',\n    jr_intro_5: '우왓! 내 친구가 멀리 떨어져있어. 엔트리봇이 있는 곳까지 안내해줄래? ',\n    jr_intro_6: '저기 엔트리봇이 있어~ 얼른 만나러 가보자.',\n    jr_intro_7: '예쁜 꽃이 있네. 꽃들을 모아 엔트리봇에게 가보자!',\n    jr_intro_8: '가는 길에 꽃이 있어! 꽃을 모아 엔트리봇에게 가보자!',\n    jr_intro_9: '엔트리봇이 멀리 떨어져 있네? 가장 빠른 길로 엔트리봇에게 가 보자.',\n    jr_intro_10: '엔트리봇을 만나러 가는 길에 꽃을 모두 모아서 가보자.',\n    jr_intro_11:\n        '엔트리봇에게 가려면 오른쪽으로 다섯번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    jr_intro_12: '반복하기를 사용해서 엔트리봇을 만나러 가자.',\n    jr_intro_13:\n        '지금 블록으로는 친구에게 갈 수가 없어. 반복 횟수를 바꿔 엔트리봇에게 갈 수 있게 해줘.',\n    jr_intro_14: '반복 블록을 사용하여 엔트리봇에게 데려다 줘.',\n    jr_intro_15:\n        '엔트리봇이 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 엔트리봇에게 갈 수 있을 거야.',\n    jr_whats_ur_name: '내가 받을 인증서에 적힐 이름은?',\n    jr_down_cert: '인증서 받기',\n    jr_popup_prefix_1: '좋아! 엔트리봇을 만났어!',\n    jr_popup_prefix_2:\n        '우왓! 엔트리봇을 만났어! <br> 하지만 엔트리봇을 만나기에는 더 적은 블록을 사용해서도 <br> 만날 수 있는데 다시 해볼래? ',\n    jr_popup_prefix_3: '좋아! 책가방을 챙겼어!',\n    jr_popup_prefix_4:\n        '우왓! 책가방이 있는 곳으로 왔어! 하지만 더 적은 블록을 사용해도 책가방 쪽으로 갈 수 있는데 다시 해볼래?',\n    jr_popup_suffix_1:\n        '고마워~ 덕분에 책가방을 챙겨서 학교에 올 수 있었어~ 다음 학교 가는 길도 함께 가자~',\n    jr_popup_suffix:\n        '고마워~ 덕분에 엔트리봇이랑 재밌게 놀 수 있었어~ <br>다음에 또 엔트리봇이랑 놀자~',\n    jr_fail_dont_go: '에궁, 그 곳으로는 갈 수 없어. 가야하는 길을 다시 알려줘~',\n    jr_fail_dont_know: '어? 이제 어디로 가지? 어디로 가야하는 지 더 알려줘~',\n    jr_fail_no_flower: '이런 그곳에는 꽃이 없어. 꽃이 있는 곳에서 사용해보자~',\n    jr_fail_forgot_flower: '앗! 엔트리봇한테 줄 꽃을 깜빡했어. 꽃을 모아서 가자~',\n    jr_fail_need_repeat: '반복 블록이 없잖아! 반복 블록을 사용해서 해보자~',\n    jr_hint_1: '안녕! 난 쥬니라고 해! 내 친구 엔트리봇이 오른쪽에 있어! 날 친구에게 데려다 줘!',\n    jr_hint_2: '엔트리봇이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    jr_hint_3: '엔트리봇이 위쪽에 있어! 친구를 만날 수 있도록 도와줘!',\n    jr_hint_4: '어서 엔트리봇을 만나러 가자! 아래쪽으로 가보는거야~',\n    jr_hint_5: '우왓! 내 친구가 멀리 떨어져있어. 엔트리봇이 있는 곳까지 안내해줄래?',\n    jr_hint_6:\n        '잘못된 블록들 때문에 친구에게 가지 못하고 있어, 잘못된 블록을 지우고 엔트리봇에게 갈 수 있도록 해줘!',\n    jr_hint_7: '예쁜 꽃이 있네. 꽃들을 모아 엔트리봇에게 가보자!',\n    jr_hint_8: '가는 길에 꽃이 있어! 꽃을 모아 엔트리봇에게 가보자!',\n    jr_hint_9: '엔트리봇이 멀리 떨어져 있네? 가장 빠른 길로 엔트리봇에게 가 보자.',\n    jr_hint_10:\n        '앗, 블록을 잘못 조립해서 제대로 갈 수가 없어. 가는 길에 꽃을 모두 모아 엔트리봇에게 가져다 줄 수 있도록 고쳐 보자.',\n    jr_hint_11:\n        '엔트리봇에게 가려면 오른쪽으로 다섯번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    jr_hint_12: '반복하기를 사용해서 엔트리봇을 만나러 가자.',\n    jr_hint_13:\n        '지금 블록으로는 친구에게 갈 수가 없어. 반복 횟수를 바꿔 엔트리봇에게 갈 수 있게 해줘.',\n    jr_hint_14: '반복 블록을 사용하여 엔트리봇에게 데려다 줘.',\n    jr_hint_15:\n        '엔트리봇이 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 엔트리봇에게 갈 수 있을 거야.',\n    jr_certification: '인증서',\n    jr_congrat: '축하드립니다!',\n    jr_congrat_msg: '문제해결 과정을 성공적으로 마쳤습니다.',\n    jr_share: '공유',\n    go_see_friends: '친구들 만나러 가요~!',\n    junior_naver: '쥬니어 네이버',\n    junior_naver_contents_1: \"의 멋진 곰 '쥬니'가 엔트리를 찾아 왔어요! \",\n    junior_naver_contents_2: '그런데 쥬니는 길을 찾는 것이 아직 어렵나봐요.',\n    junior_naver_contents_3: '쥬니가 엔트리봇을 만날 수 있도록 가야하는 방향을 알려주세요~',\n    basic_content: '기초',\n    jr_help: '도움말',\n    help: '도움말',\n    cparty_robot_intro_1:\n        '안녕 나는 엔트리봇이야. 난 부품을 얻어서 내몸을 고쳐야해. 앞으로 가기 블록으로 부품을 얻게 도와줘!',\n    cparty_robot_intro_2:\n        '좋아! 앞에도 부품이 있는데 이번에는 잘못 가다간 감전되기 쉬울 것 같아. 뛰어넘기 블록을 써서 부품까지 데려다 줘.',\n    cparty_robot_intro_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 회전하기 블록을 쓰면 충분히 갈 수 있을 것 같아! ',\n    cparty_robot_intro_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 회전과 뛰어넘기를 같이 써서 저 부품을 얻어보자! ',\n    cparty_robot_intro_5:\n        '덕분에 몸이 아주 좋아졌어! 이번에도 회전과 뛰어넘기를 같이 써야 할 거야! 어서 가보자!',\n    cparty_robot_intro_6:\n        '멋져! 이제 몸이 많이 좋아져서, 똑같은 일은 여러 번 해도 괜찮을 거야! 한 번 반복하기를 사용해서 가보자!',\n    cparty_robot_intro_7:\n        '어? 중간중간에 뛰어넘어야 할 곳이 있어! 그래도 반복하기로 충분히 갈 수 있을 거야!',\n    cparty_robot_intro_8:\n        '이런! 이번에는 부품이 저기 멀리 떨어져 있어. 그래도 반복하기를 사용하면 쉽게 갈수 있지! 얼른 도와줘!',\n    cparty_robot_intro_9:\n        '우와~ 이제 내 몸이 거의 다 고쳐진 것 같아! 이번에도 반복하기를 이용해서 부품을 구하러 가보자!',\n    cparty_robot_intro_10:\n        '대단해! 이제 마지막 부품만 있으면 내 몸을 완벽하게 고칠 수 있을 거야! 빨리 반복하기로 도와줘!',\n    cparty_car_intro_1:\n        '안녕! 나는 엔트리봇이라고 해, 자동차를 타고 계속 이동하려면 연료가 필요해! 앞에 있는 연료를 얻을 수 있게 도와줄래?',\n    cparty_car_intro_2:\n        '좋아! 그런데 이번에는 길이 직선이 아니네! 왼쪽/오른쪽 돌기 블록으로 잘 운전해서 함께 연료를 얻으러 가볼까?',\n    cparty_car_intro_3:\n        '잘했어! 이번 길 앞에는 과속방지턱이 있어. 빠르게 운전하면 사고가 날 수도 있을 것 같아, 천천히 가기 블록을 써서 연료를 얻으러 가보자!',\n    cparty_car_intro_4:\n        '야호, 이제 운전이 한결 편해졌어! 이 도로에서는 반복하기 블록을 사용해서 연료를 채우러 가볼까?',\n    cparty_car_intro_5:\n        '와 이번 도로는 조금 복잡해 보이지만, 앞으로 가기와 왼쪽/오른쪽 돌기 블록을 반복하면서 가보면 돼! 차분하게 연료까지 가보자',\n    cparty_car_intro_6:\n        '이번에는 도로에 장애물이 있어서 잘 돌아가야 될 것 같아, 만약에 장애물이 앞에 있다면 어떻게 해야 하는지 알려줘!',\n    cparty_car_intro_7:\n        '좋아 잘했어! 한번 더 만약에 블록을 사용해서 장애물을 피해 연료를 얻으러 가보자!',\n    cparty_car_intro_8:\n        '앗 아까 만났던 과속 방지턱이 두 개나 있네, 천천히 가기 블록을 이용해서 안전하게 연료를 채우러 가보자!',\n    cparty_car_intro_9:\n        '복잡해 보이는 길이지만, 앞에서 사용한 반복 블록과 만약에 블록을 잘 이용하면 충분히 운전할 수 있어, 연료를 채울 수 있도록 도와줘!',\n    cparty_car_intro_10:\n        '정말 멋져! 블록의 순서를 잘 나열해서 이제 마지막 남은 연료를 향해 힘을 내어 가보자!',\n    cparty_car_popup_prefix_1: '좋아! 연료를 얻었어!',\n    cparty_car_popup_prefix_2:\n        '우왓! 연료를 얻었어! <br> 하지만 연료를 얻기에는 더 적은 블록을 사용해서도 <br> 얻을 수 있는데 다시 해볼래? ',\n    cparty_car_popup_prefix_2_text:\n        '우왓! 연료를 얻었어! <br> 하지만 연료를 얻기에는 더 적은 명령어 사용해서도 <br> 얻을 수 있는데 다시 해볼래? ',\n    cparty_car_popup_suffix:\n        '고마워~ 덕분에 모든 배터리를 얻을 수 있었어~ <br>다음에 또 나랑 놀자~',\n    all_grade: '모든 학년',\n    grade_e3_e4: '초등 3 ~ 4 학년 이상',\n    grade_e5_e6: '초등 5 ~ 6 학년 이상',\n    grade_m1_m3: '중등 1 ~ 3 학년 이상',\n    entry_first_step: '엔트리 첫걸음',\n    entry_monthly: '월간 엔트리',\n    play_sw_2: 'EBS 소프트웨어야 놀자2',\n    entry_programming: '실전, 프로그래밍!',\n    entry_recommanded_course: '엔트리 추천 코스',\n    introduce_course:\n        '누구나 쉽게 보고 따라하면서 재미있고 다양한 소프트웨어를 만들 수 있는 강의 코스를 소개합니다.',\n    all_free: '*강의 동영상, 만들기, 교재 등이 모두 무료로 제공됩니다.',\n    cparty_result_fail_1: '에궁, 그 곳으로는 갈 수 없어. 가야하는 길을 다시 알려줘~',\n    cparty_result_fail_2: '에고고, 아파라. 뛰어 넘었어야 했던 곳이였어. 다시 해보자.',\n    cparty_result_fail_3:\n        '아이고 힘들다. 아래 블록들을 안 썼더니 너무 힘들어! 아래 블록들로 다시 만들어줘.',\n    cparty_result_fail_4: '어? 이제 어디로 가지? 어디로 가야하는 지 더 알려줘~',\n    cparty_result_fail_5: '앗! 과속방지턱에서는 속도를 줄여야해. 천천히 가기 블록을 사용해보자~',\n    cparty_result_success_1: '좋아! 부품을 얻었어!',\n    cparty_result_success_2:\n        '우왓! 부품을 얻었어! <br>하지만 부품을 얻기에는 더 적은 블록을 사용해서도 얻을 수 있는데 다시 해볼래?',\n    cparty_result_success_2_text:\n        '우왓! 부품을 얻었어! <br>하지만 부품을 얻기에는 더 적은 명령어를 사용해서도 얻을 수 있는데 다시 해볼래?',\n    cparty_result_success_3: '고마워~ 덕분에 내몸이 다 고쳐졌어~ 다음에 또 나랑 놀자~',\n    cparty_insert_name: '이름을 입력하세요.',\n    offline_file: '파일',\n    offline_edit: '편집',\n    offline_undo: '되돌리기',\n    offline_redo: '다시실행',\n    offline_copy: '복사',\n    offline_paste: '붙여넣기',\n    offline_cut: '자르기',\n    offline_quit: '종료',\n    select_one: '선택해 주세요.',\n    evaluate_challenge: '도전해본 미션의 난이도를 평가해 주세요.',\n    very_easy: '매우쉬움',\n    easy: '쉬움',\n    normal: '보통',\n    difficult: '어려움',\n    very_difficult: '매우 어려움',\n    save_dismiss: '바꾼 내용을 저장하지 않았습니다. 계속 하시겠습니까?',\n    entry_info: '엔트리 정보',\n    actual_size: '실제크기',\n    zoom_in: '확대',\n    zoom_out: '축소',\n    cparty_jr_intro_1:\n        '안녕! 난 엔트리봇 이라고 해! 학교가는 길에 책가방을 챙길 수 있도록 도와줘! ',\n    cparty_jr_intro_2: '책가방이 내 왼쪽에 있어! 왼쪽으로 가보자.',\n    cparty_jr_intro_3: '책가방이 위쪽에 있어! 책가방을 챙길 수 있도록 도와줘!',\n    cparty_jr_intro_4: '어서 책가방을 챙기러 가자! 아래쪽으로 가보는 거야~',\n    cparty_jr_intro_5: '우왓! 내 책가방이 멀리 떨어져 있어. 책가방이 있는 곳까지 안내해줄래?',\n    cparty_jr_intro_6: '책가방이 있어! 얼른 가지러 가자~',\n    cparty_jr_intro_7: '길 위에 내 연필이 있네. 연필들을 모아 책가방을 챙기러 가보자!',\n    cparty_jr_intro_8: '학교 가는 길에 연필이 있어! 연필을 모아 책가방을 챙기러 가보자!',\n    cparty_jr_intro_9: '내 책가방이 멀리 떨어져 있네? 가장 빠른 길로 책가방을 챙기러 가 보자.',\n    cparty_jr_intro_10: '가는 길에 연필을 모두 모으고 책가방을 챙기자!',\n    cparty_jr_intro_11:\n        '책가방을 챙기러 가려면 오른쪽으로 다섯 번이나 가야 하잖아? 반복하기 블록을 사용해서 좀 더 쉽게 가 보자.',\n    cparty_jr_intro_12: '반복하기를 사용해서 책가방을 챙기러 가자.',\n    cparty_jr_intro_13:\n        '지금 블록으로는 책가방이 있는 쪽으로 갈 수가 없어. 반복 횟수를 바꿔 책가방을 챙기러 갈 수 있게 해줘.',\n    cparty_jr_intro_14: '반복 블록을 사용하여 책가방을 챙기러 가줘.',\n    cparty_jr_intro_15:\n        '학교가 정~말 멀리 있잖아? 그래도 반복 블록을 사용하면 쉽게 학교에 도착 할수 있을 거야.',\n    make_new_project: '새로운 작품 만들기',\n    open_old_project: '저장된 작품 불러오기',\n    offline_download: '엔트리 다운로드',\n    offline_release: '엔트리 오프라인 에디터 출시!',\n    offline_description_1: '엔트리 오프라인 버전은',\n    offline_description_2: '인터넷이 연결되어 있지 않아도 사용할 수 있습니다. ',\n    offline_description_3: '지금 다운받아서 시작해보세요!',\n    sw_week_2015: '2015 소프트웨어교육 체험 주간',\n    cparty_desc: '두근두근 소프트웨어와의 첫만남',\n    entry_offline_download: '엔트리 오프라인 \\n다운로드',\n    entry_download_detail: '다운로드\\n바로가기',\n    offline_desc_1: '엔트리 오프라인 버전은 인터넷이 연결되어 있지 않아도 사용할 수 있습니다.',\n    offline_desc_2: '지금 다운받아서 시작해보세요!',\n    download: '다운로드',\n    version: '버전',\n    file_size: '크기',\n    update: '업데이트',\n    use_range: '사용범위',\n    offline_desc_free: '엔트리 오프라인은 기업과 개인 모두 제한 없이 무료로 사용하실 수 있습니다.',\n    offline_required: '최소 요구사항',\n    offline_required_detail:\n        '디스크 여유 공간 1GB 이상, Windows 8 이상 혹은 macOS 10.8 이상의 운영체제, 디스크 여유 공간 1GB 이상',\n    offline_notice: '설치 전 참고사항',\n    offline_notice_1: '1. 버전',\n    offline_notice_1_1: '에서는 하드웨어 연결 프로그램이 내장되어 있습니다.',\n    offline_notice_2: '2. 별도의 웹브라우져가 필요하지 않습니다.',\n    offline_notice_3: '버전 별 변경 사항 안내',\n    offline_notice_4: '버전별 다운로드',\n    offline_notice_5: '버전별 자세한 변경 사항 보기',\n    hardware_online_badge: '온라인',\n    hardware_title: '엔트리 하드웨어 연결 프로그램 다운로드',\n    hardware_desc:\n        '엔트리 온라인 ‘작품 만들기’에서 하드웨어를 연결하여 엔트리를 이용하는 경우에만 별도로 설치가 필요합니다.',\n    hardware_release:\n        '하드웨어 연결 프로그램의 자세한 변경 사항은 아래 주소에서 확인 할 수 있습니다.',\n    hardware_window_download: 'Windows 다운로드',\n    hardware_osx_download: 'Mac 다운로드',\n    cparty_jr_result_2:\n        '고마워~ 덕분에 책가방을 챙겨서 학교에 올 수 있었어~ <br>다음 학교 가는 길도 함께 가자~ ',\n    cparty_jr_result_3:\n        '우왓! 학교까지 왔어! <br>하지만 더 적은 블록을 사용해도 학교에 갈 수 있는데<br> 다시 해볼래?',\n    cparty_jr_result_4:\n        '우왓! 책가방을 얻었어!<br> 하지만 더 적은 블록을 사용해도 책가방을 얻을 수 있는데 <br>다시 해볼래? ',\n    lms_no_class: '아직 만든 학급이 없습니다.',\n    lms_create_class: '학급을 만들어 주세요.',\n    lms_add_class: '학급 만들기',\n    lms_base_class: '기본',\n    lms_delete_class: '삭제',\n    lms_my_class: '나의 학급',\n    lms_grade_1: '초등 1',\n    lms_grade_2: '초등 2',\n    lms_grade_3: '초등 3',\n    lms_grade_4: '초등 4',\n    lms_grade_5: '초등 5',\n    lms_grade_6: '초등 6',\n    lms_grade_7: '중등 1',\n    lms_grade_8: '중등 2',\n    lms_grade_9: '중등 3',\n    lms_grade_10: '일반',\n    lms_add_groupId_personal: '선생님께 받은 학급 아이디를 입력하여, 회원 정보에 추가하세요.',\n    lms_add_groupId: '학급 아이디 추가하기',\n    lms_add_group_account: '학급 계정 추가',\n    lms_enter_group_info: '발급받은 학급 아이디와 비밀번호를 입력하세요.',\n    lms_group_id: '학급 아이디',\n    lms_group_pw: '비밀번호',\n    lms_group_name: '소속 학급명',\n    personal_pwd_alert: '올바른 비밀번호 양식을 입력해 주세요',\n    personal_form_alert: '양식을 바르게 입력해 주세요',\n    personal_form_alert_2: '모든 양식을 완성해 주세요',\n    personal_no_pwd_alert: '비밀번호를 입력해 주세요',\n    select_gender: '성별을 선택해 주세요',\n    enter_group_id: '학급 아이디를 입력해 주세요',\n    enter_group_pwd: '비밀번호를 입력해 주세요',\n    info_added: '추가되었습니다',\n    no_group_id: '학급 아이디가 존재하지 않습니다',\n    no_group_pwd: '비밀번호가 일치하지 않습니다',\n    lms_please_choice: '선택해 주세요.',\n    group_lesson: '나의 학급 강의',\n    lms_banner_add_group: '학급 기능 도입',\n    lms_banner_entry_group: '엔트리 학급 만들기',\n    lms_banner_desc_1: '우리 반 학생들을 엔트리에 등록하세요!',\n    lms_banner_desc_2: '이제 보다 편리하고 쉽게 우리 반 학생들의 작품을 찾고,',\n    lms_banner_desc_3: '성장하는 모습을 확인할 수 있습니다. ',\n    lms_banner_download_manual: '메뉴얼 다운로드',\n    lms_banner_detail: '자세히 보기',\n    already_exist_email: '이미 존재하는 이메일 입니다.',\n    same_registered_email: '중복된 이메일 입니다.',\n    email_correnctly_please: '양식을 올바르게 입력해주세요.',\n    remove_project: '작품을 삭제하시겠습니까?',\n    study_lesson: '우리 반 학습하기',\n    open_project: '작품 불러오기',\n    make_group: '학급 만들기',\n    project_share: '작품 공유하기',\n    group_project_share: '학급 공유하기',\n    group_discuss: '학급 글 나누기',\n    my_profile: '마이 페이지',\n    search_updated: '최신 작품',\n    search_recent: '최근 조회수 높은 작품',\n    search_complexity: '최근 제작에 공들인 작품',\n    search_staffPicked: '스태프선정 작품 저장소',\n    search_childCnt: '사본이 많은 작품',\n    search_likeCnt: '최근 좋아요가 많은 작품',\n    search_recentLikeCnt: '최근 좋아요가 많은 작품',\n    gnb_share: '공유하기',\n    gnb_community: '커뮤니티',\n    lms_add_lectures: '강의 올리기',\n    lms_add_course: '강의 모음 올리기',\n    lms_add_homework: '과제 올리기',\n    remove_lecture_confirm: '강의를 정말 삭제하시겠습니까?',\n    popup_delete: '삭제하기',\n    remove_course_confirm: '강의 모음을 정말 삭제하시겠습니까?',\n    lms_no_lecture_teacher_1: '추가된 강의가 없습니다.',\n    lms_no_lecture_teacher_2: '우리 반 강의를 추가해 주세요.',\n    gnb_download: '다운로드',\n    lms_no_lecture_student_1: '아직 올라온 강의가 없습니다.',\n    lms_no_lecture_student_2: '선생님이 강의를 올려주시면,',\n    lms_no_lecture_student_3: '학습 내용을 확인할 수 있습니다.',\n    lms_no_class_teacher: '아직 만든 학급이 없습니다.',\n    lms_no_course_teacher_1: '추가된 강의 모음이 없습니다.',\n    lms_no_course_teacher_2: '우리 반 강의 모음을 추가해 주세요.',\n    lms_no_course_student_1: '아직 올라온 강의 모음이 없습니다.',\n    lms_no_course_student_2: '선생님이 강의 모음을  올려주시면,',\n    lms_no_course_student_3: '학습 내용을 확인할 수 있습니다.',\n    lms_no_hw_teacher_1: '추가된 과제가 없습니다.',\n    lms_no_hw_teacher_2: '우리 반 과제를 추가해 주세요.',\n    lms_no_hw_student_1: '아직 올라온 과제가 없습니다.',\n    lms_no_hw_student_2: '선생님이 과제를 올려주시면,',\n    lms_no_hw_student_3: '학습 내용을 확인할 수 있습니다.',\n    modal_edit: '수정하기',\n    modal_deadline: '마감일 설정',\n    modal_hw_desc: '상세설명 (선택)',\n    desc_optional: '',\n    modal_create_hw: '과제 만들기',\n    vol: '회차',\n    hw_title: '과제명',\n    hw_description: '내용',\n    deadline: '마감일',\n    do_homework: '과제하기',\n    hw_progress: '진행 상태',\n    hw_submit: '제출',\n    view_list: '명단보기',\n    view_desc: '내용보기',\n    do_submit: '제출하기',\n    popup_notice: '알림',\n    no_selected_hw: '선택된 과제가 없습니다.',\n    hw_delete_confirm: '선택한 과제를 정말 삭제하시겠습니까?',\n    hw_submitter: '과제 제출자 명단',\n    hw_student_desc_1: \"* '제출하기'를 눌러 제출을 완료하기 전까지 얼마든지 수정이 가능합니다\",\n    hw_student_desc_2: '* 제출 기한이 지나면 과제를 제출할 수 없습니다.',\n    popup_create_class: '학급 만들기',\n    class_name: '학급 이름',\n    image: '이미지',\n    select_class_image: '학급 이미지를 선택해 주세요.',\n    type_class_description: '학급 소개 입력',\n    set_as_primary_group: '기본학급으로 지정',\n    set_primary_group: '지정',\n    not_primary_group: '지정안함',\n    type_class_name: '학급 이름을 입력해주세요. ',\n    type_class_description_long: '학급 소개를 입력해 주세요. 170자 이내',\n    add_students: '학생 추가하기',\n    invite_students: '학생 초대하기',\n    invite_with_class: '1. 학급 코드로 초대하기',\n    invite_code_expiration: '코드 만료시간',\n    generate_code_button: '코드재발급',\n    generate_code_desc: '학생의 학급 코드 입력 방법',\n    generate_code_desc1: '엔트리 홈페이지에서 로그인을 해주세요.',\n    generate_code_desc2: '메뉴바에서<나의 학급>을 선택해주세요.',\n    generate_code_desc3: '<학급코드 입력하기>를 눌러 학급코드를 입력해주세요.',\n    invite_with_url: '2. 학급 URL로 초대하기',\n    copy_invite_url: '복사하기',\n    download_as_pdf: '학급계정 PDF로 내려받기',\n    download_as_excel: '학급계정 엑셀로 내려받기',\n    temp_password: '임시 비밀번호 발급',\n    can_not_change: '변경 불가',\n    step_name: '이름 입력',\n    step_info: '정보 추가/수정',\n    preview: '미리보기',\n    type_name_enter: '학급에 추가할 학생의 이름을 입력하고 엔터를 치세요.',\n    multiple_name_possible: '여러명의 이름 입력이 가능합니다.',\n    id_auto_create: '학번은 별도로 수정하지 않으면 자동으로 생성됩니다.',\n    student_id_desc_1: '학급 아이디는 별도의 입력없이 자동으로 생성됩니다.',\n    student_id_desc_2: '단, 엔트리에 이미 가입된 학생을 학급에 추가한다면 학생의 엔트리 아이디를',\n    student_id_desc_3: '입력해주세요. 해당 학생은 로그인 후, 학급 초대를 수락하면 됩니다.',\n    student_number: '학번',\n    temp_password_desc_1: '임시 비밀번호로 로그인 후,',\n    temp_password_desc_2: '신규 비밀번호를 다시 설정할 수 있도록 안내해주세요.',\n    temp_password_desc_3: '*한번 발급된 임시 비밀번호는 다시 볼 수 없습니다.',\n    temp_password_demo: '로그인 불가능한 안내 용 예시 계정입니다.',\n    temp_works: '작품 보기',\n    student_delete_confirm: '학생을 정말 삭제하시겠습니까?',\n    no_student_selected: '선택된 학생이 없습니다.',\n    class_assignment: '학급 과제',\n    class_list: '학급 목록',\n    select_grade: '학년을 선택 하세요.',\n    add_project: '작품 공유하기',\n    no_project_display: '학생들이 전시한 작품이 없습니다.',\n    plz_display_project: '나의 작품을 전시해 주세요.',\n    refuse_confirm: '학급 초대를 정말 거절하시겠습니까?',\n    select_class: '학급 선택',\n    group_already_registered: '이미 가입된 학급입니다.',\n    my_page_entry: '엔트리',\n    my_page_title: '마이페이지',\n    my_classGroup_title: '나의 학급',\n    my_classGroup_title_view: '나의 학급 보기',\n    my_space_area: '나만의 공간',\n    mon: '월',\n    tue: '화',\n    wed: '수',\n    thu: '목',\n    fri: '금',\n    sat: '토',\n    sun: '일',\n    jan: '1월',\n    feb: '2월',\n    mar: '3월',\n    apr: '4월',\n    may: '5월',\n    jun: '6월',\n    jul: '7월',\n    aug: '8월',\n    sep: '9월',\n    oct: '10월',\n    nov: '11월',\n    dec: '12월',\n    plz_select_lecture: '강의를 선택해 주세요.',\n    plz_set_deadline: '마감일을 설정해 주세요.',\n    hide_entry: '엔트리 가리기',\n    hide_others: '기타 가리기',\n    show_all: '모두 보기',\n    lecture_description:\n        '선생님들이 직접 만드는 엔트리 학습 공간입니다. 강의에서 예시작품을 보고 작품을 만들며 배워 보세요.',\n    curriculum_description:\n        '학습 순서와 주제에 따라 여러 강의가 모아진 학습 공간입니다. 강의 모음의 순서에 맞춰 차근차근 배워보세요.',\n    linebreak_off_desc_1: '글상자의 크기가 글자의 크기를 결정합니다.',\n    linebreak_off_desc_2: '내용을 한 줄로만 작성할 수 있습니다.',\n    linebreak_off_desc_3: '새로운 글자가 추가되면 글상자의 좌우 길이가 길어집니다.',\n    linebreak_on_desc_1: '글상자의 크기가 글자가 쓰일 수 있는 영역을 결정합니다.',\n    linebreak_on_desc_2: '내용 작성시 엔터키로 줄바꿈을 할 수 있습니다.',\n    linebreak_on_desc_3:\n        '새로운 글자 추가 시 문장의 길이가 글상자의 가로 영역을 넘어가면 자동으로 줄이 바뀝니다.',\n    not_supported_text: '해당 글씨체는 한자를 지원하지 않습니다.',\n    entry_with: '함께 만드는 엔트리',\n    ebs_season_1: '시즌 1 보러가기',\n    ebs_season_2: '시즌 2 보러가기',\n    hello_ebs: '헬로! EBS 소프트웨어',\n    hello_ebs_desc:\n        '<헬로! EBS 소프트웨어> 엔트리 버전의 양방향 서비스를 만나보세요! \\n <헬로! EBS 소프트웨어>의 동영상 강의를 통해 \\n 소프트웨어 코딩의 기본 개념을 배운 후 양방향 코딩 미션에 도전하세요!\\n 방송에서는 볼 수 없었던 <대.소.동> 친구들의 \\n 비하인드 스토리를 볼 수 있습니다!',\n    hello_ebs_sub_1: 'EBS 중학 엔트리 버전의 양방향 서비스를 ',\n    hello_ebs_sub_2: '만나보세요! ',\n    exhibit_4th_title: '엔트리 4주년 기념',\n    exhibit_4th_subtitle: '엔트리 작품 공모전',\n    exhibit_4th_desc1: '엔트리 탄생 4주년을 기념하여 작품 공모전을 개최합니다.',\n    exhibit_4th_desc2: '‘우리 모두를 위한 소프트웨어’를 주제로',\n    exhibit_4th_desc3: '여러분의 멋진 작품을 뽐내보세요!',\n    exhibit_4th_button: '자세히 보기',\n    visang_edu_entry: '비상교육 엔트리 학습하기',\n    cmass_edu_entry: '씨마스 엔트리 학습하기',\n    chunjae_edu_entry: '천재교과서 엔트리 학습하기',\n    kumsungemt_edu_entry: '금성출판사 엔트리 학습하기',\n    kumsungMid_edu_entry: '금성출판사 엔트리 학습하기',\n    gilbutEdu_edu_entry: '길벗출판사 엔트리 학습하기',\n    miraenCoding_edu_entry: '미래엔 엔트리 학습하기',\n    textbook_help_data: '도움자료',\n    textbook_teaching_activity: '수업 교안&활동지',\n    textbook_kyohacksa: '교학사',\n    textbook_kumsung: '금성출판사',\n    textbook_donga: '동아출판',\n    textbook_chunjae: '천재교과서',\n    textbook_miraen: '미래엔',\n    textbook_visang: '비상교육',\n    partner: '파트너',\n    project_term_popup_title: '작품 공개에 따른 엔트리 저작권 정책 동의',\n    project_term_popup_description_1: '작품 공개를 위해',\n    project_term_popup_description_2: '아래 정책을 확인해주세요.',\n    project_term_popup_description_3: '',\n    project_term_popup_description_4: '',\n    project_term_agree_1_1: '내가 만든 작품과 그 소스코드의 공개를 동의합니다.',\n    project_term_agree_2_1: '다른 사람이 나의 작품을 이용하는 것을 허락합니다.',\n    project_term_agree_2_2: '( 복제 , 배포 , 공중송신 포함 )',\n    project_term_agree_3_1: '다른 사람이 나의 작품을 수정하는 것을 허락합니다.',\n    project_term_agree_3_2: '( 리믹스, 변형, 2차 제작물 작성 포함)',\n    agree_all: '전체 동의',\n    select_login: '로그인 선택',\n    select: '선택하세요',\n    with_login: '로그인 하고',\n    without_login: '로그인 안하고',\n    start_challenge: '미션 도전하기',\n    start_challenge_2: '미션 도전하기',\n    if_not_save_not_login: '* 로그인을 안하고 미션에 참여하시면 진행 상황이 저장되지 않습니다.',\n    if_not_member_yet: '엔트리 회원이 아니라면?',\n    join_entry: '엔트리 회원 가입하기',\n    learned_computing: '기존에 소프트웨어 교육을 받아보셨나요?',\n    cparty_index_description_1: '두근두근 소프트웨어와 첫 만남.',\n    cparty_index_description_2:\n        '소프트웨어랑 재미있게 놀다 보면 소프트웨어의 원리도 배우고,  생각하는 힘도 쑥쑥!',\n    cparty_index_description_3: '엔트리를 통해 코딩 미션에 도전하고 인증서 받으세요.',\n    cparty_index_description_4: '2015 Online Coding Party는',\n    cparty_index_description_5: 'SW교육 체험 주간',\n    cparty_index_description_6: '의 일환으로써,',\n    cparty_index_description_7: '초등컴퓨팅교사협회',\n    cparty_index_description_8: '과 함께 만들어졌습니다.',\n    cparty_index_description_9: '2016 Online Coding Party는',\n    cparty_index_description_10: '2017 Online Coding Party는',\n    cparty_index_description_11: \"'SW교육을 준비하는 선생님들의 모임'\",\n    congratulation: '축하 드립니다!',\n    warm_up: '체험',\n    beginner: '입문',\n    intermediate: '기본',\n    advanced: '발전',\n    applied: '응용',\n    cert_msg_tail: '과정을 성공적으로 마쳤습니다.',\n    cert_msg_head: '',\n    maze_text_content_1:\n        '안녕? 나는 엔트리봇이야. 지금 나는 공장에서 탈출을 해야 해! 탈출하기 위해서 먼저 몸을 고쳐야 할 것 같아. 앞에 있는 부품을 얻을 수 있게 도와줄래? move()',\n    maze_text_content_2:\n        '좋아 아주 잘했어! 덕분에 몸이 한결 가벼워졌어! 이번에도 부품상자까지 나를 이동시켜줘. 그런데 가는길에 장애물이 있어. 장애물 앞에서는 jump()',\n    maze_text_content_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 오른쪽, 왼쪽으로 회전할 수 있는 right(); left(); 명령어를 쓰면 충분히 갈 수 있을것 같아!',\n    maze_text_content_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 지금까지 배운 명령어를 같이 써서 저 부품상자까지 가보자!',\n    maze_text_content_5:\n        '우와 부품이 두 개나 있잖아! 두 개 다 챙겨서 가자! 그러면 몸을 빨리 고칠 수 있을 것 같아!',\n    maze_text_content_6:\n        '이번이 마지막 부품들이야! 저것들만 있으면 내 몸을 다 고칠 수 있을 거야! 이번에도 도와줄 거지?',\n    maze_text_content_7:\n        '덕분에 몸이 아주 좋아졌어! 이제 똑같은 일을 여러 번 반복해도 무리는 없을 거야. 어? 그런데 앞에 있는 저 로봇은 뭐지? 뭔가 도움이 필요한 것 같아! 도와주자! for 명령어를 사용해서 저 친구한테 나를 데려다줘!',\n    maze_text_content_8:\n        '좋아! 덕분에 친구 로봇을 살릴 수 있었어! 하지만 앞에도 도움이 필요한 친구가 있네, 하지만 이번에는 벌집이 있으니까 조심해서 벌집에 안 닿게 뛰어넘어가자! 할 수 있겠지? 이번에도 for 명령어를 사용해서 친구가 있는곳까지 나를 이동시켜줘!',\n    maze_text_content_9:\n        '이번에는 for 명령어 대신 미션이 끝날때까지 같은 일을 반복하도록 하는 while 명령어를 사용해봐! 나를 친구에게 데려다주면 미션이 끝나!',\n    maze_text_content_10:\n        '이번에는 if 명령어가 나왔어! if와 while 명령어를 사용해서 내가 언제 어느 쪽으로 회전해야 하는지 알려줘!',\n    maze_text_content_11:\n        '좋아 아까 했던 것처럼 해볼까? 언제 왼쪽으로 돌아야 하는지 알려줄 수 있겠어?',\n    maze_text_content_12: '이번에는 중간중간 벌집(bee)이 있네? 언제 뛰어넘어가야 할지 알려줄래?',\n    maze_text_content_13: '여기저기 도움이 필요한 친구들이 많이 있네! 모두 가서 도와주자!',\n    maze_text_content_14:\n        '우와 이번에도 도와줘야 할 친구들이 많네. 먼저 조그마한 사각형을 돌도록 명령어를 만들고 만든 걸 반복해서 모든 친구를 구해보자.',\n    maze_text_content_15:\n        '오래 움직이다 보니 벌써 지쳐버렸어. 자주 쓰는 명령어를 function 명령어를 사용해서 함수로 만들어 놓았어! 함수를 사용하여 나를 배터리 까지 이동시켜줘!',\n    maze_text_content_16:\n        '좋아 멋진걸! 그럼 이번에는 함수에 들어갈 명령어들을 넣어서 나를 배터리까지 이동시켜줘!',\n    maze_text_content_17:\n        '좋아 이번에는 함수를 만들고, 함수를 사용해서 배터리를 얻을 수 있도록 도와줘! 함수를 만들때 jump();를 잘 섞어봐!',\n    maze_text_content_18:\n        '이번에는 길이 좀 복잡한걸? 그래도 언제 left();를 쓰고, 언제 right();를 쓰면 되는지 알려만 주면 배터리 까지 갈 수 있겠어!.',\n    maze_text_content_19:\n        '이번에는 함수가 미리 정해져 있어! 그런데 함수만 써서 배터리까지 가기 힘들것 같아. 함수와 다른 명령어들을 섞어 써서 배터리 까지 이동시켜줘!',\n    maze_text_content_20:\n        '좋아! 지금까지 정말 멋지게 잘 해줬어. 덕분에 이제 마지막 배터리만 채우면 앞으로는 충전이 필요 없을 거야. 함수를 이용해서 저 배터리를 얻고 내가 자유롭게 살 수 있도록 도와줘!',\n    maze_content_1:\n        '안녕 나는 엔트리봇이라고 해. 지금 나는 공장에서 탈출하려는데 먼저 몸을 고쳐야 할 것 같아. 앞에 있는 부품을 얻을 수 있게 도와줄래? 앞으로 가기 블록을 조립하고 시작을 눌러봐.',\n    maze_content_2:\n        '좋아 아주 잘했어! 덕분에 몸이 한결 가벼워졌어! 앞에도 부품이 있는데 이번에는 잘못 가다간 감전되기 쉬울 것 같아. 한 번 장애물 뛰어넘기 블록을 써서 부품까지 가볼까?',\n    maze_content_3:\n        '멋진걸! 저기에도 부품이 있어! 길이 조금 꼬여있지만 회전하기 블록을 쓰면 충분히 갈 수 있을 것 같아! 이번에도 도와줄 거지?',\n    maze_content_4:\n        '좋아 이제 움직이는 건 많이 편해졌어! 이번에는 회전과 뛰어넘기를 같이 써서 저 부품을 얻어보자!',\n    maze_content_5:\n        '우와 부품이 두 개나 있잖아! 두 개 다 챙겨서 가자! 그러면 몸을 빨리 고칠 수 있을 것 같아!',\n    maze_content_6:\n        '이번이 마지막 부품들이야! 저것들만 있으면 내 몸을 다 고칠 수 있을 거야! 이번에도 도와줄 거지?',\n    maze_content_7:\n        '덕분에 몸이 아주 좋아졌어! 이제 똑같은 일을 여러 번 반복해도 무리는 없을 거야. 어? 그런데 앞에 있는 저 로봇은 뭐지? 뭔가 도움이 필요한 것 같아! 도와주자! 얼른 반복하기의 숫자를 바꿔서 저 친구한테 나를 데려다줘!',\n    maze_content_8:\n        '좋아! 덕분에 친구 로봇을 살릴 수 있었어! 하지만 앞에도 도움이 필요한 친구가 있는 것 같아, 하지만 이번에는 벌집이 있으니까 조심해서 벌집에 안 닿게 뛰어넘어가자! 할 수 있겠지? 그럼 아까 했던 것처럼 반복을 써서 친구한테 갈 수 있게 해줄래?',\n    maze_content_9:\n        '이번에는 숫자만큼 반복하는 게 아니라 친구 로봇한테 갈 때까지 똑같은 일을 반복할 수 있어! 이번에도 친구를 구할 수 있도록 도와줘!',\n    maze_content_10:\n        '이번에는 만약 블록이란 게 있어! 만약 블록을 써서 언제 어느 쪽으로 돌아야 하는지 알려줘!',\n    maze_content_11: '좋아 아까 했던 것처럼 해볼까? 언제 왼쪽으로 돌아야 하는지 알려줄 수 있겠어?',\n    maze_content_12: '이번에는 중간중간 벌집이 있네? 언제 뛰어넘어가야 할지 알려줄래?',\n    maze_content_13: '여기저기 도움이 필요한 친구들이 많이 있네! 모두 도와주자!',\n    maze_content_14:\n        '우와 이번에도 도와줘야 할 친구들이 많네. 먼저 조그마한 사각형을 돌도록 블록을 만들고 만든 걸 반복해서 모든 친구를 구해보자.',\n    maze_content_15:\n        '반복을 하도 많이 했더니 자주 쓰는 블록은 외울 수 있을 것 같아! 약속 블록은 지금 내가 외운 블록들이야! 일단은 오래 움직여서 지쳤으니까 배터리를 좀 채울 수 있게 약속 호출 블록을 써서 배터리를 채울 수 있게 해줘!',\n    maze_content_16:\n        '좋아 멋진걸! 그럼 이번에는 네가 자주 쓰일 블록을 나한테 가르쳐줘! 약속 정의 블록 안에 자주 쓰일 블록을 넣어보면 돼!',\n    maze_content_17:\n        '좋아 이번에도 그러면 약속을 이용해서 배터리를 얻을 수 있도록 도와줄 거지? 약속에 뛰어넘기를 잘 섞어봐!',\n    maze_content_18:\n        '이번에는 길이 좀 복잡한걸? 그래도 언제 왼쪽으로 돌고, 언제 오른쪽으로 돌면 되는지 알려만 주면 충전할 수 있을 것 같아.',\n    maze_content_19:\n        '이번에는 약속이 미리 정해져 있어! 그런데 바로 약속을 쓰기에는 안될 것 같아. 내가 갈 길을 보고 약속을 쓰면 배터리를 채울 수 있을 것 같은데 도와줄 거지?',\n    maze_content_20:\n        '좋아! 지금까지 정말 멋지게 잘 해줬어. 덕분에 이제 마지막 배터리만 채우면 앞으로는 충전이 필요 없을 거야. 그러니까 약속을 이용해서 저 배터리를 얻고 내가 자유롭게 살 수 있도록 도와줄래?',\n    maze_content_21:\n        '안녕? 나는 엔트리 봇이야. 지금 많은 친구들이 내 도움을 필요로 하고 있어. 반복하기를 이용해서 친구들을 도울수 있게 데려다 줘!',\n    maze_content_22: '고마워! 이번에는 벌집을 뛰어넘어서 친구를 구하러 갈 수 있게 도와줘!',\n    maze_content_23:\n        '좋아! 이번에는 친구 로봇한테 갈 때까지 반복하기를 이용해서 친구를 도울 수 있게 도와줘!',\n    maze_content_24:\n        '안녕! 나는 엔트리 봇이야. 지금 나는 너무 오래 움직여서 배터리를 채워야 해. 약속 불러오기를 써서 배터리를 채울 수 있도록 도와줘!',\n    maze_content_25: '멋져! 이번에는 여러 약속을 불러와서 배터리가 있는 곳까지 가보자!',\n    maze_content_26:\n        '좋아! 이제 약속할 블록을 나한테 가르쳐줘! 약속하기 블록 안에 자주 쓰일 블록을 넣으면 돼!',\n    maze_content_27:\n        '지금은 미리 약속이 정해져 있어. 그런데, 약속을 쓰기위해서는 내가 갈 방향을 보고 약속을 사용해야해. 도와줄거지?',\n    maze_content_28: '드디어 마지막이야! 약속을 이용하여 마지막 배터리를 얻을 수 있게 도와줘!',\n    ai_content_1:\n        '안녕? 나는 엔트리봇이라고 해. 우주 탐사를 마치고 지구로 돌아가려는데 우주를 떠다니는 돌들 때문에 쉽지 않네. 내가 안전하게 집에 갈 수 있도록 도와줄래? 나의 우주선에는 나의 앞과 위, 아래에 무엇이 어느 정도의 거리에 있는지 알려주는 레이더가 있어 너의 판단을 도와줄 거야!',\n    ai_content_2:\n        '고마워! 덕분에 돌을 쉽게 피할 수 있었어. 그런데 이번엔 더 많은 돌이 있잖아? 블록들을 조립하여 돌들을 이리저리 잘 피해 보자!',\n    ai_content_3:\n        '좋았어! 안전하게 돌을 피했어. 그런데 앞을 봐! 아까보다 더 많은 돌이 있어. 하지만 걱정하지 마. 나에게 반복하기 블록이 있거든. 반복하기 블록 안에 움직이는 블록을 넣으면 목적지에 도착할 때까지 계속 움직일게!',\n    ai_content_4:\n        '대단해! 반복하기 블록을 쓰니 많은 돌을 피하기가 훨씬 수월한걸! 하지만 이렇게 일일이 조종하기는 피곤하다. 나에겐 레이더가 있으니 앞으로 무엇이 나올지 알 수 있어. 앞으로 계속 가다가 앞에 돌이 있으면 피할 수 있도록 해줄래?',\n    ai_content_5:\n        '잘했어! 여기까지 와서 아주 기뻐. 이번에는 레이더가 앞에 있는 물체까지의 거리를 말해줄 거야. 이 기능을 사용하여 돌을 피해 보자! 돌까지의 거리가 멀 때는 앞으로 계속 가다가, 거리가 가까워지면 피할 수 있도록 해줄래?',\n    ai_content_6:\n        '와~ 멋진걸? 레이더를 활용하여 돌을 잘 피해 나가고 있어! 이번에는 여러 개의 레이더를 사용하여 이리저리 돌들을 피해 나갈 수 있게 만들어줄래?',\n    ai_content_7:\n        '휴~ 지구에 점점 가까워지고 있어! 돌을 피할 때 기왕이면 더 안전한 길로 가고 싶어! 아마도 돌이 더 멀리 있는 쪽이 더 안전한 길이겠지? 위쪽 레이더와 아래쪽 레이더를 비교하여 더 안전한 쪽으로 움직이도록 해줄래?',\n    ai_content_8:\n        '좋아! 덕분에 무사히 비행하고 있어. 어? 그런데 저게 뭐지? 저건 내가 아주 위급한 상황에서 사용할 수 있는 특별한 에너지야! 이번에는 저 아이템들을 모두 모으며 움직이자!',\n    ai_content_9:\n        '훌륭해! 이제 지구까지 얼마 안 남았어. 그런데 앞을 보니 돌들로 길이 꽉 막혀서 지나갈 수가 없잖아? 하지만 걱정하지 마. 아이템을 획득해서 사용하면 앞에 있는 꽉 막힌 돌들을 없앨 수 있다고!',\n    ai_content_10:\n        '좋아! 드디어 저기 지구가 보여! 이럴 수가! 이제는 날아오는 돌들을 미리 볼 수가 없잖아? 돌들이 어떻게 날아올지 알지 못해도 지금까지처럼만 움직이면 잘 피할 수 있을 것 같아! 지구까지 가보는 거야!',\n    maze_hints_title_1: '시작 방법',\n    maze_hints_content_1: '엔트리봇은 어떻게 움직이나요?',\n    maze_hints_detail_1:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐<br>2. 다 조립했으면, 시작을 눌러봐<br>3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    maze_hints_title_2: '장애물 뛰어넘기',\n    maze_hints_content_2: '장애물이 있으면 어떻게 해야하나요?',\n    maze_hints_detail_2:\n        '길을 가다보면 장애물을 만날 수 있어.<br>장애물이 앞에 있을 때에는 뛰어넘기 블록을 사용해야 해.',\n    maze_hints_title_3: '반복 블록(1)',\n    maze_hints_content_3: '(3)회 반복하기 블록은 어떻게 사용하나요?',\n    maze_hints_detail_3:\n        '같은 행동을 여러번 반복하려면 ~번 반복하기 블록을 사용해야 해.<br>반복하고 싶은 블록들을 ~번 반복하기 안에 넣고 반복 횟수를 입력하면 돼.',\n    maze_hints_title_4: '반복 블록(2)',\n    maze_hints_content_4: '~를 만날 때 까지 반복하기 블록은 어떻게 사용하나요?',\n    maze_hints_detail_4:\n        \"~까지 반복하기'를 사용하면 같은 행동을 언제까지 반복할지를 정해줄 수 있어.<br>반복하고 싶은 블록들을 ~까지 반복하기안에 넣으면 돼.<br>그러면 {이미지}와 같은 타일 위에 있는 경우 반복이 멈추게 될 거야.\",\n    maze_hints_title_5: '만약 블록',\n    maze_hints_content_5: '만약 ~라면 블록은 어떻게 동작하나요?',\n    maze_hints_detail_5:\n        \"만약 앞에 {이미지}가 있다면' 블록을 사용하면 앞에 {이미지}가 있을 때 어떤 행동을 할 지 정해줄 수 있어.<br>앞에 {이미지}가 있을 때에만 블록 안의 블록들을 실행하고<br> 그렇지 않으면 실행하지 않게 되는 거야.\",\n    maze_hints_title_6: '반복 블록(3)',\n    maze_hints_content_6: '모든 ~를 만날 때 까지 블록은 어떻게 동작하나요?',\n    maze_hints_detail_6:\n        '모든 {타일}에 한 번씩 도착할 때까지 그 안에 있는 블록을 반복해서 실행해.<br>모든 {타일}에 한 번씩 도착하면 반복이 멈추게 될 거야.',\n    maze_hints_title_7: '특별 힌트',\n    maze_hints_content_7: '너무 어려워요. 도와주세요.',\n    maze_hints_detail_7:\n        '내가 가야하는 길을 자세히 봐. 작은 사각형 4개가 보여?<br>작은 사각형을 도는 블록을 만들고, 반복하기를 사용해 보는것은 어때?',\n    maze_hints_title_8: '약속',\n    maze_hints_content_8: '약속하기/약속 불러오기 무엇인가요? 어떻게 사용하나요?',\n    maze_hints_detail_8:\n        \"나를 움직이기 위해 자주 쓰는 블록들의 묶음을 '약속하기' 블록 아래에 조립하여 약속으로 만들 수 있어.<br>한번 만들어 놓은 약속은 '약속 불러오기' 블록을 사용하여 여러 번 꺼내 쓸 수 있다구.\",\n    ai_hints_title_1_1: '게임의 목표',\n    ai_hints_content_1_1: '돌을 피해 오른쪽 행성까지 안전하게 이동할 수 있도록 도와주세요.',\n    ai_hints_detail_1_1: '돌을 피해 오른쪽 행성까지 안전하게 이동할 수 있도록 도와주세요.',\n    ai_hints_title_1_2: '시작 방법',\n    ai_hints_content_1_2: '어떻게 시작할 수 있나요?',\n    ai_hints_detail_1_2:\n        '1. 블록 꾸러미에서 원하는 블록을 꺼내어 “시작하기를 클릭했을 때” 블록과 연결해봐<br>2. 다 조립했으면, 시작을 눌러봐<br>3. 나는 네가 조립한 블록대로 위에서부터 순서대로 움직일게',\n    ai_hints_title_1_3: '움직이게 하기',\n    ai_hints_content_1_3: '엔트리봇은 어떻게 움직이나요?',\n    ai_hints_detail_1_3:\n        '나는 위쪽으로 가거나 앞으로 가거나 아래쪽으로 갈 수 있어.<br>방향을 정할 때에는 돌이 없는 방향으로 안전하게 갈 수 있도록 해줘.<br>나를 화면 밖으로 내보내면 우주미아가 되어버리니 조심해!',\n    ai_hints_title_2_1: '게임의 목표',\n    ai_hints_content_2_1: '반복하기 블록으로 돌들을 피할 수 있도록 도와주세요.',\n    ai_hints_detail_2_1: '반복하기 블록으로 돌들을 피할 수 있도록 도와주세요.',\n    ai_hints_title_2_2: '반복 블록',\n    ai_hints_content_2_2: '반복 블록은 무슨 블록인가요?',\n    ai_hints_detail_2_2:\n        '휴~ 이번에 가야 할 길은 너무 멀어서 하나씩 조립하기는 힘들겠는걸? 반복하기블록을 사용해봐.<br>똑같이 반복되는 블록들을 반복하기 블록으로 묶어주면 아주 긴 블록을 짧게 줄여줄 수 있어!',\n    ai_hints_content_3_1: '만약 블록으로 돌을 피할 수 있도록 도와주세요.',\n    ai_hints_title_3_2: '만약 블록(1)',\n    ai_hints_content_3_2: '만약 ~라면 블록은 어떻게 동작하나요?',\n    ai_hints_detail_3_2:\n        \"만약 앞에 ~가 있다면 / 아니면 블록을 사용하면 내 바로 앞에 돌이 있는지 없는지 확인해서 다르게 움직일 수 있어~<br>만약 내 바로 앞에 돌이 있다면 '만약' 아래에 있는 블록들을 실행하고 돌이 없으면 '아니면' 안에 있는 블록들을 실행할 거야.<br>내 바로 앞에 돌이 있을 때와 없을 때, 어떻게 움직일지 잘 결정해줘~\",\n    ai_hints_content_4_1: '레이더의 사용 방법을 익히고 돌을 피해보세요.',\n    ai_hints_detail_4_1: '레이더의 사용 방법을 익히고 돌을 피해보세요.',\n    ai_hints_title_4_2: '레이더(1)',\n    ai_hints_content_4_2: '레이더란 무엇인가요? 어떻게 활용할 수 있나요?',\n    ai_hints_detail_4_2:\n        \"레이더는 지금 내가 물체와 얼마나 떨어져 있는지 알려주는 기계야.<br>만약 바로 내 앞에 무엇인가 있다면 앞쪽 레이더는 '1'을 보여줘.<br>또, 레이더는 혼자 있을 때 보다 만약 &lt;사실&gt;이라면 / 아니면 블록과<br> 같이 쓰이면 아주 강력하게 쓸 수 있어.<br>예를 들어 내 앞에 물체와의 거리가 1보다 크다면 나는 안전하게 앞으로 갈 수 있겠지만, 아니라면 위나 아래쪽으로 피하도록 할 수 있지.\",\n    ai_hints_title_4_3: '만약 블록(2)',\n    ai_hints_content_4_3: '만약 <사실>이라면 블록은 어떻게 사용하나요?',\n    ai_hints_detail_4_3:\n        \"만약 &lt;사실&gt;이라면 / 아니면 블록은 &lt;사실&gt; 안에 있는 내용이 맞으면 '만약' 아래에 있는 블록을 실행하고, 아니면 '아니면' 아래에 있는 블록을 실행해.<br>어떤 상황에서 다르게 움직이고 싶은 지를 잘 생각해서 &lt;사실&gt; 안에 적절한 판단 조건을 만들어 넣어봐.<br>판단 조건을 만족해서 '만약' 아래에 있는 블록을 실행하고 나면 '아니면' 아래에 있는 블록들은 실행되지 않는다는 걸 기억해!\",\n    ai_hints_content_5_1: '레이더를 활용해 돌을 쉽게 피할 수 있도록 도와주세요.',\n    ai_hints_detail_5_1: '레이더를 활용해 돌을 쉽게 피할 수 있도록 도와주세요.',\n    ai_hints_title_5_2: '만약 블록(3)',\n    ai_hints_content_5_2: '만약 블록이 겹쳐져 있으면 어떻게 동작하나요?',\n    ai_hints_detail_5_2:\n        '만약 ~ / 아니면 블록안에도 만약 ~ / 아니면 블록을 넣을 수 있어! 이렇게 되면 다양한 상황에서 내가 어떻게 행동해야 할지 정할 수 있어.<br>예를 들어 앞에 돌이 길을 막고 있을때와 없을때의 행동을 정한다음, 돌이 있을때의 상황에서도 상황에 따라 위쪽으로 갈지 아래쪽으로 갈지 선택 할 수 있어',\n    ai_hints_title_6_1: '레이더(2)',\n    ai_hints_content_6_1: '위쪽 레이더와 아래쪽 레이더의 값을 비교하고 싶을 땐 어떻게 하나요?',\n    ai_hints_detail_6_1:\n        '([위쪽]레이더) 블록은 위쪽 물체까지의 거리를 뜻하는 블록이야.<br>아래쪽과 위쪽 중에서 어느 쪽에 돌이 더 멀리 있는지 확인하기 위해서 쓸 수 있는 블록이지.<br>돌을 피해가는 길을 선택할 때에는 돌이 멀리 떨어져 있는 쪽으로 피하는게 앞으로 멀리 가는데 유리할거야~',\n    ai_hints_content_7_1: '아이템을 향해 이동하여 돌을 피해보세요.',\n    ai_hints_detail_7_1: '아이템을 향해 이동하여 돌을 피해보세요.',\n    ai_hints_title_7_2: '물체 이름 확인',\n    ai_hints_content_7_2: '앞으로 만날 물체의 이름을 확인해서 무엇을 할 수 있나요?',\n    ai_hints_detail_7_2:\n        '아이템을 얻기위해서는 아이템이 어디에 있는지 확인할 필요가 있어. <br>그럴 때 사용할 수 있는 블록이 [위쪽] 물체는 [아이템]인가? 블록이야.<br>이 블록을 활용하면 아이템이 어느 위치에 있는지 알 수 있고 아이템이 있는 방향으로 움직이도록 블록을 조립할 수 있어.',\n    ai_hints_content_8_1: '아이템을 적절하게 사용해서 돌을 피해보세요.',\n    ai_hints_detail_8_1: '아이템을 적절하게 사용해서 돌을 피해보세요.',\n    ai_hints_title_8_2: '아이템',\n    ai_hints_content_8_2: '아이템은 어떻게 얻고 사용하나요?',\n    ai_hints_detail_8_2:\n        '돌들을 이리저리 잘 피해 나가더라도 앞이 모두 돌들로 꽉 막혀있을 땐 빠져나갈 방법이 없겠지? 그럴 때에는 아이템사용 블럭을 사용해봐. <br>이 블록은 내 앞의 돌들을 모두 없애는 블록이야.<br>단, 아이템이 있어야지만 블록을 사용할 수 있고, 아이템은 이미지를 지나면 얻을 수 있어.',\n    ai_hints_content_9_1: '지금까지 배운 것들을 모두 활용해서 최대한 멀리 가보세요.',\n    ai_hints_detail_9_1: '지금까지 배운 것들을 모두 활용해서 최대한 멀리 가보세요.',\n    ai_hints_title_9_2: '그리고',\n    ai_hints_content_9_2: '그리고 블록은 어떻게 사용하나요?',\n    ai_hints_detail_9_2:\n        '그리고 블록에는 여러개의 조건을 넣을 수 있어, 넣은 모든 조건이 사실일때만 사실이 되어 만약 블록 안에 있는 블록이 실행되고, 하나라도 거짓이 있으면 거짓으로 인식해서 그 안에 있는 블록을 실행하지 않아',\n    maze_text_goal_1: 'move(); 명령어를 사용하여 부품 상자까지 나를 이동시켜줘!',\n    maze_text_goal_2: 'jump(); 명령어로 장애물을 피해 부품 상자까지 나를 이동시켜줘!',\n    maze_text_goal_3: 'left(); right(); 명령어로 부품상자까지 나를 이동시켜줘!',\n    maze_text_goal_4: '여러가지 명령어를 사용하여 부품상자까지 나를 이동시켜줘!',\n    maze_text_goal_5: '두 부품상자에 다 갈 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_6: '두 부품상자에 다 갈 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_7: 'for 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_8: 'for 명령어를 사용하고, 장애물을 피해 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_9: 'while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_10: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_11: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_12: 'if와 while 명령어를 사용하여 친구가 있는 곳 까지 나를 이동시켜줘!',\n    maze_text_goal_13:\n        'while과 for 명령어를 사용하여 모든 친구들을 만날 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_14:\n        'while과 for 명령어를 사용하여 모든 친구들을 만날 수 있도록 나를 이동시켜줘!',\n    maze_text_goal_15: '함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_16: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_17: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_18: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_19: '함수에 명령어를 넣고 함수를 불러와서 배터리까지 나를 이동시켜줘!',\n    maze_text_goal_20: '함수와 다른명령어들을 섞어 사용하여 배터리까지 나를 이동시켜줘!',\n    maze_attack_range: '공격 가능 횟수',\n    maze_attack: '공격',\n    maze_attack_both_sides: '양 옆 공격',\n    above_radar: '위쪽 레이더',\n    above_radar_text_mode: 'radar_up',\n    bottom_radar: '아래쪽 레이더',\n    bottom_radar_text_mode: 'radar_down',\n    front_radar: '앞쪽 레이더',\n    front_radar_text_mode: 'radar_right',\n    above_object: '위쪽 물체',\n    above_object_text_mode: 'object_up',\n    front_object: '앞쪽 물체',\n    front_object_text_mode: 'object_right',\n    below_object: '아래쪽 물체',\n    below_object_text_mode: 'object_down',\n    destination: '목적지',\n    asteroids: '돌',\n    item: '아이템',\n    wall: '벽',\n    destination_text_mode: 'destination',\n    asteroids_text_mode: 'stone',\n    item_text_mode: 'item',\n    wall_text_mode: 'wall',\n    buy_now: '구매바로가기',\n    goals: '목표',\n    instructions: '이용 안내',\n    object_info: '오브젝트 정보',\n    entry_basic_mission: '엔트리 기본 미션',\n    entry_application_mission: '엔트리 응용 미션',\n    maze_move_forward: '앞으로 한 칸 이동',\n    maze_when_run: '시작하기를 클릭했을때',\n    maze_turn_left: '왼쪽으로 회전',\n    maze_turn_right: '오른쪽으로 회전',\n    maze_repeat_times_1: '',\n    maze_repeat_times_2: '번 반복하기',\n    maze_repeat_until_1: '',\n    maze_repeat_until_2: '을 만날때까지 반복',\n    maze_call_function: '약속 불러오기',\n    maze_function: '약속하기',\n    maze_repeat_until_all_1: '모든',\n    maze_repeat_until_all_2: '만날 때 까지 반복',\n    command_guide: '명령어 도움말',\n    ai_success_msg_1: '덕분에 무사히 지구에 도착할 수 있었어! 고마워!',\n    ai_success_msg_2: '다행이야! 덕분에',\n    ai_success_msg_3:\n        '번 만큼 앞쪽으로 갈 수 있어서 지구에 구조 신호를 보냈어! 이제 지구에서 구조대가 올거야! 고마워!',\n    ai_success_msg_4: '좋았어!',\n    ai_cause_msg_1: '이런, 어떻게 움직여야 할 지 더 말해줄래?',\n    ai_cause_msg_2: '아이쿠! 정말로 위험했어! 다시 도전해보자',\n    ai_cause_msg_3: '우와왓! 가야할 길에서 벗어나버리면 우주 미아가 되버릴꺼야. 다시 도전해보자',\n    ai_cause_msg_4: '너무 복잡해, 이 블록을 써서 움직여볼래?',\n    ai_move_forward: '앞으로 가기',\n    ai_move_above: '위쪽으로 가기',\n    ai_move_under: '아래쪽으로 가기',\n    ai_repeat_until_dest: '목적지에 도달 할 때까지 반복하기',\n    ai_if_front_1: '만약 앞에',\n    ai_if_front_2: '가 있다면',\n    ai_else: '아니면',\n    ai_if_1: '만약',\n    ai_if_2: '이라면',\n    ai_use_item: '아이템 사용',\n    ai_radar: '레이더',\n    ai_above: '위쪽',\n    ai_front: '앞쪽',\n    ai_under: '아래쪽',\n    ai_object_is_1: '',\n    ai_object_is_2: '물체는',\n    challengeMission: '다른 미션 도전하기',\n    nextMission: '다음 미션 도전하기',\n    withTeacher: '함께 만든 선생님들',\n    host: '주최',\n    support: '후원',\n    subjectivity: '주관',\n    learnMore: ' 더 배우고 싶어요',\n    ai_object_is_3: '인가?',\n    stage_is_not_available:\n        '아직 진행할 수 없는 스테이지입니다. 순서대로 스테이지를 진행해 주세요.',\n    progress_not_saved: '진행상황이 저장되지 않습니다.',\n    want_refresh: '이 페이지를 새로고침 하시겠습니까?',\n    monthly_entry_grade: '초등학교 3학년 ~ 중학교 3학년',\n    monthly_entry_contents:\n        '매월 발간되는 월간엔트리와 함께 소프트웨어 교육을 시작해 보세요!  차근차근 따라하며 쉽게 익힐 수 있도록 가볍게 구성되어있습니다. 기본, 응용 콘텐츠와 더 나아가기까지! 매월 업데이트되는 8개의 콘텐츠와 교재를 만나보세요~',\n    monthly_entry_etc1:\n        '*메인 페이지의 월간 엔트리 추천코스를 활용하면 더욱 쉽게 수업을 할 수 있습니다.',\n    monthly_entry_etc2: '*월간엔트리는 학기 중에만 발간됩니다.',\n    group_make_lecture_1: '내가 만든 강의가 없습니다.',\n    group_make_lecture_2: \"'만들기>오픈 강의 만들기'에서\",\n    group_make_lecture_3: '우리반 학습내용에 추가하고 싶은 강의를 만들어 주세요.',\n    group_make_lecture_4: '강의 만들기',\n    group_add_lecture_1: '관심 강의가 없습니다.',\n    group_add_lecture_2: \"'학습하기>오픈 강의> 강의'에서 우리반 학습내용에\",\n    group_add_lecture_3: '추가하고 싶은 강의를 관심강의로 등록해 주세요.',\n    group_add_lecture_4: '강의 보기',\n    group_make_course_1: '내가 만든 강의 모음이 없습니다.',\n    group_make_course_2: \"'만들기 > 오픈 강의 만들기> 강의 모음 만들기'에서\",\n    group_make_course_3: '학습내용에 추가하고 싶은 강의 모음을 만들어 주세요.',\n    group_make_course_4: '강의 모음 만들기',\n    group_add_course_1: '관심 강의 모음이 없습니다.',\n    group_add_course_2: \"'학습하기 > 오픈 강의 > 강의 모음'에서 우리반 학습내용에\",\n    group_add_course_3: '추가하고 싶은 강의 모음을 관심 강의 모음으로 등록해 주세요.',\n    group_add_course_4: '강의 모음 보기',\n    hw_main_title: '프로그램 다운로드',\n    ai_banner_title: '인공지능 블록',\n    ai_banner_headline1: '생활 속 인공지능 알아보기',\n    ai_banner_headline2: ' ',\n    ai_banner_text1: '인공지능은 우리와 가까이 있어요.',\n    ai_banner_text2: '인공지능 활용에서 모델 학습까지 직접 만나보세요!',\n    rv_banner_title: '실시간 변수/리스트',\n    rv_banner_headline1: '사라져도 되는 정보,',\n    rv_banner_headline2: '사라지면 안 되는 정보',\n    rv_banner_text1: '변수와 리스트를 서버에 저장해',\n    rv_banner_text2: '실시간으로 정보를 사용해보세요!',\n    banner_default_title: '소프트웨어 교육의 첫걸음',\n    banner_default_title_head1: '엔트리',\n    banner_default_title_body1: '누구나 쉽고 재밌게 소프트웨어를 배울 수 있어요.',\n    banner_default_title_body2: '지금 바로 시작해보세요!',\n    playsw_banner_title: '소프트웨어야 놀자',\n    rsc2020_banner_head1: 'with 엔트리 인공지능',\n    rsc2020_banner_title: '세상을 디자인하는 RSC 2020',\n    rsc2020_banner_body1: '내 아이디어와 인공지능으로',\n    rsc2020_banner_body2: '세상을 행복하게 만들기 프로젝트',\n    playswai_banner_title: '소프트웨어야 놀자 (SECC2020)',\n    playswai_banner_head1: '소프트웨어 교육',\n    playswai_banner_head2: '콘텐츠 콘테스트',\n    playswai_banner_body1: '엔트리의 인공지능과 데이터 분석 기능을',\n    playswai_banner_body2: '활용한 다양한 작품을 기다립니다!',\n    playsw_banner_head1: 'Play with AI, Play with DATA',\n    playsw_banner_body1: '엔트리에서 인공지능 작품을 더 잘 만들고 싶다면?',\n    playsw_banner_body2: '다양한 인공지능 콘텐츠와 함께 작품을 업그레이드 해보세요!',\n    privacy_contest_title: '개인정보 보호',\n    privacy_content_head1: '우리 모두 지켜요',\n    privacy_content_head2: '안전한 엔트리 라이프',\n    privacy_content_body1: '개인정보에는 나의 모든 것이 담겨있어요.',\n    privacy_content_body2: '소중한 개인정보 안전하게 지켜요!',\n    campaign_contest_title: '코로나19 함께 이겨내보아요',\n    campaign_content_head: '',\n    campaign_content_body1: '모두에게 도움이 되는 작품을 만들어 공유해보세요.',\n    campaign_content_body2: '매주 우수작품을 선정하여 많은 사람들에게',\n    campaign_content_body3: '코로나19를 이겨낼 수 있는 힘을 전할 수 있어요!',\n    campaign_content_button: '캠페인 보기',\n    code_management_1: '엔트리 캠페인 #1 코드 잘 관리하기',\n    code_management_2: '나의 보관함과 메모 활용',\n    code_management_3: '새 기능 나의 보관함과 메모로 하는 코드 관리 비법!',\n    code_management_4: '작품을 더 잘 만들고 쉽게 공유하는 방법을 알아보아요.',\n    code_management_5: '캠페인 보기',\n    shcoolbook_study_1: '교과서 내용 그대로 학습하세요.',\n    shcoolbook_study_2: '교과서 학습하기',\n    shcoolbook_study_3: '선생님은 교실에서 수업 진행을',\n    shcoolbook_study_4: '학생은 집에서 복습을 할 수 있습니다!',\n    shcoolbook_study_5: '학습하기',\n    main_learn_1: '엔트리에 처음 오셨다면',\n    main_learn_2: '엔트리 알아보기',\n    main_learn_3: '영상을 통해 엔트리의 다양한 기능을 알아보고,',\n    main_learn_4: '멋진 작품을 만들어 친구들과 공유해보세요!',\n    main_learn_5: '영상보기',\n    hw_desc_wrapper:\n        '엔트리 하드웨어 연결 프로그램과 오프라인 버전이 \\n서비스를 한층 더 강화해 업그레이드 되었습니다.\\n업데이트 된 프로그램을 설치해주세요!',\n    hw_downolad_link: '하드웨어 연결 \\n프로그램 다운로드',\n    save_as_image_all: '모든 코드 이미지로 저장하기',\n    save_as_image: '이미지로 저장하기',\n    maze_perfect_success: '멋져! 완벽하게 성공했어~',\n    maze_success_many_block_1: '좋아',\n    maze_fail_obstacle_remain:\n        \"친구들이 다치지 않도록 모든 <span class='bitmap_obstacle_spider'></span>을 없애줘.\",\n    maze_fail_item_remain: '샐리 공주를 구하기 위해 모든 미네랄을 모아 와줘.',\n    maple_fail_item_remain:\n        '음식을 다 먹지 못해서 힘이 나지 않아. 모든 음식을 다 먹을 수 있도록 도와줘.',\n    maze_fail_not_found_destory_object: '아무것도 없는 곳에 능력을 낭비하면 안 돼!',\n    maze_fail_not_found_destory_monster: '몬스터가 없는 곳에 공격을 하면 안 돼!',\n    maple_fail_not_found_destory_monster: '공격 블록은 몬스터가 있을 때에만 해야 돼!',\n    maze_fail_more_move: '목적지까지는 좀 더 움직여야 해!',\n    maze_fail_wall_crash: '으앗! 거긴 갈 수 없는 곳이야!',\n    maze_fail_contact_brick: '에구구… 부딪혔다!',\n    maze_fail_contact_iron1: '으앗! 장애물에 부딪혀버렸어',\n    maze_fail_contact_iron2: '으앗! 장애물이 떨어져서 다쳐버렸어. 장애물이 내려오기전에 움직여줘..',\n    maze_fail_fall_hole: '앗, 함정에 빠져 버렸어...',\n    maze_fail_hit_unit:\n        '몬스터에게 당해버렸어! 위험한 몬스터를 물리치기 위해 하트 날리기 블록을 사용해줘!',\n    maze_fail_hit_unit2: '윽, 몬스터에게 공격당했다! 두 칸 떨어진 곳에서 공격해줘!',\n    maze_fail_hit_unit_by_mushroom:\n        \"주황버섯에게 당해버렸어!<br /><img src='/img/assets/maze/icon/mushroom.png' /> 공격하기 블록을 사용해서 나쁜 몬스터를 혼내줘!\",\n    maze_fail_hit_unit_by_lupin:\n        \"루팡에게 당해버렸어!<br /><img src='/img/assets/maze/icon/lupin.png' /> 공격하기 블록을 두 칸 떨어진 곳에서 사용해서 나쁜 몬스터를 혼내줘!\",\n    maze_fail_elnath_fail:\n        '으앗! 나쁜 몬스터가 나를 공격했어.<br/>나쁜 몬스터가 나에게 다가오지 못하게 혼내줘!',\n    maze_fail_pepe: '',\n    maze_fail_yeti:\n        \"그 몬스터는 너무 강해서 <img width='24px' src='/img/assets/week/blocks/yeti.png'/> 공격하기 블록으로는 혼내줄 수 없어<br/><img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> 공격하기 블록을 사용해보자.\",\n    maze_fail_peti:\n        \"그 몬스터에게 <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> 공격하기 블록을 사용하면,<br/>강한 몬스터인 <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/>가 나왔을 때 혼내줄 수 없어<br/><img width='24px' src='/img/assets/week/blocks/yeti.png'/> 공격하기 블록을 사용해보자.\",\n    maze_fail_both_side: '양 옆 공격하기는 양쪽에 몬스터가 있을 때에만 사용해야 돼!',\n    maze_wrong_attack_obstacle:\n        \"이 곳에서는 <img src='/img/assets/maze/icon/lupin.png' /> 공격하기 블록을 사용할 수 없어<br/>주황 버섯에게는 <img src='/img/assets/maze/icon/mushroom.png' /> 공격하기 블록을 사용해보자.\",\n    maze_fail_contact_spider: '거미집에 걸려 움직일 수가 없어...',\n    maze_success_perfect: '멋져! 완벽하게 성공했어~',\n    maze_success_block_excess:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br> 하지만, %2개의 블록만으로 성공하는 방법도 있어. 다시 도전해 보는 건 어때?',\n    maze_success_not_essential:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br>하지만 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maze_success_final_perfect_basic:\n        '좋아! 샐리 공주가 어디 있는지 찾았어! 이제 샐리 공주를 구할 수 있을 거야!',\n    maze_success_final_block_excess_basic:\n        '좋아! 샐리 공주가 어디 있는지 찾았어! 이제 샐리 공주를 구할 수 있을 거야!%1개의 블록을 사용했는데, %2개의 블록만으로 성공하는 방법도 있어. 다시 해볼래?',\n    maze_success_final_perfect_advanced:\n        '샐리 공주가 있는 곳까지 도착했어! 이제 악당 메피스토를 물리치고 샐리를 구하면 돼!',\n    maze_success_final_block_excess_advanced:\n        '샐리 공주가 있는 곳까지 도착했어! 이제 악당 메피스토를 물리치고 샐리를 구하면 돼!%1개의 블록을 사용했는데, %2개의 블록만으로 성공하는 방법도 있어. 다시 해볼래?',\n    maze_success_final_distance:\n        '좋아! 드디어 우리가 샐리 공주를 무사히 구해냈어. 구할 수 있도록 도와줘서 정말 고마워!<br>%1칸 움직였는데 다시 한 번 다시해서 60칸까지 가볼래?',\n    maze_success_final_perfect_ai:\n        '좋았어! 드디어 우리가 샐리 공주를 무사히 구해냈어. 구할 수 있도록 도와줘서 정말 고마워!',\n    maple_success_perfect: '좋아! 완벽하게 성공했어!!',\n    maple_success_block_excess:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br> 그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는건 어때?',\n    maple_success_not_essential:\n        '좋아! %1개의 블록을 사용해서 성공했어! <br>그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_perfect_henesys: '멋져! 헤네시스 모험을 훌륭하게 해냈어.',\n    maple_success_final_perfect_excess_henesys:\n        '멋져! 헤네시스 모험을 잘 해냈어.<br />그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_not_essential_henesys:\n        '멋져! 헤네시스 모험을 잘 해냈어.<br />그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_perfect_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br/>다음 모험도 같이 할거지? ',\n    maple_success_final_perfect_excess_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br />그런데 %2개의 블록으로도 성공하는 방법이 있어. 다시 도전해 보는 건 어때?',\n    maple_success_final_not_essential_ellinia:\n        '우와! 이 곳에서 정말 재밌는 모험을 했어!<br />그런데 이 블록을 사용하면 더 쉽게 해결할 수 있어. 다시 도전해 보는 건 어때?',\n    maple_fail_fall_hole: '으앗! 빠져버렸어!<br />뛰어넘기 블록을 사용해서 건너가보자.',\n    maple_fail_ladder_fall_hole:\n        '으앗! 빠져버렸어!<br />사다리 타기 블록을 사용해서 다른 길로 가보자.',\n    maple_fail_more_move: '성공하려면 목적지까지 조금 더 움직여야 해!',\n    maple_fail_not_found_ladder:\n        '이런, 여기엔 탈 수 있는 사다리가 없어.<br />사다리 타기 블록은 사다리가 있는 곳에서만 사용 해야해.',\n    maple_fail_not_found_meat:\n        '이런, 여기엔 먹을 수 있는 음식이 없어!<br />음식 먹기 블록은 음식이 있는 곳에서만 사용 해야해.',\n    maple_cert_input_title: '내가 받을 인증서에 적힐 이름은?',\n    maze_distance1: '거리 1',\n    maze_distance2: '거리 2',\n    maze_distance3: '거리 3',\n    ev3: 'EV3',\n    roborobo_roduino: '로두이노',\n    roborobo_schoolkit: '스쿨키트',\n    smartboard: '과학상자 코딩보드',\n    smartboardbt: '과학상자 코딩보드(무선)',\n    codestar: '코드스타',\n    cobl: '코블',\n    cobl_bt: '코블 블루투스',\n    block_coding: '블록코딩',\n    python_coding: '엔트리파이선',\n    dadublock: '다두블럭',\n    dadublock_car: '다두블럭 자동차',\n    blacksmith: '대장장이 보드',\n    course_submit_homework: '과제 제출',\n    course_done_study: '학습 완료',\n    course_show_list: '목록',\n    modi: '모디',\n    chocopi: '초코파이보드',\n    coconut: '코코넛',\n    jdkit: '제이디키트',\n    practical_course: '교과용 만들기',\n    entry_user_policy: '엔트리 이용정책',\n    entry_scholarship_title: '엔트리 학술 자료',\n    entry_scholarship_content:\n        '엔트리는 대학/학회 등과 함께 다양한 연구를 진행하여 전문성을 강화해나가고 있습니다. 엔트리에서 제공하는 연구용 자료를 확인해보세요',\n    entry_scholarship_content_sub:\n        '*엔트리에서 제공하는 데이터는 연구 및 분석에 활용될 수 있도록 온라인코딩파티에 참여한 사용자들이 미션을 해결하는 일련의 과정을 로그 형태로 저장한 데이터 입니다.',\n    entry_scholarship_download: '자료 다운로드',\n    codingparty_2016_title: '2016 온라인 코딩파티',\n    codingparty_2016_content:\n        '미션에 참여한 사용자들의 블록 조립 순서, 성공/실패 유무가 학년, 성별 정보와 함께 제공됩니다.',\n    codingparty_2017_title: '2017 온라인 코딩파티',\n    scholarship_go_mission: '미션 확인하기',\n    scholarship_guide: '자료 활용 방법',\n    scholarship_see_guide: '가이드 보기',\n    scholarship_guide_desc: '연구용 자료를 읽고 활용할 수 있는 방법이 담긴 개발 가이드 입니다. ',\n    scholarship_example: '자료 활용 예시',\n    scholarship_example_desc: '연구용 자료를 활용하여 발표된 논문을 확인 할 수 있습니다.',\n    scholarship_see_example: '논문 다운로드',\n    altino: '알티노',\n    private_project: '비공개 작품입니다.',\n    learn_programming_entry_mission: '\"엔트리봇\"과 함께 미션 해결하기',\n    learn_programming_line_mission: '\"라인레인저스\"와 샐리구하기',\n    learn_programming_choseok: '\"마음의 소리\"의 조석과 게임 만들기',\n    learn_programming_maple: '\"핑크빈\"과 함께 신나는 메이플 월드로!',\n    learn_programming_level_novice: '기초',\n    learn_programming_level_inter: '중급',\n    learn_programming_level_advanced: '고급',\n    line_look_for: '샐리를 찾아서',\n    line_rangers_title_string: '학습하기 : 라인 레인저스',\n    online_codingparty_certificate_string: '온라인 코딩파티',\n    online_codingparty_line_title_string: '라인 레인저스',\n    line_look_for_desc_1:\n        '라인 레인저스의 힘을 모아 강력한 악당 메피스토를 물리치고 샐리를 구해주세요!',\n    line_save: '샐리 구하기',\n    line_save_desc_1:\n        '메피스토 기지에 갇힌 샐리. 라인 레인저스가 장애물을 피해 샐리를 찾아갈 수 있도록 도와주세요!',\n    line_escape: '샐리와 탈출하기',\n    line_escape_desc_1:\n        '폭파되고 있는 메피스토 기지에서 샐리와 라인 레인저스가 무사히 탈출할 수 있도록 도와주세요!',\n    solve_choseok: '가위바위보 만들기',\n    solve_choseok_desc_1: '만화 속 조석이 가위바위보 게임을 만들 수 있도록 도와주세요!',\n    solve_henesys: '헤네시스',\n    solve_ellinia: '엘리니아',\n    solve_elnath: '엘나스',\n    solve_henesys_desc_1:\n        '마을을 모험하며, 배고픈 핑크빈이 음식을 배불리 먹을 수 있도록 도와주세요!',\n    solve_ellinia_desc_1: '숲 속을 탐험하며, 나쁜 몬스터들을 혼내주고 친구 몬스터들을 구해주세요!',\n    solve_elnath_desc_1:\n        '나쁜 몬스터가 점령한 설산을 지나, 새로운 모험을 시작할 수 있는 또 다른 포털을 찾아 떠나보세요 !',\n    save_modified_shape: '저장하지 않은 변경 사항이 있습니다.\\n변경 사항을 저장할까요?',\n    save_modified_table: '테이블에서 수정한 내용을 저장하시겠습니까?',\n    attach_file: '첨부',\n    enter_discuss_title: '제목을 입력해 주세요(40자 이하)',\n    enter_discuss_title_alert: '제목을 입력해 주세요',\n    discuss_upload_warn: '10MB이하의 파일을 올려주세요.',\n    discuss_list: '목록보기',\n    discuss_write_notice: '우리반 공지사항으로 지정하여 게시판 최상단에 노출합니다.',\n    discuss_write_notice_open: '공지사항으로 지정하여 게시판 최상단에 노출합니다.',\n    search_전체: '전체',\n    search_게임: '게임',\n    search_애니메이션: '애니메이션',\n    search_미디어아트: '미디어 아트',\n    search_피지컬: '피지컬',\n    search_기타: '기타',\n    discuss_write_textarea_placeholer:\n        '엔트리 커뮤니티는 우리가 함께 만들어가는 공간입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_qna:\n        '여기는 묻고답하기 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_tips:\n        '여기는 노하우&팁 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_free:\n        '여기는 엔트리 이야기 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_report:\n        '여기는 제안 및 건의 게시판입니다.\\n서로 배려하는 말로 즐거운 커뮤니티를 만들어요!\\n\\n 욕설이나 음란물과 같은 부적절한 내용의 글을 작성할 경우 이용정지 될 수 있습니다.',\n    discuss_write_textarea_placeholer_contest2019:\n        '※ 아래 양식으로 작성하여 제출해주세요.\\n\\n1. 학년 (예: 초등학교 5학년)\\n\\n2. 작품 URL (‘공유하기 > 작품 공유하기’에 작품을 공유한 다음, 작품 URL을 복사하여 적어주세요.)\\n\\n3. 작품 설명\\n\\n※ 공모전 수상자에게는 이메일이 발송될 예정입니다.\\n엔트리의 ‘내 정보 수정‘에 이메일 정보를 꼭 입력해주세요!',\n    maze_road: '길',\n    account_deletion: '회원탈퇴',\n    bug_report_too_many_request:\n        '신고 내용이 전송 되고 있습니다. 잠시 후에 다시 시도해주시길 바랍니다.',\n    pinkbean_index_title: '핑크빈과 함께 신나는 메이플 월드로!',\n    pinkbean_index_content:\n        '심심함을 참지 못한 핑크빈이 메이플 월드로 모험을 떠났습니다.<br />핑크빈과 함께 신나는 메이플 월드를 탐험하여 모험일지를 채워주세요.<br />각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 마치면 인증서도 얻을 수 있습니다.',\n    rangers_index_title: '라인 레인저스와 함께 샐리를 구하러 출동!',\n    rangers_index_content:\n        '악당 메피스토에게 납치된 샐리를 구하기 위해 라인 레인저스가 뭉쳤습니다.<br />소프트웨어의 원리를 통해 장애물을 극복하고, 샐리를 구출하는 영웅이 되어주세요.<br />각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 마치면 인증서도<br />얻을 수 있습니다.',\n    rangers_replay_button: '영상 다시보기',\n    rangers_start_button: '미션 시작',\n    lms_curriculum_intro: '학습시작',\n    lms_curriculum_goal: '학습목표',\n    lms_curriculum_prepare: '학습준비',\n    lms_curriculum_study: '실습활동',\n    lms_curriculum_summary: '학습정리',\n    lms_curriculum_quiz: '확인문제',\n    lms_curriculum_now_stage: '현재 단계',\n    bug_report_title: '버그 리포트',\n    bug_report_content:\n        '이용 시 발생하는 오류나 버그 신고 및 엔트리를 위한 좋은 제안을 해주세요. 신고나 제안과 무관한 욕설 작성 시 이용이 정지될 수 있습니다.',\n    object_import_syntax_error:\n        '불러오려는 오브젝트에 엔트리파이선 문법과 맞지 않는 블록이 포함되어 있습니다. 블록코딩으로 전환한 뒤 오브젝트를 불러와주세요.',\n    choseok_top_wrapper_panel_title: '조석과 함께 가위바위보 게임을 만들어보세요!',\n    choseok_top_wrapper_panel_des:\n        '마음의 소리 웹툰이 코딩파티 미션으로 탄생했습니다. <br/>만화속 조석이 (가위바위보 게임)을 만들어가는 과정에 참여하여 미션에<br/>도전해 보세요.<br/>각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 모두 마치면</br>인증서와 나만의 게임을 얻을 수 있습니다.<br/>',\n    choseok_mission_statement1: '조석을 움직여보자',\n    choseok_mission_statement2: '가위바위보를 시작해보자',\n    choseok_mission_statement3: '가위바위보 승부를 가려보자',\n    choseok_mission_statement4: '가위바위보 게임을 완성해보자',\n    choseok_mission_statement5: '자유롭게 만들어보자',\n    choseok_mission_statement_top1: '미션 1 : 조석을 움직이기',\n    choseok_mission_statement_top2: '미션 2 : 가위바위보를 시작하기',\n    choseok_mission_statement_top3: '미션 3 : 가위바위보 승패 만들기',\n    choseok_mission_statement_top4: '미션 4 : 가위바위보 결과 보여주기',\n    choseok_mission_statement_top5: '미션 5 : 자유롭게 만들어보기',\n    advisory_title: '엔트리 자문단',\n    advisory_sub_title: '엔트리를 함께 만들어가는 선생님 학생 자문단입니다.',\n    data_table_column: '속성',\n    data_table_row: '행',\n    data_table_provider: '출처',\n    data_table_modifidate: '수정일',\n    draw_new_table_ques_1: '데이터를 직접 입력하여 테이블로 저장할 수 있습니다.',\n    draw_new_table_ques_2: '테이블 화면으로 이동하시겠습니까?',\n    file_upload: '파일 올리기',\n    no_marked_project1: '북마크한 작품이 없습니다.',\n    no_marked_project2: '친구들의 작품을 북마크로 저장해 보세요!',\n    temp_save_project_study: '임시 저장',\n    file_upload_table_title: '테이블 새로 만들기',\n    file_upload_table_sub_title: '데이터를 직접 입력해 나만의 테이블을 만들 수 있어요.',\n    file_upload_warn_desc_table_1:\n        '폭력적이고 잔인한 데이터, 선정적인 내용의 데이터, 불쾌감을 주거나 혐오단어가 포함된 데이터,',\n    file_upload_warn_desc_table_2:\n        '본인 또는 타인의 개인정보를 침해할 수 있는 내용의 데이터, 무단 사용이 금지된 저작권의 데이터 ',\n    table_drag_upload_title: '파일을 끌어다 놓거나 클릭해서 업로드',\n    table_drag_upload_desc: 'CSV, XLS(X) 파일을 여기에 끌어다 놓거나 클릭해서 업로드 할 수 있어요.',\n    upload_select_file: '파일 선택',\n    file_upload_add: '추가',\n    file_upload_max_size_image: '5MB 이하만 업로드가 가능합니다.',\n    lecture_quiz_popup_title: '확인 문제 정답 확인',\n    realtime: '실시간',\n    cloud: '공유',\n};\nLang.Msgs = {\n    video_model_load_success: '로딩 완료',\n    video_model_load_completed: '이제 사람/사물/얼굴 인식을 사용할 수 있습니다.',\n    microbit_led_erase_all: '모두 지우기',\n    loading_plz_wait: '로딩 중입니다. 잠시만 기다려주세요.',\n    ai_utilize_video_loading: '비디오 감지 블록을 로딩 중입니다.<br/> 최대 1분까지 걸릴 수 있어요.',\n    ai_utilize_audio_listening: '듣고 있어요',\n    ai_utilize_audio_progress: '인식하고 있어요',\n    ai_utilize_audio_description: '마이크를 이용하여 음성을 인식하는 블록들의 모음입니다.',\n    upload_error_title: '파일 업로드 안내',\n    upload_error_content: '엔트리 이용정책을 지키지 않는 것으로 의심되는 파일이 제외되었습니다.',\n    monthly_intro_0:\n        '<월간 엔트리>는 소프트웨어 교육에 익숙하지 않은 선생님들도 쉽고 재미있게 소프트웨어 교육을 하실 수 있도록 만들어진 ',\n    monthly_intro_1:\n        'SW교육 잡지입니다. 재미있는 학습만화와 함께 하는 SW 교육 컨텐츠를 만나보세요!',\n    monthly_title_0: '강아지 산책시키기 / 선대칭 도형 그리기',\n    monthly_title_1: '동영상의 원리 / 음악플레이어 만들기',\n    monthly_title_2: '대한민국 지도 퍼즐 / 벚꽃 애니메이션',\n    monthly_title_3: '마우스 졸졸, 물고기 떼 / 태양계 행성',\n    monthly_title_4: '감자 캐기 / 딸기 우유의 진하기',\n    monthly_description_0:\n        '키보드 입력에 따라 움직이는 강아지와 신호와 좌표를 통해 도형을 그리는 작품을 만들어 봅시다.',\n    monthly_description_1: '변수를 활용하여 사진 영상 작품과 음악 플레이어 작품을 만들어 봅시다.',\n    monthly_description_2:\n        '~인 동안 반복하기를 이용한 퍼즐 게임과 복제본, 무작위 수를 이용한 애니메이션 작품을 만들어 봅시다.',\n    monthly_description_3:\n        '계속 반복하기 블록과 수학 연산 블록을 활용하여 물고기 미디어 아트 작품과 태양계를 만들어 봅시다.',\n    monthly_description_4:\n        '신호와 변수, 수학 연산 블록을 활용하여 감자 캐기 작품과 딸기 우유 만들기 작품을 만들어 봅시다.',\n    save_canvas_alert: '저장 중입니다.',\n    feedback_too_many_post: '신고하신 내용이 전송되고 있습니다. 10초 뒤에 다시 시도해주세요.',\n    feedback_duplicated: '이미 신고하였습니다.',\n    usable_object: '사용가능 오브젝트',\n    shared_varaible: '공유 변수',\n    invalid_url: '영상 주소를 다시 확인해 주세요.',\n    auth_only: '인증된 사용자만 이용이 가능합니다.',\n    runtime_error: '실행 오류',\n    to_be_continue: '준비 중입니다.',\n    warn: '경고',\n    error_occured:\n        \"다시 한번 시도해 주세요. 만약 같은 문제가 다시 발생 하면 '제안 및 건의' 게시판에 문의 바랍니다. \",\n    error_forbidden:\n        '로그아웃 상태라 저장을 할 수 없습니다.\\n만약 로그인했다면 다른 창에서 로그아웃 했는지 확인해 주세요.\\n로그인 확인 후 저장이 안 된다면 ‘제안 및 건의’ 게시판에 문의 하세요.',\n    list_can_not_space: '리스트의 이름은 빈 칸이 될 수 없습니다.',\n    sign_can_not_space: '신호의 이름은 빈 칸이 될 수 없습니다.',\n    variable_can_not_space: '변수의 이름은 빈 칸이 될 수 없습니다.',\n    parameter_can_not_space: '값 블록은 빈 칸이 될 수 없습니다.',\n    training_top_title: '연수 프로그램',\n    training_top_desc: '엔트리 연수 지원 프로그램을 안내해 드립니다.',\n    training_main_title01: '선생님을 위한 강사 연결 프로그램',\n    training_target01: '교육 대상 l 선생님',\n    training_sub_title01: '“우리 교실에 SW날개를 달자”',\n    training_desc01:\n        '소프트웨어(SW) 교원 연수가 필요한 학교인가요?\\nSW 교원 연수가 필요한 학교에 SW교육 전문 선생님(고투티처) 또는 전문 강사를 연결해드립니다.',\n    training_etc_ment01: '* 강의비 등 연수 비용은 학교에서 지원해주셔야합니다.',\n    training_main_title02: '소프트웨어(SW) 선도학교로 찾아가는 교원연수',\n    training_target02: '교육 대상 l SW 선도, 연구학교',\n    training_sub_title02: '“찾아가, 나누고, 이어가다”',\n    training_desc02:\n        'SW 교원 연수를 신청한 선도학교를 무작위로 추첨하여 상반기(4,5,6월)와\\n하반기(9,10,11월)에 각 지역의 SW교육 전문 선생님(고투티처)께서 알차고\\n재미있는 SW 기초 연수 진행 및 풍부한 교육사례를 공유하기 위해 찾아갑니다.',\n    training_etc_ment02: '',\n    training_main_title03: '학부모와 학생을 위한 연결 프로그램',\n    training_target03: '교육 대상 l 학부모, 학생',\n    training_sub_title03: '“SW를 더 가까이 만나는 시간”',\n    training_desc03:\n        '학부모와 학생들을 대상으로 소프트웨어(SW) 연수가 필요한 학교에 각 지역의 SW교육 전문 선생님(고투티처) 또는 전문 강사를 연결해드립니다.',\n    training_etc_ment03: '* 강의비 등 연수 비용은 학교에서 지원해주셔야합니다.',\n    training_apply: '신청하기',\n    training_ready: '준비중입니다.',\n    new_version_title: '최신 버전 설치 안내',\n    new_version_text1: '하드웨어 연결 프로그램이',\n    new_version_text2: '<strong>최신 버전</strong>이 아닙니다.',\n    new_version_text3: '서비스를 한층 더 강화해 업데이트 된',\n    new_version_text4: '최신 버전의 연결 프로그램을 설치해 주세요.',\n    new_version_download: \"최신 버전 다운로드<span class='download_icon'></span>\",\n    not_install_title: '미설치 안내',\n    hw_download_text1: '하드웨어 연결을 위해서',\n    hw_download_text2: '<strong>하드웨어 연결 프로그램</strong>을 설치해 주세요.',\n    hw_download_text3: '하드웨어 연결 프로그램이 설치되어 있지 않습니다.',\n    hw_download_text4: '최신 버전의 연결 프로그램을 설치해 주세요.',\n    hw_download_btn: \"연결 프로그램 다운로드<span class='download_icon'></span>\",\n    not_support_browser: '지원하지 않는 브라우저입니다.',\n    quiz_complete1: '퀴즈 풀기 완료!',\n    quiz_complete2: '총 {0}문제 중에 {1}문제를 맞췄습니다.',\n    quiz_incorrect: '이런 다시 한 번 생각해보자',\n    quiz_correct: '정답이야!',\n    hw_connection_success: '하드웨어 연결 성공',\n    hw_connection_success_desc: '하드웨어 아이콘을 더블클릭하면, 센서값만 확인할 수 있습니다.',\n    hw_connection_success_desc2: '작품에서 하드웨어를 사용할 수 있습니다.',\n    hw_connection_termination_title: '하드웨어 연결 해제',\n    hw_connection_termination_desc: '하드웨어와 연결이 해제되었습니다.',\n    hw_connection_failed_title: '하드웨어 연결 실패',\n    hw_connection_failed_desc: '작품에서 사용된 하드웨어가\\n연결되어 있는지 확인해 주세요.',\n    hw_module_load_fail_title: '모듈 로드 실패',\n    hw_module_load_fail_desc: '로드에 실패했습니다. 관리자에게 문의하세요.',\n    ie_page_title: '이 브라우저는<br/>지원하지 않습니다.',\n    ie_page_desc:\n        '엔트리는 인터넷 익스플로러 11 버전 이상 또는 크롬 브라우저에서 이용하실 수 있습니다.<br/>윈도우 업데이트를 진행하시거나, 크롬 브라우저를 설치해주세요.<br/>엔트리 오프라인 버전은 인터넷이 연결되어 있지 않아도 사용할 수 있습니다. 지금 다운받아서 시작해보세요!',\n    ie_page_chrome_download: '크롬 브라우저<br/>다운로드',\n    ie_page_windows_update: '윈도우 최신버전<br>업데이트',\n    ie_page_offline_32bit_download: '엔트리 오프라인 32bit<br>다운로드',\n    ie_page_offline_64bit_download: '엔트리 오프라인 64bit<br>다운로드',\n    ie_page_offline_mac_download: '엔트리 오프라인<br>다운로드',\n    cancel_deletion_your_account: '$1님의<br />회원탈퇴 신청을 취소하시겠습니까?',\n    account_deletion_canceled_complete: '회원탈퇴 신청이 취소되었습니다.',\n    journal_henesys_no1_title: '헤네시스 첫번째 모험일지',\n    journal_henesys_no2_title: '헤네시스 두번째 모험일지',\n    journal_henesys_no1_content:\n        '헤네시스에서 첫 번째 모험 일지야. 오늘 헤네시스 터줏대감이라는 대장장이 집에 가려고 점프를 하다가 떨어질 뻔했어. 그 아저씨는 집 마당 앞에 왜 그렇게 구멍을 크게 만들어 놓는 거지? 나같이 대단한 몬스터가 아니고서야 이런 구멍을 뛰어넘을 수 있는 애들은 없을 거 같은데! 여하튼 정보도 얻었으니 아저씨가 추천한 맛 집으로 가볼까?',\n    journal_henesys_no2_content:\n        '진짜 과식했다. 특히 그 식당의 고기는 정말 맛있었어. 어떻게 그렇게 부드럽게 만들었을까! 그렇지만 그 옆집 빵은 별로였어. 보니까 주방장 아저씨가 요리 수련을 한답시고 맨날 놀러 다니는 거 같더라고. 그럴 시간에 빵 하나라도 더 만들어 보는 게 나을 텐데. 후 이제 배도 채웠으니 본격적인 모험을 시작해볼까!',\n    journal_ellinia_no1_title: '엘리니아 첫번째 모험일지',\n    journal_ellinia_no2_title: '엘리니아 두번째 모험일지',\n    journal_ellinia_no1_content:\n        '휴, 모르고 주황버섯을 깔고 앉아버렸지 뭐야. 걔네가 화날만 하지.. 그래도 그렇게 나에게 다같이 몰려들어 공격할 건 뭐람! 정말 무서운 놈들이야. 슬라임들이 힘들어 할만했어. 하지만 이 핑크빈님께서 다 혼내주었으니깐 걱정 없어. 이제 슬라임들이 친구가 되어주었으니 더욱 신나게 멋진 숲으로 모험을 이어가볼까.',\n    journal_ellinia_no2_content:\n        '모험하면서 만난 친구 로얄패어리가 요즘 엘나스에 흉흉한  소문이 돈다고 했는데, 그게 뭘까? 오늘밤에 친구들이랑 집에서 놀기로 했는데 그때 물어봐야겠어. 완전 궁금한걸!  그런데 뭘 입고 가야하나.. 살이 너무쪄서 입을만 한게 없을거같은데.. 뭐 나는 늘 귀여우니까 어떤걸 입고가도 다들 좋아해줄거라구!',\n    journal_elnath_no1_title: '엘나스 첫번째 모험일지',\n    journal_elnath_no2_title: '엘나스 두번째 모험일지',\n    journal_elnath_no1_content:\n        '세상에! 이게 말로만 듣던 눈인가? 내가 사는 마을은 항상 봄이여서 눈은 처음 봤어. 몬스터들을 혼내주느라 제대로 구경을 못했는데 지금보니 온세상이 이렇게나 하얗고 차갑다니 놀라워! 푹신 푹신하고 반짝거리는게 맛있어 보였는데 맛은 특별히 없네. 그런데 왠지 달콤한 초코 시럽을 뿌려먹으면 맛있을 거 같아. 조금 들고가고 싶은데 방법이 없다니 너무 아쉬운걸.',\n    journal_elnath_no2_content:\n        '에퉤퉤, 실수로 석탄가루를 먹어버렸네. 나쁜 몬스터들! 도망가려면 조용히 도망갈 것이지 석탄을 잔뜩 뿌리면서 도망가버렸어. 덕분에 내 윤기나고 포송포송한 핑크색 피부가 갈수록 더러워지고 있잖아. 어서 여기를 나가서 깨끗하게 목욕부터 해야겠어. 아무리 모험이 좋다지만 이렇게 더럽게 돌아다니는 건 이 핑크빈님 자존심이 허락하지 않지.',\n    bug_report_alert_msg: '소중한 의견 감사합니다.',\n    version_update_msg1: '엔트리 오프라인 새 버전(%1)을\\n사용하실 수 있습니다.',\n    version_update_msg2: '엔트리 하드웨어 새 버전(%1)을\\n사용하실 수 있습니다.',\n    version_update_msg3: '지금 업데이트 하시겠습니까?',\n    select_the_hardware: '수업에 활용할<br />하드웨어를 선택하세요.',\n    select_hardware_button: '하드웨어 선택하기',\n    select_the_expansion_block: '수업에 활용할 확장 블록을 선택하세요.',\n    select_hardware_not_support_info: '오픈강의에는 하드웨어 블록을 사용할 수 없습니다.',\n    select_hardware_not_support_info2: '조금만 기다려주세요.',\n    select_expansion_block_button: '확장 블록 선택하기',\n    expansion_weather_description:\n        '기온, 강수량, 미세먼지 농도 등 한국의 날씨와 관련된 블록 모음입니다. [웨더아이 제공]',\n    expansion_festival_description:\n        '국내 지역별 다양한 행사 및 축제와 관련된 불록 모음 입니다. [한국관광공사 제공]',\n    expansion_translate_description:\n        '파파고를 이용하여 다른 언어로 번역할 수 있는 블록 모음입니다.',\n    expansion_behaviorConductDisaster_description:\n        '자연재난 발생 시 국민이 지켜야하는 기본적인 행동요령에 대한 블록들의 모음입니다. [국민안전처 제공]',\n    expansion_behaviorConductLifeSafety_description:\n        '생활 속 안전을 위해 국민이 지켜야 하는 행동요령에 대한 블록 모음입니다. [국민안전처 제공]',\n    expansion_emergencyActionGuidelines_description:\n        '자연∙사회재난 및 생활안전 사고 발생 시 국민이 지켜야 하는 행동요령에 대한 블록 모음입니다. [행정안전부 제공]',\n    ai_utilize_tts_description:\n        'nVoice 음성합성 기술로 다양한 목소리로 문장을 읽는 블록모음 입니다. (한국어 엔진 지원)',\n    hardware_need_update_title: '업데이트 안내',\n    hardware_need_update_content:\n        '보안 업데이트로 인해 하드웨어 연결 프로그램은\\n1.9.73 버전 이상만 사용할 수 있습니다.\\n더 낮은 버전이라면 최신 버전을 다운로드 받아 주세요.',\n    ai_utilize_video_description:\n        '카메라를 이용하여 사람(신체), 얼굴, 사물 등을 인식하는 블록들의 모음입니다. (IE 및 iOS 미지원)',\n    lecture_header_restart_msg: '처음부터 다시 시작하시겠습니까?',\n    ai_utilize_train_pop_error: '작품에 적용된 모델이 비활성화 또는 삭제되었습니다.',\n    cannot_delete_function:\n        '이미 사용 중인 함수입니다.\\n결과값 설정을 바꾸려면 함수 블록이\\n사용된 오브젝트가 없어야 합니다.',\n    local_variable_deletion_warning:\n        '사용 중인 지역변수가 있다면\\n관련 블록이 삭제될 수 있습니다.\\n정말로 변경할까요?',\n    warning_function_aleady_being_edited:\n        \"새로운 함수를 추가하려면\\n먼저 '저장' 또는 '취소'를 눌러\\n기존의 함수 만들기 화면에서\\n빠져나와야 합니다.\",\n    ai_utilize_pose_landmarker_description:\n        '카메라를 이용하여 사람의 신체를 인식하는 블록들의 모음입니다.',\n    ai_utilize_face_landmarker_description:\n        '카메라를 이용하여 얼굴을 인식하는 블록들의 모음입니다.',\n    ai_utilize_object_detector_description:\n        '카메라를 이용하여 사물을 인식하는 블록들의 모음입니다.',\n    ai_utilize_gesture_recognition_description:\n        '카메라를 이용하여 손을 인식하는 블록들의 모음입니다.',\n    sound_empty1: '[소리 추가하기]를 눌러 소리를 추가해 주세요.',\n    sound_empty2: '소리를 추가하는 방법',\n    sound_empty3: \"'소리 선택' 탭에서 엔트리가 제공하는 기본 소리를 선택합니다.\",\n    sound_empty4: \"'파일 올리기' 탭에서 MP3 파일을 직접 업로드합니다.\",\n    sound_empty5:\n        \"추가한 소리는 '다듬기'에서 필요한 부분만 자르거나, '조정하기'에서 크기와 빠르기 등을 조정할 수 있습니다.\",\n    sound_loading: '소리를 불러오고 있어요',\n};\nLang.Users = {\n    auth_failed: '인증에 실패하였습니다',\n    birth_year: '태어난 해',\n    birth_year_before_1990: '1990년 이전',\n    edit_personal: '회원 정보 수정',\n    email: '이메일',\n    email_desc: '새 소식이나 정보를 받을 수 있 이메일 주소',\n    email_inuse: '이미 등록된 메일주소 입니다',\n    email_match: '이메일 주소를 올바르게 입력해 주세요',\n    forgot_password: '암호를 잊으셨습니까?',\n    job: '직업',\n    language: '언어',\n    name: '이름',\n    name_desc: '사이트내에서 표현될 이름 또는 별명',\n    name_not_empty: '이름을 반드시 입력하세요',\n    password: '암호',\n    password_desc: '최소 4자이상 영문자와 숫자, 특수문자',\n    password_invalid: '암호가 틀렸습니다',\n    password_long: '암호는 4~20자 사이의 영문자와 숫자, 특수문자로 입력해 주세요',\n    password_required: '암호는 필수입력 항목입니다',\n    project_list: '작품 조회',\n    my_page: '마이 페이지',\n    regist: '가입 완료',\n    rememberme: '자동 로그인',\n    repeat_password: '암호 확인',\n    repeat_password_desc: '암호를 한번더 입력해 주세요',\n    repeat_password_not_match: '암호가 일치하지 않습니다',\n    sex: '성별',\n    signup_required_for_save: '저장을 하려면 로그인이 필요합니다.',\n    username: '아이디',\n    username_desc: '로그인시 사용할 아이디',\n    username_inuse: '이미 사용중인 아이디 입니다',\n    username_long: '아이디는 4~20자 사이의 영문자로 입력해 주세요',\n    username_unknown: '존재하지 않는 사용자 입니다',\n    already_verified: '이미 인증된 메일 주소입니다.',\n    email_address_unavailable: '유효하지 않은 인증 메일입니다.',\n    email_address_invalid_for_idpw:\n        '유효하지 않은 인증 메일입니다.\\n [아이디와 비밀번호 찾기] 메일 발송하기를\\n 다시 시도해 주세요.',\n    email_address_invalid_for_certification:\n        '유효하지 않은 인증 메일입니다.\\n [인증 메일 발송하기]를 다시 시도해 주세요.',\n    verification_complete: '이메일 주소가 인증되었습니다.',\n    reset_password_mail_sent: '비밀번호 재설정 메일이 발송되었습니다. 메일을 확인해주세요.',\n    email_not_verified:\n        '인증되지 않은 이메일 주소입니다. 인증 메일을 발송하여, 먼저 이메일 주소를 인증해주세요.',\n    verification_email_send_complete: '인증 메일이 발송되었습니다. 먼저 메일 주소를 인증해주세요.',\n    email_send_failed: '전송에 실패했습니다. 다시 한번 시도해주세요.',\n    email_not_exist: '등록되지 않은 이메일 주소입니다.',\n    not_valid_email: '올바른 형식의 이메일 주소를 입력해주세요.',\n};\nLang.Workspace = {\n    picture_rotation: '회전',\n    picture_size: '크기',\n    thickness: '굵기',\n    follow: '따라해보기',\n    SaveWithPicture: '저장되지 않은 그림이 있습니다. 저장하시겠습니까?',\n    RecursiveCallWarningTitle: '함수 호출 제한',\n    RecursiveCallWarningContent:\n        '함수를 한 번에 너무 많이 호출합니다. 함수의 호출 횟수를 줄여 주세요.',\n    SelectShape: '이동',\n    SelectCut: '자르기',\n    Pencil: '펜',\n    Line: '직선',\n    Rectangle: '사각형',\n    Ellipse: '원',\n    Text: '글상자',\n    Fill: '채우기',\n    Eraser: '지우기',\n    Magnifier: '확대/축소',\n    block_helper: '블록 도움말',\n    new_project: '새 프로젝트',\n    add_object: '오브젝트 추가하기',\n    download_image_name: '엔트리 블록',\n    all: '전체',\n    animal: '동물',\n    arduino_entry: '아두이노 연결 프로그램',\n    arduino_program: '아두이노 프로그램',\n    arduino_sample: '엔트리 연결블록',\n    arduino_driver: '아두이노 드라이버',\n    cannot_add_object: '실행중에는 오브젝트를 추가할 수 없습니다.',\n    cannot_add_picture: '실행중에는 모양을 추가할 수 없습니다.',\n    cannot_add_sound: '실행중에는 소리를 추가할 수 없습니다.',\n    cannot_add_expansion_block: '실행중에는 확장 블럭을 추가할 수 없습니다.',\n    add_object_before_edit: '모양 편집을 위해\\n오브젝트를 추가해주세요.',\n    add_table_before_edit: '테이블을 추가해주세요.',\n    cannot_edit_click_to_stop: '실행 중에는 수정할 수 없습니다.\\n클릭하여 정지하기.',\n    cannot_open_private_project:\n        \"비공개 작품은 코드를 볼 수 없습니다. '확인'을 누르면 이전 화면으로 이동합니다.\",\n    cannot_save_running_project: '실행 중에는 저장할 수 없습니다.',\n    character_gen: '캐릭터 만들기',\n    check_runtime_error: '빨간색으로 표시된 블록을 확인해 주세요.',\n    check_browser_error: '현재 브라우저에서 지원하지 않는 동작입니다.',\n    check_browser_error_video: '현재 브라우저(IE) 또는 운영체제(iOS)에서 지원하지 않는 블록입니다.',\n    check_microphone_error: '마이크가 연결되어 있는지 확인해주세요',\n    check_webcam_error: '컴퓨터에 카메라가 연결되어있지 않습니다',\n    context_download: 'PC에 저장',\n    context_duplicate: '복제하기',\n    context_remove: '삭제하기',\n    context_rename: '이름 수정',\n    coordinate: '좌표',\n    create_function: '함수 만들기',\n    direction: '이동 방향',\n    drawing: '직접 그리기',\n    enter_list_name: '새로운 리스트의 이름을 입력하세요(10글자 이하)',\n    enter_name: '새로운 이름을 입력하세요',\n    enter_new_message: '새로운 신호의 이름을 입력하세요.',\n    enter_variable_name: '새로운 변수의 이름을 입력하세요(10글자 이하)',\n    family: '엔트리봇 가족',\n    fantasy: '판타지/기타',\n    file_new: '새로 만들기',\n    file_open: '온라인 작품 불러오기',\n    file_upload: '오프라인 작품 불러오기',\n    file_upload_login_check_msg: '오프라인 작품을 불러오기 위해서는 로그인을 해야 합니다.',\n    file_save: '저장하기',\n    file_save_as: '복사본으로 저장하기',\n    file_save_download: '내 컴퓨터에 저장하기',\n    func: '함수',\n    function_create: '함수 만들기',\n    function_add: '함수 추가하기',\n    interface: '인터페이스',\n    landscape: '배경',\n    list: '리스트',\n    list_add_calcel: '리스트 추가 취소',\n    list_add_calcel_msg: '리스트 추가를 취소하였습니다.',\n    list_add_fail: '리스트 추가 실패',\n    list_add_fail_msg1: '같은 이름의 리스트가 이미 존재합니다.',\n    list_add_fail_msg2: '리스트의 이름이 적절하지 않습니다.',\n    list_add_ok: '리스트 추가 완료',\n    list_add_ok_msg: '을(를) 추가하였습니다.',\n    list_create: '리스트 추가하기',\n    list_create_placeholder: '리스트의 이름을 입력해주세요.',\n    list_dup: '같은 이름의 리스트가 이미 있어 이름이 자동으로 변경되었습니다.',\n    list_newname: '새로운 이름',\n    list_export: '리스트 내보내기',\n    list_import: '리스트 불러오기',\n    list_remove: '리스트 삭제',\n    list_rename: '리스트 이름 변경 완료',\n    list_rename_failed: '리스트 이름 변경 실패',\n    list_rename_ok: '리스트의 이름이 성공적으로 변경되었습니다.',\n    list_too_long: '리스트의 이름은 10자를 넘을 수 없습니다.',\n    message: '신호',\n    message_add_cancel: '신호 추가 취소',\n    message_add_cancel_msg: '신호 추가를 취소하였습니다.',\n    message_add_fail: '신호 추가 실패',\n    message_add_fail_msg: '같은 이름의 신호가 이미 존재합니다.',\n    message_add_ok: '신호 추가 완료',\n    message_add_ok_msg: '을(를) 추가하였습니다.',\n    message_create: '신호 만들기',\n    message_add: '신호 추가하기',\n    message_create_placeholder: '신호의 이름을 입력해주세요.',\n    message_dup: '같은 이름의 신호가 이미 존재합니다.',\n    message_remove: '신호 삭제',\n    message_remove_canceled: '신호 삭제를 취소하였습니다.',\n    message_rename: '신호 이름을 변경하였습니다.',\n    message_rename_failed: '신호 이름 변경 실패',\n    message_rename_ok: '신호의 이름이 성공적으로 변경 되었습니다.',\n    message_too_long: '신호의 이름을 10자 이내로 작성해 주세요.',\n    message_too_long_to_change: '신호의 이름을 10자 이내로 변경해 주세요.',\n    no_message_to_remove: '삭제할 신호가 없습니다',\n    no_use: '아직 오브젝트에 조립되지 않았어요.',\n    no_variable_to_remove: '삭제할 변수가 없습니다.',\n    no_variable_to_rename: '변경할 변수가 없습니다.',\n    object_not_found: '블록에서 지정한 오브젝트가 존재하지 않습니다.',\n    object_not_found_for_paste: '붙여넣기 할 오브젝트가 없습니다.',\n    people: '일반 사람들',\n    picture_add: '모양 추가하기',\n    table_add: '테이블 추가하기',\n    draw_new_table: '새로 만들기',\n    plant: '식물',\n    project: '작품',\n    project_copied: '의 사본',\n    PROJECTDEFAULTNAME: ['멋진', '재밌는', '착한', '큰', '대단한', '잘생긴', '행운의'],\n    remove_object: '오브젝트 삭제',\n    remove_object_msg: '(이)가 삭제되었습니다.',\n    removed_msg: '(이)가 성공적으로 삭제 되었습니다.',\n    rotate_method: '회전방식',\n    rotation: '방향',\n    run: '시작하기',\n    saved: '저장완료',\n    saved_msg: '(이)가 저장되었습니다.',\n    save_failed: '저장시 문제가 발생하였습니다. 다시 시도해 주세요.',\n    select_library: '오브젝트 선택',\n    select_sprite: '적용할 스프라이트를 하나 이상 선택하세요.',\n    shape_remove_fail: '모양 삭제 실패',\n    shape_remove_fail_msg: '적어도 하나 이상의 모양이 존재하여야 합니다.',\n    shape_remove_ok: '모양이 삭제 되었습니다. ',\n    shape_remove_ok_msg: '이(가) 삭제 되었습니다.',\n    load_expansion_block: '확장 블록 불러오기',\n    load_ai_utilize_block: '인공지능 블록 불러오기',\n    load_hardware_lite_block: '연결할 하드웨어 선택하기',\n    load_ai_utilize_train_block: '인공지능 모델 학습하기',\n    select_expansion_block: '확장블록 선택',\n    deselect_expansion_block_warning:\n        '확장 블록이 작품에 조립되어 있어 불러오기를 해제할 수 없습니다.',\n    deselect_ai_utilize_block_warning:\n        '인공지능 블록이 작품에 조립되어 있어 불러오기를 해제할 수 없습니다.',\n    confirm_firmware_hwlite_block_msg:\n        '%1 을(를)\\n 엔트리에서 사용하려면\\n 먼저 펌웨어를 설치해야 합니다.',\n    confirm_firmware_hwlite_block_title: '펌웨어 설치 필요',\n    confirm_firmware_hwlite_block_download: '펌웨어 다운로드',\n    confirm_firmware_hwlite_block_usb_connect: 'USB 연결',\n    confirm_firmware_hwlite_block_pass: '이미 설치함',\n    progress_firmware_hwlite_title: '펌웨어 설치',\n    progress_firmware_hwlite_step1_title: 'USB 연결 확인',\n    progress_firmware_hwlite_step1_content1: 'USB로 기기와 PC를 연결하고 아래 버튼을 눌러 주세요.',\n    progress_firmware_hwlite_step1_content2:\n        '브라우저에서 연결할 기기를 선택해 주세요.\\nUSB 통신을 기다리고 있어요.',\n    progress_firmware_hwlite_step1_content3: 'USB와 통신을 확인했습니다.',\n    progress_firmware_hwlite_step2_title: '펌웨어 설치',\n    progress_firmware_hwlite_step2_content1: '펌웨어를 설치하고 있습니다.\\n잠시만 기다려 주세요.',\n    progress_firmware_hwlite_step2_content_complete: '펌웨어 설치가 완료되었습니다.',\n    usbconnect_fail_alert:\n        \"기기 연결에 실패했습니다. 연결 상태를 확인하고 '다시 선택'을 눌러 주세요.\",\n    progress_firmware_hwlite_step2_content_fail: '펌웨어 설치에 실패했습니다.',\n    progress_firmware_hwlite_step2_content_select: '설치할 펌웨어 버전을 선택해 주세요',\n    select_hwlite_block_duplicated: '1개의 하드웨어만 선택해 주세요.',\n    select_hwlite_block_none: '연결할 하드웨어를 선택해 주세요.',\n    select_firmware_hwlite_title: '펌웨어 다운로드',\n    select_firmware_hwlite_content: '버전에 맞는 펌웨어를 다운로드 받아\\n하드웨어에 설치해 주세요.',\n    sound_add: '소리 추가하기',\n    sound_remove_fail: '소리 삭제 실패',\n    sound_remove_ok: '소리 삭제 완료',\n    sound_remove_ok_msg: '이(가) 삭제 되었습니다.',\n    stop: '정지하기',\n    pause: '일시정지',\n    restart: '다시시작',\n    speed: '속도 조절',\n    tab_attribute: '속성',\n    tab_table: '테이블',\n    tab_code: '블록',\n    tab_picture: '모양',\n    tab_sound: '소리',\n    tab_text: '글상자',\n    textbox: '글상자',\n    textbox_edit: '글상자 편집',\n    textbox_input: '글상자의 내용을 입력해주세요.',\n    things: '물건',\n    textcoding_tooltip1:\n        '블록코딩과 엔트리파이선을<br/>선택하여 자유롭게<br/>코딩을 해볼 수 있습니다.',\n    textcoding_tooltip2:\n        '실제 개발 환경과 동일하게<br/>엔트리파이선 모드의 실행 결과를<br/>확인할 수 있습니다.',\n    textcoding_tooltip3:\n        '엔트리파이선에 대한<br/>기본사항이 안내되어 있습니다.<br/><엔트리파이선 이용안내>를 확인해 주세요!',\n    upload: '파일 올리기',\n    upload_addfile: '파일 올리기',\n    variable: '변수',\n    variable_add_calcel: '변수 추가 취소',\n    variable_add_calcel_msg: '변수 추가를 취소하였습니다.',\n    variable_add_fail: '변수 추가 실패',\n    variable_add_fail_msg1: '같은 이름의 변수가 이미 존재합니다.',\n    variable_add_fail_msg2: '변수의 이름이 적절하지 않습니다.',\n    variable_add_ok: '변수 추가 완료',\n    variable_add_ok_msg: '을(를) 추가하였습니다.',\n    variable_create: '변수 만들기',\n    variable_add: '변수 추가하기',\n    variable_dup: '같은 이름의 변수가 이미 있어 이름이 자동으로 변경되었습니다.',\n    variable_newname: '새로운 이름',\n    variable_remove: '변수 삭제',\n    variable_remove_canceled: '변수 삭제를 취소하였습니다.',\n    variable_rename: '변수 이름 변경 완료',\n    variable_rename_failed: '변수 이름 변경 실패',\n    variable_rename_msg: \"'변수의 이름이 성공적으로 변경 되었습니다.'\",\n    variable_rename_ok: '변수의 이름이 성공적으로 변경되었습니다.',\n    variable_select: '변수를 선택하세요',\n    variable_too_long: '변수의 이름은 10자를 넘을 수 없습니다.',\n    open_analizy_data_import: '테이블 불러오기',\n    vehicle: '탈것',\n    add_object_alert_msg: '오브젝트가 하나도 없습니다. 오브젝트를 추가하고 시도해 주세요.',\n    add_object_alert: '경고',\n    create_variable_block: '변수 만들기',\n    create_list_block: '리스트 만들기',\n    Variable_Timer: '초시계',\n    Variable_placeholder_name: '변수 이름',\n    Message_placeholder_name: '신호 이름',\n    Variable_property: '변수 속성',\n    Variable_placeholder_content: '변수의 이름을 입력해주세요.',\n    Variable_use_all_objects: '모든 오브젝트에서 사용',\n    Variable_use_this_object: '이 오브젝트에서 사용',\n    Variable_used_at_all_objects: '모든 오브젝트에서 사용되는 변수',\n    variable_create_normal: '일반 변수로 사용\\n(작품에 저장)',\n    variable_create_cloud: '공유 변수로 사용\\n(서버에 저장)',\n    variable_create_real_time: '실시간 변수로 사용\\n(서버에 저장)',\n    Variable_used_at_special_object: '특정 오브젝트에서만 사용되는 변수',\n    Variable_used_objects: '사용된 오브젝트',\n    draw_new: '새로 그리기',\n    draw_new_ebs: '직접 그리기',\n    painter_file: '파일 ▼',\n    painter_file_save: '저장하기',\n    painter_file_saveas: '새 모양으로 저장하기',\n    new_picture: '새그림',\n    painter_edit: '편집 ▼',\n    get_file: '가져오기',\n    copy_file: '복사하기',\n    cut_picture: '자르기',\n    paste_picture: '붙이기',\n    remove_all: '모두 지우기',\n    flip_horizontal: '좌우뒤집기',\n    flip_vertical: '상하뒤집기',\n    regular: '보통',\n    bold: '굵게',\n    font_underline: '밑줄',\n    font_textblock_strikethrough: '가로줄',\n    font_textblock_underline: '밑줄',\n    font_textblock_italic: '이탤릭',\n    font_textblock_bold: '볼드',\n    font_tilt: '기울임',\n    font_cancel: '취소선',\n    font_color: '글꼴 색상',\n    font_fill: '채우기 색상',\n    font_family: '글꼴',\n    align_left: '왼쪽 정렬',\n    align_center: '가운데 정렬',\n    align_right: '오른쪽 정렬',\n    italic: '기울임',\n    textStyle: '글자',\n    add_picture: '모양 추가',\n    select_picture: '모양 선택',\n    select_table: '테이블 선택',\n    load_web: '웹에서 가져오기',\n    select_sound: '소리 선택',\n    Size: '크기',\n    show_variable: '변수 노출',\n    default_value: '기본값 ',\n    slide: '슬라이드',\n    min_value: '최솟값',\n    max_value: '최댓값',\n    number_of_list: '리스트 항목 수',\n    empty_of_list: '추가된 항목이 없습니다',\n    use_all_objects: '모든 오브젝트에 사용',\n    list_name: '리스트 이름',\n    list_property: '리스트 속성',\n    list_used_specific_objects: '특정 오브젝트에서만 사용되는 리스트',\n    List_used_all_objects: '모든 오브젝트에서 사용되는 리스트',\n    List_used_objects: '사용된 오브젝트',\n    Scene_delete_error: '장면은 최소 하나 이상 존재해야 합니다.',\n    Scene_add_error: '장면은 최대 20개까지 추가 가능합니다.',\n    replica_of_object: '의 복제본',\n    will_you_delete_scene: '장면은 한번 삭제하면 취소가 불가능 합니다. \\n정말 삭제 하시겠습니까?',\n    will_you_delete_function: '함수는 한번 삭제하면 취소가 불가능 합니다.\\n정말 삭제 하시겠습니까?',\n    duplicate_scene: '복제하기',\n    block_explain: '블록 설명 ',\n    block_intro: '블록을 클릭하면 블록에 대한 설명이 나타납니다.',\n    blocks_reference: '블록 설명',\n    hardware_guide: '하드웨어 연결 안내',\n    robot_guide: '로봇 연결 안내',\n    python_guide: '엔트리파이선 이용 안내',\n    show_list_workspace: '리스트 노출',\n    list_create_normal: '일반 리스트로 사용\\n(작품에 저장)',\n    list_create_cloud: '공유 리스트로 사용 \\n(서버에 저장)',\n    list_create_real_time: '실시간 리스트로 사용\\n(서버에 저장)',\n    confirm_quit: '바꾼 내용을 저장하지 않았습니다.',\n    confirm_load_temporary:\n        '저장하지 않고 종료한 작품이 있습니다.\\n저장하지 않은 작품을 먼저 열까요?',\n    confirm_lesson_recovery_header: '강의 복구',\n    confirm_lesson_recovery: '저장되지 않은 강의가 있습니다. 여시겠습니까?',\n    login_to_save: '로그인후에 저장 바랍니다.',\n    cannot_save_in_edit_func: '함수 편집중에는 저장할 수 없습니다.',\n    new_object: '새 오브젝트',\n    arduino_connect: '하드웨어 연결',\n    arduino_connect_success: '하드웨어가 연결되었습니다.',\n    confirm_load_header: '작품 복구',\n    uploading_msg: '업로드 중입니다',\n    file_size_exceeded: '<br>변수 또는 리스트의 값이 너무 많아<br>작품을 불러올 수 없어요.',\n    upload_fail_msg: '업로드에 실패하였습니다. \\n 다시 한번 시도해주세요.',\n    upload_not_supported_msg: '지원하지 않는 형식입니다.',\n    upload_not_supported_file_msg: '업로드 할 수 없는 파일 형식입니다.',\n    file_converting_msg: '파일 변환 중입니다.',\n    file_converting_fail_msg: '파일 변환에 실패하였습니다.',\n    fail_contact_msg: '문제가 계속된다면</br>entry@connect.or.kr 로 문의해주세요.',\n    saving_msg: '저장 중입니다',\n    saving_fail_msg: '저장에 실패하였습니다.</br>다시 한번 시도해주세요.',\n    loading_msg: '불러오는 중입니다',\n    loading_fail_msg: '불러오기에 실패하였습니다.</br>다시 한번 시도해주세요.',\n    restore_project_msg: '정상적으로 저장되지 않은 작품이 있습니다. 해당 작품을 복구하시겠습니까?',\n    quit_stop_msg: '저장 중에는 종료하실 수 없습니다.',\n    ent_drag_and_drop: '업로드 하려면 파일을 놓으세요',\n    not_supported_file_msg: '지원하지 않은 형식의 파일입니다.',\n    broken_file_msg: '파일이 깨졌거나 잘못된 파일을 불러왔습니다.',\n    check_audio_msg: 'mp3 외 오디오 파일은 재생할 수 없습니다.',\n    check_entry_file_msg: 'ENT 파일만 불러오기가 가능합니다.',\n    hardware_version_alert_text:\n        '5월 30일 부터 구버전의 연결프로그램의 사용이 중단 됩니다.\\n하드웨어 연결 프로그램을 최신 버전으로 업데이트 해주시기 바랍니다.',\n    variable_name_auto_edited_title: '변수 이름 자동 변경',\n    variable_name_auto_edited_content: '변수의 이름은 10글자를 넘을 수 없습니다.',\n    list_name_auto_edited_title: '리스트 이름 자동 변경',\n    list_name_auto_edited_content: '리스트의 이름은 10글자를 넘을 수 없습니다.',\n    list_cant_add_item: '경고',\n    list_max_length_exceeded: '리스트 항목은 최대 5,000개까지 추가할 수 있어요.',\n    list_truncated_on_load:\n        '이 작품의 리스트 항목 수가 5,000개를 초과하여 일부가 표시되지 않을 수 있습니다.\\n\\n안정적인 이용을 위해\\n리스트를 5,000개 이하로 줄여주세요.',\n    list_truncated_on_load_title: '알림',\n    cloned_scene: '복제본_',\n    default_mode: '기본형',\n    practical_course_mode: '교과형',\n    practical_course: '실과',\n    select_mode: '모드선택',\n    select_mode_popup_title: '엔트리 만들기 환경을 선택해 주세요.',\n    select_mode_popup_lable1: '기본형',\n    select_mode_popup_lable2: '교과형',\n    select_mode_popup_desc1: '엔트리의 모든 기능을 이용하여<br/>자유롭게 작품을 만듭니다.',\n    select_mode_popup_desc2: '실과 교과서에 등장하는 기능만을<br/>이용하여 작품을 만듭니다.',\n    practical_course_notice: '안내',\n    practical_course_desc:\n        \"<span class='practical_cource_title'>교과용 만들기</span>는<br />실과 교과서로 소프트웨어를 배울 때<br />필요한 기능만을 제공합니다.\",\n    practical_course_desc2:\n        '*기본형 작품 만들기를 이용하면 더 많은 기능을<br />이용해 작품을 만들 수 있습니다.',\n    practical_course_tooltip: '모든 기능을 이용하기 위해서는<br/>기본형을 선택해 주세요.',\n    name_already_exists: '이름이 중복 되었습니다.',\n    enter_the_name: '이름을 입력하여 주세요.',\n    object_not_exist_error: '오브젝트가 하나도 없습니다. 오브젝트를 추가하고 시도해 주세요.',\n    project_length_error: '작품/강의명은 띄어쓰기 포함 45자까지 입력할 수 있습니다.',\n    workspace_tutorial_popup_desc:\n        \"<span class='practical_cource_title'>작품 만들기</span>는<br />창의적인 작품을 만들 수 있도록<br /> 다양한 블록과 기능을 제공합니다.\",\n    start_guide_tutorial: '만들기 이용 안내',\n    language: '언어 선택',\n    file: '파일',\n    save: '저장하기',\n    help: '도움말',\n    print: '인쇄',\n    undo: '입력 취소',\n    redo: '다시 실행',\n    workspace_title_tooltip:\n        '기본작품명이 변경되었습니다.\\n작품을 만든 날짜를 통해 어떤 작품인지 쉽게 알 수 있습니다.',\n    workspace_object_tooltip:\n        '오브젝트의 순서는 오브젝트의 대표 이미지를 잡고\\n위아래로 이동하여 변경할 수 있습니다.\\n(모양과 소리탭에서도 동일하게 동작합니다.)',\n    workspace_comment_tooltip: '조립소에 추가한 메모를\\n한꺼번에 숨기거나 보이게 할 수 있습니다.',\n    workspace_zoom_tooltip:\n        '조립소에 추가된 블록의 크기를 바꿀 수 있습니다.\\n가운데 = 아이콘을 누르면 기본 크기로 돌아옵니다.',\n    workspace_image_tooltip: '새로워진\\n작품 만들기를\\n소개합니다.',\n    playground_block_drop: '나의 보관함의 블록을\\n조립소에 추가합니다.',\n    container_object_drop: '나의 보관함의 오브젝트를\\n오브젝트 리스트에 추가합니다.',\n    my_storage_block_drop: '블록을\\n나의 보관함에\\n추가합니다.',\n    my_storage_object_drop: '오브젝트를\\n나의 보관함에\\n추가합니다.',\n    my_storage: '나의 보관함',\n    my_block: '나의 블록',\n    red: '빨강(R)',\n    green: '녹색(G)',\n    blue: '파랑(B)',\n    hue: '색상',\n    saturation: '채도',\n    brightness: '명도',\n    spoid: '스포이드',\n    palette_mode: '팔레트 모드',\n    slider_mode: '슬라이더 모드',\n    toast_error_title_object_center: '주의',\n    toast_error_contents_object_center:\n        '오브젝트 중심점이 오브젝트와 멀리 떨어져 실행화면 밖으로 벗어날 경우, 원위치로 돌아옵니다.',\n    blocks_comming_soon: '열심히 연구 중입니다.\\n조금만 기다려 주세요!',\n    data_table: '테이블',\n    select_all: '모두',\n    now_loading_msg: '로딩 중입니다.\\n잠시만 기다려주세요.',\n    play_my_project: '만든 작품을 실행해봅시다.',\n    goal_project: '목표작품 살펴보기',\n    look_target_project: '작품을 실행하며 무엇을 만들지 살펴봅시다.',\n    ai_learning_login_required: '모델 학습 기능을 사용하시려면 \\n로그인이 필요합니다.',\n    drag_to_remove: '여기로 옮겨 버리기',\n    check_result_value: '결괏값을 가짐',\n    check_local_variable: '지역변수를 사용',\n    local_variable: '지역변수',\n    local_variable_dup: '같은 이름의 지역변수가 이미 있어 이름이 자동으로 변경되었습니다.',\n    local_variable_rename: '지역변수 이름 변경 완료',\n    local_variable_rename_failed: '지역변수 이름 변경 실패',\n    local_variable_rename_ok: '지역변수의 이름이 성공적으로 변경되었습니다.',\n    use_block_objects1: '사용된 오브젝트 (블록 {0}개)',\n    use_block_objects2: '사용된 오브젝트',\n    use_block_function: '함수에 조립되어 있어요.',\n    use_block_project: '블록 {0} 개',\n    use_blocks_project: '블록 {0} 개',\n    pose_landmarker_title_text: '사람 인식',\n    face_landmarker_title_text: '얼굴 인식',\n    object_detector_title_text: '사물 인식',\n    gesture_recognition_title_text: '손 인식',\n    sound_start_point: '시작 지점',\n    sound_end_point: '끝 지점',\n    sound_selection: '남길 영역',\n    sound_volume: '크기',\n    sound_speed: '빠르기',\n    sound_pitch: '음높이',\n    function_attribute: '함수 속성 보기',\n    variable_default_value: '변수 기본값',\n    list_default_value: '리스트 기본값',\n    func_property: '함수 속성',\n    bring_forward: '위로 옮기기',\n    send_backward: '아래로 옮기기',\n    upload_error_msg:\n        \"이용 정책을 위반하는 이미지로 의심되어\\n업로드 할 수 없습니다.\\n문제가 없다고 생각하시는 경우\\n'문의하기'를 통해 이미지를 전달해 주세요.\",\n    upload_error_msg_contain_image:\n        '이용 정책을 위반하는 것으로 의심되는\\n이미지가 포함되어 업로드 할 수 없습니다.',\n    upload_error_msg_exclude_image: '위 이미지를 제외하고 다시 시도해 주세요.',\n    select_flash_firmware_hwlite_title: '설치할 펌웨어 선택',\n    select_flash_firmware_hwlite_content:\n        '연결하려는 마이크로비트의\\n 버전을 선택해 주세요.\\n 펌웨어 설치가 완료되면 메시지가 표시됩니다.',\n    flash_firmware_success: '펌웨어 설치가 완료되었습니다.',\n    flash_firmware_failed: '펌웨어 설치에 실패했습니다. 다시 시도해 주세요.',\n};\nLang.code = '코드보기';\nLang.EntryStatic = {\n    event100: '이벤트',\n    groupProject: '학급 공유하기',\n    usage_parallel: '병렬',\n    usage_expansion: '확장',\n    usage_hw: '하드웨어',\n    usage_sequence: '순차',\n    privateProject: '나만보기',\n    privateCurriculum: '나만보기',\n    publicCurriculum: '강의 모음 공유하기',\n    publicProject: '작품 공유하기',\n    group: '학급 공유하기',\n    groupCurriculum: '학급 공유하기',\n    private: '나만보기',\n    public: '강의 공유하기',\n    lecture_is_open_true: '공개',\n    lecture_is_open_false: '비공개',\n    category_all: '모든 작품',\n    category_game: '게임',\n    category_animation: '애니메이션',\n    category_media_art: '미디어 아트',\n    category_physical: '피지컬',\n    category_etc: '기타',\n    category_category_game: '게임',\n    category_category_animation: '애니메이션',\n    category_category_media_art: '미디어 아트',\n    category_category_physical: '피지컬',\n    category_category_etc: '기타',\n    sort_created: '최신순',\n    sort_updated: '최신순',\n    sort_visit: '조회순',\n    sort_likeCnt: '좋아요순',\n    sort_comment: '댓글순',\n    period_all: '전체기간',\n    period_1: '오늘',\n    period_7: '최근 1주일',\n    period_30: '최근 1개월',\n    period_90: '최근 3개월',\n    lecture_required_time_1: ' ~ 15분',\n    lecture_required_time_2: '15분 ~ 30분',\n    lecture_required_time_3: '30분 ~ 45분',\n    lecture_required_time_4: '45 분 ~ 60분',\n    lecture_required_time_5: '1시간 이상',\n    usage_event: '이벤트',\n    usage_signal: '신호보내기',\n    usage_scene: '장면',\n    usage_repeat: '반복',\n    usage_condition_repeat: '조건반복',\n    usage_condition: '선택',\n    usage_clone: '복제본',\n    usage_rotation: '회전',\n    usage_coordinate: '좌표이동',\n    usage_arrow_move: '화살표이동',\n    usage_shape: '모양',\n    usage_speak: '말하기',\n    usage_picture_effect: '그림효과',\n    usage_textBox: '글상자',\n    usage_draw: '그리기',\n    usage_sound: '소리',\n    usage_confirm: '판단',\n    usage_comp_operation: '비교연산',\n    usage_logical_operation: '논리연산',\n    usage_math_operation: '수리연산',\n    usage_random: '무작위수',\n    usage_timer: '초시계',\n    usage_variable: '변수',\n    usage_list: '리스트',\n    usage_ask_answer: '입출력',\n    usage_function: '함수',\n    usage_arduino: '아두이노',\n    concept_resource_analytics: '자료수집/분석/표현',\n    concept_procedual: '알고리즘과 절차',\n    concept_abstractive: '추상화',\n    concept_individual: '문제분해',\n    concept_automation: '자동화',\n    concept_simulation: '시뮬레이션',\n    concept_parallel: '병렬화',\n    subject_korean: '국어',\n    subject_english: '영어',\n    subject_mathmatics: '수학',\n    subject_social: '사회',\n    subject_science: '과학',\n    subject_music: '음악',\n    subject_paint: '미술',\n    subject_athletic: '체육',\n    subject_courtesy: '도덕',\n    subject_progmatic: '실과',\n    lecture_grade_1: '초1',\n    lecture_grade_2: '초2',\n    lecture_grade_3: '초3',\n    lecture_grade_4: '초4',\n    lecture_grade_5: '초5',\n    lecture_grade_6: '초6',\n    lecture_grade_7: '중1',\n    lecture_grade_8: '중2',\n    lecture_grade_9: '중3',\n    lecture_grade_10: '일반',\n    lecture_level_1: '쉬움',\n    lecture_level_2: '중간',\n    lecture_level_3: '어려움',\n    listEnable: '리스트',\n    functionEnable: '함수',\n    messageEnable: '신호',\n    objectEditable: '오브젝트',\n    pictureeditable: '모양',\n    sceneEditable: '장면',\n    soundeditable: '소리',\n    variableEnable: '변수',\n    e_1: '초등 1학년',\n    e_2: '초등 2학년',\n    e_3: '초등 3학년',\n    e_4: '초등 4학년',\n    e_5: '초등 5학년',\n    e_6: '초등 6학년',\n    m_1: '중등 1학년',\n    m_2: '중등 2학년',\n    m_3: '중등 3학년',\n    general: '일반',\n    curriculum_is_open_true: '공개',\n    curriculum_open_false: '비공개',\n    contest2019: '공모전',\n    exhibit: '공모전',\n    notice: '공지사항',\n    qna: '묻고답하기',\n    tips: '노하우&팁',\n    free: '엔트리 이야기',\n    report: '제안 및 건의',\n    art_category_all: '모든 작품',\n    art_category_game: '게임',\n    art_category_animation: '애니메이션',\n    art_category_physical: '피지컬',\n    art_category_etc: '기타',\n    art_category_media: '미디어 아트',\n    art_sort_updated: '최신순',\n    art_sort_visit: '조회순',\n    art_sort_likeCnt: '좋아요순',\n    art_sort_comment: '댓글순',\n    art_period_all: '전체기간',\n    art_period_day: '오늘',\n    art_period_week: '최근 1주일',\n    art_period_month: '최근 1개월',\n    art_period_three_month: '최근 3개월',\n    level_high: '상',\n    level_mid: '중',\n    level_row: '하',\n    discuss_sort_created: '최신순',\n    discuss_sort_visit: '조회순',\n    discuss_sort_likesLength: '좋아요순',\n    discuss_sort_commentsLength: '댓글순',\n    discuss_period_all: '전체기간',\n    discuss_period_day: '오늘',\n    discuss_period_week: '최근 1주일',\n    discuss_period_month: '최근 1개월',\n    discuss_period_three_month: '최근 3개월',\n    art_category_living: '생활과 도구',\n    art_category_storytelling: '스토리텔링',\n    art_category_arts: '예술',\n    art_category_knowledge: '지식 공유',\n    art_period_today: '오늘',\n    art_period_quarter: '최근 3개월',\n};\nLang.Helper = {\n    when_run_button_click: '시작하기 버튼을 클릭하면 아래에 연결된 블록들을 실행합니다.',\n    when_some_key_pressed: '선택한 키를 누르면 아래에 연결된 블록들을 실행합니다.',\n    mouse_clicked: '마우스를 클릭했을 때 아래에 연결된 블록들을 실행합니다.',\n    mouse_click_cancled: '마우스 클릭을 해제했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_object_click: '오브젝트를 클릭했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_object_click_canceled: '오브젝트 클릭을 해제했을 때 아래에 연결된 블록들을 실행합니다.',\n    when_message_cast: '선택한 신호를 받으면 아래에 연결된 블록들을 실행합니다.',\n    message_cast: '선택한 신호를 보냅니다.',\n    message_cast_wait:\n        '선택한 신호를 보내고, 해당 신호를 받는 블록들의 실행이 끝날 때 까지 기다립니다.',\n    when_scene_start: '장면이 시작되면 아래에 연결된 블록들을 실행합니다. ',\n    start_scene: '선택한 장면을 시작합니다.',\n    start_neighbor_scene: '이전 또는 다음 장면을 시작합니다.',\n    wait_second: '입력한 시간만큼 기다린 후 다음 블록을 실행합니다.',\n    repeat_basic: '입력한 횟수만큼 감싸고 있는 블록들을 반복 실행합니다.',\n    repeat_inf: '감싸고 있는 블록들을 계속해서 반복 실행합니다.',\n    repeat_while_true:\n        '판단값에 따라 블록의 반복여부를 결정합니다.\\n이 될 때까지: 판단이 참이 될 때까지 감싸고 있는 블록들을 반복 실행합니다.\\n인 동안: 판단이 참인 동안 감싸고 있는 블록들을 반복 실행합니다.',\n    stop_repeat:\n        \"이 블록을 감싸는 가장 가까운 블록을 멈춥니다.\\n'반복하기'블록과 같이 ㄷ자 모양으로 다른 블록을 감싼 블록에 조립해 사용할 수 있습니다.\",\n    continue_repeat:\n        '이 블록을 감싸는 가장 가까운 반복 블록의 이번 반복을 건너뛰고 다음 반복의 처음부터 실행합니다.',\n    _if: '만일 판단이 참이라면, 감싸고 있는 블록들을 실행합니다.',\n    if_else:\n        '만일 판단이 참이라면 첫 번째 감싸고 있는 블록들을 실행하고, 거짓이면 두 번째 감싸고 있는 블록들을 실행합니다.',\n    restart_project: '작품을 처음부터 다시 실행합니다.',\n    stop_object:\n        '블록이 실행을 멈춥니다. 현재 실행중인 동작을 멈추는 블록이며, 프로그램을 종료하지 않습니다.\\n모든 : 작품의 모든 블록이 실행을 멈춥니다. \\n자신 : 해당 오브젝트의 모든 블록이 실행을 멈춥니다.\\n이 코드 : 이 블록이 포함된 블록들이 실행을 멈춥니다.\\n자신의 다른 코드 :  해당 오브젝트 중 이 블록이 포함된 블록들을 제외한 모든 블록이 실행을 멈춥니다.\\n다른 오브젝트의 : 다른 오브젝트의 모든 블록이 실행을 멈춥니다.',\n    wait_until_true: '판단이 참이 될 때까지 실행을 멈추고 기다립니다.',\n    when_clone_start:\n        '해당 오브젝트의 복제본이 새로 생성되었을 때 아래에 연결된 블록들을 실행합니다.',\n    create_clone: '선택한 오브젝트의 복제본을 생성합니다.',\n    delete_clone:\n        '‘복제본이 처음 생성되었을 때’ 블록과 함께 사용되며, 연결된 블록들이 실행되고 있는 복제본을 삭제합니다.',\n    remove_all_clones: '해당 오브젝트의 모든 복제본을 삭제합니다.',\n    move_direction: '입력한 값만큼 오브젝트의 이동 방향 화살표가 가리키는 방향으로 움직입니다.',\n    move_x: '오브젝트의 x 좌표를 입력한 값만큼 바꿉니다. ',\n    move_y: '오브젝트의 y 좌표를 입력한 값만큼 바꿉니다.',\n    move_xy_time: '오브젝트가 입력한 시간에 걸쳐 x와 y 좌표를 입력한 값만큼 바꿉니다.',\n    locate_object_time:\n        '오브젝트가 입력한 시간에 걸쳐 선택한 오브젝트 또는 마우스 포인터의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_x: '오브젝트가 입력한 x 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_y: '오브젝트가 입력한 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy: '오브젝트가 입력한 x와 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_time:\n        '오브젝트가 입력한 시간에 걸쳐 입력한 x와 y 좌표로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate: '오브젝트가 선택한 오브젝트 또는 마우스 포인터의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    rotate_absolute: '오브젝트의 방향을 입력한 각도로 정합니다.',\n    rotate_by_time:\n        '오브젝트의 방향이 입력한 시간에 걸쳐 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_relative:\n        '오브젝트의 방향이 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    direction_absolute: '오브젝트의 이동 방향을 입력한 각도로 정합니다.',\n    direction_relative:\n        '오브젝트의 이동 방향이 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    move_to_angle:\n        '오브젝트가 입력한 각도 방향으로 입력한 값만큼 움직입니다. (실행화면 위쪽이 0도를 나타내며, 시계방향으로 갈수록 각도가 증가합니다.)',\n    see_angle_object:\n        '해당 오브젝트가 방향을 회전하여 선택한 오브젝트 또는 마우스 포인터 쪽을 바라봅니다. ',\n    bounce_wall: '오브젝트가 실행화면 끝에 닿으면 튕겨 나옵니다.',\n    show: '오브젝트를 실행화면에 보이게 합니다.',\n    hide: '오브젝트를 실행화면에 보이지 않게 합니다.',\n    dialog_time:\n        '오브젝트가 입력한 내용을 입력한 시간 동안 말풍선으로 말한 후 다음 블록을 실행합니다.',\n    dialog: '오브젝트가 입력한 내용을 말풍선으로 말하는 동시에 다음 블록을 실행합니다.',\n    remove_dialog: '오브젝트가 말하거나 생각하고 있는 말풍선을 지웁니다.',\n    change_to_some_shape:\n        '오브젝트를 선택한 모양으로 바꿉니다.\\n모양 이름 블록이나 모양 번호를 입력한 값 블록을 결합해 사용할 수 있습니다.',\n    change_to_next_shape: '오브젝트의 모양을 이전 또는 다음 모양으로 바꿉니다.',\n    set_effect_volume: '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.',\n    set_effect_amount: '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.',\n    set_effect:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n색깔 : 0~100을 주기로 반복됩니다.\\n밝기 : -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.)\\n투명도 : 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로, 100 이상은 100으로 처리됩니다.)',\n    set_entity_effect:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n색깔 : 0~100을 주기로 반복됩니다.\\n밝기 : -100~100 사이의 범위로 설정할 수 있습니다. (-100 이하는 -100으로 100 이상은 100으로 처리됩니다.)\\n투명도 : 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로, 100 이상은 100으로 처리됩니다.)',\n    add_effect_amount:\n        '오브젝트에 선택한 효과를 입력한 값만큼 줍니다.\\n\\n- 색깔 : 1~100, 입력한 숫자에 해당하는 색깔 효과를 줍니다.\\n- 밝기 : -100~100, 입력한 숫자만큼 밝기 효과를 줍니다.\\n- 투명도 : 0~100, 입력한 숫자만큼 투명도 효과를 줍니다.',\n    change_effect_amount:\n        '오브젝트의 효과를 입력한 값으로 정합니다.\\n\\n- 색깔 : 1~100, 입력한 숫자에 해당하는 색깔 효과를 줍니다.\\n- 밝기 : -100~100, 입력한 숫자만큼 밝기 효과를 줍니다.\\n- 투명도 : 0~100, 입력한 숫자만큼 투명도 효과를 줍니다.',\n    change_scale_percent: '오브젝트의 크기를 입력한 값만큼 바꿉니다.',\n    set_scale_percent: '오브젝트의 크기를 입력한 값으로 정합니다.',\n    change_scale_size: '오브젝트의 크기를 입력한 값만큼 바꿉니다.',\n    set_scale_size: '오브젝트의 크기를 입력한 값으로 정합니다.',\n    stretch_scale_size: '오브젝트의 가로/세로 크기를 입력한 값만큼 늘입니다.',\n    reset_scale_size: '오브젝트를 원래 크기로 되돌립니다.',\n    flip_x: '오브젝트의 상하 모양을 뒤집습니다.',\n    flip_y: '오브젝트의 좌우 모양을 뒤집습니다.',\n    change_object_index:\n        '오브젝트가 실행화면에 보이는 순서를 변경합니다.\\n- 맨 앞으로 : 해당 오브젝트를 실행화면의 가장 앞쪽으로 가져옵니다.\\n- 앞으로 : 해당 오브젝트를 한 층 앞쪽으로 가져옵니다.\\n- 뒤로 : 해당 오브젝트를 한 층 뒤쪽으로 보냅니다.\\n- 맨 뒤로 : 해당 오브젝트를 실행화면의 가장 뒤쪽으로 보냅니다.',\n    set_object_order: '해당 오브젝트가 설정한 순서로 올라옵니다.',\n    brush_stamp: '오브젝트의 모양을 도장처럼 실행화면 위에 찍습니다.',\n    start_drawing:\n        '오브젝트가 이동하는 경로를 따라 선이 그리기 시작합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    stop_drawing: '오브젝트가 선 그리는 것을 멈춥니다.',\n    start_fill:\n        '오브젝트가 이동하는 경로를 따라 선을 그리고 내부를 채우기 시작합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    stop_fill: '오브젝트가 채우는 것을 멈춥니다.',\n    set_color: '오브젝트가 그리는 선의 색을 선택한 색으로 정합니다.',\n    set_random_color: '오브젝트가 그리는 선의 색을 무작위로 정합니다.',\n    set_fill_color: '오브젝트가 채우는 색을 선택한 색으로 정합니다.',\n    change_thickness: '오브젝트가 그리는 선의 굵기를 입력한 값만큼 바꿉니다.',\n    set_thickness:\n        '오브젝트가 그리는 선의 굵기를 입력한 값으로 정합니다. 1~무한의 범위로 설정할 수 있습니다. (1 이하는 1로 처리합니다.)',\n    change_opacity: '해당 오브젝트가 그리는 붓의 투명도를 입력한 값만큼 바꿉니다.',\n    change_brush_transparency: '해당 오브젝트가 그리는 붓의 투명도를 입력한 값만큼 바꿉니다.',\n    set_opacity:\n        '해당 오브젝트가 그리는 붓의 투명도를 입력한 값으로 정합니다. 0~100의 범위로 설정할 수 있습니다. (0 이하는 0, 100 이상은 100으로 처리합니다.)',\n    set_brush_tranparency:\n        '해당 오브젝트가 그리는 붓의 투명도를 입력한 값으로 정합니다. 0~100의 범위로 설정할 수 있습니다. (0 이하는 0, 100 이상은 100으로 처리합니다.)',\n    brush_erase_all: '해당 오브젝트가 그린 선과 도장을 모두 지웁니다.',\n    sound_something_with_block: '오브젝트가 선택한 소리를 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_something_second_with_block:\n        '오브젝트가 선택한 소리를 입력한 시간 만큼 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_something_wait_with_block: '오브젝트가 선택한 소리를 재생한 후 다음 블록을 실행합니다.',\n    sound_something_second_wait_with_block:\n        '오브젝트가 선택한 소리를 입력한 시간만큼 재생한 후 다음 블록을 실행합니다.',\n    sound_volume_change: '작품에서 재생하는 모든 소리의 크기를 입력한 값만큼 바꿉니다.',\n    sound_volume_set: '작품에서 재생하는 모든 소리의 크기를 입력한 값(%)으로 정합니다.',\n    get_sound_speed: '작품에 설정된 소리의 빠르기 값입니다.',\n    sound_speed_change: '작품에서 재생하는 모든 소리의 빠르기를 입력한 값만큼 바꿉니다.',\n    sound_speed_set: '작품에서 재생하는 모든 소리의 빠르기를 입력한 값(배수)으로 정합니다.',\n    sound_silent_all: '재생하는 소리 중 선택한 소리를 멈춥니다.',\n    play_bgm: '선택한 소리를 배경음악으로 재생하는 동시에 다음 블록을 실행합니다.',\n    stop_bgm: '재생하는 배경음악을 멈춥니다.',\n    is_clicked: '마우스를 클릭한 경우 ‘참’으로 판단합니다.',\n    is_object_clicked: '오브젝트를 클릭한 경우 ‘참’으로 판단합니다.',\n    is_press_some_key: '선택한 키가 눌려져 있는 경우 ‘참’으로 판단합니다.',\n    reach_something: '해당 오브젝트가 선택한 항목과 닿은 경우 ‘참’으로 판단합니다.',\n    is_type: '입력한 값이 선택한 문자로 이루어져 있다면 ‘참’으로 판단합니다.',\n    is_included_in_list:\n        \"선택한 리스트가 입력한 값을 가진 항목을 포함하는 경우 '참'으로 판단합니다.\",\n    boolean_basic_operator:\n        \"입력한 두 값을 비교합니다.\\n= : 왼쪽에 위치한 값과 오른쪽에 위치한 값이 같은 경우 '참'으로 판단합니다.\\n!= : 왼쪽에 위치한 값과 오른쪽에 위치한 값이 같지 않은 경우 '참'으로 판단합니다.\\n> : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 큰 경우 '참'으로 판단합니다.\\n< : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 작은 경우 '참'으로 판단합니다.\\n≥ : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 크거나 같은 경우 '참'으로 판단합니다.\\n≤ : 왼쪽에 위치한 값이 오른쪽에 위치한 값보다 작거나 같은 경우 '참'으로 판단합니다.\",\n    function_create:\n        '자주 쓰는 코드를 이 블록 아래에 조립하여 함수로 만듭니다. [함수 정의하기]의 오른쪽 빈칸에 [이름]을 조립하여 함수의 이름을 정할 수 있습니다. 함수를 실행하는 데 입력값이 필요한 경우 빈칸에 [문자/숫자값], [판단값]을 조립하여 매개변수로 사용합니다.',\n    function_field_label: \"함수 정의하기' 블록 안에 조립하며, 함수의 이름을 정합니다. \",\n    function_field_string:\n        \"함수 정의하기' 블록 안에 조립하며, 입력한 문자/숫자값(매개변수)에 따라 함수의 실행 결과가 달라집니다. 이 블록을 분리하여 함수의 코드 중 필요한 부분에 넣어 사용합니다.\",\n    function_field_boolean:\n        \"함수 정의하기' 블록 안에 조립하며, 참 또는 거짓의 판단값에 따라 함수의 실행 결과가 달라집니다. 이 블록을 분리하여 함수의 코드 중 필요한 부분에 넣어 사용합니다.\",\n    function_general: '현재 만들고 있는 함수 블록 또는 지금까지 만들어 둔 함수 블록입니다.',\n    boolean_and: '두 판단이 모두 참인 경우 ‘참’으로 판단합니다.',\n    boolean_or: '두 판단 중 하나라도 참이 있는 경우 ‘참’으로 판단합니다.',\n    boolean_not: \"해당 판단이 참이면 '거짓', 거짓이면 '참'으로 판단합니다.\",\n    is_boost_mode: '부스트모드가 켜져 있으면 ‘참’으로 판단합니다.',\n    is_current_device_type: \"작품을 실행하는 기기가 선택한 기기라면 '참'으로 판단합니다.\",\n    is_touch_supported: \"작품을 실행하는 기기에서 화면을 터치할 수 있다면 '참'으로 판단합니다.\",\n    calc_basic:\n        '입력한 두 수의 사칙연산 값입니다.\\n+ : 입력한 두 수를 더한 값입니다.\\n- : 입력한 두 수를 뺀 값입니다.\\n* : 입력한 두 수를 곱한 값입니다.\\n/ : 입력한 두 수를 나눈 값입니다.',\n    calc_rand:\n        '입력한 두 수 사이에서 선택된 무작위 수 값입니다. (두 수 모두 정수를 입력한 경우 정수가, 두 수 중 하나라도 소수를 입력한 경우 소숫점 둘째 자리의 소수 값이 선택됩니다.)',\n    get_x_coordinate: '해당 오브젝트의 x 좌푯값을 의미합니다.',\n    get_y_coordinate: '해당 오브젝트의 y 좌푯값을 의미합니다.',\n    coordinate_mouse: '마우스 포인터의 x 또는 y 좌푯값입니다.',\n    coordinate_object:\n        '선택한 오브젝트의 각종 정보 값입니다. (x 좌푯값, y 좌푯값, 방향, 이동 방향, 크기, 모양 번호, 모양 이름)',\n    quotient_and_mod:\n        '입력한 두 수를 나눈 결괏값입니다.\\n- 몫 : 앞의 수에서 뒤의 수를 나누어 생긴 몫의 값입니다.\\n- 나머지 : 앞의 수에서 뒤의 수를 나누어 생긴 나머지 값입니다.',\n    get_rotation_direction: '해당 오브젝트의 방향값, 이동 방향값을 의미합니다.',\n    calc_share: '앞 수에서 뒤 수를 나누어 생긴 몫을 의미합니다.',\n    calc_mod: '앞 수에서 뒤 수를 나누어 생긴 나머지를 의미합니다.',\n    calc_operation:\n        '입력한 수에 대한 다양한 수학식의 계산값입니다. (제곱, 루트, 사인, 코사인, 탄젠트, 아크사인, 아크코사인, 아크탄젠트, 로그, 자연로그, 소수점 부분, 소수점 버림값, 소수점 올림값, 소수점 반올림값, 팩토리얼, 절댓값)',\n    get_date:\n        '현재 날짜와 시각에 대한 값입니다.\\n- 연도: 현재 연도를 반환합니다.\\n- 월: 현재 월을 반환합니다.\\n- 일: 현재 일을 반환합니다.\\n- 요일: 현재 요일을 숫자로 반환합니다.\\n일, 월, 화, 수, 목, 금, 토요일을 차례대로 0, 1, 2, 3, 4, 5, 6으로 반환합니다.\\n- 시각: 현재 시각을 각각 시, 분, 초로 반환합니다.',\n    distance_something: '해당 오브젝트와 선택한 오브젝트 또는 마우스 포인터 간의 거릿값입니다.',\n    get_sound_duration: '선택한 소리의 길이(초) 값입니다.',\n    get_user_name:\n        '작품을 실행하고 있는 사용자의 아이디 값입니다.\\n값은 개인정보 보호를 위해 마스킹 처리되어 있습니다.',\n    get_nickname: '작품을 실행하고 있는 사용자의 닉네임 값입니다.',\n    get_project_timer_value: '이 블록이 실행되는 순간 초시계에 저장된 값입니다.',\n    choose_project_timer_action:\n        '초시계의 상태를 정합니다.\\n- 시작하기: 초시계를 시작합니다.\\n- 정지하기: 초시계를 정지합니다.\\n- 초기화하기: 초시계의 값을 0으로 초기화합니다.',\n    reset_project_timer: '실행되고 있던 타이머를 0으로 초기화합니다.',\n    set_visible_project_timer: '초시계 창을 실행화면에서 숨기거나 보이게 합니다.',\n    ask_and_wait:\n        '오브젝트가 입력한 문자를 말풍선으로 묻고, 대답을 입력받습니다. (이 블록이 실행되면 실행화면에 ‘대답 창’이 생성됩니다.)',\n    get_canvas_input_value: \"사용자가 '대답 창'에 입력한 값입니다.\",\n    set_visible_answer: \"대답 창'을 실행화면에서 숨기거나 보이게 합니다.\",\n    combine_something: '입력한 두 값을 결합한 값입니다.',\n    reverse_of_string: '입력한 값을 뒤집은 값입니다.',\n    get_variable: '선택한 변수에 저장된 값입니다.',\n    change_variable: '선택한 변수에 입력한 값을 더합니다.',\n    set_variable: '선택한 변수의 값을 입력한 값으로 정합니다.',\n    robotis_carCont_sensor_value:\n        '왼쪽 접속 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>오른쪽 접촉 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>선택 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.<br/>최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>왼쪽 적외선 센서 : 물체와 가까울 수록 큰 값 입니다.<br/>오른쪽 적외선 센서 : 물체와 가까울 수록 큰 값 값 입니다.<br/>왼쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>오른쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>(*캘리브레이션 값 - 적외선센서 조정 값)',\n    robotis_carCont_cm_led:\n        '4개의 LED 중 1번 또는 4번 LED 를 켜거나 끕니다.<br/>LED 2번과 3번은 동작 지원하지 않습니다.',\n    robotis_carCont_cm_sound_detected_clear: '최종 소리 감지횟 수를 0 으로 초기화 합니다.',\n    robotis_carCont_aux_motor_speed: '감속모터 속도를 0 ~ 1023 의 값(으)로 정합니다.',\n    robotis_carCont_cm_calibration:\n        '적외선센서 조정 값(http://support.robotis.com/ko/: 자동차로봇> 2. B. 적외선 값 조정)을 직접 정합니다.',\n    robotis_openCM70_sensor_value:\n        '최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.',\n    robotis_openCM70_aux_sensor_value:\n        '서보모터 위치 : 0 ~ 1023, 중간 위치의 값은 512 입니다.<br/>적외선센서 :  물체와 가까울 수록 큰 값 입니다.<br/>접촉센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>조도센서(CDS) : 0 ~ 1023, 밝을 수록 큰 값 입니다.<br/>온습도센서(습도) : 0 ~ 100, 습할 수록 큰 값 입니다.<br/>온습도센서(온도) : -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>온도센서 :  -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>초음파센서 : -<br/>자석센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>동작감지센서 : 동작 감지(1), 동작 미감지(0) 값 입니다.<br/>컬러센서 : 알수없음(0), 흰색(1), 검은색(2), 빨간색(3), 녹색(4), 파란색(5), 노란색(6) 값 입니다.<br/>사용자 장치 : 사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_buzzer_index: '음계를 0.1 ~ 5 초 동안 연주 합니다.',\n    robotis_openCM70_cm_buzzer_melody:\n        \"멜로디를 연주 합니다.<br/>멜로디를 연속으로 재생하는 경우, 다음 소리가 재생되지 않으면 '흐름 > X 초 기다리기' 블록을 사용하여 기다린 후 실행합니다.\",\n    robotis_openCM70_cm_sound_detected_clear: '최종 소리 감지횟 수를 0 으로 초기화 합니다.',\n    robotis_openCM70_cm_led: '제어기의 빨간색, 녹색, 파란색 LED 를 켜거나 끕니다.',\n    robotis_openCM70_cm_motion: '제어기에 다운로드 되어있는 모션을 실행합니다.',\n    robotis_openCM70_cm_autodrive_motor: '자율주행 자동차의 모터 포트를 지정합니다.',\n    robotis_openCM70_cm_autodrive_ir: '자율주행 자동차의 적외선 센서 포트를 지정합니다.',\n    robotis_openCM70_cm_autodrive_speed: '지정한 속도로 자율주행을 수행합니다.',\n    robotis_openCM70_aux_car_move: '로봇을 지정한 속도와 방향으로 움직이도록 합니다.',\n    robotis_openCM70_aux_motor_speed: '감속모터 속도를 0 ~ 100% 의 값으로 정합니다.',\n    robotis_openCM70_aux_servo_mode:\n        '서보모터를 회전모드 또는 관절모드로 정합니다.<br/>한번 설정된 모드는 계속 적용됩니다.<br/>회전모드는 서보모터 속도를 지정하여 서보모터를 회전 시킵니다.<br/>관절모드는 지정한 서보모터 속도로 서보모터 위치를 이동 시킵니다.',\n    robotis_openCM70_aux_servo_speed: '서보모터 속도를 0 ~ 100% 의 값으로 정합니다.',\n    robotis_openCM70_aux_servo_position:\n        '서보모터 위치를 -150도 ~ 150도 의 값(으)로 정합니다.<br/>서보모터 속도와 같이 사용해야 합니다.',\n    robotis_openCM70_aux_led_module: 'LED 모듈의 LED 를 켜거나 끕니다.',\n    robotis_openCM70_aux_custom:\n        '사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_poweroff_timer:\n        '제어기의 자동꺼짐 타이머를 설정합니다.<br/>설정된 만큼의 시간동안 통신이 진행되지 않으면 제어기는 자동으로 꺼집니다.',\n    robotis_openCM70_cm_custom_value:\n        '컨트롤 테이블 주소를 직접 입력하여 값을 확인 합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    robotis_openCM70_cm_custom:\n        '컨트롤 테이블 주소를 직접 입력하여 값을 정합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\n    show_variable: \"선택한 변수의 '변수 창'을 실행화면에 보이게 합니다.\",\n    hide_variable: \"선택한 변수의 '변수 창'을 실행화면에서 숨깁니다.\",\n    value_of_index_from_list: '선택한 리스트에서 입력한 순서에 있는 항목 값입니다.',\n    add_value_to_list: '입력한 값을 선택한 리스트의 마지막 항목에 추가합니다.',\n    remove_value_from_list: '선택한 리스트의 입력한 순서에 있는 항목을 삭제합니다.',\n    insert_value_to_list:\n        '입력한 값을 선택한 리스트의 입력한 순서의 항목으로 추가합니다. (입력한 항목 뒤에 있는 항목들은 순서가 하나씩 밀려납니다.)',\n    change_value_list_index:\n        '선택한 리스트에서 입력한 순서에 있는 항목의 값을 입력한 값으로 바꿉니다.',\n    length_of_list: '선택한 리스트가 보유한 항목의 개수입니다.',\n    show_list: \"선택한 리스트의 '리스트 창'을 실행화면에 보이게 합니다.\",\n    hide_list: \"선택한 리스트의 '리스트 창'을 실행화면에서 숨깁니다.\",\n    text: '해당 글상자가 표시하고 있는 문자값을 의미합니다.',\n    text_read:\n        '선택한 글상자에 입력된 텍스트 값입니다. 내용에 줄바꿈이 포함되면 띄어쓰기로 반환합니다.',\n    text_write: '글상자의 내용을 입력한 값으로 고쳐 씁니다.',\n    text_append: '글상자의 내용 뒤에 입력한 값을 추가합니다.',\n    text_prepend: '글상자의 내용 앞에 입력한 값을 추가합니다.',\n    text_change_effect: '글상자에 선택한 텍스트 효과를 켜거나 끕니다.',\n    text_change_font: '글상자를 선택한 글씨체로 변경합니다. ',\n    text_change_font_color: '글상자를 선택한 글씨색으로 변경합니다.',\n    text_change_bg_color: '글상자를 선택한 배경색으로 변경합니다.',\n    text_flush: '글상자의 내용을 모두 지웁니다.',\n    erase_all_effects: '오브젝트에 적용된 효과를 모두 지웁니다.',\n    char_at: '입력한 값에서 입력한 숫자 번째의 글자 값입니다. (공백을 포함합니다.)',\n    length_of_string: '입력한 값의 공백을 포함한 글자 수입니다.',\n    substring: '입력한 값에서 입력한 범위 내의 글자 값입니다. (공백을 포함합니다.)',\n    count_match_string:\n        '입력한 값에서 지정한 값의 글자 수이며, 영문의 경우 대문자와 소문자를 구분하여 수를 셉니다.',\n    replace_string:\n        '입력한 값에서 지정한 값을 찾아 추가로 입력한 값으로 모두 바꾼 값입니다. (영문 입력 시 대소문자를 구분합니다.)',\n    index_of_string:\n        '입력한 값에서 지정한 값이 처음으로 등장하는 위치 값입니다. (공백을 포함합니다.)',\n    change_string_case: '입력한 영문의 모든 알파벳을 대문자 또는 소문자로 바꾼 값입니다.',\n    get_block_count:\n        '선택한 항목에서 사용된 블록의 수입니다.\\n시작 블록에 조립된 블록을 기준으로 수를 셉니다.\\n- 모든: 작품의 모든 블록의 수를 셉니다.\\n- 자신: 이 오브젝트의 블록 수를 셉니다.\\n- (오브젝트 이름): 선택한 오브젝트의 블록 수를 셉니다.\\n- (장면 이름): 선택한 장면의 블록 수를 셉니다.',\n    get_boolean_value:\n        \"결합한 판단 블록의 결괏값입니다. 판단 블록이 '참'이면 'TRUE', '거짓'이면 'FALSE'를 반환합니다.\",\n    direction_relative_duration:\n        '오브젝트의 이동 방향이 입력한 시간에 걸쳐 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    get_sound_volume: '작품에 설정된 소리의 크기 값입니다.',\n    sound_from_to: '오브젝트가 선택한 소리의 입력한 구간을 재생하는 동시에 다음 블록을 실행합니다.',\n    sound_from_to_and_wait:\n        '오브젝트가 선택한 소리의 입력한 구간을 재생한 후 다음 블록을 실행합니다.',\n    Block_info: '블록 설명',\n    Block_click_msg: '블록을 클릭하면\\n블록에 대한 설명이 나타납니다.',\n    hamster_beep: '버저 소리를 짧게 냅니다.',\n    hamster_change_both_wheels_by:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    hamster_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    hamster_change_output_by:\n        '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    hamster_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    hamster_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    hamster_clear_buzzer: '버저 소리를 끕니다.',\n    hamster_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n    hamster_follow_line_until:\n        '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n    hamster_follow_line_using:\n        '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n    hamster_hand_found:\n        \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    hamster_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n    hamster_move_forward_for_secs: '입력한 시간(초) 동안 앞으로 이동합니다.',\n    hamster_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n    hamster_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    hamster_rest_for: '입력한 박자만큼 쉽니다.',\n    hamster_set_both_wheels_to:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    hamster_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n    hamster_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    hamster_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n    hamster_set_output_to:\n        '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    hamster_set_port_to: '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n    hamster_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    hamster_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    hamster_stop: '양쪽 바퀴를 정지합니다.',\n    hamster_turn_for_secs: '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    hamster_turn_once: '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n    hamster_value:\n        '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n    roboid_hamster_beep: '버저 소리를 짧게 냅니다.',\n    roboid_hamster_change_both_wheels_by:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_hamster_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    roboid_hamster_change_output_by:\n        '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    roboid_hamster_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    roboid_hamster_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_hamster_clear_buzzer: '버저 소리를 끕니다.',\n    roboid_hamster_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n    roboid_hamster_follow_line_until:\n        '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n    roboid_hamster_follow_line_using:\n        '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n    roboid_hamster_hand_found:\n        \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_hamster_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n    roboid_hamster_move_forward_for_secs: '입력한 시간(초) 동안 앞으로 이동합니다.',\n    roboid_hamster_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n    roboid_hamster_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    roboid_hamster_rest_for: '입력한 박자만큼 쉽니다.',\n    roboid_hamster_set_both_wheels_to:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_hamster_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n    roboid_hamster_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    roboid_hamster_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n    roboid_hamster_set_output_to:\n        '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n    roboid_hamster_set_port_to: '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n    roboid_hamster_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    roboid_hamster_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_hamster_stop: '양쪽 바퀴를 정지합니다.',\n    roboid_hamster_turn_for_secs:\n        '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    roboid_hamster_turn_once: '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n    roboid_hamster_value:\n        '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n    roboid_turtle_button_state:\n        \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    roboid_turtle_change_head_led_by_rgb: '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n    roboid_turtle_change_tempo_by:\n        '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    roboid_turtle_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_turtle_change_wheels_by_left_right:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    roboid_turtle_clear_head_led: '머리 LED를 끕니다.',\n    roboid_turtle_clear_sound: '소리를 끕니다.',\n    roboid_turtle_cross_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n    roboid_turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n    roboid_turtle_follow_line_until:\n        '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n    roboid_turtle_follow_line_until_black:\n        '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n    roboid_turtle_is_color_pattern:\n        \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n    roboid_turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n    roboid_turtle_pivot_around_wheel_unit_in_direction:\n        '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n    roboid_turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n    roboid_turtle_play_note_for_beats: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    roboid_turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n    roboid_turtle_play_sound_times_until_done:\n        '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n    roboid_turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n    roboid_turtle_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n    roboid_turtle_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    roboid_turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n    roboid_turtle_set_head_led_to_rgb: '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n    roboid_turtle_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    roboid_turtle_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_turtle_set_wheels_to_left_right:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    roboid_turtle_stop: '양쪽 바퀴를 정지합니다.',\n    roboid_turtle_touching_color:\n        \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    roboid_turtle_turn_at_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n    roboid_turtle_turn_unit_in_place:\n        '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    roboid_turtle_turn_unit_with_radius_in_direction:\n        '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n    roboid_turtle_value:\n        '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n    turtle_button_state:\n        \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_change_buzzer_by:\n        '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n    turtle_change_head_led_by_rgb: '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n    turtle_change_tempo_by: '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n    turtle_change_wheel_by:\n        '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    turtle_change_wheels_by_left_right:\n        '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n    turtle_clear_head_led: '머리 LED를 끕니다.',\n    turtle_clear_sound: '소리를 끕니다.',\n    turtle_cross_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n    turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n    turtle_follow_line_until:\n        '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n    turtle_follow_line_until_black:\n        '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n    turtle_is_color_pattern:\n        \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n    turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n    turtle_pivot_around_wheel_unit_in_direction:\n        '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n    turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n    turtle_play_note_for_beats: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n    turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n    turtle_play_sound_times_until_done:\n        '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n    turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n    turtle_set_buzzer_to:\n        '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n    turtle_set_following_speed_to:\n        '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n    turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n    turtle_set_head_led_to_rgb: '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n    turtle_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n    turtle_set_wheel_to:\n        '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    turtle_set_wheels_to_left_right:\n        '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n    turtle_stop: '양쪽 바퀴를 정지합니다.',\n    turtle_touching_color:\n        \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    turtle_turn_at_intersection:\n        '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n    turtle_turn_unit_in_place:\n        '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n    turtle_turn_unit_with_radius_in_direction:\n        '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n    turtle_value:\n        '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n    neobot_sensor_value:\n        'IN1 ~ IN3 포트 및 리모컨에서 입력되는 값 그리고 배터리 정보를 0부터 255의 숫자로 표시합니다.',\n    neobot_sensor_convert_scale:\n        '선택한 포트 입력값의 변화를 특정범위의 값으로 표현범위를 조절할 수 있습니다.',\n    neobot_left_motor: 'L모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.',\n    neobot_stop_left_motor: 'L모터 포트에 연결한 모터를 정지합니다.',\n    neobot_right_motor: 'R모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.',\n    neobot_stop_right_motor: 'R모터 포트에 연결한 모터를 정지합니다.',\n    neobot_all_motor:\n        'L모터 및 R모터 포트에 2개 모터를 연결하여 바퀴로 활용할 때 전, 후, 좌, 우 이동 방향 및 속도, 시간을 설정할 수 있습니다.',\n    neobot_stop_all_motor: 'L모터 및 R모터에 연결한 모터를 모두 정지합니다.',\n    neobot_set_servo:\n        'OUT1 ~ OUT3에 서보모터를 연결했을 때 0도 ~ 180도 범위 내에서 각도를 조절할 수 있습니다.',\n    neobot_set_output:\n        'OUT1 ~ OUT3에 라이팅블록 및 전자회로를 연결했을 때 출력 전압을 설정할 수 있습니다.</br>0은 0V, 1 ~ 255는 2.4 ~ 4.96V의 전압을 나타냅니다.',\n    neobot_set_fnd: 'FND로 0~99 까지의 숫자를 표시할 수 있습니다.',\n    neobot_set_fnd_off: 'FND에 표시한 숫자를 끌 수 있습니다.',\n    neobot_play_note_for:\n        '주파수 발진 방법을 이용해 멜로디에 반음 단위의 멜로디 음을 발생시킬 수 있습니다.',\n    rotate_by_angle_dropdown:\n        '오브젝트의 방향을 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    chocopi_control_button:\n        '버튼이 눌리면 참이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_control_event:\n        '버튼을 누르거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_control_joystick:\n        '조이스틱 좌우, 상하, 볼륨의 값은 0~4095까지 입니다.<br/>따라서 2047 근처가 중간이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_dc_motor:\n        'DC모터 모듈에는 직류전동기 두개를 연결 할 수 있습니다.<br/> 직류 전동기는 최대 5V로 동작하게 됩니다.<br/>값은 100이 최대(100%)이고 음수를 넣으면 반대 방향으로 회전합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_led:\n        'LED번호는 LED블록에 연결된 순서이고 1번부터 시작합니다.<br/>RGB값은 0~255사이의 값입니다.<br/>빨강(Red),녹색(Green), 파랑(Blue)순서로  입력합니다.<br/>밝은 LED를 직접보면 눈이 아프니까 값을 0~5정도로 씁니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_event:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br/>빛센서를 물체로 가리거나 치우면 시작되는 엔트리 블록을 연결합니다<br/>모션 모듈에는 포토게이트 2개를 연결할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_status:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>물체가 빛센서를 가리면 참</b>이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_photogate_time:\n        '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>이 블록은 물체가 빛센서를 가리거나 벗어난 시간을 가집니다.<br/>1/10000초까지 측정할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_motion_value:\n        '모션 모듈에는 3개의 적외선 센서가 있습니다.<br/>0~4095사이의 값을 가질 수 있는데 물체가 빛을 많이 반사할 수록 작은 값을 가집니다. <br/>거리를 대략적으로 측정할 수 있습니다. <br/>가속도와 각가속도 값의 범위는 -32768~32767 까지입니다.<br/>가속도를 이용해서 센서의 기울기를 측정할 수도 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_sensor:\n        '온도 값은 섭씨 온도입니다.<br/>습도 값은 백분율로 나타낸 상대습도 값입니다.<br/>빛은 로그스케일로 0~4095사이입니다.<br/>아날로그 값은 0~4095사이입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_servo_motor:\n        '서보모터 모듈에는 4개의 서보모터를 연결 할 수 있습니다.<br/>서보모터는 5V로 동작하게 됩니다.<br/>각도는 0~200도까지 지정할 수 있습니다.<br/>연속회전식 서보모터를 연결하면 각도에 따라 속도가 변하게됩니다.<br/>90~100 사이가 중간값입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_event:\n        '터치 모듈에는 1~12번의 연결 패드가 있습니다. <br/>만지거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_status:\n        '터치 모듈의 패드를 만지면 참이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    chocopi_touch_value:\n        '터치패드에 연결된 물체의 전기용량이 커지면 값이 작아집니다.<br/>여러 명이 손잡고 만지면 더 작은 값이 됩니다.<br/>전기용량이란 물체에 전기를 띈 입자를 얼마나 가지고 있을 수 있는 지를 말합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n    boolean_and_or:\n        '그리고: 두 판단이 모두 참인 경우 ‘참’으로 판단합니다.\\n또는: 두 판단 중 하나라도 참이 있는 경우 ‘참’으로 판단합니다.',\n    check_weather:\n        '\\n선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.\\n * 옵션\\n 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후\\n 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북\\n 날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈',\n    check_finedust:\n        '\\n선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.\\n * 옵션\\n 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북\\n 미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨',\n    get_weather_data:\n        '\\n선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.\\n * 옵션\\n 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후\\n 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북\\n 정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)',\n    get_current_weather_data:\n        '\\n현재 선택한 지역의 날씨 정보값(기온, 미세먼지농도)입니다.\\n * 옵션\\n 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북\\n 정보: (기온(℃)), 미세먼지농도(㎍)',\n    get_today_temperature:\n        '\\n오늘 선택한 지역과 시간대의 기온을 의미합니다.\\n * 옵션\\n 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북\\n 시간대: 00, 03, 06, 09, 12, 15, 18, 21',\n    check_city_weather:\n        '선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.\\n* 옵션\\n날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후\\n시도: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈',\n    check_city_finedust:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.\\n* 옵션\\n시도: 서울, 강원, 경기, 경남, 경북,광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨',\n    get_city_weather_data:\n        '선택한 날짜와 지역의 각종 날씨 정보입니다.\\n *옵션\\n날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후\\n시도:서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)',\n    get_current_city_weather_data:\n        '현재 선택한 지역의 날씨 정보입니다.\\n*옵션\\n시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n정보: 기온(℃), 미세먼지농도(㎍)',\n    get_today_city_temperature:\n        '오늘 선택한 지역과 시간대의 기온입니다.\\n*옵션\\n시도: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n시군구: 시도별로 다름\\n시간대: 00, 03, 06, 09, 12, 15, 18, 21',\n    get_cur_weather: '\\n선택한 지역의 현재 날씨입니다.',\n    get_cur_wind: '\\n선택한 지역의 현재 풍향입니다.',\n    get_cur_weather_data:\n        '\\n선택한 지역의 현재 기상 정보입니다.\\n- 기상 정보: 기온(℃), 미세먼지농도(PM10, ㎍)',\n    check_cur_weather: \"\\n선택한 지역의 현재 날씨가 선택한 날씨와 같다면 '참'으로 판단합니다.\",\n    check_cur_finddust:\n        '\\n선택한 지역의 현재 미세먼지 등급이 선택한 미세먼지 등급과 같다면 ‘참’으로 판단합니다.',\n    get_day_weather: '\\n선택한 지역의 일별 날씨입니다.',\n    get_day_weather_data:\n        '\\n선택한 지역의 일별 기상 정보입니다.\\n- 기상 정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)',\n    check_day_weather: \"\\n선택한 지역의 일별 날씨가 선택한 날씨와 같다면 '참'으로 판단합니다.\",\n    get_time_weather: '\\n선택한 지역의 시간대별(3시간) 날씨입니다.',\n    get_time_weather_data:\n        '\\n선택한 지역의 시간대별(3시간) 기상 정보입니다.\\n- 기상 정보: 기온(°c), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)',\n    check_time_weather:\n        \"\\n선택한 지역의 시간대별(3시간) 날씨가 선택한 날씨와 같다면 '참'으로 판단합니다.\",\n    count_festival:\n        '선택한 날짜와 지역에서 열리는 행사의 수입니다.\\n* 옵션 \\n지역: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n행사일: 1~12월',\n    get_festival_info:\n        '선택한 날짜와 지역에서 열리는 행사에 대한 정보입니다.\\n* 옵션 \\n지역: 서울, 강원, 경기, 경남, 경북 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 \\n행사일: 1~12월 \\n정보: 제목, 지역, 시작일, 종료일, 주소, 개요, 홈페이지',\n    get_translated_string:\n        '입력한 문자값을 선택한 언어로 번역합니다. 입력은 3000자까지 가능합니다.\\n*번역 가능한 언어 \\n - 한국어 → 영어, 중국어 간체, 중국어 번체, 베트남어, 스페인어, 인도네시아어, 태국어, 프랑스어\\n - 영어 → 일본어, 프랑스어, 한국어\\n - 중국어 간체, 중국어 번체, 베트남어, 스페인어, 인도네시아어, 태국어, 프랑스어 → 한국어\\n - 일본어 →영어 \\n - 프랑스어 → 영어',\n    check_language: '입력된 문자값의 언어를 감지합니다. 입력은 문장 형태로 3000자까지 가능합니다.',\n    count_disaster_behavior:\n        '선택한 자연재해가 발생했을 때 해야할 행동요령의 수입니다.\\n *옵션\\n 자연재해: 태풍, 홍수, 호우, 강풍, 대설, 한파, 풍랑, 황사, 폭염, 가뭄, 지진, 해일, 산사태\\n 상황: 자연재해에 따라 다름 ',\n    get_disaster_behavior:\n        '선택한 자연재해가 발생했을 때 해야하는 행동요령에 대한 정보입니다.\\n *옵션\\n 자연재해: 태풍, 홍수, 호우, 강풍, 대설, 한파, 풍랑, 황사, 폭염, 가뭄, 지진, 해일, 산사태\\n 상황: 자연재해에 따라 다름',\n    count_lifeSafety_behavior:\n        '선택한 생활 속 문제가 발생했을 때 해야할 행동요령의 수입니다.\\n *옵션\\n 생활 속 문제: 응급처치, 심폐소생술, 소화기·소화전 사용법, 식중독, 산행안전, 실종유괴, 성폭력, 학교폭력, 가정 폭력, 억류 및 납치, 교통사고, 승강기 안전사고, 미세먼지\\n 상황: 생활 속 문제에 따라 다름 ',\n    get_lifeSafety_behavior:\n        '선택한 생활 속 문제가 발생했을 때 해야할 행동요령에 대한 정보입니다.\\n *옵션\\n 생활 속 문제: 응급처치, 심폐소생술, 소화기·소화전 사용법, 식중독, 산행안전, 실종유괴, 성폭력, 학교폭력, 가정 폭력, 억류 및 납치, 교통사고, 승강기 안전사고, 미세먼지\\n 상황: 생활 속 문제에 따라 다름 ',\n    count_disaster_guideline:\n        '선택한 자연재난과 진행 정도에 따른 행동요령의 수입니다.\\n\\n- 자연재난: 태풍, 홍수, 호우, 강풍, 대설, 한파, 풍랑, 황사, 폭염, 가뭄, 지진, 지진해일, 해일, 산사태, 화산폭발',\n    get_disaster_guideline:\n        '선택한 자연재난과 진행 정도에 따른 행동요령의 내용입니다.\\n\\n- 자연재난: 태풍, 홍수, 호우, 강풍, 대설, 한파, 풍랑, 황사, 폭염, 가뭄, 지진, 지진해일, 해일, 산사태, 화산폭발',\n    count_social_disaster_guideline:\n        '선택한 사회재난과 진행 정도에 따른 행동요령의 수입니다.\\n\\n- 사회재난: 해양오염, 대규모 수질오염, 식용수, 공동구 재난, 가축질병, 감염병, 철도·지하철, 금융전산, 원전사고, 화학물질, 화재, 산불, 건축물 붕괴, 댐 붕괴, 폭발, 항공기, 화생방, 정전 및 전력부족, 전기·가스, 유도선, 수난사고, 테러, 전력수급',\n    get_social_disaster_guideline:\n        '선택한 사회재난과 진행 정도에 따른 행동요령의 내용입니다.\\n\\n- 사회재난: 해양오염, 대규모 수질오염, 식용수, 공동구 재난, 가축질병, 감염병, 철도·지하철, 금융전산, 원전사고, 화학물질, 화재, 산불, 건축물 붕괴, 댐 붕괴, 폭발, 항공기, 화생방, 정전 및 전력부족, 전기·가스, 유도선, 수난사고, 테러, 전력수급',\n    count_safety_accident_guideline:\n        '\"선택한 생활 안전 사고가 발생했을 때 해야할 행동요령의 수입니다.\\n\\n- 생활안전 사고: 응급처치, 심폐소생술, 소화기, 식중독, 산행, 어린이 놀이시설, 실종유괴, 성폭력, 학교 폭력, 가정 폭력, 억류 및 납치, 교통사고, 승강기, 미세먼지, 소화전, 가정 안전점검\"',\n    get_safety_accident_guideline:\n        '응급처치, 심폐소생술, 소화기, 식중독, 산행, 어린이 놀이시설, 실종유괴, 성폭력, 학교 폭력, 가정 폭력, 억류 및 납치, 교통사고, 승강기, 미세먼지, 소화전, 가정 안전점검',\n    read_text:\n        '입력한 문자값을 설정된 목소리로 읽습니다.\\n입력은 2500자까지 가능합니다.\\n인터넷에 연결되어 있지 않거나 인터넷 환경이 불안할 경우, 해당 블록이 실행되지 않고 다음 블록으로 넘어갈 수 있습니다.',\n    set_tts_property: '선택한 목소리가 선택한 속도와 선택한 음높이로 설정됩니다.',\n    read_text_wait_with_block: '입력한 문자값을 읽어준 후 다음 블록을 실행합니다.',\n    check_microphone: \"컴퓨터에 마이크가 연결되어 있는 경우 '참'으로 판단합니다.\",\n    speech_to_text_convert: '마이크를 통해 녹음된 음성을 인식합니다.',\n    timed_speech_to_text_convert:\n        '입력한 시간 동안 마이크를 통해 녹음된 음성을 선택한 언어로 인식합니다.',\n    set_visible_speech_to_text: '인식한 음성을 실행 화면에 보이게 하거나 숨깁니다.',\n    speech_to_text_get_value:\n        '사람의 목소리를 문자로 변환한 값입니다. 목소리가 입력되지 않거나, 음성 인식 도중 오류가 발생한 경우 null 값을 반환합니다.',\n    get_microphone_volume: '마이크에 입력되는 소리의 크기 값입니다.',\n    video_draw_webcam:\n        '컴퓨터에 연결된 카메라에 촬영되는 화면을 실행화면에서 보이게하거나 숨깁니다.(IE 및 iOS 미지원)',\n    video_check_webcam:\n        \"컴퓨터에 카메라가 연결되어 있는 경우 '참'으로 판단합니다. (IE 및 iOS 미지원)\",\n    video_change_cam: '촬영하는 카메라를 변경합니다.',\n    video_set_camera_opacity_option:\n        '촬영되는 화면의 투명도 효과를 입력한 값으로 정합니다. 0~100 사이의 범위로 설정할 수 있습니다. (0 이하는 0으로 100 이상은 100으로 처리됩니다.) (IE 및 iOS 미지원)',\n    video_flip_camera: '촬영되는 화면을 좌우 혹은 상하로 뒤집습니다. (IE 및 iOS 미지원)',\n    video_toggle_model:\n        '선택한 인식 모델을 동작시키거나 중지시킵니다. (사람 인식: 사람의 몸을 인식하여 각 신체부위의 위치 등을 알 수 있습니다. 얼굴 인식: 사람의 얼굴을 인식하여 눈, 코, 입, 귀의 위치나 예상되는 성별, 나이, 감정을 알 수 있습니다. 사물 인식: 인식된 사물의 종류를 알 수 있습니다) (IE 및 iOS 미지원)',\n    video_toggle_ind:\n        '인식된 사람/얼굴/사물의 위치와 순서를 실행화면에 보이게 하거나 숨깁니다. (IE 및 iOS 미지원)',\n    video_number_detect:\n        '인식된 사람/얼굴/사물의 개수입니다. (인식 가능 객체: 사람, 자전거, 자동차, 오토바이, 비행기, 버스, 기차, 트럭, 보트,교통 신호등, 소화전, 정지 신호, 주차 미터, 벤치, 새, 고양이, 개, 말, 양, 암소, 코끼리, 곰, 얼룩말, 기린, 책가방, 우산, 핸드백, 넥타이, 가방, 프리스비, 스키, 스노보드, 스포츠 볼, 연, 야구 방망이, 야구 글러브, 스케이트 보드, 서핑 보드, 테니스 라켓, 병, 와인 글라스, 컵, 포크, 나이프, 숟가락, 그릇, 바나나, 애플, 샌드위치, 주황색, 브로콜리, 당근, 핫도그, 피자, 도넛, 케이크, 의자, 소파, 화분, 침대, 식사테이블, 화장실, TV 모니터, 노트북, 마우스, 원격, 키보드, 휴대 전화, 전자 레인지, 오븐, 토스터기, 싱크대, 냉장고, 도서, 시계, 꽃병, 가위, 테디베어, 헤어드라이어, 칫솔) (IE 및 iOS 미지원)',\n    video_object_detected: \"선택한 사물이 인식된 경우 '참'으로 판단합니다. (IE 및 iOS 미지원)\",\n    video_is_model_loaded: \"사람/얼굴/사물 인식이 된 경우 '참'으로 판단합니다. (IE 및 iOS 미지원)\",\n    video_detected_face_info:\n        '입력한 순서의 얼굴의 성별/나이/감정의 추정값입니다. 인식이 잘 되지 않는 경우 무조건 0으로 출력됩니다. (IE 및 iOS 미지원)',\n    video_motion_value:\n        '선택한 오브젝트 혹은 실행화면 위에서 감지되는 움직임 혹은 방향 값입니다. (움직임: 움직임이 크고 빠를 수록 값이 커집니다. 방향: 오른쪽 혹은 위쪽으로 움직일 때 양수, 왼쪽 혹은 아래쪽으로 움직일 때 음수가 됩니다.) (IE 및 iOS 미지원)',\n    video_face_part_coord:\n        '입력한 순서의 얼굴 중 선택된 얼굴 부위의 위치값입니다. 인식이 잘 되지 않는 경우 무조건 0으로 출력됩니다. (왼쪽 눈, 오른쪽 눈, 코, 왼쪽 입꼬리, 오른쪽 입꼬리, 윗 입술, 아랫 입술) (IE 및 iOS 미지원)',\n    video_body_part_coord:\n        '입력한 순서의 사람의 선택한 신체 부위의 위치값입니다. (얼굴, 목, 왼쪽 어깨, 왼쪽 팔꿈치, 왼쪽 손목, 왼쪽 엉덩이, 왼쪽 무릎, 왼쪽 발목, 오른쪽 어깨, 오른쪽 팔꿈치, 오른쪽 손목, 오른쪽 엉덩이, 오른쪽 무릎, 오른쪽 발목) (IE 및 iOS 미지원)',\n    append_row_to_table:\n        '선택한 테이블의 마지막에 행(열)을 추가합니다. 추가된 행(열)의 모든 셀 값은 0입니다.',\n    insert_row_to_table:\n        '선택한 테이블의 입력한 순서에 행(열)을 추가합니다. 추가된 행(열)의 모든 셀 값은 0입니다. 추가된 행(열) 뒤에 있는 행(열)들은 순서가 하나씩 밀립니다.',\n    delete_row_from_table: '선택한 테이블의 입력한 순서에 있는 행(열)을 삭제합니다.',\n    set_value_from_table: '선택한 테이블에서 입력한 행의 속성을 입력한 값으로 바꿉니다.',\n    save_current_table:\n        '테이블을 현재 상태로 남깁니다. 작품을 정지해도 테이블에서 변경된 내용이 유지됩니다.',\n    get_table_count: '선택한 테이블의 행(열) 개수입니다.',\n    get_value_from_table:\n        '선택한 테이블에서 입력한 행의 속성 값입니다.\\n속성 값 블록 대신 (열을 의미하는) 값 블록을 결합해 사용할 수도 있습니다.',\n    get_value_from_last_row:\n        '선택한 테이블에서 마지막 행의 선택한 속성 값입니다.\\n속성 값 블록 대신 (열을 의미하는) 값 블록을 결합해 사용할 수도 있습니다.',\n    calc_values_from_table:\n        '선택한 테이블에서 선택한 속성들에 대한 요약통계량입니다. (합, 최댓값, 최솟값, 평균값, 표준편차, 중앙값)',\n    open_table: '선택한 테이블의 테이블 창을 엽니다.',\n    open_table_wait: '입력한 시간 동안 선택한 테이블의 테이블 창을 엽니다.',\n    open_table_chart: '선택한 테이블의 차트 창을 엽니다.',\n    close_table_chart: '열려있는 테이블 차트 창을 닫습니다.',\n    get_coefficient:\n        '선택한 테이블에서 두 속성 사이의 상관계수입니다. 상관계수가 1(-1)에 가까울 수록 강한 양(음)의 선형 상관관계를 갖습니다.',\n    set_value_from_cell: '테이블에서 선택한 셀을 입력한 값으로 바꿉니다.',\n    get_value_from_cell: '테이블에서 선택한 셀의 값입니다.',\n    get_value_v_lookup:\n        '테이블에서 선택한 열이 특정한 값인 행을 찾고, 그 행의 다른 열 값을 반환합니다.',\n    insert_data_for_test: '데이터를 입력하고 학습한 모델로 인식합니다.',\n    insert_text_block_for_test: '데이터를 입력하고 학습한 모델로 인식합니다.',\n    test_result:\n        '입력한 데이터를 모델에서 인식한 결과 값입니다. 값은 모델의 클래스 이름(텍스트)으로 표현됩니다.',\n    accuracy_of_result:\n        '입력한 데이터의 선택한 클래스에 대한 신뢰도 값입니다. 값은 확률(숫자)로 표현됩니다.',\n    is_group: \"입력한 데이터의 인식 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    retrain_model:\n        '모델을 다시 학습합니다. 모델 설정을 변경하거나, 입력 데이터가 되는 테이블의 내용을 수정했다면, 변경된 내용을 바탕으로 모델을 다시 학습합니다.',\n    model_is_trained:\n        \"모델이 학습되었다면 '참'을, 학습 중이거나 학습되지 않았다면 '거짓'으로 판단합니다.\",\n    set_train_visible: '모델의 상태를 표시하는 창을 실행 화면에 보이게 하거나 숨깁니다.',\n    set_train_chart:\n        '입력한 데이터와 학습한 모델의 군집을 2차원 좌표평면에 나타낸 차트 창을 열거나 닫습니다. ',\n    set_regression_option:\n        \"모델의 학습 조건을 변경합니다. 변경한 학습 조건은 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    get_regression_predict_1: '입력한 핵심 속성으로 모델이 예측한 값을 반환합니다.',\n    get_regression_predict_2: '입력한 핵심 속성으로 모델이 예측한 값을 반환합니다.',\n    get_regression_predict_3: '입력한 핵심 속성으로 모델이 예측한 값을 반환합니다.',\n    get_regression_predict_4: '입력한 핵심 속성으로 모델이 예측한 값을 반환합니다.',\n    get_regression_predict_5: '입력한 핵심 속성으로 모델이 예측한 값을 반환합니다.',\n    get_regression_predict_6: '입력한 핵심 속성으로 모델이 예측한 값을 반환합니다.',\n    get_regression_accuracy: '모델의 결정계수를 값으로 반환합니다.',\n    set_logistic_regression_option:\n        \"모델의 학습 조건을 변경합니다. 변경한 학습 조건은 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    set_logistic_regression_optimizer:\n        \"모델의 최적화 알고리즘을 변경합니다. 변경한 최적화 알고리즘은 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    get_logistic_regression_probability_1:\n        '입력한 데이터의 선택한 클래스에 대한 확률 값입니다. 값은 숫자로 표현됩니다.',\n    get_logistic_regression_probability_2:\n        '입력한 데이터의 선택한 클래스에 대한 확률 값입니다. 값은 숫자로 표현됩니다.',\n    get_logistic_regression_probability_3:\n        '입력한 데이터의 선택한 클래스에 대한 확률 값입니다. 값은 숫자로 표현됩니다.',\n    get_logistic_regression_probability_4:\n        '입력한 데이터의 선택한 클래스에 대한 확률 값입니다. 값은 숫자로 표현됩니다.',\n    get_logistic_regression_probability_5:\n        '입력한 데이터의 선택한 클래스에 대한 확률 값입니다. 값은 숫자로 표현됩니다.',\n    get_logistic_regression_probability_6:\n        '입력한 데이터의 선택한 클래스에 대한 확률 값입니다. 값은 숫자로 표현됩니다.',\n    set_decisiontree_option:\n        \"모델의 학습 조건을 변경합니다. 변경한 학습 조건은 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    set_decisiontree_tree: '학습한 결정 트리를 나타낸 창을 열거나 닫습니다.',\n    set_svm_option:\n        \"모델의 학습 조건을 변경합니다. 변경한 학습 조건은 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    set_kernel_linear:\n        \"학습 조건 중 커널을 선형으로 변경합니다. 변경한 학습 조건은 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    set_kernel_option:\n        \"학습 조건 중 커널을 다항식 또는 RBF로 변경합니다. 변경한 학습 조건은 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    is_result_1: \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_result_2: \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_result_3: \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_result_4: \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_result_5: \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_result_6: \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    get_predict_1:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 클래스 이름(텍스트)으로 표현됩니다.',\n    get_predict_2:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 클래스 이름(텍스트)으로 표현됩니다.',\n    get_predict_3:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 클래스 이름(텍스트)으로 표현됩니다.',\n    get_predict_4:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 클래스 이름(텍스트)으로 표현됩니다.',\n    get_predict_5:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 클래스 이름(텍스트)으로 표현됩니다.',\n    get_predict_6:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 클래스 이름(텍스트)으로 표현됩니다.',\n    get_result_info: '모델의 성능 평가 지표를 값으로 반환합니다.',\n    set_cluster_option_k:\n        \"군집의 개수를 입력한 값으로 바꾸어 설정합니다. 변경한 군집 개수는 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    set_cluster_option_centroids:\n        \"군집의 최초 중심점 기준을 선택한 기준으로 바꿉니다. 변경한 중심점 기준은 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    get_cluster_centriod_count: '모델의 군집 개수를 값으로 반환합니다. ',\n    get_cluster_centriod_value:\n        '지정한 군집의 중심점에 대한 핵심 속성을 반환합니다. 핵심 속성이 여러 개인 경우, 목록 상자에서 핵심 속성을 선택할 수 있습니다.',\n    get_cluster_centriod_index_1:\n        '입력한 핵심 속성이 모델이 묶은 군집 중에 어느 군집에 속하는지를 반환합니다. 값은 텍스트(군집 이름)로 표현됩니다.',\n    get_cluster_centriod_index_2:\n        '입력한 핵심 속성이 모델이 묶은 군집 중에 어느 군집에 속하는지를 반환합니다. 값은 텍스트(군집 이름)로 표현됩니다.',\n    get_cluster_centriod_index_3:\n        '입력한 핵심 속성이 모델이 묶은 군집 중에 어느 군집에 속하는지를 반환합니다. 값은 텍스트(군집 이름)로 표현됩니다.',\n    get_cluster_centriod_index_4:\n        '입력한 핵심 속성이 모델이 묶은 군집 중에 어느 군집에 속하는지를 반환합니다. 값은 텍스트(군집 이름)로 표현됩니다.',\n    get_cluster_centriod_index_5:\n        '입력한 핵심 속성이 모델이 묶은 군집 중에 어느 군집에 속하는지를 반환합니다. 값은 텍스트(군집 이름)로 표현됩니다.',\n    get_cluster_centriod_index_6:\n        '입력한 핵심 속성이 모델이 묶은 군집 중에 어느 군집에 속하는지를 반환합니다. 값은 텍스트(군집 이름)로 표현됩니다.',\n    set_number_learning_option_k:\n        \"이웃 개수를 입력한 값으로 바꾸어 설정합니다. 변경한 이웃 개수는 '모델 다시 학습하기' 블록으로 모델을 다시 학습할 때부터 적용됩니다.\",\n    get_number_learning_predict_1:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 모델의 클래스 이름(텍스트)으로 표현됩니다.',\n    get_number_learning_predict_2:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 모델의 클래스 이름(텍스트)으로 표현됩니다.',\n    get_number_learning_predict_3:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 모델의 클래스 이름(텍스트)으로 표현됩니다.',\n    get_number_learning_predict_4:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 모델의 클래스 이름(텍스트)으로 표현됩니다.',\n    get_number_learning_predict_5:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 모델의 클래스 이름(텍스트)으로 표현됩니다.',\n    get_number_learning_predict_6:\n        '입력한 데이터를 모델에서 분류한 값입니다. 값은 모델의 클래스 이름(텍스트)으로 표현됩니다.',\n    get_number_learning_predict_param_1:\n        '입력한 데이터의 선택한 클래스에 대한 분류 신뢰도 값입니다. 값은 숫자로 표현됩니다.',\n    get_number_learning_predict_param_2:\n        '입력한 데이터의 선택한 클래스에 대한 분류 신뢰도 값입니다. 값은 숫자로 표현됩니다.',\n    get_number_learning_predict_param_3:\n        '입력한 데이터의 선택한 클래스에 대한 분류 신뢰도 값입니다. 값은 숫자로 표현됩니다.',\n    get_number_learning_predict_param_4:\n        '입력한 데이터의 선택한 클래스에 대한 분류 신뢰도 값입니다. 값은 숫자로 표현됩니다.',\n    get_number_learning_predict_param_5:\n        '입력한 데이터의 선택한 클래스에 대한 분류 신뢰도 값입니다. 값은 숫자로 표현됩니다.',\n    get_number_learning_predict_param_6:\n        '입력한 데이터의 선택한 클래스에 대한 분류 신뢰도 값입니다. 값은 숫자로 표현됩니다.',\n    is_number_learning_group_1:\n        \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_number_learning_group_2:\n        \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_number_learning_group_3:\n        \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_number_learning_group_4:\n        \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_number_learning_group_5:\n        \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    is_number_learning_group_6:\n        \"입력한 데이터의 분류 결과가 선택한 클래스인 경우 '참'으로 판단합니다.\",\n    bitbrick_when_button_pressed: '비트브릭 버튼을 누르면 아래에 연결된 블록들을 실행합니다.',\n    bitbrick_when_sensor_get_value:\n        '비트브릭 센서의 값과 오른쪽에 입력한 값을 비교합니다.\\n< : 센서 값이 오른쪽에 위치한 값보다 작은 경우 ‘참’으로 판단합니다.\\n> : 센서 값이 오른쪽에 위치한 값보다 큰 경우 ‘참으로 판단합니다.\\n= :  센서 값이 오른쪽에 위치한 값과 같은 경우 ‘참으로 판단합니다.',\n    bitbrick_sensor_value:\n        '비트브릭 센서를 사용할 수 있는 블록입니다. 센서값의 범위는 0 ~1023입니다. 메인보드에 연결된 센서의 종류와 포트번호를 자동으로 인식합니다. 블록 안의 화살표를 눌러 사용하려고 하는 센서를 선택하세요.',\n    bitbrick_convert_scale: '비트브릭 센서의 값의 범위를 바꿀 수 있습니다.',\n    bitbrick_is_touch_pressed: '비트브릭 센서 중 버튼을 눌렀을 경우 ‘참’으로 판단합니다.',\n    bitbrick_is_sensor_value_compare: '비트브릭 센서 중 버튼을 눌렀을 경우 ‘참’으로 판단합니다.',\n    bitbrick_turn_off_color_led: '비트브릭 엘이디를 끕니다.',\n    bitbrick_turn_on_color_led_by_rgb:\n        '비트브릭 엘이디를 빛의 삼원색인 빨강,초록,파랑을 혼합하여 켭니다. 값의 범위는 0 ~ 255입니다.',\n    bitbrick_turn_on_color_led_by_picker: '비트브릭 엘이디를 색상 창을 사용해 켭니다.',\n    bitbrick_turn_on_color_led_by_value:\n        '비트브릭 엘이디를 색상 값으로 켭니다. 값의 범위는 0 ~ 199입니다.',\n    bitbrick_buzzer:\n        '비트브릭 버저를 사용하여 소리를 냅니다. 값의 범위는 0 ~ 96입니다. 값이 0일 때는 버저 소리를 끕니다.',\n    bitbrick_turn_off_all_motors: '비트브릭 모터를 모두 끕니다.',\n    bitbrick_dc_speed:\n        '비트브릭 디씨모터의 속도를 제어합니다. 속도 값의 범위는 –100 ~ 100입니다. 음수(-)일 때는 반시계방향으로 회전합니다. 양수(+)일 때는 시계방향으로 회전합니다. 속도가 0일 때는 회전을 멈춥니다.',\n    bitbrick_dc_direction_speed:\n        '비트브릭 디씨모터의 방향과 속력을 제어합니다. 방향은 시계방향과 반시계방향을 선택할 수 있습니다. 속력 값의 범위는 0 ~ 100입니다. 속력이 0일 때는 회전을 멈춥니다.',\n    bitbrick_servomotor_angle:\n        '비트브릭 서보모터의 각도를 제어합니다. 각도 값의 범위는 0 ~ 180입니다.',\n    diaboard_when_button_pressed:\n        '선택한 버튼을 누르거나 누르지 않으면 아래에 연결된 블록들을 실행합니다.',\n    diaboard_when_color_is: '선택한 색상을 컬러센서가 감지하면 아래에 연결된 블록들을 실행합니다.',\n    diaboard_when_sensor_is:\n        \"선택한 센서의 값과 오른쪽의 값을 비교하여 아래에 연결된 블록들을 실행합니다.\\n< : 센서값이 오른쪽 값보다 작은 경우 '참'으로 판단합니다.\\n> : 센서값이 오른쪽 값보다 큰 경우 '참'으로 판단합니다.\\n= : 센서값이 오른쪽 값과 같은 경우 '참'으로 판단합니다.\",\n    diaboard_button_pressed: \"선택한 버튼을 누르거나 누르지 않은 경우 '참'으로 판단합니다.\",\n    diaboard_color_sensor_is: \"선택한 색상을 컬러센서가 감지한 경우 '참'으로 판단합니다.\",\n    diaboard_sensor_condition:\n        \"선택한 센서의 값과 오른쪽의 값을 비교합니다.\\n< : 센서값이 오른쪽 값보다 작은 경우 '참'으로 판단합니다.\\n> : 센서값이 오른쪽 값보다 큰 경우 '참'으로 판단합니다.\\n= : 센서값이 오른쪽 값과 같은 경우 '참'으로 판단합니다.\",\n    diaboard_color_sensor_seven_hue:\n        '컬러센서가 감지하는 색상을 7가지로 분류한 값입니다.\\n7가지 색상 : 빨강, 노랑, 녹색, 청록, 파랑, 보라, 하양',\n    diaboard_color_sensor_one_hue:\n        '컬러센서가 감지한 색상값입니다.\\n색상(hue) : 0 ~ 359 사이 범위로 설정할 수 있습니다.\\n(총 360가지의 색상을 감지하며 360과 0은 같은 색으로 표현됩니다.)',\n    diaboard_sensor_value:\n        '선택한 센서가 감지한 값입니다. 값의 범위는 0 ~ 1023입니다. \\n적외선 센서 : 물체에 반사된 적외선을 양을 측정하여 물체와의 거리를 감지합니다.\\n밝기 센서 : 주변 환경이 얼마나 밝고 어두운지를 감지합니다.',\n    diaboard_convert_scale:\n        '선택한 센서가 감지한 값의 범위를 사용자가 임의로 바꿔서 사용합니다.\\n적외선 센서 : 물체에 반사된 적외선을 양을 측정하여 물체와의 거리를 감지합니다.\\n밝기 센서 : 주변 환경이 얼마나 밝고 어두운지를 감지합니다.',\n    diaboard_led_rainbow: '엘이디를 무지개 효과로 켭니다.',\n    diaboard_led_rainbow_time:\n        '엘이디를 입력한 시간만큼 무지개 효과로 켭니다.\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.',\n    diaboard_led_effect: '엘이디를 선택한 효과와 선택한 색상으로 켭니다.',\n    diaboard_led_effect_time:\n        '엘이디를 입력한 시간만큼 선택한 효과와 선택한 색상으로 켭니다.\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.',\n    diaboard_led_six: '엘이디 1번 ~ 6번을 선택한 색상으로 각자 켭니다.',\n    diaboard_led_one: '선택한 번호의 엘이디를 선택한 색상으로 켭니다.',\n    diaboard_led_one_time:\n        '선택한 번호의 엘이디를 입력한 시간만큼 선택한 색상으로 켭니다.\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.',\n    diaboard_led_hue:\n        '선택한 번호의 엘이디를 색상(hue)값으로 켭니다.\\n색상( hue) : 0 ~ 359 사이 범위로 설정할 수 있습니다.\\n(총 360가지의 색상을 감지하며 360과 0은 같은 색으로 표현됩니다.)',\n    diaboard_led_color:\n        \"선택한 번호의 엘이디를 현재 컬러센서가 감지한 색상(7가지)으로 켭니다. 컬러센서 색상이 '없음'일 때는 코드를 실행해도 엘이디를 켜지 않습니다.\\n7가지 색상 : 빨강, 노랑, 녹색, 청록, 파랑, 보라, 하양\",\n    diaboard_led_rgb:\n        '선택한 번호의 엘이디를 빨강, 녹색, 파랑값으로 켭니다.\\n빨강, 녹색, 파랑 : 0 ~ 255의 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 255이상은 255로 처리됩니다. )',\n    diaboard_led_turn_off_all: '선택한 번호의 엘이디를 끕니다.',\n    diaboard_servomotor_angle:\n        '선택한 포트의 서보모터의 각도를 입력한 값으로 정합니다.\\n각도 : 0 ~ 180 사이 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 180이상은 180으로 처리됩니다.)',\n    diaboard_servomotor_angle_time:\n        '선택한 포트의 서보모터의 초기각도와 목표각도를 설정해 입력한 시간만큼 각도를 바꿉니다.\\n각도 : 0 ~ 180 사이 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 180이상은 180으로 처리됩니다.)\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.',\n    diaboard_dc_direction_speed:\n        '선택한 포트의 디씨모터의 방향과 속력을 정합니다.\\n방향 : 시계방향과 반시계 방향을 설정할 수 있습니다.\\n속력 : 0 ~ 100까지 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 100이상은 100으로 처리됩니다.)',\n    diaboard_dc_direction_speed_time:\n        '선택한 포트의 디씨모터의 방향과 속력을 정하고, 입력한 시간만큼 동작합니다.\\n방향 : 시계방향과 반시계 방향을 설정할 수 있습니다.\\n속력 : 0 ~ 100까지 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 100이상은 100으로 처리됩니다.)\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.',\n    diaboard_dc_speed:\n        '선택한 포트의 디씨모터의 속도를 정합니다.\\n속도 : -100 ~ 100 사이의 범위로 설정할 수 있습니다.\\n(-100이하는 -100으로, 100이상은 100으로 처리됩니다.)',\n    diaboard_dc_speed_time:\n        '선택한 포트의 디씨모터의 속도를 정하고, 입력한 시간만큼 동작합니다.\\n속도 : -100 ~ 100 사이의 범위로 설정할 수 있습니다.\\n(-100이하는 -100으로, 100이상은 100으로 처리됩니다.)\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.',\n    diaboard_turn_off_all_motors: '선택한 포트의 모터를 멈춥니다.',\n    diaboard_buzzer_melody_type: '선택한 멜로디를 연주합니다.',\n    diaboard_buzzer_effect_type: '선택한 효과음을 냅니다.',\n    diaboard_buzzer_eight_melody_bpm:\n        '선택한 음들을 입력한 BPM으로 연주합니다.\\n연주속도(BPM) : 30 ~ 300 사이의 범위로 설정할 수 있습니다.\\n(30이하는 30으로, 300이상은 300으로 처리됩니다.)',\n    diaboard_buzzer_octave: '선택한 옥타브와 음으로 연주합니다.',\n    diaboard_buzzer_octave_rhythm: '선택한 옥타브와 음을 입력한 박자로 연주합니다.',\n    diaboard_buzzer_hz:\n        '입력한 주파수로 연주합니다.\\n주파수 : 33 ~ 7,900 사이의 범위로 설정할 수 있습니다.\\n(33이하는 33으로 7,900이상은 7,900으로 처리됩니다.)',\n    diaboard_buzzer_hz_change: '입력한 주파수만큼 바꿔서 연주합니다.',\n    diaboard_buzzer_speed_bpm:\n        '입력한 BPM으로 연주 속도를 정합니다.\\n연주속도(BPM) : 30 ~ 300 사이의 범위로 설정할 수 있습니다.\\n(30이하는 30으로, 300이상은 300으로 처리됩니다.)',\n    diaboard_buzzer_speed_bpm_change: '입력한 BPM만큼 연주 속도를 바꿉니다.',\n    diaboard_buzzer_sleep_rhythm: '선택한 박자만큼 쉽니다.',\n    diaboard_buzzer_stop: '버저음을 멈춥니다.',\n    change_rgb_to_hex: '입력한 빨강(R), 초록(G), 파랑(B) 값을 HEX 값으로 변환한 값입니다.',\n    change_hex_to_rgb: '입력한 HEX 값을 빨강(R), 초록(G), 파랑(B) 중 하나로 변환한 값입니다.',\n    media_pipe_video_screen:\n        '연결된 카메라가 촬영하는 것을 실행 화면에서 보이게 하거나 숨깁니다.\\n(기본값으로 50%의 투명도가 적용되어 있습니다.)',\n    media_pipe_switch_camera: '촬영하는 카메라를 변경합니다.',\n    check_connected_camera: \"컴퓨터에 카메라가 연결되어 있는 경우 '참'으로 판단합니다.\",\n    media_pipe_flip_camera: '촬영되는 화면을 좌우 혹은 상하로 뒤집습니다.',\n    media_pipe_set_opacity_camera:\n        '촬영되는 화면의 투명도 효과를 입력한 값으로 정합니다. 0~100 사이의 범위로 설정할 수 있습니다.\\n(기본값은 50이며, 0 이하는 0으로 100 이상은 100으로 처리됩니다.)',\n    media_pipe_motion_value:\n        '선택한 오브젝트 혹은 실행 화면 위에서 감지되는 움직임 혹은 방향 값입니다.\\n- 움직임: 움직임이 크고 빠를 수록 값이 커집니다.\\n- 방향: 오른쪽 혹은 위쪽으로 움직일 때 양수, 왼쪽 혹은 아래쪽으로 움직일때 음수가 됩니다',\n    when_pose_landmarker: '사람을 인식하면 아래에 연결된 블록들을 실행합니다.',\n    pose_landmarker:\n        '사람 인식을 시작하거나 중지합니다.\\n- 사람 인식: 사람의 몸을 인식하여 각 신체 부위의 위치 등을 좌표로 반환할 수 있습니다.',\n    draw_detected_pose: '인식한 사람의 형태를 실행 화면에 보이게 하거나 숨깁니다.',\n    check_detected_pose: \"사람이 인식된 경우 '참'으로 판단합니다.\",\n    count_detected_pose: '인식한 사람의 수입니다.',\n    locate_to_pose:\n        '오브젝트가 선택한 사람의 신체 부위로 이동합니다.\\n(오브젝트의 중심점이 기준이 됩니다.)',\n    locate_time_to_pose:\n        '오브젝트가 입력한 시간에 걸쳐 선택한 사람의 신체 부위로 이동합니다.\\n(오브젝트의 중심점이 기준이 됩니다.)',\n    axis_detected_pose:\n        '입력한 순서의 사람의 선택한 신체 부위의 위치값입니다. 인식이 되지 않은 경우 0을 반환합니다.\\n(신체 부위: 코, 왼쪽 눈 안쪽, 왼쪽 눈, 왼쪽 눈 바깥쪽, 오른쪽 눈 안쪽, 오른쪽 눈, 오른쪽 눈 바깥쪽, 왼쪽 귀, 오른쪽 귀, 왼쪽 입꼬리, 오른쪽 입꼬리, 왼쪽 어깨, 오른쪽 어깨, 왼쪽 팔꿈치, 오른쪽 팔꿈치, 왼쪽 손목, 오른쪽 손목, 왼쪽 소지, 오른쪽 소지, 왼쪽 검지, 오른쪽 검지, 왼쪽 엄지, 오른쪽 엄지, 왼쪽 엉덩이, 오른쪽 엉덩이, 왼쪽 무릎, 오른쪽 무릎, 왼쪽 발목, 오른쪽 발목, 왼쪽 발꿈치, 오른쪽 발꿈치, 왼쪽 발끝, 오른쪽 발끝)',\n    when_face_landmarker: '얼굴을 인식하면 아래에 연결된 블록들을 실행합니다.',\n    face_landmarker:\n        '얼굴 인식을 시작하거나 중지합니다.\\n- 얼굴 인식: 사람의 얼굴을 인식하여 눈, 코, 입, 귀의 위치나 예상되는 성별, 나이, 감정을 알 수 있습니다.',\n    draw_detected_face: '인식한 얼굴의 형태를 실행 화면에 보이게 하거나 숨깁니다.',\n    check_detected_face: \"얼굴이 인식된 경우 '참'으로 판단합니다.\",\n    count_detected_face: '인식한 얼굴의 수입니다.',\n    locate_to_face:\n        '오브젝트가 선택한 얼굴의 부위로 이동합니다.\\n(오브젝트의 중심점이 기준이 됩니다.)',\n    locate_time_to_face:\n        '오브젝트가 입력한 시간에 걸쳐 선택한 얼굴의 부위로 이동합니다.\\n(오브젝트의 중심점이 기준이 됩니다.)',\n    check_detected_gender: \"선택한 얼굴이 선택한 성별이면 '참'으로 판단합니다.\",\n    check_compare_age: \"선택한 얼굴의 나이가 입력한 수식에 해당한다면 '참'으로 판단합니다.\",\n    check_detected_emotion: \"선택한 얼굴이 선택한 감정이면 '참'으로 판단합니다.\",\n    axis_detected_face:\n        '입력한 순서의 얼굴 중 선택된 얼굴 부위의 위치값입니다. 인식이 잘 되지 않은 경우 무조건 0으로 출력됩니다. (얼굴 부위: 왼쪽 눈, 오른쪽 눈, 코, 왼쪽 입꼬리, 오른쪽 입꼬리, 윗 입술, 아랫 입술)',\n    get_detected_face_value:\n        '입력한 순서의 얼굴의 성별/나이/감정의 추정값입니다. 인식이 잘 되지 않은 경우 null을 반환합니다.',\n    when_object_detector: '사물을 인식하면 아래에 연결된 블록들을 실행합니다.',\n    object_detector:\n        '사물 인식을 시작하거나 중지합니다.\\n- 사물 인식: 인식한 사물의 종류를 알 수 있습니다.',\n    draw_detected_object: '인식한 사물의 위치와 순서를 실행 화면에 보이게 하거나 숨깁니다.',\n    check_detected_object: \"사물이 인식된 경우 '참'으로 판단합니다.\",\n    count_detected_object: '인식한 사물의 수입니다.',\n    is_detected_among_objects: \"선택한 사물이 인식된 경우 '참'으로 판단합니다.\",\n    when_hand_detection: '손을 인식하면 아래에 연결된 블록들을 실행합니다.',\n    hand_detection:\n        '손 인식을 시작하거나 중지합니다.\\n- 손 인식: 사람의 손을 인식하여 오른손인지 왼손인지 또는 어떤 동작인지를 구분하거나, 각 부위를 인식해 좌표로 반환할 수 있습니다.',\n    draw_detected_hand: '인식한 손의 형태를 실행 화면에 보이게 하거나 숨깁니다.',\n    check_detected_hand: \"손을 인식한 경우 '참'으로 판단합니다.\",\n    count_detected_hand: '인식한 손의 개수입니다.',\n    locate_to_hand:\n        '오브젝트가 선택한 손의 부위로 이동합니다.\\n(오브젝트의 중심점이 기준이 됩니다.)\\n\\n가장 먼저 인식된 손이 1번째가 되며, 2개의 손이 한 번에 인식되면 왼쪽부터 1번째가 됩니다.',\n    locate_time_to_hand:\n        '오브젝트가 입력한 시간에 걸쳐 선택한 손의 부위로 이동합니다.\\n(오브젝트의 중심점이 기준이 됩니다.)\\n\\n가장 먼저 인식된 손이 1번째가 되며, 2개의 손이 한 번에 인식되면 왼쪽부터 1번째가 됩니다.',\n    axis_detected_hand:\n        '입력한 순서의 손에서 선택한 부위의 위치 값입니다. 인식이 되지 않은 경우 0을 반환합니다.\\n\\n가장 먼저 인식된 손이 1번째가 되며, 2개의 손이 한 번에 인식되면 왼쪽부터 1번째가 됩니다.',\n    is_which_hand: \"입력한 순서의 손이 선택한 손이라면 '참'으로 판단합니다.\",\n    get_which_hand: '입력한 순서의 손이 오른손인지, 왼손인지를 반환합니다.',\n    is_which_gesture: \"입력한 순서의 손이 선택한 모양이라면 '참'으로 판단합니다.\",\n    get_which_gesture: '입력한 순서의 손이 어떤 모양인지를 반환합니다.',\n    video_capture_for_image_test:\n        '카메라를 통해 촬영된 이미지 데이터를 학습한 모델로 분류하거나 중지합니다.',\n    train_param_kernel_polynomial: '',\n    train_param_kernel_rbf: '',\n    train_param_degree: '',\n    train_param_gamma: '',\n    target_project: '목표 작품 확인하기',\n    study_goal: '학습 목표 확인하기',\n    show_hint: '힌트보기',\n};\nLang.Category = {\n    entrybot_friends: '엔트리봇 친구들',\n    people: '사람',\n    animal: '동물',\n    animal_flying: '하늘',\n    animal_land: '땅',\n    animal_water: '물',\n    animal_others: '기타',\n    plant: '식물',\n    plant_flower: '꽃',\n    plant_grass: '풀',\n    plant_tree: '나무',\n    plant_others: '기타',\n    vehicles: '탈것',\n    vehicles_flying: '하늘',\n    vehicles_land: '땅',\n    vehicles_water: '물',\n    vehicles_others: '기타',\n    architect: '건물',\n    architect_building: '건축물',\n    architect_monument: '기념물',\n    architect_others: '기타',\n    food: '음식',\n    food_vegetables: '과일/채소',\n    food_meat: '고기',\n    food_drink: '음료',\n    food_others: '기타',\n    environment: '환경',\n    environment_nature: '자연',\n    environment_space: '우주',\n    environment_others: '기타',\n    stuff: '물건',\n    stuff_living: '생활',\n    stuff_hobby: '취미',\n    stuff_others: '기타',\n    fantasy: '판타지',\n    interface: '인터페이스',\n    interface_website: '웹사이트',\n    interface_game: '게임',\n    interface_others: '기타',\n    background: '배경',\n    background_outdoor: '실외',\n    background_indoor: '실내',\n    background_nature: '자연',\n    background_others: '기타',\n};\nLang.Device = {\n    arduino: '아두이노',\n    hamster: '햄스터',\n    roboid: '로보이드',\n    turtle: '거북이',\n    albert: '알버트',\n    robotis_carCont: '로보티즈 자동차 로봇',\n    robotis_openCM70: '로보티즈 IoT',\n    sensorBoard: '엔트리 센서보드',\n    trueRobot: '뚜루뚜루',\n    CODEino: '코드이노',\n    bitbrick: '비트브릭',\n    creamo: '크리모',\n    playcode: '플레이코드',\n    funboard: '펀보드',\n    bitBlock: '비트블록',\n    xbot_epor_edge: '엑스봇',\n    dplay: '디플레이',\n    iboard: '아이보드',\n    nemoino: '네모이노',\n    ev3: 'EV3',\n    robotori: '로보토리',\n    smartBoard: '스마트보드',\n    chocopi: '초코파이보드',\n    rokoboard: '로코보드',\n    altino: '알티노',\n    mechatro: '메카트로',\n};\nLang.General = {\n    apply: '켜기',\n    clear: ' 끄기',\n    turn_on: '켜기',\n    turn_off: '끄기',\n    left: '왼쪽',\n    right: '오른쪽',\n    param_string: '문자값',\n    both: '양쪽',\n    transparent: '투명',\n    black: '검은색',\n    brown: '갈색',\n    red: '빨간색',\n    yellow: '노란색',\n    green: '초록색',\n    skyblue: '하늘색',\n    blue: '파란색',\n    purple: '보라색',\n    white: '하얀색',\n    note_c: '도',\n    note_d: '레',\n    note_e: '미',\n    note_f: '파',\n    note_g: '솔',\n    note_a: '라',\n    note_b: '시',\n    questions: '문제',\n    clock: '시계',\n    counter_clock: '반시계',\n    font_size: '글자 크기',\n    second: '초',\n    alert_title: '알림',\n    confirm_title: '확인',\n    update_title: '업데이트 알림',\n    recent_download: '최신 버전 다운로드',\n    recent_download2: '최신버전 다운로드',\n    latest_version: '최신 버전입니다.',\n    dont_show_again: '다시보지 않기',\n};\nLang.Fonts = {\n    jeju_hallasan: '한라산체',\n    gothic_coding: '코딩고딕체',\n    batang: '바탕체',\n    gothic: '나눔고딕',\n    myeongjo: '나눔명조',\n    pen_script: '나눔손글씨',\n    square_round: '나눔스퀘어라운드',\n    jalnan: '잘난체',\n    designhouse: '디자인하우스체',\n    malssami815: '말싸미815체',\n    dunggeunmo: '둥근모꼴체',\n    hs_bombaram: 'HS봄바람체',\n    yisunshin: '이순신체',\n    goyang: '고양체',\n    flower_road: '꽃길체',\n    uhbeemysen: '어비마이센체',\n    sd_comic_stencil: '산돌 코믹스탠실',\n    sd_childfundkorea: '산돌 초록우산 어린이',\n    sd_cinema_theater: '산돌 씨네마극장',\n    sd_mapssi: '산돌 맵씨',\n    sd_shabang: '산돌 별이샤방샤방',\n    sd_woodcarving: '산돌 목각',\n    sd_yongbi: '산돌 용비어천가',\n    maruburi: '마루 부리',\n    nanumbarunpen: '나눔바른펜',\n    notosans: '본고딕',\n    d2coding: 'D2 Coding',\n};\nLang.Hw = {\n    note: '음표',\n    leftWheel: '왼쪽 바퀴',\n    rightWheel: '오른쪽 바퀴',\n    leftEye: '왼쪽 눈',\n    rightEye: '오른쪽 눈',\n    led: '불빛',\n    led_en: 'LED',\n    body: '몸통',\n    front: '앞쪽',\n    port_en: '',\n    port_ko: '번 포트',\n    sensor: '센서',\n    light: '빛',\n    temp: '온도',\n    switch_: '스위치',\n    right_ko: '오른쪽',\n    right_en: '',\n    left_ko: '왼쪽',\n    left_en: '',\n    up_ko: '위쪽',\n    up_en: '',\n    down_ko: '아래쪽',\n    down_en: '',\n    output: '출력',\n    left: '왼쪽',\n    right: '오른쪽',\n    sub: '서보',\n    motor: '모터',\n    '': '',\n    buzzer: '버저',\n    IR: '적외선',\n    acceleration: '가속',\n    analog: '아날로그',\n    angular_acceleration: '각가속',\n    button: '버튼',\n    humidity: '습도',\n    joystick: '조이스틱',\n    port: '포트',\n    potentiometer: '포텐시오미터',\n    servo: '서보',\n    port_en: '',\n    right_en: '',\n    left_en: '',\n    up_en: '',\n    down_en: '',\n};\nLang.template = {\n    albert_hand_found: '손 찾음?',\n    albert_is_oid_value: ' %1 OID 값이 %2 인가? ',\n    albert_value: '%1',\n    albert_move_forward_for_secs: '앞으로 %1 초 이동하기 %2',\n    albert_move_backward_for_secs: '뒤로 %1 초 이동하기 %2',\n    albert_turn_for_secs: '%1 으로 %2 초 돌기 %3',\n    albert_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n    albert_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n    albert_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n    albert_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n    albert_stop: '정지하기 %1',\n    albert_set_pad_size_to: '말판 크기를 폭 %1 높이 %2 (으)로 정하기 %3',\n    albert_move_to_x_y_on_board: '밑판 x: %1 y: %2 위치로 이동하기 %3',\n    albert_set_orientation_on_board: '말판 %1도 방향으로 바라보기 %2',\n    albert_set_eye_to: '%1 눈을 %2 으로 정하기 %3',\n    albert_clear_eye: '%1 눈 끄기 %2',\n    albert_body_led: '몸통 LED %1 %2',\n    albert_front_led: '앞쪽 LED %1 %2',\n    albert_beep: '삐 소리내기 %1',\n    albert_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n    albert_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n    albert_clear_buzzer: '버저 끄기 %1',\n    albert_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n    albert_rest_for: '%1 박자 쉬기 %2',\n    albert_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n    albert_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n    albert_move_forward: '앞으로 이동하기 %1',\n    albert_move_backward: '뒤로 이동하기 %1',\n    albert_turn_around: '%1 으로 돌기 %2',\n    albert_set_led_to: '%1 %2 으로 정하기 %3',\n    albert_clear_led: '%1 %2',\n    albert_change_wheels_by: '%1 %2 %3',\n    albert_set_wheels_to: '%1 %2 %3',\n    arduino_text: '%1',\n    arduino_get_sensor_number: '%1  ',\n    arduino_get_port_number: '%1  ',\n    arduino_get_digital_toggle: '%1  ',\n    arduino_get_pwm_port_number: '%1  ',\n    arduino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    arduino_ext_get_analog_value: '아날로그 %1 번 센서값',\n    arduino_ext_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    arduino_ext_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n    arduino_ext_toggle_led: '디지털 %1 번 핀 %2 %3',\n    arduino_ext_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    arduino_ext_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    arduino_ext_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    arduino_ext_get_digital: '디지털 %1 번 센서값',\n    blacksmith_get_analog_value: '아날로그 %1 번 핀 센서 값',\n    blacksmith_get_analog_mapping:\n        '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n    blacksmith_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\n    blacksmith_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n    blacksmith_get_digital_toggle: '디지털 %1 번 핀 센서 값',\n    blacksmith_set_digital_toggle: '디지털 %1 번 핀 %2 %3',\n    blacksmith_set_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    blacksmith_set_digital_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    blacksmith_set_digital_buzzer: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    blacksmith_set_digital_lcd: 'LCD화면 %1 줄에 %2 나타내기 %3',\n    blacksmith_set_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n    dplay_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    nemoino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    sensorBoard_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    truetrue_get_accsensor: '가속도센서 %1 의 값',\n    truetrue_get_bottomcolorsensor: '바닥컬러센서 %1 의 값',\n    truetrue_get_frontcolorsensor: '전면컬러센서 %1 의 값',\n    truetrue_get_linesensor: '라인센서 %1 의 값',\n    truetrue_get_proxisensor: '근접센서 %1 의 값',\n    truetrue_set_colorled: '컬러LED Red %1  Green %2 Blue %3 로 설정 %4',\n    truetrue_set_dualmotor: 'DC모터 좌 %1  우 %2 속도로 %3 초 구동 %4',\n    truetrue_set_led_colorsensor: '%1 조명용 LED %2 %3',\n    truetrue_set_led_linesensor: '라인센서 조명용 LED %1 %2',\n    truetrue_set_led_proxi: '%1 조명용 LED %2 %3',\n    truetrue_set_linetracer: '라인트레이싱 모드 %1 %2',\n    truetrue_set_singlemotor: 'DC모터 %1  속도 %2 로 설정 %3',\n    CODEino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    ardublock_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    arduino_get_digital_value: '디지털 %1 번 센서값  ',\n    dplay_get_digital_value: '디지털 %1 번 센서값  ',\n    nemoino_get_digital_value: '디지털 %1 번 센서값  ',\n    sensorBoard_get_digital_value: '디지털 %1 번 센서값  ',\n    CODEino_get_digital_value: '디지털 %1 핀의 값  ',\n    CODEino_set_digital_value: '디지털 %1 핀의 %2 %3',\n    CODEino_set_pwm_value: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    ardublock_get_digital_value: '디지털 %1 번 센서값  ',\n    arduino_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dplay_toggle_led: '디지털 %1 번 핀 %2 %3',\n    nemoino_toggle_led: '디지털 %1 번 핀 %2 %3',\n    sensorBoard_toggle_led: '디지털 %1 번 핀 %2 %3',\n    CODEino_toggle_led: '디지털 %1 번 핀 %2 %3',\n    arduino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dplay_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    nemoino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    sensorBoard_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    CODEino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    ardublock_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    arduino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    dplay_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    nemoino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    sensorBoard_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    CODEino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    CODEino_set_rgb_value: '컬러 LED의 %1 색상을 %2 (으)로 정하기 %3',\n    CODEino_set_rgb_add_value: '컬러 LED의 %1 색상에 %2 만큼 더하기 %3',\n    CODEino_set_rgb_off: '컬러 LED 끄기 %1',\n    CODEino_set__led_by_rgb: '컬러 LED 색상을 빨강 %1 초록 %2 파랑 %3 (으)로 정하기 %4',\n    CODEino_rgb_set_color: '컬러 LED의 색상을 %1 (으)로 정하기 %2',\n    CODEino_led_by_value: '컬러 LED 켜기 %1',\n    ardublock_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    joystick_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n    joystick_get_digital_value: '디지털 %1 번 센서값  ',\n    joystick_toggle_led: '디지털 %1 번 핀 %2 %3',\n    joystick_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    joystick_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    sensorBoard_get_named_sensor_value: '%1  센서값',\n    sensorBoard_is_button_pressed: '%1  버튼을 눌렀는가?',\n    sensorBoard_led: '%1  LED %2   %3',\n    arduino_download_connector: '%1',\n    download_guide: '%1',\n    arduino_lite_guide: '%1',\n    arduino_download_source: '%1',\n    arduino_connected: '%1',\n    arduino_connect: '%1',\n    arduino_reconnect: '%1',\n    CODEino_get_sensor_number: '%1  ',\n    CODEino_get_named_sensor_value: '  %1  센서값 ',\n    CODEino_get_sound_status: '소리센서  %1  ',\n    CODEino_get_light_status: '빛센서  %1  ',\n    CODEino_is_button_pressed: ' 보드의  %1  ',\n    CODEino_get_accelerometer_direction: ' 3축 가속도센서  %1  ',\n    CODEino_get_accelerometer_value: ' 3축 가속도센서  %1 축의 센서값 ',\n    CODEino_get_analog_value: '아날로그 %1 센서의 값',\n    iboard_button: '%1  버튼을 눌렀는가?',\n    iboard_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    iboard_get_analog_value: '아날로그 %1 번 센서값  ',\n    iboard_get_analog_value_map: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    iboard_get_digital: '디지털 %1 번 센서값  ',\n    iboard_led: 'LED %1 번을 %2 %3',\n    iboard_motor: '모터를 %2 으로 동작하기 %3',\n    iboard_pwm_led: 'LED %1 번의 밝기를 %2 (으)로 정하기 %3',\n    iboard_rgb_led: 'RGB LED의 %1 LED %2 %3',\n    iboard_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    iboard_toggle_led: '디지털 %1 번 핀 %2 %3',\n    bitbrick_when_button_pressed: '%1 버튼 %2 눌러졌을 때',\n    bitbrick_when_sensor_get_value: '%1 %2 값 %3 %4 일 때',\n    bitbrick_is_touch_pressed: '버튼 %1 이(가) %2 인가?',\n    bitbrick_is_sensor_value_compare: '%1 값 %2 %3 인가?',\n    bitbrick_sensor_value: '%1 값',\n    bitbrick_convert_scale: '변환 %1 값 %2 ~ %3 에서 %4 ~ %5',\n    bitbrick_turn_on_color_led_by_rgb: '엘이디를 빨강 %1 초록 %2 파랑 %3 %4 (으)로 켜기',\n    bitbrick_turn_on_color_led_by_picker: '엘이디를 %1 (으)로 켜기 %2',\n    bitbrick_turn_on_color_led_by_value: '엘이디를 %1 (으)로 켜기 %2',\n    bitbrick_turn_off_color_led: '엘이디 끄기 %1',\n    bitbrick_buzzer: '버저음 %1 내기 %2',\n    bitbrick_servomotor_angle: '서보모터 %1 각도 %2 %3',\n    bitbrick_dc_direction_speed: '디씨모터 %1 방향 %2 속력 %3 %4',\n    bitbrick_dc_speed: '디씨모터 %1 속도 %2 %3',\n    bitbrick_turn_off_all_motors: '모든 모터 멈추기 %1',\n    start_drawing: '그리기 시작하기 %1',\n    stop_drawing: '그리기 멈추기 %1',\n    start_fill: '채우기 시작하기 %1',\n    stop_fill: '채우기 멈추기 %1',\n    set_color: '그리기 색을 %1 (으)로 정하기 %2',\n    set_random_color: '붓의 색을 무작위로 정하기 %1',\n    set_fill_color: '채우기 색을 %1 (으)로 정하기 %2',\n    change_thickness: '그리기 굵기를 %1 만큼 바꾸기 %2',\n    set_thickness: '그리기 굵기를 %1 (으)로 정하기 %2',\n    change_opacity: '붓의 불투명도를 %1 % 만큼 바꾸기 %2',\n    set_opacity: '붓의 불투명도를 %1 % 로 정하기 %2',\n    brush_erase_all: '모든 붓 지우기 %1',\n    brush_stamp: '도장 찍기 %1',\n    change_brush_transparency: '붓의 투명도를 %1 % 만큼 바꾸기 %2',\n    set_brush_tranparency: '붓의 투명도를 %1 % 로 정하기 %2',\n    number: '%1',\n    angle: '%1',\n    color: '%1',\n    get_x_coordinate: '%1',\n    get_y_coordinate: '%1',\n    get_angle: '%1',\n    get_rotation_direction: '%1  ',\n    distance_something: '%1 %2 %3',\n    coordinate_mouse: '%1 %2 %3',\n    coordinate_object: '%1 %2 %3 %4',\n    calc_basic: '%1 %2 %3',\n    calc_plus: '%1 %2 %3',\n    calc_minus: '%1 %2 %3',\n    calc_times: '%1 %2 %3',\n    calc_divide: '%1 %2 %3',\n    calc_mod: '%1 %2 %3 %4',\n    calc_share: '%1 %2 %3 %4',\n    calc_operation: '%1 %2 %3 %4',\n    calc_rand: '%1 %2 %3 %4 %5',\n    get_date: '%1 %2 %3',\n    get_sound_duration: '%1 %2 %3',\n    get_user_name: '아이디',\n    get_nickname: '닉네임',\n    reset_project_timer: '%1',\n    set_visible_project_timer: '%1 %2 %3 %4',\n    timer_variable: '%1 %2',\n    get_project_timer_value: '%1 %2',\n    char_at: '%1 %2 %3 %4 %5',\n    length_of_string: '%1 %2 %3',\n    substring: '%1 %2 %3 %4 %5 %6 %7',\n    replace_string: '%1 %2 %3 %4 %5 %6 %7',\n    change_string_case: '%2 %1 %4 %3',\n    count_match_string: '%1 %2 %3 %4',\n    index_of_string: '%1 %2 %3 %4 %5',\n    combine_something: '%1 %2 %3 %4 %5',\n    get_sound_volume: '%1 %2',\n    quotient_and_mod: '%1 %2 %3 %4 %5 %6',\n    choose_project_timer_action: '%1 %2 %3 %4',\n    wait_second: '%1 초 기다리기 %2',\n    repeat_basic: '%1 번 반복하기 %2',\n    hidden_loop: '%1 번 반복하기 %2',\n    repeat_inf: '계속 반복하기 %1',\n    stop_repeat: '반복 중단하기 %1',\n    continue_repeat: '이번 반복 건너뛰기 %1',\n    wait_until_true: '%1 이(가) 될 때까지 기다리기 %2',\n    _if: '만일 %1 (이)라면 %2',\n    if_else: '만일 %1 (이)라면 %2 %3 아니면',\n    create_clone: '%1 의 복제본 만들기 %2',\n    delete_clone: '이 복제본 삭제하기 %1',\n    when_clone_start: '%1 복제본이 처음 생성되었을 때',\n    stop_run: '프로그램 끝내기 %1',\n    repeat_while_true: '%1 %2  반복하기 %3',\n    stop_object: '%1 코드 멈추기 %2',\n    restart_project: '처음부터 다시 실행하기 %1',\n    remove_all_clones: '모든 복제본 삭제하기 %1',\n    functionAddButton: '%1',\n    function_field_label: '%1%2',\n    function_field_string: '%1%2',\n    function_field_boolean: '%1%2',\n    get_block_count: '%1 의 블록 수',\n    get_boolean_value: '%1 의 값',\n    change_rgb_to_hex: 'R:%1G:%2B:%3의 HEX 값',\n    change_hex_to_rgb: 'HEX%1의 %2값',\n    function_param_string: '문자/숫자값',\n    function_param_boolean: '판단값',\n    function_create: '함수 정의하기 %1 %2',\n    function_general: '함수 %1',\n    function_value: '함수',\n    expansionBlockAddButton: '%1',\n    aiUtilizeBlockAddButton: '%1',\n    aiUtilizeModelTrainButton: '%1',\n    weather_title: '%1',\n    check_weather: '%1 %2 의 날씨가 %3인가?',\n    check_finedust: '현재 %1 의 미세먼지 등급이 %2인가?',\n    get_weather_data: '%1 %2 의 %3',\n    get_current_weather_data: '현재 %1 의 %2',\n    get_today_temperature: '오늘 %1의 %2시 기온',\n    check_city_weather: '%1 %2 %3의 날씨가 %4인가?',\n    check_city_finedust: '현재 %1 %2 의 미세먼지 등급이 %3인가?',\n    get_city_weather_data: '%1 %2 %3 의 %4',\n    get_current_city_weather_data: '현재 %1 %2 의 %3',\n    get_today_city_temperature: '오늘 %1 %2의 %3시 기온',\n    get_cur_weather: '현재 %1의 날씨',\n    get_cur_wind: '현재 %1의 풍향',\n    get_cur_weather_data: '현재 %1의 %2',\n    check_cur_weather: '현재 %1의 날씨가 %2인가?',\n    check_cur_finddust: '현재 %1의 미세먼지 등급이 %2인가?',\n    get_day_weather: '%1 %2의 날씨',\n    get_day_weather_data: '%1 %2의 %3',\n    check_day_weather: '%1 %2의 날씨가 %3 인가?',\n    get_time_weather: '%1의 %2시 날씨',\n    get_time_weather_data: '%1의 %2시 %3',\n    check_time_weather: '%1의 %2시 날씨가 %3 인가?',\n    translate_title: '%1',\n    get_translated_string: '%1 %2 을(를) %3(으)로 번역한 값',\n    check_language: '%1의 언어',\n    festival_title: '%1',\n    count_festival: '%1 %2 행사의 수',\n    get_festival_info: '%1 %2 행사 %3 번째 항목의 %4',\n    behaviorConductDisaster_title: '%1',\n    count_disaster_behavior: '%1 %2 해야할 행동요령 수',\n    get_disaster_behavior: '자연재난%1 %2 해야할 행동요령 %3 번째 항목',\n    behaviorConductLifeSafety_title: '%1',\n    count_lifeSafety_behavior: '%1 에서 %2 방법의 수',\n    get_lifeSafety_behavior: '%1 에서 %2 방법 %3 번째 항목',\n    tts_title: '%1',\n    audio_title: '%1',\n    video_title: '%1',\n    read_text: '%1 읽어주기 %2',\n    set_tts_property: '%1 목소리를 %2 속도 %3 음높이로 설정하기 %4',\n    read_text_wait_with_block: '%1 읽어주고 기다리기 %2',\n    load_expansion_block: '확장 블록 불러오기',\n    load_ai_utilize_block: '인공지능 블록 불러오기',\n    load_ai_utilize_train_block: '모델 학습',\n    expansion_block_descriptions: '확장 블록은 인터넷이 연결되어 있어야 정상적으로 동작합니다.',\n    aiUtilize_block_descriptions: '불러올 인공지능 블록을 선택해 주세요.',\n    hardware_lite_descriptions:\n        '하드웨어 연결/작동 시 예기치 못한 문제가 발생할 수 있습니다.\\n 하드웨어 웹 연결 중 문제 발생 시 엔트리 고객센터 또는 해당 하드웨어 업체의 고객센터에 연락해 주세요.',\n    weather_title_text: '날씨',\n    translate_title_text: '번역',\n    festival_title_text: '행사',\n    learning_title_image: '%1',\n    learning_title_speech: '%1',\n    learning_title_text: '%1',\n    learning_title_number: '%1',\n    learning_title_regression: '%1',\n    learning_title_logistic_regression: '%1',\n    learning_title_cluster: '%1',\n    learning_title_decisiontree: '%1',\n    learning_title_svm: '%1',\n    insert_data_for_test: '학습한 모델로 분류하기 %1',\n    insert_text_block_for_test: '%1 을(를) 학습한 모델로 분류하기 %2',\n    test_result: '분류 결과',\n    accuracy_of_result: '%1에 대한 신뢰도',\n    is_group: '분류 결과가 %1 인가?',\n    retrain_model: '모델 다시 학습하기 %1',\n    model_is_trained: '모델이 학습되었는가?',\n    set_train_visible: '모델 %1 %2',\n    set_train_chart: '모델 차트 창 %1 %2',\n    set_regression_option: '학습 조건 %1 을 %2 으로 바꾸기 %3',\n    get_regression_predict_1: '%1 %2 의 예측 값',\n    get_regression_predict_2: '%1 %2 %3 %4 의 예측 값',\n    get_regression_predict_3: '%1 %2 %3 %4 %5 %6 의 예측 값',\n    get_regression_predict_4: '%1 %2 %3 %4 %5 %6 %7 %8 의 예측 값',\n    get_regression_predict_5: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 의 예측 값',\n    get_regression_predict_6: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 의 예측 값',\n    get_regression_accuracy: '결정계수',\n    set_logistic_regression_option: '학습 조건 %1 을(를) %2 (으)로 바꾸기 %3',\n    set_logistic_regression_optimizer: '최적화 알고리즘을 %1 (으)로 바꾸기 %2',\n    get_logistic_regression_probability_1: '%1 %2 의 %3 에 대한 확률',\n    get_logistic_regression_probability_2: '%1 %2 %3 %4 의 %5 에 대한 확률',\n    get_logistic_regression_probability_3: '%1 %2 %3 %4 %5 %6 의 %7 에 대한 확률',\n    get_logistic_regression_probability_4: '%1 %2 %3 %4 %5 %6 %7 %8 의 %9 에 대한 확률',\n    get_logistic_regression_probability_5: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 의 %11 에 대한 확률',\n    get_logistic_regression_probability_6:\n        '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 의 %13 에 대한 확률',\n    set_decisiontree_option: '학습 조건 %1 을 %2 으로 바꾸기 %3',\n    set_decisiontree_tree: '학습한 트리 %1 %2',\n    set_svm_option: '학습 조건 %1 을 %2 으로 바꾸기 %3',\n    set_kernel_linear: '커널을 선형으로 바꾸기 %1',\n    set_kernel_option: '커널을 %1 (으)로 바꾸고 %2 를 %3 (으)로 정하기 %4',\n    train_param_kernel_polynomial: '다항식',\n    train_param_kernel_rbf: 'RBF',\n    train_param_degree: '차수',\n    train_param_gamma: '감마',\n    is_result_1: '%1 %2 의 분류 결과가 %3 인가?',\n    is_result_2: '%1 %2 %3 %4 의 분류 결과가 %5 인가?',\n    is_result_3: '%1 %2 %3 %4 %5 %6 의 분류 결과가 %7 인가?',\n    is_result_4: '%1 %2 %3 %4 %5 %6 %7 %8 의 분류 결과가 %9 인가?',\n    is_result_5: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 의 분류 결과가 %11 인가?',\n    is_result_6: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 의 분류 결과가 %13 인가?',\n    get_predict_1: '%1 %2 의 분류 결과',\n    get_predict_2: '%1 %2 %3 %4 의 분류 결과',\n    get_predict_3: '%1 %2 %3 %4 %5 %6 의 분류 결과',\n    get_predict_4: '%1 %2 %3 %4 %5 %6 %7 %8 의 분류 결과',\n    get_predict_5: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 의 분류 결과',\n    get_predict_6: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 의 분류 결과',\n    get_result_info: '모델의 %1',\n    set_cluster_option_k: '군집을 %1 개로 바꾸기 %2',\n    set_cluster_option_centroids: '중심점 기준을 %1 로 바꾸기 %2',\n    get_cluster_centriod_count: '군집 개수',\n    get_cluster_centriod_value: '군집 %1 중심점의 %2 값',\n    get_cluster_centriod_index_1: '%1 %2의 군집',\n    get_cluster_centriod_index_2: '%1 %2 %3 %4의 군집',\n    get_cluster_centriod_index_3: '%1 %2 %3 %4 %5 %6의 군집',\n    get_cluster_centriod_index_4: '%1 %2 %3 %4 %5 %6 %7 %8의 군집',\n    get_cluster_centriod_index_5: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10의 군집',\n    get_cluster_centriod_index_6: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12의 군집',\n    set_number_learning_option_k: '이웃을 %1 개로 바꾸기 %2',\n    get_number_learning_predict_1: '%1 %2 의 분류 결과',\n    get_number_learning_predict_2: '%1 %2 %3 %4의 분류 결과',\n    get_number_learning_predict_3: '%1 %2 %3 %4 %5 %6 의 분류 결과',\n    get_number_learning_predict_4: '%1 %2 %3 %4 %5 %6 %7 %8 의 분류 결과',\n    get_number_learning_predict_5: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 의 분류 결과',\n    get_number_learning_predict_6: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 의 분류 결과',\n    get_number_learning_predict_param_1: '%1 %2 의 %3 에 대한 %4',\n    get_number_learning_predict_param_2: '%1 %2 %3 %4 의 %5 에 대한 %6',\n    get_number_learning_predict_param_3: '%1 %2 %3 %4 %5 %6 의 %7 에 대한 %8',\n    get_number_learning_predict_param_4: '%1 %2 %3 %4 %5 %6 %7 %8 의 %9 에 대한 %10',\n    get_number_learning_predict_param_5: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 의 %11 에 대한 %12',\n    get_number_learning_predict_param_6:\n        '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 의 %13 에 대한 %14',\n    is_number_learning_group_1: '%1 %2 의 분류 결과가 %3 인가?',\n    is_number_learning_group_2: '%1 %2 %3 %4 의 분류 결과가 %5 인가?',\n    is_number_learning_group_3: '%1 %2 %3 %4 %5 %6 의 분류 결과가 %7 인가?',\n    is_number_learning_group_4: '%1 %2 %3 %4 %5 %6 %7 %8 의 분류 결과가 %9 인가?',\n    is_number_learning_group_5: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 의 분류 결과가 %11 인가?',\n    is_number_learning_group_6: '%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 의 분류 결과가 %13 인가?',\n    audio_title_text: '오디오 감지',\n    voice_title_text: '음성 인식',\n    check_microphone: '마이크가 연결되었는가?',\n    get_microphone_volume: '마이크 소리 크기',\n    speech_to_text_title: '%1',\n    speech_to_text_convert: '%1 음성 인식하기 %2',\n    timed_speech_to_text_convert: '%1 초 동안 %2 음성 인식하기 %3',\n    set_visible_speech_to_text: '인식한 음성 %1 %2',\n    speech_to_text_get_value: '음성을 문자로 바꾼 값',\n    video_title_text: '비디오 감지',\n    video_draw_webcam: '비디오 화면 %1 %2',\n    video_check_webcam: '비디오가 연결되었는가?',\n    video_change_cam: '%1 카메라로 바꾸기 %2',\n    video_set_camera_opacity_option: '비디오 투명도 효과를 %1 으로 정하기 %2',\n    video_flip_camera: '비디오 화면 %1 뒤집기 %2',\n    video_toggle_model: '%1 인식 %2 %3',\n    video_toggle_ind: '인식된 %1 %2 %3',\n    video_number_detect: '인식된 %1 의 수',\n    video_object_detected: '사물 중 %1 (이)가 인식되었는가?',\n    video_is_model_loaded: '%1 인식이 되었는가?',\n    video_detected_face_info: '%1 번째 얼굴의 %2',\n    video_motion_value: '%1 에서 감지한 %2 값',\n    video_face_part_coord: '%1 번째 얼굴의 %2 의 %3 좌표',\n    video_body_part_coord: '%1 번째 사람의 %2 의 %3 좌표',\n    behaviorConductDisaster_title_text: '자연재난 국민행동요령',\n    behaviorConductLifeSafety_title_text: '생활안전 국민행동요령',\n    emergencyActionGuidelines_title_text: '국민행동요령',\n    count_disaster_guideline: '자연재난 %1 %2 의 행동요령 수',\n    get_disaster_guideline: '자연재난 %1 %2 의 행동요령 %3 번째 항목',\n    count_social_disaster_guideline: '사회재난 %1 %2 의 행동요령 수',\n    get_social_disaster_guideline: '사회재난 %1 %2 의 행동요령 %3 번째 항목',\n    count_safety_accident_guideline: '생활안전 %1 %2 의 행동요령 수',\n    get_safety_accident_guideline: '생활안전 %1 %2 의 행동요령 %3 번째 항목',\n    tts_title_text: '읽어주기',\n    hamster_hand_found: '손 찾음?',\n    hamster_value: '%1',\n    hamster_move_forward_once: '말판 앞으로 한 칸 이동하기 %1',\n    hamster_turn_once: '말판 %1 으로 한 번 돌기 %2',\n    hamster_move_forward_for_secs: '앞으로 %1 초 이동하기 %2',\n    hamster_move_backward_for_secs: '뒤로 %1 초 이동하기 %2',\n    hamster_turn_for_secs: '%1 으로 %2 초 돌기 %3',\n    hamster_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n    hamster_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n    hamster_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n    hamster_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n    hamster_follow_line_using: '%1 선을 %2 바닥 센서로 따라가기 %3',\n    hamster_follow_line_until: '%1 선을 따라 %2 교차로까지 이동하기 %3',\n    hamster_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n    hamster_stop: '정지하기 %1',\n    hamster_set_led_to: '%1 LED를 %2 으로 정하기 %3',\n    hamster_clear_led: '%1 LED 끄기 %2',\n    hamster_beep: '삐 소리내기 %1',\n    hamster_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n    hamster_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n    hamster_clear_buzzer: '버저 끄기 %1',\n    hamster_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n    hamster_rest_for: '%1 박자 쉬기 %2',\n    hamster_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n    hamster_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n    hamster_set_port_to: '포트 %1 를 %2 으로 정하기 %3',\n    hamster_change_output_by: '출력 %1 를 %2 만큼 바꾸기 %3',\n    hamster_set_output_to: '출력 %1 를 %2 (으)로 정하기 %3',\n    roboid_hamster_beep: '햄스터 %1: 삐 소리내기 %2',\n    roboid_hamster_change_both_wheels_by: '햄스터 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n    roboid_hamster_change_buzzer_by: '햄스터 %1: 버저 음을 %2 만큼 바꾸기 %3',\n    roboid_hamster_change_output_by: '햄스터 %1: 출력 %2 를 %3 만큼 바꾸기 %4',\n    roboid_hamster_change_tempo_by: '햄스터 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n    roboid_hamster_change_wheel_by: '햄스터 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n    roboid_hamster_clear_buzzer: '햄스터 %1: 버저 끄기 %2',\n    roboid_hamster_clear_led: '햄스터 %1: %2 LED 끄기 %3',\n    roboid_hamster_follow_line_until: '햄스터 %1: %2 선을 따라 %3 교차로까지 이동하기 %4',\n    roboid_hamster_follow_line_using: '햄스터 %1: %2 선을 %3 바닥 센서로 따라가기 %4',\n    roboid_hamster_hand_found: '햄스터 %1: 손 찾음?',\n    roboid_hamster_move_backward_for_secs: '햄스터 %1: 뒤로 %2 초 이동하기 %3',\n    roboid_hamster_move_forward_for_secs: '햄스터 %1: 앞으로 %2 초 이동하기 %3',\n    roboid_hamster_move_forward_once: '햄스터 %1: 말판 앞으로 한 칸 이동하기 %2',\n    roboid_hamster_play_note_for: '햄스터 %1: %2 %3 음을 %4 박자 연주하기 %5',\n    roboid_hamster_rest_for: '햄스터 %1: %2 박자 쉬기 %3',\n    roboid_hamster_set_both_wheels_to: '햄스터 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n    roboid_hamster_set_buzzer_to: '햄스터 %1: 버저 음을 %2 (으)로 정하기 %3',\n    roboid_hamster_set_following_speed_to: '햄스터 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n    roboid_hamster_set_led_to: '햄스터 %1: %2 LED를 %3 으로 정하기 %4',\n    roboid_hamster_set_output_to: '햄스터 %1: 출력 %2 를 %3 (으)로 정하기 %4',\n    roboid_hamster_set_port_to: '햄스터 %1: 포트 %2 를 %3 으로 정하기 %4',\n    roboid_hamster_set_tempo_to: '햄스터 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n    roboid_hamster_set_wheel_to: '햄스터 %1: %2 바퀴 %3 (으)로 정하기 %4',\n    roboid_hamster_stop: '햄스터 %1: 정지하기 %2',\n    roboid_hamster_turn_for_secs: '햄스터 %1: %2 으로 %3 초 돌기 %4',\n    roboid_hamster_turn_once: '햄스터 %1: 말판 %2 으로 한 번 돌기 %3',\n    roboid_hamster_value: '햄스터 %1: %2',\n    roboid_turtle_button_state: '거북이 %1: 버튼을 %2 ?',\n    roboid_turtle_change_buzzer_by: '거북이 %1: 버저 음을 %2 만큼 바꾸기 %3',\n    roboid_turtle_change_head_led_by_rgb: '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n    roboid_turtle_change_tempo_by: '거북이 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n    roboid_turtle_change_wheel_by: '거북이 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n    roboid_turtle_change_wheels_by_left_right:\n        '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n    roboid_turtle_clear_head_led: '거북이 %1: 머리 LED 끄기 %2',\n    roboid_turtle_clear_sound: '거북이 %1: 소리 끄기 %2',\n    roboid_turtle_cross_intersection: '거북이 %1: 검은색 교차로 건너가기 %2',\n    roboid_turtle_follow_line: '거북이 %1: %2 선을 따라가기 %3',\n    roboid_turtle_follow_line_until: '거북이 %1: 검은색 선을 따라 %2 까지 이동하기 %3',\n    roboid_turtle_follow_line_until_black: '거북이 %1: %2 선을 따라 검은색까지 이동하기 %3',\n    roboid_turtle_is_color_pattern: '거북이 %1: 색깔 패턴이 %2 %3 인가?',\n    roboid_turtle_move_backward_unit: '거북이 %1: 뒤로 %2 %3 이동하기 %4',\n    roboid_turtle_move_forward_unit: '거북이 %1: 앞으로 %2 %3 이동하기 %4',\n    roboid_turtle_pivot_around_wheel_unit_in_direction:\n        '거북이 %1: %2 바퀴 중심으로 %3 %4 %5 방향으로 돌기 %6',\n    roboid_turtle_play_note: '거북이 %1: %2 %3 음을 연주하기 %4',\n    roboid_turtle_play_note_for_beats: '거북이 %1: %2 %3 음을 %4 박자 연주하기 %5',\n    roboid_turtle_play_sound_times: '거북이 %1: %2 소리 %3 번 재생하기 %4',\n    roboid_turtle_play_sound_times_until_done: '거북이 %1: %2 소리 %3 번 재생하고 기다리기 %4',\n    roboid_turtle_rest_for_beats: '거북이 %1: %2 박자 쉬기 %3',\n    roboid_turtle_set_buzzer_to: '거북이 %1: 버저 음을 %2 (으)로 정하기 %3',\n    roboid_turtle_set_following_speed_to: '거북이 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n    roboid_turtle_set_head_led_to: '거북이 %1: 머리 LED를 %2 으로 정하기 %3',\n    roboid_turtle_set_head_led_to_rgb: '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n    roboid_turtle_set_tempo_to: '거북이 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n    roboid_turtle_set_wheel_to: '거북이 %1: %2 바퀴 %3 (으)로 정하기 %4',\n    roboid_turtle_set_wheels_to_left_right:\n        '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n    roboid_turtle_stop: '거북이 %1: 정지하기 %2',\n    roboid_turtle_touching_color: '거북이 %1: %2 에 닿았는가?',\n    roboid_turtle_turn_at_intersection: '거북이 %1: 검은색 교차로에서 %2 으로 돌기 %3',\n    roboid_turtle_turn_unit_in_place: '거북이 %1: %2 으로 %3 %4 제자리 돌기 %5',\n    roboid_turtle_turn_unit_with_radius_in_direction:\n        '거북이 %1: %2 으로 %3 %4 반지름 %5 cm를 %6 방향으로 돌기 %7',\n    roboid_turtle_value: '거북이 %1: %2',\n    turtle_button_state: '버튼을 %1 ?',\n    turtle_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n    turtle_change_head_led_by_rgb: '머리 LED를 R: %1 G: %2 B: %3 만큼 바꾸기 %4',\n    turtle_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n    turtle_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n    turtle_change_wheels_by_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n    turtle_clear_head_led: '머리 LED 끄기 %1',\n    turtle_clear_sound: '소리 끄기 %1',\n    turtle_cross_intersection: '검은색 교차로 건너가기 %1',\n    turtle_follow_line: '%1 선을 따라가기 %2',\n    turtle_follow_line_until: '검은색 선을 따라 %1 까지 이동하기 %2',\n    turtle_follow_line_until_black: '%1 선을 따라 검은색까지 이동하기 %2',\n    turtle_is_color_pattern: '색깔 패턴이 %1 %2 인가?',\n    turtle_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n    turtle_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n    turtle_pivot_around_wheel_unit_in_direction: '%1 바퀴 중심으로 %2 %3 %4 방향으로 돌기 %5',\n    turtle_play_note: '%1 %2 음을 연주하기 %3',\n    turtle_play_note_for_beats: '%1 %2 음을 %3 박자 연주하기 %4',\n    turtle_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n    turtle_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n    turtle_rest_for_beats: '%1 박자 쉬기 %2',\n    turtle_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n    turtle_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n    turtle_set_head_led_to: '머리 LED를 %1 으로 정하기 %2',\n    turtle_set_head_led_to_rgb: '머리 LED를 R: %1 G: %2 B: %3 (으)로 정하기 %4',\n    turtle_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n    turtle_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n    turtle_set_wheels_to_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n    turtle_stop: '정지하기 %1',\n    turtle_touching_color: '%1 에 닿았는가?',\n    turtle_turn_at_intersection: '검은색 교차로에서 %1 으로 돌기 %2',\n    turtle_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n    turtle_turn_unit_with_radius_in_direction: '%1 으로 %2 %3 반지름 %4 cm를 %5 방향으로 돌기 %6',\n    turtle_value: '%1',\n    is_clicked: '%1',\n    is_object_clicked: '%1',\n    is_press_some_key: '%1 %2',\n    reach_something: '%1 %2 %3',\n    is_type: '%1 %2 %3 %4',\n    boolean_comparison: '%1 %2 %3',\n    boolean_equal: '%1 %2 %3',\n    boolean_bigger: '%1 %2 %3',\n    boolean_smaller: '%1 %2 %3',\n    boolean_and_or: '%1 %2 %3',\n    boolean_and: '%1 %2 %3',\n    boolean_or: '%1 %2 %3',\n    boolean_not: '%1 %2 %3',\n    is_boost_mode: '%1',\n    is_current_device_type: '%1 에서 실행하는가?',\n    is_touch_supported: '화면을 터치할 수 있는가?',\n    true_or_false: '%1',\n    True: '%1  ',\n    False: '%1  ',\n    boolean_basic_operator: '%1 %2 %3',\n    show: '모양 보이기 %1',\n    hide: '모양 숨기기 %1',\n    dialog_time: '%1 을(를) %2 초 동안 %3 %4',\n    dialog: '%1 을(를) %2 %3',\n    remove_dialog: '말풍선 지우기 %1',\n    change_to_nth_shape: '%1 모양으로 바꾸기 %2',\n    change_to_next_shape: '%1 모양으로 바꾸기 %2',\n    set_effect_volume: '%1 효과를 %2 만큼 주기 %3',\n    set_effect: '%1 효과를 %2 (으)로 정하기 %3',\n    erase_all_effects: '효과 모두 지우기 %1',\n    change_scale_percent: '크기를 %1 만큼 바꾸기 %2',\n    set_scale_percent: '크기를 %1  (으)로 정하기 %2',\n    change_scale_size: '크기를 %1 만큼 바꾸기 %2',\n    set_scale_size: '크기를 %1 (으)로 정하기 %2',\n    stretch_scale_size: '%1 를 %2 만큼 늘이기 %3',\n    reset_scale_size: '원래 크기로 되돌리기 %1',\n    flip_y: '좌우 모양 뒤집기 %1',\n    flip_x: '상하 모양 뒤집기 %1',\n    set_object_order: '%1 번째로 올라오기 %2',\n    get_pictures: '%1  ',\n    change_to_some_shape: '%1 모양으로 바꾸기 %2',\n    add_effect_amount: '%1 효과를 %2 만큼 주기 %3',\n    change_effect_amount: '%1 효과를 %2 (으)로 정하기 %3',\n    set_effect_amount: '%1 효과를 %2 만큼 주기 %3',\n    set_entity_effect: '%1 효과를 %2 (으)로 정하기 %3',\n    change_object_index: '%1 보내기 %2',\n    move_direction: '이동 방향으로 %1 만큼 움직이기 %2',\n    move_x: 'x 좌표를 %1 만큼 바꾸기 %2',\n    move_y: 'y 좌표를 %1 만큼 바꾸기 %2',\n    locate_xy_time: '%1 초 동안 x: %2 y: %3 위치로 이동하기 %4',\n    rotate_by_angle: '오브젝트를 %1 만큼 회전하기 %2',\n    rotate_by_angle_dropdown: '%1 만큼 회전하기 %2',\n    see_angle: '이동 방향을 %1 (으)로 정하기 %2',\n    see_direction: '%1 쪽 보기 %2',\n    locate_xy: 'x: %1 y: %2 위치로 이동하기 %3',\n    locate_x: 'x: %1 위치로 이동하기 %2',\n    locate_y: 'y: %1 위치로 이동하기 %2',\n    locate: '%1 위치로 이동하기 %2',\n    move_xy_time: '%1 초 동안 x: %2 y: %3 만큼 움직이기 %4',\n    rotate_by_angle_time: '오브젝트를 %1 초 동안 %2 만큼 회전하기 %3',\n    bounce_wall: '화면 끝에 닿으면 튕기기 %1',\n    flip_arrow_horizontal: '화살표 방향 좌우 뒤집기 %1',\n    flip_arrow_vertical: '화살표 방향 상하 뒤집기 %1',\n    see_angle_object: '%1 쪽 바라보기 %2',\n    see_angle_direction: '오브젝트를 %1 (으)로 정하기 %2',\n    rotate_direction: '이동 방향을 %1 만큼 회전하기 %2',\n    locate_object_time: '%1 초 동안 %2 위치로 이동하기 %3',\n    rotate_absolute: '방향을 %1 (으)로 정하기 %2',\n    rotate_relative: '방향을 %1 만큼 회전하기 %2',\n    direction_absolute: '이동 방향을 %1 (으)로 정하기 %2',\n    direction_relative: '이동 방향을 %1 만큼 회전하기 %2',\n    move_to_angle: '%1 방향으로 %2 만큼 움직이기 %3',\n    rotate_by_time: '%1 초 동안 방향을 %2 만큼 회전하기 %3',\n    direction_relative_duration: '%1 초 동안 이동 방향 %2 만큼 회전하기 %3',\n    neobot_sensor_value: '%1  값',\n    neobot_turn_left: '왼쪽모터를 %1 %2 회전 %3',\n    neobot_stop_left: '왼쪽모터 정지 %1',\n    neobot_turn_right: '오른쪽모터를 %1 %2 회전 %3',\n    neobot_stop_right: '오른쪽모터 정지 %1',\n    neobot_run_motor: '%1 모터를  %2 초간 %3 %4 %5',\n    neobot_servo_1: 'SERVO1에 연결된 서보모터를 %1 속도로 %2 로 이동 %3',\n    neobot_servo_2: 'SERVO2에 연결된 서보모터를 %1 속도로 %2 로 이동 %3',\n    neobot_play_note_for: '멜로디 %1 을(를) %2 옥타브로 %3 길이만큼 소리내기 %4',\n    neobot_set_sensor_value: '%1 번 포트의 값을 %2 %3',\n    robotis_openCM70_cm_custom_value: '직접입력 주소 ( %1 ) %2 값',\n    robotis_openCM70_sensor_value: '제어기 %1 값',\n    robotis_openCM70_aux_sensor_value: '%1   %2 값',\n    robotis_openCM70_cm_buzzer_index: '제어기 음계값 %1 을(를) %2 초 동안 연주 %3',\n    robotis_openCM70_cm_buzzer_melody: '제어기 멜로디 %1 번 연주 %2',\n    robotis_openCM70_cm_sound_detected_clear: '최종소리감지횟수 초기화 %1',\n    robotis_openCM70_cm_led: '제어기 %1 LED %2 %3',\n    robotis_openCM70_cm_motion: '모션 %1 번 실행 %2',\n    robotis_openCM70_cm_autodrive_motor: '자율주행 자동차 %1 모터를 %2 에 연결 %3',\n    robotis_openCM70_cm_autodrive_ir: '자율주행 자동차 %1 적외선센서를 %2 에 연결 %3',\n    robotis_openCM70_cm_autodrive_speed: '차로를 따라 %1의 속도로 자율주행 %2',\n    robotis_openCM70_aux_car_move: '로봇을 %1% 의 속도로 %2 %3',\n    robotis_openCM70_aux_motor_speed: '%1 감속모터 속도를 %2 , 출력값을 %3%로 정하기 %4',\n    robotis_openCM70_aux_servo_mode: '%1 서보모터 모드를 %2 (으)로 정하기 %3',\n    robotis_openCM70_aux_servo_speed: '%1 서보모터 속도를 %2 , 출력값을 %3%로 정하기 %4',\n    robotis_openCM70_aux_servo_position: '%1 서보모터 위치를 %2도로 정하기 %3',\n    robotis_openCM70_aux_led_module: '%1 LED 모듈을 %2 (으)로 정하기 %3',\n    robotis_openCM70_cm_poweroff_timer: '제어기 자동꺼짐 타이머 %1 %2',\n    robotis_openCM70_aux_custom: '%1 사용자 장치를 %2 (으)로 정하기 %3',\n    robotis_openCM70_cm_custom: '직접입력 주소 ( %1 ) (을)를 %2 (으)로 정하기 %3',\n    robotis_carCont_sensor_value: '%1   값',\n    robotis_carCont_cm_led: '4번 LED %1 ,  1번 LED %2 %3',\n    robotis_carCont_cm_sound_detected_clear: '최종소리감지횟수 초기화 %1',\n    robotis_carCont_aux_motor_speed: '%1 감속모터 속도를 %2 , 출력값을 %3 (으)로 정하기 %4',\n    robotis_carCont_cm_calibration: '%1 적외선 센서 캘리브레이션 값을 %2 (으)로 정하기 %3',\n    roduino_get_analog_number: '%1  ',\n    roduino_get_port_number: '%1  ',\n    roduino_get_analog_value: '아날로그 %1 번 센서값  ',\n    roduino_get_digital_value: '디지털 %1 번 센서값  ',\n    roduino_set_digital: '디지털 %1 번 핀 %2 %3',\n    roduino_motor: '%1 %2 %3',\n    roduino_set_color_pin: '컬러센서 R : %1, G : %2, B : %3 %4',\n    roduino_get_color: '컬러센서 %1 감지',\n    roduino_on_block: ' On ',\n    roduino_off_block: ' Off ',\n    schoolkit_get_in_port_number: '%1  ',\n    schoolkit_get_out_port_number: '%1  ',\n    schoolkit_get_servo_port_number: '%1  ',\n    schoolkit_get_input_value: '디지털 %1 번 센서값  ',\n    schoolkit_set_output: '디지털 %1 번 핀 %2 %3',\n    schoolkit_motor: '%1 속도 %2(으)로 %3 %4',\n    schoolkit_set_servo_value: '서보모터 %1 번 핀 %2˚ %3',\n    schoolkit_on_block: ' On ',\n    schoolkit_off_block: ' Off ',\n    when_scene_start: '%1 장면이 시작되었을 때',\n    start_scene: '%1 시작하기 %2',\n    start_neighbor_scene: '%1 장면 시작하기 %2',\n    sound_something: '소리 %1 재생하기 %2',\n    sound_something_second: '소리 %1 %2 초 재생하기 %3',\n    sound_something_wait: '소리  %1 재생하고 기다리기 %2',\n    sound_something_second_wait: '소리 %1 %2 초 재생하고 기다리기 %3',\n    sound_volume_change: '소리 크기를 %1 만큼 바꾸기 %2',\n    sound_volume_set: '소리 크기를 %1 % 로 정하기 %2',\n    get_sound_speed: '소리 빠르기',\n    sound_speed_change: '소리 빠르기를 %1 만큼 바꾸기 %2',\n    sound_speed_set: '소리 빠르기를 %1 배로 정하기 %2',\n    sound_silent_all: '%1 소리 멈추기 %2',\n    play_bgm: '%1 을(를) 배경음악으로 재생하기 %2',\n    stop_bgm: '배경음악 멈추기 %1',\n    get_sounds: '%1  ',\n    sound_something_with_block: '소리 %1 재생하기 %2',\n    sound_something_second_with_block: '소리 %1 %2 초 재생하기 %3',\n    sound_something_wait_with_block: '소리 %1 재생하고 기다리기 %2',\n    sound_something_second_wait_with_block: '소리 %1 %2 초 재생하고 기다리기 %3',\n    sound_from_to: '소리 %1 %2 초 부터 %3 초까지 재생하기 %4',\n    sound_from_to_and_wait: '소리 %1 %2 초 부터 %3 초까지 재생하고 기다리기 %4',\n    messageAddButton: '%1',\n    when_run_button_click: '%1 시작하기 버튼을 클릭했을 때',\n    press_some_key: '%1 %2 키를 눌렀을 때 %3',\n    when_some_key_pressed: '%1 %2 키를 눌렀을 때',\n    mouse_clicked: '%1 마우스를 클릭했을 때',\n    mouse_click_cancled: '%1 마우스 클릭을 해제했을 때',\n    when_object_click: '%1 오브젝트를 클릭했을 때',\n    when_object_click_canceled: '%1 오브젝트 클릭을 해제했을 때',\n    when_some_key_click: '%1 키를 눌렀을 때',\n    when_message_cast: '%1 %2 신호를 받았을 때',\n    message_cast: '%1 신호 보내기 %2',\n    message_cast_wait: '%1 신호 보내고 기다리기 %2',\n    text: '%1',\n    text_read: '글상자 %1의 내용',\n    text_write: '%1 (이)라고 글쓰기 %2',\n    text_append: '%1 을(를) 뒤에 추가하기 %2',\n    text_prepend: '%1 을(를) 앞에 추가하기 %2',\n    text_change_effect: '텍스트에 %1 효과 %2 %3',\n    text_change_font: '글씨체를 %1 (으)로 바꾸기 %2',\n    text_change_font_color: '글씨색을 %1 (으)로 바꾸기 %2',\n    text_change_bg_color: '배경색을 %1 (으)로 바꾸기 %2',\n    text_flush: '텍스트 모두 지우기 %1',\n    analizyDataAddButton: '%1',\n    append_row_to_table: '테이블 %1에 %2 추가하기 %3',\n    insert_row_to_table: '테이블 %1 %2 번째에 %3 추가하기 %4',\n    delete_row_from_table: '테이블 %1 %2번째 %3 삭제하기 %4',\n    set_value_from_table: '테이블 %1 %2번째 행의 %3을(를) %4(으)로 바꾸기 %5',\n    save_current_table: '테이블 %1 을(를) 현재 상태로 남기기 %2',\n    get_table_count: '테이블 %1의 %2 개수',\n    get_value_from_table: '테이블 %1 %2번째 행의 %3 값',\n    get_value_from_last_row: '테이블 %1 마지막 행의 %2 값',\n    calc_values_from_table: '테이블 %1 %2의 %3',\n    open_table: '테이블 %1 창 열기 %2',\n    open_table_wait: '테이블 %1 창을 %2 초 동안 열기 %3',\n    open_table_chart: '테이블 %1 의 %2 차트 창 열기 %3',\n    close_table_chart: '테이블 차트 창 닫기 %1',\n    get_coefficient: '테이블 %1 %2 과(와) %3 의 상관계수',\n    set_value_from_cell: '테이블 %1 의 %2 셀 값을 %3 (으)로 바꾸기 %4',\n    get_value_from_cell: '테이블 %1 의 %2 셀 값',\n    get_value_v_lookup: '테이블 %1 의 %2 이(가) %3 인 행의 %4 값',\n    variableAddButton: '%1',\n    listAddButton: '%1',\n    change_variable: '%1 에 %2 만큼 더하기 %3',\n    set_variable: '%1 를 %2 (으)로 정하기 %3',\n    show_variable: '변수 %1 보이기 %2',\n    hide_variable: '변수 %1 숨기기 %2',\n    get_variable: '%1 %2',\n    ask_and_wait: '%1 을(를) 묻고 대답 기다리기 %2',\n    get_canvas_input_value: '%1  ',\n    add_value_to_list: '%1 항목을 %2 에 추가하기 %3',\n    remove_value_from_list: '%1 번째 항목을 %2 에서 삭제하기 %3',\n    insert_value_to_list: '%1 을(를) %2 의 %3 번째에 넣기 %4',\n    change_value_list_index: '%1    %2 번째 항목을 %3 (으)로 바꾸기 %4',\n    value_of_index_from_list: '%1 %2 %3 %4 %5',\n    length_of_list: '%1 %2 %3',\n    show_list: '리스트 %1 보이기 %2',\n    hide_list: '리스트 %1 숨기기 %2',\n    options_for_list: '%1  ',\n    set_visible_answer: '대답 %1 %2',\n    is_included_in_list: '%1 %2 %3 %4 %5',\n    xbot_digitalInput: '%1',\n    xbot_analogValue: '%1',\n    xbot_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n    xbot_analogOutput: '아날로그 %1 %2 %3',\n    xbot_servo: '서보 모터 %1 , 각도 %2 %3',\n    xbot_oneWheel: '바퀴(DC) 모터 %1 , 속도 %2 %3',\n    xbot_twoWheel: '바퀴(DC) 모터 오른쪽(2) 속도: %1 왼쪽(1) 속도: %2 %3',\n    xbot_rgb: 'RGB LED 켜기 R 값 %1 G 값 %2 B 값 %3 %4',\n    xbot_rgb_picker: 'RGB LED 색 %1 로 정하기 %2',\n    xbot_buzzer: '%1   %2 음을 %3 초 연주하기 %4',\n    xbot_lcd: 'LCD %1 번째 줄 ,  출력 값 %2 %3',\n    run: '',\n    mutant: 'test mutant block',\n    jr_start: '%1',\n    jr_repeat: '%1 %2 반복',\n    jr_item: '꽃 모으기 %1',\n    cparty_jr_item: '연필 줍기 %1',\n    jr_north: '  위쪽 %1',\n    jr_east: '오른쪽 %1',\n    jr_south: '  아래쪽 %1',\n    jr_west: '  왼쪽 %1',\n    jr_start_basic: '%1 %2',\n    jr_go_straight: '앞으로 가기%1',\n    jr_turn_left: '왼쪽으로 돌기%1',\n    jr_turn_right: '오른쪽으로 돌기%1',\n    jr_go_slow: '천천히 가기 %1',\n    jr_repeat_until_dest: '%1 만날 때까지 반복하기 %2',\n    jr_if_construction: '만약 %1 앞에 있다면 %2',\n    jr_if_speed: '만약 %1 앞에 있다면 %2',\n    maze_step_start: '%1 시작하기를 클릭했을 때',\n    maze_step_jump: '뛰어넘기%1',\n    maze_step_jump2: '뛰어넘기%1',\n    maze_step_jump_pinkbean: '뛰어넘기%1',\n    maze_step_for: '%1 번 반복하기%2',\n    test: '%1 this is test block %2',\n    maze_repeat_until_1: '%1 만날 때 까지 반복%2',\n    maze_repeat_until_2: '모든 %1 만날 때 까지 반복%2',\n    maze_step_if_1: '만약 앞에 %1 있다면%2',\n    maze_step_if_2: '만약 앞에 %1 있다면%2',\n    maze_call_function: '약속 불러오기%1',\n    maze_define_function: '약속하기%1',\n    maze_step_if_3: '만약 앞에 %1 있다면%2',\n    maze_step_if_4: '만약 앞에 %1 있다면%2',\n    maze_step_move_step: '앞으로 한 칸 이동%1',\n    maze_step_rotate_left: '왼쪽으로 회전%1',\n    maze_step_rotate_right: '오른쪽으로 회전%1',\n    maze_step_forward: '앞으로 가기%1',\n    maze_turn_right: '오른쪽 바라보기%1',\n    maze_turn_left: '왼쪽 바라보기%1',\n    maze_ladder_climb: '사다리 타기%1',\n    maze_attack_lupin: '%1공격하기%2',\n    maze_attack_both_side: '양옆 공격하기%1',\n    maze_attack_pepe: '%1 공격하기%2',\n    maze_attack_yeti: '%1 공격하기%2',\n    maze_attack_mushroom: '%1 공격하기%2',\n    maze_attack_peti: '%1 공격하기%2',\n    maze_eat_item: '음식 먹기%1',\n    maze_step_if_mushroom: '만약 한 칸 앞에 %1가 있다면 %2',\n    maze_step_if_yeti: '만약 앞에 %1가 있다면 %2 %3 아니면',\n    maze_step_if_left_monster: '만약 왼쪽 공격범위에 몬스터가 있다면 %1 %2 아니면',\n    maze_step_if_right_monster: '만약 오른쪽 공격범위에 몬스터가 있다면 %1 %2 아니면',\n    maze_step_if_lupin: '만약 두 칸 앞에 %1가 있다면 %2',\n    maze_step_if_else_road: '만약 한 칸 앞에 길이 있다면 %1 %2아니면',\n    maze_step_if_else_mushroom: '만약 한 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_step_if_else_lupin: '만약 두 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_step_if_else_ladder: '만약 한 칸 앞에 %1가 있다면 %2 %3아니면',\n    maze_rotate_left: '왼쪽으로 돌기%1',\n    maze_rotate_right: '오른쪽으로 돌기%1',\n    maze_moon_kick: '발차기하기%1',\n    maze_repeat_until_3: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_4: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_5: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_6: '%1에 도착할 때까지 반복하기%2',\n    maze_repeat_until_7: '목적지에 도착할 때까지 반복하기%2',\n    maze_repeat_until_goal: '목적지에 도착할 때까지 반복하기%1',\n    maze_repeat_until_beat_monster: '모든 몬스터를 혼내줄 때까지 반복하기%1',\n    maze_radar_check: '%1에 %2이 있다',\n    maze_cony_flower_throw: '부채질하기%1',\n    maze_brown_punch: '주먹 날리기%1',\n    maze_iron_switch: '장애물 조종하기%1',\n    maze_james_heart: '케이크 던지기%1',\n    maze_step_if_5: '만약 앞에 길이 없다면%2',\n    maze_step_if_6: '만약 앞에 %1이 없다면%2',\n    maze_step_if_7: '만약 앞에 %1이 있다면%2',\n    maze_step_if_8: '만약 %1이라면%2',\n    maze_step_if_else: '만약 %1이라면%2 %3 아니면',\n    test_wrapper: '%1 this is test block %2',\n    basic_button: '%1',\n    ai_move_right: '앞으로 가기 %1',\n    ai_move_up: '위쪽으로 가기 %1',\n    ai_move_down: '아래쪽으로 가기 %1',\n    ai_repeat_until_reach: '목적지에 도달 할 때까지 반복하기 %1',\n    ai_if_else_1: '만약 앞에 %1가 있다면 %2 %3 아니면',\n    ai_boolean_distance: '%1 레이더 %2 %3',\n    ai_distance_value: '%1 레이더',\n    ai_boolean_object: '%1 물체는 %2 인가?',\n    ai_use_item: '아이템 사용 %1',\n    ai_boolean_and: '%1 %2 %3',\n    ai_True: '%1',\n    ai_if_else: '만일 %1 (이)라면 %2 %3 아니면',\n    smartBoard_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값',\n    smartBoard_get_named_sensor_value: '%1 센서값',\n    smartBoard_is_button_pressed: '%1 버튼을 눌렀는가?',\n    smartBoard_set_dc_motor_direction: '%1 DC 모터를 %2 방향으로 정하기 %3',\n    smartBoard_set_dc_motor_speed: '%1 DC모터를 %2 %3',\n    smartBoard_set_dc_motor_pwm: '%1 DC모터를 %2 속도로 돌리기 %3',\n    smartBoard_set_servo_speed: '%1 번 서보모터의 속도를 %2 %3',\n    smartBoard_set_servo_angle: '%1 번 서보모터를 %2 도 로 움직이기 %3',\n    smartBoard_set_number_eight_pin: '%1 포트를 %2 %3',\n    smartBoard_set_gs1_pwm: 'GS1 포트의 PWM을 %1 로 정하기 %2',\n    robotori_digitalInput: '%1',\n    robotori_analogInput: '%1',\n    robotori_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n    robotori_analogOutput: '아날로그 %1 %2 %3',\n    robotori_servo: '서보모터 각도 %1 %2',\n    robotori_dc_direction: 'DC모터 %1 회전 %2 %3',\n    dadublock_get_analog_value: '아날로그 %1 번 센서값',\n    dadublock_get_analog_value_map:\n        '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값',\n    dadublock_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n    dadublock_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dadublock_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dadublock_set_tone: '디지털 %1 번 핀을 %2 음으로 %3 옥타브로 %4 만큼 연주하기 %5',\n    dadublock_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n    coconut_stop_motor: '모터 정지 %1',\n    coconut_move_motor: '%1 움직이기 %2',\n    coconut_turn_motor: '%1 으로 돌기 %2',\n    coconut_move_for_secs: '%1 %2 초동안 움직이기 %3',\n    coconut_turn_for_secs: '%1 으로 %2 초동안 돌기 %3',\n    coconut_turn_to_led: '%1 으로 회전하는 동안 %2LED 켜기 %3',\n    coconut_move_outmotor: '외부모터 %1(으로) 움직이기 속도 %2 %3',\n    coconut_set_led_to: '%1 LED를 %2 으로 켜기 %3',\n    coconut_clear_led: '%1 LED 끄기 %2',\n    coconut_set_led_clear: '%1 LED %2 끄기 %3',\n    coconut_set_led_time: '%1 LED %2 으로 %3 초동안 켜기 %4',\n    coconut_beep: '버저 켜기 %1',\n    coconut_buzzer_time: '버저음을 %1 초 동안 소리내기 %2',\n    coconut_buzzer_set_hz: '버즈음 %1 Hz를 %2초 동안 소리내기 %3',\n    coconut_clear_buzzer: '버저 끄기 %1',\n    coconut_play_buzzer: '%1 %2 %3 음을 %4 박자로 연주하기 %5',\n    coconut_rest_buzzer: '%1 동안 쉬기 %2',\n    coconut_play_buzzer_led: '%1 %2 %3 음을 %4 박자로 연주하는 동안 %5 LED %6 켜기 %7',\n    coconut_play_midi: '%1 연주하기 %2',\n    coconut_floor_sensor: '%1 바닥센서',\n    coconut_floor_sensing: '%1 바닥센서 %2',\n    coconut_following_line: '선 따라가기 %1',\n    coconut_front_sensor: '%1 전방센서',\n    coconut_front_sensing: '%1 전방센서 %2',\n    coconut_obstruct_sensing: '장애물 감지',\n    coconut_avoid_mode: '어보이드 모드 %1',\n    coconut_dotmatrix_set: '도트매트릭스 %1 ( %2줄, %3칸 ) %4',\n    coconut_dotmatrix_on: '도트매트릭스 모두 켜기 %1',\n    coconut_dotmatrix_off: '도트매트릭스 모두 끄기 %1',\n    coconut_dotmatrix_num: '도트매트릭스 숫자 %1표시 %2',\n    coconut_dotmatrix_small_eng: '도트매트릭스 소문자 %1표시 %2',\n    coconut_dotmatrix_big_eng: '도트매트릭스 대문자 %1표시 %2',\n    coconut_dotmatrix_kor: '도트매트릭스 한글 %1표시 %2',\n    coconut_light_sensor: '밝기',\n    coconut_tem_sensor: '온도',\n    coconut_ac_sensor: '%1 가속도',\n    coconut_outled_sensor: '외부 LED 설정 %1 %2 초동안 켜기 %3',\n    coconut_outspk_sensor: '외부 스피커 설정 %1 %2Hz로 %3초 동안 소리내기 %4',\n    coconut_outspk_sensor_off: '외부 스피커 %1 끄기 %2',\n    coconut_outinfrared_sensor: '외부 적외선센서 %1',\n    coconut_outcds_sensor: '외부 빛센서(Cds) %1',\n    coconut_servomotor_angle: '서보모터 연결 %1 각도 %2 %3',\n    chocopi_control_button: '%1 컨트롤 %2번을 누름',\n    chocopi_control_event: '%1 %2 컨트롤 %3을 %4',\n    chocopi_control_joystick: '%1 컨트롤 %2의 값',\n    chocopi_dc_motor: '%1 DC모터 %2 %3% 세기 %4 방향 %5',\n    chocopi_led: '%1 LED %2 RGB(%3 %4 %5) %6',\n    chocopi_motion_photogate_event: '%1 %2 포토게이트 %3번을 %4',\n    chocopi_motion_photogate_status: '%1 포토게이트 %2번이 막힘',\n    chocopi_motion_photogate_time: '%1 포토게이트%2번을 %3',\n    chocopi_motion_value: '%1 모션 %2의 값',\n    chocopi_sensor: '%1 센서 %2',\n    chocopi_servo_motor: '%1 서보모터 %2번 %3도 %4',\n    chocopi_touch_event: '%1 %2 터치 %3번을 %4',\n    chocopi_touch_status: '%1 터치 %2번을 만짐',\n    chocopi_touch_value: '%1 터치 %2번의 값',\n    dadublock_car_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    dadublock_car_get_analog_value: '아날로그 %1 번 센서값',\n    dadublock_car_get_analog_value_map:\n        '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n    dadublock_car_get_digital: '디지털 %1 번 센서값',\n    dadublock_car_get_irsensor: '적외선 %1 번 센서값',\n    dadublock_car_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n    dadublock_car_motor: '모터 %1 번을 %2 (으)로 %3 %의 속도로 움직이기 %4',\n    dadublock_car_motor_stop: '모터 %1 번 멈추기 %2',\n    dadublock_car_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n    dadublock_car_set_tone: '디지털 %1 번 핀 을 %2 음으로 %3의 옥타브로 %4 만큼 연주하기 %5',\n    dadublock_car_toggle_led: '디지털 %1 번 핀 %2 %3',\n    dadublock_get_digital: '디지털 %1 번 센서값',\n    ev3_get_sensor_value: '%1 의 값',\n    ev3_touch_sensor: '%1 의 터치센서가 작동되었는가?',\n    ev3_color_sensor: '%1 의  %2 값',\n    ev3_motor_power: '%1 의 값을 %2 으로 출력 %3',\n    ev3_motor_power_on_time: '%1 의 값을 %2 초 동안 %3 으로 출력 %4',\n    ev3_motor_degrees: '%1 의 값을 %2 으로  %3 도 만큼 회전 %4',\n    rokoboard_get_sensor_value_by_name: '%1 의 센서값',\n    ardublock_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    ardublock_get_analog_value: '아날로그 %1 번 센서값',\n    ardublock_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    ardublock_get_digital: '디지털 %1 번 센서값',\n    ardublock_get_left_cds_analog_value: '왼쪽 조도센서 %1 센서값',\n    ardublock_get_right_cds_analog_value: '오른쪽 조도센서 %1 센서값',\n    ardublock_get_sound_analog_value: '사운드(소리) 센서 %1 센서값',\n    ardublock_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    ardublock_set_left_motor: '왼쪽모터를 %1 으로 %2 회전 속도로 정하기 %3',\n    ardublock_set_right_motor: '오른쪽모터를 %1 으로 %2 회전 속도로 정하기 %3',\n    ardublock_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    ardublock_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    ardublock_toggle_led: '디지털 %1 번 핀 %2 %3',\n    ardublock_toggle_left_led: '왼쪽 라이트 %1 번 핀 %2 %3',\n    ardublock_toggle_right_led: '오른쪽 라이트 %1 번 핀 %2 %3',\n    mkboard_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    mkboard_get_analog_value: '아날로그 %1 번 센서값',\n    mkboard_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    mkboard_get_digital: '디지털 %1 번 센서값',\n    mkboard_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    mkboard_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    mkboard_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    mkboard_toggle_led: '디지털 %1 번 핀 %2 %3',\n    mkboard_set_lcd: '1602 문자 LCD %1 행 , %2열에 %3 출력하기 %4',\n    mkboard_lcd_command: '1602 문자 LCD %1 명령실행하기 %2',\n    altino_analogValue: '알티노 %1 센서값',\n    altino_dot_display: '전광판에 %1 글자 표시하기 %2',\n    altino_dot_display_line: '1열 %1 2열 %2 3열 %3 4열 %4 5열 %5 6열 %6 7열 %7 8열 %8 출력하기 %9',\n    altino_light: '%1 등을 %2  %3',\n    altino_rear_wheel: '뒷바퀴 오른쪽 %1 왼쪽 %2 로 정하기 %3',\n    altino_sound: '%1 옥타브 %2 음을 연주하기  %3',\n    altino_steering: '방향을 %1 로 정하기 %2',\n    jdkit_altitude: '드론을 %1 높이만큼 날리기 %2',\n    jdkit_button: '%1번 버튼 값 읽어오기',\n    jdkit_connect: '드론 연결 상태 읽어오기',\n    jdkit_emergency: '드론을 즉시 멈추기 %1',\n    jdkit_gyro: '보드 %1 기울기 값 읽어오기',\n    jdkit_joystick: '조이스틱 %1 읽기',\n    jdkit_led: '%1 LED %2  %3',\n    jdkit_motor: '%1 모터를 %2 세기로 돌리기 %3',\n    jdkit_ready: '드론 비행 준비 상태 읽어오기',\n    jdkit_rollpitch: '드론을 %1 방향 %2 세기로 움직이기 %3',\n    jdkit_throttle: '드론 프로펠러를 %1 만큼 세기로 돌리기 %2',\n    jdkit_tune: '%1 음을  %2 초동안 소리내기 %3',\n    jdkit_ultrasonic: '거리(초음파)값 읽어오기',\n    jdkit_yaw: '드론을 %1 만큼 회전하기 %2',\n    memaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    memaker_get_analog_value: '아날로그 %1 번 센서값',\n    memaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    memaker_get_digital: '디지털 %1 번 센서값',\n    memaker_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n    memaker_set_lcd: '1602 문자 LCD %1 행 , %2열에 %3 출력하기 %4',\n    memaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    memaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n    memaker_lcd_command: '1602 문자 LCD %1 명령실행하기 %2',\n    edumaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    edumaker_get_analog_value: '아날로그 %1 번 센서값',\n    edumaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n    edumaker_get_digital: '디지털 %1 번 센서값',\n    edumaker_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n    edumaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n    edumaker_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n    edumaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n    creamo_get_number_sensor_value: '가변저항_블록 %1 번 센서값  ',\n    creamo_get_port_number: '%1',\n    creamo_get_pwm_port_number: '%1  ',\n    creamo_motor_port_number: '%1',\n    creamo_toggle_led: 'LED_블록 %1 번 핀 %2 %3',\n    creamo_toggle_motor: 'Motor_블록 %1 번 핀 %2 %3',\n    creamo_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n    mechatro_get_dc_motor_current: '%1모터 사용전류값',\n    mechatro_get_digital: '%1 디지털 값',\n    mechatro_get_sensor_value: '%1 센서값',\n    mechatro_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 의 거리값 [cm]',\n    mechatro_set_blue_pw: '블루투스 비밀번호 : %1%2%3%4로 정하기%5',\n    mechatro_set_dc_motor: '%1모터 속도 %2로 정하기%3',\n    mechatro_set_digital: '%1번 %2 %3',\n    mechatro_set_pwm: '%1PWM을 %2%로 정하기 %3',\n    mechatro_set_servo_position: '%1서보모터 위치 :%2도로 옮기기 %3',\n    mechatro_set_servo_speed: '%1서보모터 속도 : 1초당 %2도로 정하기 %3',\n    mechatro_set_threshold: '%1 센서 감도 : %2로 정하기%3',\n    mechatro_set_tone: '%1버저 %2 %3 음으로 연주 %4',\n    mechatro_set_tone_time: '%1버저 %2 %3 음으로 %4 초 연주 %5',\n    funboard_buzzer_onoff: '버저 %1 %2',\n    funboard_buzzer_second: '버저%1%2초 동안%3',\n    funboard_buzzer_tone_simple: '%1%2음을%3초 연주하기%4',\n    funboard_color_led_on_pwm: '%1색  LED %2 % %3',\n    funboard_color_led_onoff: '%1색  LED %2 %3',\n    funboard_convert_scale: '%1값 %2~%3 에서 %4~%5 으로 변환값',\n    funboard_dotmatrix_1column: '%1칸 %2표시하기 %3',\n    funboard_dotmatrix_1row: '%1줄 %2표시하기 %3',\n    funboard_dotmatrix_1row_1column: '%1%2 %3표시하기 %4',\n    funboard_dotmatrix_64_display: '%1 (8x8)표시하기%2',\n    funboard_dotmatrix_big_eng: '대문자 %1표시하기 %2',\n    funboard_dotmatrix_char_display: '문자%1표시하기%2',\n    funboard_dotmatrix_extra_char: '문자 %1표시하기 %2',\n    funboard_dotmatrix_intensity: '밝기 %1% %2',\n    funboard_dotmatrix_kor: '▦  한글 %1표시하기 %2',\n    funboard_dotmatrix_num: '숫자 %1표시하기 %2',\n    funboard_dotmatrix_onoff: '모두 %1 %2',\n    funboard_dotmatrix_scroll_option: '스크롤 방향%1%2',\n    funboard_dotmatrix_scroll_rapid: '스크롤 속도 %1% %2',\n    funboard_dotmatrix_set: '%1줄 %2칸  %3 %4',\n    funboard_dotmatrix_small_eng: '소문자 %1표시하기 %2',\n    funboard_dotmatrix_string_display: '문자열%1표시하기%2',\n    funboard_dotmatrix_string_display_scroll: '문자열%1표시하기%2스크롤%3',\n    funboard_dotmatrix_symbol: '기호 %1표시하기 %2',\n    funboard_get_analog_sensor_2state: '%1값 %2',\n    funboard_get_digital_button_value: '%1 버튼  값',\n    funboard_get_number_sensor_value: '%1 값',\n    funboard_get_touch_button_value: '%1 터치  값',\n    funboard_set_digital_buzzer: '버저를 %1옥타브 %2음 %3초  연주%4',\n    funboard_what_button_pressed: '%1 버튼  눌림',\n    funboard_what_touch_button_pressed: '%1 터치됨',\n    learning_title_image_str: '분류: 이미지 모델',\n    learning_title_speech_str: '분류: 소리 모델',\n    learning_title_text_str: '분류: 텍스트 모델',\n    learning_title_number_str: '분류: 숫자 (kNN) 모델',\n    learning_title_regression_str: '예측: 숫자 모델',\n    learning_title_cluster_str: '군집: 숫자 모델',\n    learning_title_logistic_regression_str: '분류: 숫자 (로지스틱 회귀) 모델',\n    learning_title_decisiontree_str: '분류: 숫자 (결정 트리) 모델',\n    learning_title_svm_str: '분류: 숫자 (SVM) 모델',\n    media_pipe_title: '%1',\n    media_pipe_video_screen: '비디오 화면 %1 %2',\n    media_pipe_switch_camera: '%1 카메라로 바꾸기 %2',\n    check_connected_camera: '카메라가 연결되었는가?',\n    media_pipe_flip_camera: '비디오 화면 %1 뒤집기 %2',\n    media_pipe_set_opacity_camera: '비디오 투명도 효과를 %1 으로 정하기 %2',\n    media_pipe_motion_value: '%1 에서 감지한 %2 값',\n    pose_landmarker_title: '%1',\n    when_pose_landmarker: '%1 사람을 인식했을 때',\n    pose_landmarker: '사람 인식 %1 %2',\n    draw_detected_pose: '인식한 사람 %1 %2',\n    check_detected_pose: '사람을 인식했는가?',\n    count_detected_pose: '인식한 사람의 수',\n    locate_to_pose: '%1 번째의 사람의 %2 (으)로 이동하기 %3',\n    locate_time_to_pose: '%1 초 동안 %2 번째의 사람의 %3 (으)로 이동하기 %4',\n    axis_detected_pose: '%1 번째 사람의 %2 의 %3 좌표',\n    face_landmarker_title: '%1',\n    when_face_landmarker: '%1 얼굴을 인식했을 때',\n    face_landmarker: '얼굴 인식 %1 %2',\n    draw_detected_face: '인식한 얼굴 %1 %2',\n    check_detected_face: '얼굴을 인식했는가?',\n    count_detected_face: '인식한 얼굴의 수',\n    locate_to_face: '%1 번째의 얼굴의 %2 (으)로 이동하기 %3',\n    locate_time_to_face: '%1 초 동안 %2 번째의 얼굴의 %3 (으)로 이동하기 %4',\n    check_detected_gender: '%1 번째 얼굴의 성별이 %2 인가?',\n    check_compare_age: '%1 번째 얼굴의 나이 %2 %3 인가?',\n    check_detected_emotion: '%1 번째 얼굴의 감정이 %2 인가?',\n    axis_detected_face: '%1 번째 얼굴의 %2 의 %3 좌표',\n    get_detected_face_value: '%1 번째 얼굴의 %2',\n    object_detector_title: '%1',\n    when_object_detector: '%1 사물을 인식했을 때',\n    object_detector: '사물 인식 %1 %2',\n    draw_detected_object: '인식한 사물 %1 %2',\n    check_detected_object: '사물을 인식했는가?',\n    count_detected_object: '인식한 사물의 수',\n    is_detected_among_objects: '사물 중 %1 을(를) 인식했는가?',\n    hand_detection_title: '%1',\n    when_hand_detection: '%1 손을 인식했을 때',\n    hand_detection: '손 인식 %1 %2',\n    draw_detected_hand: '인식한 손 %1 %2',\n    check_detected_hand: '손을 인식했는가?',\n    count_detected_hand: '인식한 손의 수',\n    locate_to_hand: '%1 번째 손의 %2 %3 (으)로 이동하기 %4',\n    locate_time_to_hand: '%1 초 동안 %2 번째 손의 %3 %4 (으)로 이동하기 %5',\n    axis_detected_hand: '%1 번째 손의 %2 %3 의 %4 좌표',\n    is_which_hand: '%1 번째 손이 %2 인가?',\n    is_which_gesture: '%1 번째 손의 모양이 %2 인가?',\n    get_which_hand: '%1 번째 손',\n    get_which_gesture: '%1 번째 손의 모양',\n    function_create_value: '함수 정의하기 %1 %2 %3 결괏값을 %4 (으)로 정하기',\n    run: '',\n    reverse_of_string: '%1 %2 %3',\n    video_capture_for_image_test: '비디오 화면을 학습한 모델로 분류 %1 %2',\n};\nLang.TextCoding = {\n    block_name: '블록명',\n    title_syntax: '문법오류 ',\n    title_converting: '변환오류',\n    message_syntax_default: '문법에 오류가 있습니다',\n    message_syntax_unexpected_token: '문법에 맞지 않는 토큰이 포함되어 있습니다',\n    message_syntax_reserved_token: '사용할 수 없는 변수명입니다.',\n    message_syntax_reserved_token_list: '사용할 수 없는 리스트명입니다.',\n    message_syntax_unexpected_character: '문법에 맞지 않는 문자가 포함되어 있습니다',\n    message_syntax_unexpected_indent: '문법에 맞지 않는 띄어쓰기가 포함되어 있습니다',\n    message_conv_default: '지원하지 않는 코드입니다',\n    message_conv_no_support: '변환될 수 없는 코드입니다',\n    message_conv_no_variable: '변수가 선언되지 않았습니다',\n    message_conv_no_list: '리스트가 선언되지 않았습니다',\n    message_conv_no_object: '객체는 지원되지 않습니다',\n    message_conv_no_function: '함수가 변환될 수 없습니다',\n    message_conv_no_entry_event_function: '엔트리 이벤트 함수는 다른 함수 안에 존재할 수 없습니다.',\n    message_conv_undefined_function:\n        '정의되지 않은 명령어 입니다. 명령어가 올바르게 입력되었는지 확인해주세요.',\n    message_conv_is_expect1: '올바르지 않은 문법입니다. ',\n    message_conv_is_expect2: ' 가 올바르게 입력되었는지 확인해주세요.',\n    message_conv_instead: '올바르지 않은 문법입니다. %1 대신 %2 가 필요합니다.',\n    message_conv_is_wrong1: '올바르지 않은 문법입니다. ',\n    message_conv_is_wrong2: '(은/는) 올 수 없는 위치입니다.',\n    message_conv_or: ' 나 ',\n    subject_syntax_default: '기타',\n    subject_syntax_token: '토큰',\n    subject_syntax_character: '문자',\n    subject_syntax_indent: '띄워쓰기',\n    subject_conv_default: '기타',\n    subject_conv_general: '일반',\n    subject_conv_variable: '변수',\n    subject_conv_list: '리스트',\n    subject_conv_object: '객체',\n    subject_conv_function: '함수',\n    alert_variable_empty_text:\n        '등록된 변수 중에 공백(띄어쓰기)이 포함된 변수가 있으면 모드 변환을 할 수 없습니다.',\n    alert_list_empty_text:\n        '등록된 리스트 중에 공백(띄어쓰기)이 포함된 리스트가 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_field_multi:\n        '등록된 함수 중에 함수 이름에 [이름] 블록이 두번이상 포함되어 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_disorder:\n        '등록된 함수 중에[이름] 블록이 [문자/숫자값] 또는 [판단값] 블록보다 뒤에 쓰이면 모드 변환을 할 수 없습니다.',\n    alert_function_has_boolean:\n        '엔트리파이선으로 변환 후 다시 블록코딩으로 모드로 변경하면 함수에 사용된 [판단값]은 모두 [문자/숫자형]으로 변환됩니다.',\n    alert_function_editor: '함수 생성 및 편집 중에는 모드 변환을 할 수 없습니다.',\n    alert_function_no_support: '텍스트모드에서는 함수 생성 및 편집을 할 수 없습니다.',\n    alert_list_no_support: '텍스트모드에서는 리스트 생성 및 편집을 할 수 없습니다.',\n    alert_variable_no_support: '텍스트모드에서는 변수 생성 및 편집을 할 수 없습니다.',\n    alert_signal_no_support: '텍스트모드에서는 신호 생성 및 편집을 할 수 없습니다.',\n    alert_legacy_no_support: '전환할 수 없는 블록이 존재하여 모드 변환을 할 수 없습니다.',\n    alert_variable_empty_text_add_change: '변수명 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_list_empty_text_add_change: '리스트명에 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_list_contains_exceed_length_value:\n        '리스트 항목에 15자리 이상의 수가 입력되어 있으면 모드 변환을 할 수 없습니다.',\n    alert_function_name_empty_text_add_change: '함수명에 공백(띄어쓰기)이 포함될 수 없습니다.',\n    alert_no_save_on_error: '문법 오류가 존재하여 작품을 저장할 수 없습니다.',\n    alert_api_no_support:\n        '작품에 엔트리파이썬에서 지원하지 않는 \\n블록이 조립되어 있습니다. \\n해당 블록을 삭제하고 만들기 모드를 변경할까요?',\n    warn_unnecessary_arguments:\n        '&(calleeName)(); 는 괄호 사이에 값이 입력될 필요가 없는 명령어 입니다. (line:&(lineNumber))',\n    python_code: ' 오브젝트의 파이선 코드',\n    eof: '줄바꿈',\n    newline: '줄바꿈',\n    indent: '들여쓰기',\n    num: '숫자',\n    string: '문자열',\n    name: '변수명',\n};\nLang.PythonHelper = {\n    when_run_button_click_desc:\n        '[시작하기]버튼을 클릭하면 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_run_button_click_exampleCode: 'def when_start():\\n    Entry.print(\"안녕!\")',\n    when_run_button_click_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕!\"이라 말합니다.',\n    when_some_key_pressed_desc:\n        'A키를 누르면 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_some_key_pressed_elements:\n        'A-- 아래 선택지 중 하나\\n① 알파벳 : \"A\", \"B\" ~ \"Z\" 등(소문자 가능)\\n② 숫자 : 1, 2, 3, 4 ~ 9, 0\\n③ 특수키 : \"space\", \"enter\"\\n④ 방향키 : \"up\", \"down\", \"right\", \"left\"',\n    when_some_key_pressed_exampleCode:\n        'def when_press_key(\"W\"):\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(1):\\n    Entry.add_size(10)',\n    when_some_key_pressed_exampleDesc:\n        'W키를 누르면 오브젝트가 이동방향으로 10만큼 이동하고, 1키를 누르면 오브젝트의 크기가 10만큼 커집니다.',\n    mouse_clicked_desc:\n        '마우스를 클릭했을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    mouse_clicked_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.add_size(10)\\n    Entry.move_to_direction(10)',\n    mouse_clicked_exampleDesc:\n        '마우스를 클릭하면 오브젝트의 크기가 10만큼 커지면서 이동방향으로 10만큼 이동합니다.',\n    mouse_click_cancled_desc:\n        '마우스 클릭을 해제했을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    mouse_click_cancled_exampleCode:\n        'def when_click_mouse_off():\\n    Entry.move_to_direction(-10)\\n\\ndef when_click_mouse_on():\\n    Entry.move_to_direction(10)',\n    mouse_click_cancled_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 마우스 클릭을 해제하면 오브젝트가 이동방향으로 -10만큼 이동합니다.',\n    when_object_click_desc:\n        '해당 오브젝트를 클릭했을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_object_click_exampleCode:\n        'def when_click_object_on():\\n    Entry.print_for_sec(\"회전!\", 0.5)\\n    Entry.add_rotation(90)',\n    when_object_click_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 \"회전!\"이라 말하고, 90도 만큼 회전합니다.',\n    when_object_click_canceled_desc:\n        '해당 오브젝트 클릭을 해제했을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_object_click_canceled_exampleCode:\n        'def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)',\n    when_object_click_canceled_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.',\n    when_message_cast_desc:\n        'A 신호를 받으면 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\\n만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    when_message_cast_elements: 'A-- \"신호 이름\"',\n    when_message_cast_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.send_signal(\"신호\")\\n\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"안녕! 반가워\", 0.5)',\n    when_message_cast_exampleDesc:\n        '마우스를 클릭하면 \"신호\"를 보내고, \"신호\"를 받았을때 \"안녕! 반가워\"라고 0.5초간 말합니다.',\n    message_cast_desc:\n        'A에 입력된 신호를 보냅니다.\\n만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    message_cast_elements: 'A-- \"신호 이름\"',\n    message_cast_exampleCode:\n        '#\"오브젝트1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"안녕! 넌 몇살이니?\", 2)\\n    Entry.send_signal(\"신호\")\\n\\n#\"오브젝트2\"의 파이선 코드\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"안녕? 난 세 살이야.\", 2)',\n    message_cast_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"오브젝트1\"이 \"안녕! 넌 몇살이니?\"라고 2초간 말하고 \"신호를 보냅니다., \"오브젝트2\"가 \"신호\"를 받았을때 \"안녕? 난 세 살이야.\"라고 2초간 말합니다.',\n    message_cast_wait_desc:\n        'A에 입력된 신호를 보내고, 해당 신호를 받는 명령어들의 실행이 끝날 때까지 기다립니다.\\n만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.',\n    message_cast_wait_elements: 'A-- \"신호 이름\"',\n    message_cast_wait_exampleCode:\n        '#\"오브젝트1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"숨바꼭질하자!\", 2)\\n    Entry.send_signal_wait(\"신호\")\\n    Entry.hide()\\n\\n#\"오브젝트2\"의 파이선 코드\\ndef when_get_signal(\"신호\"):\\n    Entry.print_for_sec(\"그래!\", 2)',\n    message_cast_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"오브젝트1\"이 \"숨바꼭질하자!\"라고 2초 동안 말하고 \"신호\"를 보낸 후 기다립니다. \"오브젝트2\"가 \"신호\"를 받으면 \"그래!\"를 2초 동안 말합니다. \"오브젝트1\"이 그 후에 모양을 숨깁니다.',\n    when_scene_start_desc:\n        '장면이 시작되면 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_scene_start_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\"다른 곳으로 가볼까?\", 2)\\n    Entry.start_scene(\"장면 2\")\\n\\n#\"장면 2\"의 파이선 코드\\ndef when_start_scene():\\n    Entry.print(\"여기가 어디지?\")',\n    when_scene_start_exampleDesc:\n        '\"장면 1\"에서 [시작하기]버튼을 클릭하면 \"다른 곳으로 가볼까?\"라고 2초간 말하고, \"장면 2\"가 시작됩니다. \"장면 2\"가 시작되면 오브젝트가 \"여기가 어디지?\"라고 말합니다.',\n    start_scene_desc: 'A 장면을 시작합니다.',\n    start_scene_elements: 'A-- \"장면 이름\"',\n    start_scene_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_click_object_on():\\n    Entry.start_scene(\"장면 2\")',\n    start_scene_exampleDesc: '\"장면 1\"에서 해당 오브젝트를 클릭하면 \"장면 2\"가 시작됩니다.',\n    start_neighbor_scene_desc: 'A에 입력한 다음 또는 이전 장면을 시작합니다.',\n    start_neighbor_scene_elements:\n        'A-- 아래 선택지 중 하나\\n① 다음 장면: \"next\" 또는 \"다음\"\\n② 이전 장면: \"prev\" 또는 \"이전\"',\n    start_neighbor_scene_exampleCode:\n        '#\"장면 1\"의 파이선 코드\\ndef when_press_key(\"right\"):\\n    Entry.start_scene_of(\"next\")\\n\\n#\"장면 2\"의 파이선 코드\\ndef when_press_key(\"left\"):\\n    Entry.start_scene_of(\"prev\")',\n    start_neighbor_scene_exampleDesc:\n        '\"장면 1\"에서 오른쪽화살표키를 누르면 다음 장면이, \"장면 2\"에서 왼쪽화살표키를 누르면 이전 장면이 시작됩니다.',\n    wait_second_desc: 'A초만큼 기다린 후 다음 블록을 실행합니다.',\n    wait_second_elements: 'A-- 초에 해당하는 수 입력',\n    wait_second_exampleCode:\n        'def when_start():\\n    Entry.add_effect(\"color\", 10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_size(10)',\n    wait_second_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트에 색깔효과를 10만큼 주고, 2초동안 기다린 다음 크기를 10만큼 커지게 합니다.',\n    repeat_basic_desc:\n        '아래 명령어들을 A번 반복하여 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_basic_elements: 'A-- 반복할 횟수 입력',\n    repeat_basic_exampleCode:\n        'def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()',\n    repeat_basic_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.',\n    repeat_inf_desc:\n        'A 판단이 True인 동안 아래 명령어들을 반복 실행합니다. A에 True를 입력하면 계속 반복됩니다. \\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_inf_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    repeat_inf_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()',\n    repeat_inf_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.',\n    repeat_while_true_desc:\n        'A 판단이 True가 될 때까지 아래 명령어들을 반복 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    repeat_while_true_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    repeat_while_true_exampleCode:\n        'def when_start():\\n    while not Entry.is_key_pressed(\"space\"):\\n        Entry.add_rotation(90)',\n    repeat_while_true_exampleDesc:\n        '[시작하기]버튼을 클릭하면 스페이스키를 누를때까지 오브젝트가 90도 만큼 회전합니다.',\n    stop_repeat_desc:\n        \"이 블록을 감싸는 가장 가까운 블록을 멈춥니다.\\n        '반복하기'블록과 같이 ㄷ자 모양으로 다른 블록을 감싼 블록에 조립해 사용할 수 있습니다.\",\n    stop_repeat_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_key_pressed(\"enter\"):\\n            break',\n    stop_repeat_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 계속 이동합니다. 엔터키를 누르면 반복이 중단됩니다.',\n    _if_desc:\n        'A 부분의 판단이 True이면 if A:아래 명령어들을 실행하고, False이면 실행하지 않습니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    _if_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    _if_exampleCode:\n        'def when_click_mouse_on():\\n    if (Entry.value_of_mouse_pointer(\"x\") > 0):\\n        Entry.print_for_sec(\"오른쪽!\", 0.5)',\n    _if_exampleDesc:\n        '마우스를 클릭했을 때 마우스 x좌표가 0보다 크면 오브젝트가 \"오른쪽!\"이라고 0.5초 동안 말합니다.',\n    if_else_desc:\n        'A 부분의 판단이 True이면 if A: 아래 명령어들을 실행하고, False이면 else: 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    if_else_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    if_else_exampleCode:\n        'def when_click_mouse_on():\\n    if Entry.is_touched(\"mouse_pointer\"):\\n        Entry.print(\"닿았다!\")\\n    else:\\n        Entry.print(\"안 닿았다!\")',\n    if_else_exampleDesc:\n        '마우스를 클릭했을 때 마우스포인터가 오브젝트에 닿았으면 \"닿았다!\"를 그렇지 않으면 \"안 닿았다!\"를 말합니다.',\n    wait_until_true_desc: 'A 부분의 판단이 True가 될 때까지 코드의 실행을 멈추고 기다립니다.',\n    wait_until_true_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    wait_until_true_exampleCode:\n        'def when_start():\\n    Entry.print(\"엔터를 눌러봐!\")\\n    Entry.wait_until(Entry.is_key_pressed(\"enter\"))\\n    Entry.print(\"잘했어!\")',\n    wait_until_true_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"엔터를 눌러봐!\"라 말하고, 엔터키를 누를 때까지 기다립니다. 엔터키를 누르면 \"잘했어!\"라 말합니다.',\n    stop_object_desc: 'A코드의 실행을 중지합니다.',\n    stop_object_elements:\n        'A-- 아래 선택지 중 하나\\n① \"all\":  모든 오브젝트의 모든 코드\\n② \"self\" : 해당 오브젝트의 모든 코드\\n③ \"this\": 이 명령어가 포함된 코드\\n④ \"others\" : 해당 오브젝트의 코드 중 이 명령어가 포함된 코드를 제외한 모든 코드\\n⑤ \"ohter_objects\" : 이 오브젝트를 제외한 다른 모든 오브젝트의 코드',\n    stop_object_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.stop_code(\"all\")\\n',\n    stop_object_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 마우스포인터 위치로  이동합니다. 스페이스키를 누르면 모든 코드의 실행이 중지됩니다.',\n    restart_project_desc: '작품을 처음부터 다시 실행합니다.',\n    restart_project_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_size(10)\\n\\ndef when_press_key(\"enter\"):\\n    Entry.start_again()',\n    restart_project_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트의 크기가 커집니다. 엔터키를 누르면 작품을 처음부터 다시 실행합니다.',\n    when_clone_start_desc:\n        '해당 오브젝트의 복제본이 새로 생성되었을 때 아래 명령어들을 실행합니다.\\n아래 명령어는 [Tab]키를 통해 들여쓰기합니다.',\n    when_clone_start_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"self\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))',\n    when_clone_start_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.',\n    create_clone_desc: 'A 오브젝트의 복제본을 생성합니다.',\n    create_clone_elements: 'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"self\" 또는 \"자신\"',\n    create_clone_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"self\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))',\n    create_clone_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.',\n    delete_clone_desc: 'Entry.make_clone_of(A) 명령에 의해 생성된 복제본을 삭제합니다.',\n    delete_clone_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"자신\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_click_object_on():\\n    Entry.remove_this_clone()',\n    delete_clone_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 복제본을 클릭하면 클릭된 복제본을 삭제합니다.',\n    remove_all_clones_desc: '해당 오브젝트의 모든 복제본을 삭제합니다.',\n    remove_all_clones_exampleCode:\n        'def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\"자신\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_press_key(\"space\"):\\n    Entry.remove_all_clone()',\n    remove_all_clones_exampleDesc:\n        '[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 스페이스 키를 누르면 모든 복제본을 삭제합니다.',\n    move_direction_desc: 'A만큼 오브젝트의 이동방향 화살표가 가리키는 방향으로 움직입니다.',\n    move_direction_elements: 'A-- 이동할 거리에 해당하는 수',\n    move_direction_exampleCode: 'def when_start():\\n    Entry.move_to_direction(10)',\n    move_direction_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동합니다.',\n    bounce_wall_desc: '오브젝트가 화면 끝에 닿으면 튕겨져 나옵니다.',\n    bounce_wall_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()',\n    bounce_wall_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.',\n    move_x_desc: '오브젝트의 x좌표를 A만큼 바꿉니다.',\n    move_x_elements:\n        'A-- x좌표의 변화 값\\n① 양수: 오브젝트가 오른쪽으로 이동합니다.\\n② 음수: 오브젝트가 왼쪽으로 이동합니다.',\n    move_x_exampleCode:\n        'def when_start():\\n    Entry.add_x(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_x(-10)',\n    move_x_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오른쪽으로 10만큼 이동하고 2초 동안 기다린 후 왼쪽으로 10만큼 이동합니다.',\n    move_y_desc: '오브젝트의 y좌표를 A만큼 바꿉니다.',\n    move_y_elements:\n        'A-- y좌표의 변화 값\\n① 양수: 오브젝트가 위쪽으로 이동합니다.\\n② 음수: 오브젝트가 아래쪽으로 이동합니다.',\n    move_y_exampleCode:\n        'def when_start():\\n    Entry.add_y(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_y(-10)',\n    move_y_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 위쪽으로 10만큼 이동하고 2초 동안 기다린 후 아래쪽으로 10만큼 이동합니다.',\n    move_xy_time_desc: '오브젝트가 x와 y좌표를 각각 A와 B만큼 C초에 걸쳐 서서히 바꿉니다.',\n    move_xy_time_elements:\n        'A-- x좌표의 변화 값\\n① 양수: 오브젝트가 오른쪽으로 이동합니다.\\n② 음수: 오브젝트가 왼쪽으로 이동합니다.%nextB-- y좌표의 변화 값\\n① 양수: 오브젝트가 위쪽으로 이동합니다.\\n② 음수: 오브젝트가 아래쪽으로 이동합니다.%nextC-- 이동하는 시간(초)',\n    move_xy_time_exampleCode:\n        'def when_start():\\n    Entry.add_xy_for_sec(100, 100, 2)\\n    Entry.add_xy_for_sec(-100, -100, 2)',\n    move_xy_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오른쪽 위로 100만큼 2초 동안 이동한 후 왼쪽 아래로 100만큼 2초 동안 이동합니다.',\n    locate_x_desc: '오브젝트의 x좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_x_elements: 'A-- 이동할 x좌표',\n    locate_x_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_x(100)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_x(-100)\\n',\n    locate_x_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 100으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 x좌표를 -100으로 정합니다.',\n    locate_y_desc: '오브젝트의 y좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_y_elements: 'B-- 이동할 y좌표',\n    locate_y_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.set_y(100)\\n\\ndef when_press_key(\"down\"):\\n    Entry.set_y(-100)',\n    locate_y_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 y좌표를 100으로 정하고, 아래쪽화살표키를 누르면 오브젝트의 y좌표를 -100으로 정합니다.',\n    locate_xy_desc: '오브젝트가 좌표(A, B)로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_elements: 'A-- 이동할 x좌표%nextB-- 이동할 y좌표',\n    locate_xy_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_xy(0, 0)\\n\\ndef when_press_key(\"right\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\"up\"):\\n    Entry.add_y(10)',\n    locate_xy_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 오브젝트의 x, y좌표를 0으로 정합니다.',\n    locate_xy_time_desc:\n        '오브젝트가 좌표(A, B)로 C초에 걸쳐 서서히 이동합니다.(오브젝트의 중심점이 기준이 됩니다.)',\n    locate_xy_time_elements: 'A-- 이동할 x좌표%nextB-- 이동할 y좌표%nextC-- 이동하는 시간',\n    locate_xy_time_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_xy_for_sec(0, 0, 2)\\n\\ndef when_press_key(\"right\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\"up\"):\\n    Entry.add_y(10)',\n    locate_xy_time_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 2초 동안 오브젝트를 x,y 좌표 0으로 이동시킵니다.',\n    locate_desc: '오브젝트가 A의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    locate_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.move_to(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.move_to(\"오브젝트\")',\n    locate_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 마우스포인터 위치로 이동합니다.\\n스페이스키를 누르면 오브젝트가 \"오브젝트\" 위치로 이동합니다.',\n    locate_object_time_desc:\n        '오브젝트가 A의 위치로 B초에 걸쳐 서서히 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)',\n    locate_object_time_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\" %nextB-- 이동하는 시간(초)',\n    locate_object_time_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.move_to_for_sec(\"mouse_pointer\", 2)',\n    locate_object_time_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 2초 동안 서서히 마우스포인터 위치로 이동합니다.',\n    rotate_relative_desc:\n        '오브젝트의 방향을 A도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_relative_elements: 'A-- 회전할 각도',\n    rotate_relative_exampleCode:\n        'def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)',\n    rotate_relative_exampleDesc:\n        '오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.',\n    direction_relative_desc: '오브젝트의 이동 방향을 A도만큼 회전합니다.',\n    direction_relative_elements: 'A-- 회전할 각도',\n    direction_relative_exampleCode:\n        'def when_start():\\n    Entry.move_to_direction(50)\\n    Entry.wait_for_sec(0.5)\\n    Entry.add_direction(90)\\n    Entry.wait_for_sec(0.5)\\n    Entry.move_to_direction(50)',\n    direction_relative_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 50만큼 이동한 다음 0.5초간 기다립니다. 그 후 이동방향을 90도 만큼 회전하고 0.5초간 기다린 후 이동방향으로 50만큼 이동합니다.',\n    rotate_by_time_desc:\n        '오브젝트의 방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    rotate_by_time_elements: 'A-- 회전할 각도%nextB-- 회전할 시간(초)',\n    rotate_by_time_exampleCode:\n        'def when_start():\\n    Entry.add_rotation_for_sec(90, 2)\\n    Entry.add_rotation_for_sec(-90, 2)',\n    rotate_by_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 2초 동안 90도 만큼 회전하고, 다시 2초 동안 -90도 만큼 회전합니다.',\n    direction_relative_duration_desc:\n        '오브젝트의 이동방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)',\n    direction_relative_duration_elements: 'A-- 회전할 각도%nextB-- 회전할 시간(초)',\n    direction_relative_duration_exampleCode:\n        'def when_start():\\n    Entry.add_direction_for_sec(90, 2)\\n\\ndef when_start():\\n    while True:\\n        Entry.move_to_direction(1)',\n    direction_relative_duration_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트의 이동방향을 2초 동안 90도만큼 회전시킵니다. 동시에 오브젝트는 이동방향으로 1만큼 계속 이동합니다.',\n    rotate_absolute_desc: '오브젝트의 방향을 A로 정합니다.',\n    rotate_absolute_elements: 'A-- 설정할 방향',\n    rotate_absolute_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_rotation(90)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_rotation(270)',\n    rotate_absolute_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 방향을 90으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 방향을 270으로 정합니다.',\n    direction_absolute_desc: '오브젝트의 이동방향을 A로 정합니다.',\n    direction_absolute_elements: 'A-- 설정할 이동방향',\n    direction_absolute_exampleCode:\n        'def when_press_key(\"right\"):\\n    Entry.set_direction(90)\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(\"left\"):\\n    Entry.set_direction(270)\\n    Entry.move_to_direction(10)',\n    direction_absolute_exampleDesc:\n        '오른쪽화살표키를 누르면 오브젝트의 이동방향을 90으로 정한 후 해당 쪽으로 10만큼 이동하고, 왼쪽화살표키를 누르면 오브젝트의 이동방향을 270으로 정하고 해당쪽으로 10만큼 이동합니다.',\n    see_angle_object_desc:\n        '오브젝트가 A쪽을 바라봅니다. (이동방향이 A를 향하도록 오브젝트의 방향을 회전해줍니다.)',\n    see_angle_object_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    see_angle_object_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.look_at(\"mouse_pointer\")\\n\\ndef when_press_key(\"space\"):\\n    Entry.look_at(\"오브젝트\")',\n    see_angle_object_exampleDesc:\n        '마우스를 클릭하면 오브젝트가 마우스포인터쪽을 바라보고, 스페이스키를 누르면 \"오브젝트\"쪽을 바라봅니다.',\n    move_to_angle_desc: '오브젝트가 A만큼 B방향으로 움직입니다.',\n    move_to_angle_elements:\n        'A-- 이동할 거리에 해당하는 수%nextB-- 이동할 방향(12시 방향이 0도, 시계방향으로 증가)',\n    move_to_angle_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.move_to_degree(10, 0)\\n\\ndef when_press_key(\"down\"):\\n    Entry.move_to_degree(10, 180)',\n    move_to_angle_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트가 0도방향으로 10만큼 이동하고, 아래쪽화살표키를 누르면 오브젝트가 180도방향으로 10만큼 이동합니다.',\n    show_desc: '오브젝트를 화면에 나타냅니다.',\n    show_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()',\n    show_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.',\n    hide_desc: '오브젝트를 화면에서 보이지 않게 합니다.',\n    hide_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()',\n    hide_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.',\n    dialog_time_desc:\n        '오브젝트가 A를 B초 동안 말풍선으로 말한 후 다음 명령어가 실행됩니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.',\n    dialog_time_elements:\n        'A-- 말할 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등%nextB-- 말하는 시간(초)',\n    dialog_time_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(\"안녕! 나는\", 2)\\n    Entry.print_for_sec(16, 2)\\n    Entry.print_for_sec(\"살이야\", 2)',\n    dialog_time_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"안녕! 나는\", 16, \"살이야\"를 각각 2초 동안 차례대로 말합니다.',\n    dialog_desc: '오브젝트가 A를 말풍선으로 말합니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.',\n    dialog_elements: 'A-- 말할 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    dialog_exampleCode:\n        'def when_start():\\n    Entry.print(\"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\")\\n\\ndef when_press_key(1):\\n    Entry.print(1)\\n\\ndef when_press_key(2):\\n    Entry.print(2)\\n',\n    dialog_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\"를 말하고, 키보드로 1, 2를 누르면 각각 1, 2라 말합니다.',\n    remove_dialog_desc: '오브젝트가 말하고 있는 말풍선을 지웁니다.',\n    remove_dialog_exampleCode:\n        'def when_start():\\n    Entry.print(\"말풍선을 지우려면 엔터를 눌러!\")\\n\\ndef when_press_key(\"enter\"):\\n    Entry.clear_print()',\n    remove_dialog_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"말풍선을 지우려면 엔터를 눌러!\"라 말하고, 엔터키를 누르면 말풍선이 사라집니다.',\n    change_to_some_shape_desc: '오브젝트를 A 모양으로 바꿉니다.',\n    change_to_some_shape_elements:\n        'A-- 아래 선택지 중 하나\\n① 모양 이름 : [속성] 탭의 \"모양 이름\"을 적음\\n② 모양 번호 : [속성] 탭의 모양 번호를 적음',\n    change_to_some_shape_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\"오브젝트모양\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\"오브젝트모양\")',\n    change_to_some_shape_exampleDesc:\n        '[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 \"오브젝트모양\"으로 모양을 바꾸고 0.3초간 기다린 다음 \"오브젝트모양\"모양으로 모양을 바꿉니다.',\n    change_to_next_shape_desc: '오브젝트의 모양을 다음 또는 이전 모양으로 바꿉니다.',\n    change_to_next_shape_elements:\n        'A-- 아래 선택지 중 하나\\n① 다음 모양 : \"next\" 또는 \"다음\" \\n② 이전 모양 : \"pre\" 또는 \"이전\"',\n    change_to_next_shape_exampleCode:\n        'def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\"next\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\"pre\")',\n    change_to_next_shape_exampleDesc:\n        '[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 모양으로 오브젝트 모양을 바꾸고 0.3초간 기다린 다음 이전 모양으로 오브젝트 모양을 바꿉니다.',\n    add_effect_amount_desc: '오브젝트에 A 효과를 B만큼 줍니다.',\n    add_effect_amount_elements:\n        'A -- 아래 선택지 중 하나\\n① “color” 또는 “색깔“                 \\n② “brightness” 또는 “밝기”                \\n③ “transparency” 또는 “투명도”%nextB-- 효과의 변화 정도',\n    add_effect_amount_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.add_effect(\"color\", 50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\"brightness\", -50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\"transparency\", 50)',\n    add_effect_amount_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔 효과를 50만큼 주고 1초간 기다리고, 밝기 효과를 -50만큼 주고 1초간 기다립니다. 그 후 투명도 효과를 50만큼 줍니다.',\n    change_effect_amount_desc: '오브젝트의 A 효과를 B로 정합니다.',\n    change_effect_amount_elements:\n        'A-- 아래 선택지 중 하나\\n① “color” 또는 “색깔“                 \\n② “brightness” 또는 “밝기”                \\n③ “transparency” 또는 “투명도”%nextB-- 효과의 값\\n① color: 0~100 범위의 수, 100을 주기로 반복됨\\n② brightness: -100~100 사이 범위의 수, -100이하는 -100 으로 100 이상은 100 으로 처리 됨\\n③ transparency: 0~100 사이 범위의 수, 0 이하는 0으로, 100이상은 100으로 처리 됨',\n    change_effect_amount_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_effect(\"color\", 50)\\n    Entry.set_effect(\"brightness\", 50)\\n    Entry.set_effect(\"transparency\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.set_effect(\"color\", 0)\\n    Entry.set_effect(\"brightness\", 0)\\n    Entry.set_effect(\"transparency\", 0)',\n    change_effect_amount_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 각 효과를 0으로 정합니다.',\n    erase_all_effects_desc: '오브젝트에 적용된 효과를 모두 지웁니다.',\n    erase_all_effects_exampleCode:\n        'def when_click_mouse_on():\\n    Entry.set_effect(\"color\", 50)\\n    Entry.set_effect(\"brightness\", 50)\\n    Entry.set_effect(\"transparency\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.clear_effect()\\n',\n    erase_all_effects_exampleDesc:\n        '마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 오브젝트에 적용된 모든 효과를 지웁니다.',\n    change_scale_size_desc: '오브젝트의 크기를 A만큼 바꿉니다.',\n    change_scale_size_elements: 'A-- 크기 변화 값',\n    change_scale_size_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\"space\"):\\n    Entry.set_size(100)',\n    change_scale_size_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.',\n    set_scale_size_desc: '오브젝트의 크기를 A로 정합니다.',\n    set_scale_size_elements: 'A-- 크기값',\n    set_scale_size_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\"space\"):\\n    Entry.set_size(100)',\n    set_scale_size_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.',\n    flip_x_desc: '오브젝트의 상하 모양을 뒤집습니다.',\n    flip_x_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\"right\"):\\n    Entry.flip_vertical()',\n    flip_x_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.',\n    flip_y_desc: '오브젝트의 좌우 모양을 뒤집습니다.',\n    flip_y_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\"right\"):\\n    Entry.flip_vertical()',\n    flip_y_exampleDesc:\n        '위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.',\n    change_object_index_desc: '오브젝트의 레이어를 A로 가져옵니다.',\n    change_object_index_elements:\n        'A-- 아래 선택지 중 하나\\n① “front\" 또는 “맨 앞“                 \\n② “forward” 또는 “앞”                \\n③ “backward” 또는 “뒤”\\n④ “back” 또는 “맨 뒤”',\n    change_object_index_exampleCode:\n        'def when_start():\\n    Entry.send_layer_to(\"front\")\\n    Entry.wait_for_sec(2)\\n    Entry.send_layer_to(\"backward\")',\n    change_object_index_exampleDesc:\n        '오브젝트가 여러개가 겹쳐 있을 경우 [시작하기]버튼을 클릭하면  해당 오브젝트의 레이어를 가장 앞으로 가져와서 보여줍니다.',\n    brush_stamp_desc: '오브젝트의 모양을 도장처럼 실행화면 위에 찍습니다.',\n    brush_stamp_exampleCode:\n        'def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()',\n    brush_stamp_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.',\n    start_drawing_desc:\n        '오브젝트가 이동하는 경로를 따라 선이 그려지기 시작합니다. (오브젝트의 중심점이 기준)',\n    start_drawing_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    for i in range(10):\\n        Entry.move_to_direction(10)',\n    start_drawing_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 오브젝트가 이동방향으로 10만큼 10번 이동할 때 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    stop_drawing_desc: '오브젝트가 선을 그리는 것을 멈춥니다.',\n    stop_drawing_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n\\ndef when_click_mouse_on():\\n    Entry.stop_drawing()',\n    stop_drawing_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 마우스를 클릭하면 그리는것을 멈춥니다.',\n    set_color_desc: '오브젝트가 그리는 선의 색을 A로 정합니다.',\n    set_color_elements:\n        'A-- 아래 선택지 중 하나\\n① 색상 코드 : \"#FF0000\", \"#FFCC00\", \"#3333FF\", \"#000000\" 등\\n② 색깔명 : \"red\", \"orange\", \"yellow\", \"green\", \"blue\", \"navy\", \"purple\", \"black\", \"white\", \"brown\"',\n    set_color_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_color_to(\"#000099\")\\n    while True:\\n        Entry.move_to_direction(1)',\n    set_color_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 색을 \"#000099\"로 정합니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    set_random_color_desc: '오브젝트가 그리는 선의 색을 무작위로 정합니다.',\n    set_random_color_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n        Entry.set_brush_color_to_random()',\n    set_random_color_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 색깔은 계속해서 무작위로 정해집니다.',\n    change_thickness_desc: '오브젝트가 그리는 선의 굵기를 A만큼 바꿉니다.',\n    change_thickness_elements: 'A-- 굵기 변화 값',\n    change_thickness_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.add_brush_size(1)\\n        Entry.move_to_direction(10)',\n    change_thickness_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 굵기는 계속해서 1씩 커집니다.',\n    set_thickness_desc: '오브젝트가 그리는 선의 굵기를 A로 정합니다.',\n    set_thickness_elements: 'A-- 굵기값(1이상의 수)',\n    set_thickness_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)',\n    set_thickness_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    change_brush_transparency_desc: '오브젝트가 그리는 선의 투명도를 A만큼 바꿉니다.',\n    change_brush_transparency_elements: 'A-- 투명도 변화 값',\n    change_brush_transparency_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.add_brush_transparency(5)',\n    change_brush_transparency_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 투명도는 계속해서 5만큼 바꿉니다.',\n    set_brush_tranparency_desc: '오브젝트가 그리는 선의 투명도를 A로 정합니다.',\n    set_brush_tranparency_elements: 'A-- 투명도값(0~100 의 범위)',\n    set_brush_tranparency_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    Entry.set_brush_transparency(50)\\n    while True:\\n        Entry.move_to_direction(10)',\n    set_brush_tranparency_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로, 선의 투명도를 50으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.',\n    brush_erase_all_desc: '오브젝트가 그린 선과 도장을 모두 지웁니다.',\n    brush_erase_all_exampleCode:\n        'def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(10)\\n\\ndef when_click_mouse_on():\\n    Entry.clear_drawing()',\n    brush_erase_all_exampleDesc:\n        '[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 마우스를 클릭하면 오브젝트가 그린 선을 모두 지웁니다.',\n    text_read_desc:\n        '글상자 A의 내용입니다.\\n(내용 안에 개행이 있는 경우, 띄어쓰기하여 반환됩니다.)',\n    text_read_elements: 'A-- 아래 선택지 중 하나\\n① \"오브젝트(글상자) 이름\" \\n② 자기 자신',\n    text_read_exampleCode: 'def when_start():\\n    Entry.print(Entry.contents_of_textbox(\"A\"))',\n    text_read_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 글상자 \"A\"의 내용을 말합니다.​',\n    text_write_desc: '글상자의 내용을 A로 고쳐씁니다.',\n    text_write_elements: 'A-- 글상자의 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    text_write_exampleCode: 'def when_start():\\n    Entry.write_text(\"엔트리\")',\n    text_write_exampleDesc: '[시작하기]버튼을 클릭하면 글상자의 내용을 \"엔트리\"로 바꿉니다.',\n    text_append_desc: '글상자의 내용 뒤에 A를 추가합니다.',\n    text_append_elements:\n        'A-- 글상자의 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    text_append_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"안녕?\")\\n    Entry.wait_for_sec(1)\\n    Entry.append_text(\"엔트리!\")',\n    text_append_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"안녕?\"이 되었다가 1초 뒤에 \"엔트리!\"가 추가되어 \"안녕?엔트리!\"가 됩니다.',\n    text_prepend_desc: '글상자의 내용 앞에 A를 추가합니다.',\n    text_prepend_elements:\n        'A-- 글상자의 내용\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    text_prepend_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"반가워!\")\\n    Entry.wait_for_sec(1)\\n    Entry.prepend_text(\"엔트리!\")',\n    text_prepend_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"반가워!\"가 되었다가 1초 뒤에 \"엔트리!\"가 앞에 추가되어 \"엔트리!반가워!\"가 됩니다.',\n    text_flush_desc: '글상자에 저장된 값을 모두 지웁니다.',\n    text_flush_exampleCode:\n        'def when_start():\\n    Entry.write_text(\"엔트리\")\\n    Entry.wait_for_sec(1)\\n    Entry.clear_text()',\n    text_flush_exampleDesc:\n        '[시작하기]버튼을 클릭하면 글상자의 내용이 \"엔트리\"가 되었다가 1초 뒤에 모든 내용이 사라집니다.',\n    sound_something_with_block_desc: '오브젝트가 A 소리를 재생합니다.',\n    sound_something_with_block_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound(\"소리\")\\n    Entry.add_size(50)',\n    sound_something_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 재생하면서 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_second_with_block_desc: '오브젝트가 A소리를 B초 만큼 재생합니다.',\n    sound_something_second_with_block_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_second_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_for_sec(\"소리\", 1)\\n    Entry.add_size(50)',\n    sound_something_second_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 1초 동안 재생하면서, 오브젝트의 크기가 50만큼 커집니다.',\n    sound_from_to_desc: '오브젝트가 A소리를 B초부터 C초까지 재생합니다.',\n    sound_from_to_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_from_to_exampleCode:\n        'def when_start():\\n    Entry.play_sound_from_to(\"소리\", 0.5, 1)\\n    Entry.add_size(50)',\n    sound_from_to_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 0.5초부터 1초 구간까지만 재생하면서, 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_wait_with_block_desc:\n        '오브젝트가 A 소리를 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_something_wait_with_block_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_wait_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_and_wait(\"소리\")\\n    Entry.add_size(50)',\n    sound_something_wait_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_something_second_wait_with_block_desc:\n        '오브젝트가 A소리를 B초 만큼 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_something_second_wait_with_block_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_something_second_wait_with_block_exampleCode:\n        'def when_start():\\n    Entry.play_sound_for_sec_and_wait(\"소리\", 1)\\n    Entry.add_size(50)',\n    sound_something_second_wait_with_block_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 1초 동안 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_from_to_and_wait_desc:\n        '오브젝트가 A소리를 B초부터 C초까지 재생하고, 재생이 끝나면 다음 명령을 실행합니다.',\n    sound_from_to_and_wait_elements:\n        'A-- 아래 선택지 중 하나\\n① 소리 이름 : [속성] 탭의 \"소리 이름\"을 적음\\n② 소리 번호: [속성] 탭의 소리 번호를 적음',\n    sound_from_to_and_wait_exampleCode:\n        'def when_start():\\n    Entry.play_sound_from_to_and_wait(\"소리\", 0.5, 1)\\n    Entry.add_size(50)',\n    sound_from_to_and_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 0.5초부터 1초 구간까지만 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.',\n    sound_volume_change_desc: '작품에서 재생되는 모든 소리의 크기를 A퍼센트만큼 바꿉니다.',\n    sound_volume_change_elements: 'A-- 소리 크기 변화 값',\n    sound_volume_change_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")',\n    sound_volume_change_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\"작아집니다.',\n    sound_volume_set_desc: '작품에서 재생되는 모든 소리의 크기를 A퍼센트로 정합니다.',\n    sound_volume_set_elements: 'A-- 소리 크기값',\n    sound_volume_set_exampleCode:\n        'def when_press_key(\"up\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\"down\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_press_key(\"enter\"):\\n    Entry.set_sound_volume(100)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")',\n    sound_volume_set_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\"작아집니다. 엔터키를 누르면 소리의 크기를 100\"로 정합니다.',\n    sound_silent_all_desc: '현재 재생 중인 모든 소리를 멈춥니다.',\n    sound_silent_all_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\"소리\")\\n\\ndef when_press_key(\"enter\"):\\n    Entry.stop_sound()',\n    sound_silent_all_exampleDesc:\n        '[시작하기]버튼을 클릭하면 \"소리\"를 계속 재생합니다. 엔터키를 누르면 현재 재생 중인 소리를 멈춥니다.',\n    is_clicked_desc: '마우스를 클릭한 경우 True로 판단합니다.',\n    is_clicked_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_mouse_clicked():\\n            Entry.print_for_sec(\"반가워!\", 0.5)',\n    is_clicked_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 마우스를 클릭했는지 확인합니다. 만약 마우스를 클릭하면 오브젝트가 \"반가워!\"라고 0.5초간 말합니다.',\n    is_press_some_key_desc: 'A 키가 눌려져 있는 경우 True로 판단합니다.',\n    is_press_some_key_elements:\n        'A-- 아래 선택지 중 하나\\n① 알파벳 : \"A\", \"B\" ~ \"Z\" 등(소문자 가능)\\n② 숫자: 1, 2, 3, 4 ~ 9, 0\\n③ 특수키: \"space\", \"enter\"\\n④ 방향키 : \"up\", \"down\", \"right\", \"left\"',\n    is_press_some_key_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"space\"):\\n            Entry.move_to_direction(10)',\n    is_press_some_key_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 선택한 키를 눌렀는지 확인합니다. 만약 스페이스 키를 누르면 오브젝트가 이동방향으로 10만큼 이동합니다.',\n    reach_something_desc: '오브젝트가 A와 닿은 경우 True으로 판단합니다.',\n    reach_something_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\"\\n③ \"edge\", \"edge_up\", \"edge_down\", \"edge_right\", \"edge_left\"',\n    reach_something_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_touched(\"edge\"):\\n            Entry.add_rotation(150)',\n    reach_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 만약 오브젝트가 벽에 닿으면 150만큼 회전하게 됩니다.',\n    boolean_basic_operator_desc: 'A와 B를 비교하여 True 또는 False로 판단합니다.',\n    boolean_basic_operator_elements:\n        'A, B 비교하고자 하는 숫자값\\n① == : A와 B의 값이 같으면 True, 아니면 False\\n② != : A와 B의 값이 다르면 True, 아니면 False\\n③ > : A의 값이 B의 값보다 크면 true, 아니면 False\\n④ < : A의 값이 B의 값보다 작으면 true, 아니면 False\\n⑤ >= : A의 값이 B의 값보다 크거나 같으면 true, 아니면 False\\n⑥ <= : A의 값이 B의 값보다 작거나 같으면 true, 아니면 False',\n    boolean_basic_operator_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_x(10)\\n        if Entry.value_of_object(\"오브젝트\", \"x\") > 240:\\n            Entry.set_x(0)',\n    boolean_basic_operator_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트 x좌표를 10만큼 바꿉니다. 만약 오브젝트 x좌표가 240보다 크면 오브젝트 x좌표를 0으로 정합니다.',\n    boolean_and_desc: 'A와 B의 판단이 모두 True인 경우 True, 아닌 경우 False로 판단합니다.',\n    boolean_and_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_and_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") and Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_and_exampleDesc:\n        '[시작하기]버튼을 클릭하고 키보드의 \"a\" 와 \"s\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.',\n    boolean_or_desc: 'A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False로 판단합니다.',\n    boolean_or_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_or_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") or Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_or_exampleDesc:\n        '[시작하기]버튼을 클릭하면 키보드의 \"a\"나 \"s\"키 중 무엇이든 하나를 누르면 오브젝트에 색깔 효과를 10만큼 줍니다.',\n    boolean_not_desc: 'A 판단이 True이면 False, False이면 True로 판단합니다.',\n    boolean_not_elements:\n        'A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① True, False\\n② 10 == 10 , 10 > 10 , 10 <= 10 등\\n③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\"Q\") 등',\n    boolean_not_exampleCode:\n        'def when_start():\\n    while True:\\n        if not Entry.is_mouse_clicked():\\n            Entry.add_size(1)',\n    boolean_not_exampleDesc:\n        '[시작하기]버튼을 클릭하면 마우스를 클릭하지 않은 동안 크기가 1씩 커집니다.',\n    calc_basic_desc: 'A와 B의 연산값입니다.',\n    calc_basic_elements:\n        'A, B-- 연산하고자 하는 숫자값\\n① + : A와 B를 더한 값\\n② - : A와 B를 뺀 값\\n③ x : A와 B를 곱한 값\\n④ / : A와 B를 나눈 값',\n    calc_basic_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 + 10, 2)\\n    Entry.print_for_sec(10 - 10, 2)\\n    Entry.print_for_sec(10 * 10, 2)\\n    Entry.print_for_sec(10 / 10, 2)',\n    calc_basic_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10과 10을 더한값, 뺀값, 곱한값, 나눈값을 각 2초간 말합니다.',\n    calc_rand_desc:\n        'A와 B 사이에서 선택된 무작위 수의 값입니다. (두 수 모두 정수를 입력한 경우 정수로,두 수 중 하나라도 소수를 입력한 경우 소수로 무작위 수가 선택됩니다.)',\n    calc_rand_elements:\n        'A, B-- 무작위 수를 추출할 범위\\n① random.randint(A, B) : A, B를 정수로 입력하면 정수 범위에서 무작위 수를 추출\\n② random.uniform(A, B) : A, B를 실수로 입력하면 실수 범위에서 무작위 수를 추출',\n    calc_rand_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(random.randint(1, 10), 2)\\n    Entry.print_for_sec(random.uniform(0.1, 2), 2)',\n    calc_rand_exampleDesc:\n        '[시작하기]버튼을 클릭하면 1부터 10사이의 정수중 무작위 수를 뽑아 2초간 말합니다. 그 후 0.1부터 2사이의 실수중 무작위 수를 뽑아 2초간 말합니다.',\n    coordinate_mouse_desc: '마우스 포인터의 A 좌표 값을 의미합니다.',\n    coordinate_mouse_elements: 'A-- 아래 선택지 중 하나\\n① \"x\" 또는 \"X\"\\n② \"y\" 또는 \"Y\"',\n    coordinate_mouse_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_mouse_pointer(\"x\"))',\n    coordinate_mouse_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 마우스 포인터의 x좌표를 계속해서 말합니다.',\n    coordinate_object_desc: 'A에 대한 B정보값입니다.',\n    coordinate_object_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"self\" 또는 \"자신\"%nextB-- 아래 선택지 중 하나\\n① \"x\" 또는 \"X\"\\n② \"y\" 또는 \"Y\"\\n③ \"rotation\" 또는 \"방향\"\\n④ \"direction\" 또는 \"이동 방향\"\\n⑤ \"size\"  또는 \"크기\"\\n⑥ \"shape_number\" 또는 \"모양 번호\"\\n⑦ \"shape_name\" 또는 \"모양 이름\"',\n    coordinate_object_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.add_x(1)\\n        Entry.print(Entry.value_of_object(\"오브젝트\", \"x\"))\\n',\n    coordinate_object_exampleDesc:\n        '[시작하기]버튼을 클릭하면 계속해서 오브젝트의 x좌표가 1씩 증가하며, \"오브젝트\"의 x좌표를 말합니다.',\n    get_sound_volume_desc: '현재 작품에 설정된 소리의 크기값입니다.',\n    get_sound_volume_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_sound_volume())',\n    get_sound_volume_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 소리의 크기값을 계속해서 말합니다.',\n    quotient_and_mod_desc: 'A와 B의 연산값입니다.',\n    quotient_and_mod_elements:\n        'A, B-- 연산하고자 하는 숫자값\\n① // : A / B의 몫에 해당하는 값\\n② % : A / B의 나머지에 해당하는 값',\n    quotient_and_mod_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 // 3, 2)\\n    Entry.print_for_sec(10 % 3, 2)',\n    quotient_and_mod_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10 / 3의 몫인 3을 2초 동안 말하고, 나머지인 1을 2초 동안 말합니다.',\n    calc_operation_desc: 'A의 연산값입니다.',\n    calc_operation_elements:\n        'A, B-- 연산하고자 하는 숫자값\\n① A ** 2 : A를 제곱한 값\\n② math.sqrt(A): A의 루트값\\n③ math.sin(A): A의 사인값\\n④ math.cos(A): A의 코사인 값\\n⑤ math.tan(A):  A의 탄젠트값 \\n⑥ math.asin(A): A의 아크사인값\\n⑦ math.acos(A): A의 아크코사인값\\n⑧ math.atan(): A의 아크탄젠트값\\n⑨ math.log10(A): A의 로그값\\n⑩ math.log(A): A의 자연로그값\\n⑪ A - math.floor(A): A의 소수점 부분\\n⑫ math.floor(A): A의 소수점 버림값\\n⑬ math.ceil(A): A의 소수점 올림값\\n⑭ math.round(A): A의 소수점 반올림값\\n⑮ math.factorial(A): A의 팩토리얼 값\\n⑯ math.fabs(A): A의 절댓값',\n    calc_operation_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(10 ** 2, 2)\\n    Entry.print_for_sec(math.sqrt(9), 2)\\n    Entry.print_for_sec(math.sin(90), 2)\\n    Entry.print_for_sec(math.fabs(-10), 2)',\n    calc_operation_exampleDesc:\n        '[시작하기]버튼을 클릭하면 10의 제곱, 9의 루트값, 90의 사인값, -10의 절댓값을 각 2초 동안 말합니다.',\n    get_project_timer_value_desc: '이 명령이 실행되는 순간 초시계에 저장된 값입니다.',\n    get_project_timer_value_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    get_project_timer_value_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    choose_project_timer_action_desc:\n        '초시계의 동작을 A로 정합니다.\\n(이 명령어를 사용하면 실행화면에 ‘초시계 창’이 생성됩니다.)',\n    choose_project_timer_action_elements:\n        'A-- 아래 선택지 중 하나\\n① \"start\" : 초시계를 시작\\n② \"stop\" : 초시계를 정지\\n③ \"reset\" : 초시계를 초기화',\n    choose_project_timer_action_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    choose_project_timer_action_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    set_visible_project_timer_desc: '실행화면의 초시계 창을 A로 설정합니다.',\n    set_visible_project_timer_elements:\n        'A-- 아래 선택지 중 하나\\n① \"hide\" : 초시계창을 숨김\\n② \"show\" : 초시계창을 보임',\n    set_visible_project_timer_exampleCode:\n        'def when_start():\\n    Entry.timer(\"start\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\"stop\")\\n    Entry.timer_view(\"hide\")\\n    Entry.print(Entry.value_of_timer())',\n    set_visible_project_timer_exampleDesc:\n        '[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.',\n    get_date_desc: '현재 A에 대한 값입니다.',\n    get_date_elements:\n        'A-- 아래 선택지 중 하나\\n① \"year\" : 현재 연도 값\\n② \"month\" : 현재 월 값\\n③ \"day\" : 현재 일 값\\n④ \"hour\" : 현재 시간 값\\n⑤ \"minute\" : 현재 분 값\\n⑥ \"second\" : 현재 초 값',\n    get_date_exampleCode:\n        'def when_start():\\n    Entry.print(Entry.value_of_current_time(\"year\") + \"년\" + Entry.value_of_current_time(\"month\") + \"월\")',\n    get_date_exampleDesc: '[시작하기]버튼을 클릭하면 오브젝트가 현재년도와 월을 말합니다.',\n    distance_something_desc: '자신과 A까지의 거리 값입니다.',\n    distance_something_elements:\n        'A-- 아래 선택지 중 하나\\n① \"오브젝트 이름\"\\n② \"mouse_pointer\" 또는 \"마우스포인터\"',\n    distance_something_exampleCode:\n        'def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_distance_to(\"mouse_pointer\"))',\n    distance_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 마우스포인터와의 거리를 계속해서 말합니다.',\n    get_sound_duration_desc: '소리 A의 길이(초)값입니다.',\n    get_sound_duration_elements: 'A-- \"소리 이름\"',\n    get_sound_duration_exampleCode:\n        'def when_start():\\n    Entry.print(Entry.value_of_sound_length_of(\"소리\"))',\n    get_sound_duration_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"소리\"의 길이를 말합니다.',\n    get_user_name_desc:\n        '작품을 실행하고 있는 사용자의 아이디 값입니다.\\n값은 개인정보 보호를 위해 마스킹 처리되어 있습니다.',\n    get_user_name_exampleCode: 'def when_start():\\n    Entry.print(Entry.value_of_username())',\n    get_user_name_exampleDesc:\n        '[시작하기]버튼을 클릭하면 작품을 실행하고 있는 사용자의 아이디 값을 말합니다.',\n    get_nickname_desc: '작품을 실행하고 있는 사용자의 닉네임 값입니다.',\n    get_nickname_exampleCode: 'def when_start():\\n    Entry.print(Entry.value_of_nickname())',\n    get_nickname_exampleDesc:\n        '[시작하기]버튼을 클릭하면 작품을 실행하고 있는 사용자의 닉네임 값을 말합니다.',\n    length_of_string_desc: '입력한 문자값의 공백을 포함한 글자 수입니다.',\n    length_of_string_elements: 'A-- \"문자열\"',\n    length_of_string_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(len(\"안녕\"), 2)\\n    Entry.print_for_sec(len(\"엔트리\"), 2)',\n    length_of_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕\"과 \"엔트리\"의 글자 수를 각각 2초 동안 말합니다.',\n    combine_something_desc:\n        'A 문자열과 B 문자열을 결합한 값입니다. (A, B 중 하나가 숫자면 문자열로 바꾸어 처리되고, 둘 다 숫자면 덧셈 연산으로 처리됩니다.)',\n    combine_something_elements: 'A, B-- \"문자열\"',\n    combine_something_exampleCode: 'def when_start():\\n    Entry.print(\"안녕! \" + \"엔트리\")',\n    combine_something_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕!\"과 \"엔트리\"를 결합한 \"안녕! 엔트리\"를 말합니다.',\n    char_at_desc: 'A 문자열의 B번째의 글자 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    char_at_elements: 'A-- \"문자열\"%nextB-- 찾고자 하는 문자열의 위치',\n    char_at_exampleCode: 'def when_start():\\n    Entry.print(\"안녕 엔트리!\"[0])',\n    char_at_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"의 0번째 글자인 \"안\"을 말합니다.',\n    substring_desc:\n        'A 문자열의 B위치부터 C-1위치까지의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    substring_elements:\n        'A-- \"문자열\"%nextB-- 포함할 문자열의 시작 위치\\n첫 번째 글자는 0부터 시작%nextC-- 문자열을 포함하지 않는 위치',\n    substring_exampleCode: 'def when_start():\\n    Entry.print(\"안녕 엔트리!\"[1:5])',\n    substring_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"의 1에서 4번째 글자인 \"녕 엔트\"를 말합니다.',\n    index_of_string_desc:\n        'A문자열에서 B문자열이 처음으로 등장하는 위치의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)',\n    index_of_string_elements: 'A, B-- \"문자열\"',\n    index_of_string_exampleCode:\n        'def when_start():\\n    Entry.print(\"안녕 엔트리!\".find(\"엔트리\"))',\n    index_of_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"에서 \"엔트리\"가 처음으로 등장하는 위치인 3을 말합니다.',\n    replace_string_desc:\n        'A 문자열에서 B문자열을 모두 찾아 C문자열로 바꾼 값입니다.\\n(영문 입력시 대소문자를 구분합니다.)',\n    replace_string_elements: 'A, B, C-- \"문자열\"',\n    replace_string_exampleCode:\n        'def when_start():\\n    Entry.print(\"안녕 엔트리!\".replace( \"안녕\", \"반가워\"))',\n    replace_string_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"안녕 엔트리!\"에서 \"안녕\"을 \"반가워\"로 바꾼 \"반가워 엔트리!\"를 말합니다.',\n    change_string_case_desc: 'A의 모든 알파벳을 대문자 또는 소문자로 바꾼 문자값입니다.',\n    change_string_case_elements:\n        'A-- \"문자열\"\\n① A.upper(): A의 모든 알파벳을 대문자로 바꾼 값\\n② A.lower() : A의 모든 알파벳을 소문자로 바꾼 값',\n    change_string_case_exampleCode:\n        'def when_start():\\n    Entry.print_for_sec(\"Hello Entry!\".upper(), 2)\\n    Entry.print_for_sec(\"Hello Entry!\".lower(), 2)',\n    change_string_case_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"Hello Entry!\"를 모두 대문자로 바꾼 \"HELLO ENTRY!\"를 2초간 말한 다음 모두 소문자로 바꾼 \"hello entry!\"를 2초간 말합니다.',\n    ask_and_wait_desc:\n        \"오브젝트가 A 내용을 말풍선으로 묻고, 대답을 입력받습니다. 대답은 실행화면 또는 콘솔창에서 입력할 수 있으며 입력된 값은 'Entry.answer()'에 저장됩니다. \\n(이 명령어를 사용하면 실행화면에 ‘대답 창’이 생성됩니다.)\",\n    ask_and_wait_elements: 'A-- \"문자열\"',\n    ask_and_wait_exampleCode:\n        'def when_start():\\n    Entry.input(\"이름을 입력해보세요.\")\\n    Entry.print(Entry.answer() + \" 반가워!\")',\n    ask_and_wait_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"이름을 입력해보세요.\"라고 말풍선으로 묻습니다. 이름을 입력하면 \"(입력한 이름) 반가워!\"라 말합니다.',\n    get_canvas_input_value_desc:\n        'Entry.input(A) 명령에 의해 실행화면 또는 콘솔에서 입력받은 값입니다.',\n    get_canvas_input_value_exampleCode:\n        'def when_start():\\n    Entry.input(\"이름을 입력해보세요.\")\\n    Entry.print(Entry.answer() + \" 반가워!\")',\n    get_canvas_input_value_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 \"이름을 입력해보세요.\"라고 말풍선으로 묻습니다. 이름을 입력하면 \"(입력한 이름) 반가워!\"라 말합니다.',\n    set_visible_answer_desc: '실행화면의 대답 창을 A로 설정합니다.',\n    set_visible_answer_elements:\n        'A-- 아래 선택지 중 하나\\n① \"hide\" : 대답 창을 숨김\\n② \"show\" : 대답 창을 보임',\n    set_visible_answer_exampleCode:\n        'def when_start():\\n    Entry.answer_view(\"hide\")\\n    Entry.input(\"나이를 입력하세요.\")\\n    Entry.print(Entry.answer())',\n    set_visible_answer_exampleDesc:\n        '[시작하기]버튼을 클릭하면 대답창이 숨겨지고, 오브젝트가 \"나이를 입력하세요.\"라고 말풍선으로 묻습니다. 나이를 입력하면 오브젝트가 입력한 나이를 말합니다.',\n    get_variable_desc: 'A 변수에 저장된 값입니다.',\n    get_variable_elements:\n        'A-- 변수명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A',\n    get_variable_exampleCode: 'age = 16\\n\\ndef when_start():\\n    Entry.print(age)',\n    get_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 말합니다.',\n    change_variable_desc: 'A 변수에 B만큼 더합니다.',\n    change_variable_elements:\n        'A-- 변수명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 숫자값',\n    change_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.print_for_sec(age, 2)\\n    age += 2\\n    Entry.print_for_sec(age, 2)',\n    change_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 2초 동안 말합니다. 그 후 age변수에 2를 더하고 더한값인 \"18\"을 2초 동안 말합니다.',\n    set_variable_desc:\n        'A 변수의 값을 B로 정합니다. 만약 A 변수가 없으면  [속성] 탭에 A 변수가 자동 생성됩니다.',\n    set_variable_elements:\n        'A-- 변수명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 변수에 넣을 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    set_variable_exampleCode: 'age = 16\\n\\ndef when_start():\\n    Entry.print(age)',\n    set_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 말합니다.',\n    show_variable_desc: 'A 변수 창을 실행화면에 보이게 합니다.',\n    show_variable_elements:\n        'A-- \"변수명\"\\n① 모든 오브젝트에서 사용: \"A\"\\n② 이 오브젝트에서 사용: \"self.A\"',\n    show_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\"age\")\\n    Entry.wait_for_sec(2)\\n    age = 20\\n    Entry.show_variable(\"age\")',\n    show_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨깁니다. 2초 후 변수값을 17로 바꾸고 age변수창을 실행화면에 보이게 합니다.',\n    hide_variable_desc: 'A 변수 창을 실행화면에서 숨깁니다.',\n    hide_variable_elements:\n        'A-- \"변수명\"\\n① 모든 오브젝트에서 사용: \"A\"\\n② 이 오브젝트에서 사용: \"self.A\"',\n    hide_variable_exampleCode:\n        'age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\"age\")\\n    Entry.print_for_sec(age, 2)',\n    hide_variable_exampleDesc:\n        'age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨기고, 오브젝트가 age 변수에 들어 가 있는 값인 \"16\"을 2초 동안 말합니다.',\n    value_of_index_from_list_desc:\n        'A 리스트에서 B위치의 항목 값을 의미합니다. \\n(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    value_of_index_from_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치',\n    value_of_index_from_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.print(basket[1])\\n',\n    value_of_index_from_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트가 basket 리스트의 1번째 항목인 orange를 말합니다.',\n    add_value_to_list_desc: 'A 리스트의 마지막 항목으로 B값이 추가됩니다.',\n    add_value_to_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트에 넣을 항목 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    add_value_to_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket.append(\"juice\")\\n    Entry.print(basket[4])',\n    add_value_to_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 \"juice\"를 basket의 마지막 항목으로 추가합니다. 오브젝트는 basket의 4번째 항목인 \"juice\"를 말합니다.',\n    remove_value_from_list_desc:\n        'A 리스트의 B위치에 있는 항목을 삭제합니다.\\n(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    remove_value_from_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치값',\n    remove_value_from_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\ndef when_start():\\n    basket.pop(0)\\n    Entry.print(basket[0])',\n    remove_value_from_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 항목인 apple을 삭제합니다. 오브젝트는 새롭게 basket의 0번째 항목이 된 \"orange\"를 말합니다.',\n    insert_value_to_list_desc:\n        'A 리스트의 B위치에 C항목을 끼워 넣습니다. \\n(첫 번째 항목의 위치는 0부터 시작합니다. B위치보다 뒤에 있는 항목들은 순서가 하나씩 밀려납니다.)',\n    insert_value_to_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    insert_value_to_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket.insert(1, \"juice\")\\n    Entry.print(basket[2])',\n    insert_value_to_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 1번째 위치에 항목 \"juice\"를 끼워 넣습니다. 오브젝트는 새롭게 basket의 2번째 항목이 된 \"orange\"를 말합니다.',\n    change_value_list_index_desc:\n        'A 리스트에서 B위치에 있는 항목의 값을 C 값으로 바꿉니다.\\n(첫 번째 항목의 위치는 0부터 시작합니다.)',\n    change_value_list_index_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등',\n    change_value_list_index_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    basket[0] = \"juice\"\\n    Entry.print(basket[0])',\n    change_value_list_index_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 위치의 항목 \"apple\"을 \"juice\"로 바꿉니다. 오브젝트는 바뀐 basket의 0번째 항목 \"juice\"를 말합니다.',\n    length_of_list_desc: 'A 리스트가 보유한 항목 개수 값입니다.',\n    length_of_list_elements:\n        'A-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A',\n    length_of_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.print(len(basket))',\n    length_of_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트는  basket의 항목 개수인 4를 말합니다.',\n    is_included_in_list_desc: 'A값을 가진 항목이 B리스트에 포함되어 있는지 확인합니다.',\n    is_included_in_list_elements:\n        'A-- 리스트의 항목 값\\n① 문자 : \"안녕!\", \"엔트리\" 등 \\n② 숫자 : 0, 10, 35 등%nextB-- 리스트명\\n① 모든 오브젝트에서 사용: A\\n② 이 오브젝트에서 사용: self.A',\n    is_included_in_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    if \"apple\" in basket:\\n        Entry.print(\"사과가 있어!\")',\n    is_included_in_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트에 \"apple\"항목이 있는지 확인합니다. \"apple\"항목이 있기 때문에 오브젝트는 \"사과가 있어!\"라 말합니다.',\n    show_list_desc: '선택한 리스트 창을 실행화면에 보이게 합니다.',\n    show_list_elements:\n        'A-- \"리스트명\"\\n① 모든 오브젝트에서 사용: \"A\"\\n② 이 오브젝트에서 사용: \"self.A\"',\n    show_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.hide_list(\"basket\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\"basket\")',\n    show_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.',\n    hide_list_desc: '선택한 리스트 창을 실행화면에서 숨깁니다.',\n    hide_list_elements:\n        'A-- \"리스트명\"\\n① 모든 오브젝트에서 사용: \"A\"\\n② 이 오브젝트에서 사용: \"self.A\"',\n    hide_list_exampleCode:\n        'basket = [\"apple\", \"orange\", \"pear\", \"grape\"]\\n\\ndef when_start():\\n    Entry.hide_list(\"basket\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\"basket\")',\n    hide_list_exampleDesc:\n        'basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.',\n    boolean_and_or_desc: 'A와 B의 판단값을 확인하여 True 또는 False로 판단합니다.',\n    boolean_and_or_elements:\n        'A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)\\n① and : A와 B의 판단이 모두 True인 경우 True, 아닌 경우 False\\n② or : A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False',\n    boolean_and_or_exampleCode:\n        'def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\"a\") and Entry.is_key_pressed(\"s\"):\\n            Entry.add_effect(\"color\", 10)',\n    boolean_and_or_exampleDesc:\n        '[시작하기]버튼을 클릭하고 키보드의 \"a\" 와 \"s\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.',\n    check_weather_desc: 'B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.',\n    check_weather_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"sunny\" : 맑음\\n②    \"partly cloudy\" : 구름조금\\n③    \"mostly cloudy\" : 구름많음\\n④    \"cloudy\" : 흐림\\n⑤    \"rainy\" : 비\\n⑥    \"sleet\" : 진눈깨비\\n⑦    \"snowy\" : 눈%nextB-- 아래 선택지 중 하나\\n①    \"yesterday\" : 어제\\n②    \"today\" : 오늘\\n③    \"tomorrow\" : 내일\\n④    \"After 2 days\" : 모레\\n⑤    \"After 3 days\" : 3일 후\\n⑥    \"After 4 days\" : 4일 후\\n⑦    \"After 5 days\" : 5일 후\\n⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    check_weather_exampleCode:\n        'def when_start():\\n    if Weather.is_condition_sunny(\"today\", \"Seoul\"):\\n        Entry.print(\"오늘 서울의 날씨는 맑습니다.\")',\n    check_weather_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \"오늘 서울의 날씨는 맑습니다.\"라고 말합니다.​',\n    check_finedust_desc:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.',\n    check_finedust_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"good\" : 좋음\\n②    \"normal\" : 보통\\n③    \"bad\" : 나쁨\\n④    \"very bad\" : 매우나쁨%nextB-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    check_finedust_exampleCode:\n        'def when_start():\\n    if Weather.is_current_finedust_grade_good(\"Seoul\"):\\n        Entry.print(\"현재 서울의 미세먼지 등급은 좋음입니다.\")',\n    check_finedust_exampleDesc:\n        '[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​',\n    get_weather_data_desc:\n        '선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.',\n    get_weather_data_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"the lowest temperature\" : 최저기온\\n②    \"the highest temperature\" : 최고기온\\n③    \"humidity\" : 습도\\n④    \"precipitation\" : 강수량\\n⑤    \"precipitation probability\" : 강수확률\\n⑥    \"wind speed\" : 풍속%nextB-- 아래 선택지 중 하나\\n①    \"yesterday\" : 어제\\n②    \"today\" : 오늘\\n③    \"tomorrow\" : 내일\\n④    \"After 2 days\" : 모레\\n⑤    \"After 3 days\" : 3일 후\\n⑥    \"After 4 days\" : 4일 후\\n⑦    \"After 5 days\" : 5일 후\\n⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    get_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\"today\", \"Seoul\"))',\n    get_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​',\n    get_current_weather_data_desc: '현재 B지역의 A 날씨 정보값을 의미합니다.',\n    get_current_weather_data_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나\\n①    \"temperature\" : 기온\\n②    \"concentration of fine dust\" : 미세먼지농도',\n    get_current_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_current_temperature(\"Seoul\"))',\n    get_current_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.',\n    get_today_temperature_desc: '오늘 A지역의 B 시간대 기온 정보값을 의미합니다.',\n    get_today_temperature_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나\\n①    \"00\" : 당일 00시 측정된 기온값\\n②    \"03\" : 당일 03시 측정된 기온값\\n③    \"06\" : 당일 06시 측정된 기온값\\n④    \"09\" : 당일 09시 측정된 기온값\\n⑤    \"12\" : 당일 12시 측정된 기온값\\n⑥    \"15\" : 당일 15시 측정된 기온값\\n⑦    \"18\" : 당일 18시 측정된 기온값\\n⑧    \"21\" : 당일 21시 측정된 기온값',\n    get_today_temperature_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_today_temperature(\"Seoul\", 00))',\n    get_today_temperature_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​',\n    check_city_weather_desc: 'B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.',\n    check_city_weather_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"sunny\" : 맑음\\n②    \"partly cloudy\" : 구름조금\\n③    \"mostly cloudy\" : 구름많음\\n④    \"cloudy\" : 흐림\\n⑤    \"rainy\" : 비\\n⑥    \"sleet\" : 진눈깨비\\n⑦    \"snowy\" : 눈%nextB-- 아래 선택지 중 하나\\n①    \"yesterday\" : 어제\\n②    \"today\" : 오늘\\n③    \"tomorrow\" : 내일\\n④    \"After 2 days\" : 모레\\n⑤    \"After 3 days\" : 3일 후\\n⑥    \"After 4 days\" : 4일 후\\n⑦    \"After 5 days\" : 5일 후\\n⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    check_city_weather_exampleCode:\n        'def when_start():\\n    if Weather.is_condition_sunny(\"today\", \"Seoul\"):\\n        Entry.print(\"오늘 서울의 날씨는 맑습니다.\")',\n    check_city_weather_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \"오늘 서울의 날씨는 맑습니다.\"라고 말합니다.​',\n    check_city_finedust_desc:\n        '선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.',\n    check_city_finedust_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"good\" : 좋음\\n②    \"normal\" : 보통\\n③    \"bad\" : 나쁨\\n④    \"very bad\" : 매우나쁨%nextB-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    check_city_finedust_exampleCode:\n        'def when_start():\\n    if Weather.is_current_finedust_grade_good(\"Seoul\"):\\n        Entry.print(\"현재 서울의 미세먼지 등급은 좋음입니다.\")',\n    check_city_finedust_exampleDesc:\n        '[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​',\n    get_city_weather_data_desc:\n        '선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.',\n    get_city_weather_data_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"the lowest temperature\" : 최저기온\\n②    \"the highest temperature\" : 최고기온\\n③    \"humidity\" : 습도\\n④    \"precipitation\" : 강수량\\n⑤    \"precipitation probability\" : 강수확률\\n⑥    \"wind speed\" : 풍속%nextB-- 아래 선택지 중 하나\\n①    \"yesterday\" : 어제\\n②    \"today\" : 오늘\\n③    \"tomorrow\" : 내일\\n④    \"After 2 days\" : 모레\\n⑤    \"After 3 days\" : 3일 후\\n⑥    \"After 4 days\" : 4일 후\\n⑦    \"After 5 days\" : 5일 후\\n⑧    \"After 6 days\" : 6일 후%nextC-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북',\n    get_city_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\"today\", \"Seoul\"))',\n    get_city_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​',\n    get_current_city_weather_data_desc: '현재 B지역의 A 날씨 정보값을 의미합니다.',\n    get_current_city_weather_data_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나\\n①    \"temperature\" : 기온\\n②    \"concentration of fine dust\" : 미세먼지농도',\n    get_current_city_weather_data_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_current_temperature(\"Seoul\"))',\n    get_current_city_weather_data_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.',\n    get_today_city_temperature_desc: '오늘 A지역의 B 시간대 기온 정보값을 의미합니다.',\n    get_today_city_temperature_elements:\n        'A-- 아래 선택지 중 하나\\n①    \"Seoul\" : 서울\\n②    \"Gangwon-do\" : 강원\\n③    \"Gyeonggi-do\" : 경기\\n④    \"Gyeongsangnam-do\" : 경남\\n⑤    \"Gyeongsangbuk-do\" : 경북\\n⑥    \"Gwangju\" : 광주\\n⑦    \"Daegu\" : 대구\\n⑧    \"Daejeon\" : 대전\\n⑨    \"Busan\" : 부산\\n⑩    \"Sejong\" : 세종\\n⑪    \"Ulsan\" : 울산\\n⑫    \"Incheon\" : 인천\\n⑬    \"Jeollanam-do\" : 전남\\n⑭    \"Jeollabuk-do\" : 전북\\n⑮    \"Jeju\" : 제주\\nⒶ \"Chungcheongnam-do\" : 충남\\nⒷ \"Chungcheongbuk-do\": 충북%nextB-- 아래 선택지 중 하나\\n①    \"00\" : 당일 00시 측정된 기온값\\n②    \"03\" : 당일 03시 측정된 기온값\\n③    \"06\" : 당일 06시 측정된 기온값\\n④    \"09\" : 당일 09시 측정된 기온값\\n⑤    \"12\" : 당일 12시 측정된 기온값\\n⑥    \"15\" : 당일 15시 측정된 기온값\\n⑦    \"18\" : 당일 18시 측정된 기온값\\n⑧    \"21\" : 당일 21시 측정된 기온값',\n    get_today_city_temperature_exampleCode:\n        'def when_start():\\n    Entry.print(Weather.get_today_city_temperature(\"Seoul\", 00))',\n    get_today_city_temperature_exampleDesc:\n        '[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​',\n};\nLang.Painter = {\n    select_cut: '사각 점선 모양으로 오릴 수 있어요.',\n    thickness_of_eraser: '지우개 굵기',\n    font: '글꼴',\n    font_color: '글꼴 색상',\n    outline_color: '윤곽선 색상',\n    outline_thickness: '윤곽선 굵기',\n    fill_color: '채우기 색상',\n    inversion: '반전',\n    font_size: '글꼴 크기',\n    font_family: '글꼴 스타일',\n    fullscreen: '전체화면',\n    exit_fullscreen: '전체화면 해제',\n    picture_import: '모양 가져오기',\n    edit_way: '편집 방법',\n    line: '직선',\n    vertex: '꼭지점',\n    bitmap: '비트맵',\n    vector: '벡터',\n    forward: '앞으로',\n    backward: '뒤로',\n    front: '맨 앞으로',\n    back: '맨 뒤로',\n    group: '그룹화',\n    ungroup: '그룹 해제',\n    copy_picture: '복사',\n    delete_picture: '삭제',\n    cut_picture: '자르기',\n    paste_picture: '붙여넣기',\n    remove_all: '모두 삭제',\n    new_picture: '새그림',\n    edit: '편집',\n    picture_size: '크기',\n    picture_rotation: '회전',\n    thickness: '굵기',\n    font_fill: '채우기 색상',\n    painter_file_save: '저장하기',\n    painter_file_saveas: '새 모양으로 저장하기',\n    file: '파일',\n    Pencil: '펜',\n    Line: '직선',\n    Path: '형태',\n    Pan: '이동',\n    Select: '선택',\n    Rectangle: '사각형',\n    Ellipse: '원',\n    Text: '글상자',\n    Fill: '채우기',\n    Eraser: '지우기',\n    get_file: '가져오기',\n    copy_file: '복사하기',\n};\nLang.DataAnalytics = {\n    data_analysis: '데이터분석',\n    create_table: '테이블 만들기',\n    data: '데이터',\n    add_table: '테이블 추가하기',\n    show_chart: '차트 보기',\n    legend: '계열',\n    value: '값',\n    summary: '요약',\n    column_name: '열 이름',\n    total: '총합',\n    dashboard: '정보',\n    table: '테이블',\n    chart: '차트',\n    attribute: '열',\n    row: '행',\n    average: '평균',\n    standard_deviation: '표준 편차',\n    maximum: '최댓값',\n    minimum: '최솟값',\n    median: '중앙값',\n    average_explain: '해당 열의 모든 값을 더한 후 열의 개수 만큼 나눈 값',\n    standard_deviation_explain:\n        '데이터가 평균을 중심으로 얼마나 퍼져있는지 알려주는 값.\\\\n0에 가까울 수록 값들이 평균 근처에 집중되어 있다는 것을 의미',\n    maximum_minimum_explain: '해당 열의 가장 큰 값과 가장 작은 값',\n    median_explain: '해당 열의 모든 값을 크기순으로 배열했을 때\\\\n전체의 중앙에 위치하는 값',\n    add_row_above: '위쪽에 행 추가하기',\n    add_row_below: '아래쪽에 행 추가하기',\n    delete_row: '행 삭제',\n    add_property_left: '왼쪽에 열 추가하기',\n    add_property_right: '오른쪽에 열 추가하기',\n    delete_attribute: '열 삭제',\n    data_alert: '숫자가 아닌 값이 포함된 열은 개수만 확인할 수 있습니다.',\n    save: '저장하기',\n    cancel: '취소',\n    confirm: '확인',\n    attribute_count: '개',\n    row_count: '행',\n    cell_count: '개',\n    count: '개수',\n    add_chart_alert: '추가된 차트가 없습니다.\\\\n차트를 생성해주세요.',\n    enter_attribute_name: '열 이름을 입력해 주세요.(10자 이내)',\n    placeholder_attribute_name: '열 이름',\n    new_attribute: '새로운 열',\n    chart_title: '차트 제목',\n    remove_chart: '차트 삭제',\n    add_chart_first: '차트를 먼저 추가해주세요.',\n    bar: '막대',\n    line: '선',\n    pie: '원',\n    scatter: '점',\n    select_x_axis: '가로축을 선택해주세요.',\n    x_axis: '가로축',\n    y_axis: '세로축',\n    select_y_axis: '세로축을 선택해주세요.',\n    select_y_axis_or_legend: '세로축 혹은 계열을 선택해주세요.',\n    select_legend: '계열을 선택해주세요',\n    cell: '셀',\n    unable_to_express_chart: '차트로 표현할 수 없습니다.',\n    edit_attribute_name: '이름 바꾸기',\n    duplicate_attribute_name_title: '열 이름 변경에 실패하였습니다.',\n    duplicate_attribute_name_content: '같은 이름의 열이 존재합니다.',\n    fail_save_table: '테이블 저장에 실패하였습니다.',\n    duplicate_table_name_content: '같은 이름의 테이블이 존재합니다.',\n    saved_table_title: '저장되었습니다.',\n    saved_table_content: '테이블과 차트의 정보가 저장되었습니다.',\n    empty_table_name_content: '테이블 이름은 빈 칸이 될 수 없습니다',\n    do_not_delete_row: '행을 삭제할 수 없습니다.',\n    rows_cannot_less_one: '테이블에는 한 개 이상의 행이 있어야합니다.',\n    and: '외',\n    other: '건',\n    stop: '작품 정지하기',\n    restart: '작품 다시 시작',\n    pause: '작품 일시정지',\n    max_row_count_error_title: '너무 큰 테이블',\n    max_row_count_error:\n        '테이블의 셀이 30,000개 이상이면\\r\\n테이블을 불러올 수는 있지만, 편집할 수는 없습니다.\\r\\n큰 테이블의 편집은 별도 프로그램을 사용해 주세요.',\n    attributes_text: '%1 외 %2개의 속성',\n    copy: '복사',\n    delete: '삭제',\n    download: 'PC에 저장',\n    confirm_content: '변경된 테이블과 차트를 저장할까요?',\n    please_add_table: '테이블을 먼저 추가해 주세요.',\n    load_data_analytics: '테이블 불러오기',\n    summary_table_description: '테이블에서 열을 기준으로 한 기초 통계량입니다.',\n    not_exist_chart: '추가한 차트가 없습니다.',\n    please_add_chart: '차트를 먼저 추가해 주세요.',\n    chart_name: '차트 이름',\n    remove_confirm_content: '테이블을 삭제할까요?',\n    not_editable_content: '테이블의 셀이 30,000개 이상이라서\\r\\n엔트리에서 편집할 수 없어요.',\n    limit_cell_count_title: '행/열 개수 제한',\n    limit_cell_count_content:\n        '행 또는 열을 더 이상 추가할 수 없습니다.\\r\\n엔트리에서는 최대 30,000개의 셀까지의 \\r\\n테이블만 편집할 수 있습니다.',\n    must_have_one_row_content: '테이블에 행과 열이 하나는 있어야 합니다.',\n    number_of_bins: '계급 수',\n    bin_width: '계급 폭',\n    bin_boundary: '계급 경계',\n    left_closed: '왼쪽 닫힘',\n    right_closed: '오른쪽 닫힘',\n    ascending: '오름차순',\n    default: '원래대로',\n    quantity: '개수',\n    in_order: '순서',\n    not_distinguished: '구분하지 않음',\n    select_table: '[테이블 추가하기]를 눌러 테이블을 추가해 주세요.',\n    select_table_title: '테이블을 추가하는 방법',\n    select_table_des1:\n        \"1. 테이블 추가하기의 '테이블 선택' 탭에서 엔트리가 제공하는 기본 테이블을 선택해 추가합니다.\",\n    select_table_des2:\n        \"2. 테이블 추가하기의 '파일 올리기' 탭에서 CSV, XLS(X) 파일을 직접 업로드해 추가합니다.\",\n    select_table_des3:\n        \"3. 테이블 추가하기의 '새로 만들기' 탭에서 빈 테이블을 추가하고 데이터를 직접 입력합니다.\",\n    statistic: '대푯값',\n    provider: '출처',\n    description: '상세',\n    field_info: '속성 정보',\n    show_all_points: '모든 점 표시',\n    coefficient: '상관계수',\n    scatter_matrix: '산점도 행렬',\n    show_table: '테이블 보기',\n    bar_sub: '바 그래프',\n    line_sub: '라인 그래프',\n    pie_sub: '파이 차트',\n    scatter_sub: '산점도',\n    histogram: '히스토그램',\n    select_legend2: '계열을 2개 이상 선택해주세요',\n    duplicate: '복사',\n    paste: '붙여넣기',\n    cut: '잘라내기',\n    download_table: '테이블을 엑셀 파일로 다운로드',\n};\nLang.AiLearning = {\n    equation: '회귀식',\n    predict: '예측 속성',\n    cluster_number: '군집',\n    centriod: '중심점',\n    class: '클래스',\n    show: '보이기',\n    hide: '숨기기',\n    open: '열기',\n    close: '닫기',\n    probability: '신뢰도',\n    accuracy: '정확도',\n    f1: 'F1',\n    precision: '정밀도',\n    recall: '재현율',\n    train_param_optimizer_adam: 'Adam',\n    train_param_optimizer_sgd: 'SGD',\n    neighbor_count: '이웃 개수',\n    cluster_option_centroids_kmpp: '가장 먼 거리',\n    cluster_option_centroids_random: '무작위',\n    model_attr_str: '핵심 속성',\n    model_status_0: '상태: 준비',\n    model_status_1: '상태: 학습중',\n    model_status_2: '상태: 학습완료',\n    model_status_3: '상태: 모델없음',\n    train_param_learningRate: '학습률',\n    train_param_epochs: '에포크',\n    train_param_validationRate: '검증 데이터 비율',\n    train_param_C: 'C',\n    train_param_kernel_polynomial: '다항식',\n    train_param_kernel_rbf: 'RBF',\n    train_param_degree: '차수',\n    train_param_gamma: '감마',\n    start: '시작하기',\n    stop: '중지하기',\n    train_param_maxDepth: '트리의 최대 깊이',\n    train_param_minNumSamples: '노드의 최소 데이터 수',\n    chart_title: '모델 차트 창',\n    tree_title: '학습한 트리 창',\n    trained_table_postfix: '학습완료',\n    train_param_error: '테이블 열 정보가 변경된 경우에는 재 학습이 불가능 합니다.',\n};\nLang.SharePolicy = {\n    title: '엔트리 작품/게시물 공유 가이드',\n};\n\nLang.Support = ['ko', 'en', 'vn', 'jp'];\n\nLang.pose_list = {\n    nose: '코',\n    left_eye_inner: '왼쪽 눈 안쪽',\n    left_eye: '왼쪽 눈',\n    left_eye_outer: '왼쪽 눈 바깥쪽',\n    right_eye_inner: '오른쪽 눈 안쪽',\n    right_eye: '오른쪽 눈',\n    right_eye_outer: '오른쪽 눈 바깥쪽',\n    left_ear: '왼쪽 귀',\n    right_ear: '오른쪽 귀',\n    mouth_left: '왼쪽 입꼬리',\n    mouth_right: '오른쪽 입꼬리',\n    left_shoulder: '왼쪽 어깨',\n    right_shoulder: '오른쪽 어깨',\n    left_elbow: '왼쪽 팔꿈치',\n    right_elbow: '오른쪽 팔꿈치',\n    left_wrist: '왼쪽 손목',\n    right_wrist: '오른쪽 손목',\n    left_pinky: '왼쪽 소지',\n    right_pinky: '오른쪽 소지',\n    left_index: '왼쪽 검지',\n    right_index: '오른쪽 검지',\n    left_thumb: '왼쪽 엄지',\n    right_thumb: '오른쪽 엄지',\n    left_hip: '왼쪽 엉덩이',\n    right_hip: '오른쪽 엉덩이',\n    left_knee: '왼쪽 무릎',\n    right_knee: '오른쪽 무릎',\n    left_ankle: '왼쪽 발목',\n    right_ankle: '오른쪽 발목',\n    left_heel: '왼쪽 발꿈치',\n    right_heel: '오른쪽 발꿈치',\n    left_foot_index: '왼쪽 발끝 ',\n    right_foot_index: '오른쪽 발끝',\n};\n\nLang.gesture_list = {\n    closed_fist: '쥔 손',\n    open_palm: '편 손',\n    pointing_up: '가리킨 손',\n    thumb_down: '엄지 아래로',\n    thumb_up: '엄지 위로',\n    victory: '브이 사인',\n    iloveyou: '사랑해',\n    none: '알 수 없음',\n};\n\nif (typeof exports == 'object') exports.Lang = Lang;\n"
  },
  {
    "path": "extern/lang/vn.js",
    "content": "var Lang = {};\nLang.category = {\n    \"name\": \"en\"\n};\nLang.type = \"vn\";\nLang.fallbackType = \"en\";\nLang.ko = \"한국어\";\nLang.en = \"English\";\nLang.jp = \"日本語\";\nLang.vn = \"tiếng Việt\";\nLang.Command = {\n    \"1\": \"장면 추가하기\",\n    \"2\": \"장면 삭제하기\",\n    \"3\": \"장면 이름 수정\",\n    \"4\": \"장면 순서 변경\",\n    \"5\": \"장면 선택\",\n    \"101\": \"블록 쓰레드 추가하기\",\n    \"102\": \"블록 쓰레드 삭제하기\",\n    \"103\": \"블록 삭제하기\",\n    \"104\": \"블록 복구하기\",\n    \"105\": \"블록 끼워넣기\",\n    \"106\": \"블록 분리하기\",\n    \"107\": \"블록 이동하기\",\n    \"108\": \"블록 복제하기\",\n    \"109\": \"블록 복제 취소하기\",\n    \"110\": \"스크롤\",\n    \"111\": \"블록 필드값 수정\",\n    \"117\": \"블록 쓰레드 추가하기\",\n    \"118\": \"블록 끼워넣기\",\n    \"119\": \"블록 이동하기\",\n    \"120\": \"블록 분리하기\",\n    \"121\": \"블록 이동하기\",\n    \"122\": \"블록 끼워넣기\",\n    \"123\": \"블록 끼워넣기\",\n    \"201\": \"오브젝트 선택하기\",\n    \"202\": \"오브젝트 수정 버튼 클릭\",\n    \"203\": \"오브젝트 그림 추가\",\n    \"204\": \"오브젝트 그림 삭제\",\n    \"205\": \"오브젝트 소리 추가\",\n    \"206\": \"오브젝트 소리 삭제\",\n    \"207\": \"오브젝트 이름 수정\",\n    \"208\": \"오브젝트 추가\",\n    \"209\": \"오브젝트 삭제\",\n    \"210\": \"오브젝트 추가 버튼 클릭\",\n    \"211\": \"오브젝트 x 수정\",\n    \"212\": \"오브젝트 y 수정\",\n    \"213\": \"오브젝트 size 수정\",\n    \"214\": \"오브젝트 방향 수정\",\n    \"215\": \"오브젝트 이동 방향 수정\",\n    \"216\": \"오브젝트 회전방식 수정\",\n    \"217\": \"엔터티 모델 동기화\",\n    \"301\": \"do\",\n    \"302\": \"undo\",\n    \"303\": \"redo\",\n    \"401\": \"그림 수정하기\",\n    \"402\": \"그림 수정 취소하기\",\n    \"403\": \"그림 수정하기\",\n    \"404\": \"그림 수정 취소하기\",\n    \"405\": \"글상자 수정\",\n    \"501\": \"시작하기\",\n    \"502\": \"정지하기\",\n    \"601\": \"컨테이너 오브젝트 선택하기\",\n    \"701\": \"모드 바꾸기\",\n    \"702\": \"모양 추가 버튼 클릭\",\n    \"703\": \"소리 추가 버튼 클릭\",\n    \"801\": \"속성 필터 선택하기\",\n    \"802\": \"변수 추가하기 버튼 클릭\",\n    \"803\": \"변수 추가하기\",\n    \"804\": \"변수 삭제하기\",\n    \"805\": \"변수 이름 설정\",\n    \"806\": \"신호 이름 설정\",\n    \"807\": \"신호 추가\",\n    \"808\": \"신호 삭제\",\n    \"809\": \"변수 스코프 정하기\",\n    \"810\": \"변수 글로벌 체크\",\n    \"811\": \"변수 보이기 체크\",\n    \"812\": \"변수 기본값 설정\",\n    \"813\": \"변수 슬라이드로 체크\",\n    \"814\": \"변수 최솟값 정하기\",\n    \"815\": \"변수 최댓값 정하기\",\n    \"816\": \"리스트 추가 버튼 클릭\",\n    \"817\": \"리스트 추가\",\n    \"818\": \"리스트 삭제\",\n    \"819\": \"리스트 이름 정하기\",\n    \"820\": \"리스트 스코프 정하기\",\n    \"821\": \"리스트 글로벌 체크\",\n    \"822\": \"리스트 보이기 체크\",\n    \"823\": \"리스트 길이 변경\",\n    \"824\": \"리스트 기본값 설정\",\n    \"825\": \"메세지 수정 enable\",\n    \"826\": \"변수 수정 enable\",\n    \"827\": \"리스트 수정 enable\",\n    \"828\": \"변수 이름 정하기\",\n    \"829\": \"리스트 이름 정하기\",\n    \"900\": \"모달 닫기\",\n    \"1001\": \"함수 생성 시작\",\n    \"1002\": \"함수 수정 시작\",\n    \"1003\": \"함수 수정 취소\",\n    \"1004\": \"함수 생성\",\n    \"1005\": \"함수 업데이트\"\n};\nLang.CommandTooltip = {\n    \"101\": \"블록 쓰레드 추가하기\",\n    \"102\": \"블록 쓰레드 삭제하기\",\n    \"103\": \"블록 삭제하기\",\n    \"104\": \"블록 복구하기\",\n    \"105\": \"코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.\",\n    \"106\": \"블록 분리하기\",\n    \"107\": \"블록 이동하기\",\n    \"108\": \"블록 복제하기\",\n    \"109\": \"블록 복제 취소하기\",\n    \"110\": \"스크롤\",\n    \"111\": \"블록 필드값 수정@@값을 입력하기 위해 이곳을 클릭합니다.$$선택지를 클릭합니다.$$선택지를 클릭합니다.$$&value&을 입력합니다.$$&value&를 선택합니다.$$키보드 &value&를 누릅니다.\",\n    \"117\": \"블록 쓰레드 추가하기\",\n    \"118\": \"블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.\",\n    \"119\": \"블록 가져오기@@빈 곳에 블록을 끌어다 놓습니다.\",\n    \"120\": \"블록 분리하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.\",\n    \"121\": \"블록 이동하기$$블록 삭제하기@@필요 없는 코드를 <b>휴지통</b>으로 끌어옵니다.$$이 곳에 코드를 버립니다.\",\n    \"122\": \"블록 연결하기@@이 곳에 블록을 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.\",\n    \"123\": \"코드 분리하기$$코드 연결하기@@이 코드의 가장 위에 있는 블록을 잡고 분리하여 끌어옵니다.$$이 곳에 코드를 연결합니다.$$이 곳에 블록의 왼쪽 끝을 끼워 넣습니다.\",\n    \"201\": \"오브젝트 선택하기\",\n    \"301\": \"do\",\n    \"302\": \"undo\",\n    \"303\": \"redo\",\n    \"401\": \"그림 수정하기\",\n    \"402\": \"그림 수정 취소하기\",\n    \"403\": \"그림 수정하기\",\n    \"404\": \"그림 수정 취소하기\",\n    \"501\": \"실행하기@@<b>[시작하기]</b>를 누릅니다.\",\n    \"502\": \"정지하기@@<b>[정지하기]</b>를 누릅니다.\",\n    \"601\": \"컨테이너 오브젝트 선택하기\",\n    \"701\": \"모드 바꾸기\",\n    \"702\": \"모양 추가하기@@<b>모양추가</b>를 클릭합니다.\",\n    \"703\": \"소리 추가하기@@<b>소리추가</b>를 클릭합니다.\",\n    \"801\": \"변수 속성창 필터 선택하기\",\n    \"802\": \"변수 추가하기@@<b>[변수 추가]</b>를 클릭합니다.\",\n    \"803\": \"변수 추가하기@@<b>[확인]</b>을 클릭합니다.\",\n    \"804\": \"변수 삭제하기@@이 버튼을 눌러 변수를 삭제합니다.\",\n    \"805\": \"변수 이름 설정\",\n    \"1101\": \"확장 블록 추가하기@@<b>확장 블록 블러오기</b>를 클릭합니다.\"\n};\nLang.Blocks = {\n    \"download_guide\": \"• tải kết Hướng dẫn\",\n    \"dictionary\": \"dictionary\",\n    \"ai_utilize\": \"AI\",\n    \"date_yesterday\": \"yesterday\",\n    \"date_today\": \"today\",\n    \"date_tomorrow\": \"tomorrow\",\n    \"date_after_2_days\": \"After 2 days\",\n    \"date_after_3_days\": \"After 3 days\",\n    \"date_after_4_days\": \"After 4 days\",\n    \"date_after_5_days\": \"After 5 days\",\n    \"date_after_6_days\": \"After 6 days\",\n    \"location_entire\": \"all\",\n    \"location_seoul\": \"Seoul\",\n    \"location_seoul_jongno_gu\": \"Jongno-gu\",\n    \"location_seoul_jung_gu\": \"Jung-gu\",\n    \"location_seoul_yongsan_gu\": \"Yongsan-gu\",\n    \"location_seoul_seongdong_gu\": \"Seongdong-gu\",\n    \"location_seoul_gwangjin_gu\": \"Gwangjin-gu\",\n    \"location_seoul_dongdaemun_gu\": \"Dongdaemun-gu\",\n    \"location_seoul_jungnang_gu\": \"Jungrang-gu\",\n    \"location_seoul_seongbuk_gu\": \"Seongbuk-gu\",\n    \"location_seoul_gangbuk_gu\": \"Gangbuk-gu\",\n    \"location_seoul_dobong_gu\": \"Dobong-gu\",\n    \"location_seoul_nowon_gu\": \"Nowon-gu\",\n    \"location_seoul_eunpyeong_gu\": \"Eunpyeong-gu\",\n    \"location_seoul_seodaemun_gu\": \"Seodaemun-gu\",\n    \"location_seoul_mapo_gu\": \"Mapo-gu\",\n    \"location_seoul_yangcheon_gu\": \"Yangcheon-gu\",\n    \"location_seoul_gangseo_gu\": \"Gangseo-gu\",\n    \"location_seoul_guro_gu\": \"Guro-gu\",\n    \"location_seoul_geumcheon_gu\": \"Geumcheon-gu\",\n    \"location_seoul_yeongdeungpo_gu\": \"Yeongdeungpo-gu\",\n    \"location_seoul_dongjak_gu\": \"Dongjak-gu\",\n    \"location_seoul_gwanak_gu\": \"Gwanak-gu\",\n    \"location_seoul_seocho_gu\": \"Seocho-gu\",\n    \"location_seoul_gangnam_gu\": \"Gangnam-gu\",\n    \"location_seoul_songpa_gu\": \"Songpa-gu\",\n    \"location_seoul_gangdong_gu\": \"Gangdong-gu\",\n    \"location_busan\": \"Busan\",\n    \"location_busan_jung_gu\": \"Jung-gu\",\n    \"location_busan_seo_gu\": \"Seo-gu\",\n    \"location_busan_dong_gu\": \"Dong-gu\",\n    \"location_busan_yeongdo_gu\": \"Yeongdo-gu\",\n    \"location_busan_busanjin_gu\": \"Busanjin-gu\",\n    \"location_busan_dongnae_gu\": \"Dongnae-gu\",\n    \"location_busan_nam_gu\": \"Nam-gu\",\n    \"location_busan_buk_gu\": \"Buk-gu\",\n    \"location_busan_haeundae_gu\": \"Haeundae-gu\",\n    \"location_busan_saha_gu\": \"Saha-gu\",\n    \"location_busan_geumjeong_gu\": \"Geumjeong-gu\",\n    \"location_busan_gangseo_gu\": \"Gangseo-gu\",\n    \"location_busan_yeonje\": \"Yeonje-gu\",\n    \"location_busan_suyeong_gu\": \"Suyoung-gu\",\n    \"location_busan_sasang_gu\": \"Sasang-gu\",\n    \"location_busan_gijang\": \"Gijang-gun\",\n    \"location_daegu\": \"Daegu\",\n    \"location_daegu_jung_gu\": \"Jung-gu\",\n    \"location_daegu_dong_gu\": \"Dong-gu\",\n    \"location_daegu_seo_gu\": \"Seo-gu\",\n    \"location_daegu_nam_gu\": \"Nam-gu\",\n    \"location_daegu_buk_gu\": \"Buk-gu\",\n    \"location_daegu_suseong_gu\": \"Suseong-gu\",\n    \"location_daegu_dalseo_gu\": \"Dalseo-gu\",\n    \"location_daegu_dalseong\": \"Dalseong-gu\",\n    \"location_incheon\": \"Incheon\",\n    \"location_incheon_jung_gu\": \"Jung-gu\",\n    \"location_incheon_dong_gu\": \"Dong-gu\",\n    \"location_incheon_nam_gu\": \"Nam-gu\",\n    \"location_incheon_yeonsu_gu\": \"Yeonsu-gu\",\n    \"location_incheon_namdong_gu\": \"Namdong-gu\",\n    \"location_incheon_bupyeong_gu\": \"Bupyeong-gu\",\n    \"location_incheon_gyeyang_gu\": \"Gyeyang-gu\",\n    \"location_incheon_seo_gu\": \"Seo-gu\",\n    \"location_incheon_ganghwa\": \"Ganghwa-gun\",\n    \"location_incheon_ongjin_gun\": \"Ongjin-gun\",\n    \"location_gwangju\": \"Gwangju\",\n    \"location_gwangju_dong_gu\": \"Dong-gu\",\n    \"location_gwangju_seo_gu\": \"Seo-gu\",\n    \"location_gwangju_nam_gu\": \"Nam-gu\",\n    \"location_gwangju_buk_gu\": \"Buk-gu\",\n    \"location_gwangju_gwangsan_gu\": \"Gwangsan-gu\",\n    \"location_daejeon\": \"Daejeon\",\n    \"location_daejeon_dong_gu\": \"Dong-gu\",\n    \"location_daejeon_jung_gu\": \"Jung-gu\",\n    \"location_daejeon_seo_gu\": \"Seo-gu\",\n    \"location_daejeon_yuseong_gu\": \"Yuseong-gu\",\n    \"location_daejeon_daedeok_gu\": \"Daedeok-gu\",\n    \"location_ulsan\": \"Ulsan\",\n    \"location_ulsan_jung_gu\": \"Jung-gu\",\n    \"location_ulsan_nam_gu\": \"Nam-gu\",\n    \"location_ulsan_dong_gu\": \"Dong-gu\",\n    \"location_ulsan_buk_gu\": \"Buk-gu\",\n    \"location_ulsan_ulju\": \"Ulju-gun\",\n    \"location_sejong\": \"Sejong\",\n    \"location_gyeonggi\": \"Gyeonggi-do\",\n    \"location_gyeonggi_suwon_si\": \"Suwon\",\n    \"location_gyeonggi_seongnam\": \"Seongnam\",\n    \"location_gyeonggi_uijeongbu\": \"Uijeongbu\",\n    \"location_gyeonggi_anyang_si\": \"Anyang\",\n    \"location_gyeonggi_bucheon_si\": \"Bucheon\",\n    \"location_gyeonggi_gwangmyeong_si\": \"Gwangmyeong\",\n    \"location_gyeonggi_pyeongtaek_si\": \"Pyeongtaek\",\n    \"location_gyeonggi_dongducheon_si\": \"Dongducheon\",\n    \"location_gyeonggi_ansan_si\": \"Ansan\",\n    \"location_gyeonggi_goyang_si\": \"Goyang\",\n    \"location_gyeonggi_gwacheon_si\": \"Gwacheon\",\n    \"location_gyeonggi_guri\": \"Guri\",\n    \"location_gyeonggi_namyangju_si\": \"Namyangju\",\n    \"location_gyeonggi_osan\": \"Osan\",\n    \"location_gyeonggi_siheung\": \"Siheung\",\n    \"location_gyeonggi_gunpo_si\": \"Gunpo\",\n    \"location_gyeonggi_uiwang_si\": \"Uiwang\",\n    \"location_gyeonggi_hanam\": \"Hanam\",\n    \"location_gyeonggi_yongin_si\": \"Yongin\",\n    \"location_gyeonggi_paju\": \"Paju\",\n    \"location_gyeonggi_icheon\": \"Icheon\",\n    \"location_gyeonggi_anseong_si\": \"Anseong\",\n    \"location_gyeonggi_gimpo\": \"Gimpo\",\n    \"location_gyeonggi_hwaseong_si\": \"Hwaseong\",\n    \"location_gyeonggi_gwangju\": \"Guangju\",\n    \"location_gyeonggi_yangju_si\": \"Yangju\",\n    \"location_gyeonggi_pocheon\": \"Pocheon\",\n    \"location_gyeonggi_yeoju\": \"Yeoju\",\n    \"location_gyeonggi_yeoncheon_gun\": \"Yeoncheon-gun\",\n    \"location_gyeonggi_gapyeong_gun\": \"Gapyeong-gun\",\n    \"location_gyeonggi_yangpyeong\": \"Yangpyeong-gun\",\n    \"location_gangwon\": \"Gangwon-do\",\n    \"location_gangwon_chuncheon\": \"Chuncheon\",\n    \"location_gangwon_wonju\": \"Wonju\",\n    \"location_gangwon_gangneung_si\": \"Gangneung\",\n    \"location_gangwon_donghae\": \"Donghae\",\n    \"location_gangwon_taebaek_si\": \"Taebaek\",\n    \"location_gangwon_sokcho\": \"Sokcho\",\n    \"location_gangwon_samcheok_si\": \"Samcheok\",\n    \"location_gangwon_hongcheon\": \"Hongcheon-gun\",\n    \"location_gangwon_hoengseong_gun\": \"Hoengseong-gun\",\n    \"location_gangwon_yeongwol_gun\": \"Yeongwol-gun\",\n    \"location_gangwon_pyeongchang\": \"Pyeongchang-gun\",\n    \"location_gangwon_jeongseon\": \"Jeongseon-gun\",\n    \"location_gangwon_cheolwon\": \"Cheorwon-gun\",\n    \"location_gangwon_hwacheon\": \"Hwacheon-gun\",\n    \"location_gangwon_yanggu\": \"Yanggu-gun\",\n    \"location_gangwon_inje\": \"Inje-gun\",\n    \"location_gangwon_goseong\": \"Goseong-gun\",\n    \"location_gangwon_yangyang\": \"Yangyang-gun\",\n    \"location_chungcheongbuk\": \"Chungcheongbuk-do\",\n    \"location_chungcheongbuk_cheongju\": \"Cheongju\",\n    \"location_chungcheongbuk_chungju\": \"Chungju\",\n    \"location_chungcheongbuk_jecheon\": \"Jecheon\",\n    \"location_chungcheongbuk_boeun\": \"Boeun-gun\",\n    \"location_chungcheongbuk_okcheon\": \"Okcheon-gun\",\n    \"location_chungcheongbuk_yeongdong\": \"Yeongdong-gun\",\n    \"location_chungcheongbuk_jeungpyeong\": \"Jeungpyeong-gun\",\n    \"location_chungcheongbuk_jincheon\": \"Jincheon-gun\",\n    \"location_chungcheongbuk_goesan\": \"Goesan-gun\",\n    \"location_chungcheongbuk_eumseong\": \"Negative-gun\",\n    \"location_chungcheongbuk_danyang\": \"Danyang-gun\",\n    \"location_chungcheongnam\": \"Chungcheongnam-do\",\n    \"location_chungcheongnam_cheonan\": \"Cheonan\",\n    \"location_chungcheongnam_gongju\": \"Gongju\",\n    \"location_chungcheongnam_boryeong\": \"Boryeong\",\n    \"location_chungcheongnam_asan\": \"Asan\",\n    \"location_chungcheongnam_seosan\": \"Seosan\",\n    \"location_chungcheongnam_nonsan\": \"Nonsan\",\n    \"location_chungcheongnam_gyeryong\": \"Gyeryong\",\n    \"location_chungcheongnam_dangjin\": \"Dangjin\",\n    \"location_chungcheongnam_geumsan\": \"Geumsan-gun\",\n    \"location_chungcheongnam_buyeo\": \"Buyeo-gun\",\n    \"location_chungcheongnam_seocheon\": \"Seocheon-gun\",\n    \"location_chungcheongnam_cheongyang\": \"Cheongyang-gun\",\n    \"location_chungcheongnam_hongseong\": \"Hongseong-gun\",\n    \"location_chungcheongnam_yesan\": \"Yesan-gun\",\n    \"location_chungcheongnam_taean\": \"Taean-gun\",\n    \"location_jeollabuk\": \"Jeollabuk-do\",\n    \"location_jeollabuk_jeonju\": \"Jeonju\",\n    \"location_jeollabuk_gunsan_si\": \"Gunsan\",\n    \"location_jeollabuk_iksan\": \"Iksan\",\n    \"location_jeollabuk_jeongeup\": \"Jeongeup\",\n    \"location_jeollabuk_namwon\": \"Namwon\",\n    \"location_jeollabuk_gimje_si\": \"Gimje\",\n    \"location_jeollabuk_wanju\": \"Wanju-gun\",\n    \"location_jeollabuk_jinan\": \"Jinan-gun\",\n    \"location_jeollabuk_muju\": \"Muju-gun\",\n    \"location_jeollabuk_jangsu\": \"Jangsu-gun\",\n    \"location_jeollabuk_imsil\": \"Imsil-gun\",\n    \"location_jeollabuk_sunchang\": \"Sunchang-gun\",\n    \"location_jeollabuk_gochang\": \"Gochang-gun\",\n    \"location_jeollabuk_buan\": \"Buan-gun\",\n    \"location_jeollanam\": \"Jeollanam-do\",\n    \"location_jeollanam_mokpo\": \"Mokpo\",\n    \"location_jeollanam_yosu\": \"Yeosu\",\n    \"location_jeollanam_suncheon_si\": \"Suncheon\",\n    \"location_jeollanam_naju\": \"Naju\",\n    \"location_jeollanam_gwangyang_si\": \"Gwangyang\",\n    \"location_jeollanam_damyang\": \"Damyang-gun\",\n    \"location_jeollanam_gokseong\": \"Gokseong-gun\",\n    \"location_jeollanam_gurye\": \"Gurye-gun\",\n    \"location_jeollanam_goheung\": \"Goheung-gun\",\n    \"location_jeollanam_boseong\": \"Boseong-gun\",\n    \"location_jeollanam_hwasun\": \"Hwasun-gun\",\n    \"location_jeollanam_jangheung\": \"Jangheung-gun\",\n    \"location_jeollanam_gangjin\": \"Gangjin-gun\",\n    \"location_jeollanam_haenam\": \"Haenam-gun\",\n    \"location_jeollanam_yeongam\": \"Yeongam-gun\",\n    \"location_jeollanam_jindo\": \"Muan-gun\",\n    \"location_jeollanam_muan\": \"Hampyeong-gun\",\n    \"location_jeollanam_hampyeong\": \"Yeonggwang-gun\",\n    \"location_jeollanam_yeonggwang\": \"Jangseong-gun\",\n    \"location_jeollanam_jangseong\": \"Wando-gun\",\n    \"location_jeollanam_wando\": \"Jindo-gun\",\n    \"location_jeollanam_sinan\": \"Shinan-gun\",\n    \"location_gyeongsangbuk\": \"Gyeongsangbuk-do\",\n    \"location_gyeongsangbuk_pohang_si\": \"Pohang\",\n    \"location_gyeongsangbuk_gyeongju_si\": \"Gyeongju\",\n    \"location_gyeongsangbuk_gimcheon_si\": \"Gimcheon\",\n    \"location_gyeongsangbuk_andong_si\": \"Andong\",\n    \"location_gyeongsangbuk_gumi_si\": \"Gumi\",\n    \"location_gyeongsangbuk_yeongju_si\": \"Yeongju\",\n    \"location_gyeongsangbuk_yeongcheon_si\": \"Yeongcheon\",\n    \"location_gyeongsangbuk_sangju_si\": \"Changzhou\",\n    \"location_gyeongsangbuk_mungyeong_si\": \"Mungyeong\",\n    \"location_gyeongsangbuk_gyeongsan_si\": \"Gyeongsan\",\n    \"location_gyeongsangbuk_gunwi\": \"Gunwi-gun\",\n    \"location_gyeongsangbuk_uiseong\": \"Uiseong-gun\",\n    \"location_gyeongsangbuk_cheongsong\": \"Cheongsong-gun\",\n    \"location_gyeongsangbuk_goryong\": \"Yeongyang-gun\",\n    \"location_gyeongsangbuk_yeongdeok\": \"Yeongdeok-gun\",\n    \"location_gyeongsangbuk_cheongdo\": \"Cheongdo-gun\",\n    \"location_gyeongsangbuk_golyeong\": \"Goryeong-gun\",\n    \"location_gyeongsangbuk_seongju\": \"Seongju-gun\",\n    \"location_gyeongsangbuk_chilgok\": \"Chilgok-gun\",\n    \"location_gyeongsangbuk_yecheon\": \"Yecheon-gun\",\n    \"location_gyeongsangbuk_bonghwa\": \"Bonghwa-gun\",\n    \"location_gyeongsangbuk_uljin\": \"Uljin-gun\",\n    \"location_gyeongsangbuk_ulleung\": \"Ulleung-gun\",\n    \"location_gyeongsangnam\": \"Gyeongsangnam-do\",\n    \"location_gyeongsangnam_changwon_si\": \"Changwon\",\n    \"location_gyeongsangnam_jinju\": \"Jinju\",\n    \"location_gyeongsangnam_tongyeong_si\": \"Tongyeong\",\n    \"location_gyeongsangnam_sacheon_si\": \"Sacheon\",\n    \"location_gyeongsangnam_gimhae_si\": \"Gimhae\",\n    \"location_gyeongsangnam_miryang_si\": \"Miryang\",\n    \"location_gyeongsangnam_geoje_si\": \"Geoje\",\n    \"location_gyeongsangnam_yangsan_si\": \"Yangsan\",\n    \"location_gyeongsangnam_uiryeong\": \"Uiryeong-gun\",\n    \"location_gyeongsangnam_haman\": \"Haman-gun\",\n    \"location_gyeongsangnam_changnyeong\": \"Changnyeong-gun\",\n    \"location_gyeongsangnam_goseong\": \"Goseong-gun\",\n    \"location_gyeongsangnam_namhae\": \"Namhae-gun\",\n    \"location_gyeongsangnam_hadong\": \"Hadong-gun\",\n    \"location_gyeongsangnam_sancheong\": \"Sancheong-gun\",\n    \"location_gyeongsangnam_hamyang\": \"Hamyang-gun\",\n    \"location_gyeongsangnam_geochang\": \"Geochang-gun\",\n    \"location_gyeongsangnam_hapcheon\": \"Hapcheon-gun\",\n    \"location_jeju\": \"Jeju\",\n    \"location_jeju_jeju_si\": \"Jeju\",\n    \"location_jeju_seogwipo\": \"Seogwipo\",\n    \"EXPANSION_WEATHER_sunny\": \"sunny\",\n    \"EXPANSION_WEATHER_partly_cloudy\": \"partly cloudy\",\n    \"EXPANSION_WEATHER_mostly_cloudy\": \"mostly cloudy\",\n    \"EXPANSION_WEATHER_cloudy\": \"cloudy\",\n    \"EXPANSION_WEATHER_rainy\": \"rainy\",\n    \"EXPANSION_WEATHER_sleet\": \"sleet\",\n    \"EXPANSION_WEATHER_snowy\": \"snowy\",\n    \"EXPANSION_WEATHER_finedust_good\": \"good\",\n    \"EXPANSION_WEATHER_finedust_normal\": \"normal\",\n    \"EXPANSION_WEATHER_finedust_bad\": \"bad\",\n    \"EXPANSION_WEATHER_finedust_very_bad\": \"very bad\",\n    \"EXPANSION_WEATHER_lowest_temperature\": \"the lowest temperature(℃)\",\n    \"EXPANSION_WEATHER_highest_temperature\": \"the highest temperature(℃)\",\n    \"EXPANSION_WEATHER_humidity\": \"humidity(%)\",\n    \"EXPANSION_WEATHER_precipitation\": \"precipitation(mm)\",\n    \"EXPANSION_WEATHER_precipitation_probability\": \"precipitation probability(%)\",\n    \"EXPANSION_WEATHER_wind_speed\": \"wind speed(m/s)\",\n    \"EXPANSION_WEATHER_temperature\": \"temperature(℃)\",\n    \"EXPANSION_WEATHER_finedust\": \"concentration of fine dust(㎍)\",\n    \"EXPANSION_FESTIVAL_title\": \"Title\",\n    \"EXPANSION_FESTIVAL_area\": \"area\",\n    \"EXPANSION_FESTIVAL_start_date\": \"start date\",\n    \"EXPANSION_FESTIVAL_end_date\": \"end date\",\n    \"EXPANSION_FESTIVAL_address\": \"address\",\n    \"EXPANSION_FESTIVAL_coordinate\": \"coordinate\",\n    \"EXPANSION_FESTIVAL_overview\": \"overview\",\n    \"EXPANSION_FESTIVAL_homepage\": \"homepage\",\n    \"no_data\": \"No Information\",\n    \"no_sentence\": \"No sentence\",\n    \"sentence_over_20_charactor\": \"Only 20 characters can be entered.\",\n    \"sentence_over_3000_charactor\": \"Only 3000 characters can be entered.\",\n    \"sentence_over_2500_charactor\": \"Only 2500 characters can be entered.\",\n    \"unknown_sentence\": \"Unknown sentence\",\n    \"auto\": \"auto\",\n    \"korean\": \"Korean\",\n    \"english\": \"English\",\n    \"spanish\": \"Spanish\",\n    \"french\": \"French\",\n    \"german\": \"German\",\n    \"russian\": \"Russian\",\n    \"portuguese\": \"Portuguese\",\n    \"hindi\": \"Hindi\",\n    \"japan\": \"japan\",\n    \"thai\": \"Thai\",\n    \"vietnamese\": \"Vietnamese\",\n    \"indonesian\": \"Indonesian\",\n    \"chinese_simplified\": \"Simplified Chinese\",\n    \"chinese_traditional\": \"Traditional Chinese\",\n    \"italian\": \"Italian\",\n    \"behaviorConduct01001\": \"Typhoon\",\n    \"behaviorConduct01002\": \"Flood\",\n    \"behaviorConduct01003\": \"Heavy rain\",\n    \"behaviorConduct01004\": \"Gale\",\n    \"behaviorConduct01005\": \"Heavy snow\",\n    \"behaviorConduct01006\": \"Cold wave\",\n    \"behaviorConduct01007\": \"Storm\",\n    \"behaviorConduct01008\": \"Dust storm\",\n    \"behaviorConduct01009\": \"Heatwave\",\n    \"behaviorConduct01010\": \"Drought\",\n    \"behaviorConduct01011\": \"Earthquake\",\n    \"behaviorConduct01013\": \"Tsunami\",\n    \"behaviorConduct01014\": \"Landslide\",\n    \"behaviorConduct03002\": \"First aid\",\n    \"behaviorConduct03003\": \"CPR\",\n    \"behaviorConduct03004\": \"Fire extinguishers use\",\n    \"behaviorConduct03016\": \"Fireplug use\",\n    \"behaviorConduct03005\": \"Food poisoning\",\n    \"behaviorConduct03006\": \"Climbing safety\",\n    \"behaviorConduct03008\": \"Kidnapping·Missing\",\n    \"behaviorConduct03009\": \"SAE\",\n    \"behaviorConduct03010\": \"School violence\",\n    \"behaviorConduct03011\": \"Domestic Violence\",\n    \"behaviorConduct03012\": \"Detention and abduction\",\n    \"behaviorConduct03013\": \"Traffic Accident\",\n    \"behaviorConduct03014\": \"Elevator accident\",\n    \"behaviorConduct03015\": \"Fine dust\",\n    \"behaviorConduct01001001\": \"Before the typhoon comes\",\n    \"behaviorConduct01001002\": \"When the typhoon warning occurs\",\n    \"behaviorConduct01001003\": \"After the typhoon has passed\",\n    \"behaviorConduct01002002\": \"When the flood forecast occurs\",\n    \"behaviorConduct01002003\": \"When the water is pushed\",\n    \"behaviorConduct01002004\": \"After the water ir removed\",\n    \"behaviorConduct01003002\": \"When the heavy rain forecast occurs\",\n    \"behaviorConduct01003003\": \"When the heavy rain warning occurs\",\n    \"behaviorConduct01003004\": \"After the heavy rain has passed\",\n    \"behaviorConduct01004001\": \"Before the gale comes\",\n    \"behaviorConduct01004002\": \"When the gale occurs\",\n    \"behaviorConduct01005002\": \"Before the heavy snow comes\",\n    \"behaviorConduct01005003\": \"When the heavy snow occurs\",\n    \"behaviorConduct01005004\": \"After the heavy snow has passed\",\n    \"behaviorConduct01006001\": \"Before the cold wave comes\",\n    \"behaviorConduct01006002\": \"When the cold wave occurs\",\n    \"behaviorConduct01007001\": \"When the storm warning occurs\",\n    \"behaviorConduct01007002\": \"Before the storm comes\",\n    \"behaviorConduct01008001\": \"When the dust storm forecast occurs\",\n    \"behaviorConduct01008002\": \"When the dust storm occurs\",\n    \"behaviorConduct01008003\": \"After the dust storm has passed\",\n    \"behaviorConduct01009001\": \"Before the heatwave comes\",\n    \"behaviorConduct01009002\": \"When the heatwave watch occurs\",\n    \"behaviorConduct01010001\": \"When the drought occurs\",\n    \"behaviorConduct01011009\": \"Before the earthquakes comes\",\n    \"behaviorConduct01011010\": \"When the earthquake occurs\",\n    \"behaviorConduct01011012\": \"After the earthquake evacuation\",\n    \"behaviorConduct01013002\": \"Before the tsunami comes\",\n    \"behaviorConduct01013003\": \"When the tsunami occurs\",\n    \"behaviorConduct01014001\": \"When the landslide watch occurs\",\n    \"behaviorConduct03002002\": \"treat burns\",\n    \"behaviorConduct03002003\": \"prevate fever\",\n    \"behaviorConduct03002004\": \"treat when bitten by a snake\",\n    \"behaviorConduct03002005\": \"treat when shot by bee\",\n    \"behaviorConduct03002006\": \"do first aid hyperventilation syndrome\",\n    \"behaviorConduct03003001\": \"do adult CPR\",\n    \"behaviorConduct03003002\": \"do infant CPR\",\n    \"behaviorConduct03003003\": \"use an automatic defibrillator\",\n    \"behaviorConduct03004001\": \"use a powder fire extinguisher\",\n    \"behaviorConduct03016001\": \"use a indoor fire hydrants\",\n    \"behaviorConduct03005001\": \"treat food poisoning\",\n    \"behaviorConduct03006004\": \"climb the mountain safely\",\n    \"behaviorConduct03006005\": \"In the mountain safe camping\",\n    \"behaviorConduct03006002\": \"notify information on a rescue request\",\n    \"behaviorConduct03006003\": \"do first aid in mountain accident\",\n    \"behaviorConduct03008001\": \"prevate kidnapping∙missing\",\n    \"behaviorConduct03009001\": \"prevate harassment\",\n    \"behaviorConduct03010001\": \"prevate school violence\",\n    \"behaviorConduct03011001\": \"prevate domestic violence\",\n    \"behaviorConduct03012001\": \"handle detention∙abduction\",\n    \"behaviorConduct03013002\": \"handle traffic accidents\",\n    \"behaviorConduct03013005\": \"rescue from a vehicle\",\n    \"behaviorConduct03014001\": \"use elevator safely\",\n    \"behaviorConduct03014003\": \"handle elevator malfunction\",\n    \"behaviorConduct03014004\": \"use escalator safely\",\n    \"behaviorConduct03015007\": \"live on fine dusty day\",\n    \"behaviorConduct03015003\": \"live by sector\",\n    \"tts_female\": \"female\",\n    \"tts_male\": \"male\",\n    \"tts_kind\": \"kind\",\n    \"tts_sweet\": \"sweet\",\n    \"tts_echo\": \"echo\",\n    \"tts_mischievous\": \"mischievous\",\n    \"tts_dainty\": \"dainty\",\n    \"tts_veryslow\": \"very slow\",\n    \"tts_slow\": \"slow\",\n    \"tts_normal\": \"normal\",\n    \"tts_fast\": \"fast\",\n    \"tts_veryfast\": \"very fast\",\n    \"tts_verylow\": \"very low\",\n    \"tts_low\": \"low\",\n    \"tts_high\": \"high\",\n    \"tts_veryhigh\": \"very high\",\n    \"ARDUINO\": \"phần cứng\",\n    \"ARDUINO_download_connector\": \"• Download Connector\",\n    \"ARDUINO_open_connector\": \"Open Connector\",\n    \"ARDUINO_download_source\": \"• đăng nhập mã Arduino\",\n    \"ARDUINO_reconnect\": \"kết nối phần cứng\",\n    \"arduino_noti_text\": \"Mobile devices will be\\n    supported later on.\",\n    \"ROBOT_reconnect\": \"Connect Robot\",\n    \"ARDUINO_program\": \"Run the program\",\n    \"ARDUINO_cloud_pc_connector\": \"Connect to Cloud PC\",\n    \"ARDUINO_connected\": \"phần cứng được kết nối\",\n    \"ARDUINO_connect\": \"* Connect hardware\",\n    \"ARDUINO_arduino_get_number_1\": \"Số kết quả của tín hiệu\",\n    \"ARDUINO_arduino_get_number_2\": \"\",\n    \"ARDUINO_arduino_get_sensor_number_0\": \"0\",\n    \"ARDUINO_arduino_get_sensor_number_1\": \"1\",\n    \"ARDUINO_arduino_get_sensor_number_2\": \"2\",\n    \"ARDUINO_arduino_get_sensor_number_3\": \"3\",\n    \"ARDUINO_arduino_get_sensor_number_4\": \"4\",\n    \"ARDUINO_arduino_get_sensor_number_5\": \"5\",\n    \"blacksmith_toggle_on\": \"on\",\n    \"blacksmith_toggle_off\": \"off\",\n    \"blacksmith_lcd_first_line\": \"first\",\n    \"blacksmith_lcd_seconds_line\": \"seconds\",\n    \"BITBRICK_light\": \"light\",\n    \"BITBRICK_IR\": \"IR\",\n    \"BITBRICK_touch\": \"Chạm\",\n    \"BITBRICK_potentiometer\": \"potentiometer\",\n    \"BITBRICK_MIC\": \"MIC\",\n    \"BITBRICK_UserSensor\": \"UserSensor\",\n    \"BITBRICK_UserInput\": \"UserInput\",\n    \"BITBRICK_dc_direction_ccw\": \"CCW\",\n    \"BITBRICK_dc_direction_cw\": \"CW\",\n    \"chocopi_control_event_pressed\": \"pressed\",\n    \"chocopi_control_event_released\": \"released\",\n    \"chocopi_joystick_X\": \"joystick X\",\n    \"chocopi_joystick_Y\": \"joystick Y\",\n    \"chocopi_motion_photogate_event_blocked\": \"blocked\",\n    \"chocopi_motion_photogate_event_unblocked\": \"unblocked\",\n    \"chocopi_motion_photogate_time_blocked\": \"blocked\",\n    \"chocopi_motion_photogate_time_unblocked\": \"unblocked\",\n    \"chocopi_port\": \"P\",\n    \"chocopi_pot\": \"potentiometer\",\n    \"chocopi_touch_event_touch\": \"touched\",\n    \"chocopi_touch_event_untouch\": \"untouched\",\n    \"CODEino_get_sensor_number_0\": \"0\",\n    \"CODEino_get_sensor_number_1\": \"1\",\n    \"CODEino_get_sensor_number_2\": \"2\",\n    \"CODEino_get_sensor_number_3\": \"3\",\n    \"CODEino_get_sensor_number_4\": \"4\",\n    \"CODEino_get_sensor_number_5\": \"5\",\n    \"CODEino_get_sensor_number_6\": \"6\",\n    \"CODEino_sensor_name_0\": \"Âm thanh\",\n    \"CODEino_sensor_name_1\": \"Ánh sáng\",\n    \"CODEino_sensor_name_2\": \"Slide\",\n    \"CODEino_sensor_name_3\": \"Điện trở -A\",\n    \"CODEino_sensor_name_4\": \"Điện trở -B\",\n    \"CODEino_sensor_name_5\": \"Điện trở -C\",\n    \"CODEino_sensor_name_6\": \"Điện trở -D\",\n    \"CODEino_string_1\": \"Giá trị cảm biến\",\n    \"CODEino_string_2\": \" Vận hành\",\n    \"CODEino_string_3\": \"Nhấn nút\",\n    \"CODEino_string_4\": \"Kết nối A\",\n    \"CODEino_string_5\": \"Kết nối B\",\n    \"CODEino_string_6\": \"Kết nối C\",\n    \"CODEino_string_7\": \"Kết nối D\",\n    \"CODEino_string_8\": \" Cảm biến gia tốc 3-trục\",\n    \"CODEino_string_9\": \" Trục giá trị\",\n    \"CODEino_string_10\": \"Âm thanh\",\n    \"CODEino_string_11\": \"Âm thanh lớn\",\n    \"CODEino_string_12\": \"Âm thanh nhỏ\",\n    \"CODEino_string_13\": \"Ánh sáng\",\n    \"CODEino_string_14\": \"Sáng\",\n    \"CODEino_string_15\": \"Tối\",\n    \"CODEino_string_16\": \"Nghiêng trái\",\n    \"CODEino_string_17\": \"Nghiêng phải\",\n    \"CODEino_string_18\": \"Nghiêng ra trước\",\n    \"CODEino_string_19\": \"Nghiêng ra sau\",\n    \"CODEino_string_20\": \"Đảo ngược\",\n    \"CODEino_accelerometer_X\": \"X\",\n    \"CODEino_accelerometer_Y\": \"Y\",\n    \"CODEino_accelerometer_Z\": \"Z\",\n    \"CODEino_led_red\": \"Red\",\n    \"CODEino_led_green\": \"Green\",\n    \"CODEino_led_blue\": \"Blue\",\n    \"iboard_analog_number_0\": \"A0\",\n    \"iboard_analog_number_1\": \"A1\",\n    \"iboard_analog_number_2\": \"A2\",\n    \"iboard_analog_number_3\": \"A3\",\n    \"iboard_analog_number_4\": \"A4\",\n    \"iboard_analog_number_5\": \"A5\",\n    \"iboard_light\": \"Light sensor is \",\n    \"iboard_num_pin_1\": \"LED status\",\n    \"iboard_num_pin_2\": \"switch\",\n    \"iboard_num_pin_3\": \"analogue\",\n    \"iboard_num_pin_4\": \" \",\n    \"iboard_num_pin_5\": \"sensor value\",\n    \"iboard_string_1\": \"on\",\n    \"iboard_string_2\": \"off\",\n    \"iboard_string_3\": \"bright\",\n    \"iboard_string_4\": \"dark\",\n    \"iboard_string_5\": \"pressed\",\n    \"iboard_string_6\": \"opened\",\n    \"iboard_switch\": \"switch \",\n    \"iboard_tilt\": \"Slope sensor status is\",\n    \"dplay_switch\": \"스위치 \",\n    \"dplay_light\": \"Cảm biến ánh sáng\",\n    \"dplay_tilt\": \"Tình trạng cảm biến độ dốc là\",\n    \"dplay_string_1\": \"켜짐\",\n    \"dplay_string_2\": \"꺼짐\",\n    \"dplay_string_3\": \"Sáng\",\n    \"dplay_string_4\": \"Tối\",\n    \"dplay_string_5\": \"Bị nén\",\n    \"dplay_string_6\": \"Bị mở\",\n    \"dplay_num_pin_1\": \"Trạng thái LED\",\n    \"dplay_num_pin_2\": \"Công tắc\",\n    \"dplay_num_pin_3\": \"Analog\",\n    \"dplay_num_pin_4\": \"번 \",\n    \"dplay_num_pin_5\": \"Giá trị cảm biến\",\n    \"dplay_analog_number_0\": \"A0\",\n    \"dplay_analog_number_1\": \"A1\",\n    \"dplay_analog_number_2\": \"A2\",\n    \"dplay_analog_number_3\": \"A3\",\n    \"dplay_analog_number_4\": \"A4\",\n    \"dplay_analog_number_5\": \"A5\",\n    \"ARDUINO_arduino_get_string_1\": \"Chuỗi kết quả của tín hiệu\",\n    \"ARDUINO_arduino_get_string_2\": \"\",\n    \"ARDUINO_arduino_send_1\": \"Gửi tín hiệu\",\n    \"ARDUINO_arduino_send_2\": \"\",\n    \"ARDUINO_num_sensor_value_1\": \"Analog\",\n    \"ARDUINO_num_sensor_value_2\": \"Giá trị cảm biến\",\n    \"ARDUINO_get_digital_value_1\": \"Kỹ thuật số\",\n    \"ARDUINO_num_pin_1\": \"Kỹ thuật số\",\n    \"ARDUINO_num_pin_2\": \"Ghim\",\n    \"ARDUINO_toggle_pwm_1\": \"Kỹ thuật số\",\n    \"ARDUINO_toggle_pwm_2\": \"Ghim\",\n    \"ARDUINO_toggle_pwm_3\": \"\",\n    \"ARDUINO_on\": \"Mở\",\n    \"ARDUINO_convert_scale_1\": \"Map Value\",\n    \"ARDUINO_convert_scale_2\": \"\",\n    \"ARDUINO_convert_scale_3\": \"~\",\n    \"ARDUINO_convert_scale_4\": \"từ\",\n    \"ARDUINO_convert_scale_5\": \"~\",\n    \"ARDUINO_convert_scale_6\": \"\",\n    \"ARDUINO_off\": \"Tắt\",\n    \"EXPANSION\": \"Tính năng\",\n    \"brightness\": \"độ sáng\",\n    \"BRUSH\": \"Chải\",\n    \"BRUSH_brush_erase_all\": \"Xóa hết cọ\",\n    \"BRUSH_change_opacity_1\": \"Thay đổi độ mờ của cọ bằng\",\n    \"BRUSH_change_opacity_2\": \"%\",\n    \"BRUSH_change_thickness_1\": \"Thay đổi độ dày của cọ\",\n    \"BRUSH_change_thickness_2\": \"\",\n    \"BRUSH_set_color_1\": \"Thiết lập màu cọ\",\n    \"BRUSH_set_color_2\": \"\",\n    \"BRUSH_set_opacity_1\": \"Thiết lập độ mờ của cọ thành \",\n    \"BRUSH_set_opacity_2\": \"%\",\n    \"BRUSH_set_random_color\": \"Thiết lập màu cọ ngẫu nhiên\",\n    \"BRUSH_set_thickness_1\": \"Thiết lập độ dày của cọ\",\n    \"BRUSH_set_thickness_2\": \"\",\n    \"BRUSH_stamp\": \"đóng dấu\",\n    \"BRUSH_start_drawing\": \"Bắt đầu vẽ\",\n    \"BRUSH_stop_drawing\": \"Dừng vẽ\",\n    \"CALC\": \"tính toán\",\n    \"CALC_calc_mod_1\": \"Rest of\",\n    \"CALC_calc_mod_2\": \"\",\n    \"CALC_calc_mod_3\": \"\",\n    \"CALC_calc_operation_of_1\": \"\",\n    \"CALC_calc_operation_of_2\": \"của~\",\n    \"CALC_calc_operation_root\": \"căn số\",\n    \"CALC_calc_operation_square\": \"bình phương\",\n    \"CALC_calc_rand_1\": \"Số ngẫu nhiên giữa\",\n    \"CALC_calc_rand_2\": \"và\",\n    \"CALC_calc_rand_3\": \"\",\n    \"CALC_calc_share_1\": \"Quotient of\",\n    \"CALC_calc_share_2\": \"\",\n    \"CALC_calc_share_3\": \"\",\n    \"CALC_coordinate_mouse_1\": \"con chuột\",\n    \"CALC_coordinate_mouse_2\": \"tọa độ\",\n    \"CALC_coordinate_object_1\": \"\",\n    \"CALC_coordinate_object_2\": \"của~\",\n    \"CALC_coordinate_object_3\": \"Coordinate\",\n    \"CALC_distance_something_1\": \"Khoảng cách đến\",\n    \"CALC_distance_something_2\": \"\",\n    \"CALC_get_angle\": \"giá trị góc\",\n    \"CALC_get_date_1\": \"ngày\",\n    \"CALC_get_date_2\": \"\",\n    \"CALC_get_date_day\": \"thứ\",\n    \"CALC_get_date_hour\": \"thời gian(giờ)\",\n    \"CALC_get_date_minute\": \"thời gian(phút)\",\n    \"CALC_get_date_month\": \"tháng\",\n    \"CALC_get_date_second\": \"thời gian(giây)\",\n    \"CALC_get_date_year\": \"năm\",\n    \"CALC_get_sound_duration_1\": \"Chiều dài của\",\n    \"CALC_get_sound_duration_2\": \"âm thanh\",\n    \"CALC_get_timer_value\": \"giá trị đồng hồ bấm giờ\",\n    \"CALC_get_x_coordinate\": \"tọa độ X\",\n    \"CALC_get_y_coordinate\": \"tọa độ Y\",\n    \"CALC_timer_reset\": \"bắt đầu bấm giờ\",\n    \"CALC_timer_visible_1\": \"\",\n    \"CALC_timer_visible_2\": \"bộ đếm thời gian\",\n    \"CALC_timer_visible_show\": \"hiển thị\",\n    \"CALC_timer_visible_hide\": \"ẩn\",\n    \"color\": \"màu\",\n    \"FLOW\": \"Dòng chảy\",\n    \"FLOW__if_1\": \"nếu\",\n    \"FLOW__if_2\": \"thì\",\n    \"FLOW_create_clone_1\": \"Create\",\n    \"FLOW_create_clone_2\": \"bản sao của \",\n    \"FLOW_delete_clone\": \"xóa bản sao\",\n    \"FLOW_delete_clone_all\": \"xóa tất cả bản sao\",\n    \"FLOW_if_else_1\": \"nếu\",\n    \"FLOW_if_else_2\": \"thì\",\n    \"FLOW_if_else_3\": \"nếu không\",\n    \"FLOW_repeat_basic_1\": \"Repeat  \",\n    \"FLOW_repeat_basic_2\": \"lần\",\n    \"FLOW_repeat_basic_errorMsg\": \"lặp lại số lớn hơn 0 hoặc tương đương\",\n    \"FLOW_repeat_inf\": \"lặp lại liên tục\",\n    \"FLOW_restart\": \"khởi động lại dự án\",\n    \"FLOW_stop_object_1\": \"Stop\",\n    \"FLOW_stop_object_2\": \"\",\n    \"FLOW_stop_object_all\": \"tất cả đối tượng\",\n    \"FLOW_stop_object_this_object\": \"cái này\",\n    \"FLOW_stop_object_this_thread\": \"mã này\",\n    \"FLOW_stop_object_other_thread\": \"khối khác của đối tượng này\",\n    \"FLOW_stop_object_other_objects\": \"Other object\",\n    \"FLOW_stop_repeat\": \"dừng lặp lại\",\n    \"FLOW_stop_run\": \"đóng chương trình\",\n    \"FLOW_wait_second_1\": \"Wait\",\n    \"FLOW_wait_second_2\": \"giây\",\n    \"FLOW_wait_until_true_1\": \"Wait until\",\n    \"FLOW_wait_until_true_2\": \"\",\n    \"FLOW_when_clone_start\": \"khi bản sao được tạo\",\n    \"FUNC\": \"Tính năng\",\n    \"ANALYSIS\": \"Phân tích dữ liệu\",\n    \"AI\": \"Trí tuệ nhân tạo\",\n    \"JUDGEMENT\": \"Phán quyết\",\n    \"JUDGEMENT_boolean_and\": \"và\",\n    \"JUDGEMENT_boolean_not_1\": \"không phải là\",\n    \"JUDGEMENT_boolean_not_2\": \"\",\n    \"JUDGEMENT_boolean_or\": \"hoặc\",\n    \"JUDGEMENT_false\": \"sai\",\n    \"JUDGEMENT_is_clicked\": \"nhấn chuột?\",\n    \"JUDGEMENT_is_press_some_key_1\": \"Key\",\n    \"JUDGEMENT_is_press_some_key_2\": \"ấn phím?\",\n    \"JUDGEMENT_reach_something_1\": \"Chạm\",\n    \"JUDGEMENT_reach_something_2\": \"?\",\n    \"JUDGEMENT_true\": \"đúng\",\n    \"JUDGEMENT_is_boost_mode\": \"Is the boost mode on?\",\n    \"LOOKS\": \"nhìn\",\n    \"LOOKS_change_scale_percent_1\": \"thay đổi kích cỡ bằng\",\n    \"LOOKS_change_scale_percent_2\": \"\",\n    \"LOOKS_change_to_next_shape\": \"Change to next\",\n    \"LOOKS_change_to_nth_shape_1\": \"Change shape to\",\n    \"LOOKS_change_to_nth_shape_2\": \"\",\n    \"LOOKS_change_shape_prev\": \"trước\",\n    \"LOOKS_change_shape_next\": \"kế tiếp\",\n    \"LOOKS_change_to_near_shape_1\": \"Change to\",\n    \"LOOKS_change_to_near_shape_2\": \"hình dạng\",\n    \"LOOKS_dialog_1\": \"Say\",\n    \"LOOKS_dialog_2\": \"\",\n    \"LOOKS_dialog_3\": \"\",\n    \"LOOKS_dialog_time_1\": \"Say\",\n    \"LOOKS_dialog_time_2\": \"trong\",\n    \"LOOKS_dialog_time_3\": \"giây\",\n    \"LOOKS_dialog_time_4\": \"\",\n    \"LOOKS_erase_all_effects\": \"xóa tất cả hiệu ứng\",\n    \"LOOKS_flip_x\": \"lật dọc\",\n    \"LOOKS_flip_y\": \"lật ngang\",\n    \"LOOKS_hide\": \"ẩn\",\n    \"LOOKS_remove_dialog\": \"xóa bài nói\",\n    \"LOOKS_set_effect_1\": \"Set\",\n    \"LOOKS_set_effect_2\": \"thiết lập hiệu ứng\",\n    \"LOOKS_set_effect_3\": \"\",\n    \"LOOKS_set_effect_volume_1\": \"Change\",\n    \"LOOKS_set_effect_volume_2\": \"cho hiệu ứng\",\n    \"LOOKS_set_effect_volume_3\": \"\",\n    \"LOOKS_set_object_order_1\": \"go to\",\n    \"LOOKS_set_object_order_2\": \"lớp thứ\",\n    \"LOOKS_set_scale_percent_1\": \"thiết lập kích cỡ thành\",\n    \"LOOKS_set_scale_percent_2\": \"\",\n    \"LOOKS_show\": \"cho xem\",\n    \"mouse_pointer\": \"con trỏ chuột\",\n    \"MOVING\": \"động\",\n    \"MOVING_bounce_wall\": \"nếu ở cuối màn hình, bật ra\",\n    \"MOVING_bounce_when_1\": \"Bounce if reach to the\",\n    \"MOVING_bounce_when_2\": \"\",\n    \"MOVING_flip_arrow_horizontal\": \"lật ngang theo hướng mũi tên\",\n    \"MOVING_flip_arrow_vertical\": \"lật dọc theo hướng mũi tên\",\n    \"MOVING_locate_1\": \"Move to\",\n    \"MOVING_locate_2\": \"\",\n    \"MOVING_locate_time_1\": \"Moving while\",\n    \"MOVING_locate_time_2\": \"di chuyển trong ~ giây đến\",\n    \"MOVING_locate_time_3\": \"\",\n    \"MOVING_locate_x_1\": \"di chuyển đến X:\",\n    \"MOVING_locate_x_2\": \"\",\n    \"MOVING_locate_xy_1\": \"di chuyển đến X:\",\n    \"MOVING_locate_xy_2\": \"Y:\",\n    \"MOVING_locate_xy_3\": \"\",\n    \"MOVING_locate_xy_time_1\": \"Moving while\",\n    \"MOVING_locate_xy_time_2\": \"trong ~ giây x:\",\n    \"MOVING_locate_xy_time_3\": \"y:\",\n    \"MOVING_locate_xy_time_4\": \"\",\n    \"MOVING_locate_y_1\": \"di chuyển đến Y:\",\n    \"MOVING_locate_y_2\": \"\",\n    \"MOVING_move_direction_1\": \"di chuyển\",\n    \"MOVING_move_direction_2\": \"đằng trước\",\n    \"MOVING_move_direction_angle_1\": \"Rotate\",\n    \"MOVING_move_direction_angle_2\": \"và di chuyển\",\n    \"MOVING_move_direction_angle_3\": \"\",\n    \"MOVING_move_x_1\": \"thay đổi X bằng\",\n    \"MOVING_move_x_2\": \"\",\n    \"MOVING_move_xy_time_1\": \"For\",\n    \"MOVING_move_xy_time_2\": \"giây di chuyển đến X:\",\n    \"MOVING_move_xy_time_3\": \"Y:\",\n    \"MOVING_move_xy_time_4\": \"\",\n    \"MOVING_move_y_1\": \"thay đổi Y bằng\",\n    \"MOVING_move_y_2\": \"\",\n    \"MOVING_rotate_by_angle_1\": \"xoay bằng\",\n    \"MOVING_rotate_by_angle_2\": \"độ\",\n    \"MOVING_rotate_by_angle_dropdown_1\": \"Rotate by\",\n    \"MOVING_rotate_by_angle_dropdown_2\": \"độ\",\n    \"MOVING_rotate_by_angle_time_1\": \"xoay trong suốt\",\n    \"MOVING_rotate_by_angle_time_2\": \"~giây\",\n    \"MOVING_rotate_by_angle_time_3\": \"~độ\",\n    \"MOVING_rotate_direction_1\": \"thay đổi phương hướng\",\n    \"MOVING_rotate_direction_2\": \"\",\n    \"MOVING_see_angle_1\": \"thiết lập phương hướng\",\n    \"MOVING_see_angle_2\": \"\",\n    \"MOVING_see_angle_direction_1\": \"thiết lập góc\",\n    \"MOVING_see_angle_direction_2\": \"độ\",\n    \"MOVING_see_angle_object_1\": \"Turn towards\",\n    \"MOVING_see_angle_object_2\": \"\",\n    \"MOVING_see_direction_1\": \"Rotate to the\",\n    \"MOVING_see_direction_2\": \"\",\n    \"MOVING_set_direction_by_angle_1\": \"thiết lập xoay vòng\",\n    \"MOVING_set_direction_by_angle_2\": \"\",\n    \"MOVING_add_direction_by_angle_1\": \"xoay\",\n    \"MOVING_add_direction_by_angle_2\": \"\",\n    \"MOVING_add_direction_by_angle_time_1\": \"\",\n    \"MOVING_add_direction_by_angle_time_2\": \"xoay trong ~giây\",\n    \"MOVING_add_direction_by_angle_time_3\": \"\",\n    \"no_target\": \"Không có mục tiêu\",\n    \"oneself\": \"bản thân\",\n    \"opacity\": \"độ mờ\",\n    \"SCENE\": \"cảnh\",\n    \"SOUND\": \"âm thanh\",\n    \"SOUND_sound_silent_all\": \"dừng tất cả âm thanh\",\n    \"SOUND_sound_something_1\": \"mở\",\n    \"SOUND_sound_something_2\": \"âm thanh\",\n    \"SOUND_sound_something_second_1\": \"mở\",\n    \"SOUND_sound_something_second_2\": \"sound for\",\n    \"SOUND_sound_something_second_3\": \"giây\",\n    \"SOUND_sound_something_second_wait_1\": \"mở\",\n    \"SOUND_sound_something_second_wait_2\": \"Sound for\",\n    \"SOUND_sound_something_second_wait_3\": \"chờ trong~ giây\",\n    \"SOUND_sound_something_wait_1\": \"mở\",\n    \"SOUND_sound_something_wait_2\": \"mở và chờ\",\n    \"SOUND_sound_volume_change_1\": \"thay đổi âm lượng bằng\",\n    \"SOUND_sound_volume_change_2\": \"%\",\n    \"SOUND_sound_volume_set_1\": \"thiết lập âm lượng bằng\",\n    \"SOUND_sound_volume_set_2\": \"%\",\n    \"speak\": \"nói\",\n    \"think\": \"Think\",\n    \"START\": \"bắt đầu\",\n    \"START_add_message\": \"Add a message\",\n    \"START_delete_message\": \"Remove a message\",\n    \"START_message_cast\": \"Send message\",\n    \"START_message_cast_1\": \"Send\",\n    \"START_message_cast_2\": \"tin nhắn\",\n    \"START_message_cast_wait\": \"message and wait\",\n    \"START_message_send_wait_1\": \"Send\",\n    \"START_message_send_wait_2\": \"gửi tin nhắn và chờ\",\n    \"START_mouse_click_cancled\": \"khi thả nhấp chuột\",\n    \"START_mouse_clicked\": \"khi nhấp chuột\",\n    \"START_press_some_key_1\": \"When key\",\n    \"START_press_some_key_2\": \"ấn phím\",\n    \"START_press_some_key_down\": \"xuống\",\n    \"START_press_some_key_enter\": \"bắt đầu\",\n    \"START_press_some_key_left\": \"trái\",\n    \"START_press_some_key_right\": \"phải\",\n    \"START_press_some_key_space\": \"thanh cách chữ\",\n    \"START_press_some_key_up\": \"lên\",\n    \"START_when_message_cast\": \"When message received\",\n    \"START_when_message_cast_1\": \"When\",\n    \"START_when_message_cast_2\": \"nhận tin nhắn\",\n    \"START_when_object_click\": \"khi nhấp chuột vào đối tượng\",\n    \"START_when_object_click_canceled\": \"khi nhấp chuột ra khỏi đối  tượng\",\n    \"START_when_run_button_click\": \"khi chạy\",\n    \"START_when_scene_start\": \"When scene was started\",\n    \"START_when_some_key_click\": \"khi ấn phím\",\n    \"TEXT\": \"Text\",\n    \"TEXT_text\": \"Entry\",\n    \"TEXT_text_append_1\": \"After writing that\",\n    \"TEXT_text_append_2\": \"\",\n    \"TEXT_text_flush\": \"loại bỏ tất cả văn bản\",\n    \"TEXT_text_prepend_1\": \"Add\",\n    \"TEXT_text_prepend_2\": \"trước đó\",\n    \"TEXT_text_write_1\": \"Writing that\",\n    \"TEXT_text_write_2\": \"\",\n    \"VARIABLE\": \"biến số\",\n    \"VARIABLE_add_value_to_list\": \"\",\n    \"VARIABLE_add_value_to_list_1\": \"add\",\n    \"VARIABLE_add_value_to_list_2\": \"danh sách\",\n    \"VARIABLE_add_value_to_list_3\": \"\",\n    \"VARIABLE_ask_and_wait_1\": \"Ask\",\n    \"VARIABLE_ask_and_wait_2\": \"và chờ\",\n    \"VARIABLE_change_value_list_index\": \"\",\n    \"VARIABLE_change_value_list_index_1\": \"change\",\n    \"VARIABLE_change_value_list_index_3\": \"hạng mục thứ ~\",\n    \"VARIABLE_change_value_list_index_2\": \"\",\n    \"VARIABLE_change_value_list_index_4\": \"\",\n    \"VARIABLE_change_variable\": \"Adding variable\",\n    \"VARIABLE_change_variable_1\": \"Plus to\",\n    \"VARIABLE_change_variable_2\": \"bằng\",\n    \"VARIABLE_change_variable_3\": \"\",\n    \"VARIABLE_change_variable_name\": \"Rename variable\",\n    \"VARIABLE_combine_something_1\": \"Tham gia\",\n    \"VARIABLE_combine_something_2\": \"\",\n    \"VARIABLE_combine_something_3\": \"\",\n    \"VARIABLE_get_canvas_input_value\": \"trả lời\",\n    \"VARIABLE_get_variable\": \"Value of variable\",\n    \"VARIABLE_get_variable_1\": \"giá trị\",\n    \"VARIABLE_get_variable_2\": \"\",\n    \"VARIABLE_get_y\": \"tọa độ Y\",\n    \"VARIABLE_hide_list\": \"\",\n    \"VARIABLE_hide_list_1\": \"ẩn danh sách\",\n    \"VARIABLE_hide_list_2\": \"\",\n    \"VARIABLE_hide_variable\": \"Hide variable\",\n    \"VARIABLE_hide_variable_1\": \"ẩn biến số\",\n    \"VARIABLE_hide_variable_2\": \"giá trị\",\n    \"VARIABLE_insert_value_to_list\": \"\",\n    \"VARIABLE_insert_value_to_list_1\": \"insert\",\n    \"VARIABLE_insert_value_to_list_2\": \"đến\",\n    \"VARIABLE_insert_value_to_list_3\": \"\",\n    \"VARIABLE_insert_value_to_list_4\": \"vị trí thứ ~\",\n    \"VARIABLE_length_of_list\": \"\",\n    \"VARIABLE_length_of_list_1\": \"Chiều dài của\",\n    \"VARIABLE_length_of_list_2\": \"\",\n    \"VARIABLE_list\": \"\",\n    \"VARIABLE_make_variable\": \"Make variable\",\n    \"VARIABLE_list_option_first\": \"đầu tiên\",\n    \"VARIABLE_list_option_last\": \"cuối cùng\",\n    \"VARIABLE_list_option_random\": \"ngẫu nhiên\",\n    \"VARIABLE_remove_value_from_list\": \"\",\n    \"VARIABLE_remove_value_from_list_1\": \"remove\",\n    \"VARIABLE_remove_value_from_list_2\": \"từ hạng mục thứ ~\",\n    \"VARIABLE_remove_value_from_list_3\": \"\",\n    \"VARIABLE_remove_variable\": \"Remove variable\",\n    \"VARIABLE_set_variable\": \"Set variable\",\n    \"VARIABLE_set_variable_1\": \"Set\",\n    \"VARIABLE_set_variable_2\": \"để\",\n    \"VARIABLE_set_variable_3\": \"\",\n    \"VARIABLE_show_list\": \"\",\n    \"VARIABLE_show_list_1\": \"hiển thị danh sách\",\n    \"VARIABLE_show_list_2\": \"\",\n    \"VARIABLE_show_variable\": \"Show variable\",\n    \"VARIABLE_show_variable_1\": \"hiển thị biến số\",\n    \"VARIABLE_show_variable_2\": \"giá trị\",\n    \"VARIABLE_value_of_index_from_list\": \"\",\n    \"VARIABLE_value_of_index_from_list_1\": \"value of\",\n    \"VARIABLE_value_of_index_from_list_2\": \"\",\n    \"VARIABLE_value_of_index_from_list_3\": \"hạng mục thứ ~\",\n    \"HAMSTER_hand_found\": \"tìm tay?\",\n    \"HAMSTER_sensor_left_proximity\": \"left proximity\",\n    \"HAMSTER_sensor_right_proximity\": \"right proximity\",\n    \"HAMSTER_sensor_left_floor\": \"left floor\",\n    \"HAMSTER_sensor_right_floor\": \"right floor\",\n    \"HAMSTER_sensor_acceleration_x\": \"x acceleration\",\n    \"HAMSTER_sensor_acceleration_y\": \"y acceleration\",\n    \"HAMSTER_sensor_acceleration_z\": \"z acceleration\",\n    \"HAMSTER_sensor_light\": \"độ sáng\",\n    \"HAMSTER_sensor_temperature\": \"nhiệt độ\",\n    \"HAMSTER_sensor_signal_strength\": \"signal strength\",\n    \"HAMSTER_sensor_input_a\": \"input A\",\n    \"HAMSTER_sensor_input_b\": \"input B\",\n    \"HAMSTER_move_forward_once\": \"di chuyển một lần về phía trước trên bảng\",\n    \"HAMSTER_turn_once_1\": \"mở\",\n    \"HAMSTER_turn_once_2\": \"một lần trên bảng\",\n    \"HAMSTER_turn_once_left\": \"left\",\n    \"HAMSTER_turn_right\": \"right\",\n    \"HAMSTER_move_forward\": \"Di chuyển về phía trước\",\n    \"HAMSTER_move_backward\": \"Di chuyển về phía sau\",\n    \"HAMSTER_turn_around_1\": \"turn\",\n    \"HAMSTER_turn_around_2\": \"\",\n    \"HAMSTER_move_forward_for_secs_1\": \"di chuyển về phía trước\",\n    \"HAMSTER_move_forward_for_secs_2\": \"giây\",\n    \"HAMSTER_move_backward_for_secs_1\": \"di chuyển về phía sau\",\n    \"HAMSTER_move_backward_for_secs_2\": \"giây\",\n    \"HAMSTER_turn_for_secs_1\": \"turn\",\n    \"HAMSTER_turn_for_secs_2\": \"cho\",\n    \"HAMSTER_turn_for_secs_3\": \"giây\",\n    \"HAMSTER_change_both_wheels_by_1\": \"thay đổi bánh xe bên trái\",\n    \"HAMSTER_change_both_wheels_by_2\": \"phải:\",\n    \"HAMSTER_change_both_wheels_by_3\": \"\",\n    \"HAMSTER_set_both_wheels_to_1\": \"thiết lập bánh xe bên trái\",\n    \"HAMSTER_set_both_wheels_to_2\": \"phải:\",\n    \"HAMSTER_set_both_wheels_to_3\": \"\",\n    \"HAMSTER_change_wheel_by_1\": \"change\",\n    \"HAMSTER_change_wheel_by_2\": \"bánh xe bằng\",\n    \"HAMSTER_change_wheel_by_3\": \"\",\n    \"HAMSTER_left_wheel\": \"left\",\n    \"HAMSTER_right_wheel\": \"right\",\n    \"HAMSTER_both_wheels\": \"both\",\n    \"HAMSTER_set_wheel_to_1\": \"set\",\n    \"HAMSTER_set_wheel_to_2\": \"bánh xe để\",\n    \"HAMSTER_set_wheel_to_3\": \"\",\n    \"HAMSTER_follow_line_using_1\": \"follow\",\n    \"HAMSTER_follow_line_using_2\": \"sử dụng dây\",\n    \"HAMSTER_follow_line_using_3\": \"cảm biến sàn\",\n    \"HAMSTER_left_floor_sensor\": \"left\",\n    \"HAMSTER_right_floor_sensor\": \"right\",\n    \"HAMSTER_both_floor_sensors\": \"both\",\n    \"HAMSTER_follow_line_until_1\": \"follow\",\n    \"HAMSTER_follow_line_until_2\": \"đến con đường\",\n    \"HAMSTER_follow_line_until_3\": \"chỗ giao nhau\",\n    \"HAMSTER_left_intersection\": \"left\",\n    \"HAMSTER_right_intersection\": \"right\",\n    \"HAMSTER_front_intersection\": \"front\",\n    \"HAMSTER_rear_intersection\": \"rear\",\n    \"HAMSTER_set_following_speed_to_1\": \"thiết lập tốc độ sau\",\n    \"HAMSTER_set_following_speed_to_2\": \"\",\n    \"HAMSTER_front\": \"phía trước\",\n    \"HAMSTER_rear\": \"phía sau\",\n    \"HAMSTER_stop\": \"dừng lại\",\n    \"HAMSTER_set_led_to_1\": \"set\",\n    \"HAMSTER_set_led_to_2\": \"đèn Led\",\n    \"HAMSTER_set_led_to_3\": \"\",\n    \"HAMSTER_left_led\": \"left\",\n    \"HAMSTER_right_led\": \"right\",\n    \"HAMSTER_both_leds\": \"both\",\n    \"HAMSTER_clear_led_1\": \"clear\",\n    \"HAMSTER_clear_led_2\": \"led\",\n    \"HAMSTER_color_cyan\": \"xanh da trời\",\n    \"HAMSTER_color_magenta\": \"tím\",\n    \"HAMSTER_color_black\": \"màu đen\",\n    \"HAMSTER_color_white\": \"white\",\n    \"HAMSTER_color_red\": \"red\",\n    \"HAMSTER_color_yellow\": \"yellow\",\n    \"HAMSTER_color_green\": \"green\",\n    \"HAMSTER_color_blue\": \"blue\",\n    \"HAMSTER_beep\": \"tiếng bíp bíp\",\n    \"HAMSTER_change_buzzer_by_1\": \"thay đổi tiếng chuông bằng\",\n    \"HAMSTER_change_buzzer_by_2\": \"\",\n    \"HAMSTER_set_buzzer_to_1\": \"thiết lập tiếng chuông bằng\",\n    \"HAMSTER_set_buzzer_to_2\": \"\",\n    \"HAMSTER_clear_buzzer\": \"xóa chuông\",\n    \"HAMSTER_play_note_for_1\": \"play note\",\n    \"HAMSTER_play_note_for_2\": \"\",\n    \"HAMSTER_play_note_for_3\": \"cho\",\n    \"HAMSTER_play_note_for_4\": \"nhịp điệu\",\n    \"HAMSTER_rest_for_1\": \"rest for\",\n    \"HAMSTER_rest_for_2\": \"nhịp điệu\",\n    \"HAMSTER_change_tempo_by_1\": \"thay đổi nhịp độ bằng\",\n    \"HAMSTER_change_tempo_by_2\": \"\",\n    \"HAMSTER_set_tempo_to_1\": \"thiết lập nhịp độ bằng\",\n    \"HAMSTER_set_tempo_to_2\": \"bpm\",\n    \"HAMSTER_set_port_to_1\": \"thiết lập cổng\",\n    \"HAMSTER_set_port_to_2\": \"đến\",\n    \"HAMSTER_set_port_to_3\": \"\",\n    \"HAMSTER_change_output_by_1\": \"thay đổi đầu ra\",\n    \"HAMSTER_change_output_by_2\": \"bằng\",\n    \"HAMSTER_change_output_by_3\": \"\",\n    \"HAMSTER_set_output_to_1\": \"thiết lập đầu ra\",\n    \"HAMSTER_set_output_to_2\": \"bằng\",\n    \"HAMSTER_set_output_to_3\": \"\",\n    \"HAMSTER_port_a\": \"A\",\n    \"HAMSTER_port_b\": \"B\",\n    \"HAMSTER_port_ab\": \"A và B\",\n    \"HAMSTER_analog_input\": \"đầu vào analog\",\n    \"HAMSTER_digital_input\": \"đầu vào kỹ thuật số\",\n    \"HAMSTER_servo_output\": \"đầu ra servo\",\n    \"HAMSTER_pwm_output\": \"đầu ra PWM\",\n    \"HAMSTER_digital_output\": \"đầu ra kỹ thuật số\",\n    \"ROBOID_acceleration_x\": \"x acceleration\",\n    \"ROBOID_acceleration_y\": \"y acceleration\",\n    \"ROBOID_acceleration_z\": \"z acceleration\",\n    \"ROBOID_back\": \"back\",\n    \"ROBOID_both\": \"both\",\n    \"ROBOID_button\": \"button\",\n    \"ROBOID_buzzer\": \"buzzer\",\n    \"ROBOID_clicked\": \"clicked\",\n    \"ROBOID_color_any\": \"any color\",\n    \"ROBOID_color_black\": \"black\",\n    \"ROBOID_color_blue\": \"blue\",\n    \"ROBOID_color_green\": \"green\",\n    \"ROBOID_color_number\": \"color number\",\n    \"ROBOID_color_orange\": \"orange\",\n    \"ROBOID_color_pattern\": \"color pattern\",\n    \"ROBOID_color_purple\": \"purple\",\n    \"ROBOID_color_red\": \"red\",\n    \"ROBOID_color_sky_blue\": \"sky blue\",\n    \"ROBOID_color_violet\": \"violet\",\n    \"ROBOID_color_white\": \"white\",\n    \"ROBOID_color_yellow\": \"yellow\",\n    \"ROBOID_double_clicked\": \"double-clicked\",\n    \"ROBOID_floor\": \"floor\",\n    \"ROBOID_head\": \"head\",\n    \"ROBOID_head_color\": \"head color\",\n    \"ROBOID_left\": \"left\",\n    \"ROBOID_left_wheel\": \"left wheel\",\n    \"ROBOID_long_pressed\": \"long-pressed\",\n    \"ROBOID_note\": \"note\",\n    \"ROBOID_right\": \"right\",\n    \"ROBOID_right_wheel\": \"right wheel\",\n    \"ROBOID_sound_beep\": \"beep\",\n    \"ROBOID_sound_birthday\": \"birthday\",\n    \"ROBOID_sound_dibidibidip\": \"dibidibidip\",\n    \"ROBOID_sound_engine\": \"engine\",\n    \"ROBOID_sound_good_job\": \"good job\",\n    \"ROBOID_sound_march\": \"march\",\n    \"ROBOID_sound_random_beep\": \"random beep\",\n    \"ROBOID_sound_robot\": \"robot\",\n    \"ROBOID_sound_siren\": \"siren\",\n    \"ROBOID_tail\": \"tail\",\n    \"ROBOID_unit_cm\": \"cm\",\n    \"ROBOID_unit_deg\": \"degrees\",\n    \"ROBOID_unit_pulse\": \"pulses\",\n    \"ROBOID_unit_sec\": \"seconds\",\n    \"ALBERT_hand_found\": \"Tìm tay?\",\n    \"ALBERT_is_oid_1\": \"oid is\",\n    \"ALBERT_is_oid_2\": \"\",\n    \"ALBERT_is_oid_3\": \"?\",\n    \"ALBERT_front_oid\": \"front\",\n    \"ALBERT_back_oid\": \"back\",\n    \"ALBERT_sensor_left_proximity\": \"left proximity\",\n    \"ALBERT_sensor_right_proximity\": \"right proximity\",\n    \"ALBERT_sensor_acceleration_x\": \"x acceleration\",\n    \"ALBERT_sensor_acceleration_y\": \"y acceleration\",\n    \"ALBERT_sensor_acceleration_z\": \"z acceleration\",\n    \"ALBERT_sensor_light\": \"Độ sáng\",\n    \"ALBERT_sensor_temperature\": \"temperature\",\n    \"ALBERT_sensor_battery\": \"Pin\",\n    \"ALBERT_sensor_signal_strength\": \"signal strength\",\n    \"ALBERT_sensor_front_oid\": \"front oid\",\n    \"ALBERT_sensor_back_oid\": \"back oid\",\n    \"ALBERT_sensor_position_x\": \"x position\",\n    \"ALBERT_sensor_position_y\": \"y position\",\n    \"ALBERT_sensor_orientation\": \"Phương hướng\",\n    \"ALBERT_move_forward\": \"move forward\",\n    \"ALBERT_move_backward\": \"move backward\",\n    \"ALBERT_turn_around_1\": \"turn\",\n    \"ALBERT_turn_around_2\": \"\",\n    \"ALBERT_move_forward_for_secs_1\": \"Di chuyển về phía trước trong \",\n    \"ALBERT_move_forward_for_secs_2\": \"Giây\",\n    \"ALBERT_move_backward_for_secs_1\": \"Di chuyển về phía sau trong \",\n    \"ALBERT_move_backward_for_secs_2\": \"Giây\",\n    \"ALBERT_turn_for_secs_1\": \"turn\",\n    \"ALBERT_turn_for_secs_2\": \"Quay sang\",\n    \"ALBERT_turn_for_secs_3\": \"Giây\",\n    \"ALBERT_turn_left\": \"left\",\n    \"ALBERT_turn_right\": \"right\",\n    \"ALBERT_change_both_wheels_by_1\": \"Thay thế bằng bánh xe bên trái:\",\n    \"ALBERT_change_both_wheels_by_2\": \"Bên phải:\",\n    \"ALBERT_change_both_wheels_by_3\": \"\",\n    \"ALBERT_left_wheel\": \"left\",\n    \"ALBERT_right_wheel\": \"right\",\n    \"ALBERT_both_wheels\": \"both\",\n    \"ALBERT_set_both_wheels_to_1\": \"Thiết lập bánh xe bên trái:\",\n    \"ALBERT_set_both_wheels_to_2\": \"Bên phải:\",\n    \"ALBERT_set_both_wheels_to_3\": \"\",\n    \"ALBERT_change_wheel_by_1\": \"change\",\n    \"ALBERT_change_wheel_by_2\": \"Thay thế bánh xe bằng\",\n    \"ALBERT_change_wheel_by_3\": \"\",\n    \"ALBERT_set_wheel_to_1\": \"set\",\n    \"ALBERT_set_wheel_to_2\": \"Thiết lập bánh xe\",\n    \"ALBERT_set_wheel_to_3\": \"\",\n    \"ALBERT_stop\": \"Dừng lại\",\n    \"ALBERT_set_board_size_to_1\": \"set board size to width:\",\n    \"ALBERT_set_board_size_to_2\": \"height:\",\n    \"ALBERT_set_board_size_to_3\": \"\",\n    \"ALBERT_move_to_x_y_1\": \"move to x:\",\n    \"ALBERT_move_to_x_y_2\": \"y:\",\n    \"ALBERT_move_to_x_y_3\": \"on board\",\n    \"ALBERT_set_orientation_to_1\": \"set orientation to\",\n    \"ALBERT_set_orientation_to_2\": \"degrees on board\",\n    \"ALBERT_set_eye_to_1\": \"set\",\n    \"ALBERT_set_eye_to_2\": \"Mắt\",\n    \"ALBERT_set_eye_to_3\": \"\",\n    \"ALBERT_left_eye\": \"left\",\n    \"ALBERT_right_eye\": \"right\",\n    \"ALBERT_both_eyes\": \"both\",\n    \"ALBERT_clear_eye_1\": \"clear\",\n    \"ALBERT_clear_eye_2\": \"Mắt\",\n    \"ALBERT_body_led_1\": \"\",\n    \"ALBERT_body_led_2\": \"body led\",\n    \"ALBERT_front_led_1\": \"\",\n    \"ALBERT_front_led_2\": \"front led\",\n    \"ALBERT_color_cyan\": \"Xanh da trời\",\n    \"ALBERT_color_magenta\": \"Tím\",\n    \"ALBERT_color_white\": \"white\",\n    \"ALBERT_color_red\": \"red\",\n    \"ALBERT_color_yellow\": \"yellow\",\n    \"ALBERT_color_green\": \"green\",\n    \"ALBERT_color_blue\": \"blue\",\n    \"ALBERT_note_c\": \"C\",\n    \"ALBERT_note_d\": \"D\",\n    \"ALBERT_note_e\": \"E\",\n    \"ALBERT_note_f\": \"F\",\n    \"ALBERT_note_g\": \"G\",\n    \"ALBERT_note_a\": \"A\",\n    \"ALBERT_note_b\": \"B\",\n    \"ALBERT_turn_body_led_1\": \"turn\",\n    \"ALBERT_turn_body_led_2\": \"body led\",\n    \"ALBERT_turn_front_led_1\": \"turn\",\n    \"ALBERT_turn_front_led_2\": \"front led\",\n    \"ALBERT_turn_on\": \"on\",\n    \"ALBERT_turn_off\": \"off\",\n    \"ALBERT_beep\": \"Tiếng bíp bíp\",\n    \"ALBERT_change_buzzer_by_1\": \"Đổi tiếng chuông bằng\",\n    \"ALBERT_change_buzzer_by_2\": \"\",\n    \"ALBERT_set_buzzer_to_1\": \"Thiết lập tiếng chuông\",\n    \"ALBERT_set_buzzer_to_2\": \"\",\n    \"ALBERT_clear_buzzer\": \"Tắt chuông\",\n    \"ALBERT_play_note_for_1\": \"play note\",\n    \"ALBERT_play_note_for_2\": \"',\",\n    \"ALBERT_play_note_for_3\": \"Nốt\",\n    \"ALBERT_play_note_for_4\": \"Nhịp\",\n    \"ALBERT_rest_for_1\": \"rest for\",\n    \"ALBERT_rest_for_2\": \"Nhịp\",\n    \"ALBERT_change_tempo_by_1\": \"Thay đổi nhịp độ bằng ~\",\n    \"ALBERT_change_tempo_by_2\": \"\",\n    \"ALBERT_set_tempo_to_1\": \"Thiết lập nhịp độ thành\",\n    \"ALBERT_set_tempo_to_2\": \"bpm\",\n    \"VARIABLE_variable\": \"biến số\",\n    \"wall\": \"tường\",\n    \"robotis_common_case_01\": \"-\",\n    \"robotis_common_set\": \"dữ liệu đầu ra\",\n    \"robotis_common_value\": \"giá trị\",\n    \"robotis_common_clockwhise\": \"chiều kim đồng hồ\",\n    \"robotis_common_counter_clockwhise\": \"ngược chiều kim đồng hồ\",\n    \"robotis_common_wheel_mode\": \"chế độ bánh xe\",\n    \"robotis_common_joint_mode\": \"chế độ khớp\",\n    \"robotis_common_red_color\": \"đỏ\",\n    \"robotis_common_green_color\": \"xanh lá cây\",\n    \"robotis_common_blue_color\": \"xanh dương\",\n    \"robotis_common_on\": \"bật\",\n    \"robotis_common_off\": \"tắt\",\n    \"robotis_common_cm\": \"bộ điều khiển\",\n    \"robotis_common_port_1\": \"cổng 1\",\n    \"robotis_common_port_2\": \"cổng 2\",\n    \"robotis_common_port_3\": \"cổng 3\",\n    \"robotis_common_port_4\": \"cổng 4\",\n    \"robotis_common_port_5\": \"cổng 5\",\n    \"robotis_common_port_6\": \"cổng 6\",\n    \"robotis_common_play_buzzer\": \"biểu diễn\",\n    \"robotis_common_play_motion\": \"thực hiện\",\n    \"robotis_common_motion\": \"chuyển động \",\n    \"robotis_common_index_number\": \"số\",\n    \"robotis_common_left\": \"Bên trái\",\n    \"robotis_common_right\": \"Phải\",\n    \"robotis_common_minute\": \"phút\",\n    \"robotis_cm_custom\": \"nhập địa chỉ\",\n    \"robotis_cm_spring_left\": \"cảm biến tiếp xúc trái\",\n    \"robotis_cm_spring_right\": \"cảm biến tiếp xúc phải\",\n    \"robotis_cm_led_left\": \"LED trái\",\n    \"robotis_cm_led_right\": \"LED phải\",\n    \"robotis_cm_led_both\": \"LED hai bên\",\n    \"robotis_cm_switch\": \"trạng thái nút chọn\",\n    \"robotis_cm_user_button\": \"tình trạng nút của người sử dụng\",\n    \"robotis_cm_sound_detected\": \"số cuối cùng phát hiện âm thanh\",\n    \"robotis_cm_sound_detecting\": \"số thời gian thực phát hiện âm thanh\",\n    \"robotis_cm_ir_left\": \"cảm biến hồng ngoại trái\",\n    \"robotis_cm_ir_right\": \"cảm biến hồng ngoại phải\",\n    \"robotis_cm_calibration_left\": \"giá trị định chuẩn cảm biến hồng ngoại trái\",\n    \"robotis_cm_calibration_right\": \"giá trị định chuẩn cảm biến hồng ngoại phải\",\n    \"robotis_cm_clear_sound_detected\": \"khởi tạo số cuối cùng phát hiện âm thanh\",\n    \"robotis_cm_buzzer_index\": \"chỉ số thang âm\",\n    \"robotis_cm_buzzer_melody\": \"giai điệu\",\n    \"robotis_cm_led_1\": \"LED 1\",\n    \"robotis_cm_led_4\": \"LED 4\",\n    \"robotis_aux_servo_position\": \"vị trí động cơ servo\",\n    \"robotis_aux_ir\": \"cảm biến hồng ngoại\",\n    \"robotis_aux_touch\": \"liên hệ cảm biến\",\n    \"robotis_aux_brightness\": \"CDS\",\n    \"robotis_aux_hydro_themo_humidity\": \"cảm biến nhiệt độ-độ ẩm (độ ẩm)\",\n    \"robotis_aux_hydro_themo_temper\": \"cảm biến nhiệt độ-độ ẩm (nhiệt độ)\",\n    \"robotis_aux_temperature\": \"cảm biến nhiệt độ\",\n    \"robotis_aux_ultrasonic\": \"cảm biến siêu âm\",\n    \"robotis_aux_magnetic\": \"cảm biến từ trường\",\n    \"robotis_aux_motion_detection\": \"bộ dò chuyển động\",\n    \"robotis_aux_color\": \"cảm biến màu sắc\",\n    \"robotis_aux_custom\": \"thiết bị người dùng\",\n    \"robotis_carCont_aux_motor_speed_1\": \"tốc độ của động cơ giảm tốc\",\n    \"robotis_carCont_aux_motor_speed_2\": \"giá trị đầu ra\",\n    \"robotis_carCont_calibration_1\": \"giá trị định chuẩn cảm biến hồng ngoại \",\n    \"robotis_openCM70_aux_motor_speed_1\": \"tốc độ của động cơ giảm tốc\",\n    \"robotis_openCM70_aux_motor_speed_2\": \"thiết lập\",\n    \"robotis_openCM70_aux_servo_mode_1\": \"chế độ động cơ servo\",\n    \"robotis_openCM70_aux_servo_speed_1\": \"tốc độ động cơ servo\",\n    \"robotis_openCM70_aux_servo_speed_2\": \"dữ liệu đầu ra\",\n    \"robotis_openCM70_aux_servo_position_1\": \"vị trí động cơ servo\",\n    \"robotis_openCM70_aux_led_module_1\": \"mô-đun LED\",\n    \"robotis_openCM70_aux_custom_1\": \"thiết bị người dùng\",\n    \"XBOT_digital\": \"kỹ thuật số\",\n    \"XBOT_D2_digitalInput\": \"đầu vào kỹ thuật số D2\",\n    \"XBOT_D3_digitalInput\": \"đầu vào kỹ thuật số D3\",\n    \"XBOT_D11_digitalInput\": \"đầu vào kỹ thuật số D11\",\n    \"XBOT_analog\": \"Analog\",\n    \"XBOT_CDS\": \"giá trị cảm biến ánh sáng\",\n    \"XBOT_MIC\": \"giá trị cảm biến Mic\",\n    \"XBOT_analog0\": \"giá trị Analog PIN0\",\n    \"XBOT_analog1\": \"giá trị Analog PIN1\",\n    \"XBOT_analog2\": \"giá trị Analog PIN2\",\n    \"XBOT_analog3\": \"giá trị Analog PIN3\",\n    \"XBOT_Value\": \"Ouput Value\",\n    \"XBOT_pin_OutputValue\": \"PIN, giá trị đầu ra\",\n    \"XBOT_High\": \"cao\",\n    \"XBOT_Low\": \"thấp\",\n    \"XBOT_Servo\": \"động cơ Servo\",\n    \"XBOT_Head\": \"đầu (D8)\",\n    \"XBOT_ArmR\": \"tay phải(D9)\",\n    \"XBOT_ArmL\": \"tay trái(D10)\",\n    \"XBOT_angle\": \"góc độ\",\n    \"XBOT_DC\": \"động cơ bánh xe (DC)\",\n    \"XBOT_rightWheel\": \"phải\",\n    \"XBOT_leftWheel\": \"trái\",\n    \"XBOT_bothWheel\": \"hai bên\",\n    \"XBOT_speed\": \"tốc độ\",\n    \"XBOT_rightSpeed\": \"tốc độ bên phải động cơ(2) bánh xe(DC):\",\n    \"XBOT_leftSpeed\": \"tốc độ bên trái(1):\",\n    \"XBOT_RGBLED_R\": \"màu LED RBG từ màu đỏ\",\n    \"XBOT_RGBLED_G\": \"xanh lá cây\",\n    \"XBOT_RGBLED_B\": \"xanh dương\",\n    \"XBOT_RGBLED_color\": \"màu LED RBG từ\",\n    \"XBOT_set\": \"\",\n    \"XBOT_c\": \"Đô\",\n    \"XBOT_d\": \"Rê\",\n    \"XBOT_e\": \"Mi\",\n    \"XBOT_f\": \"Pha\",\n    \"XBOT_g\": \"Son\",\n    \"XBOT_a\": \"La\",\n    \"XBOT_b\": \"Si\",\n    \"XBOT_melody_ms\": \"phát nhạc trong~giây\",\n    \"XBOT_Line\": \"dòng thứ ~\",\n    \"XBOT_outputValue\": \"kiểm tra\",\n    \"roborobo_num_analog_value_1\": \"Analog\",\n    \"roborobo_num_analog_value_2\": \"Sensor Value\",\n    \"roborobo_get_digital_value_1\": \"Digital\",\n    \"roborobo_num_pin_1\": \"Digital\",\n    \"roborobo_num_pin_2\": \"Pin\",\n    \"roborobo_on\": \"On\",\n    \"roborobo_off\": \"Off\",\n    \"roborobo_motor1\": \"motor1\",\n    \"roborobo_motor2\": \"motor2\",\n    \"roborobo_motor_CW\": \"ClockWise\",\n    \"roborobo_motor_CCW\": \"CounterClockWise\",\n    \"roborobo_motor_stop\": \"Stop\",\n    \"roborobo_input_mode\": \"Input\",\n    \"roborobo_output_mode\": \"Output\",\n    \"roborobo_pwm_mode\": \"PWM\",\n    \"roborobo_servo_mode\": \"Servo\",\n    \"roborobo_color\": \"Color Sensor \",\n    \"roborobo_color_red\": \" Red \",\n    \"roborobo_color_green\": \" Green \",\n    \"roborobo_color_blue\": \" Blue \",\n    \"roborobo_color_yellow\": \" Yellow \",\n    \"roborobo_color_detected\": \" Detected \",\n    \"roborobo_degree\": \" ˚\",\n    \"robotori_D2_Input\": \"Digital Pin 2 Input Value\",\n    \"robotori_D3_Input\": \"Digital Pin 3 Input Value\",\n    \"robotori_A0_Input\": \"Analog Pin 0 Input Value\",\n    \"robotori_A1_Input\": \"Analog Pin 1 Input Value\",\n    \"robotori_A2_Input\": \"Analog Pin 2 Input Value\",\n    \"robotori_A3_Input\": \"Analog Pin 3 Input Value\",\n    \"robotori_A4_Input\": \"Analog Pin 4 Input Value\",\n    \"robotori_A5_Input\": \"Analog Pin 5 Input Value\",\n    \"robotori_digital\": \"Digital\",\n    \"robotori_D10_Output\": \"Pin 10\",\n    \"robotori_D11_Output\": \"Pin 11\",\n    \"robotori_D12_Output\": \"Pin 12\",\n    \"robotori_D13_Output\": \"Pin 13\",\n    \"robotori_pin_OutputValue\": \"Output Value\",\n    \"robotori_On\": \"On\",\n    \"robotori_Off\": \"Off\",\n    \"robotori_analog\": \"Analog\",\n    \"robotori_analog5\": \"Pin 5 Output Value\",\n    \"robotori_analog6\": \"Pin 6 Output Value\",\n    \"robotori_analog9\": \"Pin 9 Output Value\",\n    \"robotori_Servo\": \"Servo Motor\",\n    \"robotori_DC\": \"DC Motor\",\n    \"robotori_DC_rightmotor\": \"Right\",\n    \"robotori_DC_leftmotor\": \"Left\",\n    \"robotori_DC_STOP\": \"Stop\",\n    \"robotori_DC_CW\": \"clockwise\",\n    \"robotori_DC_CCW\": \"anticlockwise\",\n    \"robotori_DC_select\": \"direction\",\n    \"CALC_rotation_value\": \"giá trị vòng quay\",\n    \"CALC_direction_value\": \"giá trị phương hướng\",\n    \"VARIABLE_is_included_in_list\": \"\",\n    \"VARIABLE_is_included_in_list_1\": \"is included in\",\n    \"VARIABLE_is_included_in_list_2\": \"giá trị\",\n    \"VARIABLE_is_included_in_list_3\": \"\",\n    \"SCENE_when_scene_start\": \"khi cảnh bắt đầu\",\n    \"SCENE_start_scene_1\": \"Start\",\n    \"SCENE_start_scene_2\": \"cảnh\",\n    \"SCENE_start_neighbor_scene_1\": \"Start\",\n    \"SCENE_start_neighbor_scene_2\": \"cảnh\",\n    \"SCENE_start_scene_pre\": \"trước\",\n    \"SCENE_start_scene_next\": \"tiếp theo\",\n    \"FUNCTION_explanation_1\": \"tên\",\n    \"FUNCTION_character_variable\": \"chuỗi/số\",\n    \"FUNCTION_logical_variable\": \"biến logic\",\n    \"FUNCTION_function\": \"Tính năng\",\n    \"FUNCTION_define\": \"xác định chức năng\",\n    \"CALC_calc_operation_sin\": \"giá trị sin\",\n    \"CALC_calc_operation_cos\": \"giá trị cos\",\n    \"CALC_calc_operation_tan\": \"giá trị tan\",\n    \"CALC_calc_operation_floor\": \"giá trị làm tròn số xuống\",\n    \"CALC_calc_operation_ceil\": \"giá trị làm tròn số lên\",\n    \"CALC_calc_operation_round\": \"giá trị làm tròn\",\n    \"CALC_calc_operation_factorial\": \"giá trị giai thừa\",\n    \"CALC_calc_operation_asin\": \"giá trị asin\",\n    \"CALC_calc_operation_acos\": \"giá trị acos\",\n    \"CALC_calc_operation_atan\": \"giá trị atan\",\n    \"CALC_calc_operation_log\": \"giá trị log\",\n    \"CALC_calc_operation_ln\": \"giá trị log tự nhiên\",\n    \"CALC_calc_operation_natural\": \"integer value\",\n    \"CALC_calc_operation_unnatural\": \"giá trị thập phân\",\n    \"MOVING_locate_object_time_1\": \"factorial value\",\n    \"MOVING_locate_object_time_2\": \"trong ~giây\",\n    \"MOVING_locate_object_time_3\": \"\",\n    \"wall_up\": \"phía trên tường\",\n    \"wall_down\": \"phía dưới tường\",\n    \"wall_right\": \"bên phải tường\",\n    \"wall_left\": \"bên trái tường\",\n    \"CALC_coordinate_x_value\": \"tọa độ x\",\n    \"CALC_coordinate_y_value\": \"tọa độ y\",\n    \"CALC_coordinate_rotation_value\": \"Vòng xoay\",\n    \"CALC_coordinate_direction_value\": \"hướng\",\n    \"CALC_picture_index\": \"chỉ số hình ảnh\",\n    \"CALC_picture_name\": \"tên hình ảnh\",\n    \"FLOW_repeat_while_true_1\": \"Repeat\",\n    \"FLOW_repeat_while_true_2\": \"\",\n    \"TUT_when_start\": \"\",\n    \"TUT_move_once\": \"\",\n    \"TUT_rotate_left\": \"\",\n    \"TUT_rotate_right\": \"\",\n    \"TUT_jump_barrier\": \"\",\n    \"TUT_repeat_tutorial_1\": \"\",\n    \"TUT_repeat_tutorial_2\": \"\",\n    \"TUT_if_barrier_1\": \"\",\n    \"TUT_if_barrier_2\": \"\",\n    \"TUT_if_conical_1\": \"\",\n    \"TUT_if_conical_2\": \"\",\n    \"TUT_repeat_until\": \"\",\n    \"TUT_repeat_until_gold\": \"\",\n    \"TUT_declare_function\": \"\",\n    \"TUT_call_function\": \"\",\n    \"CALC_calc_operation_abs\": \"giá trị tuyệt đối\",\n    \"CONTEXT_COPY_option\": \"chép mã\",\n    \"Delete_Blocks\": \"xóa mã\",\n    \"Duplication_option\": \"sao chép & dán\",\n    \"Paste_blocks\": \"dán mã\",\n    \"add_my_storage\": \"add to my storage\",\n    \"export_object\": \"Export Object\",\n    \"Clear_all_blocks\": \"xóa tất cả các mã\",\n    \"add_comment\": \"add a memo\",\n    \"copy_paste_comment\": \"copy & paste the memo\",\n    \"copy_comment\": \"copy the memo\",\n    \"delete_comment\": \"delete the memo\",\n    \"fold_comment\": \"fold the memo\",\n    \"open_comment\": \"open the memo\",\n    \"separate_comment\": \"take the memo off\",\n    \"hide_all_comment\": \"hide all memos\",\n    \"show_all_comment\": \"show all memos\",\n    \"transparency\": \"độ trong suốt\",\n    \"BRUSH_change_brush_transparency_1\": \"thay đổi độ trong suốt của cọ bằng\",\n    \"BRUSH_change_brush_transparency_2\": \"%\",\n    \"BRUSH_set_brush_transparency_1\": \"thiết lập độ trong suốt của cọ bằng\",\n    \"BRUSH_set_brush_transparency_2\": \"%\",\n    \"CALC_char_at_1\": \"Ký tự\",\n    \"CALC_char_at_2\": \"của\",\n    \"CALC_char_at_3\": \"\",\n    \"CALC_length_of_string_1\": \"Chiều dài của\",\n    \"CALC_length_of_string_2\": \"\",\n    \"CALC_substring_1\": \"Chuỗi của\",\n    \"CALC_substring_2\": \"từ\",\n    \"CALC_substring_3\": \"đến\",\n    \"length_of_string\": \"to\",\n    \"CALC_substring_4\": \"\",\n    \"CALC_replace_string_1\": \"Thay thế \",\n    \"CALC_replace_string_2\": \"trong\",\n    \"CALC_replace_string_3\": \"với\",\n    \"CALC_replace_string_4\": \"\",\n    \"CALC_change_string_case_1\": \"\",\n    \"CALC_change_string_case_2\": \"của\",\n    \"CALC_change_string_case_3\": \"\",\n    \"CALC_change_string_case_sub_1\": \"chữ hoa\",\n    \"CALC_change_string_case_sub_2\": \"chữ thường\",\n    \"CALC_index_of_string_1\": \"Danh mục của\",\n    \"CALC_index_of_string_2\": \"trong\",\n    \"CALC_index_of_string_3\": \"\",\n    \"MOVING_add_direction_by_angle_time_explain_1\": \"For\",\n    \"MOVING_direction_relative_duration_1\": \"For\",\n    \"MOVING_direction_relative_duration_2\": \"thiết lập phương hướng trong~giây  \",\n    \"MOVING_direction_relative_duration_3\": \"\",\n    \"CALC_get_sound_volume\": \"âm lượng\",\n    \"SOUND_sound_from_to_1\": \"mở\",\n    \"SOUND_sound_from_to_2\": \"sound from\",\n    \"SOUND_sound_from_to_3\": \"từ ~giây\",\n    \"SOUND_sound_from_to_4\": \"đến ~giây\",\n    \"SOUND_sound_from_to_and_wait_1\": \"mở\",\n    \"SOUND_sound_from_to_and_wait_2\": \"sound from\",\n    \"SOUND_sound_from_to_and_wait_3\": \"từ ~giây\",\n    \"SOUND_sound_from_to_and_wait_4\": \"đến ~giây và chờ\",\n    \"CALC_quotient_and_mod_1\": \"\",\n    \"CALC_quotient_and_mod_2\": \"của\",\n    \"CALC_quotient_and_mod_3\": \"/\",\n    \"CALC_quotient_and_mod_4\": \" \",\n    \"CALC_quotient_and_mod_sub_1\": \"thương số\",\n    \"CALC_quotient_and_mod_sub_2\": \"phần còn lại\",\n    \"self\": \"bản thân\",\n    \"CALC_coordinate_size_value\": \"kích cỡ\",\n    \"CALC_choose_project_timer_action_1\": \"\",\n    \"CALC_choose_project_timer_action_2\": \"bộ đếm thời gian\",\n    \"CALC_choose_project_timer_action_sub_1\": \"bắt đầu\",\n    \"CALC_choose_project_timer_action_sub_2\": \"dừng lại\",\n    \"CALC_choose_project_timer_action_sub_3\": \"khởi động\",\n    \"LOOKS_change_object_index_1\": \"bring to\",\n    \"LOOKS_change_object_index_2\": \"\",\n    \"LOOKS_change_object_index_sub_1\": \"phía trước\",\n    \"LOOKS_change_object_index_sub_2\": \"đằng trước\",\n    \"LOOKS_change_object_index_sub_3\": \"đằng sau\",\n    \"LOOKS_change_object_index_sub_4\": \"phía sau\",\n    \"FLOW_repeat_while_true_until\": \"cho đến\",\n    \"FLOW_repeat_while_true_while\": \"trong khi\",\n    \"copy_block\": \"copy block(s)\",\n    \"delete_block\": \"delete block(s)\",\n    \"tidy_up_block\": \"sắp xếp các khối\",\n    \"block_hi\": \"xin chào\",\n    \"entry_bot_name\": \"Entrybot\",\n    \"hi_entry\": \"Xin chào Entry!\",\n    \"hi_entry_en\": \"Hello Entry!\",\n    \"bark_dog\": \"dog barking\",\n    \"walking_entryBot\": \"Walking Entrybot\",\n    \"doggi_bark\": \"Doggi's Bark\",\n    \"entry\": \"Entry\",\n    \"hello\": \"xin chào \",\n    \"nice\": \"rất vui được gặp bạn\",\n    \"silent\": \"Silent\",\n    \"do_name\": \"Do\",\n    \"do_sharp_name\": \"Do#(Re♭)\",\n    \"re_name\": \"Re\",\n    \"re_sharp_name\": \"Re(Mi♭)\",\n    \"mi_name\": \"Mi\",\n    \"fa_name\": \"Fa\",\n    \"fa_sharp_name\": \"Fa#(Sol♭)\",\n    \"sol_name\": \"Sol\",\n    \"sol_sharp_name\": \"Sol#(La♭)\",\n    \"la_name\": \"La\",\n    \"la_sharp_name\": \"La#(Si♭)\",\n    \"DUMMY\": \"더미\",\n    \"coconut_stop_motor\": \"stop motor\",\n    \"coconut_move_motor\": \"move motor\",\n    \"coconut_turn_motor\": \"turn\",\n    \"coconut_move_outmotor\": \"external motor\",\n    \"coconut_turn_left\": \"left\",\n    \"coconut_turn_right\": \"right\",\n    \"coconut_move_forward\": \"forward\",\n    \"coconut_move_backward\": \"backward\",\n    \"coconut_note_c\": \"note_c\",\n    \"coconut_note_d\": \"note_d\",\n    \"coconut_note_e\": \"note_e\",\n    \"coconut_note_f\": \"note_f\",\n    \"coconut_note_g\": \"note_g\",\n    \"coconut_note_a\": \"note_a\",\n    \"coconut_note_b\": \"note_b\",\n    \"coconut_move_speed_1\": \"0\",\n    \"coconut_move_speed_2\": \"50\",\n    \"coconut_move_speed_3\": \"100\",\n    \"coconut_move_speed_4\": \"150\",\n    \"coconut_move_speed_5\": \"255\",\n    \"coconut_play_buzzer_hn\": \"Half\",\n    \"coconut_play_buzzer_qn\": \"Quater\",\n    \"coconut_play_buzzer_en\": \"Eighth\",\n    \"coconut_play_buzzer_sn\": \"Sixteenth\",\n    \"coconut_play_buzzer_tn\": \"Thirty-second\",\n    \"coconut_play_buzzer_wn\": \"Whole\",\n    \"coconut_play_buzzer_dhn\": \"Dotted half\",\n    \"coconut_play_buzzer_dqn\": \"Dotted quarter\",\n    \"coconut_play_buzzer_den\": \"Dotted eighth\",\n    \"coconut_play_buzzer_dsn\": \"Dotted sixteenth\",\n    \"coconut_play_buzzer_dtn\": \"Dotted thirty-second\",\n    \"coconut_rest_buzzer_hr\": \"Half_rest\",\n    \"coconut_rest_buzzer_qr\": \"Quater_rest\",\n    \"coconut_rest_buzzer_er\": \"Eighth_rest\",\n    \"coconut_rest_buzzer_sr\": \"Sixteenth_rest\",\n    \"coconut_rest_buzzer_tr\": \"Thirty-second rest\",\n    \"coconut_rest_buzzer_wr\": \"Whole_rest\",\n    \"coconut_play_midi_1\": \"Twinkle Twinkle little star\",\n    \"coconut_play_midi_2\": \"Three bears\",\n    \"coconut_play_midi_3\": \"Mozart's Lullaby\",\n    \"coconut_play_midi_4\": \"Do-Re-Mi\",\n    \"coconut_play_midi_5\": \"Butterfly\",\n    \"coconut_floor_sensing_on\": \"detect\",\n    \"coconut_floor_sensing_off\": \"not detect\",\n    \"coconut_dotmatrix_set_on\": \"on\",\n    \"coconut_dotmatrix_set_off\": \"off\",\n    \"coconut_dotmatrix_row_0\": \"all\",\n    \"coconut_dotmatrix_row_1\": \"1\",\n    \"coconut_dotmatrix_row_2\": \"2\",\n    \"coconut_dotmatrix_row_3\": \"3\",\n    \"coconut_dotmatrix_row_4\": \"4\",\n    \"coconut_dotmatrix_row_5\": \"5\",\n    \"coconut_dotmatrix_row_6\": \"6\",\n    \"coconut_dotmatrix_row_7\": \"7\",\n    \"coconut_dotmatrix_row_8\": \"8\",\n    \"coconut_dotmatrix_col_0\": \"all\",\n    \"coconut_dotmatrix_col_1\": \"1\",\n    \"coconut_dotmatrix_col_2\": \"2\",\n    \"coconut_dotmatrix_col_3\": \"3\",\n    \"coconut_dotmatrix_col_4\": \"4\",\n    \"coconut_dotmatrix_col_5\": \"5\",\n    \"coconut_dotmatrix_col_6\": \"6\",\n    \"coconut_dotmatrix_col_7\": \"7\",\n    \"coconut_dotmatrix_col_8\": \"8\",\n    \"coconut_sensor_left_proximity\": \"left IR distance\",\n    \"coconut_sensor_right_proximity\": \"right IR distance\",\n    \"coconut_sensor_both_proximity\": \"both IR distance\",\n    \"coconut_sensor_left_floor\": \"left line tracer\",\n    \"coconut_sensor_right_floor\": \"right line tracer\",\n    \"coconut_sensor_both_floor\": \"both line tracer\",\n    \"coconut_sensor_acceleration_x\": \"X-Axis Accelerometer\",\n    \"coconut_sensor_acceleration_y\": \"Y-Axis Accelerometer\",\n    \"coconut_sensor_acceleration_z\": \"Z-Axis Accelerometer\",\n    \"coconut_sensor_light\": \"light sensor\",\n    \"coconut_sensor_temperature\": \"temperature\",\n    \"coconut_left_led\": \"left led\",\n    \"coconut_right_led\": \"right led\",\n    \"coconut_both_leds\": \"both led\",\n    \"coconut_color_cyan\": \"Cyan\",\n    \"coconut_color_magenta\": \"Magenta\",\n    \"coconut_color_black\": \"Black\",\n    \"coconut_color_white\": \"White\",\n    \"coconut_color_red\": \"Red\",\n    \"coconut_color_yellow\": \"Yellow\",\n    \"coconut_color_green\": \"Green\",\n    \"coconut_color_blue\": \"Blue\",\n    \"coconut_beep\": \"buzzer on\",\n    \"coconut_clear_buzzer\": \"buzzer off\",\n    \"coconut_x_axis\": \"X-Axis\",\n    \"coconut_y_axis\": \"Y-Axis\",\n    \"coconut_z_axis\": \"Z-Axis\",\n    \"modi_enviroment_bule\": \"Blue\",\n    \"modi_enviroment_green\": \"Green\",\n    \"modi_enviroment_humidity\": \"Humidity\",\n    \"modi_enviroment_illuminance\": \"Illuminance\",\n    \"modi_enviroment_red\": \"Red\",\n    \"modi_enviroment_temperature\": \"Temparature\",\n    \"modi_gyroscope_xAcceleratior\": \"X-axis acceleration\",\n    \"modi_gyroscope_yAcceleratior\": \"Y-axis acceleration\",\n    \"modi_gyroscope_zAcceleratior\": \"Z-axis acceleration\",\n    \"modi_motor_angle\": \"Angle\",\n    \"modi_motor_speed\": \"Speed\",\n    \"modi_motor_torque\": \"Torque\",\n    \"modi_speaker_F_DO_5\": \"DO 5\",\n    \"modi_speaker_F_DO_6\": \"DO 6\",\n    \"modi_speaker_F_DO_7\": \"DO 7\",\n    \"modi_speaker_F_DO_S_5\": \"DO #5\",\n    \"modi_speaker_F_DO_S_6\": \"DO #6\",\n    \"modi_speaker_F_DO_S_7\": \"DO #7\",\n    \"modi_speaker_F_MI_5\": \"MI 5\",\n    \"modi_speaker_F_MI_6\": \"MI 6\",\n    \"modi_speaker_F_MI_7\": \"MI 7\",\n    \"modi_speaker_F_PA_5\": \"FA 5\",\n    \"modi_speaker_F_PA_6\": \"FA 6\",\n    \"modi_speaker_F_PA_7\": \"FA 7\",\n    \"modi_speaker_F_PA_S_5\": \"FA #5\",\n    \"modi_speaker_F_PA_S_6\": \"FA #6\",\n    \"modi_speaker_F_PA_S_7\": \"FA #7\",\n    \"modi_speaker_F_RA_5\": \"LA 5\",\n    \"modi_speaker_F_RA_6\": \"LA 6\",\n    \"modi_speaker_F_RA_7\": \"LA 7\",\n    \"modi_speaker_F_RA_S_5\": \"LA #5\",\n    \"modi_speaker_F_RA_S_6\": \"LA #6\",\n    \"modi_speaker_F_RA_S_7\": \"LA #7\",\n    \"modi_speaker_F_RE_5\": \"RE 5\",\n    \"modi_speaker_F_RE_6\": \"RE 6\",\n    \"modi_speaker_F_RE_7\": \"RE 7\",\n    \"modi_speaker_F_RE_S_5\": \"LA #5\",\n    \"modi_speaker_F_RE_S_6\": \"RE #6\",\n    \"modi_speaker_F_RE_S_7\": \"RE #7\",\n    \"modi_speaker_F_SOL_5\": \"SOL 5\",\n    \"modi_speaker_F_SOL_6\": \"SOL 6\",\n    \"modi_speaker_F_SOL_7\": \"SOL 7\",\n    \"modi_speaker_F_SOL_S_5\": \"SOL #5\",\n    \"modi_speaker_F_SOL_S_6\": \"SOL #6\",\n    \"modi_speaker_F_SOL_S_7\": \"SOL #7\",\n    \"modi_speaker_F_SO_5\": \"TI 5\",\n    \"modi_speaker_F_SO_6\": \"TI 6\",\n    \"modi_speaker_F_SO_7\": \"TI 7\",\n    \"si_name\": \"Si\",\n    \"ev3_ccw\": \"CCW\",\n    \"ev3_cw\": \"CW\",\n    \"rokoboard_sensor_name_0\": \"Sound\",\n    \"rokoboard_sensor_name_1\": \"Light\",\n    \"rokoboard_sensor_name_2\": \"Slider\",\n    \"rokoboard_sensor_name_3\": \"resistance-A\",\n    \"rokoboard_sensor_name_4\": \"resistance-B\",\n    \"rokoboard_sensor_name_5\": \"resistance-C\",\n    \"rokoboard_sensor_name_6\": \"resistance-D\",\n    \"rokoboard_string_1\": \"Button Pressed\",\n    \"HW_MOTOR\": \"Motor\",\n    \"HW_SENSOR\": \"Sensor\",\n    \"HW_LED\": \"Led\",\n    \"HW_MELODY\": \"Melody\",\n    \"HW_ROBOT\": \"Robot\",\n    \"ALTINO_ACCX\": \"acceleration X axis\",\n    \"ALTINO_ACCY\": \"acceleration Y axis\",\n    \"ALTINO_ACCZ\": \"acceleration Z axis\",\n    \"ALTINO_BAT\": \"battery check\",\n    \"ALTINO_CDS\": \"light\",\n    \"ALTINO_GYROX\": \"gyro X axis\",\n    \"ALTINO_GYROY\": \"gyro Y axis\",\n    \"ALTINO_GYROZ\": \"gyro Z axis\",\n    \"ALTINO_IR1\": \"1 distance\",\n    \"ALTINO_IR2\": \"2 distance\",\n    \"ALTINO_IR3\": \"3 distance\",\n    \"ALTINO_IR4\": \"4 distance\",\n    \"ALTINO_IR5\": \"5 distance\",\n    \"ALTINO_IR6\": \"6 distance\",\n    \"ALTINO_Led_Brake_Light\": \"brake\",\n    \"ALTINO_Led_Forward_Light\": \"forward\",\n    \"ALTINO_Led_Reverse_Light\": \"backward\",\n    \"ALTINO_Led_Turn_Left_Light\": \"left direction\",\n    \"ALTINO_Led_Turn_Right_Light\": \"right direction\",\n    \"ALTINO_Line\": \"line\",\n    \"ALTINO_MAGX\": \"geomagnetic X axis\",\n    \"ALTINO_MAGY\": \"geomagnetic Y axis\",\n    \"ALTINO_MAGZ\": \"geomagnetic Z axis\",\n    \"ALTINO_REMOTE\": \"remote control\",\n    \"ALTINO_STTOR\": \"steering torque\",\n    \"ALTINO_STVAR\": \"steering potentiometer\",\n    \"ALTINO_Steering_Angle_Center\": \"center\",\n    \"ALTINO_Steering_Angle_Left10\": \"left10\",\n    \"ALTINO_Steering_Angle_Left15\": \"left15\",\n    \"ALTINO_Steering_Angle_Left20\": \"left20\",\n    \"ALTINO_Steering_Angle_Left5\": \"left5\",\n    \"ALTINO_Steering_Angle_Right10\": \"right10\",\n    \"ALTINO_Steering_Angle_Right15\": \"right15\",\n    \"ALTINO_Steering_Angle_Right20\": \"right20\",\n    \"ALTINO_Steering_Angle_Right5\": \"right5\",\n    \"ALTINO_TEM\": \"temperature\",\n    \"ALTINO_TOR1\": \"right torque\",\n    \"ALTINO_TOR2\": \"left torque\",\n    \"ALTINO_Value\": \"output value\",\n    \"ALTINO_a\": \"la\",\n    \"ALTINO_a2\": \"la#\",\n    \"ALTINO_b\": \"si\",\n    \"ALTINO_c\": \"do\",\n    \"ALTINO_c2\": \"do#\",\n    \"ALTINO_d\": \"re\",\n    \"ALTINO_d2\": \"re#\",\n    \"ALTINO_dot_display_1\": \"one char\",\n    \"ALTINO_dot_display_2\": \"display\",\n    \"ALTINO_e\": \"mi\",\n    \"ALTINO_f\": \"fa\",\n    \"ALTINO_f2\": \"fa#\",\n    \"ALTINO_g\": \"sol\",\n    \"ALTINO_g2\": \"sol#\",\n    \"ALTINO_h\": \"off\",\n    \"ALTINO_h2\": \"on\",\n    \"ALTINO_leftWheel\": \"left\",\n    \"ALTINO_melody_ms\": \"play\",\n    \"ALTINO_outputValue\": \"output\",\n    \"ALTINO_rightWheel\": \"right\",\n    \"ALTINO_set\": \" display\",\n    \"ardublock_motor_forward\": \"Forward\",\n    \"ardublock_motor_backward\": \"Backward\",\n    \"jdkit_clockwise\": \"시계방향\",\n    \"jdkit_counterclockwise\": \"반시계방향\",\n    \"jdkit_gyro_frontrear\": \"앞뒤\",\n    \"jdkit_gyro_leftright\": \"좌우\",\n    \"jdkit_joystick_leftleftright\": \"왼쪽 좌우\",\n    \"jdkit_joystick_lefttopbottom\": \"왼쪽 상하\",\n    \"jdkit_joystick_rightleftright\": \"오른쪽 좌우\",\n    \"jdkit_joystick_righttopbottom\": \"오른쪽 상하\",\n    \"jdkit_led\": \"LED\",\n    \"jdkit_led_color_green\": \"초록색\",\n    \"jdkit_led_color_orange\": \"오랜지색\",\n    \"jdkit_led_turnoff\": \"끄기\",\n    \"jdkit_led_turnon\": \"켜기\",\n    \"jdkit_motor_leftbottom\": \"왼쪽아래\",\n    \"jdkit_motor_lefttop\": \"왼쪽위\",\n    \"jdkit_motor_rightbottom\": \"오른쪽아래\",\n    \"jdkit_motor_righttop\": \"오른쪽위\",\n    \"jdkit_tune_do\": \"도\",\n    \"jdkit_tune_fa\": \"파\",\n    \"jdkit_tune_la\": \"라\",\n    \"jdkit_tune_mi\": \"미\",\n    \"jdkit_tune_re\": \"레\",\n    \"jdkit_tune_si\": \"시\",\n    \"jdkit_tune_sol\": \"솔\",\n    \"FUNBOARD_bt_down\": \"yellow(B)\",\n    \"FUNBOARD_bt_left\": \"green(C)\",\n    \"FUNBOARD_bt_right\": \"blue(D)\",\n    \"FUNBOARD_bt_up\": \"red(A)\",\n    \"FUNBOARD_column_tag\": \"column\",\n    \"FUNBOARD_do_off\": \"off\",\n    \"FUNBOARD_do_on\": \"on\",\n    \"FUNBOARD_led_color_all\": \"모두\",\n    \"FUNBOARD_led_color_blue\": \"blue\",\n    \"FUNBOARD_led_color_green\": \"green\",\n    \"FUNBOARD_led_color_red\": \"red\",\n    \"FUNBOARD_led_color_str\": \"color  \",\n    \"FUNBOARD_led_color_yellow\": \"yellow\",\n    \"FUNBOARD_led_off_str\": \"Turn off the LED\",\n    \"FUNBOARD_led_on_str\": \"Turn on the LED\",\n    \"FUNBOARD_row_tag\": \"row\",\n    \"FUNBOARD_scroll_down\": \"downward\",\n    \"FUNBOARD_scroll_left\": \"leftward\",\n    \"FUNBOARD_scroll_no\": \"no\",\n    \"FUNBOARD_scroll_right\": \"rightward\",\n    \"FUNBOARD_scroll_up\": \"upwards\",\n    \"FUNBOARD_sensor_cds\": \"light sensor\",\n    \"FUNBOARD_sensor_mic\": \"microphone sensor\",\n    \"FUNBOARD_sensor_slide\": \"potentiometer\",\n    \"FUNBOARD_sensor_state_1\": \"low\",\n    \"FUNBOARD_sensor_state_2\": \"high\",\n    \"FUNBOARD_touchbt_down\": \"yellow(B)\",\n    \"FUNBOARD_touchbt_enter\": \"   F\",\n    \"FUNBOARD_touchbt_escape\": \"   G\",\n    \"FUNBOARD_touchbt_left\": \"green(C)\",\n    \"FUNBOARD_touchbt_right\": \"blue(D)\",\n    \"FUNBOARD_touchbt_space\": \"   E\",\n    \"FUNBOARD_touchbt_up\": \"red(A)\",\n    \"funboard_dotmatrix_set_off\": \"off\",\n    \"funboard_dotmatrix_set_on\": \"on\",\n    \"AI_UTILIZE\": \"AI\",\n    \"video_show_video\": \"Show\",\n    \"video_hide_video\": \"Hide\",\n    \"video_brightness\": \"brightness\",\n    \"video_transparency\": \"transparency\",\n    \"video_left_right\": \"horizontally\",\n    \"video_top_bottom\": \"vertically\",\n    \"video_human\": \"people\",\n    \"video_face\": \"face\",\n    \"video_object\": \"object\",\n    \"video_start\": \"Start\",\n    \"video_end\": \"Stop\",\n    \"video_gender\": \"gender\",\n    \"video_age\": \"age\",\n    \"video_emotion\": \"emotion\",\n    \"video_motion_onself\": \"itself\",\n    \"video_motion_onscreen\": \"screen\",\n    \"video_motion_scale\": \"motion\",\n    \"video_motion_direction_horizontal\": \"x direction\",\n    \"video_motion_direction_vertical\": \"y direction\",\n    \"table_row\": \"row\",\n    \"table_col\": \"column\",\n    \"table_sum\": \"sum\",\n    \"table_max\": \"max\",\n    \"table_min\": \"min\",\n    \"table_avg\": \"average\",\n    \"table_stdev\": \"standard deviation\",\n    \"arduino_lite_reconnect\": \"Retry\",\n    \"arduino_lite_download_firmware\": \"Download Firmware\",\n    \"arduino_lite_download_driver\": \"Download Driver\",\n    \"arduino_lite_connect\": \"Web Connection\",\n    \"arduino_lite_disconnect\": \"Cancel\",\n    \"arduino_lite_guide\": \"• connection guide\",\n};\nLang.video_body_coord_params = {\n    \"left_eye\": \"Left Eye\",\n    \"right_eye\": \"Right Eye\",\n    \"nose\": \"Nose\",\n    \"left_mouth\": \"Left Mouth\",\n    \"right_mouth\": \"Right Mouth\",\n    \"upper_lip\": \"Upper Lip\",\n    \"lower_lip\": \"Lower Lip\",\n    \"face\": \"face\",\n    \"neck\": \"face\",\n    \"left_ear\": \"left ear\",\n    \"right_ear\": \"right ear\",\n    \"left_shoulder\": \"left shoulder\",\n    \"left_elbow\": \"left elbow\",\n    \"left_wrist\": \"left wrist\",\n    \"left_hip\": \"left hip\",\n    \"left_knee\": \"left knee\",\n    \"left_ankle\": \"left ankle\",\n    \"right_shoulder\": \"right shoulder\",\n    \"right_elbow\": \"right elbow\",\n    \"right_wrist\": \"right wrist\",\n    \"right_hip\": \"right hip\",\n    \"right_knee\": \"right knee\",\n    \"right_ankle\": \"right ankle\"\n};\nLang.video_emotion_params = {\n    \"angry\": \"Anger\",\n    \"disgusted\": \"Disgust\",\n    \"fearful\": \"Fearful\",\n    \"happy\": \"Happiness\",\n    \"neutral\": \"Neutral\",\n    \"sad\": \"Sadness\",\n    \"surprised\": \"Surprised\"\n};\nLang.video_object_params = {\n    \"person\": \"person\",\n    \"bicycle\": \"bicycle\",\n    \"car\": \"car\",\n    \"motorcycle\": \"motorcycle\",\n    \"airplane\": \"airplane\",\n    \"bus\": \"bus\",\n    \"train\": \"train\",\n    \"truck\": \"truck\",\n    \"boat\": \"boat\",\n    \"traffic light\": \"traffic light\",\n    \"fire hydrant\": \"fire hydrant\",\n    \"stop sign\": \"stop sign\",\n    \"parking meter\": \"parking meter\",\n    \"bench\": \"bench\",\n    \"bird\": \"bird\",\n    \"cat\": \"cat\",\n    \"dog\": \"dog\",\n    \"horse\": \"horse\",\n    \"sheep\": \"sheep\",\n    \"cow\": \"cow\",\n    \"elephant\": \"elephant\",\n    \"bear\": \"bear\",\n    \"zebra\": \"zebra\",\n    \"giraffe\": \"giraffe\",\n    \"backpack\": \"backpack\",\n    \"umbrella\": \"umbrella\",\n    \"handbag\": \"handbag\",\n    \"tie\": \"tie\",\n    \"suitcase\": \"suitcase\",\n    \"frisbee\": \"frisbee\",\n    \"skis\": \"skis\",\n    \"snowboard\": \"snowboard\",\n    \"sports ball\": \"sports ball\",\n    \"kite\": \"kite\",\n    \"baseball bat\": \"baseball bat\",\n    \"baseball glove\": \"baseball glove\",\n    \"skateboard\": \"skateboard\",\n    \"surfboard\": \"surfboard\",\n    \"tennis racket\": \"tennis racket\",\n    \"bottle\": \"bottle\",\n    \"wine glass\": \"wine glass\",\n    \"cup\": \"cup\",\n    \"fork\": \"fork\",\n    \"knife\": \"knife\",\n    \"spoon\": \"spoon\",\n    \"bowl\": \"bowl\",\n    \"banana\": \"banana\",\n    \"apple\": \"apple\",\n    \"sandwich\": \"sandwich\",\n    \"orange\": \"orange\",\n    \"broccoli\": \"broccoli\",\n    \"carrot\": \"carrot\",\n    \"hot dog\": \"hot dog\",\n    \"pizza\": \"pizza\",\n    \"donut\": \"donut\",\n    \"cake\": \"cake\",\n    \"chair\": \"chair\",\n    \"couch\": \"couch\",\n    \"potted plant\": \"potted plant\",\n    \"bed\": \"bed\",\n    \"dining table\": \"dining table\",\n    \"toilet\": \"toilet\",\n    \"tv\": \"tv\",\n    \"laptop\": \"laptop\",\n    \"mouse\": \"mouse\",\n    \"remote\": \"remote\",\n    \"keyboard\": \"keyboard\",\n    \"cell phone\": \"cell phone\",\n    \"microwave\": \"microwave\",\n    \"oven\": \"oven\",\n    \"toaster\": \"toaster\",\n    \"sink\": \"sink\",\n    \"refrigerator\": \"refrigerator\",\n    \"book\": \"book\",\n    \"clock\": \"clock\",\n    \"vase\": \"vase\",\n    \"scissors\": \"scissors\",\n    \"teddy bear\": \"teddy bear\",\n    \"hair drier\": \"hair dryer\",\n    \"toothbrush\": \"toothbrush\"\n};\nLang.Buttons = {\n    \"share_policy\": \"Share Guide\",\n    \"write_policy\": \"Write Guide\",\n    \"lesson_list\": \"List\",\n    \"complete_study\": \"Complete\",\n    \"show_me\": \"Show Me\",\n    \"do_this_for_me\": \"Do This For Me\",\n    \"previous\": \"Previous \",\n    \"get_started\": \"Get Started\",\n    \"next_lesson\": \"Next lesson\",\n    \"course_submit\": \"Submit\",\n    \"course_done\": \"Done\",\n    \"mission\": \"Introduction \",\n    \"basic_guide\": \"User Guide\",\n    \"apply\": \"ứng dụng\",\n    \"add\": \"Add\",\n    \"cancel\": \"hủy bỏ\",\n    \"save\": \"OK\",\n    \"start\": \"Start\",\n    \"confirm\": \"OK\",\n    \"delete\": \"Delete\",\n    \"create\": \"Create Class\",\n    \"done\": \"Done\",\n    \"accept\": \"Accept\",\n    \"refuse\": \"Refuse\",\n    \"yes\": \"Yes\",\n    \"button_no\": \"No\",\n    \"quiz_retry\": \"Try Again\",\n    \"discuss_upload\": \"Upload\",\n    \"maze_popup_guide\": \"User Guide\",\n    \"maze_popup_mapHint\": \"Hint\",\n    \"maze_hint_btn_guide\": \"User Guide\",\n    \"maze_hint_btn_block\": \"Block Help\",\n    \"maze_hint_btn_map\": \"Map Hint\",\n    \"maze_hint_btn_goal\": \"goal\",\n    \"list_save\": \"Upload\",\n    \"duplication\": \"Copy\",\n    \"export_to_excel\": \"Download\",\n    \"single_line\": \"Single line\",\n    \"multi_line\": \"Multiline\",\n    \"lecture_finish_popup_reset_lecture\": \"Do it again\",\n    \"lecture_finish_popup_show_output\": \"See the exercised\",\n    \"lecture_view_hints\": \"View hints\",\n    \"default_hint_title\": \"How do you make it?\",\n    \"show_only_vector\": \"Only Vector\"\n};\nLang.Menus = {\n    \"nothing_to_import\": \"There is no content to upload.\",\n    \"nothing_to_export\": \"There is no content to download.\",\n    \"content_copied\": \"The data is copied.\",\n    \"list_import_title\": \"Import\",\n    \"list_import_placeholder\": \"Example)\\nData1\\nData2\\nData3\\nData4\\nData5\\nData6\\nData7\\nData8\",\n    \"verifying_email\": \"Verifying email\",\n    \"list_import_notice_1\": \"You can upload the data in the list.\",\n    \"list_import_notice_2\": \"The original data will be changed into the newly uploaded data.\",\n    \"list_export_title\": \"Export\",\n    \"list_export_notice\": \"You can copy or download the data in the list.\",\n    \"robotis_opencm70\": \"Robotis Open CM70\",\n    \"cannnot_mark_favorite\": \"Private project cannot be marked as a favorite.\",\n    \"enterPassword\": \"Enter password.\",\n    \"enterPassword_update\": \"Please enter your password to save your changes.\",\n    \"enterNewPassword\": \"Enter new password.\",\n    \"reEnterNewPassword\": \"Re-enter new password.\",\n    \"resign\": \"Account deletion\",\n    \"check_sended_email\": \"Please check your inbox to verify your email.\",\n    \"signUpEmail_1\": \"Verification mail has been sent. \",\n    \"signUpEmail_2\": \"Please verify your email.\",\n    \"select_email_unauthenticated_user\": \"The email address is registered to the IDs below.\\nPlease choose the right one.\",\n    \"select_user\": \"Please choose the ID.\",\n    \"enter_password_withdraw\": \"Enter password to delete your account\",\n    \"instruction_agree\": \"Please check instruction and agree.\",\n    \"check_instructions\": \"I check instructions and agree.\",\n    \"deleteAccount_2\": \"After 30 days, every data that you created in Entry such as project/lecture/class/post/comment/like/favourite will be deleted and cannot be restored.\",\n    \"deleteAccount_1\": \"If you sign in again within 30 days, you can withdraw account deletion.\",\n    \"protect_account\": \"Protect your account with a safe password.\",\n    \"please_verify\": \"Please verify your email to click 'Verifying email'\",\n    \"unverified_email\": \"Unverified email\",\n    \"deleteAccount\": \"Delete account\",\n    \"corporatePersonal\": \"Agree to the transfer of personal information.\",\n    \"corporateTransferGuide\": \"Personal Information transfer guide\",\n    \"corporateReciever\": \"Information reciever : Connect Foundation\",\n    \"corporateAddress\": \"Connect Foundation Address&Contact\",\n    \"corporateAddress_1\": \"Meritz Tower 7, Seoul Gangnam-gu Gangnam-daero 382, Seoul, Korea\",\n    \"corporateConsent\": \"If you do not want to transfer your information, you may withdraw the consent.\",\n    \"corporateEmail\": \"For withdraw the consent, send an email to\",\n    \"corporateAddition\": \"In addition, the terms and conditions of the agreement will be changed, depending on the transfer.\",\n    \"corporateApplicationDate\": \"Application date : From October 29, 2017\",\n    \"corporateTargetChanges\": \"Application Targets and Changes : \",\n    \"corporateTarget\": \"Targets\",\n    \"corporateChanges\": \"Changes\",\n    \"corporateTerms\": \"Terms\",\n    \"corporateOperator\": \"The name of the ‘Entry’ operator\",\n    \"corporateClassroomTerms\": \"Classroom Service Terms of Use\",\n    \"doAgreeWithClassroomTerms\": \"Agree to the Classroom Service Terms of Use.\",\n    \"doChangePassword\": \"Please change the password into the one that only you can know.\",\n    \"corporatePrivacyPolicy\": \"Privacy Policy\",\n    \"corporateConsignment\": \"The name of the ‘Entry’ operator. And consignment of personal information\",\n    \"corporateEntrusted\": \"Entrusted Company : NHN Technology Services Corporation.\",\n    \"corporateConsignmentDetails\": \"Details of Consignment : Service operation.\",\n    \"corporatePeriod\": \"Consignment Period : Until the member cancels membership or the consignment contract ends.\",\n    \"corporateChangeDate\": \"Date of change : October 29, 2017\",\n    \"corporateWarning\": \"Please Agree to the transfer of personal information.\",\n    \"corporateConfirm\": \"Confirm\",\n    \"corporateTitle\": \"Hello. This is EntryLabs.<br> We are very grateful to you who are using 'Entry'. <br>Recently we have agreed to transfer the ownership of Entry web site, which has been operated for public interest purposes, to the 'Connect Foundation'.<br>Connect Foundation is a non-profit foundation founded by Naver. 'Entry' will be continuously operated under public interest purpose by 'Connect Foundation'. Therefore, All of “Entry” users will be guaranteed to use the entry exactly as same as before.<br>Since the website provider has changed from the 'EntryLabs' to the 'Connect Foundation', there is a transfer of personal information as below. However, this doesn’t mean that your information will be physically moved.<br>\",\n    \"textcoding_numberError_f\": \"You can't convert into the text mode if there is function names start with a number.\",\n    \"textcoding_bookedError_1f\": \"You can't convert into the text mode if there is function named\",\n    \"textcoding_bookedError_2f\": \".\",\n    \"textcoding_specialCharError_f\": \"You can't convert into the text mode if there is function names include special character except for underscore.\",\n    \"textcoding_numberError_v\": \"You can't convert into the text mode if there is variable names start with a number.\",\n    \"textcoding_bookedError_1v\": \"You can't convert into the text mode if there is variable named \",\n    \"textcoding_bookedError_2v\": \".\",\n    \"textcoding_specialCharError_v\": \"You can't convert into the text mode if there is variable names include special character except for underscore.\",\n    \"textcoding_numberError_l\": \"You can't convert into the text mode if there is list names start with a number.\",\n    \"textcoding_bookedError_1l\": \"You can't convert into the text mode if there is list named \",\n    \"textcoding_bookedError_2l\": \".\",\n    \"textcoding_specialCharError_l\": \"You can't convert into the text mode if there is list names include special character except for underscore.\",\n    \"no_discuss_permission\": \"You don't have permission to view this post.\",\n    \"delete_comment\": \"Are you sure you want to delete commnet\",\n    \"delete_article\": \"Are you sure you want to delete article\",\n    \"discuss_cannot_edit\": \"You cannot edit this post\",\n    \"discuss_extention\": \"You cannot upload files with that extension\",\n    \"delete_discuss_picture\": \"Do you want to delete the photo?\",\n    \"delete_discuss_file\": \"Do you want to delete the file?\",\n    \"discuss_save_question\": \"Do you want save your post?\",\n    \"discuss_cancle_question\": \"Do you want to leave without saving?\",\n    \"discuss_saved\": \"is saved\",\n    \"discuss_no_write_permission\": \"Cannot be saved with the current login account.\",\n    \"discuss_no_project_permission\": \"Cannot be saved with the current login account.\",\n    \"discuss_write_abuse_detected\": \"Several articles have been written within a \\nshort period of time. \\nPlease try again in 1 minutes.\",\n    \"contents_abuse_detected\": \"Please try again in 5 minutes.\",\n    \"contents_abuse_detected_10\": \"Please try again in 10 minutes.\",\n    \"discuss_new_write_abuse_warn\": \"Posting multiple comments within a \\nshort period of time may limit the post \\nof comments.\\nBe careful of your use.\",\n    \"discuss_write_abuse_warn\": \"Posting multiple comments within a \\nshort period of time may limit the post \\nof comments.\\nBe careful of your use.\",\n    \"find_not_your_email\": \"Please enter a valid email.\",\n    \"search_lang\": \"search\",\n    \"search_title\": \"title\",\n    \"faq_desc\": \"Check the answers for the questions you had while using the Entry.\",\n    \"faq_all\": \"Total\",\n    \"faq_site\": \"Site guide\",\n    \"faq_project\": \"Project\",\n    \"faq_hardware\": \"Hardware\",\n    \"faq_offline\": \"Offline editor\",\n    \"faq_copyright\": \"Copyright\",\n    \"faq_title\": \"FAQ\",\n    \"faq\": \"FAQ\",\n    \"malicious_warning\": \"You cannot attach an unwholesome image. If the image doesn't unwholesome, please report it.\",\n    \"fword_alert_msg\": \"You can not post abusive or malicious sentences.\",\n    \"fword_alert_1\": \"You can not post abusive comments or malicious comments\",\n    \"fword_alert_2\": \"Your post will be replaced alternative sentence because it contains unhealthy words.\",\n    \"fword_replace_1\": \"Entry is an education platform created to help anyone learn to code.\",\n    \"fword_replace_2\": \"Entry is an education platform created to help anyone learn to code.\",\n    \"fword_replace_3\": \"Entry is an education platform created to help anyone learn to code.\",\n    \"fword_replace_4\": \"Entry is an education platform created to help anyone learn to code.\",\n    \"fword_replace_5\": \"Entry is an education platform created to help anyone learn to code.\",\n    \"fword_replace_6\": \"Entry is an education platform created to help anyone learn to code.\",\n    \"fword_replace_7\": \"Entry is an education platform created to help anyone learn to code.\",\n    \"solve_quiz\": \"Quiz\",\n    \"submit_homework_first_title\": \"Complete! Submit an assignment\",\n    \"submit_homework_first_content\": \"Great work is done! Submit your assignment.<br>You may resubmit your assignment before the deadline.\",\n    \"submit_homework_again_title\": \"Resubmit\",\n    \"submit_homework_again_content\": \"This project has been submitted already.<br>Would you like to resubmit?\",\n    \"submit_homework_expired_title\": \"Submission Closed\",\n    \"submit_homework_expired_content\": \"Assignment deadline is over.\",\n    \"done_study_title\": \"Complete\",\n    \"done_study_content\": \"Fabulous project is complete\",\n    \"featured_courses\": \"Featured Courses\",\n    \"follow_along\": \"Follow Along\",\n    \"follow_along_desc\": \"Create various projects as you follow along step by step.\",\n    \"do_quiz\": \"Quiz\",\n    \"do_quiz_desc\": \"Check your knowledge through quizzes.\",\n    \"challenge\": \"Challenge\",\n    \"play\": \"Play\",\n    \"challenge_desc\": \"Learn programming concepts by solving problems.\",\n    \"creste_freely\": \"Create freely\",\n    \"creste_freely_desc\": \"Create your projects using what you've learned.\",\n    \"entry_rc_desc\": \"Learn programming concepts in steps with Entry lectures! Start now!\",\n    \"hw_deadline\": \"Deadline\",\n    \"rc_course_desc\": \"Lecture collection created for learning programming concepts level by level\",\n    \"rc_course\": \"Entry Recommended Courses\",\n    \"entry_rec_course\": \"Entry Recommended Courses\",\n    \"entry_rec_course_desc\": \"Anyone can follow along and easily create projects with Entry Lectures.\",\n    \"guidance\": \"Guidance\",\n    \"wait\": \"Wait\",\n    \"hint\": \"Hint\",\n    \"concept_guide\": \"Concept Guide\",\n    \"group_quiz\": \"Quiz\",\n    \"fail_check_hint\": \"Oh no! Try again!<br>Check [Hint] if you are stuck!\",\n    \"sort_student\": \"Student\",\n    \"sort_lesson\": \"Lesson\",\n    \"sort_course\": \"Course\",\n    \"student_progress\": \"Student Progress\",\n    \"my_progress\": \"Progress\",\n    \"lec_in_progress\": \"in progress\",\n    \"free_modal_asgn_over\": \"Assignment deadline is over.\",\n    \"free_submission_closed\": \"Submission Closed\",\n    \"free_modal_asgn_submit_first\": \"Great work is done! Submit your assignment.<br>You may resubmit your assignment before the deadline.\",\n    \"asgn_submit\": \"Complete! Submit an assignment.\",\n    \"free_modal_content_resubmit\": \"This project has been submitted already.<br>Would you like to resubmit?\",\n    \"asgn_resubmit\": \"Resubmit\",\n    \"free_modal_content_complete\": \"Fabulous Project is complete.\",\n    \"guide_modal_content_complete\": \"Let's run the program\",\n    \"success\": \"Success\",\n    \"fail\": \"Fail\",\n    \"mission_modal_content_fail\": \"<br>Check [Hint] if you are stuck!\",\n    \"mission_modal_content_success\": \"Let's run the program\",\n    \"in_progress\": \"in progress\",\n    \"completed\": \"Completed\",\n    \"submitted\": \"submitted\",\n    \"submission_closed\": \"Submission Closed\",\n    \"progress\": \"Progress\",\n    \"study_completed\": \"completed\",\n    \"view_course_desc\": \"View Description\",\n    \"main_entry_starter\": \"From basics! Entry Starter\",\n    \"main_entry_booster\": \"Concepts! Entry Booster\",\n    \"main_entry_master\": \"Ideas unfold! Entry Master\",\n    \"no_students_in_classroom\": \"No students yet.<br>Please add or invite students.\",\n    \"lectures\": \"lessons\",\n    \"Lectures\": \"Lessons\",\n    \"studentHomeworkList\": \"assignment\",\n    \"curriculums\": \"courseware\",\n    \"Curriculums\": \"Courseware\",\n    \"quiz\": \"quiz\",\n    \"no_added_group_contents_teacher\": \"There is no %1. <br>Please create a %1.\",\n    \"no_added_group_contents_student\": \"There is no %1.\",\n    \"side_project\": \"Goal project\",\n    \"custom_make_course_1\": \"Create courseware from\",\n    \"custom_make_course_2\": \"'Create lessons > Create Courseware'\",\n    \"custom_make_lecture_1\": \"Create lessons from 'open lessons'\",\n    \"custom_make_lecture_2\": \"\",\n    \"alert_enter_info\": \"Please enter your information\",\n    \"alert_enter_new_pwd\": \"Enter new password\",\n    \"alert_match_pwd\": \"Password doesn't match the confirmation\",\n    \"alert_check_pwd\": \"Please check your password\",\n    \"alert_update_complete\": \"Edit complete\",\n    \"no_group_contents_each_prefix\": \"There is no \",\n    \"no_group_contents_each_suffix\": \" in our classroom.\",\n    \"no_group_contents_all\": \"There is no new content.<br>Share projects in My Classroom gallery.\",\n    \"hw_closed\": \"submission closed\",\n    \"tag_Lecture\": \"Lessons\",\n    \"tag_Curriculum\": \"Courseware\",\n    \"tag_Discuss\": \"Discuss\",\n    \"count_ko\": \".\",\n    \"no_asgn_within_week\": \"There is no assignment due within a week\",\n    \"lecture_and_curriculum\": \"Open Lessons\",\n    \"assignments_plural\": \"Assignments\",\n    \"assignments_singular\": \"Assignment\",\n    \"project_plural\": \"Projects\",\n    \"group_news\": \"News\",\n    \"stu_management\": \"Student management\",\n    \"stu_management_camel\": \"Student Management\",\n    \"view_all\": \"View all\",\n    \"view_all_camel\": \"View All\",\n    \"view_contents_camel\": \"View All\",\n    \"view_contents\": \"Contents\",\n    \"no_updated_news\": \"There is no update\",\n    \"homework_soon_due\": \"Assignment soon due\",\n    \"new_homework\": \"New Assignment\",\n    \"no_new_homework\": \"There is no new Assignment\",\n    \"student_plural\": \"Students\",\n    \"discuss\": \"notice\",\n    \"basic_project\": \"Basic Project\",\n    \"no_permission\": \"You have no permission.\",\n    \"no_comment_write_permission\": \"Cannot write comments with the currently logged in account.\",\n    \"original_curriculum_deleted\": \"The original courseware was deleted\",\n    \"original_curriculum\": \"Original courseware\",\n    \"save_as_my_lecture\": \"Save as My Lecture\",\n    \"delete_confirm\": \"Confirm\",\n    \"lecture_open_as_copied\": \"All lectures in Open Lesson are saved as copy and open to public view\",\n    \"curriculum_open_as_copied\": \"All Courseware listed under Open Lesson are saved as copy and open to public view\",\n    \"lecture_save_as_copied_group\": \"All lectures in My Class Lecture are saved as copy and open to public view\",\n    \"curriculum_save_as_copied_group\": \"All Lecture Collection listed under My Class Lecture Collection are saved as copy and open to public view\",\n    \"homework_save_as_copied_group\": \"All Assignments listed under Class Assignment page are saved as copy and open to public view\",\n    \"lecture_save_as_copied\": \"Lecture inserted in the Lecture collection is saved as a copy.\",\n    \"done_project_save_as_copied\": \"Completed project inserted in the Lecture is saved as a copy.\",\n    \"textbook_project_can_not_applied\": \"\",\n    \"original_lecture_deleted\": \"The original lecture was deleted\",\n    \"original_lecture\": \"Original lecture\",\n    \"lecture_save_as_mine_alert\": \"Saved.\\nnSaved Lecture is listed under 'My Page > My Lecture'\",\n    \"lecture_save_as_mine\": \"Save as My Lecture\",\n    \"duplicate_username\": \"The ID you entered is already in use\",\n    \"share_your_project\": \"\",\n    \"not_available_student\": \"ID entered is class issued 'Class ID'. \\nPlease enter 'Entry Member ID'.\",\n    \"login_instruction\": \"Log-in instructions\",\n    \"login_needed\": \"Service is available after log-in\",\n    \"login_as_teacher\": \"Log in as Teacher to use the service\",\n    \"remove_my_storage\": \"Are you sure to remove it from my storage? Deleted blocks/objects cannot be recovered.\",\n    \"submit_hw\": \"submit\",\n    \"success_goal\": \"Success\",\n    \"choseok_final_result\": \"Great! I completed my own project!\",\n    \"choseok_fail_msg_timeout\": \"시간이 너무 많이 지나버렸어. 목표를 잘 보고 다시 한번 도전해봐!\",\n    \"choseok_fail_msg_die\": \"생명이 0이하인데 게임이 끝나지 않았어.\\n아래의 블록을 사용해서 다시 도전해 보는 건 어때?\",\n    \"grade_1\": \"Basic\",\n    \"grade_2\": \"Intermediate\",\n    \"grade_3\": \"Advanced\",\n    \"find_sally_title\": \"Finding Sally\",\n    \"save_sally_title\": \"Saving Sally\",\n    \"exit_sally_title\": \"Escaping\",\n    \"find_sally\": \"Combine the power of the LINE Rangers\\nand defeat the powerful villain Mephisto\\nand save Sally!\",\n    \"save_sally\": \"Sally is trapped at Mephisto's base.\\nHelp the LINE Rangers get to Sally by avoiding\\nobstacles!\",\n    \"exit_sally\": \"Help Sally and LINE Rangers escape safely\\nfrom the exploding Mephisto base!\",\n    \"go_next_mission\": \"다른 미션 도전하기\",\n    \"share_my_project\": \"내가 만든 작품 공유하기\",\n    \"share_certification\": \"인증서 공유하기\",\n    \"print_certification\": \"인증서를 뽐내봐\",\n    \"get_cparty_events\": \"내가 받은 인증서를 출력해 뽐내면 푸짐한 상품을 받을 수 있어요!\",\n    \"go_cparty_events\": \"이벤트 참여하러 가기\",\n    \"codingparty2016_blockHelper_1_title\": \"\",\n    \"codingparty2016_blockHelper_1_contents\": \"\",\n    \"codingparty2016_blockHelper_2_title\": \"\",\n    \"codingparty2016_blockHelper_2_contents\": \"\",\n    \"codingparty2016_blockHelper_3_title\": \"\",\n    \"codingparty2016_blockHelper_3_contents\": \"\",\n    \"codingparty2016_blockHelper_4_title\": \"\",\n    \"codingparty2016_blockHelper_4_contents\": \"\",\n    \"codingparty2016_blockHelper_5_title\": \"\",\n    \"codingparty2016_blockHelper_5_contents\": \"\",\n    \"codingparty2016_goalHint_1\": \"\",\n    \"codingparty2016_goalHint_2\": \"\",\n    \"codingparty2016_goalHint_3\": \"\",\n    \"codingparty2016_goalHint_4\": \"\",\n    \"codingparty2016_goalHint_5\": \"\",\n    \"codingparty2016_goalHint_6\": \"\",\n    \"codingparty2016_goalHint_7\": \"\",\n    \"codingparty2016_goalHint_8\": \"\",\n    \"codingparty2016_goalHint_9\": \"\",\n    \"codingparty2016_guide_1_1_contents\": \"\",\n    \"codingparty2016_guide_1_1_title\": \"\",\n    \"codingparty2016_guide_1_2_title\": \"\",\n    \"codingparty2016_guide_1_2_contents\": \"\",\n    \"codingparty2016_guide_1_3_title\": \"\",\n    \"codingparty2016_guide_1_3_contents\": \"\",\n    \"codingparty2016_guide_1_4_title\": \"\",\n    \"codingparty2016_guide_1_4_contents\": \"\",\n    \"codingparty2016_guide_1_5_title\": \"\",\n    \"codingparty2016_guide_1_5_contents\": \"\",\n    \"codingparty2016_guide_2_1_title\": \"\",\n    \"codingparty2016_guide_2_1_contents\": \"\",\n    \"codingparty2016_guide_3_1_title\": \"\",\n    \"codingparty2016_guide_3_1_contents\": \"\",\n    \"codingparty2016_guide_5_1_title\": \"\",\n    \"codingparty2016_guide_5_1_contents\": \"\",\n    \"codingparty2016_guide_5_2_title\": \"\",\n    \"codingparty2016_guide_5_2_contents\": \"\",\n    \"codingparty2016_guide_7_1_title\": \"\",\n    \"codingparty2016_guide_7_1_contents\": \"\",\n    \"codingparty2016_guide_9_1_title\": \"\",\n    \"codingparty2016_guide_9_1_contents\": \"\",\n    \"codingparty2016_guide_9_2_title\": \"\",\n    \"codingparty2016_guide_9_2_contents\": \"\",\n    \"find_interesting_lesson\": \"Browse through 'Class lessons’ section to find interesting lessons!\",\n    \"find_interesting_course\": \"Browse through 'Class courseware’ section to find interesting courseware!\",\n    \"select_share_settings\": \"Select share settings\",\n    \"faq_banner_title\": \"FAQ\",\n    \"check_out_faq\": \"Check out Entry’s FAQ\",\n    \"faq_banner_content\": \"Do you have any question about Entry?<br />We give you the answer in FAQ.<br />Find out now!\",\n    \"faq_banner_button\": \"Go to FAQ\",\n    \"major_updates\": \"Major updates\",\n    \"check_new_update\": \"Check out\\nEntry's new updates\",\n    \"major_updates_notification\": \"Entry's major updates are announced by notification. \",\n    \"find_out_now\": \"Find out now!\",\n    \"offline_hw_program\": \"Offline and Hardware Connection Program\",\n    \"read_more\": \"read more\",\n    \"sample_project\": \"Sample Project\",\n    \"not_supported_function\": \"thiết bị này không được hỗ trợ\",\n    \"offline_download_confirm\": \"Entry Offline Editor is available for PC. Would you like to download?\",\n    \"hardware_download_confirm\": \"Entry Hardware Program is available for PC. Would you like to download?\",\n    \"copy_text\": \"Copy text.\",\n    \"select_openArea_space\": \"Select share settings\",\n    \"mission_guide\": \"Mission guide\",\n    \"of\": \" 's  \",\n    \"no_results_found\": \"No results found\",\n    \"upload_pdf\": \"Upload PDF materials\",\n    \"select_basic_project\": \"Select Project\",\n    \"try_it_out\": \"TRY IT OUT\",\n    \"go_boardgame\": \"ENTRY-Bot Board Game\",\n    \"go_cardgame\": \"ENTRY Bot Card game\",\n    \"go_solve\": \"Learn programming\",\n    \"go_ws\": \"Entry Create\",\n    \"go_arts\": \"Entry Share\",\n    \"group_delete_alert\": \"Once you delete this class, all data including temporary student accounts will be deleted.\\nAre you sure you want to delete?\",\n    \"view_arts_list\": \"list\",\n    \"hw_submit_confirm_alert\": \"Assignment submitted\",\n    \"hw_submit_alert\": \"Would you like to submit your assignment?\",\n    \"hw_submit_alert2\": \"Would you like to submit your assignment? Submission will only submit what you've completed.\",\n    \"hw_submit_cannot\": \"You cannot submit this assignment\",\n    \"see_other_missions\": \"See other missions\",\n    \"project\": \"Project\",\n    \"marked\": \"favorite\",\n    \"group\": \"group\",\n    \"lecture\": \"Lessons\",\n    \"Lecture\": \"Lessons\",\n    \"curriculum\": \"Courseware\",\n    \"Curriculum\": \"Courseware\",\n    \"studying\": \"studying\",\n    \"open_only_shared_lecture\": \"<b>오픈 강의</b> 페이지에 <b><공개></b> 한 강의만 불러올 수 있습니다. 불러오고자 하는 <b>강의</b>의 <b>공개여부</b>를 확인해 주세요.\",\n    \"already_exist_group\": \"group already exists\",\n    \"cannot_invite_you\": \"Can't invite by yourself\",\n    \"apply_original_image\": \"Save original image\",\n    \"draw_new_ques\": \"Are you sure you want to go to \\n'Draw new object' page?\",\n    \"draw_new_ques_1\": \"You can draw an object and save it.\",\n    \"draw_new_ques_2\": \"do you want to move to draw?\",\n    \"draw_new_go\": \"Move\",\n    \"draw_new_stay\": \"No, Stay\",\n    \"file_upload_warn_title_image\": \"The following pictures are subject to the Terms of Use and related laws.\",\n    \"file_upload_warn_desc_image\": \"Violent and brutal picture<br>Sacred body exposure picture<br>Offensive or disgusting picture<br>Picture of copyright prohibited from unauthorized use\",\n    \"file_upload_warn_title_sound\": \"The following sounds are subject to the Terms of Use and related laws.\",\n    \"file_upload_warn_desc_sound\": \"Violent and cruel sound<br>Suggestive sound<br>Offensive or disgusting sound<br>Sound of copyright prohibited from unauthorized use\",\n    \"file_upload_warn_title_table\": \"The following datas are subject to the Terms of Use and related laws.\",\n    \"file_upload_warn_desc_table\": \"Violent and brutal data<br>Sacred body exposure data<br>Offensive or disgusting data<br>Data of copyright prohibited from unauthorized use\",\n    \"file_upload_warn_link\": \"Learn about copyright\",\n    \"file_upload_desc_1\": \"Make sure you don't upload\",\n    \"file_upload_desc_2\": \"Violent and brutal picture\",\n    \"file_upload_desc_3\": \"Sacred body exposure picture\",\n    \"file_upload_desc_4\": \"Offensive or disgusting picture\",\n    \"file_upload_desc_5\": \"* Uploading of above contents may be restricted under user policy and related laws.\",\n    \"picture_upload_warn_old\": \"You can only upload jpg, png, bmp files that are less than 10MB.\",\n    \"sprite_upload_warn_old\": \"You can only upload images in jpg, png, bmp format or objects in eo format that are less than 10MB.\",\n    \"picture_upload_warn_1\": \"You can only upload jpg, png, bmp, svg files that are less than 10MB.\\nThe jpg, png, and bmp images are edited in bitmap mode and the svg image is in vector mode.\",\n    \"table_upload_warn_1\": \"You can only upload csv, xls(x) files that are less than 10MB.\",\n    \"sprite_upload_warn\": \"You can only upload images in jpg, png, bmp, svg format or objects in eo format that are less than 10MB.\",\n    \"sound_upload_warn_1\": \"You can only upload mp3 files that are less than 10MB.\",\n    \"sound_edit_warn\": \"Please wait!<br>We're working on the Sound Editing function.\",\n    \"file_upload_loading\": \"Loading\",\n    \"lesson_by_teacher\": \"Teacher created lesson\",\n    \"delete_group_art\": \"from the list?\",\n    \"elementary_short\": \"elementary\",\n    \"middle_short\": \"middle school\",\n    \"grade_34\": \"3-4th\",\n    \"grade_56\": \"5-6th\",\n    \"grade_78\": \"7+\",\n    \"share_lesson\": \"sharing lesson\",\n    \"share_course\": \"sharing courseware\",\n    \"from_list_ko\": \"\",\n    \"comming_soon\": \"Coming soon\",\n    \"no_class_alert\": \"Class selected does not exist. To create a class, go to 'My Class' to create a class.\",\n    \"students_cnt\": \"\",\n    \"defult_class_alert_1\": \"Do you want to set \",\n    \"defult_class_alert_2\": \"\\n as default class?\",\n    \"default_class\": \"Default classroom\",\n    \"enter_hw_name\": \"Enter Assignment name.\",\n    \"hw_limit_20\": \"You can created up to 20 assignments\",\n    \"stu_example\": \"Example)\\n John Doe\\n John Doe\\n John Doe\",\n    \"hw_description_limit_200\": \"Add assignment description. (within 200 characters)\",\n    \"hw_title_limit_50\": \"Enter Assignment name. (within 50 characters)\",\n    \"create_project_class_1\": \"Create projects you want to share \",\n    \"create_project_class_2\": \"with the class from 'Create> Create Project'\",\n    \"create_lesson_assignment_1\": \"Create lessons you want to add as\",\n    \"create_lesson_assignment_2\": \"course assignment from 'Create > Create lessons'\",\n    \"i_make_lesson\": \"Create lessons\",\n    \"lesson_to_class_1\": \"'Favorite lessons you want to add as\",\n    \"lesson_to_class_2\": \"course assignment from 'Learn > Open lessons'\",\n    \"studying_students\": \"Student\",\n    \"lessons_count\": \"Number of Lessons\",\n    \"group_out\": \"Leave\",\n    \"enter_group_code\": \"Enter class code\",\n    \"no_group_invite\": \"There is no class invitation\",\n    \"done_create_group\": \"Class is created\",\n    \"set_default_group\": \"Set as default classroom\",\n    \"edit_group_info\": \"Modify class information\",\n    \"edit_done\": \"Edit complete\",\n    \"alert_group_out\": \"Do you want to leave the class?\",\n    \"lesson_share_cancel\": \"Cancel Sharing Lesson\",\n    \"project_share_cancel\": \"Cancel Sharing Project\",\n    \"lesson_share_cancel_alert\": \"Are you sure to change it?\",\n    \"course_share_cancel\": \"Cancel Sharing Courseware\",\n    \"select_lesson_share\": \"Select lesson to share\",\n    \"select_project_share\": \"Select project to share\",\n    \"select_lesson_share_policy_1\": \"Please check share settings\",\n    \"select_lesson_share_policyAdd\": \"Please check share settings\",\n    \"select_lesson_share_project_1\": \"Please check share settings\",\n    \"select_lesson_share_policy_2\": \"and copyright policies\",\n    \"select_lesson_share_area\": \"Select share settings\",\n    \"select_project_share_area\": \"Select share settings\",\n    \"lesson_share_policy\": \"I agree to Entry's Copyright Policies.\",\n    \"project_share_policy\": \"I agree to Entry's Copyright Policies.\",\n    \"alert_agree_share\": \"To share publicly, you must agree to Entry's copyright policies\",\n    \"alert_agree_all\": \"Agree to all items\",\n    \"select_course_share\": \"Select courseware to share\",\n    \"select_course_share_policy_1\": \"Please check share settings\",\n    \"select_course_share_policy_2\": \"and copyright policies\",\n    \"select_course_share_area\": \"Select share settings\",\n    \"course_share_policy\": \"I agree to Entry's Copyright Policies.\",\n    \"issued\": \"Issued\",\n    \"code_expired\": \"Code has expired. Press 'Reissue Code' button\",\n    \"accept_class_invite\": \"Accept class invitation\",\n    \"welcome_class\": \"Welcome to the class.\",\n    \"enter_info\": \"Please enter your information.\",\n    \"done_group_signup\": \"You have successfully enrolled to this class\",\n    \"enter_group_code_stu\": \"Enter the class code sent from your teacher\",\n    \"text_limit_50\": \"Enter 50 characters or less.\",\n    \"enter_class_name\": \"Please enter your class name\",\n    \"enter_grade\": \"Please enter your  grade\",\n    \"enter_class_info\": \"Please enter your class introduction\",\n    \"student_dup\": \"exits in this class already.\",\n    \"select_stu_print\": \"Select student to print\",\n    \"class_id_not_exist\": \"The class ID does not exist\",\n    \"error_try_again\": \"Error occured. Please try again\",\n    \"error_forbidden\": \"You have no permission\",\n    \"code_not_available\": \"The code is not valid\",\n    \"gnb_create_lessons\": \"Create lessons\",\n    \"study_lessons\": \"Learn Lesson\",\n    \"lecture_help_1\": \"Select the base project that the learner will start building his/her project on.\",\n    \"lecture_help_2\": \"To see this help message again, click the button above.\",\n    \"lecture_help_3\": \"If 'add object' is not shown, adding or deleting object is not possible.\",\n    \"lecture_help_4\": \"See PDF attachment to get help\",\n    \"lecture_help_5\": \"Select blocks needed to create project. Unselected blocks will be hidden.\",\n    \"lecture_help_6\": \"choose between block Coding and Entry Python to organize your learning environment.\",\n    \"lecture_finish_popup_title\": \"re-learn\",\n    \"lecture_finish_popup_content_1\": \"Practice Completion Do you want to practice one step from the beginning?\",\n    \"lecture_finish_popup_content_2\": \"* The practice completion status is maintained\",\n    \"lecture_start_title\": \"Start\",\n    \"lecture_goal_title\": \"Goal\",\n    \"lecture_goal_content\": \"Goal\",\n    \"lecture_prepare_title\": \"Prepare\",\n    \"lecture_summary_title\": \"Summary\",\n    \"lecture_summary_content\": \"Let's summarize what we learned.\",\n    \"lecture_quiz_title\": \"Quiz\",\n    \"lecture_quiz_content\": \"Let's check what we learned through the verification problem.\",\n    \"lecture_quiz_check_answer\": \"Check the answer\",\n    \"default_hint_title\": \"How do you make it?\",\n    \"only_pdf\": \"Only pdf file is uploadable\",\n    \"enter_project_video\": \"Enter at least one project or video\",\n    \"enter_title\": \"Enter title.\",\n    \"enter_recommanded_grade\": \"Enter recommanded grade.\",\n    \"enter_level_diff\": \"Enter level of difficulty.\",\n    \"enter_time_spent\": \"Enter time spent.\",\n    \"enter_shared_area\": \"Select at least one sharing space\",\n    \"enter_goals\": \"Enter goals\",\n    \"enter_lecture_description\": \"Enter lecture information\",\n    \"enter_curriculum_description\": \"Enter courseware information\",\n    \"first_page\": \"처음 입니다.\",\n    \"last_page\": \"마지막 입니다.\",\n    \"alert_duplicate_lecture\": \"The lesson is already registered\",\n    \"enter_lesson_alert\": \"Register one or more lessons\",\n    \"open_edit_lessons\": \"Open lesson to be edited\",\n    \"saved_alert\": \"was successfully saved.\",\n    \"select_lesson_type\": \"Select type of lesson you want to create.\",\n    \"create_lesson\": \"create lesson\",\n    \"create_lesson_desc_1\": \"create a lesson\",\n    \"create_lesson_desc_2\": \"according to learning objectives\",\n    \"create_lesson_desc_3\": \"for your course.\",\n    \"create_courseware\": \"Create courseware\",\n    \"create_courseware_desc_1\": \"put multiple lessons together\",\n    \"create_courseware_desc_2\": \"to create a courseware\",\n    \"create_courseware_desc_3\": \"\",\n    \"create_open_lesson\": \"Create open lesson\",\n    \"enter_lesson_info\": \"Enter lesson information\",\n    \"select_lesson_feature\": \"Select lesson feature\",\n    \"check_info_entered\": \"Check information entered\",\n    \"enter_lefo_lesson_long\": \"Enter information about the lesson.\",\n    \"lesson_info_desc\": \"Select features and projects that learners will use to create optimal learning environment.\",\n    \"provide_only_used\": \"Only provide blocks used in the goal project\",\n    \"see_help\": \"See help\",\n    \"select_done_project_1\": \"Select\",\n    \"select_done_project_2\": \"the goal project\",\n    \"select_done_project_3\": \"that the learner is to create\",\n    \"select_project\": \"Select my project or my favorite project\",\n    \"youtube_desc\": \"Enter Youtube links\",\n    \"lesson_video\": \"Lesson video\",\n    \"lesson_title\": \"Lesson title\",\n    \"recommended_grade\": \"grade level\",\n    \"selection_ko\": \"\",\n    \"selection_en\": \"Select\",\n    \"level_of_diff\": \"difficulty\",\n    \"select_level_of_diff\": \"Select difficulty\",\n    \"enter_lesson_title\": \"enter lesson title (in 30 characters or less)\",\n    \"select_time_spent\": \"Select time\",\n    \"time_spent\": \"time\",\n    \"lesson_overview\": \"Lesson Overview\",\n    \"upload_materials\": \"Upload course materials\",\n    \"open\": \"Open\",\n    \"cancel\": \"Cancel\",\n    \"upload_lesson_video\": \"Upload lesson video\",\n    \"youtube_upload_desc\": \"Insert Youtube link for course videos\",\n    \"cancel_select\": \"Undo select\",\n    \"select_again\": \"Select again\",\n    \"goal_project\": \"Goal\",\n    \"upload_study_data\": \"Upload learning materials that learners can view while building the project.\",\n    \"upload_limit_20mb\": \"Upload up to 20MB\",\n    \"expect_time\": \"Time spent\",\n    \"course_videos\": \"course videos\",\n    \"enter_courseware_info\": \"Enter courseware information\",\n    \"enter_course_info\": \"Enter courseware information\",\n    \"select_lessons_for_course\": \"Select lessons to create a courseware.\",\n    \"course_build_desc_1\": \"\",\n    \"course_build_desc_2\": \"Up to 30 lessons\",\n    \"course_build_desc_3\": \"allowed.\",\n    \"lseeon_list\": \"show lesson List\",\n    \"open_lessons\": \"Open lessons\",\n    \"course_title\": \"Courseware title\",\n    \"title_limit_30\": \"Enter courseware title(within 30 characters)\",\n    \"course_overview\": \"Courseware Overview\",\n    \"charactert_limit_200\": \"Enter within 200 characters\",\n    \"edit_lesson\": \"Edit lesson\",\n    \"courseware_by_teacher\": \"Teacher created lesson collections\",\n    \"select_lessons\": \"Select lessons\",\n    \"check_course_info\": \"Check if the lesson collection information is correct\",\n    \"select_share_area\": \"Select sharing space\",\n    \"upload_sub_project\": \"Goal project upload\",\n    \"file_download\": \"Download file\",\n    \"file_remove\": \"Remove file\",\n    \"check_lesson_info\": \"Check if the lesson information is correct\",\n    \"share_area\": \"Sharing space\",\n    \"enter_sub_project\": \"Register side project\",\n    \"lms_hw_title\": \"Title\",\n    \"lms_hw_ready\": \"Ready\",\n    \"lms_hw_progress\": \"In progress\",\n    \"lms_hw_complete\": \"Complete\",\n    \"lms_hw_not_submit\": \"Unfinished\",\n    \"lms_hw_closed\": \"Closed\",\n    \"submission_condition\": \"Submission is allowed only for assignments in progress\",\n    \"submit_students_only\": \"Only students are allowed to submit assignments\",\n    \"want_submit_hw\": \"Are you sure you want to submit your assignment?\",\n    \"enter_correct_id\": \"Enter correct ID\",\n    \"id_not_exist\": \"The ID does not exist.\",\n    \"agree_class_policy\": \"Agree to class service usage policy.\",\n    \"delete_class\": \"Delete classs\",\n    \"type_stu_name\": \"Please enter the student name.\",\n    \"invite_from_1\": \"is invited to\",\n    \"invite_from_2\": \"\",\n    \"lms_pw_alert_1\": \"Once you enter class,\",\n    \"lms_pw_alert_2\": \"teacher is allowed to reissue your login password.\",\n    \"lms_pw_alert_3\": \"Make sure that the invitation is from your teacher.\",\n    \"invitation_accepted\": \"Invitation Accepted!\",\n    \"cannot_issue_pw\": \"Password cannot be issued because invitation has not been accepted\",\n    \"start_me_1\": \"Start coding education\",\n    \"start_me_2\": \"with <Monthly Entry>!\",\n    \"monthly_desc_1\": \"Monthly Entry is a monthly distributed magazine created \",\n    \"monthly_desc_2\": \"to help teachers learn to teach programming in fun and easy way.\",\n    \"monthly_desc_3\": \"Check out the fun cartoons and programming contents every month!\",\n    \"monthly_desc_4\": \"* The Monthly Entry has ceased publication.\",\n    \"monthly_desc_5\": \"Download educational materials from the Educational Materials page.\",\n    \"monthly_entry\": \"Monthly Entry\",\n    \"me_desc_1\": \"Meet Monthly Entry magazine distributed monthly!\",\n    \"me_desc_2\": \"\",\n    \"solve_desc_1\": \"Learn the basics of\",\n    \"solve_desc_2\": \"software programming by solving\",\n    \"playSw_desc_1\": \"Learn to code by watching EBS TV Series and special tutorial videos!\",\n    \"playSw_desc_2\": \"\",\n    \"recommended_lessons\": \"Recommendations\",\n    \"recommended_lessons_1\": \"Follow along, challenge, solve quizzes and learn to program with Entry!\",\n    \"recommended_lessons_2\": \"\",\n    \"offline_top_desc_1\": \"Offline Editor's Save Feature has improved as well as security.\",\n    \"offline_top_desc_2\": \"Download now\",\n    \"offline_main_desc\": \"Update Entry Offline Editor\",\n    \"art_description\": \"This is a project sharing space. Create your own project and share.\",\n    \"art_description_1\": \"\",\n    \"art_description_2\": \"projects created. Create your own project and share.\",\n    \"study_index\": \"Learn to code with Entry's coursewares by topic and grade levels\",\n    \"study_for_beginner\": \"Entry First Steps for Starters\",\n    \"entrybot_desc_3\": \"Take Entrybot to school\",\n    \"entrybot_desc_4\": \"by assembling command blocks\",\n    \"move_entrybot\": \"Control Entrybot\",\n    \"can_change_entrybot_1\": \"Change Entrybot's color, make it talk\",\n    \"can_change_entrybot_2\": \"using block commands\",\n    \"learning_process_by_topics\": \"Courseware by topic\",\n    \"show_detail\": \"See Details\",\n    \"solve_mission\": \"Solve Mission\",\n    \"solve_mission_desc_1\": \"Learn to code while playing games and solving missions!\",\n    \"solve_mission_desc_2\": \"Control Entrybot move through the maze so it can reach its destination while learning the concepts of sequence, repeat, select and comparison.\",\n    \"learning_process_by_grades\": \"Courseware by grade levels\",\n    \"learning_process_by_grades_sub1\": \"Learn programming concepts in steps with Entry lectures! Start now!\",\n    \"e3_to_e4\": \"Elementary 3-4th grade\",\n    \"e5_to_e6\": \"Elementary 5-6th grade\",\n    \"m1_to_m3\": \"7th+ and above\",\n    \"make_using_entry\": \"Create projects with Entry\",\n    \"make_using_entry_desc_1\": \"Assemble block to create your own program!\",\n    \"make_using_entry_desc_2\": \"Download and follow along the learning materials to create animation, media art, game and other fun programs.\",\n    \"make_through_ebs_1\": \"Learn to code by watching EBS TV Series.\",\n    \"make_through_ebs_2\": \"The fun TV Series are accompanied by step-by-step tutorial videos so anyone can easily create programs.\",\n    \"support_block_js\": \"Block code and javascript are supported\",\n    \"study_ebs_title_1\": \"순서대로! 차례대로!\",\n    \"study_ebs_desc_1\": \"[실습] 엔트리봇의 심부름\",\n    \"study_ebs_title_2\": \"쉽고 간단하게!\",\n    \"study_ebs_desc_2\": \"[실습] 꽃송이 만들기\",\n    \"study_ebs_title_3\": \"언제 시작할까?\",\n    \"study_ebs_desc_3\": \"[실습] 동물가족 소개\",\n    \"study_ebs_title_4\": \"다른 선택, 다른 결과!\",\n    \"study_ebs_desc_4\": \"[실습] 텔레파시 게임\",\n    \"study_ebs_title_5\": \"정보를 담는 그릇\",\n    \"study_ebs_desc_5\": \"[실습] 덧셈 로봇 만들기\",\n    \"study_ebs_title_6\": \"요모조 따져 봐!\",\n    \"study_ebs_desc_6\": \"[실습] 복불복 룰렛\",\n    \"study_ebs_title_7\": \"번호로 부르면 편해요!\",\n    \"study_ebs_desc_7\": \"[실습] 나만의 버킷리스트\",\n    \"study_ebs_title_8\": \"무작위 프로그램을 만들어라!\",\n    \"study_ebs_desc_8\": \"[실습] 무작위 캐릭터 만들기\",\n    \"study_ebs_title_9\": \"어떻게 찾을까?\",\n    \"study_ebs_desc_9\": \"[실습] 도서관 책 검색\",\n    \"study_ebs_title_10\": \"줄을 서시오!\",\n    \"study_ebs_desc_10\": \"[실습] 키 정렬 프로그램\",\n    \"event\": \"이벤트\",\n    \"divide\": \"분기\",\n    \"condition\": \"conditionals\",\n    \"random_number\": \"무작위수\",\n    \"search\": \"탐색\",\n    \"sorting\": \"정렬\",\n    \"parallel\": \"병렬\",\n    \"signal\": \"신호\",\n    \"input_output\": \"입출력\",\n    \"sequential\": \"sequence\",\n    \"repeat\": \"repeat\",\n    \"choice\": \"selection\",\n    \"repeat_advanced\": \"repeat(sequence+condition)\",\n    \"function\": \"function\",\n    \"compare_operation\": \"comparison\",\n    \"arithmetic\": \"산술연산\",\n    \"entry_recommended_mission\": \"Entry Recommended Mission\",\n    \"more_mission\": \"More Mission\",\n    \"line_rangers_title\": \"Saving Sally with\\nLINE Rangers\",\n    \"line_rangers_content\": \"Save Sally trapped\\nin the Mepisto base.\",\n    \"pinkbean_title_string_basic\": \"Maple Story Basic Henesys\",\n    \"pinkbean_title_string_intermediate\": \"Maple Story Intermediate Ellinia\",\n    \"pinkbean_title_string_advanced\": \"Maple Story Advanced Elnath\",\n    \"pinkbean_title\": \"To the Maple World\\nwith PINK BEAN!\",\n    \"pinkbean_content\": \"Help Pinkbean to finish\\nhis Maple World adventure.\",\n    \"entrybot_school\": \"Go to school\",\n    \"entrybot_school_desc_1\": \"Help Entrybot to get backpack and go to school\",\n    \"entrybot_school_desc_2\": \"\",\n    \"robot_factory\": \"Robot Factory\",\n    \"robot_factory_desc_1\": \"Entrybot is trapped in a robot factory!\",\n    \"robot_factory_desc_2\": \"Collect all parts to escape the factory.\",\n    \"electric_car\": \"Electric Car\",\n    \"electric_car_desc_1\": \"Help Entrybot's car move forward \",\n    \"electric_car_desc_2\": \"by making sure it has enough fuel.\",\n    \"forest_adventure\": \"Forest Adventures\",\n    \"forest_adventure_desc_1\": \"Entrybot's friends are trapped in the forest!\",\n    \"forest_adventure_desc_2\": \"Help Entrybot's friends escape.\",\n    \"town_adventure\": \"Village Adventures\",\n    \"town_adventure_desc_1\": \"Help Entrybot find fuel\",\n    \"town_adventure_desc_2\": \"in the village.\",\n    \"space_trip\": \"Space Travels\",\n    \"space_trip_desc_1\": \"Entrybot just completed its space exploration.\",\n    \"space_trip_desc_2\": \"Help Entrybot return to Earth.\",\n    \"learn_programming_mission\": \"Learn programming by playing challenges\",\n    \"make_open_lecture\": \"Create open lessons\",\n    \"group_created\": \"Class created\",\n    \"group_signup\": \"Class enrolled\",\n    \"delete_from_list\": \"from the list?\",\n    \"delete_from_list_en\": \"Are you sure you want to delete\",\n    \"lecture_collection\": \"Courseware\",\n    \"edit_mypage_profile\": \"Managae my info\",\n    \"main_image\": \"Main image\",\n    \"edit_profile_success\": \"Applied.\",\n    \"no_project_1\": \"There are no projects to show.\",\n    \"no_project_2\": \"How about creating your project now?\",\n    \"empty_project_1\": \"There is no work made yet.\",\n    \"no_marked_project_1\": \"There is no favorite project at this moment.\",\n    \"no_marked_group_project_1\": \"There is no favorite class project at this moment.\",\n    \"no_marked_project_2\": \"'Browse through 'Share' section to find interesting projects! \",\n    \"no_markedGroup_project_2\": \"Browse through 'Class share' section to find interesting projects!\",\n    \"view_project_all\": \"Browse project\",\n    \"no_lecture_1\": \"There are no lessons to show.\",\n    \"empty_lecture_1\": \"There is no lecture made yet.\",\n    \"no_lecture_2\": \"Create lessons from 'open lessons'\",\n    \"no_marked_lecture_1\": \"There is no favorite lesson to show.\",\n    \"no_marked_group_lecture_1\": \"There is no favorite class lesson to show.\",\n    \"no_marked_lecture_2\": \"Browse through 'Open lessons' to see various lessons!\",\n    \"view_lecture\": \"Browse lessons\",\n    \"no_studying_lecture_1\": \"There are no lessons to show.\",\n    \"no_studying_lecture_2\": \"Start learning from 'Open lessons' section!\",\n    \"no_lecture_collect_1\": \"There are no courseware to show.\",\n    \"empty_lecture_collect_1\": \"There is no courseware made yet.\",\n    \"no_lecture_collect_2\": \"Create courseware from 'Create open courseware'\",\n    \"make_lecture_collection\": \"Create courseware\",\n    \"no_marked_lecture_collect_1\": \"There is no favorite courseware to show.\",\n    \"no_marked_lecture_group_collect_1\": \"There is no favorite class courseware to show.\",\n    \"no_marked_lecture_collect_2\": \"Browse through 'Open lessons' to see various lessons!\",\n    \"view_lecture_collection\": \"Browse courseware\",\n    \"no_studying_lecture_collect_1\": \"There are no courseware to show.\",\n    \"no_studying_lecture_collect_2\": \"Start learning from 'Open lessons' section!\",\n    \"my_lecture\": \"My lessons\",\n    \"markedGroup\": \"Favorite group\",\n    \"markedGroup_lecture\": \"Favorite group lessons\",\n    \"markedGroup_curriculum\": \"Favorite group curriculum\",\n    \"marked_lecture\": \"Favorite lessons\",\n    \"marked_lecture_collection\": \"My courseware\",\n    \"marked_marked_curriculum\": \"My courseware\",\n    \"studying_lecture\": \"Lessons in progress\",\n    \"completed_lecture\": \"Lessons completed\",\n    \"my_lecture_collection\": \"My courseware\",\n    \"my\": \"My\",\n    \"studying_lecture_collection\": \"Courseware in progress\",\n    \"completed_lecture_collection\": \"Courseware completed\",\n    \"my_curriculum\": \"My Courses\",\n    \"studying_curriculum\": \"Courseware in progress\",\n    \"completed_curriculum\": \"Courseware completed\",\n    \"materialCC\": \"All contents provided are released under Creative Commons CC-BY 2.0 License.\",\n    \"materialccby_new\": \"All contents provided are released under Creative Commons CC-BY 2.0 License.\",\n    \"entry_copyright_info\": \"ENTRY copyright guide\",\n    \"pdf\": \"PDF\",\n    \"helper\": \"helper\",\n    \"youtube\": \"vedio\",\n    \"tvcast\": \"vedio\",\n    \"goal\": \"goal\",\n    \"basicproject\": \"basic\",\n    \"hw\": \"phần cứng\",\n    \"object\": \"object\",\n    \"console\": \"console\",\n    \"download_info\": \"Click on the title to download resource\",\n    \"entry_materials_all\": \"Entry Educational Materials\",\n    \"entry_material\": \"Learning Entry\",\n    \"recommand_grade\": \"Grade levels\",\n    \"g3_4_grades\": \"3-4th\",\n    \"g5_6_grades\": \"5-6th\",\n    \"middle_grades\": \"7th+\",\n    \"entry_go_go\": \"Entry Go Go!\",\n    \"entry_go_go_desc\": \"Explore a set of courseware, student activity book and teacher's guide\",\n    \"entry_go_go_desc2\": \"ndevided by grade and difficulty.\",\n    \"stage_beginner\": \"Basic\",\n    \"stage_middle\": \"Advanced\",\n    \"stage_high\": \"Expert\",\n    \"middle_school_short\": \"7th+\",\n    \"learn_entry_programming\": \"Follow along step by step.\",\n    \"entry_programming_desc\": \"Entry Programming: Become an Entry expert!\",\n    \"ebs\": \"\",\n    \"ebs_material_desc\": \"Teach using the EBS TV Series and Teacher's Guide!\",\n    \"season_1_material\": \"Season 1 Teacher's Guide\",\n    \"season_2_material\": \"Season 2 Teacher's Guide\",\n    \"season_1\": \"Season 1\",\n    \"playsoftware_ebs\": \"EBS Let’s play, SW!\",\n    \"material_teacher_guide\": \"Teacher's Guide\",\n    \"season_2\": \"Season 2\",\n    \"compute_think_textbook\": \"Improve computational thinking skills\",\n    \"computational_sw\": \"Learn to code for subjects such as language arts, math, science, fine arts!\",\n    \"python_coding_text\": \"Entry Python\",\n    \"python_coding_textbook\": \"Travel to the text coding world! Entry Python\",\n    \"python_coding_desc\": \"Learn the structure and grammar of text coding with Entry Python!\",\n    \"entry_x_hardware_text\": \"Entry X Hardware\",\n    \"entry_x_hardware\": \"Entry Hardware Educational Materials\",\n    \"e_sensor\": \"E Sensorboard\",\n    \"e_sensor_board\": \"E Sensor-board\",\n    \"e_sensor_robot\": \"E Sensor-robot\",\n    \"arduino\": \"Arduino\",\n    \"arduinoext\": \"ArduinoExt Uno\",\n    \"arduinonano\": \"Arduino Nano\",\n    \"albert\": \"albert\",\n    \"orange_board\": \"orangeBoard\",\n    \"arduino_board\": \"Arduino\",\n    \"joystick\": \"joystick sensor shield\",\n    \"ardublock\": \"ardublock\",\n    \"mkboard\": \"digital monkeyboard\",\n    \"mechatro_nano\": \"Mechatro Nano+\",\n    \"mechatro_uno\": \"Mechatro Uno+\",\n    \"memaker\": \"memaker\",\n    \"edumaker\": \"EduMaker Board\",\n    \"codingtoolbox\": \"codingtoolbox\",\n    \"materials_etc_all\": \"Other Educational Materials\",\n    \"materials_teaching\": \"For Teacher Education\",\n    \"materials_etc\": \"Other Resources\",\n    \"materials_etc_resource\": \"Resources\",\n    \"materials_teaching_etc\": \"Teacher training\",\n    \"materials_teaching_1\": \"Why Coding?\",\n    \"materials_teaching_2\": \"Unplugged Acitivies with Entry\",\n    \"materials_teaching_3\": \"Learn by playing in Entry Coding Missions\",\n    \"materials_teaching_4\": \"Entry for Real World Problem Solving\",\n    \"materials_teaching_5\": \"Interdisciplinary Coding(Art,Math,Social)\",\n    \"materials_teaching_6\": \"Interdisciplinary Coding(Korean,Science,Music)\",\n    \"materials_teaching_7\": \"Physical Computing 1 (E-Sensorboard)\",\n    \"materials_teaching_8\": \"Physical Computing 2 (Hamster Robot)\",\n    \"materials_teaching_9\": \"Learn to use Entry LMS effectively \",\n    \"materials_etc_1\": \"Getting Started Guide\",\n    \"materials_etc_2\": \"Contents for Classroom Use\",\n    \"materials_etc_3\": \"Monthly Entry\",\n    \"materials_etc_4\": \"About Entry\",\n    \"materials_etc_5\": \"Introducing Entry\",\n    \"materials_etc_6\": \"Entry Block Catalogue\",\n    \"materials_etc_7\": \"Entry Python Guide\",\n    \"jr_if_1\": \"nếu\",\n    \"jr_if_2\": \"đằng trước\",\n    \"jr_fail_no_pencil\": \"There is no pencil. Use 'pencil block' at the pencil!\",\n    \"jr_fail_forgot_pencil\": \"Oh no! I forgot my pencil. Let's pick up the pencil.\",\n    \"jr_fail_much_blocks\": \"너무많은 블록을 사용했어, 다시 도전해볼래?\",\n    \"cparty_jr_success_1\": \"Hooray! I got my backpack!\",\n    \"go_right\": \"đi sang bên phải\",\n    \"go_down\": \"đi xuống\",\n    \"go_up\": \"đi lên\",\n    \"go_left\": \"đi sang bên trái\",\n    \"go_forward\": \"tiến về phía trước\",\n    \"jr_turn_left\": \"quẹo trái\",\n    \"jr_turn_right\": \"quẹo phải\",\n    \"go_slow\": \"đi chậm\",\n    \"repeat_until_reach_1\": \"\",\n    \"repeat_until_reach_2\": \"Repeat until reach\",\n    \"pick_up_pencil\": \"nhấc\",\n    \"repeat_0\": \"Repeat\",\n    \"repeat_1\": \"\",\n    \"when_start_clicked\": \"When start button clicked\",\n    \"age_0\": \"Age 0+\",\n    \"create_character\": \"Creating Character\",\n    \"age_7_9\": \"Age 7~9\",\n    \"going_school\": \"Going to School\",\n    \"age_10_12_1\": \"Age 10~12\",\n    \"collect_parts\": \"Collecting Parts\",\n    \"age_10_12_2\": \"Age 10~12\",\n    \"driving_elec_car\": \"Driving Electric Car\",\n    \"age_13\": \"Age 13+\",\n    \"travel_space\": \"Traveling Space\",\n    \"people\": \"People\",\n    \"all\": \"All\",\n    \"life\": \"Life\",\n    \"nature\": \"Nature\",\n    \"animal_insect\": \"Animal/Insect\",\n    \"environment\": \"Environment\",\n    \"things\": \"Things\",\n    \"vehicles\": \"Vehicles\",\n    \"others\": \"Others\",\n    \"fantasy\": \"Fantasy\",\n    \"instrument\": \"Instrument\",\n    \"piano\": \"Piano\",\n    \"marimba\": \"Marimba\",\n    \"drum\": \"Drum\",\n    \"janggu\": \"Janggu\",\n    \"sound_effect\": \"Sound\",\n    \"others_instrument\": \"Others\",\n    \"aboutEntryDesc_1\": \"Entry is an education platform created to help anyone learn to code.\",\n    \"aboutEntryDesc_2\": \"Students are able to learn to code while playing,\",\n    \"aboutEntryDesc_3\": \"teachers are able to teach effectively.\",\n    \"aboutEntryDesc_4\": \"Entry is a non-profit service.\",\n    \"aboutEntryDesc_5\": \"\",\n    \"viewProjectTerms\": \"See usage policy\",\n    \"openSourceTitle\": \"Promoting open source culture\",\n    \"openSourceDesc_1\": \"Entry's source code and \",\n    \"openSourceDesc_2\": \"all educational materials\",\n    \"openSourceDesc_3\": \"are open to public\",\n    \"viewOpenSource\": \"See open source code\",\n    \"eduPlatformTitle\": \"Entry for Classroom Use\",\n    \"eduPlatformDesc_1\": \"Entry is developed with teachers \",\n    \"eduPlatformDesc_2\": \"to promote learning\",\n    \"eduPlatformDesc_3\": \"in classroom settings.\",\n    \"madeWith\": \"Advisory group\",\n    \"researchTitle\": \"Continuous improvement through research\",\n    \"researchDesc_1\": \"Entry collaborates with researchers to strengthen learning effectiveness\",\n    \"researchDesc_2\": \"\",\n    \"researchDesc_3\": \"\",\n    \"viewResearch\": \"See research materials\",\n    \"atEntry\": \"Entry provides\",\n    \"entryLearnDesc_1\": \"learn while playing\",\n    \"entryLearnDesc_2\": \"< Learn > section provides various coursewares and learning materials.\",\n    \"entryLearnDesc_3\": \"Watch videos, solve problems and learn while playing.\",\n    \"entryLearnDesc_4\": \"\",\n    \"entryMakeDesc_1\": \"<Create> section provides block-based coding tool which enables\",\n    \"entryMakeDesc_2\": \"even first time learners to easily create programs.\",\n    \"entryMakeDesc_3\": \"And also provides ‘entry phython’ mode which is between block-based coding\",\n    \"entryMakeDesc_4\": \"and text-based coding to help you understand the structure and grammar\",\n    \"entryMakeDesc_5\": \"of programming languages.\",\n    \"entryShareDesc_1\": \"<Share> section allows users to share his or her project with others.\",\n    \"entryShareDesc_2\": \"Explore how the shared projects are created, make improvements,\",\n    \"entryShareDesc_3\": \"collaborate with friends to make even cooler projects.\",\n    \"entryGroup\": \"Learning Management Tool\",\n    \"entryGroupTitle\": \"My Class\",\n    \"entryGroupDesc_1\": \"<Learning Management Tool> is created to help teachers easily manage students.\",\n    \"entryGroupDesc_2\": \"Create your own class, assign homework,\",\n    \"entryGroupDesc_3\": \"share project within the class, and check student progress.\",\n    \"entryGroupDesc_4\": \"And teacher can lead the class effectively by providing more suitable coursewares\",\n    \"entryGroupDesc_5\": \"according to the students’ level.\",\n    \"unpluggedToPhysical\": \"From Unplugged Activity to Physical Computing\",\n    \"algorithmActivity\": \"Basic Algorithm\",\n    \"programmignLang\": \"Block-based Coding\",\n    \"unpluggedDesc_1\": \"Learn the basics of programming such as sequence, repetition,\",\n    \"unpluggedDesc_2\": \"selection and function by playing Entry Boardgame and Cardgame.\",\n    \"entryMaze\": \"Entrybot Maze Escape\",\n    \"entryAI\": \"Space Travels\",\n    \"algorithmDesc_1\": \"Earn a certificate by completing the coding missions.\",\n    \"algorithmDesc_2\": \"Learn to code while playing.\",\n    \"programmingLangDesc_1\": \"Coding is made easy with Entry.\",\n    \"programmingLangDesc_2\": \"Create your own games, animation, media art and much more.\",\n    \"viewSupporHwVideo\": \"See the hardware guide videos\",\n    \"viewSupporHw\": \"see which hardware connects\",\n    \"supportHwDesc_1\": \"Entry connects to many physical computing devices to create awesome projects\",\n    \"supportHwDesc_2\": \"that interacts with the physical world. More devices are continuously added!\",\n    \"entryEduSupport\": \"Entry Education Support\",\n    \"eduSupportDesc_1\": \"Entry Labs provides educational materials for free.\",\n    \"eduSupportDesc_2\": \"Download educational materials from the Educational Materials page.\",\n    \"materials_1_title\": \"Textbook by grade levels\",\n    \"materials_1_desc_1\": \"Improve coding skills step by step\",\n    \"materials_1_desc_2\": \"\",\n    \"materials_2_title\": \"EBS TV program and teacher's guide\",\n    \"materials_2_desc_1\": \"EBS TV series are accompanied\",\n    \"materials_2_desc_2\": \"by teacher's guide\",\n    \"materials_3_title\": \"Educational materials\",\n    \"materials_3_title_2\": \"for elementary and mid to high school\",\n    \"materials_3_desc_1\": \"Improve computational thinking skills.\",\n    \"materials_3_desc_2\": \"\",\n    \"moreMaterials\": \"See more educational materials\",\n    \"moreInfoAboutEntry_1\": \"Click on the links below to get Entry's latest updates.\",\n    \"moreInfoAboutEntry_2\": \"Educational materials as well as exciting news are shared.\",\n    \"material_menu_type_robot\": \"Robot\\nType\",\n    \"material_menu_type_module\": \"Module\\nType\",\n    \"material_menu_type_board\": \"Board\\nType\",\n    \"blog\": \"Blog\",\n    \"post\": \"Post\",\n    \"tvCast\": \"TVCast\",\n    \"about_entry_pre\": \"Entry\",\n    \"about_youtube\": \"Youtube\",\n    \"about_facebook\": \"Facebook\",\n    \"albertSchool\": \"Albert\",\n    \"arduinoBoard\": \"Arduino certified\",\n    \"arduinoCompatible\": \"non-certified\",\n    \"bitBlock\": \"BitBlock\",\n    \"bitbrick\": \"Bitbrick\",\n    \"creamo\": \"creamo\",\n    \"playcode\": \"playcode\",\n    \"funboard\": \"funboard\",\n    \"truerobot\": \"TrueTrue\",\n    \"bingle\": \"BINGLE\",\n    \"bingles\": \"BINGLE · S\",\n    \"codeino\": \"CODEino\",\n    \"epor\": \"EPOR\",\n    \"petrone_v2\": \"Petrone V2\",\n    \"petrone_v2_drone\": \"flight\",\n    \"petrone_v2_car\": \"drive\",\n    \"e-sensor\": \"E-Sensorboard\",\n    \"e-sensorUsb\": \"E-Sensor board\",\n    \"e-sensorBT\": \"E-Sensor board(Bluetooth)\",\n    \"mechatronics_4d\": \"4D Mechatronics\",\n    \"esensor_board\": \"E-Sensor Board\",\n    \"esensor_robot\": \"E-Sensor Robot\",\n    \"hamster\": \"Hamster\",\n    \"hummingbird\": \"Hummingbird Duo\",\n    \"roboid\": \"Roboid\",\n    \"turtle\": \"Turtle\",\n    \"littlebits\": \"Littlebits\",\n    \"orangeBoard\": \"OrangeBoard\",\n    \"robotis_carcont\": \"Robotis Robot Car\",\n    \"robotis_IoT\": \"Robotis IoT\",\n    \"robotis_IoT_Wireless\": \"Robotis IoT(Wireless)\",\n    \"dplay\": \"DPLAY\",\n    \"iboard\": \"iboard\",\n    \"nemoino\": \"NEMOino\",\n    \"xbot_epor_edge\": \"XBOT(OneTouch Dongle/USB)\",\n    \"XbotBT\": \"XBOT EPOR and EDGE Bluetooth\",\n    \"robotori\": \"robotori\",\n    \"rokoboard\": \"rokoboard\",\n    \"neobot\": \"NEOBOT\",\n    \"neobot_sensor_theme\": \"NEOBOT Senosor Theme\",\n    \"mechatro\": \"mechatro\",\n    \"about\": \"About\",\n    \"articles\": \"Articles\",\n    \"gallery\": \"Gallery\",\n    \"learn\": \"Learn\",\n    \"login\": \"Đăng nhập\",\n    \"logout\": \"Đăng xuất\",\n    \"make\": \"Create\",\n    \"register\": \"Sign Up\",\n    \"Join\": \"Tham gia\",\n    \"Edit_info\": \"Edit Info\",\n    \"Discuss\": \"Discuss\",\n    \"Explore\": \"Explore\",\n    \"Load\": \"Load\",\n    \"My_lesson\": \"Open Lessons\",\n    \"textbook_learning\": \"Learning Text book\",\n    \"Resources\": \"Resources\",\n    \"play_software\": \"EBS Let’s play, SW!\",\n    \"problem_solve\": \"Entry Learn\",\n    \"learning_textbook\": \"Learning Text book\",\n    \"context_textbook\": \"Teachers can teach the school class and students can prepare and review at home with the same content as their textbooks.\",\n    \"info_banner_textbook\": \" \",\n    \"banner_textbook\": \"Do you want to learn more\",\n    \"banner_textbook_2\": \"diverse and interesting things?\",\n    \"banner_textbook_right_banner\": \"Do you need educational \",\n    \"banner_textbook_right_banner2\": \"materials for teachers?\",\n    \"banner_textbook_right_banner_btn\": \"Download material\",\n    \"Learn\": \"Learn\",\n    \"teaching_tools\": \"Teaching Tools\",\n    \"about_entry\": \"About ENTRY\",\n    \"what_entry\": \"What is Entry?\",\n    \"create\": \"Create\",\n    \"create_new\": \"Create new\",\n    \"start_programming\": \"First Step for Software Education\",\n    \"Entry\": \"Entry\",\n    \"intro_learning\": \"Learn to code in fun and easy way.\",\n    \"intro_learning_anyone\": \"Start now with Entry!\",\n    \"start_now\": \"For Free, Forever.\",\n    \"welcome_entry\": \"Welcome to ENTRY\",\n    \"student\": \"Student\",\n    \"non_menber\": \"General\",\n    \"teacher\": \"Teacher\",\n    \"terms_conditions\": \"Terms and Conditions\",\n    \"personal_information\": \"Information about the collection and use of personal information \",\n    \"limitation_liability\": \"Limitation of Liability\",\n    \"entry_agree\": \"Agree to ENTRY’s Terms of Use\",\n    \"info_agree\": \"\",\n    \"next\": \"Next\",\n    \"enter_individual_info\": \"Enter personal information\",\n    \"enter_id\": \"Enter ID\",\n    \"enter_password\": \"Enter Password\",\n    \"confirm_password\": \"Confirm Password\",\n    \"enter_password_again\": \"Enter  your password again\",\n    \"validation_password\": \"Please use at least 5 letters and/or numbers\",\n    \"validation_id\": \"Please use 4-20 letters and/or numbers.\",\n    \"prev\": \"Back\",\n    \"born_year\": \"Year born \",\n    \"select_born\": \"Select the year you were born.\",\n    \"year\": \"years\",\n    \"gender\": \"Gender\",\n    \"choose_gender\": \"Choose gender\",\n    \"male\": \"Male\",\n    \"female\": \"Female\",\n    \"language\": \"Language\",\n    \"best_language\": \"Select your best language\",\n    \"korean\": \"Korean\",\n    \"english\": \"English\",\n    \"viet\": \"Vietnamese\",\n    \"japan\": \"japan\",\n    \"russia\": \"russia\",\n    \"chinese_simplified\": \"Chinese(Simplified)\",\n    \"chinese_traditional\": \"Chinese(Traditional)\",\n    \"option_email\": \"Email (optional)\",\n    \"insert_email\": \"Enter your email address\",\n    \"sign_up_complete\": \"Sign up complete!\",\n    \"agree_terms_conditions\": \"Please agree Terms and Conditions\",\n    \"agree_personal_information\": \"Please agree to the collection and use of personal information.\",\n    \"insert_studying_stage\": \"Please select the group you want to share your project .\",\n    \"insert_born_year\": \"Insert the year you were born\",\n    \"insert_gender\": \"Please select gender from the options.\",\n    \"select_language\": \"select language\",\n    \"check_email\": \"Check email's format\",\n    \"already_exist_id\": \"ID already exists\",\n    \"id_validation_id\": \"ID use 4-20 letters and/or numbers.\",\n    \"password_validate_pwd\": \"Password use at least 5 letters and/or numbers\",\n    \"password_validate_pwd_length\": \"Please use at least 5 numbers.\",\n    \"neoid_username_same_id\": \"Username already taken (NEOID)\",\n    \"insert_same_pwd\": \"Insert same password\",\n    \"studying_stage_group\": \"Sharing class\",\n    \"studying_stage\": \"Please select the group you want to share.\",\n    \"password\": \"Password\",\n    \"save_id\": \"Save ID\",\n    \"auto_login\": \"Keep me sign in\",\n    \"enter_id_pw\": \"Entry ID, Password\",\n    \"forgot_password\": \"Forgot your ID or password?\",\n    \"did_not_join\": \"Haven’t signed up yet?\",\n    \"go_join\": \"Go to join\",\n    \"renew_index_text_00\": \"Learn textbook\",\n    \"renew_index_text_01\": \"Let's learn Entry with textbook.\",\n    \"renew_index_text_02\": \"Through elementry textbook lectures,\",\n    \"renew_index_text_02_2\": \"learn Entry!\",\n    \"renew_index_text_03\": \"Go to\",\n    \"renew_index_text_03_2\": \"learn textbook\",\n    \"renew_index_text_1\": \"2019, Meet the changed Entry\",\n    \"renew_index_text_2\": \"The brand new 'Create Project'\",\n    \"renew_index_text_3\": \"Go to the 'Create Project'\",\n    \"renew_index_text_3_2\": \"and find out the new functions!\",\n    \"renew_index_text_4\": \"View Details\",\n    \"first_step\": \"First Step for Software Education\",\n    \"entry_content_one\": \"Bring your imagination to life with ENTRY.\",\n    \"entry_content_two\": \"Create games, animations, media art, and other cool projects!\",\n    \"entry_content_three\": \"Create projects and share with your friends. Enter the exciting world of ENTRY!\",\n    \"funny_space\": \"A Fun Learning Space\",\n    \"in_learn_section\": \"In < Learn > section,\",\n    \"learn_problem_solving\": \"Various learning contents and mini challenges are available for you in the < Learn > section. Solve mini challenges by coding. Watch fun videos and learn to program.\",\n    \"joy_create\": \"A Creative Space\",\n    \"in_make\": \"In < Create > section\",\n    \"make_contents\": \"In the <Create> section, create your own program with block-based programming language. Create simulation programs to test laws of Physics. Create animation program with your favorite characters. Bring your imagination to life with Entry. \",\n    \"and_content\": \"There is no limit to what you can create. You can experiment physical laws you’ve learned in science class, create animations featuring your favorite characters, and even make your own games. \",\n    \"share_collaborate\": \"A Sharing Space\",\n    \"explore_contents\": \"The <Explore> section, showcases thousands of projects created and shared by the Entry community. Try out the fun and creative projects, see how they are coded, and improve them. You can also cooperate with your peers to create exciting projects.\",\n    \"why_software\": \"Why is learning to code important?\",\n    \"speak_obama_contents\": \"Learning these skills isn’t just important for your future. It’s important for our country’s future.\",\n    \"obama\": \"Barack Obama\",\n    \"us_president\": \"U.S President\",\n    \"billgates_contents\": \"Learning to write programs stretches your mind, and helps you think better, creates a way of thinking about things that I think is helpful in all domains.\",\n    \"billgates\": \"Bill Gates\",\n    \"chairman_micro\": \"Chairman, Microsoft\",\n    \"eric_contents\": \"For most people on Earth, the digital revolution hasn't even started yet. Within the next 10 years, all that will change. Let's get the whole world coding!\",\n    \"eric\": \"Eric Schmidt\",\n    \"sandbug_contents\": \"An understanding of computer science is becoming increasingly essential in today’s world. Our national competitiveness depends upon our ability to educate our children—and that includes our girls—in this critical field.\",\n    \"sandbug\": \"sheryl Sandberg\",\n    \"view_entry_tools\": \"Introducing Entry’s unplugged games for teaching programming.\",\n    \"solve_problem\": \"Solve Mission\",\n    \"solve_problem_content\": \"Mini challenges will help you learn the basics of programming.\",\n    \"find_extra_title\": \"ENTRY Bot part finding extravaganza\",\n    \"all_ages\": \"For all ages\",\n    \"total\": \"Total\",\n    \"step\": \"steps\",\n    \"find_extra_contents\": \"Entry bot is special robot created one day at the Rutz Robot Toy Factory during a blackout. Help him find his missing parts and escape the factory while learning to code.\",\n    \"software_play_contents\": \"Watch ‘Let’s Play Software’ , follow along the tutorials and learn to create fun programs.\",\n    \"resources_contents\": \"Get various Entry educational materials for free\",\n    \"from\": \"From\",\n    \"sw_camp\": \"Software Creativity Camp, Ministry of Science, ICT and Future Planning\",\n    \"elementary\": \"Elementary\",\n    \"middle\": \"Middle school\",\n    \"grades\": \"Grades\",\n    \"lesson\": \"Lessons\",\n    \"sw_contents_one\": \"This guidebook is for elementary students learn physical computing over a 5-lesson course. Students learn to use Entry and create images and stoires. In the final section, students use Arduino to create a musical keyboard\",\n    \"sw_camp_detail\": \"Ministry of Science, ICT and Future Planning Software Creation Camp\",\n    \"sw_contents_two\": \"This textbook allows middle school students to experience ENTRY and physical computing over a 5-lesson course. Students learn how to use ENTRY, and create a maze game and quiz program. In the final section, students use Arduino and keyboard to steer a car.\",\n    \"sw_contents_three\": \"This is a teacher’s guide for starting computing classes in schools.  It contains a variety of unplugged activities and lesson plans using clips from ‘Let’s play, Software!’broadcasts. \",\n    \"naver_sw\": \"NAVER Let’s play, Software!\",\n    \"teacher_teaching\": \"Teacher’s Guide (for elementary grades 5-6 and above)\",\n    \"funny_sw\": \"Have Fun with Software\",\n    \"sw_contents_four\": \"This textbook allows students to learn about computing in a fun and playful way through a variety of unplugged activities such as ENTRY Board, and teaches students the basic principles of programming via ENTRY Course Mode. Once they have got down the basics, students learn how to create stories, games, artistic works, and applications using ENTRY. The textbook allows students to create and present their own software. \",\n    \"ct_text_5\": \"Grow computational thinking with skills.\",\n    \"teacher_grade_5\": \"교원 (초등학교 5학년)\",\n    \"ct_text_5_content\": \"This teacher's guide contains 8 problem solving tasks. Each task is designed to reflect the revised National Curriculum and contains interdisciplinary themes. Cultivate computational thinking skills.\",\n    \"ct_text_6\": \"교과서와 함께 키우는 컴퓨팅 사고력\",\n    \"teacher_grade_6\": \"교원 (초등학교 6학년)\",\n    \"ct_text_6_content\": \"실생활의 문제를 해결하자는 테마로 준비된 총 8개의 학습콘텐츠가 담긴 교사용 지도안입니다. 각 콘텐츠는 개정된 교육과정을 반영한 타교과와의 연계를 통해 다양한 문제를 만나고 해결해볼 수 있도록 설계되었습니다.  아이들이 컴퓨팅 사고력을 갖춘 융합형 인재가 될 수 있도록 지금 적용해보세요!\",\n    \"sw_use\": \"All textbooks are for non-commercial use only, and can be used freely so long as the author is credited. \",\n    \"title\": \"Title\",\n    \"writer\": \"By\",\n    \"view\": \"View\",\n    \"date\": \"Date\",\n    \"find_id_pwd\": \"Find ID or Password\",\n    \"send_email\": \"A link to change your password has been sent to you by email.\",\n    \"user_not_exist\": \"This email does not exist.\",\n    \"not_signup\": \"Haven't signed up yet?\",\n    \"send\": \"Send\",\n    \"sensorboard\": \"ENTRY Sensor Board\",\n    \"physical_computing\": \"Physical Computing\",\n    \"sensorboard_contents\": \"Using Arduino no longer requires building a circuit using lots of wires. With ENTRY Board, you can use LED lights, temperature, sound, light sensors, a slider, and switches by simply mounting it onto an Arduino board. Now anyone can easily create their own unique projects using ENTRY Board!\",\n    \"entrybot_boardgame\": \"ENTRY-Bot Board Game\",\n    \"unplugged\": \"Unplugged Activities\",\n    \"unplugged_contents\": \"Learn the principles of programming through Entry-bot Board Game. By helping Entrybot escape the factory, you can learn to think like a computer scientist.\",\n    \"entrybot_cardgame\": \"ENTRY Bot Cardgame : Bomb Tempest\",\n    \"entrybot_cardgame_contents\": \"12 different types of bombs appear at the city of Entry! Dismantle the bombs one at a time and learn the basics of programming. By using the concepts of sequence, repetition and conditionals, save the City and become a hero!\",\n    \"basic_learn\": \"Entry Basics\",\n    \"basic_learn_contents\": \"Learn to program with Entry’s coursewares\",\n    \"troubleshooting\": \"Problem Solving\",\n    \"playsoftware\": \"Let's play, Software!\",\n    \"make_own_lesson\": \"Create your own lessons and share them with everyone.\",\n    \"group_lecture\": \"Lessons\",\n    \"group_curriculum\": \"Courseware\",\n    \"group_homework\": \"Assignment\",\n    \"group_noproject\": \"No Project\",\n    \"group_nolecture\": \"No Lessons\",\n    \"group_nocurriculum\": \"No Courseware\",\n    \"lecture_contents\": \"Create customized lessons with limited blocks.\",\n    \"curriculum_contents\": \"Create a course by putting together series of lessons.\",\n    \"grade_info\": \"Grades information\",\n    \"difficulty\": \"Difficulty\",\n    \"usage\": \"Usages\",\n    \"learning_concept\": \"Learning concepts\",\n    \"related_subject\": \"Related subjects\",\n    \"show_more\": \"Show more\",\n    \"close\": \"Close\",\n    \"latest\": \"By Latest\",\n    \"viewCount\": \"view count\",\n    \"viewer\": \"By Viewers\",\n    \"like\": \"By Likes\",\n    \"comment\": \"By Comments\",\n    \"entire_period\": \"Entire period\",\n    \"today\": \"Today\",\n    \"latest_week\": \"Latest 1 week\",\n    \"latest_month\": \"Latest 1 month\",\n    \"latest_three_month\": \"Latest 3 months\",\n    \"current_password\": \"Current password\",\n    \"change_password\": \"Change password\",\n    \"incorrect_password\": \"Incorrect! Try again.\",\n    \"incorrect_password_login\": \"The Username or Password you entered is incorrect.\",\n    \"suspension_user\": \"The login of the account is prohibited.\",\n    \"blocked_user\": \"Blocked!!\",\n    \"new_password\": \"New password\",\n    \"password_option_1\": \"Please use at least 5 letters and/or numbers.\",\n    \"again_new_password\": \"Confirm new password\",\n    \"enter_new_pwd\": \"Enter new password.\",\n    \"confirm_new_pwd\": \"Confirm new password.\",\n    \"enter_new_pwd_again\": \"Enter new password again.\",\n    \"password_match\": \"Passwords do not match.\",\n    \"incorrect_email\": \"Incorrect email. Try again.\",\n    \"edit_button\": \"Edit info\",\n    \"edit_profile\": \"Edit\",\n    \"my_project\": \"My projects\",\n    \"my_group\": \"My Class\",\n    \"mark\": \"Marking\",\n    \"prev_state\": \"Back\",\n    \"profile_image\": \"Profile image\",\n    \"insert_profile_image\": \"Please upload a profile image.\",\n    \"at_least_180\": \"At least 180x180 pixels is recommended.\",\n    \"upload_image\": \"Upload image\",\n    \"about_me\": \"About me\",\n    \"save_change\": \"Save changes\",\n    \"basic_image\": \"Basic Image\",\n    \"profile_condition\": \"Enter something about yourself. (in 50 characters)\",\n    \"profile_back\": \"Go back\",\n    \"make_project\": \"Create Project\",\n    \"exhibit_project\": \"Exhibit Project\",\n    \"art_list_shared\": \"Shared\",\n    \"art_list_group_shared\": \"Group\",\n    \"gl_mode_boost\": \"Boost Mode\",\n    \"gl_not_supported\": \"Can not run in boost mode.\\nClick OK to run in default mode.\",\n    \"view_project\": \"View Code\",\n    \"code_view\": \"View Code\",\n    \"noResult\": \"No results found\",\n    \"comment_view\": \"Comment\",\n    \"upload_project\": \"Upload\",\n    \"edit\": \"Edit\",\n    \"save_complete\": \"Save\",\n    \"just_like\": \"Like\",\n    \"share\": \"Share\",\n    \"who_likes_project\": \"Who likes the projects\",\n    \"people_interest\": \"People interested projects\",\n    \"none_person\": \"Nobody\",\n    \"inserted_date\": \"Date\",\n    \"last_modified\": \"Last Modified\",\n    \"original_project\": \"Original project\",\n    \"for_someone\": \"'s\",\n    \"original_project_deleted\": \"The original project was deleted\",\n    \"delete_project\": \"Delete\",\n    \"delete_group_project\": \"Delete From List\",\n    \"currnet_month_time\": \"months\",\n    \"current_day_time\": \"days\",\n    \"game\": \"Game\",\n    \"animation\": \"Animation\",\n    \"media_art\": \"Media Arts\",\n    \"physical\": \"Physical\",\n    \"etc\": \"ETC\",\n    \"connected_contents\": \"Linking content\",\n    \"connected_contents_content\": \"Discover the variety of content that can be done with the entry . If you're new software to learn easily from person to enjoy board games , you can take advantage of the Arduino and physical computing , such as creating a luxurious view of your own creation .\",\n    \"basic_mission\": \"Basic mission : Entry bot Maze\",\n    \"basic_mission_content\": \"A power outage at a toy robot factory magically enabled Entrybot to come to life. Help Entrybot escape the factory and find freedom!\",\n    \"application_mission\": \"Application mission: Entry bot's Space Odyssey\",\n    \"write_article\": \"Write\",\n    \"write_contest\": \"Submit\",\n    \"view_all_articles\": \"View all posts\",\n    \"view_own_articles\": \"View my posts\",\n    \"view_qna_articles\": \"View no answered posts\",\n    \"learning_materials\": \"Learning materials\",\n    \"download_materials\": \"Learning materials download\",\n    \"download_button\": \"download\",\n    \"download_all\": \"download all\",\n    \"ebs_software_first\": \"<Let's Play Software> is a TV series created by Naver, EBS and Entry Labs. Learn the basic principles of programming. Watch the show, follow along the video tutorials, and learn to code!\",\n    \"go_software\": \"Visit Let's play software!\",\n    \"ebs_context\": \"Visit EBS\",\n    \"ebs_context_hello\": \"Visit EBS\",\n    \"category\": \"Category\",\n    \"add_picture\": \"Add Picture\",\n    \"upload_article\": \"Upload article\",\n    \"list\": \"List\",\n    \"report\": \"Report\",\n    \"upload\": \"Upload\",\n    \"staff_picks\": \"Staff Picks\",\n    \"popular_picks\": \"Popular Projects\",\n    \"lecture_header_more\": \"More Projects\",\n    \"lecture_header_reset\": \"Reset\",\n    \"lecture_header_reset_exec\": \"Reset to basic project\",\n    \"lecture_header_save\": \"Save\",\n    \"lecture_header_save_content\": \"Save current lecture\",\n    \"lecture_header_export_project\": \"Export to my project\",\n    \"lecture_header_undo\": \"Undo\",\n    \"lecture_header_redo\": \"Redo\",\n    \"lecture_er_bugs\": \"Feedback\",\n    \"lecture_container_tab_object\": \"các đối tượng\",\n    \"lecture_container_tab_video\": \"video\",\n    \"lecture_container_tab_project\": \"công trình hoàn thành\",\n    \"lecture_container_tab_help\": \"giúp đỡ\",\n    \"illigal\": \"Illegal or inappropriate behavior\",\n    \"verbal\": \"Verbal abuse or posting personal information\",\n    \"commertial\": \"Posting for commercial purposes\",\n    \"explicit\": \"Explicit content\",\n    \"other\": \"Other\",\n    \"check_one_more\": \"Please select the reason more than one.\",\n    \"enter_content\": \"Please enter the reason for your report.\",\n    \"report_result\": \"Please enter email address to be informed of report results. \",\n    \"report_success\": \"Your report was submitted successfully.\",\n    \"etc_detail\": \"Please give details\",\n    \"lecture_play\": \"Play\",\n    \"list_view_link\": \"List\",\n    \"lecture_intro\": \"Introduction Lessons\",\n    \"study_goal\": \"Goals\",\n    \"study_description\": \"Description\",\n    \"study_created\": \"Created\",\n    \"study_last_updated\": \"Updated\",\n    \"study_remove\": \"Remove\",\n    \"study_group_lecture_remove\": \"Remove From List\",\n    \"study_group_curriculum_remove\": \"Remove From List\",\n    \"study_edit\": \"Edit\",\n    \"study_comments\": \"Comments\",\n    \"study_comment_post\": \"Post\",\n    \"study_comment_remove\": \"Remove\",\n    \"study_comment_edit\": \"Edit\",\n    \"study_comment_save\": \"Save\",\n    \"study_guide_video\": \"Guide Video\",\n    \"study_basic_project\": \"Initial Project\",\n    \"study_done_project\": \"Complete Project\",\n    \"study_usage_element\": \"Usage\",\n    \"study_concept_element\": \"Concept\",\n    \"study_subject_element\": \"Related\",\n    \"study_computing_element\": \"Computational Thinking\",\n    \"study_element_none\": \"None\",\n    \"study_label_like\": \"Like\",\n    \"study_label_interest\": \"Interest\",\n    \"study_label_share\": \"Share\",\n    \"study_label_like_people\": \"People who liked this lecture\",\n    \"study_label_interest_people\": \"People who interested this lecture\",\n    \"study_related_lectures\": \"Related lectures\",\n    \"study_expand\": \"Show all\",\n    \"study_collapse\": \"Collapse\",\n    \"aftercopy\": \"Copied to clipboard\",\n    \"study_remove_curriculum\": \"Are you sure to remove this course?\",\n    \"content_required\": \" Please enter the contents.\",\n    \"upload_not_supported_file_msg\": \"Not supported file type.\",\n    \"study_remove_lecture\": \"Are you sure to remove this lesson?\",\n    \"lecture_build\": \"Make a lesson\",\n    \"lecture_build_step1\": \"1. Enter basic lesson information\",\n    \"lecture_build_step2\": \"2. Selecte required functions\",\n    \"lecture_build_step3\": \"3. Confirm all of information correctly.\",\n    \"lecture_build_choice\": \"What is main content?\",\n    \"lecture_build_project\": \"Entry Project\",\n    \"lecture_build_video\": \"Lessons Video\",\n    \"lecture_build_grade\": \"Grades\",\n    \"lecture_build_goals\": \"Goals\",\n    \"lecture_build_add_goal\": \"Add a goal\",\n    \"lecture_build_attach\": \"Attachment\",\n    \"lecture_build_attach_text\": \"Less than 20MB\",\n    \"lecture_build_assist\": \"Additional\",\n    \"lecture_build_youtube_url\": \"Paste a Youtube share link\",\n    \"lecture_build_project_done\": \"Select a completed project.\",\n    \"lecture_build_scene_text1\": \"Using scene function or not\",\n    \"lecture_build_scene_text2\": \"\",\n    \"lecture_build_object_text\": \"Using Object add function or not\",\n    \"lecture_build_blocks_text1\": \"Select required blocks only.\",\n    \"lecture_build_blocks_text2\": \"\",\n    \"lecture_build_basic1\": \"Select a project.\",\n    \"lecture_build_basic2\": \"User start with this project.\",\n    \"lecture_build_help\": \"\",\n    \"lecture_build_help_never\": \"Close permanently\",\n    \"lecture_build_close\": \"Close\",\n    \"lecture_build_scene\": \"Scene 1\",\n    \"lecture_build_add_object\": \"Add Object\",\n    \"lecture_build_start\": \"Start\",\n    \"lecture_build_tab_code\": \"Block\",\n    \"lecture_build_tab_shape\": \"Shape\",\n    \"lecture_build_tab_sound\": \"Sound\",\n    \"lecture_build_tab_attribute\": \"Attribute\",\n    \"lecture_build_tab_table\": \"Table\",\n    \"lecture_build_block_category\": \"Select block category.\",\n    \"lecture_build_attr_all\": \"All\",\n    \"lecture_build_attr_var\": \"biến số\",\n    \"lecture_build_attr_signal\": \"Signal\",\n    \"lecture_build_attr_list\": \"List\",\n    \"lecture_build_attr_func\": \"Function\",\n    \"lecture_build_edit\": \"Edit\",\n    \"lecture_build_remove\": \"Remove\",\n    \"curriculum_build\": \"Create a courseware\",\n    \"curriculum_step1\": \"Fill information about this course.\",\n    \"curriculum_step2\": \"Select lessons for this course.\",\n    \"curriculum_step3\": \"Confirm information.\",\n    \"curriculum_lecture_upload\": \"Upload\",\n    \"curriculum_lecture_edit\": \"Edit\",\n    \"curriculum_lecture_open\": \"Open\",\n    \"group_lecture_add\": \"Add my group lessons\",\n    \"group_curriculum_add\": \"Add my group curriculum\",\n    \"group_lecture_delete\": \"Delete\",\n    \"group_curriculum_delete\": \"Delete\",\n    \"group_select\": \"\",\n    \"group_studentNo\": \"Student No\",\n    \"group_username\": \"Name\",\n    \"group_userId\": \"ID\",\n    \"group_tempPassword\": \"Modify PW\",\n    \"group_gender\": \"Gender\",\n    \"group_studentCode\": \"Code\",\n    \"group_viewWorks\": \"View Works\",\n    \"added_group_lecture\": \"lessons deleted\",\n    \"added_group_curriculum\": \"Course deleted\",\n    \"deleted_group_lecture\": \"lessons deleted\",\n    \"deleted_group_curriculum\": \"Course deleted\",\n    \"modal_my\": \"My\",\n    \"modal_interest\": \"Marked\",\n    \"modal_project\": \"Project\",\n    \"section\": \"Sections\",\n    \"connect_hw\": \"kết nối phần cứng\",\n    \"connect_message\": \"Connected to %1\",\n    \"connect_fail\": \"kết nối thất bại\",\n    \"interest_curriculum\": \"Interest\",\n    \"marked_curriculum\": \"Interest Curriculum\",\n    \"searchword_required\": \"Please enter your search keyword.\",\n    \"file_required\": \"File is required.\",\n    \"file_name_error\": \"please insert correct file name\",\n    \"file_upload_max_count\": \"You can only upload 10 files at a time.\",\n    \"image_file_only\": \"You can only upload jpg, png, bmp files.\",\n    \"file_upload_max_size\": \"You can only upload less than 10MB in file size.\",\n    \"curriculum_modal_lectures\": \"My Lessons\",\n    \"curriculum_modal_interest\": \"Interest\",\n    \"group_curriculum_modal_curriculums\": \"My Courses\",\n    \"group_curriculum_modal_interest\": \"Interest\",\n    \"picture_import\": \"Import a picture\",\n    \"picture_select\": \"Select a picture\",\n    \"lecture_list_view\": \"list\",\n    \"play_software_2\": \"Let’s play, Software2!\",\n    \"play_software_2_content\": \"<Let's Play Software> is a TV series created by Naver, EBS and Entry Labs. Learn the basic principles of programming. Watch the show, follow along the video tutorials, and learn to code!\",\n    \"open_project_to_all\": \"Open\",\n    \"close_project\": \"Close\",\n    \"category_media_art\": \"Media Art\",\n    \"go_further\": \"Go further\",\n    \"marked_project\": \"Favorite Project\",\n    \"marked_group_project\": \"Favorite group project\",\n    \"basic\": \"Basic\",\n    \"application\": \"Application\",\n    \"the_great_escape\": \"The Great Escape\",\n    \"escape_guide_1\": \"ENTRY Bot suddenly began to think for himself during a power failure at the robot dog factory! \",\n    \"escape_guide_1_2\": \" Help ENTRY Bot escape the factory and find his freedom!\",\n    \"escape_guide_2\": \"ENTRY Bot is missing too many parts to make it far. Help him find his parts as he makes his way out the factory!\",\n    \"escape_guide_2_2\": \"Objectives: Sequential Execution\",\n    \"escape_guide_3\": \"I’ve finally escaped the factory! But it’s still a long way to the village. I think I’m fixed up enough to make it there without too much difficulty. Hey, what’s that robot?\",\n    \"escape_guide_3_2\": \"Objectives: Repetitive and Conditional Statements\",\n    \"escape_guide_4\": \"We’re finally getting close to the village! I’m starting to really get the hang of this! I think it might be better to just use the blocks from memory. If I just recharge my battery here, I’ll be able to live free forever.\",\n    \"escape_guide_4_2\": \"Objectives: Definitions of Function and Function Call\",\n    \"space_travel_log\": \"Space Travel Log\",\n    \"space_guide_1\": \"ENTRY Bot has finally completed his exploration of distant space. He’s trying to make his way back home to Earth, but his path is being blocked by a bunch of space rocks! Help ENTRY Bot make it back to Earth safely!\",\n    \"space_guide_2\": \"It’s finally time to return to Earth! I can’t wait to get back and rest! Tell me the positions of the rocks ahead so I can navigate through them! I’ll go the way you tell me to!\",\n    \"space_guide_2_2\": \"Objective: Reiterating IF Statements and Logical Operation\",\n    \"cfest_mission\": \"ENTRY Experiential Mission\",\n    \"maze_1_intro\": \"Hi. I’m ENTRY Bot. I’m about to save my injured friends and I need your help. Help me save my friends! First, set up the ‘Move forward one space’ block and press ‘Start’.\",\n    \"maze_1_title\": \"How to Start\",\n    \"maze_1_content\": \"How do I move ENTRY Bot?\",\n    \"maze_1_detail\": \"1. Take a block from the Block Box and connect it with the ‘When Start is pressed’ block. <br> 2. Press Start once you have finished assembling. <br> 3. I will move in the order of your assembled blocks from top to bottom. \",\n    \"maze_2_intro\": \"Alright! You’ve saved the first of my friends! Now let’s save my next friend. Oh! There’s a beehive in the way! Use the Jump Over block to avoid the beehive and save my friend!\",\n    \"maze_2_title_1\": \"Jump Over\",\n    \"maze_2_content_1\": \"How do I get around obstacles?\",\n    \"maze_2_detail_1\": \"Sometimes your path may be blocked by an obstacle. <br> When there’s an obstacle in your path, you need to use the ‘Jump Over’ block.\",\n    \"maze_2_title_2\": \"How to Start\",\n    \"maze_2_content_2\": \"How do I move ENTRY Bot?\",\n    \"maze_2_detail_2\": \"1. Take a block from the Block Box and connect it with the ‘When Start is pressed’ block. <br> 2. Press Start once you have finished assembling. <br> 3. I will move in the order of your assembled blocks from top to bottom. \",\n    \"maze_3_intro\": \"Awesome! Now let’s go save another friend! How about we use the ‘Repeat’ block that my other friend gave use? You can easily repeat the same movements over again using the ‘Repeat’ block! Try changing the number of times to repeat. \",\n    \"maze_3_title\": \"Repeat Block (1)\",\n    \"maze_3_content\": \"How do I use the ‘Repeat (3)’ block?\",\n    \"maze_3_detail\": \"To perform the same action/s more than once, you need to use the ‘Repeat’ block. <br> Put the blocks that you want to repeat inside the Repeat box and select the number of times you want to repeat.\",\n    \"maze_4_intro\": \"Super! Not too many robot friends left to save now. Take us to my friend by using the ‘Jump Over’ block on repeat while also evading the beehive!\",\n    \"maze_4_title\": \"Repeat Block (1)\",\n    \"maze_4_content\": \"How do I use the ‘Repeat (3)’ block?\",\n    \"maze_4_detail\": \"To perform the same action/s more than once, you need to use the ‘Repeat’ block. <br> Put the blocks that you want to repeat inside the Repeat box and select the number of times you want to repeat.\",\n    \"maze_5_intro\": \"Cool! Now let’s try using the ‘Repeat’ block and ‘IF’ block together! Using the ‘IF’ block, you can turn in a direction where there are no walls when you come across a wall. Well then, shall we set off to save my friend?\",\n    \"maze_5_title_1\": \"IF block\",\n    \"maze_5_content_1\": \"How does the ‘IF’ block work?\",\n    \"maze_5_detail_1\": \"You can determine what action to take when you come across a {IMAGE}. <br> The blocks are used only when you come across a {IMAGE}. <br> If there is none, the block is not used.\",\n    \"maze_5_title_2\": \"Repeat Block (2)\",\n    \"maze_5_content_2\": \"How do I use the ‘Repeat until’block?\",\n    \"maze_5_detail_2\": \"Using the ‘Repeat until’block, you can determine until when a specified action is repeated. <br> Just put the blocks you want to repeat inside the ‘Repeat until’ block. <br> Then, the repetition will stop when you reach the space where the {IMAGE} is located. \",\n    \"maze_6_intro\": \"Only one friend left! Just do as we’ve practiced and you’ll succeed! Now, let’s go save him!\",\n    \"maze_6_title_1\": \"IF block\",\n    \"maze_6_content_1\": \"How does the ‘IF’ block work?\",\n    \"maze_6_detail_1\": \"You can determine what action to take when you come across a {IMAGE}. <br> The blocks are used only when you come across a {IMAGE}. <br> If there is none, the block is not used.\",\n    \"maze_6_title_2\": \"Repeat Block (2)\",\n    \"maze_6_content_2\": \"How do I use the ‘Repeat until’block?\",\n    \"maze_6_detail_2\": \"Using the ‘Repeat until’block, you can determine until when a specified action is repeated. <br> Just put the blocks you want to repeat inside the ‘Repeat until’ block. <br> Then, the repetition will stop when you reach the space where the {IMAGE} is located. \",\n    \"maze_programing_mode_0\": \"Block Coding\",\n    \"maze_programing_mode_1\": \"Javascript\",\n    \"maze_operation1_title\": \"STEP 1 – Javascript mode guide\",\n    \"maze_operation1_1_desc\": \"Hi, I'm Entrybot, the robot dog. Give me commands to reach the mission goals. You can learn about the mission when you begin under <span class=\\\"textShadow\\\">\\'Goals.\\'</span>\",\n    \"maze_operation1_2_desc\": \"Once you learn your goal, you need to give me <b>commands</b>. <span class=\\\"textUnderline\\\">\\’Command Box\\’</span> is where the <b>commands</b> reside. You can create <b>commands</b> using <b>mouse</b> and <b>keyboard.</b> With the <span class=\\\"textShadow\\\">mouse</span>, you can click or drag the <b>commands</b> to create instructions.\",\n    \"maze_operation1_2_textset_1\": \"How to click on the commands\",\n    \"maze_operation1_2_textset_2\": \"How to drag and drop commands\",\n    \"maze_operation1_3_desc\": \"If you want to use the <span class=\\\"textShadow\\\">keyboard</span> to give commands, <b>type in the commands</b> in the \\’Command Box.\\’<br>When you type in the commands, be careful not to ommit <span class=\\\"textShadow\\\">() and ;</span>\",\n    \"maze_operation1_4_desc\": \"Once you have finished inputting the commands, click <span class=\\\"textShadow\\\">[Run.]</span></br>I will move according to your code once you click [Run.]</br>If you want to know more about each command, check out the <span class=\\\"textShadow\\\">[Command guide.]</span>\",\n    \"maze_operation7_title\": \"STEP 7 - How repeat works (repeat number of times)\",\n    \"maze_operation7_1_desc\": \"Repeating the <b>same command</b> over and over is a cumbersome task.<br>Simplify the command using the <span class=\\\"textShadow\\\">repeat</span> commands.\",\n    \"maze_operation7_2_desc\": \"Then let's look at how we can simplify commands that repeat.</br>First, click the repeat command. Then change the <span class=\\\"textShadow\\\">number</span> in<span class=\\\"textShadow\\\">i<1</span></br>Then insert the commands to repeat within  <span class=\\\"textShadow\\\"> { }</span>\",\n    \"maze_operation7_3_desc\": \"For example, this command executes <span class=\\\"textBadge number1\\\"></span>move(); 10 times.<br>It is the same as command <span class=\\\"textBadge number2\\\"></span>\",\n    \"maze_operation7_4_desc\": \"When using commands, make sure to spell the  <span class=\\\"textShadow\\\">commands correctly within { } </span></br>and that you don't forget <span class=\\\"textShadow\\\">’;'</span>.</br>Learn more about the commands in the 'command guide'\",\n    \"maze_operation7_1_textset_1\": \"When using commands repeatedly\",\n    \"maze_operation7_1_textset_2\": \"When using repeat command\",\n    \"maze_operation7_2_textset_1\": \"Number of times to repeat\",\n    \"maze_operation7_2_textset_2\": \"Commands to repeat\",\n    \"maze_operation7_4_textset_1\": \"When ({}) is missing\",\n    \"maze_operation7_4_textset_2\": \"When semicolon(;) is missing\",\n    \"study_maze_operation8_title\": \"STEP 4 - How repeat works (repeat number of times)\",\n    \"study_maze_operation16_title\": \"STEP 4 - How repeat works (repeat number of times)\",\n    \"study_maze_operation1_title\": \"STEP 1 - How repeat works (repeat number of times)\",\n    \"maze_operation9_title\": \"STEP 9 - How repeat works(Conditional loop)\",\n    \"maze_operation9_1_desc\": \"We learned about repeating for set number of times.</br>This time, let's explore <span class=\\\"textShadow\\\">commands for repeating continuously.</span></br>When you use this command, the action will be executed until end of the mission.</br>Insert commands to be repeated within ({ }).\",\n    \"maze_operation9_2_desc\": \"<span class=\\\"textBadge number1\\\"></span> move(); right(); until end of mission.<br>It is the same as command <span class=\\\"textBadge number2\\\"></span>\",\n    \"maze_operation9_3_desc\": \"Make sure to spell the <span class=\\\"textShadow\\\">commands correctly within { }</span><br>and make sure <span class=\\\"textShadow\\\">‘true'</span> isn't missing!<br>You can learn more about this command in the 'command guide'\",\n    \"maze_operation9_1_textset_1\": \"Commands to repeat\",\n    \"maze_operation9_3_textset_1\": \"When ({}) is missing\",\n    \"maze_operation9_3_textset_2\": \"When semicolon(;) is missing\",\n    \"maze_operation9_3_textset_3\": \"When semicolon(;) is missing\",\n    \"study_maze_operation3_title\": \"STEP 3 - How repeat works(Conditional loop)\",\n    \"study_maze_operation4_title\": \"STEP 4 – How condition works\",\n    \"study_ai_operation4_title\": \"STEP 4 – How condition works\",\n    \"study_ai_operation6_title\": \"STEP 6 – How condition works\",\n    \"study_ai_operation7_title\": \"STEP 7 – How condition works\",\n    \"study_ai_operation8_title\": \"STEP 8 – How condition works\",\n    \"study_ai_operation9_title\": \"STEP 9 – How condition works\",\n    \"maze_operation10_title\": \"STEP 10 – How condition works\",\n    \"maze_operation10_1_desc\": \"We learned about repeating commands until end of the mission.</br>This time, let's explore the <span class=\\\"textShadow\\\">commands that are only executed under certain conditions.</span></br>As you can see in <span class=\\\"textBadge number2\\\"></span>, using conditional statement can make commands <b>more efficient.</b>\",\n    \"maze_operation10_2_desc\": \"conditional statement can be split into  <span class=\\\"textShadow\\\">condition</span> and commands to be <span class=\\\"textShadow\\\">executed when met with the condition.</span></br>First, let's look at the <span class=\\\"textUnderline\\\">conditions.</span> Insert the condition within <span class=\\\"textUnderline\\\">( )</span> that follows ‘if'.</br>For example <span class=\\\"textBadge number1\\\"></span> <span class=\\\"textUnderline\\\">if(front == ‘wall')</span> means, \\’if there is a wall in front of me.\\’\",\n    \"maze_operation10_3_desc\": \"Now let's explore  <span class=\\\"textUnderline\\\">commands to execute when met with the condition.</span> These commands are tied within curly <span class=\\\"textShadow\\\">braces {}</span> and are executed when met with the given condition.When condition is not met, the commands are ignored.Let's look at an example <span class=\\\"textBadge number1\\\"></span>. If the condition is 'when a wall is in front of me', and the condition is met, then <b>I execute the commands within the braces and turn right following the command right();</b>\",\n    \"maze_operation10_4_desc\": \"The <span class=\\\"textShadow\\\">conditional statements</span> are often used with <span class=\\\"textShadow\\\">repeat commands.</span></br>Go straight and turn only when met with a wall. </br>I can create commands in the <span class=\\\"textUnderline pdb5\\\">order of <span class=\\\"textBadge number1\\\"></span><span class=\\\"textBadge number2\\\"></span><span class=\\\"textBadge number3\\\"></span></span>\",\n    \"maze_operation10_1_textset_1\": \"<b>[commands]</b>\",\n    \"maze_operation10_1_textset_2\": \"<span class=\\\"textMultiline\\\">move 2 forward</br>turn right,</br>move 3 forward</br>turn right, move forward…</span>\",\n    \"maze_operation10_1_textset_3\": \"<b>[conditional statements]</b>\",\n    \"maze_operation10_1_textset_4\": \"<span class=\\\"textMultiline\\\">Go forward </br><span class=\\\"textEmphasis\\\">'when met with a wall’</span></br>turn right!</span>\",\n    \"maze_operation10_2_textset_1\": \"condition\",\n    \"maze_operation10_2_textset_2\": \"commands to execute when condition is met\",\n    \"maze_operation10_3_textset_1\": \"condition\",\n    \"maze_operation10_3_textset_2\": \"commands to execute when condition is met\",\n    \"maze_operation10_4_textset_1\": \"<span class=\\\"textMultiline\\\">Go forward </br>until end of mission</span>\",\n    \"maze_operation10_4_textset_2\": \"<span class=\\\"textMultiline\\\">Go forward </br>until met with a wall</span>\",\n    \"maze_operation10_4_textset_3\": \"<span class=\\\"textMultiline\\\">Go forward </br>until met with a wall </br>then turn right</span>\",\n    \"study_maze_operation18_title\": \"STEP 6 – How condition works\",\n    \"maze_operation15_title\": \"STEP 15 – How function works\",\n    \"maze_operation15_1_desc\": \"It is a cumbersome task to type out the commands that are used often.</br><span class=\\\"textUnderline\\\">Give a name to the set of commands</span> that are used often.</br><b>Then call the set of commands by its name to create commands conveniently.</b></br>These sets commands are called <span class=\\\"textShadow\\\">'functions'.</span> Now let's explore what functions are.\",\n    \"maze_operation15_2_desc\": \"Using a function involves <b>process of creating a function</b> by grouping a set of functions, and calling the set of commands by <b>'call function’.</b></br>Let's take a look at the process of defining a function.To define a function, give a function name and set of commands to execute.</br>First input <span class=\\\"textShadow\\\">‘function'</span> and then give the <span class=\\\"textShadow\\\">function name.</span> This time, I'll call it <span class=\\\"textShadow\\\">promise.</span></br>Once you've given it a name, insert <span class=\\\"textUnderline\\\">().</span> Then type in <span class=\\\"textUnderline\\\">({ })</span>.<span class=\\\"textUnderline\\\">Once you insert the commands within these brackets,</span> you have finished defining a function!\",\n    \"maze_operation15_3_desc\": \"Take a look at this command. I created a function called  <span class=\\\"textShadow\\\">promise</span></br>When I call this function, then the commands within the <span class=\\\"textUnderline\\\">brackets({})</span> will execute</br>move();</br>move();</br>left();</br>\",\n    \"maze_operation15_4_desc\": \"To call and execute functions, <b>input the name of the functions, then add '();' behind it.</b></br>So to call a function called 'promise', I need to type <span class=\\”textShadow\\\">promise();</span> </br>to execute the function.</br>When I make commands like <span class=\\\"number1 textBadge\\\"></span>, the program will execute as that of <span class=\\\"number2 textBadge\\\"></span></br>To use the function, define function as <span class=\\\"number1 textBadge\\\"></span> and call it.\",\n    \"maze_operation15_1_textset_1\": \"Checking the commands that are used often\",\n    \"maze_operation15_1_textset_2\": \"Giving a name for set of commands\",\n    \"maze_operation15_1_textset_3\": \"Calling a set of commands\",\n    \"maze_operation15_2_textset_1\": \"Name of the command set (function name)\",\n    \"maze_operation15_2_textset_2\": \"commads to group as a set\",\n    \"maze_operation15_3_textset_1\": \"Name of the command set (function name)\",\n    \"maze_operation15_3_textset_2\": \"commads to group as a set\",\n    \"maze_operation15_4_textset_1\": \"Defining function\",\n    \"maze_operation15_4_textset_2\": \"Calling function\",\n    \"maze_operation15_4_textset_3\": \"Real situation\",\n    \"maze_object_title\": \"Object info\",\n    \"maze_object_parts_box\": \"Tool box\",\n    \"maze_object_trap\": \"trap\",\n    \"maze_object_monster\": \"monster\",\n    \"maze_object_obstacle1\": \"obstacle\",\n    \"maze_object_obstacle2\": \"bee\",\n    \"maze_object_obstacle3\": \"banana\",\n    \"maze_object_friend\": \"friend\",\n    \"maze_object_wall1\": \"wall\",\n    \"maze_object_wall2\": \"wall\",\n    \"maze_object_wall3\": \"wall\",\n    \"maze_object_battery\": \"battery\",\n    \"maze_command_ex\": \"example\",\n    \"maze_command_title\": \"command guide\",\n    \"maze_command_move_desc\": \"moves entrybot one forward\",\n    \"maze_command_jump_desc\": \"jumps over obstacles like the image below.</br><div class=\\\"obstacleSet\\\"></div>\",\n    \"maze_command_jump_desc_elec\": \"jumps over obstacles like the image below.</br><div class=\\\"obstacle_elec\\\"></div>\",\n    \"maze_command_right_desc\": \"turn 90 degrees right in place.\",\n    \"maze_command_left_desc\": \"turn 90 degrees left in place.\",\n    \"maze_command_for_desc\": \"repeat commands within curly braces <span class=\\\"textShadow\\\">{}</span> for <span class=\\\"textShadow\\\">given number</span> of times.\",\n    \"maze_command_while_desc\": \"repeat commands within curly braces <span class=\\\"textShadow\\\">{}</span> until end of mission\",\n    \"maze_command_slow_desc\": \"When condition <span class=\\\"textShadow\\\">'when met with a wall’</span> is fulfilled, </br>execute commands within curly braces <span class=\\\"textShadow\\\">{}</span>\",\n    \"maze_command_if1_desc\": \"When condition <span class=\\\"textShadow\\\">'when met with a wall’</span> is fulfilled, </br>execute commands within curly braces <span class=\\\"textShadow\\\">{}</span>\",\n    \"maze_command_if2_desc\": \"When condition <span class=\\\"textShadow\\\">'when met with a beehive’</span> is fulfilled,</br>execute commands within curly braces <span class=\\\"textShadow\\\">{}</span>\",\n    \"maze_command_if3_desc\": \"When condition <span class=\\\"textShadow\\\">'when met with a banana’</span> is fulfilled,</br>execute commands within curly braces <span class=\\\"textShadow\\\">{}</span>\",\n    \"maze_command_promise_desc\": \"when a <span class=\\\"textShadow\\\">function</span> called 'promise' is defined and executed, </br>then the functions within the curly braces <span class=\\\"textShadow\\\">{}</span> will execute. \",\n    \"perfect\": \"Perfect! You succeeded using \",\n    \"succeeded_using_blocks\": \"  blocks!\",\n    \"succeeded_using_commands\": \"  commands!\",\n    \"awesome\": \"Awesome! You succeeded using just\",\n    \"succeeded_go_to_next\": \"  blocks!\",\n    \"good\": \"Good!\",\n    \"but\": \"<br> But, there is a way to succeed using just \",\n    \"try_again\": \"  blocks. <br>Why don’t you try again?\",\n    \"try_again_commands\": \"  commands. <br>Why don’t you try again?\",\n    \"cfest_success\": \"Awesome! You helped save my friends! <br> Looks like you’re a natural born programmer! <br> See you again soon!\",\n    \"succeeded_and_cert\": \"blocks!<br> My certificate of completion is ready!\",\n    \"cause_msgs_1\": \"Oh dear, it’s a dead end. Try again.\",\n    \"cause_msgs_2\": \"Oops. There’s nothing to jump over. Try again.\",\n    \"cause_msgs_3\": \"Ouch! That hurt. You should have jumped over this. Try again.\",\n    \"cause_msgs_4\": \"Sorry, but you need to use the below blocks in this level. <br> Do you want to try again?\",\n    \"cause_msgs_5\": \"Uh oh… You’ve run out of blocks. Try again.\",\n    \"cause_msgs_6\": \"Uh oh… You’ve run out of commands. Try again.\",\n    \"close_experience\": \"The<br>End\",\n    \"replay\": \"Replay\",\n    \"go_to_next_level\": \"Next\",\n    \"move_forward\": \"Move forward\",\n    \"turn_left\": \"Left\",\n    \"turn_right\": \"Right\",\n    \"turn_en\": \"Turn \",\n    \"turn_ko\": \"\",\n    \"jump_over\": \"Jump Over\",\n    \"when_start_is_pressed\": \"When Start is pressed\",\n    \"repeat_until_ko\": \"\",\n    \"repeat_until_en\": \"Repeat until\",\n    \"repeat_until\": \"Repeat until\",\n    \"if_there_is_1\": \"If there is a \",\n    \"if_there_is_2\": \"\",\n    \"used_blocks\": \"Blocks used\",\n    \"maximum\": \"Maximum\",\n    \"used_command\": \"Command used\",\n    \"maximum_command\": \"Maximum command\",\n    \"block_box\": \"Block Box\",\n    \"block_assembly\": \"Block Assembly\",\n    \"command_box\": \"Command Box\",\n    \"command_assembly\": \"Command Assembly\",\n    \"start\": \"Start\",\n    \"engine_running\": \"Play\",\n    \"engine_replay\": \"Replay\",\n    \"goto_show\": \"Learn more\",\n    \"make_together\": \"Let's build  together!\",\n    \"make_together_content\": \"Entry is created with teachers and students\",\n    \"project_nobody_like\": \"Click 'Like', if you like it!\",\n    \"project_nobody_interest\": \"Click 'Mark' to keep it on your blog.\",\n    \"lecture_nobody_like\": \"Click 'Like', if you like it!\",\n    \"lecture_nobody_interest\": \"Click 'Mark' to keep it on your blog.\",\n    \"course_nobody_like\": \"Click 'Like', if you like it!\",\n    \"course_nobody_interest\": \"Click 'Mark' to keep it on your blog.\",\n    \"before_changed\": \"before changed\",\n    \"after_changed\": \"after changed\",\n    \"from_changed\": \"( From 17 Apr 2016 ) \",\n    \"essential\": \"essential\",\n    \"access_term_title\": \"Hello we are an educational institute Entry . <br> Thank you for loving your entry <br>From April 17, 2016 Entry Training Institute Website Terms and Conditions <br>  is amended to read as follows:\",\n    \"member_info\": \"Member information\",\n    \"personal_info\": \"Agree to the transfer of personal information.\",\n    \"option\": \"select one\",\n    \"news\": \"news\",\n    \"edu_material\": \"materials\",\n    \"latest_news\": \"Latest news\",\n    \"edu_data\": \"Educational\",\n    \"training_program\": \"Training\",\n    \"footer_phrase\": \"Entry is a nonprofit education platform powered by Naver and CONNECT Foundation\",\n    \"footer_use_free\": \"All materials created by Entry Labs may be used freely for educational purposes as long as the original source is credited.\",\n    \"footer_description_1\": \"Entry is a nonprofit education platform.\",\n    \"footer_description_2\": \"All materials created by Entry Labs may be used freely for educational purposes as long as the original source is credited.\",\n    \"nonprofit_platform\": \"nonprofit educational platform\",\n    \"this_is\": \"powered by Naver and CONNECT Foundation\",\n    \"privacy\": \"Privacy policy\",\n    \"entry_addr\": \"16F, 6, Buljeong-ro, Bundang-gu, Seongnam-si, Gyeonggi-do\",\n    \"entry_addr_additional_phone\": \"1522-9182\",\n    \"entry_addr_additional_email\": \"entry@connect.or.kr\",\n    \"entry_addr_additional_opensource\": \"Open Source License\",\n    \"phone\": \"phone\",\n    \"alert_agree_term\": \"Please agree to ENTRY’s Terms of Use\",\n    \"alert_private_policy\": \"Please agree to the collection and use of personal information.\",\n    \"agree\": \"Agree\",\n    \"optional\": \"option\",\n    \"start_software\": \"first step of software education\",\n    \"analyze_procedure\": \"절차\",\n    \"analyze_repeat\": \"반복\",\n    \"analyze_condition\": \"분기\",\n    \"analyze_interaction\": \"상호작용\",\n    \"analyze_dataRepresentation\": \"데이터 표현\",\n    \"analyze_abstraction\": \"추상화\",\n    \"analyze_sync\": \"병렬 및 동기화\",\n    \"jr_intro_1\": \"Hi! My name is Juny! My friend Entry-Bot is by my right side. Please take me to him! \",\n    \"jr_intro_2\": \"Entry-Bot is by my left! Let's go the left side. \",\n    \"jr_intro_3\": \"Entry-Bot is by my top side. Please help me meet my friend. \",\n    \"jr_intro_4\": \"Come on! Let's meet Entry-Bot! He is by my bottom side. \",\n    \"jr_intro_5\": \"Wow! My friend is far away from me. Can you guide me so I can meet Entry-Bot \",\n    \"jr_intro_6\": \"Entry-Bot is really far away from here! But It's okay. If we use repeat block, we could reach the Entry-Bot easily.\",\n    \"jr_intro_7\": \"There are beautiful flowers here! Let's give it to my friend!\",\n    \"jr_intro_8\": \"On a way to my friend, you can see the flower. Let's give it to my friend.\",\n    \"jr_intro_9\": \"Oh, my friend is far away from me. Let's find a fastest way to him!\",\n    \"jr_intro_10\": \"There are flowers! Let's pick it up! \",\n    \"jr_intro_11\": \"We should go right side exactly 5 times! Let's use repeat block so we can reach there more easily\",\n    \"jr_intro_12\": \"Let's meet my friend Entry-Bot using repeat block.\",\n    \"jr_intro_13\": \"With this misplaced block, I can't reach my friend. Please change the input number of repeat block.\",\n    \"jr_intro_14\": \"Please take me to my friend Entry-Bot using repeat block.\",\n    \"jr_intro_15\": \"Entry-Bot is really far away from here! But It's okay. If we use repeat block, we could reach the Entry-Bot easily.\",\n    \"jr_whats_ur_name\": \"What is your name to be showned on certification.\",\n    \"jr_down_cert\": \"Certification\",\n    \"jr_popup_prefix_1\": \"Hooray! I met Entry-Bot!\",\n    \"jr_popup_prefix_2\": \"Nice! I met Entry-Bot! But we can make it with fewer blocks. How about try again?\",\n    \"jr_popup_prefix_3\": \"Hooray! I got my backpack!\",\n    \"jr_popup_prefix_4\": \"Great! I have my backpack! But we can make it with fewer blocks. How about we try again?\",\n    \"jr_popup_suffix_1\": \"Thank you! I had so much fun with you. See you around!\",\n    \"jr_popup_suffix\": \"Thanks to you! I had fun time with Entry-Bot. See you around~\",\n    \"jr_fail_dont_go\": \"Oops, I can't go there. Please guide me again~\",\n    \"jr_fail_dont_know\": \"Hmm. Where should I go? Please guide me more~\",\n    \"jr_fail_no_flower\": \"There is no flower. Use 'flower block' at the flower!\",\n    \"jr_fail_forgot_flower\": \"I need more flowers for Entry-Bot. Let's try again.\",\n    \"jr_fail_need_repeat\": \"Uh? I should use 'repeat block' ! Let's try again with the block~\",\n    \"jr_hint_1\": \"Hi! My name is Juny! My friend Entry-Bot is by my right side. Please take me to him!\",\n    \"jr_hint_2\": \"Entry-Bot is by my left! Let's go the left side.\",\n    \"jr_hint_3\": \"Entry-Bot is by my top side. Please help me meet my friend.\",\n    \"jr_hint_4\": \"Come on! Let's meet Entry-Bot! He is by my bottom side.\",\n    \"jr_hint_5\": \"Wow! My friend is far away from me. Can you guide me so I can meet Entry-Bot?\",\n    \"jr_hint_6\": \"Because of the blocks that put together by mistake, I can't reach my friend. Please fix it for me so I can reach my friend Entry-Bot!\",\n    \"jr_hint_7\": \"There are beautiful flowers here! Let's give it to my friend!\",\n    \"jr_hint_8\": \"On a way to my friend, you can see the flower. Let's give it to my friend.\",\n    \"jr_hint_9\": \"Oh, my friend is far away from me. Let's find a fastest way to him!\",\n    \"jr_hint_10\": \"Oops, I can't reach to my friend because of misplaced blocks. Please fix it so I can give all of flowers to my friend.\",\n    \"jr_hint_11\": \"We should go right side exactly 5 times! Let's use repeat block so we can reach there more easily.\",\n    \"jr_hint_12\": \"Let's meet my friend Entry-Bot using repeat block.\",\n    \"jr_hint_13\": \"With this misplaced block, I can't reach my friend. Please change the input number of repeat block.\",\n    \"jr_hint_14\": \"Please take me to my friend Entry-Bot using repeat block.\",\n    \"jr_hint_15\": \"Entry-Bot is really far away from here! But It's okay. If we use repeat block, we could reach the Entry-Bot easily.\",\n    \"jr_certification\": \"Certification\",\n    \"jr_congrat\": \"Congratulation!\",\n    \"jr_congrat_msg\": \"Successfully completed for problem solving courses.\",\n    \"jr_share\": \"Share\",\n    \"go_see_friends\": \"Let us see your friends~!\",\n    \"junior_naver\": \"Junior Naver\",\n    \"junior_naver_contents_1\": \"'s  cool bear ,  Juni  came looking for entries! \",\n    \"junior_naver_contents_2\": \"But Juni' is difficult to find a way yet. \",\n    \"junior_naver_contents_3\": \"Please tell Juni to go , so he can meet entrybot.\",\n    \"basic_content\": \"Basic\",\n    \"jr_help\": \"Help\",\n    \"help\": \"Help\",\n    \"cparty_robot_intro_1\": \"Hi, My name is Entry-bot. I need to to fix myself. Please help me get my parts with 'move forward' block.\",\n    \"cparty_robot_intro_2\": \"Great! My part is right in front of me but I need to be careful not to get electrocuted. Use 'jump over' block to get to the part.\",\n    \"cparty_robot_intro_3\": \"Great! There's my part! The path is challenging but using the 'turn' block I can get there easily! Will you help?\",\n    \"cparty_robot_intro_4\": \"Nice! I feel a lot better! Try using the 'turn' block and 'jump over' block to get the parts!\",\n    \"cparty_robot_intro_5\": \"Thanks to you, I'm feeling great! Make sure to use 'turn' and 'jump over' to get the part!\",\n    \"cparty_robot_intro_6\": \"Great! I feel like I can repeat! Use repeat to get to the part!\",\n    \"cparty_robot_intro_7\": \"Watch out! There are dangerous holes to jump over but no worries! Let's use repeat to get to the part.\",\n    \"cparty_robot_intro_8\": \"Oh no! The part is far from here. Using repeat can get me there easily. Help me! \",\n    \"cparty_robot_intro_9\": \"Wow~ I'm almost complete! Let's use 'repeat' to get to the part!\",\n    \"cparty_robot_intro_10\": \"Cool! The last part will make me complete! Let's use 'repeat' to get to my last part! \",\n    \"cparty_car_intro_1\": \"Hi, My name is Entry-bot. I need battery pack to travel! Can you me get to the battery pack?\",\n    \"cparty_car_intro_2\": \"Good! We can't go straight this time! Let's use the 'turn left/right' block to get to the battery pack.\",\n    \"cparty_car_intro_3\": \"Great! There's a speed bump on our way. It'll be dangerous to drive fast. Let's use the 'go slow' block to get to the battery pack.\",\n    \"cparty_car_intro_4\": \"Yeah! The drive doesn't look easy but using the move forward, 'turn left/ right' block\",\n    \"cparty_car_intro_5\": \"The road looks challenging but we can safely get to the battery pack by repeating 'turn left/ right' blocks\",\n    \"cparty_car_intro_6\": \"There are obstacles on our way so let me know how to get around one!\",\n    \"cparty_car_intro_7\": \"Great! Let's use the 'if' block to get around obastacles and get to the battery pack.\",\n    \"cparty_car_intro_8\": \"There are two speed bumps this time! Use 'go slow' block to safely travel to the battery pack.\",\n    \"cparty_car_intro_9\": \"The road looks challenging but using the 'repeat' block and 'if' block, we can make it! Help me get to the battery pack!\",\n    \"cparty_car_intro_10\": \"Awesome! We're almost there. Let's get that last battery pack!\",\n    \"cparty_car_popup_prefix_1\": \"Hooray! I got a battery!\",\n    \"cparty_car_popup_prefix_2\": \"Nice! I got a battery! But we can make it with fewer blocks. How about try again?\",\n    \"cparty_car_popup_prefix_2_text\": \"Nice! I got a battery! But we can make it with fewer commands How about try again?\",\n    \"cparty_car_popup_suffix\": \"Thanks to you! I've got all the battery. See you around~\",\n    \"all_grade\": \"All grades\",\n    \"grade_e3_e4\": \"Elementary 3~4th grade & up\",\n    \"grade_e5_e6\": \"Elementary 5~6th grade & up\",\n    \"grade_m1_m3\": \"Middle School 1~3rd grade & up\",\n    \"entry_first_step\": \"Entry First Steps\",\n    \"entry_monthly\": \"Monthly Entry\",\n    \"play_sw_2\": \"Let's Play  Software 2\",\n    \"entry_programming\": \"Let's Program!\",\n    \"entry_recommanded_course\": \"Entry Recommended Courses\",\n    \"introduce_course\": \"Follow along and create various projects made easy and fun for everyone!\",\n    \"all_free\": \"*Course videos, customized projects, and resources are provided for free.  \",\n    \"cparty_result_fail_1\": \"Oops, I can't go there. Please guide me again~\",\n    \"cparty_result_fail_2\": \"Ouch! That hurt. You should have jumped over this. Try again.\",\n    \"cparty_result_fail_3\": \"I'm worn out! Try using the blocks below and make the travel easier.\",\n    \"cparty_result_fail_4\": \"Hmm... Where should I go? Please give me further instructions.\",\n    \"cparty_result_fail_5\": \"Oh no! You need to slow down at the speed bump. Try using the 'go slow' block.\",\n    \"cparty_result_success_1\": \"Hooray! I got a parts\",\n    \"cparty_result_success_2\": \"Nice! I got a parts! But we can make it with fewer blocks. How about we try again?\",\n    \"cparty_result_success_2_text\": \"Nice! I got a parts! But we can make it with fewer commands How about we try again?\",\n    \"cparty_result_success_3\": \"Thanks to you! I've fixed all~ See you around~\",\n    \"cparty_insert_name\": \"insert your name\",\n    \"offline_file\": \"File\",\n    \"offline_edit\": \"Edit\",\n    \"offline_undo\": \"Un-do\",\n    \"offline_redo\": \"Re-do\",\n    \"offline_quit\": \"Quit\",\n    \"select_one\": \"Please select one.\",\n    \"evaluate_challenge\": \"please evaluate the level of difficulty of the mission challenged.\",\n    \"very_easy\": \"very easy\",\n    \"easy\": \"easy\",\n    \"normal\": \"normal\",\n    \"difficult\": \"difficult\",\n    \"very_difficult\": \"very difficult\",\n    \"save_dismiss\": \"bạn đã không lưu thay đổi. Bạn có chắc chắn muốn tiếp tục không?\",\n    \"entry_info\": \"About Entry\",\n    \"actual_size\": \"Actual Size\",\n    \"zoom_in\": \"Zoom In\",\n    \"zoom_out\": \"Zoom Out\",\n    \"cparty_jr_intro_1\": \"Hi! My name is Entry-Bot! Please help me get my backpack on my way to school.\",\n    \"cparty_jr_intro_2\": \"My backpack to my left! Let's go left.\",\n    \"cparty_jr_intro_3\": \"My backpack is located above. Please help me to get my backpack.\",\n    \"cparty_jr_intro_4\": \"Come on! Let's pick up the backpack by going downwards.\",\n    \"cparty_jr_intro_5\": \"Wow! My backpack is far away from me. Could you take me to my backpack?\",\n    \"cparty_jr_intro_6\": \"There is backpack! Let's pick it up!\",\n    \"cparty_jr_intro_7\": \"There are pencils along the way. Let's pick them up on our way to the backpack.\",\n    \"cparty_jr_intro_8\": \"A pencil on our way to school! Let's pick up the pencil on our way to the backpack.\",\n    \"cparty_jr_intro_9\": \"Oh, my backpack is far away. Let's find the fastest path to it!\",\n    \"cparty_jr_intro_10\": \"Let's pick up the pencils on my way to the backpack!\",\n    \"cparty_jr_intro_11\": \"We should go right exactly 5 times! Let's use the repeat block so we can get there more easily\",\n    \"cparty_jr_intro_12\": \"Let's pick up the backpack using the repeat block.\",\n    \"cparty_jr_intro_13\": \"I can't reach my backpack with this misplaced block. Please change the number of repeats.\",\n    \"cparty_jr_intro_14\": \"Please take me to my backpack using the repeat blocks.\",\n    \"cparty_jr_intro_15\": \"School is really far from here! But that's okay. If we use the repeat block, we can get to school easily.\",\n    \"make_new_project\": \"Create New Project\",\n    \"open_old_project\": \"Open Project\",\n    \"offline_download\": \"Entry Download\",\n    \"offline_release\": \"Download Entry Offline Editor!\",\n    \"offline_description_1\": \"Install and use Entry Offline Editor\",\n    \"offline_description_2\": \"without internet connection.\",\n    \"offline_description_3\": \"Download and try it out!\",\n    \"sw_week_2015\": \"2015 소프트웨어교육 체험 주간\",\n    \"cparty_desc\": \"두근두근 소프트웨어와의 첫만남\",\n    \"entry_offline_download\": \"Download \\nOffline Editor\",\n    \"entry_download_detail\": \"Download\\nVeiw Details\",\n    \"offline_desc_1\": \"Install and use Entry Offline Editor without internet connection.\",\n    \"offline_desc_2\": \"Download and try it out!\",\n    \"download\": \"download\",\n    \"version\": \"version\",\n    \"file_size\": \"size\",\n    \"update\": \"update\",\n    \"use_range\": \"Scope of use\",\n    \"offline_desc_free\": \"Entry Offline Editor is free for both individual and corporate use.\",\n    \"offline_required\": \"System Requirement\",\n    \"offline_required_detail\": \"Minimum 1GB disk space is required, Windows7 and above or, Mac OS 10.8 and above\",\n    \"offline_notice\": \"Side notes\",\n    \"offline_notice_1\": \"1. Version\",\n    \"offline_notice_1_1\": \"does not support installation of all-in-one hardware connection program\",\n    \"offline_notice_2\": \"2. Web browser is not needed.\",\n    \"offline_notice_3\": \"Release note\",\n    \"offline_notice_4\": \"Download by version\",\n    \"offline_notice_5\": \"Release note\",\n    \"hardware_online_badge\": \"Online\",\n    \"hardware_title\": \"Entry Hardware Connector Program Download\",\n    \"hardware_desc\": \"In order to connect to hardware projects and 'Create Project' online, download and install Entry Hardware Connector Program.\",\n    \"hardware_release\": \"Details on Hardware Connector Program updates are available in the link below.\",\n    \"hardware_window_download\": \"Windows Download\",\n    \"hardware_osx_download\": \"Mac Download\",\n    \"cparty_jr_result_2\": \"Thank you! I had so much fun with you.<br> See you around!\",\n    \"cparty_jr_result_3\": \"Great! I've arrived school! But we can make it with fewer blocks.<br> How about we try again? \",\n    \"cparty_jr_result_4\": \"\",\n    \"lms_no_class\": \"There is no class.\",\n    \"lms_create_class\": \"Please create a class.\",\n    \"lms_add_class\": \"Create class\",\n    \"lms_base_class\": \"Default\",\n    \"lms_delete_class\": \"Delete\",\n    \"lms_my_class\": \"My Class\",\n    \"lms_grade_1\": \"elementary school 1\",\n    \"lms_grade_2\": \"elementary school 2\",\n    \"lms_grade_3\": \"elementary school 3\",\n    \"lms_grade_4\": \"elementary school 4\",\n    \"lms_grade_5\": \"elementary school 5\",\n    \"lms_grade_6\": \"elementary school 6\",\n    \"lms_grade_7\": \"middle school 1\",\n    \"lms_grade_8\": \"middle school 2\",\n    \"lms_grade_9\": \"middle school 3\",\n    \"lms_grade_10\": \"general\",\n    \"lms_add_groupId_personal\": \"Add classroom ID to your member profile.\",\n    \"lms_add_groupId\": \"Add Classroom ID\",\n    \"lms_add_group_account\": \"Add Classroom ID\",\n    \"lms_enter_group_info\": \"Enter classroom ID and password\",\n    \"lms_group_id\": \"Classroom ID\",\n    \"lms_group_pw\": \"Password\",\n    \"lms_group_name\": \"Class Name\",\n    \"personal_pwd_alert\": \"Enter correct password\",\n    \"personal_form_alert\": \"양식을 바르게 입력해 주세요\",\n    \"personal_form_alert_2\": \"모든 양식을 완성해 주세요\",\n    \"personal_no_pwd_alert\": \"Enter password\",\n    \"select_gender\": \"Please enter your gender\",\n    \"enter_group_id\": \"Enter classroom ID\",\n    \"enter_group_pwd\": \"Enter password\",\n    \"info_added\": \"추가되었습니다\",\n    \"no_group_id\": \"The Class ID does not exist\",\n    \"no_group_pwd\": \"비밀번호가 일치하지 않습니다\",\n    \"lms_please_choice\": \"Choose\",\n    \"group_lesson\": \"나의 학급 강의\",\n    \"lms_banner_add_group\": \"Learning Management System is now available\",\n    \"lms_banner_entry_group\": \"Create Entry class \",\n    \"lms_banner_desc_1\": \"Add your students\",\n    \"lms_banner_desc_2\": \"Manage your student's projects\",\n    \"lms_banner_desc_3\": \"and track their growth.\",\n    \"lms_banner_download_manual\": \"Manual Download\",\n    \"lms_banner_detail\": \"Try it out!\",\n    \"already_exist_email\": \"email already exists\",\n    \"same_registered_email\": \"Registered email.\",\n    \"email_correnctly_please\": \"Please enter a valid email\",\n    \"remove_project\": \"Are you sure to remove this project?\",\n    \"study_lesson\": \"Class Lessons\",\n    \"open_project\": \"Open Project\",\n    \"make_group\": \"Create Class\",\n    \"project_share\": \"Project share\",\n    \"group_project_share\": \"Class Share\",\n    \"group_discuss\": \"Class Discuss\",\n    \"my_profile\": \"My page\",\n    \"search_updated\": \"Recent Project\",\n    \"search_recent\": \"Project with most views\",\n    \"search_complexity\": \"Project with most effort\",\n    \"search_staffPicked\": \"Staff pick project save area\",\n    \"search_childCnt\": \"Project with most copies\",\n    \"search_likeCnt\": \"Project with most likes\",\n    \"search_recentLikeCnt\": \"Project with most likes\",\n    \"gnb_share\": \"Share\",\n    \"gnb_community\": \"Community\",\n    \"lms_add_lectures\": \"Add Lessons\",\n    \"lms_add_course\": \"Add Courseware\",\n    \"lms_add_homework\": \"Add Assignment\",\n    \"remove_lecture_confirm\": \"Are you sure you want to delete?\",\n    \"popup_delete\": \"Delete\",\n    \"remove_course_confirm\": \"Are you sure you want to delete?\",\n    \"lms_no_lecture_teacher_1\": \"There is no lessons.\",\n    \"lms_no_lecture_teacher_2\": \"Please create a lessons.\",\n    \"gnb_download\": \"Download\",\n    \"lms_no_lecture_student_1\": \"\",\n    \"lms_no_lecture_student_2\": \"There is no lessons.\",\n    \"lms_no_lecture_student_3\": \"\",\n    \"lms_no_class_teacher\": \"There is no class.\",\n    \"lms_no_course_teacher_1\": \"There is no courseware.\",\n    \"lms_no_course_teacher_2\": \"Please create a courseware.\",\n    \"lms_no_course_student_1\": \"\",\n    \"lms_no_course_student_2\": \"There is no courseware.\",\n    \"lms_no_course_student_3\": \"\",\n    \"lms_no_hw_teacher_1\": \"There is no assignment.\",\n    \"lms_no_hw_teacher_2\": \"Please create a assignment.\",\n    \"lms_no_hw_student_1\": \"\",\n    \"lms_no_hw_student_2\": \"There is no assignment.\",\n    \"lms_no_hw_student_3\": \"\",\n    \"modal_edit\": \"edit\",\n    \"modal_deadline\": \"Deadline\",\n    \"modal_hw_desc\": \"Description\",\n    \"desc_optional\": \"(optional)\",\n    \"modal_create_hw\": \"Create Assignment\",\n    \"vol\": \"Vol.\",\n    \"hw_title\": \"Title\",\n    \"hw_description\": \"Description\",\n    \"deadline\": \"Deadline\",\n    \"do_homework\": \"Do Assignment\",\n    \"hw_progress\": \"Progress\",\n    \"hw_submit\": \"submit\",\n    \"view_list\": \"Submitter\",\n    \"view_desc\": \"content\",\n    \"do_submit\": \"submit\",\n    \"popup_notice\": \"Alert\",\n    \"no_selected_hw\": \"No Assignment is selected\",\n    \"hw_delete_confirm\": \"Are you sure you want to delete?\",\n    \"hw_submitter\": \"List of Assignment submissions\",\n    \"hw_student_desc_1\": \"* You may edit the project until 'Submit' button completes the submission process.\",\n    \"hw_student_desc_2\": \"* Once submission period is over, project cannot be submitted.\",\n    \"popup_create_class\": \"Create Class\",\n    \"class_name\": \"Class name\",\n    \"image\": \"Image\",\n    \"select_class_image\": \"Please select a class image.\",\n    \"type_class_description\": \"Class Introduction.\",\n    \"set_as_primary_group\": \"Set as default classroom\",\n    \"set_primary_group\": \"assign\",\n    \"not_primary_group\": \"not assigned\",\n    \"type_class_name\": \"Please enter the class name.\",\n    \"type_class_description_long\": \"Please enter the class introduction.\",\n    \"add_students\": \"Add students\",\n    \"invite_students\": \"Invite students\",\n    \"invite_with_class\": \"1. Invite with class code\",\n    \"invite_code_expiration\": \"Code expiration time\",\n    \"generate_code_button\": \"reissue code\",\n    \"generate_code_desc\": \"Student instructions for entering class code\",\n    \"generate_code_desc1\": \"Log in at playentry.org\",\n    \"generate_code_desc2\": \"Select <my class> from the menu.\",\n    \"generate_code_desc3\": \"Click <Enter class code> then paste in the class code.\",\n    \"invite_with_url\": \"2. Invite using class URL\",\n    \"copy_invite_url\": \"Copy\",\n    \"download_as_pdf\": \"Download code as PDF file\",\n    \"download_as_excel\": \"Download code as Excel file\",\n    \"temp_password\": \"Temporary password\",\n    \"step_name\": \"Name\",\n    \"step_info\": \"Additional Information\",\n    \"preview\": \"Preview\",\n    \"type_name_enter\": \"To add student, type in the student name and hit enter. \",\n    \"multiple_name_possible\": \"Adding multiple student names is possible.\",\n    \"id_auto_create\": \"Student number is automatically created if not edited\",\n    \"student_id_desc_1\": \"Class ID is created automatically without manual input\",\n    \"student_id_desc_2\": \"If student account already exists, add student information. When the student logs in,\",\n    \"student_id_desc_3\": \"class invitation is sent. No extra step for sharing account information is necessary.\",\n    \"student_number\": \"Student number\",\n    \"temp_password_desc_1\": \"After logging in with temporary password,\",\n    \"temp_password_desc_2\": \"guide the students to reset the password.\",\n    \"temp_password_desc_3\": \"*You cannot see temporary password once issued\",\n    \"temp_password_demo\": \"This is an informational account that can not log in.\",\n    \"temp_works\": \"View works\",\n    \"student_delete_confirm\": \"Are you sure you want to delete?\",\n    \"no_student_selected\": \"No student is selected\",\n    \"class_assignment\": \"Class Assignments\",\n    \"class_list\": \"Class List\",\n    \"select_grade\": \"Please select the grade.\",\n    \"add_project\": \"sharing Project\",\n    \"no_project_display\": \"There is no project to display.\",\n    \"plz_display_project\": \"Please display a project.\",\n    \"refuse_confirm\": \"Are you sure you want to refuse?\",\n    \"select_class\": \"학급 선택\",\n    \"group_already_registered\": \"Already registered.\",\n    \"my_page_entry\": \"Entry\",\n    \"my_page_title\": \"My Page\",\n    \"my_classGroup_title\": \"My Class\",\n    \"my_classGroup_title_view\": \"view my class\",\n    \"my_space_area\": \"my own space\",\n    \"mon\": \"MON\",\n    \"tue\": \"TUE\",\n    \"wed\": \"WED\",\n    \"thu\": \"THU\",\n    \"fri\": \"FRI\",\n    \"sat\": \"SAT\",\n    \"sun\": \"SUN\",\n    \"jan\": \"Jan\",\n    \"feb\": \"Feb\",\n    \"mar\": \"Mar\",\n    \"apr\": \"Apr\",\n    \"may\": \"May\",\n    \"jun\": \"Jun\",\n    \"jul\": \"Jul\",\n    \"aug\": \"Aug\",\n    \"sep\": \"Sep\",\n    \"oct\": \"Oct\",\n    \"nov\": \"Nov\",\n    \"dec\": \"Dec\",\n    \"plz_select_lecture\": \"Please select a lessons.\",\n    \"plz_set_deadline\": \"Please set the deadline.\",\n    \"hide_entry\": \"Hide Entry\",\n    \"hide_others\": \"Hide Others\",\n    \"show_all\": \"Show All\",\n    \"lecture_description\": \"Lessons are listed by topics and levels. Follow along in step-by-step order.\",\n    \"curriculum_description\": \"Teacher created Entry learning space. See example projects and try creating them.\",\n    \"linebreak_off_desc_1\": \"Kích thước của hộp văn bản xác định kích thước phông chữ\",\n    \"linebreak_off_desc_2\": \"Nội dung của bạn chỉ có thể được viết trong một dòng\",\n    \"linebreak_off_desc_3\": \" bên trái và bên phải của hộp sẽ kéo dài khi bạn thêm từ \",\n    \"linebreak_on_desc_1\": \"kích thước của hộp văn bản xác định phạm vi mà bạn có thể viết\",\n    \"linebreak_on_desc_2\": \"Bạn có thể thay đổi dòng bằng cách nhấn phím 'Enter'\",\n    \"linebreak_on_desc_3\": \"Nội dung của bạn sẽ tự động đi đến dòng kế tiếp nếu chiều dài vượt quá chiều rộng của hộp văn bản, khi viết hoặc thêm từ mới.\",\n    \"not_supported_text\": \"Current font does not support Chinese characters\",\n    \"entry_with\": \"Entry is Created With Teachers\",\n    \"ebs_season_1\": \"Visit Season 1\",\n    \"ebs_season_2\": \"Visit Season 2\",\n    \"hello_ebs\": \"Hello! EBS software\",\n    \"hello_ebs_desc\": \"Learn the basic principles of programming. \\n Watch the show, follow along the video tutorials, \\n and learn to code!\",\n    \"hello_ebs_sub_1\": \"Meet EBS's interactive middle \",\n    \"hello_ebs_sub_2\": \"school age program.\",\n    \"exhibit_4th_title\": \"4th Anniversary of Entry\",\n    \"exhibit_4th_subtitle\": \"Entry Project Contest\",\n    \"exhibit_4th_desc1\": \"We hold an Entry Project Contest \",\n    \"exhibit_4th_desc2\": \"to celebrate the 4th anniversary of entry.\",\n    \"exhibit_4th_desc3\": \"Show off your great project!\",\n    \"exhibit_4th_button\": \"View Details\",\n    \"visang_edu_entry\": \"비상교육 엔트리 학습하기\",\n    \"cmass_edu_entry\": \"씨마스 엔트리 학습하기\",\n    \"chunjae_edu_entry\": \"천재교과서 엔트리 학습하기\",\n    \"kumsungemt_edu_entry\": \"금성출판사 엔트리 학습하기\",\n    \"kumsungMid_edu_entry\": \"금성출판사 엔트리 학습하기\",\n    \"gilbutEdu_edu_entry\": \"길벗출판사 엔트리 학습하기\",\n    \"miraenCoding_edu_entry\": \"미래엔 엔트리 학습하기\",\n    \"textbook_help_data\": \"Help data\",\n    \"textbook_teaching_activity\": \"teaching and activity\",\n    \"textbook_kyohacksa\": \"Kyohaksa\",\n    \"textbook_kumsung\": \"Kumsung Publishing\",\n    \"textbook_donga\": \"Dong-a Publishing\",\n    \"textbook_chunjae\": \"Chunjae Education\",\n    \"textbook_miraen\": \"Mirae-n\",\n    \"textbook_visang\": \"Visang\",\n    \"partner\": \"Our Partners\",\n    \"project_term_popup_title\": \"Copyright policy\",\n    \"project_term_popup_description_1\": \"Please review the Entry \",\n    \"project_term_popup_description_2\": \"copyright policy \",\n    \"project_term_popup_description_3\": \"to allow public viewing \",\n    \"project_term_popup_description_4\": \"of the project.\",\n    \"project_term_agree_1_1\": \"I agree to the release of my work itself and its source code.\",\n    \"project_term_agree_2_1\": \"I permit others to use it.\",\n    \"project_term_agree_2_2\": \"(includes copy, distribution, and transmission through airwaves)\",\n    \"project_term_agree_3_1\": \"I permit others to make modifications to it.\",\n    \"project_term_agree_3_2\": \"(includes remixes, modifications, and derivative works)\",\n    \"agree_all\": \"I agree to all conditions.\",\n    \"select_login\": \"Log in\",\n    \"select\": \"Please select\",\n    \"with_login\": \"Log in and\",\n    \"without_login\": \"Start Challenge\",\n    \"start_challenge\": \"Start Challenge\",\n    \"start_challenge_2\": \"without Logging in\",\n    \"if_not_save_not_login\": \"* Your progress will not be saved if not logged in.\",\n    \"if_not_member_yet\": \"If you aren't a member yet,\",\n    \"join_entry\": \"Join Entry\",\n    \"learned_computing\": \"Have you learned computing before?\",\n    \"cparty_index_description_1\": \"My first computing.\",\n    \"cparty_index_description_2\": \"Learn programming concepts and develop your thinking skills while playing Entry. \",\n    \"cparty_index_description_3\": \"Challenge yourself to exciting mission stages and earn certificates.\",\n    \"cparty_index_description_4\": \"2015 Online Coding Party is part of\",\n    \"cparty_index_description_5\": \"Software Programming Experience Week\",\n    \"cparty_index_description_6\": \"prepared with\",\n    \"cparty_index_description_7\": \"Association of Teachers for Computing.\",\n    \"cparty_index_description_8\": \"\",\n    \"cparty_index_description_9\": \"2016 Online Coding Party is part of\",\n    \"cparty_index_description_10\": \"2017 Online Coding Party is part of\",\n    \"cparty_index_description_11\": \"Association of Teachers for Computing.\",\n    \"congratulation\": \"Congratulation!\",\n    \"warm_up\": \"warm-up\",\n    \"beginner\": \"beginner\",\n    \"intermediate\": \"intermediate\",\n    \"advanced\": \"advanced\",\n    \"applied\": \"applied\",\n    \"cert_msg_tail\": \"track.\",\n    \"cert_msg_head\": \"You have successfully completed the\",\n    \"maze_text_content_1\": \" 명령어를 사용해서 나를 부품 상자까지 이동시켜줘!\",\n    \"maze_text_content_2\": \" 명령어를 사용해서 장애물을 뛰어넘어야해!\",\n    \"maze_text_content_3\": \"Nice! I see another part over there. The path is twisted but I can get there using the 'right();', 'left();' commands. \",\n    \"maze_text_content_4\": \"I can move smoothly now. Take me to my parts using the commands we've learned so far.\",\n    \"maze_text_content_5\": \"Wow! Two parts! Let's collect them both so I can recover faster.\",\n    \"maze_text_content_6\": \"Last part! I'll recover fully with that last piece. You'll help me, right?\",\n    \"maze_text_content_7\": \"I'm feeling great! I can repeat tasks without stress now. Oh no! What is that robot in front of us? I think it needs help! Use 'for' command to get to the friend!\",\n    \"maze_text_content_8\": \"Excellent! I was able to rescue my robot friend thanks to you. I see another friend over there. Be careful. There are beehives to avoid. You can do it! Let's use the 'for' command to get to my friend.\",\n    \"maze_text_content_9\": \"Use 'while' instead of 'for' to repeat until we've accomplished our goal. Take me to my friend.\",\n    \"maze_text_content_10\": \"Now we have 'if' command. Use 'if' and 'while' to let me know which way to turn.\",\n    \"maze_text_content_11\": \"Great! Let's do this once more. Tell me when to turn left.\",\n    \"maze_text_content_12\": \"There are beehives scattered in the pathway. Tell me when to jump over.\",\n    \"maze_text_content_13\": \"So many friends need help! Let's go help them\",\n    \"maze_text_content_14\": \"More friends to rescue! Let's first try going around those square blocks and repeat to get to all of my friends.\",\n    \"maze_text_content_15\": \"I'm tired from moving so much. I've grouped the commands that are often used into 'functions'. Use functions to get me to my battery!\",\n    \"maze_text_content_16\": \"Excellent! Create functions and take me to my battery!\",\n    \"maze_text_content_17\": \"Great job! Let's create functions with 'jump()\",\n    \"maze_text_content_18\": \"The pathway is complex this time. But no worries! Just tell me when to use 'left()\",\n    \"maze_text_content_19\": \"The functions are already defined! However, it seems difficult to get to the battery using only the functions. Let's try mixing functions and commands to get to the battery.\",\n    \"maze_text_content_20\": \"You've done a fantastic job so far! After I retrieve that last battery, I will no longer need charging. Help me get to the battery using the functions so I can live free forever!\",\n    \"maze_content_1\": \"Hi, I'm Entrybot. I'm trying to escape from this factory but first, I have to fix myself. Will you help me fetch my parts? Assemble 'Move forward' block and press Start. \",\n    \"maze_content_2\": \"Very good! I'm feeling much better! I see my part over there but I might get electrocuted if I don't be careful. Let's use 'jump over obstacle' block to get to the part.\",\n    \"maze_content_3\": \"Great! My part is right over there. The path is a bit twisted but I can get there using 'rotate' blocks. You'll help me, right?\",\n    \"maze_content_4\": \"Nice! I can almost move freely now. Let's get the part using 'rotate' and 'jump' blocks.\",\n    \"maze_content_5\": \"Wow! Two parts! Let's get them both so I can restore my health faster.\",\n    \"maze_content_6\": \"Thanks to you I'm feeling much better! I'm able to get better with those parts. You'll help me, right?\",\n    \"maze_content_7\": \"I'm feeling great! I can repeat the same task without trouble now. Oh! Do you see the robot over there? I think she might need help. Let's go help her out. Bring me to her by changing the number of 'repeat's\",\n    \"maze_content_8\": \"Excellent! I was able to rescue my pal! It looks like another one of my friends need help. Be careful there are beehives. Be sure to jump over the beehives! Can you do it? Help me reach her using the 'repeat' block. \",\n    \"maze_content_9\": \"Instead of repeating a task for set number of times, I can repeat until I reach my robot pal instead! Help me save my friend!\",\n    \"maze_content_10\": \"Now we can use the 'if' block. Help me use the 'if' block to turn at right timing.\",\n    \"maze_content_11\": \"Let's try it again! Let me know when to turn left.\",\n    \"maze_content_12\": \"There are beehives all over the place. Tell me when to jump!\",\n    \"maze_content_13\": \"My friends need help! Let's go help them!\",\n    \"maze_content_14\": \"More friends need rescue! Let's first go around the small square and repeat it to rescue all my friends.\",\n    \"maze_content_15\": \"Now I can memorize blocks that are used repeatedly. Promise blocks are the ones that I was able to memorize. I'm a bit tired from moving so much. Help me refill my battery using the Promise feature!\",\n    \"maze_content_16\": \"Great! Tell me which blocks are used often and put them under the Promise block!\",\n    \"maze_content_17\": \"Nice! Use Promise blocks to help me get my battery. Make sure to insert 'Jump' blocks in the Promise block.\",\n    \"maze_content_18\": \"The path looks complex! We can get through this if we turn left and right at the right time.\",\n    \"maze_content_19\": \"The 'Promise' if already set for us! However, we can't use the Promise blocks as is. I'll need to use the Promise blocks at the right timing to get the battery.\",\n    \"maze_content_20\": \"Excellent! You've done great so far! After the final battery, I won't need to charge any more. So help me get the last battery using the Promise so I can live forever free!\",\n    \"maze_content_21\": \"안녕? 나는 엔트리 봇이야. 지금 많은 친구들이 내 도움을 필요로 하고 있어. 반복하기를 이용해서 친구들을 도울수 있게 데려다 줘!\",\n    \"maze_content_22\": \"고마워! 이번에는 벌집을 뛰어넘어서 친구를 구하러 갈 수 있게 도와줘!\",\n    \"maze_content_23\": \"좋아! 이번에는 친구 로봇한테 갈 때까지 반복하기를 이용해서 친구를 도울 수 있게 도와줘!\",\n    \"maze_content_24\": \"안녕! 나는 엔트리 봇이야. 지금 나는 너무 오래 움직여서 배터리를 채워야 해. 약속 불러오기를 써서 배터리를 채울 수 있도록 도와줘!\",\n    \"maze_content_25\": \"멋져! 이번에는 여러 약속을 불러와서 배터리가 있는 곳까지 가보자!\",\n    \"maze_content_26\": \"좋아! 이제 약속할 블록을 나한테 가르쳐줘! 약속하기 블록 안에 자주 쓰일 블록을 넣으면 돼!\",\n    \"maze_content_27\": \"지금은 미리 약속이 정해져 있어. 그런데, 약속을 쓰기위해서는 내가 갈 방향을 보고 약속을 사용해야해. 도와줄거지?\",\n    \"maze_content_28\": \"드디어 마지막이야! 약속을 이용하여 마지막 배터리를 얻을 수 있게 도와줘!\",\n    \"ai_content_1\": \"Hi! I'm Entrybot. I just completed the space exploration mission and I need to return to Earth but it's not easy because of the asteroids. Could you help me return home? I have radars on top, front and back of the spaceship to detect how far an obstacle exists. It'll help you make smart decisions.\",\n    \"ai_content_2\": \"Thank you! I was able to avoid the asteroids without trouble. There are more asteroids this time. Let's try avoiding them!\",\n    \"ai_content_3\": \"Great! I was able to safely avoid the asteroids! There are more asteroids now! Don't worry though! I have the 'repeat' block. Place blocks in the 'repeat' block so we can get to the destination!\",\n    \"ai_content_4\": \"Excellent! It's so much more easier to avoid the asteroids using the repeat blocks! However, it's tiring driving the spaceship at all times! I can use the radar to sense what's coming. Help avoid the asteroids using the radar.\",\n    \"ai_content_5\": \"Nice! I'm so glad we've come this far. The radar will tell how far an object exists. Let's use the radar to avoid the asteroids! Move forward until we come close to an asteroid then avoid!\",\n    \"ai_content_6\": \"Great job! You're using radar to avoid tha asteroids. Use multiple radars to avoid the asteroids.\",\n    \"ai_content_7\": \"We're getting close to Earth! I want to go in a safer path if possible. It must be safer to move farther from the asteroids, right? Compare the distance to the obstacle using the radar on the top and bottom of the spaceship to move to a safer direction.\",\n    \"ai_content_8\": \"Excellent! We're safely cruising through space. Oh! What is that? That's looks like my special energy! Let's collect the special energy on our way!\",\n    \"ai_content_9\": \"Very good! We're almost there. The path is filled with asteroid. But don’t worry! We can get rid of the obstacles using the special item.\",\n    \"ai_content_10\": \"Good! I can see Earth! But now it's impossible to see the asteroids ahead! I'm not worried though. We can avoid the asteroids with more caution. Let's go home!\",\n    \"maze_hints_title_1\": \"How to start\",\n    \"maze_hints_content_1\": \"How do I move Entrybot?\",\n    \"maze_hints_detail_1\": \"1. Drag the block you want to use and place it under 'When Run'<br>2. Once finished, click 'Run'<br>3. I will follow the block instructions step by step, reading them from top to bottom\",\n    \"maze_hints_title_2\": \"Jumping over obstacles\",\n    \"maze_hints_content_2\": \"What do I do when I come across an obstacle?\",\n    \"maze_hints_detail_2\": \"On your pathway, you might come across obstacles.<br>Use 'jump over' block to jump over the obstacle. \",\n    \"maze_hints_title_3\": \"Repeat block(1)\",\n    \"maze_hints_content_3\": \"How do I use repeat (3) times block?\",\n    \"maze_hints_detail_3\": \"If you want to repeat an action multiple times, use 'repeat ~times' block. <br>Place the blocks you want to repeat within the 'repeat ~times' block and input how many times to repeat.\",\n    \"maze_hints_title_4\": \"Repeat block(2)\",\n    \"maze_hints_content_4\": \"How do I use 'repeat until ~' block?\",\n    \"maze_hints_detail_4\": \"Use 'repeat until~do' block to set until when an action should be performed. <br>Place the blocks you want to repeat within 'repeat until~' block.<br>Then once met with {image}, repeat will stop.\",\n    \"maze_hints_title_5\": \"If block\",\n    \"maze_hints_content_5\": \"How do I use 'if~' block?\",\n    \"maze_hints_detail_5\": \"Using 'If {image}' block, you can designate what action should follow when met with {image}.<br>Blocks within the 'If {image}' will only execute when met with {image}.\",\n    \"maze_hints_title_6\": \"Repeat block(3)\",\n    \"maze_hints_content_6\": \"How does 'Until met with all ~' block work?\",\n    \"maze_hints_detail_6\": \"Repeat blocks within 'Until met with all ~' block until met with all {tile}.<br> Once met with all {tile} repeat will stop.\",\n    \"maze_hints_title_7\": \"Special Hint\",\n    \"maze_hints_content_7\": \"It's too difficult. Help!\",\n    \"maze_hints_detail_7\": \"Look at the path that I should travel. See the 4 small squares?<br>First create blocks that will take me around the square and repeat.\",\n    \"maze_hints_title_8\": \"Function\",\n    \"maze_hints_content_8\": \"What is 'Functions/ Call Functions'? How do I use them?\",\n    \"maze_hints_detail_8\": \"Put the most often used sets of blocks under 'Function'. <br>Once you create functions, use 'Call Function' to use it as often as needed.\",\n    \"ai_hints_title_1_1\": \"Goal of the game\",\n    \"ai_hints_content_1_1\": \"Avoid asteroids and help me get to Earth\",\n    \"ai_hints_detail_1_1\": \"Avoid asteroids and help me get to Earth\",\n    \"ai_hints_title_1_2\": \"Instructions\",\n    \"ai_hints_content_1_2\": \"How do I begin?\",\n    \"ai_hints_detail_1_2\": \"1. Drag out blocks from the block box and connect is with the 'when run' block<br>2. Once finished assembling blocks, click 'Run'<br>3. I'll move according to your block instructions.\",\n    \"ai_hints_title_1_3\": \"To move\",\n    \"ai_hints_content_1_3\": \"How do I move the entrybot?\",\n    \"ai_hints_detail_1_3\": \"I can move up, forward or below.<br>When creating instructions, make sure I avoid the asteroids.<br>If you send me out of the screen, I can be lost in space forever! So be careful.\",\n    \"ai_hints_title_2_1\": \"Goal of the game\",\n    \"ai_hints_content_2_1\": \"Use repeat blocks to avoid the asteroids.\",\n    \"ai_hints_detail_2_1\": \"Use repeat blocks to avoid the asteroids.\",\n    \"ai_hints_title_2_2\": \"Repeat block\",\n    \"ai_hints_content_2_2\": \"What is a repeat block?\",\n    \"ai_hints_detail_2_2\": \"Geez! It's a long way home so putting blocks together one by one is too tiresome. Let's try using the repeat block.<br>Once you group the blocks under the repeat block, you can shorten the length of the blocks!\",\n    \"ai_hints_content_3_1\": \"Help me avoid the asteroids using the 'if' block\",\n    \"ai_hints_title_3_2\": \"if block(1)\",\n    \"ai_hints_content_3_2\": \"How does 'if ~' block work? \",\n    \"ai_hints_detail_3_2\": \"Using 'if~ in front/ else' block can help me check if there are asteroids in front of me and help me avoid them.<br>If there's an asteroid in front of me, then blocks under 'if' will execute or if there isn't an asteroid, the blocks under 'else' will execute.<br>Tell me which way to go depending on whether there's an asteroid to avoid or not.\",\n    \"ai_hints_content_4_1\": \"Learn to use the radar to avoid the asteroids.\",\n    \"ai_hints_detail_4_1\": \"Learn to use the radar to avoid the asteroids.\",\n    \"ai_hints_title_4_2\": \"radar(1)\",\n    \"ai_hints_content_4_2\": \"What is a radar and how can I use it?\",\n    \"ai_hints_detail_4_2\": \"Radar tells me how far an object exists from where I am located. <br>If there is an object in front of me, the front radar will show '1'.<br>Also, radar can become a powerful tool when used with 'if &lt;true&gt;/else' block.<br>For example, when the distance to an object in front of me shows value greater than 1, then I am able to move forward safely.<br> However, if not, then I can go above or under to avoid it.\",\n    \"ai_hints_title_4_3\": \"if block(2)\",\n    \"ai_hints_content_4_3\": \"How do I use 'if <true>' block?\",\n    \"ai_hints_detail_4_3\": \"if &lt;true&gt; block/ else' block executes blocks under 'if' when condition is met and executes blocks under 'else' when condition is not met.<br>Think about how you want to move at different situations and create a condition within &lt;true&gt; block.<br>Remember that when condition is met and blocks under 'if' are executed, then the blocks under 'else' will be ignored.\",\n    \"ai_hints_content_5_1\": \"Use the radar to help me avoid the asteroids.\",\n    \"ai_hints_detail_5_1\": \"Use the radar to help me avoid the asteroids.\",\n    \"ai_hints_title_5_2\": \"if block(3)\",\n    \"ai_hints_content_5_2\": \"How does nested if blocks work?\",\n    \"ai_hints_detail_5_2\": \"I can nest 'if ~/else' block within 'if ~/else' block. This will help me make smart decisions in various situations.<br>For example, I can act according to whether an asteroid is in my path or not, then when I'm met with and asteroid, I can decide whether to go under or above.\",\n    \"ai_hints_title_6_1\": \"Radar(2)\",\n    \"ai_hints_content_6_1\": \"How do I compare the values given by radar above and radar below?\",\n    \"ai_hints_detail_6_1\": \"([above]radar) block shows distance to an object above.<br>You can use this block to check which asteroid above or below exist further away.<br>When deciding which way to avoid the asteroid, it'll be a smarter move to go in the direction where the asteroid is further away.\",\n    \"ai_hints_content_7_1\": \"Use the item to avoid the asteroids.\",\n    \"ai_hints_detail_7_1\": \"Use the item to avoid the asteroids.\",\n    \"ai_hints_title_7_2\": \"Checking object name\",\n    \"ai_hints_content_7_2\": \"What can I do by checking the object name in front of me?\",\n    \"ai_hints_detail_7_2\": \"To gain a special item, you need to check where the item is located.<br>Use 'object [above] is [item]' block.<br>By using this block, you can figure out where the item is located and move towards it.\",\n    \"ai_hints_content_8_1\": \"Use the item to help me avoid the asteroids.\",\n    \"ai_hints_detail_8_1\": \"Use the item to help me avoid the asteroids.\",\n    \"ai_hints_title_8_2\": \"Item\",\n    \"ai_hints_content_8_2\": \"How do I gain special item and use it?\",\n    \"ai_hints_detail_8_2\": \"Even though you succeed in avoiding the asteroids, when the pathway is lined with asteroids, there is no way to avoid them. In this case, use the 'use item' block.<br>It will get rid of all blocks in front.<br>However, you can only use this block when you've gained the item by passing through the item.\",\n    \"ai_hints_content_9_1\": \"Use all your skills and knowledge to go as far as you can.\",\n    \"ai_hints_detail_9_1\": \"Use all your skills and knowledge to go as far as you can.\",\n    \"ai_hints_title_9_2\": \"and\",\n    \"ai_hints_content_9_2\": \"How do I use the 'and' block?\",\n    \"ai_hints_detail_9_2\": \"and' block can fit in many conditions. When all conditions in the 'and' block is met, then the blocks will be executed. If one of them is false, the whole 'and' statement will be false and the blocks will not be executed.\",\n    \"maze_text_goal_1\": \"Use move();  command to move me to the part box!\",\n    \"maze_text_goal_2\": \"Use jump();  command to avoid obstacles.\",\n    \"maze_text_goal_3\": \"Use left(); right(); command to take me to my parts.\",\n    \"maze_text_goal_4\": \"Use various commands to take me to my parts.\",\n    \"maze_text_goal_5\": \"Move me so I can collect both of my part boxes.\",\n    \"maze_text_goal_6\": \"Move me so I can collect both of my part boxes.\",\n    \"maze_text_goal_7\": \"Use for command to take me to my friend!\",\n    \"maze_text_goal_8\": \"Use for command and avoid obstacles to take me to my friend!\",\n    \"maze_text_goal_9\": \"Use while command to take me to my friend.\",\n    \"maze_text_goal_10\": \"Use if and while commands to take me to all my friends.\",\n    \"maze_text_goal_11\": \"Use if and while commands to take me to all my friends.\",\n    \"maze_text_goal_12\": \"Use if and while commands to take me to all my friends.\",\n    \"maze_text_goal_13\": \"Call function to take me to my battery\",\n    \"maze_text_goal_14\": \"Call function to take me to my battery\",\n    \"maze_text_goal_15\": \"Insert commands within function. Then call the function to take me to my battery\",\n    \"maze_text_goal_16\": \"Insert commands under a function. Then call the function to move me to the battery!\",\n    \"maze_text_goal_17\": \"Insert commands under a function. Then call the function to move me to the battery!\",\n    \"maze_text_goal_18\": \"Insert commands under a function. Then call the function to move me to the battery!\",\n    \"maze_text_goal_19\": \"Insert commands under a function. Then call the function to move me to the battery!\",\n    \"maze_text_goal_20\": \"Call the function and mix it with other commands and take me to my battery.\",\n    \"maze_attack_range\": \"Attack range\",\n    \"maze_attack\": \"Attack\",\n    \"maze_attack_both_sides\": \"Attack both sides\",\n    \"above_radar\": \"above radar\",\n    \"above_radar_text_mode\": \"radar_up\",\n    \"bottom_radar\": \"bottom radar\",\n    \"bottom_radar_text_mode\": \"radar_down\",\n    \"front_radar\": \"front radar\",\n    \"front_radar_text_mode\": \"radar_right\",\n    \"above_object\": \"object above\",\n    \"above_object_text_mode\": \"object_up\",\n    \"front_object\": \"object in front\",\n    \"front_object_text_mode\": \"object_right\",\n    \"below_object\": \"object below\",\n    \"below_object_text_mode\": \"object_down\",\n    \"destination\": \"destination\",\n    \"asteroids\": \"asteroids\",\n    \"item\": \"item\",\n    \"wall\": \"wall\",\n    \"destination_text_mode\": \"destination\",\n    \"asteroids_text_mode\": \"stone\",\n    \"item_text_mode\": \"item\",\n    \"wall_text_mode\": \"wall\",\n    \"buy_now\": \"Buy now\",\n    \"goals\": \"Goal\",\n    \"instructions\": \"Instructions\",\n    \"object_info\": \"Object info\",\n    \"entry_basic_mission\": \"Entry basic mission\",\n    \"entry_application_mission\": \"Entry application mission\",\n    \"maze_move_forward\": \"move one forward\",\n    \"maze_when_run\": \"khi chạy\",\n    \"maze_turn_left\": \"turn left\",\n    \"maze_turn_right\": \"turn right\",\n    \"maze_repeat_times_1\": \"repeat\",\n    \"maze_repeat_times_2\": \"times\",\n    \"maze_repeat_until_1\": \"repeat until\",\n    \"maze_repeat_until_2\": \"\",\n    \"maze_call_function\": \"call function\",\n    \"maze_function\": \"function\",\n    \"maze_repeat_until_all_1\": \"repeat until all of\",\n    \"maze_repeat_until_all_2\": \"\",\n    \"command_guide\": \"Command guide\",\n    \"ai_success_msg_1\": \"Thanks to you I've safely arrived home!\",\n    \"ai_success_msg_2\": \"Phew! I was able to travel \",\n    \"ai_success_msg_3\": \"distance  enough to send a rescue signal to Earth! The rescue crew is on its way! Thank you!\",\n    \"ai_success_msg_4\": \"Great! You succeeded using \",\n    \"ai_cause_msg_1\": \"Oh no. Tell me which way to go.\",\n    \"ai_cause_msg_2\": \"Yikes! That was close! Let's try again.\",\n    \"ai_cause_msg_3\": \"Yikes! I might get lost in space if I go off the path. Let's try again.\",\n    \"ai_cause_msg_4\": \"It's too complicated. Try this block to move.\",\n    \"ai_move_forward\": \"move forward\",\n    \"ai_move_above\": \"go above\",\n    \"ai_move_under\": \"go under\",\n    \"ai_repeat_until_dest\": \"repeat until destination\",\n    \"ai_if_front_1\": \"if\",\n    \"ai_if_front_2\": \"in front\",\n    \"ai_else\": \"else\",\n    \"ai_if_1\": \"if\",\n    \"ai_if_2\": \"\",\n    \"ai_use_item\": \"use item\",\n    \"ai_radar\": \"radar\",\n    \"ai_above\": \"above\",\n    \"ai_front\": \"front\",\n    \"ai_under\": \"under\",\n    \"ai_object_is_1\": \"is\",\n    \"ai_object_is_2\": \"object\",\n    \"challengeMission\": \"back\",\n    \"nextMission\": \"next\",\n    \"withTeacher\": \"Advisory teachers\",\n    \"host\": \"Host\",\n    \"support\": \"Support\",\n    \"subjectivity\": \"Subjectivity\",\n    \"learnMore\": \"Learn more \",\n    \"ai_object_is_3\": \"?\",\n    \"stage_is_not_available\": \"The stage isn't available yet. Please enter the stages in the given order.\",\n    \"progress_not_saved\": \"Your progress will not be saved.\",\n    \"want_refresh\": \"Do you still want to refresh the page?\",\n    \"monthly_entry_grade\": \"Elementary 3rd - Middle school 3rd grade\",\n    \"monthly_entry_contents\": \"Learn to program with Monthly Entry. This monthly digest provides project tutorials, tips and tricks and fun comics. \",\n    \"monthly_entry_etc1\": \"*The Monthly Entry project templates are provided in the main page's recommended course\",\n    \"monthly_entry_etc2\": \"* Monthly Entry is published during school semesters only\",\n    \"group_make_lecture_1\": \"There are no lessons to show.\",\n    \"group_make_lecture_2\": \" Create lessons for your class from \",\n    \"group_make_lecture_3\": \"'Create > Create lessons'\",\n    \"group_make_lecture_4\": \"Create a lessons\",\n    \"group_add_lecture_1\": \"Favorite Lesson does not exist.\",\n    \"group_add_lecture_2\": \"'학습하기>오픈 강의> 강의'에서 우리반 학습내용에\",\n    \"group_add_lecture_3\": \"추가하고 싶은 강의를 관심강의로 등록해 주세요.\",\n    \"group_add_lecture_4\": \"See Lesson\",\n    \"group_make_course_1\": \"My courseware is not exist.\",\n    \"group_make_course_2\": \"Create courseware for your class from\",\n    \"group_make_course_3\": \"'Create > Create lessons > Create Courseware'\",\n    \"group_make_course_4\": \"Create courseware\",\n    \"group_add_course_1\": \"Favorite Courseware does not exist.\",\n    \"group_add_course_2\": \"Favorite lessons you want to add as course assignment from\",\n    \"group_add_course_3\": \"'Learn > Open Lessons > Courseware\",\n    \"group_add_course_4\": \"Browse courseware\",\n    \"hw_main_title\": \"Download Program\",\n    \"datablock_contest_title\": \"Data Analysis Block\",\n    \"datablock_content_head\": \"Process and Represent the Data\",\n    \"datablock_content_body1\": \"Find meaning by charting various data in your life\",\n    \"datablock_content_body2\": \"and solve real-life problems with it!\",\n    \"campaign_contest_title\": \"Let's make a beautiful internet world\",\n    \"campaign_content_head\": \"Entry Project Contest\",\n    \"campaign_content_body1\": \"Create an originative project about 'internet ethics'\",\n    \"campaign_content_body2\": \"and apply for the contest!\",\n    \"campaign_content_button\": \"View details\",\n    \"code_management_1\": \"Entry campaign #1 How to manage code\",\n    \"code_management_2\": \"My Storage and Memo\",\n    \"code_management_3\": \"Code management secret using my storage and memo!\",\n    \"code_management_4\": \"Learn how to make your project better and share it easily.\",\n    \"code_management_5\": \"View Campaigns\",\n    \"shcoolbook_study_1\": \"Learn the contents of the textbook in entry.\",\n    \"shcoolbook_study_2\": \"Learning Textbook\",\n    \"shcoolbook_study_3\": \"Teachers can teach in the classroom\",\n    \"shcoolbook_study_4\": \"and students can review at home!\",\n    \"shcoolbook_study_5\": \"Learn now\",\n    \"main_learn_1\": \"If you are new to Entry\",\n    \"main_learn_2\": \"Learn about Entry\",\n    \"main_learn_3\": \"Watch the video to learn about the various functions of Entry,\",\n    \"main_learn_4\": \"create and share your project!\",\n    \"main_learn_5\": \"Watch the video\",\n    \"hw_desc_wrapper\": \"Install the Upgraded \\nEntry Hardware Connection Program\\nand Offline Editor\",\n    \"hw_downolad_link\": \"Download Hardware Connection Program\",\n    \"save_as_image_all\": \"Save code as image\",\n    \"save_as_image\": \"Save as image\",\n    \"maze_perfect_success\": \"Awesome! That is perfect!\",\n    \"maze_success_many_block_1\": \"좋아\",\n    \"maze_fail_obstacle_remain\": \"Get rid of all obstacles to keep your friends from getting hurt.\",\n    \"maze_fail_item_remain\": \"Collect all the Minerals to save Princess Sally.\",\n    \"maple_fail_item_remain\": \"I can't use my strength because I didn’t take all the food.<br />Help me to take all the food.\",\n    \"maze_fail_not_found_destory_object\": \"Don't waste your power on an empty space!\",\n    \"maze_fail_not_found_destory_monster\": \"Don't attack an empty space!\",\n    \"maple_fail_not_found_destory_monster\": \"You should use the attack blocks only when there are monsters!\",\n    \"maze_fail_more_move\": \"You have to move to the destination a little bit more!\",\n    \"maze_fail_wall_crash\": \"Ow! You can't go there!\",\n    \"maze_fail_contact_brick\": \"Ouch... you ran into something!\",\n    \"maze_fail_contact_iron1\": \"Ow! I hit an obstacle\",\n    \"maze_fail_contact_iron2\": \"Ow! I was hurt because an obstacle fell on me. Move before an obstacle falls down.\",\n    \"maze_fail_fall_hole\": \"I fell into a trap...\",\n    \"maze_fail_hit_unit\": \"몬스터에게 당해버렸어! 위험한 몬스터를 물리치기 위해 하트 날리기 블록을 사용해줘!\",\n    \"maze_fail_hit_unit2\": \"Ow, I was attacked by a monster! You have to attack from two cells away!\",\n    \"maze_fail_hit_unit_by_mushroom\": \"The Orange Mushroom got me!<br />Use the Attack <img src='/img/assets/maze/icon/mushroom.png' /> block to defeat the bad monsters!\",\n    \"maze_fail_hit_unit_by_lupin\": \"I got hit by Lupin! <br />Use the Attack <img src='/img/assets/maze/icon/lupin.png' /> block two spaces away to defeat the bad monster!\",\n    \"maze_fail_elnath_fail\": \"Oww! A bad monster attacked me.<br />Defeat the bad monsters to keep them from reaching me!\",\n    \"maze_fail_pepe\": \"\",\n    \"maze_fail_yeti\": \"That monster is so strong that you can't defeat it with the Attack <img width='24px' src='/img/assets/week/blocks/yeti.png'/> block.<br />Let's use the Attack <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> block.\",\n    \"maze_fail_peti\": \"If you use the Attack <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> block to attack that monster, you can't defeat the strong monsters <img width='24px' src='/img/assets/week/blocks/bigYeti.png'/> when they spawn.<br />Let's use the Attack <img width='24px' src='/img/assets/week/blocks/yeti.png'/> block.\",\n    \"maze_fail_both_side\": \"You should only use the Attack on both sides if there are monsters on both sides! \",\n    \"maze_wrong_attack_obstacle\": \"You can't use the Attack <img src='/img/assets/maze/icon/lupin.png' /> block here.<br />Let's use the Attack <img src='/img/assets/maze/icon/mushroom.png' /> block for Orange Mushrooms.\",\n    \"maze_fail_contact_spider\": \"You're caught on a cobweb and can't move...\",\n    \"maze_success_perfect\": \"Awesome! That is perfect!\",\n    \"maze_success_block_excess\": \"Great! You succeeded using %1 blocks! <br> But you can actually get there by only using %2 blocks! How about another go at it?\",\n    \"maze_success_not_essential\": \"Great! You succeeded using %1 blocks! <br>But using this block makes it easier to solve. How about another go at it?\",\n    \"maze_success_final_perfect_basic\": \"Okay, we found where Princess Sally is! Now you can save Princess Sally!\",\n    \"maze_success_final_block_excess_basic\": \"Great! We found where Princess Sally is! Now you can save Princess Sally! You used %1 blocks, but you can actually succeed by only using %2 blocks! Wanna try again?\",\n    \"maze_success_final_perfect_advanced\": \"You've reached the place where Princess Sally is! Now defeat the villain Mephisto and save Sally!\",\n    \"maze_success_final_block_excess_advanced\": \"You've reached the place where Princess Sally is! Now defeat the villain Mephisto and save Sally! You used %1 blocks, but you can actually succeed by only using %2 blocks! Wanna try again?\",\n    \"maze_success_final_distance\": \"Great! We finally saved Princess Sally safe and sound. Thank you so much for helping!<br/> You moved %1 cells. Wanna try again and aim for 60 cells?\",\n    \"maze_success_final_perfect_ai\": \"There you go! We finally saved Princess Sally safe and sound. Thank you so much for helping!\",\n    \"maple_success_perfect\": \"Great! That was perfect!\",\n    \"maple_success_block_excess\": \"Great! You’ve succeeded using %1 blocks!<br />But there is a way to succeed with %2 blocks. Why don’t you try again?\",\n    \"maple_success_not_essential\": \"Great! You’ve succeeded using %1 blocks!<br />But using this block will make it easier. Why don't you try again?\",\n    \"maple_success_final_perfect_henesys\": \"Awesome! You’ve completed the Henesys Adventure.\",\n    \"maple_success_final_perfect_excess_henesys\": \"Awesome! You’ve completed the Henesys Adventure.<br />But there is a way to succeed with %2 blocks. Would you like to try again?\",\n    \"maple_success_final_not_essential_henesys\": \"Awesome! You’ve completed the Henesys Adventure.<br />But using this block will make it easier. Would you like to try again?\",\n    \"maple_success_final_perfect_ellinia\": \"Wow! That was a really fun adventure!<br />You're going to come back for another adventure, right?\",\n    \"maple_success_final_perfect_excess_ellinia\": \"Wow! That was a really fun adventure!<br />But there is a way to succeed with %2 blocks. Would you like to try again?\",\n    \"maple_success_final_not_essential_ellinia\": \"Wow! That was a really fun adventure!<br />But using this block will make it easier. Would you like to try again?\",\n    \"maple_fail_fall_hole\": \"Oww! You’ve fallen down!<br/>Let's skip using the Jump block.\",\n    \"maple_fail_ladder_fall_hole\": \"Oww! You’ve fallen down!<br />Let's go the other way using the Climb ladder block.\",\n    \"maple_fail_more_move\": \"To succeed, we have to move a little bit further to the destination!\",\n    \"maple_fail_not_found_ladder\": \"Oh, there's no ladder to climb here.<br />You should only use the Climb ladder block where there is a ladder.\",\n    \"maple_fail_not_found_meat\": \"Oh, there's no food to take here.<br />You should only use Take food block where there is food.\",\n    \"maple_cert_input_title\": \"What name do you want in the certificate?\",\n    \"maze_distance1\": \"distance 1\",\n    \"maze_distance2\": \"distance 2\",\n    \"maze_distance3\": \"distance 3\",\n    \"ev3\": \"EV3\",\n    \"roborobo_roduino\": \"Roduino\",\n    \"roborobo_schoolkit\": \"School Kit\",\n    \"smartboard\": \"Sciencebox Codingboard\",\n    \"smartboardbt\": \"Sciencebox Codingboard(Bluetooth)\",\n    \"codestar\": \"Codestar\",\n    \"cobl\": \"Cobl\",\n    \"cobl_bt\": \"Cobl BT\",\n    \"block_coding\": \"Block Coding\",\n    \"python_coding\": \"Entry Python\",\n    \"dadublock\": \"DaduBlock\",\n    \"dadublock_car\": \"DaduBlock Car\",\n    \"blacksmith\": \"Blacksmith Board\",\n    \"course_submit_homework\": \"Submit\",\n    \"course_done_study\": \"Complete\",\n    \"course_show_list\": \"List\",\n    \"modi\": \"MODI\",\n    \"chocopi\": \"ChocoPi\",\n    \"coconut\": \"coconut\",\n    \"jdkit\": \"JDKit\",\n    \"practical_course\": \"Textbook\",\n    \"entry_user_policy\": \"Entry usage policy\",\n    \"entry_scholarship_title\": \"Entry scholarly data\",\n    \"entry_scholarship_content\": \"Entry collaborates with researchers to strengthen learning effectiveness. Check out our data.\",\n    \"entry_scholarship_content_sub\": \"*We provide data which is saved in the form of a sequence of processes by users participating in the Online coding party to assist in study and analysis.\",\n    \"entry_scholarship_download\": \"Data download\",\n    \"codingparty_2016_title\": \"2016 Online coding party\",\n    \"codingparty_2016_content\": \"We provide user's active log, who played a coding mission, with whether he/she has succeeded or not, and user age, gender\",\n    \"codingparty_2017_title\": \"2017 Online coding party\",\n    \"scholarship_go_mission\": \"Coding mission\",\n    \"scholarship_guide\": \"Guide\",\n    \"scholarship_see_guide\": \"Guide\",\n    \"scholarship_guide_desc\": \"It's a guide for how to read and use data.\",\n    \"scholarship_example\": \"Example\",\n    \"scholarship_example_desc\": \"Check out our paper by using scholarly data.\",\n    \"scholarship_see_example\": \"Download\",\n    \"altino\": \"Altino\",\n    \"private_project\": \"This is a private project\",\n    \"learn_programming_entry_mission\": \"Solving missions with EntryBot\",\n    \"learn_programming_line_mission\": \"Saving Sally with LINE Rangers\",\n    \"learn_programming_choseok\": \"Making a game with Cho Seok, author of \\\"The Sound of Your Heart\\\"\",\n    \"learn_programming_maple\": \"Going to the Maple World with \\\"PINK BEAN\\\"\",\n    \"learn_programming_level_novice\": \"easy\",\n    \"learn_programming_level_inter\": \"normal\",\n    \"learn_programming_level_advanced\": \"hard\",\n    \"line_look_for\": \"Finding Sally\",\n    \"line_rangers_title_string\": \"Learning: Line Rangers\",\n    \"online_codingparty_certificate_string\": \"Online coding party\",\n    \"online_codingparty_line_title_string\": \"Line Rangers\",\n    \"line_look_for_desc_1\": \"Combine the power of the LINE Rangers and defeat the powerful villain Mephisto and save Sally!\",\n    \"line_save\": \"Saving Sally\",\n    \"line_save_desc_1\": \"Sally is trapped at Mephisto's base. Help the LINE Rangers get to Sally by avoiding obstacles!\",\n    \"line_escape\": \"Escaping with Sally\",\n    \"line_escape_desc_1\": \"Help Sally and LINE Rangers escape safely from the exploding Mephisto base!\",\n    \"solve_choseok\": \"rock-paper-scissors\",\n    \"solve_choseok_desc_1\": \"Help Cho Seok create a rock-paper-scissors game!\",\n    \"solve_henesys\": \"HENESYS\",\n    \"solve_ellinia\": \"ELLINIA\",\n    \"solve_elnath\": \"ELNATH\",\n    \"solve_henesys_desc_1\": \"Venture into the town, and help PINK BEAN to have enough food!\",\n    \"solve_ellinia_desc_1\": \"Venture into the forest, and fight against the bad monsters to save the good monsters!\",\n    \"solve_elnath_desc_1\": \"Passing through the snow mountain occupied by bad monsters, go find another portal to start a new adventure!\",\n    \"save_modified_shape\": \"Do you want to save the modified shape?\",\n    \"save_modified_table\": \"Do you want to save the modified table?\",\n    \"attach_file\": \"File\",\n    \"enter_discuss_title\": \"Please enter the title(in 40 characters or less)\",\n    \"enter_discuss_title_alert\": \"Please enter the title\",\n    \"discuss_upload_warn\": \"You can only upload less than 10MB in file size\",\n    \"discuss_list\": \"list\",\n    \"discuss_write_notice\": \"Select this post as a notice and show it first.\",\n    \"discuss_write_notice_open\": \"Select this post as a notice and show it first.\",\n    \"search_전체\": \"All\",\n    \"search_게임\": \"Game\",\n    \"search_애니메이션\": \"Animation\",\n    \"search_미디어아트\": \"Media Art\",\n    \"search_피지컬\": \"Physical\",\n    \"search_기타\": \"ETC\",\n    \"discuss_write_textarea_placeholer\": \"Entry community is a space we make together.\\nLet's make a fun community with consideration for each other.\",\n    \"discuss_write_textarea_placeholer_qna\": \"This community is for Q&A.\\nLet's make a fun community with consideration for each other!\",\n    \"discuss_write_textarea_placeholer_tips\": \"This community is for Tips&Tricks.\\nLet's make a fun community with consideration for each other!\",\n    \"discuss_write_textarea_placeholer_free\": \"This community is for Discussion.\\nLet's make a fun community with consideration for each other!\",\n    \"discuss_write_textarea_placeholer_report\": \"This community is for Suggestions.\\nLet's make a fun community with consideration for each other!\",\n    \"discuss_write_textarea_placeholer_contest2019\": \"※ 아래 양식으로 작성하여 제출해주세요.\\n\\n1. 학년 (예: 초등학교 5학년)\\n\\n2. 작품 URL (‘공유하기 > 작품 공유하기’에 작품을 공유한 다음, 작품 URL을 복사하여 적어주세요.)\\n\\n3. 작품 설명\\n\\n※ 공모전 수상자에게는 이메일이 발송될 예정입니다.\\n엔트리의 ‘내 정보 수정‘에 이메일 정보를 꼭 입력해주세요!\",\n    \"maze_road\": \"road\",\n    \"account_deletion\": \"Account deletion\",\n    \"bug_report_too_many_request\": \"Your report is being sent. Please try again later.\",\n    \"pinkbean_index_title\": \"Let’s head to the exciting Maple World with Pink Bean!\",\n    \"pinkbean_index_content\": \"Pink Bean, who couldn’t stand boredom, has ventured into Maple World.<br />Explore the exciting Maple World with Pink Bean and fill the adventure journal.<br />You can learn the software while passing through each step, and you can get a certificate after you complete the mission.\",\n    \"rangers_index_title\": \"Saving Sally with LINE Rangers!\",\n    \"rangers_index_content\": \"LINE Rangers are combined to defeat the powerful villain Mephisto and save Sally.<br />Be the hero by avoiding obstacles and saving Sally through the principle of software.<br />You can learn about software passing through each steps and get the licence<br />after finishing the mission.\",\n    \"rangers_replay_button\": \"Replay\",\n    \"rangers_start_button\": \"Start\",\n    \"lms_curriculum_intro\": \"\",\n    \"lms_curriculum_goal\": \"\",\n    \"lms_curriculum_prepare\": \"\",\n    \"lms_curriculum_study\": \"\",\n    \"lms_curriculum_summary\": \"\",\n    \"lms_curriculum_quiz\": \"\",\n    \"lms_curriculum_now_stage\": \"\",\n    \"bug_report_title\": \"Bug Report\",\n    \"bug_report_content\": \"Please tell us about errors or good suggestions that you find when you use Entry.\",\n    \"object_import_syntax_error\": \"Since the object has syntax error blocks, it cannot be loaded. Please convert into block mode to load the object.\",\n    \"choseok_top_wrapper_panel_title\": \"조석과 함께 가위바위보 게임을 만들어보세요!\",\n    \"choseok_top_wrapper_panel_des\": \"마음의 소리 웹툰이 코딩파티 미션으로 탄생했습니다. <br/>만화속 조석이 (가위바위보 게임)을 만들어가는 과정에 참여하여 미션에<br/>도전해 보세요.<br/>각 단계를 통과하면서 자연스럽게 소프트웨어를 배워볼 수 있고, 미션을 모두 마치면</br>인증서와 나만의 게임을 얻을 수 있습니다.<br/>\",\n    \"choseok_mission_statement1\": \"조석을 움직여보자\",\n    \"choseok_mission_statement2\": \"가위바위보를 시작해보자\",\n    \"choseok_mission_statement3\": \"가위바위보 승부를 가려보자\",\n    \"choseok_mission_statement4\": \"가위바위보 게임을 완성해보자\",\n    \"choseok_mission_statement5\": \"자유롭게 만들어보자\",\n    \"choseok_mission_statement_top1\": \"미션 1 : 조석을 움직이기\",\n    \"choseok_mission_statement_top2\": \"미션 2 : 가위바위보를 시작하기\",\n    \"choseok_mission_statement_top3\": \"미션 3 : 가위바위보 승패 만들기\",\n    \"choseok_mission_statement_top4\": \"미션 4 : 가위바위보 결과 보여주기\",\n    \"choseok_mission_statement_top5\": \"미션 5 : 자유롭게 만들어보기\",\n    \"advisory_title\": \"Entry Advisory Group\",\n    \"advisory_sub_title\": \"This is an advisory group including teachers and students who make Entry together.\",\n    \"data_table_column\": \"column\",\n    \"data_table_row\": \"row\",\n    \"data_table_provider\": \"provider\",\n    \"data_table_modifidate\": \"modify\",\n    \"draw_new_table_ques_1\": \"You can enter data and save to table.\",\n    \"draw_new_table_ques_2\": \"Do you want to move to enter data?\"\n};\nLang.Msgs = {\n    \"microbit_led_erase_all\": \"Reset\",\n    \"loading_plz_wait\": \"Now Loading. Please Wait\",\n    \"ai_utilize_audio_listening\": \"Listening\",\n    \"upload_error_title\": \"File rejected\",\n    \"upload_error_content\": \"Files not complying with the entry usage policy are excluded\",\n    \"monthly_intro_0\": \"Monthly entry is an SW training magazine designed to help teachers who are unfamiliar with SW.\",\n    \"monthly_intro_1\": \"Meet the Learning contents with fun learning cartoon!\",\n    \"monthly_title_0\": \"Taking a dog walk / Drawing diagram\",\n    \"monthly_title_1\": \"Create a video / Music player\",\n    \"monthly_title_2\": \"South Korea map puzzle / Cosmos animation\",\n    \"monthly_title_3\": \"Following fishes / Planets\",\n    \"monthly_title_4\": \"Harvesting potatoes / Strawberry milk\",\n    \"monthly_description_0\": \"Let's make the dog that moved by your keyboard, and paint drawing project using signal and coordinate.\",\n    \"monthly_description_1\": \"Let's make the photo-movie project and music player using variable.\",\n    \"monthly_description_2\": \"Let's make the puzzle game that made of 'while' statement, and animation project using clone and random.\",\n    \"monthly_description_3\": \"Let's make fish-art and solar system using loop, math calculation blocks.\",\n    \"monthly_description_4\": \"Let's make the potato-digging and strawberry milk project using signal, variable and math calculation blocks.\",\n    \"save_canvas_alert\": \"Currently saving.\",\n    \"feedback_too_many_post\": \"Message sending. Please try after 10 seconds.\",\n    \"feedback_duplicated\": \"It is already reported.\",\n    \"usable_object\": \"Usable Object\",\n    \"shared_varaible\": \"Shared Variable\",\n    \"invalid_url\": \"Video URL is invalid.\",\n    \"auth_only\": \"Authenticated users only\",\n    \"runtime_error\": \"lỗi thực hiện\",\n    \"to_be_continue\": \"Still not working\",\n    \"warn\": \"cảnh báo\",\n    \"error_occured\": \"Oops, something went wrong. Why don't you try again? If you see this more than once, please let us know by Proposal board!\",\n    \"error_forbidden\": \"Can not save because you are not signed in.\\nPlease make sure if you haven’t signed out in another tab.\\nIf you still can not save after sign in, please leave a message via ‘Suggestion’.\",\n    \"list_can_not_space\": \"tên danh sách không thể để trống\",\n    \"sign_can_not_space\": \"tên tín hiệu không thể để trống\",\n    \"variable_can_not_space\": \"Variable's name can't be space\",\n    \"training_top_title\": \"Programs\",\n    \"training_top_desc\": \"Introducing Professional Development Programs\",\n    \"training_main_title01\": \"Instructors for your Professional Development Seminar\",\n    \"training_target01\": \"For l Teachers\",\n    \"training_sub_title01\": \"“Give a Boost to your Classroom”\",\n    \"training_desc01\": \"Are you looking for instructors to train your teachers?\\nWe will match you with excellent instructors with knowledge and experience.\",\n    \"training_etc_ment01\": \"* Seminar are hosted and paid for by the requesting schools\",\n    \"training_main_title02\": \"Teacher Development Program for Lead Schools\",\n    \"training_target02\": \"For l Lead and Research Schools\",\n    \"training_sub_title02\": \"“Go, Share, and Connect”\",\n    \"training_desc02\": \"We randomly select schools from the Lead and Research schools and provide Development Seminars for free.\\nSeminars are taught by Go-to-Teacher Program teachers.\",\n    \"training_etc_ment02\": \"\",\n    \"training_main_title03\": \"Experienced Instructors for Parent and Student seminars\",\n    \"training_target03\": \"For l Parents, Students\",\n    \"training_sub_title03\": \"“Time to Explore Software Education”\",\n    \"training_desc03\": \"Need instructors to introduce coding to parents and students?\\nWe will match you with our instructors with knowledge and experience. \",\n    \"training_etc_ment03\": \"* Seminar are hosted and paid for by the requesting schools\",\n    \"training_apply\": \"Apply\",\n    \"training_ready\": \"Ready\",\n    \"new_version_title\": \"Install the latest version\",\n    \"new_version_text1\": \"Current Hardware Connection Program\",\n    \"new_version_text2\": \"is not the most updated version.\",\n    \"new_version_text3\": \"Please install the latest version.\",\n    \"new_version_text4\": \"\",\n    \"new_version_download\": \"Download<span class='download_icon'></span>\",\n    \"not_install_title\": \"Uninstalled\",\n    \"hw_download_text1\": \"Install to connect hardware.\",\n    \"hw_download_text2\": \"\",\n    \"hw_download_text3\": \"Hardware Connector Program is not installed.\",\n    \"hw_download_text4\": \"Please install the latest version.\",\n    \"hw_download_btn\": \"Download<span class='download_icon'></span>\",\n    \"not_support_browser\": \"Your browser is not supported.\",\n    \"quiz_complete1\": \"Quiz is finished\",\n    \"quiz_complete2\": \"You've got {1} correct out of {0} problems\",\n    \"quiz_incorrect\": \"Let's think again\",\n    \"quiz_correct\": \"That's the answer\",\n    \"hw_connection_success\": \"Hardware connection success\",\n    \"hw_connection_success_desc\": \"Double click the hardware icon to check sensor values\",\n    \"hw_connection_success_desc2\": \"Hardware connection is successful\",\n    \"hw_connection_termination_title\": \"Disconnected\",\n    \"hw_connection_termination_desc\": \"The device has been disconnected.\",\n    \"hw_connection_failed_title\": \"Connection Failed\",\n    \"hw_connection_failed_desc\": \"Please make sure that\\nthe device used in the project is connected.\",\n    \"ie_page_title\": \"This browser is not supported\",\n    \"ie_page_desc\": \"Entry is available in Internet Explorer 10 or higher or in Chrome browser.<br/>Please update the Windows or install a Chrome browser.<br/>Offline versions are available even though the internet is not connected. Get download now!\",\n    \"ie_page_chrome_download\": \"Chrome<br/>download\",\n    \"ie_page_windows_update\": \"Windows<br/>update\",\n    \"ie_page_offline_32bit_download\": \"Windows 32bit<br/>download\",\n    \"ie_page_offline_64bit_download\": \"Windows 64bit<br/>download\",\n    \"ie_page_offline_mac_download\": \"Mac<br/>download\",\n    \"cancel_deletion_your_account\": \"Do you want to cancel the deletion of your account?\",\n    \"account_deletion_canceled_complete\": \"Account deletion has been canceled.\",\n    \"journal_henesys_no1_title\": \"Henesys Adventure Journal No. 1\",\n    \"journal_henesys_no2_title\": \"Henesys Adventure Journal No. 2\",\n    \"journal_henesys_no1_content\": \"This is the first journal for Henesys. Today, I almost fell trying to jump on the way to the blacksmith’s house. He’s important in Henesys. Why did he make such a big hole in front of his yard? I don't think there’s anyone who can jump through these holes unless it's a great monster like me! let’s go to that restaurant. It’s supposed to be good!\",\n    \"journal_henesys_no2_content\": \"I really did eat too much. The meat in that restaurant was really delicious. How could it be so tender? But the bread next door wasn’t great. The chef seemed to be always playing around, saying he’s “learning how to cook better.” He should use that time to get some more practice. Now that I’ve filled my belly, time to start a full-scale adventure!\",\n    \"journal_ellinia_no1_title\": \"Ellinia Adventure Journal No. 1\",\n    \"journal_ellinia_no2_title\": \"Ellinia Adventure Journal No. 2\",\n    \"journal_ellinia_no1_content\": \"Phew, I sat on an Orange Mushroom without even knowing. I guess that’s a good reason to get mad... But piling on me was too much! They’re a scary bunch. No wonder the slimes had a hard time. No need to worry, though! Yours truly took care of it! Now that the slimes are my friends, I’m gonna continue the adventure into this gorgeous forest.\",\n    \"journal_ellinia_no2_content\": \"My adventurous friend, Royal Fairy, told me there are some scary rumors going on around Elnath. I wonder what that is? I’m supposed to play with my friends at home tonight, so I’ll ask then. I can’t wait!  But what should I wear ... I don’t think anything is going to fit because I got bigger... Well, I’m always cute, so no matter what I wear, everyone will love it!\",\n    \"journal_elnath_no1_title\": \"Elnath Adventure Journal No. 1\",\n    \"journal_elnath_no2_title\": \"Elnath Adventure Journal No. 2\",\n    \"journal_elnath_no1_content\": \"Oh, my gosh! So this is \\\"snow\\\" I heard so much about, huh? It's always spring where I live, so this is my first snow. I wasn't paying much attention because I was busy fighting the monsters, but now I see the whole world is so white and cold! I thought it’d be tasty, but it's flavorless. I wish I can bring some back, but there's no way. Oh, too bad.\",\n    \"journal_elnath_no2_content\": \"Eww, I accidentally ate coal dust! Those bad monsters! Least they could do is run away quietly, but they just had to spread coal all over. Thanks to them, my shiny, fluffy pink skin is getting dirtier. I need to get out of here and take a clean bath. Adventure is nice, but no self-respecting monster should walk around looking this dirty.\",\n    \"bug_report_alert_msg\": \"Thank you for the report.\",\n    \"version_update_msg1\": \"You can use the latest Entry Offline version(%1).\",\n    \"version_update_msg2\": \"You can use the latest Entry Hardware version(%1).\",\n    \"version_update_msg3\": \"Do you want to update now?\",\n    \"select_the_hardware\": \"Select the hardware<br />that you would use in the lesson.\",\n    \"select_hardware_button\": \"Select\",\n    \"select_the_expansion_block\": \"Select the expansion block that you would use in the lesson.\",\n    \"select_hardware_not_support_info\": \"Hardware blocks are not available for open classes.\",\n    \"select_hardware_not_support_info2\": \"Please wait a little bit.\",\n    \"select_expansion_block_button\": \"Select\",\n    \"expansion_weather_description\": \"It is a collection of blocks related to weather in Korea such as temperature, precipitation, and fine dust concentration.\",\n    \"expansion_festival_description\": \"It is a collection of blocks related to various events and festivals by local area.\",\n    \"expansion_translate_description\": \"It is a collection of blocks that can translate into other languages using the Papago.\",\n    \"expansion_behaviorConductDisaster_description\": \"It is a collection of blocks about behavior-guidelines that the public should follow when natural disasters occur. (Provided by MPSS)\",\n    \"expansion_behaviorConductLifeSafety_description\": \"It is a collection of blocks about basic behavior-guidelines that the public should follow for safty in life. (Provided by MPSS)\",\n    \"ai_utilize_tts_description\": \"It is a collection of blocks that can read text in a variety of voice using the Clova.\",\n    \"hardware_need_update_title\": \"Entry HW update\",\n    \"hardware_need_update_content\": \"Please update to the latest version,\\nif you are using below version.\\nEntry website only supported v1.9.0 or later.\\nPlease remove the web browser cache,\\nif any block doesn't appear after updating.\",\n    \"ai_utilize_audio_description\": \"It is a collection of blocks related to speech to text functionalities.\",\n    \"ai_utilize_video_description\": \"It is a collection of blocks that can recognize movement, direction and object to be shot by using camera.\"\n};\nLang.Users = {\n    \"auth_failed\": \"Authentication failed\",\n    \"birth_year\": \"Birth Year\",\n    \"birth_year_before_1990\": \"Before 1990s\",\n    \"edit_personal\": \"Chỉnh sửa cá nhân\",\n    \"email\": \"Email\",\n    \"email_desc\": \"Enter your Email address to receive newsletters\",\n    \"email_inuse\": \"E-mail address is already in-use\",\n    \"email_match\": \"Please enter a valid email\",\n    \"forgot_password\": \"Forgot your password?\",\n    \"job\": \"Job\",\n    \"language\": \"Language\",\n    \"name\": \"Full Name\",\n    \"name_desc\": \"Enter your name\",\n    \"name_not_empty\": \"You must enter your name\",\n    \"password\": \"Password\",\n    \"password_desc\": \"\",\n    \"password_invalid\": \"Invalid Password\",\n    \"password_long\": \"Password must be between 4-20 characters long\",\n    \"password_required\": \"Password can not be blank\",\n    \"project_list\": \"Danh sách dự án\",\n    \"regist\": \"Signup Complete\",\n    \"rememberme\": \"Remember me\",\n    \"repeat_password\": \"Repeat Password\",\n    \"repeat_password_desc\": \"Repeat Password\",\n    \"repeat_password_not_match\": \"Passwords do not match\",\n    \"sex\": \"Sex\",\n    \"signup_required_for_save\": \"Signin required for saving a project.\",\n    \"username\": \"Username\",\n    \"username_desc\": \"Enter your unique name for signin\",\n    \"username_inuse\": \"Username already taken\",\n    \"username_long\": \"Username must be between 4-20 characters long\",\n    \"username_unknown\": \"Unknown user\",\n    \"already_verified\": \"Already verified\",\n    \"email_address_unavailable\": \"The email address is unavailable.\",\n    \"email_address_invalid_for_idpw\": \"The email address is not available.\\n Please try 'Find ID or Password' again to resend. \",\n    \"email_address_invalid_for_certification\": \"The email address is not available.\\n Please verify your email again.\",\n    \"verification_complete\": \"Verification has been completed.\",\n    \"reset_password_mail_sent\": \"Email for password resetting has been sent. Please check your email.\",\n    \"email_not_verified\": \"This email is not verified. Please verify your email to click 'Verifying email' first.\",\n    \"verification_email_send_complete\": \"Verifying email has been sent. Please verify your email first.\",\n    \"email_send_failed\": \"Sending email was failed. Please try again.\",\n    \"email_not_exist\": \"This email does not exist.\",\n    \"not_valid_email\": \"Please enter a correct type of email.\"\n};\nLang.Workspace = {\n    \"picture_rotation\": \"xoay vòng\",\n    \"picture_size\": \"kích cỡ\",\n    \"thickness\": \"độ dày\",\n    \"follow\": \"Follow\",\n    \"SaveWithPicture\": \"You have a unsaved drawing. Do you want to save it?\",\n    \"RecursiveCallWarningTitle\": \"Limitation of function call\",\n    \"RecursiveCallWarningContent\": \"Too many functions were called at once. Please reduce the function calls.\",\n    \"SelectShape\": \"chuyển động\",\n    \"SelectCut\": \"đoạn bỏ\",\n    \"Pencil\": \"Cây bút\",\n    \"Line\": \"Hàng\",\n    \"Rectangle\": \"Hình chữ nhật\",\n    \"Ellipse\": \"hình bầu dục\",\n    \"Text\": \"Hộp văn bản\",\n    \"Fill\": \"Lấp đầy\",\n    \"Eraser\": \"Cục tẩy\",\n    \"Magnifier\": \"kiếng hiển vi\",\n    \"block_helper\": \"Khối giúp đỡ\",\n    \"new_project\": \"New Project\",\n    \"add_object\": \"thêm đối tượng\",\n    \"download_image_name\": \"entry block\",\n    \"all\": \"Tất cả\",\n    \"animal\": \"Animal\",\n    \"arduino_entry\": \"Program for connect to Arduino\",\n    \"arduino_program\": \"Arduino program\",\n    \"arduino_sample\": \"Sample code for Arduino\",\n    \"arduino_driver\": \"Driver for arduino\",\n    \"cannot_add_object\": \"Cannot add objects while running a project.\",\n    \"cannot_add_picture\": \"Cannot add picture while running a project.\",\n    \"cannot_add_sound\": \"Cannot add sound while running a project.\",\n    \"cannot_add_expansion_block\": \"Cannot add expansion block while running a project.\",\n    \"add_object_before_edit\": \"Add object firstly,<br>to edit the shape.\",\n    \"add_table_before_edit\": \"Add table.\",\n    \"cannot_edit_click_to_stop\": \"không thể sửa đổi đề án. <br>Nhấn n để dừng lại\",\n    \"cannot_open_private_project\": \"Can not load private project. Move to home.\",\n    \"cannot_save_running_project\": \"Can not save while running a project.\",\n    \"character_gen\": \"Make an avarta\",\n    \"check_runtime_error\": \"vui lòng kiểm tra khối được đánh dấu màu đỏ\",\n    \"check_browser_error\": \"This block is not compatible to IE/Safari\",\n    \"check_microphone_error\": \"There is no microphone connected to the computer\",\n    \"check_webcam_error\": \"There is no camera connected to the computer\",\n    \"context_download\": \"tải về máy tính\",\n    \"context_duplicate\": \"lặp lại\",\n    \"context_remove\": \"loại bỏ\",\n    \"context_rename\": \"đổi tên\",\n    \"coordinate\": \"Coord\",\n    \"create_function\": \"Create Function\",\n    \"direction\": \"hướng(°)\",\n    \"drawing\": \"Paint\",\n    \"enter_list_name\": \"\",\n    \"enter_name\": \"Enter a new name\",\n    \"enter_new_message\": \"Enter new message name.\",\n    \"enter_variable_name\": \"Enter the new variable name (less than 10)\",\n    \"family\": \"Family\",\n    \"fantasy\": \"Fantasy/etc\",\n    \"file_new\": \"Dự án mới\",\n    \"file_open\": \"Dự án mở\",\n    \"file_upload\": \"Tải lên dự án của tôi\",\n    \"file_upload_login_check_msg\": \"bạn cần phải đăng nhập để tải dự án\",\n    \"file_save\": \"Lưu\",\n    \"file_save_as\": \"Lưu bản sao\",\n    \"file_save_download\": \"Tải dự án về\",\n    \"func\": \"Function\",\n    \"function_create\": \"thêm chức năng\",\n    \"function_add\": \"thêm chức năng\",\n    \"interface\": \"Interface\",\n    \"landscape\": \"Landscape\",\n    \"list\": \"danh sách\",\n    \"list_add_calcel\": \"\",\n    \"list_add_calcel_msg\": \"\",\n    \"list_add_fail\": \"\",\n    \"list_add_fail_msg1\": \"\",\n    \"list_add_fail_msg2\": \"\",\n    \"list_add_ok\": \"\",\n    \"list_add_ok_msg\": \"\",\n    \"list_create\": \"thêm danh sách\",\n    \"list_create_placeholder\": \"Input the name of the list.\",\n    \"list_dup\": \"\",\n    \"list_newname\": \"New name\",\n    \"list_export\": \"Export\",\n    \"list_import\": \"Import\",\n    \"list_remove\": \"Remove list\",\n    \"list_rename\": \"đổi tên danh sách\",\n    \"list_rename_failed\": \"\",\n    \"list_rename_ok\": \"\",\n    \"list_too_long\": \"\",\n    \"message\": \"tín hiệu\",\n    \"message_add_cancel\": \"Canceled\",\n    \"message_add_cancel_msg\": \"Add a message was canceled.\",\n    \"message_add_fail\": \"Failed\",\n    \"message_add_fail_msg\": \"Message name conflicted.\",\n    \"message_add_ok\": \"Message added\",\n    \"message_add_ok_msg\": \"was successfully added.\",\n    \"message_create\": \"thêm tín hiệu\",\n    \"message_create_placeholder\": \"Input the name of the signal\",\n    \"message_dup\": \"tên thư đã tồn tại\",\n    \"message_remove\": \"Remove a message\",\n    \"message_remove_canceled\": \"Remove a message was canceled\",\n    \"message_rename\": \"đổi tên thư \",\n    \"message_rename_failed\": \"đổi tên thư thất bại\",\n    \"message_rename_ok\": \"đổi tên thư thành công\",\n    \"message_too_long\": \"tên thư quá dài\",\n    \"no_message_to_remove\": \"There is no message to remove.\",\n    \"no_use\": \"không sử dụng\",\n    \"no_variable_to_remove\": \"\",\n    \"no_variable_to_rename\": \"There is no varibale to remove\",\n    \"object_not_found\": \"không có đối tượng được quy định trong khối\",\n    \"object_not_found_for_paste\": \"không có đối tượng để dán\",\n    \"people\": \"People\",\n    \"picture_add\": \"thêm hình dạng\",\n    \"table_add\": \"Add Table\",\n    \"draw_new_table\": \"New Table\",\n    \"plant\": \"Plant\",\n    \"project\": \"Project\",\n    \"project_copied\": \"Copy\",\n    \"PROJECTDEFAULTNAME\": ['Cool', 'Funny', 'Nice', 'Huge', 'Great', 'Handsome', 'Lucky'],\n    \"remove_object\": \"xóa đối tượng\",\n    \"remove_object_msg\": \"xóa hoàn thành thành công\",\n    \"removed_msg\": \"was successfully removed\",\n    \"rotate_method\": \"xoay vòng\",\n    \"rotation\": \"Vòng xoay(°)\",\n    \"run\": \"bắt đầu\",\n    \"saved\": \"Saved\",\n    \"saved_msg\": \"was successfully saved.\",\n    \"save_failed\": \"Problem occurred while saving a project. Please try again.\",\n    \"select_library\": \"Select Object\",\n    \"select_sprite\": \"Please select at least one sprite to apply.\",\n    \"shape_remove_fail\": \"xoá hình dạng thất bại\",\n    \"shape_remove_fail_msg\": \"phải có ít nhất 1 hoặc vài hình dạng tồn tại\",\n    \"shape_remove_ok\": \"xóa hình dạng\",\n    \"shape_remove_ok_msg\": \"đã được xóa\",\n    \"load_expansion_block\": \"Load Expansion Block\",\n    \"load_ai_utilize_block\": \"Load AI Block\",\n    \"load_ai_utilize_train_block\": \"Train Model\",\n    \"select_expansion_block\": \"Select block\",\n    \"deselect_expansion_block_warning\": \"The selected block cannot be deleted. \\nThe specified block is currently in use.\",\n    \"deselect_ai_utilize_block_warning\": \"The selected block cannot be deleted. \\nThe specified block is currently in use.\",\n    \"sound_add\": \"thêm âm thanh\",\n    \"sound_remove_fail\": \"xóa âm thanh thất bại\",\n    \"sound_remove_ok\": \"âm thanh được xóa\",\n    \"sound_remove_ok_msg\": \"đã được xóa\",\n    \"stop\": \"dừng lại\",\n    \"pause\": \"tạm ngừng\",\n    \"restart\": \"khởi động lại\",\n    \"speed\": \"tốc độ\",\n    \"tab_attribute\": \"thuộc tính\",\n    \"tab_table\": \"Table\",\n    \"tab_code\": \"khối\",\n    \"tab_picture\": \"hình dạng\",\n    \"tab_sound\": \"âm thanh\",\n    \"tab_text\": \"hộp văn bản\",\n    \"textbox\": \"Textbox\",\n    \"textbox_edit\": \"Edit Textbox\",\n    \"textbox_input\": \"Please input text for apply.\",\n    \"things\": \"Things\",\n    \"textcoding_tooltip1\": \"Instructions for 'Entry Python'<br/>is available. Check out !\",\n    \"textcoding_tooltip2\": \"Code with blocks or by Python<br/>whichever you prefer.\",\n    \"textcoding_tooltip3\": \"See Python code execution results.\",\n    \"upload\": \"Upload files\",\n    \"upload_addfile\": \"Add a file\",\n    \"variable\": \"biến số\",\n    \"variable_add_calcel\": \"Canceled\",\n    \"variable_add_calcel_msg\": \"Add a variable was canceled.\",\n    \"variable_add_fail\": \"Failed\",\n    \"variable_add_fail_msg1\": \"Variable name conflicted.\",\n    \"variable_add_fail_msg2\": \"Variable name is not proper.\",\n    \"variable_add_ok\": \"Variable added\",\n    \"variable_add_ok_msg\": \"was successfully added.\",\n    \"variable_create\": \"thêm biến số\",\n    \"variable_add\": \"thêm biến số\",\n    \"variable_dup\": \"tên biến số đã tồn tại\",\n    \"variable_newname\": \"New Name\",\n    \"variable_remove\": \"Remove variable\",\n    \"variable_remove_canceled\": \"Remove a variable was canceled\",\n    \"variable_rename\": \"đổi tên biến số\",\n    \"variable_rename_failed\": \"thất bại\",\n    \"variable_rename_msg\": \"'Rename variable was successfully completed.'\",\n    \"variable_rename_ok\": \"đổi tên biến số thành công\",\n    \"variable_select\": \"Select a variable\",\n    \"variable_too_long\": \"tên biến số quá dài\",\n    \"open_analizy_data_import\": \"Open Data Import\",\n    \"vehicle\": \"Vehicles\",\n    \"add_object_alert_msg\": \"thêm đối tượng thứ nhất\",\n    \"add_object_alert\": \"cảnh báo\",\n    \"create_variable_block\": \"Create variable\",\n    \"create_list_block\": \"tạo danh sách\",\n    \"Variable_Timer\": \"bộ đếm thời gian\",\n    \"Variable_placeholder_name\": \"tên biến số\",\n    \"Message_placeholder_name\": \"Signal name\",\n    \"Variable_property\": \"Attribute of the variable\",\n    \"Variable_placeholder_content\": \"Input the name of the variable.\",\n    \"Variable_use_all_objects\": \"sử dụng cho tất cả các đối tượng\",\n    \"Variable_use_this_object\": \"sử dụng cho đối tượng này\",\n    \"Variable_used_at_all_objects\": \"biến số được sử dụng trên tất cả các đối tượng\",\n    \"variable_create_normal\": \"Use for variable\\n(Stored in Project)\",\n    \"variable_create_cloud\": \"Cần biến số chia sẻ. \\n(Đã được lưu trên máy chủ)\",\n    \"variable_create_real_time\": \"Use for real-time variable\\n(Stored in Server)\",\n    \"Variable_used_at_special_object\": \"biến số được sử dụng trên đối tượng đặc biệt\",\n    \"Variable_used_objects\": \"Object used for the variable\",\n    \"draw_new\": \"Draw new\",\n    \"draw_new_ebs\": \"Draw new\",\n    \"painter_file\": \"tập tin▼\",\n    \"painter_file_save\": \"lưu\",\n    \"painter_file_saveas\": \"lưu thành hình ảnh mới\",\n    \"new_picture\": \"hình ảnh mới\",\n    \"painter_edit\": \"biên soạn▼\",\n    \"get_file\": \"nhận được\",\n    \"copy_file\": \"sao chép\",\n    \"cut_picture\": \"cắt\",\n    \"paste_picture\": \"dán\",\n    \"remove_all\": \"xoá tất cả\",\n    \"flip_horizontal\": \"flip horizontal\",\n    \"flip_vertical\": \"flip vertical\",\n    \"regular\": \"Regular\",\n    \"bold\": \"Bold\",\n    \"font_underline\": \"underline\",\n    \"font_tilt\": \"tilt\",\n    \"font_cancel\": \"cancel\",\n    \"font_color\": \"font color\",\n    \"font_fill\": \"Fill\",\n    \"font_family\": \"font\",\n    \"align_left\": \"left align \",\n    \"align_center\": \"center align\",\n    \"align_right\": \"right align\",\n    \"italic\": \"Italic\",\n    \"textStyle\": \"chữ\",\n    \"add_picture\": \"Add Shape\",\n    \"select_picture\": \"Select Library\",\n    \"select_table\": \"Select Table\",\n    \"select_sound\": \"Select sound\",\n    \"Size\": \"kích cỡ\",\n    \"show_variable\": \"hiển thị các biến \",\n    \"default_value\": \"Mặc định\",\n    \"slide\": \"slide\",\n    \"min_value\": \"giá trị nhỏ nhất\",\n    \"max_value\": \"giá trị lớn nhất\",\n    \"number_of_list\": \"số lượng hạng mục trong danh sách\",\n    \"empty_of_list\": \"No items added.\",\n    \"use_all_objects\": \"sử dụng cho tất cả các đối tượng\",\n    \"list_name\": \"tên danh sách\",\n    \"list_property\": \"Attribute of the list\",\n    \"list_used_specific_objects\": \"danh sách được sử dụng cho đối tượng đặc biệt\",\n    \"List_used_all_objects\": \"danh sách được sử dụng cho tất cả các đối tượng\",\n    \"List_used_objects\": \"Object used for the list\",\n    \"Scene_delete_error\": \"cảnh tượng phải có ít nhất 1 cái\",\n    \"Scene_add_error\": \"cảnh lên đến 10\",\n    \"replica_of_object\": \"bản sao của\",\n    \"will_you_delete_scene\": \"Nếu xóa cảnh sẽ không phục hồi được. Bạn có chắc chắn muốn xóa cảnh?\",\n    \"will_you_delete_function\": \"Deleting function can not be restored.\\nAre you sure you want to delete function?\",\n    \"duplicate_scene\": \"lặp lại\",\n    \"block_explain\": \"Block description \",\n    \"block_intro\": \"Clicking on the block comes the description of the block . \",\n    \"blocks_reference\": \"Khối tài liệu tham khảo\",\n    \"hardware_guide\": \"Hướng dẫn phần cứng\",\n    \"robot_guide\": \"Robot Guide\",\n    \"python_guide\": \"Entry Python Guide\",\n    \"show_list_workspace\": \"hiển thị danh sách\",\n    \"list_create_normal\": \"Use for list\\n(Stored in Project)\",\n    \"list_create_cloud\": \"sử dụng cho danh sách chia sẻ \\n(được lưu trữ trong máy chủ)\",\n    \"list_create_real_time\": \"Use for real-time list\\n(Stored in Server)\",\n    \"confirm_quit\": \"You didn't saved your changes.\",\n    \"confirm_load_temporary\": \"Bạn chưa lưu dự án. Bạn có muốn mở không?\",\n    \"login_to_save\": \"Try to save after login.\",\n    \"cannot_save_in_edit_func\": \"Can not save while editing function.\",\n    \"new_object\": \"New Object\",\n    \"arduino_connect\": \"\",\n    \"arduino_connect_success\": \"\",\n    \"confirm_load_header\": \"Dự án khôi phục\",\n    \"uploading_msg\": \"đang tải lên\",\n    \"upload_fail_msg\": \"tải lên thất bại. Vui lòng thử lại\",\n    \"upload_not_supported_msg\": \"Not supported file type.\",\n    \"upload_not_supported_file_msg\": \"Not supported file type.\",\n    \"file_converting_msg\": \"​File converting in process\",\n    \"file_converting_fail_msg\": \"​File conversion has failed\",\n    \"fail_contact_msg\": \"If the problem persists,</br>contact entry@connect.or.kr\",\n    \"saving_msg\": \"Saving\",\n    \"saving_fail_msg\": \"Save failed. Please try again.\",\n    \"loading_msg\": \"Loading\",\n    \"loading_fail_msg\": \"Load failed. Please try again.\",\n    \"restore_project_msg\": \"Project is not saved properly. Would you like to restore this project?\",\n    \"quit_stop_msg\": \"Program cannot be closed during save.\",\n    \"ent_drag_and_drop\": \"Drag and drop the file to upload\",\n    \"not_supported_file_msg\": \"This file format is not supported\",\n    \"broken_file_msg\": \"File is corrupt or wrong file is loaded\",\n    \"check_audio_msg\": \"Not supported file type.\",\n    \"check_entry_file_msg\": \"Only ENT files are loadable\",\n    \"hardware_version_alert_text\": \"Please update your hardware connector to the latest version.\",\n    \"variable_name_auto_edited_title\": \"variable name auto-edited\",\n    \"variable_name_auto_edited_content\": \"variable name cannot exceed 10 characters\",\n    \"list_name_auto_edited_title\": \"list name auto-edited\",\n    \"list_name_auto_edited_content\": \"list name cannot exceed 10 characters\",\n    \"cloned_scene\": \"Cloned_\",\n    \"default_mode\": \"Standard\",\n    \"practical_course_mode\": \"Textbook\",\n    \"practical_course\": \"practical course\",\n    \"select_mode\": \"Mode\",\n    \"select_mode_popup_title\": \"Choose 'Create' option\",\n    \"select_mode_popup_lable1\": \"Standard\",\n    \"select_mode_popup_lable2\": \"Textbook(Practical Course)\",\n    \"select_mode_popup_desc1\": \"Create projects with<br/>unlimited Entry features\",\n    \"select_mode_popup_desc2\": \"Create projects using<br/>'Practical Course' features\",\n    \"practical_course_notice\": \"Notice\",\n    \"practical_course_desc\": \"<span class='practical_cource_title'>교과용 만들기</span>는<br />실과 교과서로 소프트웨어를 배울 때<br />필요한 기능만을 제공합니다.\",\n    \"practical_course_desc2\": \"*기본형 작품 만들기를 이용하면 더 많은 기능을<br />이용해 작품을 만들 수 있습니다.\",\n    \"practical_course_tooltip\": \"모든 기능을 이용하기 위해서는<br/>기본형을 선택해 주세요.\",\n    \"name_already_exists\": \"The name already exists.\",\n    \"enter_the_name\": \"Please enter the name.\",\n    \"object_not_exist_error\": \"Object does not exist. Please add object and try again.\",\n    \"workspace_tutorial_popup_desc\": \"<span class='practical_cource_title'>작품 만들기</span>는<br />창의적인 작품을 만들 수 있도록<br /> 다양한 블록과 기능을 제공합니다.\",\n    \"start_guide_tutorial\": \"Creating Guide\",\n    \"language\": \"language\",\n    \"file\": \"file\",\n    \"save\": \"save\",\n    \"help\": \"help\",\n    \"print\": \"print\",\n    \"undo\": \"undo\",\n    \"redo\": \"redo\",\n    \"workspace_title_tooltip\": \"The default project name has changed. You can\\nrecognize what project is through the date you create in\\nthe project name.\",\n    \"workspace_object_tooltip\": \"You can change the order of the object by\\ndragging the image of the object. (It is the same\\nin the ‘Shape’ and ‘Sound’ sections.)\",\n    \"workspace_comment_tooltip\": \"You can hide or show all the memos\\nadded.\",\n    \"workspace_zoom_tooltip\": \"You can zoom in/out the blocks. If you click ‘=’\\nthe block will be back to original size.\",\n    \"workspace_image_tooltip\": \"Create your own\\nproject with new\\nfunctions!\",\n    \"playground_block_drop\": \"Add the blocks in my storage\\nto assembly station\",\n    \"container_object_drop\": \"Add the object in my storage\\nto object list\",\n    \"my_storage_block_drop\": \"Add\\nthe blocks\\nto my storage\",\n    \"my_storage_object_drop\": \"Add\\nthe object\\nto my storage\",\n    \"my_storage\": \"my storage\",\n    \"my_block\": \"My Block\",\n    \"red\": \"Red\",\n    \"green\": \"Green\",\n    \"blue\": \"Blue\",\n    \"hue\": \"Hue\",\n    \"saturation\": \"Saturation\",\n    \"brightness\": \"Brightness\",\n    \"spoid\": \"Spoid\",\n    \"palette_mode\": \"Palette mode\",\n    \"slider_mode\": \"Slider mode\",\n    \"toast_error_title_object_center\": \"Caution\",\n    \"toast_error_contents_object_center\": \"If the center point is far from the object and goes out of the canvas, it returns to its original position.\",\n    \"blocks_comming_soon\": \"I'm working hard.\\nPlease wait a little longer!\",\n    \"data_table\": \"table\",\n    \"select_all\": \"모두\",\n    \"now_loading_msg\": \"Now Loading.\\nPlease Wait.\"\n};\nLang.code = \"view code\";\nLang.EntryStatic = {\n    \"event100\": \"Event\",\n    \"groupProject\": \"open group\",\n    \"usage_parallel\": \"Parallel\",\n    \"usage_expansion\": \"Expansion\",\n    \"usage_hw\": \"Hardware\",\n    \"usage_sequence\": \"Sequence\",\n    \"privateProject\": \"only owner\",\n    \"privateCurriculum\": \"only owner\",\n    \"publicCurriculum\": \"curriculum share\",\n    \"publicProject\": \"project share\",\n    \"group\": \"open group\",\n    \"groupCurriculum\": \"open group\",\n    \"private\": \"only owner\",\n    \"public\": \"open lessons\",\n    \"lecture_is_open_true\": \"open\",\n    \"lecture_is_open_false\": \"closed\",\n    \"category_all\": \"All Categories\",\n    \"category_game\": \"Game\",\n    \"category_animation\": \"Animation\",\n    \"category_media_art\": \"Media Art\",\n    \"category_physical\": \"Physical\",\n    \"category_etc\": \"etc\",\n    \"category_category_game\": \"Game\",\n    \"category_category_animation\": \"Animation\",\n    \"category_category_media_art\": \"Media Art\",\n    \"category_category_physical\": \"Physical\",\n    \"category_category_etc\": \"etc\",\n    \"sort_created\": \"By Latest\",\n    \"sort_updated\": \"By Latest\",\n    \"sort_visit\": \"By Viewers\",\n    \"sort_likeCnt\": \"By Likes\",\n    \"sort_comment\": \"By Comments\",\n    \"period_all\": \"Entire period\",\n    \"period_1\": \"Today\",\n    \"period_7\": \"Latest 1 week\",\n    \"period_30\": \"Latest 1 month\",\n    \"period_90\": \"Latest 3 months\",\n    \"lecture_required_time_1\": \"Less than 15 min.\",\n    \"lecture_required_time_2\": \"15  to 30 min.\",\n    \"lecture_required_time_3\": \"30 to 45 min.\",\n    \"lecture_required_time_4\": \"45 to 60 min\",\n    \"lecture_required_time_5\": \"over 1 hour\",\n    \"usage_event\": \"Event\",\n    \"usage_signal\": \"Signal\",\n    \"usage_scene\": \"Scene\",\n    \"usage_repeat\": \"Repeat\",\n    \"usage_condition_repeat\": \"Condition repeat\",\n    \"usage_condition\": \"Condition\",\n    \"usage_clone\": \"Cloned Object\",\n    \"usage_rotation\": \"Rotation\",\n    \"usage_coordinate\": \"Coordinate\",\n    \"usage_arrow_move\": \"Arrow move\",\n    \"usage_shape\": \"Shape\",\n    \"usage_speak\": \"Speak\",\n    \"usage_picture_effect\": \"Effect\",\n    \"usage_textBox\": \"Textbox\",\n    \"usage_draw\": \"Draw\",\n    \"usage_sound\": \"Sound\",\n    \"usage_confirm\": \"Confirm\",\n    \"usage_comp_operation\": \"Compare operation\",\n    \"usage_logical_operation\": \"Logical operation\",\n    \"usage_math_operation\": \"Math operation\",\n    \"usage_random\": \"Random\",\n    \"usage_timer\": \"bộ đếm thời gian\",\n    \"usage_variable\": \"biến số\",\n    \"usage_list\": \"List\",\n    \"usage_ask_answer\": \" Input/Output\",\n    \"usage_function\": \"Function\",\n    \"usage_arduino\": \"Arduino\",\n    \"concept_resource_analytics\": \"Procedual Thinking\",\n    \"concept_procedual\": \"Abstractive Thinking\",\n    \"concept_abstractive\": \"Korean\",\n    \"concept_individual\": \"English\",\n    \"concept_automation\": \"Automation\",\n    \"concept_simulation\": \"Simulation\",\n    \"concept_parallel\": \"Parallel\",\n    \"subject_korean\": \"Korean\",\n    \"subject_english\": \"English\",\n    \"subject_mathmatics\": \"Mathmatics\",\n    \"subject_social\": \"Social\",\n    \"subject_science\": \"Science\",\n    \"subject_music\": \"Music\",\n    \"subject_paint\": \"Paint\",\n    \"subject_athletic\": \"Athletics\",\n    \"subject_courtesy\": \"Courtesy\",\n    \"subject_progmatic\": \"Progmatic\",\n    \"lecture_grade_1\": \"1 th\",\n    \"lecture_grade_2\": \"2 th\",\n    \"lecture_grade_3\": \"3 th\",\n    \"lecture_grade_4\": \"4 th\",\n    \"lecture_grade_5\": \"5 th\",\n    \"lecture_grade_6\": \"6 th\",\n    \"lecture_grade_7\": \"7 th\",\n    \"lecture_grade_8\": \"8 th\",\n    \"lecture_grade_9\": \"9 th\",\n    \"lecture_grade_10\": \"Graduated\",\n    \"lecture_level_1\": \"Low\",\n    \"lecture_level_2\": \"Middle\",\n    \"lecture_level_3\": \"High\",\n    \"listEnable\": \"list\",\n    \"functionEnable\": \"function\",\n    \"messageEnable\": \"message\",\n    \"objectEditable\": \"object\",\n    \"pictureeditable\": \"shape\",\n    \"sceneEditable\": \"scene\",\n    \"soundeditable\": \"sound\",\n    \"variableEnable\": \"biến số\",\n    \"e_1\": \"elementary school 1\",\n    \"e_2\": \"elementary school 2\",\n    \"e_3\": \"elementary school 3\",\n    \"e_4\": \"elementary school 4\",\n    \"e_5\": \"elementary school 5\",\n    \"e_6\": \"elementary school 6\",\n    \"m_1\": \"middle school 1\",\n    \"m_2\": \"middle school 2\",\n    \"m_3\": \"middle school 3\",\n    \"general\": \"general\",\n    \"curriculum_is_open_true\": \"open\",\n    \"curriculum_open_false\": \"closed\",\n    \"contest2019\": \"Contest\",\n    \"exhibit\": \"Contest\",\n    \"notice\": \"Notice\",\n    \"qna\": \"Q&A\",\n    \"tips\": \"Tips & Tricks\",\n    \"free\": \"Discussions\",\n    \"report\": \"Suggestions\",\n    \"art_category_all\": \"All projects\",\n    \"art_category_game\": \"Game\",\n    \"art_category_animation\": \"Animation\",\n    \"art_category_physical\": \"Physical\",\n    \"art_category_etc\": \"etc\",\n    \"art_category_media\": \"media art\",\n    \"art_sort_updated\": \"Most Recent\",\n    \"art_sort_visit\": \"Views\",\n    \"art_sort_likeCnt\": \"Likes\",\n    \"art_sort_comment\": \"Comments\",\n    \"art_period_all\": \"All\",\n    \"art_period_day\": \"Today\",\n    \"art_period_week\": \"Recent week\",\n    \"art_period_month\": \"Recent month\",\n    \"art_period_three_month\": \"Recent three month\",\n    \"level_high\": \"Row\",\n    \"level_mid\": \"Middle\",\n    \"level_row\": \"High\",\n    \"discuss_sort_created\": \"Most Recent\",\n    \"discuss_sort_visit\": \"Views\",\n    \"discuss_sort_likesLength\": \"Likes\",\n    \"discuss_sort_commentsLength\": \"Comments\",\n    \"discuss_period_all\": \"All\",\n    \"discuss_period_day\": \"Today\",\n    \"discuss_period_week\": \"Recent week\",\n    \"discuss_period_month\": \"Recent month\",\n    \"discuss_period_three_month\": \"Recent three month\"\n};\nLang.Helper = {\n    \"when_run_button_click\": \"Khi nút Bắt đầu được nhấp, khối đòn kết nối sẽ chạy.\",\n    \"when_some_key_pressed\": \"Khi một phím đã gán được nhấn, các khối kết nối dưới đây sẽ chạy. \",\n    \"mouse_clicked\": \"Khi chuột được nhấn, các khối kết nối dưới đây sẽ chạy. \",\n    \"mouse_click_cancled\": \"Khi chuột được thả ra, các khối kết nối dưới đây sẽ chạy. \",\n    \"when_object_click\": \"Khi một đối tượng liên quan được nhấn vào, các khối kết nối dưới đây sẽ chạy. \",\n    \"when_object_click_canceled\": \"Khi bỏ nhấn vào đối tượng, các khối kết nối dưới đây sẽ chạy.\",\n    \"when_message_cast\": \"Khi nhận được một dấu hiệu có liên quan, các khối kết nối dưới đây sẽ chạy. \",\n    \"message_cast\": \"Gửi tín hiệu được lựa chọn từ danh sách. \",\n    \"message_cast_wait\": \"Gửi tín hiệu được lựa chọn từ danh sách, và chờ đợi cho các khối kết thúc hoạt động. \",\n    \"when_scene_start\": \"Khi cảnh bắt đầu, các đòn nối khối sẽ chạy. \",\n    \"start_scene\": \"Bắt đầu chọn cảnh. \",\n    \"start_neighbor_scene\": \"Bắt đầu cảnh trước hoặc sau. \",\n    \"wait_second\": \"Chạy khối tiếp theo sau khi chờ đợi một khoảng thời gian. \",\n    \"repeat_basic\": \"Lặp đi lặp lại các khối bên trong để thiết lập số lượng thời gian. \",\n    \"repeat_inf\": \"Lặp đi lặp lại các khối bên trong trong khoảng thời gian không giới hạn.\",\n    \"repeat_while_true\": \"Lặp lại các khối cho đến khi các điều kiện thiết lập được đáp ứng. \",\n    \"stop_repeat\": \"dừng lặp lại các khối gần nhất\",\n    \"_if\": \"Nếu điều kiện là đúng, chạy các khối bên trong. \",\n    \"if_else\": \"Nếu điều kiện là đúng, chạy các khối trong phần 'nếu'. Nếu không, chạy các khối bên trong phần 'khác'. \",\n    \"restart_project\": \"Khởi động lại tất cả các đối tượng \",\n    \"stop_object\": \"Tất cả các đối tượng: dừng tất cả các đối tượng <br>  Khối này: Dừng tất cả các khối trong đối tượng này. <br>  Đối tượng này: dừng tất cả các khối trong đối tượng này. <br?>Khối khác của đối tượng này: ngừng các khối không kết nối với các khối của đối tượng này. \",\n    \"wait_until_true\": \"Dừng chạy và đợi đến khi giá trị điều kiện là đúng.\",\n    \"when_clone_start\": \"Khi một bản sao mới của đối tượng được tạo ra, các khối kết nối dưới đây sẽ chạy. \",\n    \"create_clone\": \"Tạo ra một bản sao của đối tượng. \",\n    \"delete_clone\": \"Xoá các đối tượng. \",\n    \"remove_all_clones\": \"Xóa tất cả các bản sao của đối tượng.\",\n    \"move_direction\": \"Di chuyển theo hướng mũi tên bằng cách thiết lập giá trị. \",\n    \"move_x\": \"Thay đổi x-vị trí của giá trị không phụ thuộc vào hướng của đối tượng.\",\n    \"move_y\": \"Thay đổi y-vị trí của giá trị không phụ thuộc vào hướng của đối tượng.\",\n    \"move_xy_time\": \"Thay đổi x và y-vị trí của giá trị không phụ thuộc vào hướng của đối tượng \",\n    \"locate_object_time\": \"Di chuyển các đối tượng đến vị trí con trỏ chuột hoặc vị trí của các đối tượng khác trong khoảng thời gian, đầu vào. \",\n    \"locate_x\": \"Di chuyển đối tượng đến các giá trị đầu vào x-vị trí. \",\n    \"locate_y\": \"Di chuyển đối tượng đến các giá trị đầu vào y-vị trí. \",\n    \"locate_xy\": \"Di chuyển đối tượng đến các giá trị đầu vào x và y-vị trí. \",\n    \"locate_xy_time\": \"Di chuyển các đối tượng với các giá trị được xác định x và y-vị trí trong khoảng thời gian đầu vào\",\n    \"locate\": \"Di chuyển đối tượng đến vị trí của con trỏ chuột hoặc đến vị trí của một đối tượng khác. \",\n    \"rotate_absolute\": \"Thiết lập hướng của đối tượng bằng số đầu vào của độ. \",\n    \"rotate_by_time\": \"Xoay đối tượng bằng số đầu vào của độ trong khoảng thời gian đầu vào\",\n    \"rotate_relative\": \"Xoay đối tượng bằng số lượng đầu vào của độ. \",\n    \"direction_absolute\": \"Thiết lập hướng của đối tượng bằng số lượng đầu vào của độ. \",\n    \"direction_relative\": \"Thay đổi hướng của đối tượng bằng số lượng đầu vào của độ. \",\n    \"move_to_angle\": \"Di chuyển đối tượng bằng các giá trị đầu vào theo hướng số lượng đầu vào của độ. \",\n    \"see_angle_object\": \"Làm cho các đối tượng phải đối mặt với một đối tượng hoặc con trỏ chuột. \",\n    \"bounce_wall\": \"Khi đối tượng chạm vào cạnh của màn hình, nó bị bật lại.\",\n    \"show\": \"Tạo đối tượng hiển thị trên màn hình.\",\n    \"hide\": \"Ẩn đối tượng từ màn hình. \",\n    \"dialog_time\": \"Chạy khối tiếp theo sau khi nội dung đầu vào được nói bởi các đối tượng trong khoảng thời gian  đầu vào. \",\n    \"dialog\": \"Chạy khối tiếp theo trong khi nội dung đầu vào được nói bởi các đối tượng.\",\n    \"remove_dialog\": \"Xóa hộp thoại đã tạo  (sử dụng khối hộp thoại) của các đối tượng. \",\n    \"change_to_some_shape\": \"Thay đổi đối tượng thành hình dạng được lựa chọn. \",\n    \"change_to_next_shape\": \"Thay đổi các đối tượng vào các hình tiếp theo. \",\n    \"set_effect_volume\": \"Áp dụng các hiệu ứng đã chọn vào đối tượng bằng các giá trị đầu vào. \",\n    \"set_effect_amount\": \"Áp dụng các hiệu ứng đã chọn vào đối tượng bằng các giá trị đầu vào.\",\n    \"set_effect\": \"Thiết lập hiệu ứng đã chọn vào đối tượng bằng các giá trị đầu vào. \",\n    \"set_entity_effect\": \"Thiết lập hiệu ứng đã chọn vào đối tượng bằng các giá trị đầu vào. \",\n    \"add_effect_amount\": \"Áp dụng các hiệu ứng đã chọn vào đối tượng bằng các giá trị đầu vào.\",\n    \"change_effect_amount\": \"Thiết lập hiệu ứng đã chọn vào đối tượng bằng các giá trị đầu vào. \",\n    \"change_scale_percent\": \"Thay đổi kích thước của đối tượng bằng giá trị đầu vào. \",\n    \"set_scale_percent\": \"Thiết lập kích thước của các đối tượng với giá trị đầu vào. \",\n    \"change_scale_size\": \"Thay đổi kích thước của đối tượng bằng giá trị đầu vào. \",\n    \"set_scale_size\": \"Thiết lập kích thước của các đối tượng với giá trị đầu vào. \",\n    \"flip_x\": \"Lật đối tượng theo chiều dọc. \",\n    \"flip_y\": \"Lật đối tượng theo chiều ngang. \",\n    \"change_object_index\": \"Mang đến phia trước: đưa đối tượng đến phía trước. <br> Mang theo một mặt đến phía trước: mang theo đối tượng một lớp đến phía trước. <br> Gửi một mặt trở lại: gửi đối tượng một lớp trở lại. <br> Gửi trở lại: gửi đối tượng trở lại\",\n    \"set_object_order\": \"Hiển thị các đối tượng theo thứ tự thiết lập. \",\n    \"brush_stamp\": \"Bản sao của đối tượng trên màn hinh giống như con dấu\",\n    \"start_drawing\": \"Sơn được quét dọc theo con đường của các đối tượng. \",\n    \"stop_drawing\": \"dừng việc vẽ của đối tượng\",\n    \"set_color\": \"Thiết lập màu sắc cọ vẽ của đối tượng bằng màu được chọn.\",\n    \"set_random_color\": \"Thiết lập màu sắc cọ vẽ của đối tượng ngẫu nhiên.\",\n    \"change_thickness\": \"Thay đổi độ dày cọ vẽ của đối tượng bằng giá trị đầu vào.\",\n    \"set_thickness\": \"Thiết lập độ dày cọ vẽ của đối tượng bằng giá trị đầu vào.\",\n    \"change_opacity\": \"Thay đổi độ trong suốt của cọ bằng giá trị đầu vào.\",\n    \"change_brush_transparency\": \"Thay đổi độ trong suốt cọ vẽ của đối tượng bằng giá trị đầu vào.\",\n    \"set_opacity\": \"Thiết lập độ trong suốt cọ vẽ của đối tượng bằng giá trị đầu vào.\",\n    \"set_brush_tranparency\": \"Thiết lập độ trong suốt cọ vẽ của đối tượng bằng giá trị đầu vào.\",\n    \"brush_erase_all\": \"Xóa tất cả cọ vẽ và các con dấu của đối tượng\",\n    \"sound_something_with_block\": \"Phát âm thanh đã chọn của đối tượng trong khi khối tiếp theo chạy. \",\n    \"sound_something_second_with_block\": \"Phát âm thanh đã chọn của đối tượng trong khoảng thời gian đầu vào đồng thời chạy khối tiếp theo.\",\n    \"sound_something_wait_with_block\": \"Phát âm thanh đã chọn của đối tượng sau đó khi âm thanh đã phát xong thì chạy các khối tiếp theo.\",\n    \"sound_something_second_wait_with_block\": \"Phát âm thanh đã chọn của đối tượng trong khoảng thời gian đầu vào sau đó chạy khối tiếp theo.\",\n    \"sound_volume_change\": \"Thay đổi âm lượng của tất cả âm thanh được phát bằng phần trăm đầu vào.\",\n    \"sound_volume_set\": \"Thiết lập âm lượng của tất cả âm thanh được phát bằng phần trăm đầu vào.\",\n    \"sound_silent_all\": \"Dừng tất cả âm thanh hiện đang phát. \",\n    \"is_clicked\": \"Kiểm tra xem chuột được nhấp hay không.\",\n    \"is_press_some_key\": \"Kiểm tra xem một phím đã gán được nhấn hay không.\",\n    \"reach_something\": \"Kiểm tra xem đối tượng đạt đến điểm được chọn hay chưa.\",\n    \"is_included_in_list\": \"Kiểm tra xem danh sách chọn có chứa các giá trị đầu vào hay không.\",\n    \"boolean_basic_operator\": \"Err:501\",\n    \"function_create\": \"Xác định một chức năng bằng cách đặt các khối thường xuyên sử dụng dưới đây. Vị trí [tên] bên cạnh [xác định chức năng] để đặt tên cho chức năng.Vượt qua số lượng các giá trị văn bản bằng cách đặt khối[số / giá trị văn bản]. Vượt qua các giá trị boolean true hoặc false bằng cách đặt các khối [giá trị boolean].\",\n    \"function_field_label\": \"Đặt bên cạnh [xác định chức năng] để đặt tên cho chức năng.\",\n    \"function_field_string\": \"Vượt qua giá trị số/văn bản bằng cách đặt các khối này bên cạnh khối [xác định chức năng] .Grab /copy khối [số / giá trị văn]  trong khối  [Xác định chức năng] và sử dụng giá trị của nó trong chức năng.\",\n    \"function_field_boolean\": \"Sử dụng các khối này để vượt qua các giá trị boolean true hoặc false. Grab/copy khối [giá trị boolean] trong khối  [xác định chức năng] và sử dụng các giá trị chức năng.\",\n    \"function_general\": \"Đây là khối chức năng hiện tại hoặc khối chức năng đã tạo ra từ lâu.\",\n    \"boolean_and\": \"Kiểm tra xem cả hai điều kiện là đúng hay không.\",\n    \"boolean_or\": \"Kiểm tra xem ít nhất một trong hai điều kiện là đúng hay không.\",\n    \"boolean_not\": \"Thay đổi điều kiện đầu vào để đối lập nó.\",\n    \"is_boost_mode\": 'Checks whether the boost mode is turned on or not.\\nIf the boost mode is on, it is judged as \"true\".',\n    \"calc_basic\": \"+: 'Thêm hai số. <br>-: Trừ hai số. <br>X: nhân hai số. <br>/: chia hai số.\",\n    \"calc_rand\": \"Chọn một giá trị ngẫu nhiên giữa hai số đầu vào.\",\n    \"get_x_coordinate\": \"Báo cáo giá trị x-vị trí của đối tượng. \",\n    \"get_y_coordinate\": \"Báo cáo giá trị y-vị trí của đối tượng. \",\n    \"coordinate_mouse\": \"Báo cáo của một trong hai giá trị x hoặc y vị trí của chuột. \",\n    \"coordinate_object\": \"Báo cáo x/y-vị trí của các đối tượng và các thông tin khác nhau (hướng, hình dạng tên, vv).\",\n    \"quotient_and_mod\": \" Thương số: câu trả lời sau khi bạn chia số đầu tiên của số thứ hai. <br>Số dư: phần còn lại sau khi chia\",\n    \"get_rotation_direction\": \"Báo cáo giá trị định hướng, hướng di chuyển giá trị của đối tượng.\",\n    \"calc_share\": \"Báo cáo thương số nhận được khi số đầu tiên chia cho số thứ hai.\",\n    \"calc_mod\": \"Báo cáo số dư nhận được khi số đầu tiên chia cho số thứ hai. \",\n    \"calc_operation\": \"Báo cáo giá trị tính toán của một loạt các phương trình liên quan đến các số đầu vào . \",\n    \"get_date\": \"Báo cáo các giá trị về năm hiện tại, tháng, ngày và thời gian. \",\n    \"distance_something\": \"Báo cáo khoảng cách giữa đối tượng và đối tượng được chọn. \",\n    \"get_sound_duration\": \"Báo cáo độ dài thời gian của âm thanh được lựa chọn.\",\n    \"get_user_name\": \"작품을 실행하고 있는 사용자의 아이디 값입니다.\",\n    \"get_nickname\": \"작품을 실행하고 있는 사용자의 닉네임 값입니다.\",\n    \"get_project_timer_value\": \"Báo cáo có bao nhiêu giây đã trôi qua kể từ khi dự án bắt đầu. \",\n    \"choose_project_timer_action\": \"Star: Bắt đầu đếm thời gian. <br>Stop: Ngừng hẹn giờ. <br>Reset: Đặt lại bộ đếm thời gian về 0. <br>(Khi khối này ở workspace, chương trình sẽ hiển thị cửa sổ bộ đếm thời gian khi chạy.) \",\n    \"reset_project_timer\": \"Đặt lại bộ đếm thời gian về 0.\",\n    \"set_visible_project_timer\": \"Hiện hoặc ẩn bộ đếm thời gian. \",\n    \"ask_and_wait\": \"Các đối tượng yêu cầu các văn bản đầu vào, và sau đó nhận được một câu trả lời như một sự giải đáp.\",\n    \"get_canvas_input_value\": \"Báo cáo các nội dung đầu vào diễn ra sau khi các đối tượng yêu cầu.\",\n    \"set_visible_answer\": \"Ẩn hoặc hiển thị ' cửa sổ trả lời'. \",\n    \"combine_something\": \"Kết hợp hai văn bản đầu vào. \",\n    \"get_variable\": \"Báo cáo giá trị của biến chọn.\",\n    \"change_variable\": \"Thêm giá trị đầu vào cho các biến được chọn. \",\n    \"set_variable\": \"Đặt giá trị của biến được chọn vào giá trị đầu vào\",\n    \"robotis_carCont_sensor_value\": \"Cảm biến kết nối bên trái: giá trị của số liên lạc (1), không tiếp xúc (0). <br/> Cảm biến liên lạc bên phải:  giá trị của số liên lạc (1), không tiếp xúc (0). <br/> Số cuối cùng của việc phát hiện âm thanh: giá trị của số cuối cùng phát hiện sống âm thanh.<br/>Số lượng các phát hiện âm thanh trực tiếp: tăng 1 khi nó phát hiện ra những âm thanh tiếp theo trong vòng 1 giây.<br/>Cảm biến hồng ngoại bên phải: giá trị là lớn hơn khi nó gần hơn với một đối tượng.<br/>Giá trị của trái cảm biến hồng ngoại hiệu chỉnh bên trái: giá trị hiệu chuẩn của cảm biến hồng ngoại.<br/>Giá trị của cảm biến hồng ngoại phải hiệu chỉnh bên phải: giá trị hiệu chuẩn của cảm biến hồng ngoại. (*Giá trị hiệu chuẩn - kiểm soát giá trị của cảm biến hồng ngoại)\",\n    \"robotis_carCont_cm_led\": \"Chỉ có LED 1 hoặc LED 4 trong số 4 đèn LED được bật hoặc tắt.<br/>Không áp dụng cho LED 2 và LED 3.\",\n    \"robotis_carCont_cm_sound_detected_clear\": \"Khởi tạo số cuối cùng của âm thanh được phát hiện đến 0.\",\n    \"robotis_carCont_aux_motor_speed\": \"Thiết lập tốc độ của động cơ giảm tốc độ với giá trị 0-1023.\",\n    \"robotis_carCont_cm_calibration\": \"Thiết lập giá trị kiểm soát của cảm biến hồng ngoại (http://support.robotis.com/ko/: automobile robot> 2. B. kiểm soát giá trị hồng ngoại).\",\n    \"robotis_openCM70_sensor_value\": \"Số cuối cùng phát hiện âm thanh: giá trị của số lần âm thanh được phát hiện cuối cùng. <br/>Số phát hiện âm thanh sống: tăng 1 khi nó phát hiện một âm tiếp theo trong vòng 1 giây. <br/>Tình trạng của nút sử dụng: giá trị của số liên lạc (1), không tiếp xúc (0).<br/>Số cuối cùng của âm thanh phát hiện: giá trị của số cuối cùng phát hiện âm thanh trực tiếp.<br/>Số lượng các phát hiện âm thanh trực tiếp: tăng 1 khi nó phát hiện ra những âm thanh tiếp theo trong vòng 1 giây.<br/>Tình trạng của người sử dụng nút: giá trị của số liên lạc (1), không tiếp xúc (0).\",\n    \"robotis_openCM70_aux_sensor_value\": \"Vị trí của động cơ servo: 0-1023, giá trị giữa là 512.<br/>cảm biến hồng ngoại: giá trị là lớn hơn khi nó gần với một đối tượng.<br/>Cảm biến Liên hệ:. Các giá trị của liên hệ (1), không tiếp xúc (0)<br/>CDS : 0-1023, giá trị là lớn hơn khi nó sáng hơn.<br/>cảm biến nhiệt độ, độ ẩm (độ ẩm): 0-100, giá trị là lớn hơn khi nó ẩm ướt hơn.<br/>cảm biến nhiệt độ, độ ẩm (nhiệt độ): -20 - 100, giá trị là lớn hơn khi nó cao hơn nhiệt độ.<br/>cảm biến nhiệt độ: -20 - 100, giá trị là lớn hơn khi nó cao hơn nhiệt độ.<br/> cảm biến siêu âm: - cảm biến từ tính:. các giá trị của hệ (1), không tiếp xúc (0)<br/>Nhận diện chuyển động: giá trị của phát hiện chuyển động (1), không phát hiện chuyển động (0).<br/>Màu sắc cảm biến: giá trị không rõ (0), trắng (1), đen (2), đỏ (3), màu xanh lá cây (4), màu xanh ( 5), vàng (6).<br/>Thiết bị người dùng: xin vui lòng tham khảo sách hướng dẫn  ROBOTIS e-manual (http://support.robotis.com/ko/) để giải thích về sản xuất cảm biến cho người dùng.\",\n    \"robotis_openCM70_cm_buzzer_index\": \"Phát âm từ 0.1 đến 5 giây.\",\n    \"robotis_openCM70_cm_buzzer_melody\": \"Phát nhịp điệu.<br/>Nếu âm thanh không phát liên tục khi lặp lại những giai điệu này thì sử dụng khối 'dòng chảy> chờ X giây' và thực hiện nó một lần nữa.\",\n    \"robotis_openCM70_cm_sound_detected_clear\": \"Số cuối cùng phát hiện âm thanh \",\n    \"robotis_openCM70_cm_led\": \"Bật hoặc tắt đèn LED màu đỏ, màu xanh lá cây, màu xanh dương của thiết bị.\",\n    \"robotis_openCM70_cm_motion\": \"Thực hiện chuyển động tải về thiết bị. \",\n    \"robotis_openCM70_cm_autodrive_motor\": \"Chỉ định cổng động cơ của ô tô lái tự động.\",\n    \"robotis_openCM70_cm_autodrive_ir\": \"Chỉ định cổng cảm biến hồng ngoại của xe lái tự động.\",\n    \"robotis_openCM70_cm_autodrive_speed\": \"Lái xe tự động được thực hiện ở tốc độ quy định dọc theo làn đường.\",\n    \"robotis_openCM70_aux_car_move\": \"Làm cho robot di chuyển với tốc độ và hướng xác định.\",\n    \"robotis_openCM70_aux_motor_speed\": \"Thiết lập tốc độ của động cơ giảm tốc với giá trị 0-100%.\",\n    \"robotis_openCM70_aux_servo_mode\": \"Thiết lập động cơ servo như chế độ bánh xe hoặc chế độ chung.<br/>Các chế độ tương tự vẫn tiếp tục áp dụng một khi đã cài đặt.<br/>Chế độ bánh xe chỉ định tốc độ động cơ servo, và quay động cơ servo.<br/>Chọn chế độ di chuyển vị trí của động cơ servo và tốc độ động cơ servo.\",\n    \"robotis_openCM70_aux_servo_speed\": \"Cài đặt tốc độ của động cơ servo với giá trị từ 0 - 100%. \",\n    \"robotis_openCM70_aux_servo_position\": \"Cài đặt vị trí của động cơ servo với giá trị từ -150 - 150 độ. <br/>Sử dụng như tốc độ động cơ servo\",\n    \"robotis_openCM70_aux_led_module\": \"Bật hoặc tắt các mô-đun LED của LED.\",\n    \"robotis_openCM70_aux_custom\": \"Vui lòng tham khảo ROBOTIS e-manual (http://support.robotis.com/ko/) để được giải thích về người sử dụng cảm biến sản xuất.\",\n    \"robotis_openCM70_cm_poweroff_timer\": \"Đặt bộ hẹn giờ tự động tắt của bộ điều khiển.<br/>Nếu giao tiếp không diễn ra trong khoảng thời gian đã đặt, bộ điều khiển sẽ tự động tắt.\",\n    \"robotis_openCM70_cm_custom_value\": \"Kiểm tra các giá trị bằng cách nhập  trực tiếp địa chỉ bảng điều khiển.<br/>Vui lòng tham khảo ROBOTIS e-manual (http://support.robotis.com/ko/)để được giải thích về bảng điều khiển.\",\n    \"robotis_openCM70_cm_custom\": \"Kiểm tra các giá trị bằng cách nhập  trực tiếp địa chỉ bảng điều khiển.<br/>Vui lòng tham khảo ROBOTIS e-manual (http://support.robotis.com/ko/)để được giải thích về bảng điều khiển.\",\n    \"show_variable\": \"Hiển thị giá trị của biến đã chọn trên màn hình.\",\n    \"hide_variable\": \"Ẩn giá trị của biến đã chọn trên màn hình.\",\n    \"value_of_index_from_list\": \"Báo cáo mục tại vị trí của giá trị nhập trong danh sách đã chọn. \",\n    \"add_value_to_list\": \"Thêm mục vào vị trí cuối cùng trong danh sách đã chọn. \",\n    \"remove_value_from_list\": \"Xóa mục tại vị trí của các giá trị đầu vào trong danh sách đã chọn. \",\n    \"insert_value_to_list\": \"Chèn mục đầu vào tại vị trí của giá trị đầu vào trong danh sách đã chọn. \",\n    \"change_value_list_index\": \"Thay thế mục tại vị trí của các giá trị đầu vào cho văn bản đầu vào \",\n    \"length_of_list\": \"Báo cáo số lượng các mục được chứa trong danh sách đã chọn. \",\n    \"show_list\": \"Hiển thị danh sách đã chọn trên màn hình.\",\n    \"hide_list\": \"Ẩn danh sách đã chọn trên màn hình.\",\n    \"text\": \"Báo cáo văn bản trong hộp văn bản. \",\n    \"text_read\": \"선택한 글상자 또는 글상자 자신의 내용입니다.<br />(내용 안에 줄바꿈이 있는 경우, 띄어쓰기하여 반환됩니다.)\",\n    \"text_write\": \"Thay đổi nội dung của hộp văn bản để nhập văn bản.\",\n    \"text_append\": \"Thêm các văn bản đầu vào phía sau hộp văn bản. \",\n    \"text_prepend\": \"Thêm văn bản đầu vào ở phía trước của hộp văn bản. \",\n    \"text_flush\": \"Xóa tất cả các văn bản được lưu trong hộp văn bản. \",\n    \"erase_all_effects\": \"Xóa tất cả các hiệu ứng về đối tượng này. \",\n    \"char_at\": \"Báo cáo thư của văn bản đầu vào. \",\n    \"length_of_string\": \"Báo cáo độ dài của văn bản đầu vào bao gồm khoảng cách \",\n    \"substring\": \"Báo cáo văn bản trích từ văn bản đầu vào giữa hai chỉ số quy định \",\n    \"replace_string\": \"Báo cáo văn bản mà đã được thay thế tất cả các văn bản đầu vào bằng một văn bản đầu vào khác\",\n    \"index_of_string\": \"Báo cáo chỉ số của văn bản đầu vào đầu tiên trong văn bản đầu vào thứ hai \",\n    \"change_string_case\": \"Báo cáo văn bản đã được chuyển đổi sang chữ hoa hoặc chữ thường \",\n    \"direction_relative_duration\": \"Xoay hướng của đối tượng này bằng số đầu vào của góc độ trong một khoảng thời gian. \",\n    \"get_sound_volume\": \"Báo cáo âm lượng âm thanh\",\n    \"sound_from_to\": \"해당 오브젝트가 선택한 소리를 입력한 시간 부분만을 재생하는 동시에 다음 블록을 실행합니다.\",\n    \"sound_from_to_and_wait\": \"해당 오브젝트가 선택한 소리를 입력한 시간 부분만을 재생하고, 소리 재생이 끝나면 다음 블록을 실행합니다.\",\n    \"Block_info\": \"Thông tin khối\",\n    \"Block_click_msg\": \"Nhấp vào các khối đi kèm các mô tả của khối. \",\n    \"hamster_beep\": \"버저 소리를 짧게 냅니다.\",\n    \"hamster_change_both_wheels_by\": \"왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"hamster_change_buzzer_by\": \"버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.\",\n    \"hamster_change_output_by\": \"선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH\",\n    \"hamster_change_tempo_by\": \"연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.\",\n    \"hamster_change_wheel_by\": \"왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"hamster_clear_buzzer\": \"버저 소리를 끕니다.\",\n    \"hamster_clear_led\": \"왼쪽/오른쪽/양쪽 LED를 끕니다.\",\n    \"hamster_follow_line_until\": \"왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.\",\n    \"hamster_follow_line_using\": \"왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.\",\n    \"hamster_hand_found\": \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"hamster_move_backward_for_secs\": \"입력한 시간(초) 동안 뒤로 이동합니다.\",\n    \"hamster_move_forward_for_secs\": \"입력한 시간(초) 동안 앞으로 이동합니다.\",\n    \"hamster_move_forward_once\": \"말판 위에서 한 칸 앞으로 이동합니다.\",\n    \"hamster_play_note_for\": \"선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.\",\n    \"hamster_rest_for\": \"입력한 박자만큼 쉽니다.\",\n    \"hamster_set_both_wheels_to\": \"왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"hamster_set_buzzer_to\": \"버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.\",\n    \"hamster_set_following_speed_to\": \"선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.\",\n    \"hamster_set_led_to\": \"왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.\",\n    \"hamster_set_output_to\": \"선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH\",\n    \"hamster_set_port_to\": \"선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.\",\n    \"hamster_set_tempo_to\": \"연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.\",\n    \"hamster_set_wheel_to\": \"왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"hamster_stop\": \"양쪽 바퀴를 정지합니다.\",\n    \"hamster_turn_for_secs\": \"입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.\",\n    \"hamster_turn_once\": \"말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.\",\n    \"hamster_value\": \"왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)\",\n    \"roboid_hamster_beep\": \"버저 소리를 짧게 냅니다.\",\n    \"roboid_hamster_change_both_wheels_by\": \"왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"roboid_hamster_change_buzzer_by\": \"버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.\",\n    \"roboid_hamster_change_output_by\": \"선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH\",\n    \"roboid_hamster_change_tempo_by\": \"연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.\",\n    \"roboid_hamster_change_wheel_by\": \"왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"roboid_hamster_clear_buzzer\": \"버저 소리를 끕니다.\",\n    \"roboid_hamster_clear_led\": \"왼쪽/오른쪽/양쪽 LED를 끕니다.\",\n    \"roboid_hamster_follow_line_until\": \"왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.\",\n    \"roboid_hamster_follow_line_using\": \"왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.\",\n    \"roboid_hamster_hand_found\": \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"roboid_hamster_move_backward_for_secs\": \"입력한 시간(초) 동안 뒤로 이동합니다.\",\n    \"roboid_hamster_move_forward_for_secs\": \"입력한 시간(초) 동안 앞으로 이동합니다.\",\n    \"roboid_hamster_move_forward_once\": \"말판 위에서 한 칸 앞으로 이동합니다.\",\n    \"roboid_hamster_play_note_for\": \"선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.\",\n    \"roboid_hamster_rest_for\": \"입력한 박자만큼 쉽니다.\",\n    \"roboid_hamster_set_both_wheels_to\": \"왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"roboid_hamster_set_buzzer_to\": \"버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.\",\n    \"roboid_hamster_set_following_speed_to\": \"선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.\",\n    \"roboid_hamster_set_led_to\": \"왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.\",\n    \"roboid_hamster_set_output_to\": \"선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH\",\n    \"roboid_hamster_set_port_to\": \"선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.\",\n    \"roboid_hamster_set_tempo_to\": \"연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.\",\n    \"roboid_hamster_set_wheel_to\": \"왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"roboid_hamster_stop\": \"양쪽 바퀴를 정지합니다.\",\n    \"roboid_hamster_turn_for_secs\": \"입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.\",\n    \"roboid_hamster_turn_once\": \"말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.\",\n    \"roboid_hamster_value\": \"왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)\",\n    \"roboid_turtle_button_state\": \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"roboid_turtle_change_buzzer_by\": \"버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.\",\n    \"roboid_turtle_change_head_led_by_rgb\": \"머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.\",\n    \"roboid_turtle_change_tempo_by\": \"연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.\",\n    \"roboid_turtle_change_wheel_by\": \"왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"roboid_turtle_change_wheels_by_left_right\": \"왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"roboid_turtle_clear_head_led\": \"머리 LED를 끕니다.\",\n    \"roboid_turtle_clear_sound\": \"소리를 끕니다.\",\n    \"roboid_turtle_cross_intersection\": \"검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.\",\n    \"roboid_turtle_follow_line\": \"하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.\",\n    \"roboid_turtle_follow_line_until\": \"하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.\",\n    \"roboid_turtle_follow_line_until_black\": \"하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.\",\n    \"roboid_turtle_is_color_pattern\": \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"roboid_turtle_move_backward_unit\": \"입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.\",\n    \"roboid_turtle_move_forward_unit\": \"입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.\",\n    \"roboid_turtle_pivot_around_wheel_unit_in_direction\": \"왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.\",\n    \"roboid_turtle_play_note\": \"선택한 계이름과 옥타브의 음을 계속 소리 냅니다.\",\n    \"roboid_turtle_play_note_for_beats\": \"선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.\",\n    \"roboid_turtle_play_sound_times\": \"선택한 소리를 입력한 횟수만큼 재생합니다.\",\n    \"roboid_turtle_play_sound_times_until_done\": \"선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.\",\n    \"roboid_turtle_rest_for_beats\": \"입력한 박자만큼 쉽니다.\",\n    \"roboid_turtle_set_buzzer_to\": \"버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.\",\n    \"roboid_turtle_set_following_speed_to\": \"선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.\",\n    \"roboid_turtle_set_head_led_to\": \"머리 LED를 선택한 색깔로 켭니다.\",\n    \"roboid_turtle_set_head_led_to_rgb\": \"머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.\",\n    \"roboid_turtle_set_tempo_to\": \"연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.\",\n    \"roboid_turtle_set_wheel_to\": \"왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"roboid_turtle_set_wheels_to_left_right\": \"왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"roboid_turtle_stop\": \"양쪽 바퀴를 정지합니다.\",\n    \"roboid_turtle_touching_color\": \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"roboid_turtle_turn_at_intersection\": \"검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.\",\n    \"roboid_turtle_turn_unit_in_place\": \"입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.\",\n    \"roboid_turtle_turn_unit_with_radius_in_direction\": \"입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.\",\n    \"roboid_turtle_value\": \"색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.\",\n    \"turtle_button_state\": \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"turtle_change_buzzer_by\": \"버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.\",\n    \"turtle_change_head_led_by_rgb\": \"머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.\",\n    \"turtle_change_tempo_by\": \"연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.\",\n    \"turtle_change_wheel_by\": \"왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"turtle_change_wheels_by_left_right\": \"왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.\",\n    \"turtle_clear_head_led\": \"머리 LED를 끕니다.\",\n    \"turtle_clear_sound\": \"소리를 끕니다.\",\n    \"turtle_cross_intersection\": \"검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.\",\n    \"turtle_follow_line\": \"하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.\",\n    \"turtle_follow_line_until\": \"하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.\",\n    \"turtle_follow_line_until_black\": \"하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.\",\n    \"turtle_is_color_pattern\": \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"turtle_move_backward_unit\": \"입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.\",\n    \"turtle_move_forward_unit\": \"입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.\",\n    \"turtle_pivot_around_wheel_unit_in_direction\": \"왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.\",\n    \"turtle_play_note\": \"선택한 계이름과 옥타브의 음을 계속 소리 냅니다.\",\n    \"turtle_play_note_for_beats\": \"선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.\",\n    \"turtle_play_sound_times\": \"선택한 소리를 입력한 횟수만큼 재생합니다.\",\n    \"turtle_play_sound_times_until_done\": \"선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.\",\n    \"turtle_rest_for_beats\": \"입력한 박자만큼 쉽니다.\",\n    \"turtle_set_buzzer_to\": \"버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.\",\n    \"turtle_set_following_speed_to\": \"선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.\",\n    \"turtle_set_head_led_to\": \"머리 LED를 선택한 색깔로 켭니다.\",\n    \"turtle_set_head_led_to_rgb\": \"머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.\",\n    \"turtle_set_tempo_to\": \"연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.\",\n    \"turtle_set_wheel_to\": \"왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"turtle_set_wheels_to_left_right\": \"왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.\",\n    \"turtle_stop\": \"양쪽 바퀴를 정지합니다.\",\n    \"turtle_touching_color\": \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n    \"turtle_turn_at_intersection\": \"검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.\",\n    \"turtle_turn_unit_in_place\": \"입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.\",\n    \"turtle_turn_unit_with_radius_in_direction\": \"입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.\",\n    \"turtle_value\": \"색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.\",\n    \"neobot_sensor_value\": \"Chỉ ra các giá trị đầu vào từ cổng IN1 - IN3 và các thông tin của pin như số từ 0 đến 255. \",\n    \"neobot_sensor_convert_scale\": \"Quy mô thể hiện sự thay đổi các cổng được lựa chọn của các giá trị đầu vào như giá trị của một quy mô cụ thể có thể được điều chỉnh. \",\n    \"neobot_left_motor\": \"Thiết lập hướng bánh xe và tốc độ của động cơ kết nối với cổng động cơ L. \",\n    \"neobot_stop_left_motor\": \"Dừng động cơ kết nối với cổng động cơ L.\",\n    \"neobot_right_motor\": \"Thiết lập hướng bánh xe và tốc độ của động cơ kết nối với cổng động cơ R. \",\n    \"neobot_stop_right_motor\": \"Dừng động cơ kết nối với cổng động cơ R.\",\n    \"neobot_all_motor\": \"Tốc độ, thời gian, và hướng về phía trước, sau, trái và phải, khi kết nối 2 động cơ đến cổng động cơ L và R có thể được thiết lập và sử dụng như bánh xe.\",\n    \"neobot_stop_all_motor\": \"Dừng động cơ kết nối với cả động cơ L và R.\",\n    \"neobot_set_servo\": \"Các góc trong vòng 0 - 180 độ khi kết nối động cơ servo đến OUT1 - OUT3 có thể được điều chỉnh\",\n    \"neobot_set_output\": \"Điện áp đầu ra khi kết nối khối ánh sáng và mạch điện tử đến OUT1 -. OUT3 có thể được thiết lập.</br>0 chỉ 0V, và 1 ~ 255 chỉ 2.4 ~ 4.96V.\",\n    \"neobot_set_fnd\": \"Số từ 0 đến 99 với FND có thể được chỉ định.\",\n    \"neobot_set_fnd_off\": \"Số ghi trên FND có thể được tắt. \",\n    \"neobot_play_note_for\": \"Ghi chú trong đơn vị nửa cung của giai điệu có thể được chơi bằng cách sử dụng dao động tần số.\",\n    \"rotate_by_angle_dropdown\": \"오브젝트의 방향을 입력한 각도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)\",\n    \"chocopi_control_button\": \"버튼이 눌리면 참이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_control_event\": \"버튼을 누르거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_control_joystick\": \"조이스틱 좌우, 상하, 볼륨의 값은 0~4095까지 입니다.<br/>따라서 2047 근처가 중간이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_dc_motor\": \"DC모터 모듈에는 직류전동기 두개를 연결 할 수 있습니다.<br/> 직류 전동기는 최대 5V로 동작하게 됩니다.<br/>값은 100이 최대(100%)이고 음수를 넣으면 반대 방향으로 회전합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_led\": \"LED번호는 LED블록에 연결된 순서이고 1번부터 시작합니다.<br/>RGB값은 0~255사이의 값입니다.<br/>빨강(Red),녹색(Green), 파랑(Blue)순서로  입력합니다.<br/>밝은 LED를 직접보면 눈이 아프니까 값을 0~5정도로 씁니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_motion_photogate_event\": \"포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br/>빛센서를 물체로 가리거나 치우면 시작되는 엔트리 블록을 연결합니다<br/>모션 모듈에는 포토게이트 2개를 연결할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_motion_photogate_status\": \"포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>물체가 빛센서를 가리면 참</b>이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_motion_photogate_time\": \"포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>이 블록은 물체가 빛센서를 가리거나 벗어난 시간을 가집니다.<br/>1/10000초까지 측정할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_motion_value\": \"모션 모듈에는 3개의 적외선 센서가 있습니다.<br/>0~4095사이의 값을 가질 수 있는데 물체가 빛을 많이 반사할 수록 작은 값을 가집니다. <br/>거리를 대략적으로 측정할 수 있습니다. <br/>가속도와 각가속도 값의 범위는 -32768~32767 까지입니다.<br/>가속도를 이용해서 센서의 기울기를 측정할 수도 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_sensor\": \"온도 값은 섭씨 온도입니다.<br/>습도 값은 백분율로 나타낸 상대습도 값입니다.<br/>빛은 로그스케일로 0~4095사이입니다.<br/>아날로그 값은 0~4095사이입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_servo_motor\": \"서보모터 모듈에는 4개의 서보모터를 연결 할 수 있습니다.<br/>서보모터는 5V로 동작하게 됩니다.<br/>각도는 0~200도까지 지정할 수 있습니다.<br/>연속회전식 서보모터를 연결하면 각도에 따라 속도가 변하게됩니다.<br/>90~100 사이가 중간값입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_touch_event\": \"터치 모듈에는 1~12번의 연결 패드가 있습니다. <br/>만지거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_touch_status\": \"터치 모듈의 패드를 만지면 참이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"chocopi_touch_value\": \"터치패드에 연결된 물체의 전기용량이 커지면 값이 작아집니다.<br/>여러 명이 손잡고 만지면 더 작은 값이 됩니다.<br/>전기용량이란 물체에 전기를 띈 입자를 얼마나 가지고 있을 수 있는 지를 말합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.\",\n    \"boolean_and_or\": \"그리고 : 두 판단이 모두 참인 경우 ‘참’으로 판단합니다.<br>또는 : 두 판단 중 하나라도 참이 있는 경우 ‘참’으로 판단합니다.\",\n    \"check_weather\": \"<br>선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈\",\n    \"check_finedust\": \"<br>선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨\",\n    \"get_weather_data\": \"<br>선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)\",\n    \"get_current_weather_data\": \"<br>현재 선택한 지역의 날씨 정보값(기온, 미세먼지농도)입니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 정보: (기온(℃)), 미세먼지농도(㎍)\",\n    \"get_today_temperature\": \"<br>오늘 선택한 지역과 시간대의 기온을 의미합니다.<br> * 옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 시간대: 00, 03, 06, 09, 12, 15, 18, 21\",\n    \"check_city_weather\": \"<br>선택한 날짜와 지역의 날씨 정보를 실제 날씨 상태와 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 날씨: 맑음, 구름조금, 구름많음, 흐림, 비, 진눈깨비, 눈\",\n    \"check_city_finedust\": \"<br>선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.<br> * 옵션<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 미세먼지 등급: 좋음, 보통, 나쁨, 매우나쁨\",\n    \"get_city_weather_data\": \"<br>선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.<br> * 옵션<br> 날짜: 어제, 오늘, 내일, 모레, 3일 후, 4일 후, 5일 후, 6일 후<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 정보: 최저기온(℃), 최고기온(℃), 습도(%), 강수량(mm), 강수확률(%), 풍속(m/s)\",\n    \"get_current_city_weather_data\": \"<br>현재 선택한 지역의 날씨 정보값(기온, 미세먼지농도)입니다.<br> * 옵션<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 정보: (기온(℃)), 미세먼지농도(㎍)\",\n    \"get_today_city_temperature\": \"<br>오늘 선택한 지역과 시간대의 기온을 의미합니다.<br> * 옵션<br> 시도: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북 <br> 시군구: 시도별로 다름<br> 시간대: 00, 03, 06, 09, 12, 15, 18, 21\",\n    \"count_festival\": \"<br>선택한 날짜와 지역에서 열리는 행사의 수입니다.<br> *옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 행사일: 1월~12월\",\n    \"get_festival_info\": \"<br>선택한 날짜와 지역에서 열리는 행사에 대한 정보입니다.<br> *옵션<br> 지역: 서울, 강원, 경기, 경남, 경북, 광주, 대구, 대전, 부산, 세종, 울산, 인천, 전남, 전북, 제주, 충남, 충북<br> 행사일: 1월~12월<br> 정보: 제목, 지역, 시작일, 종료일, 주소, 개요, 홈페이지\",\n    \"get_translated_string\": \"The number of events held on the selected date and region.\",\n    \"check_language\": \"Reports the information(Title, area, start date, end date, address, overview, homepage) about events held on the selected date and region.\",\n    \"count_disaster_behavior\": \"<br>The number of behavior-guideline's when selected natural disaster occurs.\",\n    \"get_disaster_behavior\": \"<br>Reports the information about behavior-guidelines when selected natural disaster occurs.\",\n    \"count_lifeSafety_behavior\": \"<br>The number of behavior-guideline's when selected life problem occurs.\",\n    \"get_lifeSafety_behavior\": \"<br>Reports the information about behavior-guidelines when selected life problem occurs.\",\n    \"read_text\": \"Read the entered text in setted voice.\",\n    \"set_tts_property\": \"Set the selected voice to selected speed and selected pitch. <br> The selected voice will be set up to selected speed and selected pitch.\",\n    \"read_text_wait_with_block\": \"Read the entered text in setted voice then the next block runs after the reading finished.\",\n    \"check_microphone\": \"Check whether microphone is connected with the computer.\",\n    \"speech_to_text_convert\": \"Converts voice input into the microphone into text.\",\n    \"get_microphone_volume\": \"Reports the volume of sound input to the microphone.\",\n    \"speech_to_text_get_value\": \"Reports the value that converted speech to text. If no voice is input or an error occurs during voice recognition, it will have 0 value.\",\n    \"video_draw_webcam\": \"Show or hide the video screen.\",\n    \"video_check_webcam\": \"Check whether video is connected with the computer.\",\n    \"video_set_camera_option\": \"Set the selected effect to the video screen by the input value.\",\n    \"video_flip_camera\": \"Flips the video screen horizontally or vertically.\",\n    \"video_toggle_model\": \"Start or stop the selected recognition model. Face Recognition: Recognizes a person's face to know where the eyes, nose, mouth, and ear are located, or the expected gender, age, and emotion. Human Recognition: Recognizes a person's body to know where each part is located Object Recognition: Shows the recognized object type. (Person or thing)\",\n    \"video_toggle_ind\": \"Show location and index of the detected humans / faces / objects on the screen.\",\n    \"video_number_detect\": \"Reports number of people / faces /objects detected on the video screen.\",\n    \"video_detected_face_info\": \"Reports the estimated value of the selected face area among the faces in the input order. If it is not recognized, it is outputted as 0 unconditionally. (Gender, Age, Emotion)\",\n    \"video_motion_value\": \"Reports the motion or direction value detected on the selected object or screen.\",\n    \"video_face_part_coord\": \"Reports the position value of the selected face area among the faces in the input order. If it is not recognized, it is outputted as 0 unconditionally. (Left eye, Right eye, Nose, Left mouse, Right mouse, Upper Lip, Lower Lip)\",\n    \"video_body_part_coord\": \"Reports number of human detected on the video screen. (Face, Right shoulder, Right elbow, Right wrist, Left shoulder, Left elbow, Left wrist, Right hip, Right knee, Right ankle, Left hip, Left knee, Left ankle)\",\n    \"append_row_to_table\": \"Adds a row(col) to the end location of the selected table.\",\n    \"insert_row_to_table\": \"Inserts a row(col) to the location of the input value on the selected table.\",\n    \"delete_row_from_table\": \"Deletes the row(col) at the location of input value from the selected table.\",\n    \"set_value_from_table\": \"Replaces value of selected attribute at the location of the input value to the input value.\",\n    \"get_table_count\": \"Reports the number of rows or attribute on the selected table.\",\n    \"get_value_from_table\": \"Reports the value of selected attribute at the location of the input value from the selected table.\",\n    \"calc_values_from_table\": \"Reports calculated value of the selected attributes in the selected table. (sum, maximum, minimum, average, standard deviation)\",\n    \"open_table_chart\": \"Open the chart of the selected table.\",\n    \"close_table_chart\": \"Close the table chart.\",\n    \"get_coefficient\": \"Correlation coefficient between two attributes in the selected table. The closer the correlation coefficient is to 1(-1), the stronger the positive (negative) linear correlation.\"\n};\nLang.Category = {\n    \"entrybot_friends\": \"Entrybot friends\",\n    \"people\": \"People\",\n    \"animal\": \"Animal\",\n    \"animal_flying\": \"Flying\",\n    \"animal_land\": \"Land\",\n    \"animal_water\": \"Water\",\n    \"animal_others\": \"Others\",\n    \"plant\": \"Plant\",\n    \"plant_flower\": \"Flowers\",\n    \"plant_grass\": \"Grass\",\n    \"plant_tree\": \"Tree\",\n    \"plant_others\": \"Others\",\n    \"vehicles\": \"Vehicles\",\n    \"vehicles_flying\": \"Flying\",\n    \"vehicles_land\": \"Land\",\n    \"vehicles_water\": \"Water\",\n    \"vehicles_others\": \"Others\",\n    \"architect\": \"Building\",\n    \"architect_building\": \"Structure\",\n    \"architect_monument\": \"Monument\",\n    \"architect_others\": \"Others\",\n    \"food\": \"Food\",\n    \"food_vegetables\": \"Fruits/Vegetables\",\n    \"food_meat\": \"Meat\",\n    \"food_drink\": \"Drink\",\n    \"food_others\": \"Others\",\n    \"environment\": \"Environment\",\n    \"environment_nature\": \"Nature\",\n    \"environment_space\": \"Space\",\n    \"environment_others\": \"Others\",\n    \"stuff\": \"Things\",\n    \"stuff_living\": \"Living\",\n    \"stuff_hobby\": \"Hobby\",\n    \"stuff_others\": \"Others\",\n    \"fantasy\": \"Fantasy\",\n    \"interface\": \"Interface\",\n    \"interface_website\": \"Website\",\n    \"interface_game\": \"Game\",\n    \"interface_others\": \"Others\",\n    \"background\": \"Background\",\n    \"background_outdoor\": \"Outdoor\",\n    \"background_indoor\": \"Indoor\",\n    \"background_nature\": \"Nature\",\n    \"background_others\": \"Others\"\n};\nLang.Device = {\n    \"arduino\": \"arduino\",\n    \"hamster\": \"hamster\",\n    \"roboid\": \"roboid\",\n    \"turtle\": \"turtle\",\n    \"albert\": \"albert\",\n    \"robotis_carCont\": \"\",\n    \"robotis_openCM70\": \"\",\n    \"sensorBoard\": \"Entry Sensor Board\",\n    \"trueRobot\": \"TrueTrueRobot\",\n    \"CODEino\": \"CODEino\",\n    \"bitbrick\": \"bitbrick\",\n    \"creamo\": \"creamo\",\n    \"playcode\": \"playcode\",\n    \"funboard\": \"funboard\",\n    \"bitBlock\": \"bitBlock\",\n    \"xbot_epor_edge\": \"XBOT\",\n    \"dplay\": \"DPLAY\",\n    \"iboard\": \"iboard\",\n    \"nemoino\": \"NEMOino\",\n    \"ev3\": \"EV3\",\n    \"robotori\": \"robotori\",\n    \"smartBoard\": \"smartBoard\",\n    \"chocopi\": \"ChocoPi\",\n    \"rokoboard\": \"rokoboard\",\n    \"altino\": \"알티노\",\n    \"mechatro\": \"mechatro\"\n};\nLang.General = {\n    \"turn_on\": \"Bật\",\n    \"turn_off\": \"Tắt\",\n    \"left\": \"Bên trái\",\n    \"right\": \"Bên phải\",\n    \"param_string\": \"chuỗi\",\n    \"both\": \"Hai bên\",\n    \"transparent\": \"transparent\",\n    \"black\": \"black\",\n    \"brown\": \"brown\",\n    \"red\": \"Đỏ\",\n    \"yellow\": \"Vàng\",\n    \"green\": \"Xanh lá cây\",\n    \"skyblue\": \"Xanh da trời\",\n    \"blue\": \"Xanh dương\",\n    \"purple\": \"Tím\",\n    \"white\": \"Trắng\",\n    \"note_c\": \"Đô\",\n    \"note_d\": \"Rê\",\n    \"note_e\": \"Mi\",\n    \"note_f\": \"Pha\",\n    \"note_g\": \"Son\",\n    \"note_a\": \"La\",\n    \"note_b\": \"Si\",\n    \"questions\": \"Question\",\n    \"clock\": \"clock\",\n    \"counter_clock\": \"counterclock\",\n    \"font_size\": \"font size\",\n    \"second\": \"&quot;\",\n    \"alert_title\": \"Alert\",\n    \"confirm_title\": \"Confirm\",\n    \"update_title\": \"Alert\",\n    \"recent_download\": \"Download\",\n    \"recent_download2\": \"Download the latest version\",\n    \"latest_version\": \"You are running the latest version.\",\n    \"dont_show_again\": \"Do not show this again\"\n};\nLang.Fonts = {\n    \"jeju_hallasan\": \"Jeju Hallasan\",\n    \"gothic_coding\": \"Gothic Coding\",\n    \"batang\": \"Batang\",\n    \"gothic\": \"Nanum Gothic\",\n    \"myeongjo\": \"Nanum Myeongjo\",\n    \"pen_script\": \"Nanum Pen Script\",\n    \"square_round\": \"Nanum SquareRound\",\n    \"jalnan\": \"jalnan\",\n    \"designhouse\": \"designhouse\",\n    \"malssami815\": \"Malssami815\",\n    \"dunggeunmo\": \"DungGeunMo\",\n    \"hs_bombaram\": \"HS Bombaram\",\n    \"yisunshin\": \"YiSunShin\",\n    \"goyang\": \"Goyang\",\n    \"flower_road\": \"SangSangFlowerRoad\",\n    \"uhbeemysen\": \"UhBeemysen\",\n    \"sd_comic_stencil\": \"Sandoll Comicstencil\",\n    \"sd_childfundkorea\": \"Sandoll Childfundkorea\",\n    \"sd_cinema_theater\": \"Sandoll Cinema Theater\",\n    \"sd_mapssi\": \"Sandoll Mapssi\",\n    \"sd_shabang\": \"Sandoll Shabang\",\n    \"sd_woodcarving\": \"Sandoll Woodcarving\",\n    \"sd_yongbi\": \"Sandoll Yongbi\"\n};\nLang.Hw = {\n    \"note\": \"Nốt nhạc\",\n    \"leftWheel\": \"Bánh xe trái\",\n    \"rightWheel\": \"Bánh xe phải\",\n    \"leftEye\": \"Mắt trái\",\n    \"rightEye\": \"Mắt phải\",\n    \"led\": \"Đèn LED\",\n    \"led_en\": \"LED\",\n    \"body\": \"Cơ thể\",\n    \"front\": \"Phía trước\",\n    \"port_en\": \"port\",\n    \"port_ko\": \"\",\n    \"sensor\": \"cảm biến\",\n    \"light\": \"ánh sáng\",\n    \"temp\": \"temp\",\n    \"switch_\": \"sw_\",\n    \"right_ko\": \"\",\n    \"right_en\": \"R\",\n    \"left_ko\": \"\",\n    \"left_en\": \"L\",\n    \"up_ko\": \"\",\n    \"up_en\": \"U\",\n    \"down_ko\": \"\",\n    \"down_en\": \"D\",\n    \"output\": \"đầu ra\",\n    \"left\": \"bên trái\",\n    \"right\": \"bên phải\",\n    \"sub\": \"servo\",\n    \"motor\": \"motor\",\n    \"\": \"\",\n    \"buzzer\": \"Chuông\",\n    \"IR\": \"infrared\",\n    \"acceleration\": \"acceleration\",\n    \"analog\": \"analog\",\n    \"angular_acceleration\": \"angular acceleration\",\n    \"button\": \"button\",\n    \"humidity\": \"humidity\",\n    \"joystick\": \"joystick\",\n    \"port\": \"port\",\n    \"potentiometer\": \"potentiometer\",\n    \"servo\": \"servo\"\n};\nLang.template = {\n    \"albert_hand_found\": \"tìm tay?\",\n    \"albert_is_oid_value\": \"giá trị %1 là oid %2\",\n    \"albert_value\": \"%1\",\n    \"albert_move_forward_for_secs\": \"di chuyển về phía trước %1 giây %2\",\n    \"albert_move_backward_for_secs\": \"di chuyển về phía sau %1 giây %2\",\n    \"albert_turn_for_secs\": \"quay lại %1  %2 giây %3\",\n    \"albert_change_both_wheels_by\": \"thay đổi bánh xe bên trái:%1 phải: %2 %3\",\n    \"albert_set_both_wheels_to\": \"thiết lập bánh xe bên trái:%1 phải: %2 %3\",\n    \"albert_change_wheel_by\": \"thay đổi %1 bằng %2 %3\",\n    \"albert_set_wheel_to\": \"thiết lập %1 thành %2 %3\",\n    \"albert_stop\": \"dừng lại %1\",\n    \"albert_set_pad_size_to\": \"thiết lập kích thước pad chiều rộng %1 chiều cao: %2 %3\",\n    \"albert_move_to_x_y_on_board\": \"di chuyển đến x: %1 y: %2 trên bảng %3 \",\n    \"albert_set_orientation_on_board\": \"thiết lập định hướng để %1 trên bảng %2\",\n    \"albert_set_eye_to\": \"thiết lập %1 thành %2 %3\",\n    \"albert_clear_eye\": \"xóa %1 %2\",\n    \"albert_body_led\": \"thân LED %1 %2\",\n    \"albert_front_led\": \"phía trước LED %1 %2\",\n    \"albert_beep\": \"tiếng bíp bíp %1\",\n    \"albert_change_buzzer_by\": \"thay đổi chuông bằng %1 %2\",\n    \"albert_set_buzzer_to\": \"thiết lập chuông bằng %1 %2\",\n    \"albert_clear_buzzer\": \"xóa chuông %1\",\n    \"albert_play_note_for\": \"phát âm %1 %2 cho %3 nhịp %4\",\n    \"albert_rest_for\": \"nghỉ %1 nhịp %2\",\n    \"albert_change_tempo_by\": \"thay đổi nhịp độ bằng %1 %2\",\n    \"albert_set_tempo_to\": \"thiết lập nhịp độ bằng %1 bpm %2\",\n    \"albert_move_forward\": \"di chuyển về phía trước %1\",\n    \"albert_move_backward\": \"di chuyển về phía sau %1\",\n    \"albert_turn_around\": \"quay về %1 %2\",\n    \"albert_set_led_to\": \"thiết lập %1 %2 %3\",\n    \"albert_clear_led\": \"xóa %1 %2\",\n    \"albert_change_wheels_by\": \"%1 %2 %3\",\n    \"albert_set_wheels_to\": \"%1 %2 %3\",\n    \"arduino_text\": \"%1\",\n    \"arduino_get_sensor_number\": \"%1  \",\n    \"arduino_get_port_number\": \"%1  \",\n    \"arduino_get_digital_toggle\": \"%1  \",\n    \"arduino_get_pwm_port_number\": \"%1  \",\n    \"arduino_get_number_sensor_value\": \"giá trị biến số Analog %1\",\n    \"arduino_ext_get_analog_value\": \"giá trị biến số Analog %1\",\n    \"arduino_ext_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"arduino_ext_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"arduino_ext_toggle_led\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"arduino_ext_digital_pwm\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"arduino_ext_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"arduino_ext_set_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"arduino_ext_get_digital\": \"giá trị cảm biến kỹ thuật số %1\",\n    \"blacksmith_get_analog_value\": \"Read analog %1 pin sensor value\",\n    \"blacksmith_get_analog_mapping\": \"Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5\",\n    \"blacksmith_get_digital_bluetooth\": \"Bluetooth RX 2 value\",\n    \"blacksmith_get_digital_ultrasonic\": \"Read ultrasonic Trig %1 Echo %2 sensor value\",\n    \"blacksmith_get_digital_toggle\": \"Digital %1 pin sensor value\",\n    \"blacksmith_set_digital_toggle\": \"Digital %1 pin %2 %3\",\n    \"blacksmith_set_digital_pwm\": \"Digital pwm %1 Pin %2 %3\",\n    \"blacksmith_set_digital_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"blacksmith_set_digital_buzzer\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"blacksmith_set_digital_lcd\": \"LCD %1 line %2 appear %3\",\n    \"blacksmith_set_digital_bluetooth\": \"Bluetooth TX 3 Pin %1 data send %2\",\n    \"dplay_get_number_sensor_value\": \"giá trị cảm biến Analog %1\",\n    \"nemoino_get_number_sensor_value\": \"giá trị cảm biến Analog %1\",\n    \"sensorBoard_get_number_sensor_value\": \"giá trị cảm biến Analog %1\",\n    \"truetrue_get_accsensor\": \"3-AXIS Accelerometer %1 Sensor value\",\n    \"truetrue_get_bottomcolorsensor\": \"Bottom Color %1 Sensor value\",\n    \"truetrue_get_frontcolorsensor\": \"Front Color %1 Sensor value\",\n    \"truetrue_get_linesensor\": \"Line %1 Sensor value\",\n    \"truetrue_get_proxisensor\": \"Proximity %1 Sensor value\",\n    \"truetrue_set_colorled\": \"Set Color LED Red %1  Green %2 Blue %3 %4\",\n    \"truetrue_set_dualmotor\": \"Set DC motor left %1  right %2 during %3 seconds %4\",\n    \"truetrue_set_led_colorsensor\": \"LED for %1 color sensor %2 %3\",\n    \"truetrue_set_led_linesensor\": \"LED for line sensor %1 %2\",\n    \"truetrue_set_led_proxi\": \"LED for %1 proximity sensor %2 %3\",\n    \"truetrue_set_linetracer\": \"Line tracing mode %1 %2\",\n    \"truetrue_set_singlemotor\": \"Set DC motor %1  speed %2 %3\",\n    \"CODEino_get_number_sensor_value\": \"giá trị cảm biến Analog %1\",\n    \"ardublock_get_number_sensor_value\": \"giá trị cảm biến Analog %1\",\n    \"arduino_get_digital_value\": \"giá trị cảm biến kỹ thuật số %1\",\n    \"dplay_get_digital_value\": \"giá trị cảm biến kỹ thuật số %1\",\n    \"nemoino_get_digital_value\": \"giá trị cảm biến kỹ thuật số %1\",\n    \"sensorBoard_get_digital_value\": \"giá trị cảm biến kỹ thuật số %1\",\n    \"CODEino_get_digital_value\": \"giá trị cảm biến kỹ thuật số %1\",\n    \"CODEino_set_digital_value\": \"Digital %1 Pin %2 %3\",\n    \"CODEino_set_pwm_value\": \"Digital %1 Pin %2 %3\",\n    \"ardublock_get_digital_value\": \"giá trị cảm biến kỹ thuật số %1\",\n    \"arduino_toggle_led\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"dplay_toggle_led\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"nemoino_toggle_led\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"sensorBoard_toggle_led\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"CODEino_toggle_led\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"arduino_toggle_pwm\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"dplay_toggle_pwm\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"nemoino_toggle_pwm\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"sensorBoard_toggle_pwm\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"CODEino_toggle_pwm\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"ardublock_toggle_pwm\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"arduino_convert_scale\": \"bản đồ giá trị từ %1 %2 ~ %3 đến %4 %5\",\n    \"dplay_convert_scale\": \"bản đồ giá trị từ %1 %2 ~ %3 đến %4 %5\",\n    \"nemoino_convert_scale\": \"bản đồ giá trị từ %1 %2 ~ %3 đến %4 %5\",\n    \"sensorBoard_convert_scale\": \"bản đồ giá trị từ %1 %2 ~ %3 đến %4 %5\",\n    \"CODEino_convert_scale\": \"bản đồ giá trị từ %1 %2 ~ %3 đến %4 %5\",\n    \"CODEino_set_rgb_value\": \"Set color LED %1 by %2 %3\",\n    \"CODEino_set_rgb_add_value\": \"Add color LED %1 by %2 %3\",\n    \"CODEino_set_rgb_off\": \"Turn off LED %1\",\n    \"CODEino_set__led_by_rgb\": \"Turn on color LED, Red %1 Green %2 Blue %3 %4\",\n    \"CODEino_rgb_set_color\": \"Select %1 for color LED %2\",\n    \"CODEino_led_by_value\": \"Turn on LED %1\",\n    \"ardublock_convert_scale\": \"bản đồ giá trị từ %1 %2 ~ %3 đến %4 %5\",\n    \"joystick_get_number_sensor_value\": \"giá trị cảm biến Analog %1\",\n    \"joystick_get_digital_value\": \"giá trị cảm biến kỹ thuật số %1\",\n    \"joystick_toggle_led\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"joystick_toggle_pwm\": \"kỹ thuật số %1 Pin %2 %3\",\n    \"joystick_convert_scale\": \"bản đồ giá trị từ %1 %2 ~ %3 đến %4 %5\",\n    \"sensorBoard_get_named_sensor_value\": \"giá trị cảm biến %1\",\n    \"sensorBoard_is_button_pressed\": \"nhấn nút %1?\",\n    \"sensorBoard_led\": \"%1 LED %2 %3\",\n    \"arduino_download_connector\": \"%1\",\n    \"download_guide\": \"%1\",\n    \"arduino_download_source\": \"%1\",\n    \"arduino_connected\": \"%1\",\n    \"arduino_connect\": \"%1\",\n    \"arduino_reconnect\": \"%1\",\n    \"CODEino_get_sensor_number\": \"%1\",\n    \"CODEino_get_named_sensor_value\": \"giá trị biến số %1\",\n    \"CODEino_get_sound_status\": \"âm thanh %1\",\n    \"CODEino_get_light_status\": \"ánh sáng %1\",\n    \"CODEino_is_button_pressed\": \"vận hành %1\",\n    \"CODEino_get_accelerometer_direction\": \"cảm biến gia tốc 3 trục %1\",\n    \"CODEino_get_accelerometer_value\": \"cảm biến gia tốc 3 trục %1-giá trị trục\",\n    \"CODEino_get_analog_value\": \"Analog %1 Sensor value\",\n    \"iboard_button\": \"Pressed %1 button?\",\n    \"iboard_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"iboard_get_analog_value\": \"Analog %1 Sensor value  \",\n    \"iboard_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"iboard_get_digital\": \"Digital %1 Sensor value  \",\n    \"iboard_led\": \"Digital %1 Pin %2 %3\",\n    \"iboard_motor\": \"Digital %1 Pin %2 %3\",\n    \"iboard_pwm_led\": \"Digital %1 Pin %2 %3\",\n    \"iboard_rgb_led\": \" %1 LED %2 %3\",\n    \"iboard_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"iboard_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"bitbrick_is_touch_pressed\": \"nhấn nút %1 %2?\",\n    \"bitbrick_is_sensor_value_compare\": \"nhấn nút %1 %2 %3?\",\n    \"bitbrick_sensor_value\": \"giá trị %1\",\n    \"bitbrick_convert_scale\": \"đổi giá trị %1 từ %2~%3 đến %4~%5\",\n    \"bitbrick_turn_on_color_led_by_rgb\": \"mở màu LED R%1 G %2 B %3 %4\",\n    \"bitbrick_turn_on_color_led_by_picker\": \"chọn %1 cho màu LED %2\",\n    \"bitbrick_turn_on_color_led_by_value\": \"mở màu LED, chọn %1 %2\",\n    \"bitbrick_turn_off_color_led\": \"tắt màu LED %1\",\n    \"bitbrick_buzzer\": \"âm buzz %1 giây %2\",\n    \"bitbrick_servomotor_angle\": \"động cơ servo %1 góc độ %2 %3\",\n    \"bitbrick_dc_direction_speed\": \"động cơ DC %1 %2 tốc độ phương hướng %3 %4\",\n    \"bitbrick_dc_speed\": \"động cơ DC %1 tốc độ %2 %3\",\n    \"bitbrick_turn_off_all_motors\": \"tắt tất cả các động cơ %1\",\n    \"start_drawing\": \"bắt đầu vẽ %1\",\n    \"stop_drawing\": \"ngừng vẽ %1\",\n    \"set_color\": \"thiết lập màu cọ bằng %1 %2\",\n    \"set_random_color\": \"thiết lập màu cọ ngẫu nhiên %1\",\n    \"change_thickness\": \"Thay đổi độ dày bằng %1 %2\",\n    \"set_thickness\": \"thiết lập độ dày %1 %2\",\n    \"change_opacity\": \"thay đổi độ mờ bằng %1 % %2\",\n    \"set_opacity\": \"thiết lập độ mờ bằng %1 % %2\",\n    \"brush_erase_all\": \"xóa hết cọ %1\",\n    \"brush_stamp\": \"đóng dấu %1\",\n    \"change_brush_transparency\": \"thay đổi độ trong suốt bằng %1 % %2\",\n    \"set_brush_tranparency\": \"thiết lập độ trong suốt của cọ bằng %1 % %2\",\n    \"number\": \"%1\",\n    \"angle\": \"%1\",\n    \"color\": \"%1\",\n    \"get_x_coordinate\": \"%1\",\n    \"get_y_coordinate\": \"%1\",\n    \"get_angle\": \"%1\",\n    \"get_rotation_direction\": \"%1  \",\n    \"distance_something\": \"%1 %2 %3\",\n    \"coordinate_mouse\": \"%1 %2 %3\",\n    \"coordinate_object\": \"%1 %2 %3 %4\",\n    \"calc_basic\": \"%1 %2 %3\",\n    \"calc_plus\": \"%1 %2 %3\",\n    \"calc_minus\": \"%1 %2 %3\",\n    \"calc_times\": \"%1 %2 %3\",\n    \"calc_divide\": \"%1 %2 %3\",\n    \"calc_mod\": \"%1 %2 %3\",\n    \"calc_share\": \"%1 %2 %3\",\n    \"calc_operation\": \"%1 %2 %3 %4\",\n    \"calc_rand\": \"%1 %2 %3 %4 %5\",\n    \"get_date\": \"%1 %2 %3\",\n    \"get_sound_duration\": \"%1 %2 %3\",\n    \"get_user_name\": \"User ID\",\n    \"get_nickname\": \"Nickname\",\n    \"reset_project_timer\": \"%1\",\n    \"set_visible_project_timer\": \"%1 %2 %3 %4\",\n    \"timer_variable\": \"%1 %2\",\n    \"get_project_timer_value\": \"%1 %2\",\n    \"char_at\": \"%1 %2 %3 %4 %5\",\n    \"length_of_string\": \"%1 %2 %3\",\n    \"substring\": \"%1 %2 %3 %4 %5 %6 %7\",\n    \"replace_string\": \"%1 %2 %3 %4 %5 %6 %7\",\n    \"change_string_case\": \"%1 %2 %3 %4 %5 \",\n    \"index_of_string\": \"%1 %2 %3 %4 %5\",\n    \"combine_something\": \"%1 %2 %3 %4 %5\",\n    \"get_sound_volume\": \"%1 %2\",\n    \"quotient_and_mod\": \"%1 %6 %3 %2 %5 %4\",\n    \"choose_project_timer_action\": \"%1 %2 %3 %4 \",\n    \"wait_second\": \"chờ %1 giây %2\",\n    \"repeat_basic\": \"lặp lại %1 lần %2\",\n    \"hidden_loop\": \"lặp lại %1 lần %2\",\n    \"repeat_inf\": \"lặp lại liên tục %1\",\n    \"stop_repeat\": \"ngừng lặp lại %1\",\n    \"wait_until_true\": \"chờ đến %1 %2\",\n    \"_if\": \"nếu %1 thì %2\",\n    \"if_else\": \"nếu %1 thì %2 %3 hoặc\",\n    \"create_clone\": \"tạo bản sao %1 của %2\",\n    \"delete_clone\": \"Loại bỏ bản sao này %1\",\n    \"when_clone_start\": \"%1 khi bản sao được loại bỏ\",\n    \"stop_run\": \"đóng chương trình %1\",\n    \"repeat_while_true\": \"lặp lại %2 %1 %3\",\n    \"stop_object\": \"dừng lại %1 %2\",\n    \"restart_project\": \"khởi động lại dự án %1\",\n    \"remove_all_clones\": \"xóa tất cả các bản sao %1\",\n    \"functionAddButton\": \"%1\",\n    \"function_field_label\": \"%1%2\",\n    \"function_field_string\": \"%1%2\",\n    \"function_field_boolean\": \"%1%2\",\n    \"function_param_string\": \"ký tự/số\",\n    \"function_param_boolean\": \"giá trị đánh giá\",\n    \"function_create\": \"xác định chức năng %1 %2\",\n    \"function_general\": \"chức năng %1\",\n    \"expansionBlockAddButton\": \"%1\",\n    \"aiUtilizeBlockAddButton\": \"%1\",\n    \"aiUtilizeModelTrainButton\": \"%1\",\n    \"weather_title\": \"%1\",\n    \"check_weather\": \"%1 %2's weather is %3?\",\n    \"check_finedust\": \"Current %1's fine dust grade is %2?\",\n    \"get_weather_data\": \"%1 %2's %3\",\n    \"get_current_weather_data\": \"Current %1's %2\",\n    \"get_today_temperature\": \"Today %1's %2h temperature(℃)\",\n    \"check_city_weather\": \"%1 %2 %3's weather is %4?\",\n    \"check_city_finedust\": \"Current %1 %2's fine dust grade is %3?\",\n    \"get_city_weather_data\": \"%1 %2 %3's %4\",\n    \"get_current_city_weather_data\": \"Current %1 %2's %3\",\n    \"get_today_city_temperature\": \"Today %1 %2's %3h temperature(℃)\",\n    \"translate_title\": \"%1\",\n    \"get_translated_string\": \"Translate %1 %2 into %3\",\n    \"check_language\": \"language of %1\",\n    \"festival_title\": \"%1\",\n    \"count_festival\": \"%1 %2's number of events\",\n    \"get_festival_info\": \"%4 of item %3 of event in %1 %2\",\n    \"behaviorConductDisaster_title\": \"%1\",\n    \"count_disaster_behavior\": \"%1 %2 behavior-guidelines's number\",\n    \"get_disaster_behavior\": \"value of item %3 of %1 %2 behavior-guidelines\",\n    \"behaviorConductLifeSafety_title\": \"%1\",\n    \"count_lifeSafety_behavior\": \"%1 %2 behavior-guidelines's number\",\n    \"get_lifeSafety_behavior\": \"value of item %3 of %1 how to %2\",\n    \"tts_title\": \"%1\",\n    \"audio_title\": \"%1\",\n    \"video_title\": \"%1\",\n    \"read_text\": \"read %1 %2\",\n    \"set_tts_property\": \"set in a %1 voice at %2 speed and %3 pitch %4\",\n    \"read_text_wait_with_block\": \"read %1 and wait %2\",\n    \"load_expansion_block\": \"add\",\n    \"load_ai_utilize_block\": \"Load AI Block\",\n    \"load_ai_utilize_train_block\": \"Train Model\",\n    \"expansion_block_descriptions\": \"The expansion block works normally when the Internet is connected.\",\n    \"aiUtilize_block_descriptions\": \"The A.I. Utilization block works normally when the Internet is connected.\",\n    \"weather_title_text\": \"weather\",\n    \"translate_title_text\": \"translate\",\n    \"festival_title_text\": \"festival\",\n    \"audio_title_text\": \"Audio Sensing\",\n    \"check_microphone\": \"Connected with microphone?\",\n    \"get_microphone_volume\": \"Microphone volume\",\n    \"speech_to_text_convert\": \"Recognize the voice %1\",\n    \"speech_to_text_get_value\": \"Text Value Converted from Speech\",\n    \"video_title_text\": \"Video Detection\",\n    \"video_draw_webcam\": \"%1 the video screen\",\n    \"video_check_webcam\": \"connected with video?\",\n    \"video_set_camera_opacity_option\": \"Set video transparency effect to %1 %2\",\n    \"video_flip_camera\": \"Flip video screen %1 %2\",\n    \"video_toggle_model\": \"%1 recognition %2 %3\",\n    \"video_toggle_ind\": \"%2 detected %1 %3\",\n    \"video_number_detect\": \"Number of detected %1\",\n    \"video_detected_face_info\": \"%2 of %1 th face\",\n    \"video_motion_value\": \"Video %2 value on %1\",\n    \"video_face_part_coord\": \"%3 coordinate of %2 in %1 th face\",\n    \"video_body_part_coord\": \"%3 coordinate of %1 th human's %2\",\n    \"behaviorConductDisaster_title_text\": \"desaster\",\n    \"behaviorConductLifeSafety_title_text\": \"lifeSafety\",\n    \"tts_title_text\": \"read\",\n    \"hamster_hand_found\": \"tìm tay?\",\n    \"hamster_value\": \"%1\",\n    \"hamster_move_forward_once\": \"di chuyển về phía trước một lần trên bảng %1\",\n    \"hamster_turn_once\": \"quay lại một lần %1 trên bảng\",\n    \"hamster_move_forward_for_secs\": \"di chuyển về phía trước %1 giây %2\",\n    \"hamster_move_backward_for_secs\": \"di chuyển về phía sau %1 giây %2\",\n    \"hamster_turn_for_secs\": \"quay lại %1  %2 giây %3\",\n    \"hamster_change_both_wheels_by\": \"thay đổi bánh xe bên trái: %1 phải: %2 %3\",\n    \"hamster_set_both_wheels_to\": \"thiết lập bánh xe bên trái: %1 phải: %2 %3\",\n    \"hamster_change_wheel_by\": \"thay đổi %1 bằng %2 %3\",\n    \"hamster_set_wheel_to\": \"thiết lập %1 bằng %2 %3\",\n    \"hamster_follow_line_using\": \"theo dòng %1 bằng cách sử dụng %2 cảm biến sàn %3\",\n    \"hamster_follow_line_until\": \"theo dòng %1 cho đến %2 giao lộ  %3\",\n    \"hamster_set_following_speed_to\": \"thiết lập theo dõi tốc độ %1 %2\",\n    \"hamster_stop\": \"dừng lại %1 \",\n    \"hamster_set_led_to\": \"thiết lập %1 thành %2 %3\",\n    \"hamster_clear_led\": \"xóa %1 %2\",\n    \"hamster_beep\": \"tiếng bíp bíp %1\",\n    \"hamster_change_buzzer_by\": \"thay đổi chuông bằng %1 %2\",\n    \"hamster_set_buzzer_to\": \"thiết lập chuông bằng %1 %2\",\n    \"hamster_clear_buzzer\": \"xóa chuông %1\",\n    \"hamster_play_note_for\": \"phát âm %1 %2 cho %3 nhịp %4\",\n    \"hamster_rest_for\": \"nghỉ %1 nhịp %2\",\n    \"hamster_change_tempo_by\": \"thay đổi nhịp độ bằng %1 %2\",\n    \"hamster_set_tempo_to\": \"thiết lập nhịp độ bằng %1 bpm %2\",\n    \"hamster_set_port_to\": \"thiết lập cổng %1 bằng %2 %3\",\n    \"hamster_change_output_by\": \"thay đổi đầu ra %1 bằng %2 %3\",\n    \"hamster_set_output_to\": \"thiết lập đầu ra %1 thành %2 %3\",\n    \"roboid_hamster_beep\": \"Hamster %1: beep %2\",\n    \"roboid_hamster_change_both_wheels_by\": \"Hamster %1: change wheels by left: %2 right: %3 %4\",\n    \"roboid_hamster_change_buzzer_by\": \"Hamster %1: change buzzer by %2 %3\",\n    \"roboid_hamster_change_output_by\": \"Hamster %1: change output %2 by %3 %4\",\n    \"roboid_hamster_change_tempo_by\": \"Hamster %1: change tempo by %2 %3\",\n    \"roboid_hamster_change_wheel_by\": \"Hamster %1: change %2 wheel by %3 %4\",\n    \"roboid_hamster_clear_buzzer\": \"Hamster %1: clear buzzer %2\",\n    \"roboid_hamster_clear_led\": \"Hamster %1: clear %2 led %3\",\n    \"roboid_hamster_follow_line_until\": \"Hamster %1: follow %2 line until %3 intersection %4\",\n    \"roboid_hamster_follow_line_using\": \"Hamster %1: follow %2 line using %3 floor sensor %4\",\n    \"roboid_hamster_hand_found\": \"Hamster %1: hand found?\",\n    \"roboid_hamster_move_backward_for_secs\": \"Hamster %1: move backward for %2 secs %3\",\n    \"roboid_hamster_move_forward_for_secs\": \"Hamster %1: move forward for %2 secs %3\",\n    \"roboid_hamster_move_forward_once\": \"Hamster %1: move forward once on board %2\",\n    \"roboid_hamster_play_note_for\": \"Hamster %1: play note %2 %3 for %4 beats %5\",\n    \"roboid_hamster_rest_for\": \"Hamster %1: rest for %2 beats %3\",\n    \"roboid_hamster_set_both_wheels_to\": \"Hamster %1: set wheels to left: %2 right: %3 %4\",\n    \"roboid_hamster_set_buzzer_to\": \"Hamster %1: set buzzer to %2 %3\",\n    \"roboid_hamster_set_following_speed_to\": \"Hamster %1: set following speed to %2 %3\",\n    \"roboid_hamster_set_led_to\": \"Hamster %1: set %2 led to %3 %4\",\n    \"roboid_hamster_set_output_to\": \"Hamster %1: set output %2 to %3 %4\",\n    \"roboid_hamster_set_port_to\": \"Hamster %1: set port %2 to %3 %4\",\n    \"roboid_hamster_set_tempo_to\": \"Hamster %1: set tempo to %2 bpm %3\",\n    \"roboid_hamster_set_wheel_to\": \"Hamster %1: set %2 wheel to %3 %4\",\n    \"roboid_hamster_stop\": \"Hamster %1: stop %2\",\n    \"roboid_hamster_turn_for_secs\": \"Hamster %1: turn %2 for %3 secs %4\",\n    \"roboid_hamster_turn_once\": \"Hamster %1: turn %2 once on board %3\",\n    \"roboid_hamster_value\": \"Hamster %1: %2\",\n    \"roboid_turtle_button_state\": \"Turtle %1: button %2 ?\",\n    \"roboid_turtle_change_buzzer_by\": \"Turtle %1: change buzzer by %2 %3\",\n    \"roboid_turtle_change_head_led_by_rgb\": \"Turtle %1: change head led by r: %2 g: %3 b: %4 %5\",\n    \"roboid_turtle_change_tempo_by\": \"Turtle %1: change tempo by %2 %3\",\n    \"roboid_turtle_change_wheel_by\": \"Turtle %1: change %2 wheel by %3 %4\",\n    \"roboid_turtle_change_wheels_by_left_right\": \"Turtle %1: change wheels by left: %2 right: %3 %4\",\n    \"roboid_turtle_clear_head_led\": \"Turtle %1: clear head led %2\",\n    \"roboid_turtle_clear_sound\": \"Turtle %1: clear sound %2\",\n    \"roboid_turtle_cross_intersection\": \"Turtle %1: cross black intersection %2\",\n    \"roboid_turtle_follow_line\": \"Turtle %1: follow %2 line %3\",\n    \"roboid_turtle_follow_line_until\": \"Turtle %1: follow black line until %2 %3\",\n    \"roboid_turtle_follow_line_until_black\": \"Turtle %1: follow %2 line until black %3\",\n    \"roboid_turtle_is_color_pattern\": \"Turtle %1: color pattern %2 %3 ?\",\n    \"roboid_turtle_move_backward_unit\": \"Turtle %1: move backward %2 %3 %4\",\n    \"roboid_turtle_move_forward_unit\": \"Turtle %1: move forward %2 %3 %4\",\n    \"roboid_turtle_pivot_around_wheel_unit_in_direction\": \"Turtle %1: pivot around %2 wheel %3 %4 in %5 direction %6\",\n    \"roboid_turtle_play_note\": \"Turtle %1: play note %2 %3 %4\",\n    \"roboid_turtle_play_note_for_beats\": \"Turtle %1: play note %2 %3 for %4 beats %5\",\n    \"roboid_turtle_play_sound_times\": \"Turtle %1: play sound %2 %3 times %4\",\n    \"roboid_turtle_play_sound_times_until_done\": \"Turtle %1: play sound %2 %3 times until done %4\",\n    \"roboid_turtle_rest_for_beats\": \"Turtle %1: rest for %2 beats %3\",\n    \"roboid_turtle_set_buzzer_to\": \"Turtle %1: set buzzer to %2 %3\",\n    \"roboid_turtle_set_following_speed_to\": \"Turtle %1: set following speed to %2 %3\",\n    \"roboid_turtle_set_head_led_to\": \"Turtle %1: set head led to %2 %3\",\n    \"roboid_turtle_set_head_led_to_rgb\": \"Turtle %1: set head led to r: %2 g: %3 b: %4 %5\",\n    \"roboid_turtle_set_tempo_to\": \"Turtle %1: set tempo to %2 bpm %3\",\n    \"roboid_turtle_set_wheel_to\": \"Turtle %1: set %2 wheel to %3 %4\",\n    \"roboid_turtle_set_wheels_to_left_right\": \"Turtle %1: set wheels to left: %2 right: %3 %4\",\n    \"roboid_turtle_stop\": \"Turtle %1: stop %2\",\n    \"roboid_turtle_touching_color\": \"Turtle %1: touching %2 ?\",\n    \"roboid_turtle_turn_at_intersection\": \"Turtle %1: turn %2 at black intersection %3\",\n    \"roboid_turtle_turn_unit_in_place\": \"Turtle %1: turn %2 %3 %4 in place %5\",\n    \"roboid_turtle_turn_unit_with_radius_in_direction\": \"Turtle %1: turn %2 %3 %4 with radius %5 cm in %6 direction %7\",\n    \"roboid_turtle_value\": \"Turtle %1: %2\",\n    \"turtle_button_state\": \"button %1 ?\",\n    \"turtle_change_buzzer_by\": \"change buzzer by %1 %2\",\n    \"turtle_change_head_led_by_rgb\": \"change head led by r: %1 g: %2 b: %3 %4\",\n    \"turtle_change_tempo_by\": \"change tempo by %1 %2\",\n    \"turtle_change_wheel_by\": \"change %1 wheel by %2 %3\",\n    \"turtle_change_wheels_by_left_right\": \"change wheels by left: %1 right: %2 %3\",\n    \"turtle_clear_head_led\": \"clear head led %1\",\n    \"turtle_clear_sound\": \"clear sound %1\",\n    \"turtle_cross_intersection\": \"cross black intersection %1\",\n    \"turtle_follow_line\": \"follow %1 line %2\",\n    \"turtle_follow_line_until\": \"follow black line until %1 %2\",\n    \"turtle_follow_line_until_black\": \"follow %1 line until black %2\",\n    \"turtle_is_color_pattern\": \"color pattern %1 %2 ?\",\n    \"turtle_move_backward_unit\": \"move backward %1 %2 %3\",\n    \"turtle_move_forward_unit\": \"move forward %1 %2 %3\",\n    \"turtle_pivot_around_wheel_unit_in_direction\": \"pivot around %1 wheel %2 %3 in %4 direction %5\",\n    \"turtle_play_note\": \"play note %1 %2 %3\",\n    \"turtle_play_note_for_beats\": \"play note %1 %2 for %3 beats %4\",\n    \"turtle_play_sound_times\": \"play sound %1 %2 times %3\",\n    \"turtle_play_sound_times_until_done\": \"play sound %1 %2 times until done %3\",\n    \"turtle_rest_for_beats\": \"rest for %1 beats %2\",\n    \"turtle_set_buzzer_to\": \"set buzzer to %1 %2\",\n    \"turtle_set_following_speed_to\": \"set following speed to %1 %2\",\n    \"turtle_set_head_led_to\": \"set head led to %1 %2\",\n    \"turtle_set_head_led_to_rgb\": \"set head led to r: %1 g: %2 b: %3 %4\",\n    \"turtle_set_tempo_to\": \"set tempo to %1 bpm %2\",\n    \"turtle_set_wheel_to\": \"set %1 wheel to %2 %3\",\n    \"turtle_set_wheels_to_left_right\": \"set wheels to left: %1 right: %2 %3\",\n    \"turtle_stop\": \"stop %1\",\n    \"turtle_touching_color\": \"touching %1 ?\",\n    \"turtle_turn_at_intersection\": \"turn %1 at black intersection %2\",\n    \"turtle_turn_unit_in_place\": \"turn %1 %2 %3 in place %4\",\n    \"turtle_turn_unit_with_radius_in_direction\": \"turn %1 %2 %3 with radius %4 cm in %5 direction %6\",\n    \"turtle_value\": \"%1\",\n    \"is_clicked\": \"%1\",\n    \"is_press_some_key\": \"%1 %2\",\n    \"reach_something\": \"%1 %2 %3\",\n    \"boolean_comparison\": \"%1 %2 %3\",\n    \"boolean_equal\": \"%1 %2 %3\",\n    \"boolean_bigger\": \"%1 %2 %3\",\n    \"boolean_smaller\": \"%1 %2 %3\",\n    \"boolean_and_or\": \"%1 %2 %3\",\n    \"boolean_and\": \"%1 %2 %3\",\n    \"boolean_or\": \"%1 %2 %3\",\n    \"boolean_not\": \"%1 %2 %3\",\n    \"is_boost_mode\": \"%1\",\n    \"true_or_false\": \"%1\",\n    \"True\": \"%1\",\n    \"False\": \"%1\",\n    \"boolean_basic_operator\": \"%1 %2 %3\",\n    \"show\": \"hiển thị %1\",\n    \"hide\": \"ẩn %1\",\n    \"dialog_time\": \"nói %1 cho %2 giây %3 %4\",\n    \"dialog\": \"nói %1 %2 %3\",\n    \"remove_dialog\": \"xóa bài nói %1\",\n    \"change_to_nth_shape\": \"thay đổi bằng hình dạng %1 %2\",\n    \"change_to_next_shape\": \"thay đổi bằng hình dạng %1 %2\",\n    \"set_effect_volume\": \"thay đổi %1 hiệu ứng bằng %2 %3\",\n    \"set_effect\": \"thiết lập %1 hiệu ứng bằng %2 %3\",\n    \"erase_all_effects\": \"xóa tất cả các hiệu ứng %1\",\n    \"change_scale_percent\": \"thay đổi kích cỡ bằng %1 %2\",\n    \"set_scale_percent\": \"thiết lập kích cỡ thành %1 %2\",\n    \"change_scale_size\": \"thay đổi kích cỡ bằng %1 %2\",\n    \"set_scale_size\": \"thiết lập kích cỡ thành %1 %2\",\n    \"flip_y\": \"lật ngang %1\",\n    \"flip_x\": \"lật dọc %1\",\n    \"set_object_order\": \"đi đến lớp thứ %1 %2\",\n    \"get_pictures\": \"%1  \",\n    \"change_to_some_shape\": \"thay đổi bằng hình dạng %1 %2\",\n    \"add_effect_amount\": \"thay đổi %1 hiệu ứng bằng %2 %3\",\n    \"change_effect_amount\": \"thiết lập %1 hiệu ứng bằng %2 %3\",\n    \"set_effect_amount\": \"thay đổi %1 hiệu ứng bằng %2 %3\",\n    \"set_entity_effect\": \"thiết lập %1 hiệu ứng bằng %2 %3\",\n    \"change_object_index\": \"mang đến cho %1 %2\",\n    \"move_direction\": \"di chuyển %1 về phía trước %2\",\n    \"move_x\": \"thay đổi X bằng %1 %2\",\n    \"move_y\": \"thay đổi Y bằng %1 %2\",\n    \"locate_xy_time\": \"di chuyển trong %1 giây đến x: %2, y: %3 %4\",\n    \"rotate_by_angle\": \"xoay %1 độ %2\",\n    \"rotate_by_angle_dropdown\": \"xoay %1 độ %2\",\n    \"see_angle\": \"thiết lập phương hướng bằng %1 %2\",\n    \"see_direction\": \"xoay thành %1 %2\",\n    \"locate_xy\": \"di chuyển đến X: %1 Y: %2 %3\",\n    \"locate_x\": \"di chuyển đến X: %1 %2\",\n    \"locate_y\": \"di chuyển đến Y: %1 %2\",\n    \"locate\": \"di chuyển đến %1 %2\",\n    \"move_xy_time\": \"trong %1 giây di chuyển đến X: %2 Y: %3 %4\",\n    \"rotate_by_angle_time\": \"xoay trong %1 giây bằng %2 độ %3\",\n    \"bounce_wall\": \"nếu ở cạnh màn hình thì bật ra %1\",\n    \"flip_arrow_horizontal\": \"lật ngang theo hướng mũi tên %1\",\n    \"flip_arrow_vertical\": \"lật dọc theo hướng mũi tên %1\",\n    \"see_angle_object\": \"chuyển hướng tới %1 %2\",\n    \"see_angle_direction\": \"thiết lập góc độ bằng %1 độ %2\",\n    \"rotate_direction\": \"thay đổi phương hướng bằng %1 %2\",\n    \"locate_object_time\": \"trong %1 giây di chuyển đến %2 %3\",\n    \"rotate_absolute\": \"thiết lập hướng bằng %1 %2\",\n    \"rotate_relative\": \"xoay hướng %1 %2\",\n    \"direction_absolute\": \"thiết lập phương hướng bằng %1 %2\",\n    \"direction_relative\": \"thay đổi phương hướng bằng %1 %2\",\n    \"move_to_angle\": \"theo hướng %1 và di chuyển %2 %3\",\n    \"rotate_by_time\": \"trong %1 giây xoay hướng %2 %3\",\n    \"direction_relative_duration\": \"trong %1 giây thiết lập phương hướng bằng %2 %3\",\n    \"neobot_sensor_value\": \"giá trị %1\",\n    \"neobot_turn_left\": \"xoay hướng %1 %2 %3\",\n    \"neobot_stop_left\": \"dừng động cơ bên trái %1\",\n    \"neobot_turn_right\": \"xoay hướng động cơ bên phải %1 %2 %3\",\n    \"neobot_stop_right\": \"dừng động cơ bên phải %1\",\n    \"neobot_run_motor\": \"chạy động cơ %1 trong %2 giây\",\n    \"neobot_servo_1\": \"Di chuyển động cơ được kết nối đến SERVO1 %2 với tốc độ %1 %3\",\n    \"neobot_servo_2\": \"Di chuyển động cơ được kết nối đến SERVO2 %2 với tốc độ %1 %3\",\n    \"neobot_play_note_for\": \"phát giai điệu %1 đến quãng tám %2, âm thanh phát ra %3 %4\",\n    \"neobot_set_sensor_value\": \"%1 giá trị cổng đến %2 %3\",\n    \"robotis_openCM70_cm_custom_value\": \"địa chỉ tùy chỉnh ( %1 ) giá trị %2\",\n    \"robotis_openCM70_sensor_value\": \"giá trị điều khiển %1\",\n    \"robotis_openCM70_aux_sensor_value\": \"giá trị %1   %2\",\n    \"robotis_openCM70_cm_buzzer_index\": \"phát %1 giá trị bộ điều khiển thanh âm  trong %2 giây %3\",\n    \"robotis_openCM70_cm_buzzer_melody\": \"phát bộ điều khiển giai điệu %1 lần %2\",\n    \"robotis_openCM70_cm_sound_detected_clear\": \"phát bộ điều khiển giai điệu %1 lần %2\",\n    \"robotis_openCM70_cm_led\": \"bộ điều khiển %1 LED %2 %3\",\n    \"robotis_openCM70_cm_motion\": \"mở chuyển động %1 lần\",\n    \"robotis_openCM70_cm_autodrive_motor\": \"Ô tô lái tự động %1 sử dụng động cơ %2 %3\",\n    \"robotis_openCM70_cm_autodrive_ir\": \"Ô tô tự lái %1 sử dụng cảm biến hồng ngoại %2 %3\",\n    \"robotis_openCM70_cm_autodrive_speed\": \"Thực hiện lái xe tự trị ở tốc độ %1 %2\",\n    \"robotis_openCM70_aux_car_move\": \"Làm cho robot đi %2 với tốc độ %1% %3\",\n    \"robotis_openCM70_aux_motor_speed\": \"Thiết lập tốc độ giảm tốc động cơ của %1 tới %2 , và giá trị đầu ra đến %3% %4\",\n    \"robotis_openCM70_aux_servo_mode\": \"Thiết lập chế độ của %1 động cơ servo bằng %2 %3\",\n    \"robotis_openCM70_aux_servo_speed\": \"Thiết lập tốc độ tốc động cơ servo của %1 tới %2, và giá trị đầu ra đến %3% %4\",\n    \"robotis_openCM70_aux_servo_position\": \"Thiết lập vị trí của %1 động cơ servo bằng %2 độ %3\",\n    \"robotis_openCM70_aux_led_module\": \"thiết lập %1 mô-đun LED như %2 %3\",\n    \"robotis_openCM70_aux_custom\": \"thiết lập %1 thiết bị người dùng như %2 %3\",\n    \"robotis_openCM70_cm_poweroff_timer\": \"Bộ hẹn giờ tự động tắt bộ điều khiển %1 %2\",\n    \"robotis_openCM70_cm_custom\": \"thiết lập địa chỉ tùy chỉnh ( %1 ) như %2 %3\",\n    \"robotis_carCont_sensor_value\": \"giá trị %1\",\n    \"robotis_carCont_cm_led\": \"%1 LED 4, %2 LED %3\",\n    \"robotis_carCont_cm_sound_detected_clear\": \"khởi tạo số cuối cùng phát hiện âm thanh %1\",\n    \"robotis_carCont_aux_motor_speed\": \"Thiết lập tốc độ giảm tốc động cơ của %1 tới %2, và giá trị đầu ra đến %3 %4\",\n    \"robotis_carCont_cm_calibration\": \"Thiết lập %1 giá trị của cảm biến hồng ngoại hiệu chuẩn bằng %2 %3\",\n    \"roduino_get_analog_number\": \"%1  \",\n    \"roduino_get_port_number\": \"%1  \",\n    \"roduino_get_analog_value\": \"Analog %1 Sensor value  \",\n    \"roduino_get_digital_value\": \"Digital %1 Sensor value  \",\n    \"roduino_set_digital\": \"Digital %1 Pin %2 %3\",\n    \"roduino_motor\": \"%1 %2 %3\",\n    \"roduino_set_color_pin\": \"Color Sensor R : %1, G : %2, B : %3 %4\",\n    \"roduino_get_color\": \"Color Sensor %1 Detected \",\n    \"roduino_on_block\": \" On \",\n    \"roduino_off_block\": \" Off \",\n    \"schoolkit_get_in_port_number\": \"%1  \",\n    \"schoolkit_get_out_port_number\": \"%1  \",\n    \"schoolkit_get_servo_port_number\": \"%1  \",\n    \"schoolkit_get_input_value\": \"Digital %1 Sensor value  \",\n    \"schoolkit_set_output\": \"Digital %1 Pin %2 %3\",\n    \"schoolkit_motor\": \"%1 Speed %2 %3 %4\",\n    \"schoolkit_set_servo_value\": \"Servo %1 Pin %2˚ %3\",\n    \"schoolkit_on_block\": \" On \",\n    \"schoolkit_off_block\": \" Off \",\n    \"when_scene_start\": \"%1 khi cảnh tượng bắt đầu\",\n    \"start_scene\": \"bắt đầu %1 cảnh %2\",\n    \"start_neighbor_scene\": \"bắt đầu %1 cảnh %2\",\n    \"sound_something\": \"phát %1 âm thanh %2\",\n    \"sound_something_second\": \"phát %1 âm thanh trong %2 giây %3\",\n    \"sound_something_wait\": \"phát %1 âm thanh và chờ %2\",\n    \"sound_something_second_wait\": \"phát %1 âm thanh trong %2 giây và chờ %3\",\n    \"sound_volume_change\": \"thay đổi âm lượng bằng %1 % %2\",\n    \"sound_volume_set\": \"thiết lập âm lượng bằng %1 % %2\",\n    \"sound_silent_all\": \"dừng tất cả âm thanh %1\",\n    \"get_sounds\": \"%1  \",\n    \"sound_something_with_block\": \"phát %1 âm thanh %2\",\n    \"sound_something_second_with_block\": \"phát %1 âm thanh trong %2 giây %3\",\n    \"sound_something_wait_with_block\": \"phát %1 âm thanh và chờ %2\",\n    \"sound_something_second_wait_with_block\": \"phát %1 âm thanh trong %2 giây và chờ %3\",\n    \"sound_from_to\": \"phát %1 âm thanh từ %2 đến %3 giây %4\",\n    \"sound_from_to_and_wait\": \"phát %1 âm thanh từ %2 đến %3 giây và chờ %4\",\n    \"when_run_button_click\": \"%1 khi chạy\",\n    \"press_some_key\": \"%1 khi phím %2 được nhấn %3\",\n    \"when_some_key_pressed\": \"%1 khi phím %2 được nhấn\",\n    \"mouse_clicked\": \"%1 khi nhấp chuột\",\n    \"mouse_click_cancled\": \"%1 khi thả nhấp chuột\",\n    \"when_object_click\": \"%1 khi nhấp vào đối tượng\",\n    \"when_object_click_canceled\": \"%1 khi thả nhấp chuột trên đối tượng\",\n    \"when_some_key_click\": \"%1 khi nhấn phím\",\n    \"when_message_cast\": \"%1 khi nhận được %2 tin nhắn\",\n    \"message_cast\": \"gửi %1 tin nhắn %2\",\n    \"message_cast_wait\": \"gửi %1 tin nhắn và chờ %2\",\n    \"text\": \"%1\",\n    \"text_read\": \"Textbox %1’s contents\",\n    \"text_write\": \"viết là %1 %2\",\n    \"text_append\": \"sau khi viết là %1 %2\",\n    \"text_prepend\": \"thêm %1 trước %2\",\n    \"text_flush\": \"xóa hết văn bản %1\",\n    \"analizyDataAddButton\": \"%1\",\n    \"append_row_to_table\": \"Add a %2 to the table %1 %3\",\n    \"insert_row_to_table\": \"Insert %3 to %2th row from the %1 %4\",\n    \"delete_row_from_table\": \"Remove %2th %3 from table %1 %4\",\n    \"set_value_from_table\": \"Change %3 in the %1 %2th row to %4 %5\",\n    \"get_table_count\": \"length of %2 in the %1\",\n    \"get_value_from_table\": \"value of the %3 in %2th row of the %1\",\n    \"calc_values_from_table\": \"%3 of the %2 in the %1\",\n    \"open_table_chart\": \"Open the chart of the %1 %2\",\n    \"close_table_chart\": \"Close the table chart\",\n    \"get_coefficient\": 'Correlation coefficient between %2and %3 in table %1',\n    \"variableAddButton\": \"%1\",\n    \"listAddButton\": \"%1\",\n    \"change_variable\": \"thêm vào %1 bằng %2 %3\",\n    \"set_variable\": \"thiết lập %1 bằng %2 %3\",\n    \"show_variable\": \"hiển thị biến số %1 giá trị %2\",\n    \"hide_variable\": \"ẩn biến số %1 giá trị %2\",\n    \"get_variable\": \"%2 %1\",\n    \"ask_and_wait\": \"hỏi %1 và trả lời %2\",\n    \"get_canvas_input_value\": \"%1  \",\n    \"add_value_to_list\": \"thêm %1 vào danh sách %2 %3\",\n    \"remove_value_from_list\": \"xóa hạng mục thứ %1 từ %2 %3\",\n    \"insert_value_to_list\": \"chèn %1 đến vị trí thứ %3 của %2 %4\",\n    \"change_value_list_index\": \"thay đổi hạng mục thứ %1 %2 đến %3 %4\",\n    \"value_of_index_from_list\": \"thay đổi hạng mục thứ %1 %2 đến %3 %4\",\n    \"length_of_list\": \"%1 %2 %3\",\n    \"show_list\": \"hiển thị danh sách %1 %2\",\n    \"hide_list\": \"ẩn danh sách %1 %2\",\n    \"options_for_list\": \"%1  \",\n    \"set_visible_answer\": \"trả lời %1 %2\",\n    \"is_included_in_list\": \"%1 %2 %3 %4 %5\",\n    \"xbot_digitalInput\": \"%1\",\n    \"xbot_analogValue\": \"%1\",\n    \"xbot_digitalOutput\": \"kỹ thuật số %1 Pin, dữ liệu đầu ra %2 %3\",\n    \"xbot_analogOutput\": \"Analog %1 %2 %3\",\n    \"xbot_servo\": \"động cơ servo %1 góc độ %2 %3\",\n    \"xbot_oneWheel\": \"động cơ bánh xe (DC) %1, tốc độ %2 %3\",\n    \"xbot_twoWheel\": \"động cơ bánh xe (DC) tốc độ bên phải (2): %1 tốc độ bên trái(1): %2 %3\",\n    \"xbot_rgb\": \"màu RGB LED từ màu đỏ %1 xanh lá cây %2 xanh dương %3 %4\",\n    \"xbot_rgb_picker\": \"màu RGB LED từ %1  %2\",\n    \"xbot_buzzer\": \"phát âm %1   %2 trong %3 giây phát giai điệu %4\",\n    \"xbot_lcd\": \"LCD dòng thứ %1, văn bản %2 %3\",\n    \"run\": \"\",\n    \"mutant\": \"kiểm tra đột biến khối\",\n    \"jr_start\": \"%1\",\n    \"jr_repeat\": \"lần %1 %2\",\n    \"jr_item\": \"thu thập hoa %1\",\n    \"cparty_jr_item\": \"nhấc %1\",\n    \"jr_north\": \"lên %1\",\n    \"jr_east\": \"Bên phải %1\",\n    \"jr_south\": \"xuống %1\",\n    \"jr_west\": \"Bên trái %1\",\n    \"jr_start_basic\": \"%1 %2\",\n    \"jr_go_straight\": \"tiến về phía trước %1\",\n    \"jr_turn_left\": \"quay sang trái %1\",\n    \"jr_turn_right\": \"quay sang phải %1\",\n    \"jr_go_slow\": \"đi chậm %1\",\n    \"jr_repeat_until_dest\": \"Lặp lại cho đến khi gặp %1 %2\",\n    \"jr_if_construction\": \"nếu phía trước là %1 thì %2\",\n    \"jr_if_speed\": \"nếu phía trước là %1 thì %2\",\n    \"maze_step_start\": \"%1 khi chạy\",\n    \"maze_step_jump\": \"bỏ qua %1\",\n    \"maze_step_jump2\": \"Jump%1\",\n    \"maze_step_jump_pinkbean\": \"Jump%1\",\n    \"maze_step_for\": \"lặp lại %1 lần %2\",\n    \"test\": \"%1 đây là khối văn bản %2 \",\n    \"maze_repeat_until_1\": \"Lặp lại cho đến khi gặp %1 %2 \",\n    \"maze_repeat_until_2\": \"Lặp lại cho đến khi gặp tất cả %1 %2 \",\n    \"maze_step_if_1\": \"nếu phía trước có %1 thì %2\",\n    \"maze_step_if_2\": \"nếu phía trước có %1 thì %2\",\n    \"maze_call_function\": \"nhập cuộc hẹn %1\",\n    \"maze_define_function\": \"cuộc hẹn %1\",\n    \"maze_step_if_3\": \"nếu phía trước có %1 thì %2\",\n    \"maze_step_if_4\": \"nếu phía trước có %1 thì %2\",\n    \"maze_step_move_step\": \"di chuyển về phía trước 1 bước %1\",\n    \"maze_step_rotate_left\": \"quẹo trái %1\",\n    \"maze_step_rotate_right\": \"quẹo phải %1\",\n    \"maze_step_forward\": \"tiến về phía trước %1\",\n    \"maze_turn_right\": \"tiến về phía trước %1\",\n    \"maze_turn_left\": \"tiến về phía trước %1\",\n    \"maze_ladder_climb\": \"Climb ladder%1\",\n    \"maze_attack_lupin\": \"Attack %1 %2\",\n    \"maze_attack_both_side\": \"Attack both sides%1\",\n    \"maze_attack_pepe\": \"Attack %1 %2\",\n    \"maze_attack_yeti\": \"Attack %1 %2\",\n    \"maze_attack_mushroom\": \"Attack %1 %2\",\n    \"maze_attack_peti\": \"Attack %1 %2\",\n    \"maze_eat_item\": \"Take food%1\",\n    \"maze_step_if_mushroom\": \"If there is %1 one space forward %2\",\n    \"maze_step_if_yeti\": \"If there is %1 in front %2 %3 else\",\n    \"maze_step_if_left_monster\": \"If there is a monster in the left side attack range %1 %2 else\",\n    \"maze_step_if_right_monster\": \"If there is a monster in the right side attack range %1 %2 else\",\n    \"maze_step_if_lupin\": \"If there is %1 two spaces forward %2\",\n    \"maze_step_if_else_road\": \"If there is road one space forward %1 %2else\",\n    \"maze_step_if_else_mushroom\": \"If there is %1 one space forward %2 %3 else\",\n    \"maze_step_if_else_lupin\": \"If there is %1 two spaces forward %2 %3 else\",\n    \"maze_step_if_else_ladder\": \"If there is %1 one space forward %2 %3 else\",\n    \"maze_rotate_left\": \"quay sang trái %1\",\n    \"maze_rotate_right\": \"quay sang phải %1\",\n    \"maze_moon_kick\": \"đá %1\",\n    \"maze_repeat_until_3\": \"Lặp lại cho đến khi gặp %1 %2 \",\n    \"maze_repeat_until_4\": \"Lặp lại cho đến khi gặp %1 %2 \",\n    \"maze_repeat_until_5\": \"Lặp lại cho đến khi gặp %1 %2 \",\n    \"maze_repeat_until_6\": \"Lặp lại cho đến khi đến nơi %1 %2 \",\n    \"maze_repeat_until_7\": \"Repeat until reaching %1 %2\",\n    \"maze_repeat_until_goal\": \"Repeat until arrival to destination%1\",\n    \"maze_repeat_until_beat_monster\": \"Repeat until all monsters are defeated %1\",\n    \"maze_radar_check\": \"trong %1 có %2\",\n    \"maze_cony_flower_throw\": \"ném hoa %1\",\n    \"maze_brown_punch\": \"đấm %1\",\n    \"maze_iron_switch\": \"điều khiển chướng ngại vật %1\",\n    \"maze_james_heart\": \"gửi tim %1\",\n    \"maze_step_if_5\": \"nếu phía trước không có con đường thì %2\",\n    \"maze_step_if_6\": \"nếu phía trước không có %1 thì %2\",\n    \"maze_step_if_7\": \"nếu phía trước không có %1 thì %2\",\n    \"maze_step_if_8\": \"nếu là %1 thì %2\",\n    \"maze_step_if_else\": \"nếu là %1 thì %2 %3 hoặc\",\n    \"test_wrapper\": \"%1 đây là khối văn bản %2 \",\n    \"basic_button\": \"%1\",\n    \"ai_move_right\": \"di chuyển về phía trước %1\",\n    \"ai_move_up\": \"đi lên trên %1\",\n    \"ai_move_down\": \"đi xuống dưới %1\",\n    \"ai_repeat_until_reach\": \"lặp lại cho đến khi đến đích %1 \",\n    \"ai_if_else_1\": \"nếu phía trước có %1 thì %2 %3 còn không thì\",\n    \"ai_boolean_distance\": \"%1 ra-đa %2 %3\",\n    \"ai_distance_value\": \"%1 ra-đa\",\n    \"ai_boolean_object\": \"đối tượng %1 có phải là %2 không?\",\n    \"ai_use_item\": \"sử dụng hệ thống %1\",\n    \"ai_boolean_and\": \"%1 %2 %3\",\n    \"ai_True\": \"%1\",\n    \"ai_if_else\": \"nếu là %1 thì %2 %3 còn không thì\",\n    \"smartBoard_convert_scale\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"smartBoard_get_named_sensor_value\": \"%1 Sensor value\",\n    \"smartBoard_is_button_pressed\": \"Pressed %1 button?\",\n    \"smartBoard_set_dc_motor_direction\": \"%1 DC Motor change direction %2 %3\",\n    \"smartBoard_set_dc_motor_speed\": \"%1 DC Motor %2 %3\",\n    \"smartBoard_set_dc_motor_pwm\": \"%1 DC Motor set speed %2 %3\",\n    \"smartBoard_set_servo_speed\": \"%1 RC Servo Motor Speed %2 %3\",\n    \"smartBoard_set_servo_angle\": \"%1 RC Servo Motor set angle %2 %3\",\n    \"smartBoard_set_number_eight_pin\": \"%1 port %2 %3\",\n    \"smartBoard_set_gs1_pwm\": \"GS1 port %1 %2\",\n    \"robotori_digitalInput\": \"%1\",\n    \"robotori_analogInput\": \"%1\",\n    \"robotori_digitalOutput\": \"Digital %1 PIN, Output Value %2 %3\",\n    \"robotori_analogOutput\": \"Analog %1 %2 %3\",\n    \"robotori_servo\": \"Servo Motor Angle %1 %2\",\n    \"robotori_dc_direction\": \"DC Motor %1 Direction %2 %3\",\n    \"dadublock_get_analog_value\": \"Analog %1 Sensor value\",\n    \"dadublock_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5  \",\n    \"dadublock_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"dadublock_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"dadublock_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"dadublock_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"dadublock_set_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"coconut_stop_motor\": \"stop motor %1\",\n    \"coconut_move_motor\": \"move %1 %2\",\n    \"coconut_turn_motor\": \"turn %1 %2\",\n    \"coconut_move_for_secs\": \"move %1 for time %2 %3\",\n    \"coconut_turn_for_secs\": \"turn %1 for %2 secs %3\",\n    \"coconut_turn_to_led\": \"turn %1 RGB %2 %3\",\n    \"coconut_move_outmotor\": \"external Motor %1 speed %2 %3\",\n    \"coconut_set_led_to\": \"turn on RGB %1 %2 %3\",\n    \"coconut_clear_led\": \"turn off RGB %1 %2\",\n    \"coconut_set_led_clear\": \"turn off RGB %1 %2 %3\",\n    \"coconut_set_led_time\": \"turn on RGB %1 %2 for time %3 %4\",\n    \"coconut_beep\": \"buzzer on %1\",\n    \"coconut_buzzer_time\": \"play buzzer for time %1 %2\",\n    \"coconut_buzzer_set_hz\": \"play buzzer on frequency %1 Hz for time %2 %3\",\n    \"coconut_clear_buzzer\": \"buzzer off %1\",\n    \"coconut_play_buzzer\": \"play buzzer on note %1 octave %2 %3 beat %4 %5\",\n    \"coconut_rest_buzzer\": \"rest beat %1 %2\",\n    \"coconut_play_buzzer_led\": \"play buzzer on note %1 octave %2 %3 beat %4 RGB %5 %6 %7\",\n    \"coconut_play_midi\": \"play melody %1 %2\",\n    \"coconut_floor_sensor\": \"line tracer %1\",\n    \"coconut_floor_sensing\": \"line tracer detect %1 %2\",\n    \"coconut_following_line\": \"follow the line %1\",\n    \"coconut_front_sensor\": \"IR distance sensor %1\",\n    \"coconut_front_sensing\": \"detecting obstacle %1 %2\",\n    \"coconut_obstruct_sensing\": \"detecting obstacle\",\n    \"coconut_avoid_mode\": \"avoid mode %1\",\n    \"coconut_dotmatrix_set\": \"LED Matrix %1 ( ROW %2, COL %3 ) %4\",\n    \"coconut_dotmatrix_on\": \"turn on all LED Matrix %1\",\n    \"coconut_dotmatrix_off\": \"LED Matrix clear all %1\",\n    \"coconut_dotmatrix_num\": \"LED Matrix show %1 %2\",\n    \"coconut_dotmatrix_small_eng\": \"LED Matrix show small letter %1 %2\",\n    \"coconut_dotmatrix_big_eng\": \"LED Matrix show capital letters %1 %2\",\n    \"coconut_dotmatrix_kor\": \"LED Matrix show Korean %1 %2\",\n    \"coconut_light_sensor\": \"light sensor\",\n    \"coconut_tem_sensor\": \"temperature\",\n    \"coconut_ac_sensor\": \"3-Axis Accelerometer %1 angle\",\n    \"coconut_outled_sensor\": \"set external LED pin %1 for time %2 %3\",\n    \"coconut_outspk_sensor\": \"set Speaker pin %1 frequency %2 (Hz) duration %3 seconds %4\",\n    \"coconut_outspk_sensor_off\": \"stop Speaker pin %1 %2\",\n    \"coconut_outinfrared_sensor\": \"external IR sensor %1\",\n    \"coconut_outcds_sensor\": \"external Cds sensor %1\",\n    \"coconut_servomotor_angle\": \"set servo pin %1 angle as %2 %3\",\n    \"chocopi_control_button\": \"%1 controller %2 is pressed\",\n    \"chocopi_control_event\": \"%1 When %2 controller %3 is %4\",\n    \"chocopi_control_joystick\": \"%1 controller %2 value\",\n    \"chocopi_dc_motor\": \"%1 DC motor #%2  %3 % direction %4 %5\",\n    \"chocopi_led\": \"%1 LED #%2 RGB(%3 %4 %5) %6\",\n    \"chocopi_motion_photogate_event\": \"%1 When %2 photogate %3 is %4\",\n    \"chocopi_motion_photogate_status\": \"%1 photogate #%2 is blocked\",\n    \"chocopi_motion_photogate_time\": \"time when %1 photogate %2 was %3\",\n    \"chocopi_motion_value\": \"%1 motion %2 value\",\n    \"chocopi_sensor\": \"%1 sensor %2\",\n    \"chocopi_servo_motor\": \"%1 set servo motor #%2 %3 degree %4\",\n    \"chocopi_touch_event\": \"%1 When %2 touch pad%3 is %4\",\n    \"chocopi_touch_status\": \"%1 touch pad%2 is touched\",\n    \"chocopi_touch_value\": \"%1 touch pad%2 value\",\n    \"dadublock_car_digital_pwm\": \"디지털 %1 번 핀을 %2 (으)로 정하기 %3\",\n    \"dadublock_car_get_analog_value\": \"아날로그 %1 번 센서값\",\n    \"dadublock_car_get_analog_value_map\": \"아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  \",\n    \"dadublock_car_get_digital\": \"디지털 %1 번 센서값\",\n    \"dadublock_car_get_irsensor\": \"적외선 %1 번 센서값\",\n    \"dadublock_car_get_ultrasonic_value\": \"울트라소닉 Trig %1번핀 Echo %2번핀 센서값\",\n    \"dadublock_car_motor\": \"모터 %1 번을 %2 (으)로 %3 %의 속도로 움직이기 %4\",\n    \"dadublock_car_motor_stop\": \"모터 %1 번 멈추기 %2\",\n    \"dadublock_car_set_servo\": \"서보모터 %1 번 핀을 %2 의 각도로 정하기 %3\",\n    \"dadublock_car_set_tone\": \"디지털 %1 번 핀 을 %2 음으로 %3의 옥타브로 %4 만큼 연주하기 %5\",\n    \"dadublock_car_toggle_led\": \"디지털 %1 번 핀 %2 %3\",\n    \"dadublock_get_digital\": \"디지털 %1 번 센서값\",\n    \"ev3_get_sensor_value\": \"%1's value\",\n    \"ev3_touch_sensor\": \"%1's touch sensor activted?\",\n    \"ev3_color_sensor\": \"%1's %2 value\",\n    \"ev3_motor_power\": \"%1's value print as %2 %3\",\n    \"ev3_motor_power_on_time\": \"%1's value for %2seconds %3 printed %4\",\n    \"ev3_motor_degrees\": \"%1's value in %2 direction turn %3 degrees %4\",\n    \"rokoboard_get_sensor_value_by_name\": \"%1 value\",\n    \"ardublock_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"ardublock_get_analog_value\": \"Analog %1 Sensor value\",\n    \"ardublock_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"ardublock_get_digital\": \"Digital %1 Sensor value\",\n    \"ardublock_get_left_cds_analog_value\": \"Left CDS %1 Sensor value\",\n    \"ardublock_get_right_cds_analog_value\": \"Left CDS  %1 Sensor value\",\n    \"ardublock_get_sound_analog_value\": \"Analog Sound %1 Sensor value\",\n    \"ardublock_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"ardublock_set_left_motor\": \"Left motor direction to %1 speed %2 set %3\",\n    \"ardublock_set_right_motor\": \"Right motor direction to %1 speed %2 set %3\",\n    \"ardublock_set_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"ardublock_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"ardublock_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"ardublock_toggle_left_led\": \"Left Light %1 Pin %2 %3\",\n    \"ardublock_toggle_right_led\": \"Right Light %1 Pin %2 %3\",\n    \"mkboard_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"mkboard_get_analog_value\": \"Analog %1 Sensor value\",\n    \"mkboard_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"mkboard_get_digital\": \"Digital %1 Sensor value\",\n    \"mkboard_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"mkboard_set_servo\": \"Set servo pin %1 angle as %2 %3\",\n    \"mkboard_set_tone\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"mkboard_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"mkboard_set_lcd\": \"1602 LCD Row %1, Column %2 Value %3 %4\",\n    \"mkboard_lcd_command\": \"1602 LCD Command %1 execute %2\",\n    \"altino_analogValue\": \"altino %1 sensor value\",\n    \"altino_dot_display\": \"electronic scoreboard %1 display %2\",\n    \"altino_dot_display_line\": \"1col %1 2col %2 3col %3 4col %4 5col %5 6col %6 7col %7 8col %8 display %9\",\n    \"altino_light\": \"%1 light %2  %3\",\n    \"altino_rear_wheel\": \"rear motor right %1 left %2 setting %3\",\n    \"altino_sound\": \"%1 octave %2 play  %3\",\n    \"altino_steering\": \"direction %1 setting %2\",\n    \"jdkit_altitude\": \"드론을 %1 높이만큼 날리기 %2\",\n    \"jdkit_button\": \"%1번 버튼 값 읽어오기\",\n    \"jdkit_connect\": \"드론 연결 상태 읽어오기\",\n    \"jdkit_emergency\": \"드론을 즉시 멈추기 %1\",\n    \"jdkit_gyro\": \"보드 %1 기울기 값 읽어오기\",\n    \"jdkit_joystick\": \"조이스틱 %1 읽기\",\n    \"jdkit_led\": \"%1 LED %2  %3\",\n    \"jdkit_motor\": \"%1 모터를 %2 세기로 돌리기 %3\",\n    \"jdkit_ready\": \"드론 비행 준비 상태 읽어오기\",\n    \"jdkit_rollpitch\": \"드론을 %1 방향 %2 세기로 움직이기 %3\",\n    \"jdkit_throttle\": \"드론 프로펠러를 %1 만큼 세기로 돌리기 %2\",\n    \"jdkit_tune\": \"%1 음을  %2 초동안 소리내기 %3\",\n    \"jdkit_ultrasonic\": \"거리(초음파)값 읽어오기\",\n    \"jdkit_yaw\": \"드론을 %1 만큼 회전하기 %2\",\n    \"memaker_digital_pwm\": \"Digital %1 Pin %2 %3\",\n    \"memaker_get_analog_value\": \"Analog %1 Sensor value\",\n    \"memaker_get_analog_value_map\": \"Map Value %1 %2 ~ %3 to %4 ~ %5\",\n    \"memaker_get_digital\": \"Digital %1 Sensor value\",\n    \"memaker_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"memaker_set_lcd\": \"1602 LCD Row %1, Column %2 Value %3 %4\",\n    \"memaker_set_servo\": \"Set servo pin %1 angle as %3\",\n    \"memaker_toggle_led\": \"Digital %1 Pin %2 %3\",\n    \"memaker_lcd_command\": \"1602 LCD Command %1 execute %2\",\n    \"edumaker_digital_pwm\": \"디지털 %1 번 핀을 %2 (으)로 정하기 %3\",\n    \"edumaker_get_analog_value\": \"아날로그 %1 번 센서값\",\n    \"edumaker_get_analog_value_map\": \"%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값\",\n    \"edumaker_get_digital\": \"디지털 %1 번 센서값\",\n    \"edumaker_get_ultrasonic_value\": \"울트라소닉 Trig %1 Echo %2 센서값\",\n    \"edumaker_set_servo\": \"디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3\",\n    \"edumaker_set_tone\": \"디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5\",\n    \"edumaker_toggle_led\": \"디지털 %1 번 핀 %2 %3\",\n    \"creamo_get_number_sensor_value\": \"PWM_Block %1 Sensor value\",\n    \"creamo_get_port_number\": \"%1\",\n    \"creamo_get_pwm_port_number\": \"%1\",\n    \"creamo_motor_port_number\": \"%1\",\n    \"creamo_toggle_led\": \"LED_Block %1 Pin %2 %3\",\n    \"creamo_toggle_motor\": \"Motor_Block %1 pin %2 %3\",\n    \"creamo_toggle_pwm\": \"Digital %1 Pin %2 %3\",\n    \"mechatro_get_dc_motor_current\": \"Get 1%motor current\",\n    \"mechatro_get_digital\": \"%1\",\n    \"mechatro_get_sensor_value\": \"Analog %1 Sensor value\",\n    \"mechatro_get_ultrasonic_value\": \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n    \"mechatro_set_blue_pw\": \"Change PW of Bluetooth to %1%2%3%4 %5\",\n    \"mechatro_set_dc_motor\": \"Set %1 motor speed to %2 %3\",\n    \"mechatro_set_digital\": \"Digital %1 Pin %2 %3\",\n    \"mechatro_set_pwm\": \"Digital %1 Pin %2 %3\",\n    \"mechatro_set_servo_position\": \"Set servo pin %1 angle as %2 %3\",\n    \"mechatro_set_servo_speed\": \"Set servo pin %1 speed %2 degree per second %3\",\n    \"mechatro_set_threshold\": \"Set %1 threshold : %2%3\",\n    \"mechatro_set_tone\": \"Play tone pin %1 on note %2 octave %3 %4\",\n    \"mechatro_set_tone_time\": \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n    \"funboard_buzzer_onoff\": \"buzzer %1 %2\",\n    \"funboard_buzzer_second\": \"buzzer%1%2seconds%3\",\n    \"funboard_buzzer_tone_simple\": \"play note%1%2,%3sec of Melody Playing%4\",\n    \"funboard_color_led_on_pwm\": \"%1COLOR  LED %2 % %3\",\n    \"funboard_color_led_onoff\": \"%1COLOR  LED %2 %3\",\n    \"funboard_convert_scale\": \"Convert %1 value from %2~%3 to %4~%5\",\n    \"funboard_dotmatrix_1column\": \"%1column %2set %3\",\n    \"funboard_dotmatrix_1row\": \"%1row %2set %3\",\n    \"funboard_dotmatrix_1row_1column\": \"%1%2 %3set %4\",\n    \"funboard_dotmatrix_64_display\": \"%1 (8x8)display%2\",\n    \"funboard_dotmatrix_big_eng\": \"capital letters %1 %2\",\n    \"funboard_dotmatrix_char_display\": \"char%1display%2\",\n    \"funboard_dotmatrix_extra_char\": \"char %1 %2\",\n    \"funboard_dotmatrix_intensity\": \"Intensity %1% %2\",\n    \"funboard_dotmatrix_kor\": \"∷∷  korean %1 %2\",\n    \"funboard_dotmatrix_num\": \"number %1 %2\",\n    \"funboard_dotmatrix_onoff\": \"turn all %1 %2\",\n    \"funboard_dotmatrix_scroll_option\": \"scroll direction%1%2\",\n    \"funboard_dotmatrix_scroll_rapid\": \"scroll rapid %1% %2\",\n    \"funboard_dotmatrix_set\": \"%1row %2column  %3 %4\",\n    \"funboard_dotmatrix_small_eng\": \"small letter %1 %2\",\n    \"funboard_dotmatrix_string_display\": \"string%1display%2\",\n    \"funboard_dotmatrix_string_display_scroll\": \"string%1display%2scroll%3\",\n    \"funboard_dotmatrix_symbol\": \"symbol %1 %2\",\n    \"funboard_get_analog_sensor_2state\": \"%1 value %2\",\n    \"funboard_get_digital_button_value\": \"%1 button value\",\n    \"funboard_get_number_sensor_value\": \"%1 value\",\n    \"funboard_get_touch_button_value\": \"%1 touch button value\",\n    \"funboard_set_digital_buzzer\": \"Play tone octave %1 note %2 beat %3 %4\",\n    \"funboard_what_button_pressed\": \"%1 button pressed.\",\n    \"funboard_what_touch_button_pressed\": \"%1 touch button pressed.\"\n};\nLang.TextCoding = {\n    \"block_name\": \"Block Name\",\n    \"title_syntax\": \"Syntax Error\",\n    \"title_converting\": \"Converting Error\",\n    \"message_syntax_default\": \"Syntax error occured\",\n    \"message_syntax_unexpected_token\": \"Unexpected token exist\",\n    \"message_syntax_reserved_token\": \"Unavailable variable name.\",\n    \"message_syntax_reserved_token_list\": \"Unavailable list name.\",\n    \"message_syntax_unexpected_character\": \"Unexpected characters exist\",\n    \"message_syntax_unexpected_indent\": \"Unexpected indent exist\",\n    \"message_conv_default\": \"Unsupported code exists\",\n    \"message_conv_no_support\": \"Unconvertable code exists\",\n    \"message_conv_no_variable\": \"Variable did not declare\",\n    \"message_conv_no_list\": \"List did not declare\",\n    \"message_conv_no_object\": \"Object can't convert\",\n    \"message_conv_no_function\": \"Function can't convert\",\n    \"message_conv_no_entry_event_function\": \"Entry Event Function can't exist within other functions.\",\n    \"message_conv_undefined_function\": \"Undefined instruction. Please make sure you instruction correctly.\",\n    \"message_conv_is_expect1\": \"Syntax error. Please make sure you type \",\n    \"message_conv_is_expect2\": \" correctly.\",\n    \"message_conv_instead\": \"Syntax error. It should be %2 instead of %1.\",\n    \"message_conv_is_wrong1\": \"Syntax error. \",\n    \"message_conv_is_wrong2\": \" are not allowed to be there.\",\n    \"message_conv_or\": \" or \",\n    \"subject_syntax_default\": \"ETC\",\n    \"subject_syntax_token\": \"Token\",\n    \"subject_syntax_character\": \"Character\",\n    \"subject_syntax_indent\": \"Indent\",\n    \"subject_conv_default\": \"ETC\",\n    \"subject_conv_general\": \"General\",\n    \"subject_conv_variable\": \"Variable\",\n    \"subject_conv_list\": \"List\",\n    \"subject_conv_object\": \"Object\",\n    \"subject_conv_function\": \"Function\",\n    \"alert_variable_empty_text\": \"You can't convert into the text mode if there is empty text among registered variables.\",\n    \"alert_list_empty_text\": \"You can't convert into the text mode if there is empty text among registered lists.\",\n    \"alert_function_name_field_multi\": \"You can't convert into the text mode if there is name field block over two times among registered functions.\",\n    \"alert_function_name_disorder\": \"You can't convert into the text mode if name field is behind than string/number or judgement param field among registered functions.\",\n    \"alert_function_has_boolean\": \"If you convert into the text mode and then back to block coding, the [Judgment] used in the function is converted to [Character/Number].\",\n    \"alert_function_editor\": \"Youn can't convert into the text mode in the middle of function creation or editing.\",\n    \"alert_function_no_support\": \"Youn can't use the function creation or editing in the text mode.\",\n    \"alert_list_no_support\": \"Youn can't use the list creation or editing in the text mode.\",\n    \"alert_variable_no_support\": \"Youn can't use the variable creation or editing in the text mode.\",\n    \"alert_signal_no_support\": \"Youn can't use the signal creation or editing in the text mode.\",\n    \"alert_legacy_no_support\": \"Mode switch is not allowed due to inconvertible blocks\",\n    \"alert_variable_empty_text_add_change\": \"The empty text can't be included in variable name.\",\n    \"alert_list_empty_text_add_change\": \"The empty text can't be included in list name.\",\n    \"alert_list_contains_exceed_length_value\": \"You can't convert into the text mode if more than 15 digits are entered in the list item.\",\n    \"alert_function_name_empty_text_add_change\": \"The empty text can't be included in function name.\",\n    \"alert_no_save_on_error\": \"The code with an error can't save.\",\n    \"alert_api_no_support\": \"The project contains blocks \\nthat are not supported by Entry-Python. \\nDelete all those blocks and \\nchange to Entry-Python mode?\",\n    \"warn_unnecessary_arguments\": \"&(calleeName)(); command doesn't require value within parentheses. (line:&(lineNumber))\",\n    \"python_code\": \"'s python code\",\n    \"eof\": \"line change\",\n    \"newline\": \"line change\",\n    \"indent\": \"indentation\",\n    \"num\": \"number\",\n    \"string\": \"string\",\n    \"name\": \"variable name\"\n};\nLang.PythonHelper = {\n    \"when_run_button_click_desc\": \"[시작하기]버튼을 클릭하면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"when_run_button_click_exampleCode\": \"def when_start():\\n    Entry.print(\\\"안녕!\\\")\",\n    \"when_run_button_click_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"안녕!\\\"이라 말합니다.\",\n    \"when_some_key_pressed_desc\": \"A키를 누르면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"when_some_key_pressed_elements\": \"A-- 아래 선택지 중 하나<br>① 알파벳 : \\\"A\\\", \\\"B\\\" ~ \\\"Z\\\" 등(소문자 가능)<br>② 숫자 : 1, 2, 3, 4 ~ 9, 0<br>③ 특수키 : \\\"space\\\", \\\"enter\\\"<br>④ 방향키 : \\\"up\\\", \\\"down\\\", \\\"right\\\", \\\"left\\\"\",\n    \"when_some_key_pressed_exampleCode\": \"def when_press_key(\\\"W\\\"):\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(1):\\n    Entry.add_size(10)\",\n    \"when_some_key_pressed_exampleDesc\": \"W키를 누르면 오브젝트가 이동방향으로 10만큼 이동하고, 1키를 누르면 오브젝트의 크기가 10만큼 커집니다.\",\n    \"mouse_clicked_desc\": \"마우스를 클릭했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"mouse_clicked_exampleCode\": \"def when_click_mouse_on():\\n    Entry.add_size(10)\\n    Entry.move_to_direction(10)\",\n    \"mouse_clicked_exampleDesc\": \"마우스를 클릭하면 오브젝트의 크기가 10만큼 커지면서 이동방향으로 10만큼 이동합니다.\",\n    \"mouse_click_cancled_desc\": \"마우스 클릭을 해제했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"mouse_click_cancled_exampleCode\": \"def when_click_mouse_off():\\n    Entry.move_to_direction(-10)\\n\\ndef when_click_mouse_on():\\n    Entry.move_to_direction(10)\",\n    \"mouse_click_cancled_exampleDesc\": \"마우스를 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 마우스 클릭을 해제하면 오브젝트가 이동방향으로 -10만큼 이동합니다.\",\n    \"when_object_click_desc\": \"해당 오브젝트를 클릭했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"when_object_click_exampleCode\": \"def when_click_object_on():\\n    Entry.print_for_sec(\\\"회전!\\\", 0.5)\\n    Entry.add_rotation(90)\",\n    \"when_object_click_exampleDesc\": \"오브젝트를 클릭하면 오브젝트가 \\\"회전!\\\"이라 말하고, 90도 만큼 회전합니다.\",\n    \"when_object_click_canceled_desc\": \"해당 오브젝트 클릭을 해제했을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"when_object_click_canceled_exampleCode\": \"def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)\",\n    \"when_object_click_canceled_exampleDesc\": \"오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.\",\n    \"when_message_cast_desc\": \"A 신호를 받으면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.\",\n    \"when_message_cast_elements\": \"A-- \\\"신호 이름\\\"\",\n    \"when_message_cast_exampleCode\": \"def when_click_mouse_on():\\n    Entry.send_signal(\\\"신호\\\")\\n\\ndef when_get_signal(\\\"신호\\\"):\\n    Entry.print_for_sec(\\\"안녕! 반가워\\\", 0.5)\",\n    \"when_message_cast_exampleDesc\": \"마우스를 클릭하면 \\\"신호\\\"를 보내고, \\\"신호\\\"를 받았을때 \\\"안녕! 반가워\\\"라고 0.5초간 말합니다.\",\n    \"message_cast_desc\": \"A에 입력된 신호를 보냅니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.\",\n    \"message_cast_elements\": \"A-- \\\"신호 이름\\\"\",\n    \"message_cast_exampleCode\": \"#\\\"오브젝트1\\\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\\\"안녕! 넌 몇살이니?\\\", 2)\\n    Entry.send_signal(\\\"신호\\\")\\n\\n#\\\"오브젝트2\\\"의 파이선 코드\\ndef when_get_signal(\\\"신호\\\"):\\n    Entry.print_for_sec(\\\"안녕? 난 세 살이야.\\\", 2)\",\n    \"message_cast_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"오브젝트1\\\"이 \\\"안녕! 넌 몇살이니?\\\"라고 2초간 말하고 \\\"신호를 보냅니다., \\\"오브젝트2\\\"가 \\\"신호\\\"를 받았을때 \\\"안녕? 난 세 살이야.\\\"라고 2초간 말합니다.\",\n    \"message_cast_wait_desc\": \"A에 입력된 신호를 보내고, 해당 신호를 받는 명령어들의 실행이 끝날 때까지 기다립니다.<br>만약 A 신호가 없으면  [속성] 탭에 A 신호가 자동 생성됩니다.\",\n    \"message_cast_wait_elements\": \"A-- \\\"신호 이름\\\"\",\n    \"message_cast_wait_exampleCode\": \"#\\\"오브젝트1\\\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\\\"숨바꼭질하자!\\\", 2)\\n    Entry.send_signal_wait(\\\"신호\\\")\\n    Entry.hide()\\n\\n#\\\"오브젝트2\\\"의 파이선 코드\\ndef when_get_signal(\\\"신호\\\"):\\n    Entry.print_for_sec(\\\"그래!\\\", 2)\",\n    \"message_cast_wait_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"오브젝트1\\\"이 \\\"숨바꼭질하자!\\\"라고 2초 동안 말하고 \\\"신호\\\"를 보낸 후 기다립니다. \\\"오브젝트2\\\"가 \\\"신호\\\"를 받으면 \\\"그래!\\\"를 2초 동안 말합니다. \\\"오브젝트1\\\"이 그 후에 모양을 숨깁니다.\",\n    \"when_scene_start_desc\": \"장면이 시작되면 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"when_scene_start_exampleCode\": \"#\\\"장면 1\\\"의 파이선 코드\\ndef when_start():\\n    Entry.print_for_sec(\\\"다른 곳으로 가볼까?\\\", 2)\\n    Entry.start_scene(\\\"장면 2\\\")\\n\\n#\\\"장면 2\\\"의 파이선 코드\\ndef when_start_scene():\\n    Entry.print(\\\"여기가 어디지?\\\")\",\n    \"when_scene_start_exampleDesc\": \"\\\"장면 1\\\"에서 [시작하기]버튼을 클릭하면 \\\"다른 곳으로 가볼까?\\\"라고 2초간 말하고, \\\"장면 2\\\"가 시작됩니다. \\\"장면 2\\\"가 시작되면 오브젝트가 \\\"여기가 어디지?\\\"라고 말합니다.\",\n    \"start_scene_desc\": \"A 장면을 시작합니다.\",\n    \"start_scene_elements\": \"A-- \\\"장면 이름\\\"\",\n    \"start_scene_exampleCode\": \"#\\\"장면 1\\\"의 파이선 코드\\ndef when_click_object_on():\\n    Entry.start_scene(\\\"장면 2\\\")\",\n    \"start_scene_exampleDesc\": \"\\\"장면 1\\\"에서 해당 오브젝트를 클릭하면 \\\"장면 2\\\"가 시작됩니다.\",\n    \"start_neighbor_scene_desc\": \"A에 입력한 다음 또는 이전 장면을 시작합니다.\",\n    \"start_neighbor_scene_elements\": \"A-- 아래 선택지 중 하나<br>① 다음 장면: \\\"next\\\" 또는 \\\"다음\\\"<br>② 이전 장면: \\\"prev\\\" 또는 \\\"이전\\\"\",\n    \"start_neighbor_scene_exampleCode\": \"#\\\"장면 1\\\"의 파이선 코드\\ndef when_press_key(\\\"right\\\"):\\n    Entry.start_scene_of(\\\"next\\\")\\n\\n#\\\"장면 2\\\"의 파이선 코드\\ndef when_press_key(\\\"left\\\"):\\n    Entry.start_scene_of(\\\"prev\\\")\",\n    \"start_neighbor_scene_exampleDesc\": \"\\\"장면 1\\\"에서 오른쪽화살표키를 누르면 다음 장면이, \\\"장면 2\\\"에서 왼쪽화살표키를 누르면 이전 장면이 시작됩니다.\",\n    \"wait_second_desc\": \"A초만큼 기다린 후 다음 블록을 실행합니다.\",\n    \"wait_second_elements\": \"A-- 초에 해당하는 수 입력\",\n    \"wait_second_exampleCode\": \"def when_start():\\n    Entry.add_effect(\\\"color\\\", 10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_size(10)\",\n    \"wait_second_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트에 색깔효과를 10만큼 주고, 2초동안 기다린 다음 크기를 10만큼 커지게 합니다.\",\n    \"repeat_basic_desc\": \"아래 명령어들을 A번 반복하여 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"repeat_basic_elements\": \"A-- 반복할 횟수 입력\",\n    \"repeat_basic_exampleCode\": \"def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()\",\n    \"repeat_basic_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.\",\n    \"repeat_inf_desc\": \"A 판단이 True인 동안 아래 명령어들을 반복 실행합니다. A에 True를 입력하면 계속 반복됩니다. <br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"repeat_inf_elements\": \"A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\") 등\",\n    \"repeat_inf_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()\",\n    \"repeat_inf_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.\",\n    \"repeat_while_true_desc\": \"A 판단이 True가 될 때까지 아래 명령어들을 반복 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"repeat_while_true_elements\": \"A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\") 등\",\n    \"repeat_while_true_exampleCode\": \"def when_start():\\n    while not Entry.is_key_pressed(\\\"space\\\"):\\n        Entry.add_rotation(90)\",\n    \"repeat_while_true_exampleDesc\": \"[시작하기]버튼을 클릭하면 스페이스키를 누를때까지 오브젝트가 90도 만큼 회전합니다.\",\n    \"stop_repeat_desc\": \"이 명령어와 가장 가까운 반복 명령어의 반복을 중단합니다.\",\n    \"stop_repeat_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_key_pressed(\\\"enter\\\"):\\n            break\",\n    \"stop_repeat_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 계속 이동합니다. 엔터키를 누르면 반복이 중단됩니다.\",\n    \"_if_desc\": \"A 부분의 판단이 True이면 if A:아래 명령어들을 실행하고, False이면 실행하지 않습니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"_if_elements\": \"A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\") 등\",\n    \"_if_exampleCode\": \"def when_click_mouse_on():\\n    if (Entry.value_of_mouse_pointer(\\\"x\\\") > 0):\\n        Entry.print_for_sec(\\\"오른쪽!\\\", 0.5)\",\n    \"_if_exampleDesc\": \"마우스를 클릭했을 때 마우스 x좌표가 0보다 크면 오브젝트가 \\\"오른쪽!\\\"이라고 0.5초 동안 말합니다.\",\n    \"if_else_desc\": \"A 부분의 판단이 True이면 if A: 아래 명령어들을 실행하고, False이면 else: 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"if_else_elements\": \"A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\") 등\",\n    \"if_else_exampleCode\": \"def when_click_mouse_on():\\n    if Entry.is_touched(\\\"mouse_pointer\\\"):\\n        Entry.print(\\\"닿았다!\\\")\\n    else:\\n        Entry.print(\\\"안 닿았다!\\\")\",\n    \"if_else_exampleDesc\": \"마우스를 클릭했을 때 마우스포인터가 오브젝트에 닿았으면 \\\"닿았다!\\\"를 그렇지 않으면 \\\"안 닿았다!\\\"를 말합니다.\",\n    \"wait_until_true_desc\": \"A 부분의 판단이 True가 될 때까지 코드의 실행을 멈추고 기다립니다.\",\n    \"wait_until_true_elements\": \"A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\") 등\",\n    \"wait_until_true_exampleCode\": \"def when_start():\\n    Entry.print(\\\"엔터를 눌러봐!\\\")\\n    Entry.wait_until(Entry.is_key_pressed(\\\"enter\\\"))\\n    Entry.print(\\\"잘했어!\\\")\",\n    \"wait_until_true_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"엔터를 눌러봐!\\\"라 말하고, 엔터키를 누를 때까지 기다립니다. 엔터키를 누르면 \\\"잘했어!\\\"라 말합니다.\",\n    \"stop_object_desc\": \"A코드의 실행을 중지합니다.\",\n    \"stop_object_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"all\\\":  모든 오브젝트의 모든 코드<br>② \\\"self\\\" : 해당 오브젝트의 모든 코드<br>③ \\\"this\\\": 이 명령어가 포함된 코드<br>④ \\\"others\\\" : 해당 오브젝트의 코드 중 이 명령어가 포함된 코드를 제외한 모든 코드<br/>⑤ \\\"ohter_objects\\\" : 이 오브젝트를 제외한 다른 모든 오브젝트의 코드\",\n    \"stop_object_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to(\\\"mouse_pointer\\\")\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.stop_code(\\\"all\\\")\\n\",\n    \"stop_object_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 계속해서 마우스포인터 위치로  이동합니다. 스페이스키를 누르면 모든 코드의 실행이 중지됩니다.\",\n    \"restart_project_desc\": \"작품을 처음부터 다시 실행합니다.\",\n    \"restart_project_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.add_size(10)\\n\\ndef when_press_key(\\\"enter\\\"):\\n    Entry.start_again()\",\n    \"restart_project_exampleDesc\": \"[시작하기]버튼을 클릭하면 계속해서 오브젝트의 크기가 커집니다. 엔터키를 누르면 작품을 처음부터 다시 실행합니다.\",\n    \"when_clone_start_desc\": \"해당 오브젝트의 복제본이 새로 생성되었을 때 아래 명령어들을 실행합니다.<br>아래 명령어는 [Tab]키를 통해 들여쓰기합니다.\",\n    \"when_clone_start_exampleCode\": \"def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\\\"self\\\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\",\n    \"when_clone_start_exampleDesc\": \"[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.\",\n    \"create_clone_desc\": \"A 오브젝트의 복제본을 생성합니다.\",\n    \"create_clone_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"오브젝트 이름\\\"<br>② \\\"self\\\" 또는 \\\"자신\\\"\",\n    \"create_clone_exampleCode\": \"def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\\\"self\\\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\",\n    \"create_clone_exampleDesc\": \"[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다.\",\n    \"delete_clone_desc\": \"Entry.make_clone_of(A) 명령에 의해 생성된 복제본을 삭제합니다.\",\n    \"delete_clone_exampleCode\": \"def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\\\"자신\\\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_click_object_on():\\n    Entry.remove_this_clone()\",\n    \"delete_clone_exampleDesc\": \"[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 복제본을 클릭하면 클릭된 복제본을 삭제합니다.\",\n    \"remove_all_clones_desc\": \"해당 오브젝트의 모든 복제본을 삭제합니다.\",\n    \"remove_all_clones_exampleCode\": \"def when_start():\\n    for i in range(5):\\n        Entry.make_clone_of(\\\"자신\\\")\\n\\ndef when_make_clone():\\n    Entry.set_x(random.randint(-200, 200))\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.remove_all_clone()\",\n    \"remove_all_clones_exampleDesc\": \"[시작하기]버튼을 클릭하면 자신의 복제본 5개를 만듭니다. 복제본이 새로 생성되었을때 복제본의 x좌표를 -200에서 200사이의 무작위수로 정합니다. 스페이스 키를 누르면 모든 복제본을 삭제합니다.\",\n    \"move_direction_desc\": \"A만큼 오브젝트의 이동방향 화살표가 가리키는 방향으로 움직입니다.\",\n    \"move_direction_elements\": \"A-- 이동할 거리에 해당하는 수\",\n    \"move_direction_exampleCode\": \"def when_start():\\n    Entry.move_to_direction(10)\",\n    \"move_direction_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동합니다.\",\n    \"bounce_wall_desc\": \"오브젝트가 화면 끝에 닿으면 튕겨져 나옵니다.\",\n    \"bounce_wall_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.bounce_on_edge()\",\n    \"bounce_wall_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 계속해서 이동방향으로 10만큼 이동하고, 벽에 닿으면 튕깁니다.\",\n    \"move_x_desc\": \"오브젝트의 x좌표를 A만큼 바꿉니다.\",\n    \"move_x_elements\": \"A-- x좌표의 변화 값<br>① 양수: 오브젝트가 오른쪽으로 이동합니다.<br>② 음수: 오브젝트가 왼쪽으로 이동합니다.\",\n    \"move_x_exampleCode\": \"def when_start():\\n    Entry.add_x(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_x(-10)\",\n    \"move_x_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오른쪽으로 10만큼 이동하고 2초 동안 기다린 후 왼쪽으로 10만큼 이동합니다.\",\n    \"move_y_desc\": \"오브젝트의 y좌표를 A만큼 바꿉니다.\",\n    \"move_y_elements\": \"A-- y좌표의 변화 값<br>① 양수: 오브젝트가 위쪽으로 이동합니다.<br>② 음수: 오브젝트가 아래쪽으로 이동합니다.\",\n    \"move_y_exampleCode\": \"def when_start():\\n    Entry.add_y(10)\\n    Entry.wait_for_sec(2)\\n    Entry.add_y(-10)\",\n    \"move_y_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 위쪽으로 10만큼 이동하고 2초 동안 기다린 후 아래쪽으로 10만큼 이동합니다.\",\n    \"move_xy_time_desc\": \"오브젝트가 x와 y좌표를 각각 A와 B만큼 C초에 걸쳐 서서히 바꿉니다.\",\n    \"move_xy_time_elements\": \"A-- x좌표의 변화 값<br>① 양수: 오브젝트가 오른쪽으로 이동합니다.<br>② 음수: 오브젝트가 왼쪽으로 이동합니다.%nextB-- y좌표의 변화 값<br>① 양수: 오브젝트가 위쪽으로 이동합니다.<br>② 음수: 오브젝트가 아래쪽으로 이동합니다.%nextC-- 이동하는 시간(초)\",\n    \"move_xy_time_exampleCode\": \"def when_start():\\n    Entry.add_xy_for_sec(100, 100, 2)\\n    Entry.add_xy_for_sec(-100, -100, 2)\",\n    \"move_xy_time_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오른쪽 위로 100만큼 2초 동안 이동한 후 왼쪽 아래로 100만큼 2초 동안 이동합니다.\",\n    \"locate_x_desc\": \"오브젝트의 x좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)\",\n    \"locate_x_elements\": \"A-- 이동할 x좌표\",\n    \"locate_x_exampleCode\": \"def when_press_key(\\\"right\\\"):\\n    Entry.set_x(100)\\n\\ndef when_press_key(\\\"left\\\"):\\n    Entry.set_x(-100)\\n\",\n    \"locate_x_exampleDesc\": \"오른쪽화살표키를 누르면 오브젝트의 x좌표를 100으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 x좌표를 -100으로 정합니다.\",\n    \"locate_y_desc\": \"오브젝트의 y좌표를 A로 정합니다. (오브젝트의 중심점이 기준이 됩니다.)\",\n    \"locate_y_elements\": \"B-- 이동할 y좌표\",\n    \"locate_y_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.set_y(100)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.set_y(-100)\",\n    \"locate_y_exampleDesc\": \"위쪽화살표키를 누르면 오브젝트의 y좌표를 100으로 정하고, 아래쪽화살표키를 누르면 오브젝트의 y좌표를 -100으로 정합니다.\",\n    \"locate_xy_desc\": \"오브젝트가 좌표(A, B)로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)\",\n    \"locate_xy_elements\": \"A-- 이동할 x좌표%nextB-- 이동할 y좌표\",\n    \"locate_xy_exampleCode\": \"def when_click_mouse_on():\\n    Entry.set_xy(0, 0)\\n\\ndef when_press_key(\\\"right\\\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\\\"up\\\"):\\n    Entry.add_y(10)\",\n    \"locate_xy_exampleDesc\": \"오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 오브젝트의 x, y좌표를 0으로 정합니다.\",\n    \"locate_xy_time_desc\": \"오브젝트가 좌표(A, B)로 C초에 걸쳐 서서히 이동합니다.(오브젝트의 중심점이 기준이 됩니다.)\",\n    \"locate_xy_time_elements\": \"A-- 이동할 x좌표%nextB-- 이동할 y좌표%nextC-- 이동하는 시간\",\n    \"locate_xy_time_exampleCode\": \"def when_click_mouse_on():\\n    Entry.set_xy_for_sec(0, 0, 2)\\n\\ndef when_press_key(\\\"right\\\"):\\n    Entry.add_x(10)\\n\\ndef when_press_key(\\\"up\\\"):\\n    Entry.add_y(10)\",\n    \"locate_xy_time_exampleDesc\": \"오른쪽화살표키를 누르면 오브젝트의 x좌표를 10만큼 바꾸고, 위쪽화살표키를 누르면 오브젝트의 y좌표를 10만큼 바꿉니다. 마우스를 클릭하면 2초 동안 오브젝트를 x,y 좌표 0으로 이동시킵니다.\",\n    \"locate_desc\": \"오브젝트가 A의 위치로 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)\",\n    \"locate_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"오브젝트 이름\\\"<br>② \\\"mouse_pointer\\\" 또는 \\\"마우스포인터\\\"\",\n    \"locate_exampleCode\": \"def when_click_mouse_on():\\n    Entry.move_to(\\\"mouse_pointer\\\")\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.move_to(\\\"오브젝트\\\")\",\n    \"locate_exampleDesc\": \"마우스를 클릭하면 오브젝트가 마우스포인터 위치로 이동합니다.<br>스페이스키를 누르면 오브젝트가 \\\"오브젝트\\\" 위치로 이동합니다.\",\n    \"locate_object_time_desc\": \"오브젝트가 A의 위치로 B초에 걸쳐 서서히 이동합니다. (오브젝트의 중심점이 기준이 됩니다.)\",\n    \"locate_object_time_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"오브젝트 이름\\\"<br>② \\\"mouse_pointer\\\" 또는 \\\"마우스포인터\\\" %nextB-- 이동하는 시간(초)\",\n    \"locate_object_time_exampleCode\": \"def when_click_mouse_on():\\n    Entry.move_to_for_sec(\\\"mouse_pointer\\\", 2)\",\n    \"locate_object_time_exampleDesc\": \"마우스를 클릭하면 오브젝트가 2초 동안 서서히 마우스포인터 위치로 이동합니다.\",\n    \"rotate_relative_desc\": \"오브젝트의 방향을 A도만큼 시계방향으로 회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)\",\n    \"rotate_relative_elements\": \"A-- 회전할 각도\",\n    \"rotate_relative_exampleCode\": \"def when_click_object_on():\\n    Entry.add_rotation(90)\\n\\ndef when_click_object_off():\\n    Entry.add_rotation(-90)\",\n    \"rotate_relative_exampleDesc\": \"오브젝트를 클릭하면 오브젝트가 90도 만큼 회전하고, 오브젝트 클릭을 해제하면 오브젝트가 -90도 만큼 회전합니다.\",\n    \"direction_relative_desc\": \"오브젝트의 이동 방향을 A도만큼 회전합니다.\",\n    \"direction_relative_elements\": \"A-- 회전할 각도\",\n    \"direction_relative_exampleCode\": \"def when_start():\\n    Entry.move_to_direction(50)\\n    Entry.wait_for_sec(0.5)\\n    Entry.add_direction(90)\\n    Entry.wait_for_sec(0.5)\\n    Entry.move_to_direction(50)\",\n    \"direction_relative_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 50만큼 이동한 다음 0.5초간 기다립니다. 그 후 이동방향을 90도 만큼 회전하고 0.5초간 기다린 후 이동방향으로 50만큼 이동합니다.\",\n    \"rotate_by_time_desc\": \"오브젝트의 방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)\",\n    \"rotate_by_time_elements\": \"A-- 회전할 각도%nextB-- 회전할 시간(초)\",\n    \"rotate_by_time_exampleCode\": \"def when_start():\\n    Entry.add_rotation_for_sec(90, 2)\\n    Entry.add_rotation_for_sec(-90, 2)\",\n    \"rotate_by_time_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 2초 동안 90도 만큼 회전하고, 다시 2초 동안 -90도 만큼 회전합니다.\",\n    \"direction_relative_duration_desc\": \"오브젝트의 이동방향을 시계방향으로 A도만큼 B초에 걸쳐  회전합니다. (오브젝트의 중심점을 기준으로 회전합니다.)\",\n    \"direction_relative_duration_elements\": \"A-- 회전할 각도%nextB-- 회전할 시간(초)\",\n    \"direction_relative_duration_exampleCode\": \"def when_start():\\n    Entry.add_direction_for_sec(90, 2)\\n\\ndef when_start():\\n    while True:\\n        Entry.move_to_direction(1)\",\n    \"direction_relative_duration_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트의 이동방향을 2초 동안 90도만큼 회전시킵니다. 동시에 오브젝트는 이동방향으로 1만큼 계속 이동합니다.\",\n    \"rotate_absolute_desc\": \"오브젝트의 방향을 A로 정합니다.\",\n    \"rotate_absolute_elements\": \"A-- 설정할 방향\",\n    \"rotate_absolute_exampleCode\": \"def when_press_key(\\\"right\\\"):\\n    Entry.set_rotation(90)\\n\\ndef when_press_key(\\\"left\\\"):\\n    Entry.set_rotation(270)\",\n    \"rotate_absolute_exampleDesc\": \"오른쪽화살표키를 누르면 오브젝트의 방향을 90으로 정하고, 왼쪽화살표키를 누르면 오브젝트의 방향을 270으로 정합니다.\",\n    \"direction_absolute_desc\": \"오브젝트의 이동방향을 A로 정합니다.\",\n    \"direction_absolute_elements\": \"A-- 설정할 이동방향\",\n    \"direction_absolute_exampleCode\": \"def when_press_key(\\\"right\\\"):\\n    Entry.set_direction(90)\\n    Entry.move_to_direction(10)\\n\\ndef when_press_key(\\\"left\\\"):\\n    Entry.set_direction(270)\\n    Entry.move_to_direction(10)\",\n    \"direction_absolute_exampleDesc\": \"오른쪽화살표키를 누르면 오브젝트의 이동방향을 90으로 정한 후 해당 쪽으로 10만큼 이동하고, 왼쪽화살표키를 누르면 오브젝트의 이동방향을 270으로 정하고 해당쪽으로 10만큼 이동합니다.\",\n    \"see_angle_object_desc\": \"오브젝트가 A쪽을 바라봅니다. (이동방향이 A를 향하도록 오브젝트의 방향을 회전해줍니다.)\",\n    \"see_angle_object_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"오브젝트 이름\\\"<br>② \\\"mouse_pointer\\\" 또는 \\\"마우스포인터\\\"\",\n    \"see_angle_object_exampleCode\": \"def when_click_mouse_on():\\n    Entry.look_at(\\\"mouse_pointer\\\")\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.look_at(\\\"오브젝트\\\")\",\n    \"see_angle_object_exampleDesc\": \"마우스를 클릭하면 오브젝트가 마우스포인터쪽을 바라보고, 스페이스키를 누르면 \\\"오브젝트\\\"쪽을 바라봅니다.\",\n    \"move_to_angle_desc\": \"오브젝트가 A만큼 B방향으로 움직입니다.\",\n    \"move_to_angle_elements\": \"A-- 이동할 거리에 해당하는 수%nextB-- 이동할 방향(12시 방향이 0도, 시계방향으로 증가)\",\n    \"move_to_angle_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.move_to_degree(10, 0)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.move_to_degree(10, 180)\",\n    \"move_to_angle_exampleDesc\": \"위쪽화살표키를 누르면 오브젝트가 0도방향으로 10만큼 이동하고, 아래쪽화살표키를 누르면 오브젝트가 180도방향으로 10만큼 이동합니다.\",\n    \"show_desc\": \"오브젝트를 화면에 나타냅니다.\",\n    \"show_exampleCode\": \"def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()\",\n    \"show_exampleDesc\": \"[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.\",\n    \"hide_desc\": \"오브젝트를 화면에서 보이지 않게 합니다.\",\n    \"hide_exampleCode\": \"def when_start():\\n    Entry.wait_for_sec(1)\\n    Entry.hide()\\n    Entry.wait_for_sec(1)\\n    Entry.show()\",\n    \"hide_exampleDesc\": \"[시작하기]버튼을 클릭하면 1초 뒤에 오브젝트 모양이 숨겨지고, 다음 1초 뒤에 오브젝트 모양이 나타납니다.\",\n    \"dialog_time_desc\": \"오브젝트가 A를 B초 동안 말풍선으로 말한 후 다음 명령어가 실행됩니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.\",\n    \"dialog_time_elements\": \"A-- 말할 내용<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등%nextB-- 말하는 시간(초)\",\n    \"dialog_time_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(\\\"안녕! 나는\\\", 2)\\n    Entry.print_for_sec(16, 2)\\n    Entry.print_for_sec(\\\"살이야\\\", 2)\",\n    \"dialog_time_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"안녕! 나는\\\", 16, \\\"살이야\\\"를 각각 2초 동안 차례대로 말합니다.\",\n    \"dialog_desc\": \"오브젝트가 A를 말풍선으로 말합니다. 콘솔창에서도 실행 결과를 볼 수 있습니다.\",\n    \"dialog_elements\": \"A-- 말할 내용<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등\",\n    \"dialog_exampleCode\": \"def when_start():\\n    Entry.print(\\\"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\\\")\\n\\ndef when_press_key(1):\\n    Entry.print(1)\\n\\ndef when_press_key(2):\\n    Entry.print(2)\\n\",\n    \"dialog_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"키보드로 숫자 1,2 를 누르면 숫자를 말해볼게\\\"를 말하고, 키보드로 1, 2를 누르면 각각 1, 2라 말합니다.\",\n    \"remove_dialog_desc\": \"오브젝트가 말하고 있는 말풍선을 지웁니다.\",\n    \"remove_dialog_exampleCode\": \"def when_start():\\n    Entry.print(\\\"말풍선을 지우려면 엔터를 눌러!\\\")\\n\\ndef when_press_key(\\\"enter\\\"):\\n    Entry.clear_print()\",\n    \"remove_dialog_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"말풍선을 지우려면 엔터를 눌러!\\\"라 말하고, 엔터키를 누르면 말풍선이 사라집니다.\",\n    \"change_to_some_shape_desc\": \"오브젝트를 A 모양으로 바꿉니다.\",\n    \"change_to_some_shape_elements\": \"A-- 아래 선택지 중 하나<br>① 모양 이름 : [속성] 탭의 \\\"모양 이름\\\"을 적음<br>② 모양 번호 : [속성] 탭의 모양 번호를 적음\",\n    \"change_to_some_shape_exampleCode\": \"def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\\\"오브젝트모양\\\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape(\\\"오브젝트모양\\\")\",\n    \"change_to_some_shape_exampleDesc\": \"[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 \\\"오브젝트모양\\\"으로 모양을 바꾸고 0.3초간 기다린 다음 \\\"오브젝트모양\\\"모양으로 모양을 바꿉니다.\",\n    \"change_to_next_shape_desc\": \"오브젝트의 모양을 다음 또는 이전 모양으로 바꿉니다.\",\n    \"change_to_next_shape_elements\": \"A-- 아래 선택지 중 하나<br>① 다음 모양 : \\\"next\\\" 또는 \\\"다음\\\" <br>② 이전 모양 : \\\"pre\\\" 또는 \\\"이전\\\"\",\n    \"change_to_next_shape_exampleCode\": \"def when_start():\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\\\"next\\\")\\n    Entry.wait_for_sec(0.3)\\n    Entry.change_shape_to(\\\"pre\\\")\",\n    \"change_to_next_shape_exampleDesc\": \"[시작하기]버튼을 클릭하면 0.3초간 기다린 다음 모양으로 오브젝트 모양을 바꾸고 0.3초간 기다린 다음 이전 모양으로 오브젝트 모양을 바꿉니다.\",\n    \"add_effect_amount_desc\": \"오브젝트에 A 효과를 B만큼 줍니다.\",\n    \"add_effect_amount_elements\": \"A -- 아래 선택지 중 하나<br>① “color” 또는 “색깔“                 <br>② “brightness” 또는 “밝기”                <br>③ “transparency” 또는 “투명도”%nextB-- 효과의 변화 정도\",\n    \"add_effect_amount_exampleCode\": \"def when_click_mouse_on():\\n    Entry.add_effect(\\\"color\\\", 50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\\\"brightness\\\", -50)\\n    Entry.wait_for_sec(1)\\n    Entry.add_effect(\\\"transparency\\\", 50)\",\n    \"add_effect_amount_exampleDesc\": \"마우스를 클릭하면 오브젝트에 색깔 효과를 50만큼 주고 1초간 기다리고, 밝기 효과를 -50만큼 주고 1초간 기다립니다. 그 후 투명도 효과를 50만큼 줍니다.\",\n    \"change_effect_amount_desc\": \"오브젝트의 A 효과를 B로 정합니다.\",\n    \"change_effect_amount_elements\": \"A-- 아래 선택지 중 하나<br>① “color” 또는 “색깔“                 <br>② “brightness” 또는 “밝기”                <br>③ “transparency” 또는 “투명도”%nextB-- 효과의 값<br>① color: 0~100 범위의 수, 100을 주기로 반복됨<br>② brightness: -100~100 사이 범위의 수, -100이하는 -100 으로 100 이상은 100 으로 처리 됨<br>③ transparency: 0~100 사이 범위의 수, 0 이하는 0으로, 100이상은 100으로 처리 됨\",\n    \"change_effect_amount_exampleCode\": \"def when_click_mouse_on():\\n    Entry.set_effect(\\\"color\\\", 50)\\n    Entry.set_effect(\\\"brightness\\\", 50)\\n    Entry.set_effect(\\\"transparency\\\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.set_effect(\\\"color\\\", 0)\\n    Entry.set_effect(\\\"brightness\\\", 0)\\n    Entry.set_effect(\\\"transparency\\\", 0)\",\n    \"change_effect_amount_exampleDesc\": \"마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 각 효과를 0으로 정합니다.\",\n    \"erase_all_effects_desc\": \"오브젝트에 적용된 효과를 모두 지웁니다.\",\n    \"erase_all_effects_exampleCode\": \"def when_click_mouse_on():\\n    Entry.set_effect(\\\"color\\\", 50)\\n    Entry.set_effect(\\\"brightness\\\", 50)\\n    Entry.set_effect(\\\"transparency\\\", 50)\\n\\ndef when_click_mouse_off():\\n    Entry.clear_effect()\\n\",\n    \"erase_all_effects_exampleDesc\": \"마우스를 클릭하면 오브젝트에 색깔, 밝기, 투명도 효과를 50으로 정하고, 마우스 클릭을 해제하면 오브젝트에 적용된 모든 효과를 지웁니다.\",\n    \"change_scale_size_desc\": \"오브젝트의 크기를 A만큼 바꿉니다.\",\n    \"change_scale_size_elements\": \"A-- 크기 변화 값\",\n    \"change_scale_size_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.set_size(100)\",\n    \"change_scale_size_exampleDesc\": \"위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.\",\n    \"set_scale_size_desc\": \"오브젝트의 크기를 A로 정합니다.\",\n    \"set_scale_size_elements\": \"A-- 크기값\",\n    \"set_scale_size_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.add_size(10)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.add_size(-10)\\n\\ndef when_press_key(\\\"space\\\"):\\n    Entry.set_size(100)\",\n    \"set_scale_size_exampleDesc\": \"위쪽화살표키를 누르면 오브젝트의 크기가 10만큼 커지고, 아래쪽화살표키를 누르면 오브젝트의 크기가 10만큼 작아집니다. 스페이스키를 누르면 오브젝트의 크기를 100으로 정합니다.\",\n    \"flip_x_desc\": \"오브젝트의 상하 모양을 뒤집습니다.\",\n    \"flip_x_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\\\"right\\\"):\\n    Entry.flip_vertical()\",\n    \"flip_x_exampleDesc\": \"위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.\",\n    \"flip_y_desc\": \"오브젝트의 좌우 모양을 뒤집습니다.\",\n    \"flip_y_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.flip_horizontal()\\n\\ndef when_press_key(\\\"right\\\"):\\n    Entry.flip_vertical()\",\n    \"flip_y_exampleDesc\": \"위쪽화살표키를 누르면 오브젝트의 상하 모양을 뒤집고, 오른쪽화살표키를 누르면 오브젝트의 좌우 모양을 뒤집습니다.\",\n    \"change_object_index_desc\": \"오브젝트의 레이어를 A로 가져옵니다.\",\n    \"change_object_index_elements\": \"A-- 아래 선택지 중 하나<br>① “front\\\" 또는 “맨 앞“                 <br>② “forward” 또는 “앞”                <br>③ “backward” 또는 “뒤”<br>④ “back” 또는 “맨 뒤”\",\n    \"change_object_index_exampleCode\": \"def when_start():\\n    Entry.send_layer_to(\\\"front\\\")\\n    Entry.wait_for_sec(2)\\n    Entry.send_layer_to(\\\"backward\\\")\",\n    \"change_object_index_exampleDesc\": \"오브젝트가 여러개가 겹쳐 있을 경우 [시작하기]버튼을 클릭하면  해당 오브젝트의 레이어를 가장 앞으로 가져와서 보여줍니다.\",\n    \"brush_stamp_desc\": \"오브젝트의 모양을 도장처럼 실행화면 위에 찍습니다.\",\n    \"brush_stamp_exampleCode\": \"def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\\n        Entry.stamp()\",\n    \"brush_stamp_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 이동방향으로 10만큼 이동하고, 도장찍는 행동을 10번 반복합니다.\",\n    \"start_drawing_desc\": \"오브젝트가 이동하는 경로를 따라 선이 그려지기 시작합니다. (오브젝트의 중심점이 기준)\",\n    \"start_drawing_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    for i in range(10):\\n        Entry.move_to_direction(10)\",\n    \"start_drawing_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작되고, 오브젝트가 이동방향으로 10만큼 10번 이동할 때 오브젝트의 이동경로를 따라 선이 그려집니다.\",\n    \"stop_drawing_desc\": \"오브젝트가 선을 그리는 것을 멈춥니다.\",\n    \"stop_drawing_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n\\ndef when_click_mouse_on():\\n    Entry.stop_drawing()\",\n    \"stop_drawing_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작되고 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 마우스를 클릭하면 그리는것을 멈춥니다.\",\n    \"set_color_desc\": \"오브젝트가 그리는 선의 색을 A로 정합니다.\",\n    \"set_color_elements\": \"A-- 아래 선택지 중 하나<br>① 색상 코드 : \\\"#FF0000\\\", \\\"#FFCC00\\\", \\\"#3333FF\\\", \\\"#000000\\\" 등<br>② 색깔명 : \\\"red\\\", \\\"orange\\\", \\\"yellow\\\", \\\"green\\\", \\\"blue\\\", \\\"navy\\\", \\\"purple\\\", \\\"black\\\", \\\"white\\\", \\\"brown\\\"\",\n    \"set_color_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_color_to(\\\"#000099\\\")\\n    while True:\\n        Entry.move_to_direction(1)\",\n    \"set_color_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 색을 \\\"#000099\\\"로 정합니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.\",\n    \"set_random_color_desc\": \"오브젝트가 그리는 선의 색을 무작위로 정합니다.\",\n    \"set_random_color_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(1)\\n        Entry.set_brush_color_to_random()\",\n    \"set_random_color_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 1만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 색깔은 계속해서 무작위로 정해집니다.\",\n    \"change_thickness_desc\": \"오브젝트가 그리는 선의 굵기를 A만큼 바꿉니다.\",\n    \"change_thickness_elements\": \"A-- 굵기 변화 값\",\n    \"change_thickness_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.add_brush_size(1)\\n        Entry.move_to_direction(10)\",\n    \"change_thickness_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 굵기는 계속해서 1씩 커집니다.\",\n    \"set_thickness_desc\": \"오브젝트가 그리는 선의 굵기를 A로 정합니다.\",\n    \"set_thickness_elements\": \"A-- 굵기값(1이상의 수)\",\n    \"set_thickness_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)\",\n    \"set_thickness_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.\",\n    \"change_brush_transparency_desc\": \"오브젝트가 그리는 선의 투명도를 A만큼 바꿉니다.\",\n    \"change_brush_transparency_elements\": \"A-- 투명도 변화 값\",\n    \"change_brush_transparency_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    while True:\\n        Entry.move_to_direction(10)\\n        Entry.add_brush_transparency(5)\",\n    \"change_brush_transparency_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 선의 투명도는 계속해서 5만큼 바꿉니다.\",\n    \"set_brush_tranparency_desc\": \"오브젝트가 그리는 선의 투명도를 A로 정합니다.\",\n    \"set_brush_tranparency_elements\": \"A-- 투명도값(0~100 의 범위)\",\n    \"set_brush_tranparency_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    Entry.set_brush_size(10)\\n    Entry.set_brush_transparency(50)\\n    while True:\\n        Entry.move_to_direction(10)\",\n    \"set_brush_tranparency_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작되고, 선의 굵기를 10으로, 선의 투명도를 50으로 정합니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다.\",\n    \"brush_erase_all_desc\": \"오브젝트가 그린 선과 도장을 모두 지웁니다.\",\n    \"brush_erase_all_exampleCode\": \"def when_start():\\n    Entry.start_drawing()\\n    while True:\\n        Entry.move_to_direction(10)\\n\\ndef when_click_mouse_on():\\n    Entry.clear_drawing()\",\n    \"brush_erase_all_exampleDesc\": \"[시작하기]버튼을 클릭하면 그리기가 시작됩니다. 오브젝트는 계속해서 이동방향으로 10만큼 움직이고, 오브젝트의 이동경로를 따라 선이 그려집니다. 마우스를 클릭하면 오브젝트가 그린 선을 모두 지웁니다.\",\n    \"text_read_desc\": \"글상자 A의 내용입니다.<br />(내용 안에 개행이 있는 경우, 띄어쓰기하여 반환됩니다.)\",\n    \"text_read_elements\": \"A-- 아래 선택지 중 하나<br />① \\\"오브젝트(글상자) 이름\\\" <br />② 자기 자신\",\n    \"text_read_exampleCode\": \"def when_start():\\n    Entry.print(Entry.contents_of_textbox(\\\"A\\\"))\",\n    \"text_read_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 글상자 \\\"A\\\"의 내용을 말합니다.​\",\n    \"text_write_desc\": \"글상자의 내용을 A로 고쳐씁니다.\",\n    \"text_write_elements\": \"A-- 글상자의 내용<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등\",\n    \"text_write_exampleCode\": \"def when_start():\\n    Entry.write_text(\\\"엔트리\\\")\",\n    \"text_write_exampleDesc\": \"[시작하기]버튼을 클릭하면 글상자의 내용을 \\\"엔트리\\\"로 바꿉니다.\",\n    \"text_append_desc\": \"글상자의 내용 뒤에 A를 추가합니다.\",\n    \"text_append_elements\": \"A-- 글상자의 내용<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등\",\n    \"text_append_exampleCode\": \"def when_start():\\n    Entry.write_text(\\\"안녕?\\\")\\n    Entry.wait_for_sec(1)\\n    Entry.append_text(\\\"엔트리!\\\")\",\n    \"text_append_exampleDesc\": \"[시작하기]버튼을 클릭하면 글상자의 내용이 \\\"안녕?\\\"이 되었다가 1초 뒤에 \\\"엔트리!\\\"가 추가되어 \\\"안녕?엔트리!\\\"가 됩니다.\",\n    \"text_prepend_desc\": \"글상자의 내용 앞에 A를 추가합니다.\",\n    \"text_prepend_elements\": \"A-- 글상자의 내용<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등\",\n    \"text_prepend_exampleCode\": \"def when_start():\\n    Entry.write_text(\\\"반가워!\\\")\\n    Entry.wait_for_sec(1)\\n    Entry.prepend_text(\\\"엔트리!\\\")\",\n    \"text_prepend_exampleDesc\": \"[시작하기]버튼을 클릭하면 글상자의 내용이 \\\"반가워!\\\"가 되었다가 1초 뒤에 \\\"엔트리!\\\"가 앞에 추가되어 \\\"엔트리!반가워!\\\"가 됩니다.\",\n    \"text_flush_desc\": \"글상자에 저장된 값을 모두 지웁니다.\",\n    \"text_flush_exampleCode\": \"def when_start():\\n    Entry.write_text(\\\"엔트리\\\")\\n    Entry.wait_for_sec(1)\\n    Entry.clear_text()\",\n    \"text_flush_exampleDesc\": \"[시작하기]버튼을 클릭하면 글상자의 내용이 \\\"엔트리\\\"가 되었다가 1초 뒤에 모든 내용이 사라집니다.\",\n    \"sound_something_with_block_desc\": \"오브젝트가 A 소리를 재생합니다.\",\n    \"sound_something_with_block_elements\": \"A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \\\"소리 이름\\\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음\",\n    \"sound_something_with_block_exampleCode\": \"def when_start():\\n    Entry.play_sound(\\\"소리\\\")\\n    Entry.add_size(50)\",\n    \"sound_something_with_block_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 재생하면서 오브젝트의 크기가 50만큼 커집니다.\",\n    \"sound_something_second_with_block_desc\": \"오브젝트가 A소리를 B초 만큼 재생합니다.\",\n    \"sound_something_second_with_block_elements\": \"A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \\\"소리 이름\\\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음\",\n    \"sound_something_second_with_block_exampleCode\": \"def when_start():\\n    Entry.play_sound_for_sec(\\\"소리\\\", 1)\\n    Entry.add_size(50)\",\n    \"sound_something_second_with_block_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 1초 동안 재생하면서, 오브젝트의 크기가 50만큼 커집니다.\",\n    \"sound_from_to_desc\": \"오브젝트가 A소리를 B초부터 C초까지 재생합니다.\",\n    \"sound_from_to_elements\": \"A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \\\"소리 이름\\\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음\",\n    \"sound_from_to_exampleCode\": \"def when_start():\\n    Entry.play_sound_from_to(\\\"소리\\\", 0.5, 1)\\n    Entry.add_size(50)\",\n    \"sound_from_to_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 0.5초부터 1초 구간까지만 재생하면서, 오브젝트의 크기가 50만큼 커집니다.\",\n    \"sound_something_wait_with_block_desc\": \"오브젝트가 A 소리를 재생하고, 재생이 끝나면 다음 명령을 실행합니다.\",\n    \"sound_something_wait_with_block_elements\": \"A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \\\"소리 이름\\\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음\",\n    \"sound_something_wait_with_block_exampleCode\": \"def when_start():\\n    Entry.play_sound_and_wait(\\\"소리\\\")\\n    Entry.add_size(50)\",\n    \"sound_something_wait_with_block_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.\",\n    \"sound_something_second_wait_with_block_desc\": \"오브젝트가 A소리를 B초 만큼 재생하고, 재생이 끝나면 다음 명령을 실행합니다.\",\n    \"sound_something_second_wait_with_block_elements\": \"A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \\\"소리 이름\\\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음\",\n    \"sound_something_second_wait_with_block_exampleCode\": \"def when_start():\\n    Entry.play_sound_for_sec_and_wait(\\\"소리\\\", 1)\\n    Entry.add_size(50)\",\n    \"sound_something_second_wait_with_block_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 1초 동안 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.\",\n    \"sound_from_to_and_wait_desc\": \"오브젝트가 A소리를 B초부터 C초까지 재생하고, 재생이 끝나면 다음 명령을 실행합니다.\",\n    \"sound_from_to_and_wait_elements\": \"A-- 아래 선택지 중 하나<br>① 소리 이름 : [속성] 탭의 \\\"소리 이름\\\"을 적음<br>② 소리 번호: [속성] 탭의 소리 번호를 적음\",\n    \"sound_from_to_and_wait_exampleCode\": \"def when_start():\\n    Entry.play_sound_from_to_and_wait(\\\"소리\\\", 0.5, 1)\\n    Entry.add_size(50)\",\n    \"sound_from_to_and_wait_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 0.5초부터 1초 구간까지만 재생하고, 재생이 끝나면 오브젝트의 크기가 50만큼 커집니다.\",\n    \"sound_volume_change_desc\": \"작품에서 재생되는 모든 소리의 크기를 A퍼센트만큼 바꿉니다.\",\n    \"sound_volume_change_elements\": \"A-- 소리 크기 변화 값\",\n    \"sound_volume_change_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\\\"소리\\\")\",\n    \"sound_volume_change_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\\\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\\\"작아집니다.\",\n    \"sound_volume_set_desc\": \"작품에서 재생되는 모든 소리의 크기를 A퍼센트로 정합니다.\",\n    \"sound_volume_set_elements\": \"A-- 소리 크기값\",\n    \"sound_volume_set_exampleCode\": \"def when_press_key(\\\"up\\\"):\\n    Entry.add_sound_volume(10)\\n\\ndef when_press_key(\\\"down\\\"):\\n    Entry.add_sound_volume(-10)\\n\\ndef when_press_key(\\\"enter\\\"):\\n    Entry.set_sound_volume(100)\\n\\ndef when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\\\"소리\\\")\",\n    \"sound_volume_set_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 계속 재생합니다. 위쪽화살표키를 누르면 소리의 크기가 10\\\" 커지고, 아래쪽화살표키를 누르면 소리의 크기가 10\\\"작아집니다. 엔터키를 누르면 소리의 크기를 100\\\"로 정합니다.\",\n    \"sound_silent_all_desc\": \"현재 재생 중인 모든 소리를 멈춥니다.\",\n    \"sound_silent_all_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.play_sound_and_wait(\\\"소리\\\")\\n\\ndef when_press_key(\\\"enter\\\"):\\n    Entry.stop_sound()\",\n    \"sound_silent_all_exampleDesc\": \"[시작하기]버튼을 클릭하면 \\\"소리\\\"를 계속 재생합니다. 엔터키를 누르면 현재 재생 중인 소리를 멈춥니다.\",\n    \"is_clicked_desc\": \"마우스를 클릭한 경우 True로 판단합니다.\",\n    \"is_clicked_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_mouse_clicked():\\n            Entry.print_for_sec(\\\"반가워!\\\", 0.5)\",\n    \"is_clicked_exampleDesc\": \"[시작하기]버튼을 클릭하면 계속해서 마우스를 클릭했는지 확인합니다. 만약 마우스를 클릭하면 오브젝트가 \\\"반가워!\\\"라고 0.5초간 말합니다.\",\n    \"is_press_some_key_desc\": \"A 키가 눌려져 있는 경우 True로 판단합니다.\",\n    \"is_press_some_key_elements\": \"A-- 아래 선택지 중 하나<br>① 알파벳 : \\\"A\\\", \\\"B\\\" ~ \\\"Z\\\" 등(소문자 가능)<br>② 숫자: 1, 2, 3, 4 ~ 9, 0<br>③ 특수키: \\\"space\\\", \\\"enter\\\"<br>④ 방향키 : \\\"up\\\", \\\"down\\\", \\\"right\\\", \\\"left\\\"\",\n    \"is_press_some_key_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\\\"space\\\"):\\n            Entry.move_to_direction(10)\",\n    \"is_press_some_key_exampleDesc\": \"[시작하기]버튼을 클릭하면 계속해서 선택한 키를 눌렀는지 확인합니다. 만약 스페이스 키를 누르면 오브젝트가 이동방향으로 10만큼 이동합니다.\",\n    \"reach_something_desc\": \"오브젝트가 A와 닿은 경우 True으로 판단합니다.\",\n    \"reach_something_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"오브젝트 이름\\\"<br>② \\\"mouse_pointer\\\" 또는 \\\"마우스포인터\\\"<br>③ \\\"edge\\\", \\\"edge_up\\\", \\\"edge_down\\\", \\\"edge_right\\\", \\\"edge_left\\\"\",\n    \"reach_something_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.move_to_direction(10)\\n        if Entry.is_touched(\\\"edge\\\"):\\n            Entry.add_rotation(150)\",\n    \"reach_something_exampleDesc\": \"[시작하기]버튼을 클릭하면 계속해서 오브젝트가 이동방향으로 10만큼 이동합니다. 만약 오브젝트가 벽에 닿으면 150만큼 회전하게 됩니다.\",\n    \"boolean_basic_operator_desc\": \"A와 B를 비교하여 True 또는 False로 판단합니다.\",\n    \"boolean_basic_operator_elements\": \"A, B-- 비교하고자 하는 숫자값<br>① == : A와 B의 값이 같으면 True, 아니면 False<br>② > : A의 값이 B의 값보다 크면 true, 아니면 False<br>③ < : A의 값이 B의 값보다 작으면 true, 아니면 False<br>④ >= : A의 값이 B의 값보다 크거나 같으면 true, 아니면 False<br>⑤ <= : A의 값이 B의 값보다 작거나 같으면 true, 아니면 False\",\n    \"boolean_basic_operator_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.add_x(10)\\n        if Entry.value_of_object(\\\"오브젝트\\\", \\\"x\\\") > 240:\\n            Entry.set_x(0)\",\n    \"boolean_basic_operator_exampleDesc\": \"[시작하기]버튼을 클릭하면 계속해서 오브젝트 x좌표를 10만큼 바꿉니다. 만약 오브젝트 x좌표가 240보다 크면 오브젝트 x좌표를 0으로 정합니다.\",\n    \"boolean_and_desc\": \"A와 B의 판단이 모두 True인 경우 True, 아닌 경우 False로 판단합니다.\",\n    \"boolean_and_elements\": \"A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\") 등\",\n    \"boolean_and_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\\\"a\\\") and Entry.is_key_pressed(\\\"s\\\"):\\n            Entry.add_effect(\\\"color\\\", 10)\",\n    \"boolean_and_exampleDesc\": \"[시작하기]버튼을 클릭하고 키보드의 \\\"a\\\" 와 \\\"s\\\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.\",\n    \"boolean_or_desc\": \"A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False로 판단합니다.\",\n    \"boolean_or_elements\": \"A, B-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\") 등\",\n    \"boolean_or_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\\\"a\\\") or Entry.is_key_pressed(\\\"s\\\"):\\n            Entry.add_effect(\\\"color\\\", 10)\",\n    \"boolean_or_exampleDesc\": \"[시작하기]버튼을 클릭하면 키보드의 \\\"a\\\"나 \\\"s\\\"키 중 무엇이든 하나를 누르면 오브젝트에 색깔 효과를 10만큼 줍니다.\",\n    \"boolean_not_desc\": \"A 판단이 True이면 False, False이면 True로 판단합니다.\",\n    \"boolean_not_elements\": \"A-- True 또는 False로 판단할 수 있는 명령어 입력(판단 카테고리의 명령어)<br>① True, False<br>② 10 == 10 , 10 > 10 , 10 <= 10 등<br>③ Entry.is_mouse_clicked(), Entry.is_key_pressed(\\\"Q\\\") 등\",\n    \"boolean_not_exampleCode\": \"def when_start():\\n    while True:\\n        if not Entry.is_mouse_clicked():\\n            Entry.add_size(1)\",\n    \"boolean_not_exampleDesc\": \"[시작하기]버튼을 클릭하면 마우스를 클릭하지 않은 동안 크기가 1씩 커집니다.\",\n    \"calc_basic_desc\": \"A와 B의 연산값입니다.\",\n    \"calc_basic_elements\": \"A, B-- 연산하고자 하는 숫자값<br>① + : A와 B를 더한 값<br>② - : A와 B를 뺀 값<br>③ x : A와 B를 곱한 값<br>④ / : A와 B를 나눈 값\",\n    \"calc_basic_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(10 + 10, 2)\\n    Entry.print_for_sec(10 - 10, 2)\\n    Entry.print_for_sec(10 * 10, 2)\\n    Entry.print_for_sec(10 / 10, 2)\",\n    \"calc_basic_exampleDesc\": \"[시작하기]버튼을 클릭하면 10과 10을 더한값, 뺀값, 곱한값, 나눈값을 각 2초간 말합니다.\",\n    \"calc_rand_desc\": \"A와 B 사이에서 선택된 무작위 수의 값입니다. (두 수 모두 정수를 입력한 경우 정수로,두 수 중 하나라도 소수를 입력한 경우 소수로 무작위 수가 선택됩니다.)\",\n    \"calc_rand_elements\": \"A, B-- 무작위 수를 추출할 범위<br>① random.randint(A, B) : A, B를 정수로 입력하면 정수 범위에서 무작위 수를 추출<br>② random.uniform(A, B) : A, B를 실수로 입력하면 실수 범위에서 무작위 수를 추출\",\n    \"calc_rand_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(random.randint(1, 10), 2)\\n    Entry.print_for_sec(random.uniform(0.1, 2), 2)\",\n    \"calc_rand_exampleDesc\": \"[시작하기]버튼을 클릭하면 1부터 10사이의 정수중 무작위 수를 뽑아 2초간 말합니다. 그 후 0.1부터 2사이의 실수중 무작위 수를 뽑아 2초간 말합니다.\",\n    \"coordinate_mouse_desc\": \"마우스 포인터의 A 좌표 값을 의미합니다.\",\n    \"coordinate_mouse_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"x\\\" 또는 \\\"X\\\"<br>② \\\"y\\\" 또는 \\\"Y\\\"\",\n    \"coordinate_mouse_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_mouse_pointer(\\\"x\\\"))\",\n    \"coordinate_mouse_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 마우스 포인터의 x좌표를 계속해서 말합니다.\",\n    \"coordinate_object_desc\": \"A에 대한 B정보값입니다.\",\n    \"coordinate_object_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"오브젝트 이름\\\"<br>② \\\"self\\\" 또는 \\\"자신\\\"%nextB-- 아래 선택지 중 하나<br>① \\\"x\\\" 또는 \\\"X\\\"<br>② \\\"y\\\" 또는 \\\"Y\\\"<br>③ \\\"rotation\\\" 또는 \\\"방향\\\"<br>④ \\\"direction\\\" 또는 \\\"이동 방향\\\"<br>⑤ \\\"size\\\"  또는 \\\"크기\\\"<br>⑥ \\\"shape_number\\\" 또는 \\\"모양 번호\\\"<br>⑦ \\\"shape_name\\\" 또는 \\\"모양 이름\\\"\",\n    \"coordinate_object_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.add_x(1)\\n        Entry.print(Entry.value_of_object(\\\"오브젝트\\\", \\\"x\\\"))\\n\",\n    \"coordinate_object_exampleDesc\": \"[시작하기]버튼을 클릭하면 계속해서 오브젝트의 x좌표가 1씩 증가하며, \\\"오브젝트\\\"의 x좌표를 말합니다.\",\n    \"get_sound_volume_desc\": \"현재 작품에 설정된 소리의 크기값입니다.\",\n    \"get_sound_volume_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_sound_volume())\",\n    \"get_sound_volume_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 소리의 크기값을 계속해서 말합니다.\",\n    \"quotient_and_mod_desc\": \"A와 B의 연산값입니다.\",\n    \"quotient_and_mod_elements\": \"A, B-- 연산하고자 하는 숫자값<br>① // : A / B의 몫에 해당하는 값<br>② % : A / B의 나머지에 해당하는 값\",\n    \"quotient_and_mod_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(10 // 3, 2)\\n    Entry.print_for_sec(10 % 3, 2)\",\n    \"quotient_and_mod_exampleDesc\": \"[시작하기]버튼을 클릭하면 10 / 3의 몫인 3을 2초 동안 말하고, 나머지인 1을 2초 동안 말합니다.\",\n    \"calc_operation_desc\": \"A의 연산값입니다.\",\n    \"calc_operation_elements\": \"A, B-- 연산하고자 하는 숫자값<br>① A ** 2 : A를 제곱한 값<br>② math.sqrt(A): A의 루트값<br>③ math.sin(A): A의 사인값<br>④ math.cos(A): A의 코사인 값<br>⑤ math.tan(A):  A의 탄젠트값 <br>⑥ math.asin(A): A의 아크사인값<br>⑦ math.acos(A): A의 아크코사인값<br>⑧ math.atan(): A의 아크탄젠트값<br>⑨ math.log10(A): A의 로그값<br>⑩ math.log(A): A의 자연로그값<br>⑪ A - math.floor(A): A의 소수점 부분<br>⑫ math.floor(A): A의 소수점 버림값<br>⑬ math.ceil(A): A의 소수점 올림값<br>⑭ math.round(A): A의 소수점 반올림값<br>⑮ math.factorial(A): A의 팩토리얼 값<br>⑯ math.fabs(A): A의 절댓값\",\n    \"calc_operation_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(10 ** 2, 2)\\n    Entry.print_for_sec(math.sqrt(9), 2)\\n    Entry.print_for_sec(math.sin(90), 2)\\n    Entry.print_for_sec(math.fabs(-10), 2)\",\n    \"calc_operation_exampleDesc\": \"[시작하기]버튼을 클릭하면 10의 제곱, 9의 루트값, 90의 사인값, -10의 절댓값을 각 2초 동안 말합니다.\",\n    \"get_project_timer_value_desc\": \"이 명령이 실행되는 순간 초시계에 저장된 값입니다.\",\n    \"get_project_timer_value_exampleCode\": \"def when_start():\\n    Entry.timer(\\\"start\\\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\\\"stop\\\")\\n    Entry.timer_view(\\\"hide\\\")\\n    Entry.print(Entry.value_of_timer())\",\n    \"get_project_timer_value_exampleDesc\": \"[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.\",\n    \"choose_project_timer_action_desc\": \"초시계의 동작을 A로 정합니다.<br>(이 명령어를 사용하면 실행화면에 ‘초시계 창’이 생성됩니다.)\",\n    \"choose_project_timer_action_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"start\\\" : 초시계를 시작<br>② \\\"stop\\\" : 초시계를 정지<br>③ \\\"reset\\\" : 초시계를 초기화\",\n    \"choose_project_timer_action_exampleCode\": \"def when_start():\\n    Entry.timer(\\\"start\\\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\\\"stop\\\")\\n    Entry.timer_view(\\\"hide\\\")\\n    Entry.print(Entry.value_of_timer())\",\n    \"choose_project_timer_action_exampleDesc\": \"[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.\",\n    \"set_visible_project_timer_desc\": \"실행화면의 초시계 창을 A로 설정합니다.\",\n    \"set_visible_project_timer_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"hide\\\" : 초시계창을 숨김<br>② \\\"show\\\" : 초시계창을 보임\",\n    \"set_visible_project_timer_exampleCode\": \"def when_start():\\n    Entry.timer(\\\"start\\\")\\n    Entry.wait_for_sec(3)\\n    Entry.timer(\\\"stop\\\")\\n    Entry.timer_view(\\\"hide\\\")\\n    Entry.print(Entry.value_of_timer())\",\n    \"set_visible_project_timer_exampleDesc\": \"[시작하기]버튼을 클릭하면 초시계를 시작합니다. 3초 뒤에는 초시계를 정지하고 초시계창을 숨깁니다. 그 후 초시계값을 말합니다.\",\n    \"get_date_desc\": \"현재 A에 대한 값입니다.\",\n    \"get_date_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"year\\\" : 현재 연도 값<br>② \\\"month\\\" : 현재 월 값<br>③ \\\"day\\\" : 현재 일 값<br>④ \\\"hour\\\" : 현재 시간 값<br>⑤ \\\"minute\\\" : 현재 분 값<br>⑥ \\\"second\\\" : 현재 초 값\",\n    \"get_date_exampleCode\": \"def when_start():\\n    Entry.print(Entry.value_of_current_time(\\\"year\\\") + \\\"년\\\" + Entry.value_of_current_time(\\\"month\\\") + \\\"월\\\")\",\n    \"get_date_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 현재년도와 월을 말합니다.\",\n    \"distance_something_desc\": \"자신과 A까지의 거리 값입니다.\",\n    \"distance_something_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"오브젝트 이름\\\"<br>② \\\"mouse_pointer\\\" 또는 \\\"마우스포인터\\\"\",\n    \"distance_something_exampleCode\": \"def when_start():\\n    while True:\\n        Entry.print(Entry.value_of_distance_to(\\\"mouse_pointer\\\"))\",\n    \"distance_something_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 마우스포인터와의 거리를 계속해서 말합니다.\",\n    \"get_sound_duration_desc\": \"소리 A의 길이(초)값입니다.\",\n    \"get_sound_duration_elements\": \"A-- \\\"소리 이름\\\"\",\n    \"get_sound_duration_exampleCode\": \"def when_start():\\n    Entry.print(Entry.value_of_sound_length_of(\\\"소리\\\"))\",\n    \"get_sound_duration_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"소리\\\"의 길이를 말합니다.\",\n    \"get_user_name_desc\": \"작품을 실행하고 있는 사용자의 아이디 값입니다.\",\n    \"get_user_name_exampleCode\": \"def when_start():\\n    Entry.print(Entry.value_of_username())\",\n    \"get_user_name_exampleDesc\": \"[시작하기]버튼을 클릭하면 작품을 실행하고 있는 사용자의 아이디 값을 말합니다.\",\n    \"get_nickname_desc\": \"작품을 실행하고 있는 사용자의 닉네임 값입니다.\",\n    \"get_nickname_exampleCode\": \"def when_start():\\n    Entry.print(Entry.value_of_nickname())\",\n    \"get_nickname_exampleDesc\": \"[시작하기]버튼을 클릭하면 작품을 실행하고 있는 사용자의 닉네임 값을 말합니다.\",\n    \"length_of_string_desc\": \"입력한 문자값의 공백을 포함한 글자 수입니다.\",\n    \"length_of_string_elements\": \"A-- \\\"문자열\\\"\",\n    \"length_of_string_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(len(\\\"안녕\\\"), 2)\\n    Entry.print_for_sec(len(\\\"엔트리\\\"), 2)\",\n    \"length_of_string_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"안녕\\\"과 \\\"엔트리\\\"의 글자 수를 각각 2초 동안 말합니다.\",\n    \"combine_something_desc\": \"A 문자열과 B 문자열을 결합한 값입니다. (A, B 중 하나가 숫자면 문자열로 바꾸어 처리되고, 둘 다 숫자면 덧셈 연산으로 처리됩니다.)\",\n    \"combine_something_elements\": \"A, B-- \\\"문자열\\\"\",\n    \"combine_something_exampleCode\": \"def when_start():\\n    Entry.print(\\\"안녕! \\\" + \\\"엔트리\\\")\",\n    \"combine_something_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"안녕!\\\"과 \\\"엔트리\\\"를 결합한 \\\"안녕! 엔트리\\\"를 말합니다.\",\n    \"char_at_desc\": \"A 문자열의 B번째의 글자 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)\",\n    \"char_at_elements\": \"A-- \\\"문자열\\\"%nextB-- 찾고자 하는 문자열의 위치\",\n    \"char_at_exampleCode\": \"def when_start():\\n    Entry.print(\\\"안녕 엔트리!\\\"[0])\",\n    \"char_at_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"안녕 엔트리!\\\"의 0번째 글자인 \\\"안\\\"을 말합니다.\",\n    \"substring_desc\": \"A 문자열의 B위치부터 C-1위치까지의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)\",\n    \"substring_elements\": \"A-- \\\"문자열\\\"%nextB-- 포함할 문자열의 시작 위치<br>첫 번째 글자는 0부터 시작%nextC-- 문자열을 포함하지 않는 위치\",\n    \"substring_exampleCode\": \"def when_start():\\n    Entry.print(\\\"안녕 엔트리!\\\"[1:5])\",\n    \"substring_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"안녕 엔트리!\\\"의 1에서 4번째 글자인 \\\"녕 엔트\\\"를 말합니다.\",\n    \"index_of_string_desc\": \"A문자열에서 B문자열이 처음으로 등장하는 위치의 값입니다. (첫 번째 글자의 위치는 0부터 시작합니다.)\",\n    \"index_of_string_elements\": \"A, B-- \\\"문자열\\\"\",\n    \"index_of_string_exampleCode\": \"def when_start():\\n    Entry.print(\\\"안녕 엔트리!\\\".find(\\\"엔트리\\\"))\",\n    \"index_of_string_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"안녕 엔트리!\\\"에서 \\\"엔트리\\\"가 처음으로 등장하는 위치인 3을 말합니다.\",\n    \"replace_string_desc\": \"A 문자열에서 B문자열을 모두 찾아 C문자열로 바꾼 값입니다.<br>(영문 입력시 대소문자를 구분합니다.)\",\n    \"replace_string_elements\": \"A, B, C-- \\\"문자열\\\"\",\n    \"replace_string_exampleCode\": \"def when_start():\\n    Entry.print(\\\"안녕 엔트리!\\\".replace( \\\"안녕\\\", \\\"반가워\\\"))\",\n    \"replace_string_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"안녕 엔트리!\\\"에서 \\\"안녕\\\"을 \\\"반가워\\\"로 바꾼 \\\"반가워 엔트리!\\\"를 말합니다.\",\n    \"change_string_case_desc\": \"A의 모든 알파벳을 대문자 또는 소문자로 바꾼 문자값입니다.\",\n    \"change_string_case_elements\": \"A-- \\\"문자열\\\"<br>① A.upper(): A의 모든 알파벳을 대문자로 바꾼 값<br>② A.lower() : A의 모든 알파벳을 소문자로 바꾼 값\",\n    \"change_string_case_exampleCode\": \"def when_start():\\n    Entry.print_for_sec(\\\"Hello Entry!\\\".upper(), 2)\\n    Entry.print_for_sec(\\\"Hello Entry!\\\".lower(), 2)\",\n    \"change_string_case_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"Hello Entry!\\\"를 모두 대문자로 바꾼 \\\"HELLO ENTRY!\\\"를 2초간 말한 다음 모두 소문자로 바꾼 \\\"hello entry!\\\"를 2초간 말합니다.\",\n    \"ask_and_wait_desc\": \"오브젝트가 A 내용을 말풍선으로 묻고, 대답을 입력받습니다. 대답은 실행화면 또는 콘솔창에서 입력할 수 있으며 입력된 값은 'Entry.answer()'에 저장됩니다. <br>(이 명령어를 사용하면 실행화면에 ‘대답 창’이 생성됩니다.)\",\n    \"ask_and_wait_elements\": \"A-- \\\"문자열\\\"\",\n    \"ask_and_wait_exampleCode\": \"def when_start():\\n    Entry.input(\\\"이름을 입력해보세요.\\\")\\n    Entry.print(Entry.answer() + \\\" 반가워!\\\")\",\n    \"ask_and_wait_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"이름을 입력해보세요.\\\"라고 말풍선으로 묻습니다. 이름을 입력하면 \\\"(입력한 이름) 반가워!\\\"라 말합니다.\",\n    \"get_canvas_input_value_desc\": \"Entry.input(A) 명령에 의해 실행화면 또는 콘솔에서 입력받은 값입니다.\",\n    \"get_canvas_input_value_exampleCode\": \"def when_start():\\n    Entry.input(\\\"이름을 입력해보세요.\\\")\\n    Entry.print(Entry.answer() + \\\" 반가워!\\\")\",\n    \"get_canvas_input_value_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 \\\"이름을 입력해보세요.\\\"라고 말풍선으로 묻습니다. 이름을 입력하면 \\\"(입력한 이름) 반가워!\\\"라 말합니다.\",\n    \"set_visible_answer_desc\": \"실행화면의 대답 창을 A로 설정합니다.\",\n    \"set_visible_answer_elements\": \"A-- 아래 선택지 중 하나<br>① \\\"hide\\\" : 대답 창을 숨김<br>② \\\"show\\\" : 대답 창을 보임\",\n    \"set_visible_answer_exampleCode\": \"def when_start():\\n    Entry.answer_view(\\\"hide\\\")\\n    Entry.input(\\\"나이를 입력하세요.\\\")\\n    Entry.print(Entry.answer())\",\n    \"set_visible_answer_exampleDesc\": \"[시작하기]버튼을 클릭하면 대답창이 숨겨지고, 오브젝트가 \\\"나이를 입력하세요.\\\"라고 말풍선으로 묻습니다. 나이를 입력하면 오브젝트가 입력한 나이를 말합니다.\",\n    \"get_variable_desc\": \"A 변수에 저장된 값입니다.\",\n    \"get_variable_elements\": \"A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A\",\n    \"get_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.print(age)\",\n    \"get_variable_exampleDesc\": \"age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \\\"16\\\"을 말합니다.\",\n    \"change_variable_desc\": \"A 변수에 B만큼 더합니다.\",\n    \"change_variable_elements\": \"A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 숫자값\",\n    \"change_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.print_for_sec(age, 2)\\n    age += 2\\n    Entry.print_for_sec(age, 2)\",\n    \"change_variable_exampleDesc\": \"age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \\\"16\\\"을 2초 동안 말합니다. 그 후 age변수에 2를 더하고 더한값인 \\\"18\\\"을 2초 동안 말합니다.\",\n    \"set_variable_desc\": \"A 변수의 값을 B로 정합니다. 만약 A 변수가 없으면  [속성] 탭에 A 변수가 자동 생성됩니다.\",\n    \"set_variable_elements\": \"A-- 변수명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 변수에 넣을 값<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등\",\n    \"set_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.print(age)\",\n    \"set_variable_exampleDesc\": \"age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 오브젝트가 age 변수에 들어 가 있는 값인 \\\"16\\\"을 말합니다.\",\n    \"show_variable_desc\": \"A 변수 창을 실행화면에 보이게 합니다.\",\n    \"show_variable_elements\": \"A-- \\\"변수명\\\"<br>① 모든 오브젝트에서 사용: \\\"A\\\"<br>② 이 오브젝트에서 사용: \\\"self.A\\\"\",\n    \"show_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\\\"age\\\")\\n    Entry.wait_for_sec(2)\\n    age = 20\\n    Entry.show_variable(\\\"age\\\")\",\n    \"show_variable_exampleDesc\": \"age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨깁니다. 2초 후 변수값을 17로 바꾸고 age변수창을 실행화면에 보이게 합니다.\",\n    \"hide_variable_desc\": \"A 변수 창을 실행화면에서 숨깁니다.\",\n    \"hide_variable_elements\": \"A-- \\\"변수명\\\"<br>① 모든 오브젝트에서 사용: \\\"A\\\"<br>② 이 오브젝트에서 사용: \\\"self.A\\\"\",\n    \"hide_variable_exampleCode\": \"age = 16\\n\\ndef when_start():\\n    Entry.hide_variable(\\\"age\\\")\\n    Entry.print_for_sec(age, 2)\",\n    \"hide_variable_exampleDesc\": \"age라는 변수를 만들고 그 값을 16으로 정합니다. [시작하기]버튼을 클릭하면 age변수창을 실행화면에서 숨기고, 오브젝트가 age 변수에 들어 가 있는 값인 \\\"16\\\"을 2초 동안 말합니다.\",\n    \"value_of_index_from_list_desc\": \"A 리스트에서 B위치의 항목 값을 의미합니다. <br>(첫 번째 항목의 위치는 0부터 시작합니다.)\",\n    \"value_of_index_from_list_elements\": \"A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치\",\n    \"value_of_index_from_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    Entry.print(basket[1])\\n\",\n    \"value_of_index_from_list_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트가 basket 리스트의 1번째 항목인 orange를 말합니다.\",\n    \"add_value_to_list_desc\": \"A 리스트의 마지막 항목으로 B값이 추가됩니다.\",\n    \"add_value_to_list_elements\": \"A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트에 넣을 항목 값<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등\",\n    \"add_value_to_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    basket.append(\\\"juice\\\")\\n    Entry.print(basket[4])\",\n    \"add_value_to_list_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 \\\"juice\\\"를 basket의 마지막 항목으로 추가합니다. 오브젝트는 basket의 4번째 항목인 \\\"juice\\\"를 말합니다.\",\n    \"remove_value_from_list_desc\": \"A 리스트의 B위치에 있는 항목을 삭제합니다.<br>(첫 번째 항목의 위치는 0부터 시작합니다.)\",\n    \"remove_value_from_list_elements\": \"A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치값\",\n    \"remove_value_from_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\ndef when_start():\\n    basket.pop(0)\\n    Entry.print(basket[0])\",\n    \"remove_value_from_list_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 항목인 apple을 삭제합니다. 오브젝트는 새롭게 basket의 0번째 항목이 된 \\\"orange\\\"를 말합니다.\",\n    \"insert_value_to_list_desc\": \"A 리스트의 B위치에 C항목을 끼워 넣습니다. <br>(첫 번째 항목의 위치는 0부터 시작합니다. B위치보다 뒤에 있는 항목들은 순서가 하나씩 밀려납니다.)\",\n    \"insert_value_to_list_elements\": \"A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등\",\n    \"insert_value_to_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    basket.insert(1, \\\"juice\\\")\\n    Entry.print(basket[2])\",\n    \"insert_value_to_list_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 1번째 위치에 항목 \\\"juice\\\"를 끼워 넣습니다. 오브젝트는 새롭게 basket의 2번째 항목이 된 \\\"orange\\\"를 말합니다.\",\n    \"change_value_list_index_desc\": \"A 리스트에서 B위치에 있는 항목의 값을 C 값으로 바꿉니다.<br>(첫 번째 항목의 위치는 0부터 시작합니다.)\",\n    \"change_value_list_index_elements\": \"A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A%nextB-- 리스트 항목의 위치%nextC-- 리스트에 넣을 항목 값<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등\",\n    \"change_value_list_index_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    basket[0] = \\\"juice\\\"\\n    Entry.print(basket[0])\",\n    \"change_value_list_index_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket의 0번째 위치의 항목 \\\"apple\\\"을 \\\"juice\\\"로 바꿉니다. 오브젝트는 바뀐 basket의 0번째 항목 \\\"juice\\\"를 말합니다.\",\n    \"length_of_list_desc\": \"A 리스트가 보유한 항목 개수 값입니다.\",\n    \"length_of_list_elements\": \"A-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A\",\n    \"length_of_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    Entry.print(len(basket))\",\n    \"length_of_list_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 오브젝트는  basket의 항목 개수인 4를 말합니다.\",\n    \"is_included_in_list_desc\": \"A값을 가진 항목이 B리스트에 포함되어 있는지 확인합니다.\",\n    \"is_included_in_list_elements\": \"A-- 리스트의 항목 값<br>① 문자 : \\\"안녕!\\\", \\\"엔트리\\\" 등 <br>② 숫자 : 0, 10, 35 등%nextB-- 리스트명<br>① 모든 오브젝트에서 사용: A<br>② 이 오브젝트에서 사용: self.A\",\n    \"is_included_in_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    if \\\"apple\\\" in basket:\\n        Entry.print(\\\"사과가 있어!\\\")\",\n    \"is_included_in_list_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트에 \\\"apple\\\"항목이 있는지 확인합니다. \\\"apple\\\"항목이 있기 때문에 오브젝트는 \\\"사과가 있어!\\\"라 말합니다.\",\n    \"show_list_desc\": \"선택한 리스트 창을 실행화면에 보이게 합니다.\",\n    \"show_list_elements\": \"A-- \\\"리스트명\\\"<br>① 모든 오브젝트에서 사용: \\\"A\\\"<br>② 이 오브젝트에서 사용: \\\"self.A\\\"\",\n    \"show_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    Entry.hide_list(\\\"basket\\\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\\\"basket\\\")\",\n    \"show_list_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.\",\n    \"hide_list_desc\": \"선택한 리스트 창을 실행화면에서 숨깁니다.\",\n    \"hide_list_elements\": \"A-- \\\"리스트명\\\"<br>① 모든 오브젝트에서 사용: \\\"A\\\"<br>② 이 오브젝트에서 사용: \\\"self.A\\\"\",\n    \"hide_list_exampleCode\": \"basket = [\\\"apple\\\", \\\"orange\\\", \\\"pear\\\", \\\"grape\\\"]\\n\\ndef when_start():\\n    Entry.hide_list(\\\"basket\\\")\\n    Entry.wait_for_sec(2)\\n    Entry.show_list(\\\"basket\\\")\",\n    \"hide_list_exampleDesc\": \"basket이라는 리스트를 만들고 4개의 항목을 넣습니다. [시작하기]버튼을 클릭하면 basket 리스트를 2초간 숨긴 다음 보여줍니다.\",\n    \"boolean_and_or_desc\": \"A와 B의 판단값을 확인하여 True 또는 False로 판단합니다.\",\n    \"boolean_and_or_elements\": \"② or : A와 B의 판단 중 하나라도 True인 경우 True, 아닌 경우 False\",\n    \"boolean_and_or_exampleCode\": \"def when_start():\\n    while True:\\n        if Entry.is_key_pressed(\\\"a\\\") and Entry.is_key_pressed(\\\"s\\\"):\\n            Entry.add_effect(\\\"color\\\", 10)\",\n    \"boolean_and_or_exampleDesc\": \"[시작하기]버튼을 클릭하고 키보드의 \\\"a\\\" 와 \\\"s\\\"키를 동시에 눌렀을 때, 색깔 효과를 10만큼 줍니다.\",\n    \"check_weather_desc\": \"B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.\",\n    \"check_weather_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"sunny\\\" : 맑음<br>②    \\\"partly cloudy\\\" : 구름조금<br>③    \\\"mostly cloudy\\\" : 구름많음<br>④    \\\"cloudy\\\" : 흐림<br>⑤    \\\"rainy\\\" : 비<br>⑥    \\\"sleet\\\" : 진눈깨비<br>⑦    \\\"snowy\\\" : 눈%nextB-- 아래 선택지 중 하나<br>①    \\\"yesterday\\\" : 어제<br>②    \\\"today\\\" : 오늘<br>③    \\\"tomorrow\\\" : 내일<br>④    \\\"After 2 days\\\" : 모레<br>⑤    \\\"After 3 days\\\" : 3일 후<br>⑥    \\\"After 4 days\\\" : 4일 후<br>⑦    \\\"After 5 days\\\" : 5일 후<br>⑧    \\\"After 6 days\\\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"check_weather_exampleCode\": \"def when_start():\\n    if Weather.is_condition_sunny(\\\"today\\\", \\\"Seoul\\\"):\\n        Entry.print(\\\"오늘 서울의 날씨는 맑습니다.\\\")\",\n    \"check_weather_exampleDesc\": \"[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \\\"오늘 서울의 날씨는 맑습니다.\\\"라고 말합니다.​\",\n    \"check_finedust_desc\": \"선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.\",\n    \"check_finedust_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"good\\\" : 좋음<br>②    \\\"normal\\\" : 보통<br>③    \\\"bad\\\" : 나쁨<br>④    \\\"very bad\\\" : 매우나쁨%nextB-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"check_finedust_exampleCode\": \"def when_start():\\n    if Weather.is_current_finedust_grade_good(\\\"Seoul\\\"):\\n        Entry.print(\\\"현재 서울의 미세먼지 등급은 좋음입니다.\\\")\",\n    \"check_finedust_exampleDesc\": \"[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​\",\n    \"get_weather_data_desc\": \"선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.\",\n    \"get_weather_data_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"the lowest temperature\\\" : 최저기온<br>②    \\\"the highest temperature\\\" : 최고기온<br>③    \\\"humidity\\\" : 습도<br>④    \\\"precipitation\\\" : 강수량<br>⑤    \\\"precipitation probability\\\" : 강수확률<br>⑥    \\\"wind speed\\\" : 풍속%nextB-- 아래 선택지 중 하나<br>①    \\\"yesterday\\\" : 어제<br>②    \\\"today\\\" : 오늘<br>③    \\\"tomorrow\\\" : 내일<br>④    \\\"After 2 days\\\" : 모레<br>⑤    \\\"After 3 days\\\" : 3일 후<br>⑥    \\\"After 4 days\\\" : 4일 후<br>⑦    \\\"After 5 days\\\" : 5일 후<br>⑧    \\\"After 6 days\\\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"get_weather_data_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\\\"today\\\", \\\"Seoul\\\"))\",\n    \"get_weather_data_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​\",\n    \"get_current_weather_data_desc\": \"현재 B지역의 A 날씨 정보값을 의미합니다.\",\n    \"get_current_weather_data_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북%nextB-- 아래 선택지 중 하나<br>①    \\\"temperature\\\" : 기온<br>②    \\\"concentration of fine dust\\\" : 미세먼지농도\",\n    \"get_current_weather_data_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_current_temperature(\\\"Seoul\\\"))\",\n    \"get_current_weather_data_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.\",\n    \"get_today_temperature_desc\": \"오늘 A지역의 B 시간대 기온 정보값을 의미합니다.\",\n    \"get_today_temperature_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북%nextB-- 아래 선택지 중 하나<br>①    \\\"00\\\" : 당일 00시 측정된 기온값<br>②    \\\"03\\\" : 당일 03시 측정된 기온값<br>③    \\\"06\\\" : 당일 06시 측정된 기온값<br>④    \\\"09\\\" : 당일 09시 측정된 기온값<br>⑤    \\\"12\\\" : 당일 12시 측정된 기온값<br>⑥    \\\"15\\\" : 당일 15시 측정된 기온값<br>⑦    \\\"18\\\" : 당일 18시 측정된 기온값<br>⑧    \\\"21\\\" : 당일 21시 측정된 기온값\",\n    \"get_today_temperature_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_today_temperature(\\\"Seoul\\\", 00))\",\n    \"get_today_temperature_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​\",\n    \"check_city_weather_desc\": \"B날짜에 C지역의 날씨가 A인 경우 True로 판단합니다.\",\n    \"check_city_weather_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"sunny\\\" : 맑음<br>②    \\\"partly cloudy\\\" : 구름조금<br>③    \\\"mostly cloudy\\\" : 구름많음<br>④    \\\"cloudy\\\" : 흐림<br>⑤    \\\"rainy\\\" : 비<br>⑥    \\\"sleet\\\" : 진눈깨비<br>⑦    \\\"snowy\\\" : 눈%nextB-- 아래 선택지 중 하나<br>①    \\\"yesterday\\\" : 어제<br>②    \\\"today\\\" : 오늘<br>③    \\\"tomorrow\\\" : 내일<br>④    \\\"After 2 days\\\" : 모레<br>⑤    \\\"After 3 days\\\" : 3일 후<br>⑥    \\\"After 4 days\\\" : 4일 후<br>⑦    \\\"After 5 days\\\" : 5일 후<br>⑧    \\\"After 6 days\\\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"check_city_weather_exampleCode\": \"def when_start():\\n    if Weather.is_condition_sunny(\\\"today\\\", \\\"Seoul\\\"):\\n        Entry.print(\\\"오늘 서울의 날씨는 맑습니다.\\\")\",\n    \"check_city_weather_exampleDesc\": \"[시작하기]버튼을 클릭하면 오늘 서울의 날씨가 맑은지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 \\\"오늘 서울의 날씨는 맑습니다.\\\"라고 말합니다.​\",\n    \"check_city_finedust_desc\": \"선택한 지역의 현재 미세먼지 정보를 실제 미세먼지 등급과 비교하여 일치하는 경우 ‘참’으로 판단합니다.\",\n    \"check_city_finedust_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"good\\\" : 좋음<br>②    \\\"normal\\\" : 보통<br>③    \\\"bad\\\" : 나쁨<br>④    \\\"very bad\\\" : 매우나쁨%nextB-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"check_city_finedust_exampleCode\": \"def when_start():\\n    if Weather.is_current_finedust_grade_good(\\\"Seoul\\\"):\\n        Entry.print(\\\"현재 서울의 미세먼지 등급은 좋음입니다.\\\")\",\n    \"check_city_finedust_exampleDesc\": \"[시작하기]버튼을 클릭하면 현재 서울의 미세먼지 등급이 좋음인지 확인합니다. 만약 서울의 날씨가 맑다면 오브젝트가 “오늘 서울의 미세먼지 등급은 좋음입니다.”라고 말합니다.​\",\n    \"get_city_weather_data_desc\": \"선택한 날짜와 지역의 각종 날씨 정보값(최저기온, 최고기온, 습도, 강수량, 강수확률, 풍속)입니다.\",\n    \"get_city_weather_data_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"the lowest temperature\\\" : 최저기온<br>②    \\\"the highest temperature\\\" : 최고기온<br>③    \\\"humidity\\\" : 습도<br>④    \\\"precipitation\\\" : 강수량<br>⑤    \\\"precipitation probability\\\" : 강수확률<br>⑥    \\\"wind speed\\\" : 풍속%nextB-- 아래 선택지 중 하나<br>①    \\\"yesterday\\\" : 어제<br>②    \\\"today\\\" : 오늘<br>③    \\\"tomorrow\\\" : 내일<br>④    \\\"After 2 days\\\" : 모레<br>⑤    \\\"After 3 days\\\" : 3일 후<br>⑥    \\\"After 4 days\\\" : 4일 후<br>⑦    \\\"After 5 days\\\" : 5일 후<br>⑧    \\\"After 6 days\\\" : 6일 후%nextC-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북\",\n    \"get_city_weather_data_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_lowest_temperature(\\\"today\\\", \\\"Seoul\\\"))\",\n    \"get_city_weather_data_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 최저기온을 말합니다.​\",\n    \"get_current_city_weather_data_desc\": \"현재 B지역의 A 날씨 정보값을 의미합니다.\",\n    \"get_current_city_weather_data_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북%nextB-- 아래 선택지 중 하나<br>①    \\\"temperature\\\" : 기온<br>②    \\\"concentration of fine dust\\\" : 미세먼지농도\",\n    \"get_current_city_weather_data_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_current_temperature(\\\"Seoul\\\"))\",\n    \"get_current_city_weather_data_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 현재 서울의 기온을 말합니다.\",\n    \"get_today_city_temperature_desc\": \"오늘 A지역의 B 시간대 기온 정보값을 의미합니다.\",\n    \"get_today_city_temperature_elements\": \"A-- 아래 선택지 중 하나<br>①    \\\"Seoul\\\" : 서울<br>②    \\\"Gangwon-do\\\" : 강원<br>③    \\\"Gyeonggi-do\\\" : 경기<br>④    \\\"Gyeongsangnam-do\\\" : 경남<br>⑤    \\\"Gyeongsangbuk-do\\\" : 경북<br>⑥    \\\"Gwangju\\\" : 광주<br>⑦    \\\"Daegu\\\" : 대구<br>⑧    \\\"Daejeon\\\" : 대전<br>⑨    \\\"Busan\\\" : 부산<br>⑩    \\\"Sejong\\\" : 세종<br>⑪    \\\"Ulsan\\\" : 울산<br>⑫    \\\"Incheon\\\" : 인천<br>⑬    \\\"Jeollanam-do\\\" : 전남<br>⑭    \\\"Jeollabuk-do\\\" : 전북<br>⑮    \\\"Jeju\\\" : 제주<br>Ⓐ \\\"Chungcheongnam-do\\\" : 충남<br>Ⓑ \\\"Chungcheongbuk-do\\\": 충북%nextB-- 아래 선택지 중 하나<br>①    \\\"00\\\" : 당일 00시 측정된 기온값<br>②    \\\"03\\\" : 당일 03시 측정된 기온값<br>③    \\\"06\\\" : 당일 06시 측정된 기온값<br>④    \\\"09\\\" : 당일 09시 측정된 기온값<br>⑤    \\\"12\\\" : 당일 12시 측정된 기온값<br>⑥    \\\"15\\\" : 당일 15시 측정된 기온값<br>⑦    \\\"18\\\" : 당일 18시 측정된 기온값<br>⑧    \\\"21\\\" : 당일 21시 측정된 기온값\",\n    \"get_today_city_temperature_exampleCode\": \"def when_start():\\n    Entry.print(Weather.get_today_city_temperature(\\\"Seoul\\\", 00))\",\n    \"get_today_city_temperature_exampleDesc\": \"[시작하기]버튼을 클릭하면 오브젝트가 오늘 서울의 00시 기온을 말합니다.​\"\n};\nLang.Painter = {\n    \"select_cut\": \"You can cut with a square dotted line.\",\n    \"thickness_of_eraser\": \"Thickness of eraser\",\n    \"font\": \"Font\",\n    \"font_color\": \"Font color\",\n    \"outline_color\": \"Outline color\",\n    \"outline_thickness\": \"Outline thickness\",\n    \"fill_color\": \"Fill\",\n    \"inversion\": \"Inversion\",\n    \"font_size\": \"Font size\",\n    \"font_family\": \"Font family\",\n    \"fullscreen\": \"Full screen\",\n    \"exit_fullscreen\": \"Exit full screen\",\n    \"picture_import\": \"Import a picture\",\n    \"edit_way\": \"Edit way\",\n    \"line\": \"Hàng\",\n    \"vertex\": \"Vertex\",\n    \"bitmap\": \"Bitmap\",\n    \"vector\": \"Vector\",\n    \"forward\": \"đằng trước\",\n    \"backward\": \"đằng sau\",\n    \"front\": \"phía trước\",\n    \"back\": \"phía sau\",\n    \"group\": \"group\",\n    \"ungroup\": \"ungroup\",\n    \"copy_picture\": \"sao chép\",\n    \"delete_picture\": \"delete\",\n    \"cut_picture\": \"cắt\",\n    \"paste_picture\": \"dán\",\n    \"remove_all\": \"xoá tất cả\",\n    \"new_picture\": \"hình ảnh mới\",\n    \"edit\": \"Edit\",\n    \"picture_size\": \"kích cỡ\",\n    \"picture_rotation\": \"xoay vòng\",\n    \"thickness\": \"độ dày\",\n    \"font_fill\": \"Fill\",\n    \"painter_file_save\": \"lưu\",\n    \"painter_file_saveas\": \"lưu thành hình ảnh mới\",\n    \"file\": \"File\",\n    \"Pencil\": \"Cây bút\",\n    \"Line\": \"Hàng\",\n    \"Path\": \"Path\",\n    \"Pan\": \"Move\",\n    \"Select\": \"Select\",\n    \"Rectangle\": \"Hình chữ nhật\",\n    \"Ellipse\": \"hình bầu dục\",\n    \"Text\": \"Hộp văn bản\",\n    \"Fill\": \"Lấp đầy\",\n    \"Eraser\": \"Cục tẩy\",\n    \"get_file\": \"nhận được\",\n    \"copy_file\": \"sao chép\"\n};\nLang.DataAnalytics = {\n    \"data_analysis\": \"Data Analysis\",\n    \"create_table\": \"Add Table\",\n    \"data\": \"Data Analysis\",\n    \"add_table\": \"Add Table\",\n    \"show_chart\": \"Show Chart\",\n    \"legend\": \"Legend\",\n    \"dashboard\": \"Dashboard\",\n    \"table\": \"Table\",\n    \"chart\": \"Chart\",\n    \"attribute\": \"Column\",\n    \"row\": \"Row\",\n    \"average\": \"Average\",\n    \"standard_deviation\": \"Standard Deviation\",\n    \"maximum\": \"Maximum\",\n    \"minimum\": \"Minimum\",\n    \"median\": \"Median\",\n    \"average_explain\": \"The result that add all values of that property and divide the total by number of the property.\",\n    \"standard_deviation_explain\": \"A value that tells how spread out the data are from the average.\\nCloser to zero means that the values are concentrated near the average.\",\n    \"maximum_minimum_explain\": \"Largest and Smallest values for the property\",\n    \"median_explain\": \"The value located at the center of the whole when all the values of the property are arranged in size order.\",\n    \"add_row_above\": \"Add row above\",\n    \"add_row_below\": \"Add row below\",\n    \"delete_row\": \"Delete Row\",\n    \"add_property_left\": \"Add Property to left\",\n    \"add_property_right\": \"Add Property to right\",\n    \"delete_attribute\": \"Delete Attribute\",\n    \"data_alert\": \"You can only see counts for attributes that contain non-numeric values.\",\n    \"save\": \"lưu\",\n    \"cancel\": \"hủy bỏ\",\n    \"confirm\": \"OK\",\n    \"attribute_count\": \".\",\n    \"row_count\": \"row\",\n    \"cell_count\": \"cell\",\n    \"count\": \"count\",\n    \"add_chart_alert\": \"No chart in table.\\nAdd table.\",\n    \"enter_attribute_name\": \"Please enter a column name(with less than 10 characters).\",\n    \"placeholder_attribute_name\": \"Column name\",\n    \"new_attribute\": \"New column\",\n    \"chart_title\": \"Chart title\",\n    \"remove_chart\": \"Delete chart\",\n    \"add_chart_first\": \"No chart in table. \\nAdd table.\",\n    \"bar\": \"bar\",\n    \"line\": \"line\",\n    \"pie\": \"pie\",\n    \"scatter\": \"scatter\",\n    \"select_x_axis\": \"Select the horizontal axis.\",\n    \"x_axis\": \"Horiz. axis\",\n    \"y_axis\": \"Ver. axis\",\n    \"select_y_axis\": \"Select the vertical axis.\",\n    \"select_y_axis_or_legend\": \"Select the vertical axis or legends.\",\n    \"select_legend\": \"Select the legends.\",\n    \"cell\": \"Cell\",\n    \"unable_to_express_chart\": \"This cannot be expressed in charts.\",\n    \"edit_attribute_name\": \"Change name\",\n    \"duplicate_attribute_name_title\": \"Failed to change column name.\",\n    \"duplicate_attribute_name_content\": \"A column with the same name exists.\",\n    \"fail_save_table\": \"Failed to save table.\",\n    \"duplicate_table_name_content\": \"A table with the same name exists.\",\n    \"saved_table_title\": \"Saved successfully.\",\n    \"saved_table_content\": \"The information of table and charts was successfully saved.\",\n    \"empty_table_name_content\": \"Table's name can't be space.\",\n    \"do_not_delete_row\": \"The row cannot be deleted.\",\n    \"rows_cannot_less_one\": \"Tables must have at least one row.\"\n};\nLang.SharePolicy = {\n    \"title\": \"Entry Project/Post share Guide\"\n};\n\nLang.Support = [\"ko\", \"en\", \"vn\", \"jp\"];\nif (typeof exports == \"object\")\n    exports.Lang = Lang;\n"
  },
  {
    "path": "extern/object-detector.worker.js",
    "content": "self.importScripts(`${self.location.pathname}/../vision_bundle.js`);\n\nlet flipState;\nlet isRun = false;\n\nself.onmessage = async ({ data }) => {\n    if (data.action === 'object_detector_init') {\n        initializeObjectDetector(data);\n    } else if (data.action === 'object_detector_restart') {\n        isRun = true;\n    } else if (data.action === 'object_detector_change_option') {\n        changeObjectDetectorOption(data.option);\n    } else if (data.action === 'object_detector') {\n        flipState = data.flipState;\n        predictObjectDetector(data.imageBitmap);\n    } else if (data.action === 'clear_object_detector') {\n        clearPredictObjectDetector();\n    }\n};\n\nlet objectNameList;\nlet workerContext;\nlet drawingUtils;\nlet objectDetector;\nlet isPrevObjectDetector = false;\nlet countDetectedObject = 0;\nlet isDrawDetectedObjectDetector = false;\n\nconst initializeObjectDetector = async (data) => {\n    const { canvas, lang, option } = data;\n    isRun = true;\n    objectNameList = lang.objectNameList;\n    isDrawDetectedObjectDetector = option.isDrawDetectedObjectDetector;\n    workerContext = canvas.getContext('2d');\n    workerContext.font = '20px Arial';\n    workerContext.lineWidth = 5;\n    drawingUtils = new DrawingUtils(workerContext);\n    const vision = await FilesetResolver.forVisionTasks(`${self.location.pathname}/../wasm`);\n    objectDetector = await ObjectDetector.createFromOptions(vision, {\n        baseOptions: {\n            modelAssetPath: `${self.location.pathname}/../model/object_detector_lite.tflite`,\n            delegate: 'GPU',\n        },\n        runningMode: 'VIDEO',\n        scoreThreshold: 0.5,\n        maxResults: 8,\n    });\n    self.postMessage({ action: 'next_object_detector' });\n};\n\nconst changeObjectDetectorOption = (option) => {\n    isDrawDetectedObjectDetector = option.isDrawDetectedObjectDetector;\n};\n\nconst YX = (a) => {\n    return Math.max(1, Math.min(10, 10 * (1 - (a - -0.15) / 0.25) + (1 - (0.1 - a) / 0.25)));\n};\n\nconst predictObjectDetector = (imageBitmap) => {\n    try {\n        if (!workerContext || !objectDetector || !isRun) {\n            return;\n        }\n        const startTimeMs = performance.now();\n        const results = objectDetector.detectForVideo(imageBitmap, startTimeMs);\n        workerContext.save();\n        workerContext.clearRect(0, 0, 640, 360);\n        const { detections } = results;\n        self.postMessage({\n            action: 'object_detector_data',\n            objectDetectorResult: results,\n        });\n        if (detections.length) {\n            if (!isPrevObjectDetector) {\n                isPrevObjectDetector = true;\n                self.postMessage({ action: 'start_object_detector' });\n            }\n            if (detections.length !== countDetectedObject) {\n                countDetectedObject = detections.length;\n                self.postMessage({\n                    action: 'count_detected_object_detector',\n                    count: countDetectedObject,\n                });\n            }\n            if (!isDrawDetectedObjectDetector) {\n                return;\n            }\n            detections.forEach((detect, i) => {\n                drawObjectDetections(detect, i);\n            });\n        } else if (isPrevObjectDetector) {\n            isPrevObjectDetector = false;\n            countDetectedObject = 0;\n            self.postMessage({ action: 'stop_object_detector' });\n        }\n    } catch (e) {\n        console.error(e);\n    } finally {\n        workerContext.restore();\n        requestAnimationFrame(() => {\n            self.postMessage({ action: 'next_object_detector' });\n        });\n    }\n};\n\nconst colors = [\n    'rgb(66, 133, 244)',\n    'rgb(36, 193, 224)',\n    'rgb(52, 168, 83)',\n    'rgb(161, 66, 244)',\n    'rgb(244, 57, 160)',\n    'rgb(234, 67, 53)',\n    'rgb(250, 123, 23)',\n    'rgb(252, 201, 52)',\n];\n\nconst contextFlip = (context, axis) => {\n    if (flipState === 0) {\n        context.scale(-1, 1);\n        return {\n            x: -axis.x - axis.offsetX,\n            y: axis.y - axis.offsetY,\n        };\n    } else if (flipState === 1) {\n        context.scale(1, 1);\n        return {\n            x: axis.x + 3,\n            y: axis.y - axis.offsetY,\n        };\n    } else if (flipState === 2) {\n        context.scale(-1, -1);\n        return {\n            x: -axis.x - axis.offsetX,\n            y: -(axis.y - axis.offsetY - 6),\n        };\n    } else if (flipState === 3) {\n        context.scale(1, -1);\n        return {\n            x: axis.x + 3,\n            y: -(axis.y - axis.offsetY - 6),\n        };\n    }\n};\n\nlet offset = 0;\nfunction drawObjectDetections(detect, i) {\n    try {\n        const { boundingBox, categories } = detect;\n        const [category] = categories;\n        const displayName = category.displayName || category.categoryName;\n        const text = objectNameList[displayName] || displayName;\n\n        const x = boundingBox.originX;\n        const y = boundingBox.originY;\n        const w = boundingBox.width;\n        const h = boundingBox.height;\n        const e = (640 / 600) * 4;\n        const measureText = workerContext.measureText(text);\n        const l = measureText.width + 6;\n        const measureSize =\n            measureText.fontBoundingBoxAscent + measureText.fontBoundingBoxDescent + 2 * e;\n        const m = x + w - l;\n        workerContext.strokeStyle = colors[i];\n        workerContext.beginPath();\n        workerContext.moveTo(x, y);\n        workerContext.lineTo(x + w, y);\n        workerContext.lineTo(x + w, y + h);\n        workerContext.lineTo(x, y + h);\n        workerContext.lineTo(x, y);\n        workerContext.stroke();\n        workerContext.fillStyle = colors[i];\n        workerContext.fillRect(m, y, l, measureSize);\n        const { x: axisX, y: axisY } = contextFlip(workerContext, {\n            offsetX: l - 3,\n            offsetY: 3 * e,\n            x: m,\n            y: y + measureSize,\n        });\n        workerContext.fillStyle = 'white';\n        workerContext.fillText(text, axisX, axisY);\n        contextFlip(workerContext, { offsetX: 0, offsetY: 0, x: 0, y: 0 });\n    } catch (e) {\n        console.error(e.stack);\n    }\n}\n\nconst clearPredictObjectDetector = () => {\n    console.log('clearPredictObjectDetector');\n    isRun = false;\n    isPrevObjectDetector = false;\n    countDetectedObject = 0;\n    workerContext.clearRect(0, 0, 640, 360);\n};\n"
  },
  {
    "path": "extern/pose-landmarker.worker.js",
    "content": "self.importScripts(`${self.location.pathname}/../vision_bundle.js`);\n\nlet flipState;\nlet isRun = false;\n\nself.onmessage = async ({ data }) => {\n    if (data.action === 'pose_landmarker_init') {\n        initializePoseLandmarker(data);\n    } else if (data.action === 'pose_landmarker_restart') {\n        isRun = true;\n    } else if (data.action === 'pose_landmarker_change_option') {\n        changePoseLandmarkerOption(data.option);\n    } else if (data.action === 'pose_landmarker') {\n        flipState = data.flipState;\n        predictPoseLandmarker(data.imageBitmap);\n    } else if (data.action === 'clear_pose_landmarker') {\n        clearPredictPoseLandmarker();\n    }\n};\n\nlet person;\nlet workerContext;\nlet drawingUtils;\nlet poseLandmarker;\nlet isPrevPoseLandmarker = false;\nlet countDetectedPose = 0;\nlet isDrawDetectedPoseLandmarker = false;\n\nconst initializePoseLandmarker = async (data) => {\n    const { canvas, lang, option } = data;\n    isRun = true;\n    person = lang.person;\n    isDrawDetectedPoseLandmarker = option.isDrawDetectedPoseLandmarker;\n    workerContext = canvas.getContext('2d');\n    workerContext.font = '20px Arial';\n    drawingUtils = new DrawingUtils(workerContext);\n    const vision = await FilesetResolver.forVisionTasks(`${self.location.pathname}/../wasm`);\n    poseLandmarker = await PoseLandmarker.createFromOptions(vision, {\n        baseOptions: {\n            modelAssetPath: `${self.location.pathname}/../model/pose_landmarker_lite.task`,\n            delegate: 'GPU',\n        },\n        runningMode: 'VIDEO',\n        numPoses: 4,\n    });\n    self.postMessage({ action: 'next_pose_landmarker' });\n};\n\nconst changePoseLandmarkerOption = (option) => {\n    isDrawDetectedPoseLandmarker = option.isDrawDetectedPoseLandmarker;\n};\n\nconst contextFlip = (context, axis) => {\n    if (flipState === 0) {\n        context.scale(-1, 1);\n        return {\n            x: -axis.x * 640,\n            y: axis.y * 360 - 20,\n        };\n    } else if (flipState === 1) {\n        context.scale(1, 1);\n        return {\n            x: axis.x * 640,\n            y: axis.y * 360 - 20,\n        };\n    } else if (flipState === 2) {\n        context.scale(-1, -1);\n        return {\n            x: -axis.x * 640,\n            y: -axis.y * 360 + 20,\n        };\n    } else if (flipState === 3) {\n        context.scale(1, -1);\n        return {\n            x: axis.x * 640,\n            y: -axis.y * 360 + 20,\n        };\n    }\n};\n\nconst predictPoseLandmarker = async (imageBitmap) => {\n    try {\n        if (!workerContext || !poseLandmarker) {\n            return;\n        }\n        const startTimeMs = performance.now();\n        const results = await poseLandmarker.detectForVideo(imageBitmap, startTimeMs);\n        if (!isRun) {\n            return;\n        }\n        workerContext.save();\n        workerContext.clearRect(0, 0, 640, 360);\n        const { landmarks } = results;\n        self.postMessage({\n            action: 'pose_landmarker_data',\n            poseLandmarkerResult: results,\n        });\n        if (landmarks.length) {\n            if (!isPrevPoseLandmarker) {\n                isPrevPoseLandmarker = true;\n                self.postMessage({ action: 'start_pose_landmarker' });\n            }\n            if (landmarks.length !== countDetectedPose) {\n                countDetectedPose = landmarks.length;\n                self.postMessage({\n                    action: 'count_detected_pose_landmarker',\n                    count: countDetectedPose,\n                });\n            }\n            if (!isDrawDetectedPoseLandmarker) {\n                return;\n            }\n            landmarks.forEach((landmark, i) => {\n                const mark7 = landmark[7];\n                const { x, y } = contextFlip(workerContext, mark7);\n                workerContext.fillStyle = '#FF0000';\n                workerContext.fillText(`${i + 1}-${person}`, x, y);\n                contextFlip(workerContext, mark7);\n                drawingUtils.drawLandmarks(landmark, {\n                    radius: (data) => DrawingUtils.lerp(data.from.z, -0.15, 0.1, 5, 1),\n                });\n                drawingUtils.drawConnectors(landmark, PoseLandmarker.POSE_CONNECTIONS);\n            });\n        } else if (isPrevPoseLandmarker) {\n            isPrevPoseLandmarker = false;\n            countDetectedPose = 0;\n            self.postMessage({ action: 'stop_pose_landmarker' });\n        }\n    } catch (e) {\n        console.error(e);\n    } finally {\n        workerContext.restore();\n        requestAnimationFrame(() => {\n            self.postMessage({ action: 'next_pose_landmarker' });\n        });\n    }\n};\n\nconst clearPredictPoseLandmarker = () => {\n    console.log('clearPredictPoseLandmarker');\n    isRun = false;\n    isPrevPoseLandmarker = false;\n    countDetectedPose = 0;\n    workerContext.clearRect(0, 0, 640, 360);\n};\n"
  },
  {
    "path": "extern/util/CanvasInput.js",
    "content": "'use strict';\n\n/*!\n *  CanvasInput v1.1.5\n *  http://goldfirestudios.com/blog/108/CanvasInput-HTML5-Canvas-Text-Input\n *\n *  (c) 2013-2014, James Simpson of GoldFire Studios\n *  goldfirestudios.com\n *\n *  MIT License\n */\n(function() {\n    // create a buffer that stores all inputs so that tabbing\n    // between them is made possible.\n    var inputs = []; // initialize the Canvas Input\n\n    var CanvasInput = function CanvasInput(o) {\n        var self = this;\n        o = o ? o : {}; // setup the defaults\n\n        self._canvas = o.canvas || null;\n        self._isHidden = true;\n        self._ctx = self._canvas ? self._canvas.getContext('2d') : null;\n        self._x = o.x || 0;\n        self._y = o.y || 0;\n        self._extraX = o.extraX || 0;\n        self._extraY = o.extraY || 0;\n        self._fontSize = o.fontSize || 14;\n        self._fontFamily = o.fontFamily || 'Arial';\n        self._fontColor = o.fontColor || '#000';\n        self._placeHolderColor = o.placeHolderColor || '#bfbebd';\n        self._fontWeight = o.fontWeight || 'normal';\n        self._fontStyle = o.fontStyle || 'normal';\n        self._readonly = o.readonly || false;\n        self._maxlength = o.maxlength || null;\n        self._width = o.width || 150;\n        self._height = o.height || self._fontSize;\n        self._padding = o.padding >= 0 ? o.padding : 5;\n        self._borderWidth = o.borderWidth >= 0 ? o.borderWidth : 1;\n        self._borderColor = o.borderColor || '#959595';\n        self._borderRadius = o.borderRadius >= 0 ? o.borderRadius : 3;\n        self._backgroundImage = o.backgroundImage || '';\n        self._boxShadow = o.boxShadow || '1px 1px 0px rgba(255, 255, 255, 1)';\n        self._innerShadow = o.innerShadow || '0px 0px 4px rgba(0, 0, 0, 0.4)';\n        self._selectionColor = o.selectionColor || 'rgba(179, 212, 253, 0.8)';\n        self._placeHolder = o.placeHolder || '';\n        self._value = o.value || self._placeHolder;\n\n        self._onsubmit = o.onsubmit || function() {};\n\n        self._onkeydown = o.onkeydown || function() {};\n\n        self._onkeyup = o.onkeyup || function() {};\n\n        self._onfocus = o.onfocus || function() {};\n\n        self._onblur = o.onblur || function() {};\n\n        self._cursor = false;\n        self._cursorPos = 0;\n        self._hasFocus = false;\n        self._selection = [0, 0];\n        self._wasOver = false;\n        self._topPosition = o.topPosition; // parse box shadow\n        self.boxShadow(self._boxShadow, true); // calculate the full width and height with padding, borders and shadows\n\n        self._calcWH(); // setup the off-DOM canvas\n\n        self._renderCanvas = document.createElement('canvas');\n\n        self._renderCanvas.setAttribute('width', self.outerW);\n\n        self._renderCanvas.setAttribute('height', self.outerH);\n\n        self._renderCtx = self._renderCanvas.getContext('2d'); // setup another off-DOM canvas for inner-shadows\n\n        self._shadowCanvas = document.createElement('canvas');\n\n        self._shadowCanvas.setAttribute('width', self._width + self._padding * 2);\n\n        self._shadowCanvas.setAttribute('height', self._height + self._padding * 2);\n\n        self._shadowCtx = self._shadowCanvas.getContext('2d'); // setup the background color\n\n        if (typeof o.backgroundGradient !== 'undefined') {\n            self._backgroundColor = self._renderCtx.createLinearGradient(0, 0, 0, self.outerH);\n\n            self._backgroundColor.addColorStop(0, o.backgroundGradient[0]);\n\n            self._backgroundColor.addColorStop(1, o.backgroundGradient[1]);\n        } else {\n            self._backgroundColor = o.backgroundColor || '#fff';\n        } // setup main canvas events\n\n        if (self._canvas) {\n            self._canvas.addEventListener(\n                'mousemove',\n                function(e) {\n                    e = e || window.event;\n                    self.mousemove(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'mousedown',\n                function(e) {\n                    e = e || window.event;\n                    self.mousedown(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'touchstart',\n                function(e) {\n                    e = e || window.event;\n                    self.mousedown(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'mouseup',\n                function(e) {\n                    e = e || window.event;\n                    self.mouseup(e, self);\n                },\n                false\n            );\n        } // setup a global mouseup to blur the input outside of the canvas\n\n        window.addEventListener(\n            'mouseup',\n            function(e) {\n                //e = e || window.event;\n                //if (self._hasFocus && !self._mouseDown) {\n                //self.blur();\n                //}\n            },\n            true\n        ); // create the hidden input element\n\n        self._hiddenInput = document.createElement('input');\n        self._hiddenInput.className = 'entryCanvasHiddenInput';\n        self._hiddenInput.type = 'text';\n        self._hiddenInput.style.position = 'absolute';\n        self._hiddenInput.style.opacity = 0;\n        self._hiddenInput.style.pointerEvents = 'none';\n        self._hiddenInput.style.left = '-500px';\n        self._hiddenInput.style.top = '0px';\n        self._hiddenInput.style.width = ''.concat(self._width, 'px');\n        self._hiddenInput.style.height = ''.concat(self._height, 'px');\n        self._hiddenInput.style.zIndex = -999;\n\n        if (self._maxlength) {\n            self._hiddenInput.maxLength = self._maxlength;\n        }\n\n        document.body.appendChild(self._hiddenInput);\n        self._hiddenInput.value = self._value; // setup the keydown listener\n\n        self._hiddenInput.addEventListener('keydown', function(e) {\n            e = e || window.event;\n\n            if (self._hasFocus) {\n                self.keydown(e, self);\n            }\n        }); // setup the keyup listener\n\n        self._hiddenInput.addEventListener('keyup', function(e) {\n            e = e || window.event; // update the canvas input state information from the hidden input\n\n            self._value = self._hiddenInput.value;\n            self._cursorPos = self._hiddenInput.selectionStart;\n            self.render();\n\n            if (self._hasFocus) {\n                self._onkeyup(e, self);\n            }\n        }); // add this to the buffer\n\n        inputs.push(self);\n        self._inputsIndex = inputs.length - 1; // draw the text box\n\n        self.render();\n    };\n\n    window.CanvasInput = CanvasInput; // setup the prototype\n\n    CanvasInput.prototype = {\n        /**\n         * Get/set the main canvas.\n         * @param  {Object} data Canvas reference.\n         * @return {Mixed}      CanvasInput or current canvas.\n         */\n        canvas: function canvas(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._canvas = data;\n                self._ctx = self._canvas.getContext('2d');\n                return self.render();\n            } else {\n                return self._canvas;\n            }\n        },\n\n        /**\n         * Get/set the x-position.\n         * @param  {Number} data The pixel position along the x-coordinate.\n         * @return {Mixed}      CanvasInput or current x-value.\n         */\n        x: function x(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._x = data;\n                return self.render();\n            } else {\n                return self._x;\n            }\n        },\n\n        /**\n         * Get/set the y-position.\n         * @param  {Number} data The pixel position along the y-coordinate.\n         * @return {Mixed}      CanvasInput or current y-value.\n         */\n        y: function y(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._y = data;\n                return self.render();\n            } else {\n                return self._y;\n            }\n        },\n\n        /**\n         * Get/set the extra x-position (generally used when no canvas is specified).\n         * @param  {Number} data The pixel position along the x-coordinate.\n         * @return {Mixed}      CanvasInput or current x-value.\n         */\n        extraX: function extraX(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._extraX = data;\n                return self.render();\n            } else {\n                return self._extraX;\n            }\n        },\n\n        /**\n         * Get/set the extra y-position (generally used when no canvas is specified).\n         * @param  {Number} data The pixel position along the y-coordinate.\n         * @return {Mixed}      CanvasInput or current y-value.\n         */\n        extraY: function extraY(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._extraY = data;\n                return self.render();\n            } else {\n                return self._extraY;\n            }\n        },\n\n        /**\n         * Get/set the font size.\n         * @param  {Number} data Font size.\n         * @return {Mixed}      CanvasInput or current font size.\n         */\n        fontSize: function fontSize(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontSize = data;\n                return self.render();\n            } else {\n                return self._fontSize;\n            }\n        },\n\n        /**\n         * Get/set the font family.\n         * @param  {String} data Font family.\n         * @return {Mixed}      CanvasInput or current font family.\n         */\n        fontFamily: function fontFamily(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontFamily = data;\n                return self.render();\n            } else {\n                return self._fontFamily;\n            }\n        },\n\n        /**\n         * Get/set the font color.\n         * @param  {String} data Font color.\n         * @return {Mixed}      CanvasInput or current font color.\n         */\n        fontColor: function fontColor(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontColor = data;\n                return self.render();\n            } else {\n                return self._fontColor;\n            }\n        },\n\n        /**\n         * Get/set the place holder font color.\n         * @param  {String} data Font color.\n         * @return {Mixed}      CanvasInput or current place holder font color.\n         */\n        placeHolderColor: function placeHolderColor(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._placeHolderColor = data;\n                return self.render();\n            } else {\n                return self._placeHolderColor;\n            }\n        },\n\n        /**\n         * Get/set the font weight.\n         * @param  {String} data Font weight.\n         * @return {Mixed}      CanvasInput or current font weight.\n         */\n        fontWeight: function fontWeight(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontWeight = data;\n                return self.render();\n            } else {\n                return self._fontWeight;\n            }\n        },\n\n        /**\n         * Get/set the font style.\n         * @param  {String} data Font style.\n         * @return {Mixed}      CanvasInput or current font style.\n         */\n        fontStyle: function fontStyle(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontStyle = data;\n                return self.render();\n            } else {\n                return self._fontStyle;\n            }\n        },\n\n        /**\n         * Get/set the width of the text box.\n         * @param  {Number} data Width in pixels.\n         * @return {Mixed}      CanvasInput or current width.\n         */\n        width: function width(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._width = data;\n\n                self._calcWH();\n\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._width;\n            }\n        },\n\n        /**\n         * Get/set the height of the text box.\n         * @param  {Number} data Height in pixels.\n         * @return {Mixed}      CanvasInput or current height.\n         */\n        height: function height(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._height = data;\n\n                self._calcWH();\n\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._height;\n            }\n        },\n\n        /**\n         * Get/set the padding of the text box.\n         * @param  {Number} data Padding in pixels.\n         * @return {Mixed}      CanvasInput or current padding.\n         */\n        padding: function padding(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._padding = data;\n\n                self._calcWH();\n\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._padding;\n            }\n        },\n\n        /**\n         * Get/set the border width.\n         * @param  {Number} data Border width.\n         * @return {Mixed}      CanvasInput or current border width.\n         */\n        borderWidth: function borderWidth(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderWidth = data;\n\n                self._calcWH();\n\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._borderWidth;\n            }\n        },\n\n        /**\n         * Get/set the border color.\n         * @param  {String} data Border color.\n         * @return {Mixed}      CanvasInput or current border color.\n         */\n        borderColor: function borderColor(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderColor = data;\n                return self.render();\n            } else {\n                return self._borderColor;\n            }\n        },\n\n        /**\n         * Get/set the border radius.\n         * @param  {Number} data Border radius.\n         * @return {Mixed}      CanvasInput or current border radius.\n         */\n        borderRadius: function borderRadius(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderRadius = data;\n                return self.render();\n            } else {\n                return self._borderRadius;\n            }\n        },\n\n        /**\n         * Get/set the background color.\n         * @param  {Number} data Background color.\n         * @return {Mixed}      CanvasInput or current background color.\n         */\n        backgroundColor: function backgroundColor(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._backgroundColor = data;\n                return self.render();\n            } else {\n                return self._backgroundColor;\n            }\n        },\n\n        /**\n         * Get/set the background gradient.\n         * @param  {Number} data Background gradient.\n         * @return {Mixed}      CanvasInput or current background gradient.\n         */\n        backgroundGradient: function backgroundGradient(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._backgroundColor = self._renderCtx.createLinearGradient(0, 0, 0, self.outerH);\n\n                self._backgroundColor.addColorStop(0, data[0]);\n\n                self._backgroundColor.addColorStop(1, data[1]);\n\n                return self.render();\n            } else {\n                return self._backgroundColor;\n            }\n        },\n\n        /**\n         * Get/set the box shadow.\n         * @param  {String} data     Box shadow in CSS format (1px 1px 1px rgba(0, 0, 0.5)).\n         * @param  {Boolean} doReturn (optional) True to prevent a premature render.\n         * @return {Mixed}          CanvasInput or current box shadow.\n         */\n        boxShadow: function boxShadow(data, doReturn) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                // parse box shadow\n                var boxShadow = data.split('px ');\n                self._boxShadow = {\n                    x: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[0], 10),\n                    y: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[1], 10),\n                    blur: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[2], 10),\n                    color: self._boxShadow === 'none' ? '' : boxShadow[3],\n                }; // take into account the shadow and its direction\n\n                if (self._boxShadow.x < 0) {\n                    self.shadowL = Math.abs(self._boxShadow.x) + self._boxShadow.blur;\n                    self.shadowR = self._boxShadow.blur + self._boxShadow.x;\n                } else {\n                    self.shadowL = Math.abs(self._boxShadow.blur - self._boxShadow.x);\n                    self.shadowR = self._boxShadow.blur + self._boxShadow.x;\n                }\n\n                if (self._boxShadow.y < 0) {\n                    self.shadowT = Math.abs(self._boxShadow.y) + self._boxShadow.blur;\n                    self.shadowB = self._boxShadow.blur + self._boxShadow.y;\n                } else {\n                    self.shadowT = Math.abs(self._boxShadow.blur - self._boxShadow.y);\n                    self.shadowB = self._boxShadow.blur + self._boxShadow.y;\n                }\n\n                self.shadowW = self.shadowL + self.shadowR;\n                self.shadowH = self.shadowT + self.shadowB;\n\n                self._calcWH();\n\n                if (!doReturn) {\n                    self._updateCanvasWH();\n\n                    return self.render();\n                }\n            } else {\n                return self._boxShadow;\n            }\n        },\n\n        /**\n         * Get/set the inner shadow.\n         * @param  {String} data In the format of a CSS box shadow (1px 1px 1px rgba(0, 0, 0.5)).\n         * @return {Mixed}          CanvasInput or current inner shadow.\n         */\n        innerShadow: function innerShadow(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._innerShadow = data;\n                return self.render();\n            } else {\n                return self._innerShadow;\n            }\n        },\n\n        /**\n         * Get/set the text selection color.\n         * @param  {String} data Color.\n         * @return {Mixed}      CanvasInput or current selection color.\n         */\n        selectionColor: function selectionColor(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._selectionColor = data;\n                return self.render();\n            } else {\n                return self._selectionColor;\n            }\n        },\n\n        /**\n         * Get/set the place holder text.\n         * @param  {String} data Place holder text.\n         * @return {Mixed}      CanvasInput or current place holder text.\n         */\n        placeHolder: function placeHolder(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._placeHolder = data;\n                return self.render();\n            } else {\n                return self._placeHolder;\n            }\n        },\n\n        /**\n         * Get/set the current text box value.\n         * @param  {String} data Text value.\n         * @return {Mixed}      CanvasInput or current text value.\n         */\n        value: function value(data) {\n            var self = this;\n\n            if (typeof data !== 'undefined') {\n                self._value = ''.concat(data);\n                self._hiddenInput.value = ''.concat(data); // update the cursor position\n\n                self._cursorPos = self._clipText().length;\n                self.render();\n                return self;\n            } else {\n                return self._value === self._placeHolder ? '' : self._value;\n            }\n        },\n\n        /**\n         * Set or fire the onsubmit event.\n         * @param  {Function} fn Custom callback.\n         */\n        onsubmit: function onsubmit(fn) {\n            var self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onsubmit = fn;\n                return self;\n            } else {\n                self._onsubmit();\n            }\n        },\n\n        /**\n         * Set or fire the onkeydown event.\n         * @param  {Function} fn Custom callback.\n         */\n        onkeydown: function onkeydown(fn) {\n            var self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onkeydown = fn;\n                return self;\n            } else {\n                self._onkeydown();\n            }\n        },\n\n        /**\n         * Set or fire the onkeyup event.\n         * @param  {Function} fn Custom callback.\n         */\n        onkeyup: function onkeyup(fn) {\n            var self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onkeyup = fn;\n                return self;\n            } else {\n                self._onkeyup();\n            }\n        },\n\n        /**\n         * Place focus on the CanvasInput box, placing the cursor\n         * either at the end of the text or where the user clicked.\n         * @param  {Number} pos (optional) The position to place the cursor.\n         * @return {CanvasInput}\n         */\n        focus: function focus(pos) {\n            var self = this;\n            var input; // if this is readonly, don't allow it to get focus\n\n            if (self._readonly) {\n                return;\n            } // only fire the focus event when going from unfocussed\n\n            if (!self._hasFocus) {\n                self._onfocus(self); // remove focus from all other inputs\n\n                for (var i = 0; i < inputs.length; i++) {\n                    if (inputs[i]._hasFocus) {\n                        inputs[i].blur();\n                    }\n                }\n            } // remove selection\n\n            if (!self._selectionUpdated) {\n                self._selection = [0, 0];\n            } else {\n                delete self._selectionUpdated;\n            } // update the cursor position\n\n            self._cursorPos = typeof pos === 'number' ? pos : self._clipText().length; // clear the place holder\n\n            if (self._placeHolder === self._value) {\n                self._value = '';\n                self._hiddenInput.value = '';\n            }\n\n            self._hasFocus = true;\n            self._cursor = true; // setup cursor interval\n\n            if (self._cursorInterval) {\n                clearInterval(self._cursorInterval);\n            }\n\n            requestAnimationFrame(function() {\n                self._cursorInterval = setInterval(function() {\n                    self._cursor = !self._cursor;\n                    self.render();\n                }, 500); // check if this is Chrome for Android (there is a bug with returning incorrect character key codes)\n            });\n\n            var nav = navigator.userAgent.toLowerCase();\n            var isChromeMobile =\n                nav.indexOf('chrome') >= 0 &&\n                nav.indexOf('mobile') >= 0 &&\n                nav.indexOf('android') >= 0; // add support for mobile\n\n            var isMobile = typeof window.orientation !== 'undefined';\n            var hasHiddenFocus = false;\n            if (\n                isMobile &&\n                !isChromeMobile &&\n                document &&\n                document.createElement &&\n                (input = document.createElement('input'))\n            ) {\n                input.type = 'text';\n                input.style.opacity = 0;\n                input.style.position = 'absolute';\n                input.style.left = ''.concat(\n                    self._x + self._extraX + (self._canvas ? self._canvas.offsetLeft : 0),\n                    'px'\n                );\n                input.style.top = ''.concat(\n                    self._y + self._extraY + (self._canvas ? self._canvas.offsetTop : 0),\n                    'px'\n                );\n                input.style.width = self._width;\n                input.style.height = 0;\n                const form = document.createElement('form');\n                form.appendChild(input);\n                document.body.appendChild(form);\n                input.focus();\n                input.addEventListener(\n                    'blur',\n                    function() {\n                        if (!hasHiddenFocus) {\n                            self.blur(self);\n                        }\n                    },\n                    false\n                );\n                input.addEventListener(\n                    'focus',\n                    () => {\n                        self.focus();\n                    },\n                    false\n                );\n            } else if (isMobile) {\n                self.value(prompt(self._placeHolder) || '');\n            } // move the real focus to the hidden input\n\n            var hasSelection = self._selection[0] > 0 || self._selection[1] > 0;\n            hasHiddenFocus = true;\n            self._hiddenInput.focus();\n            hasHiddenFocus = false;\n            self._hiddenInput.selectionStart = hasSelection ? self._selection[0] : self._cursorPos;\n            self._hiddenInput.selectionEnd = hasSelection ? self._selection[1] : self._cursorPos;\n\n            return self.render();\n        },\n\n        /**\n         * Removes focus from the CanvasInput box.\n         * @param  {Object} _this Reference to this.\n         * @return {CanvasInput}\n         */\n        blur: function blur(_this) {\n            var self = _this || this;\n\n            self._onblur(self);\n\n            if (self._cursorInterval) {\n                clearInterval(self._cursorInterval);\n            }\n\n            self._hasFocus = false;\n            self._cursor = false;\n            self._selection = [0, 0];\n\n            self._hiddenInput.blur(); // fill the place holder\n\n            if (self._value === '') {\n                self._value = self._placeHolder;\n            }\n\n            if (self._isHidden) {\n                return;\n            }\n\n            return self.render();\n        },\n\n        /**\n         * Fired with the keydown event to draw the typed characters.\n         * @param  {Event}       e    The keydown event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        keydown: function keydown(e, self) {\n            var keyCode = e.which;\n            var isShift = e.shiftKey;\n            var key = null;\n            var startText;\n            var endText; // make sure the correct text field is being updated\n\n            if (!self._hasFocus) {\n                return;\n            } // fire custom user event\n\n            self._onkeydown(e, self); // add support for Ctrl/Cmd+A selection\n\n            if (keyCode === 65 && (e.ctrlKey || e.metaKey)) {\n                self._selection = [0, self._value.length];\n                self._hiddenInput.selectionStart = 0;\n                self._hiddenInput.selectionEnd = self._value.length;\n                e.preventDefault();\n                return self.render();\n            } // block keys that shouldn't be processed\n\n            if (keyCode === 17 || e.metaKey || e.ctrlKey) {\n                return self;\n            }\n\n            if (keyCode === 13) {\n                // enter key\n                e.preventDefault();\n\n                self._onsubmit(e, self); //Entry.dispatchEvent('canvasInputComplete');\n            } else if (keyCode === 9) {\n                // tab key\n                e.preventDefault();\n\n                if (inputs.length > 1) {\n                    var next = inputs[self._inputsIndex + 1] ? self._inputsIndex + 1 : 0;\n                    self.blur();\n                    setTimeout(function() {\n                        inputs[next].focus();\n                    }, 5);\n                }\n            } // update the canvas input state information from the hidden input\n\n            self._value = self._hiddenInput.value;\n            self._cursorPos = self._hiddenInput.selectionStart;\n            self._selection = [0, 0];\n\n            if (!self._isHidden) {\n                return self.render();\n            }\n        },\n\n        /**\n         * Fired with the click event on the canvas, and puts focus on/off\n         * based on where the user clicks.\n         * @param  {Event}       e    The click event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        click: function click(e, self) {\n            //var mouse = self._mousePos(e),\n            //x = mouse.x,\n            //y = mouse.y;\n            if (this._isFirstClick) {\n                delete this._isFirstClick;\n                return;\n            }\n\n            var roundRect = Entry.stage.canvas.canvas.getBoundingClientRect();\n            var x = ((e.x - roundRect.left) / roundRect.width - 0.5) * 480;\n            var y = ((e.y - roundRect.top) / roundRect.height - 0.5) * -270;\n\n            if (self._endSelection) {\n                delete self._endSelection;\n                delete self._selectionUpdated;\n                return;\n            }\n\n            if ((self._canvas && self._overInput(x, y)) || !self._canvas) {\n                if (self._isHidden) {\n                    return;\n                }\n\n                if (self._mouseDown) {\n                    self._mouseDown = false;\n                    self.click(e, self);\n                    return self.focus(self._clickPos(x, y));\n                }\n            } else {\n                return self.blur();\n            }\n        },\n\n        /**\n         * Fired with the mousemove event to update the default cursor.\n         * @param  {Event}       e    The mousemove event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        mousemove: function mousemove(e, self) {\n            var mouse = self._mousePos(e);\n\n            var x = mouse.x;\n            var y = mouse.y;\n\n            var isOver = self._overInput(x, y);\n\n            if (isOver && self._canvas) {\n                self._canvas.style.cursor = 'text';\n                self._wasOver = true;\n            } else if (self._wasOver && self._canvas) {\n                self._canvas.style.cursor = 'default';\n                self._wasOver = false;\n            }\n\n            if (self._hasFocus && self._selectionStart >= 0) {\n                var curPos = self._clickPos(x, y);\n\n                var start = Math.min(self._selectionStart, curPos);\n                var end = Math.max(self._selectionStart, curPos);\n\n                if (!isOver) {\n                    self._selectionUpdated = true;\n                    self._endSelection = true;\n                    delete self._selectionStart;\n                    self.render();\n                    return;\n                }\n\n                if (self._selection[0] !== start || self._selection[1] !== end) {\n                    self._selection = [start, end];\n                    self.render();\n                }\n            }\n        },\n\n        /**\n         * Fired with the mousedown event to start a selection drag.\n         * @param  {Event} e    The mousedown event.\n         * @param  {CanvasInput} self\n         */\n        mousedown: function mousedown(e, self) {\n            e = Entry.Utils.convertMouseEvent(e);\n            var roundRect = Entry.stage.getBoundRect();\n            var offsetX = e.offsetX || e.clientX - roundRect.left;\n            var offsetY = e.offsetY || e.clientY - roundRect.top;\n            var x = (offsetX / roundRect.width - 0.5) * 480;\n            var y = (offsetY / roundRect.height - 0.5) * -270;\n            var isOver = self._overInput(x, y); // setup the 'click' event\n\n            self._mouseDown = isOver;\n            var inputField = Entry.stage.inputField;\n\n            if (isOver && !inputField._isHidden) {\n                self._hasFocus = true;\n                inputField.focus();\n            } else if (!isOver && inputField) {\n                self._hasFocus = false;\n                inputField.blur();\n            } // start the selection drag if inside the input\n\n            if (self._hasFocus && isOver) {\n                self._selectionStart = self._clickPos(x, y);\n            }\n        },\n\n        /**\n         * Fired with the mouseup event to end a selection drag.\n         * @param  {Event} e    The mouseup event.\n         * @param  {CanvasInput} self\n         */\n        mouseup: function mouseup(e, self) {\n            //var mouse = self._mousePos(e),\n            //x = mouse.x,\n            //y = mouse.y;\n            //// update selection if a drag has happened\n            //var isSelection = self._clickPos(x, y) !== self._selectionStart;\n            //if (self._hasFocus && self._selectionStart >= 0 && self._overInput(x, y) && isSelection) {\n            //self._selectionUpdated = true;\n            //delete self._selectionStart;\n            //self.render();\n            //} else {\n            //delete self._selectionStart;\n            //}\n            //self.click(e, self);\n            // if (self._isHidden)\n            //     return;\n            // self.render();\n            // self.click(e,self);\n            // var roundRect = Entry.stage.canvas.canvas.getBoundingClientRect();\n            // var x = ((e.clientX - roundRect.left) / roundRect.width - 0.5) * 480;\n            // var y = ((e.clientY - roundRect.top) / roundRect.height - 0.5) * -270;\n        },\n\n        /**\n         * Helper method to get the off-DOM canvas.\n         * @return {Object} Reference to the canvas.\n         */\n        renderCanvas: function renderCanvas() {\n            return this._renderCanvas;\n        },\n        show: function show() {\n            var self = this;\n            self._isHidden = false;\n            self._isFirstClick = true;\n            self.value('');\n            self.focus();\n        },\n        hide: function hide() {\n            var self = this;\n            self._isHidden = true;\n            self.blur();\n        },\n        setPosition: function setPosition(x, y) {\n            var self = this;\n            self._isHidden = false;\n            self._isFirstClick = true;\n            self._x = x || 0;\n            self._y = y || 0;\n            self.value('');\n            self.focus();\n        },\n\n        /**\n         * Clears and redraws the CanvasInput on an off-DOM canvas,\n         * and if a main canvas is provided, draws it all onto that.\n         * @return {CanvasInput}\n         */\n        render: function render() {\n            var self = this;\n            var ctx = self._renderCtx;\n            var w = self.outerW;\n            var h = self.outerH;\n            var br = self._borderRadius;\n            var bw = self._borderWidth;\n            var sw = self.shadowW;\n            var sh = self.shadowH; // clear the canvas\n\n            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // setup the box shadow\n\n            ctx.shadowOffsetX = self._boxShadow.x;\n            ctx.shadowOffsetY = self._boxShadow.y;\n            ctx.shadowBlur = self._boxShadow.blur;\n            ctx.shadowColor = self._boxShadow.color; // draw the border\n\n            if (self._borderWidth > 0) {\n                ctx.fillStyle = self._borderColor; // self._roundedRect(ctx, self.shadowL, self.shadowT, w - sw, h - sh, br);\n\n                self._roundedRect(ctx, self.shadowL, self.shadowT, w - sw, h - sh, br);\n\n                ctx.fill();\n                ctx.shadowOffsetX = 0;\n                ctx.shadowOffsetY = 0;\n                ctx.shadowBlur = 0;\n            } // draw the text box background\n\n            self._drawTextBox(function() {\n                // make sure all shadows are reset\n                ctx.shadowOffsetX = 0;\n                ctx.shadowOffsetY = 0;\n                ctx.shadowBlur = 0; // clip the text so that it fits within the box\n\n                var text = self._clipText(); // draw the selection\n\n                var paddingBorder = self._padding + self._borderWidth + self.shadowT;\n\n                if (self._selection[1] > 0) {\n                    var selectOffset = self._textWidth(text.substring(0, self._selection[0]));\n\n                    var selectWidth = self._textWidth(\n                        text.substring(self._selection[0], self._selection[1])\n                    );\n\n                    ctx.fillStyle = self._selectionColor;\n                    ctx.fillRect(\n                        paddingBorder + selectOffset,\n                        paddingBorder,\n                        selectWidth,\n                        self._height\n                    );\n                } // draw the cursor\n\n                if (self._cursor) {\n                    var cursorOffset = self._textWidth(text.substring(0, self._cursorPos));\n\n                    ctx.fillStyle = self._fontColor;\n                    ctx.fillRect(paddingBorder + cursorOffset, paddingBorder, 1, self._height);\n                } // draw the text\n\n                var textX = self._padding + self._borderWidth + self.shadowL;\n                var textY = Math.round(paddingBorder + self._height / 2); // only remove the placeholder text if they have typed something\n\n                text = text === '' && self._placeHolder ? self._placeHolder : text;\n                ctx.fillStyle =\n                    self._value !== '' && self._value !== self._placeHolder\n                        ? self._fontColor\n                        : self._placeHolderColor;\n                ctx.font = ''\n                    .concat(self._fontStyle, ' ')\n                    .concat(self._fontWeight, ' ')\n                    .concat(self._fontSize, 'px ')\n                    .concat(self._fontFamily);\n                ctx.textAlign = 'left';\n                ctx.textBaseline = 'middle';\n                ctx.fillText(text, textX, textY); // parse inner shadow\n\n                var innerShadow = self._innerShadow.split('px ');\n\n                var isOffsetX = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[0], 10);\n                var isOffsetY = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[1], 10);\n                var isBlur = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[2], 10);\n                var isColor = self._innerShadow === 'none' ? '' : innerShadow[3]; // draw the inner-shadow (damn you canvas, this should be easier than this...)\n\n                if (isBlur > 0) {\n                    var shadowCtx = self._shadowCtx;\n                    var scw = shadowCtx.canvas.width;\n                    var sch = shadowCtx.canvas.height;\n                    shadowCtx.clearRect(0, 0, scw, sch);\n                    shadowCtx.shadowBlur = isBlur;\n                    shadowCtx.shadowColor = isColor; // top shadow\n\n                    shadowCtx.shadowOffsetX = 0;\n                    shadowCtx.shadowOffsetY = isOffsetY;\n                    shadowCtx.fillRect(-1 * w, -100, 3 * w, 100); // right shadow\n\n                    shadowCtx.shadowOffsetX = isOffsetX;\n                    shadowCtx.shadowOffsetY = 0;\n                    shadowCtx.fillRect(scw, -1 * h, 100, 3 * h); // bottom shadow\n\n                    shadowCtx.shadowOffsetX = 0;\n                    shadowCtx.shadowOffsetY = isOffsetY;\n                    shadowCtx.fillRect(-1 * w, sch, 3 * w, 100); // left shadow\n\n                    shadowCtx.shadowOffsetX = isOffsetX;\n                    shadowCtx.shadowOffsetY = 0;\n                    shadowCtx.fillRect(-100, -1 * h, 100, 3 * h); // create a clipping mask on the main canvas\n\n                    self._roundedRect(\n                        ctx,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        w - bw * 2 - sw,\n                        h - bw * 2 - sh,\n                        br\n                    );\n\n                    ctx.clip(); // draw the inner-shadow from the off-DOM canvas\n\n                    ctx.drawImage(\n                        self._shadowCanvas,\n                        0,\n                        0,\n                        scw,\n                        sch,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        scw,\n                        sch\n                    );\n                } // draw to the visible canvas\n\n                if (self._ctx) {\n                    // self._ctx.clearRect(self._x, self._y, ctx.canvas.width, ctx.canvas.height);\n                    self._ctx.drawImage(self._renderCanvas, self._x, self._y);\n                }\n\n                return self;\n            });\n        },\n\n        /**\n         * Draw the text box area with either an image or background color.\n         * @param  {Function} fn Callback.\n         */\n        _drawTextBox: function _drawTextBox(fn) {\n            var self = this;\n            var ctx = self._renderCtx;\n            var w = self.outerW;\n            var h = self.outerH;\n            var br = self._borderRadius;\n            var bw = self._borderWidth;\n            var sw = self.shadowW;\n            var sh = self.shadowH; // only draw the background shape if no image is being used\n\n            if (self._backgroundImage === '') {\n                ctx.fillStyle = self._backgroundColor;\n\n                self._roundedRect(\n                    ctx,\n                    bw + self.shadowL,\n                    bw + self.shadowT,\n                    w - bw * 2 - sw,\n                    h - bw * 2 - sh,\n                    br\n                );\n\n                ctx.fill();\n                fn();\n            } else {\n                var img = new Image();\n                img.src = self._backgroundImage;\n\n                img.onload = function() {\n                    ctx.drawImage(\n                        img,\n                        0,\n                        0,\n                        img.width,\n                        img.height,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        w,\n                        h\n                    );\n                    fn();\n                };\n            }\n        },\n\n        /**\n         * Deletes selected text in selection range and repositions cursor.\n         * @return {Boolean} true if text removed.\n         */\n        _clearSelection: function _clearSelection() {\n            var self = this;\n\n            if (self._selection[1] > 0) {\n                // clear the selected contents\n                var start = self._selection[0];\n                var end = self._selection[1];\n                self._value = self._value.substr(0, start) + self._value.substr(end);\n                self._cursorPos = start;\n                self._cursorPos = self._cursorPos < 0 ? 0 : self._cursorPos;\n                self._selection = [0, 0];\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * Clip the text string to only return what fits in the visible text box.\n         * @param  {String} value The text to clip.\n         * @return {String} The clipped text.\n         */\n        _clipText: function _clipText(value) {\n            var self = this;\n            value = typeof value === 'undefined' ? self._value : value;\n\n            var textWidth = self._textWidth(value);\n\n            var fillPer = textWidth / (self._width - self._padding);\n            var text = fillPer > 1 ? value.substr(-1 * Math.floor(value.length / fillPer)) : value;\n            return ''.concat(text);\n        },\n\n        /**\n         * Gets the pixel with of passed text.\n         * @param  {String} text The text to measure.\n         * @return {Number}      The measured width.\n         */\n        _textWidth: function _textWidth(text) {\n            var self = this;\n            var ctx = self._renderCtx;\n            ctx.font = ''\n                .concat(self._fontStyle, ' ')\n                .concat(self._fontWeight, ' ')\n                .concat(self._fontSize, 'px ')\n                .concat(self._fontFamily);\n            ctx.textAlign = 'left';\n            return ctx.measureText(text).width;\n        },\n\n        /**\n         * Recalculate the outer with and height of the text box.\n         */\n        _calcWH: function _calcWH() {\n            var self = this; // calculate the full width and height with padding, borders and shadows\n\n            self.outerW = self._width + self._padding * 2 + self._borderWidth * 2 + self.shadowW;\n            self.outerH = self._height + self._padding * 2 + self._borderWidth * 2 + self.shadowH;\n        },\n\n        /**\n         * Update the width and height of the off-DOM canvas when attributes are changed.\n         */\n        _updateCanvasWH: function _updateCanvasWH() {\n            var self = this;\n            var oldW = self._renderCanvas.width;\n            var oldH = self._renderCanvas.height; // update off-DOM canvas\n\n            self._renderCanvas.setAttribute('width', self.outerW);\n\n            self._renderCanvas.setAttribute('height', self.outerH);\n\n            self._shadowCanvas.setAttribute('width', self._width + self._padding * 2);\n\n            self._shadowCanvas.setAttribute('height', self._height + self._padding * 2); // clear the main canvas\n\n            if (self._ctx) {\n                self._ctx.clearRect(self._x, self._y, oldW, oldH);\n            }\n        },\n\n        /**\n         * Creates the path for a rectangle with rounded corners.\n         * Must call ctx.fill() after calling this to draw the rectangle.\n         * @param  {Object} ctx Canvas context.\n         * @param  {Number} x   x-coordinate to draw from.\n         * @param  {Number} y   y-coordinate to draw from.\n         * @param  {Number} w   Width of rectangle.\n         * @param  {Number} h   Height of rectangle.\n         * @param  {Number} r   Border radius.\n         */\n        _roundedRect: function _roundedRect(ctx, x, y, w, h, r) {\n            if (w < 2 * r) {\n                r = w / 2;\n            }\n\n            if (h < 2 * r) {\n                r = h / 2;\n            }\n\n            ctx.beginPath();\n            ctx.moveTo(x + r, y);\n            ctx.lineTo(x + w - r, y);\n            ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n            ctx.lineTo(x + w, y + h - r);\n            ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n            ctx.lineTo(x + r, y + h);\n            ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n            ctx.lineTo(x, y + r);\n            ctx.quadraticCurveTo(x, y, x + r, y);\n            ctx.closePath();\n        },\n\n        /**\n         * Checks if a coordinate point is over the input box.\n         * @param  {Number} x x-coordinate position.\n         * @param  {Number} y y-coordinate position.\n         * @return {Boolean}   True if it is over the input box.\n         */\n        _overInput: function _overInput(x, y) {\n            return x >= -226 && x <= 183 && y >= -110 && y <= -73;\n        },\n\n        /**\n         * Use the mouse's x & y coordinates to determine\n         * the position clicked in the text.\n         * @param  {Number} x X-coordinate.\n         * @param  {Number} y Y-coordinate.\n         * @return {Number}   Cursor position.\n         */\n        _clickPos: function _clickPos(x, y) {\n            var self = this;\n            var value = self._value; // don't count placeholder text in this\n\n            if (self._value === self._placeHolder) {\n                value = '';\n            } // determine where the click was made along the string\n\n            var text = self._clipText(value);\n\n            var totalW = 0;\n            var pos = text.length;\n\n            if (x - (self._x + self._extraX) < self._textWidth(text)) {\n                // loop through each character to identify the position\n                for (var i = 0; i < text.length; i++) {\n                    totalW += self._textWidth(text[i]);\n\n                    if (totalW >= x - (self._x + self._extraX)) {\n                        pos = i;\n                        break;\n                    }\n                }\n            }\n\n            return pos;\n        },\n\n        /**\n         * Calculate the mouse position based on the event callback and the elements on the page.\n         * @param  {Event} e\n         * @return {Object}   x & y values\n         */\n        _mousePos: function _mousePos(e) {\n            var elm = e.target;\n            var style = document.defaultView.getComputedStyle(elm, undefined);\n            var paddingLeft = parseInt(style.paddingLeft, 10) || 0;\n            var paddingTop = parseInt(style.paddingLeft, 10) || 0;\n            var borderLeft = parseInt(style.borderLeftWidth, 10) || 0;\n            var borderTop = parseInt(style.borderLeftWidth, 10) || 0;\n            var htmlTop = document.body.parentNode.offsetTop || 0;\n            var htmlLeft = document.body.parentNode.offsetLeft || 0;\n            var offsetX = 0;\n            var offsetY = 0;\n            var x;\n            var y; // calculate the total offset\n\n            if (typeof elm.offsetParent !== 'undefined') {\n                do {\n                    offsetX += elm.offsetLeft;\n                    offsetY += elm.offsetTop;\n                } while ((elm = elm.offsetParent));\n            } // take into account borders and padding\n\n            offsetX += paddingLeft + borderLeft + htmlLeft;\n            offsetY += paddingTop + borderTop + htmlTop;\n            return {\n                x: e.pageX - offsetX,\n                y: e.pageY - offsetY,\n            };\n        },\n        hasFocus: function hasFocus() {\n            return this._hasFocus;\n        },\n    };\n})();\n"
  },
  {
    "path": "extern/util/CanvasInputOrg.js",
    "content": "/*!\n *  CanvasInput v1.1.5\n *  http://goldfirestudios.com/blog/108/CanvasInput-HTML5-Canvas-Text-Input\n *\n *  (c) 2013-2014, James Simpson of GoldFire Studios\n *  goldfirestudios.com\n *\n *  MIT License\n */\n\n(function() {\n    // create a buffer that stores all inputs so that tabbing\n    // between them is made possible.\n    const inputs = [];\n\n    // initialize the Canvas Input\n    const CanvasInput = function(o) {\n        const self = this;\n\n        o = o ? o : {};\n\n        // setup the defaults\n        self._canvas = o.canvas || null;\n        self._isHidden = true;\n        self._ctx = self._canvas ? self._canvas.getContext('2d') : null;\n        self._x = o.x || 0;\n        self._y = o.y || 0;\n        self._extraX = o.extraX || 0;\n        self._extraY = o.extraY || 0;\n        self._fontSize = o.fontSize || 14;\n        self._fontFamily = o.fontFamily || 'Arial';\n        self._fontColor = o.fontColor || '#000';\n        self._placeHolderColor = o.placeHolderColor || '#bfbebd';\n        self._fontWeight = o.fontWeight || 'normal';\n        self._fontStyle = o.fontStyle || 'normal';\n        self._readonly = o.readonly || false;\n        self._maxlength = o.maxlength || null;\n        self._width = o.width || 150;\n        self._height = o.height || self._fontSize;\n        self._padding = o.padding >= 0 ? o.padding : 5;\n        self._borderWidth = o.borderWidth >= 0 ? o.borderWidth : 1;\n        self._borderColor = o.borderColor || '#959595';\n        self._borderRadius = o.borderRadius >= 0 ? o.borderRadius : 3;\n        self._backgroundImage = o.backgroundImage || '';\n        self._boxShadow = o.boxShadow || '1px 1px 0px rgba(255, 255, 255, 1)';\n        self._innerShadow = o.innerShadow || '0px 0px 4px rgba(0, 0, 0, 0.4)';\n        self._selectionColor = o.selectionColor || 'rgba(179, 212, 253, 0.8)';\n        self._placeHolder = o.placeHolder || '';\n        self._value = o.value || self._placeHolder;\n        self._onsubmit = o.onsubmit || function() {};\n        self._onkeydown = o.onkeydown || function() {};\n        self._onkeyup = o.onkeyup || function() {};\n        self._onfocus = o.onfocus || function() {};\n        self._onblur = o.onblur || function() {};\n        self._cursor = false;\n        self._cursorPos = 0;\n        self._hasFocus = false;\n        self._selection = [0, 0];\n        self._wasOver = false;\n        self._topPosition = o.topPosition;\n\n        // parse box shadow\n        self.boxShadow(self._boxShadow, true);\n\n        // calculate the full width and height with padding, borders and shadows\n        self._calcWH();\n\n        // setup the off-DOM canvas\n        self._renderCanvas = document.createElement('canvas');\n        self._renderCanvas.setAttribute('width', self.outerW);\n        self._renderCanvas.setAttribute('height', self.outerH);\n        self._renderCtx = self._renderCanvas.getContext('2d');\n\n        // setup another off-DOM canvas for inner-shadows\n        self._shadowCanvas = document.createElement('canvas');\n        self._shadowCanvas.setAttribute('width', self._width + self._padding * 2);\n        self._shadowCanvas.setAttribute('height', self._height + self._padding * 2);\n        self._shadowCtx = self._shadowCanvas.getContext('2d');\n\n        // setup the background color\n        if (typeof o.backgroundGradient !== 'undefined') {\n            self._backgroundColor = self._renderCtx.createLinearGradient(0, 0, 0, self.outerH);\n            self._backgroundColor.addColorStop(0, o.backgroundGradient[0]);\n            self._backgroundColor.addColorStop(1, o.backgroundGradient[1]);\n        } else {\n            self._backgroundColor = o.backgroundColor || '#fff';\n        }\n\n        // setup main canvas events\n        if (self._canvas) {\n            self._canvas.addEventListener(\n                'mousemove',\n                (e) => {\n                    e = e || window.event;\n                    self.mousemove(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'mousedown',\n                (e) => {\n                    e = e || window.event;\n                    self.mousedown(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'touchstart',\n                (e) => {\n                    e = e || window.event;\n                    self.mousedown(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'mouseup',\n                (e) => {\n                    e = e || window.event;\n                    self.mouseup(e, self);\n                },\n                false\n            );\n        }\n\n        // setup a global mouseup to blur the input outside of the canvas\n        window.addEventListener(\n            'mouseup',\n            (e) => {\n                //e = e || window.event;\n                //if (self._hasFocus && !self._mouseDown) {\n                //self.blur();\n                //}\n            },\n            true\n        );\n\n        // create the hidden input element\n        self._hiddenInput = document.createElement('input');\n        self._hiddenInput.className = 'entryCanvasHiddenInput';\n        self._hiddenInput.type = 'text';\n        self._hiddenInput.style.position = 'absolute';\n        self._hiddenInput.style.opacity = 0;\n        self._hiddenInput.style.pointerEvents = 'none';\n        self._hiddenInput.style.left = '-500px';\n        self._hiddenInput.style.top = '0px';\n        self._hiddenInput.style.width = `${self._width}px`;\n        self._hiddenInput.style.height = `${self._height}px`;\n        self._hiddenInput.style.zIndex = -999;\n        if (self._maxlength) {\n            self._hiddenInput.maxLength = self._maxlength;\n        }\n        document.body.appendChild(self._hiddenInput);\n        self._hiddenInput.value = self._value;\n\n        // setup the keydown listener\n        self._hiddenInput.addEventListener('keydown', (e) => {\n            e = e || window.event;\n\n            if (self._hasFocus) {\n                self.keydown(e, self);\n            }\n        });\n\n        // setup the keyup listener\n        self._hiddenInput.addEventListener('keyup', (e) => {\n            e = e || window.event;\n\n            // update the canvas input state information from the hidden input\n            self._value = self._hiddenInput.value;\n            self._cursorPos = self._hiddenInput.selectionStart;\n            self.render();\n\n            if (self._hasFocus) {\n                self._onkeyup(e, self);\n            }\n        });\n\n        // add this to the buffer\n        inputs.push(self);\n        self._inputsIndex = inputs.length - 1;\n\n        // draw the text box\n        self.render();\n    };\n    window.CanvasInput = CanvasInput;\n    // setup the prototype\n    CanvasInput.prototype = {\n        /**\n         * Get/set the main canvas.\n         * @param  {Object} data Canvas reference.\n         * @return {Mixed}      CanvasInput or current canvas.\n         */\n        canvas(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._canvas = data;\n                self._ctx = self._canvas.getContext('2d');\n\n                return self.render();\n            } else {\n                return self._canvas;\n            }\n        },\n\n        /**\n         * Get/set the x-position.\n         * @param  {Number} data The pixel position along the x-coordinate.\n         * @return {Mixed}      CanvasInput or current x-value.\n         */\n        x(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._x = data;\n\n                return self.render();\n            } else {\n                return self._x;\n            }\n        },\n\n        /**\n         * Get/set the y-position.\n         * @param  {Number} data The pixel position along the y-coordinate.\n         * @return {Mixed}      CanvasInput or current y-value.\n         */\n        y(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._y = data;\n\n                return self.render();\n            } else {\n                return self._y;\n            }\n        },\n\n        /**\n         * Get/set the extra x-position (generally used when no canvas is specified).\n         * @param  {Number} data The pixel position along the x-coordinate.\n         * @return {Mixed}      CanvasInput or current x-value.\n         */\n        extraX(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._extraX = data;\n\n                return self.render();\n            } else {\n                return self._extraX;\n            }\n        },\n\n        /**\n         * Get/set the extra y-position (generally used when no canvas is specified).\n         * @param  {Number} data The pixel position along the y-coordinate.\n         * @return {Mixed}      CanvasInput or current y-value.\n         */\n        extraY(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._extraY = data;\n\n                return self.render();\n            } else {\n                return self._extraY;\n            }\n        },\n\n        /**\n         * Get/set the font size.\n         * @param  {Number} data Font size.\n         * @return {Mixed}      CanvasInput or current font size.\n         */\n        fontSize(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontSize = data;\n\n                return self.render();\n            } else {\n                return self._fontSize;\n            }\n        },\n\n        /**\n         * Get/set the font family.\n         * @param  {String} data Font family.\n         * @return {Mixed}      CanvasInput or current font family.\n         */\n        fontFamily(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontFamily = data;\n\n                return self.render();\n            } else {\n                return self._fontFamily;\n            }\n        },\n\n        /**\n         * Get/set the font color.\n         * @param  {String} data Font color.\n         * @return {Mixed}      CanvasInput or current font color.\n         */\n        fontColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontColor = data;\n\n                return self.render();\n            } else {\n                return self._fontColor;\n            }\n        },\n\n        /**\n         * Get/set the place holder font color.\n         * @param  {String} data Font color.\n         * @return {Mixed}      CanvasInput or current place holder font color.\n         */\n        placeHolderColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._placeHolderColor = data;\n\n                return self.render();\n            } else {\n                return self._placeHolderColor;\n            }\n        },\n\n        /**\n         * Get/set the font weight.\n         * @param  {String} data Font weight.\n         * @return {Mixed}      CanvasInput or current font weight.\n         */\n        fontWeight(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontWeight = data;\n\n                return self.render();\n            } else {\n                return self._fontWeight;\n            }\n        },\n\n        /**\n         * Get/set the font style.\n         * @param  {String} data Font style.\n         * @return {Mixed}      CanvasInput or current font style.\n         */\n        fontStyle(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontStyle = data;\n\n                return self.render();\n            } else {\n                return self._fontStyle;\n            }\n        },\n\n        /**\n         * Get/set the width of the text box.\n         * @param  {Number} data Width in pixels.\n         * @return {Mixed}      CanvasInput or current width.\n         */\n        width(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._width = data;\n                self._calcWH();\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._width;\n            }\n        },\n\n        /**\n         * Get/set the height of the text box.\n         * @param  {Number} data Height in pixels.\n         * @return {Mixed}      CanvasInput or current height.\n         */\n        height(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._height = data;\n                self._calcWH();\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._height;\n            }\n        },\n\n        /**\n         * Get/set the padding of the text box.\n         * @param  {Number} data Padding in pixels.\n         * @return {Mixed}      CanvasInput or current padding.\n         */\n        padding(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._padding = data;\n                self._calcWH();\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._padding;\n            }\n        },\n\n        /**\n         * Get/set the border width.\n         * @param  {Number} data Border width.\n         * @return {Mixed}      CanvasInput or current border width.\n         */\n        borderWidth(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderWidth = data;\n                self._calcWH();\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._borderWidth;\n            }\n        },\n\n        /**\n         * Get/set the border color.\n         * @param  {String} data Border color.\n         * @return {Mixed}      CanvasInput or current border color.\n         */\n        borderColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderColor = data;\n\n                return self.render();\n            } else {\n                return self._borderColor;\n            }\n        },\n\n        /**\n         * Get/set the border radius.\n         * @param  {Number} data Border radius.\n         * @return {Mixed}      CanvasInput or current border radius.\n         */\n        borderRadius(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderRadius = data;\n\n                return self.render();\n            } else {\n                return self._borderRadius;\n            }\n        },\n\n        /**\n         * Get/set the background color.\n         * @param  {Number} data Background color.\n         * @return {Mixed}      CanvasInput or current background color.\n         */\n        backgroundColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._backgroundColor = data;\n\n                return self.render();\n            } else {\n                return self._backgroundColor;\n            }\n        },\n\n        /**\n         * Get/set the background gradient.\n         * @param  {Number} data Background gradient.\n         * @return {Mixed}      CanvasInput or current background gradient.\n         */\n        backgroundGradient(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._backgroundColor = self._renderCtx.createLinearGradient(0, 0, 0, self.outerH);\n                self._backgroundColor.addColorStop(0, data[0]);\n                self._backgroundColor.addColorStop(1, data[1]);\n\n                return self.render();\n            } else {\n                return self._backgroundColor;\n            }\n        },\n\n        /**\n         * Get/set the box shadow.\n         * @param  {String} data     Box shadow in CSS format (1px 1px 1px rgba(0, 0, 0.5)).\n         * @param  {Boolean} doReturn (optional) True to prevent a premature render.\n         * @return {Mixed}          CanvasInput or current box shadow.\n         */\n        boxShadow(data, doReturn) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                // parse box shadow\n                const boxShadow = data.split('px ');\n                self._boxShadow = {\n                    x: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[0], 10),\n                    y: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[1], 10),\n                    blur: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[2], 10),\n                    color: self._boxShadow === 'none' ? '' : boxShadow[3],\n                };\n\n                // take into account the shadow and its direction\n                if (self._boxShadow.x < 0) {\n                    self.shadowL = Math.abs(self._boxShadow.x) + self._boxShadow.blur;\n                    self.shadowR = self._boxShadow.blur + self._boxShadow.x;\n                } else {\n                    self.shadowL = Math.abs(self._boxShadow.blur - self._boxShadow.x);\n                    self.shadowR = self._boxShadow.blur + self._boxShadow.x;\n                }\n                if (self._boxShadow.y < 0) {\n                    self.shadowT = Math.abs(self._boxShadow.y) + self._boxShadow.blur;\n                    self.shadowB = self._boxShadow.blur + self._boxShadow.y;\n                } else {\n                    self.shadowT = Math.abs(self._boxShadow.blur - self._boxShadow.y);\n                    self.shadowB = self._boxShadow.blur + self._boxShadow.y;\n                }\n\n                self.shadowW = self.shadowL + self.shadowR;\n                self.shadowH = self.shadowT + self.shadowB;\n\n                self._calcWH();\n\n                if (!doReturn) {\n                    self._updateCanvasWH();\n\n                    return self.render();\n                }\n            } else {\n                return self._boxShadow;\n            }\n        },\n\n        /**\n         * Get/set the inner shadow.\n         * @param  {String} data In the format of a CSS box shadow (1px 1px 1px rgba(0, 0, 0.5)).\n         * @return {Mixed}          CanvasInput or current inner shadow.\n         */\n        innerShadow(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._innerShadow = data;\n\n                return self.render();\n            } else {\n                return self._innerShadow;\n            }\n        },\n\n        /**\n         * Get/set the text selection color.\n         * @param  {String} data Color.\n         * @return {Mixed}      CanvasInput or current selection color.\n         */\n        selectionColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._selectionColor = data;\n\n                return self.render();\n            } else {\n                return self._selectionColor;\n            }\n        },\n\n        /**\n         * Get/set the place holder text.\n         * @param  {String} data Place holder text.\n         * @return {Mixed}      CanvasInput or current place holder text.\n         */\n        placeHolder(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._placeHolder = data;\n\n                return self.render();\n            } else {\n                return self._placeHolder;\n            }\n        },\n\n        /**\n         * Get/set the current text box value.\n         * @param  {String} data Text value.\n         * @return {Mixed}      CanvasInput or current text value.\n         */\n        value(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._value = `${data}`;\n                self._hiddenInput.value = `${data}`;\n\n                // update the cursor position\n                self._cursorPos = self._clipText().length;\n\n                self.render();\n\n                return self;\n            } else {\n                return self._value === self._placeHolder ? '' : self._value;\n            }\n        },\n\n        /**\n         * Set or fire the onsubmit event.\n         * @param  {Function} fn Custom callback.\n         */\n        onsubmit(fn) {\n            const self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onsubmit = fn;\n\n                return self;\n            } else {\n                self._onsubmit();\n            }\n        },\n\n        /**\n         * Set or fire the onkeydown event.\n         * @param  {Function} fn Custom callback.\n         */\n        onkeydown(fn) {\n            const self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onkeydown = fn;\n\n                return self;\n            } else {\n                self._onkeydown();\n            }\n        },\n\n        /**\n         * Set or fire the onkeyup event.\n         * @param  {Function} fn Custom callback.\n         */\n        onkeyup(fn) {\n            const self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onkeyup = fn;\n\n                return self;\n            } else {\n                self._onkeyup();\n            }\n        },\n\n        /**\n         * Place focus on the CanvasInput box, placing the cursor\n         * either at the end of the text or where the user clicked.\n         * @param  {Number} pos (optional) The position to place the cursor.\n         * @return {CanvasInput}\n         */\n        focus(pos) {\n            const self = this;\n            let input;\n\n            // if this is readonly, don't allow it to get focus\n            if (self._readonly) {\n                return;\n            }\n\n            // only fire the focus event when going from unfocussed\n            if (!self._hasFocus) {\n                self._onfocus(self);\n\n                // remove focus from all other inputs\n                for (let i = 0; i < inputs.length; i++) {\n                    if (inputs[i]._hasFocus) {\n                        inputs[i].blur();\n                    }\n                }\n            }\n\n            // remove selection\n            if (!self._selectionUpdated) {\n                self._selection = [0, 0];\n            } else {\n                delete self._selectionUpdated;\n            }\n\n            // update the cursor position\n            self._cursorPos = typeof pos === 'number' ? pos : self._clipText().length;\n\n            // clear the place holder\n            if (self._placeHolder === self._value) {\n                self._value = '';\n                self._hiddenInput.value = '';\n            }\n\n            self._hasFocus = true;\n            self._cursor = true;\n\n            // setup cursor interval\n            if (self._cursorInterval) {\n                clearInterval(self._cursorInterval);\n            }\n            self._cursorInterval = setInterval(() => {\n                self._cursor = !self._cursor;\n                self.render();\n            }, 500);\n\n            // check if this is Chrome for Android (there is a bug with returning incorrect character key codes)\n            const nav = navigator.userAgent.toLowerCase();\n            const isChromeMobile =\n                nav.indexOf('chrome') >= 0 &&\n                nav.indexOf('mobile') >= 0 &&\n                nav.indexOf('android') >= 0;\n\n            // add support for mobile\n            const isMobile = typeof window.orientation !== 'undefined';\n            if (\n                isMobile &&\n                !isChromeMobile &&\n                document &&\n                document.createElement &&\n                (input = document.createElement('input'))\n            ) {\n                input.type = 'text';\n                input.style.opacity = 0;\n                input.style.position = 'absolute';\n                input.style.left = `${self._x +\n                    self._extraX +\n                    (self._canvas ? self._canvas.offsetLeft : 0)}px`;\n                input.style.top = `${self._y +\n                    self._extraY +\n                    (self._canvas ? self._canvas.offsetTop : 0)}px`;\n                input.style.width = self._width;\n                input.style.height = 0;\n                document.body.appendChild(input);\n                input.focus();\n                input.addEventListener(\n                    'blur',\n                    () => {\n                        self.blur(self);\n                    },\n                    false\n                );\n            } else if (isMobile) {\n                self.value(prompt(self._placeHolder) || '');\n            }\n\n            // move the real focus to the hidden input\n            const hasSelection = self._selection[0] > 0 || self._selection[1] > 0;\n            self._hiddenInput.focus();\n            self._hiddenInput.selectionStart = hasSelection ? self._selection[0] : self._cursorPos;\n            self._hiddenInput.selectionEnd = hasSelection ? self._selection[1] : self._cursorPos;\n\n            return self.render();\n        },\n\n        /**\n         * Removes focus from the CanvasInput box.\n         * @param  {Object} _this Reference to this.\n         * @return {CanvasInput}\n         */\n        blur(_this) {\n            const self = _this || this;\n\n            self._onblur(self);\n\n            if (self._cursorInterval) {\n                clearInterval(self._cursorInterval);\n            }\n            self._hasFocus = false;\n            self._cursor = false;\n            self._selection = [0, 0];\n            self._hiddenInput.blur();\n\n            // fill the place holder\n            if (self._value === '') {\n                self._value = self._placeHolder;\n            }\n\n            if (self._isHidden) {\n                return;\n            }\n            return self.render();\n        },\n\n        /**\n         * Fired with the keydown event to draw the typed characters.\n         * @param  {Event}       e    The keydown event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        keydown(e, self) {\n            const keyCode = e.which;\n            const isShift = e.shiftKey;\n            const key = null;\n            let startText;\n            let endText;\n\n            // make sure the correct text field is being updated\n            if (!self._hasFocus) {\n                return;\n            }\n\n            // fire custom user event\n            self._onkeydown(e, self);\n\n            // add support for Ctrl/Cmd+A selection\n            if (keyCode === 65 && (e.ctrlKey || e.metaKey)) {\n                self._selection = [0, self._value.length];\n                self._hiddenInput.selectionStart = 0;\n                self._hiddenInput.selectionEnd = self._value.length;\n                e.preventDefault();\n                return self.render();\n            }\n\n            // block keys that shouldn't be processed\n            if (keyCode === 17 || e.metaKey || e.ctrlKey) {\n                return self;\n            }\n\n            if (keyCode === 13) {\n                // enter key\n                e.preventDefault();\n                self._onsubmit(e, self);\n                //Entry.dispatchEvent('canvasInputComplete');\n            } else if (keyCode === 9) {\n                // tab key\n                e.preventDefault();\n                if (inputs.length > 1) {\n                    const next = inputs[self._inputsIndex + 1] ? self._inputsIndex + 1 : 0;\n                    self.blur();\n                    setTimeout(() => {\n                        inputs[next].focus();\n                    }, 5);\n                }\n            }\n\n            // update the canvas input state information from the hidden input\n            self._value = self._hiddenInput.value;\n            self._cursorPos = self._hiddenInput.selectionStart;\n            self._selection = [0, 0];\n\n            if (!self._isHidden) {\n                return self.render();\n            }\n        },\n\n        /**\n         * Fired with the click event on the canvas, and puts focus on/off\n         * based on where the user clicks.\n         * @param  {Event}       e    The click event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        click(e, self) {\n            //var mouse = self._mousePos(e),\n            //x = mouse.x,\n            //y = mouse.y;\n\n            if (this._isFirstClick) {\n                delete this._isFirstClick;\n                return;\n            }\n            const roundRect = Entry.stage.canvas.canvas.getBoundingClientRect();\n            const x = ((e.x - roundRect.left) / roundRect.width - 0.5) * 480;\n            const y = ((e.y - roundRect.top) / roundRect.height - 0.5) * -270;\n\n            if (self._endSelection) {\n                delete self._endSelection;\n                delete self._selectionUpdated;\n                return;\n            }\n\n            if ((self._canvas && self._overInput(x, y)) || !self._canvas) {\n                if (self._isHidden) {\n                    return;\n                }\n                if (self._mouseDown) {\n                    self._mouseDown = false;\n                    self.click(e, self);\n                    return self.focus(self._clickPos(x, y));\n                }\n            } else {\n                return self.blur();\n            }\n        },\n\n        /**\n         * Fired with the mousemove event to update the default cursor.\n         * @param  {Event}       e    The mousemove event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        mousemove(e, self) {\n            const mouse = self._mousePos(e);\n            const x = mouse.x;\n            const y = mouse.y;\n            const isOver = self._overInput(x, y);\n\n            if (isOver && self._canvas) {\n                self._canvas.style.cursor = 'text';\n                self._wasOver = true;\n            } else if (self._wasOver && self._canvas) {\n                self._canvas.style.cursor = 'default';\n                self._wasOver = false;\n            }\n\n            if (self._hasFocus && self._selectionStart >= 0) {\n                const curPos = self._clickPos(x, y);\n                const start = Math.min(self._selectionStart, curPos);\n                const end = Math.max(self._selectionStart, curPos);\n\n                if (!isOver) {\n                    self._selectionUpdated = true;\n                    self._endSelection = true;\n                    delete self._selectionStart;\n                    self.render();\n                    return;\n                }\n\n                if (self._selection[0] !== start || self._selection[1] !== end) {\n                    self._selection = [start, end];\n                    self.render();\n                }\n            }\n        },\n\n        /**\n         * Fired with the mousedown event to start a selection drag.\n         * @param  {Event} e    The mousedown event.\n         * @param  {CanvasInput} self\n         */\n        mousedown(e, self) {\n            e = Entry.Utils.convertMouseEvent(e);\n            const roundRect = Entry.stage.getBoundRect();\n            const scrollPos = Entry.Utils.getScrollPos();\n            const x = ((e.pageX - roundRect.left - scrollPos.left) / roundRect.width - 0.5) * 480;\n            const y = ((e.pageY - roundRect.top - scrollPos.top) / roundRect.height - 0.5) * -270;\n\n            const mouse = self._mousePos(e);\n            const isOver = self._overInput(x, y);\n\n            // setup the 'click' event\n            self._mouseDown = isOver;\n\n            const inputField = Entry.stage.inputField;\n            if (isOver && !inputField._isHidden) {\n                self._hasFocus = true;\n                inputField.focus();\n            } else if (!isOver && inputField) {\n                self._hasFocus = false;\n                inputField.blur();\n            }\n\n            // start the selection drag if inside the input\n            if (self._hasFocus && isOver) {\n                self._selectionStart = self._clickPos(x, y);\n            }\n        },\n\n        /**\n         * Fired with the mouseup event to end a selection drag.\n         * @param  {Event} e    The mouseup event.\n         * @param  {CanvasInput} self\n         */\n        mouseup(e, self) {\n            //var mouse = self._mousePos(e),\n            //x = mouse.x,\n            //y = mouse.y;\n            //// update selection if a drag has happened\n            //var isSelection = self._clickPos(x, y) !== self._selectionStart;\n            //if (self._hasFocus && self._selectionStart >= 0 && self._overInput(x, y) && isSelection) {\n            //self._selectionUpdated = true;\n            //delete self._selectionStart;\n            //self.render();\n            //} else {\n            //delete self._selectionStart;\n            //}\n            //self.click(e, self);\n            // if (self._isHidden)\n            //     return;\n            // self.render();\n            // self.click(e,self);\n            // var roundRect = Entry.stage.canvas.canvas.getBoundingClientRect();\n            // var x = ((e.clientX - roundRect.left) / roundRect.width - 0.5) * 480;\n            // var y = ((e.clientY - roundRect.top) / roundRect.height - 0.5) * -270;\n        },\n\n        /**\n         * Helper method to get the off-DOM canvas.\n         * @return {Object} Reference to the canvas.\n         */\n        renderCanvas() {\n            return this._renderCanvas;\n        },\n\n        show() {\n            const self = this;\n            self._isHidden = false;\n            self._isFirstClick = true;\n\n            self.value('');\n            self.focus();\n        },\n\n        hide() {\n            const self = this;\n\n            self._isHidden = true;\n            self.blur();\n        },\n\n        setPosition(x, y) {\n            const self = this;\n            self._isHidden = false;\n            self._isFirstClick = true;\n\n            self._x = x || 0;\n            self._y = y || 0;\n\n            self.value('');\n            self.focus();\n        },\n\n        /**\n         * Clears and redraws the CanvasInput on an off-DOM canvas,\n         * and if a main canvas is provided, draws it all onto that.\n         * @return {CanvasInput}\n         */\n        render() {\n            const self = this;\n            const ctx = self._renderCtx;\n            const w = self.outerW;\n            const h = self.outerH;\n            const br = self._borderRadius;\n            const bw = self._borderWidth;\n            const sw = self.shadowW;\n            const sh = self.shadowH;\n\n            // clear the canvas\n            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n\n            // setup the box shadow\n            ctx.shadowOffsetX = self._boxShadow.x;\n            ctx.shadowOffsetY = self._boxShadow.y;\n            ctx.shadowBlur = self._boxShadow.blur;\n            ctx.shadowColor = self._boxShadow.color;\n\n            // draw the border\n            if (self._borderWidth > 0) {\n                ctx.fillStyle = self._borderColor;\n                // self._roundedRect(ctx, self.shadowL, self.shadowT, w - sw, h - sh, br);\n                self._roundedRect(ctx, self.shadowL, self.shadowT, w - sw, h - sh, br);\n                ctx.fill();\n\n                ctx.shadowOffsetX = 0;\n                ctx.shadowOffsetY = 0;\n                ctx.shadowBlur = 0;\n            }\n\n            // draw the text box background\n            self._drawTextBox(() => {\n                // make sure all shadows are reset\n                ctx.shadowOffsetX = 0;\n                ctx.shadowOffsetY = 0;\n                ctx.shadowBlur = 0;\n\n                // clip the text so that it fits within the box\n                let text = self._clipText();\n\n                // draw the selection\n                const paddingBorder = self._padding + self._borderWidth + self.shadowT;\n                if (self._selection[1] > 0) {\n                    const selectOffset = self._textWidth(text.substring(0, self._selection[0]));\n                    const selectWidth = self._textWidth(\n                        text.substring(self._selection[0], self._selection[1])\n                    );\n\n                    ctx.fillStyle = self._selectionColor;\n                    ctx.fillRect(\n                        paddingBorder + selectOffset,\n                        paddingBorder,\n                        selectWidth,\n                        self._height\n                    );\n                }\n\n                // draw the cursor\n                if (self._cursor) {\n                    const cursorOffset = self._textWidth(text.substring(0, self._cursorPos));\n                    ctx.fillStyle = self._fontColor;\n                    ctx.fillRect(paddingBorder + cursorOffset, paddingBorder, 1, self._height);\n                }\n\n                // draw the text\n                const textX = self._padding + self._borderWidth + self.shadowL;\n                const textY = Math.round(paddingBorder + self._height / 2);\n\n                // only remove the placeholder text if they have typed something\n                text = text === '' && self._placeHolder ? self._placeHolder : text;\n\n                ctx.fillStyle =\n                    self._value !== '' && self._value !== self._placeHolder\n                        ? self._fontColor\n                        : self._placeHolderColor;\n                ctx.font = `${self._fontStyle} ${self._fontWeight} ${self._fontSize}px ${self._fontFamily}`;\n                ctx.textAlign = 'left';\n                ctx.textBaseline = 'middle';\n                ctx.fillText(text, textX, textY);\n\n                // parse inner shadow\n                const innerShadow = self._innerShadow.split('px ');\n                const isOffsetX = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[0], 10);\n                const isOffsetY = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[1], 10);\n                const isBlur = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[2], 10);\n                const isColor = self._innerShadow === 'none' ? '' : innerShadow[3];\n\n                // draw the inner-shadow (damn you canvas, this should be easier than this...)\n                if (isBlur > 0) {\n                    const shadowCtx = self._shadowCtx;\n                    const scw = shadowCtx.canvas.width;\n                    const sch = shadowCtx.canvas.height;\n\n                    shadowCtx.clearRect(0, 0, scw, sch);\n                    shadowCtx.shadowBlur = isBlur;\n                    shadowCtx.shadowColor = isColor;\n\n                    // top shadow\n                    shadowCtx.shadowOffsetX = 0;\n                    shadowCtx.shadowOffsetY = isOffsetY;\n                    shadowCtx.fillRect(-1 * w, -100, 3 * w, 100);\n\n                    // right shadow\n                    shadowCtx.shadowOffsetX = isOffsetX;\n                    shadowCtx.shadowOffsetY = 0;\n                    shadowCtx.fillRect(scw, -1 * h, 100, 3 * h);\n\n                    // bottom shadow\n                    shadowCtx.shadowOffsetX = 0;\n                    shadowCtx.shadowOffsetY = isOffsetY;\n                    shadowCtx.fillRect(-1 * w, sch, 3 * w, 100);\n\n                    // left shadow\n                    shadowCtx.shadowOffsetX = isOffsetX;\n                    shadowCtx.shadowOffsetY = 0;\n                    shadowCtx.fillRect(-100, -1 * h, 100, 3 * h);\n\n                    // create a clipping mask on the main canvas\n                    self._roundedRect(\n                        ctx,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        w - bw * 2 - sw,\n                        h - bw * 2 - sh,\n                        br\n                    );\n                    ctx.clip();\n\n                    // draw the inner-shadow from the off-DOM canvas\n                    ctx.drawImage(\n                        self._shadowCanvas,\n                        0,\n                        0,\n                        scw,\n                        sch,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        scw,\n                        sch\n                    );\n                }\n\n                // draw to the visible canvas\n                if (self._ctx) {\n                    // self._ctx.clearRect(self._x, self._y, ctx.canvas.width, ctx.canvas.height);\n                    self._ctx.drawImage(self._renderCanvas, self._x, self._y);\n                }\n\n                return self;\n            });\n        },\n\n        /**\n         * Draw the text box area with either an image or background color.\n         * @param  {Function} fn Callback.\n         */\n        _drawTextBox(fn) {\n            const self = this;\n            const ctx = self._renderCtx;\n            const w = self.outerW;\n            const h = self.outerH;\n            const br = self._borderRadius;\n            const bw = self._borderWidth;\n            const sw = self.shadowW;\n            const sh = self.shadowH;\n\n            // only draw the background shape if no image is being used\n            if (self._backgroundImage === '') {\n                ctx.fillStyle = self._backgroundColor;\n                self._roundedRect(\n                    ctx,\n                    bw + self.shadowL,\n                    bw + self.shadowT,\n                    w - bw * 2 - sw,\n                    h - bw * 2 - sh,\n                    br\n                );\n                ctx.fill();\n\n                fn();\n            } else {\n                const img = new Image();\n                img.src = self._backgroundImage;\n                img.onload = function() {\n                    ctx.drawImage(\n                        img,\n                        0,\n                        0,\n                        img.width,\n                        img.height,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        w,\n                        h\n                    );\n\n                    fn();\n                };\n            }\n        },\n\n        /**\n         * Deletes selected text in selection range and repositions cursor.\n         * @return {Boolean} true if text removed.\n         */\n        _clearSelection() {\n            const self = this;\n\n            if (self._selection[1] > 0) {\n                // clear the selected contents\n                const start = self._selection[0];\n                const end = self._selection[1];\n\n                self._value = self._value.substr(0, start) + self._value.substr(end);\n                self._cursorPos = start;\n                self._cursorPos = self._cursorPos < 0 ? 0 : self._cursorPos;\n                self._selection = [0, 0];\n\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * Clip the text string to only return what fits in the visible text box.\n         * @param  {String} value The text to clip.\n         * @return {String} The clipped text.\n         */\n        _clipText(value) {\n            const self = this;\n            value = typeof value === 'undefined' ? self._value : value;\n\n            const textWidth = self._textWidth(value);\n            const fillPer = textWidth / (self._width - self._padding);\n            const text =\n                fillPer > 1 ? value.substr(-1 * Math.floor(value.length / fillPer)) : value;\n\n            return `${text}`;\n        },\n\n        /**\n         * Gets the pixel with of passed text.\n         * @param  {String} text The text to measure.\n         * @return {Number}      The measured width.\n         */\n        _textWidth(text) {\n            const self = this;\n            const ctx = self._renderCtx;\n\n            ctx.font = `${self._fontStyle} ${self._fontWeight} ${self._fontSize}px ${self._fontFamily}`;\n            ctx.textAlign = 'left';\n\n            return ctx.measureText(text).width;\n        },\n\n        /**\n         * Recalculate the outer with and height of the text box.\n         */\n        _calcWH() {\n            const self = this;\n\n            // calculate the full width and height with padding, borders and shadows\n            self.outerW = self._width + self._padding * 2 + self._borderWidth * 2 + self.shadowW;\n            self.outerH = self._height + self._padding * 2 + self._borderWidth * 2 + self.shadowH;\n        },\n\n        /**\n         * Update the width and height of the off-DOM canvas when attributes are changed.\n         */\n        _updateCanvasWH() {\n            const self = this;\n            const oldW = self._renderCanvas.width;\n            const oldH = self._renderCanvas.height;\n\n            // update off-DOM canvas\n            self._renderCanvas.setAttribute('width', self.outerW);\n            self._renderCanvas.setAttribute('height', self.outerH);\n            self._shadowCanvas.setAttribute('width', self._width + self._padding * 2);\n            self._shadowCanvas.setAttribute('height', self._height + self._padding * 2);\n\n            // clear the main canvas\n            if (self._ctx) {\n                self._ctx.clearRect(self._x, self._y, oldW, oldH);\n            }\n        },\n\n        /**\n         * Creates the path for a rectangle with rounded corners.\n         * Must call ctx.fill() after calling this to draw the rectangle.\n         * @param  {Object} ctx Canvas context.\n         * @param  {Number} x   x-coordinate to draw from.\n         * @param  {Number} y   y-coordinate to draw from.\n         * @param  {Number} w   Width of rectangle.\n         * @param  {Number} h   Height of rectangle.\n         * @param  {Number} r   Border radius.\n         */\n        _roundedRect(ctx, x, y, w, h, r) {\n            if (w < 2 * r) {\n                r = w / 2;\n            }\n            if (h < 2 * r) {\n                r = h / 2;\n            }\n\n            ctx.beginPath();\n\n            ctx.moveTo(x + r, y);\n            ctx.lineTo(x + w - r, y);\n            ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n            ctx.lineTo(x + w, y + h - r);\n            ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n            ctx.lineTo(x + r, y + h);\n            ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n            ctx.lineTo(x, y + r);\n            ctx.quadraticCurveTo(x, y, x + r, y);\n\n            ctx.closePath();\n        },\n\n        /**\n         * Checks if a coordinate point is over the input box.\n         * @param  {Number} x x-coordinate position.\n         * @param  {Number} y y-coordinate position.\n         * @return {Boolean}   True if it is over the input box.\n         */\n        _overInput(x, y) {\n            const self = this;\n            return x >= -138 && x <= 148 && y >= -112 && y <= -91;\n        },\n\n        /**\n         * Use the mouse's x & y coordinates to determine\n         * the position clicked in the text.\n         * @param  {Number} x X-coordinate.\n         * @param  {Number} y Y-coordinate.\n         * @return {Number}   Cursor position.\n         */\n        _clickPos(x, y) {\n            const self = this;\n            let value = self._value;\n\n            // don't count placeholder text in this\n            if (self._value === self._placeHolder) {\n                value = '';\n            }\n\n            // determine where the click was made along the string\n            const text = self._clipText(value);\n            let totalW = 0;\n            let pos = text.length;\n\n            if (x - (self._x + self._extraX) < self._textWidth(text)) {\n                // loop through each character to identify the position\n                for (let i = 0; i < text.length; i++) {\n                    totalW += self._textWidth(text[i]);\n                    if (totalW >= x - (self._x + self._extraX)) {\n                        pos = i;\n                        break;\n                    }\n                }\n            }\n\n            return pos;\n        },\n\n        /**\n         * Calculate the mouse position based on the event callback and the elements on the page.\n         * @param  {Event} e\n         * @return {Object}   x & y values\n         */\n        _mousePos(e) {\n            let elm = e.target;\n            const style = document.defaultView.getComputedStyle(elm, undefined);\n            const paddingLeft = parseInt(style.paddingLeft, 10) || 0;\n            const paddingTop = parseInt(style.paddingLeft, 10) || 0;\n            const borderLeft = parseInt(style.borderLeftWidth, 10) || 0;\n            const borderTop = parseInt(style.borderLeftWidth, 10) || 0;\n            const htmlTop = document.body.parentNode.offsetTop || 0;\n            const htmlLeft = document.body.parentNode.offsetLeft || 0;\n            let offsetX = 0;\n            let offsetY = 0;\n            let x;\n            let y;\n\n            // calculate the total offset\n            if (typeof elm.offsetParent !== 'undefined') {\n                do {\n                    offsetX += elm.offsetLeft;\n                    offsetY += elm.offsetTop;\n                } while ((elm = elm.offsetParent));\n            }\n\n            // take into account borders and padding\n            offsetX += paddingLeft + borderLeft + htmlLeft;\n            offsetY += paddingTop + borderTop + htmlTop;\n\n            return {\n                x: e.pageX - offsetX,\n                y: e.pageY - offsetY,\n            };\n        },\n        hasFocus() {\n            return this._hasFocus;\n        },\n    };\n})();\n"
  },
  {
    "path": "extern/util/DragDropTouch.js",
    "content": "let DragDropTouch;\r\n(function(DragDropTouch_1) {\r\n    'use strict';\r\n    /**\r\n     * Object used to hold the data that is being dragged during drag and drop operations.\r\n     *\r\n     * It may hold one or more data items of different types. For more information about\r\n     * drag and drop operations and data transfer objects, see\r\n     * <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer\">HTML Drag and Drop API</a>.\r\n     *\r\n     * This object is created automatically by the @see:DragDropTouch singleton and is\r\n     * accessible through the @see:dataTransfer property of all drag events.\r\n     */\r\n    const DataTransfer = (function() {\r\n        function DataTransfer() {\r\n            this._dropEffect = 'move';\r\n            this._effectAllowed = 'all';\r\n            this._data = {};\r\n        }\r\n        Object.defineProperty(DataTransfer.prototype, 'dropEffect', {\r\n            /**\r\n             * Gets or sets the type of drag-and-drop operation currently selected.\r\n             * The value must be 'none',  'copy',  'link', or 'move'.\r\n             */\r\n            get() {\r\n                return this._dropEffect;\r\n            },\r\n            set(value) {\r\n                this._dropEffect = value;\r\n            },\r\n            enumerable: true,\r\n            configurable: true,\r\n        });\r\n        Object.defineProperty(DataTransfer.prototype, 'effectAllowed', {\r\n            /**\r\n             * Gets or sets the types of operations that are possible.\r\n             * Must be one of 'none', 'copy', 'copyLink', 'copyMove', 'link',\r\n             * 'linkMove', 'move', 'all' or 'uninitialized'.\r\n             */\r\n            get() {\r\n                return this._effectAllowed;\r\n            },\r\n            set(value) {\r\n                this._effectAllowed = value;\r\n            },\r\n            enumerable: true,\r\n            configurable: true,\r\n        });\r\n        Object.defineProperty(DataTransfer.prototype, 'types', {\r\n            /**\r\n             * Gets an array of strings giving the formats that were set in the @see:dragstart event.\r\n             */\r\n            get() {\r\n                return Object.keys(this._data);\r\n            },\r\n            enumerable: true,\r\n            configurable: true,\r\n        });\r\n        /**\r\n         * Removes the data associated with a given type.\r\n         *\r\n         * The type argument is optional. If the type is empty or not specified, the data\r\n         * associated with all types is removed. If data for the specified type does not exist,\r\n         * or the data transfer contains no data, this method will have no effect.\r\n         *\r\n         * @param type Type of data to remove.\r\n         */\r\n        DataTransfer.prototype.clearData = function(type) {\r\n            if (type != null) {\r\n                delete this._data[type];\r\n            } else {\r\n                this._data = null;\r\n            }\r\n        };\r\n        /**\r\n         * Retrieves the data for a given type, or an empty string if data for that type does\r\n         * not exist or the data transfer contains no data.\r\n         *\r\n         * @param type Type of data to retrieve.\r\n         */\r\n        DataTransfer.prototype.getData = function(type) {\r\n            return this._data[type] || '';\r\n        };\r\n        /**\r\n         * Set the data for a given type.\r\n         *\r\n         * For a list of recommended drag types, please see\r\n         * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Recommended_Drag_Types.\r\n         *\r\n         * @param type Type of data to add.\r\n         * @param value Data to add.\r\n         */\r\n        DataTransfer.prototype.setData = function(type, value) {\r\n            this._data[type] = value;\r\n        };\r\n        /**\r\n         * Set the image to be used for dragging if a custom one is desired.\r\n         *\r\n         * @param img An image element to use as the drag feedback image.\r\n         * @param offsetX The horizontal offset within the image.\r\n         * @param offsetY The vertical offset within the image.\r\n         */\r\n        DataTransfer.prototype.setDragImage = function(img, offsetX, offsetY) {\r\n            const ddt = DragDropTouch._instance;\r\n            ddt._imgCustom = img;\r\n            ddt._imgOffset = { x: offsetX, y: offsetY };\r\n        };\r\n        return DataTransfer;\r\n    })();\r\n    DragDropTouch_1.DataTransfer = DataTransfer;\r\n    /**\r\n     * Defines a class that adds support for touch-based HTML5 drag/drop operations.\r\n     *\r\n     * The @see:DragDropTouch class listens to touch events and raises the\r\n     * appropriate HTML5 drag/drop events as if the events had been caused\r\n     * by mouse actions.\r\n     *\r\n     * The purpose of this class is to enable using existing, standard HTML5\r\n     * drag/drop code on mobile devices running IOS or Android.\r\n     *\r\n     * To use, include the DragDropTouch.js file on the page. The class will\r\n     * automatically start monitoring touch events and will raise the HTML5\r\n     * drag drop events (dragstart, dragenter, dragleave, drop, dragend) which\r\n     * should be handled by the application.\r\n     *\r\n     * For details and examples on HTML drag and drop, see\r\n     * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations.\r\n     */\r\n    var DragDropTouch = (function() {\r\n        /**\r\n         * Initializes the single instance of the @see:DragDropTouch class.\r\n         */\r\n        function DragDropTouch() {\r\n            this._lastClick = 0;\r\n            // enforce singleton pattern\r\n            if (DragDropTouch._instance) {\r\n                throw 'DragDropTouch instance already created.';\r\n            }\r\n            // detect passive event support\r\n            // https://github.com/Modernizr/Modernizr/issues/1894\r\n            let supportsPassive = false;\r\n            document.addEventListener('test', () => {}, {\r\n                get passive() {\r\n                    supportsPassive = true;\r\n                    return true;\r\n                },\r\n            });\r\n            // listen to touch events\r\n            if ('ontouchstart' in document) {\r\n                let d = document,\r\n                    ts = this._touchstart.bind(this),\r\n                    tm = this._touchmove.bind(this),\r\n                    te = this._touchend.bind(this),\r\n                    opt = supportsPassive ? { passive: false, capture: false } : false;\r\n                d.addEventListener('touchstart', ts, opt);\r\n                d.addEventListener('touchmove', tm, opt);\r\n                d.addEventListener('touchend', te);\r\n                d.addEventListener('touchcancel', te);\r\n            }\r\n        }\r\n        /**\r\n         * Gets a reference to the @see:DragDropTouch singleton.\r\n         */\r\n        DragDropTouch.getInstance = function() {\r\n            return DragDropTouch._instance;\r\n        };\r\n        // ** event handlers\r\n        DragDropTouch.prototype._touchstart = function(e) {\r\n            const _this = this;\r\n            if (this._shouldHandle(e)) {\r\n                // raise double-click and prevent zooming\r\n                if (Date.now() - this._lastClick < DragDropTouch._DBLCLICK) {\r\n                    if (this._dispatchEvent(e, 'dblclick', e.target)) {\r\n                        e.preventDefault();\r\n                        this._reset();\r\n                        return;\r\n                    }\r\n                }\r\n                // clear all variables\r\n                this._reset();\r\n                // get nearest draggable element\r\n                const src = this._closestDraggable(e.target);\r\n                if (src) {\r\n                    // give caller a chance to handle the hover/move events\r\n                    if (\r\n                        !this._dispatchEvent(e, 'mousemove', e.target) &&\r\n                        !this._dispatchEvent(e, 'mousedown', e.target)\r\n                    ) {\r\n                        // get ready to start dragging\r\n                        this._dragSource = src;\r\n                        this._ptDown = this._getPoint(e);\r\n                        this._lastTouch = e;\r\n                        e.preventDefault();\r\n                        // show context menu if the user hasn't started dragging after a while\r\n                        setTimeout(() => {\r\n                            if (_this._dragSource == src && _this._img == null) {\r\n                                if (_this._dispatchEvent(e, 'contextmenu', src)) {\r\n                                    _this._reset();\r\n                                }\r\n                            }\r\n                        }, DragDropTouch._CTXMENU);\r\n                        if (DragDropTouch._ISPRESSHOLDMODE) {\r\n                            this._pressHoldInterval = setTimeout(() => {\r\n                                _this._isDragEnabled = true;\r\n                                _this._touchmove(e);\r\n                            }, DragDropTouch._PRESSHOLDAWAIT);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n        };\r\n        DragDropTouch.prototype._touchmove = function(e) {\r\n            if (this._shouldCancelPressHoldMove(e)) {\r\n                this._reset();\r\n                return;\r\n            }\r\n            if (this._shouldHandleMove(e) || this._shouldHandlePressHoldMove(e)) {\r\n                // see if target wants to handle move\r\n                const target = this._getTarget(e);\r\n                if (this._dispatchEvent(e, 'mousemove', target)) {\r\n                    this._lastTouch = e;\r\n                    e.preventDefault();\r\n                    return;\r\n                }\r\n                // start dragging\r\n                if (this._dragSource && !this._img && this._shouldStartDragging(e)) {\r\n                    this._dispatchEvent(e, 'dragstart', this._dragSource);\r\n                    this._createImage(e);\r\n                    this._dispatchEvent(e, 'dragenter', target);\r\n                }\r\n                // continue dragging\r\n                if (this._img) {\r\n                    this._lastTouch = e;\r\n                    e.preventDefault(); // prevent scrolling\r\n                    if (target != this._lastTarget) {\r\n                        this._dispatchEvent(this._lastTouch, 'dragleave', this._lastTarget);\r\n                        this._dispatchEvent(e, 'dragenter', target);\r\n                        this._lastTarget = target;\r\n                    }\r\n                    this._moveImage(e);\r\n                    this._dispatchEvent(e, 'dragover', target);\r\n                }\r\n            }\r\n        };\r\n        DragDropTouch.prototype._touchend = function(e) {\r\n            if (this._shouldHandle(e)) {\r\n                // see if target wants to handle up\r\n                if (this._dispatchEvent(this._lastTouch, 'mouseup', e.target)) {\r\n                    e.preventDefault();\r\n                    return;\r\n                }\r\n                // user clicked the element but didn't drag, so clear the source and simulate a click\r\n                if (!this._img) {\r\n                    this._dragSource = null;\r\n                    this._dispatchEvent(this._lastTouch, 'click', e.target);\r\n                    this._lastClick = Date.now();\r\n                }\r\n                // finish dragging\r\n                this._destroyImage();\r\n                if (this._dragSource) {\r\n                    if (e.type.indexOf('cancel') < 0) {\r\n                        this._dispatchEvent(this._lastTouch, 'drop', this._lastTarget);\r\n                    }\r\n                    this._dispatchEvent(this._lastTouch, 'dragend', this._dragSource);\r\n                    this._reset();\r\n                }\r\n            }\r\n        };\r\n        // ** utilities\r\n        // ignore events that have been handled or that involve more than one touch\r\n        DragDropTouch.prototype._shouldHandle = function(e) {\r\n            return e && !e.defaultPrevented && e.touches && e.touches.length < 2;\r\n        };\r\n\r\n        // use regular condition outside of press & hold mode\r\n        DragDropTouch.prototype._shouldHandleMove = function(e) {\r\n            return !DragDropTouch._ISPRESSHOLDMODE && this._shouldHandle(e);\r\n        };\r\n\r\n        // allow to handle moves that involve many touches for press & hold\r\n        DragDropTouch.prototype._shouldHandlePressHoldMove = function(e) {\r\n            return (\r\n                DragDropTouch._ISPRESSHOLDMODE &&\r\n                this._isDragEnabled &&\r\n                e &&\r\n                e.touches &&\r\n                e.touches.length\r\n            );\r\n        };\r\n\r\n        // reset data if user drags without pressing & holding\r\n        DragDropTouch.prototype._shouldCancelPressHoldMove = function(e) {\r\n            return (\r\n                DragDropTouch._ISPRESSHOLDMODE &&\r\n                !this._isDragEnabled &&\r\n                this._getDelta(e) > DragDropTouch._PRESSHOLDMARGIN\r\n            );\r\n        };\r\n\r\n        // start dragging when specified delta is detected\r\n        DragDropTouch.prototype._shouldStartDragging = function(e) {\r\n            const delta = this._getDelta(e);\r\n            return (\r\n                delta > DragDropTouch._THRESHOLD ||\r\n                (DragDropTouch._ISPRESSHOLDMODE && delta >= DragDropTouch._PRESSHOLDTHRESHOLD)\r\n            );\r\n        };\r\n\r\n        // clear all members\r\n        DragDropTouch.prototype._reset = function() {\r\n            this._destroyImage();\r\n            this._dragSource = null;\r\n            this._lastTouch = null;\r\n            this._lastTarget = null;\r\n            this._ptDown = null;\r\n            this._dataTransfer = new DataTransfer();\r\n            this._isDragEnabled = false;\r\n            clearInterval(this._pressHoldInterval);\r\n        };\r\n        // get point for a touch event\r\n        DragDropTouch.prototype._getPoint = function(e, page) {\r\n            if (e && e.touches) {\r\n                e = e.touches[0];\r\n            }\r\n            return { x: page ? e.pageX : e.clientX, y: page ? e.pageY : e.clientY };\r\n        };\r\n        // get distance between the current touch event and the first one\r\n        DragDropTouch.prototype._getDelta = function(e) {\r\n            if (DragDropTouch._ISPRESSHOLDMODE && !this._ptDown) {\r\n                return 0;\r\n}\r\n            const p = this._getPoint(e);\r\n            return Math.abs(p.x - this._ptDown.x) + Math.abs(p.y - this._ptDown.y);\r\n        };\r\n        // get the element at a given touch event\r\n        DragDropTouch.prototype._getTarget = function(e) {\r\n            let pt = this._getPoint(e),\r\n                el = document.elementFromPoint(pt.x, pt.y);\r\n            while (el && getComputedStyle(el).pointerEvents == 'none') {\r\n                el = el.parentElement;\r\n            }\r\n            return el;\r\n        };\r\n        // create drag image from source element\r\n        DragDropTouch.prototype._createImage = function(e) {\r\n            // just in case...\r\n            if (this._img) {\r\n                this._destroyImage();\r\n            }\r\n            // create drag image from custom element or drag source\r\n            const src = this._imgCustom || this._dragSource;\r\n            this._img = src.cloneNode(true);\r\n            this._copyStyle(src, this._img);\r\n            this._img.style.top = this._img.style.left = '-9999px';\r\n            // if creating from drag source, apply offset and opacity\r\n            if (!this._imgCustom) {\r\n                let rc = src.getBoundingClientRect(),\r\n                    pt = this._getPoint(e);\r\n                this._imgOffset = { x: pt.x - rc.left, y: pt.y - rc.top };\r\n                this._img.style.opacity = DragDropTouch._OPACITY.toString();\r\n            }\r\n            // add image to document\r\n            this._moveImage(e);\r\n            document.body.appendChild(this._img);\r\n        };\r\n        // dispose of drag image element\r\n        DragDropTouch.prototype._destroyImage = function() {\r\n            if (this._img && this._img.parentElement) {\r\n                this._img.parentElement.removeChild(this._img);\r\n            }\r\n            this._img = null;\r\n            this._imgCustom = null;\r\n        };\r\n        // move the drag image element\r\n        DragDropTouch.prototype._moveImage = function(e) {\r\n            const _this = this;\r\n            requestAnimationFrame(() => {\r\n                if (_this._img) {\r\n                    let pt = _this._getPoint(e, true),\r\n                        s = _this._img.style;\r\n                    s.position = 'absolute';\r\n                    s.pointerEvents = 'none';\r\n                    s.zIndex = '999999';\r\n                    s.left = `${Math.round(pt.x - _this._imgOffset.x)  }px`;\r\n                    s.top = `${Math.round(pt.y - _this._imgOffset.y)  }px`;\r\n                }\r\n            });\r\n        };\r\n        // copy properties from an object to another\r\n        DragDropTouch.prototype._copyProps = function(dst, src, props) {\r\n            for (let i = 0; i < props.length; i++) {\r\n                const p = props[i];\r\n                dst[p] = src[p];\r\n            }\r\n        };\r\n        DragDropTouch.prototype._copyStyle = function(src, dst) {\r\n            // remove potentially troublesome attributes\r\n            DragDropTouch._rmvAtts.forEach((att) => {\r\n                dst.removeAttribute(att);\r\n            });\r\n            // copy canvas content\r\n            if (src instanceof HTMLCanvasElement) {\r\n                let cSrc = src,\r\n                    cDst = dst;\r\n                cDst.width = cSrc.width;\r\n                cDst.height = cSrc.height;\r\n                cDst.getContext('2d').drawImage(cSrc, 0, 0);\r\n            }\r\n            // copy style (without transitions)\r\n            const cs = getComputedStyle(src);\r\n            for (var i = 0; i < cs.length; i++) {\r\n                const key = cs[i];\r\n                if (key.indexOf('transition') < 0) {\r\n                    dst.style[key] = cs[key];\r\n                }\r\n            }\r\n            dst.style.pointerEvents = 'none';\r\n            // and repeat for all children\r\n            for (var i = 0; i < src.children.length; i++) {\r\n                this._copyStyle(src.children[i], dst.children[i]);\r\n            }\r\n        };\r\n        DragDropTouch.prototype._dispatchEvent = function(e, type, target) {\r\n            if (e && target) {\r\n                let evt = document.createEvent('Event'),\r\n                    t = e.touches ? e.touches[0] : e;\r\n                evt.initEvent(type, true, true);\r\n                evt.button = 0;\r\n                evt.which = evt.buttons = 1;\r\n                this._copyProps(evt, e, DragDropTouch._kbdProps);\r\n                this._copyProps(evt, t, DragDropTouch._ptProps);\r\n                evt.dataTransfer = this._dataTransfer;\r\n                target.dispatchEvent(evt);\r\n                return evt.defaultPrevented;\r\n            }\r\n            return false;\r\n        };\r\n        // gets an element's closest draggable ancestor\r\n        DragDropTouch.prototype._closestDraggable = function(e) {\r\n            for (; e; e = e.parentElement) {\r\n                if (e.hasAttribute('draggable') && e.draggable) {\r\n                    return e;\r\n                }\r\n            }\r\n            return null;\r\n        };\r\n        return DragDropTouch;\r\n    })();\r\n    /*private*/ DragDropTouch._instance = new DragDropTouch(); // singleton\r\n    // constants\r\n    DragDropTouch._THRESHOLD = 5; // pixels to move before drag starts\r\n    DragDropTouch._OPACITY = 0.5; // drag image opacity\r\n    DragDropTouch._DBLCLICK = 500; // max ms between clicks in a double click\r\n    DragDropTouch._CTXMENU = 900; // ms to hold before raising 'contextmenu' event\r\n    DragDropTouch._ISPRESSHOLDMODE = false; // decides of press & hold mode presence\r\n    DragDropTouch._PRESSHOLDAWAIT = 400; // ms to wait before press & hold is detected\r\n    DragDropTouch._PRESSHOLDMARGIN = 25; // pixels that finger might shiver while pressing\r\n    DragDropTouch._PRESSHOLDTHRESHOLD = 0; // pixels to move before drag starts\r\n    // copy styles/attributes from drag source to drag image element\r\n    DragDropTouch._rmvAtts = 'id,class,style,draggable'.split(',');\r\n    // synthesize and dispatch an event\r\n    // returns true if the event has been handled (e.preventDefault == true)\r\n    DragDropTouch._kbdProps = 'altKey,ctrlKey,metaKey,shiftKey'.split(',');\r\n    DragDropTouch._ptProps = 'pageX,pageY,clientX,clientY,screenX,screenY'.split(',');\r\n    DragDropTouch_1.DragDropTouch = DragDropTouch;\r\n})(DragDropTouch || (DragDropTouch = {}));\r\n"
  },
  {
    "path": "extern/util/filbert.js",
    "content": "// Filbert is a Python parser written in JavaScript.\n//\n// Filbert was written by Matt Lott and released under an MIT\n// license. It was adatped from [Acorn](https://github.com/marijnh/acorn.git)\n// by Marijn Haverbeke.\n//\n// Git repository for Filbert are available at\n//\n//     https://github.com/differentmatt/filbert.git\n//\n// Please use the [github bug tracker][ghbt] to report issues.\n//\n// [ghbt]: https://github.com/differentmatt/filbert/issues\n\n(function(root, mod) {\n    if (typeof exports == 'object' && typeof module == 'object') return mod(exports); // CommonJS\n    if (typeof define == 'function' && define.amd) return define(['exports'], mod); // AMD\n    mod(root.filbert || (root.filbert = {})); // Plain browser env\n})(this, function(exports) {\n    'use strict';\n\n    exports.version = '0.5.1';\n\n    // The main exported interface (under `self.filbert` when in the\n    // browser) is a `parse` function that takes a code string and\n    // returns an abstract syntax tree as specified by [Mozilla parser\n    // API][api].\n    //\n    // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API\n\n    var options, input, inputLen, sourceFile, nc;\n\n    exports.parse = function(inpt, opts) {\n        input = String(inpt);\n        inputLen = input.length;\n        setOptions(opts);\n        initTokenState();\n        nc = getNodeCreator(startNode, startNodeFrom, finishNode, unpackTuple);\n        return parseTopLevel(options.program);\n    };\n\n    // A second optional argument can be given to further configure\n    // the parser process. These options are recognized:\n\n    var defaultOptions = exports.defaultOptions = {\n        // `languageVersion` indicates the Python version to parse. It\n        // is not currently in use, but will support 2 or 3 eventually.\n        languageVersion: 3,\n        // When `allowTrailingCommas` is false, the parser will not allow\n        // trailing commas in array and object literals.\n        allowTrailingCommas: true,\n        // When enabled, a return at the top level is not considered an\n        // error.\n        allowReturnOutsideFunction: true,\n        // When `locations` is on, `loc` properties holding objects with\n        // `start` and `end` properties in `{line, column}` form (with\n        // line being 1-based and column 0-based) will be attached to the\n        // nodes.\n        locations: true,\n        // A function can be passed as `onComment` option, which will\n        // cause Filbert to call that function with `(text, start,\n        // end)` parameters whenever a comment is skipped.\n        // `text` is the content of the comment, and `start` and `end` are\n        // character offsets that denote the start and end of the comment.\n        // When the `locations` option is on, two more parameters are\n        // passed, the full `{line, column}` locations of the start and\n        // end of the comments. Note that you are not allowed to call the\n        // parser from the callback-that will corrupt its internal state.\n        onComment: null,\n        // [semi-standardized][range] `range` property holding a `[start,\n        // end]` array with the same numbers, set the `ranges` option to\n        // `true`.\n        //\n        // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678\n        ranges: false,\n        // It is possible to parse multiple files into a single AST by\n        // passing the tree produced by parsing the first file as\n        // `program` option in subsequent parses. This will add the\n        // toplevel forms of the parsed file to the `Program` (top) node\n        // of an existing parse tree.\n        program: null,\n        // When `locations` is on, you can pass this to record the source\n        // file in every node's `loc` object.\n        sourceFile: null,\n        // This value, if given, is stored in every node, whether\n        // `locations` is on or off.\n        directSourceFile: null,\n        // Python runtime library object name\n        runtimeParamName: '__pythonRuntime',\n    };\n\n    function setOptions(opts) {\n        options = opts || {};\n        for (var opt in defaultOptions) if (!Object.prototype.hasOwnProperty.call(options, opt))\n            options[opt] = defaultOptions[opt];\n        sourceFile = options.sourceFile || null;\n    }\n\n    // The `getLineInfo` function is mostly useful when the\n    // `locations` option is off (for performance reasons) and you\n    // want to find the line/column position for a given character\n    // offset. `input` should be the code string that the offset refers\n    // into.\n\n    var getLineInfo = exports.getLineInfo = function(input, offset) {\n        for (var line = 1, cur = 0; ;) {\n            lineBreak.lastIndex = cur;\n            var match = lineBreak.exec(input);\n            if (match && match.index < offset) {\n                ++line;\n                cur = match.index + match[0].length;\n            } else break;\n        }\n        return { line: line, column: offset - cur };\n    };\n\n    // Filbert is organized as a tokenizer and a recursive-descent parser.\n    // The `tokenize` export provides an interface to the tokenizer.\n    // Because the tokenizer is optimized for being efficiently used by\n    // the Filbert parser itself, this interface is somewhat crude and not\n    // very modular. Performing another parse or call to `tokenize` will\n    // reset the internal state, and invalidate existing tokenizers.\n\n    exports.tokenize = function(inpt, opts) {\n        input = String(inpt);\n        inputLen = input.length;\n        setOptions(opts);\n        initTokenState();\n\n        var t = {};\n\n        function getToken(forceRegexp) {\n            lastEnd = tokEnd;\n            readToken(forceRegexp);\n            t.start = tokStart;\n            t.end = tokEnd;\n            t.startLoc = tokStartLoc;\n            t.endLoc = tokEndLoc;\n            t.type = tokType;\n            t.value = tokVal;\n            return t;\n        }\n\n        getToken.jumpTo = function(pos, reAllowed) {\n            tokPos = pos;\n            if (options.locations) {\n                tokCurLine = 1;\n                tokLineStart = lineBreak.lastIndex = 0;\n                var match;\n                while ((match = lineBreak.exec(input)) && match.index < pos) {\n                    ++tokCurLine;\n                    tokLineStart = match.index + match[0].length;\n                }\n            }\n            tokRegexpAllowed = reAllowed;\n            skipSpace();\n        };\n        return getToken;\n    };\n\n    // State is kept in (closure-)global variables. We already saw the\n    // `options`, `input`, and `inputLen` variables above.\n\n    // The current position of the tokenizer in the input.\n\n    var tokPos;\n\n    // The start and end offsets of the current token.\n\n    var tokStart, tokEnd;\n\n    // When `options.locations` is true, these hold objects\n    // containing the tokens start and end line/column pairs.\n\n    var tokStartLoc, tokEndLoc;\n\n    // The type and value of the current token. Token types are objects,\n    // named by variables against which they can be compared, and\n    // holding properties that describe them (indicating, for example,\n    // the precedence of an infix operator, and the original name of a\n    // keyword token). The kind of value that's held in `tokVal` depends\n    // on the type of the token. For literals, it is the literal value,\n    // for operators, the operator name, and so on.\n\n    var tokType, tokVal;\n\n    // Interal state for the tokenizer. To distinguish between division\n    // operators and regular expressions, it remembers whether the last\n    // token was one that is allowed to be followed by an expression.\n    // (If it is, a slash is probably a regexp, if it isn't it's a\n    // division operator. See the `parseStatement` function for a\n    // caveat.)\n\n    var tokRegexpAllowed;\n\n    // When `options.locations` is true, these are used to keep\n    // track of the current line, and know when a new line has been\n    // entered.\n\n    var tokCurLine, tokLineStart;\n\n    // These store the position of the previous token, which is useful\n    // when finishing a node and assigning its `end` position.\n\n    var lastStart, lastEnd, lastEndLoc;\n\n    // This is the parser's state. `inFunction` is used to reject\n    // `return` statements outside of functions, `strict` indicates\n    // whether strict mode is on, and `bracketNesting` tracks the level\n    // of nesting within brackets for implicit lint continuation.\n\n    var inFunction, strict, bracketNesting;\n\n    // This function is used to raise exceptions on parse errors. It\n    // takes an offset integer (into the current `input`) to indicate\n    // the location of the error, attaches the position to the end\n    // of the error message, and then raises a `SyntaxError` with that\n    // message.\n\n    function raise(pos, message, readType, expectedType) {\n        var loc = getLineInfo(input, pos);\n        var err = new SyntaxError(message);\n        err.pos = pos;\n        err.loc = loc;\n        err.raisedAt = tokPos;\n        err.tokLen = tokEnd - tokStart + 1;\n        err.tokType = readType;\n        err.expectedType = expectedType;\n        throw err;\n    }\n\n    // Reused empty array added for node fields that are always empty.\n\n    var empty = [];\n\n    // Used for name collision avoidance whend adding extra AST identifiers\n\n    var newAstIdCount = 0;\n\n    var indentHist = exports.indentHist = {\n        // Current indentation stack\n        indent: [],\n\n        // Number of dedent tokens left (i.e. if tokType == _dedent, dedentCount > 0)\n        // Multiple dedent tokens are read in at once, but processed individually in readToken()\n        dedentCount: 0,\n\n        init: function() {\n            this.indent = [];\n            this.dedentCount = 0;\n        },\n        count: function() {\n            return this.indent.length;\n        },\n        len: function(i) {\n            if (typeof i === 'undefined' || i >= this.indent.length) i = this.indent.length - 1;\n            return this.indent[i].length;\n        },\n        isIndent: function(s) {\n            return this.indent.length === 0 || s.length > this.len();\n        },\n        isDedent: function(s) {\n            return this.indent.length > 0 && s.length < this.len();\n        },\n        addIndent: function(s) {\n            this.indent.push(s);\n        },\n        addDedent: function(s) {\n            this.dedentCount = 0;\n            for (var i = this.indent.length - 1; i >= 0 && s.length < this.indent[i].length; --i)\n                ++this.dedentCount;\n        },\n        updateDedent: function() {\n            this.dedentCount = this.count();\n        },\n        pop: function() {\n            --this.dedentCount;\n            this.indent.pop();\n        },\n        undoIndent: function() {\n            this.pop();\n        },\n    };\n\n    // ## Scope\n\n    // Collection of namespaces saved as a stack\n    // A namespace is a mapping of identifiers to 3 types: variables, functions, classes\n    // A namespace also knows whether it is for global, class, or function\n    // A new namespace is pushed at function and class start, and popped at their end\n    // Starts with a global namespace on the stack\n    // E.g. scope.namespaces ~ [{type: 'g', map:{x: 'v', MyClass: 'c'} }, ...]\n\n    // TODO: Not tracking built-in namespace\n\n    var scope = exports.scope = {\n        namespaces: [],\n        init: function() {\n            this.namespaces = [{ type: 'g', map: {} }];\n        },\n        current: function(offset) {\n            offset = offset || 0;\n            return this.namespaces[this.namespaces.length - offset - 1];\n        },\n        startClass: function(id) {\n            this.current().map[id] = 'c';\n            this.namespaces.push({ type: 'c', map: {}, className: id });\n        },\n        startFn: function(id) {\n            this.current().map[id] = 'f';\n            this.namespaces.push({ type: 'f', map: {}, fnName: id });\n        },\n        end: function() {\n            this.namespaces.pop();\n        },\n        addVar: function(id) {\n            this.current().map[id] = 'v';\n        },\n        exists: function(id) {\n            return this.current().map.hasOwnProperty(id);\n        },\n        isClass: function() {\n            return this.current().type === 'c';\n        },\n        isUserFunction: function(name) {\n            // Loose match (i.e. order ignored)\n            // TODO: does not identify user-defined class methods\n            for (var i = this.namespaces.length - 1; i >= 0; i--)\n                for (var key in this.namespaces[i].map)\n                    if (key === name && this.namespaces[i].map[key] === 'f')\n                        return true;\n            return false;\n        },\n        isParentClass: function() {\n            return this.current(1).type === 'c';\n        },\n        isNewObj: function(id) {\n            for (var i = this.namespaces.length - 1; i >= 0; i--)\n                if (this.namespaces[i].map[id] === 'c') return true;\n                else if (this.namespaces[i].map[id] === 'f') break;\n            return false;\n        },\n        getParentClassName: function() {\n            return this.current(1).className;\n        },\n        getThisReplace: function() {\n            return this.current().thisReplace;\n        },\n        setThisReplace: function(s) {\n            this.current().thisReplace = s;\n        },\n    };\n\n\n    // ## Token types\n\n    // The assignment of fine-grained, information-carrying type objects\n    // allows the tokenizer to store the information it has about a\n    // token in a way that is very cheap for the parser to look up.\n\n    // All token type variables start with an underscore, to make them\n    // easy to recognize.\n\n    // These are the general types. The `type` property is only used to\n    // make them recognizeable when debugging.\n\n    var _num = { type: 'num' }, _regexp = { type: 'regexp' }, _string = { type: 'string' };\n    var _name = { type: 'name' }, _eof = { type: 'eof' };\n    var _newline = { type: 'newline' }, _indent = { type: 'indent' }, _dedent = { type: 'dedent' };\n\n    // Keyword tokens. The `keyword` property (also used in keyword-like\n    // operators) indicates that the token originated from an\n    // identifier-like word, which is used when parsing property names.\n    //\n    // The `beforeExpr` property is used to disambiguate between regular\n    // expressions and divisions. It is set on all token types that can\n    // be followed by an expression (thus, a slash after them would be a\n    // regular expression).\n\n    var _dict = { keyword: 'dict' };  // TODO: not a keyword\n    var _as = { keyword: 'as' }, _assert = { keyword: 'assert' }, _break = { keyword: 'break' };\n    var _class = { keyword: 'class' }, _continue = { keyword: 'continue' };\n    var _def = { keyword: 'def' }, _del = { keyword: 'del' };\n    var _elif = { keyword: 'elif', beforeExpr: true }, _else = { keyword: 'else', beforeExpr: true };\n    var _except = { keyword: 'except', beforeExpr: true }, _finally = { keyword: 'finally' };\n    var _for = { keyword: 'for' }, _from = { keyword: 'from' }, _global = { keyword: 'global' };\n    var _if = { keyword: 'if' }, _import = { keyword: 'import' };\n    var _lambda = { keyword: 'lambda' }, _nonlocal = { keyword: 'nonlocal' };\n    var _pass = { keyword: 'pass' }, _raise = { keyword: 'raise' };\n    var _return = { keyword: 'return', beforeExpr: true }, _try = { keyword: 'try' };\n    var _while = { keyword: 'while' }, _with = { keyword: 'with' }, _yield = { keyword: 'yield' };\n\n    // The keywords that denote values.\n\n    var _none = { keyword: 'None', atomValue: null }, _true = { keyword: 'True', atomValue: true };\n    var _false = { keyword: 'False', atomValue: false };\n\n    // Some keywords are treated as regular operators. `in` sometimes\n    // (when parsing `for`) needs to be tested against specifically, so\n    // we assign a variable name to it for quick comparing.\n    // 'prec' is the operator precedence'\n\n    var _or = { keyword: 'or', prec: 1, beforeExpr: true, rep: '||' };\n    var _and = { keyword: 'and', prec: 2, beforeExpr: true, rep: '&&' };\n    var _not = { keyword: 'not', prec: 3, prefix: true, beforeExpr: true, rep: '!' };\n    var _in = { keyword: 'in', prec: 4, beforeExpr: true };\n    var _is = { keyword: 'is', prec: 4, beforeExpr: true };\n\n    // Map keyword names to token types.\n\n    var keywordTypes = {\n        'dict': _dict,\n        'False': _false, 'None': _none, 'True': _true, 'and': _and, 'as': _as,\n        'break': _break, 'class': _class, 'continue': _continue, 'def': _def, 'del': _del,\n        'elif': _elif, 'else': _else, 'except': _except, 'finally': _finally, 'for': _for,\n        'from': _from, 'global': _global, 'if': _if, 'import': _import, 'in': _in, 'is': _is,\n        'lambda': _lambda, 'nonlocal': _nonlocal, 'not': _not, 'or': _or,\n        'pass': _pass, 'raise': _raise, 'return': _return, 'try': _try, 'while': _while,\n        'with': _with, 'yield': _yield,\n    };\n\n    // Punctuation token types. Again, the `type` property is purely for debugging.\n\n    var _bracketL = { type: '[', beforeExpr: true }, _bracketR = { type: ']' },\n        _braceL = { type: '{', beforeExpr: true };\n    var _braceR = { type: '}' }, _parenL = { type: '(', beforeExpr: true }, _parenR = { type: ')' };\n    var _comma = { type: ',', beforeExpr: true }, _semi = { type: ';', beforeExpr: true };\n    var _colon = { type: ':', beforeExpr: true }, _dot = { type: '.' }, _question = { type: '?', beforeExpr: true };\n    const _comment = { type: '#' };\n\n    // Operators. These carry several kinds of properties to help the\n    // parser use them properly (the presence of these properties is\n    // what categorizes them as operators).\n    //\n    // `prec` specifies the precedence of this operator.\n    //\n    // `prefix` marks the operator as a prefix unary operator.\n    //\n    // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as\n    // binary operators with a very low precedence, that should result\n    // in AssignmentExpression nodes.\n\n    var _slash = { prec: 10, beforeExpr: true }, _eq = { isAssign: true, beforeExpr: true };\n    var _assign = { isAssign: true, beforeExpr: true };\n    var _equality = { prec: 4, beforeExpr: true };\n    var _relational = { prec: 4, beforeExpr: true };\n    var _bitwiseOR = { prec: 5, beforeExpr: true };\n    var _bitwiseXOR = { prec: 6, beforeExpr: true };\n    var _bitwiseAND = { prec: 7, beforeExpr: true };\n    var _bitShift = { prec: 8, beforeExpr: true };\n    var _plusMin = { prec: 9, beforeExpr: true };\n    var _multiplyModulo = { prec: 10, beforeExpr: true };\n    var _floorDiv = { prec: 10, beforeExpr: true };\n    var _posNegNot = { prec: 11, prefix: true, beforeExpr: true };\n    var _bitwiseNOT = { prec: 11, prefix: true, beforeExpr: true };\n    var _exponentiation = { prec: 12, beforeExpr: true };\n\n    // Provide access to the token types for external users of the\n    // tokenizer.\n\n    exports.tokTypes = {\n        bracketL: _bracketL, bracketR: _bracketR, braceL: _braceL, braceR: _braceR,\n        parenL: _parenL, parenR: _parenR, comma: _comma, semi: _semi, colon: _colon,\n        dot: _dot, question: _question, slash: _slash, eq: _eq, name: _name, eof: _eof,\n        num: _num, regexp: _regexp, string: _string,\n        newline: _newline, indent: _indent, dedent: _dedent,\n        exponentiation: _exponentiation, floorDiv: _floorDiv, plusMin: _plusMin,\n        posNegNot: _posNegNot, multiplyModulo: _multiplyModulo,\n    };\n    for (var kw in keywordTypes) exports.tokTypes['_' + kw] = keywordTypes[kw];\n\n    // This is a trick taken from Esprima. It turns out that, on\n    // non-Chrome browsers, to check whether a string is in a set, a\n    // predicate containing a big ugly `switch` statement is faster than\n    // a regular expression, and on Chrome the two are about on par.\n    // This function uses `eval` (non-lexical) to produce such a\n    // predicate from a space-separated string of words.\n    //\n    // It starts by sorting the words by length.\n\n    function makePredicate(words) {\n        words = words.split(' ');\n        var f = '', cats = [];\n        out: for (var i = 0; i < words.length; ++i) {\n            for (var j = 0; j < cats.length; ++j)\n                if (cats[j][0].length == words[i].length) {\n                    cats[j].push(words[i]);\n                    continue out;\n                }\n            cats.push([words[i]]);\n        }\n\n        function compareTo(arr) {\n            if (arr.length == 1) return f += 'return str === ' + JSON.stringify(arr[0]) + ';';\n            f += 'switch(str){';\n            for (var i = 0; i < arr.length; ++i) f += 'case ' + JSON.stringify(arr[i]) + ':';\n            f += 'return true}return false;';\n        }\n\n        // When there are more than three length categories, an outer\n        // switch first dispatches on the lengths, to save on comparisons.\n\n        if (cats.length > 3) {\n            cats.sort(function(a, b) {\n                return b.length - a.length;\n            });\n            f += 'switch(str.length){';\n            for (var i = 0; i < cats.length; ++i) {\n                var cat = cats[i];\n                f += 'case ' + cat[0].length + ':';\n                compareTo(cat);\n            }\n            f += '}';\n\n            // Otherwise, simply generate a flat `switch` statement.\n\n        } else {\n            compareTo(words);\n        }\n        return new Function('str', f);\n    }\n\n    // The forbidden variable names\n\n    var isStrictBadIdWord = makePredicate('eval arguments');\n\n    // Keywords\n    // TODO: dict isn't a keyword, it's a builtin\n\n    var isKeyword = makePredicate('dict False None True and as assert break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield exec');\n\n    // ## Character categories\n\n    // Big ugly regular expressions that match characters in the\n    // whitespace, identifier, and identifier-start categories. These\n    // are only applied when a character is found to actually have a\n    // code point above 128.\n\n    var nonASCIIwhitespace = /[\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\\ufeff]/;\n    var nonASCIIidentifierStartChars = '\\xaa\\xb5\\xba\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u02c1\\u02c6-\\u02d1\\u02e0-\\u02e4\\u02ec\\u02ee\\u0370-\\u0374\\u0376\\u0377\\u037a-\\u037d\\u0386\\u0388-\\u038a\\u038c\\u038e-\\u03a1\\u03a3-\\u03f5\\u03f7-\\u0481\\u048a-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05d0-\\u05ea\\u05f0-\\u05f2\\u0620-\\u064a\\u066e\\u066f\\u0671-\\u06d3\\u06d5\\u06e5\\u06e6\\u06ee\\u06ef\\u06fa-\\u06fc\\u06ff\\u0710\\u0712-\\u072f\\u074d-\\u07a5\\u07b1\\u07ca-\\u07ea\\u07f4\\u07f5\\u07fa\\u0800-\\u0815\\u081a\\u0824\\u0828\\u0840-\\u0858\\u08a0\\u08a2-\\u08ac\\u0904-\\u0939\\u093d\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097f\\u0985-\\u098c\\u098f\\u0990\\u0993-\\u09a8\\u09aa-\\u09b0\\u09b2\\u09b6-\\u09b9\\u09bd\\u09ce\\u09dc\\u09dd\\u09df-\\u09e1\\u09f0\\u09f1\\u0a05-\\u0a0a\\u0a0f\\u0a10\\u0a13-\\u0a28\\u0a2a-\\u0a30\\u0a32\\u0a33\\u0a35\\u0a36\\u0a38\\u0a39\\u0a59-\\u0a5c\\u0a5e\\u0a72-\\u0a74\\u0a85-\\u0a8d\\u0a8f-\\u0a91\\u0a93-\\u0aa8\\u0aaa-\\u0ab0\\u0ab2\\u0ab3\\u0ab5-\\u0ab9\\u0abd\\u0ad0\\u0ae0\\u0ae1\\u0b05-\\u0b0c\\u0b0f\\u0b10\\u0b13-\\u0b28\\u0b2a-\\u0b30\\u0b32\\u0b33\\u0b35-\\u0b39\\u0b3d\\u0b5c\\u0b5d\\u0b5f-\\u0b61\\u0b71\\u0b83\\u0b85-\\u0b8a\\u0b8e-\\u0b90\\u0b92-\\u0b95\\u0b99\\u0b9a\\u0b9c\\u0b9e\\u0b9f\\u0ba3\\u0ba4\\u0ba8-\\u0baa\\u0bae-\\u0bb9\\u0bd0\\u0c05-\\u0c0c\\u0c0e-\\u0c10\\u0c12-\\u0c28\\u0c2a-\\u0c33\\u0c35-\\u0c39\\u0c3d\\u0c58\\u0c59\\u0c60\\u0c61\\u0c85-\\u0c8c\\u0c8e-\\u0c90\\u0c92-\\u0ca8\\u0caa-\\u0cb3\\u0cb5-\\u0cb9\\u0cbd\\u0cde\\u0ce0\\u0ce1\\u0cf1\\u0cf2\\u0d05-\\u0d0c\\u0d0e-\\u0d10\\u0d12-\\u0d3a\\u0d3d\\u0d4e\\u0d60\\u0d61\\u0d7a-\\u0d7f\\u0d85-\\u0d96\\u0d9a-\\u0db1\\u0db3-\\u0dbb\\u0dbd\\u0dc0-\\u0dc6\\u0e01-\\u0e30\\u0e32\\u0e33\\u0e40-\\u0e46\\u0e81\\u0e82\\u0e84\\u0e87\\u0e88\\u0e8a\\u0e8d\\u0e94-\\u0e97\\u0e99-\\u0e9f\\u0ea1-\\u0ea3\\u0ea5\\u0ea7\\u0eaa\\u0eab\\u0ead-\\u0eb0\\u0eb2\\u0eb3\\u0ebd\\u0ec0-\\u0ec4\\u0ec6\\u0edc-\\u0edf\\u0f00\\u0f40-\\u0f47\\u0f49-\\u0f6c\\u0f88-\\u0f8c\\u1000-\\u102a\\u103f\\u1050-\\u1055\\u105a-\\u105d\\u1061\\u1065\\u1066\\u106e-\\u1070\\u1075-\\u1081\\u108e\\u10a0-\\u10c5\\u10c7\\u10cd\\u10d0-\\u10fa\\u10fc-\\u1248\\u124a-\\u124d\\u1250-\\u1256\\u1258\\u125a-\\u125d\\u1260-\\u1288\\u128a-\\u128d\\u1290-\\u12b0\\u12b2-\\u12b5\\u12b8-\\u12be\\u12c0\\u12c2-\\u12c5\\u12c8-\\u12d6\\u12d8-\\u1310\\u1312-\\u1315\\u1318-\\u135a\\u1380-\\u138f\\u13a0-\\u13f4\\u1401-\\u166c\\u166f-\\u167f\\u1681-\\u169a\\u16a0-\\u16ea\\u16ee-\\u16f0\\u1700-\\u170c\\u170e-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176c\\u176e-\\u1770\\u1780-\\u17b3\\u17d7\\u17dc\\u1820-\\u1877\\u1880-\\u18a8\\u18aa\\u18b0-\\u18f5\\u1900-\\u191c\\u1950-\\u196d\\u1970-\\u1974\\u1980-\\u19ab\\u19c1-\\u19c7\\u1a00-\\u1a16\\u1a20-\\u1a54\\u1aa7\\u1b05-\\u1b33\\u1b45-\\u1b4b\\u1b83-\\u1ba0\\u1bae\\u1baf\\u1bba-\\u1be5\\u1c00-\\u1c23\\u1c4d-\\u1c4f\\u1c5a-\\u1c7d\\u1ce9-\\u1cec\\u1cee-\\u1cf1\\u1cf5\\u1cf6\\u1d00-\\u1dbf\\u1e00-\\u1f15\\u1f18-\\u1f1d\\u1f20-\\u1f45\\u1f48-\\u1f4d\\u1f50-\\u1f57\\u1f59\\u1f5b\\u1f5d\\u1f5f-\\u1f7d\\u1f80-\\u1fb4\\u1fb6-\\u1fbc\\u1fbe\\u1fc2-\\u1fc4\\u1fc6-\\u1fcc\\u1fd0-\\u1fd3\\u1fd6-\\u1fdb\\u1fe0-\\u1fec\\u1ff2-\\u1ff4\\u1ff6-\\u1ffc\\u2071\\u207f\\u2090-\\u209c\\u2102\\u2107\\u210a-\\u2113\\u2115\\u2119-\\u211d\\u2124\\u2126\\u2128\\u212a-\\u212d\\u212f-\\u2139\\u213c-\\u213f\\u2145-\\u2149\\u214e\\u2160-\\u2188\\u2c00-\\u2c2e\\u2c30-\\u2c5e\\u2c60-\\u2ce4\\u2ceb-\\u2cee\\u2cf2\\u2cf3\\u2d00-\\u2d25\\u2d27\\u2d2d\\u2d30-\\u2d67\\u2d6f\\u2d80-\\u2d96\\u2da0-\\u2da6\\u2da8-\\u2dae\\u2db0-\\u2db6\\u2db8-\\u2dbe\\u2dc0-\\u2dc6\\u2dc8-\\u2dce\\u2dd0-\\u2dd6\\u2dd8-\\u2dde\\u2e2f\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303c\\u3041-\\u3096\\u309d-\\u309f\\u30a1-\\u30fa\\u30fc-\\u30ff\\u3105-\\u312d\\u3131-\\u318e\\u31a0-\\u31ba\\u31f0-\\u31ff\\u3400-\\u4db5\\u4e00-\\u9fcc\\ua000-\\ua48c\\ua4d0-\\ua4fd\\ua500-\\ua60c\\ua610-\\ua61f\\ua62a\\ua62b\\ua640-\\ua66e\\ua67f-\\ua697\\ua6a0-\\ua6ef\\ua717-\\ua71f\\ua722-\\ua788\\ua78b-\\ua78e\\ua790-\\ua793\\ua7a0-\\ua7aa\\ua7f8-\\ua801\\ua803-\\ua805\\ua807-\\ua80a\\ua80c-\\ua822\\ua840-\\ua873\\ua882-\\ua8b3\\ua8f2-\\ua8f7\\ua8fb\\ua90a-\\ua925\\ua930-\\ua946\\ua960-\\ua97c\\ua984-\\ua9b2\\ua9cf\\uaa00-\\uaa28\\uaa40-\\uaa42\\uaa44-\\uaa4b\\uaa60-\\uaa76\\uaa7a\\uaa80-\\uaaaf\\uaab1\\uaab5\\uaab6\\uaab9-\\uaabd\\uaac0\\uaac2\\uaadb-\\uaadd\\uaae0-\\uaaea\\uaaf2-\\uaaf4\\uab01-\\uab06\\uab09-\\uab0e\\uab11-\\uab16\\uab20-\\uab26\\uab28-\\uab2e\\uabc0-\\uabe2\\uac00-\\ud7a3\\ud7b0-\\ud7c6\\ud7cb-\\ud7fb\\uf900-\\ufa6d\\ufa70-\\ufad9\\ufb00-\\ufb06\\ufb13-\\ufb17\\ufb1d\\ufb1f-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40\\ufb41\\ufb43\\ufb44\\ufb46-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb\\ufe70-\\ufe74\\ufe76-\\ufefc\\uff21-\\uff3a\\uff41-\\uff5a\\uff66-\\uffbe\\uffc2-\\uffc7\\uffca-\\uffcf\\uffd2-\\uffd7\\uffda-\\uffdc';\n    var nonASCIIidentifierChars = '\\u0300-\\u036f\\u0483-\\u0487\\u0591-\\u05bd\\u05bf\\u05c1\\u05c2\\u05c4\\u05c5\\u05c7\\u0610-\\u061a\\u0620-\\u0649\\u0672-\\u06d3\\u06e7-\\u06e8\\u06fb-\\u06fc\\u0730-\\u074a\\u0800-\\u0814\\u081b-\\u0823\\u0825-\\u0827\\u0829-\\u082d\\u0840-\\u0857\\u08e4-\\u08fe\\u0900-\\u0903\\u093a-\\u093c\\u093e-\\u094f\\u0951-\\u0957\\u0962-\\u0963\\u0966-\\u096f\\u0981-\\u0983\\u09bc\\u09be-\\u09c4\\u09c7\\u09c8\\u09d7\\u09df-\\u09e0\\u0a01-\\u0a03\\u0a3c\\u0a3e-\\u0a42\\u0a47\\u0a48\\u0a4b-\\u0a4d\\u0a51\\u0a66-\\u0a71\\u0a75\\u0a81-\\u0a83\\u0abc\\u0abe-\\u0ac5\\u0ac7-\\u0ac9\\u0acb-\\u0acd\\u0ae2-\\u0ae3\\u0ae6-\\u0aef\\u0b01-\\u0b03\\u0b3c\\u0b3e-\\u0b44\\u0b47\\u0b48\\u0b4b-\\u0b4d\\u0b56\\u0b57\\u0b5f-\\u0b60\\u0b66-\\u0b6f\\u0b82\\u0bbe-\\u0bc2\\u0bc6-\\u0bc8\\u0bca-\\u0bcd\\u0bd7\\u0be6-\\u0bef\\u0c01-\\u0c03\\u0c46-\\u0c48\\u0c4a-\\u0c4d\\u0c55\\u0c56\\u0c62-\\u0c63\\u0c66-\\u0c6f\\u0c82\\u0c83\\u0cbc\\u0cbe-\\u0cc4\\u0cc6-\\u0cc8\\u0cca-\\u0ccd\\u0cd5\\u0cd6\\u0ce2-\\u0ce3\\u0ce6-\\u0cef\\u0d02\\u0d03\\u0d46-\\u0d48\\u0d57\\u0d62-\\u0d63\\u0d66-\\u0d6f\\u0d82\\u0d83\\u0dca\\u0dcf-\\u0dd4\\u0dd6\\u0dd8-\\u0ddf\\u0df2\\u0df3\\u0e34-\\u0e3a\\u0e40-\\u0e45\\u0e50-\\u0e59\\u0eb4-\\u0eb9\\u0ec8-\\u0ecd\\u0ed0-\\u0ed9\\u0f18\\u0f19\\u0f20-\\u0f29\\u0f35\\u0f37\\u0f39\\u0f41-\\u0f47\\u0f71-\\u0f84\\u0f86-\\u0f87\\u0f8d-\\u0f97\\u0f99-\\u0fbc\\u0fc6\\u1000-\\u1029\\u1040-\\u1049\\u1067-\\u106d\\u1071-\\u1074\\u1082-\\u108d\\u108f-\\u109d\\u135d-\\u135f\\u170e-\\u1710\\u1720-\\u1730\\u1740-\\u1750\\u1772\\u1773\\u1780-\\u17b2\\u17dd\\u17e0-\\u17e9\\u180b-\\u180d\\u1810-\\u1819\\u1920-\\u192b\\u1930-\\u193b\\u1951-\\u196d\\u19b0-\\u19c0\\u19c8-\\u19c9\\u19d0-\\u19d9\\u1a00-\\u1a15\\u1a20-\\u1a53\\u1a60-\\u1a7c\\u1a7f-\\u1a89\\u1a90-\\u1a99\\u1b46-\\u1b4b\\u1b50-\\u1b59\\u1b6b-\\u1b73\\u1bb0-\\u1bb9\\u1be6-\\u1bf3\\u1c00-\\u1c22\\u1c40-\\u1c49\\u1c5b-\\u1c7d\\u1cd0-\\u1cd2\\u1d00-\\u1dbe\\u1e01-\\u1f15\\u200c\\u200d\\u203f\\u2040\\u2054\\u20d0-\\u20dc\\u20e1\\u20e5-\\u20f0\\u2d81-\\u2d96\\u2de0-\\u2dff\\u3021-\\u3028\\u3099\\u309a\\ua640-\\ua66d\\ua674-\\ua67d\\ua69f\\ua6f0-\\ua6f1\\ua7f8-\\ua800\\ua806\\ua80b\\ua823-\\ua827\\ua880-\\ua881\\ua8b4-\\ua8c4\\ua8d0-\\ua8d9\\ua8f3-\\ua8f7\\ua900-\\ua909\\ua926-\\ua92d\\ua930-\\ua945\\ua980-\\ua983\\ua9b3-\\ua9c0\\uaa00-\\uaa27\\uaa40-\\uaa41\\uaa4c-\\uaa4d\\uaa50-\\uaa59\\uaa7b\\uaae0-\\uaae9\\uaaf2-\\uaaf3\\uabc0-\\uabe1\\uabec\\uabed\\uabf0-\\uabf9\\ufb20-\\ufb28\\ufe00-\\ufe0f\\ufe20-\\ufe26\\ufe33\\ufe34\\ufe4d-\\ufe4f\\uff10-\\uff19\\uff3f';\n    var nonASCIIidentifierStart = new RegExp('[' + nonASCIIidentifierStartChars + ']');\n    var nonASCIIidentifier = new RegExp('[' + nonASCIIidentifierStartChars + nonASCIIidentifierChars + ']');\n\n    // Whether a single character denotes a newline.\n\n    var newline = /[\\n\\r\\u2028\\u2029]/;\n\n    // Matches a whole line break (where CRLF is considered a single\n    // line break). Used to count lines.\n\n    var lineBreak = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n\n    // Test whether a given character code starts an identifier.\n\n    var isIdentifierStart = exports.isIdentifierStart = function(code) {\n        if (code < 65) return code === 36;\n        if (code < 91) return true;\n        if (code < 97) return code === 95;\n        if (code < 123) return true;\n        return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code));\n    };\n\n    // Test whether a given character is part of an identifier.\n\n    var isIdentifierChar = exports.isIdentifierChar = function(code) {\n        if (code < 48) return code === 36;\n        if (code < 58) return true;\n        if (code < 65) return false;\n        if (code < 91) return true;\n        if (code < 97) return code === 95;\n        if (code < 123) return true;\n        return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code));\n    };\n\n    // ## Tokenizer\n\n    // These are used when `options.locations` is on, for the\n    // `tokStartLoc` and `tokEndLoc` properties.\n\n    function Position() {\n        this.line = tokCurLine;\n        this.column = tokPos - tokLineStart;\n    }\n\n    // Reset the token state. Used at the start of a parse.\n\n    function initTokenState() {\n        tokCurLine = 1;\n        tokPos = tokLineStart = 0;\n        tokRegexpAllowed = true;\n        indentHist.init();\n        newAstIdCount = 0;\n        scope.init();\n    }\n\n    // Called at the end of every token. Sets `tokEnd`, `tokVal`, and\n    // `tokRegexpAllowed`, and skips the space after the token, so that\n    // the next one's `tokStart` will point at the right position.\n\n    function finishToken(type, val) {\n        tokEnd = tokPos;\n        if (options.locations) tokEndLoc = new Position;\n        tokType = type;\n        if (type === _parenL || type === _braceL || type === _bracketL) ++bracketNesting;\n        if (type === _parenR || type === _braceR || type === _bracketR) --bracketNesting;\n        if (type !== _newline) skipSpace();\n        tokVal = val;\n        tokRegexpAllowed = type.beforeExpr;\n    }\n\n    function skipLine() {\n        var ch = input.charCodeAt(++tokPos);\n        while (tokPos < inputLen && !isNewline(ch)) {\n            ++tokPos;\n            ch = input.charCodeAt(tokPos);\n        }\n    }\n\n    function skipLineComment() {\n        var start = tokPos;\n        var startLoc = options.onComment && options.locations && new Position;\n        skipLine();\n        if (options.onComment)\n            options.onComment(input.slice(start + 1, tokPos), start, tokPos,\n                startLoc, options.locations && new Position);\n    }\n\n    // Called at the start of the parse and after every token. Skips\n    // whitespace and comments, and.\n\n    function skipSpace() {\n        while (tokPos < inputLen) {\n            var ch = input.charCodeAt(tokPos);\n            if (ch === 92) {\n                ++tokPos;\n                if (isNewline(input.charCodeAt(tokPos))) {\n                    if (input.charCodeAt(tokPos) === 13 && input.charCodeAt(tokPos + 1) === 10) ++tokPos;\n                    ++tokPos;\n                    if (options.location) {\n                        tokLineStart = tokPos;\n                        ++tokCurLine;\n                    }\n                } else {\n                    raise(tokPos, 'Unexpected character after line continuation character');\n                }\n            }\n            else if (isSpace(ch)) ++tokPos;\n            else if (bracketNesting > 0 && isNewline(ch)) {\n                if (ch === 13 && input.charCodeAt(tokPos + 1) === 10) ++tokPos;\n                ++tokPos;\n                if (options.location) {\n                    tokLineStart = tokPos;\n                    ++tokCurLine;\n                }\n            }\n            else break;\n        }\n    }\n\n    function isSpace(ch) {\n        if (ch === 32 || // ' '\n            ch === 9 || ch === 11 || ch === 12 ||\n            ch === 160 || // '\\xa0'\n            ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {\n            return true;\n        }\n        return false;\n    }\n\n    function isNewline(ch) {\n        if (ch === 10 || ch === 13 ||\n            ch === 8232 || ch === 8233) {\n            return true;\n        }\n        return false;\n    }\n\n    // ### Token reading\n\n    // This is the function that is called to fetch the next token. It\n    // is somewhat obscure, because it works in character codes rather\n    // than characters, and because operator parsing has been inlined\n    // into it.\n    //\n    // All in the name of speed.\n    //\n    // The `forceRegexp` parameter is used in the one case where the\n    // `tokRegexpAllowed` trick does not work. See `parseStatement`.\n\n    function readToken_singleLineComment() {\n        ++tokPos;\n        skipSpace();\n\n        let out = '';\n        let ch = input.charCodeAt(tokPos);\n        while (!isNewline(ch)) {\n            out += String.fromCharCode(ch);\n            ch = input.charCodeAt(++tokPos);\n        }\n\n        return finishToken(_comment, out);\n    }\n\n    function readToken_dot() {\n        var next = input.charCodeAt(tokPos + 1);\n        if (next >= 48 && next <= 57) return readNumber(true);\n        ++tokPos;\n        return finishToken(_dot);\n    }\n\n    function readToken_slash() { // '/'\n        if (tokRegexpAllowed) {\n            ++tokPos;\n            return readRegexp();\n        }\n        var next = input.charCodeAt(tokPos + 1);\n        if (next === 47) return finishOp(_floorDiv, 2);\n        if (next === 61) return finishOp(_assign, 2);\n        return finishOp(_slash, 1);\n    }\n\n    function readToken_mult_modulo(code) { // '*%'\n        var next = input.charCodeAt(tokPos + 1);\n        if (next === 42 && next === code) return finishOp(_exponentiation, 2);\n        if (next === 61) return finishOp(_assign, 2);\n        return finishOp(_multiplyModulo, 1);\n    }\n\n    function readToken_pipe_amp(code) { // '|&'\n        var next = input.charCodeAt(tokPos + 1);\n        if (next === 61) return finishOp(_assign, 2);\n        return finishOp(code === 124 ? _bitwiseOR : _bitwiseAND, 1);\n    }\n\n    function readToken_caret() { // '^'\n        var next = input.charCodeAt(tokPos + 1);\n        if (next === 61) return finishOp(_assign, 2);\n        return finishOp(_bitwiseXOR, 1);\n    }\n\n    function readToken_plus_min(code) { // '+-'\n        var next = input.charCodeAt(tokPos + 1);\n        if (next === 61) return finishOp(_assign, 2);\n        return finishOp(_plusMin, 1);\n    }\n\n    function readToken_lt_gt(code) { // '<>'\n        var next = input.charCodeAt(tokPos + 1);\n        var size = 1;\n        if (next === code) {\n            size = 2;\n            if (input.charCodeAt(tokPos + size) === 61) return finishOp(_assign, size + 1);\n            return finishOp(_bitShift, size);\n        }\n        if (next === 61) size = 2;\n        return finishOp(_relational, size);\n    }\n\n    function readToken_eq_excl(code) { // '=!'\n        var next = input.charCodeAt(tokPos + 1);\n        if (next === 61) return finishOp(_equality, 2);\n        return finishOp(_eq, 1);\n    }\n\n    // Parse indentation\n    // Possible output: _indent, _dedent, _eof, readToken()\n    // TODO: disallow unequal indents of same length (e.g. nested if/else block)\n\n    function readToken_indent() {\n        // Read indent, skip empty lines and comments\n        var indent = '';\n        var indentPos = tokPos;\n        var ch, next;\n        while (indentPos < inputLen) {\n            ch = input.charCodeAt(indentPos);\n            if (isSpace(ch)) {\n                indent += String.fromCharCode(ch);\n                ++indentPos;\n            } else if (isNewline(ch)) { // newline\n                indent = '';\n                if (ch === 13 && input.charCodeAt(indentPos + 1) === 10) ++indentPos;\n                ++indentPos;\n                tokPos = indentPos;\n                if (options.locations) {\n                    tokLineStart = indentPos;\n                    ++tokCurLine;\n                }\n            } else {\n                break;\n            }\n        }\n\n        // Determine token type based on indent found versus indentation history\n        var type;\n        if (indent.length > 0) {\n            if (indentHist.isIndent(indent)) {\n                type = _indent;\n                if (indentHist.count() >= 1) tokStart += indentHist.len(indentHist.count() - 1);\n                indentHist.addIndent(indent);\n            } else if (indentHist.isDedent(indent)) {\n                type = _dedent;\n                indentHist.addDedent(indent);\n                var nextDedent = indentHist.count() - indentHist.dedentCount;\n                if (nextDedent >= 2) {\n                    tokStart += indentHist.len(nextDedent) - indentHist.len(nextDedent - 1);\n                }\n            } else {\n                tokPos += indent.length;\n            }\n        } else if (indentPos >= inputLen) {\n            type = _eof;\n        } else if (indentHist.count() > 0) {\n            type = _dedent;\n            indentHist.updateDedent();\n        }\n\n        switch (type) {\n            case _indent:\n            case _dedent:\n                return finishOp(type, indentPos - ++tokPos);\n            case _eof:\n                tokPos = inputLen;\n                if (options.locations) tokStartLoc = new Position;\n                return finishOp(type, 0);\n            default:\n                tokType = null;\n                return readToken();\n        }\n    }\n\n    function getTokenFromCode(code) {\n        switch (code) {\n\n            case 13:\n            case 10:\n            case 8232:\n            case 8233:\n                ++tokPos;\n                if (code === 13 && input.charCodeAt(tokPos) === 10) ++tokPos;\n                if (options.locations) {\n                    ++tokCurLine;\n                    tokLineStart = tokPos;\n                }\n                return finishToken(_newline);\n\n            case 35: // '#'\n                return readToken_singleLineComment();\n\n            // The interpretation of a dot depends on whether it is followed\n            // by a digit.\n            case 46: // '.'\n                return readToken_dot();\n\n            // Punctuation tokens.\n            case 40:\n                ++tokPos;\n                return finishToken(_parenL);\n            case 41:\n                ++tokPos;\n                return finishToken(_parenR);\n            case 59:\n                ++tokPos;\n                return finishToken(_semi);\n            case 44:\n                ++tokPos;\n                return finishToken(_comma);\n            case 91:\n                ++tokPos;\n                return finishToken(_bracketL);\n            case 93:\n                ++tokPos;\n                return finishToken(_bracketR);\n            case 123:\n                ++tokPos;\n                return finishToken(_braceL);\n            case 125:\n                ++tokPos;\n                return finishToken(_braceR);\n            case 58:\n                ++tokPos;\n                return finishToken(_colon);\n            case 63:\n                ++tokPos;\n                return finishToken(_question);\n\n            // Anything else beginning with a digit is an integer, octal\n            // number, or float.\n            case 48:\n            case 49:\n            case 50:\n            case 51:\n            case 52:\n            case 53:\n            case 54:\n            case 55:\n            case 56:\n            case 57: // 1-9\n                return readNumber(false);\n\n            // Quotes produce strings.\n            case 34:\n            case 39: // '\"', \"'\"\n                return readString(code);\n\n            // Operators are parsed inline in tiny state machines. '=' (61) is\n            // often referred to. `finishOp` simply skips the amount of\n            // characters it is given as second argument, and returns a token\n            // of the type given by its first argument.\n\n            case 47: // '/'\n                return readToken_slash(code);\n\n            case 42:\n            case 37: // '*%'\n                return readToken_mult_modulo(code);\n\n            case 124:\n            case 38: // '|&'\n                return readToken_pipe_amp(code);\n\n            case 94: // '^'\n                return readToken_caret();\n\n            case 43:\n            case 45: // '+-'\n                return readToken_plus_min(code);\n\n            case 60:\n            case 62: // '<>'\n                return readToken_lt_gt(code);\n\n            case 61:\n            case 33: // '=!'\n                return readToken_eq_excl(code);\n\n            case 126: // '~'\n                return finishOp(_bitwiseNOT, 1);\n        }\n\n        return false;\n    }\n\n    function readZero() {\n        var val = '';\n        for (var i = tokPos; i < inputLen; i++) {\n            var ch = input.charCodeAt(tokPos);\n            if (isNewline(ch))\n                break;\n\n            val += input[i];\n            tokPos = i;\n        }\n\n        return finishToken(_string, String(val));\n    }\n\n    function readToken(forceRegexp) {\n        if (tokType === _dedent) {\n            indentHist.pop();\n            if (indentHist.dedentCount > 0) return;\n        }\n\n        if (!forceRegexp) tokStart = tokPos;\n        else tokPos = tokStart + 1;\n        if (options.locations) tokStartLoc = new Position;\n        if (forceRegexp) return readRegexp();\n        if (tokPos >= inputLen) return finishToken(_eof);\n        if (tokType === _newline) return readToken_indent();\n\n        if (input.split('=').length > 1 && isKeyword(input.split('=')[0].trim())) {\n            tokPos = input.split(/\\r|\\n/g).length - 1 + 3;\n            if (input.split('=')[1].trim()[0] == '[') {\n                raise(tokPos, 'Reserved list word');\n            } else {\n                raise(tokPos, 'Reserved variable word');\n            }\n        }\n\n        var code = input.charCodeAt(tokPos);\n        // Identifier or keyword. '\\uXXXX' sequences are allowed in\n        // identifiers, so '\\' also dispatches to that.\n        if (isIdentifierStart(code) || code === 92 /* '\\' */) return readWord();\n\n        var tok = getTokenFromCode(code);\n\n        if (tok === false) {\n            // If we are here, we either found a non-ASCII identifier\n            // character, or something that's entirely disallowed.\n            var ch = String.fromCharCode(code);\n            if (ch === '\\\\' || nonASCIIidentifierStart.test(ch)) return readWord();\n            raise(tokPos + 3, 'Unexpected character \\'' + ch + '\\'');\n        }\n        return tok;\n    }\n\n    function finishOp(type, size) {\n        var str = input.slice(tokPos, tokPos + size);\n        tokPos += size;\n        finishToken(type, str);\n    }\n\n    // Parse a regular expression. Some context-awareness is necessary,\n    // since a '/' inside a '[]' set does not end the expression.\n\n    function readRegexp() {\n        var content = '', escaped, inClass, start = tokPos, value;\n        for (; ;) {\n            if (tokPos >= inputLen) raise(start, 'Unterminated regular expression');\n            var ch = input.charAt(tokPos);\n            if (newline.test(ch)) raise(start, 'Unterminated regular expression');\n            if (!escaped) {\n                if (ch === '[') inClass = true;\n                else if (ch === ']' && inClass) inClass = false;\n                else if (ch === '/' && !inClass) break;\n                escaped = ch === '\\\\';\n            } else escaped = false;\n            ++tokPos;\n        }\n        content = input.slice(start, tokPos);\n        ++tokPos;\n        // Need to use `readWord1` because '\\uXXXX' sequences are allowed\n        // here (don't ask).\n        var mods = readWord1();\n        if (mods && !/^[gmsiy]*$/.test(mods)) raise(start, 'Invalid regular expression flag');\n        try {\n            value = new RegExp(content, mods);\n        } catch (e) {\n            if (e instanceof SyntaxError) raise(start, 'Error parsing regular expression: ' + e.message);\n            raise(e);\n        }\n        return finishToken(_regexp, value);\n    }\n\n    // Read an integer in the given radix. Return null if zero digits\n    // were read, the integer value otherwise. When `len` is given, this\n    // will return `null` unless the integer has exactly `len` digits.\n\n    function readInt(radix, len) {\n        var start = tokPos, total = 0;\n        for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {\n            var code = input.charCodeAt(tokPos), val;\n            if (code >= 97) val = code - 97 + 10; // a\n            else if (code >= 65) val = code - 65 + 10; // A\n            else if (code >= 48 && code <= 57) val = code - 48; // 0-9\n            else val = Infinity;\n            if (val >= radix) break;\n            ++tokPos;\n            total = total * radix + val;\n        }\n        if (tokPos === start || len != null && tokPos - start !== len) return null;\n\n        return total;\n    }\n\n    function readHexNumber() {\n        tokPos += 2; // 0x\n        var val = readInt(16);\n        if (val == null) raise(tokStart + 2, 'Expected hexadecimal number');\n        if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, 'Identifier directly after number');\n        return finishToken(_num, val);\n    }\n\n    // Read an integer, octal integer, or floating-point number.\n\n    function readNumber(startsWithDot) {\n        var start = tokPos, isFloat = false, octal = input.charCodeAt(tokPos) === 48;\n        if (!startsWithDot && readInt(10) === null) raise(start, 'Invalid number');\n        if (input.charCodeAt(tokPos) === 46) {\n            ++tokPos;\n            readInt(10);\n            isFloat = true;\n        }\n        var next = input.charCodeAt(tokPos);\n        if (next === 69 || next === 101) { // 'eE'\n            next = input.charCodeAt(++tokPos);\n            if (next === 43 || next === 45) ++tokPos; // '+-'\n            if (readInt(10) === null) raise(start, 'Invalid number');\n            isFloat = true;\n        }\n        if (isIdentifierStart(input.charCodeAt(tokPos))) raise(tokPos, 'Identifier directly after number');\n\n        var str = input.slice(start, tokPos), val;\n        if (isFloat) val = parseFloat(str);\n        else if (!octal || str.length === 1) val = parseInt(str, 10);\n        else if (/[89]/.test(str) || strict) raise(start, 'Invalid number');\n        else val = str;\n        return finishToken(_num, val);\n    }\n\n    // Read a string value, interpreting backslash-escapes.\n\n    function readString(quote) {\n        tokPos++;\n        var ch = input.charCodeAt(tokPos);\n        var tripleQuoted = false;\n        if (ch === quote && input.charCodeAt(tokPos + 1) === quote) {\n            tripleQuoted = true;\n            tokPos += 2;\n        }\n        var out = '';\n        for (; ;) {\n            if (tokPos >= inputLen) raise(tokStart, 'Unterminated string constant');\n            var ch = input.charCodeAt(tokPos);\n            if (ch === quote) {\n                if (tripleQuoted) {\n                    if (input.charCodeAt(tokPos + 1) === quote &&\n                        input.charCodeAt(tokPos + 2) === quote) {\n                        tokPos += 3;\n                        return finishToken(_string, out);\n                    }\n                } else {\n                    ++tokPos;\n                    return finishToken(_string, out);\n                }\n            }\n            if (ch === 92) { // '\\'\n                ch = input.charCodeAt(++tokPos);\n                var octal = /^[0-7]+/.exec(input.slice(tokPos, tokPos + 3));\n                if (octal) octal = octal[0];\n                while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1);\n                if (octal === '0') octal = null;\n                ++tokPos;\n                if (octal) {\n                    if (strict) raise(tokPos - 2, 'Octal literal in strict mode');\n                    out += String.fromCharCode(parseInt(octal, 8));\n                    tokPos += octal.length - 1;\n                } else {\n                    switch (ch) {\n                        case 110:\n                            out += '\\n';\n                            break; // 'n' -> '\\n'\n                        case 114:\n                            out += '\\r';\n                            break; // 'r' -> '\\r'\n                        // case 120: out += String.fromCharCode(readHexChar(2)); break; // 'x'\n                        // case 117: out += String.fromCharCode(readHexChar(4)); break; // 'u'\n                        // case 85: // 'U'\n                        //   ch = readHexChar(8);\n                        //   if (ch < 0xFFFF && (ch < 0xD800 || 0xDBFF < ch)) out += String.fromCharCode(ch); // If it's UTF-16\n                        //   else { // If we need UCS-2\n                        //     ch -= 0x10000;\n                        //     out += String.fromCharCode((ch>>10)+0xd800)+String.fromCharCode((ch%0x400)+0xdc00);\n                        //   }\n                        //   break;\n                        case 116:\n                            out += '\\t';\n                            break; // 't' -> '\\t'\n                        case 98:\n                            out += '\\b';\n                            break; // 'b' -> '\\b'\n                        case 118:\n                            out += '\\u000b';\n                            break; // 'v' -> '\\u000b'\n                        case 102:\n                            out += '\\f';\n                            break; // 'f' -> '\\f'\n                        case 48:\n                            out += '\\0';\n                            break; // 0 -> '\\0'\n                        case 13:\n                            if (input.charCodeAt(tokPos) === 10) ++tokPos; // '\\r\\n'\n                        case 10: // ' \\n'\n                            if (options.locations) {\n                                tokLineStart = tokPos;\n                                ++tokCurLine;\n                            }\n                            break;\n                        default:\n                            out += '\\\\' + String.fromCharCode(ch);\n                            break; // Python doesn't remove slashes on failed escapes\n                    }\n                }\n            } else {\n                if (isNewline(ch)) {\n                    if (tripleQuoted) {\n                        out += String.fromCharCode(ch);\n                        ++tokPos;\n                        if (ch === 13 && input.charCodeAt(tokPos) === 10) {\n                            ++tokPos;\n                            out += '\\n';\n                        }\n                        if (options.location) {\n                            tokLineStart = tokPos;\n                            ++tokCurLine;\n                        }\n                    } else raise(tokStart, 'Unterminated string constant');\n                } else {\n                    out += String.fromCharCode(ch); // '\\'\n                    ++tokPos;\n                }\n            }\n        }\n    }\n\n    // Used to read character escape sequences ('\\x', '\\u', '\\U').\n\n    function readHexChar(len) {\n        var n = readInt(16, len);\n        if (n === null) raise(tokStart, 'Bad character escape sequence');\n        return n;\n    }\n\n    // Used to signal to callers of `readWord1` whether the word\n    // contained any escape sequences. This is needed because words with\n    // escape sequences must not be interpreted as keywords.\n\n    var containsEsc;\n\n    // Read an identifier, and return it as a string. Sets `containsEsc`\n    // to whether the word contained a '\\u' escape.\n    //\n    // Only builds up the word character-by-character when it actually\n    // containeds an escape, as a micro-optimization.\n\n    function readWord1() {\n        containsEsc = false;\n        var word, first = true, start = tokPos;\n        for (; ;) {\n            var ch = input.charCodeAt(tokPos);\n            if (isIdentifierChar(ch)) {\n                if (containsEsc) word += input.charAt(tokPos);\n                ++tokPos;\n            } else if (ch === 92) { // \"\\\"\n                if (!containsEsc) word = input.slice(start, tokPos);\n                containsEsc = true;\n                if (input.charCodeAt(++tokPos) != 117) // \"u\"\n                    raise(tokPos, 'Expecting Unicode escape sequence \\\\uXXXX');\n                ++tokPos;\n                var esc = readHexChar(4);\n                var escStr = String.fromCharCode(esc);\n                if (!escStr) raise(tokPos - 1, 'Invalid Unicode escape');\n                if (!(first ? isIdentifierStart(esc) : isIdentifierChar(esc)))\n                    raise(tokPos - 4, 'Invalid Unicode escape');\n                word += escStr;\n            } else {\n                break;\n            }\n            first = false;\n        }\n        return containsEsc ? word : input.slice(start, tokPos);\n    }\n\n    // Read an identifier or keyword token. Will check for reserved\n    // words when necessary.\n\n    function readWord() {\n        var word = readWord1();\n        var type = _name;\n        if (!containsEsc && isKeyword(word))\n            type = keywordTypes[word];\n        return finishToken(type, word);\n    }\n\n    // ## Parser\n\n    // A recursive descent parser operates by defining functions for all\n    // syntactic elements, and recursively calling those, each function\n    // advancing the input stream and returning an AST node. Precedence\n    // of constructs (for example, the fact that `!x[1]` means `!(x[1])`\n    // instead of `(!x)[1]` is handled by the fact that the parser\n    // function that parses unary prefix operators is called first, and\n    // in turn calls the function that parses `[]` subscripts - that\n    // way, it'll receive the node for `x[1]` already parsed, and wraps\n    // *that* in the unary operator node.\n    //\n    // Acorn uses an [operator precedence parser][opp] to handle binary\n    // operator precedence, because it is much more compact than using\n    // the technique outlined above, which uses different, nesting\n    // functions to specify precedence, for all of the ten binary\n    // precedence levels that JavaScript defines.\n    //\n    // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser\n\n    // ### Parser utilities\n\n    // Continue to the next token.\n\n    function next() {\n        lastStart = tokStart;\n        lastEnd = tokEnd;\n        lastEndLoc = tokEndLoc;\n        readToken();\n    }\n\n    // Enter strict mode. Re-reads the next token to please pedantic\n    // tests (\"use strict\"; 010; -- should fail).\n\n    function setStrict(strct) {\n        strict = strct;\n        tokPos = tokStart;\n        if (options.locations) {\n            while (tokPos < tokLineStart) {\n                tokLineStart = input.lastIndexOf('\\n', tokLineStart - 2) + 1;\n                --tokCurLine;\n            }\n        }\n        skipSpace();\n        readToken();\n    }\n\n    // Start an AST node, attaching a start offset.\n\n    function Node() {\n        this.type = null;\n    }\n\n    exports.Node = Node;\n\n    function SourceLocation() {\n        this.start = tokStartLoc;\n        this.end = null;\n        if (sourceFile !== null) this.source = sourceFile;\n    }\n\n    function startNode() {\n        var node = new Node();\n        if (options.locations)\n            node.loc = new SourceLocation();\n        if (options.directSourceFile)\n            node.sourceFile = options.directSourceFile;\n        if (options.ranges)\n            node.range = [tokStart, 0];\n        return node;\n    }\n\n    // Finish an AST node, adding `type` and `end` properties.\n\n    function finishNode(node, type) {\n        node.type = type;\n        if (options.locations)\n            node.loc.end = lastEndLoc;\n        if (options.ranges)\n            node.range[1] = lastEnd;\n        return node;\n    }\n\n    // Start a node whose start offset information should be based on\n    // the start of another node. For example, a binary operator node is\n    // only started after its left-hand side has already been parsed.\n\n    function startNodeFrom(other) {\n        var node = new Node();\n        if (options.locations) {\n            node.loc = new SourceLocation();\n            node.loc.start = other.loc.start;\n        }\n        if (options.ranges)\n            node.range = [other.range[0], 0];\n\n        return node;\n    }\n\n    // ## Node creation utilities\n\n    var getNodeCreator = exports.getNodeCreator = function(startNode, startNodeFrom, finishNode, unpackTuple) {\n\n        return {\n\n            // Finish a node whose end offset information should be based on\n            // the end of another node.  For example, createNode* functions\n            // are used to create extra AST nodes which may be based on a single\n            // parsed user code node.\n\n            finishNodeFrom: function(endNode, node, type) {\n                node.type = type;\n                if (options.locations) node.loc.end = endNode.loc.end;\n                if (options.ranges) node.range[1] = endNode.range[1];\n                return node;\n            },\n\n            // Create an AST node using start offsets\n\n            createNodeFrom: function(startNode, type, props) {\n                var node = startNodeFrom(startNode);\n                for (var prop in props) node[prop] = props[prop];\n                return finishNode(node, type);\n            },\n\n            // Create an AST node using start and end offsets\n\n            createNodeSpan: function(startNode, endNode, type, props) {\n                var node = startNodeFrom(startNode);\n                for (var prop in props) node[prop] = props[prop];\n                return this.finishNodeFrom(endNode, node, type);\n            },\n\n            createGeneratedNodeSpan: function(startNode, endNode, type, props) {\n                var node = startNodeFrom(startNode);\n                for (var prop in props) node[prop] = props[prop];\n                node.userCode = false;\n                return this.finishNodeFrom(endNode, node, type);\n            },\n\n            // while (__formalsIndex < __params.formals.length) {\n            //   <argsId>.push(__params.formals[__formalsIndex++]); }\n            createNodeArgsWhileConsequent: function(argsId, s) {\n                var __paramsFormals = this.createNodeMembIds(argsId, '__params' + s, 'formals');\n                var __formalsIndexId = this.createGeneratedNodeSpan(argsId, argsId, 'Identifier', { name: '__formalsIndex' + s });\n                return this.createGeneratedNodeSpan(argsId, argsId, 'WhileStatement', {\n                    test: this.createGeneratedNodeSpan(argsId, argsId, 'BinaryExpression', {\n                        operator: '<', left: __formalsIndexId,\n                        right: this.createGeneratedNodeSpan(argsId, argsId, 'MemberExpression', {\n                            computed: false, object: __paramsFormals,\n                            property: this.createGeneratedNodeSpan(argsId, argsId, 'Identifier', { name: 'length' }),\n                        }),\n                    }),\n                    body: this.createGeneratedNodeSpan(argsId, argsId, 'BlockStatement', {\n                        body: [this.createGeneratedNodeSpan(argsId, argsId, 'ExpressionStatement', {\n                            expression: this.createGeneratedNodeSpan(argsId, argsId, 'CallExpression', {\n                                callee: this.createNodeMembIds(argsId, argsId.name, 'push'),\n                                arguments: [this.createGeneratedNodeSpan(argsId, argsId, 'MemberExpression', {\n                                    computed: true, object: __paramsFormals,\n                                    property: this.createGeneratedNodeSpan(argsId, argsId, 'UpdateExpression', {\n                                        operator: '++', prefix: false, argument: __formalsIndexId,\n                                    }),\n                                })],\n                            }),\n                        })],\n                    }),\n                });\n            },\n\n            // { while (__formalsIndex < __args.length) {\n            //   <argsId>.push(__args[__formalsIndex++]); }}\n            createNodeArgsAlternate: function(argsId, s) {\n                var __args = '__args' + s;\n                var __formalsIndexId = this.createGeneratedNodeSpan(argsId, argsId, 'Identifier', { name: '__formalsIndex' + s });\n                return this.createGeneratedNodeSpan(argsId, argsId, 'BlockStatement', {\n                    body: [this.createGeneratedNodeSpan(argsId, argsId, 'WhileStatement', {\n                        test: this.createGeneratedNodeSpan(argsId, argsId, 'BinaryExpression', {\n                            operator: '<', left: __formalsIndexId,\n                            right: this.createNodeMembIds(argsId, __args, 'length'),\n                        }),\n                        body: this.createGeneratedNodeSpan(argsId, argsId, 'BlockStatement', {\n                            body: [this.createGeneratedNodeSpan(argsId, argsId, 'ExpressionStatement', {\n                                expression: this.createGeneratedNodeSpan(argsId, argsId, 'CallExpression', {\n                                    callee: this.createNodeMembIds(argsId, argsId.name, 'push'),\n                                    arguments: [this.createGeneratedNodeSpan(argsId, argsId, 'MemberExpression', {\n                                        computed: true,\n                                        object: this.createGeneratedNodeSpan(argsId, argsId, 'Identifier', { name: __args }),\n                                        property: this.createGeneratedNodeSpan(argsId, argsId, 'UpdateExpression', {\n                                            operator: '++', prefix: false, argument: __formalsIndexId,\n                                        }),\n                                    })],\n                                }),\n                            })],\n                        }),\n                    })],\n                });\n            },\n\n            // return (function() {<body>}).call(this);\n            createNodeFnBodyIife: function(body) {\n                var iifeBody = this.createGeneratedNodeSpan(body, body, 'FunctionExpression', {\n                    params: [], defaults: [], body: body, generator: false, expression: false,\n                });\n                var iifeCall = this.createGeneratedNodeSpan(body, body, 'CallExpression', {\n                    callee: this.createGeneratedNodeSpan(body, body, 'MemberExpression', {\n                        computed: false, object: iifeBody,\n                        property: this.createGeneratedNodeSpan(body, body, 'Identifier', { name: 'call' }),\n                    }),\n                    arguments: [this.createGeneratedNodeSpan(body, body, 'ThisExpression')],\n                });\n                return this.createGeneratedNodeSpan(body, body, 'ReturnStatement', { argument: iifeCall });\n            },\n\n            // E.g. Math.pow(2, 3)\n\n            createNodeMemberCall: function(node, object, property, args) {\n                var objId = this.createNodeFrom(node, 'Identifier', { name: object });\n                var propId = this.createNodeFrom(node, 'Identifier', { name: property });\n                var member = this.createNodeFrom(node, 'MemberExpression', {\n                    object: objId,\n                    property: propId,\n                    computed: false,\n                });\n                node.callee = member;\n                node.arguments = args;\n                return finishNode(node, 'CallExpression');\n            },\n\n            // o.p\n            createNodeMembIds: function(r, o, p) {\n                return this.createNodeSpan(r, r, 'MemberExpression', {\n                    computed: false,\n                    object: this.createNodeSpan(r, r, 'Identifier', { name: o }),\n                    property: this.createNodeSpan(r, r, 'Identifier', { name: p }),\n                });\n            },\n\n            // o[p]\n            createNodeMembIdLit: function(r, o, p) {\n                return this.createNodeSpan(r, r, 'MemberExpression', {\n                    computed: true,\n                    object: this.createNodeSpan(r, r, 'Identifier', { name: o }),\n                    property: this.createNodeSpan(r, r, 'Literal', { value: p }),\n                });\n            },\n\n            // E.g. pyRuntime.ops.add\n\n            createNodeOpsCallee: function(node, fnName) {\n                var runtimeId = this.createGeneratedNodeSpan(node, node, 'Identifier', { name: options.runtimeParamName });\n                var opsId = this.createGeneratedNodeSpan(node, node, 'Identifier', { name: 'ops' });\n                var addId = this.createGeneratedNodeSpan(node, node, 'Identifier', { name: fnName });\n                var opsMember = this.createGeneratedNodeSpan(node, node, 'MemberExpression', {\n                    object: runtimeId,\n                    property: opsId,\n                    computed: false,\n                });\n                return this.createGeneratedNodeSpan(node, node, 'MemberExpression', {\n                    object: opsMember,\n                    property: addId,\n                    computed: false,\n                });\n            },\n\n            // var __params = arguments.length === 1 && arguments[0].formals && arguments[0].keywords ? arguments[0] : null;\n            createNodeParamsCheck: function(r, s) {\n                var __paramsId = this.createNodeSpan(r, r, 'Identifier', { name: '__params' + s });\n                var arguments0 = this.createNodeMembIdLit(r, 'arguments', 0);\n                var checks = this.createNodeSpan(r, r, 'ConditionalExpression', {\n                    test: this.createNodeSpan(r, r, 'LogicalExpression', {\n                        operator: '&&',\n                        left: this.createNodeSpan(r, r, 'LogicalExpression', {\n                            operator: '&&',\n                            left: this.createNodeSpan(r, r, 'BinaryExpression', {\n                                operator: '===',\n                                left: this.createNodeMembIds(r, 'arguments', 'length'),\n                                right: this.createNodeSpan(r, r, 'Literal', { value: 1 }),\n                            }),\n                            right: this.createNodeSpan(r, r, 'MemberExpression', {\n                                computed: false, object: arguments0,\n                                property: this.createNodeSpan(r, r, 'Identifier', { name: 'formals' }),\n                            }),\n                        }),\n                        right: this.createNodeSpan(r, r, 'MemberExpression', {\n                            computed: false, object: arguments0,\n                            property: this.createNodeSpan(r, r, 'Identifier', { name: 'keywords' }),\n                        }),\n                    }),\n                    consequent: arguments0,\n                    alternate: this.createNodeSpan(r, r, 'Literal', { value: null }),\n                });\n                return this.createGeneratedVarDeclFromId(r, __paramsId, checks);\n            },\n\n            // function __getParam(v, d) {\n            //   var r = d;\n            //   if (__params) {\n            //     if (__formalsIndex < __params.formals.length) {\n            //       r = __params.formals[__formalsIndex++];\n            //     } else if (v in __params.keywords) {\n            //       r = __params.keywords[v];\n            //       delete __params.keywords[v];\n            //     }\n            //   } else if (__formalsIndex < __args.length) {\n            //     r = __args[__formalsIndex++];\n            //   }\n            //   return r;\n            // }\n            createNodeGetParamFn: function(r, s) {\n                var dId = this.createNodeSpan(r, r, 'Identifier', { name: 'd' });\n                var vId = this.createNodeSpan(r, r, 'Identifier', { name: 'v' });\n                var rId = this.createNodeSpan(r, r, 'Identifier', { name: 'r' });\n                var __formalsIndexId = this.createNodeSpan(r, r, 'Identifier', { name: '__formalsIndex' + s });\n                var __params = '__params' + s;\n                var __getParam = '__getParam' + s;\n                var __args = '__args' + s;\n                var __paramsFormals = this.createNodeMembIds(r, __params, 'formals');\n                var __paramsKeywords = this.createNodeMembIds(r, __params, 'keywords');\n                var __paramsKeywordsV = this.createNodeSpan(r, r, 'MemberExpression', {\n                    computed: true,\n                    property: vId,\n                    object: __paramsKeywords,\n                });\n                return this.createGeneratedNodeSpan(r, r, 'FunctionDeclaration', {\n                    id: this.createNodeSpan(r, r, 'Identifier', { name: __getParam }),\n                    params: [vId, dId],\n                    defaults: [],\n                    body: this.createNodeSpan(r, r, 'BlockStatement', {\n                        body: [this.createGeneratedVarDeclFromId(r, rId, dId),\n                            this.createGeneratedNodeSpan(r, r, 'IfStatement', {\n                                test: this.createNodeSpan(r, r, 'Identifier', { name: __params }),\n                                consequent: this.createNodeSpan(r, r, 'BlockStatement', {\n                                    body: [this.createGeneratedNodeSpan(r, r, 'IfStatement', {\n                                        test: this.createNodeSpan(r, r, 'BinaryExpression', {\n                                            operator: '<', left: __formalsIndexId,\n                                            right: this.createNodeSpan(r, r, 'MemberExpression', {\n                                                computed: false, object: __paramsFormals,\n                                                property: this.createNodeSpan(r, r, 'Identifier', { name: 'length' }),\n                                            }),\n                                        }),\n                                        consequent: this.createNodeSpan(r, r, 'BlockStatement', {\n                                            body: [this.createGeneratedNodeSpan(r, r, 'ExpressionStatement', {\n                                                expression: this.createGeneratedNodeSpan(r, r, 'AssignmentExpression', {\n                                                    operator: '=', left: rId,\n                                                    right: this.createNodeSpan(r, r, 'MemberExpression', {\n                                                        computed: true, object: __paramsFormals,\n                                                        property: this.createNodeSpan(r, r, 'UpdateExpression', {\n                                                            operator: '++', argument: __formalsIndexId, prefix: false,\n                                                        }),\n                                                    }),\n                                                }),\n                                            })],\n                                        }),\n                                        alternate: this.createGeneratedNodeSpan(r, r, 'IfStatement', {\n                                            test: this.createNodeSpan(r, r, 'BinaryExpression', {\n                                                operator: 'in', left: vId, right: __paramsKeywords,\n                                            }),\n                                            consequent: this.createNodeSpan(r, r, 'BlockStatement', {\n                                                body: [this.createGeneratedNodeSpan(r, r, 'ExpressionStatement', {\n                                                    expression: this.createGeneratedNodeSpan(r, r, 'AssignmentExpression', {\n                                                        operator: '=', left: rId, right: __paramsKeywordsV,\n                                                    }),\n                                                }),\n                                                    this.createGeneratedNodeSpan(r, r, 'ExpressionStatement', {\n                                                        expression: this.createNodeSpan(r, r, 'UnaryExpression', {\n                                                            operator: 'delete',\n                                                            prefix: true,\n                                                            argument: __paramsKeywordsV,\n                                                        }),\n                                                    })],\n                                            }),\n                                            alternate: null,\n                                        }),\n                                    })],\n                                }),\n                                alternate: this.createGeneratedNodeSpan(r, r, 'IfStatement', {\n                                    test: this.createGeneratedNodeSpan(r, r, 'BinaryExpression', {\n                                        operator: '<', left: __formalsIndexId,\n                                        right: this.createNodeMembIds(r, __args, 'length'),\n                                    }),\n                                    consequent: this.createGeneratedNodeSpan(r, r, 'BlockStatement', {\n                                        body: [this.createGeneratedNodeSpan(r, r, 'ExpressionStatement', {\n                                            expression: this.createGeneratedNodeSpan(r, r, 'AssignmentExpression', {\n                                                operator: '=', left: rId,\n                                                right: this.createGeneratedNodeSpan(r, r, 'MemberExpression', {\n                                                    computed: true,\n                                                    object: this.createGeneratedNodeSpan(r, r, 'Identifier', { name: __args }),\n                                                    property: this.createGeneratedNodeSpan(r, r, 'UpdateExpression', {\n                                                        operator: '++', argument: __formalsIndexId, prefix: false,\n                                                    }),\n                                                }),\n                                            }),\n                                        })],\n                                    }),\n                                    alternate: null,\n                                }),\n                            }),\n                            this.createGeneratedNodeSpan(r, r, 'ReturnStatement', { argument: rId })],\n                    }),\n                    rest: null, generator: false, expression: false,\n                });\n            },\n\n            // E.g. pyRuntime.utils.add\n\n            createNodeRuntimeCall: function(r, mod, fn, args) {\n                return this.createNodeSpan(r, r, 'CallExpression', {\n                    callee: this.createNodeSpan(r, r, 'MemberExpression', {\n                        computed: false,\n                        object: this.createNodeMembIds(r, options.runtimeParamName, mod),\n                        property: this.createNodeSpan(r, r, 'Identifier', { name: fn }),\n                    }),\n                    arguments: args,\n                });\n            },\n\n            // Used to convert 'id = init' to 'var id = init'\n\n            createVarDeclFromId: function(refNode, id, init) {\n                var decl = startNodeFrom(refNode);\n                decl.id = id;\n                decl.init = init;\n                this.finishNodeFrom(refNode, decl, 'VariableDeclarator');\n                var declDecl = startNodeFrom(refNode);\n                declDecl.kind = 'var';\n                declDecl.declarations = [decl];\n                return this.finishNodeFrom(refNode, declDecl, 'VariableDeclaration');\n            },\n\n            createGeneratedVarDeclFromId: function(refNode, id, init) {\n                var decl = startNodeFrom(refNode);\n                decl.id = id;\n                decl.init = init;\n                this.finishNodeFrom(refNode, decl, 'VariableDeclarator');\n                var declDecl = startNodeFrom(refNode);\n                declDecl.kind = 'var';\n                declDecl.declarations = [decl];\n                declDecl.userCode = false;\n                return this.finishNodeFrom(refNode, declDecl, 'VariableDeclaration');\n            },\n\n            createClass: function(container, ctorNode, classParams, classBodyRefNode, classBlock) {\n                // Helper to identify class methods which were parsed onto the class prototype\n\n                function getPrototype(stmt) {\n                    if (stmt.expression && stmt.expression.left && stmt.expression.left.object &&\n                        stmt.expression.left.object.property && stmt.expression.left.object.property.name === 'prototype')\n                        return stmt.expression.left.property.name;\n                    return null;\n                }\n\n                // Start building class constructor\n\n                var ctorBlock = startNodeFrom(classBlock);\n                ctorBlock.body = [];\n\n                // Add parent class constructor call\n\n                if (classParams.length === 1) {\n                    var objId = this.createNodeSpan(classBodyRefNode, classBodyRefNode, 'Identifier', { name: classParams[0].name });\n                    var propertyId = this.createNodeSpan(classBodyRefNode, classBodyRefNode, 'Identifier', { name: 'call' });\n                    var calleeMember = this.createNodeSpan(classBodyRefNode, classBodyRefNode, 'MemberExpression', {\n                        object: objId,\n                        property: propertyId,\n                        computed: false,\n                    });\n                    var thisExpr = this.createNodeSpan(classBodyRefNode, classBodyRefNode, 'ThisExpression');\n                    var callExpr = this.createNodeSpan(classBodyRefNode, classBodyRefNode, 'CallExpression', {\n                        callee: calleeMember,\n                        arguments: [thisExpr],\n                    });\n                    var superExpr = this.createNodeSpan(classBodyRefNode, classBodyRefNode, 'ExpressionStatement', { expression: callExpr });\n                    ctorBlock.body.push(superExpr);\n                }\n\n                // Add non-function statements and contents of special '__init__' method\n\n                for (var i in classBlock.body) {\n                    var stmt = classBlock.body[i];\n                    var prototype = getPrototype(stmt);\n                    if (!prototype) {\n                        ctorBlock.body.push(stmt);\n                    }\n                    else if (prototype === '__init__') {\n                        for (var j in stmt.expression.right.body.body)\n                            ctorBlock.body.push(stmt.expression.right.body.body[j]);\n                        ctorNode.params = stmt.expression.right.params;\n                    }\n                }\n\n                // Finish class constructor\n\n                ctorNode.body = finishNode(ctorBlock, 'BlockStatement');\n                finishNode(ctorNode, 'ClassDeclaration');\n                container.body.push(ctorNode);\n\n                // Add inheritance via 'MyClass.prototype = Object.create(ParentClass.prototype)'\n\n                if (classParams.length === 1) {\n                    var childClassId = this.createNodeSpan(ctorNode, ctorNode, 'Identifier', { name: ctorNode.id.name });\n                    var childPrototypeId = this.createNodeSpan(ctorNode, ctorNode, 'Identifier', { name: 'prototype' });\n                    var childPrototypeMember = this.createNodeSpan(ctorNode, ctorNode, 'MemberExpression', {\n                        object: childClassId,\n                        property: childPrototypeId,\n                        computed: false,\n                    });\n                    var parentClassId = this.createNodeSpan(ctorNode, ctorNode, 'Identifier', { name: classParams[0].name });\n                    var parentPrototypeId = this.createNodeSpan(ctorNode, ctorNode, 'Identifier', { name: 'prototype' });\n                    var parentPrototypeMember = this.createNodeSpan(ctorNode, ctorNode, 'MemberExpression', {\n                        object: parentClassId,\n                        property: parentPrototypeId,\n                        computed: false,\n                    });\n                    var objClassId = this.createNodeSpan(ctorNode, ctorNode, 'Identifier', { name: 'Object' });\n                    var objCreateId = this.createNodeSpan(ctorNode, ctorNode, 'Identifier', { name: 'create' });\n                    var objPropertyMember = this.createNodeSpan(ctorNode, ctorNode, 'MemberExpression', {\n                        object: objClassId,\n                        property: objCreateId,\n                        computed: false,\n                    });\n                    var callExpr = this.createNodeSpan(ctorNode, ctorNode, 'CallExpression', {\n                        callee: objPropertyMember,\n                        arguments: [parentPrototypeMember],\n                    });\n                    var assignExpr = this.createNodeSpan(ctorNode, ctorNode, 'AssignmentExpression', {\n                        left: childPrototypeMember,\n                        operator: '=',\n                        right: callExpr,\n                    });\n                    var inheritanceExpr = this.createNodeSpan(ctorNode, ctorNode, 'ExpressionStatement', { expression: assignExpr });\n                    container.body.push(inheritanceExpr);\n                }\n\n                // Add class methods, which are already prototype assignments\n\n                for (var i in classBlock.body) {\n                    var stmt = classBlock.body[i];\n                    var prototype = getPrototype(stmt);\n                    if (prototype && prototype !== '__init__')\n                        container.body.push(stmt);\n                }\n\n                return finishNode(container, 'BlockStatement');\n            },\n\n            // Create for loop\n            //\n            // Problem:\n            // 1. JavaScript for/in loop iterates on properties, which are the indexes for an Array\n            //    Python iterates on the list items themselves, not indexes\n            // 2. JavaScript for/in does not necessarily iterate in order\n            // Solution:\n            // Generate extra AST to do the right thing at runtime\n            // JavaScript for/in is used for dictionaries\n            // If iterating through an ordered sequence, return something like:\n            // { var __right = right;\n            //    if (__right instanceof Array) {\n            //      for(var __index=0; __index < __right.length; __index++) {\n            //        i = __right[__index];\n            //        ...\n            //      }\n            //    } else {\n            //      for(i in __right){...}\n            //    }\n            // }\n            // When the loop target is a Tuple, it is unpacked into each for body in the example above.\n            // E.g. 'for k, v in __right: total += v' becomes:\n            // for (var __tmp in __right) {\n            //    k = __tmp[0];\n            //    v = __tmp[1];\n            //    total += v;\n            // }\n\n            // TODO: for/in on a string should go through items, not indexes. String obj and string literal.\n\n            createFor: function(node, init, tupleArgs, right, body) {\n                var forOrderedBody = body;\n                var forInBody = JSON.parse(JSON.stringify(forOrderedBody));\n\n                var tmpVarSuffix = newAstIdCount++;\n\n                var arrayId = this.createNodeSpan(node, node, 'Identifier', { name: 'Array' });\n                var lengthId = this.createNodeSpan(init, init, 'Identifier', { name: 'length' });\n                var zeroLit = this.createNodeSpan(init, init, 'Literal', { value: 0 });\n\n                // var __rightN = right\n\n                var rightId = this.createNodeSpan(right, right, 'Identifier', { name: '__filbertRight' + tmpVarSuffix });\n                var rightAssign = this.createVarDeclFromId(right, rightId, right);\n\n                // for(;;) and for(in) loops\n\n                var forRightId = this.createNodeSpan(init, init, 'Identifier', { name: '__filbertRight' + tmpVarSuffix });\n\n                // for (var __indexN; __indexN < __rightN.length; ++__indexN)\n\n                var forOrderedIndexId = this.createNodeSpan(init, init, 'Identifier', { name: '__filbertIndex' + tmpVarSuffix });\n                var forOrderedIndexDeclr = this.createNodeSpan(init, init, 'VariableDeclarator', {\n                    id: forOrderedIndexId,\n                    init: zeroLit,\n                });\n                var forOrderedIndexDecln = this.createNodeSpan(init, init, 'VariableDeclaration', {\n                    declarations: [forOrderedIndexDeclr],\n                    kind: 'var',\n                });\n                var forOrderedTestMember = this.createNodeSpan(init, init, 'MemberExpression', {\n                    object: forRightId,\n                    property: lengthId,\n                    computed: false,\n                });\n                var forOrderedTestBinop = this.createNodeSpan(init, init, 'BinaryExpression', {\n                    left: forOrderedIndexId,\n                    operator: '<',\n                    right: forOrderedTestMember,\n                });\n                var forOrderedUpdate = this.createNodeSpan(init, init, 'UpdateExpression', {\n                    operator: '++',\n                    prefix: true,\n                    argument: forOrderedIndexId,\n                });\n                var forOrderedMember = this.createNodeSpan(init, init, 'MemberExpression', {\n                    object: forRightId,\n                    property: forOrderedIndexId,\n                    computed: true,\n                });\n\n                if (tupleArgs) {\n                    var varStmts = unpackTuple(tupleArgs, forOrderedMember);\n                    for (var i = varStmts.length - 1; i >= 0; i--) forOrderedBody.body.unshift(varStmts[i]);\n                }\n                else {\n                    if (init.type === 'Identifier' && !scope.exists(init.name)) {\n                        scope.addVar(init.name);\n                        forOrderedBody.body.unshift(this.createVarDeclFromId(init, init, forOrderedMember));\n                    } else {\n                        var forOrderedInit = this.createNodeSpan(init, init, 'AssignmentExpression', {\n                            operator: '=',\n                            left: init,\n                            right: forOrderedMember,\n                        });\n                        var forOrderedInitStmt = this.createNodeSpan(init, init, 'ExpressionStatement', { expression: forOrderedInit });\n                        forOrderedBody.body.unshift(forOrderedInitStmt);\n                    }\n                }\n\n                var forOrdered = this.createNodeSpan(node, node, 'ForStatement', {\n                    init: forOrderedIndexDecln,\n                    test: forOrderedTestBinop,\n                    update: forOrderedUpdate,\n                    body: forOrderedBody,\n                });\n                var forOrderedBlock = this.createNodeSpan(node, node, 'BlockStatement', { body: [forOrdered] });\n\n                // for (init in __rightN)\n\n                var forInLeft = init;\n                if (tupleArgs) {\n                    var varStmts = unpackTuple(tupleArgs, right);\n                    forInLeft = varStmts[0];\n                    for (var i = varStmts.length - 1; i > 0; i--) forInBody.body.unshift(varStmts[i]);\n                }\n                else if (init.type === 'Identifier' && !scope.exists(init.name)) {\n                    scope.addVar(init.name);\n                    forInLeft = this.createVarDeclFromId(init, init, null);\n                }\n                var forIn = this.createNodeSpan(node, node, 'ForInStatement', {\n                    left: forInLeft,\n                    right: forRightId,\n                    body: forInBody,\n                });\n                var forInBlock = this.createNodeSpan(node, node, 'BlockStatement', { body: [forIn] });\n\n                // if ordered sequence then forOrdered else forIn\n\n                var ifRightId = this.createNodeSpan(node, node, 'Identifier', { name: '__filbertRight' + tmpVarSuffix });\n                var ifTest = this.createNodeSpan(node, node, 'BinaryExpression', {\n                    left: ifRightId,\n                    operator: 'instanceof',\n                    right: arrayId,\n                });\n                var ifStmt = this.createNodeSpan(node, node, 'IfStatement', {\n                    test: ifTest,\n                    consequent: forOrderedBlock,\n                    alternate: forInBlock,\n                });\n\n                node.body = [rightAssign, ifStmt];\n\n                return node;\n            },\n\n            // expr => __tmpList.push(expr);\n\n            createListCompPush: function(expr, tmpVarSuffix) {\n                var exprPushTmpListId = this.createNodeSpan(expr, expr, 'Identifier', { name: '__tmpList' + tmpVarSuffix });\n                var exprPushId = this.createNodeSpan(expr, expr, 'Identifier', { name: 'push' });\n                var exprMember = this.createNodeSpan(expr, expr, 'MemberExpression', {\n                    object: exprPushTmpListId,\n                    property: exprPushId,\n                    computed: false,\n                });\n                var exprCall = this.createNodeSpan(expr, expr, 'CallExpression', {\n                    callee: exprMember,\n                    arguments: [expr],\n                });\n                return this.createNodeSpan(expr, expr, 'ExpressionStatement', { expression: exprCall });\n            },\n\n            //  (function() {\n            //    var _list = [];\n            //    ...\n            //    body\n            //    return _list;\n            //  }());\n\n            createListCompIife: function(node, body, tmpVarSuffix) {\n                var iifeRuntimeId = this.createNodeSpan(node, node, 'Identifier', { name: options.runtimeParamName });\n                var iifeObjectsId = this.createNodeSpan(node, node, 'Identifier', { name: 'objects' });\n                var iifeObjMember = this.createNodeSpan(node, node, 'MemberExpression', {\n                    object: iifeRuntimeId,\n                    property: iifeObjectsId,\n                    computed: false,\n                });\n                var iifeListId = this.createNodeSpan(node, node, 'Identifier', { name: 'list' });\n                var iifeListMember = this.createNodeSpan(node, node, 'MemberExpression', {\n                    object: iifeObjMember,\n                    property: iifeListId,\n                    computed: false,\n                });\n                var iifeNewExpr = this.createNodeSpan(node, node, 'NewExpression', {\n                    callee: iifeListMember,\n                    arguments: [],\n                });\n                var iifeListId = this.createNodeSpan(node, node, 'Identifier', { name: '__tmpList' + tmpVarSuffix });\n                var iifeListDecl = this.createVarDeclFromId(node, iifeListId, iifeNewExpr);\n\n                var iifeReturnListId = this.createNodeSpan(node, node, 'Identifier', { name: '__tmpList' + tmpVarSuffix });\n                var iifeReturn = this.createNodeSpan(node, node, 'ReturnStatement', { argument: iifeReturnListId });\n\n                var iifeBlock = this.createNodeSpan(node, node, 'BlockStatement', { body: [iifeListDecl, body, iifeReturn] });\n                var fnExpr = this.createNodeSpan(node, node, 'FunctionExpression', {\n                    params: [],\n                    defaults: [],\n                    body: iifeBlock,\n                    generator: false,\n                    expression: false,\n                });\n\n                return this.createNodeSpan(node, node, 'CallExpression', { callee: fnExpr, arguments: [] });\n            },\n        };\n    };\n\n    // Predicate that tests whether the next token is of the given\n    // type, and if yes, consumes it as a side effect.\n\n    function eat(type) {\n        if (tokType === type) {\n            next();\n            return true;\n        }\n    }\n\n    // Expect a token of a given type. If found, consume it, otherwise,\n    // raise an unexpected token error.\n\n    function expect(type) {\n        if (tokType === type) next();\n        else {\n            var args = Array.prototype.slice.call(arguments);\n            if (args.length > 1)\n                unexpected({\n                    type: args.map(function(t) {\n                        return t.type;\n                    }),\n                });\n            else\n                unexpected(type);\n        }\n    }\n\n    // Raise an unexpected token error.\n\n    function unexpected(expectedType) {\n        raise(tokStart, 'Unexpected token',\n            tokType && tokType.type, expectedType && expectedType.type);\n    }\n\n    // Verify that a node is an lval - somethin g that can be assigned\n    // to.\n\n    function checkLVal(expr) {\n        if (expr.type !== 'Identifier' && expr.type !== 'MemberExpression')\n            raise(expr.start, 'Assigning to rvalue');\n        if (strict && expr.type === 'Identifier' && isStrictBadIdWord(expr.name))\n            raise(expr.start, 'Assigning to ' + expr.name + ' in strict mode');\n    }\n\n    // Get args for a new tuple expression\n\n    function getTupleArgs(expr) {\n        if (expr.callee && expr.callee.object && expr.callee.object.object &&\n            expr.callee.object.object.name === options.runtimeParamName &&\n            expr.callee.property && expr.callee.property.name === 'tuple')\n            return expr.arguments;\n        return null;\n    }\n\n    // Unpack an lvalue tuple into indivual variable assignments\n    // 'arg0, arg1 = right' becomes:\n    // var tmp = right\n    // arg0 = tmp[0]\n    // arg1 = tmp[1]\n    // ...\n\n    function unpackTuple(tupleArgs, right) {\n        if (!tupleArgs || tupleArgs.length < 1) unexpected();\n\n        var varStmts = [];\n\n        // var tmp = right\n\n        var tmpId = nc.createNodeSpan(right, right, 'Identifier', { name: '__filbertTmp' + newAstIdCount++ });\n        var tmpDecl = nc.createVarDeclFromId(right, tmpId, right);\n        varStmts.push(tmpDecl);\n\n        // argN = tmp[N]\n\n        for (var i = 0; i < tupleArgs.length; i++) {\n            var lval = tupleArgs[i];\n            var subTupleArgs = getTupleArgs(lval);\n            if (subTupleArgs) {\n                var subLit = nc.createNodeSpan(right, right, 'Literal', { value: i });\n                var subRight = nc.createNodeSpan(right, right, 'MemberExpression', {\n                    object: tmpId,\n                    property: subLit,\n                    computed: true,\n                });\n                var subStmts = unpackTuple(subTupleArgs, subRight);\n                for (var j = 0; j < subStmts.length; j++) varStmts.push(subStmts[j]);\n            } else {\n                checkLVal(lval);\n                var indexId = nc.createNodeSpan(right, right, 'Literal', { value: i });\n                var init = nc.createNodeSpan(right, right, 'MemberExpression', {\n                    object: tmpId,\n                    property: indexId,\n                    computed: true,\n                });\n                if (lval.type === 'Identifier' && !scope.exists(lval.name)) {\n                    scope.addVar(lval.name);\n                    var varDecl = nc.createVarDeclFromId(lval, lval, init);\n                    varStmts.push(varDecl);\n                }\n                else {\n                    var node = startNodeFrom(lval);\n                    node.left = lval;\n                    node.operator = '=';\n                    node.right = init;\n                    finishNode(node, 'AssignmentExpression');\n                    varStmts.push(nc.createNodeFrom(node, 'ExpressionStatement', { expression: node }));\n                }\n            }\n        }\n\n        return varStmts;\n    }\n\n    // ### Statement parsing\n\n    // Parse a program. Initializes the parser, reads any number of\n    // statements, and wraps them in a Program node.  Optionally takes a\n    // `program` argument.  If present, the statements will be appended\n    // to its body instead of creating a new node.\n\n    function parseTopLevel(program) {\n        lastStart = lastEnd = tokPos;\n        if (options.locations) lastEndLoc = new Position;\n        inFunction = strict = null;\n        bracketNesting = 0;\n        readToken();\n        var node = program || startNode();\n        if (!program) node.body = [];\n        while (tokType !== _eof) {\n            var stmt = parseStatement();\n            if (stmt) node.body.push(stmt);\n        }\n        return finishNode(node, 'Program');\n    }\n\n    // Parse a single statement.\n    //\n    // If expecting a statement and finding a slash operator, parse a\n    // regular expression literal. This is to handle cases like\n    // `if (foo) /blah/.exec(foo);`, where looking at the previous token\n    // does not help.\n\n    function parseStatement() {\n        if (tokType === _slash || tokType === _assign && tokVal == '/=')\n            readToken(true);\n\n        var starttype = tokType, node = startNode();\n\n        // Most types of statements are recognized by the keyword they\n        // start with. Many are trivial to parse, some require a bit of\n        // complexity.\n\n        switch (starttype) {\n\n            case _break:\n                next();\n                return finishNode(node, 'BreakStatement');\n\n            case _continue:\n                next();\n                return finishNode(node, 'ContinueStatement');\n\n            case _class:\n                next();\n                return parseClass(node);\n\n            case _def:\n                next();\n                return parseFunction(node);\n\n            case _for:\n                next();\n                return parseFor(node);\n\n            case _from: // Skipping from and import statements for now\n                skipLine();\n                next();\n                return parseStatement();\n\n            case _if:\n            case _elif:\n                next();\n                if (tokType === _parenL) node.test = parseParenExpression();\n                else node.test = parseExpression();\n                expect(_colon);\n                node.consequent = parseSuite();\n                if (tokType === _elif)\n                    node.alternate = parseStatement();\n                else\n                    node.alternate = eat(_else) && eat(_colon) ? parseSuite() : null;\n                return finishNode(node, 'IfStatement');\n\n            case _import: // Skipping from and import statements for now\n                skipLine();\n                next();\n                return parseStatement();\n\n            case _newline:\n                // TODO: parseStatement() should probably eat it's own newline\n                next();\n                return null;\n\n            case _pass:\n                next();\n                return finishNode(node, 'EmptyStatement');\n\n            case _return:\n                if (!inFunction && !options.allowReturnOutsideFunction)\n                    raise(tokStart, '\\'return\\' outside of function');\n                next();\n                if (tokType === _newline || tokType === _eof) node.argument = null;\n                else {\n                    node.argument = parseExpression();\n                }\n                return finishNode(node, 'ReturnStatement');\n\n            case _try: // TODO, and remove parseBlock\n                next();\n                node.block = parseBlock();\n                node.handler = null;\n                if (tokType === _catch) {\n                    var clause = startNode();\n                    next();\n                    expect(_parenL);\n                    clause.param = parseIdent();\n                    if (strict && isStrictBadIdWord(clause.param.name))\n                        raise(clause.param.start, 'Binding ' + clause.param.name + ' in strict mode');\n                    expect(_parenR);\n                    clause.guard = null;\n                    clause.body = parseBlock();\n                    node.handler = finishNode(clause, 'CatchClause');\n                }\n                node.guardedHandlers = empty;\n                node.finalizer = eat(_finally) ? parseBlock() : null;\n                if (!node.handler && !node.finalizer)\n                    raise(node.start, 'Missing catch or finally clause');\n                return finishNode(node, 'TryStatement');\n\n            case _while:\n                next();\n                if (tokType === _parenL) node.test = parseParenExpression();\n                else node.test = parseExpression();\n                expect(_colon);\n                node.body = parseSuite();\n                return finishNode(node, 'WhileStatement');\n\n            case _with: // TODO\n                if (strict) raise(tokStart, '\\'with\\' in strict mode');\n                next();\n                node.object = parseParenExpression();\n                node.body = parseStatement();\n                return finishNode(node, 'WithStatement');\n\n            case _semi:\n                next();\n                return finishNode(node, 'EmptyStatement');\n\n            case _comment:\n                node.value = tokVal;\n                next();\n                return finishNode(node, 'Comment');\n            // Assume it's an ExpressionStatement. If an assign has been\n            // converted to a variable declaration, pass it up as is.\n\n            default:\n                var expr = parseExpression();\n                if (tokType !== _semi && tokType !== _newline && tokType !== _eof) unexpected();\n                if (expr.type === 'VariableDeclaration' || expr.type === 'BlockStatement') {\n                    return expr;\n                } else {\n                    node.expression = expr;\n                    return finishNode(node, 'ExpressionStatement');\n                }\n        }\n    }\n\n    // Parse indent-enclosed block of statements\n\n    function parseBlock() {\n        var node = startNode();\n        node.body = [];\n        while (tokType !== _dedent && tokType !== _eof) {\n            var stmt = parseStatement();\n            if (stmt) node.body.push(stmt);\n        }\n        if (tokType === _dedent) next();\n        return finishNode(node, 'BlockStatement');\n    }\n\n    // Parse 'suite' from Python grammar spec\n    // Will replace parseBlock eventually\n\n    function parseSuite() {\n        // NOTE: This is not strictly valid Python for this to be an empty block\n        var node = startNode();\n        node.body = [];\n\n        if (tokType === _comment) {\n            node.comment = { value: tokVal };\n            next();\n        }\n        if (eat(_newline)) {\n            if (tokType === _indent) {\n                expect(_indent);\n                while (!eat(_dedent) && !eat(_eof)) {\n                    var stmt = parseStatement();\n                    if (stmt) node.body.push(stmt);\n                }\n            }\n        } else if (tokType !== _eof) {\n            node.body.push(parseStatement());\n            next();\n        }\n        return finishNode(node, 'BlockStatement');\n    }\n\n    // Parse for/in loop\n\n    function parseFor(node) {\n        var init = parseExpression(false, true);\n        var tupleArgs = getTupleArgs(init);\n        if (!tupleArgs) checkLVal(init);\n        expect(_in);\n        var right = parseExpression();\n        expect(_colon);\n        var body = parseSuite();\n        finishNode(node, 'BlockStatement');\n        return nc.createFor(node, init, tupleArgs, right, body);\n    }\n\n    // ### Expression parsing\n\n    // These nest, from the most general expression type at the top to\n    // 'atomic', nondivisible expression types at the bottom. Most of\n    // the functions will simply let the function(s) below them parse,\n    // and, *if* the syntactic construct they handle is present, wrap\n    // the AST node that the inner parser gave them in another node.\n\n    // Parse a full expression. The arguments are used to forbid comma\n    // sequences (in argument lists, array literals, or object literals)\n    // or the `in` operator (in for loops initalization expressions).\n\n    function parseExpression(noComma, noIn) {\n        return parseMaybeAssign(noIn);\n    }\n\n    // Used for constructs like `switch` and `if` that insist on\n    // parentheses around their expression.\n\n    function parseParenExpression() {\n        expect(_parenL);\n        var val = parseExpression();\n        expect(_parenR);\n        return val;\n    }\n\n    // Parse an assignment expression. This includes applications of\n    // operators like `+=`.\n    // Add 'this.' to assignments in a class constructor.\n    // Convert identifier assignment to variable declaration if the\n    // identifier doesn't exist in this namespace yet.\n\n    function parseMaybeAssign(noIn) {\n        var left = parseMaybeTuple(noIn);\n        if (!tokType.isAssign)\n            return left;\n        var node;\n        while (tokType.isAssign) {\n            if (!node) {\n                var tupleArgs = getTupleArgs(left);\n                if (tupleArgs) {\n                    next();\n                    var right = parseMaybeTuple(noIn);\n                    var blockNode = startNodeFrom(left);\n                    blockNode.body = unpackTuple(tupleArgs, right);\n                    return finishNode(blockNode, 'BlockStatement');\n                }\n\n                if (scope.isClass()) {\n                    var thisExpr = nc.createNodeFrom(left, 'ThisExpression');\n                    left = nc.createNodeFrom(left, 'MemberExpression', { object: thisExpr, property: left });\n                }\n\n                node = startNodeFrom(left);\n                node.operator = tokVal;\n                checkLVal(left);\n                node.left = left;\n            }\n\n            if (node.right) {\n                if (!node.left.length)\n                    node.left = [node.left];\n                node.left.push(node.right);\n                left = node.right;\n            }\n\n            next();\n            node.right = parseMaybeTuple(noIn);\n\n            if (left.type === 'Identifier' && !scope.exists(left.name)) {\n                if (!node.operator || node.length > 1) unexpected();\n                scope.addVar(left.name);\n                // return nc.createVarDeclFromId(node.left, node.left, node.right);\n                // customized variable must be assign\n            }\n        }\n        return finishNode(node, 'AssignmentExpression');\n    }\n\n    // Parse a tuple\n\n    function parseMaybeTuple(noIn) {\n        var expr = parseExprOps(noIn);\n        if (tokType === _comma) {\n            return parseTuple(noIn, expr);\n        }\n        return expr;\n    }\n\n    // Start the precedence parser.\n\n    function parseExprOps(noIn) {\n        return parseExprOp(parseMaybeUnary(noIn), -1, noIn);\n    }\n\n    // Parse binary operators with the operator precedence parsing\n    // algorithm. `left` is the left-hand side of the operator.\n    // `minPrec` provides context that allows the function to stop and\n    // defer further parser to one of its callers when it encounters an\n    // operator that has a lower precedence than the set it is parsing.\n    // Exponentiation is evaluated right-to-left, so 'prec >= minPrec'\n    // Exponentiation operator 'x**y' is replaced with 'Math.pow(x, y)'\n    // Floor division operator 'x//y' is replaced with 'Math.floor(x/y)'\n    // 'in' and 'not in' implemented via indexOf()\n\n    function parseExprOp(left, minPrec, noIn) {\n        var node, exprNode, right, op = tokType, val = tokVal;\n        var prec = op === _not ? _in.prec : op.prec;\n        if (false) {\n            node = startNodeFrom(left);\n            next();\n            right = parseExprOp(parseMaybeUnary(noIn), prec, noIn);\n            exprNode = nc.createNodeMemberCall(node, 'math', 'pow', [left, right]);\n            return parseExprOp(exprNode, minPrec, noIn);\n        } else if (prec != null && (!noIn || op !== _in)) {\n            if (prec > minPrec) {\n                next();\n                node = startNodeFrom(left);\n                if (op === _floorDiv) {\n                    right = parseExprOp(parseMaybeUnary(noIn), prec, noIn);\n                    finishNode(node);\n                    exprNode = nc.createNodeSpan(node, node, 'BinaryExpression', {\n                        left: left,\n                        operator: '//',\n                        right: right,\n                    });\n                } else if (op === _in || op === _not) {\n                    if (op === _in || eat(_in)) {\n                        right = parseExprOp(parseMaybeUnary(noIn), prec, noIn);\n                        finishNode(node);\n                        var notLit = nc.createNodeSpan(node, node, 'Literal', { value: op === _not });\n                        exprNode = nc.createNodeRuntimeCall(node, 'ops', 'in', [left, right, notLit]);\n                    } else raise(tokPos, 'Expected \\'not in\\' comparison operator');\n                } else {\n                    if (op === _is) {\n                        if (eat(_not)) node.operator = '!==';\n                        else node.operator = '===';\n                    } else node.operator = op.rep != null ? op.rep : val;\n                    node.left = left;\n                    node.right = parseExprOp(parseMaybeUnary(noIn), prec, noIn);\n                    exprNode = finishNode(node, (op === _or || op === _and) ? 'LogicalExpression' : 'BinaryExpression');\n                }\n                return parseExprOp(exprNode, minPrec, noIn);\n            }\n        }\n        return left;\n    }\n\n    // Parse unary operators.\n    // '-+' are prefixes here, with different precedence.\n\n    function parseMaybeUnary(noIn) {\n        if (tokType.prefix || tokType === _plusMin) {\n            var prec = tokType === _plusMin ? _posNegNot.prec : tokType.prec;\n            var node = startNode();\n            node.operator = tokType.rep != null ? tokType.rep : tokVal;\n            node.prefix = true;\n            tokRegexpAllowed = true;\n            next();\n            node.argument = parseExprOp(parseMaybeUnary(noIn), prec, noIn);\n            return finishNode(node, 'UnaryExpression');\n        }\n        return parseSubscripts(parseExprAtom());\n    }\n\n    // Parse call, dot, and `[]`-subscript expressions.\n\n    function parseSubscripts(base, noCalls) {\n        var node = startNodeFrom(base);\n        if (eat(_dot)) {\n            var id = parseIdent(true);\n            if (pythonRuntime.imports[base.name] && pythonRuntime.imports[base.name][id.name]) {\n                // Calling a Python import function\n                // TODO: Unpack parameters into JavaScript-friendly parameters\n                var runtimeId = nc.createNodeSpan(base, base, 'Identifier', { name: options.runtimeParamName });\n                var importsId = nc.createNodeSpan(base, base, 'Identifier', { name: 'imports' });\n                var runtimeMember = nc.createNodeSpan(base, base, 'MemberExpression', {\n                    object: runtimeId,\n                    property: importsId,\n                    computed: false,\n                });\n                node.object = nc.createNodeSpan(base, base, 'MemberExpression', {\n                    object: runtimeMember,\n                    property: base,\n                    computed: false,\n                });\n            } else if (base.name && base.name === scope.getThisReplace()) {\n                node.object = nc.createNodeSpan(base, base, 'ThisExpression');\n            } else node.object = base;\n            node.property = id;\n            node.computed = false;\n            return parseSubscripts(finishNode(node, 'MemberExpression'), noCalls);\n        } else if (eat(_bracketL)) {\n            var expr, isSlice = false;\n            if (eat(_colon)) isSlice = true;\n            else expr = parseExpression();\n            if (!isSlice && eat(_colon)) isSlice = true;\n            if (isSlice) return parseSlice(node, base, expr, noCalls);\n            var subscriptCall = nc.createNodeSpan(expr, expr, 'CallExpression');\n            subscriptCall.callee = nc.createNodeOpsCallee(expr, 'subscriptIndex');\n            subscriptCall.arguments = [base, expr];\n            node.object = base;\n            node.property = subscriptCall;\n            node.computed = true;\n            expect(_bracketR);\n            return parseSubscripts(finishNode(node, 'MemberExpression'), noCalls);\n        } else if (!noCalls && eat(_parenL)) {\n            node.arguments = parseExprList(_parenR, false);\n            if (scope.isNewObj(base.name)) finishNode(node, 'NewExpression');\n            else finishNode(node, 'CallExpression');\n            if (pythonRuntime.functions[base.name]) {\n                // Calling a Python built-in function\n                // TODO: Unpack parameters into JavaScript-friendly parameters\n                if (base.type !== 'Identifier') unexpected();\n                var runtimeId = nc.createNodeSpan(base, base, 'Identifier', { name: options.runtimeParamName });\n                var functionsId = nc.createNodeSpan(base, base, 'Identifier', { name: 'functions' });\n                var runtimeMember = nc.createNodeSpan(base, base, 'MemberExpression', {\n                    object: runtimeId,\n                    property: functionsId,\n                    computed: false,\n                });\n                node.callee = nc.createNodeSpan(base, base, 'MemberExpression', {\n                    object: runtimeMember,\n                    property: base,\n                    computed: false,\n                });\n            } else node.callee = base;\n            if (tokType === _comment) {\n                node.comment = { value: tokVal };\n                next();\n            }\n            return parseSubscripts(node, noCalls);\n        }\n        return base;\n    }\n\n    function parseSlice(node, base, start, noCalls) {\n        var end, step;\n        if (!start) start = nc.createNodeFrom(node, 'Literal', { value: null });\n        if (tokType === _bracketR || eat(_colon)) {\n            end = nc.createNodeFrom(node, 'Literal', { value: null });\n        } else {\n            end = parseExpression();\n            if (tokType !== _bracketR) expect(_colon);\n        }\n        if (tokType === _bracketR) step = nc.createNodeFrom(node, 'Literal', { value: null });\n        else step = parseExpression();\n        expect(_bracketR);\n\n        node.arguments = [start, end, step];\n        var sliceId = nc.createNodeFrom(base, 'Identifier', { name: '_pySlice' });\n        var memberExpr = nc.createNodeSpan(base, base, 'MemberExpression', {\n            object: base,\n            property: sliceId,\n            computed: false,\n        });\n        node.callee = memberExpr;\n        return parseSubscripts(finishNode(node, 'CallExpression'), noCalls);\n    }\n\n    // Parse an atomic expression - either a single token that is an\n    // expression, an expression started by a keyword like `function` or\n    // `new`, or an expression wrapped in punctuation like `()`, `[]`,\n    // or `{}`.\n\n    function parseExprAtom() {\n        switch (tokType) {\n\n            case _dict:\n                next();\n                return parseDict(_parenR);\n\n            case _name:\n                return parseIdent();\n\n            case _num:\n            case _string:\n            case _regexp:\n                var node = startNode();\n                node.value = tokVal;\n                node.raw = input.slice(tokStart, tokEnd);\n                next();\n                return finishNode(node, 'Literal');\n\n            case _none:\n            case _true:\n            case _false:\n                var node = startNode();\n                node.value = tokType.atomValue;\n                node.raw = tokType.keyword;\n                next();\n                return finishNode(node, 'Literal');\n\n            case _parenL:\n                var tokStartLoc1 = tokStartLoc, tokStart1 = tokStart;\n                next();\n                if (tokType === _parenR) {\n                    // Empty tuple\n                    var node = parseTuple(false);\n                    eat(_parenR);\n                    return node;\n                }\n                var val = parseMaybeTuple(false);\n                if (options.locations) {\n                    val.loc.start = tokStartLoc1;\n                    val.loc.end = tokEndLoc;\n                }\n                if (options.ranges)\n                    val.range = [tokStart1, tokEnd];\n                expect(_parenR);\n                return val;\n\n            case _bracketL:\n                return parseList();\n\n            case _braceL:\n                return parseDict(_braceR);\n\n            case _indent:\n                raise(tokStart, 'Unexpected indent');\n\n            default:\n                unexpected();\n        }\n    }\n\n    // Parse list\n\n    // Custom list object is used to simulate native Python list\n    // E.g. Python '[]' becomes JavaScript 'new __pythonRuntime.objects.list();'\n    // If list comprehension, build something like this:\n    //(function() {\n    //  var _list = [];\n    //  ...\n    //  _list.push(expr);\n    //  return _list;\n    //}());\n\n    function parseList() {\n        var node = startNode();\n        node.arguments = [];\n        next();\n\n        if (!eat(_bracketR)) {\n            var expr = parseExprOps(false);\n            if (tokType === _for || tokType === _if) {\n\n                // List comprehension\n                var tmpVarSuffix = newAstIdCount++;\n                expr = nc.createListCompPush(expr, tmpVarSuffix);\n                var body = parseCompIter(expr, true);\n                finishNode(node);\n                return nc.createListCompIife(node, body, tmpVarSuffix);\n\n            } else if (eat(_comma)) {\n                node.arguments = [expr].concat(parseExprList(_bracketR, true, false));\n            }\n            else {\n                expect(_bracketR);\n                node.arguments = [expr];\n            }\n        }\n\n        finishNode(node, 'NewExpression');\n        var runtimeId = nc.createNodeSpan(node, node, 'Identifier', { name: options.runtimeParamName });\n        var objectsId = nc.createNodeSpan(node, node, 'Identifier', { name: 'objects' });\n        var runtimeMember = nc.createNodeSpan(node, node, 'MemberExpression', {\n            object: runtimeId,\n            property: objectsId,\n            computed: false,\n        });\n        var listId = nc.createNodeSpan(node, node, 'Identifier', { name: 'list' });\n        node.callee = nc.createNodeSpan(node, node, 'MemberExpression', {\n            object: runtimeMember,\n            property: listId,\n            computed: false,\n        });\n        return node;\n    }\n\n    // Parse a comp_iter from Python language grammar\n    // Used to build list comprehensions\n    // 'expr' is the body to be used after unrolling the ifs and fors\n\n    function parseCompIter(expr, first) {\n        if (first && tokType !== _for) unexpected();\n        if (eat(_bracketR)) return expr;\n        var node = startNode();\n        if (eat(_for)) {\n            var init = parseExpression(false, true);\n            var tupleArgs = getTupleArgs(init);\n            if (!tupleArgs) checkLVal(init);\n            expect(_in);\n            var right = parseExpression();\n            var body = parseCompIter(expr, false);\n            var block = nc.createNodeSpan(body, body, 'BlockStatement', { body: [body] });\n            finishNode(node, 'BlockStatement');\n            return nc.createFor(node, init, tupleArgs, right, block);\n        } else if (eat(_if)) {\n            if (tokType === _parenL) node.test = parseParenExpression();\n            else node.test = parseExpression();\n            node.consequent = parseCompIter(expr, false);\n            return finishNode(node, 'IfStatement');\n        } else unexpected();\n    }\n\n    // Parse class\n\n    function parseClass(ctorNode) {\n        // Container for class constructor and prototype functions\n        var container = startNodeFrom(ctorNode);\n        container.body = [];\n\n        // Parse class signature\n        ctorNode.id = parseIdent();\n        ctorNode.params = [];\n        var classParams = [];\n        if (eat(_parenL)) {\n            var first = true;\n            while (!eat(_parenR)) {\n                if (!first) expect(_comma); else first = false;\n                classParams.push(parseIdent());\n            }\n        }\n        if (classParams.length > 1) raise(tokPos, 'Multiple inheritance not supported');\n        expect(_colon);\n\n        // Start new namespace for class body\n        scope.startClass(ctorNode.id.name);\n\n        // Save a reference for source ranges\n        var classBodyRefNode = finishNode(startNode());\n\n        // Parse class body\n        var classBlock = parseSuite();\n\n        // Generate additional AST to implement class\n        var classStmt = nc.createClass(container, ctorNode, classParams, classBodyRefNode, classBlock);\n\n        scope.end();\n\n        return classStmt;\n    }\n\n    // Parse dictionary\n    // Custom dict object used to simulate native Python dict\n    // E.g. \"{'k1':'v1', 'k2':'v2'}\" becomes \"new __pythonRuntime.objects.dict(['k1', 'v1'], ['k2', 'v2']);\"\n\n    function parseDict(tokClose) {\n        var node = startNode(), first = true, key, value;\n        node.arguments = [];\n        next();\n        while (!eat(tokClose)) {\n            if (!first) {\n                expect(_comma);\n            } else first = false;\n\n            if (tokClose === _braceR) {\n                key = parsePropertyName();\n                expect(_colon);\n                value = parseExprOps(false);\n            } else if (tokClose === _parenR) {\n                var keyId = parseIdent(true);\n                key = startNodeFrom(keyId);\n                key.value = keyId.name;\n                finishNode(key, 'Literal');\n                expect(_eq);\n                value = parseExprOps(false);\n            } else unexpected();\n            node.arguments.push(nc.createNodeSpan(key, value, 'ArrayExpression', { elements: [key, value] }));\n        }\n        finishNode(node, 'NewExpression');\n\n        var runtimeId = nc.createNodeSpan(node, node, 'Identifier', { name: options.runtimeParamName });\n        var objectsId = nc.createNodeSpan(node, node, 'Identifier', { name: 'objects' });\n        var runtimeMember = nc.createNodeSpan(node, node, 'MemberExpression', {\n            object: runtimeId,\n            property: objectsId,\n            computed: false,\n        });\n        var listId = nc.createNodeSpan(node, node, 'Identifier', { name: 'dict' });\n        node.callee = nc.createNodeSpan(node, node, 'MemberExpression', {\n            object: runtimeMember,\n            property: listId,\n            computed: false,\n        });\n\n        return node;\n    }\n\n    function parsePropertyName() {\n        if (tokType === _num || tokType === _string) return parseExprAtom();\n        return parseIdent(true);\n    }\n\n    function parseFunction(node) {\n        // TODO: The node creation utilities used here are tightly coupled (e.g. variable names)\n\n        var suffix = newAstIdCount++;\n        node.id = parseIdent();\n        node.params = [];\n\n        // Parse parameters\n\n        var formals = [];     // In order, maybe with default value\n        var argsId = null;    // *args\n        var kwargsId = null;  // **kwargs\n        var defaultsFound = false;\n        var first = true;\n        expect(_parenL);\n        while (!eat(_parenR)) {\n            if (!first) expect(_comma); else first = false;\n            if (tokVal === '*') {\n                if (kwargsId) raise(tokPos, 'invalid syntax');\n                next();\n                argsId = parseIdent();\n            } else if (tokVal === '**') {\n                next();\n                kwargsId = parseIdent();\n            } else {\n                if (kwargsId) raise(tokPos, 'invalid syntax');\n                var paramId = parseIdent(null, true);\n                if (eat(_eq)) {\n                    formals.push({ id: paramId, expr: parseExprOps(false) });\n                    defaultsFound = true;\n                } else {\n                    if (defaultsFound) raise(tokPos, 'non-default argument follows default argument');\n                    if (argsId) raise(tokPos, 'missing required keyword-only argument');\n                    formals.push({ id: paramId, expr: null });\n                }\n            }\n        }\n        expect(_colon);\n\n        // Start a new scope with regard to the `inFunction`\n        // flag (restore them to their old value afterwards).\n        // `inFunction` used to throw syntax error for stray `return`\n        var oldInFunc = inFunction = true;\n\n        scope.startFn(node.id.name);\n\n        // If class method, remove class instance var from params and save for 'this' replacement\n        if (scope.isParentClass()) {\n            var selfId = formals.shift();\n            scope.setThisReplace(selfId.id.name);\n        }\n\n        var body = parseSuite();\n        node.body = nc.createNodeSpan(body, body, 'BlockStatement', { body: [] });\n\n        // Add runtime parameter processing\n        // The caller may pass a complex parameter object as a single parameter like this:\n        // {formals:[<expr>, <expr>, ...], keywords:{<id>:<expr>, <id>:<expr>, ...}}\n\n        /*\n    if (formals.length > 0 || argsId || kwargsId) {\n      // var __params = arguments.length === 1 && arguments[0].formals && arguments[0].keywords ? arguments[0] : null;\n      node.body.body.push(nc.createNodeParamsCheck(node.id, suffix));\n\n      // var __formalsIndex = 0;\n      node.body.body.push(nc.createGeneratedVarDeclFromId(node.id,\n        nc.createNodeSpan(node.id, node.id, \"Identifier\", { name: '__formalsIndex' + suffix }),\n        nc.createNodeSpan(node.id, node.id, \"Literal\", { value: 0 })));\n\n      // var __args = arguments;\n      node.body.body.push(nc.createGeneratedVarDeclFromId(node.id,\n        nc.createNodeSpan(node.id, node.id, \"Identifier\", { name: '__args' + suffix }),\n        nc.createNodeSpan(node.id, node.id, \"Identifier\", { name: 'arguments' })));\n    }\n    */\n\n        if (formals.length > 0) {\n            // function __getParam(v, d) {\n            //   var r = d;\n            //   if (__params) {\n            //     if (__formalsIndex < __params.formals.length) {\n            //       r = __params.formals[__formalsIndex++];\n            //     } else if (v in __params.keywords) {\n            //       r = __params.keywords[v];\n            //       delete __params.keywords[v];\n            //     }\n            //   } else if (__formalsIndex < __args.length) {\n            //     r = __args[__formalsIndex++];\n            //   }\n            //   return r;\n            // }\n            //node.body.body.push(nc.createNodeGetParamFn(node.id, suffix));\n\n            node.arguments = [];\n            for (var i = 0; i < formals.length; i++) {\n                // var <param> = __getParam('<param>', <optional default>);\n                node.arguments.push(nc.createNodeSpan(formals[i].id, formals[i].id, 'Identifier', { name: formals[i].id.name }));\n            }\n        }\n\n        var refNode = argsId || kwargsId;\n        if (refNode) {\n            if (argsId) {\n                // var <args> = [];\n                var argsAssign = nc.createGeneratedVarDeclFromId(argsId, argsId, nc.createNodeSpan(argsId, argsId, 'ArrayExpression', { elements: [] }));\n                node.body.body.push(argsAssign);\n            }\n            if (kwargsId) {\n                // var <kwargs> = {};\n                var kwargsAssign = nc.createGeneratedVarDeclFromId(kwargsId, kwargsId, nc.createNodeSpan(kwargsId, kwargsId, 'ObjectExpression', { properties: [] }));\n                node.body.body.push(kwargsAssign);\n            }\n            // if (__params) {}\n            var argsIf = nc.createNodeSpan(refNode, refNode, 'IfStatement', {\n                test: nc.createNodeSpan(refNode, refNode, 'Identifier', { name: '__params' + suffix }),\n                consequent: nc.createNodeSpan(refNode, refNode, 'BlockStatement', { body: [] }),\n            });\n            if (argsId) {\n                // while (__formalsIndex < __params.formals.length) {\n                //   <argsId>.push(__params.formals[__formalsIndex++]); }\n                argsIf.consequent.body.push(nc.createNodeArgsWhileConsequent(argsId, suffix));\n                // { while (__formalsIndex < __args.length) {\n                //   <argsId>.push(__args[__formalsIndex++]); }}\n                argsIf.alternate = nc.createNodeArgsAlternate(argsId, suffix);\n            }\n            if (kwargsId) {\n                // <kwargs> = __params.keywords\n                argsIf.consequent.body.push(nc.createNodeSpan(kwargsId, kwargsId, 'ExpressionStatement', {\n                    expression: nc.createNodeSpan(kwargsId, kwargsId, 'AssignmentExpression', {\n                        operator: '=',\n                        left: kwargsId,\n                        right: nc.createNodeMembIds(kwargsId, '__params' + suffix, 'keywords'),\n                    }),\n                }));\n            }\n            node.body.body.push(argsIf);\n        }\n\n        // Convert original body to 'return (function() {<body>}).call(this);'\n        node.body.body.push(nc.createNodeFnBodyIife(body));\n\n        inFunction = oldInFunc;\n\n        // Verify that argument names are not repeated\n        for (var i = 0; i < formals.length; ++i) {\n            for (var j = 0; j < i; ++j) if (formals[i].id.name === formals[j].id.name)\n                raise(formals[i].id.start, 'Argument name clash');\n        }\n\n        // If class method, replace with prototype function literals\n        var retNode;\n        if (scope.isParentClass()) {\n            finishNode(node);\n            var classId = nc.createNodeSpan(node, node, 'Identifier', { name: scope.getParentClassName() });\n            var prototypeId = nc.createNodeSpan(node, node, 'Identifier', { name: 'prototype' });\n            var functionId = node.id;\n            var prototypeMember = nc.createNodeSpan(node, node, 'MemberExpression', {\n                object: classId,\n                property: prototypeId,\n                computed: false,\n            });\n            var functionMember = nc.createNodeSpan(node, node, 'MemberExpression', {\n                object: prototypeMember,\n                property: functionId,\n                computed: false,\n            });\n            var functionExpr = nc.createNodeSpan(node, node, 'FunctionExpression', {\n                body: node.body,\n                params: node.params,\n            });\n            var assignExpr = nc.createNodeSpan(node, node, 'AssignmentExpression', {\n                left: functionMember,\n                operator: '=',\n                right: functionExpr,\n            });\n            retNode = nc.createNodeSpan(node, node, 'ExpressionStatement', { expression: assignExpr });\n        } else retNode = finishNode(node, 'FunctionDeclaration');\n\n        scope.end();\n\n        return retNode;\n    }\n\n    // Parses a comma-separated list of expressions, and returns them as\n    // an array. `close` is the token type that ends the list, and\n    // `allowEmpty` can be turned on to allow subsequent commas with\n    // nothing in between them to be parsed as `null` (which is needed\n    // for array literals).\n\n    function parseExprList(close, allowTrailingComma, allowEmpty) {\n        var elts = [], first = true;\n        while (!eat(close)) {\n            if (!first) {\n                expect(_comma, close);\n                if (allowTrailingComma && options.allowTrailingCommas && eat(close)) break;\n            } else first = false;\n\n            if (allowEmpty && tokType === _comma) elts.push(null);\n            else elts.push(parseExprOps(false));\n        }\n        return elts;\n    }\n\n    function parseParamsList() {\n        // In: expr, expr, ..., id=expr, id=expr, ...\n        // Out: expr, expr, ..., {id:expr, __kwp:true}, {id:expr, __kwp:true}, ...\n        var elts = [], first = true;\n        while (!eat(_parenR)) {\n            if (!first) expect(_comma);\n            else first = false;\n            var expr = parseExprOps(false);\n            if (eat(_eq)) {\n                var right = parseExprOps(false);\n                var kwId = nc.createNodeSpan(expr, right, 'Identifier', { name: '__kwp' });\n                var kwLit = nc.createNodeSpan(expr, right, 'Literal', { value: true });\n                var left = nc.createNodeSpan(expr, right, 'ObjectExpression', { properties: [] });\n                left.properties.push({ type: 'Property', key: expr, value: right, kind: 'init' });\n                left.properties.push({ type: 'Property', key: kwId, value: kwLit, kind: 'init' });\n                expr = left;\n            }\n            elts.push(expr);\n        }\n        return elts;\n    }\n\n    // Parse the next token as an identifier. If `liberal` is true (used\n    // when parsing properties), it will also convert keywords into\n    // identifiers.\n    // `isString` is use for Entry Python start block\n\n    // TODO: liberal?\n\n    function parseIdent(liberal, isString) {\n        var node = startNode();\n        if (liberal) liberal = false;\n        if (tokType === _name || (isString && ((tokType === _string) || (tokType === _num)))) {\n            if (!liberal && strict && input.slice(tokStart, tokEnd).indexOf('\\\\') == -1)\n                raise(tokStart, 'The keyword \\'' + tokVal + '\\' is reserved');\n            node.name = tokVal;\n        } else if (liberal && tokType.keyword) {\n            node.name = tokType.keyword;\n        } else {\n            unexpected();\n        }\n        tokRegexpAllowed = false;\n        next();\n        return finishNode(node, 'Identifier');\n    }\n\n    function parseTuple(noIn, expr) {\n        var node = expr ? startNodeFrom(expr) : startNode();\n        node.arguments = expr ? [expr] : [];\n\n        // Tuple with single element has special trailing comma: t = 'hi',\n        // Look ahead and eat comma in this scenario\n        if (tokType === _comma) {\n            var oldPos = tokPos;\n            skipSpace();\n            var newPos = tokPos;\n            tokPos = oldPos;\n            if (newPos >= inputLen || input[newPos] === ';' || input[newPos] === ')' || newline.test(input[newPos]))\n                eat(_comma);\n        }\n\n        while (eat(_comma)) {\n            node.arguments.push(parseExprOps(noIn));\n        }\n        finishNode(node, 'NewExpression');\n\n        var runtimeId = nc.createNodeSpan(node, node, 'Identifier', { name: options.runtimeParamName });\n        var objectsId = nc.createNodeSpan(node, node, 'Identifier', { name: 'objects' });\n        var runtimeMember = nc.createNodeSpan(node, node, 'MemberExpression', {\n            object: runtimeId,\n            property: objectsId,\n            computed: false,\n        });\n        var listId = nc.createNodeSpan(node, node, 'Identifier', { name: 'tuple' });\n        node.callee = nc.createNodeSpan(node, node, 'MemberExpression', {\n            object: runtimeMember,\n            property: listId,\n            computed: false,\n        });\n\n        return node;\n    }\n\n\n    // ## Python runtime library\n\n    var pythonRuntime = exports.pythonRuntime = {\n\n        // Shim JavaScript objects that impersonate Python equivalents\n\n        // TODO: use 'type' or isSequence instead of 'instanceof Array' to id these\n\n        internal: {\n            // Only used within runtime\n            isSeq: function(a) {\n                return a && (a._type === 'list' || a._type === 'tuple');\n            },\n            slice: function(obj, start, end, step) {\n                if (step == null || step === 0) step = 1; // TODO: step === 0 is a runtime error\n                if (start == null) {\n                    if (step < 0) start = obj.length - 1;\n                    else start = 0;\n                } else if (start < 0) start += obj.length;\n                if (end == null) {\n                    if (step < 0) end = -1;\n                    else end = obj.length;\n                } else if (end < 0) end += obj.length;\n\n                var ret = new pythonRuntime.objects.list(), tmp, i;\n                if (step < 0) {\n                    tmp = obj.slice(end + 1, start + 1);\n                    for (i = tmp.length - 1; i >= 0; i += step) ret.append(tmp[i]);\n                } else {\n                    tmp = obj.slice(start, end);\n                    if (step === 1) ret = pythonRuntime.utils.createList(tmp);\n                    else for (i = 0; i < tmp.length; i += step) ret.append(tmp[i]);\n                }\n                return ret;\n            },\n            isJSArray: Array.isArray || function(obj) {\n                return toString.call(obj) === '[object Array]';\n            },\n        },\n\n        utils: {\n            convertToDict: function(dict) {\n                if (!dict.hasOwnProperty('_type')) {\n                    Object.defineProperty(dict, '_type',\n                        {\n                            get: function() {\n                                return 'dict';\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!dict.hasOwnProperty('_isPython')) {\n                    Object.defineProperty(dict, '_isPython',\n                        {\n                            get: function() {\n                                return true;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!dict.hasOwnProperty('items')) {\n                    Object.defineProperty(dict, 'items',\n                        {\n                            value: function() {\n                                var items = new pythonRuntime.objects.list();\n                                for (var k in this) items.append(new pythonRuntime.objects.tuple(k, this[k]));\n                                return items;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!dict.hasOwnProperty('length')) {\n                    Object.defineProperty(dict, 'length',\n                        {\n                            get: function() {\n                                return Object.keys(this).length;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!dict.hasOwnProperty('clear')) {\n                    Object.defineProperty(dict, 'clear',\n                        {\n                            value: function() {\n                                for (var i in this) delete this[i];\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!dict.hasOwnProperty('get')) {\n                    Object.defineProperty(dict, 'get',\n                        {\n                            value: function(key, def) {\n                                if (key in this) return this[key];\n                                else if (def !== undefined) return def;\n                                return null;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!dict.hasOwnProperty('keys')) {\n                    Object.defineProperty(dict, 'keys',\n                        {\n                            value: function() {\n                                return Object.keys(this);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!dict.hasOwnProperty('pop')) {\n                    Object.defineProperty(dict, 'pop',\n                        {\n                            value: function(key, def) {\n                                var value;\n                                if (key in this) {\n                                    value = this[key];\n                                    delete this[key];\n                                } else if (def !== undefined) value = def;\n                                else return new Error('KeyError');\n                                return value;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!dict.hasOwnProperty('values')) {\n                    Object.defineProperty(dict, 'values',\n                        {\n                            value: function() {\n                                var values = new pythonRuntime.objects.list();\n                                for (var key in this) values.append(this[key]);\n                                return values;\n                            },\n                            enumerable: false,\n                        });\n                }\n            },\n            createDict: function() {\n                var ret = new pythonRuntime.objects.dict();\n                if (arguments.length === 1 && arguments[0] instanceof Object)\n                    for (var k in arguments[0]) ret[k] = arguments[0][k];\n                else\n                    throw TypeError('createDict expects a single JavaScript object');\n                return ret;\n            },\n            createParamsObj: function() {\n                // In: expr, expr, ..., {id:expr, __kwp:true}, {id:expr, __kwp:true}, ...\n                // Out: {formals:[expr, expr, ...], keywords:{id:expr, id:expr, ...}}\n                var params = { formals: new pythonRuntime.objects.list(), keywords: new pythonRuntime.objects.dict() };\n                for (var i = 0; i < arguments.length; i++) {\n                    if (arguments[i] && arguments[i].__kwp === true) {\n                        for (var k in arguments[i])\n                            if (k !== '__kwp') params.keywords[k] = arguments[i][k];\n                    }\n                    else params.formals.push(arguments[i]);\n                }\n                return params;\n            },\n            convertToList: function(list) {\n                if (!list.hasOwnProperty('_type')) {\n                    Object.defineProperty(list, '_type',\n                        {\n                            get: function() {\n                                return 'list';\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('_isPython')) {\n                    Object.defineProperty(list, '_isPython',\n                        {\n                            get: function() {\n                                return true;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('append')) {\n                    Object.defineProperty(list, 'append',\n                        {\n                            value: function(x) {\n                                this.push(x);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('clear')) {\n                    Object.defineProperty(list, 'clear',\n                        {\n                            value: function() {\n                                this.splice(0, this.length);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('copy')) {\n                    Object.defineProperty(list, 'copy',\n                        {\n                            value: function() {\n                                return this.slice(0);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('count')) {\n                    Object.defineProperty(list, 'count',\n                        {\n                            value: function(x) {\n                                var c = 0;\n                                for (var i = 0; i < this.length; i++)\n                                    if (this[i] === x) c++;\n                                return c;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('equals')) {\n                    Object.defineProperty(list, 'equals',\n                        {\n                            value: function(x) {\n                                try {\n                                    if (this.length !== x.length) return false;\n                                    for (var i = 0; i < this.length; i++) {\n                                        if (this[i].hasOwnProperty('equals')) {\n                                            if (!this[i].equals(x[i])) return false;\n                                        } else if (this[i] !== x[i]) return false;\n                                    }\n                                    return true;\n                                }\n                                catch (e) {\n                                }\n                                return false;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('extend')) {\n                    Object.defineProperty(list, 'extend',\n                        {\n                            value: function(L) {\n                                for (var i = 0; i < L.length; i++) this.push(L[i]);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('index')) {\n                    Object.defineProperty(list, 'index',\n                        {\n                            value: function(x) {\n                                return this.indexOf(x);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('indexOf')) {\n                    Object.defineProperty(list, 'indexOf',\n                        {\n                            value: function(x, fromIndex) {\n                                try {\n                                    for (var i = fromIndex ? fromIndex : 0; i < this.length; i++) {\n                                        if (this[i].hasOwnProperty('equals')) {\n                                            if (this[i].equals(x)) return i;\n                                        } else if (this[i] === x) return i;\n                                    }\n                                }\n                                catch (e) {\n                                }\n                                return -1;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('insert')) {\n                    Object.defineProperty(list, 'insert',\n                        {\n                            value: function(i, x) {\n                                this.splice(i, 0, x);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('pop')) {\n                    Object.defineProperty(list, 'pop',\n                        {\n                            value: function(i) {\n                                if (!i)\n                                    i = this.length - 1;\n                                var item = this[i];\n                                this.splice(i, 1);\n                                return item;\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('_pySlice')) {\n                    Object.defineProperty(list, '_pySlice',\n                        {\n                            value: function(start, end, step) {\n                                return pythonRuntime.internal.slice(this, start, end, step);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('remove')) {\n                    Object.defineProperty(list, 'remove',\n                        {\n                            value: function(x) {\n                                this.splice(this.indexOf(x), 1);\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('sort')) {\n                    Object.defineProperty(list, 'sort',\n                        {\n                            value: function(x, reverse) {\n                                var list2 = this.slice(0);\n                                var apply_key = function(a, numerical) {\n                                    var list3 = list2.map(x);\n                                    // construct a dict that maps the listay before and after the map\n                                    var mapping = {};\n                                    for (var i in list3) mapping[list3[i]] = list2[i];\n                                    if (numerical)\n                                        list3.sort(function(a, b) {\n                                            return a - b;\n                                        });\n                                    else\n                                        list3.sort();\n                                    for (var i in a) a[i] = mapping[list3[i]];\n                                };\n                                for (var i in this) {\n                                    if (typeof this[i] !== 'number' || !isFinite(this[i])) {\n                                        if (typeof x != 'undefined') {\n                                            apply_key(this, false);\n                                        }\n                                        else {\n                                            list2.sort();\n                                            for (var j in this) this[j] = list2[j];\n                                        }\n                                        if (reverse)\n                                            this.reverse();\n                                        return;\n                                    }\n                                }\n                                if (typeof x != 'undefined') {\n                                    apply_key(this, true);\n                                }\n                                else {\n                                    list2.sort(function(a, b) {\n                                        return a - b;\n                                    });\n                                    for (var i in this) this[i] = list2[i];\n                                }\n                                if (reverse)\n                                    this.reverse();\n                            },\n                            enumerable: false,\n                        });\n                }\n                if (!list.hasOwnProperty('toString')) {\n                    Object.defineProperty(list, 'toString',\n                        {\n                            value: function() {\n                                return '[' + this.join(', ') + ']';\n                            },\n                            enumerable: false,\n                        });\n                }\n            },\n            createList: function() {\n                var ret = new pythonRuntime.objects.list();\n                if (arguments.length === 1 && arguments[0] instanceof Array)\n                    for (var i in arguments[0]) ret.push(arguments[0][i]);\n                else\n                    for (var i in arguments) ret.push(arguments[i]);\n                return ret;\n            },\n        },\n\n        ops: {\n            add: function(a, b) {\n                if (pythonRuntime.internal.isSeq(a) && pythonRuntime.internal.isSeq(b)) {\n                    if (a._type !== b._type)\n                        throw TypeError('can only concatenate ' + a._type + ' (not \\'' + b._type + '\\') to ' + a._type);\n                    var ret;\n                    if (a._type === 'list') ret = new pythonRuntime.objects.list();\n                    else if (a._type === 'tuple') ret = new pythonRuntime.objects.tuple();\n                    if (ret) {\n                        for (var i = 0; i < a.length; i++) ret.push(a[i]);\n                        for (var i = 0; i < b.length; i++) ret.push(b[i]);\n                        return ret;\n                    }\n                }\n                return a + b;\n            },\n            in: function(a, b, n) {\n                var r = b.hasOwnProperty('indexOf') ? b.indexOf(a) >= 0 : a in b;\n                return n ? !r : r;\n            },\n            multiply: function(a, b) {\n                // TODO: non-sequence operand must be an integer\n                if (pythonRuntime.internal.isSeq(a) && !isNaN(parseInt(b))) {\n                    var ret;\n                    if (a._type === 'list') ret = new pythonRuntime.objects.list();\n                    else if (a._type === 'tuple') ret = new pythonRuntime.objects.tuple();\n                    if (ret) {\n                        for (var i = 0; i < b; i++)\n                            for (var j = 0; j < a.length; j++) ret.push(a[j]);\n                        return ret;\n                    }\n                }\n                else if (pythonRuntime.internal.isSeq(b) && !isNaN(parseInt(a))) {\n                    var ret;\n                    if (b._type === 'list') ret = new pythonRuntime.objects.list();\n                    else if (b._type === 'tuple') ret = new pythonRuntime.objects.tuple();\n                    if (ret) {\n                        for (var i = 0; i < a; i++)\n                            for (var j = 0; j < b.length; j++) ret.push(b[j]);\n                        return ret;\n                    }\n                }\n                return a * b;\n            },\n            subscriptIndex: function(o, i) {\n                if (pythonRuntime.internal.isSeq(o) && i < 0) return o.length + i;\n                if (pythonRuntime.internal.isJSArray(o) && i < 0) return o.length + i;\n                if (typeof o === 'string' && i < 0) return o.length + i;\n                return i;\n            },\n        },\n\n        objects: {\n            dict: function() {\n                var obj = {};\n                for (var i in arguments) obj[arguments[i][0]] = arguments[i][1];\n                pythonRuntime.utils.convertToDict(obj);\n                return obj;\n            },\n            list: function() {\n                var arr = [];\n                arr.push.apply(arr, arguments);\n                pythonRuntime.utils.convertToList(arr);\n                return arr;\n            },\n            tuple: function() {\n                var arr = [];\n                arr.push.apply(arr, arguments);\n                Object.defineProperty(arr, '_type',\n                    {\n                        get: function() {\n                            return 'tuple';\n                        },\n                        enumerable: false,\n                    });\n                Object.defineProperty(arr, '_isPython',\n                    {\n                        get: function() {\n                            return true;\n                        },\n                        enumerable: false,\n                    });\n                Object.defineProperty(arr, 'count',\n                    {\n                        value: function(x) {\n                            var c = 0;\n                            for (var i = 0; i < this.length; i++)\n                                if (this[i] === x) c++;\n                            return c;\n                        },\n                        enumerable: false,\n                    });\n                Object.defineProperty(arr, 'equals',\n                    {\n                        value: function(x) {\n                            try {\n                                if (this.length !== x.length) return false;\n                                for (var i = 0; i < this.length; i++) {\n                                    if (this[i].hasOwnProperty('equals')) {\n                                        if (!this[i].equals(x[i])) return false;\n                                    } else if (this[i] !== x[i]) return false;\n                                }\n                                return true;\n                            }\n                            catch (e) {\n                            }\n                            return false;\n                        },\n                        enumerable: false,\n                    });\n                Object.defineProperty(arr, 'index',\n                    {\n                        value: function(x) {\n                            return this.indexOf(x);\n                        },\n                        enumerable: false,\n                    });\n                Object.defineProperty(arr, 'indexOf',\n                    {\n                        value: function(x, fromIndex) {\n                            try {\n                                for (var i = fromIndex ? fromIndex : 0; i < this.length; i++) {\n                                    if (this[i].hasOwnProperty('equals')) {\n                                        if (this[i].equals(x)) return i;\n                                    } else if (this[i] === x) return i;\n                                }\n                            }\n                            catch (e) {\n                            }\n                            return -1;\n                        },\n                        enumerable: false,\n                    });\n                Object.defineProperty(arr, '_pySlice',\n                    {\n                        value: function(start, end, step) {\n                            return pythonRuntime.internal.slice(this, start, end, step);\n                        },\n                        enumerable: false,\n                    });\n                Object.defineProperty(arr, 'toString',\n                    {\n                        value: function() {\n                            var s = '(' + this.join(', ');\n                            if (this.length === 1) s += ',';\n                            s += ')';\n                            return s;\n                        },\n                        enumerable: false,\n                    });\n                return arr;\n            },\n        },\n\n        // Python built-in functions\n\n        functions: {\n            /*\n      abs: function(x) {\n        return Math.abs(x);\n      },\n      all: function(iterable) {\n        for (var i in iterable) if (pythonRuntime.functions.bool(iterable[i]) !== true) return false;\n        return true;\n      },\n      any: function(iterable) {\n        for (var i in iterable) if (pythonRuntime.functions.bool(iterable[i]) === true) return true;\n        return false;\n      },\n      ascii: function(obj) {\n        var s = pythonRuntime.functions.repr(obj),\n            asc = \"\",\n            code;\n        for (var i = 0; i < s.length; i++) {\n          code = s.charCodeAt(i);\n          if (code <= 127) asc += s[i];\n          else if (code <= 0xFF) asc += \"\\\\x\" + code.toString(16);\n          else if (0xD800 <= code && code <= 0xDBFF) { // UCS-2 for the astral chars\n            // if (i+1 >= s.length) throw \"High surrogate not followed by low surrogate\"; // Is this needed?\n            code = ((code-0xD800)*0x400)+(s.charCodeAt(++i)-0xDC00)+0x10000;\n            asc += \"\\\\U\" + (\"000\"+code.toString(16)).slice(-8);\n          } else if (code <= 0xFFFF) asc += \"\\\\u\" + (\"0\"+code.toString(16)).slice(-4);\n          else if (code <= 0x10FFFF) asc += \"\\\\U\" + (\"000\"+code.toString(16)).slice(-8);\n          else; // Invalid value, should probably throw something. It should never get here though as strings shouldn't contain them in the first place\n        }\n        return asc;\n      },\n      bool: function(x) {\n        return !(x === undefined || // No argument\n                 x === null || // None\n                 x === false || // False\n                 x === 0 || // Zero\n                 x.length === 0 || // Empty Sequence\n                 // TODO: Empty Mapping, needs more support for python mappings first\n                 (x.__bool__ !== undefined && x.__bool__() === false) || // If it has bool conversion defined\n                 (x.__len__ !== undefined && (x.__len__() === false || x.__len__() === 0))); // If it has length conversion defined\n      },\n      chr: function(i) {\n        return String.fromCharCode(i); // TODO: Error code for not 0 <= i <= 1114111\n      },\n      divmod: function(a, b) {\n        return pythonRuntime.objects.tuple(Math.floor(a/b), a%b);\n      },\n      enumerate: function(iterable, start) {\n        start = start || 0;\n        var ret = new pythonRuntime.objects.list();\n        for (var i in iterable) ret.push(new pythonRuntime.objects.tuple(start++, iterable[i]));\n        return ret;\n      },\n      filter: function(fn, iterable) {\n        fn = fn || function () { return true; };\n        var ret = new pythonRuntime.objects.list();\n        for (var i in iterable) if (fn(iterable[i])) ret.push(iterable[i]);\n        return ret;\n      },\n      float: function(x) {\n        if (x === undefined) return 0.0;\n        else if (typeof x == \"string\") { // TODO: Fix type check\n          x = x.trim().toLowerCase();\n          if ((/^[+-]?inf(inity)?$/i).exec(x) !== null) return Infinity*(x[0]===\"-\"?-1:1);\n          else if ((/^nan$/i).exec(x) !== null) return NaN;\n          else return parseFloat(x);\n        } else if (typeof x == \"number\") { // TODO: Fix type check\n          return x; // TODO: Get python types working right so we can return an actual float\n        } else {\n          if (x.__float__ !== undefined) return x.__float__();\n          else return null; // TODO: Throw TypeError: float() argument must be a string or a number, not '<type of x>'\n        }\n      },\n      hex: function(x) {\n        return x.toString(16);\n      },\n      int: function (s) {\n        return parseInt(s);\n      },\n      len: function (o) {\n        return o.length;\n      },\n      list: function (iterable) {\n        var ret = new pythonRuntime.objects.list();\n        if (iterable instanceof Array) for (var i in iterable) ret.push(iterable[i]);\n        else for (var i in iterable) ret.push(i);\n        return ret;\n      },\n      map: function(fn, iterable) {\n        // TODO: support additional iterables passed\n        var ret = new pythonRuntime.objects.list();\n        for (var i in iterable) ret.push(fn(iterable[i]));\n        return ret;\n      },\n      max: function(arg1, arg2) {\n        // TODO: support optional keyword-only arguments\n        // TODO: empty iterable raises Python ValueError\n        if (!arg2) { // iterable\n          var max = null;\n          for (var i in arg1) if (max === null || arg1[i] > max) max = arg1[i];\n          return max;\n        } else return arg1 >= arg2 ? arg1 : arg2;\n      },\n      min: function(arg1, arg2) {\n        // TODO: support optional keyword-only arguments\n        // TODO: empty iterable raises Python ValueError\n        if (!arg2) { // iterable\n          var max = null;\n          for (var i in arg1) if (max === null || arg1[i] < max) max = arg1[i];\n          return max;\n        } else return arg1 <= arg2 ? arg1 : arg2;\n      },\n      oct: function(x) {\n        return x.toString(8);\n      },\n      ord: function(c) {\n        return c.charCodeAt(0);\n      },\n      pow: function(x, y, z) {\n        return z ? Math.pow(x, y) % z : Math.pow(x, y);\n      },\n      print: function () {\n        var s = \"\";\n        for (var i = 0; i < arguments.length; i++)\n          s += i === 0 ? arguments[i] : \" \" + arguments[i];\n        console.log(s);\n      },\n      */\n            range: function(start, stop, step) {\n                if (stop === undefined) {\n                    stop = start;\n                    start = 0;\n                    step = 1;\n                }\n                else if (step === undefined) step = 1;\n                var r = new pythonRuntime.objects.list();\n                if (start < stop && step > 0 || start > stop && step < 0) {\n                    var i = start;\n                    while (i < stop && step > 0 || i > stop && step < 0) {\n                        r.append(i);\n                        i += step;\n                    }\n                }\n                return r;\n            },\n            /*\n      repr: function (obj) {\n        if (typeof obj === 'string') return \"'\" + obj + \"'\"; // TODO: Patch until typesystem comes up.\n        if (obj.__repr__ !== undefined) return obj.__repr__();\n        else if (obj.__class__ !== undefined && obj.__class__.module !== undefined && obj.__class__.__name__) {\n          return '<'+obj.__class__.__module__+'.'+obj.__class__.__name__+' object>';\n        } else return obj.toString(); // Raise a please report warning here, we should never reach this piece of code\n      },\n      reversed: function (seq) {\n        var ret = new pythonRuntime.objects.list();\n        for (var i in seq) ret.push(seq[i]);\n        return ret.reverse();\n      },\n      round: function (num, ndigits) {\n        if (ndigits) {\n          var scale = Math.pow(10, ndigits);\n          return Math.round(num * scale) / scale;\n        }\n        return Math.round(num);\n      },\n      sorted: function (iterable, key, reverse) {\n        var ret = new pythonRuntime.objects.list();\n        for (var i in iterable) ret.push(iterable[i]);\n        if(key) ret.sort(key); else ret.sort();\n        if (reverse) ret.reverse();\n        return ret;\n      },\n      str: function (obj) {\n        return obj.toString();\n      },\n      sum: function (iterable, start) {\n        // TODO: start can't be a string\n        var ret = start || 0;\n        for (var i in iterable) ret += iterable[i];\n        return ret;\n      },\n      tuple: function (iterable) {\n        var ret = new pythonRuntime.objects.tuple();\n        for (var i in iterable) ret.push(iterable[i]);\n        return ret;\n      }\n      */\n        },\n\n        // Python imports\n        // TODO: from x import y, z\n\n        imports: {\n            random: {\n                random: function() {\n                    return Math.random();\n                },\n            },\n        },\n    };\n});\n"
  },
  {
    "path": "extern/util/handle.js",
    "content": "/**\n * Resize handle on Easel.js\n */\n'use strict';\n\nvar EaselHandle = function(canvas) {\n    if (typeof createjs != 'object') {\n        throw 'createjs is not founded';\n    }\n    this.canvas = canvas;\n    this.color = '#c1c7cd';\n    //this.color = \"#6BD5FF\";\n    this.arrowColor = '#E79040';\n    this.centerColor = '#93440F';\n    this.rotateKnobColor = '#6B6B6B';\n\n    this.x = 0;\n    this.y = 0;\n    this.rotation = 0;\n    this.direction = 0;\n    this.width = 100;\n    this.height = 100;\n    this.flipX = false;\n    this.flipY = false;\n    this.visible = false;\n    this.draggable = true;\n\n    this.centerEditable = true;\n    this.rotationEditable = true;\n    this.directionEditable = true;\n    this.resizeEnable = true;\n\n    this.onChangeFunction = null;\n    this.callerObject = null;\n\n    this.createHandle();\n    this.render();\n    this.selectedObject = null;\n};\n\n(function(p) {\n    p.setChangeListener = function(object, func) {\n        this.onChangeFunction = func;\n        this.callerObject = object;\n        return this;\n    };\n\n    /**\n     * for undo and redo\n     */\n    p.setEditStartListener = function(object, func) {\n        this.onEditStartFunction = func;\n        this.editStartCallerObject = object;\n        return this;\n    };\n\n    p.setEditEndListener = function(object, func) {\n        this.onEditEndFunction = func;\n        this.editEndCallerObject = object;\n        return this;\n    };\n\n    p.toggleCenter = function(isEnable) {\n        this.centerEditable = isEnable;\n        this.centerPoint.visible = isEnable;\n    };\n\n    p.toggleRotation = function(isEnable) {\n        this.rotationEditable = isEnable;\n        this.rotateKnob.visible = isEnable;\n    };\n\n    p.toggleDirection = function(isEnable) {\n        this.directionEditable = isEnable;\n        this.directionArrow.visible = isEnable;\n    };\n\n    p.toggleResize = function(isEnable) {\n        this.resizeEditable = isEnable;\n        for (var i = 0; i < 8; i++) {\n            this.knobs[i].visible = isEnable;\n        }\n    };\n\n    p.toggleFont = function(isEnable) {\n        this.fontEditable = isEnable;\n        this.fontKnob.visible = isEnable;\n    };\n\n    p.setX = function(xPos) {\n        this.x = xPos;\n        this.container.x = xPos;\n        this.background.x = xPos;\n    };\n\n    p.setY = function(yPos) {\n        this.y = yPos;\n        this.container.y = yPos;\n        this.background.y = yPos;\n    };\n\n    p.setWidth = function(width) {\n        this.width = width;\n        this.background.scaleX = width / 100;\n    };\n\n    p.setHeight = function(height) {\n        this.height = height;\n        this.background.scaleY = height / 100;\n    };\n\n    p.setRegX = function(regX) {\n        this.regX = regX;\n        this.centerPoint.x = regX;\n    };\n\n    p.setRegY = function(regY) {\n        this.regY = regY;\n        this.centerPoint.y = regY;\n    };\n\n    p.setRotation = function(rotation) {\n        rotation = (rotation + 360) % 360;\n        this.rotation = rotation;\n        this.container.rotation = rotation;\n        this.background.rotation = rotation;\n        this.updateKnobCursor();\n    };\n\n    p.setDirection = function(direction) {\n        direction = (direction + 360) % 360;\n        this.direction = direction;\n        this.directionArrow.rotation = direction;\n    };\n\n    p.setVisible = function(visible) {\n        this.visible = visible;\n        this.container.visible = visible;\n        this.background.visible = visible;\n    };\n\n    p.setFont = function(fontSize) {\n        this.font = fontSize;\n        this.fontKnob.y = fontSize - this.height / 2;\n    };\n\n    p.createHandle = function() {\n        var handle = this;\n        var container = new createjs.Container();\n\n        //border\n        var border = new createjs.Shape();\n        container.addChild(border);\n        this.border = border;\n\n        //edge\n        var edge = new createjs.Shape();\n        edge.cursor = 'move';\n        edge.on('mousedown', function(e) {\n            var offset = handle.getEventCoordinate(e);\n            offset.x -= handle.x;\n            offset.y -= handle.y;\n            this.offset = offset;\n            handle.dispatchEditStartEvent();\n        });\n        edge.on('pressmove', function(e) {\n            if (handle.getDraggable()) {\n                var pos = handle.getEventCoordinate(e);\n                pos.x -= this.offset.x;\n                pos.y -= this.offset.y;\n                handle.setX(pos.x);\n                handle.setY(pos.y);\n                handle.dispatchOnChangeEvent();\n            }\n        });\n        edge.on('pressup', function(e) {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(edge);\n        this.edge = edge;\n\n        //rotate knob\n        var rotateKnob = new createjs.Shape();\n        rotateKnob.cursor = 'crosshair';\n        rotateKnob.on('mousedown', function(e) {\n            handle.dispatchEditStartEvent();\n        });\n        rotateKnob.on('pressmove', function(e) {\n            var pos = handle.getEventCoordinate(e);\n            pos.x -= handle.x;\n            pos.y -= handle.y;\n            var rotation = (-Math.atan2(pos.x, pos.y) / Math.PI) * 180 - 180;\n            handle.setRotation(rotation);\n            handle.dispatchOnChangeEvent();\n        });\n        rotateKnob.on('pressup', function(e) {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(rotateKnob);\n        container.setChildIndex(rotateKnob, 1);\n        this.rotateKnob = rotateKnob;\n\n        var directionArrow = new createjs.Shape();\n\n        directionArrow.graphics\n            .ss(4, 1, 1)\n            .s(this.arrowColor)\n            .f(this.arrowColor)\n            .dc(0, 0, this.DHANDLE_RADIUS)\n            .mt(0, 0)\n            .lt(0, -40)\n            .lt(7, -32)\n            .lt(-7, -32)\n            .lt(0, -40)\n            .es();\n        directionArrow.on('mousedown', function(e) {\n            handle.dispatchEditStartEvent();\n        });\n        directionArrow.on('pressmove', function(e) {\n            var pos = handle.getLocalCoordinate(handle.getEventCoordinate(e));\n            var rotation = (-Math.atan2(pos.x, pos.y) / Math.PI) * 180 - 180;\n            handle.setDirection(rotation);\n            handle.dispatchOnChangeEvent();\n        });\n        directionArrow.on('pressup', function(e) {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(directionArrow);\n        container.setChildIndex(directionArrow, 0);\n        this.directionArrow = directionArrow;\n\n        // center\n        var centerPoint = new createjs.Shape();\n        centerPoint.graphics\n            .beginFill(this.centerColor)\n            .ss(1, 2, 0)\n            .s(this.centerColor)\n            .dc(0, 0, 5, 5);\n        centerPoint.on('mousedown', function(e) {\n            handle.dispatchEditStartEvent();\n        });\n        centerPoint.on('pressmove', function(e) {\n            var pos = handle.getEventCoordinate(e);\n            pos = handle.getLocalCoordinate(pos);\n            handle.setRegX(pos.x);\n            handle.setRegY(pos.y);\n            handle.dispatchOnChangeEvent();\n        });\n        centerPoint.on('pressup', function(e) {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(centerPoint);\n        this.centerPoint = centerPoint;\n\n        //resize knobs\n        this.knobs = [];\n        for (var i = 0; i < 8; i++) {\n            var knob = new createjs.Shape();\n            knob.graphics\n                .beginFill(this.color)\n                .ss(1, 2, 0)\n                .s(this.color)\n                .dr(-3, -3, 6, 6);\n            knob.knobIndex = i;\n            //knob.cursor = \"move\";\n            knob.on('mousedown', function(e) {\n                var otherKnobIndex =\n                    this.knobIndex + 4 > 7 ? this.knobIndex + 4 - 8 : this.knobIndex + 4;\n                var otherKnob = handle.knobs[otherKnobIndex];\n                var otherKnobPos = handle.getGlobalCoordinate(otherKnob);\n                this.otherKnobPos = otherKnobPos;\n                handle.dispatchEditStartEvent();\n            });\n            knob.on('pressmove', function(e) {\n                var pos = handle.getEventCoordinate(e);\n                if (handle.checkCenterPointState(handle.regX, handle.regY)) {\n                    handle.setRegX(0);\n                    handle.setRegY(0);\n                    handle.dispatchOnChangeEvent();\n                }\n                handle.adjust(this.knobIndex, this.otherKnobPos, pos);\n            });\n            knob.on('pressup', function(e) {\n                handle.dispatchEditEndEvent();\n            });\n            container.addChild(knob);\n            this.knobs.push(knob);\n        }\n\n        var background = new createjs.Shape();\n        background.graphics\n            .ss(1, 2, 0)\n            .s('rgba(254,254,254,0.01)')\n            .beginFill('rgba(254,254,254,1)')\n            .dr(-50, -50, 100, 100);\n        background.on('mousedown', function(e) {\n            var offset = handle.getEventCoordinate(e);\n            offset.x -= handle.x;\n            offset.y -= handle.y;\n            this.offset = offset;\n            handle.dispatchEditStartEvent();\n        });\n        background.on('pressmove', function(e) {\n            if (handle.getDraggable()) {\n                var pos = handle.getEventCoordinate(e);\n                pos.x -= this.offset.x;\n                pos.y -= this.offset.y;\n                handle.setX(pos.x);\n                handle.setY(pos.y);\n                handle.dispatchOnChangeEvent();\n            }\n        });\n        background.on('pressup', function(e) {\n            handle.dispatchEditEndEvent();\n        });\n        this.canvas.addChildAt(background, 0);\n        this.background = background;\n\n        this.container = container;\n        this.canvas.addChild(this.container);\n    };\n\n    p.checkCenterPointState = function(x, y) {\n        var standard = 718;\n        var res = Math.sqrt(x * x + y * y);\n        if (res > standard && Entry.engine.isState('stop')) {\n            Entry.toast.warning(\n                Lang.Workspace.toast_error_title_object_center,\n                Lang.Workspace.toast_error_contents_object_center\n            );\n            return true;\n        }\n        return false;\n    };\n\n    p.render = function() {\n        this.renderBorder();\n        this.renderEdge();\n        this.renderRotateKnob();\n        this.renderKnobs();\n    };\n\n    p.renderEdge = function() {\n        var width = this.width;\n        var height = this.height;\n        this.edge.graphics\n            .clear()\n            .ss(10, 2, 0)\n            .s('rgba(254,254,254,0.01)')\n            .lt(-width / 2, -height / 2)\n            .lt(0, -height / 2)\n            .lt(0, -height / 2)\n            .lt(+width / 2, -height / 2)\n            .lt(+width / 2, +height / 2)\n            .lt(-width / 2, +height / 2)\n            .cp();\n    };\n\n    p.renderRotateKnob = function() {\n        var width = this.width;\n        var height = this.height;\n        this.rotateKnob.graphics\n            .clear()\n            .ss(1, 2, 0)\n            .s(this.rotateKnobColor)\n            .mt(0, -height / 2)\n            .lt(0, -height / 2)\n            .lt(0, -height / 2 - 20)\n            .cp()\n            .beginFill(this.rotateKnobColor)\n            .dc(0, -height / 2 - 20, 4);\n    };\n\n    p.renderBorder = function() {\n        var width = this.width;\n        var height = this.height;\n        this.border.graphics\n            .clear()\n            .ss(1, 2, 0)\n            .s(this.color)\n            .lt(-width / 2, -height / 2)\n            .lt(0, -height / 2)\n            .lt(0, -height / 2)\n            .lt(+width / 2, -height / 2)\n            .lt(+width / 2, +height / 2)\n            .lt(-width / 2, +height / 2)\n            .cp();\n    };\n\n    p.renderKnobs = function() {\n        var width = this.width / 2;\n        var height = this.height / 2;\n        this.knobs.forEach(function(knob, i) {\n            knob.x = Math.round(Math.sin((i / 4) * Math.PI)) * width;\n            knob.y = Math.round(Math.cos((i / 4) * Math.PI)) * height;\n        });\n    };\n\n    p.getEventCoordinate = function(e) {\n        return {\n            x: e.stageX * 0.75 - 240,\n            y: e.stageY * 0.75 - 135,\n        };\n    };\n\n    p.getGlobalCoordinate = function(childObject) {\n        var container = this.container;\n        var rotation = -((this.container.rotation * Math.PI) / 180);\n        return {\n            x: this.x + childObject.x * Math.cos(rotation) + childObject.y * Math.sin(rotation),\n            y: this.y + childObject.y * Math.cos(rotation) - childObject.x * Math.sin(rotation),\n        };\n    };\n\n    p.getLocalCoordinate = function(pos) {\n        var container = this.container;\n        var rotation = (this.container.rotation * Math.PI) / 180;\n        pos.x -= this.x;\n        pos.y -= this.y;\n        return {\n            x: pos.x * Math.cos(rotation) + pos.y * Math.sin(rotation),\n            y: pos.y * Math.cos(rotation) - pos.x * Math.sin(rotation),\n        };\n    };\n\n    p.adjust = function(knobIndex, otherKnobPos, pos) {\n        var newPoint = this.calcPos({ x: this.x, y: this.y }, otherKnobPos, pos);\n        var newCenter = {\n            x: (otherKnobPos.x + newPoint.x) / 2,\n            y: (otherKnobPos.y + newPoint.y) / 2,\n        };\n        var newLength = Math.sqrt(\n            Math.pow(newPoint.x - otherKnobPos.x, 2) + Math.pow(newPoint.y - otherKnobPos.y, 2)\n        );\n        if (knobIndex % 4 == 0) {\n            var ratio = newLength / this.height;\n            this.height = newLength;\n            this.setRegY(this.regY * ratio);\n        } else if (knobIndex % 4 == 2) {\n            var ratio = newLength / this.width;\n            this.width = newLength;\n            this.setRegX(this.regX * ratio);\n        } else {\n            var oldLength =\n                2 *\n                Math.sqrt(\n                    Math.pow(this.x - otherKnobPos.x, 2) + Math.pow(this.y - otherKnobPos.y, 2)\n                );\n            var newWidth = (this.width * newLength) / oldLength;\n            var ratio = newWidth / this.width;\n            this.setWidth(newWidth);\n            this.setRegX(this.regX * ratio);\n            var newHeight = (this.height * newLength) / oldLength;\n            ratio = newHeight / this.height;\n            this.setHeight((this.height * newLength) / oldLength);\n            this.setRegY(this.regY * ratio);\n        }\n        this.setX(newCenter.x);\n        this.setY(newCenter.y);\n\n        this.render();\n        this.dispatchOnChangeEvent();\n    };\n\n    p.updateKnobCursor = function() {\n        var rotation = this.rotation;\n        var cursorList = ['ns-resize', 'nwse-resize', 'ew-resize', 'nesw-resize'];\n        var iter = Math.round(rotation / 45);\n        for (var i = 0; i < iter; i++) {\n            cursorList.unshift(cursorList.pop());\n        }\n        for (var i = 0; i < 8; i++) {\n            this.knobs[i].cursor = cursorList[i % 4];\n        }\n    };\n\n    p.calcPos = function(pos1, pos2, targetPos) {\n        if (pos1.x == pos2.x) {\n            return {\n                x: pos1.x,\n                y: targetPos.y,\n            };\n        } else if (pos1.y == pos2.y) {\n            return {\n                x: targetPos.x,\n                y: pos1.y,\n            };\n        } else {\n            var a = pos1.y - pos2.y;\n            var b = pos2.x - pos1.x;\n            var c = pos1.x * pos2.y - pos2.x * pos1.y;\n            var k = -(a * targetPos.x + b * targetPos.y + c) / (a * a + b * b);\n            return {\n                x: targetPos.x + a * k,\n                y: targetPos.y + b * k,\n            };\n        }\n    };\n\n    p.dispatchOnChangeEvent = function() {\n        if (this.onChangeFunction) this.onChangeFunction.call(this.callerObject, this);\n    };\n\n    p.dispatchEditStartEvent = function() {\n        if (this.onEditStartFunction)\n            this.onEditStartFunction.call(this.editStartCallerObject, this);\n    };\n\n    p.dispatchEditEndEvent = function() {\n        if (this.onEditEndFunction) this.onEditEndFunction.call(this.editEndCallerObject, this);\n    };\n\n    p.setDraggable = function(bool) {\n        this.draggable = bool;\n    };\n\n    p.getDraggable = function() {\n        return this.draggable;\n    };\n})(EaselHandle.prototype);\n"
  },
  {
    "path": "extern/util/ndgmr.Collision.js",
    "content": "/*\n  The MIT License\n\n  Copyright (c) 2012 Olaf Horstmann, indiegamr.com\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\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 THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n*/\n\n\n/**\n* A Pixel Perfect Collision Detection for EaselJS Bitmap-Objects\n* @author olsn, indiegamr.com\n**/\n\nthis.ndgmr = this.ndgmr || {};\n\n(function() {\n  var threshold = 2;\n\n  var collisionCanvas = document.createElement('canvas');\n  var collisionCtx = collisionCanvas.getContext('2d');\n      //collisionCtx.globalCompositeOperation = 'source-in';\n      collisionCtx.save();\n\n  var collisionCanvas2 = document.createElement('canvas');\n  var collisionCtx2 = collisionCanvas2.getContext('2d');\n      collisionCtx2.save();\n\n  var cachedBAFrames = [];\n\n  var checkRectCollision = function(bitmap1,bitmap2) {\n    var b1, b2;\n    if (bitmap1 instanceof createjs.Container ||\n           bitmap2 instanceof createjs.Container) {\n        b1 = bitmap1.getTransformedBounds();\n        b2 = bitmap2.getTransformedBounds();\n    } else {\n        b1 = getBounds(bitmap1);\n        b2 = getBounds(bitmap2);\n    }\n    if (Math.min(b1.width, b1.height, b2.width, b2.height) < 2)\n        threshold = 1;\n    else\n        threshold = 1;\n    return calculateIntersection(b1,b2);\n  }\n  ndgmr.checkRectCollision = checkRectCollision;\n\n  var checkPixelCollision = function(bitmap1, bitmap2, alphaThreshold, getRect) {\n    //display the intersecting canvases for debugging\n    if ( ndgmr.DEBUG || ndgmr.DEBUG_COLLISION ) {\n      document.body.appendChild(collisionCanvas);\n      document.body.appendChild(collisionCanvas2);\n    }\n\n    getRect = getRect || false;\n\n    var areObjectsCloseEnough,\n        intersetion,\n        imageData1, imageData2,\n        pixelIntersection;\n\n    areObjectsCloseEnough = _collisionDistancePrecheck(bitmap1,bitmap2);\n    if ( !areObjectsCloseEnough ) {\n        return false;\n    }\n\n    intersection = checkRectCollision(bitmap1,bitmap2);\n    if ( !intersection ) {\n        return false;\n    }\n\n    if (bitmap1 instanceof createjs.Container ||\n           bitmap2 instanceof createjs.Container) {\n        return intersection;\n    }\n\n    if (intersection.width === 0 || intersection.height === 0)\n        return false;\n\n    //chrome float point number bug\n    if (intersection.width/threshold < 1 ||\n          intersection.height/threshold < 1)\n        return false;\n\n    alphaThreshold = alphaThreshold || 0;\n    alphaThreshold = Math.min(0.99999,alphaThreshold);\n\n    //setting the canvas size\n    collisionCanvas.width  = intersection.width / threshold;\n    collisionCanvas.height = intersection.height / threshold;\n    collisionCanvas2.width  = intersection.width / threshold;\n    collisionCanvas2.height = intersection.height / threshold;\n\n    imageData1 = _intersectingImagePart(intersection,bitmap1,collisionCtx,1);\n    imageData2 = _intersectingImagePart(intersection,bitmap2,collisionCtx2,2);\n\n    //compare the alpha values to the threshold and return the result\n    // = true if pixels are both > alphaThreshold at one coordinate\n    pixelIntersection = _compareAlphaValues(imageData1,imageData2,intersection.width / threshold,intersection.height,alphaThreshold / threshold, getRect);\n\n    if ( pixelIntersection ) {\n      pixelIntersection.x  += intersection.x;\n      pixelIntersection.x2 += intersection.x;\n      pixelIntersection.y  += intersection.y;\n      pixelIntersection.y2 += intersection.y;\n    } else {\n      return false;\n    }\n\n    return pixelIntersection;\n  }\n  ndgmr.checkPixelCollision = checkPixelCollision;\n\n  var _collisionDistancePrecheck = function(bitmap1,bitmap2) {\n    var ir1, ir2;\n\n    ir1 = bitmap1.getTransformedBounds();\n    ir2 = bitmap2.getTransformedBounds();\n\n    //precheck if objects are even close enough\n    return ( Math.abs(ir2.x-ir1.x) < (ir1.x < ir2.x ? ir1.width : ir2.width)\n         && Math.abs(ir2.y-ir1.y) < (ir1.y < ir2.y ? ir1.height : ir2.height ))\n  }\n\n  var _intersectingImagePart = function(intersetion,bitmap,ctx,i) {\n    var bl, image, frameName, sr;\n\n    if ( bitmap instanceof createjs.Bitmap ) {\n      image = bitmap.image;\n    } else if ( bitmap instanceof createjs.Sprite ) {\n    frame = bitmap.spriteSheet.getFrame( bitmap.currentFrame )\n      frameName = frame.image.src + ':' +\n                  frame.rect.x + ':' + frame.rect.y + ':' +\n                  frame.rect.width  + ':' + frame.rect.height;// + ':' + frame.rect.regX  + ':' + frame.rect.regY\n      if ( cachedBAFrames[frameName] ) {\n        image = cachedBAFrames[frameName];\n      } else {\n        cachedBAFrames[frameName] = image = createjs.SpriteSheetUtils.extractFrame(bitmap.spriteSheet,bitmap.currentFrame);\n      }\n    }\n\n    bl = bitmap.globalToLocal(intersetion.x,intersetion.y);\n    ctx.restore();\n    ctx.save();\n    //ctx.clearRect(0,0,intersetion.width,intersetion.height);\n    ctx.rotate(_getParentalCumulatedProperty(bitmap,'rotation')*(Math.PI/181));\n    ctx.scale(_getParentalCumulatedProperty(bitmap,'scaleX','*') / threshold,_getParentalCumulatedProperty(bitmap,'scaleY','*') / threshold);\n    ctx.translate((-bl.x-intersetion['rect'+i].regX) / threshold,(  -bl.y-intersetion['rect'+i].regY) / threshold);\n    if ( (sr = bitmap.sourceRect) != undefined ) {\n      ctx.drawImage(image,sr.x,sr.y,sr.width,sr.height,0,0,sr.width,sr.height);\n    } else {\n      ctx.drawImage(image,0,0,image.width / threshold,image.height / threshold);\n    }\n    return ctx.getImageData(0, 0, intersetion.width / threshold, intersetion.height / threshold).data;\n  }\n\n  var _compareAlphaValues = function(imageData1,imageData2,width,height,alphaThreshold,getRect) {\n    var alpha1, alpha2, x, y, offset = 3,\n        pixelRect = {x:Infinity,y:Infinity,x2:-Infinity,y2:-Infinity};\n\n    // parsing through the pixels checking for an alpha match\n    // TODO: intelligent parsing, not just from 0 to end!\n    for ( y = 0; y < height; ++y) {\n        for ( x = 0; x < width; ++x) {\n            alpha1 = imageData1.length > offset+1 ? imageData1[offset] / 255 : 0;\n            alpha2 = imageData2.length > offset+1 ? imageData2[offset] / 255 : 0;\n\n            if ( alpha1 > alphaThreshold && alpha2 > alphaThreshold ) {\n              if ( getRect ) {\n                if ( x < pixelRect.x  ) pixelRect.x  = x;\n                if ( x > pixelRect.x2 ) pixelRect.x2 = x;\n                if ( y < pixelRect.y  ) pixelRect.y  = y;\n                if ( y > pixelRect.y2 ) pixelRect.y2 = y;\n              } else {\n                return {x:x,y:y,width:1,height:1};\n              }\n            }\n            offset += 4;\n        }\n    }\n\n    if ( pixelRect.x != Infinity ) {\n      pixelRect.width  = pixelRect.x2 - pixelRect.x + 1;\n      pixelRect.height = pixelRect.y2 - pixelRect.y + 1;\n      return pixelRect;\n    }\n\n    return null;\n  }\n\n  // this is needed to paint the intersection part correctly,\n  // if the tested bitmap is a child to a rotated/scaled parent\n  // this was not painted correctly before\n  var _getParentalCumulatedProperty = function(child,propName,operation) {\n    operation = operation || '+';\n    if ( child.parent && child.parent[propName] ) {\n      var cp = child[propName];\n      var pp = _getParentalCumulatedProperty(child.parent,propName,operation);\n      if ( operation == '*' ) {\n        return cp * pp;\n      } else {\n        return cp + pp;\n      }\n    }\n\n    return child[propName];\n  }\n\n  var calculateIntersection = function(rect1, rect2)\n  {\n    // first we have to calculate the\n    // center of each rectangle and half of\n    // width and height\n    var dx, dy, r1={}, r2={};\n    r1.cx = rect1.x + (r1.hw = (rect1.width /2));\n    r1.cy = rect1.y + (r1.hh = (rect1.height/2));\n    r2.cx = rect2.x + (r2.hw = (rect2.width /2));\n    r2.cy = rect2.y + (r2.hh = (rect2.height/2));\n\n    dx = Math.abs(r1.cx-r2.cx) - (r1.hw + r2.hw);\n    dy = Math.abs(r1.cy-r2.cy) - (r1.hh + r2.hh);\n\n    if (dx < 0 && dy < 0) {\n      dx = Math.min(Math.min(rect1.width,rect2.width),-dx);\n      dy = Math.min(Math.min(rect1.height,rect2.height),-dy);\n      return {x:Math.max(rect1.x,rect2.x),\n              y:Math.max(rect1.y,rect2.y),\n              width:dx,\n              height:dy,\n              rect1: rect1,\n              rect2: rect2};\n    } else {\n      return null;\n    }\n  }\n  ndgmr.calculateIntersection = calculateIntersection;\n\n  var getBounds = function(obj) {\n    var bounds={x:Infinity,y:Infinity,width:0,height:0};\n    if ( obj instanceof createjs.Container ) {\n      bounds.x2 = -Infinity;\n      bounds.y2 = -Infinity;\n      var children = obj.children, l=children.length, cbounds, c;\n      for ( c = 0; c < l; c++ ) {\n        cbounds = getBounds(children[c]);\n        if ( cbounds.x < bounds.x ) bounds.x = cbounds.x;\n        if ( cbounds.y < bounds.y ) bounds.y = cbounds.y;\n        if ( cbounds.x + cbounds.width > bounds.x2 ) bounds.x2 = cbounds.x + cbounds.width;\n        if ( cbounds.y + cbounds.height > bounds.y2 ) bounds.y2 = cbounds.y + cbounds.height;\n        //if ( cbounds.x - bounds.x + cbounds.width  > bounds.width  ) bounds.width  = cbounds.x - bounds.x + cbounds.width;\n        //if ( cbounds.y - bounds.y + cbounds.height > bounds.height ) bounds.height = cbounds.y - bounds.y + cbounds.height;\n      }\n      if ( bounds.x == Infinity ) bounds.x = 0;\n      if ( bounds.y == Infinity ) bounds.y = 0;\n      if ( bounds.x2 == Infinity ) bounds.x2 = 0;\n      if ( bounds.y2 == Infinity ) bounds.y2 = 0;\n\n      bounds.width = bounds.x2 - bounds.x;\n      bounds.height = bounds.y2 - bounds.y;\n      delete bounds.x2;\n      delete bounds.y2;\n    } else {\n      var gp,gp2,gp3,gp4,imgr={},sr;\n      if ( obj instanceof createjs.Bitmap ) {\n        sr = obj.sourceRect || obj.image;\n\n        imgr.width = sr.width;\n        imgr.height = sr.height;\n      } else if ( obj instanceof createjs.Sprite ) {\n        if ( obj.spriteSheet._frames && obj.spriteSheet._frames[obj.currentFrame] && obj.spriteSheet._frames[obj.currentFrame].image ) {\n          var cframe = obj.spriteSheet.getFrame(obj.currentFrame);\n          imgr.width =  cframe.rect.width;\n          imgr.height =  cframe.rect.height;\n          imgr.regX = cframe.regX;\n          imgr.regY = cframe.regY;\n        } else {\n          bounds.x = obj.x || 0;\n          bounds.y = obj.y || 0;\n        }\n      } else {\n        bounds.x = obj.x || 0;\n        bounds.y = obj.y || 0;\n      }\n\n      imgr.regX = imgr.regX || 0; imgr.width  = imgr.width  || 0;\n      imgr.regY = imgr.regY || 0; imgr.height = imgr.height || 0;\n      bounds.regX = imgr.regX;\n      bounds.regY = imgr.regY;\n\n      gp  = obj.localToGlobal(0         -imgr.regX,0          -imgr.regY);\n      gp2 = obj.localToGlobal(imgr.width-imgr.regX,imgr.height-imgr.regY);\n      gp3 = obj.localToGlobal(imgr.width-imgr.regX,0          -imgr.regY);\n      gp4 = obj.localToGlobal(0         -imgr.regX,imgr.height-imgr.regY);\n\n      bounds.x = Math.min(Math.min(Math.min(gp.x,gp2.x),gp3.x),gp4.x);\n      bounds.y = Math.min(Math.min(Math.min(gp.y,gp2.y),gp3.y),gp4.y);\n      bounds.width = Math.max(Math.max(Math.max(gp.x,gp2.x),gp3.x),gp4.x) - bounds.x;\n      bounds.height = Math.max(Math.max(Math.max(gp.y,gp2.y),gp3.y),gp4.y) - bounds.y;\n    }\n    return bounds;\n  }\n  ndgmr.getBounds = getBounds;\n}());\n"
  },
  {
    "path": "extern/util/static.js",
    "content": "'use strict';\n\n/* eslint-disable */\nvar EntryStatic = {\n    fontFamily: \"NanumGothic, 'Nanum Gothic'\",\n    fontOffsetY: -2.5,\n    heightLetter: 'M',\n    messageMaxLength: 10,\n};\n\nEntryStatic.variableBlockList = [\n    'get_variable',\n    'change_variable',\n    'set_variable',\n    'show_variable',\n    'hide_variable',\n    'value_of_index_from_list',\n    'add_value_to_list',\n    'remove_value_from_list',\n    'insert_value_to_list',\n    'change_value_list_index',\n    'length_of_list',\n    'is_included_in_list',\n    'show_list',\n    'hide_list',\n];\n\nEntryStatic.messageBlockList = ['when_message_cast', 'message_cast', 'message_cast_wait'];\n\nEntryStatic.getAllBlocks = function () {\n    return [\n        {\n            category: 'start',\n            blocks: [\n                'messageAddButton',\n                'when_run_button_click',\n                'when_some_key_pressed',\n                'mouse_clicked',\n                'mouse_click_cancled',\n                'when_object_click',\n                'when_object_click_canceled',\n                'when_message_cast',\n                'message_cast',\n                'message_cast_wait',\n                'when_scene_start',\n                'start_scene',\n                'start_neighbor_scene',\n                'check_object_property',\n                'check_block_execution',\n                'switch_scope',\n                'is_answer_submited',\n                'check_lecture_goal',\n                'check_variable_by_name',\n                'show_prompt',\n                'check_goal_success',\n                'positive_number',\n                'negative_number',\n                'wildcard_string',\n                'wildcard_boolean',\n                'register_score',\n            ],\n        },\n        {\n            category: 'flow',\n            blocks: [\n                'wait_second',\n                'repeat_basic',\n                'repeat_inf',\n                'repeat_while_true',\n                'stop_repeat',\n                'continue_repeat',\n                '_if',\n                'if_else',\n                'wait_until_true',\n                'stop_object',\n                'restart_project',\n                'when_clone_start',\n                'create_clone',\n                'delete_clone',\n                'remove_all_clones',\n            ],\n        },\n        {\n            category: 'moving',\n            blocks: [\n                'move_direction',\n                'bounce_wall',\n                'move_x',\n                'move_y',\n                'move_xy_time',\n                'locate_x',\n                'locate_y',\n                'locate_xy',\n                'locate_xy_time',\n                'locate',\n                'locate_object_time',\n                'rotate_relative',\n                'direction_relative',\n                'rotate_by_time',\n                'direction_relative_duration',\n                'rotate_absolute',\n                'direction_absolute',\n                'see_angle_object',\n                'move_to_angle',\n            ],\n        },\n        {\n            category: 'looks',\n            blocks: [\n                'show',\n                'hide',\n                'dialog_time',\n                'dialog',\n                'remove_dialog',\n                'change_to_some_shape',\n                'change_to_next_shape',\n                'add_effect_amount',\n                'change_effect_amount',\n                'erase_all_effects',\n                'change_scale_size',\n                'set_scale_size',\n                'stretch_scale_size',\n                'reset_scale_size',\n                'flip_x',\n                'flip_y',\n                'change_object_index',\n            ],\n        },\n        {\n            category: 'brush',\n            blocks: [\n                'brush_stamp',\n                'start_drawing',\n                'stop_drawing',\n                'set_color',\n                'change_thickness',\n                'set_thickness',\n                'start_fill',\n                'stop_fill',\n                'set_fill_color',\n                'set_random_color',\n                'change_brush_transparency',\n                'set_brush_tranparency',\n                'brush_erase_all',\n            ],\n        },\n        {\n            category: 'text',\n            blocks: [\n                'text_read',\n                'text_write',\n                'text_append',\n                'text_prepend',\n                'text_change_effect',\n                'text_change_font',\n                'text_change_font_color',\n                'text_change_bg_color',\n                'text_flush',\n            ],\n        },\n        {\n            category: 'sound',\n            blocks: [\n                'sound_something_with_block',\n                'sound_something_second_with_block',\n                'sound_from_to',\n                'sound_something_wait_with_block',\n                'sound_something_second_wait_with_block',\n                'sound_from_to_and_wait',\n                'get_sound_duration',\n                'get_sound_volume',\n                'sound_volume_change',\n                'sound_volume_set',\n                'get_sound_speed',\n                'sound_speed_change',\n                'sound_speed_set',\n                'sound_silent_all',\n                'play_bgm',\n                'stop_bgm',\n            ],\n        },\n        {\n            category: 'judgement',\n            blocks: [\n                'is_clicked',\n                'is_object_clicked',\n                'is_press_some_key',\n                'reach_something',\n                'is_type',\n                'boolean_basic_operator',\n                'boolean_and_or',\n                'boolean_not',\n                'is_boost_mode',\n                'is_current_device_type',\n                'is_touch_supported',\n            ],\n        },\n        {\n            category: 'calc',\n            blocks: [\n                'calc_basic',\n                'calc_rand',\n                'coordinate_mouse',\n                'coordinate_object',\n                'quotient_and_mod',\n                'calc_operation',\n                'get_project_timer_value',\n                'choose_project_timer_action',\n                'set_visible_project_timer',\n                'get_date',\n                'distance_something',\n                'get_user_name',\n                'get_nickname',\n                'length_of_string',\n                'count_match_string',\n                'combine_something',\n                'char_at',\n                'substring',\n                'index_of_string',\n                'replace_string',\n                'reverse_of_string',\n                'change_string_case',\n                'get_block_count',\n                'change_rgb_to_hex',\n                'change_hex_to_rgb',\n                'get_boolean_value',\n            ],\n        },\n        {\n            category: 'variable',\n            blocks: [\n                'variableAddButton',\n                'listAddButton',\n                'ask_and_wait',\n                'get_canvas_input_value',\n                'set_visible_answer',\n                'get_variable',\n                'change_variable',\n                'set_variable',\n                'show_variable',\n                'hide_variable',\n                'value_of_index_from_list',\n                'add_value_to_list',\n                'remove_value_from_list',\n                'insert_value_to_list',\n                'change_value_list_index',\n                'length_of_list',\n                'is_included_in_list',\n                'show_list',\n                'hide_list',\n            ],\n        },\n        {\n            category: 'func',\n            blocks: [\n                'functionAddButton',\n                'function_name',\n                'showFunctionPropsButton',\n                'set_func_variable',\n                'get_func_variable',\n            ],\n        },\n        {\n            category: 'analysis',\n            blocks: [\n                'analizyDataAddButton',\n                'append_row_to_table',\n                'insert_row_to_table',\n                'delete_row_from_table',\n                'set_value_from_table',\n                'save_current_table',\n                'get_table_count',\n                'get_value_from_table',\n                'get_value_from_last_row',\n                'calc_values_from_table',\n                'open_table',\n                'open_table_wait',\n                'open_table_chart',\n                'close_table_chart',\n                'get_coefficient',\n                'set_value_from_cell',\n                'get_value_from_cell',\n                'get_value_v_lookup',\n            ],\n        },\n        {\n            category: 'ai_utilize',\n            blocks: [\n                'aiUtilizeBlockAddButton',\n                'aiUtilizeModelTrainButton',\n                'learning_title_image',\n                'learning_title_speech',\n                'learning_title_text',\n                'learning_title_number',\n                'learning_title_regression',\n                'learning_title_cluster',\n                'learning_title_logistic_regression',\n                'learning_title_decisiontree',\n                'learning_title_svm',\n                'retrain_model',\n                'model_is_trained',\n                'set_train_visible',\n                'set_train_chart',\n                'set_regression_option',\n                'get_regression_predict_1',\n                'get_regression_predict_2',\n                'get_regression_predict_3',\n                'get_regression_predict_4',\n                'get_regression_predict_5',\n                'get_regression_predict_6',\n                'get_regression_accuracy',\n                'set_logistic_regression_option',\n                'set_logistic_regression_optimizer',\n                'get_logistic_regression_probability_1',\n                'get_logistic_regression_probability_2',\n                'get_logistic_regression_probability_3',\n                'get_logistic_regression_probability_4',\n                'get_logistic_regression_probability_5',\n                'get_logistic_regression_probability_6',\n                'set_decisiontree_option',\n                'set_decisiontree_tree',\n                'set_svm_option',\n                'set_kernel_linear',\n                'set_kernel_option',\n                'is_result_1',\n                'is_result_2',\n                'is_result_3',\n                'is_result_4',\n                'is_result_5',\n                'is_result_6',\n                'get_predict_1',\n                'get_predict_2',\n                'get_predict_3',\n                'get_predict_4',\n                'get_predict_5',\n                'get_predict_6',\n                'get_result_info',\n                'set_cluster_option_k',\n                'set_cluster_option_centroids',\n                'get_cluster_centriod_count',\n                'get_cluster_centriod_value',\n                'get_cluster_centriod_index_1',\n                'get_cluster_centriod_index_2',\n                'get_cluster_centriod_index_3',\n                'get_cluster_centriod_index_4',\n                'get_cluster_centriod_index_5',\n                'get_cluster_centriod_index_6',\n                'set_number_learning_option_k',\n                'get_number_learning_predict_1',\n                'get_number_learning_predict_2',\n                'get_number_learning_predict_3',\n                'get_number_learning_predict_4',\n                'get_number_learning_predict_5',\n                'get_number_learning_predict_6',\n                'get_number_learning_predict_param_1',\n                'get_number_learning_predict_param_2',\n                'get_number_learning_predict_param_3',\n                'get_number_learning_predict_param_4',\n                'get_number_learning_predict_param_5',\n                'get_number_learning_predict_param_6',\n                'is_number_learning_group_1',\n                'is_number_learning_group_2',\n                'is_number_learning_group_3',\n                'is_number_learning_group_4',\n                'is_number_learning_group_5',\n                'is_number_learning_group_6',\n                'insert_data_for_test',\n                'video_capture_for_image_test',\n                'insert_text_block_for_test',\n                'test_result',\n                'accuracy_of_result',\n                'is_group',\n                'audio_title',\n                'check_microphone',\n                'get_microphone_volume',\n                'speech_to_text_title',\n                'speech_to_text_convert',\n                'timed_speech_to_text_convert',\n                'set_visible_speech_to_text',\n                'speech_to_text_get_value',\n                'tts_title',\n                'read_text',\n                'read_text_wait_with_block',\n                'set_tts_property',\n                'translate_title',\n                'get_translated_string',\n                'check_language',\n                'video_title',\n                'video_draw_webcam',\n                'video_change_cam',\n                'video_check_webcam',\n                'video_flip_camera',\n                'video_set_camera_opacity_option',\n                'video_motion_value',\n                'video_toggle_model',\n                'video_is_model_loaded',\n                'video_object_detected',\n                'video_number_detect',\n                'video_toggle_ind',\n                'video_body_part_coord',\n                'video_face_part_coord',\n                'video_detected_face_info',\n                'media_pipe_title',\n                'media_pipe_video_screen',\n                'media_pipe_switch_camera',\n                'check_connected_camera',\n                'media_pipe_flip_camera',\n                'media_pipe_set_opacity_camera',\n                'media_pipe_motion_value',\n                'hand_detection_title',\n                'when_hand_detection',\n                'hand_detection',\n                'draw_detected_hand',\n                'check_detected_hand',\n                'count_detected_hand',\n                'locate_to_hand',\n                'locate_time_to_hand',\n                'axis_detected_hand',\n                'is_which_hand',\n                'get_which_hand',\n                'is_which_gesture',\n                'get_which_gesture',\n                'pose_landmarker_title',\n                'when_pose_landmarker',\n                'pose_landmarker',\n                'draw_detected_pose',\n                'check_detected_pose',\n                'count_detected_pose',\n                'locate_to_pose',\n                'locate_time_to_pose',\n                'axis_detected_pose',\n                'face_landmarker_title',\n                'when_face_landmarker',\n                'face_landmarker',\n                'draw_detected_face',\n                'check_detected_face',\n                'count_detected_face',\n                'locate_to_face',\n                'locate_time_to_face',\n                'check_detected_gender',\n                'check_compare_age',\n                'check_detected_emotion',\n                'axis_detected_face',\n                'get_detected_face_value',\n                'object_detector_title',\n                'when_object_detector',\n                'object_detector',\n                'draw_detected_object',\n                'check_detected_object',\n                'count_detected_object',\n                'is_detected_among_objects',\n            ],\n        },\n        {\n            category: 'expansion',\n            blocks: [\n                'expansionBlockAddButton',\n                'weather_title',\n                'get_cur_weather',\n                'get_cur_wind',\n                'get_cur_weather_data',\n                'check_cur_weather',\n                'check_cur_finddust',\n                'get_day_weather',\n                'get_day_weather_data',\n                'check_day_weather',\n                'get_time_weather',\n                'get_time_weather_data',\n                'check_time_weather',\n                'check_weather',\n                'check_finedust',\n                'get_weather_data',\n                'get_current_weather_data',\n                'get_today_temperature',\n                'check_city_weather',\n                'check_city_finedust',\n                'get_city_weather_data',\n                'get_current_city_weather_data',\n                'get_today_city_temperature',\n                'festival_title',\n                'count_festival',\n                'get_festival_info',\n                'emergencyActionGuidelines_title',\n                'count_disaster_guideline',\n                'get_disaster_guideline',\n                'count_social_disaster_guideline',\n                'get_social_disaster_guideline',\n                'count_safety_accident_guideline',\n                'get_safety_accident_guideline',\n                'disaster_alert_title',\n                'count_disaster_alert',\n                'get_disaster_alert',\n                'check_disaster_alert',\n            ],\n        },\n        {\n            category: 'arduino',\n            blocks: [\n                'hardware_connect_helper',\n                'hardware_noti_installed',\n                'arduino_reconnect',\n                'arduino_open',\n                'hardware_program_download',\n                'arduino_cloud_pc_open',\n                'arduino_lite_disconnect',\n                'hardware_device_name_title',\n                'hardware_device_name_content',\n                'hardware_connected_noti',\n                'arduino_lite_connected_noti',\n                'arduino_lite_reconnect',\n                'hardware_noti_not_installed',\n                'arduino_lite_download_firmware',\n                'arduino_lite_connect',\n                'arduino_lite_guide',\n                'arduino_noti',\n                'arduino_lite_alert',\n            ].concat(EntryStatic.DynamicHardwareBlocks),\n        },\n    ];\n};\n\n/* eslint-disable */\nObject.defineProperty(EntryStatic, 'fonts', {\n    get: function () {\n        return [\n            {\n                name: Lang.Fonts.batang,\n                family: 'KoPub Batang',\n                url: '/css/kopubbatang.css',\n                visible: false,\n            },\n            {\n                name: Lang.Fonts.jeju_hallasan,\n                family: 'Jeju Hallasan',\n                url: '/css/jejuhallasan.css',\n                visible: false,\n            },\n            {\n                name: Lang.Fonts.gothic,\n                family: 'Nanum Gothic',\n                url: '/css/nanumgothic.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.myeongjo,\n                family: 'Nanum Myeongjo',\n                url: '/css/nanummyeongjo.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.nanumbarunpen,\n                family: 'Nanum Barun Pen',\n                url: '/css/nanumbarunpen.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.pen_script,\n                family: 'Nanum Pen Script',\n                url: '/css/nanumpenscript.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.square_round,\n                family: 'NanumSquareRound',\n                url: '/css/square_round.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.maruburi,\n                family: 'MaruBuri',\n                url: '/css/maruburi.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.notosans,\n                family: 'NotoSans',\n                url: '/css/notosans.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.d2coding,\n                family: 'D2 Coding',\n                url: '/css/d2coding.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.jalnan,\n                family: 'yg-jalnan',\n                url: '/css/jalnan.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.designhouse,\n                family: 'designhouseOTFLight00',\n                url: '/css/designhouse.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.dunggeunmo,\n                family: 'DungGeunMo',\n                url: '/css/dunggeunmo.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.uhbeemysen,\n                family: 'UhBeemysen',\n                url: '/css/uhbeemysen.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.sd_comic_stencil,\n                family: 'SDComicStencil',\n                style: {\n                    backgroundColor: '#f7fcff',\n                    padding: '17px 22px 14px 16px',\n                    margin: '0px',\n                    borderTop: 'solid 1px #d6e9f4',\n                },\n                url: '/css/SDComicStencil.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.sd_childfundkorea,\n                family: 'SDChildfundkorea',\n                style: {\n                    backgroundColor: '#f7fcff',\n                    padding: '17px 22px 14px 16px',\n                    margin: '0px',\n                    borderTop: 'solid 1px #d6e9f4',\n                },\n                url: '/css/SDChildfundkorea.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.sd_cinema_theater,\n                family: 'SDCinemaTheater',\n                style: {\n                    backgroundColor: '#f7fcff',\n                    padding: '17px 22px 14px 16px',\n                    margin: '0px',\n                    borderTop: 'solid 1px #d6e9f4',\n                },\n                url: '/css/SDCinemaTheater.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.sd_mapssi,\n                family: 'SDMapssi',\n                style: {\n                    backgroundColor: '#f7fcff',\n                    padding: '17px 22px 14px 16px',\n                    margin: '0px',\n                    borderTop: 'solid 1px #d6e9f4',\n                },\n                url: '/css/SDMapssi.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.sd_shabang,\n                family: 'SDShabang',\n                style: {\n                    backgroundColor: '#f7fcff',\n                    padding: '17px 22px 14px 16px',\n                    margin: '0px',\n                    borderTop: 'solid 1px #d6e9f4',\n                },\n                url: '/css/SDShabang.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.sd_woodcarving,\n                family: 'SDWoodcarving',\n                style: {\n                    backgroundColor: '#f7fcff',\n                    padding: '17px 22px 14px 16px',\n                    margin: '0px',\n                    borderTop: 'solid 1px #d6e9f4',\n                },\n                url: '/css/SDWoodcarving.css',\n                visible: true,\n            },\n            {\n                name: Lang.Fonts.sd_yongbi,\n                family: 'SDYongbi',\n                style: {\n                    backgroundColor: '#f7fcff',\n                    padding: '17px 22px 14px 16px',\n                    margin: '0px',\n                    borderTop: 'solid 1px #d6e9f4',\n                },\n                url: '/css/SDYongbi.css',\n                visible: true,\n            },\n        ];\n    },\n});\n\nEntryStatic.colorSet = {\n    arrow: {\n        default: {\n            DEFAULT: '#FFFFFF',\n            START: '#FFFFFF',\n            FLOW: '#3A71BC',\n            MOVING: '#8641B6',\n            LOOKS: '#FFFFFF',\n            TEXT: '#DC9C32',\n            SOUND: '#83A617',\n            JUDGE: '#89A1F7',\n            CALC: '#E8B349',\n            VARIABLE: '#CE38CE',\n            HARDWARE: '#FFFFFF',\n            EXPANSION: '#FF8888',\n            AI_UTILIZE: '#FF8888',\n            HIDDEN: '#FFFFFF',\n        },\n    },\n    block: {\n        default: {\n            START: '#00b400',\n            FLOW: '#19baea',\n            MOVING: '#ad3efb',\n            LOOKS: '#ff3a61',\n            BRUSH: '#ff9b00',\n            TEXT: '#e43500',\n            SOUND: '#67b100',\n            JUDGE: '#4562f5',\n            CALC: '#f4af18',\n            VARIABLE: '#dd47d8',\n            ANALYSIS: '#25aeff',\n            FUNC: '#de5c04',\n            HARDWARE: '#00b6b1',\n            EXPANSION: '#ef6d6d',\n            AI_UTILIZE: '#8222ff',\n            HIDDEN: '#8aa3b2',\n            AI_LEARNING: '#8222ff',\n        },\n        lighten: {\n            START: '#3bce3b',\n            FLOW: '#6dddfe',\n            MOVING: '#bd65fb',\n            LOOKS: '#ff5577',\n            BRUSH: '#ffb250',\n            TEXT: '#ff6739',\n            SOUND: '#7ecc12',\n            JUDGE: '#99adff',\n            CALC: '#ffde82',\n            VARIABLE: '#f778f3',\n            ANALYSIS: '#d6e9f4',\n            FUNC: '#ff7b22',\n            HARDWARE: '#78d5d3',\n            EXPANSION: '#ffaeae',\n            AI_UTILIZE: '#ffaeae',\n            HIDDEN: '#ffaeae',\n            AI_LEARNING: '#8222ff',\n        },\n        darken: {\n            START: '#009400',\n            FLOW: '#1498c0',\n            MOVING: '#8b19db',\n            LOOKS: '#c72042',\n            BRUSH: '#fc6500',\n            TEXT: '#ad2800',\n            SOUND: '#508a00',\n            JUDGE: '#1b3ad8',\n            CALC: '#ff7f00',\n            VARIABLE: '#b819b3',\n            ANALYSIS: '#1592ff',\n            FUNC: '#a14100',\n            HARDWARE: '#008380',\n            EXPANSION: '#c63f3f',\n            AI_UTILIZE: '#670bdd',\n            HIDDEN: '#728997',\n            AI_LEARNING: '#670bdd',\n        },\n        emphasize: {\n            '#00b400': '#5BC982', //START\n            '#19baea': '#62A5F4', //FLOW\n            '#ad3efb': '#C08FF7', //MOVING\n            '#ff3a61': '#F46487', //LOOKS\n            '#fc7e01': '#FFB05A', //BRUSH\n            '#e43500': '#F2C670', //TEXT\n            '#67b100': '#C4DD31', //SOUND\n            '#4562f5': '#C0CBFF', //JUDGE\n            '#f4af18': '#FCDA90', //CALC\n            '#dd47d8': '#F279F2', //VARIABLE\n            '#de5c04': '#DD884E', //FUNC\n            '#00b6b1': '#09BAB5', //HARDWARE\n            //Not guided emphasize color for EXPANSION\n        },\n    },\n    common: {\n        WHITE: '#FFFFFF',\n        DARK: '#000000',\n        GRAY: '#6c8696',\n        TRANSPARENT: 'transparent',\n        BUTTON: '#4f80ff',\n        BUTTON_BACKGROUND: '#eee',\n        TEXT: '#333',\n        BUTTON_BACKGROUND_DISABLED: '#f9f9f9',\n        BUTTON_DISABLED: '#cbcbcb',\n        ALERT: '#FB2729',\n    },\n};\n\nEntryStatic.getDefaultFontFamily = function () {\n    const localLang = Lang || {};\n    const type = localLang.type;\n    const fallbackType = localLang.fallbackType;\n    const langType = type || fallbackType || 'en';\n    switch (langType) {\n        default:\n            return \"NanumGothic, 'Nanum Gothic', 나눔고딕, NanumGothicWeb, '맑은 고딕', 'Malgun Gothic', Dotum\";\n    }\n};\n\nEntryStatic.getCategoryByBlock = function (blockName) {\n    if (!blockName) {\n        return false;\n    }\n    const allBlocks = EntryStatic.getAllBlocks();\n    for (let i = 0, len = allBlocks.length; i < len; i++) {\n        const blocks = allBlocks[i].blocks;\n        if (blocks.indexOf(blockName) > -1) {\n            return allBlocks[i].category;\n        }\n    }\n    return false;\n};\n\n// for server node js code\nif (typeof exports === 'object') {\n    exports.blockInfo = EntryStatic.blockInfo;\n    exports.getAllBlocks = EntryStatic.getAllBlocks;\n    exports.getCategoryByBlock = EntryStatic.getCategoryByBlock;\n    exports.EntryStatic = EntryStatic;\n}\n"
  },
  {
    "path": "extern/util/static_mini.js",
    "content": "'use strict';\n\n/* eslint-disable */\nvar EntryStatic = {\n    isPracticalCourse: true,\n    fontFamily: \"NanumGothic, 'Nanum Gothic'\",\n    exportBlockFontFamily:\n        \"NanumGothic, 'Nanum Gothic', 'NanumGothic', '나눔고딕','NanumGothicWeb', '맑은 고딕', 'Malgun Gothic', Dotum\",\n    fontOffsetY: -2.5,\n    heightLetter: 'M',\n    objectTypes: ['sprite', 'textBox'],\n};\n\nEntryStatic.usageList = [\n    'usage_event',\n    'usage_signal',\n    'usage_scene',\n    'usage_repeat',\n    'usage_condition_repeat',\n    'usage_condition',\n    'usage_clone',\n    'usage_arrow_move',\n    'usage_rotation',\n    'usage_coordinate',\n    'usage_shape',\n    'usage_speak',\n    'usage_picture_effect',\n    'usage_textBox',\n    'usage_draw',\n    'usage_sound',\n    'usage_confirm',\n    'usage_comp_operation',\n    'usage_logical_operation',\n    'usage_math_operation',\n    'usage_random',\n    'usage_timer',\n    'usage_variable',\n    'usage_list',\n    'usage_ask_answer',\n    'usage_function',\n    'usage_arduino',\n];\n\nEntryStatic.conceptList = [\n    'concept_resource_analytics',\n    'concept_individual',\n    'concept_abstractive',\n    'concept_procedual',\n    'concept_automation',\n    'concept_simulation',\n    'concept_parallel',\n];\n\nEntryStatic.subjectList = [\n    'subject_korean',\n    'subject_mathmatics',\n    'subject_social',\n    'subject_science',\n    'subject_english',\n    'subject_courtesy',\n    'subject_music',\n    'subject_paint',\n    'subject_athletic',\n    'subject_progmatic',\n];\n\nEntryStatic.lectureLevels = [1, 2, 3];\n\n// EntryStatic.lectureLevels = ['level_high', 'level_mid','level_row'];\n\nEntryStatic.lectureGrades = [\n    'e_1',\n    'e_2',\n    'e_3',\n    'e_4',\n    'e_5',\n    'e_6',\n    'm_1',\n    'm_2',\n    'm_3',\n    'general',\n];\n\nEntryStatic.categoryList = [\n    'category_game',\n    'category_animation',\n    'category_media_art',\n    'category_physical',\n    'category_etc',\n];\n\nEntryStatic.requiredTimes = [1, 2, 3, 4, 5];\n\nEntryStatic.searchProjectOption = [\n    {\n        key: 'search_updated',\n        lang: 'search_updated',\n        value: 'updated',\n    },\n    {\n        key: 'search_recent',\n        lang: 'search_recent',\n        value: 'recent',\n    },\n    {\n        key: 'search_complexity',\n        lang: 'search_complexity',\n        value: 'complexity',\n    },\n    {\n        key: 'search_staffPicked',\n        lang: 'search_staffPicked',\n        value: 'staffPicked',\n    },\n    {\n        key: 'search_childCnt',\n        lang: 'search_childCnt',\n        value: 'childCnt',\n    },\n    {\n        key: 'search_likeCnt',\n        lang: 'search_likeCnt',\n        value: 'recentLikeCnt',\n    },\n];\n\nEntryStatic.variableBlockList = [\n    'get_variable',\n    'change_variable',\n    'set_variable',\n    'show_variable',\n    'hide_variable',\n];\n\nEntryStatic.messageBlockList = ['when_message_cast', 'message_cast', 'message_cast_wait'];\n\nEntryStatic.getAllBlocks = function () {\n    return [\n        {\n            category: 'start',\n            blocks: [\n                'when_run_button_click',\n                'when_some_key_pressed',\n                'mouse_clicked',\n                'mouse_click_cancled',\n                'when_object_click',\n                'when_object_click_canceled',\n                'when_message_cast',\n                'message_cast',\n                'message_cast_wait',\n            ],\n        },\n        {\n            category: 'flow',\n            blocks: [\n                'wait_second',\n                'repeat_basic',\n                'repeat_inf',\n                'repeat_while_true',\n                'stop_repeat',\n                'continue_repeat',\n                '_if',\n                'if_else',\n                'wait_until_true',\n                'stop_object',\n            ],\n        },\n        {\n            category: 'moving',\n            blocks: [\n                'move_direction',\n                'bounce_wall',\n                'move_x',\n                'move_y',\n                'move_xy_time',\n                'locate_xy',\n                'locate_xy_time',\n                'locate',\n                'locate_object_time',\n                'rotate_relative',\n                'direction_relative',\n                'rotate_absolute',\n                'direction_absolute',\n                'see_angle_object',\n            ],\n        },\n        {\n            category: 'looks',\n            blocks: [\n                'show',\n                'hide',\n                'dialog_time',\n                'dialog',\n                'change_to_some_shape',\n                'change_to_next_shape',\n                'add_effect_amount',\n                'change_effect_amount',\n                'erase_all_effects',\n                'change_scale_size',\n                'set_scale_size',\n                'change_object_index',\n            ],\n        },\n        {\n            category: 'brush',\n            blocks: [\n                'brush_stamp',\n                'start_drawing',\n                'stop_drawing',\n                'set_color',\n                'change_thickness',\n                'set_thickness',\n                'brush_erase_all',\n            ],\n        },\n        {\n            category: 'text',\n            blocks: [\n                'text_write',\n                'text_append',\n                'text_prepend',\n                'text_change_effect',\n                'text_change_font',\n                'text_change_font_color',\n                'text_change_bg_color',\n                'text_flush',\n            ],\n        },\n        {\n            category: 'sound',\n            blocks: [\n                'sound_something_with_block',\n                'sound_something_wait_with_block',\n                'sound_volume_change',\n                'sound_volume_set',\n            ],\n        },\n        {\n            category: 'judgement',\n            blocks: [\n                'is_clicked',\n                'is_press_some_key',\n                'reach_something',\n                'boolean_basic_operator',\n                'boolean_and_or',\n                'boolean_not',\n            ],\n        },\n        {\n            category: 'calc',\n            blocks: [\n                'calc_basic',\n                'calc_rand',\n                'coordinate_object',\n                'quotient_and_mod',\n                'calc_operation',\n                'get_project_timer_value',\n                'choose_project_timer_action',\n                'set_visible_project_timer',\n                'length_of_string',\n                'combine_something',\n                'char_at',\n                'substring',\n                'replace_string',\n            ],\n        },\n        {\n            category: 'variable',\n            blocks: [\n                'variableAddButton',\n                'ask_and_wait',\n                'get_canvas_input_value',\n                'set_visible_answer',\n                'get_variable',\n                'change_variable',\n                'set_variable',\n                'show_variable',\n                'hide_variable',\n            ],\n        },\n        {\n            category: 'ai_utilize',\n            blocks: [\n                'aiUtilizeBlockAddButton',\n                'aiUtilizeModelTrainButton',\n                'learning_title_image',\n                'learning_title_speech',\n                'learning_title_text',\n                'learning_title_number',\n                'learning_title_regression',\n                'learning_title_cluster',\n                'learning_title_logistic_regression',\n                'learning_title_decisiontree',\n                'learning_title_svm',\n                'retrain_model',\n                'model_is_trained',\n                'set_train_visible',\n                'set_train_chart',\n                'set_regression_option',\n                'get_regression_predict_1',\n                'get_regression_predict_2',\n                'get_regression_predict_3',\n                'get_regression_predict_4',\n                'get_regression_predict_5',\n                'get_regression_predict_6',\n                'get_regression_accuracy',\n                'set_logistic_regression_option',\n                'set_logistic_regression_optimizer',\n                'get_logistic_regression_probability_1',\n                'get_logistic_regression_probability_2',\n                'get_logistic_regression_probability_3',\n                'get_logistic_regression_probability_4',\n                'get_logistic_regression_probability_5',\n                'get_logistic_regression_probability_6',\n                'set_decisiontree_option',\n                'set_decisiontree_tree',\n                'set_svm_option',\n                'set_kernel_linear',\n                'set_kernel_option',\n                'is_result_1',\n                'is_result_2',\n                'is_result_3',\n                'is_result_4',\n                'is_result_5',\n                'is_result_6',\n                'get_predict_1',\n                'get_predict_2',\n                'get_predict_3',\n                'get_predict_4',\n                'get_predict_5',\n                'get_predict_6',\n                'get_result_info',\n                'set_cluster_option_k',\n                'set_cluster_option_centroids',\n                'get_cluster_centriod_count',\n                'get_cluster_centriod_value',\n                'get_cluster_centriod_index_1',\n                'get_cluster_centriod_index_2',\n                'get_cluster_centriod_index_3',\n                'get_cluster_centriod_index_4',\n                'get_cluster_centriod_index_5',\n                'get_cluster_centriod_index_6',\n                'set_number_learning_option_k',\n                'get_number_learning_predict_1',\n                'get_number_learning_predict_2',\n                'get_number_learning_predict_3',\n                'get_number_learning_predict_4',\n                'get_number_learning_predict_5',\n                'get_number_learning_predict_6',\n                'get_number_learning_predict_param_1',\n                'get_number_learning_predict_param_2',\n                'get_number_learning_predict_param_3',\n                'get_number_learning_predict_param_4',\n                'get_number_learning_predict_param_5',\n                'get_number_learning_predict_param_6',\n                'is_number_learning_group_1',\n                'is_number_learning_group_2',\n                'is_number_learning_group_3',\n                'is_number_learning_group_4',\n                'is_number_learning_group_5',\n                'is_number_learning_group_6',\n                'insert_data_for_test',\n                'video_capture_for_image_test',\n                'insert_text_block_for_test',\n                'test_result',\n                'accuracy_of_result',\n                'is_group',\n                'audio_title',\n                'check_microphone',\n                'get_microphone_volume',\n                'speech_to_text_title',\n                'speech_to_text_convert',\n                'timed_speech_to_text_convert',\n                'set_visible_speech_to_text',\n                'speech_to_text_get_value',\n                'tts_title',\n                'read_text',\n                'read_text_wait_with_block',\n                'set_tts_property',\n                'translate_title',\n                'get_translated_string',\n                'check_language',\n                'video_title',\n                'video_draw_webcam',\n                'video_change_cam',\n                'video_check_webcam',\n                'video_flip_camera',\n                'video_set_camera_opacity_option',\n                'video_motion_value',\n                'video_toggle_model',\n                'video_is_model_loaded',\n                'video_object_detected',\n                'video_number_detect',\n                'video_toggle_ind',\n                'video_body_part_coord',\n                'video_face_part_coord',\n                'video_detected_face_info',\n                'media_pipe_title',\n                'media_pipe_video_screen',\n                'media_pipe_switch_camera',\n                'check_connected_camera',\n                'media_pipe_flip_camera',\n                'media_pipe_set_opacity_camera',\n                'media_pipe_motion_value',\n                'hand_detection_title',\n                'when_hand_detection',\n                'hand_detection',\n                'draw_detected_hand',\n                'check_detected_hand',\n                'count_detected_hand',\n                'locate_to_hand',\n                'locate_time_to_hand',\n                'axis_detected_hand',\n                'is_which_hand',\n                'get_which_hand',\n                'is_which_gesture',\n                'get_which_gesture',\n                'pose_landmarker_title',\n                'when_pose_landmarker',\n                'pose_landmarker',\n                'draw_detected_pose',\n                'check_detected_pose',\n                'count_detected_pose',\n                'locate_to_pose',\n                'locate_time_to_pose',\n                'axis_detected_pose',\n                'face_landmarker_title',\n                'when_face_landmarker',\n                'face_landmarker',\n                'draw_detected_face',\n                'check_detected_face',\n                'count_detected_face',\n                'locate_to_face',\n                'locate_time_to_face',\n                'check_detected_gender',\n                'check_compare_age',\n                'check_detected_emotion',\n                'axis_detected_face',\n                'get_detected_face_value',\n                'object_detector_title',\n                'when_object_detector',\n                'object_detector',\n                'draw_detected_object',\n                'check_detected_object',\n                'count_detected_object',\n                'is_detected_among_objects',\n            ],\n        },\n        {\n            category: 'hw_sensor',\n            visible: false,\n            blocks: [\n                'practical_course_dummy',\n                'hardware_device_name_title_sensor',\n                'hardware_device_name_content_sensor',\n            ].concat(EntryStatic.DynamicPracticalHardwareBlocks['hw_sensor']),\n        },\n        {\n            category: 'hw_motor',\n            visible: false,\n            blocks: [\n                'practical_course_dummy',\n                'hardware_device_name_title_motor',\n                'hardware_device_name_content_motor',\n            ].concat(EntryStatic.DynamicPracticalHardwareBlocks['hw_motor']),\n        },\n        {\n            category: 'hw_led',\n            visible: false,\n            blocks: [\n                'practical_course_dummy',\n                'hardware_device_name_title_led',\n                'hardware_device_name_content_led',\n            ].concat(EntryStatic.DynamicPracticalHardwareBlocks['hw_led']),\n        },\n        {\n            category: 'hw_melody',\n            visible: false,\n            blocks: [\n                'practical_course_dummy',\n                'hardware_device_name_title_melody',\n                'hardware_device_name_content_melody',\n            ].concat(EntryStatic.DynamicPracticalHardwareBlocks['hw_melody']),\n        },\n        {\n            category: 'hw_robot',\n            blocks: [\n                'robot_connect_helper',\n                'robot_reconnect',\n                'arduino_open',\n                'arduino_connect',\n                'hardware_program_download',\n                'arduino_connected',\n                'hardware_device_name_title_robot',\n                'hardware_device_name_content',\n                'hardware_connected_noti',\n                'robot_noti',\n            ],\n        },\n        {\n            category: 'arduino',\n            visible: false,\n            blocks: EntryStatic.DynamicHardwareBlocks,\n        },\n    ];\n};\nEntryStatic.DynamicHardwareBlocks = [];\nEntryStatic.discussCategories = [\n    // 'notice',\n    'qna',\n    'tips',\n    'free',\n    'report',\n    'notice',\n];\n\nEntryStatic.artCategories = [\n    {\n        key: 'art_category_',\n        lang: 'art_category_all',\n        value: '',\n    },\n    {\n        key: 'art_category_게임',\n        lang: 'art_category_game',\n        value: '게임',\n    },\n    {\n        key: 'art_category_애니메이션',\n        lang: 'art_category_animation',\n        value: '애니메이션',\n    },\n    {\n        key: 'art_category_미디어아트',\n        lang: 'art_category_media',\n        value: '미디어아트',\n    },\n    {\n        key: 'art_category_피지컬',\n        lang: 'art_category_physical',\n        value: '피지컬',\n    },\n    {\n        key: 'art_category_기타',\n        lang: 'art_category_etc',\n        value: '기타',\n    },\n];\n\nEntryStatic.artSortOptions = [\n    {\n        key: 'art_sort_updated',\n        lang: 'art_sort_updated',\n        value: 'updated',\n    },\n    {\n        key: 'art_sort_visit',\n        lang: 'art_sort_visit',\n        value: 'visit',\n    },\n    {\n        key: 'art_sort_likeCnt',\n        lang: 'art_sort_likeCnt',\n        value: 'likeCnt',\n    },\n    {\n        key: 'art_sort_comment',\n        lang: 'art_sort_comment',\n        value: 'comment',\n    },\n];\n\nEntryStatic.discussSortOptions = [\n    {\n        lang: 'discuss_sort_created',\n        value: 'created',\n    },\n    {\n        lang: 'discuss_sort_visit',\n        value: 'visit',\n    },\n    {\n        lang: 'discuss_sort_likesLength',\n        value: 'likesLength',\n    },\n    {\n        lang: 'discuss_sort_commentsLength',\n        value: 'commentsLength',\n    },\n];\nEntryStatic.discussPeriodOptions = [\n    {\n        key: 'discuss_period_',\n        lang: 'discuss_period_all',\n        value: '',\n    },\n    {\n        key: 'discuss_period_1',\n        lang: 'discuss_period_day',\n        value: '1',\n    },\n    {\n        key: 'discuss_period_7',\n        lang: 'discuss_period_week',\n        value: '7',\n    },\n    {\n        key: 'discuss_period_30',\n        lang: 'discuss_period_month',\n        value: '30',\n    },\n    {\n        key: 'discuss_period_90',\n        lang: 'discuss_period_three_month',\n        value: '90',\n    },\n];\n\nEntryStatic.artPeriodOptions = [\n    {\n        key: 'art_period_',\n        lang: 'art_period_all',\n        value: '',\n    },\n    {\n        key: 'art_period_1',\n        lang: 'art_period_day',\n        value: '1',\n    },\n    {\n        key: 'art_period_7',\n        lang: 'art_period_week',\n        value: '7',\n    },\n    {\n        key: 'art_period_30',\n        lang: 'art_period_month',\n        value: '30',\n    },\n    {\n        key: 'art_period_90',\n        lang: 'art_period_three_month',\n        value: '90',\n    },\n];\n\nEntryStatic.getCategoryByBlock = function (blockName) {\n    if (!blockName) {\n        return false;\n    }\n    let allBlocks = EntryStatic.getAllBlocks();\n    for (let i = 0, len = allBlocks.length; i < len; i++) {\n        let blocks = allBlocks[i].blocks;\n        if (blocks.indexOf(blockName) > -1) {\n            return allBlocks[i].category;\n        }\n    }\n    return false;\n};\n\nEntryStatic.objectMainCategories = [\n    'entrybot_friends',\n    'people',\n    'animal',\n    'plant',\n    'vehicles',\n    'architect',\n    'food',\n    'environment',\n    'stuff',\n    'fantasy',\n    'interface',\n    'background',\n];\n\nEntryStatic.objectSubCategories = {\n    entrybot_friends: [],\n    people: [],\n    animal: ['animal_flying', 'animal_land', 'animal_water', 'animal_others'],\n    plant: ['plant_flower', 'plant_grass', 'plant_tree', 'plant_others'],\n    vehicles: ['vehicles_flying', 'vehicles_land', 'vehicles_water', 'vehicles_others'],\n    architect: ['architect_building', 'architect_monument', 'architect_others'],\n    food: ['food_vegetables', 'food_meat', 'food_drink', 'food_others'],\n    environment: ['environment_nature', 'environment_space', 'environment_others'],\n    stuff: ['stuff_living', 'stuff_hobby', 'stuff_others'],\n    fantasy: [],\n    interface: ['interface_website', 'interface_game', 'interface_others'],\n    background: [\n        'background_outdoor',\n        'background_indoor',\n        'background_nature',\n        'background_others',\n    ],\n};\n\nEntryStatic.fonts = [\n    {\n        name: Lang.Fonts.batang,\n        family: 'KoPub Batang',\n        url: '/css/kopubbatang.css',\n        visible: false,\n    },\n    {\n        name: Lang.Fonts.jeju_hallasan,\n        family: 'Jeju Hallasan',\n        url: '/css/jejuhallasan.css',\n        visible: false,\n    },\n    {\n        name: Lang.Fonts.gothic,\n        family: 'Nanum Gothic',\n        url: '/css/nanumgothic.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.myeongjo,\n        family: 'Nanum Myeongjo',\n        url: '/css/nanummyeongjo.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.nanumbarunpen,\n        family: 'Nanum Barun Pen',\n        url: '/css/nanumbarunpen.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.pen_script,\n        family: 'Nanum Pen Script',\n        url: '/css/nanumpenscript.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.square_round,\n        family: 'NanumSquareRound',\n        url: '/css/square_round.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.maruburi,\n        family: 'MaruBuri',\n        url: '/css/maruburi.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.notosans,\n        family: 'NotoSans',\n        url: '/css/notosans.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.d2coding,\n        family: 'D2 Coding',\n        url: '/css/d2coding.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.jalnan,\n        family: 'yg-jalnan',\n        url: '/css/jalnan.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.designhouse,\n        family: 'designhouseOTFLight00',\n        url: '/css/designhouse.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.dunggeunmo,\n        family: 'DungGeunMo',\n        url: '/css/dunggeunmo.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.uhbeemysen,\n        family: 'UhBeemysen',\n        url: '/css/uhbeemysen.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.sd_comic_stencil,\n        family: 'SDComicStencil',\n        style: {\n            backgroundColor: '#f7fcff',\n            padding: '17px 22px 14px 16px',\n            margin: '0px',\n            borderTop: 'solid 1px #d6e9f4',\n        },\n        url: '/css/SDComicStencil.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.sd_childfundkorea,\n        family: 'SDChildfundkorea',\n        style: {\n            backgroundColor: '#f7fcff',\n            padding: '17px 22px 14px 16px',\n            margin: '0px',\n            borderTop: 'solid 1px #d6e9f4',\n        },\n        url: '/css/SDChildfundkorea.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.sd_cinema_theater,\n        family: 'SDCinemaTheater',\n        style: {\n            backgroundColor: '#f7fcff',\n            padding: '17px 22px 14px 16px',\n            margin: '0px',\n            borderTop: 'solid 1px #d6e9f4',\n        },\n        url: '/css/SDCinemaTheater.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.sd_mapssi,\n        family: 'SDMapssi',\n        style: {\n            backgroundColor: '#f7fcff',\n            padding: '17px 22px 14px 16px',\n            margin: '0px',\n            borderTop: 'solid 1px #d6e9f4',\n        },\n        url: '/css/SDMapssi.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.sd_shabang,\n        family: 'SDShabang',\n        style: {\n            backgroundColor: '#f7fcff',\n            padding: '17px 22px 14px 16px',\n            margin: '0px',\n            borderTop: 'solid 1px #d6e9f4',\n        },\n        url: '/css/SDShabang.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.sd_woodcarving,\n        family: 'SDWoodcarving',\n        style: {\n            backgroundColor: '#f7fcff',\n            padding: '17px 22px 14px 16px',\n            margin: '0px',\n            borderTop: 'solid 1px #d6e9f4',\n        },\n        url: '/css/SDWoodcarving.css',\n        visible: true,\n    },\n    {\n        name: Lang.Fonts.sd_yongbi,\n        family: 'SDYongbi',\n        style: {\n            backgroundColor: '#f7fcff',\n            padding: '17px 22px 14px 16px',\n            margin: '0px',\n            borderTop: 'solid 1px #d6e9f4',\n        },\n        url: '/css/SDYongbi.css',\n        visible: true,\n    },\n];\n\nEntryStatic.colorSet = {\n    arrow: {\n        default: {\n            DEFAULT: '#FFFFFF',\n            START: '#FFFFFF',\n            FLOW: '#3A71BC',\n            MOVING: '#8641B6',\n            LOOKS: '#FFFFFF',\n            TEXT: '#DC9C32',\n            SOUND: '#83A617',\n            JUDGE: '#89A1F7',\n            CALC: '#E8B349',\n            VARIABLE: '#CE38CE',\n            HARDWARE: '#FFFFFF',\n            EXPANSION: '#FF8888',\n            AI_UTILIZE: '#FF8888',\n        },\n    },\n    block: {\n        default: {\n            START: '#00b400',\n            FLOW: '#19baea',\n            MOVING: '#ad3efb',\n            LOOKS: '#ff3a61',\n            BRUSH: '#ff9b00',\n            TEXT: '#e43500',\n            SOUND: '#67b100',\n            JUDGE: '#4562f5',\n            CALC: '#f4af18',\n            VARIABLE: '#dd47d8',\n            ANALYSIS: '#25aeff',\n            FUNC: '#de5c04',\n            HARDWARE: '#00b6b1',\n            EXPANSION: '#ef6d6d',\n            AI_UTILIZE: '#8222ff',\n            HIDDEN: '#8aa3b2',\n            AI_LEARNING: '#8222ff',\n        },\n        lighten: {\n            START: '#3bce3b',\n            FLOW: '#6dddfe',\n            MOVING: '#bd65fb',\n            LOOKS: '#ff5577',\n            BRUSH: '#ffb250',\n            TEXT: '#ff6739',\n            SOUND: '#7ecc12',\n            JUDGE: '#99adff',\n            CALC: '#ffde82',\n            VARIABLE: '#f778f3',\n            ANALYSIS: '#d6e9f4',\n            FUNC: '#ff7b22',\n            HARDWARE: '#78d5d3',\n            EXPANSION: '#ffaeae',\n            AI_UTILIZE: '#ffaeae',\n            HIDDEN: '#ffaeae',\n            AI_LEARNING: '#8222ff',\n        },\n        darken: {\n            START: '#009400',\n            FLOW: '#1498c0',\n            MOVING: '#8b19db',\n            LOOKS: '#c72042',\n            BRUSH: '#fc6500',\n            TEXT: '#ad2800',\n            SOUND: '#508a00',\n            JUDGE: '#1b3ad8',\n            CALC: '#ff7f00',\n            VARIABLE: '#b819b3',\n            ANALYSIS: '#1592ff',\n            FUNC: '#a14100',\n            HARDWARE: '#008380',\n            EXPANSION: '#c63f3f',\n            AI_UTILIZE: '#670bdd',\n            HIDDEN: '#728997',\n            AI_LEARNING: '#670bdd',\n        },\n        emphasize: {\n            '#00b400': '#5BC982', //START\n            '#19baea': '#62A5F4', //FLOW\n            '#ad3efb': '#C08FF7', //MOVING\n            '#ff3a61': '#F46487', //LOOKS\n            '#fc7e01': '#FFB05A', //BRUSH\n            '#e43500': '#F2C670', //TEXT\n            '#67b100': '#C4DD31', //SOUND\n            '#4562f5': '#C0CBFF', //JUDGE\n            '#f4af18': '#FCDA90', //CALC\n            '#dd47d8': '#F279F2', //VARIABLE\n            '#de5c04': '#DD884E', //FUNC\n            '#00b6b1': '#09BAB5', //HARDWARE\n            //Not guided emphasize color for EXPANSION\n        },\n    },\n    common: {\n        WHITE: '#FFFFFF',\n        DARK: '#000000',\n        GRAY: '#6c8696',\n        TRANSPARENT: 'transparent',\n        BUTTON: '#4f80ff',\n        BUTTON_BACKGROUND: '#eee',\n        TEXT: '#333',\n        ALERT: '#FB2729',\n    },\n};\n\nEntryStatic.initOptions = {\n    listEnable: false,\n    functionEnable: false,\n    sceneEditable: false,\n};\n\nEntryStatic.hwCategoryList = ['hw_sensor', 'hw_motor', 'hw_led', 'hw_melody'];\n\nEntryStatic.DynamicPracticalHardwareBlocks = {};\n\nEntryStatic.hwCategoryList.forEach((category) => {\n    EntryStatic.DynamicPracticalHardwareBlocks[category] = [];\n});\n\nEntryStatic.hwMiniSupportList = [\n    'neobot',\n    'roborobo_schoolkit',\n    'robotis_openCM70',\n    'robotis_openCM70EDU',\n    'robotis_Dream',\n];\n\nEntryStatic.COMMAND_TYPES = {\n    addThread: 101,\n    destroyThread: 102,\n    destroyBlock: 103,\n    recoverBlock: 104,\n    insertBlock: 105,\n    separateBlock: 106,\n    moveBlock: 107,\n    cloneBlock: 108,\n    uncloneBlock: 109,\n    scrollBoard: 110,\n    setFieldValue: 111,\n\n    selectObject: 201,\n\n    do: 301,\n    undo: 302,\n    redo: 303,\n};\n\nEntryStatic.getDefaultFontFamily = function () {\n    const localLang = Lang || {};\n    const type = localLang.type;\n    const fallbackType = localLang.fallbackType;\n    const langType = type || fallbackType || 'en';\n    switch (langType) {\n        default:\n            return \"NanumGothic, 'Nanum Gothic', 나눔고딕, NanumGothicWeb, '맑은 고딕', 'Malgun Gothic', Dotum\";\n    }\n};\n\n// for server node js code\nif (typeof exports == 'object') {\n    exports.blockInfo = EntryStatic.blockInfo;\n    exports.getAllBlocks = EntryStatic.getAllBlocks;\n    exports.getCategoryByBlock = EntryStatic.getCategoryByBlock;\n    exports.EntryStatic = EntryStatic;\n}\n"
  },
  {
    "path": "extern/vision.worker.js",
    "content": "self.importScripts(`${self.location.pathname}/../vision_bundle.js`);\n\nself.onmessage = async ({ data }) => {\n    if (data.action === 'pose_landmarker_init') {\n        initializePoseLandmarker(data);\n    } else if (data.action === 'gesture_recognizer_change_option') {\n        changeGestureOption(data.option);\n    } else if (data.action === 'pose_landmarker') {\n        predictPoseLandmarker(data.imageBitmap);\n    } else if (data.action === 'clear_pose_landmarker') {\n        clearPredictPoseLandmarker();\n    }\n};\n\nlet workerContext;\nlet drawingUtils;\nlet gestureRecognizer;\nlet poseLandmarker;\nlet isPrevHandDetected = false;\nlet isPrevPoseLandmarker = false;\nlet countDetectedHand = 0;\nlet isDrawDetectedHand = false;\nlet isDrawDetectedPoseLandmarker = false;\n\nconst initializePoseLandmarker = async (data) => {\n    const { canvas } = data;\n    isDrawDetectedPoseLandmarker = data.isDrawDetectedPoseLandmarker;\n    workerContext = canvas.getContext('2d');\n    workerContext.font = '20px Arial';\n    drawingUtils = new DrawingUtils(workerContext);\n    const vision = await FilesetResolver.forVisionTasks(`${self.location.pathname}/../wasm`);\n    poseLandmarker = await PoseLandmarker.createFromOptions(vision, {\n        baseOptions: {\n            modelAssetPath: `${self.location.pathname}/../model/pose_landmarker_lite.task`,\n            delegate: 'GPU',\n        },\n        runningMode: 'VIDEO',\n        numPoses: 1,\n    });\n    self.postMessage({ action: 'next_pose_landmarker' });\n};\n\nconst YX = (a) => {\n    return Math.max(1, Math.min(10, 10 * (1 - (a - -0.15) / 0.25) + (1 - (0.1 - a) / 0.25)));\n};\n\nconst predictPoseLandmarker = async (imageBitmap) => {\n    try {\n        if (!workerContext || !poseLandmarker) {\n            return;\n        }\n        const startTimeMs = performance.now();\n        const results = await poseLandmarker.detectForVideo(imageBitmap, startTimeMs);\n        workerContext.save();\n        workerContext.clearRect(0, 0, 640, 360);\n        const { landmarks } = results;\n        self.postMessage({\n            action: 'pose_landmaker_data',\n            poseLandmarkerResult: results,\n        });\n        if (landmarks.length) {\n            if (!isPrevPoseLandmarker) {\n                isPrevPoseLandmarker = true;\n                self.postMessage({ action: 'start_pose_landmarker' });\n            }\n            // if (landmarks.length !== countDetectedHand) {\n            //     countDetectedHand = landmarks.length;\n            //     self.postMessage({\n            //         action: 'count_detected_hand_gesture_recognizer',\n            //         count: countDetectedHand,\n            //     });\n            // }\n            // if (!isDrawDetectedPoseLandmarker) {\n            //     return;\n            // }\n            landmarks.forEach((landmark, i) => {\n                drawingUtils.drawLandmarks(landmark, {\n                    radius: (data) => DrawingUtils.lerp(data.from.z, -0.15, 0.1, 5, 1),\n                });\n                drawingUtils.drawConnectors(landmark, PoseLandmarker.POSE_CONNECTIONS);\n            });\n        } else if (isPrevPoseLandmarker) {\n            isPrevPoseLandmarker = false;\n            // countDetectedHand = 0;\n            self.postMessage({ action: 'stop_pose_landmarker' });\n        }\n    } catch (e) {\n        console.error(e);\n    } finally {\n        workerContext.restore();\n        requestAnimationFrame(() => {\n            self.postMessage({ action: 'next_pose_landmarker' });\n        });\n    }\n};\n\nconst clearPredictPoseLandmarker = () => {\n    console.log('clearPredictPoseLandmarker');\n    workerContext.clearRect(0, 0, 640, 360);\n};\n"
  },
  {
    "path": "extern/vision_bundle.js",
    "content": "var commonjsGlobal =\n        'undefined' != typeof globalThis\n            ? globalThis\n            : 'undefined' != typeof window\n            ? window\n            : 'undefined' != typeof global\n            ? global\n            : 'undefined' != typeof self\n            ? self\n            : {},\n    vision = {},\n    fileset_resolver = {};\nlet supportsSimd;\nObject.defineProperty(fileset_resolver, '__esModule', { value: !0 }),\n    (fileset_resolver.FilesetResolver = void 0);\nconst WASM_SIMD_CHECK = new Uint8Array([\n    0,\n    97,\n    115,\n    109,\n    1,\n    0,\n    0,\n    0,\n    1,\n    5,\n    1,\n    96,\n    0,\n    1,\n    123,\n    3,\n    2,\n    1,\n    0,\n    10,\n    10,\n    1,\n    8,\n    0,\n    65,\n    0,\n    253,\n    15,\n    253,\n    98,\n    11,\n]);\nasync function isSimdSupported() {\n    if (void 0 === supportsSimd)\n        try {\n            await WebAssembly.instantiate(WASM_SIMD_CHECK), (supportsSimd = !0);\n        } catch (e) {\n            supportsSimd = !1;\n        }\n    return supportsSimd;\n}\nasync function createFileset(e, t = '') {\n    const r = (await isSimdSupported()) ? 'wasm_internal' : 'wasm_nosimd_internal';\n    return { wasmLoaderPath: `${t}/${e}_${r}.js`, wasmBinaryPath: `${t}/${e}_${r}.wasm` };\n}\nclass FilesetResolver$1 {\n    static isSimdSupported() {\n        return isSimdSupported();\n    }\n    static forAudioTasks(e) {\n        return createFileset('audio', e);\n    }\n    static forTextTasks(e) {\n        return createFileset('text', e);\n    }\n    static forVisionTasks(e) {\n        return createFileset('vision', e);\n    }\n}\nfileset_resolver.FilesetResolver = FilesetResolver$1;\nvar drawing_utils = {};\nObject.defineProperty(drawing_utils, '__esModule', { value: !0 }),\n    (drawing_utils.DrawingUtils = void 0);\nconst DEFAULT_OPTIONS = { color: 'white', lineWidth: 4, radius: 6 };\nfunction addDefaultOptions(e) {\n    return (\n        (e = e || {}),\n        Object.assign(Object.assign(Object.assign({}, DEFAULT_OPTIONS), { fillColor: e.color }), e)\n    );\n}\nfunction resolve(e, t) {\n    return e instanceof Function ? e(t) : e;\n}\nclass DrawingUtils$1 {\n    constructor(e) {\n        this.ctx = e;\n    }\n    static clamp(e, t, r) {\n        const o = Math.min(t, r),\n            i = Math.max(t, r);\n        return Math.max(o, Math.min(i, e));\n    }\n    static lerp(e, t, r, o, i) {\n        const a = o * (1 - (e - t) / (r - t)) + i * (1 - (r - e) / (r - t));\n        return DrawingUtils$1.clamp(a, o, i);\n    }\n    drawLandmarks(e, t) {\n        if (!e) return;\n        const r = this.ctx,\n            o = addDefaultOptions(t);\n        r.save();\n        const i = r.canvas;\n        let a = 0;\n        for (const t of e) {\n            (r.fillStyle = resolve(o.fillColor, { index: a, from: t })),\n                (r.strokeStyle = resolve(o.color, { index: a, from: t })),\n                (r.lineWidth = resolve(o.lineWidth, { index: a, from: t }));\n            const e = new Path2D();\n            e.arc(\n                t.x * i.width,\n                t.y * i.height,\n                resolve(o.radius, { index: a, from: t }),\n                0,\n                2 * Math.PI\n            ),\n                r.fill(e),\n                r.stroke(e),\n                ++a;\n        }\n        r.restore();\n    }\n    drawConnectors(e, t, r) {\n        if (!e || !t) return;\n        const o = this.ctx,\n            i = addDefaultOptions(r);\n        o.save();\n        const a = o.canvas;\n        let n = 0;\n        for (const r of t) {\n            o.beginPath();\n            const t = e[r.start],\n                s = e[r.end];\n            t &&\n                s &&\n                ((o.strokeStyle = resolve(i.color, { index: n, from: t, to: s })),\n                (o.lineWidth = resolve(i.lineWidth, { index: n, from: t, to: s })),\n                o.moveTo(t.x * a.width, t.y * a.height),\n                o.lineTo(s.x * a.width, s.y * a.height)),\n                ++n,\n                o.stroke();\n        }\n        o.restore();\n    }\n    drawBoundingBox(e, t) {\n        const r = this.ctx,\n            o = addDefaultOptions(t);\n        r.save(),\n            r.beginPath(),\n            (r.lineWidth = resolve(o.lineWidth, {})),\n            (r.strokeStyle = resolve(o.color, {})),\n            (r.fillStyle = resolve(o.fillColor, {})),\n            r.moveTo(e.originX, e.originY),\n            r.lineTo(e.originX + e.width, e.originY),\n            r.lineTo(e.originX + e.width, e.originY + e.height),\n            r.lineTo(e.originX, e.originY + e.height),\n            r.lineTo(e.originX, e.originY),\n            r.stroke(),\n            r.fill(),\n            r.restore();\n    }\n}\ndrawing_utils.DrawingUtils = DrawingUtils$1;\nvar image = {},\n    image_shader_context = {};\nObject.defineProperty(image_shader_context, '__esModule', { value: !0 }),\n    (image_shader_context.MPImageShaderContext = image_shader_context.assertNotNull = void 0);\nconst VERTEX_SHADER =\n        '\\n  attribute vec2 aVertex;\\n  attribute vec2 aTex;\\n  varying vec2 vTex;\\n  void main(void) {\\n    gl_Position = vec4(aVertex, 0.0, 1.0);\\n    vTex = aTex;\\n  }',\n    FRAGMENT_SHADER =\n        '\\n  precision mediump float;\\n  varying vec2 vTex;\\n  uniform sampler2D inputTexture;\\n   void main() {\\n     gl_FragColor = texture2D(inputTexture, vTex);\\n   }\\n ';\nfunction assertNotNull(e, t) {\n    if (null === e) throw new Error(`Unable to obtain required WebGL resource: ${t}`);\n    return e;\n}\nimage_shader_context.assertNotNull = assertNotNull;\nclass MPImageShaderBuffers {\n    constructor(e, t, r, o) {\n        (this.gl = e),\n            (this.vertexArrayObject = t),\n            (this.vertexBuffer = r),\n            (this.textureBuffer = o);\n    }\n    bind() {\n        this.gl.bindVertexArray(this.vertexArrayObject);\n    }\n    unbind() {\n        this.gl.bindVertexArray(null);\n    }\n    close() {\n        this.gl.deleteVertexArray(this.vertexArrayObject),\n            this.gl.deleteBuffer(this.vertexBuffer),\n            this.gl.deleteBuffer(this.textureBuffer);\n    }\n}\nclass MPImageShaderContext {\n    compileShader(e, t) {\n        const r = this.gl,\n            o = assertNotNull(r.createShader(t), 'Failed to create WebGL shader');\n        if (\n            (r.shaderSource(o, e), r.compileShader(o), !r.getShaderParameter(o, r.COMPILE_STATUS))\n        ) {\n            const e = r.getShaderInfoLog(o);\n            throw new Error(`Could not compile WebGL shader: ${e}`);\n        }\n        return r.attachShader(this.program, o), o;\n    }\n    setupShaders() {\n        const e = this.gl;\n        (this.program = assertNotNull(e.createProgram(), 'Failed to create WebGL program')),\n            (this.vertexShader = this.compileShader(VERTEX_SHADER, e.VERTEX_SHADER)),\n            (this.fragmentShader = this.compileShader(FRAGMENT_SHADER, e.FRAGMENT_SHADER)),\n            e.linkProgram(this.program);\n        if (!e.getProgramParameter(this.program, e.LINK_STATUS)) {\n            const t = e.getProgramInfoLog(this.program);\n            throw new Error(`Error during program linking: ${t}`);\n        }\n        (this.aVertex = e.getAttribLocation(this.program, 'aVertex')),\n            (this.aTex = e.getAttribLocation(this.program, 'aTex'));\n    }\n    createBuffers(e) {\n        const t = this.gl,\n            r = assertNotNull(t.createVertexArray(), 'Failed to create vertex array');\n        t.bindVertexArray(r);\n        const o = assertNotNull(t.createBuffer(), 'Failed to create buffer');\n        t.bindBuffer(t.ARRAY_BUFFER, o),\n            t.enableVertexAttribArray(this.aVertex),\n            t.vertexAttribPointer(this.aVertex, 2, t.FLOAT, !1, 0, 0),\n            t.bufferData(\n                t.ARRAY_BUFFER,\n                new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]),\n                t.STATIC_DRAW\n            );\n        const i = assertNotNull(t.createBuffer(), 'Failed to create buffer');\n        t.bindBuffer(t.ARRAY_BUFFER, i),\n            t.enableVertexAttribArray(this.aTex),\n            t.vertexAttribPointer(this.aTex, 2, t.FLOAT, !1, 0, 0);\n        const a = e ? [0, 1, 0, 0, 1, 0, 1, 1] : [0, 0, 0, 1, 1, 1, 1, 0];\n        return (\n            t.bufferData(t.ARRAY_BUFFER, new Float32Array(a), t.STATIC_DRAW),\n            t.bindBuffer(t.ARRAY_BUFFER, null),\n            t.bindVertexArray(null),\n            new MPImageShaderBuffers(t, r, o, i)\n        );\n    }\n    getShaderBuffers(e) {\n        return e\n            ? (this.shaderBuffersFlipVertically ||\n                  (this.shaderBuffersFlipVertically = this.createBuffers(!0)),\n              this.shaderBuffersFlipVertically)\n            : (this.shaderBuffersPassthrough ||\n                  (this.shaderBuffersPassthrough = this.createBuffers(!1)),\n              this.shaderBuffersPassthrough);\n    }\n    maybeInitGL(e) {\n        if (this.gl) {\n            if (e !== this.gl) throw new Error('Cannot change GL context once initialized');\n        } else this.gl = e;\n    }\n    run(e, t, r) {\n        this.maybeInitGL(e), this.program || this.setupShaders();\n        const o = this.getShaderBuffers(t);\n        e.useProgram(this.program), o.bind();\n        const i = r();\n        return o.unbind(), i;\n    }\n    bindFramebuffer(e, t) {\n        this.maybeInitGL(e),\n            this.framebuffer ||\n                (this.framebuffer = assertNotNull(\n                    e.createFramebuffer(),\n                    'Failed to create framebuffe.'\n                )),\n            e.bindFramebuffer(e.FRAMEBUFFER, this.framebuffer),\n            e.framebufferTexture2D(e.FRAMEBUFFER, e.COLOR_ATTACHMENT0, e.TEXTURE_2D, t, 0);\n    }\n    unbindFramebuffer() {\n        var e;\n        null === (e = this.gl) || void 0 === e || e.bindFramebuffer(this.gl.FRAMEBUFFER, null);\n    }\n    close() {\n        if (this.program) {\n            const e = this.gl;\n            e.deleteProgram(this.program),\n                e.deleteShader(this.vertexShader),\n                e.deleteShader(this.fragmentShader);\n        }\n        this.framebuffer && this.gl.deleteFramebuffer(this.framebuffer),\n            this.shaderBuffersPassthrough && this.shaderBuffersPassthrough.close(),\n            this.shaderBuffersFlipVertically && this.shaderBuffersFlipVertically.close();\n    }\n}\n(image_shader_context.MPImageShaderContext = MPImageShaderContext),\n    Object.defineProperty(image, '__esModule', { value: !0 }),\n    (image.MPImage = void 0);\nconst image_shader_context_1$2 = image_shader_context,\n    INSTANCE_COUNT_WARNING_THRESHOLD$1 = 250;\nvar MPImageType;\n!(function(e) {\n    (e[(e.IMAGE_DATA = 0)] = 'IMAGE_DATA'),\n        (e[(e.IMAGE_BITMAP = 1)] = 'IMAGE_BITMAP'),\n        (e[(e.WEBGL_TEXTURE = 2)] = 'WEBGL_TEXTURE');\n})(MPImageType || (MPImageType = {}));\nclass MPImage$1 {\n    constructor(e, t, r, o, i, a, n) {\n        (this.containers = e),\n            (this.ownsImageBitmap = t),\n            (this.ownsWebGLTexture = r),\n            (this.canvas = o),\n            (this.shaderContext = i),\n            (this.width = a),\n            (this.height = n),\n            (this.ownsImageBitmap || this.ownsWebGLTexture) &&\n                (--MPImage$1.instancesBeforeWarning,\n                0 === MPImage$1.instancesBeforeWarning &&\n                    console.error(\n                        'You seem to be creating MPImage instances without invoking .close(). This leaks resources.'\n                    ));\n    }\n    hasImageData() {\n        return !!this.getContainer(MPImageType.IMAGE_DATA);\n    }\n    hasImageBitmap() {\n        return !!this.getContainer(MPImageType.IMAGE_BITMAP);\n    }\n    hasWebGLTexture() {\n        return !!this.getContainer(MPImageType.WEBGL_TEXTURE);\n    }\n    getAsImageData() {\n        return this.convertToImageData();\n    }\n    getAsImageBitmap() {\n        return this.convertToImageBitmap();\n    }\n    getAsWebGLTexture() {\n        return this.convertToWebGLTexture();\n    }\n    getContainer(e) {\n        switch (e) {\n            case MPImageType.IMAGE_DATA:\n                return this.containers.find((e) => e instanceof ImageData);\n            case MPImageType.IMAGE_BITMAP:\n                return this.containers.find(\n                    (e) => 'undefined' != typeof ImageBitmap && e instanceof ImageBitmap\n                );\n            case MPImageType.WEBGL_TEXTURE:\n                return this.containers.find(\n                    (e) => 'undefined' != typeof WebGLTexture && e instanceof WebGLTexture\n                );\n            default:\n                throw new Error(`Type is not supported: ${e}`);\n        }\n    }\n    clone() {\n        const e = [];\n        for (const t of this.containers) {\n            let r;\n            if (t instanceof ImageData) r = new ImageData(t.data, this.width, this.height);\n            else if (t instanceof WebGLTexture) {\n                const e = this.getGL(),\n                    t = this.getShaderContext();\n                e.activeTexture(e.TEXTURE1),\n                    (r = (0, image_shader_context_1$2.assertNotNull)(\n                        e.createTexture(),\n                        'Failed to create texture'\n                    )),\n                    e.bindTexture(e.TEXTURE_2D, r),\n                    this.configureTextureParams(),\n                    e.texImage2D(\n                        e.TEXTURE_2D,\n                        0,\n                        e.RGBA,\n                        this.width,\n                        this.height,\n                        0,\n                        e.RGBA,\n                        e.UNSIGNED_BYTE,\n                        null\n                    ),\n                    e.bindTexture(e.TEXTURE_2D, null),\n                    t.bindFramebuffer(e, r),\n                    t.run(e, !1, () => {\n                        this.bindTexture(),\n                            e.clearColor(0, 0, 0, 0),\n                            e.clear(e.COLOR_BUFFER_BIT),\n                            e.drawArrays(e.TRIANGLE_FAN, 0, 4),\n                            this.unbindTexture();\n                    }),\n                    t.unbindFramebuffer(),\n                    this.unbindTexture();\n            } else {\n                if (!(t instanceof ImageBitmap)) throw new Error(`Type is not supported: ${t}`);\n                this.convertToWebGLTexture(),\n                    this.bindTexture(),\n                    (r = this.copyTextureToBitmap()),\n                    this.unbindTexture();\n            }\n            e.push(r);\n        }\n        return new MPImage$1(\n            e,\n            this.hasImageBitmap(),\n            this.hasWebGLTexture(),\n            this.canvas,\n            this.shaderContext,\n            this.width,\n            this.height\n        );\n    }\n    getOffscreenCanvas() {\n        if (!(this.canvas instanceof OffscreenCanvas))\n            throw new Error(\n                'Conversion to ImageBitmap requires that the MediaPipe Tasks is initialized with an OffscreenCanvas'\n            );\n        return this.canvas;\n    }\n    getGL() {\n        if (!this.canvas)\n            throw new Error(\n                'Conversion to different image formats require that a canvas is passed when iniitializing the image.'\n            );\n        return (\n            this.gl ||\n                (this.gl = (0, image_shader_context_1$2.assertNotNull)(\n                    this.canvas.getContext('webgl2'),\n                    'You cannot use a canvas that is already bound to a different type of rendering context.'\n                )),\n            this.gl\n        );\n    }\n    getShaderContext() {\n        return (\n            this.shaderContext ||\n                (this.shaderContext = new image_shader_context_1$2.MPImageShaderContext()),\n            this.shaderContext\n        );\n    }\n    convertToImageBitmap() {\n        let e = this.getContainer(MPImageType.IMAGE_BITMAP);\n        return (\n            e ||\n                (this.convertToWebGLTexture(),\n                (e = this.convertWebGLTextureToImageBitmap()),\n                this.containers.push(e),\n                (this.ownsImageBitmap = !0)),\n            e\n        );\n    }\n    convertToImageData() {\n        let e = this.getContainer(MPImageType.IMAGE_DATA);\n        if (!e) {\n            const t = this.getGL(),\n                r = this.getShaderContext(),\n                o = new Uint8Array(this.width * this.height * 4),\n                i = this.convertToWebGLTexture();\n            r.bindFramebuffer(t, i),\n                t.readPixels(0, 0, this.width, this.height, t.RGBA, t.UNSIGNED_BYTE, o),\n                r.unbindFramebuffer(),\n                (e = new ImageData(new Uint8ClampedArray(o.buffer), this.width, this.height)),\n                this.containers.push(e);\n        }\n        return e;\n    }\n    convertToWebGLTexture() {\n        let e = this.getContainer(MPImageType.WEBGL_TEXTURE);\n        if (!e) {\n            const t = this.getGL();\n            e = this.bindTexture();\n            const r = this.getContainer(MPImageType.IMAGE_BITMAP) || this.convertToImageData();\n            t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, r), this.unbindTexture();\n        }\n        return e;\n    }\n    configureTextureParams() {\n        const e = this.getGL();\n        e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE),\n            e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE),\n            e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR),\n            e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR);\n    }\n    bindTexture() {\n        const e = this.getGL();\n        e.viewport(0, 0, this.width, this.height), e.activeTexture(e.TEXTURE0);\n        let t = this.getContainer(MPImageType.WEBGL_TEXTURE);\n        return (\n            t\n                ? e.bindTexture(e.TEXTURE_2D, t)\n                : ((t = (0, image_shader_context_1$2.assertNotNull)(\n                      e.createTexture(),\n                      'Failed to create texture'\n                  )),\n                  this.containers.push(t),\n                  (this.ownsWebGLTexture = !0),\n                  e.bindTexture(e.TEXTURE_2D, t),\n                  this.configureTextureParams()),\n            t\n        );\n    }\n    unbindTexture() {\n        this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n    }\n    copyTextureToBitmap() {\n        const e = this.getGL();\n        return this.getShaderContext().run(e, !0, () =>\n            this.runWithResizedCanvas(\n                () => (\n                    e.bindFramebuffer(e.FRAMEBUFFER, null),\n                    e.clearColor(0, 0, 0, 0),\n                    e.clear(e.COLOR_BUFFER_BIT),\n                    e.drawArrays(e.TRIANGLE_FAN, 0, 4),\n                    this.getOffscreenCanvas().transferToImageBitmap()\n                )\n            )\n        );\n    }\n    convertWebGLTextureToImageBitmap() {\n        this.bindTexture();\n        const e = this.copyTextureToBitmap();\n        return this.unbindTexture(), e;\n    }\n    runWithResizedCanvas(e) {\n        const t = this.canvas;\n        if (t.width === this.width && t.height === this.height) return e();\n        const r = t.width,\n            o = t.height;\n        (t.width = this.width), (t.height = this.height);\n        const i = e();\n        return (t.width = r), (t.height = o), i;\n    }\n    close() {\n        if (\n            (this.ownsImageBitmap && this.getContainer(MPImageType.IMAGE_BITMAP).close(),\n            this.ownsWebGLTexture)\n        ) {\n            this.getGL().deleteTexture(this.getContainer(MPImageType.WEBGL_TEXTURE));\n        }\n        MPImage$1.instancesBeforeWarning = -1;\n    }\n}\n(image.MPImage = MPImage$1),\n    (MPImage$1.instancesBeforeWarning = INSTANCE_COUNT_WARNING_THRESHOLD$1);\nvar mask = {},\n    platform_utils = {};\nfunction isWebKit(e = navigator) {\n    const t = e.userAgent;\n    return t.includes('Safari') && !t.includes('Chrome');\n}\nfunction isIOS() {\n    return (\n        ['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'].includes(\n            navigator.platform\n        ) ||\n        (navigator.userAgent.includes('Mac') && 'ontouchend' in document)\n    );\n}\nObject.defineProperty(platform_utils, '__esModule', { value: !0 }),\n    (platform_utils.isIOS = platform_utils.isWebKit = void 0),\n    (platform_utils.isWebKit = isWebKit),\n    (platform_utils.isIOS = isIOS),\n    Object.defineProperty(mask, '__esModule', { value: !0 }),\n    (mask.MPMask = void 0);\nconst image_shader_context_1$1 = image_shader_context,\n    platform_utils_1$1 = platform_utils,\n    INSTANCE_COUNT_WARNING_THRESHOLD = 250;\nvar MPMaskType;\n!(function(e) {\n    (e[(e.UINT8_ARRAY = 0)] = 'UINT8_ARRAY'),\n        (e[(e.FLOAT32_ARRAY = 1)] = 'FLOAT32_ARRAY'),\n        (e[(e.WEBGL_TEXTURE = 2)] = 'WEBGL_TEXTURE');\n})(MPMaskType || (MPMaskType = {}));\nclass MPMask$1 {\n    constructor(e, t, r, o, i, a) {\n        (this.containers = e),\n            (this.ownsWebGLTexture = t),\n            (this.canvas = r),\n            (this.shaderContext = o),\n            (this.width = i),\n            (this.height = a),\n            this.ownsWebGLTexture &&\n                (--MPMask$1.instancesBeforeWarning,\n                0 === MPMask$1.instancesBeforeWarning &&\n                    console.error(\n                        'You seem to be creating MPMask instances without invoking .close(). This leaks resources.'\n                    ));\n    }\n    hasUint8Array() {\n        return !!this.getContainer(MPMaskType.UINT8_ARRAY);\n    }\n    hasFloat32Array() {\n        return !!this.getContainer(MPMaskType.FLOAT32_ARRAY);\n    }\n    hasWebGLTexture() {\n        return !!this.getContainer(MPMaskType.WEBGL_TEXTURE);\n    }\n    getAsUint8Array() {\n        return this.convertToUint8Array();\n    }\n    getAsFloat32Array() {\n        return this.convertToFloat32Array();\n    }\n    getAsWebGLTexture() {\n        return this.convertToWebGLTexture();\n    }\n    getTexImage2DFormat() {\n        const e = this.getGL();\n        if (!MPMask$1.texImage2DFormat)\n            if (\n                e.getExtension('EXT_color_buffer_float') &&\n                e.getExtension('OES_texture_float_linear') &&\n                e.getExtension('EXT_float_blend')\n            )\n                MPMask$1.texImage2DFormat = e.R32F;\n            else {\n                if (!e.getExtension('EXT_color_buffer_half_float'))\n                    throw new Error(\n                        'GPU does not fully support 4-channel float32 or float16 formats'\n                    );\n                MPMask$1.texImage2DFormat = e.R16F;\n            }\n        return MPMask$1.texImage2DFormat;\n    }\n    getContainer(e) {\n        switch (e) {\n            case MPMaskType.UINT8_ARRAY:\n                return this.containers.find((e) => e instanceof Uint8Array);\n            case MPMaskType.FLOAT32_ARRAY:\n                return this.containers.find((e) => e instanceof Float32Array);\n            case MPMaskType.WEBGL_TEXTURE:\n                return this.containers.find(\n                    (e) => 'undefined' != typeof WebGLTexture && e instanceof WebGLTexture\n                );\n            default:\n                throw new Error(`Type is not supported: ${e}`);\n        }\n    }\n    clone() {\n        const e = [];\n        for (const t of this.containers) {\n            let r;\n            if (t instanceof Uint8Array) r = new Uint8Array(t);\n            else if (t instanceof Float32Array) r = new Float32Array(t);\n            else {\n                if (!(t instanceof WebGLTexture)) throw new Error(`Type is not supported: ${t}`);\n                {\n                    const e = this.getGL(),\n                        t = this.getShaderContext();\n                    e.activeTexture(e.TEXTURE1),\n                        (r = (0, image_shader_context_1$1.assertNotNull)(\n                            e.createTexture(),\n                            'Failed to create texture'\n                        )),\n                        e.bindTexture(e.TEXTURE_2D, r),\n                        this.configureTextureParams();\n                    const o = this.getTexImage2DFormat();\n                    e.texImage2D(\n                        e.TEXTURE_2D,\n                        0,\n                        o,\n                        this.width,\n                        this.height,\n                        0,\n                        e.RED,\n                        e.FLOAT,\n                        null\n                    ),\n                        e.bindTexture(e.TEXTURE_2D, null),\n                        t.bindFramebuffer(e, r),\n                        t.run(e, !1, () => {\n                            this.bindTexture(),\n                                e.clearColor(0, 0, 0, 0),\n                                e.clear(e.COLOR_BUFFER_BIT),\n                                e.drawArrays(e.TRIANGLE_FAN, 0, 4),\n                                this.unbindTexture();\n                        }),\n                        t.unbindFramebuffer(),\n                        this.unbindTexture();\n                }\n            }\n            e.push(r);\n        }\n        return new MPMask$1(\n            e,\n            this.hasWebGLTexture(),\n            this.canvas,\n            this.shaderContext,\n            this.width,\n            this.height\n        );\n    }\n    getGL() {\n        if (!this.canvas)\n            throw new Error(\n                'Conversion to different image formats require that a canvas is passed when initializing the image.'\n            );\n        return (\n            this.gl ||\n                (this.gl = (0, image_shader_context_1$1.assertNotNull)(\n                    this.canvas.getContext('webgl2'),\n                    'You cannot use a canvas that is already bound to a different type of rendering context.'\n                )),\n            this.gl\n        );\n    }\n    getShaderContext() {\n        return (\n            this.shaderContext ||\n                (this.shaderContext = new image_shader_context_1$1.MPImageShaderContext()),\n            this.shaderContext\n        );\n    }\n    convertToFloat32Array() {\n        let e = this.getContainer(MPMaskType.FLOAT32_ARRAY);\n        if (!e) {\n            const t = this.getContainer(MPMaskType.UINT8_ARRAY);\n            if (t) e = new Float32Array(t).map((e) => e / 255);\n            else {\n                e = new Float32Array(this.width * this.height);\n                const t = this.getGL(),\n                    r = this.getShaderContext(),\n                    o = this.convertToWebGLTexture();\n                if ((r.bindFramebuffer(t, o), (0, platform_utils_1$1.isIOS)())) {\n                    const r = new Float32Array(this.width * this.height * 4);\n                    t.readPixels(0, 0, this.width, this.height, t.RGBA, t.FLOAT, r);\n                    for (let t = 0, o = 0; t < e.length; ++t, o += 4) e[t] = r[o];\n                } else t.readPixels(0, 0, this.width, this.height, t.RED, t.FLOAT, e);\n            }\n            this.containers.push(e);\n        }\n        return e;\n    }\n    convertToUint8Array() {\n        let e = this.getContainer(MPMaskType.UINT8_ARRAY);\n        if (!e) {\n            const t = this.convertToFloat32Array();\n            (e = new Uint8Array(t.map((e) => 255 * e))), this.containers.push(e);\n        }\n        return e;\n    }\n    convertToWebGLTexture() {\n        let e = this.getContainer(MPMaskType.WEBGL_TEXTURE);\n        if (!e) {\n            const t = this.getGL();\n            e = this.bindTexture();\n            const r = this.convertToFloat32Array(),\n                o = this.getTexImage2DFormat();\n            t.texImage2D(t.TEXTURE_2D, 0, o, this.width, this.height, 0, t.RED, t.FLOAT, r),\n                this.unbindTexture();\n        }\n        return e;\n    }\n    configureTextureParams() {\n        const e = this.getGL();\n        e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE),\n            e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE),\n            e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.NEAREST),\n            e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.NEAREST);\n    }\n    bindTexture() {\n        const e = this.getGL();\n        e.viewport(0, 0, this.width, this.height), e.activeTexture(e.TEXTURE0);\n        let t = this.getContainer(MPMaskType.WEBGL_TEXTURE);\n        return (\n            t\n                ? e.bindTexture(e.TEXTURE_2D, t)\n                : ((t = (0, image_shader_context_1$1.assertNotNull)(\n                      e.createTexture(),\n                      'Failed to create texture'\n                  )),\n                  this.containers.push(t),\n                  (this.ownsWebGLTexture = !0),\n                  e.bindTexture(e.TEXTURE_2D, t),\n                  this.configureTextureParams()),\n            t\n        );\n    }\n    unbindTexture() {\n        this.gl.bindTexture(this.gl.TEXTURE_2D, null);\n    }\n    close() {\n        if (this.ownsWebGLTexture) {\n            this.getGL().deleteTexture(this.getContainer(MPMaskType.WEBGL_TEXTURE));\n        }\n        MPMask$1.instancesBeforeWarning = -1;\n    }\n}\n(mask.MPMask = MPMask$1), (MPMask$1.instancesBeforeWarning = INSTANCE_COUNT_WARNING_THRESHOLD);\nvar face_detector = {},\n    calculator_pb = {},\n    googleProtobuf = {};\n(function(exports) {\n    var $jscomp = $jscomp || {};\n    ($jscomp.scope = {}),\n        ($jscomp.findInternal = function(e, t, r) {\n            e instanceof String && (e = String(e));\n            for (var o = e.length, i = 0; i < o; i++) {\n                var a = e[i];\n                if (t.call(r, a, i, e)) return { i: i, v: a };\n            }\n            return { i: -1, v: void 0 };\n        }),\n        ($jscomp.ASSUME_ES5 = !1),\n        ($jscomp.ASSUME_NO_NATIVE_MAP = !1),\n        ($jscomp.ASSUME_NO_NATIVE_SET = !1),\n        ($jscomp.SIMPLE_FROUND_POLYFILL = !1),\n        ($jscomp.defineProperty =\n            $jscomp.ASSUME_ES5 || 'function' == typeof Object.defineProperties\n                ? Object.defineProperty\n                : function(e, t, r) {\n                      e != Array.prototype && e != Object.prototype && (e[t] = r.value);\n                  }),\n        ($jscomp.getGlobal = function(e) {\n            return 'undefined' != typeof window && window === e\n                ? e\n                : void 0 !== commonjsGlobal && null != commonjsGlobal\n                ? commonjsGlobal\n                : e;\n        }),\n        ($jscomp.global = $jscomp.getGlobal(commonjsGlobal)),\n        ($jscomp.polyfill = function(e, t, r, o) {\n            if (t) {\n                for (r = $jscomp.global, e = e.split('.'), o = 0; o < e.length - 1; o++) {\n                    var i = e[o];\n                    i in r || (r[i] = {}), (r = r[i]);\n                }\n                (t = t((o = r[(e = e[e.length - 1])]))) != o &&\n                    null != t &&\n                    $jscomp.defineProperty(r, e, { configurable: !0, writable: !0, value: t });\n            }\n        }),\n        $jscomp.polyfill(\n            'Array.prototype.findIndex',\n            function(e) {\n                return (\n                    e ||\n                    function(e, t) {\n                        return $jscomp.findInternal(this, e, t).i;\n                    }\n                );\n            },\n            'es6',\n            'es3'\n        ),\n        ($jscomp.checkStringArgs = function(e, t, r) {\n            if (null == e)\n                throw new TypeError(\n                    \"The 'this' value for String.prototype.\" + r + ' must not be null or undefined'\n                );\n            if (t instanceof RegExp)\n                throw new TypeError(\n                    'First argument to String.prototype.' + r + ' must not be a regular expression'\n                );\n            return e + '';\n        }),\n        $jscomp.polyfill(\n            'String.prototype.endsWith',\n            function(e) {\n                return (\n                    e ||\n                    function(e, t) {\n                        var r = $jscomp.checkStringArgs(this, e, 'endsWith');\n                        (e += ''),\n                            void 0 === t && (t = r.length),\n                            (t = Math.max(0, Math.min(0 | t, r.length)));\n                        for (var o = e.length; 0 < o && 0 < t; ) if (r[--t] != e[--o]) return !1;\n                        return 0 >= o;\n                    }\n                );\n            },\n            'es6',\n            'es3'\n        ),\n        $jscomp.polyfill(\n            'Array.prototype.find',\n            function(e) {\n                return (\n                    e ||\n                    function(e, t) {\n                        return $jscomp.findInternal(this, e, t).v;\n                    }\n                );\n            },\n            'es6',\n            'es3'\n        ),\n        $jscomp.polyfill(\n            'String.prototype.startsWith',\n            function(e) {\n                return (\n                    e ||\n                    function(e, t) {\n                        var r = $jscomp.checkStringArgs(this, e, 'startsWith');\n                        e += '';\n                        var o = r.length,\n                            i = e.length;\n                        t = Math.max(0, Math.min(0 | t, r.length));\n                        for (var a = 0; a < i && t < o; ) if (r[t++] != e[a++]) return !1;\n                        return a >= i;\n                    }\n                );\n            },\n            'es6',\n            'es3'\n        ),\n        $jscomp.polyfill(\n            'String.prototype.repeat',\n            function(e) {\n                return (\n                    e ||\n                    function(e) {\n                        var t = $jscomp.checkStringArgs(this, null, 'repeat');\n                        if (0 > e || 1342177279 < e) throw new RangeError('Invalid count value');\n                        e |= 0;\n                        for (var r = ''; e; ) 1 & e && (r += t), (e >>>= 1) && (t += t);\n                        return r;\n                    }\n                );\n            },\n            'es6',\n            'es3'\n        );\n    var COMPILED = !0,\n        goog = goog || {};\n    (goog.global = commonjsGlobal || self),\n        (goog.exportPath_ = function(e, t, r) {\n            (e = e.split('.')),\n                (r = r || goog.global),\n                e[0] in r || void 0 === r.execScript || r.execScript('var ' + e[0]);\n            for (var o; e.length && (o = e.shift()); )\n                e.length || void 0 === t\n                    ? (r = r[o] && r[o] !== Object.prototype[o] ? r[o] : (r[o] = {}))\n                    : (r[o] = t);\n        }),\n        (goog.define = function(e, t) {\n            return t;\n        }),\n        (goog.FEATURESET_YEAR = 2012),\n        (goog.DEBUG = !0),\n        (goog.LOCALE = 'en'),\n        (goog.TRUSTED_SITE = !0),\n        (goog.STRICT_MODE_COMPATIBLE = !1),\n        (goog.DISALLOW_TEST_ONLY_CODE = !goog.DEBUG),\n        (goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING = !1),\n        (goog.provide = function(e) {\n            if (goog.isInModuleLoader_())\n                throw Error('goog.provide cannot be used within a module.');\n            goog.constructNamespace_(e);\n        }),\n        (goog.constructNamespace_ = function(e, t) {\n            goog.exportPath_(e, t);\n        }),\n        (goog.getScriptNonce = function(e) {\n            return e && e != goog.global\n                ? goog.getScriptNonce_(e.document)\n                : (null === goog.cspNonce_ &&\n                      (goog.cspNonce_ = goog.getScriptNonce_(goog.global.document)),\n                  goog.cspNonce_);\n        }),\n        (goog.NONCE_PATTERN_ = /^[\\w+/_-]+[=]{0,2}$/),\n        (goog.cspNonce_ = null),\n        (goog.getScriptNonce_ = function(e) {\n            return (e = e.querySelector && e.querySelector('script[nonce]')) &&\n                (e = e.nonce || e.getAttribute('nonce')) &&\n                goog.NONCE_PATTERN_.test(e)\n                ? e\n                : '';\n        }),\n        (goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/),\n        (goog.module = function(e) {\n            if ('string' != typeof e || !e || -1 == e.search(goog.VALID_MODULE_RE_))\n                throw Error('Invalid module identifier');\n            if (!goog.isInGoogModuleLoader_())\n                throw Error(\n                    'Module ' +\n                        e +\n                        \" has been loaded incorrectly. Note, modules cannot be loaded as normal scripts. They require some kind of pre-processing step. You're likely trying to load a module via a script tag or as a part of a concatenated bundle without rewriting the module. For more info see: https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.\"\n                );\n            if (goog.moduleLoaderState_.moduleName)\n                throw Error('goog.module may only be called once per module.');\n            goog.moduleLoaderState_.moduleName = e;\n        }),\n        (goog.module.get = function(e) {\n            return goog.module.getInternal_(e);\n        }),\n        (goog.module.getInternal_ = function(e) {\n            return null;\n        }),\n        (goog.ModuleType = { ES6: 'es6', GOOG: 'goog' }),\n        (goog.moduleLoaderState_ = null),\n        (goog.isInModuleLoader_ = function() {\n            return goog.isInGoogModuleLoader_() || goog.isInEs6ModuleLoader_();\n        }),\n        (goog.isInGoogModuleLoader_ = function() {\n            return (\n                !!goog.moduleLoaderState_ && goog.moduleLoaderState_.type == goog.ModuleType.GOOG\n            );\n        }),\n        (goog.isInEs6ModuleLoader_ = function() {\n            if (goog.moduleLoaderState_ && goog.moduleLoaderState_.type == goog.ModuleType.ES6)\n                return !0;\n            var e = goog.global.$jscomp;\n            return !!e && 'function' == typeof e.getCurrentModulePath && !!e.getCurrentModulePath();\n        }),\n        (goog.module.declareLegacyNamespace = function() {\n            goog.moduleLoaderState_.declareLegacyNamespace = !0;\n        }),\n        (goog.declareModuleId = function(e) {\n            if (goog.moduleLoaderState_) goog.moduleLoaderState_.moduleName = e;\n            else {\n                var t = goog.global.$jscomp;\n                if (!t || 'function' != typeof t.getCurrentModulePath)\n                    throw Error('Module with namespace \"' + e + '\" has been loaded incorrectly.');\n                (t = t.require(t.getCurrentModulePath())),\n                    (goog.loadedModules_[e] = {\n                        exports: t,\n                        type: goog.ModuleType.ES6,\n                        moduleId: e,\n                    });\n            }\n        }),\n        (goog.setTestOnly = function(e) {\n            if (goog.DISALLOW_TEST_ONLY_CODE)\n                throw ((e = e || ''),\n                Error(\n                    'Importing test-only code into non-debug environment' + (e ? ': ' + e : '.')\n                ));\n        }),\n        (goog.forwardDeclare = function(e) {}),\n        (goog.getObjectByName = function(e, t) {\n            (e = e.split('.')), (t = t || goog.global);\n            for (var r = 0; r < e.length; r++) if (null == (t = t[e[r]])) return null;\n            return t;\n        }),\n        (goog.globalize = function(e, t) {\n            for (var r in ((t = t || goog.global), e)) t[r] = e[r];\n        }),\n        (goog.addDependency = function(e, t, r, o) {}),\n        (goog.ENABLE_DEBUG_LOADER = !0),\n        (goog.logToConsole_ = function(e) {\n            goog.global.console && goog.global.console.error(e);\n        }),\n        (goog.require = function(e) {}),\n        (goog.requireType = function(e) {\n            return {};\n        }),\n        (goog.basePath = ''),\n        (goog.nullFunction = function() {}),\n        (goog.abstractMethod = function() {\n            throw Error('unimplemented abstract method');\n        }),\n        (goog.addSingletonGetter = function(e) {\n            (e.instance_ = void 0),\n                (e.getInstance = function() {\n                    return e.instance_\n                        ? e.instance_\n                        : (goog.DEBUG &&\n                              (goog.instantiatedSingletons_[\n                                  goog.instantiatedSingletons_.length\n                              ] = e),\n                          (e.instance_ = new e()));\n                });\n        }),\n        (goog.instantiatedSingletons_ = []),\n        (goog.LOAD_MODULE_USING_EVAL = !0),\n        (goog.SEAL_MODULE_EXPORTS = goog.DEBUG),\n        (goog.loadedModules_ = {}),\n        (goog.DEPENDENCIES_ENABLED = !COMPILED),\n        (goog.TRANSPILE = 'detect'),\n        (goog.ASSUME_ES_MODULES_TRANSPILED = !1),\n        (goog.TRANSPILE_TO_LANGUAGE = ''),\n        (goog.TRANSPILER = 'transpile.js'),\n        (goog.hasBadLetScoping = null),\n        (goog.useSafari10Workaround = function() {\n            if (null == goog.hasBadLetScoping) {\n                try {\n                    var a = !eval(\n                        '\"use strict\";let x = 1; function f() { return typeof x; };f() == \"number\";'\n                    );\n                } catch (e) {\n                    a = !1;\n                }\n                goog.hasBadLetScoping = a;\n            }\n            return goog.hasBadLetScoping;\n        }),\n        (goog.workaroundSafari10EvalBug = function(e) {\n            return '(function(){' + e + '\\n;})();\\n';\n        }),\n        (goog.loadModule = function(e) {\n            var t = goog.moduleLoaderState_;\n            try {\n                if (\n                    ((goog.moduleLoaderState_ = {\n                        moduleName: '',\n                        declareLegacyNamespace: !1,\n                        type: goog.ModuleType.GOOG,\n                    }),\n                    goog.isFunction(e))\n                )\n                    var r = e.call(void 0, {});\n                else {\n                    if ('string' != typeof e) throw Error('Invalid module definition');\n                    goog.useSafari10Workaround() && (e = goog.workaroundSafari10EvalBug(e)),\n                        (r = goog.loadModuleFromSource_.call(void 0, e));\n                }\n                var o = goog.moduleLoaderState_.moduleName;\n                if ('string' != typeof o || !o) throw Error('Invalid module name \"' + o + '\"');\n                goog.moduleLoaderState_.declareLegacyNamespace\n                    ? goog.constructNamespace_(o, r)\n                    : goog.SEAL_MODULE_EXPORTS &&\n                      Object.seal &&\n                      'object' == typeof r &&\n                      null != r &&\n                      Object.seal(r),\n                    (goog.loadedModules_[o] = {\n                        exports: r,\n                        type: goog.ModuleType.GOOG,\n                        moduleId: goog.moduleLoaderState_.moduleName,\n                    });\n            } finally {\n                goog.moduleLoaderState_ = t;\n            }\n        }),\n        (goog.loadModuleFromSource_ = function(a) {\n            return eval(a), {};\n        }),\n        (goog.normalizePath_ = function(e) {\n            e = e.split('/');\n            for (var t = 0; t < e.length; )\n                '.' == e[t]\n                    ? e.splice(t, 1)\n                    : t && '..' == e[t] && e[t - 1] && '..' != e[t - 1]\n                    ? e.splice(--t, 2)\n                    : t++;\n            return e.join('/');\n        }),\n        (goog.loadFileSync_ = function(e) {\n            if (goog.global.CLOSURE_LOAD_FILE_SYNC) return goog.global.CLOSURE_LOAD_FILE_SYNC(e);\n            try {\n                var t = new goog.global.XMLHttpRequest();\n                return (\n                    t.open('get', e, !1),\n                    t.send(),\n                    0 == t.status || 200 == t.status ? t.responseText : null\n                );\n            } catch (e) {\n                return null;\n            }\n        }),\n        (goog.transpile_ = function(e, t, r) {\n            var o = goog.global.$jscomp;\n            o || (goog.global.$jscomp = o = {});\n            var i = o.transpile;\n            if (!i) {\n                var a = goog.basePath + goog.TRANSPILER,\n                    n = goog.loadFileSync_(a);\n                if (n) {\n                    if (\n                        (function() {\n                            (0, eval)(n + '\\n//# sourceURL=' + a);\n                        }.call(goog.global),\n                        goog.global.$gwtExport &&\n                            goog.global.$gwtExport.$jscomp &&\n                            !goog.global.$gwtExport.$jscomp.transpile)\n                    )\n                        throw Error(\n                            'The transpiler did not properly export the \"transpile\" method. $gwtExport: ' +\n                                JSON.stringify(goog.global.$gwtExport)\n                        );\n                    (goog.global.$jscomp.transpile = goog.global.$gwtExport.$jscomp.transpile),\n                        (i = (o = goog.global.$jscomp).transpile);\n                }\n            }\n            return (\n                i ||\n                    (i = o.transpile = function(e, t) {\n                        return (\n                            goog.logToConsole_(\n                                t + ' requires transpilation but no transpiler was found.'\n                            ),\n                            e\n                        );\n                    }),\n                i(e, t, r)\n            );\n        }),\n        (goog.typeOf = function(e) {\n            var t = typeof e;\n            if ('object' == t) {\n                if (!e) return 'null';\n                if (e instanceof Array) return 'array';\n                if (e instanceof Object) return t;\n                var r = Object.prototype.toString.call(e);\n                if ('[object Window]' == r) return 'object';\n                if (\n                    '[object Array]' == r ||\n                    ('number' == typeof e.length &&\n                        void 0 !== e.splice &&\n                        void 0 !== e.propertyIsEnumerable &&\n                        !e.propertyIsEnumerable('splice'))\n                )\n                    return 'array';\n                if (\n                    '[object Function]' == r ||\n                    (void 0 !== e.call &&\n                        void 0 !== e.propertyIsEnumerable &&\n                        !e.propertyIsEnumerable('call'))\n                )\n                    return 'function';\n            } else if ('function' == t && void 0 === e.call) return 'object';\n            return t;\n        }),\n        (goog.isArray = function(e) {\n            return 'array' == goog.typeOf(e);\n        }),\n        (goog.isArrayLike = function(e) {\n            var t = goog.typeOf(e);\n            return 'array' == t || ('object' == t && 'number' == typeof e.length);\n        }),\n        (goog.isDateLike = function(e) {\n            return goog.isObject(e) && 'function' == typeof e.getFullYear;\n        }),\n        (goog.isFunction = function(e) {\n            return 'function' == goog.typeOf(e);\n        }),\n        (goog.isObject = function(e) {\n            var t = typeof e;\n            return ('object' == t && null != e) || 'function' == t;\n        }),\n        (goog.getUid = function(e) {\n            return (\n                (Object.prototype.hasOwnProperty.call(e, goog.UID_PROPERTY_) &&\n                    e[goog.UID_PROPERTY_]) ||\n                (e[goog.UID_PROPERTY_] = ++goog.uidCounter_)\n            );\n        }),\n        (goog.hasUid = function(e) {\n            return !!e[goog.UID_PROPERTY_];\n        }),\n        (goog.removeUid = function(e) {\n            null !== e && 'removeAttribute' in e && e.removeAttribute(goog.UID_PROPERTY_);\n            try {\n                delete e[goog.UID_PROPERTY_];\n            } catch (e) {}\n        }),\n        (goog.UID_PROPERTY_ = 'closure_uid_' + ((1e9 * Math.random()) >>> 0)),\n        (goog.uidCounter_ = 0),\n        (goog.getHashCode = goog.getUid),\n        (goog.removeHashCode = goog.removeUid),\n        (goog.cloneObject = function(e) {\n            var t = goog.typeOf(e);\n            if ('object' == t || 'array' == t) {\n                if ('function' == typeof e.clone) return e.clone();\n                for (var r in ((t = 'array' == t ? [] : {}), e)) t[r] = goog.cloneObject(e[r]);\n                return t;\n            }\n            return e;\n        }),\n        (goog.bindNative_ = function(e, t, r) {\n            return e.call.apply(e.bind, arguments);\n        }),\n        (goog.bindJs_ = function(e, t, r) {\n            if (!e) throw Error();\n            if (2 < arguments.length) {\n                var o = Array.prototype.slice.call(arguments, 2);\n                return function() {\n                    var r = Array.prototype.slice.call(arguments);\n                    return Array.prototype.unshift.apply(r, o), e.apply(t, r);\n                };\n            }\n            return function() {\n                return e.apply(t, arguments);\n            };\n        }),\n        (goog.bind = function(e, t, r) {\n            return (\n                Function.prototype.bind &&\n                -1 != Function.prototype.bind.toString().indexOf('native code')\n                    ? (goog.bind = goog.bindNative_)\n                    : (goog.bind = goog.bindJs_),\n                goog.bind.apply(null, arguments)\n            );\n        }),\n        (goog.partial = function(e, t) {\n            var r = Array.prototype.slice.call(arguments, 1);\n            return function() {\n                var t = r.slice();\n                return t.push.apply(t, arguments), e.apply(this, t);\n            };\n        }),\n        (goog.mixin = function(e, t) {\n            for (var r in t) e[r] = t[r];\n        }),\n        (goog.now =\n            (goog.TRUSTED_SITE && Date.now) ||\n            function() {\n                return +new Date();\n            }),\n        (goog.globalEval = function(e) {\n            if (goog.global.execScript) goog.global.execScript(e, 'JavaScript');\n            else {\n                if (!goog.global.eval) throw Error('goog.globalEval not available');\n                if (null == goog.evalWorksForGlobals_) {\n                    try {\n                        goog.global.eval('var _evalTest_ = 1;');\n                    } catch (e) {}\n                    if (void 0 !== goog.global._evalTest_) {\n                        try {\n                            delete goog.global._evalTest_;\n                        } catch (e) {}\n                        goog.evalWorksForGlobals_ = !0;\n                    } else goog.evalWorksForGlobals_ = !1;\n                }\n                if (goog.evalWorksForGlobals_) goog.global.eval(e);\n                else {\n                    var t = goog.global.document,\n                        r = t.createElement('script');\n                    (r.type = 'text/javascript'),\n                        (r.defer = !1),\n                        r.appendChild(t.createTextNode(e)),\n                        t.head.appendChild(r),\n                        t.head.removeChild(r);\n                }\n            }\n        }),\n        (goog.evalWorksForGlobals_ = null),\n        (goog.getCssName = function(e, t) {\n            if ('.' == String(e).charAt(0))\n                throw Error(\n                    'className passed in goog.getCssName must not start with \".\". You passed: ' + e\n                );\n            var r = function(e) {\n                    return goog.cssNameMapping_[e] || e;\n                },\n                o = function(e) {\n                    e = e.split('-');\n                    for (var t = [], o = 0; o < e.length; o++) t.push(r(e[o]));\n                    return t.join('-');\n                };\n            return (\n                (o = goog.cssNameMapping_\n                    ? 'BY_WHOLE' == goog.cssNameMappingStyle_\n                        ? r\n                        : o\n                    : function(e) {\n                          return e;\n                      }),\n                (e = t ? e + '-' + o(t) : o(e)),\n                goog.global.CLOSURE_CSS_NAME_MAP_FN ? goog.global.CLOSURE_CSS_NAME_MAP_FN(e) : e\n            );\n        }),\n        (goog.setCssNameMapping = function(e, t) {\n            (goog.cssNameMapping_ = e), (goog.cssNameMappingStyle_ = t);\n        }),\n        (goog.getMsg = function(e, t, r) {\n            return (\n                r && r.html && (e = e.replace(/</g, '&lt;')),\n                t &&\n                    (e = e.replace(/\\{\\$([^}]+)}/g, function(e, r) {\n                        return null != t && r in t ? t[r] : e;\n                    })),\n                e\n            );\n        }),\n        (goog.getMsgWithFallback = function(e, t) {\n            return e;\n        }),\n        (goog.exportSymbol = function(e, t, r) {\n            goog.exportPath_(e, t, r);\n        }),\n        (goog.exportProperty = function(e, t, r) {\n            e[t] = r;\n        }),\n        (goog.inherits = function(e, t) {\n            function r() {}\n            (r.prototype = t.prototype),\n                (e.superClass_ = t.prototype),\n                (e.prototype = new r()),\n                (e.prototype.constructor = e),\n                (e.base = function(e, r, o) {\n                    for (var i = Array(arguments.length - 2), a = 2; a < arguments.length; a++)\n                        i[a - 2] = arguments[a];\n                    return t.prototype[r].apply(e, i);\n                });\n        }),\n        (goog.scope = function(e) {\n            if (goog.isInModuleLoader_())\n                throw Error('goog.scope is not supported within a module.');\n            e.call(goog.global);\n        }),\n        (goog.defineClass = function(e, t) {\n            var r = t.constructor,\n                o = t.statics;\n            return (\n                (r && r != Object.prototype.constructor) ||\n                    (r = function() {\n                        throw Error('cannot instantiate an interface (no constructor defined).');\n                    }),\n                (r = goog.defineClass.createSealingConstructor_(r, e)),\n                e && goog.inherits(r, e),\n                delete t.constructor,\n                delete t.statics,\n                goog.defineClass.applyProperties_(r.prototype, t),\n                null != o &&\n                    (o instanceof Function ? o(r) : goog.defineClass.applyProperties_(r, o)),\n                r\n            );\n        }),\n        (goog.defineClass.SEAL_CLASS_INSTANCES = goog.DEBUG),\n        (goog.defineClass.createSealingConstructor_ = function(e, t) {\n            if (!goog.defineClass.SEAL_CLASS_INSTANCES) return e;\n            var r = !goog.defineClass.isUnsealable_(t),\n                o = function() {\n                    var t = e.apply(this, arguments) || this;\n                    return (\n                        (t[goog.UID_PROPERTY_] = t[goog.UID_PROPERTY_]),\n                        this.constructor === o &&\n                            r &&\n                            Object.seal instanceof Function &&\n                            Object.seal(t),\n                        t\n                    );\n                };\n            return o;\n        }),\n        (goog.defineClass.isUnsealable_ = function(e) {\n            return e && e.prototype && e.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_];\n        }),\n        (goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = 'constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf'.split(\n            ' '\n        )),\n        (goog.defineClass.applyProperties_ = function(e, t) {\n            for (var r in t) Object.prototype.hasOwnProperty.call(t, r) && (e[r] = t[r]);\n            for (var o = 0; o < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; o++)\n                (r = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[o]),\n                    Object.prototype.hasOwnProperty.call(t, r) && (e[r] = t[r]);\n        }),\n        (goog.tagUnsealableClass = function(e) {}),\n        (goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = 'goog_defineClass_legacy_unsealable'),\n        (goog.TRUSTED_TYPES_POLICY_NAME = ''),\n        (goog.identity_ = function(e) {\n            return e;\n        }),\n        (goog.createTrustedTypesPolicy = function(e) {\n            var t = null,\n                r = goog.global.trustedTypes || goog.global.TrustedTypes;\n            if (!r || !r.createPolicy) return t;\n            try {\n                t = r.createPolicy(e, {\n                    createHTML: goog.identity_,\n                    createScript: goog.identity_,\n                    createScriptURL: goog.identity_,\n                    createURL: goog.identity_,\n                });\n            } catch (e) {\n                goog.logToConsole_(e.message);\n            }\n            return t;\n        }),\n        (goog.TRUSTED_TYPES_POLICY_ = goog.TRUSTED_TYPES_POLICY_NAME\n            ? goog.createTrustedTypesPolicy(goog.TRUSTED_TYPES_POLICY_NAME + '#base')\n            : null),\n        (goog.object = {}),\n        (goog.object.is = function(e, t) {\n            return e === t ? 0 !== e || 1 / e == 1 / t : e != e && t != t;\n        }),\n        (goog.object.forEach = function(e, t, r) {\n            for (var o in e) t.call(r, e[o], o, e);\n        }),\n        (goog.object.filter = function(e, t, r) {\n            var o,\n                i = {};\n            for (o in e) t.call(r, e[o], o, e) && (i[o] = e[o]);\n            return i;\n        }),\n        (goog.object.map = function(e, t, r) {\n            var o,\n                i = {};\n            for (o in e) i[o] = t.call(r, e[o], o, e);\n            return i;\n        }),\n        (goog.object.some = function(e, t, r) {\n            for (var o in e) if (t.call(r, e[o], o, e)) return !0;\n            return !1;\n        }),\n        (goog.object.every = function(e, t, r) {\n            for (var o in e) if (!t.call(r, e[o], o, e)) return !1;\n            return !0;\n        }),\n        (goog.object.getCount = function(e) {\n            var t,\n                r = 0;\n            for (t in e) r++;\n            return r;\n        }),\n        (goog.object.getAnyKey = function(e) {\n            for (var t in e) return t;\n        }),\n        (goog.object.getAnyValue = function(e) {\n            for (var t in e) return e[t];\n        }),\n        (goog.object.contains = function(e, t) {\n            return goog.object.containsValue(e, t);\n        }),\n        (goog.object.getValues = function(e) {\n            var t,\n                r = [],\n                o = 0;\n            for (t in e) r[o++] = e[t];\n            return r;\n        }),\n        (goog.object.getKeys = function(e) {\n            var t,\n                r = [],\n                o = 0;\n            for (t in e) r[o++] = t;\n            return r;\n        }),\n        (goog.object.getValueByKeys = function(e, t) {\n            var r = goog.isArrayLike(t),\n                o = r ? t : arguments;\n            for (r = r ? 0 : 1; r < o.length; r++) {\n                if (null == e) return;\n                e = e[o[r]];\n            }\n            return e;\n        }),\n        (goog.object.containsKey = function(e, t) {\n            return null !== e && t in e;\n        }),\n        (goog.object.containsValue = function(e, t) {\n            for (var r in e) if (e[r] == t) return !0;\n            return !1;\n        }),\n        (goog.object.findKey = function(e, t, r) {\n            for (var o in e) if (t.call(r, e[o], o, e)) return o;\n        }),\n        (goog.object.findValue = function(e, t, r) {\n            return (t = goog.object.findKey(e, t, r)) && e[t];\n        }),\n        (goog.object.isEmpty = function(e) {\n            for (var t in e) return !1;\n            return !0;\n        }),\n        (goog.object.clear = function(e) {\n            for (var t in e) delete e[t];\n        }),\n        (goog.object.remove = function(e, t) {\n            var r;\n            return (r = t in e) && delete e[t], r;\n        }),\n        (goog.object.add = function(e, t, r) {\n            if (null !== e && t in e)\n                throw Error('The object already contains the key \"' + t + '\"');\n            goog.object.set(e, t, r);\n        }),\n        (goog.object.get = function(e, t, r) {\n            return null !== e && t in e ? e[t] : r;\n        }),\n        (goog.object.set = function(e, t, r) {\n            e[t] = r;\n        }),\n        (goog.object.setIfUndefined = function(e, t, r) {\n            return t in e ? e[t] : (e[t] = r);\n        }),\n        (goog.object.setWithReturnValueIfNotSet = function(e, t, r) {\n            return t in e ? e[t] : ((r = r()), (e[t] = r));\n        }),\n        (goog.object.equals = function(e, t) {\n            for (var r in e) if (!(r in t) || e[r] !== t[r]) return !1;\n            for (var o in t) if (!(o in e)) return !1;\n            return !0;\n        }),\n        (goog.object.clone = function(e) {\n            var t,\n                r = {};\n            for (t in e) r[t] = e[t];\n            return r;\n        }),\n        (goog.object.unsafeClone = function(e) {\n            var t = goog.typeOf(e);\n            if ('object' == t || 'array' == t) {\n                if (goog.isFunction(e.clone)) return e.clone();\n                for (var r in ((t = 'array' == t ? [] : {}), e))\n                    t[r] = goog.object.unsafeClone(e[r]);\n                return t;\n            }\n            return e;\n        }),\n        (goog.object.transpose = function(e) {\n            var t,\n                r = {};\n            for (t in e) r[e[t]] = t;\n            return r;\n        }),\n        (goog.object.PROTOTYPE_FIELDS_ = 'constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf'.split(\n            ' '\n        )),\n        (goog.object.extend = function(e, t) {\n            for (var r, o, i = 1; i < arguments.length; i++) {\n                for (r in (o = arguments[i])) e[r] = o[r];\n                for (var a = 0; a < goog.object.PROTOTYPE_FIELDS_.length; a++)\n                    (r = goog.object.PROTOTYPE_FIELDS_[a]),\n                        Object.prototype.hasOwnProperty.call(o, r) && (e[r] = o[r]);\n            }\n        }),\n        (goog.object.create = function(e) {\n            var t = arguments.length;\n            if (1 == t && Array.isArray(arguments[0]))\n                return goog.object.create.apply(null, arguments[0]);\n            if (t % 2) throw Error('Uneven number of arguments');\n            for (var r = {}, o = 0; o < t; o += 2) r[arguments[o]] = arguments[o + 1];\n            return r;\n        }),\n        (goog.object.createSet = function(e) {\n            var t = arguments.length;\n            if (1 == t && Array.isArray(arguments[0]))\n                return goog.object.createSet.apply(null, arguments[0]);\n            for (var r = {}, o = 0; o < t; o++) r[arguments[o]] = !0;\n            return r;\n        }),\n        (goog.object.createImmutableView = function(e) {\n            var t = e;\n            return (\n                Object.isFrozen &&\n                    !Object.isFrozen(e) &&\n                    ((t = Object.create(e)), Object.freeze(t)),\n                t\n            );\n        }),\n        (goog.object.isImmutableView = function(e) {\n            return !!Object.isFrozen && Object.isFrozen(e);\n        }),\n        (goog.object.getAllPropertyNames = function(e, t, r) {\n            if (!e) return [];\n            if (!Object.getOwnPropertyNames || !Object.getPrototypeOf)\n                return goog.object.getKeys(e);\n            for (\n                var o = {};\n                e && (e !== Object.prototype || t) && (e !== Function.prototype || r);\n\n            ) {\n                for (var i = Object.getOwnPropertyNames(e), a = 0; a < i.length; a++) o[i[a]] = !0;\n                e = Object.getPrototypeOf(e);\n            }\n            return goog.object.getKeys(o);\n        }),\n        (goog.object.getSuperClass = function(e) {\n            return (e = Object.getPrototypeOf(e.prototype)) && e.constructor;\n        });\n    var jspb = { asserts: {} };\n    (jspb.asserts.doAssertFailure = function(e, t, r, o) {\n        var i = 'Assertion failed';\n        if (r) {\n            i += ': ' + r;\n            var a = o;\n        } else e && ((i += ': ' + e), (a = t));\n        throw Error('' + i, a || []);\n    }),\n        (jspb.asserts.assert = function(e, t, r) {\n            for (var o = [], i = 2; i < arguments.length; ++i) o[i - 2] = arguments[i];\n            return e || jspb.asserts.doAssertFailure('', null, t, o), e;\n        }),\n        (jspb.asserts.assertString = function(e, t, r) {\n            for (var o = [], i = 2; i < arguments.length; ++i) o[i - 2] = arguments[i];\n            return (\n                'string' != typeof e &&\n                    jspb.asserts.doAssertFailure(\n                        'Expected string but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        o\n                    ),\n                e\n            );\n        }),\n        (jspb.asserts.assertArray = function(e, t, r) {\n            for (var o = [], i = 2; i < arguments.length; ++i) o[i - 2] = arguments[i];\n            return (\n                Array.isArray(e) ||\n                    jspb.asserts.doAssertFailure(\n                        'Expected array but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        o\n                    ),\n                e\n            );\n        }),\n        (jspb.asserts.fail = function(e, t) {\n            for (var r = [], o = 1; o < arguments.length; ++o) r[o - 1] = arguments[o];\n            throw Error('Failure' + (e ? ': ' + e : ''), r);\n        }),\n        (jspb.asserts.assertInstanceof = function(e, t, r, o) {\n            for (var i = [], a = 3; a < arguments.length; ++a) i[a - 3] = arguments[a];\n            return (\n                e instanceof t ||\n                    jspb.asserts.doAssertFailure(\n                        'Expected instanceof %s but got %s.',\n                        [jspb.asserts.getType(t), jspb.asserts.getType(e)],\n                        r,\n                        i\n                    ),\n                e\n            );\n        }),\n        (jspb.asserts.getType = function(e) {\n            return e instanceof Function\n                ? e.displayName || e.name || 'unknown type name'\n                : e instanceof Object\n                ? e.constructor.displayName ||\n                  e.constructor.name ||\n                  Object.prototype.toString.call(e)\n                : null === e\n                ? 'null'\n                : typeof e;\n        }),\n        (jspb.BinaryConstants = {}),\n        (jspb.ConstBinaryMessage = function() {}),\n        (jspb.BinaryMessage = function() {}),\n        (jspb.BinaryConstants.FieldType = {\n            INVALID: -1,\n            DOUBLE: 1,\n            FLOAT: 2,\n            INT64: 3,\n            UINT64: 4,\n            INT32: 5,\n            FIXED64: 6,\n            FIXED32: 7,\n            BOOL: 8,\n            STRING: 9,\n            GROUP: 10,\n            MESSAGE: 11,\n            BYTES: 12,\n            UINT32: 13,\n            ENUM: 14,\n            SFIXED32: 15,\n            SFIXED64: 16,\n            SINT32: 17,\n            SINT64: 18,\n            FHASH64: 30,\n            VHASH64: 31,\n        }),\n        (jspb.BinaryConstants.WireType = {\n            INVALID: -1,\n            VARINT: 0,\n            FIXED64: 1,\n            DELIMITED: 2,\n            START_GROUP: 3,\n            END_GROUP: 4,\n            FIXED32: 5,\n        }),\n        (jspb.BinaryConstants.FieldTypeToWireType = function(e) {\n            var t = jspb.BinaryConstants.FieldType,\n                r = jspb.BinaryConstants.WireType;\n            switch (e) {\n                case t.INT32:\n                case t.INT64:\n                case t.UINT32:\n                case t.UINT64:\n                case t.SINT32:\n                case t.SINT64:\n                case t.BOOL:\n                case t.ENUM:\n                case t.VHASH64:\n                    return r.VARINT;\n                case t.DOUBLE:\n                case t.FIXED64:\n                case t.SFIXED64:\n                case t.FHASH64:\n                    return r.FIXED64;\n                case t.STRING:\n                case t.MESSAGE:\n                case t.BYTES:\n                    return r.DELIMITED;\n                case t.FLOAT:\n                case t.FIXED32:\n                case t.SFIXED32:\n                    return r.FIXED32;\n                default:\n                    return r.INVALID;\n            }\n        }),\n        (jspb.BinaryConstants.INVALID_FIELD_NUMBER = -1),\n        (jspb.BinaryConstants.FLOAT32_EPS = 1401298464324817e-60),\n        (jspb.BinaryConstants.FLOAT32_MIN = 11754943508222875e-54),\n        (jspb.BinaryConstants.FLOAT32_MAX = 34028234663852886e22),\n        (jspb.BinaryConstants.FLOAT64_EPS = 5e-324),\n        (jspb.BinaryConstants.FLOAT64_MIN = 22250738585072014e-324),\n        (jspb.BinaryConstants.FLOAT64_MAX = 17976931348623157e292),\n        (jspb.BinaryConstants.TWO_TO_20 = 1048576),\n        (jspb.BinaryConstants.TWO_TO_23 = 8388608),\n        (jspb.BinaryConstants.TWO_TO_31 = 2147483648),\n        (jspb.BinaryConstants.TWO_TO_32 = 4294967296),\n        (jspb.BinaryConstants.TWO_TO_52 = 4503599627370496),\n        (jspb.BinaryConstants.TWO_TO_63 = 0x8000000000000000),\n        (jspb.BinaryConstants.TWO_TO_64 = 0x10000000000000000),\n        (jspb.BinaryConstants.ZERO_HASH = '\\0\\0\\0\\0\\0\\0\\0\\0'),\n        (goog.debug = {}),\n        (goog.debug.Error = function(e) {\n            if (Error.captureStackTrace) Error.captureStackTrace(this, goog.debug.Error);\n            else {\n                var t = Error().stack;\n                t && (this.stack = t);\n            }\n            e && (this.message = String(e)), (this.reportErrorToServer = !0);\n        }),\n        goog.inherits(goog.debug.Error, Error),\n        (goog.debug.Error.prototype.name = 'CustomError'),\n        (goog.dom = {}),\n        (goog.dom.NodeType = {\n            ELEMENT: 1,\n            ATTRIBUTE: 2,\n            TEXT: 3,\n            CDATA_SECTION: 4,\n            ENTITY_REFERENCE: 5,\n            ENTITY: 6,\n            PROCESSING_INSTRUCTION: 7,\n            COMMENT: 8,\n            DOCUMENT: 9,\n            DOCUMENT_TYPE: 10,\n            DOCUMENT_FRAGMENT: 11,\n            NOTATION: 12,\n        }),\n        (goog.asserts = {}),\n        (goog.asserts.ENABLE_ASSERTS = goog.DEBUG),\n        (goog.asserts.AssertionError = function(e, t) {\n            goog.debug.Error.call(this, goog.asserts.subs_(e, t)), (this.messagePattern = e);\n        }),\n        goog.inherits(goog.asserts.AssertionError, goog.debug.Error),\n        (goog.asserts.AssertionError.prototype.name = 'AssertionError'),\n        (goog.asserts.DEFAULT_ERROR_HANDLER = function(e) {\n            throw e;\n        }),\n        (goog.asserts.errorHandler_ = goog.asserts.DEFAULT_ERROR_HANDLER),\n        (goog.asserts.subs_ = function(e, t) {\n            for (var r = '', o = (e = e.split('%s')).length - 1, i = 0; i < o; i++)\n                r += e[i] + (i < t.length ? t[i] : '%s');\n            return r + e[o];\n        }),\n        (goog.asserts.doAssertFailure_ = function(e, t, r, o) {\n            var i = 'Assertion failed';\n            if (r) {\n                i += ': ' + r;\n                var a = o;\n            } else e && ((i += ': ' + e), (a = t));\n            (e = new goog.asserts.AssertionError('' + i, a || [])), goog.asserts.errorHandler_(e);\n        }),\n        (goog.asserts.setErrorHandler = function(e) {\n            goog.asserts.ENABLE_ASSERTS && (goog.asserts.errorHandler_ = e);\n        }),\n        (goog.asserts.assert = function(e, t, r) {\n            return (\n                goog.asserts.ENABLE_ASSERTS &&\n                    !e &&\n                    goog.asserts.doAssertFailure_(\n                        '',\n                        null,\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertExists = function(e, t, r) {\n            return (\n                goog.asserts.ENABLE_ASSERTS &&\n                    null == e &&\n                    goog.asserts.doAssertFailure_(\n                        'Expected to exist: %s.',\n                        [e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.fail = function(e, t) {\n            goog.asserts.ENABLE_ASSERTS &&\n                goog.asserts.errorHandler_(\n                    new goog.asserts.AssertionError(\n                        'Failure' + (e ? ': ' + e : ''),\n                        Array.prototype.slice.call(arguments, 1)\n                    )\n                );\n        }),\n        (goog.asserts.assertNumber = function(e, t, r) {\n            return (\n                goog.asserts.ENABLE_ASSERTS &&\n                    'number' != typeof e &&\n                    goog.asserts.doAssertFailure_(\n                        'Expected number but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertString = function(e, t, r) {\n            return (\n                goog.asserts.ENABLE_ASSERTS &&\n                    'string' != typeof e &&\n                    goog.asserts.doAssertFailure_(\n                        'Expected string but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertFunction = function(e, t, r) {\n            return (\n                goog.asserts.ENABLE_ASSERTS &&\n                    !goog.isFunction(e) &&\n                    goog.asserts.doAssertFailure_(\n                        'Expected function but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertObject = function(e, t, r) {\n            return (\n                goog.asserts.ENABLE_ASSERTS &&\n                    !goog.isObject(e) &&\n                    goog.asserts.doAssertFailure_(\n                        'Expected object but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertArray = function(e, t, r) {\n            return (\n                goog.asserts.ENABLE_ASSERTS &&\n                    !Array.isArray(e) &&\n                    goog.asserts.doAssertFailure_(\n                        'Expected array but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertBoolean = function(e, t, r) {\n            return (\n                goog.asserts.ENABLE_ASSERTS &&\n                    'boolean' != typeof e &&\n                    goog.asserts.doAssertFailure_(\n                        'Expected boolean but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertElement = function(e, t, r) {\n            return (\n                !goog.asserts.ENABLE_ASSERTS ||\n                    (goog.isObject(e) && e.nodeType == goog.dom.NodeType.ELEMENT) ||\n                    goog.asserts.doAssertFailure_(\n                        'Expected Element but got %s: %s.',\n                        [goog.typeOf(e), e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertInstanceof = function(e, t, r, o) {\n            return (\n                !goog.asserts.ENABLE_ASSERTS ||\n                    e instanceof t ||\n                    goog.asserts.doAssertFailure_(\n                        'Expected instanceof %s but got %s.',\n                        [goog.asserts.getType_(t), goog.asserts.getType_(e)],\n                        r,\n                        Array.prototype.slice.call(arguments, 3)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertFinite = function(e, t, r) {\n            return (\n                !goog.asserts.ENABLE_ASSERTS ||\n                    ('number' == typeof e && isFinite(e)) ||\n                    goog.asserts.doAssertFailure_(\n                        'Expected %s to be a finite number but it is not.',\n                        [e],\n                        t,\n                        Array.prototype.slice.call(arguments, 2)\n                    ),\n                e\n            );\n        }),\n        (goog.asserts.assertObjectPrototypeIsIntact = function() {\n            for (var e in Object.prototype)\n                goog.asserts.fail(e + ' should not be enumerable in Object.prototype.');\n        }),\n        (goog.asserts.getType_ = function(e) {\n            return e instanceof Function\n                ? e.displayName || e.name || 'unknown type name'\n                : e instanceof Object\n                ? e.constructor.displayName ||\n                  e.constructor.name ||\n                  Object.prototype.toString.call(e)\n                : null === e\n                ? 'null'\n                : typeof e;\n        }),\n        (goog.array = {}),\n        (goog.NATIVE_ARRAY_PROTOTYPES = goog.TRUSTED_SITE),\n        (goog.array.ASSUME_NATIVE_FUNCTIONS = 2012 < goog.FEATURESET_YEAR),\n        (goog.array.peek = function(e) {\n            return e[e.length - 1];\n        }),\n        (goog.array.last = goog.array.peek),\n        (goog.array.indexOf =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.indexOf)\n                ? function(e, t, r) {\n                      return (\n                          goog.asserts.assert(null != e.length),\n                          Array.prototype.indexOf.call(e, t, r)\n                      );\n                  }\n                : function(e, t, r) {\n                      if (\n                          ((r = null == r ? 0 : 0 > r ? Math.max(0, e.length + r) : r),\n                          'string' == typeof e)\n                      )\n                          return 'string' != typeof t || 1 != t.length ? -1 : e.indexOf(t, r);\n                      for (; r < e.length; r++) if (r in e && e[r] === t) return r;\n                      return -1;\n                  }),\n        (goog.array.lastIndexOf =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.lastIndexOf)\n                ? function(e, t, r) {\n                      return (\n                          goog.asserts.assert(null != e.length),\n                          Array.prototype.lastIndexOf.call(e, t, null == r ? e.length - 1 : r)\n                      );\n                  }\n                : function(e, t, r) {\n                      if (\n                          (0 > (r = null == r ? e.length - 1 : r) &&\n                              (r = Math.max(0, e.length + r)),\n                          'string' == typeof e)\n                      )\n                          return 'string' != typeof t || 1 != t.length ? -1 : e.lastIndexOf(t, r);\n                      for (; 0 <= r; r--) if (r in e && e[r] === t) return r;\n                      return -1;\n                  }),\n        (goog.array.forEach =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.forEach)\n                ? function(e, t, r) {\n                      goog.asserts.assert(null != e.length), Array.prototype.forEach.call(e, t, r);\n                  }\n                : function(e, t, r) {\n                      for (\n                          var o = e.length, i = 'string' == typeof e ? e.split('') : e, a = 0;\n                          a < o;\n                          a++\n                      )\n                          a in i && t.call(r, i[a], a, e);\n                  }),\n        (goog.array.forEachRight = function(e, t, r) {\n            var o = e.length,\n                i = 'string' == typeof e ? e.split('') : e;\n            for (--o; 0 <= o; --o) o in i && t.call(r, i[o], o, e);\n        }),\n        (goog.array.filter =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.filter)\n                ? function(e, t, r) {\n                      return (\n                          goog.asserts.assert(null != e.length),\n                          Array.prototype.filter.call(e, t, r)\n                      );\n                  }\n                : function(e, t, r) {\n                      for (\n                          var o = e.length,\n                              i = [],\n                              a = 0,\n                              n = 'string' == typeof e ? e.split('') : e,\n                              s = 0;\n                          s < o;\n                          s++\n                      )\n                          if (s in n) {\n                              var p = n[s];\n                              t.call(r, p, s, e) && (i[a++] = p);\n                          }\n                      return i;\n                  }),\n        (goog.array.map =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.map)\n                ? function(e, t, r) {\n                      return (\n                          goog.asserts.assert(null != e.length), Array.prototype.map.call(e, t, r)\n                      );\n                  }\n                : function(e, t, r) {\n                      for (\n                          var o = e.length,\n                              i = Array(o),\n                              a = 'string' == typeof e ? e.split('') : e,\n                              n = 0;\n                          n < o;\n                          n++\n                      )\n                          n in a && (i[n] = t.call(r, a[n], n, e));\n                      return i;\n                  }),\n        (goog.array.reduce =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduce)\n                ? function(e, t, r, o) {\n                      return (\n                          goog.asserts.assert(null != e.length),\n                          o && (t = goog.bind(t, o)),\n                          Array.prototype.reduce.call(e, t, r)\n                      );\n                  }\n                : function(e, t, r, o) {\n                      var i = r;\n                      return (\n                          goog.array.forEach(e, function(r, a) {\n                              i = t.call(o, i, r, a, e);\n                          }),\n                          i\n                      );\n                  }),\n        (goog.array.reduceRight =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduceRight)\n                ? function(e, t, r, o) {\n                      return (\n                          goog.asserts.assert(null != e.length),\n                          goog.asserts.assert(null != t),\n                          o && (t = goog.bind(t, o)),\n                          Array.prototype.reduceRight.call(e, t, r)\n                      );\n                  }\n                : function(e, t, r, o) {\n                      var i = r;\n                      return (\n                          goog.array.forEachRight(e, function(r, a) {\n                              i = t.call(o, i, r, a, e);\n                          }),\n                          i\n                      );\n                  }),\n        (goog.array.some =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.some)\n                ? function(e, t, r) {\n                      return (\n                          goog.asserts.assert(null != e.length), Array.prototype.some.call(e, t, r)\n                      );\n                  }\n                : function(e, t, r) {\n                      for (\n                          var o = e.length, i = 'string' == typeof e ? e.split('') : e, a = 0;\n                          a < o;\n                          a++\n                      )\n                          if (a in i && t.call(r, i[a], a, e)) return !0;\n                      return !1;\n                  }),\n        (goog.array.every =\n            goog.NATIVE_ARRAY_PROTOTYPES &&\n            (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.every)\n                ? function(e, t, r) {\n                      return (\n                          goog.asserts.assert(null != e.length), Array.prototype.every.call(e, t, r)\n                      );\n                  }\n                : function(e, t, r) {\n                      for (\n                          var o = e.length, i = 'string' == typeof e ? e.split('') : e, a = 0;\n                          a < o;\n                          a++\n                      )\n                          if (a in i && !t.call(r, i[a], a, e)) return !1;\n                      return !0;\n                  }),\n        (goog.array.count = function(e, t, r) {\n            var o = 0;\n            return (\n                goog.array.forEach(\n                    e,\n                    function(e, i, a) {\n                        t.call(r, e, i, a) && ++o;\n                    },\n                    r\n                ),\n                o\n            );\n        }),\n        (goog.array.find = function(e, t, r) {\n            return 0 > (t = goog.array.findIndex(e, t, r))\n                ? null\n                : 'string' == typeof e\n                ? e.charAt(t)\n                : e[t];\n        }),\n        (goog.array.findIndex = function(e, t, r) {\n            for (var o = e.length, i = 'string' == typeof e ? e.split('') : e, a = 0; a < o; a++)\n                if (a in i && t.call(r, i[a], a, e)) return a;\n            return -1;\n        }),\n        (goog.array.findRight = function(e, t, r) {\n            return 0 > (t = goog.array.findIndexRight(e, t, r))\n                ? null\n                : 'string' == typeof e\n                ? e.charAt(t)\n                : e[t];\n        }),\n        (goog.array.findIndexRight = function(e, t, r) {\n            var o = e.length,\n                i = 'string' == typeof e ? e.split('') : e;\n            for (--o; 0 <= o; o--) if (o in i && t.call(r, i[o], o, e)) return o;\n            return -1;\n        }),\n        (goog.array.contains = function(e, t) {\n            return 0 <= goog.array.indexOf(e, t);\n        }),\n        (goog.array.isEmpty = function(e) {\n            return 0 == e.length;\n        }),\n        (goog.array.clear = function(e) {\n            if (!Array.isArray(e)) for (var t = e.length - 1; 0 <= t; t--) delete e[t];\n            e.length = 0;\n        }),\n        (goog.array.insert = function(e, t) {\n            goog.array.contains(e, t) || e.push(t);\n        }),\n        (goog.array.insertAt = function(e, t, r) {\n            goog.array.splice(e, r, 0, t);\n        }),\n        (goog.array.insertArrayAt = function(e, t, r) {\n            goog.partial(goog.array.splice, e, r, 0).apply(null, t);\n        }),\n        (goog.array.insertBefore = function(e, t, r) {\n            var o;\n            2 == arguments.length || 0 > (o = goog.array.indexOf(e, r))\n                ? e.push(t)\n                : goog.array.insertAt(e, t, o);\n        }),\n        (goog.array.remove = function(e, t) {\n            var r;\n            return (r = 0 <= (t = goog.array.indexOf(e, t))) && goog.array.removeAt(e, t), r;\n        }),\n        (goog.array.removeLast = function(e, t) {\n            return 0 <= (t = goog.array.lastIndexOf(e, t)) && (goog.array.removeAt(e, t), !0);\n        }),\n        (goog.array.removeAt = function(e, t) {\n            return (\n                goog.asserts.assert(null != e.length),\n                1 == Array.prototype.splice.call(e, t, 1).length\n            );\n        }),\n        (goog.array.removeIf = function(e, t, r) {\n            return 0 <= (t = goog.array.findIndex(e, t, r)) && (goog.array.removeAt(e, t), !0);\n        }),\n        (goog.array.removeAllIf = function(e, t, r) {\n            var o = 0;\n            return (\n                goog.array.forEachRight(e, function(i, a) {\n                    t.call(r, i, a, e) && goog.array.removeAt(e, a) && o++;\n                }),\n                o\n            );\n        }),\n        (goog.array.concat = function(e) {\n            return Array.prototype.concat.apply([], arguments);\n        }),\n        (goog.array.join = function(e) {\n            return Array.prototype.concat.apply([], arguments);\n        }),\n        (goog.array.toArray = function(e) {\n            var t = e.length;\n            if (0 < t) {\n                for (var r = Array(t), o = 0; o < t; o++) r[o] = e[o];\n                return r;\n            }\n            return [];\n        }),\n        (goog.array.clone = goog.array.toArray),\n        (goog.array.extend = function(e, t) {\n            for (var r = 1; r < arguments.length; r++) {\n                var o = arguments[r];\n                if (goog.isArrayLike(o)) {\n                    var i = e.length || 0,\n                        a = o.length || 0;\n                    e.length = i + a;\n                    for (var n = 0; n < a; n++) e[i + n] = o[n];\n                } else e.push(o);\n            }\n        }),\n        (goog.array.splice = function(e, t, r, o) {\n            return (\n                goog.asserts.assert(null != e.length),\n                Array.prototype.splice.apply(e, goog.array.slice(arguments, 1))\n            );\n        }),\n        (goog.array.slice = function(e, t, r) {\n            return (\n                goog.asserts.assert(null != e.length),\n                2 >= arguments.length\n                    ? Array.prototype.slice.call(e, t)\n                    : Array.prototype.slice.call(e, t, r)\n            );\n        }),\n        (goog.array.removeDuplicates = function(e, t, r) {\n            t = t || e;\n            var o = function(e) {\n                return goog.isObject(e) ? 'o' + goog.getUid(e) : (typeof e).charAt(0) + e;\n            };\n            (r = r || o), (o = {});\n            for (var i = 0, a = 0; a < e.length; ) {\n                var n = e[a++],\n                    s = r(n);\n                Object.prototype.hasOwnProperty.call(o, s) || ((o[s] = !0), (t[i++] = n));\n            }\n            t.length = i;\n        }),\n        (goog.array.binarySearch = function(e, t, r) {\n            return goog.array.binarySearch_(e, r || goog.array.defaultCompare, !1, t);\n        }),\n        (goog.array.binarySelect = function(e, t, r) {\n            return goog.array.binarySearch_(e, t, !0, void 0, r);\n        }),\n        (goog.array.binarySearch_ = function(e, t, r, o, i) {\n            for (var a, n = 0, s = e.length; n < s; ) {\n                var p = n + ((s - n) >>> 1),\n                    d = r ? t.call(i, e[p], p, e) : t(o, e[p]);\n                0 < d ? (n = p + 1) : ((s = p), (a = !d));\n            }\n            return a ? n : -n - 1;\n        }),\n        (goog.array.sort = function(e, t) {\n            e.sort(t || goog.array.defaultCompare);\n        }),\n        (goog.array.stableSort = function(e, t) {\n            for (var r = Array(e.length), o = 0; o < e.length; o++)\n                r[o] = { index: o, value: e[o] };\n            var i = t || goog.array.defaultCompare;\n            for (\n                goog.array.sort(r, function(e, t) {\n                    return i(e.value, t.value) || e.index - t.index;\n                }),\n                    o = 0;\n                o < e.length;\n                o++\n            )\n                e[o] = r[o].value;\n        }),\n        (goog.array.sortByKey = function(e, t, r) {\n            var o = r || goog.array.defaultCompare;\n            goog.array.sort(e, function(e, r) {\n                return o(t(e), t(r));\n            });\n        }),\n        (goog.array.sortObjectsByKey = function(e, t, r) {\n            goog.array.sortByKey(\n                e,\n                function(e) {\n                    return e[t];\n                },\n                r\n            );\n        }),\n        (goog.array.isSorted = function(e, t, r) {\n            t = t || goog.array.defaultCompare;\n            for (var o = 1; o < e.length; o++) {\n                var i = t(e[o - 1], e[o]);\n                if (0 < i || (0 == i && r)) return !1;\n            }\n            return !0;\n        }),\n        (goog.array.equals = function(e, t, r) {\n            if (!goog.isArrayLike(e) || !goog.isArrayLike(t) || e.length != t.length) return !1;\n            var o = e.length;\n            r = r || goog.array.defaultCompareEquality;\n            for (var i = 0; i < o; i++) if (!r(e[i], t[i])) return !1;\n            return !0;\n        }),\n        (goog.array.compare3 = function(e, t, r) {\n            r = r || goog.array.defaultCompare;\n            for (var o = Math.min(e.length, t.length), i = 0; i < o; i++) {\n                var a = r(e[i], t[i]);\n                if (0 != a) return a;\n            }\n            return goog.array.defaultCompare(e.length, t.length);\n        }),\n        (goog.array.defaultCompare = function(e, t) {\n            return e > t ? 1 : e < t ? -1 : 0;\n        }),\n        (goog.array.inverseDefaultCompare = function(e, t) {\n            return -goog.array.defaultCompare(e, t);\n        }),\n        (goog.array.defaultCompareEquality = function(e, t) {\n            return e === t;\n        }),\n        (goog.array.binaryInsert = function(e, t, r) {\n            return (\n                0 > (r = goog.array.binarySearch(e, t, r)) &&\n                (goog.array.insertAt(e, t, -(r + 1)), !0)\n            );\n        }),\n        (goog.array.binaryRemove = function(e, t, r) {\n            return 0 <= (t = goog.array.binarySearch(e, t, r)) && goog.array.removeAt(e, t);\n        }),\n        (goog.array.bucket = function(e, t, r) {\n            for (var o = {}, i = 0; i < e.length; i++) {\n                var a = e[i],\n                    n = t.call(r, a, i, e);\n                void 0 !== n && (o[n] || (o[n] = [])).push(a);\n            }\n            return o;\n        }),\n        (goog.array.toObject = function(e, t, r) {\n            var o = {};\n            return (\n                goog.array.forEach(e, function(i, a) {\n                    o[t.call(r, i, a, e)] = i;\n                }),\n                o\n            );\n        }),\n        (goog.array.range = function(e, t, r) {\n            var o = [],\n                i = 0,\n                a = e;\n            if ((void 0 !== t && ((i = e), (a = t)), 0 > (r = r || 1) * (a - i))) return [];\n            if (0 < r) for (e = i; e < a; e += r) o.push(e);\n            else for (e = i; e > a; e += r) o.push(e);\n            return o;\n        }),\n        (goog.array.repeat = function(e, t) {\n            for (var r = [], o = 0; o < t; o++) r[o] = e;\n            return r;\n        }),\n        (goog.array.flatten = function(e) {\n            for (var t = [], r = 0; r < arguments.length; r++) {\n                var o = arguments[r];\n                if (Array.isArray(o))\n                    for (var i = 0; i < o.length; i += 8192) {\n                        var a = goog.array.slice(o, i, i + 8192);\n                        a = goog.array.flatten.apply(null, a);\n                        for (var n = 0; n < a.length; n++) t.push(a[n]);\n                    }\n                else t.push(o);\n            }\n            return t;\n        }),\n        (goog.array.rotate = function(e, t) {\n            return (\n                goog.asserts.assert(null != e.length),\n                e.length &&\n                    (0 < (t %= e.length)\n                        ? Array.prototype.unshift.apply(e, e.splice(-t, t))\n                        : 0 > t && Array.prototype.push.apply(e, e.splice(0, -t))),\n                e\n            );\n        }),\n        (goog.array.moveItem = function(e, t, r) {\n            goog.asserts.assert(0 <= t && t < e.length),\n                goog.asserts.assert(0 <= r && r < e.length),\n                (t = Array.prototype.splice.call(e, t, 1)),\n                Array.prototype.splice.call(e, r, 0, t[0]);\n        }),\n        (goog.array.zip = function(e) {\n            if (!arguments.length) return [];\n            for (var t = [], r = arguments[0].length, o = 1; o < arguments.length; o++)\n                arguments[o].length < r && (r = arguments[o].length);\n            for (o = 0; o < r; o++) {\n                for (var i = [], a = 0; a < arguments.length; a++) i.push(arguments[a][o]);\n                t.push(i);\n            }\n            return t;\n        }),\n        (goog.array.shuffle = function(e, t) {\n            t = t || Math.random;\n            for (var r = e.length - 1; 0 < r; r--) {\n                var o = Math.floor(t() * (r + 1)),\n                    i = e[r];\n                (e[r] = e[o]), (e[o] = i);\n            }\n        }),\n        (goog.array.copyByIndex = function(e, t) {\n            var r = [];\n            return (\n                goog.array.forEach(t, function(t) {\n                    r.push(e[t]);\n                }),\n                r\n            );\n        }),\n        (goog.array.concatMap = function(e, t, r) {\n            return goog.array.concat.apply([], goog.array.map(e, t, r));\n        }),\n        (goog.crypt = {}),\n        (goog.crypt.stringToByteArray = function(e) {\n            for (var t = [], r = 0, o = 0; o < e.length; o++) {\n                var i = e.charCodeAt(o);\n                255 < i && ((t[r++] = 255 & i), (i >>= 8)), (t[r++] = i);\n            }\n            return t;\n        }),\n        (goog.crypt.byteArrayToString = function(e) {\n            if (8192 >= e.length) return String.fromCharCode.apply(null, e);\n            for (var t = '', r = 0; r < e.length; r += 8192) {\n                var o = goog.array.slice(e, r, r + 8192);\n                t += String.fromCharCode.apply(null, o);\n            }\n            return t;\n        }),\n        (goog.crypt.byteArrayToHex = function(e, t) {\n            return goog.array\n                .map(e, function(e) {\n                    return 1 < (e = e.toString(16)).length ? e : '0' + e;\n                })\n                .join(t || '');\n        }),\n        (goog.crypt.hexToByteArray = function(e) {\n            goog.asserts.assert(0 == e.length % 2, 'Key string length must be multiple of 2');\n            for (var t = [], r = 0; r < e.length; r += 2)\n                t.push(parseInt(e.substring(r, r + 2), 16));\n            return t;\n        }),\n        (goog.crypt.stringToUtf8ByteArray = function(e) {\n            for (var t = [], r = 0, o = 0; o < e.length; o++) {\n                var i = e.charCodeAt(o);\n                128 > i\n                    ? (t[r++] = i)\n                    : (2048 > i\n                          ? (t[r++] = (i >> 6) | 192)\n                          : (55296 == (64512 & i) &&\n                            o + 1 < e.length &&\n                            56320 == (64512 & e.charCodeAt(o + 1))\n                                ? ((i = 65536 + ((1023 & i) << 10) + (1023 & e.charCodeAt(++o))),\n                                  (t[r++] = (i >> 18) | 240),\n                                  (t[r++] = ((i >> 12) & 63) | 128))\n                                : (t[r++] = (i >> 12) | 224),\n                            (t[r++] = ((i >> 6) & 63) | 128)),\n                      (t[r++] = (63 & i) | 128));\n            }\n            return t;\n        }),\n        (goog.crypt.utf8ByteArrayToString = function(e) {\n            for (var t = [], r = 0, o = 0; r < e.length; ) {\n                var i = e[r++];\n                if (128 > i) t[o++] = String.fromCharCode(i);\n                else if (191 < i && 224 > i) {\n                    var a = e[r++];\n                    t[o++] = String.fromCharCode(((31 & i) << 6) | (63 & a));\n                } else if (239 < i && 365 > i) {\n                    a = e[r++];\n                    var n = e[r++];\n                    (i =\n                        (((7 & i) << 18) | ((63 & a) << 12) | ((63 & n) << 6) | (63 & e[r++])) -\n                        65536),\n                        (t[o++] = String.fromCharCode(55296 + (i >> 10))),\n                        (t[o++] = String.fromCharCode(56320 + (1023 & i)));\n                } else\n                    (a = e[r++]),\n                        (n = e[r++]),\n                        (t[o++] = String.fromCharCode(\n                            ((15 & i) << 12) | ((63 & a) << 6) | (63 & n)\n                        ));\n            }\n            return t.join('');\n        }),\n        (goog.crypt.xorByteArray = function(e, t) {\n            goog.asserts.assert(e.length == t.length, 'XOR array lengths must match');\n            for (var r = [], o = 0; o < e.length; o++) r.push(e[o] ^ t[o]);\n            return r;\n        }),\n        (goog.dom.asserts = {}),\n        (goog.dom.asserts.assertIsLocation = function(e) {\n            if (goog.asserts.ENABLE_ASSERTS) {\n                var t = goog.dom.asserts.getWindow_(e);\n                t &&\n                    (!e || (!(e instanceof t.Location) && e instanceof t.Element)) &&\n                    goog.asserts.fail(\n                        'Argument is not a Location (or a non-Element mock); got: %s',\n                        goog.dom.asserts.debugStringForType_(e)\n                    );\n            }\n            return e;\n        }),\n        (goog.dom.asserts.assertIsElementType_ = function(e, t) {\n            if (goog.asserts.ENABLE_ASSERTS) {\n                var r = goog.dom.asserts.getWindow_(e);\n                r &&\n                    void 0 !== r[t] &&\n                    ((e &&\n                        (e instanceof r[t] ||\n                            !(e instanceof r.Location || e instanceof r.Element))) ||\n                        goog.asserts.fail(\n                            'Argument is not a %s (or a non-Element, non-Location mock); got: %s',\n                            t,\n                            goog.dom.asserts.debugStringForType_(e)\n                        ));\n            }\n            return e;\n        }),\n        (goog.dom.asserts.assertIsHTMLAnchorElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLAnchorElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLButtonElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLButtonElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLLinkElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLLinkElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLImageElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLImageElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLAudioElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLAudioElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLVideoElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLVideoElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLInputElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLInputElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLTextAreaElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLTextAreaElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLCanvasElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLCanvasElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLEmbedElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLEmbedElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLFormElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLFormElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLFrameElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLFrameElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLIFrameElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLIFrameElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLObjectElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLObjectElement');\n        }),\n        (goog.dom.asserts.assertIsHTMLScriptElement = function(e) {\n            return goog.dom.asserts.assertIsElementType_(e, 'HTMLScriptElement');\n        }),\n        (goog.dom.asserts.debugStringForType_ = function(e) {\n            if (!goog.isObject(e))\n                return void 0 === e ? 'undefined' : null === e ? 'null' : typeof e;\n            try {\n                return (\n                    e.constructor.displayName ||\n                    e.constructor.name ||\n                    Object.prototype.toString.call(e)\n                );\n            } catch (e) {\n                return '<object could not be stringified>';\n            }\n        }),\n        (goog.dom.asserts.getWindow_ = function(e) {\n            try {\n                var t = e && e.ownerDocument,\n                    r = t && (t.defaultView || t.parentWindow);\n                if ((r = r || goog.global).Element && r.Location) return r;\n            } catch (e) {}\n            return null;\n        }),\n        (goog.functions = {}),\n        (goog.functions.constant = function(e) {\n            return function() {\n                return e;\n            };\n        }),\n        (goog.functions.FALSE = function() {\n            return !1;\n        }),\n        (goog.functions.TRUE = function() {\n            return !0;\n        }),\n        (goog.functions.NULL = function() {\n            return null;\n        }),\n        (goog.functions.identity = function(e, t) {\n            return e;\n        }),\n        (goog.functions.error = function(e) {\n            return function() {\n                throw Error(e);\n            };\n        }),\n        (goog.functions.fail = function(e) {\n            return function() {\n                throw e;\n            };\n        }),\n        (goog.functions.lock = function(e, t) {\n            return (\n                (t = t || 0),\n                function() {\n                    return e.apply(this, Array.prototype.slice.call(arguments, 0, t));\n                }\n            );\n        }),\n        (goog.functions.nth = function(e) {\n            return function() {\n                return arguments[e];\n            };\n        }),\n        (goog.functions.partialRight = function(e, t) {\n            var r = Array.prototype.slice.call(arguments, 1);\n            return function() {\n                var t = Array.prototype.slice.call(arguments);\n                return t.push.apply(t, r), e.apply(this, t);\n            };\n        }),\n        (goog.functions.withReturnValue = function(e, t) {\n            return goog.functions.sequence(e, goog.functions.constant(t));\n        }),\n        (goog.functions.equalTo = function(e, t) {\n            return function(r) {\n                return t ? e == r : e === r;\n            };\n        }),\n        (goog.functions.compose = function(e, t) {\n            var r = arguments,\n                o = r.length;\n            return function() {\n                var e;\n                o && (e = r[o - 1].apply(this, arguments));\n                for (var t = o - 2; 0 <= t; t--) e = r[t].call(this, e);\n                return e;\n            };\n        }),\n        (goog.functions.sequence = function(e) {\n            var t = arguments,\n                r = t.length;\n            return function() {\n                for (var e, o = 0; o < r; o++) e = t[o].apply(this, arguments);\n                return e;\n            };\n        }),\n        (goog.functions.and = function(e) {\n            var t = arguments,\n                r = t.length;\n            return function() {\n                for (var e = 0; e < r; e++) if (!t[e].apply(this, arguments)) return !1;\n                return !0;\n            };\n        }),\n        (goog.functions.or = function(e) {\n            var t = arguments,\n                r = t.length;\n            return function() {\n                for (var e = 0; e < r; e++) if (t[e].apply(this, arguments)) return !0;\n                return !1;\n            };\n        }),\n        (goog.functions.not = function(e) {\n            return function() {\n                return !e.apply(this, arguments);\n            };\n        }),\n        (goog.functions.create = function(e, t) {\n            var r = function() {};\n            return (\n                (r.prototype = e.prototype),\n                (r = new r()),\n                e.apply(r, Array.prototype.slice.call(arguments, 1)),\n                r\n            );\n        }),\n        (goog.functions.CACHE_RETURN_VALUE = !0),\n        (goog.functions.cacheReturnValue = function(e) {\n            var t,\n                r = !1;\n            return function() {\n                return goog.functions.CACHE_RETURN_VALUE ? (r || ((t = e()), (r = !0)), t) : e();\n            };\n        }),\n        (goog.functions.once = function(e) {\n            var t = e;\n            return function() {\n                if (t) {\n                    var e = t;\n                    (t = null), e();\n                }\n            };\n        }),\n        (goog.functions.debounce = function(e, t, r) {\n            var o = 0;\n            return function(i) {\n                goog.global.clearTimeout(o);\n                var a = arguments;\n                o = goog.global.setTimeout(function() {\n                    e.apply(r, a);\n                }, t);\n            };\n        }),\n        (goog.functions.throttle = function(e, t, r) {\n            var o = 0,\n                i = !1,\n                a = [],\n                n = function() {\n                    (o = 0), i && ((i = !1), s());\n                },\n                s = function() {\n                    (o = goog.global.setTimeout(n, t)), e.apply(r, a);\n                };\n            return function(e) {\n                (a = arguments), o ? (i = !0) : s();\n            };\n        }),\n        (goog.functions.rateLimit = function(e, t, r) {\n            var o = 0,\n                i = function() {\n                    o = 0;\n                };\n            return function(a) {\n                o || ((o = goog.global.setTimeout(i, t)), e.apply(r, arguments));\n            };\n        }),\n        (goog.dom.HtmlElement = function() {}),\n        (goog.dom.TagName = function(e) {\n            this.tagName_ = e;\n        }),\n        (goog.dom.TagName.prototype.toString = function() {\n            return this.tagName_;\n        }),\n        (goog.dom.TagName.A = new goog.dom.TagName('A')),\n        (goog.dom.TagName.ABBR = new goog.dom.TagName('ABBR')),\n        (goog.dom.TagName.ACRONYM = new goog.dom.TagName('ACRONYM')),\n        (goog.dom.TagName.ADDRESS = new goog.dom.TagName('ADDRESS')),\n        (goog.dom.TagName.APPLET = new goog.dom.TagName('APPLET')),\n        (goog.dom.TagName.AREA = new goog.dom.TagName('AREA')),\n        (goog.dom.TagName.ARTICLE = new goog.dom.TagName('ARTICLE')),\n        (goog.dom.TagName.ASIDE = new goog.dom.TagName('ASIDE')),\n        (goog.dom.TagName.AUDIO = new goog.dom.TagName('AUDIO')),\n        (goog.dom.TagName.B = new goog.dom.TagName('B')),\n        (goog.dom.TagName.BASE = new goog.dom.TagName('BASE')),\n        (goog.dom.TagName.BASEFONT = new goog.dom.TagName('BASEFONT')),\n        (goog.dom.TagName.BDI = new goog.dom.TagName('BDI')),\n        (goog.dom.TagName.BDO = new goog.dom.TagName('BDO')),\n        (goog.dom.TagName.BIG = new goog.dom.TagName('BIG')),\n        (goog.dom.TagName.BLOCKQUOTE = new goog.dom.TagName('BLOCKQUOTE')),\n        (goog.dom.TagName.BODY = new goog.dom.TagName('BODY')),\n        (goog.dom.TagName.BR = new goog.dom.TagName('BR')),\n        (goog.dom.TagName.BUTTON = new goog.dom.TagName('BUTTON')),\n        (goog.dom.TagName.CANVAS = new goog.dom.TagName('CANVAS')),\n        (goog.dom.TagName.CAPTION = new goog.dom.TagName('CAPTION')),\n        (goog.dom.TagName.CENTER = new goog.dom.TagName('CENTER')),\n        (goog.dom.TagName.CITE = new goog.dom.TagName('CITE')),\n        (goog.dom.TagName.CODE = new goog.dom.TagName('CODE')),\n        (goog.dom.TagName.COL = new goog.dom.TagName('COL')),\n        (goog.dom.TagName.COLGROUP = new goog.dom.TagName('COLGROUP')),\n        (goog.dom.TagName.COMMAND = new goog.dom.TagName('COMMAND')),\n        (goog.dom.TagName.DATA = new goog.dom.TagName('DATA')),\n        (goog.dom.TagName.DATALIST = new goog.dom.TagName('DATALIST')),\n        (goog.dom.TagName.DD = new goog.dom.TagName('DD')),\n        (goog.dom.TagName.DEL = new goog.dom.TagName('DEL')),\n        (goog.dom.TagName.DETAILS = new goog.dom.TagName('DETAILS')),\n        (goog.dom.TagName.DFN = new goog.dom.TagName('DFN')),\n        (goog.dom.TagName.DIALOG = new goog.dom.TagName('DIALOG')),\n        (goog.dom.TagName.DIR = new goog.dom.TagName('DIR')),\n        (goog.dom.TagName.DIV = new goog.dom.TagName('DIV')),\n        (goog.dom.TagName.DL = new goog.dom.TagName('DL')),\n        (goog.dom.TagName.DT = new goog.dom.TagName('DT')),\n        (goog.dom.TagName.EM = new goog.dom.TagName('EM')),\n        (goog.dom.TagName.EMBED = new goog.dom.TagName('EMBED')),\n        (goog.dom.TagName.FIELDSET = new goog.dom.TagName('FIELDSET')),\n        (goog.dom.TagName.FIGCAPTION = new goog.dom.TagName('FIGCAPTION')),\n        (goog.dom.TagName.FIGURE = new goog.dom.TagName('FIGURE')),\n        (goog.dom.TagName.FONT = new goog.dom.TagName('FONT')),\n        (goog.dom.TagName.FOOTER = new goog.dom.TagName('FOOTER')),\n        (goog.dom.TagName.FORM = new goog.dom.TagName('FORM')),\n        (goog.dom.TagName.FRAME = new goog.dom.TagName('FRAME')),\n        (goog.dom.TagName.FRAMESET = new goog.dom.TagName('FRAMESET')),\n        (goog.dom.TagName.H1 = new goog.dom.TagName('H1')),\n        (goog.dom.TagName.H2 = new goog.dom.TagName('H2')),\n        (goog.dom.TagName.H3 = new goog.dom.TagName('H3')),\n        (goog.dom.TagName.H4 = new goog.dom.TagName('H4')),\n        (goog.dom.TagName.H5 = new goog.dom.TagName('H5')),\n        (goog.dom.TagName.H6 = new goog.dom.TagName('H6')),\n        (goog.dom.TagName.HEAD = new goog.dom.TagName('HEAD')),\n        (goog.dom.TagName.HEADER = new goog.dom.TagName('HEADER')),\n        (goog.dom.TagName.HGROUP = new goog.dom.TagName('HGROUP')),\n        (goog.dom.TagName.HR = new goog.dom.TagName('HR')),\n        (goog.dom.TagName.HTML = new goog.dom.TagName('HTML')),\n        (goog.dom.TagName.I = new goog.dom.TagName('I')),\n        (goog.dom.TagName.IFRAME = new goog.dom.TagName('IFRAME')),\n        (goog.dom.TagName.IMG = new goog.dom.TagName('IMG')),\n        (goog.dom.TagName.INPUT = new goog.dom.TagName('INPUT')),\n        (goog.dom.TagName.INS = new goog.dom.TagName('INS')),\n        (goog.dom.TagName.ISINDEX = new goog.dom.TagName('ISINDEX')),\n        (goog.dom.TagName.KBD = new goog.dom.TagName('KBD')),\n        (goog.dom.TagName.KEYGEN = new goog.dom.TagName('KEYGEN')),\n        (goog.dom.TagName.LABEL = new goog.dom.TagName('LABEL')),\n        (goog.dom.TagName.LEGEND = new goog.dom.TagName('LEGEND')),\n        (goog.dom.TagName.LI = new goog.dom.TagName('LI')),\n        (goog.dom.TagName.LINK = new goog.dom.TagName('LINK')),\n        (goog.dom.TagName.MAIN = new goog.dom.TagName('MAIN')),\n        (goog.dom.TagName.MAP = new goog.dom.TagName('MAP')),\n        (goog.dom.TagName.MARK = new goog.dom.TagName('MARK')),\n        (goog.dom.TagName.MATH = new goog.dom.TagName('MATH')),\n        (goog.dom.TagName.MENU = new goog.dom.TagName('MENU')),\n        (goog.dom.TagName.MENUITEM = new goog.dom.TagName('MENUITEM')),\n        (goog.dom.TagName.META = new goog.dom.TagName('META')),\n        (goog.dom.TagName.METER = new goog.dom.TagName('METER')),\n        (goog.dom.TagName.NAV = new goog.dom.TagName('NAV')),\n        (goog.dom.TagName.NOFRAMES = new goog.dom.TagName('NOFRAMES')),\n        (goog.dom.TagName.NOSCRIPT = new goog.dom.TagName('NOSCRIPT')),\n        (goog.dom.TagName.OBJECT = new goog.dom.TagName('OBJECT')),\n        (goog.dom.TagName.OL = new goog.dom.TagName('OL')),\n        (goog.dom.TagName.OPTGROUP = new goog.dom.TagName('OPTGROUP')),\n        (goog.dom.TagName.OPTION = new goog.dom.TagName('OPTION')),\n        (goog.dom.TagName.OUTPUT = new goog.dom.TagName('OUTPUT')),\n        (goog.dom.TagName.P = new goog.dom.TagName('P')),\n        (goog.dom.TagName.PARAM = new goog.dom.TagName('PARAM')),\n        (goog.dom.TagName.PICTURE = new goog.dom.TagName('PICTURE')),\n        (goog.dom.TagName.PRE = new goog.dom.TagName('PRE')),\n        (goog.dom.TagName.PROGRESS = new goog.dom.TagName('PROGRESS')),\n        (goog.dom.TagName.Q = new goog.dom.TagName('Q')),\n        (goog.dom.TagName.RP = new goog.dom.TagName('RP')),\n        (goog.dom.TagName.RT = new goog.dom.TagName('RT')),\n        (goog.dom.TagName.RTC = new goog.dom.TagName('RTC')),\n        (goog.dom.TagName.RUBY = new goog.dom.TagName('RUBY')),\n        (goog.dom.TagName.S = new goog.dom.TagName('S')),\n        (goog.dom.TagName.SAMP = new goog.dom.TagName('SAMP')),\n        (goog.dom.TagName.SCRIPT = new goog.dom.TagName('SCRIPT')),\n        (goog.dom.TagName.SECTION = new goog.dom.TagName('SECTION')),\n        (goog.dom.TagName.SELECT = new goog.dom.TagName('SELECT')),\n        (goog.dom.TagName.SMALL = new goog.dom.TagName('SMALL')),\n        (goog.dom.TagName.SOURCE = new goog.dom.TagName('SOURCE')),\n        (goog.dom.TagName.SPAN = new goog.dom.TagName('SPAN')),\n        (goog.dom.TagName.STRIKE = new goog.dom.TagName('STRIKE')),\n        (goog.dom.TagName.STRONG = new goog.dom.TagName('STRONG')),\n        (goog.dom.TagName.STYLE = new goog.dom.TagName('STYLE')),\n        (goog.dom.TagName.SUB = new goog.dom.TagName('SUB')),\n        (goog.dom.TagName.SUMMARY = new goog.dom.TagName('SUMMARY')),\n        (goog.dom.TagName.SUP = new goog.dom.TagName('SUP')),\n        (goog.dom.TagName.SVG = new goog.dom.TagName('SVG')),\n        (goog.dom.TagName.TABLE = new goog.dom.TagName('TABLE')),\n        (goog.dom.TagName.TBODY = new goog.dom.TagName('TBODY')),\n        (goog.dom.TagName.TD = new goog.dom.TagName('TD')),\n        (goog.dom.TagName.TEMPLATE = new goog.dom.TagName('TEMPLATE')),\n        (goog.dom.TagName.TEXTAREA = new goog.dom.TagName('TEXTAREA')),\n        (goog.dom.TagName.TFOOT = new goog.dom.TagName('TFOOT')),\n        (goog.dom.TagName.TH = new goog.dom.TagName('TH')),\n        (goog.dom.TagName.THEAD = new goog.dom.TagName('THEAD')),\n        (goog.dom.TagName.TIME = new goog.dom.TagName('TIME')),\n        (goog.dom.TagName.TITLE = new goog.dom.TagName('TITLE')),\n        (goog.dom.TagName.TR = new goog.dom.TagName('TR')),\n        (goog.dom.TagName.TRACK = new goog.dom.TagName('TRACK')),\n        (goog.dom.TagName.TT = new goog.dom.TagName('TT')),\n        (goog.dom.TagName.U = new goog.dom.TagName('U')),\n        (goog.dom.TagName.UL = new goog.dom.TagName('UL')),\n        (goog.dom.TagName.VAR = new goog.dom.TagName('VAR')),\n        (goog.dom.TagName.VIDEO = new goog.dom.TagName('VIDEO')),\n        (goog.dom.TagName.WBR = new goog.dom.TagName('WBR')),\n        (goog.dom.tags = {}),\n        (goog.dom.tags.VOID_TAGS_ = {\n            area: !0,\n            base: !0,\n            br: !0,\n            col: !0,\n            command: !0,\n            embed: !0,\n            hr: !0,\n            img: !0,\n            input: !0,\n            keygen: !0,\n            link: !0,\n            meta: !0,\n            param: !0,\n            source: !0,\n            track: !0,\n            wbr: !0,\n        }),\n        (goog.dom.tags.isVoidTag = function(e) {\n            return !0 === goog.dom.tags.VOID_TAGS_[e];\n        }),\n        (goog.html = {}),\n        (goog.html.trustedtypes = {}),\n        (goog.html.trustedtypes.PRIVATE_DO_NOT_ACCESS_OR_ELSE_POLICY = goog.TRUSTED_TYPES_POLICY_NAME\n            ? goog.createTrustedTypesPolicy(goog.TRUSTED_TYPES_POLICY_NAME + '#html')\n            : null),\n        (goog.string = {}),\n        (goog.string.TypedString = function() {}),\n        (goog.string.Const = function(e, t) {\n            (this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ =\n                (e === goog.string.Const.GOOG_STRING_CONSTRUCTOR_TOKEN_PRIVATE_ && t) || ''),\n                (this.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ =\n                    goog.string.Const.TYPE_MARKER_);\n        }),\n        (goog.string.Const.prototype.implementsGoogStringTypedString = !0),\n        (goog.string.Const.prototype.getTypedStringValue = function() {\n            return this.stringConstValueWithSecurityContract__googStringSecurityPrivate_;\n        }),\n        goog.DEBUG &&\n            (goog.string.Const.prototype.toString = function() {\n                return (\n                    'Const{' +\n                    this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ +\n                    '}'\n                );\n            }),\n        (goog.string.Const.unwrap = function(e) {\n            return e instanceof goog.string.Const &&\n                e.constructor === goog.string.Const &&\n                e.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ ===\n                    goog.string.Const.TYPE_MARKER_\n                ? e.stringConstValueWithSecurityContract__googStringSecurityPrivate_\n                : (goog.asserts.fail(\"expected object of type Const, got '\" + e + \"'\"),\n                  'type_error:Const');\n        }),\n        (goog.string.Const.from = function(e) {\n            return new goog.string.Const(\n                goog.string.Const.GOOG_STRING_CONSTRUCTOR_TOKEN_PRIVATE_,\n                e\n            );\n        }),\n        (goog.string.Const.TYPE_MARKER_ = {}),\n        (goog.string.Const.GOOG_STRING_CONSTRUCTOR_TOKEN_PRIVATE_ = {}),\n        (goog.string.Const.EMPTY = goog.string.Const.from('')),\n        (goog.html.SafeScript = function() {\n            (this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = ''),\n                (this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =\n                    goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_);\n        }),\n        (goog.html.SafeScript.prototype.implementsGoogStringTypedString = !0),\n        (goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}),\n        (goog.html.SafeScript.fromConstant = function(e) {\n            return 0 === (e = goog.string.Const.unwrap(e)).length\n                ? goog.html.SafeScript.EMPTY\n                : goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(e);\n        }),\n        (goog.html.SafeScript.fromConstantAndArgs = function(e, t) {\n            for (var r = [], o = 1; o < arguments.length; o++)\n                r.push(goog.html.SafeScript.stringify_(arguments[o]));\n            return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(\n                '(' + goog.string.Const.unwrap(e) + ')(' + r.join(', ') + ');'\n            );\n        }),\n        (goog.html.SafeScript.fromJson = function(e) {\n            return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(\n                goog.html.SafeScript.stringify_(e)\n            );\n        }),\n        (goog.html.SafeScript.prototype.getTypedStringValue = function() {\n            return this.privateDoNotAccessOrElseSafeScriptWrappedValue_.toString();\n        }),\n        goog.DEBUG &&\n            (goog.html.SafeScript.prototype.toString = function() {\n                return 'SafeScript{' + this.privateDoNotAccessOrElseSafeScriptWrappedValue_ + '}';\n            }),\n        (goog.html.SafeScript.unwrap = function(e) {\n            return goog.html.SafeScript.unwrapTrustedScript(e).toString();\n        }),\n        (goog.html.SafeScript.unwrapTrustedScript = function(e) {\n            return e instanceof goog.html.SafeScript &&\n                e.constructor === goog.html.SafeScript &&\n                e.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===\n                    goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_\n                ? e.privateDoNotAccessOrElseSafeScriptWrappedValue_\n                : (goog.asserts.fail(\n                      \"expected object of type SafeScript, got '\" +\n                          e +\n                          \"' of type \" +\n                          goog.typeOf(e)\n                  ),\n                  'type_error:SafeScript');\n        }),\n        (goog.html.SafeScript.stringify_ = function(e) {\n            return JSON.stringify(e).replace(/</g, '\\\\x3c');\n        }),\n        (goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse = function(e) {\n            return new goog.html.SafeScript().initSecurityPrivateDoNotAccessOrElse_(e);\n        }),\n        (goog.html.SafeScript.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(e) {\n            return (\n                (this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = goog.html.trustedtypes\n                    .PRIVATE_DO_NOT_ACCESS_OR_ELSE_POLICY\n                    ? goog.html.trustedtypes.PRIVATE_DO_NOT_ACCESS_OR_ELSE_POLICY.createScript(e)\n                    : e),\n                this\n            );\n        }),\n        (goog.html.SafeScript.EMPTY = goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(\n            ''\n        )),\n        (goog.fs = {}),\n        (goog.fs.url = {}),\n        (goog.fs.url.createObjectUrl = function(e) {\n            return goog.fs.url.getUrlObject_().createObjectURL(e);\n        }),\n        (goog.fs.url.revokeObjectUrl = function(e) {\n            goog.fs.url.getUrlObject_().revokeObjectURL(e);\n        }),\n        (goog.fs.url.UrlObject_ = function() {}),\n        (goog.fs.url.UrlObject_.prototype.createObjectURL = function(e) {}),\n        (goog.fs.url.UrlObject_.prototype.revokeObjectURL = function(e) {}),\n        (goog.fs.url.getUrlObject_ = function() {\n            var e = goog.fs.url.findUrlObject_();\n            if (null != e) return e;\n            throw Error(\"This browser doesn't seem to support blob URLs\");\n        }),\n        (goog.fs.url.findUrlObject_ = function() {\n            return void 0 !== goog.global.URL && void 0 !== goog.global.URL.createObjectURL\n                ? goog.global.URL\n                : void 0 !== goog.global.webkitURL &&\n                  void 0 !== goog.global.webkitURL.createObjectURL\n                ? goog.global.webkitURL\n                : void 0 !== goog.global.createObjectURL\n                ? goog.global\n                : null;\n        }),\n        (goog.fs.url.browserSupportsObjectUrls = function() {\n            return null != goog.fs.url.findUrlObject_();\n        }),\n        (goog.fs.blob = {}),\n        (goog.fs.blob.getBlob = function(e) {\n            var t = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;\n            if (void 0 !== t) {\n                t = new t();\n                for (var r = 0; r < arguments.length; r++) t.append(arguments[r]);\n                return t.getBlob();\n            }\n            return goog.fs.blob.getBlobWithProperties(goog.array.toArray(arguments));\n        }),\n        (goog.fs.blob.getBlobWithProperties = function(e, t, r) {\n            var o = goog.global.BlobBuilder || goog.global.WebKitBlobBuilder;\n            if (void 0 !== o) {\n                o = new o();\n                for (var i = 0; i < e.length; i++) o.append(e[i], r);\n                return o.getBlob(t);\n            }\n            if (void 0 !== goog.global.Blob)\n                return (o = {}), t && (o.type = t), r && (o.endings = r), new Blob(e, o);\n            throw Error(\"This browser doesn't seem to support creating Blobs\");\n        }),\n        (goog.i18n = {}),\n        (goog.i18n.bidi = {}),\n        (goog.i18n.bidi.FORCE_RTL = !1),\n        (goog.i18n.bidi.IS_RTL =\n            goog.i18n.bidi.FORCE_RTL ||\n            (('ar' == goog.LOCALE.substring(0, 2).toLowerCase() ||\n                'fa' == goog.LOCALE.substring(0, 2).toLowerCase() ||\n                'he' == goog.LOCALE.substring(0, 2).toLowerCase() ||\n                'iw' == goog.LOCALE.substring(0, 2).toLowerCase() ||\n                'ps' == goog.LOCALE.substring(0, 2).toLowerCase() ||\n                'sd' == goog.LOCALE.substring(0, 2).toLowerCase() ||\n                'ug' == goog.LOCALE.substring(0, 2).toLowerCase() ||\n                'ur' == goog.LOCALE.substring(0, 2).toLowerCase() ||\n                'yi' == goog.LOCALE.substring(0, 2).toLowerCase()) &&\n                (2 == goog.LOCALE.length ||\n                    '-' == goog.LOCALE.substring(2, 3) ||\n                    '_' == goog.LOCALE.substring(2, 3))) ||\n            (3 <= goog.LOCALE.length &&\n                'ckb' == goog.LOCALE.substring(0, 3).toLowerCase() &&\n                (3 == goog.LOCALE.length ||\n                    '-' == goog.LOCALE.substring(3, 4) ||\n                    '_' == goog.LOCALE.substring(3, 4))) ||\n            (7 <= goog.LOCALE.length &&\n                ('-' == goog.LOCALE.substring(2, 3) || '_' == goog.LOCALE.substring(2, 3)) &&\n                ('adlm' == goog.LOCALE.substring(3, 7).toLowerCase() ||\n                    'arab' == goog.LOCALE.substring(3, 7).toLowerCase() ||\n                    'hebr' == goog.LOCALE.substring(3, 7).toLowerCase() ||\n                    'nkoo' == goog.LOCALE.substring(3, 7).toLowerCase() ||\n                    'rohg' == goog.LOCALE.substring(3, 7).toLowerCase() ||\n                    'thaa' == goog.LOCALE.substring(3, 7).toLowerCase())) ||\n            (8 <= goog.LOCALE.length &&\n                ('-' == goog.LOCALE.substring(3, 4) || '_' == goog.LOCALE.substring(3, 4)) &&\n                ('adlm' == goog.LOCALE.substring(4, 8).toLowerCase() ||\n                    'arab' == goog.LOCALE.substring(4, 8).toLowerCase() ||\n                    'hebr' == goog.LOCALE.substring(4, 8).toLowerCase() ||\n                    'nkoo' == goog.LOCALE.substring(4, 8).toLowerCase() ||\n                    'rohg' == goog.LOCALE.substring(4, 8).toLowerCase() ||\n                    'thaa' == goog.LOCALE.substring(4, 8).toLowerCase()))),\n        (goog.i18n.bidi.Format = { LRE: '‪', RLE: '‫', PDF: '‬', LRM: '‎', RLM: '‏' }),\n        (goog.i18n.bidi.Dir = { LTR: 1, RTL: -1, NEUTRAL: 0 }),\n        (goog.i18n.bidi.RIGHT = 'right'),\n        (goog.i18n.bidi.LEFT = 'left'),\n        (goog.i18n.bidi.I18N_RIGHT = goog.i18n.bidi.IS_RTL\n            ? goog.i18n.bidi.LEFT\n            : goog.i18n.bidi.RIGHT),\n        (goog.i18n.bidi.I18N_LEFT = goog.i18n.bidi.IS_RTL\n            ? goog.i18n.bidi.RIGHT\n            : goog.i18n.bidi.LEFT),\n        (goog.i18n.bidi.toDir = function(e, t) {\n            return 'number' == typeof e\n                ? 0 < e\n                    ? goog.i18n.bidi.Dir.LTR\n                    : 0 > e\n                    ? goog.i18n.bidi.Dir.RTL\n                    : t\n                    ? null\n                    : goog.i18n.bidi.Dir.NEUTRAL\n                : null == e\n                ? null\n                : e\n                ? goog.i18n.bidi.Dir.RTL\n                : goog.i18n.bidi.Dir.LTR;\n        }),\n        (goog.i18n.bidi.ltrChars_ =\n            'A-Za-zÀ-ÖØ-öø-ʸ̀-֐ऀ-῿‎Ⰰ-\\ud801\\ud804-\\ud839\\ud83c-\\udbff豈-﬜︀-﹯﻽-￿'),\n        (goog.i18n.bidi.rtlChars_ = '֑-ۯۺ-ࣿ‏\\ud802-\\ud803\\ud83a-\\ud83bיִ-﷿ﹰ-ﻼ'),\n        (goog.i18n.bidi.htmlSkipReg_ = /<[^>]*>|&[^;]+;/g),\n        (goog.i18n.bidi.stripHtmlIfNeeded_ = function(e, t) {\n            return t ? e.replace(goog.i18n.bidi.htmlSkipReg_, '') : e;\n        }),\n        (goog.i18n.bidi.rtlCharReg_ = new RegExp('[' + goog.i18n.bidi.rtlChars_ + ']')),\n        (goog.i18n.bidi.ltrCharReg_ = new RegExp('[' + goog.i18n.bidi.ltrChars_ + ']')),\n        (goog.i18n.bidi.hasAnyRtl = function(e, t) {\n            return goog.i18n.bidi.rtlCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(e, t));\n        }),\n        (goog.i18n.bidi.hasRtlChar = goog.i18n.bidi.hasAnyRtl),\n        (goog.i18n.bidi.hasAnyLtr = function(e, t) {\n            return goog.i18n.bidi.ltrCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(e, t));\n        }),\n        (goog.i18n.bidi.ltrRe_ = new RegExp('^[' + goog.i18n.bidi.ltrChars_ + ']')),\n        (goog.i18n.bidi.rtlRe_ = new RegExp('^[' + goog.i18n.bidi.rtlChars_ + ']')),\n        (goog.i18n.bidi.isRtlChar = function(e) {\n            return goog.i18n.bidi.rtlRe_.test(e);\n        }),\n        (goog.i18n.bidi.isLtrChar = function(e) {\n            return goog.i18n.bidi.ltrRe_.test(e);\n        }),\n        (goog.i18n.bidi.isNeutralChar = function(e) {\n            return !goog.i18n.bidi.isLtrChar(e) && !goog.i18n.bidi.isRtlChar(e);\n        }),\n        (goog.i18n.bidi.ltrDirCheckRe_ = new RegExp(\n            '^[^' + goog.i18n.bidi.rtlChars_ + ']*[' + goog.i18n.bidi.ltrChars_ + ']'\n        )),\n        (goog.i18n.bidi.rtlDirCheckRe_ = new RegExp(\n            '^[^' + goog.i18n.bidi.ltrChars_ + ']*[' + goog.i18n.bidi.rtlChars_ + ']'\n        )),\n        (goog.i18n.bidi.startsWithRtl = function(e, t) {\n            return goog.i18n.bidi.rtlDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(e, t));\n        }),\n        (goog.i18n.bidi.isRtlText = goog.i18n.bidi.startsWithRtl),\n        (goog.i18n.bidi.startsWithLtr = function(e, t) {\n            return goog.i18n.bidi.ltrDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(e, t));\n        }),\n        (goog.i18n.bidi.isLtrText = goog.i18n.bidi.startsWithLtr),\n        (goog.i18n.bidi.isRequiredLtrRe_ = /^http:\\/\\/.*/),\n        (goog.i18n.bidi.isNeutralText = function(e, t) {\n            return (\n                (e = goog.i18n.bidi.stripHtmlIfNeeded_(e, t)),\n                goog.i18n.bidi.isRequiredLtrRe_.test(e) ||\n                    (!goog.i18n.bidi.hasAnyLtr(e) && !goog.i18n.bidi.hasAnyRtl(e))\n            );\n        }),\n        (goog.i18n.bidi.ltrExitDirCheckRe_ = new RegExp(\n            '[' + goog.i18n.bidi.ltrChars_ + '][^' + goog.i18n.bidi.rtlChars_ + ']*$'\n        )),\n        (goog.i18n.bidi.rtlExitDirCheckRe_ = new RegExp(\n            '[' + goog.i18n.bidi.rtlChars_ + '][^' + goog.i18n.bidi.ltrChars_ + ']*$'\n        )),\n        (goog.i18n.bidi.endsWithLtr = function(e, t) {\n            return goog.i18n.bidi.ltrExitDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(e, t));\n        }),\n        (goog.i18n.bidi.isLtrExitText = goog.i18n.bidi.endsWithLtr),\n        (goog.i18n.bidi.endsWithRtl = function(e, t) {\n            return goog.i18n.bidi.rtlExitDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(e, t));\n        }),\n        (goog.i18n.bidi.isRtlExitText = goog.i18n.bidi.endsWithRtl),\n        (goog.i18n.bidi.rtlLocalesRe_ = /^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|.*[-_](Adlm|Arab|Hebr|Nkoo|Rohg|Thaa))(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)/i),\n        (goog.i18n.bidi.isRtlLanguage = function(e) {\n            return goog.i18n.bidi.rtlLocalesRe_.test(e);\n        }),\n        (goog.i18n.bidi.bracketGuardTextRe_ = /(\\(.*?\\)+)|(\\[.*?\\]+)|(\\{.*?\\}+)|(<.*?>+)/g),\n        (goog.i18n.bidi.guardBracketInText = function(e, t) {\n            return (\n                (t = (void 0 === t\n                  ? goog.i18n.bidi.hasAnyRtl(e)\n                  : t)\n                    ? goog.i18n.bidi.Format.RLM\n                    : goog.i18n.bidi.Format.LRM),\n                e.replace(goog.i18n.bidi.bracketGuardTextRe_, t + '$&' + t)\n            );\n        }),\n        (goog.i18n.bidi.enforceRtlInHtml = function(e) {\n            return '<' == e.charAt(0)\n                ? e.replace(/<\\w+/, '$& dir=rtl')\n                : '\\n<span dir=rtl>' + e + '</span>';\n        }),\n        (goog.i18n.bidi.enforceRtlInText = function(e) {\n            return goog.i18n.bidi.Format.RLE + e + goog.i18n.bidi.Format.PDF;\n        }),\n        (goog.i18n.bidi.enforceLtrInHtml = function(e) {\n            return '<' == e.charAt(0)\n                ? e.replace(/<\\w+/, '$& dir=ltr')\n                : '\\n<span dir=ltr>' + e + '</span>';\n        }),\n        (goog.i18n.bidi.enforceLtrInText = function(e) {\n            return goog.i18n.bidi.Format.LRE + e + goog.i18n.bidi.Format.PDF;\n        }),\n        (goog.i18n.bidi.dimensionsRe_ = /:\\s*([.\\d][.\\w]*)\\s+([.\\d][.\\w]*)\\s+([.\\d][.\\w]*)\\s+([.\\d][.\\w]*)/g),\n        (goog.i18n.bidi.leftRe_ = /left/gi),\n        (goog.i18n.bidi.rightRe_ = /right/gi),\n        (goog.i18n.bidi.tempRe_ = /%%%%/g),\n        (goog.i18n.bidi.mirrorCSS = function(e) {\n            return e\n                .replace(goog.i18n.bidi.dimensionsRe_, ':$1 $4 $3 $2')\n                .replace(goog.i18n.bidi.leftRe_, '%%%%')\n                .replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT)\n                .replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT);\n        }),\n        (goog.i18n.bidi.doubleQuoteSubstituteRe_ = /([\\u0591-\\u05f2])\"/g),\n        (goog.i18n.bidi.singleQuoteSubstituteRe_ = /([\\u0591-\\u05f2])'/g),\n        (goog.i18n.bidi.normalizeHebrewQuote = function(e) {\n            return e\n                .replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, '$1״')\n                .replace(goog.i18n.bidi.singleQuoteSubstituteRe_, '$1׳');\n        }),\n        (goog.i18n.bidi.wordSeparatorRe_ = /\\s+/),\n        (goog.i18n.bidi.hasNumeralsRe_ = /[\\d\\u06f0-\\u06f9]/),\n        (goog.i18n.bidi.rtlDetectionThreshold_ = 0.4),\n        (goog.i18n.bidi.estimateDirection = function(e, t) {\n            var r = 0,\n                o = 0,\n                i = !1;\n            for (\n                e = goog.i18n.bidi.stripHtmlIfNeeded_(e, t).split(goog.i18n.bidi.wordSeparatorRe_),\n                    t = 0;\n                t < e.length;\n                t++\n            ) {\n                var a = e[t];\n                goog.i18n.bidi.startsWithRtl(a)\n                    ? (r++, o++)\n                    : goog.i18n.bidi.isRequiredLtrRe_.test(a)\n                    ? (i = !0)\n                    : goog.i18n.bidi.hasAnyLtr(a)\n                    ? o++\n                    : goog.i18n.bidi.hasNumeralsRe_.test(a) && (i = !0);\n            }\n            return 0 == o\n                ? i\n                    ? goog.i18n.bidi.Dir.LTR\n                    : goog.i18n.bidi.Dir.NEUTRAL\n                : r / o > goog.i18n.bidi.rtlDetectionThreshold_\n                ? goog.i18n.bidi.Dir.RTL\n                : goog.i18n.bidi.Dir.LTR;\n        }),\n        (goog.i18n.bidi.detectRtlDirectionality = function(e, t) {\n            return goog.i18n.bidi.estimateDirection(e, t) == goog.i18n.bidi.Dir.RTL;\n        }),\n        (goog.i18n.bidi.setElementDirAndAlign = function(e, t) {\n            e &&\n                (t = goog.i18n.bidi.toDir(t)) &&\n                ((e.style.textAlign =\n                    t == goog.i18n.bidi.Dir.RTL ? goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT),\n                (e.dir = t == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr'));\n        }),\n        (goog.i18n.bidi.setElementDirByTextDirectionality = function(e, t) {\n            switch (goog.i18n.bidi.estimateDirection(t)) {\n                case goog.i18n.bidi.Dir.LTR:\n                    e.dir = 'ltr';\n                    break;\n                case goog.i18n.bidi.Dir.RTL:\n                    e.dir = 'rtl';\n                    break;\n                default:\n                    e.removeAttribute('dir');\n            }\n        }),\n        (goog.i18n.bidi.DirectionalString = function() {}),\n        (goog.html.TrustedResourceUrl = function(e, t) {\n            (this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ =\n                (e === goog.html.TrustedResourceUrl.CONSTRUCTOR_TOKEN_PRIVATE_ && t) || ''),\n                (this.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =\n                    goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_);\n        }),\n        (goog.html.TrustedResourceUrl.prototype.implementsGoogStringTypedString = !0),\n        (goog.html.TrustedResourceUrl.prototype.getTypedStringValue = function() {\n            return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_.toString();\n        }),\n        (goog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString = !0),\n        (goog.html.TrustedResourceUrl.prototype.getDirection = function() {\n            return goog.i18n.bidi.Dir.LTR;\n        }),\n        (goog.html.TrustedResourceUrl.prototype.cloneWithParams = function(e, t) {\n            var r = goog.html.TrustedResourceUrl.unwrap(this),\n                o = (r = goog.html.TrustedResourceUrl.URL_PARAM_PARSER_.exec(r))[3] || '';\n            return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(\n                r[1] +\n                    goog.html.TrustedResourceUrl.stringifyParams_('?', r[2] || '', e) +\n                    goog.html.TrustedResourceUrl.stringifyParams_('#', o, t)\n            );\n        }),\n        goog.DEBUG &&\n            (goog.html.TrustedResourceUrl.prototype.toString = function() {\n                return (\n                    'TrustedResourceUrl{' +\n                    this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ +\n                    '}'\n                );\n            }),\n        (goog.html.TrustedResourceUrl.unwrap = function(e) {\n            return goog.html.TrustedResourceUrl.unwrapTrustedScriptURL(e).toString();\n        }),\n        (goog.html.TrustedResourceUrl.unwrapTrustedScriptURL = function(e) {\n            return e instanceof goog.html.TrustedResourceUrl &&\n                e.constructor === goog.html.TrustedResourceUrl &&\n                e.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===\n                    goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_\n                ? e.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_\n                : (goog.asserts.fail(\n                      \"expected object of type TrustedResourceUrl, got '\" +\n                          e +\n                          \"' of type \" +\n                          goog.typeOf(e)\n                  ),\n                  'type_error:TrustedResourceUrl');\n        }),\n        (goog.html.TrustedResourceUrl.format = function(e, t) {\n            var r = goog.string.Const.unwrap(e);\n            if (!goog.html.TrustedResourceUrl.BASE_URL_.test(r))\n                throw Error('Invalid TrustedResourceUrl format: ' + r);\n            return (\n                (e = r.replace(goog.html.TrustedResourceUrl.FORMAT_MARKER_, function(e, o) {\n                    if (!Object.prototype.hasOwnProperty.call(t, o))\n                        throw Error(\n                            'Found marker, \"' +\n                                o +\n                                '\", in format string, \"' +\n                                r +\n                                '\", but no valid label mapping found in args: ' +\n                                JSON.stringify(t)\n                        );\n                    return (e = t[o]) instanceof goog.string.Const\n                        ? goog.string.Const.unwrap(e)\n                        : encodeURIComponent(String(e));\n                })),\n                goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(\n                    e\n                )\n            );\n        }),\n        (goog.html.TrustedResourceUrl.FORMAT_MARKER_ = /%{(\\w+)}/g),\n        (goog.html.TrustedResourceUrl.BASE_URL_ = /^((https:)?\\/\\/[0-9a-z.:[\\]-]+\\/|\\/[^/\\\\]|[^:/\\\\%]+\\/|[^:/\\\\%]*[?#]|about:blank#)/i),\n        (goog.html.TrustedResourceUrl.URL_PARAM_PARSER_ = /^([^?#]*)(\\?[^#]*)?(#[\\s\\S]*)?/),\n        (goog.html.TrustedResourceUrl.formatWithParams = function(e, t, r, o) {\n            return goog.html.TrustedResourceUrl.format(e, t).cloneWithParams(r, o);\n        }),\n        (goog.html.TrustedResourceUrl.fromConstant = function(e) {\n            return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(\n                goog.string.Const.unwrap(e)\n            );\n        }),\n        (goog.html.TrustedResourceUrl.fromConstants = function(e) {\n            for (var t = '', r = 0; r < e.length; r++) t += goog.string.Const.unwrap(e[r]);\n            return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(\n                t\n            );\n        }),\n        (goog.html.TrustedResourceUrl.fromSafeScript = function(e) {\n            return (\n                (e = goog.fs.blob.getBlobWithProperties(\n                    [goog.html.SafeScript.unwrap(e)],\n                    'text/javascript'\n                )),\n                (e = goog.fs.url.createObjectUrl(e)),\n                goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(\n                    e\n                )\n            );\n        }),\n        (goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}),\n        (goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(\n            e\n        ) {\n            return (\n                (e = goog.html.trustedtypes.PRIVATE_DO_NOT_ACCESS_OR_ELSE_POLICY\n                    ? goog.html.trustedtypes.PRIVATE_DO_NOT_ACCESS_OR_ELSE_POLICY.createScriptURL(e)\n                    : e),\n                new goog.html.TrustedResourceUrl(\n                    goog.html.TrustedResourceUrl.CONSTRUCTOR_TOKEN_PRIVATE_,\n                    e\n                )\n            );\n        }),\n        (goog.html.TrustedResourceUrl.stringifyParams_ = function(e, t, r) {\n            if (null == r) return t;\n            if ('string' == typeof r) return r ? e + encodeURIComponent(r) : '';\n            for (var o in r) {\n                var i = r[o];\n                i = Array.isArray(i) ? i : [i];\n                for (var a = 0; a < i.length; a++) {\n                    var n = i[a];\n                    null != n &&\n                        (t || (t = e),\n                        (t +=\n                            (t.length > e.length ? '&' : '') +\n                            encodeURIComponent(o) +\n                            '=' +\n                            encodeURIComponent(String(n))));\n                }\n            }\n            return t;\n        }),\n        (goog.html.TrustedResourceUrl.CONSTRUCTOR_TOKEN_PRIVATE_ = {}),\n        (goog.string.internal = {}),\n        (goog.string.internal.startsWith = function(e, t) {\n            return 0 == e.lastIndexOf(t, 0);\n        }),\n        (goog.string.internal.endsWith = function(e, t) {\n            var r = e.length - t.length;\n            return 0 <= r && e.indexOf(t, r) == r;\n        }),\n        (goog.string.internal.caseInsensitiveStartsWith = function(e, t) {\n            return 0 == goog.string.internal.caseInsensitiveCompare(t, e.substr(0, t.length));\n        }),\n        (goog.string.internal.caseInsensitiveEndsWith = function(e, t) {\n            return (\n                0 ==\n                goog.string.internal.caseInsensitiveCompare(\n                    t,\n                    e.substr(e.length - t.length, t.length)\n                )\n            );\n        }),\n        (goog.string.internal.caseInsensitiveEquals = function(e, t) {\n            return e.toLowerCase() == t.toLowerCase();\n        }),\n        (goog.string.internal.isEmptyOrWhitespace = function(e) {\n            return /^[\\s\\xa0]*$/.test(e);\n        }),\n        (goog.string.internal.trim =\n            goog.TRUSTED_SITE && String.prototype.trim\n                ? function(e) {\n                      return e.trim();\n                  }\n                : function(e) {\n                      return /^[\\s\\xa0]*([\\s\\S]*?)[\\s\\xa0]*$/.exec(e)[1];\n                  }),\n        (goog.string.internal.caseInsensitiveCompare = function(e, t) {\n            return (e = String(e).toLowerCase()) < (t = String(t).toLowerCase())\n                ? -1\n                : e == t\n                ? 0\n                : 1;\n        }),\n        (goog.string.internal.newLineToBr = function(e, t) {\n            return e.replace(/(\\r\\n|\\r|\\n)/g, t ? '<br />' : '<br>');\n        }),\n        (goog.string.internal.htmlEscape = function(e, t) {\n            if (t)\n                e = e\n                    .replace(goog.string.internal.AMP_RE_, '&amp;')\n                    .replace(goog.string.internal.LT_RE_, '&lt;')\n                    .replace(goog.string.internal.GT_RE_, '&gt;')\n                    .replace(goog.string.internal.QUOT_RE_, '&quot;')\n                    .replace(goog.string.internal.SINGLE_QUOTE_RE_, '&#39;')\n                    .replace(goog.string.internal.NULL_RE_, '&#0;');\n            else {\n                if (!goog.string.internal.ALL_RE_.test(e)) return e;\n                -1 != e.indexOf('&') && (e = e.replace(goog.string.internal.AMP_RE_, '&amp;')),\n                    -1 != e.indexOf('<') && (e = e.replace(goog.string.internal.LT_RE_, '&lt;')),\n                    -1 != e.indexOf('>') && (e = e.replace(goog.string.internal.GT_RE_, '&gt;')),\n                    -1 != e.indexOf('\"') &&\n                        (e = e.replace(goog.string.internal.QUOT_RE_, '&quot;')),\n                    -1 != e.indexOf(\"'\") &&\n                        (e = e.replace(goog.string.internal.SINGLE_QUOTE_RE_, '&#39;')),\n                    -1 != e.indexOf('\\0') && (e = e.replace(goog.string.internal.NULL_RE_, '&#0;'));\n            }\n            return e;\n        }),\n        (goog.string.internal.AMP_RE_ = /&/g),\n        (goog.string.internal.LT_RE_ = /</g),\n        (goog.string.internal.GT_RE_ = />/g),\n        (goog.string.internal.QUOT_RE_ = /\"/g),\n        (goog.string.internal.SINGLE_QUOTE_RE_ = /'/g),\n        (goog.string.internal.NULL_RE_ = /\\x00/g),\n        (goog.string.internal.ALL_RE_ = /[\\x00&<>\"']/),\n        (goog.string.internal.whitespaceEscape = function(e, t) {\n            return goog.string.internal.newLineToBr(e.replace(/  /g, ' &#160;'), t);\n        }),\n        (goog.string.internal.contains = function(e, t) {\n            return -1 != e.indexOf(t);\n        }),\n        (goog.string.internal.caseInsensitiveContains = function(e, t) {\n            return goog.string.internal.contains(e.toLowerCase(), t.toLowerCase());\n        }),\n        (goog.string.internal.compareVersions = function(e, t) {\n            var r = 0;\n            (e = goog.string.internal.trim(String(e)).split('.')),\n                (t = goog.string.internal.trim(String(t)).split('.'));\n            for (var o = Math.max(e.length, t.length), i = 0; 0 == r && i < o; i++) {\n                var a = e[i] || '',\n                    n = t[i] || '';\n                do {\n                    if (\n                        ((a = /(\\d*)(\\D*)(.*)/.exec(a) || ['', '', '', '']),\n                        (n = /(\\d*)(\\D*)(.*)/.exec(n) || ['', '', '', '']),\n                        0 == a[0].length && 0 == n[0].length)\n                    )\n                        break;\n                    r = 0 == a[1].length ? 0 : parseInt(a[1], 10);\n                    var s = 0 == n[1].length ? 0 : parseInt(n[1], 10);\n                    (r =\n                        goog.string.internal.compareElements_(r, s) ||\n                        goog.string.internal.compareElements_(0 == a[2].length, 0 == n[2].length) ||\n                        goog.string.internal.compareElements_(a[2], n[2])),\n                        (a = a[3]),\n                        (n = n[3]);\n                } while (0 == r);\n            }\n            return r;\n        }),\n        (goog.string.internal.compareElements_ = function(e, t) {\n            return e < t ? -1 : e > t ? 1 : 0;\n        }),\n        (goog.html.SafeUrl = function(e, t) {\n            (this.privateDoNotAccessOrElseSafeUrlWrappedValue_ =\n                (e === goog.html.SafeUrl.CONSTRUCTOR_TOKEN_PRIVATE_ && t) || ''),\n                (this.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =\n                    goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_);\n        }),\n        (goog.html.SafeUrl.INNOCUOUS_STRING = 'about:invalid#zClosurez'),\n        (goog.html.SafeUrl.prototype.implementsGoogStringTypedString = !0),\n        (goog.html.SafeUrl.prototype.getTypedStringValue = function() {\n            return this.privateDoNotAccessOrElseSafeUrlWrappedValue_.toString();\n        }),\n        (goog.html.SafeUrl.prototype.implementsGoogI18nBidiDirectionalString = !0),\n        (goog.html.SafeUrl.prototype.getDirection = function() {\n            return goog.i18n.bidi.Dir.LTR;\n        }),\n        goog.DEBUG &&\n            (goog.html.SafeUrl.prototype.toString = function() {\n                return 'SafeUrl{' + this.privateDoNotAccessOrElseSafeUrlWrappedValue_ + '}';\n            }),\n        (goog.html.SafeUrl.unwrap = function(e) {\n            return e instanceof goog.html.SafeUrl &&\n                e.constructor === goog.html.SafeUrl &&\n                e.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===\n                    goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_\n                ? e.privateDoNotAccessOrElseSafeUrlWrappedValue_\n                : (goog.asserts.fail(\n                      \"expected object of type SafeUrl, got '\" + e + \"' of type \" + goog.typeOf(e)\n                  ),\n                  'type_error:SafeUrl');\n        }),\n        (goog.html.SafeUrl.fromConstant = function(e) {\n            return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(\n                goog.string.Const.unwrap(e)\n            );\n        }),\n        (goog.html.SAFE_MIME_TYPE_PATTERN_ = /^(?:audio\\/(?:3gpp2|3gpp|aac|L16|midi|mp3|mp4|mpeg|oga|ogg|opus|x-m4a|x-matroska|x-wav|wav|webm)|image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp|x-icon)|text\\/csv|video\\/(?:mpeg|mp4|ogg|webm|quicktime|x-matroska))(?:;\\w+=(?:\\w+|\"[\\w;,= ]+\"))*$/i),\n        (goog.html.SafeUrl.isSafeMimeType = function(e) {\n            return goog.html.SAFE_MIME_TYPE_PATTERN_.test(e);\n        }),\n        (goog.html.SafeUrl.fromBlob = function(e) {\n            return (\n                (e = goog.html.SafeUrl.isSafeMimeType(e.type)\n                    ? goog.fs.url.createObjectUrl(e)\n                    : goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.SafeUrl.fromMediaSource = function(e) {\n            return (\n                goog.asserts.assert('MediaSource' in goog.global, 'No support for MediaSource'),\n                (e =\n                    e instanceof MediaSource\n                        ? goog.fs.url.createObjectUrl(e)\n                        : goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.DATA_URL_PATTERN_ = /^data:(.*);base64,[a-z0-9+\\/]+=*$/i),\n        (goog.html.SafeUrl.fromDataUrl = function(e) {\n            var t = (e = e.replace(/(%0A|%0D)/g, '')).match(goog.html.DATA_URL_PATTERN_);\n            return (\n                (t = t && goog.html.SafeUrl.isSafeMimeType(t[1])),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(\n                    t ? e : goog.html.SafeUrl.INNOCUOUS_STRING\n                )\n            );\n        }),\n        (goog.html.SafeUrl.fromTelUrl = function(e) {\n            return (\n                goog.string.internal.caseInsensitiveStartsWith(e, 'tel:') ||\n                    (e = goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.SIP_URL_PATTERN_ = /^sip[s]?:[+a-z0-9_.!$%&'*\\/=^`{|}~-]+@([a-z0-9-]+\\.)+[a-z0-9]{2,63}$/i),\n        (goog.html.SafeUrl.fromSipUrl = function(e) {\n            return (\n                goog.html.SIP_URL_PATTERN_.test(decodeURIComponent(e)) ||\n                    (e = goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.SafeUrl.fromFacebookMessengerUrl = function(e) {\n            return (\n                goog.string.internal.caseInsensitiveStartsWith(e, 'fb-messenger://share') ||\n                    (e = goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.SafeUrl.fromWhatsAppUrl = function(e) {\n            return (\n                goog.string.internal.caseInsensitiveStartsWith(e, 'whatsapp://send') ||\n                    (e = goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.SafeUrl.fromSmsUrl = function(e) {\n            return (\n                (goog.string.internal.caseInsensitiveStartsWith(e, 'sms:') &&\n                    goog.html.SafeUrl.isSmsUrlBodyValid_(e)) ||\n                    (e = goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.SafeUrl.isSmsUrlBodyValid_ = function(e) {\n            var t = e.indexOf('#');\n            if ((0 < t && (e = e.substring(0, t)), !(t = e.match(/[?&]body=/gi)))) return !0;\n            if (1 < t.length) return !1;\n            if (!(e = e.match(/[?&]body=([^&]*)/)[1])) return !0;\n            try {\n                decodeURIComponent(e);\n            } catch (e) {\n                return !1;\n            }\n            return /^(?:[a-z0-9\\-_.~]|%[0-9a-f]{2})+$/i.test(e);\n        }),\n        (goog.html.SafeUrl.fromSshUrl = function(e) {\n            return (\n                goog.string.internal.caseInsensitiveStartsWith(e, 'ssh://') ||\n                    (e = goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.SafeUrl.sanitizeChromeExtensionUrl = function(e, t) {\n            return goog.html.SafeUrl.sanitizeExtensionUrl_(\n                /^chrome-extension:\\/\\/([^\\/]+)\\//,\n                e,\n                t\n            );\n        }),\n        (goog.html.SafeUrl.sanitizeFirefoxExtensionUrl = function(e, t) {\n            return goog.html.SafeUrl.sanitizeExtensionUrl_(/^moz-extension:\\/\\/([^\\/]+)\\//, e, t);\n        }),\n        (goog.html.SafeUrl.sanitizeEdgeExtensionUrl = function(e, t) {\n            return goog.html.SafeUrl.sanitizeExtensionUrl_(\n                /^ms-browser-extension:\\/\\/([^\\/]+)\\//,\n                e,\n                t\n            );\n        }),\n        (goog.html.SafeUrl.sanitizeExtensionUrl_ = function(e, t, r) {\n            return (\n                (e = e.exec(t))\n                    ? ((e = e[1]),\n                      -1 ==\n                          (r instanceof goog.string.Const\n                              ? [goog.string.Const.unwrap(r)]\n                              : r.map(function(e) {\n                                    return goog.string.Const.unwrap(e);\n                                })\n                          ).indexOf(e) && (t = goog.html.SafeUrl.INNOCUOUS_STRING))\n                    : (t = goog.html.SafeUrl.INNOCUOUS_STRING),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(t)\n            );\n        }),\n        (goog.html.SafeUrl.fromTrustedResourceUrl = function(e) {\n            return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(\n                goog.html.TrustedResourceUrl.unwrap(e)\n            );\n        }),\n        (goog.html.SAFE_URL_PATTERN_ = /^(?:(?:https?|mailto|ftp):|[^:/?#]*(?:[/?#]|$))/i),\n        (goog.html.SafeUrl.SAFE_URL_PATTERN = goog.html.SAFE_URL_PATTERN_),\n        (goog.html.SafeUrl.sanitize = function(e) {\n            return e instanceof goog.html.SafeUrl\n                ? e\n                : ((e =\n                      'object' == typeof e && e.implementsGoogStringTypedString\n                          ? e.getTypedStringValue()\n                          : String(e)),\n                  goog.html.SAFE_URL_PATTERN_.test(e) || (e = goog.html.SafeUrl.INNOCUOUS_STRING),\n                  goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e));\n        }),\n        (goog.html.SafeUrl.sanitizeAssertUnchanged = function(e, t) {\n            return e instanceof goog.html.SafeUrl\n                ? e\n                : ((e =\n                      'object' == typeof e && e.implementsGoogStringTypedString\n                          ? e.getTypedStringValue()\n                          : String(e)),\n                  t &&\n                  /^data:/i.test(e) &&\n                  (t = goog.html.SafeUrl.fromDataUrl(e)).getTypedStringValue() == e\n                      ? t\n                      : (goog.asserts.assert(\n                            goog.html.SAFE_URL_PATTERN_.test(e),\n                            '%s does not match the safe URL pattern',\n                            e\n                        ) || (e = goog.html.SafeUrl.INNOCUOUS_STRING),\n                        goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(e)));\n        }),\n        (goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}),\n        (goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse = function(e) {\n            return new goog.html.SafeUrl(goog.html.SafeUrl.CONSTRUCTOR_TOKEN_PRIVATE_, e);\n        }),\n        (goog.html.SafeUrl.ABOUT_BLANK = goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(\n            'about:blank'\n        )),\n        (goog.html.SafeUrl.CONSTRUCTOR_TOKEN_PRIVATE_ = {}),\n        (goog.html.SafeStyle = function() {\n            (this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = ''),\n                (this.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =\n                    goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_);\n        }),\n        (goog.html.SafeStyle.prototype.implementsGoogStringTypedString = !0),\n        (goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}),\n        (goog.html.SafeStyle.fromConstant = function(e) {\n            return 0 === (e = goog.string.Const.unwrap(e)).length\n                ? goog.html.SafeStyle.EMPTY\n                : (goog.asserts.assert(\n                      goog.string.internal.endsWith(e, ';'),\n                      \"Last character of style string is not ';': \" + e\n                  ),\n                  goog.asserts.assert(\n                      goog.string.internal.contains(e, ':'),\n                      'Style string must contain at least one \\':\\', to specify a \"name: value\" pair: ' +\n                          e\n                  ),\n                  goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(e));\n        }),\n        (goog.html.SafeStyle.prototype.getTypedStringValue = function() {\n            return this.privateDoNotAccessOrElseSafeStyleWrappedValue_;\n        }),\n        goog.DEBUG &&\n            (goog.html.SafeStyle.prototype.toString = function() {\n                return 'SafeStyle{' + this.privateDoNotAccessOrElseSafeStyleWrappedValue_ + '}';\n            }),\n        (goog.html.SafeStyle.unwrap = function(e) {\n            return e instanceof goog.html.SafeStyle &&\n                e.constructor === goog.html.SafeStyle &&\n                e.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===\n                    goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_\n                ? e.privateDoNotAccessOrElseSafeStyleWrappedValue_\n                : (goog.asserts.fail(\n                      \"expected object of type SafeStyle, got '\" + e + \"' of type \" + goog.typeOf(e)\n                  ),\n                  'type_error:SafeStyle');\n        }),\n        (goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse = function(e) {\n            return new goog.html.SafeStyle().initSecurityPrivateDoNotAccessOrElse_(e);\n        }),\n        (goog.html.SafeStyle.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(e) {\n            return (this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = e), this;\n        }),\n        (goog.html.SafeStyle.EMPTY = goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(\n            ''\n        )),\n        (goog.html.SafeStyle.INNOCUOUS_STRING = 'zClosurez'),\n        (goog.html.SafeStyle.create = function(e) {\n            var t,\n                r = '';\n            for (t in e) {\n                if (!/^[-_a-zA-Z0-9]+$/.test(t))\n                    throw Error('Name allows only [-_a-zA-Z0-9], got: ' + t);\n                var o = e[t];\n                null != o &&\n                    (r +=\n                        t +\n                        ':' +\n                        (o = Array.isArray(o)\n                            ? goog.array\n                                  .map(o, goog.html.SafeStyle.sanitizePropertyValue_)\n                                  .join(' ')\n                            : goog.html.SafeStyle.sanitizePropertyValue_(o)) +\n                        ';');\n            }\n            return r\n                ? goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(r)\n                : goog.html.SafeStyle.EMPTY;\n        }),\n        (goog.html.SafeStyle.sanitizePropertyValue_ = function(e) {\n            if (e instanceof goog.html.SafeUrl)\n                return (\n                    'url(\"' +\n                    goog.html.SafeUrl.unwrap(e)\n                        .replace(/</g, '%3c')\n                        .replace(/[\\\\\"]/g, '\\\\$&') +\n                    '\")'\n                );\n            if (\n                ((e =\n                    e instanceof goog.string.Const\n                        ? goog.string.Const.unwrap(e)\n                        : goog.html.SafeStyle.sanitizePropertyValueString_(String(e))),\n                /[{;}]/.test(e))\n            )\n                throw new goog.asserts.AssertionError('Value does not allow [{;}], got: %s.', [e]);\n            return e;\n        }),\n        (goog.html.SafeStyle.sanitizePropertyValueString_ = function(e) {\n            var t = e\n                .replace(goog.html.SafeStyle.FUNCTIONS_RE_, '$1')\n                .replace(goog.html.SafeStyle.FUNCTIONS_RE_, '$1')\n                .replace(goog.html.SafeStyle.URL_RE_, 'url');\n            return goog.html.SafeStyle.VALUE_RE_.test(t)\n                ? goog.html.SafeStyle.COMMENT_RE_.test(e)\n                    ? (goog.asserts.fail('String value disallows comments, got: ' + e),\n                      goog.html.SafeStyle.INNOCUOUS_STRING)\n                    : goog.html.SafeStyle.hasBalancedQuotes_(e)\n                    ? goog.html.SafeStyle.hasBalancedSquareBrackets_(e)\n                        ? goog.html.SafeStyle.sanitizeUrl_(e)\n                        : (goog.asserts.fail(\n                              'String value requires balanced square brackets and one identifier per pair of brackets, got: ' +\n                                  e\n                          ),\n                          goog.html.SafeStyle.INNOCUOUS_STRING)\n                    : (goog.asserts.fail('String value requires balanced quotes, got: ' + e),\n                      goog.html.SafeStyle.INNOCUOUS_STRING)\n                : (goog.asserts.fail(\n                      'String value allows only ' +\n                          goog.html.SafeStyle.VALUE_ALLOWED_CHARS_ +\n                          ' and simple functions, got: ' +\n                          e\n                  ),\n                  goog.html.SafeStyle.INNOCUOUS_STRING);\n        }),\n        (goog.html.SafeStyle.hasBalancedQuotes_ = function(e) {\n            for (var t = !0, r = !0, o = 0; o < e.length; o++) {\n                var i = e.charAt(o);\n                \"'\" == i && r ? (t = !t) : '\"' == i && t && (r = !r);\n            }\n            return t && r;\n        }),\n        (goog.html.SafeStyle.hasBalancedSquareBrackets_ = function(e) {\n            for (var t = !0, r = /^[-_a-zA-Z0-9]$/, o = 0; o < e.length; o++) {\n                var i = e.charAt(o);\n                if (']' == i) {\n                    if (t) return !1;\n                    t = !0;\n                } else if ('[' == i) {\n                    if (!t) return !1;\n                    t = !1;\n                } else if (!t && !r.test(i)) return !1;\n            }\n            return t;\n        }),\n        (goog.html.SafeStyle.VALUE_ALLOWED_CHARS_ = '[-,.\"\\'%_!# a-zA-Z0-9\\\\[\\\\]]'),\n        (goog.html.SafeStyle.VALUE_RE_ = new RegExp(\n            '^' + goog.html.SafeStyle.VALUE_ALLOWED_CHARS_ + '+$'\n        )),\n        (goog.html.SafeStyle.URL_RE_ = /\\b(url\\([ \\t\\n]*)('[ -&(-\\[\\]-~]*'|\"[ !#-\\[\\]-~]*\"|[!#-&*-\\[\\]-~]*)([ \\t\\n]*\\))/g),\n        (goog.html.SafeStyle.ALLOWED_FUNCTIONS_ = 'calc cubic-bezier fit-content hsl hsla linear-gradient matrix minmax repeat rgb rgba (rotate|scale|translate)(X|Y|Z|3d)?'.split(\n            ' '\n        )),\n        (goog.html.SafeStyle.FUNCTIONS_RE_ = new RegExp(\n            '\\\\b(' +\n                goog.html.SafeStyle.ALLOWED_FUNCTIONS_.join('|') +\n                ')\\\\([-+*/0-9a-z.%\\\\[\\\\], ]+\\\\)',\n            'g'\n        )),\n        (goog.html.SafeStyle.COMMENT_RE_ = /\\/\\*/),\n        (goog.html.SafeStyle.sanitizeUrl_ = function(e) {\n            return e.replace(goog.html.SafeStyle.URL_RE_, function(e, t, r, o) {\n                var i = '';\n                return (\n                    (r = r.replace(/^(['\"])(.*)\\1$/, function(e, t, r) {\n                        return (i = t), r;\n                    })),\n                    (e = goog.html.SafeUrl.sanitize(r).getTypedStringValue()),\n                    t + i + e + i + o\n                );\n            });\n        }),\n        (goog.html.SafeStyle.concat = function(e) {\n            var t = '',\n                r = function(e) {\n                    Array.isArray(e)\n                        ? goog.array.forEach(e, r)\n                        : (t += goog.html.SafeStyle.unwrap(e));\n                };\n            return (\n                goog.array.forEach(arguments, r),\n                t\n                    ? goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(t)\n                    : goog.html.SafeStyle.EMPTY\n            );\n        }),\n        (goog.html.SafeStyleSheet = function() {\n            (this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = ''),\n                (this.SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =\n                    goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_);\n        }),\n        (goog.html.SafeStyleSheet.prototype.implementsGoogStringTypedString = !0),\n        (goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}),\n        (goog.html.SafeStyleSheet.createRule = function(e, t) {\n            if (goog.string.internal.contains(e, '<'))\n                throw Error(\"Selector does not allow '<', got: \" + e);\n            var r = e.replace(/('|\")((?!\\1)[^\\r\\n\\f\\\\]|\\\\[\\s\\S])*\\1/g, '');\n            if (!/^[-_a-zA-Z0-9#.:* ,>+~[\\]()=^$|]+$/.test(r))\n                throw Error(\n                    'Selector allows only [-_a-zA-Z0-9#.:* ,>+~[\\\\]()=^$|] and strings, got: ' + e\n                );\n            if (!goog.html.SafeStyleSheet.hasBalancedBrackets_(r))\n                throw Error('() and [] in selector must be balanced, got: ' + e);\n            return (\n                t instanceof goog.html.SafeStyle || (t = goog.html.SafeStyle.create(t)),\n                (e = e + '{' + goog.html.SafeStyle.unwrap(t).replace(/</g, '\\\\3C ') + '}'),\n                goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(e)\n            );\n        }),\n        (goog.html.SafeStyleSheet.hasBalancedBrackets_ = function(e) {\n            for (var t = { '(': ')', '[': ']' }, r = [], o = 0; o < e.length; o++) {\n                var i = e[o];\n                if (t[i]) r.push(t[i]);\n                else if (goog.object.contains(t, i) && r.pop() != i) return !1;\n            }\n            return 0 == r.length;\n        }),\n        (goog.html.SafeStyleSheet.concat = function(e) {\n            var t = '',\n                r = function(e) {\n                    Array.isArray(e)\n                        ? goog.array.forEach(e, r)\n                        : (t += goog.html.SafeStyleSheet.unwrap(e));\n                };\n            return (\n                goog.array.forEach(arguments, r),\n                goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(t)\n            );\n        }),\n        (goog.html.SafeStyleSheet.fromConstant = function(e) {\n            return 0 === (e = goog.string.Const.unwrap(e)).length\n                ? goog.html.SafeStyleSheet.EMPTY\n                : (goog.asserts.assert(\n                      !goog.string.internal.contains(e, '<'),\n                      \"Forbidden '<' character in style sheet string: \" + e\n                  ),\n                  goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(e));\n        }),\n        (goog.html.SafeStyleSheet.prototype.getTypedStringValue = function() {\n            return this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_;\n        }),\n        goog.DEBUG &&\n            (goog.html.SafeStyleSheet.prototype.toString = function() {\n                return (\n                    'SafeStyleSheet{' +\n                    this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ +\n                    '}'\n                );\n            }),\n        (goog.html.SafeStyleSheet.unwrap = function(e) {\n            return e instanceof goog.html.SafeStyleSheet &&\n                e.constructor === goog.html.SafeStyleSheet &&\n                e.SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===\n                    goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_\n                ? e.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_\n                : (goog.asserts.fail(\n                      \"expected object of type SafeStyleSheet, got '\" +\n                          e +\n                          \"' of type \" +\n                          goog.typeOf(e)\n                  ),\n                  'type_error:SafeStyleSheet');\n        }),\n        (goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse = function(\n            e\n        ) {\n            return new goog.html.SafeStyleSheet().initSecurityPrivateDoNotAccessOrElse_(e);\n        }),\n        (goog.html.SafeStyleSheet.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(e) {\n            return (this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = e), this;\n        }),\n        (goog.html.SafeStyleSheet.EMPTY = goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(\n            ''\n        )),\n        (goog.labs = {}),\n        (goog.labs.userAgent = {}),\n        (goog.labs.userAgent.util = {}),\n        (goog.labs.userAgent.util.getNativeUserAgentString_ = function() {\n            var e = goog.labs.userAgent.util.getNavigator_();\n            return e && (e = e.userAgent) ? e : '';\n        }),\n        (goog.labs.userAgent.util.getNavigator_ = function() {\n            return goog.global.navigator;\n        }),\n        (goog.labs.userAgent.util.userAgent_ = goog.labs.userAgent.util.getNativeUserAgentString_()),\n        (goog.labs.userAgent.util.setUserAgent = function(e) {\n            goog.labs.userAgent.util.userAgent_ =\n                e || goog.labs.userAgent.util.getNativeUserAgentString_();\n        }),\n        (goog.labs.userAgent.util.getUserAgent = function() {\n            return goog.labs.userAgent.util.userAgent_;\n        }),\n        (goog.labs.userAgent.util.matchUserAgent = function(e) {\n            var t = goog.labs.userAgent.util.getUserAgent();\n            return goog.string.internal.contains(t, e);\n        }),\n        (goog.labs.userAgent.util.matchUserAgentIgnoreCase = function(e) {\n            var t = goog.labs.userAgent.util.getUserAgent();\n            return goog.string.internal.caseInsensitiveContains(t, e);\n        }),\n        (goog.labs.userAgent.util.extractVersionTuples = function(e) {\n            for (var t, r = /(\\w[\\w ]+)\\/([^\\s]+)\\s*(?:\\((.*?)\\))?/g, o = []; (t = r.exec(e)); )\n                o.push([t[1], t[2], t[3] || void 0]);\n            return o;\n        }),\n        (goog.labs.userAgent.browser = {}),\n        (goog.labs.userAgent.browser.matchOpera_ = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Opera');\n        }),\n        (goog.labs.userAgent.browser.matchIE_ = function() {\n            return (\n                goog.labs.userAgent.util.matchUserAgent('Trident') ||\n                goog.labs.userAgent.util.matchUserAgent('MSIE')\n            );\n        }),\n        (goog.labs.userAgent.browser.matchEdgeHtml_ = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Edge');\n        }),\n        (goog.labs.userAgent.browser.matchEdgeChromium_ = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Edg/');\n        }),\n        (goog.labs.userAgent.browser.matchOperaChromium_ = function() {\n            return goog.labs.userAgent.util.matchUserAgent('OPR');\n        }),\n        (goog.labs.userAgent.browser.matchFirefox_ = function() {\n            return (\n                goog.labs.userAgent.util.matchUserAgent('Firefox') ||\n                goog.labs.userAgent.util.matchUserAgent('FxiOS')\n            );\n        }),\n        (goog.labs.userAgent.browser.matchSafari_ = function() {\n            return (\n                goog.labs.userAgent.util.matchUserAgent('Safari') &&\n                !(\n                    goog.labs.userAgent.browser.matchChrome_() ||\n                    goog.labs.userAgent.browser.matchCoast_() ||\n                    goog.labs.userAgent.browser.matchOpera_() ||\n                    goog.labs.userAgent.browser.matchEdgeHtml_() ||\n                    goog.labs.userAgent.browser.matchEdgeChromium_() ||\n                    goog.labs.userAgent.browser.matchOperaChromium_() ||\n                    goog.labs.userAgent.browser.matchFirefox_() ||\n                    goog.labs.userAgent.browser.isSilk() ||\n                    goog.labs.userAgent.util.matchUserAgent('Android')\n                )\n            );\n        }),\n        (goog.labs.userAgent.browser.matchCoast_ = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Coast');\n        }),\n        (goog.labs.userAgent.browser.matchIosWebview_ = function() {\n            return (\n                (goog.labs.userAgent.util.matchUserAgent('iPad') ||\n                    goog.labs.userAgent.util.matchUserAgent('iPhone')) &&\n                !goog.labs.userAgent.browser.matchSafari_() &&\n                !goog.labs.userAgent.browser.matchChrome_() &&\n                !goog.labs.userAgent.browser.matchCoast_() &&\n                !goog.labs.userAgent.browser.matchFirefox_() &&\n                goog.labs.userAgent.util.matchUserAgent('AppleWebKit')\n            );\n        }),\n        (goog.labs.userAgent.browser.matchChrome_ = function() {\n            return (\n                (goog.labs.userAgent.util.matchUserAgent('Chrome') ||\n                    goog.labs.userAgent.util.matchUserAgent('CriOS')) &&\n                !goog.labs.userAgent.browser.matchEdgeHtml_()\n            );\n        }),\n        (goog.labs.userAgent.browser.matchAndroidBrowser_ = function() {\n            return (\n                goog.labs.userAgent.util.matchUserAgent('Android') &&\n                !(\n                    goog.labs.userAgent.browser.isChrome() ||\n                    goog.labs.userAgent.browser.isFirefox() ||\n                    goog.labs.userAgent.browser.isOpera() ||\n                    goog.labs.userAgent.browser.isSilk()\n                )\n            );\n        }),\n        (goog.labs.userAgent.browser.isOpera = goog.labs.userAgent.browser.matchOpera_),\n        (goog.labs.userAgent.browser.isIE = goog.labs.userAgent.browser.matchIE_),\n        (goog.labs.userAgent.browser.isEdge = goog.labs.userAgent.browser.matchEdgeHtml_),\n        (goog.labs.userAgent.browser.isEdgeChromium =\n            goog.labs.userAgent.browser.matchEdgeChromium_),\n        (goog.labs.userAgent.browser.isOperaChromium =\n            goog.labs.userAgent.browser.matchOperaChromium_),\n        (goog.labs.userAgent.browser.isFirefox = goog.labs.userAgent.browser.matchFirefox_),\n        (goog.labs.userAgent.browser.isSafari = goog.labs.userAgent.browser.matchSafari_),\n        (goog.labs.userAgent.browser.isCoast = goog.labs.userAgent.browser.matchCoast_),\n        (goog.labs.userAgent.browser.isIosWebview = goog.labs.userAgent.browser.matchIosWebview_),\n        (goog.labs.userAgent.browser.isChrome = goog.labs.userAgent.browser.matchChrome_),\n        (goog.labs.userAgent.browser.isAndroidBrowser =\n            goog.labs.userAgent.browser.matchAndroidBrowser_),\n        (goog.labs.userAgent.browser.isSilk = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Silk');\n        }),\n        (goog.labs.userAgent.browser.getVersion = function() {\n            function e(e) {\n                return (e = goog.array.find(e, o)), r[e] || '';\n            }\n            var t = goog.labs.userAgent.util.getUserAgent();\n            if (goog.labs.userAgent.browser.isIE())\n                return goog.labs.userAgent.browser.getIEVersion_(t);\n            t = goog.labs.userAgent.util.extractVersionTuples(t);\n            var r = {};\n            goog.array.forEach(t, function(e) {\n                r[e[0]] = e[1];\n            });\n            var o = goog.partial(goog.object.containsKey, r);\n            return goog.labs.userAgent.browser.isOpera()\n                ? e(['Version', 'Opera'])\n                : goog.labs.userAgent.browser.isEdge()\n                ? e(['Edge'])\n                : goog.labs.userAgent.browser.isEdgeChromium()\n                ? e(['Edg'])\n                : goog.labs.userAgent.browser.isChrome()\n                ? e(['Chrome', 'CriOS', 'HeadlessChrome'])\n                : ((t = t[2]) && t[1]) || '';\n        }),\n        (goog.labs.userAgent.browser.isVersionOrHigher = function(e) {\n            return (\n                0 <=\n                goog.string.internal.compareVersions(goog.labs.userAgent.browser.getVersion(), e)\n            );\n        }),\n        (goog.labs.userAgent.browser.getIEVersion_ = function(e) {\n            var t = /rv: *([\\d\\.]*)/.exec(e);\n            if (t && t[1]) return t[1];\n            t = '';\n            var r = /MSIE +([\\d\\.]+)/.exec(e);\n            if (r && r[1])\n                if (((e = /Trident\\/(\\d.\\d)/.exec(e)), '7.0' == r[1]))\n                    if (e && e[1])\n                        switch (e[1]) {\n                            case '4.0':\n                                t = '8.0';\n                                break;\n                            case '5.0':\n                                t = '9.0';\n                                break;\n                            case '6.0':\n                                t = '10.0';\n                                break;\n                            case '7.0':\n                                t = '11.0';\n                        }\n                    else t = '7.0';\n                else t = r[1];\n            return t;\n        }),\n        (goog.html.SafeHtml = function() {\n            (this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = ''),\n                (this.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ =\n                    goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_),\n                (this.dir_ = null);\n        }),\n        (goog.html.SafeHtml.ENABLE_ERROR_MESSAGES = goog.DEBUG),\n        (goog.html.SafeHtml.SUPPORT_STYLE_ATTRIBUTE = !0),\n        (goog.html.SafeHtml.prototype.implementsGoogI18nBidiDirectionalString = !0),\n        (goog.html.SafeHtml.prototype.getDirection = function() {\n            return this.dir_;\n        }),\n        (goog.html.SafeHtml.prototype.implementsGoogStringTypedString = !0),\n        (goog.html.SafeHtml.prototype.getTypedStringValue = function() {\n            return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_.toString();\n        }),\n        goog.DEBUG &&\n            (goog.html.SafeHtml.prototype.toString = function() {\n                return 'SafeHtml{' + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ + '}';\n            }),\n        (goog.html.SafeHtml.unwrap = function(e) {\n            return goog.html.SafeHtml.unwrapTrustedHTML(e).toString();\n        }),\n        (goog.html.SafeHtml.unwrapTrustedHTML = function(e) {\n            return e instanceof goog.html.SafeHtml &&\n                e.constructor === goog.html.SafeHtml &&\n                e.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ ===\n                    goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_\n                ? e.privateDoNotAccessOrElseSafeHtmlWrappedValue_\n                : (goog.asserts.fail(\n                      \"expected object of type SafeHtml, got '\" + e + \"' of type \" + goog.typeOf(e)\n                  ),\n                  'type_error:SafeHtml');\n        }),\n        (goog.html.SafeHtml.htmlEscape = function(e) {\n            if (e instanceof goog.html.SafeHtml) return e;\n            var t = 'object' == typeof e,\n                r = null;\n            return (\n                t && e.implementsGoogI18nBidiDirectionalString && (r = e.getDirection()),\n                (e = t && e.implementsGoogStringTypedString ? e.getTypedStringValue() : String(e)),\n                goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n                    goog.string.internal.htmlEscape(e),\n                    r\n                )\n            );\n        }),\n        (goog.html.SafeHtml.htmlEscapePreservingNewlines = function(e) {\n            return e instanceof goog.html.SafeHtml\n                ? e\n                : ((e = goog.html.SafeHtml.htmlEscape(e)),\n                  goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n                      goog.string.internal.newLineToBr(goog.html.SafeHtml.unwrap(e)),\n                      e.getDirection()\n                  ));\n        }),\n        (goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces = function(e) {\n            return e instanceof goog.html.SafeHtml\n                ? e\n                : ((e = goog.html.SafeHtml.htmlEscape(e)),\n                  goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n                      goog.string.internal.whitespaceEscape(goog.html.SafeHtml.unwrap(e)),\n                      e.getDirection()\n                  ));\n        }),\n        (goog.html.SafeHtml.from = goog.html.SafeHtml.htmlEscape),\n        (goog.html.SafeHtml.comment = function(e) {\n            return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n                '\\x3c!--' + goog.string.internal.htmlEscape(e) + '--\\x3e',\n                null\n            );\n        }),\n        (goog.html.SafeHtml.VALID_NAMES_IN_TAG_ = /^[a-zA-Z0-9-]+$/),\n        (goog.html.SafeHtml.URL_ATTRIBUTES_ = {\n            action: !0,\n            cite: !0,\n            data: !0,\n            formaction: !0,\n            href: !0,\n            manifest: !0,\n            poster: !0,\n            src: !0,\n        }),\n        (goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_ = {\n            APPLET: !0,\n            BASE: !0,\n            EMBED: !0,\n            IFRAME: !0,\n            LINK: !0,\n            MATH: !0,\n            META: !0,\n            OBJECT: !0,\n            SCRIPT: !0,\n            STYLE: !0,\n            SVG: !0,\n            TEMPLATE: !0,\n        }),\n        (goog.html.SafeHtml.create = function(e, t, r) {\n            return (\n                goog.html.SafeHtml.verifyTagName(String(e)),\n                goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(\n                    String(e),\n                    t,\n                    r\n                )\n            );\n        }),\n        (goog.html.SafeHtml.verifyTagName = function(e) {\n            if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(e))\n                throw Error(\n                    goog.html.SafeHtml.ENABLE_ERROR_MESSAGES ? 'Invalid tag name <' + e + '>.' : ''\n                );\n            if (e.toUpperCase() in goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_)\n                throw Error(\n                    goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                        ? 'Tag name <' + e + '> is not allowed for SafeHtml.'\n                        : ''\n                );\n        }),\n        (goog.html.SafeHtml.createIframe = function(e, t, r, o) {\n            e && goog.html.TrustedResourceUrl.unwrap(e);\n            var i = {};\n            return (\n                (i.src = e || null),\n                (i.srcdoc = t && goog.html.SafeHtml.unwrap(t)),\n                (e = goog.html.SafeHtml.combineAttributes(i, { sandbox: '' }, r)),\n                goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse('iframe', e, o)\n            );\n        }),\n        (goog.html.SafeHtml.createSandboxIframe = function(e, t, r, o) {\n            if (!goog.html.SafeHtml.canUseSandboxIframe())\n                throw Error(\n                    goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                        ? 'The browser does not support sandboxed iframes.'\n                        : ''\n                );\n            var i = {};\n            return (\n                (i.src = e ? goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(e)) : null),\n                (i.srcdoc = t || null),\n                (i.sandbox = ''),\n                (e = goog.html.SafeHtml.combineAttributes(i, {}, r)),\n                goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse('iframe', e, o)\n            );\n        }),\n        (goog.html.SafeHtml.canUseSandboxIframe = function() {\n            return (\n                goog.global.HTMLIFrameElement &&\n                'sandbox' in goog.global.HTMLIFrameElement.prototype\n            );\n        }),\n        (goog.html.SafeHtml.createScriptSrc = function(e, t) {\n            return (\n                goog.html.TrustedResourceUrl.unwrap(e),\n                (e = goog.html.SafeHtml.combineAttributes({ src: e }, {}, t)),\n                goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse('script', e)\n            );\n        }),\n        (goog.html.SafeHtml.createScript = function(e, t) {\n            for (var r in t) {\n                var o = r.toLowerCase();\n                if ('language' == o || 'src' == o || 'text' == o || 'type' == o)\n                    throw Error(\n                        goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                            ? 'Cannot set \"' + o + '\" attribute'\n                            : ''\n                    );\n            }\n            for (r = '', e = goog.array.concat(e), o = 0; o < e.length; o++)\n                r += goog.html.SafeScript.unwrap(e[o]);\n            return (\n                (e = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n                    r,\n                    goog.i18n.bidi.Dir.NEUTRAL\n                )),\n                goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse('script', t, e)\n            );\n        }),\n        (goog.html.SafeHtml.createStyle = function(e, t) {\n            t = goog.html.SafeHtml.combineAttributes({ type: 'text/css' }, {}, t);\n            var r = '';\n            e = goog.array.concat(e);\n            for (var o = 0; o < e.length; o++) r += goog.html.SafeStyleSheet.unwrap(e[o]);\n            return (\n                (e = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n                    r,\n                    goog.i18n.bidi.Dir.NEUTRAL\n                )),\n                goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse('style', t, e)\n            );\n        }),\n        (goog.html.SafeHtml.createMetaRefresh = function(e, t) {\n            return (\n                (e = goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(e))),\n                (goog.labs.userAgent.browser.isIE() || goog.labs.userAgent.browser.isEdge()) &&\n                    goog.string.internal.contains(e, ';') &&\n                    (e = \"'\" + e.replace(/'/g, '%27') + \"'\"),\n                goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse('meta', {\n                    'http-equiv': 'refresh',\n                    content: (t || 0) + '; url=' + e,\n                })\n            );\n        }),\n        (goog.html.SafeHtml.getAttrNameAndValue_ = function(e, t, r) {\n            if (r instanceof goog.string.Const) r = goog.string.Const.unwrap(r);\n            else if ('style' == t.toLowerCase()) {\n                if (!goog.html.SafeHtml.SUPPORT_STYLE_ATTRIBUTE)\n                    throw Error(\n                        goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                            ? 'Attribute \"style\" not supported.'\n                            : ''\n                    );\n                r = goog.html.SafeHtml.getStyleValue_(r);\n            } else {\n                if (/^on/i.test(t))\n                    throw Error(\n                        goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                            ? 'Attribute \"' +\n                                  t +\n                                  '\" requires goog.string.Const value, \"' +\n                                  r +\n                                  '\" given.'\n                            : ''\n                    );\n                if (t.toLowerCase() in goog.html.SafeHtml.URL_ATTRIBUTES_)\n                    if (r instanceof goog.html.TrustedResourceUrl)\n                        r = goog.html.TrustedResourceUrl.unwrap(r);\n                    else if (r instanceof goog.html.SafeUrl) r = goog.html.SafeUrl.unwrap(r);\n                    else {\n                        if ('string' != typeof r)\n                            throw Error(\n                                goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                                    ? 'Attribute \"' +\n                                          t +\n                                          '\" on tag \"' +\n                                          e +\n                                          '\" requires goog.html.SafeUrl, goog.string.Const, or string, value \"' +\n                                          r +\n                                          '\" given.'\n                                    : ''\n                            );\n                        r = goog.html.SafeUrl.sanitize(r).getTypedStringValue();\n                    }\n            }\n            return (\n                r.implementsGoogStringTypedString && (r = r.getTypedStringValue()),\n                goog.asserts.assert(\n                    'string' == typeof r || 'number' == typeof r,\n                    'String or number value expected, got ' + typeof r + ' with value: ' + r\n                ),\n                t + '=\"' + goog.string.internal.htmlEscape(String(r)) + '\"'\n            );\n        }),\n        (goog.html.SafeHtml.getStyleValue_ = function(e) {\n            if (!goog.isObject(e))\n                throw Error(\n                    goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                        ? 'The \"style\" attribute requires goog.html.SafeStyle or map of style properties, ' +\n                              typeof e +\n                              ' given: ' +\n                              e\n                        : ''\n                );\n            return (\n                e instanceof goog.html.SafeStyle || (e = goog.html.SafeStyle.create(e)),\n                goog.html.SafeStyle.unwrap(e)\n            );\n        }),\n        (goog.html.SafeHtml.createWithDir = function(e, t, r, o) {\n            return ((t = goog.html.SafeHtml.create(t, r, o)).dir_ = e), t;\n        }),\n        (goog.html.SafeHtml.join = function(e, t) {\n            var r = (e = goog.html.SafeHtml.htmlEscape(e)).getDirection(),\n                o = [],\n                i = function(e) {\n                    Array.isArray(e)\n                        ? goog.array.forEach(e, i)\n                        : ((e = goog.html.SafeHtml.htmlEscape(e)),\n                          o.push(goog.html.SafeHtml.unwrap(e)),\n                          (e = e.getDirection()),\n                          r == goog.i18n.bidi.Dir.NEUTRAL\n                              ? (r = e)\n                              : e != goog.i18n.bidi.Dir.NEUTRAL && r != e && (r = null));\n                };\n            return (\n                goog.array.forEach(t, i),\n                goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n                    o.join(goog.html.SafeHtml.unwrap(e)),\n                    r\n                )\n            );\n        }),\n        (goog.html.SafeHtml.concat = function(e) {\n            return goog.html.SafeHtml.join(\n                goog.html.SafeHtml.EMPTY,\n                Array.prototype.slice.call(arguments)\n            );\n        }),\n        (goog.html.SafeHtml.concatWithDir = function(e, t) {\n            var r = goog.html.SafeHtml.concat(goog.array.slice(arguments, 1));\n            return (r.dir_ = e), r;\n        }),\n        (goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}),\n        (goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse = function(e, t) {\n            return new goog.html.SafeHtml().initSecurityPrivateDoNotAccessOrElse_(e, t);\n        }),\n        (goog.html.SafeHtml.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(e, t) {\n            return (\n                (this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = goog.html.trustedtypes\n                    .PRIVATE_DO_NOT_ACCESS_OR_ELSE_POLICY\n                    ? goog.html.trustedtypes.PRIVATE_DO_NOT_ACCESS_OR_ELSE_POLICY.createHTML(e)\n                    : e),\n                (this.dir_ = t),\n                this\n            );\n        }),\n        (goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse = function(e, t, r) {\n            var o = null,\n                i = '<' + e + goog.html.SafeHtml.stringifyAttributes(e, t);\n            return (\n                null == r ? (r = []) : Array.isArray(r) || (r = [r]),\n                goog.dom.tags.isVoidTag(e.toLowerCase())\n                    ? (goog.asserts.assert(\n                          !r.length,\n                          'Void tag <' + e + '> does not allow content.'\n                      ),\n                      (i += '>'))\n                    : ((o = goog.html.SafeHtml.concat(r)),\n                      (i += '>' + goog.html.SafeHtml.unwrap(o) + '</' + e + '>'),\n                      (o = o.getDirection())),\n                (e = t && t.dir) &&\n                    (o = /^(ltr|rtl|auto)$/i.test(e) ? goog.i18n.bidi.Dir.NEUTRAL : null),\n                goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(i, o)\n            );\n        }),\n        (goog.html.SafeHtml.stringifyAttributes = function(e, t) {\n            var r = '';\n            if (t)\n                for (var o in t) {\n                    if (!goog.html.SafeHtml.VALID_NAMES_IN_TAG_.test(o))\n                        throw Error(\n                            goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                                ? 'Invalid attribute name \"' + o + '\".'\n                                : ''\n                        );\n                    var i = t[o];\n                    null != i && (r += ' ' + goog.html.SafeHtml.getAttrNameAndValue_(e, o, i));\n                }\n            return r;\n        }),\n        (goog.html.SafeHtml.combineAttributes = function(e, t, r) {\n            var o,\n                i = {};\n            for (o in e)\n                goog.asserts.assert(o.toLowerCase() == o, 'Must be lower case'), (i[o] = e[o]);\n            for (o in t)\n                goog.asserts.assert(o.toLowerCase() == o, 'Must be lower case'), (i[o] = t[o]);\n            if (r)\n                for (o in r) {\n                    var a = o.toLowerCase();\n                    if (a in e)\n                        throw Error(\n                            goog.html.SafeHtml.ENABLE_ERROR_MESSAGES\n                                ? 'Cannot override \"' +\n                                      a +\n                                      '\" attribute, got \"' +\n                                      o +\n                                      '\" with value \"' +\n                                      r[o] +\n                                      '\"'\n                                : ''\n                        );\n                    a in t && delete i[a], (i[o] = r[o]);\n                }\n            return i;\n        }),\n        (goog.html.SafeHtml.DOCTYPE_HTML = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n            '<!DOCTYPE html>',\n            goog.i18n.bidi.Dir.NEUTRAL\n        )),\n        (goog.html.SafeHtml.EMPTY = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n            '',\n            goog.i18n.bidi.Dir.NEUTRAL\n        )),\n        (goog.html.SafeHtml.BR = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(\n            '<br>',\n            goog.i18n.bidi.Dir.NEUTRAL\n        )),\n        (goog.html.uncheckedconversions = {}),\n        (goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract = function(\n            e,\n            t,\n            r\n        ) {\n            return (\n                goog.asserts.assertString(\n                    goog.string.Const.unwrap(e),\n                    'must provide justification'\n                ),\n                goog.asserts.assert(\n                    !goog.string.internal.isEmptyOrWhitespace(goog.string.Const.unwrap(e)),\n                    'must provide non-empty justification'\n                ),\n                goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(t, r || null)\n            );\n        }),\n        (goog.html.uncheckedconversions.safeScriptFromStringKnownToSatisfyTypeContract = function(\n            e,\n            t\n        ) {\n            return (\n                goog.asserts.assertString(\n                    goog.string.Const.unwrap(e),\n                    'must provide justification'\n                ),\n                goog.asserts.assert(\n                    !goog.string.internal.isEmptyOrWhitespace(goog.string.Const.unwrap(e)),\n                    'must provide non-empty justification'\n                ),\n                goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(t)\n            );\n        }),\n        (goog.html.uncheckedconversions.safeStyleFromStringKnownToSatisfyTypeContract = function(\n            e,\n            t\n        ) {\n            return (\n                goog.asserts.assertString(\n                    goog.string.Const.unwrap(e),\n                    'must provide justification'\n                ),\n                goog.asserts.assert(\n                    !goog.string.internal.isEmptyOrWhitespace(goog.string.Const.unwrap(e)),\n                    'must provide non-empty justification'\n                ),\n                goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(t)\n            );\n        }),\n        (goog.html.uncheckedconversions.safeStyleSheetFromStringKnownToSatisfyTypeContract = function(\n            e,\n            t\n        ) {\n            return (\n                goog.asserts.assertString(\n                    goog.string.Const.unwrap(e),\n                    'must provide justification'\n                ),\n                goog.asserts.assert(\n                    !goog.string.internal.isEmptyOrWhitespace(goog.string.Const.unwrap(e)),\n                    'must provide non-empty justification'\n                ),\n                goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(t)\n            );\n        }),\n        (goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract = function(\n            e,\n            t\n        ) {\n            return (\n                goog.asserts.assertString(\n                    goog.string.Const.unwrap(e),\n                    'must provide justification'\n                ),\n                goog.asserts.assert(\n                    !goog.string.internal.isEmptyOrWhitespace(goog.string.Const.unwrap(e)),\n                    'must provide non-empty justification'\n                ),\n                goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(t)\n            );\n        }),\n        (goog.html.uncheckedconversions.trustedResourceUrlFromStringKnownToSatisfyTypeContract = function(\n            e,\n            t\n        ) {\n            return (\n                goog.asserts.assertString(\n                    goog.string.Const.unwrap(e),\n                    'must provide justification'\n                ),\n                goog.asserts.assert(\n                    !goog.string.internal.isEmptyOrWhitespace(goog.string.Const.unwrap(e)),\n                    'must provide non-empty justification'\n                ),\n                goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(\n                    t\n                )\n            );\n        }),\n        (goog.dom.safe = {}),\n        (goog.dom.safe.InsertAdjacentHtmlPosition = {\n            AFTERBEGIN: 'afterbegin',\n            AFTEREND: 'afterend',\n            BEFOREBEGIN: 'beforebegin',\n            BEFOREEND: 'beforeend',\n        }),\n        (goog.dom.safe.insertAdjacentHtml = function(e, t, r) {\n            e.insertAdjacentHTML(t, goog.html.SafeHtml.unwrapTrustedHTML(r));\n        }),\n        (goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_ = {\n            MATH: !0,\n            SCRIPT: !0,\n            STYLE: !0,\n            SVG: !0,\n            TEMPLATE: !0,\n        }),\n        (goog.dom.safe.isInnerHtmlCleanupRecursive_ = goog.functions.cacheReturnValue(function() {\n            if (goog.DEBUG && 'undefined' == typeof document) return !1;\n            var e = document.createElement('div'),\n                t = document.createElement('div');\n            return (\n                t.appendChild(document.createElement('div')),\n                e.appendChild(t),\n                !(goog.DEBUG && !e.firstChild) &&\n                    ((t = e.firstChild.firstChild),\n                    (e.innerHTML = goog.html.SafeHtml.unwrapTrustedHTML(goog.html.SafeHtml.EMPTY)),\n                    !t.parentElement)\n            );\n        })),\n        (goog.dom.safe.unsafeSetInnerHtmlDoNotUseOrElse = function(e, t) {\n            if (goog.dom.safe.isInnerHtmlCleanupRecursive_())\n                for (; e.lastChild; ) e.removeChild(e.lastChild);\n            e.innerHTML = goog.html.SafeHtml.unwrapTrustedHTML(t);\n        }),\n        (goog.dom.safe.setInnerHtml = function(e, t) {\n            if (goog.asserts.ENABLE_ASSERTS) {\n                var r = e.tagName.toUpperCase();\n                if (goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_[r])\n                    throw Error(\n                        'goog.dom.safe.setInnerHtml cannot be used to set content of ' +\n                            e.tagName +\n                            '.'\n                    );\n            }\n            goog.dom.safe.unsafeSetInnerHtmlDoNotUseOrElse(e, t);\n        }),\n        (goog.dom.safe.setOuterHtml = function(e, t) {\n            e.outerHTML = goog.html.SafeHtml.unwrapTrustedHTML(t);\n        }),\n        (goog.dom.safe.setFormElementAction = function(e, t) {\n            (t = t instanceof goog.html.SafeUrl ? t : goog.html.SafeUrl.sanitizeAssertUnchanged(t)),\n                (goog.dom.asserts.assertIsHTMLFormElement(e).action = goog.html.SafeUrl.unwrap(t));\n        }),\n        (goog.dom.safe.setButtonFormAction = function(e, t) {\n            (t = t instanceof goog.html.SafeUrl ? t : goog.html.SafeUrl.sanitizeAssertUnchanged(t)),\n                (goog.dom.asserts.assertIsHTMLButtonElement(\n                    e\n                ).formAction = goog.html.SafeUrl.unwrap(t));\n        }),\n        (goog.dom.safe.setInputFormAction = function(e, t) {\n            (t = t instanceof goog.html.SafeUrl ? t : goog.html.SafeUrl.sanitizeAssertUnchanged(t)),\n                (goog.dom.asserts.assertIsHTMLInputElement(e).formAction = goog.html.SafeUrl.unwrap(\n                    t\n                ));\n        }),\n        (goog.dom.safe.setStyle = function(e, t) {\n            e.style.cssText = goog.html.SafeStyle.unwrap(t);\n        }),\n        (goog.dom.safe.documentWrite = function(e, t) {\n            e.write(goog.html.SafeHtml.unwrapTrustedHTML(t));\n        }),\n        (goog.dom.safe.setAnchorHref = function(e, t) {\n            goog.dom.asserts.assertIsHTMLAnchorElement(e),\n                (t =\n                    t instanceof goog.html.SafeUrl\n                        ? t\n                        : goog.html.SafeUrl.sanitizeAssertUnchanged(t)),\n                (e.href = goog.html.SafeUrl.unwrap(t));\n        }),\n        (goog.dom.safe.setImageSrc = function(e, t) {\n            if ((goog.dom.asserts.assertIsHTMLImageElement(e), !(t instanceof goog.html.SafeUrl))) {\n                var r = /^data:image\\//i.test(t);\n                t = goog.html.SafeUrl.sanitizeAssertUnchanged(t, r);\n            }\n            e.src = goog.html.SafeUrl.unwrap(t);\n        }),\n        (goog.dom.safe.setAudioSrc = function(e, t) {\n            if ((goog.dom.asserts.assertIsHTMLAudioElement(e), !(t instanceof goog.html.SafeUrl))) {\n                var r = /^data:audio\\//i.test(t);\n                t = goog.html.SafeUrl.sanitizeAssertUnchanged(t, r);\n            }\n            e.src = goog.html.SafeUrl.unwrap(t);\n        }),\n        (goog.dom.safe.setVideoSrc = function(e, t) {\n            if ((goog.dom.asserts.assertIsHTMLVideoElement(e), !(t instanceof goog.html.SafeUrl))) {\n                var r = /^data:video\\//i.test(t);\n                t = goog.html.SafeUrl.sanitizeAssertUnchanged(t, r);\n            }\n            e.src = goog.html.SafeUrl.unwrap(t);\n        }),\n        (goog.dom.safe.setEmbedSrc = function(e, t) {\n            goog.dom.asserts.assertIsHTMLEmbedElement(e),\n                (e.src = goog.html.TrustedResourceUrl.unwrapTrustedScriptURL(t));\n        }),\n        (goog.dom.safe.setFrameSrc = function(e, t) {\n            goog.dom.asserts.assertIsHTMLFrameElement(e),\n                (e.src = goog.html.TrustedResourceUrl.unwrap(t));\n        }),\n        (goog.dom.safe.setIframeSrc = function(e, t) {\n            goog.dom.asserts.assertIsHTMLIFrameElement(e),\n                (e.src = goog.html.TrustedResourceUrl.unwrap(t));\n        }),\n        (goog.dom.safe.setIframeSrcdoc = function(e, t) {\n            goog.dom.asserts.assertIsHTMLIFrameElement(e),\n                (e.srcdoc = goog.html.SafeHtml.unwrapTrustedHTML(t));\n        }),\n        (goog.dom.safe.setLinkHrefAndRel = function(e, t, r) {\n            goog.dom.asserts.assertIsHTMLLinkElement(e),\n                (e.rel = r),\n                goog.string.internal.caseInsensitiveContains(r, 'stylesheet')\n                    ? (goog.asserts.assert(\n                          t instanceof goog.html.TrustedResourceUrl,\n                          'URL must be TrustedResourceUrl because \"rel\" contains \"stylesheet\"'\n                      ),\n                      (e.href = goog.html.TrustedResourceUrl.unwrap(t)))\n                    : (e.href =\n                          t instanceof goog.html.TrustedResourceUrl\n                              ? goog.html.TrustedResourceUrl.unwrap(t)\n                              : t instanceof goog.html.SafeUrl\n                              ? goog.html.SafeUrl.unwrap(t)\n                              : goog.html.SafeUrl.unwrap(\n                                    goog.html.SafeUrl.sanitizeAssertUnchanged(t)\n                                ));\n        }),\n        (goog.dom.safe.setObjectData = function(e, t) {\n            goog.dom.asserts.assertIsHTMLObjectElement(e),\n                (e.data = goog.html.TrustedResourceUrl.unwrapTrustedScriptURL(t));\n        }),\n        (goog.dom.safe.setScriptSrc = function(e, t) {\n            goog.dom.asserts.assertIsHTMLScriptElement(e),\n                (e.src = goog.html.TrustedResourceUrl.unwrapTrustedScriptURL(t)),\n                (t = goog.getScriptNonce()) && e.setAttribute('nonce', t);\n        }),\n        (goog.dom.safe.setScriptContent = function(e, t) {\n            goog.dom.asserts.assertIsHTMLScriptElement(e),\n                (e.text = goog.html.SafeScript.unwrapTrustedScript(t)),\n                (t = goog.getScriptNonce()) && e.setAttribute('nonce', t);\n        }),\n        (goog.dom.safe.setLocationHref = function(e, t) {\n            goog.dom.asserts.assertIsLocation(e),\n                (t =\n                    t instanceof goog.html.SafeUrl\n                        ? t\n                        : goog.html.SafeUrl.sanitizeAssertUnchanged(t)),\n                (e.href = goog.html.SafeUrl.unwrap(t));\n        }),\n        (goog.dom.safe.assignLocation = function(e, t) {\n            goog.dom.asserts.assertIsLocation(e),\n                (t =\n                    t instanceof goog.html.SafeUrl\n                        ? t\n                        : goog.html.SafeUrl.sanitizeAssertUnchanged(t)),\n                e.assign(goog.html.SafeUrl.unwrap(t));\n        }),\n        (goog.dom.safe.replaceLocation = function(e, t) {\n            (t = t instanceof goog.html.SafeUrl ? t : goog.html.SafeUrl.sanitizeAssertUnchanged(t)),\n                e.replace(goog.html.SafeUrl.unwrap(t));\n        }),\n        (goog.dom.safe.openInWindow = function(e, t, r, o, i) {\n            return (\n                (e =\n                    e instanceof goog.html.SafeUrl\n                        ? e\n                        : goog.html.SafeUrl.sanitizeAssertUnchanged(e)),\n                (t = t || goog.global),\n                (r = r instanceof goog.string.Const ? goog.string.Const.unwrap(r) : r || ''),\n                t.open(goog.html.SafeUrl.unwrap(e), r, o, i)\n            );\n        }),\n        (goog.dom.safe.parseFromStringHtml = function(e, t) {\n            return goog.dom.safe.parseFromString(e, t, 'text/html');\n        }),\n        (goog.dom.safe.parseFromString = function(e, t, r) {\n            return e.parseFromString(goog.html.SafeHtml.unwrapTrustedHTML(t), r);\n        }),\n        (goog.dom.safe.createImageFromBlob = function(e) {\n            if (!/^image\\/.*/g.test(e.type))\n                throw Error('goog.dom.safe.createImageFromBlob only accepts MIME type image/.*.');\n            var t = goog.global.URL.createObjectURL(e);\n            return (\n                ((e = new goog.global.Image()).onload = function() {\n                    goog.global.URL.revokeObjectURL(t);\n                }),\n                goog.dom.safe.setImageSrc(\n                    e,\n                    goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract(\n                        goog.string.Const.from('Image blob URL.'),\n                        t\n                    )\n                ),\n                e\n            );\n        }),\n        (goog.string.DETECT_DOUBLE_ESCAPING = !1),\n        (goog.string.FORCE_NON_DOM_HTML_UNESCAPING = !1),\n        (goog.string.Unicode = { NBSP: ' ' }),\n        (goog.string.startsWith = goog.string.internal.startsWith),\n        (goog.string.endsWith = goog.string.internal.endsWith),\n        (goog.string.caseInsensitiveStartsWith = goog.string.internal.caseInsensitiveStartsWith),\n        (goog.string.caseInsensitiveEndsWith = goog.string.internal.caseInsensitiveEndsWith),\n        (goog.string.caseInsensitiveEquals = goog.string.internal.caseInsensitiveEquals),\n        (goog.string.subs = function(e, t) {\n            for (\n                var r = e.split('%s'), o = '', i = Array.prototype.slice.call(arguments, 1);\n                i.length && 1 < r.length;\n\n            )\n                o += r.shift() + i.shift();\n            return o + r.join('%s');\n        }),\n        (goog.string.collapseWhitespace = function(e) {\n            return e.replace(/[\\s\\xa0]+/g, ' ').replace(/^\\s+|\\s+$/g, '');\n        }),\n        (goog.string.isEmptyOrWhitespace = goog.string.internal.isEmptyOrWhitespace),\n        (goog.string.isEmptyString = function(e) {\n            return 0 == e.length;\n        }),\n        (goog.string.isEmpty = goog.string.isEmptyOrWhitespace),\n        (goog.string.isEmptyOrWhitespaceSafe = function(e) {\n            return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(e));\n        }),\n        (goog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe),\n        (goog.string.isBreakingWhitespace = function(e) {\n            return !/[^\\t\\n\\r ]/.test(e);\n        }),\n        (goog.string.isAlpha = function(e) {\n            return !/[^a-zA-Z]/.test(e);\n        }),\n        (goog.string.isNumeric = function(e) {\n            return !/[^0-9]/.test(e);\n        }),\n        (goog.string.isAlphaNumeric = function(e) {\n            return !/[^a-zA-Z0-9]/.test(e);\n        }),\n        (goog.string.isSpace = function(e) {\n            return ' ' == e;\n        }),\n        (goog.string.isUnicodeChar = function(e) {\n            return (1 == e.length && ' ' <= e && '~' >= e) || ('' <= e && '�' >= e);\n        }),\n        (goog.string.stripNewlines = function(e) {\n            return e.replace(/(\\r\\n|\\r|\\n)+/g, ' ');\n        }),\n        (goog.string.canonicalizeNewlines = function(e) {\n            return e.replace(/(\\r\\n|\\r|\\n)/g, '\\n');\n        }),\n        (goog.string.normalizeWhitespace = function(e) {\n            return e.replace(/\\xa0|\\s/g, ' ');\n        }),\n        (goog.string.normalizeSpaces = function(e) {\n            return e.replace(/\\xa0|[ \\t]+/g, ' ');\n        }),\n        (goog.string.collapseBreakingSpaces = function(e) {\n            return e.replace(/[\\t\\r\\n ]+/g, ' ').replace(/^[\\t\\r\\n ]+|[\\t\\r\\n ]+$/g, '');\n        }),\n        (goog.string.trim = goog.string.internal.trim),\n        (goog.string.trimLeft = function(e) {\n            return e.replace(/^[\\s\\xa0]+/, '');\n        }),\n        (goog.string.trimRight = function(e) {\n            return e.replace(/[\\s\\xa0]+$/, '');\n        }),\n        (goog.string.caseInsensitiveCompare = goog.string.internal.caseInsensitiveCompare),\n        (goog.string.numberAwareCompare_ = function(e, t, r) {\n            if (e == t) return 0;\n            if (!e) return -1;\n            if (!t) return 1;\n            for (\n                var o = e.toLowerCase().match(r),\n                    i = t.toLowerCase().match(r),\n                    a = Math.min(o.length, i.length),\n                    n = 0;\n                n < a;\n                n++\n            ) {\n                r = o[n];\n                var s = i[n];\n                if (r != s)\n                    return (\n                        (e = parseInt(r, 10)),\n                        !isNaN(e) && ((t = parseInt(s, 10)), !isNaN(t) && e - t)\n                            ? e - t\n                            : r < s\n                            ? -1\n                            : 1\n                    );\n            }\n            return o.length != i.length ? o.length - i.length : e < t ? -1 : 1;\n        }),\n        (goog.string.intAwareCompare = function(e, t) {\n            return goog.string.numberAwareCompare_(e, t, /\\d+|\\D+/g);\n        }),\n        (goog.string.floatAwareCompare = function(e, t) {\n            return goog.string.numberAwareCompare_(e, t, /\\d+|\\.\\d+|\\D+/g);\n        }),\n        (goog.string.numerateCompare = goog.string.floatAwareCompare),\n        (goog.string.urlEncode = function(e) {\n            return encodeURIComponent(String(e));\n        }),\n        (goog.string.urlDecode = function(e) {\n            return decodeURIComponent(e.replace(/\\+/g, ' '));\n        }),\n        (goog.string.newLineToBr = goog.string.internal.newLineToBr),\n        (goog.string.htmlEscape = function(e, t) {\n            return (\n                (e = goog.string.internal.htmlEscape(e, t)),\n                goog.string.DETECT_DOUBLE_ESCAPING && (e = e.replace(goog.string.E_RE_, '&#101;')),\n                e\n            );\n        }),\n        (goog.string.E_RE_ = /e/g),\n        (goog.string.unescapeEntities = function(e) {\n            return goog.string.contains(e, '&')\n                ? !goog.string.FORCE_NON_DOM_HTML_UNESCAPING && 'document' in goog.global\n                    ? goog.string.unescapeEntitiesUsingDom_(e)\n                    : goog.string.unescapePureXmlEntities_(e)\n                : e;\n        }),\n        (goog.string.unescapeEntitiesWithDocument = function(e, t) {\n            return goog.string.contains(e, '&') ? goog.string.unescapeEntitiesUsingDom_(e, t) : e;\n        }),\n        (goog.string.unescapeEntitiesUsingDom_ = function(e, t) {\n            var r = { '&amp;': '&', '&lt;': '<', '&gt;': '>', '&quot;': '\"' },\n                o = t ? t.createElement('div') : goog.global.document.createElement('div');\n            return e.replace(goog.string.HTML_ENTITY_PATTERN_, function(e, t) {\n                var i = r[e];\n                return (\n                    i ||\n                    ('#' == t.charAt(0) &&\n                        ((t = Number('0' + t.substr(1))), isNaN(t) || (i = String.fromCharCode(t))),\n                    i ||\n                        (goog.dom.safe.setInnerHtml(\n                            o,\n                            goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract(\n                                goog.string.Const.from('Single HTML entity.'),\n                                e + ' '\n                            )\n                        ),\n                        (i = o.firstChild.nodeValue.slice(0, -1))),\n                    (r[e] = i))\n                );\n            });\n        }),\n        (goog.string.unescapePureXmlEntities_ = function(e) {\n            return e.replace(/&([^;]+);/g, function(e, t) {\n                switch (t) {\n                    case 'amp':\n                        return '&';\n                    case 'lt':\n                        return '<';\n                    case 'gt':\n                        return '>';\n                    case 'quot':\n                        return '\"';\n                    default:\n                        return '#' != t.charAt(0) || ((t = Number('0' + t.substr(1))), isNaN(t))\n                            ? e\n                            : String.fromCharCode(t);\n                }\n            });\n        }),\n        (goog.string.HTML_ENTITY_PATTERN_ = /&([^;\\s<&]+);?/g),\n        (goog.string.whitespaceEscape = function(e, t) {\n            return goog.string.newLineToBr(e.replace(/  /g, ' &#160;'), t);\n        }),\n        (goog.string.preserveSpaces = function(e) {\n            return e.replace(/(^|[\\n ]) /g, '$1' + goog.string.Unicode.NBSP);\n        }),\n        (goog.string.stripQuotes = function(e, t) {\n            for (var r = t.length, o = 0; o < r; o++) {\n                var i = 1 == r ? t : t.charAt(o);\n                if (e.charAt(0) == i && e.charAt(e.length - 1) == i)\n                    return e.substring(1, e.length - 1);\n            }\n            return e;\n        }),\n        (goog.string.truncate = function(e, t, r) {\n            return (\n                r && (e = goog.string.unescapeEntities(e)),\n                e.length > t && (e = e.substring(0, t - 3) + '...'),\n                r && (e = goog.string.htmlEscape(e)),\n                e\n            );\n        }),\n        (goog.string.truncateMiddle = function(e, t, r, o) {\n            if ((r && (e = goog.string.unescapeEntities(e)), o && e.length > t)) {\n                o > t && (o = t);\n                var i = e.length - o;\n                e = e.substring(0, t - o) + '...' + e.substring(i);\n            } else\n                e.length > t &&\n                    ((o = Math.floor(t / 2)),\n                    (i = e.length - o),\n                    (e = e.substring(0, o + (t % 2)) + '...' + e.substring(i)));\n            return r && (e = goog.string.htmlEscape(e)), e;\n        }),\n        (goog.string.specialEscapeChars_ = {\n            '\\0': '\\\\0',\n            '\\b': '\\\\b',\n            '\\f': '\\\\f',\n            '\\n': '\\\\n',\n            '\\r': '\\\\r',\n            '\\t': '\\\\t',\n            '\\v': '\\\\x0B',\n            '\"': '\\\\\"',\n            '\\\\': '\\\\\\\\',\n            '<': '\\\\u003C',\n        }),\n        (goog.string.jsEscapeCache_ = { \"'\": \"\\\\'\" }),\n        (goog.string.quote = function(e) {\n            e = String(e);\n            for (var t = ['\"'], r = 0; r < e.length; r++) {\n                var o = e.charAt(r),\n                    i = o.charCodeAt(0);\n                t[r + 1] =\n                    goog.string.specialEscapeChars_[o] ||\n                    (31 < i && 127 > i ? o : goog.string.escapeChar(o));\n            }\n            return t.push('\"'), t.join('');\n        }),\n        (goog.string.escapeString = function(e) {\n            for (var t = [], r = 0; r < e.length; r++) t[r] = goog.string.escapeChar(e.charAt(r));\n            return t.join('');\n        }),\n        (goog.string.escapeChar = function(e) {\n            if (e in goog.string.jsEscapeCache_) return goog.string.jsEscapeCache_[e];\n            if (e in goog.string.specialEscapeChars_)\n                return (goog.string.jsEscapeCache_[e] = goog.string.specialEscapeChars_[e]);\n            var t = e.charCodeAt(0);\n            if (31 < t && 127 > t) var r = e;\n            else\n                256 > t\n                    ? ((r = '\\\\x'), (16 > t || 256 < t) && (r += '0'))\n                    : ((r = '\\\\u'), 4096 > t && (r += '0')),\n                    (r += t.toString(16).toUpperCase());\n            return (goog.string.jsEscapeCache_[e] = r);\n        }),\n        (goog.string.contains = goog.string.internal.contains),\n        (goog.string.caseInsensitiveContains = goog.string.internal.caseInsensitiveContains),\n        (goog.string.countOf = function(e, t) {\n            return e && t ? e.split(t).length - 1 : 0;\n        }),\n        (goog.string.removeAt = function(e, t, r) {\n            var o = e;\n            return (\n                0 <= t &&\n                    t < e.length &&\n                    0 < r &&\n                    (o = e.substr(0, t) + e.substr(t + r, e.length - t - r)),\n                o\n            );\n        }),\n        (goog.string.remove = function(e, t) {\n            return e.replace(t, '');\n        }),\n        (goog.string.removeAll = function(e, t) {\n            return (t = new RegExp(goog.string.regExpEscape(t), 'g')), e.replace(t, '');\n        }),\n        (goog.string.replaceAll = function(e, t, r) {\n            return (\n                (t = new RegExp(goog.string.regExpEscape(t), 'g')),\n                e.replace(t, r.replace(/\\$/g, '$$$$'))\n            );\n        }),\n        (goog.string.regExpEscape = function(e) {\n            return String(e)\n                .replace(/([-()\\[\\]{}+?*.$\\^|,:#<!\\\\])/g, '\\\\$1')\n                .replace(/\\x08/g, '\\\\x08');\n        }),\n        (goog.string.repeat = String.prototype.repeat\n            ? function(e, t) {\n                  return e.repeat(t);\n              }\n            : function(e, t) {\n                  return Array(t + 1).join(e);\n              }),\n        (goog.string.padNumber = function(e, t, r) {\n            return (\n                -1 == (r = (e = void 0 !== r ? e.toFixed(r) : String(e)).indexOf('.')) &&\n                    (r = e.length),\n                goog.string.repeat('0', Math.max(0, t - r)) + e\n            );\n        }),\n        (goog.string.makeSafe = function(e) {\n            return null == e ? '' : String(e);\n        }),\n        (goog.string.buildString = function(e) {\n            return Array.prototype.join.call(arguments, '');\n        }),\n        (goog.string.getRandomString = function() {\n            return (\n                Math.floor(2147483648 * Math.random()).toString(36) +\n                Math.abs(Math.floor(2147483648 * Math.random()) ^ goog.now()).toString(36)\n            );\n        }),\n        (goog.string.compareVersions = goog.string.internal.compareVersions),\n        (goog.string.hashCode = function(e) {\n            for (var t = 0, r = 0; r < e.length; ++r) t = (31 * t + e.charCodeAt(r)) >>> 0;\n            return t;\n        }),\n        (goog.string.uniqueStringCounter_ = (2147483648 * Math.random()) | 0),\n        (goog.string.createUniqueString = function() {\n            return 'goog_' + goog.string.uniqueStringCounter_++;\n        }),\n        (goog.string.toNumber = function(e) {\n            var t = Number(e);\n            return 0 == t && goog.string.isEmptyOrWhitespace(e) ? NaN : t;\n        }),\n        (goog.string.isLowerCamelCase = function(e) {\n            return /^[a-z]+([A-Z][a-z]*)*$/.test(e);\n        }),\n        (goog.string.isUpperCamelCase = function(e) {\n            return /^([A-Z][a-z]*)+$/.test(e);\n        }),\n        (goog.string.toCamelCase = function(e) {\n            return String(e).replace(/\\-([a-z])/g, function(e, t) {\n                return t.toUpperCase();\n            });\n        }),\n        (goog.string.toSelectorCase = function(e) {\n            return String(e)\n                .replace(/([A-Z])/g, '-$1')\n                .toLowerCase();\n        }),\n        (goog.string.toTitleCase = function(e, t) {\n            return (\n                (t = 'string' == typeof t ? goog.string.regExpEscape(t) : '\\\\s'),\n                e.replace(new RegExp('(^' + (t ? '|[' + t + ']+' : '') + ')([a-z])', 'g'), function(\n                    e,\n                    t,\n                    r\n                ) {\n                    return t + r.toUpperCase();\n                })\n            );\n        }),\n        (goog.string.capitalize = function(e) {\n            return String(e.charAt(0)).toUpperCase() + String(e.substr(1)).toLowerCase();\n        }),\n        (goog.string.parseInt = function(e) {\n            return (\n                isFinite(e) && (e = String(e)),\n                'string' == typeof e\n                    ? /^\\s*-?0x/i.test(e)\n                        ? parseInt(e, 16)\n                        : parseInt(e, 10)\n                    : NaN\n            );\n        }),\n        (goog.string.splitLimit = function(e, t, r) {\n            e = e.split(t);\n            for (var o = []; 0 < r && e.length; ) o.push(e.shift()), r--;\n            return e.length && o.push(e.join(t)), o;\n        }),\n        (goog.string.lastComponent = function(e, t) {\n            if (!t) return e;\n            'string' == typeof t && (t = [t]);\n            for (var r = -1, o = 0; o < t.length; o++)\n                if ('' != t[o]) {\n                    var i = e.lastIndexOf(t[o]);\n                    i > r && (r = i);\n                }\n            return -1 == r ? e : e.slice(r + 1);\n        }),\n        (goog.string.editDistance = function(e, t) {\n            var r = [],\n                o = [];\n            if (e == t) return 0;\n            if (!e.length || !t.length) return Math.max(e.length, t.length);\n            for (var i = 0; i < t.length + 1; i++) r[i] = i;\n            for (i = 0; i < e.length; i++) {\n                o[0] = i + 1;\n                for (var a = 0; a < t.length; a++)\n                    o[a + 1] = Math.min(o[a] + 1, r[a + 1] + 1, r[a] + Number(e[i] != t[a]));\n                for (a = 0; a < r.length; a++) r[a] = o[a];\n            }\n            return o[t.length];\n        }),\n        (goog.labs.userAgent.engine = {}),\n        (goog.labs.userAgent.engine.isPresto = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Presto');\n        }),\n        (goog.labs.userAgent.engine.isTrident = function() {\n            return (\n                goog.labs.userAgent.util.matchUserAgent('Trident') ||\n                goog.labs.userAgent.util.matchUserAgent('MSIE')\n            );\n        }),\n        (goog.labs.userAgent.engine.isEdge = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Edge');\n        }),\n        (goog.labs.userAgent.engine.isWebKit = function() {\n            return (\n                goog.labs.userAgent.util.matchUserAgentIgnoreCase('WebKit') &&\n                !goog.labs.userAgent.engine.isEdge()\n            );\n        }),\n        (goog.labs.userAgent.engine.isGecko = function() {\n            return (\n                goog.labs.userAgent.util.matchUserAgent('Gecko') &&\n                !goog.labs.userAgent.engine.isWebKit() &&\n                !goog.labs.userAgent.engine.isTrident() &&\n                !goog.labs.userAgent.engine.isEdge()\n            );\n        }),\n        (goog.labs.userAgent.engine.getVersion = function() {\n            var e = goog.labs.userAgent.util.getUserAgent();\n            if (e) {\n                e = goog.labs.userAgent.util.extractVersionTuples(e);\n                var t,\n                    r = goog.labs.userAgent.engine.getEngineTuple_(e);\n                if (r)\n                    return 'Gecko' == r[0]\n                        ? goog.labs.userAgent.engine.getVersionForKey_(e, 'Firefox')\n                        : r[1];\n                if ((e = e[0]) && (t = e[2]) && (t = /Trident\\/([^\\s;]+)/.exec(t))) return t[1];\n            }\n            return '';\n        }),\n        (goog.labs.userAgent.engine.getEngineTuple_ = function(e) {\n            if (!goog.labs.userAgent.engine.isEdge()) return e[1];\n            for (var t = 0; t < e.length; t++) {\n                var r = e[t];\n                if ('Edge' == r[0]) return r;\n            }\n        }),\n        (goog.labs.userAgent.engine.isVersionOrHigher = function(e) {\n            return 0 <= goog.string.compareVersions(goog.labs.userAgent.engine.getVersion(), e);\n        }),\n        (goog.labs.userAgent.engine.getVersionForKey_ = function(e, t) {\n            return (\n                ((e = goog.array.find(e, function(e) {\n                    return t == e[0];\n                })) &&\n                    e[1]) ||\n                ''\n            );\n        }),\n        (goog.labs.userAgent.platform = {}),\n        (goog.labs.userAgent.platform.isAndroid = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Android');\n        }),\n        (goog.labs.userAgent.platform.isIpod = function() {\n            return goog.labs.userAgent.util.matchUserAgent('iPod');\n        }),\n        (goog.labs.userAgent.platform.isIphone = function() {\n            return (\n                goog.labs.userAgent.util.matchUserAgent('iPhone') &&\n                !goog.labs.userAgent.util.matchUserAgent('iPod') &&\n                !goog.labs.userAgent.util.matchUserAgent('iPad')\n            );\n        }),\n        (goog.labs.userAgent.platform.isIpad = function() {\n            return goog.labs.userAgent.util.matchUserAgent('iPad');\n        }),\n        (goog.labs.userAgent.platform.isIos = function() {\n            return (\n                goog.labs.userAgent.platform.isIphone() ||\n                goog.labs.userAgent.platform.isIpad() ||\n                goog.labs.userAgent.platform.isIpod()\n            );\n        }),\n        (goog.labs.userAgent.platform.isMacintosh = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Macintosh');\n        }),\n        (goog.labs.userAgent.platform.isLinux = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Linux');\n        }),\n        (goog.labs.userAgent.platform.isWindows = function() {\n            return goog.labs.userAgent.util.matchUserAgent('Windows');\n        }),\n        (goog.labs.userAgent.platform.isChromeOS = function() {\n            return goog.labs.userAgent.util.matchUserAgent('CrOS');\n        }),\n        (goog.labs.userAgent.platform.isChromecast = function() {\n            return goog.labs.userAgent.util.matchUserAgent('CrKey');\n        }),\n        (goog.labs.userAgent.platform.isKaiOS = function() {\n            return goog.labs.userAgent.util.matchUserAgentIgnoreCase('KaiOS');\n        }),\n        (goog.labs.userAgent.platform.getVersion = function() {\n            var e = goog.labs.userAgent.util.getUserAgent(),\n                t = '';\n            return (\n                goog.labs.userAgent.platform.isWindows()\n                    ? (t = (e = (t = /Windows (?:NT|Phone) ([0-9.]+)/).exec(e)) ? e[1] : '0.0')\n                    : goog.labs.userAgent.platform.isIos()\n                    ? (t =\n                          (e = (t = /(?:iPhone|iPod|iPad|CPU)\\s+OS\\s+(\\S+)/).exec(e)) &&\n                          e[1].replace(/_/g, '.'))\n                    : goog.labs.userAgent.platform.isMacintosh()\n                    ? (t = (e = (t = /Mac OS X ([0-9_.]+)/).exec(e))\n                          ? e[1].replace(/_/g, '.')\n                          : '10')\n                    : goog.labs.userAgent.platform.isKaiOS()\n                    ? (t = (e = (t = /(?:KaiOS)\\/(\\S+)/i).exec(e)) && e[1])\n                    : goog.labs.userAgent.platform.isAndroid()\n                    ? (t = (e = (t = /Android\\s+([^\\);]+)(\\)|;)/).exec(e)) && e[1])\n                    : goog.labs.userAgent.platform.isChromeOS() &&\n                      (t = (e = (t = /(?:CrOS\\s+(?:i686|x86_64)\\s+([0-9.]+))/).exec(e)) && e[1]),\n                t || ''\n            );\n        }),\n        (goog.labs.userAgent.platform.isVersionOrHigher = function(e) {\n            return 0 <= goog.string.compareVersions(goog.labs.userAgent.platform.getVersion(), e);\n        }),\n        (goog.reflect = {}),\n        (goog.reflect.object = function(e, t) {\n            return t;\n        }),\n        (goog.reflect.objectProperty = function(e, t) {\n            return e;\n        }),\n        (goog.reflect.sinkValue = function(e) {\n            return goog.reflect.sinkValue[' '](e), e;\n        }),\n        (goog.reflect.sinkValue[' '] = goog.nullFunction),\n        (goog.reflect.canAccessProperty = function(e, t) {\n            try {\n                return goog.reflect.sinkValue(e[t]), !0;\n            } catch (e) {}\n            return !1;\n        }),\n        (goog.reflect.cache = function(e, t, r, o) {\n            return (\n                (o = o ? o(t) : t),\n                Object.prototype.hasOwnProperty.call(e, o) ? e[o] : (e[o] = r(t))\n            );\n        }),\n        (goog.userAgent = {}),\n        (goog.userAgent.ASSUME_IE = !1),\n        (goog.userAgent.ASSUME_EDGE = !1),\n        (goog.userAgent.ASSUME_GECKO = !1),\n        (goog.userAgent.ASSUME_WEBKIT = !1),\n        (goog.userAgent.ASSUME_MOBILE_WEBKIT = !1),\n        (goog.userAgent.ASSUME_OPERA = !1),\n        (goog.userAgent.ASSUME_ANY_VERSION = !1),\n        (goog.userAgent.BROWSER_KNOWN_ =\n            goog.userAgent.ASSUME_IE ||\n            goog.userAgent.ASSUME_EDGE ||\n            goog.userAgent.ASSUME_GECKO ||\n            goog.userAgent.ASSUME_MOBILE_WEBKIT ||\n            goog.userAgent.ASSUME_WEBKIT ||\n            goog.userAgent.ASSUME_OPERA),\n        (goog.userAgent.getUserAgentString = function() {\n            return goog.labs.userAgent.util.getUserAgent();\n        }),\n        (goog.userAgent.getNavigatorTyped = function() {\n            return goog.global.navigator || null;\n        }),\n        (goog.userAgent.getNavigator = function() {\n            return goog.userAgent.getNavigatorTyped();\n        }),\n        (goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_\n            ? goog.userAgent.ASSUME_OPERA\n            : goog.labs.userAgent.browser.isOpera()),\n        (goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_\n            ? goog.userAgent.ASSUME_IE\n            : goog.labs.userAgent.browser.isIE()),\n        (goog.userAgent.EDGE = goog.userAgent.BROWSER_KNOWN_\n            ? goog.userAgent.ASSUME_EDGE\n            : goog.labs.userAgent.engine.isEdge()),\n        (goog.userAgent.EDGE_OR_IE = goog.userAgent.EDGE || goog.userAgent.IE),\n        (goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_\n            ? goog.userAgent.ASSUME_GECKO\n            : goog.labs.userAgent.engine.isGecko()),\n        (goog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_\n            ? goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT\n            : goog.labs.userAgent.engine.isWebKit()),\n        (goog.userAgent.isMobile_ = function() {\n            return goog.userAgent.WEBKIT && goog.labs.userAgent.util.matchUserAgent('Mobile');\n        }),\n        (goog.userAgent.MOBILE = goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.isMobile_()),\n        (goog.userAgent.SAFARI = goog.userAgent.WEBKIT),\n        (goog.userAgent.determinePlatform_ = function() {\n            var e = goog.userAgent.getNavigatorTyped();\n            return (e && e.platform) || '';\n        }),\n        (goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_()),\n        (goog.userAgent.ASSUME_MAC = !1),\n        (goog.userAgent.ASSUME_WINDOWS = !1),\n        (goog.userAgent.ASSUME_LINUX = !1),\n        (goog.userAgent.ASSUME_X11 = !1),\n        (goog.userAgent.ASSUME_ANDROID = !1),\n        (goog.userAgent.ASSUME_IPHONE = !1),\n        (goog.userAgent.ASSUME_IPAD = !1),\n        (goog.userAgent.ASSUME_IPOD = !1),\n        (goog.userAgent.ASSUME_KAIOS = !1),\n        (goog.userAgent.PLATFORM_KNOWN_ =\n            goog.userAgent.ASSUME_MAC ||\n            goog.userAgent.ASSUME_WINDOWS ||\n            goog.userAgent.ASSUME_LINUX ||\n            goog.userAgent.ASSUME_X11 ||\n            goog.userAgent.ASSUME_ANDROID ||\n            goog.userAgent.ASSUME_IPHONE ||\n            goog.userAgent.ASSUME_IPAD ||\n            goog.userAgent.ASSUME_IPOD),\n        (goog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_MAC\n            : goog.labs.userAgent.platform.isMacintosh());\n    (goog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_\n        ? goog.userAgent.ASSUME_WINDOWS\n        : goog.labs.userAgent.platform.isWindows()),\n        (goog.userAgent.isLegacyLinux_ = function() {\n            return (\n                goog.labs.userAgent.platform.isLinux() || goog.labs.userAgent.platform.isChromeOS()\n            );\n        }),\n        (goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_LINUX\n            : goog.userAgent.isLegacyLinux_()),\n        (goog.userAgent.isX11_ = function() {\n            var e = goog.userAgent.getNavigatorTyped();\n            return !!e && goog.string.contains(e.appVersion || '', 'X11');\n        }),\n        (goog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_X11\n            : goog.userAgent.isX11_()),\n        (goog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_ANDROID\n            : goog.labs.userAgent.platform.isAndroid()),\n        (goog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_IPHONE\n            : goog.labs.userAgent.platform.isIphone()),\n        (goog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_IPAD\n            : goog.labs.userAgent.platform.isIpad()),\n        (goog.userAgent.IPOD = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_IPOD\n            : goog.labs.userAgent.platform.isIpod()),\n        (goog.userAgent.IOS = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_IPHONE ||\n              goog.userAgent.ASSUME_IPAD ||\n              goog.userAgent.ASSUME_IPOD\n            : goog.labs.userAgent.platform.isIos()),\n        (goog.userAgent.KAIOS = goog.userAgent.PLATFORM_KNOWN_\n            ? goog.userAgent.ASSUME_KAIOS\n            : goog.labs.userAgent.platform.isKaiOS()),\n        (goog.userAgent.determineVersion_ = function() {\n            var e = '',\n                t = goog.userAgent.getVersionRegexResult_();\n            return (\n                t && (e = t ? t[1] : ''),\n                goog.userAgent.IE &&\n                null != (t = goog.userAgent.getDocumentMode_()) &&\n                t > parseFloat(e)\n                    ? String(t)\n                    : e\n            );\n        }),\n        (goog.userAgent.getVersionRegexResult_ = function() {\n            var e = goog.userAgent.getUserAgentString();\n            return goog.userAgent.GECKO\n                ? /rv:([^\\);]+)(\\)|;)/.exec(e)\n                : goog.userAgent.EDGE\n                ? /Edge\\/([\\d\\.]+)/.exec(e)\n                : goog.userAgent.IE\n                ? /\\b(?:MSIE|rv)[: ]([^\\);]+)(\\)|;)/.exec(e)\n                : goog.userAgent.WEBKIT\n                ? /WebKit\\/(\\S+)/.exec(e)\n                : goog.userAgent.OPERA\n                ? /(?:Version)[ \\/]?(\\S+)/.exec(e)\n                : void 0;\n        }),\n        (goog.userAgent.getDocumentMode_ = function() {\n            var e = goog.global.document;\n            return e ? e.documentMode : void 0;\n        }),\n        (goog.userAgent.VERSION = goog.userAgent.determineVersion_()),\n        (goog.userAgent.compare = function(e, t) {\n            return goog.string.compareVersions(e, t);\n        }),\n        (goog.userAgent.isVersionOrHigherCache_ = {}),\n        (goog.userAgent.isVersionOrHigher = function(e) {\n            return (\n                goog.userAgent.ASSUME_ANY_VERSION ||\n                goog.reflect.cache(goog.userAgent.isVersionOrHigherCache_, e, function() {\n                    return 0 <= goog.string.compareVersions(goog.userAgent.VERSION, e);\n                })\n            );\n        }),\n        (goog.userAgent.isVersion = goog.userAgent.isVersionOrHigher),\n        (goog.userAgent.isDocumentModeOrHigher = function(e) {\n            return Number(goog.userAgent.DOCUMENT_MODE) >= e;\n        }),\n        (goog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher),\n        (goog.userAgent.DOCUMENT_MODE = (function() {\n            if (goog.global.document && goog.userAgent.IE) {\n                var e = goog.userAgent.getDocumentMode_();\n                return e || parseInt(goog.userAgent.VERSION, 10) || void 0;\n            }\n        })()),\n        (goog.userAgent.product = {}),\n        (goog.userAgent.product.ASSUME_FIREFOX = !1),\n        (goog.userAgent.product.ASSUME_IPHONE = !1),\n        (goog.userAgent.product.ASSUME_IPAD = !1),\n        (goog.userAgent.product.ASSUME_ANDROID = !1),\n        (goog.userAgent.product.ASSUME_CHROME = !1),\n        (goog.userAgent.product.ASSUME_SAFARI = !1),\n        (goog.userAgent.product.PRODUCT_KNOWN_ =\n            goog.userAgent.ASSUME_IE ||\n            goog.userAgent.ASSUME_EDGE ||\n            goog.userAgent.ASSUME_OPERA ||\n            goog.userAgent.product.ASSUME_FIREFOX ||\n            goog.userAgent.product.ASSUME_IPHONE ||\n            goog.userAgent.product.ASSUME_IPAD ||\n            goog.userAgent.product.ASSUME_ANDROID ||\n            goog.userAgent.product.ASSUME_CHROME ||\n            goog.userAgent.product.ASSUME_SAFARI),\n        (goog.userAgent.product.OPERA = goog.userAgent.OPERA),\n        (goog.userAgent.product.IE = goog.userAgent.IE),\n        (goog.userAgent.product.EDGE = goog.userAgent.EDGE),\n        (goog.userAgent.product.FIREFOX = goog.userAgent.product.PRODUCT_KNOWN_\n            ? goog.userAgent.product.ASSUME_FIREFOX\n            : goog.labs.userAgent.browser.isFirefox()),\n        (goog.userAgent.product.isIphoneOrIpod_ = function() {\n            return goog.labs.userAgent.platform.isIphone() || goog.labs.userAgent.platform.isIpod();\n        }),\n        (goog.userAgent.product.IPHONE = goog.userAgent.product.PRODUCT_KNOWN_\n            ? goog.userAgent.product.ASSUME_IPHONE\n            : goog.userAgent.product.isIphoneOrIpod_()),\n        (goog.userAgent.product.IPAD = goog.userAgent.product.PRODUCT_KNOWN_\n            ? goog.userAgent.product.ASSUME_IPAD\n            : goog.labs.userAgent.platform.isIpad()),\n        (goog.userAgent.product.ANDROID = goog.userAgent.product.PRODUCT_KNOWN_\n            ? goog.userAgent.product.ASSUME_ANDROID\n            : goog.labs.userAgent.browser.isAndroidBrowser()),\n        (goog.userAgent.product.CHROME = goog.userAgent.product.PRODUCT_KNOWN_\n            ? goog.userAgent.product.ASSUME_CHROME\n            : goog.labs.userAgent.browser.isChrome()),\n        (goog.userAgent.product.isSafariDesktop_ = function() {\n            return goog.labs.userAgent.browser.isSafari() && !goog.labs.userAgent.platform.isIos();\n        }),\n        (goog.userAgent.product.SAFARI = goog.userAgent.product.PRODUCT_KNOWN_\n            ? goog.userAgent.product.ASSUME_SAFARI\n            : goog.userAgent.product.isSafariDesktop_()),\n        (goog.crypt.base64 = {}),\n        (goog.crypt.base64.DEFAULT_ALPHABET_COMMON_ =\n            'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'),\n        (goog.crypt.base64.ENCODED_VALS = goog.crypt.base64.DEFAULT_ALPHABET_COMMON_ + '+/='),\n        (goog.crypt.base64.ENCODED_VALS_WEBSAFE =\n            goog.crypt.base64.DEFAULT_ALPHABET_COMMON_ + '-_.'),\n        (goog.crypt.base64.Alphabet = {\n            DEFAULT: 0,\n            NO_PADDING: 1,\n            WEBSAFE: 2,\n            WEBSAFE_DOT_PADDING: 3,\n            WEBSAFE_NO_PADDING: 4,\n        }),\n        (goog.crypt.base64.paddingChars_ = '=.'),\n        (goog.crypt.base64.isPadding_ = function(e) {\n            return goog.string.contains(goog.crypt.base64.paddingChars_, e);\n        }),\n        (goog.crypt.base64.byteToCharMaps_ = {}),\n        (goog.crypt.base64.charToByteMap_ = null),\n        (goog.crypt.base64.ASSUME_NATIVE_SUPPORT_ =\n            goog.userAgent.GECKO ||\n            (goog.userAgent.WEBKIT && !goog.userAgent.product.SAFARI) ||\n            goog.userAgent.OPERA),\n        (goog.crypt.base64.HAS_NATIVE_ENCODE_ =\n            goog.crypt.base64.ASSUME_NATIVE_SUPPORT_ || 'function' == typeof goog.global.btoa),\n        (goog.crypt.base64.HAS_NATIVE_DECODE_ =\n            goog.crypt.base64.ASSUME_NATIVE_SUPPORT_ ||\n            (!goog.userAgent.product.SAFARI &&\n                !goog.userAgent.IE &&\n                'function' == typeof goog.global.atob)),\n        (goog.crypt.base64.encodeByteArray = function(e, t) {\n            goog.asserts.assert(\n                goog.isArrayLike(e),\n                'encodeByteArray takes an array as a parameter'\n            ),\n                void 0 === t && (t = goog.crypt.base64.Alphabet.DEFAULT),\n                goog.crypt.base64.init_(),\n                (t = goog.crypt.base64.byteToCharMaps_[t]);\n            for (var r = [], o = 0; o < e.length; o += 3) {\n                var i = e[o],\n                    a = o + 1 < e.length,\n                    n = a ? e[o + 1] : 0,\n                    s = o + 2 < e.length,\n                    p = s ? e[o + 2] : 0,\n                    d = i >> 2;\n                (i = ((3 & i) << 4) | (n >> 4)),\n                    (n = ((15 & n) << 2) | (p >> 6)),\n                    (p &= 63),\n                    s || ((p = 64), a || (n = 64)),\n                    r.push(t[d], t[i], t[n] || '', t[p] || '');\n            }\n            return r.join('');\n        }),\n        (goog.crypt.base64.encodeString = function(e, t) {\n            return goog.crypt.base64.HAS_NATIVE_ENCODE_ && !t\n                ? goog.global.btoa(e)\n                : goog.crypt.base64.encodeByteArray(goog.crypt.stringToByteArray(e), t);\n        }),\n        (goog.crypt.base64.decodeString = function(e, t) {\n            if (goog.crypt.base64.HAS_NATIVE_DECODE_ && !t) return goog.global.atob(e);\n            var r = '';\n            return (\n                goog.crypt.base64.decodeStringInternal_(e, function(e) {\n                    r += String.fromCharCode(e);\n                }),\n                r\n            );\n        }),\n        (goog.crypt.base64.decodeStringToByteArray = function(e, t) {\n            var r = [];\n            return (\n                goog.crypt.base64.decodeStringInternal_(e, function(e) {\n                    r.push(e);\n                }),\n                r\n            );\n        }),\n        (goog.crypt.base64.decodeStringToUint8Array = function(e) {\n            goog.asserts.assert(\n                !goog.userAgent.IE || goog.userAgent.isVersionOrHigher('10'),\n                'Browser does not support typed arrays'\n            );\n            var t = e.length,\n                r = (3 * t) / 4;\n            r % 3\n                ? (r = Math.floor(r))\n                : goog.crypt.base64.isPadding_(e[t - 1]) &&\n                  (r = goog.crypt.base64.isPadding_(e[t - 2]) ? r - 2 : r - 1);\n            var o = new Uint8Array(r),\n                i = 0;\n            return (\n                goog.crypt.base64.decodeStringInternal_(e, function(e) {\n                    o[i++] = e;\n                }),\n                o.subarray(0, i)\n            );\n        }),\n        (goog.crypt.base64.decodeStringInternal_ = function(e, t) {\n            function r(t) {\n                for (; o < e.length; ) {\n                    var r = e.charAt(o++),\n                        i = goog.crypt.base64.charToByteMap_[r];\n                    if (null != i) return i;\n                    if (!goog.string.isEmptyOrWhitespace(r))\n                        throw Error('Unknown base64 encoding at char: ' + r);\n                }\n                return t;\n            }\n            goog.crypt.base64.init_();\n            for (var o = 0; ; ) {\n                var i = r(-1),\n                    a = r(0),\n                    n = r(64),\n                    s = r(64);\n                if (64 === s && -1 === i) break;\n                t((i << 2) | (a >> 4)),\n                    64 != n && (t(((a << 4) & 240) | (n >> 2)), 64 != s && t(((n << 6) & 192) | s));\n            }\n        }),\n        (goog.crypt.base64.init_ = function() {\n            if (!goog.crypt.base64.charToByteMap_) {\n                goog.crypt.base64.charToByteMap_ = {};\n                for (\n                    var e = goog.crypt.base64.DEFAULT_ALPHABET_COMMON_.split(''),\n                        t = ['+/=', '+/', '-_=', '-_.', '-_'],\n                        r = 0;\n                    5 > r;\n                    r++\n                ) {\n                    var o = e.concat(t[r].split(''));\n                    goog.crypt.base64.byteToCharMaps_[r] = o;\n                    for (var i = 0; i < o.length; i++) {\n                        var a = o[i],\n                            n = goog.crypt.base64.charToByteMap_[a];\n                        void 0 === n\n                            ? (goog.crypt.base64.charToByteMap_[a] = i)\n                            : goog.asserts.assert(n === i);\n                    }\n                }\n            }\n        }),\n        (jspb.utils = {}),\n        (jspb.utils.split64Low = 0),\n        (jspb.utils.split64High = 0),\n        (jspb.utils.splitUint64 = function(e) {\n            var t = e >>> 0;\n            (e = Math.floor((e - t) / jspb.BinaryConstants.TWO_TO_32) >>> 0),\n                (jspb.utils.split64Low = t),\n                (jspb.utils.split64High = e);\n        }),\n        (jspb.utils.splitInt64 = function(e) {\n            var t = 0 > e,\n                r = (e = Math.abs(e)) >>> 0;\n            (e = Math.floor((e - r) / jspb.BinaryConstants.TWO_TO_32)),\n                (e >>>= 0),\n                t &&\n                    ((e = ~e >>> 0),\n                    4294967295 < (r = 1 + (~r >>> 0)) && ((r = 0), 4294967295 < ++e && (e = 0))),\n                (jspb.utils.split64Low = r),\n                (jspb.utils.split64High = e);\n        }),\n        (jspb.utils.splitZigzag64 = function(e) {\n            var t = 0 > e;\n            (e = 2 * Math.abs(e)), jspb.utils.splitUint64(e), (e = jspb.utils.split64Low);\n            var r = jspb.utils.split64High;\n            t && (0 == e ? (0 == r ? (r = e = 4294967295) : (r--, (e = 4294967295))) : e--),\n                (jspb.utils.split64Low = e),\n                (jspb.utils.split64High = r);\n        }),\n        (jspb.utils.splitFloat32 = function(e) {\n            var t = 0 > e ? 1 : 0;\n            if (0 === (e = t ? -e : e))\n                0 < 1 / e\n                    ? ((jspb.utils.split64High = 0), (jspb.utils.split64Low = 0))\n                    : ((jspb.utils.split64High = 0), (jspb.utils.split64Low = 2147483648));\n            else if (isNaN(e)) (jspb.utils.split64High = 0), (jspb.utils.split64Low = 2147483647);\n            else if (e > jspb.BinaryConstants.FLOAT32_MAX)\n                (jspb.utils.split64High = 0),\n                    (jspb.utils.split64Low = ((t << 31) | 2139095040) >>> 0);\n            else if (e < jspb.BinaryConstants.FLOAT32_MIN)\n                (e = Math.round(e / Math.pow(2, -149))),\n                    (jspb.utils.split64High = 0),\n                    (jspb.utils.split64Low = ((t << 31) | e) >>> 0);\n            else {\n                var r = Math.floor(Math.log(e) / Math.LN2);\n                (e *= Math.pow(2, -r)),\n                    16777216 <= (e = Math.round(e * jspb.BinaryConstants.TWO_TO_23)) && ++r,\n                    (jspb.utils.split64High = 0),\n                    (jspb.utils.split64Low = ((t << 31) | ((r + 127) << 23) | (8388607 & e)) >>> 0);\n            }\n        }),\n        (jspb.utils.splitFloat64 = function(e) {\n            var t = 0 > e ? 1 : 0;\n            if (0 === (e = t ? -e : e))\n                (jspb.utils.split64High = 0 < 1 / e ? 0 : 2147483648), (jspb.utils.split64Low = 0);\n            else if (isNaN(e))\n                (jspb.utils.split64High = 2147483647), (jspb.utils.split64Low = 4294967295);\n            else if (e > jspb.BinaryConstants.FLOAT64_MAX)\n                (jspb.utils.split64High = ((t << 31) | 2146435072) >>> 0),\n                    (jspb.utils.split64Low = 0);\n            else if (e < jspb.BinaryConstants.FLOAT64_MIN) {\n                var r = e / Math.pow(2, -1074);\n                (e = r / jspb.BinaryConstants.TWO_TO_32),\n                    (jspb.utils.split64High = ((t << 31) | e) >>> 0),\n                    (jspb.utils.split64Low = r >>> 0);\n            } else {\n                var o = 0;\n                if (2 <= (r = e)) for (; 2 <= r && 1023 > o; ) o++, (r /= 2);\n                else for (; 1 > r && -1022 < o; ) (r *= 2), o--;\n                (e = ((r = e * Math.pow(2, -o)) * jspb.BinaryConstants.TWO_TO_20) & 1048575),\n                    (r = (r * jspb.BinaryConstants.TWO_TO_52) >>> 0),\n                    (jspb.utils.split64High = ((t << 31) | ((o + 1023) << 20) | e) >>> 0),\n                    (jspb.utils.split64Low = r);\n            }\n        }),\n        (jspb.utils.splitHash64 = function(e) {\n            var t = e.charCodeAt(0),\n                r = e.charCodeAt(1),\n                o = e.charCodeAt(2),\n                i = e.charCodeAt(3),\n                a = e.charCodeAt(4),\n                n = e.charCodeAt(5),\n                s = e.charCodeAt(6);\n            (e = e.charCodeAt(7)),\n                (jspb.utils.split64Low = (t + (r << 8) + (o << 16) + (i << 24)) >>> 0),\n                (jspb.utils.split64High = (a + (n << 8) + (s << 16) + (e << 24)) >>> 0);\n        }),\n        (jspb.utils.joinUint64 = function(e, t) {\n            return t * jspb.BinaryConstants.TWO_TO_32 + (e >>> 0);\n        }),\n        (jspb.utils.joinInt64 = function(e, t) {\n            var r = 2147483648 & t;\n            return (\n                r && ((t = ~t >>> 0), 0 == (e = (1 + ~e) >>> 0) && (t = (t + 1) >>> 0)),\n                (e = jspb.utils.joinUint64(e, t)),\n                r ? -e : e\n            );\n        }),\n        (jspb.utils.toZigzag64 = function(e, t, r) {\n            var o = t >> 31;\n            return r((e << 1) ^ o, ((t << 1) | (e >>> 31)) ^ o);\n        }),\n        (jspb.utils.joinZigzag64 = function(e, t) {\n            return jspb.utils.fromZigzag64(e, t, jspb.utils.joinInt64);\n        }),\n        (jspb.utils.fromZigzag64 = function(e, t, r) {\n            var o = -(1 & e);\n            return r(((e >>> 1) | (t << 31)) ^ o, (t >>> 1) ^ o);\n        }),\n        (jspb.utils.joinFloat32 = function(e, t) {\n            t = 2 * (e >> 31) + 1;\n            var r = (e >>> 23) & 255;\n            return (\n                (e &= 8388607),\n                255 == r\n                    ? e\n                        ? NaN\n                        : (1 / 0) * t\n                    : 0 == r\n                    ? t * Math.pow(2, -149) * e\n                    : t * Math.pow(2, r - 150) * (e + Math.pow(2, 23))\n            );\n        }),\n        (jspb.utils.joinFloat64 = function(e, t) {\n            var r = 2 * (t >> 31) + 1,\n                o = (t >>> 20) & 2047;\n            return (\n                (e = jspb.BinaryConstants.TWO_TO_32 * (1048575 & t) + e),\n                2047 == o\n                    ? e\n                        ? NaN\n                        : (1 / 0) * r\n                    : 0 == o\n                    ? r * Math.pow(2, -1074) * e\n                    : r * Math.pow(2, o - 1075) * (e + jspb.BinaryConstants.TWO_TO_52)\n            );\n        }),\n        (jspb.utils.joinHash64 = function(e, t) {\n            return String.fromCharCode(\n                (e >>> 0) & 255,\n                (e >>> 8) & 255,\n                (e >>> 16) & 255,\n                (e >>> 24) & 255,\n                (t >>> 0) & 255,\n                (t >>> 8) & 255,\n                (t >>> 16) & 255,\n                (t >>> 24) & 255\n            );\n        }),\n        (jspb.utils.DIGITS = '0123456789abcdef'.split('')),\n        (jspb.utils.ZERO_CHAR_CODE_ = 48),\n        (jspb.utils.A_CHAR_CODE_ = 97),\n        (jspb.utils.joinUnsignedDecimalString = function(e, t) {\n            function r(e, t) {\n                return (e = e ? String(e) : ''), t ? '0000000'.slice(e.length) + e : e;\n            }\n            if (2097151 >= t) return '' + jspb.utils.joinUint64(e, t);\n            var o = (((e >>> 24) | (t << 8)) >>> 0) & 16777215;\n            return (\n                (e = (16777215 & e) + 6777216 * o + 6710656 * (t = (t >> 16) & 65535)),\n                (o += 8147497 * t),\n                (t *= 2),\n                1e7 <= e && ((o += Math.floor(e / 1e7)), (e %= 1e7)),\n                1e7 <= o && ((t += Math.floor(o / 1e7)), (o %= 1e7)),\n                r(t, 0) + r(o, t) + r(e, 1)\n            );\n        }),\n        (jspb.utils.joinSignedDecimalString = function(e, t) {\n            var r = 2147483648 & t;\n            return (\n                r && (t = (~t + (0 == (e = (1 + ~e) >>> 0) ? 1 : 0)) >>> 0),\n                (e = jspb.utils.joinUnsignedDecimalString(e, t)),\n                r ? '-' + e : e\n            );\n        }),\n        (jspb.utils.hash64ToDecimalString = function(e, t) {\n            jspb.utils.splitHash64(e), (e = jspb.utils.split64Low);\n            var r = jspb.utils.split64High;\n            return t\n                ? jspb.utils.joinSignedDecimalString(e, r)\n                : jspb.utils.joinUnsignedDecimalString(e, r);\n        }),\n        (jspb.utils.hash64ArrayToDecimalStrings = function(e, t) {\n            for (var r = Array(e.length), o = 0; o < e.length; o++)\n                r[o] = jspb.utils.hash64ToDecimalString(e[o], t);\n            return r;\n        }),\n        (jspb.utils.decimalStringToHash64 = function(e) {\n            function t(e, t) {\n                for (var r = 0; 8 > r && (1 !== e || 0 < t); r++)\n                    (t = e * o[r] + t), (o[r] = 255 & t), (t >>>= 8);\n            }\n            jspb.asserts.assert(0 < e.length);\n            var r = !1;\n            '-' === e[0] && ((r = !0), (e = e.slice(1)));\n            for (var o = [0, 0, 0, 0, 0, 0, 0, 0], i = 0; i < e.length; i++)\n                t(10, e.charCodeAt(i) - jspb.utils.ZERO_CHAR_CODE_);\n            return (\n                r &&\n                    ((function() {\n                        for (var e = 0; 8 > e; e++) o[e] = 255 & ~o[e];\n                    })(),\n                    t(1, 1)),\n                goog.crypt.byteArrayToString(o)\n            );\n        }),\n        (jspb.utils.splitDecimalString = function(e) {\n            jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(e));\n        }),\n        (jspb.utils.toHexDigit_ = function(e) {\n            return String.fromCharCode(\n                10 > e ? jspb.utils.ZERO_CHAR_CODE_ + e : jspb.utils.A_CHAR_CODE_ - 10 + e\n            );\n        }),\n        (jspb.utils.fromHexCharCode_ = function(e) {\n            return e >= jspb.utils.A_CHAR_CODE_\n                ? e - jspb.utils.A_CHAR_CODE_ + 10\n                : e - jspb.utils.ZERO_CHAR_CODE_;\n        }),\n        (jspb.utils.hash64ToHexString = function(e) {\n            var t = Array(18);\n            (t[0] = '0'), (t[1] = 'x');\n            for (var r = 0; 8 > r; r++) {\n                var o = e.charCodeAt(7 - r);\n                (t[2 * r + 2] = jspb.utils.toHexDigit_(o >> 4)),\n                    (t[2 * r + 3] = jspb.utils.toHexDigit_(15 & o));\n            }\n            return t.join('');\n        }),\n        (jspb.utils.hexStringToHash64 = function(e) {\n            (e = e.toLowerCase()),\n                jspb.asserts.assert(18 == e.length),\n                jspb.asserts.assert('0' == e[0]),\n                jspb.asserts.assert('x' == e[1]);\n            for (var t = '', r = 0; 8 > r; r++) {\n                var o = jspb.utils.fromHexCharCode_(e.charCodeAt(2 * r + 2)),\n                    i = jspb.utils.fromHexCharCode_(e.charCodeAt(2 * r + 3));\n                t = String.fromCharCode(16 * o + i) + t;\n            }\n            return t;\n        }),\n        (jspb.utils.hash64ToNumber = function(e, t) {\n            jspb.utils.splitHash64(e), (e = jspb.utils.split64Low);\n            var r = jspb.utils.split64High;\n            return t ? jspb.utils.joinInt64(e, r) : jspb.utils.joinUint64(e, r);\n        }),\n        (jspb.utils.numberToHash64 = function(e) {\n            return (\n                jspb.utils.splitInt64(e),\n                jspb.utils.joinHash64(jspb.utils.split64Low, jspb.utils.split64High)\n            );\n        }),\n        (jspb.utils.countVarints = function(e, t, r) {\n            for (var o = 0, i = t; i < r; i++) o += e[i] >> 7;\n            return r - t - o;\n        }),\n        (jspb.utils.countVarintFields = function(e, t, r, o) {\n            var i = 0;\n            if (128 > (o = 8 * o + jspb.BinaryConstants.WireType.VARINT))\n                for (; t < r && e[t++] == o; )\n                    for (i++; ; ) {\n                        var a = e[t++];\n                        if (0 == (128 & a)) break;\n                    }\n            else\n                for (; t < r; ) {\n                    for (a = o; 128 < a; ) {\n                        if (e[t] != ((127 & a) | 128)) return i;\n                        t++, (a >>= 7);\n                    }\n                    if (e[t++] != a) break;\n                    for (i++; 0 != (128 & (a = e[t++])); );\n                }\n            return i;\n        }),\n        (jspb.utils.countFixedFields_ = function(e, t, r, o, i) {\n            var a = 0;\n            if (128 > o) for (; t < r && e[t++] == o; ) a++, (t += i);\n            else\n                for (; t < r; ) {\n                    for (var n = o; 128 < n; ) {\n                        if (e[t++] != ((127 & n) | 128)) return a;\n                        n >>= 7;\n                    }\n                    if (e[t++] != n) break;\n                    a++, (t += i);\n                }\n            return a;\n        }),\n        (jspb.utils.countFixed32Fields = function(e, t, r, o) {\n            return jspb.utils.countFixedFields_(\n                e,\n                t,\n                r,\n                8 * o + jspb.BinaryConstants.WireType.FIXED32,\n                4\n            );\n        }),\n        (jspb.utils.countFixed64Fields = function(e, t, r, o) {\n            return jspb.utils.countFixedFields_(\n                e,\n                t,\n                r,\n                8 * o + jspb.BinaryConstants.WireType.FIXED64,\n                8\n            );\n        }),\n        (jspb.utils.countDelimitedFields = function(e, t, r, o) {\n            var i = 0;\n            for (o = 8 * o + jspb.BinaryConstants.WireType.DELIMITED; t < r; ) {\n                for (var a = o; 128 < a; ) {\n                    if (e[t++] != ((127 & a) | 128)) return i;\n                    a >>= 7;\n                }\n                if (e[t++] != a) break;\n                i++;\n                for (\n                    var n = 0, s = 1;\n                    (n += (127 & (a = e[t++])) * s), (s *= 128), 0 != (128 & a);\n\n                );\n                t += n;\n            }\n            return i;\n        }),\n        (jspb.utils.debugBytesToTextFormat = function(e) {\n            var t = '\"';\n            if (e) {\n                e = jspb.utils.byteSourceToUint8Array(e);\n                for (var r = 0; r < e.length; r++)\n                    (t += '\\\\x'), 16 > e[r] && (t += '0'), (t += e[r].toString(16));\n            }\n            return t + '\"';\n        }),\n        (jspb.utils.debugScalarToTextFormat = function(e) {\n            return 'string' == typeof e ? goog.string.quote(e) : e.toString();\n        }),\n        (jspb.utils.stringToByteArray = function(e) {\n            for (var t = new Uint8Array(e.length), r = 0; r < e.length; r++) {\n                var o = e.charCodeAt(r);\n                if (255 < o)\n                    throw Error(\n                        'Conversion error: string contains codepoint outside of byte range'\n                    );\n                t[r] = o;\n            }\n            return t;\n        }),\n        (jspb.utils.byteSourceToUint8Array = function(e) {\n            return e.constructor === Uint8Array\n                ? e\n                : e.constructor === ArrayBuffer || e.constructor === Array\n                ? new Uint8Array(e)\n                : e.constructor === String\n                ? goog.crypt.base64.decodeStringToUint8Array(e)\n                : e instanceof Uint8Array\n                ? new Uint8Array(e.buffer, e.byteOffset, e.byteLength)\n                : (jspb.asserts.fail('Type not convertible to Uint8Array.'), new Uint8Array(0));\n        }),\n        (jspb.BinaryDecoder = function(e, t, r) {\n            (this.bytes_ = null),\n                (this.cursor_ = this.end_ = this.start_ = 0),\n                (this.error_ = !1),\n                e && this.setBlock(e, t, r);\n        }),\n        (jspb.BinaryDecoder.instanceCache_ = []),\n        (jspb.BinaryDecoder.alloc = function(e, t, r) {\n            if (jspb.BinaryDecoder.instanceCache_.length) {\n                var o = jspb.BinaryDecoder.instanceCache_.pop();\n                return e && o.setBlock(e, t, r), o;\n            }\n            return new jspb.BinaryDecoder(e, t, r);\n        }),\n        (jspb.BinaryDecoder.prototype.free = function() {\n            this.clear(),\n                100 > jspb.BinaryDecoder.instanceCache_.length &&\n                    jspb.BinaryDecoder.instanceCache_.push(this);\n        }),\n        (jspb.BinaryDecoder.prototype.clone = function() {\n            return jspb.BinaryDecoder.alloc(this.bytes_, this.start_, this.end_ - this.start_);\n        }),\n        (jspb.BinaryDecoder.prototype.clear = function() {\n            (this.bytes_ = null), (this.cursor_ = this.end_ = this.start_ = 0), (this.error_ = !1);\n        }),\n        (jspb.BinaryDecoder.prototype.getBuffer = function() {\n            return this.bytes_;\n        }),\n        (jspb.BinaryDecoder.prototype.setBlock = function(e, t, r) {\n            (this.bytes_ = jspb.utils.byteSourceToUint8Array(e)),\n                (this.start_ = void 0 !== t ? t : 0),\n                (this.end_ = void 0 !== r ? this.start_ + r : this.bytes_.length),\n                (this.cursor_ = this.start_);\n        }),\n        (jspb.BinaryDecoder.prototype.getEnd = function() {\n            return this.end_;\n        }),\n        (jspb.BinaryDecoder.prototype.setEnd = function(e) {\n            this.end_ = e;\n        }),\n        (jspb.BinaryDecoder.prototype.reset = function() {\n            this.cursor_ = this.start_;\n        }),\n        (jspb.BinaryDecoder.prototype.getCursor = function() {\n            return this.cursor_;\n        }),\n        (jspb.BinaryDecoder.prototype.setCursor = function(e) {\n            this.cursor_ = e;\n        }),\n        (jspb.BinaryDecoder.prototype.advance = function(e) {\n            (this.cursor_ += e), jspb.asserts.assert(this.cursor_ <= this.end_);\n        }),\n        (jspb.BinaryDecoder.prototype.atEnd = function() {\n            return this.cursor_ == this.end_;\n        }),\n        (jspb.BinaryDecoder.prototype.pastEnd = function() {\n            return this.cursor_ > this.end_;\n        }),\n        (jspb.BinaryDecoder.prototype.getError = function() {\n            return this.error_ || 0 > this.cursor_ || this.cursor_ > this.end_;\n        }),\n        (jspb.BinaryDecoder.prototype.readSplitVarint64 = function(e) {\n            for (var t = 128, r = 0, o = 0, i = 0; 4 > i && 128 <= t; i++)\n                r |= (127 & (t = this.bytes_[this.cursor_++])) << (7 * i);\n            if (\n                (128 <= t &&\n                    ((r |= (127 & (t = this.bytes_[this.cursor_++])) << 28), (o |= (127 & t) >> 4)),\n                128 <= t)\n            )\n                for (i = 0; 5 > i && 128 <= t; i++)\n                    o |= (127 & (t = this.bytes_[this.cursor_++])) << (7 * i + 3);\n            if (128 > t) return e(r >>> 0, o >>> 0);\n            jspb.asserts.fail('Failed to read varint, encoding is invalid.'), (this.error_ = !0);\n        }),\n        (jspb.BinaryDecoder.prototype.readSplitZigzagVarint64 = function(e) {\n            return this.readSplitVarint64(function(t, r) {\n                return jspb.utils.fromZigzag64(t, r, e);\n            });\n        }),\n        (jspb.BinaryDecoder.prototype.readSplitFixed64 = function(e) {\n            var t = this.bytes_,\n                r = this.cursor_;\n            this.cursor_ += 8;\n            for (var o = 0, i = 0, a = r + 7; a >= r; a--)\n                (o = (o << 8) | t[a]), (i = (i << 8) | t[a + 4]);\n            return e(o, i);\n        }),\n        (jspb.BinaryDecoder.prototype.skipVarint = function() {\n            for (; 128 & this.bytes_[this.cursor_]; ) this.cursor_++;\n            this.cursor_++;\n        }),\n        (jspb.BinaryDecoder.prototype.unskipVarint = function(e) {\n            for (; 128 < e; ) this.cursor_--, (e >>>= 7);\n            this.cursor_--;\n        }),\n        (jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() {\n            var e = this.bytes_,\n                t = e[this.cursor_ + 0],\n                r = 127 & t;\n            return 128 > t\n                ? ((this.cursor_ += 1), jspb.asserts.assert(this.cursor_ <= this.end_), r)\n                : ((r |= (127 & (t = e[this.cursor_ + 1])) << 7),\n                  128 > t\n                      ? ((this.cursor_ += 2), jspb.asserts.assert(this.cursor_ <= this.end_), r)\n                      : ((r |= (127 & (t = e[this.cursor_ + 2])) << 14),\n                        128 > t\n                            ? ((this.cursor_ += 3),\n                              jspb.asserts.assert(this.cursor_ <= this.end_),\n                              r)\n                            : ((r |= (127 & (t = e[this.cursor_ + 3])) << 21),\n                              128 > t\n                                  ? ((this.cursor_ += 4),\n                                    jspb.asserts.assert(this.cursor_ <= this.end_),\n                                    r)\n                                  : ((r |= (15 & (t = e[this.cursor_ + 4])) << 28),\n                                    128 > t\n                                        ? ((this.cursor_ += 5),\n                                          jspb.asserts.assert(this.cursor_ <= this.end_),\n                                          r >>> 0)\n                                        : ((this.cursor_ += 5),\n                                          128 <= e[this.cursor_++] &&\n                                              128 <= e[this.cursor_++] &&\n                                              128 <= e[this.cursor_++] &&\n                                              128 <= e[this.cursor_++] &&\n                                              128 <= e[this.cursor_++] &&\n                                              jspb.asserts.assert(!1),\n                                          jspb.asserts.assert(this.cursor_ <= this.end_),\n                                          r)))));\n        }),\n        (jspb.BinaryDecoder.prototype.readSignedVarint32 = function() {\n            return ~~this.readUnsignedVarint32();\n        }),\n        (jspb.BinaryDecoder.prototype.readUnsignedVarint32String = function() {\n            return this.readUnsignedVarint32().toString();\n        }),\n        (jspb.BinaryDecoder.prototype.readSignedVarint32String = function() {\n            return this.readSignedVarint32().toString();\n        }),\n        (jspb.BinaryDecoder.prototype.readZigzagVarint32 = function() {\n            var e = this.readUnsignedVarint32();\n            return (e >>> 1) ^ -(1 & e);\n        }),\n        (jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() {\n            return this.readSplitVarint64(jspb.utils.joinUint64);\n        }),\n        (jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() {\n            return this.readSplitVarint64(jspb.utils.joinUnsignedDecimalString);\n        }),\n        (jspb.BinaryDecoder.prototype.readSignedVarint64 = function() {\n            return this.readSplitVarint64(jspb.utils.joinInt64);\n        }),\n        (jspb.BinaryDecoder.prototype.readSignedVarint64String = function() {\n            return this.readSplitVarint64(jspb.utils.joinSignedDecimalString);\n        }),\n        (jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() {\n            return this.readSplitVarint64(jspb.utils.joinZigzag64);\n        }),\n        (jspb.BinaryDecoder.prototype.readZigzagVarintHash64 = function() {\n            return this.readSplitZigzagVarint64(jspb.utils.joinHash64);\n        }),\n        (jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() {\n            return this.readSplitZigzagVarint64(jspb.utils.joinSignedDecimalString);\n        }),\n        (jspb.BinaryDecoder.prototype.readUint8 = function() {\n            var e = this.bytes_[this.cursor_ + 0];\n            return (this.cursor_ += 1), jspb.asserts.assert(this.cursor_ <= this.end_), e;\n        }),\n        (jspb.BinaryDecoder.prototype.readUint16 = function() {\n            var e = this.bytes_[this.cursor_ + 0],\n                t = this.bytes_[this.cursor_ + 1];\n            return (\n                (this.cursor_ += 2),\n                jspb.asserts.assert(this.cursor_ <= this.end_),\n                (e << 0) | (t << 8)\n            );\n        }),\n        (jspb.BinaryDecoder.prototype.readUint32 = function() {\n            var e = this.bytes_[this.cursor_ + 0],\n                t = this.bytes_[this.cursor_ + 1],\n                r = this.bytes_[this.cursor_ + 2],\n                o = this.bytes_[this.cursor_ + 3];\n            return (\n                (this.cursor_ += 4),\n                jspb.asserts.assert(this.cursor_ <= this.end_),\n                ((e << 0) | (t << 8) | (r << 16) | (o << 24)) >>> 0\n            );\n        }),\n        (jspb.BinaryDecoder.prototype.readUint64 = function() {\n            var e = this.readUint32(),\n                t = this.readUint32();\n            return jspb.utils.joinUint64(e, t);\n        }),\n        (jspb.BinaryDecoder.prototype.readUint64String = function() {\n            var e = this.readUint32(),\n                t = this.readUint32();\n            return jspb.utils.joinUnsignedDecimalString(e, t);\n        }),\n        (jspb.BinaryDecoder.prototype.readInt8 = function() {\n            var e = this.bytes_[this.cursor_ + 0];\n            return (\n                (this.cursor_ += 1), jspb.asserts.assert(this.cursor_ <= this.end_), (e << 24) >> 24\n            );\n        }),\n        (jspb.BinaryDecoder.prototype.readInt16 = function() {\n            var e = this.bytes_[this.cursor_ + 0],\n                t = this.bytes_[this.cursor_ + 1];\n            return (\n                (this.cursor_ += 2),\n                jspb.asserts.assert(this.cursor_ <= this.end_),\n                (((e << 0) | (t << 8)) << 16) >> 16\n            );\n        }),\n        (jspb.BinaryDecoder.prototype.readInt32 = function() {\n            var e = this.bytes_[this.cursor_ + 0],\n                t = this.bytes_[this.cursor_ + 1],\n                r = this.bytes_[this.cursor_ + 2],\n                o = this.bytes_[this.cursor_ + 3];\n            return (\n                (this.cursor_ += 4),\n                jspb.asserts.assert(this.cursor_ <= this.end_),\n                (e << 0) | (t << 8) | (r << 16) | (o << 24)\n            );\n        }),\n        (jspb.BinaryDecoder.prototype.readInt64 = function() {\n            var e = this.readUint32(),\n                t = this.readUint32();\n            return jspb.utils.joinInt64(e, t);\n        }),\n        (jspb.BinaryDecoder.prototype.readInt64String = function() {\n            var e = this.readUint32(),\n                t = this.readUint32();\n            return jspb.utils.joinSignedDecimalString(e, t);\n        }),\n        (jspb.BinaryDecoder.prototype.readFloat = function() {\n            var e = this.readUint32();\n            return jspb.utils.joinFloat32(e, 0);\n        }),\n        (jspb.BinaryDecoder.prototype.readDouble = function() {\n            var e = this.readUint32(),\n                t = this.readUint32();\n            return jspb.utils.joinFloat64(e, t);\n        }),\n        (jspb.BinaryDecoder.prototype.readBool = function() {\n            return !!this.bytes_[this.cursor_++];\n        }),\n        (jspb.BinaryDecoder.prototype.readEnum = function() {\n            return this.readSignedVarint32();\n        }),\n        (jspb.BinaryDecoder.prototype.readString = function(e) {\n            var t = this.bytes_,\n                r = this.cursor_;\n            e = r + e;\n            for (var o = [], i = ''; r < e; ) {\n                var a = t[r++];\n                if (128 > a) o.push(a);\n                else {\n                    if (192 > a) continue;\n                    if (224 > a) {\n                        var n = t[r++];\n                        o.push(((31 & a) << 6) | (63 & n));\n                    } else if (240 > a) {\n                        n = t[r++];\n                        var s = t[r++];\n                        o.push(((15 & a) << 12) | ((63 & n) << 6) | (63 & s));\n                    } else if (248 > a) {\n                        (a =\n                            ((7 & a) << 18) |\n                            ((63 & (n = t[r++])) << 12) |\n                            ((63 & (s = t[r++])) << 6) |\n                            (63 & t[r++])),\n                            (a -= 65536),\n                            o.push(55296 + ((a >> 10) & 1023), 56320 + (1023 & a));\n                    }\n                }\n                8192 <= o.length && ((i += String.fromCharCode.apply(null, o)), (o.length = 0));\n            }\n            return (i += goog.crypt.byteArrayToString(o)), (this.cursor_ = r), i;\n        }),\n        (jspb.BinaryDecoder.prototype.readStringWithLength = function() {\n            var e = this.readUnsignedVarint32();\n            return this.readString(e);\n        }),\n        (jspb.BinaryDecoder.prototype.readBytes = function(e) {\n            if (0 > e || this.cursor_ + e > this.bytes_.length)\n                return (\n                    (this.error_ = !0), jspb.asserts.fail('Invalid byte length!'), new Uint8Array(0)\n                );\n            var t = this.bytes_.subarray(this.cursor_, this.cursor_ + e);\n            return (this.cursor_ += e), jspb.asserts.assert(this.cursor_ <= this.end_), t;\n        }),\n        (jspb.BinaryDecoder.prototype.readVarintHash64 = function() {\n            return this.readSplitVarint64(jspb.utils.joinHash64);\n        }),\n        (jspb.BinaryDecoder.prototype.readFixedHash64 = function() {\n            var e = this.bytes_,\n                t = this.cursor_,\n                r = e[t + 0],\n                o = e[t + 1],\n                i = e[t + 2],\n                a = e[t + 3],\n                n = e[t + 4],\n                s = e[t + 5],\n                p = e[t + 6];\n            return (e = e[t + 7]), (this.cursor_ += 8), String.fromCharCode(r, o, i, a, n, s, p, e);\n        }),\n        (jspb.BinaryReader = function(e, t, r) {\n            (this.decoder_ = jspb.BinaryDecoder.alloc(e, t, r)),\n                (this.fieldCursor_ = this.decoder_.getCursor()),\n                (this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER),\n                (this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID),\n                (this.error_ = !1),\n                (this.readCallbacks_ = null);\n        }),\n        (jspb.BinaryReader.instanceCache_ = []),\n        (jspb.BinaryReader.alloc = function(e, t, r) {\n            if (jspb.BinaryReader.instanceCache_.length) {\n                var o = jspb.BinaryReader.instanceCache_.pop();\n                return e && o.decoder_.setBlock(e, t, r), o;\n            }\n            return new jspb.BinaryReader(e, t, r);\n        }),\n        (jspb.BinaryReader.prototype.alloc = jspb.BinaryReader.alloc),\n        (jspb.BinaryReader.prototype.free = function() {\n            this.decoder_.clear(),\n                (this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER),\n                (this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID),\n                (this.error_ = !1),\n                (this.readCallbacks_ = null),\n                100 > jspb.BinaryReader.instanceCache_.length &&\n                    jspb.BinaryReader.instanceCache_.push(this);\n        }),\n        (jspb.BinaryReader.prototype.getFieldCursor = function() {\n            return this.fieldCursor_;\n        }),\n        (jspb.BinaryReader.prototype.getCursor = function() {\n            return this.decoder_.getCursor();\n        }),\n        (jspb.BinaryReader.prototype.getBuffer = function() {\n            return this.decoder_.getBuffer();\n        }),\n        (jspb.BinaryReader.prototype.getFieldNumber = function() {\n            return this.nextField_;\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'getFieldNumber',\n            jspb.BinaryReader.prototype.getFieldNumber\n        ),\n        (jspb.BinaryReader.prototype.getWireType = function() {\n            return this.nextWireType_;\n        }),\n        (jspb.BinaryReader.prototype.isDelimited = function() {\n            return this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED;\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'isDelimited',\n            jspb.BinaryReader.prototype.isDelimited\n        ),\n        (jspb.BinaryReader.prototype.isEndGroup = function() {\n            return this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP;\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'isEndGroup',\n            jspb.BinaryReader.prototype.isEndGroup\n        ),\n        (jspb.BinaryReader.prototype.getError = function() {\n            return this.error_ || this.decoder_.getError();\n        }),\n        (jspb.BinaryReader.prototype.setBlock = function(e, t, r) {\n            this.decoder_.setBlock(e, t, r),\n                (this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER),\n                (this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID);\n        }),\n        (jspb.BinaryReader.prototype.reset = function() {\n            this.decoder_.reset(),\n                (this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER),\n                (this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID);\n        }),\n        (jspb.BinaryReader.prototype.advance = function(e) {\n            this.decoder_.advance(e);\n        }),\n        (jspb.BinaryReader.prototype.nextField = function() {\n            if (this.decoder_.atEnd()) return !1;\n            if (this.getError()) return jspb.asserts.fail('Decoder hit an error'), !1;\n            this.fieldCursor_ = this.decoder_.getCursor();\n            var e = this.decoder_.readUnsignedVarint32(),\n                t = e >>> 3;\n            return (e &= 7) != jspb.BinaryConstants.WireType.VARINT &&\n                e != jspb.BinaryConstants.WireType.FIXED32 &&\n                e != jspb.BinaryConstants.WireType.FIXED64 &&\n                e != jspb.BinaryConstants.WireType.DELIMITED &&\n                e != jspb.BinaryConstants.WireType.START_GROUP &&\n                e != jspb.BinaryConstants.WireType.END_GROUP\n                ? (jspb.asserts.fail(\n                      'Invalid wire type: %s (at position %s)',\n                      e,\n                      this.fieldCursor_\n                  ),\n                  (this.error_ = !0),\n                  !1)\n                : ((this.nextField_ = t), (this.nextWireType_ = e), !0);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'nextField',\n            jspb.BinaryReader.prototype.nextField\n        ),\n        (jspb.BinaryReader.prototype.unskipHeader = function() {\n            this.decoder_.unskipVarint((this.nextField_ << 3) | this.nextWireType_);\n        }),\n        (jspb.BinaryReader.prototype.skipMatchingFields = function() {\n            var e = this.nextField_;\n            for (this.unskipHeader(); this.nextField() && this.getFieldNumber() == e; )\n                this.skipField();\n            this.decoder_.atEnd() || this.unskipHeader();\n        }),\n        (jspb.BinaryReader.prototype.skipVarintField = function() {\n            this.nextWireType_ != jspb.BinaryConstants.WireType.VARINT\n                ? (jspb.asserts.fail('Invalid wire type for skipVarintField'), this.skipField())\n                : this.decoder_.skipVarint();\n        }),\n        (jspb.BinaryReader.prototype.skipDelimitedField = function() {\n            if (this.nextWireType_ != jspb.BinaryConstants.WireType.DELIMITED)\n                jspb.asserts.fail('Invalid wire type for skipDelimitedField'), this.skipField();\n            else {\n                var e = this.decoder_.readUnsignedVarint32();\n                this.decoder_.advance(e);\n            }\n        }),\n        (jspb.BinaryReader.prototype.skipFixed32Field = function() {\n            this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED32\n                ? (jspb.asserts.fail('Invalid wire type for skipFixed32Field'), this.skipField())\n                : this.decoder_.advance(4);\n        }),\n        (jspb.BinaryReader.prototype.skipFixed64Field = function() {\n            this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED64\n                ? (jspb.asserts.fail('Invalid wire type for skipFixed64Field'), this.skipField())\n                : this.decoder_.advance(8);\n        }),\n        (jspb.BinaryReader.prototype.skipGroup = function() {\n            for (var e = this.nextField_; ; ) {\n                if (!this.nextField()) {\n                    jspb.asserts.fail('Unmatched start-group tag: stream EOF'), (this.error_ = !0);\n                    break;\n                }\n                if (this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP) {\n                    this.nextField_ != e &&\n                        (jspb.asserts.fail('Unmatched end-group tag'), (this.error_ = !0));\n                    break;\n                }\n                this.skipField();\n            }\n        }),\n        (jspb.BinaryReader.prototype.skipField = function() {\n            switch (this.nextWireType_) {\n                case jspb.BinaryConstants.WireType.VARINT:\n                    this.skipVarintField();\n                    break;\n                case jspb.BinaryConstants.WireType.FIXED64:\n                    this.skipFixed64Field();\n                    break;\n                case jspb.BinaryConstants.WireType.DELIMITED:\n                    this.skipDelimitedField();\n                    break;\n                case jspb.BinaryConstants.WireType.FIXED32:\n                    this.skipFixed32Field();\n                    break;\n                case jspb.BinaryConstants.WireType.START_GROUP:\n                    this.skipGroup();\n                    break;\n                default:\n                    jspb.asserts.fail('Invalid wire encoding for field.');\n            }\n        }),\n        (jspb.BinaryReader.prototype.registerReadCallback = function(e, t) {\n            null === this.readCallbacks_ && (this.readCallbacks_ = {}),\n                jspb.asserts.assert(!this.readCallbacks_[e]),\n                (this.readCallbacks_[e] = t);\n        }),\n        (jspb.BinaryReader.prototype.runReadCallback = function(e) {\n            return (\n                jspb.asserts.assert(null !== this.readCallbacks_),\n                (e = this.readCallbacks_[e]),\n                jspb.asserts.assert(e),\n                e(this)\n            );\n        }),\n        (jspb.BinaryReader.prototype.readAny = function(e) {\n            this.nextWireType_ = jspb.BinaryConstants.FieldTypeToWireType(e);\n            var t = jspb.BinaryConstants.FieldType;\n            switch (e) {\n                case t.DOUBLE:\n                    return this.readDouble();\n                case t.FLOAT:\n                    return this.readFloat();\n                case t.INT64:\n                    return this.readInt64();\n                case t.UINT64:\n                    return this.readUint64();\n                case t.INT32:\n                    return this.readInt32();\n                case t.FIXED64:\n                    return this.readFixed64();\n                case t.FIXED32:\n                    return this.readFixed32();\n                case t.BOOL:\n                    return this.readBool();\n                case t.STRING:\n                    return this.readString();\n                case t.GROUP:\n                    jspb.asserts.fail('Group field type not supported in readAny()');\n                case t.MESSAGE:\n                    jspb.asserts.fail('Message field type not supported in readAny()');\n                case t.BYTES:\n                    return this.readBytes();\n                case t.UINT32:\n                    return this.readUint32();\n                case t.ENUM:\n                    return this.readEnum();\n                case t.SFIXED32:\n                    return this.readSfixed32();\n                case t.SFIXED64:\n                    return this.readSfixed64();\n                case t.SINT32:\n                    return this.readSint32();\n                case t.SINT64:\n                    return this.readSint64();\n                case t.FHASH64:\n                    return this.readFixedHash64();\n                case t.VHASH64:\n                    return this.readVarintHash64();\n                default:\n                    jspb.asserts.fail('Invalid field type in readAny()');\n            }\n            return 0;\n        }),\n        (jspb.BinaryReader.prototype.readMessage = function(e, t) {\n            jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);\n            var r = this.decoder_.getEnd(),\n                o = this.decoder_.readUnsignedVarint32();\n            (o = this.decoder_.getCursor() + o),\n                this.decoder_.setEnd(o),\n                t(e, this),\n                this.decoder_.setCursor(o),\n                this.decoder_.setEnd(r);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readMessage',\n            jspb.BinaryReader.prototype.readMessage\n        ),\n        (jspb.BinaryReader.prototype.readGroup = function(e, t, r) {\n            jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.START_GROUP),\n                jspb.asserts.assert(this.nextField_ == e),\n                r(t, this),\n                this.error_ ||\n                    this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP ||\n                    (jspb.asserts.fail('Group submessage did not end with an END_GROUP tag'),\n                    (this.error_ = !0));\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readGroup',\n            jspb.BinaryReader.prototype.readGroup\n        ),\n        (jspb.BinaryReader.prototype.getFieldDecoder = function() {\n            jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);\n            var e = this.decoder_.readUnsignedVarint32(),\n                t = this.decoder_.getCursor(),\n                r = t + e;\n            return (\n                (e = jspb.BinaryDecoder.alloc(this.decoder_.getBuffer(), t, e)),\n                this.decoder_.setCursor(r),\n                e\n            );\n        }),\n        (jspb.BinaryReader.prototype.readInt32 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readSignedVarint32()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readInt32',\n            jspb.BinaryReader.prototype.readInt32\n        ),\n        (jspb.BinaryReader.prototype.readInt32String = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readSignedVarint32String()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readInt64 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readSignedVarint64()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readInt64',\n            jspb.BinaryReader.prototype.readInt64\n        ),\n        (jspb.BinaryReader.prototype.readInt64String = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readSignedVarint64String()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readUint32 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readUnsignedVarint32()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readUint32',\n            jspb.BinaryReader.prototype.readUint32\n        ),\n        (jspb.BinaryReader.prototype.readUint32String = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readUnsignedVarint32String()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readUint64 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readUnsignedVarint64()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readUint64',\n            jspb.BinaryReader.prototype.readUint64\n        ),\n        (jspb.BinaryReader.prototype.readUint64String = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readUnsignedVarint64String()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readSint32 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readZigzagVarint32()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readSint32',\n            jspb.BinaryReader.prototype.readSint32\n        ),\n        (jspb.BinaryReader.prototype.readSint64 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readZigzagVarint64()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readSint64',\n            jspb.BinaryReader.prototype.readSint64\n        ),\n        (jspb.BinaryReader.prototype.readSint64String = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readZigzagVarint64String()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readFixed32 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32),\n                this.decoder_.readUint32()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readFixed32',\n            jspb.BinaryReader.prototype.readFixed32\n        ),\n        (jspb.BinaryReader.prototype.readFixed64 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64),\n                this.decoder_.readUint64()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readFixed64',\n            jspb.BinaryReader.prototype.readFixed64\n        ),\n        (jspb.BinaryReader.prototype.readFixed64String = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64),\n                this.decoder_.readUint64String()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readSfixed32 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32),\n                this.decoder_.readInt32()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readSfixed32',\n            jspb.BinaryReader.prototype.readSfixed32\n        ),\n        (jspb.BinaryReader.prototype.readSfixed32String = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32),\n                this.decoder_.readInt32().toString()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readSfixed64 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64),\n                this.decoder_.readInt64()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readSfixed64',\n            jspb.BinaryReader.prototype.readSfixed64\n        ),\n        (jspb.BinaryReader.prototype.readSfixed64String = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64),\n                this.decoder_.readInt64String()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readFloat = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32),\n                this.decoder_.readFloat()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readFloat',\n            jspb.BinaryReader.prototype.readFloat\n        ),\n        (jspb.BinaryReader.prototype.readDouble = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64),\n                this.decoder_.readDouble()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readDouble',\n            jspb.BinaryReader.prototype.readDouble\n        ),\n        (jspb.BinaryReader.prototype.readBool = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                !!this.decoder_.readUnsignedVarint32()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readBool',\n            jspb.BinaryReader.prototype.readBool\n        ),\n        (jspb.BinaryReader.prototype.readEnum = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readSignedVarint64()\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readEnum',\n            jspb.BinaryReader.prototype.readEnum\n        ),\n        (jspb.BinaryReader.prototype.readString = function() {\n            jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);\n            var e = this.decoder_.readUnsignedVarint32();\n            return this.decoder_.readString(e);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readString',\n            jspb.BinaryReader.prototype.readString\n        ),\n        (jspb.BinaryReader.prototype.readBytes = function() {\n            jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);\n            var e = this.decoder_.readUnsignedVarint32();\n            return this.decoder_.readBytes(e);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readBytes',\n            jspb.BinaryReader.prototype.readBytes\n        ),\n        (jspb.BinaryReader.prototype.readVarintHash64 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readVarintHash64()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readSintHash64 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readZigzagVarintHash64()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readSplitVarint64 = function(e) {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readSplitVarint64(e)\n            );\n        }),\n        (jspb.BinaryReader.prototype.readSplitZigzagVarint64 = function(e) {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT),\n                this.decoder_.readSplitVarint64(function(t, r) {\n                    return jspb.utils.fromZigzag64(t, r, e);\n                })\n            );\n        }),\n        (jspb.BinaryReader.prototype.readFixedHash64 = function() {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64),\n                this.decoder_.readFixedHash64()\n            );\n        }),\n        (jspb.BinaryReader.prototype.readSplitFixed64 = function(e) {\n            return (\n                jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64),\n                this.decoder_.readSplitFixed64(e)\n            );\n        }),\n        (jspb.BinaryReader.prototype.readPackedField_ = function(e) {\n            jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);\n            var t = this.decoder_.readUnsignedVarint32();\n            t = this.decoder_.getCursor() + t;\n            for (var r = []; this.decoder_.getCursor() < t; ) r.push(e.call(this.decoder_));\n            return r;\n        }),\n        (jspb.BinaryReader.prototype.readPackedInt32 = function() {\n            return this.readPackedField_(this.decoder_.readSignedVarint32);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedInt32',\n            jspb.BinaryReader.prototype.readPackedInt32\n        ),\n        (jspb.BinaryReader.prototype.readPackedInt32String = function() {\n            return this.readPackedField_(this.decoder_.readSignedVarint32String);\n        }),\n        (jspb.BinaryReader.prototype.readPackedInt64 = function() {\n            return this.readPackedField_(this.decoder_.readSignedVarint64);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedInt64',\n            jspb.BinaryReader.prototype.readPackedInt64\n        ),\n        (jspb.BinaryReader.prototype.readPackedInt64String = function() {\n            return this.readPackedField_(this.decoder_.readSignedVarint64String);\n        }),\n        (jspb.BinaryReader.prototype.readPackedUint32 = function() {\n            return this.readPackedField_(this.decoder_.readUnsignedVarint32);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedUint32',\n            jspb.BinaryReader.prototype.readPackedUint32\n        ),\n        (jspb.BinaryReader.prototype.readPackedUint32String = function() {\n            return this.readPackedField_(this.decoder_.readUnsignedVarint32String);\n        }),\n        (jspb.BinaryReader.prototype.readPackedUint64 = function() {\n            return this.readPackedField_(this.decoder_.readUnsignedVarint64);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedUint64',\n            jspb.BinaryReader.prototype.readPackedUint64\n        ),\n        (jspb.BinaryReader.prototype.readPackedUint64String = function() {\n            return this.readPackedField_(this.decoder_.readUnsignedVarint64String);\n        }),\n        (jspb.BinaryReader.prototype.readPackedSint32 = function() {\n            return this.readPackedField_(this.decoder_.readZigzagVarint32);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedSint32',\n            jspb.BinaryReader.prototype.readPackedSint32\n        ),\n        (jspb.BinaryReader.prototype.readPackedSint64 = function() {\n            return this.readPackedField_(this.decoder_.readZigzagVarint64);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedSint64',\n            jspb.BinaryReader.prototype.readPackedSint64\n        ),\n        (jspb.BinaryReader.prototype.readPackedSint64String = function() {\n            return this.readPackedField_(this.decoder_.readZigzagVarint64String);\n        }),\n        (jspb.BinaryReader.prototype.readPackedFixed32 = function() {\n            return this.readPackedField_(this.decoder_.readUint32);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedFixed32',\n            jspb.BinaryReader.prototype.readPackedFixed32\n        ),\n        (jspb.BinaryReader.prototype.readPackedFixed64 = function() {\n            return this.readPackedField_(this.decoder_.readUint64);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedFixed64',\n            jspb.BinaryReader.prototype.readPackedFixed64\n        ),\n        (jspb.BinaryReader.prototype.readPackedFixed64String = function() {\n            return this.readPackedField_(this.decoder_.readUint64String);\n        }),\n        (jspb.BinaryReader.prototype.readPackedSfixed32 = function() {\n            return this.readPackedField_(this.decoder_.readInt32);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedSfixed32',\n            jspb.BinaryReader.prototype.readPackedSfixed32\n        ),\n        (jspb.BinaryReader.prototype.readPackedSfixed64 = function() {\n            return this.readPackedField_(this.decoder_.readInt64);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedSfixed64',\n            jspb.BinaryReader.prototype.readPackedSfixed64\n        ),\n        (jspb.BinaryReader.prototype.readPackedSfixed64String = function() {\n            return this.readPackedField_(this.decoder_.readInt64String);\n        }),\n        (jspb.BinaryReader.prototype.readPackedFloat = function() {\n            return this.readPackedField_(this.decoder_.readFloat);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedFloat',\n            jspb.BinaryReader.prototype.readPackedFloat\n        ),\n        (jspb.BinaryReader.prototype.readPackedDouble = function() {\n            return this.readPackedField_(this.decoder_.readDouble);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedDouble',\n            jspb.BinaryReader.prototype.readPackedDouble\n        ),\n        (jspb.BinaryReader.prototype.readPackedBool = function() {\n            return this.readPackedField_(this.decoder_.readBool);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedBool',\n            jspb.BinaryReader.prototype.readPackedBool\n        ),\n        (jspb.BinaryReader.prototype.readPackedEnum = function() {\n            return this.readPackedField_(this.decoder_.readEnum);\n        }),\n        goog.exportProperty(\n            jspb.BinaryReader.prototype,\n            'readPackedEnum',\n            jspb.BinaryReader.prototype.readPackedEnum\n        ),\n        (jspb.BinaryReader.prototype.readPackedVarintHash64 = function() {\n            return this.readPackedField_(this.decoder_.readVarintHash64);\n        }),\n        (jspb.BinaryReader.prototype.readPackedFixedHash64 = function() {\n            return this.readPackedField_(this.decoder_.readFixedHash64);\n        }),\n        (jspb.BinaryEncoder = function() {\n            this.buffer_ = [];\n        }),\n        (jspb.BinaryEncoder.prototype.length = function() {\n            return this.buffer_.length;\n        }),\n        (jspb.BinaryEncoder.prototype.end = function() {\n            var e = this.buffer_;\n            return (this.buffer_ = []), e;\n        }),\n        (jspb.BinaryEncoder.prototype.writeSplitVarint64 = function(e, t) {\n            for (\n                jspb.asserts.assert(e == Math.floor(e)),\n                    jspb.asserts.assert(t == Math.floor(t)),\n                    jspb.asserts.assert(0 <= e && e < jspb.BinaryConstants.TWO_TO_32),\n                    jspb.asserts.assert(0 <= t && t < jspb.BinaryConstants.TWO_TO_32);\n                0 < t || 127 < e;\n\n            )\n                this.buffer_.push((127 & e) | 128), (e = ((e >>> 7) | (t << 25)) >>> 0), (t >>>= 7);\n            this.buffer_.push(e);\n        }),\n        (jspb.BinaryEncoder.prototype.writeSplitFixed64 = function(e, t) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(t == Math.floor(t)),\n                jspb.asserts.assert(0 <= e && e < jspb.BinaryConstants.TWO_TO_32),\n                jspb.asserts.assert(0 <= t && t < jspb.BinaryConstants.TWO_TO_32),\n                this.writeUint32(e),\n                this.writeUint32(t);\n        }),\n        (jspb.BinaryEncoder.prototype.writeUnsignedVarint32 = function(e) {\n            for (\n                jspb.asserts.assert(e == Math.floor(e)),\n                    jspb.asserts.assert(0 <= e && e < jspb.BinaryConstants.TWO_TO_32);\n                127 < e;\n\n            )\n                this.buffer_.push((127 & e) | 128), (e >>>= 7);\n            this.buffer_.push(e);\n        }),\n        (jspb.BinaryEncoder.prototype.writeSignedVarint32 = function(e) {\n            if (\n                (jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(\n                    e >= -jspb.BinaryConstants.TWO_TO_31 && e < jspb.BinaryConstants.TWO_TO_31\n                ),\n                0 <= e)\n            )\n                this.writeUnsignedVarint32(e);\n            else {\n                for (var t = 0; 9 > t; t++) this.buffer_.push((127 & e) | 128), (e >>= 7);\n                this.buffer_.push(1);\n            }\n        }),\n        (jspb.BinaryEncoder.prototype.writeUnsignedVarint64 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(0 <= e && e < jspb.BinaryConstants.TWO_TO_64),\n                jspb.utils.splitInt64(e),\n                this.writeSplitVarint64(jspb.utils.split64Low, jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeSignedVarint64 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(\n                    e >= -jspb.BinaryConstants.TWO_TO_63 && e < jspb.BinaryConstants.TWO_TO_63\n                ),\n                jspb.utils.splitInt64(e),\n                this.writeSplitVarint64(jspb.utils.split64Low, jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeZigzagVarint32 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(\n                    e >= -jspb.BinaryConstants.TWO_TO_31 && e < jspb.BinaryConstants.TWO_TO_31\n                ),\n                this.writeUnsignedVarint32(((e << 1) ^ (e >> 31)) >>> 0);\n        }),\n        (jspb.BinaryEncoder.prototype.writeZigzagVarint64 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(\n                    e >= -jspb.BinaryConstants.TWO_TO_63 && e < jspb.BinaryConstants.TWO_TO_63\n                ),\n                jspb.utils.splitZigzag64(e),\n                this.writeSplitVarint64(jspb.utils.split64Low, jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeZigzagVarint64String = function(e) {\n            this.writeZigzagVarintHash64(jspb.utils.decimalStringToHash64(e));\n        }),\n        (jspb.BinaryEncoder.prototype.writeZigzagVarintHash64 = function(e) {\n            var t = this;\n            jspb.utils.splitHash64(e),\n                jspb.utils.toZigzag64(jspb.utils.split64Low, jspb.utils.split64High, function(\n                    e,\n                    r\n                ) {\n                    t.writeSplitVarint64(e >>> 0, r >>> 0);\n                });\n        }),\n        (jspb.BinaryEncoder.prototype.writeUint8 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(0 <= e && 256 > e),\n                this.buffer_.push((e >>> 0) & 255);\n        }),\n        (jspb.BinaryEncoder.prototype.writeUint16 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(0 <= e && 65536 > e),\n                this.buffer_.push((e >>> 0) & 255),\n                this.buffer_.push((e >>> 8) & 255);\n        }),\n        (jspb.BinaryEncoder.prototype.writeUint32 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(0 <= e && e < jspb.BinaryConstants.TWO_TO_32),\n                this.buffer_.push((e >>> 0) & 255),\n                this.buffer_.push((e >>> 8) & 255),\n                this.buffer_.push((e >>> 16) & 255),\n                this.buffer_.push((e >>> 24) & 255);\n        }),\n        (jspb.BinaryEncoder.prototype.writeUint64 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(0 <= e && e < jspb.BinaryConstants.TWO_TO_64),\n                jspb.utils.splitUint64(e),\n                this.writeUint32(jspb.utils.split64Low),\n                this.writeUint32(jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeInt8 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(-128 <= e && 128 > e),\n                this.buffer_.push((e >>> 0) & 255);\n        }),\n        (jspb.BinaryEncoder.prototype.writeInt16 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(-32768 <= e && 32768 > e),\n                this.buffer_.push((e >>> 0) & 255),\n                this.buffer_.push((e >>> 8) & 255);\n        }),\n        (jspb.BinaryEncoder.prototype.writeInt32 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(\n                    e >= -jspb.BinaryConstants.TWO_TO_31 && e < jspb.BinaryConstants.TWO_TO_31\n                ),\n                this.buffer_.push((e >>> 0) & 255),\n                this.buffer_.push((e >>> 8) & 255),\n                this.buffer_.push((e >>> 16) & 255),\n                this.buffer_.push((e >>> 24) & 255);\n        }),\n        (jspb.BinaryEncoder.prototype.writeInt64 = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(\n                    e >= -jspb.BinaryConstants.TWO_TO_63 && e < jspb.BinaryConstants.TWO_TO_63\n                ),\n                jspb.utils.splitInt64(e),\n                this.writeSplitFixed64(jspb.utils.split64Low, jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeInt64String = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(\n                    +e >= -jspb.BinaryConstants.TWO_TO_63 && +e < jspb.BinaryConstants.TWO_TO_63\n                ),\n                jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(e)),\n                this.writeSplitFixed64(jspb.utils.split64Low, jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeFloat = function(e) {\n            jspb.asserts.assert(\n                1 / 0 === e ||\n                    -1 / 0 === e ||\n                    isNaN(e) ||\n                    (e >= -jspb.BinaryConstants.FLOAT32_MAX &&\n                        e <= jspb.BinaryConstants.FLOAT32_MAX)\n            ),\n                jspb.utils.splitFloat32(e),\n                this.writeUint32(jspb.utils.split64Low);\n        }),\n        (jspb.BinaryEncoder.prototype.writeDouble = function(e) {\n            jspb.asserts.assert(\n                1 / 0 === e ||\n                    -1 / 0 === e ||\n                    isNaN(e) ||\n                    (e >= -jspb.BinaryConstants.FLOAT64_MAX &&\n                        e <= jspb.BinaryConstants.FLOAT64_MAX)\n            ),\n                jspb.utils.splitFloat64(e),\n                this.writeUint32(jspb.utils.split64Low),\n                this.writeUint32(jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeBool = function(e) {\n            jspb.asserts.assert('boolean' == typeof e || 'number' == typeof e),\n                this.buffer_.push(e ? 1 : 0);\n        }),\n        (jspb.BinaryEncoder.prototype.writeEnum = function(e) {\n            jspb.asserts.assert(e == Math.floor(e)),\n                jspb.asserts.assert(\n                    e >= -jspb.BinaryConstants.TWO_TO_31 && e < jspb.BinaryConstants.TWO_TO_31\n                ),\n                this.writeSignedVarint32(e);\n        }),\n        (jspb.BinaryEncoder.prototype.writeBytes = function(e) {\n            this.buffer_.push.apply(this.buffer_, e);\n        }),\n        (jspb.BinaryEncoder.prototype.writeVarintHash64 = function(e) {\n            jspb.utils.splitHash64(e),\n                this.writeSplitVarint64(jspb.utils.split64Low, jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeFixedHash64 = function(e) {\n            jspb.utils.splitHash64(e),\n                this.writeUint32(jspb.utils.split64Low),\n                this.writeUint32(jspb.utils.split64High);\n        }),\n        (jspb.BinaryEncoder.prototype.writeString = function(e) {\n            var t = this.buffer_.length;\n            jspb.asserts.assertString(e);\n            for (var r = 0; r < e.length; r++) {\n                var o = e.charCodeAt(r);\n                if (128 > o) this.buffer_.push(o);\n                else if (2048 > o)\n                    this.buffer_.push((o >> 6) | 192), this.buffer_.push((63 & o) | 128);\n                else if (65536 > o)\n                    if (55296 <= o && 56319 >= o && r + 1 < e.length) {\n                        var i = e.charCodeAt(r + 1);\n                        56320 <= i &&\n                            57343 >= i &&\n                            ((o = 1024 * (o - 55296) + i - 56320 + 65536),\n                            this.buffer_.push((o >> 18) | 240),\n                            this.buffer_.push(((o >> 12) & 63) | 128),\n                            this.buffer_.push(((o >> 6) & 63) | 128),\n                            this.buffer_.push((63 & o) | 128),\n                            r++);\n                    } else\n                        this.buffer_.push((o >> 12) | 224),\n                            this.buffer_.push(((o >> 6) & 63) | 128),\n                            this.buffer_.push((63 & o) | 128);\n            }\n            return this.buffer_.length - t;\n        }),\n        (jspb.arith = {}),\n        (jspb.arith.UInt64 = function(e, t) {\n            (this.lo = e), (this.hi = t);\n        }),\n        (jspb.arith.UInt64.prototype.cmp = function(e) {\n            return this.hi < e.hi || (this.hi == e.hi && this.lo < e.lo)\n                ? -1\n                : this.hi == e.hi && this.lo == e.lo\n                ? 0\n                : 1;\n        }),\n        (jspb.arith.UInt64.prototype.rightShift = function() {\n            return new jspb.arith.UInt64(\n                ((this.lo >>> 1) | ((1 & this.hi) << 31)) >>> 0,\n                (this.hi >>> 1) >>> 0\n            );\n        }),\n        (jspb.arith.UInt64.prototype.leftShift = function() {\n            return new jspb.arith.UInt64(\n                (this.lo << 1) >>> 0,\n                ((this.hi << 1) | (this.lo >>> 31)) >>> 0\n            );\n        }),\n        (jspb.arith.UInt64.prototype.msb = function() {\n            return !!(2147483648 & this.hi);\n        }),\n        (jspb.arith.UInt64.prototype.lsb = function() {\n            return !!(1 & this.lo);\n        }),\n        (jspb.arith.UInt64.prototype.zero = function() {\n            return 0 == this.lo && 0 == this.hi;\n        }),\n        (jspb.arith.UInt64.prototype.add = function(e) {\n            return new jspb.arith.UInt64(\n                (((this.lo + e.lo) & 4294967295) >>> 0) >>> 0,\n                ((((this.hi + e.hi) & 4294967295) >>> 0) +\n                    (4294967296 <= this.lo + e.lo ? 1 : 0)) >>>\n                    0\n            );\n        }),\n        (jspb.arith.UInt64.prototype.sub = function(e) {\n            return new jspb.arith.UInt64(\n                (((this.lo - e.lo) & 4294967295) >>> 0) >>> 0,\n                ((((this.hi - e.hi) & 4294967295) >>> 0) - (0 > this.lo - e.lo ? 1 : 0)) >>> 0\n            );\n        }),\n        (jspb.arith.UInt64.mul32x32 = function(e, t) {\n            var r = 65535 & e,\n                o = 65535 & t,\n                i = t >>> 16;\n            for (\n                t = r * o + 65536 * ((r * i) & 65535) + 65536 * (((e >>>= 16) * o) & 65535),\n                    r = e * i + ((r * i) >>> 16) + ((e * o) >>> 16);\n                4294967296 <= t;\n\n            )\n                (t -= 4294967296), (r += 1);\n            return new jspb.arith.UInt64(t >>> 0, r >>> 0);\n        }),\n        (jspb.arith.UInt64.prototype.mul = function(e) {\n            var t = jspb.arith.UInt64.mul32x32(this.lo, e);\n            return ((e = jspb.arith.UInt64.mul32x32(this.hi, e)).hi = e.lo), (e.lo = 0), t.add(e);\n        }),\n        (jspb.arith.UInt64.prototype.div = function(e) {\n            if (0 == e) return [];\n            var t = new jspb.arith.UInt64(0, 0),\n                r = new jspb.arith.UInt64(this.lo, this.hi);\n            e = new jspb.arith.UInt64(e, 0);\n            for (var o = new jspb.arith.UInt64(1, 0); !e.msb(); )\n                (e = e.leftShift()), (o = o.leftShift());\n            for (; !o.zero(); )\n                0 >= e.cmp(r) && ((t = t.add(o)), (r = r.sub(e))),\n                    (e = e.rightShift()),\n                    (o = o.rightShift());\n            return [t, r];\n        }),\n        (jspb.arith.UInt64.prototype.toString = function() {\n            for (var e = '', t = this; !t.zero(); ) {\n                var r = (t = t.div(10))[0];\n                (e = t[1].lo + e), (t = r);\n            }\n            return '' == e && (e = '0'), e;\n        }),\n        (jspb.arith.UInt64.fromString = function(e) {\n            for (\n                var t = new jspb.arith.UInt64(0, 0), r = new jspb.arith.UInt64(0, 0), o = 0;\n                o < e.length;\n                o++\n            ) {\n                if ('0' > e[o] || '9' < e[o]) return null;\n                var i = parseInt(e[o], 10);\n                (r.lo = i), (t = t.mul(10).add(r));\n            }\n            return t;\n        }),\n        (jspb.arith.UInt64.prototype.clone = function() {\n            return new jspb.arith.UInt64(this.lo, this.hi);\n        }),\n        (jspb.arith.Int64 = function(e, t) {\n            (this.lo = e), (this.hi = t);\n        }),\n        (jspb.arith.Int64.prototype.add = function(e) {\n            return new jspb.arith.Int64(\n                (((this.lo + e.lo) & 4294967295) >>> 0) >>> 0,\n                ((((this.hi + e.hi) & 4294967295) >>> 0) +\n                    (4294967296 <= this.lo + e.lo ? 1 : 0)) >>>\n                    0\n            );\n        }),\n        (jspb.arith.Int64.prototype.sub = function(e) {\n            return new jspb.arith.Int64(\n                (((this.lo - e.lo) & 4294967295) >>> 0) >>> 0,\n                ((((this.hi - e.hi) & 4294967295) >>> 0) - (0 > this.lo - e.lo ? 1 : 0)) >>> 0\n            );\n        }),\n        (jspb.arith.Int64.prototype.clone = function() {\n            return new jspb.arith.Int64(this.lo, this.hi);\n        }),\n        (jspb.arith.Int64.prototype.toString = function() {\n            var e = 0 != (2147483648 & this.hi),\n                t = new jspb.arith.UInt64(this.lo, this.hi);\n            return e && (t = new jspb.arith.UInt64(0, 0).sub(t)), (e ? '-' : '') + t.toString();\n        }),\n        (jspb.arith.Int64.fromString = function(e) {\n            var t = 0 < e.length && '-' == e[0];\n            return (\n                t && (e = e.substring(1)),\n                null === (e = jspb.arith.UInt64.fromString(e))\n                    ? null\n                    : (t && (e = new jspb.arith.UInt64(0, 0).sub(e)),\n                      new jspb.arith.Int64(e.lo, e.hi))\n            );\n        }),\n        (jspb.BinaryWriter = function() {\n            (this.blocks_ = []),\n                (this.totalLength_ = 0),\n                (this.encoder_ = new jspb.BinaryEncoder()),\n                (this.bookmarks_ = []);\n        }),\n        (jspb.BinaryWriter.prototype.appendUint8Array_ = function(e) {\n            var t = this.encoder_.end();\n            this.blocks_.push(t), this.blocks_.push(e), (this.totalLength_ += t.length + e.length);\n        }),\n        (jspb.BinaryWriter.prototype.beginDelimited_ = function(e) {\n            return (\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                (e = this.encoder_.end()),\n                this.blocks_.push(e),\n                (this.totalLength_ += e.length),\n                e.push(this.totalLength_),\n                e\n            );\n        }),\n        (jspb.BinaryWriter.prototype.endDelimited_ = function(e) {\n            var t = e.pop();\n            for (\n                t = this.totalLength_ + this.encoder_.length() - t, jspb.asserts.assert(0 <= t);\n                127 < t;\n\n            )\n                e.push((127 & t) | 128), (t >>>= 7), this.totalLength_++;\n            e.push(t), this.totalLength_++;\n        }),\n        (jspb.BinaryWriter.prototype.writeSerializedMessage = function(e, t, r) {\n            this.appendUint8Array_(e.subarray(t, r));\n        }),\n        (jspb.BinaryWriter.prototype.maybeWriteSerializedMessage = function(e, t, r) {\n            null != e && null != t && null != r && this.writeSerializedMessage(e, t, r);\n        }),\n        (jspb.BinaryWriter.prototype.reset = function() {\n            (this.blocks_ = []),\n                this.encoder_.end(),\n                (this.totalLength_ = 0),\n                (this.bookmarks_ = []);\n        }),\n        (jspb.BinaryWriter.prototype.getResultBuffer = function() {\n            jspb.asserts.assert(0 == this.bookmarks_.length);\n            for (\n                var e = new Uint8Array(this.totalLength_ + this.encoder_.length()),\n                    t = this.blocks_,\n                    r = t.length,\n                    o = 0,\n                    i = 0;\n                i < r;\n                i++\n            ) {\n                var a = t[i];\n                e.set(a, o), (o += a.length);\n            }\n            return (\n                (t = this.encoder_.end()),\n                e.set(t, o),\n                (o += t.length),\n                jspb.asserts.assert(o == e.length),\n                (this.blocks_ = [e]),\n                e\n            );\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'getResultBuffer',\n            jspb.BinaryWriter.prototype.getResultBuffer\n        ),\n        (jspb.BinaryWriter.prototype.getResultBase64String = function(e) {\n            return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), e);\n        }),\n        (jspb.BinaryWriter.prototype.beginSubMessage = function(e) {\n            this.bookmarks_.push(this.beginDelimited_(e));\n        }),\n        (jspb.BinaryWriter.prototype.endSubMessage = function() {\n            jspb.asserts.assert(0 <= this.bookmarks_.length),\n                this.endDelimited_(this.bookmarks_.pop());\n        }),\n        (jspb.BinaryWriter.prototype.writeFieldHeader_ = function(e, t) {\n            jspb.asserts.assert(1 <= e && e == Math.floor(e)),\n                this.encoder_.writeUnsignedVarint32(8 * e + t);\n        }),\n        (jspb.BinaryWriter.prototype.writeAny = function(e, t, r) {\n            var o = jspb.BinaryConstants.FieldType;\n            switch (e) {\n                case o.DOUBLE:\n                    this.writeDouble(t, r);\n                    break;\n                case o.FLOAT:\n                    this.writeFloat(t, r);\n                    break;\n                case o.INT64:\n                    this.writeInt64(t, r);\n                    break;\n                case o.UINT64:\n                    this.writeUint64(t, r);\n                    break;\n                case o.INT32:\n                    this.writeInt32(t, r);\n                    break;\n                case o.FIXED64:\n                    this.writeFixed64(t, r);\n                    break;\n                case o.FIXED32:\n                    this.writeFixed32(t, r);\n                    break;\n                case o.BOOL:\n                    this.writeBool(t, r);\n                    break;\n                case o.STRING:\n                    this.writeString(t, r);\n                    break;\n                case o.GROUP:\n                    jspb.asserts.fail('Group field type not supported in writeAny()');\n                    break;\n                case o.MESSAGE:\n                    jspb.asserts.fail('Message field type not supported in writeAny()');\n                    break;\n                case o.BYTES:\n                    this.writeBytes(t, r);\n                    break;\n                case o.UINT32:\n                    this.writeUint32(t, r);\n                    break;\n                case o.ENUM:\n                    this.writeEnum(t, r);\n                    break;\n                case o.SFIXED32:\n                    this.writeSfixed32(t, r);\n                    break;\n                case o.SFIXED64:\n                    this.writeSfixed64(t, r);\n                    break;\n                case o.SINT32:\n                    this.writeSint32(t, r);\n                    break;\n                case o.SINT64:\n                    this.writeSint64(t, r);\n                    break;\n                case o.FHASH64:\n                    this.writeFixedHash64(t, r);\n                    break;\n                case o.VHASH64:\n                    this.writeVarintHash64(t, r);\n                    break;\n                default:\n                    jspb.asserts.fail('Invalid field type in writeAny()');\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writeUnsignedVarint32_ = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeUnsignedVarint32(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeSignedVarint32_ = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeSignedVarint32(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeUnsignedVarint64_ = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeUnsignedVarint64(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeSignedVarint64_ = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeSignedVarint64(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeZigzagVarint32_ = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeZigzagVarint32(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeZigzagVarint64_ = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeZigzagVarint64(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeZigzagVarint64String_ = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeZigzagVarint64String(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeZigzagVarintHash64_ = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeZigzagVarintHash64(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeInt32 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(\n                    t >= -jspb.BinaryConstants.TWO_TO_31 && t < jspb.BinaryConstants.TWO_TO_31\n                ),\n                this.writeSignedVarint32_(e, t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeInt32',\n            jspb.BinaryWriter.prototype.writeInt32\n        ),\n        (jspb.BinaryWriter.prototype.writeInt32String = function(e, t) {\n            null != t &&\n                ((t = parseInt(t, 10)),\n                jspb.asserts.assert(\n                    t >= -jspb.BinaryConstants.TWO_TO_31 && t < jspb.BinaryConstants.TWO_TO_31\n                ),\n                this.writeSignedVarint32_(e, t));\n        }),\n        (jspb.BinaryWriter.prototype.writeInt64 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(\n                    t >= -jspb.BinaryConstants.TWO_TO_63 && t < jspb.BinaryConstants.TWO_TO_63\n                ),\n                this.writeSignedVarint64_(e, t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeInt64',\n            jspb.BinaryWriter.prototype.writeInt64\n        ),\n        (jspb.BinaryWriter.prototype.writeInt64String = function(e, t) {\n            null != t &&\n                ((t = jspb.arith.Int64.fromString(t)),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeSplitVarint64(t.lo, t.hi));\n        }),\n        (jspb.BinaryWriter.prototype.writeUint32 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(0 <= t && t < jspb.BinaryConstants.TWO_TO_32),\n                this.writeUnsignedVarint32_(e, t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeUint32',\n            jspb.BinaryWriter.prototype.writeUint32\n        ),\n        (jspb.BinaryWriter.prototype.writeUint32String = function(e, t) {\n            null != t &&\n                ((t = parseInt(t, 10)),\n                jspb.asserts.assert(0 <= t && t < jspb.BinaryConstants.TWO_TO_32),\n                this.writeUnsignedVarint32_(e, t));\n        }),\n        (jspb.BinaryWriter.prototype.writeUint64 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(0 <= t && t < jspb.BinaryConstants.TWO_TO_64),\n                this.writeUnsignedVarint64_(e, t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeUint64',\n            jspb.BinaryWriter.prototype.writeUint64\n        ),\n        (jspb.BinaryWriter.prototype.writeUint64String = function(e, t) {\n            null != t &&\n                ((t = jspb.arith.UInt64.fromString(t)),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeSplitVarint64(t.lo, t.hi));\n        }),\n        (jspb.BinaryWriter.prototype.writeSint32 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(\n                    t >= -jspb.BinaryConstants.TWO_TO_31 && t < jspb.BinaryConstants.TWO_TO_31\n                ),\n                this.writeZigzagVarint32_(e, t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeSint32',\n            jspb.BinaryWriter.prototype.writeSint32\n        ),\n        (jspb.BinaryWriter.prototype.writeSint64 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(\n                    t >= -jspb.BinaryConstants.TWO_TO_63 && t < jspb.BinaryConstants.TWO_TO_63\n                ),\n                this.writeZigzagVarint64_(e, t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeSint64',\n            jspb.BinaryWriter.prototype.writeSint64\n        ),\n        (jspb.BinaryWriter.prototype.writeSintHash64 = function(e, t) {\n            null != t && this.writeZigzagVarintHash64_(e, t);\n        }),\n        (jspb.BinaryWriter.prototype.writeSint64String = function(e, t) {\n            null != t && this.writeZigzagVarint64String_(e, t);\n        }),\n        (jspb.BinaryWriter.prototype.writeFixed32 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(0 <= t && t < jspb.BinaryConstants.TWO_TO_32),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED32),\n                this.encoder_.writeUint32(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeFixed32',\n            jspb.BinaryWriter.prototype.writeFixed32\n        ),\n        (jspb.BinaryWriter.prototype.writeFixed64 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(0 <= t && t < jspb.BinaryConstants.TWO_TO_64),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED64),\n                this.encoder_.writeUint64(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeFixed64',\n            jspb.BinaryWriter.prototype.writeFixed64\n        ),\n        (jspb.BinaryWriter.prototype.writeFixed64String = function(e, t) {\n            null != t &&\n                ((t = jspb.arith.UInt64.fromString(t)),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED64),\n                this.encoder_.writeSplitFixed64(t.lo, t.hi));\n        }),\n        (jspb.BinaryWriter.prototype.writeSfixed32 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(\n                    t >= -jspb.BinaryConstants.TWO_TO_31 && t < jspb.BinaryConstants.TWO_TO_31\n                ),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED32),\n                this.encoder_.writeInt32(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeSfixed32',\n            jspb.BinaryWriter.prototype.writeSfixed32\n        ),\n        (jspb.BinaryWriter.prototype.writeSfixed64 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(\n                    t >= -jspb.BinaryConstants.TWO_TO_63 && t < jspb.BinaryConstants.TWO_TO_63\n                ),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED64),\n                this.encoder_.writeInt64(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeSfixed64',\n            jspb.BinaryWriter.prototype.writeSfixed64\n        ),\n        (jspb.BinaryWriter.prototype.writeSfixed64String = function(e, t) {\n            null != t &&\n                ((t = jspb.arith.Int64.fromString(t)),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED64),\n                this.encoder_.writeSplitFixed64(t.lo, t.hi));\n        }),\n        (jspb.BinaryWriter.prototype.writeFloat = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED32),\n                this.encoder_.writeFloat(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeFloat',\n            jspb.BinaryWriter.prototype.writeFloat\n        ),\n        (jspb.BinaryWriter.prototype.writeDouble = function(e, t) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED64),\n                this.encoder_.writeDouble(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeDouble',\n            jspb.BinaryWriter.prototype.writeDouble\n        ),\n        (jspb.BinaryWriter.prototype.writeBool = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert('boolean' == typeof t || 'number' == typeof t),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeBool(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeBool',\n            jspb.BinaryWriter.prototype.writeBool\n        ),\n        (jspb.BinaryWriter.prototype.writeEnum = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(\n                    t >= -jspb.BinaryConstants.TWO_TO_31 && t < jspb.BinaryConstants.TWO_TO_31\n                ),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeSignedVarint32(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeEnum',\n            jspb.BinaryWriter.prototype.writeEnum\n        ),\n        (jspb.BinaryWriter.prototype.writeString = function(e, t) {\n            null != t &&\n                ((e = this.beginDelimited_(e)),\n                this.encoder_.writeString(t),\n                this.endDelimited_(e));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeString',\n            jspb.BinaryWriter.prototype.writeString\n        ),\n        (jspb.BinaryWriter.prototype.writeBytes = function(e, t) {\n            null != t &&\n                ((t = jspb.utils.byteSourceToUint8Array(t)),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                this.encoder_.writeUnsignedVarint32(t.length),\n                this.appendUint8Array_(t));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeBytes',\n            jspb.BinaryWriter.prototype.writeBytes\n        ),\n        (jspb.BinaryWriter.prototype.writeMessage = function(e, t, r) {\n            null != t && ((e = this.beginDelimited_(e)), r(t, this), this.endDelimited_(e));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeMessage',\n            jspb.BinaryWriter.prototype.writeMessage\n        ),\n        (jspb.BinaryWriter.prototype.writeMessageSet = function(e, t, r) {\n            null != t &&\n                (this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.START_GROUP),\n                this.writeFieldHeader_(2, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeSignedVarint32(e),\n                (e = this.beginDelimited_(3)),\n                r(t, this),\n                this.endDelimited_(e),\n                this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.END_GROUP));\n        }),\n        (jspb.BinaryWriter.prototype.writeGroup = function(e, t, r) {\n            null != t &&\n                (this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.START_GROUP),\n                r(t, this),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.END_GROUP));\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeGroup',\n            jspb.BinaryWriter.prototype.writeGroup\n        ),\n        (jspb.BinaryWriter.prototype.writeFixedHash64 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(8 == t.length),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED64),\n                this.encoder_.writeFixedHash64(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeVarintHash64 = function(e, t) {\n            null != t &&\n                (jspb.asserts.assert(8 == t.length),\n                this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeVarintHash64(t));\n        }),\n        (jspb.BinaryWriter.prototype.writeSplitFixed64 = function(e, t, r) {\n            this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.FIXED64),\n                this.encoder_.writeSplitFixed64(t, r);\n        }),\n        (jspb.BinaryWriter.prototype.writeSplitVarint64 = function(e, t, r) {\n            this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT),\n                this.encoder_.writeSplitVarint64(t, r);\n        }),\n        (jspb.BinaryWriter.prototype.writeSplitZigzagVarint64 = function(e, t, r) {\n            this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.VARINT);\n            var o = this.encoder_;\n            jspb.utils.toZigzag64(t, r, function(e, t) {\n                o.writeSplitVarint64(e >>> 0, t >>> 0);\n            });\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeSignedVarint32_(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedInt32',\n            jspb.BinaryWriter.prototype.writeRepeatedInt32\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeInt32String(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeSignedVarint64_(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedInt64',\n            jspb.BinaryWriter.prototype.writeRepeatedInt64\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedSplitFixed64 = function(e, t, r, o) {\n            if (null != t)\n                for (var i = 0; i < t.length; i++) this.writeSplitFixed64(e, r(t[i]), o(t[i]));\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedSplitVarint64 = function(e, t, r, o) {\n            if (null != t)\n                for (var i = 0; i < t.length; i++) this.writeSplitVarint64(e, r(t[i]), o(t[i]));\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedSplitZigzagVarint64 = function(e, t, r, o) {\n            if (null != t)\n                for (var i = 0; i < t.length; i++)\n                    this.writeSplitZigzagVarint64(e, r(t[i]), o(t[i]));\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeInt64String(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeUnsignedVarint32_(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedUint32',\n            jspb.BinaryWriter.prototype.writeRepeatedUint32\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeUint32String(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeUnsignedVarint64_(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedUint64',\n            jspb.BinaryWriter.prototype.writeRepeatedUint64\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeUint64String(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeZigzagVarint32_(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedSint32',\n            jspb.BinaryWriter.prototype.writeRepeatedSint32\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeZigzagVarint64_(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedSint64',\n            jspb.BinaryWriter.prototype.writeRepeatedSint64\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(e, t) {\n            if (null != t)\n                for (var r = 0; r < t.length; r++) this.writeZigzagVarint64String_(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedSintHash64 = function(e, t) {\n            if (null != t)\n                for (var r = 0; r < t.length; r++) this.writeZigzagVarintHash64_(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeFixed32(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedFixed32',\n            jspb.BinaryWriter.prototype.writeRepeatedFixed32\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeFixed64(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedFixed64',\n            jspb.BinaryWriter.prototype.writeRepeatedFixed64\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeFixed64String(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedFixed64String',\n            jspb.BinaryWriter.prototype.writeRepeatedFixed64String\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeSfixed32(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedSfixed32',\n            jspb.BinaryWriter.prototype.writeRepeatedSfixed32\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeSfixed64(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedSfixed64',\n            jspb.BinaryWriter.prototype.writeRepeatedSfixed64\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeSfixed64String(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedFloat = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeFloat(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedFloat',\n            jspb.BinaryWriter.prototype.writeRepeatedFloat\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedDouble = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeDouble(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedDouble',\n            jspb.BinaryWriter.prototype.writeRepeatedDouble\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedBool = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeBool(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedBool',\n            jspb.BinaryWriter.prototype.writeRepeatedBool\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedEnum = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeEnum(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedEnum',\n            jspb.BinaryWriter.prototype.writeRepeatedEnum\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedString = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeString(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedString',\n            jspb.BinaryWriter.prototype.writeRepeatedString\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedBytes = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeBytes(e, t[r]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedBytes',\n            jspb.BinaryWriter.prototype.writeRepeatedBytes\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedMessage = function(e, t, r) {\n            if (null != t)\n                for (var o = 0; o < t.length; o++) {\n                    var i = this.beginDelimited_(e);\n                    r(t[o], this), this.endDelimited_(i);\n                }\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedMessage',\n            jspb.BinaryWriter.prototype.writeRepeatedMessage\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedGroup = function(e, t, r) {\n            if (null != t)\n                for (var o = 0; o < t.length; o++)\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.START_GROUP),\n                        r(t[o], this),\n                        this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.END_GROUP);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writeRepeatedGroup',\n            jspb.BinaryWriter.prototype.writeRepeatedGroup\n        ),\n        (jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeFixedHash64(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = function(e, t) {\n            if (null != t) for (var r = 0; r < t.length; r++) this.writeVarintHash64(e, t[r]);\n        }),\n        (jspb.BinaryWriter.prototype.writePackedInt32 = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeSignedVarint32(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedInt32',\n            jspb.BinaryWriter.prototype.writePackedInt32\n        ),\n        (jspb.BinaryWriter.prototype.writePackedInt32String = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++)\n                    this.encoder_.writeSignedVarint32(parseInt(t[r], 10));\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedInt64 = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeSignedVarint64(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedInt64',\n            jspb.BinaryWriter.prototype.writePackedInt64\n        ),\n        (jspb.BinaryWriter.prototype.writePackedSplitFixed64 = function(e, t, r, o) {\n            if (null != t) {\n                e = this.beginDelimited_(e);\n                for (var i = 0; i < t.length; i++)\n                    this.encoder_.writeSplitFixed64(r(t[i]), o(t[i]));\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedSplitVarint64 = function(e, t, r, o) {\n            if (null != t) {\n                e = this.beginDelimited_(e);\n                for (var i = 0; i < t.length; i++)\n                    this.encoder_.writeSplitVarint64(r(t[i]), o(t[i]));\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedSplitZigzagVarint64 = function(e, t, r, o) {\n            if (null != t) {\n                e = this.beginDelimited_(e);\n                for (var i = this.encoder_, a = 0; a < t.length; a++)\n                    jspb.utils.toZigzag64(r(t[a]), o(t[a]), function(e, t) {\n                        i.writeSplitVarint64(e >>> 0, t >>> 0);\n                    });\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedInt64String = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) {\n                    var o = jspb.arith.Int64.fromString(t[r]);\n                    this.encoder_.writeSplitVarint64(o.lo, o.hi);\n                }\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedUint32 = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeUnsignedVarint32(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedUint32',\n            jspb.BinaryWriter.prototype.writePackedUint32\n        ),\n        (jspb.BinaryWriter.prototype.writePackedUint32String = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++)\n                    this.encoder_.writeUnsignedVarint32(parseInt(t[r], 10));\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedUint64 = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeUnsignedVarint64(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedUint64',\n            jspb.BinaryWriter.prototype.writePackedUint64\n        ),\n        (jspb.BinaryWriter.prototype.writePackedUint64String = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) {\n                    var o = jspb.arith.UInt64.fromString(t[r]);\n                    this.encoder_.writeSplitVarint64(o.lo, o.hi);\n                }\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedSint32 = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeZigzagVarint32(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedSint32',\n            jspb.BinaryWriter.prototype.writePackedSint32\n        ),\n        (jspb.BinaryWriter.prototype.writePackedSint64 = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeZigzagVarint64(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedSint64',\n            jspb.BinaryWriter.prototype.writePackedSint64\n        ),\n        (jspb.BinaryWriter.prototype.writePackedSint64String = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++)\n                    this.encoder_.writeZigzagVarintHash64(jspb.utils.decimalStringToHash64(t[r]));\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedSintHash64 = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeZigzagVarintHash64(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedFixed32 = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(4 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeUint32(t[e]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedFixed32',\n            jspb.BinaryWriter.prototype.writePackedFixed32\n        ),\n        (jspb.BinaryWriter.prototype.writePackedFixed64 = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(8 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeUint64(t[e]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedFixed64',\n            jspb.BinaryWriter.prototype.writePackedFixed64\n        ),\n        (jspb.BinaryWriter.prototype.writePackedFixed64String = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(8 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                ) {\n                    var r = jspb.arith.UInt64.fromString(t[e]);\n                    this.encoder_.writeSplitFixed64(r.lo, r.hi);\n                }\n        }),\n        (jspb.BinaryWriter.prototype.writePackedSfixed32 = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(4 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeInt32(t[e]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedSfixed32',\n            jspb.BinaryWriter.prototype.writePackedSfixed32\n        ),\n        (jspb.BinaryWriter.prototype.writePackedSfixed64 = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(8 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeInt64(t[e]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedSfixed64',\n            jspb.BinaryWriter.prototype.writePackedSfixed64\n        ),\n        (jspb.BinaryWriter.prototype.writePackedSfixed64String = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(8 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeInt64String(t[e]);\n        }),\n        (jspb.BinaryWriter.prototype.writePackedFloat = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(4 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeFloat(t[e]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedFloat',\n            jspb.BinaryWriter.prototype.writePackedFloat\n        ),\n        (jspb.BinaryWriter.prototype.writePackedDouble = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(8 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeDouble(t[e]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedDouble',\n            jspb.BinaryWriter.prototype.writePackedDouble\n        ),\n        (jspb.BinaryWriter.prototype.writePackedBool = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeBool(t[e]);\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedBool',\n            jspb.BinaryWriter.prototype.writePackedBool\n        ),\n        (jspb.BinaryWriter.prototype.writePackedEnum = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeEnum(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        goog.exportProperty(\n            jspb.BinaryWriter.prototype,\n            'writePackedEnum',\n            jspb.BinaryWriter.prototype.writePackedEnum\n        ),\n        (jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(e, t) {\n            if (null != t && t.length)\n                for (\n                    this.writeFieldHeader_(e, jspb.BinaryConstants.WireType.DELIMITED),\n                        this.encoder_.writeUnsignedVarint32(8 * t.length),\n                        e = 0;\n                    e < t.length;\n                    e++\n                )\n                    this.encoder_.writeFixedHash64(t[e]);\n        }),\n        (jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(e, t) {\n            if (null != t && t.length) {\n                e = this.beginDelimited_(e);\n                for (var r = 0; r < t.length; r++) this.encoder_.writeVarintHash64(t[r]);\n                this.endDelimited_(e);\n            }\n        }),\n        (jspb.Map = function(e, t) {\n            (this.arr_ = e),\n                (this.valueCtor_ = t),\n                (this.map_ = {}),\n                (this.arrClean = !0),\n                0 < this.arr_.length && this.loadFromArray_();\n        }),\n        goog.exportSymbol('jspb.Map', jspb.Map),\n        (jspb.Map.prototype.loadFromArray_ = function() {\n            for (var e = 0; e < this.arr_.length; e++) {\n                var t = this.arr_[e],\n                    r = t[0];\n                this.map_[r.toString()] = new jspb.Map.Entry_(r, t[1]);\n            }\n            this.arrClean = !0;\n        }),\n        (jspb.Map.prototype.toArray = function() {\n            if (this.arrClean) {\n                if (this.valueCtor_) {\n                    var e,\n                        t = this.map_;\n                    for (e in t)\n                        if (Object.prototype.hasOwnProperty.call(t, e)) {\n                            var r = t[e].valueWrapper;\n                            r && r.toArray();\n                        }\n                }\n            } else {\n                for (\n                    this.arr_.length = 0, (t = this.stringKeys_()).sort(), e = 0;\n                    e < t.length;\n                    e++\n                ) {\n                    var o = this.map_[t[e]];\n                    (r = o.valueWrapper) && r.toArray(), this.arr_.push([o.key, o.value]);\n                }\n                this.arrClean = !0;\n            }\n            return this.arr_;\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'toArray', jspb.Map.prototype.toArray),\n        (jspb.Map.prototype.toObject = function(e, t) {\n            for (var r = this.toArray(), o = [], i = 0; i < r.length; i++) {\n                var a = this.map_[r[i][0].toString()];\n                this.wrapEntry_(a);\n                var n = a.valueWrapper;\n                n ? (jspb.asserts.assert(t), o.push([a.key, t(e, n)])) : o.push([a.key, a.value]);\n            }\n            return o;\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'toObject', jspb.Map.prototype.toObject),\n        (jspb.Map.fromObject = function(e, t, r) {\n            t = new jspb.Map([], t);\n            for (var o = 0; o < e.length; o++) {\n                var i = e[o][0],\n                    a = r(e[o][1]);\n                t.set(i, a);\n            }\n            return t;\n        }),\n        goog.exportProperty(jspb.Map, 'fromObject', jspb.Map.fromObject),\n        (jspb.Map.ArrayIteratorIterable_ = function(e) {\n            (this.idx_ = 0), (this.arr_ = e);\n        }),\n        (jspb.Map.ArrayIteratorIterable_.prototype.next = function() {\n            return this.idx_ < this.arr_.length\n                ? { done: !1, value: this.arr_[this.idx_++] }\n                : { done: !0, value: void 0 };\n        }),\n        'undefined' != typeof Symbol &&\n            (jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] = function() {\n                return this;\n            }),\n        (jspb.Map.prototype.getLength = function() {\n            return this.stringKeys_().length;\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'getLength', jspb.Map.prototype.getLength),\n        (jspb.Map.prototype.clear = function() {\n            (this.map_ = {}), (this.arrClean = !1);\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'clear', jspb.Map.prototype.clear),\n        (jspb.Map.prototype.del = function(e) {\n            e = e.toString();\n            var t = this.map_.hasOwnProperty(e);\n            return delete this.map_[e], (this.arrClean = !1), t;\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'del', jspb.Map.prototype.del),\n        (jspb.Map.prototype.getEntryList = function() {\n            var e = [],\n                t = this.stringKeys_();\n            t.sort();\n            for (var r = 0; r < t.length; r++) {\n                var o = this.map_[t[r]];\n                e.push([o.key, o.value]);\n            }\n            return e;\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'getEntryList', jspb.Map.prototype.getEntryList),\n        (jspb.Map.prototype.entries = function() {\n            var e = [],\n                t = this.stringKeys_();\n            t.sort();\n            for (var r = 0; r < t.length; r++) {\n                var o = this.map_[t[r]];\n                e.push([o.key, this.wrapEntry_(o)]);\n            }\n            return new jspb.Map.ArrayIteratorIterable_(e);\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'entries', jspb.Map.prototype.entries),\n        (jspb.Map.prototype.keys = function() {\n            var e = [],\n                t = this.stringKeys_();\n            t.sort();\n            for (var r = 0; r < t.length; r++) e.push(this.map_[t[r]].key);\n            return new jspb.Map.ArrayIteratorIterable_(e);\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'keys', jspb.Map.prototype.keys),\n        (jspb.Map.prototype.values = function() {\n            var e = [],\n                t = this.stringKeys_();\n            t.sort();\n            for (var r = 0; r < t.length; r++) e.push(this.wrapEntry_(this.map_[t[r]]));\n            return new jspb.Map.ArrayIteratorIterable_(e);\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'values', jspb.Map.prototype.values),\n        (jspb.Map.prototype.forEach = function(e, t) {\n            var r = this.stringKeys_();\n            r.sort();\n            for (var o = 0; o < r.length; o++) {\n                var i = this.map_[r[o]];\n                e.call(t, this.wrapEntry_(i), i.key, this);\n            }\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'forEach', jspb.Map.prototype.forEach),\n        (jspb.Map.prototype.set = function(e, t) {\n            var r = new jspb.Map.Entry_(e);\n            return (\n                this.valueCtor_ ? ((r.valueWrapper = t), (r.value = t.toArray())) : (r.value = t),\n                (this.map_[e.toString()] = r),\n                (this.arrClean = !1),\n                this\n            );\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'set', jspb.Map.prototype.set),\n        (jspb.Map.prototype.wrapEntry_ = function(e) {\n            return this.valueCtor_\n                ? (e.valueWrapper || (e.valueWrapper = new this.valueCtor_(e.value)),\n                  e.valueWrapper)\n                : e.value;\n        }),\n        (jspb.Map.prototype.get = function(e) {\n            if ((e = this.map_[e.toString()])) return this.wrapEntry_(e);\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'get', jspb.Map.prototype.get),\n        (jspb.Map.prototype.has = function(e) {\n            return e.toString() in this.map_;\n        }),\n        goog.exportProperty(jspb.Map.prototype, 'has', jspb.Map.prototype.has),\n        (jspb.Map.prototype.serializeBinary = function(e, t, r, o, i) {\n            var a = this.stringKeys_();\n            a.sort();\n            for (var n = 0; n < a.length; n++) {\n                var s = this.map_[a[n]];\n                t.beginSubMessage(e),\n                    r.call(t, 1, s.key),\n                    this.valueCtor_ ? o.call(t, 2, this.wrapEntry_(s), i) : o.call(t, 2, s.value),\n                    t.endSubMessage();\n            }\n        }),\n        goog.exportProperty(\n            jspb.Map.prototype,\n            'serializeBinary',\n            jspb.Map.prototype.serializeBinary\n        ),\n        (jspb.Map.deserializeBinary = function(e, t, r, o, i, a, n) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                var s = t.getFieldNumber();\n                1 == s\n                    ? (a = r.call(t))\n                    : 2 == s &&\n                      (e.valueCtor_\n                          ? (jspb.asserts.assert(i), n || (n = new e.valueCtor_()), o.call(t, n, i))\n                          : (n = o.call(t)));\n            }\n            jspb.asserts.assert(null != a), jspb.asserts.assert(null != n), e.set(a, n);\n        }),\n        goog.exportProperty(jspb.Map, 'deserializeBinary', jspb.Map.deserializeBinary),\n        (jspb.Map.prototype.stringKeys_ = function() {\n            var e,\n                t = this.map_,\n                r = [];\n            for (e in t) Object.prototype.hasOwnProperty.call(t, e) && r.push(e);\n            return r;\n        }),\n        (jspb.Map.Entry_ = function(e, t) {\n            (this.key = e), (this.value = t), (this.valueWrapper = void 0);\n        }),\n        (jspb.ExtensionFieldInfo = function(e, t, r, o, i) {\n            (this.fieldIndex = e),\n                (this.fieldName = t),\n                (this.ctor = r),\n                (this.toObjectFn = o),\n                (this.isRepeated = i);\n        }),\n        goog.exportSymbol('jspb.ExtensionFieldInfo', jspb.ExtensionFieldInfo),\n        (jspb.ExtensionFieldBinaryInfo = function(e, t, r, o, i, a) {\n            (this.fieldInfo = e),\n                (this.binaryReaderFn = t),\n                (this.binaryWriterFn = r),\n                (this.binaryMessageSerializeFn = o),\n                (this.binaryMessageDeserializeFn = i),\n                (this.isPacked = a);\n        }),\n        goog.exportSymbol('jspb.ExtensionFieldBinaryInfo', jspb.ExtensionFieldBinaryInfo),\n        (jspb.ExtensionFieldInfo.prototype.isMessageType = function() {\n            return !!this.ctor;\n        }),\n        goog.exportProperty(\n            jspb.ExtensionFieldInfo.prototype,\n            'isMessageType',\n            jspb.ExtensionFieldInfo.prototype.isMessageType\n        ),\n        (jspb.Message = function() {}),\n        goog.exportSymbol('jspb.Message', jspb.Message),\n        (jspb.Message.GENERATE_TO_OBJECT = !0),\n        goog.exportProperty(jspb.Message, 'GENERATE_TO_OBJECT', jspb.Message.GENERATE_TO_OBJECT),\n        (jspb.Message.GENERATE_FROM_OBJECT = !goog.DISALLOW_TEST_ONLY_CODE),\n        goog.exportProperty(\n            jspb.Message,\n            'GENERATE_FROM_OBJECT',\n            jspb.Message.GENERATE_FROM_OBJECT\n        ),\n        (jspb.Message.GENERATE_TO_STRING = !0),\n        (jspb.Message.ASSUME_LOCAL_ARRAYS = !1),\n        (jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS = !0),\n        (jspb.Message.SUPPORTS_UINT8ARRAY_ = 'function' == typeof Uint8Array),\n        (jspb.Message.prototype.getJsPbMessageId = function() {\n            return this.messageId_;\n        }),\n        goog.exportProperty(\n            jspb.Message.prototype,\n            'getJsPbMessageId',\n            jspb.Message.prototype.getJsPbMessageId\n        ),\n        (jspb.Message.getIndex_ = function(e, t) {\n            return t + e.arrayIndexOffset_;\n        }),\n        (jspb.Message.hiddenES6Property_ = function() {}),\n        (jspb.Message.getFieldNumber_ = function(e, t) {\n            return t - e.arrayIndexOffset_;\n        }),\n        (jspb.Message.initialize = function(e, t, r, o, i, a) {\n            if (\n                ((e.wrappers_ = null),\n                t || (t = r ? [r] : []),\n                (e.messageId_ = r ? String(r) : void 0),\n                (e.arrayIndexOffset_ = 0 === r ? -1 : 0),\n                (e.array = t),\n                jspb.Message.initPivotAndExtensionObject_(e, o),\n                (e.convertedPrimitiveFields_ = {}),\n                jspb.Message.SERIALIZE_EMPTY_TRAILING_FIELDS || (e.repeatedFields = i),\n                i)\n            )\n                for (t = 0; t < i.length; t++)\n                    (r = i[t]) < e.pivot_\n                        ? ((r = jspb.Message.getIndex_(e, r)),\n                          (e.array[r] = e.array[r] || jspb.Message.EMPTY_LIST_SENTINEL_))\n                        : (jspb.Message.maybeInitEmptyExtensionObject_(e),\n                          (e.extensionObject_[r] =\n                              e.extensionObject_[r] || jspb.Message.EMPTY_LIST_SENTINEL_));\n            if (a && a.length)\n                for (t = 0; t < a.length; t++) jspb.Message.computeOneofCase(e, a[t]);\n        }),\n        goog.exportProperty(jspb.Message, 'initialize', jspb.Message.initialize),\n        (jspb.Message.EMPTY_LIST_SENTINEL_ = goog.DEBUG && Object.freeze ? Object.freeze([]) : []),\n        (jspb.Message.isArray_ = function(e) {\n            return jspb.Message.ASSUME_LOCAL_ARRAYS ? e instanceof Array : Array.isArray(e);\n        }),\n        (jspb.Message.isExtensionObject_ = function(e) {\n            return !(\n                null === e ||\n                'object' != typeof e ||\n                jspb.Message.isArray_(e) ||\n                (jspb.Message.SUPPORTS_UINT8ARRAY_ && e instanceof Uint8Array)\n            );\n        }),\n        (jspb.Message.initPivotAndExtensionObject_ = function(e, t) {\n            var r = e.array.length,\n                o = -1;\n            if (r && ((o = r - 1), (r = e.array[o]), jspb.Message.isExtensionObject_(r)))\n                return (\n                    (e.pivot_ = jspb.Message.getFieldNumber_(e, o)), void (e.extensionObject_ = r)\n                );\n            -1 < t\n                ? ((e.pivot_ = Math.max(t, jspb.Message.getFieldNumber_(e, o + 1))),\n                  (e.extensionObject_ = null))\n                : (e.pivot_ = Number.MAX_VALUE);\n        }),\n        (jspb.Message.maybeInitEmptyExtensionObject_ = function(e) {\n            var t = jspb.Message.getIndex_(e, e.pivot_);\n            e.array[t] || (e.extensionObject_ = e.array[t] = {});\n        }),\n        (jspb.Message.toObjectList = function(e, t, r) {\n            for (var o = [], i = 0; i < e.length; i++) o[i] = t.call(e[i], r, e[i]);\n            return o;\n        }),\n        goog.exportProperty(jspb.Message, 'toObjectList', jspb.Message.toObjectList),\n        (jspb.Message.toObjectExtension = function(e, t, r, o, i) {\n            for (var a in r) {\n                var n = r[a],\n                    s = o.call(e, n);\n                if (null != s) {\n                    for (var p in n.fieldName) if (n.fieldName.hasOwnProperty(p)) break;\n                    t[p] = n.toObjectFn\n                        ? n.isRepeated\n                            ? jspb.Message.toObjectList(s, n.toObjectFn, i)\n                            : n.toObjectFn(i, s)\n                        : s;\n                }\n            }\n        }),\n        goog.exportProperty(jspb.Message, 'toObjectExtension', jspb.Message.toObjectExtension),\n        (jspb.Message.serializeBinaryExtensions = function(e, t, r, o) {\n            for (var i in r) {\n                var a = r[i],\n                    n = a.fieldInfo;\n                if (!a.binaryWriterFn)\n                    throw Error(\n                        'Message extension present that was generated without binary serialization support'\n                    );\n                var s = o.call(e, n);\n                if (null != s)\n                    if (n.isMessageType()) {\n                        if (!a.binaryMessageSerializeFn)\n                            throw Error(\n                                'Message extension present holding submessage without binary support enabled, and message is being serialized to binary format'\n                            );\n                        a.binaryWriterFn.call(t, n.fieldIndex, s, a.binaryMessageSerializeFn);\n                    } else a.binaryWriterFn.call(t, n.fieldIndex, s);\n            }\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'serializeBinaryExtensions',\n            jspb.Message.serializeBinaryExtensions\n        ),\n        (jspb.Message.readBinaryExtension = function(e, t, r, o, i) {\n            var a = r[t.getFieldNumber()];\n            if (a) {\n                if (((r = a.fieldInfo), !a.binaryReaderFn))\n                    throw Error(\n                        'Deserializing extension whose generated code does not support binary format'\n                    );\n                if (r.isMessageType()) {\n                    var n = new r.ctor();\n                    a.binaryReaderFn.call(t, n, a.binaryMessageDeserializeFn);\n                } else n = a.binaryReaderFn.call(t);\n                r.isRepeated && !a.isPacked\n                    ? (t = o.call(e, r))\n                        ? t.push(n)\n                        : i.call(e, r, [n])\n                    : i.call(e, r, n);\n            } else t.skipField();\n        }),\n        goog.exportProperty(jspb.Message, 'readBinaryExtension', jspb.Message.readBinaryExtension),\n        (jspb.Message.getField = function(e, t) {\n            if (t < e.pivot_) {\n                t = jspb.Message.getIndex_(e, t);\n                var r = e.array[t];\n                return r === jspb.Message.EMPTY_LIST_SENTINEL_ ? (e.array[t] = []) : r;\n            }\n            if (e.extensionObject_)\n                return (r = e.extensionObject_[t]) === jspb.Message.EMPTY_LIST_SENTINEL_\n                    ? (e.extensionObject_[t] = [])\n                    : r;\n        }),\n        goog.exportProperty(jspb.Message, 'getField', jspb.Message.getField),\n        (jspb.Message.getRepeatedField = function(e, t) {\n            return jspb.Message.getField(e, t);\n        }),\n        goog.exportProperty(jspb.Message, 'getRepeatedField', jspb.Message.getRepeatedField),\n        (jspb.Message.getOptionalFloatingPointField = function(e, t) {\n            return null == (e = jspb.Message.getField(e, t)) ? e : +e;\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'getOptionalFloatingPointField',\n            jspb.Message.getOptionalFloatingPointField\n        ),\n        (jspb.Message.getBooleanField = function(e, t) {\n            return null == (e = jspb.Message.getField(e, t)) ? e : !!e;\n        }),\n        goog.exportProperty(jspb.Message, 'getBooleanField', jspb.Message.getBooleanField),\n        (jspb.Message.getRepeatedFloatingPointField = function(e, t) {\n            var r = jspb.Message.getRepeatedField(e, t);\n            if (\n                (e.convertedPrimitiveFields_ || (e.convertedPrimitiveFields_ = {}),\n                !e.convertedPrimitiveFields_[t])\n            ) {\n                for (var o = 0; o < r.length; o++) r[o] = +r[o];\n                e.convertedPrimitiveFields_[t] = !0;\n            }\n            return r;\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'getRepeatedFloatingPointField',\n            jspb.Message.getRepeatedFloatingPointField\n        ),\n        (jspb.Message.getRepeatedBooleanField = function(e, t) {\n            var r = jspb.Message.getRepeatedField(e, t);\n            if (\n                (e.convertedPrimitiveFields_ || (e.convertedPrimitiveFields_ = {}),\n                !e.convertedPrimitiveFields_[t])\n            ) {\n                for (var o = 0; o < r.length; o++) r[o] = !!r[o];\n                e.convertedPrimitiveFields_[t] = !0;\n            }\n            return r;\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'getRepeatedBooleanField',\n            jspb.Message.getRepeatedBooleanField\n        ),\n        (jspb.Message.bytesAsB64 = function(e) {\n            return null == e || 'string' == typeof e\n                ? e\n                : jspb.Message.SUPPORTS_UINT8ARRAY_ && e instanceof Uint8Array\n                ? goog.crypt.base64.encodeByteArray(e)\n                : (jspb.asserts.fail('Cannot coerce to b64 string: ' + goog.typeOf(e)), null);\n        }),\n        goog.exportProperty(jspb.Message, 'bytesAsB64', jspb.Message.bytesAsB64),\n        (jspb.Message.bytesAsU8 = function(e) {\n            return null == e || e instanceof Uint8Array\n                ? e\n                : 'string' == typeof e\n                ? goog.crypt.base64.decodeStringToUint8Array(e)\n                : (jspb.asserts.fail('Cannot coerce to Uint8Array: ' + goog.typeOf(e)), null);\n        }),\n        goog.exportProperty(jspb.Message, 'bytesAsU8', jspb.Message.bytesAsU8),\n        (jspb.Message.bytesListAsB64 = function(e) {\n            return (\n                jspb.Message.assertConsistentTypes_(e),\n                e.length && 'string' != typeof e[0] ? goog.array.map(e, jspb.Message.bytesAsB64) : e\n            );\n        }),\n        goog.exportProperty(jspb.Message, 'bytesListAsB64', jspb.Message.bytesListAsB64),\n        (jspb.Message.bytesListAsU8 = function(e) {\n            return (\n                jspb.Message.assertConsistentTypes_(e),\n                !e.length || e[0] instanceof Uint8Array\n                    ? e\n                    : goog.array.map(e, jspb.Message.bytesAsU8)\n            );\n        }),\n        goog.exportProperty(jspb.Message, 'bytesListAsU8', jspb.Message.bytesListAsU8),\n        (jspb.Message.assertConsistentTypes_ = function(e) {\n            if (goog.DEBUG && e && 1 < e.length) {\n                var t = goog.typeOf(e[0]);\n                goog.array.forEach(e, function(e) {\n                    goog.typeOf(e) != t &&\n                        jspb.asserts.fail(\n                            'Inconsistent type in JSPB repeated field array. Got ' +\n                                goog.typeOf(e) +\n                                ' expected ' +\n                                t\n                        );\n                });\n            }\n        }),\n        (jspb.Message.getFieldWithDefault = function(e, t, r) {\n            return null == (e = jspb.Message.getField(e, t)) ? r : e;\n        }),\n        goog.exportProperty(jspb.Message, 'getFieldWithDefault', jspb.Message.getFieldWithDefault),\n        (jspb.Message.getBooleanFieldWithDefault = function(e, t, r) {\n            return null == (e = jspb.Message.getBooleanField(e, t)) ? r : e;\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'getBooleanFieldWithDefault',\n            jspb.Message.getBooleanFieldWithDefault\n        ),\n        (jspb.Message.getFloatingPointFieldWithDefault = function(e, t, r) {\n            return null == (e = jspb.Message.getOptionalFloatingPointField(e, t)) ? r : e;\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'getFloatingPointFieldWithDefault',\n            jspb.Message.getFloatingPointFieldWithDefault\n        ),\n        (jspb.Message.getFieldProto3 = jspb.Message.getFieldWithDefault),\n        goog.exportProperty(jspb.Message, 'getFieldProto3', jspb.Message.getFieldProto3),\n        (jspb.Message.getMapField = function(e, t, r, o) {\n            if ((e.wrappers_ || (e.wrappers_ = {}), t in e.wrappers_)) return e.wrappers_[t];\n            var i = jspb.Message.getField(e, t);\n            if (!i) {\n                if (r) return;\n                (i = []), jspb.Message.setField(e, t, i);\n            }\n            return (e.wrappers_[t] = new jspb.Map(i, o));\n        }),\n        goog.exportProperty(jspb.Message, 'getMapField', jspb.Message.getMapField),\n        (jspb.Message.setField = function(e, t, r) {\n            return (\n                jspb.asserts.assertInstanceof(e, jspb.Message),\n                t < e.pivot_\n                    ? (e.array[jspb.Message.getIndex_(e, t)] = r)\n                    : (jspb.Message.maybeInitEmptyExtensionObject_(e), (e.extensionObject_[t] = r)),\n                e\n            );\n        }),\n        goog.exportProperty(jspb.Message, 'setField', jspb.Message.setField),\n        (jspb.Message.setProto3IntField = function(e, t, r) {\n            return jspb.Message.setFieldIgnoringDefault_(e, t, r, 0);\n        }),\n        goog.exportProperty(jspb.Message, 'setProto3IntField', jspb.Message.setProto3IntField),\n        (jspb.Message.setProto3FloatField = function(e, t, r) {\n            return jspb.Message.setFieldIgnoringDefault_(e, t, r, 0);\n        }),\n        goog.exportProperty(jspb.Message, 'setProto3FloatField', jspb.Message.setProto3FloatField),\n        (jspb.Message.setProto3BooleanField = function(e, t, r) {\n            return jspb.Message.setFieldIgnoringDefault_(e, t, r, !1);\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'setProto3BooleanField',\n            jspb.Message.setProto3BooleanField\n        ),\n        (jspb.Message.setProto3StringField = function(e, t, r) {\n            return jspb.Message.setFieldIgnoringDefault_(e, t, r, '');\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'setProto3StringField',\n            jspb.Message.setProto3StringField\n        ),\n        (jspb.Message.setProto3BytesField = function(e, t, r) {\n            return jspb.Message.setFieldIgnoringDefault_(e, t, r, '');\n        }),\n        goog.exportProperty(jspb.Message, 'setProto3BytesField', jspb.Message.setProto3BytesField),\n        (jspb.Message.setProto3EnumField = function(e, t, r) {\n            return jspb.Message.setFieldIgnoringDefault_(e, t, r, 0);\n        }),\n        goog.exportProperty(jspb.Message, 'setProto3EnumField', jspb.Message.setProto3EnumField),\n        (jspb.Message.setProto3StringIntField = function(e, t, r) {\n            return jspb.Message.setFieldIgnoringDefault_(e, t, r, '0');\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'setProto3StringIntField',\n            jspb.Message.setProto3StringIntField\n        ),\n        (jspb.Message.setFieldIgnoringDefault_ = function(e, t, r, o) {\n            return (\n                jspb.asserts.assertInstanceof(e, jspb.Message),\n                r !== o\n                    ? jspb.Message.setField(e, t, r)\n                    : t < e.pivot_\n                    ? (e.array[jspb.Message.getIndex_(e, t)] = null)\n                    : (jspb.Message.maybeInitEmptyExtensionObject_(e),\n                      delete e.extensionObject_[t]),\n                e\n            );\n        }),\n        (jspb.Message.addToRepeatedField = function(e, t, r, o) {\n            return (\n                jspb.asserts.assertInstanceof(e, jspb.Message),\n                (t = jspb.Message.getRepeatedField(e, t)),\n                null != o ? t.splice(o, 0, r) : t.push(r),\n                e\n            );\n        }),\n        goog.exportProperty(jspb.Message, 'addToRepeatedField', jspb.Message.addToRepeatedField),\n        (jspb.Message.setOneofField = function(e, t, r, o) {\n            return (\n                jspb.asserts.assertInstanceof(e, jspb.Message),\n                (r = jspb.Message.computeOneofCase(e, r)) &&\n                    r !== t &&\n                    void 0 !== o &&\n                    (e.wrappers_ && r in e.wrappers_ && (e.wrappers_[r] = void 0),\n                    jspb.Message.setField(e, r, void 0)),\n                jspb.Message.setField(e, t, o)\n            );\n        }),\n        goog.exportProperty(jspb.Message, 'setOneofField', jspb.Message.setOneofField),\n        (jspb.Message.computeOneofCase = function(e, t) {\n            for (var r, o, i = 0; i < t.length; i++) {\n                var a = t[i],\n                    n = jspb.Message.getField(e, a);\n                null != n && ((r = a), (o = n), jspb.Message.setField(e, a, void 0));\n            }\n            return r ? (jspb.Message.setField(e, r, o), r) : 0;\n        }),\n        goog.exportProperty(jspb.Message, 'computeOneofCase', jspb.Message.computeOneofCase),\n        (jspb.Message.getWrapperField = function(e, t, r, o) {\n            if ((e.wrappers_ || (e.wrappers_ = {}), !e.wrappers_[r])) {\n                var i = jspb.Message.getField(e, r);\n                (o || i) && (e.wrappers_[r] = new t(i));\n            }\n            return e.wrappers_[r];\n        }),\n        goog.exportProperty(jspb.Message, 'getWrapperField', jspb.Message.getWrapperField),\n        (jspb.Message.getRepeatedWrapperField = function(e, t, r) {\n            return (\n                jspb.Message.wrapRepeatedField_(e, t, r),\n                (t = e.wrappers_[r]) == jspb.Message.EMPTY_LIST_SENTINEL_ &&\n                    (t = e.wrappers_[r] = []),\n                t\n            );\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'getRepeatedWrapperField',\n            jspb.Message.getRepeatedWrapperField\n        ),\n        (jspb.Message.wrapRepeatedField_ = function(e, t, r) {\n            if ((e.wrappers_ || (e.wrappers_ = {}), !e.wrappers_[r])) {\n                for (var o = jspb.Message.getRepeatedField(e, r), i = [], a = 0; a < o.length; a++)\n                    i[a] = new t(o[a]);\n                e.wrappers_[r] = i;\n            }\n        }),\n        (jspb.Message.setWrapperField = function(e, t, r) {\n            jspb.asserts.assertInstanceof(e, jspb.Message), e.wrappers_ || (e.wrappers_ = {});\n            var o = r ? r.toArray() : r;\n            return (e.wrappers_[t] = r), jspb.Message.setField(e, t, o);\n        }),\n        goog.exportProperty(jspb.Message, 'setWrapperField', jspb.Message.setWrapperField),\n        (jspb.Message.setOneofWrapperField = function(e, t, r, o) {\n            jspb.asserts.assertInstanceof(e, jspb.Message), e.wrappers_ || (e.wrappers_ = {});\n            var i = o ? o.toArray() : o;\n            return (e.wrappers_[t] = o), jspb.Message.setOneofField(e, t, r, i);\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'setOneofWrapperField',\n            jspb.Message.setOneofWrapperField\n        ),\n        (jspb.Message.setRepeatedWrapperField = function(e, t, r) {\n            jspb.asserts.assertInstanceof(e, jspb.Message),\n                e.wrappers_ || (e.wrappers_ = {}),\n                (r = r || []);\n            for (var o = [], i = 0; i < r.length; i++) o[i] = r[i].toArray();\n            return (e.wrappers_[t] = r), jspb.Message.setField(e, t, o);\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'setRepeatedWrapperField',\n            jspb.Message.setRepeatedWrapperField\n        ),\n        (jspb.Message.addToRepeatedWrapperField = function(e, t, r, o, i) {\n            jspb.Message.wrapRepeatedField_(e, o, t);\n            var a = e.wrappers_[t];\n            return (\n                a || (a = e.wrappers_[t] = []),\n                (r = r || new o()),\n                (e = jspb.Message.getRepeatedField(e, t)),\n                null != i\n                    ? (a.splice(i, 0, r), e.splice(i, 0, r.toArray()))\n                    : (a.push(r), e.push(r.toArray())),\n                r\n            );\n        }),\n        goog.exportProperty(\n            jspb.Message,\n            'addToRepeatedWrapperField',\n            jspb.Message.addToRepeatedWrapperField\n        ),\n        (jspb.Message.toMap = function(e, t, r, o) {\n            for (var i = {}, a = 0; a < e.length; a++)\n                i[t.call(e[a])] = r ? r.call(e[a], o, e[a]) : e[a];\n            return i;\n        }),\n        goog.exportProperty(jspb.Message, 'toMap', jspb.Message.toMap),\n        (jspb.Message.prototype.syncMapFields_ = function() {\n            if (this.wrappers_)\n                for (var e in this.wrappers_) {\n                    var t = this.wrappers_[e];\n                    if (Array.isArray(t)) for (var r = 0; r < t.length; r++) t[r] && t[r].toArray();\n                    else t && t.toArray();\n                }\n        }),\n        (jspb.Message.prototype.toArray = function() {\n            return this.syncMapFields_(), this.array;\n        }),\n        goog.exportProperty(jspb.Message.prototype, 'toArray', jspb.Message.prototype.toArray),\n        jspb.Message.GENERATE_TO_STRING &&\n            (jspb.Message.prototype.toString = function() {\n                return this.syncMapFields_(), this.array.toString();\n            }),\n        (jspb.Message.prototype.getExtension = function(e) {\n            if (this.extensionObject_) {\n                this.wrappers_ || (this.wrappers_ = {});\n                var t = e.fieldIndex;\n                if (e.isRepeated) {\n                    if (e.isMessageType())\n                        return (\n                            this.wrappers_[t] ||\n                                (this.wrappers_[t] = goog.array.map(\n                                    this.extensionObject_[t] || [],\n                                    function(t) {\n                                        return new e.ctor(t);\n                                    }\n                                )),\n                            this.wrappers_[t]\n                        );\n                } else if (e.isMessageType())\n                    return (\n                        !this.wrappers_[t] &&\n                            this.extensionObject_[t] &&\n                            (this.wrappers_[t] = new e.ctor(this.extensionObject_[t])),\n                        this.wrappers_[t]\n                    );\n                return this.extensionObject_[t];\n            }\n        }),\n        goog.exportProperty(\n            jspb.Message.prototype,\n            'getExtension',\n            jspb.Message.prototype.getExtension\n        ),\n        (jspb.Message.prototype.setExtension = function(e, t) {\n            this.wrappers_ || (this.wrappers_ = {}),\n                jspb.Message.maybeInitEmptyExtensionObject_(this);\n            var r = e.fieldIndex;\n            return (\n                e.isRepeated\n                    ? ((t = t || []),\n                      e.isMessageType()\n                          ? ((this.wrappers_[r] = t),\n                            (this.extensionObject_[r] = goog.array.map(t, function(e) {\n                                return e.toArray();\n                            })))\n                          : (this.extensionObject_[r] = t))\n                    : e.isMessageType()\n                    ? ((this.wrappers_[r] = t), (this.extensionObject_[r] = t ? t.toArray() : t))\n                    : (this.extensionObject_[r] = t),\n                this\n            );\n        }),\n        goog.exportProperty(\n            jspb.Message.prototype,\n            'setExtension',\n            jspb.Message.prototype.setExtension\n        ),\n        (jspb.Message.difference = function(e, t) {\n            if (!(e instanceof t.constructor)) throw Error('Messages have different types.');\n            var r = e.toArray();\n            t = t.toArray();\n            var o = [],\n                i = 0,\n                a = r.length > t.length ? r.length : t.length;\n            for (e.getJsPbMessageId() && ((o[0] = e.getJsPbMessageId()), (i = 1)); i < a; i++)\n                jspb.Message.compareFields(r[i], t[i]) || (o[i] = t[i]);\n            return new e.constructor(o);\n        }),\n        goog.exportProperty(jspb.Message, 'difference', jspb.Message.difference),\n        (jspb.Message.equals = function(e, t) {\n            return (\n                e == t ||\n                (!(!e || !t) &&\n                    e instanceof t.constructor &&\n                    jspb.Message.compareFields(e.toArray(), t.toArray()))\n            );\n        }),\n        goog.exportProperty(jspb.Message, 'equals', jspb.Message.equals),\n        (jspb.Message.compareExtensions = function(e, t) {\n            (e = e || {}), (t = t || {});\n            var r,\n                o = {};\n            for (r in e) o[r] = 0;\n            for (r in t) o[r] = 0;\n            for (r in o) if (!jspb.Message.compareFields(e[r], t[r])) return !1;\n            return !0;\n        }),\n        goog.exportProperty(jspb.Message, 'compareExtensions', jspb.Message.compareExtensions),\n        (jspb.Message.compareFields = function(e, t) {\n            if (e == t) return !0;\n            if (!goog.isObject(e) || !goog.isObject(t))\n                return (\n                    !!(('number' == typeof e && isNaN(e)) || ('number' == typeof t && isNaN(t))) &&\n                    String(e) == String(t)\n                );\n            if (e.constructor != t.constructor) return !1;\n            if (jspb.Message.SUPPORTS_UINT8ARRAY_ && e.constructor === Uint8Array) {\n                if (e.length != t.length) return !1;\n                for (var r = 0; r < e.length; r++) if (e[r] != t[r]) return !1;\n                return !0;\n            }\n            if (e.constructor === Array) {\n                var o = void 0,\n                    i = void 0,\n                    a = Math.max(e.length, t.length);\n                for (r = 0; r < a; r++) {\n                    var n = e[r],\n                        s = t[r];\n                    if (\n                        (n &&\n                            n.constructor == Object &&\n                            (jspb.asserts.assert(void 0 === o),\n                            jspb.asserts.assert(r === e.length - 1),\n                            (o = n),\n                            (n = void 0)),\n                        s &&\n                            s.constructor == Object &&\n                            (jspb.asserts.assert(void 0 === i),\n                            jspb.asserts.assert(r === t.length - 1),\n                            (i = s),\n                            (s = void 0)),\n                        !jspb.Message.compareFields(n, s))\n                    )\n                        return !1;\n                }\n                return (\n                    (!o && !i) ||\n                    ((o = o || {}), (i = i || {}), jspb.Message.compareExtensions(o, i))\n                );\n            }\n            if (e.constructor === Object) return jspb.Message.compareExtensions(e, t);\n            throw Error('Invalid type in JSPB array');\n        }),\n        goog.exportProperty(jspb.Message, 'compareFields', jspb.Message.compareFields),\n        (jspb.Message.prototype.cloneMessage = function() {\n            return jspb.Message.cloneMessage(this);\n        }),\n        goog.exportProperty(\n            jspb.Message.prototype,\n            'cloneMessage',\n            jspb.Message.prototype.cloneMessage\n        ),\n        (jspb.Message.prototype.clone = function() {\n            return jspb.Message.cloneMessage(this);\n        }),\n        goog.exportProperty(jspb.Message.prototype, 'clone', jspb.Message.prototype.clone),\n        (jspb.Message.clone = function(e) {\n            return jspb.Message.cloneMessage(e);\n        }),\n        goog.exportProperty(jspb.Message, 'clone', jspb.Message.clone),\n        (jspb.Message.cloneMessage = function(e) {\n            return new e.constructor(jspb.Message.clone_(e.toArray()));\n        }),\n        (jspb.Message.copyInto = function(e, t) {\n            jspb.asserts.assertInstanceof(e, jspb.Message),\n                jspb.asserts.assertInstanceof(t, jspb.Message),\n                jspb.asserts.assert(\n                    e.constructor == t.constructor,\n                    'Copy source and target message should have the same type.'\n                ),\n                (e = jspb.Message.clone(e));\n            for (var r = t.toArray(), o = e.toArray(), i = (r.length = 0); i < o.length; i++)\n                r[i] = o[i];\n            (t.wrappers_ = e.wrappers_), (t.extensionObject_ = e.extensionObject_);\n        }),\n        goog.exportProperty(jspb.Message, 'copyInto', jspb.Message.copyInto),\n        (jspb.Message.clone_ = function(e) {\n            if (Array.isArray(e)) {\n                for (var t = Array(e.length), r = 0; r < e.length; r++) {\n                    var o = e[r];\n                    null != o &&\n                        (t[r] =\n                            'object' == typeof o ? jspb.Message.clone_(jspb.asserts.assert(o)) : o);\n                }\n                return t;\n            }\n            if (jspb.Message.SUPPORTS_UINT8ARRAY_ && e instanceof Uint8Array)\n                return new Uint8Array(e);\n            for (r in ((t = {}), e))\n                null != (o = e[r]) &&\n                    (t[r] = 'object' == typeof o ? jspb.Message.clone_(jspb.asserts.assert(o)) : o);\n            return t;\n        }),\n        (jspb.Message.registerMessageType = function(e, t) {\n            t.messageId = e;\n        }),\n        goog.exportProperty(jspb.Message, 'registerMessageType', jspb.Message.registerMessageType),\n        (jspb.Message.messageSetExtensions = {}),\n        (jspb.Message.messageSetExtensionsBinary = {}),\n        (jspb.Export = {}),\n        (exports.Map = jspb.Map),\n        (exports.Message = jspb.Message),\n        (exports.BinaryReader = jspb.BinaryReader),\n        (exports.BinaryWriter = jspb.BinaryWriter),\n        (exports.ExtensionFieldInfo = jspb.ExtensionFieldInfo),\n        (exports.ExtensionFieldBinaryInfo = jspb.ExtensionFieldBinaryInfo),\n        (exports.exportSymbol = goog.exportSymbol),\n        (exports.inherits = goog.inherits),\n        (exports.object = { extend: goog.object.extend }),\n        (exports.typeOf = goog.typeOf);\n})(googleProtobuf);\nvar calculator_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.CalculatorOptions', null, o),\n        (proto.mediapipe.CalculatorOptions = function(e) {\n            t.Message.initialize(this, e, 0, 2, null, null);\n        }),\n        r.inherits(proto.mediapipe.CalculatorOptions, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.CalculatorOptions.displayName = 'proto.mediapipe.CalculatorOptions'),\n        (proto.mediapipe.CalculatorOptions.extensions = {}),\n        (proto.mediapipe.CalculatorOptions.extensionsBinary = {}),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.CalculatorOptions.prototype.toObject = function(e) {\n                return proto.mediapipe.CalculatorOptions.toObject(e, this);\n            }),\n            (proto.mediapipe.CalculatorOptions.toObject = function(e, r) {\n                var o,\n                    i = { mergeFields: null == (o = t.Message.getBooleanField(r, 1)) ? void 0 : o };\n                return (\n                    t.Message.toObjectExtension(\n                        r,\n                        i,\n                        proto.mediapipe.CalculatorOptions.extensions,\n                        proto.mediapipe.CalculatorOptions.prototype.getExtension,\n                        e\n                    ),\n                    e && (i.$jspbMessageInstance = r),\n                    i\n                );\n            })),\n        (proto.mediapipe.CalculatorOptions.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.CalculatorOptions();\n            return proto.mediapipe.CalculatorOptions.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.CalculatorOptions.deserializeBinaryFromReader = function(e, r) {\n            for (; r.nextField() && !r.isEndGroup(); ) {\n                if (1 === r.getFieldNumber()) {\n                    var o = r.readBool();\n                    e.setMergeFields(o);\n                } else\n                    t.Message.readBinaryExtension(\n                        e,\n                        r,\n                        proto.mediapipe.CalculatorOptions.extensionsBinary,\n                        proto.mediapipe.CalculatorOptions.prototype.getExtension,\n                        proto.mediapipe.CalculatorOptions.prototype.setExtension\n                    );\n            }\n            return e;\n        }),\n        (proto.mediapipe.CalculatorOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.CalculatorOptions.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.CalculatorOptions.serializeBinaryToWriter = function(e, r) {\n            var o;\n            null != (o = t.Message.getField(e, 1)) && r.writeBool(1, o),\n                t.Message.serializeBinaryExtensions(\n                    e,\n                    r,\n                    proto.mediapipe.CalculatorOptions.extensionsBinary,\n                    proto.mediapipe.CalculatorOptions.prototype.getExtension\n                );\n        }),\n        (proto.mediapipe.CalculatorOptions.prototype.getMergeFields = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 1, !1);\n        }),\n        (proto.mediapipe.CalculatorOptions.prototype.setMergeFields = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.CalculatorOptions.prototype.clearMergeFields = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.CalculatorOptions.prototype.hasMergeFields = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(calculator_options_pb);\nvar any_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.google.protobuf.Any', null, o),\n        (proto.google.protobuf.Any = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.google.protobuf.Any, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.google.protobuf.Any.displayName = 'proto.google.protobuf.Any'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.google.protobuf.Any.prototype.toObject = function(e) {\n                return proto.google.protobuf.Any.toObject(e, this);\n            }),\n            (proto.google.protobuf.Any.toObject = function(e, r) {\n                var o = {\n                    typeUrl: t.Message.getFieldWithDefault(r, 1, ''),\n                    value: r.getValue_asB64(),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.google.protobuf.Any.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.google.protobuf.Any();\n            return proto.google.protobuf.Any.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.google.protobuf.Any.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setTypeUrl(r);\n                        break;\n                    case 2:\n                        r = t.readBytes();\n                        e.setValue(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.google.protobuf.Any.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return proto.google.protobuf.Any.serializeBinaryToWriter(this, e), e.getResultBuffer();\n        }),\n        (proto.google.protobuf.Any.serializeBinaryToWriter = function(e, t) {\n            var r = void 0;\n            (r = e.getTypeUrl()).length > 0 && t.writeString(1, r),\n                (r = e.getValue_asU8()).length > 0 && t.writeBytes(2, r);\n        }),\n        (proto.google.protobuf.Any.prototype.getTypeUrl = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.google.protobuf.Any.prototype.setTypeUrl = function(e) {\n            return t.Message.setProto3StringField(this, 1, e);\n        }),\n        (proto.google.protobuf.Any.prototype.getValue = function() {\n            return t.Message.getFieldWithDefault(this, 2, '');\n        }),\n        (proto.google.protobuf.Any.prototype.getValue_asB64 = function() {\n            return t.Message.bytesAsB64(this.getValue());\n        }),\n        (proto.google.protobuf.Any.prototype.getValue_asU8 = function() {\n            return t.Message.bytesAsU8(this.getValue());\n        }),\n        (proto.google.protobuf.Any.prototype.setValue = function(e) {\n            return t.Message.setProto3BytesField(this, 2, e);\n        }),\n        r.object.extend(e, proto.google.protobuf),\n        (proto.google.protobuf.Any.prototype.getTypeName = function() {\n            return this.getTypeUrl()\n                .split('/')\n                .pop();\n        }),\n        (proto.google.protobuf.Any.prototype.pack = function(e, t, r) {\n            r || (r = 'type.googleapis.com/'),\n                '/' != r.substr(-1) ? this.setTypeUrl(r + '/' + t) : this.setTypeUrl(r + t),\n                this.setValue(e);\n        }),\n        (proto.google.protobuf.Any.prototype.unpack = function(e, t) {\n            return this.getTypeName() == t ? e(this.getValue_asU8()) : null;\n        });\n})(any_pb);\nvar mediapipe_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.MediaPipeOptions', null, o),\n        (proto.mediapipe.MediaPipeOptions = function(e) {\n            t.Message.initialize(this, e, 0, 1, null, null);\n        }),\n        r.inherits(proto.mediapipe.MediaPipeOptions, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.MediaPipeOptions.displayName = 'proto.mediapipe.MediaPipeOptions'),\n        (proto.mediapipe.MediaPipeOptions.extensions = {}),\n        (proto.mediapipe.MediaPipeOptions.extensionsBinary = {}),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.MediaPipeOptions.prototype.toObject = function(e) {\n                return proto.mediapipe.MediaPipeOptions.toObject(e, this);\n            }),\n            (proto.mediapipe.MediaPipeOptions.toObject = function(e, r) {\n                var o = {};\n                return (\n                    t.Message.toObjectExtension(\n                        r,\n                        o,\n                        proto.mediapipe.MediaPipeOptions.extensions,\n                        proto.mediapipe.MediaPipeOptions.prototype.getExtension,\n                        e\n                    ),\n                    e && (o.$jspbMessageInstance = r),\n                    o\n                );\n            })),\n        (proto.mediapipe.MediaPipeOptions.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.MediaPipeOptions();\n            return proto.mediapipe.MediaPipeOptions.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.MediaPipeOptions.deserializeBinaryFromReader = function(e, r) {\n            for (; r.nextField() && !r.isEndGroup(); ) {\n                r.getFieldNumber();\n                t.Message.readBinaryExtension(\n                    e,\n                    r,\n                    proto.mediapipe.MediaPipeOptions.extensionsBinary,\n                    proto.mediapipe.MediaPipeOptions.prototype.getExtension,\n                    proto.mediapipe.MediaPipeOptions.prototype.setExtension\n                );\n            }\n            return e;\n        }),\n        (proto.mediapipe.MediaPipeOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.MediaPipeOptions.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.MediaPipeOptions.serializeBinaryToWriter = function(e, r) {\n            t.Message.serializeBinaryExtensions(\n                e,\n                r,\n                proto.mediapipe.MediaPipeOptions.extensionsBinary,\n                proto.mediapipe.MediaPipeOptions.prototype.getExtension\n            );\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(mediapipe_options_pb);\nvar packet_factory_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.PacketFactoryConfig', null, o),\n        r.exportSymbol('proto.mediapipe.PacketFactoryOptions', null, o),\n        r.exportSymbol('proto.mediapipe.PacketManagerConfig', null, o),\n        (proto.mediapipe.PacketFactoryOptions = function(e) {\n            t.Message.initialize(this, e, 0, 1, null, null);\n        }),\n        r.inherits(proto.mediapipe.PacketFactoryOptions, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.PacketFactoryOptions.displayName =\n                'proto.mediapipe.PacketFactoryOptions'),\n        (proto.mediapipe.PacketFactoryOptions.extensions = {}),\n        (proto.mediapipe.PacketFactoryOptions.extensionsBinary = {}),\n        (proto.mediapipe.PacketFactoryConfig = function(e) {\n            t.Message.initialize(this, e, 0, 500, null, null);\n        }),\n        r.inherits(proto.mediapipe.PacketFactoryConfig, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.PacketFactoryConfig.displayName =\n                'proto.mediapipe.PacketFactoryConfig'),\n        (proto.mediapipe.PacketManagerConfig = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.PacketManagerConfig.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.PacketManagerConfig, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.PacketManagerConfig.displayName =\n                'proto.mediapipe.PacketManagerConfig'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.PacketFactoryOptions.prototype.toObject = function(e) {\n                return proto.mediapipe.PacketFactoryOptions.toObject(e, this);\n            }),\n            (proto.mediapipe.PacketFactoryOptions.toObject = function(e, r) {\n                var o = {};\n                return (\n                    t.Message.toObjectExtension(\n                        r,\n                        o,\n                        proto.mediapipe.PacketFactoryOptions.extensions,\n                        proto.mediapipe.PacketFactoryOptions.prototype.getExtension,\n                        e\n                    ),\n                    e && (o.$jspbMessageInstance = r),\n                    o\n                );\n            })),\n        (proto.mediapipe.PacketFactoryOptions.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.PacketFactoryOptions();\n            return proto.mediapipe.PacketFactoryOptions.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.PacketFactoryOptions.deserializeBinaryFromReader = function(e, r) {\n            for (; r.nextField() && !r.isEndGroup(); ) {\n                r.getFieldNumber();\n                t.Message.readBinaryExtension(\n                    e,\n                    r,\n                    proto.mediapipe.PacketFactoryOptions.extensionsBinary,\n                    proto.mediapipe.PacketFactoryOptions.prototype.getExtension,\n                    proto.mediapipe.PacketFactoryOptions.prototype.setExtension\n                );\n            }\n            return e;\n        }),\n        (proto.mediapipe.PacketFactoryOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.PacketFactoryOptions.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.PacketFactoryOptions.serializeBinaryToWriter = function(e, r) {\n            t.Message.serializeBinaryExtensions(\n                e,\n                r,\n                proto.mediapipe.PacketFactoryOptions.extensionsBinary,\n                proto.mediapipe.PacketFactoryOptions.prototype.getExtension\n            );\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.PacketFactoryConfig.prototype.toObject = function(e) {\n                return proto.mediapipe.PacketFactoryConfig.toObject(e, this);\n            }),\n            (proto.mediapipe.PacketFactoryConfig.toObject = function(e, r) {\n                var o,\n                    i = {\n                        packetFactory: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        outputSidePacket: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        externalOutput: null == (o = t.Message.getField(r, 1002)) ? void 0 : o,\n                        options:\n                            (o = r.getOptions()) &&\n                            proto.mediapipe.PacketFactoryOptions.toObject(e, o),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.PacketFactoryConfig.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.PacketFactoryConfig();\n            return proto.mediapipe.PacketFactoryConfig.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setPacketFactory(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.setOutputSidePacket(r);\n                        break;\n                    case 1002:\n                        r = t.readString();\n                        e.setExternalOutput(r);\n                        break;\n                    case 3:\n                        r = new proto.mediapipe.PacketFactoryOptions();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.PacketFactoryOptions.deserializeBinaryFromReader\n                        ),\n                            e.setOptions(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.PacketFactoryConfig.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.PacketFactoryConfig.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeString(2, o),\n                null != (o = t.Message.getField(e, 1002)) && r.writeString(1002, o),\n                null != (o = e.getOptions()) &&\n                    r.writeMessage(\n                        3,\n                        o,\n                        proto.mediapipe.PacketFactoryOptions.serializeBinaryToWriter\n                    );\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.getPacketFactory = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.setPacketFactory = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.clearPacketFactory = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.hasPacketFactory = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.getOutputSidePacket = function() {\n            return t.Message.getFieldWithDefault(this, 2, '');\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.setOutputSidePacket = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.clearOutputSidePacket = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.hasOutputSidePacket = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.getExternalOutput = function() {\n            return t.Message.getFieldWithDefault(this, 1002, '');\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.setExternalOutput = function(e) {\n            return t.Message.setField(this, 1002, e);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.clearExternalOutput = function() {\n            return t.Message.setField(this, 1002, void 0);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.hasExternalOutput = function() {\n            return null != t.Message.getField(this, 1002);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.getOptions = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.PacketFactoryOptions, 3);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.setOptions = function(e) {\n            return t.Message.setWrapperField(this, 3, e);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.clearOptions = function() {\n            return this.setOptions(void 0);\n        }),\n        (proto.mediapipe.PacketFactoryConfig.prototype.hasOptions = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.PacketManagerConfig.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.PacketManagerConfig.prototype.toObject = function(e) {\n                return proto.mediapipe.PacketManagerConfig.toObject(e, this);\n            }),\n            (proto.mediapipe.PacketManagerConfig.toObject = function(e, r) {\n                var o = {\n                    packetList: t.Message.toObjectList(\n                        r.getPacketList(),\n                        proto.mediapipe.PacketFactoryConfig.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.PacketManagerConfig.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.PacketManagerConfig();\n            return proto.mediapipe.PacketManagerConfig.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.PacketManagerConfig.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.PacketFactoryConfig();\n                    t.readMessage(\n                        r,\n                        proto.mediapipe.PacketFactoryConfig.deserializeBinaryFromReader\n                    ),\n                        e.addPacket(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.PacketManagerConfig.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.PacketManagerConfig.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.PacketManagerConfig.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getPacketList()).length > 0 &&\n                t.writeRepeatedMessage(\n                    1,\n                    r,\n                    proto.mediapipe.PacketFactoryConfig.serializeBinaryToWriter\n                );\n        }),\n        (proto.mediapipe.PacketManagerConfig.prototype.getPacketList = function() {\n            return t.Message.getRepeatedWrapperField(this, proto.mediapipe.PacketFactoryConfig, 1);\n        }),\n        (proto.mediapipe.PacketManagerConfig.prototype.setPacketList = function(e) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.PacketManagerConfig.prototype.addPacket = function(e, r) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.PacketFactoryConfig,\n                r\n            );\n        }),\n        (proto.mediapipe.PacketManagerConfig.prototype.clearPacketList = function() {\n            return this.setPacketList([]);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(packet_factory_pb);\nvar packet_generator_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.PacketGeneratorConfig', null, o),\n        r.exportSymbol('proto.mediapipe.PacketGeneratorOptions', null, o),\n        (proto.mediapipe.PacketGeneratorOptions = function(e) {\n            t.Message.initialize(this, e, 0, 2, null, null);\n        }),\n        r.inherits(proto.mediapipe.PacketGeneratorOptions, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.PacketGeneratorOptions.displayName =\n                'proto.mediapipe.PacketGeneratorOptions'),\n        (proto.mediapipe.PacketGeneratorOptions.extensions = {}),\n        (proto.mediapipe.PacketGeneratorOptions.extensionsBinary = {}),\n        (proto.mediapipe.PacketGeneratorConfig = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                500,\n                proto.mediapipe.PacketGeneratorConfig.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.PacketGeneratorConfig, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.PacketGeneratorConfig.displayName =\n                'proto.mediapipe.PacketGeneratorConfig'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.PacketGeneratorOptions.prototype.toObject = function(e) {\n                return proto.mediapipe.PacketGeneratorOptions.toObject(e, this);\n            }),\n            (proto.mediapipe.PacketGeneratorOptions.toObject = function(e, r) {\n                var o = { mergeFields: t.Message.getBooleanFieldWithDefault(r, 1, !0) };\n                return (\n                    t.Message.toObjectExtension(\n                        r,\n                        o,\n                        proto.mediapipe.PacketGeneratorOptions.extensions,\n                        proto.mediapipe.PacketGeneratorOptions.prototype.getExtension,\n                        e\n                    ),\n                    e && (o.$jspbMessageInstance = r),\n                    o\n                );\n            })),\n        (proto.mediapipe.PacketGeneratorOptions.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.PacketGeneratorOptions();\n            return proto.mediapipe.PacketGeneratorOptions.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.PacketGeneratorOptions.deserializeBinaryFromReader = function(e, r) {\n            for (; r.nextField() && !r.isEndGroup(); ) {\n                if (1 === r.getFieldNumber()) {\n                    var o = r.readBool();\n                    e.setMergeFields(o);\n                } else\n                    t.Message.readBinaryExtension(\n                        e,\n                        r,\n                        proto.mediapipe.PacketGeneratorOptions.extensionsBinary,\n                        proto.mediapipe.PacketGeneratorOptions.prototype.getExtension,\n                        proto.mediapipe.PacketGeneratorOptions.prototype.setExtension\n                    );\n            }\n            return e;\n        }),\n        (proto.mediapipe.PacketGeneratorOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.PacketGeneratorOptions.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.PacketGeneratorOptions.serializeBinaryToWriter = function(e, r) {\n            var o;\n            null != (o = t.Message.getField(e, 1)) && r.writeBool(1, o),\n                t.Message.serializeBinaryExtensions(\n                    e,\n                    r,\n                    proto.mediapipe.PacketGeneratorOptions.extensionsBinary,\n                    proto.mediapipe.PacketGeneratorOptions.prototype.getExtension\n                );\n        }),\n        (proto.mediapipe.PacketGeneratorOptions.prototype.getMergeFields = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 1, !0);\n        }),\n        (proto.mediapipe.PacketGeneratorOptions.prototype.setMergeFields = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.PacketGeneratorOptions.prototype.clearMergeFields = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.PacketGeneratorOptions.prototype.hasMergeFields = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.repeatedFields_ = [2, 1002, 3, 1003]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.PacketGeneratorConfig.prototype.toObject = function(e) {\n                return proto.mediapipe.PacketGeneratorConfig.toObject(e, this);\n            }),\n            (proto.mediapipe.PacketGeneratorConfig.toObject = function(e, r) {\n                var o,\n                    i = {\n                        packetGenerator: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        inputSidePacketList:\n                            null == (o = t.Message.getRepeatedField(r, 2)) ? void 0 : o,\n                        externalInputList:\n                            null == (o = t.Message.getRepeatedField(r, 1002)) ? void 0 : o,\n                        outputSidePacketList:\n                            null == (o = t.Message.getRepeatedField(r, 3)) ? void 0 : o,\n                        externalOutputList:\n                            null == (o = t.Message.getRepeatedField(r, 1003)) ? void 0 : o,\n                        options:\n                            (o = r.getOptions()) &&\n                            proto.mediapipe.PacketGeneratorOptions.toObject(e, o),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.PacketGeneratorConfig.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.PacketGeneratorConfig();\n            return proto.mediapipe.PacketGeneratorConfig.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setPacketGenerator(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.addInputSidePacket(r);\n                        break;\n                    case 1002:\n                        r = t.readString();\n                        e.addExternalInput(r);\n                        break;\n                    case 3:\n                        r = t.readString();\n                        e.addOutputSidePacket(r);\n                        break;\n                    case 1003:\n                        r = t.readString();\n                        e.addExternalOutput(r);\n                        break;\n                    case 4:\n                        r = new proto.mediapipe.PacketGeneratorOptions();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.PacketGeneratorOptions.deserializeBinaryFromReader\n                        ),\n                            e.setOptions(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.PacketGeneratorConfig.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                (o = e.getInputSidePacketList()).length > 0 && r.writeRepeatedString(2, o),\n                (o = e.getExternalInputList()).length > 0 && r.writeRepeatedString(1002, o),\n                (o = e.getOutputSidePacketList()).length > 0 && r.writeRepeatedString(3, o),\n                (o = e.getExternalOutputList()).length > 0 && r.writeRepeatedString(1003, o),\n                null != (o = e.getOptions()) &&\n                    r.writeMessage(\n                        4,\n                        o,\n                        proto.mediapipe.PacketGeneratorOptions.serializeBinaryToWriter\n                    );\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.getPacketGenerator = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.setPacketGenerator = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.clearPacketGenerator = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.hasPacketGenerator = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.getInputSidePacketList = function() {\n            return t.Message.getRepeatedField(this, 2);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.setInputSidePacketList = function(e) {\n            return t.Message.setField(this, 2, e || []);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.addInputSidePacket = function(e, r) {\n            return t.Message.addToRepeatedField(this, 2, e, r);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.clearInputSidePacketList = function() {\n            return this.setInputSidePacketList([]);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.getExternalInputList = function() {\n            return t.Message.getRepeatedField(this, 1002);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.setExternalInputList = function(e) {\n            return t.Message.setField(this, 1002, e || []);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.addExternalInput = function(e, r) {\n            return t.Message.addToRepeatedField(this, 1002, e, r);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.clearExternalInputList = function() {\n            return this.setExternalInputList([]);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.getOutputSidePacketList = function() {\n            return t.Message.getRepeatedField(this, 3);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.setOutputSidePacketList = function(e) {\n            return t.Message.setField(this, 3, e || []);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.addOutputSidePacket = function(e, r) {\n            return t.Message.addToRepeatedField(this, 3, e, r);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.clearOutputSidePacketList = function() {\n            return this.setOutputSidePacketList([]);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.getExternalOutputList = function() {\n            return t.Message.getRepeatedField(this, 1003);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.setExternalOutputList = function(e) {\n            return t.Message.setField(this, 1003, e || []);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.addExternalOutput = function(e, r) {\n            return t.Message.addToRepeatedField(this, 1003, e, r);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.clearExternalOutputList = function() {\n            return this.setExternalOutputList([]);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.getOptions = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.PacketGeneratorOptions, 4);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.setOptions = function(e) {\n            return t.Message.setWrapperField(this, 4, e);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.clearOptions = function() {\n            return this.setOptions(void 0);\n        }),\n        (proto.mediapipe.PacketGeneratorConfig.prototype.hasOptions = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(packet_generator_pb);\nvar status_handler_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = mediapipe_options_pb;\n    r.object.extend(proto, i),\n        r.exportSymbol('proto.mediapipe.StatusHandlerConfig', null, o),\n        (proto.mediapipe.StatusHandlerConfig = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                500,\n                proto.mediapipe.StatusHandlerConfig.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.StatusHandlerConfig, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.StatusHandlerConfig.displayName =\n                'proto.mediapipe.StatusHandlerConfig'),\n        (proto.mediapipe.StatusHandlerConfig.repeatedFields_ = [2, 1002]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.StatusHandlerConfig.prototype.toObject = function(e) {\n                return proto.mediapipe.StatusHandlerConfig.toObject(e, this);\n            }),\n            (proto.mediapipe.StatusHandlerConfig.toObject = function(e, r) {\n                var o,\n                    a = {\n                        statusHandler: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        inputSidePacketList:\n                            null == (o = t.Message.getRepeatedField(r, 2)) ? void 0 : o,\n                        externalInputList:\n                            null == (o = t.Message.getRepeatedField(r, 1002)) ? void 0 : o,\n                        options: (o = r.getOptions()) && i.MediaPipeOptions.toObject(e, o),\n                    };\n                return e && (a.$jspbMessageInstance = r), a;\n            })),\n        (proto.mediapipe.StatusHandlerConfig.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.StatusHandlerConfig();\n            return proto.mediapipe.StatusHandlerConfig.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setStatusHandler(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.addInputSidePacket(r);\n                        break;\n                    case 1002:\n                        r = t.readString();\n                        e.addExternalInput(r);\n                        break;\n                    case 3:\n                        r = new i.MediaPipeOptions();\n                        t.readMessage(r, i.MediaPipeOptions.deserializeBinaryFromReader),\n                            e.setOptions(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.StatusHandlerConfig.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.StatusHandlerConfig.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                (o = e.getInputSidePacketList()).length > 0 && r.writeRepeatedString(2, o),\n                (o = e.getExternalInputList()).length > 0 && r.writeRepeatedString(1002, o),\n                null != (o = e.getOptions()) &&\n                    r.writeMessage(3, o, i.MediaPipeOptions.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.getStatusHandler = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.setStatusHandler = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.clearStatusHandler = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.hasStatusHandler = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.getInputSidePacketList = function() {\n            return t.Message.getRepeatedField(this, 2);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.setInputSidePacketList = function(e) {\n            return t.Message.setField(this, 2, e || []);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.addInputSidePacket = function(e, r) {\n            return t.Message.addToRepeatedField(this, 2, e, r);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.clearInputSidePacketList = function() {\n            return this.setInputSidePacketList([]);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.getExternalInputList = function() {\n            return t.Message.getRepeatedField(this, 1002);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.setExternalInputList = function(e) {\n            return t.Message.setField(this, 1002, e || []);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.addExternalInput = function(e, r) {\n            return t.Message.addToRepeatedField(this, 1002, e, r);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.clearExternalInputList = function() {\n            return this.setExternalInputList([]);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.getOptions = function() {\n            return t.Message.getWrapperField(this, i.MediaPipeOptions, 3);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.setOptions = function(e) {\n            return t.Message.setWrapperField(this, 3, e);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.clearOptions = function() {\n            return this.setOptions(void 0);\n        }),\n        (proto.mediapipe.StatusHandlerConfig.prototype.hasOptions = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(status_handler_pb);\nvar stream_handler_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = mediapipe_options_pb;\n    r.object.extend(proto, i),\n        r.exportSymbol('proto.mediapipe.InputStreamHandlerConfig', null, o),\n        r.exportSymbol('proto.mediapipe.OutputStreamHandlerConfig', null, o),\n        (proto.mediapipe.InputStreamHandlerConfig = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.InputStreamHandlerConfig, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.InputStreamHandlerConfig.displayName =\n                'proto.mediapipe.InputStreamHandlerConfig'),\n        (proto.mediapipe.OutputStreamHandlerConfig = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.OutputStreamHandlerConfig.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.OutputStreamHandlerConfig, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.OutputStreamHandlerConfig.displayName =\n                'proto.mediapipe.OutputStreamHandlerConfig'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.InputStreamHandlerConfig.prototype.toObject = function(e) {\n                return proto.mediapipe.InputStreamHandlerConfig.toObject(e, this);\n            }),\n            (proto.mediapipe.InputStreamHandlerConfig.toObject = function(e, r) {\n                var o,\n                    a = {\n                        inputStreamHandler: t.Message.getFieldWithDefault(\n                            r,\n                            1,\n                            'DefaultInputStreamHandler'\n                        ),\n                        options: (o = r.getOptions()) && i.MediaPipeOptions.toObject(e, o),\n                    };\n                return e && (a.$jspbMessageInstance = r), a;\n            })),\n        (proto.mediapipe.InputStreamHandlerConfig.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.InputStreamHandlerConfig();\n            return proto.mediapipe.InputStreamHandlerConfig.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setInputStreamHandler(r);\n                        break;\n                    case 3:\n                        r = new i.MediaPipeOptions();\n                        t.readMessage(r, i.MediaPipeOptions.deserializeBinaryFromReader),\n                            e.setOptions(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.InputStreamHandlerConfig.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                null != (o = e.getOptions()) &&\n                    r.writeMessage(3, o, i.MediaPipeOptions.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.getInputStreamHandler = function() {\n            return t.Message.getFieldWithDefault(this, 1, 'DefaultInputStreamHandler');\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.setInputStreamHandler = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.clearInputStreamHandler = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.hasInputStreamHandler = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.getOptions = function() {\n            return t.Message.getWrapperField(this, i.MediaPipeOptions, 3);\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.setOptions = function(e) {\n            return t.Message.setWrapperField(this, 3, e);\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.clearOptions = function() {\n            return this.setOptions(void 0);\n        }),\n        (proto.mediapipe.InputStreamHandlerConfig.prototype.hasOptions = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.repeatedFields_ = [2]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.OutputStreamHandlerConfig.prototype.toObject = function(e) {\n                return proto.mediapipe.OutputStreamHandlerConfig.toObject(e, this);\n            }),\n            (proto.mediapipe.OutputStreamHandlerConfig.toObject = function(e, r) {\n                var o,\n                    a = {\n                        outputStreamHandler: t.Message.getFieldWithDefault(\n                            r,\n                            1,\n                            'InOrderOutputStreamHandler'\n                        ),\n                        inputSidePacketList:\n                            null == (o = t.Message.getRepeatedField(r, 2)) ? void 0 : o,\n                        options: (o = r.getOptions()) && i.MediaPipeOptions.toObject(e, o),\n                    };\n                return e && (a.$jspbMessageInstance = r), a;\n            })),\n        (proto.mediapipe.OutputStreamHandlerConfig.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.OutputStreamHandlerConfig();\n            return proto.mediapipe.OutputStreamHandlerConfig.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setOutputStreamHandler(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.addInputSidePacket(r);\n                        break;\n                    case 3:\n                        r = new i.MediaPipeOptions();\n                        t.readMessage(r, i.MediaPipeOptions.deserializeBinaryFromReader),\n                            e.setOptions(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.OutputStreamHandlerConfig.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                (o = e.getInputSidePacketList()).length > 0 && r.writeRepeatedString(2, o),\n                null != (o = e.getOptions()) &&\n                    r.writeMessage(3, o, i.MediaPipeOptions.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.getOutputStreamHandler = function() {\n            return t.Message.getFieldWithDefault(this, 1, 'InOrderOutputStreamHandler');\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.setOutputStreamHandler = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.clearOutputStreamHandler = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.hasOutputStreamHandler = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.getInputSidePacketList = function() {\n            return t.Message.getRepeatedField(this, 2);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.setInputSidePacketList = function(e) {\n            return t.Message.setField(this, 2, e || []);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.addInputSidePacket = function(e, r) {\n            return t.Message.addToRepeatedField(this, 2, e, r);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.clearInputSidePacketList = function() {\n            return this.setInputSidePacketList([]);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.getOptions = function() {\n            return t.Message.getWrapperField(this, i.MediaPipeOptions, 3);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.setOptions = function(e) {\n            return t.Message.setWrapperField(this, 3, e);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.clearOptions = function() {\n            return this.setOptions(void 0);\n        }),\n        (proto.mediapipe.OutputStreamHandlerConfig.prototype.hasOptions = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(stream_handler_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_options_pb;\n        r.object.extend(proto, i);\n        var a = any_pb;\n        r.object.extend(proto, a);\n        var n = mediapipe_options_pb;\n        r.object.extend(proto, n);\n        var s = packet_factory_pb;\n        r.object.extend(proto, s);\n        var p = packet_generator_pb;\n        r.object.extend(proto, p);\n        var d = status_handler_pb;\n        r.object.extend(proto, d);\n        var l = stream_handler_pb;\n        r.object.extend(proto, l),\n            r.exportSymbol('proto.mediapipe.CalculatorGraphConfig', null, o),\n            r.exportSymbol('proto.mediapipe.CalculatorGraphConfig.Node', null, o),\n            r.exportSymbol('proto.mediapipe.ExecutorConfig', null, o),\n            r.exportSymbol('proto.mediapipe.InputCollection', null, o),\n            r.exportSymbol('proto.mediapipe.InputCollection.InputType', null, o),\n            r.exportSymbol('proto.mediapipe.InputCollectionSet', null, o),\n            r.exportSymbol('proto.mediapipe.InputStreamInfo', null, o),\n            r.exportSymbol('proto.mediapipe.ProfilerConfig', null, o),\n            (proto.mediapipe.ExecutorConfig = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.ExecutorConfig, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.ExecutorConfig.displayName = 'proto.mediapipe.ExecutorConfig'),\n            (proto.mediapipe.InputCollection = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    500,\n                    proto.mediapipe.InputCollection.repeatedFields_,\n                    null\n                );\n            }),\n            r.inherits(proto.mediapipe.InputCollection, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.InputCollection.displayName = 'proto.mediapipe.InputCollection'),\n            (proto.mediapipe.InputCollectionSet = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    -1,\n                    proto.mediapipe.InputCollectionSet.repeatedFields_,\n                    null\n                );\n            }),\n            r.inherits(proto.mediapipe.InputCollectionSet, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.InputCollectionSet.displayName =\n                    'proto.mediapipe.InputCollectionSet'),\n            (proto.mediapipe.InputStreamInfo = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.InputStreamInfo, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.InputStreamInfo.displayName = 'proto.mediapipe.InputStreamInfo'),\n            (proto.mediapipe.ProfilerConfig = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    -1,\n                    proto.mediapipe.ProfilerConfig.repeatedFields_,\n                    null\n                );\n            }),\n            r.inherits(proto.mediapipe.ProfilerConfig, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.ProfilerConfig.displayName = 'proto.mediapipe.ProfilerConfig'),\n            (proto.mediapipe.CalculatorGraphConfig = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    500,\n                    proto.mediapipe.CalculatorGraphConfig.repeatedFields_,\n                    null\n                );\n            }),\n            r.inherits(proto.mediapipe.CalculatorGraphConfig, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.CalculatorGraphConfig.displayName =\n                    'proto.mediapipe.CalculatorGraphConfig'),\n            (proto.mediapipe.CalculatorGraphConfig.Node = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    500,\n                    proto.mediapipe.CalculatorGraphConfig.Node.repeatedFields_,\n                    null\n                );\n            }),\n            r.inherits(proto.mediapipe.CalculatorGraphConfig.Node, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.CalculatorGraphConfig.Node.displayName =\n                    'proto.mediapipe.CalculatorGraphConfig.Node'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.ExecutorConfig.prototype.toObject = function(e) {\n                    return proto.mediapipe.ExecutorConfig.toObject(e, this);\n                }),\n                (proto.mediapipe.ExecutorConfig.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            name: t.Message.getFieldWithDefault(r, 1, ''),\n                            type: t.Message.getFieldWithDefault(r, 2, ''),\n                            options: (o = r.getOptions()) && n.MediaPipeOptions.toObject(e, o),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.ExecutorConfig.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.ExecutorConfig();\n                return proto.mediapipe.ExecutorConfig.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.ExecutorConfig.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readString();\n                            e.setName(r);\n                            break;\n                        case 2:\n                            r = t.readString();\n                            e.setType(r);\n                            break;\n                        case 3:\n                            r = new n.MediaPipeOptions();\n                            t.readMessage(r, n.MediaPipeOptions.deserializeBinaryFromReader),\n                                e.setOptions(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.ExecutorConfig.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.ExecutorConfig.serializeBinaryToWriter = function(e, t) {\n                var r = void 0;\n                (r = e.getName()).length > 0 && t.writeString(1, r),\n                    (r = e.getType()).length > 0 && t.writeString(2, r),\n                    null != (r = e.getOptions()) &&\n                        t.writeMessage(3, r, n.MediaPipeOptions.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.getName = function() {\n                return t.Message.getFieldWithDefault(this, 1, '');\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.setName = function(e) {\n                return t.Message.setProto3StringField(this, 1, e);\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.getType = function() {\n                return t.Message.getFieldWithDefault(this, 2, '');\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.setType = function(e) {\n                return t.Message.setProto3StringField(this, 2, e);\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.getOptions = function() {\n                return t.Message.getWrapperField(this, n.MediaPipeOptions, 3);\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.setOptions = function(e) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.clearOptions = function() {\n                return this.setOptions(void 0);\n            }),\n            (proto.mediapipe.ExecutorConfig.prototype.hasOptions = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.InputCollection.repeatedFields_ = [2, 1002]),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.InputCollection.prototype.toObject = function(e) {\n                    return proto.mediapipe.InputCollection.toObject(e, this);\n                }),\n                (proto.mediapipe.InputCollection.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            name: t.Message.getFieldWithDefault(r, 1, ''),\n                            sidePacketNameList:\n                                null == (o = t.Message.getRepeatedField(r, 2)) ? void 0 : o,\n                            externalInputNameList:\n                                null == (o = t.Message.getRepeatedField(r, 1002)) ? void 0 : o,\n                            inputType: t.Message.getFieldWithDefault(r, 3, 0),\n                            fileName: t.Message.getFieldWithDefault(r, 4, ''),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.InputCollection.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.InputCollection();\n                return proto.mediapipe.InputCollection.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.InputCollection.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readString();\n                            e.setName(r);\n                            break;\n                        case 2:\n                            r = t.readString();\n                            e.addSidePacketName(r);\n                            break;\n                        case 1002:\n                            r = t.readString();\n                            e.addExternalInputName(r);\n                            break;\n                        case 3:\n                            r = t.readEnum();\n                            e.setInputType(r);\n                            break;\n                        case 4:\n                            r = t.readString();\n                            e.setFileName(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.InputCollection.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.InputCollection.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.InputCollection.serializeBinaryToWriter = function(e, t) {\n                var r = void 0;\n                (r = e.getName()).length > 0 && t.writeString(1, r),\n                    (r = e.getSidePacketNameList()).length > 0 && t.writeRepeatedString(2, r),\n                    (r = e.getExternalInputNameList()).length > 0 && t.writeRepeatedString(1002, r),\n                    0 !== (r = e.getInputType()) && t.writeEnum(3, r),\n                    (r = e.getFileName()).length > 0 && t.writeString(4, r);\n            }),\n            (proto.mediapipe.InputCollection.InputType = {\n                UNKNOWN: 0,\n                RECORDIO: 1,\n                FOREIGN_RECORDIO: 2,\n                FOREIGN_CSV_TEXT: 3,\n                INVALID_UPPER_BOUND: 4,\n            }),\n            (proto.mediapipe.InputCollection.prototype.getName = function() {\n                return t.Message.getFieldWithDefault(this, 1, '');\n            }),\n            (proto.mediapipe.InputCollection.prototype.setName = function(e) {\n                return t.Message.setProto3StringField(this, 1, e);\n            }),\n            (proto.mediapipe.InputCollection.prototype.getSidePacketNameList = function() {\n                return t.Message.getRepeatedField(this, 2);\n            }),\n            (proto.mediapipe.InputCollection.prototype.setSidePacketNameList = function(e) {\n                return t.Message.setField(this, 2, e || []);\n            }),\n            (proto.mediapipe.InputCollection.prototype.addSidePacketName = function(e, r) {\n                return t.Message.addToRepeatedField(this, 2, e, r);\n            }),\n            (proto.mediapipe.InputCollection.prototype.clearSidePacketNameList = function() {\n                return this.setSidePacketNameList([]);\n            }),\n            (proto.mediapipe.InputCollection.prototype.getExternalInputNameList = function() {\n                return t.Message.getRepeatedField(this, 1002);\n            }),\n            (proto.mediapipe.InputCollection.prototype.setExternalInputNameList = function(e) {\n                return t.Message.setField(this, 1002, e || []);\n            }),\n            (proto.mediapipe.InputCollection.prototype.addExternalInputName = function(e, r) {\n                return t.Message.addToRepeatedField(this, 1002, e, r);\n            }),\n            (proto.mediapipe.InputCollection.prototype.clearExternalInputNameList = function() {\n                return this.setExternalInputNameList([]);\n            }),\n            (proto.mediapipe.InputCollection.prototype.getInputType = function() {\n                return t.Message.getFieldWithDefault(this, 3, 0);\n            }),\n            (proto.mediapipe.InputCollection.prototype.setInputType = function(e) {\n                return t.Message.setProto3EnumField(this, 3, e);\n            }),\n            (proto.mediapipe.InputCollection.prototype.getFileName = function() {\n                return t.Message.getFieldWithDefault(this, 4, '');\n            }),\n            (proto.mediapipe.InputCollection.prototype.setFileName = function(e) {\n                return t.Message.setProto3StringField(this, 4, e);\n            }),\n            (proto.mediapipe.InputCollectionSet.repeatedFields_ = [1]),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.InputCollectionSet.prototype.toObject = function(e) {\n                    return proto.mediapipe.InputCollectionSet.toObject(e, this);\n                }),\n                (proto.mediapipe.InputCollectionSet.toObject = function(e, r) {\n                    var o = {\n                        inputCollectionList: t.Message.toObjectList(\n                            r.getInputCollectionList(),\n                            proto.mediapipe.InputCollection.toObject,\n                            e\n                        ),\n                    };\n                    return e && (o.$jspbMessageInstance = r), o;\n                })),\n            (proto.mediapipe.InputCollectionSet.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.InputCollectionSet();\n                return proto.mediapipe.InputCollectionSet.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.InputCollectionSet.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    if (1 === t.getFieldNumber()) {\n                        var r = new proto.mediapipe.InputCollection();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.InputCollection.deserializeBinaryFromReader\n                        ),\n                            e.addInputCollection(r);\n                    } else t.skipField();\n                }\n                return e;\n            }),\n            (proto.mediapipe.InputCollectionSet.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.InputCollectionSet.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.InputCollectionSet.serializeBinaryToWriter = function(e, t) {\n                var r;\n                (r = e.getInputCollectionList()).length > 0 &&\n                    t.writeRepeatedMessage(\n                        1,\n                        r,\n                        proto.mediapipe.InputCollection.serializeBinaryToWriter\n                    );\n            }),\n            (proto.mediapipe.InputCollectionSet.prototype.getInputCollectionList = function() {\n                return t.Message.getRepeatedWrapperField(this, proto.mediapipe.InputCollection, 1);\n            }),\n            (proto.mediapipe.InputCollectionSet.prototype.setInputCollectionList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.InputCollectionSet.prototype.addInputCollection = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    1,\n                    e,\n                    proto.mediapipe.InputCollection,\n                    r\n                );\n            }),\n            (proto.mediapipe.InputCollectionSet.prototype.clearInputCollectionList = function() {\n                return this.setInputCollectionList([]);\n            }),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.InputStreamInfo.prototype.toObject = function(e) {\n                    return proto.mediapipe.InputStreamInfo.toObject(e, this);\n                }),\n                (proto.mediapipe.InputStreamInfo.toObject = function(e, r) {\n                    var o = {\n                        tagIndex: t.Message.getFieldWithDefault(r, 1, ''),\n                        backEdge: t.Message.getBooleanFieldWithDefault(r, 2, !1),\n                    };\n                    return e && (o.$jspbMessageInstance = r), o;\n                })),\n            (proto.mediapipe.InputStreamInfo.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.InputStreamInfo();\n                return proto.mediapipe.InputStreamInfo.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.InputStreamInfo.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readString();\n                            e.setTagIndex(r);\n                            break;\n                        case 2:\n                            r = t.readBool();\n                            e.setBackEdge(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.InputStreamInfo.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.InputStreamInfo.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.InputStreamInfo.serializeBinaryToWriter = function(e, t) {\n                var r = void 0;\n                (r = e.getTagIndex()).length > 0 && t.writeString(1, r),\n                    (r = e.getBackEdge()) && t.writeBool(2, r);\n            }),\n            (proto.mediapipe.InputStreamInfo.prototype.getTagIndex = function() {\n                return t.Message.getFieldWithDefault(this, 1, '');\n            }),\n            (proto.mediapipe.InputStreamInfo.prototype.setTagIndex = function(e) {\n                return t.Message.setProto3StringField(this, 1, e);\n            }),\n            (proto.mediapipe.InputStreamInfo.prototype.getBackEdge = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 2, !1);\n            }),\n            (proto.mediapipe.InputStreamInfo.prototype.setBackEdge = function(e) {\n                return t.Message.setProto3BooleanField(this, 2, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.repeatedFields_ = [8]),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.ProfilerConfig.prototype.toObject = function(e) {\n                    return proto.mediapipe.ProfilerConfig.toObject(e, this);\n                }),\n                (proto.mediapipe.ProfilerConfig.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            histogramIntervalSizeUsec: t.Message.getFieldWithDefault(r, 1, 0),\n                            numHistogramIntervals: t.Message.getFieldWithDefault(r, 2, 0),\n                            enableInputOutputLatency: t.Message.getBooleanFieldWithDefault(\n                                r,\n                                3,\n                                !1\n                            ),\n                            enableProfiler: t.Message.getBooleanFieldWithDefault(r, 4, !1),\n                            enableStreamLatency: t.Message.getBooleanFieldWithDefault(r, 5, !1),\n                            usePacketTimestampForAddedPacket: t.Message.getBooleanFieldWithDefault(\n                                r,\n                                6,\n                                !1\n                            ),\n                            traceLogCapacity: t.Message.getFieldWithDefault(r, 7, 0),\n                            traceEventTypesDisabledList:\n                                null == (o = t.Message.getRepeatedField(r, 8)) ? void 0 : o,\n                            traceLogPath: t.Message.getFieldWithDefault(r, 9, ''),\n                            traceLogCount: t.Message.getFieldWithDefault(r, 10, 0),\n                            traceLogIntervalUsec: t.Message.getFieldWithDefault(r, 11, 0),\n                            traceLogMarginUsec: t.Message.getFieldWithDefault(r, 12, 0),\n                            traceLogDurationEvents: t.Message.getBooleanFieldWithDefault(r, 13, !1),\n                            traceLogIntervalCount: t.Message.getFieldWithDefault(r, 14, 0),\n                            traceLogDisabled: t.Message.getBooleanFieldWithDefault(r, 15, !1),\n                            traceEnabled: t.Message.getBooleanFieldWithDefault(r, 16, !1),\n                            traceLogInstantEvents: t.Message.getBooleanFieldWithDefault(r, 17, !1),\n                            calculatorFilter: t.Message.getFieldWithDefault(r, 18, ''),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.ProfilerConfig.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.ProfilerConfig();\n                return proto.mediapipe.ProfilerConfig.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.ProfilerConfig.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readInt64();\n                            e.setHistogramIntervalSizeUsec(r);\n                            break;\n                        case 2:\n                            r = t.readInt64();\n                            e.setNumHistogramIntervals(r);\n                            break;\n                        case 3:\n                            r = t.readBool();\n                            e.setEnableInputOutputLatency(r);\n                            break;\n                        case 4:\n                            r = t.readBool();\n                            e.setEnableProfiler(r);\n                            break;\n                        case 5:\n                            r = t.readBool();\n                            e.setEnableStreamLatency(r);\n                            break;\n                        case 6:\n                            r = t.readBool();\n                            e.setUsePacketTimestampForAddedPacket(r);\n                            break;\n                        case 7:\n                            r = t.readInt64();\n                            e.setTraceLogCapacity(r);\n                            break;\n                        case 8:\n                            for (\n                                var o = t.isDelimited() ? t.readPackedInt32() : [t.readInt32()],\n                                    i = 0;\n                                i < o.length;\n                                i++\n                            )\n                                e.addTraceEventTypesDisabled(o[i]);\n                            break;\n                        case 9:\n                            r = t.readString();\n                            e.setTraceLogPath(r);\n                            break;\n                        case 10:\n                            r = t.readInt32();\n                            e.setTraceLogCount(r);\n                            break;\n                        case 11:\n                            r = t.readInt64();\n                            e.setTraceLogIntervalUsec(r);\n                            break;\n                        case 12:\n                            r = t.readInt64();\n                            e.setTraceLogMarginUsec(r);\n                            break;\n                        case 13:\n                            r = t.readBool();\n                            e.setTraceLogDurationEvents(r);\n                            break;\n                        case 14:\n                            r = t.readInt32();\n                            e.setTraceLogIntervalCount(r);\n                            break;\n                        case 15:\n                            r = t.readBool();\n                            e.setTraceLogDisabled(r);\n                            break;\n                        case 16:\n                            r = t.readBool();\n                            e.setTraceEnabled(r);\n                            break;\n                        case 17:\n                            r = t.readBool();\n                            e.setTraceLogInstantEvents(r);\n                            break;\n                        case 18:\n                            r = t.readString();\n                            e.setCalculatorFilter(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.ProfilerConfig.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.ProfilerConfig.serializeBinaryToWriter = function(e, t) {\n                var r = void 0;\n                0 !== (r = e.getHistogramIntervalSizeUsec()) && t.writeInt64(1, r),\n                    0 !== (r = e.getNumHistogramIntervals()) && t.writeInt64(2, r),\n                    (r = e.getEnableInputOutputLatency()) && t.writeBool(3, r),\n                    (r = e.getEnableProfiler()) && t.writeBool(4, r),\n                    (r = e.getEnableStreamLatency()) && t.writeBool(5, r),\n                    (r = e.getUsePacketTimestampForAddedPacket()) && t.writeBool(6, r),\n                    0 !== (r = e.getTraceLogCapacity()) && t.writeInt64(7, r),\n                    (r = e.getTraceEventTypesDisabledList()).length > 0 && t.writePackedInt32(8, r),\n                    (r = e.getTraceLogPath()).length > 0 && t.writeString(9, r),\n                    0 !== (r = e.getTraceLogCount()) && t.writeInt32(10, r),\n                    0 !== (r = e.getTraceLogIntervalUsec()) && t.writeInt64(11, r),\n                    0 !== (r = e.getTraceLogMarginUsec()) && t.writeInt64(12, r),\n                    (r = e.getTraceLogDurationEvents()) && t.writeBool(13, r),\n                    0 !== (r = e.getTraceLogIntervalCount()) && t.writeInt32(14, r),\n                    (r = e.getTraceLogDisabled()) && t.writeBool(15, r),\n                    (r = e.getTraceEnabled()) && t.writeBool(16, r),\n                    (r = e.getTraceLogInstantEvents()) && t.writeBool(17, r),\n                    (r = e.getCalculatorFilter()).length > 0 && t.writeString(18, r);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getHistogramIntervalSizeUsec = function() {\n                return t.Message.getFieldWithDefault(this, 1, 0);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setHistogramIntervalSizeUsec = function(e) {\n                return t.Message.setProto3IntField(this, 1, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getNumHistogramIntervals = function() {\n                return t.Message.getFieldWithDefault(this, 2, 0);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setNumHistogramIntervals = function(e) {\n                return t.Message.setProto3IntField(this, 2, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getEnableInputOutputLatency = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 3, !1);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setEnableInputOutputLatency = function(e) {\n                return t.Message.setProto3BooleanField(this, 3, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getEnableProfiler = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 4, !1);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setEnableProfiler = function(e) {\n                return t.Message.setProto3BooleanField(this, 4, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getEnableStreamLatency = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 5, !1);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setEnableStreamLatency = function(e) {\n                return t.Message.setProto3BooleanField(this, 5, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getUsePacketTimestampForAddedPacket = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 6, !1);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setUsePacketTimestampForAddedPacket = function(\n                e\n            ) {\n                return t.Message.setProto3BooleanField(this, 6, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogCapacity = function() {\n                return t.Message.getFieldWithDefault(this, 7, 0);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogCapacity = function(e) {\n                return t.Message.setProto3IntField(this, 7, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceEventTypesDisabledList = function() {\n                return t.Message.getRepeatedField(this, 8);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceEventTypesDisabledList = function(e) {\n                return t.Message.setField(this, 8, e || []);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.addTraceEventTypesDisabled = function(e, r) {\n                return t.Message.addToRepeatedField(this, 8, e, r);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.clearTraceEventTypesDisabledList = function() {\n                return this.setTraceEventTypesDisabledList([]);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogPath = function() {\n                return t.Message.getFieldWithDefault(this, 9, '');\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogPath = function(e) {\n                return t.Message.setProto3StringField(this, 9, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogCount = function() {\n                return t.Message.getFieldWithDefault(this, 10, 0);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogCount = function(e) {\n                return t.Message.setProto3IntField(this, 10, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogIntervalUsec = function() {\n                return t.Message.getFieldWithDefault(this, 11, 0);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogIntervalUsec = function(e) {\n                return t.Message.setProto3IntField(this, 11, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogMarginUsec = function() {\n                return t.Message.getFieldWithDefault(this, 12, 0);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogMarginUsec = function(e) {\n                return t.Message.setProto3IntField(this, 12, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogDurationEvents = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 13, !1);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogDurationEvents = function(e) {\n                return t.Message.setProto3BooleanField(this, 13, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogIntervalCount = function() {\n                return t.Message.getFieldWithDefault(this, 14, 0);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogIntervalCount = function(e) {\n                return t.Message.setProto3IntField(this, 14, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogDisabled = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 15, !1);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogDisabled = function(e) {\n                return t.Message.setProto3BooleanField(this, 15, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceEnabled = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 16, !1);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceEnabled = function(e) {\n                return t.Message.setProto3BooleanField(this, 16, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getTraceLogInstantEvents = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 17, !1);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setTraceLogInstantEvents = function(e) {\n                return t.Message.setProto3BooleanField(this, 17, e);\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.getCalculatorFilter = function() {\n                return t.Message.getFieldWithDefault(this, 18, '');\n            }),\n            (proto.mediapipe.ProfilerConfig.prototype.setCalculatorFilter = function(e) {\n                return t.Message.setProto3StringField(this, 18, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.repeatedFields_ = [\n                1,\n                6,\n                7,\n                9,\n                10,\n                15,\n                16,\n                17,\n                14,\n                1002,\n            ]),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.CalculatorGraphConfig.prototype.toObject = function(e) {\n                    return proto.mediapipe.CalculatorGraphConfig.toObject(e, this);\n                }),\n                (proto.mediapipe.CalculatorGraphConfig.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            nodeList: t.Message.toObjectList(\n                                r.getNodeList(),\n                                proto.mediapipe.CalculatorGraphConfig.Node.toObject,\n                                e\n                            ),\n                            packetFactoryList: t.Message.toObjectList(\n                                r.getPacketFactoryList(),\n                                s.PacketFactoryConfig.toObject,\n                                e\n                            ),\n                            packetGeneratorList: t.Message.toObjectList(\n                                r.getPacketGeneratorList(),\n                                p.PacketGeneratorConfig.toObject,\n                                e\n                            ),\n                            numThreads: t.Message.getFieldWithDefault(r, 8, 0),\n                            statusHandlerList: t.Message.toObjectList(\n                                r.getStatusHandlerList(),\n                                d.StatusHandlerConfig.toObject,\n                                e\n                            ),\n                            inputStreamList:\n                                null == (o = t.Message.getRepeatedField(r, 10)) ? void 0 : o,\n                            outputStreamList:\n                                null == (o = t.Message.getRepeatedField(r, 15)) ? void 0 : o,\n                            inputSidePacketList:\n                                null == (o = t.Message.getRepeatedField(r, 16)) ? void 0 : o,\n                            outputSidePacketList:\n                                null == (o = t.Message.getRepeatedField(r, 17)) ? void 0 : o,\n                            maxQueueSize: t.Message.getFieldWithDefault(r, 11, 0),\n                            reportDeadlock: t.Message.getBooleanFieldWithDefault(r, 21, !1),\n                            inputStreamHandler:\n                                (o = r.getInputStreamHandler()) &&\n                                l.InputStreamHandlerConfig.toObject(e, o),\n                            outputStreamHandler:\n                                (o = r.getOutputStreamHandler()) &&\n                                l.OutputStreamHandlerConfig.toObject(e, o),\n                            executorList: t.Message.toObjectList(\n                                r.getExecutorList(),\n                                proto.mediapipe.ExecutorConfig.toObject,\n                                e\n                            ),\n                            profilerConfig:\n                                (o = r.getProfilerConfig()) &&\n                                proto.mediapipe.ProfilerConfig.toObject(e, o),\n                            pb_package: t.Message.getFieldWithDefault(r, 19, ''),\n                            type: t.Message.getFieldWithDefault(r, 20, ''),\n                            options: (o = r.getOptions()) && n.MediaPipeOptions.toObject(e, o),\n                            graphOptionsList: t.Message.toObjectList(\n                                r.getGraphOptionsList(),\n                                a.Any.toObject,\n                                e\n                            ),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.CalculatorGraphConfig.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.CalculatorGraphConfig();\n                return proto.mediapipe.CalculatorGraphConfig.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new proto.mediapipe.CalculatorGraphConfig.Node();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.CalculatorGraphConfig.Node\n                                    .deserializeBinaryFromReader\n                            ),\n                                e.addNode(r);\n                            break;\n                        case 6:\n                            r = new s.PacketFactoryConfig();\n                            t.readMessage(r, s.PacketFactoryConfig.deserializeBinaryFromReader),\n                                e.addPacketFactory(r);\n                            break;\n                        case 7:\n                            r = new p.PacketGeneratorConfig();\n                            t.readMessage(r, p.PacketGeneratorConfig.deserializeBinaryFromReader),\n                                e.addPacketGenerator(r);\n                            break;\n                        case 8:\n                            r = t.readInt32();\n                            e.setNumThreads(r);\n                            break;\n                        case 9:\n                            r = new d.StatusHandlerConfig();\n                            t.readMessage(r, d.StatusHandlerConfig.deserializeBinaryFromReader),\n                                e.addStatusHandler(r);\n                            break;\n                        case 10:\n                            r = t.readString();\n                            e.addInputStream(r);\n                            break;\n                        case 15:\n                            r = t.readString();\n                            e.addOutputStream(r);\n                            break;\n                        case 16:\n                            r = t.readString();\n                            e.addInputSidePacket(r);\n                            break;\n                        case 17:\n                            r = t.readString();\n                            e.addOutputSidePacket(r);\n                            break;\n                        case 11:\n                            r = t.readInt32();\n                            e.setMaxQueueSize(r);\n                            break;\n                        case 21:\n                            r = t.readBool();\n                            e.setReportDeadlock(r);\n                            break;\n                        case 12:\n                            r = new l.InputStreamHandlerConfig();\n                            t.readMessage(\n                                r,\n                                l.InputStreamHandlerConfig.deserializeBinaryFromReader\n                            ),\n                                e.setInputStreamHandler(r);\n                            break;\n                        case 13:\n                            r = new l.OutputStreamHandlerConfig();\n                            t.readMessage(\n                                r,\n                                l.OutputStreamHandlerConfig.deserializeBinaryFromReader\n                            ),\n                                e.setOutputStreamHandler(r);\n                            break;\n                        case 14:\n                            r = new proto.mediapipe.ExecutorConfig();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.ExecutorConfig.deserializeBinaryFromReader\n                            ),\n                                e.addExecutor(r);\n                            break;\n                        case 18:\n                            r = new proto.mediapipe.ProfilerConfig();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.ProfilerConfig.deserializeBinaryFromReader\n                            ),\n                                e.setProfilerConfig(r);\n                            break;\n                        case 19:\n                            r = t.readString();\n                            e.setPackage(r);\n                            break;\n                        case 20:\n                            r = t.readString();\n                            e.setType(r);\n                            break;\n                        case 1001:\n                            r = new n.MediaPipeOptions();\n                            t.readMessage(r, n.MediaPipeOptions.deserializeBinaryFromReader),\n                                e.setOptions(r);\n                            break;\n                        case 1002:\n                            r = new a.Any();\n                            t.readMessage(r, a.Any.deserializeBinaryFromReader),\n                                e.addGraphOptions(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.CalculatorGraphConfig.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.serializeBinaryToWriter = function(e, t) {\n                var r = void 0;\n                (r = e.getNodeList()).length > 0 &&\n                    t.writeRepeatedMessage(\n                        1,\n                        r,\n                        proto.mediapipe.CalculatorGraphConfig.Node.serializeBinaryToWriter\n                    ),\n                    (r = e.getPacketFactoryList()).length > 0 &&\n                        t.writeRepeatedMessage(6, r, s.PacketFactoryConfig.serializeBinaryToWriter),\n                    (r = e.getPacketGeneratorList()).length > 0 &&\n                        t.writeRepeatedMessage(\n                            7,\n                            r,\n                            p.PacketGeneratorConfig.serializeBinaryToWriter\n                        ),\n                    0 !== (r = e.getNumThreads()) && t.writeInt32(8, r),\n                    (r = e.getStatusHandlerList()).length > 0 &&\n                        t.writeRepeatedMessage(9, r, d.StatusHandlerConfig.serializeBinaryToWriter),\n                    (r = e.getInputStreamList()).length > 0 && t.writeRepeatedString(10, r),\n                    (r = e.getOutputStreamList()).length > 0 && t.writeRepeatedString(15, r),\n                    (r = e.getInputSidePacketList()).length > 0 && t.writeRepeatedString(16, r),\n                    (r = e.getOutputSidePacketList()).length > 0 && t.writeRepeatedString(17, r),\n                    0 !== (r = e.getMaxQueueSize()) && t.writeInt32(11, r),\n                    (r = e.getReportDeadlock()) && t.writeBool(21, r),\n                    null != (r = e.getInputStreamHandler()) &&\n                        t.writeMessage(12, r, l.InputStreamHandlerConfig.serializeBinaryToWriter),\n                    null != (r = e.getOutputStreamHandler()) &&\n                        t.writeMessage(13, r, l.OutputStreamHandlerConfig.serializeBinaryToWriter),\n                    (r = e.getExecutorList()).length > 0 &&\n                        t.writeRepeatedMessage(\n                            14,\n                            r,\n                            proto.mediapipe.ExecutorConfig.serializeBinaryToWriter\n                        ),\n                    null != (r = e.getProfilerConfig()) &&\n                        t.writeMessage(\n                            18,\n                            r,\n                            proto.mediapipe.ProfilerConfig.serializeBinaryToWriter\n                        ),\n                    (r = e.getPackage()).length > 0 && t.writeString(19, r),\n                    (r = e.getType()).length > 0 && t.writeString(20, r),\n                    null != (r = e.getOptions()) &&\n                        t.writeMessage(1001, r, n.MediaPipeOptions.serializeBinaryToWriter),\n                    (r = e.getGraphOptionsList()).length > 0 &&\n                        t.writeRepeatedMessage(1002, r, a.Any.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.repeatedFields_ = [\n                3,\n                4,\n                5,\n                6,\n                8,\n                13,\n                17,\n                1005,\n            ]),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.CalculatorGraphConfig.Node.prototype.toObject = function(e) {\n                    return proto.mediapipe.CalculatorGraphConfig.Node.toObject(e, this);\n                }),\n                (proto.mediapipe.CalculatorGraphConfig.Node.toObject = function(e, r) {\n                    var o,\n                        n = {\n                            name: t.Message.getFieldWithDefault(r, 1, ''),\n                            calculator: t.Message.getFieldWithDefault(r, 2, ''),\n                            inputStreamList:\n                                null == (o = t.Message.getRepeatedField(r, 3)) ? void 0 : o,\n                            outputStreamList:\n                                null == (o = t.Message.getRepeatedField(r, 4)) ? void 0 : o,\n                            inputSidePacketList:\n                                null == (o = t.Message.getRepeatedField(r, 5)) ? void 0 : o,\n                            outputSidePacketList:\n                                null == (o = t.Message.getRepeatedField(r, 6)) ? void 0 : o,\n                            options: (o = r.getOptions()) && i.CalculatorOptions.toObject(e, o),\n                            nodeOptionsList: t.Message.toObjectList(\n                                r.getNodeOptionsList(),\n                                a.Any.toObject,\n                                e\n                            ),\n                            sourceLayer: t.Message.getFieldWithDefault(r, 9, 0),\n                            bufferSizeHint: t.Message.getFieldWithDefault(r, 10, 0),\n                            inputStreamHandler:\n                                (o = r.getInputStreamHandler()) &&\n                                l.InputStreamHandlerConfig.toObject(e, o),\n                            outputStreamHandler:\n                                (o = r.getOutputStreamHandler()) &&\n                                l.OutputStreamHandlerConfig.toObject(e, o),\n                            inputStreamInfoList: t.Message.toObjectList(\n                                r.getInputStreamInfoList(),\n                                proto.mediapipe.InputStreamInfo.toObject,\n                                e\n                            ),\n                            executor: t.Message.getFieldWithDefault(r, 14, ''),\n                            profilerConfig:\n                                (o = r.getProfilerConfig()) &&\n                                proto.mediapipe.ProfilerConfig.toObject(e, o),\n                            maxInFlight: t.Message.getFieldWithDefault(r, 16, 0),\n                            optionValueList:\n                                null == (o = t.Message.getRepeatedField(r, 17)) ? void 0 : o,\n                            externalInputList:\n                                null == (o = t.Message.getRepeatedField(r, 1005)) ? void 0 : o,\n                        };\n                    return e && (n.$jspbMessageInstance = r), n;\n                })),\n            (proto.mediapipe.CalculatorGraphConfig.Node.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.CalculatorGraphConfig.Node();\n                return proto.mediapipe.CalculatorGraphConfig.Node.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readString();\n                            e.setName(r);\n                            break;\n                        case 2:\n                            r = t.readString();\n                            e.setCalculator(r);\n                            break;\n                        case 3:\n                            r = t.readString();\n                            e.addInputStream(r);\n                            break;\n                        case 4:\n                            r = t.readString();\n                            e.addOutputStream(r);\n                            break;\n                        case 5:\n                            r = t.readString();\n                            e.addInputSidePacket(r);\n                            break;\n                        case 6:\n                            r = t.readString();\n                            e.addOutputSidePacket(r);\n                            break;\n                        case 7:\n                            r = new i.CalculatorOptions();\n                            t.readMessage(r, i.CalculatorOptions.deserializeBinaryFromReader),\n                                e.setOptions(r);\n                            break;\n                        case 8:\n                            r = new a.Any();\n                            t.readMessage(r, a.Any.deserializeBinaryFromReader),\n                                e.addNodeOptions(r);\n                            break;\n                        case 9:\n                            r = t.readInt32();\n                            e.setSourceLayer(r);\n                            break;\n                        case 10:\n                            r = t.readInt32();\n                            e.setBufferSizeHint(r);\n                            break;\n                        case 11:\n                            r = new l.InputStreamHandlerConfig();\n                            t.readMessage(\n                                r,\n                                l.InputStreamHandlerConfig.deserializeBinaryFromReader\n                            ),\n                                e.setInputStreamHandler(r);\n                            break;\n                        case 12:\n                            r = new l.OutputStreamHandlerConfig();\n                            t.readMessage(\n                                r,\n                                l.OutputStreamHandlerConfig.deserializeBinaryFromReader\n                            ),\n                                e.setOutputStreamHandler(r);\n                            break;\n                        case 13:\n                            r = new proto.mediapipe.InputStreamInfo();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.InputStreamInfo.deserializeBinaryFromReader\n                            ),\n                                e.addInputStreamInfo(r);\n                            break;\n                        case 14:\n                            r = t.readString();\n                            e.setExecutor(r);\n                            break;\n                        case 15:\n                            r = new proto.mediapipe.ProfilerConfig();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.ProfilerConfig.deserializeBinaryFromReader\n                            ),\n                                e.setProfilerConfig(r);\n                            break;\n                        case 16:\n                            r = t.readInt32();\n                            e.setMaxInFlight(r);\n                            break;\n                        case 17:\n                            r = t.readString();\n                            e.addOptionValue(r);\n                            break;\n                        case 1005:\n                            r = t.readString();\n                            e.addExternalInput(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.CalculatorGraphConfig.Node.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.serializeBinaryToWriter = function(e, t) {\n                var r = void 0;\n                (r = e.getName()).length > 0 && t.writeString(1, r),\n                    (r = e.getCalculator()).length > 0 && t.writeString(2, r),\n                    (r = e.getInputStreamList()).length > 0 && t.writeRepeatedString(3, r),\n                    (r = e.getOutputStreamList()).length > 0 && t.writeRepeatedString(4, r),\n                    (r = e.getInputSidePacketList()).length > 0 && t.writeRepeatedString(5, r),\n                    (r = e.getOutputSidePacketList()).length > 0 && t.writeRepeatedString(6, r),\n                    null != (r = e.getOptions()) &&\n                        t.writeMessage(7, r, i.CalculatorOptions.serializeBinaryToWriter),\n                    (r = e.getNodeOptionsList()).length > 0 &&\n                        t.writeRepeatedMessage(8, r, a.Any.serializeBinaryToWriter),\n                    0 !== (r = e.getSourceLayer()) && t.writeInt32(9, r),\n                    0 !== (r = e.getBufferSizeHint()) && t.writeInt32(10, r),\n                    null != (r = e.getInputStreamHandler()) &&\n                        t.writeMessage(11, r, l.InputStreamHandlerConfig.serializeBinaryToWriter),\n                    null != (r = e.getOutputStreamHandler()) &&\n                        t.writeMessage(12, r, l.OutputStreamHandlerConfig.serializeBinaryToWriter),\n                    (r = e.getInputStreamInfoList()).length > 0 &&\n                        t.writeRepeatedMessage(\n                            13,\n                            r,\n                            proto.mediapipe.InputStreamInfo.serializeBinaryToWriter\n                        ),\n                    (r = e.getExecutor()).length > 0 && t.writeString(14, r),\n                    null != (r = e.getProfilerConfig()) &&\n                        t.writeMessage(\n                            15,\n                            r,\n                            proto.mediapipe.ProfilerConfig.serializeBinaryToWriter\n                        ),\n                    0 !== (r = e.getMaxInFlight()) && t.writeInt32(16, r),\n                    (r = e.getOptionValueList()).length > 0 && t.writeRepeatedString(17, r),\n                    (r = e.getExternalInputList()).length > 0 && t.writeRepeatedString(1005, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getName = function() {\n                return t.Message.getFieldWithDefault(this, 1, '');\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setName = function(e) {\n                return t.Message.setProto3StringField(this, 1, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getCalculator = function() {\n                return t.Message.getFieldWithDefault(this, 2, '');\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setCalculator = function(e) {\n                return t.Message.setProto3StringField(this, 2, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getInputStreamList = function() {\n                return t.Message.getRepeatedField(this, 3);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setInputStreamList = function(e) {\n                return t.Message.setField(this, 3, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.addInputStream = function(e, r) {\n                return t.Message.addToRepeatedField(this, 3, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearInputStreamList = function() {\n                return this.setInputStreamList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getOutputStreamList = function() {\n                return t.Message.getRepeatedField(this, 4);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setOutputStreamList = function(\n                e\n            ) {\n                return t.Message.setField(this, 4, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.addOutputStream = function(e, r) {\n                return t.Message.addToRepeatedField(this, 4, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearOutputStreamList = function() {\n                return this.setOutputStreamList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getInputSidePacketList = function() {\n                return t.Message.getRepeatedField(this, 5);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setInputSidePacketList = function(\n                e\n            ) {\n                return t.Message.setField(this, 5, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.addInputSidePacket = function(\n                e,\n                r\n            ) {\n                return t.Message.addToRepeatedField(this, 5, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearInputSidePacketList = function() {\n                return this.setInputSidePacketList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getOutputSidePacketList = function() {\n                return t.Message.getRepeatedField(this, 6);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setOutputSidePacketList = function(\n                e\n            ) {\n                return t.Message.setField(this, 6, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.addOutputSidePacket = function(\n                e,\n                r\n            ) {\n                return t.Message.addToRepeatedField(this, 6, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearOutputSidePacketList = function() {\n                return this.setOutputSidePacketList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getOptions = function() {\n                return t.Message.getWrapperField(this, i.CalculatorOptions, 7);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setOptions = function(e) {\n                return t.Message.setWrapperField(this, 7, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearOptions = function() {\n                return this.setOptions(void 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.hasOptions = function() {\n                return null != t.Message.getField(this, 7);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getNodeOptionsList = function() {\n                return t.Message.getRepeatedWrapperField(this, a.Any, 8);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setNodeOptionsList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 8, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.addNodeOptions = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    8,\n                    e,\n                    proto.google.protobuf.Any,\n                    r\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearNodeOptionsList = function() {\n                return this.setNodeOptionsList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getSourceLayer = function() {\n                return t.Message.getFieldWithDefault(this, 9, 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setSourceLayer = function(e) {\n                return t.Message.setProto3IntField(this, 9, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getBufferSizeHint = function() {\n                return t.Message.getFieldWithDefault(this, 10, 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setBufferSizeHint = function(e) {\n                return t.Message.setProto3IntField(this, 10, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getInputStreamHandler = function() {\n                return t.Message.getWrapperField(this, l.InputStreamHandlerConfig, 11);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setInputStreamHandler = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 11, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearInputStreamHandler = function() {\n                return this.setInputStreamHandler(void 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.hasInputStreamHandler = function() {\n                return null != t.Message.getField(this, 11);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getOutputStreamHandler = function() {\n                return t.Message.getWrapperField(this, l.OutputStreamHandlerConfig, 12);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setOutputStreamHandler = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 12, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearOutputStreamHandler = function() {\n                return this.setOutputStreamHandler(void 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.hasOutputStreamHandler = function() {\n                return null != t.Message.getField(this, 12);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getInputStreamInfoList = function() {\n                return t.Message.getRepeatedWrapperField(this, proto.mediapipe.InputStreamInfo, 13);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setInputStreamInfoList = function(\n                e\n            ) {\n                return t.Message.setRepeatedWrapperField(this, 13, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.addInputStreamInfo = function(\n                e,\n                r\n            ) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    13,\n                    e,\n                    proto.mediapipe.InputStreamInfo,\n                    r\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearInputStreamInfoList = function() {\n                return this.setInputStreamInfoList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getExecutor = function() {\n                return t.Message.getFieldWithDefault(this, 14, '');\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setExecutor = function(e) {\n                return t.Message.setProto3StringField(this, 14, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getProfilerConfig = function() {\n                return t.Message.getWrapperField(this, proto.mediapipe.ProfilerConfig, 15);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setProfilerConfig = function(e) {\n                return t.Message.setWrapperField(this, 15, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearProfilerConfig = function() {\n                return this.setProfilerConfig(void 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.hasProfilerConfig = function() {\n                return null != t.Message.getField(this, 15);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getMaxInFlight = function() {\n                return t.Message.getFieldWithDefault(this, 16, 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setMaxInFlight = function(e) {\n                return t.Message.setProto3IntField(this, 16, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getOptionValueList = function() {\n                return t.Message.getRepeatedField(this, 17);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setOptionValueList = function(e) {\n                return t.Message.setField(this, 17, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.addOptionValue = function(e, r) {\n                return t.Message.addToRepeatedField(this, 17, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearOptionValueList = function() {\n                return this.setOptionValueList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.getExternalInputList = function() {\n                return t.Message.getRepeatedField(this, 1005);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.setExternalInputList = function(\n                e\n            ) {\n                return t.Message.setField(this, 1005, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.addExternalInput = function(\n                e,\n                r\n            ) {\n                return t.Message.addToRepeatedField(this, 1005, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.Node.prototype.clearExternalInputList = function() {\n                return this.setExternalInputList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getNodeList = function() {\n                return t.Message.getRepeatedWrapperField(\n                    this,\n                    proto.mediapipe.CalculatorGraphConfig.Node,\n                    1\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setNodeList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addNode = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    1,\n                    e,\n                    proto.mediapipe.CalculatorGraphConfig.Node,\n                    r\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearNodeList = function() {\n                return this.setNodeList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getPacketFactoryList = function() {\n                return t.Message.getRepeatedWrapperField(this, s.PacketFactoryConfig, 6);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setPacketFactoryList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 6, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addPacketFactory = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    6,\n                    e,\n                    proto.mediapipe.PacketFactoryConfig,\n                    r\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearPacketFactoryList = function() {\n                return this.setPacketFactoryList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getPacketGeneratorList = function() {\n                return t.Message.getRepeatedWrapperField(this, p.PacketGeneratorConfig, 7);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setPacketGeneratorList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 7, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addPacketGenerator = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    7,\n                    e,\n                    proto.mediapipe.PacketGeneratorConfig,\n                    r\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearPacketGeneratorList = function() {\n                return this.setPacketGeneratorList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getNumThreads = function() {\n                return t.Message.getFieldWithDefault(this, 8, 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setNumThreads = function(e) {\n                return t.Message.setProto3IntField(this, 8, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getStatusHandlerList = function() {\n                return t.Message.getRepeatedWrapperField(this, d.StatusHandlerConfig, 9);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setStatusHandlerList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 9, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addStatusHandler = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    9,\n                    e,\n                    proto.mediapipe.StatusHandlerConfig,\n                    r\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearStatusHandlerList = function() {\n                return this.setStatusHandlerList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getInputStreamList = function() {\n                return t.Message.getRepeatedField(this, 10);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setInputStreamList = function(e) {\n                return t.Message.setField(this, 10, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addInputStream = function(e, r) {\n                return t.Message.addToRepeatedField(this, 10, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearInputStreamList = function() {\n                return this.setInputStreamList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getOutputStreamList = function() {\n                return t.Message.getRepeatedField(this, 15);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setOutputStreamList = function(e) {\n                return t.Message.setField(this, 15, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addOutputStream = function(e, r) {\n                return t.Message.addToRepeatedField(this, 15, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearOutputStreamList = function() {\n                return this.setOutputStreamList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getInputSidePacketList = function() {\n                return t.Message.getRepeatedField(this, 16);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setInputSidePacketList = function(e) {\n                return t.Message.setField(this, 16, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addInputSidePacket = function(e, r) {\n                return t.Message.addToRepeatedField(this, 16, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearInputSidePacketList = function() {\n                return this.setInputSidePacketList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getOutputSidePacketList = function() {\n                return t.Message.getRepeatedField(this, 17);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setOutputSidePacketList = function(e) {\n                return t.Message.setField(this, 17, e || []);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addOutputSidePacket = function(e, r) {\n                return t.Message.addToRepeatedField(this, 17, e, r);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearOutputSidePacketList = function() {\n                return this.setOutputSidePacketList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getMaxQueueSize = function() {\n                return t.Message.getFieldWithDefault(this, 11, 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setMaxQueueSize = function(e) {\n                return t.Message.setProto3IntField(this, 11, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getReportDeadlock = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 21, !1);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setReportDeadlock = function(e) {\n                return t.Message.setProto3BooleanField(this, 21, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getInputStreamHandler = function() {\n                return t.Message.getWrapperField(this, l.InputStreamHandlerConfig, 12);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setInputStreamHandler = function(e) {\n                return t.Message.setWrapperField(this, 12, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearInputStreamHandler = function() {\n                return this.setInputStreamHandler(void 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.hasInputStreamHandler = function() {\n                return null != t.Message.getField(this, 12);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getOutputStreamHandler = function() {\n                return t.Message.getWrapperField(this, l.OutputStreamHandlerConfig, 13);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setOutputStreamHandler = function(e) {\n                return t.Message.setWrapperField(this, 13, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearOutputStreamHandler = function() {\n                return this.setOutputStreamHandler(void 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.hasOutputStreamHandler = function() {\n                return null != t.Message.getField(this, 13);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getExecutorList = function() {\n                return t.Message.getRepeatedWrapperField(this, proto.mediapipe.ExecutorConfig, 14);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setExecutorList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 14, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addExecutor = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    14,\n                    e,\n                    proto.mediapipe.ExecutorConfig,\n                    r\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearExecutorList = function() {\n                return this.setExecutorList([]);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getProfilerConfig = function() {\n                return t.Message.getWrapperField(this, proto.mediapipe.ProfilerConfig, 18);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setProfilerConfig = function(e) {\n                return t.Message.setWrapperField(this, 18, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearProfilerConfig = function() {\n                return this.setProfilerConfig(void 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.hasProfilerConfig = function() {\n                return null != t.Message.getField(this, 18);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getPackage = function() {\n                return t.Message.getFieldWithDefault(this, 19, '');\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setPackage = function(e) {\n                return t.Message.setProto3StringField(this, 19, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getType = function() {\n                return t.Message.getFieldWithDefault(this, 20, '');\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setType = function(e) {\n                return t.Message.setProto3StringField(this, 20, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getOptions = function() {\n                return t.Message.getWrapperField(this, n.MediaPipeOptions, 1001);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setOptions = function(e) {\n                return t.Message.setWrapperField(this, 1001, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearOptions = function() {\n                return this.setOptions(void 0);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.hasOptions = function() {\n                return null != t.Message.getField(this, 1001);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.getGraphOptionsList = function() {\n                return t.Message.getRepeatedWrapperField(this, a.Any, 1002);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.setGraphOptionsList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 1002, e);\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.addGraphOptions = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    1002,\n                    e,\n                    proto.google.protobuf.Any,\n                    r\n                );\n            }),\n            (proto.mediapipe.CalculatorGraphConfig.prototype.clearGraphOptionsList = function() {\n                return this.setGraphOptionsList([]);\n            }),\n            r.object.extend(e, proto.mediapipe);\n    })(calculator_pb);\nvar detection_pb = {},\n    location_data_pb = {},\n    rasterization_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.Rasterization', null, o),\n        r.exportSymbol('proto.mediapipe.Rasterization.Interval', null, o),\n        (proto.mediapipe.Rasterization = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.Rasterization.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.Rasterization, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.Rasterization.displayName = 'proto.mediapipe.Rasterization'),\n        (proto.mediapipe.Rasterization.Interval = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.Rasterization.Interval, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.Rasterization.Interval.displayName =\n                'proto.mediapipe.Rasterization.Interval'),\n        (proto.mediapipe.Rasterization.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.Rasterization.prototype.toObject = function(e) {\n                return proto.mediapipe.Rasterization.toObject(e, this);\n            }),\n            (proto.mediapipe.Rasterization.toObject = function(e, r) {\n                var o = {\n                    intervalList: t.Message.toObjectList(\n                        r.getIntervalList(),\n                        proto.mediapipe.Rasterization.Interval.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.Rasterization.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.Rasterization();\n            return proto.mediapipe.Rasterization.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.Rasterization.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.Rasterization.Interval();\n                    t.readMessage(\n                        r,\n                        proto.mediapipe.Rasterization.Interval.deserializeBinaryFromReader\n                    ),\n                        e.addInterval(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.Rasterization.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.Rasterization.serializeBinaryToWriter(this, e), e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.Rasterization.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getIntervalList()).length > 0 &&\n                t.writeRepeatedMessage(\n                    1,\n                    r,\n                    proto.mediapipe.Rasterization.Interval.serializeBinaryToWriter\n                );\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.Rasterization.Interval.prototype.toObject = function(e) {\n                return proto.mediapipe.Rasterization.Interval.toObject(e, this);\n            }),\n            (proto.mediapipe.Rasterization.Interval.toObject = function(e, r) {\n                var o,\n                    i = {\n                        y: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        leftX: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        rightX: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.Rasterization.Interval.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.Rasterization.Interval();\n            return proto.mediapipe.Rasterization.Interval.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.Rasterization.Interval.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readInt32();\n                        e.setY(r);\n                        break;\n                    case 2:\n                        r = t.readInt32();\n                        e.setLeftX(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setRightX(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.Rasterization.Interval.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.Rasterization.Interval.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.getY = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.setY = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.clearY = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.hasY = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.getLeftX = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.setLeftX = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.clearLeftX = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.hasLeftX = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.getRightX = function() {\n            return t.Message.getFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.setRightX = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.clearRightX = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.Rasterization.Interval.prototype.hasRightX = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.Rasterization.prototype.getIntervalList = function() {\n            return t.Message.getRepeatedWrapperField(\n                this,\n                proto.mediapipe.Rasterization.Interval,\n                1\n            );\n        }),\n        (proto.mediapipe.Rasterization.prototype.setIntervalList = function(e) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.Rasterization.prototype.addInterval = function(e, r) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.Rasterization.Interval,\n                r\n            );\n        }),\n        (proto.mediapipe.Rasterization.prototype.clearIntervalList = function() {\n            return this.setIntervalList([]);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(rasterization_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = rasterization_pb;\n        r.object.extend(proto, i),\n            r.exportSymbol('proto.mediapipe.LocationData', null, o),\n            r.exportSymbol('proto.mediapipe.LocationData.BinaryMask', null, o),\n            r.exportSymbol('proto.mediapipe.LocationData.BoundingBox', null, o),\n            r.exportSymbol('proto.mediapipe.LocationData.Format', null, o),\n            r.exportSymbol('proto.mediapipe.LocationData.RelativeBoundingBox', null, o),\n            r.exportSymbol('proto.mediapipe.LocationData.RelativeKeypoint', null, o),\n            (proto.mediapipe.LocationData = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    -1,\n                    proto.mediapipe.LocationData.repeatedFields_,\n                    null\n                );\n            }),\n            r.inherits(proto.mediapipe.LocationData, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.LocationData.displayName = 'proto.mediapipe.LocationData'),\n            (proto.mediapipe.LocationData.BoundingBox = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.LocationData.BoundingBox, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.LocationData.BoundingBox.displayName =\n                    'proto.mediapipe.LocationData.BoundingBox'),\n            (proto.mediapipe.LocationData.RelativeBoundingBox = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.LocationData.RelativeBoundingBox, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.LocationData.RelativeBoundingBox.displayName =\n                    'proto.mediapipe.LocationData.RelativeBoundingBox'),\n            (proto.mediapipe.LocationData.BinaryMask = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.LocationData.BinaryMask, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.LocationData.BinaryMask.displayName =\n                    'proto.mediapipe.LocationData.BinaryMask'),\n            (proto.mediapipe.LocationData.RelativeKeypoint = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.LocationData.RelativeKeypoint, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.LocationData.RelativeKeypoint.displayName =\n                    'proto.mediapipe.LocationData.RelativeKeypoint'),\n            (proto.mediapipe.LocationData.repeatedFields_ = [5]),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.LocationData.prototype.toObject = function(e) {\n                    return proto.mediapipe.LocationData.toObject(e, this);\n                }),\n                (proto.mediapipe.LocationData.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            format: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                            boundingBox:\n                                (o = r.getBoundingBox()) &&\n                                proto.mediapipe.LocationData.BoundingBox.toObject(e, o),\n                            relativeBoundingBox:\n                                (o = r.getRelativeBoundingBox()) &&\n                                proto.mediapipe.LocationData.RelativeBoundingBox.toObject(e, o),\n                            mask:\n                                (o = r.getMask()) &&\n                                proto.mediapipe.LocationData.BinaryMask.toObject(e, o),\n                            relativeKeypointsList: t.Message.toObjectList(\n                                r.getRelativeKeypointsList(),\n                                proto.mediapipe.LocationData.RelativeKeypoint.toObject,\n                                e\n                            ),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.LocationData.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.LocationData();\n                return proto.mediapipe.LocationData.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.LocationData.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readEnum();\n                            e.setFormat(r);\n                            break;\n                        case 2:\n                            r = new proto.mediapipe.LocationData.BoundingBox();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.LocationData.BoundingBox.deserializeBinaryFromReader\n                            ),\n                                e.setBoundingBox(r);\n                            break;\n                        case 3:\n                            r = new proto.mediapipe.LocationData.RelativeBoundingBox();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.LocationData.RelativeBoundingBox\n                                    .deserializeBinaryFromReader\n                            ),\n                                e.setRelativeBoundingBox(r);\n                            break;\n                        case 4:\n                            r = new proto.mediapipe.LocationData.BinaryMask();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.LocationData.BinaryMask.deserializeBinaryFromReader\n                            ),\n                                e.setMask(r);\n                            break;\n                        case 5:\n                            r = new proto.mediapipe.LocationData.RelativeKeypoint();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.LocationData.RelativeKeypoint\n                                    .deserializeBinaryFromReader\n                            ),\n                                e.addRelativeKeypoints(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.LocationData.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.LocationData.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.LocationData.serializeBinaryToWriter = function(e, r) {\n                var o = void 0;\n                null != (o = t.Message.getField(e, 1)) && r.writeEnum(1, o),\n                    null != (o = e.getBoundingBox()) &&\n                        r.writeMessage(\n                            2,\n                            o,\n                            proto.mediapipe.LocationData.BoundingBox.serializeBinaryToWriter\n                        ),\n                    null != (o = e.getRelativeBoundingBox()) &&\n                        r.writeMessage(\n                            3,\n                            o,\n                            proto.mediapipe.LocationData.RelativeBoundingBox.serializeBinaryToWriter\n                        ),\n                    null != (o = e.getMask()) &&\n                        r.writeMessage(\n                            4,\n                            o,\n                            proto.mediapipe.LocationData.BinaryMask.serializeBinaryToWriter\n                        ),\n                    (o = e.getRelativeKeypointsList()).length > 0 &&\n                        r.writeRepeatedMessage(\n                            5,\n                            o,\n                            proto.mediapipe.LocationData.RelativeKeypoint.serializeBinaryToWriter\n                        );\n            }),\n            (proto.mediapipe.LocationData.Format = {\n                GLOBAL: 0,\n                BOUNDING_BOX: 1,\n                RELATIVE_BOUNDING_BOX: 2,\n                MASK: 3,\n            }),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.LocationData.BoundingBox.prototype.toObject = function(e) {\n                    return proto.mediapipe.LocationData.BoundingBox.toObject(e, this);\n                }),\n                (proto.mediapipe.LocationData.BoundingBox.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            xmin: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                            ymin: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                            width: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                            height: null == (o = t.Message.getField(r, 4)) ? void 0 : o,\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.LocationData.BoundingBox.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.LocationData.BoundingBox();\n                return proto.mediapipe.LocationData.BoundingBox.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readInt32();\n                            e.setXmin(r);\n                            break;\n                        case 2:\n                            r = t.readInt32();\n                            e.setYmin(r);\n                            break;\n                        case 3:\n                            r = t.readInt32();\n                            e.setWidth(r);\n                            break;\n                        case 4:\n                            r = t.readInt32();\n                            e.setHeight(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.LocationData.BoundingBox.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.serializeBinaryToWriter = function(e, r) {\n                var o = void 0;\n                null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                    null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                    null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o),\n                    null != (o = t.Message.getField(e, 4)) && r.writeInt32(4, o);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.getXmin = function() {\n                return t.Message.getFieldWithDefault(this, 1, 0);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.setXmin = function(e) {\n                return t.Message.setField(this, 1, e);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.clearXmin = function() {\n                return t.Message.setField(this, 1, void 0);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.hasXmin = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.getYmin = function() {\n                return t.Message.getFieldWithDefault(this, 2, 0);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.setYmin = function(e) {\n                return t.Message.setField(this, 2, e);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.clearYmin = function() {\n                return t.Message.setField(this, 2, void 0);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.hasYmin = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.getWidth = function() {\n                return t.Message.getFieldWithDefault(this, 3, 0);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.setWidth = function(e) {\n                return t.Message.setField(this, 3, e);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.clearWidth = function() {\n                return t.Message.setField(this, 3, void 0);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.hasWidth = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.getHeight = function() {\n                return t.Message.getFieldWithDefault(this, 4, 0);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.setHeight = function(e) {\n                return t.Message.setField(this, 4, e);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.clearHeight = function() {\n                return t.Message.setField(this, 4, void 0);\n            }),\n            (proto.mediapipe.LocationData.BoundingBox.prototype.hasHeight = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.LocationData.RelativeBoundingBox.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.LocationData.RelativeBoundingBox.toObject(e, this);\n                }),\n                (proto.mediapipe.LocationData.RelativeBoundingBox.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            xmin:\n                                null == (o = t.Message.getOptionalFloatingPointField(r, 1))\n                                    ? void 0\n                                    : o,\n                            ymin:\n                                null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                    ? void 0\n                                    : o,\n                            width:\n                                null == (o = t.Message.getOptionalFloatingPointField(r, 3))\n                                    ? void 0\n                                    : o,\n                            height:\n                                null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                    ? void 0\n                                    : o,\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.LocationData.RelativeBoundingBox();\n                return proto.mediapipe.LocationData.RelativeBoundingBox.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readFloat();\n                            e.setXmin(r);\n                            break;\n                        case 2:\n                            r = t.readFloat();\n                            e.setYmin(r);\n                            break;\n                        case 3:\n                            r = t.readFloat();\n                            e.setWidth(r);\n                            break;\n                        case 4:\n                            r = t.readFloat();\n                            e.setHeight(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.LocationData.RelativeBoundingBox.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.serializeBinaryToWriter = function(\n                e,\n                r\n            ) {\n                var o = void 0;\n                null != (o = t.Message.getField(e, 1)) && r.writeFloat(1, o),\n                    null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                    null != (o = t.Message.getField(e, 3)) && r.writeFloat(3, o),\n                    null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.getXmin = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.setXmin = function(e) {\n                return t.Message.setField(this, 1, e);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.clearXmin = function() {\n                return t.Message.setField(this, 1, void 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.hasXmin = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.getYmin = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.setYmin = function(e) {\n                return t.Message.setField(this, 2, e);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.clearYmin = function() {\n                return t.Message.setField(this, 2, void 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.hasYmin = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.getWidth = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.setWidth = function(e) {\n                return t.Message.setField(this, 3, e);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.clearWidth = function() {\n                return t.Message.setField(this, 3, void 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.hasWidth = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.getHeight = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.setHeight = function(e) {\n                return t.Message.setField(this, 4, e);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.clearHeight = function() {\n                return t.Message.setField(this, 4, void 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeBoundingBox.prototype.hasHeight = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.LocationData.BinaryMask.prototype.toObject = function(e) {\n                    return proto.mediapipe.LocationData.BinaryMask.toObject(e, this);\n                }),\n                (proto.mediapipe.LocationData.BinaryMask.toObject = function(e, r) {\n                    var o,\n                        a = {\n                            width: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                            height: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                            rasterization:\n                                (o = r.getRasterization()) && i.Rasterization.toObject(e, o),\n                        };\n                    return e && (a.$jspbMessageInstance = r), a;\n                })),\n            (proto.mediapipe.LocationData.BinaryMask.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.LocationData.BinaryMask();\n                return proto.mediapipe.LocationData.BinaryMask.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readInt32();\n                            e.setWidth(r);\n                            break;\n                        case 2:\n                            r = t.readInt32();\n                            e.setHeight(r);\n                            break;\n                        case 3:\n                            r = new i.Rasterization();\n                            t.readMessage(r, i.Rasterization.deserializeBinaryFromReader),\n                                e.setRasterization(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.LocationData.BinaryMask.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.serializeBinaryToWriter = function(e, r) {\n                var o = void 0;\n                null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                    null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                    null != (o = e.getRasterization()) &&\n                        r.writeMessage(3, o, i.Rasterization.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.getWidth = function() {\n                return t.Message.getFieldWithDefault(this, 1, 0);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.setWidth = function(e) {\n                return t.Message.setField(this, 1, e);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.clearWidth = function() {\n                return t.Message.setField(this, 1, void 0);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.hasWidth = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.getHeight = function() {\n                return t.Message.getFieldWithDefault(this, 2, 0);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.setHeight = function(e) {\n                return t.Message.setField(this, 2, e);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.clearHeight = function() {\n                return t.Message.setField(this, 2, void 0);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.hasHeight = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.getRasterization = function() {\n                return t.Message.getWrapperField(this, i.Rasterization, 3);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.setRasterization = function(e) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.clearRasterization = function() {\n                return this.setRasterization(void 0);\n            }),\n            (proto.mediapipe.LocationData.BinaryMask.prototype.hasRasterization = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.LocationData.RelativeKeypoint.prototype.toObject = function(e) {\n                    return proto.mediapipe.LocationData.RelativeKeypoint.toObject(e, this);\n                }),\n                (proto.mediapipe.LocationData.RelativeKeypoint.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            x:\n                                null == (o = t.Message.getOptionalFloatingPointField(r, 1))\n                                    ? void 0\n                                    : o,\n                            y:\n                                null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                    ? void 0\n                                    : o,\n                            keypointLabel: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                            score:\n                                null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                    ? void 0\n                                    : o,\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.LocationData.RelativeKeypoint.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.LocationData.RelativeKeypoint();\n                return proto.mediapipe.LocationData.RelativeKeypoint.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readFloat();\n                            e.setX(r);\n                            break;\n                        case 2:\n                            r = t.readFloat();\n                            e.setY(r);\n                            break;\n                        case 3:\n                            r = t.readString();\n                            e.setKeypointLabel(r);\n                            break;\n                        case 4:\n                            r = t.readFloat();\n                            e.setScore(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.LocationData.RelativeKeypoint.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.serializeBinaryToWriter = function(\n                e,\n                r\n            ) {\n                var o = void 0;\n                null != (o = t.Message.getField(e, 1)) && r.writeFloat(1, o),\n                    null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                    null != (o = t.Message.getField(e, 3)) && r.writeString(3, o),\n                    null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.getX = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.setX = function(e) {\n                return t.Message.setField(this, 1, e);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.clearX = function() {\n                return t.Message.setField(this, 1, void 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.hasX = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.getY = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.setY = function(e) {\n                return t.Message.setField(this, 2, e);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.clearY = function() {\n                return t.Message.setField(this, 2, void 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.hasY = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.getKeypointLabel = function() {\n                return t.Message.getFieldWithDefault(this, 3, '');\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.setKeypointLabel = function(\n                e\n            ) {\n                return t.Message.setField(this, 3, e);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.clearKeypointLabel = function() {\n                return t.Message.setField(this, 3, void 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.hasKeypointLabel = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.getScore = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.setScore = function(e) {\n                return t.Message.setField(this, 4, e);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.clearScore = function() {\n                return t.Message.setField(this, 4, void 0);\n            }),\n            (proto.mediapipe.LocationData.RelativeKeypoint.prototype.hasScore = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.LocationData.prototype.getFormat = function() {\n                return t.Message.getFieldWithDefault(this, 1, 0);\n            }),\n            (proto.mediapipe.LocationData.prototype.setFormat = function(e) {\n                return t.Message.setField(this, 1, e);\n            }),\n            (proto.mediapipe.LocationData.prototype.clearFormat = function() {\n                return t.Message.setField(this, 1, void 0);\n            }),\n            (proto.mediapipe.LocationData.prototype.hasFormat = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.LocationData.prototype.getBoundingBox = function() {\n                return t.Message.getWrapperField(this, proto.mediapipe.LocationData.BoundingBox, 2);\n            }),\n            (proto.mediapipe.LocationData.prototype.setBoundingBox = function(e) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.LocationData.prototype.clearBoundingBox = function() {\n                return this.setBoundingBox(void 0);\n            }),\n            (proto.mediapipe.LocationData.prototype.hasBoundingBox = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.LocationData.prototype.getRelativeBoundingBox = function() {\n                return t.Message.getWrapperField(\n                    this,\n                    proto.mediapipe.LocationData.RelativeBoundingBox,\n                    3\n                );\n            }),\n            (proto.mediapipe.LocationData.prototype.setRelativeBoundingBox = function(e) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.LocationData.prototype.clearRelativeBoundingBox = function() {\n                return this.setRelativeBoundingBox(void 0);\n            }),\n            (proto.mediapipe.LocationData.prototype.hasRelativeBoundingBox = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.LocationData.prototype.getMask = function() {\n                return t.Message.getWrapperField(this, proto.mediapipe.LocationData.BinaryMask, 4);\n            }),\n            (proto.mediapipe.LocationData.prototype.setMask = function(e) {\n                return t.Message.setWrapperField(this, 4, e);\n            }),\n            (proto.mediapipe.LocationData.prototype.clearMask = function() {\n                return this.setMask(void 0);\n            }),\n            (proto.mediapipe.LocationData.prototype.hasMask = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.LocationData.prototype.getRelativeKeypointsList = function() {\n                return t.Message.getRepeatedWrapperField(\n                    this,\n                    proto.mediapipe.LocationData.RelativeKeypoint,\n                    5\n                );\n            }),\n            (proto.mediapipe.LocationData.prototype.setRelativeKeypointsList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 5, e);\n            }),\n            (proto.mediapipe.LocationData.prototype.addRelativeKeypoints = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    5,\n                    e,\n                    proto.mediapipe.LocationData.RelativeKeypoint,\n                    r\n                );\n            }),\n            (proto.mediapipe.LocationData.prototype.clearRelativeKeypointsList = function() {\n                return this.setRelativeKeypointsList([]);\n            }),\n            r.object.extend(e, proto.mediapipe);\n    })(location_data_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = location_data_pb;\n        r.object.extend(proto, i),\n            r.exportSymbol('proto.mediapipe.Detection', null, o),\n            r.exportSymbol('proto.mediapipe.Detection.AssociatedDetection', null, o),\n            r.exportSymbol('proto.mediapipe.DetectionList', null, o),\n            (proto.mediapipe.Detection = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    -1,\n                    proto.mediapipe.Detection.repeatedFields_,\n                    null\n                );\n            }),\n            r.inherits(proto.mediapipe.Detection, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.Detection.displayName = 'proto.mediapipe.Detection'),\n            (proto.mediapipe.Detection.AssociatedDetection = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.Detection.AssociatedDetection, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.Detection.AssociatedDetection.displayName =\n                    'proto.mediapipe.Detection.AssociatedDetection'),\n            (proto.mediapipe.DetectionList = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    -1,\n                    proto.mediapipe.DetectionList.repeatedFields_,\n                    null\n                );\n            }),\n            r.inherits(proto.mediapipe.DetectionList, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.DetectionList.displayName = 'proto.mediapipe.DetectionList'),\n            (proto.mediapipe.Detection.repeatedFields_ = [1, 2, 3, 8, 9]),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.Detection.prototype.toObject = function(e) {\n                    return proto.mediapipe.Detection.toObject(e, this);\n                }),\n                (proto.mediapipe.Detection.toObject = function(e, r) {\n                    var o,\n                        a = {\n                            labelList: null == (o = t.Message.getRepeatedField(r, 1)) ? void 0 : o,\n                            labelIdList:\n                                null == (o = t.Message.getRepeatedField(r, 2)) ? void 0 : o,\n                            scoreList:\n                                null == (o = t.Message.getRepeatedFloatingPointField(r, 3))\n                                    ? void 0\n                                    : o,\n                            locationData:\n                                (o = r.getLocationData()) && i.LocationData.toObject(e, o),\n                            featureTag: null == (o = t.Message.getField(r, 5)) ? void 0 : o,\n                            trackId: null == (o = t.Message.getField(r, 6)) ? void 0 : o,\n                            detectionId: null == (o = t.Message.getField(r, 7)) ? void 0 : o,\n                            associatedDetectionsList: t.Message.toObjectList(\n                                r.getAssociatedDetectionsList(),\n                                proto.mediapipe.Detection.AssociatedDetection.toObject,\n                                e\n                            ),\n                            displayNameList:\n                                null == (o = t.Message.getRepeatedField(r, 9)) ? void 0 : o,\n                            timestampUsec: null == (o = t.Message.getField(r, 10)) ? void 0 : o,\n                        };\n                    return e && (a.$jspbMessageInstance = r), a;\n                })),\n            (proto.mediapipe.Detection.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.Detection();\n                return proto.mediapipe.Detection.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.Detection.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readString();\n                            e.addLabel(r);\n                            break;\n                        case 2:\n                            for (\n                                var o = t.isDelimited() ? t.readPackedInt32() : [t.readInt32()],\n                                    a = 0;\n                                a < o.length;\n                                a++\n                            )\n                                e.addLabelId(o[a]);\n                            break;\n                        case 3:\n                            for (\n                                o = t.isDelimited() ? t.readPackedFloat() : [t.readFloat()], a = 0;\n                                a < o.length;\n                                a++\n                            )\n                                e.addScore(o[a]);\n                            break;\n                        case 4:\n                            r = new i.LocationData();\n                            t.readMessage(r, i.LocationData.deserializeBinaryFromReader),\n                                e.setLocationData(r);\n                            break;\n                        case 5:\n                            r = t.readString();\n                            e.setFeatureTag(r);\n                            break;\n                        case 6:\n                            r = t.readString();\n                            e.setTrackId(r);\n                            break;\n                        case 7:\n                            r = t.readInt64();\n                            e.setDetectionId(r);\n                            break;\n                        case 8:\n                            r = new proto.mediapipe.Detection.AssociatedDetection();\n                            t.readMessage(\n                                r,\n                                proto.mediapipe.Detection.AssociatedDetection\n                                    .deserializeBinaryFromReader\n                            ),\n                                e.addAssociatedDetections(r);\n                            break;\n                        case 9:\n                            r = t.readString();\n                            e.addDisplayName(r);\n                            break;\n                        case 10:\n                            r = t.readInt64();\n                            e.setTimestampUsec(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.Detection.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.Detection.serializeBinaryToWriter(this, e), e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.Detection.serializeBinaryToWriter = function(e, r) {\n                var o = void 0;\n                (o = e.getLabelList()).length > 0 && r.writeRepeatedString(1, o),\n                    (o = e.getLabelIdList()).length > 0 && r.writePackedInt32(2, o),\n                    (o = e.getScoreList()).length > 0 && r.writePackedFloat(3, o),\n                    null != (o = e.getLocationData()) &&\n                        r.writeMessage(4, o, i.LocationData.serializeBinaryToWriter),\n                    null != (o = t.Message.getField(e, 5)) && r.writeString(5, o),\n                    null != (o = t.Message.getField(e, 6)) && r.writeString(6, o),\n                    null != (o = t.Message.getField(e, 7)) && r.writeInt64(7, o),\n                    (o = e.getAssociatedDetectionsList()).length > 0 &&\n                        r.writeRepeatedMessage(\n                            8,\n                            o,\n                            proto.mediapipe.Detection.AssociatedDetection.serializeBinaryToWriter\n                        ),\n                    (o = e.getDisplayNameList()).length > 0 && r.writeRepeatedString(9, o),\n                    null != (o = t.Message.getField(e, 10)) && r.writeInt64(10, o);\n            }),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.Detection.AssociatedDetection.prototype.toObject = function(e) {\n                    return proto.mediapipe.Detection.AssociatedDetection.toObject(e, this);\n                }),\n                (proto.mediapipe.Detection.AssociatedDetection.toObject = function(e, r) {\n                    var o,\n                        i = {\n                            id: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                            confidence:\n                                null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                    ? void 0\n                                    : o,\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.Detection.AssociatedDetection.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.Detection.AssociatedDetection();\n                return proto.mediapipe.Detection.AssociatedDetection.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = t.readInt32();\n                            e.setId(r);\n                            break;\n                        case 2:\n                            r = t.readFloat();\n                            e.setConfidence(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.Detection.AssociatedDetection.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.serializeBinaryToWriter = function(\n                e,\n                r\n            ) {\n                var o = void 0;\n                null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                    null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o);\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.getId = function() {\n                return t.Message.getFieldWithDefault(this, 1, 0);\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.setId = function(e) {\n                return t.Message.setField(this, 1, e);\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.clearId = function() {\n                return t.Message.setField(this, 1, void 0);\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.hasId = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.getConfidence = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.setConfidence = function(e) {\n                return t.Message.setField(this, 2, e);\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.clearConfidence = function() {\n                return t.Message.setField(this, 2, void 0);\n            }),\n            (proto.mediapipe.Detection.AssociatedDetection.prototype.hasConfidence = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.Detection.prototype.getLabelList = function() {\n                return t.Message.getRepeatedField(this, 1);\n            }),\n            (proto.mediapipe.Detection.prototype.setLabelList = function(e) {\n                return t.Message.setField(this, 1, e || []);\n            }),\n            (proto.mediapipe.Detection.prototype.addLabel = function(e, r) {\n                return t.Message.addToRepeatedField(this, 1, e, r);\n            }),\n            (proto.mediapipe.Detection.prototype.clearLabelList = function() {\n                return this.setLabelList([]);\n            }),\n            (proto.mediapipe.Detection.prototype.getLabelIdList = function() {\n                return t.Message.getRepeatedField(this, 2);\n            }),\n            (proto.mediapipe.Detection.prototype.setLabelIdList = function(e) {\n                return t.Message.setField(this, 2, e || []);\n            }),\n            (proto.mediapipe.Detection.prototype.addLabelId = function(e, r) {\n                return t.Message.addToRepeatedField(this, 2, e, r);\n            }),\n            (proto.mediapipe.Detection.prototype.clearLabelIdList = function() {\n                return this.setLabelIdList([]);\n            }),\n            (proto.mediapipe.Detection.prototype.getScoreList = function() {\n                return t.Message.getRepeatedFloatingPointField(this, 3);\n            }),\n            (proto.mediapipe.Detection.prototype.setScoreList = function(e) {\n                return t.Message.setField(this, 3, e || []);\n            }),\n            (proto.mediapipe.Detection.prototype.addScore = function(e, r) {\n                return t.Message.addToRepeatedField(this, 3, e, r);\n            }),\n            (proto.mediapipe.Detection.prototype.clearScoreList = function() {\n                return this.setScoreList([]);\n            }),\n            (proto.mediapipe.Detection.prototype.getLocationData = function() {\n                return t.Message.getWrapperField(this, i.LocationData, 4);\n            }),\n            (proto.mediapipe.Detection.prototype.setLocationData = function(e) {\n                return t.Message.setWrapperField(this, 4, e);\n            }),\n            (proto.mediapipe.Detection.prototype.clearLocationData = function() {\n                return this.setLocationData(void 0);\n            }),\n            (proto.mediapipe.Detection.prototype.hasLocationData = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.Detection.prototype.getFeatureTag = function() {\n                return t.Message.getFieldWithDefault(this, 5, '');\n            }),\n            (proto.mediapipe.Detection.prototype.setFeatureTag = function(e) {\n                return t.Message.setField(this, 5, e);\n            }),\n            (proto.mediapipe.Detection.prototype.clearFeatureTag = function() {\n                return t.Message.setField(this, 5, void 0);\n            }),\n            (proto.mediapipe.Detection.prototype.hasFeatureTag = function() {\n                return null != t.Message.getField(this, 5);\n            }),\n            (proto.mediapipe.Detection.prototype.getTrackId = function() {\n                return t.Message.getFieldWithDefault(this, 6, '');\n            }),\n            (proto.mediapipe.Detection.prototype.setTrackId = function(e) {\n                return t.Message.setField(this, 6, e);\n            }),\n            (proto.mediapipe.Detection.prototype.clearTrackId = function() {\n                return t.Message.setField(this, 6, void 0);\n            }),\n            (proto.mediapipe.Detection.prototype.hasTrackId = function() {\n                return null != t.Message.getField(this, 6);\n            }),\n            (proto.mediapipe.Detection.prototype.getDetectionId = function() {\n                return t.Message.getFieldWithDefault(this, 7, 0);\n            }),\n            (proto.mediapipe.Detection.prototype.setDetectionId = function(e) {\n                return t.Message.setField(this, 7, e);\n            }),\n            (proto.mediapipe.Detection.prototype.clearDetectionId = function() {\n                return t.Message.setField(this, 7, void 0);\n            }),\n            (proto.mediapipe.Detection.prototype.hasDetectionId = function() {\n                return null != t.Message.getField(this, 7);\n            }),\n            (proto.mediapipe.Detection.prototype.getAssociatedDetectionsList = function() {\n                return t.Message.getRepeatedWrapperField(\n                    this,\n                    proto.mediapipe.Detection.AssociatedDetection,\n                    8\n                );\n            }),\n            (proto.mediapipe.Detection.prototype.setAssociatedDetectionsList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 8, e);\n            }),\n            (proto.mediapipe.Detection.prototype.addAssociatedDetections = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    8,\n                    e,\n                    proto.mediapipe.Detection.AssociatedDetection,\n                    r\n                );\n            }),\n            (proto.mediapipe.Detection.prototype.clearAssociatedDetectionsList = function() {\n                return this.setAssociatedDetectionsList([]);\n            }),\n            (proto.mediapipe.Detection.prototype.getDisplayNameList = function() {\n                return t.Message.getRepeatedField(this, 9);\n            }),\n            (proto.mediapipe.Detection.prototype.setDisplayNameList = function(e) {\n                return t.Message.setField(this, 9, e || []);\n            }),\n            (proto.mediapipe.Detection.prototype.addDisplayName = function(e, r) {\n                return t.Message.addToRepeatedField(this, 9, e, r);\n            }),\n            (proto.mediapipe.Detection.prototype.clearDisplayNameList = function() {\n                return this.setDisplayNameList([]);\n            }),\n            (proto.mediapipe.Detection.prototype.getTimestampUsec = function() {\n                return t.Message.getFieldWithDefault(this, 10, 0);\n            }),\n            (proto.mediapipe.Detection.prototype.setTimestampUsec = function(e) {\n                return t.Message.setField(this, 10, e);\n            }),\n            (proto.mediapipe.Detection.prototype.clearTimestampUsec = function() {\n                return t.Message.setField(this, 10, void 0);\n            }),\n            (proto.mediapipe.Detection.prototype.hasTimestampUsec = function() {\n                return null != t.Message.getField(this, 10);\n            }),\n            (proto.mediapipe.DetectionList.repeatedFields_ = [1]),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.DetectionList.prototype.toObject = function(e) {\n                    return proto.mediapipe.DetectionList.toObject(e, this);\n                }),\n                (proto.mediapipe.DetectionList.toObject = function(e, r) {\n                    var o = {\n                        detectionList: t.Message.toObjectList(\n                            r.getDetectionList(),\n                            proto.mediapipe.Detection.toObject,\n                            e\n                        ),\n                    };\n                    return e && (o.$jspbMessageInstance = r), o;\n                })),\n            (proto.mediapipe.DetectionList.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.DetectionList();\n                return proto.mediapipe.DetectionList.deserializeBinaryFromReader(o, r);\n            }),\n            (proto.mediapipe.DetectionList.deserializeBinaryFromReader = function(e, t) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    if (1 === t.getFieldNumber()) {\n                        var r = new proto.mediapipe.Detection();\n                        t.readMessage(r, proto.mediapipe.Detection.deserializeBinaryFromReader),\n                            e.addDetection(r);\n                    } else t.skipField();\n                }\n                return e;\n            }),\n            (proto.mediapipe.DetectionList.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.DetectionList.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.DetectionList.serializeBinaryToWriter = function(e, t) {\n                var r;\n                (r = e.getDetectionList()).length > 0 &&\n                    t.writeRepeatedMessage(1, r, proto.mediapipe.Detection.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.DetectionList.prototype.getDetectionList = function() {\n                return t.Message.getRepeatedWrapperField(this, proto.mediapipe.Detection, 1);\n            }),\n            (proto.mediapipe.DetectionList.prototype.setDetectionList = function(e) {\n                return t.Message.setRepeatedWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.DetectionList.prototype.addDetection = function(e, r) {\n                return t.Message.addToRepeatedWrapperField(\n                    this,\n                    1,\n                    e,\n                    proto.mediapipe.Detection,\n                    r\n                );\n            }),\n            (proto.mediapipe.DetectionList.prototype.clearDetectionList = function() {\n                return this.setDetectionList([]);\n            }),\n            r.object.extend(e, proto.mediapipe);\n    })(detection_pb);\nvar base_options_pb = {},\n    acceleration_pb = {},\n    inference_calculator_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a),\n        r.exportSymbol('proto.mediapipe.InferenceCalculatorOptions', null, o),\n        r.exportSymbol('proto.mediapipe.InferenceCalculatorOptions.Delegate', null, o),\n        r.exportSymbol('proto.mediapipe.InferenceCalculatorOptions.Delegate.DelegateCase', null, o),\n        r.exportSymbol('proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu', null, o),\n        r.exportSymbol('proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.Api', null, o),\n        r.exportSymbol(\n            'proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.InferenceUsage',\n            null,\n            o\n        ),\n        r.exportSymbol('proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi', null, o),\n        r.exportSymbol('proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite', null, o),\n        r.exportSymbol('proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack', null, o),\n        (proto.mediapipe.InferenceCalculatorOptions = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.InferenceCalculatorOptions, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.InferenceCalculatorOptions.displayName =\n                'proto.mediapipe.InferenceCalculatorOptions'),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                null,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.oneofGroups_\n            );\n        }),\n        r.inherits(proto.mediapipe.InferenceCalculatorOptions.Delegate, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.displayName =\n                'proto.mediapipe.InferenceCalculatorOptions.Delegate'),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.displayName =\n                'proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite'),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.displayName =\n                'proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu'),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.displayName =\n                'proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi'),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.displayName =\n                'proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.InferenceCalculatorOptions.prototype.toObject = function(e) {\n                return proto.mediapipe.InferenceCalculatorOptions.toObject(e, this);\n            }),\n            (proto.mediapipe.InferenceCalculatorOptions.toObject = function(e, r) {\n                var o,\n                    i = {\n                        modelPath: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        useGpu: t.Message.getBooleanFieldWithDefault(r, 2, !1),\n                        useNnapi: t.Message.getBooleanFieldWithDefault(r, 3, !1),\n                        cpuNumThread: t.Message.getFieldWithDefault(r, 4, -1),\n                        delegate:\n                            (o = r.getDelegate()) &&\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.toObject(e, o),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.InferenceCalculatorOptions.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.InferenceCalculatorOptions();\n            return proto.mediapipe.InferenceCalculatorOptions.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setModelPath(r);\n                        break;\n                    case 2:\n                        r = t.readBool();\n                        e.setUseGpu(r);\n                        break;\n                    case 3:\n                        r = t.readBool();\n                        e.setUseNnapi(r);\n                        break;\n                    case 4:\n                        r = t.readInt32();\n                        e.setCpuNumThread(r);\n                        break;\n                    case 5:\n                        r = new proto.mediapipe.InferenceCalculatorOptions.Delegate();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setDelegate(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.InferenceCalculatorOptions.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeBool(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeBool(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeInt32(4, o),\n                null != (o = e.getDelegate()) &&\n                    r.writeMessage(\n                        5,\n                        o,\n                        proto.mediapipe.InferenceCalculatorOptions.Delegate.serializeBinaryToWriter\n                    );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.oneofGroups_ = [[1, 2, 3, 4]]),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.DelegateCase = {\n            DELEGATE_NOT_SET: 0,\n            TFLITE: 1,\n            GPU: 2,\n            NNAPI: 3,\n            XNNPACK: 4,\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.getDelegateCase = function() {\n            return t.Message.computeOneofCase(\n                this,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.oneofGroups_[0]\n            );\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.toObject = function(e) {\n                return proto.mediapipe.InferenceCalculatorOptions.Delegate.toObject(e, this);\n            }),\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.toObject = function(e, t) {\n                var r,\n                    o = {\n                        tflite:\n                            (r = t.getTflite()) &&\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.toObject(\n                                e,\n                                r\n                            ),\n                        gpu:\n                            (r = t.getGpu()) &&\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.toObject(e, r),\n                        nnapi:\n                            (r = t.getNnapi()) &&\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.toObject(\n                                e,\n                                r\n                            ),\n                        xnnpack:\n                            (r = t.getXnnpack()) &&\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.toObject(\n                                e,\n                                r\n                            ),\n                    };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.InferenceCalculatorOptions.Delegate();\n            return proto.mediapipe.InferenceCalculatorOptions.Delegate.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setTflite(r);\n                        break;\n                    case 2:\n                        r = new proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setGpu(r);\n                        break;\n                    case 3:\n                        r = new proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setNnapi(r);\n                        break;\n                    case 4:\n                        r = new proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setXnnpack(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.serializeBinaryToWriter = function(\n            e,\n            t\n        ) {\n            var r = void 0;\n            null != (r = e.getTflite()) &&\n                t.writeMessage(\n                    1,\n                    r,\n                    proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite\n                        .serializeBinaryToWriter\n                ),\n                null != (r = e.getGpu()) &&\n                    t.writeMessage(\n                        2,\n                        r,\n                        proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu\n                            .serializeBinaryToWriter\n                    ),\n                null != (r = e.getNnapi()) &&\n                    t.writeMessage(\n                        3,\n                        r,\n                        proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi\n                            .serializeBinaryToWriter\n                    ),\n                null != (r = e.getXnnpack()) &&\n                    t.writeMessage(\n                        4,\n                        r,\n                        proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack\n                            .serializeBinaryToWriter\n                    );\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.toObject(e, this);\n            }),\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.toObject = function(e, t) {\n                var r = {};\n                return e && (r.$jspbMessageInstance = t), r;\n            })),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite();\n            return proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                t.getFieldNumber();\n                t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite.serializeBinaryToWriter = function(\n            e,\n            t\n        ) {}),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.toObject(e, this);\n            }),\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.toObject = function(e, r) {\n                var o,\n                    i = {\n                        useAdvancedGpuApi: t.Message.getBooleanFieldWithDefault(r, 1, !1),\n                        api: t.Message.getFieldWithDefault(r, 4, 0),\n                        allowPrecisionLoss: t.Message.getBooleanFieldWithDefault(r, 3, !0),\n                        cachedKernelPath: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        serializedModelDir: null == (o = t.Message.getField(r, 7)) ? void 0 : o,\n                        modelToken: null == (o = t.Message.getField(r, 8)) ? void 0 : o,\n                        usage: t.Message.getFieldWithDefault(r, 5, 2),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu();\n            return proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readBool();\n                        e.setUseAdvancedGpuApi(r);\n                        break;\n                    case 4:\n                        r = t.readEnum();\n                        e.setApi(r);\n                        break;\n                    case 3:\n                        r = t.readBool();\n                        e.setAllowPrecisionLoss(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.setCachedKernelPath(r);\n                        break;\n                    case 7:\n                        r = t.readString();\n                        e.setSerializedModelDir(r);\n                        break;\n                    case 8:\n                        r = t.readString();\n                        e.setModelToken(r);\n                        break;\n                    case 5:\n                        r = t.readEnum();\n                        e.setUsage(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeBool(1, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeEnum(4, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeBool(3, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeString(2, o),\n                null != (o = t.Message.getField(e, 7)) && r.writeString(7, o),\n                null != (o = t.Message.getField(e, 8)) && r.writeString(8, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeEnum(5, o);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.Api = {\n            ANY: 0,\n            OPENGL: 1,\n            OPENCL: 2,\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.InferenceUsage = {\n            UNSPECIFIED: 0,\n            FAST_SINGLE_ANSWER: 1,\n            SUSTAINED_SPEED: 2,\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.getUseAdvancedGpuApi = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 1, !1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.setUseAdvancedGpuApi = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.clearUseAdvancedGpuApi = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.hasUseAdvancedGpuApi = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.getApi = function() {\n            return t.Message.getFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.setApi = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.clearApi = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.hasApi = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.getAllowPrecisionLoss = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 3, !0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.setAllowPrecisionLoss = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.clearAllowPrecisionLoss = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.hasAllowPrecisionLoss = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.getCachedKernelPath = function() {\n            return t.Message.getFieldWithDefault(this, 2, '');\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.setCachedKernelPath = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.clearCachedKernelPath = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.hasCachedKernelPath = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.getSerializedModelDir = function() {\n            return t.Message.getFieldWithDefault(this, 7, '');\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.setSerializedModelDir = function(\n            e\n        ) {\n            return t.Message.setField(this, 7, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.clearSerializedModelDir = function() {\n            return t.Message.setField(this, 7, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.hasSerializedModelDir = function() {\n            return null != t.Message.getField(this, 7);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.getModelToken = function() {\n            return t.Message.getFieldWithDefault(this, 8, '');\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.setModelToken = function(\n            e\n        ) {\n            return t.Message.setField(this, 8, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.clearModelToken = function() {\n            return t.Message.setField(this, 8, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.hasModelToken = function() {\n            return null != t.Message.getField(this, 8);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.getUsage = function() {\n            return t.Message.getFieldWithDefault(this, 5, 2);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.setUsage = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.clearUsage = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu.prototype.hasUsage = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.toObject(e, this);\n            }),\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.toObject = function(e, r) {\n                var o,\n                    i = {\n                        cacheDir: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        modelToken: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        acceleratorName: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi();\n            return proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setCacheDir(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.setModelToken(r);\n                        break;\n                    case 3:\n                        r = t.readString();\n                        e.setAcceleratorName(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeString(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeString(3, o);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.getCacheDir = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.setCacheDir = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.clearCacheDir = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.hasCacheDir = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.getModelToken = function() {\n            return t.Message.getFieldWithDefault(this, 2, '');\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.setModelToken = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.clearModelToken = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.hasModelToken = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.getAcceleratorName = function() {\n            return t.Message.getFieldWithDefault(this, 3, '');\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.setAcceleratorName = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.clearAcceleratorName = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi.prototype.hasAcceleratorName = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.toObject = function(e, r) {\n                var o = { numThreads: t.Message.getFieldWithDefault(r, 1, -1) };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack();\n            return proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = t.readInt32();\n                    e.setNumThreads(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o;\n            null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.prototype.getNumThreads = function() {\n            return t.Message.getFieldWithDefault(this, 1, -1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.prototype.setNumThreads = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.prototype.clearNumThreads = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack.prototype.hasNumThreads = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.getTflite = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.TfLite,\n                1\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.setTflite = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                1,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.clearTflite = function() {\n            return this.setTflite(void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.hasTflite = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.getGpu = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.Gpu,\n                2\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.setGpu = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                2,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.clearGpu = function() {\n            return this.setGpu(void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.hasGpu = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.getNnapi = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.Nnapi,\n                3\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.setNnapi = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                3,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.clearNnapi = function() {\n            return this.setNnapi(void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.hasNnapi = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.getXnnpack = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.Xnnpack,\n                4\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.setXnnpack = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                4,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.clearXnnpack = function() {\n            return this.setXnnpack(void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.Delegate.prototype.hasXnnpack = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.ext = new t.ExtensionFieldInfo(\n            336783863,\n            { ext: 0 },\n            proto.mediapipe.InferenceCalculatorOptions,\n            proto.mediapipe.InferenceCalculatorOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[336783863] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.InferenceCalculatorOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.InferenceCalculatorOptions.serializeBinaryToWriter,\n            proto.mediapipe.InferenceCalculatorOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[336783863] =\n            proto.mediapipe.InferenceCalculatorOptions.ext),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.getModelPath = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.setModelPath = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.clearModelPath = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.hasModelPath = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.getUseGpu = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 2, !1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.setUseGpu = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.clearUseGpu = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.hasUseGpu = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.getUseNnapi = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 3, !1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.setUseNnapi = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.clearUseNnapi = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.hasUseNnapi = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.getCpuNumThread = function() {\n            return t.Message.getFieldWithDefault(this, 4, -1);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.setCpuNumThread = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.clearCpuNumThread = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.hasCpuNumThread = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.getDelegate = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.InferenceCalculatorOptions.Delegate,\n                5\n            );\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.setDelegate = function(e) {\n            return t.Message.setWrapperField(this, 5, e);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.clearDelegate = function() {\n            return this.setDelegate(void 0);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.prototype.hasDelegate = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.InferenceCalculatorOptions.ext = new t.ExtensionFieldInfo(\n            336783863,\n            { ext: 0 },\n            proto.mediapipe.InferenceCalculatorOptions,\n            proto.mediapipe.InferenceCalculatorOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[336783863] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.InferenceCalculatorOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.InferenceCalculatorOptions.serializeBinaryToWriter,\n            proto.mediapipe.InferenceCalculatorOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[336783863] =\n            proto.mediapipe.InferenceCalculatorOptions.ext),\n        r.object.extend(e, proto.mediapipe);\n})(inference_calculator_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = inference_calculator_pb;\n        r.object.extend(proto, i),\n            r.exportSymbol('proto.mediapipe.tasks.core.proto.Acceleration', null, o),\n            r.exportSymbol('proto.mediapipe.tasks.core.proto.Acceleration.DelegateCase', null, o),\n            (proto.mediapipe.tasks.core.proto.Acceleration = function(e) {\n                t.Message.initialize(\n                    this,\n                    e,\n                    0,\n                    -1,\n                    null,\n                    proto.mediapipe.tasks.core.proto.Acceleration.oneofGroups_\n                );\n            }),\n            r.inherits(proto.mediapipe.tasks.core.proto.Acceleration, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.core.proto.Acceleration.displayName =\n                    'proto.mediapipe.tasks.core.proto.Acceleration'),\n            (proto.mediapipe.tasks.core.proto.Acceleration.oneofGroups_ = [[1, 2, 4, 5]]),\n            (proto.mediapipe.tasks.core.proto.Acceleration.DelegateCase = {\n                DELEGATE_NOT_SET: 0,\n                XNNPACK: 1,\n                GPU: 2,\n                TFLITE: 4,\n                NNAPI: 5,\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.getDelegateCase = function() {\n                return t.Message.computeOneofCase(\n                    this,\n                    proto.mediapipe.tasks.core.proto.Acceleration.oneofGroups_[0]\n                );\n            }),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.core.proto.Acceleration.prototype.toObject = function(e) {\n                    return proto.mediapipe.tasks.core.proto.Acceleration.toObject(e, this);\n                }),\n                (proto.mediapipe.tasks.core.proto.Acceleration.toObject = function(e, t) {\n                    var r,\n                        o = {\n                            xnnpack:\n                                (r = t.getXnnpack()) &&\n                                i.InferenceCalculatorOptions.Delegate.Xnnpack.toObject(e, r),\n                            gpu:\n                                (r = t.getGpu()) &&\n                                i.InferenceCalculatorOptions.Delegate.Gpu.toObject(e, r),\n                            tflite:\n                                (r = t.getTflite()) &&\n                                i.InferenceCalculatorOptions.Delegate.TfLite.toObject(e, r),\n                            nnapi:\n                                (r = t.getNnapi()) &&\n                                i.InferenceCalculatorOptions.Delegate.Nnapi.toObject(e, r),\n                        };\n                    return e && (o.$jspbMessageInstance = t), o;\n                })),\n            (proto.mediapipe.tasks.core.proto.Acceleration.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.core.proto.Acceleration();\n                return proto.mediapipe.tasks.core.proto.Acceleration.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new i.InferenceCalculatorOptions.Delegate.Xnnpack();\n                            t.readMessage(\n                                r,\n                                i.InferenceCalculatorOptions.Delegate.Xnnpack\n                                    .deserializeBinaryFromReader\n                            ),\n                                e.setXnnpack(r);\n                            break;\n                        case 2:\n                            r = new i.InferenceCalculatorOptions.Delegate.Gpu();\n                            t.readMessage(\n                                r,\n                                i.InferenceCalculatorOptions.Delegate.Gpu\n                                    .deserializeBinaryFromReader\n                            ),\n                                e.setGpu(r);\n                            break;\n                        case 4:\n                            r = new i.InferenceCalculatorOptions.Delegate.TfLite();\n                            t.readMessage(\n                                r,\n                                i.InferenceCalculatorOptions.Delegate.TfLite\n                                    .deserializeBinaryFromReader\n                            ),\n                                e.setTflite(r);\n                            break;\n                        case 5:\n                            r = new i.InferenceCalculatorOptions.Delegate.Nnapi();\n                            t.readMessage(\n                                r,\n                                i.InferenceCalculatorOptions.Delegate.Nnapi\n                                    .deserializeBinaryFromReader\n                            ),\n                                e.setNnapi(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.core.proto.Acceleration.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.serializeBinaryToWriter = function(\n                e,\n                t\n            ) {\n                var r = void 0;\n                null != (r = e.getXnnpack()) &&\n                    t.writeMessage(\n                        1,\n                        r,\n                        i.InferenceCalculatorOptions.Delegate.Xnnpack.serializeBinaryToWriter\n                    ),\n                    null != (r = e.getGpu()) &&\n                        t.writeMessage(\n                            2,\n                            r,\n                            i.InferenceCalculatorOptions.Delegate.Gpu.serializeBinaryToWriter\n                        ),\n                    null != (r = e.getTflite()) &&\n                        t.writeMessage(\n                            4,\n                            r,\n                            i.InferenceCalculatorOptions.Delegate.TfLite.serializeBinaryToWriter\n                        ),\n                    null != (r = e.getNnapi()) &&\n                        t.writeMessage(\n                            5,\n                            r,\n                            i.InferenceCalculatorOptions.Delegate.Nnapi.serializeBinaryToWriter\n                        );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.getXnnpack = function() {\n                return t.Message.getWrapperField(\n                    this,\n                    i.InferenceCalculatorOptions.Delegate.Xnnpack,\n                    1\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.setXnnpack = function(e) {\n                return t.Message.setOneofWrapperField(\n                    this,\n                    1,\n                    proto.mediapipe.tasks.core.proto.Acceleration.oneofGroups_[0],\n                    e\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.clearXnnpack = function() {\n                return this.setXnnpack(void 0);\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.hasXnnpack = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.getGpu = function() {\n                return t.Message.getWrapperField(\n                    this,\n                    i.InferenceCalculatorOptions.Delegate.Gpu,\n                    2\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.setGpu = function(e) {\n                return t.Message.setOneofWrapperField(\n                    this,\n                    2,\n                    proto.mediapipe.tasks.core.proto.Acceleration.oneofGroups_[0],\n                    e\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.clearGpu = function() {\n                return this.setGpu(void 0);\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.hasGpu = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.getTflite = function() {\n                return t.Message.getWrapperField(\n                    this,\n                    i.InferenceCalculatorOptions.Delegate.TfLite,\n                    4\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.setTflite = function(e) {\n                return t.Message.setOneofWrapperField(\n                    this,\n                    4,\n                    proto.mediapipe.tasks.core.proto.Acceleration.oneofGroups_[0],\n                    e\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.clearTflite = function() {\n                return this.setTflite(void 0);\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.hasTflite = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.getNnapi = function() {\n                return t.Message.getWrapperField(\n                    this,\n                    i.InferenceCalculatorOptions.Delegate.Nnapi,\n                    5\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.setNnapi = function(e) {\n                return t.Message.setOneofWrapperField(\n                    this,\n                    5,\n                    proto.mediapipe.tasks.core.proto.Acceleration.oneofGroups_[0],\n                    e\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.clearNnapi = function() {\n                return this.setNnapi(void 0);\n            }),\n            (proto.mediapipe.tasks.core.proto.Acceleration.prototype.hasNnapi = function() {\n                return null != t.Message.getField(this, 5);\n            }),\n            r.object.extend(e, proto.mediapipe.tasks.core.proto);\n    })(acceleration_pb);\nvar external_file_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.tasks.core.proto.ExternalFile', null, o),\n        r.exportSymbol('proto.mediapipe.tasks.core.proto.FileDescriptorMeta', null, o),\n        r.exportSymbol('proto.mediapipe.tasks.core.proto.FilePointerMeta', null, o),\n        (proto.mediapipe.tasks.core.proto.ExternalFile = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.tasks.core.proto.ExternalFile, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.core.proto.ExternalFile.displayName =\n                'proto.mediapipe.tasks.core.proto.ExternalFile'),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.tasks.core.proto.FileDescriptorMeta, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.displayName =\n                'proto.mediapipe.tasks.core.proto.FileDescriptorMeta'),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.tasks.core.proto.FilePointerMeta, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.core.proto.FilePointerMeta.displayName =\n                'proto.mediapipe.tasks.core.proto.FilePointerMeta'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.core.proto.ExternalFile.prototype.toObject = function(e) {\n                return proto.mediapipe.tasks.core.proto.ExternalFile.toObject(e, this);\n            }),\n            (proto.mediapipe.tasks.core.proto.ExternalFile.toObject = function(e, r) {\n                var o,\n                    i = {\n                        fileContent: r.getFileContent_asB64(),\n                        fileName: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        fileDescriptorMeta:\n                            (o = r.getFileDescriptorMeta()) &&\n                            proto.mediapipe.tasks.core.proto.FileDescriptorMeta.toObject(e, o),\n                        filePointerMeta:\n                            (o = r.getFilePointerMeta()) &&\n                            proto.mediapipe.tasks.core.proto.FilePointerMeta.toObject(e, o),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.core.proto.ExternalFile();\n            return proto.mediapipe.tasks.core.proto.ExternalFile.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readBytes();\n                        e.setFileContent(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.setFileName(r);\n                        break;\n                    case 3:\n                        r = new proto.mediapipe.tasks.core.proto.FileDescriptorMeta();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.tasks.core.proto.FileDescriptorMeta\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setFileDescriptorMeta(r);\n                        break;\n                    case 4:\n                        r = new proto.mediapipe.tasks.core.proto.FilePointerMeta();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.tasks.core.proto.FilePointerMeta\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setFilePointerMeta(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.core.proto.ExternalFile.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeBytes(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeString(2, o),\n                null != (o = e.getFileDescriptorMeta()) &&\n                    r.writeMessage(\n                        3,\n                        o,\n                        proto.mediapipe.tasks.core.proto.FileDescriptorMeta.serializeBinaryToWriter\n                    ),\n                null != (o = e.getFilePointerMeta()) &&\n                    r.writeMessage(\n                        4,\n                        o,\n                        proto.mediapipe.tasks.core.proto.FilePointerMeta.serializeBinaryToWriter\n                    );\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.getFileContent = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.getFileContent_asB64 = function() {\n            return t.Message.bytesAsB64(this.getFileContent());\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.getFileContent_asU8 = function() {\n            return t.Message.bytesAsU8(this.getFileContent());\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.setFileContent = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.clearFileContent = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.hasFileContent = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.getFileName = function() {\n            return t.Message.getFieldWithDefault(this, 2, '');\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.setFileName = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.clearFileName = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.hasFileName = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.getFileDescriptorMeta = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.tasks.core.proto.FileDescriptorMeta,\n                3\n            );\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.setFileDescriptorMeta = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.clearFileDescriptorMeta = function() {\n            return this.setFileDescriptorMeta(void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.hasFileDescriptorMeta = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.getFilePointerMeta = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.tasks.core.proto.FilePointerMeta,\n                4\n            );\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.setFilePointerMeta = function(e) {\n            return t.Message.setWrapperField(this, 4, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.clearFilePointerMeta = function() {\n            return this.setFilePointerMeta(void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.ExternalFile.prototype.hasFilePointerMeta = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.toObject = function(e) {\n                return proto.mediapipe.tasks.core.proto.FileDescriptorMeta.toObject(e, this);\n            }),\n            (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.toObject = function(e, r) {\n                var o,\n                    i = {\n                        fd: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        length: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        offset: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.core.proto.FileDescriptorMeta();\n            return proto.mediapipe.tasks.core.proto.FileDescriptorMeta.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readInt32();\n                        e.setFd(r);\n                        break;\n                    case 2:\n                        r = t.readInt64();\n                        e.setLength(r);\n                        break;\n                    case 3:\n                        r = t.readInt64();\n                        e.setOffset(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.core.proto.FileDescriptorMeta.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt64(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt64(3, o);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.getFd = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.setFd = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.clearFd = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.hasFd = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.getLength = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.setLength = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.clearLength = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.hasLength = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.getOffset = function() {\n            return t.Message.getFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.setOffset = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.clearOffset = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FileDescriptorMeta.prototype.hasOffset = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.toObject = function(e) {\n                return proto.mediapipe.tasks.core.proto.FilePointerMeta.toObject(e, this);\n            }),\n            (proto.mediapipe.tasks.core.proto.FilePointerMeta.toObject = function(e, r) {\n                var o,\n                    i = {\n                        pointer: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        length: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.core.proto.FilePointerMeta();\n            return proto.mediapipe.tasks.core.proto.FilePointerMeta.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readUint64();\n                        e.setPointer(r);\n                        break;\n                    case 2:\n                        r = t.readInt64();\n                        e.setLength(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.core.proto.FilePointerMeta.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeUint64(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt64(2, o);\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.getPointer = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.setPointer = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.clearPointer = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.hasPointer = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.getLength = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.setLength = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.clearLength = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.core.proto.FilePointerMeta.prototype.hasLength = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        r.object.extend(e, proto.mediapipe.tasks.core.proto);\n})(external_file_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = acceleration_pb;\n        r.object.extend(proto, i);\n        var a = external_file_pb;\n        r.object.extend(proto, a),\n            r.exportSymbol('proto.mediapipe.tasks.core.proto.BaseOptions', null, o),\n            (proto.mediapipe.tasks.core.proto.BaseOptions = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.tasks.core.proto.BaseOptions, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.core.proto.BaseOptions.displayName =\n                    'proto.mediapipe.tasks.core.proto.BaseOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.core.proto.BaseOptions.prototype.toObject = function(e) {\n                    return proto.mediapipe.tasks.core.proto.BaseOptions.toObject(e, this);\n                }),\n                (proto.mediapipe.tasks.core.proto.BaseOptions.toObject = function(e, r) {\n                    var o,\n                        n = {\n                            modelAsset: (o = r.getModelAsset()) && a.ExternalFile.toObject(e, o),\n                            useStreamMode: t.Message.getBooleanFieldWithDefault(r, 2, !1),\n                            acceleration:\n                                (o = r.getAcceleration()) && i.Acceleration.toObject(e, o),\n                        };\n                    return e && (n.$jspbMessageInstance = r), n;\n                })),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.deserializeBinary = function(e) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.core.proto.BaseOptions();\n                return proto.mediapipe.tasks.core.proto.BaseOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new a.ExternalFile();\n                            t.readMessage(r, a.ExternalFile.deserializeBinaryFromReader),\n                                e.setModelAsset(r);\n                            break;\n                        case 2:\n                            r = t.readBool();\n                            e.setUseStreamMode(r);\n                            break;\n                        case 3:\n                            r = new i.Acceleration();\n                            t.readMessage(r, i.Acceleration.deserializeBinaryFromReader),\n                                e.setAcceleration(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.core.proto.BaseOptions.serializeBinaryToWriter(this, e),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.serializeBinaryToWriter = function(e, r) {\n                var o = void 0;\n                null != (o = e.getModelAsset()) &&\n                    r.writeMessage(1, o, a.ExternalFile.serializeBinaryToWriter),\n                    null != (o = t.Message.getField(e, 2)) && r.writeBool(2, o),\n                    null != (o = e.getAcceleration()) &&\n                        r.writeMessage(3, o, i.Acceleration.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.getModelAsset = function() {\n                return t.Message.getWrapperField(this, a.ExternalFile, 1);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.setModelAsset = function(e) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.clearModelAsset = function() {\n                return this.setModelAsset(void 0);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.hasModelAsset = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.getUseStreamMode = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 2, !1);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.setUseStreamMode = function(e) {\n                return t.Message.setField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.clearUseStreamMode = function() {\n                return t.Message.setField(this, 2, void 0);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.hasUseStreamMode = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.getAcceleration = function() {\n                return t.Message.getWrapperField(this, i.Acceleration, 3);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.setAcceleration = function(e) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.clearAcceleration = function() {\n                return this.setAcceleration(void 0);\n            }),\n            (proto.mediapipe.tasks.core.proto.BaseOptions.prototype.hasAcceleration = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            r.object.extend(e, proto.mediapipe.tasks.core.proto);\n    })(base_options_pb);\nvar face_detector_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                        minDetectionConfidence: t.Message.getFloatingPointFieldWithDefault(\n                            r,\n                            2,\n                            0.5\n                        ),\n                        minSuppressionThreshold: t.Message.getFloatingPointFieldWithDefault(\n                            r,\n                            3,\n                            0.5\n                        ),\n                        numFaces: null == (o = t.Message.getField(r, 4)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions();\n            return proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new n.BaseOptions();\n                        t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setMinDetectionConfidence(r);\n                        break;\n                    case 3:\n                        r = t.readFloat();\n                        e.setMinSuppressionThreshold(r);\n                        break;\n                    case 4:\n                        r = t.readInt32();\n                        e.setNumFaces(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getBaseOptions()) &&\n                r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeFloat(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeInt32(4, o);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            502141897,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[502141897] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[502141897] =\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.getMinDetectionConfidence = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0.5);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.setMinDetectionConfidence = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.clearMinDetectionConfidence = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.hasMinDetectionConfidence = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.getMinSuppressionThreshold = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0.5);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.setMinSuppressionThreshold = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.clearMinSuppressionThreshold = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.hasMinSuppressionThreshold = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.getNumFaces = function() {\n            return t.Message.getFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.setNumFaces = function(\n            e\n        ) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.clearNumFaces = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.prototype.hasNumFaces = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            502141897,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[502141897] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[502141897] =\n            proto.mediapipe.tasks.vision.face_detector.proto.FaceDetectorGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.face_detector.proto);\n})(face_detector_graph_options_pb);\nvar detection_result = {};\nObject.defineProperty(detection_result, '__esModule', { value: !0 }),\n    (detection_result.convertFromDetectionProto = void 0);\nconst DEFAULT_CATEGORY_INDEX = -1;\nfunction convertFromDetectionProto(e) {\n    var t, r, o, i, a, n, s, p, d, l, g, c, u;\n    const m = e.getScoreList(),\n        f = e.getLabelIdList(),\n        h = e.getLabelList(),\n        y = e.getDisplayNameList(),\n        b = { categories: [], keypoints: [] };\n    for (let e = 0; e < m.length; e++)\n        b.categories.push({\n            score: m[e],\n            index: null !== (t = f[e]) && void 0 !== t ? t : DEFAULT_CATEGORY_INDEX,\n            categoryName: null !== (r = h[e]) && void 0 !== r ? r : '',\n            displayName: null !== (o = y[e]) && void 0 !== o ? o : '',\n        });\n    const _ = null === (i = e.getLocationData()) || void 0 === i ? void 0 : i.getBoundingBox();\n    if (\n        (_ &&\n            (b.boundingBox = {\n                originX: null !== (a = _.getXmin()) && void 0 !== a ? a : 0,\n                originY: null !== (n = _.getYmin()) && void 0 !== n ? n : 0,\n                width: null !== (s = _.getWidth()) && void 0 !== s ? s : 0,\n                height: null !== (p = _.getHeight()) && void 0 !== p ? p : 0,\n            }),\n        null === (d = e.getLocationData()) || void 0 === d\n            ? void 0\n            : d.getRelativeKeypointsList().length)\n    )\n        for (const t of e.getLocationData().getRelativeKeypointsList())\n            b.keypoints.push({\n                x: null !== (l = t.getX()) && void 0 !== l ? l : 0,\n                y: null !== (g = t.getY()) && void 0 !== g ? g : 0,\n                score: null !== (c = t.getScore()) && void 0 !== c ? c : 0,\n                label: null !== (u = t.getKeypointLabel()) && void 0 !== u ? u : '',\n            });\n    return b;\n}\ndetection_result.convertFromDetectionProto = convertFromDetectionProto;\nvar vision_task_runner = {},\n    rect_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.NormalizedRect', null, o),\n        r.exportSymbol('proto.mediapipe.Rect', null, o),\n        (proto.mediapipe.Rect = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.Rect, t.Message),\n        r.DEBUG && !COMPILED && (proto.mediapipe.Rect.displayName = 'proto.mediapipe.Rect'),\n        (proto.mediapipe.NormalizedRect = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.NormalizedRect, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.NormalizedRect.displayName = 'proto.mediapipe.NormalizedRect'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.Rect.prototype.toObject = function(e) {\n                return proto.mediapipe.Rect.toObject(e, this);\n            }),\n            (proto.mediapipe.Rect.toObject = function(e, r) {\n                var o,\n                    i = {\n                        xCenter: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        yCenter: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        height: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                        width: null == (o = t.Message.getField(r, 4)) ? void 0 : o,\n                        rotation: t.Message.getFloatingPointFieldWithDefault(r, 5, 0),\n                        rectId: null == (o = t.Message.getField(r, 6)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.Rect.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.Rect();\n            return proto.mediapipe.Rect.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.Rect.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readInt32();\n                        e.setXCenter(r);\n                        break;\n                    case 2:\n                        r = t.readInt32();\n                        e.setYCenter(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setHeight(r);\n                        break;\n                    case 4:\n                        r = t.readInt32();\n                        e.setWidth(r);\n                        break;\n                    case 5:\n                        r = t.readFloat();\n                        e.setRotation(r);\n                        break;\n                    case 6:\n                        r = t.readInt64();\n                        e.setRectId(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.Rect.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return proto.mediapipe.Rect.serializeBinaryToWriter(this, e), e.getResultBuffer();\n        }),\n        (proto.mediapipe.Rect.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeInt32(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeFloat(5, o),\n                null != (o = t.Message.getField(e, 6)) && r.writeInt64(6, o);\n        }),\n        (proto.mediapipe.Rect.prototype.getXCenter = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.Rect.prototype.setXCenter = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.Rect.prototype.clearXCenter = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.Rect.prototype.hasXCenter = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.Rect.prototype.getYCenter = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.Rect.prototype.setYCenter = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.Rect.prototype.clearYCenter = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.Rect.prototype.hasYCenter = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.Rect.prototype.getHeight = function() {\n            return t.Message.getFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.Rect.prototype.setHeight = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.Rect.prototype.clearHeight = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.Rect.prototype.hasHeight = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.Rect.prototype.getWidth = function() {\n            return t.Message.getFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.Rect.prototype.setWidth = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.Rect.prototype.clearWidth = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.Rect.prototype.hasWidth = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.Rect.prototype.getRotation = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 5, 0);\n        }),\n        (proto.mediapipe.Rect.prototype.setRotation = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.Rect.prototype.clearRotation = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.Rect.prototype.hasRotation = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.Rect.prototype.getRectId = function() {\n            return t.Message.getFieldWithDefault(this, 6, 0);\n        }),\n        (proto.mediapipe.Rect.prototype.setRectId = function(e) {\n            return t.Message.setField(this, 6, e);\n        }),\n        (proto.mediapipe.Rect.prototype.clearRectId = function() {\n            return t.Message.setField(this, 6, void 0);\n        }),\n        (proto.mediapipe.Rect.prototype.hasRectId = function() {\n            return null != t.Message.getField(this, 6);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.NormalizedRect.prototype.toObject = function(e) {\n                return proto.mediapipe.NormalizedRect.toObject(e, this);\n            }),\n            (proto.mediapipe.NormalizedRect.toObject = function(e, r) {\n                var o,\n                    i = {\n                        xCenter:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 1))\n                                ? void 0\n                                : o,\n                        yCenter:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                ? void 0\n                                : o,\n                        height:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        width:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                ? void 0\n                                : o,\n                        rotation: t.Message.getFloatingPointFieldWithDefault(r, 5, 0),\n                        rectId: null == (o = t.Message.getField(r, 6)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.NormalizedRect.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.NormalizedRect();\n            return proto.mediapipe.NormalizedRect.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.NormalizedRect.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readFloat();\n                        e.setXCenter(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setYCenter(r);\n                        break;\n                    case 3:\n                        r = t.readFloat();\n                        e.setHeight(r);\n                        break;\n                    case 4:\n                        r = t.readFloat();\n                        e.setWidth(r);\n                        break;\n                    case 5:\n                        r = t.readFloat();\n                        e.setRotation(r);\n                        break;\n                    case 6:\n                        r = t.readInt64();\n                        e.setRectId(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.NormalizedRect.serializeBinaryToWriter(this, e), e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.NormalizedRect.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeFloat(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeFloat(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeFloat(5, o),\n                null != (o = t.Message.getField(e, 6)) && r.writeInt64(6, o);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.getXCenter = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.setXCenter = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.clearXCenter = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.hasXCenter = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.getYCenter = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.setYCenter = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.clearYCenter = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.hasYCenter = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.getHeight = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.setHeight = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.clearHeight = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.hasHeight = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.getWidth = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.setWidth = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.clearWidth = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.hasWidth = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.getRotation = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 5, 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.setRotation = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.clearRotation = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.hasRotation = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.getRectId = function() {\n            return t.Message.getFieldWithDefault(this, 6, 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.setRectId = function(e) {\n            return t.Message.setField(this, 6, e);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.clearRectId = function() {\n            return t.Message.setField(this, 6, void 0);\n        }),\n        (proto.mediapipe.NormalizedRect.prototype.hasRectId = function() {\n            return null != t.Message.getField(this, 6);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(rect_pb);\nvar task_runner = {},\n    graph_runner = {};\n!(function(e) {\n    Object.defineProperty(e, '__esModule', { value: !0 }),\n        (e.createGraphRunner = e.createMediaPipeLib = e.GraphRunner = e.CALCULATOR_GRAPH_CONFIG_LISTENER_NAME = void 0);\n    const t = platform_utils;\n    e.CALCULATOR_GRAPH_CONFIG_LISTENER_NAME = '__graph_config__';\n    class r {\n        constructor(e, r) {\n            (this.autoResizeCanvas = !0),\n                (this.wasmModule = e),\n                (this.audioPtr = null),\n                (this.audioSize = 0),\n                (this.hasMultiStreamSupport =\n                    'function' == typeof this.wasmModule._addIntToInputStream),\n                void 0 !== r\n                    ? (this.wasmModule.canvas = r)\n                    : 'undefined' == typeof OffscreenCanvas || (0, t.isWebKit)()\n                    ? (console.warn(\n                          'OffscreenCanvas not supported and GraphRunner constructor glCanvas parameter is undefined. Creating backup canvas.'\n                      ),\n                      (this.wasmModule.canvas = document.createElement('canvas')))\n                    : (this.wasmModule.canvas = new OffscreenCanvas(1, 1));\n        }\n        async initializeGraph(e) {\n            const t = await fetch(e),\n                r = await t.arrayBuffer(),\n                o = !(e.endsWith('.pbtxt') || e.endsWith('.textproto'));\n            this.setGraph(new Uint8Array(r), o);\n        }\n        setGraphFromString(e) {\n            this.setGraph(new TextEncoder().encode(e), !1);\n        }\n        setGraph(e, t) {\n            const r = e.length,\n                o = this.wasmModule._malloc(r);\n            this.wasmModule.HEAPU8.set(e, o),\n                t\n                    ? this.wasmModule._changeBinaryGraph(r, o)\n                    : this.wasmModule._changeTextGraph(r, o),\n                this.wasmModule._free(o);\n        }\n        configureAudio(e, t, r, o, i) {\n            this.wasmModule._configureAudio ||\n                console.warn(\n                    'Attempting to use configureAudio without support for input audio. Is build dep \":gl_graph_runner_audio\" missing?'\n                ),\n                (o = o || 'input_audio'),\n                this.wrapStringPtr(o, (o) => {\n                    (i = i || 'audio_header'),\n                        this.wrapStringPtr(i, (i) => {\n                            this.wasmModule._configureAudio(o, i, e, t, r);\n                        });\n                });\n        }\n        setAutoResizeCanvas(e) {\n            this.autoResizeCanvas = e;\n        }\n        setAutoRenderToScreen(e) {\n            this.wasmModule._setAutoRenderToScreen(e);\n        }\n        bindTextureToStream(e, t) {\n            if (!this.wasmModule.canvas) throw new Error('No OpenGL canvas configured.');\n            t\n                ? this.wasmModule._bindTextureToStream(t)\n                : console.assert(this.wasmModule._bindTextureToCanvas());\n            const r =\n                this.wasmModule.canvas.getContext('webgl2') ||\n                this.wasmModule.canvas.getContext('webgl');\n            if (!r)\n                throw new Error(\n                    'Failed to obtain WebGL context from the provided canvas. `getContext()` should only be invoked with `webgl` or `webgl2`.'\n                );\n            let o, i;\n            return (\n                r.texImage2D(r.TEXTURE_2D, 0, r.RGBA, r.RGBA, r.UNSIGNED_BYTE, e),\n                e.videoWidth\n                    ? ((o = e.videoWidth), (i = e.videoHeight))\n                    : e.naturalWidth\n                    ? ((o = e.naturalWidth), (i = e.naturalHeight))\n                    : ((o = e.width), (i = e.height)),\n                !this.autoResizeCanvas ||\n                    (o === this.wasmModule.canvas.width && i === this.wasmModule.canvas.height) ||\n                    ((this.wasmModule.canvas.width = o), (this.wasmModule.canvas.height = i)),\n                [o, i]\n            );\n        }\n        processGl(e, t) {\n            const [r, o] = this.bindTextureToStream(e),\n                i = this.wasmModule._malloc(16);\n            (this.wasmModule.HEAPU32[i / 4] = r),\n                (this.wasmModule.HEAPU32[i / 4 + 1] = o),\n                (this.wasmModule.HEAPF64[i / 8 + 1] = t),\n                this.wasmModule._processGl(i),\n                this.wasmModule._free(i);\n        }\n        wrapStringPtr(e, t) {\n            this.hasMultiStreamSupport ||\n                console.error(\n                    'No wasm multistream support detected: ensure dependency inclusion of :gl_graph_runner_internal_multi_input target'\n                );\n            const r = this.wasmModule.stringToNewUTF8(e);\n            t(r), this.wasmModule._free(r);\n        }\n        wrapStringPtrPtr(e, t) {\n            this.hasMultiStreamSupport ||\n                console.error(\n                    'No wasm multistream support detected: ensure dependency inclusion of :gl_graph_runner_internal_multi_input target'\n                );\n            const r = new Uint32Array(e.length);\n            for (let t = 0; t < e.length; t++) r[t] = this.wasmModule.stringToNewUTF8(e[t]);\n            const o = this.wasmModule._malloc(4 * r.length);\n            this.wasmModule.HEAPU32.set(r, o >> 2), t(o);\n            for (const e of r) this.wasmModule._free(e);\n            this.wasmModule._free(o);\n        }\n        getCalculatorGraphConfig(t, r) {\n            const o = e.CALCULATOR_GRAPH_CONFIG_LISTENER_NAME;\n            this.setListener(o, (e) => {\n                t(e);\n            }),\n                this.wrapStringPtr(o, (e) => {\n                    this.wasmModule._getGraphConfig(e, r);\n                }),\n                delete this.wasmModule.simpleListeners[o];\n        }\n        setListener(e, t) {\n            (this.wasmModule.simpleListeners = this.wasmModule.simpleListeners || {}),\n                (this.wasmModule.simpleListeners[e] = t);\n        }\n        setVectorListener(e, t) {\n            let r = [];\n            (this.wasmModule.simpleListeners = this.wasmModule.simpleListeners || {}),\n                (this.wasmModule.simpleListeners[e] = (e, o, i) => {\n                    o ? (t(r, i), (r = [])) : r.push(e);\n                });\n        }\n        attachErrorListener(e) {\n            this.wasmModule.errorListener = e;\n        }\n        attachEmptyPacketListener(e, t) {\n            (this.wasmModule.emptyPacketListeners = this.wasmModule.emptyPacketListeners || {}),\n                (this.wasmModule.emptyPacketListeners[e] = t);\n        }\n        addAudioToStream(e, t, r) {\n            this.addAudioToStreamWithShape(e, 0, 0, t, r);\n        }\n        addAudioToStreamWithShape(e, t, r, o, i) {\n            const a = 4 * e.length;\n            this.audioSize !== a &&\n                (this.audioPtr && this.wasmModule._free(this.audioPtr),\n                (this.audioPtr = this.wasmModule._malloc(a)),\n                (this.audioSize = a)),\n                this.wasmModule.HEAPF32.set(e, this.audioPtr / 4),\n                this.wrapStringPtr(o, (e) => {\n                    this.wasmModule._addAudioToInputStream(this.audioPtr, t, r, e, i);\n                });\n        }\n        addGpuBufferToStream(e, t, r) {\n            this.wrapStringPtr(t, (t) => {\n                const [o, i] = this.bindTextureToStream(e, t);\n                this.wasmModule._addBoundTextureToStream(t, o, i, r);\n            });\n        }\n        addBoolToStream(e, t, r) {\n            this.wrapStringPtr(t, (t) => {\n                this.wasmModule._addBoolToInputStream(e, t, r);\n            });\n        }\n        addDoubleToStream(e, t, r) {\n            this.wrapStringPtr(t, (t) => {\n                this.wasmModule._addDoubleToInputStream(e, t, r);\n            });\n        }\n        addFloatToStream(e, t, r) {\n            this.wrapStringPtr(t, (t) => {\n                this.wasmModule._addFloatToInputStream(e, t, r);\n            });\n        }\n        addIntToStream(e, t, r) {\n            this.wrapStringPtr(t, (t) => {\n                this.wasmModule._addIntToInputStream(e, t, r);\n            });\n        }\n        addStringToStream(e, t, r) {\n            this.wrapStringPtr(t, (t) => {\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._addStringToInputStream(e, t, r);\n                });\n            });\n        }\n        addStringRecordToStream(e, t, r) {\n            this.wrapStringPtr(t, (t) => {\n                this.wrapStringPtrPtr(Object.keys(e), (o) => {\n                    this.wrapStringPtrPtr(Object.values(e), (i) => {\n                        this.wasmModule._addFlatHashMapToInputStream(\n                            o,\n                            i,\n                            Object.keys(e).length,\n                            t,\n                            r\n                        );\n                    });\n                });\n            });\n        }\n        addProtoToStream(e, t, r, o) {\n            this.wrapStringPtr(r, (r) => {\n                this.wrapStringPtr(t, (t) => {\n                    const i = this.wasmModule._malloc(e.length);\n                    this.wasmModule.HEAPU8.set(e, i),\n                        this.wasmModule._addProtoToInputStream(i, e.length, t, r, o),\n                        this.wasmModule._free(i);\n                });\n            });\n        }\n        addEmptyPacketToStream(e, t) {\n            this.wrapStringPtr(e, (e) => {\n                this.wasmModule._addEmptyPacketToInputStream(e, t);\n            });\n        }\n        addBoolToInputSidePacket(e, t) {\n            this.wrapStringPtr(t, (t) => {\n                this.wasmModule._addBoolToInputSidePacket(e, t);\n            });\n        }\n        addDoubleToInputSidePacket(e, t) {\n            this.wrapStringPtr(t, (t) => {\n                this.wasmModule._addDoubleToInputSidePacket(e, t);\n            });\n        }\n        addFloatToInputSidePacket(e, t) {\n            this.wrapStringPtr(t, (t) => {\n                this.wasmModule._addFloatToInputSidePacket(e, t);\n            });\n        }\n        addIntToInputSidePacket(e, t) {\n            this.wrapStringPtr(t, (t) => {\n                this.wasmModule._addIntToInputSidePacket(e, t);\n            });\n        }\n        addStringToInputSidePacket(e, t) {\n            this.wrapStringPtr(t, (t) => {\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._addStringToInputSidePacket(e, t);\n                });\n            });\n        }\n        addProtoToInputSidePacket(e, t, r) {\n            this.wrapStringPtr(r, (r) => {\n                this.wrapStringPtr(t, (t) => {\n                    const o = this.wasmModule._malloc(e.length);\n                    this.wasmModule.HEAPU8.set(e, o),\n                        this.wasmModule._addProtoToInputSidePacket(o, e.length, t, r),\n                        this.wasmModule._free(o);\n                });\n            });\n        }\n        attachBoolListener(e, t) {\n            this.setListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachBoolListener(e);\n                });\n        }\n        attachBoolVectorListener(e, t) {\n            this.setVectorListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachBoolVectorListener(e);\n                });\n        }\n        attachIntListener(e, t) {\n            this.setListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachIntListener(e);\n                });\n        }\n        attachIntVectorListener(e, t) {\n            this.setVectorListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachIntVectorListener(e);\n                });\n        }\n        attachDoubleListener(e, t) {\n            this.setListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachDoubleListener(e);\n                });\n        }\n        attachDoubleVectorListener(e, t) {\n            this.setVectorListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachDoubleVectorListener(e);\n                });\n        }\n        attachFloatListener(e, t) {\n            this.setListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachFloatListener(e);\n                });\n        }\n        attachFloatVectorListener(e, t) {\n            this.setVectorListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachFloatVectorListener(e);\n                });\n        }\n        attachStringListener(e, t) {\n            this.setListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachStringListener(e);\n                });\n        }\n        attachStringVectorListener(e, t) {\n            this.setVectorListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachStringVectorListener(e);\n                });\n        }\n        attachProtoListener(e, t, r) {\n            this.setListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachProtoListener(e, r || !1);\n                });\n        }\n        attachProtoVectorListener(e, t, r) {\n            this.setVectorListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachProtoVectorListener(e, r || !1);\n                });\n        }\n        attachAudioListener(e, t, r) {\n            this.wasmModule._attachAudioListener ||\n                console.warn(\n                    'Attempting to use attachAudioListener without support for output audio. Is build dep \":gl_graph_runner_audio_out\" missing?'\n                ),\n                this.setListener(e, (e, r) => {\n                    const o = new Float32Array(e.buffer, e.byteOffset, e.length / 4);\n                    t(o, r);\n                }),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmModule._attachAudioListener(e, r || !1);\n                });\n        }\n        finishProcessing() {\n            this.wasmModule._waitUntilIdle();\n        }\n        closeGraph() {\n            this.wasmModule._closeGraph(),\n                (this.wasmModule.simpleListeners = void 0),\n                (this.wasmModule.emptyPacketListeners = void 0);\n        }\n    }\n    async function o(e) {\n        if ('function' != typeof importScripts) {\n            const t = document.createElement('script');\n            return (\n                t.setAttribute('src', e),\n                t.setAttribute('crossorigin', 'anonymous'),\n                new Promise((e) => {\n                    t.addEventListener(\n                        'load',\n                        () => {\n                            e();\n                        },\n                        !1\n                    ),\n                        t.addEventListener(\n                            'error',\n                            () => {\n                                e();\n                            },\n                            !1\n                        ),\n                        document.body.appendChild(t);\n                })\n            );\n        }\n        importScripts(e.toString());\n    }\n    async function i(e, t, r, i, a) {\n        const n = [];\n        if (\n            (t && n.push(t),\n            r && n.push(r),\n            n.length && (await Promise.all(n.map(o))),\n            !self.ModuleFactory)\n        )\n            throw new Error('ModuleFactory not set.');\n        if (self.Module && a) {\n            const e = self.Module;\n            (e.locateFile = a.locateFile),\n                a.mainScriptUrlOrBlob && (e.mainScriptUrlOrBlob = a.mainScriptUrlOrBlob);\n        }\n        const s = await self.ModuleFactory(self.Module || a);\n        return (self.ModuleFactory = self.Module = void 0), new e(s, i);\n    }\n    (e.GraphRunner = r),\n        (e.createMediaPipeLib = i),\n        (e.createGraphRunner = async function(e, t, o, a) {\n            return i(r, e, t, o, a);\n        });\n})(graph_runner);\nvar register_model_resources_graph_service = {};\nfunction SupportModelResourcesGraphService(e) {\n    return class extends e {\n        registerModelResourcesGraphService() {\n            this.wasmModule._registerModelResourcesGraphService();\n        }\n    };\n}\nObject.defineProperty(register_model_resources_graph_service, '__esModule', { value: !0 }),\n    (register_model_resources_graph_service.SupportModelResourcesGraphService = void 0),\n    (register_model_resources_graph_service.SupportModelResourcesGraphService = SupportModelResourcesGraphService),\n    Object.defineProperty(task_runner, '__esModule', { value: !0 }),\n    (task_runner.TaskRunner = task_runner.createTaskRunner = task_runner.CachedGraphRunner = void 0);\nconst inference_calculator_pb_1 = inference_calculator_pb,\n    calculator_pb_1 = calculator_pb,\n    acceleration_pb_1 = acceleration_pb,\n    external_file_pb_1 = external_file_pb,\n    graph_runner_1$1 = graph_runner,\n    register_model_resources_graph_service_1$1 = register_model_resources_graph_service,\n    NO_ASSETS = void 0,\n    FREE_MEMORY_STREAM = 'free_memory',\n    UNUSED_STREAM_SUFFIX = '_unused_out',\n    CachedGraphRunnerType = (0,\n    register_model_resources_graph_service_1$1.SupportModelResourcesGraphService)(\n        graph_runner_1$1.GraphRunner\n    );\nclass CachedGraphRunner extends CachedGraphRunnerType {}\nasync function createTaskRunner(e, t, r, o) {\n    const i = { locateFile: () => r.wasmBinaryPath.toString() },\n        a = await (0, graph_runner_1$1.createMediaPipeLib)(e, r.wasmLoaderPath, NO_ASSETS, t, i);\n    return await a.setOptions(o), a;\n}\n(task_runner.CachedGraphRunner = CachedGraphRunner),\n    (task_runner.createTaskRunner = createTaskRunner);\nclass TaskRunner {\n    static async createInstance(e, t, r, o) {\n        return createTaskRunner(e, t, r, o);\n    }\n    constructor(e) {\n        (this.graphRunner = e),\n            (this.processingErrors = []),\n            (this.latestOutputTimestamp = 0),\n            this.graphRunner.setAutoRenderToScreen(!1);\n    }\n    applyOptions(e) {\n        var t, r, o, i, a, n;\n        const s = e.baseOptions || {};\n        if (\n            (null === (t = e.baseOptions) || void 0 === t ? void 0 : t.modelAssetBuffer) &&\n            (null === (r = e.baseOptions) || void 0 === r ? void 0 : r.modelAssetPath)\n        )\n            throw new Error(\n                'Cannot set both baseOptions.modelAssetPath and baseOptions.modelAssetBuffer'\n            );\n        if (\n            !(\n                (null === (o = this.baseOptions.getModelAsset()) || void 0 === o\n                    ? void 0\n                    : o.hasFileContent()) ||\n                (null === (i = this.baseOptions.getModelAsset()) || void 0 === i\n                    ? void 0\n                    : i.hasFileName()) ||\n                (null === (a = e.baseOptions) || void 0 === a ? void 0 : a.modelAssetBuffer) ||\n                (null === (n = e.baseOptions) || void 0 === n ? void 0 : n.modelAssetPath)\n            )\n        )\n            throw new Error(\n                'Either baseOptions.modelAssetPath or baseOptions.modelAssetBuffer must be set'\n            );\n        return (\n            this.setAcceleration(s),\n            s.modelAssetPath\n                ? fetch(s.modelAssetPath.toString())\n                      .then((e) => {\n                          if (e.ok) return e.arrayBuffer();\n                          throw new Error(\n                              `Failed to fetch model: ${s.modelAssetPath} (${e.status})`\n                          );\n                      })\n                      .then((e) => {\n                          try {\n                              this.graphRunner.wasmModule.FS_unlink('/model.dat');\n                          } catch (e) {}\n                          this.graphRunner.wasmModule.FS_createDataFile(\n                              '/',\n                              'model.dat',\n                              new Uint8Array(e),\n                              !0,\n                              !1,\n                              !1\n                          ),\n                              this.setExternalFile('/model.dat'),\n                              this.refreshGraph(),\n                              this.onGraphRefreshed();\n                      })\n                : (this.setExternalFile(s.modelAssetBuffer),\n                  this.refreshGraph(),\n                  this.onGraphRefreshed(),\n                  Promise.resolve())\n        );\n    }\n    onGraphRefreshed() {}\n    getCalculatorGraphConfig() {\n        let e;\n        if (\n            (this.graphRunner.getCalculatorGraphConfig((t) => {\n                e = calculator_pb_1.CalculatorGraphConfig.deserializeBinary(t);\n            }),\n            !e)\n        )\n            throw new Error('Failed to retrieve CalculatorGraphConfig');\n        return e;\n    }\n    setGraph(e, t) {\n        this.graphRunner.attachErrorListener((e, t) => {\n            this.processingErrors.push(new Error(t));\n        }),\n            this.graphRunner.registerModelResourcesGraphService(),\n            this.graphRunner.setGraph(e, t),\n            (this.keepaliveNode = void 0),\n            this.handleErrors();\n    }\n    finishProcessing() {\n        this.graphRunner.finishProcessing(), this.handleErrors();\n    }\n    setLatestOutputTimestamp(e) {\n        this.latestOutputTimestamp = Math.max(this.latestOutputTimestamp, e);\n    }\n    getSynctheticTimestamp() {\n        return this.latestOutputTimestamp + 1;\n    }\n    handleErrors() {\n        try {\n            const e = this.processingErrors.length;\n            if (1 === e) throw new Error(this.processingErrors[0].message);\n            if (e > 1)\n                throw new Error(\n                    'Encountered multiple errors: ' +\n                        this.processingErrors.map((e) => e.message).join(', ')\n                );\n        } finally {\n            this.processingErrors = [];\n        }\n    }\n    setExternalFile(e) {\n        const t = this.baseOptions.getModelAsset() || new external_file_pb_1.ExternalFile();\n        'string' == typeof e\n            ? (t.setFileName(e), t.clearFileContent())\n            : e instanceof Uint8Array && (t.setFileContent(e), t.clearFileName()),\n            this.baseOptions.setModelAsset(t);\n    }\n    setAcceleration(e) {\n        let t = this.baseOptions.getAcceleration();\n        t ||\n            ((t = new acceleration_pb_1.Acceleration()),\n            t.setTflite(\n                new inference_calculator_pb_1.InferenceCalculatorOptions.Delegate.TfLite()\n            )),\n            'delegate' in e &&\n                ('GPU' === e.delegate\n                    ? t.setGpu(\n                          new inference_calculator_pb_1.InferenceCalculatorOptions.Delegate.Gpu()\n                      )\n                    : t.setTflite(\n                          new inference_calculator_pb_1.InferenceCalculatorOptions.Delegate.TfLite()\n                      )),\n            this.baseOptions.setAcceleration(t);\n    }\n    addKeepaliveNode(e) {\n        (this.keepaliveNode = new calculator_pb_1.CalculatorGraphConfig.Node()),\n            this.keepaliveNode.setCalculator('PassThroughCalculator'),\n            this.keepaliveNode.addInputStream(FREE_MEMORY_STREAM),\n            this.keepaliveNode.addOutputStream(FREE_MEMORY_STREAM + UNUSED_STREAM_SUFFIX),\n            e.addInputStream(FREE_MEMORY_STREAM),\n            e.addNode(this.keepaliveNode);\n    }\n    keepStreamAlive(e) {\n        this.keepaliveNode.addInputStream(e),\n            this.keepaliveNode.addOutputStream(e + UNUSED_STREAM_SUFFIX);\n    }\n    freeKeepaliveStreams() {\n        this.graphRunner.addBoolToStream(!0, FREE_MEMORY_STREAM, this.latestOutputTimestamp);\n    }\n    close() {\n        (this.keepaliveNode = void 0), this.graphRunner.closeGraph();\n    }\n}\ntask_runner.TaskRunner = TaskRunner;\nvar graph_runner_image_lib = {};\nfunction SupportImage(e) {\n    return class extends e {\n        get wasmImageModule() {\n            return this.wasmModule;\n        }\n        addGpuBufferAsImageToStream(e, t, r) {\n            this.wrapStringPtr(t, (t) => {\n                const [o, i] = this.bindTextureToStream(e, t);\n                this.wasmImageModule._addBoundTextureAsImageToStream(t, o, i, r);\n            });\n        }\n        attachImageListener(e, t) {\n            this.setListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmImageModule._attachImageListener(e);\n                });\n        }\n        attachImageVectorListener(e, t) {\n            this.setVectorListener(e, t),\n                this.wrapStringPtr(e, (e) => {\n                    this.wasmImageModule._attachImageVectorListener(e);\n                });\n        }\n    };\n}\nObject.defineProperty(graph_runner_image_lib, '__esModule', { value: !0 }),\n    (graph_runner_image_lib.SupportImage = void 0),\n    (graph_runner_image_lib.SupportImage = SupportImage),\n    Object.defineProperty(vision_task_runner, '__esModule', { value: !0 }),\n    (vision_task_runner.VisionTaskRunner = vision_task_runner.VisionGraphRunner = void 0);\nconst rect_pb_1 = rect_pb,\n    task_runner_1 = task_runner,\n    image_1$1 = image,\n    image_shader_context_1 = image_shader_context,\n    mask_1$1 = mask,\n    graph_runner_1 = graph_runner,\n    graph_runner_image_lib_1 = graph_runner_image_lib,\n    platform_utils_1 = platform_utils,\n    register_model_resources_graph_service_1 = register_model_resources_graph_service,\n    GraphRunnerVisionType = (0,\n    register_model_resources_graph_service_1.SupportModelResourcesGraphService)(\n        (0, graph_runner_image_lib_1.SupportImage)(graph_runner_1.GraphRunner)\n    );\nclass VisionGraphRunner extends GraphRunnerVisionType {}\nfunction createCanvas() {\n    return 'undefined' != typeof OffscreenCanvas && !(0, platform_utils_1.isWebKit)()\n        ? void 0\n        : document.createElement('canvas');\n}\nvision_task_runner.VisionGraphRunner = VisionGraphRunner;\nclass VisionTaskRunner extends task_runner_1.TaskRunner {\n    static async createVisionInstance(e, t, r) {\n        var o;\n        const i = null !== (o = r.canvas) && void 0 !== o ? o : createCanvas();\n        return task_runner_1.TaskRunner.createInstance(e, i, t, r);\n    }\n    constructor(e, t, r, o) {\n        super(e),\n            (this.graphRunner = e),\n            (this.imageStreamName = t),\n            (this.normRectStreamName = r),\n            (this.roiAllowed = o),\n            (this.shaderContext = new image_shader_context_1.MPImageShaderContext());\n    }\n    applyOptions(e) {\n        if ('runningMode' in e) {\n            const t = !!e.runningMode && 'IMAGE' !== e.runningMode;\n            this.baseOptions.setUseStreamMode(t);\n        }\n        if (void 0 !== e.canvas && this.graphRunner.wasmModule.canvas !== e.canvas)\n            throw new Error('You must create a new task to reset the canvas.');\n        return super.applyOptions(e);\n    }\n    processImageData(e, t) {\n        var r;\n        if (null === (r = this.baseOptions) || void 0 === r ? void 0 : r.getUseStreamMode())\n            throw new Error(\n                \"Task is not initialized with image mode. 'runningMode' must be set to 'IMAGE'.\"\n            );\n        this.process(e, t, this.getSynctheticTimestamp());\n    }\n    processVideoData(e, t, r) {\n        var o;\n        if (!(null === (o = this.baseOptions) || void 0 === o ? void 0 : o.getUseStreamMode()))\n            throw new Error(\n                \"Task is not initialized with video mode. 'runningMode' must be set to 'VIDEO'.\"\n            );\n        this.process(e, t, r);\n    }\n    getImageSourceSize(e) {\n        return void 0 !== e.videoWidth\n            ? [e.videoWidth, e.videoHeight]\n            : void 0 !== e.naturalWidth\n            ? [e.naturalWidth, e.naturalHeight]\n            : [e.width, e.height];\n    }\n    convertToNormalizedRect(e, t) {\n        const r = new rect_pb_1.NormalizedRect();\n        if (null == t ? void 0 : t.regionOfInterest) {\n            if (!this.roiAllowed) throw new Error(\"This task doesn't support region-of-interest.\");\n            const e = t.regionOfInterest;\n            if (e.left >= e.right || e.top >= e.bottom)\n                throw new Error('Expected RectF with left < right and top < bottom.');\n            if (e.left < 0 || e.top < 0 || e.right > 1 || e.bottom > 1)\n                throw new Error('Expected RectF values to be in [0,1].');\n            r.setXCenter((e.left + e.right) / 2),\n                r.setYCenter((e.top + e.bottom) / 2),\n                r.setWidth(e.right - e.left),\n                r.setHeight(e.bottom - e.top);\n        } else r.setXCenter(0.5), r.setYCenter(0.5), r.setWidth(1), r.setHeight(1);\n        if (null == t ? void 0 : t.rotationDegrees) {\n            if ((null == t ? void 0 : t.rotationDegrees) % 90 != 0)\n                throw new Error('Expected rotation to be a multiple of 90°.');\n            if (\n                (r.setRotation((-Math.PI * t.rotationDegrees) / 180),\n                (null == t ? void 0 : t.rotationDegrees) % 180 != 0)\n            ) {\n                const [t, o] = this.getImageSourceSize(e),\n                    i = (r.getHeight() * o) / t,\n                    a = (r.getWidth() * t) / o;\n                r.setWidth(i), r.setHeight(a);\n            }\n        }\n        return r;\n    }\n    process(e, t, r) {\n        const o = this.convertToNormalizedRect(e, t);\n        this.graphRunner.addProtoToStream(\n            o.serializeBinary(),\n            'mediapipe.NormalizedRect',\n            this.normRectStreamName,\n            r\n        ),\n            this.graphRunner.addGpuBufferAsImageToStream(\n                e,\n                this.imageStreamName,\n                null != r ? r : performance.now()\n            ),\n            this.finishProcessing();\n    }\n    convertToMPImage(e, t) {\n        const { data: r, width: o, height: i } = e,\n            a = o * i;\n        let n;\n        if (r instanceof Uint8Array)\n            if (r.length === 3 * a) {\n                const e = new Uint8ClampedArray(4 * a);\n                for (let t = 0; t < a; ++t)\n                    (e[4 * t] = r[3 * t]),\n                        (e[4 * t + 1] = r[3 * t + 1]),\n                        (e[4 * t + 2] = r[3 * t + 2]),\n                        (e[4 * t + 3] = 255);\n                n = new ImageData(e, o, i);\n            } else {\n                if (r.length !== 4 * a)\n                    throw new Error('Unsupported channel count: ' + r.length / a);\n                n = new ImageData(new Uint8ClampedArray(r.buffer, r.byteOffset, r.length), o, i);\n            }\n        else {\n            if (!(r instanceof WebGLTexture))\n                throw new Error(`Unsupported format: ${r.constructor.name}`);\n            n = r;\n        }\n        const s = new image_1$1.MPImage(\n            [n],\n            !1,\n            !1,\n            this.graphRunner.wasmModule.canvas,\n            this.shaderContext,\n            o,\n            i\n        );\n        return t ? s.clone() : s;\n    }\n    convertToMPMask(e, t) {\n        const { data: r, width: o, height: i } = e,\n            a = o * i;\n        let n;\n        if (r instanceof Uint8Array || r instanceof Float32Array) {\n            if (r.length !== a) throw new Error('Unsupported channel count: ' + r.length / a);\n            n = r;\n        } else n = r;\n        const s = new mask_1$1.MPMask(\n            [n],\n            !1,\n            this.graphRunner.wasmModule.canvas,\n            this.shaderContext,\n            o,\n            i\n        );\n        return t ? s.clone() : s;\n    }\n    close() {\n        this.shaderContext.close(), super.close();\n    }\n}\nvision_task_runner.VisionTaskRunner = VisionTaskRunner;\nvar face_detector_options = {};\nObject.defineProperty(face_detector_options, '__esModule', { value: !0 });\nvar face_detector_result = {};\nObject.defineProperty(face_detector_result, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.FaceDetector = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = detection_pb,\n            n = base_options_pb,\n            s = face_detector_graph_options_pb,\n            p = detection_result,\n            d = vision_task_runner,\n            l = 'image_in',\n            g = 'norm_rect_in',\n            c = 'detections';\n        r(face_detector_options, e), r(face_detector_result, e);\n        class u extends d.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(u, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(u, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static async createFromModelPath(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(u, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new d.VisionGraphRunner(e, t), l, g, !1),\n                    (this.result = { detections: [] }),\n                    (this.options = new s.FaceDetectorGraphOptions()),\n                    this.options.setBaseOptions(new n.BaseOptions()),\n                    this.options.setMinDetectionConfidence(0.5),\n                    this.options.setMinSuppressionThreshold(0.3);\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                var t, r;\n                return (\n                    'minDetectionConfidence' in e &&\n                        this.options.setMinDetectionConfidence(\n                            null !== (t = e.minDetectionConfidence) && void 0 !== t ? t : 0.5\n                        ),\n                    'minSuppressionThreshold' in e &&\n                        this.options.setMinSuppressionThreshold(\n                            null !== (r = e.minSuppressionThreshold) && void 0 !== r ? r : 0.3\n                        ),\n                    this.applyOptions(e)\n                );\n            }\n            detect(e, t) {\n                return (this.result = { detections: [] }), this.processImageData(e, t), this.result;\n            }\n            detectForVideo(e, t, r) {\n                return (\n                    (this.result = { detections: [] }), this.processVideoData(e, r, t), this.result\n                );\n            }\n            addJsFaceDetections(e) {\n                for (const t of e) {\n                    const e = a.Detection.deserializeBinary(t);\n                    this.result.detections.push((0, p.convertFromDetectionProto)(e));\n                }\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(l), e.addInputStream(g), e.addOutputStream(c);\n                const t = new i.CalculatorOptions();\n                t.setExtension(s.FaceDetectorGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.face_detector.FaceDetectorGraph'),\n                    r.addInputStream('IMAGE:' + l),\n                    r.addInputStream('NORM_RECT:' + g),\n                    r.addOutputStream('DETECTIONS:' + c),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.graphRunner.attachProtoVectorListener(c, (e, t) => {\n                        this.addJsFaceDetections(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(c, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    });\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        e.FaceDetector = u;\n    })(face_detector);\nvar face_landmarker = {},\n    classification_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.Classification', null, o),\n        r.exportSymbol('proto.mediapipe.ClassificationList', null, o),\n        r.exportSymbol('proto.mediapipe.ClassificationListCollection', null, o),\n        (proto.mediapipe.Classification = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.Classification, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.Classification.displayName = 'proto.mediapipe.Classification'),\n        (proto.mediapipe.ClassificationList = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.ClassificationList.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.ClassificationList, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.ClassificationList.displayName = 'proto.mediapipe.ClassificationList'),\n        (proto.mediapipe.ClassificationListCollection = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.ClassificationListCollection.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.ClassificationListCollection, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.ClassificationListCollection.displayName =\n                'proto.mediapipe.ClassificationListCollection'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.Classification.prototype.toObject = function(e) {\n                return proto.mediapipe.Classification.toObject(e, this);\n            }),\n            (proto.mediapipe.Classification.toObject = function(e, r) {\n                var o,\n                    i = {\n                        index: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        score:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                ? void 0\n                                : o,\n                        label: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                        displayName: null == (o = t.Message.getField(r, 4)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.Classification.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.Classification();\n            return proto.mediapipe.Classification.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.Classification.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readInt32();\n                        e.setIndex(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setScore(r);\n                        break;\n                    case 3:\n                        r = t.readString();\n                        e.setLabel(r);\n                        break;\n                    case 4:\n                        r = t.readString();\n                        e.setDisplayName(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.Classification.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.Classification.serializeBinaryToWriter(this, e), e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.Classification.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeString(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeString(4, o);\n        }),\n        (proto.mediapipe.Classification.prototype.getIndex = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.Classification.prototype.setIndex = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.Classification.prototype.clearIndex = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.Classification.prototype.hasIndex = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.Classification.prototype.getScore = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.Classification.prototype.setScore = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.Classification.prototype.clearScore = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.Classification.prototype.hasScore = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.Classification.prototype.getLabel = function() {\n            return t.Message.getFieldWithDefault(this, 3, '');\n        }),\n        (proto.mediapipe.Classification.prototype.setLabel = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.Classification.prototype.clearLabel = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.Classification.prototype.hasLabel = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.Classification.prototype.getDisplayName = function() {\n            return t.Message.getFieldWithDefault(this, 4, '');\n        }),\n        (proto.mediapipe.Classification.prototype.setDisplayName = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.Classification.prototype.clearDisplayName = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.Classification.prototype.hasDisplayName = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.ClassificationList.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.ClassificationList.prototype.toObject = function(e) {\n                return proto.mediapipe.ClassificationList.toObject(e, this);\n            }),\n            (proto.mediapipe.ClassificationList.toObject = function(e, r) {\n                var o = {\n                    classificationList: t.Message.toObjectList(\n                        r.getClassificationList(),\n                        proto.mediapipe.Classification.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.ClassificationList.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.ClassificationList();\n            return proto.mediapipe.ClassificationList.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.ClassificationList.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.Classification();\n                    t.readMessage(r, proto.mediapipe.Classification.deserializeBinaryFromReader),\n                        e.addClassification(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.ClassificationList.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.ClassificationList.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.ClassificationList.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getClassificationList()).length > 0 &&\n                t.writeRepeatedMessage(\n                    1,\n                    r,\n                    proto.mediapipe.Classification.serializeBinaryToWriter\n                );\n        }),\n        (proto.mediapipe.ClassificationList.prototype.getClassificationList = function() {\n            return t.Message.getRepeatedWrapperField(this, proto.mediapipe.Classification, 1);\n        }),\n        (proto.mediapipe.ClassificationList.prototype.setClassificationList = function(e) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.ClassificationList.prototype.addClassification = function(e, r) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.Classification,\n                r\n            );\n        }),\n        (proto.mediapipe.ClassificationList.prototype.clearClassificationList = function() {\n            return this.setClassificationList([]);\n        }),\n        (proto.mediapipe.ClassificationListCollection.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.ClassificationListCollection.prototype.toObject = function(e) {\n                return proto.mediapipe.ClassificationListCollection.toObject(e, this);\n            }),\n            (proto.mediapipe.ClassificationListCollection.toObject = function(e, r) {\n                var o = {\n                    classificationListList: t.Message.toObjectList(\n                        r.getClassificationListList(),\n                        proto.mediapipe.ClassificationList.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.ClassificationListCollection.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.ClassificationListCollection();\n            return proto.mediapipe.ClassificationListCollection.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.ClassificationListCollection.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.ClassificationList();\n                    t.readMessage(\n                        r,\n                        proto.mediapipe.ClassificationList.deserializeBinaryFromReader\n                    ),\n                        e.addClassificationList(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.ClassificationListCollection.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.ClassificationListCollection.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.ClassificationListCollection.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getClassificationListList()).length > 0 &&\n                t.writeRepeatedMessage(\n                    1,\n                    r,\n                    proto.mediapipe.ClassificationList.serializeBinaryToWriter\n                );\n        }),\n        (proto.mediapipe.ClassificationListCollection.prototype.getClassificationListList = function() {\n            return t.Message.getRepeatedWrapperField(this, proto.mediapipe.ClassificationList, 1);\n        }),\n        (proto.mediapipe.ClassificationListCollection.prototype.setClassificationListList = function(\n            e\n        ) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.ClassificationListCollection.prototype.addClassificationList = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.ClassificationList,\n                r\n            );\n        }),\n        (proto.mediapipe.ClassificationListCollection.prototype.clearClassificationListList = function() {\n            return this.setClassificationListList([]);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(classification_pb);\nvar landmark_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.Landmark', null, o),\n        r.exportSymbol('proto.mediapipe.LandmarkList', null, o),\n        r.exportSymbol('proto.mediapipe.LandmarkListCollection', null, o),\n        r.exportSymbol('proto.mediapipe.NormalizedLandmark', null, o),\n        r.exportSymbol('proto.mediapipe.NormalizedLandmarkList', null, o),\n        r.exportSymbol('proto.mediapipe.NormalizedLandmarkListCollection', null, o),\n        (proto.mediapipe.Landmark = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.Landmark, t.Message),\n        r.DEBUG && !COMPILED && (proto.mediapipe.Landmark.displayName = 'proto.mediapipe.Landmark'),\n        (proto.mediapipe.LandmarkList = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.LandmarkList.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.LandmarkList, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.LandmarkList.displayName = 'proto.mediapipe.LandmarkList'),\n        (proto.mediapipe.LandmarkListCollection = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.LandmarkListCollection.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.LandmarkListCollection, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.LandmarkListCollection.displayName =\n                'proto.mediapipe.LandmarkListCollection'),\n        (proto.mediapipe.NormalizedLandmark = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.NormalizedLandmark, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.NormalizedLandmark.displayName = 'proto.mediapipe.NormalizedLandmark'),\n        (proto.mediapipe.NormalizedLandmarkList = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.NormalizedLandmarkList.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.NormalizedLandmarkList, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.NormalizedLandmarkList.displayName =\n                'proto.mediapipe.NormalizedLandmarkList'),\n        (proto.mediapipe.NormalizedLandmarkListCollection = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.NormalizedLandmarkListCollection.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.NormalizedLandmarkListCollection, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.NormalizedLandmarkListCollection.displayName =\n                'proto.mediapipe.NormalizedLandmarkListCollection'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.Landmark.prototype.toObject = function(e) {\n                return proto.mediapipe.Landmark.toObject(e, this);\n            }),\n            (proto.mediapipe.Landmark.toObject = function(e, r) {\n                var o,\n                    i = {\n                        x: null == (o = t.Message.getOptionalFloatingPointField(r, 1)) ? void 0 : o,\n                        y: null == (o = t.Message.getOptionalFloatingPointField(r, 2)) ? void 0 : o,\n                        z: null == (o = t.Message.getOptionalFloatingPointField(r, 3)) ? void 0 : o,\n                        visibility:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                ? void 0\n                                : o,\n                        presence:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 5))\n                                ? void 0\n                                : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.Landmark.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.Landmark();\n            return proto.mediapipe.Landmark.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.Landmark.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readFloat();\n                        e.setX(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setY(r);\n                        break;\n                    case 3:\n                        r = t.readFloat();\n                        e.setZ(r);\n                        break;\n                    case 4:\n                        r = t.readFloat();\n                        e.setVisibility(r);\n                        break;\n                    case 5:\n                        r = t.readFloat();\n                        e.setPresence(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.Landmark.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return proto.mediapipe.Landmark.serializeBinaryToWriter(this, e), e.getResultBuffer();\n        }),\n        (proto.mediapipe.Landmark.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeFloat(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeFloat(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeFloat(5, o);\n        }),\n        (proto.mediapipe.Landmark.prototype.getX = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.setX = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.Landmark.prototype.clearX = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.hasX = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.Landmark.prototype.getY = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.setY = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.Landmark.prototype.clearY = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.hasY = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.Landmark.prototype.getZ = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.setZ = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.Landmark.prototype.clearZ = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.hasZ = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.Landmark.prototype.getVisibility = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.setVisibility = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.Landmark.prototype.clearVisibility = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.hasVisibility = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.Landmark.prototype.getPresence = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 5, 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.setPresence = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.Landmark.prototype.clearPresence = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.Landmark.prototype.hasPresence = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.LandmarkList.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.LandmarkList.prototype.toObject = function(e) {\n                return proto.mediapipe.LandmarkList.toObject(e, this);\n            }),\n            (proto.mediapipe.LandmarkList.toObject = function(e, r) {\n                var o = {\n                    landmarkList: t.Message.toObjectList(\n                        r.getLandmarkList(),\n                        proto.mediapipe.Landmark.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.LandmarkList.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.LandmarkList();\n            return proto.mediapipe.LandmarkList.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.LandmarkList.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.Landmark();\n                    t.readMessage(r, proto.mediapipe.Landmark.deserializeBinaryFromReader),\n                        e.addLandmark(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.LandmarkList.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.LandmarkList.serializeBinaryToWriter(this, e), e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.LandmarkList.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getLandmarkList()).length > 0 &&\n                t.writeRepeatedMessage(1, r, proto.mediapipe.Landmark.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.LandmarkList.prototype.getLandmarkList = function() {\n            return t.Message.getRepeatedWrapperField(this, proto.mediapipe.Landmark, 1);\n        }),\n        (proto.mediapipe.LandmarkList.prototype.setLandmarkList = function(e) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.LandmarkList.prototype.addLandmark = function(e, r) {\n            return t.Message.addToRepeatedWrapperField(this, 1, e, proto.mediapipe.Landmark, r);\n        }),\n        (proto.mediapipe.LandmarkList.prototype.clearLandmarkList = function() {\n            return this.setLandmarkList([]);\n        }),\n        (proto.mediapipe.LandmarkListCollection.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.LandmarkListCollection.prototype.toObject = function(e) {\n                return proto.mediapipe.LandmarkListCollection.toObject(e, this);\n            }),\n            (proto.mediapipe.LandmarkListCollection.toObject = function(e, r) {\n                var o = {\n                    landmarkListList: t.Message.toObjectList(\n                        r.getLandmarkListList(),\n                        proto.mediapipe.LandmarkList.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.LandmarkListCollection.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.LandmarkListCollection();\n            return proto.mediapipe.LandmarkListCollection.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.LandmarkListCollection.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.LandmarkList();\n                    t.readMessage(r, proto.mediapipe.LandmarkList.deserializeBinaryFromReader),\n                        e.addLandmarkList(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.LandmarkListCollection.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.LandmarkListCollection.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.LandmarkListCollection.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getLandmarkListList()).length > 0 &&\n                t.writeRepeatedMessage(1, r, proto.mediapipe.LandmarkList.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.LandmarkListCollection.prototype.getLandmarkListList = function() {\n            return t.Message.getRepeatedWrapperField(this, proto.mediapipe.LandmarkList, 1);\n        }),\n        (proto.mediapipe.LandmarkListCollection.prototype.setLandmarkListList = function(e) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.LandmarkListCollection.prototype.addLandmarkList = function(e, r) {\n            return t.Message.addToRepeatedWrapperField(this, 1, e, proto.mediapipe.LandmarkList, r);\n        }),\n        (proto.mediapipe.LandmarkListCollection.prototype.clearLandmarkListList = function() {\n            return this.setLandmarkListList([]);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.NormalizedLandmark.prototype.toObject = function(e) {\n                return proto.mediapipe.NormalizedLandmark.toObject(e, this);\n            }),\n            (proto.mediapipe.NormalizedLandmark.toObject = function(e, r) {\n                var o,\n                    i = {\n                        x: null == (o = t.Message.getOptionalFloatingPointField(r, 1)) ? void 0 : o,\n                        y: null == (o = t.Message.getOptionalFloatingPointField(r, 2)) ? void 0 : o,\n                        z: null == (o = t.Message.getOptionalFloatingPointField(r, 3)) ? void 0 : o,\n                        visibility:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                ? void 0\n                                : o,\n                        presence:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 5))\n                                ? void 0\n                                : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.NormalizedLandmark.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.NormalizedLandmark();\n            return proto.mediapipe.NormalizedLandmark.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.NormalizedLandmark.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readFloat();\n                        e.setX(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setY(r);\n                        break;\n                    case 3:\n                        r = t.readFloat();\n                        e.setZ(r);\n                        break;\n                    case 4:\n                        r = t.readFloat();\n                        e.setVisibility(r);\n                        break;\n                    case 5:\n                        r = t.readFloat();\n                        e.setPresence(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.NormalizedLandmark.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.NormalizedLandmark.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeFloat(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeFloat(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeFloat(5, o);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.getX = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.setX = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.clearX = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.hasX = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.getY = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.setY = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.clearY = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.hasY = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.getZ = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.setZ = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.clearZ = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.hasZ = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.getVisibility = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.setVisibility = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.clearVisibility = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.hasVisibility = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.getPresence = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 5, 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.setPresence = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.clearPresence = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.NormalizedLandmark.prototype.hasPresence = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.NormalizedLandmarkList.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.NormalizedLandmarkList.prototype.toObject = function(e) {\n                return proto.mediapipe.NormalizedLandmarkList.toObject(e, this);\n            }),\n            (proto.mediapipe.NormalizedLandmarkList.toObject = function(e, r) {\n                var o = {\n                    landmarkList: t.Message.toObjectList(\n                        r.getLandmarkList(),\n                        proto.mediapipe.NormalizedLandmark.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.NormalizedLandmarkList.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.NormalizedLandmarkList();\n            return proto.mediapipe.NormalizedLandmarkList.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.NormalizedLandmarkList.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.NormalizedLandmark();\n                    t.readMessage(\n                        r,\n                        proto.mediapipe.NormalizedLandmark.deserializeBinaryFromReader\n                    ),\n                        e.addLandmark(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.NormalizedLandmarkList.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.NormalizedLandmarkList.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.NormalizedLandmarkList.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getLandmarkList()).length > 0 &&\n                t.writeRepeatedMessage(\n                    1,\n                    r,\n                    proto.mediapipe.NormalizedLandmark.serializeBinaryToWriter\n                );\n        }),\n        (proto.mediapipe.NormalizedLandmarkList.prototype.getLandmarkList = function() {\n            return t.Message.getRepeatedWrapperField(this, proto.mediapipe.NormalizedLandmark, 1);\n        }),\n        (proto.mediapipe.NormalizedLandmarkList.prototype.setLandmarkList = function(e) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.NormalizedLandmarkList.prototype.addLandmark = function(e, r) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.NormalizedLandmark,\n                r\n            );\n        }),\n        (proto.mediapipe.NormalizedLandmarkList.prototype.clearLandmarkList = function() {\n            return this.setLandmarkList([]);\n        }),\n        (proto.mediapipe.NormalizedLandmarkListCollection.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.NormalizedLandmarkListCollection.prototype.toObject = function(e) {\n                return proto.mediapipe.NormalizedLandmarkListCollection.toObject(e, this);\n            }),\n            (proto.mediapipe.NormalizedLandmarkListCollection.toObject = function(e, r) {\n                var o = {\n                    landmarkListList: t.Message.toObjectList(\n                        r.getLandmarkListList(),\n                        proto.mediapipe.NormalizedLandmarkList.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.NormalizedLandmarkListCollection.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.NormalizedLandmarkListCollection();\n            return proto.mediapipe.NormalizedLandmarkListCollection.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.NormalizedLandmarkListCollection.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.NormalizedLandmarkList();\n                    t.readMessage(\n                        r,\n                        proto.mediapipe.NormalizedLandmarkList.deserializeBinaryFromReader\n                    ),\n                        e.addLandmarkList(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.NormalizedLandmarkListCollection.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.NormalizedLandmarkListCollection.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.NormalizedLandmarkListCollection.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getLandmarkListList()).length > 0 &&\n                t.writeRepeatedMessage(\n                    1,\n                    r,\n                    proto.mediapipe.NormalizedLandmarkList.serializeBinaryToWriter\n                );\n        }),\n        (proto.mediapipe.NormalizedLandmarkListCollection.prototype.getLandmarkListList = function() {\n            return t.Message.getRepeatedWrapperField(\n                this,\n                proto.mediapipe.NormalizedLandmarkList,\n                1\n            );\n        }),\n        (proto.mediapipe.NormalizedLandmarkListCollection.prototype.setLandmarkListList = function(\n            e\n        ) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.NormalizedLandmarkListCollection.prototype.addLandmarkList = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.NormalizedLandmarkList,\n                r\n            );\n        }),\n        (proto.mediapipe.NormalizedLandmarkListCollection.prototype.clearLandmarkListList = function() {\n            return this.setLandmarkListList([]);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(landmark_pb);\nvar face_geometry_pb = {},\n    matrix_data_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.MatrixData', null, o),\n        r.exportSymbol('proto.mediapipe.MatrixData.Layout', null, o),\n        (proto.mediapipe.MatrixData = function(e) {\n            t.Message.initialize(this, e, 0, -1, proto.mediapipe.MatrixData.repeatedFields_, null);\n        }),\n        r.inherits(proto.mediapipe.MatrixData, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.MatrixData.displayName = 'proto.mediapipe.MatrixData'),\n        (proto.mediapipe.MatrixData.repeatedFields_ = [3]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.MatrixData.prototype.toObject = function(e) {\n                return proto.mediapipe.MatrixData.toObject(e, this);\n            }),\n            (proto.mediapipe.MatrixData.toObject = function(e, r) {\n                var o,\n                    i = {\n                        rows: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        cols: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        packedDataList:\n                            null == (o = t.Message.getRepeatedFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        layout: t.Message.getFieldWithDefault(r, 4, 0),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.MatrixData.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.MatrixData();\n            return proto.mediapipe.MatrixData.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.MatrixData.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readInt32();\n                        e.setRows(r);\n                        break;\n                    case 2:\n                        r = t.readInt32();\n                        e.setCols(r);\n                        break;\n                    case 3:\n                        for (\n                            var o = t.isDelimited() ? t.readPackedFloat() : [t.readFloat()], i = 0;\n                            i < o.length;\n                            i++\n                        )\n                            e.addPackedData(o[i]);\n                        break;\n                    case 4:\n                        r = t.readEnum();\n                        e.setLayout(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.MatrixData.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return proto.mediapipe.MatrixData.serializeBinaryToWriter(this, e), e.getResultBuffer();\n        }),\n        (proto.mediapipe.MatrixData.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                (o = e.getPackedDataList()).length > 0 && r.writePackedFloat(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeEnum(4, o);\n        }),\n        (proto.mediapipe.MatrixData.Layout = { COLUMN_MAJOR: 0, ROW_MAJOR: 1 }),\n        (proto.mediapipe.MatrixData.prototype.getRows = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.MatrixData.prototype.setRows = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.MatrixData.prototype.clearRows = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.MatrixData.prototype.hasRows = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.MatrixData.prototype.getCols = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.MatrixData.prototype.setCols = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.MatrixData.prototype.clearCols = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.MatrixData.prototype.hasCols = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.MatrixData.prototype.getPackedDataList = function() {\n            return t.Message.getRepeatedFloatingPointField(this, 3);\n        }),\n        (proto.mediapipe.MatrixData.prototype.setPackedDataList = function(e) {\n            return t.Message.setField(this, 3, e || []);\n        }),\n        (proto.mediapipe.MatrixData.prototype.addPackedData = function(e, r) {\n            return t.Message.addToRepeatedField(this, 3, e, r);\n        }),\n        (proto.mediapipe.MatrixData.prototype.clearPackedDataList = function() {\n            return this.setPackedDataList([]);\n        }),\n        (proto.mediapipe.MatrixData.prototype.getLayout = function() {\n            return t.Message.getFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.MatrixData.prototype.setLayout = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.MatrixData.prototype.clearLayout = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.MatrixData.prototype.hasLayout = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(matrix_data_pb);\nvar mesh_3d_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d', null, o),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.PrimitiveType',\n            null,\n            o\n        ),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.VertexType',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.displayName =\n                'proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d'),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.repeatedFields_ = [3, 4]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.toObject(e, this);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.toObject = function(e, r) {\n                var o,\n                    i = {\n                        vertexType: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        primitiveType: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        vertexBufferList:\n                            null == (o = t.Message.getRepeatedFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        indexBufferList:\n                            null == (o = t.Message.getRepeatedField(r, 4)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d();\n            return proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readEnum();\n                        e.setVertexType(r);\n                        break;\n                    case 2:\n                        r = t.readEnum();\n                        e.setPrimitiveType(r);\n                        break;\n                    case 3:\n                        for (\n                            var o = t.isDelimited() ? t.readPackedFloat() : [t.readFloat()], i = 0;\n                            i < o.length;\n                            i++\n                        )\n                            e.addVertexBuffer(o[i]);\n                        break;\n                    case 4:\n                        for (\n                            o = t.isDelimited() ? t.readPackedUint32() : [t.readUint32()], i = 0;\n                            i < o.length;\n                            i++\n                        )\n                            e.addIndexBuffer(o[i]);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeEnum(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeEnum(2, o),\n                (o = e.getVertexBufferList()).length > 0 && r.writeRepeatedFloat(3, o),\n                (o = e.getIndexBufferList()).length > 0 && r.writeRepeatedUint32(4, o);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.VertexType = { VERTEX_PT: 0 }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.PrimitiveType = { TRIANGLE: 0 }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.getVertexType = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.setVertexType = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.clearVertexType = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.hasVertexType = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.getPrimitiveType = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.setPrimitiveType = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.clearPrimitiveType = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.hasPrimitiveType = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.getVertexBufferList = function() {\n            return t.Message.getRepeatedFloatingPointField(this, 3);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.setVertexBufferList = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e || []);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.addVertexBuffer = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedField(this, 3, e, r);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.clearVertexBufferList = function() {\n            return this.setVertexBufferList([]);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.getIndexBufferList = function() {\n            return t.Message.getRepeatedField(this, 4);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.setIndexBufferList = function(\n            e\n        ) {\n            return t.Message.setField(this, 4, e || []);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.addIndexBuffer = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedField(this, 4, e, r);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.proto.Mesh3d.prototype.clearIndexBufferList = function() {\n            return this.setIndexBufferList([]);\n        }),\n        r.object.extend(e, proto.mediapipe.tasks.vision.face_geometry.proto);\n})(mesh_3d_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = matrix_data_pb;\n        r.object.extend(proto, i);\n        var a = mesh_3d_pb;\n        r.object.extend(proto, a),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.displayName =\n                    'proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.toObject = function(\n                    e,\n                    t\n                ) {\n                    var r,\n                        o = {\n                            mesh: (r = t.getMesh()) && a.Mesh3d.toObject(e, r),\n                            poseTransformMatrix:\n                                (r = t.getPoseTransformMatrix()) && i.MatrixData.toObject(e, r),\n                        };\n                    return e && (o.$jspbMessageInstance = t), o;\n                })),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry();\n                return proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new a.Mesh3d();\n                            t.readMessage(r, a.Mesh3d.deserializeBinaryFromReader), e.setMesh(r);\n                            break;\n                        case 2:\n                            r = new i.MatrixData();\n                            t.readMessage(r, i.MatrixData.deserializeBinaryFromReader),\n                                e.setPoseTransformMatrix(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.serializeBinaryToWriter = function(\n                e,\n                t\n            ) {\n                var r = void 0;\n                null != (r = e.getMesh()) && t.writeMessage(1, r, a.Mesh3d.serializeBinaryToWriter),\n                    null != (r = e.getPoseTransformMatrix()) &&\n                        t.writeMessage(2, r, i.MatrixData.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.getMesh = function() {\n                return t.Message.getWrapperField(this, a.Mesh3d, 1);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.setMesh = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.clearMesh = function() {\n                return this.setMesh(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.hasMesh = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.getPoseTransformMatrix = function() {\n                return t.Message.getWrapperField(this, i.MatrixData, 2);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.setPoseTransformMatrix = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.clearPoseTransformMatrix = function() {\n                return this.setPoseTransformMatrix(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometry.prototype.hasPoseTransformMatrix = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            r.object.extend(e, proto.mediapipe.tasks.vision.face_geometry.proto);\n    })(face_geometry_pb);\nvar face_landmarker_graph_options_pb = {},\n    face_geometry_graph_options_pb = {},\n    geometry_pipeline_calculator_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_options_pb;\n    r.object.extend(proto, i);\n    var a = external_file_pb;\n    r.object.extend(proto, a),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions = function(\n            e\n        ) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.displayName =\n                'proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.toObject = function(\n                e,\n                t\n            ) {\n                var r,\n                    o = {\n                        metadataFile: (r = t.getMetadataFile()) && a.ExternalFile.toObject(e, r),\n                    };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions();\n            return proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new a.ExternalFile();\n                    t.readMessage(r, a.ExternalFile.deserializeBinaryFromReader),\n                        e.setMetadataFile(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.serializeBinaryToWriter = function(\n            e,\n            t\n        ) {\n            var r;\n            null != (r = e.getMetadataFile()) &&\n                t.writeMessage(1, r, a.ExternalFile.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.ext = new t.ExtensionFieldInfo(\n            512499200,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions,\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.toObject,\n            0\n        )),\n        (i.CalculatorOptions.extensionsBinary[512499200] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (i.CalculatorOptions.extensions[512499200] =\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.ext),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.prototype.getMetadataFile = function() {\n            return t.Message.getWrapperField(this, a.ExternalFile, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.prototype.setMetadataFile = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.prototype.clearMetadataFile = function() {\n            return this.setMetadataFile(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.prototype.hasMetadataFile = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.ext = new t.ExtensionFieldInfo(\n            512499200,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions,\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.toObject,\n            0\n        )),\n        (i.CalculatorOptions.extensionsBinary[512499200] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (i.CalculatorOptions.extensions[512499200] =\n            proto.mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculatorOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.face_geometry);\n})(geometry_pipeline_calculator_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_options_pb;\n        r.object.extend(proto, i);\n        var a = geometry_pipeline_calculator_pb;\n        r.object.extend(proto, a),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.toObject = function(\n                    e,\n                    t\n                ) {\n                    var r,\n                        o = {\n                            geometryPipelineOptions:\n                                (r = t.getGeometryPipelineOptions()) &&\n                                a.FaceGeometryPipelineCalculatorOptions.toObject(e, r),\n                        };\n                    return e && (o.$jspbMessageInstance = t), o;\n                })),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions();\n                return proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    if (1 === t.getFieldNumber()) {\n                        var r = new a.FaceGeometryPipelineCalculatorOptions();\n                        t.readMessage(\n                            r,\n                            a.FaceGeometryPipelineCalculatorOptions.deserializeBinaryFromReader\n                        ),\n                            e.setGeometryPipelineOptions(r);\n                    } else t.skipField();\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.serializeBinaryToWriter = function(\n                e,\n                t\n            ) {\n                var r;\n                null != (r = e.getGeometryPipelineOptions()) &&\n                    t.writeMessage(\n                        1,\n                        r,\n                        a.FaceGeometryPipelineCalculatorOptions.serializeBinaryToWriter\n                    );\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.ext = new t.ExtensionFieldInfo(\n                515723506,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions,\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.toObject,\n                0\n            )),\n            (i.CalculatorOptions.extensionsBinary[515723506] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (i.CalculatorOptions.extensions[515723506] =\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.prototype.getGeometryPipelineOptions = function() {\n                return t.Message.getWrapperField(this, a.FaceGeometryPipelineCalculatorOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.prototype.setGeometryPipelineOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.prototype.clearGeometryPipelineOptions = function() {\n                return this.setGeometryPipelineOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.prototype.hasGeometryPipelineOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.ext = new t.ExtensionFieldInfo(\n                515723506,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions,\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.toObject,\n                0\n            )),\n            (i.CalculatorOptions.extensionsBinary[515723506] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (i.CalculatorOptions.extensions[515723506] =\n                proto.mediapipe.tasks.vision.face_geometry.proto.FaceGeometryGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.face_geometry.proto);\n    })(face_geometry_graph_options_pb);\nvar face_landmarks_detector_graph_options_pb = {},\n    face_blendshapes_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions = function(\n            e\n        ) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.toObject = function(\n                e,\n                t\n            ) {\n                var r,\n                    o = { baseOptions: (r = t.getBaseOptions()) && n.BaseOptions.toObject(e, r) };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions();\n            return proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new n.BaseOptions();\n                    t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                        e.setBaseOptions(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.serializeBinaryToWriter = function(\n            e,\n            t\n        ) {\n            var r;\n            null != (r = e.getBaseOptions()) &&\n                t.writeMessage(1, r, n.BaseOptions.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.ext = new t.ExtensionFieldInfo(\n            508981768,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions,\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[508981768] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[508981768] =\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.ext = new t.ExtensionFieldInfo(\n            508981768,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions,\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[508981768] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[508981768] =\n            proto.mediapipe.tasks.vision.face_landmarker.proto.FaceBlendshapesGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.face_landmarker.proto);\n})(face_blendshapes_graph_options_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_pb;\n        r.object.extend(proto, i);\n        var a = calculator_options_pb;\n        r.object.extend(proto, a);\n        var n = base_options_pb;\n        r.object.extend(proto, n);\n        var s = face_blendshapes_graph_options_pb;\n        r.object.extend(proto, s),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.face_landmarker.proto\n                    .FaceLandmarksDetectorGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.toObject = function(\n                    e,\n                    r\n                ) {\n                    var o,\n                        i = {\n                            baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                            minDetectionConfidence: t.Message.getFloatingPointFieldWithDefault(\n                                r,\n                                2,\n                                0.5\n                            ),\n                            smoothLandmarks:\n                                null == (o = t.Message.getBooleanField(r, 4)) ? void 0 : o,\n                            faceBlendshapesGraphOptions:\n                                (o = r.getFaceBlendshapesGraphOptions()) &&\n                                s.FaceBlendshapesGraphOptions.toObject(e, o),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions();\n                return proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new n.BaseOptions();\n                            t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                                e.setBaseOptions(r);\n                            break;\n                        case 2:\n                            r = t.readFloat();\n                            e.setMinDetectionConfidence(r);\n                            break;\n                        case 4:\n                            r = t.readBool();\n                            e.setSmoothLandmarks(r);\n                            break;\n                        case 3:\n                            r = new s.FaceBlendshapesGraphOptions();\n                            t.readMessage(\n                                r,\n                                s.FaceBlendshapesGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setFaceBlendshapesGraphOptions(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.serializeBinaryToWriter = function(\n                e,\n                r\n            ) {\n                var o = void 0;\n                null != (o = e.getBaseOptions()) &&\n                    r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                    null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                    null != (o = t.Message.getField(e, 4)) && r.writeBool(4, o),\n                    null != (o = e.getFaceBlendshapesGraphOptions()) &&\n                        r.writeMessage(3, o, s.FaceBlendshapesGraphOptions.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n                508968149,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[508968149] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[508968149] =\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.getBaseOptions = function() {\n                return t.Message.getWrapperField(this, n.BaseOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.setBaseOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.clearBaseOptions = function() {\n                return this.setBaseOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.hasBaseOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.getMinDetectionConfidence = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 2, 0.5);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.setMinDetectionConfidence = function(\n                e\n            ) {\n                return t.Message.setField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.clearMinDetectionConfidence = function() {\n                return t.Message.setField(this, 2, void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.hasMinDetectionConfidence = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.getSmoothLandmarks = function() {\n                return t.Message.getBooleanFieldWithDefault(this, 4, !1);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.setSmoothLandmarks = function(\n                e\n            ) {\n                return t.Message.setField(this, 4, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.clearSmoothLandmarks = function() {\n                return t.Message.setField(this, 4, void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.hasSmoothLandmarks = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.getFaceBlendshapesGraphOptions = function() {\n                return t.Message.getWrapperField(this, s.FaceBlendshapesGraphOptions, 3);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.setFaceBlendshapesGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.clearFaceBlendshapesGraphOptions = function() {\n                return this.setFaceBlendshapesGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.prototype.hasFaceBlendshapesGraphOptions = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n                508968149,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[508968149] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[508968149] =\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarksDetectorGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.face_landmarker.proto);\n    })(face_landmarks_detector_graph_options_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_pb;\n        r.object.extend(proto, i);\n        var a = calculator_options_pb;\n        r.object.extend(proto, a);\n        var n = base_options_pb;\n        r.object.extend(proto, n);\n        var s = face_detector_graph_options_pb;\n        r.object.extend(proto, s);\n        var p = face_geometry_graph_options_pb;\n        r.object.extend(proto, p);\n        var d = face_landmarks_detector_graph_options_pb;\n        r.object.extend(proto, d),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.toObject = function(\n                    e,\n                    r\n                ) {\n                    var o,\n                        i = {\n                            baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                            faceDetectorGraphOptions:\n                                (o = r.getFaceDetectorGraphOptions()) &&\n                                s.FaceDetectorGraphOptions.toObject(e, o),\n                            faceLandmarksDetectorGraphOptions:\n                                (o = r.getFaceLandmarksDetectorGraphOptions()) &&\n                                d.FaceLandmarksDetectorGraphOptions.toObject(e, o),\n                            minTrackingConfidence: t.Message.getFloatingPointFieldWithDefault(\n                                r,\n                                4,\n                                0.5\n                            ),\n                            faceGeometryGraphOptions:\n                                (o = r.getFaceGeometryGraphOptions()) &&\n                                p.FaceGeometryGraphOptions.toObject(e, o),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions();\n                return proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new n.BaseOptions();\n                            t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                                e.setBaseOptions(r);\n                            break;\n                        case 2:\n                            r = new s.FaceDetectorGraphOptions();\n                            t.readMessage(\n                                r,\n                                s.FaceDetectorGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setFaceDetectorGraphOptions(r);\n                            break;\n                        case 3:\n                            r = new d.FaceLandmarksDetectorGraphOptions();\n                            t.readMessage(\n                                r,\n                                d.FaceLandmarksDetectorGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setFaceLandmarksDetectorGraphOptions(r);\n                            break;\n                        case 4:\n                            r = t.readFloat();\n                            e.setMinTrackingConfidence(r);\n                            break;\n                        case 5:\n                            r = new p.FaceGeometryGraphOptions();\n                            t.readMessage(\n                                r,\n                                p.FaceGeometryGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setFaceGeometryGraphOptions(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.serializeBinaryToWriter = function(\n                e,\n                r\n            ) {\n                var o = void 0;\n                null != (o = e.getBaseOptions()) &&\n                    r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                    null != (o = e.getFaceDetectorGraphOptions()) &&\n                        r.writeMessage(2, o, s.FaceDetectorGraphOptions.serializeBinaryToWriter),\n                    null != (o = e.getFaceLandmarksDetectorGraphOptions()) &&\n                        r.writeMessage(\n                            3,\n                            o,\n                            d.FaceLandmarksDetectorGraphOptions.serializeBinaryToWriter\n                        ),\n                    null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o),\n                    null != (o = e.getFaceGeometryGraphOptions()) &&\n                        r.writeMessage(5, o, p.FaceGeometryGraphOptions.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.ext = new t.ExtensionFieldInfo(\n                508968150,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[508968150] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[508968150] =\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.getBaseOptions = function() {\n                return t.Message.getWrapperField(this, n.BaseOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.setBaseOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.clearBaseOptions = function() {\n                return this.setBaseOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.hasBaseOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.getFaceDetectorGraphOptions = function() {\n                return t.Message.getWrapperField(this, s.FaceDetectorGraphOptions, 2);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.setFaceDetectorGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.clearFaceDetectorGraphOptions = function() {\n                return this.setFaceDetectorGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.hasFaceDetectorGraphOptions = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.getFaceLandmarksDetectorGraphOptions = function() {\n                return t.Message.getWrapperField(this, d.FaceLandmarksDetectorGraphOptions, 3);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.setFaceLandmarksDetectorGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.clearFaceLandmarksDetectorGraphOptions = function() {\n                return this.setFaceLandmarksDetectorGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.hasFaceLandmarksDetectorGraphOptions = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.getMinTrackingConfidence = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 4, 0.5);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.setMinTrackingConfidence = function(\n                e\n            ) {\n                return t.Message.setField(this, 4, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.clearMinTrackingConfidence = function() {\n                return t.Message.setField(this, 4, void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.hasMinTrackingConfidence = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.getFaceGeometryGraphOptions = function() {\n                return t.Message.getWrapperField(this, p.FaceGeometryGraphOptions, 5);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.setFaceGeometryGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 5, e);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.clearFaceGeometryGraphOptions = function() {\n                return this.setFaceGeometryGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.prototype.hasFaceGeometryGraphOptions = function() {\n                return null != t.Message.getField(this, 5);\n            }),\n            (proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.ext = new t.ExtensionFieldInfo(\n                508968150,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[508968150] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[508968150] =\n                proto.mediapipe.tasks.vision.face_landmarker.proto.FaceLandmarkerGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.face_landmarker.proto);\n    })(face_landmarker_graph_options_pb);\nvar classifier_result = {};\nObject.defineProperty(classifier_result, '__esModule', { value: !0 }),\n    (classifier_result.convertFromClassificationResultProto = classifier_result.convertFromClassifications = void 0);\nconst DEFAULT_INDEX$1 = -1,\n    DEFAULT_SCORE = 0;\nfunction convertFromClassifications(e, t = DEFAULT_INDEX$1, r = '') {\n    return {\n        categories: e.map((e) => {\n            var t, r, o, i;\n            return {\n                index: null !== (t = e.getIndex()) && void 0 !== t ? t : DEFAULT_INDEX$1,\n                score: null !== (r = e.getScore()) && void 0 !== r ? r : DEFAULT_SCORE,\n                categoryName: null !== (o = e.getLabel()) && void 0 !== o ? o : '',\n                displayName: null !== (i = e.getDisplayName()) && void 0 !== i ? i : '',\n            };\n        }),\n        headIndex: t,\n        headName: r,\n    };\n}\nfunction convertFromClassificationsProto(e) {\n    var t, r;\n    return convertFromClassifications(\n        null !==\n            (r =\n                null === (t = e.getClassificationList()) || void 0 === t\n                    ? void 0\n                    : t.getClassificationList()) && void 0 !== r\n            ? r\n            : [],\n        e.getHeadIndex(),\n        e.getHeadName()\n    );\n}\nfunction convertFromClassificationResultProto(e) {\n    const t = {\n        classifications: e.getClassificationsList().map((e) => convertFromClassificationsProto(e)),\n    };\n    return e.hasTimestampMs() && (t.timestampMs = e.getTimestampMs()), t;\n}\n(classifier_result.convertFromClassifications = convertFromClassifications),\n    (classifier_result.convertFromClassificationResultProto = convertFromClassificationResultProto);\nvar landmark_result = {};\nfunction convertToLandmarks(e) {\n    var t, r, o;\n    const i = [];\n    for (const a of e.getLandmarkList())\n        i.push({\n            x: null !== (t = a.getX()) && void 0 !== t ? t : 0,\n            y: null !== (r = a.getY()) && void 0 !== r ? r : 0,\n            z: null !== (o = a.getZ()) && void 0 !== o ? o : 0,\n        });\n    return i;\n}\nfunction convertToWorldLandmarks(e) {\n    var t, r, o;\n    const i = [];\n    for (const a of e.getLandmarkList())\n        i.push({\n            x: null !== (t = a.getX()) && void 0 !== t ? t : 0,\n            y: null !== (r = a.getY()) && void 0 !== r ? r : 0,\n            z: null !== (o = a.getZ()) && void 0 !== o ? o : 0,\n        });\n    return i;\n}\nObject.defineProperty(landmark_result, '__esModule', { value: !0 }),\n    (landmark_result.convertToWorldLandmarks = landmark_result.convertToLandmarks = void 0),\n    (landmark_result.convertToLandmarks = convertToLandmarks),\n    (landmark_result.convertToWorldLandmarks = convertToWorldLandmarks);\nvar face_landmarks_connections = {},\n    exports;\n(exports = face_landmarks_connections),\n    Object.defineProperty(exports, '__esModule', { value: !0 }),\n    (exports.FACE_LANDMARKS_TESSELATION = exports.FACE_LANDMARKS_CONTOURS = exports.FACE_LANDMARKS_FACE_OVAL = exports.FACE_LANDMARKS_RIGHT_IRIS = exports.FACE_LANDMARKS_RIGHT_EYEBROW = exports.FACE_LANDMARKS_RIGHT_EYE = exports.FACE_LANDMARKS_LEFT_IRIS = exports.FACE_LANDMARKS_LEFT_EYEBROW = exports.FACE_LANDMARKS_LEFT_EYE = exports.FACE_LANDMARKS_LIPS = void 0),\n    (exports.FACE_LANDMARKS_LIPS = [\n        { start: 61, end: 146 },\n        { start: 146, end: 91 },\n        { start: 91, end: 181 },\n        { start: 181, end: 84 },\n        { start: 84, end: 17 },\n        { start: 17, end: 314 },\n        { start: 314, end: 405 },\n        { start: 405, end: 321 },\n        { start: 321, end: 375 },\n        { start: 375, end: 291 },\n        { start: 61, end: 185 },\n        { start: 185, end: 40 },\n        { start: 40, end: 39 },\n        { start: 39, end: 37 },\n        { start: 37, end: 0 },\n        { start: 0, end: 267 },\n        { start: 267, end: 269 },\n        { start: 269, end: 270 },\n        { start: 270, end: 409 },\n        { start: 409, end: 291 },\n        { start: 78, end: 95 },\n        { start: 95, end: 88 },\n        { start: 88, end: 178 },\n        { start: 178, end: 87 },\n        { start: 87, end: 14 },\n        { start: 14, end: 317 },\n        { start: 317, end: 402 },\n        { start: 402, end: 318 },\n        { start: 318, end: 324 },\n        { start: 324, end: 308 },\n        { start: 78, end: 191 },\n        { start: 191, end: 80 },\n        { start: 80, end: 81 },\n        { start: 81, end: 82 },\n        { start: 82, end: 13 },\n        { start: 13, end: 312 },\n        { start: 312, end: 311 },\n        { start: 311, end: 310 },\n        { start: 310, end: 415 },\n        { start: 415, end: 308 },\n    ]),\n    (exports.FACE_LANDMARKS_LEFT_EYE = [\n        { start: 263, end: 249 },\n        { start: 249, end: 390 },\n        { start: 390, end: 373 },\n        { start: 373, end: 374 },\n        { start: 374, end: 380 },\n        { start: 380, end: 381 },\n        { start: 381, end: 382 },\n        { start: 382, end: 362 },\n        { start: 263, end: 466 },\n        { start: 466, end: 388 },\n        { start: 388, end: 387 },\n        { start: 387, end: 386 },\n        { start: 386, end: 385 },\n        { start: 385, end: 384 },\n        { start: 384, end: 398 },\n        { start: 398, end: 362 },\n    ]),\n    (exports.FACE_LANDMARKS_LEFT_EYEBROW = [\n        { start: 276, end: 283 },\n        { start: 283, end: 282 },\n        { start: 282, end: 295 },\n        { start: 295, end: 285 },\n        { start: 300, end: 293 },\n        { start: 293, end: 334 },\n        { start: 334, end: 296 },\n        { start: 296, end: 336 },\n    ]),\n    (exports.FACE_LANDMARKS_LEFT_IRIS = [\n        { start: 474, end: 475 },\n        { start: 475, end: 476 },\n        { start: 476, end: 477 },\n        { start: 477, end: 474 },\n    ]),\n    (exports.FACE_LANDMARKS_RIGHT_EYE = [\n        { start: 33, end: 7 },\n        { start: 7, end: 163 },\n        { start: 163, end: 144 },\n        { start: 144, end: 145 },\n        { start: 145, end: 153 },\n        { start: 153, end: 154 },\n        { start: 154, end: 155 },\n        { start: 155, end: 133 },\n        { start: 33, end: 246 },\n        { start: 246, end: 161 },\n        { start: 161, end: 160 },\n        { start: 160, end: 159 },\n        { start: 159, end: 158 },\n        { start: 158, end: 157 },\n        { start: 157, end: 173 },\n        { start: 173, end: 133 },\n    ]),\n    (exports.FACE_LANDMARKS_RIGHT_EYEBROW = [\n        { start: 46, end: 53 },\n        { start: 53, end: 52 },\n        { start: 52, end: 65 },\n        { start: 65, end: 55 },\n        { start: 70, end: 63 },\n        { start: 63, end: 105 },\n        { start: 105, end: 66 },\n        { start: 66, end: 107 },\n    ]),\n    (exports.FACE_LANDMARKS_RIGHT_IRIS = [\n        { start: 469, end: 470 },\n        { start: 470, end: 471 },\n        { start: 471, end: 472 },\n        { start: 472, end: 469 },\n    ]),\n    (exports.FACE_LANDMARKS_FACE_OVAL = [\n        { start: 10, end: 338 },\n        { start: 338, end: 297 },\n        { start: 297, end: 332 },\n        { start: 332, end: 284 },\n        { start: 284, end: 251 },\n        { start: 251, end: 389 },\n        { start: 389, end: 356 },\n        { start: 356, end: 454 },\n        { start: 454, end: 323 },\n        { start: 323, end: 361 },\n        { start: 361, end: 288 },\n        { start: 288, end: 397 },\n        { start: 397, end: 365 },\n        { start: 365, end: 379 },\n        { start: 379, end: 378 },\n        { start: 378, end: 400 },\n        { start: 400, end: 377 },\n        { start: 377, end: 152 },\n        { start: 152, end: 148 },\n        { start: 148, end: 176 },\n        { start: 176, end: 149 },\n        { start: 149, end: 150 },\n        { start: 150, end: 136 },\n        { start: 136, end: 172 },\n        { start: 172, end: 58 },\n        { start: 58, end: 132 },\n        { start: 132, end: 93 },\n        { start: 93, end: 234 },\n        { start: 234, end: 127 },\n        { start: 127, end: 162 },\n        { start: 162, end: 21 },\n        { start: 21, end: 54 },\n        { start: 54, end: 103 },\n        { start: 103, end: 67 },\n        { start: 67, end: 109 },\n        { start: 109, end: 10 },\n    ]),\n    (exports.FACE_LANDMARKS_CONTOURS = [\n        ...exports.FACE_LANDMARKS_LIPS,\n        ...exports.FACE_LANDMARKS_LEFT_EYE,\n        ...exports.FACE_LANDMARKS_LEFT_EYEBROW,\n        ...exports.FACE_LANDMARKS_RIGHT_EYE,\n        ...exports.FACE_LANDMARKS_RIGHT_EYEBROW,\n        ...exports.FACE_LANDMARKS_FACE_OVAL,\n    ]),\n    (exports.FACE_LANDMARKS_TESSELATION = [\n        { start: 127, end: 34 },\n        { start: 34, end: 139 },\n        { start: 139, end: 127 },\n        { start: 11, end: 0 },\n        { start: 0, end: 37 },\n        { start: 37, end: 11 },\n        { start: 232, end: 231 },\n        { start: 231, end: 120 },\n        { start: 120, end: 232 },\n        { start: 72, end: 37 },\n        { start: 37, end: 39 },\n        { start: 39, end: 72 },\n        { start: 128, end: 121 },\n        { start: 121, end: 47 },\n        { start: 47, end: 128 },\n        { start: 232, end: 121 },\n        { start: 121, end: 128 },\n        { start: 128, end: 232 },\n        { start: 104, end: 69 },\n        { start: 69, end: 67 },\n        { start: 67, end: 104 },\n        { start: 175, end: 171 },\n        { start: 171, end: 148 },\n        { start: 148, end: 175 },\n        { start: 118, end: 50 },\n        { start: 50, end: 101 },\n        { start: 101, end: 118 },\n        { start: 73, end: 39 },\n        { start: 39, end: 40 },\n        { start: 40, end: 73 },\n        { start: 9, end: 151 },\n        { start: 151, end: 108 },\n        { start: 108, end: 9 },\n        { start: 48, end: 115 },\n        { start: 115, end: 131 },\n        { start: 131, end: 48 },\n        { start: 194, end: 204 },\n        { start: 204, end: 211 },\n        { start: 211, end: 194 },\n        { start: 74, end: 40 },\n        { start: 40, end: 185 },\n        { start: 185, end: 74 },\n        { start: 80, end: 42 },\n        { start: 42, end: 183 },\n        { start: 183, end: 80 },\n        { start: 40, end: 92 },\n        { start: 92, end: 186 },\n        { start: 186, end: 40 },\n        { start: 230, end: 229 },\n        { start: 229, end: 118 },\n        { start: 118, end: 230 },\n        { start: 202, end: 212 },\n        { start: 212, end: 214 },\n        { start: 214, end: 202 },\n        { start: 83, end: 18 },\n        { start: 18, end: 17 },\n        { start: 17, end: 83 },\n        { start: 76, end: 61 },\n        { start: 61, end: 146 },\n        { start: 146, end: 76 },\n        { start: 160, end: 29 },\n        { start: 29, end: 30 },\n        { start: 30, end: 160 },\n        { start: 56, end: 157 },\n        { start: 157, end: 173 },\n        { start: 173, end: 56 },\n        { start: 106, end: 204 },\n        { start: 204, end: 194 },\n        { start: 194, end: 106 },\n        { start: 135, end: 214 },\n        { start: 214, end: 192 },\n        { start: 192, end: 135 },\n        { start: 203, end: 165 },\n        { start: 165, end: 98 },\n        { start: 98, end: 203 },\n        { start: 21, end: 71 },\n        { start: 71, end: 68 },\n        { start: 68, end: 21 },\n        { start: 51, end: 45 },\n        { start: 45, end: 4 },\n        { start: 4, end: 51 },\n        { start: 144, end: 24 },\n        { start: 24, end: 23 },\n        { start: 23, end: 144 },\n        { start: 77, end: 146 },\n        { start: 146, end: 91 },\n        { start: 91, end: 77 },\n        { start: 205, end: 50 },\n        { start: 50, end: 187 },\n        { start: 187, end: 205 },\n        { start: 201, end: 200 },\n        { start: 200, end: 18 },\n        { start: 18, end: 201 },\n        { start: 91, end: 106 },\n        { start: 106, end: 182 },\n        { start: 182, end: 91 },\n        { start: 90, end: 91 },\n        { start: 91, end: 181 },\n        { start: 181, end: 90 },\n        { start: 85, end: 84 },\n        { start: 84, end: 17 },\n        { start: 17, end: 85 },\n        { start: 206, end: 203 },\n        { start: 203, end: 36 },\n        { start: 36, end: 206 },\n        { start: 148, end: 171 },\n        { start: 171, end: 140 },\n        { start: 140, end: 148 },\n        { start: 92, end: 40 },\n        { start: 40, end: 39 },\n        { start: 39, end: 92 },\n        { start: 193, end: 189 },\n        { start: 189, end: 244 },\n        { start: 244, end: 193 },\n        { start: 159, end: 158 },\n        { start: 158, end: 28 },\n        { start: 28, end: 159 },\n        { start: 247, end: 246 },\n        { start: 246, end: 161 },\n        { start: 161, end: 247 },\n        { start: 236, end: 3 },\n        { start: 3, end: 196 },\n        { start: 196, end: 236 },\n        { start: 54, end: 68 },\n        { start: 68, end: 104 },\n        { start: 104, end: 54 },\n        { start: 193, end: 168 },\n        { start: 168, end: 8 },\n        { start: 8, end: 193 },\n        { start: 117, end: 228 },\n        { start: 228, end: 31 },\n        { start: 31, end: 117 },\n        { start: 189, end: 193 },\n        { start: 193, end: 55 },\n        { start: 55, end: 189 },\n        { start: 98, end: 97 },\n        { start: 97, end: 99 },\n        { start: 99, end: 98 },\n        { start: 126, end: 47 },\n        { start: 47, end: 100 },\n        { start: 100, end: 126 },\n        { start: 166, end: 79 },\n        { start: 79, end: 218 },\n        { start: 218, end: 166 },\n        { start: 155, end: 154 },\n        { start: 154, end: 26 },\n        { start: 26, end: 155 },\n        { start: 209, end: 49 },\n        { start: 49, end: 131 },\n        { start: 131, end: 209 },\n        { start: 135, end: 136 },\n        { start: 136, end: 150 },\n        { start: 150, end: 135 },\n        { start: 47, end: 126 },\n        { start: 126, end: 217 },\n        { start: 217, end: 47 },\n        { start: 223, end: 52 },\n        { start: 52, end: 53 },\n        { start: 53, end: 223 },\n        { start: 45, end: 51 },\n        { start: 51, end: 134 },\n        { start: 134, end: 45 },\n        { start: 211, end: 170 },\n        { start: 170, end: 140 },\n        { start: 140, end: 211 },\n        { start: 67, end: 69 },\n        { start: 69, end: 108 },\n        { start: 108, end: 67 },\n        { start: 43, end: 106 },\n        { start: 106, end: 91 },\n        { start: 91, end: 43 },\n        { start: 230, end: 119 },\n        { start: 119, end: 120 },\n        { start: 120, end: 230 },\n        { start: 226, end: 130 },\n        { start: 130, end: 247 },\n        { start: 247, end: 226 },\n        { start: 63, end: 53 },\n        { start: 53, end: 52 },\n        { start: 52, end: 63 },\n        { start: 238, end: 20 },\n        { start: 20, end: 242 },\n        { start: 242, end: 238 },\n        { start: 46, end: 70 },\n        { start: 70, end: 156 },\n        { start: 156, end: 46 },\n        { start: 78, end: 62 },\n        { start: 62, end: 96 },\n        { start: 96, end: 78 },\n        { start: 46, end: 53 },\n        { start: 53, end: 63 },\n        { start: 63, end: 46 },\n        { start: 143, end: 34 },\n        { start: 34, end: 227 },\n        { start: 227, end: 143 },\n        { start: 123, end: 117 },\n        { start: 117, end: 111 },\n        { start: 111, end: 123 },\n        { start: 44, end: 125 },\n        { start: 125, end: 19 },\n        { start: 19, end: 44 },\n        { start: 236, end: 134 },\n        { start: 134, end: 51 },\n        { start: 51, end: 236 },\n        { start: 216, end: 206 },\n        { start: 206, end: 205 },\n        { start: 205, end: 216 },\n        { start: 154, end: 153 },\n        { start: 153, end: 22 },\n        { start: 22, end: 154 },\n        { start: 39, end: 37 },\n        { start: 37, end: 167 },\n        { start: 167, end: 39 },\n        { start: 200, end: 201 },\n        { start: 201, end: 208 },\n        { start: 208, end: 200 },\n        { start: 36, end: 142 },\n        { start: 142, end: 100 },\n        { start: 100, end: 36 },\n        { start: 57, end: 212 },\n        { start: 212, end: 202 },\n        { start: 202, end: 57 },\n        { start: 20, end: 60 },\n        { start: 60, end: 99 },\n        { start: 99, end: 20 },\n        { start: 28, end: 158 },\n        { start: 158, end: 157 },\n        { start: 157, end: 28 },\n        { start: 35, end: 226 },\n        { start: 226, end: 113 },\n        { start: 113, end: 35 },\n        { start: 160, end: 159 },\n        { start: 159, end: 27 },\n        { start: 27, end: 160 },\n        { start: 204, end: 202 },\n        { start: 202, end: 210 },\n        { start: 210, end: 204 },\n        { start: 113, end: 225 },\n        { start: 225, end: 46 },\n        { start: 46, end: 113 },\n        { start: 43, end: 202 },\n        { start: 202, end: 204 },\n        { start: 204, end: 43 },\n        { start: 62, end: 76 },\n        { start: 76, end: 77 },\n        { start: 77, end: 62 },\n        { start: 137, end: 123 },\n        { start: 123, end: 116 },\n        { start: 116, end: 137 },\n        { start: 41, end: 38 },\n        { start: 38, end: 72 },\n        { start: 72, end: 41 },\n        { start: 203, end: 129 },\n        { start: 129, end: 142 },\n        { start: 142, end: 203 },\n        { start: 64, end: 98 },\n        { start: 98, end: 240 },\n        { start: 240, end: 64 },\n        { start: 49, end: 102 },\n        { start: 102, end: 64 },\n        { start: 64, end: 49 },\n        { start: 41, end: 73 },\n        { start: 73, end: 74 },\n        { start: 74, end: 41 },\n        { start: 212, end: 216 },\n        { start: 216, end: 207 },\n        { start: 207, end: 212 },\n        { start: 42, end: 74 },\n        { start: 74, end: 184 },\n        { start: 184, end: 42 },\n        { start: 169, end: 170 },\n        { start: 170, end: 211 },\n        { start: 211, end: 169 },\n        { start: 170, end: 149 },\n        { start: 149, end: 176 },\n        { start: 176, end: 170 },\n        { start: 105, end: 66 },\n        { start: 66, end: 69 },\n        { start: 69, end: 105 },\n        { start: 122, end: 6 },\n        { start: 6, end: 168 },\n        { start: 168, end: 122 },\n        { start: 123, end: 147 },\n        { start: 147, end: 187 },\n        { start: 187, end: 123 },\n        { start: 96, end: 77 },\n        { start: 77, end: 90 },\n        { start: 90, end: 96 },\n        { start: 65, end: 55 },\n        { start: 55, end: 107 },\n        { start: 107, end: 65 },\n        { start: 89, end: 90 },\n        { start: 90, end: 180 },\n        { start: 180, end: 89 },\n        { start: 101, end: 100 },\n        { start: 100, end: 120 },\n        { start: 120, end: 101 },\n        { start: 63, end: 105 },\n        { start: 105, end: 104 },\n        { start: 104, end: 63 },\n        { start: 93, end: 137 },\n        { start: 137, end: 227 },\n        { start: 227, end: 93 },\n        { start: 15, end: 86 },\n        { start: 86, end: 85 },\n        { start: 85, end: 15 },\n        { start: 129, end: 102 },\n        { start: 102, end: 49 },\n        { start: 49, end: 129 },\n        { start: 14, end: 87 },\n        { start: 87, end: 86 },\n        { start: 86, end: 14 },\n        { start: 55, end: 8 },\n        { start: 8, end: 9 },\n        { start: 9, end: 55 },\n        { start: 100, end: 47 },\n        { start: 47, end: 121 },\n        { start: 121, end: 100 },\n        { start: 145, end: 23 },\n        { start: 23, end: 22 },\n        { start: 22, end: 145 },\n        { start: 88, end: 89 },\n        { start: 89, end: 179 },\n        { start: 179, end: 88 },\n        { start: 6, end: 122 },\n        { start: 122, end: 196 },\n        { start: 196, end: 6 },\n        { start: 88, end: 95 },\n        { start: 95, end: 96 },\n        { start: 96, end: 88 },\n        { start: 138, end: 172 },\n        { start: 172, end: 136 },\n        { start: 136, end: 138 },\n        { start: 215, end: 58 },\n        { start: 58, end: 172 },\n        { start: 172, end: 215 },\n        { start: 115, end: 48 },\n        { start: 48, end: 219 },\n        { start: 219, end: 115 },\n        { start: 42, end: 80 },\n        { start: 80, end: 81 },\n        { start: 81, end: 42 },\n        { start: 195, end: 3 },\n        { start: 3, end: 51 },\n        { start: 51, end: 195 },\n        { start: 43, end: 146 },\n        { start: 146, end: 61 },\n        { start: 61, end: 43 },\n        { start: 171, end: 175 },\n        { start: 175, end: 199 },\n        { start: 199, end: 171 },\n        { start: 81, end: 82 },\n        { start: 82, end: 38 },\n        { start: 38, end: 81 },\n        { start: 53, end: 46 },\n        { start: 46, end: 225 },\n        { start: 225, end: 53 },\n        { start: 144, end: 163 },\n        { start: 163, end: 110 },\n        { start: 110, end: 144 },\n        { start: 52, end: 65 },\n        { start: 65, end: 66 },\n        { start: 66, end: 52 },\n        { start: 229, end: 228 },\n        { start: 228, end: 117 },\n        { start: 117, end: 229 },\n        { start: 34, end: 127 },\n        { start: 127, end: 234 },\n        { start: 234, end: 34 },\n        { start: 107, end: 108 },\n        { start: 108, end: 69 },\n        { start: 69, end: 107 },\n        { start: 109, end: 108 },\n        { start: 108, end: 151 },\n        { start: 151, end: 109 },\n        { start: 48, end: 64 },\n        { start: 64, end: 235 },\n        { start: 235, end: 48 },\n        { start: 62, end: 78 },\n        { start: 78, end: 191 },\n        { start: 191, end: 62 },\n        { start: 129, end: 209 },\n        { start: 209, end: 126 },\n        { start: 126, end: 129 },\n        { start: 111, end: 35 },\n        { start: 35, end: 143 },\n        { start: 143, end: 111 },\n        { start: 117, end: 123 },\n        { start: 123, end: 50 },\n        { start: 50, end: 117 },\n        { start: 222, end: 65 },\n        { start: 65, end: 52 },\n        { start: 52, end: 222 },\n        { start: 19, end: 125 },\n        { start: 125, end: 141 },\n        { start: 141, end: 19 },\n        { start: 221, end: 55 },\n        { start: 55, end: 65 },\n        { start: 65, end: 221 },\n        { start: 3, end: 195 },\n        { start: 195, end: 197 },\n        { start: 197, end: 3 },\n        { start: 25, end: 7 },\n        { start: 7, end: 33 },\n        { start: 33, end: 25 },\n        { start: 220, end: 237 },\n        { start: 237, end: 44 },\n        { start: 44, end: 220 },\n        { start: 70, end: 71 },\n        { start: 71, end: 139 },\n        { start: 139, end: 70 },\n        { start: 122, end: 193 },\n        { start: 193, end: 245 },\n        { start: 245, end: 122 },\n        { start: 247, end: 130 },\n        { start: 130, end: 33 },\n        { start: 33, end: 247 },\n        { start: 71, end: 21 },\n        { start: 21, end: 162 },\n        { start: 162, end: 71 },\n        { start: 170, end: 169 },\n        { start: 169, end: 150 },\n        { start: 150, end: 170 },\n        { start: 188, end: 174 },\n        { start: 174, end: 196 },\n        { start: 196, end: 188 },\n        { start: 216, end: 186 },\n        { start: 186, end: 92 },\n        { start: 92, end: 216 },\n        { start: 2, end: 97 },\n        { start: 97, end: 167 },\n        { start: 167, end: 2 },\n        { start: 141, end: 125 },\n        { start: 125, end: 241 },\n        { start: 241, end: 141 },\n        { start: 164, end: 167 },\n        { start: 167, end: 37 },\n        { start: 37, end: 164 },\n        { start: 72, end: 38 },\n        { start: 38, end: 12 },\n        { start: 12, end: 72 },\n        { start: 38, end: 82 },\n        { start: 82, end: 13 },\n        { start: 13, end: 38 },\n        { start: 63, end: 68 },\n        { start: 68, end: 71 },\n        { start: 71, end: 63 },\n        { start: 226, end: 35 },\n        { start: 35, end: 111 },\n        { start: 111, end: 226 },\n        { start: 101, end: 50 },\n        { start: 50, end: 205 },\n        { start: 205, end: 101 },\n        { start: 206, end: 92 },\n        { start: 92, end: 165 },\n        { start: 165, end: 206 },\n        { start: 209, end: 198 },\n        { start: 198, end: 217 },\n        { start: 217, end: 209 },\n        { start: 165, end: 167 },\n        { start: 167, end: 97 },\n        { start: 97, end: 165 },\n        { start: 220, end: 115 },\n        { start: 115, end: 218 },\n        { start: 218, end: 220 },\n        { start: 133, end: 112 },\n        { start: 112, end: 243 },\n        { start: 243, end: 133 },\n        { start: 239, end: 238 },\n        { start: 238, end: 241 },\n        { start: 241, end: 239 },\n        { start: 214, end: 135 },\n        { start: 135, end: 169 },\n        { start: 169, end: 214 },\n        { start: 190, end: 173 },\n        { start: 173, end: 133 },\n        { start: 133, end: 190 },\n        { start: 171, end: 208 },\n        { start: 208, end: 32 },\n        { start: 32, end: 171 },\n        { start: 125, end: 44 },\n        { start: 44, end: 237 },\n        { start: 237, end: 125 },\n        { start: 86, end: 87 },\n        { start: 87, end: 178 },\n        { start: 178, end: 86 },\n        { start: 85, end: 86 },\n        { start: 86, end: 179 },\n        { start: 179, end: 85 },\n        { start: 84, end: 85 },\n        { start: 85, end: 180 },\n        { start: 180, end: 84 },\n        { start: 83, end: 84 },\n        { start: 84, end: 181 },\n        { start: 181, end: 83 },\n        { start: 201, end: 83 },\n        { start: 83, end: 182 },\n        { start: 182, end: 201 },\n        { start: 137, end: 93 },\n        { start: 93, end: 132 },\n        { start: 132, end: 137 },\n        { start: 76, end: 62 },\n        { start: 62, end: 183 },\n        { start: 183, end: 76 },\n        { start: 61, end: 76 },\n        { start: 76, end: 184 },\n        { start: 184, end: 61 },\n        { start: 57, end: 61 },\n        { start: 61, end: 185 },\n        { start: 185, end: 57 },\n        { start: 212, end: 57 },\n        { start: 57, end: 186 },\n        { start: 186, end: 212 },\n        { start: 214, end: 207 },\n        { start: 207, end: 187 },\n        { start: 187, end: 214 },\n        { start: 34, end: 143 },\n        { start: 143, end: 156 },\n        { start: 156, end: 34 },\n        { start: 79, end: 239 },\n        { start: 239, end: 237 },\n        { start: 237, end: 79 },\n        { start: 123, end: 137 },\n        { start: 137, end: 177 },\n        { start: 177, end: 123 },\n        { start: 44, end: 1 },\n        { start: 1, end: 4 },\n        { start: 4, end: 44 },\n        { start: 201, end: 194 },\n        { start: 194, end: 32 },\n        { start: 32, end: 201 },\n        { start: 64, end: 102 },\n        { start: 102, end: 129 },\n        { start: 129, end: 64 },\n        { start: 213, end: 215 },\n        { start: 215, end: 138 },\n        { start: 138, end: 213 },\n        { start: 59, end: 166 },\n        { start: 166, end: 219 },\n        { start: 219, end: 59 },\n        { start: 242, end: 99 },\n        { start: 99, end: 97 },\n        { start: 97, end: 242 },\n        { start: 2, end: 94 },\n        { start: 94, end: 141 },\n        { start: 141, end: 2 },\n        { start: 75, end: 59 },\n        { start: 59, end: 235 },\n        { start: 235, end: 75 },\n        { start: 24, end: 110 },\n        { start: 110, end: 228 },\n        { start: 228, end: 24 },\n        { start: 25, end: 130 },\n        { start: 130, end: 226 },\n        { start: 226, end: 25 },\n        { start: 23, end: 24 },\n        { start: 24, end: 229 },\n        { start: 229, end: 23 },\n        { start: 22, end: 23 },\n        { start: 23, end: 230 },\n        { start: 230, end: 22 },\n        { start: 26, end: 22 },\n        { start: 22, end: 231 },\n        { start: 231, end: 26 },\n        { start: 112, end: 26 },\n        { start: 26, end: 232 },\n        { start: 232, end: 112 },\n        { start: 189, end: 190 },\n        { start: 190, end: 243 },\n        { start: 243, end: 189 },\n        { start: 221, end: 56 },\n        { start: 56, end: 190 },\n        { start: 190, end: 221 },\n        { start: 28, end: 56 },\n        { start: 56, end: 221 },\n        { start: 221, end: 28 },\n        { start: 27, end: 28 },\n        { start: 28, end: 222 },\n        { start: 222, end: 27 },\n        { start: 29, end: 27 },\n        { start: 27, end: 223 },\n        { start: 223, end: 29 },\n        { start: 30, end: 29 },\n        { start: 29, end: 224 },\n        { start: 224, end: 30 },\n        { start: 247, end: 30 },\n        { start: 30, end: 225 },\n        { start: 225, end: 247 },\n        { start: 238, end: 79 },\n        { start: 79, end: 20 },\n        { start: 20, end: 238 },\n        { start: 166, end: 59 },\n        { start: 59, end: 75 },\n        { start: 75, end: 166 },\n        { start: 60, end: 75 },\n        { start: 75, end: 240 },\n        { start: 240, end: 60 },\n        { start: 147, end: 177 },\n        { start: 177, end: 215 },\n        { start: 215, end: 147 },\n        { start: 20, end: 79 },\n        { start: 79, end: 166 },\n        { start: 166, end: 20 },\n        { start: 187, end: 147 },\n        { start: 147, end: 213 },\n        { start: 213, end: 187 },\n        { start: 112, end: 233 },\n        { start: 233, end: 244 },\n        { start: 244, end: 112 },\n        { start: 233, end: 128 },\n        { start: 128, end: 245 },\n        { start: 245, end: 233 },\n        { start: 128, end: 114 },\n        { start: 114, end: 188 },\n        { start: 188, end: 128 },\n        { start: 114, end: 217 },\n        { start: 217, end: 174 },\n        { start: 174, end: 114 },\n        { start: 131, end: 115 },\n        { start: 115, end: 220 },\n        { start: 220, end: 131 },\n        { start: 217, end: 198 },\n        { start: 198, end: 236 },\n        { start: 236, end: 217 },\n        { start: 198, end: 131 },\n        { start: 131, end: 134 },\n        { start: 134, end: 198 },\n        { start: 177, end: 132 },\n        { start: 132, end: 58 },\n        { start: 58, end: 177 },\n        { start: 143, end: 35 },\n        { start: 35, end: 124 },\n        { start: 124, end: 143 },\n        { start: 110, end: 163 },\n        { start: 163, end: 7 },\n        { start: 7, end: 110 },\n        { start: 228, end: 110 },\n        { start: 110, end: 25 },\n        { start: 25, end: 228 },\n        { start: 356, end: 389 },\n        { start: 389, end: 368 },\n        { start: 368, end: 356 },\n        { start: 11, end: 302 },\n        { start: 302, end: 267 },\n        { start: 267, end: 11 },\n        { start: 452, end: 350 },\n        { start: 350, end: 349 },\n        { start: 349, end: 452 },\n        { start: 302, end: 303 },\n        { start: 303, end: 269 },\n        { start: 269, end: 302 },\n        { start: 357, end: 343 },\n        { start: 343, end: 277 },\n        { start: 277, end: 357 },\n        { start: 452, end: 453 },\n        { start: 453, end: 357 },\n        { start: 357, end: 452 },\n        { start: 333, end: 332 },\n        { start: 332, end: 297 },\n        { start: 297, end: 333 },\n        { start: 175, end: 152 },\n        { start: 152, end: 377 },\n        { start: 377, end: 175 },\n        { start: 347, end: 348 },\n        { start: 348, end: 330 },\n        { start: 330, end: 347 },\n        { start: 303, end: 304 },\n        { start: 304, end: 270 },\n        { start: 270, end: 303 },\n        { start: 9, end: 336 },\n        { start: 336, end: 337 },\n        { start: 337, end: 9 },\n        { start: 278, end: 279 },\n        { start: 279, end: 360 },\n        { start: 360, end: 278 },\n        { start: 418, end: 262 },\n        { start: 262, end: 431 },\n        { start: 431, end: 418 },\n        { start: 304, end: 408 },\n        { start: 408, end: 409 },\n        { start: 409, end: 304 },\n        { start: 310, end: 415 },\n        { start: 415, end: 407 },\n        { start: 407, end: 310 },\n        { start: 270, end: 409 },\n        { start: 409, end: 410 },\n        { start: 410, end: 270 },\n        { start: 450, end: 348 },\n        { start: 348, end: 347 },\n        { start: 347, end: 450 },\n        { start: 422, end: 430 },\n        { start: 430, end: 434 },\n        { start: 434, end: 422 },\n        { start: 313, end: 314 },\n        { start: 314, end: 17 },\n        { start: 17, end: 313 },\n        { start: 306, end: 307 },\n        { start: 307, end: 375 },\n        { start: 375, end: 306 },\n        { start: 387, end: 388 },\n        { start: 388, end: 260 },\n        { start: 260, end: 387 },\n        { start: 286, end: 414 },\n        { start: 414, end: 398 },\n        { start: 398, end: 286 },\n        { start: 335, end: 406 },\n        { start: 406, end: 418 },\n        { start: 418, end: 335 },\n        { start: 364, end: 367 },\n        { start: 367, end: 416 },\n        { start: 416, end: 364 },\n        { start: 423, end: 358 },\n        { start: 358, end: 327 },\n        { start: 327, end: 423 },\n        { start: 251, end: 284 },\n        { start: 284, end: 298 },\n        { start: 298, end: 251 },\n        { start: 281, end: 5 },\n        { start: 5, end: 4 },\n        { start: 4, end: 281 },\n        { start: 373, end: 374 },\n        { start: 374, end: 253 },\n        { start: 253, end: 373 },\n        { start: 307, end: 320 },\n        { start: 320, end: 321 },\n        { start: 321, end: 307 },\n        { start: 425, end: 427 },\n        { start: 427, end: 411 },\n        { start: 411, end: 425 },\n        { start: 421, end: 313 },\n        { start: 313, end: 18 },\n        { start: 18, end: 421 },\n        { start: 321, end: 405 },\n        { start: 405, end: 406 },\n        { start: 406, end: 321 },\n        { start: 320, end: 404 },\n        { start: 404, end: 405 },\n        { start: 405, end: 320 },\n        { start: 315, end: 16 },\n        { start: 16, end: 17 },\n        { start: 17, end: 315 },\n        { start: 426, end: 425 },\n        { start: 425, end: 266 },\n        { start: 266, end: 426 },\n        { start: 377, end: 400 },\n        { start: 400, end: 369 },\n        { start: 369, end: 377 },\n        { start: 322, end: 391 },\n        { start: 391, end: 269 },\n        { start: 269, end: 322 },\n        { start: 417, end: 465 },\n        { start: 465, end: 464 },\n        { start: 464, end: 417 },\n        { start: 386, end: 257 },\n        { start: 257, end: 258 },\n        { start: 258, end: 386 },\n        { start: 466, end: 260 },\n        { start: 260, end: 388 },\n        { start: 388, end: 466 },\n        { start: 456, end: 399 },\n        { start: 399, end: 419 },\n        { start: 419, end: 456 },\n        { start: 284, end: 332 },\n        { start: 332, end: 333 },\n        { start: 333, end: 284 },\n        { start: 417, end: 285 },\n        { start: 285, end: 8 },\n        { start: 8, end: 417 },\n        { start: 346, end: 340 },\n        { start: 340, end: 261 },\n        { start: 261, end: 346 },\n        { start: 413, end: 441 },\n        { start: 441, end: 285 },\n        { start: 285, end: 413 },\n        { start: 327, end: 460 },\n        { start: 460, end: 328 },\n        { start: 328, end: 327 },\n        { start: 355, end: 371 },\n        { start: 371, end: 329 },\n        { start: 329, end: 355 },\n        { start: 392, end: 439 },\n        { start: 439, end: 438 },\n        { start: 438, end: 392 },\n        { start: 382, end: 341 },\n        { start: 341, end: 256 },\n        { start: 256, end: 382 },\n        { start: 429, end: 420 },\n        { start: 420, end: 360 },\n        { start: 360, end: 429 },\n        { start: 364, end: 394 },\n        { start: 394, end: 379 },\n        { start: 379, end: 364 },\n        { start: 277, end: 343 },\n        { start: 343, end: 437 },\n        { start: 437, end: 277 },\n        { start: 443, end: 444 },\n        { start: 444, end: 283 },\n        { start: 283, end: 443 },\n        { start: 275, end: 440 },\n        { start: 440, end: 363 },\n        { start: 363, end: 275 },\n        { start: 431, end: 262 },\n        { start: 262, end: 369 },\n        { start: 369, end: 431 },\n        { start: 297, end: 338 },\n        { start: 338, end: 337 },\n        { start: 337, end: 297 },\n        { start: 273, end: 375 },\n        { start: 375, end: 321 },\n        { start: 321, end: 273 },\n        { start: 450, end: 451 },\n        { start: 451, end: 349 },\n        { start: 349, end: 450 },\n        { start: 446, end: 342 },\n        { start: 342, end: 467 },\n        { start: 467, end: 446 },\n        { start: 293, end: 334 },\n        { start: 334, end: 282 },\n        { start: 282, end: 293 },\n        { start: 458, end: 461 },\n        { start: 461, end: 462 },\n        { start: 462, end: 458 },\n        { start: 276, end: 353 },\n        { start: 353, end: 383 },\n        { start: 383, end: 276 },\n        { start: 308, end: 324 },\n        { start: 324, end: 325 },\n        { start: 325, end: 308 },\n        { start: 276, end: 300 },\n        { start: 300, end: 293 },\n        { start: 293, end: 276 },\n        { start: 372, end: 345 },\n        { start: 345, end: 447 },\n        { start: 447, end: 372 },\n        { start: 352, end: 345 },\n        { start: 345, end: 340 },\n        { start: 340, end: 352 },\n        { start: 274, end: 1 },\n        { start: 1, end: 19 },\n        { start: 19, end: 274 },\n        { start: 456, end: 248 },\n        { start: 248, end: 281 },\n        { start: 281, end: 456 },\n        { start: 436, end: 427 },\n        { start: 427, end: 425 },\n        { start: 425, end: 436 },\n        { start: 381, end: 256 },\n        { start: 256, end: 252 },\n        { start: 252, end: 381 },\n        { start: 269, end: 391 },\n        { start: 391, end: 393 },\n        { start: 393, end: 269 },\n        { start: 200, end: 199 },\n        { start: 199, end: 428 },\n        { start: 428, end: 200 },\n        { start: 266, end: 330 },\n        { start: 330, end: 329 },\n        { start: 329, end: 266 },\n        { start: 287, end: 273 },\n        { start: 273, end: 422 },\n        { start: 422, end: 287 },\n        { start: 250, end: 462 },\n        { start: 462, end: 328 },\n        { start: 328, end: 250 },\n        { start: 258, end: 286 },\n        { start: 286, end: 384 },\n        { start: 384, end: 258 },\n        { start: 265, end: 353 },\n        { start: 353, end: 342 },\n        { start: 342, end: 265 },\n        { start: 387, end: 259 },\n        { start: 259, end: 257 },\n        { start: 257, end: 387 },\n        { start: 424, end: 431 },\n        { start: 431, end: 430 },\n        { start: 430, end: 424 },\n        { start: 342, end: 353 },\n        { start: 353, end: 276 },\n        { start: 276, end: 342 },\n        { start: 273, end: 335 },\n        { start: 335, end: 424 },\n        { start: 424, end: 273 },\n        { start: 292, end: 325 },\n        { start: 325, end: 307 },\n        { start: 307, end: 292 },\n        { start: 366, end: 447 },\n        { start: 447, end: 345 },\n        { start: 345, end: 366 },\n        { start: 271, end: 303 },\n        { start: 303, end: 302 },\n        { start: 302, end: 271 },\n        { start: 423, end: 266 },\n        { start: 266, end: 371 },\n        { start: 371, end: 423 },\n        { start: 294, end: 455 },\n        { start: 455, end: 460 },\n        { start: 460, end: 294 },\n        { start: 279, end: 278 },\n        { start: 278, end: 294 },\n        { start: 294, end: 279 },\n        { start: 271, end: 272 },\n        { start: 272, end: 304 },\n        { start: 304, end: 271 },\n        { start: 432, end: 434 },\n        { start: 434, end: 427 },\n        { start: 427, end: 432 },\n        { start: 272, end: 407 },\n        { start: 407, end: 408 },\n        { start: 408, end: 272 },\n        { start: 394, end: 430 },\n        { start: 430, end: 431 },\n        { start: 431, end: 394 },\n        { start: 395, end: 369 },\n        { start: 369, end: 400 },\n        { start: 400, end: 395 },\n        { start: 334, end: 333 },\n        { start: 333, end: 299 },\n        { start: 299, end: 334 },\n        { start: 351, end: 417 },\n        { start: 417, end: 168 },\n        { start: 168, end: 351 },\n        { start: 352, end: 280 },\n        { start: 280, end: 411 },\n        { start: 411, end: 352 },\n        { start: 325, end: 319 },\n        { start: 319, end: 320 },\n        { start: 320, end: 325 },\n        { start: 295, end: 296 },\n        { start: 296, end: 336 },\n        { start: 336, end: 295 },\n        { start: 319, end: 403 },\n        { start: 403, end: 404 },\n        { start: 404, end: 319 },\n        { start: 330, end: 348 },\n        { start: 348, end: 349 },\n        { start: 349, end: 330 },\n        { start: 293, end: 298 },\n        { start: 298, end: 333 },\n        { start: 333, end: 293 },\n        { start: 323, end: 454 },\n        { start: 454, end: 447 },\n        { start: 447, end: 323 },\n        { start: 15, end: 16 },\n        { start: 16, end: 315 },\n        { start: 315, end: 15 },\n        { start: 358, end: 429 },\n        { start: 429, end: 279 },\n        { start: 279, end: 358 },\n        { start: 14, end: 15 },\n        { start: 15, end: 316 },\n        { start: 316, end: 14 },\n        { start: 285, end: 336 },\n        { start: 336, end: 9 },\n        { start: 9, end: 285 },\n        { start: 329, end: 349 },\n        { start: 349, end: 350 },\n        { start: 350, end: 329 },\n        { start: 374, end: 380 },\n        { start: 380, end: 252 },\n        { start: 252, end: 374 },\n        { start: 318, end: 402 },\n        { start: 402, end: 403 },\n        { start: 403, end: 318 },\n        { start: 6, end: 197 },\n        { start: 197, end: 419 },\n        { start: 419, end: 6 },\n        { start: 318, end: 319 },\n        { start: 319, end: 325 },\n        { start: 325, end: 318 },\n        { start: 367, end: 364 },\n        { start: 364, end: 365 },\n        { start: 365, end: 367 },\n        { start: 435, end: 367 },\n        { start: 367, end: 397 },\n        { start: 397, end: 435 },\n        { start: 344, end: 438 },\n        { start: 438, end: 439 },\n        { start: 439, end: 344 },\n        { start: 272, end: 271 },\n        { start: 271, end: 311 },\n        { start: 311, end: 272 },\n        { start: 195, end: 5 },\n        { start: 5, end: 281 },\n        { start: 281, end: 195 },\n        { start: 273, end: 287 },\n        { start: 287, end: 291 },\n        { start: 291, end: 273 },\n        { start: 396, end: 428 },\n        { start: 428, end: 199 },\n        { start: 199, end: 396 },\n        { start: 311, end: 271 },\n        { start: 271, end: 268 },\n        { start: 268, end: 311 },\n        { start: 283, end: 444 },\n        { start: 444, end: 445 },\n        { start: 445, end: 283 },\n        { start: 373, end: 254 },\n        { start: 254, end: 339 },\n        { start: 339, end: 373 },\n        { start: 282, end: 334 },\n        { start: 334, end: 296 },\n        { start: 296, end: 282 },\n        { start: 449, end: 347 },\n        { start: 347, end: 346 },\n        { start: 346, end: 449 },\n        { start: 264, end: 447 },\n        { start: 447, end: 454 },\n        { start: 454, end: 264 },\n        { start: 336, end: 296 },\n        { start: 296, end: 299 },\n        { start: 299, end: 336 },\n        { start: 338, end: 10 },\n        { start: 10, end: 151 },\n        { start: 151, end: 338 },\n        { start: 278, end: 439 },\n        { start: 439, end: 455 },\n        { start: 455, end: 278 },\n        { start: 292, end: 407 },\n        { start: 407, end: 415 },\n        { start: 415, end: 292 },\n        { start: 358, end: 371 },\n        { start: 371, end: 355 },\n        { start: 355, end: 358 },\n        { start: 340, end: 345 },\n        { start: 345, end: 372 },\n        { start: 372, end: 340 },\n        { start: 346, end: 347 },\n        { start: 347, end: 280 },\n        { start: 280, end: 346 },\n        { start: 442, end: 443 },\n        { start: 443, end: 282 },\n        { start: 282, end: 442 },\n        { start: 19, end: 94 },\n        { start: 94, end: 370 },\n        { start: 370, end: 19 },\n        { start: 441, end: 442 },\n        { start: 442, end: 295 },\n        { start: 295, end: 441 },\n        { start: 248, end: 419 },\n        { start: 419, end: 197 },\n        { start: 197, end: 248 },\n        { start: 263, end: 255 },\n        { start: 255, end: 359 },\n        { start: 359, end: 263 },\n        { start: 440, end: 275 },\n        { start: 275, end: 274 },\n        { start: 274, end: 440 },\n        { start: 300, end: 383 },\n        { start: 383, end: 368 },\n        { start: 368, end: 300 },\n        { start: 351, end: 412 },\n        { start: 412, end: 465 },\n        { start: 465, end: 351 },\n        { start: 263, end: 467 },\n        { start: 467, end: 466 },\n        { start: 466, end: 263 },\n        { start: 301, end: 368 },\n        { start: 368, end: 389 },\n        { start: 389, end: 301 },\n        { start: 395, end: 378 },\n        { start: 378, end: 379 },\n        { start: 379, end: 395 },\n        { start: 412, end: 351 },\n        { start: 351, end: 419 },\n        { start: 419, end: 412 },\n        { start: 436, end: 426 },\n        { start: 426, end: 322 },\n        { start: 322, end: 436 },\n        { start: 2, end: 164 },\n        { start: 164, end: 393 },\n        { start: 393, end: 2 },\n        { start: 370, end: 462 },\n        { start: 462, end: 461 },\n        { start: 461, end: 370 },\n        { start: 164, end: 0 },\n        { start: 0, end: 267 },\n        { start: 267, end: 164 },\n        { start: 302, end: 11 },\n        { start: 11, end: 12 },\n        { start: 12, end: 302 },\n        { start: 268, end: 12 },\n        { start: 12, end: 13 },\n        { start: 13, end: 268 },\n        { start: 293, end: 300 },\n        { start: 300, end: 301 },\n        { start: 301, end: 293 },\n        { start: 446, end: 261 },\n        { start: 261, end: 340 },\n        { start: 340, end: 446 },\n        { start: 330, end: 266 },\n        { start: 266, end: 425 },\n        { start: 425, end: 330 },\n        { start: 426, end: 423 },\n        { start: 423, end: 391 },\n        { start: 391, end: 426 },\n        { start: 429, end: 355 },\n        { start: 355, end: 437 },\n        { start: 437, end: 429 },\n        { start: 391, end: 327 },\n        { start: 327, end: 326 },\n        { start: 326, end: 391 },\n        { start: 440, end: 457 },\n        { start: 457, end: 438 },\n        { start: 438, end: 440 },\n        { start: 341, end: 382 },\n        { start: 382, end: 362 },\n        { start: 362, end: 341 },\n        { start: 459, end: 457 },\n        { start: 457, end: 461 },\n        { start: 461, end: 459 },\n        { start: 434, end: 430 },\n        { start: 430, end: 394 },\n        { start: 394, end: 434 },\n        { start: 414, end: 463 },\n        { start: 463, end: 362 },\n        { start: 362, end: 414 },\n        { start: 396, end: 369 },\n        { start: 369, end: 262 },\n        { start: 262, end: 396 },\n        { start: 354, end: 461 },\n        { start: 461, end: 457 },\n        { start: 457, end: 354 },\n        { start: 316, end: 403 },\n        { start: 403, end: 402 },\n        { start: 402, end: 316 },\n        { start: 315, end: 404 },\n        { start: 404, end: 403 },\n        { start: 403, end: 315 },\n        { start: 314, end: 405 },\n        { start: 405, end: 404 },\n        { start: 404, end: 314 },\n        { start: 313, end: 406 },\n        { start: 406, end: 405 },\n        { start: 405, end: 313 },\n        { start: 421, end: 418 },\n        { start: 418, end: 406 },\n        { start: 406, end: 421 },\n        { start: 366, end: 401 },\n        { start: 401, end: 361 },\n        { start: 361, end: 366 },\n        { start: 306, end: 408 },\n        { start: 408, end: 407 },\n        { start: 407, end: 306 },\n        { start: 291, end: 409 },\n        { start: 409, end: 408 },\n        { start: 408, end: 291 },\n        { start: 287, end: 410 },\n        { start: 410, end: 409 },\n        { start: 409, end: 287 },\n        { start: 432, end: 436 },\n        { start: 436, end: 410 },\n        { start: 410, end: 432 },\n        { start: 434, end: 416 },\n        { start: 416, end: 411 },\n        { start: 411, end: 434 },\n        { start: 264, end: 368 },\n        { start: 368, end: 383 },\n        { start: 383, end: 264 },\n        { start: 309, end: 438 },\n        { start: 438, end: 457 },\n        { start: 457, end: 309 },\n        { start: 352, end: 376 },\n        { start: 376, end: 401 },\n        { start: 401, end: 352 },\n        { start: 274, end: 275 },\n        { start: 275, end: 4 },\n        { start: 4, end: 274 },\n        { start: 421, end: 428 },\n        { start: 428, end: 262 },\n        { start: 262, end: 421 },\n        { start: 294, end: 327 },\n        { start: 327, end: 358 },\n        { start: 358, end: 294 },\n        { start: 433, end: 416 },\n        { start: 416, end: 367 },\n        { start: 367, end: 433 },\n        { start: 289, end: 455 },\n        { start: 455, end: 439 },\n        { start: 439, end: 289 },\n        { start: 462, end: 370 },\n        { start: 370, end: 326 },\n        { start: 326, end: 462 },\n        { start: 2, end: 326 },\n        { start: 326, end: 370 },\n        { start: 370, end: 2 },\n        { start: 305, end: 460 },\n        { start: 460, end: 455 },\n        { start: 455, end: 305 },\n        { start: 254, end: 449 },\n        { start: 449, end: 448 },\n        { start: 448, end: 254 },\n        { start: 255, end: 261 },\n        { start: 261, end: 446 },\n        { start: 446, end: 255 },\n        { start: 253, end: 450 },\n        { start: 450, end: 449 },\n        { start: 449, end: 253 },\n        { start: 252, end: 451 },\n        { start: 451, end: 450 },\n        { start: 450, end: 252 },\n        { start: 256, end: 452 },\n        { start: 452, end: 451 },\n        { start: 451, end: 256 },\n        { start: 341, end: 453 },\n        { start: 453, end: 452 },\n        { start: 452, end: 341 },\n        { start: 413, end: 464 },\n        { start: 464, end: 463 },\n        { start: 463, end: 413 },\n        { start: 441, end: 413 },\n        { start: 413, end: 414 },\n        { start: 414, end: 441 },\n        { start: 258, end: 442 },\n        { start: 442, end: 441 },\n        { start: 441, end: 258 },\n        { start: 257, end: 443 },\n        { start: 443, end: 442 },\n        { start: 442, end: 257 },\n        { start: 259, end: 444 },\n        { start: 444, end: 443 },\n        { start: 443, end: 259 },\n        { start: 260, end: 445 },\n        { start: 445, end: 444 },\n        { start: 444, end: 260 },\n        { start: 467, end: 342 },\n        { start: 342, end: 445 },\n        { start: 445, end: 467 },\n        { start: 459, end: 458 },\n        { start: 458, end: 250 },\n        { start: 250, end: 459 },\n        { start: 289, end: 392 },\n        { start: 392, end: 290 },\n        { start: 290, end: 289 },\n        { start: 290, end: 328 },\n        { start: 328, end: 460 },\n        { start: 460, end: 290 },\n        { start: 376, end: 433 },\n        { start: 433, end: 435 },\n        { start: 435, end: 376 },\n        { start: 250, end: 290 },\n        { start: 290, end: 392 },\n        { start: 392, end: 250 },\n        { start: 411, end: 416 },\n        { start: 416, end: 433 },\n        { start: 433, end: 411 },\n        { start: 341, end: 463 },\n        { start: 463, end: 464 },\n        { start: 464, end: 341 },\n        { start: 453, end: 464 },\n        { start: 464, end: 465 },\n        { start: 465, end: 453 },\n        { start: 357, end: 465 },\n        { start: 465, end: 412 },\n        { start: 412, end: 357 },\n        { start: 343, end: 412 },\n        { start: 412, end: 399 },\n        { start: 399, end: 343 },\n        { start: 360, end: 363 },\n        { start: 363, end: 440 },\n        { start: 440, end: 360 },\n        { start: 437, end: 399 },\n        { start: 399, end: 456 },\n        { start: 456, end: 437 },\n        { start: 420, end: 456 },\n        { start: 456, end: 363 },\n        { start: 363, end: 420 },\n        { start: 401, end: 435 },\n        { start: 435, end: 288 },\n        { start: 288, end: 401 },\n        { start: 372, end: 383 },\n        { start: 383, end: 353 },\n        { start: 353, end: 372 },\n        { start: 339, end: 255 },\n        { start: 255, end: 249 },\n        { start: 249, end: 339 },\n        { start: 448, end: 261 },\n        { start: 261, end: 255 },\n        { start: 255, end: 448 },\n        { start: 133, end: 243 },\n        { start: 243, end: 190 },\n        { start: 190, end: 133 },\n        { start: 133, end: 155 },\n        { start: 155, end: 112 },\n        { start: 112, end: 133 },\n        { start: 33, end: 246 },\n        { start: 246, end: 247 },\n        { start: 247, end: 33 },\n        { start: 33, end: 130 },\n        { start: 130, end: 25 },\n        { start: 25, end: 33 },\n        { start: 398, end: 384 },\n        { start: 384, end: 286 },\n        { start: 286, end: 398 },\n        { start: 362, end: 398 },\n        { start: 398, end: 414 },\n        { start: 414, end: 362 },\n        { start: 362, end: 463 },\n        { start: 463, end: 341 },\n        { start: 341, end: 362 },\n        { start: 263, end: 359 },\n        { start: 359, end: 467 },\n        { start: 467, end: 263 },\n        { start: 263, end: 249 },\n        { start: 249, end: 255 },\n        { start: 255, end: 263 },\n        { start: 466, end: 467 },\n        { start: 467, end: 260 },\n        { start: 260, end: 466 },\n        { start: 75, end: 60 },\n        { start: 60, end: 166 },\n        { start: 166, end: 75 },\n        { start: 238, end: 239 },\n        { start: 239, end: 79 },\n        { start: 79, end: 238 },\n        { start: 162, end: 127 },\n        { start: 127, end: 139 },\n        { start: 139, end: 162 },\n        { start: 72, end: 11 },\n        { start: 11, end: 37 },\n        { start: 37, end: 72 },\n        { start: 121, end: 232 },\n        { start: 232, end: 120 },\n        { start: 120, end: 121 },\n        { start: 73, end: 72 },\n        { start: 72, end: 39 },\n        { start: 39, end: 73 },\n        { start: 114, end: 128 },\n        { start: 128, end: 47 },\n        { start: 47, end: 114 },\n        { start: 233, end: 232 },\n        { start: 232, end: 128 },\n        { start: 128, end: 233 },\n        { start: 103, end: 104 },\n        { start: 104, end: 67 },\n        { start: 67, end: 103 },\n        { start: 152, end: 175 },\n        { start: 175, end: 148 },\n        { start: 148, end: 152 },\n        { start: 119, end: 118 },\n        { start: 118, end: 101 },\n        { start: 101, end: 119 },\n        { start: 74, end: 73 },\n        { start: 73, end: 40 },\n        { start: 40, end: 74 },\n        { start: 107, end: 9 },\n        { start: 9, end: 108 },\n        { start: 108, end: 107 },\n        { start: 49, end: 48 },\n        { start: 48, end: 131 },\n        { start: 131, end: 49 },\n        { start: 32, end: 194 },\n        { start: 194, end: 211 },\n        { start: 211, end: 32 },\n        { start: 184, end: 74 },\n        { start: 74, end: 185 },\n        { start: 185, end: 184 },\n        { start: 191, end: 80 },\n        { start: 80, end: 183 },\n        { start: 183, end: 191 },\n        { start: 185, end: 40 },\n        { start: 40, end: 186 },\n        { start: 186, end: 185 },\n        { start: 119, end: 230 },\n        { start: 230, end: 118 },\n        { start: 118, end: 119 },\n        { start: 210, end: 202 },\n        { start: 202, end: 214 },\n        { start: 214, end: 210 },\n        { start: 84, end: 83 },\n        { start: 83, end: 17 },\n        { start: 17, end: 84 },\n        { start: 77, end: 76 },\n        { start: 76, end: 146 },\n        { start: 146, end: 77 },\n        { start: 161, end: 160 },\n        { start: 160, end: 30 },\n        { start: 30, end: 161 },\n        { start: 190, end: 56 },\n        { start: 56, end: 173 },\n        { start: 173, end: 190 },\n        { start: 182, end: 106 },\n        { start: 106, end: 194 },\n        { start: 194, end: 182 },\n        { start: 138, end: 135 },\n        { start: 135, end: 192 },\n        { start: 192, end: 138 },\n        { start: 129, end: 203 },\n        { start: 203, end: 98 },\n        { start: 98, end: 129 },\n        { start: 54, end: 21 },\n        { start: 21, end: 68 },\n        { start: 68, end: 54 },\n        { start: 5, end: 51 },\n        { start: 51, end: 4 },\n        { start: 4, end: 5 },\n        { start: 145, end: 144 },\n        { start: 144, end: 23 },\n        { start: 23, end: 145 },\n        { start: 90, end: 77 },\n        { start: 77, end: 91 },\n        { start: 91, end: 90 },\n        { start: 207, end: 205 },\n        { start: 205, end: 187 },\n        { start: 187, end: 207 },\n        { start: 83, end: 201 },\n        { start: 201, end: 18 },\n        { start: 18, end: 83 },\n        { start: 181, end: 91 },\n        { start: 91, end: 182 },\n        { start: 182, end: 181 },\n        { start: 180, end: 90 },\n        { start: 90, end: 181 },\n        { start: 181, end: 180 },\n        { start: 16, end: 85 },\n        { start: 85, end: 17 },\n        { start: 17, end: 16 },\n        { start: 205, end: 206 },\n        { start: 206, end: 36 },\n        { start: 36, end: 205 },\n        { start: 176, end: 148 },\n        { start: 148, end: 140 },\n        { start: 140, end: 176 },\n        { start: 165, end: 92 },\n        { start: 92, end: 39 },\n        { start: 39, end: 165 },\n        { start: 245, end: 193 },\n        { start: 193, end: 244 },\n        { start: 244, end: 245 },\n        { start: 27, end: 159 },\n        { start: 159, end: 28 },\n        { start: 28, end: 27 },\n        { start: 30, end: 247 },\n        { start: 247, end: 161 },\n        { start: 161, end: 30 },\n        { start: 174, end: 236 },\n        { start: 236, end: 196 },\n        { start: 196, end: 174 },\n        { start: 103, end: 54 },\n        { start: 54, end: 104 },\n        { start: 104, end: 103 },\n        { start: 55, end: 193 },\n        { start: 193, end: 8 },\n        { start: 8, end: 55 },\n        { start: 111, end: 117 },\n        { start: 117, end: 31 },\n        { start: 31, end: 111 },\n        { start: 221, end: 189 },\n        { start: 189, end: 55 },\n        { start: 55, end: 221 },\n        { start: 240, end: 98 },\n        { start: 98, end: 99 },\n        { start: 99, end: 240 },\n        { start: 142, end: 126 },\n        { start: 126, end: 100 },\n        { start: 100, end: 142 },\n        { start: 219, end: 166 },\n        { start: 166, end: 218 },\n        { start: 218, end: 219 },\n        { start: 112, end: 155 },\n        { start: 155, end: 26 },\n        { start: 26, end: 112 },\n        { start: 198, end: 209 },\n        { start: 209, end: 131 },\n        { start: 131, end: 198 },\n        { start: 169, end: 135 },\n        { start: 135, end: 150 },\n        { start: 150, end: 169 },\n        { start: 114, end: 47 },\n        { start: 47, end: 217 },\n        { start: 217, end: 114 },\n        { start: 224, end: 223 },\n        { start: 223, end: 53 },\n        { start: 53, end: 224 },\n        { start: 220, end: 45 },\n        { start: 45, end: 134 },\n        { start: 134, end: 220 },\n        { start: 32, end: 211 },\n        { start: 211, end: 140 },\n        { start: 140, end: 32 },\n        { start: 109, end: 67 },\n        { start: 67, end: 108 },\n        { start: 108, end: 109 },\n        { start: 146, end: 43 },\n        { start: 43, end: 91 },\n        { start: 91, end: 146 },\n        { start: 231, end: 230 },\n        { start: 230, end: 120 },\n        { start: 120, end: 231 },\n        { start: 113, end: 226 },\n        { start: 226, end: 247 },\n        { start: 247, end: 113 },\n        { start: 105, end: 63 },\n        { start: 63, end: 52 },\n        { start: 52, end: 105 },\n        { start: 241, end: 238 },\n        { start: 238, end: 242 },\n        { start: 242, end: 241 },\n        { start: 124, end: 46 },\n        { start: 46, end: 156 },\n        { start: 156, end: 124 },\n        { start: 95, end: 78 },\n        { start: 78, end: 96 },\n        { start: 96, end: 95 },\n        { start: 70, end: 46 },\n        { start: 46, end: 63 },\n        { start: 63, end: 70 },\n        { start: 116, end: 143 },\n        { start: 143, end: 227 },\n        { start: 227, end: 116 },\n        { start: 116, end: 123 },\n        { start: 123, end: 111 },\n        { start: 111, end: 116 },\n        { start: 1, end: 44 },\n        { start: 44, end: 19 },\n        { start: 19, end: 1 },\n        { start: 3, end: 236 },\n        { start: 236, end: 51 },\n        { start: 51, end: 3 },\n        { start: 207, end: 216 },\n        { start: 216, end: 205 },\n        { start: 205, end: 207 },\n        { start: 26, end: 154 },\n        { start: 154, end: 22 },\n        { start: 22, end: 26 },\n        { start: 165, end: 39 },\n        { start: 39, end: 167 },\n        { start: 167, end: 165 },\n        { start: 199, end: 200 },\n        { start: 200, end: 208 },\n        { start: 208, end: 199 },\n        { start: 101, end: 36 },\n        { start: 36, end: 100 },\n        { start: 100, end: 101 },\n        { start: 43, end: 57 },\n        { start: 57, end: 202 },\n        { start: 202, end: 43 },\n        { start: 242, end: 20 },\n        { start: 20, end: 99 },\n        { start: 99, end: 242 },\n        { start: 56, end: 28 },\n        { start: 28, end: 157 },\n        { start: 157, end: 56 },\n        { start: 124, end: 35 },\n        { start: 35, end: 113 },\n        { start: 113, end: 124 },\n        { start: 29, end: 160 },\n        { start: 160, end: 27 },\n        { start: 27, end: 29 },\n        { start: 211, end: 204 },\n        { start: 204, end: 210 },\n        { start: 210, end: 211 },\n        { start: 124, end: 113 },\n        { start: 113, end: 46 },\n        { start: 46, end: 124 },\n        { start: 106, end: 43 },\n        { start: 43, end: 204 },\n        { start: 204, end: 106 },\n        { start: 96, end: 62 },\n        { start: 62, end: 77 },\n        { start: 77, end: 96 },\n        { start: 227, end: 137 },\n        { start: 137, end: 116 },\n        { start: 116, end: 227 },\n        { start: 73, end: 41 },\n        { start: 41, end: 72 },\n        { start: 72, end: 73 },\n        { start: 36, end: 203 },\n        { start: 203, end: 142 },\n        { start: 142, end: 36 },\n        { start: 235, end: 64 },\n        { start: 64, end: 240 },\n        { start: 240, end: 235 },\n        { start: 48, end: 49 },\n        { start: 49, end: 64 },\n        { start: 64, end: 48 },\n        { start: 42, end: 41 },\n        { start: 41, end: 74 },\n        { start: 74, end: 42 },\n        { start: 214, end: 212 },\n        { start: 212, end: 207 },\n        { start: 207, end: 214 },\n        { start: 183, end: 42 },\n        { start: 42, end: 184 },\n        { start: 184, end: 183 },\n        { start: 210, end: 169 },\n        { start: 169, end: 211 },\n        { start: 211, end: 210 },\n        { start: 140, end: 170 },\n        { start: 170, end: 176 },\n        { start: 176, end: 140 },\n        { start: 104, end: 105 },\n        { start: 105, end: 69 },\n        { start: 69, end: 104 },\n        { start: 193, end: 122 },\n        { start: 122, end: 168 },\n        { start: 168, end: 193 },\n        { start: 50, end: 123 },\n        { start: 123, end: 187 },\n        { start: 187, end: 50 },\n        { start: 89, end: 96 },\n        { start: 96, end: 90 },\n        { start: 90, end: 89 },\n        { start: 66, end: 65 },\n        { start: 65, end: 107 },\n        { start: 107, end: 66 },\n        { start: 179, end: 89 },\n        { start: 89, end: 180 },\n        { start: 180, end: 179 },\n        { start: 119, end: 101 },\n        { start: 101, end: 120 },\n        { start: 120, end: 119 },\n        { start: 68, end: 63 },\n        { start: 63, end: 104 },\n        { start: 104, end: 68 },\n        { start: 234, end: 93 },\n        { start: 93, end: 227 },\n        { start: 227, end: 234 },\n        { start: 16, end: 15 },\n        { start: 15, end: 85 },\n        { start: 85, end: 16 },\n        { start: 209, end: 129 },\n        { start: 129, end: 49 },\n        { start: 49, end: 209 },\n        { start: 15, end: 14 },\n        { start: 14, end: 86 },\n        { start: 86, end: 15 },\n        { start: 107, end: 55 },\n        { start: 55, end: 9 },\n        { start: 9, end: 107 },\n        { start: 120, end: 100 },\n        { start: 100, end: 121 },\n        { start: 121, end: 120 },\n        { start: 153, end: 145 },\n        { start: 145, end: 22 },\n        { start: 22, end: 153 },\n        { start: 178, end: 88 },\n        { start: 88, end: 179 },\n        { start: 179, end: 178 },\n        { start: 197, end: 6 },\n        { start: 6, end: 196 },\n        { start: 196, end: 197 },\n        { start: 89, end: 88 },\n        { start: 88, end: 96 },\n        { start: 96, end: 89 },\n        { start: 135, end: 138 },\n        { start: 138, end: 136 },\n        { start: 136, end: 135 },\n        { start: 138, end: 215 },\n        { start: 215, end: 172 },\n        { start: 172, end: 138 },\n        { start: 218, end: 115 },\n        { start: 115, end: 219 },\n        { start: 219, end: 218 },\n        { start: 41, end: 42 },\n        { start: 42, end: 81 },\n        { start: 81, end: 41 },\n        { start: 5, end: 195 },\n        { start: 195, end: 51 },\n        { start: 51, end: 5 },\n        { start: 57, end: 43 },\n        { start: 43, end: 61 },\n        { start: 61, end: 57 },\n        { start: 208, end: 171 },\n        { start: 171, end: 199 },\n        { start: 199, end: 208 },\n        { start: 41, end: 81 },\n        { start: 81, end: 38 },\n        { start: 38, end: 41 },\n        { start: 224, end: 53 },\n        { start: 53, end: 225 },\n        { start: 225, end: 224 },\n        { start: 24, end: 144 },\n        { start: 144, end: 110 },\n        { start: 110, end: 24 },\n        { start: 105, end: 52 },\n        { start: 52, end: 66 },\n        { start: 66, end: 105 },\n        { start: 118, end: 229 },\n        { start: 229, end: 117 },\n        { start: 117, end: 118 },\n        { start: 227, end: 34 },\n        { start: 34, end: 234 },\n        { start: 234, end: 227 },\n        { start: 66, end: 107 },\n        { start: 107, end: 69 },\n        { start: 69, end: 66 },\n        { start: 10, end: 109 },\n        { start: 109, end: 151 },\n        { start: 151, end: 10 },\n        { start: 219, end: 48 },\n        { start: 48, end: 235 },\n        { start: 235, end: 219 },\n        { start: 183, end: 62 },\n        { start: 62, end: 191 },\n        { start: 191, end: 183 },\n        { start: 142, end: 129 },\n        { start: 129, end: 126 },\n        { start: 126, end: 142 },\n        { start: 116, end: 111 },\n        { start: 111, end: 143 },\n        { start: 143, end: 116 },\n        { start: 118, end: 117 },\n        { start: 117, end: 50 },\n        { start: 50, end: 118 },\n        { start: 223, end: 222 },\n        { start: 222, end: 52 },\n        { start: 52, end: 223 },\n        { start: 94, end: 19 },\n        { start: 19, end: 141 },\n        { start: 141, end: 94 },\n        { start: 222, end: 221 },\n        { start: 221, end: 65 },\n        { start: 65, end: 222 },\n        { start: 196, end: 3 },\n        { start: 3, end: 197 },\n        { start: 197, end: 196 },\n        { start: 45, end: 220 },\n        { start: 220, end: 44 },\n        { start: 44, end: 45 },\n        { start: 156, end: 70 },\n        { start: 70, end: 139 },\n        { start: 139, end: 156 },\n        { start: 188, end: 122 },\n        { start: 122, end: 245 },\n        { start: 245, end: 188 },\n        { start: 139, end: 71 },\n        { start: 71, end: 162 },\n        { start: 162, end: 139 },\n        { start: 149, end: 170 },\n        { start: 170, end: 150 },\n        { start: 150, end: 149 },\n        { start: 122, end: 188 },\n        { start: 188, end: 196 },\n        { start: 196, end: 122 },\n        { start: 206, end: 216 },\n        { start: 216, end: 92 },\n        { start: 92, end: 206 },\n        { start: 164, end: 2 },\n        { start: 2, end: 167 },\n        { start: 167, end: 164 },\n        { start: 242, end: 141 },\n        { start: 141, end: 241 },\n        { start: 241, end: 242 },\n        { start: 0, end: 164 },\n        { start: 164, end: 37 },\n        { start: 37, end: 0 },\n        { start: 11, end: 72 },\n        { start: 72, end: 12 },\n        { start: 12, end: 11 },\n        { start: 12, end: 38 },\n        { start: 38, end: 13 },\n        { start: 13, end: 12 },\n        { start: 70, end: 63 },\n        { start: 63, end: 71 },\n        { start: 71, end: 70 },\n        { start: 31, end: 226 },\n        { start: 226, end: 111 },\n        { start: 111, end: 31 },\n        { start: 36, end: 101 },\n        { start: 101, end: 205 },\n        { start: 205, end: 36 },\n        { start: 203, end: 206 },\n        { start: 206, end: 165 },\n        { start: 165, end: 203 },\n        { start: 126, end: 209 },\n        { start: 209, end: 217 },\n        { start: 217, end: 126 },\n        { start: 98, end: 165 },\n        { start: 165, end: 97 },\n        { start: 97, end: 98 },\n        { start: 237, end: 220 },\n        { start: 220, end: 218 },\n        { start: 218, end: 237 },\n        { start: 237, end: 239 },\n        { start: 239, end: 241 },\n        { start: 241, end: 237 },\n        { start: 210, end: 214 },\n        { start: 214, end: 169 },\n        { start: 169, end: 210 },\n        { start: 140, end: 171 },\n        { start: 171, end: 32 },\n        { start: 32, end: 140 },\n        { start: 241, end: 125 },\n        { start: 125, end: 237 },\n        { start: 237, end: 241 },\n        { start: 179, end: 86 },\n        { start: 86, end: 178 },\n        { start: 178, end: 179 },\n        { start: 180, end: 85 },\n        { start: 85, end: 179 },\n        { start: 179, end: 180 },\n        { start: 181, end: 84 },\n        { start: 84, end: 180 },\n        { start: 180, end: 181 },\n        { start: 182, end: 83 },\n        { start: 83, end: 181 },\n        { start: 181, end: 182 },\n        { start: 194, end: 201 },\n        { start: 201, end: 182 },\n        { start: 182, end: 194 },\n        { start: 177, end: 137 },\n        { start: 137, end: 132 },\n        { start: 132, end: 177 },\n        { start: 184, end: 76 },\n        { start: 76, end: 183 },\n        { start: 183, end: 184 },\n        { start: 185, end: 61 },\n        { start: 61, end: 184 },\n        { start: 184, end: 185 },\n        { start: 186, end: 57 },\n        { start: 57, end: 185 },\n        { start: 185, end: 186 },\n        { start: 216, end: 212 },\n        { start: 212, end: 186 },\n        { start: 186, end: 216 },\n        { start: 192, end: 214 },\n        { start: 214, end: 187 },\n        { start: 187, end: 192 },\n        { start: 139, end: 34 },\n        { start: 34, end: 156 },\n        { start: 156, end: 139 },\n        { start: 218, end: 79 },\n        { start: 79, end: 237 },\n        { start: 237, end: 218 },\n        { start: 147, end: 123 },\n        { start: 123, end: 177 },\n        { start: 177, end: 147 },\n        { start: 45, end: 44 },\n        { start: 44, end: 4 },\n        { start: 4, end: 45 },\n        { start: 208, end: 201 },\n        { start: 201, end: 32 },\n        { start: 32, end: 208 },\n        { start: 98, end: 64 },\n        { start: 64, end: 129 },\n        { start: 129, end: 98 },\n        { start: 192, end: 213 },\n        { start: 213, end: 138 },\n        { start: 138, end: 192 },\n        { start: 235, end: 59 },\n        { start: 59, end: 219 },\n        { start: 219, end: 235 },\n        { start: 141, end: 242 },\n        { start: 242, end: 97 },\n        { start: 97, end: 141 },\n        { start: 97, end: 2 },\n        { start: 2, end: 141 },\n        { start: 141, end: 97 },\n        { start: 240, end: 75 },\n        { start: 75, end: 235 },\n        { start: 235, end: 240 },\n        { start: 229, end: 24 },\n        { start: 24, end: 228 },\n        { start: 228, end: 229 },\n        { start: 31, end: 25 },\n        { start: 25, end: 226 },\n        { start: 226, end: 31 },\n        { start: 230, end: 23 },\n        { start: 23, end: 229 },\n        { start: 229, end: 230 },\n        { start: 231, end: 22 },\n        { start: 22, end: 230 },\n        { start: 230, end: 231 },\n        { start: 232, end: 26 },\n        { start: 26, end: 231 },\n        { start: 231, end: 232 },\n        { start: 233, end: 112 },\n        { start: 112, end: 232 },\n        { start: 232, end: 233 },\n        { start: 244, end: 189 },\n        { start: 189, end: 243 },\n        { start: 243, end: 244 },\n        { start: 189, end: 221 },\n        { start: 221, end: 190 },\n        { start: 190, end: 189 },\n        { start: 222, end: 28 },\n        { start: 28, end: 221 },\n        { start: 221, end: 222 },\n        { start: 223, end: 27 },\n        { start: 27, end: 222 },\n        { start: 222, end: 223 },\n        { start: 224, end: 29 },\n        { start: 29, end: 223 },\n        { start: 223, end: 224 },\n        { start: 225, end: 30 },\n        { start: 30, end: 224 },\n        { start: 224, end: 225 },\n        { start: 113, end: 247 },\n        { start: 247, end: 225 },\n        { start: 225, end: 113 },\n        { start: 99, end: 60 },\n        { start: 60, end: 240 },\n        { start: 240, end: 99 },\n        { start: 213, end: 147 },\n        { start: 147, end: 215 },\n        { start: 215, end: 213 },\n        { start: 60, end: 20 },\n        { start: 20, end: 166 },\n        { start: 166, end: 60 },\n        { start: 192, end: 187 },\n        { start: 187, end: 213 },\n        { start: 213, end: 192 },\n        { start: 243, end: 112 },\n        { start: 112, end: 244 },\n        { start: 244, end: 243 },\n        { start: 244, end: 233 },\n        { start: 233, end: 245 },\n        { start: 245, end: 244 },\n        { start: 245, end: 128 },\n        { start: 128, end: 188 },\n        { start: 188, end: 245 },\n        { start: 188, end: 114 },\n        { start: 114, end: 174 },\n        { start: 174, end: 188 },\n        { start: 134, end: 131 },\n        { start: 131, end: 220 },\n        { start: 220, end: 134 },\n        { start: 174, end: 217 },\n        { start: 217, end: 236 },\n        { start: 236, end: 174 },\n        { start: 236, end: 198 },\n        { start: 198, end: 134 },\n        { start: 134, end: 236 },\n        { start: 215, end: 177 },\n        { start: 177, end: 58 },\n        { start: 58, end: 215 },\n        { start: 156, end: 143 },\n        { start: 143, end: 124 },\n        { start: 124, end: 156 },\n        { start: 25, end: 110 },\n        { start: 110, end: 7 },\n        { start: 7, end: 25 },\n        { start: 31, end: 228 },\n        { start: 228, end: 25 },\n        { start: 25, end: 31 },\n        { start: 264, end: 356 },\n        { start: 356, end: 368 },\n        { start: 368, end: 264 },\n        { start: 0, end: 11 },\n        { start: 11, end: 267 },\n        { start: 267, end: 0 },\n        { start: 451, end: 452 },\n        { start: 452, end: 349 },\n        { start: 349, end: 451 },\n        { start: 267, end: 302 },\n        { start: 302, end: 269 },\n        { start: 269, end: 267 },\n        { start: 350, end: 357 },\n        { start: 357, end: 277 },\n        { start: 277, end: 350 },\n        { start: 350, end: 452 },\n        { start: 452, end: 357 },\n        { start: 357, end: 350 },\n        { start: 299, end: 333 },\n        { start: 333, end: 297 },\n        { start: 297, end: 299 },\n        { start: 396, end: 175 },\n        { start: 175, end: 377 },\n        { start: 377, end: 396 },\n        { start: 280, end: 347 },\n        { start: 347, end: 330 },\n        { start: 330, end: 280 },\n        { start: 269, end: 303 },\n        { start: 303, end: 270 },\n        { start: 270, end: 269 },\n        { start: 151, end: 9 },\n        { start: 9, end: 337 },\n        { start: 337, end: 151 },\n        { start: 344, end: 278 },\n        { start: 278, end: 360 },\n        { start: 360, end: 344 },\n        { start: 424, end: 418 },\n        { start: 418, end: 431 },\n        { start: 431, end: 424 },\n        { start: 270, end: 304 },\n        { start: 304, end: 409 },\n        { start: 409, end: 270 },\n        { start: 272, end: 310 },\n        { start: 310, end: 407 },\n        { start: 407, end: 272 },\n        { start: 322, end: 270 },\n        { start: 270, end: 410 },\n        { start: 410, end: 322 },\n        { start: 449, end: 450 },\n        { start: 450, end: 347 },\n        { start: 347, end: 449 },\n        { start: 432, end: 422 },\n        { start: 422, end: 434 },\n        { start: 434, end: 432 },\n        { start: 18, end: 313 },\n        { start: 313, end: 17 },\n        { start: 17, end: 18 },\n        { start: 291, end: 306 },\n        { start: 306, end: 375 },\n        { start: 375, end: 291 },\n        { start: 259, end: 387 },\n        { start: 387, end: 260 },\n        { start: 260, end: 259 },\n        { start: 424, end: 335 },\n        { start: 335, end: 418 },\n        { start: 418, end: 424 },\n        { start: 434, end: 364 },\n        { start: 364, end: 416 },\n        { start: 416, end: 434 },\n        { start: 391, end: 423 },\n        { start: 423, end: 327 },\n        { start: 327, end: 391 },\n        { start: 301, end: 251 },\n        { start: 251, end: 298 },\n        { start: 298, end: 301 },\n        { start: 275, end: 281 },\n        { start: 281, end: 4 },\n        { start: 4, end: 275 },\n        { start: 254, end: 373 },\n        { start: 373, end: 253 },\n        { start: 253, end: 254 },\n        { start: 375, end: 307 },\n        { start: 307, end: 321 },\n        { start: 321, end: 375 },\n        { start: 280, end: 425 },\n        { start: 425, end: 411 },\n        { start: 411, end: 280 },\n        { start: 200, end: 421 },\n        { start: 421, end: 18 },\n        { start: 18, end: 200 },\n        { start: 335, end: 321 },\n        { start: 321, end: 406 },\n        { start: 406, end: 335 },\n        { start: 321, end: 320 },\n        { start: 320, end: 405 },\n        { start: 405, end: 321 },\n        { start: 314, end: 315 },\n        { start: 315, end: 17 },\n        { start: 17, end: 314 },\n        { start: 423, end: 426 },\n        { start: 426, end: 266 },\n        { start: 266, end: 423 },\n        { start: 396, end: 377 },\n        { start: 377, end: 369 },\n        { start: 369, end: 396 },\n        { start: 270, end: 322 },\n        { start: 322, end: 269 },\n        { start: 269, end: 270 },\n        { start: 413, end: 417 },\n        { start: 417, end: 464 },\n        { start: 464, end: 413 },\n        { start: 385, end: 386 },\n        { start: 386, end: 258 },\n        { start: 258, end: 385 },\n        { start: 248, end: 456 },\n        { start: 456, end: 419 },\n        { start: 419, end: 248 },\n        { start: 298, end: 284 },\n        { start: 284, end: 333 },\n        { start: 333, end: 298 },\n        { start: 168, end: 417 },\n        { start: 417, end: 8 },\n        { start: 8, end: 168 },\n        { start: 448, end: 346 },\n        { start: 346, end: 261 },\n        { start: 261, end: 448 },\n        { start: 417, end: 413 },\n        { start: 413, end: 285 },\n        { start: 285, end: 417 },\n        { start: 326, end: 327 },\n        { start: 327, end: 328 },\n        { start: 328, end: 326 },\n        { start: 277, end: 355 },\n        { start: 355, end: 329 },\n        { start: 329, end: 277 },\n        { start: 309, end: 392 },\n        { start: 392, end: 438 },\n        { start: 438, end: 309 },\n        { start: 381, end: 382 },\n        { start: 382, end: 256 },\n        { start: 256, end: 381 },\n        { start: 279, end: 429 },\n        { start: 429, end: 360 },\n        { start: 360, end: 279 },\n        { start: 365, end: 364 },\n        { start: 364, end: 379 },\n        { start: 379, end: 365 },\n        { start: 355, end: 277 },\n        { start: 277, end: 437 },\n        { start: 437, end: 355 },\n        { start: 282, end: 443 },\n        { start: 443, end: 283 },\n        { start: 283, end: 282 },\n        { start: 281, end: 275 },\n        { start: 275, end: 363 },\n        { start: 363, end: 281 },\n        { start: 395, end: 431 },\n        { start: 431, end: 369 },\n        { start: 369, end: 395 },\n        { start: 299, end: 297 },\n        { start: 297, end: 337 },\n        { start: 337, end: 299 },\n        { start: 335, end: 273 },\n        { start: 273, end: 321 },\n        { start: 321, end: 335 },\n        { start: 348, end: 450 },\n        { start: 450, end: 349 },\n        { start: 349, end: 348 },\n        { start: 359, end: 446 },\n        { start: 446, end: 467 },\n        { start: 467, end: 359 },\n        { start: 283, end: 293 },\n        { start: 293, end: 282 },\n        { start: 282, end: 283 },\n        { start: 250, end: 458 },\n        { start: 458, end: 462 },\n        { start: 462, end: 250 },\n        { start: 300, end: 276 },\n        { start: 276, end: 383 },\n        { start: 383, end: 300 },\n        { start: 292, end: 308 },\n        { start: 308, end: 325 },\n        { start: 325, end: 292 },\n        { start: 283, end: 276 },\n        { start: 276, end: 293 },\n        { start: 293, end: 283 },\n        { start: 264, end: 372 },\n        { start: 372, end: 447 },\n        { start: 447, end: 264 },\n        { start: 346, end: 352 },\n        { start: 352, end: 340 },\n        { start: 340, end: 346 },\n        { start: 354, end: 274 },\n        { start: 274, end: 19 },\n        { start: 19, end: 354 },\n        { start: 363, end: 456 },\n        { start: 456, end: 281 },\n        { start: 281, end: 363 },\n        { start: 426, end: 436 },\n        { start: 436, end: 425 },\n        { start: 425, end: 426 },\n        { start: 380, end: 381 },\n        { start: 381, end: 252 },\n        { start: 252, end: 380 },\n        { start: 267, end: 269 },\n        { start: 269, end: 393 },\n        { start: 393, end: 267 },\n        { start: 421, end: 200 },\n        { start: 200, end: 428 },\n        { start: 428, end: 421 },\n        { start: 371, end: 266 },\n        { start: 266, end: 329 },\n        { start: 329, end: 371 },\n        { start: 432, end: 287 },\n        { start: 287, end: 422 },\n        { start: 422, end: 432 },\n        { start: 290, end: 250 },\n        { start: 250, end: 328 },\n        { start: 328, end: 290 },\n        { start: 385, end: 258 },\n        { start: 258, end: 384 },\n        { start: 384, end: 385 },\n        { start: 446, end: 265 },\n        { start: 265, end: 342 },\n        { start: 342, end: 446 },\n        { start: 386, end: 387 },\n        { start: 387, end: 257 },\n        { start: 257, end: 386 },\n        { start: 422, end: 424 },\n        { start: 424, end: 430 },\n        { start: 430, end: 422 },\n        { start: 445, end: 342 },\n        { start: 342, end: 276 },\n        { start: 276, end: 445 },\n        { start: 422, end: 273 },\n        { start: 273, end: 424 },\n        { start: 424, end: 422 },\n        { start: 306, end: 292 },\n        { start: 292, end: 307 },\n        { start: 307, end: 306 },\n        { start: 352, end: 366 },\n        { start: 366, end: 345 },\n        { start: 345, end: 352 },\n        { start: 268, end: 271 },\n        { start: 271, end: 302 },\n        { start: 302, end: 268 },\n        { start: 358, end: 423 },\n        { start: 423, end: 371 },\n        { start: 371, end: 358 },\n        { start: 327, end: 294 },\n        { start: 294, end: 460 },\n        { start: 460, end: 327 },\n        { start: 331, end: 279 },\n        { start: 279, end: 294 },\n        { start: 294, end: 331 },\n        { start: 303, end: 271 },\n        { start: 271, end: 304 },\n        { start: 304, end: 303 },\n        { start: 436, end: 432 },\n        { start: 432, end: 427 },\n        { start: 427, end: 436 },\n        { start: 304, end: 272 },\n        { start: 272, end: 408 },\n        { start: 408, end: 304 },\n        { start: 395, end: 394 },\n        { start: 394, end: 431 },\n        { start: 431, end: 395 },\n        { start: 378, end: 395 },\n        { start: 395, end: 400 },\n        { start: 400, end: 378 },\n        { start: 296, end: 334 },\n        { start: 334, end: 299 },\n        { start: 299, end: 296 },\n        { start: 6, end: 351 },\n        { start: 351, end: 168 },\n        { start: 168, end: 6 },\n        { start: 376, end: 352 },\n        { start: 352, end: 411 },\n        { start: 411, end: 376 },\n        { start: 307, end: 325 },\n        { start: 325, end: 320 },\n        { start: 320, end: 307 },\n        { start: 285, end: 295 },\n        { start: 295, end: 336 },\n        { start: 336, end: 285 },\n        { start: 320, end: 319 },\n        { start: 319, end: 404 },\n        { start: 404, end: 320 },\n        { start: 329, end: 330 },\n        { start: 330, end: 349 },\n        { start: 349, end: 329 },\n        { start: 334, end: 293 },\n        { start: 293, end: 333 },\n        { start: 333, end: 334 },\n        { start: 366, end: 323 },\n        { start: 323, end: 447 },\n        { start: 447, end: 366 },\n        { start: 316, end: 15 },\n        { start: 15, end: 315 },\n        { start: 315, end: 316 },\n        { start: 331, end: 358 },\n        { start: 358, end: 279 },\n        { start: 279, end: 331 },\n        { start: 317, end: 14 },\n        { start: 14, end: 316 },\n        { start: 316, end: 317 },\n        { start: 8, end: 285 },\n        { start: 285, end: 9 },\n        { start: 9, end: 8 },\n        { start: 277, end: 329 },\n        { start: 329, end: 350 },\n        { start: 350, end: 277 },\n        { start: 253, end: 374 },\n        { start: 374, end: 252 },\n        { start: 252, end: 253 },\n        { start: 319, end: 318 },\n        { start: 318, end: 403 },\n        { start: 403, end: 319 },\n        { start: 351, end: 6 },\n        { start: 6, end: 419 },\n        { start: 419, end: 351 },\n        { start: 324, end: 318 },\n        { start: 318, end: 325 },\n        { start: 325, end: 324 },\n        { start: 397, end: 367 },\n        { start: 367, end: 365 },\n        { start: 365, end: 397 },\n        { start: 288, end: 435 },\n        { start: 435, end: 397 },\n        { start: 397, end: 288 },\n        { start: 278, end: 344 },\n        { start: 344, end: 439 },\n        { start: 439, end: 278 },\n        { start: 310, end: 272 },\n        { start: 272, end: 311 },\n        { start: 311, end: 310 },\n        { start: 248, end: 195 },\n        { start: 195, end: 281 },\n        { start: 281, end: 248 },\n        { start: 375, end: 273 },\n        { start: 273, end: 291 },\n        { start: 291, end: 375 },\n        { start: 175, end: 396 },\n        { start: 396, end: 199 },\n        { start: 199, end: 175 },\n        { start: 312, end: 311 },\n        { start: 311, end: 268 },\n        { start: 268, end: 312 },\n        { start: 276, end: 283 },\n        { start: 283, end: 445 },\n        { start: 445, end: 276 },\n        { start: 390, end: 373 },\n        { start: 373, end: 339 },\n        { start: 339, end: 390 },\n        { start: 295, end: 282 },\n        { start: 282, end: 296 },\n        { start: 296, end: 295 },\n        { start: 448, end: 449 },\n        { start: 449, end: 346 },\n        { start: 346, end: 448 },\n        { start: 356, end: 264 },\n        { start: 264, end: 454 },\n        { start: 454, end: 356 },\n        { start: 337, end: 336 },\n        { start: 336, end: 299 },\n        { start: 299, end: 337 },\n        { start: 337, end: 338 },\n        { start: 338, end: 151 },\n        { start: 151, end: 337 },\n        { start: 294, end: 278 },\n        { start: 278, end: 455 },\n        { start: 455, end: 294 },\n        { start: 308, end: 292 },\n        { start: 292, end: 415 },\n        { start: 415, end: 308 },\n        { start: 429, end: 358 },\n        { start: 358, end: 355 },\n        { start: 355, end: 429 },\n        { start: 265, end: 340 },\n        { start: 340, end: 372 },\n        { start: 372, end: 265 },\n        { start: 352, end: 346 },\n        { start: 346, end: 280 },\n        { start: 280, end: 352 },\n        { start: 295, end: 442 },\n        { start: 442, end: 282 },\n        { start: 282, end: 295 },\n        { start: 354, end: 19 },\n        { start: 19, end: 370 },\n        { start: 370, end: 354 },\n        { start: 285, end: 441 },\n        { start: 441, end: 295 },\n        { start: 295, end: 285 },\n        { start: 195, end: 248 },\n        { start: 248, end: 197 },\n        { start: 197, end: 195 },\n        { start: 457, end: 440 },\n        { start: 440, end: 274 },\n        { start: 274, end: 457 },\n        { start: 301, end: 300 },\n        { start: 300, end: 368 },\n        { start: 368, end: 301 },\n        { start: 417, end: 351 },\n        { start: 351, end: 465 },\n        { start: 465, end: 417 },\n        { start: 251, end: 301 },\n        { start: 301, end: 389 },\n        { start: 389, end: 251 },\n        { start: 394, end: 395 },\n        { start: 395, end: 379 },\n        { start: 379, end: 394 },\n        { start: 399, end: 412 },\n        { start: 412, end: 419 },\n        { start: 419, end: 399 },\n        { start: 410, end: 436 },\n        { start: 436, end: 322 },\n        { start: 322, end: 410 },\n        { start: 326, end: 2 },\n        { start: 2, end: 393 },\n        { start: 393, end: 326 },\n        { start: 354, end: 370 },\n        { start: 370, end: 461 },\n        { start: 461, end: 354 },\n        { start: 393, end: 164 },\n        { start: 164, end: 267 },\n        { start: 267, end: 393 },\n        { start: 268, end: 302 },\n        { start: 302, end: 12 },\n        { start: 12, end: 268 },\n        { start: 312, end: 268 },\n        { start: 268, end: 13 },\n        { start: 13, end: 312 },\n        { start: 298, end: 293 },\n        { start: 293, end: 301 },\n        { start: 301, end: 298 },\n        { start: 265, end: 446 },\n        { start: 446, end: 340 },\n        { start: 340, end: 265 },\n        { start: 280, end: 330 },\n        { start: 330, end: 425 },\n        { start: 425, end: 280 },\n        { start: 322, end: 426 },\n        { start: 426, end: 391 },\n        { start: 391, end: 322 },\n        { start: 420, end: 429 },\n        { start: 429, end: 437 },\n        { start: 437, end: 420 },\n        { start: 393, end: 391 },\n        { start: 391, end: 326 },\n        { start: 326, end: 393 },\n        { start: 344, end: 440 },\n        { start: 440, end: 438 },\n        { start: 438, end: 344 },\n        { start: 458, end: 459 },\n        { start: 459, end: 461 },\n        { start: 461, end: 458 },\n        { start: 364, end: 434 },\n        { start: 434, end: 394 },\n        { start: 394, end: 364 },\n        { start: 428, end: 396 },\n        { start: 396, end: 262 },\n        { start: 262, end: 428 },\n        { start: 274, end: 354 },\n        { start: 354, end: 457 },\n        { start: 457, end: 274 },\n        { start: 317, end: 316 },\n        { start: 316, end: 402 },\n        { start: 402, end: 317 },\n        { start: 316, end: 315 },\n        { start: 315, end: 403 },\n        { start: 403, end: 316 },\n        { start: 315, end: 314 },\n        { start: 314, end: 404 },\n        { start: 404, end: 315 },\n        { start: 314, end: 313 },\n        { start: 313, end: 405 },\n        { start: 405, end: 314 },\n        { start: 313, end: 421 },\n        { start: 421, end: 406 },\n        { start: 406, end: 313 },\n        { start: 323, end: 366 },\n        { start: 366, end: 361 },\n        { start: 361, end: 323 },\n        { start: 292, end: 306 },\n        { start: 306, end: 407 },\n        { start: 407, end: 292 },\n        { start: 306, end: 291 },\n        { start: 291, end: 408 },\n        { start: 408, end: 306 },\n        { start: 291, end: 287 },\n        { start: 287, end: 409 },\n        { start: 409, end: 291 },\n        { start: 287, end: 432 },\n        { start: 432, end: 410 },\n        { start: 410, end: 287 },\n        { start: 427, end: 434 },\n        { start: 434, end: 411 },\n        { start: 411, end: 427 },\n        { start: 372, end: 264 },\n        { start: 264, end: 383 },\n        { start: 383, end: 372 },\n        { start: 459, end: 309 },\n        { start: 309, end: 457 },\n        { start: 457, end: 459 },\n        { start: 366, end: 352 },\n        { start: 352, end: 401 },\n        { start: 401, end: 366 },\n        { start: 1, end: 274 },\n        { start: 274, end: 4 },\n        { start: 4, end: 1 },\n        { start: 418, end: 421 },\n        { start: 421, end: 262 },\n        { start: 262, end: 418 },\n        { start: 331, end: 294 },\n        { start: 294, end: 358 },\n        { start: 358, end: 331 },\n        { start: 435, end: 433 },\n        { start: 433, end: 367 },\n        { start: 367, end: 435 },\n        { start: 392, end: 289 },\n        { start: 289, end: 439 },\n        { start: 439, end: 392 },\n        { start: 328, end: 462 },\n        { start: 462, end: 326 },\n        { start: 326, end: 328 },\n        { start: 94, end: 2 },\n        { start: 2, end: 370 },\n        { start: 370, end: 94 },\n        { start: 289, end: 305 },\n        { start: 305, end: 455 },\n        { start: 455, end: 289 },\n        { start: 339, end: 254 },\n        { start: 254, end: 448 },\n        { start: 448, end: 339 },\n        { start: 359, end: 255 },\n        { start: 255, end: 446 },\n        { start: 446, end: 359 },\n        { start: 254, end: 253 },\n        { start: 253, end: 449 },\n        { start: 449, end: 254 },\n        { start: 253, end: 252 },\n        { start: 252, end: 450 },\n        { start: 450, end: 253 },\n        { start: 252, end: 256 },\n        { start: 256, end: 451 },\n        { start: 451, end: 252 },\n        { start: 256, end: 341 },\n        { start: 341, end: 452 },\n        { start: 452, end: 256 },\n        { start: 414, end: 413 },\n        { start: 413, end: 463 },\n        { start: 463, end: 414 },\n        { start: 286, end: 441 },\n        { start: 441, end: 414 },\n        { start: 414, end: 286 },\n        { start: 286, end: 258 },\n        { start: 258, end: 441 },\n        { start: 441, end: 286 },\n        { start: 258, end: 257 },\n        { start: 257, end: 442 },\n        { start: 442, end: 258 },\n        { start: 257, end: 259 },\n        { start: 259, end: 443 },\n        { start: 443, end: 257 },\n        { start: 259, end: 260 },\n        { start: 260, end: 444 },\n        { start: 444, end: 259 },\n        { start: 260, end: 467 },\n        { start: 467, end: 445 },\n        { start: 445, end: 260 },\n        { start: 309, end: 459 },\n        { start: 459, end: 250 },\n        { start: 250, end: 309 },\n        { start: 305, end: 289 },\n        { start: 289, end: 290 },\n        { start: 290, end: 305 },\n        { start: 305, end: 290 },\n        { start: 290, end: 460 },\n        { start: 460, end: 305 },\n        { start: 401, end: 376 },\n        { start: 376, end: 435 },\n        { start: 435, end: 401 },\n        { start: 309, end: 250 },\n        { start: 250, end: 392 },\n        { start: 392, end: 309 },\n        { start: 376, end: 411 },\n        { start: 411, end: 433 },\n        { start: 433, end: 376 },\n        { start: 453, end: 341 },\n        { start: 341, end: 464 },\n        { start: 464, end: 453 },\n        { start: 357, end: 453 },\n        { start: 453, end: 465 },\n        { start: 465, end: 357 },\n        { start: 343, end: 357 },\n        { start: 357, end: 412 },\n        { start: 412, end: 343 },\n        { start: 437, end: 343 },\n        { start: 343, end: 399 },\n        { start: 399, end: 437 },\n        { start: 344, end: 360 },\n        { start: 360, end: 440 },\n        { start: 440, end: 344 },\n        { start: 420, end: 437 },\n        { start: 437, end: 456 },\n        { start: 456, end: 420 },\n        { start: 360, end: 420 },\n        { start: 420, end: 363 },\n        { start: 363, end: 360 },\n        { start: 361, end: 401 },\n        { start: 401, end: 288 },\n        { start: 288, end: 361 },\n        { start: 265, end: 372 },\n        { start: 372, end: 353 },\n        { start: 353, end: 265 },\n        { start: 390, end: 339 },\n        { start: 339, end: 249 },\n        { start: 249, end: 390 },\n        { start: 339, end: 448 },\n        { start: 448, end: 255 },\n        { start: 255, end: 339 },\n    ]);\nvar face_landmarker_options = {};\nObject.defineProperty(face_landmarker_options, '__esModule', { value: !0 });\nvar face_landmarker_result = {};\nObject.defineProperty(face_landmarker_result, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.FaceLandmarker = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = classification_pb,\n            n = landmark_pb,\n            s = base_options_pb,\n            p = face_detector_graph_options_pb,\n            d = face_geometry_pb,\n            l = face_landmarker_graph_options_pb,\n            g = face_landmarks_detector_graph_options_pb,\n            c = classifier_result,\n            u = landmark_result,\n            m = vision_task_runner,\n            f = face_landmarks_connections;\n        r(face_landmarker_options, e), r(face_landmarker_result, e);\n        const h = 'image_in',\n            y = 'norm_rect',\n            b = 'face_landmarks',\n            _ = 'blendshapes',\n            O = 'face_geometry',\n            F = 0.5;\n        class M extends m.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return m.VisionTaskRunner.createVisionInstance(M, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return m.VisionTaskRunner.createVisionInstance(M, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return m.VisionTaskRunner.createVisionInstance(M, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new m.VisionGraphRunner(e, t), h, y, !1),\n                    (this.result = {\n                        faceLandmarks: [],\n                        faceBlendshapes: [],\n                        facialTransformationMatrixes: [],\n                    }),\n                    (this.outputFaceBlendshapes = !1),\n                    (this.outputFacialTransformationMatrixes = !1),\n                    (this.options = new l.FaceLandmarkerGraphOptions()),\n                    this.options.setBaseOptions(new s.BaseOptions()),\n                    (this.faceLandmarksDetectorGraphOptions = new g.FaceLandmarksDetectorGraphOptions()),\n                    this.options.setFaceLandmarksDetectorGraphOptions(\n                        this.faceLandmarksDetectorGraphOptions\n                    ),\n                    (this.faceDetectorGraphOptions = new p.FaceDetectorGraphOptions()),\n                    this.options.setFaceDetectorGraphOptions(this.faceDetectorGraphOptions),\n                    this.initDefaults();\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                var t, r, o, i;\n                return (\n                    'numFaces' in e &&\n                        this.faceDetectorGraphOptions.setNumFaces(\n                            null !== (t = e.numFaces) && void 0 !== t ? t : 1\n                        ),\n                    'minFaceDetectionConfidence' in e &&\n                        this.faceDetectorGraphOptions.setMinDetectionConfidence(\n                            null !== (r = e.minFaceDetectionConfidence) && void 0 !== r ? r : F\n                        ),\n                    'minTrackingConfidence' in e &&\n                        this.options.setMinTrackingConfidence(\n                            null !== (o = e.minTrackingConfidence) && void 0 !== o ? o : F\n                        ),\n                    'minFacePresenceConfidence' in e &&\n                        this.faceLandmarksDetectorGraphOptions.setMinDetectionConfidence(\n                            null !== (i = e.minFacePresenceConfidence) && void 0 !== i ? i : F\n                        ),\n                    'outputFaceBlendshapes' in e &&\n                        (this.outputFaceBlendshapes = !!e.outputFaceBlendshapes),\n                    'outputFacialTransformationMatrixes' in e &&\n                        (this.outputFacialTransformationMatrixes = !!e.outputFacialTransformationMatrixes),\n                    this.applyOptions(e)\n                );\n            }\n            detect(e, t) {\n                return this.resetResults(), this.processImageData(e, t), this.result;\n            }\n            detectForVideo(e, t, r) {\n                return this.resetResults(), this.processVideoData(e, r, t), this.result;\n            }\n            resetResults() {\n                this.result = {\n                    faceLandmarks: [],\n                    faceBlendshapes: [],\n                    facialTransformationMatrixes: [],\n                };\n            }\n            initDefaults() {\n                this.faceDetectorGraphOptions.setNumFaces(1),\n                    this.faceDetectorGraphOptions.setMinDetectionConfidence(F),\n                    this.faceLandmarksDetectorGraphOptions.setMinDetectionConfidence(F),\n                    this.options.setMinTrackingConfidence(F);\n            }\n            addJsLandmarks(e) {\n                for (const t of e) {\n                    const e = n.NormalizedLandmarkList.deserializeBinary(t);\n                    this.result.faceLandmarks.push((0, u.convertToLandmarks)(e));\n                }\n            }\n            addBlenshape(e) {\n                var t;\n                if (this.outputFaceBlendshapes)\n                    for (const r of e) {\n                        const e = a.ClassificationList.deserializeBinary(r);\n                        this.result.faceBlendshapes.push(\n                            (0, c.convertFromClassifications)(\n                                null !== (t = e.getClassificationList()) && void 0 !== t ? t : []\n                            )\n                        );\n                    }\n            }\n            addFacialTransformationMatrixes(e) {\n                var t, r, o;\n                if (this.outputFacialTransformationMatrixes)\n                    for (const i of e) {\n                        const e = d.FaceGeometry.deserializeBinary(i).getPoseTransformMatrix();\n                        e &&\n                            this.result.facialTransformationMatrixes.push({\n                                rows: null !== (t = e.getRows()) && void 0 !== t ? t : 0,\n                                columns: null !== (r = e.getCols()) && void 0 !== r ? r : 0,\n                                data: null !== (o = e.getPackedDataList()) && void 0 !== o ? o : [],\n                            });\n                    }\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(h), e.addInputStream(y), e.addOutputStream(b);\n                const t = new i.CalculatorOptions();\n                t.setExtension(l.FaceLandmarkerGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.face_landmarker.FaceLandmarkerGraph'),\n                    r.addInputStream('IMAGE:' + h),\n                    r.addInputStream('NORM_RECT:' + y),\n                    r.addOutputStream('NORM_LANDMARKS:' + b),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.graphRunner.attachProtoVectorListener(b, (e, t) => {\n                        this.addJsLandmarks(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(b, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    }),\n                    this.outputFaceBlendshapes &&\n                        (e.addOutputStream(_),\n                        r.addOutputStream('BLENDSHAPES:' + _),\n                        this.graphRunner.attachProtoVectorListener(_, (e, t) => {\n                            this.addBlenshape(e), this.setLatestOutputTimestamp(t);\n                        }),\n                        this.graphRunner.attachEmptyPacketListener(_, (e) => {\n                            this.setLatestOutputTimestamp(e);\n                        })),\n                    this.outputFacialTransformationMatrixes &&\n                        (e.addOutputStream(O),\n                        r.addOutputStream('FACE_GEOMETRY:' + O),\n                        this.graphRunner.attachProtoVectorListener(O, (e, t) => {\n                            this.addFacialTransformationMatrixes(e),\n                                this.setLatestOutputTimestamp(t);\n                        }),\n                        this.graphRunner.attachEmptyPacketListener(O, (e) => {\n                            this.setLatestOutputTimestamp(e);\n                        }));\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        (e.FaceLandmarker = M),\n            (M.FACE_LANDMARKS_LIPS = f.FACE_LANDMARKS_LIPS),\n            (M.FACE_LANDMARKS_LEFT_EYE = f.FACE_LANDMARKS_LEFT_EYE),\n            (M.FACE_LANDMARKS_LEFT_EYEBROW = f.FACE_LANDMARKS_LEFT_EYEBROW),\n            (M.FACE_LANDMARKS_LEFT_IRIS = f.FACE_LANDMARKS_LEFT_IRIS),\n            (M.FACE_LANDMARKS_RIGHT_EYE = f.FACE_LANDMARKS_RIGHT_EYE),\n            (M.FACE_LANDMARKS_RIGHT_EYEBROW = f.FACE_LANDMARKS_RIGHT_EYEBROW),\n            (M.FACE_LANDMARKS_RIGHT_IRIS = f.FACE_LANDMARKS_RIGHT_IRIS),\n            (M.FACE_LANDMARKS_FACE_OVAL = f.FACE_LANDMARKS_FACE_OVAL),\n            (M.FACE_LANDMARKS_CONTOURS = f.FACE_LANDMARKS_CONTOURS),\n            (M.FACE_LANDMARKS_TESSELATION = f.FACE_LANDMARKS_TESSELATION);\n    })(face_landmarker);\nvar face_stylizer = {},\n    face_stylizer_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n);\n    var s = face_landmarker_graph_options_pb;\n    r.object.extend(proto, s),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                        faceLandmarkerGraphOptions:\n                            (o = r.getFaceLandmarkerGraphOptions()) &&\n                            s.FaceLandmarkerGraphOptions.toObject(e, o),\n                        faceAlignmentSize: t.Message.getFieldWithDefault(r, 3, 256),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions();\n            return proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new n.BaseOptions();\n                        t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = new s.FaceLandmarkerGraphOptions();\n                        t.readMessage(r, s.FaceLandmarkerGraphOptions.deserializeBinaryFromReader),\n                            e.setFaceLandmarkerGraphOptions(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setFaceAlignmentSize(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getBaseOptions()) &&\n                r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                null != (o = e.getFaceLandmarkerGraphOptions()) &&\n                    r.writeMessage(2, o, s.FaceLandmarkerGraphOptions.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.ext = new t.ExtensionFieldInfo(\n            513916220,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions,\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[513916220] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[513916220] =\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.getFaceLandmarkerGraphOptions = function() {\n            return t.Message.getWrapperField(this, s.FaceLandmarkerGraphOptions, 2);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.setFaceLandmarkerGraphOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.clearFaceLandmarkerGraphOptions = function() {\n            return this.setFaceLandmarkerGraphOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.hasFaceLandmarkerGraphOptions = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.getFaceAlignmentSize = function() {\n            return t.Message.getFieldWithDefault(this, 3, 256);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.setFaceAlignmentSize = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.clearFaceAlignmentSize = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.prototype.hasFaceAlignmentSize = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.ext = new t.ExtensionFieldInfo(\n            513916220,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions,\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[513916220] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[513916220] =\n            proto.mediapipe.tasks.vision.face_stylizer.proto.FaceStylizerGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.face_stylizer.proto);\n})(face_stylizer_graph_options_pb);\nvar face_stylizer_options = {};\nObject.defineProperty(face_stylizer_options, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.FaceStylizer = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = base_options_pb,\n            n = face_stylizer_graph_options_pb,\n            s = vision_task_runner;\n        r(face_stylizer_options, e);\n        const p = 'image_in',\n            d = 'norm_rect',\n            l = 'stylized_image';\n        class g extends s.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return s.VisionTaskRunner.createVisionInstance(g, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return s.VisionTaskRunner.createVisionInstance(g, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return s.VisionTaskRunner.createVisionInstance(g, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new s.VisionGraphRunner(e, t), p, d, !0),\n                    (this.options = new n.FaceStylizerGraphOptions()),\n                    this.options.setBaseOptions(new a.BaseOptions());\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                return super.applyOptions(e);\n            }\n            stylize(e, t, r) {\n                const o = 'function' != typeof t ? t : {};\n                if (\n                    ((this.userCallback = 'function' == typeof t ? t : r),\n                    this.processImageData(e, null != o ? o : {}),\n                    !this.userCallback)\n                )\n                    return this.result;\n            }\n            stylizeForVideo(e, t, r, o) {\n                const i = 'function' != typeof r ? r : {};\n                if (\n                    ((this.userCallback = 'function' == typeof r ? r : o),\n                    this.processVideoData(e, i, t),\n                    (this.userCallback = void 0),\n                    !this.userCallback)\n                )\n                    return this.result;\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(p), e.addInputStream(d), e.addOutputStream(l);\n                const t = new i.CalculatorOptions();\n                t.setExtension(n.FaceStylizerGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.face_stylizer.FaceStylizerGraph'),\n                    r.addInputStream('IMAGE:' + p),\n                    r.addInputStream('NORM_RECT:' + d),\n                    r.addOutputStream('STYLIZED_IMAGE:' + l),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.graphRunner.attachImageListener(l, (e, t) => {\n                        const r = this.convertToMPImage(e, !this.userCallback);\n                        (this.result = r),\n                            this.userCallback && this.userCallback(r),\n                            this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(l, (e) => {\n                        (this.result = null),\n                            this.userCallback && this.userCallback(null),\n                            this.setLatestOutputTimestamp(e);\n                    });\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        e.FaceStylizer = g;\n    })(face_stylizer);\nvar gesture_recognizer = {},\n    gesture_classifier_graph_options_pb = {},\n    classifier_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.tasks.components.processors.proto.ClassifierOptions', null, o),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.tasks.components.processors.proto.ClassifierOptions, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.displayName =\n                'proto.mediapipe.tasks.components.processors.proto.ClassifierOptions'),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.repeatedFields_ = [\n            4,\n            5,\n        ]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        displayNamesLocale: t.Message.getFieldWithDefault(r, 1, 'en'),\n                        maxResults: t.Message.getFieldWithDefault(r, 2, -1),\n                        scoreThreshold:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        categoryAllowlistList:\n                            null == (o = t.Message.getRepeatedField(r, 4)) ? void 0 : o,\n                        categoryDenylistList:\n                            null == (o = t.Message.getRepeatedField(r, 5)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.components.processors.proto.ClassifierOptions();\n            return proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setDisplayNamesLocale(r);\n                        break;\n                    case 2:\n                        r = t.readInt32();\n                        e.setMaxResults(r);\n                        break;\n                    case 3:\n                        r = t.readFloat();\n                        e.setScoreThreshold(r);\n                        break;\n                    case 4:\n                        r = t.readString();\n                        e.addCategoryAllowlist(r);\n                        break;\n                    case 5:\n                        r = t.readString();\n                        e.addCategoryDenylist(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeFloat(3, o),\n                (o = e.getCategoryAllowlistList()).length > 0 && r.writeRepeatedString(4, o),\n                (o = e.getCategoryDenylistList()).length > 0 && r.writeRepeatedString(5, o);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.getDisplayNamesLocale = function() {\n            return t.Message.getFieldWithDefault(this, 1, 'en');\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.setDisplayNamesLocale = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.clearDisplayNamesLocale = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.hasDisplayNamesLocale = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.getMaxResults = function() {\n            return t.Message.getFieldWithDefault(this, 2, -1);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.setMaxResults = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.clearMaxResults = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.hasMaxResults = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.getScoreThreshold = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.setScoreThreshold = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.clearScoreThreshold = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.hasScoreThreshold = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.getCategoryAllowlistList = function() {\n            return t.Message.getRepeatedField(this, 4);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.setCategoryAllowlistList = function(\n            e\n        ) {\n            return t.Message.setField(this, 4, e || []);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.addCategoryAllowlist = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedField(this, 4, e, r);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.clearCategoryAllowlistList = function() {\n            return this.setCategoryAllowlistList([]);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.getCategoryDenylistList = function() {\n            return t.Message.getRepeatedField(this, 5);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.setCategoryDenylistList = function(\n            e\n        ) {\n            return t.Message.setField(this, 5, e || []);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.addCategoryDenylist = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedField(this, 5, e, r);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.ClassifierOptions.prototype.clearCategoryDenylistList = function() {\n            return this.setCategoryDenylistList([]);\n        }),\n        r.object.extend(e, proto.mediapipe.tasks.components.processors.proto);\n})(classifier_options_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_pb;\n        r.object.extend(proto, i);\n        var a = calculator_options_pb;\n        r.object.extend(proto, a);\n        var n = classifier_options_pb;\n        r.object.extend(proto, n);\n        var s = base_options_pb;\n        r.object.extend(proto, s),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.toObject = function(\n                    e,\n                    t\n                ) {\n                    var r,\n                        o = {\n                            baseOptions: (r = t.getBaseOptions()) && s.BaseOptions.toObject(e, r),\n                            classifierOptions:\n                                (r = t.getClassifierOptions()) &&\n                                n.ClassifierOptions.toObject(e, r),\n                        };\n                    return e && (o.$jspbMessageInstance = t), o;\n                })),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions();\n                return proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new s.BaseOptions();\n                            t.readMessage(r, s.BaseOptions.deserializeBinaryFromReader),\n                                e.setBaseOptions(r);\n                            break;\n                        case 2:\n                            r = new n.ClassifierOptions();\n                            t.readMessage(r, n.ClassifierOptions.deserializeBinaryFromReader),\n                                e.setClassifierOptions(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.serializeBinaryToWriter = function(\n                e,\n                t\n            ) {\n                var r = void 0;\n                null != (r = e.getBaseOptions()) &&\n                    t.writeMessage(1, r, s.BaseOptions.serializeBinaryToWriter),\n                    null != (r = e.getClassifierOptions()) &&\n                        t.writeMessage(2, r, n.ClassifierOptions.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.ext = new t.ExtensionFieldInfo(\n                478825465,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[478825465] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[478825465] =\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.getBaseOptions = function() {\n                return t.Message.getWrapperField(this, s.BaseOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.setBaseOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.clearBaseOptions = function() {\n                return this.setBaseOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.hasBaseOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.getClassifierOptions = function() {\n                return t.Message.getWrapperField(this, n.ClassifierOptions, 2);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.setClassifierOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.clearClassifierOptions = function() {\n                return this.setClassifierOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.prototype.hasClassifierOptions = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.ext = new t.ExtensionFieldInfo(\n                478825465,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[478825465] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[478825465] =\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureClassifierGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.gesture_recognizer.proto);\n    })(gesture_classifier_graph_options_pb);\nvar gesture_recognizer_graph_options_pb = {},\n    hand_gesture_recognizer_graph_options_pb = {},\n    gesture_embedder_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions = function(\n            e\n        ) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.toObject = function(\n                e,\n                t\n            ) {\n                var r,\n                    o = { baseOptions: (r = t.getBaseOptions()) && n.BaseOptions.toObject(e, r) };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions();\n            return proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new n.BaseOptions();\n                    t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                        e.setBaseOptions(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.serializeBinaryToWriter = function(\n            e,\n            t\n        ) {\n            var r;\n            null != (r = e.getBaseOptions()) &&\n                t.writeMessage(1, r, n.BaseOptions.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.ext = new t.ExtensionFieldInfo(\n            478825422,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions,\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[478825422] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[478825422] =\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.ext = new t.ExtensionFieldInfo(\n            478825422,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions,\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[478825422] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[478825422] =\n            proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureEmbedderGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.gesture_recognizer.proto);\n})(gesture_embedder_graph_options_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_pb;\n        r.object.extend(proto, i);\n        var a = calculator_options_pb;\n        r.object.extend(proto, a);\n        var n = base_options_pb;\n        r.object.extend(proto, n);\n        var s = gesture_classifier_graph_options_pb;\n        r.object.extend(proto, s);\n        var p = gesture_embedder_graph_options_pb;\n        r.object.extend(proto, p),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto\n                    .HandGestureRecognizerGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.toObject = function(\n                    e,\n                    t\n                ) {\n                    var r,\n                        o = {\n                            baseOptions: (r = t.getBaseOptions()) && n.BaseOptions.toObject(e, r),\n                            gestureEmbedderGraphOptions:\n                                (r = t.getGestureEmbedderGraphOptions()) &&\n                                p.GestureEmbedderGraphOptions.toObject(e, r),\n                            cannedGestureClassifierGraphOptions:\n                                (r = t.getCannedGestureClassifierGraphOptions()) &&\n                                s.GestureClassifierGraphOptions.toObject(e, r),\n                            customGestureClassifierGraphOptions:\n                                (r = t.getCustomGestureClassifierGraphOptions()) &&\n                                s.GestureClassifierGraphOptions.toObject(e, r),\n                        };\n                    return e && (o.$jspbMessageInstance = t), o;\n                })),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions();\n                return proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new n.BaseOptions();\n                            t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                                e.setBaseOptions(r);\n                            break;\n                        case 2:\n                            r = new p.GestureEmbedderGraphOptions();\n                            t.readMessage(\n                                r,\n                                p.GestureEmbedderGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setGestureEmbedderGraphOptions(r);\n                            break;\n                        case 3:\n                            r = new s.GestureClassifierGraphOptions();\n                            t.readMessage(\n                                r,\n                                s.GestureClassifierGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setCannedGestureClassifierGraphOptions(r);\n                            break;\n                        case 4:\n                            r = new s.GestureClassifierGraphOptions();\n                            t.readMessage(\n                                r,\n                                s.GestureClassifierGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setCustomGestureClassifierGraphOptions(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.serializeBinaryToWriter = function(\n                e,\n                t\n            ) {\n                var r = void 0;\n                null != (r = e.getBaseOptions()) &&\n                    t.writeMessage(1, r, n.BaseOptions.serializeBinaryToWriter),\n                    null != (r = e.getGestureEmbedderGraphOptions()) &&\n                        t.writeMessage(2, r, p.GestureEmbedderGraphOptions.serializeBinaryToWriter),\n                    null != (r = e.getCannedGestureClassifierGraphOptions()) &&\n                        t.writeMessage(\n                            3,\n                            r,\n                            s.GestureClassifierGraphOptions.serializeBinaryToWriter\n                        ),\n                    null != (r = e.getCustomGestureClassifierGraphOptions()) &&\n                        t.writeMessage(\n                            4,\n                            r,\n                            s.GestureClassifierGraphOptions.serializeBinaryToWriter\n                        );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.ext = new t.ExtensionFieldInfo(\n                463370452,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[463370452] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[463370452] =\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.getBaseOptions = function() {\n                return t.Message.getWrapperField(this, n.BaseOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.setBaseOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.clearBaseOptions = function() {\n                return this.setBaseOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.hasBaseOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.getGestureEmbedderGraphOptions = function() {\n                return t.Message.getWrapperField(this, p.GestureEmbedderGraphOptions, 2);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.setGestureEmbedderGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.clearGestureEmbedderGraphOptions = function() {\n                return this.setGestureEmbedderGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.hasGestureEmbedderGraphOptions = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.getCannedGestureClassifierGraphOptions = function() {\n                return t.Message.getWrapperField(this, s.GestureClassifierGraphOptions, 3);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.setCannedGestureClassifierGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.clearCannedGestureClassifierGraphOptions = function() {\n                return this.setCannedGestureClassifierGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.hasCannedGestureClassifierGraphOptions = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.getCustomGestureClassifierGraphOptions = function() {\n                return t.Message.getWrapperField(this, s.GestureClassifierGraphOptions, 4);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.setCustomGestureClassifierGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 4, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.clearCustomGestureClassifierGraphOptions = function() {\n                return this.setCustomGestureClassifierGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.prototype.hasCustomGestureClassifierGraphOptions = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.ext = new t.ExtensionFieldInfo(\n                463370452,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[463370452] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[463370452] =\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.HandGestureRecognizerGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.gesture_recognizer.proto);\n    })(hand_gesture_recognizer_graph_options_pb);\nvar hand_landmarker_graph_options_pb = {},\n    hand_detector_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                        minDetectionConfidence: t.Message.getFloatingPointFieldWithDefault(\n                            r,\n                            2,\n                            0.5\n                        ),\n                        numHands: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions();\n            return proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new n.BaseOptions();\n                        t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setMinDetectionConfidence(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setNumHands(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getBaseOptions()) &&\n                r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            464864288,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[464864288] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[464864288] =\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.getMinDetectionConfidence = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0.5);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.setMinDetectionConfidence = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.clearMinDetectionConfidence = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.hasMinDetectionConfidence = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.getNumHands = function() {\n            return t.Message.getFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.setNumHands = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.clearNumHands = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.prototype.hasNumHands = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            464864288,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[464864288] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[464864288] =\n            proto.mediapipe.tasks.vision.hand_detector.proto.HandDetectorGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.hand_detector.proto);\n})(hand_detector_graph_options_pb);\nvar hand_landmarks_detector_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions = function(\n            e\n        ) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                        minDetectionConfidence: t.Message.getFloatingPointFieldWithDefault(\n                            r,\n                            2,\n                            0.5\n                        ),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions();\n            return proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new n.BaseOptions();\n                        t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setMinDetectionConfidence(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getBaseOptions()) &&\n                r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            474472470,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[474472470] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[474472470] =\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.getMinDetectionConfidence = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0.5);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.setMinDetectionConfidence = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.clearMinDetectionConfidence = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.prototype.hasMinDetectionConfidence = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            474472470,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[474472470] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[474472470] =\n            proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarksDetectorGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.hand_landmarker.proto);\n})(hand_landmarks_detector_graph_options_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_pb;\n        r.object.extend(proto, i);\n        var a = calculator_options_pb;\n        r.object.extend(proto, a);\n        var n = base_options_pb;\n        r.object.extend(proto, n);\n        var s = hand_detector_graph_options_pb;\n        r.object.extend(proto, s);\n        var p = hand_landmarks_detector_graph_options_pb;\n        r.object.extend(proto, p),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.toObject = function(\n                    e,\n                    r\n                ) {\n                    var o,\n                        i = {\n                            baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                            handDetectorGraphOptions:\n                                (o = r.getHandDetectorGraphOptions()) &&\n                                s.HandDetectorGraphOptions.toObject(e, o),\n                            handLandmarksDetectorGraphOptions:\n                                (o = r.getHandLandmarksDetectorGraphOptions()) &&\n                                p.HandLandmarksDetectorGraphOptions.toObject(e, o),\n                            minTrackingConfidence: t.Message.getFloatingPointFieldWithDefault(\n                                r,\n                                4,\n                                0.5\n                            ),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions();\n                return proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new n.BaseOptions();\n                            t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                                e.setBaseOptions(r);\n                            break;\n                        case 2:\n                            r = new s.HandDetectorGraphOptions();\n                            t.readMessage(\n                                r,\n                                s.HandDetectorGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setHandDetectorGraphOptions(r);\n                            break;\n                        case 3:\n                            r = new p.HandLandmarksDetectorGraphOptions();\n                            t.readMessage(\n                                r,\n                                p.HandLandmarksDetectorGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setHandLandmarksDetectorGraphOptions(r);\n                            break;\n                        case 4:\n                            r = t.readFloat();\n                            e.setMinTrackingConfidence(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.serializeBinaryToWriter = function(\n                e,\n                r\n            ) {\n                var o = void 0;\n                null != (o = e.getBaseOptions()) &&\n                    r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                    null != (o = e.getHandDetectorGraphOptions()) &&\n                        r.writeMessage(2, o, s.HandDetectorGraphOptions.serializeBinaryToWriter),\n                    null != (o = e.getHandLandmarksDetectorGraphOptions()) &&\n                        r.writeMessage(\n                            3,\n                            o,\n                            p.HandLandmarksDetectorGraphOptions.serializeBinaryToWriter\n                        ),\n                    null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.ext = new t.ExtensionFieldInfo(\n                462713202,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions,\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[462713202] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[462713202] =\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.getBaseOptions = function() {\n                return t.Message.getWrapperField(this, n.BaseOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.setBaseOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.clearBaseOptions = function() {\n                return this.setBaseOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.hasBaseOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.getHandDetectorGraphOptions = function() {\n                return t.Message.getWrapperField(this, s.HandDetectorGraphOptions, 2);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.setHandDetectorGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.clearHandDetectorGraphOptions = function() {\n                return this.setHandDetectorGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.hasHandDetectorGraphOptions = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.getHandLandmarksDetectorGraphOptions = function() {\n                return t.Message.getWrapperField(this, p.HandLandmarksDetectorGraphOptions, 3);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.setHandLandmarksDetectorGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.clearHandLandmarksDetectorGraphOptions = function() {\n                return this.setHandLandmarksDetectorGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.hasHandLandmarksDetectorGraphOptions = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.getMinTrackingConfidence = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 4, 0.5);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.setMinTrackingConfidence = function(\n                e\n            ) {\n                return t.Message.setField(this, 4, e);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.clearMinTrackingConfidence = function() {\n                return t.Message.setField(this, 4, void 0);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.prototype.hasMinTrackingConfidence = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.ext = new t.ExtensionFieldInfo(\n                462713202,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions,\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[462713202] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[462713202] =\n                proto.mediapipe.tasks.vision.hand_landmarker.proto.HandLandmarkerGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.hand_landmarker.proto);\n    })(hand_landmarker_graph_options_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_pb;\n        r.object.extend(proto, i);\n        var a = calculator_options_pb;\n        r.object.extend(proto, a);\n        var n = base_options_pb;\n        r.object.extend(proto, n);\n        var s = hand_gesture_recognizer_graph_options_pb;\n        r.object.extend(proto, s);\n        var p = hand_landmarker_graph_options_pb;\n        r.object.extend(proto, p),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.toObject = function(\n                    e,\n                    t\n                ) {\n                    var r,\n                        o = {\n                            baseOptions: (r = t.getBaseOptions()) && n.BaseOptions.toObject(e, r),\n                            handLandmarkerGraphOptions:\n                                (r = t.getHandLandmarkerGraphOptions()) &&\n                                p.HandLandmarkerGraphOptions.toObject(e, r),\n                            handGestureRecognizerGraphOptions:\n                                (r = t.getHandGestureRecognizerGraphOptions()) &&\n                                s.HandGestureRecognizerGraphOptions.toObject(e, r),\n                        };\n                    return e && (o.$jspbMessageInstance = t), o;\n                })),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions();\n                return proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new n.BaseOptions();\n                            t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                                e.setBaseOptions(r);\n                            break;\n                        case 2:\n                            r = new p.HandLandmarkerGraphOptions();\n                            t.readMessage(\n                                r,\n                                p.HandLandmarkerGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setHandLandmarkerGraphOptions(r);\n                            break;\n                        case 3:\n                            r = new s.HandGestureRecognizerGraphOptions();\n                            t.readMessage(\n                                r,\n                                s.HandGestureRecognizerGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setHandGestureRecognizerGraphOptions(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.serializeBinaryToWriter = function(\n                e,\n                t\n            ) {\n                var r = void 0;\n                null != (r = e.getBaseOptions()) &&\n                    t.writeMessage(1, r, n.BaseOptions.serializeBinaryToWriter),\n                    null != (r = e.getHandLandmarkerGraphOptions()) &&\n                        t.writeMessage(2, r, p.HandLandmarkerGraphOptions.serializeBinaryToWriter),\n                    null != (r = e.getHandGestureRecognizerGraphOptions()) &&\n                        t.writeMessage(\n                            3,\n                            r,\n                            s.HandGestureRecognizerGraphOptions.serializeBinaryToWriter\n                        );\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.ext = new t.ExtensionFieldInfo(\n                479097054,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[479097054] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[479097054] =\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.getBaseOptions = function() {\n                return t.Message.getWrapperField(this, n.BaseOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.setBaseOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.clearBaseOptions = function() {\n                return this.setBaseOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.hasBaseOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.getHandLandmarkerGraphOptions = function() {\n                return t.Message.getWrapperField(this, p.HandLandmarkerGraphOptions, 2);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.setHandLandmarkerGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.clearHandLandmarkerGraphOptions = function() {\n                return this.setHandLandmarkerGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.hasHandLandmarkerGraphOptions = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.getHandGestureRecognizerGraphOptions = function() {\n                return t.Message.getWrapperField(this, s.HandGestureRecognizerGraphOptions, 3);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.setHandGestureRecognizerGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.clearHandGestureRecognizerGraphOptions = function() {\n                return this.setHandGestureRecognizerGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.prototype.hasHandGestureRecognizerGraphOptions = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.ext = new t.ExtensionFieldInfo(\n                479097054,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[479097054] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[479097054] =\n                proto.mediapipe.tasks.vision.gesture_recognizer.proto.GestureRecognizerGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.gesture_recognizer.proto);\n    })(gesture_recognizer_graph_options_pb);\nvar classifier_options = {};\nObject.defineProperty(classifier_options, '__esModule', { value: !0 }),\n    (classifier_options.convertClassifierOptionsToProto = void 0);\nconst classifier_options_pb_1 = classifier_options_pb;\nfunction convertClassifierOptionsToProto(e, t) {\n    const r = t ? t.clone() : new classifier_options_pb_1.ClassifierOptions();\n    return (\n        void 0 !== e.displayNamesLocale\n            ? r.setDisplayNamesLocale(e.displayNamesLocale)\n            : void 0 === e.displayNamesLocale && r.clearDisplayNamesLocale(),\n        void 0 !== e.maxResults\n            ? r.setMaxResults(e.maxResults)\n            : 'maxResults' in e && r.clearMaxResults(),\n        void 0 !== e.scoreThreshold\n            ? r.setScoreThreshold(e.scoreThreshold)\n            : 'scoreThreshold' in e && r.clearScoreThreshold(),\n        void 0 !== e.categoryAllowlist\n            ? r.setCategoryAllowlistList(e.categoryAllowlist)\n            : 'categoryAllowlist' in e && r.clearCategoryAllowlistList(),\n        void 0 !== e.categoryDenylist\n            ? r.setCategoryDenylistList(e.categoryDenylist)\n            : 'categoryDenylist' in e && r.clearCategoryDenylistList(),\n        r\n    );\n}\nclassifier_options.convertClassifierOptionsToProto = convertClassifierOptionsToProto;\nvar hand_landmarks_connections = {};\nObject.defineProperty(hand_landmarks_connections, '__esModule', { value: !0 }),\n    (hand_landmarks_connections.HAND_CONNECTIONS = void 0),\n    (hand_landmarks_connections.HAND_CONNECTIONS = [\n        { start: 0, end: 1 },\n        { start: 1, end: 2 },\n        { start: 2, end: 3 },\n        { start: 3, end: 4 },\n        { start: 0, end: 5 },\n        { start: 5, end: 6 },\n        { start: 6, end: 7 },\n        { start: 7, end: 8 },\n        { start: 5, end: 9 },\n        { start: 9, end: 10 },\n        { start: 10, end: 11 },\n        { start: 11, end: 12 },\n        { start: 9, end: 13 },\n        { start: 13, end: 14 },\n        { start: 14, end: 15 },\n        { start: 15, end: 16 },\n        { start: 13, end: 17 },\n        { start: 0, end: 17 },\n        { start: 17, end: 18 },\n        { start: 18, end: 19 },\n        { start: 19, end: 20 },\n    ]);\nvar gesture_recognizer_options = {};\nObject.defineProperty(gesture_recognizer_options, '__esModule', { value: !0 });\nvar gesture_recognizer_result = {};\nObject.defineProperty(gesture_recognizer_result, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.GestureRecognizer = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = classification_pb,\n            n = landmark_pb,\n            s = base_options_pb,\n            p = gesture_classifier_graph_options_pb,\n            d = gesture_recognizer_graph_options_pb,\n            l = hand_gesture_recognizer_graph_options_pb,\n            g = hand_detector_graph_options_pb,\n            c = hand_landmarker_graph_options_pb,\n            u = hand_landmarks_detector_graph_options_pb,\n            m = classifier_options,\n            f = vision_task_runner,\n            h = hand_landmarks_connections;\n        r(gesture_recognizer_options, e), r(gesture_recognizer_result, e);\n        const y = 'image_in',\n            b = 'norm_rect',\n            _ = 'hand_gestures',\n            O = 'hand_landmarks',\n            F = 'world_hand_landmarks',\n            M = 'handedness',\n            R = 0.5;\n        class v extends f.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return f.VisionTaskRunner.createVisionInstance(v, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return f.VisionTaskRunner.createVisionInstance(v, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return f.VisionTaskRunner.createVisionInstance(v, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new f.VisionGraphRunner(e, t), y, b, !1),\n                    (this.gestures = []),\n                    (this.landmarks = []),\n                    (this.worldLandmarks = []),\n                    (this.handednesses = []),\n                    (this.options = new d.GestureRecognizerGraphOptions()),\n                    this.options.setBaseOptions(new s.BaseOptions()),\n                    (this.handLandmarkerGraphOptions = new c.HandLandmarkerGraphOptions()),\n                    this.options.setHandLandmarkerGraphOptions(this.handLandmarkerGraphOptions),\n                    (this.handLandmarksDetectorGraphOptions = new u.HandLandmarksDetectorGraphOptions()),\n                    this.handLandmarkerGraphOptions.setHandLandmarksDetectorGraphOptions(\n                        this.handLandmarksDetectorGraphOptions\n                    ),\n                    (this.handDetectorGraphOptions = new g.HandDetectorGraphOptions()),\n                    this.handLandmarkerGraphOptions.setHandDetectorGraphOptions(\n                        this.handDetectorGraphOptions\n                    ),\n                    (this.handGestureRecognizerGraphOptions = new l.HandGestureRecognizerGraphOptions()),\n                    this.options.setHandGestureRecognizerGraphOptions(\n                        this.handGestureRecognizerGraphOptions\n                    ),\n                    this.handDetectorGraphOptions.setMinDetectionConfidence(R),\n                    this.handLandmarkerGraphOptions.setMinTrackingConfidence(R),\n                    this.handLandmarksDetectorGraphOptions.setMinDetectionConfidence(R);\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                var t, r, o, i, a, n, s, d;\n                if (\n                    (this.handDetectorGraphOptions.setNumHands(\n                        null !== (t = e.numHands) && void 0 !== t ? t : 1\n                    ),\n                    'minHandDetectionConfidence' in e &&\n                        this.handDetectorGraphOptions.setMinDetectionConfidence(\n                            null !== (r = e.minHandDetectionConfidence) && void 0 !== r ? r : R\n                        ),\n                    'minTrackingConfidence' in e &&\n                        this.handLandmarkerGraphOptions.setMinTrackingConfidence(\n                            null !== (o = e.minTrackingConfidence) && void 0 !== o ? o : R\n                        ),\n                    'minHandPresenceConfidence' in e &&\n                        this.handLandmarksDetectorGraphOptions.setMinDetectionConfidence(\n                            null !== (i = e.minHandPresenceConfidence) && void 0 !== i ? i : R\n                        ),\n                    e.cannedGesturesClassifierOptions)\n                ) {\n                    const t = new p.GestureClassifierGraphOptions();\n                    t.setClassifierOptions(\n                        (0, m.convertClassifierOptionsToProto)(\n                            e.cannedGesturesClassifierOptions,\n                            null ===\n                                (a = this.handGestureRecognizerGraphOptions.getCannedGestureClassifierGraphOptions()) ||\n                                void 0 === a\n                                ? void 0\n                                : a.getClassifierOptions()\n                        )\n                    ),\n                        this.handGestureRecognizerGraphOptions.setCannedGestureClassifierGraphOptions(\n                            t\n                        );\n                } else\n                    void 0 === e.cannedGesturesClassifierOptions &&\n                        (null ===\n                            (n = this.handGestureRecognizerGraphOptions.getCannedGestureClassifierGraphOptions()) ||\n                            void 0 === n ||\n                            n.clearClassifierOptions());\n                if (e.customGesturesClassifierOptions) {\n                    const t = new p.GestureClassifierGraphOptions();\n                    t.setClassifierOptions(\n                        (0, m.convertClassifierOptionsToProto)(\n                            e.customGesturesClassifierOptions,\n                            null ===\n                                (s = this.handGestureRecognizerGraphOptions.getCustomGestureClassifierGraphOptions()) ||\n                                void 0 === s\n                                ? void 0\n                                : s.getClassifierOptions()\n                        )\n                    ),\n                        this.handGestureRecognizerGraphOptions.setCustomGestureClassifierGraphOptions(\n                            t\n                        );\n                } else\n                    void 0 === e.customGesturesClassifierOptions &&\n                        (null ===\n                            (d = this.handGestureRecognizerGraphOptions.getCustomGestureClassifierGraphOptions()) ||\n                            void 0 === d ||\n                            d.clearClassifierOptions());\n                return this.applyOptions(e);\n            }\n            recognize(e, t) {\n                return this.resetResults(), this.processImageData(e, t), this.processResults();\n            }\n            recognizeForVideo(e, t, r) {\n                return this.resetResults(), this.processVideoData(e, r, t), this.processResults();\n            }\n            resetResults() {\n                (this.gestures = []),\n                    (this.landmarks = []),\n                    (this.worldLandmarks = []),\n                    (this.handednesses = []);\n            }\n            processResults() {\n                return 0 === this.gestures.length\n                    ? { gestures: [], landmarks: [], worldLandmarks: [], handednesses: [] }\n                    : {\n                          gestures: this.gestures,\n                          landmarks: this.landmarks,\n                          worldLandmarks: this.worldLandmarks,\n                          handednesses: this.handednesses,\n                      };\n            }\n            toJsCategories(e, t = !0) {\n                var r, o, i;\n                const n = [];\n                for (const s of e) {\n                    const e = a.ClassificationList.deserializeBinary(s),\n                        p = [];\n                    for (const a of e.getClassificationList()) {\n                        const e = t && a.hasIndex() ? a.getIndex() : -1;\n                        p.push({\n                            score: null !== (r = a.getScore()) && void 0 !== r ? r : 0,\n                            index: e,\n                            categoryName: null !== (o = a.getLabel()) && void 0 !== o ? o : '',\n                            displayName: null !== (i = a.getDisplayName()) && void 0 !== i ? i : '',\n                        });\n                    }\n                    n.push(p);\n                }\n                return n;\n            }\n            addJsLandmarks(e) {\n                var t, r, o;\n                for (const i of e) {\n                    const e = n.NormalizedLandmarkList.deserializeBinary(i),\n                        a = [];\n                    for (const i of e.getLandmarkList())\n                        a.push({\n                            x: null !== (t = i.getX()) && void 0 !== t ? t : 0,\n                            y: null !== (r = i.getY()) && void 0 !== r ? r : 0,\n                            z: null !== (o = i.getZ()) && void 0 !== o ? o : 0,\n                        });\n                    this.landmarks.push(a);\n                }\n            }\n            adddJsWorldLandmarks(e) {\n                var t, r, o;\n                for (const i of e) {\n                    const e = n.LandmarkList.deserializeBinary(i),\n                        a = [];\n                    for (const i of e.getLandmarkList())\n                        a.push({\n                            x: null !== (t = i.getX()) && void 0 !== t ? t : 0,\n                            y: null !== (r = i.getY()) && void 0 !== r ? r : 0,\n                            z: null !== (o = i.getZ()) && void 0 !== o ? o : 0,\n                        });\n                    this.worldLandmarks.push(a);\n                }\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(y),\n                    e.addInputStream(b),\n                    e.addOutputStream(_),\n                    e.addOutputStream(O),\n                    e.addOutputStream(F),\n                    e.addOutputStream(M);\n                const t = new i.CalculatorOptions();\n                t.setExtension(d.GestureRecognizerGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.gesture_recognizer.GestureRecognizerGraph'),\n                    r.addInputStream('IMAGE:' + y),\n                    r.addInputStream('NORM_RECT:' + b),\n                    r.addOutputStream('HAND_GESTURES:' + _),\n                    r.addOutputStream('LANDMARKS:' + O),\n                    r.addOutputStream('WORLD_LANDMARKS:' + F),\n                    r.addOutputStream('HANDEDNESS:' + M),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.graphRunner.attachProtoVectorListener(O, (e, t) => {\n                        this.addJsLandmarks(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(O, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    }),\n                    this.graphRunner.attachProtoVectorListener(F, (e, t) => {\n                        this.adddJsWorldLandmarks(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(F, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    }),\n                    this.graphRunner.attachProtoVectorListener(_, (e, t) => {\n                        this.gestures.push(...this.toJsCategories(e, !1)),\n                            this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(_, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    }),\n                    this.graphRunner.attachProtoVectorListener(M, (e, t) => {\n                        this.handednesses.push(...this.toJsCategories(e)),\n                            this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(M, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    });\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        (e.GestureRecognizer = v), (v.HAND_CONNECTIONS = h.HAND_CONNECTIONS);\n    })(gesture_recognizer);\nvar hand_landmarker = {},\n    hand_landmarker_options = {};\nObject.defineProperty(hand_landmarker_options, '__esModule', { value: !0 });\nvar hand_landmarker_result = {};\nObject.defineProperty(hand_landmarker_result, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.HandLandmarker = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = classification_pb,\n            n = landmark_pb,\n            s = base_options_pb,\n            p = hand_detector_graph_options_pb,\n            d = hand_landmarker_graph_options_pb,\n            l = hand_landmarks_detector_graph_options_pb,\n            g = landmark_result,\n            c = vision_task_runner,\n            u = hand_landmarks_connections;\n        r(hand_landmarker_options, e), r(hand_landmarker_result, e);\n        const m = 'image_in',\n            f = 'norm_rect',\n            h = 'hand_landmarks',\n            y = 'world_hand_landmarks',\n            b = 'handedness',\n            _ = 0.5;\n        class O extends c.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return c.VisionTaskRunner.createVisionInstance(O, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return c.VisionTaskRunner.createVisionInstance(O, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return c.VisionTaskRunner.createVisionInstance(O, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new c.VisionGraphRunner(e, t), m, f, !1),\n                    (this.landmarks = []),\n                    (this.worldLandmarks = []),\n                    (this.handednesses = []),\n                    (this.options = new d.HandLandmarkerGraphOptions()),\n                    this.options.setBaseOptions(new s.BaseOptions()),\n                    (this.handLandmarksDetectorGraphOptions = new l.HandLandmarksDetectorGraphOptions()),\n                    this.options.setHandLandmarksDetectorGraphOptions(\n                        this.handLandmarksDetectorGraphOptions\n                    ),\n                    (this.handDetectorGraphOptions = new p.HandDetectorGraphOptions()),\n                    this.options.setHandDetectorGraphOptions(this.handDetectorGraphOptions),\n                    this.initDefaults();\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                var t, r, o, i;\n                return (\n                    'numHands' in e &&\n                        this.handDetectorGraphOptions.setNumHands(\n                            null !== (t = e.numHands) && void 0 !== t ? t : 1\n                        ),\n                    'minHandDetectionConfidence' in e &&\n                        this.handDetectorGraphOptions.setMinDetectionConfidence(\n                            null !== (r = e.minHandDetectionConfidence) && void 0 !== r ? r : _\n                        ),\n                    'minTrackingConfidence' in e &&\n                        this.options.setMinTrackingConfidence(\n                            null !== (o = e.minTrackingConfidence) && void 0 !== o ? o : _\n                        ),\n                    'minHandPresenceConfidence' in e &&\n                        this.handLandmarksDetectorGraphOptions.setMinDetectionConfidence(\n                            null !== (i = e.minHandPresenceConfidence) && void 0 !== i ? i : _\n                        ),\n                    this.applyOptions(e)\n                );\n            }\n            detect(e, t) {\n                return this.resetResults(), this.processImageData(e, t), this.processResults();\n            }\n            detectForVideo(e, t, r) {\n                return this.resetResults(), this.processVideoData(e, r, t), this.processResults();\n            }\n            resetResults() {\n                (this.landmarks = []), (this.worldLandmarks = []), (this.handednesses = []);\n            }\n            processResults() {\n                return {\n                    landmarks: this.landmarks,\n                    worldLandmarks: this.worldLandmarks,\n                    handednesses: this.handednesses,\n                };\n            }\n            initDefaults() {\n                this.handDetectorGraphOptions.setNumHands(1),\n                    this.handDetectorGraphOptions.setMinDetectionConfidence(_),\n                    this.handLandmarksDetectorGraphOptions.setMinDetectionConfidence(_),\n                    this.options.setMinTrackingConfidence(_);\n            }\n            toJsCategories(e) {\n                var t, r, o, i;\n                const n = [];\n                for (const s of e) {\n                    const e = a.ClassificationList.deserializeBinary(s),\n                        p = [];\n                    for (const a of e.getClassificationList())\n                        p.push({\n                            score: null !== (t = a.getScore()) && void 0 !== t ? t : 0,\n                            index: null !== (r = a.getIndex()) && void 0 !== r ? r : -1,\n                            categoryName: null !== (o = a.getLabel()) && void 0 !== o ? o : '',\n                            displayName: null !== (i = a.getDisplayName()) && void 0 !== i ? i : '',\n                        });\n                    n.push(p);\n                }\n                return n;\n            }\n            addJsLandmarks(e) {\n                for (const t of e) {\n                    const e = n.NormalizedLandmarkList.deserializeBinary(t);\n                    this.landmarks.push((0, g.convertToLandmarks)(e));\n                }\n            }\n            adddJsWorldLandmarks(e) {\n                for (const t of e) {\n                    const e = n.LandmarkList.deserializeBinary(t);\n                    this.worldLandmarks.push((0, g.convertToWorldLandmarks)(e));\n                }\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(m),\n                    e.addInputStream(f),\n                    e.addOutputStream(h),\n                    e.addOutputStream(y),\n                    e.addOutputStream(b);\n                const t = new i.CalculatorOptions();\n                t.setExtension(d.HandLandmarkerGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.hand_landmarker.HandLandmarkerGraph'),\n                    r.addInputStream('IMAGE:' + m),\n                    r.addInputStream('NORM_RECT:' + f),\n                    r.addOutputStream('LANDMARKS:' + h),\n                    r.addOutputStream('WORLD_LANDMARKS:' + y),\n                    r.addOutputStream('HANDEDNESS:' + b),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.graphRunner.attachProtoVectorListener(h, (e, t) => {\n                        this.addJsLandmarks(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(h, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    }),\n                    this.graphRunner.attachProtoVectorListener(y, (e, t) => {\n                        this.adddJsWorldLandmarks(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(y, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    }),\n                    this.graphRunner.attachProtoVectorListener(b, (e, t) => {\n                        this.handednesses.push(...this.toJsCategories(e)),\n                            this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(b, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    });\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        (e.HandLandmarker = O), (O.HAND_CONNECTIONS = u.HAND_CONNECTIONS);\n    })(hand_landmarker);\nvar image_classifier = {},\n    classifications_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = classification_pb;\n    r.object.extend(proto, i),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.components.containers.proto.ClassificationResult',\n            null,\n            o\n        ),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.components.containers.proto.Classifications',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.tasks.components.containers.proto.Classifications, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.components.containers.proto.Classifications.displayName =\n                'proto.mediapipe.tasks.components.containers.proto.Classifications'),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.tasks.components.containers.proto.ClassificationResult\n                    .repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.components.containers.proto.ClassificationResult,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.displayName =\n                'proto.mediapipe.tasks.components.containers.proto.ClassificationResult'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.components.containers.proto.Classifications.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.components.containers.proto.Classifications.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    a = {\n                        classificationList:\n                            (o = r.getClassificationList()) && i.ClassificationList.toObject(e, o),\n                        headIndex: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        headName: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                    };\n                return e && (a.$jspbMessageInstance = r), a;\n            })),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.components.containers.proto.Classifications();\n            return proto.mediapipe.tasks.components.containers.proto.Classifications.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 4:\n                        var r = new i.ClassificationList();\n                        t.readMessage(r, i.ClassificationList.deserializeBinaryFromReader),\n                            e.setClassificationList(r);\n                        break;\n                    case 2:\n                        r = t.readInt32();\n                        e.setHeadIndex(r);\n                        break;\n                    case 3:\n                        r = t.readString();\n                        e.setHeadName(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.components.containers.proto.Classifications.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getClassificationList()) &&\n                r.writeMessage(4, o, i.ClassificationList.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeString(3, o);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.getClassificationList = function() {\n            return t.Message.getWrapperField(this, i.ClassificationList, 4);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.setClassificationList = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 4, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.clearClassificationList = function() {\n            return this.setClassificationList(void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.hasClassificationList = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.getHeadIndex = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.setHeadIndex = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.clearHeadIndex = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.hasHeadIndex = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.getHeadName = function() {\n            return t.Message.getFieldWithDefault(this, 3, '');\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.setHeadName = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.clearHeadName = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Classifications.prototype.hasHeadName = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.repeatedFields_ = [\n            1,\n        ]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.components.containers.proto.ClassificationResult.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        classificationsList: t.Message.toObjectList(\n                            r.getClassificationsList(),\n                            proto.mediapipe.tasks.components.containers.proto.Classifications\n                                .toObject,\n                            e\n                        ),\n                        timestampMs: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.components.containers.proto.ClassificationResult();\n            return proto.mediapipe.tasks.components.containers.proto.ClassificationResult.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.tasks.components.containers.proto.Classifications();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.tasks.components.containers.proto.Classifications\n                                .deserializeBinaryFromReader\n                        ),\n                            e.addClassifications(r);\n                        break;\n                    case 2:\n                        r = t.readInt64();\n                        e.setTimestampMs(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.components.containers.proto.ClassificationResult.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            (o = e.getClassificationsList()).length > 0 &&\n                r.writeRepeatedMessage(\n                    1,\n                    o,\n                    proto.mediapipe.tasks.components.containers.proto.Classifications\n                        .serializeBinaryToWriter\n                ),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt64(2, o);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.getClassificationsList = function() {\n            return t.Message.getRepeatedWrapperField(\n                this,\n                proto.mediapipe.tasks.components.containers.proto.Classifications,\n                1\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.setClassificationsList = function(\n            e\n        ) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.addClassifications = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.tasks.components.containers.proto.Classifications,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.clearClassificationsList = function() {\n            return this.setClassificationsList([]);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.getTimestampMs = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.setTimestampMs = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.clearTimestampMs = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.ClassificationResult.prototype.hasTimestampMs = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        r.object.extend(e, proto.mediapipe.tasks.components.containers.proto);\n})(classifications_pb);\nvar image_classifier_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = classifier_options_pb;\n    r.object.extend(proto, n);\n    var s = base_options_pb;\n    r.object.extend(proto, s),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions = function(\n            e\n        ) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.toObject = function(\n                e,\n                t\n            ) {\n                var r,\n                    o = {\n                        baseOptions: (r = t.getBaseOptions()) && s.BaseOptions.toObject(e, r),\n                        classifierOptions:\n                            (r = t.getClassifierOptions()) && n.ClassifierOptions.toObject(e, r),\n                    };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions();\n            return proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new s.BaseOptions();\n                        t.readMessage(r, s.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = new n.ClassifierOptions();\n                        t.readMessage(r, n.ClassifierOptions.deserializeBinaryFromReader),\n                            e.setClassifierOptions(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.serializeBinaryToWriter = function(\n            e,\n            t\n        ) {\n            var r = void 0;\n            null != (r = e.getBaseOptions()) &&\n                t.writeMessage(1, r, s.BaseOptions.serializeBinaryToWriter),\n                null != (r = e.getClassifierOptions()) &&\n                    t.writeMessage(2, r, n.ClassifierOptions.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.ext = new t.ExtensionFieldInfo(\n            456383383,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions,\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[456383383] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[456383383] =\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, s.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.getClassifierOptions = function() {\n            return t.Message.getWrapperField(this, n.ClassifierOptions, 2);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.setClassifierOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.clearClassifierOptions = function() {\n            return this.setClassifierOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.prototype.hasClassifierOptions = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.ext = new t.ExtensionFieldInfo(\n            456383383,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions,\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[456383383] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[456383383] =\n            proto.mediapipe.tasks.vision.image_classifier.proto.ImageClassifierGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.image_classifier.proto);\n})(image_classifier_graph_options_pb);\nvar image_classifier_options = {};\nObject.defineProperty(image_classifier_options, '__esModule', { value: !0 });\nvar image_classifier_result = {};\nObject.defineProperty(image_classifier_result, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.ImageClassifier = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = classifications_pb,\n            n = base_options_pb,\n            s = image_classifier_graph_options_pb,\n            p = classifier_options,\n            d = classifier_result,\n            l = vision_task_runner,\n            g = 'input_image',\n            c = 'norm_rect',\n            u = 'classifications';\n        r(image_classifier_options, e), r(image_classifier_result, e);\n        class m extends l.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return l.VisionTaskRunner.createVisionInstance(m, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return l.VisionTaskRunner.createVisionInstance(m, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return l.VisionTaskRunner.createVisionInstance(m, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new l.VisionGraphRunner(e, t), g, c, !0),\n                    (this.classificationResult = { classifications: [] }),\n                    (this.options = new s.ImageClassifierGraphOptions()),\n                    this.options.setBaseOptions(new n.BaseOptions());\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                return (\n                    this.options.setClassifierOptions(\n                        (0, p.convertClassifierOptionsToProto)(\n                            e,\n                            this.options.getClassifierOptions()\n                        )\n                    ),\n                    this.applyOptions(e)\n                );\n            }\n            classify(e, t) {\n                return (\n                    (this.classificationResult = { classifications: [] }),\n                    this.processImageData(e, t),\n                    this.classificationResult\n                );\n            }\n            classifyForVideo(e, t, r) {\n                return (\n                    (this.classificationResult = { classifications: [] }),\n                    this.processVideoData(e, r, t),\n                    this.classificationResult\n                );\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(g), e.addInputStream(c), e.addOutputStream(u);\n                const t = new i.CalculatorOptions();\n                t.setExtension(s.ImageClassifierGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.image_classifier.ImageClassifierGraph'),\n                    r.addInputStream('IMAGE:' + g),\n                    r.addInputStream('NORM_RECT:' + c),\n                    r.addOutputStream('CLASSIFICATIONS:' + u),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.graphRunner.attachProtoListener(u, (e, t) => {\n                        (this.classificationResult = (0, d.convertFromClassificationResultProto)(\n                            a.ClassificationResult.deserializeBinary(e)\n                        )),\n                            this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(u, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    });\n                const n = e.serializeBinary();\n                this.setGraph(new Uint8Array(n), !0);\n            }\n        }\n        e.ImageClassifier = m;\n    })(image_classifier);\nvar image_embedder = {},\n    embeddings_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.tasks.components.containers.proto.Embedding', null, o),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.components.containers.proto.Embedding.EmbeddingCase',\n            null,\n            o\n        ),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.components.containers.proto.EmbeddingResult',\n            null,\n            o\n        ),\n        r.exportSymbol('proto.mediapipe.tasks.components.containers.proto.FloatEmbedding', null, o),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.tasks.components.containers.proto.FloatEmbedding, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.displayName =\n                'proto.mediapipe.tasks.components.containers.proto.FloatEmbedding'),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.displayName =\n                'proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding'),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                null,\n                proto.mediapipe.tasks.components.containers.proto.Embedding.oneofGroups_\n            );\n        }),\n        r.inherits(proto.mediapipe.tasks.components.containers.proto.Embedding, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.components.containers.proto.Embedding.displayName =\n                'proto.mediapipe.tasks.components.containers.proto.Embedding'),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.tasks.components.containers.proto.EmbeddingResult, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.displayName =\n                'proto.mediapipe.tasks.components.containers.proto.EmbeddingResult'),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        valuesList:\n                            null == (o = t.Message.getRepeatedFloatingPointField(r, 1))\n                                ? void 0\n                                : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.components.containers.proto.FloatEmbedding();\n            return proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber())\n                    for (\n                        var r = t.isDelimited() ? t.readPackedFloat() : [t.readFloat()], o = 0;\n                        o < r.length;\n                        o++\n                    )\n                        e.addValues(r[o]);\n                else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.serializeBinaryToWriter = function(\n            e,\n            t\n        ) {\n            var r;\n            (r = e.getValuesList()).length > 0 && t.writePackedFloat(1, r);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.prototype.getValuesList = function() {\n            return t.Message.getRepeatedFloatingPointField(this, 1);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.prototype.setValuesList = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e || []);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.prototype.addValues = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedField(this, 1, e, r);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.prototype.clearValuesList = function() {\n            return this.setValuesList([]);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.toObject = function(\n                e,\n                t\n            ) {\n                var r = { values: t.getValues_asB64() };\n                return e && (r.$jspbMessageInstance = t), r;\n            })),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding();\n            return proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = t.readBytes();\n                    e.setValues(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o;\n            null != (o = t.Message.getField(e, 1)) && r.writeBytes(1, o);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.prototype.getValues = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.prototype.getValues_asB64 = function() {\n            return t.Message.bytesAsB64(this.getValues());\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.prototype.getValues_asU8 = function() {\n            return t.Message.bytesAsU8(this.getValues());\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.prototype.setValues = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.prototype.clearValues = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.prototype.hasValues = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.oneofGroups_ = [[1, 2]]),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.EmbeddingCase = {\n            EMBEDDING_NOT_SET: 0,\n            FLOAT_EMBEDDING: 1,\n            QUANTIZED_EMBEDDING: 2,\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.getEmbeddingCase = function() {\n            return t.Message.computeOneofCase(\n                this,\n                proto.mediapipe.tasks.components.containers.proto.Embedding.oneofGroups_[0]\n            );\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.components.containers.proto.Embedding.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.components.containers.proto.Embedding.toObject = function(e, r) {\n                var o,\n                    i = {\n                        floatEmbedding:\n                            (o = r.getFloatEmbedding()) &&\n                            proto.mediapipe.tasks.components.containers.proto.FloatEmbedding.toObject(\n                                e,\n                                o\n                            ),\n                        quantizedEmbedding:\n                            (o = r.getQuantizedEmbedding()) &&\n                            proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding.toObject(\n                                e,\n                                o\n                            ),\n                        headIndex: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                        headName: null == (o = t.Message.getField(r, 4)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.components.containers.proto.Embedding();\n            return proto.mediapipe.tasks.components.containers.proto.Embedding.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.tasks.components.containers.proto.FloatEmbedding();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.tasks.components.containers.proto.FloatEmbedding\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setFloatEmbedding(r);\n                        break;\n                    case 2:\n                        r = new proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setQuantizedEmbedding(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setHeadIndex(r);\n                        break;\n                    case 4:\n                        r = t.readString();\n                        e.setHeadName(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.components.containers.proto.Embedding.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getFloatEmbedding()) &&\n                r.writeMessage(\n                    1,\n                    o,\n                    proto.mediapipe.tasks.components.containers.proto.FloatEmbedding\n                        .serializeBinaryToWriter\n                ),\n                null != (o = e.getQuantizedEmbedding()) &&\n                    r.writeMessage(\n                        2,\n                        o,\n                        proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding\n                            .serializeBinaryToWriter\n                    ),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeString(4, o);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.getFloatEmbedding = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.tasks.components.containers.proto.FloatEmbedding,\n                1\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.setFloatEmbedding = function(\n            e\n        ) {\n            return t.Message.setOneofWrapperField(\n                this,\n                1,\n                proto.mediapipe.tasks.components.containers.proto.Embedding.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.clearFloatEmbedding = function() {\n            return this.setFloatEmbedding(void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.hasFloatEmbedding = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.getQuantizedEmbedding = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.tasks.components.containers.proto.QuantizedEmbedding,\n                2\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.setQuantizedEmbedding = function(\n            e\n        ) {\n            return t.Message.setOneofWrapperField(\n                this,\n                2,\n                proto.mediapipe.tasks.components.containers.proto.Embedding.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.clearQuantizedEmbedding = function() {\n            return this.setQuantizedEmbedding(void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.hasQuantizedEmbedding = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.getHeadIndex = function() {\n            return t.Message.getFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.setHeadIndex = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.clearHeadIndex = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.hasHeadIndex = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.getHeadName = function() {\n            return t.Message.getFieldWithDefault(this, 4, '');\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.setHeadName = function(\n            e\n        ) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.clearHeadName = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.Embedding.prototype.hasHeadName = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        embeddingsList: t.Message.toObjectList(\n                            r.getEmbeddingsList(),\n                            proto.mediapipe.tasks.components.containers.proto.Embedding.toObject,\n                            e\n                        ),\n                        timestampMs: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.components.containers.proto.EmbeddingResult();\n            return proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.tasks.components.containers.proto.Embedding();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.tasks.components.containers.proto.Embedding\n                                .deserializeBinaryFromReader\n                        ),\n                            e.addEmbeddings(r);\n                        break;\n                    case 2:\n                        r = t.readInt64();\n                        e.setTimestampMs(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            (o = e.getEmbeddingsList()).length > 0 &&\n                r.writeRepeatedMessage(\n                    1,\n                    o,\n                    proto.mediapipe.tasks.components.containers.proto.Embedding\n                        .serializeBinaryToWriter\n                ),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt64(2, o);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.getEmbeddingsList = function() {\n            return t.Message.getRepeatedWrapperField(\n                this,\n                proto.mediapipe.tasks.components.containers.proto.Embedding,\n                1\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.setEmbeddingsList = function(\n            e\n        ) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.addEmbeddings = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.tasks.components.containers.proto.Embedding,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.clearEmbeddingsList = function() {\n            return this.setEmbeddingsList([]);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.getTimestampMs = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.setTimestampMs = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.clearTimestampMs = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.components.containers.proto.EmbeddingResult.prototype.hasTimestampMs = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        r.object.extend(e, proto.mediapipe.tasks.components.containers.proto);\n})(embeddings_pb);\nvar image_embedder_graph_options_pb = {},\n    embedder_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.tasks.components.processors.proto.EmbedderOptions', null, o),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.tasks.components.processors.proto.EmbedderOptions, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.displayName =\n                'proto.mediapipe.tasks.components.processors.proto.EmbedderOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        l2Normalize: null == (o = t.Message.getBooleanField(r, 1)) ? void 0 : o,\n                        quantize: null == (o = t.Message.getBooleanField(r, 2)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.components.processors.proto.EmbedderOptions();\n            return proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readBool();\n                        e.setL2Normalize(r);\n                        break;\n                    case 2:\n                        r = t.readBool();\n                        e.setQuantize(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeBool(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeBool(2, o);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.getL2Normalize = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 1, !1);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.setL2Normalize = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.clearL2Normalize = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.hasL2Normalize = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.getQuantize = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 2, !1);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.setQuantize = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.clearQuantize = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.components.processors.proto.EmbedderOptions.prototype.hasQuantize = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        r.object.extend(e, proto.mediapipe.tasks.components.processors.proto);\n})(embedder_options_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_pb;\n        r.object.extend(proto, i);\n        var a = calculator_options_pb;\n        r.object.extend(proto, a);\n        var n = embedder_options_pb;\n        r.object.extend(proto, n);\n        var s = base_options_pb;\n        r.object.extend(proto, s),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.toObject = function(\n                    e,\n                    t\n                ) {\n                    var r,\n                        o = {\n                            baseOptions: (r = t.getBaseOptions()) && s.BaseOptions.toObject(e, r),\n                            embedderOptions:\n                                (r = t.getEmbedderOptions()) && n.EmbedderOptions.toObject(e, r),\n                        };\n                    return e && (o.$jspbMessageInstance = t), o;\n                })),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions();\n                return proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new s.BaseOptions();\n                            t.readMessage(r, s.BaseOptions.deserializeBinaryFromReader),\n                                e.setBaseOptions(r);\n                            break;\n                        case 2:\n                            r = new n.EmbedderOptions();\n                            t.readMessage(r, n.EmbedderOptions.deserializeBinaryFromReader),\n                                e.setEmbedderOptions(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.serializeBinaryToWriter = function(\n                e,\n                t\n            ) {\n                var r = void 0;\n                null != (r = e.getBaseOptions()) &&\n                    t.writeMessage(1, r, s.BaseOptions.serializeBinaryToWriter),\n                    null != (r = e.getEmbedderOptions()) &&\n                        t.writeMessage(2, r, n.EmbedderOptions.serializeBinaryToWriter);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.ext = new t.ExtensionFieldInfo(\n                476348187,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions,\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[476348187] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[476348187] =\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.getBaseOptions = function() {\n                return t.Message.getWrapperField(this, s.BaseOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.setBaseOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.clearBaseOptions = function() {\n                return this.setBaseOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.hasBaseOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.getEmbedderOptions = function() {\n                return t.Message.getWrapperField(this, n.EmbedderOptions, 2);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.setEmbedderOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.clearEmbedderOptions = function() {\n                return this.setEmbedderOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.prototype.hasEmbedderOptions = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.ext = new t.ExtensionFieldInfo(\n                476348187,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions,\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[476348187] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[476348187] =\n                proto.mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.image_embedder.proto);\n    })(image_embedder_graph_options_pb);\nvar embedder_options = {};\nObject.defineProperty(embedder_options, '__esModule', { value: !0 }),\n    (embedder_options.convertEmbedderOptionsToProto = void 0);\nconst embedder_options_pb_1 = embedder_options_pb;\nfunction convertEmbedderOptionsToProto(e, t) {\n    const r = t ? t.clone() : new embedder_options_pb_1.EmbedderOptions();\n    return (\n        void 0 !== e.l2Normalize\n            ? r.setL2Normalize(e.l2Normalize)\n            : 'l2Normalize' in e && r.clearL2Normalize(),\n        void 0 !== e.quantize ? r.setQuantize(e.quantize) : 'quantize' in e && r.clearQuantize(),\n        r\n    );\n}\nembedder_options.convertEmbedderOptionsToProto = convertEmbedderOptionsToProto;\nvar embedder_result = {};\nObject.defineProperty(embedder_result, '__esModule', { value: !0 }),\n    (embedder_result.convertFromEmbeddingResultProto = void 0);\nconst DEFAULT_INDEX = -1;\nfunction convertFromEmbeddingsProto(e) {\n    var t, r, o, i;\n    const a = {\n        headIndex: null !== (t = e.getHeadIndex()) && void 0 !== t ? t : DEFAULT_INDEX,\n        headName: null !== (r = e.getHeadName()) && void 0 !== r ? r : '',\n    };\n    if (e.hasFloatEmbedding()) a.floatEmbedding = e.getFloatEmbedding().getValuesList();\n    else {\n        const t =\n            null !==\n                (i =\n                    null === (o = e.getQuantizedEmbedding()) || void 0 === o\n                        ? void 0\n                        : o.getValues()) && void 0 !== i\n                ? i\n                : '';\n        a.quantizedEmbedding =\n            'string' == typeof t ? Uint8Array.from(atob(t), (e) => e.charCodeAt(0)) : t;\n    }\n    return a;\n}\nfunction convertFromEmbeddingResultProto(e) {\n    return {\n        embeddings: e.getEmbeddingsList().map((e) => convertFromEmbeddingsProto(e)),\n        timestampMs: e.getTimestampMs(),\n    };\n}\nembedder_result.convertFromEmbeddingResultProto = convertFromEmbeddingResultProto;\nvar cosine_similarity = {};\nfunction computeCosineSimilarity(e, t) {\n    if (e.floatEmbedding && t.floatEmbedding) return compute(e.floatEmbedding, t.floatEmbedding);\n    if (e.quantizedEmbedding && t.quantizedEmbedding)\n        return compute(convertToBytes(e.quantizedEmbedding), convertToBytes(t.quantizedEmbedding));\n    throw new Error('Cannot compute cosine similarity between quantized and float embeddings.');\n}\nfunction convertToBytes(e) {\n    return Array.from(e, (e) => (e > 127 ? e - 256 : e));\n}\nfunction compute(e, t) {\n    if (e.length !== t.length)\n        throw new Error(\n            `Cannot compute cosine similarity between embeddings of different sizes (${e.length} vs. ${t.length}).`\n        );\n    let r = 0,\n        o = 0,\n        i = 0;\n    for (let a = 0; a < e.length; a++) (r += e[a] * t[a]), (o += e[a] * e[a]), (i += t[a] * t[a]);\n    if (o <= 0 || i <= 0)\n        throw new Error('Cannot compute cosine similarity on embedding with 0 norm.');\n    return r / Math.sqrt(o * i);\n}\nObject.defineProperty(cosine_similarity, '__esModule', { value: !0 }),\n    (cosine_similarity.computeCosineSimilarity = void 0),\n    (cosine_similarity.computeCosineSimilarity = computeCosineSimilarity);\nvar image_embedder_options = {};\nObject.defineProperty(image_embedder_options, '__esModule', { value: !0 });\nvar image_embedder_result = {};\nObject.defineProperty(image_embedder_result, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.ImageEmbedder = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = embeddings_pb,\n            n = base_options_pb,\n            s = image_embedder_graph_options_pb,\n            p = embedder_options,\n            d = embedder_result,\n            l = cosine_similarity,\n            g = vision_task_runner,\n            c = 'image_in',\n            u = 'norm_rect',\n            m = 'embeddings_out';\n        r(image_embedder_options, e), r(image_embedder_result, e);\n        class f extends g.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return g.VisionTaskRunner.createVisionInstance(f, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return g.VisionTaskRunner.createVisionInstance(f, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return g.VisionTaskRunner.createVisionInstance(f, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new g.VisionGraphRunner(e, t), c, u, !0),\n                    (this.options = new s.ImageEmbedderGraphOptions()),\n                    (this.embeddings = { embeddings: [] }),\n                    this.options.setBaseOptions(new n.BaseOptions());\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                return (\n                    this.options.setEmbedderOptions(\n                        (0, p.convertEmbedderOptionsToProto)(e, this.options.getEmbedderOptions())\n                    ),\n                    this.applyOptions(e)\n                );\n            }\n            embed(e, t) {\n                return this.processImageData(e, t), this.embeddings;\n            }\n            embedForVideo(e, t, r) {\n                return this.processVideoData(e, r, t), this.embeddings;\n            }\n            static cosineSimilarity(e, t) {\n                return (0, l.computeCosineSimilarity)(e, t);\n            }\n            addJsImageEmdedding(e) {\n                const t = a.EmbeddingResult.deserializeBinary(e);\n                this.embeddings = (0, d.convertFromEmbeddingResultProto)(t);\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(c), e.addInputStream(u), e.addOutputStream(m);\n                const t = new i.CalculatorOptions();\n                t.setExtension(s.ImageEmbedderGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.image_embedder.ImageEmbedderGraph'),\n                    r.addInputStream('IMAGE:' + c),\n                    r.addInputStream('NORM_RECT:' + u),\n                    r.addOutputStream('EMBEDDINGS:' + m),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.graphRunner.attachProtoListener(m, (e, t) => {\n                        this.addJsImageEmdedding(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(m, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    });\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        e.ImageEmbedder = f;\n    })(image_embedder);\nvar image_segmenter = {},\n    tensors_to_segmentation_calculator_pb = {},\n    segmenter_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions', null, o),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.Activation',\n            null,\n            o\n        ),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.OutputType',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.displayName =\n                'proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        outputType: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        activation: t.Message.getFieldWithDefault(r, 2, 0),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions();\n            return proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readEnum();\n                        e.setOutputType(r);\n                        break;\n                    case 2:\n                        r = t.readEnum();\n                        e.setActivation(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeEnum(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeEnum(2, o);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.OutputType = {\n            UNSPECIFIED: 0,\n            CATEGORY_MASK: 1,\n            CONFIDENCE_MASK: 2,\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.Activation = {\n            NONE: 0,\n            SIGMOID: 1,\n            SOFTMAX: 2,\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.getOutputType = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.setOutputType = function(\n            e\n        ) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.clearOutputType = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.hasOutputType = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.getActivation = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.setActivation = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.clearActivation = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.SegmenterOptions.prototype.hasActivation = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        r.object.extend(e, proto.mediapipe.tasks.vision.image_segmenter.proto);\n})(segmenter_options_pb);\nvar label_map_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.LabelMapItem', null, o),\n        (proto.mediapipe.LabelMapItem = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.LabelMapItem.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.LabelMapItem, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.LabelMapItem.displayName = 'proto.mediapipe.LabelMapItem'),\n        (proto.mediapipe.LabelMapItem.repeatedFields_ = [3]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.LabelMapItem.prototype.toObject = function(e) {\n                return proto.mediapipe.LabelMapItem.toObject(e, this);\n            }),\n            (proto.mediapipe.LabelMapItem.toObject = function(e, r) {\n                var o,\n                    i = {\n                        name: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        displayName: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        childNameList: null == (o = t.Message.getRepeatedField(r, 3)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.LabelMapItem.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.LabelMapItem();\n            return proto.mediapipe.LabelMapItem.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.LabelMapItem.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setName(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.setDisplayName(r);\n                        break;\n                    case 3:\n                        r = t.readString();\n                        e.addChildName(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.LabelMapItem.serializeBinaryToWriter(this, e), e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.LabelMapItem.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeString(2, o),\n                (o = e.getChildNameList()).length > 0 && r.writeRepeatedString(3, o);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.getName = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.setName = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.clearName = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.hasName = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.getDisplayName = function() {\n            return t.Message.getFieldWithDefault(this, 2, '');\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.setDisplayName = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.clearDisplayName = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.hasDisplayName = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.getChildNameList = function() {\n            return t.Message.getRepeatedField(this, 3);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.setChildNameList = function(e) {\n            return t.Message.setField(this, 3, e || []);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.addChildName = function(e, r) {\n            return t.Message.addToRepeatedField(this, 3, e, r);\n        }),\n        (proto.mediapipe.LabelMapItem.prototype.clearChildNameList = function() {\n            return this.setChildNameList([]);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(label_map_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_options_pb;\n        r.object.extend(proto, i);\n        var a = segmenter_options_pb;\n        r.object.extend(proto, a);\n        var n = label_map_pb;\n        r.object.extend(proto, n),\n            r.exportSymbol('proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions', null, o),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions = function(e) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions, t.Message),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.displayName =\n                    'proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.toObject = function(\n                    e,\n                    t\n                ) {\n                    var r,\n                        o = {\n                            segmenterOptions:\n                                (r = t.getSegmenterOptions()) && a.SegmenterOptions.toObject(e, r),\n                            labelItemsMap: (r = t.getLabelItemsMap())\n                                ? r.toObject(e, proto.mediapipe.LabelMapItem.toObject)\n                                : [],\n                        };\n                    return e && (o.$jspbMessageInstance = t), o;\n                })),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions();\n                return proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.deserializeBinaryFromReader = function(\n                e,\n                r\n            ) {\n                for (; r.nextField() && !r.isEndGroup(); ) {\n                    switch (r.getFieldNumber()) {\n                        case 1:\n                            var o = new a.SegmenterOptions();\n                            r.readMessage(o, a.SegmenterOptions.deserializeBinaryFromReader),\n                                e.setSegmenterOptions(o);\n                            break;\n                        case 2:\n                            o = e.getLabelItemsMap();\n                            r.readMessage(o, function(e, r) {\n                                t.Map.deserializeBinary(\n                                    e,\n                                    r,\n                                    t.BinaryReader.prototype.readInt64,\n                                    t.BinaryReader.prototype.readMessage,\n                                    proto.mediapipe.LabelMapItem.deserializeBinaryFromReader,\n                                    0,\n                                    new proto.mediapipe.LabelMapItem()\n                                );\n                            });\n                            break;\n                        default:\n                            r.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.serializeBinaryToWriter = function(\n                e,\n                r\n            ) {\n                var o = void 0;\n                null != (o = e.getSegmenterOptions()) &&\n                    r.writeMessage(1, o, a.SegmenterOptions.serializeBinaryToWriter),\n                    (o = e.getLabelItemsMap(!0)) &&\n                        o.getLength() > 0 &&\n                        o.serializeBinary(\n                            2,\n                            r,\n                            t.BinaryWriter.prototype.writeInt64,\n                            t.BinaryWriter.prototype.writeMessage,\n                            proto.mediapipe.LabelMapItem.serializeBinaryToWriter\n                        );\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.ext = new t.ExtensionFieldInfo(\n                458105876,\n                { ext: 0 },\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions,\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.toObject,\n                0\n            )),\n            (i.CalculatorOptions.extensionsBinary[458105876] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (i.CalculatorOptions.extensions[458105876] =\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.ext),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.prototype.getSegmenterOptions = function() {\n                return t.Message.getWrapperField(this, a.SegmenterOptions, 1);\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.prototype.setSegmenterOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.prototype.clearSegmenterOptions = function() {\n                return this.setSegmenterOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.prototype.hasSegmenterOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.prototype.getLabelItemsMap = function(\n                e\n            ) {\n                return t.Message.getMapField(this, 2, e, proto.mediapipe.LabelMapItem);\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.prototype.clearLabelItemsMap = function() {\n                return this.getLabelItemsMap().clear(), this;\n            }),\n            (proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.ext = new t.ExtensionFieldInfo(\n                458105876,\n                { ext: 0 },\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions,\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.toObject,\n                0\n            )),\n            (i.CalculatorOptions.extensionsBinary[458105876] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (i.CalculatorOptions.extensions[458105876] =\n                proto.mediapipe.tasks.TensorsToSegmentationCalculatorOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks);\n    })(tensors_to_segmentation_calculator_pb);\nvar image_segmenter_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n);\n    var s = segmenter_options_pb;\n    r.object.extend(proto, s),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions = function(\n            e\n        ) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                        displayNamesLocale: t.Message.getFieldWithDefault(r, 2, 'en'),\n                        segmenterOptions:\n                            (o = r.getSegmenterOptions()) && s.SegmenterOptions.toObject(e, o),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions();\n            return proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new n.BaseOptions();\n                        t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.setDisplayNamesLocale(r);\n                        break;\n                    case 3:\n                        r = new s.SegmenterOptions();\n                        t.readMessage(r, s.SegmenterOptions.deserializeBinaryFromReader),\n                            e.setSegmenterOptions(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getBaseOptions()) &&\n                r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 2)) && r.writeString(2, o),\n                null != (o = e.getSegmenterOptions()) &&\n                    r.writeMessage(3, o, s.SegmenterOptions.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.ext = new t.ExtensionFieldInfo(\n            458105758,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions,\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[458105758] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[458105758] =\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.getDisplayNamesLocale = function() {\n            return t.Message.getFieldWithDefault(this, 2, 'en');\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.setDisplayNamesLocale = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.clearDisplayNamesLocale = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.hasDisplayNamesLocale = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.getSegmenterOptions = function() {\n            return t.Message.getWrapperField(this, s.SegmenterOptions, 3);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.setSegmenterOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.clearSegmenterOptions = function() {\n            return this.setSegmenterOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.prototype.hasSegmenterOptions = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.ext = new t.ExtensionFieldInfo(\n            458105758,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions,\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[458105758] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[458105758] =\n            proto.mediapipe.tasks.vision.image_segmenter.proto.ImageSegmenterGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.image_segmenter.proto);\n})(image_segmenter_graph_options_pb);\nvar image_segmenter_result = {};\nObject.defineProperty(image_segmenter_result, '__esModule', { value: !0 }),\n    (image_segmenter_result.ImageSegmenterResult = void 0);\nclass ImageSegmenterResult {\n    constructor(e, t, r) {\n        (this.confidenceMasks = e), (this.categoryMask = t), (this.qualityScores = r);\n    }\n    close() {\n        var e, t;\n        null === (e = this.confidenceMasks) ||\n            void 0 === e ||\n            e.forEach((e) => {\n                e.close();\n            }),\n            null === (t = this.categoryMask) || void 0 === t || t.close();\n    }\n}\nimage_segmenter_result.ImageSegmenterResult = ImageSegmenterResult;\nvar image_segmenter_options = {};\nObject.defineProperty(image_segmenter_options, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.ImageSegmenter = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = base_options_pb,\n            n = tensors_to_segmentation_calculator_pb,\n            s = image_segmenter_graph_options_pb,\n            p = segmenter_options_pb,\n            d = vision_task_runner,\n            l = image_segmenter_result;\n        r(image_segmenter_options, e), r(image_segmenter_result, e);\n        const g = 'image_in',\n            c = 'norm_rect',\n            u = 'confidence_masks',\n            m = 'category_mask',\n            f = 'quality_scores',\n            h = 'mediapipe.tasks.TensorsToSegmentationCalculator';\n        class y extends d.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(y, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(y, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(y, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new d.VisionGraphRunner(e, t), g, c, !1),\n                    (this.labels = []),\n                    (this.outputCategoryMask = false),\n                    (this.outputConfidenceMasks = true),\n                    (this.options = new s.ImageSegmenterGraphOptions()),\n                    (this.segmenterOptions = new p.SegmenterOptions()),\n                    this.options.setSegmenterOptions(this.segmenterOptions),\n                    this.options.setBaseOptions(new a.BaseOptions());\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                var t, r;\n                return (\n                    void 0 !== e.displayNamesLocale\n                        ? this.options.setDisplayNamesLocale(e.displayNamesLocale)\n                        : 'displayNamesLocale' in e && this.options.clearDisplayNamesLocale(),\n                    'outputCategoryMask' in e &&\n                        (this.outputCategoryMask =\n                            null !== (t = e.outputCategoryMask) && void 0 !== t && t),\n                    'outputConfidenceMasks' in e &&\n                        (this.outputConfidenceMasks =\n                            null === (r = e.outputConfidenceMasks) || void 0 === r || r),\n                    super.applyOptions(e)\n                );\n            }\n            onGraphRefreshed() {\n                this.populateLabels();\n            }\n            populateLabels() {\n                var e, t, r;\n                const o = this.getCalculatorGraphConfig()\n                    .getNodeList()\n                    .filter((e) => e.getName().includes(h));\n                if (((this.labels = []), o.length > 1))\n                    throw new Error(`The graph has more than one ${h}.`);\n                if (1 === o.length) {\n                    (null !==\n                        (r =\n                            null ===\n                                (t =\n                                    null === (e = o[0].getOptions()) || void 0 === e\n                                        ? void 0\n                                        : e.getExtension(\n                                              n.TensorsToSegmentationCalculatorOptions.ext\n                                          )) || void 0 === t\n                                ? void 0\n                                : t.getLabelItemsMap()) && void 0 !== r\n                        ? r\n                        : new Map()\n                    ).forEach((e, t) => {\n                        this.labels[Number(t)] = e.getName();\n                    });\n                }\n            }\n            segment(e, t, r) {\n                const o = 'function' != typeof t ? t : {};\n                return (\n                    (this.userCallback = 'function' == typeof t ? t : r),\n                    this.reset(),\n                    this.processImageData(e, o),\n                    this.processResults()\n                );\n            }\n            segmentForVideo(e, t, r, o) {\n                const i = 'function' != typeof r ? r : {};\n                return (\n                    (this.userCallback = 'function' == typeof r ? r : o),\n                    this.reset(),\n                    this.processVideoData(e, i, t),\n                    this.processResults()\n                );\n            }\n            getLabels() {\n                return this.labels;\n            }\n            reset() {\n                (this.categoryMask = void 0),\n                    (this.confidenceMasks = void 0),\n                    (this.qualityScores = void 0);\n            }\n            processResults() {\n                try {\n                    const e = new l.ImageSegmenterResult(\n                        this.confidenceMasks,\n                        this.categoryMask,\n                        this.qualityScores\n                    );\n                    if (!this.userCallback) return e;\n                    this.userCallback(e);\n                } finally {\n                    this.freeKeepaliveStreams();\n                }\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(g), e.addInputStream(c);\n                const t = new i.CalculatorOptions();\n                t.setExtension(s.ImageSegmenterGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.image_segmenter.ImageSegmenterGraph'),\n                    r.addInputStream('IMAGE:' + g),\n                    r.addInputStream('NORM_RECT:' + c),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.addKeepaliveNode(e),\n                    this.outputConfidenceMasks &&\n                        (e.addOutputStream(u),\n                        r.addOutputStream('CONFIDENCE_MASKS:' + u),\n                        this.keepStreamAlive(u),\n                        this.graphRunner.attachImageVectorListener(u, (e, t) => {\n                            (this.confidenceMasks = e.map((e) =>\n                                this.convertToMPMask(e, !this.userCallback)\n                            )),\n                                this.setLatestOutputTimestamp(t);\n                        }),\n                        this.graphRunner.attachEmptyPacketListener(u, (e) => {\n                            (this.confidenceMasks = []), this.setLatestOutputTimestamp(e);\n                        })),\n                    this.outputCategoryMask &&\n                        (e.addOutputStream(m),\n                        r.addOutputStream('CATEGORY_MASK:' + m),\n                        this.keepStreamAlive(m),\n                        this.graphRunner.attachImageListener(m, (e, t) => {\n                            (this.categoryMask = this.convertToMPMask(e, !this.userCallback)),\n                                this.setLatestOutputTimestamp(t);\n                        }),\n                        this.graphRunner.attachEmptyPacketListener(m, (e) => {\n                            (this.categoryMask = void 0), this.setLatestOutputTimestamp(e);\n                        })),\n                    e.addOutputStream(f),\n                    r.addOutputStream('QUALITY_SCORES:' + f),\n                    this.graphRunner.attachFloatVectorListener(f, (e, t) => {\n                        (this.qualityScores = e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(f, (e) => {\n                        (this.categoryMask = void 0), this.setLatestOutputTimestamp(e);\n                    });\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        e.ImageSegmenter = y;\n    })(image_segmenter);\nvar interactive_segmenter = {},\n    color_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')();\n    r.exportSymbol('proto.mediapipe.Color', null, o),\n        r.exportSymbol('proto.mediapipe.ColorMap', null, o),\n        (proto.mediapipe.Color = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.Color, t.Message),\n        r.DEBUG && !COMPILED && (proto.mediapipe.Color.displayName = 'proto.mediapipe.Color'),\n        (proto.mediapipe.ColorMap = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.ColorMap, t.Message),\n        r.DEBUG && !COMPILED && (proto.mediapipe.ColorMap.displayName = 'proto.mediapipe.ColorMap'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.Color.prototype.toObject = function(e) {\n                return proto.mediapipe.Color.toObject(e, this);\n            }),\n            (proto.mediapipe.Color.toObject = function(e, r) {\n                var o,\n                    i = {\n                        r: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        g: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        b: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.Color.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.Color();\n            return proto.mediapipe.Color.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.Color.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readInt32();\n                        e.setR(r);\n                        break;\n                    case 2:\n                        r = t.readInt32();\n                        e.setG(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setB(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.Color.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return proto.mediapipe.Color.serializeBinaryToWriter(this, e), e.getResultBuffer();\n        }),\n        (proto.mediapipe.Color.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeInt32(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o);\n        }),\n        (proto.mediapipe.Color.prototype.getR = function() {\n            return t.Message.getFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.Color.prototype.setR = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.Color.prototype.clearR = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.Color.prototype.hasR = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.Color.prototype.getG = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.Color.prototype.setG = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.Color.prototype.clearG = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.Color.prototype.hasG = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.Color.prototype.getB = function() {\n            return t.Message.getFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.Color.prototype.setB = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.Color.prototype.clearB = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.Color.prototype.hasB = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.ColorMap.prototype.toObject = function(e) {\n                return proto.mediapipe.ColorMap.toObject(e, this);\n            }),\n            (proto.mediapipe.ColorMap.toObject = function(e, t) {\n                var r,\n                    o = {\n                        labelToColorMap: (r = t.getLabelToColorMap())\n                            ? r.toObject(e, proto.mediapipe.Color.toObject)\n                            : [],\n                    };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.ColorMap.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.ColorMap();\n            return proto.mediapipe.ColorMap.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.ColorMap.deserializeBinaryFromReader = function(e, r) {\n            for (; r.nextField() && !r.isEndGroup(); ) {\n                if (1 === r.getFieldNumber()) {\n                    var o = e.getLabelToColorMap();\n                    r.readMessage(o, function(e, r) {\n                        t.Map.deserializeBinary(\n                            e,\n                            r,\n                            t.BinaryReader.prototype.readString,\n                            t.BinaryReader.prototype.readMessage,\n                            proto.mediapipe.Color.deserializeBinaryFromReader,\n                            '',\n                            new proto.mediapipe.Color()\n                        );\n                    });\n                } else r.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.ColorMap.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return proto.mediapipe.ColorMap.serializeBinaryToWriter(this, e), e.getResultBuffer();\n        }),\n        (proto.mediapipe.ColorMap.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            (o = e.getLabelToColorMap(!0)) &&\n                o.getLength() > 0 &&\n                o.serializeBinary(\n                    1,\n                    r,\n                    t.BinaryWriter.prototype.writeString,\n                    t.BinaryWriter.prototype.writeMessage,\n                    proto.mediapipe.Color.serializeBinaryToWriter\n                );\n        }),\n        (proto.mediapipe.ColorMap.prototype.getLabelToColorMap = function(e) {\n            return t.Message.getMapField(this, 1, e, proto.mediapipe.Color);\n        }),\n        (proto.mediapipe.ColorMap.prototype.clearLabelToColorMap = function() {\n            return this.getLabelToColorMap().clear(), this;\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(color_pb);\nvar render_data_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = color_pb;\n    r.object.extend(proto, i),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.Arrow', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.DataCase', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.FilledOval', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.FilledRectangle', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.FilledRoundedRectangle', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.GradientLine', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.Line', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.Line.LineType', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.Oval', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.Point', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.Rectangle', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.RoundedRectangle', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.Scribble', null, o),\n        r.exportSymbol('proto.mediapipe.RenderAnnotation.Text', null, o),\n        r.exportSymbol('proto.mediapipe.RenderData', null, o),\n        r.exportSymbol('proto.mediapipe.RenderViewport', null, o),\n        (proto.mediapipe.RenderData = function(e) {\n            t.Message.initialize(this, e, 0, -1, proto.mediapipe.RenderData.repeatedFields_, null);\n        }),\n        r.inherits(proto.mediapipe.RenderData, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderData.displayName = 'proto.mediapipe.RenderData'),\n        (proto.mediapipe.RenderAnnotation = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                null,\n                proto.mediapipe.RenderAnnotation.oneofGroups_\n            );\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.displayName = 'proto.mediapipe.RenderAnnotation'),\n        (proto.mediapipe.RenderAnnotation.Rectangle = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.Rectangle, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.Rectangle.displayName =\n                'proto.mediapipe.RenderAnnotation.Rectangle'),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.FilledRectangle, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.FilledRectangle.displayName =\n                'proto.mediapipe.RenderAnnotation.FilledRectangle'),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.RoundedRectangle, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.RoundedRectangle.displayName =\n                'proto.mediapipe.RenderAnnotation.RoundedRectangle'),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.FilledRoundedRectangle, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.displayName =\n                'proto.mediapipe.RenderAnnotation.FilledRoundedRectangle'),\n        (proto.mediapipe.RenderAnnotation.Oval = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.Oval, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.Oval.displayName =\n                'proto.mediapipe.RenderAnnotation.Oval'),\n        (proto.mediapipe.RenderAnnotation.FilledOval = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.FilledOval, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.FilledOval.displayName =\n                'proto.mediapipe.RenderAnnotation.FilledOval'),\n        (proto.mediapipe.RenderAnnotation.Point = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.Point, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.Point.displayName =\n                'proto.mediapipe.RenderAnnotation.Point'),\n        (proto.mediapipe.RenderAnnotation.Line = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.Line, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.Line.displayName =\n                'proto.mediapipe.RenderAnnotation.Line'),\n        (proto.mediapipe.RenderAnnotation.GradientLine = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.GradientLine, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.GradientLine.displayName =\n                'proto.mediapipe.RenderAnnotation.GradientLine'),\n        (proto.mediapipe.RenderAnnotation.Scribble = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.RenderAnnotation.Scribble.repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.Scribble, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.Scribble.displayName =\n                'proto.mediapipe.RenderAnnotation.Scribble'),\n        (proto.mediapipe.RenderAnnotation.Arrow = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.Arrow, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.Arrow.displayName =\n                'proto.mediapipe.RenderAnnotation.Arrow'),\n        (proto.mediapipe.RenderAnnotation.Text = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderAnnotation.Text, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderAnnotation.Text.displayName =\n                'proto.mediapipe.RenderAnnotation.Text'),\n        (proto.mediapipe.RenderViewport = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(proto.mediapipe.RenderViewport, t.Message),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.RenderViewport.displayName = 'proto.mediapipe.RenderViewport'),\n        (proto.mediapipe.RenderData.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderData.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderData.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderData.toObject = function(e, r) {\n                var o,\n                    i = {\n                        renderAnnotationsList: t.Message.toObjectList(\n                            r.getRenderAnnotationsList(),\n                            proto.mediapipe.RenderAnnotation.toObject,\n                            e\n                        ),\n                        sceneClass: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        sceneViewport:\n                            (o = r.getSceneViewport()) &&\n                            proto.mediapipe.RenderViewport.toObject(e, o),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.RenderData.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderData();\n            return proto.mediapipe.RenderData.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderData.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.RenderAnnotation();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.deserializeBinaryFromReader\n                        ),\n                            e.addRenderAnnotations(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.setSceneClass(r);\n                        break;\n                    case 3:\n                        r = new proto.mediapipe.RenderViewport();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderViewport.deserializeBinaryFromReader\n                        ),\n                            e.setSceneViewport(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderData.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return proto.mediapipe.RenderData.serializeBinaryToWriter(this, e), e.getResultBuffer();\n        }),\n        (proto.mediapipe.RenderData.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            (o = e.getRenderAnnotationsList()).length > 0 &&\n                r.writeRepeatedMessage(\n                    1,\n                    o,\n                    proto.mediapipe.RenderAnnotation.serializeBinaryToWriter\n                ),\n                null != (o = t.Message.getField(e, 2)) && r.writeString(2, o),\n                null != (o = e.getSceneViewport()) &&\n                    r.writeMessage(3, o, proto.mediapipe.RenderViewport.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.RenderData.prototype.getRenderAnnotationsList = function() {\n            return t.Message.getRepeatedWrapperField(this, proto.mediapipe.RenderAnnotation, 1);\n        }),\n        (proto.mediapipe.RenderData.prototype.setRenderAnnotationsList = function(e) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderData.prototype.addRenderAnnotations = function(e, r) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.RenderAnnotation,\n                r\n            );\n        }),\n        (proto.mediapipe.RenderData.prototype.clearRenderAnnotationsList = function() {\n            return this.setRenderAnnotationsList([]);\n        }),\n        (proto.mediapipe.RenderData.prototype.getSceneClass = function() {\n            return t.Message.getFieldWithDefault(this, 2, '');\n        }),\n        (proto.mediapipe.RenderData.prototype.setSceneClass = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderData.prototype.clearSceneClass = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderData.prototype.hasSceneClass = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderData.prototype.getSceneViewport = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderViewport, 3);\n        }),\n        (proto.mediapipe.RenderData.prototype.setSceneViewport = function(e) {\n            return t.Message.setWrapperField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderData.prototype.clearSceneViewport = function() {\n            return this.setSceneViewport(void 0);\n        }),\n        (proto.mediapipe.RenderData.prototype.hasSceneViewport = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.RenderAnnotation.oneofGroups_ = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 14, 15]]),\n        (proto.mediapipe.RenderAnnotation.DataCase = {\n            DATA_NOT_SET: 0,\n            RECTANGLE: 1,\n            FILLED_RECTANGLE: 2,\n            OVAL: 3,\n            FILLED_OVAL: 4,\n            POINT: 5,\n            LINE: 6,\n            ARROW: 7,\n            TEXT: 8,\n            ROUNDED_RECTANGLE: 9,\n            FILLED_ROUNDED_RECTANGLE: 10,\n            GRADIENT_LINE: 14,\n            SCRIBBLE: 15,\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getDataCase = function() {\n            return t.Message.computeOneofCase(\n                this,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0]\n            );\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.toObject = function(e, r) {\n                var o,\n                    a = {\n                        rectangle:\n                            (o = r.getRectangle()) &&\n                            proto.mediapipe.RenderAnnotation.Rectangle.toObject(e, o),\n                        filledRectangle:\n                            (o = r.getFilledRectangle()) &&\n                            proto.mediapipe.RenderAnnotation.FilledRectangle.toObject(e, o),\n                        oval:\n                            (o = r.getOval()) &&\n                            proto.mediapipe.RenderAnnotation.Oval.toObject(e, o),\n                        filledOval:\n                            (o = r.getFilledOval()) &&\n                            proto.mediapipe.RenderAnnotation.FilledOval.toObject(e, o),\n                        point:\n                            (o = r.getPoint()) &&\n                            proto.mediapipe.RenderAnnotation.Point.toObject(e, o),\n                        line:\n                            (o = r.getLine()) &&\n                            proto.mediapipe.RenderAnnotation.Line.toObject(e, o),\n                        arrow:\n                            (o = r.getArrow()) &&\n                            proto.mediapipe.RenderAnnotation.Arrow.toObject(e, o),\n                        text:\n                            (o = r.getText()) &&\n                            proto.mediapipe.RenderAnnotation.Text.toObject(e, o),\n                        roundedRectangle:\n                            (o = r.getRoundedRectangle()) &&\n                            proto.mediapipe.RenderAnnotation.RoundedRectangle.toObject(e, o),\n                        filledRoundedRectangle:\n                            (o = r.getFilledRoundedRectangle()) &&\n                            proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.toObject(e, o),\n                        gradientLine:\n                            (o = r.getGradientLine()) &&\n                            proto.mediapipe.RenderAnnotation.GradientLine.toObject(e, o),\n                        scribble:\n                            (o = r.getScribble()) &&\n                            proto.mediapipe.RenderAnnotation.Scribble.toObject(e, o),\n                        thickness: t.Message.getFloatingPointFieldWithDefault(r, 11, 1),\n                        color: (o = r.getColor()) && i.Color.toObject(e, o),\n                        sceneTag: null == (o = t.Message.getField(r, 13)) ? void 0 : o,\n                    };\n                return e && (a.$jspbMessageInstance = r), a;\n            })),\n        (proto.mediapipe.RenderAnnotation.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation();\n            return proto.mediapipe.RenderAnnotation.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.RenderAnnotation.Rectangle();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Rectangle.deserializeBinaryFromReader\n                        ),\n                            e.setRectangle(r);\n                        break;\n                    case 2:\n                        r = new proto.mediapipe.RenderAnnotation.FilledRectangle();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.FilledRectangle\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setFilledRectangle(r);\n                        break;\n                    case 3:\n                        r = new proto.mediapipe.RenderAnnotation.Oval();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Oval.deserializeBinaryFromReader\n                        ),\n                            e.setOval(r);\n                        break;\n                    case 4:\n                        r = new proto.mediapipe.RenderAnnotation.FilledOval();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.FilledOval.deserializeBinaryFromReader\n                        ),\n                            e.setFilledOval(r);\n                        break;\n                    case 5:\n                        r = new proto.mediapipe.RenderAnnotation.Point();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Point.deserializeBinaryFromReader\n                        ),\n                            e.setPoint(r);\n                        break;\n                    case 6:\n                        r = new proto.mediapipe.RenderAnnotation.Line();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Line.deserializeBinaryFromReader\n                        ),\n                            e.setLine(r);\n                        break;\n                    case 7:\n                        r = new proto.mediapipe.RenderAnnotation.Arrow();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Arrow.deserializeBinaryFromReader\n                        ),\n                            e.setArrow(r);\n                        break;\n                    case 8:\n                        r = new proto.mediapipe.RenderAnnotation.Text();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Text.deserializeBinaryFromReader\n                        ),\n                            e.setText(r);\n                        break;\n                    case 9:\n                        r = new proto.mediapipe.RenderAnnotation.RoundedRectangle();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.RoundedRectangle\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setRoundedRectangle(r);\n                        break;\n                    case 10:\n                        r = new proto.mediapipe.RenderAnnotation.FilledRoundedRectangle();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.FilledRoundedRectangle\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setFilledRoundedRectangle(r);\n                        break;\n                    case 14:\n                        r = new proto.mediapipe.RenderAnnotation.GradientLine();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.GradientLine\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setGradientLine(r);\n                        break;\n                    case 15:\n                        r = new proto.mediapipe.RenderAnnotation.Scribble();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Scribble.deserializeBinaryFromReader\n                        ),\n                            e.setScribble(r);\n                        break;\n                    case 11:\n                        r = t.readDouble();\n                        e.setThickness(r);\n                        break;\n                    case 12:\n                        r = new i.Color();\n                        t.readMessage(r, i.Color.deserializeBinaryFromReader), e.setColor(r);\n                        break;\n                    case 13:\n                        r = t.readString();\n                        e.setSceneTag(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = e.getRectangle()) &&\n                r.writeMessage(\n                    1,\n                    o,\n                    proto.mediapipe.RenderAnnotation.Rectangle.serializeBinaryToWriter\n                ),\n                null != (o = e.getFilledRectangle()) &&\n                    r.writeMessage(\n                        2,\n                        o,\n                        proto.mediapipe.RenderAnnotation.FilledRectangle.serializeBinaryToWriter\n                    ),\n                null != (o = e.getOval()) &&\n                    r.writeMessage(\n                        3,\n                        o,\n                        proto.mediapipe.RenderAnnotation.Oval.serializeBinaryToWriter\n                    ),\n                null != (o = e.getFilledOval()) &&\n                    r.writeMessage(\n                        4,\n                        o,\n                        proto.mediapipe.RenderAnnotation.FilledOval.serializeBinaryToWriter\n                    ),\n                null != (o = e.getPoint()) &&\n                    r.writeMessage(\n                        5,\n                        o,\n                        proto.mediapipe.RenderAnnotation.Point.serializeBinaryToWriter\n                    ),\n                null != (o = e.getLine()) &&\n                    r.writeMessage(\n                        6,\n                        o,\n                        proto.mediapipe.RenderAnnotation.Line.serializeBinaryToWriter\n                    ),\n                null != (o = e.getArrow()) &&\n                    r.writeMessage(\n                        7,\n                        o,\n                        proto.mediapipe.RenderAnnotation.Arrow.serializeBinaryToWriter\n                    ),\n                null != (o = e.getText()) &&\n                    r.writeMessage(\n                        8,\n                        o,\n                        proto.mediapipe.RenderAnnotation.Text.serializeBinaryToWriter\n                    ),\n                null != (o = e.getRoundedRectangle()) &&\n                    r.writeMessage(\n                        9,\n                        o,\n                        proto.mediapipe.RenderAnnotation.RoundedRectangle.serializeBinaryToWriter\n                    ),\n                null != (o = e.getFilledRoundedRectangle()) &&\n                    r.writeMessage(\n                        10,\n                        o,\n                        proto.mediapipe.RenderAnnotation.FilledRoundedRectangle\n                            .serializeBinaryToWriter\n                    ),\n                null != (o = e.getGradientLine()) &&\n                    r.writeMessage(\n                        14,\n                        o,\n                        proto.mediapipe.RenderAnnotation.GradientLine.serializeBinaryToWriter\n                    ),\n                null != (o = e.getScribble()) &&\n                    r.writeMessage(\n                        15,\n                        o,\n                        proto.mediapipe.RenderAnnotation.Scribble.serializeBinaryToWriter\n                    ),\n                null != (o = t.Message.getField(e, 11)) && r.writeDouble(11, o),\n                null != (o = e.getColor()) &&\n                    r.writeMessage(12, o, i.Color.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 13)) && r.writeString(13, o);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.Rectangle.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.Rectangle.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.Rectangle.toObject = function(e, r) {\n                var o,\n                    i = {\n                        left:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 1))\n                                ? void 0\n                                : o,\n                        top:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                ? void 0\n                                : o,\n                        right:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        bottom:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                ? void 0\n                                : o,\n                        normalized: t.Message.getBooleanFieldWithDefault(r, 5, !1),\n                        rotation:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 6))\n                                ? void 0\n                                : o,\n                        topLeftThickness:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 7))\n                                ? void 0\n                                : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.RenderAnnotation.Rectangle.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.Rectangle();\n            return proto.mediapipe.RenderAnnotation.Rectangle.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readDouble();\n                        e.setLeft(r);\n                        break;\n                    case 2:\n                        r = t.readDouble();\n                        e.setTop(r);\n                        break;\n                    case 3:\n                        r = t.readDouble();\n                        e.setRight(r);\n                        break;\n                    case 4:\n                        r = t.readDouble();\n                        e.setBottom(r);\n                        break;\n                    case 5:\n                        r = t.readBool();\n                        e.setNormalized(r);\n                        break;\n                    case 6:\n                        r = t.readDouble();\n                        e.setRotation(r);\n                        break;\n                    case 7:\n                        r = t.readDouble();\n                        e.setTopLeftThickness(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.Rectangle.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeDouble(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeDouble(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeDouble(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeDouble(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeBool(5, o),\n                null != (o = t.Message.getField(e, 6)) && r.writeDouble(6, o),\n                null != (o = t.Message.getField(e, 7)) && r.writeDouble(7, o);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.getLeft = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.setLeft = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.clearLeft = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.hasLeft = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.getTop = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.setTop = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.clearTop = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.hasTop = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.getRight = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.setRight = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.clearRight = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.hasRight = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.getBottom = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.setBottom = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.clearBottom = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.hasBottom = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.getNormalized = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 5, !1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.setNormalized = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.clearNormalized = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.hasNormalized = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.getRotation = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 6, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.setRotation = function(e) {\n            return t.Message.setField(this, 6, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.clearRotation = function() {\n            return t.Message.setField(this, 6, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.hasRotation = function() {\n            return null != t.Message.getField(this, 6);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.getTopLeftThickness = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 7, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.setTopLeftThickness = function(e) {\n            return t.Message.setField(this, 7, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.clearTopLeftThickness = function() {\n            return t.Message.setField(this, 7, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Rectangle.prototype.hasTopLeftThickness = function() {\n            return null != t.Message.getField(this, 7);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.FilledRectangle.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.FilledRectangle.toObject = function(e, t) {\n                var r,\n                    o = {\n                        rectangle:\n                            (r = t.getRectangle()) &&\n                            proto.mediapipe.RenderAnnotation.Rectangle.toObject(e, r),\n                        fillColor: (r = t.getFillColor()) && i.Color.toObject(e, r),\n                    };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.FilledRectangle();\n            return proto.mediapipe.RenderAnnotation.FilledRectangle.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.RenderAnnotation.Rectangle();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Rectangle.deserializeBinaryFromReader\n                        ),\n                            e.setRectangle(r);\n                        break;\n                    case 2:\n                        r = new i.Color();\n                        t.readMessage(r, i.Color.deserializeBinaryFromReader), e.setFillColor(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.FilledRectangle.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.serializeBinaryToWriter = function(e, t) {\n            var r = void 0;\n            null != (r = e.getRectangle()) &&\n                t.writeMessage(\n                    1,\n                    r,\n                    proto.mediapipe.RenderAnnotation.Rectangle.serializeBinaryToWriter\n                ),\n                null != (r = e.getFillColor()) &&\n                    t.writeMessage(2, r, i.Color.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.getRectangle = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Rectangle, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.setRectangle = function(e) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.clearRectangle = function() {\n            return this.setRectangle(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.hasRectangle = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.getFillColor = function() {\n            return t.Message.getWrapperField(this, i.Color, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.setFillColor = function(e) {\n            return t.Message.setWrapperField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.clearFillColor = function() {\n            return this.setFillColor(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRectangle.prototype.hasFillColor = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.RoundedRectangle.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.RoundedRectangle.toObject = function(e, r) {\n                var o,\n                    i = {\n                        rectangle:\n                            (o = r.getRectangle()) &&\n                            proto.mediapipe.RenderAnnotation.Rectangle.toObject(e, o),\n                        cornerRadius: t.Message.getFieldWithDefault(r, 2, 0),\n                        lineType: t.Message.getFieldWithDefault(r, 3, 4),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.RoundedRectangle();\n            return proto.mediapipe.RenderAnnotation.RoundedRectangle.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.RenderAnnotation.Rectangle();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Rectangle.deserializeBinaryFromReader\n                        ),\n                            e.setRectangle(r);\n                        break;\n                    case 2:\n                        r = t.readInt32();\n                        e.setCornerRadius(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setLineType(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.RoundedRectangle.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getRectangle()) &&\n                r.writeMessage(\n                    1,\n                    o,\n                    proto.mediapipe.RenderAnnotation.Rectangle.serializeBinaryToWriter\n                ),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.getRectangle = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Rectangle, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.setRectangle = function(e) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.clearRectangle = function() {\n            return this.setRectangle(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.hasRectangle = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.getCornerRadius = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.setCornerRadius = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.clearCornerRadius = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.hasCornerRadius = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.getLineType = function() {\n            return t.Message.getFieldWithDefault(this, 3, 4);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.setLineType = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.clearLineType = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.RoundedRectangle.prototype.hasLineType = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.toObject = function(e, t) {\n                var r,\n                    o = {\n                        roundedRectangle:\n                            (r = t.getRoundedRectangle()) &&\n                            proto.mediapipe.RenderAnnotation.RoundedRectangle.toObject(e, r),\n                        fillColor: (r = t.getFillColor()) && i.Color.toObject(e, r),\n                    };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.FilledRoundedRectangle();\n            return proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.RenderAnnotation.RoundedRectangle();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.RoundedRectangle\n                                .deserializeBinaryFromReader\n                        ),\n                            e.setRoundedRectangle(r);\n                        break;\n                    case 2:\n                        r = new i.Color();\n                        t.readMessage(r, i.Color.deserializeBinaryFromReader), e.setFillColor(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.serializeBinaryToWriter = function(\n            e,\n            t\n        ) {\n            var r = void 0;\n            null != (r = e.getRoundedRectangle()) &&\n                t.writeMessage(\n                    1,\n                    r,\n                    proto.mediapipe.RenderAnnotation.RoundedRectangle.serializeBinaryToWriter\n                ),\n                null != (r = e.getFillColor()) &&\n                    t.writeMessage(2, r, i.Color.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.getRoundedRectangle = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.RenderAnnotation.RoundedRectangle,\n                1\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.setRoundedRectangle = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.clearRoundedRectangle = function() {\n            return this.setRoundedRectangle(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.hasRoundedRectangle = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.getFillColor = function() {\n            return t.Message.getWrapperField(this, i.Color, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.setFillColor = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.clearFillColor = function() {\n            return this.setFillColor(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledRoundedRectangle.prototype.hasFillColor = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.Oval.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.Oval.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.Oval.toObject = function(e, t) {\n                var r,\n                    o = {\n                        rectangle:\n                            (r = t.getRectangle()) &&\n                            proto.mediapipe.RenderAnnotation.Rectangle.toObject(e, r),\n                    };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.RenderAnnotation.Oval.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.Oval();\n            return proto.mediapipe.RenderAnnotation.Oval.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.Oval.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.RenderAnnotation.Rectangle();\n                    t.readMessage(\n                        r,\n                        proto.mediapipe.RenderAnnotation.Rectangle.deserializeBinaryFromReader\n                    ),\n                        e.setRectangle(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.Oval.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.Oval.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Oval.serializeBinaryToWriter = function(e, t) {\n            var r;\n            null != (r = e.getRectangle()) &&\n                t.writeMessage(\n                    1,\n                    r,\n                    proto.mediapipe.RenderAnnotation.Rectangle.serializeBinaryToWriter\n                );\n        }),\n        (proto.mediapipe.RenderAnnotation.Oval.prototype.getRectangle = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Rectangle, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Oval.prototype.setRectangle = function(e) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Oval.prototype.clearRectangle = function() {\n            return this.setRectangle(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Oval.prototype.hasRectangle = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.FilledOval.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.FilledOval.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.FilledOval.toObject = function(e, t) {\n                var r,\n                    o = {\n                        oval:\n                            (r = t.getOval()) &&\n                            proto.mediapipe.RenderAnnotation.Oval.toObject(e, r),\n                        fillColor: (r = t.getFillColor()) && i.Color.toObject(e, r),\n                    };\n                return e && (o.$jspbMessageInstance = t), o;\n            })),\n        (proto.mediapipe.RenderAnnotation.FilledOval.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.FilledOval();\n            return proto.mediapipe.RenderAnnotation.FilledOval.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new proto.mediapipe.RenderAnnotation.Oval();\n                        t.readMessage(\n                            r,\n                            proto.mediapipe.RenderAnnotation.Oval.deserializeBinaryFromReader\n                        ),\n                            e.setOval(r);\n                        break;\n                    case 2:\n                        r = new i.Color();\n                        t.readMessage(r, i.Color.deserializeBinaryFromReader), e.setFillColor(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.FilledOval.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.serializeBinaryToWriter = function(e, t) {\n            var r = void 0;\n            null != (r = e.getOval()) &&\n                t.writeMessage(1, r, proto.mediapipe.RenderAnnotation.Oval.serializeBinaryToWriter),\n                null != (r = e.getFillColor()) &&\n                    t.writeMessage(2, r, i.Color.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.getOval = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Oval, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.setOval = function(e) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.clearOval = function() {\n            return this.setOval(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.hasOval = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.getFillColor = function() {\n            return t.Message.getWrapperField(this, i.Color, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.setFillColor = function(e) {\n            return t.Message.setWrapperField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.clearFillColor = function() {\n            return this.setFillColor(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.FilledOval.prototype.hasFillColor = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.Point.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.Point.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.Point.toObject = function(e, r) {\n                var o,\n                    i = {\n                        x: null == (o = t.Message.getOptionalFloatingPointField(r, 1)) ? void 0 : o,\n                        y: null == (o = t.Message.getOptionalFloatingPointField(r, 2)) ? void 0 : o,\n                        normalized: t.Message.getBooleanFieldWithDefault(r, 3, !1),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.RenderAnnotation.Point.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.Point();\n            return proto.mediapipe.RenderAnnotation.Point.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readDouble();\n                        e.setX(r);\n                        break;\n                    case 2:\n                        r = t.readDouble();\n                        e.setY(r);\n                        break;\n                    case 3:\n                        r = t.readBool();\n                        e.setNormalized(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.Point.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeDouble(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeDouble(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeBool(3, o);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.getX = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.setX = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.clearX = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.hasX = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.getY = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.setY = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.clearY = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.hasY = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.getNormalized = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 3, !1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.setNormalized = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.clearNormalized = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Point.prototype.hasNormalized = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.Line.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.Line.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.Line.toObject = function(e, r) {\n                var o,\n                    i = {\n                        xStart:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 1))\n                                ? void 0\n                                : o,\n                        yStart:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                ? void 0\n                                : o,\n                        xEnd:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        yEnd:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                ? void 0\n                                : o,\n                        normalized: t.Message.getBooleanFieldWithDefault(r, 5, !1),\n                        lineType: t.Message.getFieldWithDefault(r, 6, 1),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.RenderAnnotation.Line.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.Line();\n            return proto.mediapipe.RenderAnnotation.Line.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readDouble();\n                        e.setXStart(r);\n                        break;\n                    case 2:\n                        r = t.readDouble();\n                        e.setYStart(r);\n                        break;\n                    case 3:\n                        r = t.readDouble();\n                        e.setXEnd(r);\n                        break;\n                    case 4:\n                        r = t.readDouble();\n                        e.setYEnd(r);\n                        break;\n                    case 5:\n                        r = t.readBool();\n                        e.setNormalized(r);\n                        break;\n                    case 6:\n                        r = t.readEnum();\n                        e.setLineType(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.Line.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeDouble(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeDouble(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeDouble(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeDouble(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeBool(5, o),\n                null != (o = t.Message.getField(e, 6)) && r.writeEnum(6, o);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.LineType = { UNKNOWN: 0, SOLID: 1, DASHED: 2 }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.getXStart = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.setXStart = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.clearXStart = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.hasXStart = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.getYStart = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.setYStart = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.clearYStart = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.hasYStart = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.getXEnd = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.setXEnd = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.clearXEnd = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.hasXEnd = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.getYEnd = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.setYEnd = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.clearYEnd = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.hasYEnd = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.getNormalized = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 5, !1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.setNormalized = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.clearNormalized = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.hasNormalized = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.getLineType = function() {\n            return t.Message.getFieldWithDefault(this, 6, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.setLineType = function(e) {\n            return t.Message.setField(this, 6, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.clearLineType = function() {\n            return t.Message.setField(this, 6, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Line.prototype.hasLineType = function() {\n            return null != t.Message.getField(this, 6);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.GradientLine.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.GradientLine.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.GradientLine.toObject = function(e, r) {\n                var o,\n                    a = {\n                        xStart:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 1))\n                                ? void 0\n                                : o,\n                        yStart:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                ? void 0\n                                : o,\n                        xEnd:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        yEnd:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                ? void 0\n                                : o,\n                        normalized: t.Message.getBooleanFieldWithDefault(r, 5, !1),\n                        color1: (o = r.getColor1()) && i.Color.toObject(e, o),\n                        color2: (o = r.getColor2()) && i.Color.toObject(e, o),\n                    };\n                return e && (a.$jspbMessageInstance = r), a;\n            })),\n        (proto.mediapipe.RenderAnnotation.GradientLine.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.GradientLine();\n            return proto.mediapipe.RenderAnnotation.GradientLine.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readDouble();\n                        e.setXStart(r);\n                        break;\n                    case 2:\n                        r = t.readDouble();\n                        e.setYStart(r);\n                        break;\n                    case 3:\n                        r = t.readDouble();\n                        e.setXEnd(r);\n                        break;\n                    case 4:\n                        r = t.readDouble();\n                        e.setYEnd(r);\n                        break;\n                    case 5:\n                        r = t.readBool();\n                        e.setNormalized(r);\n                        break;\n                    case 6:\n                        r = new i.Color();\n                        t.readMessage(r, i.Color.deserializeBinaryFromReader), e.setColor1(r);\n                        break;\n                    case 7:\n                        r = new i.Color();\n                        t.readMessage(r, i.Color.deserializeBinaryFromReader), e.setColor2(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.GradientLine.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeDouble(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeDouble(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeDouble(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeDouble(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeBool(5, o),\n                null != (o = e.getColor1()) &&\n                    r.writeMessage(6, o, i.Color.serializeBinaryToWriter),\n                null != (o = e.getColor2()) &&\n                    r.writeMessage(7, o, i.Color.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.getXStart = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.setXStart = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.clearXStart = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.hasXStart = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.getYStart = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.setYStart = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.clearYStart = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.hasYStart = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.getXEnd = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.setXEnd = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.clearXEnd = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.hasXEnd = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.getYEnd = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.setYEnd = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.clearYEnd = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.hasYEnd = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.getNormalized = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 5, !1);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.setNormalized = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.clearNormalized = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.hasNormalized = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.getColor1 = function() {\n            return t.Message.getWrapperField(this, i.Color, 6);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.setColor1 = function(e) {\n            return t.Message.setWrapperField(this, 6, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.clearColor1 = function() {\n            return this.setColor1(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.hasColor1 = function() {\n            return null != t.Message.getField(this, 6);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.getColor2 = function() {\n            return t.Message.getWrapperField(this, i.Color, 7);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.setColor2 = function(e) {\n            return t.Message.setWrapperField(this, 7, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.clearColor2 = function() {\n            return this.setColor2(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.GradientLine.prototype.hasColor2 = function() {\n            return null != t.Message.getField(this, 7);\n        }),\n        (proto.mediapipe.RenderAnnotation.Scribble.repeatedFields_ = [1]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.Scribble.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.Scribble.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.Scribble.toObject = function(e, r) {\n                var o = {\n                    pointList: t.Message.toObjectList(\n                        r.getPointList(),\n                        proto.mediapipe.RenderAnnotation.Point.toObject,\n                        e\n                    ),\n                };\n                return e && (o.$jspbMessageInstance = r), o;\n            })),\n        (proto.mediapipe.RenderAnnotation.Scribble.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.Scribble();\n            return proto.mediapipe.RenderAnnotation.Scribble.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.Scribble.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                if (1 === t.getFieldNumber()) {\n                    var r = new proto.mediapipe.RenderAnnotation.Point();\n                    t.readMessage(\n                        r,\n                        proto.mediapipe.RenderAnnotation.Point.deserializeBinaryFromReader\n                    ),\n                        e.addPoint(r);\n                } else t.skipField();\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.Scribble.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.Scribble.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Scribble.serializeBinaryToWriter = function(e, t) {\n            var r;\n            (r = e.getPointList()).length > 0 &&\n                t.writeRepeatedMessage(\n                    1,\n                    r,\n                    proto.mediapipe.RenderAnnotation.Point.serializeBinaryToWriter\n                );\n        }),\n        (proto.mediapipe.RenderAnnotation.Scribble.prototype.getPointList = function() {\n            return t.Message.getRepeatedWrapperField(\n                this,\n                proto.mediapipe.RenderAnnotation.Point,\n                1\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Scribble.prototype.setPointList = function(e) {\n            return t.Message.setRepeatedWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Scribble.prototype.addPoint = function(e, r) {\n            return t.Message.addToRepeatedWrapperField(\n                this,\n                1,\n                e,\n                proto.mediapipe.RenderAnnotation.Point,\n                r\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Scribble.prototype.clearPointList = function() {\n            return this.setPointList([]);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.Arrow.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.Arrow.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.Arrow.toObject = function(e, r) {\n                var o,\n                    i = {\n                        xStart:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 1))\n                                ? void 0\n                                : o,\n                        yStart:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                ? void 0\n                                : o,\n                        xEnd:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        yEnd:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                ? void 0\n                                : o,\n                        normalized: t.Message.getBooleanFieldWithDefault(r, 5, !1),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.RenderAnnotation.Arrow.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.Arrow();\n            return proto.mediapipe.RenderAnnotation.Arrow.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readDouble();\n                        e.setXStart(r);\n                        break;\n                    case 2:\n                        r = t.readDouble();\n                        e.setYStart(r);\n                        break;\n                    case 3:\n                        r = t.readDouble();\n                        e.setXEnd(r);\n                        break;\n                    case 4:\n                        r = t.readDouble();\n                        e.setYEnd(r);\n                        break;\n                    case 5:\n                        r = t.readBool();\n                        e.setNormalized(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.Arrow.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeDouble(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeDouble(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeDouble(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeDouble(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeBool(5, o);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.getXStart = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 1, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.setXStart = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.clearXStart = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.hasXStart = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.getYStart = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.setYStart = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.clearYStart = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.hasYStart = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.getXEnd = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.setXEnd = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.clearXEnd = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.hasXEnd = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.getYEnd = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.setYEnd = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.clearYEnd = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.hasYEnd = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.getNormalized = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 5, !1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.setNormalized = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.clearNormalized = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Arrow.prototype.hasNormalized = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderAnnotation.Text.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderAnnotation.Text.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderAnnotation.Text.toObject = function(e, r) {\n                var o,\n                    a = {\n                        displayText: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        left:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 2))\n                                ? void 0\n                                : o,\n                        baseline:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 3))\n                                ? void 0\n                                : o,\n                        fontHeight: t.Message.getFloatingPointFieldWithDefault(r, 4, 8),\n                        normalized: t.Message.getBooleanFieldWithDefault(r, 5, !1),\n                        fontFace: t.Message.getFieldWithDefault(r, 6, 0),\n                        centerHorizontally: t.Message.getBooleanFieldWithDefault(r, 7, !1),\n                        centerVertically: t.Message.getBooleanFieldWithDefault(r, 8, !1),\n                        outlineThickness: t.Message.getFloatingPointFieldWithDefault(r, 11, 0),\n                        outlineColor: (o = r.getOutlineColor()) && i.Color.toObject(e, o),\n                    };\n                return e && (a.$jspbMessageInstance = r), a;\n            })),\n        (proto.mediapipe.RenderAnnotation.Text.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderAnnotation.Text();\n            return proto.mediapipe.RenderAnnotation.Text.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setDisplayText(r);\n                        break;\n                    case 2:\n                        r = t.readDouble();\n                        e.setLeft(r);\n                        break;\n                    case 3:\n                        r = t.readDouble();\n                        e.setBaseline(r);\n                        break;\n                    case 4:\n                        r = t.readDouble();\n                        e.setFontHeight(r);\n                        break;\n                    case 5:\n                        r = t.readBool();\n                        e.setNormalized(r);\n                        break;\n                    case 6:\n                        r = t.readInt32();\n                        e.setFontFace(r);\n                        break;\n                    case 7:\n                        r = t.readBool();\n                        e.setCenterHorizontally(r);\n                        break;\n                    case 8:\n                        r = t.readBool();\n                        e.setCenterVertically(r);\n                        break;\n                    case 11:\n                        r = t.readDouble();\n                        e.setOutlineThickness(r);\n                        break;\n                    case 12:\n                        r = new i.Color();\n                        t.readMessage(r, i.Color.deserializeBinaryFromReader), e.setOutlineColor(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderAnnotation.Text.serializeBinaryToWriter(this, e),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeDouble(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeDouble(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeDouble(4, o),\n                null != (o = t.Message.getField(e, 5)) && r.writeBool(5, o),\n                null != (o = t.Message.getField(e, 6)) && r.writeInt32(6, o),\n                null != (o = t.Message.getField(e, 7)) && r.writeBool(7, o),\n                null != (o = t.Message.getField(e, 8)) && r.writeBool(8, o),\n                null != (o = t.Message.getField(e, 11)) && r.writeDouble(11, o),\n                null != (o = e.getOutlineColor()) &&\n                    r.writeMessage(12, o, i.Color.serializeBinaryToWriter);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getDisplayText = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setDisplayText = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearDisplayText = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasDisplayText = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getLeft = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setLeft = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearLeft = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasLeft = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getBaseline = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setBaseline = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearBaseline = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasBaseline = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getFontHeight = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 8);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setFontHeight = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearFontHeight = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasFontHeight = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getNormalized = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 5, !1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setNormalized = function(e) {\n            return t.Message.setField(this, 5, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearNormalized = function() {\n            return t.Message.setField(this, 5, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasNormalized = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getFontFace = function() {\n            return t.Message.getFieldWithDefault(this, 6, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setFontFace = function(e) {\n            return t.Message.setField(this, 6, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearFontFace = function() {\n            return t.Message.setField(this, 6, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasFontFace = function() {\n            return null != t.Message.getField(this, 6);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getCenterHorizontally = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 7, !1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setCenterHorizontally = function(e) {\n            return t.Message.setField(this, 7, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearCenterHorizontally = function() {\n            return t.Message.setField(this, 7, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasCenterHorizontally = function() {\n            return null != t.Message.getField(this, 7);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getCenterVertically = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 8, !1);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setCenterVertically = function(e) {\n            return t.Message.setField(this, 8, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearCenterVertically = function() {\n            return t.Message.setField(this, 8, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasCenterVertically = function() {\n            return null != t.Message.getField(this, 8);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getOutlineThickness = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 11, 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setOutlineThickness = function(e) {\n            return t.Message.setField(this, 11, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearOutlineThickness = function() {\n            return t.Message.setField(this, 11, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasOutlineThickness = function() {\n            return null != t.Message.getField(this, 11);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.getOutlineColor = function() {\n            return t.Message.getWrapperField(this, i.Color, 12);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.setOutlineColor = function(e) {\n            return t.Message.setWrapperField(this, 12, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.clearOutlineColor = function() {\n            return this.setOutlineColor(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.Text.prototype.hasOutlineColor = function() {\n            return null != t.Message.getField(this, 12);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getRectangle = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Rectangle, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setRectangle = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                1,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearRectangle = function() {\n            return this.setRectangle(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasRectangle = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getFilledRectangle = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.RenderAnnotation.FilledRectangle,\n                2\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setFilledRectangle = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                2,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearFilledRectangle = function() {\n            return this.setFilledRectangle(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasFilledRectangle = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getOval = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Oval, 3);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setOval = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                3,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearOval = function() {\n            return this.setOval(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasOval = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getFilledOval = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.FilledOval, 4);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setFilledOval = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                4,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearFilledOval = function() {\n            return this.setFilledOval(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasFilledOval = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getPoint = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Point, 5);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setPoint = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                5,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearPoint = function() {\n            return this.setPoint(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasPoint = function() {\n            return null != t.Message.getField(this, 5);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getLine = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Line, 6);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setLine = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                6,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearLine = function() {\n            return this.setLine(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasLine = function() {\n            return null != t.Message.getField(this, 6);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getArrow = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Arrow, 7);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setArrow = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                7,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearArrow = function() {\n            return this.setArrow(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasArrow = function() {\n            return null != t.Message.getField(this, 7);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getText = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Text, 8);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setText = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                8,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearText = function() {\n            return this.setText(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasText = function() {\n            return null != t.Message.getField(this, 8);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getRoundedRectangle = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.RenderAnnotation.RoundedRectangle,\n                9\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setRoundedRectangle = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                9,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearRoundedRectangle = function() {\n            return this.setRoundedRectangle(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasRoundedRectangle = function() {\n            return null != t.Message.getField(this, 9);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getFilledRoundedRectangle = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.RenderAnnotation.FilledRoundedRectangle,\n                10\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setFilledRoundedRectangle = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                10,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearFilledRoundedRectangle = function() {\n            return this.setFilledRoundedRectangle(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasFilledRoundedRectangle = function() {\n            return null != t.Message.getField(this, 10);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getGradientLine = function() {\n            return t.Message.getWrapperField(\n                this,\n                proto.mediapipe.RenderAnnotation.GradientLine,\n                14\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setGradientLine = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                14,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearGradientLine = function() {\n            return this.setGradientLine(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasGradientLine = function() {\n            return null != t.Message.getField(this, 14);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getScribble = function() {\n            return t.Message.getWrapperField(this, proto.mediapipe.RenderAnnotation.Scribble, 15);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setScribble = function(e) {\n            return t.Message.setOneofWrapperField(\n                this,\n                15,\n                proto.mediapipe.RenderAnnotation.oneofGroups_[0],\n                e\n            );\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearScribble = function() {\n            return this.setScribble(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasScribble = function() {\n            return null != t.Message.getField(this, 15);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getThickness = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 11, 1);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setThickness = function(e) {\n            return t.Message.setField(this, 11, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearThickness = function() {\n            return t.Message.setField(this, 11, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasThickness = function() {\n            return null != t.Message.getField(this, 11);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getColor = function() {\n            return t.Message.getWrapperField(this, i.Color, 12);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setColor = function(e) {\n            return t.Message.setWrapperField(this, 12, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearColor = function() {\n            return this.setColor(void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasColor = function() {\n            return null != t.Message.getField(this, 12);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.getSceneTag = function() {\n            return t.Message.getFieldWithDefault(this, 13, '');\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.setSceneTag = function(e) {\n            return t.Message.setField(this, 13, e);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.clearSceneTag = function() {\n            return t.Message.setField(this, 13, void 0);\n        }),\n        (proto.mediapipe.RenderAnnotation.prototype.hasSceneTag = function() {\n            return null != t.Message.getField(this, 13);\n        }),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.RenderViewport.prototype.toObject = function(e) {\n                return proto.mediapipe.RenderViewport.toObject(e, this);\n            }),\n            (proto.mediapipe.RenderViewport.toObject = function(e, r) {\n                var o,\n                    i = {\n                        id: null == (o = t.Message.getField(r, 1)) ? void 0 : o,\n                        widthPx: null == (o = t.Message.getField(r, 2)) ? void 0 : o,\n                        heightPx: null == (o = t.Message.getField(r, 3)) ? void 0 : o,\n                        composeOnVideo: null == (o = t.Message.getBooleanField(r, 4)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.RenderViewport.deserializeBinary = function(e) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.RenderViewport();\n            return proto.mediapipe.RenderViewport.deserializeBinaryFromReader(o, r);\n        }),\n        (proto.mediapipe.RenderViewport.deserializeBinaryFromReader = function(e, t) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = t.readString();\n                        e.setId(r);\n                        break;\n                    case 2:\n                        r = t.readInt32();\n                        e.setWidthPx(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setHeightPx(r);\n                        break;\n                    case 4:\n                        r = t.readBool();\n                        e.setComposeOnVideo(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.RenderViewport.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.RenderViewport.serializeBinaryToWriter(this, e), e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.RenderViewport.serializeBinaryToWriter = function(e, r) {\n            var o = void 0;\n            null != (o = t.Message.getField(e, 1)) && r.writeString(1, o),\n                null != (o = t.Message.getField(e, 2)) && r.writeInt32(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeBool(4, o);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.getId = function() {\n            return t.Message.getFieldWithDefault(this, 1, '');\n        }),\n        (proto.mediapipe.RenderViewport.prototype.setId = function(e) {\n            return t.Message.setField(this, 1, e);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.clearId = function() {\n            return t.Message.setField(this, 1, void 0);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.hasId = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.getWidthPx = function() {\n            return t.Message.getFieldWithDefault(this, 2, 0);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.setWidthPx = function(e) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.clearWidthPx = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.hasWidthPx = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.getHeightPx = function() {\n            return t.Message.getFieldWithDefault(this, 3, 0);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.setHeightPx = function(e) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.clearHeightPx = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.hasHeightPx = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.getComposeOnVideo = function() {\n            return t.Message.getBooleanFieldWithDefault(this, 4, !1);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.setComposeOnVideo = function(e) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.clearComposeOnVideo = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.RenderViewport.prototype.hasComposeOnVideo = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        r.object.extend(e, proto.mediapipe);\n})(render_data_pb);\nvar interactive_segmenter_result = {};\nObject.defineProperty(interactive_segmenter_result, '__esModule', { value: !0 }),\n    (interactive_segmenter_result.InteractiveSegmenterResult = void 0);\nclass InteractiveSegmenterResult {\n    constructor(e, t, r) {\n        (this.confidenceMasks = e), (this.categoryMask = t), (this.qualityScores = r);\n    }\n    close() {\n        var e, t;\n        null === (e = this.confidenceMasks) ||\n            void 0 === e ||\n            e.forEach((e) => {\n                e.close();\n            }),\n            null === (t = this.categoryMask) || void 0 === t || t.close();\n    }\n}\ninteractive_segmenter_result.InteractiveSegmenterResult = InteractiveSegmenterResult;\nvar interactive_segmenter_options = {};\nObject.defineProperty(interactive_segmenter_options, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.InteractiveSegmenter = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = base_options_pb,\n            n = image_segmenter_graph_options_pb,\n            s = segmenter_options_pb,\n            p = vision_task_runner,\n            d = color_pb,\n            l = render_data_pb,\n            g = interactive_segmenter_result;\n        r(interactive_segmenter_options, e), r(interactive_segmenter_result, e);\n        const c = 'image_in',\n            u = 'norm_rect_in',\n            m = 'roi_in',\n            f = 'confidence_masks',\n            h = 'category_mask',\n            y = 'quality_scores';\n        class b extends p.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return p.VisionTaskRunner.createVisionInstance(b, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return p.VisionTaskRunner.createVisionInstance(b, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return p.VisionTaskRunner.createVisionInstance(b, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new p.VisionGraphRunner(e, t), c, u, !1),\n                    (this.outputCategoryMask = false),\n                    (this.outputConfidenceMasks = true),\n                    (this.options = new n.ImageSegmenterGraphOptions()),\n                    (this.segmenterOptions = new s.SegmenterOptions()),\n                    this.options.setSegmenterOptions(this.segmenterOptions),\n                    this.options.setBaseOptions(new a.BaseOptions());\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                var t, r;\n                return (\n                    'outputCategoryMask' in e &&\n                        (this.outputCategoryMask =\n                            null !== (t = e.outputCategoryMask) && void 0 !== t && t),\n                    'outputConfidenceMasks' in e &&\n                        (this.outputConfidenceMasks =\n                            null === (r = e.outputConfidenceMasks) || void 0 === r || r),\n                    super.applyOptions(e)\n                );\n            }\n            segment(e, t, r, o) {\n                const i = 'function' != typeof r ? r : {};\n                return (\n                    (this.userCallback = 'function' == typeof r ? r : o),\n                    this.reset(),\n                    this.processRenderData(t, this.getSynctheticTimestamp()),\n                    this.processImageData(e, i),\n                    this.processResults()\n                );\n            }\n            reset() {\n                (this.confidenceMasks = void 0),\n                    (this.categoryMask = void 0),\n                    (this.qualityScores = void 0);\n            }\n            processResults() {\n                try {\n                    const e = new g.InteractiveSegmenterResult(\n                        this.confidenceMasks,\n                        this.categoryMask,\n                        this.qualityScores\n                    );\n                    if (!this.userCallback) return e;\n                    this.userCallback(e);\n                } finally {\n                    this.freeKeepaliveStreams();\n                }\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(c), e.addInputStream(m), e.addInputStream(u);\n                const t = new i.CalculatorOptions();\n                t.setExtension(n.ImageSegmenterGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator(\n                    'mediapipe.tasks.vision.interactive_segmenter.InteractiveSegmenterGraph'\n                ),\n                    r.addInputStream('IMAGE:' + c),\n                    r.addInputStream('ROI:' + m),\n                    r.addInputStream('NORM_RECT:' + u),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.addKeepaliveNode(e),\n                    this.outputConfidenceMasks &&\n                        (e.addOutputStream(f),\n                        r.addOutputStream('CONFIDENCE_MASKS:' + f),\n                        this.keepStreamAlive(f),\n                        this.graphRunner.attachImageVectorListener(f, (e, t) => {\n                            (this.confidenceMasks = e.map((e) =>\n                                this.convertToMPMask(e, !this.userCallback)\n                            )),\n                                this.setLatestOutputTimestamp(t);\n                        }),\n                        this.graphRunner.attachEmptyPacketListener(f, (e) => {\n                            (this.confidenceMasks = []), this.setLatestOutputTimestamp(e);\n                        })),\n                    this.outputCategoryMask &&\n                        (e.addOutputStream(h),\n                        r.addOutputStream('CATEGORY_MASK:' + h),\n                        this.keepStreamAlive(h),\n                        this.graphRunner.attachImageListener(h, (e, t) => {\n                            (this.categoryMask = this.convertToMPMask(e, !this.userCallback)),\n                                this.setLatestOutputTimestamp(t);\n                        }),\n                        this.graphRunner.attachEmptyPacketListener(h, (e) => {\n                            (this.categoryMask = void 0), this.setLatestOutputTimestamp(e);\n                        })),\n                    e.addOutputStream(y),\n                    r.addOutputStream('QUALITY_SCORES:' + y),\n                    this.graphRunner.attachFloatVectorListener(y, (e, t) => {\n                        (this.qualityScores = e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(y, (e) => {\n                        (this.categoryMask = void 0), this.setLatestOutputTimestamp(e);\n                    });\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n            processRenderData(e, t) {\n                const r = new l.RenderData(),\n                    o = new l.RenderAnnotation(),\n                    i = new d.Color();\n                if ((i.setR(255), o.setColor(i), e.keypoint && e.scribble))\n                    throw new Error('Cannot provide both keypoint and scribble.');\n                if (e.keypoint) {\n                    const t = new l.RenderAnnotation.Point();\n                    t.setNormalized(!0), t.setX(e.keypoint.x), t.setY(e.keypoint.y), o.setPoint(t);\n                } else {\n                    if (!e.scribble)\n                        throw new Error('Must provide either a keypoint or a scribble.');\n                    {\n                        const t = new l.RenderAnnotation.Scribble();\n                        for (const r of e.scribble) {\n                            const e = new l.RenderAnnotation.Point();\n                            e.setNormalized(!0), e.setX(r.x), e.setY(r.y), t.addPoint(e);\n                        }\n                        o.setScribble(t);\n                    }\n                }\n                r.addRenderAnnotations(o),\n                    this.graphRunner.addProtoToStream(\n                        r.serializeBinary(),\n                        'drishti.RenderData',\n                        m,\n                        t\n                    );\n            }\n        }\n        e.InteractiveSegmenter = b;\n    })(interactive_segmenter);\nvar object_detector = {},\n    object_detector_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions = function(e) {\n            t.Message.initialize(\n                this,\n                e,\n                0,\n                -1,\n                proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions\n                    .repeatedFields_,\n                null\n            );\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.displayName =\n                'proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions'),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.repeatedFields_ = [\n            5,\n            6,\n        ]),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                        displayNamesLocale: t.Message.getFieldWithDefault(r, 2, 'en'),\n                        maxResults: t.Message.getFieldWithDefault(r, 3, -1),\n                        scoreThreshold:\n                            null == (o = t.Message.getOptionalFloatingPointField(r, 4))\n                                ? void 0\n                                : o,\n                        categoryAllowlistList:\n                            null == (o = t.Message.getRepeatedField(r, 5)) ? void 0 : o,\n                        categoryDenylistList:\n                            null == (o = t.Message.getRepeatedField(r, 6)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions();\n            return proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new n.BaseOptions();\n                        t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = t.readString();\n                        e.setDisplayNamesLocale(r);\n                        break;\n                    case 3:\n                        r = t.readInt32();\n                        e.setMaxResults(r);\n                        break;\n                    case 4:\n                        r = t.readFloat();\n                        e.setScoreThreshold(r);\n                        break;\n                    case 5:\n                        r = t.readString();\n                        e.addCategoryAllowlist(r);\n                        break;\n                    case 6:\n                        r = t.readString();\n                        e.addCategoryDenylist(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getBaseOptions()) &&\n                r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 2)) && r.writeString(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeInt32(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o),\n                (o = e.getCategoryAllowlistList()).length > 0 && r.writeRepeatedString(5, o),\n                (o = e.getCategoryDenylistList()).length > 0 && r.writeRepeatedString(6, o);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.ext = new t.ExtensionFieldInfo(\n            443442058,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions,\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[443442058] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[443442058] =\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.ext),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.getDisplayNamesLocale = function() {\n            return t.Message.getFieldWithDefault(this, 2, 'en');\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.setDisplayNamesLocale = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.clearDisplayNamesLocale = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.hasDisplayNamesLocale = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.getMaxResults = function() {\n            return t.Message.getFieldWithDefault(this, 3, -1);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.setMaxResults = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.clearMaxResults = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.hasMaxResults = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.getScoreThreshold = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.setScoreThreshold = function(\n            e\n        ) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.clearScoreThreshold = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.hasScoreThreshold = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.getCategoryAllowlistList = function() {\n            return t.Message.getRepeatedField(this, 5);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.setCategoryAllowlistList = function(\n            e\n        ) {\n            return t.Message.setField(this, 5, e || []);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.addCategoryAllowlist = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedField(this, 5, e, r);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.clearCategoryAllowlistList = function() {\n            return this.setCategoryAllowlistList([]);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.getCategoryDenylistList = function() {\n            return t.Message.getRepeatedField(this, 6);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.setCategoryDenylistList = function(\n            e\n        ) {\n            return t.Message.setField(this, 6, e || []);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.addCategoryDenylist = function(\n            e,\n            r\n        ) {\n            return t.Message.addToRepeatedField(this, 6, e, r);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.prototype.clearCategoryDenylistList = function() {\n            return this.setCategoryDenylistList([]);\n        }),\n        (proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.ext = new t.ExtensionFieldInfo(\n            443442058,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions,\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[443442058] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[443442058] =\n            proto.mediapipe.tasks.vision.object_detector.proto.ObjectDetectorOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.object_detector.proto);\n})(object_detector_options_pb);\nvar object_detector_options = {};\nObject.defineProperty(object_detector_options, '__esModule', { value: !0 });\nvar object_detector_result = {};\nObject.defineProperty(object_detector_result, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.ObjectDetector = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = detection_pb,\n            n = base_options_pb,\n            s = object_detector_options_pb,\n            p = detection_result,\n            d = vision_task_runner,\n            l = 'input_frame_gpu',\n            g = 'norm_rect',\n            c = 'detections';\n        r(object_detector_options, e), r(object_detector_result, e);\n        class u extends d.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(u, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(u, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static async createFromModelPath(e, t) {\n                return d.VisionTaskRunner.createVisionInstance(u, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new d.VisionGraphRunner(e, t), l, g, !1),\n                    (this.result = { detections: [] }),\n                    (this.options = new s.ObjectDetectorOptions()),\n                    this.options.setBaseOptions(new n.BaseOptions());\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                return (\n                    void 0 !== e.displayNamesLocale\n                        ? this.options.setDisplayNamesLocale(e.displayNamesLocale)\n                        : 'displayNamesLocale' in e && this.options.clearDisplayNamesLocale(),\n                    void 0 !== e.maxResults\n                        ? this.options.setMaxResults(e.maxResults)\n                        : 'maxResults' in e && this.options.clearMaxResults(),\n                    void 0 !== e.scoreThreshold\n                        ? this.options.setScoreThreshold(e.scoreThreshold)\n                        : 'scoreThreshold' in e && this.options.clearScoreThreshold(),\n                    void 0 !== e.categoryAllowlist\n                        ? this.options.setCategoryAllowlistList(e.categoryAllowlist)\n                        : 'categoryAllowlist' in e && this.options.clearCategoryAllowlistList(),\n                    void 0 !== e.categoryDenylist\n                        ? this.options.setCategoryDenylistList(e.categoryDenylist)\n                        : 'categoryDenylist' in e && this.options.clearCategoryDenylistList(),\n                    this.applyOptions(e)\n                );\n            }\n            detect(e, t) {\n                return (this.result = { detections: [] }), this.processImageData(e, t), this.result;\n            }\n            detectForVideo(e, t, r) {\n                return (\n                    (this.result = { detections: [] }), this.processVideoData(e, r, t), this.result\n                );\n            }\n            addJsObjectDetections(e) {\n                for (const t of e) {\n                    const e = a.Detection.deserializeBinary(t);\n                    this.result.detections.push((0, p.convertFromDetectionProto)(e));\n                }\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(l), e.addInputStream(g), e.addOutputStream(c);\n                const t = new i.CalculatorOptions();\n                t.setExtension(s.ObjectDetectorOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.ObjectDetectorGraph'),\n                    r.addInputStream('IMAGE:' + l),\n                    r.addInputStream('NORM_RECT:' + g),\n                    r.addOutputStream('DETECTIONS:' + c),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.graphRunner.attachProtoVectorListener(c, (e, t) => {\n                        this.addJsObjectDetections(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(c, (e) => {\n                        this.setLatestOutputTimestamp(e);\n                    });\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        e.ObjectDetector = u;\n    })(object_detector);\nvar pose_landmarker = {},\n    pose_detector_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions = function(e) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                        minDetectionConfidence: t.Message.getFloatingPointFieldWithDefault(\n                            r,\n                            2,\n                            0.5\n                        ),\n                        minSuppressionThreshold: t.Message.getFloatingPointFieldWithDefault(\n                            r,\n                            3,\n                            0.5\n                        ),\n                        numPoses: null == (o = t.Message.getField(r, 4)) ? void 0 : o,\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions();\n            return proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new n.BaseOptions();\n                        t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setMinDetectionConfidence(r);\n                        break;\n                    case 3:\n                        r = t.readFloat();\n                        e.setMinSuppressionThreshold(r);\n                        break;\n                    case 4:\n                        r = t.readInt32();\n                        e.setNumPoses(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getBaseOptions()) &&\n                r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o),\n                null != (o = t.Message.getField(e, 3)) && r.writeFloat(3, o),\n                null != (o = t.Message.getField(e, 4)) && r.writeInt32(4, o);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            514774813,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[514774813] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[514774813] =\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.getMinDetectionConfidence = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0.5);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.setMinDetectionConfidence = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.clearMinDetectionConfidence = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.hasMinDetectionConfidence = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.getMinSuppressionThreshold = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 3, 0.5);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.setMinSuppressionThreshold = function(\n            e\n        ) {\n            return t.Message.setField(this, 3, e);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.clearMinSuppressionThreshold = function() {\n            return t.Message.setField(this, 3, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.hasMinSuppressionThreshold = function() {\n            return null != t.Message.getField(this, 3);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.getNumPoses = function() {\n            return t.Message.getFieldWithDefault(this, 4, 0);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.setNumPoses = function(\n            e\n        ) {\n            return t.Message.setField(this, 4, e);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.clearNumPoses = function() {\n            return t.Message.setField(this, 4, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.prototype.hasNumPoses = function() {\n            return null != t.Message.getField(this, 4);\n        }),\n        (proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            514774813,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[514774813] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[514774813] =\n            proto.mediapipe.tasks.vision.pose_detector.proto.PoseDetectorGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.pose_detector.proto);\n})(pose_detector_graph_options_pb);\nvar pose_landmarker_graph_options_pb = {},\n    pose_landmarks_detector_graph_options_pb = {};\n!(function(e) {\n    var t = googleProtobuf,\n        r = t,\n        o =\n            ('undefined' != typeof globalThis && globalThis) ||\n            ('undefined' != typeof window && window) ||\n            (void 0 !== o && o) ||\n            ('undefined' != typeof self && self) ||\n            function() {\n                return this;\n            }.call(null) ||\n            Function('return this')(),\n        i = calculator_pb;\n    r.object.extend(proto, i);\n    var a = calculator_options_pb;\n    r.object.extend(proto, a);\n    var n = base_options_pb;\n    r.object.extend(proto, n),\n        r.exportSymbol(\n            'proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions',\n            null,\n            o\n        ),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions = function(\n            e\n        ) {\n            t.Message.initialize(this, e, 0, -1, null, null);\n        }),\n        r.inherits(\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions,\n            t.Message\n        ),\n        r.DEBUG &&\n            !COMPILED &&\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.displayName =\n                'proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions'),\n        t.Message.GENERATE_TO_OBJECT &&\n            ((proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.toObject = function(\n                e\n            ) {\n                return proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.toObject(\n                    e,\n                    this\n                );\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.toObject = function(\n                e,\n                r\n            ) {\n                var o,\n                    i = {\n                        baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                        minDetectionConfidence: t.Message.getFloatingPointFieldWithDefault(\n                            r,\n                            2,\n                            0.5\n                        ),\n                    };\n                return e && (i.$jspbMessageInstance = r), i;\n            })),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.deserializeBinary = function(\n            e\n        ) {\n            var r = new t.BinaryReader(e),\n                o = new proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions();\n            return proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.deserializeBinaryFromReader(\n                o,\n                r\n            );\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.deserializeBinaryFromReader = function(\n            e,\n            t\n        ) {\n            for (; t.nextField() && !t.isEndGroup(); ) {\n                switch (t.getFieldNumber()) {\n                    case 1:\n                        var r = new n.BaseOptions();\n                        t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                            e.setBaseOptions(r);\n                        break;\n                    case 2:\n                        r = t.readFloat();\n                        e.setMinDetectionConfidence(r);\n                        break;\n                    default:\n                        t.skipField();\n                }\n            }\n            return e;\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.serializeBinary = function() {\n            var e = new t.BinaryWriter();\n            return (\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.serializeBinaryToWriter(\n                    this,\n                    e\n                ),\n                e.getResultBuffer()\n            );\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.serializeBinaryToWriter = function(\n            e,\n            r\n        ) {\n            var o = void 0;\n            null != (o = e.getBaseOptions()) &&\n                r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                null != (o = t.Message.getField(e, 2)) && r.writeFloat(2, o);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            518928384,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[518928384] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[518928384] =\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.ext),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.getBaseOptions = function() {\n            return t.Message.getWrapperField(this, n.BaseOptions, 1);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.setBaseOptions = function(\n            e\n        ) {\n            return t.Message.setWrapperField(this, 1, e);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.clearBaseOptions = function() {\n            return this.setBaseOptions(void 0);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.hasBaseOptions = function() {\n            return null != t.Message.getField(this, 1);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.getMinDetectionConfidence = function() {\n            return t.Message.getFloatingPointFieldWithDefault(this, 2, 0.5);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.setMinDetectionConfidence = function(\n            e\n        ) {\n            return t.Message.setField(this, 2, e);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.clearMinDetectionConfidence = function() {\n            return t.Message.setField(this, 2, void 0);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.prototype.hasMinDetectionConfidence = function() {\n            return null != t.Message.getField(this, 2);\n        }),\n        (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.ext = new t.ExtensionFieldInfo(\n            518928384,\n            { ext: 0 },\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions,\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.toObject,\n            0\n        )),\n        (a.CalculatorOptions.extensionsBinary[518928384] = new t.ExtensionFieldBinaryInfo(\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.ext,\n            t.BinaryReader.prototype.readMessage,\n            t.BinaryWriter.prototype.writeMessage,\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.serializeBinaryToWriter,\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.deserializeBinaryFromReader,\n            !1\n        )),\n        (a.CalculatorOptions.extensions[518928384] =\n            proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarksDetectorGraphOptions.ext),\n        r.object.extend(e, proto.mediapipe.tasks.vision.pose_landmarker.proto);\n})(pose_landmarks_detector_graph_options_pb),\n    (function(e) {\n        var t = googleProtobuf,\n            r = t,\n            o =\n                ('undefined' != typeof globalThis && globalThis) ||\n                ('undefined' != typeof window && window) ||\n                (void 0 !== o && o) ||\n                ('undefined' != typeof self && self) ||\n                function() {\n                    return this;\n                }.call(null) ||\n                Function('return this')(),\n            i = calculator_pb;\n        r.object.extend(proto, i);\n        var a = calculator_options_pb;\n        r.object.extend(proto, a);\n        var n = base_options_pb;\n        r.object.extend(proto, n);\n        var s = pose_detector_graph_options_pb;\n        r.object.extend(proto, s);\n        var p = pose_landmarks_detector_graph_options_pb;\n        r.object.extend(proto, p),\n            r.exportSymbol(\n                'proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions',\n                null,\n                o\n            ),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions = function(\n                e\n            ) {\n                t.Message.initialize(this, e, 0, -1, null, null);\n            }),\n            r.inherits(\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions,\n                t.Message\n            ),\n            r.DEBUG &&\n                !COMPILED &&\n                (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.displayName =\n                    'proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions'),\n            t.Message.GENERATE_TO_OBJECT &&\n                ((proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.toObject = function(\n                    e\n                ) {\n                    return proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.toObject(\n                        e,\n                        this\n                    );\n                }),\n                (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.toObject = function(\n                    e,\n                    r\n                ) {\n                    var o,\n                        i = {\n                            baseOptions: (o = r.getBaseOptions()) && n.BaseOptions.toObject(e, o),\n                            poseDetectorGraphOptions:\n                                (o = r.getPoseDetectorGraphOptions()) &&\n                                s.PoseDetectorGraphOptions.toObject(e, o),\n                            poseLandmarksDetectorGraphOptions:\n                                (o = r.getPoseLandmarksDetectorGraphOptions()) &&\n                                p.PoseLandmarksDetectorGraphOptions.toObject(e, o),\n                            minTrackingConfidence: t.Message.getFloatingPointFieldWithDefault(\n                                r,\n                                4,\n                                0.5\n                            ),\n                        };\n                    return e && (i.$jspbMessageInstance = r), i;\n                })),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.deserializeBinary = function(\n                e\n            ) {\n                var r = new t.BinaryReader(e),\n                    o = new proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions();\n                return proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.deserializeBinaryFromReader(\n                    o,\n                    r\n                );\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.deserializeBinaryFromReader = function(\n                e,\n                t\n            ) {\n                for (; t.nextField() && !t.isEndGroup(); ) {\n                    switch (t.getFieldNumber()) {\n                        case 1:\n                            var r = new n.BaseOptions();\n                            t.readMessage(r, n.BaseOptions.deserializeBinaryFromReader),\n                                e.setBaseOptions(r);\n                            break;\n                        case 2:\n                            r = new s.PoseDetectorGraphOptions();\n                            t.readMessage(\n                                r,\n                                s.PoseDetectorGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setPoseDetectorGraphOptions(r);\n                            break;\n                        case 3:\n                            r = new p.PoseLandmarksDetectorGraphOptions();\n                            t.readMessage(\n                                r,\n                                p.PoseLandmarksDetectorGraphOptions.deserializeBinaryFromReader\n                            ),\n                                e.setPoseLandmarksDetectorGraphOptions(r);\n                            break;\n                        case 4:\n                            r = t.readFloat();\n                            e.setMinTrackingConfidence(r);\n                            break;\n                        default:\n                            t.skipField();\n                    }\n                }\n                return e;\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.serializeBinary = function() {\n                var e = new t.BinaryWriter();\n                return (\n                    proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.serializeBinaryToWriter(\n                        this,\n                        e\n                    ),\n                    e.getResultBuffer()\n                );\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.serializeBinaryToWriter = function(\n                e,\n                r\n            ) {\n                var o = void 0;\n                null != (o = e.getBaseOptions()) &&\n                    r.writeMessage(1, o, n.BaseOptions.serializeBinaryToWriter),\n                    null != (o = e.getPoseDetectorGraphOptions()) &&\n                        r.writeMessage(2, o, s.PoseDetectorGraphOptions.serializeBinaryToWriter),\n                    null != (o = e.getPoseLandmarksDetectorGraphOptions()) &&\n                        r.writeMessage(\n                            3,\n                            o,\n                            p.PoseLandmarksDetectorGraphOptions.serializeBinaryToWriter\n                        ),\n                    null != (o = t.Message.getField(e, 4)) && r.writeFloat(4, o);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.ext = new t.ExtensionFieldInfo(\n                516587230,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions,\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[516587230] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[516587230] =\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.ext),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.getBaseOptions = function() {\n                return t.Message.getWrapperField(this, n.BaseOptions, 1);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.setBaseOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 1, e);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.clearBaseOptions = function() {\n                return this.setBaseOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.hasBaseOptions = function() {\n                return null != t.Message.getField(this, 1);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.getPoseDetectorGraphOptions = function() {\n                return t.Message.getWrapperField(this, s.PoseDetectorGraphOptions, 2);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.setPoseDetectorGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 2, e);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.clearPoseDetectorGraphOptions = function() {\n                return this.setPoseDetectorGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.hasPoseDetectorGraphOptions = function() {\n                return null != t.Message.getField(this, 2);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.getPoseLandmarksDetectorGraphOptions = function() {\n                return t.Message.getWrapperField(this, p.PoseLandmarksDetectorGraphOptions, 3);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.setPoseLandmarksDetectorGraphOptions = function(\n                e\n            ) {\n                return t.Message.setWrapperField(this, 3, e);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.clearPoseLandmarksDetectorGraphOptions = function() {\n                return this.setPoseLandmarksDetectorGraphOptions(void 0);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.hasPoseLandmarksDetectorGraphOptions = function() {\n                return null != t.Message.getField(this, 3);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.getMinTrackingConfidence = function() {\n                return t.Message.getFloatingPointFieldWithDefault(this, 4, 0.5);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.setMinTrackingConfidence = function(\n                e\n            ) {\n                return t.Message.setField(this, 4, e);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.clearMinTrackingConfidence = function() {\n                return t.Message.setField(this, 4, void 0);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.prototype.hasMinTrackingConfidence = function() {\n                return null != t.Message.getField(this, 4);\n            }),\n            (proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.ext = new t.ExtensionFieldInfo(\n                516587230,\n                { ext: 0 },\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions,\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.toObject,\n                0\n            )),\n            (a.CalculatorOptions.extensionsBinary[516587230] = new t.ExtensionFieldBinaryInfo(\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.ext,\n                t.BinaryReader.prototype.readMessage,\n                t.BinaryWriter.prototype.writeMessage,\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.serializeBinaryToWriter,\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.deserializeBinaryFromReader,\n                !1\n            )),\n            (a.CalculatorOptions.extensions[516587230] =\n                proto.mediapipe.tasks.vision.pose_landmarker.proto.PoseLandmarkerGraphOptions.ext),\n            r.object.extend(e, proto.mediapipe.tasks.vision.pose_landmarker.proto);\n    })(pose_landmarker_graph_options_pb);\nvar pose_landmarker_result = {};\nObject.defineProperty(pose_landmarker_result, '__esModule', { value: !0 }),\n    (pose_landmarker_result.PoseLandmarkerResult = void 0);\nclass PoseLandmarkerResult {\n    constructor(e, t, r) {\n        (this.landmarks = e), (this.worldLandmarks = t), (this.segmentationMasks = r);\n    }\n    close() {\n        var e;\n        null === (e = this.segmentationMasks) ||\n            void 0 === e ||\n            e.forEach((e) => {\n                e.close();\n            });\n    }\n}\npose_landmarker_result.PoseLandmarkerResult = PoseLandmarkerResult;\nvar pose_landmarker_options = {};\nObject.defineProperty(pose_landmarker_options, '__esModule', { value: !0 }),\n    (function(e) {\n        var t =\n                (commonjsGlobal && commonjsGlobal.__createBinding) ||\n                (Object.create\n                    ? function(e, t, r, o) {\n                          void 0 === o && (o = r);\n                          var i = Object.getOwnPropertyDescriptor(t, r);\n                          (i && !('get' in i ? !t.__esModule : i.writable || i.configurable)) ||\n                              (i = {\n                                  enumerable: !0,\n                                  get: function() {\n                                      return t[r];\n                                  },\n                              }),\n                              Object.defineProperty(e, o, i);\n                      }\n                    : function(e, t, r, o) {\n                          void 0 === o && (o = r), (e[o] = t[r]);\n                      }),\n            r =\n                (commonjsGlobal && commonjsGlobal.__exportStar) ||\n                function(e, r) {\n                    for (var o in e)\n                        'default' === o || Object.prototype.hasOwnProperty.call(r, o) || t(r, e, o);\n                };\n        Object.defineProperty(e, '__esModule', { value: !0 }), (e.PoseLandmarker = void 0);\n        const o = calculator_pb,\n            i = calculator_options_pb,\n            a = landmark_pb,\n            n = base_options_pb,\n            s = pose_detector_graph_options_pb,\n            p = pose_landmarker_graph_options_pb,\n            d = pose_landmarks_detector_graph_options_pb,\n            l = landmark_result,\n            g = vision_task_runner,\n            c = pose_landmarker_result;\n        r(pose_landmarker_options, e), r(pose_landmarker_result, e);\n        const u = 'image_in',\n            m = 'norm_rect',\n            f = 'normalized_landmarks',\n            h = 'world_landmarks',\n            y = 'segmentation_masks',\n            b = 0.5;\n        class _ extends g.VisionTaskRunner {\n            static createFromOptions(e, t) {\n                return g.VisionTaskRunner.createVisionInstance(_, e, t);\n            }\n            static createFromModelBuffer(e, t) {\n                return g.VisionTaskRunner.createVisionInstance(_, e, {\n                    baseOptions: { modelAssetBuffer: t },\n                });\n            }\n            static createFromModelPath(e, t) {\n                return g.VisionTaskRunner.createVisionInstance(_, e, {\n                    baseOptions: { modelAssetPath: t },\n                });\n            }\n            constructor(e, t) {\n                super(new g.VisionGraphRunner(e, t), u, m, !1),\n                    (this.landmarks = []),\n                    (this.worldLandmarks = []),\n                    (this.outputSegmentationMasks = !1),\n                    (this.options = new p.PoseLandmarkerGraphOptions()),\n                    this.options.setBaseOptions(new n.BaseOptions()),\n                    (this.poseLandmarksDetectorGraphOptions = new d.PoseLandmarksDetectorGraphOptions()),\n                    this.options.setPoseLandmarksDetectorGraphOptions(\n                        this.poseLandmarksDetectorGraphOptions\n                    ),\n                    (this.poseDetectorGraphOptions = new s.PoseDetectorGraphOptions()),\n                    this.options.setPoseDetectorGraphOptions(this.poseDetectorGraphOptions),\n                    this.initDefaults();\n            }\n            get baseOptions() {\n                return this.options.getBaseOptions();\n            }\n            set baseOptions(e) {\n                this.options.setBaseOptions(e);\n            }\n            setOptions(e) {\n                var t, r, o, i, a;\n                return (\n                    'numPoses' in e &&\n                        this.poseDetectorGraphOptions.setNumPoses(\n                            null !== (t = e.numPoses) && void 0 !== t ? t : 1\n                        ),\n                    'minPoseDetectionConfidence' in e &&\n                        this.poseDetectorGraphOptions.setMinDetectionConfidence(\n                            null !== (r = e.minPoseDetectionConfidence) && void 0 !== r ? r : b\n                        ),\n                    'minTrackingConfidence' in e &&\n                        this.options.setMinTrackingConfidence(\n                            null !== (o = e.minTrackingConfidence) && void 0 !== o ? o : b\n                        ),\n                    'minPosePresenceConfidence' in e &&\n                        this.poseLandmarksDetectorGraphOptions.setMinDetectionConfidence(\n                            null !== (i = e.minPosePresenceConfidence) && void 0 !== i ? i : b\n                        ),\n                    'outputSegmentationMasks' in e &&\n                        (this.outputSegmentationMasks =\n                            null !== (a = e.outputSegmentationMasks) && void 0 !== a && a),\n                    this.applyOptions(e)\n                );\n            }\n            detect(e, t, r) {\n                const o = 'function' != typeof t ? t : {};\n                return (\n                    (this.userCallback = 'function' == typeof t ? t : r),\n                    this.resetResults(),\n                    this.processImageData(e, o),\n                    this.processResults()\n                );\n            }\n            detectForVideo(e, t, r, o) {\n                const i = 'function' != typeof r ? r : {};\n                return (\n                    (this.userCallback = 'function' == typeof r ? r : o),\n                    this.resetResults(),\n                    this.processVideoData(e, i, t),\n                    this.processResults()\n                );\n            }\n            resetResults() {\n                (this.landmarks = []),\n                    (this.worldLandmarks = []),\n                    (this.segmentationMasks = void 0);\n            }\n            processResults() {\n                try {\n                    const e = new c.PoseLandmarkerResult(\n                        this.landmarks,\n                        this.worldLandmarks,\n                        this.segmentationMasks\n                    );\n                    if (!this.userCallback) return e;\n                    this.userCallback(e);\n                } finally {\n                    this.freeKeepaliveStreams();\n                }\n            }\n            initDefaults() {\n                this.poseDetectorGraphOptions.setNumPoses(1),\n                    this.poseDetectorGraphOptions.setMinDetectionConfidence(b),\n                    this.poseLandmarksDetectorGraphOptions.setMinDetectionConfidence(b),\n                    this.options.setMinTrackingConfidence(b);\n            }\n            addJsLandmarks(e) {\n                this.landmarks = [];\n                for (const t of e) {\n                    const e = a.NormalizedLandmarkList.deserializeBinary(t);\n                    this.landmarks.push((0, l.convertToLandmarks)(e));\n                }\n            }\n            adddJsWorldLandmarks(e) {\n                this.worldLandmarks = [];\n                for (const t of e) {\n                    const e = a.LandmarkList.deserializeBinary(t);\n                    this.worldLandmarks.push((0, l.convertToWorldLandmarks)(e));\n                }\n            }\n            refreshGraph() {\n                const e = new o.CalculatorGraphConfig();\n                e.addInputStream(u),\n                    e.addInputStream(m),\n                    e.addOutputStream(f),\n                    e.addOutputStream(h),\n                    e.addOutputStream(y);\n                const t = new i.CalculatorOptions();\n                t.setExtension(p.PoseLandmarkerGraphOptions.ext, this.options);\n                const r = new o.CalculatorGraphConfig.Node();\n                r.setCalculator('mediapipe.tasks.vision.pose_landmarker.PoseLandmarkerGraph'),\n                    r.addInputStream('IMAGE:' + u),\n                    r.addInputStream('NORM_RECT:' + m),\n                    r.addOutputStream('NORM_LANDMARKS:' + f),\n                    r.addOutputStream('WORLD_LANDMARKS:' + h),\n                    r.setOptions(t),\n                    e.addNode(r),\n                    this.addKeepaliveNode(e),\n                    this.graphRunner.attachProtoVectorListener(f, (e, t) => {\n                        this.addJsLandmarks(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(f, (e) => {\n                        (this.landmarks = []), this.setLatestOutputTimestamp(e);\n                    }),\n                    this.graphRunner.attachProtoVectorListener(h, (e, t) => {\n                        this.adddJsWorldLandmarks(e), this.setLatestOutputTimestamp(t);\n                    }),\n                    this.graphRunner.attachEmptyPacketListener(h, (e) => {\n                        (this.worldLandmarks = []), this.setLatestOutputTimestamp(e);\n                    }),\n                    this.outputSegmentationMasks &&\n                        (r.addOutputStream('SEGMENTATION_MASK:' + y),\n                        this.keepStreamAlive(y),\n                        this.graphRunner.attachImageVectorListener(y, (e, t) => {\n                            (this.segmentationMasks = e.map((e) =>\n                                this.convertToMPMask(e, !this.userCallback)\n                            )),\n                                this.setLatestOutputTimestamp(t);\n                        }),\n                        this.graphRunner.attachEmptyPacketListener(y, (e) => {\n                            (this.segmentationMasks = []), this.setLatestOutputTimestamp(e);\n                        }));\n                const a = e.serializeBinary();\n                this.setGraph(new Uint8Array(a), !0);\n            }\n        }\n        (e.PoseLandmarker = _),\n            (_.POSE_CONNECTIONS = [\n                { start: 0, end: 1 },\n                { start: 1, end: 2 },\n                { start: 2, end: 3 },\n                { start: 3, end: 7 },\n                { start: 0, end: 4 },\n                { start: 4, end: 5 },\n                { start: 5, end: 6 },\n                { start: 6, end: 8 },\n                { start: 9, end: 10 },\n                { start: 11, end: 12 },\n                { start: 11, end: 13 },\n                { start: 13, end: 15 },\n                { start: 15, end: 17 },\n                { start: 15, end: 19 },\n                { start: 15, end: 21 },\n                { start: 17, end: 19 },\n                { start: 12, end: 14 },\n                { start: 14, end: 16 },\n                { start: 16, end: 18 },\n                { start: 16, end: 20 },\n                { start: 16, end: 22 },\n                { start: 18, end: 20 },\n                { start: 11, end: 23 },\n                { start: 12, end: 24 },\n                { start: 23, end: 24 },\n                { start: 23, end: 25 },\n                { start: 24, end: 26 },\n                { start: 25, end: 27 },\n                { start: 26, end: 28 },\n                { start: 27, end: 29 },\n                { start: 28, end: 30 },\n                { start: 29, end: 31 },\n                { start: 30, end: 32 },\n                { start: 27, end: 31 },\n                { start: 28, end: 32 },\n            ]);\n    })(pose_landmarker),\n    Object.defineProperty(vision, '__esModule', { value: !0 });\nvar PoseLandmarker_1 = (vision.PoseLandmarker = ObjectDetector_1 = vision.ObjectDetector = InteractiveSegmenter_1 = vision.InteractiveSegmenter = ImageSegmenter_1 = vision.ImageSegmenter = ImageEmbedder_1 = vision.ImageEmbedder = ImageClassifier_1 = vision.ImageClassifier = HandLandmarker_1 = vision.HandLandmarker = GestureRecognizer_1 = vision.GestureRecognizer = FaceStylizer_1 = vision.FaceStylizer = FaceLandmarker_1 = vision.FaceLandmarker = FaceDetector_1 = vision.FaceDetector = MPMask_1 = vision.MPMask = MPImage_1 = vision.MPImage = FilesetResolver_1 = vision.FilesetResolver = DrawingUtils_1 = vision.DrawingUtils = void 0);\nconst fileset_resolver_1 = fileset_resolver,\n    drawing_utils_1 = drawing_utils,\n    image_1 = image,\n    mask_1 = mask,\n    face_detector_1 = face_detector,\n    face_landmarker_1 = face_landmarker,\n    face_stylizer_1 = face_stylizer,\n    gesture_recognizer_1 = gesture_recognizer,\n    hand_landmarker_1 = hand_landmarker,\n    image_classifier_1 = image_classifier,\n    image_embedder_1 = image_embedder,\n    image_segmenter_1 = image_segmenter,\n    interactive_segmenter_1 = interactive_segmenter,\n    object_detector_1 = object_detector,\n    pose_landmarker_1 = pose_landmarker,\n    DrawingUtils = drawing_utils_1.DrawingUtils;\nvar DrawingUtils_1 = (vision.DrawingUtils = DrawingUtils);\nconst FilesetResolver = fileset_resolver_1.FilesetResolver;\nvar FilesetResolver_1 = (vision.FilesetResolver = FilesetResolver);\nconst MPImage = image_1.MPImage;\nvar MPImage_1 = (vision.MPImage = MPImage);\nconst MPMask = mask_1.MPMask;\nvar MPMask_1 = (vision.MPMask = MPMask);\nconst FaceDetector = face_detector_1.FaceDetector;\nvar FaceDetector_1 = (vision.FaceDetector = FaceDetector);\nconst FaceLandmarker = face_landmarker_1.FaceLandmarker;\nvar FaceLandmarker_1 = (vision.FaceLandmarker = FaceLandmarker);\nconst FaceStylizer = face_stylizer_1.FaceStylizer;\nvar FaceStylizer_1 = (vision.FaceStylizer = FaceStylizer);\nconst GestureRecognizer = gesture_recognizer_1.GestureRecognizer;\nvar GestureRecognizer_1 = (vision.GestureRecognizer = GestureRecognizer);\nconst HandLandmarker = hand_landmarker_1.HandLandmarker;\nvar HandLandmarker_1 = (vision.HandLandmarker = HandLandmarker);\nconst ImageClassifier = image_classifier_1.ImageClassifier;\nvar ImageClassifier_1 = (vision.ImageClassifier = ImageClassifier);\nconst ImageEmbedder = image_embedder_1.ImageEmbedder;\nvar ImageEmbedder_1 = (vision.ImageEmbedder = ImageEmbedder);\nconst ImageSegmenter = image_segmenter_1.ImageSegmenter;\nvar ImageSegmenter_1 = (vision.ImageSegmenter = ImageSegmenter);\nconst InteractiveSegmenter = interactive_segmenter_1.InteractiveSegmenter;\nvar InteractiveSegmenter_1 = (vision.InteractiveSegmenter = InteractiveSegmenter);\nconst ObjectDetector = object_detector_1.ObjectDetector;\nvar ObjectDetector_1 = (vision.ObjectDetector = ObjectDetector);\nconst PoseLandmarker = pose_landmarker_1.PoseLandmarker;\nPoseLandmarker_1 = vision.PoseLandmarker = PoseLandmarker;\n"
  },
  {
    "path": "extern/wasm/vision_wasm_internal.js",
    "content": "// Build 551939664\n\nvar ModuleFactory = (() => {\n  var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;\n  if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;\n  return (\nfunction(ModuleFactory = {})  {\n\nvar Module=typeof ModuleFactory!=\"undefined\"?ModuleFactory:{};var readyPromiseResolve,readyPromiseReject;Module[\"ready\"]=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram=\"./this.program\";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window==\"object\";var ENVIRONMENT_IS_WORKER=typeof importScripts==\"function\";var ENVIRONMENT_IS_NODE=typeof process==\"object\"&&typeof process.versions==\"object\"&&typeof process.versions.node==\"string\";var scriptDirectory=\"\";function locateFile(path){if(Module[\"locateFile\"]){return Module[\"locateFile\"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){var fs=require(\"fs\");var nodePath=require(\"path\");if(ENVIRONMENT_IS_WORKER){scriptDirectory=nodePath.dirname(scriptDirectory)+\"/\"}else{scriptDirectory=__dirname+\"/\"}read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:\"utf8\")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:\"utf8\",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module[\"thisProgram\"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\\\/g,\"/\")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};Module[\"inspect\"]=()=>\"[Emscripten Module object]\"}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=\"undefined\"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf(\"blob:\")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,\"\").lastIndexOf(\"/\")+1)}else{scriptDirectory=\"\"}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);xhr.responseType=\"arraybuffer\";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,true);xhr.responseType=\"arraybuffer\";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module[\"print\"]||console.log.bind(console);var err=Module[\"printErr\"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module[\"arguments\"])arguments_=Module[\"arguments\"];if(Module[\"thisProgram\"])thisProgram=Module[\"thisProgram\"];if(Module[\"quit\"])quit_=Module[\"quit\"];var wasmBinary;if(Module[\"wasmBinary\"])wasmBinary=Module[\"wasmBinary\"];var noExitRuntime=Module[\"noExitRuntime\"]||true;if(typeof WebAssembly!=\"object\"){abort(\"no native wasm support detected\")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module[\"HEAP8\"]=HEAP8=new Int8Array(b);Module[\"HEAP16\"]=HEAP16=new Int16Array(b);Module[\"HEAP32\"]=HEAP32=new Int32Array(b);Module[\"HEAPU8\"]=HEAPU8=new Uint8Array(b);Module[\"HEAPU16\"]=HEAPU16=new Uint16Array(b);Module[\"HEAPU32\"]=HEAPU32=new Uint32Array(b);Module[\"HEAPF32\"]=HEAPF32=new Float32Array(b);Module[\"HEAPF64\"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}function preRun(){if(Module[\"preRun\"]){if(typeof Module[\"preRun\"]==\"function\")Module[\"preRun\"]=[Module[\"preRun\"]];while(Module[\"preRun\"].length){addOnPreRun(Module[\"preRun\"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module[\"noFSInit\"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module[\"postRun\"]){if(typeof Module[\"postRun\"]==\"function\")Module[\"postRun\"]=[Module[\"postRun\"]];while(Module[\"postRun\"].length){addOnPostRun(Module[\"postRun\"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module[\"monitorRunDependencies\"]){Module[\"monitorRunDependencies\"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module[\"monitorRunDependencies\"]){Module[\"monitorRunDependencies\"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module[\"onAbort\"]){Module[\"onAbort\"](what)}what=\"Aborted(\"+what+\")\";err(what);ABORT=true;EXITSTATUS=1;what+=\". Build with -sASSERTIONS for more info.\";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix=\"data:application/octet-stream;base64,\";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith(\"file://\")}var wasmBinaryFile;wasmBinaryFile=\"vision_wasm_internal.wasm\";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw\"both async and sync fetching of the wasm failed\"}catch(err){abort(err)}}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch==\"function\"&&!isFileURI(binaryFile)){return fetch(binaryFile,{credentials:\"same-origin\"}).then(response=>{if(!response[\"ok\"]){throw\"failed to load wasm binary file at '\"+binaryFile+\"'\"}return response[\"arrayBuffer\"]()}).catch(()=>getBinary(binaryFile))}else{if(readAsync){return new Promise((resolve,reject)=>{readAsync(binaryFile,response=>resolve(new Uint8Array(response)),reject)})}}}return Promise.resolve().then(()=>getBinary(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>{return WebAssembly.instantiate(binary,imports)}).then(instance=>{return instance}).then(receiver,reason=>{err(\"failed to asynchronously prepare wasm: \"+reason);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming==\"function\"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch==\"function\"){return fetch(binaryFile,{credentials:\"same-origin\"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(\"wasm streaming compile failed: \"+reason);err(\"falling back to ArrayBuffer instantiation\");return instantiateArrayBuffer(binaryFile,imports,callback)})})}else{return instantiateArrayBuffer(binaryFile,imports,callback)}}function createWasm(){var info={\"a\":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module[\"asm\"]=exports;wasmMemory=Module[\"asm\"][\"od\"];updateMemoryViews();wasmTable=Module[\"asm\"][\"qd\"];addOnInit(Module[\"asm\"][\"pd\"]);removeRunDependency(\"wasm-instantiate\");return exports}addRunDependency(\"wasm-instantiate\");function receiveInstantiationResult(result){receiveInstance(result[\"instance\"])}if(Module[\"instantiateWasm\"]){try{return Module[\"instantiateWasm\"](info,receiveInstance)}catch(e){err(\"Module.instantiateWasm callback failed with error: \"+e);readyPromiseReject(e)}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var tempDouble;var tempI64;var ASM_CONSTS={1188066:$0=>{const canvas=Emval.toValue($0);const context=canvas.getContext(\"webgpu\");return JsValStore.add(context.getCurrentTexture())},1188201:($0,$1,$2,$3,$4)=>{const drawable=Emval.toValue($0);const device=JsValStore.get($1);const texture=JsValStore.get($2);const width=$3;const height=$4;device.queue.copyExternalImageToTexture({source:drawable},{texture:texture},[width,height])},1188452:($0,$1,$2,$3)=>{const sourceExtTex=Emval.toValue($0);const device=JsValStore.get($1);const sampler=JsValStore.get($2);const bgLayout=JsValStore.get($3);const bindGroup=device.createBindGroup({layout:bgLayout,entries:[{binding:0,resource:sampler},{binding:1,resource:sourceExtTex}]});return JsValStore.add(bindGroup)},1188800:($0,$1)=>{const inputArray=Emval.toValue($0);const output=Emval.toValue($1);const ctx=output.getContext(\"2d\");const image_data=new ImageData(inputArray,output.width,output.height);ctx.putImageData(image_data,0,0)},1189024:($0,$1)=>{const input=Emval.toValue($0);const outputArray=Emval.toValue($1);const ctx=input.getContext(\"2d\");const data=ctx.getImageData(0,0,input.width,input.height);outputArray.set(data.data)},1189228:($0,$1)=>{const input=Emval.toValue($0);const output=Emval.toValue($1);const ctx=output.getContext(\"2d\");ctx.drawImage(input,0,0)},1189364:()=>{return typeof HTMLCanvasElement!==\"undefined\"},1189419:()=>{return!!Module[\"preinitializedWebGPUDevice\"]},1189470:()=>{specialHTMLTargets[\"#canvas\"]=Module.canvas},1189521:()=>{return typeof wasmOffsetConverter!==\"undefined\"}};function JsWrapImageConverter(){if(!Module._imageConverter){Module._imageConverter=(binaryPtr,binarySize,width,height,numChannels,makeDeepCopy,outputType)=>{const imageData=new outputType(makeDeepCopy?Module.HEAPU8.slice(binaryPtr,binaryPtr+binarySize).buffer:Module.HEAPU8.buffer,binaryPtr,width*height*numChannels);return{data:imageData,width:width,height:height}}}}function JsOnUint8ArrayImageListener(output_stream_name,binary_ptr,binary_size,width,height,num_channels,make_deep_copy,timestamp_ms){const image=Module._imageConverter(binary_ptr,binary_size,width,height,num_channels,make_deep_copy,Uint8Array);Module._wrapSimpleListenerOutput(output_stream_name,image,timestamp_ms)}function JsOnFloat32ArrayImageListener(output_stream_name,binary_ptr,binary_size,width,height,num_channels,make_deep_copy,timestamp_ms){const image=Module._imageConverter(binary_ptr,binary_size,width,height,num_channels,make_deep_copy,Float32Array);Module._wrapSimpleListenerOutput(output_stream_name,image,timestamp_ms)}function JsOnWebGLTextureListener(output_stream_name,name,width,height,timestamp_ms){Module._wrapSimpleListenerOutput(output_stream_name,{data:GL.textures[name],width:width,height:height},timestamp_ms)}function JsOnUint8ArrayImageVectorListener(output_stream_name,binary_ptr,binary_size,width,height,num_channels,make_deep_copy,timestamp_ms){const image=Module._imageConverter(binary_ptr,binary_size,width,height,num_channels,make_deep_copy,Uint8Array);Module._wrapSimpleListenerOutput(output_stream_name,image,false,timestamp_ms)}function JsOnFloat32ArrayImageVectorListener(output_stream_name,binary_ptr,binary_size,width,height,num_channels,make_deep_copy,timestamp_ms){const image=Module._imageConverter(binary_ptr,binary_size,width,height,num_channels,make_deep_copy,Float32Array);Module._wrapSimpleListenerOutput(output_stream_name,image,false,timestamp_ms)}function JsOnWebGLTextureVectorListener(output_stream_name,name,width,height,timestamp_ms){Module._wrapSimpleListenerOutput(output_stream_name,{data:GL.textures[name],width:width,height:height},false,timestamp_ms)}function JsOnEmptyPacketListener(output_stream_name,timestamp){Module._wrapEmptyPacketListenerOutput(output_stream_name,timestamp)}function JsOnVectorFinishedListener(output_stream_name,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,undefined,true,timestamp)}function JsOnSimpleListenerBool(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,timestamp)}function JsOnVectorListenerBool(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,false,timestamp)}function JsOnSimpleListenerInt(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,timestamp)}function JsOnVectorListenerInt(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,false,timestamp)}function JsOnSimpleListenerDouble(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,timestamp)}function JsOnVectorListenerDouble(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,false,timestamp)}function JsOnSimpleListenerFloat(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,timestamp)}function JsOnVectorListenerFloat(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,false,timestamp)}function JsOnSimpleListenerString(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,UTF8ToString(out_data),timestamp)}function JsOnVectorListenerString(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,UTF8ToString(out_data),false,timestamp)}function JsOnVectorListenerProto(output_stream_name,proto_ptr,proto_size,make_deep_copy,timestamp){const newProtoArray=make_deep_copy?Module.HEAPU8.slice(proto_ptr,proto_ptr+proto_size):new Uint8Array(Module.HEAPU8.buffer,proto_ptr,proto_size);Module._wrapSimpleListenerOutput(output_stream_name,newProtoArray,false,timestamp)}function JsWrapSimpleListeners(){if(!Module._wrapSimpleListenerOutput){Module._wrapSimpleListenerOutput=(outputStreamName,...args)=>{if(Module.simpleListeners){const streamName=UTF8ToString(outputStreamName);if(Module.simpleListeners[streamName]){Module.simpleListeners[streamName](...args)}}}}if(!Module._wrapEmptyPacketListenerOutput){Module._wrapEmptyPacketListenerOutput=(outputStreamName,timestamp)=>{if(Module.emptyPacketListeners){const streamName=UTF8ToString(outputStreamName);if(Module.emptyPacketListeners[streamName]){Module.emptyPacketListeners[streamName](timestamp)}}}}}function JsOnSimpleListenerBinaryArray(output_stream_name,binary_ptr,binary_size,make_deep_copy,timestamp){const newProtoArray=make_deep_copy?Module.HEAPU8.slice(binary_ptr,binary_ptr+binary_size):new Uint8Array(Module.HEAPU8.buffer,binary_ptr,binary_size);Module._wrapSimpleListenerOutput(output_stream_name,newProtoArray,timestamp)}function mediapipe_import_external_texture(device_handle,source_handle){const device=WebGPU.mgrDevice.get(device_handle);const source=Emval.toValue(source_handle);const externalTexture=device.importExternalTexture({source:source});return Emval.toHandle(externalTexture)}function mediapipe_create_utility_canvas2d(){let canvas;if(typeof OffscreenCanvas!==\"undefined\"){canvas=new OffscreenCanvas(0,0)}else{canvas=document.createElement(\"canvas\");canvas.style.display=\"none\";canvas.id=\"canvas_2d\";document.body.appendChild(canvas)}return Emval.toHandle(canvas)}function xnnLoadWasmModuleJS(code,offset,offset_end,invalid_function_index){const tableOriginalSize=wasmTable.length;const binary=new Uint8Array(HEAPU8.slice(code+offset,code+offset_end));try{var module=new WebAssembly.Module(binary);var instance=new WebAssembly.Instance(module,{env:{memory:wasmMemory}});for(var symName in instance.exports){var value=instance.exports[symName];addFunction(value)}if(tableOriginalSize<wasmTable.length){return tableOriginalSize}return invalid_function_index}catch(error){console.log(error);return invalid_function_index}}function JsWrapErrorListener(code,message){if(Module.errorListener){const stringMessage=UTF8ToString(message);Module.errorListener(code,stringMessage)}}function custom_emscripten_dbgn(str,len){if(typeof dbg!==\"undefined\"){dbg(UTF8ToString(str,len))}else{if(typeof custom_dbg===\"undefined\"){function custom_dbg(text){console.warn.apply(console,arguments)}}custom_dbg(UTF8ToString(str,len))}}function HaveOffsetConverter(){return typeof wasmOffsetConverter!==\"undefined\"}function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(!Browser.mainLoop.running){Browser.mainLoop.running=true}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method=\"timeout\"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method=\"rAF\"}else if(mode==2){if(typeof setImmediate==\"undefined\"){var setImmediates=[];var emscriptenMainLoopMessageId=\"setimmediate\";var Browser_setImmediate_messageHandler=event=>{if(event.data===emscriptenMainLoopMessageId||event.data.target===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}};addEventListener(\"message\",Browser_setImmediate_messageHandler,true);setImmediate=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module[\"setImmediates\"]===undefined)Module[\"setImmediates\"]=[];Module[\"setImmediates\"].push(func);postMessage({target:emscriptenMainLoopMessageId})}else postMessage(emscriptenMainLoopMessageId,\"*\")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){setImmediate(Browser.mainLoop.runner)};Browser.mainLoop.method=\"immediate\"}return 0}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){global.performance=require(\"perf_hooks\").performance}_emscripten_get_now=()=>performance.now();function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,noSetTiming){assert(!Browser.mainLoop.func,\"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.\");Browser.mainLoop.func=browserIterationFunc;Browser.mainLoop.arg=arg;var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;function checkIsRunning(){if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop){return false}return true}Browser.mainLoop.running=false;Browser.mainLoop.runner=function Browser_mainLoop_runner(){if(ABORT)return;if(Browser.mainLoop.queue.length>0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}out('main loop blocker \"'+blocker.name+'\" took '+(Date.now()-start)+\" ms\");Browser.mainLoop.updateStatus();if(!checkIsRunning())return;setTimeout(Browser.mainLoop.runner,0);return}if(!checkIsRunning())return;Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0;if(Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}GL.newRenderingFrameStarted();Browser.mainLoop.runIter(browserIterationFunc);if(!checkIsRunning())return;if(typeof SDL==\"object\"&&SDL.audio&&SDL.audio.queueNewAudioData)SDL.audio.queueNewAudioData();Browser.mainLoop.scheduler()};if(!noSetTiming){if(fps&&fps>0){_emscripten_set_main_loop_timing(0,1e3/fps)}else{_emscripten_set_main_loop_timing(1,1)}Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw\"unwind\"}}function handleException(e){if(e instanceof ExitStatus||e==\"unwind\"){return EXITSTATUS}quit_(1,e)}function ExitStatus(status){this.name=\"ExitStatus\";this.message=`Program terminated with exit(${status})`;this.status=status}var PATH={isAbs:path=>path.charAt(0)===\"/\",splitPath:filename=>{var splitPathRe=/^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last===\".\"){parts.splice(i,1)}else if(last===\"..\"){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift(\"..\")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)===\"/\";path=PATH.normalizeArray(path.split(\"/\").filter(p=>!!p),!isAbsolute).join(\"/\");if(!path&&!isAbsolute){path=\".\"}if(path&&trailingSlash){path+=\"/\"}return(isAbsolute?\"/\":\"\")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return\".\"}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path===\"/\")return\"/\";path=PATH.normalize(path);path=path.replace(/\\/$/,\"\");var lastSlash=path.lastIndexOf(\"/\");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join(\"/\"))},join2:(l,r)=>{return PATH.normalize(l+\"/\"+r)}};function initRandomFill(){if(typeof crypto==\"object\"&&typeof crypto[\"getRandomValues\"]==\"function\"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require(\"crypto\");var randomFillSync=crypto_module[\"randomFillSync\"];if(randomFillSync){return view=>crypto_module[\"randomFillSync\"](view)}var randomBytes=crypto_module[\"randomBytes\"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort(\"initRandomDevice\")}function randomFill(view){return(randomFill=initRandomFill())(view)}var PATH_FS={resolve:function(){var resolvedPath=\"\",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=\"string\"){throw new TypeError(\"Arguments to path.resolve must be strings\")}else if(!path){return\"\"}resolvedPath=path+\"/\"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split(\"/\").filter(p=>!!p),!resolvedAbsolute).join(\"/\");return(resolvedAbsolute?\"/\":\"\")+resolvedPath||\".\"},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!==\"\")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!==\"\")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split(\"/\"));var toParts=trim(to.split(\"/\"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push(\"..\")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join(\"/\")}};function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var UTF8Decoder=typeof TextDecoder!=\"undefined\"?new TextDecoder(\"utf8\"):undefined;function UTF8ArrayToString(heapOrArray,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str=\"\";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str}var TTY={ttys:[],init:function(){},shutdown:function(){},register:function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open:function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close:function(stream){stream.tty.ops.fsync(stream.tty)},fsync:function(stream){stream.tty.ops.fsync(stream.tty)},read:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(60)}try{for(var i=0;i<length;i++){stream.tty.ops.put_char(stream.tty,buffer[offset+i])}}catch(e){throw new FS.ErrnoError(29)}if(length){stream.node.timestamp=Date.now()}return i}},default_tty_ops:{get_char:function(tty){if(!tty.input.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;try{bytesRead=fs.readSync(process.stdin.fd,buf,0,BUFSIZE,-1)}catch(e){if(e.toString().includes(\"EOF\"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString(\"utf-8\")}else{result=null}}else if(typeof window!=\"undefined\"&&typeof window.prompt==\"function\"){result=window.prompt(\"Input: \");if(result!==null){result+=\"\\n\"}}else if(typeof readline==\"function\"){result=readline();if(result!==null){result+=\"\\n\"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};function zeroMemory(address,size){HEAPU8.fill(0,address,address+size);return address}function alignMemory(size,alignment){return Math.ceil(size/alignment)*alignment}function mmapAlloc(size){size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(!ptr)return 0;return zeroMemory(ptr,size)}var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,\"/\",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray:function(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage:function(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)>>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr:function(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr:function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup:function(parent,name){throw FS.genericErrors[44]},mknod:function(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename:function(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink:function(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir:function(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir:function(node){var entries=[\".\",\"..\"];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink:function(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink:function(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read:function(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size},write:function(stream,buffer,offset,length,position,canOwn){if(buffer.buffer===HEAP8.buffer){canOwn=false}if(!length)return 0;var node=stream.node;node.timestamp=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=buffer.slice(offset,offset+length);node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray){node.contents.set(buffer.subarray(offset,offset+length),position)}else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length},llseek:function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(28)}return position},allocate:function(stream,offset,length){MEMFS.expandFileStorage(stream.node,offset+length);stream.node.usedBytes=Math.max(stream.node.usedBytes,offset+length)},mmap:function(stream,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&contents.buffer===HEAP8.buffer){allocated=false;ptr=contents.byteOffset}else{if(position>0||position+length<contents.length){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}allocated=true;ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}HEAP8.set(contents,ptr)}return{ptr:ptr,allocated:allocated}},msync:function(stream,buffer,offset,length,mmapFlags){MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0}}};function asyncLoad(url,onload,onerror,noRunDep){var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):\"\";readAsync(url,arrayBuffer=>{assert(arrayBuffer,`Loading data file \"${url}\" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file \"${url}\" failed.`}});if(dep)addRunDependency(dep)}var preloadPlugins=Module[\"preloadPlugins\"]||[];function FS_handledByPreloadPlugin(byteArray,fullname,finish,onerror){if(typeof Browser!=\"undefined\")Browser.init();var handled=false;preloadPlugins.forEach(function(plugin){if(handled)return;if(plugin[\"canHandle\"](fullname)){plugin[\"handle\"](byteArray,fullname,finish,onerror);handled=true}});return handled}function FS_createPreloadedFile(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{if(onerror)onerror();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url==\"string\"){asyncLoad(url,byteArray=>processData(byteArray),onerror)}else{processData(url)}}function FS_modeStringToFlags(str){var flagModes={\"r\":0,\"r+\":2,\"w\":512|64|1,\"w+\":512|64|2,\"a\":1024|64|1,\"a+\":1024|64|2};var flags=flagModes[str];if(typeof flags==\"undefined\"){throw new Error(`Unknown file open mode: ${str}`)}return flags}function FS_getMode(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode}var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:\"/\",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:(path,opts={})=>{path=PATH_FS.resolve(path);if(!path)return{path:\"\",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split(\"/\").filter(p=>!!p);var current=FS.root;var current_path=\"/\";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}current=FS.lookupNode(current,parts[i]);current_path=PATH.join2(current_path,parts[i]);if(FS.isMountpoint(current)){if(!islast||islast&&opts.follow_mount){current=current.mounted.root}}if(!islast||opts.follow){var count=0;while(FS.isLink(current.mode)){var link=FS.readlink(current_path);current_path=PATH_FS.resolve(PATH.dirname(current_path),link);var lookup=FS.lookupPath(current_path,{recurse_count:opts.recurse_count+1});current=lookup.node;if(count++>40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:node=>{var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!==\"/\"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName:(parentid,name)=>{var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length},hashAddNode:node=>{var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:node=>{var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:(parent,name)=>{var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:(parent,name,mode,rdev)=>{var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:node=>{FS.hashRemoveNode(node)},isRoot:node=>{return node===node.parent},isMountpoint:node=>{return!!node.mounted},isFile:mode=>{return(mode&61440)===32768},isDir:mode=>{return(mode&61440)===16384},isLink:mode=>{return(mode&61440)===40960},isChrdev:mode=>{return(mode&61440)===8192},isBlkdev:mode=>{return(mode&61440)===24576},isFIFO:mode=>{return(mode&61440)===4096},isSocket:mode=>{return(mode&49152)===49152},flagsToPermissionString:flag=>{var perms=[\"r\",\"w\",\"rw\"][flag&3];if(flag&512){perms+=\"w\"}return perms},nodePermissions:(node,perms)=>{if(FS.ignorePermissions){return 0}if(perms.includes(\"r\")&&!(node.mode&292)){return 2}else if(perms.includes(\"w\")&&!(node.mode&146)){return 2}else if(perms.includes(\"x\")&&!(node.mode&73)){return 2}return 0},mayLookup:dir=>{var errCode=FS.nodePermissions(dir,\"x\");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:(dir,name)=>{try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,\"wx\")},mayDelete:(dir,name,isdir)=>{var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,\"wx\");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:(node,flags)=>{if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!==\"r\"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:()=>{for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:fd=>FS.streams[fd],createStream:(stream,fd=-1)=>{if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}},flags:{get:function(){return this.shared.flags},set:function(val){this.shared.flags=val}},position:{get:function(){return this.shared.position},set:function(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:fd=>{FS.streams[fd]=null},chrdev_stream_ops:{open:stream=>{var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:()=>{throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice:(dev,ops)=>{FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts:mount=>{var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:(populate,callback)=>{if(typeof populate==\"function\"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:(type,opts,mountpoint)=>{var root=mountpoint===\"/\";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:mountpoint=>{var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:(parent,name)=>{return parent.node_ops.lookup(parent,name)},mknod:(path,mode,dev)=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name===\".\"||name===\"..\"){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:(path,mode)=>{mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:(path,mode)=>{mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:(path,mode)=>{var dirs=path.split(\"/\");var d=\"\";for(var i=0;i<dirs.length;++i){if(!dirs[i])continue;d+=\"/\"+dirs[i];try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev:(path,mode,dev)=>{if(typeof dev==\"undefined\"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink:(oldpath,newpath)=>{if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename:(old_path,new_path)=>{var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!==\".\"){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!==\".\"){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,\"w\");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir:path=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink:path=>{var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat:(path,dontFollow)=>{var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat:path=>{return FS.stat(path,true)},chmod:(path,mode,dontFollow)=>{var node;if(typeof path==\"string\"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod:(path,mode)=>{FS.chmod(path,mode,true)},fchmod:(fd,mode)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chmod(stream.node,mode)},chown:(path,uid,gid,dontFollow)=>{var node;if(typeof path==\"string\"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown:(path,uid,gid)=>{FS.chown(path,uid,gid,true)},fchown:(fd,uid,gid)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chown(stream.node,uid,gid)},truncate:(path,len)=>{if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path==\"string\"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,\"w\");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate:(fd,len)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime:(path,atime,mtime)=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open:(path,flags,mode)=>{if(path===\"\"){throw new FS.ErrnoError(44)}flags=typeof flags==\"string\"?FS_modeStringToFlags(flags):flags;mode=typeof mode==\"undefined\"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path==\"object\"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module[\"logReadFiles\"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close:stream=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed:stream=>{return stream.fd===null},llseek:(stream,offset,whence)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read:(stream,buffer,offset,length,position)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!=\"undefined\";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write:(stream,buffer,offset,length,position,canOwn)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!=\"undefined\";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate:(stream,offset,length)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap:(stream,length,position,prot,flags)=>{if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync:(stream,buffer,offset,length,mmapFlags)=>{if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl:(stream,cmd,arg)=>{if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile:(path,opts={})=>{opts.flags=opts.flags||0;opts.encoding=opts.encoding||\"binary\";if(opts.encoding!==\"utf8\"&&opts.encoding!==\"binary\"){throw new Error(`Invalid encoding type \"${opts.encoding}\"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding===\"utf8\"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding===\"binary\"){ret=buf}FS.close(stream);return ret},writeFile:(path,data,opts={})=>{opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data==\"string\"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error(\"Unsupported data type\")}FS.close(stream)},cwd:()=>FS.currentPath,chdir:path=>{var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,\"x\");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories:()=>{FS.mkdir(\"/tmp\");FS.mkdir(\"/home\");FS.mkdir(\"/home/web_user\")},createDefaultDevices:()=>{FS.mkdir(\"/dev\");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev(\"/dev/null\",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev(\"/dev/tty\",FS.makedev(5,0));FS.mkdev(\"/dev/tty1\",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice(\"/dev\",\"random\",randomByte);FS.createDevice(\"/dev\",\"urandom\",randomByte);FS.mkdir(\"/dev/shm\");FS.mkdir(\"/dev/shm/tmp\")},createSpecialDirectories:()=>{FS.mkdir(\"/proc\");var proc_self=FS.mkdir(\"/proc/self\");FS.mkdir(\"/proc/self/fd\");FS.mount({mount:()=>{var node=FS.createNode(proc_self,\"fd\",16384|511,73);node.node_ops={lookup:(parent,name)=>{var fd=+name;var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);var ret={parent:null,mount:{mountpoint:\"fake\"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},\"/proc/self/fd\")},createStandardStreams:()=>{if(Module[\"stdin\"]){FS.createDevice(\"/dev\",\"stdin\",Module[\"stdin\"])}else{FS.symlink(\"/dev/tty\",\"/dev/stdin\")}if(Module[\"stdout\"]){FS.createDevice(\"/dev\",\"stdout\",null,Module[\"stdout\"])}else{FS.symlink(\"/dev/tty\",\"/dev/stdout\")}if(Module[\"stderr\"]){FS.createDevice(\"/dev\",\"stderr\",null,Module[\"stderr\"])}else{FS.symlink(\"/dev/tty1\",\"/dev/stderr\")}var stdin=FS.open(\"/dev/stdin\",0);var stdout=FS.open(\"/dev/stdout\",1);var stderr=FS.open(\"/dev/stderr\",1)},ensureErrnoError:()=>{if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.name=\"ErrnoError\";this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message=\"FS error\"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=\"<generic error, no stack>\"})},staticInit:()=>{FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},\"/\");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={\"MEMFS\":MEMFS}},init:(input,output,error)=>{FS.init.initialized=true;FS.ensureErrnoError();Module[\"stdin\"]=input||Module[\"stdin\"];Module[\"stdout\"]=output||Module[\"stdout\"];Module[\"stderr\"]=error||Module[\"stderr\"];FS.createStandardStreams()},quit:()=>{FS.init.initialized=false;for(var i=0;i<FS.streams.length;i++){var stream=FS.streams[i];if(!stream){continue}FS.close(stream)}},findObject:(path,dontResolveLastLink)=>{var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath:(path,dontResolveLastLink)=>{try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path===\"/\"}catch(e){ret.error=e.errno}return ret},createPath:(parent,path,canRead,canWrite)=>{parent=typeof parent==\"string\"?parent:FS.getPath(parent);var parts=path.split(\"/\").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile:(parent,name,properties,canRead,canWrite)=>{var path=PATH.join2(typeof parent==\"string\"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile:(parent,name,data,canRead,canWrite,canOwn)=>{var path=name;if(parent){parent=typeof parent==\"string\"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data==\"string\"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,577);FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}return node},createDevice:(parent,name,input,output)=>{var path=PATH.join2(typeof parent==\"string\"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:stream=>{stream.seekable=false},close:stream=>{if(output&&output.buffer&&output.buffer.length){output(10)}},read:(stream,buffer,offset,length,pos)=>{var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write:(stream,buffer,offset,length,pos)=>{for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(29)}}if(length){stream.node.timestamp=Date.now()}return i}});return FS.mkdev(path,mode,dev)},forceLoadFile:obj=>{if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!=\"undefined\"){throw new Error(\"Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.\")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error(\"Cannot load without read() or XMLHttpRequest.\")}},createLazyFile:(parent,name,url,canRead,canWrite)=>{function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open(\"HEAD\",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error(\"Couldn't load \"+url+\". Status: \"+xhr.status);var datalength=Number(xhr.getResponseHeader(\"Content-length\"));var header;var hasByteServing=(header=xhr.getResponseHeader(\"Accept-Ranges\"))&&header===\"bytes\";var usesGzip=(header=xhr.getResponseHeader(\"Content-Encoding\"))&&header===\"gzip\";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error(\"invalid range (\"+from+\", \"+to+\") or no bytes requested!\");if(to>datalength-1)throw new Error(\"only \"+datalength+\" bytes available! programmer error!\");var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);if(datalength!==chunkSize)xhr.setRequestHeader(\"Range\",\"bytes=\"+from+\"-\"+to);xhr.responseType=\"arraybuffer\";if(xhr.overrideMimeType){xhr.overrideMimeType(\"text/plain; charset=x-user-defined\")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error(\"Couldn't load \"+url+\". Status: \"+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||\"\",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==\"undefined\"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==\"undefined\")throw new Error(\"doXHR failed!\");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out(\"LazyFiles on gzip forces download of the whole file when length is accessed\")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=\"undefined\"){if(!ENVIRONMENT_IS_WORKER)throw\"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc\";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size}stream_ops.read=(stream,buffer,offset,length,position)=>{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):\"\"}var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt:function(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat:function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-54}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAP32[buf+12>>2]=stat.uid;HEAP32[buf+16>>2]=stat.gid;HEAP32[buf+20>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAPU32[buf+48>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream}};function _proc_exit(code){EXITSTATUS=code;if(!keepRuntimeAlive()){if(Module[\"onExit\"])Module[\"onExit\"](code);ABORT=true}quit_(code,new ExitStatus(code))}function exitJS(status,implicit){EXITSTATUS=status;_proc_exit(status)}var _exit=exitJS;function maybeExit(){if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}}function callUserCallback(func){if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}}function safeSetTimeout(func,timeout){return setTimeout(()=>{callUserCallback(func)},timeout)}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text=\"warning: \"+text;err(text)}}var Browser={mainLoop:{running:false,scheduler:null,method:\"\",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;setMainLoop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()},updateStatus:function(){if(Module[\"setStatus\"]){var message=Module[\"statusMessage\"]||\"Please wait...\";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining<expected){Module[\"setStatus\"](message+\" (\"+(expected-remaining)+\"/\"+expected+\")\")}else{Module[\"setStatus\"](message)}}else{Module[\"setStatus\"](\"\")}}},runIter:function(func){if(ABORT)return;if(Module[\"preMainLoop\"]){var preRet=Module[\"preMainLoop\"]();if(preRet===false){return}}callUserCallback(func);if(Module[\"postMainLoop\"])Module[\"postMainLoop\"]()}},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function(){if(Browser.initted)return;Browser.initted=true;var imagePlugin={};imagePlugin[\"canHandle\"]=function imagePlugin_canHandle(name){return!Module.noImageDecoding&&/\\.(jpg|jpeg|png|bmp)$/i.test(name)};imagePlugin[\"handle\"]=function imagePlugin_handle(byteArray,name,onload,onerror){var b=new Blob([byteArray],{type:Browser.getMimetype(name)});if(b.size!==byteArray.length){b=new Blob([new Uint8Array(byteArray).buffer],{type:Browser.getMimetype(name)})}var url=URL.createObjectURL(b);var img=new Image;img.onload=()=>{assert(img.complete,\"Image \"+name+\" could not be decoded\");var canvas=document.createElement(\"canvas\");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext(\"2d\");ctx.drawImage(img,0,0);preloadedImages[name]=canvas;URL.revokeObjectURL(url);if(onload)onload(byteArray)};img.onerror=event=>{out(\"Image \"+url+\" could not be decoded\");if(onerror)onerror()};img.src=url};preloadPlugins.push(imagePlugin);var audioPlugin={};audioPlugin[\"canHandle\"]=function audioPlugin_canHandle(name){return!Module.noAudioDecoding&&name.substr(-4)in{\".ogg\":1,\".wav\":1,\".mp3\":1}};audioPlugin[\"handle\"]=function audioPlugin_handle(byteArray,name,onload,onerror){var done=false;function finish(audio){if(done)return;done=true;preloadedAudios[name]=audio;if(onload)onload(byteArray)}var b=new Blob([byteArray],{type:Browser.getMimetype(name)});var url=URL.createObjectURL(b);var audio=new Audio;audio.addEventListener(\"canplaythrough\",()=>finish(audio),false);audio.onerror=function audio_onerror(event){if(done)return;err(\"warning: browser could not fully decode audio \"+name+\", trying slower base64 approach\");function encode64(data){var BASE=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";var PAD=\"=\";var ret=\"\";var leftchar=0;var leftbits=0;for(var i=0;i<data.length;i++){leftchar=leftchar<<8|data[i];leftbits+=8;while(leftbits>=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src=\"data:audio/x-\"+name.substr(-3)+\";base64,\"+encode64(byteArray);finish(audio)};audio.src=url;safeSetTimeout(()=>{finish(audio)},1e4)};preloadPlugins.push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document[\"pointerLockElement\"]===Module[\"canvas\"]||document[\"mozPointerLockElement\"]===Module[\"canvas\"]||document[\"webkitPointerLockElement\"]===Module[\"canvas\"]||document[\"msPointerLockElement\"]===Module[\"canvas\"]}var canvas=Module[\"canvas\"];if(canvas){canvas.requestPointerLock=canvas[\"requestPointerLock\"]||canvas[\"mozRequestPointerLock\"]||canvas[\"webkitRequestPointerLock\"]||canvas[\"msRequestPointerLock\"]||(()=>{});canvas.exitPointerLock=document[\"exitPointerLock\"]||document[\"mozExitPointerLock\"]||document[\"webkitExitPointerLock\"]||document[\"msExitPointerLock\"]||(()=>{});canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener(\"pointerlockchange\",pointerLockChange,false);document.addEventListener(\"mozpointerlockchange\",pointerLockChange,false);document.addEventListener(\"webkitpointerlockchange\",pointerLockChange,false);document.addEventListener(\"mspointerlockchange\",pointerLockChange,false);if(Module[\"elementPointerLock\"]){canvas.addEventListener(\"click\",ev=>{if(!Browser.pointerLock&&Module[\"canvas\"].requestPointerLock){Module[\"canvas\"].requestPointerLock();ev.preventDefault()}},false)}}},createContext:function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false,majorVersion:typeof WebGL2RenderingContext!=\"undefined\"?2:1};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}if(typeof GL!=\"undefined\"){contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}}else{ctx=canvas.getContext(\"2d\")}if(!ctx)return null;if(setInModule){if(!useWebGL)assert(typeof GLctx==\"undefined\",\"cannot set in module if GLctx is used, but we are a non-GL context that would replace it\");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach(callback=>callback());Browser.init()}return ctx},destroyContext:function(canvas,useWebGL,setInModule){},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer,resizeCanvas){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;if(typeof Browser.lockPointer==\"undefined\")Browser.lockPointer=true;if(typeof Browser.resizeCanvas==\"undefined\")Browser.resizeCanvas=false;var canvas=Module[\"canvas\"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document[\"fullscreenElement\"]||document[\"mozFullScreenElement\"]||document[\"msFullscreenElement\"]||document[\"webkitFullscreenElement\"]||document[\"webkitCurrentFullScreenElement\"])===canvasContainer){canvas.exitFullscreen=Browser.exitFullscreen;if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas){Browser.setFullscreenCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas){Browser.setWindowedCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}if(Module[\"onFullScreen\"])Module[\"onFullScreen\"](Browser.isFullscreen);if(Module[\"onFullscreen\"])Module[\"onFullscreen\"](Browser.isFullscreen)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener(\"fullscreenchange\",fullscreenChange,false);document.addEventListener(\"mozfullscreenchange\",fullscreenChange,false);document.addEventListener(\"webkitfullscreenchange\",fullscreenChange,false);document.addEventListener(\"MSFullscreenChange\",fullscreenChange,false)}var canvasContainer=document.createElement(\"div\");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer[\"requestFullscreen\"]||canvasContainer[\"mozRequestFullScreen\"]||canvasContainer[\"msRequestFullscreen\"]||(canvasContainer[\"webkitRequestFullscreen\"]?()=>canvasContainer[\"webkitRequestFullscreen\"](Element[\"ALLOW_KEYBOARD_INPUT\"]):null)||(canvasContainer[\"webkitRequestFullScreen\"]?()=>canvasContainer[\"webkitRequestFullScreen\"](Element[\"ALLOW_KEYBOARD_INPUT\"]):null);canvasContainer.requestFullscreen()},exitFullscreen:function(){if(!Browser.isFullscreen){return false}var CFS=document[\"exitFullscreen\"]||document[\"cancelFullScreen\"]||document[\"mozCancelFullScreen\"]||document[\"msExitFullscreen\"]||document[\"webkitCancelFullScreen\"]||(()=>{});CFS.apply(document,[]);return true},nextRAF:0,fakeRequestAnimationFrame:function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)},requestAnimationFrame:function(func){if(typeof requestAnimationFrame==\"function\"){requestAnimationFrame(func);return}var RAF=Browser.fakeRequestAnimationFrame;RAF(func)},safeSetTimeout:function(func,timeout){return safeSetTimeout(func,timeout)},safeRequestAnimationFrame:function(func){return Browser.requestAnimationFrame(()=>{callUserCallback(func)})},getMimetype:function(name){return{\"jpg\":\"image/jpeg\",\"jpeg\":\"image/jpeg\",\"png\":\"image/png\",\"bmp\":\"image/bmp\",\"ogg\":\"audio/ogg\",\"wav\":\"audio/wav\",\"mp3\":\"audio/mpeg\"}[name.substr(name.lastIndexOf(\".\")+1)]},getUserMedia:function(func){if(!window.getUserMedia){window.getUserMedia=navigator[\"getUserMedia\"]||navigator[\"mozGetUserMedia\"]}window.getUserMedia(func)},getMovementX:function(event){return event[\"movementX\"]||event[\"mozMovementX\"]||event[\"webkitMovementX\"]||0},getMovementY:function(event){return event[\"movementY\"]||event[\"mozMovementY\"]||event[\"webkitMovementY\"]||0},getMouseWheelDelta:function(event){var delta=0;switch(event.type){case\"DOMMouseScroll\":delta=event.detail/3;break;case\"mousewheel\":delta=event.wheelDelta/120;break;case\"wheel\":delta=event.deltaY;switch(event.deltaMode){case 0:delta/=100;break;case 1:delta/=3;break;case 2:delta*=80;break;default:throw\"unrecognized mouse wheel delta mode: \"+event.deltaMode}break;default:throw\"unrecognized mouse wheel event: \"+event.type}return delta},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event){if(Browser.pointerLock){if(event.type!=\"mousemove\"&&\"mozMovementX\"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!=\"undefined\"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module[\"canvas\"].getBoundingClientRect();var cw=Module[\"canvas\"].width;var ch=Module[\"canvas\"].height;var scrollX=typeof window.scrollX!=\"undefined\"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!=\"undefined\"?window.scrollY:window.pageYOffset;if(event.type===\"touchstart\"||event.type===\"touchend\"||event.type===\"touchmove\"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type===\"touchstart\"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type===\"touchend\"||event.type===\"touchmove\"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}},resizeListeners:[],updateResizeListeners:function(){var canvas=Module[\"canvas\"];Browser.resizeListeners.forEach(listener=>listener(canvas.width,canvas.height))},setCanvasSize:function(width,height,noUpdates){var canvas=Module[\"canvas\"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!=\"undefined\"){var flags=HEAPU32[SDL.screen>>2];flags=flags|8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module[\"canvas\"]);Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!=\"undefined\"){var flags=HEAPU32[SDL.screen>>2];flags=flags&~8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module[\"canvas\"]);Browser.updateResizeListeners()},updateCanvasDimensions:function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module[\"forcedAspectRatio\"]&&Module[\"forcedAspectRatio\"]>0){if(w/h<Module[\"forcedAspectRatio\"]){w=Math.round(h*Module[\"forcedAspectRatio\"])}else{h=Math.round(w/Module[\"forcedAspectRatio\"])}}if((document[\"fullscreenElement\"]||document[\"mozFullScreenElement\"]||document[\"msFullscreenElement\"]||document[\"webkitFullscreenElement\"]||document[\"webkitCurrentFullScreenElement\"])===canvas.parentNode&&typeof screen!=\"undefined\"){var factor=Math.min(screen.width/w,screen.height/h);w=Math.round(w*factor);h=Math.round(h*factor)}if(Browser.resizeCanvas){if(canvas.width!=w)canvas.width=w;if(canvas.height!=h)canvas.height=h;if(typeof canvas.style!=\"undefined\"){canvas.style.removeProperty(\"width\");canvas.style.removeProperty(\"height\")}}else{if(canvas.width!=wNative)canvas.width=wNative;if(canvas.height!=hNative)canvas.height=hNative;if(typeof canvas.style!=\"undefined\"){if(w!=wNative||h!=hNative){canvas.style.setProperty(\"width\",w+\"px\",\"important\");canvas.style.setProperty(\"height\",h+\"px\",\"important\")}else{canvas.style.removeProperty(\"width\");canvas.style.removeProperty(\"height\")}}}}};function callRuntimeCallbacks(callbacks){while(callbacks.length>0){callbacks.shift()(Module)}}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast}function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:case 21505:{if(!stream.tty)return-59;return 0}case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-59;return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;return 0}case 21524:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}var dlopenMissingError=\"To use dlopen, you need enable dynamic linking, see https://emscripten.org/docs/compiling/Dynamic-Linking.html\";function __dlopen_js(handle){abort(dlopenMissingError)}function __dlsym_js(handle,symbol){abort(dlopenMissingError)}function __embind_register_bigint(primitiveType,name,size,minRange,maxRange){}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError(`Unknown type size: ${size}`)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret=\"\";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return\"_unknown\"}name=name.replace(/[^a-zA-Z0-9_]/g,\"$\");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return{[name]:function(){return body.apply(this,arguments)}}[name]}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+\"\\n\"+stack.replace(/^Error(:[^\\n]*)?\\n/,\"\")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function registerType(rawType,registeredInstance,options={}){if(!(\"argPackAdvance\"in registeredInstance)){throw new TypeError(\"registerType registeredInstance requires argPackAdvance\")}var name=registeredInstance.name;if(!rawType){throwBindingError(`type \"${name}\" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function __embind_register_bool(rawType,name,size,trueValue,falseValue){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":function(wt){return!!wt},\"toWireType\":function(destructors,o){return o?trueValue:falseValue},\"argPackAdvance\":8,\"readValueFromPointer\":function(pointer){var heap;if(size===1){heap=HEAP8}else if(size===2){heap=HEAP16}else if(size===4){heap=HEAP32}else{throw new TypeError(\"Unknown boolean type size: \"+name)}return this[\"fromWireType\"](heap[pointer>>shift])},destructorFunction:null})}function HandleAllocator(){this.allocated=[undefined];this.freelist=[];this.get=function(id){return this.allocated[id]};this.has=function(id){return this.allocated[id]!==undefined};this.allocate=function(handle){var id=this.freelist.pop()||this.allocated.length;this.allocated[id]=handle;return id};this.free=function(id){this.allocated[id]=undefined;this.freelist.push(id)}}var emval_handles=new HandleAllocator;function __emval_decref(handle){if(handle>=emval_handles.reserved&&0===--emval_handles.get(handle).refcount){emval_handles.free(handle)}}function count_emval_handles(){var count=0;for(var i=emval_handles.reserved;i<emval_handles.allocated.length;++i){if(emval_handles.allocated[i]!==undefined){++count}}return count}function init_emval(){emval_handles.allocated.push({value:undefined},{value:null},{value:true},{value:false});emval_handles.reserved=emval_handles.allocated.length;Module[\"count_emval_handles\"]=count_emval_handles}var Emval={toValue:handle=>{if(!handle){throwBindingError(\"Cannot use deleted val. handle = \"+handle)}return emval_handles.get(handle).value},toHandle:value=>{switch(value){case undefined:return 1;case null:return 2;case true:return 3;case false:return 4;default:{return emval_handles.allocate({refcount:1,value:value})}}}};function simpleReadValueFromPointer(pointer){return this[\"fromWireType\"](HEAP32[pointer>>2])}function __embind_register_emval(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":function(handle){var rv=Emval.toValue(handle);__emval_decref(handle);return rv},\"toWireType\":function(destructors,value){return Emval.toHandle(value)},\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:null})}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this[\"fromWireType\"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this[\"fromWireType\"](HEAPF64[pointer>>3])};default:throw new TypeError(\"Unknown float type: \"+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":function(value){return value},\"toWireType\":function(destructors,value){return value},\"argPackAdvance\":8,\"readValueFromPointer\":floatReadValueFromPointer(name,shift),destructorFunction:null})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError(\"Unknown integer type: \"+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<<bitshift>>>bitshift}var isUnsignedType=name.includes(\"unsigned\");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name:name,\"fromWireType\":fromWireType,\"toWireType\":toWireType,\"argPackAdvance\":8,\"readValueFromPointer\":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(heap.buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":decodeMemoryView,\"argPackAdvance\":8,\"readValueFromPointer\":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name===\"std::string\";registerType(rawType,{name:name,\"fromWireType\":function(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i<length;++i){a[i]=String.fromCharCode(HEAPU8[payload+i])}str=a.join(\"\")}_free(value);return str},\"toWireType\":function(destructors,value){if(value instanceof ArrayBuffer){value=new Uint8Array(value)}var length;var valueIsOfTypeString=typeof value==\"string\";if(!(valueIsOfTypeString||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int8Array)){throwBindingError(\"Cannot pass non-string to std::string\")}if(stdStringIsUTF8&&valueIsOfTypeString){length=lengthBytesUTF8(value)}else{length=value.length}var base=_malloc(4+length+1);var ptr=base+4;HEAPU32[base>>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i<length;++i){var charCode=value.charCodeAt(i);if(charCode>255){_free(ptr);throwBindingError(\"String has UTF-16 code units that do not fit in 8 bits\")}HEAPU8[ptr+i]=charCode}}else{for(var i=0;i<length;++i){HEAPU8[ptr+i]=value[i]}}}if(destructors!==null){destructors.push(_free,base)}return base},\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}var UTF16Decoder=typeof TextDecoder!=\"undefined\"?new TextDecoder(\"utf-16le\"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str=\"\";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite<str.length*2?maxBytesToWrite/2:str.length;for(var i=0;i<numCharsToWrite;++i){var codeUnit=str.charCodeAt(i);HEAP16[outPtr>>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str=\"\";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343)++i;len+=4}return len}function __embind_register_std_wstring(rawType,charSize,name){name=readLatin1String(name);var decodeString,encodeString,getHeap,lengthBytesUTF,shift;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;getHeap=()=>HEAPU16;shift=1}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;getHeap=()=>HEAPU32;shift=2}registerType(rawType,{name:name,\"fromWireType\":function(value){var length=HEAPU32[value>>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},\"toWireType\":function(destructors,value){if(!(typeof value==\"string\")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,\"argPackAdvance\":0,\"fromWireType\":function(){return undefined},\"toWireType\":function(destructors,o){return undefined}})}var nowIsMonotonic=true;function __emscripten_get_now_is_monotonic(){return nowIsMonotonic}function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+\" has unknown type \"+getTypeName(rawType))}return impl}function __emval_as(handle,returnType,destructorsRef){handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,\"emval::as\");var destructors=[];var rd=Emval.toHandle(destructors);HEAPU32[destructorsRef>>2]=rd;return returnType[\"toWireType\"](destructors,handle)}var emval_symbols={};function getStringOrSymbol(address){var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}return symbol}function emval_get_global(){if(typeof globalThis==\"object\"){return globalThis}function testGlobal(obj){obj[\"$$$embind_global$$$\"]=obj;var success=typeof $$$embind_global$$$==\"object\"&&obj[\"$$$embind_global$$$\"]==obj;if(!success){delete obj[\"$$$embind_global$$$\"]}return success}if(typeof $$$embind_global$$$==\"object\"){return $$$embind_global$$$}if(typeof global==\"object\"&&testGlobal(global)){$$$embind_global$$$=global}else if(typeof self==\"object\"&&testGlobal(self)){$$$embind_global$$$=self}if(typeof $$$embind_global$$$==\"object\"){return $$$embind_global$$$}throw Error(\"unable to get global object.\")}function __emval_get_global(name){if(name===0){return Emval.toHandle(emval_get_global())}else{name=getStringOrSymbol(name);return Emval.toHandle(emval_get_global()[name])}}function __emval_get_property(handle,key){handle=Emval.toValue(handle);key=Emval.toValue(key);return Emval.toHandle(handle[key])}function __emval_incref(handle){if(handle>4){emval_handles.get(handle).refcount+=1}}function __emval_instanceof(object,constructor){object=Emval.toValue(object);constructor=Emval.toValue(constructor);return object instanceof constructor}function __emval_new_cstring(v){return Emval.toHandle(getStringOrSymbol(v))}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function __emval_run_destructors(handle){var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)}function __emval_set_property(handle,key,value){handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value}function __emval_take_value(type,arg){type=requireRegisteredType(type,\"_emval_take_value\");var v=type[\"readValueFromPointer\"](arg);return Emval.toHandle(v)}function __emval_typeof(handle){handle=Emval.toValue(handle);return Emval.toHandle(typeof handle)}function readI53FromI64(ptr){return HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296}function __gmtime_js(time,tmPtr){var date=new Date(readI53FromI64(time)*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}function isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];function ydayFromDate(date){var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday}function __localtime_js(time,tmPtr){var date=new Date(readI53FromI64(time)*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}function __mktime_js(tmPtr){var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();return date.getTime()/1e3|0}function __mmap_js(len,prot,flags,fd,off,allocated,addr){try{var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,off,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}FS.munmap(stream)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function stringToNewUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret}function __tzset_js(timezone,daylight,tzname){var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\\(([A-Za-z ]+)\\)$/);return match?match[1]:\"GMT\"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=stringToNewUTF8(winterName);var summerNamePtr=stringToNewUTF8(summerName);if(summerOffset<winterOffset){HEAPU32[tzname>>2]=winterNamePtr;HEAPU32[tzname+4>>2]=summerNamePtr}else{HEAPU32[tzname>>2]=summerNamePtr;HEAPU32[tzname+4>>2]=winterNamePtr}}function _abort(){abort(\"\")}var readEmAsmArgsArray=[];function readEmAsmArgs(sigPtr,buf){readEmAsmArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){buf+=ch!=105&buf;readEmAsmArgsArray.push(ch==105?HEAP32[buf]:HEAPF64[buf++>>1]);++buf}return readEmAsmArgsArray}function runEmAsmFunction(code,sigPtr,argbuf){var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_asm_const_int(code,sigPtr,argbuf){return runEmAsmFunction(code,sigPtr,argbuf)}function _emscripten_date_now(){return Date.now()}function _emscripten_err(str){err(UTF8ToString(str))}function _emscripten_errn(str,len){err(UTF8ToString(str,len))}function getHeapMax(){return 2147483648}function _emscripten_get_heap_max(){return getHeapMax()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function _emscripten_outn(str,len){out(UTF8ToString(str,len))}function _emscripten_pc_get_function(pc){abort(\"Cannot use emscripten_pc_get_function without -sUSE_OFFSET_CONVERTER\")}function emscripten_realloc_buffer(size){var b=wasmMemory.buffer;var pages=size-b.byteLength+65535>>>16;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}function convertFrameToPC(frame){abort(\"Cannot use convertFrameToPC (needed by __builtin_return_address) without -sUSE_OFFSET_CONVERTER\");return 0}var UNWIND_CACHE={};function saveInUnwindCache(callstack){callstack.forEach(frame=>{var pc=convertFrameToPC(frame);if(pc){UNWIND_CACHE[pc]=frame}})}function jsStackTrace(){var error=new Error;if(!error.stack){try{throw new Error}catch(e){error=e}if(!error.stack){return\"(no stack trace available)\"}}return error.stack.toString()}function _emscripten_stack_snapshot(){var callstack=jsStackTrace().split(\"\\n\");if(callstack[0]==\"Error\"){callstack.shift()}saveInUnwindCache(callstack);UNWIND_CACHE.last_addr=convertFrameToPC(callstack[3]);UNWIND_CACHE.last_stack=callstack;return UNWIND_CACHE.last_addr}function _emscripten_stack_unwind_buffer(addr,buffer,count){var stack;if(UNWIND_CACHE.last_addr==addr){stack=UNWIND_CACHE.last_stack}else{stack=jsStackTrace().split(\"\\n\");if(stack[0]==\"Error\"){stack.shift()}saveInUnwindCache(stack)}var offset=3;while(stack[offset]&&convertFrameToPC(stack[offset])!=addr){++offset}for(var i=0;i<count&&stack[i+offset];++i){HEAP32[buffer+i*4>>2]=convertFrameToPC(stack[i+offset])}return i}function webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension(\"ANGLE_instanced_arrays\");if(ext){ctx[\"vertexAttribDivisor\"]=function(index,divisor){ext[\"vertexAttribDivisorANGLE\"](index,divisor)};ctx[\"drawArraysInstanced\"]=function(mode,first,count,primcount){ext[\"drawArraysInstancedANGLE\"](mode,first,count,primcount)};ctx[\"drawElementsInstanced\"]=function(mode,count,type,indices,primcount){ext[\"drawElementsInstancedANGLE\"](mode,count,type,indices,primcount)};return 1}}function webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension(\"OES_vertex_array_object\");if(ext){ctx[\"createVertexArray\"]=function(){return ext[\"createVertexArrayOES\"]()};ctx[\"deleteVertexArray\"]=function(vao){ext[\"deleteVertexArrayOES\"](vao)};ctx[\"bindVertexArray\"]=function(vao){ext[\"bindVertexArrayOES\"](vao)};ctx[\"isVertexArray\"]=function(vao){return ext[\"isVertexArrayOES\"](vao)};return 1}}function webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension(\"WEBGL_draw_buffers\");if(ext){ctx[\"drawBuffers\"]=function(n,bufs){ext[\"drawBuffersWEBGL\"](n,bufs)};return 1}}function webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(ctx){return!!(ctx.dibvbi=ctx.getExtension(\"WEBGL_draw_instanced_base_vertex_base_instance\"))}function webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(ctx){return!!(ctx.mdibvbi=ctx.getExtension(\"WEBGL_multi_draw_instanced_base_vertex_base_instance\"))}function webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebgl=ctx.getExtension(\"WEBGL_multi_draw\"))}var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:function(table){var ret=GL.counter++;for(var i=table.length;i<ret;i++){table[i]=null}return ret},MAX_TEMP_BUFFER_SIZE:2097152,numTempVertexBuffersPerSize:64,log2ceilLookup:function(i){return 32-Math.clz32(i===0?0:i-1)},generateTempBuffers:function(quads,context){var largestIndex=GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);context.tempVertexBufferCounters1=[];context.tempVertexBufferCounters2=[];context.tempVertexBufferCounters1.length=context.tempVertexBufferCounters2.length=largestIndex+1;context.tempVertexBuffers1=[];context.tempVertexBuffers2=[];context.tempVertexBuffers1.length=context.tempVertexBuffers2.length=largestIndex+1;context.tempIndexBuffers=[];context.tempIndexBuffers.length=largestIndex+1;for(var i=0;i<=largestIndex;++i){context.tempIndexBuffers[i]=null;context.tempVertexBufferCounters1[i]=context.tempVertexBufferCounters2[i]=0;var ringbufferLength=GL.numTempVertexBuffersPerSize;context.tempVertexBuffers1[i]=[];context.tempVertexBuffers2[i]=[];var ringbuffer1=context.tempVertexBuffers1[i];var ringbuffer2=context.tempVertexBuffers2[i];ringbuffer1.length=ringbuffer2.length=ringbufferLength;for(var j=0;j<ringbufferLength;++j){ringbuffer1[j]=ringbuffer2[j]=null}}if(quads){context.tempQuadIndexBuffer=GLctx.createBuffer();context.GLctx.bindBuffer(34963,context.tempQuadIndexBuffer);var numIndexes=GL.MAX_TEMP_BUFFER_SIZE>>1;var quadIndexes=new Uint16Array(numIndexes);var i=0,v=0;while(1){quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+1;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v+3;if(i>=numIndexes)break;v+=4}context.GLctx.bufferData(34963,quadIndexes,35044);context.GLctx.bindBuffer(34963,null)}},getTempVertexBuffer:function getTempVertexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ringbuffer=GL.currentContext.tempVertexBuffers1[idx];var nextFreeBufferIndex=GL.currentContext.tempVertexBufferCounters1[idx];GL.currentContext.tempVertexBufferCounters1[idx]=GL.currentContext.tempVertexBufferCounters1[idx]+1&GL.numTempVertexBuffersPerSize-1;var vbo=ringbuffer[nextFreeBufferIndex];if(vbo){return vbo}var prevVBO=GLctx.getParameter(34964);ringbuffer[nextFreeBufferIndex]=GLctx.createBuffer();GLctx.bindBuffer(34962,ringbuffer[nextFreeBufferIndex]);GLctx.bufferData(34962,1<<idx,35048);GLctx.bindBuffer(34962,prevVBO);return ringbuffer[nextFreeBufferIndex]},getTempIndexBuffer:function getTempIndexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ibo=GL.currentContext.tempIndexBuffers[idx];if(ibo){return ibo}var prevIBO=GLctx.getParameter(34965);GL.currentContext.tempIndexBuffers[idx]=GLctx.createBuffer();GLctx.bindBuffer(34963,GL.currentContext.tempIndexBuffers[idx]);GLctx.bufferData(34963,1<<idx,35048);GLctx.bindBuffer(34963,prevIBO);return GL.currentContext.tempIndexBuffers[idx]},newRenderingFrameStarted:function newRenderingFrameStarted(){if(!GL.currentContext){return}var vb=GL.currentContext.tempVertexBuffers1;GL.currentContext.tempVertexBuffers1=GL.currentContext.tempVertexBuffers2;GL.currentContext.tempVertexBuffers2=vb;vb=GL.currentContext.tempVertexBufferCounters1;GL.currentContext.tempVertexBufferCounters1=GL.currentContext.tempVertexBufferCounters2;GL.currentContext.tempVertexBufferCounters2=vb;var largestIndex=GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);for(var i=0;i<=largestIndex;++i){GL.currentContext.tempVertexBufferCounters1[i]=0}},getSource:function(shader,count,string,length){var source=\"\";for(var i=0;i<count;++i){var len=length?HEAP32[length+i*4>>2]:-1;source+=UTF8ToString(HEAP32[string+i*4>>2],len<0?undefined:len)}return source},calcBufLength:function calcBufLength(size,type,stride,count){if(stride>0){return count*stride}var typeSize=GL.byteSizeByType[type-GL.byteSizeByTypeRoot];return size*typeSize*count},usedTempBuffers:[],preDrawHandleClientVertexAttribBindings:function preDrawHandleClientVertexAttribBindings(count){GL.resetBufferBinding=false;for(var i=0;i<GL.currentContext.maxVertexAttribs;++i){var cb=GL.currentContext.clientBuffers[i];if(!cb.clientside||!cb.enabled)continue;GL.resetBufferBinding=true;var size=GL.calcBufLength(cb.size,cb.type,cb.stride,count);var buf=GL.getTempVertexBuffer(size);GLctx.bindBuffer(34962,buf);GLctx.bufferSubData(34962,0,HEAPU8.subarray(cb.ptr,cb.ptr+size));cb.vertexAttribPointerAdaptor.call(GLctx,i,cb.size,cb.type,cb.normalized,cb.stride,0)}},postDrawHandleClientVertexAttribBindings:function postDrawHandleClientVertexAttribBindings(){if(GL.resetBufferBinding){GLctx.bindBuffer(34962,GL.buffers[GLctx.currentArrayBufferBinding])}},createContext:function(canvas,webGLContextAttributes){if(!canvas.getContextSafariWebGL2Fixed){canvas.getContextSafariWebGL2Fixed=canvas.getContext;function fixedGetContext(ver,attrs){var gl=canvas.getContextSafariWebGL2Fixed(ver,attrs);return ver==\"webgl\"==gl instanceof WebGLRenderingContext?gl:null}canvas.getContext=fixedGetContext}var ctx=webGLContextAttributes.majorVersion>1?canvas.getContext(\"webgl2\",webGLContextAttributes):canvas.getContext(\"webgl\",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==\"undefined\"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}context.maxVertexAttribs=context.GLctx.getParameter(34921);context.clientBuffers=[];for(var i=0;i<context.maxVertexAttribs;i++){context.clientBuffers[i]={enabled:false,clientside:false,size:0,type:0,normalized:0,stride:0,ptr:0,vertexAttribPointerAdaptor:null}}GL.generateTempBuffers(false,context);return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return!(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==\"object\")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;GL.contexts[contextHandle]=null},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;webgl_enable_ANGLE_instanced_arrays(GLctx);webgl_enable_OES_vertex_array_object(GLctx);webgl_enable_WEBGL_draw_buffers(GLctx);webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(context.version>=2){GLctx.disjointTimerQueryExt=GLctx.getExtension(\"EXT_disjoint_timer_query_webgl2\")}if(context.version<2||!GLctx.disjointTimerQueryExt){GLctx.disjointTimerQueryExt=GLctx.getExtension(\"EXT_disjoint_timer_query\")}webgl_enable_WEBGL_multi_draw(GLctx);var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(!ext.includes(\"lose_context\")&&!ext.includes(\"debug\")){GLctx.getExtension(ext)}})}};function withStackSave(f){var stack=stackSave();var ret=f();stackRestore(stack);return ret}var JSEvents={inEventHandler:0,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[]},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push(JSEvents.removeAllEventListeners);JSEvents.removeEventListenersRegistered=true}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence<y.precedence})},removeDeferredCalls:function(targetFunction){for(var i=0;i<JSEvents.deferredCalls.length;++i){if(JSEvents.deferredCalls[i].targetFunction==targetFunction){JSEvents.deferredCalls.splice(i,1);--i}}},canPerformEventHandlerRequests:function(){return JSEvents.inEventHandler&&JSEvents.currentEventHandler.allowsDeferredCalls},runDeferredCalls:function(){if(!JSEvents.canPerformEventHandlerRequests()){return}for(var i=0;i<JSEvents.deferredCalls.length;++i){var call=JSEvents.deferredCalls[i];JSEvents.deferredCalls.splice(i,1);--i;call.targetFunction.apply(null,call.argsList)}},eventHandlers:[],removeAllHandlersOnTarget:function(target,eventTypeString){for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==target&&(!eventTypeString||eventTypeString==JSEvents.eventHandlers[i].eventTypeString)){JSEvents._removeHandler(i--)}}},_removeHandler:function(i){var h=JSEvents.eventHandlers[i];h.target.removeEventListener(h.eventTypeString,h.eventListenerFunc,h.useCapture);JSEvents.eventHandlers.splice(i,1)},registerOrRemoveHandler:function(eventHandler){if(!eventHandler.target){return-4}var jsEventHandler=function jsEventHandler(event){++JSEvents.inEventHandler;JSEvents.currentEventHandler=eventHandler;JSEvents.runDeferredCalls();eventHandler.handlerFunc(event);JSEvents.runDeferredCalls();--JSEvents.inEventHandler};if(eventHandler.callbackfunc){eventHandler.eventListenerFunc=jsEventHandler;eventHandler.target.addEventListener(eventHandler.eventTypeString,jsEventHandler,eventHandler.useCapture);JSEvents.eventHandlers.push(eventHandler);JSEvents.registerRemoveEventListeners()}else{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==eventHandler.target&&JSEvents.eventHandlers[i].eventTypeString==eventHandler.eventTypeString){JSEvents._removeHandler(i--)}}}return 0},getNodeNameForTarget:function(target){if(!target)return\"\";if(target==window)return\"#window\";if(target==screen)return\"#screen\";return target&&target.nodeName?target.nodeName:\"\"},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};var emscripten_webgl_power_preferences=[\"default\",\"low-power\",\"high-performance\"];var specialHTMLTargets=[0,typeof document!=\"undefined\"?document:0,typeof window!=\"undefined\"?window:0];function findEventTarget(target){try{if(!target)return window;if(typeof target==\"number\")target=specialHTMLTargets[target]||UTF8ToString(target);if(target===\"#window\")return window;else if(target===\"#document\")return document;else if(target===\"#screen\")return screen;else if(target===\"#canvas\")return Module[\"canvas\"];return typeof target==\"string\"?document.getElementById(target):target}catch(e){return null}}function findCanvasEventTarget(target){if(typeof target==\"number\")target=UTF8ToString(target);if(!target||target===\"#canvas\"){if(typeof GL!=\"undefined\"&&GL.offscreenCanvases[\"canvas\"])return GL.offscreenCanvases[\"canvas\"];return Module[\"canvas\"]}if(typeof GL!=\"undefined\"&&GL.offscreenCanvases[target])return GL.offscreenCanvases[target];return findEventTarget(target)}function _emscripten_webgl_do_create_context(target,attributes){var a=attributes>>2;var powerPreference=HEAP32[a+(24>>2)];var contextAttributes={\"alpha\":!!HEAP32[a+(0>>2)],\"depth\":!!HEAP32[a+(4>>2)],\"stencil\":!!HEAP32[a+(8>>2)],\"antialias\":!!HEAP32[a+(12>>2)],\"premultipliedAlpha\":!!HEAP32[a+(16>>2)],\"preserveDrawingBuffer\":!!HEAP32[a+(20>>2)],\"powerPreference\":emscripten_webgl_power_preferences[powerPreference],\"failIfMajorPerformanceCaveat\":!!HEAP32[a+(28>>2)],majorVersion:HEAP32[a+(32>>2)],minorVersion:HEAP32[a+(36>>2)],enableExtensionsByDefault:HEAP32[a+(40>>2)],explicitSwapControl:HEAP32[a+(44>>2)],proxyContextToMainThread:HEAP32[a+(48>>2)],renderViaOffscreenBackBuffer:HEAP32[a+(52>>2)]};var canvas=findCanvasEventTarget(target);if(!canvas){return 0}if(contextAttributes.explicitSwapControl){return 0}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}var _emscripten_webgl_create_context=_emscripten_webgl_do_create_context;function _emscripten_webgl_destroy_context(contextHandle){if(GL.currentContext==contextHandle)GL.currentContext=0;GL.deleteContext(contextHandle)}function _emscripten_webgl_get_context_attributes(c,a){if(!a)return-5;c=GL.contexts[c];if(!c)return-3;var t=c.GLctx;if(!t)return-3;t=t.getContextAttributes();HEAP32[a>>2]=t.alpha;HEAP32[a+4>>2]=t.depth;HEAP32[a+8>>2]=t.stencil;HEAP32[a+12>>2]=t.antialias;HEAP32[a+16>>2]=t.premultipliedAlpha;HEAP32[a+20>>2]=t.preserveDrawingBuffer;var power=t[\"powerPreference\"]&&emscripten_webgl_power_preferences.indexOf(t[\"powerPreference\"]);HEAP32[a+24>>2]=power;HEAP32[a+28>>2]=t.failIfMajorPerformanceCaveat;HEAP32[a+32>>2]=c.version;HEAP32[a+36>>2]=0;HEAP32[a+40>>2]=c.attributes.enableExtensionsByDefault;return 0}function _emscripten_webgl_do_get_current_context(){return GL.currentContext?GL.currentContext.handle:0}var _emscripten_webgl_get_current_context=_emscripten_webgl_do_get_current_context;function _emscripten_webgl_init_context_attributes(attributes){var a=attributes>>2;for(var i=0;i<56>>2;++i){HEAP32[a+i]=0}HEAP32[a+(0>>2)]=HEAP32[a+(4>>2)]=HEAP32[a+(12>>2)]=HEAP32[a+(16>>2)]=HEAP32[a+(32>>2)]=HEAP32[a+(40>>2)]=1}function _emscripten_webgl_make_context_current(contextHandle){var success=GL.makeContextCurrent(contextHandle);return success?0:-5}function stringToUTF8OnStack(str){var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret}function convertI32PairToI53(lo,hi){return(lo>>>0)+hi*4294967296}var wasmTableMirror=[];function getWasmTableEntry(funcPtr){var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func}var WebGPU={errorCallback:function(callback,type,message,userdata){withStackSave(()=>{var messagePtr=stringToUTF8OnStack(message);getWasmTableEntry(callback)(type,messagePtr,userdata)})},initManagers:function(){if(WebGPU.mgrDevice)return;function Manager(){this.objects={};this.nextId=1;this.create=function(object,wrapper={}){var id=this.nextId++;wrapper.refcount=1;wrapper.object=object;this.objects[id]=wrapper;return id};this.get=function(id){if(!id)return undefined;var o=this.objects[id];return o.object};this.reference=function(id){var o=this.objects[id];o.refcount++};this.release=function(id){var o=this.objects[id];o.refcount--;if(o.refcount<=0){delete this.objects[id]}}}WebGPU.mgrSurface=WebGPU.mgrSurface||new Manager;WebGPU.mgrSwapChain=WebGPU.mgrSwapChain||new Manager;WebGPU.mgrAdapter=WebGPU.mgrAdapter||new Manager;WebGPU.mgrDevice=WebGPU.mgrDevice||new Manager;WebGPU.mgrQueue=WebGPU.mgrQueue||new Manager;WebGPU.mgrCommandBuffer=WebGPU.mgrCommandBuffer||new Manager;WebGPU.mgrCommandEncoder=WebGPU.mgrCommandEncoder||new Manager;WebGPU.mgrRenderPassEncoder=WebGPU.mgrRenderPassEncoder||new Manager;WebGPU.mgrComputePassEncoder=WebGPU.mgrComputePassEncoder||new Manager;WebGPU.mgrBindGroup=WebGPU.mgrBindGroup||new Manager;WebGPU.mgrBuffer=WebGPU.mgrBuffer||new Manager;WebGPU.mgrSampler=WebGPU.mgrSampler||new Manager;WebGPU.mgrTexture=WebGPU.mgrTexture||new Manager;WebGPU.mgrTextureView=WebGPU.mgrTextureView||new Manager;WebGPU.mgrQuerySet=WebGPU.mgrQuerySet||new Manager;WebGPU.mgrBindGroupLayout=WebGPU.mgrBindGroupLayout||new Manager;WebGPU.mgrPipelineLayout=WebGPU.mgrPipelineLayout||new Manager;WebGPU.mgrRenderPipeline=WebGPU.mgrRenderPipeline||new Manager;WebGPU.mgrComputePipeline=WebGPU.mgrComputePipeline||new Manager;WebGPU.mgrShaderModule=WebGPU.mgrShaderModule||new Manager;WebGPU.mgrRenderBundleEncoder=WebGPU.mgrRenderBundleEncoder||new Manager;WebGPU.mgrRenderBundle=WebGPU.mgrRenderBundle||new Manager},makeColor:function(ptr){return{\"r\":HEAPF64[ptr>>3],\"g\":HEAPF64[ptr+8>>3],\"b\":HEAPF64[ptr+16>>3],\"a\":HEAPF64[ptr+24>>3]}},makeExtent3D:function(ptr){return{\"width\":HEAPU32[ptr>>2],\"height\":HEAPU32[ptr+4>>2],\"depthOrArrayLayers\":HEAPU32[ptr+8>>2]}},makeOrigin3D:function(ptr){return{\"x\":HEAPU32[ptr>>2],\"y\":HEAPU32[ptr+4>>2],\"z\":HEAPU32[ptr+8>>2]}},makeImageCopyTexture:function(ptr){return{\"texture\":WebGPU.mgrTexture.get(HEAPU32[ptr+4>>2]),\"mipLevel\":HEAPU32[ptr+8>>2],\"origin\":WebGPU.makeOrigin3D(ptr+12),\"aspect\":WebGPU.TextureAspect[HEAPU32[ptr+24>>2]]}},makeTextureDataLayout:function(ptr){var bytesPerRow=HEAPU32[ptr+16>>2];var rowsPerImage=HEAPU32[ptr+20>>2];return{\"offset\":HEAPU32[ptr+4+8>>2]*4294967296+HEAPU32[ptr+8>>2],\"bytesPerRow\":bytesPerRow===4294967295?undefined:bytesPerRow,\"rowsPerImage\":rowsPerImage===4294967295?undefined:rowsPerImage}},makeImageCopyBuffer:function(ptr){var layoutPtr=ptr+8;var bufferCopyView=WebGPU.makeTextureDataLayout(layoutPtr);bufferCopyView[\"buffer\"]=WebGPU.mgrBuffer.get(HEAPU32[ptr+32>>2]);return bufferCopyView},makePipelineConstants:function(constantCount,constantsPtr){if(!constantCount)return;var constants={};for(var i=0;i<constantCount;++i){var entryPtr=constantsPtr+16*i;var key=UTF8ToString(HEAPU32[entryPtr+4>>2]);constants[key]=HEAPF64[entryPtr+8>>3]}return constants},makePipelineLayout:function(layoutPtr){if(!layoutPtr)return\"auto\";return WebGPU.mgrPipelineLayout.get(layoutPtr)},makeProgrammableStageDescriptor:function(ptr){if(!ptr)return undefined;return{\"module\":WebGPU.mgrShaderModule.get(HEAPU32[ptr+4>>2]),\"entryPoint\":UTF8ToString(HEAPU32[ptr+8>>2]),\"constants\":WebGPU.makePipelineConstants(HEAPU32[ptr+12>>2],HEAPU32[ptr+16>>2])}},DeviceLostReason:{undefined:0,destroyed:1},PreferredFormat:{rgba8unorm:18,bgra8unorm:23},AddressMode:[\"repeat\",\"mirror-repeat\",\"clamp-to-edge\"],BlendFactor:[\"zero\",\"one\",\"src\",\"one-minus-src\",\"src-alpha\",\"one-minus-src-alpha\",\"dst\",\"one-minus-dst\",\"dst-alpha\",\"one-minus-dst-alpha\",\"src-alpha-saturated\",\"constant\",\"one-minus-constant\"],BlendOperation:[\"add\",\"subtract\",\"reverse-subtract\",\"min\",\"max\"],BufferBindingType:[,\"uniform\",\"storage\",\"read-only-storage\"],CompareFunction:[,\"never\",\"less\",\"less-equal\",\"greater\",\"greater-equal\",\"equal\",\"not-equal\",\"always\"],CompilationInfoRequestStatus:[\"success\",\"error\",\"device-lost\",\"unknown\"],ComputePassTimestampLocation:[\"beginning\",\"end\"],CullMode:[\"none\",\"front\",\"back\"],ErrorFilter:[\"validation\",\"out-of-memory\"],FeatureName:[,\"depth-clip-control\",\"depth32float-stencil8\",\"timestamp-query\",\"pipeline-statistics-query\",\"texture-compression-bc\",\"texture-compression-etc2\",\"texture-compression-astc\",\"indirect-first-instance\"],FilterMode:[\"nearest\",\"linear\"],FrontFace:[\"ccw\",\"cw\"],IndexFormat:[,\"uint16\",\"uint32\"],LoadOp:[,\"clear\",\"load\"],PipelineStatisticName:[\"vertex-shader-invocations\",\"clipper-invocations\",\"clipper-primitives-out\",\"fragment-shader-invocations\",\"compute-shader-invocations\"],PowerPreference:[,\"low-power\",\"high-performance\"],PrimitiveTopology:[\"point-list\",\"line-list\",\"line-strip\",\"triangle-list\",\"triangle-strip\"],QueryType:[\"occlusion\",\"pipeline-statistics\",\"timestamp\"],RenderPassTimestampLocation:[\"beginning\",\"end\"],SamplerBindingType:[,\"filtering\",\"non-filtering\",\"comparison\"],StencilOperation:[\"keep\",\"zero\",\"replace\",\"invert\",\"increment-clamp\",\"decrement-clamp\",\"increment-wrap\",\"decrement-wrap\"],StorageTextureAccess:[,\"write-only\"],StoreOp:[,\"store\",\"discard\"],TextureAspect:[\"all\",\"stencil-only\",\"depth-only\"],TextureComponentType:[\"float\",\"sint\",\"uint\",\"depth-comparison\"],TextureDimension:[\"1d\",\"2d\",\"3d\"],TextureFormat:[,\"r8unorm\",\"r8snorm\",\"r8uint\",\"r8sint\",\"r16uint\",\"r16sint\",\"r16float\",\"rg8unorm\",\"rg8snorm\",\"rg8uint\",\"rg8sint\",\"r32float\",\"r32uint\",\"r32sint\",\"rg16uint\",\"rg16sint\",\"rg16float\",\"rgba8unorm\",\"rgba8unorm-srgb\",\"rgba8snorm\",\"rgba8uint\",\"rgba8sint\",\"bgra8unorm\",\"bgra8unorm-srgb\",\"rgb10a2unorm\",\"rg11b10ufloat\",\"rgb9e5ufloat\",\"rg32float\",\"rg32uint\",\"rg32sint\",\"rgba16uint\",\"rgba16sint\",\"rgba16float\",\"rgba32float\",\"rgba32uint\",\"rgba32sint\",\"stencil8\",\"depth16unorm\",\"depth24plus\",\"depth24plus-stencil8\",\"depth32float\",\"depth32float-stencil8\",\"bc1-rgba-unorm\",\"bc1-rgba-unorm-srgb\",\"bc2-rgba-unorm\",\"bc2-rgba-unorm-srgb\",\"bc3-rgba-unorm\",\"bc3-rgba-unorm-srgb\",\"bc4-r-unorm\",\"bc4-r-snorm\",\"bc5-rg-unorm\",\"bc5-rg-snorm\",\"bc6h-rgb-ufloat\",\"bc6h-rgb-float\",\"bc7-rgba-unorm\",\"bc7-rgba-unorm-srgb\",\"etc2-rgb8unorm\",\"etc2-rgb8unorm-srgb\",\"etc2-rgb8a1unorm\",\"etc2-rgb8a1unorm-srgb\",\"etc2-rgba8unorm\",\"etc2-rgba8unorm-srgb\",\"eac-r11unorm\",\"eac-r11snorm\",\"eac-rg11unorm\",\"eac-rg11snorm\",\"astc-4x4-unorm\",\"astc-4x4-unorm-srgb\",\"astc-5x4-unorm\",\"astc-5x4-unorm-srgb\",\"astc-5x5-unorm\",\"astc-5x5-unorm-srgb\",\"astc-6x5-unorm\",\"astc-6x5-unorm-srgb\",\"astc-6x6-unorm\",\"astc-6x6-unorm-srgb\",\"astc-8x5-unorm\",\"astc-8x5-unorm-srgb\",\"astc-8x6-unorm\",\"astc-8x6-unorm-srgb\",\"astc-8x8-unorm\",\"astc-8x8-unorm-srgb\",\"astc-10x5-unorm\",\"astc-10x5-unorm-srgb\",\"astc-10x6-unorm\",\"astc-10x6-unorm-srgb\",\"astc-10x8-unorm\",\"astc-10x8-unorm-srgb\",\"astc-10x10-unorm\",\"astc-10x10-unorm-srgb\",\"astc-12x10-unorm\",\"astc-12x10-unorm-srgb\",\"astc-12x12-unorm\",\"astc-12x12-unorm-srgb\"],TextureSampleType:[,\"float\",\"unfilterable-float\",\"depth\",\"sint\",\"uint\"],TextureViewDimension:[,\"1d\",\"2d\",\"2d-array\",\"cube\",\"cube-array\",\"3d\"],VertexFormat:[,\"uint8x2\",\"uint8x4\",\"sint8x2\",\"sint8x4\",\"unorm8x2\",\"unorm8x4\",\"snorm8x2\",\"snorm8x4\",\"uint16x2\",\"uint16x4\",\"sint16x2\",\"sint16x4\",\"unorm16x2\",\"unorm16x4\",\"snorm16x2\",\"snorm16x4\",\"float16x2\",\"float16x4\",\"float32\",\"float32x2\",\"float32x3\",\"float32x4\",\"uint32\",\"uint32x2\",\"uint32x3\",\"uint32x4\",\"sint32\",\"sint32x2\",\"sint32x3\",\"sint32x4\"],VertexStepMode:[\"vertex\",\"instance\"],FeatureNameString2Enum:{undefined:\"0\",\"depth-clip-control\":\"1\",\"depth32float-stencil8\":\"2\",\"timestamp-query\":\"3\",\"pipeline-statistics-query\":\"4\",\"texture-compression-bc\":\"5\",\"texture-compression-etc2\":\"6\",\"texture-compression-astc\":\"7\",\"indirect-first-instance\":\"8\"}};var JsValStore={values:{},next_id:1,add:function(js_val){var id;do{id=JsValStore.next_id++;if(JsValStore.next_id>2147483647)JsValStore.next_id=1}while(id in JsValStore.values);JsValStore.values[id]=js_val;return id},remove:function(id){delete JsValStore.values[id]},get:function(id){return JsValStore.values[id]}};function _emscripten_webgpu_export_bind_group_layout(handle){return JsValStore.add(WebGPU.mgrBindGroupLayout.get(handle))}function _emscripten_webgpu_export_device(handle){return JsValStore.add(WebGPU.mgrDevice.get(handle))}function _emscripten_webgpu_export_sampler(handle){return JsValStore.add(WebGPU.mgrSampler.get(handle))}function _emscripten_webgpu_export_texture(handle){return JsValStore.add(WebGPU.mgrTexture.get(handle))}function _emscripten_webgpu_get_device(){if(WebGPU.preinitializedDeviceId===undefined){var device=Module[\"preinitializedWebGPUDevice\"];var deviceWrapper={queueId:WebGPU.mgrQueue.create(device[\"queue\"])};WebGPU.preinitializedDeviceId=WebGPU.mgrDevice.create(device,deviceWrapper)}WebGPU.mgrDevice.reference(WebGPU.preinitializedDeviceId);return WebGPU.preinitializedDeviceId}function _emscripten_webgpu_import_bind_group(handle){return WebGPU.mgrBindGroup.create(JsValStore.get(handle))}function _emscripten_webgpu_import_texture(handle){return WebGPU.mgrTexture.create(JsValStore.get(handle))}function _emscripten_webgpu_release_js_handle(id){JsValStore.remove(id)}var ENV={};function getExecutableName(){return thisProgram||\"./this.program\"}function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof navigator==\"object\"&&navigator.languages&&navigator.languages[0]||\"C\").replace(\"-\",\"_\")+\".UTF-8\";var env={\"USER\":\"web_user\",\"LOGNAME\":\"web_user\",\"PATH\":\"/\",\"PWD\":\"/\",\"HOME\":\"/home/web_user\",\"LANG\":lang,\"_\":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings}function stringToAscii(str,buffer){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0}function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAPU32[penviron_buf_size>>2]=bufSize;return 0}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return e.errno}}function doReadv(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break;if(typeof offset!==\"undefined\"){offset+=curr}}return ret}function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return e.errno}}function convertI32PairToI53Checked(lo,hi){return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var offset=convertI32PairToI53Checked(offset_low,offset_high);if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return e.errno}}function doWritev(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!==\"undefined\"){offset+=curr}}return ret}function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return e.errno}}function _getentropy(buffer,size){randomFill(HEAPU8.subarray(buffer,buffer+size));return 0}function _glActiveTexture(x0){GLctx.activeTexture(x0)}function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _glBindAttribLocation(program,index,name){GLctx.bindAttribLocation(GL.programs[program],index,UTF8ToString(name))}function _glBindBuffer(target,buffer){if(target==34962){GLctx.currentArrayBufferBinding=buffer}else if(target==34963){GLctx.currentElementArrayBufferBinding=buffer}if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])}function _glBindBufferBase(target,index,buffer){GLctx.bindBufferBase(target,index,GL.buffers[buffer])}function _glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(target,GL.framebuffers[framebuffer])}function _glBindTexture(target,texture){GLctx.bindTexture(target,GL.textures[texture])}function _glBindVertexArray(vao){GLctx.bindVertexArray(GL.vaos[vao]);var ibo=GLctx.getParameter(34965);GLctx.currentElementArrayBufferBinding=ibo?ibo.name|0:0}function _glBlendEquation(x0){GLctx.blendEquation(x0)}function _glBlendFunc(x0,x1){GLctx.blendFunc(x0,x1)}function _glBufferData(target,size,data,usage){if(GL.currentContext.version>=2){if(data&&size){GLctx.bufferData(target,HEAPU8,usage,data,size)}else{GLctx.bufferData(target,size,usage)}}else{GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}}function _glClear(x0){GLctx.clear(x0)}function _glClearColor(x0,x1,x2,x3){GLctx.clearColor(x0,x1,x2,x3)}function _glClientWaitSync(sync,flags,timeout_low,timeout_high){var timeout=convertI32PairToI53(timeout_low,timeout_high);return GLctx.clientWaitSync(GL.syncs[sync],flags,timeout)}function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;program.maxUniformLength=program.maxAttributeLength=program.maxUniformBlockNameLength=0;program.uniformIdCounter=1;GL.programs[id]=program;return id}function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GLctx.currentArrayBufferBinding)GLctx.currentArrayBufferBinding=0;if(id==GLctx.currentElementArrayBufferBinding)GLctx.currentElementArrayBufferBinding=0;if(id==GLctx.currentPixelPackBufferBinding)GLctx.currentPixelPackBufferBinding=0;if(id==GLctx.currentPixelUnpackBufferBinding)GLctx.currentPixelUnpackBufferBinding=0}}function _glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var id=HEAP32[framebuffers+i*4>>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}}function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null}function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _glDeleteSync(id){if(!id)return;var sync=GL.syncs[id];if(!sync){GL.recordError(1281);return}GLctx.deleteSync(sync);sync.name=0;GL.syncs[id]=null}function _glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _glDeleteVertexArrays(n,vaos){for(var i=0;i<n;i++){var id=HEAP32[vaos+i*4>>2];GLctx.deleteVertexArray(GL.vaos[id]);GL.vaos[id]=null}}function _glDisable(x0){GLctx.disable(x0)}function _glDisableVertexAttribArray(index){var cb=GL.currentContext.clientBuffers[index];cb.enabled=false;GLctx.disableVertexAttribArray(index)}function _glDrawArrays(mode,first,count){GL.preDrawHandleClientVertexAttribBindings(first+count);GLctx.drawArrays(mode,first,count);GL.postDrawHandleClientVertexAttribBindings()}var tempFixedLengthArray=[];function _glDrawBuffers(n,bufs){var bufArray=tempFixedLengthArray[n];for(var i=0;i<n;i++){bufArray[i]=HEAP32[bufs+i*4>>2]}GLctx.drawBuffers(bufArray)}function _glEnable(x0){GLctx.enable(x0)}function _glEnableVertexAttribArray(index){var cb=GL.currentContext.clientBuffers[index];cb.enabled=true;GLctx.enableVertexAttribArray(index)}function _glFenceSync(condition,flags){var sync=GLctx.fenceSync(condition,flags);if(sync){var id=GL.getNewId(GL.syncs);sync.name=id;GL.syncs[id]=sync;return id}return 0}function _glFinish(){GLctx.finish()}function _glFlush(){GLctx.flush()}function _glFramebufferTexture2D(target,attachment,textarget,texture,level){GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)}function _glFramebufferTextureLayer(target,attachment,texture,level,layer){GLctx.framebufferTextureLayer(target,attachment,GL.textures[texture],level,layer)}function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0;i<n;i++){var buffer=GLctx[createFunction]();var id=buffer&&GL.getNewId(objectTable);if(buffer){buffer.name=id;objectTable[id]=buffer}else{GL.recordError(1282)}HEAP32[buffers+i*4>>2]=id}}function _glGenBuffers(n,buffers){__glGenObject(n,buffers,\"createBuffer\",GL.buffers)}function _glGenFramebuffers(n,ids){__glGenObject(n,ids,\"createFramebuffer\",GL.framebuffers)}function _glGenTextures(n,textures){__glGenObject(n,textures,\"createTexture\",GL.textures)}function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,\"createVertexArray\",GL.vaos)}function _glGetAttribLocation(program,name){return GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name))}function _glGetError(){var error=GLctx.getError()||GL.lastError;GL.lastError=0;return error}function writeI53ToI64(ptr,num){HEAPU32[ptr>>2]=num;HEAPU32[ptr+4>>2]=(num-HEAPU32[ptr>>2])/4294967296}function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=0&&type!=1){GL.recordError(1280)}return;case 34814:case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats?formats.length:0;break;case 33309:if(GL.currentContext.version<2){GL.recordError(1282);return}var exts=GLctx.getSupportedExtensions()||[];ret=2*exts.length;break;case 33307:case 33308:if(GL.currentContext.version<2){GL.recordError(1280);return}ret=name_==33307?3:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case\"number\":ret=result;break;case\"boolean\":ret=result?1:0;break;case\"string\":GL.recordError(1280);return;case\"object\":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:{ret=0;break}default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i<result.length;++i){switch(type){case 0:HEAP32[p+i*4>>2]=result[i];break;case 2:HEAPF32[p+i*4>>2]=result[i];break;case 4:HEAP8[p+i>>0]=result[i]?1:0;break}}return}else{try{ret=result.name|0}catch(e){GL.recordError(1280);err(\"GL_INVALID_ENUM in glGet\"+type+\"v: Unknown object returned from WebGL getParameter(\"+name_+\")! (error: \"+e+\")\");return}}break;default:GL.recordError(1280);err(\"GL_INVALID_ENUM in glGet\"+type+\"v: Native code calling glGet\"+type+\"v(\"+name_+\") and it returns \"+result+\" of type \"+typeof result+\"!\");return}}switch(type){case 1:writeI53ToI64(p,ret);break;case 0:HEAP32[p>>2]=ret;break;case 2:HEAPF32[p>>2]=ret;break;case 4:HEAP8[p>>0]=ret?1:0;break}}function _glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,0)}function _glGetProgramiv(program,pname,p){if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}program=GL.programs[program];if(pname==35716){var log=GLctx.getProgramInfoLog(program);if(log===null)log=\"(unknown error)\";HEAP32[p>>2]=log.length+1}else if(pname==35719){if(!program.maxUniformLength){for(var i=0;i<GLctx.getProgramParameter(program,35718);++i){program.maxUniformLength=Math.max(program.maxUniformLength,GLctx.getActiveUniform(program,i).name.length+1)}}HEAP32[p>>2]=program.maxUniformLength}else if(pname==35722){if(!program.maxAttributeLength){for(var i=0;i<GLctx.getProgramParameter(program,35721);++i){program.maxAttributeLength=Math.max(program.maxAttributeLength,GLctx.getActiveAttrib(program,i).name.length+1)}}HEAP32[p>>2]=program.maxAttributeLength}else if(pname==35381){if(!program.maxUniformBlockNameLength){for(var i=0;i<GLctx.getProgramParameter(program,35382);++i){program.maxUniformBlockNameLength=Math.max(program.maxUniformBlockNameLength,GLctx.getActiveUniformBlockName(program,i).length+1)}}HEAP32[p>>2]=program.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(program,pname)}}function _glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log=\"(unknown error)\";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _glGetShaderiv(shader,pname,p){if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log=\"(unknown error)\";var logLength=log?log.length+1:0;HEAP32[p>>2]=logLength}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source?source.length+1:0;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}}function _glGetString(name_){var ret=GL.stringCache[name_];if(!ret){switch(name_){case 7939:var exts=GLctx.getSupportedExtensions()||[];exts=exts.concat(exts.map(function(e){return\"GL_\"+e}));ret=stringToNewUTF8(exts.join(\" \"));break;case 7936:case 7937:case 37445:case 37446:var s=GLctx.getParameter(name_);if(!s){GL.recordError(1280)}ret=s&&stringToNewUTF8(s);break;case 7938:var glVersion=GLctx.getParameter(7938);if(GL.currentContext.version>=2)glVersion=\"OpenGL ES 3.0 (\"+glVersion+\")\";else{glVersion=\"OpenGL ES 2.0 (\"+glVersion+\")\"}ret=stringToNewUTF8(glVersion);break;case 35724:var glslVersion=GLctx.getParameter(35724);var ver_re=/^WebGL GLSL ES ([0-9]\\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+\"0\";glslVersion=\"OpenGL ES GLSL ES \"+ver_num[1]+\" (\"+glslVersion+\")\"}ret=stringToNewUTF8(glslVersion);break;default:GL.recordError(1280)}GL.stringCache[name_]=ret}return ret}function _glGetUniformBlockIndex(program,uniformBlockName){return GLctx.getUniformBlockIndex(GL.programs[program],UTF8ToString(uniformBlockName))}function jstoi_q(str){return parseInt(str)}function webglGetLeftBracePos(name){return name.slice(-1)==\"]\"&&name.lastIndexOf(\"[\")}function webglPrepareUniformLocationsBeforeFirstUse(program){var uniformLocsById=program.uniformLocsById,uniformSizeAndIdsByName=program.uniformSizeAndIdsByName,i,j;if(!uniformLocsById){program.uniformLocsById=uniformLocsById={};program.uniformArrayNamesById={};for(i=0;i<GLctx.getProgramParameter(program,35718);++i){var u=GLctx.getActiveUniform(program,i);var nm=u.name;var sz=u.size;var lb=webglGetLeftBracePos(nm);var arrayName=lb>0?nm.slice(0,lb):nm;var id=program.uniformIdCounter;program.uniformIdCounter+=sz;uniformSizeAndIdsByName[arrayName]=[sz,id];for(j=0;j<sz;++j){uniformLocsById[id]=j;program.uniformArrayNamesById[id++]=arrayName}}}}function _glGetUniformLocation(program,name){name=UTF8ToString(name);if(program=GL.programs[program]){webglPrepareUniformLocationsBeforeFirstUse(program);var uniformLocsById=program.uniformLocsById;var arrayIndex=0;var uniformBaseName=name;var leftBrace=webglGetLeftBracePos(name);if(leftBrace>0){arrayIndex=jstoi_q(name.slice(leftBrace+1))>>>0;uniformBaseName=name.slice(0,leftBrace)}var sizeAndId=program.uniformSizeAndIdsByName[uniformBaseName];if(sizeAndId&&arrayIndex<sizeAndId[0]){arrayIndex+=sizeAndId[1];if(uniformLocsById[arrayIndex]=uniformLocsById[arrayIndex]||GLctx.getUniformLocation(program,name)){return arrayIndex}}}else{GL.recordError(1281)}return-1}function _glLinkProgram(program){program=GL.programs[program];GLctx.linkProgram(program);program.uniformLocsById=0;program.uniformSizeAndIdsByName={}}function _glPixelStorei(pname,param){if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)}function computeUnpackAlignedImageSize(width,height,sizePerPixel,alignment){function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height*alignedRowSize}function colorChannelsInGlTextureFormat(format){var colorChannels={5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4};return colorChannels[format-6402]||1}function heapObjectForWebGLType(type){type-=5120;if(type==0)return HEAP8;if(type==1)return HEAPU8;if(type==2)return HEAP16;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922||type==28520||type==30779||type==30782)return HEAPU32;return HEAPU16}function heapAccessShiftForWebGLHeap(heap){return 31-Math.clz32(heap.BYTES_PER_ELEMENT)}function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat){var heap=heapObjectForWebGLType(type);var shift=heapAccessShiftForWebGLHeap(heap);var byteSize=1<<shift;var sizePerPixel=colorChannelsInGlTextureFormat(format)*byteSize;var bytes=computeUnpackAlignedImageSize(width,height,sizePerPixel,GL.unpackAlignment);return heap.subarray(pixels>>shift,pixels+bytes>>shift)}function _glReadPixels(x,y,width,height,format,type,pixels){if(GL.currentContext.version>=2){if(GLctx.currentPixelPackBufferBinding){GLctx.readPixels(x,y,width,height,format,type,pixels)}else{var heap=heapObjectForWebGLType(type);GLctx.readPixels(x,y,width,height,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}return}var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)}function _glTexParameterf(x0,x1,x2){GLctx.texParameterf(x0,x1,x2)}function _glTexParameterfv(target,pname,params){var param=HEAPF32[params>>2];GLctx.texParameterf(target,pname,param)}function _glTexParameteri(x0,x1,x2){GLctx.texParameteri(x0,x1,x2)}function _glTexStorage2D(x0,x1,x2,x3,x4){GLctx.texStorage2D(x0,x1,x2,x3,x4)}function _glTexStorage3D(x0,x1,x2,x3,x4,x5){GLctx.texStorage3D(x0,x1,x2,x3,x4,x5)}function _glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels){if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)}function _glTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,null)}}function webglGetUniformLocation(location){var p=GLctx.currentProgram;if(p){var webglLoc=p.uniformLocsById[location];if(typeof webglLoc==\"number\"){p.uniformLocsById[location]=webglLoc=GLctx.getUniformLocation(p,p.uniformArrayNamesById[location]+(webglLoc>0?\"[\"+webglLoc+\"]\":\"\"))}return webglLoc}else{GL.recordError(1282)}}function _glUniform1f(location,v0){GLctx.uniform1f(webglGetUniformLocation(location),v0)}function _glUniform1i(location,v0){GLctx.uniform1i(webglGetUniformLocation(location),v0)}function _glUniform2f(location,v0,v1){GLctx.uniform2f(webglGetUniformLocation(location),v0,v1)}var miniTempWebGLFloatBuffers=[];function _glUniform2fv(location,count,value){if(GL.currentContext.version>=2){count&&GLctx.uniform2fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*2);return}if(count<=144){var view=miniTempWebGLFloatBuffers[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(webglGetUniformLocation(location),view)}function _glUniform3f(location,v0,v1,v2){GLctx.uniform3f(webglGetUniformLocation(location),v0,v1,v2)}function _glUniform4fv(location,count,value){if(GL.currentContext.version>=2){count&&GLctx.uniform4fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLFloatBuffers[4*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<4*count;i+=4){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(webglGetUniformLocation(location),view)}var miniTempWebGLIntBuffers=[];function _glUniform4iv(location,count,value){if(GL.currentContext.version>=2){count&&GLctx.uniform4iv(webglGetUniformLocation(location),HEAP32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLIntBuffers[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2];view[i+3]=HEAP32[value+(4*i+12)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4iv(webglGetUniformLocation(location),view)}function _glUniformBlockBinding(program,uniformBlockIndex,uniformBlockBinding){program=GL.programs[program];GLctx.uniformBlockBinding(program,uniformBlockIndex,uniformBlockBinding)}function _glUniformMatrix4fv(location,count,transpose,value){if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*16);return}if(count<=18){var view=miniTempWebGLFloatBuffers[16*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<16*count;i+=16){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3];view[i+4]=heap[dst+4];view[i+5]=heap[dst+5];view[i+6]=heap[dst+6];view[i+7]=heap[dst+7];view[i+8]=heap[dst+8];view[i+9]=heap[dst+9];view[i+10]=heap[dst+10];view[i+11]=heap[dst+11];view[i+12]=heap[dst+12];view[i+13]=heap[dst+13];view[i+14]=heap[dst+14];view[i+15]=heap[dst+15]}}else{var view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,view)}function _glUseProgram(program){program=GL.programs[program];GLctx.useProgram(program);GLctx.currentProgram=program}function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){var cb=GL.currentContext.clientBuffers[index];if(!GLctx.currentArrayBufferBinding){cb.size=size;cb.type=type;cb.normalized=normalized;cb.stride=stride;cb.ptr=ptr;cb.clientside=true;cb.vertexAttribPointerAdaptor=function(index,size,type,normalized,stride,ptr){this.vertexAttribPointer(index,size,type,normalized,stride,ptr)};return}cb.clientside=false;GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _glViewport(x0,x1,x2,x3){GLctx.viewport(x0,x1,x2,x3)}function _mediapipe_find_canvas_event_target(canvasSelector){let target=findCanvasEventTarget(canvasSelector);if(Module&&!target){target=Module.canvasWebGpu}return Emval.toHandle(target)}function _mediapipe_webgl_tex_image_drawable(drawableHandle){const drawable=Emval.toValue(drawableHandle);GLctx.texImage2D(GLctx.TEXTURE_2D,0,GLctx.RGBA,GLctx.RGBA,GLctx.UNSIGNED_BYTE,drawable)}function arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):\"\"};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={\"%c\":\"%a %b %d %H:%M:%S %Y\",\"%D\":\"%m/%d/%y\",\"%F\":\"%Y-%m-%d\",\"%h\":\"%b\",\"%r\":\"%I:%M:%S %p\",\"%R\":\"%H:%M\",\"%T\":\"%H:%M:%S\",\"%x\":\"%m/%d/%y\",\"%X\":\"%H:%M:%S\",\"%Ec\":\"%c\",\"%EC\":\"%C\",\"%Ex\":\"%m/%d/%y\",\"%EX\":\"%H:%M:%S\",\"%Ey\":\"%y\",\"%EY\":\"%Y\",\"%Od\":\"%d\",\"%Oe\":\"%e\",\"%OH\":\"%H\",\"%OI\":\"%I\",\"%Om\":\"%m\",\"%OM\":\"%M\",\"%OS\":\"%S\",\"%Ou\":\"%u\",\"%OU\":\"%U\",\"%OV\":\"%V\",\"%Ow\":\"%w\",\"%OW\":\"%W\",\"%Oy\":\"%y\"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,\"g\"),EXPANSION_RULES_1[rule])}var WEEKDAYS=[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"];var MONTHS=[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"];function leadingSomething(value,digits,character){var str=typeof value==\"number\"?value.toString():value||\"\";while(str.length<digits){str=character[0]+str}return str}function leadingNulls(value,digits){return leadingSomething(value,digits,\"0\")}function compareByDay(date1,date2){function sgn(value){return value<0?-1:value>0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={\"%a\":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},\"%A\":function(date){return WEEKDAYS[date.tm_wday]},\"%b\":function(date){return MONTHS[date.tm_mon].substring(0,3)},\"%B\":function(date){return MONTHS[date.tm_mon]},\"%C\":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},\"%d\":function(date){return leadingNulls(date.tm_mday,2)},\"%e\":function(date){return leadingSomething(date.tm_mday,2,\" \")},\"%g\":function(date){return getWeekBasedYear(date).toString().substring(2)},\"%G\":function(date){return getWeekBasedYear(date)},\"%H\":function(date){return leadingNulls(date.tm_hour,2)},\"%I\":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},\"%j\":function(date){return leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3)},\"%m\":function(date){return leadingNulls(date.tm_mon+1,2)},\"%M\":function(date){return leadingNulls(date.tm_min,2)},\"%n\":function(){return\"\\n\"},\"%p\":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return\"AM\"}return\"PM\"},\"%S\":function(date){return leadingNulls(date.tm_sec,2)},\"%t\":function(){return\"\\t\"},\"%u\":function(date){return date.tm_wday||7},\"%U\":function(date){var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},\"%V\":function(date){var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},\"%w\":function(date){return date.tm_wday},\"%W\":function(date){var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},\"%y\":function(date){return(date.tm_year+1900).toString().substring(2)},\"%Y\":function(date){return date.tm_year+1900},\"%z\":function(date){var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?\"+\":\"-\")+String(\"0000\"+off).slice(-4)},\"%Z\":function(date){return date.tm_zone},\"%%\":function(){return\"%\"}};pattern=pattern.replace(/%%/g,\"\\0\\0\");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,\"g\"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\\0\\0/g,\"%\");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm,loc){return _strftime(s,maxsize,format,tm)}function _wgpuBindGroupLayoutRelease(id){WebGPU.mgrBindGroupLayout.release(id)}function _wgpuBindGroupRelease(id){WebGPU.mgrBindGroup.release(id)}function _wgpuBufferGetMappedRange(bufferId,offset,size){var bufferWrapper=WebGPU.mgrBuffer.objects[bufferId];if(size===0)warnOnce(\"getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE\");size=size>>>0;if(size===4294967295)size=undefined;if(bufferWrapper.mapMode!==2){return 0}var mapped;try{mapped=bufferWrapper.object[\"getMappedRange\"](offset,size)}catch(ex){return 0}var data=_memalign(16,mapped.byteLength);HEAPU8.fill(0,data,mapped.byteLength);bufferWrapper.onUnmap.push(()=>{new Uint8Array(mapped).set(HEAPU8.subarray(data,data+mapped.byteLength));_free(data)});return data}function _wgpuBufferReference(id){WebGPU.mgrBuffer.reference(id)}function _wgpuBufferRelease(id){WebGPU.mgrBuffer.release(id)}function _wgpuBufferUnmap(bufferId){var bufferWrapper=WebGPU.mgrBuffer.objects[bufferId];if(!bufferWrapper.onUnmap){return}for(var i=0;i<bufferWrapper.onUnmap.length;++i){bufferWrapper.onUnmap[i]()}bufferWrapper.onUnmap=undefined;bufferWrapper.object[\"unmap\"]()}function _wgpuCommandBufferRelease(id){WebGPU.mgrCommandBuffer.release(id)}function _wgpuCommandEncoderBeginComputePass(encoderId,descriptor){var desc;function makeComputePassTimestampWrite(twPtr){return{\"querySet\":WebGPU.mgrQuerySet.get(HEAPU32[twPtr>>2]),\"queryIndex\":HEAPU32[twPtr+4>>2],\"location\":WebGPU.ComputePassTimestampLocation[HEAPU32[twPtr+8>>2]]}}function makeComputePassTimestampWrites(count,twPtr){var timestampWrites=[];for(var i=0;i<count;++i){timestampWrites.push(makeComputePassTimestampWrite(twPtr+12*i))}return timestampWrites}if(descriptor){desc={};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var timestampWriteCount=HEAPU32[descriptor+8>>2];if(timestampWriteCount){desc[\"timestampWrites\"]=makeComputePassTimestampWrites(timestampWriteCount,HEAPU32[descriptor+12>>2])}}var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);return WebGPU.mgrComputePassEncoder.create(commandEncoder[\"beginComputePass\"](desc))}function _wgpuCommandEncoderBeginRenderPass(encoderId,descriptor){function makeColorAttachment(caPtr){var viewPtr=HEAPU32[caPtr>>2];if(viewPtr===0){return undefined}var loadOpInt=HEAPU32[caPtr+8>>2];var storeOpInt=HEAPU32[caPtr+12>>2];var clearValue=WebGPU.makeColor(caPtr+16);return{\"view\":WebGPU.mgrTextureView.get(viewPtr),\"resolveTarget\":WebGPU.mgrTextureView.get(HEAPU32[caPtr+4>>2]),\"clearValue\":clearValue,\"loadOp\":WebGPU.LoadOp[loadOpInt],\"storeOp\":WebGPU.StoreOp[storeOpInt]}}function makeColorAttachments(count,caPtr){var attachments=[];for(var i=0;i<count;++i){attachments.push(makeColorAttachment(caPtr+48*i))}return attachments}function makeDepthStencilAttachment(dsaPtr){if(dsaPtr===0)return undefined;return{\"view\":WebGPU.mgrTextureView.get(HEAPU32[dsaPtr>>2]),\"depthClearValue\":HEAPF32[dsaPtr+12>>2],\"depthLoadOp\":WebGPU.LoadOp[HEAPU32[dsaPtr+4>>2]],\"depthStoreOp\":WebGPU.StoreOp[HEAPU32[dsaPtr+8>>2]],\"depthReadOnly\":HEAP8[dsaPtr+16>>0]!==0,\"stencilClearValue\":HEAPU32[dsaPtr+28>>2],\"stencilLoadOp\":WebGPU.LoadOp[HEAPU32[dsaPtr+20>>2]],\"stencilStoreOp\":WebGPU.StoreOp[HEAPU32[dsaPtr+24>>2]],\"stencilReadOnly\":HEAP8[dsaPtr+32>>0]!==0}}function makeRenderPassTimestampWrite(twPtr){return{\"querySet\":WebGPU.mgrQuerySet.get(HEAPU32[twPtr>>2]),\"queryIndex\":HEAPU32[twPtr+4>>2],\"location\":WebGPU.RenderPassTimestampLocation[HEAPU32[twPtr+8>>2]]}}function makeRenderPassTimestampWrites(count,twPtr){var timestampWrites=[];for(var i=0;i<count;++i){timestampWrites.push(makeRenderPassTimestampWrite(twPtr+12*i))}return timestampWrites}function makeRenderPassDescriptor(descriptor){var nextInChainPtr=HEAPU32[descriptor>>2];var maxDrawCount=undefined;if(nextInChainPtr!==0){var sType=HEAPU32[nextInChainPtr+4>>2];var renderPassDescriptorMaxDrawCount=nextInChainPtr;maxDrawCount=HEAPU32[renderPassDescriptorMaxDrawCount+4+8>>2]*4294967296+HEAPU32[renderPassDescriptorMaxDrawCount+8>>2]}var desc={\"label\":undefined,\"colorAttachments\":makeColorAttachments(HEAPU32[descriptor+8>>2],HEAPU32[descriptor+12>>2]),\"depthStencilAttachment\":makeDepthStencilAttachment(HEAPU32[descriptor+16>>2]),\"occlusionQuerySet\":WebGPU.mgrQuerySet.get(HEAPU32[descriptor+20>>2]),\"maxDrawCount\":maxDrawCount};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var timestampWriteCount=HEAPU32[descriptor+24>>2];if(timestampWriteCount){desc[\"timestampWrites\"]=makeRenderPassTimestampWrites(timestampWriteCount,HEAPU32[descriptor+28>>2])}return desc}var desc=makeRenderPassDescriptor(descriptor);var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);return WebGPU.mgrRenderPassEncoder.create(commandEncoder[\"beginRenderPass\"](desc))}function _wgpuCommandEncoderCopyBufferToTexture(encoderId,srcPtr,dstPtr,copySizePtr){var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);var copySize=WebGPU.makeExtent3D(copySizePtr);commandEncoder[\"copyBufferToTexture\"](WebGPU.makeImageCopyBuffer(srcPtr),WebGPU.makeImageCopyTexture(dstPtr),copySize)}function _wgpuCommandEncoderCopyTextureToTexture(encoderId,srcPtr,dstPtr,copySizePtr){var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);var copySize=WebGPU.makeExtent3D(copySizePtr);commandEncoder[\"copyTextureToTexture\"](WebGPU.makeImageCopyTexture(srcPtr),WebGPU.makeImageCopyTexture(dstPtr),copySize)}function _wgpuCommandEncoderFinish(encoderId){var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);return WebGPU.mgrCommandBuffer.create(commandEncoder[\"finish\"]())}function _wgpuCommandEncoderRelease(id){WebGPU.mgrCommandEncoder.release(id)}function _wgpuComputePassEncoderDispatchWorkgroups(passId,x,y,z){var pass=WebGPU.mgrComputePassEncoder.get(passId);pass[\"dispatchWorkgroups\"](x,y,z)}function _wgpuComputePassEncoderEnd(passId){var pass=WebGPU.mgrComputePassEncoder.get(passId);pass[\"end\"]()}function _wgpuComputePassEncoderRelease(id){WebGPU.mgrComputePassEncoder.release(id)}function _wgpuComputePassEncoderSetBindGroup(passId,groupIndex,groupId,dynamicOffsetCount,dynamicOffsetsPtr){var pass=WebGPU.mgrComputePassEncoder.get(passId);var group=WebGPU.mgrBindGroup.get(groupId);if(dynamicOffsetCount==0){pass[\"setBindGroup\"](groupIndex,group)}else{var offsets=[];for(var i=0;i<dynamicOffsetCount;i++,dynamicOffsetsPtr+=4){offsets.push(HEAPU32[dynamicOffsetsPtr>>2])}pass[\"setBindGroup\"](groupIndex,group,offsets)}}function _wgpuComputePassEncoderSetPipeline(passId,pipelineId){var pass=WebGPU.mgrComputePassEncoder.get(passId);var pipeline=WebGPU.mgrComputePipeline.get(pipelineId);pass[\"setPipeline\"](pipeline)}function _wgpuComputePipelineGetBindGroupLayout(pipelineId,groupIndex){var pipeline=WebGPU.mgrComputePipeline.get(pipelineId);return WebGPU.mgrBindGroupLayout.create(pipeline[\"getBindGroupLayout\"](groupIndex))}function _wgpuComputePipelineRelease(id){WebGPU.mgrComputePipeline.release(id)}function _wgpuDeviceCreateBindGroup(deviceId,descriptor){function makeEntry(entryPtr){var bufferId=HEAPU32[entryPtr+8>>2];var samplerId=HEAPU32[entryPtr+32>>2];var textureViewId=HEAPU32[entryPtr+36>>2];var binding=HEAPU32[entryPtr+4>>2];if(bufferId){var size_low=HEAP32[entryPtr+24>>2];var size_high=HEAP32[entryPtr+28>>2];var size=size_high===-1&&size_low===-1?undefined:convertI32PairToI53(size_low,size_high);return{\"binding\":binding,\"resource\":{\"buffer\":WebGPU.mgrBuffer.get(bufferId),\"offset\":HEAPU32[entryPtr+4+16>>2]*4294967296+HEAPU32[entryPtr+16>>2],\"size\":size}}}else if(samplerId){return{\"binding\":binding,\"resource\":WebGPU.mgrSampler.get(samplerId)}}else{return{\"binding\":binding,\"resource\":WebGPU.mgrTextureView.get(textureViewId)}}}function makeEntries(count,entriesPtrs){var entries=[];for(var i=0;i<count;++i){entries.push(makeEntry(entriesPtrs+40*i))}return entries}var desc={\"label\":undefined,\"layout\":WebGPU.mgrBindGroupLayout.get(HEAPU32[descriptor+8>>2]),\"entries\":makeEntries(HEAPU32[descriptor+12>>2],HEAPU32[descriptor+16>>2])};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrBindGroup.create(device[\"createBindGroup\"](desc))}function _wgpuDeviceCreateBuffer(deviceId,descriptor){var mappedAtCreation=HEAP8[descriptor+24>>0]!==0;var desc={\"label\":undefined,\"usage\":HEAPU32[descriptor+8>>2],\"size\":HEAPU32[descriptor+4+16>>2]*4294967296+HEAPU32[descriptor+16>>2],\"mappedAtCreation\":mappedAtCreation};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);var bufferWrapper={};var id=WebGPU.mgrBuffer.create(device[\"createBuffer\"](desc),bufferWrapper);if(mappedAtCreation){bufferWrapper.mapMode=2;bufferWrapper.onUnmap=[]}return id}function _wgpuDeviceCreateCommandEncoder(deviceId,descriptor){var desc;if(descriptor){desc={\"label\":undefined};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr)}var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrCommandEncoder.create(device[\"createCommandEncoder\"](desc))}function _wgpuDeviceCreateComputePipeline(deviceId,descriptor){var desc={\"label\":undefined,\"layout\":WebGPU.makePipelineLayout(HEAPU32[descriptor+8>>2]),\"compute\":WebGPU.makeProgrammableStageDescriptor(descriptor+12)};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrComputePipeline.create(device[\"createComputePipeline\"](desc))}function _wgpuDeviceCreateRenderPipeline(deviceId,descriptor){function makePrimitiveState(rsPtr){if(!rsPtr)return undefined;return{\"topology\":WebGPU.PrimitiveTopology[HEAPU32[rsPtr+4>>2]],\"stripIndexFormat\":WebGPU.IndexFormat[HEAPU32[rsPtr+8>>2]],\"frontFace\":WebGPU.FrontFace[HEAPU32[rsPtr+12>>2]],\"cullMode\":WebGPU.CullMode[HEAPU32[rsPtr+16>>2]]}}function makeBlendComponent(bdPtr){if(!bdPtr)return undefined;return{\"operation\":WebGPU.BlendOperation[HEAPU32[bdPtr>>2]],\"srcFactor\":WebGPU.BlendFactor[HEAPU32[bdPtr+4>>2]],\"dstFactor\":WebGPU.BlendFactor[HEAPU32[bdPtr+8>>2]]}}function makeBlendState(bsPtr){if(!bsPtr)return undefined;return{\"alpha\":makeBlendComponent(bsPtr+12),\"color\":makeBlendComponent(bsPtr+0)}}function makeColorState(csPtr){var formatInt=HEAPU32[csPtr+4>>2];return formatInt===0?undefined:{\"format\":WebGPU.TextureFormat[formatInt],\"blend\":makeBlendState(HEAPU32[csPtr+8>>2]),\"writeMask\":HEAPU32[csPtr+12>>2]}}function makeColorStates(count,csArrayPtr){var states=[];for(var i=0;i<count;++i){states.push(makeColorState(csArrayPtr+16*i))}return states}function makeStencilStateFace(ssfPtr){return{\"compare\":WebGPU.CompareFunction[HEAPU32[ssfPtr>>2]],\"failOp\":WebGPU.StencilOperation[HEAPU32[ssfPtr+4>>2]],\"depthFailOp\":WebGPU.StencilOperation[HEAPU32[ssfPtr+8>>2]],\"passOp\":WebGPU.StencilOperation[HEAPU32[ssfPtr+12>>2]]}}function makeDepthStencilState(dssPtr){if(!dssPtr)return undefined;return{\"format\":WebGPU.TextureFormat[HEAPU32[dssPtr+4>>2]],\"depthWriteEnabled\":HEAP8[dssPtr+8>>0]!==0,\"depthCompare\":WebGPU.CompareFunction[HEAPU32[dssPtr+12>>2]],\"stencilFront\":makeStencilStateFace(dssPtr+16),\"stencilBack\":makeStencilStateFace(dssPtr+32),\"stencilReadMask\":HEAPU32[dssPtr+48>>2],\"stencilWriteMask\":HEAPU32[dssPtr+52>>2],\"depthBias\":HEAPU32[dssPtr+56>>2],\"depthBiasSlopeScale\":HEAPF32[dssPtr+60>>2],\"depthBiasClamp\":HEAPF32[dssPtr+64>>2]}}function makeVertexAttribute(vaPtr){return{\"format\":WebGPU.VertexFormat[HEAPU32[vaPtr>>2]],\"offset\":HEAPU32[vaPtr+4+8>>2]*4294967296+HEAPU32[vaPtr+8>>2],\"shaderLocation\":HEAPU32[vaPtr+16>>2]}}function makeVertexAttributes(count,vaArrayPtr){var vas=[];for(var i=0;i<count;++i){vas.push(makeVertexAttribute(vaArrayPtr+i*24))}return vas}function makeVertexBuffer(vbPtr){if(!vbPtr)return undefined;var stepModeInt=HEAPU32[vbPtr+8>>2];return stepModeInt===2?null:{\"arrayStride\":HEAPU32[vbPtr+4>>2]*4294967296+HEAPU32[vbPtr>>2],\"stepMode\":WebGPU.VertexStepMode[stepModeInt],\"attributes\":makeVertexAttributes(HEAPU32[vbPtr+12>>2],HEAPU32[vbPtr+16>>2])}}function makeVertexBuffers(count,vbArrayPtr){if(!count)return undefined;var vbs=[];for(var i=0;i<count;++i){vbs.push(makeVertexBuffer(vbArrayPtr+i*24))}return vbs}function makeVertexState(viPtr){if(!viPtr)return undefined;return{\"module\":WebGPU.mgrShaderModule.get(HEAPU32[viPtr+4>>2]),\"entryPoint\":UTF8ToString(HEAPU32[viPtr+8>>2]),\"constants\":WebGPU.makePipelineConstants(HEAPU32[viPtr+12>>2],HEAPU32[viPtr+16>>2]),\"buffers\":makeVertexBuffers(HEAPU32[viPtr+20>>2],HEAPU32[viPtr+24>>2])}}function makeMultisampleState(msPtr){if(!msPtr)return undefined;return{\"count\":HEAPU32[msPtr+4>>2],\"mask\":HEAPU32[msPtr+8>>2],\"alphaToCoverageEnabled\":HEAP8[msPtr+12>>0]!==0}}function makeFragmentState(fsPtr){if(!fsPtr)return undefined;return{\"module\":WebGPU.mgrShaderModule.get(HEAPU32[fsPtr+4>>2]),\"entryPoint\":UTF8ToString(HEAPU32[fsPtr+8>>2]),\"constants\":WebGPU.makePipelineConstants(HEAPU32[fsPtr+12>>2],HEAPU32[fsPtr+16>>2]),\"targets\":makeColorStates(HEAPU32[fsPtr+20>>2],HEAPU32[fsPtr+24>>2])}}var desc={\"label\":undefined,\"layout\":WebGPU.makePipelineLayout(HEAPU32[descriptor+8>>2]),\"vertex\":makeVertexState(descriptor+12),\"primitive\":makePrimitiveState(descriptor+40),\"depthStencil\":makeDepthStencilState(HEAPU32[descriptor+60>>2]),\"multisample\":makeMultisampleState(descriptor+64),\"fragment\":makeFragmentState(HEAPU32[descriptor+80>>2])};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrRenderPipeline.create(device[\"createRenderPipeline\"](desc))}function _wgpuDeviceCreateSampler(deviceId,descriptor){var desc={\"label\":undefined,\"addressModeU\":WebGPU.AddressMode[HEAPU32[descriptor+8>>2]],\"addressModeV\":WebGPU.AddressMode[HEAPU32[descriptor+12>>2]],\"addressModeW\":WebGPU.AddressMode[HEAPU32[descriptor+16>>2]],\"magFilter\":WebGPU.FilterMode[HEAPU32[descriptor+20>>2]],\"minFilter\":WebGPU.FilterMode[HEAPU32[descriptor+24>>2]],\"mipmapFilter\":WebGPU.FilterMode[HEAPU32[descriptor+28>>2]],\"lodMinClamp\":HEAPF32[descriptor+32>>2],\"lodMaxClamp\":HEAPF32[descriptor+36>>2],\"compare\":WebGPU.CompareFunction[HEAPU32[descriptor+40>>2]]};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrSampler.create(device[\"createSampler\"](desc))}function _wgpuDeviceCreateShaderModule(deviceId,descriptor){var nextInChainPtr=HEAPU32[descriptor>>2];var sType=HEAPU32[nextInChainPtr+4>>2];var desc={\"label\":undefined,\"code\":\"\"};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);switch(sType){case 5:{var count=HEAPU32[nextInChainPtr+8>>2];var start=HEAPU32[nextInChainPtr+12>>2];desc[\"code\"]=HEAPU32.subarray(start>>2,(start>>2)+count);break}case 6:{var sourcePtr=HEAPU32[nextInChainPtr+8>>2];if(sourcePtr){desc[\"code\"]=UTF8ToString(sourcePtr)}break}}var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrShaderModule.create(device[\"createShaderModule\"](desc))}function _wgpuDeviceCreateTexture(deviceId,descriptor){var desc={\"label\":undefined,\"size\":WebGPU.makeExtent3D(descriptor+16),\"mipLevelCount\":HEAPU32[descriptor+32>>2],\"sampleCount\":HEAPU32[descriptor+36>>2],\"dimension\":WebGPU.TextureDimension[HEAPU32[descriptor+12>>2]],\"format\":WebGPU.TextureFormat[HEAPU32[descriptor+28>>2]],\"usage\":HEAPU32[descriptor+8>>2]};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var viewFormatCount=HEAPU32[descriptor+40>>2];if(viewFormatCount){var viewFormatsPtr=HEAPU32[descriptor+44>>2];desc[\"viewFormats\"]=Array.from(HEAP32.subarray(viewFormatsPtr>>2,(viewFormatsPtr>>2)+viewFormatCount),function(format){return WebGPU.TextureFormat[format]})}var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrTexture.create(device[\"createTexture\"](desc))}function _wgpuDeviceGetQueue(deviceId){var queueId=WebGPU.mgrDevice.objects[deviceId].queueId;WebGPU.mgrQueue.reference(queueId);return queueId}function _wgpuDeviceReference(id){WebGPU.mgrDevice.reference(id)}function _wgpuDeviceRelease(id){WebGPU.mgrDevice.release(id)}function _wgpuPipelineLayoutRelease(id){WebGPU.mgrPipelineLayout.release(id)}function _wgpuQuerySetRelease(id){WebGPU.mgrQuerySet.release(id)}function _wgpuQueueRelease(id){WebGPU.mgrQueue.release(id)}function _wgpuQueueSubmit(queueId,commandCount,commands){var queue=WebGPU.mgrQueue.get(queueId);var cmds=Array.from(HEAP32.subarray(commands>>2,(commands>>2)+commandCount),function(id){return WebGPU.mgrCommandBuffer.get(id)});queue[\"submit\"](cmds)}function _wgpuQueueWriteBuffer(queueId,bufferId,bufferOffset_low,bufferOffset_high,data,size){var bufferOffset=convertI32PairToI53Checked(bufferOffset_low,bufferOffset_high);if(isNaN(bufferOffset))return undefined;var queue=WebGPU.mgrQueue.get(queueId);var buffer=WebGPU.mgrBuffer.get(bufferId);var subarray=HEAPU8.subarray(data,data+size);queue[\"writeBuffer\"](buffer,bufferOffset,subarray,0,size)}function _wgpuRenderPassEncoderDraw(passId,vertexCount,instanceCount,firstVertex,firstInstance){var pass=WebGPU.mgrRenderPassEncoder.get(passId);pass[\"draw\"](vertexCount,instanceCount,firstVertex,firstInstance)}function _wgpuRenderPassEncoderEnd(passId){var pass=WebGPU.mgrRenderPassEncoder.get(passId);pass[\"end\"]()}function _wgpuRenderPassEncoderRelease(id){WebGPU.mgrRenderPassEncoder.release(id)}function _wgpuRenderPassEncoderSetBindGroup(passId,groupIndex,groupId,dynamicOffsetCount,dynamicOffsetsPtr){var pass=WebGPU.mgrRenderPassEncoder.get(passId);var group=WebGPU.mgrBindGroup.get(groupId);if(dynamicOffsetCount==0){pass[\"setBindGroup\"](groupIndex,group)}else{var offsets=[];for(var i=0;i<dynamicOffsetCount;i++,dynamicOffsetsPtr+=4){offsets.push(HEAPU32[dynamicOffsetsPtr>>2])}pass[\"setBindGroup\"](groupIndex,group,offsets)}}function _wgpuRenderPassEncoderSetPipeline(passId,pipelineId){var pass=WebGPU.mgrRenderPassEncoder.get(passId);var pipeline=WebGPU.mgrRenderPipeline.get(pipelineId);pass[\"setPipeline\"](pipeline)}function _wgpuRenderPipelineGetBindGroupLayout(pipelineId,groupIndex){var pipeline=WebGPU.mgrRenderPipeline.get(pipelineId);return WebGPU.mgrBindGroupLayout.create(pipeline[\"getBindGroupLayout\"](groupIndex))}function _wgpuRenderPipelineRelease(id){WebGPU.mgrRenderPipeline.release(id)}function _wgpuSamplerReference(id){WebGPU.mgrSampler.reference(id)}function _wgpuSamplerRelease(id){WebGPU.mgrSampler.release(id)}function _wgpuShaderModuleReference(id){WebGPU.mgrShaderModule.reference(id)}function _wgpuShaderModuleRelease(id){WebGPU.mgrShaderModule.release(id)}function _wgpuTextureCreateView(textureId,descriptor){var desc;if(descriptor){var mipLevelCount=HEAPU32[descriptor+20>>2];var arrayLayerCount=HEAPU32[descriptor+28>>2];desc={\"format\":WebGPU.TextureFormat[HEAPU32[descriptor+8>>2]],\"dimension\":WebGPU.TextureViewDimension[HEAPU32[descriptor+12>>2]],\"baseMipLevel\":HEAPU32[descriptor+16>>2],\"mipLevelCount\":mipLevelCount===4294967295?undefined:mipLevelCount,\"baseArrayLayer\":HEAPU32[descriptor+24>>2],\"arrayLayerCount\":arrayLayerCount===4294967295?undefined:arrayLayerCount,\"aspect\":WebGPU.TextureAspect[HEAPU32[descriptor+32>>2]]};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr)}var texture=WebGPU.mgrTexture.get(textureId);return WebGPU.mgrTextureView.create(texture[\"createView\"](desc))}function _wgpuTextureDestroy(textureId){WebGPU.mgrTexture.get(textureId)[\"destroy\"]()}function _wgpuTextureReference(id){WebGPU.mgrTexture.reference(id)}function _wgpuTextureRelease(id){WebGPU.mgrTexture.release(id)}function _wgpuTextureViewReference(id){WebGPU.mgrTextureView.reference(id)}function _wgpuTextureViewRelease(id){WebGPU.mgrTextureView.release(id)}function getCFunc(ident){var func=Module[\"_\"+ident];return func}function ccall(ident,returnType,argTypes,args,opts){var toC={\"string\":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},\"array\":arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType===\"string\"){return UTF8ToString(ret)}if(returnType===\"boolean\")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);function onDone(ret){if(stack!==0)stackRestore(stack);return convertReturnValue(ret)}ret=onDone(ret);return ret}Module[\"requestFullscreen\"]=function Module_requestFullscreen(lockPointer,resizeCanvas){Browser.requestFullscreen(lockPointer,resizeCanvas)};Module[\"requestAnimationFrame\"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module[\"setCanvasSize\"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module[\"pauseMainLoop\"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module[\"resumeMainLoop\"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module[\"getUserMedia\"]=function Module_getUserMedia(){Browser.getUserMedia()};Module[\"createContext\"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};var preloadedImages={};var preloadedAudios={};var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();Module[\"FS_createPath\"]=FS.createPath;Module[\"FS_createDataFile\"]=FS.createDataFile;Module[\"FS_createPreloadedFile\"]=FS.createPreloadedFile;Module[\"FS_unlink\"]=FS.unlink;Module[\"FS_createLazyFile\"]=FS.createLazyFile;Module[\"FS_createDevice\"]=FS.createDevice;embind_init_charCodes();BindingError=Module[\"BindingError\"]=extendError(Error,\"BindingError\");InternalError=Module[\"InternalError\"]=extendError(Error,\"InternalError\");init_emval();var GLctx;WebGPU.initManagers();for(var i=0;i<32;++i)tempFixedLengthArray.push(new Array(i));var miniTempWebGLFloatBuffersStorage=new Float32Array(288);for(var i=0;i<288;++i){miniTempWebGLFloatBuffers[i]=miniTempWebGLFloatBuffersStorage.subarray(0,i+1)}var miniTempWebGLIntBuffersStorage=new Int32Array(288);for(var i=0;i<288;++i){miniTempWebGLIntBuffers[i]=miniTempWebGLIntBuffersStorage.subarray(0,i+1)}var wasmImports={\"nd\":HaveOffsetConverter,\"md\":JsOnEmptyPacketListener,\"ld\":JsOnFloat32ArrayImageListener,\"kd\":JsOnFloat32ArrayImageVectorListener,\"Ma\":JsOnSimpleListenerBinaryArray,\"jd\":JsOnSimpleListenerBool,\"id\":JsOnSimpleListenerDouble,\"hd\":JsOnSimpleListenerFloat,\"gd\":JsOnSimpleListenerInt,\"fd\":JsOnSimpleListenerString,\"ed\":JsOnUint8ArrayImageListener,\"dd\":JsOnUint8ArrayImageVectorListener,\"K\":JsOnVectorFinishedListener,\"cd\":JsOnVectorListenerBool,\"bd\":JsOnVectorListenerDouble,\"ad\":JsOnVectorListenerFloat,\"$c\":JsOnVectorListenerInt,\"_c\":JsOnVectorListenerProto,\"Zc\":JsOnVectorListenerString,\"Yc\":JsOnWebGLTextureListener,\"Xc\":JsOnWebGLTextureVectorListener,\"G\":JsWrapErrorListener,\"La\":JsWrapImageConverter,\"r\":JsWrapSimpleListeners,\"i\":___cxa_throw,\"Ka\":___syscall_fcntl64,\"Wc\":___syscall_fstat64,\"Vc\":___syscall_ioctl,\"Uc\":___syscall_lstat64,\"Tc\":___syscall_newfstatat,\"Ja\":___syscall_openat,\"Sc\":___syscall_stat64,\"Oc\":__dlopen_js,\"Nc\":__dlsym_js,\"Tb\":__embind_register_bigint,\"Mc\":__embind_register_bool,\"Lc\":__embind_register_emval,\"Ga\":__embind_register_float,\"E\":__embind_register_integer,\"n\":__embind_register_memory_view,\"Fa\":__embind_register_std_string,\"ja\":__embind_register_std_wstring,\"Kc\":__embind_register_void,\"Jc\":__emscripten_get_now_is_monotonic,\"ia\":__emval_as,\"m\":__emval_decref,\"ha\":__emval_get_global,\"Ea\":__emval_get_property,\"Da\":__emval_incref,\"ga\":__emval_instanceof,\"ba\":__emval_new_cstring,\"fa\":__emval_run_destructors,\"Ca\":__emval_set_property,\"aa\":__emval_take_value,\"Ic\":__emval_typeof,\"Hc\":__gmtime_js,\"Gc\":__localtime_js,\"Fc\":__mktime_js,\"Ec\":__mmap_js,\"Dc\":__munmap_js,\"Cc\":__tzset_js,\"a\":_abort,\"Bc\":custom_emscripten_dbgn,\"D\":_emscripten_asm_const_int,\"Ac\":_emscripten_date_now,\"Ba\":_emscripten_err,\"zc\":_emscripten_errn,\"yc\":_emscripten_get_heap_max,\"u\":_emscripten_get_now,\"xc\":_emscripten_memcpy_big,\"wc\":_emscripten_outn,\"vc\":_emscripten_pc_get_function,\"uc\":_emscripten_resize_heap,\"tc\":_emscripten_stack_snapshot,\"sc\":_emscripten_stack_unwind_buffer,\"rc\":_emscripten_webgl_create_context,\"qc\":_emscripten_webgl_destroy_context,\"pc\":_emscripten_webgl_get_context_attributes,\"Aa\":_emscripten_webgl_get_current_context,\"oc\":_emscripten_webgl_init_context_attributes,\"nc\":_emscripten_webgl_make_context_current,\"mc\":_emscripten_webgpu_export_bind_group_layout,\"za\":_emscripten_webgpu_export_device,\"lc\":_emscripten_webgpu_export_sampler,\"kc\":_emscripten_webgpu_export_texture,\"J\":_emscripten_webgpu_get_device,\"jc\":_emscripten_webgpu_import_bind_group,\"ic\":_emscripten_webgpu_import_texture,\"U\":_emscripten_webgpu_release_js_handle,\"Rc\":_environ_get,\"Qc\":_environ_sizes_get,\"ya\":_exit,\"ka\":_fd_close,\"Ia\":_fd_read,\"Ub\":_fd_seek,\"Ha\":_fd_write,\"hc\":_getentropy,\"d\":_glActiveTexture,\"$\":_glAttachShader,\"gc\":_glBindAttribLocation,\"e\":_glBindBuffer,\"fc\":_glBindBufferBase,\"v\":_glBindFramebuffer,\"b\":_glBindTexture,\"t\":_glBindVertexArray,\"xa\":_glBlendEquation,\"ec\":_glBlendFunc,\"p\":_glBufferData,\"z\":_glClear,\"ea\":_glClearColor,\"Sb\":_glClientWaitSync,\"wa\":_glCompileShader,\"va\":_glCreateProgram,\"ua\":_glCreateShader,\"C\":_glDeleteBuffers,\"P\":_glDeleteFramebuffers,\"j\":_glDeleteProgram,\"T\":_glDeleteShader,\"S\":_glDeleteSync,\"y\":_glDeleteTextures,\"O\":_glDeleteVertexArrays,\"I\":_glDisable,\"s\":_glDisableVertexAttribArray,\"o\":_glDrawArrays,\"R\":_glDrawBuffers,\"dc\":_glEnable,\"l\":_glEnableVertexAttribArray,\"ta\":_glFenceSync,\"_\":_glFinish,\"H\":_glFlush,\"x\":_glFramebufferTexture2D,\"sa\":_glFramebufferTextureLayer,\"w\":_glGenBuffers,\"N\":_glGenFramebuffers,\"B\":_glGenTextures,\"M\":_glGenVertexArrays,\"ra\":_glGetAttribLocation,\"Z\":_glGetError,\"q\":_glGetIntegerv,\"cc\":_glGetProgramiv,\"bc\":_glGetShaderInfoLog,\"ac\":_glGetShaderiv,\"F\":_glGetString,\"$b\":_glGetUniformBlockIndex,\"g\":_glGetUniformLocation,\"qa\":_glLinkProgram,\"Y\":_glPixelStorei,\"da\":_glReadPixels,\"pa\":_glShaderSource,\"A\":_glTexImage2D,\"X\":_glTexParameterf,\"oa\":_glTexParameterfv,\"c\":_glTexParameteri,\"ca\":_glTexStorage2D,\"_b\":_glTexStorage3D,\"Q\":_glTexSubImage2D,\"Zb\":_glTexSubImage3D,\"W\":_glUniform1f,\"f\":_glUniform1i,\"Yb\":_glUniform2f,\"Xb\":_glUniform2fv,\"na\":_glUniform3f,\"ma\":_glUniform4fv,\"Wb\":_glUniform4iv,\"Vb\":_glUniformBlockBinding,\"la\":_glUniformMatrix4fv,\"h\":_glUseProgram,\"k\":_glVertexAttribPointer,\"L\":_glViewport,\"Qb\":mediapipe_create_utility_canvas2d,\"Pb\":_mediapipe_find_canvas_event_target,\"Ob\":mediapipe_import_external_texture,\"Nb\":_mediapipe_webgl_tex_image_drawable,\"Pc\":_proc_exit,\"V\":_strftime,\"Mb\":_strftime_l,\"Lb\":_wgpuBindGroupLayoutRelease,\"Kb\":_wgpuBindGroupRelease,\"Jb\":_wgpuBufferGetMappedRange,\"Ib\":_wgpuBufferReference,\"Hb\":_wgpuBufferRelease,\"Gb\":_wgpuBufferUnmap,\"Fb\":_wgpuCommandBufferRelease,\"Eb\":_wgpuCommandEncoderBeginComputePass,\"Db\":_wgpuCommandEncoderBeginRenderPass,\"Cb\":_wgpuCommandEncoderCopyBufferToTexture,\"Bb\":_wgpuCommandEncoderCopyTextureToTexture,\"Ab\":_wgpuCommandEncoderFinish,\"zb\":_wgpuCommandEncoderRelease,\"yb\":_wgpuComputePassEncoderDispatchWorkgroups,\"xb\":_wgpuComputePassEncoderEnd,\"wb\":_wgpuComputePassEncoderRelease,\"vb\":_wgpuComputePassEncoderSetBindGroup,\"ub\":_wgpuComputePassEncoderSetPipeline,\"tb\":_wgpuComputePipelineGetBindGroupLayout,\"sb\":_wgpuComputePipelineRelease,\"rb\":_wgpuDeviceCreateBindGroup,\"qb\":_wgpuDeviceCreateBuffer,\"pb\":_wgpuDeviceCreateCommandEncoder,\"ob\":_wgpuDeviceCreateComputePipeline,\"nb\":_wgpuDeviceCreateRenderPipeline,\"mb\":_wgpuDeviceCreateSampler,\"lb\":_wgpuDeviceCreateShaderModule,\"kb\":_wgpuDeviceCreateTexture,\"jb\":_wgpuDeviceGetQueue,\"ib\":_wgpuDeviceReference,\"hb\":_wgpuDeviceRelease,\"gb\":_wgpuPipelineLayoutRelease,\"fb\":_wgpuQuerySetRelease,\"eb\":_wgpuQueueRelease,\"db\":_wgpuQueueSubmit,\"Rb\":_wgpuQueueWriteBuffer,\"cb\":_wgpuRenderPassEncoderDraw,\"bb\":_wgpuRenderPassEncoderEnd,\"ab\":_wgpuRenderPassEncoderRelease,\"$a\":_wgpuRenderPassEncoderSetBindGroup,\"_a\":_wgpuRenderPassEncoderSetPipeline,\"Za\":_wgpuRenderPipelineGetBindGroupLayout,\"Ya\":_wgpuRenderPipelineRelease,\"Xa\":_wgpuSamplerReference,\"Wa\":_wgpuSamplerRelease,\"Va\":_wgpuShaderModuleReference,\"Ua\":_wgpuShaderModuleRelease,\"Ta\":_wgpuTextureCreateView,\"Sa\":_wgpuTextureDestroy,\"Ra\":_wgpuTextureReference,\"Qa\":_wgpuTextureRelease,\"Pa\":_wgpuTextureViewReference,\"Oa\":_wgpuTextureViewRelease,\"Na\":xnnLoadWasmModuleJS};var asm=createWasm();var ___wasm_call_ctors=function(){return(___wasm_call_ctors=Module[\"asm\"][\"pd\"]).apply(null,arguments)};var _free=Module[\"_free\"]=function(){return(_free=Module[\"_free\"]=Module[\"asm\"][\"rd\"]).apply(null,arguments)};var _malloc=Module[\"_malloc\"]=function(){return(_malloc=Module[\"_malloc\"]=Module[\"asm\"][\"sd\"]).apply(null,arguments)};var _addBoundTextureAsImageToStream=Module[\"_addBoundTextureAsImageToStream\"]=function(){return(_addBoundTextureAsImageToStream=Module[\"_addBoundTextureAsImageToStream\"]=Module[\"asm\"][\"td\"]).apply(null,arguments)};var _attachImageListener=Module[\"_attachImageListener\"]=function(){return(_attachImageListener=Module[\"_attachImageListener\"]=Module[\"asm\"][\"ud\"]).apply(null,arguments)};var _attachImageVectorListener=Module[\"_attachImageVectorListener\"]=function(){return(_attachImageVectorListener=Module[\"_attachImageVectorListener\"]=Module[\"asm\"][\"vd\"]).apply(null,arguments)};var _registerModelResourcesGraphService=Module[\"_registerModelResourcesGraphService\"]=function(){return(_registerModelResourcesGraphService=Module[\"_registerModelResourcesGraphService\"]=Module[\"asm\"][\"wd\"]).apply(null,arguments)};var ___errno_location=function(){return(___errno_location=Module[\"asm\"][\"xd\"]).apply(null,arguments)};var _bindTextureToStream=Module[\"_bindTextureToStream\"]=function(){return(_bindTextureToStream=Module[\"_bindTextureToStream\"]=Module[\"asm\"][\"yd\"]).apply(null,arguments)};var _addBoundTextureToStream=Module[\"_addBoundTextureToStream\"]=function(){return(_addBoundTextureToStream=Module[\"_addBoundTextureToStream\"]=Module[\"asm\"][\"zd\"]).apply(null,arguments)};var _addDoubleToInputStream=Module[\"_addDoubleToInputStream\"]=function(){return(_addDoubleToInputStream=Module[\"_addDoubleToInputStream\"]=Module[\"asm\"][\"Ad\"]).apply(null,arguments)};var _addFloatToInputStream=Module[\"_addFloatToInputStream\"]=function(){return(_addFloatToInputStream=Module[\"_addFloatToInputStream\"]=Module[\"asm\"][\"Bd\"]).apply(null,arguments)};var _addBoolToInputStream=Module[\"_addBoolToInputStream\"]=function(){return(_addBoolToInputStream=Module[\"_addBoolToInputStream\"]=Module[\"asm\"][\"Cd\"]).apply(null,arguments)};var _addIntToInputStream=Module[\"_addIntToInputStream\"]=function(){return(_addIntToInputStream=Module[\"_addIntToInputStream\"]=Module[\"asm\"][\"Dd\"]).apply(null,arguments)};var _addStringToInputStream=Module[\"_addStringToInputStream\"]=function(){return(_addStringToInputStream=Module[\"_addStringToInputStream\"]=Module[\"asm\"][\"Ed\"]).apply(null,arguments)};var _addFlatHashMapToInputStream=Module[\"_addFlatHashMapToInputStream\"]=function(){return(_addFlatHashMapToInputStream=Module[\"_addFlatHashMapToInputStream\"]=Module[\"asm\"][\"Fd\"]).apply(null,arguments)};var _addProtoToInputStream=Module[\"_addProtoToInputStream\"]=function(){return(_addProtoToInputStream=Module[\"_addProtoToInputStream\"]=Module[\"asm\"][\"Gd\"]).apply(null,arguments)};var _addEmptyPacketToInputStream=Module[\"_addEmptyPacketToInputStream\"]=function(){return(_addEmptyPacketToInputStream=Module[\"_addEmptyPacketToInputStream\"]=Module[\"asm\"][\"Hd\"]).apply(null,arguments)};var _addBoolToInputSidePacket=Module[\"_addBoolToInputSidePacket\"]=function(){return(_addBoolToInputSidePacket=Module[\"_addBoolToInputSidePacket\"]=Module[\"asm\"][\"Id\"]).apply(null,arguments)};var _addDoubleToInputSidePacket=Module[\"_addDoubleToInputSidePacket\"]=function(){return(_addDoubleToInputSidePacket=Module[\"_addDoubleToInputSidePacket\"]=Module[\"asm\"][\"Jd\"]).apply(null,arguments)};var _addFloatToInputSidePacket=Module[\"_addFloatToInputSidePacket\"]=function(){return(_addFloatToInputSidePacket=Module[\"_addFloatToInputSidePacket\"]=Module[\"asm\"][\"Kd\"]).apply(null,arguments)};var _addIntToInputSidePacket=Module[\"_addIntToInputSidePacket\"]=function(){return(_addIntToInputSidePacket=Module[\"_addIntToInputSidePacket\"]=Module[\"asm\"][\"Ld\"]).apply(null,arguments)};var _addStringToInputSidePacket=Module[\"_addStringToInputSidePacket\"]=function(){return(_addStringToInputSidePacket=Module[\"_addStringToInputSidePacket\"]=Module[\"asm\"][\"Md\"]).apply(null,arguments)};var _addProtoToInputSidePacket=Module[\"_addProtoToInputSidePacket\"]=function(){return(_addProtoToInputSidePacket=Module[\"_addProtoToInputSidePacket\"]=Module[\"asm\"][\"Nd\"]).apply(null,arguments)};var _attachBoolListener=Module[\"_attachBoolListener\"]=function(){return(_attachBoolListener=Module[\"_attachBoolListener\"]=Module[\"asm\"][\"Od\"]).apply(null,arguments)};var _attachBoolVectorListener=Module[\"_attachBoolVectorListener\"]=function(){return(_attachBoolVectorListener=Module[\"_attachBoolVectorListener\"]=Module[\"asm\"][\"Pd\"]).apply(null,arguments)};var _attachDoubleListener=Module[\"_attachDoubleListener\"]=function(){return(_attachDoubleListener=Module[\"_attachDoubleListener\"]=Module[\"asm\"][\"Qd\"]).apply(null,arguments)};var _attachDoubleVectorListener=Module[\"_attachDoubleVectorListener\"]=function(){return(_attachDoubleVectorListener=Module[\"_attachDoubleVectorListener\"]=Module[\"asm\"][\"Rd\"]).apply(null,arguments)};var _attachFloatListener=Module[\"_attachFloatListener\"]=function(){return(_attachFloatListener=Module[\"_attachFloatListener\"]=Module[\"asm\"][\"Sd\"]).apply(null,arguments)};var _attachFloatVectorListener=Module[\"_attachFloatVectorListener\"]=function(){return(_attachFloatVectorListener=Module[\"_attachFloatVectorListener\"]=Module[\"asm\"][\"Td\"]).apply(null,arguments)};var _attachIntListener=Module[\"_attachIntListener\"]=function(){return(_attachIntListener=Module[\"_attachIntListener\"]=Module[\"asm\"][\"Ud\"]).apply(null,arguments)};var _attachIntVectorListener=Module[\"_attachIntVectorListener\"]=function(){return(_attachIntVectorListener=Module[\"_attachIntVectorListener\"]=Module[\"asm\"][\"Vd\"]).apply(null,arguments)};var _attachStringListener=Module[\"_attachStringListener\"]=function(){return(_attachStringListener=Module[\"_attachStringListener\"]=Module[\"asm\"][\"Wd\"]).apply(null,arguments)};var _attachStringVectorListener=Module[\"_attachStringVectorListener\"]=function(){return(_attachStringVectorListener=Module[\"_attachStringVectorListener\"]=Module[\"asm\"][\"Xd\"]).apply(null,arguments)};var _attachProtoListener=Module[\"_attachProtoListener\"]=function(){return(_attachProtoListener=Module[\"_attachProtoListener\"]=Module[\"asm\"][\"Yd\"]).apply(null,arguments)};var _attachProtoVectorListener=Module[\"_attachProtoVectorListener\"]=function(){return(_attachProtoVectorListener=Module[\"_attachProtoVectorListener\"]=Module[\"asm\"][\"Zd\"]).apply(null,arguments)};var _getGraphConfig=Module[\"_getGraphConfig\"]=function(){return(_getGraphConfig=Module[\"_getGraphConfig\"]=Module[\"asm\"][\"_d\"]).apply(null,arguments)};var _clearSubgraphs=Module[\"_clearSubgraphs\"]=function(){return(_clearSubgraphs=Module[\"_clearSubgraphs\"]=Module[\"asm\"][\"$d\"]).apply(null,arguments)};var _pushBinarySubgraph=Module[\"_pushBinarySubgraph\"]=function(){return(_pushBinarySubgraph=Module[\"_pushBinarySubgraph\"]=Module[\"asm\"][\"ae\"]).apply(null,arguments)};var _pushTextSubgraph=Module[\"_pushTextSubgraph\"]=function(){return(_pushTextSubgraph=Module[\"_pushTextSubgraph\"]=Module[\"asm\"][\"be\"]).apply(null,arguments)};var _changeBinaryGraph=Module[\"_changeBinaryGraph\"]=function(){return(_changeBinaryGraph=Module[\"_changeBinaryGraph\"]=Module[\"asm\"][\"ce\"]).apply(null,arguments)};var _changeTextGraph=Module[\"_changeTextGraph\"]=function(){return(_changeTextGraph=Module[\"_changeTextGraph\"]=Module[\"asm\"][\"de\"]).apply(null,arguments)};var _processGl=Module[\"_processGl\"]=function(){return(_processGl=Module[\"_processGl\"]=Module[\"asm\"][\"ee\"]).apply(null,arguments)};var _process=Module[\"_process\"]=function(){return(_process=Module[\"_process\"]=Module[\"asm\"][\"fe\"]).apply(null,arguments)};var _bindTextureToCanvas=Module[\"_bindTextureToCanvas\"]=function(){return(_bindTextureToCanvas=Module[\"_bindTextureToCanvas\"]=Module[\"asm\"][\"ge\"]).apply(null,arguments)};var _requestShaderRefreshOnGraphChange=Module[\"_requestShaderRefreshOnGraphChange\"]=function(){return(_requestShaderRefreshOnGraphChange=Module[\"_requestShaderRefreshOnGraphChange\"]=Module[\"asm\"][\"he\"]).apply(null,arguments)};var _waitUntilIdle=Module[\"_waitUntilIdle\"]=function(){return(_waitUntilIdle=Module[\"_waitUntilIdle\"]=Module[\"asm\"][\"ie\"]).apply(null,arguments)};var _closeGraph=Module[\"_closeGraph\"]=function(){return(_closeGraph=Module[\"_closeGraph\"]=Module[\"asm\"][\"je\"]).apply(null,arguments)};var _setAutoRenderToScreen=Module[\"_setAutoRenderToScreen\"]=function(){return(_setAutoRenderToScreen=Module[\"_setAutoRenderToScreen\"]=Module[\"asm\"][\"ke\"]).apply(null,arguments)};var ___getTypeName=function(){return(___getTypeName=Module[\"asm\"][\"le\"]).apply(null,arguments)};var __embind_initialize_bindings=Module[\"__embind_initialize_bindings\"]=function(){return(__embind_initialize_bindings=Module[\"__embind_initialize_bindings\"]=Module[\"asm\"][\"me\"]).apply(null,arguments)};var _emscripten_builtin_memalign=function(){return(_emscripten_builtin_memalign=Module[\"asm\"][\"ne\"]).apply(null,arguments)};var _memalign=function(){return(_memalign=Module[\"asm\"][\"oe\"]).apply(null,arguments)};var stackSave=function(){return(stackSave=Module[\"asm\"][\"pe\"]).apply(null,arguments)};var stackRestore=function(){return(stackRestore=Module[\"asm\"][\"qe\"]).apply(null,arguments)};var stackAlloc=function(){return(stackAlloc=Module[\"asm\"][\"re\"]).apply(null,arguments)};var ___cxa_is_pointer_type=function(){return(___cxa_is_pointer_type=Module[\"asm\"][\"se\"]).apply(null,arguments)};var ___start_em_js=Module[\"___start_em_js\"]=1180644;var ___stop_em_js=Module[\"___stop_em_js\"]=1188066;Module[\"addRunDependency\"]=addRunDependency;Module[\"removeRunDependency\"]=removeRunDependency;Module[\"FS_createPath\"]=FS.createPath;Module[\"FS_createDataFile\"]=FS.createDataFile;Module[\"FS_createLazyFile\"]=FS.createLazyFile;Module[\"FS_createDevice\"]=FS.createDevice;Module[\"FS_unlink\"]=FS.unlink;Module[\"ccall\"]=ccall;Module[\"stringToNewUTF8\"]=stringToNewUTF8;Module[\"FS_createPreloadedFile\"]=FS.createPreloadedFile;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module[\"calledRun\"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module[\"onRuntimeInitialized\"])Module[\"onRuntimeInitialized\"]();postRun()}if(Module[\"setStatus\"]){Module[\"setStatus\"](\"Running...\");setTimeout(function(){setTimeout(function(){Module[\"setStatus\"](\"\")},1);doRun()},1)}else{doRun()}}if(Module[\"preInit\"]){if(typeof Module[\"preInit\"]==\"function\")Module[\"preInit\"]=[Module[\"preInit\"]];while(Module[\"preInit\"].length>0){Module[\"preInit\"].pop()()}}run();\n\n\n  return ModuleFactory.ready\n}\n\n);\n})();\nif (typeof exports === 'object' && typeof module === 'object')\n  module.exports = ModuleFactory;\nelse if (typeof define === 'function' && define['amd'])\n  define([], function() { return ModuleFactory; });\nelse if (typeof exports === 'object')\n  exports[\"ModuleFactory\"] = ModuleFactory;\n"
  },
  {
    "path": "extern/wasm/vision_wasm_nosimd_internal.js",
    "content": "// Build 551939664\n\nvar ModuleFactory = (() => {\n  var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;\n  if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;\n  return (\nfunction(ModuleFactory = {})  {\n\nvar Module=typeof ModuleFactory!=\"undefined\"?ModuleFactory:{};var readyPromiseResolve,readyPromiseReject;Module[\"ready\"]=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram=\"./this.program\";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window==\"object\";var ENVIRONMENT_IS_WORKER=typeof importScripts==\"function\";var ENVIRONMENT_IS_NODE=typeof process==\"object\"&&typeof process.versions==\"object\"&&typeof process.versions.node==\"string\";var scriptDirectory=\"\";function locateFile(path){if(Module[\"locateFile\"]){return Module[\"locateFile\"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){var fs=require(\"fs\");var nodePath=require(\"path\");if(ENVIRONMENT_IS_WORKER){scriptDirectory=nodePath.dirname(scriptDirectory)+\"/\"}else{scriptDirectory=__dirname+\"/\"}read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:\"utf8\")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:\"utf8\",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module[\"thisProgram\"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\\\/g,\"/\")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};Module[\"inspect\"]=()=>\"[Emscripten Module object]\"}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=\"undefined\"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf(\"blob:\")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,\"\").lastIndexOf(\"/\")+1)}else{scriptDirectory=\"\"}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);xhr.responseType=\"arraybuffer\";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,true);xhr.responseType=\"arraybuffer\";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module[\"print\"]||console.log.bind(console);var err=Module[\"printErr\"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module[\"arguments\"])arguments_=Module[\"arguments\"];if(Module[\"thisProgram\"])thisProgram=Module[\"thisProgram\"];if(Module[\"quit\"])quit_=Module[\"quit\"];var wasmBinary;if(Module[\"wasmBinary\"])wasmBinary=Module[\"wasmBinary\"];var noExitRuntime=Module[\"noExitRuntime\"]||true;if(typeof WebAssembly!=\"object\"){abort(\"no native wasm support detected\")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module[\"HEAP8\"]=HEAP8=new Int8Array(b);Module[\"HEAP16\"]=HEAP16=new Int16Array(b);Module[\"HEAP32\"]=HEAP32=new Int32Array(b);Module[\"HEAPU8\"]=HEAPU8=new Uint8Array(b);Module[\"HEAPU16\"]=HEAPU16=new Uint16Array(b);Module[\"HEAPU32\"]=HEAPU32=new Uint32Array(b);Module[\"HEAPF32\"]=HEAPF32=new Float32Array(b);Module[\"HEAPF64\"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}function preRun(){if(Module[\"preRun\"]){if(typeof Module[\"preRun\"]==\"function\")Module[\"preRun\"]=[Module[\"preRun\"]];while(Module[\"preRun\"].length){addOnPreRun(Module[\"preRun\"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module[\"noFSInit\"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module[\"postRun\"]){if(typeof Module[\"postRun\"]==\"function\")Module[\"postRun\"]=[Module[\"postRun\"]];while(Module[\"postRun\"].length){addOnPostRun(Module[\"postRun\"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module[\"monitorRunDependencies\"]){Module[\"monitorRunDependencies\"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module[\"monitorRunDependencies\"]){Module[\"monitorRunDependencies\"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module[\"onAbort\"]){Module[\"onAbort\"](what)}what=\"Aborted(\"+what+\")\";err(what);ABORT=true;EXITSTATUS=1;what+=\". Build with -sASSERTIONS for more info.\";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix=\"data:application/octet-stream;base64,\";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith(\"file://\")}var wasmBinaryFile;wasmBinaryFile=\"vision_wasm_nosimd_internal.wasm\";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw\"both async and sync fetching of the wasm failed\"}catch(err){abort(err)}}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch==\"function\"&&!isFileURI(binaryFile)){return fetch(binaryFile,{credentials:\"same-origin\"}).then(response=>{if(!response[\"ok\"]){throw\"failed to load wasm binary file at '\"+binaryFile+\"'\"}return response[\"arrayBuffer\"]()}).catch(()=>getBinary(binaryFile))}else{if(readAsync){return new Promise((resolve,reject)=>{readAsync(binaryFile,response=>resolve(new Uint8Array(response)),reject)})}}}return Promise.resolve().then(()=>getBinary(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>{return WebAssembly.instantiate(binary,imports)}).then(instance=>{return instance}).then(receiver,reason=>{err(\"failed to asynchronously prepare wasm: \"+reason);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming==\"function\"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch==\"function\"){return fetch(binaryFile,{credentials:\"same-origin\"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(\"wasm streaming compile failed: \"+reason);err(\"falling back to ArrayBuffer instantiation\");return instantiateArrayBuffer(binaryFile,imports,callback)})})}else{return instantiateArrayBuffer(binaryFile,imports,callback)}}function createWasm(){var info={\"a\":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module[\"asm\"]=exports;wasmMemory=Module[\"asm\"][\"od\"];updateMemoryViews();wasmTable=Module[\"asm\"][\"qd\"];addOnInit(Module[\"asm\"][\"pd\"]);removeRunDependency(\"wasm-instantiate\");return exports}addRunDependency(\"wasm-instantiate\");function receiveInstantiationResult(result){receiveInstance(result[\"instance\"])}if(Module[\"instantiateWasm\"]){try{return Module[\"instantiateWasm\"](info,receiveInstance)}catch(e){err(\"Module.instantiateWasm callback failed with error: \"+e);readyPromiseReject(e)}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var tempDouble;var tempI64;var ASM_CONSTS={1188450:$0=>{const canvas=Emval.toValue($0);const context=canvas.getContext(\"webgpu\");return JsValStore.add(context.getCurrentTexture())},1188585:($0,$1,$2,$3,$4)=>{const drawable=Emval.toValue($0);const device=JsValStore.get($1);const texture=JsValStore.get($2);const width=$3;const height=$4;device.queue.copyExternalImageToTexture({source:drawable},{texture:texture},[width,height])},1188836:($0,$1,$2,$3)=>{const sourceExtTex=Emval.toValue($0);const device=JsValStore.get($1);const sampler=JsValStore.get($2);const bgLayout=JsValStore.get($3);const bindGroup=device.createBindGroup({layout:bgLayout,entries:[{binding:0,resource:sampler},{binding:1,resource:sourceExtTex}]});return JsValStore.add(bindGroup)},1189184:($0,$1)=>{const inputArray=Emval.toValue($0);const output=Emval.toValue($1);const ctx=output.getContext(\"2d\");const image_data=new ImageData(inputArray,output.width,output.height);ctx.putImageData(image_data,0,0)},1189408:($0,$1)=>{const input=Emval.toValue($0);const outputArray=Emval.toValue($1);const ctx=input.getContext(\"2d\");const data=ctx.getImageData(0,0,input.width,input.height);outputArray.set(data.data)},1189612:($0,$1)=>{const input=Emval.toValue($0);const output=Emval.toValue($1);const ctx=output.getContext(\"2d\");ctx.drawImage(input,0,0)},1189748:()=>{return typeof HTMLCanvasElement!==\"undefined\"},1189803:()=>{return!!Module[\"preinitializedWebGPUDevice\"]},1189854:()=>{specialHTMLTargets[\"#canvas\"]=Module.canvas},1189905:()=>{return typeof wasmOffsetConverter!==\"undefined\"}};function JsWrapImageConverter(){if(!Module._imageConverter){Module._imageConverter=(binaryPtr,binarySize,width,height,numChannels,makeDeepCopy,outputType)=>{const imageData=new outputType(makeDeepCopy?Module.HEAPU8.slice(binaryPtr,binaryPtr+binarySize).buffer:Module.HEAPU8.buffer,binaryPtr,width*height*numChannels);return{data:imageData,width:width,height:height}}}}function JsOnUint8ArrayImageListener(output_stream_name,binary_ptr,binary_size,width,height,num_channels,make_deep_copy,timestamp_ms){const image=Module._imageConverter(binary_ptr,binary_size,width,height,num_channels,make_deep_copy,Uint8Array);Module._wrapSimpleListenerOutput(output_stream_name,image,timestamp_ms)}function JsOnFloat32ArrayImageListener(output_stream_name,binary_ptr,binary_size,width,height,num_channels,make_deep_copy,timestamp_ms){const image=Module._imageConverter(binary_ptr,binary_size,width,height,num_channels,make_deep_copy,Float32Array);Module._wrapSimpleListenerOutput(output_stream_name,image,timestamp_ms)}function JsOnWebGLTextureListener(output_stream_name,name,width,height,timestamp_ms){Module._wrapSimpleListenerOutput(output_stream_name,{data:GL.textures[name],width:width,height:height},timestamp_ms)}function JsOnUint8ArrayImageVectorListener(output_stream_name,binary_ptr,binary_size,width,height,num_channels,make_deep_copy,timestamp_ms){const image=Module._imageConverter(binary_ptr,binary_size,width,height,num_channels,make_deep_copy,Uint8Array);Module._wrapSimpleListenerOutput(output_stream_name,image,false,timestamp_ms)}function JsOnFloat32ArrayImageVectorListener(output_stream_name,binary_ptr,binary_size,width,height,num_channels,make_deep_copy,timestamp_ms){const image=Module._imageConverter(binary_ptr,binary_size,width,height,num_channels,make_deep_copy,Float32Array);Module._wrapSimpleListenerOutput(output_stream_name,image,false,timestamp_ms)}function JsOnWebGLTextureVectorListener(output_stream_name,name,width,height,timestamp_ms){Module._wrapSimpleListenerOutput(output_stream_name,{data:GL.textures[name],width:width,height:height},false,timestamp_ms)}function JsOnEmptyPacketListener(output_stream_name,timestamp){Module._wrapEmptyPacketListenerOutput(output_stream_name,timestamp)}function JsOnVectorFinishedListener(output_stream_name,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,undefined,true,timestamp)}function JsOnSimpleListenerBool(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,timestamp)}function JsOnVectorListenerBool(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,false,timestamp)}function JsOnSimpleListenerInt(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,timestamp)}function JsOnVectorListenerInt(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,false,timestamp)}function JsOnSimpleListenerDouble(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,timestamp)}function JsOnVectorListenerDouble(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,false,timestamp)}function JsOnSimpleListenerFloat(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,timestamp)}function JsOnVectorListenerFloat(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,out_data,false,timestamp)}function JsOnSimpleListenerString(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,UTF8ToString(out_data),timestamp)}function JsOnVectorListenerString(output_stream_name,out_data,timestamp){Module._wrapSimpleListenerOutput(output_stream_name,UTF8ToString(out_data),false,timestamp)}function JsOnVectorListenerProto(output_stream_name,proto_ptr,proto_size,make_deep_copy,timestamp){const newProtoArray=make_deep_copy?Module.HEAPU8.slice(proto_ptr,proto_ptr+proto_size):new Uint8Array(Module.HEAPU8.buffer,proto_ptr,proto_size);Module._wrapSimpleListenerOutput(output_stream_name,newProtoArray,false,timestamp)}function JsWrapSimpleListeners(){if(!Module._wrapSimpleListenerOutput){Module._wrapSimpleListenerOutput=(outputStreamName,...args)=>{if(Module.simpleListeners){const streamName=UTF8ToString(outputStreamName);if(Module.simpleListeners[streamName]){Module.simpleListeners[streamName](...args)}}}}if(!Module._wrapEmptyPacketListenerOutput){Module._wrapEmptyPacketListenerOutput=(outputStreamName,timestamp)=>{if(Module.emptyPacketListeners){const streamName=UTF8ToString(outputStreamName);if(Module.emptyPacketListeners[streamName]){Module.emptyPacketListeners[streamName](timestamp)}}}}}function JsOnSimpleListenerBinaryArray(output_stream_name,binary_ptr,binary_size,make_deep_copy,timestamp){const newProtoArray=make_deep_copy?Module.HEAPU8.slice(binary_ptr,binary_ptr+binary_size):new Uint8Array(Module.HEAPU8.buffer,binary_ptr,binary_size);Module._wrapSimpleListenerOutput(output_stream_name,newProtoArray,timestamp)}function mediapipe_import_external_texture(device_handle,source_handle){const device=WebGPU.mgrDevice.get(device_handle);const source=Emval.toValue(source_handle);const externalTexture=device.importExternalTexture({source:source});return Emval.toHandle(externalTexture)}function mediapipe_create_utility_canvas2d(){let canvas;if(typeof OffscreenCanvas!==\"undefined\"){canvas=new OffscreenCanvas(0,0)}else{canvas=document.createElement(\"canvas\");canvas.style.display=\"none\";canvas.id=\"canvas_2d\";document.body.appendChild(canvas)}return Emval.toHandle(canvas)}function xnnLoadWasmModuleJS(code,offset,offset_end,invalid_function_index){const tableOriginalSize=wasmTable.length;const binary=new Uint8Array(HEAPU8.slice(code+offset,code+offset_end));try{var module=new WebAssembly.Module(binary);var instance=new WebAssembly.Instance(module,{env:{memory:wasmMemory}});for(var symName in instance.exports){var value=instance.exports[symName];addFunction(value)}if(tableOriginalSize<wasmTable.length){return tableOriginalSize}return invalid_function_index}catch(error){console.log(error);return invalid_function_index}}function JsWrapErrorListener(code,message){if(Module.errorListener){const stringMessage=UTF8ToString(message);Module.errorListener(code,stringMessage)}}function custom_emscripten_dbgn(str,len){if(typeof dbg!==\"undefined\"){dbg(UTF8ToString(str,len))}else{if(typeof custom_dbg===\"undefined\"){function custom_dbg(text){console.warn.apply(console,arguments)}}custom_dbg(UTF8ToString(str,len))}}function HaveOffsetConverter(){return typeof wasmOffsetConverter!==\"undefined\"}function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(!Browser.mainLoop.running){Browser.mainLoop.running=true}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method=\"timeout\"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method=\"rAF\"}else if(mode==2){if(typeof setImmediate==\"undefined\"){var setImmediates=[];var emscriptenMainLoopMessageId=\"setimmediate\";var Browser_setImmediate_messageHandler=event=>{if(event.data===emscriptenMainLoopMessageId||event.data.target===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}};addEventListener(\"message\",Browser_setImmediate_messageHandler,true);setImmediate=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module[\"setImmediates\"]===undefined)Module[\"setImmediates\"]=[];Module[\"setImmediates\"].push(func);postMessage({target:emscriptenMainLoopMessageId})}else postMessage(emscriptenMainLoopMessageId,\"*\")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){setImmediate(Browser.mainLoop.runner)};Browser.mainLoop.method=\"immediate\"}return 0}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){global.performance=require(\"perf_hooks\").performance}_emscripten_get_now=()=>performance.now();function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,noSetTiming){assert(!Browser.mainLoop.func,\"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.\");Browser.mainLoop.func=browserIterationFunc;Browser.mainLoop.arg=arg;var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;function checkIsRunning(){if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop){return false}return true}Browser.mainLoop.running=false;Browser.mainLoop.runner=function Browser_mainLoop_runner(){if(ABORT)return;if(Browser.mainLoop.queue.length>0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}out('main loop blocker \"'+blocker.name+'\" took '+(Date.now()-start)+\" ms\");Browser.mainLoop.updateStatus();if(!checkIsRunning())return;setTimeout(Browser.mainLoop.runner,0);return}if(!checkIsRunning())return;Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0;if(Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}GL.newRenderingFrameStarted();Browser.mainLoop.runIter(browserIterationFunc);if(!checkIsRunning())return;if(typeof SDL==\"object\"&&SDL.audio&&SDL.audio.queueNewAudioData)SDL.audio.queueNewAudioData();Browser.mainLoop.scheduler()};if(!noSetTiming){if(fps&&fps>0){_emscripten_set_main_loop_timing(0,1e3/fps)}else{_emscripten_set_main_loop_timing(1,1)}Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw\"unwind\"}}function handleException(e){if(e instanceof ExitStatus||e==\"unwind\"){return EXITSTATUS}quit_(1,e)}function ExitStatus(status){this.name=\"ExitStatus\";this.message=`Program terminated with exit(${status})`;this.status=status}var PATH={isAbs:path=>path.charAt(0)===\"/\",splitPath:filename=>{var splitPathRe=/^(\\/?|)([\\s\\S]*?)((?:\\.{1,2}|[^\\/]+?|)(\\.[^.\\/]*|))(?:[\\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last===\".\"){parts.splice(i,1)}else if(last===\"..\"){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift(\"..\")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)===\"/\";path=PATH.normalizeArray(path.split(\"/\").filter(p=>!!p),!isAbsolute).join(\"/\");if(!path&&!isAbsolute){path=\".\"}if(path&&trailingSlash){path+=\"/\"}return(isAbsolute?\"/\":\"\")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return\".\"}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path===\"/\")return\"/\";path=PATH.normalize(path);path=path.replace(/\\/$/,\"\");var lastSlash=path.lastIndexOf(\"/\");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join(\"/\"))},join2:(l,r)=>{return PATH.normalize(l+\"/\"+r)}};function initRandomFill(){if(typeof crypto==\"object\"&&typeof crypto[\"getRandomValues\"]==\"function\"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require(\"crypto\");var randomFillSync=crypto_module[\"randomFillSync\"];if(randomFillSync){return view=>crypto_module[\"randomFillSync\"](view)}var randomBytes=crypto_module[\"randomBytes\"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort(\"initRandomDevice\")}function randomFill(view){return(randomFill=initRandomFill())(view)}var PATH_FS={resolve:function(){var resolvedPath=\"\",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=\"string\"){throw new TypeError(\"Arguments to path.resolve must be strings\")}else if(!path){return\"\"}resolvedPath=path+\"/\"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split(\"/\").filter(p=>!!p),!resolvedAbsolute).join(\"/\");return(resolvedAbsolute?\"/\":\"\")+resolvedPath||\".\"},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!==\"\")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!==\"\")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split(\"/\"));var toParts=trim(to.split(\"/\"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push(\"..\")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join(\"/\")}};function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var UTF8Decoder=typeof TextDecoder!=\"undefined\"?new TextDecoder(\"utf8\"):undefined;function UTF8ArrayToString(heapOrArray,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str=\"\";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str}var TTY={ttys:[],init:function(){},shutdown:function(){},register:function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open:function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close:function(stream){stream.tty.ops.fsync(stream.tty)},fsync:function(stream){stream.tty.ops.fsync(stream.tty)},read:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(60)}try{for(var i=0;i<length;i++){stream.tty.ops.put_char(stream.tty,buffer[offset+i])}}catch(e){throw new FS.ErrnoError(29)}if(length){stream.node.timestamp=Date.now()}return i}},default_tty_ops:{get_char:function(tty){if(!tty.input.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc(BUFSIZE);var bytesRead=0;try{bytesRead=fs.readSync(process.stdin.fd,buf,0,BUFSIZE,-1)}catch(e){if(e.toString().includes(\"EOF\"))bytesRead=0;else throw e}if(bytesRead>0){result=buf.slice(0,bytesRead).toString(\"utf-8\")}else{result=null}}else if(typeof window!=\"undefined\"&&typeof window.prompt==\"function\"){result=window.prompt(\"Input: \");if(result!==null){result+=\"\\n\"}}else if(typeof readline==\"function\"){result=readline();if(result!==null){result+=\"\\n\"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};function zeroMemory(address,size){HEAPU8.fill(0,address,address+size);return address}function alignMemory(size,alignment){return Math.ceil(size/alignment)*alignment}function mmapAlloc(size){size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(!ptr)return 0;return zeroMemory(ptr,size)}var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,\"/\",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray:function(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage:function(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)>>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr:function(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr:function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup:function(parent,name){throw FS.genericErrors[44]},mknod:function(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename:function(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink:function(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir:function(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir:function(node){var entries=[\".\",\"..\"];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink:function(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink:function(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read:function(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size},write:function(stream,buffer,offset,length,position,canOwn){if(buffer.buffer===HEAP8.buffer){canOwn=false}if(!length)return 0;var node=stream.node;node.timestamp=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=buffer.slice(offset,offset+length);node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray){node.contents.set(buffer.subarray(offset,offset+length),position)}else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length},llseek:function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(28)}return position},allocate:function(stream,offset,length){MEMFS.expandFileStorage(stream.node,offset+length);stream.node.usedBytes=Math.max(stream.node.usedBytes,offset+length)},mmap:function(stream,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&contents.buffer===HEAP8.buffer){allocated=false;ptr=contents.byteOffset}else{if(position>0||position+length<contents.length){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}allocated=true;ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}HEAP8.set(contents,ptr)}return{ptr:ptr,allocated:allocated}},msync:function(stream,buffer,offset,length,mmapFlags){MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0}}};function asyncLoad(url,onload,onerror,noRunDep){var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):\"\";readAsync(url,arrayBuffer=>{assert(arrayBuffer,`Loading data file \"${url}\" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file \"${url}\" failed.`}});if(dep)addRunDependency(dep)}var preloadPlugins=Module[\"preloadPlugins\"]||[];function FS_handledByPreloadPlugin(byteArray,fullname,finish,onerror){if(typeof Browser!=\"undefined\")Browser.init();var handled=false;preloadPlugins.forEach(function(plugin){if(handled)return;if(plugin[\"canHandle\"](fullname)){plugin[\"handle\"](byteArray,fullname,finish,onerror);handled=true}});return handled}function FS_createPreloadedFile(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{if(onerror)onerror();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url==\"string\"){asyncLoad(url,byteArray=>processData(byteArray),onerror)}else{processData(url)}}function FS_modeStringToFlags(str){var flagModes={\"r\":0,\"r+\":2,\"w\":512|64|1,\"w+\":512|64|2,\"a\":1024|64|1,\"a+\":1024|64|2};var flags=flagModes[str];if(typeof flags==\"undefined\"){throw new Error(`Unknown file open mode: ${str}`)}return flags}function FS_getMode(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode}var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:\"/\",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:(path,opts={})=>{path=PATH_FS.resolve(path);if(!path)return{path:\"\",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split(\"/\").filter(p=>!!p);var current=FS.root;var current_path=\"/\";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}current=FS.lookupNode(current,parts[i]);current_path=PATH.join2(current_path,parts[i]);if(FS.isMountpoint(current)){if(!islast||islast&&opts.follow_mount){current=current.mounted.root}}if(!islast||opts.follow){var count=0;while(FS.isLink(current.mode)){var link=FS.readlink(current_path);current_path=PATH_FS.resolve(PATH.dirname(current_path),link);var lookup=FS.lookupPath(current_path,{recurse_count:opts.recurse_count+1});current=lookup.node;if(count++>40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:node=>{var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!==\"/\"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName:(parentid,name)=>{var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length},hashAddNode:node=>{var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:node=>{var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:(parent,name)=>{var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:(parent,name,mode,rdev)=>{var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:node=>{FS.hashRemoveNode(node)},isRoot:node=>{return node===node.parent},isMountpoint:node=>{return!!node.mounted},isFile:mode=>{return(mode&61440)===32768},isDir:mode=>{return(mode&61440)===16384},isLink:mode=>{return(mode&61440)===40960},isChrdev:mode=>{return(mode&61440)===8192},isBlkdev:mode=>{return(mode&61440)===24576},isFIFO:mode=>{return(mode&61440)===4096},isSocket:mode=>{return(mode&49152)===49152},flagsToPermissionString:flag=>{var perms=[\"r\",\"w\",\"rw\"][flag&3];if(flag&512){perms+=\"w\"}return perms},nodePermissions:(node,perms)=>{if(FS.ignorePermissions){return 0}if(perms.includes(\"r\")&&!(node.mode&292)){return 2}else if(perms.includes(\"w\")&&!(node.mode&146)){return 2}else if(perms.includes(\"x\")&&!(node.mode&73)){return 2}return 0},mayLookup:dir=>{var errCode=FS.nodePermissions(dir,\"x\");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:(dir,name)=>{try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,\"wx\")},mayDelete:(dir,name,isdir)=>{var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,\"wx\");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:(node,flags)=>{if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!==\"r\"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:()=>{for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:fd=>FS.streams[fd],createStream:(stream,fd=-1)=>{if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}},flags:{get:function(){return this.shared.flags},set:function(val){this.shared.flags=val}},position:{get:function(){return this.shared.position},set:function(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:fd=>{FS.streams[fd]=null},chrdev_stream_ops:{open:stream=>{var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:()=>{throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice:(dev,ops)=>{FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts:mount=>{var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:(populate,callback)=>{if(typeof populate==\"function\"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:(type,opts,mountpoint)=>{var root=mountpoint===\"/\";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:mountpoint=>{var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:(parent,name)=>{return parent.node_ops.lookup(parent,name)},mknod:(path,mode,dev)=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name===\".\"||name===\"..\"){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:(path,mode)=>{mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:(path,mode)=>{mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:(path,mode)=>{var dirs=path.split(\"/\");var d=\"\";for(var i=0;i<dirs.length;++i){if(!dirs[i])continue;d+=\"/\"+dirs[i];try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev:(path,mode,dev)=>{if(typeof dev==\"undefined\"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink:(oldpath,newpath)=>{if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename:(old_path,new_path)=>{var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!==\".\"){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!==\".\"){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,\"w\");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir:path=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink:path=>{var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat:(path,dontFollow)=>{var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat:path=>{return FS.stat(path,true)},chmod:(path,mode,dontFollow)=>{var node;if(typeof path==\"string\"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod:(path,mode)=>{FS.chmod(path,mode,true)},fchmod:(fd,mode)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chmod(stream.node,mode)},chown:(path,uid,gid,dontFollow)=>{var node;if(typeof path==\"string\"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown:(path,uid,gid)=>{FS.chown(path,uid,gid,true)},fchown:(fd,uid,gid)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chown(stream.node,uid,gid)},truncate:(path,len)=>{if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path==\"string\"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,\"w\");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate:(fd,len)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime:(path,atime,mtime)=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open:(path,flags,mode)=>{if(path===\"\"){throw new FS.ErrnoError(44)}flags=typeof flags==\"string\"?FS_modeStringToFlags(flags):flags;mode=typeof mode==\"undefined\"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path==\"object\"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module[\"logReadFiles\"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close:stream=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed:stream=>{return stream.fd===null},llseek:(stream,offset,whence)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read:(stream,buffer,offset,length,position)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!=\"undefined\";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write:(stream,buffer,offset,length,position,canOwn)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!=\"undefined\";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate:(stream,offset,length)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap:(stream,length,position,prot,flags)=>{if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync:(stream,buffer,offset,length,mmapFlags)=>{if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl:(stream,cmd,arg)=>{if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile:(path,opts={})=>{opts.flags=opts.flags||0;opts.encoding=opts.encoding||\"binary\";if(opts.encoding!==\"utf8\"&&opts.encoding!==\"binary\"){throw new Error(`Invalid encoding type \"${opts.encoding}\"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding===\"utf8\"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding===\"binary\"){ret=buf}FS.close(stream);return ret},writeFile:(path,data,opts={})=>{opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data==\"string\"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error(\"Unsupported data type\")}FS.close(stream)},cwd:()=>FS.currentPath,chdir:path=>{var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,\"x\");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories:()=>{FS.mkdir(\"/tmp\");FS.mkdir(\"/home\");FS.mkdir(\"/home/web_user\")},createDefaultDevices:()=>{FS.mkdir(\"/dev\");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev(\"/dev/null\",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev(\"/dev/tty\",FS.makedev(5,0));FS.mkdev(\"/dev/tty1\",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice(\"/dev\",\"random\",randomByte);FS.createDevice(\"/dev\",\"urandom\",randomByte);FS.mkdir(\"/dev/shm\");FS.mkdir(\"/dev/shm/tmp\")},createSpecialDirectories:()=>{FS.mkdir(\"/proc\");var proc_self=FS.mkdir(\"/proc/self\");FS.mkdir(\"/proc/self/fd\");FS.mount({mount:()=>{var node=FS.createNode(proc_self,\"fd\",16384|511,73);node.node_ops={lookup:(parent,name)=>{var fd=+name;var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);var ret={parent:null,mount:{mountpoint:\"fake\"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},\"/proc/self/fd\")},createStandardStreams:()=>{if(Module[\"stdin\"]){FS.createDevice(\"/dev\",\"stdin\",Module[\"stdin\"])}else{FS.symlink(\"/dev/tty\",\"/dev/stdin\")}if(Module[\"stdout\"]){FS.createDevice(\"/dev\",\"stdout\",null,Module[\"stdout\"])}else{FS.symlink(\"/dev/tty\",\"/dev/stdout\")}if(Module[\"stderr\"]){FS.createDevice(\"/dev\",\"stderr\",null,Module[\"stderr\"])}else{FS.symlink(\"/dev/tty1\",\"/dev/stderr\")}var stdin=FS.open(\"/dev/stdin\",0);var stdout=FS.open(\"/dev/stdout\",1);var stderr=FS.open(\"/dev/stderr\",1)},ensureErrnoError:()=>{if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.name=\"ErrnoError\";this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message=\"FS error\"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=\"<generic error, no stack>\"})},staticInit:()=>{FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},\"/\");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={\"MEMFS\":MEMFS}},init:(input,output,error)=>{FS.init.initialized=true;FS.ensureErrnoError();Module[\"stdin\"]=input||Module[\"stdin\"];Module[\"stdout\"]=output||Module[\"stdout\"];Module[\"stderr\"]=error||Module[\"stderr\"];FS.createStandardStreams()},quit:()=>{FS.init.initialized=false;for(var i=0;i<FS.streams.length;i++){var stream=FS.streams[i];if(!stream){continue}FS.close(stream)}},findObject:(path,dontResolveLastLink)=>{var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath:(path,dontResolveLastLink)=>{try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path===\"/\"}catch(e){ret.error=e.errno}return ret},createPath:(parent,path,canRead,canWrite)=>{parent=typeof parent==\"string\"?parent:FS.getPath(parent);var parts=path.split(\"/\").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile:(parent,name,properties,canRead,canWrite)=>{var path=PATH.join2(typeof parent==\"string\"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile:(parent,name,data,canRead,canWrite,canOwn)=>{var path=name;if(parent){parent=typeof parent==\"string\"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data==\"string\"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,577);FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}return node},createDevice:(parent,name,input,output)=>{var path=PATH.join2(typeof parent==\"string\"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:stream=>{stream.seekable=false},close:stream=>{if(output&&output.buffer&&output.buffer.length){output(10)}},read:(stream,buffer,offset,length,pos)=>{var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write:(stream,buffer,offset,length,pos)=>{for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(29)}}if(length){stream.node.timestamp=Date.now()}return i}});return FS.mkdev(path,mode,dev)},forceLoadFile:obj=>{if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!=\"undefined\"){throw new Error(\"Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.\")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error(\"Cannot load without read() or XMLHttpRequest.\")}},createLazyFile:(parent,name,url,canRead,canWrite)=>{function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open(\"HEAD\",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error(\"Couldn't load \"+url+\". Status: \"+xhr.status);var datalength=Number(xhr.getResponseHeader(\"Content-length\"));var header;var hasByteServing=(header=xhr.getResponseHeader(\"Accept-Ranges\"))&&header===\"bytes\";var usesGzip=(header=xhr.getResponseHeader(\"Content-Encoding\"))&&header===\"gzip\";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error(\"invalid range (\"+from+\", \"+to+\") or no bytes requested!\");if(to>datalength-1)throw new Error(\"only \"+datalength+\" bytes available! programmer error!\");var xhr=new XMLHttpRequest;xhr.open(\"GET\",url,false);if(datalength!==chunkSize)xhr.setRequestHeader(\"Range\",\"bytes=\"+from+\"-\"+to);xhr.responseType=\"arraybuffer\";if(xhr.overrideMimeType){xhr.overrideMimeType(\"text/plain; charset=x-user-defined\")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error(\"Couldn't load \"+url+\". Status: \"+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||\"\",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==\"undefined\"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==\"undefined\")throw new Error(\"doXHR failed!\");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out(\"LazyFiles on gzip forces download of the whole file when length is accessed\")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=\"undefined\"){if(!ENVIRONMENT_IS_WORKER)throw\"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc\";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size}stream_ops.read=(stream,buffer,offset,length,position)=>{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):\"\"}var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt:function(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat:function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-54}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAP32[buf+12>>2]=stat.uid;HEAP32[buf+16>>2]=stat.gid;HEAP32[buf+20>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAPU32[buf+48>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream}};function _proc_exit(code){EXITSTATUS=code;if(!keepRuntimeAlive()){if(Module[\"onExit\"])Module[\"onExit\"](code);ABORT=true}quit_(code,new ExitStatus(code))}function exitJS(status,implicit){EXITSTATUS=status;_proc_exit(status)}var _exit=exitJS;function maybeExit(){if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}}function callUserCallback(func){if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}}function safeSetTimeout(func,timeout){return setTimeout(()=>{callUserCallback(func)},timeout)}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;if(ENVIRONMENT_IS_NODE)text=\"warning: \"+text;err(text)}}var Browser={mainLoop:{running:false,scheduler:null,method:\"\",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;setMainLoop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()},updateStatus:function(){if(Module[\"setStatus\"]){var message=Module[\"statusMessage\"]||\"Please wait...\";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining<expected){Module[\"setStatus\"](message+\" (\"+(expected-remaining)+\"/\"+expected+\")\")}else{Module[\"setStatus\"](message)}}else{Module[\"setStatus\"](\"\")}}},runIter:function(func){if(ABORT)return;if(Module[\"preMainLoop\"]){var preRet=Module[\"preMainLoop\"]();if(preRet===false){return}}callUserCallback(func);if(Module[\"postMainLoop\"])Module[\"postMainLoop\"]()}},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function(){if(Browser.initted)return;Browser.initted=true;var imagePlugin={};imagePlugin[\"canHandle\"]=function imagePlugin_canHandle(name){return!Module.noImageDecoding&&/\\.(jpg|jpeg|png|bmp)$/i.test(name)};imagePlugin[\"handle\"]=function imagePlugin_handle(byteArray,name,onload,onerror){var b=new Blob([byteArray],{type:Browser.getMimetype(name)});if(b.size!==byteArray.length){b=new Blob([new Uint8Array(byteArray).buffer],{type:Browser.getMimetype(name)})}var url=URL.createObjectURL(b);var img=new Image;img.onload=()=>{assert(img.complete,\"Image \"+name+\" could not be decoded\");var canvas=document.createElement(\"canvas\");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext(\"2d\");ctx.drawImage(img,0,0);preloadedImages[name]=canvas;URL.revokeObjectURL(url);if(onload)onload(byteArray)};img.onerror=event=>{out(\"Image \"+url+\" could not be decoded\");if(onerror)onerror()};img.src=url};preloadPlugins.push(imagePlugin);var audioPlugin={};audioPlugin[\"canHandle\"]=function audioPlugin_canHandle(name){return!Module.noAudioDecoding&&name.substr(-4)in{\".ogg\":1,\".wav\":1,\".mp3\":1}};audioPlugin[\"handle\"]=function audioPlugin_handle(byteArray,name,onload,onerror){var done=false;function finish(audio){if(done)return;done=true;preloadedAudios[name]=audio;if(onload)onload(byteArray)}var b=new Blob([byteArray],{type:Browser.getMimetype(name)});var url=URL.createObjectURL(b);var audio=new Audio;audio.addEventListener(\"canplaythrough\",()=>finish(audio),false);audio.onerror=function audio_onerror(event){if(done)return;err(\"warning: browser could not fully decode audio \"+name+\", trying slower base64 approach\");function encode64(data){var BASE=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";var PAD=\"=\";var ret=\"\";var leftchar=0;var leftbits=0;for(var i=0;i<data.length;i++){leftchar=leftchar<<8|data[i];leftbits+=8;while(leftbits>=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src=\"data:audio/x-\"+name.substr(-3)+\";base64,\"+encode64(byteArray);finish(audio)};audio.src=url;safeSetTimeout(()=>{finish(audio)},1e4)};preloadPlugins.push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document[\"pointerLockElement\"]===Module[\"canvas\"]||document[\"mozPointerLockElement\"]===Module[\"canvas\"]||document[\"webkitPointerLockElement\"]===Module[\"canvas\"]||document[\"msPointerLockElement\"]===Module[\"canvas\"]}var canvas=Module[\"canvas\"];if(canvas){canvas.requestPointerLock=canvas[\"requestPointerLock\"]||canvas[\"mozRequestPointerLock\"]||canvas[\"webkitRequestPointerLock\"]||canvas[\"msRequestPointerLock\"]||(()=>{});canvas.exitPointerLock=document[\"exitPointerLock\"]||document[\"mozExitPointerLock\"]||document[\"webkitExitPointerLock\"]||document[\"msExitPointerLock\"]||(()=>{});canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener(\"pointerlockchange\",pointerLockChange,false);document.addEventListener(\"mozpointerlockchange\",pointerLockChange,false);document.addEventListener(\"webkitpointerlockchange\",pointerLockChange,false);document.addEventListener(\"mspointerlockchange\",pointerLockChange,false);if(Module[\"elementPointerLock\"]){canvas.addEventListener(\"click\",ev=>{if(!Browser.pointerLock&&Module[\"canvas\"].requestPointerLock){Module[\"canvas\"].requestPointerLock();ev.preventDefault()}},false)}}},createContext:function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false,majorVersion:typeof WebGL2RenderingContext!=\"undefined\"?2:1};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}if(typeof GL!=\"undefined\"){contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}}else{ctx=canvas.getContext(\"2d\")}if(!ctx)return null;if(setInModule){if(!useWebGL)assert(typeof GLctx==\"undefined\",\"cannot set in module if GLctx is used, but we are a non-GL context that would replace it\");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach(callback=>callback());Browser.init()}return ctx},destroyContext:function(canvas,useWebGL,setInModule){},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer,resizeCanvas){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;if(typeof Browser.lockPointer==\"undefined\")Browser.lockPointer=true;if(typeof Browser.resizeCanvas==\"undefined\")Browser.resizeCanvas=false;var canvas=Module[\"canvas\"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document[\"fullscreenElement\"]||document[\"mozFullScreenElement\"]||document[\"msFullscreenElement\"]||document[\"webkitFullscreenElement\"]||document[\"webkitCurrentFullScreenElement\"])===canvasContainer){canvas.exitFullscreen=Browser.exitFullscreen;if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas){Browser.setFullscreenCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas){Browser.setWindowedCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}if(Module[\"onFullScreen\"])Module[\"onFullScreen\"](Browser.isFullscreen);if(Module[\"onFullscreen\"])Module[\"onFullscreen\"](Browser.isFullscreen)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener(\"fullscreenchange\",fullscreenChange,false);document.addEventListener(\"mozfullscreenchange\",fullscreenChange,false);document.addEventListener(\"webkitfullscreenchange\",fullscreenChange,false);document.addEventListener(\"MSFullscreenChange\",fullscreenChange,false)}var canvasContainer=document.createElement(\"div\");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer[\"requestFullscreen\"]||canvasContainer[\"mozRequestFullScreen\"]||canvasContainer[\"msRequestFullscreen\"]||(canvasContainer[\"webkitRequestFullscreen\"]?()=>canvasContainer[\"webkitRequestFullscreen\"](Element[\"ALLOW_KEYBOARD_INPUT\"]):null)||(canvasContainer[\"webkitRequestFullScreen\"]?()=>canvasContainer[\"webkitRequestFullScreen\"](Element[\"ALLOW_KEYBOARD_INPUT\"]):null);canvasContainer.requestFullscreen()},exitFullscreen:function(){if(!Browser.isFullscreen){return false}var CFS=document[\"exitFullscreen\"]||document[\"cancelFullScreen\"]||document[\"mozCancelFullScreen\"]||document[\"msExitFullscreen\"]||document[\"webkitCancelFullScreen\"]||(()=>{});CFS.apply(document,[]);return true},nextRAF:0,fakeRequestAnimationFrame:function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)},requestAnimationFrame:function(func){if(typeof requestAnimationFrame==\"function\"){requestAnimationFrame(func);return}var RAF=Browser.fakeRequestAnimationFrame;RAF(func)},safeSetTimeout:function(func,timeout){return safeSetTimeout(func,timeout)},safeRequestAnimationFrame:function(func){return Browser.requestAnimationFrame(()=>{callUserCallback(func)})},getMimetype:function(name){return{\"jpg\":\"image/jpeg\",\"jpeg\":\"image/jpeg\",\"png\":\"image/png\",\"bmp\":\"image/bmp\",\"ogg\":\"audio/ogg\",\"wav\":\"audio/wav\",\"mp3\":\"audio/mpeg\"}[name.substr(name.lastIndexOf(\".\")+1)]},getUserMedia:function(func){if(!window.getUserMedia){window.getUserMedia=navigator[\"getUserMedia\"]||navigator[\"mozGetUserMedia\"]}window.getUserMedia(func)},getMovementX:function(event){return event[\"movementX\"]||event[\"mozMovementX\"]||event[\"webkitMovementX\"]||0},getMovementY:function(event){return event[\"movementY\"]||event[\"mozMovementY\"]||event[\"webkitMovementY\"]||0},getMouseWheelDelta:function(event){var delta=0;switch(event.type){case\"DOMMouseScroll\":delta=event.detail/3;break;case\"mousewheel\":delta=event.wheelDelta/120;break;case\"wheel\":delta=event.deltaY;switch(event.deltaMode){case 0:delta/=100;break;case 1:delta/=3;break;case 2:delta*=80;break;default:throw\"unrecognized mouse wheel delta mode: \"+event.deltaMode}break;default:throw\"unrecognized mouse wheel event: \"+event.type}return delta},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event){if(Browser.pointerLock){if(event.type!=\"mousemove\"&&\"mozMovementX\"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!=\"undefined\"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module[\"canvas\"].getBoundingClientRect();var cw=Module[\"canvas\"].width;var ch=Module[\"canvas\"].height;var scrollX=typeof window.scrollX!=\"undefined\"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!=\"undefined\"?window.scrollY:window.pageYOffset;if(event.type===\"touchstart\"||event.type===\"touchend\"||event.type===\"touchmove\"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type===\"touchstart\"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type===\"touchend\"||event.type===\"touchmove\"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}},resizeListeners:[],updateResizeListeners:function(){var canvas=Module[\"canvas\"];Browser.resizeListeners.forEach(listener=>listener(canvas.width,canvas.height))},setCanvasSize:function(width,height,noUpdates){var canvas=Module[\"canvas\"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!=\"undefined\"){var flags=HEAPU32[SDL.screen>>2];flags=flags|8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module[\"canvas\"]);Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!=\"undefined\"){var flags=HEAPU32[SDL.screen>>2];flags=flags&~8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module[\"canvas\"]);Browser.updateResizeListeners()},updateCanvasDimensions:function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module[\"forcedAspectRatio\"]&&Module[\"forcedAspectRatio\"]>0){if(w/h<Module[\"forcedAspectRatio\"]){w=Math.round(h*Module[\"forcedAspectRatio\"])}else{h=Math.round(w/Module[\"forcedAspectRatio\"])}}if((document[\"fullscreenElement\"]||document[\"mozFullScreenElement\"]||document[\"msFullscreenElement\"]||document[\"webkitFullscreenElement\"]||document[\"webkitCurrentFullScreenElement\"])===canvas.parentNode&&typeof screen!=\"undefined\"){var factor=Math.min(screen.width/w,screen.height/h);w=Math.round(w*factor);h=Math.round(h*factor)}if(Browser.resizeCanvas){if(canvas.width!=w)canvas.width=w;if(canvas.height!=h)canvas.height=h;if(typeof canvas.style!=\"undefined\"){canvas.style.removeProperty(\"width\");canvas.style.removeProperty(\"height\")}}else{if(canvas.width!=wNative)canvas.width=wNative;if(canvas.height!=hNative)canvas.height=hNative;if(typeof canvas.style!=\"undefined\"){if(w!=wNative||h!=hNative){canvas.style.setProperty(\"width\",w+\"px\",\"important\");canvas.style.setProperty(\"height\",h+\"px\",\"important\")}else{canvas.style.removeProperty(\"width\");canvas.style.removeProperty(\"height\")}}}}};function callRuntimeCallbacks(callbacks){while(callbacks.length>0){callbacks.shift()(Module)}}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast}function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:case 21505:{if(!stream.tty)return-59;return 0}case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-59;return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;return 0}case 21524:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}var dlopenMissingError=\"To use dlopen, you need enable dynamic linking, see https://emscripten.org/docs/compiling/Dynamic-Linking.html\";function __dlopen_js(handle){abort(dlopenMissingError)}function __dlsym_js(handle,symbol){abort(dlopenMissingError)}function __embind_register_bigint(primitiveType,name,size,minRange,maxRange){}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError(`Unknown type size: ${size}`)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret=\"\";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return\"_unknown\"}name=name.replace(/[^a-zA-Z0-9_]/g,\"$\");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return{[name]:function(){return body.apply(this,arguments)}}[name]}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+\"\\n\"+stack.replace(/^Error(:[^\\n]*)?\\n/,\"\")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function registerType(rawType,registeredInstance,options={}){if(!(\"argPackAdvance\"in registeredInstance)){throw new TypeError(\"registerType registeredInstance requires argPackAdvance\")}var name=registeredInstance.name;if(!rawType){throwBindingError(`type \"${name}\" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function __embind_register_bool(rawType,name,size,trueValue,falseValue){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":function(wt){return!!wt},\"toWireType\":function(destructors,o){return o?trueValue:falseValue},\"argPackAdvance\":8,\"readValueFromPointer\":function(pointer){var heap;if(size===1){heap=HEAP8}else if(size===2){heap=HEAP16}else if(size===4){heap=HEAP32}else{throw new TypeError(\"Unknown boolean type size: \"+name)}return this[\"fromWireType\"](heap[pointer>>shift])},destructorFunction:null})}function HandleAllocator(){this.allocated=[undefined];this.freelist=[];this.get=function(id){return this.allocated[id]};this.has=function(id){return this.allocated[id]!==undefined};this.allocate=function(handle){var id=this.freelist.pop()||this.allocated.length;this.allocated[id]=handle;return id};this.free=function(id){this.allocated[id]=undefined;this.freelist.push(id)}}var emval_handles=new HandleAllocator;function __emval_decref(handle){if(handle>=emval_handles.reserved&&0===--emval_handles.get(handle).refcount){emval_handles.free(handle)}}function count_emval_handles(){var count=0;for(var i=emval_handles.reserved;i<emval_handles.allocated.length;++i){if(emval_handles.allocated[i]!==undefined){++count}}return count}function init_emval(){emval_handles.allocated.push({value:undefined},{value:null},{value:true},{value:false});emval_handles.reserved=emval_handles.allocated.length;Module[\"count_emval_handles\"]=count_emval_handles}var Emval={toValue:handle=>{if(!handle){throwBindingError(\"Cannot use deleted val. handle = \"+handle)}return emval_handles.get(handle).value},toHandle:value=>{switch(value){case undefined:return 1;case null:return 2;case true:return 3;case false:return 4;default:{return emval_handles.allocate({refcount:1,value:value})}}}};function simpleReadValueFromPointer(pointer){return this[\"fromWireType\"](HEAP32[pointer>>2])}function __embind_register_emval(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":function(handle){var rv=Emval.toValue(handle);__emval_decref(handle);return rv},\"toWireType\":function(destructors,value){return Emval.toHandle(value)},\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:null})}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this[\"fromWireType\"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this[\"fromWireType\"](HEAPF64[pointer>>3])};default:throw new TypeError(\"Unknown float type: \"+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":function(value){return value},\"toWireType\":function(destructors,value){return value},\"argPackAdvance\":8,\"readValueFromPointer\":floatReadValueFromPointer(name,shift),destructorFunction:null})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError(\"Unknown integer type: \"+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<<bitshift>>>bitshift}var isUnsignedType=name.includes(\"unsigned\");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name:name,\"fromWireType\":fromWireType,\"toWireType\":toWireType,\"argPackAdvance\":8,\"readValueFromPointer\":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(heap.buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,\"fromWireType\":decodeMemoryView,\"argPackAdvance\":8,\"readValueFromPointer\":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name===\"std::string\";registerType(rawType,{name:name,\"fromWireType\":function(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i<length;++i){a[i]=String.fromCharCode(HEAPU8[payload+i])}str=a.join(\"\")}_free(value);return str},\"toWireType\":function(destructors,value){if(value instanceof ArrayBuffer){value=new Uint8Array(value)}var length;var valueIsOfTypeString=typeof value==\"string\";if(!(valueIsOfTypeString||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int8Array)){throwBindingError(\"Cannot pass non-string to std::string\")}if(stdStringIsUTF8&&valueIsOfTypeString){length=lengthBytesUTF8(value)}else{length=value.length}var base=_malloc(4+length+1);var ptr=base+4;HEAPU32[base>>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i<length;++i){var charCode=value.charCodeAt(i);if(charCode>255){_free(ptr);throwBindingError(\"String has UTF-16 code units that do not fit in 8 bits\")}HEAPU8[ptr+i]=charCode}}else{for(var i=0;i<length;++i){HEAPU8[ptr+i]=value[i]}}}if(destructors!==null){destructors.push(_free,base)}return base},\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}var UTF16Decoder=typeof TextDecoder!=\"undefined\"?new TextDecoder(\"utf-16le\"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str=\"\";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite<str.length*2?maxBytesToWrite/2:str.length;for(var i=0;i<numCharsToWrite;++i){var codeUnit=str.charCodeAt(i);HEAP16[outPtr>>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str=\"\";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){var codeUnit=str.charCodeAt(i);if(codeUnit>=55296&&codeUnit<=57343)++i;len+=4}return len}function __embind_register_std_wstring(rawType,charSize,name){name=readLatin1String(name);var decodeString,encodeString,getHeap,lengthBytesUTF,shift;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;getHeap=()=>HEAPU16;shift=1}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;getHeap=()=>HEAPU32;shift=2}registerType(rawType,{name:name,\"fromWireType\":function(value){var length=HEAPU32[value>>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},\"toWireType\":function(destructors,value){if(!(typeof value==\"string\")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},\"argPackAdvance\":8,\"readValueFromPointer\":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,\"argPackAdvance\":0,\"fromWireType\":function(){return undefined},\"toWireType\":function(destructors,o){return undefined}})}var nowIsMonotonic=true;function __emscripten_get_now_is_monotonic(){return nowIsMonotonic}function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+\" has unknown type \"+getTypeName(rawType))}return impl}function __emval_as(handle,returnType,destructorsRef){handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,\"emval::as\");var destructors=[];var rd=Emval.toHandle(destructors);HEAPU32[destructorsRef>>2]=rd;return returnType[\"toWireType\"](destructors,handle)}var emval_symbols={};function getStringOrSymbol(address){var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}return symbol}function emval_get_global(){if(typeof globalThis==\"object\"){return globalThis}function testGlobal(obj){obj[\"$$$embind_global$$$\"]=obj;var success=typeof $$$embind_global$$$==\"object\"&&obj[\"$$$embind_global$$$\"]==obj;if(!success){delete obj[\"$$$embind_global$$$\"]}return success}if(typeof $$$embind_global$$$==\"object\"){return $$$embind_global$$$}if(typeof global==\"object\"&&testGlobal(global)){$$$embind_global$$$=global}else if(typeof self==\"object\"&&testGlobal(self)){$$$embind_global$$$=self}if(typeof $$$embind_global$$$==\"object\"){return $$$embind_global$$$}throw Error(\"unable to get global object.\")}function __emval_get_global(name){if(name===0){return Emval.toHandle(emval_get_global())}else{name=getStringOrSymbol(name);return Emval.toHandle(emval_get_global()[name])}}function __emval_get_property(handle,key){handle=Emval.toValue(handle);key=Emval.toValue(key);return Emval.toHandle(handle[key])}function __emval_incref(handle){if(handle>4){emval_handles.get(handle).refcount+=1}}function __emval_instanceof(object,constructor){object=Emval.toValue(object);constructor=Emval.toValue(constructor);return object instanceof constructor}function __emval_new_cstring(v){return Emval.toHandle(getStringOrSymbol(v))}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function __emval_run_destructors(handle){var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)}function __emval_set_property(handle,key,value){handle=Emval.toValue(handle);key=Emval.toValue(key);value=Emval.toValue(value);handle[key]=value}function __emval_take_value(type,arg){type=requireRegisteredType(type,\"_emval_take_value\");var v=type[\"readValueFromPointer\"](arg);return Emval.toHandle(v)}function __emval_typeof(handle){handle=Emval.toValue(handle);return Emval.toHandle(typeof handle)}function readI53FromI64(ptr){return HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296}function __gmtime_js(time,tmPtr){var date=new Date(readI53FromI64(time)*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday}function isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];function ydayFromDate(date){var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday}function __localtime_js(time,tmPtr){var date=new Date(readI53FromI64(time)*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}function __mktime_js(tmPtr){var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getYear();return date.getTime()/1e3|0}function __mmap_js(len,prot,flags,fd,off,allocated,addr){try{var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,off,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset){try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}FS.munmap(stream)}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return-e.errno}}function stringToNewUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret}function __tzset_js(timezone,daylight,tzname){var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\\(([A-Za-z ]+)\\)$/);return match?match[1]:\"GMT\"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=stringToNewUTF8(winterName);var summerNamePtr=stringToNewUTF8(summerName);if(summerOffset<winterOffset){HEAPU32[tzname>>2]=winterNamePtr;HEAPU32[tzname+4>>2]=summerNamePtr}else{HEAPU32[tzname>>2]=summerNamePtr;HEAPU32[tzname+4>>2]=winterNamePtr}}function _abort(){abort(\"\")}var readEmAsmArgsArray=[];function readEmAsmArgs(sigPtr,buf){readEmAsmArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){buf+=ch!=105&buf;readEmAsmArgsArray.push(ch==105?HEAP32[buf]:HEAPF64[buf++>>1]);++buf}return readEmAsmArgsArray}function runEmAsmFunction(code,sigPtr,argbuf){var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_asm_const_int(code,sigPtr,argbuf){return runEmAsmFunction(code,sigPtr,argbuf)}function _emscripten_date_now(){return Date.now()}function _emscripten_err(str){err(UTF8ToString(str))}function _emscripten_errn(str,len){err(UTF8ToString(str,len))}function getHeapMax(){return 2147483648}function _emscripten_get_heap_max(){return getHeapMax()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function _emscripten_outn(str,len){out(UTF8ToString(str,len))}function _emscripten_pc_get_function(pc){abort(\"Cannot use emscripten_pc_get_function without -sUSE_OFFSET_CONVERTER\")}function emscripten_realloc_buffer(size){var b=wasmMemory.buffer;var pages=size-b.byteLength+65535>>>16;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}function convertFrameToPC(frame){abort(\"Cannot use convertFrameToPC (needed by __builtin_return_address) without -sUSE_OFFSET_CONVERTER\");return 0}var UNWIND_CACHE={};function saveInUnwindCache(callstack){callstack.forEach(frame=>{var pc=convertFrameToPC(frame);if(pc){UNWIND_CACHE[pc]=frame}})}function jsStackTrace(){var error=new Error;if(!error.stack){try{throw new Error}catch(e){error=e}if(!error.stack){return\"(no stack trace available)\"}}return error.stack.toString()}function _emscripten_stack_snapshot(){var callstack=jsStackTrace().split(\"\\n\");if(callstack[0]==\"Error\"){callstack.shift()}saveInUnwindCache(callstack);UNWIND_CACHE.last_addr=convertFrameToPC(callstack[3]);UNWIND_CACHE.last_stack=callstack;return UNWIND_CACHE.last_addr}function _emscripten_stack_unwind_buffer(addr,buffer,count){var stack;if(UNWIND_CACHE.last_addr==addr){stack=UNWIND_CACHE.last_stack}else{stack=jsStackTrace().split(\"\\n\");if(stack[0]==\"Error\"){stack.shift()}saveInUnwindCache(stack)}var offset=3;while(stack[offset]&&convertFrameToPC(stack[offset])!=addr){++offset}for(var i=0;i<count&&stack[i+offset];++i){HEAP32[buffer+i*4>>2]=convertFrameToPC(stack[i+offset])}return i}function webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension(\"ANGLE_instanced_arrays\");if(ext){ctx[\"vertexAttribDivisor\"]=function(index,divisor){ext[\"vertexAttribDivisorANGLE\"](index,divisor)};ctx[\"drawArraysInstanced\"]=function(mode,first,count,primcount){ext[\"drawArraysInstancedANGLE\"](mode,first,count,primcount)};ctx[\"drawElementsInstanced\"]=function(mode,count,type,indices,primcount){ext[\"drawElementsInstancedANGLE\"](mode,count,type,indices,primcount)};return 1}}function webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension(\"OES_vertex_array_object\");if(ext){ctx[\"createVertexArray\"]=function(){return ext[\"createVertexArrayOES\"]()};ctx[\"deleteVertexArray\"]=function(vao){ext[\"deleteVertexArrayOES\"](vao)};ctx[\"bindVertexArray\"]=function(vao){ext[\"bindVertexArrayOES\"](vao)};ctx[\"isVertexArray\"]=function(vao){return ext[\"isVertexArrayOES\"](vao)};return 1}}function webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension(\"WEBGL_draw_buffers\");if(ext){ctx[\"drawBuffers\"]=function(n,bufs){ext[\"drawBuffersWEBGL\"](n,bufs)};return 1}}function webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(ctx){return!!(ctx.dibvbi=ctx.getExtension(\"WEBGL_draw_instanced_base_vertex_base_instance\"))}function webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(ctx){return!!(ctx.mdibvbi=ctx.getExtension(\"WEBGL_multi_draw_instanced_base_vertex_base_instance\"))}function webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebgl=ctx.getExtension(\"WEBGL_multi_draw\"))}var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:function(table){var ret=GL.counter++;for(var i=table.length;i<ret;i++){table[i]=null}return ret},MAX_TEMP_BUFFER_SIZE:2097152,numTempVertexBuffersPerSize:64,log2ceilLookup:function(i){return 32-Math.clz32(i===0?0:i-1)},generateTempBuffers:function(quads,context){var largestIndex=GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);context.tempVertexBufferCounters1=[];context.tempVertexBufferCounters2=[];context.tempVertexBufferCounters1.length=context.tempVertexBufferCounters2.length=largestIndex+1;context.tempVertexBuffers1=[];context.tempVertexBuffers2=[];context.tempVertexBuffers1.length=context.tempVertexBuffers2.length=largestIndex+1;context.tempIndexBuffers=[];context.tempIndexBuffers.length=largestIndex+1;for(var i=0;i<=largestIndex;++i){context.tempIndexBuffers[i]=null;context.tempVertexBufferCounters1[i]=context.tempVertexBufferCounters2[i]=0;var ringbufferLength=GL.numTempVertexBuffersPerSize;context.tempVertexBuffers1[i]=[];context.tempVertexBuffers2[i]=[];var ringbuffer1=context.tempVertexBuffers1[i];var ringbuffer2=context.tempVertexBuffers2[i];ringbuffer1.length=ringbuffer2.length=ringbufferLength;for(var j=0;j<ringbufferLength;++j){ringbuffer1[j]=ringbuffer2[j]=null}}if(quads){context.tempQuadIndexBuffer=GLctx.createBuffer();context.GLctx.bindBuffer(34963,context.tempQuadIndexBuffer);var numIndexes=GL.MAX_TEMP_BUFFER_SIZE>>1;var quadIndexes=new Uint16Array(numIndexes);var i=0,v=0;while(1){quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+1;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v+3;if(i>=numIndexes)break;v+=4}context.GLctx.bufferData(34963,quadIndexes,35044);context.GLctx.bindBuffer(34963,null)}},getTempVertexBuffer:function getTempVertexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ringbuffer=GL.currentContext.tempVertexBuffers1[idx];var nextFreeBufferIndex=GL.currentContext.tempVertexBufferCounters1[idx];GL.currentContext.tempVertexBufferCounters1[idx]=GL.currentContext.tempVertexBufferCounters1[idx]+1&GL.numTempVertexBuffersPerSize-1;var vbo=ringbuffer[nextFreeBufferIndex];if(vbo){return vbo}var prevVBO=GLctx.getParameter(34964);ringbuffer[nextFreeBufferIndex]=GLctx.createBuffer();GLctx.bindBuffer(34962,ringbuffer[nextFreeBufferIndex]);GLctx.bufferData(34962,1<<idx,35048);GLctx.bindBuffer(34962,prevVBO);return ringbuffer[nextFreeBufferIndex]},getTempIndexBuffer:function getTempIndexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ibo=GL.currentContext.tempIndexBuffers[idx];if(ibo){return ibo}var prevIBO=GLctx.getParameter(34965);GL.currentContext.tempIndexBuffers[idx]=GLctx.createBuffer();GLctx.bindBuffer(34963,GL.currentContext.tempIndexBuffers[idx]);GLctx.bufferData(34963,1<<idx,35048);GLctx.bindBuffer(34963,prevIBO);return GL.currentContext.tempIndexBuffers[idx]},newRenderingFrameStarted:function newRenderingFrameStarted(){if(!GL.currentContext){return}var vb=GL.currentContext.tempVertexBuffers1;GL.currentContext.tempVertexBuffers1=GL.currentContext.tempVertexBuffers2;GL.currentContext.tempVertexBuffers2=vb;vb=GL.currentContext.tempVertexBufferCounters1;GL.currentContext.tempVertexBufferCounters1=GL.currentContext.tempVertexBufferCounters2;GL.currentContext.tempVertexBufferCounters2=vb;var largestIndex=GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);for(var i=0;i<=largestIndex;++i){GL.currentContext.tempVertexBufferCounters1[i]=0}},getSource:function(shader,count,string,length){var source=\"\";for(var i=0;i<count;++i){var len=length?HEAP32[length+i*4>>2]:-1;source+=UTF8ToString(HEAP32[string+i*4>>2],len<0?undefined:len)}return source},calcBufLength:function calcBufLength(size,type,stride,count){if(stride>0){return count*stride}var typeSize=GL.byteSizeByType[type-GL.byteSizeByTypeRoot];return size*typeSize*count},usedTempBuffers:[],preDrawHandleClientVertexAttribBindings:function preDrawHandleClientVertexAttribBindings(count){GL.resetBufferBinding=false;for(var i=0;i<GL.currentContext.maxVertexAttribs;++i){var cb=GL.currentContext.clientBuffers[i];if(!cb.clientside||!cb.enabled)continue;GL.resetBufferBinding=true;var size=GL.calcBufLength(cb.size,cb.type,cb.stride,count);var buf=GL.getTempVertexBuffer(size);GLctx.bindBuffer(34962,buf);GLctx.bufferSubData(34962,0,HEAPU8.subarray(cb.ptr,cb.ptr+size));cb.vertexAttribPointerAdaptor.call(GLctx,i,cb.size,cb.type,cb.normalized,cb.stride,0)}},postDrawHandleClientVertexAttribBindings:function postDrawHandleClientVertexAttribBindings(){if(GL.resetBufferBinding){GLctx.bindBuffer(34962,GL.buffers[GLctx.currentArrayBufferBinding])}},createContext:function(canvas,webGLContextAttributes){if(!canvas.getContextSafariWebGL2Fixed){canvas.getContextSafariWebGL2Fixed=canvas.getContext;function fixedGetContext(ver,attrs){var gl=canvas.getContextSafariWebGL2Fixed(ver,attrs);return ver==\"webgl\"==gl instanceof WebGLRenderingContext?gl:null}canvas.getContext=fixedGetContext}var ctx=webGLContextAttributes.majorVersion>1?canvas.getContext(\"webgl2\",webGLContextAttributes):canvas.getContext(\"webgl\",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==\"undefined\"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}context.maxVertexAttribs=context.GLctx.getParameter(34921);context.clientBuffers=[];for(var i=0;i<context.maxVertexAttribs;i++){context.clientBuffers[i]={enabled:false,clientside:false,size:0,type:0,normalized:0,stride:0,ptr:0,vertexAttribPointerAdaptor:null}}GL.generateTempBuffers(false,context);return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return!(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==\"object\")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;GL.contexts[contextHandle]=null},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;webgl_enable_ANGLE_instanced_arrays(GLctx);webgl_enable_OES_vertex_array_object(GLctx);webgl_enable_WEBGL_draw_buffers(GLctx);webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(context.version>=2){GLctx.disjointTimerQueryExt=GLctx.getExtension(\"EXT_disjoint_timer_query_webgl2\")}if(context.version<2||!GLctx.disjointTimerQueryExt){GLctx.disjointTimerQueryExt=GLctx.getExtension(\"EXT_disjoint_timer_query\")}webgl_enable_WEBGL_multi_draw(GLctx);var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(!ext.includes(\"lose_context\")&&!ext.includes(\"debug\")){GLctx.getExtension(ext)}})}};function withStackSave(f){var stack=stackSave();var ret=f();stackRestore(stack);return ret}var JSEvents={inEventHandler:0,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[]},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push(JSEvents.removeAllEventListeners);JSEvents.removeEventListenersRegistered=true}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence<y.precedence})},removeDeferredCalls:function(targetFunction){for(var i=0;i<JSEvents.deferredCalls.length;++i){if(JSEvents.deferredCalls[i].targetFunction==targetFunction){JSEvents.deferredCalls.splice(i,1);--i}}},canPerformEventHandlerRequests:function(){return JSEvents.inEventHandler&&JSEvents.currentEventHandler.allowsDeferredCalls},runDeferredCalls:function(){if(!JSEvents.canPerformEventHandlerRequests()){return}for(var i=0;i<JSEvents.deferredCalls.length;++i){var call=JSEvents.deferredCalls[i];JSEvents.deferredCalls.splice(i,1);--i;call.targetFunction.apply(null,call.argsList)}},eventHandlers:[],removeAllHandlersOnTarget:function(target,eventTypeString){for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==target&&(!eventTypeString||eventTypeString==JSEvents.eventHandlers[i].eventTypeString)){JSEvents._removeHandler(i--)}}},_removeHandler:function(i){var h=JSEvents.eventHandlers[i];h.target.removeEventListener(h.eventTypeString,h.eventListenerFunc,h.useCapture);JSEvents.eventHandlers.splice(i,1)},registerOrRemoveHandler:function(eventHandler){if(!eventHandler.target){return-4}var jsEventHandler=function jsEventHandler(event){++JSEvents.inEventHandler;JSEvents.currentEventHandler=eventHandler;JSEvents.runDeferredCalls();eventHandler.handlerFunc(event);JSEvents.runDeferredCalls();--JSEvents.inEventHandler};if(eventHandler.callbackfunc){eventHandler.eventListenerFunc=jsEventHandler;eventHandler.target.addEventListener(eventHandler.eventTypeString,jsEventHandler,eventHandler.useCapture);JSEvents.eventHandlers.push(eventHandler);JSEvents.registerRemoveEventListeners()}else{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==eventHandler.target&&JSEvents.eventHandlers[i].eventTypeString==eventHandler.eventTypeString){JSEvents._removeHandler(i--)}}}return 0},getNodeNameForTarget:function(target){if(!target)return\"\";if(target==window)return\"#window\";if(target==screen)return\"#screen\";return target&&target.nodeName?target.nodeName:\"\"},fullscreenEnabled:function(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};var emscripten_webgl_power_preferences=[\"default\",\"low-power\",\"high-performance\"];var specialHTMLTargets=[0,typeof document!=\"undefined\"?document:0,typeof window!=\"undefined\"?window:0];function findEventTarget(target){try{if(!target)return window;if(typeof target==\"number\")target=specialHTMLTargets[target]||UTF8ToString(target);if(target===\"#window\")return window;else if(target===\"#document\")return document;else if(target===\"#screen\")return screen;else if(target===\"#canvas\")return Module[\"canvas\"];return typeof target==\"string\"?document.getElementById(target):target}catch(e){return null}}function findCanvasEventTarget(target){if(typeof target==\"number\")target=UTF8ToString(target);if(!target||target===\"#canvas\"){if(typeof GL!=\"undefined\"&&GL.offscreenCanvases[\"canvas\"])return GL.offscreenCanvases[\"canvas\"];return Module[\"canvas\"]}if(typeof GL!=\"undefined\"&&GL.offscreenCanvases[target])return GL.offscreenCanvases[target];return findEventTarget(target)}function _emscripten_webgl_do_create_context(target,attributes){var a=attributes>>2;var powerPreference=HEAP32[a+(24>>2)];var contextAttributes={\"alpha\":!!HEAP32[a+(0>>2)],\"depth\":!!HEAP32[a+(4>>2)],\"stencil\":!!HEAP32[a+(8>>2)],\"antialias\":!!HEAP32[a+(12>>2)],\"premultipliedAlpha\":!!HEAP32[a+(16>>2)],\"preserveDrawingBuffer\":!!HEAP32[a+(20>>2)],\"powerPreference\":emscripten_webgl_power_preferences[powerPreference],\"failIfMajorPerformanceCaveat\":!!HEAP32[a+(28>>2)],majorVersion:HEAP32[a+(32>>2)],minorVersion:HEAP32[a+(36>>2)],enableExtensionsByDefault:HEAP32[a+(40>>2)],explicitSwapControl:HEAP32[a+(44>>2)],proxyContextToMainThread:HEAP32[a+(48>>2)],renderViaOffscreenBackBuffer:HEAP32[a+(52>>2)]};var canvas=findCanvasEventTarget(target);if(!canvas){return 0}if(contextAttributes.explicitSwapControl){return 0}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle}var _emscripten_webgl_create_context=_emscripten_webgl_do_create_context;function _emscripten_webgl_destroy_context(contextHandle){if(GL.currentContext==contextHandle)GL.currentContext=0;GL.deleteContext(contextHandle)}function _emscripten_webgl_get_context_attributes(c,a){if(!a)return-5;c=GL.contexts[c];if(!c)return-3;var t=c.GLctx;if(!t)return-3;t=t.getContextAttributes();HEAP32[a>>2]=t.alpha;HEAP32[a+4>>2]=t.depth;HEAP32[a+8>>2]=t.stencil;HEAP32[a+12>>2]=t.antialias;HEAP32[a+16>>2]=t.premultipliedAlpha;HEAP32[a+20>>2]=t.preserveDrawingBuffer;var power=t[\"powerPreference\"]&&emscripten_webgl_power_preferences.indexOf(t[\"powerPreference\"]);HEAP32[a+24>>2]=power;HEAP32[a+28>>2]=t.failIfMajorPerformanceCaveat;HEAP32[a+32>>2]=c.version;HEAP32[a+36>>2]=0;HEAP32[a+40>>2]=c.attributes.enableExtensionsByDefault;return 0}function _emscripten_webgl_do_get_current_context(){return GL.currentContext?GL.currentContext.handle:0}var _emscripten_webgl_get_current_context=_emscripten_webgl_do_get_current_context;function _emscripten_webgl_init_context_attributes(attributes){var a=attributes>>2;for(var i=0;i<56>>2;++i){HEAP32[a+i]=0}HEAP32[a+(0>>2)]=HEAP32[a+(4>>2)]=HEAP32[a+(12>>2)]=HEAP32[a+(16>>2)]=HEAP32[a+(32>>2)]=HEAP32[a+(40>>2)]=1}function _emscripten_webgl_make_context_current(contextHandle){var success=GL.makeContextCurrent(contextHandle);return success?0:-5}function stringToUTF8OnStack(str){var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret}function convertI32PairToI53(lo,hi){return(lo>>>0)+hi*4294967296}var wasmTableMirror=[];function getWasmTableEntry(funcPtr){var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func}var WebGPU={errorCallback:function(callback,type,message,userdata){withStackSave(()=>{var messagePtr=stringToUTF8OnStack(message);getWasmTableEntry(callback)(type,messagePtr,userdata)})},initManagers:function(){if(WebGPU.mgrDevice)return;function Manager(){this.objects={};this.nextId=1;this.create=function(object,wrapper={}){var id=this.nextId++;wrapper.refcount=1;wrapper.object=object;this.objects[id]=wrapper;return id};this.get=function(id){if(!id)return undefined;var o=this.objects[id];return o.object};this.reference=function(id){var o=this.objects[id];o.refcount++};this.release=function(id){var o=this.objects[id];o.refcount--;if(o.refcount<=0){delete this.objects[id]}}}WebGPU.mgrSurface=WebGPU.mgrSurface||new Manager;WebGPU.mgrSwapChain=WebGPU.mgrSwapChain||new Manager;WebGPU.mgrAdapter=WebGPU.mgrAdapter||new Manager;WebGPU.mgrDevice=WebGPU.mgrDevice||new Manager;WebGPU.mgrQueue=WebGPU.mgrQueue||new Manager;WebGPU.mgrCommandBuffer=WebGPU.mgrCommandBuffer||new Manager;WebGPU.mgrCommandEncoder=WebGPU.mgrCommandEncoder||new Manager;WebGPU.mgrRenderPassEncoder=WebGPU.mgrRenderPassEncoder||new Manager;WebGPU.mgrComputePassEncoder=WebGPU.mgrComputePassEncoder||new Manager;WebGPU.mgrBindGroup=WebGPU.mgrBindGroup||new Manager;WebGPU.mgrBuffer=WebGPU.mgrBuffer||new Manager;WebGPU.mgrSampler=WebGPU.mgrSampler||new Manager;WebGPU.mgrTexture=WebGPU.mgrTexture||new Manager;WebGPU.mgrTextureView=WebGPU.mgrTextureView||new Manager;WebGPU.mgrQuerySet=WebGPU.mgrQuerySet||new Manager;WebGPU.mgrBindGroupLayout=WebGPU.mgrBindGroupLayout||new Manager;WebGPU.mgrPipelineLayout=WebGPU.mgrPipelineLayout||new Manager;WebGPU.mgrRenderPipeline=WebGPU.mgrRenderPipeline||new Manager;WebGPU.mgrComputePipeline=WebGPU.mgrComputePipeline||new Manager;WebGPU.mgrShaderModule=WebGPU.mgrShaderModule||new Manager;WebGPU.mgrRenderBundleEncoder=WebGPU.mgrRenderBundleEncoder||new Manager;WebGPU.mgrRenderBundle=WebGPU.mgrRenderBundle||new Manager},makeColor:function(ptr){return{\"r\":HEAPF64[ptr>>3],\"g\":HEAPF64[ptr+8>>3],\"b\":HEAPF64[ptr+16>>3],\"a\":HEAPF64[ptr+24>>3]}},makeExtent3D:function(ptr){return{\"width\":HEAPU32[ptr>>2],\"height\":HEAPU32[ptr+4>>2],\"depthOrArrayLayers\":HEAPU32[ptr+8>>2]}},makeOrigin3D:function(ptr){return{\"x\":HEAPU32[ptr>>2],\"y\":HEAPU32[ptr+4>>2],\"z\":HEAPU32[ptr+8>>2]}},makeImageCopyTexture:function(ptr){return{\"texture\":WebGPU.mgrTexture.get(HEAPU32[ptr+4>>2]),\"mipLevel\":HEAPU32[ptr+8>>2],\"origin\":WebGPU.makeOrigin3D(ptr+12),\"aspect\":WebGPU.TextureAspect[HEAPU32[ptr+24>>2]]}},makeTextureDataLayout:function(ptr){var bytesPerRow=HEAPU32[ptr+16>>2];var rowsPerImage=HEAPU32[ptr+20>>2];return{\"offset\":HEAPU32[ptr+4+8>>2]*4294967296+HEAPU32[ptr+8>>2],\"bytesPerRow\":bytesPerRow===4294967295?undefined:bytesPerRow,\"rowsPerImage\":rowsPerImage===4294967295?undefined:rowsPerImage}},makeImageCopyBuffer:function(ptr){var layoutPtr=ptr+8;var bufferCopyView=WebGPU.makeTextureDataLayout(layoutPtr);bufferCopyView[\"buffer\"]=WebGPU.mgrBuffer.get(HEAPU32[ptr+32>>2]);return bufferCopyView},makePipelineConstants:function(constantCount,constantsPtr){if(!constantCount)return;var constants={};for(var i=0;i<constantCount;++i){var entryPtr=constantsPtr+16*i;var key=UTF8ToString(HEAPU32[entryPtr+4>>2]);constants[key]=HEAPF64[entryPtr+8>>3]}return constants},makePipelineLayout:function(layoutPtr){if(!layoutPtr)return\"auto\";return WebGPU.mgrPipelineLayout.get(layoutPtr)},makeProgrammableStageDescriptor:function(ptr){if(!ptr)return undefined;return{\"module\":WebGPU.mgrShaderModule.get(HEAPU32[ptr+4>>2]),\"entryPoint\":UTF8ToString(HEAPU32[ptr+8>>2]),\"constants\":WebGPU.makePipelineConstants(HEAPU32[ptr+12>>2],HEAPU32[ptr+16>>2])}},DeviceLostReason:{undefined:0,destroyed:1},PreferredFormat:{rgba8unorm:18,bgra8unorm:23},AddressMode:[\"repeat\",\"mirror-repeat\",\"clamp-to-edge\"],BlendFactor:[\"zero\",\"one\",\"src\",\"one-minus-src\",\"src-alpha\",\"one-minus-src-alpha\",\"dst\",\"one-minus-dst\",\"dst-alpha\",\"one-minus-dst-alpha\",\"src-alpha-saturated\",\"constant\",\"one-minus-constant\"],BlendOperation:[\"add\",\"subtract\",\"reverse-subtract\",\"min\",\"max\"],BufferBindingType:[,\"uniform\",\"storage\",\"read-only-storage\"],CompareFunction:[,\"never\",\"less\",\"less-equal\",\"greater\",\"greater-equal\",\"equal\",\"not-equal\",\"always\"],CompilationInfoRequestStatus:[\"success\",\"error\",\"device-lost\",\"unknown\"],ComputePassTimestampLocation:[\"beginning\",\"end\"],CullMode:[\"none\",\"front\",\"back\"],ErrorFilter:[\"validation\",\"out-of-memory\"],FeatureName:[,\"depth-clip-control\",\"depth32float-stencil8\",\"timestamp-query\",\"pipeline-statistics-query\",\"texture-compression-bc\",\"texture-compression-etc2\",\"texture-compression-astc\",\"indirect-first-instance\"],FilterMode:[\"nearest\",\"linear\"],FrontFace:[\"ccw\",\"cw\"],IndexFormat:[,\"uint16\",\"uint32\"],LoadOp:[,\"clear\",\"load\"],PipelineStatisticName:[\"vertex-shader-invocations\",\"clipper-invocations\",\"clipper-primitives-out\",\"fragment-shader-invocations\",\"compute-shader-invocations\"],PowerPreference:[,\"low-power\",\"high-performance\"],PrimitiveTopology:[\"point-list\",\"line-list\",\"line-strip\",\"triangle-list\",\"triangle-strip\"],QueryType:[\"occlusion\",\"pipeline-statistics\",\"timestamp\"],RenderPassTimestampLocation:[\"beginning\",\"end\"],SamplerBindingType:[,\"filtering\",\"non-filtering\",\"comparison\"],StencilOperation:[\"keep\",\"zero\",\"replace\",\"invert\",\"increment-clamp\",\"decrement-clamp\",\"increment-wrap\",\"decrement-wrap\"],StorageTextureAccess:[,\"write-only\"],StoreOp:[,\"store\",\"discard\"],TextureAspect:[\"all\",\"stencil-only\",\"depth-only\"],TextureComponentType:[\"float\",\"sint\",\"uint\",\"depth-comparison\"],TextureDimension:[\"1d\",\"2d\",\"3d\"],TextureFormat:[,\"r8unorm\",\"r8snorm\",\"r8uint\",\"r8sint\",\"r16uint\",\"r16sint\",\"r16float\",\"rg8unorm\",\"rg8snorm\",\"rg8uint\",\"rg8sint\",\"r32float\",\"r32uint\",\"r32sint\",\"rg16uint\",\"rg16sint\",\"rg16float\",\"rgba8unorm\",\"rgba8unorm-srgb\",\"rgba8snorm\",\"rgba8uint\",\"rgba8sint\",\"bgra8unorm\",\"bgra8unorm-srgb\",\"rgb10a2unorm\",\"rg11b10ufloat\",\"rgb9e5ufloat\",\"rg32float\",\"rg32uint\",\"rg32sint\",\"rgba16uint\",\"rgba16sint\",\"rgba16float\",\"rgba32float\",\"rgba32uint\",\"rgba32sint\",\"stencil8\",\"depth16unorm\",\"depth24plus\",\"depth24plus-stencil8\",\"depth32float\",\"depth32float-stencil8\",\"bc1-rgba-unorm\",\"bc1-rgba-unorm-srgb\",\"bc2-rgba-unorm\",\"bc2-rgba-unorm-srgb\",\"bc3-rgba-unorm\",\"bc3-rgba-unorm-srgb\",\"bc4-r-unorm\",\"bc4-r-snorm\",\"bc5-rg-unorm\",\"bc5-rg-snorm\",\"bc6h-rgb-ufloat\",\"bc6h-rgb-float\",\"bc7-rgba-unorm\",\"bc7-rgba-unorm-srgb\",\"etc2-rgb8unorm\",\"etc2-rgb8unorm-srgb\",\"etc2-rgb8a1unorm\",\"etc2-rgb8a1unorm-srgb\",\"etc2-rgba8unorm\",\"etc2-rgba8unorm-srgb\",\"eac-r11unorm\",\"eac-r11snorm\",\"eac-rg11unorm\",\"eac-rg11snorm\",\"astc-4x4-unorm\",\"astc-4x4-unorm-srgb\",\"astc-5x4-unorm\",\"astc-5x4-unorm-srgb\",\"astc-5x5-unorm\",\"astc-5x5-unorm-srgb\",\"astc-6x5-unorm\",\"astc-6x5-unorm-srgb\",\"astc-6x6-unorm\",\"astc-6x6-unorm-srgb\",\"astc-8x5-unorm\",\"astc-8x5-unorm-srgb\",\"astc-8x6-unorm\",\"astc-8x6-unorm-srgb\",\"astc-8x8-unorm\",\"astc-8x8-unorm-srgb\",\"astc-10x5-unorm\",\"astc-10x5-unorm-srgb\",\"astc-10x6-unorm\",\"astc-10x6-unorm-srgb\",\"astc-10x8-unorm\",\"astc-10x8-unorm-srgb\",\"astc-10x10-unorm\",\"astc-10x10-unorm-srgb\",\"astc-12x10-unorm\",\"astc-12x10-unorm-srgb\",\"astc-12x12-unorm\",\"astc-12x12-unorm-srgb\"],TextureSampleType:[,\"float\",\"unfilterable-float\",\"depth\",\"sint\",\"uint\"],TextureViewDimension:[,\"1d\",\"2d\",\"2d-array\",\"cube\",\"cube-array\",\"3d\"],VertexFormat:[,\"uint8x2\",\"uint8x4\",\"sint8x2\",\"sint8x4\",\"unorm8x2\",\"unorm8x4\",\"snorm8x2\",\"snorm8x4\",\"uint16x2\",\"uint16x4\",\"sint16x2\",\"sint16x4\",\"unorm16x2\",\"unorm16x4\",\"snorm16x2\",\"snorm16x4\",\"float16x2\",\"float16x4\",\"float32\",\"float32x2\",\"float32x3\",\"float32x4\",\"uint32\",\"uint32x2\",\"uint32x3\",\"uint32x4\",\"sint32\",\"sint32x2\",\"sint32x3\",\"sint32x4\"],VertexStepMode:[\"vertex\",\"instance\"],FeatureNameString2Enum:{undefined:\"0\",\"depth-clip-control\":\"1\",\"depth32float-stencil8\":\"2\",\"timestamp-query\":\"3\",\"pipeline-statistics-query\":\"4\",\"texture-compression-bc\":\"5\",\"texture-compression-etc2\":\"6\",\"texture-compression-astc\":\"7\",\"indirect-first-instance\":\"8\"}};var JsValStore={values:{},next_id:1,add:function(js_val){var id;do{id=JsValStore.next_id++;if(JsValStore.next_id>2147483647)JsValStore.next_id=1}while(id in JsValStore.values);JsValStore.values[id]=js_val;return id},remove:function(id){delete JsValStore.values[id]},get:function(id){return JsValStore.values[id]}};function _emscripten_webgpu_export_bind_group_layout(handle){return JsValStore.add(WebGPU.mgrBindGroupLayout.get(handle))}function _emscripten_webgpu_export_device(handle){return JsValStore.add(WebGPU.mgrDevice.get(handle))}function _emscripten_webgpu_export_sampler(handle){return JsValStore.add(WebGPU.mgrSampler.get(handle))}function _emscripten_webgpu_export_texture(handle){return JsValStore.add(WebGPU.mgrTexture.get(handle))}function _emscripten_webgpu_get_device(){if(WebGPU.preinitializedDeviceId===undefined){var device=Module[\"preinitializedWebGPUDevice\"];var deviceWrapper={queueId:WebGPU.mgrQueue.create(device[\"queue\"])};WebGPU.preinitializedDeviceId=WebGPU.mgrDevice.create(device,deviceWrapper)}WebGPU.mgrDevice.reference(WebGPU.preinitializedDeviceId);return WebGPU.preinitializedDeviceId}function _emscripten_webgpu_import_bind_group(handle){return WebGPU.mgrBindGroup.create(JsValStore.get(handle))}function _emscripten_webgpu_import_texture(handle){return WebGPU.mgrTexture.create(JsValStore.get(handle))}function _emscripten_webgpu_release_js_handle(id){JsValStore.remove(id)}var ENV={};function getExecutableName(){return thisProgram||\"./this.program\"}function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof navigator==\"object\"&&navigator.languages&&navigator.languages[0]||\"C\").replace(\"-\",\"_\")+\".UTF-8\";var env={\"USER\":\"web_user\",\"LOGNAME\":\"web_user\",\"PATH\":\"/\",\"PWD\":\"/\",\"HOME\":\"/home/web_user\",\"LANG\":lang,\"_\":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings}function stringToAscii(str,buffer){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0}function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAPU32[penviron_buf_size>>2]=bufSize;return 0}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return e.errno}}function doReadv(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break;if(typeof offset!==\"undefined\"){offset+=curr}}return ret}function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return e.errno}}function convertI32PairToI53Checked(lo,hi){return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var offset=convertI32PairToI53Checked(offset_low,offset_high);if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return e.errno}}function doWritev(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!==\"undefined\"){offset+=curr}}return ret}function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS==\"undefined\"||!(e.name===\"ErrnoError\"))throw e;return e.errno}}function _getentropy(buffer,size){randomFill(HEAPU8.subarray(buffer,buffer+size));return 0}function _glActiveTexture(x0){GLctx.activeTexture(x0)}function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _glBindAttribLocation(program,index,name){GLctx.bindAttribLocation(GL.programs[program],index,UTF8ToString(name))}function _glBindBuffer(target,buffer){if(target==34962){GLctx.currentArrayBufferBinding=buffer}else if(target==34963){GLctx.currentElementArrayBufferBinding=buffer}if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])}function _glBindBufferBase(target,index,buffer){GLctx.bindBufferBase(target,index,GL.buffers[buffer])}function _glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(target,GL.framebuffers[framebuffer])}function _glBindTexture(target,texture){GLctx.bindTexture(target,GL.textures[texture])}function _glBindVertexArray(vao){GLctx.bindVertexArray(GL.vaos[vao]);var ibo=GLctx.getParameter(34965);GLctx.currentElementArrayBufferBinding=ibo?ibo.name|0:0}function _glBlendEquation(x0){GLctx.blendEquation(x0)}function _glBlendFunc(x0,x1){GLctx.blendFunc(x0,x1)}function _glBufferData(target,size,data,usage){if(GL.currentContext.version>=2){if(data&&size){GLctx.bufferData(target,HEAPU8,usage,data,size)}else{GLctx.bufferData(target,size,usage)}}else{GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}}function _glClear(x0){GLctx.clear(x0)}function _glClearColor(x0,x1,x2,x3){GLctx.clearColor(x0,x1,x2,x3)}function _glClientWaitSync(sync,flags,timeout_low,timeout_high){var timeout=convertI32PairToI53(timeout_low,timeout_high);return GLctx.clientWaitSync(GL.syncs[sync],flags,timeout)}function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;program.maxUniformLength=program.maxAttributeLength=program.maxUniformBlockNameLength=0;program.uniformIdCounter=1;GL.programs[id]=program;return id}function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GLctx.currentArrayBufferBinding)GLctx.currentArrayBufferBinding=0;if(id==GLctx.currentElementArrayBufferBinding)GLctx.currentElementArrayBufferBinding=0;if(id==GLctx.currentPixelPackBufferBinding)GLctx.currentPixelPackBufferBinding=0;if(id==GLctx.currentPixelUnpackBufferBinding)GLctx.currentPixelUnpackBufferBinding=0}}function _glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var id=HEAP32[framebuffers+i*4>>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}}function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null}function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _glDeleteSync(id){if(!id)return;var sync=GL.syncs[id];if(!sync){GL.recordError(1281);return}GLctx.deleteSync(sync);sync.name=0;GL.syncs[id]=null}function _glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _glDeleteVertexArrays(n,vaos){for(var i=0;i<n;i++){var id=HEAP32[vaos+i*4>>2];GLctx.deleteVertexArray(GL.vaos[id]);GL.vaos[id]=null}}function _glDisable(x0){GLctx.disable(x0)}function _glDisableVertexAttribArray(index){var cb=GL.currentContext.clientBuffers[index];cb.enabled=false;GLctx.disableVertexAttribArray(index)}function _glDrawArrays(mode,first,count){GL.preDrawHandleClientVertexAttribBindings(first+count);GLctx.drawArrays(mode,first,count);GL.postDrawHandleClientVertexAttribBindings()}var tempFixedLengthArray=[];function _glDrawBuffers(n,bufs){var bufArray=tempFixedLengthArray[n];for(var i=0;i<n;i++){bufArray[i]=HEAP32[bufs+i*4>>2]}GLctx.drawBuffers(bufArray)}function _glEnable(x0){GLctx.enable(x0)}function _glEnableVertexAttribArray(index){var cb=GL.currentContext.clientBuffers[index];cb.enabled=true;GLctx.enableVertexAttribArray(index)}function _glFenceSync(condition,flags){var sync=GLctx.fenceSync(condition,flags);if(sync){var id=GL.getNewId(GL.syncs);sync.name=id;GL.syncs[id]=sync;return id}return 0}function _glFinish(){GLctx.finish()}function _glFlush(){GLctx.flush()}function _glFramebufferTexture2D(target,attachment,textarget,texture,level){GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)}function _glFramebufferTextureLayer(target,attachment,texture,level,layer){GLctx.framebufferTextureLayer(target,attachment,GL.textures[texture],level,layer)}function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0;i<n;i++){var buffer=GLctx[createFunction]();var id=buffer&&GL.getNewId(objectTable);if(buffer){buffer.name=id;objectTable[id]=buffer}else{GL.recordError(1282)}HEAP32[buffers+i*4>>2]=id}}function _glGenBuffers(n,buffers){__glGenObject(n,buffers,\"createBuffer\",GL.buffers)}function _glGenFramebuffers(n,ids){__glGenObject(n,ids,\"createFramebuffer\",GL.framebuffers)}function _glGenTextures(n,textures){__glGenObject(n,textures,\"createTexture\",GL.textures)}function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,\"createVertexArray\",GL.vaos)}function _glGetAttribLocation(program,name){return GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name))}function _glGetError(){var error=GLctx.getError()||GL.lastError;GL.lastError=0;return error}function writeI53ToI64(ptr,num){HEAPU32[ptr>>2]=num;HEAPU32[ptr+4>>2]=(num-HEAPU32[ptr>>2])/4294967296}function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=0&&type!=1){GL.recordError(1280)}return;case 34814:case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats?formats.length:0;break;case 33309:if(GL.currentContext.version<2){GL.recordError(1282);return}var exts=GLctx.getSupportedExtensions()||[];ret=2*exts.length;break;case 33307:case 33308:if(GL.currentContext.version<2){GL.recordError(1280);return}ret=name_==33307?3:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case\"number\":ret=result;break;case\"boolean\":ret=result?1:0;break;case\"string\":GL.recordError(1280);return;case\"object\":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:{ret=0;break}default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i<result.length;++i){switch(type){case 0:HEAP32[p+i*4>>2]=result[i];break;case 2:HEAPF32[p+i*4>>2]=result[i];break;case 4:HEAP8[p+i>>0]=result[i]?1:0;break}}return}else{try{ret=result.name|0}catch(e){GL.recordError(1280);err(\"GL_INVALID_ENUM in glGet\"+type+\"v: Unknown object returned from WebGL getParameter(\"+name_+\")! (error: \"+e+\")\");return}}break;default:GL.recordError(1280);err(\"GL_INVALID_ENUM in glGet\"+type+\"v: Native code calling glGet\"+type+\"v(\"+name_+\") and it returns \"+result+\" of type \"+typeof result+\"!\");return}}switch(type){case 1:writeI53ToI64(p,ret);break;case 0:HEAP32[p>>2]=ret;break;case 2:HEAPF32[p>>2]=ret;break;case 4:HEAP8[p>>0]=ret?1:0;break}}function _glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,0)}function _glGetProgramiv(program,pname,p){if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}program=GL.programs[program];if(pname==35716){var log=GLctx.getProgramInfoLog(program);if(log===null)log=\"(unknown error)\";HEAP32[p>>2]=log.length+1}else if(pname==35719){if(!program.maxUniformLength){for(var i=0;i<GLctx.getProgramParameter(program,35718);++i){program.maxUniformLength=Math.max(program.maxUniformLength,GLctx.getActiveUniform(program,i).name.length+1)}}HEAP32[p>>2]=program.maxUniformLength}else if(pname==35722){if(!program.maxAttributeLength){for(var i=0;i<GLctx.getProgramParameter(program,35721);++i){program.maxAttributeLength=Math.max(program.maxAttributeLength,GLctx.getActiveAttrib(program,i).name.length+1)}}HEAP32[p>>2]=program.maxAttributeLength}else if(pname==35381){if(!program.maxUniformBlockNameLength){for(var i=0;i<GLctx.getProgramParameter(program,35382);++i){program.maxUniformBlockNameLength=Math.max(program.maxUniformBlockNameLength,GLctx.getActiveUniformBlockName(program,i).length+1)}}HEAP32[p>>2]=program.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(program,pname)}}function _glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log=\"(unknown error)\";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _glGetShaderiv(shader,pname,p){if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log=\"(unknown error)\";var logLength=log?log.length+1:0;HEAP32[p>>2]=logLength}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source?source.length+1:0;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}}function _glGetString(name_){var ret=GL.stringCache[name_];if(!ret){switch(name_){case 7939:var exts=GLctx.getSupportedExtensions()||[];exts=exts.concat(exts.map(function(e){return\"GL_\"+e}));ret=stringToNewUTF8(exts.join(\" \"));break;case 7936:case 7937:case 37445:case 37446:var s=GLctx.getParameter(name_);if(!s){GL.recordError(1280)}ret=s&&stringToNewUTF8(s);break;case 7938:var glVersion=GLctx.getParameter(7938);if(GL.currentContext.version>=2)glVersion=\"OpenGL ES 3.0 (\"+glVersion+\")\";else{glVersion=\"OpenGL ES 2.0 (\"+glVersion+\")\"}ret=stringToNewUTF8(glVersion);break;case 35724:var glslVersion=GLctx.getParameter(35724);var ver_re=/^WebGL GLSL ES ([0-9]\\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+\"0\";glslVersion=\"OpenGL ES GLSL ES \"+ver_num[1]+\" (\"+glslVersion+\")\"}ret=stringToNewUTF8(glslVersion);break;default:GL.recordError(1280)}GL.stringCache[name_]=ret}return ret}function _glGetUniformBlockIndex(program,uniformBlockName){return GLctx.getUniformBlockIndex(GL.programs[program],UTF8ToString(uniformBlockName))}function jstoi_q(str){return parseInt(str)}function webglGetLeftBracePos(name){return name.slice(-1)==\"]\"&&name.lastIndexOf(\"[\")}function webglPrepareUniformLocationsBeforeFirstUse(program){var uniformLocsById=program.uniformLocsById,uniformSizeAndIdsByName=program.uniformSizeAndIdsByName,i,j;if(!uniformLocsById){program.uniformLocsById=uniformLocsById={};program.uniformArrayNamesById={};for(i=0;i<GLctx.getProgramParameter(program,35718);++i){var u=GLctx.getActiveUniform(program,i);var nm=u.name;var sz=u.size;var lb=webglGetLeftBracePos(nm);var arrayName=lb>0?nm.slice(0,lb):nm;var id=program.uniformIdCounter;program.uniformIdCounter+=sz;uniformSizeAndIdsByName[arrayName]=[sz,id];for(j=0;j<sz;++j){uniformLocsById[id]=j;program.uniformArrayNamesById[id++]=arrayName}}}}function _glGetUniformLocation(program,name){name=UTF8ToString(name);if(program=GL.programs[program]){webglPrepareUniformLocationsBeforeFirstUse(program);var uniformLocsById=program.uniformLocsById;var arrayIndex=0;var uniformBaseName=name;var leftBrace=webglGetLeftBracePos(name);if(leftBrace>0){arrayIndex=jstoi_q(name.slice(leftBrace+1))>>>0;uniformBaseName=name.slice(0,leftBrace)}var sizeAndId=program.uniformSizeAndIdsByName[uniformBaseName];if(sizeAndId&&arrayIndex<sizeAndId[0]){arrayIndex+=sizeAndId[1];if(uniformLocsById[arrayIndex]=uniformLocsById[arrayIndex]||GLctx.getUniformLocation(program,name)){return arrayIndex}}}else{GL.recordError(1281)}return-1}function _glLinkProgram(program){program=GL.programs[program];GLctx.linkProgram(program);program.uniformLocsById=0;program.uniformSizeAndIdsByName={}}function _glPixelStorei(pname,param){if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)}function computeUnpackAlignedImageSize(width,height,sizePerPixel,alignment){function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height*alignedRowSize}function colorChannelsInGlTextureFormat(format){var colorChannels={5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4};return colorChannels[format-6402]||1}function heapObjectForWebGLType(type){type-=5120;if(type==0)return HEAP8;if(type==1)return HEAPU8;if(type==2)return HEAP16;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922||type==28520||type==30779||type==30782)return HEAPU32;return HEAPU16}function heapAccessShiftForWebGLHeap(heap){return 31-Math.clz32(heap.BYTES_PER_ELEMENT)}function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat){var heap=heapObjectForWebGLType(type);var shift=heapAccessShiftForWebGLHeap(heap);var byteSize=1<<shift;var sizePerPixel=colorChannelsInGlTextureFormat(format)*byteSize;var bytes=computeUnpackAlignedImageSize(width,height,sizePerPixel,GL.unpackAlignment);return heap.subarray(pixels>>shift,pixels+bytes>>shift)}function _glReadPixels(x,y,width,height,format,type,pixels){if(GL.currentContext.version>=2){if(GLctx.currentPixelPackBufferBinding){GLctx.readPixels(x,y,width,height,format,type,pixels)}else{var heap=heapObjectForWebGLType(type);GLctx.readPixels(x,y,width,height,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}return}var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)}function _glTexParameterf(x0,x1,x2){GLctx.texParameterf(x0,x1,x2)}function _glTexParameterfv(target,pname,params){var param=HEAPF32[params>>2];GLctx.texParameterf(target,pname,param)}function _glTexParameteri(x0,x1,x2){GLctx.texParameteri(x0,x1,x2)}function _glTexStorage2D(x0,x1,x2,x3,x4){GLctx.texStorage2D(x0,x1,x2,x3,x4)}function _glTexStorage3D(x0,x1,x2,x3,x4,x5){GLctx.texStorage3D(x0,x1,x2,x3,x4,x5)}function _glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels){if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)}function _glTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,null)}}function webglGetUniformLocation(location){var p=GLctx.currentProgram;if(p){var webglLoc=p.uniformLocsById[location];if(typeof webglLoc==\"number\"){p.uniformLocsById[location]=webglLoc=GLctx.getUniformLocation(p,p.uniformArrayNamesById[location]+(webglLoc>0?\"[\"+webglLoc+\"]\":\"\"))}return webglLoc}else{GL.recordError(1282)}}function _glUniform1f(location,v0){GLctx.uniform1f(webglGetUniformLocation(location),v0)}function _glUniform1i(location,v0){GLctx.uniform1i(webglGetUniformLocation(location),v0)}function _glUniform2f(location,v0,v1){GLctx.uniform2f(webglGetUniformLocation(location),v0,v1)}var miniTempWebGLFloatBuffers=[];function _glUniform2fv(location,count,value){if(GL.currentContext.version>=2){count&&GLctx.uniform2fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*2);return}if(count<=144){var view=miniTempWebGLFloatBuffers[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(webglGetUniformLocation(location),view)}function _glUniform3f(location,v0,v1,v2){GLctx.uniform3f(webglGetUniformLocation(location),v0,v1,v2)}function _glUniform4fv(location,count,value){if(GL.currentContext.version>=2){count&&GLctx.uniform4fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLFloatBuffers[4*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<4*count;i+=4){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(webglGetUniformLocation(location),view)}var miniTempWebGLIntBuffers=[];function _glUniform4iv(location,count,value){if(GL.currentContext.version>=2){count&&GLctx.uniform4iv(webglGetUniformLocation(location),HEAP32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLIntBuffers[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2];view[i+3]=HEAP32[value+(4*i+12)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4iv(webglGetUniformLocation(location),view)}function _glUniformBlockBinding(program,uniformBlockIndex,uniformBlockBinding){program=GL.programs[program];GLctx.uniformBlockBinding(program,uniformBlockIndex,uniformBlockBinding)}function _glUniformMatrix4fv(location,count,transpose,value){if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*16);return}if(count<=18){var view=miniTempWebGLFloatBuffers[16*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<16*count;i+=16){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3];view[i+4]=heap[dst+4];view[i+5]=heap[dst+5];view[i+6]=heap[dst+6];view[i+7]=heap[dst+7];view[i+8]=heap[dst+8];view[i+9]=heap[dst+9];view[i+10]=heap[dst+10];view[i+11]=heap[dst+11];view[i+12]=heap[dst+12];view[i+13]=heap[dst+13];view[i+14]=heap[dst+14];view[i+15]=heap[dst+15]}}else{var view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,view)}function _glUseProgram(program){program=GL.programs[program];GLctx.useProgram(program);GLctx.currentProgram=program}function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){var cb=GL.currentContext.clientBuffers[index];if(!GLctx.currentArrayBufferBinding){cb.size=size;cb.type=type;cb.normalized=normalized;cb.stride=stride;cb.ptr=ptr;cb.clientside=true;cb.vertexAttribPointerAdaptor=function(index,size,type,normalized,stride,ptr){this.vertexAttribPointer(index,size,type,normalized,stride,ptr)};return}cb.clientside=false;GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _glViewport(x0,x1,x2,x3){GLctx.viewport(x0,x1,x2,x3)}function _mediapipe_find_canvas_event_target(canvasSelector){let target=findCanvasEventTarget(canvasSelector);if(Module&&!target){target=Module.canvasWebGpu}return Emval.toHandle(target)}function _mediapipe_webgl_tex_image_drawable(drawableHandle){const drawable=Emval.toValue(drawableHandle);GLctx.texImage2D(GLctx.TEXTURE_2D,0,GLctx.RGBA,GLctx.RGBA,GLctx.UNSIGNED_BYTE,drawable)}function arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):\"\"};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={\"%c\":\"%a %b %d %H:%M:%S %Y\",\"%D\":\"%m/%d/%y\",\"%F\":\"%Y-%m-%d\",\"%h\":\"%b\",\"%r\":\"%I:%M:%S %p\",\"%R\":\"%H:%M\",\"%T\":\"%H:%M:%S\",\"%x\":\"%m/%d/%y\",\"%X\":\"%H:%M:%S\",\"%Ec\":\"%c\",\"%EC\":\"%C\",\"%Ex\":\"%m/%d/%y\",\"%EX\":\"%H:%M:%S\",\"%Ey\":\"%y\",\"%EY\":\"%Y\",\"%Od\":\"%d\",\"%Oe\":\"%e\",\"%OH\":\"%H\",\"%OI\":\"%I\",\"%Om\":\"%m\",\"%OM\":\"%M\",\"%OS\":\"%S\",\"%Ou\":\"%u\",\"%OU\":\"%U\",\"%OV\":\"%V\",\"%Ow\":\"%w\",\"%OW\":\"%W\",\"%Oy\":\"%y\"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,\"g\"),EXPANSION_RULES_1[rule])}var WEEKDAYS=[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"];var MONTHS=[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"];function leadingSomething(value,digits,character){var str=typeof value==\"number\"?value.toString():value||\"\";while(str.length<digits){str=character[0]+str}return str}function leadingNulls(value,digits){return leadingSomething(value,digits,\"0\")}function compareByDay(date1,date2){function sgn(value){return value<0?-1:value>0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={\"%a\":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},\"%A\":function(date){return WEEKDAYS[date.tm_wday]},\"%b\":function(date){return MONTHS[date.tm_mon].substring(0,3)},\"%B\":function(date){return MONTHS[date.tm_mon]},\"%C\":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},\"%d\":function(date){return leadingNulls(date.tm_mday,2)},\"%e\":function(date){return leadingSomething(date.tm_mday,2,\" \")},\"%g\":function(date){return getWeekBasedYear(date).toString().substring(2)},\"%G\":function(date){return getWeekBasedYear(date)},\"%H\":function(date){return leadingNulls(date.tm_hour,2)},\"%I\":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},\"%j\":function(date){return leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3)},\"%m\":function(date){return leadingNulls(date.tm_mon+1,2)},\"%M\":function(date){return leadingNulls(date.tm_min,2)},\"%n\":function(){return\"\\n\"},\"%p\":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return\"AM\"}return\"PM\"},\"%S\":function(date){return leadingNulls(date.tm_sec,2)},\"%t\":function(){return\"\\t\"},\"%u\":function(date){return date.tm_wday||7},\"%U\":function(date){var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},\"%V\":function(date){var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},\"%w\":function(date){return date.tm_wday},\"%W\":function(date){var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},\"%y\":function(date){return(date.tm_year+1900).toString().substring(2)},\"%Y\":function(date){return date.tm_year+1900},\"%z\":function(date){var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?\"+\":\"-\")+String(\"0000\"+off).slice(-4)},\"%Z\":function(date){return date.tm_zone},\"%%\":function(){return\"%\"}};pattern=pattern.replace(/%%/g,\"\\0\\0\");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,\"g\"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\\0\\0/g,\"%\");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm,loc){return _strftime(s,maxsize,format,tm)}function _wgpuBindGroupLayoutRelease(id){WebGPU.mgrBindGroupLayout.release(id)}function _wgpuBindGroupRelease(id){WebGPU.mgrBindGroup.release(id)}function _wgpuBufferGetMappedRange(bufferId,offset,size){var bufferWrapper=WebGPU.mgrBuffer.objects[bufferId];if(size===0)warnOnce(\"getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE\");size=size>>>0;if(size===4294967295)size=undefined;if(bufferWrapper.mapMode!==2){return 0}var mapped;try{mapped=bufferWrapper.object[\"getMappedRange\"](offset,size)}catch(ex){return 0}var data=_memalign(16,mapped.byteLength);HEAPU8.fill(0,data,mapped.byteLength);bufferWrapper.onUnmap.push(()=>{new Uint8Array(mapped).set(HEAPU8.subarray(data,data+mapped.byteLength));_free(data)});return data}function _wgpuBufferReference(id){WebGPU.mgrBuffer.reference(id)}function _wgpuBufferRelease(id){WebGPU.mgrBuffer.release(id)}function _wgpuBufferUnmap(bufferId){var bufferWrapper=WebGPU.mgrBuffer.objects[bufferId];if(!bufferWrapper.onUnmap){return}for(var i=0;i<bufferWrapper.onUnmap.length;++i){bufferWrapper.onUnmap[i]()}bufferWrapper.onUnmap=undefined;bufferWrapper.object[\"unmap\"]()}function _wgpuCommandBufferRelease(id){WebGPU.mgrCommandBuffer.release(id)}function _wgpuCommandEncoderBeginComputePass(encoderId,descriptor){var desc;function makeComputePassTimestampWrite(twPtr){return{\"querySet\":WebGPU.mgrQuerySet.get(HEAPU32[twPtr>>2]),\"queryIndex\":HEAPU32[twPtr+4>>2],\"location\":WebGPU.ComputePassTimestampLocation[HEAPU32[twPtr+8>>2]]}}function makeComputePassTimestampWrites(count,twPtr){var timestampWrites=[];for(var i=0;i<count;++i){timestampWrites.push(makeComputePassTimestampWrite(twPtr+12*i))}return timestampWrites}if(descriptor){desc={};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var timestampWriteCount=HEAPU32[descriptor+8>>2];if(timestampWriteCount){desc[\"timestampWrites\"]=makeComputePassTimestampWrites(timestampWriteCount,HEAPU32[descriptor+12>>2])}}var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);return WebGPU.mgrComputePassEncoder.create(commandEncoder[\"beginComputePass\"](desc))}function _wgpuCommandEncoderBeginRenderPass(encoderId,descriptor){function makeColorAttachment(caPtr){var viewPtr=HEAPU32[caPtr>>2];if(viewPtr===0){return undefined}var loadOpInt=HEAPU32[caPtr+8>>2];var storeOpInt=HEAPU32[caPtr+12>>2];var clearValue=WebGPU.makeColor(caPtr+16);return{\"view\":WebGPU.mgrTextureView.get(viewPtr),\"resolveTarget\":WebGPU.mgrTextureView.get(HEAPU32[caPtr+4>>2]),\"clearValue\":clearValue,\"loadOp\":WebGPU.LoadOp[loadOpInt],\"storeOp\":WebGPU.StoreOp[storeOpInt]}}function makeColorAttachments(count,caPtr){var attachments=[];for(var i=0;i<count;++i){attachments.push(makeColorAttachment(caPtr+48*i))}return attachments}function makeDepthStencilAttachment(dsaPtr){if(dsaPtr===0)return undefined;return{\"view\":WebGPU.mgrTextureView.get(HEAPU32[dsaPtr>>2]),\"depthClearValue\":HEAPF32[dsaPtr+12>>2],\"depthLoadOp\":WebGPU.LoadOp[HEAPU32[dsaPtr+4>>2]],\"depthStoreOp\":WebGPU.StoreOp[HEAPU32[dsaPtr+8>>2]],\"depthReadOnly\":HEAP8[dsaPtr+16>>0]!==0,\"stencilClearValue\":HEAPU32[dsaPtr+28>>2],\"stencilLoadOp\":WebGPU.LoadOp[HEAPU32[dsaPtr+20>>2]],\"stencilStoreOp\":WebGPU.StoreOp[HEAPU32[dsaPtr+24>>2]],\"stencilReadOnly\":HEAP8[dsaPtr+32>>0]!==0}}function makeRenderPassTimestampWrite(twPtr){return{\"querySet\":WebGPU.mgrQuerySet.get(HEAPU32[twPtr>>2]),\"queryIndex\":HEAPU32[twPtr+4>>2],\"location\":WebGPU.RenderPassTimestampLocation[HEAPU32[twPtr+8>>2]]}}function makeRenderPassTimestampWrites(count,twPtr){var timestampWrites=[];for(var i=0;i<count;++i){timestampWrites.push(makeRenderPassTimestampWrite(twPtr+12*i))}return timestampWrites}function makeRenderPassDescriptor(descriptor){var nextInChainPtr=HEAPU32[descriptor>>2];var maxDrawCount=undefined;if(nextInChainPtr!==0){var sType=HEAPU32[nextInChainPtr+4>>2];var renderPassDescriptorMaxDrawCount=nextInChainPtr;maxDrawCount=HEAPU32[renderPassDescriptorMaxDrawCount+4+8>>2]*4294967296+HEAPU32[renderPassDescriptorMaxDrawCount+8>>2]}var desc={\"label\":undefined,\"colorAttachments\":makeColorAttachments(HEAPU32[descriptor+8>>2],HEAPU32[descriptor+12>>2]),\"depthStencilAttachment\":makeDepthStencilAttachment(HEAPU32[descriptor+16>>2]),\"occlusionQuerySet\":WebGPU.mgrQuerySet.get(HEAPU32[descriptor+20>>2]),\"maxDrawCount\":maxDrawCount};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var timestampWriteCount=HEAPU32[descriptor+24>>2];if(timestampWriteCount){desc[\"timestampWrites\"]=makeRenderPassTimestampWrites(timestampWriteCount,HEAPU32[descriptor+28>>2])}return desc}var desc=makeRenderPassDescriptor(descriptor);var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);return WebGPU.mgrRenderPassEncoder.create(commandEncoder[\"beginRenderPass\"](desc))}function _wgpuCommandEncoderCopyBufferToTexture(encoderId,srcPtr,dstPtr,copySizePtr){var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);var copySize=WebGPU.makeExtent3D(copySizePtr);commandEncoder[\"copyBufferToTexture\"](WebGPU.makeImageCopyBuffer(srcPtr),WebGPU.makeImageCopyTexture(dstPtr),copySize)}function _wgpuCommandEncoderCopyTextureToTexture(encoderId,srcPtr,dstPtr,copySizePtr){var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);var copySize=WebGPU.makeExtent3D(copySizePtr);commandEncoder[\"copyTextureToTexture\"](WebGPU.makeImageCopyTexture(srcPtr),WebGPU.makeImageCopyTexture(dstPtr),copySize)}function _wgpuCommandEncoderFinish(encoderId){var commandEncoder=WebGPU.mgrCommandEncoder.get(encoderId);return WebGPU.mgrCommandBuffer.create(commandEncoder[\"finish\"]())}function _wgpuCommandEncoderRelease(id){WebGPU.mgrCommandEncoder.release(id)}function _wgpuComputePassEncoderDispatchWorkgroups(passId,x,y,z){var pass=WebGPU.mgrComputePassEncoder.get(passId);pass[\"dispatchWorkgroups\"](x,y,z)}function _wgpuComputePassEncoderEnd(passId){var pass=WebGPU.mgrComputePassEncoder.get(passId);pass[\"end\"]()}function _wgpuComputePassEncoderRelease(id){WebGPU.mgrComputePassEncoder.release(id)}function _wgpuComputePassEncoderSetBindGroup(passId,groupIndex,groupId,dynamicOffsetCount,dynamicOffsetsPtr){var pass=WebGPU.mgrComputePassEncoder.get(passId);var group=WebGPU.mgrBindGroup.get(groupId);if(dynamicOffsetCount==0){pass[\"setBindGroup\"](groupIndex,group)}else{var offsets=[];for(var i=0;i<dynamicOffsetCount;i++,dynamicOffsetsPtr+=4){offsets.push(HEAPU32[dynamicOffsetsPtr>>2])}pass[\"setBindGroup\"](groupIndex,group,offsets)}}function _wgpuComputePassEncoderSetPipeline(passId,pipelineId){var pass=WebGPU.mgrComputePassEncoder.get(passId);var pipeline=WebGPU.mgrComputePipeline.get(pipelineId);pass[\"setPipeline\"](pipeline)}function _wgpuComputePipelineGetBindGroupLayout(pipelineId,groupIndex){var pipeline=WebGPU.mgrComputePipeline.get(pipelineId);return WebGPU.mgrBindGroupLayout.create(pipeline[\"getBindGroupLayout\"](groupIndex))}function _wgpuComputePipelineRelease(id){WebGPU.mgrComputePipeline.release(id)}function _wgpuDeviceCreateBindGroup(deviceId,descriptor){function makeEntry(entryPtr){var bufferId=HEAPU32[entryPtr+8>>2];var samplerId=HEAPU32[entryPtr+32>>2];var textureViewId=HEAPU32[entryPtr+36>>2];var binding=HEAPU32[entryPtr+4>>2];if(bufferId){var size_low=HEAP32[entryPtr+24>>2];var size_high=HEAP32[entryPtr+28>>2];var size=size_high===-1&&size_low===-1?undefined:convertI32PairToI53(size_low,size_high);return{\"binding\":binding,\"resource\":{\"buffer\":WebGPU.mgrBuffer.get(bufferId),\"offset\":HEAPU32[entryPtr+4+16>>2]*4294967296+HEAPU32[entryPtr+16>>2],\"size\":size}}}else if(samplerId){return{\"binding\":binding,\"resource\":WebGPU.mgrSampler.get(samplerId)}}else{return{\"binding\":binding,\"resource\":WebGPU.mgrTextureView.get(textureViewId)}}}function makeEntries(count,entriesPtrs){var entries=[];for(var i=0;i<count;++i){entries.push(makeEntry(entriesPtrs+40*i))}return entries}var desc={\"label\":undefined,\"layout\":WebGPU.mgrBindGroupLayout.get(HEAPU32[descriptor+8>>2]),\"entries\":makeEntries(HEAPU32[descriptor+12>>2],HEAPU32[descriptor+16>>2])};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrBindGroup.create(device[\"createBindGroup\"](desc))}function _wgpuDeviceCreateBuffer(deviceId,descriptor){var mappedAtCreation=HEAP8[descriptor+24>>0]!==0;var desc={\"label\":undefined,\"usage\":HEAPU32[descriptor+8>>2],\"size\":HEAPU32[descriptor+4+16>>2]*4294967296+HEAPU32[descriptor+16>>2],\"mappedAtCreation\":mappedAtCreation};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);var bufferWrapper={};var id=WebGPU.mgrBuffer.create(device[\"createBuffer\"](desc),bufferWrapper);if(mappedAtCreation){bufferWrapper.mapMode=2;bufferWrapper.onUnmap=[]}return id}function _wgpuDeviceCreateCommandEncoder(deviceId,descriptor){var desc;if(descriptor){desc={\"label\":undefined};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr)}var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrCommandEncoder.create(device[\"createCommandEncoder\"](desc))}function _wgpuDeviceCreateComputePipeline(deviceId,descriptor){var desc={\"label\":undefined,\"layout\":WebGPU.makePipelineLayout(HEAPU32[descriptor+8>>2]),\"compute\":WebGPU.makeProgrammableStageDescriptor(descriptor+12)};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrComputePipeline.create(device[\"createComputePipeline\"](desc))}function _wgpuDeviceCreateRenderPipeline(deviceId,descriptor){function makePrimitiveState(rsPtr){if(!rsPtr)return undefined;return{\"topology\":WebGPU.PrimitiveTopology[HEAPU32[rsPtr+4>>2]],\"stripIndexFormat\":WebGPU.IndexFormat[HEAPU32[rsPtr+8>>2]],\"frontFace\":WebGPU.FrontFace[HEAPU32[rsPtr+12>>2]],\"cullMode\":WebGPU.CullMode[HEAPU32[rsPtr+16>>2]]}}function makeBlendComponent(bdPtr){if(!bdPtr)return undefined;return{\"operation\":WebGPU.BlendOperation[HEAPU32[bdPtr>>2]],\"srcFactor\":WebGPU.BlendFactor[HEAPU32[bdPtr+4>>2]],\"dstFactor\":WebGPU.BlendFactor[HEAPU32[bdPtr+8>>2]]}}function makeBlendState(bsPtr){if(!bsPtr)return undefined;return{\"alpha\":makeBlendComponent(bsPtr+12),\"color\":makeBlendComponent(bsPtr+0)}}function makeColorState(csPtr){var formatInt=HEAPU32[csPtr+4>>2];return formatInt===0?undefined:{\"format\":WebGPU.TextureFormat[formatInt],\"blend\":makeBlendState(HEAPU32[csPtr+8>>2]),\"writeMask\":HEAPU32[csPtr+12>>2]}}function makeColorStates(count,csArrayPtr){var states=[];for(var i=0;i<count;++i){states.push(makeColorState(csArrayPtr+16*i))}return states}function makeStencilStateFace(ssfPtr){return{\"compare\":WebGPU.CompareFunction[HEAPU32[ssfPtr>>2]],\"failOp\":WebGPU.StencilOperation[HEAPU32[ssfPtr+4>>2]],\"depthFailOp\":WebGPU.StencilOperation[HEAPU32[ssfPtr+8>>2]],\"passOp\":WebGPU.StencilOperation[HEAPU32[ssfPtr+12>>2]]}}function makeDepthStencilState(dssPtr){if(!dssPtr)return undefined;return{\"format\":WebGPU.TextureFormat[HEAPU32[dssPtr+4>>2]],\"depthWriteEnabled\":HEAP8[dssPtr+8>>0]!==0,\"depthCompare\":WebGPU.CompareFunction[HEAPU32[dssPtr+12>>2]],\"stencilFront\":makeStencilStateFace(dssPtr+16),\"stencilBack\":makeStencilStateFace(dssPtr+32),\"stencilReadMask\":HEAPU32[dssPtr+48>>2],\"stencilWriteMask\":HEAPU32[dssPtr+52>>2],\"depthBias\":HEAPU32[dssPtr+56>>2],\"depthBiasSlopeScale\":HEAPF32[dssPtr+60>>2],\"depthBiasClamp\":HEAPF32[dssPtr+64>>2]}}function makeVertexAttribute(vaPtr){return{\"format\":WebGPU.VertexFormat[HEAPU32[vaPtr>>2]],\"offset\":HEAPU32[vaPtr+4+8>>2]*4294967296+HEAPU32[vaPtr+8>>2],\"shaderLocation\":HEAPU32[vaPtr+16>>2]}}function makeVertexAttributes(count,vaArrayPtr){var vas=[];for(var i=0;i<count;++i){vas.push(makeVertexAttribute(vaArrayPtr+i*24))}return vas}function makeVertexBuffer(vbPtr){if(!vbPtr)return undefined;var stepModeInt=HEAPU32[vbPtr+8>>2];return stepModeInt===2?null:{\"arrayStride\":HEAPU32[vbPtr+4>>2]*4294967296+HEAPU32[vbPtr>>2],\"stepMode\":WebGPU.VertexStepMode[stepModeInt],\"attributes\":makeVertexAttributes(HEAPU32[vbPtr+12>>2],HEAPU32[vbPtr+16>>2])}}function makeVertexBuffers(count,vbArrayPtr){if(!count)return undefined;var vbs=[];for(var i=0;i<count;++i){vbs.push(makeVertexBuffer(vbArrayPtr+i*24))}return vbs}function makeVertexState(viPtr){if(!viPtr)return undefined;return{\"module\":WebGPU.mgrShaderModule.get(HEAPU32[viPtr+4>>2]),\"entryPoint\":UTF8ToString(HEAPU32[viPtr+8>>2]),\"constants\":WebGPU.makePipelineConstants(HEAPU32[viPtr+12>>2],HEAPU32[viPtr+16>>2]),\"buffers\":makeVertexBuffers(HEAPU32[viPtr+20>>2],HEAPU32[viPtr+24>>2])}}function makeMultisampleState(msPtr){if(!msPtr)return undefined;return{\"count\":HEAPU32[msPtr+4>>2],\"mask\":HEAPU32[msPtr+8>>2],\"alphaToCoverageEnabled\":HEAP8[msPtr+12>>0]!==0}}function makeFragmentState(fsPtr){if(!fsPtr)return undefined;return{\"module\":WebGPU.mgrShaderModule.get(HEAPU32[fsPtr+4>>2]),\"entryPoint\":UTF8ToString(HEAPU32[fsPtr+8>>2]),\"constants\":WebGPU.makePipelineConstants(HEAPU32[fsPtr+12>>2],HEAPU32[fsPtr+16>>2]),\"targets\":makeColorStates(HEAPU32[fsPtr+20>>2],HEAPU32[fsPtr+24>>2])}}var desc={\"label\":undefined,\"layout\":WebGPU.makePipelineLayout(HEAPU32[descriptor+8>>2]),\"vertex\":makeVertexState(descriptor+12),\"primitive\":makePrimitiveState(descriptor+40),\"depthStencil\":makeDepthStencilState(HEAPU32[descriptor+60>>2]),\"multisample\":makeMultisampleState(descriptor+64),\"fragment\":makeFragmentState(HEAPU32[descriptor+80>>2])};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrRenderPipeline.create(device[\"createRenderPipeline\"](desc))}function _wgpuDeviceCreateSampler(deviceId,descriptor){var desc={\"label\":undefined,\"addressModeU\":WebGPU.AddressMode[HEAPU32[descriptor+8>>2]],\"addressModeV\":WebGPU.AddressMode[HEAPU32[descriptor+12>>2]],\"addressModeW\":WebGPU.AddressMode[HEAPU32[descriptor+16>>2]],\"magFilter\":WebGPU.FilterMode[HEAPU32[descriptor+20>>2]],\"minFilter\":WebGPU.FilterMode[HEAPU32[descriptor+24>>2]],\"mipmapFilter\":WebGPU.FilterMode[HEAPU32[descriptor+28>>2]],\"lodMinClamp\":HEAPF32[descriptor+32>>2],\"lodMaxClamp\":HEAPF32[descriptor+36>>2],\"compare\":WebGPU.CompareFunction[HEAPU32[descriptor+40>>2]]};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrSampler.create(device[\"createSampler\"](desc))}function _wgpuDeviceCreateShaderModule(deviceId,descriptor){var nextInChainPtr=HEAPU32[descriptor>>2];var sType=HEAPU32[nextInChainPtr+4>>2];var desc={\"label\":undefined,\"code\":\"\"};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);switch(sType){case 5:{var count=HEAPU32[nextInChainPtr+8>>2];var start=HEAPU32[nextInChainPtr+12>>2];desc[\"code\"]=HEAPU32.subarray(start>>2,(start>>2)+count);break}case 6:{var sourcePtr=HEAPU32[nextInChainPtr+8>>2];if(sourcePtr){desc[\"code\"]=UTF8ToString(sourcePtr)}break}}var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrShaderModule.create(device[\"createShaderModule\"](desc))}function _wgpuDeviceCreateTexture(deviceId,descriptor){var desc={\"label\":undefined,\"size\":WebGPU.makeExtent3D(descriptor+16),\"mipLevelCount\":HEAPU32[descriptor+32>>2],\"sampleCount\":HEAPU32[descriptor+36>>2],\"dimension\":WebGPU.TextureDimension[HEAPU32[descriptor+12>>2]],\"format\":WebGPU.TextureFormat[HEAPU32[descriptor+28>>2]],\"usage\":HEAPU32[descriptor+8>>2]};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr);var viewFormatCount=HEAPU32[descriptor+40>>2];if(viewFormatCount){var viewFormatsPtr=HEAPU32[descriptor+44>>2];desc[\"viewFormats\"]=Array.from(HEAP32.subarray(viewFormatsPtr>>2,(viewFormatsPtr>>2)+viewFormatCount),function(format){return WebGPU.TextureFormat[format]})}var device=WebGPU.mgrDevice.get(deviceId);return WebGPU.mgrTexture.create(device[\"createTexture\"](desc))}function _wgpuDeviceGetQueue(deviceId){var queueId=WebGPU.mgrDevice.objects[deviceId].queueId;WebGPU.mgrQueue.reference(queueId);return queueId}function _wgpuDeviceReference(id){WebGPU.mgrDevice.reference(id)}function _wgpuDeviceRelease(id){WebGPU.mgrDevice.release(id)}function _wgpuPipelineLayoutRelease(id){WebGPU.mgrPipelineLayout.release(id)}function _wgpuQuerySetRelease(id){WebGPU.mgrQuerySet.release(id)}function _wgpuQueueRelease(id){WebGPU.mgrQueue.release(id)}function _wgpuQueueSubmit(queueId,commandCount,commands){var queue=WebGPU.mgrQueue.get(queueId);var cmds=Array.from(HEAP32.subarray(commands>>2,(commands>>2)+commandCount),function(id){return WebGPU.mgrCommandBuffer.get(id)});queue[\"submit\"](cmds)}function _wgpuQueueWriteBuffer(queueId,bufferId,bufferOffset_low,bufferOffset_high,data,size){var bufferOffset=convertI32PairToI53Checked(bufferOffset_low,bufferOffset_high);if(isNaN(bufferOffset))return undefined;var queue=WebGPU.mgrQueue.get(queueId);var buffer=WebGPU.mgrBuffer.get(bufferId);var subarray=HEAPU8.subarray(data,data+size);queue[\"writeBuffer\"](buffer,bufferOffset,subarray,0,size)}function _wgpuRenderPassEncoderDraw(passId,vertexCount,instanceCount,firstVertex,firstInstance){var pass=WebGPU.mgrRenderPassEncoder.get(passId);pass[\"draw\"](vertexCount,instanceCount,firstVertex,firstInstance)}function _wgpuRenderPassEncoderEnd(passId){var pass=WebGPU.mgrRenderPassEncoder.get(passId);pass[\"end\"]()}function _wgpuRenderPassEncoderRelease(id){WebGPU.mgrRenderPassEncoder.release(id)}function _wgpuRenderPassEncoderSetBindGroup(passId,groupIndex,groupId,dynamicOffsetCount,dynamicOffsetsPtr){var pass=WebGPU.mgrRenderPassEncoder.get(passId);var group=WebGPU.mgrBindGroup.get(groupId);if(dynamicOffsetCount==0){pass[\"setBindGroup\"](groupIndex,group)}else{var offsets=[];for(var i=0;i<dynamicOffsetCount;i++,dynamicOffsetsPtr+=4){offsets.push(HEAPU32[dynamicOffsetsPtr>>2])}pass[\"setBindGroup\"](groupIndex,group,offsets)}}function _wgpuRenderPassEncoderSetPipeline(passId,pipelineId){var pass=WebGPU.mgrRenderPassEncoder.get(passId);var pipeline=WebGPU.mgrRenderPipeline.get(pipelineId);pass[\"setPipeline\"](pipeline)}function _wgpuRenderPipelineGetBindGroupLayout(pipelineId,groupIndex){var pipeline=WebGPU.mgrRenderPipeline.get(pipelineId);return WebGPU.mgrBindGroupLayout.create(pipeline[\"getBindGroupLayout\"](groupIndex))}function _wgpuRenderPipelineRelease(id){WebGPU.mgrRenderPipeline.release(id)}function _wgpuSamplerReference(id){WebGPU.mgrSampler.reference(id)}function _wgpuSamplerRelease(id){WebGPU.mgrSampler.release(id)}function _wgpuShaderModuleReference(id){WebGPU.mgrShaderModule.reference(id)}function _wgpuShaderModuleRelease(id){WebGPU.mgrShaderModule.release(id)}function _wgpuTextureCreateView(textureId,descriptor){var desc;if(descriptor){var mipLevelCount=HEAPU32[descriptor+20>>2];var arrayLayerCount=HEAPU32[descriptor+28>>2];desc={\"format\":WebGPU.TextureFormat[HEAPU32[descriptor+8>>2]],\"dimension\":WebGPU.TextureViewDimension[HEAPU32[descriptor+12>>2]],\"baseMipLevel\":HEAPU32[descriptor+16>>2],\"mipLevelCount\":mipLevelCount===4294967295?undefined:mipLevelCount,\"baseArrayLayer\":HEAPU32[descriptor+24>>2],\"arrayLayerCount\":arrayLayerCount===4294967295?undefined:arrayLayerCount,\"aspect\":WebGPU.TextureAspect[HEAPU32[descriptor+32>>2]]};var labelPtr=HEAPU32[descriptor+4>>2];if(labelPtr)desc[\"label\"]=UTF8ToString(labelPtr)}var texture=WebGPU.mgrTexture.get(textureId);return WebGPU.mgrTextureView.create(texture[\"createView\"](desc))}function _wgpuTextureDestroy(textureId){WebGPU.mgrTexture.get(textureId)[\"destroy\"]()}function _wgpuTextureReference(id){WebGPU.mgrTexture.reference(id)}function _wgpuTextureRelease(id){WebGPU.mgrTexture.release(id)}function _wgpuTextureViewReference(id){WebGPU.mgrTextureView.reference(id)}function _wgpuTextureViewRelease(id){WebGPU.mgrTextureView.release(id)}function getCFunc(ident){var func=Module[\"_\"+ident];return func}function ccall(ident,returnType,argTypes,args,opts){var toC={\"string\":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},\"array\":arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType===\"string\"){return UTF8ToString(ret)}if(returnType===\"boolean\")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);function onDone(ret){if(stack!==0)stackRestore(stack);return convertReturnValue(ret)}ret=onDone(ret);return ret}Module[\"requestFullscreen\"]=function Module_requestFullscreen(lockPointer,resizeCanvas){Browser.requestFullscreen(lockPointer,resizeCanvas)};Module[\"requestAnimationFrame\"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module[\"setCanvasSize\"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module[\"pauseMainLoop\"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module[\"resumeMainLoop\"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module[\"getUserMedia\"]=function Module_getUserMedia(){Browser.getUserMedia()};Module[\"createContext\"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};var preloadedImages={};var preloadedAudios={};var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();Module[\"FS_createPath\"]=FS.createPath;Module[\"FS_createDataFile\"]=FS.createDataFile;Module[\"FS_createPreloadedFile\"]=FS.createPreloadedFile;Module[\"FS_unlink\"]=FS.unlink;Module[\"FS_createLazyFile\"]=FS.createLazyFile;Module[\"FS_createDevice\"]=FS.createDevice;embind_init_charCodes();BindingError=Module[\"BindingError\"]=extendError(Error,\"BindingError\");InternalError=Module[\"InternalError\"]=extendError(Error,\"InternalError\");init_emval();var GLctx;WebGPU.initManagers();for(var i=0;i<32;++i)tempFixedLengthArray.push(new Array(i));var miniTempWebGLFloatBuffersStorage=new Float32Array(288);for(var i=0;i<288;++i){miniTempWebGLFloatBuffers[i]=miniTempWebGLFloatBuffersStorage.subarray(0,i+1)}var miniTempWebGLIntBuffersStorage=new Int32Array(288);for(var i=0;i<288;++i){miniTempWebGLIntBuffers[i]=miniTempWebGLIntBuffersStorage.subarray(0,i+1)}var wasmImports={\"nd\":HaveOffsetConverter,\"md\":JsOnEmptyPacketListener,\"ld\":JsOnFloat32ArrayImageListener,\"kd\":JsOnFloat32ArrayImageVectorListener,\"Ma\":JsOnSimpleListenerBinaryArray,\"jd\":JsOnSimpleListenerBool,\"id\":JsOnSimpleListenerDouble,\"hd\":JsOnSimpleListenerFloat,\"gd\":JsOnSimpleListenerInt,\"fd\":JsOnSimpleListenerString,\"ed\":JsOnUint8ArrayImageListener,\"dd\":JsOnUint8ArrayImageVectorListener,\"K\":JsOnVectorFinishedListener,\"cd\":JsOnVectorListenerBool,\"bd\":JsOnVectorListenerDouble,\"ad\":JsOnVectorListenerFloat,\"$c\":JsOnVectorListenerInt,\"_c\":JsOnVectorListenerProto,\"Zc\":JsOnVectorListenerString,\"Yc\":JsOnWebGLTextureListener,\"Xc\":JsOnWebGLTextureVectorListener,\"G\":JsWrapErrorListener,\"La\":JsWrapImageConverter,\"r\":JsWrapSimpleListeners,\"i\":___cxa_throw,\"Ka\":___syscall_fcntl64,\"Wc\":___syscall_fstat64,\"Vc\":___syscall_ioctl,\"Uc\":___syscall_lstat64,\"Tc\":___syscall_newfstatat,\"Ja\":___syscall_openat,\"Sc\":___syscall_stat64,\"Oc\":__dlopen_js,\"Nc\":__dlsym_js,\"Tb\":__embind_register_bigint,\"Mc\":__embind_register_bool,\"Lc\":__embind_register_emval,\"Ga\":__embind_register_float,\"E\":__embind_register_integer,\"n\":__embind_register_memory_view,\"Fa\":__embind_register_std_string,\"ja\":__embind_register_std_wstring,\"Kc\":__embind_register_void,\"Jc\":__emscripten_get_now_is_monotonic,\"ia\":__emval_as,\"m\":__emval_decref,\"ha\":__emval_get_global,\"Ea\":__emval_get_property,\"Da\":__emval_incref,\"ga\":__emval_instanceof,\"ba\":__emval_new_cstring,\"fa\":__emval_run_destructors,\"Ca\":__emval_set_property,\"aa\":__emval_take_value,\"Ic\":__emval_typeof,\"Hc\":__gmtime_js,\"Gc\":__localtime_js,\"Fc\":__mktime_js,\"Ec\":__mmap_js,\"Dc\":__munmap_js,\"Cc\":__tzset_js,\"a\":_abort,\"Bc\":custom_emscripten_dbgn,\"D\":_emscripten_asm_const_int,\"Ac\":_emscripten_date_now,\"Ba\":_emscripten_err,\"zc\":_emscripten_errn,\"yc\":_emscripten_get_heap_max,\"u\":_emscripten_get_now,\"xc\":_emscripten_memcpy_big,\"wc\":_emscripten_outn,\"vc\":_emscripten_pc_get_function,\"uc\":_emscripten_resize_heap,\"tc\":_emscripten_stack_snapshot,\"sc\":_emscripten_stack_unwind_buffer,\"rc\":_emscripten_webgl_create_context,\"qc\":_emscripten_webgl_destroy_context,\"pc\":_emscripten_webgl_get_context_attributes,\"Aa\":_emscripten_webgl_get_current_context,\"oc\":_emscripten_webgl_init_context_attributes,\"nc\":_emscripten_webgl_make_context_current,\"mc\":_emscripten_webgpu_export_bind_group_layout,\"za\":_emscripten_webgpu_export_device,\"lc\":_emscripten_webgpu_export_sampler,\"kc\":_emscripten_webgpu_export_texture,\"J\":_emscripten_webgpu_get_device,\"jc\":_emscripten_webgpu_import_bind_group,\"ic\":_emscripten_webgpu_import_texture,\"U\":_emscripten_webgpu_release_js_handle,\"Rc\":_environ_get,\"Qc\":_environ_sizes_get,\"ya\":_exit,\"ka\":_fd_close,\"Ia\":_fd_read,\"Ub\":_fd_seek,\"Ha\":_fd_write,\"hc\":_getentropy,\"d\":_glActiveTexture,\"$\":_glAttachShader,\"gc\":_glBindAttribLocation,\"e\":_glBindBuffer,\"fc\":_glBindBufferBase,\"v\":_glBindFramebuffer,\"b\":_glBindTexture,\"t\":_glBindVertexArray,\"xa\":_glBlendEquation,\"ec\":_glBlendFunc,\"p\":_glBufferData,\"z\":_glClear,\"ea\":_glClearColor,\"Sb\":_glClientWaitSync,\"wa\":_glCompileShader,\"va\":_glCreateProgram,\"ua\":_glCreateShader,\"C\":_glDeleteBuffers,\"P\":_glDeleteFramebuffers,\"j\":_glDeleteProgram,\"T\":_glDeleteShader,\"S\":_glDeleteSync,\"y\":_glDeleteTextures,\"O\":_glDeleteVertexArrays,\"I\":_glDisable,\"s\":_glDisableVertexAttribArray,\"o\":_glDrawArrays,\"R\":_glDrawBuffers,\"dc\":_glEnable,\"l\":_glEnableVertexAttribArray,\"ta\":_glFenceSync,\"_\":_glFinish,\"H\":_glFlush,\"x\":_glFramebufferTexture2D,\"sa\":_glFramebufferTextureLayer,\"w\":_glGenBuffers,\"N\":_glGenFramebuffers,\"B\":_glGenTextures,\"M\":_glGenVertexArrays,\"ra\":_glGetAttribLocation,\"Z\":_glGetError,\"q\":_glGetIntegerv,\"cc\":_glGetProgramiv,\"bc\":_glGetShaderInfoLog,\"ac\":_glGetShaderiv,\"F\":_glGetString,\"$b\":_glGetUniformBlockIndex,\"g\":_glGetUniformLocation,\"qa\":_glLinkProgram,\"Y\":_glPixelStorei,\"da\":_glReadPixels,\"pa\":_glShaderSource,\"A\":_glTexImage2D,\"X\":_glTexParameterf,\"oa\":_glTexParameterfv,\"c\":_glTexParameteri,\"ca\":_glTexStorage2D,\"_b\":_glTexStorage3D,\"Q\":_glTexSubImage2D,\"Zb\":_glTexSubImage3D,\"W\":_glUniform1f,\"f\":_glUniform1i,\"Yb\":_glUniform2f,\"Xb\":_glUniform2fv,\"na\":_glUniform3f,\"ma\":_glUniform4fv,\"Wb\":_glUniform4iv,\"Vb\":_glUniformBlockBinding,\"la\":_glUniformMatrix4fv,\"h\":_glUseProgram,\"k\":_glVertexAttribPointer,\"L\":_glViewport,\"Qb\":mediapipe_create_utility_canvas2d,\"Pb\":_mediapipe_find_canvas_event_target,\"Ob\":mediapipe_import_external_texture,\"Nb\":_mediapipe_webgl_tex_image_drawable,\"Pc\":_proc_exit,\"V\":_strftime,\"Mb\":_strftime_l,\"Lb\":_wgpuBindGroupLayoutRelease,\"Kb\":_wgpuBindGroupRelease,\"Jb\":_wgpuBufferGetMappedRange,\"Ib\":_wgpuBufferReference,\"Hb\":_wgpuBufferRelease,\"Gb\":_wgpuBufferUnmap,\"Fb\":_wgpuCommandBufferRelease,\"Eb\":_wgpuCommandEncoderBeginComputePass,\"Db\":_wgpuCommandEncoderBeginRenderPass,\"Cb\":_wgpuCommandEncoderCopyBufferToTexture,\"Bb\":_wgpuCommandEncoderCopyTextureToTexture,\"Ab\":_wgpuCommandEncoderFinish,\"zb\":_wgpuCommandEncoderRelease,\"yb\":_wgpuComputePassEncoderDispatchWorkgroups,\"xb\":_wgpuComputePassEncoderEnd,\"wb\":_wgpuComputePassEncoderRelease,\"vb\":_wgpuComputePassEncoderSetBindGroup,\"ub\":_wgpuComputePassEncoderSetPipeline,\"tb\":_wgpuComputePipelineGetBindGroupLayout,\"sb\":_wgpuComputePipelineRelease,\"rb\":_wgpuDeviceCreateBindGroup,\"qb\":_wgpuDeviceCreateBuffer,\"pb\":_wgpuDeviceCreateCommandEncoder,\"ob\":_wgpuDeviceCreateComputePipeline,\"nb\":_wgpuDeviceCreateRenderPipeline,\"mb\":_wgpuDeviceCreateSampler,\"lb\":_wgpuDeviceCreateShaderModule,\"kb\":_wgpuDeviceCreateTexture,\"jb\":_wgpuDeviceGetQueue,\"ib\":_wgpuDeviceReference,\"hb\":_wgpuDeviceRelease,\"gb\":_wgpuPipelineLayoutRelease,\"fb\":_wgpuQuerySetRelease,\"eb\":_wgpuQueueRelease,\"db\":_wgpuQueueSubmit,\"Rb\":_wgpuQueueWriteBuffer,\"cb\":_wgpuRenderPassEncoderDraw,\"bb\":_wgpuRenderPassEncoderEnd,\"ab\":_wgpuRenderPassEncoderRelease,\"$a\":_wgpuRenderPassEncoderSetBindGroup,\"_a\":_wgpuRenderPassEncoderSetPipeline,\"Za\":_wgpuRenderPipelineGetBindGroupLayout,\"Ya\":_wgpuRenderPipelineRelease,\"Xa\":_wgpuSamplerReference,\"Wa\":_wgpuSamplerRelease,\"Va\":_wgpuShaderModuleReference,\"Ua\":_wgpuShaderModuleRelease,\"Ta\":_wgpuTextureCreateView,\"Sa\":_wgpuTextureDestroy,\"Ra\":_wgpuTextureReference,\"Qa\":_wgpuTextureRelease,\"Pa\":_wgpuTextureViewReference,\"Oa\":_wgpuTextureViewRelease,\"Na\":xnnLoadWasmModuleJS};var asm=createWasm();var ___wasm_call_ctors=function(){return(___wasm_call_ctors=Module[\"asm\"][\"pd\"]).apply(null,arguments)};var _free=Module[\"_free\"]=function(){return(_free=Module[\"_free\"]=Module[\"asm\"][\"rd\"]).apply(null,arguments)};var _malloc=Module[\"_malloc\"]=function(){return(_malloc=Module[\"_malloc\"]=Module[\"asm\"][\"sd\"]).apply(null,arguments)};var _addBoundTextureAsImageToStream=Module[\"_addBoundTextureAsImageToStream\"]=function(){return(_addBoundTextureAsImageToStream=Module[\"_addBoundTextureAsImageToStream\"]=Module[\"asm\"][\"td\"]).apply(null,arguments)};var _attachImageListener=Module[\"_attachImageListener\"]=function(){return(_attachImageListener=Module[\"_attachImageListener\"]=Module[\"asm\"][\"ud\"]).apply(null,arguments)};var _attachImageVectorListener=Module[\"_attachImageVectorListener\"]=function(){return(_attachImageVectorListener=Module[\"_attachImageVectorListener\"]=Module[\"asm\"][\"vd\"]).apply(null,arguments)};var _registerModelResourcesGraphService=Module[\"_registerModelResourcesGraphService\"]=function(){return(_registerModelResourcesGraphService=Module[\"_registerModelResourcesGraphService\"]=Module[\"asm\"][\"wd\"]).apply(null,arguments)};var ___errno_location=function(){return(___errno_location=Module[\"asm\"][\"xd\"]).apply(null,arguments)};var _bindTextureToStream=Module[\"_bindTextureToStream\"]=function(){return(_bindTextureToStream=Module[\"_bindTextureToStream\"]=Module[\"asm\"][\"yd\"]).apply(null,arguments)};var _addBoundTextureToStream=Module[\"_addBoundTextureToStream\"]=function(){return(_addBoundTextureToStream=Module[\"_addBoundTextureToStream\"]=Module[\"asm\"][\"zd\"]).apply(null,arguments)};var _addDoubleToInputStream=Module[\"_addDoubleToInputStream\"]=function(){return(_addDoubleToInputStream=Module[\"_addDoubleToInputStream\"]=Module[\"asm\"][\"Ad\"]).apply(null,arguments)};var _addFloatToInputStream=Module[\"_addFloatToInputStream\"]=function(){return(_addFloatToInputStream=Module[\"_addFloatToInputStream\"]=Module[\"asm\"][\"Bd\"]).apply(null,arguments)};var _addBoolToInputStream=Module[\"_addBoolToInputStream\"]=function(){return(_addBoolToInputStream=Module[\"_addBoolToInputStream\"]=Module[\"asm\"][\"Cd\"]).apply(null,arguments)};var _addIntToInputStream=Module[\"_addIntToInputStream\"]=function(){return(_addIntToInputStream=Module[\"_addIntToInputStream\"]=Module[\"asm\"][\"Dd\"]).apply(null,arguments)};var _addStringToInputStream=Module[\"_addStringToInputStream\"]=function(){return(_addStringToInputStream=Module[\"_addStringToInputStream\"]=Module[\"asm\"][\"Ed\"]).apply(null,arguments)};var _addFlatHashMapToInputStream=Module[\"_addFlatHashMapToInputStream\"]=function(){return(_addFlatHashMapToInputStream=Module[\"_addFlatHashMapToInputStream\"]=Module[\"asm\"][\"Fd\"]).apply(null,arguments)};var _addProtoToInputStream=Module[\"_addProtoToInputStream\"]=function(){return(_addProtoToInputStream=Module[\"_addProtoToInputStream\"]=Module[\"asm\"][\"Gd\"]).apply(null,arguments)};var _addEmptyPacketToInputStream=Module[\"_addEmptyPacketToInputStream\"]=function(){return(_addEmptyPacketToInputStream=Module[\"_addEmptyPacketToInputStream\"]=Module[\"asm\"][\"Hd\"]).apply(null,arguments)};var _addBoolToInputSidePacket=Module[\"_addBoolToInputSidePacket\"]=function(){return(_addBoolToInputSidePacket=Module[\"_addBoolToInputSidePacket\"]=Module[\"asm\"][\"Id\"]).apply(null,arguments)};var _addDoubleToInputSidePacket=Module[\"_addDoubleToInputSidePacket\"]=function(){return(_addDoubleToInputSidePacket=Module[\"_addDoubleToInputSidePacket\"]=Module[\"asm\"][\"Jd\"]).apply(null,arguments)};var _addFloatToInputSidePacket=Module[\"_addFloatToInputSidePacket\"]=function(){return(_addFloatToInputSidePacket=Module[\"_addFloatToInputSidePacket\"]=Module[\"asm\"][\"Kd\"]).apply(null,arguments)};var _addIntToInputSidePacket=Module[\"_addIntToInputSidePacket\"]=function(){return(_addIntToInputSidePacket=Module[\"_addIntToInputSidePacket\"]=Module[\"asm\"][\"Ld\"]).apply(null,arguments)};var _addStringToInputSidePacket=Module[\"_addStringToInputSidePacket\"]=function(){return(_addStringToInputSidePacket=Module[\"_addStringToInputSidePacket\"]=Module[\"asm\"][\"Md\"]).apply(null,arguments)};var _addProtoToInputSidePacket=Module[\"_addProtoToInputSidePacket\"]=function(){return(_addProtoToInputSidePacket=Module[\"_addProtoToInputSidePacket\"]=Module[\"asm\"][\"Nd\"]).apply(null,arguments)};var _attachBoolListener=Module[\"_attachBoolListener\"]=function(){return(_attachBoolListener=Module[\"_attachBoolListener\"]=Module[\"asm\"][\"Od\"]).apply(null,arguments)};var _attachBoolVectorListener=Module[\"_attachBoolVectorListener\"]=function(){return(_attachBoolVectorListener=Module[\"_attachBoolVectorListener\"]=Module[\"asm\"][\"Pd\"]).apply(null,arguments)};var _attachDoubleListener=Module[\"_attachDoubleListener\"]=function(){return(_attachDoubleListener=Module[\"_attachDoubleListener\"]=Module[\"asm\"][\"Qd\"]).apply(null,arguments)};var _attachDoubleVectorListener=Module[\"_attachDoubleVectorListener\"]=function(){return(_attachDoubleVectorListener=Module[\"_attachDoubleVectorListener\"]=Module[\"asm\"][\"Rd\"]).apply(null,arguments)};var _attachFloatListener=Module[\"_attachFloatListener\"]=function(){return(_attachFloatListener=Module[\"_attachFloatListener\"]=Module[\"asm\"][\"Sd\"]).apply(null,arguments)};var _attachFloatVectorListener=Module[\"_attachFloatVectorListener\"]=function(){return(_attachFloatVectorListener=Module[\"_attachFloatVectorListener\"]=Module[\"asm\"][\"Td\"]).apply(null,arguments)};var _attachIntListener=Module[\"_attachIntListener\"]=function(){return(_attachIntListener=Module[\"_attachIntListener\"]=Module[\"asm\"][\"Ud\"]).apply(null,arguments)};var _attachIntVectorListener=Module[\"_attachIntVectorListener\"]=function(){return(_attachIntVectorListener=Module[\"_attachIntVectorListener\"]=Module[\"asm\"][\"Vd\"]).apply(null,arguments)};var _attachStringListener=Module[\"_attachStringListener\"]=function(){return(_attachStringListener=Module[\"_attachStringListener\"]=Module[\"asm\"][\"Wd\"]).apply(null,arguments)};var _attachStringVectorListener=Module[\"_attachStringVectorListener\"]=function(){return(_attachStringVectorListener=Module[\"_attachStringVectorListener\"]=Module[\"asm\"][\"Xd\"]).apply(null,arguments)};var _attachProtoListener=Module[\"_attachProtoListener\"]=function(){return(_attachProtoListener=Module[\"_attachProtoListener\"]=Module[\"asm\"][\"Yd\"]).apply(null,arguments)};var _attachProtoVectorListener=Module[\"_attachProtoVectorListener\"]=function(){return(_attachProtoVectorListener=Module[\"_attachProtoVectorListener\"]=Module[\"asm\"][\"Zd\"]).apply(null,arguments)};var _getGraphConfig=Module[\"_getGraphConfig\"]=function(){return(_getGraphConfig=Module[\"_getGraphConfig\"]=Module[\"asm\"][\"_d\"]).apply(null,arguments)};var _clearSubgraphs=Module[\"_clearSubgraphs\"]=function(){return(_clearSubgraphs=Module[\"_clearSubgraphs\"]=Module[\"asm\"][\"$d\"]).apply(null,arguments)};var _pushBinarySubgraph=Module[\"_pushBinarySubgraph\"]=function(){return(_pushBinarySubgraph=Module[\"_pushBinarySubgraph\"]=Module[\"asm\"][\"ae\"]).apply(null,arguments)};var _pushTextSubgraph=Module[\"_pushTextSubgraph\"]=function(){return(_pushTextSubgraph=Module[\"_pushTextSubgraph\"]=Module[\"asm\"][\"be\"]).apply(null,arguments)};var _changeBinaryGraph=Module[\"_changeBinaryGraph\"]=function(){return(_changeBinaryGraph=Module[\"_changeBinaryGraph\"]=Module[\"asm\"][\"ce\"]).apply(null,arguments)};var _changeTextGraph=Module[\"_changeTextGraph\"]=function(){return(_changeTextGraph=Module[\"_changeTextGraph\"]=Module[\"asm\"][\"de\"]).apply(null,arguments)};var _processGl=Module[\"_processGl\"]=function(){return(_processGl=Module[\"_processGl\"]=Module[\"asm\"][\"ee\"]).apply(null,arguments)};var _process=Module[\"_process\"]=function(){return(_process=Module[\"_process\"]=Module[\"asm\"][\"fe\"]).apply(null,arguments)};var _bindTextureToCanvas=Module[\"_bindTextureToCanvas\"]=function(){return(_bindTextureToCanvas=Module[\"_bindTextureToCanvas\"]=Module[\"asm\"][\"ge\"]).apply(null,arguments)};var _requestShaderRefreshOnGraphChange=Module[\"_requestShaderRefreshOnGraphChange\"]=function(){return(_requestShaderRefreshOnGraphChange=Module[\"_requestShaderRefreshOnGraphChange\"]=Module[\"asm\"][\"he\"]).apply(null,arguments)};var _waitUntilIdle=Module[\"_waitUntilIdle\"]=function(){return(_waitUntilIdle=Module[\"_waitUntilIdle\"]=Module[\"asm\"][\"ie\"]).apply(null,arguments)};var _closeGraph=Module[\"_closeGraph\"]=function(){return(_closeGraph=Module[\"_closeGraph\"]=Module[\"asm\"][\"je\"]).apply(null,arguments)};var _setAutoRenderToScreen=Module[\"_setAutoRenderToScreen\"]=function(){return(_setAutoRenderToScreen=Module[\"_setAutoRenderToScreen\"]=Module[\"asm\"][\"ke\"]).apply(null,arguments)};var ___getTypeName=function(){return(___getTypeName=Module[\"asm\"][\"le\"]).apply(null,arguments)};var __embind_initialize_bindings=Module[\"__embind_initialize_bindings\"]=function(){return(__embind_initialize_bindings=Module[\"__embind_initialize_bindings\"]=Module[\"asm\"][\"me\"]).apply(null,arguments)};var _emscripten_builtin_memalign=function(){return(_emscripten_builtin_memalign=Module[\"asm\"][\"ne\"]).apply(null,arguments)};var _memalign=function(){return(_memalign=Module[\"asm\"][\"oe\"]).apply(null,arguments)};var stackSave=function(){return(stackSave=Module[\"asm\"][\"pe\"]).apply(null,arguments)};var stackRestore=function(){return(stackRestore=Module[\"asm\"][\"qe\"]).apply(null,arguments)};var stackAlloc=function(){return(stackAlloc=Module[\"asm\"][\"re\"]).apply(null,arguments)};var ___cxa_is_pointer_type=function(){return(___cxa_is_pointer_type=Module[\"asm\"][\"se\"]).apply(null,arguments)};var ___start_em_js=Module[\"___start_em_js\"]=1181028;var ___stop_em_js=Module[\"___stop_em_js\"]=1188450;Module[\"addRunDependency\"]=addRunDependency;Module[\"removeRunDependency\"]=removeRunDependency;Module[\"FS_createPath\"]=FS.createPath;Module[\"FS_createDataFile\"]=FS.createDataFile;Module[\"FS_createLazyFile\"]=FS.createLazyFile;Module[\"FS_createDevice\"]=FS.createDevice;Module[\"FS_unlink\"]=FS.unlink;Module[\"ccall\"]=ccall;Module[\"stringToNewUTF8\"]=stringToNewUTF8;Module[\"FS_createPreloadedFile\"]=FS.createPreloadedFile;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module[\"calledRun\"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module[\"onRuntimeInitialized\"])Module[\"onRuntimeInitialized\"]();postRun()}if(Module[\"setStatus\"]){Module[\"setStatus\"](\"Running...\");setTimeout(function(){setTimeout(function(){Module[\"setStatus\"](\"\")},1);doRun()},1)}else{doRun()}}if(Module[\"preInit\"]){if(typeof Module[\"preInit\"]==\"function\")Module[\"preInit\"]=[Module[\"preInit\"]];while(Module[\"preInit\"].length>0){Module[\"preInit\"].pop()()}}run();\n\n\n  return ModuleFactory.ready\n}\n\n);\n})();\nif (typeof exports === 'object' && typeof module === 'object')\n  module.exports = ModuleFactory;\nelse if (typeof define === 'function' && define['amd'])\n  define([], function() { return ModuleFactory; });\nelse if (typeof exports === 'object')\n  exports[\"ModuleFactory\"] = ModuleFactory;\n"
  },
  {
    "path": "jsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"target\": \"ES6\"\n    },\n    \"exclude\": [\n        \"test\",\n        \"test_util\",\n        \"scripts\",\n        \"images\",\n        \"extern/blockly\",\n        \"node_modules\",\n        \"**/node_modules/*\"\n    ]\n}\n"
  },
  {
    "path": "karma.conf.js",
    "content": "// Karma configuration\n// Generated on Tue Jun 23 2015 15:42:45 GMT+0900 (KST)\n\nmodule.exports = function(config) {\n    config.set({\n        // base path that will be used to resolve all patterns (eg. files, exclude)\n        basePath: '',\n\n        // frameworks to use\n        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter\n        frameworks: ['mocha'],\n\n        // list of files / patterns to load in the browser\n        files: ['test/**/*.js'],\n\n        // list of files to exclude\n        exclude: [],\n\n        // preprocess matching files before serving them to the browser\n        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor\n        preprocessors: {},\n\n        // test results reporter to use\n        // possible values: 'dots', 'progress'\n        // available reporters: https://npmjs.org/browse/keyword/karma-reporter\n        reporters: ['progress'],\n\n        // web server port\n        port: 9876,\n\n        // enable / disable colors in the output (reporters and logs)\n        colors: true,\n\n        // level of logging\n        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG\n        logLevel: config.LOG_ERROR,\n\n        // enable / disable watching file and executing tests whenever any file changes\n        autoWatch: true,\n\n        // start these browsers\n        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher\n        browsers: ['Chrome'],\n\n        // Continuous Integration mode\n        // if true, Karma captures browsers, runs the tests and exits\n        singleRun: true,\n    });\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n    \"name\": \"@entrylabs/entry\",\n    \"title\": \"EntryJS\",\n    \"description\": \"JavaScript library for visual programming\",\n    \"version\": \"4.0.22\",\n    \"main\": \"dist/entry.min.js\",\n    \"homepage\": \"https://playentry.org\",\n    \"author\": {\n        \"name\": \"Entry Korea corp and other contributors\"\n    },\n    \"repository\": {\n        \"type\": \"git\",\n        \"url\": \"git+https://github.com/entrylabs/entryjs.git\"\n    },\n    \"keywords\": [\n        \"entry\",\n        \"entryjs\",\n        \"javascript\"\n    ],\n    \"bugs\": {\n        \"url\": \"https://github.com/entrylabs/entryjs/issues\"\n    },\n    \"scripts\": {\n        \"lint\": \"cross-env NODE_ENV=lint webpack -w\",\n        \"serve:webgl\": \"cross-env NODE_ENV=serve webpack-dev-server --open  --hot --host 127.0.0.1 --webgl=true\",\n        \"serve\": \"cross-env NODE_ENV=serve webpack-dev-server --open --hot --host 127.0.0.1\",\n        \"serve:mini\": \"cross-env NODE_ENV=serve-mini webpack-dev-server --open --hot --host 127.0.0.1\",\n        \"prod\": \"cross-env NODE_ENV=production webpack\",\n        \"dev\": \"webpack -w\",\n        \"test\": \"jest --colors\",\n        \"clean\": \"rimraf ./dist\",\n        \"dist\": \"webpack\"\n    },\n    \"license\": \"Apache-2.0\",\n    \"dependencies\": {\n        \"@entrylabs/event\": \"^1.0.3\",\n        \"@mediapipe/tasks-vision\": \"^0.10.3\",\n        \"@tensorflow/tfjs\": \"^4.17.0\",\n        \"@types/crypto-js\": \"^4.0.1\",\n        \"@types/hammerjs\": \"^2.0.41\",\n        \"@types/isomorphic-fetch\": \"^0.0.35\",\n        \"autoprefixer\": \"^9.4.3\",\n        \"buffer\": \"^6.0.3\",\n        \"copy-webpack-plugin\": \"^12.0.2\",\n        \"core-js\": \"^3.6.4\",\n        \"crypto-js\": \"^4.0.0\",\n        \"cuid\": \"^2.1.6\",\n        \"events\": \"^3.0.0\",\n        \"file-saver\": \"^2.0.2\",\n        \"fontfaceonload\": \"^1.0.2\",\n        \"hammerjs\": \"^2.0.8\",\n        \"html-webpack-plugin\": \"^5.5.3\",\n        \"html-webpack-template\": \"^6.2.0\",\n        \"isomorphic-fetch\": \"^2.2.1\",\n        \"jest\": \"^24.9.0\",\n        \"khaiii\": \"^0.0.2\",\n        \"libsvm-js\": \"^0.2.1\",\n        \"lodash\": \"^4.17.15\",\n        \"mathjs\": \"^7.1.0\",\n        \"ml-cart\": \"^2.1.1\",\n        \"pixi.js\": \"5.3.12\",\n        \"postcss-flexbugs-fixes\": \"^4.1.0\",\n        \"simplebar\": \"^5.3.0\",\n        \"skmeans\": \"^0.11.3\",\n        \"socket.io-client\": \"^2.3.0\",\n        \"ua-parser-js\": \"^1.0.38\",\n        \"uid\": \"^0.0.2\",\n        \"webpack\": \"^5.85.0\",\n        \"worker-loader\": \"^3.0.8\",\n        \"xss-filters\": \"^1.2.7\"\n    },\n    \"devDependencies\": {\n        \"@babel/core\": \"^7.22.1\",\n        \"@babel/eslint-parser\": \"^7.11.0\",\n        \"@babel/eslint-plugin\": \"^7.11.0\",\n        \"@babel/plugin-proposal-class-properties\": \"^7.8.3\",\n        \"@babel/plugin-proposal-object-rest-spread\": \"^7.8.3\",\n        \"@babel/plugin-proposal-private-methods\": \"^7.8.3\",\n        \"@babel/plugin-syntax-dynamic-import\": \"^7.8.3\",\n        \"@babel/plugin-transform-modules-commonjs\": \"^7.8.3\",\n        \"@babel/plugin-transform-object-assign\": \"^7.8.3\",\n        \"@babel/plugin-transform-runtime\": \"^7.8.3\",\n        \"@babel/preset-env\": \"^7.10.2\",\n        \"@babel/runtime\": \"^7.8.4\",\n        \"@egjs/visible\": \"^2.1.0\",\n        \"@types/createjs\": \"^0.0.29\",\n        \"@types/jquery\": \"^3.3.38\",\n        \"@types/lodash\": \"^4.14.155\",\n        \"@types/node\": \"^14.0.11\",\n        \"@types/pixi.js\": \"5.0.0\",\n        \"@types/w3c-web-usb\": \"^1.0.8\",\n        \"@types/web-bluetooth\": \"^0.0.18\",\n        \"@types/webpack-env\": \"^1.15.2\",\n        \"@typescript-eslint/parser\": \"^3.1.0\",\n        \"audiobuffer-to-wav\": \"^1.0.0\",\n        \"babel-loader\": \"^8.0.6\",\n        \"babel-plugin-dynamic-import-node\": \"^2.3.0\",\n        \"chai\": \"^3.2.0\",\n        \"clean-webpack-plugin\": \"^1.0.1\",\n        \"cross-env\": \"^5.1.4\",\n        \"css-loader\": \"^3.2.0\",\n        \"cssnano\": \"^4.1.10\",\n        \"eslint\": \"7.32.0\",\n        \"eslint-config-prettier\": \"^9.1.0\",\n        \"eslint-loader\": \"^4.0.2\",\n        \"eslint-plugin-prettier\": \"^5.1.3\",\n        \"extract-text-webpack-plugin\": \"^4.0.0-beta.0\",\n        \"file-loader\": \"^4.2.0\",\n        \"karma\": \"^4.2.0\",\n        \"karma-chai\": \"^0.1.0\",\n        \"karma-chrome-launcher\": \"^3.1.0\",\n        \"karma-mocha\": \"^1.3.0\",\n        \"less\": \"^3.10.1\",\n        \"less-loader\": \"^5.0.0\",\n        \"mini-css-extract-plugin\": \"^2.7.6\",\n        \"mocha\": \"^6.2.0\",\n        \"postcss-loader\": \"^3.0.0\",\n        \"prettier\": \"^3.2.5\",\n        \"prettier-eslint\": \"^16.3.0\",\n        \"style-loader\": \"^0.20.2\",\n        \"terser-webpack-plugin\": \"^5.3.9\",\n        \"ts-loader\": \"^9.4.3\",\n        \"typescript\": \"^4.7.4\",\n        \"url-loader\": \"^1.0.1\",\n        \"webpack-cli\": \"^5.1.1\",\n        \"webpack-dev-server\": \"^4.15.0\",\n        \"webpack-manifest-plugin\": \"^5.0.0\",\n        \"webpack-merge\": \"^5.9.0\",\n        \"webpack-strip-block\": \"^0.3.0\"\n    },\n    \"resolutions\": {\n        \"pixi.js\": \"5.3.7\"\n    },\n    \"publishConfig\": {\n        \"access\": \"public\"\n    },\n    \"files\": [\n        \"dist/\",\n        \"extern/\",\n        \"images/\",\n        \"weights/\",\n        \"src/playground/blocks/\",\n        \"src/playground/block_entry.js\",\n        \"src/playground/block_entry_mini.js\",\n        \"package.json\",\n        \"LICENSE\",\n        \"NOTICE\",\n        \"COPYING\",\n        \"README.md\",\n        \"README-en.md\"\n    ]\n}\n"
  },
  {
    "path": "scripts/build.sh",
    "content": "#!/usr/bin/env bash\nset -e # 에러 발생 시 스크립트 중단\n\ngit config --global user.name \"Entry Dev\";\ngit config --global user.email \"entrydev@nts-corp.com\";\n\nexport NODE_ENV=production\ngit clone -b build \"https://github.com/$GITHUB_REPOSITORY\" build\nrm -rf build/**/* || exit 0\ncp -r dist build/\ncp -r extern build/\ncp -r images build/\ncp -r weights build/\nrsync -R package.json build\nrsync -R LICENSE build\nrsync -R NOTICE build\nrsync -R COPYING build\nrsync -R README.md build\nrsync -R README-en.md build\nrsync -R src/playground/block_entry.js build\nrsync -R src/playground/block_entry_mini.js build\nrsync -r -R src/playground/blocks/ build\nls -al\nls -al build\n"
  },
  {
    "path": "scripts/build_action.sh",
    "content": "#!/usr/bin/env bash\nset -e # 에러 발생 시 스크립트 중단\n\ngit config --global user.name \"Entry Dev\";\ngit config --global user.email \"entrydev@nts-corp.com\";\n\nbranchName=${GITHUB_REF##*/}\ndeployName=\"dist/$branchName\"\n\nexport NODE_ENV=production\n\n#if [ \"$branchName\" = \"master\" ]\n#then\n    #git clone -b build \"https://github.com/$GITHUB_REPOSITORY\" build\n#else     \n    #git clone \"https://github.com/$GITHUB_REPOSITORY\" build\n    #if git show-ref --quiet refs/remotes/origin/\"$deployName\"; then\n    #    git clone -b \"$deployName\" \"https://github.com/$GITHUB_REPOSITORY\" build\n    #else \n    #    git clone \"https://github.com/$GITHUB_REPOSITORY\" build\n    #    git checkout -b \"$deployName\"\n    #fi\n#fi\n\ngit clone -b build \"https://github.com/$GITHUB_REPOSITORY\" build\nrm -rf build/**/* || exit 0\ncp -r dist build/\ncp -r extern build/\ncp -r images build/\ncp -r weights build/\nrsync -R src/playground/block_entry.js build\nrsync -R src/playground/block_entry_mini.js build\nrsync -r -R src/playground/blocks/ build\nls -al\nls -al build\n"
  },
  {
    "path": "scripts/deploy.sh",
    "content": "#!/usr/bin/env bash\nset -e # 에러 발생 시 스크립트 중단\n\ngit config --local user.email \"entrydev@nts-corp.com\"\ngit config --local user.name \"Entry Dev\"\n\nrm .gitignore\nbranchName=${GITHUB_REF##*/}\ndeployName=\"dist/$branchName\"\n\nDATEFMT=`date \"+%Y%m%d\"`\n# echo \"$DATEFMT: My message\"\ncd build\ngit config user.name \"Entry Dev\"\ngit config user.email \"entrydev@nts-corp.com\"\n\necho \"target branch's name is $branchName\"\n\nif [ \"$branchName\" = \"master\" ]\nthen\n    echo \"deploy to build branch\"\n    git add .\n    git commit -m \"Entry Js PUBLISH by v3.$DATEFMT.${GITHUB_RUN_NUMBER}\"\n    git tag -a \"v3.$DATEFMT.${GITHUB_RUN_NUMBER}\" -m \"build v3.$DATEFMT.${TRAVIS_BUILD_NUMBER}\"\n#    git push --force --quiet \"https://${GH_TOKEN}@${GH_REF}\" build --tags\nelse\n    echo \"deploy branch's name is $deployName\"\n    git checkout -b \"$deployName\"    \n    echo \"Entry Js deploy $deployName\" > ${GITHUB_RUN_NUMBER}\n#    git push --delete \"https://${GH_TOKEN}@${GH_REF}\" \"$deployName\"\n    git add .\n    git commit -m \"Entry Js deploy $deployName\"\n#    git push --force --quiet \"https://${GH_TOKEN}@${GH_REF}\" \"$deployName\"\nfi\n#curl -d '{\"tag_name\": \"v$DATEFMT\",\"target_commitish\": \"build\",\"name\": \"v$DATEFMT\",\"body\": \"Description of the release\",\"draft\": false,\"prerelease\": false}' -X POST \"https://developer.github.com/v3/repos/kimokim/entryjs/releases\"\n"
  },
  {
    "path": "scripts/deploy_action.sh",
    "content": "#!/usr/bin/env bash\nset -e # 에러 발생 시 스크립트 중단\n\ngit config --local user.email \"entrydev@nts-corp.com\"\ngit config --local user.name \"Entry Dev\"\n\nrm .gitignore\nbranchName=${GITHUB_REF##*/}\ndeployName=\"dist/$branchName\"\n\nDATEFMT=`date \"+%Y%m%d\"`\n# echo \"$DATEFMT: My message\"\ncd build\ngit config user.name \"Entry Dev\"\ngit config user.email \"entrydev@nts-corp.com\"\n\necho \"target branch's name is $branchName\"\necho \"https://${TEST}@github.com/$GITHUB_REPOSITORY\"\nif [ \"$branchName\" = \"master\" ]\nthen\n    echo \"deploy to build branch\"\n    git add .\n    git commit -m \"Entry Js PUBLISH by v3.$DATEFMT.${GITHUB_RUN_NUMBER}\"\n    git tag -a \"v3.$DATEFMT.${GITHUB_RUN_NUMBER}\" -m \"build v3.$DATEFMT.${TRAVIS_BUILD_NUMBER}\"\n#    git push --force --quiet \"https://${GH_TOKEN}@${GH_REF}\" build --tags\nelse\n    echo \"deploy branch's name is $deployName\"\n    if git show-ref --quiet refs/remotes/origin/\"$deployName\"; then\n        git push --delete \"https://${github_token}@github.com/$GITHUB_REPOSITORY\" \"$deployName\"\n    fi    \n    git add .\n    git commit -m \"Entry Js deploy $deployName\"\n    #git push --force --quiet \"https://${GH_TOKEN}@${GH_REF}\" \"$deployName\"\nfi\n#curl -d '{\"tag_name\": \"v$DATEFMT\",\"target_commitish\": \"build\",\"name\": \"v$DATEFMT\",\"body\": \"Description of the release\",\"draft\": false,\"prerelease\": false}' -X POST \"https://developer.github.com/v3/repos/kimokim/entryjs/releases\"\n"
  },
  {
    "path": "src/class/AILearning.js",
    "content": "import TextLearning, { classes as TextClasses } from './learning/TextLearning';\nimport Cluster, { classes as ClusterClasses } from './learning/Cluster';\nimport Regression, { classes as RegressionClasses } from './learning/Regression';\nimport ImageLearning, { classes as ImageClasses } from './learning/ImageLearning';\nimport SpeechClassification, { classes as SpeechClasses } from './learning/SpeechClassification';\nimport NumberClassification, {\n    classes as NumberClassificationClasses,\n} from './learning/NumberClassification';\nimport DecisionTree, { classes as DecisionTreeClasses } from './learning/DecisionTree';\nimport LogisticRegression, {\n    classes as LogisticRegressionClasses,\n} from './learning/LogisticRegression';\nimport Svm, { classes as SvmClasses } from './learning/Svm';\nimport DataTable from './DataTable';\n\nimport blockAiLearning from '../playground/blocks/block_ai_learning';\nimport blockAiLearningKnn from '../playground/blocks/block_ai_learning_knn';\nimport blockAiLearningCluster from '../playground/blocks/block_ai_learning_cluster';\nimport blockAiLearningRegression from '../playground/blocks/block_ai_learning_regression';\n// eslint-disable-next-line max-len\nimport blockAiLearningLogisticRegression from '../playground/blocks/block_ai_learning_logistic_regression';\nimport blockAiLearningDecisiontree from '../playground/blocks/block_ai_learning_decisiontree';\nimport blockAiLearningSvm from '../playground/blocks/block_ai_learning_svm';\nimport blockAiUtilizeMediaPipe from '../playground/blocks/block_ai_utilize_media_pipe';\nimport InputPopup from './learning/InputPopup';\nimport _isEmpty from 'lodash/isEmpty';\n\nEntry.MlPopup = InputPopup;\nconst basicBlockList = [\n    blockAiLearning,\n    blockAiLearningKnn,\n    blockAiLearningCluster,\n    blockAiLearningRegression,\n    blockAiLearningLogisticRegression,\n    blockAiLearningDecisiontree,\n    blockAiLearningSvm,\n    blockAiUtilizeMediaPipe,\n];\n\nconst banClasses = [\n    ...ClusterClasses,\n    ...RegressionClasses,\n    ...TextClasses,\n    ...ImageClasses,\n    ...SpeechClasses,\n    ...NumberClassificationClasses,\n    ...DecisionTreeClasses,\n    ...LogisticRegressionClasses,\n    ...SvmClasses,\n];\n\nexport default class AILearning {\n    #playground;\n    #categoryName = 'ai_learning';\n    #labels = [];\n    #url;\n    #type;\n    #oid;\n    #modelId;\n    isLoaded = false;\n    isLoading = false;\n    result = [];\n    isEnable;\n    #recordTime = 2000;\n    #module = null;\n    #tableData = null;\n    #dataApi = undefined;\n\n    constructor(playground, isEnable = true) {\n        this.#playground = playground;\n        this.isEnable = isEnable;\n    }\n\n    get labels() {\n        return this.#labels;\n    }\n\n    init() {\n        const blockObject = {};\n        basicBlockList.forEach((value) => {\n            if ('getBlocks' in value) {\n                Object.assign(blockObject, value.getBlocks());\n            }\n        });\n        Entry.block = Object.assign(Entry.block, blockObject);\n    }\n\n    setDataApi(api) {\n        this.#dataApi = api;\n    }\n\n    removeAllBlocks() {\n        const utilizeBlock = [];\n        Object.values(Entry.ALL_AI_UTILIZE_BLOCK_LIST)\n            .map((x) => Object.keys(x.getBlocks()))\n            .forEach((category) => {\n                category.forEach((block) => {\n                    utilizeBlock.push(block);\n                });\n            });\n\n        const { blocks } = EntryStatic.getAllBlocks().find(\n            ({ category }) => category === 'ai_utilize'\n        );\n        blocks\n            .filter((x) => !utilizeBlock.includes(x))\n            .forEach((blockType) => {\n                Entry.Utils.removeBlockByType(blockType);\n            });\n        this.banBlocks();\n        this.destroy();\n    }\n\n    removeLearningBlocks() {\n        if (!this.isLoaded) {\n            return;\n        }\n        this.#modelId = undefined;\n        const { blocks } = EntryStatic.getAllBlocks().find(\n            ({ category }) => category === 'ai_utilize'\n        );\n        blocks\n            .filter((x) => Entry.block?.[x]?.class === 'ai_learning')\n            .forEach((blockType) => {\n                Entry.Utils.removeBlockByType(blockType);\n            });\n        this.banBlocks();\n        this.destroy();\n    }\n\n    async loadModel({ url, trainParam, tableData, isActive, classes }) {\n        const modelPath = await this.#dataApi?.getModelDownloadUrl(url);\n        if (!modelPath || !this.isEnable || !isActive) {\n            return;\n        }\n        const type = this.#type;\n        const name = this.name;\n        const recordTime = this.#recordTime;\n\n        if (type === 'text') {\n            this.#module = new TextLearning({\n                url: modelPath,\n                labels: this.#labels,\n                type,\n                modelId: this.#modelId,\n                loadModel: this.#dataApi?.loadModel,\n            });\n        } else if (type === 'number') {\n            this.#tableData = tableData || createDataTable(classes, name);\n            this.#module = new NumberClassification({\n                name,\n                result: this.result,\n                url: modelPath,\n                trainParam,\n                table: this.#tableData,\n                modelId: this.#modelId,\n                loadModel: this.#dataApi?.loadModel,\n            });\n            this.#labels = this.#module.getLabels();\n        } else if (type === 'cluster') {\n            this.#tableData = tableData || createDataTable(classes, name);\n            this.#module = new Cluster({\n                name,\n                result: this.result,\n                trainParam,\n                table: this.#tableData,\n            });\n        } else if (type === 'regression') {\n            this.#tableData = tableData || createDataTable(classes, name);\n            this.#module = new Regression({\n                name,\n                result: this.result,\n                url: modelPath,\n                trainParam,\n                table: this.#tableData,\n            });\n        } else if (type === 'image') {\n            this.#module = new ImageLearning({\n                url: modelPath,\n                labels: this.#labels,\n                type,\n            });\n        } else if (type === 'speech') {\n            this.#module = new SpeechClassification({\n                url: modelPath,\n                labels: this.#labels,\n                type,\n                recordTime,\n            });\n        } else if (type === 'logisticRegression') {\n            this.#tableData = tableData || createDataTable(classes, name);\n            this.#module = new LogisticRegression({\n                name,\n                result: this.result,\n                url: modelPath,\n                trainParam,\n                table: this.#tableData,\n            });\n        } else if (type === 'decisionTree') {\n            this.#tableData = tableData || createDataTable(classes, name);\n            this.#module = new DecisionTree({\n                name,\n                result: this.result,\n                url: modelPath,\n                trainParam,\n                table: this.#tableData,\n                modelId: this.#modelId,\n                loadModel: this.#dataApi?.loadModel,\n            });\n        } else if (type === 'svm') {\n            this.#tableData = tableData || createDataTable(classes, name);\n            this.#module = new Svm({\n                name,\n                result: this.result,\n                url: modelPath,\n                trainParam,\n                table: this.#tableData,\n                modelId: this.#modelId,\n                loadModel: this.#dataApi?.loadModel,\n            });\n        }\n\n        if (this.#module) {\n            this.unbanBlocks();\n            this.isLoaded = true;\n        }\n    }\n    async load(modelInfo) {\n        const {\n            labels,\n            type,\n            classes = [],\n            model,\n            id,\n            url,\n            _id,\n            isActive = true,\n            name,\n            recordTime,\n            trainParam,\n            tableData,\n            result,\n        } = modelInfo || {};\n        if (!this.#dataApi) {\n            console.log('there is no dataApi');\n            return;\n        } else if (_isEmpty(modelInfo)) {\n            console.log('empty modelInfo');\n            return;\n        }\n        this.destroy();\n\n        if (!labels) {\n            const parsed =\n                classes.length === 1 && typeof classes[0] === 'string'\n                    ? JSON.parse(classes[0])\n                    : classes;\n            this.#labels = parsed.map(({ name }) => name);\n        } else {\n            this.#labels = labels;\n        }\n        this.#type = type;\n        this.#url = url;\n        this.#oid = _id;\n        this.name = name;\n        this.#modelId = model || id;\n        this.#recordTime = recordTime;\n        this.result = result;\n\n        if (this.#playground) {\n            this.#playground.reloadPlayground();\n        }\n\n        this.loadModel({ url, trainParam, tableData, isActive, classes });\n    }\n\n    async reload(url) {\n        await this.#module?.reload?.(url);\n    }\n\n    openInputPopup() {\n        this.#module?.openInputPopup?.();\n    }\n\n    train() {\n        this.#module?.train?.();\n    }\n\n    isTrained() {\n        return this.#module?.isTrained?.();\n    }\n\n    setTrainOption(type, value) {\n        this.#module?.setTrainOption?.(type, value);\n    }\n\n    getTrainOption() {\n        return this.#module?.getTrainOption?.();\n    }\n\n    getTableData() {\n        return this.#tableData;\n    }\n\n    getTrainResult() {\n        return this.#module?.getTrainResult?.();\n    }\n\n    getPredictResult(index) {\n        return this.#module?.getResult?.(index);\n    }\n\n    getId() {\n        return this.#modelId;\n    }\n\n    setVisible(visible) {\n        this.#module?.setVisible?.(visible);\n    }\n\n    setChartVisible(visible) {\n        if (visible) {\n            this.#module?.openChart?.();\n        } else {\n            this.#module?.closeChart?.();\n        }\n    }\n\n    openManager() {\n        if (this.isEnable) {\n            Entry.dispatchEvent('openAIUtilizeTrainManager');\n        } else {\n            console.log('Disabled learning for offline');\n        }\n    }\n\n    async predict(obj) {\n        if (this.#module && this.#module.predict) {\n            this.result = await this.#module.predict(obj);\n        }\n        return [];\n    }\n\n    startPredict() {\n        if (this.#module && this.#module.startPredict) {\n            this.#module.startPredict();\n        }\n    }\n\n    stopPredict() {\n        if (this.#module && this.#module.stopPredict) {\n            this.#module.stopPredict();\n        }\n    }\n\n    unbanBlocks() {\n        this.banBlocks();\n        const blockMenu = getBlockMenu(this.#playground);\n        if (blockMenu) {\n            this.#module?.unbanBlocks?.(blockMenu);\n        }\n    }\n\n    banBlocks() {\n        const blockMenu = getBlockMenu(this.#playground);\n        if (blockMenu) {\n            banClasses.forEach((clazz) => {\n                blockMenu.banClass(clazz);\n            });\n        }\n    }\n\n    destroy() {\n        this.#labels = [];\n        this.#url = null;\n        this.#type = null;\n        this.isLoading = false;\n        this.result = [];\n        this.isLoaded = false;\n        this.#recordTime = 2000;\n        this.#tableData = null;\n        if (this.#module) {\n            this.#module?.destroy?.();\n            this.#module = null;\n        }\n    }\n\n    toJSON() {\n        if (!this.isLoaded) {\n            return;\n        }\n        return {\n            labels: this.#labels,\n            url: this.#url,\n            type: this.#type,\n            id: this.#modelId,\n            _id: this.#oid,\n            recordTime: this.#recordTime,\n            trainParam: this.getTrainOption(),\n            result: this.getTrainResult(),\n            tableData: this.#tableData,\n        };\n    }\n}\n\nfunction getBlockMenu(playground) {\n    const { mainWorkspace } = playground;\n    if (!mainWorkspace) {\n        return;\n    }\n\n    const blockMenu = _.result(mainWorkspace, 'blockMenu');\n    if (!blockMenu) {\n        return;\n    }\n    return blockMenu;\n}\n\nfunction createDataTable(classes, name) {\n    if (!classes.length) {\n        return;\n    }\n    try {\n        const [{ samples }] = classes;\n        const [sample = {}] = samples || [];\n        let data = sample.data;\n        data.id = data.id || data._id;\n        if (typeof data === 'string') {\n            data = JSON.parse(data);\n        }\n        if (data && data?.id && !DataTable.getSource(data?.id)) {\n            DataTable.addSource(data, false);\n        }\n        return data;\n    } catch (e) {\n        console.log('set table error', e);\n    }\n}\n"
  },
  {
    "path": "src/class/AIUtilize.js",
    "content": "import ExtraBlockUtils from '../util/extrablockUtils';\nimport '../playground/blocks/block_ai_utilize_audio';\nimport '../playground/blocks/block_ai_utilize_tts';\nimport '../playground/blocks/block_ai_utilize_translate';\nimport '../playground/blocks/block_ai_utilize_video';\nimport '../playground/blocks/block_ai_utilize_gesture_recognition';\nimport '../playground/blocks/block_ai_utilize_pose_landmarker';\nimport '../playground/blocks/block_ai_utilize_face_landmarker';\nimport '../playground/blocks/block_ai_utilize_object_detector';\n\nexport default class AIUtilize {\n    constructor(playground) {\n        this.playground = playground;\n    }\n\n    init() {\n        const blockObject = {};\n        Object.entries(Entry.AI_UTILIZE_BLOCK).forEach(([key, value]) => {\n            if (key === 'video') {\n                Entry.AI_UTILIZE_BLOCK_LIST_DEPRECATED.video = value;\n            } else {\n                Entry.AI_UTILIZE_BLOCK_LIST[key] = value;\n            }\n            Entry.ALL_AI_UTILIZE_BLOCK_LIST[key] = value;\n            if ('getBlocks' in value) {\n                Object.assign(blockObject, value.getBlocks());\n            }\n        });\n        Entry.block = Object.assign(Entry.block, blockObject);\n    }\n\n    banAllAIUtilizeBlock() {\n        ExtraBlockUtils.banAllBlocks(this.playground, Entry.ALL_AI_UTILIZE_BLOCK_LIST);\n    }\n\n    banAIUtilizeBlocks(aiUtilizeNames = []) {\n        ExtraBlockUtils.banBlocks(\n            aiUtilizeNames,\n            Entry.ALL_AI_UTILIZE_BLOCK_LIST,\n            (aiUtilizeTypes) => Entry.do('objectRemoveAIUtilizeBlocks', aiUtilizeTypes).isPass(true)\n        );\n    }\n\n    isActive(aiUtilizeName) {\n        return ExtraBlockUtils.isActive(aiUtilizeName, Entry.ALL_AI_UTILIZE_BLOCK_LIST);\n    }\n\n    addAIUtilizeBlocks(blockNames) {\n        Entry.do('objectAddAIUtilizeBlocks', blockNames);\n    }\n\n    getAIUtilizes(blockList) {\n        return ExtraBlockUtils.getExtras(blockList, 'category_ai_utilize');\n    }\n\n    destroy() {\n        // 우선 interface 만 정의함.\n    }\n}\n"
  },
  {
    "path": "src/class/DataTable.js",
    "content": "import _map from 'lodash/map';\nimport _sum from 'lodash/sum';\nimport _find from 'lodash/find';\nimport _uniq from 'lodash/uniq';\nimport _every from 'lodash/every';\nimport _filter from 'lodash/filter';\nimport _flatten from 'lodash/flatten';\nimport _cloneDeep from 'lodash/cloneDeep';\nimport _findIndex from 'lodash/findIndex';\nimport _isEmpty from 'lodash/isEmpty';\nimport DataTableSource from './source/DataTableSource';\nimport { DataAnalytics, ModalChart, ModalTable } from '@entrylabs/tool';\n\nclass DataTable {\n    #tables = [];\n    #view;\n    modals = [];\n    selected;\n\n    get tables() {\n        return this.#tables;\n    }\n\n    get dataTables() {\n        return _map(\n            this.#tables,\n            ({ id, fields, chart, name, origin, summary, provider, description, fieldInfos }) => ({\n                id,\n                name,\n                provider,\n                description,\n                fieldInfos,\n                summary,\n                chart: _cloneDeep(chart),\n                table: [[...fields], ..._cloneDeep(origin)],\n            })\n        );\n    }\n\n    constructor() {\n        this.#generateView();\n    }\n\n    removeAllBlocks() {\n        const { blocks } = EntryStatic.getAllBlocks().find(\n            ({ category }) => category === 'analysis'\n        );\n        blocks.forEach((blockType) => {\n            Entry.Utils.removeBlockByType(blockType);\n        });\n        this.banAllBlock();\n        this.clear();\n    }\n\n    banAllBlock() {\n        Entry.playground.blockMenu.banClass('analysis');\n    }\n\n    unbanBlock() {\n        Entry.playground.blockMenu.unbanClass('analysis');\n    }\n\n    getTables(blockList = []) {\n        return _uniq(\n            _flatten(\n                blockList\n                    .filter((block) => {\n                        const { _schema = {}, data = {} } = block || {};\n                        if (!data.type) {\n                            return false;\n                        }\n                        const { isFor, isNotFor = [] } = _schema;\n                        const [key] = isNotFor;\n                        return key && isFor && key === 'analysis';\n                    })\n                    .map((block) => {\n                        const { params = [] } = block.data || {};\n                        return params.filter((param) => {\n                            if (typeof param !== 'string') {\n                                return false;\n                            }\n                            return _find(this.#tables, { id: param });\n                        });\n                    })\n            )\n        ).map((tableId) => {\n            const table = this.getSource(tableId);\n            return table.toJSON();\n        });\n    }\n\n    getSource(id) {\n        if (!id) {\n            console.warn('empty argument');\n            return null;\n        }\n        return _find(this.#tables, { id }) || _find(this.#tables, { _id: id });\n    }\n\n    getIndex({ id }) {\n        if (!id) {\n            console.warn('empty argument');\n            return null;\n        }\n        return _findIndex(this.#tables, { id });\n    }\n\n    addSource(table, view = true) {\n        const data = table || { name: Lang.Workspace.data_table };\n        data.name = Entry.getOrderedName(data.name, this.#tables, 'name');\n\n        this.#tables.push(table instanceof DataTableSource ? table : new DataTableSource(table));\n        this.hide();\n        if (view) {\n            this.show({ list: this.dataTables, selectedIndex: this.dataTables.length - 1 });\n        }\n    }\n\n    addSources(tables = []) {\n        const dataTableSources = _map(tables, (table) =>\n            table instanceof DataTableSource ? table : new DataTableSource(table)\n        );\n        this.#tables.push(...dataTableSources);\n        this.hide();\n        this.show({ list: this.dataTables, selectedIndex: this.dataTables.length - 1 });\n    }\n\n    changeItemPosition(start, end) {\n        if (this.#tables.length) {\n            this.#tables.splice(end, 0, this.#tables.splice(start, 1)[0]);\n        }\n    }\n\n    setSource(selected) {\n        const { chart, table, name, id } = selected;\n        const source = this.getSource(id);\n        if (source) {\n            source.modal = null;\n            source.setArray({\n                name,\n                chart,\n                fields: table[0],\n                data: table.slice(1),\n            });\n            source.updated = new Date();\n        } else {\n            const newSource = new DataTableSource({\n                chart,\n                data: table.slice(1),\n                fields: table[0],\n                name,\n            });\n            this.#tables.push(newSource);\n            selected.id = newSource.id;\n        }\n    }\n\n    saveTable = ({ selected }) => {\n        this.setSource(selected);\n        Entry.playground.reloadPlayground();\n        Entry.creationChangedEvent?.notify();\n    };\n\n    removeTable = (index) => {\n        this.#tables = _filter(this.#tables, (__, tIndex) => index !== tIndex);\n        Entry.creationChangedEvent?.notify();\n    };\n\n    show(data) {\n        if (!this.dataAnalytics) {\n            this.#generateView();\n        }\n        this.dataAnalytics.show(\n            data || { selectedIndex: this.#tables.legnth - 1, list: this.dataTables }\n        );\n    }\n\n    hide() {\n        this.dataAnalytics && this.dataAnalytics.hide();\n        if (this.#tables.length) {\n            this.unbanBlock();\n        } else {\n            this.banAllBlock();\n        }\n        Entry.playground.reloadPlayground();\n        Entry.playground.refreshPlayground();\n        Entry.dispatchEvent('dismissModal');\n    }\n\n    getColumnIndex(col) {\n        if (Entry.Utils.isNumber(col)) {\n            return parseFloat(col);\n        }\n\n        if (/[^A-Za-z]|\\s/.test(col)) {\n            return 0;\n        }\n\n        // return _.chain(col)\n        //     .toUpper()\n        //     .reduce((prev, curr) => prev * 26 + curr.charCodeAt() - 64, 0)\n        //     .value();\n\n        return _sum(\n            _map(\n                col,\n                (cn, i) => (cn.toUpperCase().charCodeAt(0) - 64) * Math.pow(26, col.length - i - 1)\n            )\n        );\n    }\n\n    #generateView() {\n        const view = document.createElement('div');\n        view.className = 'table-modal';\n        document.body.appendChild(view);\n        this.dataAnalytics = new DataAnalytics({ container: view, data: {}, isShow: false })\n            .on('submit', this.saveTable)\n            .on('alert', ({ message, title = Lang.DataAnalytics.max_row_count_error_title }) =>\n                Entry.modal.alert(message, title)\n            )\n            .on('toast', (message) => {\n                const { title, content } = message;\n                Entry.toast.alert(title, content);\n            })\n            .on('close', async () => {\n                this.hide();\n            })\n            .on('addTable', () => {\n                Entry.dispatchEvent('openTableManager');\n            })\n            .on('removeTable', this.removeTable);\n    }\n\n    getTableJSON() {\n        return this.tables.filter(_.identity).map((v) => (v.toJSON ? v.toJSON() : v));\n    }\n\n    setTables(tables = []) {\n        if (_isEmpty(tables)) {\n            return;\n        }\n\n        tables.forEach((table) => {\n            const data = table || { name: Lang.Workspace.data_table };\n            data.name = Entry.getOrderedName(data.name, this.#tables, 'name');\n            const isDataTableSource = data instanceof DataTableSource;\n            this.#tables.push(isDataTableSource ? data : new DataTableSource(data));\n        });\n\n        tables.length && this.refreshPlayground();\n    }\n\n    refreshPlayground() {\n        const isWorkspace = Entry.type === 'workspace';\n        if (isWorkspace) {\n            this.unbanBlock();\n            Entry.playground.reloadPlayground();\n            Entry.playground.refreshPlayground();\n        }\n    }\n\n    showChart(tableId, chartIndex = 0) {\n        this.closeModal();\n        const source = this.getSource(tableId);\n        if (!source) {\n            console.log(`not exist souce, table id: ${tableId}`);\n            return;\n        }\n        let chart = source.modals.find((m) => m.name === 'chart');\n        if (!chart) {\n            chart = this.createChart(source, chartIndex);\n            source.modals.push(chart);\n            this.modals.push(chart);\n        }\n        source.forceApply();\n        chart.show(undefined, { chartIndex });\n    }\n\n    showTable(tableId) {\n        this.closeModal();\n        const source = this.getSource(tableId);\n        if (!source) {\n            console.log(`not exist souce, table id: ${tableId}`);\n            return;\n        }\n        let table = source.modals.find((m) => m.name === 'table');\n        if (!table) {\n            table = this.createTable(source);\n            source.modals.push(table);\n            this.modals.push(table);\n        }\n        source.forceApply();\n        table.show();\n    }\n\n    closeModal() {\n        this.modals.forEach((m) => {\n            m.hide();\n        });\n    }\n\n    createChart(source, chartIndex = 0) {\n        const { chart = [], fields, rows } = source;\n        const container = Entry.Dom('div', {\n            class: 'entry-table-chart',\n            parent: $(Entry.modalContainer),\n        })[0];\n        const modal = new ModalChart({\n            data: {\n                chartIndex,\n                source: { fields, origin: rows, chart },\n                togglePause: () => Entry.engine.togglePause(),\n                stop: () => Entry.engine.toggleStop(),\n                isIframe: self !== top,\n            },\n            container,\n        });\n        modal.name = 'chart';\n        return modal;\n    }\n\n    createTable(source) {\n        const container = Entry.Dom('div', {\n            class: 'entry-table-modal',\n            parent: $(Entry.modalContainer),\n        })[0];\n        const modal = new ModalTable({\n            data: {\n                table: source,\n                tables: this.tables,\n                stop: () => Entry.engine.toggleStop(),\n                isIframe: self !== top,\n                togglePause: () => Entry.engine.togglePause(),\n            },\n            container,\n        });\n        modal.name = 'table';\n        return modal;\n    }\n\n    clear() {\n        this.#tables = [];\n        this.modals = [];\n    }\n}\n\nEntry.DataTable = new DataTable();\n\nexport default Entry.DataTable;\n"
  },
  {
    "path": "src/class/Expansion.js",
    "content": "import ExtraBlockUtils from '../util/extrablockUtils';\nimport '../playground/blocks/block_expansion_weather';\nimport '../playground/blocks/block_expansion_festival';\nimport '../playground/blocks/block_expansion_behaviorconduct_disaster';\nimport '../playground/blocks/block_expansion_behaviorconduct_lifesafety';\nimport '../playground/blocks/block_expansion_emergencyActionGuidelines';\nimport '../playground/blocks/block_expansion_disasterAlert';\n\nexport default class Expansion {\n    constructor(playground) {\n        this.playground = playground;\n    }\n\n    async init() {\n        const blockObject = {};\n        Object.entries(Entry.EXPANSION_BLOCK).forEach(([key, value]) => {\n            if (!value.disabled) {\n                Entry.EXPANSION_BLOCK_LIST[key] = value;\n            }\n            if ('getBlocks' in value) {\n                Object.assign(blockObject, value.getBlocks());\n            }\n        });\n        Entry.block = Object.assign(Entry.block, blockObject);\n    }\n\n    banAllExpansionBlock() {\n        ExtraBlockUtils.banAllBlocks(this.playground, Entry.EXPANSION_BLOCK_LIST);\n    }\n\n    banExpansionBlocks(expansionNames) {\n        ExtraBlockUtils.banBlocks(expansionNames, Entry.EXPANSION_BLOCK_LIST, (expansionTypes) =>\n            Entry.do('objectRemoveExpansionBlocks', expansionTypes).isPass(true)\n        );\n    }\n\n    isActive(expansionName) {\n        return ExtraBlockUtils.isActive(expansionName, Entry.EXPANSION_BLOCK_LIST);\n    }\n\n    addExpansionBlocks(blockNames) {\n        Entry.do('objectAddExpansionBlocks', blockNames);\n    }\n\n    getExpansions(blockList) {\n        return ExtraBlockUtils.getExtras(blockList, 'category_expansion');\n    }\n\n    destroy() {\n        // 우선 interface 만 정의함.\n    }\n}\n"
  },
  {
    "path": "src/class/LiterallycanvasPainter.js",
    "content": "'use strict';\n\nEntry.LiterallycanvasPainter = class LiterallycanvasPainter {\n    constructor(view) {\n        this.view = view;\n        this.baseUrl = Entry.painterBaseUrl;\n\n        this.file = {\n            id: Entry.generateHash(),\n            name: '새그림',\n            modified: false,\n            mode: 'new', // new or edit\n        };\n\n        this._keyboardEvents = [];\n\n        Entry.addEventListener('pictureImport', this.addPicture.bind(this));\n        Entry.addEventListener('run', this.detachKeyboardEvents.bind(this));\n        Entry.addEventListener('stop', this.attachKeyboardEvents.bind(this));\n\n        //dropdown header dispose\n        $('body').on('mouseup', '.active li', () => {\n            $('.painterTopHeader.active').removeClass('active');\n        });\n\n        this.clipboard = null;\n    }\n\n    initialize() {\n        if (this.lc) {\n            return;\n        }\n\n        const that = this;\n\n        const imgURL = that.baseUrl;\n        const bgImage = new Image();\n        bgImage.src = `${imgURL}/transparent-pattern.png`;\n\n        const WIDTH = 960;\n        const HEIGHT = 540;\n        that.lc = LC.init(that.view, {\n            imageURLPrefix: imgURL,\n            zoomMax: 3.0,\n            zoomMin: 0.5,\n            toolbarPosition: 'bottom',\n            imageSize: { width: WIDTH, height: HEIGHT },\n            backgroundShapes: [\n                LC.createShape('Rectangle', {\n                    x: 0,\n                    y: 0,\n                    width: WIDTH,\n                    height: HEIGHT,\n                    strokeWidth: 0,\n                    strokeColor: 'transparent',\n                }),\n            ],\n        });\n        //that.lc.respondToSizeChange();\n\n        bgImage.onload = function () {\n            that.lc.repaintLayer('background');\n        };\n\n        const watchFunc = function (e) {\n            if (e && ((e.shape && !e.opts && e.shape.isPass) || (e.opts && e.opts.isPass))) {\n                Entry.do('processPicture', e, that.lc);\n            } else {\n                Entry.do('editPicture', e, that.lc);\n            }\n            if (Entry.stage.selectedObject) {\n                that.file.modified = true;\n            }\n        };\n\n        that.lc.on('clear', watchFunc);\n        that.lc.on('remove', watchFunc);\n        that.lc.on('shapeEdit', watchFunc);\n        that.lc.on('shapeSave', watchFunc);\n\n        that.lc.on('toolChange', that.updateEditMenu.bind(that));\n        that.lc.on('lc-pointerdrag', that.stagemousemove.bind(that));\n        that.lc.on('lc-pointermove', that.stagemousemove.bind(that));\n\n        that.initTopBar();\n        that.updateEditMenu();\n\n        that.attachKeyboardEvents();\n    }\n\n    show() {\n        if (!this.lc) {\n            this.initialize();\n        }\n        this.isShow = true;\n    }\n\n    hide() {\n        this.isShow = false;\n    }\n\n    changePicture(picture = {}) {\n        if (this.file && this.file.id === picture.id) {\n            if (!this.file.isUpdate) {\n                Entry.stage.updateObject();\n                this.file.isUpdate = true;\n            }\n            return;\n        } else if (!this.file.modified) {\n            this.afterModified(picture);\n        } else {\n            if (this.isConfirm) {\n                return;\n            }\n\n            this.isConfirm = true;\n            let wasRun = false;\n            if (Entry.engine.state === 'run') {\n                Entry.engine.toggleStop();\n                wasRun = true;\n            }\n            Entry.modal.confirm(Lang.Menus.save_modified_shape).then((result) => {\n                this.isConfirm = false;\n                if (result === true) {\n                    this.fileSave(true);\n                } else {\n                    this.file.modified = false;\n                }\n\n                if (!wasRun) {\n                    this.afterModified(picture);\n                } else {\n                    Entry.playground.injectPicture();\n                }\n            });\n        }\n        Entry.stage.updateObject();\n        this.file.isUpdate = true;\n    }\n\n    afterModified(picture) {\n        const file = this.file;\n        file.modified = false;\n        this.lc.clear(false);\n\n        if (picture.id) {\n            file.id = picture.id || Entry.generateHash();\n            file.name = picture.name;\n            file.mode = 'edit';\n            file.objectId = picture.objectId;\n\n            this.addPicture(picture, true);\n        } else {\n            file.id = Entry.generateHash();\n        }\n        // INFO: picture 변경시마다 undoStack 리셋\n        this.lc.undoStack = [];\n        Entry.stateManager.removeAllPictureCommand();\n    }\n\n    getImageSrc(picture) {\n        const { fileurl } = picture || {};\n        if (fileurl) {\n            return fileurl;\n        }\n\n        const { imageType = 'png', filename } = picture || {};\n        return `${Entry.defaultPath}/uploads/${filename.substring(0, 2)}/${filename.substring(\n            2,\n            4\n        )}/image/${filename}.${imageType}`;\n    }\n\n    addPicture(picture, isOriginal) {\n        const image = new Image();\n\n        if (picture.fileurl) {\n            image.src = picture.fileurl;\n        } else {\n            // deprecated\n            image.src = `${Entry.defaultPath}/uploads/${picture.filename.substring(\n                0,\n                2\n            )}/${picture.filename.substring(2, 4)}/image/${picture.filename}.png`;\n        }\n\n        const dimension = picture.dimension;\n        const shape = LC.createShape('Image', {\n            x: 480,\n            y: 270,\n            width: dimension.width,\n            height: dimension.height,\n            image,\n        });\n\n        this.lc.saveShape(shape, !isOriginal);\n\n        image.onload = function () {\n            this.lc.setTool(this.lc.tools.SelectShape);\n            this.lc.tool.setShape(this.lc, shape);\n        }.bind(this);\n    }\n\n    copy() {\n        if (this.lc.tool.name !== 'SelectShape' || !this.lc.tool.selectedShape) {\n            return;\n        }\n\n        const shape = this.lc.tool.selectedShape;\n        this.clipboard = {\n            className: shape.className,\n            data: shape.toJSON(),\n        };\n        this.updateEditMenu();\n    }\n\n    cut() {\n        if (this.lc.tool.name !== 'SelectShape' || !this.lc.tool.selectedShape) {\n            return;\n        }\n\n        this.copy();\n        const shape = this.lc.tool.selectedShape;\n        this.lc.removeShape(shape);\n        this.lc.tool.setShape(this.lc, null);\n    }\n\n    paste() {\n        if (!this.clipboard) {\n            return;\n        }\n\n        const shape = this.lc.addShape(this.clipboard);\n        this.lc.setTool(this.lc.tools.SelectShape);\n        this.lc.tool.setShape(this.lc, shape);\n    }\n\n    updateEditMenu() {\n        const isSelected = this.lc.tool.name === 'SelectShape' ? 'block' : 'none';\n        // this._cutButton.style.display = isSelected;\n        // this._copyButton.style.display = isSelected;\n        // this._pasteButton.style.display = this.clipboard ? \"block\" : \"none\";\n    }\n\n    fileSave(taskParam) {\n        if (!Entry.stage.selectedObject) {\n            return;\n        }\n        this.lc.trigger('dispose');\n        const dataURL = this.lc.getImage().toDataURL();\n        this.file_ = JSON.parse(JSON.stringify(this.file));\n        Entry.dispatchEvent('saveCanvasImage', {\n            file: this.file_,\n            image: dataURL,\n            task: taskParam,\n        });\n\n        this.file.isUpdate = false;\n        this.file.modified = false;\n    }\n\n    newPicture() {\n        if (!Entry.stage.selectedObject) {\n            return;\n        }\n        const newPicture = {\n            dimension: {\n                height: 1,\n                width: 1,\n            },\n            //filename: \"_1x1\",\n            fileurl: `${Entry.mediaFilePath}_1x1.png`,\n            thumbUrl: `${Entry.mediaFilePath}_1x1.png`,\n            name: Lang.Painter.new_picture,\n        };\n\n        newPicture.id = Entry.generateHash();\n        if (this.file && this.file.objectId) {\n            newPicture.objectId = this.file.objectId;\n        }\n        Entry.playground.addPicture(newPicture, true);\n    }\n\n    _keyboardPressControl(e) {\n        if (!this.isShow || Entry.Utils.isInInput(e)) {\n            return;\n        }\n\n        const keyCode = e.keyCode || e.which;\n        const ctrlKey = e.ctrlKey;\n\n        if (keyCode == 8 || keyCode == 46) {\n            //destroy\n            this.cut();\n            e.preventDefault();\n        } else if (ctrlKey) {\n            if (keyCode == 67) {\n                //copy\n                this.copy();\n            } else if (keyCode == 88) {\n                //cut\n                this.cut();\n            }\n        }\n\n        if (ctrlKey && keyCode == 86) {\n            //paste\n            this.paste();\n        }\n        this.lc.trigger('keyDown', e);\n    }\n\n    _keyboardUpControl(e) {\n        if (!this.isShow || Entry.Utils.isInInput(e)) {\n            return;\n        }\n\n        this.lc.trigger('keyUp', e);\n    }\n\n    toggleFullscreen(isFullscreen) {\n        const { painter = {}, pictureView_ } = Entry.playground;\n        const { view = {} } = painter;\n        const $view = $(view);\n        if ((isFullscreen !== true && $view.hasClass('fullscreen')) || isFullscreen === false) {\n            pictureView_.appendChild(view);\n            $(view).removeClass('fullscreen');\n            if (this.fullscreenButton) {\n                this.fullscreenButton.setAttribute('title', Lang.Painter.fullscreen);\n                this.fullscreenButton.setAttribute('alt', Lang.Painter.fullscreen);\n            }\n        } else {\n            document.body.appendChild(view);\n            $(view).addClass('fullscreen');\n            if (this.fullscreenButton) {\n                this.fullscreenButton.setAttribute('title', Lang.Painter.exit_fullscreen);\n                this.fullscreenButton.setAttribute('alt', Lang.Painter.exit_fullscreen);\n            }\n        }\n        $(view).find('.lc-drawing.with-gui').trigger('resize');\n    }\n\n    initTopBar() {\n        const painter = this;\n\n        const ce = Entry.createElement;\n\n        const painterTop = ce(document.getElementById('canvas-top-menu'));\n        painterTop.addClass('entryPlaygroundPainterTop');\n        painterTop.addClass('entryPainterTop');\n\n        const painterTopFullscreenButton = ce('div', 'entryPainterTopFullscreenButton');\n        painterTopFullscreenButton.setAttribute('title', Lang.Painter.fullscreen);\n        painterTopFullscreenButton.setAttribute('alt', Lang.Painter.fullscreen);\n        painterTopFullscreenButton.addClass('entryPlaygroundPainterFullscreenButton');\n        painterTopFullscreenButton.bindOnClick(() => {\n            this.toggleFullscreen();\n        });\n        this.fullscreenButton = painterTopFullscreenButton;\n        painterTop.appendChild(painterTopFullscreenButton);\n\n        const painterTopMenu = ce('nav', 'entryPainterTopMenu');\n        painterTopMenu.addClass('entryPlaygroundPainterTopMenu');\n        painterTop.appendChild(painterTopMenu);\n\n        const painterTopMenuFileNew = ce('div', 'entryPainterTopMenuFileNew');\n        painterTopMenuFileNew.bindOnClick(painter.newPicture.bind(this));\n        painterTopMenuFileNew.addClass('entryPlaygroundPainterTopMenuFileNew');\n        painterTopMenuFileNew.innerHTML = Lang.Painter.new_picture;\n        painterTopMenu.appendChild(painterTopMenuFileNew);\n\n        const painterTopMenuFile = ce('div', 'entryPainterTopMenuFile');\n        painterTopMenuFile.addClass('entryPlaygroundPainterTopMenuFile painterTopHeader');\n        painterTopMenuFile.innerHTML = Lang.Painter.file;\n        const painterTopMenuFileDropdown = ce('div');\n\n        painterTopMenuFileDropdown.addClass('entryPlaygroundPainterTopMenuFileDropdown');\n        painterTopMenu.appendChild(painterTopMenuFile);\n        painterTopMenuFile.appendChild(painterTopMenuFileDropdown);\n\n        const painterTopMenuEdit = ce('div', 'entryPainterTopMenuEdit');\n        painterTopMenuEdit.addClass('entryPlaygroundPainterTopMenuEdit painterTopHeader');\n        painterTopMenuEdit.innerHTML = Lang.Painter.edit;\n        painterTopMenu.appendChild(painterTopMenuEdit);\n\n        const painterTopMenuFileSave = ce('div', 'entryPainterTopMenuFileSave');\n        painterTopMenuFileSave.bindOnClick(() => {\n            painter.fileSave(false);\n        });\n        painterTopMenuFileSave.addClass('entryPainterTopMenuFileSave');\n        painterTopMenuFileSave.innerHTML = Lang.Painter.painter_file_save;\n        painterTopMenuFileDropdown.appendChild(painterTopMenuFileSave);\n\n        const painterTopMenuFileSaveAsLink = ce('div', 'entryPainterTopMenuFileSaveAs');\n        painterTopMenuFileSaveAsLink.bindOnClick(() => {\n            painter.file.mode = 'new';\n            painter.fileSave(false);\n        });\n        painterTopMenuFileSaveAsLink.addClass('entryPlaygroundPainterTopMenuFileSaveAs');\n        painterTopMenuFileSaveAsLink.innerHTML = Lang.Painter.painter_file_saveas;\n        painterTopMenuFileDropdown.appendChild(painterTopMenuFileSaveAsLink);\n\n        const painterTopMenuEditDropdown = ce('div');\n        painterTopMenuEditDropdown.addClass('entryPlaygroundPainterTopMenuEditDropdown');\n        painterTopMenuEdit.appendChild(painterTopMenuEditDropdown);\n\n        const painterTopMenuEditImport = ce('div', 'entryPainterTopMenuEditImport');\n        painterTopMenuEditImport.bindOnClick(() => {\n            Entry.dispatchEvent('openPictureImport');\n        });\n        painterTopMenuEditImport.addClass('entryPainterTopMenuEditImport');\n        painterTopMenuEditImport.innerHTML = Lang.Painter.get_file;\n        painterTopMenuEditDropdown.appendChild(painterTopMenuEditImport);\n\n        const painterTopMenuEditCopy = ce('div', 'entryPainterTopMenuEditCopy');\n        painterTopMenuEditCopy.bindOnClick(() => {\n            painter.copy();\n        });\n        painterTopMenuEditCopy.addClass('entryPlaygroundPainterTopMenuEditCopy');\n        painterTopMenuEditCopy.innerHTML = Lang.Painter.copy_file;\n        painterTopMenuEditDropdown.appendChild(painterTopMenuEditCopy);\n\n        const painterTopMenuEditCut = ce('div', 'entryPainterTopMenuEditCut');\n        painterTopMenuEditCut.bindOnClick(() => {\n            painter.cut();\n        });\n        painterTopMenuEditCut.addClass('entryPlaygroundPainterTopMenuEditCut');\n        painterTopMenuEditCut.innerHTML = Lang.Painter.cut_picture;\n        painterTopMenuEditDropdown.appendChild(painterTopMenuEditCut);\n\n        const painterTopMenuEditPaste = ce('div', 'entryPainterTopMenuEditPaste');\n        painterTopMenuEditPaste.bindOnClick(() => {\n            painter.paste();\n        });\n        painterTopMenuEditPaste.addClass('entryPlaygroundPainterTopMenuEditPaste');\n        painterTopMenuEditPaste.innerHTML = Lang.Painter.paste_picture;\n        painterTopMenuEditDropdown.appendChild(painterTopMenuEditPaste);\n\n        const painterTopMenuEditEraseAll = ce('div', 'entryPainterTopMenuEditEraseAll');\n        painterTopMenuEditEraseAll.addClass('entryPlaygroundPainterTopMenuEditEraseAll');\n        painterTopMenuEditEraseAll.innerHTML = Lang.Painter.remove_all;\n        painterTopMenuEditEraseAll.bindOnClick(() => {\n            painter.lc.clear();\n        });\n        painterTopMenuEditDropdown.appendChild(painterTopMenuEditEraseAll);\n\n        $(painterTopMenuFile).on('click tab', menuClickEvent);\n        $(painterTopMenuEdit).on('click tab', menuClickEvent);\n        $(document).on('click tap', (e) => {\n            e.stopPropagation();\n            $(painterTopMenuFile).removeClass('active');\n            $(painterTopMenuEdit).removeClass('active');\n        });\n\n        const painterTopStageXY = ce('div', 'entryPainterTopStageXY');\n        const entryPainterTopStageXYLabel = ce('span', 'entryPainterTopStageXYLabel');\n        this.painterTopStageXY = entryPainterTopStageXYLabel;\n        painterTopStageXY.addClass('entryPlaygroundPainterTopStageXY');\n        entryPainterTopStageXYLabel.addClass('entryPainterTopStageXYLabel');\n        painterTopStageXY.appendChild(entryPainterTopStageXYLabel);\n        painterTop.appendChild(painterTopStageXY);\n\n        Entry.addEventListener('pictureSelected', this.changePicture.bind(this));\n\n        function menuClickEvent(e) {\n            $(painterTopMenuFile).removeClass('active');\n            $(painterTopMenuEdit).removeClass('active');\n            if (e.target === this) {\n                e.stopImmediatePropagation();\n                $(this).addClass('active');\n            }\n        }\n    }\n\n    stagemousemove(event) {\n        this.painterTopStageXY.textContent = `x:${event.x.toFixed(1)}, y:${event.y.toFixed(1)}`;\n    }\n\n    attachKeyboardEvents() {\n        this.detachKeyboardEvents();\n\n        const events = this._keyboardEvents;\n\n        let evt = Entry.keyPressed;\n        evt && events.push(evt.attach(this, this._keyboardPressControl));\n\n        evt = Entry.keyUpped;\n        evt && events.push(evt.attach(this, this._keyboardUpControl));\n    }\n\n    detachKeyboardEvents() {\n        const events = this._keyboardEvents;\n        if (!events || !events.length) {\n            return;\n        }\n\n        while (events.length) {\n            const evt = events.pop();\n            evt.destroy && evt.destroy();\n        }\n    }\n\n    clear() {\n        this.toggleFullscreen(false);\n    }\n\n    undo() {\n        this.lc.undo();\n    }\n\n    redo() {\n        if (this.lc.canRedo()) {\n            this.lc.redo();\n        }\n    }\n};\n"
  },
  {
    "path": "src/class/blockCountViewer.js",
    "content": "import _get from 'lodash/get';\n\nEntry.BlockCountViewer = class {\n    constructor() {\n        if (!Entry.codeChangedEvent) {\n            Entry.codeChangedEvent = new Entry.Event(window);\n        }\n\n        const updateView = () => {\n            Entry.Utils.clearObjectsBlocksForEventThread();\n            this.updateView();\n        };\n\n        Entry.codeChangedEvent.attach(this, updateView);\n        Entry.addEventListener('loadComplete', updateView);\n    }\n\n    generateView(sceneView, option) {\n        this.view_ = sceneView;\n        if (!option || option === 'workspace' || option === 'playground') {\n            const blockCountView = Entry.createElement('span').addClass('blockCountView');\n            this.view_.appendChild(blockCountView);\n            this.blockCountView = blockCountView;\n            this.updateView();\n        }\n    }\n\n    async updateView() {\n        if (this.blockCountView) {\n            const blocks = await Entry.Utils.getObjectsBlocksForEventThread();\n            const count = _get(blocks, 'length', 0);\n\n            let langText = Lang.Workspace.use_blocks_project;\n            if (count === 1) {\n                langText = Lang.Workspace.use_block_project;\n            }\n            this.blockCountView.innerHTML = Entry.Utils.stringFormat(\n                langText,\n                `<strong>${Entry.Utils.shortenNumber(count)}</strong>`\n            );\n        }\n    }\n\n    destroy() {\n        // 우선 interface 만 정의함.\n    }\n};\n"
  },
  {
    "path": "src/class/container.js",
    "content": "/**\n * @fileoverview Container handle all object in entry.\n */\n\n'use strict';\n\nimport { Draggable } from '@entrylabs/tool';\nimport { GEHelper } from '../graphicEngine/GEHelper';\nimport DataTable from './DataTable';\nimport { getInputList } from '@entrylabs/legacy-video';\n/**\n * Class for a container.\n * This have view for objects.\n * @constructor\n */\nEntry.Container = class Container {\n    constructor() {\n        /**\n         * Array for entry objects\n         * @type {Array.<Entry.EntryObject>}\n         */\n        this.objects_ = [];\n\n        /**\n         * Dictionary for caching images\n         * @type {Dictionary.<createjs.Image}\n         */\n        this.cachedPicture = {};\n\n        this.selectedObject = null;\n\n        /**\n         * variable for canvas input\n         * @type {String}\n         */\n        this.inputValue = {};\n        this.sttValue = {};\n        /**\n         * object model store copied object by context menu\n         * @type {object model}\n         */\n        this.copiedObject = null;\n\n        this.isObjectDragging = false;\n        /**\n         * Array for storing current scene objects\n         * @type {Array.<object model>}\n         */\n        this.currentObjects_ = null;\n        this._extensionObjects = [];\n        Entry.addEventListener('workspaceChangeMode', () => {\n            const ws = Entry.getMainWS();\n            if (ws && ws.getMode() === Entry.Workspace.MODE_VIMBOARD) {\n                this.objects_.forEach(({ script }) => {\n                    script && script.destroyView();\n                });\n            }\n        });\n\n        Entry.addEventListener('run', this.disableSort.bind(this));\n        Entry.addEventListener('stop', this.enableSort.bind(this));\n    }\n\n    /**\n     * Control bar view generator.\n     * @param {!Element} containerView containerView from Entry.\n     */\n    generateView(containerView) {\n        this._view = containerView;\n        this._view.addClass('entryContainer');\n        this._view.addClass('entryContainerWorkspace');\n        this._view.setAttribute('id', 'entryContainerWorkspaceId');\n\n        const addButton = Entry.createElement('div')\n            .addClass('entryAddObjectWorkspace')\n            .bindOnClick(() => {\n                Entry.dispatchEvent('openSpriteManager');\n            });\n        addButton.textContent = Lang.Workspace.add_object;\n\n        const ulWrapper = Entry.createElement('div');\n        this._view.appendChild(ulWrapper);\n\n        // const scroll = new Simplebar(ulWrapper, { autoHide: false });\n        const scrollWrapper = ulWrapper;\n        let baseClass = 'entryContainerListWorkspaceWrapper';\n        if (Entry.isForLecture) {\n            baseClass += ' lecture';\n        }\n        scrollWrapper.addClass(baseClass);\n        Entry.Utils.disableContextmenu(scrollWrapper);\n\n        const longPressEvent = (e) => {\n            let longPressTimer = null;\n            const doc = $(document);\n\n            longPressTimer = setTimeout(() => {\n                if (longPressTimer) {\n                    longPressTimer = null;\n                    this._rightClick(e);\n                }\n            }, 1000);\n\n            const event = Entry.Utils.convertMouseEvent(e);\n            const mouseDownCoordinate = { x: event.clientX, y: event.clientY };\n\n            // 움직임 포착된 경우 타이머 종료\n            doc.bind('mousemove.container touchmove.container', (e) => {\n                const event = Entry.Utils.convertMouseEvent(e);\n                const moveThreshold = 5;\n                if (!mouseDownCoordinate) {\n                    return;\n                }\n                const diff = Math.sqrt(\n                    Math.pow(event.pageX - mouseDownCoordinate.x, 2) +\n                        Math.pow(event.pageY - mouseDownCoordinate.y, 2)\n                );\n\n                if (diff > moveThreshold && longPressTimer) {\n                    clearTimeout(longPressTimer);\n                    longPressTimer = null;\n                }\n            });\n\n            // 터치가 끝난 경우 타이머 종료\n            doc.bind('mouseup.container touchend.container', () => {\n                doc.unbind('.container');\n                if (longPressTimer) {\n                    clearTimeout(longPressTimer);\n                    longPressTimer = null;\n                }\n            });\n        };\n        /*\n         * 오른쪽 버튼 클릭 시 컨텍스트메뉴 발생\n         */\n        scrollWrapper.addEventListener('mousedown', (e) => {\n            if (Entry.Utils.isRightButton(e)) {\n                e.stopPropagation();\n                this._rightClick(e);\n            }\n\n            if (Entry.isMobile()) {\n                e.stopPropagation();\n                longPressEvent(e);\n            }\n        });\n\n        /*\n         * 터치 디바이스의 롱클릭 대응. touch 1초간 유지시 컨텍스트메뉴 발생.\n         * 현재위치에서 일정 범위 이상 벗어난 경우취소\n         */\n        scrollWrapper.addEventListener('touchstart', (e) => {\n            if (e.eventFromEntryObject) {\n                return;\n            }\n\n            longPressEvent(e);\n        });\n\n        const extensionListView = Entry.createElement('ul');\n        scrollWrapper.appendChild(extensionListView);\n        this._extensionListView = Entry.Dom(extensionListView, {\n            class: 'entryContainerExtensions',\n        });\n\n        const listView = Entry.createElement('ul').addClass('entryContainerListWorkspace');\n        scrollWrapper.appendChild(listView);\n        this.listView_ = listView;\n\n        this.enableSort();\n    }\n\n    enableSort() {\n        if (this.sortableListViewWidget) {\n            this.sortableListViewWidget.setData({\n                disabled: false,\n            });\n        } else {\n            const draggableOption = {};\n            if (Entry.isMobile()) {\n                draggableOption.lockAxis = 'y';\n                draggableOption.distance = 50;\n            }\n            this.sortableListViewWidget = new Draggable({\n                data: {\n                    ...draggableOption,\n                    canSortable: true,\n                    sortableTarget: ['entryObjectThumbnailWorkspace'],\n                    items: this._getSortableObjectList(),\n                    itemShadowStyle: {\n                        position: 'absolute',\n                        height: '100%',\n                        width: '100%',\n                        backgroundColor: '#8aa3b2',\n                        border: 'solid 1px #728997',\n                    },\n                    onDragActionChange: (isDragging, key) => {\n                        if (!Entry.objectEditable) {\n                            return;\n                        }\n                        Entry.ContextMenu.hide();\n                        if (isDragging) {\n                            this.selectedObject.setObjectFold(isDragging, true);\n                        } else {\n                            this.selectedObject.resetObjectFold();\n                        }\n                        Entry.playground.setBackpackPointEvent(isDragging);\n                        this.dragObjectKey = key;\n                        this.isObjectDragging = isDragging;\n                    },\n                    onChangeList: (newIndex, oldIndex) => {\n                        if (!Entry.objectEditable) {\n                            return;\n                        }\n                        if (newIndex !== oldIndex) {\n                            Entry.do('objectReorder', newIndex, oldIndex);\n                        }\n                    },\n                },\n                container: this.listView_,\n            });\n        }\n    }\n\n    updateSortableObjectList(objects) {\n        this.sortableListViewWidget.setData({\n            items: this._getSortableObjectList(objects),\n        });\n    }\n\n    _getSortableObjectList(objects) {\n        const targetObjects = objects || this.currentObjects_ || [];\n\n        return targetObjects.map((value) => {\n            const { id, view_, thumbUrl } = value;\n            return {\n                key: id,\n                item: view_,\n                image: thumbUrl,\n            };\n        });\n    }\n\n    /**\n     * disable sort.\n     */\n    disableSort() {\n        const view = this.listView_;\n\n        if (!view) {\n            return;\n        }\n\n        this.sortableListViewWidget.setData({ disabled: true });\n    }\n\n    /**\n     * update list view to sort item.\n     */\n    updateListView() {\n        const view = this.listView_;\n\n        if (!view) {\n            return;\n        }\n\n        let objs = this.getCurrentObjects().slice();\n\n        const ret = objs.filter(({ index }) => index !== undefined);\n\n        if (ret.length === objs.length) {\n            objs = objs.sort((a, b) => a.index - b.index);\n        }\n\n        objs.forEach((obj) => {\n            !obj.view_ && obj.generateView();\n        });\n\n        Entry.stage.sortZorder();\n        this.updateSortableObjectList(objs);\n        return true;\n    }\n\n    setObjects(objectModels) {\n        objectModels.forEach((model) => {\n            if (model) {\n                const object = new Entry.EntryObject(model);\n                this.objects_.push(object);\n            }\n        });\n        this.updateObjectsOrder();\n        this.updateListView();\n        Entry.variableContainer.updateViews();\n        const type = Entry.type;\n        if (type === 'workspace' || type === 'phone' || type === 'playground') {\n            const target = this.getCurrentObjects()[0];\n            target && this.selectObject(target.id);\n        }\n    }\n\n    /**\n     * get Pictures element\n     * @param {!String} pictureId\n     */\n    getPictureElement(pictureId, objectId) {\n        const object = this.getObject(objectId);\n        const picture = object.getPicture(pictureId);\n        if (picture) {\n            return picture.view;\n        } else {\n            throw new Error('No picture found');\n        }\n    }\n    /**\n     * Set Pictures\n     * @param {!Object picture} picture\n     */\n    setPicture(picture) {\n        const pictures = this.getObject(picture.objectId).pictures;\n        const index = _.findIndex(pictures, ({ id }) => id === picture.id);\n        if (!~index) {\n            throw new Error('No picture found');\n        }\n        pictures[index] = Object.assign(\n            _.pick(picture, [\n                'dimension',\n                'id',\n                'filename',\n                'fileurl',\n                'thumbUrl',\n                'name',\n                'imageType',\n            ]),\n            { view: pictures[index].view }\n        );\n    }\n\n    /**\n     * Set Pictures\n     * @param {!String} pictureId\n     */\n    selectPicture(pictureId, objectId) {\n        const object = this.getObject(objectId);\n        const picture_ = object.getPicture(pictureId);\n        if (picture_) {\n            object.selectedPicture = picture_;\n            object.entity.setImage(picture_);\n            object.updateThumbnailView();\n            this.sortableListViewWidget.setData({\n                items: this._getSortableObjectList(),\n            });\n            return object.id;\n        }\n        throw new Error('No picture found');\n    }\n\n    selectSound(soundId, objectId) {\n        const object = this.getObject(objectId);\n        const sound = object.getSound(soundId);\n        if (sound) {\n            object.selectedSound = sound;\n            return object.id;\n        }\n        throw new Error('No sound found');\n    }\n\n    /**\n     * Add object\n     * @param {!object model} objectModel\n     * @param {?number} index exist when user add object\n     * @return {Entry.EntryObject}\n     */\n    addObject(objectModel, ...rest) {\n        let target;\n        if ('name' in objectModel.sprite) {\n            target = objectModel.sprite;\n        } else {\n            target = objectModel;\n            if (!target.name) {\n                target.name = 'untitled';\n            }\n        }\n        target.name = Entry.getOrderedName(target.name, this.objects_);\n        objectModel.id = objectModel.id || Entry.generateHash();\n        return Entry.do('addObject', objectModel, ...rest);\n    }\n\n    addObjectFunc(objectModel, index, isNotRender) {\n        delete objectModel.scene;\n        const object = new Entry.EntryObject(objectModel);\n        object.scene = Entry.scene.selectedScene;\n\n        let isBackground = objectModel.sprite.category || {};\n        isBackground = isBackground.main === 'background';\n\n        if (typeof index === 'number') {\n            if (isBackground) {\n                object.setLock(true);\n                this.objects_.push(object);\n            } else {\n                this.objects_.splice(index, 0, object);\n            }\n        } else if (isBackground) {\n            this.objects_.push(object);\n        } else {\n            this.objects_.unshift(object);\n        }\n        if (!isNotRender) {\n            object.generateView();\n            this.setCurrentObjects();\n            this.selectObject(object.id);\n            this.updateObjectsOrder();\n            this.updateListView();\n            Entry.variableContainer.updateViews();\n            Entry.variableContainer.updateList();\n        }\n    }\n\n    renderObject(object) {\n        object.generateView();\n        this.setCurrentObjects();\n        this.selectObject(object.id);\n        Entry.variableContainer.updateViews();\n    }\n\n    addExtension(obj) {\n        this._extensionObjects.push(obj);\n        if (this._extensionListView) {\n            this._extensionListView.append(obj.renderView());\n        }\n        return obj;\n    }\n\n    removeExtension(obj) {\n        if (!obj) {\n            return;\n        }\n\n        const extensions = this._extensionObjects;\n        const index = extensions.indexOf(obj);\n        if (~index) {\n            extensions.splice(index, 1);\n        }\n\n        obj.destroy && obj.destroy();\n    }\n\n    /**\n     * Add Clone object\n     * @param {!Entry.EntryObject} object\n     */\n    addCloneObject(object, scene, isNotRender) {\n        const json = object.toJSON(true);\n\n        json.script = change('sounds', object, json);\n        json.script = change('pictures', object, json);\n\n        Entry.variableContainer.addCloneLocalVariables({\n            objectId: object.id,\n            newObjectId: json.id,\n            json,\n        });\n        json.scene = scene || Entry.scene.selectedScene;\n        this.addObject(json, null, isNotRender);\n\n        return this.getObject(json.id);\n\n        function change(keyName, object, jsonData) {\n            const target = jsonData.sprite[keyName];\n            let script = jsonData.script;\n            (object[keyName] || []).forEach((value, index) => {\n                script = script.replace(new RegExp(value.id, 'g'), target[index].id);\n            });\n            return script;\n        }\n    }\n\n    removeObject(id, isPass) {\n        const objects = this.objects_;\n\n        const object = this.getObject(id);\n        const index = objects.indexOf(object);\n\n        object.destroy();\n        objects.splice(index, 1);\n        Entry.variableContainer.removeLocalVariables(object.id);\n        Entry.engine.hideProjectTimer();\n\n        if (isPass === true) {\n            return;\n        }\n\n        this.setCurrentObjects();\n        Entry.stage.sortZorder();\n        const [first] = this.getCurrentObjects();\n        if (first) {\n            this.selectObject(first.id);\n        } else {\n            Entry.stage.selectObject(null);\n            Entry.playground.flushPlayground();\n        }\n\n        this.updateListView();\n        Entry.playground.reloadPlayground();\n        GEHelper.resManager.imageRemoved('container::removeObject');\n    }\n\n    /**\n     * Select object\n     * @param {string} objectId\n     */\n    selectObject(objectId, changeScene) {\n        if (!objectId) {\n            return;\n        }\n        const object = this.getObject(objectId);\n        const workspace = Entry.getMainWS();\n        const isSelected = object && object.isSelected();\n        if (changeScene && object) {\n            Entry.scene.selectScene(object.scene);\n        }\n\n        const className = 'selectedObject';\n        this.mapObjectOnScene((o) => {\n            !o.view_ && _.result(o, 'generateView');\n            const selected = o === object;\n            const view = o.view_;\n            if (view) {\n                if (selected) {\n                    view.addClass(className);\n                } else {\n                    view.removeClass(className);\n                    o.setObjectFold(false);\n                }\n            }\n\n            o.isSelected_ = selected;\n        });\n\n        if (object) {\n            if (workspace && workspace.vimBoard && Entry.isTextMode) {\n                const sObject = workspace.vimBoard._currentObject;\n                const parser = workspace.vimBoard._parser;\n                if (sObject && !this.getObject(sObject.id)) {\n                } else if (parser && parser._onError) {\n                    if (sObject && object.id != sObject.id) {\n                        if (!Entry.scene.isSceneCloning) {\n                            try {\n                                workspace._syncTextCode();\n                            } catch (e) {}\n                            if (parser && !parser._onError) {\n                                this.selectObject(object.id, true);\n                                return;\n                            } else {\n                                this.selectObject(sObject.id, true);\n                                return;\n                            }\n                        } else {\n                            this.selectObject(sObject.id);\n                            return;\n                        }\n                    }\n                } else {\n                    if (sObject && object.id != sObject.id) {\n                        if (!Entry.scene.isSceneCloning) {\n                            try {\n                                workspace._syncTextCode();\n                            } catch (e) {}\n                            if (parser && parser._onError) {\n                                this.selectObject(sObject.id, true);\n                                return;\n                            }\n                        } else {\n                            this.selectObject(sObject.id);\n                            return;\n                        }\n                    }\n                }\n            }\n        } else {\n            workspace && workspace.vimBoard && workspace.vimBoard.clearText();\n        }\n\n        if (Entry.playground) {\n            object ? Entry.playground.injectObject(object) : Entry.playground.injectEmptyObject();\n        }\n        if (Entry.type !== 'minimize' && Entry.engine.isState('stop')) {\n            Entry.stage.selectObject(object);\n        }\n        this.selectedObject = object;\n        !isSelected && object && object.updateCoordinateView();\n    }\n\n    /**\n     * Get all objects\n     */\n    getAllObjects() {\n        return this.objects_;\n    }\n\n    /**\n     * Object Getter\n     * @param {string} objectId\n     * @return {Entry.EntryObject}\n     */\n    getObject(objectId) {\n        const playground = Entry.playground;\n        if (!objectId && playground && playground.object) {\n            objectId = playground.object.id;\n        } else if (objectId instanceof Entry.EntryObject) {\n            return objectId;\n        }\n\n        return _.find(this.objects_, { id: objectId });\n    }\n\n    /**\n     * Entity Getter\n     * @param {string} objectId\n     * @return {Entry.EntityObject}\n     */\n    getEntity(objectId) {\n        const object = this.getObject(objectId);\n        if (!object) {\n            return Entry.toast.alert(\n                Lang.Msgs.runtime_error,\n                Lang.Workspace.object_not_found,\n                true\n            );\n        }\n        return object.entity;\n    }\n\n    /**\n     * get variable on canvas\n     * @return {Entry.Variable}\n     */\n    getVariable(variableId) {\n        for (let i = 0; i < this.variables_.length; i++) {\n            const variable = this.variables_[i];\n            if (variable.getId() == variableId) {\n                return variable;\n            }\n            if (variable.getName() == variableId) {\n                return variable;\n            }\n        }\n    }\n\n    /**\n     * Move object in objects_\n     * this method is for sortable\n     * @param {number!} start\n     * @param {number!} end\n     * @param {boolean?} isCallFromState\n     * @return {Entry.State}\n     */\n    moveElement(end, start) {\n        const objs = this.getCurrentObjects();\n        const startIndex = this.getAllObjects().indexOf(objs[start]);\n        const endIndex = this.getAllObjects().indexOf(objs[end]);\n        this.objects_.splice(endIndex, 0, this.objects_.splice(startIndex, 1)[0]);\n        this.setCurrentObjects();\n        this.updateListView();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * generate list for dropdown dynamic\n     * obj param for renderview.changeCode\n     * @param {string} menuName\n     * @param {string} obj\n     */\n    async getDropdownList(menuName, obj) {\n        let result = [];\n        switch (menuName) {\n            case 'sprites':\n                result = this.getCurrentObjects().map(({ name, id }) => [name, id]);\n                break;\n            case 'allSprites':\n                result = this.getAllObjects().map(({ name, id, scene = {} }) => {\n                    const { name: sceneName } = scene;\n                    return [`${sceneName} - ${name}`, id];\n                });\n                break;\n            case 'spritesWithMouse':\n                result = this.getCurrentObjects().map(({ name, id }) => [name, id]);\n                result.push([Lang.Blocks.mouse_pointer, 'mouse']);\n                break;\n            case 'spritesWithSelf':\n                result = this.getCurrentObjects().map(({ name, id }) => [name, id]);\n                result.push([Lang.Blocks.self, 'self']);\n                break;\n            case 'textBoxWithSelf': {\n                result = [\n                    ...this.getCurrentObjects().reduce((acc, { objectType, name, id }) => {\n                        if (objectType === 'textBox') {\n                            acc.push([name, id]);\n                        }\n                        return acc;\n                    }, result),\n                    [Lang.Blocks.self, 'self'],\n                ];\n                break;\n            }\n            case 'collision':\n                result = [\n                    [Lang.Blocks.mouse_pointer, 'mouse'],\n                    ...this.getCurrentObjects().map(({ name, id }) => [name, id]),\n                    [Lang.Blocks.wall, 'wall'],\n                    [Lang.Blocks.wall_up, 'wall_up'],\n                    [Lang.Blocks.wall_down, 'wall_down'],\n                    [Lang.Blocks.wall_right, 'wall_right'],\n                    [Lang.Blocks.wall_left, 'wall_left'],\n                ];\n                break;\n            case 'pictures': {\n                const object = Entry.playground.object || obj;\n                if (!object) {\n                    break;\n                }\n                result = (object.pictures || []).map(({ name, id }) => [name, id]);\n                break;\n            }\n            case 'messages':\n                result = Entry.variableContainer.messages_.map(({ name, id }) => [name, id]);\n                break;\n            case 'variables': {\n                const object = Entry.playground.object || obj;\n                if (!object) {\n                    break;\n                }\n                Entry.variableContainer.variables_.forEach((variable) => {\n                    if (\n                        variable.object_ &&\n                        object &&\n                        (variable.object_ != object.id || Entry.Func.isEdit)\n                    ) {\n                        return;\n                    }\n                    result.push([variable.getName(), variable.getId()]);\n                });\n                if (!result || result.length === 0) {\n                    // result.push([Lang.Blocks.VARIABLE_variable, 'null']);\n                    result = [];\n                }\n                break;\n            }\n            case 'lists': {\n                const object = Entry.playground.object || obj;\n                if (!object) {\n                    break;\n                }\n                Entry.variableContainer.lists_.forEach((list) => {\n                    if (\n                        list.object_ &&\n                        object &&\n                        (list.object_ != object.id || Entry.Func.isEdit)\n                    ) {\n                        return;\n                    }\n                    result.push([list.getName(), list.getId()]);\n                });\n\n                if (!result || result.length === 0) {\n                    // result.push([Lang.Blocks.VARIABLE_list, 'null']);\n                    result = [];\n                }\n                break;\n            }\n            case 'tables': {\n                const { tables } = DataTable;\n                if (tables) {\n                    result = tables.map((table) => [table.name, table.id]);\n                }\n                break;\n            }\n            case 'scenes':\n                result = Entry.scene.getScenes().map(({ name, id }) => [name, id]);\n                break;\n            case 'sounds': {\n                const object = Entry.playground.object || obj;\n                if (!object) {\n                    break;\n                }\n                result = (object.sounds || []).map(({ name, id }) => [name, id]);\n                break;\n            }\n            case 'clone':\n                result = [\n                    [Lang.Blocks.oneself, 'self'],\n                    ...this.getCurrentObjects().map(({ name, id }) => [name, id]),\n                ];\n                break;\n            case 'objectSequence':\n                for (let i = 0; i < this.getCurrentObjects().length; i++) {\n                    result.push([(i + 1).toString(), i.toString()]);\n                }\n                break;\n            case 'fonts':\n                result = EntryStatic.fonts\n                    .filter((x) => x.visible)\n                    .map((font) => [font.name, font.family]);\n                break;\n            case 'connectedCameras': {\n                const inputList = await getInputList();\n                result = [].concat(\n                    inputList\n                        .filter((input) => input.kind === 'videoinput')\n                        .map((item, index) => [\n                            item.label || `Unspecified Device-${index + 1}`,\n                            index,\n                        ])\n                );\n                break;\n            }\n            case 'blockCount':\n                result = [\n                    [Lang.Blocks.this_project, 'all'],\n                    [Lang.Blocks.this_object, 'self'],\n                    ...this.getCurrentObjects().map(({ name, id }) => [name, `object-${id}`]),\n                    ...Entry.scene.getScenes().map(({ name, id }) => [name, `scene-${id}`]),\n                ];\n        }\n        if (!result.length) {\n            result = [[Lang.Blocks.no_target, 'null']];\n        }\n        return result;\n    }\n\n    /**\n     * Initialize entities to state before run\n     */\n    clearRunningState() {\n        this.mapObject((object) => {\n            object.clearExecutor();\n        });\n    }\n\n    clearRunningStateOnScene() {\n        this.mapObjectOnScene((object) => {\n            if (object instanceof Entry.TargetChecker) {\n                return;\n            }\n            object.clearExecutor();\n        });\n    }\n\n    /**\n     * Apply map function to objects. But this not replace object with returned one.\n     * So giving map function don't have to return object.\n     * And this support another arguments.\n     * @param {!function} mapFunction\n     * @param {} param\n     */\n    mapObject(mapFunction, param) {\n        return [...this._extensionObjects, ...this.objects_].map((object) =>\n            mapFunction(object, param)\n        );\n    }\n\n    mapObjectOnScene(mapFunction, param) {\n        return [...this._extensionObjects, ...this.getCurrentObjects()].map((object) =>\n            mapFunction(object, param)\n        );\n    }\n\n    /**\n     * Apply map function to objects. But this not replace object with returned one.\n     * So giving map function don't have to return object.\n     * And this support another arguments.\n     * @param {!function} mapFunction\n     * @param {} param\n     */\n    mapEntity(mapFunction, param) {\n        return this.objects_.map(({ entity }) => mapFunction(entity, param));\n    }\n\n    mapEntityOnScene(mapFunction, param) {\n        return this.getCurrentObjects().map(({ entity }) => mapFunction(entity, param));\n    }\n\n    /**\n     * Apply map function to objects. But this not replace object with returned one.\n     * So giving map function don't have to return object.\n     * And this support another arguments.\n     * This also apply to cloned entities.\n     * @param {!function} mapFunction\n     * @param {} param\n     */\n    mapEntityIncludeClone(mapFunction, param) {\n        const objects = this.objects_;\n        const length = objects.length;\n        const output = [];\n        for (let i = 0; i < length; i++) {\n            const object = objects[i];\n            const lenx = object.clonedEntities.length;\n            output.push(mapFunction(object.entity, param));\n            for (let j = 0; j < lenx; j++) {\n                const entity = object.clonedEntities[j];\n                if (entity && !entity.isStamp) {\n                    output.push(mapFunction(entity, param));\n                }\n            }\n        }\n        return output;\n    }\n\n    mapEntityIncludeCloneOnScene(mapFunction, param) {\n        const objects = this.getCurrentObjects();\n        const length = objects.length;\n        const output = [];\n        for (let i = 0; i < this._extensionObjects.length; i++) {\n            const object = this._extensionObjects[i];\n            output.push(mapFunction(object.entity, param));\n        }\n        for (let i = 0; i < length; i++) {\n            const object = objects[i];\n            output.push(mapFunction(object.entity, param));\n\n            object.getClonedEntities().forEach((entity) => {\n                output.push(mapFunction(entity, param));\n            });\n        }\n        return output;\n    }\n\n    /**\n     * @deprecated 새로운 리소스 관리자 생겨서 이제 사용안함\n     * Get cached picture\n     * @param {!string} pictureId\n     * @return {?createjs.Image}\n     */\n    getCachedPicture(pictureId) {\n        Entry.assert(typeof pictureId === 'string', 'pictureId must be string');\n        return this.cachedPicture[pictureId];\n    }\n\n    /**\n     * @deprecated 새로운 리소스 관리자 생겨서 이제 사용안함\n     * cache picture\n     * @param {!picture object} pictureModel\n     */\n    cachePicture(pictureId, image) {\n        this.cachedPicture[pictureId] = image;\n    }\n\n    /**\n     * @deprecated 새로운 리소스 관리자 생겨서 이제 사용안함\n     * @param entity\n     * @param pictures\n     * @param isClone\n     */\n    unCachePictures(entity, pictures, isClone) {\n        if (!entity || !pictures) {\n            return;\n        }\n        let entityId;\n\n        if (pictures.constructor !== Array) {\n            pictures = [pictures];\n        }\n\n        if (entity.constructor === Entry.EntityObject) {\n            entityId = entity.id;\n        } else {\n            entityId = entity;\n        }\n\n        pictures.forEach(({ id }) => {\n            delete this.cachedPicture[id + (isClone ? '' : entityId)];\n        });\n    }\n\n    /**\n     * convert this object's data to JSON.\n     * @return {JSON}\n     */\n    toJSON() {\n        return this.objects_.map((object) => object.toJSON());\n    }\n\n    /**\n     * take snapshot of current objects sequence\n     */\n    takeSequenceSnapshot() {\n        const length = this.objects_.length;\n        const objects = this.objects_;\n        for (let i = 0; i < length; i++) {\n            objects[i].index = i;\n        }\n    }\n\n    /**\n     * load snapshot of original objects sequence\n     */\n    loadSequenceSnapshot() {\n        const length = this.objects_.length;\n        const arr = new Array(length);\n        for (let i = 0; i < length; i++) {\n            const object = this.objects_[i];\n            const _index = object.index !== undefined ? object.index : i;\n            arr[_index] = object;\n            delete object.index;\n        }\n        this.objects_ = arr;\n        this.setCurrentObjects();\n        Entry.stage.sortZorder();\n        this.updateListView();\n    }\n\n    /**\n     * return canvas inputValue\n     * @return {String}\n     */\n    getInputValue() {\n        return this.inputValue.getValue();\n    }\n\n    getSttValue() {\n        return this.sttValue.getValue();\n    }\n\n    /**\n     * set canvas inputValue\n     * @param {String} inputValue from canvas\n     */\n    setInputValue(inputValue) {\n        if (this.inputValue.complete) {\n            return;\n        }\n        if (!inputValue) {\n            this.inputValue.setValue(0);\n        } else {\n            this.inputValue.setValue(inputValue);\n        }\n        Entry.stage.hideInputField();\n        Entry.dispatchEvent('answerSubmitted');\n        if (Entry.console) {\n            Entry.console.stopInput(inputValue);\n        }\n        this.inputValue.complete = true;\n    }\n\n    setSttValue(inputValue) {\n        if (this.sttValue.complete) {\n            return;\n        }\n        if (!inputValue) {\n            this.sttValue.setValue('');\n        } else {\n            this.sttValue.setValue(inputValue);\n        }\n        Entry.dispatchEvent('sttSubmitted');\n\n        this.sttValue.complete = true;\n    }\n\n    enableSttValue() {\n        this.sttValue.complete = false;\n    }\n\n    resetSceneDuringRun() {\n        if (!Entry.engine.isState('run')) {\n            return;\n        }\n\n        this.mapEntityOnScene((entity) => {\n            entity.reset();\n        });\n        this.clearRunningStateOnScene();\n        Entry.stage.hideInputField();\n    }\n\n    setCopiedObject(object) {\n        this.copiedObject = object;\n    }\n\n    updateObjectsOrder() {\n        this.objects_ = Entry.scene\n            .getScenes()\n            .reduce((objs, scene) => [...objs, ...this.getSceneObjects(scene)], []);\n    }\n\n    /**\n     *  get objects list belonged to specific scene\n     *  @param {scene model} scene\n     *  @return {Array<object model>}\n     */\n    getSceneObjects(scene) {\n        scene = scene || Entry.scene.selectedScene;\n        if (!scene) {\n            return [];\n        }\n\n        const sceneId = scene.id;\n        return this.getAllObjects().filter(({ scene: { id } }) => id === sceneId);\n    }\n\n    /**\n     *  set objects list belonged to specific scene\n     */\n    setCurrentObjects() {\n        this.currentObjects_ = this.getSceneObjects();\n        if (this.currentObjects_.length) {\n            Entry.playground.hidePictureCurtain();\n        } else {\n            Entry.playground.showPictureCurtain();\n        }\n    }\n\n    /**\n     *  get objects list belonged to current scene\n     */\n    getCurrentObjects() {\n        if (_.isEmpty(this.currentObjects_)) {\n            this.setCurrentObjects();\n        }\n        return this.currentObjects_ || [];\n    }\n\n    /**\n     *  get project jsons in art_view for saving especially for art_viewcontroller\n     *  @param {!resource project} project\n     *  @return {entry project} project\n     */\n    getProjectWithJSON(project) {\n        project.objects = this.toJSON();\n        project.variables = Entry.variableContainer.getVariableJSON();\n        project.messages = Entry.variableContainer.getMessageJSON();\n        project.scenes = Entry.scene.toJSON();\n        return project;\n    }\n\n    blurAllInputs() {\n        this.getSceneObjects().map(({ view_ }) => {\n            $(view_).find('input').blur();\n        });\n    }\n\n    showProjectAnswer() {\n        const answer = this.inputValue;\n        if (!answer) {\n            return;\n        }\n        answer.setVisible(true);\n    }\n    showSttAnswer() {\n        const answer = this.sttValue;\n        if (!answer) {\n            return;\n        }\n        answer.setVisible(true);\n    }\n\n    hideProjectAnswer(removeBlock, notIncludeSelf) {\n        const answer = this.inputValue;\n        if (!answer || !answer.isVisible() || Entry.engine.isState('run')) {\n            return;\n        }\n\n        const objects = this.getAllObjects();\n        const answerTypes = ['ask_and_wait', 'get_canvas_input_value', 'set_visible_answer'];\n\n        for (let i = 0, len = objects.length; i < len; i++) {\n            const code = objects[i].script;\n            for (let j = 0; j < answerTypes.length; j++) {\n                const blocks = code.getBlockList(false, answerTypes[j]);\n                if (notIncludeSelf) {\n                    const index = blocks.indexOf(removeBlock);\n                    if (~index) {\n                        blocks.splice(index, 1);\n                    }\n                }\n                if (blocks.length) {\n                    return;\n                }\n            }\n        }\n\n        //answer related blocks not found\n        //hide canvas answer view\n        answer.setVisible(false);\n    }\n    hideSttAnswer(removeBlock, notIncludeSelf) {\n        const answer = this.sttValue;\n        if (!answer || !answer.isVisible() || Entry.engine.isState('run')) {\n            return;\n        }\n\n        const objects = this.getAllObjects();\n        const answerTypes = ['ask_and_wait', 'get_canvas_input_value', 'set_visible_answer'];\n\n        for (let i = 0, len = objects.length; i < len; i++) {\n            const code = objects[i].script;\n            for (let j = 0; j < answerTypes.length; j++) {\n                const blocks = code.getBlockList(false, answerTypes[j]);\n                if (notIncludeSelf) {\n                    const index = blocks.indexOf(removeBlock);\n                    if (~index) {\n                        blocks.splice(index, 1);\n                    }\n                }\n                if (blocks.length) {\n                    return;\n                }\n            }\n        }\n\n        //answer related blocks not found\n        //hide canvas answer view\n        answer.setVisible(false);\n    }\n\n    getView() {\n        return this._view;\n    }\n\n    // dummy\n    resize() {\n        return;\n    }\n\n    _rightClick = (e) => {\n        e.stopPropagation();\n        const touchEvent = Entry.Utils.convertMouseEvent(e);\n\n        const options = [\n            {\n                text: Lang.Blocks.Paste_blocks,\n                enable: !Entry.engine.isState('run') && !!this.copiedObject,\n                callback: () => {\n                    if (this.copiedObject) {\n                        this.addCloneObject(this.copiedObject);\n                    } else {\n                        Entry.toast.alert(\n                            Lang.Workspace.add_object_alert,\n                            Lang.Workspace.object_not_found_for_paste\n                        );\n                    }\n                },\n            },\n        ];\n\n        Entry.ContextMenu.show(options, 'workspace-contextmenu', {\n            x: touchEvent.clientX,\n            y: touchEvent.clientY,\n        });\n    };\n\n    removeFuncBlocks(functionType) {\n        this.objects_.forEach(({ script }) => {\n            script.removeBlocksByType(functionType);\n        });\n    }\n\n    clear() {\n        [...this.objects_, ...this._extensionObjects].forEach((o) => o.destroy());\n        this.objects_ = [];\n        // INFO : clear 시도할때 _extensionObjects 초기화\n        this._extensionObjects = [];\n        // TODO: clear 때 this._extensionListView 도 비워 줘야 하는지 확인 필요.\n        Entry.playground.clear();\n    }\n\n    selectNeighborObject(option) {\n        const objects = this.getCurrentObjects();\n        if (!objects || objects.length === 0) {\n            return;\n        }\n\n        let currentIndex = objects.indexOf(Entry.playground.object);\n        const maxLen = objects.length;\n        switch (option) {\n            case 'prev':\n                if (--currentIndex < 0) {\n                    currentIndex = objects.length - 1;\n                }\n                break;\n            case 'next':\n                currentIndex = ++currentIndex % maxLen;\n                break;\n        }\n\n        const object = objects[currentIndex];\n        if (!object) {\n            return;\n        }\n\n        this.selectObject(object.id);\n    }\n\n    getObjectIndex(objectId) {\n        return this.objects_.indexOf(this.getObject(objectId));\n    }\n\n    getDom(query) {\n        if (query.length >= 1) {\n            switch (query.shift()) {\n                case 'objectIndex':\n                    return this.objects_[query.shift()].getDom(query);\n                case 'objectId':\n                    return this.getObject(query.shift()).getDom(query);\n            }\n        } else {\n        }\n    }\n\n    isSceneObjectsExist() {\n        return !_.isEmpty(this.getSceneObjects());\n    }\n\n    adjustClonedValues(oldIds, newIds) {\n        if (!(oldIds && newIds)) {\n            return;\n        }\n        const that = this;\n        newIds.forEach((newId) => {\n            that.getObject(newId)\n                .script.getBlockList()\n                .forEach((b) => {\n                    if (!b || !b.params) {\n                        return;\n                    }\n                    let changed = false;\n                    const ret = b.params.map((p) => {\n                        if (typeof p !== 'string') {\n                            return p;\n                        }\n                        const index = oldIds.indexOf(p);\n                        if (index < 0) {\n                            return p;\n                        }\n                        changed = true;\n                        return newIds[index];\n                    });\n                    changed && b.set({ params: ret });\n                });\n        });\n    }\n\n    getBlockList() {\n        return _.flatten(this.objects_.map(({ script }) => script.getBlockList()));\n    }\n\n    scrollToObject(ObjectId) {\n        const { view_ } = this.getObject(ObjectId);\n\n        view_ && view_.scrollIntoView();\n        document.body.scrollIntoView();\n    }\n\n    setSound(sound) {\n        const sounds = this.getObject(sound.objectId).sounds;\n        const index = _.findIndex(sounds, ({ id }) => id === sound.id);\n        if (!~index) {\n            throw new Error('No sound found');\n        }\n        const path =\n            sound.fileurl ||\n            `${Entry.defaultPath}/uploads/${sound.filename.substring(\n                0,\n                2\n            )}/${sound.filename.substring(2, 4)}/${Entry.soundPath}${sound.filename}${\n                sound.ext || '.mp3'\n            }`;\n        sounds[index] = Object.assign(\n            _.pick(sound, [\n                'duration',\n                'ext',\n                'fileurl',\n                'filename',\n                'id',\n                'label',\n                'name',\n                'path',\n            ]),\n            {\n                view: sounds[index].view,\n                path,\n            }\n        );\n        return sounds[index];\n    }\n\n    destroy() {\n        // 우선 interface 만 정의함.\n    }\n};\n"
  },
  {
    "path": "src/class/dialog.ts",
    "content": "'use strict';\n\nimport * as PIXI from 'pixi.js';\nimport { GEHelper } from '../graphicEngine/GEHelper';\n\ntype EntryObjectEntity = any;\n\ntype NotchType = 'ne' | 'nw' | 'se' | 'sw';\n\nconst _cache = new Map();\nclass EntryDialog {\n    private parent: EntryObjectEntity;\n    private padding = 10;\n    private border = 2;\n    private width: number;\n    private height: number;\n    private notch: any;\n    private _isNoContentTried: boolean;\n    private readonly message_: string;\n    private readonly mode_: 'speak' | 'ask' | 'yell' | 'think';\n    public object: any;\n\n    constructor(\n        entity: EntryObjectEntity,\n        message: string | number,\n        mode: 'speak' | 'ask' | 'yell' | 'think',\n        isStamp: boolean\n    ) {\n        if (entity.isEngineStop) {\n            return;\n        }\n        if (entity.dialog) {\n            entity.dialog.remove(true);\n        }\n        entity.dialog = this;\n        this.parent = entity;\n\n        let messageString = typeof message == 'number' ? String(message) : message;\n        if (Entry.console) {\n            Entry.console.print(message, mode);\n        }\n        messageString = messageString.match(/.{1,15}/g).join('\\n');\n        this.message_ = messageString;\n        this.mode_ = mode;\n        if (mode === 'speak' || mode === 'ask' || mode === 'think' || mode === 'yell') {\n            this.generateSpeak(mode);\n        }\n        if (!isStamp) {\n            Entry.stage.loadDialog(this);\n        }\n    }\n\n    private getNotchType(bound: any) {\n        const parentObj = this.parent.object;\n        const entity = parentObj.entity;\n        const cache = _cache.get(parentObj.id) || {};\n        const { x, y } = cache;\n        let notchType = cache.notchType;\n\n        if (entity.x != x || entity.y != y) {\n            if (bound.y - 20 - this.border > -135) {\n                notchType = 'n';\n            } else {\n                notchType = 's';\n            }\n            if (bound.x + bound.width / 2 < 0) {\n                notchType += 'e';\n            } else {\n                notchType += 'w';\n            }\n            _cache.set(parentObj.id, {\n                notchType,\n                x: entity.x,\n                y: entity.y,\n            });\n        }\n\n        return notchType;\n    }\n\n    private setNotchPositionForPixi(bound: any) {\n        const notchType = this.getNotchType(bound);\n        if (notchType.includes('n')) {\n            this.object.y = Math.max(\n                bound.y - this.height / 2 - 20 - this.padding,\n                -135 + this.height / 2 + this.padding\n            );\n        } else {\n            this.object.y = Math.min(\n                bound.y + bound.height + this.height / 2 + 20 + this.padding,\n                135 - this.height / 2 - this.padding\n            );\n        }\n        if (notchType.includes('e')) {\n            this.object.x = Math.min(\n                bound.x + bound.width + this.width / 2,\n                240 - this.width / 2 - this.padding\n            );\n        } else {\n            this.object.x = Math.max(\n                bound.x - this.width / 2,\n                -240 + this.width / 2 + this.padding\n            );\n        }\n        return notchType;\n    }\n\n    private setNotchPositionForCreateJs(bound: any) {\n        let notchType = '';\n        if (bound.y - 20 - this.border > -135) {\n            this.object.y = Math.max(\n                bound.y - this.height / 2 - 20 - this.padding,\n                -135 + this.height / 2 + this.padding\n            );\n            notchType += 'n';\n        } else {\n            this.object.y = Math.min(\n                bound.y + bound.height + this.height / 2 + 20 + this.padding,\n                135 - this.height / 2 - this.padding\n            );\n            notchType += 's';\n        }\n        if (bound.x + bound.width / 2 < 0) {\n            this.object.x = Math.min(\n                bound.x + bound.width + this.width / 2,\n                240 - this.width / 2 - this.padding\n            );\n            notchType += 'e';\n        } else {\n            this.object.x = Math.max(\n                bound.x - this.width / 2,\n                -240 + this.width / 2 + this.padding\n            );\n            notchType += 'w';\n        }\n        return notchType;\n    }\n\n    /**\n     * Set position\n     */\n    update() {\n        const parentObj = this.parent.object;\n        let bound = GEHelper.calcParentBound(parentObj);\n        if (!bound && this.parent.type === 'textBox') {\n            if (!this._isNoContentTried) {\n                this.parent.setText(' ');\n                bound = GEHelper.calcParentBound(parentObj);\n                this._isNoContentTried = true;\n            } else {\n                delete this._isNoContentTried;\n                return;\n            }\n        }\n        if (!this.object) {\n            return;\n        }\n\n        let notchType = '';\n\n        if (GEHelper.isWebGL) {\n            notchType = this.setNotchPositionForPixi(bound);\n        } else {\n            notchType = this.setNotchPositionForCreateJs(bound);\n        }\n\n        if (this.notch && this.notch.type != notchType) {\n            this.object.removeChild(this.notch);\n            if (this.mode_ === 'think') {\n                this.notch = this.createThinkkNotch(notchType as NotchType);\n                this.object.addChild(this.notch);\n            } else if (this.mode_ === 'speak' || this.mode_ === 'ask') {\n                this.notch = this.createSpeakNotch(notchType as NotchType);\n                this.object.addChild(this.notch);\n            }\n        }\n\n        this._isNoContentTried && this.parent.setText('');\n        Entry.requestUpdate = true;\n    }\n\n    remove(saveCache: boolean) {\n        if (!saveCache) {\n            _cache.clear();\n        }\n        Entry.stage.unloadDialog(this);\n        this.parent.dialog = null;\n        Entry.requestUpdate = true;\n    }\n\n    private createSpeakNotch(type: NotchType) {\n        const notch = GEHelper.newGraphic();\n        notch.type = type;\n        const colorSet = EntryStatic.colorSet.canvas || {};\n        const height = this.height + this.padding;\n        const padding = this.padding;\n        const width = this.width;\n        if (type === 'ne') {\n            notch.graphics\n                .f('#ffffff')\n                .ss(3, 2)\n                .s('#ffffff')\n                .mt(3, height)\n                .lt(11, height)\n                .ss(2, 1, 1)\n                .s(colorSet.dialog || '#4f80ff')\n                .mt(2, height)\n                .lt(2, height + 9)\n                .lt(12, height);\n        } else if (type === 'nw') {\n            notch.graphics\n                .f('#ffffff')\n                .ss(3, 2)\n                .s('#ffffff')\n                .mt(width - 3, height)\n                .lt(width - 11, height)\n                .ss(2, 1, 1)\n                .s(colorSet.dialog || '#4f80ff')\n                .mt(width - 2, height)\n                .lt(width - 2, height + 9)\n                .lt(width - 12, height);\n        } else if (type === 'se') {\n            notch.graphics\n                .f('#ffffff')\n                .ss(3, 2)\n                .s('#ffffff')\n                .mt(3, -padding)\n                .lt(11, -padding)\n                .ss(2, 1, 1)\n                .s(colorSet.dialog || '#4f80ff')\n                .mt(2, -padding)\n                .lt(2, -padding - 9)\n                .lt(12, -padding);\n        } else if (type === 'sw') {\n            notch.graphics\n                .f('#ffffff')\n                .ss(3, 2)\n                .s('#ffffff')\n                .mt(width - 3, -padding)\n                .lt(width - 11, -padding)\n                .ss(2, 1, 1)\n                .s(colorSet.dialog || '#4f80ff')\n                .mt(this.width - 2, -padding)\n                .lt(width - 2, -padding - 9)\n                .lt(width - 12, -padding);\n        }\n        return notch;\n    }\n\n    private createThinkkNotch(type: NotchType) {\n        const notch = GEHelper.newGraphic();\n        notch.type = type;\n        const colorSet = EntryStatic.colorSet.canvas || {};\n        const height = this.height + this.padding;\n        const padding = this.padding;\n        const width = this.width;\n        if (type === 'ne') {\n            notch.graphics\n                .f('#ffffff')\n                .ss(3, 2)\n                .s('#ffffff')\n                .mt(3, height)\n                .lt(11, height)\n                .ss(2, 1, 1)\n                .s(colorSet.dialog || '#4f80ff')\n                .mt(2, height)\n                .qt(2, height + 9, 12, height)\n                .de(2, height + 9, 5, 4);\n        } else if (type === 'nw') {\n            notch.graphics\n                .f('#ffffff')\n                .ss(3, 2)\n                .s('#ffffff')\n                .mt(width - 3, height)\n                .lt(width - 11, height)\n                .ss(2, 1, 1)\n                .s(colorSet.dialog || '#4f80ff')\n                .mt(width, height)\n                .qt(width, height + 9, width - 12, height)\n                .de(width - 3, height + 9, 5, 4);\n        } else if (type === 'se') {\n            notch.graphics\n                .f('#ffffff')\n                .ss(3, 2)\n                .s('#ffffff')\n                .mt(3, -padding)\n                .lt(11, -padding)\n                .ss(2, 1, 1)\n                .s(colorSet.dialog || '#4f80ff')\n                .mt(2, -padding)\n                .qt(2, -padding - 9, 12, -padding)\n                .de(0, -padding - 12, 5, 4);\n        } else if (type === 'sw') {\n            notch.graphics\n                .f('#ffffff')\n                .ss(3, 2)\n                .s('#ffffff')\n                .mt(width - 3, -padding)\n                .lt(width - 11, -padding)\n                .ss(2, 1, 1)\n                .s(colorSet.dialog || '#4f80ff')\n                .mt(this.width - 2, -padding)\n                .qt(width - 2, -padding - 9, width - 12, -padding)\n                .de(width - 6, -padding - 12, 5, 4);\n        }\n        return notch;\n    }\n\n    private drawZigZagLineX({ ctx, x1, y1, x2, y2, padding, zigzagSpacing, oneZigZagLength }: any) {\n        let zx = 0;\n        ctx.moveTo(x1 + padding, y1);\n        for (let n = 0; zx < x2 - padding; n++) {\n            zx = (n + 1) * zigzagSpacing + x1 + padding;\n            const zy = (n % 2 == 0 ? -oneZigZagLength : oneZigZagLength) + y1;\n            ctx.lineTo(zx, zy);\n        }\n        ctx.lineTo(x2 - padding, y2);\n    }\n    private drawZigZagLineY({ ctx, x1, y1, x2, y2, padding, zigzagSpacing, oneZigZagLength }: any) {\n        let zy = 0;\n        ctx.moveTo(x1, y1 + padding);\n        for (let n = 0; zy < y2 - padding; n++) {\n            zy = (n + 1) * zigzagSpacing + y1 + padding;\n            const zx = (n % 2 !== 0 ? -oneZigZagLength : oneZigZagLength) + x1;\n            ctx.lineTo(zx, zy);\n        }\n        ctx.lineTo(x2, y2 - padding);\n    }\n    private drawZigZagRect({ x, y, w, h, borderColor, fillColor }: any) {\n        const rect = GEHelper.newGraphic();\n        const zigzagSpacing = 3;\n        const oneZigZagLength = 5;\n        const ctx = rect.graphics;\n        ctx.setStrokeStyle(1);\n        ctx.beginStroke(borderColor);\n        ctx.beginFill(fillColor);\n        const padding = 10;\n        this.drawZigZagLineX({\n            ctx,\n            x1: x,\n            y1: y,\n            x2: x + w,\n            y2: y,\n            padding,\n            zigzagSpacing,\n            oneZigZagLength,\n        });\n        ctx.lineTo(x + w, y + padding);\n        this.drawZigZagLineY({\n            ctx,\n            x1: x + w,\n            y1: y,\n            x2: x + w,\n            y2: y + h,\n            padding,\n            zigzagSpacing,\n            oneZigZagLength,\n        });\n        ctx.lineTo(x + w - padding, y + h);\n        this.drawZigZagLineX({\n            ctx,\n            x1: x,\n            y1: y + h,\n            x2: x + w,\n            y2: y + h,\n            padding,\n            zigzagSpacing,\n            oneZigZagLength,\n        });\n        ctx.moveTo(x + padding, y + h);\n        ctx.lineTo(x, y + h - padding);\n        this.drawZigZagLineY({\n            ctx,\n            x1: x,\n            y1: y,\n            x2: x,\n            y2: y + h,\n            padding,\n            zigzagSpacing,\n            oneZigZagLength,\n        });\n        ctx.moveTo(x + padding, y);\n        ctx.lineTo(x, y + padding);\n        return rect;\n    }\n\n    private drawYellStart({ x, y, w, h, fillColor, borderColor }: any) {\n        const star = GEHelper.newGraphic();\n        const pointSize = 0.2;\n        const radius = Math.sqrt(w * w + h * h) / 2;\n        const sides = 30;\n        const angle = -90;\n        star.graphics\n            .f(fillColor)\n            .ss(2, 'round')\n            .s(borderColor)\n            .drawPolyStar(x + radius / 2, y + radius / 2, radius, sides, pointSize, angle);\n        return star;\n    }\n\n    private generateSpeak(mode: 'speak' | 'ask' | 'yell' | 'think') {\n        this.object = GEHelper.newContainer('[dialog] container');\n        const fontFamily = EntryStatic.fontFamily || \"NanumGothic, 'Nanum Gothic'\";\n        const text = GEHelper.textHelper.newText(\n            this.message_,\n            `15px ${fontFamily}`,\n            '#000000',\n            'top',\n            'left'\n        );\n\n        let bound;\n        if (GEHelper.isWebGL) {\n            bound = text;\n        } else {\n            bound = text.getTransformedBounds();\n        }\n\n        const height = bound.height;\n        const width = bound.width >= 10 ? bound.width : 17;\n        const colorSet = EntryStatic.colorSet.canvas || {};\n        if (mode === 'yell') {\n            const rect = this.drawZigZagRect({\n                x: -this.padding,\n                y: -this.padding,\n                w: width + 2 * this.padding,\n                h: height + 2 * this.padding,\n                fillColor: colorSet.dialogBG || '#ffffff',\n                borderColor: colorSet.dialog || '#4f80ff',\n            });\n            this.object.addChild(rect);\n        } else {\n            const rect = GEHelper.newGraphic();\n            rect.graphics\n                .f(colorSet.dialogBG || '#ffffff')\n                .ss(2, 'round')\n                .s(colorSet.dialog || '#4f80ff')\n                .rr(\n                    -this.padding,\n                    -this.padding,\n                    width + 2 * this.padding,\n                    height + 2 * this.padding,\n                    this.padding\n                );\n            this.object.addChild(rect);\n        }\n        this.object.regX = width / 2;\n        this.object.regY = height / 2;\n        this.width = width;\n        this.height = height;\n        if (mode === 'think') {\n            this.notch = this.createThinkkNotch('nw');\n            this.object.addChild(this.notch);\n        } else if (mode === 'speak' || mode === 'ask') {\n            this.notch = this.createSpeakNotch('nw');\n            this.object.addChild(this.notch);\n        }\n        this.update();\n        this.object.addChild(text);\n        Entry.requestUpdate = true;\n    }\n}\n\nexport default EntryDialog;\nEntry.Dialog = EntryDialog;\n"
  },
  {
    "path": "src/class/doneProject.js",
    "content": "'use strict';\n\nrequire('../util/static');\n\nEntry.DoneProject = class DoneProject {\n    constructor(id) {\n        this.generateView(id);\n    }\n    init(projectId) {\n        this.projectId = projectId;\n    }\n\n    generateView(doneProject) {\n        // this.youtubeTab.removeClass('entryRemove');\n\n        const doneContainer = Entry.createElement('div');\n        doneContainer.addClass('entryContainerDoneWorkspace');\n        // var parentcontainer = document.getElementById('entryContainerWorkspaceId');\n\n        this.doneContainer = doneContainer;\n        const view = this.doneContainer;\n        // var width = parentcontainer.offsetWidth;\n\n        const url = '/api/iframe/project/';\n        const iframe = Entry.createElement('iframe');\n        iframe.setAttribute('id', 'doneProjectframe');\n        iframe.setAttribute('frameborder', 0);\n        iframe.setAttribute('src', url + doneProject);\n        this.doneProjectFrame = iframe;\n        this.doneContainer.appendChild(iframe);\n        doneContainer.addClass('entryRemove');\n    }\n\n    getView() {\n        return this.doneContainer;\n    }\n\n    resize() {\n        const iframe = document.getElementById('doneProjectframe');\n        const w = this.doneContainer.offsetWidth;\n\n        iframe.width = `${w}px`;\n        iframe.height = `${(w * 9) / 16}px`;\n    }\n};\n"
  },
  {
    "path": "src/class/engine.js",
    "content": "import { GEHelper } from '../graphicEngine/GEHelper';\nimport audioUtils from '../util/audioUtils';\n\nconst EntryEngineState = {\n    stop: 'stop',\n    stopping: 'stopping',\n    pause: 'pause',\n    run: 'run',\n};\n\nEntry.Engine = class Engine {\n    constructor() {\n        this.execPromises = [];\n        this.state = EntryEngineState.stop;\n        this.popup = null;\n        this.isUpdating = true;\n        this.speeds = [1, 15, 30, 45, 60];\n        this.engineTimer = {\n            isInit: false,\n            isPaused: false,\n            start: 0,\n            pauseStart: 0,\n            pausedTime: 0,\n        };\n        this._engineTimeouts = [];\n        this._engineTimeoutSeq = 0;\n\n        this.attachKeyboardCapture();\n\n        const _addEventListener = Entry.addEventListener.bind(Entry);\n\n        _addEventListener('canvasClick', () => this.fireEvent('mouse_clicked'));\n        _addEventListener('canvasClickCanceled', () => this.fireEvent('mouse_click_cancled'));\n        _addEventListener('entityClick', (entity) => {\n            const objId = entity.id;\n            Entry.stage.clickedObjectId = objId;\n            this.fireEventOnEntity('when_object_click', entity);\n        });\n        _addEventListener('entityClickCanceled', (entity) => {\n            delete Entry.stage.clickedObjectId;\n            this.fireEventOnEntity('when_object_click_canceled', entity);\n        });\n\n        if (Entry.type !== 'phone' && Entry.type !== 'playground') {\n            _addEventListener(\n                'stageMouseMove',\n                _.throttle(this.updateMouseView.bind(this), 100, {\n                    leading: false,\n                })\n            );\n            _addEventListener('stageMouseOut', this.hideMouseView.bind(this));\n        }\n\n        const $win = $(window);\n        _addEventListener('run', () => $win.bind('keydown', arrowHandler));\n        _addEventListener('stop', () => $win.unbind('keydown', arrowHandler));\n\n        function arrowHandler(e) {\n            const code = e.keyCode || e.which;\n            const input = Entry.stage.inputField;\n\n            if (code === 32 && input && input.hasFocus()) {\n                return;\n            }\n\n            if (_.includes([37, 38, 39, 40, 32], code)) {\n                e.preventDefault();\n            }\n        }\n\n        Entry.message = new Entry.Event(window);\n    }\n\n    /**\n     * Control bar view generator.\n     * @param {!Element} controlView controlView from Entry.\n     * @param {?string} option for choose type of view.\n     */\n    generateView(controlView, option = 'workspace') {\n        this.option = option;\n        if (option === 'workspace') {\n            /** @type {!Element} */\n            this.view_ = controlView;\n            this.view_.addClass('entryEngine_w').addClass('entryEngineWorkspace_w');\n            this.view_.addClass('test');\n\n            this.speedButton = Entry.createElement('button')\n                .addClass(\n                    'entrySpeedButtonWorkspace',\n                    'entryEngineTopWorkspace',\n                    'entryEngineButtonWorkspace_w'\n                )\n                .appendTo(this.view_)\n                .bindOnClick(function (e) {\n                    Entry.engine.toggleSpeedPanel();\n                    this.blur();\n                });\n\n            this.maximizeButton = Entry.createElement('button')\n                .addClass(\n                    'entryEngineButtonWorkspace_w',\n                    'entryEngineTopWorkspace',\n                    'entryMaximizeButtonWorkspace_w'\n                )\n                .appendTo(this.view_)\n                .bindOnClick(function (e) {\n                    Entry.engine.toggleFullScreen();\n                    this.blur();\n                });\n\n            this.coordinateButton = Entry.createElement('button')\n                .addClass(\n                    'entryEngineButtonWorkspace_w',\n                    'entryEngineTopWorkspace',\n                    'entryCoordinateButtonWorkspace_w'\n                )\n                .appendTo(this.view_)\n                .bindOnClick(function (e) {\n                    if (this.hasClass('toggleOn')) {\n                        this.removeClass('toggleOn');\n                    } else {\n                        this.addClass('toggleOn');\n                    }\n\n                    this.blur();\n                    Entry.stage.toggleCoordinator();\n                });\n\n            this.mouseView = Entry.createElement('div')\n                .addClass('entryMouseViewWorkspace_w')\n                .addClass('entryHide')\n                .appendTo(this.view_);\n\n            this.mouseViewInput = Entry.createElement('input').appendTo(this.mouseView);\n            $(this.mouseViewInput).attr('readonly', 'readonly');\n\n            this.buttonWrapper = Entry.createElement('div').addClass('entryEngineButtonWrapper');\n            this.view_.after(this.buttonWrapper);\n\n            /*\n              TODO markup\n              오브젝트 추가하기, 시작하기, 미사용버튼, 기본 일시정지/다시시작,\n              전체화면 일시정지/다시시작, 기본/전체화면 정지 순서\n             */\n            this.addButton = Entry.createElement('button')\n                .addClass('entryEngineButtonWorkspace_w')\n                .addClass('entryAddButtonWorkspace_w')\n                .bindOnClick(function () {\n                    Entry.do('addObjectButtonClick');\n                    this.blur();\n                })\n                .appendTo(this.buttonWrapper);\n            this.addButton.textContent = Lang.Workspace.add_object;\n            if (!Entry.objectAddable) {\n                this.addButton.addClass('entryRemove');\n            }\n\n            this.runButton = Entry.createElement('button')\n                .addClass('entryEngineButtonWorkspace_w')\n                .addClass('entryRunButtonWorkspace_w')\n                .bindOnClick(() => Entry.do('toggleRun', 'runButton'))\n                .appendTo(this.buttonWrapper);\n            this.runButton.textContent = Lang.Workspace.run;\n\n            this.runButton2 = Entry.createElement('button')\n                .addClass('entryEngineButtonWorkspace_w')\n                .addClass('entryRunButtonWorkspace_w2')\n                .appendTo(this.buttonWrapper)\n                .bindOnClick(() => Entry.engine.toggleRun());\n\n            this.pauseButton = Entry.createElement('button')\n                .addClass('entryEngineButtonWorkspace_w')\n                .addClass('entryPauseButtonWorkspace_w')\n                .addClass('entryRemove')\n                .appendTo(this.buttonWrapper)\n                .bindOnClick(function (e) {\n                    this.blur();\n                    Entry.engine.togglePause();\n                });\n\n            this.pauseButtonFull = Entry.createElement('button')\n                .addClass('entryEngineButtonWorkspace_w')\n                .addClass('entryPauseButtonWorkspace_full')\n                .addClass('entryRemove')\n                .appendTo(this.buttonWrapper)\n                .bindOnClick(function () {\n                    this.blur();\n                    Entry.engine.togglePause();\n                });\n\n            this.stopButton = Entry.createElement('button')\n                .addClass('entryEngineButtonWorkspace_w')\n                .addClass('entryStopButtonWorkspace_w')\n                .addClass('entryRemove')\n                .bindOnClick(() => Entry.do('toggleStop', 'stopButton'))\n                .appendTo(this.buttonWrapper);\n            this.stopButton.textContent = Lang.Workspace.stop;\n\n            this.stopButton2 = Entry.createElement('button')\n                .addClass('entryEngineButtonWorkspace_w')\n                .addClass('entryStopButtonWorkspace_w2')\n                .addClass('entryRemove')\n                .bindOnClick(function () {\n                    this.blur();\n                    Entry.engine.toggleStop();\n                })\n                .appendTo(this.buttonWrapper);\n            this.stopButton2.textContent = Lang.Workspace.stop;\n        } else if (option == 'minimize') {\n            /** @type {!Element} */\n            this.view_ = controlView;\n            this.view_.addClass('entryEngine');\n            this.view_.addClass('entryEngineMinimize');\n\n            this.maximizeButton = Entry.createElement('button');\n            this.maximizeButton.addClass('entryEngineButtonMinimize');\n            this.maximizeButton.addClass('entryMaximizeButtonMinimize');\n            this.view_.appendChild(this.maximizeButton);\n            this.maximizeButton.bindOnClick((e) => {\n                Entry.engine.toggleFullScreen();\n            });\n\n            this.coordinateButton = Entry.createElement('button');\n            this.coordinateButton.addClass('entryEngineButtonMinimize');\n            this.coordinateButton.addClass('entryCoordinateButtonMinimize');\n            this.view_.appendChild(this.coordinateButton);\n            this.coordinateButton.bindOnClick(function (e) {\n                if (this.hasClass('toggleOn')) {\n                    this.removeClass('toggleOn');\n                } else {\n                    this.addClass('toggleOn');\n                }\n                Entry.stage.toggleCoordinator();\n            });\n\n            this.stopButton = Entry.createElement('button');\n            this.stopButton.addClass('entryEngineButtonMinimize');\n            this.stopButton.addClass('entryStopButtonMinimize');\n            this.stopButton.addClass('entryRemove');\n            this.stopButton.textContent = Lang.Workspace.stop;\n            this.view_.appendChild(this.stopButton);\n            this.stopButton.bindOnClick(function (e) {\n                this.blur();\n                Entry.engine.toggleStop();\n            });\n\n            this.pauseButton = Entry.createElement('button');\n            this.pauseButton.textContent = Lang.Workspace.pause;\n            this.pauseButton.addClass('entryEngineButtonMinimize');\n            this.pauseButton.addClass('entryPauseButtonMinimize');\n            this.pauseButton.addClass('entryRemove');\n            this.view_.appendChild(this.pauseButton);\n            this.pauseButton.bindOnClick(function (e) {\n                this.blur();\n                Entry.engine.togglePause();\n            });\n\n            this.mouseView = Entry.createElement('div');\n            this.mouseView.addClass('entryMouseViewMinimize');\n            this.mouseView.addClass('entryHide');\n\n            this.mouseViewInput = Entry.createElement('input').appendTo(this.mouseView);\n            $(this.mouseViewInput).attr('readonly', 'readonly');\n            $(this.mouseViewInput).attr(\n                'style',\n                'border: none;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;line-height: normal'\n            );\n\n            this.view_.appendChild(this.mouseView);\n            const setRunButton = (isLoaded) => {\n                if (!isLoaded) {\n                    return;\n                }\n                this.isLoaded = true;\n                const isSoundEmpty = Entry.soundQueue.urls.size < 1;\n                if (isSoundEmpty || Entry.soundQueue.loadComplete) {\n                    if (!this.runButtonCurtain) {\n                        this.runButtonCurtain = Entry.Dom('div', {\n                            class: 'entryRunButtonBigMinimizeCurtain',\n                            parent: $('#entryCanvasWrapper'),\n                        });\n                    }\n                    if (!this.runButton) {\n                        this.runButton = Entry.Dom('div', {\n                            class: 'entryRunButtonBigMinimize',\n                            parent: this.runButtonCurtain,\n                        });\n                        this.runButton.bindOnClick(() => Entry.engine.toggleRun());\n                    }\n                    if (Entry.options.isStartOnLoaded && Entry.engine.state === 'stop') {\n                        Entry.engine.toggleRun();\n                    }\n                }\n            };\n\n            Entry.addEventListener('loadComplete', () => setRunButton(true));\n            Entry.addEventListener('soundLoaded', () => setRunButton(this.isLoaded));\n        } else if (option == 'phone') {\n            this.view_ = controlView;\n            this.view_.addClass('entryEngine', 'entryEnginePhone');\n\n            this.headerView_ = Entry.createElement('div', 'entryEngineHeader');\n            this.headerView_.addClass('entryEngineHeaderPhone');\n            this.view_.appendChild(this.headerView_);\n\n            this.maximizeButton = Entry.createElement('button');\n            this.maximizeButton.addClass('entryEngineButtonPhone', 'entryMaximizeButtonPhone');\n            this.headerView_.appendChild(this.maximizeButton);\n            this.maximizeButton.bindOnClick((e) => {\n                Entry.engine.footerView_.addClass('entryRemove');\n                Entry.engine.headerView_.addClass('entryRemove');\n                Entry.launchFullScreen(Entry.engine.view_);\n            });\n            document.addEventListener('fullscreenchange', (e) => {\n                Entry.engine.exitFullScreen();\n            });\n            document.addEventListener('webkitfullscreenchange', (e) => {\n                Entry.engine.exitFullScreen();\n            });\n            document.addEventListener('mozfullscreenchange', (e) => {\n                Entry.engine.exitFullScreen();\n            });\n\n            this.footerView_ = Entry.createElement('div', 'entryEngineFooter');\n            this.footerView_.addClass('entryEngineFooterPhone');\n            this.view_.appendChild(this.footerView_);\n\n            this.runButton = Entry.createElement('button');\n            this.runButton.addClass('entryEngineButtonPhone', 'entryRunButtonPhone');\n            if (Entry.objectAddable) {\n                this.runButton.addClass('small');\n            }\n            this.runButton.textContent = Lang.Workspace.run;\n\n            this.footerView_.appendChild(this.runButton);\n            this.runButton.bindOnClick((e) => {\n                Entry.engine.toggleRun();\n            });\n\n            this.stopButton = Entry.createElement('button');\n            this.stopButton.addClass(\n                'entryEngineButtonPhone',\n                'entryStopButtonPhone',\n                'entryRemove'\n            );\n            if (Entry.objectAddable) {\n                this.stopButton.addClass('small');\n            }\n            this.stopButton.textContent = Lang.Workspace.stop;\n\n            this.footerView_.appendChild(this.stopButton);\n            this.stopButton.bindOnClick((e) => {\n                Entry.engine.toggleStop();\n            });\n        }\n    }\n\n    toggleAudioShadePanel() {\n        if (this.audioShadePanelOn) {\n            this.audioShadePanelOn = false;\n            $(this.audioShadePanel_).remove();\n            delete this.audioShadePanel_;\n        } else if (Entry.engine.isState('run')) {\n            this.audioShadePanelOn = true;\n            this.audioShadePanel_ = Entry.createElement('div', 'audioShadeCirclebox');\n            this.audioShadePanel_.addClass('audioShadeCirclebox');\n            const audioShadeMainCircle = Entry.createElement('div', 'audioShadeCircle').addClass(\n                'audioShadeCircle'\n            );\n            audioShadeMainCircle.appendChild(\n                Entry.createElement('div', 'audioShadeInner').addClass('audioShadeInner')\n            );\n            audioShadeMainCircle.appendChild(\n                Entry.createElement('div', 'audioShadeInner').addClass('audioShadeInner')\n            );\n            audioShadeMainCircle.appendChild(\n                Entry.createElement('div', 'audioShadeInner').addClass('audioShadeInner')\n            );\n            this.audioShadePanel_.appendChild(audioShadeMainCircle);\n            const micImage = Entry.createElement('img', 'audioShadeImg').addClass('audioShadeImg');\n            micImage.src = `${Entry.mediaFilePath}ic-audio-sensing-mic.svg`;\n            audioShadeMainCircle.appendChild(micImage);\n\n            const audioShadeText = Entry.createElement('div', 'audioShadeText').addClass(\n                'audioShadeText'\n            );\n            audioShadeText.textContent = Lang.Msgs.ai_utilize_audio_listening;\n            this.audioShadePanel_.appendChild(audioShadeText);\n            this.minimizedView_ = document.querySelector('#entryCanvasWrapper');\n            if (this.view_.classList[0] === 'entryEngine') {\n                this.minimizedView_.insertBefore(this.audioShadePanel_, Entry.stage.canvas.canvas);\n            } else {\n                this.view_.insertBefore(this.audioShadePanel_, Entry.stage.canvas.canvas);\n            }\n        }\n    }\n\n    toggleAudioProgressPanel() {\n        if (this.audioShadePanelOn) {\n            Entry.engine.toggleAudioShadePanel();\n        }\n        if (this.audioProgressPanelOn) {\n            this.audioProgressPanelOn = false;\n            $(this.audioProgressPanel_).remove();\n            delete this.audioProgressPanel_;\n        } else if (Entry.engine.isState('run')) {\n            this.audioProgressPanelOn = true;\n            this.audioProgressPanel_ = Entry.createElement('div', 'audioShadeCirclebox');\n            this.audioProgressPanel_.addClass('audioShadeCirclebox');\n            const audioShadeMainCircle = Entry.createElement('div', 'audioShadeCircle').addClass(\n                'audioShadeCircle'\n            );\n\n            const audioProgressSpinner = Entry.createElement(\n                'canvas',\n                'audioProgressCanvas'\n            ).addClass('audioProgress');\n\n            const ctx = audioProgressSpinner.getContext('2d');\n            const circlesRotate = [0, 15, 30, 45, 60];\n            audioProgressSpinner.width = 100;\n            audioProgressSpinner.height = 100;\n            function fnDraw() {\n                audioProgressSpinner.width = audioProgressSpinner.width;\n                fnCircle();\n                window.requestAnimationFrame(fnDraw);\n            }\n            fnDraw();\n\n            function fnReturnDeg(deg) {\n                return (deg * Math.PI) / 180;\n            }\n\n            function fnCircle() {\n                ctx.fillStyle = 'white';\n                for (let i = 0; i < circlesRotate.length; i++) {\n                    ctx.beginPath();\n                    ctx.save();\n                    ctx.translate(audioProgressSpinner.width / 2, audioProgressSpinner.height / 2);\n                    ctx.rotate(fnReturnDeg(circlesRotate[i]));\n                    ctx.arc(0, -audioProgressSpinner.height / 3, 7, Math.PI, 10);\n                    ctx.fill();\n                    ctx.restore();\n                    if (circlesRotate[i] < 60 || circlesRotate[i] > 300) {\n                        circlesRotate[i] += 3;\n                    } else {\n                        circlesRotate[i] += 7;\n                    }\n                    if (circlesRotate[i] > 360) {\n                        circlesRotate[i] -= 360;\n                    }\n                }\n            }\n            audioShadeMainCircle.appendChild(audioProgressSpinner);\n\n            this.audioProgressPanel_.appendChild(audioShadeMainCircle);\n\n            const audioShadeText = Entry.createElement('div', 'audioShadeText').addClass(\n                'audioShadeText'\n            );\n            audioShadeText.innerHTML = Lang.Msgs.ai_utilize_audio_progress;\n            this.audioProgressPanel_.appendChild(audioShadeText);\n            this.minimizedView_ = document.querySelector('#entryCanvasWrapper');\n            if (this.view_.classList[0] === 'entryEngine') {\n                this.minimizedView_.insertBefore(\n                    this.audioProgressPanel_,\n                    Entry.stage.canvas.canvas\n                );\n            } else {\n                this.view_.insertBefore(this.audioProgressPanel_, Entry.stage.canvas.canvas);\n            }\n        }\n    }\n\n    hideAllAudioPanel() {\n        if (this.audioShadePanelOn) {\n            this.audioShadePanelOn = false;\n            $(this.audioShadePanel_).remove();\n            delete this.audioShadePanel_;\n        }\n        if (this.audioProgressPanelOn) {\n            this.audioProgressPanelOn = false;\n            $(this.audioProgressPanel_).remove();\n            delete this.audioProgressPanel_;\n        }\n    }\n\n    toggleSpeedPanel() {\n        if (this.speedPanelOn) {\n            this.speedPanelOn = false;\n            this.speedButton.removeClass('on');\n\n            $(this.speedLabel_).parent().remove();\n            delete this.speedLabel_;\n            $(this.speedProgress_).fadeOut(null, function (e) {\n                $(this).remove();\n                delete this.speedProgress_;\n            });\n            $(this.speedHandle_).remove();\n            delete this.speedHandle_;\n        } else {\n            this.speedPanelOn = true;\n            this.speedButton.addClass('on');\n\n            const speedBox = Entry.createElement('div', 'entrySpeedBox');\n            speedBox.addClass('entrySpeedBox');\n            this.view_.insertBefore(speedBox, Entry.stage.canvas.canvas);\n\n            this.speedLabel_ = Entry.createElement('div', 'entrySpeedLabelWorkspace');\n            this.speedLabel_.textContent = Lang.Workspace.speed;\n            speedBox.appendChild(this.speedLabel_);\n\n            this.speedProgress_ = Entry.createElement('table', 'entrySpeedProgressWorkspace');\n            const tr = Entry.createElement('tr').appendTo(this.speedProgress_);\n\n            this.speeds.forEach((speed, i) => {\n                Entry.createElement('td', `progressCell${i}`)\n                    .addClass('progressCell')\n                    .bindOnClick(() => {\n                        this.setSpeedMeter(speed);\n                    })\n                    .appendTo(tr);\n            });\n\n            speedBox.appendChild(this.speedProgress_);\n            this.setSpeedMeter(Entry.FPS);\n        }\n    }\n\n    setSpeedMeter(FPS) {\n        let level = this.speeds.indexOf(FPS);\n        if (level < 0) {\n            return;\n        }\n        level = Math.min(4, level);\n        level = Math.max(0, level);\n        if (this.speedPanelOn) {\n            const elements = document.querySelectorAll(`.progressCell`);\n            Array.from(elements).forEach((element, i) => {\n                if (level === i) {\n                    element.className = 'progressCell on';\n                } else if (element.className.indexOf('on') > -1) {\n                    element.className = 'progressCell';\n                }\n            });\n        }\n        if (Entry.FPS == FPS) {\n            return;\n        }\n        clearInterval(this.ticker);\n        Entry.tickTime = Math.floor(1000 / FPS);\n        this.ticker = setInterval(this.update, Entry.tickTime);\n        Entry.FPS = FPS;\n    }\n\n    start() {\n        GEHelper.Ticker.setFPS(Entry.FPS);\n\n        if (!this.ticker) {\n            Entry.tickTime = Math.floor(1000 / Entry.FPS);\n            this.ticker = setInterval(this.update, Entry.tickTime);\n        }\n    }\n\n    stop() {\n        GEHelper.Ticker.reset();\n        audioUtils.stopRecord();\n        clearInterval(this.ticker);\n        this.ticker = null;\n        this._stopEngineTimer();\n        this._clearEngineTimeouts();\n    }\n\n    /**\n     * 매 틱당 실행되며, canvas, object 를 업데이트한다.\n     * 추가로, 하드웨어의 데이터도 업데이트한다.\n     */\n    update = () => {\n        if (Entry.engine.isState('run')) {\n            Entry.container.mapObjectOnScene(this.computeFunction);\n            if (Entry.hw.communicationType !== 'manual') {\n                Entry.hw.update();\n            }\n            this._processEngineTimeouts();\n        }\n    };\n\n    /**\n     * Compute function for map. (Ntry 에 동일한 명칭의 함수가 있어 그대로 둠)\n     */\n    computeFunction({ script }) {\n        script.tick();\n    }\n\n    /**\n     * Check this state is same with argument\n     * @param {string} state\n     * @return {boolean}\n     */\n    isState(state) {\n        return this.state.indexOf(state) > -1;\n    }\n\n    /**\n     * Execute this function when click start button\n     */\n    run() {\n        if (this.isState('run')) {\n            this.toggleStop();\n        } else if (this.isState('stop') || this.isState('pause')) {\n            this.toggleRun();\n        }\n    }\n\n    /**\n     * toggle this engine state run\n     */\n    toggleRun(disableAchieve) {\n        const isSupportWebAudio = window.AudioContext || window.webkitAudioContext;\n        if (isSupportWebAudio && !this.isSoundInitialized) {\n            createjs.WebAudioPlugin.playEmptySound();\n            this.isSoundInitialized = true;\n        }\n        Entry.Utils.forceStopSounds();\n        const variableContainer = Entry.variableContainer;\n        const container = Entry.container;\n        const WS = Entry.getMainWS();\n\n        if (this.state === EntryEngineState.pause) {\n            return this.togglePause();\n        }\n\n        Entry.Utils.blur();\n\n        WS && WS.syncCode();\n\n        Entry.addActivity('run');\n\n        if (this.state === EntryEngineState.stop) {\n            container.mapEntity((entity) => {\n                entity.takeSnapshot();\n            });\n            variableContainer.mapVariable((variable) => {\n                variable.takeSnapshot();\n            });\n            variableContainer.mapList((variable) => {\n                variable.takeSnapshot();\n            });\n            variableContainer.mapFunc((func) => {\n                func.takeSnapshot();\n            });\n            if (Entry.container.sttValue) {\n                Entry.container.sttValue.takeSnapshot();\n            }\n            this.projectTimer.takeSnapshot();\n            container.inputValue.takeSnapshot();\n\n            container.takeSequenceSnapshot();\n            Entry.scene.takeStartSceneSnapshot();\n            this.state = EntryEngineState.run;\n            this._resetEngineTimer();\n            this.fireEvent('start');\n            this.achieveEnabled = !(disableAchieve === false);\n        }\n        this.state = EntryEngineState.run;\n        if (Entry.type === 'mobile') {\n            this.view_.addClass('entryEngineBlueWorkspace');\n        }\n\n        if (this.runButton) {\n            this.setPauseButton(this.option);\n            this.runButton.addClass('run');\n            this.runButton.addClass('entryRemove');\n            if (this.runButtonCurtain) {\n                this.runButtonCurtain.addClass('entryRemove');\n            }\n            this.stopButton.removeClass('entryRemove');\n            if (this.addButton) {\n                this.addButton.addClass('entryRemove');\n                if (Entry.objectAddable) {\n                    this.pauseButton.removeClass('entryRemove');\n                }\n            }\n            if (this.pauseButton && (Entry.type === 'minimize' || Entry.objectAddable)) {\n                this.pauseButton.removeClass('entryRemove');\n            }\n\n            if (this.runButton2) {\n                this.runButton2.addClass('entryRemove');\n            }\n            if (this.stopButton2) {\n                this.stopButton2.removeClass('entryRemove');\n            }\n            if (this.pauseButtonFull) {\n                this.pauseButtonFull.removeClass('entryRemove');\n            }\n        }\n\n        if (!this.isUpdating) {\n            this.update();\n            this.isUpdating = true;\n        }\n\n        this.setEnableInputField(true);\n\n        this.selectedObject = Entry.stage.selectedObject;\n        Entry.stage.selectObject();\n        Entry.dispatchEvent('closeBackPack');\n        Entry.dispatchEvent('run');\n    }\n\n    /**\n     * toggle this engine state stop\n     */\n    async toggleStop() {\n        this.state = EntryEngineState.stopping;\n        Entry.dispatchEvent('beforeStop');\n        try {\n            await Promise.all(this.execPromises);\n        } catch (e) {}\n        const container = Entry.container;\n        const variableContainer = Entry.variableContainer;\n\n        Entry.Utils.blur();\n        audioUtils.stopRecord();\n        Entry.addActivity('stop');\n\n        container.mapEntity((entity) => {\n            entity.loadSnapshot();\n            entity.object.filters = [];\n            entity.resetFilter();\n            if (entity.dialog) {\n                entity.dialog.remove();\n            }\n            if (entity.brush) {\n                entity.removeBrush();\n            }\n            if (entity.paint) {\n                entity.removePaint();\n            }\n        });\n\n        variableContainer.mapVariable((variable) => {\n            variable.loadSnapshot();\n        });\n        variableContainer.mapList((variable) => {\n            variable.loadSnapshot();\n        });\n        variableContainer.mapFunc((func) => {\n            func.loadSnapshot();\n        });\n        this.stopProjectTimer();\n        if (Entry.timerInstances) {\n            Entry.timerInstances.forEach((instance) => {\n                instance.destroy();\n            });\n        }\n        if (Entry.container.sttValue) {\n            Entry.container.sttValue.loadSnapshot();\n        }\n        container.clearRunningState();\n        container.loadSequenceSnapshot();\n        this.projectTimer.loadSnapshot();\n        container.inputValue.loadSnapshot();\n        Entry.scene.loadStartSceneSnapshot();\n        Entry.Func.clearThreads();\n        Entry.Utils.setVolume(1);\n        if (Entry.hwLite.getStatus() === 'connected') {\n            Entry.hwLite.setZero();\n        }\n        createjs.Sound.setVolume(1);\n        createjs.Sound.stop();\n        Entry.soundInstances.clear();\n        Entry.bgmInstances.clear();\n        Entry.playbackRateValue = 1;\n        Entry.targetChecker && Entry.targetChecker.clearListener();\n\n        this.view_.removeClass('entryEngineBlueWorkspace');\n        if (this.runButton) {\n            this.runButton.removeClass('entryRemove');\n            if (this.runButtonCurtain) {\n                this.runButtonCurtain.removeClass('entryRemove');\n            }\n            this.stopButton.addClass('entryRemove');\n            if (this.pauseButton) {\n                this.pauseButton.addClass('entryRemove');\n            }\n            if (this.pauseButtonFull) {\n                this.pauseButtonFull.addClass('entryRemove');\n            }\n            if (this.addButton && Entry.objectAddable) {\n                this.addButton.removeClass('entryRemove');\n            }\n\n            if (this.runButton2) {\n                this.runButton2.removeClass('entryRemove');\n            }\n            if (this.stopButton2) {\n                this.stopButton2.addClass('entryRemove');\n            }\n        }\n\n        this.state = EntryEngineState.stop;\n        this._stopEngineTimer();\n        this._clearEngineTimeouts();\n        this.setEnableInputField(false);\n        Entry.dispatchEvent('stop');\n        Entry.stage.hideInputField();\n        (function (w) {\n            w && w.getMode() === Entry.Workspace.MODE_VIMBOARD && w.codeToText();\n        })(Entry.getMainWS());\n        Entry.dispatchEvent('dispatchEventDidToggleStop');\n        Entry.stage.selectObject(this.selectedObject);\n    }\n\n    setEnableInputField(on) {\n        const inputField = Entry.stage.inputField;\n        if (inputField) {\n            inputField._readonly = !on;\n            if (!inputField._isHidden) {\n                on ? inputField.focus() : inputField.blur();\n            }\n        }\n    }\n\n    /**\n     * toggle this engine state pause\n     */\n    togglePause({ visible = true } = {}) {\n        const timer = Entry.engine.projectTimer;\n        if (this.state === EntryEngineState.pause) {\n            this.setEnableInputField(true);\n            timer.pausedTime += new Date().getTime() - timer.pauseStart;\n            if (timer.isPaused) {\n                timer.pauseStart = new Date().getTime();\n            } else {\n                delete timer.pauseStart;\n            }\n            this.state = EntryEngineState.run;\n            this._resumeEngineTimer();\n            Entry.Utils.recoverSoundInstances();\n            if (visible && this.runButton) {\n                this.setPauseButton(this.option);\n                if (this.runButton2) {\n                    this.runButton2.addClass('entryRemove');\n                } else {\n                    this.runButton.addClass('entryRemove');\n                    if (this.runButtonCurtain) {\n                        this.runButtonCurtain.addClass('entryRemove');\n                    }\n                }\n            }\n\n            if (Entry.timerInstances) {\n                Entry.timerInstances.forEach((instance) => {\n                    instance.resume();\n                });\n            }\n        } else {\n            this.state = EntryEngineState.pause;\n            this.setEnableInputField(false);\n            if (!timer.isPaused) {\n                timer.pauseStart = new Date().getTime();\n            } else {\n                timer.pausedTime += new Date().getTime() - timer.pauseStart;\n                timer.pauseStart = new Date().getTime();\n            }\n            this._pauseEngineTimer();\n            Entry.Utils.pauseSoundInstances();\n            if (visible && this.runButton) {\n                this.setPauseButton(this.option);\n                this.stopButton.removeClass('entryRemove');\n                if (this.runButton2) {\n                    this.runButton2.removeClass('entryRemove');\n                } else {\n                    this.runButton.removeClass('entryRemove');\n                    if (this.runButtonCurtain) {\n                        this.runButtonCurtain.removeClass('entryRemove');\n                    }\n                }\n            }\n\n            if (Entry.timerInstances) {\n                Entry.timerInstances.forEach((instance) => {\n                    instance.pause();\n                });\n            }\n        }\n        Entry.dispatchEvent('dispatchEventDidTogglePause');\n    }\n\n    setPauseButton() {\n        if (this.state === EntryEngineState.pause) {\n            if (this.pauseButton) {\n                this.pauseButton.textContent = Lang.Workspace.restart;\n                if (this.option !== 'minimize') {\n                    this.pauseButton.removeClass('entryPauseButtonWorkspace_w');\n                    this.pauseButton.addClass('entryRestartButtonWorkspace_w');\n                }\n            }\n            if (this.pauseButtonFull) {\n                this.pauseButtonFull.textContent = Lang.Workspace.restart;\n                if (this.option !== 'minimize') {\n                    // workspace && buttonWrapper check\n                    if (this.buttonWrapper) {\n                        this.pauseButtonFull.addClass('entryPauseButtonWorkspace_full');\n                    } else {\n                        this.pauseButtonFull.removeClass('entryPauseButtonWorkspace_full');\n                    }\n                    this.pauseButtonFull.addClass('entryRestartButtonWorkspace_full');\n                }\n            }\n        } else {\n            if (this.pauseButton) {\n                this.pauseButton.textContent = Lang.Workspace.pause;\n                if (this.option !== 'minimize') {\n                    this.pauseButton.addClass('entryPauseButtonWorkspace_w');\n                    this.pauseButton.removeClass('entryRestartButtonWorkspace_w');\n                }\n            }\n            if (this.pauseButtonFull) {\n                this.pauseButtonFull.textContent = Lang.Workspace.pause;\n                if (this.option !== 'minimize') {\n                    this.pauseButtonFull.addClass('entryPauseButtonWorkspace_full');\n                    this.pauseButtonFull.removeClass('entryRestartButtonWorkspace_full');\n                }\n            }\n        }\n    }\n\n    /**\n     * @param {string} eventName\n     */\n    fireEvent(eventName) {\n        if (this.state !== EntryEngineState.run) {\n            return;\n        }\n        Entry.container.mapEntityIncludeCloneOnScene(this.raiseEvent, eventName);\n    }\n\n    /**\n     * @param {string} eventName\n     * @param {string} value\n     */\n    fireEventWithValue(eventName, value) {\n        if (this.state !== EntryEngineState.run) {\n            return;\n        }\n        return Entry.container.mapEntityIncludeCloneOnScene(this.raiseKeyEvent, [eventName, value]);\n    }\n\n    /**\n     * this is callback function for map.\n     * @param {Entry.EntryObject} object\n     * @param {string} eventName\n     */\n    raiseEvent = (entity, eventName) => {\n        entity.parent.script.raiseEvent(eventName, entity);\n    };\n\n    /**\n     * @param {string} eventName\n     * @param {Entry.EntityObject} entity\n     */\n    fireEventOnEntity(eventName, entity) {\n        if (this.state === EntryEngineState.run) {\n            Entry.container.mapEntityIncludeCloneOnScene(this.raiseEventOnEntity, [\n                entity,\n                eventName,\n            ]);\n        }\n    }\n\n    /**\n     * this is callback function for map.\n     * @param {Entry.EntryObject} object\n     * @param {Array} param\n     */\n    raiseEventOnEntity(entity, param) {\n        if (entity !== param[0]) {\n            return;\n        }\n        const eventName = param[1];\n        entity.parent.script.raiseEvent(eventName, entity);\n    }\n\n    /**\n     * @param {KeyboardEvent} e\n     * @param {boolean} isForce\n     */\n    captureKeyEvent(e, isForce) {\n        const keyCode = Entry.Utils.inputToKeycode(e);\n        if (!keyCode) {\n            return;\n        }\n        const isWorkspace = Entry.type === 'workspace';\n\n        if (Entry.Utils.isInInput(e) && !isForce) {\n            return;\n        }\n\n        //mouse shortcuts\n        if (keyCode !== 17 && e.ctrlKey && isWorkspace) {\n            if (keyCode === 83) {\n                e.preventDefault();\n                Entry.dispatchEvent(e.shiftKey ? 'saveAsWorkspace' : 'saveWorkspace');\n            } else if (keyCode === 82) {\n                e.preventDefault();\n                Entry.engine.run();\n            } else if (keyCode === 90) {\n                e.preventDefault();\n                Entry.dispatchEvent(e.shiftKey ? 'redo' : 'undo');\n            }\n        } else if (Entry.engine.isState('run')) {\n            e.preventDefault && e.preventDefault();\n            Entry.container.mapEntityIncludeCloneOnScene(Entry.engine.raiseKeyEvent, [\n                'keyPress',\n                keyCode,\n            ]);\n        }\n\n        if (Entry.engine.isState('stop')) {\n            if (isWorkspace && keyCode >= 37 && keyCode <= 40) {\n                Entry.stage.moveSprite(e);\n            }\n        }\n    }\n\n    raiseKeyEvent(entity, [eventName, keyCode]) {\n        return entity.parent.script.raiseEvent(eventName, entity, String(keyCode));\n    }\n\n    updateMouseView() {\n        const { x, y } = Entry.stage.mouseCoordinate;\n        this.mouseViewInput.value = `X : ${x}, Y : ${y}`;\n        this.mouseView.removeClass('entryHide');\n    }\n\n    hideMouseView() {\n        this.mouseView.addClass('entryHide');\n    }\n\n    toggleFullScreen(popupClassName) {\n        Entry.dispatchEvent('toggleFullScreen');\n        if (!Entry.fullScreenEnable) {\n            return;\n        }\n\n        if (!this.popup) {\n            Entry.view_.addClass('fullscreen');\n            this.popup = new Entry.Popup(popupClassName);\n            if (Entry.engine.speedPanelOn) {\n                Entry.engine.toggleSpeedPanel();\n            }\n            if (Entry.type !== 'workspace') {\n                const $doc = $(document);\n                const body = $(this.popup.body_);\n                body.css('top', $doc.scrollTop());\n                $('body').css('overflow', 'hidden');\n\n                popup.window_.appendChild(Entry.stage.canvas.canvas);\n                popup.window_.appendChild(Entry.engine.runButton[0]);\n            }\n            popup.window_.appendChild(Entry.engine.view_);\n            if (Entry.type === 'workspace') {\n                Entry.engine.view_.appendChild(this.buttonWrapper);\n                if (Entry.targetChecker) {\n                    popup.window_.appendChild(Entry.targetChecker.getStatusView()[0]);\n                }\n            }\n\n            if (window.top !== window.self) {\n                if (Entry.iframeDomAccess === 'direct') {\n                    window.top.addEventListener('pointermove', this.copyEvent);\n                    window.top.addEventListener('pointerdown', this.copyEvent);\n                    window.top.addEventListener('pointerup', this.copyEvent);\n                    window.top.addEventListener('pointerupoutside', this.copyEvent);\n                    window.top.addEventListener('pointercancel', this.copyEvent);\n                    window.top.addEventListener('mouseup', this.copyEvent);\n                    window.top.addEventListener('mousemove', this.copyEvent);\n                } else if (Entry.iframeDomAccess === 'message') {\n                    window.top.postMessage({ type: 'toggleFullScreen', value: 'addEvent' }, '*');\n                }\n            }\n        } else {\n            if (window.top !== window.self) {\n                if (Entry.iframeDomAccess === 'direct') {\n                    window.top.removeEventListener('pointermove', this.copyEvent);\n                    window.top.removeEventListener('pointerdown', this.copyEvent);\n                    window.top.removeEventListener('pointerup', this.copyEvent);\n                    window.top.removeEventListener('pointerupoutside', this.copyEvent);\n                    window.top.removeEventListener('pointercancel', this.copyEvent);\n                    window.top.removeEventListener('mouseup', this.copyEvent);\n                    window.top.removeEventListener('mousemove', this.copyEvent);\n                } else if (Entry.iframeDomAccess === 'message') {\n                    window.top.postMessage({ type: 'toggleFullScreen', value: 'removeEvent' }, '*');\n                }\n            }\n            this.popup.remove();\n            this.popup = null;\n        }\n        Entry.windowResized.notify();\n    }\n\n    copyEvent(event) {\n        const eventClone = new event.constructor(event.type, event);\n        window.self.dispatchEvent(eventClone);\n        if (GEHelper.isWebGL && ['mousemove', 'pointermove'].includes(event.type)) {\n            window.document.dispatchEvent(eventClone);\n        }\n    }\n\n    closeFullScreen() {\n        if (this.popup) {\n            this.popup.remove();\n            this.popup = null;\n        }\n\n        Entry.windowResized.notify();\n    }\n\n    exitFullScreen() {\n        if (document.webkitIsFullScreen || document.mozIsFullScreen || document.isFullScreen) {\n        } else {\n            Entry.engine.footerView_.removeClass('entryRemove');\n            Entry.engine.headerView_.removeClass('entryRemove');\n        }\n        Entry.windowResized.notify();\n    }\n\n    showProjectTimer() {\n        const timer = Entry.engine.projectTimer;\n        if (!timer) {\n            return;\n        }\n        this.projectTimer.setVisible(true);\n    }\n\n    hideProjectTimer(removeBlock, notIncludeSelf) {\n        const timer = this.projectTimer;\n        if (!timer || !timer.isVisible() || this.isState('run')) {\n            return;\n        }\n        const objects = Entry.container.getAllObjects();\n\n        const timerTypes = [\n            'get_project_timer_value',\n            'reset_project_timer',\n            'set_visible_project_timer',\n            'choose_project_timer_action',\n        ];\n\n        for (let i = 0, len = objects.length; i < len; i++) {\n            const code = objects[i].script;\n            for (let j = 0; j < timerTypes.length; j++) {\n                const blocks = code.getBlockList(false, timerTypes[j]);\n                if (notIncludeSelf) {\n                    const index = blocks.indexOf(removeBlock);\n                    if (index > -1) {\n                        blocks.splice(index, 1);\n                    }\n                }\n                if (blocks.length > 0) {\n                    return;\n                }\n            }\n        }\n        timer.setVisible(false);\n    }\n\n    clearTimer() {\n        clearInterval(this.ticker);\n        clearInterval(this.projectTimer.tick);\n    }\n\n    startProjectTimer() {\n        const timer = this.projectTimer;\n\n        if (!timer) {\n            return;\n        }\n\n        timer.start = new Date().getTime();\n        timer.isInit = true;\n        timer.isPaused = false;\n        timer.pausedTime = 0;\n        timer.tick = setInterval((e) => {\n            Entry.engine.updateProjectTimer();\n        }, 1000 / 60);\n    }\n\n    stopProjectTimer() {\n        const timer = this.projectTimer;\n        if (!timer) {\n            return;\n        }\n        this.updateProjectTimer(0);\n        timer.isPaused = false;\n        timer.isInit = false;\n        timer.pausedTime = 0;\n        clearInterval(timer.tick);\n    }\n\n    resetTimer() {\n        const timer = this.projectTimer;\n        if (!timer.isInit) {\n            return;\n        }\n        const isPaused = timer.isPaused;\n\n        delete timer.pauseStart;\n\n        this.updateProjectTimer(0);\n        timer.pausedTime = 0;\n\n        timer.isPaused = isPaused;\n\n        if (!isPaused) {\n            return;\n        }\n\n        clearInterval(timer.tick);\n        timer.isInit = false;\n        delete timer.start;\n    }\n\n    updateProjectTimer(value) {\n        const engine = Entry.engine;\n        const timer = engine.projectTimer;\n        if (!timer) {\n            return;\n        }\n        const current = new Date().getTime();\n        if (typeof value == 'undefined') {\n            if (!timer.isPaused && !engine.isState('pause')) {\n                timer.setValue(\n                    Math.max((current - (timer.start || current) - timer.pausedTime) / 1000, 0)\n                );\n            }\n        } else {\n            timer.setValue(value);\n            timer.pausedTime = 0;\n            timer.start = current;\n        }\n    }\n\n    raiseMessage(value) {\n        Entry.message.notify(Entry.variableContainer.getMessage(value));\n        return Entry.container.mapEntityIncludeCloneOnScene(this.raiseKeyEvent, [\n            'when_message_cast',\n            value,\n        ]);\n    }\n\n    getDom(query) {\n        if (query.length >= 1) {\n            switch (query.shift()) {\n                case 'runButton':\n                    return this.runButton;\n                case 'stopButton':\n                    return this.stopButton;\n                case 'objectAddButton':\n                    return this.addButton;\n            }\n        } else {\n        }\n    }\n\n    attachKeyboardCapture() {\n        if (Entry.keyPressed) {\n            this._keyboardEvent && this.detachKeyboardCapture();\n            this._keyboardEvent = Entry.keyPressed.attach(this, this.captureKeyEvent);\n        }\n    }\n\n    detachKeyboardCapture() {\n        if (Entry.keyPressed && this._keyboardEvent) {\n            this._keyboardEvent.destroy();\n            delete this._keyboardEvent;\n        }\n    }\n\n    applyOption() {\n        const SMALL = 'small';\n\n        if (Entry.objectAddable) {\n            this.runButton.addClass(SMALL);\n            this.stopButton.addClass(SMALL);\n            this.addButton.removeClass('entryRemove');\n        } else {\n            this.runButton.removeClass(SMALL);\n            this.stopButton.removeClass(SMALL);\n            this.addButton.addClass('entryRemove');\n        }\n    }\n\n    destroy() {\n        // 우선 interface 만 정의함.\n    }\n\n    trimPromiseExecutor() {\n        return this.execPromises.filter((promise) => promise instanceof Promise);\n    }\n\n    addPromiseExecutor(promises) {\n        this.execPromises = this.trimPromiseExecutor();\n        const index = this.execPromises.length;\n        promises.forEach((promise, i) => {\n            const execPromise = (async function () {\n                const result = await promise;\n                const j = Entry.engine.execPromises.indexOf(execPromise);\n                Entry.engine.execPromises[j] = result;\n            })();\n            this.execPromises[index + i] = execPromise;\n        });\n    }\n\n    _resetEngineTimer() {\n        const timer = this.engineTimer;\n        timer.start = new Date().getTime();\n        timer.pausedTime = 0;\n        timer.pauseStart = 0;\n        timer.isPaused = false;\n        timer.isInit = true;\n    }\n\n    _pauseEngineTimer() {\n        const timer = this.engineTimer;\n        if (!timer.isInit || timer.isPaused) {\n            return;\n        }\n        timer.isPaused = true;\n        timer.pauseStart = new Date().getTime();\n    }\n\n    _resumeEngineTimer() {\n        const timer = this.engineTimer;\n        if (!timer.isInit || !timer.isPaused) {\n            return;\n        }\n        if (timer.pauseStart) {\n            timer.pausedTime += new Date().getTime() - timer.pauseStart;\n        }\n        timer.pauseStart = 0;\n        timer.isPaused = false;\n    }\n\n    _stopEngineTimer() {\n        const timer = this.engineTimer;\n        timer.isInit = false;\n        timer.isPaused = false;\n        timer.start = 0;\n        timer.pauseStart = 0;\n        timer.pausedTime = 0;\n    }\n\n    _getEngineTimeMs() {\n        const timer = this.engineTimer;\n        if (!timer.isInit) {\n            return 0;\n        }\n        const now = timer.isPaused && timer.pauseStart ? timer.pauseStart : new Date().getTime();\n        return Math.max(now - timer.start - timer.pausedTime, 0);\n    }\n\n    _processEngineTimeouts() {\n        if (!this._engineTimeouts.length) {\n            return;\n        }\n        const nowMs = this._getEngineTimeMs();\n        const timeouts = this._engineTimeouts;\n        let writeIndex = 0;\n        for (let i = 0; i < timeouts.length; i++) {\n            const item = timeouts[i];\n            if (item.targetTimeMs <= nowMs) {\n                try {\n                    item.callback();\n                } catch (e) {\n                    console.error('Engine setTimeout callback error', e);\n                }\n            } else {\n                timeouts[writeIndex++] = item;\n            }\n        }\n        if (writeIndex !== timeouts.length) {\n            timeouts.length = writeIndex;\n        }\n    }\n\n    _clearEngineTimeouts() {\n        this._engineTimeouts = [];\n    }\n\n    setTimeout(callback, delay) {\n        if (typeof callback !== 'function') {\n            return null;\n        }\n        const id = ++this._engineTimeoutSeq;\n        const targetTimeMs = this._getEngineTimeMs() + Math.max(Number(delay) || 0, 0);\n        this._engineTimeouts.push({\n            id,\n            callback,\n            targetTimeMs,\n        });\n        return id;\n    }\n\n    clearTimeout(id) {\n        this._engineTimeouts = this._engineTimeouts.filter((item) => item.id !== id);\n    }\n};\n"
  },
  {
    "path": "src/class/entity.js",
    "content": "/**\n * @fileoverview entity object is class for entry object canvas view.\n */\n\n'use strict';\n\nimport { GEHelper } from '../graphicEngine/GEHelper';\nimport { GEDragHelper } from '../graphicEngine/GEDragHelper';\n\nconst FONT_PADDING_TOP_EXCEPTIONS = ['Nanum Gothic Coding', 'SDMapssi'];\nconst TEXT_BOX_REPOSITION_THRESHOLD = 10;\nconst TEXT_BOX_REPOSITION_OFFSET = 10;\nconst TEXT_BOX_WEBGL_OFFSET = 5.9;\n\n/**\n * Construct entity class\n * @param {!Entry.EntryObject} object\n * @constructor\n */\nEntry.EntityObject = class EntityObject {\n    constructor(object) {\n        /** @type {!string} */\n        this.parent = object;\n        this.type = object.objectType;\n        /** @type {Array<xml script>} */\n        this.flip = false;\n        this.collision = Entry.Utils.COLLISION.NONE;\n        this.id = Entry.generateHash();\n        this.removed = false;\n        this.stamps = [];\n        this.shapes = [];\n        this.paintShapes = [];\n        this._rndPosX = 0;\n        this._rndPosY = 0;\n        this.scaleOriginX = 0;\n        this.scaleOriginY = 0;\n        this.voice = { speed: 0, pitch: 0, speaker: 'kyuri', volume: 1 };\n        this.defaultLog = {\n            textEffect: {},\n        };\n\n        if (this.type === 'sprite') {\n            this._rndPosX = GEHelper.rndPosition();\n            this._rndPosY = GEHelper.rndPosition();\n            this.object = GEHelper.newEmptySprite();\n            this.object.pixelPerfect = true;\n            this._scaleAdaptor = GEHelper.newAScaleAdaptor(this.object);\n            this.setInitialEffectValue();\n        } else if (this.type === 'textBox') {\n            this.object = GEHelper.newContainer();\n            this._scaleAdaptor = GEHelper.newAScaleAdaptor(this.object);\n            this.textObject = GEHelper.textHelper.newText(\n                '',\n                '20px Nanum Gothic',\n                '',\n                'middle',\n                'center'\n            );\n\n            /*\n             bgObject 가 transparent 인 경우에도 textObject 가 hit 처리되어서\n             container on event 가 동작해버리는 이슈가 있었음. (issues/10463)\n             textObject 를 정확히 그려진 부분만 interactive 하도록 플래그 수정\n             */\n            this.textObject.pixelPerfect = true;\n\n            if (GEHelper.isWebGL) {\n                this.textObject.anchor.set(0.5, 0.5);\n            }\n            this.bgObject = GEHelper.newGraphic();\n            this.bgObject.graphics.beginFill('#ffffff').drawRect(0, 0, 100, 100);\n            this.object.addChild(this.bgObject);\n            this.object.addChild(this.textObject);\n\n            this.fontType = 'Nanum Gothic';\n            this.fontSize = 20;\n            this.fontBold = false;\n            this.fontItalic = false;\n            this.underLine = false;\n            this.strike = false;\n        }\n\n        this.object.entity = this;\n        this.object.cursor = 'pointer';\n        this.object.mouseEnabled = true;\n        GEDragHelper.handleDrag(this.object);\n\n        this.object.on(GEDragHelper.types.DOWN, function ({ stageX, stageY }) {\n            const id = this.entity.parent.id;\n            Entry.dispatchEvent('entityClick', this.entity);\n            Entry.stage.isObjectClick = true;\n\n            if (Entry.type !== 'minimize' && Entry.stage.isEntitySelectable()) {\n                if (Entry.objectEditable) {\n                    this.offset = {\n                        x: -this.parent.x + this.entity.getX() - (stageX * 0.75 - 240),\n                        y: -this.parent.y - this.entity.getY() - (stageY * 0.75 - 135),\n                    };\n                    this.cursor = 'move';\n                    this.entity.initCommand();\n                }\n                Entry.container.selectObject(id);\n            }\n        });\n\n        this.object.on(GEDragHelper.types.UP, function () {\n            Entry.dispatchEvent('entityClickCanceled', this.entity);\n            this.cursor = 'pointer';\n            this.entity.checkCommand();\n        });\n\n        if (Entry.type !== 'minimize' && Entry.objectEditable) {\n            this.object.on(GEDragHelper.types.MOVE, function ({ stageX, stageY }) {\n                if (Entry.stage.isEntitySelectable()) {\n                    const entity = this.entity;\n                    if (entity.parent.getLock()) {\n                        return;\n                    }\n\n                    if (this.offset) {\n                        entity.setX(stageX * 0.75 - 240 + this.offset.x);\n                        entity.setY(-(stageY * 0.75 - 135) - this.offset.y);\n                    }\n                    Entry.stage.updateObject();\n                }\n            });\n        }\n    }\n\n    /**\n     * Construct entity class\n     * @param {?picture model} pictureModel\n     * @param {?entity model} entityModel\n     * @constructor\n     */\n    injectModel(pictureModel, entityModel) {\n        const type = this.type;\n        if (type === 'sprite') {\n            this.setImage(pictureModel);\n        } else if (type === 'textBox') {\n            const parent = this.parent;\n            entityModel.text = entityModel.text || parent.text || parent.name;\n            this.setFont(entityModel.font);\n            this.setBGColour(entityModel.bgColor);\n            this.setColour(entityModel.colour);\n            this.setUnderLine(entityModel.underLine);\n            this.setStrike(entityModel.strike);\n            this.setText(entityModel.text);\n        }\n\n        //entity\n        if (entityModel) {\n            this.syncModel_(entityModel);\n        }\n    }\n\n    /**\n     * sync this model with parameter\n     * @param {!entity model} entityModel\n     * @private\n     */\n    syncModel_({\n        x,\n        y,\n        regX,\n        regY,\n        scaleX,\n        scaleY,\n        rotation,\n        direction,\n        lineBreak,\n        width,\n        height,\n        text,\n        textAlign,\n        fontSize,\n        visible,\n    }) {\n        this.setX(x);\n        this.setY(y);\n        this.setRegX(regX);\n        this.setRegY(regY);\n        this.setScaleX(scaleX);\n        this.setScaleY(scaleY);\n        this.scaleOriginX = scaleX;\n        this.scaleOriginY = scaleY;\n        this.setRotation(rotation);\n        this.setDirection(direction, true);\n        this.setLineBreak(lineBreak);\n        this.setWidth(width);\n        this.setHeight(height);\n        this.setText(text);\n        this.setTextAlign(textAlign);\n        this.setFontSize(fontSize || this.getFontSize());\n        this.setVisible(visible);\n    }\n\n    initCommand() {\n        if (!Entry.engine.isState('stop')) {\n            return;\n        }\n\n        this._entityModelBefore = this.toJSON();\n    }\n\n    checkCommand() {\n        if (!Entry.engine.isState('stop')) {\n            return;\n        }\n\n        const oldModel = this._entityModelBefore;\n        delete this._entityModelBefore;\n        const json = this.toJSON();\n\n        if (_.isEqual(json, oldModel)) {\n            return;\n        }\n\n        Entry.do('entitySetModel', this.parent.id, json, oldModel);\n    }\n\n    /**\n     * for redo and undo\n     * @param {!entity model} entityModel\n     * @return {Entry.State} capture current state\n     */\n    setModel(entityModel) {\n        this.syncModel_(entityModel);\n        Entry.dispatchEvent('updateObject');\n        Entry.stage.updateObject();\n    }\n\n    /**\n     * X coordinate setter\n     * @param {number} x\n     */\n    setX(x) {\n        if (typeof x !== 'number') {\n            return;\n        }\n\n        /** @type {number} */\n        this.x = x;\n        this.object.x = this.x + this._rndPosX;\n        !this.isClone && this.parent.updateCoordinateView();\n        this.updateDialog();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * X coordinate getter\n     * @return {number}\n     */\n    getX(toFixedValue) {\n        if (toFixedValue) {\n            return Entry.Utils.toFixed(this.x, toFixedValue);\n        } else {\n            return this.x;\n        }\n    }\n\n    /**\n     * Y coordinate setter\n     * @param {number} y\n     */\n    setY(y) {\n        if (typeof y !== 'number') {\n            return;\n        }\n\n        /** @type {number} */\n        this.y = y;\n        this.object.y = -this.y + this._rndPosY;\n        !this.isClone && this.parent.updateCoordinateView();\n        this.updateDialog();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * Y coordinate getter\n     * @return {number}\n     */\n    getY(toFixedValue) {\n        if (toFixedValue) {\n            return Entry.Utils.toFixed(this.y, toFixedValue);\n        } else {\n            return this.y;\n        }\n    }\n\n    /**\n     * direction getter\n     * @return {number}\n     */\n    getDirection(toFixedValue) {\n        if (toFixedValue) {\n            return Entry.Utils.toFixed(this.direction, toFixedValue);\n        } else {\n            return this.direction;\n        }\n    }\n\n    /**\n     * direction setter\n     * @param {number} direction\n     * @param {boolean} flippable\n     */\n    setDirection(dir = 0, flippable) {\n        const direction = dir.mod(360);\n        const parent = this.parent;\n\n        if (parent.getRotateMethod() === 'vertical' && !flippable) {\n            const previousIsRight = this.direction >= 0 && this.direction < 180;\n            const afterIsRight = direction >= 0 && direction < 180;\n            if (previousIsRight != afterIsRight) {\n                this.setScaleX(-this.getScaleX());\n                Entry.stage.updateObject();\n                this.flip = !this.flip;\n            }\n        }\n        /** @type {number} */\n        this.direction = direction;\n        this.object.direction = this.direction * GEHelper.rotateWrite;\n        !this.isClone && parent.updateRotationView();\n        Entry.dispatchEvent('updateObject');\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * rotation setter\n     * @param {number} rotation\n     * */\n    setRotation(rotation) {\n        /** @type {number} */\n        if (this.parent.getRotateMethod() !== 'free') {\n            rotation = 0;\n        }\n\n        this.rotation = rotation.mod(360);\n        this.object.rotation = this.rotation * GEHelper.rotateWrite;\n        this.updateDialog();\n        !this.isClone && this.parent.updateRotationView();\n        Entry.dispatchEvent('updateObject');\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * rotation getter\n     * @return {number}\n     */\n    getRotation(toFixedValue) {\n        if (toFixedValue) {\n            return Entry.Utils.toFixed(this.rotation, toFixedValue);\n        } else {\n            return this.rotation;\n        }\n    }\n\n    /**\n     * regX coordinate setter\n     * @param {number} regX\n     */\n    setRegX(regX) {\n        if (this.type === 'textBox') {\n            regX = 0;\n        }\n        /** @type {number} */\n        this.regX = regX;\n        if (GEHelper.isWebGL) {\n            this._scaleAdaptor.pivot.setX(regX);\n        } else {\n            this.object.regX = this.regX;\n        }\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * regX coordinate getter\n     * @return {number}\n     */\n    getRegX() {\n        return this.regX;\n    }\n\n    /**\n     * regY coordinate setter\n     * @param {number} regY\n     */\n    setRegY(regY) {\n        if (this.type === 'textBox') {\n            regY = 0;\n        }\n        /** @type {number} */\n        this.regY = regY;\n        if (GEHelper.isWebGL) {\n            this._scaleAdaptor.pivot.setY(regY);\n        } else {\n            this.object.regY = this.regY;\n        }\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * regY coordinate getter\n     * @return {number}\n     */\n    getRegY() {\n        return this.regY;\n    }\n\n    /**\n     * scaleX coordinate setter\n     * @param {number} scaleX\n     */\n    setScaleX(scaleX) {\n        /** @type {number} */\n        this.scaleX = scaleX;\n        if (Entry.engine.isState('stop')) {\n            this.scaleOriginX = scaleX;\n        }\n        if (GEHelper.isWebGL) {\n            this._scaleAdaptor.scale.setX(scaleX);\n            if (this.textObject) {\n                this.textObject.setFontScaleX(scaleX);\n            }\n        } else {\n            this.object.scaleX = this.scaleX;\n        }\n        this.parent.updateCoordinateView();\n        this.updateDialog();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * scaleX coordinate getter\n     * @return {number}\n     */\n    getScaleX() {\n        return this.scaleX;\n    }\n\n    /**\n     * scaleY coordinate setter\n     * @param {number} scaleY\n     */\n    setScaleY(scaleY) {\n        /** @type {number} */\n        this.scaleY = scaleY;\n        if (Entry.engine.isState('stop')) {\n            this.scaleOriginY = scaleY;\n        }\n        if (GEHelper.isWebGL) {\n            this._scaleAdaptor.scale.setY(scaleY);\n            if (this.textObject) {\n                this.textObject.setFontScaleY(scaleY);\n            }\n        } else {\n            this.object.scaleY = this.scaleY;\n        }\n        this.parent.updateCoordinateView();\n        this.updateDialog();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * scaleY coordinate getter\n     * @return {number}\n     */\n    getScaleY() {\n        return this.scaleY;\n    }\n\n    /**\n     * object size setter\n     * @param {number} size\n     */\n    setSize(size) {\n        const scale = Math.max(1, size) / this.getSize();\n        this.setScaleX(this.getScaleX() * scale);\n        this.setScaleY(this.getScaleY() * scale);\n        !this.isClone && this.parent.updateCoordinateView();\n        Entry.requestUpdate = true;\n    }\n\n    resetSize() {\n        this.setScaleX(this.scaleOriginX);\n        this.setScaleY(this.scaleOriginY);\n        !this.isClone && this.parent.updateCoordinateView();\n        Entry.requestUpdate = true;\n    }\n\n    setXSize(size) {\n        const scale = Math.max(1, size) / this.getSize();\n        this.setScaleX(this.getScaleX() * scale);\n        !this.isClone && this.parent.updateCoordinateView();\n        Entry.requestUpdate = true;\n    }\n\n    setYSize(size) {\n        const scale = Math.max(1, size) / this.getSize();\n        this.setScaleY(this.getScaleY() * scale);\n        !this.isClone && this.parent.updateCoordinateView();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * get object size\n     * @return {number}\n     */\n    getSize(toFixedValue) {\n        const value =\n            (this.getWidth() * Math.abs(this.getScaleX()) +\n                this.getHeight() * Math.abs(this.getScaleY())) /\n            2;\n        if (toFixedValue) {\n            return Entry.Utils.toFixed(value, toFixedValue);\n        }\n        return value;\n    }\n\n    /**\n     * width coordinate setter\n     * @param {number} width\n     */\n    setWidth(width) {\n        /** @type {number} */\n        this.width = width;\n        //todo [박봉배] object.width -> object.$width 로 변경\n        this.object.$width = this.width;\n        if (this.textObject && this.getLineBreak()) {\n            if (GEHelper.isWebGL) {\n                this.textObject.style.wordWrapWidth = this.width;\n            } else {\n                this.textObject.lineWidth = this.width;\n            }\n        }\n        this.updateDialog();\n        this.updateBG();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * width coordinate getter\n     * @return {number}\n     */\n    getWidth() {\n        return this.width;\n    }\n\n    /**\n     * height coordinate setter\n     * @param {number} height\n     */\n    setHeight(height) {\n        /** @type {number} */\n        //todo [박봉배] object.height -> object.$height 로 변경\n        this.height = height;\n        if (this.textObject) {\n            this.object.$height = this.height;\n            this.alignTextBox();\n        }\n        this.updateDialog();\n        this.updateBG();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * height coordinate getter\n     * @return {number}\n     */\n    getHeight() {\n        return this.height;\n    }\n\n    setColorWithLog(colour) {\n        if (!this.defaultLog.textColor) {\n            this.defaultLog.textColor = this.colour || '#000000';\n        }\n        this.setColour(colour);\n    }\n\n    /**\n     * colour setter\n     * @param {?string} colour\n     */\n    setColour(colour = '#000000') {\n        /** @type {string} */\n        this.colour = colour;\n        if (this.textObject) {\n            GEHelper.textHelper.setColor(this.textObject, this.colour);\n        }\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * colour getter\n     * @return {colour}\n     */\n    getColour() {\n        return this.colour;\n    }\n\n    /**\n     * NT11576 BGcolor with log #3513\n     * @param {*} colour\n     */\n    setBGColourWithLog(colour = 'transparent') {\n        if (!this.defaultLog.textBGColor) {\n            this.defaultLog.textBGColor = this.bgColor || 'transparent';\n        }\n        this.setBGColour(colour);\n    }\n\n    /**\n     * BG colour setter, for textBox object\n     * @param {?string} colour\n     */\n    setBGColour(colour = 'transparent') {\n        /** @type {string} */\n        this.bgColor = colour;\n        this.updateBG();\n        //this.object.color = this.colour;\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * BG colour getter, for textBox object\n     * @return {colour}\n     */\n    getBGColour() {\n        return this.bgColor;\n    }\n\n    setUnderLine(underLine = false) {\n        this.underLine = underLine;\n        if (GEHelper.isWebGL) {\n            this.textObject.style.underLine = underLine;\n        } else {\n            this.textObject.underLine = underLine;\n        }\n        Entry.requestUpdate = true;\n    }\n\n    getUnderLine() {\n        return this.underLine;\n    }\n\n    setStrike(strike = false) {\n        this.strike = strike;\n        if (GEHelper.isWebGL) {\n            this.textObject.style.cancelLine = strike;\n        } else {\n            this.textObject.strike = strike;\n        }\n        Entry.requestUpdate = true;\n    }\n\n    getStrike() {\n        return this.strike;\n    }\n\n    /**\n     * font getter\n     */\n    getFont() {\n        const fontArray = [];\n        if (this.fontBold) {\n            fontArray.push('bold');\n        }\n        if (this.fontItalic) {\n            fontArray.push('italic');\n        }\n        fontArray.push(`${this.getFontSize()}px`);\n        fontArray.push(this.fontType);\n        return fontArray.join(' ');\n    }\n\n    setFontWithLog(font, shouldUpdateWidth) {\n        if (!this.defaultLog.textFont) {\n            this.defaultLog.textFont = `${this.getFontSize()} ${this.fontType}`;\n        }\n        this.setFont(font, shouldUpdateWidth);\n    }\n\n    /**\n     * font setter\n     */\n    setFont(font = '20 Nanum Gothic', shouldUpdateWidth = true) {\n        if (this.parent.objectType !== 'textBox') {\n            return;\n        }\n        if (this.textObject.font === font) {\n            return;\n        }\n\n        const fontArray = font.split(' ');\n        let i = 0;\n\n        // NT11576 wodnjs6512\n        // #3513 글씨체 변경시에 기존 bold 와 italic을 받아와서 사용하도록\n        if ((i = fontArray.indexOf('bold') > -1)) {\n            fontArray.splice(i - 1, 1);\n            this.setFontBold(true);\n        } else if (this.fontBold) {\n            this.setFontBold(true);\n        }\n        if ((i = fontArray.indexOf('italic') > -1)) {\n            fontArray.splice(i - 1, 1);\n            this.setFontItalic(true);\n        } else if (this.fontItalic) {\n            this.setFontItalic(true);\n        }\n\n        if (this.getLineBreak()) {\n            this.setLineBreak(this.getLineBreak());\n        }\n\n        this.setFontSize(parseFloat(fontArray.shift()));\n        this.setFontType(fontArray.join(' '));\n\n        this._syncFontStyle();\n        Entry.stage.update();\n\n        // NT11576 wodnjs6512\n        // #3513 기존의 텍스트 상자 리사이즈가 필요없는 경우에는 disable 할수 있도록 옵션으로 실행 default = 실행\n        if (shouldUpdateWidth) {\n            this.setWidth(this.textObject.getMeasuredWidth());\n        }\n\n        this.updateBG();\n        Entry.stage.update();\n        Entry.stage.updateObject();\n    }\n\n    setLineHeight() {\n        const lineHeight = this.fontSize + 2;\n\n        if (GEHelper.isWebGL) {\n            this.textObject.style.lineHeight = lineHeight;\n        } else {\n            this.textObject.lineHeight = lineHeight;\n        }\n    }\n\n    syncFont() {\n        const textObject = this.textObject;\n        this._syncFontStyle();\n        this.setLineHeight();\n        Entry.stage.update();\n        if (this.getLineBreak()) {\n            if (this.fontType === 'Nanum Gothic Coding') {\n                textObject.y = textObject.getMeasuredLineHeight() / 2 - this.getHeight() / 2 + 10;\n            }\n        } else {\n            this.setWidth(textObject.getMeasuredWidth());\n            this.setHeight(textObject.getMeasuredHeight());\n        }\n        Entry.stage.updateObject();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * font type getter\n     */\n    getFontType() {\n        return this.fontType;\n    }\n\n    /**\n     * font type setter\n     */\n    setFontType(fontType = 'Nanum Gothic') {\n        if (this.parent.objectType !== 'textBox') {\n            return;\n        }\n        this.fontType = fontType;\n        this.syncFont();\n    }\n\n    /**\n     * font size getter\n     */\n    getFontSize() {\n        return this.fontSize;\n    }\n\n    /**\n     * font size setter\n     */\n    setFontSize(fontSize = 20) {\n        if (this.parent.objectType !== 'textBox') {\n            return;\n        }\n        if (this.fontSize === fontSize) {\n            return;\n        }\n        this.fontSize = fontSize;\n        this.syncFont();\n        this.alignTextBox();\n    }\n\n    /**\n     * set font bold state\n     */\n    setFontBold(isFontBold = false) {\n        this.fontBold = isFontBold;\n        this.syncFont();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * toggle bold on,off and return current\n     */\n    toggleFontBold() {\n        this.fontBold = !this.fontBold;\n        this.syncFont();\n        return this.fontBold;\n    }\n\n    /**\n     * set font italic state\n     */\n    setFontItalic(isFontItalic = false) {\n        this.fontItalic = isFontItalic;\n        this.syncFont();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * toggle italic on,off and return current\n     */\n    toggleFontItalic() {\n        this.fontItalic = !this.fontItalic;\n        this.syncFont();\n        return this.fontItalic;\n    }\n\n    getFontName() {\n        if (this.type !== 'textBox') {\n            return;\n        }\n        const font = this.textObject.font;\n        if (!font) {\n            return '';\n        }\n\n        return font\n            .split(' ')\n            .filter((font) => !/^(bold|italic)$/.test(font) && !~font.indexOf('px'))\n            .join(' ')\n            .trim();\n    }\n\n    /**\n     * NT11576 wodnjs6512\n     * #3513 text effect setter\n     * @param {string} effect\n     */\n    setTextEffect(effect, mode) {\n        if (this.parent.objectType !== 'textBox') {\n            return;\n        }\n        // remember default\n        if (this.defaultLog.textEffect[effect] == undefined) {\n            this.defaultLog.textEffect[effect] = this[effect];\n        }\n        this.textObject.text = this.text;\n        this.applyEffectByNameAndValue(effect, mode == 'on');\n    }\n\n    /**\n     * NT11576 wodnjs6512\n     * #3513 reset text effect accroding to the log left with setTextEffect()\n     */\n    resetTextEffect() {\n        for (const effect of Object.keys(this.defaultLog.textEffect)) {\n            const value = this.defaultLog.textEffect[effect];\n            this.applyEffectByNameAndValue(effect, value);\n        }\n        if (this.defaultLog.textColor) {\n            this.setColour(this.defaultLog.textColor);\n        }\n        if (this.defaultLog.textFont) {\n            this.setFont(this.defaultLog.textFont);\n        }\n        if (this.defaultLog.textBGColor) {\n            this.setBGColour(this.defaultLog.textBGColor);\n        }\n        this.defaultLog = {\n            textEffect: {},\n        };\n    }\n\n    /**\n     * NT11576 wodnjs6512\n     * #3513 change font style and update stage\n     * @param {*} effect\n     * @param {*} mode\n     */\n\n    applyEffectByNameAndValue(effect, mode) {\n        switch (effect) {\n            case 'fontBold':\n                this.setFontBold(mode);\n                break;\n            case 'fontItalic':\n                this.setFontItalic(mode);\n                break;\n            case 'underLine':\n                this.setUnderLine(mode);\n                break;\n            case 'strike':\n                this.setStrike(mode);\n                break;\n        }\n        this.updateTextbox();\n    }\n\n    updateTextbox() {\n        if (!this.lineBreak) {\n            this.setWidth(this.textObject.getMeasuredWidth());\n            this.parent.updateCoordinateView();\n        }\n        this.updateBG();\n        Entry.stage.updateObject();\n    }\n\n    /**\n     * text setter\n     * @param {string} text\n     */\n    setText(text = '') {\n        if (this.parent.objectType !== 'textBox') {\n            return;\n        }\n        /** @type {string} */\n        this.text = text;\n        this.textObject.text = this.text;\n        this.updateTextbox();\n    }\n\n    /**\n     * text getter\n     * @return {string}\n     */\n    getText() {\n        return this.text;\n    }\n\n    /**\n     * textAlign setter\n     * @param {number} textAlign\n     */\n    setTextAlign(textAlign = Entry.TEXT_ALIGN_CENTER) {\n        if (this.parent.objectType !== 'textBox') {\n            return;\n        }\n        this.textAlign = textAlign;\n\n        const textObj = this.textObject;\n        const alignValue = Entry.TEXT_ALIGNS[textAlign];\n        if (GEHelper.isWebGL) {\n            const anchorX = [0.5, 0, 1];\n            textObj.anchor.x = anchorX[textAlign];\n            textObj.style.align = alignValue;\n        } else {\n            textObj.textAlign = alignValue;\n        }\n\n        this.alignTextBox();\n        this.updateBG();\n        Entry.stage.updateObject();\n        /*\n        this.setWidth(this.textObject.getMeasuredWidth());\n        this.updateBG();\n        */\n    }\n\n    /**\n     * textAlign getter\n     * @return {number}\n     */\n    getTextAlign() {\n        return this.textAlign;\n    }\n\n    /**\n     * lineBreak setter\n     * @param {boolean} lineBreak\n     */\n    setLineBreak(lineBreak = false) {\n        if (this.parent.objectType !== 'textBox') {\n            return;\n        }\n        const isWebGL = GEHelper.isWebGL;\n        const previousState = this.lineBreak;\n        this.lineBreak = lineBreak;\n\n        if (previousState && !this.lineBreak) {\n            if (isWebGL) {\n                this.textObject.style.wordWrap = false;\n            } else {\n                this.textObject.lineWidth = null;\n            }\n            this.setHeight(this.textObject.getMeasuredLineHeight());\n            this.setText(this.getText().replace(/\\n/g, ''));\n            if (isWebGL) {\n                this.textObject.anchor.y = 0.5;\n            }\n        } else if (this.lineBreak) {\n            if (previousState === false) {\n                this.setFontSize(this.getFontSize() * this.getScaleX());\n                this.setHeight(this.textObject.getMeasuredLineHeight() * 3);\n                this.setWidth(this.getWidth() * this.getScaleX());\n                this.setScaleX(1);\n                this.setScaleY(1);\n            }\n            if (isWebGL) {\n                this.textObject.anchor.y = 0;\n                this.textObject.style.wordWrap = true;\n                this.textObject.style.breakWords = true;\n                this.textObject.style.wordWrapWidth = Math.ceil(this.getWidth());\n            } else {\n                this.textObject.lineWidth = Math.ceil(this.getWidth());\n            }\n            this.alignTextBox();\n            if (this.fontType === 'Nanum Gothic Coding') {\n                const textObjectHeight = this.textObject.getMeasuredLineHeight();\n                this.textObject.y = textObjectHeight / 2 - this.getHeight() / 2 + 10;\n            }\n        }\n\n        Entry.stage.updateObject();\n    }\n\n    /**\n     * lineBreak getter\n     * @return {number}\n     */\n    getLineBreak() {\n        return this.lineBreak;\n    }\n\n    /**\n     * visible setter\n     * @param {boolean} visible\n     */\n    setVisible(visible = true) {\n        /** @type {string} */\n        this.visible = visible;\n        this.object.visible = this.visible;\n        if (this.dialog) {\n            this.syncDialogVisible();\n        }\n        Entry.requestUpdate = true;\n        return this.visible;\n    }\n\n    /**\n     * visible getter\n     * @return {boolean}\n     */\n    getVisible() {\n        return this.visible;\n    }\n\n    /**\n     * Change picture\n     * @param {?picture model} pictureModel\n     */\n    setImage(pictureModel) {\n        if (!pictureModel) {\n            return;\n        }\n        const that = this;\n        delete pictureModel._id;\n\n        Entry.assert(this.type === 'sprite', 'Set image is only for sprite object');\n        if (!pictureModel.id) {\n            pictureModel.id = Entry.generateHash();\n        }\n\n        this.picture = pictureModel;\n        const dimension = this.picture.dimension;\n        const entityWidth = this.getWidth();\n        const entityHeight = this.getHeight();\n\n        const absoluteRegX = this.getRegX() - entityWidth / 2;\n        const absoluteRegY = this.getRegY() - entityHeight / 2;\n        this.setWidth(dimension.width);\n        this.setHeight(dimension.height);\n        if (!dimension.scaleX) {\n            dimension.scaleX = this.getScaleX();\n            dimension.scaleY = this.getScaleY();\n        }\n\n        this.setScaleX(this.scaleX);\n        this.setScaleY(this.scaleY);\n        this.setRegX(this.width / 2 + absoluteRegX);\n        this.setRegY(this.height / 2 + absoluteRegY);\n\n        /**\n         * //이 코드는 createjs 일때만 호출 됨.\n         * @param {AtlasImageLoadingInfo} info\n         */\n        const onImageLoad = GEHelper.isWebGL\n            ? null\n            : (info) => {\n                  if (this.removed) {\n                      return;\n                  }\n                  const isResizedImage = info.source() !== this.object.image;\n                  if (isResizedImage) {\n                      this.object.image = info.source();\n                  }\n                  const hasFilter = !_.isEmpty(that.object.filters);\n                  GEHelper.colorFilter.setCache(this, hasFilter);\n                  Entry.requestUpdate = true;\n              };\n\n        GEHelper.resManager.reqResource(\n            this.object,\n            this.parent.scene.id,\n            pictureModel,\n            onImageLoad\n        );\n        if (GEHelper.isWebGL) {\n            this._scaleAdaptor.updateScaleFactor();\n            this.object.refreshFilter();\n        }\n\n        Entry.dispatchEvent('updateObject');\n    }\n\n    /**\n     * Apply easel filter\n     */\n    applyFilter(isForce, forceEffects) {\n        const effects = this.effect;\n        const object = this.object;\n\n        let diffEffects = isEqualEffects(effects, this.getInitialEffectValue());\n        if (!isForce && diffEffects.length === 0) {\n            return;\n        }\n\n        if (Array.isArray(forceEffects)) {\n            diffEffects = diffEffects.concat(forceEffects);\n        }\n\n        (function (e, obj) {\n            const f = [];\n            const adjust = Entry.adjustValueWithMaxMin;\n\n            if (~diffEffects.indexOf('brightness')) {\n                const brightness = adjust(e.brightness, -100, 100);\n                f.push(GEHelper.colorFilter.brightness(brightness));\n            }\n\n            if (~diffEffects.indexOf('hue')) {\n                f.push(GEHelper.colorFilter.hue(e.hue.mod(360)));\n            }\n\n            if (~diffEffects.indexOf('hsv')) {\n                /* eslint-disable */\n                let matrixValue = [\n                    1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1,\n                ];\n                /* eslint-enable */\n\n                const degrees = e.hsv * 3.6;\n                const r = (degrees * 3 * Math.PI) / 180;\n                const cosVal = Math.cos(r);\n                const sinVal = Math.sin(r);\n\n                let v = Math.abs(e.hsv / 100);\n                if (v > 1) {\n                    v = v - Math.floor(v);\n                }\n\n                if (v > 0 && v <= 0.33) {\n                    /* eslint-disable */\n                    matrixValue = [\n                        1,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        cosVal,\n                        sinVal,\n                        0,\n                        0,\n                        0,\n                        -1 * sinVal,\n                        cosVal,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        1,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        1,\n                    ];\n                } else if (v <= 0.66) {\n                    matrixValue = [\n                        cosVal,\n                        0,\n                        sinVal,\n                        0,\n                        0,\n                        1,\n                        0,\n                        0,\n                        0,\n                        0,\n                        sinVal,\n                        0,\n                        cosVal,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        1,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        1,\n                    ];\n                } else if (v <= 0.99) {\n                    matrixValue = [\n                        cosVal,\n                        sinVal,\n                        0,\n                        0,\n                        0,\n                        -1 * sinVal,\n                        cosVal,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        1,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        1,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        1,\n                    ];\n                }\n                /* eslint-enable */\n\n                const colorFilter = GEHelper.colorFilter.newColorMatrixFilter(matrixValue);\n                f.push(colorFilter);\n            }\n\n            if (~diffEffects.indexOf('alpha')) {\n                e.alpha = adjust(e.alpha, 0, 1);\n                obj.alpha = e.alpha;\n                if (obj.alpha < 0.001) {\n                    obj.interactive = false;\n                } else {\n                    obj.interactive = true;\n                }\n            }\n            if (GEHelper.isWebGL) {\n                obj.setFilterAndCache(f);\n            } else {\n                obj.filters = f;\n            }\n        })(effects, object);\n\n        this.cache();\n\n        function isEqualEffects(effectsA, effectsB) {\n            const diffEffects = [];\n            for (const key in effectsA) {\n                if (effectsA[key] !== effectsB[key]) {\n                    diffEffects.push(key);\n                }\n            }\n            return diffEffects;\n        }\n    }\n\n    /**\n     * Remove all filter\n     */\n    resetFilter() {\n        if (this.parent.objectType !== 'sprite') {\n            return;\n        }\n\n        const object = this.object;\n        if (GEHelper.isWebGL) {\n            object.setFilterAndCache(null);\n        } else {\n            object.filters = [];\n        }\n        this.setInitialEffectValue();\n        object.alpha = this.effect.alpha;\n        if (object.alpha < 0.001) {\n            object.interactive = false;\n        } else {\n            object.interactive = true;\n        }\n        GEHelper.colorFilter.setCache(this, false);\n    }\n\n    /**\n     * update dialog position if exist\n     */\n    updateDialog() {\n        if (this.dialog) {\n            this.dialog.update();\n        }\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * save current state data to 'snapshot_'\n     */\n    takeSnapshot() {\n        this.snapshot_ = this.toJSON();\n        this.collision = Entry.Utils.COLLISION.NONE;\n    }\n\n    /**\n     * load snapshot to current entity\n     */\n    loadSnapshot() {\n        if (this.snapshot_) {\n            this.syncModel_(this.snapshot_);\n        }\n        if (this.parent.objectType === 'sprite') {\n            this.setImage(this.parent.getPicture());\n        }\n\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * Remove itself when this is clone\n     */\n    removeClone(isLast) {\n        if (!this.isClone) {\n            return;\n        }\n\n        const clonedEntities = this.parent.clonedEntities;\n\n        if (isLast !== true) {\n            const index = clonedEntities.indexOf(this);\n            if (index > -1) {\n                clonedEntities.splice(index, 1);\n            }\n        } else {\n            clonedEntities.pop();\n        }\n\n        _.result(this, 'clearExecutor');\n        this.destroy(true);\n    }\n\n    clearExecutor() {\n        this.parent.script.clearExecutorsByEntity(this);\n    }\n\n    /**\n     * convert this entity's data to JSON.\n     * @return {JSON}\n     */\n    toJSON() {\n        const _cut = Entry.cutDecimal;\n\n        const json = {};\n        json.x = _cut(this.getX());\n        json.y = _cut(this.getY());\n        json.regX = _cut(this.getRegX());\n        json.regY = _cut(this.getRegY());\n        json.scaleX = this.getScaleX();\n        json.scaleY = this.getScaleY();\n        json.rotation = _cut(this.getRotation());\n        json.direction = _cut(this.getDirection());\n        json.width = _cut(this.getWidth());\n        json.height = _cut(this.getHeight());\n        json.font = this.getFont();\n        json.visible = this.getVisible();\n\n        if (this.parent.objectType === 'textBox') {\n            json.colour = this.getColour();\n            json.text = this.getText();\n            json.textAlign = this.getTextAlign();\n            json.lineBreak = this.getLineBreak();\n            json.bgColor = this.getBGColour();\n            json.underLine = this.getUnderLine();\n            json.strike = this.getStrike();\n            json.fontSize = this.getFontSize();\n        }\n        return json;\n    }\n\n    /*\n     * Return initial effect value\n     * @return {effect}\n     */\n    setInitialEffectValue() {\n        this.effect = this.getInitialEffectValue();\n        Entry.requestUpdate = true;\n    }\n\n    /*\n     * Return initial effect value\n     * @return {effect}\n     */\n    getInitialEffectValue() {\n        return {\n            blur: 0,\n            hue: 0,\n            hsv: 0,\n            brightness: 0,\n            contrast: 0,\n            saturation: 0,\n            alpha: 1,\n        };\n    }\n\n    /*\n     * Return initial effect value\n     * @return {effect}\n     */\n    setVoiceProp(prop) {\n        const { speed = 0, pitch = 0, speaker = 'kyuri', volume = 1 } = prop;\n        this.voice = { speed, pitch, speaker, volume };\n    }\n\n    /*\n     * Return initial effect value\n     * @return {effect}\n     */\n    getVoiceProp() {\n        return this.voice;\n    }\n\n    /*\n     * remove brush\n     */\n    removeBrush() {\n        this._removeShapes();\n        this.brush = null;\n    }\n\n    removePaint() {\n        this._removePaintShapes();\n        this.paint = null;\n    }\n\n    eraseBrush() {\n        const brush = this.brush;\n        if (brush) {\n            // WebGL 인경우 createjs와 같은 코드로 동작하지 않아서 코드 분기생성 (#11626)\n            const isWebGL = GEHelper.isWebGL;\n            if (isWebGL) {\n                const { r, g, b } = brush.rgb;\n                const thickness = brush.thickness;\n                const opacity = 1 - brush.opacity / 100;\n                brush.clear();\n                brush.setStrokeStyle(thickness);\n                brush.beginStrokeFast(Entry.rgb2Number(r, g, b), opacity);\n            } else {\n                // 기존 스펙으로 롤백(#11434)\n                const stroke = brush._stroke.style;\n                const thickness = brush._strokeStyle.width;\n                brush.clear().setStrokeStyle(thickness).beginStroke(stroke);\n            }\n        }\n        Entry.requestUpdate = true;\n    }\n\n    erasePaint() {\n        const paint = this.paint;\n        if (paint) {\n            paint.clear();\n        }\n        Entry.requestUpdate = true;\n    }\n\n    _removeShapes() {\n        const container = Entry.stage.selectedObjectContainer;\n        const shapes = this.shapes;\n        const LEN = shapes.length;\n        let s;\n        for (let i = 0; i < LEN; i++) {\n            s = shapes[i];\n            container.removeChild(s);\n            s.destroy && s.destroy(true); //pixi 일때만 호출\n        }\n        this.shapes = [];\n    }\n\n    _removePaintShapes() {\n        const container = Entry.stage.selectedObjectContainer;\n        const shapes = this.paintShapes;\n        const LEN = shapes.length;\n        let s;\n        for (let i = 0; i < LEN; i++) {\n            s = shapes[i];\n            container.removeChild(s);\n            s.destroy && s.destroy(true); //pixi 일때만 호출\n        }\n        this.paintShapes = [];\n    }\n\n    updateBG() {\n        if (!this.bgObject) {\n            return;\n        }\n        this.bgObject.graphics.clear();\n        const width = this.getWidth();\n        const height = this.getHeight();\n        const bgColor = this.getBGColour();\n        const hasColor = (bgColor || '').indexOf('#') === 0;\n        this.bgObject.alpha = hasColor ? 1 : 0;\n\n        this.bgObject.graphics.beginFill(bgColor).drawRect(-width / 2, -height / 2, width, height);\n        if (this.getLineBreak()) {\n            this.bgObject.x = 0;\n        } else {\n            const fontAlign = this.getTextAlign();\n            switch (fontAlign) {\n                case Entry.TEXT_ALIGN_LEFT:\n                    this.bgObject.x = width / 2;\n                    break;\n                case Entry.TEXT_ALIGN_CENTER:\n                    this.bgObject.x = 0;\n                    break;\n                case Entry.TEXT_ALIGN_RIGHT:\n                    this.bgObject.x = -width / 2;\n                    break;\n            }\n        }\n    }\n\n    // 통상적 높이 계산을 위한 Method\n    getMeasuredLineHeight() {\n        if (!this.invisibleCanvas) {\n            if (this.textObject.canvas) {\n                this.invisibleCanvas = this.textObject.canvas;\n            } else {\n                this.invisibleCanvas = Entry.Dom($('<canvas id=\"invisibleCanvas\"></canvas>'))[0];\n            }\n        }\n        const fontCanvas = this.invisibleCanvas;\n        const context = fontCanvas.getContext('2d');\n        context.font = this.textObject.font;\n        return Math.round(context.measureText('M').width * 100) / 100;\n    }\n\n    alignTextBox() {\n        if (this.type !== 'textBox') {\n            return;\n        }\n        const textObject = this.textObject;\n        const isWebGL = GEHelper.isWebGL;\n        if (this.lineBreak) {\n            if (isWebGL) {\n                textObject.y =\n                    -this.getHeight() / 2 + TEXT_BOX_REPOSITION_OFFSET - TEXT_BOX_WEBGL_OFFSET;\n            } else {\n                const desiredValue =\n                    textObject.getMeasuredLineHeight() / 2 -\n                    this.getHeight() / 2 +\n                    TEXT_BOX_REPOSITION_OFFSET / 2;\n                // 가끔씩 계산의 값이 달라지는 경우가 있어서 확인하여서 기존과 차이가 거의 없다면 그대로,\n                if (Math.abs(desiredValue - textObject.y) > TEXT_BOX_REPOSITION_THRESHOLD) {\n                    textObject.y =\n                        FONT_PADDING_TOP_EXCEPTIONS.indexOf(this.fontType) > -1\n                            ? desiredValue + TEXT_BOX_REPOSITION_OFFSET\n                            : desiredValue;\n                }\n            }\n\n            switch (this.textAlign) {\n                case Entry.TEXT_ALIGN_CENTER:\n                    textObject.x = 0;\n                    break;\n                case Entry.TEXT_ALIGN_LEFT:\n                    textObject.x = -this.getWidth() / 2;\n                    break;\n                case Entry.TEXT_ALIGN_RIGHT:\n                    textObject.x = this.getWidth() / 2;\n                    break;\n            }\n            if (isWebGL) {\n                textObject.style.maxHeight = this.getHeight();\n            } else {\n                textObject.maxHeight = this.getHeight();\n            }\n        } else {\n            textObject.x = 0;\n            textObject.y = 0;\n        }\n    }\n\n    syncDialogVisible() {\n        if (this.dialog?.object) {\n            this.dialog.object.visible = this.visible;\n        }\n    }\n\n    addStamp() {\n        const stampEntity = new Entry.StampEntity(this.parent, this);\n        const stage = Entry.stage;\n        stage.loadEntity(stampEntity, stage.selectedObjectContainer.getChildIndex(this.object));\n        this.stamps.push(stampEntity);\n\n        Entry.requestUpdate = true;\n    }\n\n    removeStamps() {\n        this.stamps.forEach((s) => s.destroy());\n        this.stamps = [];\n        Entry.requestUpdate = true;\n    }\n\n    destroy(isClone) {\n        if (this.removed) {\n            return;\n        }\n\n        this.removed = true;\n\n        const object = this.object;\n        if (object) {\n            GEHelper.colorFilter.setCache(this, false);\n            object.removeAllEventListeners && object.removeAllEventListeners();\n            delete object.image;\n            delete object.entity;\n        }\n\n        if (this._scaleAdaptor) {\n            this._scaleAdaptor.destroy();\n            this._scaleAdaptor = null;\n        }\n\n        if (this.stamps && this.stamps.length) {\n            this.removeStamps();\n        }\n\n        _.result(this.dialog, 'remove');\n        this.brush && this.removeBrush();\n        this.paint && this.removePaint();\n        Entry.stage.unloadEntity(this);\n\n        //pixi 전용 코드\n        object && object.destroy && object.destroy({ children: true });\n    }\n\n    cache() {\n        const { object } = this;\n        if (object) {\n            if (!GEHelper.isWebGL) {\n                object.cache(0, 0, this.getWidth(), this.getHeight());\n            }\n            Entry.requestUpdate = true;\n        }\n    }\n\n    reset() {\n        this.resetTextEffect();\n        this.loadSnapshot();\n        this.resetFilter();\n\n        _.result(this.dialog, 'remove');\n        this.shapes.length && this.removeBrush();\n        this.paintShapes.length && this.removePaint();\n    }\n\n    _syncFontStyle() {\n        this.textObject.font = this.getFont();\n        if (!GEHelper.isWebGL) {\n            return;\n        }\n        const style = this.textObject.style;\n        style.fontSize = `${this.getFontSize()}px`;\n        style.fontStyle = this.fontItalic ? 'italic' : 'normal';\n        style.fontWeight = this.fontBold ? 'bold' : 'normal';\n        style.fontFamily = this.fontType;\n    }\n};\n"
  },
  {
    "path": "src/class/entryModuleLoader.ts",
    "content": "import fetch from 'isomorphic-fetch';\nimport cryptojs from 'crypto-js';\nimport { EntryBlock, EntryBlockModule, EntryHardwareBlockModule } from '../../types/index';\n\ntype EntryBlockRegisterSchema = {\n    blockName: string;\n    block: EntryBlock;\n    isBlockShowBlockMenu?: boolean;\n};\n\nclass EntryModuleLoader {\n    public moduleList: string[] = [];\n    public moduleListLite: string[] = [];\n\n    /**\n     * @deprecated\n     * 해당 url 을 동적으로 로드한다.\n     * 해당 함수는 굉장히 위험하므로 추가적인 방어로직이 필요하다.\n     * key는 로컬에서 파일을 암호화 하여 entry-hw 에서 전달, 해당 파일을 로컬에 있는 키로 1차 검증, 서버로 2차 검증을 통한 무결성/보안 확보\n     * 오프라인의 경우, 오픈소스임으로, 로컬상태에서의 비정상적인 사용에 대한 제약이 힘든 부분이 있음. 다만, 온라인이 되는 경우 서버 검증을 사용 할 수 있음\n     */\n    // bl.loadModule(moduleName: string) bl.loadBlock(blockName, block)...\n    async loadModule(moduleInfo: { name: string; file: string }): Promise<void> {\n        if (!moduleInfo.file || !moduleInfo.name) {\n            return;\n        }\n\n        let blockFile = moduleInfo.file;\n        if (Entry.offlineModulePath) {\n            if (window.sendSync) {\n                blockFile = window.sendSync('decryptBlock', blockFile);\n            }\n        }\n\n        const key = cryptojs.SHA1(blockFile);\n        // sha1 key를 이용한 블럭 파일 검증.\n        if (window.navigator.onLine) {\n            try {\n                const sha1Result = await fetch(\n                    `${Entry.moduleBaseUrl}key/${moduleInfo.name}/${key}`\n                );\n                if (sha1Result.status != 200) {\n                    throw new Error('MODULE NOT VERIFIED');\n                }\n            } catch (e) {\n                throw new Error('MODULE NOT VERIFIED');\n            }\n        }\n        if (!moduleInfo) {\n            return;\n        }\n        await this.loadScript(moduleInfo.name, blockFile);\n    }\n\n    async loadModuleFromLocalOrOnline(name: string, isLite?: boolean) {\n        const lowerCaseName = isLite ? name : name.toLowerCase();\n        const baseUrl = isLite ? Entry.moduleliteBaseUrl : Entry.moduleBaseUrl;\n        let path = `${baseUrl}${name}/files/block`;\n        if (Entry.offlineModulePath) {\n            path = `file://${Entry.offlineModulePath}/${lowerCaseName}/block`;\n        }\n        const response = await fetch(path);\n        if (response.status != 200) {\n            throw new Error('MODULE NOT EXIST');\n        }\n        let result = await response.text();\n        const key = cryptojs.SHA1(result).toString();\n        const isValid = Entry.HARDWARE_LITE_LIST.some(\n            (item: any) => item.name == name && item.sha1 == key\n        );\n        if (!isValid) {\n            return alert('NOT VALID MODULE');\n        }\n        if (Entry.offlineModulePath) {\n            if (window.sendSync) {\n                result = window.sendSync('decryptBlock', result);\n            }\n        }\n        await this.loadScript(name, result, isLite);\n    }\n\n    async loadScript(name: string, code: string, isLite?: boolean) {\n        return await new Promise(async (resolve, reject) => {\n            const scriptElementId = `entryModuleScript${Date.now()}`;\n            const scriptElement = document.createElement('script');\n            scriptElement.id = scriptElementId;\n\n            scriptElement.onload = () => {\n                this.moduleListLite = [name];\n                scriptElement.remove();\n                resolve();\n            };\n            scriptElement.onerror = (e) => {\n                scriptElement.remove();\n                reject(e);\n            };\n\n            const blobedBlock = new Blob([code], {\n                type: 'text/javascript',\n            });\n            const blobUrl = URL.createObjectURL(blobedBlock);\n\n            scriptElement.src = blobUrl;\n            // noinspection JSCheckFunctionSignatures\n            document.body.appendChild(scriptElement);\n            URL.revokeObjectURL(blobUrl);\n        });\n    }\n\n    // noinspection JSUnusedGlobalSymbols\n    /**\n     * [!] 외부에서 사용하는 함수입니다. 모듈화된 블록이 엔트리 등록을 위해 사용하는 함수임\n     * 각 블록정보가 존재해야할 위치에 모든 데이터를 뿌려준다. 위치는 아래와 같다\n     * - Entry.HARDWARE_LIST\n     * - Entry.block : 실제 블록 정보를 담는다.\n     *\n     * 워크스페이스 리로드시 정보가 저장되지 않는다.\n     * 이 후 블록메뉴에 블록들을 실시간으로 추가한 뒤 reDraw 한다.\n     * @param moduleObject 하드웨어 모듈. 여타 하드웨어 모듈 파일 참조\n     */\n    registerHardwareModule(moduleObject: EntryHardwareBlockModule) {\n        if (!moduleObject.getBlocks || !moduleObject.blockMenuBlocks) {\n            return;\n        }\n\n        if (typeof moduleObject.id === 'string') {\n            const prevModuleBlocks =\n                Entry.HARDWARE_LIST[moduleObject.id] &&\n                Entry.HARDWARE_LIST[moduleObject.id].blockMenuBlocks;\n            if (prevModuleBlocks) {\n                this.removePrevModuleBlock(prevModuleBlocks);\n            }\n            Entry.HARDWARE_LIST[moduleObject.id] = moduleObject;\n        } else if (moduleObject.id instanceof Array) {\n            moduleObject.id.forEach((id) => {\n                const prevModuleBlocks =\n                    Entry.HARDWARE_LIST[id] && Entry.HARDWARE_LIST[id].blockMenuBlocks;\n                if (prevModuleBlocks) {\n                    this.removePrevModuleBlock(prevModuleBlocks);\n                }\n                Entry.HARDWARE_LIST[id] = moduleObject;\n            });\n        }\n\n        this.setLanguageTemplates(moduleObject);\n        const blockObjects = moduleObject.getBlocks();\n        const blockMenuBlocks = moduleObject.blockMenuBlocks;\n        this.loadBlocks({\n            categoryName: 'arduino',\n            blockSchemas: Object.entries(blockObjects).map(([blockName, block]) => ({\n                blockName,\n                block,\n                isBlockShowBlockMenu: blockMenuBlocks.indexOf(blockName) > -1,\n            })),\n        });\n\n        Entry.hw.setExternalModule(moduleObject);\n        Entry.dispatchEvent('hwChanged');\n    }\n\n    // clear prevModule if present\n    removePrevModuleBlock(prevModuleBlocks: Array<string>) {\n        let removedCnt = 0;\n        for (const key of Object.keys(Entry.block)) {\n            if (prevModuleBlocks.indexOf(key) > -1) {\n                delete Entry.block[key];\n                removedCnt++;\n            }\n            if (removedCnt == prevModuleBlocks.length) {\n                break;\n            }\n        }\n    }\n\n    // 모듈화 적용시, 팝업이벤트로부터 모듈name값만 받아서 동적으로 로드한다.\n    async registerHardwareLiteModule(moduleObject: EntryHardwareBlockModule) {\n        if (!moduleObject.getBlocks || !moduleObject.blockMenuBlocks) {\n            return;\n        }\n        Entry.hwLite.banClassAllHardwareLite();\n        this.setLanguageTemplates(moduleObject);\n        const blockObjects = moduleObject.getBlocks();\n        const blockMenuBlocks = moduleObject.blockMenuBlocks;\n        this.loadBlocks({\n            categoryName: 'arduino',\n            blockSchemas: Object.entries(blockObjects).map(([blockName, block]) => ({\n                blockName,\n                block,\n                isBlockShowBlockMenu: blockMenuBlocks.indexOf(blockName) > -1,\n            })),\n        });\n        Entry.hwLite.setExternalModule(moduleObject);\n    }\n\n    /**\n     * 이 함수는 외부 블록 모듈 URL 의 코드가 호출한다.\n     * 엔트리 내 '확장' 카테고리에 블록을 추가한다.\n     * 블록은 moduleObject 의 정보에 따라 타이틀, 설명 TextBlock 이 같이 추가된다.\n     * @param moduleObject\n     */\n    registerBlockModule(moduleObject: EntryBlockModule) {\n        const { name, title, description, getBlocks } = moduleObject;\n        const blockSchemas: EntryBlockRegisterSchema[] = [];\n\n        title && blockSchemas.push(this.createTextBlock(name, title.ko));\n        description && blockSchemas.push(this.createTextBlock(name, description));\n        getBlocks &&\n            blockSchemas.push(\n                ...Object.entries(getBlocks()).map(([blockName, block]) => ({\n                    blockName,\n                    block,\n                    isBlockShowBlockMenu: true,\n                }))\n            );\n\n        this.loadBlocks({\n            categoryName: 'expansion',\n            blockSchemas,\n        });\n    }\n\n    loadBlocks({\n        categoryName,\n        blockSchemas,\n    }: {\n        categoryName: string;\n        blockSchemas: EntryBlockRegisterSchema[];\n    }) {\n        const blockMenu = Entry.getMainWS()?.blockMenu;\n\n        blockSchemas.forEach((blockSchema) => {\n            this.applyDefaultProperties(blockSchema);\n            const { blockName, block, isBlockShowBlockMenu } = blockSchema;\n\n            // 블록의 카테고리를 정의할때 사용\n            if (!block.category) {\n                block.category = categoryName;\n            }\n\n            Entry.block[blockName] = block;\n            if (isBlockShowBlockMenu && blockMenu) {\n                blockMenu.addCategoryData(categoryName, blockName);\n            }\n        });\n        if (!blockMenu) {\n            return;\n        }\n\n        blockMenu.reDraw();\n    }\n\n    private createTextBlock(moduleName: string, content: string): EntryBlockRegisterSchema {\n        const blockName = `${moduleName}_${Math.random()}`;\n        const block: EntryBlock = {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            skeleton: 'basic_text',\n            class: moduleName,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: content,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: blockName,\n            },\n            isNotFor: [moduleName],\n            events: {},\n        };\n        return { blockName, block };\n    }\n\n    /**\n     * TODO 리로드 되는 경우 다시 불러오지 않기 때문에 템플릿정보 저장이 필요함\n     */\n    private setLanguageTemplates(moduleObject: EntryHardwareBlockModule) {\n        if (moduleObject.setLanguage) {\n            const langTemplate = moduleObject.setLanguage();\n            const data = langTemplate[Lang.type] || langTemplate[Lang.fallbackType];\n            for (const key in data) {\n                Object.assign(Lang[key], data[key]);\n            }\n        }\n    }\n\n    /**\n     * 블록 모델이 블록객체로서 구현되기 전에 불충분한 프로퍼티나 잘못된 값이 있는 경우 이쪽에서 수정한다.\n     */\n    private applyDefaultProperties({ blockName, block }: EntryBlockRegisterSchema) {\n        if (!block.color) {\n            block.color = EntryStatic.colorSet.block.default.EXPANSION;\n            block.outerLine = EntryStatic.colorSet.block.darken.EXPANSION;\n        }\n\n        if (!block.type) {\n            block.type = blockName;\n        }\n    }\n}\n\nconst instance = new EntryModuleLoader();\nexport default instance;\nEntry.moduleManager = instance;\n\n/**\n * 프로젝트 가 외부 모듈이 사용되었는지 확인하고, 로드한다\n * @param {*} project 엔트리 프로젝트\n * @return Promise\n */\nEntry.loadExternalModules = async (project = {}) => {\n    const { externalModules = [] } = project;\n    await Promise.all(externalModules.map(instance.loadModuleFromLocalOrOnline.bind(instance)));\n};\n\nEntry.loadLiteExternalModules = async (project = {}) => {\n    const { externalModulesLite = [] } = project;\n    Entry.externalModulesLite = externalModulesLite;\n    await Promise.all(externalModulesLite.map(instance.registerHardwareLiteModule.bind(instance)));\n};\n\n/**\n * 개발용 코드, path를 통해서 블럭을 로딩할수 있음.\n * @param path\n */\nEntry.loadLiteTestModule = async (file: File, name: string) => {\n    const result = await file.text();\n    await Entry.moduleManager.loadScript(name, result, true);\n    // Entry.moduleManager.registerHardwareLiteModule(name);\n};\n\nEntry.loadLiteTestModuleUploader = () => {\n    const headerBtns = document.querySelector('section');\n    const fileInput = document.createElement('input');\n    fileInput.type = 'file';\n    const nameInput = document.createElement('input');\n    nameInput.type = 'text';\n    const loadButton = document.createElement('button');\n    loadButton.innerText = '적용';\n    const handleUpdate = async () => {\n        const file = fileInput.files[0];\n        fileInput.value = null;\n        await Entry.loadLiteTestModule(file, nameInput.value);\n    };\n\n    loadButton.onclick = handleUpdate;\n    headerBtns.prepend(loadButton);\n    headerBtns.prepend(fileInput);\n    headerBtns.prepend(nameInput);\n};\n"
  },
  {
    "path": "src/class/function.js",
    "content": "import _truncate from 'lodash/truncate';\nimport _trim from 'lodash/trim';\nimport _cloneDeep from 'lodash/cloneDeep';\nimport _find from 'lodash/find';\n\nclass EntryFunc {\n    static isEdit = false;\n    static threads = {};\n\n    constructor(func = {}) {\n        const {\n            type = 'normal',\n            id = Entry.generateHash(),\n            localVariables = [],\n            useLocalVariables = false,\n        } = func;\n        this.id = id;\n        this.type = type;\n        this.localVariables = localVariables;\n        this.useLocalVariables = useLocalVariables;\n        let content;\n        //inspect empty content\n        if (func && func.content && func.content.length > 4) {\n            content = func.content;\n        }\n\n        let codeType = 'function_create';\n        if (type === 'value') {\n            codeType = 'function_create_value';\n        }\n        this.content = content\n            ? new Entry.Code(content)\n            : new Entry.Code([\n                  [\n                      {\n                          type: codeType,\n                          copyable: false,\n                          deletable: false,\n                          x: 40,\n                          y: 40,\n                      },\n                  ],\n              ]);\n        this.block = null;\n        this.blockMenuBlock = null;\n        this.hashMap = {};\n        this.paramMap = {};\n\n        EntryFunc._generateFunctionSchema(this.id, type);\n\n        if (func && func.content) {\n            const blockMap = this.content._blockMap;\n            for (const key in blockMap) {\n                EntryFunc.registerParamBlock(blockMap[key].type);\n            }\n            EntryFunc.generateWsBlock(this);\n        }\n\n        EntryFunc.registerFunction(this);\n\n        EntryFunc.updateMenu();\n    }\n\n    destroy() {\n        this.blockMenuBlock && this.blockMenuBlock.destroy();\n    }\n\n    edit() {\n        if (EntryFunc.isEdit) {\n            return;\n        }\n        EntryFunc.isEdit = true;\n        Entry.getMainWS().blockMenu.deleteRendered('variable');\n        if (!EntryFunc.svg) {\n            EntryFunc.isEdit = EntryFunc.initEditView();\n        } else {\n            this.parentView.appendChild(this.svg);\n        }\n    }\n\n    generateBlock() {\n        const generatedInfo = EntryFunc.generateBlock(this);\n        this.block = generatedInfo.block;\n        this.description = generatedInfo.description;\n    }\n\n    defaultLocalVariable(isForce) {\n        return {\n            name: this.makeLocalVariableName(isForce),\n            value: 0,\n        };\n    }\n\n    setLocalVariableLength(length) {\n        if (!this.localVariables) {\n            this.localVariables = [];\n        }\n        if (this.localVariables.length >= length) {\n            this.localVariables.splice(length, this.localVariables.length - length);\n        } else {\n            const max = length - this.localVariables.length;\n            for (let i = 0; i < max; i++) {\n                this.localVariables.push(this.defaultLocalVariable(true));\n            }\n        }\n        Entry.variableContainer && Entry.variableContainer.updateFuncScrollBar(this);\n    }\n\n    appendLocalVariable(value) {\n        if (!this.localVariables) {\n            this.localVariables = [];\n        }\n        this.localVariables.push(value);\n\n        Entry.variableContainer && Entry.variableContainer.updateFuncScrollBar(this);\n    }\n\n    insertFuncLocalVariable(value, index) {\n        if (!this.localVariables) {\n            this.localVariables = [];\n        }\n        this.localVariables.splice(index, 0, value);\n\n        Entry.variableContainer && Entry.variableContainer.updateFuncScrollBar(this);\n    }\n\n    removeLocalVariable(idx) {\n        if (!Array.isArray(this.localVariables)) {\n            return;\n        }\n        if (this.localVariables.length >= idx) {\n            this.localVariables.splice(idx, 1);\n        }\n        Entry.variableContainer && Entry.variableContainer.updateFuncScrollBar(this);\n    }\n\n    removeLastLocalVariable() {\n        this.removeLocalVariable(this.localVariables.length - 1);\n    }\n\n    toggleFunctionUseLocalVariables() {\n        this.useLocalVariables = !this.useLocalVariables;\n        Entry.variableContainer && Entry.variableContainer.updateFuncSettingView(this);\n        EntryFunc.updateMenu();\n    }\n\n    getLocalVariables() {\n        return this.localVariables;\n    }\n\n    makeLocalVariableName(isForce) {\n        let name = Lang.Workspace.local_variable;\n        if (this.checkLocalVariableName(name)) {\n            name = Entry.getOrderedName(name, this.localVariables, 'name');\n            if (!isForce) {\n                Entry.toast.warning(\n                    Lang.Workspace.local_variable_rename,\n                    Lang.Workspace.local_variable_dup\n                );\n            }\n        }\n\n        return name;\n    }\n\n    checkLocalVariableName(name) {\n        return this.localVariables.some((localVariable) => localVariable.name === name);\n    }\n\n    changeNameLocalVariable(name, index) {\n        const localVariable = this.localVariables[index];\n        localVariable.name = name;\n        const { playground } = Entry;\n        if (playground) {\n            playground.blockMenu.deleteRendered('func');\n            playground.reloadPlayground();\n        }\n    }\n\n    getValue(variableId, localVariables) {\n        const localVariable = _find(\n            localVariables || this.localVariables,\n            (localVariable) => localVariable.id === variableId\n        );\n        return localVariable?.value || 0;\n    }\n\n    setValue(value, variableId, localVariables) {\n        const localVariable = _find(\n            localVariables || this.localVariables,\n            (localVariable) => localVariable.id === variableId\n        );\n        localVariable.value = value;\n    }\n\n    getBlockById(blockId) {\n        return this?.content?.findById(blockId);\n    }\n\n    getFuncBlockByFuncId(funcId) {\n        return this?.content?.findByType(funcId);\n    }\n\n    getBlockByParamId(paramId) {\n        return this?.content?.findByParamId(paramId);\n    }\n\n    static changeFunctionName(name) {\n        Entry.Mutator.mutate(\n            'function_name',\n            {\n                template: `${Lang.Workspace.func}: ${_trim(\n                    _truncate(name, {\n                        length: 20,\n                    })\n                )}`,\n            },\n            { type: 'noChange', isRestore: undefined }\n        );\n    }\n\n    static initBlock(blockMenu) {\n        blockMenu.banClass('functionEdit', true);\n        blockMenu.banClass('useLocalVariables', true);\n        this.changeFunctionName('');\n    }\n\n    static registerFunction(func) {\n        const workspace = Entry && Entry.getMainWS();\n        if (!workspace) {\n            return;\n        }\n        const blockMenu = workspace.getBlockMenu();\n        const menuCode = blockMenu.code;\n\n        let index = undefined;\n        if (this._fieldLabel) {\n            index = menuCode.getThreadIndex(this._fieldLabel.thread);\n        }\n\n        this._targetFuncBlock = menuCode.createThread(\n            [\n                {\n                    type: `func_${func.id}`,\n                    category: 'func',\n                    x: -9999,\n                },\n            ],\n            index\n        );\n        func.blockMenuBlock = this._targetFuncBlock;\n    }\n\n    static clearThreads() {\n        this.threads = {};\n    }\n\n    static edit(func) {\n        let funcElement = func;\n        if (typeof func === 'string') {\n            funcElement = Entry.variableContainer.getFunction(/(func_)?(.*)/.exec(func)[2]);\n        }\n        if (!funcElement) {\n            console.error('no function');\n            return;\n        }\n        this.unbindFuncChangeEvent();\n        this.unbindWorkspaceStateChangeEvent();\n\n        this.cancelEdit();\n\n        this.targetFunc = funcElement;\n        EntryFunc.isEdit = true;\n        Entry.getMainWS().blockMenu.deleteRendered('variable');\n        if (this.initEditView(funcElement.content) === false) {\n            EntryFunc.isEdit = false;\n            return;\n        } // edit fail\n        this.bindFuncChangeEvent(funcElement);\n        this.updateMenu();\n        requestAnimationFrame(() => {\n            const schema = Entry.block[`func_${funcElement.id}`];\n            if (schema && schema.paramsBackupEvent) {\n                schema.paramsBackupEvent.notify();\n            }\n\n            this._backupContent = funcElement.content.stringify();\n            this._backupOption = {\n                type: funcElement.type,\n                useLocalVariables: funcElement.useLocalVariables,\n                localVariables: _cloneDeep(funcElement.localVariables),\n            };\n            Entry.getMainWS().overlayBoard.reDraw();\n        });\n    }\n\n    static initEditView(content) {\n        if (this.targetFunc) {\n            const defBlock = this.targetFunc.content.getEventMap('funcDef')[0];\n\n            if (defBlock) {\n                let outputBlock = defBlock.params[0];\n                let functionNmaeTemplate = '';\n                let booleanIndex = 0;\n                let stringIndex = 0;\n\n                while (outputBlock) {\n                    const value = outputBlock.params[0];\n                    const valueType = value.type;\n                    switch (outputBlock.type) {\n                        case 'function_field_label':\n                            functionNmaeTemplate = `${functionNmaeTemplate} ${value}`;\n                            break;\n                        case 'function_field_boolean':\n                            booleanIndex++;\n                            // eslint-disable-next-line max-len\n                            functionNmaeTemplate += ` <${Lang.Blocks.FUNCTION_logical_variable} ${booleanIndex}>`;\n                            break;\n                        case 'function_field_string':\n                            stringIndex++;\n                            // eslint-disable-next-line max-len\n                            functionNmaeTemplate += ` (${Lang.Blocks.FUNCTION_character_variable} ${stringIndex})`;\n                            break;\n                    }\n\n                    outputBlock = outputBlock.getOutputBlock();\n                }\n                this.changeFunctionName(functionNmaeTemplate);\n            }\n        }\n        if (!this.menuCode) {\n            this.setupMenuCode();\n        }\n        const workspace = Entry.getMainWS();\n        if (workspace.setMode(Entry.Workspace.MODE_OVERLAYBOARD) === false) {\n            this.endEdit('cancelEdit');\n            return false;\n        }\n        workspace.changeOverlayBoardCode(content);\n\n        this._workspaceStateEvent = workspace.changeEvent.attach(this, (message = 'cancelEdit') => {\n            this.endEdit(message);\n            if (workspace.getMode() === Entry.Workspace.MODE_VIMBOARD) {\n                workspace.blockMenu.banClass('functionInit');\n            }\n        });\n        content.board.alignThreads();\n\n        return true;\n    }\n\n    static endEdit(message) {\n        this.unbindFuncChangeEvent();\n        this.unbindWorkspaceStateChangeEvent();\n        const targetFuncId = this.targetFunc.id;\n\n        if (this.targetFunc && this.targetFunc.content) {\n            this.targetFunc.content.destroyView();\n        }\n\n        switch (message) {\n            case 'save':\n                this.save();\n                break;\n            case 'cancelEdit':\n                this.cancelEdit();\n                break;\n        }\n\n        this._backupContent = null;\n        this._backupOption = null;\n\n        delete this.targetFunc;\n        EntryFunc.isEdit = false;\n\n        const workspace = Entry.getMainWS();\n        const blockMenu = workspace.getBlockMenu();\n\n        blockMenu.deleteRendered('variable');\n\n        const blockSchema = Entry.block[`func_${targetFuncId}`];\n        if (blockSchema && blockSchema.destroyParamsBackupEvent) {\n            blockSchema.destroyParamsBackupEvent.notify();\n        }\n        this.updateMenu();\n    }\n\n    static save() {\n        this.targetFunc.generateBlock(true);\n        Entry.variableContainer.saveFunction(this.targetFunc);\n        this._restoreBoardToVimBoard();\n    }\n\n    static cancelEdit() {\n        if (!this.targetFunc) {\n            return;\n        }\n\n        if (!this.targetFunc.block) {\n            this._targetFuncBlock.destroy();\n            delete Entry.variableContainer.functions_[this.targetFunc.id];\n            delete Entry.variableContainer.selected;\n        } else {\n            if (this._backupContent) {\n                this.targetFunc.content.load(this._backupContent);\n                this.targetFunc.useLocalVariables = this._backupOption.useLocalVariables;\n                this.targetFunc.localVariables = this._backupOption.localVariables;\n                this.changeType(this.targetFunc, this._backupOption.type);\n                this._generateFunctionSchema(this.targetFunc.id);\n                this.generateWsBlock(this.targetFunc);\n            }\n        }\n        Entry.variableContainer.updateList();\n\n        this._restoreBoardToVimBoard();\n    }\n\n    static setupMenuCode() {\n        const workspace = Entry.getMainWS();\n        if (!workspace) {\n            return;\n        }\n        const blockMenu = workspace.getBlockMenu();\n        const menuCode = blockMenu.code;\n        const CATEGORY = 'func';\n        this._fieldLabel = menuCode\n            .createThread([\n                {\n                    type: 'function_field_label',\n                    copyable: false,\n                    category: CATEGORY,\n                    x: -9999,\n                },\n            ])\n            .getFirstBlock();\n\n        this._fieldString = menuCode\n            .createThread([\n                {\n                    type: 'function_field_string',\n                    category: CATEGORY,\n                    x: -9999,\n                    copyable: false,\n                    assemble: false,\n                    params: [{ type: this.requestParamBlock('string') }],\n                },\n            ])\n            .getFirstBlock();\n\n        this._fieldBoolean = menuCode\n            .createThread([\n                {\n                    type: 'function_field_boolean',\n                    copyable: false,\n                    assemble: false,\n                    category: CATEGORY,\n                    x: -9999,\n                    params: [{ type: this.requestParamBlock('boolean') }],\n                },\n            ])\n            .getFirstBlock();\n\n        this.menuCode = menuCode; // TODO Destroy 혹은 cleanProject 같은 로직이 동작했을때 삭제 필요\n        blockMenu.align();\n    }\n\n    static refreshMenuCode() {\n        if (!Entry.playground.mainWorkspace) {\n            return;\n        }\n        if (!this.menuCode) {\n            this.setupMenuCode();\n        }\n\n        this._fieldString.params[0].changeType(this.requestParamBlock('string'));\n        this._fieldBoolean.params[0].changeType(this.requestParamBlock('boolean'));\n    }\n\n    static requestParamBlock(type) {\n        let blockPrototype;\n        switch (type) {\n            case 'string':\n                blockPrototype = Entry.block.function_param_string;\n                break;\n            case 'boolean':\n                blockPrototype = Entry.block.function_param_boolean;\n                break;\n            default:\n                return null;\n        }\n\n        const blockType = `${type}Param_${Entry.generateHash()}`;\n        Entry.block[blockType] = EntryFunc.createParamBlock(blockType, blockPrototype, type);\n        return blockType;\n    }\n\n    static registerParamBlock(type) {\n        if (!type) {\n            return;\n        }\n\n        let blockPrototype;\n        if (type.indexOf('stringParam') > -1) {\n            blockPrototype = Entry.block.function_param_string;\n        } else if (type.indexOf('booleanParam') > -1) {\n            blockPrototype = Entry.block.function_param_boolean;\n        }\n\n        //not a function param block\n        if (!blockPrototype) {\n            return;\n        }\n\n        EntryFunc.createParamBlock(type, blockPrototype, type);\n    }\n\n    static createParamBlock(type, blockPrototype, originalType) {\n        const originalTypeFullName = /string/gi.test(originalType)\n            ? 'function_param_string'\n            : 'function_param_boolean';\n        let BlockSchema = function () {};\n        BlockSchema.prototype = blockPrototype;\n        BlockSchema = new BlockSchema();\n        BlockSchema.changeEvent = new Entry.Event();\n        BlockSchema.template = Lang.template[originalTypeFullName];\n        BlockSchema.fontColor = blockPrototype.fontColor || '#FFF';\n\n        Entry.block[type] = BlockSchema;\n        return BlockSchema;\n    }\n\n    static updateMenu() {\n        const workspace = Entry.getMainWS();\n        if (!workspace) {\n            return;\n        }\n        const blockMenu = workspace.getBlockMenu();\n        if (this.targetFunc) {\n            !this.menuCode && this.setupMenuCode();\n            blockMenu.banClass('functionInit', true);\n            blockMenu.unbanClass('functionEdit', true);\n            if (this.targetFunc && this.targetFunc.useLocalVariables) {\n                blockMenu.unbanClass('useLocalVariables', true);\n            } else {\n                blockMenu.banClass('useLocalVariables', true);\n            }\n            Entry.variableContainer &&\n                Entry.variableContainer.updateFuncSettingView(this.targetFunc);\n        } else {\n            !workspace.isVimMode() && blockMenu.unbanClass('functionInit', true);\n            blockMenu.banClass('functionEdit', true);\n            blockMenu.banClass('useLocalVariables', true);\n        }\n        blockMenu.lastSelector === 'func' && blockMenu.align();\n    }\n\n    static generateBlock(func) {\n        const blockSchema = Entry.block[`func_${func.id}`];\n        const block = {\n            template: blockSchema.template,\n            params: blockSchema.params,\n        };\n\n        const reg = /(%\\d)/im;\n        const templateParams = blockSchema.template.split(reg);\n        let description = '';\n        let booleanIndex = 0;\n        let stringIndex = 0;\n        for (const i in templateParams) {\n            const templateChunk = templateParams[i];\n            if (reg.test(templateChunk)) {\n                const paramIndex = Number(templateChunk.split('%')[1]) - 1;\n                const param = blockSchema.params[paramIndex];\n                if (param.accept === 'boolean') {\n                    description +=\n                        Lang.template.function_param_boolean + (booleanIndex ? booleanIndex : '');\n                    booleanIndex++;\n                } else if (param.type !== 'Indicator') {\n                    description +=\n                        Lang.template.function_param_string + (stringIndex ? stringIndex : '');\n                    stringIndex++;\n                }\n            } else {\n                description += templateChunk;\n            }\n        }\n\n        return { block, description };\n    }\n\n    static generateWsBlock(target, isRestore) {\n        this.unbindFuncChangeEvent();\n        const targetFunc = target ? target : this.targetFunc;\n        const defBlock = targetFunc.content.getEventMap('funcDef')[0];\n\n        if (!defBlock) {\n            return;\n        }\n\n        let outputBlock = defBlock.params[0];\n        let booleanIndex = 0;\n        let stringIndex = 0;\n        const schemaParams = [];\n        let schemaTemplate = '';\n        let functionNmaeTemplate = '';\n        const hashMap = targetFunc.hashMap;\n        const paramMap = targetFunc.paramMap;\n        const blockIds = [];\n\n        while (outputBlock) {\n            const value = outputBlock.params[0];\n            const valueType = value.type;\n            switch (outputBlock.type) {\n                case 'function_field_label':\n                    schemaTemplate = `${schemaTemplate} ${value}`;\n                    functionNmaeTemplate = `${functionNmaeTemplate} ${value}`;\n                    break;\n                case 'function_field_boolean':\n                    Entry.Mutator.mutate(valueType, {\n                        template: `${Lang.Blocks.FUNCTION_logical_variable} ${booleanIndex + 1}`,\n                    });\n                    hashMap[valueType] = false;\n                    paramMap[valueType] = booleanIndex + stringIndex;\n                    booleanIndex++;\n                    schemaParams.push({\n                        type: 'Block',\n                        accept: 'boolean',\n                    });\n                    schemaTemplate += ` %${booleanIndex + stringIndex}`;\n\n                    // eslint-disable-next-line max-len\n                    functionNmaeTemplate += ` <${Lang.Blocks.FUNCTION_logical_variable} ${booleanIndex}>`;\n\n                    blockIds.push(outputBlock.id);\n                    break;\n                case 'function_field_string':\n                    Entry.Mutator.mutate(valueType, {\n                        template: `${Lang.Blocks.FUNCTION_character_variable} ${stringIndex + 1}`,\n                    });\n                    hashMap[valueType] = false;\n                    paramMap[valueType] = booleanIndex + stringIndex;\n                    stringIndex++;\n                    schemaTemplate += ` %${booleanIndex + stringIndex}`;\n\n                    // eslint-disable-next-line max-len\n                    functionNmaeTemplate += ` (${Lang.Blocks.FUNCTION_character_variable} ${stringIndex})`;\n\n                    schemaParams.push({\n                        type: 'Block',\n                        accept: 'string',\n                    });\n                    blockIds.push(outputBlock.id);\n                    break;\n            }\n            outputBlock = outputBlock.getOutputBlock();\n        }\n\n        this.changeFunctionName(functionNmaeTemplate);\n\n        if (targetFunc.type !== 'value') {\n            schemaTemplate += ` %${booleanIndex + stringIndex + 1}`;\n            schemaParams.push({\n                type: 'Indicator',\n                img: 'block_icon/func_icon.svg',\n                size: 12,\n            });\n        }\n\n        const funcName = `func_${targetFunc.id}`;\n        const block = Entry.block[funcName];\n\n        const originParams = block.params.slice(0, block.params.length - 1);\n        const newParams = schemaParams.slice(0, schemaParams.length - 1);\n        const originParamsLength = originParams.length;\n        const newParamsLength = newParams.length;\n\n        let changeData = {};\n\n        if (newParamsLength > originParamsLength) {\n            const outputBlockIds = targetFunc.outputBlockIds;\n            if (outputBlockIds) {\n                let startPos = 0;\n                while (outputBlockIds[startPos] === blockIds[startPos]) {\n                    if (!outputBlockIds[startPos]) {\n                        break;\n                    }\n\n                    startPos++;\n                }\n\n                let endPos = 0;\n                while (\n                    outputBlockIds[outputBlockIds.length - endPos - 1] ===\n                    blockIds[blockIds.length - endPos - 1]\n                ) {\n                    if (!outputBlockIds[outputBlockIds.length - endPos - 1]) {\n                        break;\n                    }\n                    endPos++;\n                }\n\n                endPos = blockIds.length - endPos - 1;\n                changeData = {\n                    type: 'insert',\n                    startPos,\n                    endPos,\n                };\n            }\n        } else if (newParamsLength < originParamsLength) {\n            changeData = {\n                type: 'cut',\n                pos: newParamsLength,\n            };\n        } else {\n            changeData = { type: 'noChange' };\n        }\n\n        changeData.isRestore = isRestore;\n\n        targetFunc.outputBlockIds = blockIds;\n\n        Entry.Mutator.mutate(\n            funcName,\n            {\n                params: schemaParams,\n                template: schemaTemplate,\n            },\n            changeData\n        );\n\n        for (const key in hashMap) {\n            const state = hashMap[key];\n            if (state) {\n                const text = /string/.test(key)\n                    ? Lang.Blocks.FUNCTION_character_variable\n                    : Lang.Blocks.FUNCTION_logical_variable;\n\n                Entry.Mutator.mutate(key, { template: text });\n            } else {\n                hashMap[key] = true;\n            }\n        }\n\n        this.bindFuncChangeEvent(targetFunc);\n    }\n\n    static bindFuncChangeEvent(targetFunc) {\n        const selectedTargetFunc = targetFunc ? targetFunc : this.targetFunc;\n        if (!this._funcChangeEvent && selectedTargetFunc.content.getEventMap('funcDef')[0].view) {\n            this._funcChangeEvent = selectedTargetFunc.content\n                .getEventMap('funcDef')[0]\n                .view._contents[1].changeEvent.attach(this, this.generateWsBlock);\n        }\n    }\n\n    static unbindFuncChangeEvent() {\n        if (!this._funcChangeEvent) {\n            return;\n        }\n        this._funcChangeEvent.destroy();\n        delete this._funcChangeEvent;\n    }\n\n    static unbindWorkspaceStateChangeEvent() {\n        const event = this._workspaceStateEvent;\n        if (!event) {\n            return;\n        }\n\n        event.destroy();\n        delete this._workspaceStateEvent;\n    }\n\n    static reset() {\n        if (this.isEdit) {\n            this.endEdit();\n        }\n        this.menuCode = undefined;\n    }\n\n    static changeType(func, type = 'normal') {\n        func.destroy();\n        func.type = type;\n        delete func.block;\n        delete func.blockMenuBlock;\n        EntryFunc._generateFunctionSchema(func.id, type, true);\n\n        const tempContent = func.content.toJSON();\n\n        if (func && func.content) {\n            const blockMap = func.content._blockMap;\n            for (const key in blockMap) {\n                EntryFunc.registerParamBlock(blockMap[key].type);\n            }\n        }\n\n        const blockType = type === 'normal' ? 'function_create' : 'function_create_value';\n        let block;\n        func.content.getThreads().some((thread, idx) => {\n            const target = thread.getFirstBlock();\n            if (\n                target instanceof Entry.Block &&\n                ['function_create_value', 'function_create'].includes(target?.type)\n            ) {\n                tempContent[idx][0].type = blockType;\n                block = target;\n                return true;\n            }\n        });\n\n        block.changeType(blockType);\n        func.content = new Entry.Code(tempContent);\n\n        const workspace = Entry.getMainWS();\n        workspace.changeOverlayBoardCode(func.content);\n        func.block = block;\n        Entry.variableContainer.updateList();\n        EntryFunc.registerFunction(func);\n        EntryFunc.generateWsBlock(func, true);\n        EntryFunc.updateMenu();\n\n        // reDrawVariableContainer()\n\n        // b = Entry.variableContainer.getFunction(/(func_)?(.*)/.exec('0q91')[2]);\n        // Entry.Func.changeType(b, 'value')\n    }\n\n    static _generateFunctionSchema(functionId, type = 'normal', isUpdate) {\n        const prefixedFunctionId = `func_${functionId}`;\n        if (!isUpdate && Entry.block[prefixedFunctionId]) {\n            return;\n        }\n        let BlockSchema = function () {};\n        BlockSchema.prototype = Entry.block.function_general;\n\n        if (type === 'value') {\n            BlockSchema.prototype = Entry.block.function_value;\n        }\n\n        BlockSchema = new BlockSchema();\n        BlockSchema.changeEvent = new Entry.Event();\n        BlockSchema.template = Lang.template.function_general;\n\n        if (type === 'value') {\n            BlockSchema.template = Lang.template.function_value;\n        }\n\n        Entry.block[prefixedFunctionId] = BlockSchema;\n    }\n\n    /**\n     * 이전 워크스페이스 보드 형태가 VIMBOARD 였던 경우면 VIMBOARD 로 돌린다.\n     * @private\n     */\n    static _restoreBoardToVimBoard() {\n        const ws = Entry.getMainWS();\n        if (ws && ws.overlayModefrom === Entry.Workspace.MODE_VIMBOARD) {\n            ws.setMode({\n                boardType: Entry.Workspace.MODE_VIMBOARD,\n                textType: Entry.Vim.TEXT_TYPE_PY,\n                runType: Entry.Vim.WORKSPACE_MODE,\n            });\n            Entry.variableContainer.functionAddButton_.addClass('disable');\n        }\n    }\n\n    takeSnapshot() {\n        this.snapshot_ = {\n            localVariables: _cloneDeep(this.localVariables),\n        };\n    }\n\n    loadSnapshot() {\n        if (!this.snapshot_) {\n            return;\n        }\n        const { localVariables } = this.snapshot_;\n        this.localVariables = localVariables;\n        delete this.snapshot_;\n    }\n}\n\nEntry.Func = EntryFunc;\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/event-dispatcher.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { EventEmitter } from 'events';\n\n/**\n * @hidden\n */\nexport interface TypedDispatcher<T> {\n    addEventListener<K extends keyof T>(\n        type: K,\n        listener: (event: CustomEvent<T[K]>) => void\n    ): void;\n    removeEventListener<K extends keyof T>(\n        type: K,\n        callback: (event: CustomEvent<T[K]>) => void\n    ): void;\n    dispatchEvent(event: CustomEvent<T>): boolean;\n    dispatchEvent<K extends keyof T>(type: K, detail: T[K]): boolean;\n    addListener<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\n    on<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\n    once<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\n    prependListener<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\n    prependOnceListener<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\n    removeListener<K extends keyof T>(event: K, listener: (data: T[K]) => void): this;\n    removeAllListeners<K extends keyof T>(event?: K): this;\n    // tslint:disable-next-line:ban-types\n    listeners<K extends keyof T>(event: K): Function[];\n    emit<K extends keyof T>(event: K, data: T[K]): boolean;\n    // tslint:disable-next-line:array-type\n    eventNames<K extends keyof T>(): Array<K>;\n    listenerCount<K extends keyof T>(type: K): number;\n    setMaxListeners(n: number): this;\n    getMaxListeners(): number;\n}\n\n/**\n * @hidden\n */\nexport class EventDispatcher extends EventEmitter implements EventTarget {\n    private isEventListenerObject = (\n        listener: EventListenerOrEventListenerObject\n    ): listener is EventListenerObject =>\n        (listener as EventListenerObject).handleEvent !== undefined;\n\n    public addEventListener(type: string, listener: EventListenerOrEventListenerObject | null) {\n        if (listener) {\n            const handler = this.isEventListenerObject(listener) ? listener.handleEvent : listener;\n            super.addListener(type, handler);\n        }\n    }\n\n    public removeEventListener(type: string, callback: EventListenerOrEventListenerObject | null) {\n        if (callback) {\n            const handler = this.isEventListenerObject(callback) ? callback.handleEvent : callback;\n            super.removeListener(type, handler);\n        }\n    }\n\n    public dispatchEvent(event: Event): boolean;\n    public dispatchEvent<T>(type: string, detail: T): boolean;\n    public dispatchEvent<T>(eventOrType: Event | string, detail?: T): boolean {\n        let event: Event;\n        if (typeof eventOrType === 'string') {\n            event = new CustomEvent(eventOrType, {\n                detail,\n            });\n        } else {\n            event = eventOrType;\n        }\n\n        return super.emit(event.type, event);\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/index.ts",
    "content": "// 사용하는 서비스 정리\n\nimport { AccelerometerService } from './services/accelerometer';\nimport { ButtonService } from './services/button';\nimport { DeviceInformationService } from './services/device-information';\nimport { DfuControlService } from './services/dfu-control';\nimport { EventService } from './services/event';\nimport { IoPinService } from './services/io-pin';\nimport { LedService } from './services/led';\nimport { MagnetometerService } from './services/magnetometer';\nimport { TemperatureService } from './services/temperature';\nimport { UartService } from './services/uart';\n\nexport const getServiceClassesByModuleId = (moduleId: string) => {\n    switch (moduleId) {\n        case '220302':\n            {\n                // INFO : entryjs minify 과정에서 function.name 값이 uglify되는 이슈 대응\n                return [\n                    DeviceInformationService,\n                    ButtonService,\n                    LedService,\n                    TemperatureService,\n                    AccelerometerService,\n                    MagnetometerService,\n                    UartService,\n                    EventService,\n                    DfuControlService,\n                    IoPinService,\n                ];\n            }\n            break;\n    }\n};\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/promise-queue.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/**\n * @hidden\n */\ninterface QueuedPromise {\n    fn: () => Promise<any>;\n    resolve: (value?: any | PromiseLike<any> | undefined) => void;\n    reject: (reason?: any) => void;\n}\n\n/**\n * @hidden\n */\nexport class PromiseQueue {\n    private queue: QueuedPromise[] = [];\n    private running = 0;\n\n    constructor(private concurrent = 1) {}\n\n    private async pump(): Promise<void> {\n        if (this.running >= this.concurrent) {\n            return;\n        }\n\n        const promise = this.queue.shift();\n\n        if (!promise) {\n            return;\n        }\n\n        this.running++;\n\n        try {\n            const result = await promise.fn();\n            promise.resolve(result);\n        } catch (error) {\n            promise.reject(error);\n        }\n\n        this.running--;\n        return this.pump();\n    }\n\n    public add<T>(fn: () => Promise<T>): Promise<T> {\n        return new Promise((resolve, reject) => {\n            this.queue.push({\n                fn,\n                resolve,\n                reject,\n            });\n\n            return this.pump();\n        });\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/service-helper.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { EventEmitter } from 'events';\nimport { PromiseQueue } from './promise-queue';\n\n/**\n * @hidden\n */\nexport interface ServiceEventHandler {\n    characteristic: BluetoothCharacteristicUUID;\n    handler: (event: Event) => void;\n}\n\n/**\n * @hidden\n */\nexport class ServiceHelper {\n    private static queue = new PromiseQueue();\n\n    private characteristics?: BluetoothRemoteGATTCharacteristic[];\n\n    constructor(private service: BluetoothRemoteGATTService, private emitter?: EventEmitter) {}\n\n    private async getCharacteristic(\n        uuid: BluetoothCharacteristicUUID\n    ): Promise<BluetoothRemoteGATTCharacteristic | undefined> {\n        if (!this.characteristics) {\n            this.characteristics = await this.service.getCharacteristics();\n        }\n\n        return this.characteristics.find((characteristic) => characteristic.uuid === uuid);\n    }\n\n    public async getCharacteristicValue(uuid: BluetoothCharacteristicUUID): Promise<DataView> {\n        const characteristic = await this.getCharacteristic(uuid);\n\n        if (!characteristic) {\n            throw new Error('Unable to locate characteristic');\n        }\n\n        return await ServiceHelper.queue.add(async () => characteristic.readValue());\n    }\n\n    public async setCharacteristicValue(\n        uuid: BluetoothCharacteristicUUID,\n        value: BufferSource\n    ): Promise<void> {\n        const characteristic = await this.getCharacteristic(uuid);\n\n        if (!characteristic) {\n            throw new Error('Unable to locate characteristic');\n        }\n\n        await ServiceHelper.queue.add(async () => characteristic.writeValue(value));\n    }\n\n    public async handleListener(\n        event: string,\n        uuid: BluetoothCharacteristicUUID,\n        handler: (event: Event) => void\n    ) {\n        const characteristic = await this.getCharacteristic(uuid);\n\n        if (!characteristic) {\n            return;\n        }\n\n        await ServiceHelper.queue.add(async () => characteristic.startNotifications());\n\n        this.emitter!.on('newListener', (emitterEvent: string) => {\n            if (emitterEvent !== event || this.emitter!.listenerCount(event) > 0) {\n                return;\n            }\n\n            return ServiceHelper.queue.add(async () =>\n                characteristic.addEventListener('characteristicvaluechanged', handler)\n            );\n        });\n\n        this.emitter!.on('removeListener', (emitterEvent: string) => {\n            if (emitterEvent !== event || this.emitter!.listenerCount(event) > 0) {\n                return;\n            }\n\n            return ServiceHelper.queue.add(async () =>\n                characteristic.removeEventListener('characteristicvaluechanged', handler)\n            );\n        });\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/accelerometer.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { EventDispatcher, TypedDispatcher } from '../event-dispatcher';\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum AccelerometerCharacteristic {\n    accelerometerData = 'e95dca4b-251d-470a-a062-fa1922dfa9a8',\n    accelerometerPeriod = 'e95dfb24-251d-470a-a062-fa1922dfa9a8',\n}\n\n/**\n * Data received from the accelerometer\n */\nexport interface AccelerometerData {\n    /**\n     * Force in direction X\n     */\n    x: number;\n    /**\n     * Force in direction Y\n     */\n    y: number;\n    /**\n     * Force in direction Z\n     */\n    z: number;\n}\n\n/**\n * The sample period to read accelerometer data (milliseconds)\n */\nexport type AccelerometerPeriod = 1 | 2 | 5 | 10 | 20 | 80 | 160 | 640;\n\n/**\n * Events raised by the accelerometer service\n */\nexport interface AccelerometerEvents {\n    /**\n     * @hidden\n     */\n    newListener: keyof AccelerometerEvents;\n    /**\n     * @hidden\n     */\n    removeListener: keyof AccelerometerEvents;\n    /**\n     * Accelerometer data changed event\n     */\n    accelerometerdatachanged: AccelerometerData;\n}\n\n/**\n * Accelerometer Service\n */\nexport class AccelerometerService extends (EventDispatcher as new () => TypedDispatcher<\n    AccelerometerEvents\n>) {\n    public static serviceName = 'AccelerometerService';\n    /**\n     * @hidden\n     */\n    public static uuid = 'e95d0753-251d-470a-a062-fa1922dfa9a8';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<AccelerometerService> {\n        const bluetoothService = new AccelerometerService(service);\n        await bluetoothService.init();\n        return bluetoothService;\n    }\n\n    private helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        super();\n        //@ts-ignore\n        this.helper = new ServiceHelper(service, this);\n    }\n\n    private async init() {\n        await this.helper.handleListener(\n            'accelerometerdatachanged',\n            AccelerometerCharacteristic.accelerometerData,\n            this.accelerometerDataChangedHandler.bind(this)\n        );\n    }\n\n    /**\n     * Read acceleromter data\n     */\n    public async readAccelerometerData(): Promise<AccelerometerData> {\n        const view = await this.helper.getCharacteristicValue(\n            AccelerometerCharacteristic.accelerometerData\n        );\n        return this.dataViewToAccelerometerData(view);\n    }\n\n    /**\n     * Get accelerometer sample period\n     */\n    public async getAccelerometerPeriod(): Promise<AccelerometerPeriod> {\n        const view = await this.helper.getCharacteristicValue(\n            AccelerometerCharacteristic.accelerometerPeriod\n        );\n        return view.getUint16(0, true) as AccelerometerPeriod;\n    }\n\n    /**\n     * Set accelerometer sample period\n     * @param frequency The frequency interval to use\n     */\n    public async setAccelerometerPeriod(frequency: AccelerometerPeriod): Promise<void> {\n        const view = new DataView(new ArrayBuffer(2));\n        view.setUint16(0, frequency, true);\n        return this.helper.setCharacteristicValue(\n            AccelerometerCharacteristic.accelerometerPeriod,\n            view\n        );\n    }\n\n    private accelerometerDataChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        const value = this.dataViewToAccelerometerData(view);\n        this.dispatchEvent('accelerometerdatachanged', value);\n    }\n\n    private dataViewToAccelerometerData(view: DataView): AccelerometerData {\n        return {\n            x: view.getInt16(0, true) / 1000.0,\n            y: view.getInt16(2, true) / 1000.0,\n            z: view.getInt16(4, true) / 1000.0,\n        };\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/button.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { EventDispatcher, TypedDispatcher } from '../event-dispatcher';\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum ButtonCharacteristic {\n    buttonAState = 'e95dda90-251d-470a-a062-fa1922dfa9a8',\n    buttonBState = 'e95dda91-251d-470a-a062-fa1922dfa9a8',\n}\n\n/**\n * Button state enum\n */\nexport enum ButtonState {\n    /**\n     * Button released\n     */\n    Release = 0,\n    /**\n     * Button pressed - short\n     */\n    ShortPress = 1,\n    /**\n     * Button pressed - long\n     */\n    LongPress = 2,\n}\n\n/**\n * Events raised by the button service\n */\nexport interface ButtonEvents {\n    /**\n     * @hidden\n     */\n    newListener: keyof ButtonEvents;\n    /**\n     * @hidden\n     */\n    removeListener: keyof ButtonEvents;\n    /**\n     * Button A state changed event\n     */\n    buttonastatechanged: ButtonState;\n    /**\n     * Button B state changed event\n     */\n    buttonbstatechanged: ButtonState;\n}\n\n/**\n * Button Service\n */\nexport class ButtonService extends (EventDispatcher as new () => TypedDispatcher<ButtonEvents>) {\n    public static serviceName = 'ButtonService';\n    /**\n     * @hidden\n     */\n    public static uuid = 'e95d9882-251d-470a-a062-fa1922dfa9a8';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<ButtonService> {\n        const bluetoothService = new ButtonService(service);\n        await bluetoothService.init();\n        return bluetoothService;\n    }\n\n    private helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        super();\n        //@ts-ignore\n        this.helper = new ServiceHelper(service, this);\n    }\n\n    private async init() {\n        await this.helper.handleListener(\n            'buttonastatechanged',\n            ButtonCharacteristic.buttonAState,\n            this.buttonAStateChangedHandler.bind(this)\n        );\n        await this.helper.handleListener(\n            'buttonbstatechanged',\n            ButtonCharacteristic.buttonBState,\n            this.buttonBStateChangedHandler.bind(this)\n        );\n    }\n\n    /**\n     * Read state of button A\n     */\n    public async readButtonAState(): Promise<ButtonState> {\n        const view = await this.helper.getCharacteristicValue(ButtonCharacteristic.buttonAState);\n        return view.getUint8(0);\n    }\n\n    /**\n     * Read state of button B\n     */\n    public async readButtonBState(): Promise<ButtonState> {\n        const view = await this.helper.getCharacteristicValue(ButtonCharacteristic.buttonBState);\n        return view.getUint8(0);\n    }\n\n    private buttonAStateChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        this.dispatchEvent('buttonastatechanged', view.getUint8(0));\n    }\n\n    private buttonBStateChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        this.dispatchEvent('buttonbstatechanged', view.getUint8(0));\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/device-information.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum DeviceInformationCharacteristic {\n    modelNumber = '00002a24-0000-1000-8000-00805f9b34fb',\n    serialNumber = '00002a25-0000-1000-8000-00805f9b34fb',\n    firmwareRevision = '00002a26-0000-1000-8000-00805f9b34fb',\n    hardwareRevision = '00002a27-0000-1000-8000-00805f9b34fb',\n    manufacturer = '00002a29-0000-1000-8000-00805f9b34fb',\n}\n\n/**\n * Device information structure\n */\nexport interface DeviceInformation {\n    /**\n     * Model Number\n     */\n    modelNumber?: string;\n    /**\n     * Serial Number\n     */\n    serialNumber?: string;\n    /**\n     * Firmware Revision\n     */\n    firmwareRevision?: string;\n    /**\n     * Hardware Revision\n     */\n    hardwareRevision?: string;\n    /**\n     * Manufacturer Name\n     */\n    manufacturer?: string;\n}\n\n/**\n * Device Information Service\n */\nexport class DeviceInformationService {\n    public static serviceName = 'DeviceInformationService';\n    /**\n     * @hidden\n     */\n    public static uuid = '0000180a-0000-1000-8000-00805f9b34fb';\n\n    /**\n     * @hidden\n     */\n    public static async create(\n        service: BluetoothRemoteGATTService\n    ): Promise<DeviceInformationService> {\n        return new DeviceInformationService(service);\n    }\n\n    private helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        this.helper = new ServiceHelper(service);\n    }\n\n    /**\n     * Read device information\n     */\n    public async readDeviceInformation(): Promise<DeviceInformation> {\n        const info: DeviceInformation = {};\n\n        const modelNumber = await this.readStringCharacteristic(\n            DeviceInformationCharacteristic.modelNumber\n        );\n        if (modelNumber) info.modelNumber = modelNumber;\n\n        const serialNumber = await this.readStringCharacteristic(\n            DeviceInformationCharacteristic.serialNumber\n        );\n        if (serialNumber) info.serialNumber = serialNumber;\n\n        const firmwareRevision = await this.readStringCharacteristic(\n            DeviceInformationCharacteristic.firmwareRevision\n        );\n        if (firmwareRevision) info.firmwareRevision = firmwareRevision;\n\n        const hardwareRevision = await this.readStringCharacteristic(\n            DeviceInformationCharacteristic.hardwareRevision\n        );\n        if (hardwareRevision) info.hardwareRevision = hardwareRevision;\n\n        const manufacturer = await this.readStringCharacteristic(\n            DeviceInformationCharacteristic.manufacturer\n        );\n        if (manufacturer) info.manufacturer = manufacturer;\n\n        return info;\n    }\n\n    private async readStringCharacteristic(\n        uuid: BluetoothCharacteristicUUID\n    ): Promise<string | undefined> {\n        try {\n            const view = await this.helper.getCharacteristicValue(uuid);\n            const buffer = view.buffer.slice(view.byteOffset, view.byteOffset + view.byteLength);\n            return String.fromCharCode.apply(null, Array.from(new Uint8Array(buffer)));\n        } catch (_e) {\n            return undefined;\n        }\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/dfu-control.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum DfuCharacteristic {\n    dfuControl = 'e95d93b1-251d-470a-a062-fa1922dfa9a8',\n}\n\n/**\n * @hidden\n */\nexport class DfuControlService {\n    public static serviceName = 'DfuControlService';\n    /**\n     * @hidden\n     */\n    public static uuid = 'e95d93b0-251d-470a-a062-fa1922dfa9a8';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<DfuControlService> {\n        return new DfuControlService(service);\n    }\n\n    /**\n     * @hidden\n     */\n    public helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        this.helper = new ServiceHelper(service);\n    }\n\n    /**\n     * Request device switches to DFU mode\n     */\n    public requestDfu(): Promise<void> {\n        return this.helper.setCharacteristicValue(\n            DfuCharacteristic.dfuControl,\n            new Uint8Array([1])\n        );\n    }\n\n    /**\n     * Request flash code\n     */\n    public requestFlashCode(): Promise<void> {\n        return this.helper.setCharacteristicValue(\n            DfuCharacteristic.dfuControl,\n            new Uint8Array([2])\n        );\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/event.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { EventDispatcher, TypedDispatcher } from '../event-dispatcher';\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum EventCharacteristic {\n    microBitRequirements = 'e95db84c-251d-470a-a062-fa1922dfa9a8',\n    microBitEvent = 'e95d9775-251d-470a-a062-fa1922dfa9a8',\n    clientRequirements = 'e95d23c4-251d-470a-a062-fa1922dfa9a8',\n    clientEvent = 'e95d5404-251d-470a-a062-fa1922dfa9a8',\n}\n\n/**\n * micro:bit event\n */\nexport interface MicrobitEvent {\n    /**\n     * The type of event\n     */\n    type: number;\n    /**\n     * The value for the event\n     */\n    value: number;\n}\n\n/**\n * Events raised by the event service\n */\nexport interface MicrobitEvents {\n    /**\n     * @hidden\n     */\n    newListener: keyof MicrobitEvents;\n    /**\n     * @hidden\n     */\n    removeListener: keyof MicrobitEvents;\n    /**\n     * micro:bit requirements changed event\n     */\n    microbitrequirementschanged: MicrobitEvent;\n    /**\n     * micro:bit event event\n     */\n    microbitevent: MicrobitEvent;\n}\n\n/**\n * Event Service\n */\nexport class EventService extends (EventDispatcher as new () => TypedDispatcher<MicrobitEvents>) {\n    public static serviceName = 'EventService';\n    /**\n     * @hidden\n     */\n    public static uuid = 'e95d93af-251d-470a-a062-fa1922dfa9a8';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<EventService> {\n        const bluetoothService = new EventService(service);\n        await bluetoothService.init();\n        return bluetoothService;\n    }\n\n    private helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        super();\n        //@ts-ignore\n        this.helper = new ServiceHelper(service, this);\n    }\n\n    private async init() {\n        await this.helper.handleListener(\n            'microbitevent',\n            EventCharacteristic.microBitEvent,\n            this.eventHandler.bind(this)\n        );\n        await this.helper.handleListener(\n            'microbitrequirementschanged',\n            EventCharacteristic.microBitRequirements,\n            this.microbitRequirementsChangedHandler.bind(this)\n        );\n    }\n\n    /**\n     * Get micro:bit event requirements\n     */\n    public async getMicrobitRequirements(): Promise<MicrobitEvent> {\n        const view = await this.helper.getCharacteristicValue(\n            EventCharacteristic.microBitRequirements\n        );\n        return this.viewToMicrobitEvent(view);\n    }\n\n    /**\n     * Set client event requirements\n     * @param type The type of event to set\n     * @param value The value to set\n     */\n    public async setClientRequirements(type: number, value: number): Promise<void> {\n        const view = new DataView(new ArrayBuffer(4));\n        view.setUint16(0, type, true);\n        view.setUint16(1, value, true);\n        return await this.helper.setCharacteristicValue(\n            EventCharacteristic.clientRequirements,\n            view\n        );\n    }\n\n    /**\n     * Read micro:bit event\n     */\n    public async readMicrobitEvent(): Promise<MicrobitEvent> {\n        const view = await this.helper.getCharacteristicValue(EventCharacteristic.microBitEvent);\n        return this.viewToMicrobitEvent(view);\n    }\n\n    /**\n     * Write client event\n     * @param type The event type\n     * @param value The event value\n     */\n    public async writeClientEvent(type: number, value: number): Promise<void> {\n        const view = new DataView(new ArrayBuffer(4));\n        view.setUint16(0, type, true);\n        view.setUint16(1, value, true);\n        return await this.helper.setCharacteristicValue(EventCharacteristic.clientEvent, view);\n    }\n\n    private microbitRequirementsChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        const microbitEvent = this.viewToMicrobitEvent(view);\n        this.dispatchEvent('microbitrequirementschanged', microbitEvent);\n    }\n\n    private eventHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        const microbitEvent = this.viewToMicrobitEvent(view);\n        this.dispatchEvent('microbitevent', microbitEvent);\n    }\n\n    private viewToMicrobitEvent(view: DataView): MicrobitEvent {\n        const type = view.getUint16(0, true);\n        const value = view.getUint16(1, true);\n        return {\n            type,\n            value,\n        };\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/io-pin.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { ServiceHelper } from '../service-helper';\nimport { EventDispatcher, TypedDispatcher } from '../event-dispatcher';\n\n/**\n * @hidden\n */\nexport enum IoPinCharacteristic {\n    pinData = 'e95d8d00-251d-470a-a062-fa1922dfa9a8',\n    pinAdConfiguration = 'e95d5899-251d-470a-a062-fa1922dfa9a8',\n    pinIoConfiguration = 'e95db9fe-251d-470a-a062-fa1922dfa9a8',\n    pwmControl = 'e95dd822-251d-470a-a062-fa1922dfa9a8',\n}\n\nconst littleEndian = true;\n\n/**\n * Pin data\n */\nexport interface PinData {\n    /**\n     * Pin number\n     */\n    pin: number;\n    /**\n     * Pin value\n     */\n    value: number;\n}\n\n/**\n * PWM control data\n */\nexport interface PwmControlData {\n    /**\n     * Pin number\n     */\n    pin: number;\n    /**\n     * Pin value\n     */\n    value: number;\n    /**\n     * Period (in microseconds)\n     */\n    period: number;\n}\n\n/**\n * Analogue/Digital Enum\n */\nexport enum AD {\n    Digital = 0,\n    Analogue = 1,\n}\n\n/**\n * Input/Output Enum\n */\nexport enum IO {\n    Output = 0,\n    Input = 1,\n}\n\n/**\n * Events raised by the magnetometer service\n */\nexport interface IoPinEvents {\n    /**\n     * @hidden\n     */\n    newListener: keyof IoPinEvents;\n    /**\n     * @hidden\n     */\n    removeListener: keyof IoPinEvents;\n    /**\n     * Pin data changed event\n     */\n    pindatachanged: PinData[];\n}\n\n/**\n * @hidden\n */\nexport class IoPinService extends (EventDispatcher as new () => TypedDispatcher<IoPinEvents>) {\n    public static serviceName = 'IoPinService';\n    /**\n     * @hidden\n     */\n    public static uuid = 'e95d127b-251d-470a-a062-fa1922dfa9a8';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<IoPinService> {\n        const bluetoothService = new IoPinService(service);\n        await bluetoothService.init();\n        return bluetoothService;\n    }\n\n    /**\n     * @hidden\n     */\n    public helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        super();\n        //@ts-ignore\n        this.helper = new ServiceHelper(service, this);\n    }\n\n    private async init() {\n        await this.helper.handleListener(\n            'pindatachanged',\n            IoPinCharacteristic.pinData,\n            this.pinDataChangedHandler.bind(this)\n        );\n    }\n\n    /**\n     * Read pin data\n     */\n    public async readPinData(): Promise<PinData[]> {\n        const view = await this.helper.getCharacteristicValue(IoPinCharacteristic.pinData);\n        return this.dataViewToPinData(view);\n    }\n\n    /**\n     * Write pin data\n     * @param data The pin data to write\n     */\n    public async writePinData(data: PinData[]): Promise<void> {\n        const view = this.pinDataToDataView(data);\n        return this.helper.setCharacteristicValue(IoPinCharacteristic.pinData, view);\n    }\n\n    /**\n     * Get pin analogue/digital configuration\n     */\n    public async getAdConfiguration(): Promise<AD[]> {\n        const view = await this.helper.getCharacteristicValue(\n            IoPinCharacteristic.pinAdConfiguration\n        );\n        return this.dataViewToConfig(view);\n    }\n\n    /**\n     * Set pin analogue/digital configuration\n     * @param config The analogue/digital configuration to set\n     */\n    public async setAdConfiguration(config: AD[]): Promise<void> {\n        const view = this.configToDataView(config);\n        return this.helper.setCharacteristicValue(IoPinCharacteristic.pinAdConfiguration, view);\n    }\n\n    /**\n     * Get pin input/output configuration\n     */\n    public async getIoConfiguration(): Promise<IO[]> {\n        const view = await this.helper.getCharacteristicValue(\n            IoPinCharacteristic.pinIoConfiguration\n        );\n        return this.dataViewToConfig(view);\n    }\n\n    /**\n     * Set pin input/output configuration\n     * @param config The input/output configuration to set\n     */\n    public async setIoConfiguration(config: IO[]): Promise<void> {\n        const view = this.configToDataView(config);\n        return this.helper.setCharacteristicValue(IoPinCharacteristic.pinIoConfiguration, view);\n    }\n\n    /**\n     * Set pin PWM control\n     * @param data The PWM control data to set\n     */\n    public async setPwmControl(data: PwmControlData): Promise<void> {\n        const view = this.pwmControlDataToDataView(data);\n        return this.helper.setCharacteristicValue(IoPinCharacteristic.pwmControl, view);\n    }\n\n    private pinDataChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        const value = this.dataViewToPinData(view);\n        this.dispatchEvent('pindatachanged', value);\n    }\n\n    private dataViewToPinData(view: DataView): PinData[] {\n        const data = [];\n        for (let i = 0; i < view.byteLength; i += 2) {\n            data.push({\n                pin: view.getUint8(i),\n                value: view.getUint8(i + 1),\n            });\n        }\n        return data;\n    }\n\n    private pinDataToDataView(data: PinData[]): DataView {\n        const view = new DataView(new ArrayBuffer(data.length * 2));\n        data.forEach((pinData, index) => {\n            view.setUint8(index * 2, pinData.pin);\n            view.setUint8(index * 2 + 1, pinData.value);\n        });\n        return view;\n    }\n\n    private dataViewToConfig(view: DataView): number[] {\n        const result: number[] = [];\n        const value = (view.getUint16(0) << 8) + view.getUint8(2);\n\n        for (let i = 0; i < 24; i++) {\n            result.push(value >> i);\n        }\n\n        return result;\n    }\n\n    private configToDataView(config: number[]): DataView {\n        const view = new DataView(new ArrayBuffer(3));\n        let value = 0;\n\n        // tslint:disable-next-line:prefer-for-of\n        for (let i = 0; i < config.length; i++) {\n            value &= 1 << config[i];\n        }\n\n        view.setUint16(0, value >> 8, littleEndian);\n        view.setUint8(2, value & 0xff);\n        return view;\n    }\n\n    private pwmControlDataToDataView(data: PwmControlData): DataView {\n        const view = new DataView(new ArrayBuffer(7));\n        view.setUint8(0, data.pin);\n        view.setUint16(1, data.value, littleEndian);\n        view.setUint32(3, data.period, littleEndian);\n        return view;\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/led.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum LedCharacteristic {\n    ledMatrixState = 'e95d7b77-251d-470a-a062-fa1922dfa9a8',\n    ledText = 'e95d93ee-251d-470a-a062-fa1922dfa9a8',\n    scrollingDelay = 'e95d0d2d-251d-470a-a062-fa1922dfa9a8',\n}\n\n/**\n * LED matrix structure\n */\nexport type LedMatrix = [\n    [boolean, boolean, boolean, boolean, boolean],\n    [boolean, boolean, boolean, boolean, boolean],\n    [boolean, boolean, boolean, boolean, boolean],\n    [boolean, boolean, boolean, boolean, boolean],\n    [boolean, boolean, boolean, boolean, boolean]\n];\n\n/**\n * LED Service\n */\nexport class LedService {\n    public static serviceName = 'LedService';\n    /**\n     * @hidden\n     */\n    public static uuid = 'e95dd91d-251d-470a-a062-fa1922dfa9a8';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<LedService> {\n        return new LedService(service);\n    }\n\n    private helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        this.helper = new ServiceHelper(service);\n    }\n\n    /**\n     * Write text to the LED matrix\n     * @param text Te text to display\n     */\n    public async writeText(text: string): Promise<void> {\n        const encoded = this.encodeString(text);\n        return this.helper.setCharacteristicValue(LedCharacteristic.ledText, encoded);\n    }\n\n    /**\n     * Read matrix state\n     */\n    public async readMatrixState(): Promise<LedMatrix> {\n        const view = await this.helper.getCharacteristicValue(LedCharacteristic.ledMatrixState);\n        return this.viewToLedMatrix(view);\n    }\n\n    /**\n     * Write matrix state\n     * @param state The matrix data to set\n     */\n    public async writeMatrixState(state: LedMatrix): Promise<void> {\n        const view = this.ledMatrixToView(state);\n        return this.helper.setCharacteristicValue(LedCharacteristic.ledMatrixState, view);\n    }\n\n    /**\n     * Get scrolling delay\n     */\n    public async getScrollingDelay(): Promise<number> {\n        const view = await this.helper.getCharacteristicValue(LedCharacteristic.scrollingDelay);\n        return view.getUint16(0, true);\n    }\n\n    /**\n     * Set scrolling delay\n     * @param delay The delay to set (milliseconds)\n     */\n    public async setScrollingDelay(delay: number): Promise<void> {\n        const view = new DataView(new ArrayBuffer(2));\n        view.setUint16(0, delay, true);\n        return this.helper.setCharacteristicValue(LedCharacteristic.scrollingDelay, view);\n    }\n\n    private encodeString(text: string): ArrayBuffer {\n        const buffer = new ArrayBuffer(text.length);\n        const view = new Uint8Array(buffer);\n        for (let i = 0; i < text.length; i++) {\n            view[i] = text.charCodeAt(i);\n        }\n        return buffer;\n    }\n\n    private viewToLedMatrix(view: DataView): LedMatrix {\n        const matrix: boolean[][] = [];\n        for (let i = 0; i < 5; i++) {\n            matrix[i] = this.byteToBoolArray(view.getUint8(i));\n        }\n        return matrix as LedMatrix;\n    }\n\n    private byteToBoolArray(byte: number): boolean[] {\n        const bools = [false, false, false, false, false];\n        for (let i = 0; i < bools.length; i++) {\n            bools[i] = (byte & 1) === 1;\n            byte >>= 1;\n        }\n        return bools.reverse();\n    }\n\n    private ledMatrixToView(matrix: LedMatrix): DataView {\n        const view = new DataView(new ArrayBuffer(5));\n        for (let i = 0; i < 5; i++) {\n            view.setUint8(i, this.boolArrayToByte(matrix[i]));\n        }\n        return view;\n    }\n\n    private boolArrayToByte(bools: boolean[]): number {\n        return bools.reduce((byte, bool) => (byte << 1) | (bool ? 1 : 0), 0);\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/magnetometer.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { EventDispatcher, TypedDispatcher } from '../event-dispatcher';\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum MagnetometerCharacteristic {\n    magnetometerData = 'e95dfb11-251d-470a-a062-fa1922dfa9a8',\n    magnetometerPeriod = 'e95d386c-251d-470a-a062-fa1922dfa9a8',\n    magnetometerBearing = 'e95d9715-251d-470a-a062-fa1922dfa9a8',\n    magnetometerCalibration = 'e95db358-251d-470a-a062-fa1922dfa9a8',\n}\n\n/**\n * Data received from the magnetometer\n */\nexport interface MagnetometerData {\n    /**\n     * Force in direction X\n     */\n    x: number;\n    /**\n     * Force in direction Y\n     */\n    y: number;\n    /**\n     * Force in direction Z\n     */\n    z: number;\n}\n\n/**\n * Magnetometer calibation state\n */\nexport enum MagnetometerCalibration {\n    /**\n     * Unknown state\n     */\n    unknown = 0,\n    /**\n     * Calibration has been requestes\n     */\n    requested = 1,\n    /**\n     * Calibration completed\n     */\n    completed = 2,\n    /**\n     * Calibration had an error\n     */\n    errored = 3,\n}\n\n/**\n * The sample period to read magnetometer data (milliseconds)\n */\nexport type MagnetometerPeriod = 1 | 2 | 5 | 10 | 20 | 80 | 160 | 640;\n\n/**\n * Events raised by the magnetometer service\n */\nexport interface MagnetometerEvents {\n    /**\n     * @hidden\n     */\n    newListener: keyof MagnetometerEvents;\n    /**\n     * @hidden\n     */\n    removeListener: keyof MagnetometerEvents;\n    /**\n     * Magnetometer data changed event\n     */\n    magnetometerdatachanged: MagnetometerData;\n    /**\n     * Magnetometer bearing changed event\n     */\n    magnetometerbearingchanged: number;\n    /**\n     * Magnetometer calibration changed event\n     */\n    magnetometercalibrationchanged: MagnetometerCalibration;\n}\n\n/**\n * Magnetometer Service\n */\nexport class MagnetometerService extends (EventDispatcher as new () => TypedDispatcher<\n    MagnetometerEvents\n>) {\n    public static serviceName = 'MagnetometerService';\n    /**\n     * @hidden\n     */\n    public static uuid = 'e95df2d8-251d-470a-a062-fa1922dfa9a8';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<MagnetometerService> {\n        const bluetoothService = new MagnetometerService(service);\n        await bluetoothService.init();\n        return bluetoothService;\n    }\n\n    private helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        super();\n        //@ts-ignore\n        this.helper = new ServiceHelper(service, this);\n    }\n\n    private async init() {\n        await this.helper.handleListener(\n            'magnetometerdatachanged',\n            MagnetometerCharacteristic.magnetometerData,\n            this.magnetometerDataChangedHandler.bind(this)\n        );\n        await this.helper.handleListener(\n            'magnetometerbearingchanged',\n            MagnetometerCharacteristic.magnetometerBearing,\n            this.magnetometerBearingChangedHandler.bind(this)\n        );\n        await this.helper.handleListener(\n            'magnetometercalibrationchanged',\n            MagnetometerCharacteristic.magnetometerCalibration,\n            this.magnetometerCalibrationChangedHandler.bind(this)\n        );\n    }\n\n    /**\n     * Request magnetometer calibration\n     */\n    public async calibrate() {\n        return this.helper.setCharacteristicValue(\n            MagnetometerCharacteristic.magnetometerCalibration,\n            new Uint8Array([1])\n        );\n    }\n\n    /**\n     * Read magnetometer data\n     */\n    public async readMagnetometerData(): Promise<MagnetometerData> {\n        const view = await this.helper.getCharacteristicValue(\n            MagnetometerCharacteristic.magnetometerData\n        );\n        return this.dataViewToMagnetometerData(view);\n    }\n\n    /**\n     * Read magnetometer bearing\n     */\n    public async readMagnetometerBearing(): Promise<number | undefined> {\n        const view = await this.helper.getCharacteristicValue(\n            MagnetometerCharacteristic.magnetometerBearing\n        );\n        if (view.byteLength === 2) {\n            return view.getUint16(0, true);\n        }\n        return undefined;\n    }\n\n    /**\n     * Get magnetometer sample period\n     */\n    public async getMagnetometerPeriod(): Promise<MagnetometerPeriod> {\n        const view = await this.helper.getCharacteristicValue(\n            MagnetometerCharacteristic.magnetometerPeriod\n        );\n        return view.getUint16(0, true) as MagnetometerPeriod;\n    }\n\n    /**\n     * Set magnetometer sample period\n     * @param frequency The frequency interval to use\n     */\n    public async setMagnetometerPeriod(frequency: MagnetometerPeriod): Promise<void> {\n        const view = new DataView(new ArrayBuffer(2));\n        view.setUint16(0, frequency, true);\n        return this.helper.setCharacteristicValue(\n            MagnetometerCharacteristic.magnetometerPeriod,\n            view\n        );\n    }\n\n    private magnetometerDataChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        const value = this.dataViewToMagnetometerData(view);\n        this.dispatchEvent('magnetometerdatachanged', value);\n    }\n\n    private magnetometerBearingChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        if (view.byteLength === 2) {\n            this.dispatchEvent('magnetometerbearingchanged', view.getUint16(0, true));\n        }\n    }\n\n    private magnetometerCalibrationChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        if (view.byteLength === 1) {\n            this.dispatchEvent('magnetometercalibrationchanged', view.getUint8(\n                0\n            ) as MagnetometerCalibration);\n        }\n    }\n\n    private dataViewToMagnetometerData(view: DataView): MagnetometerData {\n        return {\n            x: view.getInt16(0, true),\n            y: view.getInt16(1, true),\n            z: view.getInt16(2, true),\n        };\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/temperature.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { TypedDispatcher, EventDispatcher } from '../event-dispatcher';\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum TemperatureCharacteristic {\n    temperature = 'e95d9250-251d-470a-a062-fa1922dfa9a8',\n    temperaturePeriod = 'e95d1b25-251d-470a-a062-fa1922dfa9a8',\n}\n\n/**\n * Events raised by the temperature service\n */\nexport interface TemperatureEvents {\n    /**\n     * @hidden\n     */\n    newListener: keyof TemperatureEvents;\n    /**\n     * @hidden\n     */\n    removeListener: keyof TemperatureEvents;\n    /**\n     * Temperature changed event\n     */\n    temperaturechanged: number;\n}\n\n/**\n * Temperature Service\n */\nexport class TemperatureService extends (EventDispatcher as new () => TypedDispatcher<\n    TemperatureEvents\n>) {\n    public static serviceName = 'TemperatureService';\n    /**\n     * @hidden\n     */\n    public static uuid = 'e95d6100-251d-470a-a062-fa1922dfa9a8';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<TemperatureService> {\n        const bluetoothService = new TemperatureService(service);\n        await bluetoothService.init();\n        return bluetoothService;\n    }\n\n    private helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        super();\n        //@ts-ignore\n        this.helper = new ServiceHelper(service, this);\n    }\n\n    private async init() {\n        await this.helper.handleListener(\n            'temperaturechanged',\n            TemperatureCharacteristic.temperature,\n            this.temperatureChangedHandler.bind(this)\n        );\n    }\n\n    /**\n     * Read temperature\n     */\n    public async readTemperature(): Promise<number> {\n        const view = await this.helper.getCharacteristicValue(\n            TemperatureCharacteristic.temperature\n        );\n        return view.getInt8(0);\n    }\n\n    /**\n     * Get temperature sample period\n     */\n    public async getTemperaturePeriod(): Promise<number> {\n        const view = await this.helper.getCharacteristicValue(\n            TemperatureCharacteristic.temperaturePeriod\n        );\n        return view.getUint16(0, true);\n    }\n\n    /**\n     * Set temperature sample period\n     * @param frequency The frequency to use (milliseconds)\n     */\n    public async setTemperaturePeriod(frequency: number): Promise<void> {\n        const view = new DataView(new ArrayBuffer(2));\n        view.setUint16(0, frequency, true);\n        return await this.helper.setCharacteristicValue(\n            TemperatureCharacteristic.temperaturePeriod,\n            view\n        );\n    }\n\n    private temperatureChangedHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        this.dispatchEvent('temperaturechanged', view.getInt8(0));\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/bluetoothServices/services/uart.ts",
    "content": "/*\n * micro:bit Web Bluetooth\n * Copyright (c) 2019 Rob Moran\n *\n * The MIT License (MIT)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\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 THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { EventDispatcher, TypedDispatcher } from '../event-dispatcher';\nimport { ServiceHelper } from '../service-helper';\n\n/**\n * @hidden\n */\nexport enum UartCharacteristic {\n    tx = '6e400002-b5a3-f393-e0a9-e50e24dcca9e',\n    rx = '6e400003-b5a3-f393-e0a9-e50e24dcca9e',\n}\n\n/**\n * Events raised by the UART service\n */\nexport interface UartEvents {\n    /**\n     * @hidden\n     */\n    newListener: keyof UartEvents;\n    /**\n     * @hidden\n     */\n    removeListener: keyof UartEvents;\n    /**\n     * Serial data received event\n     */\n    receive: Uint8Array;\n    /**\n     * Serial received text event\n     */\n    receiveText: string;\n}\n\n/**\n * UART Service\n */\nexport class UartService extends (EventDispatcher as new () => TypedDispatcher<UartEvents>) {\n    public static serviceName = 'UartService';\n    /**\n     * @hidden\n     */\n    public static uuid = '6e400001-b5a3-f393-e0a9-e50e24dcca9e';\n\n    /**\n     * @hidden\n     */\n    public static async create(service: BluetoothRemoteGATTService): Promise<UartService> {\n        const bluetoothService = new UartService(service);\n        await bluetoothService.init();\n        return bluetoothService;\n    }\n\n    private helper: ServiceHelper;\n\n    /**\n     * @hidden\n     */\n    constructor(service: BluetoothRemoteGATTService) {\n        super();\n        //@ts-ignore\n        this.helper = new ServiceHelper(service, this);\n    }\n\n    private async init() {\n        await this.helper.handleListener(\n            'receive',\n            UartCharacteristic.tx,\n            this.receiveHandler.bind(this)\n        );\n        await this.helper.handleListener(\n            'receiveText',\n            UartCharacteristic.tx,\n            this.receiveTextHandler.bind(this)\n        );\n    }\n\n    /**\n     * Send serial data\n     * @param value The buffer to send\n     */\n    public async send(value: BufferSource): Promise<void> {\n        return this.helper.setCharacteristicValue(UartCharacteristic.rx, value);\n    }\n\n    /**\n     * Send serial text\n     * @param value The text to send\n     */\n    public async sendText(value: string): Promise<void> {\n        const arrayData = value.split('').map((e: string) => e.charCodeAt(0));\n        return this.helper.setCharacteristicValue(\n            UartCharacteristic.rx,\n            new Uint8Array(arrayData).buffer\n        );\n    }\n\n    private receiveHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        const value = new Uint8Array(view.buffer);\n        this.dispatchEvent('receive', value);\n    }\n\n    private receiveTextHandler(event: Event) {\n        const view = (event.target as BluetoothRemoteGATTCharacteristic).value!;\n        const numberArray = Array.prototype.slice.call(new Uint8Array(view.buffer));\n        const value = String.fromCharCode.apply(null, numberArray);\n        this.dispatchEvent('receiveText', value);\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/externalProgramLauncher.ts",
    "content": "class ExternalProgramLauncher {\n    public programNotInstalled = false;\n    private loadingView: Window;\n\n    public executeUrl(schemeUrl: string, notInstalledCallback: () => void) {\n        if (navigator.userAgent.indexOf('MSIE') > 0 || navigator.userAgent.indexOf('Trident') > 0) {\n            if (navigator.msLaunchUri !== undefined) {\n                executeIe(schemeUrl);\n            } else {\n                let ieVersion;\n                // @ts-ignore IE 에 실제 있는 프로퍼티이다.\n                if (document.documentMode > 0) {\n                    // @ts-ignore IE 에 실제 있는 프로퍼티이다.\n                    ieVersion = document.documentMode;\n                } else {\n                    ieVersion = navigator.userAgent.match(/(?:MSIE) ([0-9.]+)/)[1];\n                }\n\n                if (ieVersion < 9) {\n                    alert(Lang.msgs.not_support_browser);\n                } else {\n                    this.init(schemeUrl, (programInstalled) => {\n                        if (programInstalled === false) {\n                            notInstalledCallback();\n                        }\n                    });\n                }\n            }\n        } else if (navigator.userAgent.indexOf('Firefox') > 0) {\n            executeFirefox(schemeUrl);\n        } else if (navigator.userAgent.indexOf('Chrome') > 0) {\n            executeChrome(schemeUrl);\n        } else if (navigator.userAgent.indexOf('Safari') > 0) {\n            executeSafari(schemeUrl);\n        } else {\n            alert(Lang.msgs.not_support_browser);\n        }\n\n        function executeIe(customUrl: string) {\n            navigator.msLaunchUri(\n                customUrl,\n                () => {},\n                () => {\n                    notInstalledCallback();\n                }\n            );\n        }\n\n        function executeFirefox(customUrl: string) {\n            const iFrame = document.createElement('iframe');\n            iFrame.src = 'about:blank';\n            iFrame.setAttribute('style', 'display:none');\n            document.getElementsByTagName('body')[0].appendChild(iFrame);\n            const fnTimeout = setTimeout(() => {\n                let isInstalled = false;\n                try {\n                    iFrame.contentWindow.location.href = customUrl;\n                    isInstalled = true;\n                } catch (e) {\n                    if (e.name === 'NS_ERROR_UNKNOWN_PROTOCOL') {\n                        isInstalled = false;\n                    }\n                }\n\n                if (!isInstalled) {\n                    notInstalledCallback();\n                }\n\n                document.getElementsByTagName('body')[0].removeChild(iFrame);\n                clearTimeout(fnTimeout);\n            }, 500);\n        }\n\n        function executeChrome(customUrl: string) {\n            let isInstalled = false;\n            window.focus();\n            $(window).one('blur', () => {\n                isInstalled = true;\n            });\n            Entry.dispatchEvent('workspaceUnbindUnload', true);\n            location.assign(encodeURI(customUrl));\n            setTimeout(() => {\n                Entry.dispatchEvent('workspaceBindUnload', true);\n            }, 100);\n            setTimeout(() => {\n                if (isInstalled === false) {\n                    notInstalledCallback();\n                }\n                window.onblur = null;\n            }, 3000);\n        }\n\n        /**\n         * safari 브라우저에서 ${customUrl} 인식하여 페이지 이동 처리되서 분기처리(미설치 안내팝업)\n         *\n         * @param customUrl\n         */\n        function executeSafari(customUrl: string) {\n            const iFrame = document.createElement('iframe');\n            iFrame.src = 'about:blank';\n            iFrame.setAttribute('style', 'display:none');\n            document.getElementsByTagName('body')[0].appendChild(iFrame);\n            let isInstalled;\n\n            try {\n                iFrame.contentWindow.location.href = customUrl;\n                isInstalled = true;\n            } catch (err) {\n                isInstalled = false;\n            }\n\n            if (!isInstalled) {\n                notInstalledCallback();\n            }\n            setTimeout(() => {\n                document.getElementsByTagName('body')[0].removeChild(iFrame);\n            }, 500);\n        }\n    }\n\n    public set() {\n        this.programNotInstalled = true;\n    }\n\n    private init(schemeUrl: string, callback: (programInstalled: boolean) => void) {\n        const settings = this.getLoadingViewStyle();\n\n        this.loadingView = window.open('/views/hwLoading.html', 'entry_hw_launcher', settings);\n        let fnInterval: NodeJS.Timeout = undefined;\n        fnInterval = setTimeout(() => {\n            this.runViewer(schemeUrl, callback);\n            clearInterval(fnInterval);\n        }, 1000);\n    }\n\n    private runViewer(schemeUrl: string, callback: (programInstalled: boolean) => void) {\n        this.loadingView.document.write(\n            // eslint-disable-next-line max-len\n            `<iframe src='${schemeUrl}' onload='opener.Entry.hw.programLauncher.set()' style='display:none;width:0;height:0'></iframe>`\n        );\n        let tryCounter = 0;\n        const programNotInstalled = false;\n        let tryExecutionTimeout: NodeJS.Timeout = undefined;\n        tryExecutionTimeout = setInterval(() => {\n            try {\n                this.loadingView.location.href;\n            } catch (e) {\n                this.programNotInstalled = true;\n            }\n\n            if (programNotInstalled || tryCounter > 10) {\n                clearInterval(tryExecutionTimeout);\n                let nCloseCounter = 0;\n                let nCloseInterval: NodeJS.Timeout = undefined;\n                nCloseInterval = setInterval(() => {\n                    nCloseCounter++;\n                    if (this.loadingView.closed || nCloseCounter > 2) {\n                        clearInterval(nCloseInterval);\n                    } else {\n                        this.loadingView.close();\n                    }\n                    this.programNotInstalled = false;\n                    tryCounter = 0;\n                }, 5000);\n                callback(!this.programNotInstalled);\n            }\n            tryCounter++;\n        }, 100);\n    }\n\n    private getLoadingViewStyle() {\n        const width = 220;\n        const height = 225;\n        const left = window.screenLeft;\n        const top = window.screenTop;\n        return `width=${width}, height=${height},  top=${top}, left=${left}`;\n    }\n}\n\nexport default ExternalProgramLauncher;\n"
  },
  {
    "path": "src/class/hardware/functions/createHardwarePopup.ts",
    "content": "import PopupHelper from '../../popup_helper';\n\nexport default function createHardwarePopup(onOkButtonClicked?: () => void) {\n    const popupHelper = window.popupHelper || new PopupHelper(true);\n    popupHelper.addPopup('hwDownload', {\n        type: 'confirm',\n        title: Lang.Msgs.not_install_title,\n        setPopupLayout(popup: any) {\n            const content = Entry.Dom('div', {\n                class: 'contentArea',\n            });\n            const text = Entry.Dom('div', {\n                class: 'textArea',\n                parent: content,\n            });\n            const text1 = Entry.Dom('div', {\n                class: 'text1',\n                parent: text,\n            });\n            const text2 = Entry.Dom('div', {\n                class: 'text2',\n                parent: text,\n            });\n            const text3 = Entry.Dom('div', {\n                class: 'text3',\n                parent: text,\n            });\n            const text4 = Entry.Dom('div', {\n                class: 'text4',\n                parent: text,\n            });\n            const cancel = Entry.Dom('div', {\n                classes: ['popupCancelBtn', 'popupDefaultBtn'],\n                parent: content,\n            });\n            const ok = Entry.Dom('div', {\n                classes: ['popupOkBtn', 'popupDefaultBtn'],\n                parent: content,\n            });\n            (text1 as any).text(Lang.Msgs.hw_download_text1);\n            (text2 as any).html(Lang.Msgs.hw_download_text2);\n            (text3 as any).text(Lang.Msgs.hw_download_text3);\n            (text4 as any).text(Lang.Msgs.hw_download_text4);\n            (cancel as any).text(Lang.Buttons.cancel);\n            (ok as any).html(Lang.Msgs.hw_download_btn);\n\n            (content as any).bindOnClick('.popupDefaultBtn', function() {\n                const $this = $(this);\n                if ($this.hasClass('popupOkBtn')) {\n                    onOkButtonClicked();\n                }\n                popupHelper.hide(/*'hwDownload'*/);\n            });\n\n            popup.append(content);\n        },\n    });\n\n    return popupHelper;\n}\n"
  },
  {
    "path": "src/class/hardware/hardwareMonitor.ts",
    "content": "import { EntryHardwareBlockModule } from '../../../types/index';\n\nconst hwMonitorSvgTemplate =\n    '<svg id=\"hwMonitor\" width=\"100%\" height=\"100%\"' +\n    'version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"></svg>';\n\nexport default class HardwareMonitor {\n    private _hwModule: EntryHardwareBlockModule;\n    private snap: any;\n    private _svgGroup: any;\n    private _portMap: any;\n    private _portViews: any;\n    private hwView: any;\n    private pathGroup: any;\n    private _template: any;\n    private _svglistGroup: any;\n    private _pathGroup: any;\n    private _portMapList: any;\n    private listsnap: any;\n    private _rect: any;\n\n    private svgDom = Entry.Dom($(hwMonitorSvgTemplate));\n    private changeOffset = 0; // 0 : off 1: on\n    private scale = 0.5;\n    private _listPortViews: any = {};\n\n    constructor(hwModule: EntryHardwareBlockModule) {\n        this._hwModule = hwModule;\n\n        Entry.addEventListener('windowResized', () => {\n            const mode = this._hwModule.monitorTemplate.mode;\n            if (mode == 'both') {\n                this.resize();\n                this.resizeList();\n            }\n\n            if (mode == 'list') {\n                this.resizeList();\n            } else {\n                this.resize();\n            }\n        });\n        Entry.addEventListener('hwModeChange', () => {\n            this.changeMode();\n        });\n    }\n\n    initView() {\n        this.svgDom = Entry.Dom($(hwMonitorSvgTemplate));\n    }\n\n    generateViewByMode() {\n        this._template =\n            typeof this._hwModule.monitorTemplate === 'function'\n                ? this._hwModule.monitorTemplate()\n                : this._hwModule.monitorTemplate;\n\n        const monitorTemplate = this._template;\n\n        if (monitorTemplate.mode === 'both') {\n            this.generateListView();\n            this.generateView();\n        } else if (monitorTemplate.mode === 'list') {\n            this.generateListView();\n        } else {\n            this.generateView();\n        }\n    }\n\n    generateView() {\n        this.snap = Entry.SVG('hwMonitor');\n        this._svgGroup = this.snap.elem('g');\n        this._portMap = {\n            n: [],\n            e: [],\n            s: [],\n            w: [],\n        };\n        const monitorTemplate = this._template;\n\n        const imgObj = {\n            href: monitorTemplate.imgPath\n                ? Entry.mediaFilePath + monitorTemplate.imgPath\n                : undefined,\n            x: -monitorTemplate.width / 2,\n            y: -monitorTemplate.height / 2,\n\n            width: monitorTemplate.width,\n            height: monitorTemplate.height,\n        };\n\n        this._portViews = {};\n        if (imgObj.href) {\n            this.hwView = this._svgGroup.elem('image');\n            this.hwView = this.hwView.attr(imgObj);\n        }\n        const ports = monitorTemplate.ports;\n        this.pathGroup = null;\n        this.pathGroup = this._svgGroup.elem('g');\n\n        const portsTemp = [];\n        for (const key in ports) {\n            const port = ports[key];\n            const portView = this.generatePortView(port, '_svgGroup');\n\n            this._portViews[key] = portView;\n            portsTemp.push(portView);\n        }\n\n        portsTemp.sort((a, b) => a.box.x - b.box.x);\n\n        const portMap = this._portMap;\n\n        portsTemp.map((v) => {\n            const degree = (Math.atan2(-v.box.y, v.box.x) / Math.PI + 2) % 2;\n            let map;\n\n            if (degree < 1) {\n                map = portMap.n;\n            } else {\n                map = portMap.s;\n            }\n            map.push(v);\n        });\n        this.resize();\n    }\n\n    toggleMode(mode: string) {\n        const monitorTemplate = this._hwModule.monitorTemplate;\n        if (mode === 'list') {\n            monitorTemplate.TempPort = null;\n            if (this._hwModule.monitorTemplate.ports) {\n                this._hwModule.monitorTemplate.TempPort = this._hwModule.monitorTemplate.ports;\n                this._hwModule.monitorTemplate.listPorts = this.addPortEle(\n                    this._hwModule.monitorTemplate.listPorts,\n                    this._hwModule.monitorTemplate.ports\n                );\n            }\n\n            $(this._svglistGroup).remove();\n\n            if (this._svgGroup) {\n                $(this._svgGroup).remove();\n            }\n\n            $(this._pathGroup).remove();\n            this._hwModule.monitorTemplate.mode = 'list';\n            this.generateListView();\n        } else {\n            if (this._hwModule.monitorTemplate.TempPort) {\n                this._hwModule.monitorTemplate.ports = this._hwModule.monitorTemplate.TempPort;\n                this._hwModule.monitorTemplate.listPorts = this.removePortEle(\n                    this._hwModule.monitorTemplate.listPorts,\n                    this._hwModule.monitorTemplate.ports\n                );\n            }\n\n            $(this._svglistGroup).remove();\n            this._hwModule.monitorTemplate.mode = 'both';\n            this.generateListView();\n            this.generateView();\n        }\n    }\n\n    setHwModule(hwModule: EntryHardwareBlockModule) {\n        this._hwModule = hwModule;\n    }\n\n    changeMode() {\n        if (this._hwModule.monitorTemplate.mode === 'both') {\n            this.toggleMode('list');\n        } else if (this._hwModule.monitorTemplate.mode === 'list') {\n            this.toggleMode('both');\n        }\n    }\n\n    addPortEle(listPort: any, ports: any) {\n        if (typeof ports != 'object') {\n            return listPort;\n        }\n\n        for (const item in ports) {\n            listPort[item] = ports[item];\n        }\n\n        return listPort;\n    }\n\n    removePortEle(listPort: any, ports: any) {\n        if (typeof ports != 'object') {\n            return listPort;\n        }\n\n        for (const item in ports) {\n            delete listPort[item];\n        }\n        return listPort;\n    }\n\n    generateListView() {\n        this._portMapList = {\n            n: [],\n        };\n        this._svglistGroup = null;\n\n        this.listsnap = Entry.SVG('hwMonitor');\n        this._svglistGroup = this.listsnap.elem('g');\n        const monitorTemplate = this._template;\n        const ports = monitorTemplate.listPorts;\n\n        this.pathGroup = this._svglistGroup.elem('g');\n\n        const portsTempList = [];\n\n        for (const key in ports) {\n            const port = ports[key];\n            const portView = this.generatePortView(port, '_svglistGroup');\n\n            this._listPortViews[key] = portView;\n            portsTempList.push(portView);\n        }\n        const portMapList = this._portMapList;\n\n        portsTempList.map((v) => {\n            portMapList.n.push(v);\n        });\n\n        this.resizeList();\n    }\n\n    generatePortView(port: any, target: string) {\n        // @ts-ignore\n        const svgGroup = this[target].elem('g');\n        svgGroup.addClass('hwComponent');\n        let path = null;\n\n        path = this.pathGroup.elem('path').attr({\n            d: 'm0,0',\n            fill: 'none',\n            stroke: port.type === 'input' ? '#00CFCA' : '#CA7DFF',\n            'stroke-width': 3,\n        });\n\n        const wrapperRect = svgGroup.elem('rect').attr({\n            x: 0,\n            y: 0,\n            width: 150,\n            height: 22,\n            rx: 4,\n            ry: 4,\n            fill: '#fff',\n            stroke: '#a0a1a1',\n        });\n        const nameView = svgGroup.elem('text').attr({\n            x: 4,\n            y: 12,\n            fill: '#000',\n            class: 'hwComponentName',\n            'alignment-baseline': 'central',\n        });\n        nameView.textContent = port.name;\n\n        let width = nameView.getComputedTextLength();\n\n        const valueRect = svgGroup.elem('rect').attr({\n            x: width + 8,\n            y: 2,\n            width: 30,\n            height: 18,\n            rx: 9,\n            ry: 9,\n            fill: port.type === 'input' ? '#00CFCA' : '#CA7DFF',\n        });\n\n        const valueView = svgGroup.elem('text').attr({\n            x: width + 13,\n            y: 12,\n            fill: '#fff',\n            class: 'hwComponentValue',\n            'alignment-baseline': 'central',\n        });\n        valueView.textContent = 0;\n        width += 40;\n\n        wrapperRect.attr({\n            width,\n        });\n\n        const returnObj = {\n            group: svgGroup,\n            value: valueView,\n            type: port.type,\n            path,\n            box: {\n                x: port.pos.x - this._template.width / 2,\n                y: port.pos.y - this._template.height / 2,\n                width,\n            },\n            width,\n        };\n\n        return returnObj;\n    }\n\n    getView() {\n        return this.svgDom;\n    }\n\n    update(portData: any, sendQueue: any) {\n        const mode = this._template.mode;\n        const objectKeys = this._template.keys || [];\n        let portView = [];\n\n        if (mode == 'list') {\n            portView = this._listPortViews;\n        } else if (mode == 'both' && this._portViews) {\n            portView = this._listPortViews;\n            for (const elem in this._portViews) {\n                portView[elem] = this._portViews[elem];\n            }\n        } else {\n            portView = this._portViews;\n        }\n\n        if (sendQueue) {\n            for (const elem in sendQueue) {\n                if (sendQueue[elem] != 0 && portView[elem]) {\n                    portView[elem].type = 'output';\n                }\n            }\n        }\n\n        for (const key in portView) {\n            const port = portView[key];\n\n            if (port.type == 'input') {\n                let value = portData[key];\n                if (objectKeys.length > 0) {\n                    $.each(objectKeys, (idx, valueKey) => {\n                        if ($.isPlainObject(value)) {\n                            value = value[valueKey] || 0;\n                        } else {\n                            return false;\n                        }\n                    });\n                    port.value.textContent = value ? value : 0;\n                    port.group.getElementsByTagName('rect')[1].attr({ fill: '#00CFCA' });\n                } else {\n                    port.value.textContent = value ? value : 0;\n                    port.group.getElementsByTagName('rect')[1].attr({ fill: '#00CFCA' });\n                }\n            } else {\n                let value = sendQueue ? sendQueue[key] : portData[key];\n                if (objectKeys.length > 0) {\n                    $.each(objectKeys, (idx, valueKey) => {\n                        if ($.isPlainObject(value)) {\n                            value = value[valueKey] || 0;\n                        } else {\n                            return false;\n                        }\n                    });\n                    port.value.textContent = value ? value : 0;\n                    port.group.getElementsByTagName('rect')[1].attr({ fill: '#CA7DFF' });\n                } else {\n                    port.value.textContent = value ? value : 0;\n                    port.group.getElementsByTagName('rect')[1].attr({ fill: '#CA7DFF' });\n                }\n            }\n        }\n    }\n\n    resize() {\n        if (!this.svgDom) {\n            return;\n        }\n\n        const bRect = this.svgDom.get(0).getBoundingClientRect();\n\n        this._svgGroup.attr({\n            transform: `translate(${bRect.width / 2},${bRect.height / 1.8})`,\n        });\n\n        this._rect = bRect;\n\n        if (this._template.height <= 0 || bRect.height <= 0) {\n            return;\n        }\n\n        this.scale = (this._template.height * (bRect.height / this._template.height)) / 1000;\n\n        if (this.hwView && this.scale) {\n            this.hwView.attr({\n                transform: `scale(${this.scale})`,\n            });\n        }\n\n        this.align();\n    }\n\n    resizeList() {\n        const bRect = this.svgDom.get(0).getBoundingClientRect();\n        this._svglistGroup.attr({\n            transform: `translate(${bRect.width / 2},${bRect.height / 2})`,\n        });\n        this._rect = bRect;\n        this.alignList();\n    }\n\n    align() {\n        this._alignNS(this._portMap.s.concat(), this._template.height * (this.scale / 3) + 5, 27);\n        this._alignNS(\n            this._portMap.n.concat(),\n            (-this._template.height * this.scale) / 3 - 32,\n            -27\n        );\n    }\n\n    alignList() {\n        let ports = this._hwModule.monitorTemplate.listPorts || {};\n        const length = ports.length;\n        for (let i = 0; i < ports.length; i++) {\n            const port = ports[i];\n\n            port.group.attr({\n                transform: `translate(${this._template.width * (i / length - 0.5)},${-this._template\n                    .width /\n                    2 -\n                    30})`,\n            });\n        }\n\n        ports = this._portMapList.n.concat();\n        this._alignNSList(ports, (-this._template.width * this.scale) / 2 - 32 /*, -27*/);\n    }\n\n    _alignNS(ports: any, yCursor: any, gap: any) {\n        const length = ports.length;\n        const mid = (length - 1) / 2;\n        let lP = -this._rect.width / 2;\n        let rP = this._rect.width / 2;\n        const width = this._rect.width;\n        let wholeWidth = 0;\n        const listLine = 0;\n        const mode = this._hwModule.monitorTemplate.mode;\n\n        for (let i = 0; i < ports.length; i++) {\n            wholeWidth += ports[i].width + 5;\n        }\n\n        if (wholeWidth < rP - lP) {\n            rP = wholeWidth / 2 + 3;\n            lP = -wholeWidth / 2 - 3;\n        }\n\n        while (ports.length > 1) {\n            const lPort = ports.shift();\n            const rPort = ports.pop();\n            const prevLP = lP;\n            const prevRP = rP;\n            let gapTemp = gap;\n            if (wholeWidth <= rP - lP) {\n                lP += lPort.width + 5;\n                rP -= rPort.width + 5;\n                gapTemp = 0;\n            } else if (ports.length === 0) {\n                lP = (lP + rP) / 2 - 3;\n                rP = lP + 6;\n            } else {\n                lP = Math.max(lP, -width / 2 + lPort.width) + 15;\n                rP = Math.min(rP, width / 2 - rPort.width) - 15;\n            }\n\n            this._movePort(lPort, lP, yCursor, prevLP);\n            this._movePort(rPort, rP, yCursor, prevRP);\n\n            wholeWidth -= lPort.width + rPort.width + 10;\n            yCursor += gapTemp;\n        }\n\n        if (ports.length) {\n            this._movePort(ports[0], (rP + lP - ports[0].width) / 2, yCursor, 100);\n        }\n    }\n\n    _alignNSList(ports: any, yCursor: any) {\n        const length = ports.length;\n        const width = this._rect.width;\n        const height = this._rect.height;\n        let initX = -this._rect.width / 2 + 10;\n        const initY = -this._rect.height / 2 + 10;\n        let wholeWidth = 0;\n        const listLine = 0;\n\n        for (var i = 0; i < ports.length; i++) {\n            wholeWidth += ports[i].width; // 전체 width\n        }\n\n        let lineIndent = 0;\n        let currentWidth = 0;\n        const tempXpos = initX;\n        let Yval = 0;\n        let cPort: any = 0;\n        let nPort: any = 0;\n        for (var i = 0; i < ports.length; i++) {\n            cPort = ports[i];\n\n            if (i != ports.length - 1) {\n                nPort = ports[i + 1];\n            }\n\n            currentWidth += cPort.width;\n\n            const lP = initX;\n            Yval = initY + lineIndent * 30;\n            cPort.group.attr({\n                transform: `translate(${lP},${Yval})`,\n            });\n            initX += cPort.width + 10;\n\n            if (currentWidth > width - (cPort.width + nPort.width / 2.2)) {\n                lineIndent += 1;\n                initX = tempXpos;\n                currentWidth = 0;\n            }\n        }\n    }\n\n    _movePort(port: any, x: any, y: any, prevPointer: any) {\n        let groupX = x;\n        let path;\n        const portX = port.box.x * this.scale;\n        const portY = port.box.y * this.scale;\n\n        if (x > prevPointer) {\n            // left side\n            groupX = x - port.width;\n            if (x > portX && portX > prevPointer) {\n                path = `M${portX},${y}L${portX},${portY}`;\n            } else {\n                path = `M${(x + prevPointer) / 2},${y}l0,${\n                    portY > y ? 28 : -3\n                }H${portX}L${portX},${portY}`;\n            }\n        } else if (x < portX && portX < prevPointer) {\n            // right side\n            path = `m${portX},${y}L${portX},${portY}`;\n        } else {\n            path = `m${(prevPointer + x) / 2},${y}l0,${\n                portY > y ? 28 : -3\n            }H${portX}L${portX},${portY}`;\n        }\n\n        port.group.attr({ transform: `translate(${groupX},${y})` });\n        port.path.attr({ d: path });\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/hardwareSocketMessageHandler.ts",
    "content": "import isObject from 'lodash/isObject';\n\n/**\n * 엔트리 하드웨어 -> 엔트리 워크스페이스간 통신을 정리한 클래스\n * action, data(payload) 를 메세지로 받는다.\n * action\n * - state { statement: String } : 현재 상태를 정의한다. 하드웨어의 연결 상태 체크용\n * - init { name: String } : 현재 연결된 하드웨어의 모듈명을 전달 받고, 서버에서 블록데이터를 받아온다.\n * - default { anyObject for data handle }: 이전의 hw.js 에 있는 로직을 그대로 복사. 과거 코드 대응\n *   - disconnect : 이전 disconnectHardware 와 동일\n */\n\ntype EntryHardwareSocketMessage = {\n    action: string;\n    data: any;\n};\n\nexport default class {\n    private socket: SocketIOClient.Socket;\n    private readonly listeners: { [type: string]: any };\n\n    constructor(socket: SocketIOClient.Socket) {\n        this.socket = socket;\n        this.listeners = [];\n        socket.on('message', this._onAction.bind(this));\n    }\n\n    _onAction(message: EntryHardwareSocketMessage) {\n        // 객체 구조가 이모양인건 기존 호환성때문.\n        // 정리해서 이쁘게 만들도록 하자 (entry-hw-server 수정필요)\n        const { data } = message;\n        const { action, data: payload } = data;\n        switch (action) {\n            case 'state':\n                this._onStateAction(payload);\n                break;\n            case 'init':\n                this._onInitAction(payload);\n                break;\n            default:\n                this._onDefaultAction(data);\n        }\n    }\n\n    /**\n     * 현재 하드웨어 연결 상태를 표기한다.\n     * connected 의 경우 어떤 하드웨어와 연결되었는지 표기된다.\n     * @param payload {*} payload\n     * @private\n     */\n    _onStateAction(payload: any) {\n        const { statement, name } = payload;\n        this.dispatchEvent('state', statement, name);\n    }\n\n    _onInitAction({ name }: any) {\n        this.dispatchEvent('init', name);\n    }\n\n    /**\n     * 1.7.0 이전 하드웨어 버전의 원활한 통신을 위해 남겨두어야 한다.\n     * @param data\n     * @private\n     */\n    _onDefaultAction(data: any) {\n        if (data) {\n            let portData = {};\n            if (typeof data === 'string') {\n                switch (data) {\n                    case 'disconnectHardware': {\n                        this.dispatchEvent('disconnect');\n                        return;\n                    }\n                    default: {\n                        portData = JSON.parse(data);\n                        break;\n                    }\n                }\n            } else if (isObject(data)) {\n                portData = data;\n            }\n            this.dispatchEvent('data', portData);\n        }\n    }\n\n    addEventListener(type: string, callback: (...args: any[]) => void) {\n        if (!(type in this.listeners)) {\n            this.listeners[type] = [];\n        }\n        this.listeners[type].push(callback);\n    }\n\n    removeEventListener(type: string, callback: () => void) {\n        if (!(type in this.listeners)) {\n            return;\n        }\n        const stack = this.listeners[type];\n        for (let i = 0, l = stack.length; i < l; i++) {\n            if (stack[i] === callback) {\n                stack.splice(i, 1);\n                return;\n            }\n        }\n    }\n\n    dispatchEvent(eventName: string, ...args: any[]) {\n        if (!(eventName in this.listeners)) {\n            return true;\n        }\n        const stack = this.listeners[eventName].slice();\n\n        for (let i = 0, l = stack.length; i < l; i++) {\n            stack[i].call(this, ...args);\n        }\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/webApiConnector.ts",
    "content": "// INFO : 웹연결 api의 라이프사이클 함수를 모아놓은 추상 클래스\nexport default class WebApiConnector {\n    connect() {}\n    disconnect() {}\n    initialDevice() {}\n}\n"
  },
  {
    "path": "src/class/hardware/webBluetoothConnector.ts",
    "content": "import { EntryHWLiteBaseModule } from 'types';\nimport HardwareLite from '../hw_lite';\nimport WebApiConnector from './webApiConnector';\nimport { getServiceClassesByModuleId } from './bluetoothServices';\n\nexport default class WebBluetoothConnector extends WebApiConnector {\n    private hwModule: EntryHWLiteBaseModule;\n    private hwLite: HardwareLite;\n    private device: BluetoothDevice;\n    private services: any; // TODO: 타입할당\n    private serviceClasses: any[];\n\n    constructor(hwModule: EntryHWLiteBaseModule, hwLite: HardwareLite) {\n        super();\n        this.hwModule = hwModule;\n        this.setServiceClasses();\n    }\n\n    async connect() {\n        await this.setDevice();\n        await this.setServices();\n    }\n\n    async disconnect() {\n        await this.device.gatt.disconnect();\n        this.hwModule = undefined;\n        this.device = undefined;\n        this.services = undefined;\n        this.serviceClasses = undefined;\n    }\n\n    async initialDevice() {\n        if (this.hwModule?.initialHandshake) {\n            this.hwModule?.initialHandshake();\n        }\n    }\n\n    async setDevice() {\n        const filters = this.hwModule.bluetoothInfo.filters;\n        const optionalServices = this.serviceClasses.map((serviceClass) => serviceClass.uuid);\n        this.device = await navigator.bluetooth.requestDevice({ filters, optionalServices });\n    }\n\n    setServiceClasses() {\n        this.serviceClasses = getServiceClassesByModuleId(this.hwModule.id);\n    }\n\n    async setServices() {\n        if (!this.device || !this.device.gatt) {\n            this.hwLite.getConnectFailedMenu();\n            return;\n        }\n\n        if (!this.device.gatt.connected) {\n            await this.device.gatt.connect();\n        }\n\n        this.services = {};\n\n        const primaryServices = await this.device.gatt.getPrimaryServices();\n\n        for (const primaryService of primaryServices) {\n            for (const serviceClass of this.serviceClasses) {\n                if (primaryService.uuid === serviceClass.uuid) {\n                    this.services[serviceClass.serviceName] = await serviceClass.create(primaryService);\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/webSerialConnector.ts",
    "content": "import { EntryHWLiteBaseModule } from 'types';\nimport HardwareLite from '../hw_lite';\nimport WebApiConnector from './webApiConnector';\nimport throttle from 'lodash/throttle';\n\nconst Buffer = require('buffer/').Buffer;\n\nclass LineBreakTransformer {\n    private container: string;\n    constructor() {\n        this.container = '';\n    }\n\n    transform(chunk: string, controller: any) {\n        try {\n            this.container += chunk;\n            // @ts-ignore\n            const lines = this.container.split(Entry.hwLite?.hwModule?.delimeter || '\\r\\n');\n            this.container = lines.pop();\n            lines.forEach((line) => controller.enqueue(line));\n        } catch (e) {\n            controller.enqueue(chunk);\n        }\n    }\n\n    flush(controller: any) {\n        controller.enqueue(this.container);\n    }\n}\n\nexport default class WebSerialConnector extends WebApiConnector {\n    private writer: any; // SerialPort.writer;\n    private reader: any; //SerialPort.reader;\n    private hwModule: EntryHWLiteBaseModule; // > 추후 전용 타입으로 변경\n    private port: any;\n    private connectionType: 'ascii' | 'bytestream' | undefined;\n    private writableStream: any;\n    private isSendAsyncRun: boolean;\n    private hwLite: HardwareLite;\n    private sendAsyncWithThrottle: any;\n\n    constructor(hwModule: EntryHWLiteBaseModule, hwLite: HardwareLite) {\n        super();\n        this.hwLite = hwLite;\n        this.hwModule = hwModule;\n        this.isSendAsyncRun = false;\n        this.hwLite.setStatus('disconnected');\n        Entry.addEventListener('beforeStop', this.checkConditionBeforeStop.bind(this));\n        this.sendAsyncWithThrottle = throttle(this.sendAsync, this.hwModule.duration);\n    }\n\n    async connect() {\n        // @ts-ignore\n        const port = await navigator.serial.requestPort();\n        const { portData } = this.hwModule || {};\n        await port.open(\n            portData || {\n                baudRate: 9600,\n                dataBits: 8,\n                parity: 'none',\n                bufferSize: 256,\n                stopBits: 1,\n            }\n        );\n        this.port = port;\n        const encoder = new TextEncoderStream();\n        const writable = port.writable;\n\n        this.connectionType = portData?.connectionType;\n        if (portData?.writeAscii || portData?.connectionType === 'ascii') {\n            const writableStream = encoder.readable.pipeTo(writable);\n            this.writableStream = writableStream;\n            this.writer = encoder.writable.getWriter();\n        } else {\n            this.writer = port.writable.getWriter();\n        }\n\n        let readable = this.port.readable;\n        if (portData?.readAscii || this.connectionType === 'ascii') {\n            readable = readable.pipeThrough(new TextDecoderStream());\n        }\n        if (this.hwModule?.delimeter || this.connectionType === 'ascii') {\n            readable = readable.pipeThrough(new TransformStream(new LineBreakTransformer()));\n        }\n        this.reader = readable.getReader();\n    }\n\n    async disconnect() {\n        // INFO: 디바이스가 제거되었을 때, reader만 단독 예외처리\n        try {\n            await this.reader?.cancel().catch((error: any) => {\n                console.error(error);\n            });\n\n            await this.writer?.close();\n            if (this.connectionType === 'ascii' && this.writableStream) {\n                await this.writableStream;\n            }\n        } catch (err) {\n            console.error(err);\n        } finally {\n            await this.port?.close();\n            this.port = null;\n            this.reader = null;\n            this.writer = null;\n            this.writableStream = null;\n            this.hwModule = null;\n        }\n    }\n\n    async initialDevice() {\n        if (this.hwModule.initialHandshake) {\n            const result = await this.hwModule.initialHandshake();\n            if (!result) {\n                throw new Error('Handshake Error : 디바이스와 연결에 실패하였습니다.');\n            }\n        }\n        if (this.hwModule.portData?.constantServing) {\n            this.constantServing();\n        }\n    }\n\n    /**\n     * 디바이스와 1회성 통신\n     * @param data\n     * @returns Promise resolves to resulting message\n     */\n    async sendAsync(data?: Buffer | string, isResetReq?: boolean, callback?: Function) {\n        if (this.isSendAsyncRun) {\n            return;\n        } else {\n            this.isSendAsyncRun = true;\n        }\n        if (!data || this.hwLite.getStatus() !== 'connected') {\n            return;\n        }\n        // @ts-ignore\n        const encodedData = typeof data === 'string' ? data : Buffer.from(data, 'utf8');\n\n        try {\n            if (this.hwLite.getStatus() !== 'connected') {\n                Entry.toast.alert(\n                    Lang.Msgs.hw_connection_failed_title,\n                    Lang.Msgs.hw_connection_failed_desc,\n                    false\n                );\n                throw new Error('HARDWARE LITE NOT CONNECTED');\n            }\n            await this.writer.write(encodedData);\n            if (isResetReq) {\n                this.isSendAsyncRun = false;\n                return;\n            }\n            const { value, done } = await this.reader.read();\n            if (callback) {\n                return callback(value);\n            }\n            this.hwLite._updatePortData();\n            return value;\n        } catch (err) {\n            console.error(err);\n            this.hwLite.getConnectFailedMenu();\n        } finally {\n            this.isSendAsyncRun = false;\n        }\n    }\n\n    async constantServing() {\n        try {\n            if (this.hwLite.getStatus() === 'disconnected') {\n                return;\n            }\n            if (this.hwModule?.portData?.constantServing !== 'ReadOnly') {\n                const reqLocal = this.hwModule?.requestLocalData();\n                if (reqLocal && this.hwLite.getStatus() === 'connected') {\n                    if (Entry.engine.isState('run')) {\n                        this.writer.write(Buffer.from(reqLocal));\n                    }\n                }\n            }\n\n            const { value, done } = await this.reader.read();\n            if (done) {\n                this.hwLite.getConnectFailedMenu();\n                return;\n            }\n            this.hwModule?.handleLocalData(value);\n            this.hwLite._updatePortData();\n\n            setTimeout(() => {\n                this.constantServing();\n            }, this.hwModule.duration || 0);\n        } catch (error) {\n            console.error(error);\n            this.hwLite.getConnectFailedMenu();\n            return;\n        }\n    }\n\n    async readPortData() {\n        try {\n            if (this.hwLite.getStatus() === 'connected' && Entry.engine.isState('run')) {\n                const { value, done } = await this.reader.read();\n\n                if (!value) {\n                    this.reader.cancel();\n                    throw new Error(\"reader's value is undefined. check device\");\n                }\n                return value;\n            }\n        } catch (error) {\n            console.error(error);\n            this.hwLite.getConnectFailedMenu();\n        }\n    }\n\n    async writePortData(data: string) {\n        if (data && this.hwLite.getStatus() === 'connected') {\n            const result = await this.writer.write(Buffer.from(data));\n        }\n    }\n\n    async removeSerialPort() {\n        try {\n            // INFO: 디바이스가 제거되었을 때, reader만 단독 예외처리\n            await this.reader?.cancel().catch((error: any) => {\n                console.error(error);\n            });\n\n            await this.writer?.close();\n            if (this.connectionType === 'ascii' && this.writableStream) {\n                await this.writableStream;\n            }\n        } catch (error) {\n            console.error(error);\n        } finally {\n            await this.port?.close();\n            this.port = null;\n            this.reader = null;\n            this.writer = null;\n            this.writableStream = null;\n        }\n    }\n\n    // engine 동작중 에러 발생시 호출, 디바이스에 read, write가 모두 안되는 것이 전제\n    async handleConnectErrorInEngineRun() {\n        // INFO: Engin.toggleStop에서 setZero가 실행되지 않도록 상태변경\n        if (this.hwLite.getStatus() === 'willDisconnect') {\n            return;\n        }\n        this.hwLite.setStatus('willDisconnect');\n        if (Entry.engine.isState('run')) {\n            await Entry.engine.toggleStop();\n        }\n        await this.removeSerialPort();\n        this.hwLite.getConnectFailedMenu();\n        Entry.toast.alert(\n            Lang.Msgs.hw_connection_failed_title,\n            Lang.Msgs.hw_connection_failed_desc,\n            false\n        );\n    }\n\n    update() {\n        if (this.hwLite.getStatus() !== 'connected') {\n            console.error('Cannot update hwLite queue. Check connection status.');\n            return;\n        }\n        if (this.hwModule?.portData?.constantServing) {\n            const reqLocal = this.hwModule?.requestLocalData();\n            if (reqLocal) {\n                this.writer.write(Buffer.from(reqLocal));\n            }\n        }\n    }\n\n    sendAsciiAsBuffer(asciiStr: string) {\n        this.writer.write(Buffer.from(asciiStr, 'utf8'));\n    }\n\n    checkConditionBeforeStop() {\n        this.isSendAsyncRun = false;\n    }\n}\n"
  },
  {
    "path": "src/class/hardware/webUsbFlasher.ts",
    "content": "import { stringToUint8Array } from '../../util/hardwareUtils';\n\nconst filters = [\n    {\n        vendorId: 3368,\n        productId: 516,\n        classCode: 255,\n        subclassCode: 3,\n    },\n    {\n        vendorId: 3368,\n        productId: 516,\n        classCode: 255,\n        subclassCode: 0,\n    },\n];\n\nexport default class WebUsbFlasher {\n    private device: USBDevice;\n    private isTransfer: boolean;\n    private claimInterface: number;\n    private endpointNumber: number;\n    private flashingPercent: number;\n\n    private flashState: string;\n    constructor() {\n        this.isTransfer = false;\n        this.claimInterface = -1;\n        this.endpointNumber = -1;\n    }\n\n    // INFO: 연결된 기기에 파라미터로 넘어온 펌웨어를 플래싱\n    // TODO: 현재 유일한 지원기종인 microbitble에 맞춰져있음, 추후 지원기기가 늘어나면 로직수정 필요\n    async flashFirmware(firmwareUrl: string, percentCallback: Function) {\n        try {\n            if (!this.device) {\n                throw Error('device undefined');\n            }\n            const response = await fetch(firmwareUrl);\n            const hexData = await response.text();\n            const data = stringToUint8Array(hexData);\n\n            this.flashState = 'start';\n\n            let chunkSize = 62;\n            let offset = 0;\n            let sentPages = 0;\n\n            this.flashState = 'flashing';\n            while (offset < data.length) {\n                const end = Math.min(data.length, offset + chunkSize);\n                const nextPageData = data.slice(offset, end);\n                const cmdData = new Uint8Array(2 + nextPageData.length);\n                cmdData[0] = 0x8c;\n                cmdData[1] = nextPageData.length;\n                cmdData.set(nextPageData, 2);\n                // TODO: 퍼센트 로직도 분리\n                if (sentPages % 128 == 0) {\n                    this.flashingPercent = (offset / data.length) * 100;\n                    percentCallback && percentCallback(this.flashingPercent);\n                }\n                await this.writeBuffer(cmdData);\n                sentPages++;\n                offset = end;\n            }\n            this.flashingPercent = (offset / data.length) * 100;\n            percentCallback && percentCallback(this.flashingPercent);\n            this.flashState = 'end';\n\n            // INFO: close\n            const flashResult = await this.writeData([0x8b]);\n            if (flashResult[1] !== 0) {\n                throw Error('flash failed');\n            }\n\n            // INFO: reset\n            await this.writeData([0x89]);\n        } finally {\n            this.flashState = 'idle';\n        }\n    }\n\n    // INFO: 펌웨어 플래시전 webUsb로 기기와 브라우저를 연결\n    async connectUsb() {\n        // TODO: 지원기기가 늘어나면 vendorId 변수값으로 변경\n        this.device = await navigator.usb.requestDevice({\n            filters: [{ vendorId: 0x0d28 }],\n        });\n        await this.device.open();\n        await this.device.selectConfiguration(1);\n        this.findInterface();\n        await this.device.claimInterface(this.claimInterface);\n        const result = await this.writeData([0x8a, 1]);\n        if (result[1] !== 0) {\n            throw Error('device open failed');\n        }\n    }\n\n    findInterface() {\n        const filteredInterfaces = this.device.configurations[0].interfaces.filter(\n            (interfaceItem) => {\n                const alternateInterface = interfaceItem.alternates[0];\n\n                for (const filter of filters) {\n                    if (\n                        (filter.classCode === null ||\n                            alternateInterface.interfaceClass === filter.classCode) &&\n                        !(\n                            filter.subclassCode !== null &&\n                            alternateInterface.interfaceSubclass !== filter.subclassCode\n                        )\n                    ) {\n                        if (alternateInterface.endpoints.length === 0) {\n                            return true;\n                        }\n                        if (\n                            alternateInterface.endpoints.length === 2 &&\n                            alternateInterface.endpoints.every(\n                                (endpoint) => endpoint.packetSize === 64\n                            )\n                        ) {\n                            return true;\n                        }\n                    }\n                }\n\n                return false;\n            }\n        );\n\n        const iface = filteredInterfaces[filteredInterfaces.length - 1];\n        const altIface = iface.alternates[0];\n        if (altIface.endpoints.length) {\n            // study: endpoints 역할\n            this.isTransfer = true;\n            const epIn = altIface.endpoints.filter((e) => 'in' == e.direction)[0];\n            this.endpointNumber = epIn.endpointNumber;\n        }\n        this.claimInterface = iface.interfaceNumber;\n    }\n\n    async transfer(data: Uint8Array) {\n        if (this.isTransfer) {\n            await this.device.transferOut(this.endpointNumber, new Uint8Array(data));\n            return await this.device.transferIn(this.endpointNumber, 64);\n        } else {\n            await this.device.controlTransferOut(\n                {\n                    requestType: 'class',\n                    recipient: 'interface',\n                    request: 9,\n                    value: 512,\n                    index: this.claimInterface,\n                },\n                data\n            );\n\n            return await this.device.controlTransferIn(\n                {\n                    requestType: 'class',\n                    recipient: 'interface',\n                    request: 1,\n                    value: 256,\n                    index: this.claimInterface,\n                },\n                64\n            );\n        }\n    }\n\n    // TODO: buffer랑 합치기\n    async writeData(data: Array<number>): Promise<Uint8Array> {\n        const response = await this.transfer(new Uint8Array(data));\n        if (!response.data?.buffer) {\n            throw Error('writeData failed');\n        }\n        return new Uint8Array(response.data.buffer);\n    }\n\n    async writeBuffer(buffer: Uint8Array): Promise<Uint8Array> {\n        const response = await this.transfer(buffer);\n        if (!response.data?.buffer) {\n            throw Error('writeData failed');\n        }\n        return new Uint8Array(response.data.buffer);\n    }\n}\n"
  },
  {
    "path": "src/class/helper.js",
    "content": "import debounce from 'lodash/debounce';\n\nclass EntryBlockHelper {\n    constructor() {\n        this.visible = false;\n        Entry.addEventListener('workspaceChangeMode', () => {\n            if (this._blockView) {\n                this.renderBlock(this._blockView.type);\n            }\n        });\n        this.resize = debounce(this.resize, 300);\n    }\n\n    generateView(parentView) {\n        if (this.parentView_) {\n            return;\n        }\n        /** @type {!Element} parent view */\n        this.parentView_ = parentView;\n        const helper = this;\n        helper.blockHelpData = EntryStatic.blockInfo;\n        const blockHelperWrapper = Entry.createElement('div', 'entryBlockHelperWorkspaceWrapper');\n        const blockHelperView = Entry.createElement('div', 'entryBlockHelperWorkspace');\n        blockHelperWrapper.appendChild(blockHelperView);\n        this.view = blockHelperWrapper;\n        if (Entry.isForLecture) {\n            blockHelperView.addClass('lecture');\n        }\n        helper.parentView_.appendChild(blockHelperWrapper);\n\n        const blockHelperContent = Entry.createElement('div', 'entryBlockHelperContentWorkspace');\n        this._contentView = blockHelperContent;\n\n        const commandTitle = Entry.createElement('div');\n        commandTitle.addClass('entryBlockHelperTitle textModeElem');\n        commandTitle.textContent = 'Command';\n        blockHelperContent.appendChild(commandTitle);\n\n        blockHelperContent.addClass('entryBlockHelperIntro');\n        if (Entry.isForLecture) {\n            blockHelperContent.addClass('lecture');\n        }\n        blockHelperView.appendChild(blockHelperContent);\n        helper.blockHelperContent_ = blockHelperContent;\n        helper.blockHelperView_ = blockHelperView;\n\n        const blockHelperBlock = Entry.createElement('div', 'entryBlockHelperBlockWorkspace');\n        helper.blockHelperContent_.appendChild(blockHelperBlock);\n\n        const descTitle = Entry.createElement('div');\n        descTitle.addClass('entryBlockHelperTitle textModeElem');\n        descTitle.textContent = 'Explanation';\n        blockHelperContent.appendChild(descTitle);\n\n        const blockHelperDescription = Entry.createElement(\n            'div',\n            'entryBlockHelperDescriptionWorkspace'\n        );\n        blockHelperDescription.addClass('entryBlockHelperContent selectAble');\n        helper.blockHelperContent_.appendChild(blockHelperDescription);\n        blockHelperDescription.textContent = Lang.Helper.Block_click_msg;\n        this.blockHelperDescription_ = blockHelperDescription;\n\n        const elementsTitle = Entry.createElement('div');\n        elementsTitle.addClass('entryBlockHelperTitle textModeElem');\n        elementsTitle.textContent = 'Element';\n        blockHelperContent.appendChild(elementsTitle);\n        this._elementsTitle = elementsTitle;\n\n        this._elementsContainer = Entry.createElement('div', 'entryBlockHelperElementsContainer');\n\n        this._elementsContainer.addClass('entryBlockHelperContent textModeElem selectAble');\n        blockHelperContent.appendChild(this._elementsContainer);\n\n        const blockHelperLink = Entry.createElement(\n            'div',\n            'entryBlockHelperLinkWorkspace'\n        );\n        blockHelperLink.addClass('blockHelperLink');\n        const helperLink = Entry.createElement('a', 'entryBlockHelperLink');\n        helperLink.addClass('linkTextElem');\n        helperLink.setAttribute('target' ,'_blank');\n        blockHelperLink.appendChild(helperLink);\n        blockHelperContent.appendChild(blockHelperLink);\n        this.blockHelperLink_ = helperLink;\n\n        if (typeof CodeMirror !== 'undefined') {\n            const codeMirrorTitle = Entry.createElement('div');\n            codeMirrorTitle.addClass('entryBlockHelperTitle textModeElem');\n            codeMirrorTitle.textContent = 'Example Code';\n            blockHelperContent.appendChild(codeMirrorTitle);\n\n            const codeMirrorView = Entry.createElement(\n                'div',\n                'entryBlockHelperCodeMirrorContainer'\n            );\n            codeMirrorView.addClass('textModeElem');\n            blockHelperContent.appendChild(codeMirrorView);\n\n            this.codeMirror = CodeMirror(codeMirrorView, {\n                lineNumbers: true,\n                value: '',\n                mode: { name: 'python' },\n                indentUnit: 4,\n                theme: 'default',\n                viewportMargin: 10,\n                styleActiveLine: false,\n                readOnly: true,\n            });\n\n            this._doc = this.codeMirror.getDoc();\n            this._codeMirror = this.codeMirror;\n\n            const codeMirrorDescTitle = Entry.createElement('div');\n            codeMirrorDescTitle.addClass('entryBlockHelperTitle textModeElem');\n            codeMirrorDescTitle.textContent = 'Example Explanation';\n            blockHelperContent.appendChild(codeMirrorDescTitle);\n\n            this._codeMirrorDesc = Entry.createElement('div');\n            this._codeMirrorDesc.addClass('entryBlockHelperContent textModeElem selectAble');\n            blockHelperContent.appendChild(this._codeMirrorDesc);\n        }\n\n        this._renderView = new Entry.RenderView($(blockHelperBlock), 'LEFT_MOST');\n        this.code = new Entry.Code([]);\n        this.code.isFor = 'blockHelper';\n        this._renderView.changeCode(this.code);\n\n        this.first = true;\n    }\n\n    bindWorkspace(workspace) {\n        if (!workspace) {\n            return;\n        }\n\n        if (this._blockViewObserver) {\n            this._blockViewObserver.destroy();\n        }\n\n        this.workspace = workspace;\n        if (this._renderView) {\n            this._renderView.workspace = workspace;\n        }\n        this._blockViewObserver = workspace.observe(this, '_updateSelectedBlock', [\n            'selectedBlockView',\n        ]);\n    }\n\n    renderBlock(type) {\n        const description = Lang.Helper[type];\n        if (!type || !this.visible || !description || Entry.block[type].isPrimitive) {\n            return;\n        }\n\n        if (this.first) {\n            this.blockHelperContent_.removeClass('entryBlockHelperIntro');\n            this.first = false;\n        }\n\n        const code = this.code;\n        code.clear();\n        let def = Entry.block[type].def || { type };\n\n        if (this.workspace.getMode() === Entry.Workspace.MODE_VIMBOARD) {\n            this._contentView.addClass('textMode');\n            this.blockHelperDescription_.textContent = Lang.PythonHelper[`${type}_desc`];\n\n            let elements = Lang.PythonHelper[`${type}_elements`];\n            this._elementsContainer.textContent = '';\n            if (elements) {\n                this._elementsTitle.removeClass('entryRemove');\n                elements = elements.split('%next');\n                while (elements.length) {\n                    (function(elems) {\n                        const contents = elems.split('-- ');\n                        const box = Entry.createElement('div');\n                        box.addClass('entryBlockHelperElementsContainer');\n                        const left = Entry.createElement('div');\n\n                        left.textContent = contents[0];\n                        left.addClass('elementLeft');\n\n                        const right = Entry.createElement('div');\n                        right.addClass('elementRight');\n                        right.textContent = contents[1];\n                        box.appendChild(left);\n                        box.appendChild(right);\n                        this._elementsContainer.appendChild(box);\n                    }.bind(this)(elements.shift()));\n                }\n            } else {\n                this._elementsTitle.addClass('entryRemove');\n            }\n            this._codeMirrorDesc.textContent = Lang.PythonHelper[`${type}_exampleDesc`];\n\n            const exampleCode = Lang.PythonHelper[`${type}_exampleCode`];\n            this._codeMirror.setValue(exampleCode);\n            this.codeMirror.refresh();\n            def = Entry.block[type].pyHelpDef || def;\n        } else {\n            this._contentView.removeClass('textMode');\n            this.blockHelperDescription_.textContent = description;\n            const category = Entry.block[type].wikiClass || Entry.Utils.getBlockCategory(type);\n            if (category) {\n                this.blockHelperLink_.textContent = Lang.Helper.link_to_entry_wiki;\n                this.blockHelperLink_.href = Lang.Helper[`wiki_link_${category}`];\n            } else {\n                this.blockHelperLink_.textContent = '';\n                this.blockHelperLink_.href = '';\n            }\n        }\n\n        code.createThread([def]);\n\n        code.board.align();\n        code.board.resize();\n\n        this._renderView.align();\n        this._renderView.setDomSize();\n    }\n\n    getView() {\n        return this.view;\n    }\n\n    resize() {\n        this.codeMirror && this.codeMirror.refresh();\n    }\n\n    _updateSelectedBlock() {\n        const blockView = this.workspace.selectedBlockView;\n        // noinspection EqualityComparisonWithCoercionJS\n        if (!blockView || !this.visible || blockView == this._blockView) {\n            return;\n        }\n\n        const type = blockView.block.type;\n        this._blockView = blockView;\n        this.renderBlock(type);\n    }\n}\n\nexport default EntryBlockHelper;\n"
  },
  {
    "path": "src/class/hw.ts",
    "content": "﻿import HardwareSocketMessageHandler from './hardware/hardwareSocketMessageHandler';\nimport HardwareMonitor from './hardware/hardwareMonitor';\nimport createHardwarePopup from './hardware/functions/createHardwarePopup';\nimport ExternalProgramLauncher from './hardware/externalProgramLauncher';\n// eslint-disable-next-line prettier/prettier\nimport PopupHelper from './popup_helper';\nimport {\n    HardwareMessageData,\n    WebSocketMessage,\n    EntryHardwareBlockModule,\n    UnknownAny,\n} from '../../types/index';\n\nenum HardwareModuleType {\n    builtIn = 'builtin',\n    module = 'module',\n}\n\nenum HardwareStatement {\n    disconnected = 'disconnected',\n    socketConnected = 'socketConnected',\n    hardwareConnected = 'hardwareConnected',\n}\n\nexport default class Hardware {\n    get httpsServerAddress() {\n        return 'https://hw.playentry.org:23518';\n    } // 하드웨어 프로그램 접속용 주소\n    get httpsServerAddress2() {\n        return 'https://hardware.playentry.org:23518';\n    } // legacy\n    get httpServerAddress() {\n        return 'http://127.0.0.1:23518';\n    } // http 인 오프라인 접속용 주소\n    get cloudRoomIdKey() {\n        return 'entryhwRoomId';\n    }\n    private get socketConnectOption() {\n        return {\n            transports: ['websocket', 'polling'],\n            query: {\n                client: true,\n                roomId: this.sessionRoomId,\n            },\n        };\n    }\n\n    // socketIO 및 하드웨어 커넥션용\n    private readonly sessionRoomId: string;\n    private readonly socketConnectionRetryCount = 3;\n    private reconnectionTimeout: NodeJS.Timeout;\n    private programConnected: boolean;\n    private socket: SocketIOClient.Socket; // 실제 연결된 소켓\n    private socketMode: number;\n\n    // entryjs 내 하드웨어모듈 통신용\n    public portData: UnknownAny;\n    public sendQueue: UnknownAny;\n\n    // 현재 연결된 모듈 컨트롤용\n    public hwModule?: EntryHardwareBlockModule;\n    public communicationType: string; // 'manual' || 'auto'\n    private currentDeviceKey?: string;\n    private hwModuleType: HardwareModuleType;\n    private hwMonitor?: HardwareMonitor;\n\n    // 하드웨어 설치여부 확인용\n    // public programLauncher 는 ExternalProgramLauncher 만든 iframe view 에서 onload 로 호출한다\n    public programLauncher: ExternalProgramLauncher;\n    private popupHelper?: PopupHelper;\n\n    constructor() {\n        const prevRoomId = localStorage.getItem(this.cloudRoomIdKey);\n        this.sessionRoomId = prevRoomId || this._createRandomRoomId();\n        if (!prevRoomId) {\n            localStorage.setItem(this.cloudRoomIdKey, this.sessionRoomId);\n        }\n\n        this.programConnected = false;\n        this.communicationType = 'auto';\n        this.portData = {};\n        this.sendQueue = {};\n        this.hwModuleType = HardwareModuleType.builtIn;\n\n        this._initHardwareObject();\n        this._addEntryEventListener();\n    }\n\n    async _loadExternalHardwareBlock(moduleinfo: { name: string; file: any }) {\n        try {\n            await Entry.moduleManager.loadModuleFromLocalOrOnline(moduleinfo.name);\n        } catch (e) {\n            console.log(e);\n            Entry.toast.alert(\n                Lang.Msgs.hw_module_load_fail_title,\n                `${moduleinfo.name} ${Lang.Msgs.hw_module_load_fail_desc}`\n            );\n        }\n    }\n\n    retryConnect() {\n        this._initSocket();\n    }\n\n    openHardwareProgram(args?: { [key: string]: string }) {\n        this._alertUnderVersionUsed().then(() => {\n            this._executeHardware(args);\n\n            if (!this.socket || !this.socket.connected) {\n                setTimeout(() => {\n                    this._initSocket();\n                }, 1000);\n            }\n        });\n    }\n\n    /**\n     * 외부 하드웨어 모듈을 등록한다.\n     * 이때 기존 외부 하드웨어 모듈이 추가되어있는 경우를 대비하여,\n     * 현재 보여지고 있는 하드웨어 블록들을 전부 숨김처리한다.\n     * @param moduleObject\n     */\n    setExternalModule(moduleObject: EntryHardwareBlockModule) {\n        this.hwModule = moduleObject;\n        this.hwModuleType = HardwareModuleType.module;\n        this._banClassAllHardware();\n        Entry.dispatchEvent('hwChanged');\n    }\n\n    /**\n     * 하드웨어 블록메뉴의 노출상태를 변경한다.\n     * 최초 실행시 모든 하드웨어 블록 숨김 / 미연결 상태 버튼 출력\n     * 현재 하드웨어 로드가 외부 모듈에 의한 것인 경우는 연결이 해제되어도 블록숨김을 실행하지 않는다.\n     */\n    refreshHardwareBlockMenu() {\n        if (Entry.hwLite.getStatus() !== 'disconnected') {\n            console.log('canel refreshHardwareBlockMenu() for HwLITE');\n            return;\n        }\n\n        const workspace = Entry.getMainWS();\n        const blockMenu = workspace && workspace.blockMenu;\n\n        if (!blockMenu) {\n            return;\n        }\n\n        if (!this.hwModule) {\n            // NOTE 이 코드는 하드웨어 블록 초기화 작업도 겸하므로 삭제금지\n            this._banClassAllHardware();\n        }\n\n        const { disconnected, socketConnected, hardwareConnected } = HardwareStatement;\n        if (this.programConnected) {\n            if (this.hwModule) {\n                blockMenu.unbanClass(this.hwModule.name);\n                this._setHardwareDefaultMenu(hardwareConnected);\n            } else {\n                this._setHardwareDefaultMenu(socketConnected);\n            }\n        } else {\n            this._setHardwareDefaultMenu(disconnected);\n        }\n\n        blockMenu.hwCodeOutdated = true;\n        blockMenu._generateHwCode(true);\n        blockMenu.reDraw();\n    }\n\n    disconnectSocket() {\n        if (this.programConnected) {\n            Entry.propertyPanel && Entry.propertyPanel.removeMode('hw');\n            this.programConnected = false;\n            this.currentDeviceKey = undefined;\n\n            /*\n            entryjs 내에 존재하던 기존 하드웨어의 경우 원래 프로세스에 따라 연결 종료시 보여주지 않는다.\n            만약 외부모듈인 경우, 하드웨어가 연결종료 되더라도 블록은 남는다.\n             */\n            if (this.hwModuleType === HardwareModuleType.builtIn) {\n                this.hwModule = undefined;\n            }\n\n            this.socket && this.socket.close();\n            this.socket = undefined;\n\n            Entry.dispatchEvent('hwChanged');\n            Entry.toast.alert(\n                Lang.Msgs.hw_connection_termination_title,\n                Lang.Msgs.hw_connection_termination_desc,\n                false\n            );\n        }\n    }\n\n    /**\n     * @deprecated\n     */\n    setDigitalPortValue(port: any, value: any) {\n        console.warn('this function will be deprecated. please use Entry.hw.sendQueue directly.');\n        this.sendQueue[port] = value;\n        this.removePortReadable(port);\n    }\n\n    /**\n     * @deprecated\n     */\n    getAnalogPortValue(port: any) {\n        console.warn('this function will be deprecated. please use Entry.hw.portData directly.');\n        if (!this.programConnected || !this.hwModule) {\n            return 0;\n        }\n        return this.portData[`a${port}`];\n    }\n\n    /**\n     * @deprecated\n     */\n    getDigitalPortValue(port: any) {\n        console.warn('this function will be deprecated. please use Entry.hw.portData directly.');\n        if (!this.programConnected || !this.hwModule) {\n            return 0;\n        }\n        this.setPortReadable(port);\n        if (this.portData[port] !== undefined) {\n            return this.portData[port];\n        } else {\n            return 0;\n        }\n    }\n\n    /**\n     * @deprecated\n     */\n    setPortReadable(port: any) {\n        console.warn('this function will be deprecated. please control port state directly.');\n        if (!this.sendQueue.readablePorts) {\n            this.sendQueue.readablePorts = [];\n        }\n\n        let isPass = false;\n        for (const i in this.sendQueue.readablePorts) {\n            if (this.sendQueue.readablePorts[i] == port) {\n                isPass = true;\n                break;\n            }\n        }\n\n        if (!isPass) {\n            this.sendQueue.readablePorts.push(port);\n        }\n    }\n\n    /**\n     * @deprecated\n     */\n    removePortReadable(port: any) {\n        console.warn('this function will be deprecated. please use Entry.hw.sendQueue directly.');\n        if (!this.sendQueue.readablePorts && !Array.isArray(this.sendQueue.readablePorts)) {\n            return;\n        }\n        let target;\n        for (const i in this.sendQueue.readablePorts) {\n            if (this.sendQueue.readablePorts[i] == port) {\n                target = Number(i);\n                break;\n            }\n        }\n\n        if (target != undefined) {\n            this.sendQueue.readablePorts = this.sendQueue.readablePorts\n                .slice(0, target)\n                .concat(\n                    this.sendQueue.readablePorts.slice(\n                        target + 1,\n                        this.sendQueue.readablePorts.length\n                    )\n                );\n        }\n    }\n\n    update() {\n        if (!this.socket || this.socket.disconnected) {\n            return;\n        }\n\n        if (this.hwModule && this.hwModule.sendMessage) {\n            this.hwModule.sendMessage(this);\n        } else {\n            this._sendSocketMessage({\n                data: JSON.stringify(this.sendQueue),\n                mode: this.socketMode,\n                type: 'utf8',\n            });\n        }\n\n        this.hwModule && this.hwModule.afterSend && this.hwModule.afterSend(this.sendQueue);\n    }\n\n    closeConnection() {\n        this.socket?.close();\n    }\n\n    downloadConnector() {\n        Entry.dispatchEvent('hwDownload', 'hardware');\n    }\n\n    downloadGuide() {\n        Entry.dispatchEvent('hwDownload', 'manual');\n    }\n\n    downloadSource() {\n        Entry.dispatchEvent('hwDownload', 'ino');\n    }\n\n    setZero() {\n        this.hwModule?.setZero();\n    }\n\n    /**\n     * 디바이스의 연결상태를 체크한다.\n     * 만약 이미 바로 직전에 동일한 하드웨어와 연결된 경우는 dataHandler 로 데이터를 전송하기만 한다.\n     * 새로운 하드웨어의 연결인 경우는 연결 하드웨어를 치환하고 엔트리에 상태변경을 요청한다.\n     * @param data\n     */\n    checkDevice(data: HardwareMessageData) {\n        if (data.company === undefined) {\n            return;\n        }\n\n        const key = `${this._convertHexToString(data.company)}.${this._convertHexToString(\n            data.model\n        )}`;\n\n        if (this.currentDeviceKey && key === this.currentDeviceKey) {\n            if (this.hwModule && this.hwModule.dataHandler) {\n                this.hwModule.dataHandler(data);\n            }\n            return;\n        }\n\n        this.currentDeviceKey = key;\n        this.hwModule = Entry.HARDWARE_LIST[key];\n        if (!this.hwModule) {\n            return;\n        }\n        this.communicationType = this.hwModule.communicationType || 'auto';\n        this.setDeviceNameContent(true);\n        this._banClassAllHardware();\n        Entry.dispatchEvent('hwChanged');\n\n        if (Entry.propertyPanel && this.hwModule.monitorTemplate) {\n            this._setHardwareMonitorTemplate();\n        }\n        Entry.toast.success(Lang.Msgs.hw_connection_success, Lang.Msgs.hw_connection_success_desc2);\n    }\n\n    openHardwareDownloadPopup() {\n        if (Entry.events_.openHardWareDownloadModal) {\n            Entry.dispatchEvent('openHardWareDownloadModal');\n        } else {\n            this.popupHelper.show('hwDownload', true);\n        }\n    }\n\n    // INFO: 블록메뉴의 '연결한 하드웨어:' 블럭의 값을 세팅하는 함수.\n    // setName이 true이면 연결된 하드웨어명을, false이면 기본값(없음)으로 세팅한다.\n    setDeviceNameContent(setName: boolean) {\n        const deviceName = setName\n            ? this.hwModule.title[Lang.type]\n            : Lang.Blocks.hardware_device_name_content;\n        if (this.hwModule?.hasPracticalCourse && EntryStatic.isPracticalCourse) {\n            Entry.block.changeBlockText('hardware_device_name_content_sensor', deviceName);\n            Entry.block.changeBlockText('hardware_device_name_content_motor', deviceName);\n            Entry.block.changeBlockText('hardware_device_name_content_led', deviceName);\n            Entry.block.changeBlockText('hardware_device_name_content_melody', deviceName);\n        } else {\n            Entry.block.changeBlockText('hardware_device_name_content', deviceName);\n        }\n    }\n\n    private _initHardwareObject() {\n        const { hardwareEnable } = Entry;\n        this.popupHelper = createHardwarePopup(() => {\n            this.downloadConnector();\n        });\n        hardwareEnable && this._initSocket();\n    }\n\n    private _addEntryEventListener() {\n        // hwChanged 에 걸려있는 다른 이벤트 함수와 동일선상에 두기위함\n        Entry.addEventListener('hwChanged', this.refreshHardwareBlockMenu.bind(this));\n        Entry.addEventListener('stop', this.setZero.bind(this));\n    }\n\n    private _createRandomRoomId() {\n        return 'xxxxxxxxyx'.replace(/[xy]/g, (c) => {\n            const r = (Math.random() * 16) | 0;\n            const v = c === 'x' ? r : (r & 0x3) | 0x8;\n            return v.toString(16);\n        });\n    }\n\n    private _trySocketConnect(url: string) {\n        return new Promise((resolve, reject) => {\n            const socket = io.connect(url, this.socketConnectOption);\n            socket.io.reconnectionAttempts(this.socketConnectionRetryCount);\n            socket.io.reconnectionDelayMax(1000);\n            socket.io.timeout(1000);\n            socket.on('connect', () => {\n                this._handleSocketConnected(socket);\n                resolve();\n            });\n            socket.on('reconnect_failed', () => {\n                reject();\n            });\n        });\n    }\n\n    private _handleSocketConnected(socket: SocketIOClient.Socket) {\n        socket.removeEventListener('reconnect_failed');\n        socket.removeEventListener('connect');\n        // this._initHardware(socket);\n        this.socket = socket;\n        this._setSocketConnected();\n        if (Entry.playground && Entry.playground.object) {\n            Entry.playground.setMenu(Entry.playground.object.objectType);\n        }\n\n        socket.on('connect', () => {\n            this._setSocketConnected();\n        });\n\n        socket.on('mode', (mode: number) => {\n            if (this.socketMode === 0 && mode === 1) {\n                this._disconnectHardware();\n            }\n            this.socketMode = mode;\n        });\n\n        const messageHandler = new HardwareSocketMessageHandler(socket);\n        messageHandler.addEventListener('init', this._loadExternalHardwareBlock.bind(this));\n        messageHandler.addEventListener('state', async (statement, name) => {\n            /*\n            statement 로는 before_connect, connected 등 하드웨어 프로그램의 상태 전부가 오지만\n            WS 에서는 connected 외에 전부 socketConnected 상태로 머무르게 된다.\n             */\n            switch (statement) {\n                case 'disconnectHardware':\n                    this._disconnectHardware();\n                    break;\n                case 'connected':\n                    // init action 과 동일동작\n                    await this._loadExternalHardwareBlock(name);\n                    break;\n                default:\n                    break;\n            }\n        });\n\n        // 1.7.0 버전 이전 하드웨어 프로그램 종료로직 대응으로 남겨두어야 한다.\n        messageHandler.addEventListener('disconnect', this._disconnectHardware.bind(this));\n        messageHandler.addEventListener('data', (portData: HardwareMessageData) => {\n            this.portData = portData;\n            this.checkDevice(portData);\n            this._updatePortData(portData);\n            if (this.hwModule && this.hwModule.afterReceive) {\n                this.hwModule.afterReceive(portData);\n            }\n        });\n\n        socket.on('disconnect', () => {\n            // cloud PC 연결 클릭시 순간 disconnect 되고 재연결을 시도하기 위한 로직\n            this._setSocketClosed();\n            this.reconnectionTimeout = setTimeout(() => {\n                this._initSocket();\n            }, 1500);\n        });\n\n        socket.on('reconnect_failed', () => {\n            this._setSocketClosed();\n        });\n    }\n\n    private _setSocketConnected() {\n        this.programConnected = true;\n        console.log('Hardware Program Connected'); // 하드웨어 프로그램 연결 성공, 스테이터스 변화 필요\n        Entry.dispatchEvent('hwChanged');\n    }\n\n    private _setSocketClosed(needRedraw: boolean = true) {\n        this.programConnected = false;\n        this.hwModule = undefined;\n        this.currentDeviceKey = undefined;\n        needRedraw && Entry.dispatchEvent('hwChanged');\n    }\n\n    /**\n     * 이미 연결했던 소켓이 존재한다면 재연결을 시도한다.\n     * 연결성공했던 소켓이 없다면 전체 리스트를 순회하며 연결을 시도한다.\n     * @private\n     */\n    private _initSocket() {\n        if (this.socket) {\n            if (this.reconnectionTimeout) {\n                clearTimeout(this.reconnectionTimeout);\n                this.reconnectionTimeout = undefined;\n            }\n            this.socket.io.reconnection(true);\n            this.socket.connect();\n        } else {\n            const connectionTries = [this.httpsServerAddress, this.httpsServerAddress2];\n\n            // http 혹은 파일시스템 프로토콜에서 동작하는 경우, 로컬호스트 를 최우선 연결시도 한다.\n            if (['http:', 'file:'].indexOf(location.protocol) > -1) {\n                connectionTries.unshift(this.httpServerAddress);\n            } else {\n                connectionTries.push(this.httpServerAddress);\n            }\n\n            // 주소에 담겨져있는 순서대로 소켓 연결을 요청한다.\n            connectionTries\n                .reduce<Promise<boolean>>(async (prevPromise, address) => {\n                    const prevResult = await prevPromise;\n                    if (prevResult) {\n                        return true;\n                    }\n\n                    // NOTE : 하드웨어 웹연결과 충돌을 방지\n                    if (Entry.hwLite.getStatus() !== 'disconnected') {\n                        console.log('canel connectionTry for HwLITE');\n                        return;\n                    }\n\n                    try {\n                        await this._trySocketConnect(address);\n                        return true;\n                    } catch (e) {\n                        return !!(this.programConnected || this.socket);\n                    }\n                }, undefined)\n                .then((result) => {\n                    // 하드웨어 소켓 연결 시도 결과 반환 로직\n                    if (!result) {\n                        console.warn('All hardware socket connection failed');\n                        this._setSocketClosed();\n                    }\n                })\n                .catch(() => {\n                    console.error('Error occurred while try to connect hardware socket');\n                });\n        }\n    }\n\n    /**\n     * 하드웨어 버튼 노출상태를 변경한다.\n     * @param statement {HardwareStatement}\n     * @private\n     */\n    private _setHardwareDefaultMenu(statement: HardwareStatement) {\n        const workspace = Entry.getMainWS();\n        const blockMenu = workspace && workspace.blockMenu;\n\n        if (!blockMenu) {\n            return;\n        }\n\n        const { disconnected, socketConnected, hardwareConnected } = HardwareStatement;\n\n        switch (statement) {\n            case disconnected:\n                blockMenu.unbanClass('arduinoDisconnected', true);\n                blockMenu.banClass('arduinoConnected', true);\n                blockMenu.banClass('arduinoConnect', true);\n                Entry.hwLite?.isHwLiteSupportAgent()\n                    ? blockMenu.unbanClass('arduinoLiteSupported', true)\n                    : blockMenu.banClass('arduinoLiteSupported', true);\n                break;\n            case socketConnected:\n                blockMenu.banClass('arduinoLiteSupported', true);\n                blockMenu.banClass('arduinoDisconnected', true);\n                blockMenu.banClass('arduinoConnected', true);\n                blockMenu.unbanClass('arduinoConnect', true);\n                break;\n            case hardwareConnected:\n                blockMenu.banClass('arduinoLiteSupported', true);\n                blockMenu.banClass('arduinoDisconnected', true);\n                blockMenu.unbanClass('arduinoConnected', true);\n                blockMenu.banClass('arduinoConnect', true);\n                break;\n        }\n    }\n\n    /**\n     * 모든 하드웨어를 숨김처리한다. 현재 연결된 하드웨어도 예외는 없다.\n     * @private\n     */\n    private _banClassAllHardware() {\n        const workspace = Entry.getMainWS();\n        const blockMenu = workspace && workspace.blockMenu;\n        if (!blockMenu) {\n            return;\n        }\n\n        Object.values(Entry.HARDWARE_LIST || {}).forEach((hardware: any) => {\n            blockMenu.banClass(hardware.name, true);\n        });\n    }\n\n    private _disconnectHardware() {\n        if (this.hwModule) {\n            Entry.propertyPanel && Entry.propertyPanel.removeMode('hw');\n            this.currentDeviceKey = undefined;\n            this.hwModule = undefined;\n            this.setDeviceNameContent(false);\n            Entry.dispatchEvent('hwChanged');\n            Entry.toast.alert(\n                Lang.Msgs.hw_connection_termination_title,\n                Lang.Msgs.hw_connection_termination_desc,\n                false\n            );\n        }\n    }\n\n    private _sendSocketMessage(message: WebSocketMessage) {\n        if (this.programConnected && this.socket && !this.socket.disconnected) {\n            this.socket.emit('message', message);\n        }\n    }\n\n    private _updatePortData(data: HardwareMessageData) {\n        if (this.hwMonitor && Entry.propertyPanel && Entry.propertyPanel.selected === 'hw') {\n            this.hwMonitor.update(data, this.sendQueue);\n        }\n    }\n\n    private _setHardwareMonitorTemplate() {\n        if (!this.hwMonitor) {\n            this.hwMonitor = new HardwareMonitor(this.hwModule);\n        } else {\n            this.hwMonitor.setHwModule(this.hwModule);\n            this.hwMonitor.initView();\n        }\n        Entry.propertyPanel.addMode('hw', this.hwMonitor);\n        this.hwMonitor.generateViewByMode();\n    }\n\n    /**\n     * 버전 공지용 함수.\n     * 1.9.0 버전으로 올라가면서 SSL 인증서 문제로 과거버전은 소켓연결에 문제가 있음.\n     * 그에 따른 조치이기 때문에 추후 유저들이 1.9.0 버전의 사용비중이 높아진다면 삭제해도 무방하다.\n     * @returns {Promise<void>}\n     * @private\n     */\n    private _alertUnderVersionUsed() {\n        return new Promise((resolve) => {\n            const dontShowChecked = localStorage.getItem('skipNoticeHWOldVersion');\n            if (!dontShowChecked) {\n                const title = Lang.Msgs.hardware_need_update_title;\n                const content = Lang.Msgs.hardware_need_update_content;\n                Entry.modal\n                    .alert(content, title, {\n                        withDontShowAgain: true,\n                    })\n                    .then((data: { dontShowChecked: boolean }) => {\n                        const { dontShowChecked } = data || {};\n                        if (dontShowChecked) {\n                            localStorage.setItem('skipNoticeHWOldVersion', 'true');\n                        }\n                        resolve(null);\n                    });\n            } else {\n                resolve(null);\n            }\n        });\n    }\n\n    private _executeHardware(args?: { [key: string]: string }) {\n        this.programLauncher = new ExternalProgramLauncher();\n\n        const customSchemaArgsString = Object.entries({\n            roomId: this.sessionRoomId,\n            ...args,\n        }).reduce(\n            (result, [key, value]) =>\n                result === '' ? `${key}:${value}` : `${result}&${key}:${value}`,\n            ''\n        );\n\n        const entryHardwareUrl = `entryhw://?${customSchemaArgsString}`;\n        console.log('request Hardware using url custom schema.. : ', entryHardwareUrl);\n        this.programLauncher.executeUrl(entryHardwareUrl, () => this.openHardwareDownloadPopup());\n    }\n\n    private _convertHexToString(num: number | string) {\n        if (typeof num === 'string') {\n            return num.toUpperCase();\n        }\n\n        return num.toString(16).toUpperCase();\n    }\n}\n\nEntry.HW = Hardware;\n"
  },
  {
    "path": "src/class/hw_lite.ts",
    "content": "import { EntryHWLiteBaseModule, HWLiteStatus } from '../../types/index';\nimport ExtraBlockUtils from '../util/extrablockUtils';\nimport HardwareMonitor from './hardware/hardwareMonitor';\nimport WebUsbFlasher from './hardware/webUsbFlasher';\nimport WebSerialConnector from './hardware/webSerialConnector';\nimport WebApiConnector from './hardware/webApiConnector';\nimport WebBluetoothConnector from './hardware/webBluetoothConnector';\n\nconst ARDUINO_BOARD_IDS: string[] = ['010101', '040201', '080101'];\n\nexport default class HardwareLite {\n    private status: HWLiteStatus;\n    private webConnector: WebApiConnector;\n    private serial: WebSerialConnector;\n    private bluetooth: WebBluetoothConnector;\n    private flasher: WebUsbFlasher;\n    hwModule: EntryHWLiteBaseModule;\n    static setExternalModule: any;\n    static refreshHardwareLiteBlockMenu: any;\n    static banClassAllHardwareLite: any;\n    static isHwLiteSupportAgent: any;\n    private playground: any;\n    private hwMonitor?: HardwareMonitor;\n    static getStatus: any;\n    private customPromptPayload: String;\n\n    constructor(playground: any) {\n        this.playground = playground;\n        this.hwModule = null;\n        this.status = 'disconnected';\n        Entry.addEventListener('hwLiteChanged', this.refreshHardwareLiteBlockMenu.bind(this));\n        this.setExternalModule.bind(this);\n    }\n\n    setZero() {\n        this.hwModule?.setZero();\n    }\n\n    isActive(name: string) {\n        if (this.hwModule) {\n            const data = {};\n            // @ts-ignore\n            data[name] = this.hwModule;\n            return ExtraBlockUtils.isActive(name, data);\n        }\n        return false;\n    }\n    /**\n     * 모든 하드웨어를 숨김처리한다. 현재 연결된 하드웨어도 예외는 없다.\n     * @private\n     */\n    banClassAllHardwareLite() {\n        const workspace = Entry.getMainWS();\n        const blockMenu = workspace && workspace.blockMenu;\n        if (!blockMenu) {\n            return;\n        }\n        Object.values(Entry.HARDWARE_LITE_LIST || {}).forEach((hardware: any) => {\n            blockMenu.banClass(hardware.name, true);\n        });\n        ExtraBlockUtils.banAllBlocks(this.playground, Entry.HARDWARE_LITE_LIST);\n        blockMenu.reDraw();\n    }\n\n    setExternalModule(moduleObject: EntryHWLiteBaseModule) {\n        this.hwModule = moduleObject;\n        this.banClassAllHardwareLite();\n        Entry.block.changeBlockText('hardware_device_name_content', this.hwModule.title.ko);\n        Entry.dispatchEvent('hwLiteChanged');\n        this.setWebConnector();\n        this.setFlasher();\n        if (Entry.propertyPanel && this.hwModule.monitorTemplate) {\n            this._setHardwareMonitorTemplate();\n        }\n    }\n\n    getConnectFailedMenu() {\n        this.status = 'connectFailed';\n        this.refreshHardwareLiteBlockMenu();\n    }\n\n    setFirmwareDownloadButton(callback: Function) {\n        const workspace = Entry.getMainWS();\n        const blockMenu = workspace && workspace.blockMenu;\n        if (!blockMenu) {\n            return;\n        }\n        Entry.block.changeBlockEvent('arduino_lite_download_firmware', 'mousedown', async () => {\n            await callback();\n        });\n        blockMenu.changeTypeThreadByBlockKey('arduino_lite_download_firmware');\n    }\n\n    private _setHardwareMonitorTemplate() {\n        if (!this.hwMonitor) {\n            this.hwMonitor = new HardwareMonitor(this.hwModule);\n        } else {\n            this.hwMonitor.setHwModule(this.hwModule);\n            this.hwMonitor.initView();\n        }\n        Entry.propertyPanel.addMode('hw', this.hwMonitor);\n        this.hwMonitor.generateViewByMode();\n    }\n\n    _updatePortData() {\n        if (this.hwMonitor && Entry.propertyPanel && Entry.propertyPanel.selected === 'hw') {\n            this.hwMonitor.update(this.hwModule.getMonitorPort(), null);\n        }\n    }\n\n    isHwLiteSupportAgent() {\n        const userAgentString = navigator.userAgent.toLowerCase();\n\n        // INFO: 디바이스가 모바일이거나 일렉트론이면 1차적으로 제외\n        if (userAgentString.includes('mobile') || userAgentString.includes('electron')) {\n            return false;\n        } else if (\n            userAgentString.includes('whale') ||\n            userAgentString.includes('edge') ||\n            userAgentString.includes('chrome')\n        ) {\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    refreshHardwareLiteBlockMenu() {\n        const blockMenu = Entry.getMainWS()?.blockMenu;\n        if (!blockMenu) {\n            return;\n        }\n\n        switch (this.status) {\n            case 'disconnected': {\n                blockMenu.banClass('arduinoLiteConnected', true);\n                blockMenu.banClass('arduinoLiteConnectFailed', true);\n                blockMenu.banClass('arduinoLiteGuide', true);\n                blockMenu.unbanClass('arduinoLiteDisconnected', true);\n                blockMenu.unbanClass('arduinoDisconnected', true);\n                this.isHwLiteSupportAgent()\n                    ? blockMenu.unbanClass('arduinoLiteSupported', true)\n                    : blockMenu.banClass('arduinoLiteSupported', true);\n                this.banClassAllHardwareLite();\n                break;\n            }\n            case 'connected':\n                blockMenu.banClass('arduinoLiteConnectFailed', true);\n                blockMenu.banClass('arduinoLiteDisconnected', true);\n                blockMenu.banClass('arduinoDisconnected', true);\n                blockMenu.banClass('arduinoLiteSupported', true);\n                blockMenu.banClass('arduinoLiteGuide', true);\n                blockMenu.unbanClass('arduinoLiteConnected', true);\n                blockMenu.unbanClass(this.hwModule?.name, true);\n                break;\n            case 'connectFailed':\n                blockMenu.banClass('arduinoLiteDisconnected', true);\n                blockMenu.banClass('arduinoLiteConnected', true);\n                blockMenu.banClass('arduinoDisconnected', true);\n                blockMenu.banClass('arduinoLiteSupported', true);\n                blockMenu.unbanClass('arduinoLiteConnectFailed', true);\n                if (typeof this.hwModule?.id === 'string') {\n                    if (ARDUINO_BOARD_IDS.includes(this.hwModule.id)) {\n                        blockMenu.unbanClass('arduinoLiteGuide', true);\n                    }\n                }\n                // else if (this.hwModule?.id instanceof Array) {\n                //     for (const id in this.hwModule.id) {\n                //         if (ARDUINO_BOARD_IDS.includes(this.hwModule.id[id])) {\n                //             blockMenu.unbanClass('arduinoLiteGuide', true);\n                //             break;\n                //         }\n                //     }\n                // }\n                this.banClassAllHardwareLite();\n                break;\n        }\n        blockMenu.hwCodeOutdated = true;\n        blockMenu._generateHwCode(true);\n        blockMenu.reDraw();\n    }\n\n    async connect() {\n        if (this.status === 'connected') {\n            return;\n        }\n        try {\n            await this.webConnector.connect();\n            this.setStatus('connected');\n            this.refreshHardwareLiteBlockMenu();\n            await this.webConnector.initialDevice();\n            Entry.toast.success(\n                Lang.Msgs.hw_connection_success,\n                Lang.Msgs.hw_connection_success_desc2\n            );\n        } catch (error) {\n            console.error(error);\n            Entry.toast.alert(\n                Lang.Msgs.hw_connection_failed_title,\n                Lang.Msgs.hw_connection_failed_desc,\n                false\n            );\n            this.getConnectFailedMenu();\n        }\n    }\n\n    async disconnect() {\n        try {\n            Entry.hardwareLiteBlocks = [];\n            this.status = 'willDisconnect';\n            await this.webConnector?.disconnect();\n        } catch (err) {\n            console.error(err);\n        } finally {\n            this.hwModule = null;\n            this.customPromptPayload = null;\n            this.status = 'disconnected';\n            this.removeWebConnector();\n            this.removeFlasher();\n            Entry.dispatchEvent('hwLiteChanged');\n            Entry.toast.alert(\n                Lang.Msgs.hw_connection_termination_title,\n                Lang.Msgs.hw_connection_termination_desc,\n                false\n            );\n        }\n    }\n\n    addHardwareLiteModule(module: EntryHWLiteBaseModule) {\n        Entry.do('objectAddHardwareLiteBlocks', module);\n    }\n    removeHardwareLiteModule() {\n        Entry.do('objectRemoveHardwareLiteBlocks', this.hwModule);\n    }\n\n    setWebConnector() {\n        const webapiType = this.hwModule.webapiType;\n\n        switch (webapiType) {\n            case 'ble': {\n                if (!this.hwModule.bluetoothInfo) {\n                    console.error('Invalid bluetooth hwModule');\n                    this.getConnectFailedMenu();\n                    return;\n                }\n                this.bluetooth = new WebBluetoothConnector(this.hwModule, this);\n                this.webConnector = this.bluetooth;\n                break;\n            }\n            case 'serial':\n            case undefined: {\n                if (!this.hwModule.portData) {\n                    console.error('Invalid serial hwModule');\n                    this.getConnectFailedMenu();\n                    return;\n                }\n                this.serial = new WebSerialConnector(this.hwModule, this);\n                this.webConnector = this.serial;\n            }\n        }\n    }\n\n    removeWebConnector() {\n        this.webConnector = undefined;\n        this.serial = undefined;\n        this.bluetooth = undefined;\n    }\n\n    setFlasher() {\n        if (this.hwModule.supportFirmwareFlash) {\n            this.flasher = new WebUsbFlasher();\n        }\n    }\n    removeFlasher() {\n        this.flasher = undefined;\n    }\n\n    getStatus() {\n        return this.status;\n    }\n    setStatus(state: HWLiteStatus) {\n        this.status = state;\n    }\n\n    getCustomPromptPayload() {\n        return this.customPromptPayload;\n    }\n\n    setCustomPromptPayload(payload: String) {\n        this.customPromptPayload = payload;\n    }\n\n    // INFO: customPrompt 테스트용. entryjs 단독으로 테스트하는 경우 아래 함수를 사용\n    testCustomPromptPayload() {\n        if (!this.hwModule) {\n            window.alert('\"Entry.hwLite.hwModule\" is not set. use \"addHardwareLiteModule\" first.');\n            return;\n        }\n        if (!this.hwModule.customPrompt) {\n            window.alert(\n                'Entry.hwLite.hwModule.customPrompt is not set. check your hardware module.'\n            );\n            return;\n        }\n        const payload = window.prompt(\n            `${this.hwModule.customPrompt.title} \\n ${this.hwModule.customPrompt.description}`,\n            this.hwModule.customPrompt.defaultValue || ''\n        );\n        this.setCustomPromptPayload(payload);\n        console.log('Entry.hwLite.customPromptPayload : ', this.customPromptPayload);\n    }\n}\n\nEntry.HWLite = HardwareLite;\n"
  },
  {
    "path": "src/class/intro.ts",
    "content": "/**\n * 프로퍼티 패널쪽에서 프로젝트의 속성을 보여주는 뷰를 담당\n * @use entry-lms\n */\n\nimport { IEntry } from '../../types/index';\n\nclass EntryIntro implements IEntry.Intro {\n    public modes: any = {};\n    public selected: any = undefined;\n    private view_?: any;\n\n    generateView(introView: any) {\n        this.view_ = introView;\n        this.view_.addClass('entryPlaygroundIntro');\n    }\n\n    setView(view: any) {\n        if (this.view_.firstChild) {\n            this.view_.removeChild(this.view_.firstChild);\n        }\n        this.view_.addClass('active');\n        view.appendTo(this.view_);\n        Entry.windowResized.notify();\n    }\n\n    removeView() {\n        if (this.view_.firstChild) {\n            this.view_.removeChild(this.view_.firstChild);\n        }\n        this.view_.removeClass('active');\n    }\n}\n\nexport default EntryIntro;\nEntry.Intro = EntryIntro;\n"
  },
  {
    "path": "src/class/learning/Chart.js",
    "content": "import { BillBoard, Tree } from '@entrylabs/tool';\n\nexport default class LearningChart {\n    constructor(modalData, type = 'chart') {\n        if (type === 'tree') {\n            this.modal = this.createTree(modalData);\n        } else {\n            this.modal = this.createChart(modalData);\n        }\n        this.modal.show();\n    }\n\n    show() {\n        this.modal.show();\n    }\n\n    hide() {\n        this.modal.hide();\n    }\n\n    destroy() {\n        this.modal.hide();\n        this.modal = null;\n    }\n\n    load(data) {\n        this.modal.setData(data);\n    }\n\n    createChart({ title = '', description = '', source }) {\n        const container = Entry.Dom('div', {\n            class: 'entry-learning-chart',\n            parent: $(Entry.modalContainer),\n        })[0];\n\n        return new BillBoard({\n            data: {\n                source,\n                title,\n                description,\n                togglePause: () => Entry.engine.togglePause(),\n                stop: () => Entry.engine.toggleStop(),\n                isIframe: self !== top,\n            },\n            container,\n        });\n    }\n\n    createTree({ title = '', source }) {\n        const container = Entry.Dom('div', {\n            class: 'entry-learning-chart',\n            parent: $(Entry.modalContainer),\n        })[0];\n\n        return new Tree({\n            data: {\n                source,\n                title,\n                togglePause: () => Entry.engine.togglePause(),\n                stop: () => Entry.engine.toggleStop(),\n                isIframe: self !== top,\n            },\n            container,\n        });\n    }\n}\n"
  },
  {
    "path": "src/class/learning/Cluster.js",
    "content": "import { kmpp } from 'skmeans/kinit';\n// import { kmpp } from 'skmeans/dist/node/kinit';\nimport floor from 'lodash/floor';\nimport _toNumber from 'lodash/toNumber';\nimport _isNaN from 'lodash/isNaN';\nimport LearningView from './LearningView';\nimport Chart from './Chart';\nimport DataTable from '../DataTable';\n\nconst GRAPH_COLOR = [\n    '#4f80ff',\n    '#f16670',\n    '#6e5ae6',\n    '#00b6b1',\n    '#9fbaff',\n    '#fcad93',\n    '#c5b4ff',\n    '#b3c3cd',\n    '#2d51ac',\n    '#a23941',\n    '#423496',\n    '#2a7d7f',\n];\n\nexport const classes = [\n    'ai_learning_train',\n    'ai_learning_cluster',\n    'cluster_attr_1',\n    'cluster_attr_2',\n    'cluster_attr_3',\n    'cluster_attr_4',\n    'cluster_attr_5',\n    'cluster_attr_6',\n    'ai_learning_train_chart',\n];\n\nclass Cluster {\n    #attrLength = 0;\n    #trainParam = null;\n    #result = {};\n    #table = {};\n    #trainCallback;\n    #chart = null;\n    #isTrained = false;\n    #chartEnable = false;\n    #view = null;\n    #predictResult = null;\n    #fields = [];\n    #name = '';\n\n    constructor(params = {}) {\n        this.#view = new LearningView({ name: params.name || '', status: 0 });\n        // 정지시 data 초기화.\n        Entry.addEventListener('stop', () => {\n            this.init({ ...params });\n        });\n        this.init({ ...params });\n    }\n\n    init({ name, result, table, trainParam }) {\n        this.#name = name;\n        this.#trainParam = trainParam;\n        this.#result = result;\n        this.#table = table;\n        this.#trainCallback = (value) => {\n            this.#view.setValue(value);\n        };\n        this.#isTrained = true;\n\n        this.#attrLength = table?.select?.[0]?.length || 0;\n        if (this.#attrLength === 2) {\n            this.#chartEnable = true;\n        }\n        this.#fields = table?.select?.[0]?.map((index) => table?.fields[index]);\n    }\n\n    setTable() {\n        const tableSource = DataTable.getSource(this.#table.id);\n        if (this.#table?.fieldsInfo?.length !== tableSource?.fields?.length) {\n            Entry.toast.alert(Lang.Msgs.warn, Lang.AiLearning.train_param_error);\n            throw Error(Lang.AiLearning.train_param_error);\n        }\n        this.#table.data = tableSource.rows;\n    }\n\n    destroy() {\n        this.#view.destroy();\n        if (this.#chart) {\n            this.#chart.destroy();\n            this.#chart = null;\n        }\n    }\n\n    setVisible(visible) {\n        this.#view.setVisible(visible);\n    }\n\n    unbanBlocks(blockMenu) {\n        blockMenu.unbanClass(`ai_learning_train`);\n        blockMenu.unbanClass(`ai_learning_cluster`);\n        blockMenu.unbanClass(`cluster_attr_${this.#attrLength}`);\n        if (this.#chartEnable) {\n            blockMenu.unbanClass('ai_learning_train_chart');\n        }\n    }\n\n    isTrained() {\n        return this.#isTrained;\n    }\n\n    openChart() {\n        if (!this.#chartEnable) {\n            return;\n        }\n        if (!this.#chart) {\n            const { k } = this.#trainParam;\n            this.#chart = new Chart({\n                source: this.chartData,\n                title: Lang.AiLearning.chart_title,\n                description: `\n                    <em>${Lang.AiLearning.cluster_number}</em>   ${k}\n                    ${this.#fields.map(\n                        (field, index) =>\n                            `<em>${Lang.AiLearning.model_attr_str} ${index + 1}</em>${field}`\n                    )}\n                `,\n            });\n        } else {\n            this.#chart.show();\n        }\n    }\n\n    closeChart() {\n        this.#chart?.hide();\n    }\n\n    setTrainOption(type, value) {\n        this.#trainParam = {\n            ...this.#trainParam,\n            [type]: value,\n        };\n    }\n\n    getTrainOption() {\n        return this.#trainParam;\n    }\n\n    getTrainResult() {\n        return this.#result;\n    }\n\n    getResult() {\n        return this.#predictResult;\n    }\n\n    train() {\n        this.setTable();\n        this.#trainCallback(1);\n        this.#isTrained = false;\n        const { data, select } = this.#table;\n        const filtered = data.filter(\n            (row) => !select.flat().some((selected) => _isNaN(_toNumber(row[selected])))\n        );\n        const [attr] = select;\n\n        const { centroids, indexes } = kmeans(\n            filtered.map((row) => attr.map((i) => parseFloat(row[i]) || 0)),\n            this.#trainParam\n        );\n        this.#result = {\n            graphData: convertGraphData(filtered, centroids, indexes, attr),\n            centroids,\n        };\n        this.#isTrained = true;\n        const { k } = this.#trainParam;\n        this.#chart?.load({\n            source: this.chartData,\n            description: `\n                    <em>${Lang.AiLearning.cluster_number}</em>   ${k}\n                    ${this.#fields.map(\n                        (field, index) =>\n                            `<em>${Lang.AiLearning.model_attr_str} ${index + 1}</em>${field}`\n                    )}\n                `,\n        });\n        this.#trainCallback(100);\n    }\n\n    predict(arr = []) {\n        if (!this.isTrained) {\n            return;\n        }\n        const { k } = this.#trainParam;\n        const { centroids } = this.#result;\n\n        this.#predictResult = predictCluster(arr, k, centroids) + 1;\n        return this.#predictResult;\n    }\n\n    findColor(id, a, b) {\n        const { centroids, graphData } = this.#result;\n        if (id === 'y') {\n            const { type = 0 } =\n                graphData?.find(({ x, y }) => String(x) === String(a) && String(y) === String(b)) ||\n                {};\n            return GRAPH_COLOR[type];\n        } else if (id === 'centroid' && b) {\n            const type = centroids?.findIndex(([x]) => String(x) === String(a)) || 0;\n            return GRAPH_COLOR[type];\n        }\n        return undefined;\n    }\n\n    get chartData() {\n        return {\n            data: {\n                type: 'scatter',\n                json: this.#result.graphData,\n                keys: { value: ['y', 'centroid'], x: 'x' },\n                color: (color, d) => this.findColor(d.id, d.x, d.value) || color,\n                labels: false,\n            },\n            options: {\n                point: {\n                    pattern: [\n                        'circle',\n                        // eslint-disable-next-line max-len\n                        \"<g><circle cx='10' cy='10' r='10'></circle><rect x='5' y='5' width='10' height='10' style='fill:#fff'></rect></g>\",\n                    ],\n                },\n                legend: {\n                    show: false,\n                },\n                tooltip: {\n                    contents: (data) => {\n                        const [{ x, value, id }] = data;\n                        if (id === 'centroid' && value) {\n                            const { centroids } = this.#result;\n                            const type = centroids?.findIndex(([a, b]) => x === a && value === b);\n                            return `\n                                <div class=\"chart_handle_wrapper\">\n                                    ${Lang.AiLearning.centriod} ${type + 1}| ${\n                                this.#fields[0]\n                            }: ${x}, ${this.#fields[1]}: ${value}\n                                <div>\n                            `;\n                        }\n                        return `\n                            <div class=\"chart_handle_wrapper\">\n                                ${this.#fields[0]}: ${x}, ${this.#fields[1]}: ${value}\n                            <div>\n                        `;\n                    },\n                },\n                axis: {\n                    x: {\n                        tick: {\n                            fit: false,\n                            count: 5,\n                        },\n                    },\n                },\n                grid: {\n                    x: {\n                        show: true,\n                    },\n                    y: {\n                        show: true,\n                    },\n                },\n            },\n        };\n    }\n}\n\nexport default Cluster;\n\nfunction convertGraphData(data, centroids, indexes, attr) {\n    return data\n        .map((cur, index) =>\n            cur.reduce(\n                (acc, cur, idx) => {\n                    if (idx === attr[0]) {\n                        acc.x = cur;\n                    } else if (idx === attr[1]) {\n                        acc.y = cur;\n                    }\n                    return acc;\n                },\n                { index, type: indexes[index] }\n            )\n        )\n        .concat(\n            centroids.map(([x = 0, centroid = 0], type) => ({\n                x,\n                centroid,\n                type,\n            }))\n        );\n}\n\nfunction eudist(a, b) {\n    let sum = 0;\n    for (let i = 0; i < a.length; i++) {\n        const d = (a[i] || 0) - (b[i] || 0);\n        sum += d * d;\n    }\n\n    return sum;\n}\n\nfunction predictCluster(arr, k, centroids) {\n    let min = Infinity;\n    let closestCentroidIndex = 0;\n    for (let i = 0; i < k; i++) {\n        const dist = eudist(arr, centroids[i]);\n        if (dist < min) {\n            min = dist;\n            closestCentroidIndex = i;\n        }\n    }\n    return closestCentroidIndex;\n}\n\nfunction kmeans(inputs, trainParam) {\n    const dim = inputs[0].length;\n    let centroids = [];\n\n    if (!trainParam.initialCentroids) {\n        const _idxs = {};\n\n        while (centroids.length < trainParam.k) {\n            const idx = Math.floor(Math.random() * inputs.length);\n\n            if (!_idxs[idx]) {\n                _idxs[idx] = true;\n                centroids.push(inputs[idx].slice());\n            }\n        }\n    } else if (trainParam.initialCentroids === 'random') {\n        const maxs = new Array(dim).fill(-Infinity);\n        const mins = new Array(dim).fill(Infinity);\n        for (let i = 0; i < dim; i++) {\n            for (let j = 0; j < inputs.length; j++) {\n                if (inputs[j][i] < mins[i]) {\n                    mins[i] = inputs[j][i];\n                }\n                if (inputs[j][i] > maxs[i]) {\n                    maxs[i] = inputs[j][i];\n                }\n            }\n        }\n\n        for (let i = 0; i < trainParam.k; i++) {\n            const temp = [];\n            for (let j = 0; j < dim; j++) {\n                temp.push(Math.random() * (maxs[j] - mins[j]) + mins[j]);\n            }\n            centroids.push(temp);\n        }\n    } else if (trainParam.initialCentroids === 'kmpp') {\n        centroids = kmpp(\n            inputs.map((e) => e.slice()),\n            trainParam.k\n        );\n    } else {\n        centroids = trainParam.initialCentroids;\n    }\n\n    let indexes = new Array(inputs.length).fill(0);\n\n    let iter = 0;\n    let maxIter = trainParam.maxIter || 10000;\n    let conv = false;\n    while (!conv && iter < maxIter) {\n        // copy old centroids\n        let oldCentroids = centroids.map((e) => e.slice());\n\n        // set inputs idx (closest centroid index)\n        for (let i = 0; i < inputs.length; i++) {\n            indexes[i] = predictCluster(inputs[i], trainParam.k, centroids);\n        }\n\n        // move centroid to avg inputs\n        let sums = Array.from(new Array(trainParam.k), () => new Array(dim).fill(0));\n        let counts = new Array(trainParam.k).fill(0);\n\n        for (let i = 0; i < inputs.length; i++) {\n            counts[indexes[i]]++;\n            for (let j = 0; j < dim; j++) {\n                sums[indexes[i]][j] += inputs[i][j];\n            }\n        }\n\n        for (let i = 0; i < trainParam.k; i++) {\n            for (let j = 0; j < dim; j++) {\n                centroids[i][j] = floor(sums[i][j] / counts[i], 2);\n            }\n        }\n\n        // check conv\n        let centroidsUpdateDistance = 0;\n        centroids.forEach((e, i) => {\n            centroidsUpdateDistance += eudist(e, oldCentroids[i]);\n        });\n\n        if (centroidsUpdateDistance === 0) {\n            conv = true;\n        }\n\n        if (trainParam.onIterEnd) {\n            trainParam.onIterEnd(\n                oldCentroids.map((e) => e.slice()),\n                centroids.map((e) => e.slice())\n            );\n        }\n\n        iter++;\n    }\n\n    return {\n        iter,\n        indexes,\n        centroids,\n    };\n}\n"
  },
  {
    "path": "src/class/learning/DecisionTree.js",
    "content": "import * as tf from '@tensorflow/tfjs';\nimport _floor from 'lodash/floor';\nimport _max from 'lodash/max';\nimport _sum from 'lodash/sum';\nimport _mean from 'lodash/mean';\nimport _toNumber from 'lodash/toNumber';\nimport _isNaN from 'lodash/isNaN';\nimport LearningBase from './LearningBase';\nimport { DecisionTreeClassifier as DTClassifier } from 'ml-cart';\nimport Utils from './Utils';\nimport Chart from './Chart';\n\nexport const classes = [\n    'ai_learning_train',\n    'ai_learning_decisiontree',\n    'decisiontree_attr_1',\n    'decisiontree_attr_2',\n    'decisiontree_attr_3',\n    'decisiontree_attr_4',\n    'decisiontree_attr_5',\n    'decisiontree_attr_6',\n];\n\nclass DecisionTree extends LearningBase {\n    type = 'decisiontree';\n\n    init({ name, url, result, table, trainParam, modelId, loadModel }) {\n        this.name = name;\n        this.trainParam = trainParam;\n        this.result = result;\n        this.table = table;\n        this.loadModel = loadModel;\n        this.trainCallback = (value) => {\n            this.view.setValue(value);\n        };\n        this.trained = true;\n        this.attrLength = table?.select?.[0]?.length || 0;\n\n        this.fields = table?.select?.[0]?.map((index) => table?.fields[index]);\n        this.predictFields = table?.select?.[1]?.map((index) => table?.fields[index]);\n        if (this.url !== url || this.modelId !== modelId) {\n            this.load(url, modelId);\n            this.url = url;\n            this.modelId = modelId;\n        }\n        if (!Utils.isWebGlSupport()) {\n            tf.setBackend('cpu');\n        }\n    }\n\n    generateTree() {\n        const { graphData, fields, valueMap } = this.result;\n        this.tree = new Chart(\n            {\n                source: {\n                    graphData,\n                    fields,\n                    valueMap,\n                },\n                title: Lang.AiLearning.tree_title,\n            },\n            'tree'\n        );\n    }\n\n    openChart() {\n        if (!this.tree) {\n            this.generateTree();\n        } else {\n            this.tree.show();\n        }\n    }\n\n    closeChart() {\n        this.tree?.hide();\n    }\n\n    destroy() {\n        if (this.tree) {\n            this.tree.destroy();\n            this.tree = null;\n        }\n        super.destroy();\n    }\n\n    async train() {\n        this.setTable();\n        this.trained = false;\n        if (this.tree) {\n            this.tree.destroy();\n            this.tree = null;\n        }\n        this.trainCallback(1);\n        const {\n            testRate = 0.2,\n            maxDepth = 3,\n            minNumSamples = 3,\n            epochs = 1,\n            batchSize = 1,\n        } = this.trainParam;\n        const { trainX, trainY, testArr, select, fields, valueMap, numClass } = getData(\n            testRate,\n            this.table\n        );\n        this.valueMap = Object.fromEntries(\n            Object.entries(valueMap).map(([key, value]) => [value, key])\n        );\n        this.model = createModel(maxDepth, minNumSamples);\n        this.model?.train(trainX, trainY);\n\n        const { confusionMatrix, score } = evaluate(this.model, testArr, numClass);\n        this.trained = true;\n        this.trainCallback(100);\n        const { accuracy, f1, precision, recall } = score;\n        this.result = {\n            graphData: this.model.toJSON().root,\n            select,\n            fields,\n            confusionMatrix,\n            accuracy,\n            f1,\n            valueMap: this.valueMap,\n            precision,\n            recall,\n        };\n    }\n\n    async load(url, modelId) {\n        const data = await this.loadModel({ url, modelId });\n        if (!data) {\n            return;\n        }\n        const { model, result } = data;\n        this.model = DTClassifier.load(model);\n        this.valueMap = result?.valueMap;\n        this.result = {\n            ...result,\n            graphData: this.model?.toJSON().root,\n        };\n    }\n\n    async predict(array) {\n        if (!this.model) {\n            throw new Error(\"can't predict: no model\");\n        }\n        const xs = [array];\n        const preds = this.model.predict(xs);\n        this.predictResult = preds.map((target) => ({\n            className: this.valueMap[target + 1],\n            probability: 1,\n        }));\n    }\n}\n\nexport default DecisionTree;\n\nfunction createModel(maxDepth, minNumSamples) {\n    return new DTClassifier({\n        gainFunction: 'gini', // 'gini' Only\n        maxDepth,\n        minNumSamples,\n    });\n}\n\nfunction getData(testRate = 0.2, data) {\n    const tempMap = {};\n    const tempMapCount = {};\n    const { select = [[0], [1]], data: table, fields } = data;\n    const [attr, predict] = select;\n    const filtered = table.filter(\n        (row) => !select[0].some((selected) => _isNaN(_toNumber(row[selected])))\n    );\n    const dataArray = filtered\n        .map((row) => ({\n            x: attr.map((i) => parseFloat(row[i]) || 0),\n            y: Utils.stringToNumber(predict[0], row[predict[0]], tempMap, tempMapCount),\n        }))\n        .map((row) => ({\n            x: row.x,\n            y: row.y - 1,\n        }));\n    const [train, test] = sliceArray(dataArray, testRate);\n\n    return {\n        trainX: train.map((v) => v.x),\n        trainY: train.map((v) => v.y),\n        testArr: test,\n        select,\n        fields,\n        valueMap: { ...tempMap[predict[0]] },\n        numClass: tempMapCount[predict[0]] || 1,\n    };\n}\n\nfunction sliceArray(dataArray, testRate) {\n    Utils.shuffle(dataArray);\n    const testNum = Math.floor(dataArray.length * testRate);\n    const testArr = dataArray.slice(0, testNum);\n    const trainArr = dataArray.slice(testNum, dataArray.length);\n    return [trainArr, testArr];\n}\n\nfunction evaluate(model, validateData = [{ x: 0, y: 0 }], numClass) {\n    const xs = validateData.map((data) => data.x);\n    const ys = validateData.map((data) => data.y);\n    const predictYs = model.predict(xs);\n    const length = predictYs.length;\n    // Confusion Matrix 생성\n    const confusionMatrix = Array(numClass)\n        .fill(0)\n        .map(() => Array(numClass).fill(0));\n\n    for (let idx = 0; idx < length; idx++) {\n        confusionMatrix[ys[idx]][predictYs[idx]]++;\n    }\n    const score = Utils.getScores(confusionMatrix, numClass);\n    return { confusionMatrix, score };\n}\n"
  },
  {
    "path": "src/class/learning/ImageLearning.js",
    "content": "import * as tf from '@tensorflow/tfjs';\nimport VideoUtils from '@entrylabs/legacy-video';\nimport MediaPipeUtils from '../../util/mediaPipeUtils';\nconst mediaPipeUtils = MediaPipeUtils.getInstance();\nexport const classes = [\n    'ai_learning_image'\n];\nconst SCALAR_VALUE = 127.5;\nconst SIZE = 224;\nclass ImageLearning {\n    #type = null;\n    #url = '';\n    #labels = [];\n    #popup = null;\n    #result = [];\n    #axis = 0;\n    #isPredicting = false;\n    #captureCanvas;\n    #captureTimeoutClear;\n    constructor({ url, labels, type }) {\n        this.#type = type;\n        this.#url = url;\n        this.#labels = labels;\n        this.load(url);\n        Entry.addEventListener('stop', () => {\n            this.#result = [];\n            this.#isPredicting = false;\n        });\n        if (!isWebGlSupport()) {\n            tf.setBackend('cpu');\n        }\n    }\n\n    get labels() {\n        return this.#labels;\n    }\n\n    getResult(index) {\n        const result = this.#result.length ? this.#result : this.#popup?.result || [];\n        const defaultResult = { probability: 0, className: '' };\n        if (index !== undefined && index > -1) {\n            return (\n                result.find(({ className }) => className === this.#labels[index]) || defaultResult\n            );\n        }\n        return result[0] || defaultResult;\n    }\n\n    unbanBlocks(blockMenu) {\n        blockMenu.unbanClass(`ai_learning_classification`);\n        if (this.#type) {\n            blockMenu.unbanClass(`ai_learning_${this.#type}`);\n        }\n    }\n\n    openInputPopup() {\n        Entry.dispatchEvent('openMLInputPopup', {\n            type: 'image',\n            predict: async (canvas) => {\n                this.#result = await this.predict(canvas);\n            },\n            url: this.#url,\n            labels: this.#labels,\n            setResult: (result) => {\n                this.#result = result;\n            },\n        });\n    }\n\n    getVideo() {\n        if (VideoUtils.isInitialized) {\n            return VideoUtils.video;\n        }\n        if (mediaPipeUtils.isInitialized) {\n            return mediaPipeUtils.video;\n        }\n        return null;\n    }\n    async startPredict() {\n        if (!this.isLoaded || this.#isPredicting) {\n            return false;\n        }\n\n        this.#isPredicting = true;\n        if (!this.captureCanvas) {\n            this.#captureCanvas = document.createElement('canvas');\n            this.#captureCanvas.width = SIZE;\n            this.#captureCanvas.height = SIZE;\n        }\n\n        this.#captureTimeoutClear = Entry.Utils.asyncAnimationFrame(async () => {\n            const video = this.getVideo();\n            if (!video) {\n                return;\n            }\n            const context = this.#captureCanvas.getContext('2d');\n            context.drawImage(video, 0, 0, SIZE, SIZE);\n\n            this.#result = await this.predict(this.#captureCanvas);\n        });\n\n        return this.#result;\n    }\n\n    async predict(canvas) {\n        tf.engine().startScope();\n        const tensor = await this.preprocess(canvas);\n        const logits = this.model.predict(tensor);\n        const result = await this.namePredictions(logits);\n        logits.dispose();\n        tf.engine().endScope();\n        return result;\n    }\n\n    stopPredict() {\n        this.#result = [];\n        this.#isPredicting = false;\n        this.#captureTimeoutClear && this.#captureTimeoutClear();\n    }\n\n    async namePredictions(logits) {\n        const values = Array.from(await logits.data());\n        return values\n            .map((probability, index) => ({\n                className: this.#labels[index] || index,\n                probability,\n            }))\n            .sort((a, b) => a.probability > b.probability ? -1 : a.probability < b.probability ? 1 : 0);\n    }\n\n    async preprocess(canvas) {\n        return tf.tidy(() => {\n            const offset = tf.scalar(SCALAR_VALUE);\n            return tf.browser\n                .fromPixels(canvas)\n                .toFloat()\n                .sub(offset)\n                .div(offset)\n                .expandDims(this.#axis);\n        });\n    }\n\n    async load(url) {\n        this.model = await tf.loadLayersModel(url);\n        this.isLoaded = true;\n    }\n\n    async reload(url) {\n        this.model = await tf.loadLayersModel(url || this.#url);\n        this.isLoaded = true;\n    }\n}\n\nexport default ImageLearning;\n\nfunction isWebGlSupport() {\n    try {\n        const currentCanvas = document.createElement('canvas');\n        return !!currentCanvas.getContext('webgl', { premultipliedalpha: false });\n    } catch (e) {\n        console.log('error', e);\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/class/learning/InputPopup.js",
    "content": "import PopupHelper from '../popup_helper';\n\nconst MlPopup = class InputPopup {\n    #popupKey = 'ai_learning';\n\n    constructor(source) {\n        this.generatePopupView(source);\n    }\n\n    open() {\n        this.popupHelper.show(this.#popupKey);\n    }\n\n    generatePopupView({ url, labels, type, recordTime, setResult }) {\n        if (!this.popupHelper) {\n            if (window.popupHelper) {\n                this.popupHelper = window.popupHelper;\n            } else {\n                this.popupHelper = new PopupHelper(true);\n            }\n        }\n        let isPauseClicked = false;\n        this.popupHelper.addPopup(this.#popupKey, {\n            type: 'confirm',\n            title: Lang.Blocks.learn_popup_title,\n            onShow: () => {\n                this.popupHelper.addClass('learning_popup');\n                isPauseClicked = false;\n                localStorage.setItem(\n                    this.#popupKey,\n                    JSON.stringify({ url, labels, type, recordTime })\n                );\n                this.isLoading = true;\n                setResult && setResult([]);\n                if (Entry.engine.state == 'run') {\n                    Entry.engine.togglePause({ visible: false });\n                }\n            },\n            closeEvent: () => {\n                this.isLoading = false;\n                if (Entry.engine.state == 'pause' && !isPauseClicked) {\n                    Entry.engine.togglePause({ visible: false });\n                }\n            },\n            setPopupLayout: (popup) => {\n                const content = Entry.Dom('div', {\n                    class: 'contentArea',\n                });\n                const iframe = Entry.Dom('iframe', {\n                    class: `learningInputPopup ${type}`,\n                    src: `/learning/popup/${type}`\n                });\n                $(iframe).on('load', ({ target }) => {\n                    target.contentWindow.addEventListener(\n                        'message',\n                        ({ data: eventData = {} }) => {\n                            if (typeof eventData !== 'string') {\n                                return;\n                            }\n                            const { key, data } = JSON.parse(eventData);\n                            if (key === 'predict') {\n                                setResult && setResult(data);\n                                this.popupHelper.hide();\n                            }\n                            if (key === 'stop') {\n                                this.popupHelper.hide();\n                                Entry.engine.toggleStop();\n                            }\n                            if (key === 'pause') {\n                                if (!isPauseClicked) {\n                                    isPauseClicked = true;\n                                    Entry.engine.togglePause({ visible: false });\n                                }\n                                Entry.engine.togglePause();\n                            }\n                            if (key === 'error') {\n                                this.popupHelper.hide();\n                                this.toastError();\n                            }\n                        },\n                        false\n                    );\n                });\n                content.append(iframe);\n                popup.append(content);\n            },\n        });\n    }\n\n    toastError() {\n        Entry.toast.alert(Lang.Msgs.warn, Lang.Msgs.ai_utilize_train_pop_error, true);\n    }\n};\n\nexport default MlPopup;\n"
  },
  {
    "path": "src/class/learning/LearningBase.ts",
    "content": "import LearningView from './LearningView';\nimport DataTable from '../DataTable';\n\ntype Table = {\n    id: string;\n    fieldsInfo: Array<any>;\n    data: Array<any>;\n};\nclass LearningBase {\n    type = 'base';\n    attrLength = 0;\n    name: string = '';\n    view?: LearningView = null;\n    trained: boolean = false;\n    chartEnable: boolean = false;\n    fields: Array<String> = [];\n    predictFields: Array<String> = [];\n    result = {};\n    loadModel: () => {};\n    table: Table;\n    trainParam: any = null;\n    trainCallback: (value: any) => void;\n\n    chart: any = null;\n    predictResult: any = null;\n\n    constructor(params: any = {}) {\n        this.view = new LearningView({ name: params.name || '', status: 0 });\n        // 정지시 data 초기화.\n        Entry.addEventListener('stop', () => {\n            this.init({ ...params });\n        });\n        this.init({ ...params });\n    }\n\n    init({ name, result, table, trainParam }: any) {\n        this.name = name;\n        this.trainParam = trainParam;\n        this.result = result;\n        this.table = table;\n        this.trainCallback = (value: any) => {\n            this.view.setValue(value);\n        };\n        this.trained = true;\n        this.attrLength = table?.select?.[0]?.length || 0;\n        if (this.attrLength === 2) {\n            this.chartEnable = true;\n        }\n        this.fields = table?.select?.[0]?.map((index: number) => table?.fields[index]);\n    }\n\n    isTrained() {\n        return this.trained;\n    }\n\n    setTable() {\n        const tableSource = DataTable.getSource(this.table.id);\n        if (this.table?.fieldsInfo?.length !== tableSource?.fields?.length) {\n            Entry.toast.alert(Lang.Msgs.warn, Lang.AiLearning.train_param_error);\n            throw Error(Lang.AiLearning.train_param_error);\n        }\n        this.table.data = tableSource.rows;\n    }\n\n    destroy() {\n        this.view.destroy();\n        if (this.chart) {\n            this.chart.destroy();\n            this.chart = null;\n        }\n    }\n\n    setVisible(visible: boolean) {\n        this.view.setVisible(visible);\n    }\n\n    unbanBlocks(blockMenu: any) {\n        blockMenu.unbanClass(`ai_learning_train`);\n        blockMenu.unbanClass(`ai_learning_${this.type}`);\n        blockMenu.unbanClass(`${this.type}_attr_${this.attrLength}`);\n        if (this.chartEnable) {\n            blockMenu.unbanClass('ai_learning_train_chart');\n        }\n    }\n\n    openChart() {\n        if (!this.chartEnable) {\n            return;\n        }\n        if (!this.chart) {\n            this.generateChart();\n        } else {\n            this.chart.show();\n        }\n    }\n\n    closeChart() {\n        this.chart?.hide();\n    }\n\n    setTrainOption(type: string, value: any) {\n        this.trainParam = {\n            ...this.trainParam,\n            [type]: value,\n        };\n    }\n\n    getTrainOption() {\n        return this.trainParam;\n    }\n\n    getTrainResult() {\n        return this.result;\n    }\n\n    getResult() {\n        return this.predictResult;\n    }\n\n    generateChart() {\n        throw new Error('Method not implemented.');\n    }\n\n    train() {\n        throw new Error('Method not implemented.');\n    }\n\n    load() {\n        throw new Error('Method not implemented.');\n    }\n\n    predict() {\n        throw new Error('Method not implemented.');\n    }\n}\n\nexport default LearningBase;\n"
  },
  {
    "path": "src/class/learning/LearningView.js",
    "content": "import { GEHelper } from '../../graphicEngine/GEHelper';\nimport { GEDragHelper } from '../../graphicEngine/GEDragHelper';\n\nconst GL_VAR_POS = {\n    VALUE_Y: -8.5,\n    LABEL_Y: -8,\n    STATUS_Y: 8,\n};\nconst STATUS = {\n    READY: 0,\n    LEARNING: 1,\n    DONE: 2,\n    NO_MODEL: 3,\n};\n\nexport default class LearningView {\n    constructor({ name = 'model name', status = STATUS.NO_MODEL, value = 0 } = {}) {\n        this.id = Entry.generateHash();\n        this.visible = true;\n        this.value = value;\n        const fontFamily = EntryStatic.fontFamily || \"NanumGothic, 'Nanum Gothic'\";\n        this.BORDER = 6;\n        this.FONT = `10pt ${fontFamily}`;\n        this.VALUE_FONT = `9pt ${fontFamily}`;\n        this.name = name;\n        this.status = status;\n        this.generateView();\n        Entry.addEventListener('stop', () => {\n            this.view_.visible = true;\n            this.visible = true;\n            this.setValue(0);\n        });\n    }\n\n    setX(x) {\n        this.x_ = x;\n        this.updateView();\n    }\n    getX() {\n        return this.x_;\n    }\n    setY(y) {\n        this.y_ = y;\n        this.updateView();\n    }\n    getY() {\n        return this.y_;\n    }\n    isVisible() {\n        return this.visible;\n    }\n    setVisible(visibleState) {\n        this.view_.visible = visibleState;\n        this.visible = visibleState;\n        this.updateView();\n    }\n    setValue(value) {\n        this.value = value;\n        if (value == 0) {\n            this.status = STATUS.READY;\n        } else if (value === 100) {\n            this.status = STATUS.DONE;\n        } else if (value < 100) {\n            this.status = STATUS.LEARNING;\n        }\n        this.updateView();\n    }\n    getValue() {\n        return this.value;\n    }\n    destroy() {\n        Entry.stage.removeVariable(this);\n    }\n    setStatus(status) {\n        this.status = status;\n        this.updateView();\n    }\n\n    generateView(variableIndex = 0) {\n        this.view_ = GEHelper.newContainer();\n        this.rect_ = GEHelper.newGraphic();\n        this.view_.addChild(this.rect_);\n        this.view_.variable = this;\n        this.view_.visible = this.visible;\n        this.view_.mouseEnabled = true;\n        GEDragHelper.handleDrag(this.view_);\n\n        this.wrapper_ = GEHelper.newGraphic();\n        this.view_.addChild(this.wrapper_);\n        this.textView_ = GEHelper.textHelper.newText(this.name, this.FONT, '#000000', 'alphabetic');\n        this.textView_.x = 4;\n        if (GEHelper.isWebGL) {\n            this.textView_.y = GL_VAR_POS.LABEL_Y;\n        } else {\n            this.textView_.y = 1;\n        }\n        this.view_.addChild(this.textView_);\n        this.statusView = GEHelper.textHelper.newText(\n            Lang.AiLearning[`model_status_${this.status}`],\n            this.FONT,\n            '#000000',\n            'alphabetic'\n        );\n        this.statusView.x = 4;\n        if (GEHelper.isWebGL) {\n            this.statusView.y = GL_VAR_POS.STATUS_Y;\n        } else {\n            this.statusView.y = 15;\n        }\n        this.view_.addChild(this.statusView);\n\n        this.view_.on(GEDragHelper.types.DOWN, function(evt) {\n            if (Entry.type !== 'workspace') {\n                return;\n            }\n            this.offset = {\n                x: this.x - (evt.stageX * 0.75 - 240),\n                y: this.y - (evt.stageY * 0.75 - 135),\n            };\n        });\n\n        this.view_.on(GEDragHelper.types.MOVE, function(evt) {\n            if (Entry.type !== 'workspace') {\n                return;\n            }\n            this.variable.setX(evt.stageX * 0.75 - 240 + this.offset.x);\n            this.variable.setY(evt.stageY * 0.75 - 135 + this.offset.y);\n            this.variable.updateView();\n        });\n\n        let width = this.textView_.getMeasuredWidth() + 26;\n        width = Math.max(width, 90);\n        this.maxWidth = width - 20;\n\n        this.slideBar_ = GEHelper.newGraphic();\n        this.slideBar_.graphics\n            .beginFill('#d8d8d8')\n            .s('#d8d8d8')\n            .ss(1)\n            .rr(6, 28, this.maxWidth, 5, 2);\n        this.view_.addChild(this.slideBar_);\n        const visibleValue = (this.value / 100) * this.maxWidth;\n        this.valueBar = GEHelper.newGraphic();\n        if (visibleValue > 0) {\n            this.valueBar.graphics\n                .beginFill('#4f80ff')\n                .s('#4f80ff')\n                .ss(1)\n                .rr(6, 28, visibleValue, 5, 2);\n        }\n        this.view_.addChild(this.valueBar);\n        const variableLength = Entry.variableContainer.variables_.length;\n        if (this.getX() && this.getY()) {\n            this.setX(this.getX());\n            this.setY(this.getY());\n        } else {\n            this.setX(10 - 240 + Math.floor(variableLength / 11) * 80);\n            this.setY(variableIndex * 24 + 20 - 135 - Math.floor(variableLength / 11) * 264);\n        }\n\n        this.setVisible(this.isVisible());\n        Entry.stage.loadVariable(this);\n    }\n\n    updateView() {\n        if (!this.view_) {\n            return;\n        }\n\n        if (this.isVisible()) {\n            this._adjustSingleViewPosition();\n            const oldContent = this.textView_.text;\n            let newContent = this.name;\n\n            if (oldContent !== newContent) {\n                this.textView_.text = newContent;\n                this._nameWidth = null;\n            }\n\n            if (!this._nameWidth) {\n                this._nameWidth = this.textView_.getMeasuredWidth();\n            }\n\n            const oldStatus = this.statusView.text;\n            let newStatus = Lang.AiLearning[`model_status_${this.status}`];\n\n            if (oldStatus !== newStatus) {\n                this.statusView.text = newStatus;\n            }\n\n            let width = this._nameWidth + 35;\n            const colorSet = EntryStatic.colorSet.canvas || {};\n            width = Math.max(width, 90);\n            this.rect_.graphics\n                .clear()\n                .f('#ffffff')\n                .ss(1, 2, 0)\n                .s(colorSet.border || '#aac5d5')\n                .rr(0, -14, width, 54, 4);\n\n            width = this._nameWidth + 26;\n            width = Math.max(width, 90);\n            this.maxWidth = width - 16;\n            const visibleValue = (this.value / 100) * this.maxWidth;\n            this.slideBar_.graphics\n                .clear()\n                .beginFill('#d8d8d8')\n                .s('#d8d8d8')\n                .ss(1)\n                .rr(6, 28, this.maxWidth + 4, 5, 2);\n            if (visibleValue > 0) {\n                this.valueBar.graphics\n                    .clear()\n                    .beginFill('#4f80ff')\n                    .s('#4f80ff')\n                    .ss(1)\n                    .rr(6, 28, visibleValue, 5, 2);\n            }\n        }\n        Entry.requestUpdate = true;\n    }\n\n    _adjustSingleViewPosition() {\n        this.view_.x = this.getX();\n        this.view_.y = this.getY();\n    }\n}\n"
  },
  {
    "path": "src/class/learning/LogisticRegression.js",
    "content": "import * as tf from '@tensorflow/tfjs';\nimport _floor from 'lodash/floor';\nimport _max from 'lodash/max';\nimport _sum from 'lodash/sum';\nimport _mean from 'lodash/mean';\nimport _toNumber from 'lodash/toNumber';\nimport _isNaN from 'lodash/isNaN';\nimport LearningBase from './LearningBase';\nimport Utils from './Utils';\n\nexport const classes = [\n    'ai_learning_train',\n    'ai_learning_logistic_regression',\n    'logistic_regression_attr_1',\n    'logistic_regression_attr_2',\n    'logistic_regression_attr_3',\n    'logistic_regression_attr_4',\n    'logistic_regression_attr_5',\n    'logistic_regression_attr_6',\n];\n\nclass LogisticRegression extends LearningBase {\n    type = 'logistic_regression';\n\n    init({ name, url, result, table, trainParam }) {\n        this.name = name;\n        this.trainParam = trainParam;\n        this.result = result;\n        this.table = table;\n        this.trainCallback = (value) => {\n            this.view.setValue(value);\n        };\n        this.trained = true;\n\n        this.attrLength = table?.select?.[0]?.length || 0;\n        if (this.attrLength === 1) {\n            this.chartEnable = true;\n        }\n        if (this.url !== url) {\n            this.load(url);\n            this.url = url;\n        }\n\n        this.fields = table?.select?.[0]?.map((index) => table?.fields[index]);\n        this.predictFields = table?.select?.[1]?.map((index) => table?.fields[index]);\n\n        if (!Utils.isWebGlSupport()) {\n            tf.setBackend('cpu');\n        }\n    }\n\n    async load(url) {\n        const model = await tf.loadLayersModel(url);\n        const modelData = new Promise((resolve) =>\n            model.save({\n                save: (data) => {\n                    const layers = data?.modelTopology?.config?.layers;\n                    if (Array.isArray(layers)) {\n                        data.modelTopology.config.layers.forEach((layer) => {\n                            if (layer?.config?.name) {\n                                layer.config.name = `${layer.config.name}_ws`;\n                            }\n                        });\n                    }\n                    if (Array.isArray(data.weightSpecs)) {\n                        data.weightSpecs.forEach((spec) => {\n                            const splits = spec.name.split('/');\n                            splits[0] = `${splits[0]}_ws`;\n                            spec.name = splits.join('/');\n                        });\n                    }\n                    resolve(data);\n                },\n            })\n        );\n        this.model = await tf.loadLayersModel({ load: () => modelData });\n        model.dispose();\n    }\n\n    async reload(url) {\n        this.model = await tf.loadLayersModel(url || this.url);\n        this.isLoaded = true;\n    }\n\n    async train() {\n        this.setTable();\n        this.trained = false;\n        let currentEpoch = 0;\n        let percent = 0;\n        this.trainCallback(1);\n\n        const { validationRate = 0.25, testRate = 0.2 } = this.trainParam;\n        const {\n            trainData,\n            validateData,\n            testArr,\n            select,\n            fields,\n            valueMap,\n            dataLength,\n            numClass,\n        } = getData(validationRate, testRate, this.table, this.trainParam);\n\n        this.valueMap = Object.fromEntries(\n            Object.entries(valueMap).map(([key, value]) => [value, key])\n        );\n        this.model = createModel(dataLength, numClass);\n        this.lastHistory = await trainModel(\n            this.model,\n            trainData,\n            validateData,\n            this.trainParam,\n            () => {\n                currentEpoch = currentEpoch + 1;\n                percent = _floor((currentEpoch / this.trainParam.epochs) * 100);\n                this.trainCallback(Math.min(percent, 100));\n            }\n        );\n        const { score, confusionMatrix } = await this.evaluate(\n            this.model,\n            testArr,\n            valueMap,\n            numClass\n        );\n        const { accuracy, f1, precision, recall } = score;\n        this.trained = true;\n        this.result = {\n            select,\n            fields,\n            confusionMatrix,\n            accuracy,\n            f1,\n            valueMap: this.valueMap,\n            precision,\n            recall,\n        };\n    }\n\n    async predict(array) {\n        if (!this.model) {\n            throw new Error(\"can't predict: no model\");\n        }\n        const xs = tf.tensor([array]);\n        const preds = this.model.predict(xs);\n        const resultArray = preds.arraySync();\n        const valueMap = this.result?.valueMap || {};\n        this.predictResult = resultArray\n            .map((arr) =>\n                arr.map((probability, index) => ({\n                    probability: _floor(probability, 3),\n                    className: valueMap[index + 1],\n                }))\n            )\n            .flat();\n    }\n\n    async evaluate(model, validateData = [{ x: 0, y: 0 }], classMap, numClass) {\n        const evalData = validateData;\n        const xs = tf.tensor(Array.from(evalData, (evalData) => evalData.x));\n        const ys = tf.tensor(Array.from(evalData, (evalData) => evalData.y)).argMax(-1);\n        const preds = model.predict(xs);\n        const pred = preds.argMax(-1);\n        const confusionMatrixZip = await tf.math.confusionMatrix(ys, pred, numClass);\n        const matrixArray = Array.from(confusionMatrixZip.dataSync());\n        const confusionMatrix = Utils.arrayToMatrix(matrixArray, numClass);\n        const score = Utils.getScores(confusionMatrix, numClass);\n        return {\n            score,\n            confusionMatrix,\n        };\n    }\n}\n\nexport default LogisticRegression;\n\nfunction createModel(inputShape, numClasses = 1) {\n    const model = tf.sequential({\n        layers: [\n            tf.layers.dense({\n                name: 'log_dense_ws',\n                inputShape: [inputShape],\n                units: numClasses,\n                activation: numClasses === 2 ? 'sigmoid' : 'softmax',\n                useBias: false,\n                kernelInitializer: tf.initializers.varianceScaling({}),\n            }),\n        ],\n    });\n    return model;\n}\n\nasync function trainModel(model, inputs, outputs, trainParam, onEpochEnd) {\n    const {\n        batchSize = 0,\n        epochs = 0,\n        optimizer: optimizerStr = 'adm',\n        learningRate = 0.1,\n    } = trainParam;\n    const optimizer =\n        optimizerStr === 'adm' ? tf.train.adam(learningRate * 1) : tf.train.sgd(learningRate * 1);\n    model.compile({\n        optimizer,\n        loss: tf.losses.meanSquaredError,\n        metrics: ['acc', 'ce'],\n    });\n    return await model.fitDataset(inputs.batch(batchSize * 1), {\n        epochs: epochs * 1,\n        validationData: outputs.batch(batchSize * 1),\n        callbacks: {\n            onEpochEnd,\n        },\n    });\n}\n\nfunction getData(validationRate, testRate, data, trainParam) {\n    const tempMap = {};\n    const tempMapCount = {};\n    const { select = [[0], [1]], data: table, fields } = data;\n    const [attr, predict] = select;\n    const filtered = table.filter(\n        (row) => !select[0].some((selected) => _isNaN(_toNumber(row[selected])))\n    );\n    const dataArray = filtered\n        .map((row) => ({\n            x: attr.map((i) => parseFloat(row[i]) || 0),\n            y: Utils.stringToNumber(predict[0], row[predict[0]], tempMap, tempMapCount),\n        }))\n        .map((row) => {\n            const yRow = Array(tempMapCount[predict[0]]).fill(0);\n            yRow[row.y - 1] = 1;\n            return {\n                x: row.x,\n                y: yRow,\n            };\n        });\n    const [train, validate, test] = sliceArray(dataArray, validationRate, testRate);\n\n    return {\n        trainData: arrayToZip(train),\n        validateData: arrayToZip(validate),\n        testArr: test,\n        select,\n        fields,\n        valueMap: { ...tempMap[predict[0]] },\n        dataLength: attr.length,\n        numClass: tempMapCount[predict[0]],\n    };\n}\n\nfunction sliceArray(dataArray, validationRate = 0.25, testRate = 0.2) {\n    Utils.shuffle(dataArray);\n    const testNum = dataArray.length - Math.floor(dataArray.length * testRate);\n    const validateNum = Math.floor(testNum * validationRate);\n\n    const validateArr = dataArray.slice(0, validateNum);\n    const trainArr = dataArray.slice(validateNum, testNum);\n    const testArr = dataArray.slice(testNum, dataArray.length);\n    return [trainArr, validateArr, testArr];\n}\n\nfunction arrayToZip(array) {\n    const xs = tf.data.array(array.map((v) => v.x));\n    const ys = tf.data.array(array.map((v) => v.y));\n    return tf.data.zip({ xs, ys });\n}\n"
  },
  {
    "path": "src/class/learning/NumberClassification.js",
    "content": "import LearningView from './LearningView';\nimport Chart from './Chart';\nimport _uniq from 'lodash/uniq';\nimport _floor from 'lodash/floor';\nimport _sum from 'lodash/sum';\nimport _mean from 'lodash/mean';\nimport _toNumber from 'lodash/toNumber';\nimport _isNaN from 'lodash/isNaN';\nimport DataTable from '../DataTable';\n\nexport const classes = [\n    'ai_learning_train',\n    'ai_learning_number',\n    'number_learning_attr_1',\n    'number_learning_attr_2',\n    'number_learning_attr_3',\n    'number_learning_attr_4',\n    'number_learning_attr_5',\n    'number_learning_attr_6',\n];\n\nclass NumberClassification {\n    #attrLength = 0;\n    #trainParam = null;\n    #table = {};\n    #trainCallback;\n    #chart = null;\n    #isTrained = false;\n    #chartEnable = false;\n    #view = null;\n    #predictResult = null;\n    #name = '';\n    #fields = [];\n    #predictField = [];\n    #loadModel;\n    constructor(params = {}) {\n        this.#view = new LearningView({ name: params.name || '', status: 0 });\n        // 정지시 data 초기화.\n        Entry.addEventListener('stop', () => {\n            this.init({ ...params });\n        });\n        this.init({ ...params });\n    }\n\n    init({ name, url, table, trainParam, modelId, loadModel, result }) {\n        this.#name = name;\n        this.#table = table;\n        this.result = result;\n        this.#trainCallback = (value) => {\n            this.#view.setValue(value);\n        };\n        this.#isTrained = true;\n        this.#loadModel = loadModel;\n\n        this.#attrLength = table?.select?.[0]?.length || 0;\n        this.#fields = table?.select?.[0]?.map((index) => table?.fields[index]);\n        this.#predictField = table?.select?.[1]?.map((index) => table?.fields[index]);\n        if (this.#attrLength === 2) {\n            this.#chartEnable = true;\n        }\n        if (this.url !== url || this.modelId !== modelId) {\n            // load시 trainParam에 추가되는 파라미터가 있어서 로드 직전 추가.\n            this.#trainParam = trainParam;\n            this.load(url, modelId);\n            this.url = url;\n            this.modelId = modelId;\n        }\n    }\n\n    setTable() {\n        const tableSource = DataTable.getSource(this.#table.id);\n        if (this.#table?.fieldsInfo?.length !== tableSource?.fields?.length) {\n            Entry.toast.alert(Lang.Msgs.warn, Lang.AiLearning.train_param_error);\n            throw Error(Lang.AiLearning.train_param_error);\n        }\n        this.#table.data = tableSource.rows;\n    }\n\n    destroy() {\n        this.#view.destroy();\n        if (this.#chart) {\n            this.#chart.destroy();\n            this.#chart = null;\n        }\n    }\n\n    createColor() {\n        return this.#trainParam.labels.reduce(\n            (acc, cur, idx, arr) => ({\n                ...acc,\n                [cur]: Entry.Utils.randomColor(),\n            }),\n            {}\n        );\n    }\n\n    setVisible(visible) {\n        this.#view.setVisible(visible);\n    }\n\n    unbanBlocks(blockMenu) {\n        blockMenu.unbanClass(`ai_learning_train`);\n        blockMenu.unbanClass(`ai_learning_number`);\n        blockMenu.unbanClass(`number_learning_attr_${this.#attrLength}`);\n        if (this.#chartEnable) {\n            blockMenu.unbanClass('ai_learning_train_chart');\n        }\n    }\n\n    isTrained() {\n        return this.#isTrained;\n    }\n\n    openChart() {\n        if (!this.#chartEnable) {\n            return;\n        }\n        if (!this.#chart) {\n            this.#chart = new Chart({\n                title: Lang.AiLearning.chart_title,\n                description: `<em>${Lang.AiLearning.class}</em>   ${this.#predictField[0]}<em>${\n                    Lang.AiLearning.model_attr_str\n                } 1</em>${this.#fields[0]}<em>${Lang.AiLearning.model_attr_str} 2</em>${\n                    this.#fields[1]\n                }`,\n                source: this.chartData,\n            });\n        } else {\n            this.#chart.show();\n        }\n    }\n\n    closeChart() {\n        this.#chart?.hide();\n    }\n\n    setTrainOption(type, value) {\n        this.trainParam = {\n            ...this.trainParam,\n            [type]: value,\n        };\n    }\n\n    getTrainOption() {\n        return this.#trainParam;\n    }\n\n    getResult() {\n        return this.#predictResult;\n    }\n\n    getTrainResult() {\n        return this.result;\n    }\n\n    getLabels() {\n        const { data: trainData, labels } = convertTableToKnnData(this.#table);\n        return _uniq(labels[0]).sort((a, b) => String(a).localeCompare(String(b)));\n    }\n\n    train() {\n        this.setTable();\n        this.#trainCallback(1);\n        this.#isTrained = false;\n        const { data: trainData, labels } = convertTableToKnnData(this.#table);\n        const trainLabels = labels[0];\n        const uniqLabels = _uniq(labels[0]).sort((a, b) => String(a).localeCompare(String(b)));\n        const numLabels = uniqLabels.length;\n        const maxVector = new Array(trainData[0].length).fill(-Infinity);\n        trainData.forEach((e) => {\n            for (let i = 0; i < maxVector.length; i++) {\n                maxVector[i] = maxVector[i] > e[i] ? maxVector[i] : e[i];\n            }\n        });\n\n        const minVector = new Array(trainData[0].length).fill(Infinity);\n        trainData.forEach((e) => {\n            for (let i = 0; i < minVector.length; i++) {\n                minVector[i] = minVector[i] < e[i] ? minVector[i] : e[i];\n            }\n        });\n        this.#trainParam = {\n            ...this.#trainParam,\n            trainData,\n            trainLabels,\n            labels: uniqLabels,\n            numLabels,\n            maxVector,\n            minVector,\n        };\n        this.#isTrained = true;\n        this.colors = this.createColor();\n        this.#chart?.load({\n            source: this.chartData,\n        });\n        this.#trainCallback(100);\n    }\n\n    async load(url, modelId) {\n        const savedData = await this.#loadModel({ url, modelId });\n        if (!savedData) {\n            return;\n        }\n        this.#trainParam = {\n            ...this.#trainParam,\n            trainData: savedData.data,\n            trainLabels: savedData.labels,\n            labels: _uniq(savedData.labels).sort((a, b) =>\n                String(a).localeCompare(String(b))\n            ),\n            maxVector: savedData.maxVector,\n            minVector: savedData.minVector,\n            numLabels: savedData.numLabels,\n            neighbors: savedData.neighbors,\n            isLoaded: true,\n        };\n        this.colors = this.createColor();\n    }\n\n    normalize(data = []) {\n        const normData = [];\n        const { minVector, maxVector } = this.#trainParam;\n        for (let i = 0; i < data.length; i++) {\n            normData.push((data[i] - minVector[i]) / (maxVector[i] - minVector[i]));\n        }\n        return normData;\n    }\n\n    predict(data) {\n        const distData = [];\n        const { trainData, trainLabels, neighbors } = this.#trainParam;\n\n        for (let i = 0; i < trainData.length; i++) {\n            const dist = eudist(this.normalize(data), this.normalize(trainData[i]));\n            distData.push({\n                index: i,\n                dist,\n                label: trainLabels[i],\n            });\n        }\n\n        distData.sort((a, b) => a.dist - b.dist);\n\n        const counts = {};\n        for (let i = 0; i < neighbors; i++) {\n            const { label, dist } = distData[i];\n            if (!counts[label]) {\n                counts[label] = [];\n            }\n            counts[label].push(dist);\n        }\n\n        const totalDistance = _sum(Object.values(counts).flat());\n        this.#predictResult = Object.keys(counts)\n            .map((className) => {\n                const dist = _mean(counts[className]);\n                const count = counts[className].length;\n                const distProbability =\n                    totalDistance === 0 ? 1 : (totalDistance - dist) / totalDistance;\n                const probability = (count / neighbors) * 99 + distProbability;\n                return {\n                    className,\n                    count,\n                    probability,\n                };\n            })\n            .sort((a, b) => b.probability - a.probability);\n        return this.#predictResult;\n    }\n\n    findLabel(x, y) {\n        const strX = String(x);\n        const strY = String(y);\n        const index = this.#trainParam.trainData.findIndex(\n            (row) => String(row[0]) === strX && String(row[1]) === strY\n        );\n        return this.#trainParam.trainLabels[index];\n    }\n\n    findColor(id, a, b) {\n        if (id === 'y') {\n            return this.colors[this.findLabel(a, b)];\n        }\n        return undefined;\n    }\n\n    get chartData() {\n        const json = this.#trainParam.trainData.map((row, idx) => ({\n            x: row[0],\n            y: row[1],\n            index: this.#trainParam.trainLabels[idx],\n        }));\n        return {\n            data: {\n                type: 'scatter',\n                json,\n                keys: { value: ['y'], x: 'x' },\n                color: (color, d) => this.findColor(d.id, d.x, d.value) || color,\n                labels: false,\n            },\n            options: {\n                point: {\n                    pattern: ['circle'],\n                },\n                legend: {\n                    show: false,\n                },\n                tooltip: {\n                    contents: (data) => {\n                        const [{ x, value }] = data;\n                        const label = this.findLabel(x, value);\n                        return `\n                        <div class=\"chart_handle_wrapper\">\n                            ${Lang.AiLearning.class}: ${label}, ${this.#fields[0]}: ${x}, ${\n                            this.#fields[1]\n                        }: ${value}\n                        <div>`;\n                    },\n                },\n                axis: {\n                    x: {\n                        tick: {\n                            fit: false,\n                            count: 10,\n                        },\n                    },\n                },\n                grid: {\n                    x: {\n                        show: true,\n                    },\n                    y: {\n                        show: true,\n                    },\n                },\n            },\n        };\n    }\n}\n\nexport default NumberClassification;\n\nfunction eudist(a, b) {\n    let sum = 0;\n    for (let i = 0; i < a.length; i++) {\n        const d = (a[i] || 0) - (b[i] || 0);\n        sum += d * d;\n    }\n\n    return sum;\n}\n\nfunction convertTableToKnnData(tableData = {}) {\n    const { select = [[0], [1]], data: table = [] } = tableData;\n    const [attr, predict] = select;\n    const filtered = table.filter(\n        (row) => !select[0].some((selected) => _isNaN(_toNumber(row[selected])))\n    );\n    return filtered.reduce(\n        (accumulator, row) => {\n            const { data = [], labels = [] } = accumulator;\n            return {\n                data: [...data, row.filter((data, index) => attr.includes(index))],\n                labels: predict.map((i, idx) => {\n                    const arr = labels[idx] || [];\n                    return [...arr, row[i]];\n                }),\n            };\n        },\n        { data: [], labels: [] }\n    );\n}\n"
  },
  {
    "path": "src/class/learning/Regression.js",
    "content": "import * as tf from '@tensorflow/tfjs';\nimport _floor from 'lodash/floor';\nimport _max from 'lodash/max';\nimport Chart from './Chart';\nimport _sum from 'lodash/sum';\nimport _mean from 'lodash/mean';\nimport _toNumber from 'lodash/toNumber';\nimport _isNaN from 'lodash/isNaN';\nimport LearningBase from './LearningBase';\nimport Utils from './Utils';\n\nexport const classes = [\n    'ai_learning_train',\n    'ai_learning_regression',\n    'regression_attr_1',\n    'regression_attr_2',\n    'regression_attr_3',\n    'regression_attr_4',\n    'regression_attr_5',\n    'regression_attr_6',\n    'ai_learning_train_chart',\n];\n\nclass Regression extends LearningBase {\n    type = 'regression';\n\n    init({ name, url, result, table, trainParam }) {\n        this.name = name;\n        this.trainParam = trainParam;\n        this.result = result;\n        this.table = table;\n        this.trainCallback = (value) => {\n            this.view.setValue(value);\n        };\n        this.trained = true;\n\n        this.attrLength = table?.select?.[0]?.length || 0;\n        if (this.attrLength === 1) {\n            this.chartEnable = true;\n        }\n        if (this.url !== url) {\n            this.load(url);\n            this.url = url;\n        }\n\n        this.fields = table?.select?.[0]?.map((index) => table?.fields[index]);\n        this.predictFields = table?.select?.[1]?.map((index) => table?.fields[index]);\n\n        if (!Utils.isWebGlSupport()) {\n            tf.setBackend('cpu');\n        }\n    }\n\n    generateChart() {\n        this.chart = new Chart({\n            source: this.chartData,\n            title: Lang.AiLearning.chart_title,\n            description: `\n                ${this.fields.map(\n                    (field, index) =>\n                        `<em>${Lang.AiLearning.model_attr_str} ${index + 1}</em>: ${field}`\n                )}\n                <em>${Lang.AiLearning.predict}</em>${this.predictFields[0]}<em>${\n                Lang.AiLearning.equation\n            }</em>${this.result.equation}\n            `,\n        });\n    }\n\n    async train() {\n        try {\n            this.setTable();\n            this.trained = false;\n            let currentEpoch = 0;\n            let percent = 0;\n            this.trainCallback(1);\n            const { inputs, outputs } = convertToTfData(this.table, this.trainParam);\n            const { model, trainHistory, a, b, graphData = [], rsquared, normResult } = await train(\n                inputs,\n                outputs,\n                this.trainParam,\n                undefined,\n                () => {\n                    currentEpoch = currentEpoch + 1;\n                    percent = _floor((currentEpoch / this.trainParam.epochs) * 100);\n                    this.trainCallback(Math.min(percent, 100));\n                }\n            );\n            this.model = model;\n            const { acc = [] } = trainHistory?.history || {};\n            const accuracy = _max(acc) || 0;\n            const graphPoints = (graphData.originalPoints || []).slice(0, 1000);\n            if (inputs.length == 1) {\n                graphData.predictedPoints.map(({ x, y }, i) => {\n                    let index = graphPoints.sort((a, b) => a.x - b.x).findIndex((p) => p.x >= x);\n                    if (index < 0 && i > 0) {\n                        index = graphPoints.length - 1;\n                    }\n                    if (graphPoints[index]) {\n                        graphPoints[index].equation = y;\n                    }\n                });\n            }\n            this.result = {\n                graphData: graphPoints,\n                accuracy,\n                normResult,\n                rsquared,\n                equation: `Y = ${a\n                    .map((a, i) => `${addSign(a)}X<sub>${i + 1}</sub>`)\n                    .join('')} ${addSign(b)}`,\n            };\n            this.trained = true;\n            this.chart?.load({\n                source: this.chartData,\n                description: `\n                    ${this.fields.map(\n                        (field, index) =>\n                            `<em>${Lang.AiLearning.model_attr_str} ${index + 1}</em> ${field}`\n                    )}\n                    <em>${Lang.AiLearning.predict}</em> ${this.predictFields[0]}<em>${\n                    Lang.AiLearning.equation\n                }</em>${this.result.equation}\n                `,\n            });\n        } catch (e) {\n            console.log('train error', e);\n        }\n    }\n\n    async load(url) {\n        const model = await tf.loadLayersModel(url);\n        const modelData = new Promise((resolve) =>\n            model.save({\n                save: (data) => {\n                    const layers = data?.modelTopology?.config?.layers;\n                    if (Array.isArray(layers)) {\n                        data.modelTopology.config.layers.forEach((layer) => {\n                            if (layer?.config?.name) {\n                                layer.config.name = `${layer.config.name}_ws`;\n                            }\n                        });\n                    }\n                    if (Array.isArray(data.weightSpecs)) {\n                        data.weightSpecs.forEach((spec) => {\n                            const splits = spec.name.split('/');\n                            splits[0] = `${splits[0]}_ws`;\n                            spec.name = splits.join('/');\n                        });\n                    }\n                    resolve(data);\n                },\n            })\n        );\n        this.model = await tf.loadLayersModel({ load: () => modelData });\n        model.dispose();\n    }\n\n    convertNomalResult() {\n        const { inputMin, inputMax, outputMax, outputMin } = this.result.normResult;\n        if (!Array.isArray(inputMin)) {\n            return this.result.normResult;\n        }\n        return {\n            inputMin: tf.tensor1d(inputMin),\n            inputMax: tf.tensor1d(inputMax),\n            outputMax: tf.tensor1d(outputMax),\n            outputMin: tf.tensor1d(outputMin),\n        };\n    }\n    async predict(data) {\n        tf.engine().startScope();\n        const { inputMin, inputMax, outputMax, outputMin } = this.convertNomalResult();\n        const result = tf.tidy(() => {\n            let convertedData;\n            if (Array.isArray(data)) {\n                convertedData = tf.tensor2d([data]);\n            } else {\n                convertedData = tf.tensor1d([data]);\n            }\n            convertedData = convertedData.sub(inputMin).div(inputMax.sub(inputMin));\n            const preds = this.model\n                .predict(convertedData)\n                .mul(outputMax.sub(outputMin))\n                .add(outputMin);\n            const [result] = preds.dataSync();\n            this.predictResult = _floor(result, 2);\n            preds.dispose();\n            return this.predictResult;\n        });\n        tf.engine().endScope();\n        return result;\n    }\n\n    get chartData() {\n        return {\n            data: {\n                json: this.result.graphData,\n                keys: { value: ['equation', 'y'], x: 'x' },\n                types: {\n                    y: 'scatter',\n                    equation: 'line',\n                },\n            },\n            options: {\n                legend: {\n                    show: false,\n                },\n                tooltip: {\n                    contents: (data) => {\n                        const [{ x, value, id }] = data;\n                        return `\n                            <div class=\"chart_handle_wrapper\">\n                                ${this.fields[0]}: ${x}, ${this.predictFields[0]}: ${value}\n                            <div>\n                        `;\n                    },\n                },\n                line: {\n                    connectNull: true,\n                    point: false,\n                },\n                axis: {\n                    x: {\n                        tick: {\n                            fit: false,\n                            count: 15,\n                        },\n                    },\n                },\n                grid: {\n                    x: {\n                        show: true,\n                    },\n                    y: {\n                        show: true,\n                    },\n                },\n            },\n        };\n    }\n}\n\nexport default Regression;\n\nfunction addSign(x) {\n    return x < 0 ? x : `+${x}`;\n}\n\nfunction convertToTfData(data, trainParam) {\n    const { select = [[0], [1]], data: table } = data;\n    const [attr, predict] = select;\n    const { epochs = 1, batchSize = 1 } = trainParam;\n    const filtered = table.filter(\n        (row) => !select.flat().some((selected) => _isNaN(_toNumber(row[selected])))\n    );\n    const totalDataSize = Math.ceil(filtered.length / batchSize) * epochs;\n    return filtered.reduce(\n        (accumulator, row) => {\n            const { inputs = [], outputs = [] } = accumulator;\n            return {\n                inputs: attr.map((i, idx) => {\n                    const arr = inputs[idx] || [];\n                    return [...arr, parseFloat(row[i]) || 0];\n                }),\n                outputs: predict.map((i, idx) => {\n                    const arr = outputs[idx] || [];\n                    return [...arr, parseFloat(row[i]) || 0];\n                }),\n                totalDataSize,\n            };\n        },\n        { inputs: [], outputs: [] }\n    );\n}\n\nfunction convertToTensor(inputs, outputs) {\n    return tf.tidy(() => {\n        const inputTensor = tf.tensor2d(inputs).transpose();\n        const outputTensor = tf.tensor2d(outputs).transpose();\n\n        const inputMax = inputTensor.max(0);\n        const inputMin = inputTensor.min(0);\n        const outputMax = outputTensor.max(0);\n        const outputMin = outputTensor.min(0);\n\n        // (d - min) / (max - min)\n        const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));\n        const normalizedOutputs = outputTensor.sub(outputMin).div(outputMax.sub(outputMin));\n\n        return {\n            inputs: normalizedInputs,\n            outputs: normalizedOutputs,\n            inputMax,\n            inputMin,\n            outputMax,\n            outputMin,\n        };\n    });\n}\n\nfunction createModel(inputShape) {\n    const model = tf.sequential();\n    model.add(tf.layers.dense({ inputShape: [inputShape], units: 1, name: 'reg_dense_ws' }));\n    return model;\n}\nasync function trainModel(model, inputs, outputs, trainParam, onBatchEnd, onEpochEnd) {\n    model.compile({\n        optimizer: tf.train.adam(trainParam.learningRate),\n        loss: tf.losses.meanSquaredError,\n        metrics: ['mse', 'acc', 'ce'],\n    });\n\n    return await model.fit(inputs, outputs, {\n        batchSize: trainParam.batchSize,\n        epochs: trainParam.epochs,\n        shuffle: trainParam.shuffle,\n        validationSplit: trainParam.validationRate,\n        callbacks: {\n            onBatchEnd,\n            onEpochEnd,\n        },\n    });\n}\nconst TEST_POINT_COUNT = 2;\nfunction testModel(model, normalizationData) {\n    const { inputMin, inputMax, outputMin, outputMax } = normalizationData;\n\n    const [xs, preds] = tf.tidy(() => {\n        const xs = tf.linspace(0, 1, TEST_POINT_COUNT);\n        const preds = model.predict(xs.reshape([TEST_POINT_COUNT, 1]));\n\n        // d * (max - min) + min\n        const unNormXs = xs.mul(inputMax.sub(inputMin)).add(inputMin);\n        // @ts-ignore\n        const unNormPreds = preds.mul(outputMax.sub(outputMin)).add(outputMin);\n        return [unNormXs.dataSync(), unNormPreds.dataSync()];\n    });\n    return Array.from(xs).map((val, i) => ({\n        x: val,\n        y: preds[i],\n    }));\n}\n\nfunction getR2Score(model, normResult, y) {\n    const yData = y[0];\n    const yHat = model\n        .predict(normResult.inputs)\n        .mul(normResult.outputMax.sub(normResult.outputMin))\n        .add(normResult.outputMin)\n        .dataSync();\n    const yMean = yData.reduce((acc, cur) => acc + cur) / yData.length;\n\n    const ssr = yHat\n        .map((e, index) => (e - yData[index]) * (e - yData[index]))\n        .reduce((acc, cur) => acc + cur);\n    const sst = yData.map((e) => (e - yMean) * (e - yMean)).reduce((acc, cur) => acc + cur);\n    const r2 = 1 - ssr / sst;\n\n    return Math.max(r2, 0);\n}\n\nasync function train(inputs, outputs, trainParam, onBatchEnd, onEpochEnd) {\n    const normResult = convertToTensor(inputs, outputs);\n    const model = createModel(inputs.length);\n    const history = await trainModel(\n        model,\n        normResult.inputs,\n        normResult.outputs,\n        trainParam,\n        onBatchEnd,\n        onEpochEnd\n    );\n\n    // @ts-ignore\n    const weight = model.layers[0].weights[0].val;\n    // @ts-ignore\n    const bias = model.layers[0].weights[1].val;\n\n    const inputMin = normResult.inputMin;\n    const inputMax = normResult.inputMax;\n    const outputMin = normResult.outputMin;\n    const outputMax = normResult.outputMax;\n\n    const o = outputMax.sub(outputMin);\n    const oi = o.div(inputMax.sub(inputMin));\n\n    const a = oi.mul(weight.transpose());\n    const b = bias\n        .mul(o)\n        .add(outputMin)\n        .sub(a.matMul(inputMin.expandDims(0).transpose()));\n    const r2 = getR2Score(model, normResult, outputs);\n    const graphData = {\n        originalPoints: [],\n        predictedPoints: [],\n    };\n    if (inputs.length === 1) {\n        graphData.originalPoints = inputs[0].map((e, i) => ({\n            x: e,\n            y: outputs[0][i],\n        }));\n        graphData.predictedPoints = testModel(model, normResult);\n    }\n\n    return {\n        model,\n        normResult,\n        trainHistory: history,\n        a: Array.from(a.dataSync()).map((x) => _floor(x, 2)),\n        b: _floor(b.dataSync()[0], 2),\n        rsquared: _floor(r2, 2),\n        graphData,\n    };\n}\n"
  },
  {
    "path": "src/class/learning/SpeechClassification.js",
    "content": "import * as tf from '@tensorflow/tfjs';\nexport const classes = ['ai_learning_speech'];\n\nclass Classification {\n    #type = null;\n    #url = '';\n    #labels = [];\n    #recordTime = 2000;\n    #result = [];\n\n    constructor({ url, labels, type, recordTime }) {\n        this.#type = type;\n        this.#url = url;\n        this.#labels = labels;\n        this.#recordTime = recordTime;\n        this.load(url);\n    }\n\n    get labels() {\n        return this.#labels;\n    }\n\n    getResult(index) {\n        const result = this.#result || [];\n        const defaultResult = { probability: 0, className: '' };\n        if (index !== undefined && index > -1) {\n            return (\n                result.find(({ className }) => className === this.#labels[index]) || defaultResult\n            );\n        }\n        return result[0] || defaultResult;\n    }\n\n    unbanBlocks(blockMenu) {\n        blockMenu.unbanClass(`ai_learning_classification`);\n        if (this.#type) {\n            blockMenu.unbanClass(`ai_learning_${this.#type}`);\n        }\n    }\n\n    openInputPopup() {\n        Entry.dispatchEvent('openMLInputPopup', {\n            type: this.#type,\n            recordTime: this.#recordTime,\n            predict: async (data) => {\n                this.#result = await this.predict(data);\n            },\n            url: this.#url,\n            labels: this.#labels,\n            setResult: (result) => {\n                this.#result = result;\n            },\n        });\n    }\n\n    async namePredictions(logits) {\n        const values = Array.from(await logits.data());\n        return values\n            .map((probability, index) => ({\n                className: this.#labels[index] || index,\n                probability,\n            }))\n            .sort((a, b) => a.probability > b.probability ? -1 : a.probability < b.probability ? 1 : 0);\n    }\n\n    async predict(tensor) {\n        const logits = this.model.predict(tensor);\n        return await this.namePredictions(logits);\n    }\n\n    async load(url) {\n        this.model = await tf.loadLayersModel(url);\n    }\n\n    async reload(url) {\n        this.model = await tf.loadLayersModel(url || this.#url);\n        this.isLoaded = true;\n    }\n}\n\nexport default Classification;\n"
  },
  {
    "path": "src/class/learning/Svm.js",
    "content": "import LearningBase from './LearningBase';\nimport _floor from 'lodash/floor';\nimport _max from 'lodash/max';\nimport _sum from 'lodash/sum';\nimport _mean from 'lodash/mean';\nimport _toNumber from 'lodash/toNumber';\nimport _isNaN from 'lodash/isNaN';\nimport Utils from './Utils';\nconst SVM = require('libsvm-js/asm');\n\nexport const classes = [\n    'ai_learning_train',\n    'ai_learning_svm',\n    'svm_attr_1',\n    'svm_attr_2',\n    'svm_attr_3',\n    'svm_attr_4',\n    'svm_attr_5',\n    'svm_attr_6',\n];\n\nexport const KERNEL_STRING_TYPE = {\n    LINEAR: 'linear',\n    POLYNOMIAL: 'polynomial',\n    RBF: 'rbf',\n};\n\nexport const OPTION_DEFAULT_VALUE = {\n    epochs: 30,\n    batchSize: 16,\n    k: 4,\n    initialCentroids: 'kmpp',\n    neighbors: 10,\n    validationRate: 0.25,\n    C: 0.00001,\n    degree: 3,\n    gamma: 1,\n};\n\nclass Svm extends LearningBase {\n    type = 'svm';\n\n    init({ name, url, result, table, trainParam, modelId, loadModel }) {\n        this.name = name;\n        this.trainParam = trainParam;\n        this.result = result;\n        this.table = table;\n        this.loadModel = loadModel;\n        this.trainCallback = (value) => {\n            this.view.setValue(value);\n        };\n        // train 확인 필요\n        this.trained = true;\n        this.chartEnable = false;\n        this.attrLength = table?.select?.[0]?.length || 0;\n\n        this.fields = table?.select?.[0]?.map((index) => table?.fields[index]);\n        this.predictFields = table?.select?.[1]?.map((index) => table?.fields[index]);\n        if (this.url !== url || this.modelId !== modelId) {\n            this.load(url, modelId);\n            this.url = url;\n            this.modelId = modelId;\n        }\n    }\n\n    checkTrainOptionValidation() {\n        const { kernel, C, degree, gamma } = this.trainParam;\n        if (!kernel || !C || !degree || !gamma) {\n            throw new Error(\"can't train: trainOptions contain undefined\");\n        }\n        switch (kernel) {\n            case KERNEL_STRING_TYPE.LINEAR:\n                if (\n                    degree !== OPTION_DEFAULT_VALUE.degree ||\n                    gamma !== OPTION_DEFAULT_VALUE.gamma\n                ) {\n                    throw new Error(\n                        `can't train: invalid kernelOption. kernel type ${KERNEL_STRING_TYPE.LINEAR}`\n                    );\n                }\n                break;\n            case KERNEL_STRING_TYPE.POLYNOMIAL:\n                if (gamma !== OPTION_DEFAULT_VALUE.gamma) {\n                    throw new Error(\n                        `can't train: invalid kernelOption. kernel type ${KERNEL_STRING_TYPE.POLYNOMIAL}`\n                    );\n                }\n                break;\n            case KERNEL_STRING_TYPE.RBF:\n                if (degree !== OPTION_DEFAULT_VALUE.degree) {\n                    throw new Error(\n                        `can't train: invalid kernelOption. kernel type ${KERNEL_STRING_TYPE.RBF}`\n                    );\n                }\n                break;\n            default:\n        }\n    }\n\n    async train() {\n        this.trained = false;\n        this.setTable();\n        this.trainCallback(1);\n        this.checkTrainOptionValidation();\n        const { testRate = 0.2, C, kernel, degree, gamma } = this.trainParam;\n        const {\n            trainX,\n            trainY,\n            testArr,\n            select,\n            fields,\n            PREDICT_STR2NUM_MAP,\n            numClass,\n        } = this.getData(testRate, this.table);\n        const svmTrainOption = {\n            kernel,\n            C,\n            degree,\n            gamma,\n        };\n\n        this.predictValueMap = Object.fromEntries(\n            Object.entries(PREDICT_STR2NUM_MAP).map(([key, value]) => [value, key])\n        );\n        this.trainCallback(30);\n\n        this.model = createModel();\n        trainModel(this.model, trainX, trainY, svmTrainOption);\n        this.trainCallback(80);\n\n        const { confusionMatrix, score } = this.evaluate(this.model, testArr, numClass);\n\n        const { accuracy, f1, precision, recall } = score;\n\n        this.trainCallback(100);\n        this.trained = true;\n        this.result = {\n            select,\n            fields,\n            confusionMatrix,\n            accuracy,\n            f1,\n            valueMap: this.predictValueMap,\n            precision,\n            recall,\n        };\n    }\n\n    async load(url, modelId) {\n        const data = await this.loadModel({ url, modelId });\n        if (!data) {\n            return;\n        }\n        const { serializeModel, result } = data;\n        this.model = SVM.load(serializeModel);\n        this.valueMap = result?.valueMap;\n        this.result = result;\n    }\n\n    // INFO: 예상치 전체를 가져옴. Deeplearning 레포의 predictArrays와 동일\n    async predict(array) {\n        if (!this.model) {\n            throw new Error(\"can't predict: no model\");\n        }\n        const xs = [array];\n        const preds = this.model.predict(xs);\n        this.predictResult = preds.map((target) => ({\n            className: this.valueMap[target + 1],\n            probability: 1,\n        }));\n    }\n\n    getData(testRate, data) {\n        const STR2NUM_MAP = {};\n        const STR2NUM_MAP_COUNT = {};\n        const { select = [[0], [1]], data: table, fields } = data;\n        const [attr, predict] = select;\n        const filtered = table.filter(\n            (row) => !select[0].some((selected) => _isNaN(_toNumber(row[selected])))\n        );\n        const dataArray = filtered\n            .map((row) => ({\n                x: attr.map((i) => parseFloat(row[i]) || 0),\n                y: Utils.stringToNumber(\n                    predict[0],\n                    row[predict[0]],\n                    STR2NUM_MAP,\n                    STR2NUM_MAP_COUNT\n                ),\n            }))\n            .map((row) => ({\n                x: row.x,\n                y: row.y - 1,\n            }));\n        const { trainArr, testArr } = this.sliceArray(dataArray, testRate);\n        return {\n            trainX: trainArr.map((v) => v.x),\n            trainY: trainArr.map((v) => v.y),\n            testArr,\n            select,\n            fields,\n            PREDICT_STR2NUM_MAP: { ...STR2NUM_MAP[predict[0]] },\n            numClass: STR2NUM_MAP_COUNT[predict[0]],\n        };\n    }\n\n    sliceArray(dataArray, testRate) {\n        Utils.shuffle(dataArray);\n        const testNum = Math.floor(dataArray.length * testRate);\n        const testArr = dataArray.slice(0, testNum);\n        const trainArr = dataArray.slice(testNum, dataArray.length);\n        return { trainArr, testArr };\n    }\n\n    evaluate(model, validateData, numClass) {\n        const xs = validateData.map((data) => data.x);\n        const ys = validateData.map((data) => data.y);\n        const predictYs = model.predict(xs);\n        const length = predictYs.length;\n\n        const confusionMatrix = Array(numClass)\n            .fill(0)\n            .map(() => Array(numClass).fill(0));\n\n        for (let idx = 0; idx < length; idx++) {\n            confusionMatrix[ys[idx]][predictYs[idx]]++;\n        }\n        const score = Utils.getScores(confusionMatrix, numClass);\n        return { confusionMatrix, score };\n    }\n}\n\nexport default Svm;\n\nfunction createModel() {\n    return new SVM({ type: SVM.SVM_TYPES.C_SVC, probabilityEstimates: true });\n}\n\nfunction trainModel(model, samples, labels, svmTrainOption) {\n    let kernelType;\n    if (svmTrainOption.kernel === KERNEL_STRING_TYPE.LINEAR) {\n        kernelType = SVM.KERNEL_TYPES.LINEAR;\n    } else if (svmTrainOption.kernel === KERNEL_STRING_TYPE.POLYNOMIAL) {\n        kernelType = SVM.KERNEL_TYPES.POLYNOMIAL;\n    } else if (svmTrainOption.kernel === KERNEL_STRING_TYPE.RBF) {\n        kernelType = SVM.KERNEL_TYPES.RBF;\n    } else {\n        throw new Error(\"can't create model: unexpected kernel type\");\n    }\n\n    model.free();\n\n    model.kernel = kernelType;\n    model.cost = svmTrainOption.C;\n    model.degree = svmTrainOption.degree;\n    model.gamma = svmTrainOption.gamma;\n\n    model.train(samples, labels);\n}\n"
  },
  {
    "path": "src/class/learning/TextLearning.js",
    "content": "import Bayes, { fromJson } from './bayes';\nimport * as Khaiii from 'khaiii';\n\nexport const classes = [\n    'ai_learning_classification',\n    'ai_learning_text'\n];\n\nconst KhaiiModule = {\n    isInitialized: false,\n    module: undefined,\n    async load(resourceRoot = `${Entry.Utils.getEntryjsPath()}/extern/khaiii`) {\n        if (this.isInitialized) {\n            return;\n        }\n        this.module = await Khaiii.initialize({\n            resourceProvider: 'webfs',\n            resourceRoot,\n        });\n        this.isInitialized = true;\n    },\n};\n\nclass TextNaiveBaye {\n    #type = 'text';\n    #url = '';\n    #labels = [];\n    #popup = null;\n    #result = [];\n    #loadModel;\n\n    constructor({ url, labels, modelId, loadModel }) {\n        this.#url = url;\n        this.#labels = labels;\n        this.#loadModel = loadModel;\n        this.classifier = new Bayes({\n            tokenizer: this.tokenizer,\n        });\n        this.load(url, modelId);\n    }\n\n    get labels() {\n        return this.#labels;\n    }\n\n    unbanBlocks(blockMenu) {\n        blockMenu.unbanClass(`ai_learning_classification`);\n        blockMenu.unbanClass(`ai_learning_text`);\n    }\n\n    isAvailable() {\n        if (!this.isLoaded) {\n            throw new Error('ai learning text model load error');\n        }\n        return true;\n    }\n\n    getResult(index) {\n        const result = this.#result?.length ? this.#result : this.#popup?.result || [];\n        const defaultResult = { probability: 0, className: '' };\n        if (index !== undefined && index > -1) {\n            return (\n                result.find(({ className }) => className === this.#labels[index]) || defaultResult\n            );\n        }\n        return result[0] || defaultResult;\n    }\n\n    openInputPopup() {\n        const isAvailable = this.isAvailable();\n        if (!isAvailable) {\n            return;\n        }\n        this.#result = [];\n        Entry.dispatchEvent('openMLInputPopup', {\n            type: 'text',\n            predict: async (text) => {\n                this.#result = await this.predict(text);\n            },\n            url: this.#url,\n            labels: this.#labels,\n            setResult: (result) => {\n                this.#result = result;\n            },\n        });\n    }\n\n    tokenizer = async (text) => {\n        if (!KhaiiModule.module) {\n            throw new Error('module not loaded');\n        }\n        if (!text) {\n            return [];\n        }\n        const analized = KhaiiModule.module.analyze(text); // 형태소 분석 진행\n        const filtered = analized\n            .map((wordInfo) =>\n                wordInfo.morphs\n                    .filter((morph) => {\n                        const category = morph.tag.charAt(0);\n                        return category === 'V' || category === 'N' || category === 'S';\n                    })\n                    .map((morph) => morph.lex)\n            )\n            .flat();\n        return filtered;\n    };\n\n    async predict(textData) {\n        await KhaiiModule.load();\n        this.#result = await this.classifier.categorize(textData);\n        return this.#result;\n    }\n\n    async load(url, modelId) {\n        const data = await this.#loadModel({ url, modelId });\n        if (!data) {\n            return;\n        }\n        this.classifier = fromJson(JSON.stringify(data));\n        this.classifier.tokenizer = this.tokenizer;\n        this.isLoaded = true;\n    }\n}\n\nexport default TextNaiveBaye;\n"
  },
  {
    "path": "src/class/learning/Utils.ts",
    "content": "const toFixed = (num: number) => parseFloat(num.toFixed(2));\n\nexport const CommonUtil = {\n    isWebGlSupport: () => {\n        try {\n            const currentCanvas = document.createElement('canvas');\n            return !!currentCanvas.getContext('webgl', { premultipliedalpha: false });\n        } catch (e) {\n            console.log('error', e);\n            return false;\n        }\n    },\n    stringToNumber: (\n        i: number,\n        value: string,\n        tempMap: {\n            [key: number]: {\n                [key: string]: number;\n            };\n        },\n        tempMapCount: {\n            [key: string]: number;\n        }\n    ) => {\n        // if (!isNaN(parseFloat(value))) {\n        //     return parseFloat(value);\n        // }\n        if (!tempMap[i]) {\n            tempMap[i] = {};\n        }\n        if (!tempMap[i]?.[value]) {\n            if (!tempMapCount[i]) {\n                tempMapCount[i] = 0;\n            }\n            tempMapCount[i] = tempMapCount[i] + 1;\n            tempMap[i][value] = tempMapCount[i];\n        }\n        return tempMap[i][value];\n    },\n    shuffle: (arr: Array<any>) => {\n        let j;\n        let x;\n        let i;\n        for (i = arr.length; i; i -= 1) {\n            j = Math.floor(Math.random() * i);\n            x = arr[i - 1];\n            arr[i - 1] = arr[j];\n            arr[j] = x;\n        }\n    },\n    getScores: (confusionMatrix: any, numClasses: number) => {\n        let total = 0;\n        let acc = 0;\n        const precisions = [];\n        const recalls = [];\n        for (let i = 0; i < numClasses; i++) {\n            let rowSum = 0;\n            let colSum = 0;\n            for (let j = 0; j < numClasses; j++) {\n                rowSum += confusionMatrix[i][j];\n                colSum += confusionMatrix[j][i];\n            }\n            const matrixValue = confusionMatrix?.[i]?.[i] || 0;\n            precisions.push(confusionMatrix[i][i] / rowSum || 0);\n            recalls.push(confusionMatrix[i][i] / colSum || 0);\n            total += rowSum;\n            acc += matrixValue;\n        }\n        const precision = precisions.reduce((a, b) => a + b, 0) / precisions.length;\n        const recall = recalls.reduce((a, b) => a + b, 0) / recalls.length;\n        return {\n            accuracy: toFixed(acc / total),\n            precision: toFixed(precision),\n            recall: toFixed(recall),\n            f1: toFixed(2 / (1 / precision + 1 / recall)),\n        };\n    },\n    arrayToMatrix(array: Array<number>, columns: number) {\n        return Array(Math.ceil(array.length / columns))\n            .fill('')\n            .reduce((acc, cur, index) => [...acc, [...array].splice(index * columns, columns)], []);\n    },\n};\n\nexport default CommonUtil;\n"
  },
  {
    "path": "src/class/learning/bayes.ts",
    "content": "import sortBy from 'lodash/sortBy';\n\nconst defaultTokenizer = function(text: string) {\n    const rgxPunctuation = /[^(a-zA-ZA-Яa-я0-9_)+\\s]/g;\n    const sanitized = text.replace(rgxPunctuation, ' ');\n    return sanitized.split(/\\s+/);\n};\n\nclass Naivebayes {\n    static STATE_KEYS: Array<keyof Naivebayes> = [\n        'categories',\n        'docCount',\n        'totalDocuments',\n        'vocabulary',\n        'vocabularySize',\n        'wordCount',\n        'wordFrequencyCount',\n        'options'\n    ];\n    public options: {\n        tokenizer?: Function;\n    } = {};\n    public vocabulary: {[key: string]: boolean}  = {};\n    public tokenizer: Function;\n    public vocabularySize= 0;\n    public totalDocuments= 0;\n    public docCount:  {[key: string]: number} = {};\n    public wordCount:  {[key: string]: number} = {};\n    public wordFrequencyCount:  {[key: string]: any}= {};\n    public categories: {[key: string]: boolean} = {};\n\n    constructor(options: any) {\n        if (typeof options !== 'undefined') {\n            if (!options || typeof options !== 'object' || Array.isArray(options)) {\n                throw TypeError(`NaiveBayes got invalid options: ${options}. Pass in an object.`);\n            }\n            this.options = options;\n        }\n        this.tokenizer = this.options.tokenizer || defaultTokenizer;\n    }\n\n    public frequencyTable(tokens: Array<string>) {\n        return tokens.reduce((acc: {[key: string]: number}, cur: string) => {\n            if (!acc[cur]) {\n                acc[cur] = 0;\n            }\n            acc[cur] = acc[cur] + 1;\n            return acc;\n        }, {});\n    }\n\n    public initializeCategory(categoryName: string) {\n        if (!this.categories[categoryName]) {\n            this.docCount[categoryName] = 0;\n            this.wordCount[categoryName] = 0;\n            this.wordFrequencyCount[categoryName] = {};\n            this.categories[categoryName] = true;\n        }\n        return this;\n    }\n\n    public async learn(text: string, category: string) {\n        this.initializeCategory(category);\n        this.docCount[category]++;\n        this.totalDocuments++;\n        const tokens = await this.tokenizer(text);\n        const frequencyTable = this.frequencyTable(tokens);\n\n        Object\n            .keys(frequencyTable)\n            .forEach((token) => {\n                if (!this.vocabulary[token]) {\n                    this.vocabulary[token] = true;\n                    this.vocabularySize++;\n                }\n                const frequencyInText = frequencyTable[token];\n\n                if (!this.wordFrequencyCount[category][token]) {\n                    this.wordFrequencyCount[category][token] = frequencyInText;\n                } else {\n                    this.wordFrequencyCount[category][token] += frequencyInText;\n                }\n                this.wordCount[category] += frequencyInText;\n            });\n        return this;\n    }\n\n    public async categorize(text: string) {\n        // let maxProbability = -Infinity;\n        // let chosenCategory = null;\n        let totalProbabilities = 0;\n        const categoryProbabilities: {[key: string]: number} = {};\n        const tokens = await this.tokenizer(text);\n        const frequencyTable = this.frequencyTable(tokens);\n        Object\n            .keys(this.categories)\n            .forEach((category) => {\n                const categoryProbability = this.docCount[category] / this.totalDocuments;\n                let logProbability = Math.log(categoryProbability);\n                Object\n                    .keys(frequencyTable)\n                    .forEach((token) => {\n                        const frequencyInText = frequencyTable[token];\n                        const tokenProbability = this.tokenProbability(token, category);\n                        logProbability += frequencyInText * Math.log(tokenProbability);\n                    });\n                // if (logProbability > maxProbability) {\n                //     maxProbability = logProbability;\n                //     chosenCategory = category;\n                // }\n                const expected = Math.exp(logProbability);\n                totalProbabilities = totalProbabilities + expected;\n                categoryProbabilities[category] = expected;\n            });\n        const probabilities = Object\n            .keys(categoryProbabilities)\n            .map((category) => ({\n                className: category,\n                probability: categoryProbabilities[category] /= totalProbabilities\n            }));\n        return sortBy(probabilities,['probability']).reverse();\n    }\n\n    private tokenProbability(token: string, category: string) {\n        const wordFrequencyCount = this.wordFrequencyCount[category][token] || 0;\n        const wordCount = this.wordCount[category];\n        return (wordFrequencyCount + 1) / (wordCount + this.vocabularySize);\n    }\n\n    public toJson() {\n        const state = Naivebayes.STATE_KEYS.reduce(\n            (acc: {[key: string]: any}, cur: keyof Naivebayes) => {\n                acc[cur] = this[cur];\n                return acc;\n            }, {});\n        return JSON.stringify(state);\n    }\n}\n\nexport function fromJson(jsonStr: string) {\n    try {\n        const parsed = JSON.parse(jsonStr);\n        const classifier = new Naivebayes(parsed.options);\n        Naivebayes.STATE_KEYS.forEach((k: keyof Naivebayes) => {\n            if (typeof parsed[k] === 'undefined' || parsed[k] === null) {\n                throw new Error(`FromJson: JSON string is missing an expected property: ${k}.`);\n            }\n            classifier[k] = parsed[k];\n        });\n\n        return classifier;\n    } catch (e) {\n        throw new Error('Naivebayes.fromJson expects a valid JSON string.')\n    }\n}\n\nexport default Naivebayes;\n\n"
  },
  {
    "path": "src/class/maxrect-packer/abstract_bin.ts",
    "content": "import { IRectangle } from \"./geom/Rectangle\";\nimport { IOption } from \"./maxrects_packer\";\nimport { ImageRect } from './geom/ImageRect';\n\nexport interface IBin {\n    width: number;\n    height: number;\n    maxWidth: number;\n    maxHeight: number;\n    index:number;\n    freeRects: IRectangle[];\n    rects: ImageRect[];\n    options: IOption;\n}\n\nexport abstract class Bin implements IBin {\n    public width: number;\n    public height: number;\n    public maxWidth: number;\n    public maxHeight: number;\n    public index:number;\n    public freeRects: IRectangle[];\n    public rects: ImageRect[];\n    public options: IOption;\n    public abstract add (rect:ImageRect): boolean;\n\n    protected pushRect(rect:ImageRect, oversized:boolean) {\n        rect.binIndex = this.index;\n        rect.oversized = oversized;\n        this.rects.push(rect);\n    }\n}\n"
  },
  {
    "path": "src/class/maxrect-packer/geom/ImageRect.ts",
    "content": "import { Rectangle } from './Rectangle';\nimport { AtlasTexture } from '../../pixi/atlas/texture/AtlasTexture';\n\nexport class ImageRect extends Rectangle {\n    constructor(public x: number = 0, public y: number = 0, public width: number = 0, public height: number = 0) {\n        super(...arguments);\n        this.dataWidth = width;\n        this.dataHeight = height;\n    }\n    /** @deprecated */\n    scaleFactor:number = 1;\n    scaleFactorX:number = 1;\n    scaleFactorY:number = 1;\n    binIndex:number = -1;\n    /**\n     * 이 값은 bin-packer 에서 할당하는데데, packing 하기 전에 AtlasImageLoadingInfo 에서 resize 를 하기 때문에 true가 될 일이 없음.\n     */\n    oversized:boolean;\n    data:{path:string, tex:AtlasTexture};\n\n    dataWidth:number = 0;\n    dataHeight:number = 0;\n\n\n}"
  },
  {
    "path": "src/class/maxrect-packer/geom/Rectangle.ts",
    "content": "export interface IRectangle {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n}\n\nexport class Rectangle implements IRectangle {\n    constructor (public x: number = 0, public y: number = 0, public width: number = 0, public height: number = 0) {\n    }\n    public static Collide (first: Rectangle, second: Rectangle) { return first.collide(second); }\n    public static Contain (first: Rectangle, second: Rectangle) { return first.contain(second); }\n\n    public area (): number { return this.width * this.height; }\n\n    public collide (rect: Rectangle): boolean {\n        return !(rect.x >= this.x + this.width || rect.x + rect.width <= this.x ||\n                rect.y >= this.y + this.height || rect.y + rect.height <= this.y);\n    }\n\n    public contain (rect: Rectangle): boolean {\n        return (rect.x >= this.x && rect.y >= this.y &&\n                rect.x + rect.width <= this.x + this.width && rect.y + rect.height <= this.y + this.height);\n    }\n\n}\n"
  },
  {
    "path": "src/class/maxrect-packer/maxrects_bin.ts",
    "content": "import { EDGE_MAX_VALUE, IOption } from \"./maxrects_packer\";\nimport { Rectangle, IRectangle } from \"./geom/Rectangle\";\nimport { Bin } from \"./abstract_bin\";\nimport { ImageRect } from './geom/ImageRect';\n\nexport class MaxRectsBin extends Bin {\n    public width: number;\n    public height: number;\n    public freeRects: Rectangle[] = [];\n    public rects: ImageRect[] = [];\n    private verticalExpand: boolean = false;\n    private stage: Rectangle;\n\n    constructor (\n        public index:number,\n        public maxWidth: number = EDGE_MAX_VALUE,\n        public maxHeight: number = EDGE_MAX_VALUE,\n        public border: number = 0,\n        public padding: number = 0,\n        public options: IOption = { smart: true, pot: true, square: true }\n    ) {\n        super();\n        this.width = this.options.smart ? 0 : maxWidth;\n        this.height = this.options.smart ? 0 : maxHeight;\n        this.freeRects.push(new Rectangle(border, border, this.maxWidth + this.padding*2 - this.border, this.maxHeight + this.padding*2 - this.border));\n        this.stage = new Rectangle(0, 0, this.width, this.height);\n    }\n\n    public add (rect:ImageRect): boolean {\n        var PAD = this.padding * 2;\n        var width:number = rect.width;\n        var height:number = rect.height;\n        let node: Rectangle | undefined = this.findNode(width + PAD, height + PAD);\n        if (node) {\n            this.updateBinSize(node);\n            let numRectToProcess = this.freeRects.length;\n            let i: number = 0;\n            while (i < numRectToProcess) {\n                if (this.splitNode(this.freeRects[i], node)) {\n                    this.freeRects.splice(i, 1);\n                    numRectToProcess--;\n                    i--;\n                }\n                i++;\n            }\n            this.pruneFreeList();\n            this.verticalExpand = this.width > this.height ? true : false;\n            rect.x = node.x;\n            rect.y = node.y;\n            this.pushRect(rect, false);\n            return true;\n        } else if (!this.verticalExpand) {\n            if (this.updateBinSize(new Rectangle(this.width + PAD, 0, width + this.padding, height + PAD))\n                || this.updateBinSize(new Rectangle(0, this.height + PAD, width + PAD, height + PAD))) {\n                return this.add(rect);\n            }\n        } else {\n            if (this.updateBinSize(new Rectangle(\n                0, this.height + PAD,\n                width + PAD, height + PAD\n            )) || this.updateBinSize(new Rectangle(\n                this.width + PAD, 0,\n                width + PAD, height + PAD\n            ))) {\n                return this.add(rect);\n            }\n        }\n        return undefined;\n    }\n    /*\n    public add (width: number, height: number, data: any): Rectangle | undefined {\n        let node: Rectangle | undefined = this.findNode(width + this.padding, height + this.padding);\n        if (node) {\n            this.updateBinSize(node);\n            let numRectToProcess = this.freeRects.length;\n            let i: number = 0;\n            while (i < numRectToProcess) {\n                if (this.splitNode(this.freeRects[i], node)) {\n                    this.freeRects.splice(i, 1);\n                    numRectToProcess--;\n                    i--;\n                }\n                i++;\n            }\n            this.pruneFreeList();\n            this.verticalExpand = this.width > this.height ? true : false;\n            let rect: Rectangle = new Rectangle(node.x, node.y, width, height);\n            rect.data = data;\n            this.rects.push(rect);\n            return rect;\n        } else if (!this.verticalExpand) {\n            if (this.updateBinSize(new Rectangle(this.width + this.padding, 0, width + this.padding, height + this.padding))\n                || this.updateBinSize(new Rectangle(0, this.height + this.padding, width + this.padding, height + this.padding))) {\n                return this.add(width, height, data);\n            }\n        } else {\n            if (this.updateBinSize(new Rectangle(\n                0, this.height + this.padding,\n                width + this.padding, height + this.padding\n            )) || this.updateBinSize(new Rectangle(\n                this.width + this.padding, 0,\n                width + this.padding, height + this.padding\n            ))) {\n                return this.add(width, height, data);\n            }\n        }\n        return undefined;\n    }\n    */\n\n    private findNode (width: number, height: number): Rectangle | undefined {\n        let score: number = Number.MAX_VALUE;\n        let areaFit: number;\n        let r: Rectangle;\n        let bestNode: Rectangle | undefined;\n        for (let i in this.freeRects) {\n            r = this.freeRects[i];\n            if (r.width >= width && r.height >= height) {\n                areaFit = r.width * r.height - width * height;\n                if (areaFit < score) {\n                    // bestNode.x = r.x;\n                    // bestNode.y = r.y;\n                    // bestNode.width = width;\n                    // bestNode.height = height;\n                    bestNode = new Rectangle(r.x, r.y, width, height);\n                    score = areaFit;\n                }\n            }\n        }\n        return bestNode;\n    }\n\n    private splitNode (freeRect: Rectangle, usedNode: Rectangle): boolean {\n        // Test if usedNode intersect with freeRect\n        if (!freeRect.collide(usedNode)) return false;\n\n        // Do vertical split\n        if (usedNode.x < freeRect.x + freeRect.width && usedNode.x + usedNode.width > freeRect.x) {\n            // New node at the top side of the used node\n            if (usedNode.y > freeRect.y && usedNode.y < freeRect.y + freeRect.height) {\n                let newNode: Rectangle = new Rectangle(freeRect.x, freeRect.y, freeRect.width, usedNode.y - freeRect.y);\n                this.freeRects.push(newNode);\n            }\n            // New node at the bottom side of the used node\n            if (usedNode.y + usedNode.height < freeRect.y + freeRect.height) {\n                let newNode = new Rectangle(\n                    freeRect.x,\n                    usedNode.y + usedNode.height,\n                    freeRect.width,\n                    freeRect.y + freeRect.height - (usedNode.y + usedNode.height)\n                );\n                this.freeRects.push(newNode);\n            }\n        }\n\n        // Do Horizontal split\n        if (usedNode.y < freeRect.y + freeRect.height &&\n            usedNode.y + usedNode.height > freeRect.y) {\n            // New node at the left side of the used node.\n            if (usedNode.x > freeRect.x && usedNode.x < freeRect.x + freeRect.width) {\n                let newNode = new Rectangle(freeRect.x, freeRect.y, usedNode.x - freeRect.x, freeRect.height);\n                this.freeRects.push(newNode);\n            }\n            // New node at the right side of the used node.\n            if (usedNode.x + usedNode.width < freeRect.x + freeRect.width) {\n                let newNode = new Rectangle(\n                    usedNode.x + usedNode.width,\n                    freeRect.y,\n                    freeRect.x + freeRect.width - (usedNode.x + usedNode.width),\n                    freeRect.height\n                );\n                this.freeRects.push(newNode);\n            }\n        }\n        return true;\n    }\n\n    private pruneFreeList () {\n        // Go through each pair of freeRects and remove any rects that is redundant\n        let i: number = 0;\n        let j: number = 0;\n        let len: number = this.freeRects.length;\n        while (i < len) {\n            j = i + 1;\n            let tmpRect1 = this.freeRects[i];\n            while (j < len) {\n                let tmpRect2 = this.freeRects[j];\n                if (tmpRect2.contain(tmpRect1)) {\n                    this.freeRects.splice(i, 1);\n                    i--;\n                    len--;\n                    break;\n                }\n                if (tmpRect1.contain(tmpRect2)) {\n                    this.freeRects.splice(j, 1);\n                    j--;\n                    len--;\n                }\n                j++;\n            }\n            i++;\n        }\n    }\n\n    private updateBinSize (node: Rectangle): boolean {\n        if (!this.options.smart) return false;\n        if (this.stage.contain(node)) return false;\n        var PAD = this.padding * 2;\n        let tmpWidth: number = Math.max(this.width, node.x + node.width - PAD);\n        let tmpHeight: number = Math.max(this.height, node.y + node.height - PAD);\n        if (this.options.pot) {\n            tmpWidth = Math.pow(2, Math.ceil(Math.log(tmpWidth) * Math.LOG2E));\n            tmpHeight = Math.pow(2, Math.ceil(Math.log(tmpHeight) * Math.LOG2E));\n        }\n        if (this.options.square) {\n            tmpWidth = tmpHeight = Math.max(tmpWidth, tmpHeight);\n        }\n        if (tmpWidth > this.maxWidth + PAD || tmpHeight > this.maxHeight + PAD) {\n            return false;\n        }\n        this.expandFreeRects(tmpWidth + PAD, tmpHeight + PAD);\n        this.width = this.stage.width = tmpWidth;\n        this.height = this.stage.height = tmpHeight;\n        return true;\n    }\n\n    private expandFreeRects (width: number, height: number) {\n        var PAD = this.padding * 2;\n        this.freeRects.forEach((freeRect, index) => {\n            if (freeRect.x + freeRect.width >= Math.min(this.width + PAD, width)) {\n                freeRect.width = width - freeRect.x;\n            }\n            if (freeRect.y + freeRect.height >= Math.min(this.height + PAD, height)) {\n                freeRect.height = height - freeRect.y;\n            }\n        }, this);\n        this.freeRects.push(new Rectangle(this.width + PAD, 0, width - this.width - PAD, height));\n        this.freeRects.push(new Rectangle(0, this.height + PAD, width, height - this.height - PAD));\n        this.freeRects.forEach((freeRect, index) => {\n            if (freeRect.width <= 0 || freeRect.height <= 0) {\n                this.freeRects.splice(index, 1);\n            }\n        }, this);\n        this.pruneFreeList();\n    }\n}\n"
  },
  {
    "path": "src/class/maxrect-packer/maxrects_packer.ts",
    "content": "import { Rectangle, IRectangle } from \"./geom/Rectangle\";\nimport { MaxRectsBin } from \"./maxrects_bin\";\nimport { OversizedElementBin } from \"./oversized_element_bin\";\nimport { Bin, IBin } from \"./abstract_bin\";\nimport { ImageRect } from './geom/ImageRect';\n\nexport const EDGE_MAX_VALUE: number = 4096;\nexport const EDGE_MIN_VALUE: number = 128;\n\n/**\n * Options for MaxRect Packer\n * @property {boolean} options.smart Smart sizing packer (default is true)\n * @property {boolean} options.pot use power of 2 sizing (default is true)\n * @property {boolean} options.square use square size (default is false)\n * @export\n * @interface Option\n */\nexport interface IOption {\n    smart?: boolean;\n    pot?: boolean;\n    square?: boolean;\n}\n\nexport class MaxRectsPacker {\n    public bins: Bin[];\n    /**\n     * Creates an instance of MaxRectsPacker.\n     * @param {number} width of the output atlas (default is 4096)\n     * @param {number} height of the output atlas (default is 4096)\n     * @param {number} border of bin-texture (default is 0)\n     * @param {number} padding between glyphs/images (default is 0)\n     * @param {IOption} [options={}] (Optional) packing options\n     * @memberof MaxRectsPacker\n     */\n    constructor (\n        public width: number = EDGE_MAX_VALUE,\n        public height: number = EDGE_MAX_VALUE,\n        public border: number = 0,\n        public padding: number = 0,\n        public options: IOption = { smart: true, pot: true, square: true }\n    ) {\n        this.bins = [];\n    }\n\n    public add(rect:ImageRect) {\n        var width = rect.width;\n        var height = rect.height;\n        var binIndex:number = this.bins.length;\n        if (width > this.width || height > this.height) {\n            this.bins.push(new OversizedElementBin(binIndex, rect));\n        } else {\n            let added = this.bins.find(bin => bin.add(rect));\n            if (!added) {\n                let bin = new MaxRectsBin(binIndex, this.width, this.height, this.border, this.padding, this.options);\n                bin.add(rect);\n                this.bins.push(bin);\n            }\n        }\n    }\n\n    /**\n     * Add an Array of bins/rectangles to the packer.\n     * Object structure: { width, height, data }\n     * @param {IRectangle[]} rects Array of bin/rectangles\n     * @memberof MaxRectsPacker\n     */\n    public addArray (rects: ImageRect[]) {\n        this.sort(rects).forEach((r:ImageRect) => this.add(r));\n    }\n\n    private sort (rects: IRectangle[]) {\n        return rects.slice().sort((a, b) => Math.max(b.width, b.height) - Math.max(a.width, a.height));\n    }\n\n    public empty() {\n        this.bins.length = 0;\n    }\n}\n"
  },
  {
    "path": "src/class/maxrect-packer/oversized_element_bin.ts",
    "content": "import { IOption } from \"./maxrects_packer\";\nimport { Bin } from \"./abstract_bin\";\nimport { ImageRect } from './geom/ImageRect';\n\nexport class OversizedElementBin extends Bin {\n    public maxWidth: number;\n    public maxHeight: number;\n    public options: IOption;\n\n    constructor (public index:number, rect:ImageRect) {\n        super();\n        this.rects = [];\n        this.freeRects = [];\n        this.maxWidth = rect.width;\n        this.maxHeight = rect.height;\n        this.options = { smart: false, pot: false, square: false };\n        this.pushRect(rect, true);\n    }\n    add (rect:ImageRect): boolean { return false; }\n\n}\n"
  },
  {
    "path": "src/class/object.js",
    "content": "/**;\n * @fileoverview Object for Entry.\n */\n'use strict';\n\nimport DomUtils from '../../src/util/domUtils';\nimport { GEHelper } from '../graphicEngine/GEHelper';\n\nconst _findIndex = require('lodash/findIndex');\n\n/**\n * Class for entry object.\n * @param {?object model} model for object\n * @constructor\n */\nEntry.EntryObject = class {\n    constructor(model) {\n        if (model) {\n            this.id = model.id;\n            this.name = model.name || model.sprite.name;\n            this.text = model.text || this.name;\n            this.objectType = model.objectType || 'sprite';\n            this.script = new Entry.Code(model.script || [], this);\n            this.pictures = Entry.Utils.copy(model.sprite.pictures || []);\n            this.sounds = Entry.Utils.copy(model.sprite.sounds || []);\n\n            this._setFocused = Entry.Utils.setFocused;\n            this._setBlurredTimer = Entry.Utils.setBlurredTimer;\n            this.editObjectValueWhenEnterPress = Entry.Utils.whenEnter(() => {\n                this.editObjectValues(false);\n            });\n\n            this.sounds.forEach((s) => {\n                if (!s.id) {\n                    s.id = Entry.generateHash();\n                }\n                Entry.initSound(s);\n            });\n\n            this.lock = model.lock ? model.lock : false;\n            this.isEditing = false;\n\n            if (this.objectType === 'sprite') {\n                this.selectedPicture = !model.selectedPictureId\n                    ? this.pictures[0]\n                    : this.getPicture(model.selectedPictureId);\n            }\n\n            if (this.sounds?.length) {\n                this.selectedSound = this.sounds[0];\n            }\n\n            this.scene = Entry.scene.getSceneById(model.scene) || Entry.scene.selectedScene;\n\n            this.setRotateMethod(model.rotateMethod);\n\n            //entity\n            this.entity = new Entry.EntityObject(this);\n            this.entity.injectModel(\n                this.selectedPicture ? this.selectedPicture : null,\n                model.entity ? model.entity : this.initEntity(model)\n            );\n\n            this.clonedEntities = [];\n\n            Entry.stage.loadObject(this);\n\n            const pictures = this.pictures;\n\n            for (const i in pictures) {\n                const picture = pictures[i];\n                picture.objectId = this.id;\n                if (!picture.id) {\n                    picture.id = Entry.generateHash();\n                }\n                GEHelper.resManager.reqResource(null, this.scene.id, picture);\n            }\n            Entry.requestUpdate = true;\n        }\n\n        this._isContextMenuEnabled = true;\n\n        this.isFolded = false;\n    }\n\n    /**\n     * View generator for workspace or others.\n     * Entry.type === 'phone' 관련 뷰 삭제\n     * @return {!Element}\n     */\n    generateView() {\n        return this.generateWorkspaceView();\n    }\n\n    /**\n     * Object name setter\n     * @param {!string} name\n     */\n    setName(name) {\n        Entry.assert(typeof name === 'string', 'object name must be string');\n\n        this.name = name;\n        if (this.nameView_) {\n            this.nameView_.value = name;\n        }\n    }\n\n    getName() {\n        return this.name;\n    }\n\n    /**\n     * Object text setter\n     * @param {!string} name\n     */\n    setText(text) {\n        Entry.assert(typeof text === 'string', 'object text must be string');\n        this.text = text;\n    }\n\n    /**\n     * Object script setter\n     * @param {!xml script} script\n     */\n    setScript(script) {\n        this.script = script;\n    }\n\n    /**\n     * Object script getter\n     * @return {!xml script} script\n     */\n    getScriptText() {\n        return this.script.stringify();\n    }\n\n    /**\n     * Initialize entity model if not exist\n     * @param {!object model} model for object\n     * @return {entity model}\n     */\n    initEntity(model) {\n        const json = {};\n        json.rotation = json.x = json.y = 0;\n        json.direction = 90;\n\n        if (this.objectType == 'sprite') {\n            const dimension = model.sprite.pictures[0].dimension;\n            json.regX = dimension.width / 2;\n            json.regY = dimension.height / 2;\n            let scale;\n            const mainCategory = model.sprite.category.main;\n            if (mainCategory == 'background' || mainCategory == 'new') {\n                scale = Math.max(270 / dimension.height, 480 / dimension.width);\n            } else if (mainCategory == 'new') {\n                scale = 1;\n            } else {\n                scale = 200 / (dimension.width + dimension.height);\n            }\n\n            json.scaleX = json.scaleY = scale;\n            json.width = dimension.width;\n            json.height = dimension.height;\n        } else if (this.objectType == 'textBox') {\n            json.regX = 25;\n            json.regY = 12;\n            json.scaleX = json.scaleY = 1.5;\n            json.width = 50;\n            json.height = 24;\n            json.text = model.text;\n            if (model.options) {\n                const options = model.options;\n                let fontStyle = '';\n                const {\n                    fontSize = 20,\n                    textAlign = 0,\n                    scaleX = 1.5,\n                    regX,\n                    regY,\n                    width,\n                    height,\n                } = options;\n                if (options.bold) {\n                    fontStyle += 'bold ';\n                }\n                if (options.italic) {\n                    fontStyle += 'italic ';\n                }\n\n                json.underLine = options.underLine;\n                json.strike = options.strike;\n                if (typeof options.font === 'string') {\n                    json.font = options.font;\n                } else {\n                    json.font = `${fontStyle}${fontSize}px ${options.font.family}`;\n                }\n                json.colour = options.colour;\n                json.bgColor = options.bgColor || options.background;\n                json.lineBreak = options.lineBreak;\n                json.textAlign = textAlign;\n                json.scaleX = json.scaleY = scaleX;\n                if (options.lineBreak) {\n                    json.width = width || 256;\n                    json.height = height || json.width * 0.5625;\n                    json.regX = regX || json.width / 2;\n                    json.regY = regY || json.height / 2;\n                }\n            } else {\n                json.underLine = false;\n                json.strike = false;\n                json.font = '20px Nanum Gothic';\n                json.colour = '#000000';\n                json.bgColor = '#ffffff';\n            }\n        }\n\n        return json;\n    }\n\n    /**\n     * Update thumbnail view;\n     */\n    updateThumbnailView() {\n        const thumb = this.thumbnailView_;\n        const picture = this.entity.picture;\n        const objectType = this.objectType;\n        this.thumbUrl = '';\n        if (objectType === 'sprite') {\n            if (picture.thumbUrl || picture.fileurl) {\n                this.thumbUrl = picture.thumbUrl || picture.fileurl;\n            } else {\n                const fileName = picture.filename;\n                this.thumbUrl = `${Entry.defaultPath}/uploads/${fileName.substring(\n                    0,\n                    2\n                )}/${fileName.substring(2, 4)}/thumb/${fileName}.png`;\n            }\n            thumb.style.backgroundImage = `url(${encodeURI(this.thumbUrl)})`;\n        } else if (objectType === 'textBox') {\n            const { type } = Lang || {};\n            const filename = type === 'ko' ? 'text_icon_ko.svg' : 'text_icon.svg';\n            this.thumbUrl = `${Entry.mediaFilePath}${filename}`;\n            $(thumb).addClass('entryObjectTextBox');\n        }\n    }\n\n    /**\n     * Update coordinate view;\n     */\n    updateCoordinateView(isForced) {\n        if (!this.isSelected() && !isForced) {\n            return;\n        }\n\n        const view = this.coordinateView_;\n        if (view && view.xInput_ && view.yInput_) {\n            const originX = view.xInput_.value;\n            const originY = view.yInput_.value;\n            const size = view.sizeInput_.value;\n            const entity = this.entity;\n            const newX = entity.getX(1);\n            const newY = entity.getY(1);\n            const newSize = entity.getSize(1);\n\n            if (originX != newX) {\n                view.xInput_.value = newX;\n            }\n            if (originY != newY) {\n                view.yInput_.value = newY;\n            }\n            if (size != newSize) {\n                view.sizeInput_.value = newSize;\n            }\n        }\n    }\n\n    /**\n     * Update rotation view;\n     */\n    updateRotationView(isForced) {\n        if ((!this.isSelected() || !this.view_) && !isForced) {\n            return;\n        }\n        const rotateMethod = this.getRotateMethod();\n        const entity = this.entity;\n        const className = 'entryRemove';\n\n        if (rotateMethod === 'free') {\n            this.rotateWrapper_.removeClass(className);\n            this.rotateInput_.value = `${entity.getRotation(1)}`;\n            this.directionInput_.value = `${entity.getDirection(1)}`;\n        } else {\n            this.rotateWrapper_.addClass(className);\n            this.directionInput_.value = `${entity.getDirection(1)}`;\n        }\n    }\n\n    /**\n     * Add picture object by picture model.\n     * @param {picture model} picture\n     */\n    addPicture(picture, index) {\n        picture.objectId = this.id;\n\n        if (typeof index === 'undefined') {\n            this.pictures.push(picture);\n        } else {\n            this.pictures.splice(index, 0, picture);\n        }\n\n        Entry.playground.injectPicture(this);\n    }\n\n    /**\n     * Remove picture object.\n     * @param {string} pictureId\n     * @return {boolean} return true if success\n     */\n    removePicture(pictureId) {\n        const pictures = this.pictures;\n        if (pictures.length < 2) {\n            return;\n        }\n\n        const playground = Entry.playground;\n        const picture = this.getPicture(pictureId);\n\n        pictures.splice(pictures.indexOf(picture), 1);\n        if (picture === this.selectedPicture) {\n            playground.selectPicture(pictures[0], true);\n        }\n        GEHelper.resManager.imageRemoved('EntityObject::removePicture');\n        playground.injectPicture(this);\n        playground.reloadPlayground();\n    }\n\n    /**\n     * Get picture object by Id.\n     * @param {?string} pictureId\n     * @return {picture object}\n     */\n    getPicture(value) {\n        //priority\n        //1. pictureId\n        //2. pictureName\n        //3. index\n        if (!value) {\n            return this.selectedPicture;\n        }\n\n        value = `${value}`.trim();\n        const pictures = this.pictures;\n        const len = pictures.length;\n\n        for (let i = 0; i < len; i++) {\n            if (pictures[i].id == value) {\n                return pictures[i];\n            }\n        }\n\n        for (let i = 0; i < len; i++) {\n            if (pictures[i].name == value) {\n                return pictures[i];\n            }\n        }\n\n        const checker = Entry.parseNumber(value);\n        if (!(checker === false && typeof checker === 'boolean') && len >= checker && checker > 0) {\n            return pictures[checker - 1];\n        }\n        return null;\n    }\n\n    getPictureIndex(value) {\n        return this.pictures.indexOf(this.getPicture(value));\n    }\n\n    /**\n     * Get previous picture object by Id.\n     * @param {?string} pictureId\n     * @return {picture object}\n     */\n    getPrevPicture(pictureId) {\n        const pictures = this.pictures;\n        let idx = this.getPictureIndex(pictureId);\n        return pictures[idx === 0 ? pictures.length - 1 : --idx];\n    }\n\n    /**\n     * Get next picture object by Id.\n     * @param {?string} pictureId\n     * @return {picture object}\n     */\n    getNextPicture(pictureId) {\n        const pictures = this.pictures;\n        const len = pictures.length;\n        let idx = this.getPictureIndex(pictureId);\n        return pictures[idx == len - 1 ? 0 : ++idx];\n    }\n\n    /**\n     * Select picture object by Id.\n     * @param {!string} pictureId\n     * @return {picture object}\n     */\n    selectPicture(pictureId) {\n        const picture = this.getPicture(pictureId);\n        if (!picture) {\n            throw new Error(`No picture with pictureId : ${pictureId}`);\n        }\n\n        this.selectedPicture = picture;\n        this.entity.setImage(picture);\n        this.updateThumbnailView();\n    }\n\n    selectSound(soundId) {\n        const sound = this.getSound(soundId);\n        if (!sound) {\n            throw new Error(`No sound with soundId : ${soundId}`);\n        }\n        this.selectedSound = sound;\n    }\n\n    /**\n     * Add sound to object\n     * @param {sound model} sound\n     */\n    addSound(sound, index) {\n        if (!sound.id) {\n            sound.id = Entry.generateHash();\n        }\n\n        Entry.initSound(sound, index);\n\n        if (typeof index === 'undefined') {\n            this.sounds.push(sound);\n        } else {\n            this.sounds.splice(index, 0, sound);\n        }\n\n        Entry.playground.injectSound(this);\n    }\n\n    /**\n     * Remove sound object.\n     * @param {string} soundId\n     */\n    removeSound(soundId) {\n        const playground = Entry.playground;\n        const sound = this.getSound(soundId);\n\n        const index = _findIndex(this.sounds, (sound) => sound.id === soundId);\n        this.sounds.splice(index, 1);\n        if (sound === this.selectedSound) {\n            if (this.sounds?.length) {\n                playground.selectSound(this.sounds[0], true);\n            } else {\n                this.selectedSound = undefined;\n            }\n        }\n\n        Entry.playground.injectSound();\n        Entry.playground.reloadPlayground();\n    }\n\n    /**\n     * rotate method getter\n     * @return {string}\n     */\n    getRotateMethod() {\n        if (!this.rotateMethod) {\n            this.rotateMethod = 'free';\n        }\n\n        return this.rotateMethod;\n    }\n\n    /**\n     * rotate method setter\n     * @param {string} rotateMethod\n     */\n    setRotateMethod(rotateMethod = 'free') {\n        /** @type {string} */\n        this.rotateMethod = rotateMethod;\n        this.updateRotateMethodView();\n\n        const stage = Entry.stage;\n        const entity = stage.selectedObject && stage.selectedObject.entity;\n\n        if (entity) {\n            stage.updateObject();\n            stage.updateHandle();\n        }\n    }\n\n    initRotateValue(rotateMethod) {\n        if (this.rotateMethod === rotateMethod) {\n            return;\n        }\n\n        const entity = this.entity;\n        const direction = entity.direction;\n        entity.direction = direction !== undefined ? direction : 90.0;\n        entity.rotation = 0.0;\n        entity.flip = false;\n    }\n\n    updateRotateMethodView() {\n        if (!this.rotateModeAView_) {\n            return;\n        }\n\n        const SELECTED = 'selected';\n\n        this.rotateModeAView_.removeClass(SELECTED);\n        this.rotateModeBView_.removeClass(SELECTED);\n        this.rotateModeCView_.removeClass(SELECTED);\n\n        const rotateMethod = this.rotateMethod;\n        if (rotateMethod === 'free') {\n            this.rotateModeAView_.addClass(SELECTED);\n        } else if (rotateMethod === 'vertical') {\n            this.rotateModeBView_.addClass(SELECTED);\n        } else {\n            this.rotateModeCView_.addClass(SELECTED);\n        }\n\n        this.updateRotationView();\n    }\n\n    /**\n     * Add clone entity for clone block\n     * If parameter given, this clone the parameter entity itself.\n     * Otherwise, this clone this object's entity.\n     * @param {?Entry.EntryObject} object\n     * @param {?Entry.EntityObject} entity\n     * @param {?xml block} script\n     */\n    addCloneEntity(object, entity, script) {\n        if (this.clonedEntities.length > Entry.maxCloneLimit) {\n            return;\n        }\n\n        const clonedEntity = new Entry.EntityObject(this);\n        clonedEntity.isClone = true;\n\n        entity = entity || this.entity;\n\n        clonedEntity.injectModel(entity.picture || null, entity.toJSON());\n        clonedEntity.snapshot_ = entity.snapshot_;\n\n        if (entity.effect) {\n            clonedEntity.effect = _.clone(entity.effect);\n            clonedEntity.applyFilter();\n        }\n\n        Entry.engine.raiseEventOnEntity(clonedEntity, [clonedEntity, 'when_clone_start']);\n\n        clonedEntity.isStarted = true;\n        this.addCloneVariables(\n            this,\n            clonedEntity,\n            entity ? entity.variables : null,\n            entity ? entity.lists : null\n        );\n\n        this.clonedEntities.push(clonedEntity);\n        let targetIndex = Entry.stage.selectedObjectContainer.getChildIndex(entity.object);\n\n        const offsetCount = (entity.shapes.length ? 1 : 0) + (entity.paintShapes.length ? 1 : 0);\n        targetIndex -= offsetCount + entity.stamps.length;\n\n        Entry.stage.loadEntity(clonedEntity, targetIndex);\n\n        if (entity.brush) {\n            Entry.setCloneBrush(clonedEntity, entity.brush);\n        }\n    }\n\n    /**\n     * return true when object is selected\n     * @return {Boolean}\n     */\n    isSelected() {\n        return this.isSelected_;\n    }\n\n    /**\n     * convert this object's data to JSON.\n     * @return {JSON}\n     */\n    toJSON(isClone) {\n        const json = {};\n        json.id = isClone ? Entry.generateHash() : this.id;\n        json.name = this.name;\n        json.script = this.getScriptText();\n        json.objectType = this.objectType;\n        json.rotateMethod = this.getRotateMethod();\n        json.scene = this.scene.id;\n        json.sprite = {\n            pictures: Entry.getPicturesJSON(this.pictures, isClone),\n            sounds: Entry.getSoundsJSON(this.sounds, isClone),\n        };\n        if (this.objectType === 'textBox') {\n            json.text = this.text;\n        } else {\n            json.selectedPictureId =\n                json.sprite.pictures[this.pictures.indexOf(this.selectedPicture)].id;\n        }\n        json.lock = this.lock;\n        json.entity = this.entity.toJSON();\n        return json;\n    }\n\n    /**\n     * destroy this object\n     */\n    destroy() {\n        this.entity && this.entity.destroy();\n        Entry.removeElement(this.view_);\n    }\n\n    /**\n     * Get sound object by Id.\n     * @param {?string} soundId\n     * @return {sound object}\n     */\n    getSound(value) {\n        //priority\n        //1. soundId\n        //2. soundName\n        //3. index\n        if (!value) {\n            return this.selectedSound;\n        }\n\n        value = String(value).trim();\n        const sounds = this.sounds;\n        const len = sounds.length;\n\n        for (let i = 0; i < len; i++) {\n            if (sounds[i].id == value) {\n                return sounds[i];\n            }\n        }\n\n        for (let i = 0; i < len; i++) {\n            if (sounds[i].name == value) {\n                return sounds[i];\n            }\n        }\n\n        const checker = Entry.parseNumber(value);\n        if (!(checker === false && typeof checker === 'boolean') && len >= checker && checker > 0) {\n            return sounds[checker - 1];\n        }\n\n        return null;\n    }\n\n    addCloneVariables({ id }, entity, variables, lists) {\n        const _whereFunc = _.partial(_.filter, _, { object_: id });\n        const _cloneFunc = (v) => v.clone();\n        const { variables_, lists_ } = Entry.variableContainer;\n\n        entity.variables = (variables || _whereFunc(variables_)).map(_cloneFunc);\n        entity.lists = (lists || _whereFunc(lists_)).map(_cloneFunc);\n    }\n\n    getLock() {\n        return this.lock;\n    }\n\n    setLock(bool) {\n        this.lock = bool;\n        Entry.stage.updateObject();\n        return bool;\n    }\n\n    updateInputViews(isLocked) {\n        isLocked = isLocked || this.getLock();\n        const inputs = [\n            this.nameView_,\n            this.coordinateView_.xInput_,\n            this.coordinateView_.yInput_,\n            this.rotateInput_,\n            this.directionInput_,\n            this.coordinateView_.sizeInput_,\n        ];\n\n        if (isLocked) {\n            inputs.forEach((input) => {\n                input.setAttribute('disabled', 'disabled');\n            });\n        } else {\n            inputs.forEach((input) => {\n                input.removeAttribute('disabled');\n            });\n        }\n\n        this.isEditing = !isLocked;\n    }\n\n    editObjectValues(activate) {\n        const inputs = [\n            this.nameView_,\n            this.coordinateView_.xInput_,\n            this.coordinateView_.yInput_,\n            this.rotateInput_,\n            this.directionInput_,\n            this.coordinateView_.sizeInput_,\n        ];\n\n        if (activate && !this.isEditing) {\n            this.isEditing = true;\n        } else {\n            inputs.forEach((input) => {\n                input.blur(true);\n            });\n\n            this.isEditing = false;\n        }\n    }\n\n    /**\n     *  get only clonedEntities among clonedEntities except for stamp entity\n     *  @return {Array<clone Entity> } entities\n     */\n    getClonedEntities() {\n        return this.clonedEntities.concat();\n    }\n\n    clearExecutor() {\n        this.script.clearExecutors();\n\n        const clonedEntities = this.clonedEntities;\n        for (let j = clonedEntities.length - 1; j >= 0; j--) {\n            clonedEntities[j].removeClone(true);\n        }\n        this.entity.removeStamps();\n    }\n\n    _rightClick(e) {\n        if (!this.isContextMenuEnabled()) {\n            return;\n        }\n        e.stopPropagation();\n\n        const object = this;\n        const container = Entry.container;\n        const objects = container._getSortableObjectList();\n        const objectIndex = objects.findIndex((item) => item.key == this.id);\n        const contextMenus = [\n            {\n                text: Lang.Workspace.context_duplicate,\n                enable: !Entry.engine.isState('run'),\n                callback() {\n                    container.addCloneObject(object);\n                },\n            },\n            {\n                text: Lang.Workspace.copy_file,\n                callback() {\n                    container.setCopiedObject(object);\n                },\n            },\n            {\n                text: Lang.Blocks.Paste_blocks,\n                enable: !Entry.engine.isState('run') && !!container.copiedObject,\n                callback() {\n                    if (container.copiedObject) {\n                        container.addCloneObject(container.copiedObject);\n                    } else {\n                        Entry.toast.alert(\n                            Lang.Workspace.add_object_alert,\n                            Lang.Workspace.object_not_found_for_paste\n                        );\n                    }\n                },\n            },\n            {\n                text: Lang.Workspace.context_remove,\n                enable: !Entry.engine.isState('run') && !this.getLock(),\n                callback: () => {\n                    if (this.getLock()) {\n                        return true;\n                    }\n                    Entry.dispatchEvent('removeObject', object);\n                    const { id } = object;\n                    Entry.do('removeObject', id);\n                    Entry.Utils.forceStopSounds();\n                },\n            },\n            {\n                text: Lang.Workspace.bring_forward,\n                enable: objectIndex > 0,\n                callback() {\n                    Entry.do('objectReorder', objectIndex - 1, objectIndex);\n                },\n            },\n            {\n                text: Lang.Workspace.send_backward,\n                enable: objectIndex < objects.length - 1,\n                callback() {\n                    Entry.do('objectReorder', objectIndex + 1, objectIndex);\n                },\n            },\n        ];\n\n        if (!Entry.backpackDisable) {\n            contextMenus.push({\n                text: Lang.Blocks.add_my_storage,\n                enable: !Entry.engine.isState('run') && !!window.user,\n                callback: () => {\n                    this.addStorage();\n                },\n            });\n        }\n\n        if (Entry.exportObjectEnable) {\n            contextMenus.push({\n                text: Lang.Blocks.export_object,\n                callback() {\n                    Entry.dispatchEvent('exportObject', object);\n                },\n            });\n        }\n\n        const { clientX: x, clientY: y } = Entry.Utils.convertMouseEvent(e);\n        Entry.ContextMenu.show(contextMenus, 'workspace-contextmenu', { x, y });\n    }\n\n    addStorage() {\n        Entry.dispatchEvent('addStorage', {\n            type: 'object',\n            data: this,\n        });\n    }\n\n    enableContextMenu() {\n        this._isContextMenuEnabled = true;\n    }\n\n    disableContextMenu() {\n        this._isContextMenuEnabled = false;\n    }\n\n    isContextMenuEnabled() {\n        return this._isContextMenuEnabled && Entry.objectEditable;\n    }\n\n    toggleEditObject() {\n        if (this.isEditing || Entry.engine.isState('run')) {\n            return;\n        }\n\n        this.editObjectValues(true);\n        if (Entry.playground.object !== this) {\n            Entry.container.selectObject(this.id);\n        }\n    }\n\n    getDom(query) {\n        if (_.isEmpty(query)) {\n            return this.view_;\n        }\n\n        switch (query.shift()) {\n            case 'editButton':\n                return this.editView_;\n            case 'nameInput':\n                return this.nameView_;\n            case 'removeButton':\n                return this.deleteView_;\n            case 'xInput':\n                return this.coordinateView_.xInput_;\n            case 'yInput':\n                return this.coordinateView_.yInput_;\n            case 'sizeInput':\n                return this.coordinateView_.sizeInput_;\n            case 'directionInput':\n                return this.directionInput_;\n            case 'rotationInput':\n                return this.rotateInput_;\n            case 'rotationMethod':\n                return this._getRotateView(query.shift());\n        }\n    }\n\n    setInputBlurred(...target) {\n        target = this.getDom(target);\n        if (!target) {\n            return;\n        }\n        target._focused = false;\n    }\n\n    generateWorkspaceView() {\n        const exceptionsForMouseDown = [];\n\n        const that = this;\n        const objectId = this.id;\n\n        this.view_ = this.createObjectView(objectId, exceptionsForMouseDown); // container\n        if (!Entry.objectEditable) {\n            this.view_.addClass('entryDisabled');\n        }\n        this.view_.appendChild(this.createObjectInfoView()); // visible, lock\n\n        const thumbnailView = this.createThumbnailView(objectId); // thumbnail\n        this.thumbnailView_ = thumbnailView;\n        this.view_.appendChild(thumbnailView);\n\n        this.view_.appendChild(this.createWrapperView()); // name space\n\n        const informationView = this.createInformationView();\n        this.informationView_ = informationView;\n        this.view_.appendChild(informationView);\n\n        const deleteView = this.createDeleteView(exceptionsForMouseDown, that); // delete\n        this.deleteView_ = deleteView;\n        this.view_.appendChild(deleteView);\n\n        const rotationWrapperView = this.createRotationWrapperView();\n        this.view_.appendChild(rotationWrapperView);\n\n        this.updateThumbnailView();\n        this.updateRotateMethodView();\n        this.updateInputViews();\n\n        this.updateCoordinateView(true);\n        this.updateRotationView(true);\n\n        if (!Entry.objectEditable) {\n            this.setDisabled();\n        } else {\n            Entry.addEventListener('run', this.setDisabled);\n            Entry.addEventListener('dispatchEventDidToggleStop', this.setEnabled);\n        }\n\n        return this.view_;\n    }\n\n    createRotationMethodWrapperView() {\n        const rotationMethodWrapper = Entry.createElement('div').addClass('rotationMethodWrapper');\n\n        const rotateMethodLabelView = Entry.createElement('span').addClass(\n            'entryObjectRotateMethodLabelWorkspace'\n        );\n        rotationMethodWrapper.appendChild(rotateMethodLabelView);\n        rotateMethodLabelView.textContent = `${Lang.Workspace.rotate_method}`;\n\n        const rotateModeAView = Entry.createElement('span').addClass(\n            'entryObjectRotateModeWorkspace entryObjectRotateModeAWorkspace'\n        );\n        this.rotateModeAView_ = rotateModeAView;\n        rotationMethodWrapper.appendChild(rotateModeAView);\n        rotationMethodWrapper.appendChild(rotateModeAView);\n\n        if (Entry.objectEditable) {\n            rotateModeAView.bindOnClick(\n                this._whenRotateEditable(() => {\n                    Entry.do('objectUpdateRotateMethod', this.id, 'free');\n                }, this)\n            );\n        }\n\n        const rotateModeBView = Entry.createElement('span').addClass(\n            'entryObjectRotateModeWorkspace entryObjectRotateModeBWorkspace'\n        );\n        this.rotateModeBView_ = rotateModeBView;\n        rotationMethodWrapper.appendChild(rotateModeBView);\n        if (Entry.objectEditable) {\n            rotateModeBView.bindOnClick(\n                this._whenRotateEditable(() => {\n                    Entry.do('objectUpdateRotateMethod', this.id, 'vertical');\n                }, this)\n            );\n        }\n\n        const rotateModeCView = Entry.createElement('span').addClass(\n            'entryObjectRotateModeWorkspace entryObjectRotateModeCWorkspace'\n        );\n        this.rotateModeCView_ = rotateModeCView;\n        rotationMethodWrapper.appendChild(rotateModeCView);\n        if (Entry.objectEditable) {\n            rotateModeCView.bindOnClick(\n                this._whenRotateEditable(() => {\n                    Entry.do('objectUpdateRotateMethod', this.id, 'none');\n                }, this)\n            );\n        }\n\n        return rotationMethodWrapper;\n    }\n\n    createRotateLabelWrapperView() {\n        const rotateLabelWrapperView = Entry.createElement('div').addClass(\n            'entryObjectRotateLabelWrapperWorkspace'\n        );\n\n        const rotateWrapper = Entry.createElement('span').addClass(\n            'entryObjectRotateWorkspaceWrapper'\n        );\n        const rotateSpan = Entry.createElement('span').addClass('entryObjectRotateSpanWorkspace');\n        rotateSpan.textContent = `${Lang.Workspace.rotation}`;\n        const RotateDegCoordi = Entry.createElement('span').addClass(\n            'entryObjectCoordinateSpanWorkspace degree'\n        );\n\n        const rotateInput = Entry.createElement('input').addClass(\n            'entryObjectRotateInputWorkspace'\n        );\n        rotateInput.setAttribute('type', 'text');\n        rotateInput.onkeypress = this.editObjectValueWhenEnterPress;\n        rotateInput.onfocus = this._setFocused;\n        rotateInput.onblur = this._setBlurredTimer(() => {\n            const object = Entry.container.getObject(this.id);\n            if (!object) {\n                return;\n            }\n            let value = rotateInput.value;\n            const idx = value.indexOf('˚');\n            if (~idx) {\n                value = value.substring(0, idx);\n            }\n\n            Entry.do(\n                'objectUpdateRotationValue',\n                this.id,\n                Entry.Utils.isNumber(value) ? value : this.entity.getRotation()\n            );\n        });\n\n        this.rotateWrapper_ = rotateWrapper;\n        this.rotateSpan_ = rotateSpan;\n        this.rotateInput_ = rotateInput;\n\n        const directionWrapper = Entry.createElement('span').addClass(\n            'entryObjectDirectionWorkspaceWrapper'\n        );\n        const directionSpan = Entry.createElement('span').addClass(\n            'entryObjectDirectionSpanWorkspace'\n        );\n        directionSpan.textContent = `${Lang.Workspace.direction}`;\n        const DirectionDegCoordi = Entry.createElement('span').addClass(\n            'entryObjectCoordinateSpanWorkspace degree'\n        );\n        const directionInput = Entry.createElement('input').addClass(\n            'entryObjectDirectionInputWorkspace'\n        );\n        directionInput.setAttribute('type', 'text');\n        directionInput.onkeypress = this.editObjectValueWhenEnterPress;\n        directionInput.onfocus = this._setFocused;\n        directionInput.onblur = this._setBlurredTimer(() => {\n            const object = Entry.container.getObject(this.id);\n            if (!object) {\n                return;\n            }\n            let value = directionInput.value;\n            const idx = value.indexOf('˚');\n            if (~idx) {\n                value = value.substring(0, idx);\n            }\n\n            Entry.do(\n                'objectUpdateDirectionValue',\n                this.id,\n                Entry.Utils.isNumber(value) ? value : this.entity.getDirection()\n            );\n        });\n\n        this.directionInput_ = directionInput;\n        rotateWrapper.appendChild(rotateSpan);\n        rotateWrapper.appendChild(rotateInput);\n        rotateWrapper.appendChild(RotateDegCoordi);\n        directionWrapper.appendChild(directionSpan);\n        directionWrapper.appendChild(directionInput);\n        directionWrapper.appendChild(DirectionDegCoordi);\n\n        rotateLabelWrapperView.appendChild(rotateWrapper);\n        rotateLabelWrapperView.appendChild(directionWrapper);\n        rotateLabelWrapperView.rotateInput_ = rotateInput;\n        rotateLabelWrapperView.directionInput_ = directionInput;\n\n        return rotateLabelWrapperView;\n    }\n\n    createCoordinationView() {\n        const coordinationView = Entry.createElement('div').addClass(\n            'entryObjectCoordinateWorkspace'\n        );\n\n        const xCoordiWrapper = Entry.createElement('span').addClass(\n            'entryObjectCoordinateWorkspaceWrapper'\n        );\n        const xCoordi = Entry.createElement('span').addClass('entryObjectCoordinateSpanWorkspace');\n        xCoordi.textContent = 'X';\n        const xInput = Entry.createElement('input').addClass('entryObjectCoordinateInputWorkspace');\n        xInput.setAttribute('type', 'text');\n        xInput.onkeypress = this.editObjectValueWhenEnterPress;\n        xInput.onfocus = this._setFocused;\n        xInput.onblur = this._setBlurredTimer(() => {\n            const object = Entry.container.getObject(this.id);\n            if (!object) {\n                return;\n            }\n\n            const value = xInput.value;\n            Entry.do(\n                'objectUpdatePosX',\n                this.id,\n                Entry.Utils.isNumber(value) ? value : this.entity.getX()\n            );\n        });\n\n        const yCoordiWrapper = Entry.createElement('span').addClass(\n            'entryObjectCoordinateWorkspaceWrapper'\n        );\n        const yCoordi = Entry.createElement('span').addClass('entryObjectCoordinateSpanWorkspace');\n        yCoordi.textContent = 'Y';\n        const PerCoordi = Entry.createElement('span').addClass(\n            'entryObjectCoordinateSpanWorkspace'\n        );\n        PerCoordi.textContent = '%';\n        const yInput = Entry.createElement('input').addClass(\n            'entryObjectCoordinateInputWorkspace entryObjectCoordinateInputWorkspace_right'\n        );\n        yInput.setAttribute('type', 'text');\n        yInput.onkeypress = this.editObjectValueWhenEnterPress;\n        yInput.onfocus = this._setFocused;\n        yInput.onblur = this._setBlurredTimer(() => {\n            const object = Entry.container.getObject(this.id);\n            if (!object) {\n                return;\n            }\n            const value = yInput.value;\n            Entry.do(\n                'objectUpdatePosY',\n                this.id,\n                Entry.Utils.isNumber(value) ? value : this.entity.getY()\n            );\n        });\n\n        const sizeWrapper = Entry.createElement('span').addClass(\n            'entryObjectCoordinateSizeWrapper'\n        );\n        const sizeSpan = Entry.createElement('span').addClass('entryObjectCoordinateSizeWorkspace');\n        sizeSpan.textContent = `${Lang.Workspace.Size}`;\n        const sizeInput = Entry.createElement('input').addClass(\n            'entryObjectCoordinateInputWorkspace',\n            'entryObjectCoordinateInputWorkspace_size'\n        );\n        sizeInput.setAttribute('type', 'text');\n        sizeInput.onkeypress = this.editObjectValueWhenEnterPress;\n        sizeInput.onfocus = this._setFocused;\n        sizeInput.onblur = this._setBlurredTimer(() => {\n            const object = Entry.container.getObject(this.id);\n            if (!object) {\n                return;\n            }\n            const value = sizeInput.value;\n            Entry.do(\n                'objectUpdateSize',\n                this.id,\n                Entry.Utils.isNumber(value) ? value : this.entity.getSize()\n            );\n        });\n\n        xCoordiWrapper.appendChild(xCoordi);\n        xCoordiWrapper.appendChild(xInput);\n        yCoordiWrapper.appendChild(yCoordi);\n        yCoordiWrapper.appendChild(yInput);\n        sizeWrapper.appendChild(sizeSpan);\n        sizeWrapper.appendChild(sizeInput);\n        sizeWrapper.appendChild(PerCoordi);\n\n        coordinationView.appendChild(xCoordiWrapper);\n        coordinationView.appendChild(yCoordiWrapper);\n        coordinationView.appendChild(sizeWrapper);\n        coordinationView.xInput_ = xInput;\n        coordinationView.yInput_ = yInput;\n        coordinationView.sizeInput_ = sizeInput;\n\n        return coordinationView;\n    }\n\n    createRotationWrapperView() {\n        const rotationWrapperView = Entry.createElement('div').addClass(\n            'entryObjectRotationWrapperWorkspace'\n        );\n\n        const coordinationView = this.createCoordinationView();\n        this.coordinateView_ = coordinationView;\n        rotationWrapperView.appendChild(coordinationView);\n\n        const rotateLabelWrapperView = this.createRotateLabelWrapperView();\n        rotationWrapperView.appendChild(rotateLabelWrapperView);\n\n        const rotationMethodWrapperView = this.createRotationMethodWrapperView();\n        rotateLabelWrapperView.appendChild(rotationMethodWrapperView);\n        this.rotationMethodWrapper_ = rotationMethodWrapperView;\n\n        return rotationWrapperView;\n    }\n\n    setObjectFold(isFold, isPass) {\n        const $view = $(this.view_);\n        if (isFold) {\n            $view.addClass('fold');\n        } else {\n            $view.removeClass('fold');\n        }\n        if (!isPass) {\n            this.isFolded = isFold;\n        }\n    }\n\n    resetObjectFold() {\n        this.setObjectFold(this.isFolded);\n    }\n\n    createInformationView() {\n        const informationView = Entry.createElement('div').addClass(\n            'entryObjectInformationWorkspace'\n        );\n        informationView.bindOnClick(() => {\n            const $view = $(this.view_);\n            if ($view.hasClass('selectedObject')) {\n                this.setObjectFold(!this.isFolded);\n            }\n        });\n        return informationView;\n    }\n\n    createDeleteView(exceptionsForMouseDown) {\n        const deleteView = Entry.createElement('div').addClass('entryObjectDeleteWorkspace');\n        exceptionsForMouseDown.push(deleteView);\n        if (Entry.objectEditable && Entry.objectDeletable) {\n            deleteView.bindOnClick((e) => {\n                e.stopPropagation();\n                if (this.getLock() || Entry.engine.isState('run')) {\n                    return;\n                }\n                Entry.do('removeObject', this.id);\n                Entry.removeEventListener('run', this.setDisabled);\n                Entry.removeEventListener('dispatchEventDidToggleStop', this.setEnabled);\n            });\n        }\n        return deleteView;\n    }\n\n    createNameView() {\n        const nameView = Entry.createElement('input').addClass('entryObjectNameWorkspace');\n        nameView.addEventListener('click', (e) => {\n            if (!_.includes(this.view_.classList, 'selectedObject')) {\n                e.preventDefault();\n            }\n        });\n        nameView.addEventListener('contextmenu', (e) => {\n            e.preventDefault();\n            if (!_.includes(this.view_.classList, 'selectedObject')) {\n                this._rightClick(e);\n            }\n        });\n        nameView.addEventListener('focus', () => {\n            if (!_.includes(this.view_.classList, 'selectedObject')) {\n                nameView.blur();\n            }\n        });\n\n        const onKeyPressed = Entry.Utils.whenEnter(() => {\n            this.editObjectValues(false);\n        });\n\n        nameView.onkeypress = onKeyPressed;\n\n        nameView.onfocus = Entry.Utils.setFocused;\n\n        const nameViewBlur = this._setBlurredTimer(() => {\n            const object = Entry.container.getObject(this.id);\n            if (!object) {\n                return;\n            } else if (nameView.value.trim() === '') {\n                return Entry.modal.alert(Lang.Workspace.enter_the_name).then(() => {\n                    nameView.focus();\n                });\n            }\n            Entry.do('objectNameEdit', this.id, nameView.value);\n        });\n\n        Entry.attachEventListener(nameView, 'blur', nameViewBlur);\n        nameView.value = this.name;\n        return nameView;\n    }\n\n    setDisabled = () => {\n        if (this.nameView_) {\n            this.nameView_.disabled = true;\n        }\n        if (this.rotateInput_) {\n            this.rotateInput_.disabled = true;\n        }\n        if (this.directionInput_) {\n            this.directionInput_.disabled = true;\n        }\n        if (this.coordinateView_) {\n            this.coordinateView_.sizeInput_.disabled = true;\n            this.coordinateView_.xInput_.disabled = true;\n            this.coordinateView_.yInput_.disabled = true;\n        }\n    };\n\n    setEnabled = () => {\n        if (this.nameView_) {\n            this.nameView_.disabled = false;\n        }\n        if (this.rotateInput_) {\n            this.rotateInput_.disabled = false;\n        }\n        if (this.directionInput_) {\n            this.directionInput_.disabled = false;\n        }\n        if (this.coordinateView_) {\n            this.coordinateView_.sizeInput_.disabled = false;\n            this.coordinateView_.xInput_.disabled = false;\n            this.coordinateView_.yInput_.disabled = false;\n        }\n    };\n\n    createWrapperView() {\n        const wrapperView = Entry.createElement('div').addClass('entryObjectWrapperWorkspace');\n\n        const nameView = this.createNameView();\n        wrapperView.appendChild(nameView);\n        this.nameView_ = nameView;\n\n        return wrapperView;\n    }\n\n    createThumbnailView(objectId) {\n        const thumbnail = Entry.createElement('div').addClass('entryObjectThumbnailWorkspace');\n\n        DomUtils.addEventListenerMultiple(thumbnail, 'mousedown touchstart', (e) => {\n            Entry.do('containerSelectObject', objectId);\n        });\n\n        thumbnail.addEventListener('touchmove', (e) => {\n            e.preventDefault();\n        });\n\n        return thumbnail;\n    }\n\n    createObjectInfoView() {\n        const objectInfoView = Entry.createElement('ul').addClass('objectInfoView');\n        const objectInfoVisible = Entry.createElement('li').addClass('objectInfo_visible');\n        if (!this.entity.getVisible()) {\n            objectInfoVisible.addClass('objectInfo_unvisible');\n        }\n\n        const objectInfoLock = Entry.createElement('li').addClass('objectInfo_unlock');\n        if (this.getLock()) {\n            objectInfoLock.addClass('objectInfo_lock');\n        }\n\n        if (Entry.objectEditable) {\n            objectInfoVisible.bindOnClick(() => {\n                if (Entry.engine.isState('run')) {\n                    return;\n                }\n\n                const entity = this.entity;\n                const visible = entity.setVisible(!entity.getVisible());\n                if (visible) {\n                    objectInfoVisible.removeClass('objectInfo_unvisible');\n                } else {\n                    objectInfoVisible.addClass('objectInfo_unvisible');\n                }\n            });\n\n            objectInfoLock.bindOnClick(() => {\n                if (Entry.engine.isState('run')) {\n                    return;\n                }\n\n                if (this.setLock(!this.getLock())) {\n                    objectInfoLock.addClass('objectInfo_lock');\n                } else {\n                    objectInfoLock.removeClass('objectInfo_lock');\n                }\n\n                this.updateInputViews(this.getLock());\n            });\n        }\n\n        objectInfoView.appendChild(objectInfoVisible);\n        objectInfoView.appendChild(objectInfoLock);\n        return objectInfoView;\n    }\n\n    createObjectView(objectId, exceptionsForMouseDown) {\n        const objectView = Entry.createElement('li', objectId).addClass(\n            'entryContainerListElementWorkspace'\n        );\n\n        $(objectView).on('dragstart', (e) => {\n            e.originalEvent.dataTransfer.setData('text', objectId);\n        });\n        const fragment = document.createDocumentFragment();\n        fragment.appendChild(objectView);\n        // generate context menu\n        Entry.Utils.disableContextmenu(objectView);\n\n        objectView.addEventListener('click', (e) => {\n            const isFirstClick = !_.includes(this.view_.classList, 'selectedObject');\n            if (isFirstClick && Entry.isMobile()) {\n                e.preventDefault();\n                document.activeElement.blur();\n            }\n\n            if (\n                Entry.container.getObject(objectId) &&\n                !_.includes(exceptionsForMouseDown, e.target)\n            ) {\n                Entry.do('selectObject', objectId);\n            }\n        });\n\n        const longPressEvent = (e) => {\n            const doc = $(document);\n            const touchEvent = Entry.Utils.convertMouseEvent(e);\n            const mouseDownCoordinate = { x: touchEvent.clientX, y: touchEvent.clientY };\n            let longPressTimer = null;\n\n            longPressTimer = setTimeout(() => {\n                if (longPressTimer) {\n                    longPressTimer = null;\n                    this._rightClick(e);\n                }\n            }, 1000);\n\n            doc.bind('mousemove.object touchmove.object', (e) => {\n                const touchEvent = Entry.Utils.convertMouseEvent(e);\n\n                const diff = Math.sqrt(\n                    Math.pow(touchEvent.pageX - mouseDownCoordinate.x, 2) +\n                        Math.pow(touchEvent.pageY - mouseDownCoordinate.y, 2)\n                );\n\n                if (diff > 5 && longPressTimer) {\n                    clearTimeout(longPressTimer);\n                    longPressTimer = null;\n                }\n            });\n            doc.bind('mouseup.object touchend.object', (e) => {\n                e.stopPropagation();\n                doc.unbind('.object');\n                if (longPressTimer) {\n                    clearTimeout(longPressTimer);\n                    longPressTimer = null;\n                }\n            });\n        };\n\n        objectView.addEventListener('mousedown', (e) => {\n            if (Entry.Utils.isRightButton(e)) {\n                e.stopPropagation();\n                this._rightClick(e);\n            }\n\n            if (Entry.isMobile()) {\n                e.stopPropagation();\n                longPressEvent(e);\n            }\n        });\n\n        objectView.addEventListener('touchstart', (e) => {\n            e.eventFromEntryObject = true;\n            Entry.documentMousedown.notify(e);\n            longPressEvent(e);\n        });\n\n        return objectView;\n    }\n\n    _getRotateView(type = 'free') {\n        if (type === 'free') {\n            return this.rotateModeAView_;\n        } else if (type === 'none') {\n            return this.rotateModeCView_;\n        } else {\n            return this.rotateModeBView_;\n        }\n    }\n\n    getIndex() {\n        return Entry.container.getObjectIndex(this.id);\n    }\n\n    _whenRotateEditable(func, obj) {\n        return Entry.Utils.when(() => !(Entry.engine.isState('run') || obj.getLock()), func);\n    }\n};\n"
  },
  {
    "path": "src/class/painter.js",
    "content": "import Extension from '../extensions/extension';\n\n// 1px * 1px png iamge\nconst NULL_IMAGE =\n    // eslint-disable-next-line max-len\n    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAAtJREFUGFdjYAACAAAFAAGq1chRAAAAAElFTkSuQmCC';\nlet EntryPaint;\nEntry.Painter = class Painter {\n    constructor(view) {\n        this.view = view;\n        this.cache = [];\n\n        this.file = {\n            id: Entry.generateHash(),\n            name: '새그림',\n            modified: false,\n            mode: 'new', // new or edit\n        };\n\n        this.dropper = Extension.getExtension('Dropper');\n        this.isShow = false;\n        this.clipboard = null;\n        this._keyboardEvents = [];\n        Entry.addEventListener('pictureImport', this.addPicture.bind(this));\n        Entry.addEventListener('run', this.detachKeyboardEvents.bind(this));\n        Entry.addEventListener('stop', this.attachKeyboardEvents.bind(this));\n        this.importEntryPaint();\n    }\n\n    async importEntryPaint() {\n        EntryPaint = window.EntryPaint.default;\n        if (this.requestShow) {\n            this.initialize();\n        }\n    }\n\n    get graphicsMode() {\n        return this.entryPaint.graphicsMode;\n    }\n\n    initialize() {\n        if (this.entryPaint || !EntryPaint) {\n            this.requestShow = true;\n            return;\n        }\n\n        this.isShow = true;\n\n        this.entryPaint = EntryPaint.create({ parent: this.view, mode: 'entry' });\n        this.entryPaint.setDropper && this.entryPaint.setDropper(this.dropper);\n\n        this.isImport = true;\n        this.entryPaint.on('SNAPSHOT_SAVED', (e) => {\n            if (!this.isImport && Entry.stage.selectedObject) {\n                Entry.do('editPicture', e, this.entryPaint);\n                this.file.modified = true;\n            }\n            this.isImport = false;\n        });\n        this.entryPaint.on('NEW_PICTURE', this.newPicture.bind(this));\n        this.entryPaint.on('IMPORT_IMAGE', () => {\n            Entry.dispatchEvent('openPictureImport');\n        });\n        this.entryPaint.on('SAVE_PICTURE', () => {\n            this.fileSave(false);\n        });\n        this.entryPaint.on('SAVE_NEW_PICTURE', () => {\n            this.file.mode = 'new';\n            this.fileSave(false);\n        });\n        this.entryPaint.on('FULL_SCREEN_ON', () => {\n            this.toggleFullscreen(true);\n        });\n        this.entryPaint.on('FULL_SCREEN_OFF', () => {\n            this.toggleFullscreen(false);\n        });\n\n        Entry.addEventListener('pictureSelected', this.changePicture.bind(this));\n    }\n\n    show() {\n        if (!this.isShow) {\n            this.initialize();\n        }\n        this.realign && Entry.windowResized.detach(this.realign);\n        this.realign = Entry.windowResized.attach(this.view, this.entryPaint.realign);\n    }\n\n    hide() {\n        this.alertSaveModifiedPicture();\n        this.entryPaint && Entry.windowResized.detach(this.realign);\n    }\n\n    newPicture() {\n        const newPicture = {\n            dimension: {\n                height: 1,\n                width: 1,\n            },\n            fileurl: `${Entry.mediaFilePath}_1x1.png`,\n            thumbUrl: `${Entry.mediaFilePath}_1x1.png`,\n            name: Lang.Painter.new_picture,\n            imageType: 'png',\n        };\n\n        newPicture.id = Entry.generateHash();\n        if (this.file && this.file.objectId) {\n            newPicture.objectId = this.file.objectId;\n        }\n        Entry.playground.addPicture(newPicture, true);\n    }\n\n    changePicture(picture = {}, removed) {\n        if (this.file && this.file.id === picture.id) {\n            if (!this.file.isUpdate) {\n                Entry.stage.updateObject();\n                this.file.isUpdate = true;\n            }\n            return;\n        } else if (!this.file.modified) {\n            this.afterModified(picture);\n        } else {\n            if (this.isConfirm) {\n                return;\n            }\n\n            this.isConfirm = true;\n            let wasRun = false;\n            if (Entry.engine.state === 'run') {\n                Entry.engine.toggleStop();\n                wasRun = true;\n            }\n\n            if (removed) {\n                this.updatePicture(picture);\n            } else {\n                this.alertSaveModifiedPicture(picture, wasRun);\n            }\n        }\n        Entry.stage.updateObject();\n        this.file.isUpdate = true;\n    }\n\n    updatePicture(picture = {}, wasRun = true, result = true) {\n        this.isConfirm = false;\n        result ? this.fileSave(true) : (this.file.modified = false);\n        wasRun ? Entry.playground.injectPicture() : this.afterModified(picture);\n        Entry.stage.updateObject();\n    }\n\n    alertSaveModifiedPicture(picture, wasRun) {\n        if (!this.file.modified) {\n            return;\n        }\n\n        Entry.modal.confirm(Lang.Menus.save_modified_shape).then((result) => {\n            this.updatePicture(picture, wasRun, result);\n        });\n    }\n\n    afterModified(picture) {\n        const file = this.file;\n        file.modified = false;\n        this.isImport = true;\n\n        if (picture.id) {\n            file.id = picture.id || Entry.generateHash();\n            file.name = picture.name;\n            file.mode = 'edit';\n            file.objectId = picture.objectId;\n\n            this.addPicture(picture, true);\n        } else {\n            file.id = Entry.generateHash();\n            this.entryPaint.reset();\n        }\n\n        Entry.stateManager.removeAllPictureCommand();\n    }\n\n    getImageSrc(picture) {\n        const { fileurl } = picture || {};\n        if (fileurl) {\n            return fileurl;\n        }\n\n        const { imageType = 'png', filename } = picture || {};\n        return `${Entry.defaultPath}/uploads/${filename.substring(0, 2)}/${filename.substring(\n            2,\n            4\n        )}/image/${filename}.${imageType === 'svg' ? 'svg' : 'png'}`;\n    }\n\n    addPicture(picture = {}, isChangeShape) {\n        picture.imageType = picture.imageType || 'png';\n        const { imageType } = picture;\n        const imageSrc = this.getImageSrc(picture);\n\n        isChangeShape && (this.isImport = true);\n\n        switch (imageType) {\n            case 'png':\n                this.entryPaint.addBitmap(imageSrc, {\n                    graphicsMode: this.isImport ? this.graphicsMode.BITMAP : '',\n                });\n                break;\n            case 'svg':\n                this.entryPaint.addSVG(imageSrc, {\n                    graphicsMode: this.isImport ? this.graphicsMode.VECTOR : '',\n                });\n                break;\n            default:\n                this.entryPaint.addBitmap(imageSrc, {\n                    graphicsMode: this.isImport ? this.graphicsMode.BITMAP : '',\n                });\n        }\n    }\n\n    _getImageType() {\n        if (this.entryPaint.mode === this.graphicsMode.VECTOR) {\n            return 'svg';\n        } else {\n            return 'png';\n        }\n    }\n\n    fileSave(taskParam) {\n        if (!Entry.stage.selectedObject) {\n            return;\n        }\n        const dataURL = this.entryPaint.getDataURL() || NULL_IMAGE;\n        if (this.entryPaint.mode === this.graphicsMode.VECTOR) {\n            this.file.svg = this.entryPaint.exportSVG();\n        } else {\n            delete this.file.svg;\n        }\n        this.file.ext = this._getImageType();\n        const file = JSON.parse(JSON.stringify(this.file));\n        Entry.dispatchEvent('saveCanvasImage', {\n            file,\n            image: dataURL,\n            task: taskParam,\n        });\n        this.file.isUpdate = false;\n        this.file.modified = false;\n    }\n\n    attachKeyboardEvents() {\n        this.detachKeyboardEvents();\n\n        const events = this._keyboardEvents;\n\n        let evt = Entry.keyPressed;\n        evt && events.push(evt.attach(this, this._keyboardPressControl));\n\n        evt = Entry.keyUpped;\n        evt && events.push(evt.attach(this, this._keyboardUpControl));\n    }\n\n    detachKeyboardEvents() {\n        const events = this._keyboardEvents;\n        if (!events || !events.length) {\n            return;\n        }\n\n        while (events.length) {\n            const evt = events.pop();\n            evt.destroy && evt.destroy();\n        }\n    }\n\n    _keyboardUpControl(e) {}\n    _keyboardPressControl(e) {}\n\n    toggleFullscreen(isFullscreen) {\n        const { pictureView_ } = Entry.playground;\n        const $view = $(this.view);\n        if ((isFullscreen !== true && $view.hasClass('fullscreen')) || isFullscreen === false) {\n            pictureView_.appendChild(this.view);\n            $view.removeClass('fullscreen');\n            if (this.fullscreenButton) {\n                this.fullscreenButton.setAttribute('title', Lang.Painter.fullscreen);\n                this.fullscreenButton.setAttribute('alt', Lang.Painter.fullscreen);\n            }\n        } else {\n            document.body.appendChild(this.view);\n            $view.addClass('fullscreen');\n            if (this.fullscreenButton) {\n                this.fullscreenButton.setAttribute('title', Lang.Painter.exit_fullscreen);\n                this.fullscreenButton.setAttribute('alt', Lang.Painter.exit_fullscreen);\n            }\n        }\n        this.entryPaint && this.entryPaint.realign();\n    }\n\n    clear() {\n        this.toggleFullscreen(false);\n    }\n\n    undo() {\n        this.entryPaint.undo();\n    }\n\n    redo() {\n        this.entryPaint.redo();\n    }\n};\n"
  },
  {
    "path": "src/class/pdf.ts",
    "content": "/**\n * 사용처: Entry#lecture 관련 로직 한군데\n */\n\nclass EntryPDF {\n    private _view: HTMLDivElement;\n\n    constructor(filename: string) {\n        this.generateView(filename);\n    }\n\n    private generateView(file: string) {\n        const pdfView = Entry.createElement('div', 'entryPdfWorkspace');\n\n        // @ts-ignore 아무리봐도 순수 HTMLDivElement 에는 이 함수가 없음. 그러나 모르는 무언가가 있을 수 있으므로 그냥 둠\n        pdfView.addClass('entryRemove');\n        let url = '/pdfjs/web/viewer.html';\n        if (file && file !== '') {\n            url += `?file=${file}`;\n        }\n\n        const pdfViewIframe = Entry.createElement('iframe', 'entryPdfIframeWorkspace');\n        pdfViewIframe.setAttribute('id', 'pdfViewIframe');\n        pdfViewIframe.setAttribute('frameborder', '0');\n        pdfViewIframe.setAttribute('src', url);\n        pdfView.appendChild(pdfViewIframe);\n        this._view = pdfView;\n    }\n\n    getView() {\n        return this._view;\n    }\n\n    resize() {\n        const container = document.getElementById('entryContainerWorkspaceId');\n        const viewFrame = document.getElementById('pdfViewIframe') as HTMLIFrameElement;\n        const width = container.offsetWidth;\n        viewFrame.width = `${width}px`;\n        viewFrame.height = `${(width * 9) / 16}px`;\n    }\n}\n\nexport default EntryPDF;\nEntry.Pdf = EntryPDF;\n"
  },
  {
    "path": "src/class/pixi/atlas/AtlasCanvasViewer.ts",
    "content": "/**\n * BaseTexture 의 canvas 에 drawing이 잘 되는지 확인하기 위한 debug 클라스.\n */\n\nconst style = (viewerHeight: number) => `<style>\n    .atlas-canvas-container {\n        position: absolute;\n        width: 100%;\n        pointer-events: none;\n        display: none;\n    }\n    .atlas-canvas {\n        width: auto; height: ${viewerHeight}px; float: right; border: 1px solid red;\n    }\n</style>`;\n\nconst dom = `<div class='atlas-canvas-container'></div>`;\n\nexport class AtlasCanvasViewer {\n    private $style: any;\n    private $container: any;\n    private attached: boolean;\n\n    constructor(viewerHeight: number = 200) {\n        this.$style = $(style(viewerHeight));\n        this.$container = $(dom);\n    }\n\n    private attachToBody() {\n        if (this.attached) {\n            return;\n        }\n        this.attached = true;\n        setTimeout(() => {\n            this.$container.click(() => false);\n            $('head').append(this.$style);\n            $('body').append(this.$container);\n        }, 500);\n    }\n\n    add(c: HTMLCanvasElement) {\n        const isCanvas = c instanceof HTMLCanvasElement;\n        if (!isCanvas) {\n            return;\n        }\n        this.attachToBody();\n        const cc = $(c);\n        this.$container.append(cc);\n        cc.addClass('atlas-canvas');\n    }\n\n    removeCanvas(c: HTMLCanvasElement) {\n        if (!c) {\n            return;\n        }\n        $(c).remove();\n    }\n\n    empty() {\n        this.$container.empty();\n    }\n\n    toggleVisible() {\n        this.$container.toggle();\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/EntryTextureOption.ts",
    "content": "import PIXIHelper from '../helper/PIXIHelper';\nimport { Rectangle, SCALE_MODES, MIPMAP_MODES } from 'pixi.js';\nimport { MaxRectsPacker } from '../../maxrect-packer/maxrects_packer';\nimport { clog } from '../utils/logs';\n\ninterface ITexOption {}\n\ninterface IAtlasOption extends ITexOption {\n    extrudeSize: number;\n    atlasSize: number;\n    newPacker: () => MaxRectsPacker;\n}\n\nexport class EntryTextureOption {\n    private _USE_ATLAS: boolean = false;\n    get USE_ATLAS(): boolean {\n        return this._USE_ATLAS;\n    }\n\n    private readonly GPU_TEX_MAX_SIZE: number;\n\n    /** 텍스쳐를 최대 몇으로 할지의 값을 Canvas.width , height 기준으로 몇배로 할 지에 대한 값. */\n    private readonly _texStageRatio: number;\n\n    readonly scaleMode = SCALE_MODES.LINEAR;\n    readonly mipmap: MIPMAP_MODES = MIPMAP_MODES.OFF;\n    readonly atlasOption: IAtlasOption;\n\n    /** 텍스쳐 1개의 최대 크기. 이 크기보다 크면 리사이즈 함. */\n    readonly texMaxRect: Rectangle;\n\n    constructor(stageWidth: number, stageHeight: number) {\n        this._USE_ATLAS = this._isSpriteSheetEnabled();\n        this.GPU_TEX_MAX_SIZE = this.computeMaxTextureSize(4096);\n        this._texStageRatio = 1;\n        this.texMaxRect = this.getTexRect(\n            stageWidth,\n            stageHeight,\n            this._texStageRatio,\n            this.GPU_TEX_MAX_SIZE\n        );\n        this.atlasOption = {\n            extrudeSize: 2,\n            atlasSize: this.GPU_TEX_MAX_SIZE,\n            newPacker: this.newPacker.bind(this),\n        };\n    }\n\n    private newPacker(): MaxRectsPacker {\n        //https://www.npmjs.com/package/maxrects-packer\n        const PADDING = 6; //텍스쳐 사이의 간격.\n        const BORDER = 2; //베이스 텍스쳐 테두리 간격\n        const MAX = this.atlasOption.atlasSize;\n        const OPTION = {\n            smart: false,\n            pot: true,\n            square: false,\n        };\n        return new MaxRectsPacker(MAX, MAX, BORDER, PADDING, OPTION);\n    }\n\n    private getTexRect(w: number, h: number, ratio: number, max: number): Rectangle {\n        return new Rectangle(0, 0,\n            Math.min(Math.round(w * ratio), max),\n            Math.min(Math.round(h * ratio), max),\n        );\n    }\n\n    private computeMaxTextureSize(LIMIT: number): number {\n        const canvas: HTMLCanvasElement = PIXIHelper.getOffScreenCanvas(true);\n        // @ts-ignore\n        const ctx: WebGLRenderingContext =\n            canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n        let size = ctx ? ctx.getParameter(ctx.MAX_TEXTURE_SIZE) : 2048;\n        size = Math.min(size, LIMIT);\n        clog(`Max texture size : ${size}`);\n        return size;\n    }\n\n    private _isSpriteSheetEnabled(): boolean {\n        const spriteSheetString = 'ss=1';\n        const url = window.location.href;\n        const query = url.split('?')[1];\n        if (!query) return false;\n        const arr = query.split('&');\n        for (let i = 0; i < arr.length; i++) {\n            if (arr[i] == spriteSheetString) return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/ISceneTextures.ts",
    "content": "import { Texture } from 'pixi.js';\nimport { AtlasImageLoadingInfo } from './loader/AtlasImageLoadingInfo';\nimport { IRawPicture } from './model/IRawPicture';\n\nexport interface ISceneTextures {\n    addPicInfo(info: IRawPicture): void;\n\n    activate(): void;\n\n    deactivate(): void;\n\n    getTexture(path: string): Texture;\n\n    putImage(info: AtlasImageLoadingInfo, forceUpdateBaseTexture?: boolean): void;\n\n    _internal_imageRemoved(): void;\n\n    destroy(): void;\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/PIXIAtlasHelper.ts",
    "content": "import { IRawPicture } from './model/IRawPicture';\nimport { PrimitiveSet } from './structure/PrimitiveSet';\nimport { ImageRect } from '../../maxrect-packer/geom/ImageRect';\nimport { autoFit } from '../utils/AutoFit';\n\ninterface ISimpleRect {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n}\n\nclass _PIXIAtlasHelper {\n    /**\n     * rawData.fileurl || rawData.filename\n     * @param rawData\n     */\n    getRawPath(rawData: IRawPicture): string {\n        return rawData.fileurl || rawData.filename;\n    }\n\n    /**\n     * EntryObject를 전부 조회하여 지정된 장면에서 사용하는 picture의 경로 set 객체를 리턴.\n     * @param sceneID\n     */\n    getScenePathSet(sceneID: string): PrimitiveSet {\n        const arrObj: any[] = Entry.container.getAllObjects();\n        const pathSet = new PrimitiveSet();\n\n        const LEN = arrObj.length;\n        let LEN2;\n        let pics: IRawPicture[];\n        let obj: any;\n        for (let i = 0; i < LEN; i++) {\n            obj = arrObj[i];\n            if (sceneID != obj.scene.id) {\n                continue;\n            }\n            pics = obj.pictures;\n            if (!pics || !(LEN2 = pics.length)) {\n                continue;\n            }\n            for (let j = 0; j < LEN2; j++) {\n                pathSet.put(this.getRawPath(pics[j]));\n            }\n        }\n        return pathSet;\n    }\n\n    /**\n     * 이미지별 텍스쳐 사이즈 리턴 (정수)\n     * @param pic, texMaxRect\n     */\n    getNewImageRect(pic: IRawPicture, texMaxRect: ISimpleRect): ImageRect {\n        const w = pic.dimension.width | 0;\n        const h = pic.dimension.height | 0;\n\n        const r = new ImageRect(0, 0, w, h);\n        if (w > texMaxRect.width || h > texMaxRect.height) {\n            autoFit.fit(texMaxRect, r, autoFit.ScaleMode.INSIDE, autoFit.AlignMode.TL);\n            r.width = Math.ceil(r.width);\n            r.height = Math.ceil(r.height);\n            r.scaleFactor = w / r.width;\n            r.scaleFactorX = w / r.width;\n            r.scaleFactorY = h / r.height;\n        }\n        return r;\n    }\n}\n\nexport const PIXIAtlasHelper: _PIXIAtlasHelper = new _PIXIAtlasHelper();\n"
  },
  {
    "path": "src/class/pixi/atlas/PIXIAtlasManager.ts",
    "content": "import { Sprite } from 'pixi.js';\nimport { SceneBins } from './SceneBins';\nimport { AtlasCanvasViewer } from './AtlasCanvasViewer';\nimport { AtlasImageLoader, ImageLoaderHandler } from './loader/AtlasImageLoader';\nimport { AtlasImageLoadingInfo } from './loader/AtlasImageLoadingInfo';\nimport { IRawPicture } from './model/IRawPicture';\nimport { PIXIAtlasHelper } from './PIXIAtlasHelper';\nimport { EntryTextureOption } from './EntryTextureOption';\nimport { ISceneTextures } from './ISceneTextures';\nimport { SceneTextures } from './SceneTextures';\nimport { clog } from '../utils/logs';\nimport { IGEResManager } from '../../../graphicEngine/IGEResManager';\nimport each from 'lodash/each';\n\ntype SceneBinsMap = { [key: string]: ISceneTextures };\n\nexport class PIXIAtlasManager implements IGEResManager {\n    private _sceneID_sceneBin_map: SceneBinsMap = {};\n    private _activatedScene: ISceneTextures;\n    private _imageLoader: AtlasImageLoader;\n    private _viewer: AtlasCanvasViewer;\n    private _option: EntryTextureOption;\n\n    /**\n     * @private\n     * @constructor\n     */\n    public INIT() {\n        if (this._imageLoader) {\n            throw new Error('do not call twice');\n        }\n        this._option = new EntryTextureOption(640, 360);\n        this._viewer = new AtlasCanvasViewer();\n        this._imageLoader = new AtlasImageLoader(this._onImageLoaded.bind(this));\n\n        Entry.addEventListener('saveCanvasImage', () => {\n            this.imageRemoved('canvas image saved');\n        });\n    }\n\n    private _onImageLoaded(info: AtlasImageLoadingInfo) {\n        this._activatedScene && this._activatedScene.putImage(info);\n    }\n\n    activateScene(sceneID: string) {\n        if (this._activatedScene) {\n            this._activatedScene.deactivate();\n        }\n        this._activatedScene = this._getSceneBin(sceneID);\n        this._activatedScene.activate();\n    }\n\n    reqResource(\n        spriteNullable: Sprite,\n        sceneID: string,\n        pic: IRawPicture,\n        callback: ImageLoaderHandler\n    ): void {\n        const bin: ISceneTextures = this._getSceneBin(sceneID);\n        bin.addPicInfo(pic);\n        const tex = bin.getTexture(PIXIAtlasHelper.getRawPath(pic));\n        if (spriteNullable) {\n            spriteNullable.texture = tex;\n        }\n    }\n\n    private _getSceneBin(sceneID: string, createIfNotExist: boolean = true): ISceneTextures {\n        let s: ISceneTextures = this._sceneID_sceneBin_map[sceneID];\n        if (!s && createIfNotExist) {\n            if (this._option.USE_ATLAS) {\n                s = new SceneBins(sceneID, this._option, this._imageLoader, this._viewer);\n            } else {\n                s = new SceneTextures(sceneID, this._option, this._imageLoader);\n            }\n            this._sceneID_sceneBin_map[sceneID] = s;\n        }\n        return s;\n    }\n\n    removeScene(sceneID: string): void {\n        const s: ISceneTextures = this._getSceneBin(sceneID, false);\n        if (!s) {\n            return;\n        }\n        if (this._activatedScene == s) {\n            this._activatedScene = null;\n        }\n        s.destroy();\n        delete this._sceneID_sceneBin_map[sceneID];\n        this.imageRemoved(`scend(${sceneID}) removed.`);\n    }\n\n    imageRemoved(reason: string): void {\n        clog(`AtlasManager::imageRemoved - ${reason}`);\n        this._activatedScene && this._activatedScene._internal_imageRemoved();\n        this._imageLoader.requestSync();\n    }\n\n    clearProject(): void {\n        clog('clearProject');\n        this._imageLoader.empty();\n        each(this._sceneID_sceneBin_map, (bin: ISceneTextures) => {\n            bin.destroy();\n        });\n        this._sceneID_sceneBin_map = {};\n        this._activatedScene = null;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/PIXIScaleAdaptor.ts",
    "content": "/**\n * 텍스쳐가 너무 커서 리사이즈 된 경우에 그만큼 보정하기 위한 클래스.\n * 예를 들어 원본크기가 2048, 리사이즈를 1024로 했으면 scaleFactor = 2;\n * entity에서 scale = 5 로 설정하면\n * Sprite.scale = entiry.scale(5) * scaleFactor(2) = 10 이 된다.\n */\nimport { DisplayObject, Sprite, Point, ObservablePoint } from 'pixi.js';\nimport { IDestroyer } from '../../../util/destroyer/Destroyer';\nimport { AtlasTexture } from '../atlas/texture/AtlasTexture';\n\ntype AdaptorConstructor = new () => ScaleFactorNormalAdaptor;\n\nexport namespace PIXIScaleAdaptor {\n    export function factory(target: DisplayObject): ScaleFactorNormalAdaptor {\n        const clazz: AdaptorConstructor =\n            target instanceof Sprite ? ScaleFactorSpriteAdaptor : ScaleFactorNormalAdaptor;\n        const adaptor: ScaleFactorNormalAdaptor = new clazz();\n        adaptor._internal_init(target);\n        return adaptor;\n    }\n}\n\nclass ScaleFactorNormalAdaptor implements IDestroyer {\n    public scale: ScaleFactorPoint;\n    public pivot: ScaleFactorPoint;\n    protected _target: DisplayObject;\n\n    _internal_init(target: DisplayObject) {\n        this._target = target;\n        this.scale = new ScaleFactorPoint(target.scale, 'scale');\n        this.pivot = new ScaleFactorPoint(target.pivot, 'pivot');\n    }\n\n    updateScaleFactor() {\n        //do nothing\n    }\n\n    destroy() {\n        this.pivot.destroy();\n        this.scale.destroy();\n        this._target = null;\n        this.pivot = null;\n        this.scale = null;\n    }\n}\n\nclass ScaleFactorSpriteAdaptor extends ScaleFactorNormalAdaptor {\n    updateScaleFactor() {\n        const sp = this._target as Sprite;\n        const tex = sp.texture as AtlasTexture;\n        const sfx = tex.textureScaleFactorX;\n        const sfy = tex.textureScaleFactorY;\n        if (!sfx || !sfy) {\n            return;\n        }\n        this.scale.internal_setScaleFactor(sfx, sfy);\n        this.pivot.internal_setScaleFactor(1 / sfx, 1 / sfy);\n    }\n}\n\nclass ScaleFactorPoint {\n    private _scaleX: number = 1;\n    private _scaleY: number = 1;\n    private _x: number = 0;\n    private _y: number = 0;\n\n    // eslint-disable-next-line no-useless-constructor\n    constructor(protected _point: Point | ObservablePoint, protected name: string) {}\n\n    internal_setScaleFactor(x: number, y: number) {\n        this._scaleX = x;\n        this._scaleY = y;\n        this.set(this._x, this._y);\n    }\n\n    setX(value: number): void {\n        this._x = value;\n        this._point.x = value * this._scaleX;\n    }\n\n    setY(value: number): void {\n        this._y = value;\n        this._point.y = value * this._scaleY;\n    }\n\n    set(x: number, y: number): void {\n        this._x = x;\n        this._y = y || (y != 0 ? x : 0);\n        this._point.set(this._x * this._scaleX, this._y * this._scaleY);\n    }\n\n    destroy(): void {\n        this._point = null;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/SceneBins.ts",
    "content": "/**\n * 하나의 Scene에서 사용하는 이미지들을 TextureAtlas 로 만들어줌.\n */\n\nimport { IRawPicture } from './model/IRawPicture';\nimport PIXIHelper from '../helper/PIXIHelper';\nimport { AtlasCanvasViewer } from './AtlasCanvasViewer';\nimport { AtlasImageLoadingInfo } from './loader/AtlasImageLoadingInfo';\nimport { PrimitiveSet } from './structure/PrimitiveSet';\nimport { MaxRectsPacker } from '../../maxrect-packer/maxrects_packer';\nimport { MaxRectsBin } from '../../maxrect-packer/maxrects_bin';\nimport { AtlasTexture } from './texture/AtlasTexture';\nimport { AtlasBaseTexture } from './texture/AtlasBaseTexture';\nimport { PrimitiveMap } from './structure/PrimitiveMap';\nimport { AtlasImageLoader } from './loader/AtlasImageLoader';\nimport { PIXIAtlasHelper } from './PIXIAtlasHelper';\nimport { TimeoutTimer } from '../utils/TimeoutTimer';\nimport { ImageRect } from '../../maxrect-packer/geom/ImageRect';\nimport { EntryTextureOption } from './EntryTextureOption';\nimport { ISceneTextures } from './ISceneTextures';\nimport each from 'lodash/each';\n\nconst TIMEOUT_INTERVAL = 250;\n\n/**\n * packing 이 되기전에 texture 객체를 생성하기 위한 BaseTexture\n */\nlet EMPTY_BASE_TEX: AtlasBaseTexture;\n\nexport class SceneBins implements ISceneTextures {\n    private static initEmptyTex(maxSize: number) {\n        if (EMPTY_BASE_TEX) {\n            return;\n        }\n        const TEX = new AtlasBaseTexture();\n        EMPTY_BASE_TEX = TEX;\n        TEX.setRealSize(maxSize, maxSize);\n        TEX.setSize(maxSize, maxSize);\n\n        const tex: any = TEX;\n        const emptyEmit = function() {};\n        tex.destroy = emptyEmit;\n        tex.on = emptyEmit;\n        tex.once = emptyEmit;\n        tex.emit = emptyEmit;\n    }\n\n    //private _pathSet:PrimitiveSet = new PrimitiveSet();//패킹 전/후 pathf르 모두 저장.\n    private _packedRects: ImageRect[] = [];\n    private _notPackedRects: ImageRect[] = [];\n    private _arrBaseTexture: AtlasBaseTexture[] = [];\n    private _packer: MaxRectsPacker;\n    private _path_tex_map: PrimitiveMap<AtlasTexture> = new PrimitiveMap();\n    private _activated: boolean;\n    private _imageRemoved: boolean;\n    private _timer: TimeoutTimer = new TimeoutTimer();\n\n    constructor(\n        public sceneID: string,\n        private _option: EntryTextureOption,\n        private _loader: AtlasImageLoader,\n        private _viewer: AtlasCanvasViewer\n    ) {\n        SceneBins.initEmptyTex(_option.atlasOption.atlasSize);\n        this._packer = _option.atlasOption.newPacker();\n    }\n\n    addPicInfo(pic: IRawPicture): void {\n        const path = PIXIAtlasHelper.getRawPath(pic);\n        if (this._path_tex_map.hasValue(path)) {\n            return;\n        }\n\n        const rect: ImageRect = PIXIAtlasHelper.getNewImageRect(pic, this._option.texMaxRect);\n        this._loader.load(pic, rect);\n        const tex: AtlasTexture = this._newTexture(path, rect);\n        rect.data = { path, tex };\n        this._notPackedRects.push(rect);\n\n        if (!this._activated) {\n            return;\n        }\n\n        if (this._timer.isRunning) {\n            return;\n        }\n\n        console.log('pack scheduled');\n        this._timer.timeout(TIMEOUT_INTERVAL, () => {\n            if (this._imageRemoved) {\n                console.log('삭제된 이미지가 있어서 invalidate');\n                this._invalidate();\n            } else {\n                console.log('just packing');\n                this._pack();\n            }\n        });\n    }\n\n    private _newTexture(path: string, rect: ImageRect): AtlasTexture {\n        const tex = new AtlasTexture(EMPTY_BASE_TEX, rect);\n        this._path_tex_map.add(path, tex);\n        return tex;\n    }\n\n    /** 패킹 하지 않은 Rect를 packing 한다. */\n    private _pack() {\n        if (!this._notPackedRects.length) {\n            return;\n        }\n\n        const len = this._notPackedRects.length;\n        let time = new Date().getTime();\n        this._packer.addArray(this._notPackedRects);\n        const willUpdateBaseTextures: AtlasBaseTexture[] = [];\n\n        this._notPackedRects.forEach((r: ImageRect) => {\n            const base: AtlasBaseTexture = this._getBaseTexture(r.binIndex);\n            r.data.tex.updateBaseAndUVs(base);\n\n            const imgInfo = this._loader.getImageInfo(r.data.path);\n            if (!imgInfo.isReady) {\n                return;\n            }\n\n            this.putImage(imgInfo, false);\n            if (willUpdateBaseTextures.indexOf(base) == -1) {\n                willUpdateBaseTextures.push(base);\n            }\n        });\n\n        willUpdateBaseTextures.forEach((base: AtlasBaseTexture) => {\n            base.update();\n        });\n\n        this._destroyBaseTextureAfter(this._packer.bins.length);\n        this._packedRects = this._packedRects.concat(this._notPackedRects);\n        this._notPackedRects = [];\n        time = new Date().getTime() - time;\n        console.log(`pack ${len} items. time:${time}`);\n    }\n\n    activate(): void {\n        this._activated = true;\n        this._invalidate();\n        const BASE_TEX_MAX_SIZE = this._option.atlasOption.atlasSize;\n        each(this._packer.bins, (bin: MaxRectsBin, index: number) => {\n            const base: AtlasBaseTexture = this._arrBaseTexture[index];\n            base.activate(BASE_TEX_MAX_SIZE);\n            base.update();\n        });\n\n        const EXTRUDE_SIZE = this._option.atlasOption.extrudeSize;\n        this._path_tex_map.each((t: AtlasTexture, path: string) => {\n            const info = this._loader.getImageInfo(path);\n            if (!info || !info.isReady) {\n                return;\n            }\n            t.drawImageAtBaseTexture(info, EXTRUDE_SIZE);\n        });\n    }\n\n    private _getBaseTexture(index: number): AtlasBaseTexture {\n        let base: AtlasBaseTexture = this._arrBaseTexture[index];\n        if (base) {\n            return base;\n        }\n        const OP = this._option;\n        base = new AtlasBaseTexture(this._viewer, OP.scaleMode);\n        base.setCanvas(PIXIHelper.getOffScreenCanvas());\n        // base.imageType = 'png'; deprecated v5\n        base.setRealSize(OP.atlasOption.atlasSize, OP.atlasOption.atlasSize);\n        base.setSize(OP.atlasOption.atlasSize, OP.atlasOption.atlasSize);\n        base.mipmap = OP.mipmap;\n        this._arrBaseTexture[index] = base;\n        return base;\n    }\n\n    deactivate() {\n        this._timer.reset();\n        this._activated = false;\n        each(this._arrBaseTexture, (b: AtlasBaseTexture) => {\n            b.deactivate();\n        });\n    }\n\n    getTexture(path: string): AtlasTexture {\n        return this._path_tex_map.getValue(path);\n    }\n\n    /**\n     * Scene이 활성화 되어 있을때 이미지가 로드 되면 이 함수를 통해 로드된 이미지 정보가 주입됨.\n     * @param info\n     * @param forceUpdateBaseTexture\n     */\n    putImage(info: AtlasImageLoadingInfo, forceUpdateBaseTexture: boolean = true) {\n        if (!info) {\n            return;\n        }\n        const t: AtlasTexture = this.getTexture(info.path);\n\n        if (!t) {\n            return;\n        } //이 Scene에서 사용안함\n        if (t.isEmptyTexture) {\n            return;\n        }\n\n        // console.log(\"put imgageData\");\n        const atlasOption = this._option.atlasOption;\n\n        const base: AtlasBaseTexture = t.getBaseTexture();\n        if (!base.activated) {\n            base.activate(atlasOption.atlasSize);\n        }\n        t.drawImageAtBaseTexture(info, atlasOption.extrudeSize);\n        if (forceUpdateBaseTexture) {\n            base.update();\n        }\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * 모든 텍스쳐 패킹을 다시 한다.\n     * @private\n     */\n    private _invalidate(): void {\n        if (!this._activated) {\n            return;\n        }\n        this._imageRemoved = false;\n        const usedPathSet: PrimitiveSet = PIXIAtlasHelper.getScenePathSet(this.sceneID);\n        this._notPackedRects.length = 0;\n        this._packedRects.length = 0;\n\n        const unusedPath: string[] = [];\n\n        //사용안하는 path를 검색, 패킹을 다시 할 것이기 때문에 사용하는 텍스쳐의 rect 정보를 저장.\n        this._path_tex_map.each((tex: AtlasTexture, path: string) => {\n            if (usedPathSet && usedPathSet.hasValue(path)) {\n                this._notPackedRects.push(this._path_tex_map.getValue(path).imageRectForPacking);\n            } else {\n                unusedPath.push(path);\n            }\n        });\n\n        console.log('unusedPath', unusedPath);\n\n        //사용안하는 texture를 제거\n        unusedPath.forEach((path: string) => {\n            this._path_tex_map.remove(path).destroy(false);\n        });\n\n        this._packer.empty();\n        this._cleanCanvas();\n\n        this._pack();\n    }\n\n    private _cleanCanvas() {\n        const LEN = this._arrBaseTexture.length;\n        for (let i = 0; i < LEN; i++) {\n            this._arrBaseTexture[i].cleanCanvas();\n        }\n    }\n\n    _internal_imageRemoved(): void {\n        this._imageRemoved = true;\n    }\n\n    private _destroyBaseTextureAfter(startIndex: number) {\n        const LEN = this._arrBaseTexture.length;\n        for (let i = startIndex; i < LEN; i++) {\n            this._arrBaseTexture[i].destroy();\n        }\n        this._arrBaseTexture.length = startIndex;\n    }\n\n    destroy() {\n        this._timer.reset();\n        this._path_tex_map.each((tex: AtlasTexture, path: string) => {\n            tex.destroy(false);\n        });\n        this._path_tex_map.destroy();\n\n        this._destroyBaseTextureAfter(0);\n\n        this._timer = null;\n        this._arrBaseTexture = null;\n        this._path_tex_map = null;\n        this._packer = null;\n        this._viewer = null;\n        this._packedRects = null;\n        this._notPackedRects = null;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/SceneTextures.ts",
    "content": "import { ISceneTextures } from './ISceneTextures';\nimport { AtlasImageLoadingInfo } from './loader/AtlasImageLoadingInfo';\nimport { PrimitiveMap } from './structure/PrimitiveMap';\nimport { ImageRect } from '../../maxrect-packer/geom/ImageRect';\nimport { AtlasImageLoader } from './loader/AtlasImageLoader';\nimport { EntryTextureOption } from './EntryTextureOption';\nimport { EntryTexture } from './texture/EntryTexture';\nimport { EntryBaseTexture } from './texture/EntryBaseTexture';\nimport { IRawPicture } from './model/IRawPicture';\nimport { PIXIAtlasHelper } from './PIXIAtlasHelper';\nimport { clog } from '../utils/logs';\nimport { PrimitiveSet } from './structure/PrimitiveSet';\nimport { TimeoutTimer } from '../utils/TimeoutTimer';\n\nexport class SceneTextures implements ISceneTextures {\n    private _path_tex_map: PrimitiveMap<EntryTexture> = new PrimitiveMap();\n    private _activated: boolean;\n    private _gcTimer: TimeoutTimer = new TimeoutTimer();\n\n    constructor(\n        public sceneID: string,\n        private _option: EntryTextureOption,\n        private _loader: AtlasImageLoader\n    ) {}\n\n    _internal_imageRemoved(): void {\n        if (this._gcTimer.isRunning) {\n            return;\n        }\n        this._gcTimer.timeout(500, () => {\n            this._gcTexture();\n        });\n    }\n\n    _gcTexture(): void {\n        const usedPathSet: PrimitiveSet = PIXIAtlasHelper.getScenePathSet(this.sceneID);\n        let deleteCnt = 0;\n        this._path_tex_map.each((tex: EntryTexture, path: string) => {\n            if (usedPathSet.hasValue(path)) {\n                return;\n            }\n            tex.destroy(true);\n            this._path_tex_map.remove(path);\n            deleteCnt++;\n        });\n        if (deleteCnt) {\n            clog(`[SceneTextures] ${deleteCnt} textures deleted`);\n        }\n    }\n\n    activate(): void {\n        this._activated = true;\n        this._path_tex_map.each((tex: EntryTexture, path: string) => {\n            const info = this._loader.getImageInfo(path);\n            if (!info || !info.isReady) {\n                return;\n            }\n            this.putImage(info, false);\n        });\n    }\n\n    addPicInfo(pic: IRawPicture): void {\n        const path = PIXIAtlasHelper.getRawPath(pic);\n        const map = this._path_tex_map;\n        if (map.hasValue(path)) {\n            return;\n        }\n\n        const info = this._loader.getImageInfo(path);\n        const rect: ImageRect = PIXIAtlasHelper.getNewImageRect(pic, this._option.texMaxRect);\n        if (!info) {\n            this._loader.load(pic, rect);\n        }\n        const tex = this._newTexture(path, rect);\n        map.add(path, tex);\n        if (info && info.isReady) {\n            this.putImage(info, false);\n        }\n    }\n\n    private _newTexture(path: string, rect: ImageRect): EntryTexture {\n        const baseTex: EntryBaseTexture = new EntryBaseTexture();\n        baseTex.width = rect.width;\n        baseTex.height = rect.height;\n        baseTex.mipmap = this._option.mipmap;\n        baseTex.scaleMode = this._option.scaleMode;\n        const tex = new EntryTexture(baseTex, rect);\n        this._path_tex_map.add(path, tex);\n        return tex;\n    }\n\n    deactivate(): void {\n        this._activated = false;\n        this._path_tex_map.each((tex: EntryTexture, path: string) => {\n            tex.getBaseTexture().dispose();\n        });\n    }\n\n    getTexture(path: string): EntryTexture {\n        return this._path_tex_map.getValue(path);\n    }\n\n    putImage(info: AtlasImageLoadingInfo, forceUpdateBaseTexture: boolean): void {\n        const tex: EntryTexture = this._path_tex_map.getValue(info.path);\n        if (!tex) {\n            return;\n        }\n        const baseTex = tex.getBaseTexture();\n        const source = info.source();\n\n        // protected 값에대한 직접접근입니다. 타입체크 하지않습니다.\n        // @ts-ignore\n        if (tex._frame) {\n            // @ts-ignore\n            const textureFrame = tex._frame;\n            if (textureFrame.height != info.srcHeight) {\n                textureFrame.height = info.srcHeight;\n            }\n            if (textureFrame.width != info.srcWidth) {\n                textureFrame.width = info.srcWidth;\n            }\n        }\n        baseTex.updateSource(source);\n\n        Entry.requestUpdate = true;\n    }\n\n    destroy(): void {\n        clog('destroy', this.sceneID);\n        this._gcTimer.reset();\n        this._gcTimer = null;\n\n        this._path_tex_map.each((tex: EntryTexture, path: string) => {\n            tex.destroy(true);\n        });\n        this._path_tex_map.destroy();\n        this._path_tex_map = null;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/loader/AtlasImageLoader.ts",
    "content": "import { AtlasImageLoadingInfo } from './AtlasImageLoadingInfo';\nimport { IRawPicture } from '../model/IRawPicture';\nimport { PrimitiveSet } from '../structure/PrimitiveSet';\nimport { TimeoutTimer } from '../../utils/TimeoutTimer';\nimport { PIXIAtlasHelper } from '../PIXIAtlasHelper';\nimport { ImageRect } from '../../../maxrect-packer/geom/ImageRect';\nimport { clog } from '../../utils/logs';\n// @ts-ignore\nimport each from 'lodash/each';\n\nconst TIME_OUT_DELAY: number = 1000;\n\ntype LoadingInfoMap = { [key: string]: AtlasImageLoadingInfo };\n\nexport type ImageLoaderHandler = (info: AtlasImageLoadingInfo) => void;\ndeclare let Entry: any;\n\nexport class AtlasImageLoader {\n    private _path_info_map: LoadingInfoMap = {};\n    private _timer: TimeoutTimer = new TimeoutTimer();\n    private _syncRequested: boolean;\n\n    constructor(private _onLoadCallback: ImageLoaderHandler) {}\n\n    /**\n     * model 의 이미지를 로드 후, rect.scaleFactor가 1이 아닐경우 rect 만큼 리사이즈한 canvas 를 소스로 설정하긔\n     * @param model\n     * @param imgRect\n     * @param subCallback\n     */\n    load(model: IRawPicture, imgRect: ImageRect) {\n        const path = PIXIAtlasHelper.getRawPath(model);\n        let info: AtlasImageLoadingInfo = this._path_info_map[path];\n\n        if (info) {\n            return;\n        }\n\n        info = new AtlasImageLoadingInfo(model, imgRect, this._onLoadCallback);\n        this._path_info_map[path] = info;\n        info.load();\n    }\n\n    getImageInfo(rawPath: string): AtlasImageLoadingInfo {\n        return this._path_info_map[rawPath];\n    }\n\n    /**\n     * 엔트리오브젝트에서 사용중인 이미지 리스트와 싱크를 맞춰 사용하지 않는 이미지 정보를 삭제함.\n     */\n    private _syncWithEntryObjects() {\n        this._syncRequested = false;\n        const arrObj: any[] = Entry.container.getAllObjects();\n        const allPathSet: PrimitiveSet = new PrimitiveSet();\n\n        const LEN = arrObj.length;\n        let LEN2;\n        let pics: IRawPicture[];\n        let pic: IRawPicture;\n        for (let i = 0; i < LEN; i++) {\n            pics = arrObj[i].pictures;\n            if (!pics || !(LEN2 = pics.length)) {\n                continue;\n            }\n            for (let j = 0; j < LEN2; j++) {\n                pic = pics[j];\n                allPathSet.put(pic.filename || pic.fileurl);\n            }\n        }\n\n        let deleteCnt = 0;\n        each(this._path_info_map, (info: AtlasImageLoadingInfo, path: string) => {\n            if (allPathSet.hasValue(path)) {\n                return;\n            }\n            info.destroy();\n            deleteCnt++;\n            delete this._path_info_map[path];\n        });\n\n        if (deleteCnt > 0) {\n            clog(`${deleteCnt} image item(s) deleted`);\n        }\n    }\n\n    /**\n     * 로드/케시된 모든 정보를 지움.\n     */\n    empty() {\n        this._timer.reset();\n        this._syncRequested = false;\n        each(this._path_info_map, (info: AtlasImageLoadingInfo, path: string) => {\n            info.destroy();\n        });\n        this._path_info_map = {};\n    }\n\n    requestSync() {\n        if (this._syncRequested) {\n            return;\n        }\n        this._syncRequested = true;\n\n        this._timer.timeout(TIME_OUT_DELAY, () => {\n            this._syncWithEntryObjects();\n        });\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/loader/AtlasImageLoadingInfo.ts",
    "content": "import { IRawPicture } from '../model/IRawPicture';\nimport { PIXIAtlasHelper } from '../PIXIAtlasHelper';\nimport { ImageRect } from '../../../maxrect-packer/geom/ImageRect';\nimport PIXIHelper from '../../helper/PIXIHelper';\nimport { cwarn } from '../../utils/logs';\nimport { ImageLoaderHandler } from './AtlasImageLoader';\n\ndeclare let Entry: any;\n\nenum LoadingState {\n    NONE = 1,\n    LOADING = 2,\n    COMPLETE = 3,\n    DESTROYED = 4,\n}\n\nexport class AtlasImageLoadingInfo {\n    loadState: LoadingState = LoadingState.NONE;\n    private _img: HTMLImageElement;\n    private _canvas: HTMLCanvasElement;\n\n    /**  계산된 이미지 경로. */\n    private _realPath: string;\n\n    /**  picture json 에 정의된 경로. fileurl or filename */\n    private _rawPath: string;\n\n    private _triedCnt: number = 0;\n    private _picName: string;\n\n    // 로드된 이미지 혹은 resize된 이미지의 사이즈. dimension 의 값과 다른 경우가 있어서 추가함.\n    public srcWidth: number;\n    public srcHeight: number;\n    private _subCallback: ImageLoaderHandler[] = [];\n\n    /**\n     * model 의 이미지를 로드 후, imgRect.scaleFactor가 1이 아닐경우 imgRect 만큼 리사이즈한 canvas 를 소스로 설정하긔\n     * @param model\n     * @param _imgRect\n     * @param _onLoadCallback\n     */\n    constructor(\n        model: IRawPicture,\n        private _imgRect: ImageRect,\n        private _onLoadCallback: ImageLoaderHandler\n    ) {\n        this._realPath = this._getImageSrc(model);\n        this._rawPath = PIXIAtlasHelper.getRawPath(model);\n        this._picName = model.name;\n    }\n\n    source(): HTMLImageElement | HTMLCanvasElement {\n        return this._img || this._canvas;\n    }\n\n    /**\n     * 이미지가 로드 되면 호출 할 콜백들. 이미지가 로드 된 후 add된 값들은 무시 됨.\n     * @param fn\n     */\n    addCallback(fn: ImageLoaderHandler): void {\n        if (!fn || this.isReady) {\n            return;\n        }\n        this._subCallback.push(fn);\n    }\n\n    load() {\n        if (this.loadState != LoadingState.NONE) {\n            return;\n        }\n        this.loadState = LoadingState.LOADING;\n        const img: HTMLImageElement = new Image();\n        this._img = img;\n\n        img.crossOrigin = 'Anonymous';\n\n        img.onload = () => {\n            Entry.Loader.removeQueue();\n            if (this.loadState == LoadingState.DESTROYED) {\n                return;\n            }\n            this.loadState = LoadingState.COMPLETE;\n\n            this._canvas = this._resizeIfNotValidSize();\n            if (this._canvas) {\n                this._destroyImage();\n            }\n\n            this._onLoadCallback(this);\n            this._onLoadCallback = null;\n            this._subCallback.forEach((fn) => {\n                fn(this);\n            });\n            this._subCallback = null;\n        };\n\n        img.onerror = (err) => {\n            Entry.Loader.removeQueue();\n            if (this.loadState == LoadingState.DESTROYED) {\n                return;\n            }\n            if (!this._triedCnt) {\n                if (Entry.type !== 'invisible') {\n                    console.log('err=', this._picName, 'load failed');\n                }\n                this._triedCnt = 1;\n                this._loadPath(this._realPath);\n            } else if (this._triedCnt < 3) {\n                this._triedCnt++;\n                this._loadPath(`${Entry.mediaFilePath}_1x1.png`);\n            } else {\n                //prevent infinite call\n                img.onerror = null;\n            }\n        };\n        this._loadPath(this._realPath);\n    }\n\n    private _loadPath(path: string) {\n        if (this.loadState == LoadingState.DESTROYED) {\n            return;\n        }\n        Entry.Loader.addQueue();\n        this._img.src = path;\n    }\n\n    get isReady() {\n        return this.loadState == LoadingState.COMPLETE;\n    }\n\n    /** pictureModel.fileurl or pictureModel.filename **/\n    get path(): string {\n        return this._rawPath;\n    }\n\n    private _getImageSrc(picture: IRawPicture) {\n        if (picture.fileurl) {\n            return picture.fileurl;\n        }\n\n        const name = picture.filename;\n        return `${Entry.defaultPath}/uploads/${name.substring(0, 2)}/${name.substring(\n            2,\n            4\n        )}/image/${name}.png`;\n    }\n\n    destroy() {\n        this.loadState = LoadingState.DESTROYED;\n        this._destroyImage();\n        if (this._canvas) {\n            this._canvas = null;\n        }\n        this._subCallback = null;\n        this._rawPath = this._realPath = null;\n    }\n\n    private _destroyImage() {\n        if (!this._img) {\n            return;\n        }\n        this._img.onload = this._img.onerror = null;\n        this._img = null;\n    }\n\n    private _resizeIfNotValidSize() {\n        const img: HTMLImageElement = this._img;\n        const sw = img.naturalWidth || img.width;\n        const sh = img.naturalHeight || img.height;\n        this.srcWidth = sw;\n        this.srcHeight = sh;\n        const r = this._imgRect;\n\n        const isScale1 = r.scaleFactorX == 1 && r.scaleFactorY == 1;\n        const isSameSizeWithData = r.dataWidth == sw && r.dataHeight == sh;\n\n        if (isScale1 && isSameSizeWithData) {\n            return null;\n        }\n\n        // if(!isScale1) {\n        //     let sfx = r.scaleFactorX.toFixed(3);\n        //     let sfy = r.scaleFactorY.toFixed(3);\n        //     clog(`tex-rezie (${sw},${sh})->(${r.width},${r.height}). factor:(${sfx},${sfy})`);\n        // }\n\n        if (!isSameSizeWithData) {\n            cwarn(\n                `Image size not match. data(w=${r.dataWidth},h=${r.dataHeight}), real(w=${sw},h=${sh})`\n            );\n        }\n\n        const canvas = PIXIHelper.getOffScreenCanvas();\n        this.srcWidth = canvas.width = r.width;\n        this.srcHeight = canvas.height = r.height;\n        const ctx: CanvasRenderingContext2D = canvas.getContext('2d');\n        ctx.imageSmoothingEnabled = true;\n        ctx.drawImage(img, 0, 0, r.width, r.height);\n        return canvas;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/model/IRawObject.ts",
    "content": "import { IRawPicture } from './IRawPicture';\n\nexport interface IRawObject {\n    id: string,\n    name: string,\n    script: string,\n    objectType: string,\n    rotateMethod: string,\n    scene: string,\n    sprite:{ pictures:IRawPicture[], sounds:any[] },\n    text: string,\n    lock: boolean,\n    entity: any\n}"
  },
  {
    "path": "src/class/pixi/atlas/model/IRawPicture.ts",
    "content": "export interface IRawPicture {\n    id:string;\n    dimension: { width:number, height:number };\n    fileurl:string;\n    filename:string;\n    name:string;\n}"
  },
  {
    "path": "src/class/pixi/atlas/structure/PrimitiveMap.ts",
    "content": "// @ts-ignore\nimport each from 'lodash/each';\n\nexport class PrimitiveMap<T> {\n    private _map: { [key: string]: T } = {};\n\n    add(key: string | number, value: T) {\n        this._map[key] = value;\n    }\n\n    getValue(key: string | number): T {\n        return this._map[key];\n    }\n\n    hasValue(key: string | number): boolean {\n        return Boolean(this._map[key]);\n    }\n\n    remove(key: string | number): T {\n        const v: T = this._map[key];\n        delete this._map[key];\n        return v;\n    }\n\n    destroy(): void {\n        this._map = null;\n    }\n\n    each(f: (value: T, key: string | number) => void): void {\n        each(this._map, f);\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/structure/PrimitiveSet.ts",
    "content": "// @ts-ignore\nimport each from 'lodash/each';\n\nexport class PrimitiveSet {\n    private _map: any = {};\n\n    hasValue(value: string | number): boolean {\n        return this._map[value];\n    }\n\n    put(value: string | number) {\n        this._map[value] = true;\n    }\n\n    remove(value: string | number) {\n        delete this._map[value];\n    }\n\n    each(callback: (value: string | number) => void) {\n        each(this._map, (v: boolean, key: string) => {\n            callback(key);\n        });\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/texture/AtlasBaseTexture.ts",
    "content": "import { BaseTexture, resources } from 'pixi.js';\nimport { AtlasCanvasViewer } from '../AtlasCanvasViewer';\n\nexport class AtlasBaseTexture extends BaseTexture {\n    private _canvas: HTMLCanvasElement;\n    private _ctx: CanvasRenderingContext2D;\n    private _activated: boolean;\n\n    constructor(private _viewer?: AtlasCanvasViewer, scaleMode?: number) {\n        super(null, { scaleMode });\n    }\n\n    get activated(): boolean {\n        return this._activated;\n    }\n\n    setCanvas(canvas: HTMLCanvasElement) {\n        const resource = new resources.CanvasResource(canvas);\n        this.setResource(resource);\n        this._canvas = canvas;\n        this._ctx = canvas.getContext('2d');\n    }\n\n    getCanvas(): HTMLCanvasElement {\n        return this._canvas;\n    }\n\n    cleanCanvas(): void {\n        this._ctx.clearRect(0, 0, this._canvas.width, this._canvas.height);\n    }\n\n    activate(MAX_SIZE: number) {\n        this._activated = true;\n        this._canvas.width = MAX_SIZE;\n        this._canvas.height = MAX_SIZE;\n        // this.hasLoaded = true; deprecated v5\n        this._viewer.add(this._canvas);\n    }\n\n    deactivate() {\n        this._activated = false;\n        this._canvas.width = 1;\n        this._canvas.height = 1;\n        this.dispose();\n    }\n\n    destroy() {\n        super.destroy();\n        this._canvas = null;\n        this._ctx = null;\n    }\n\n    dispose() {\n        super.dispose();\n        if (this._viewer) {\n            this._viewer.removeCanvas(this._canvas);\n        }\n    }\n\n    getCtx() {\n        return this._ctx;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/texture/AtlasTexture.ts",
    "content": "/*\n생성자에서 empty base texture 를 받은 후, sprite 를 통해 즉시 stage에서 사용 할 수 있도록 함.\n */\n\nimport { AtlasBaseTexture } from './AtlasBaseTexture';\nimport { ImageRect } from '../../../maxrect-packer/geom/ImageRect';\nimport { AtlasImageLoadingInfo } from '../loader/AtlasImageLoadingInfo';\nimport { EntryTextureBase } from './EntryTextureBase';\n\nexport class AtlasTexture extends EntryTextureBase {\n    /** binpacking의 rect 참조를 위한 변수. 다용 용도로 사용하지 말긔. */\n    public imageRectForPacking: ImageRect;\n    private _isEmptyTexture: boolean;\n    public textureScaleFactorX: number;\n    public textureScaleFactorY: number;\n\n    constructor(baseTexture: AtlasBaseTexture, imageRect: ImageRect) {\n        super(baseTexture, imageRect);\n        this._isEmptyTexture = true;\n        this.imageRectForPacking = imageRect;\n    }\n\n    get isEmptyTexture(): boolean {\n        return this._isEmptyTexture;\n    }\n\n    getBaseTexture(): AtlasBaseTexture {\n        return this.baseTexture as AtlasBaseTexture;\n    }\n\n    /**\n     * @param info\n     * @param extrude - must uint value. Reduce flickering in some cases where sprites have to be put next to each other in the final program.\n     * example: https://www.codeandweb.com/texturepacker/documentation/texture-settings\n     */\n    drawImageAtBaseTexture(info: AtlasImageLoadingInfo, extrude: number): void {\n        if (this._isEmptyTexture) {\n            return;\n        }\n        const img = info.source();\n        const ctx: CanvasRenderingContext2D = this.getBaseTexture().getCtx();\n        const r = this.frame;\n        const w = r.width;\n        const h = r.height;\n        const rx = r.x;\n        const ry = r.y;\n\n        const sw = info.srcWidth;\n        const sh = info.srcHeight;\n\n        /* //for debug background\n        ctx.fillStyle = PIXIHelper.randomRGBAString(0.3);\n        ctx.fillRect(rx, ry, w, h);\n        //*/\n        ctx.drawImage(img, 0, 0, sw, sh, rx, ry, w, h);\n        if (extrude) {\n            ctx.save();\n            ctx.imageSmoothingEnabled = false;\n            //top\n            ctx.drawImage(img, 0, 0, sw, 1, rx, ry - extrude, w, extrude);\n            //down\n            ctx.drawImage(img, 0, sh - 1, sw, 1, rx, ry + h, w, extrude);\n            //left\n            ctx.drawImage(img, 0, 0, 1, sh, rx - extrude, ry, extrude, h);\n            //right\n            ctx.drawImage(img, sw - 1, 0, 1, sh, rx + w, ry, extrude, h);\n            ctx.restore();\n        }\n    }\n\n    /**\n     * 진짜로 사용할 BaseTexture를 할당 받고, uv를 업데이트 함.\n     * @param base\n     */\n    updateBaseAndUVs(base: AtlasBaseTexture): void {\n        this._isEmptyTexture = false;\n        this.baseTexture = base;\n        if (\n            this.frame.x != this.imageRectForPacking.x ||\n            this.frame.y != this.imageRectForPacking.y\n        ) {\n            this.frame.x = this.imageRectForPacking.x;\n            this.frame.y = this.imageRectForPacking.y;\n            this._updateUvs();\n        }\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/texture/EntryBaseTexture.ts",
    "content": "import { BaseTexture, resources } from 'pixi.js';\n\nexport class EntryBaseTexture extends BaseTexture {\n    private _hasSource: boolean;\n\n    updateSource(src: HTMLImageElement | HTMLCanvasElement) {\n        if (!this.resource) {\n            const resource = resources.autoDetectResource(src);\n            this.setResource(resource);\n            this.update();\n        }\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/texture/EntryTexture.ts",
    "content": "import { ImageRect } from '../../../maxrect-packer/geom/ImageRect';\nimport { EntryBaseTexture } from './EntryBaseTexture';\nimport { EntryTextureBase } from './EntryTextureBase';\n\nexport class EntryTexture extends EntryTextureBase {\n    constructor(baseTexture: EntryBaseTexture, imageRect: ImageRect) {\n        super(baseTexture, imageRect);\n    }\n\n    getBaseTexture(): EntryBaseTexture {\n        return this.baseTexture as EntryBaseTexture;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/atlas/texture/EntryTextureBase.ts",
    "content": "import { ImageRect } from '../../../maxrect-packer/geom/ImageRect';\nimport { Texture, RenderTexture, Rectangle, BaseTexture } from 'pixi.js';\n\nexport class EntryTextureBase extends Texture {\n    public textureScaleFactorX: number;\n    public textureScaleFactorY: number;\n\n    constructor(baseTexture: BaseTexture, imageRect: ImageRect) {\n        const frame = new Rectangle(0, 0, imageRect.width, imageRect.height);\n        super(baseTexture, frame);\n        this.textureScaleFactorX = imageRect.scaleFactorX;\n        this.textureScaleFactorY = imageRect.scaleFactorY;\n    }\n\n    assignTextureScaleFactor(target: RenderTexture) {\n        if (target) {\n            const tex: any = target;\n            //textureScaleFactor 변수 네이밍을 여기저기서 쓰지 않으려고 메서드를 만듬.\n            tex.textureScaleFactorX = this.textureScaleFactorX;\n            tex.textureScaleFactorY = this.textureScaleFactorY;\n        }\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/etc/PIXI-ndgmr.Collision.js",
    "content": "/*\n  The MIT License\n\n  Copyright (c) 2012 Olaf Horstmann, indiegamr.com\n\n  Permission is hereby granted, free of charge, to any person obtaining a copy\n  of this software and associated documentation files (the \"Software\"), to deal\n  in the Software without restriction, including without limitation the rights\n  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n  copies of the Software, and to permit persons to whom the Software is\n  furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\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 THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n  THE SOFTWARE.\n*/\n\n/**\n * [original]\n * A Pixel Perfect Collision Detection for EaselJS Bitmap-Objects\n * @author olsn, indiegamr.com\n *\n * [edit 2018.09.01]\n * A Pixel Perfect Collision Detection for entryjs PIXI.Sprite-Object\n *\n **/\nimport * as PIXI from 'pixi.js';\nconst ndgmr = {};\n\n//--------- Class CollisionCanvas -------\nclass CollisionCanvas {\n    constructor() {\n        /** @readonly **/\n        this._canvas = document.createElement('canvas');\n        this._ctx = this._canvas.getContext('2d');\n        this._ctx.save();\n        this._prepended = false;\n    }\n\n    /**\n     * for debug\n     * @param color css style color\n     */\n    __prepend(color) {\n        if (this._prepended) {\n            return;\n        }\n        this._prepended = true;\n        $('body').prepend(this._canvas);\n        $(this._canvas).css('border', `1px solid ${color}`);\n    }\n\n    render(obj, intersectRect) {\n        const tex = obj.internal_getOriginalTex();\n        if (!tex) {\n            return;\n        }\n        const fr = tex.frame;\n        if (!fr || fr.width === 0 || fr.height === 0) {\n            return;\n        }\n        if (!tex.baseTexture) {\n            return;\n        }\n        const { source } = tex.baseTexture.resource || {};\n        if (!source) {\n            return;\n        }\n\n        const IR = intersectRect;\n        const canvas = this._canvas;\n        const ctx = this._ctx;\n\n        canvas.width = IR.width;\n        canvas.height = IR.height;\n\n        obj.toLocal(IR, null, _LP);\n\n        const { a, b, c, d } = obj.worldTransform;\n        ctx.setTransform(a, b, c, d, 0, 0);\n        ctx.translate(-_LP.x, -_LP.y);\n\n        ctx.drawImage(source, fr.x, fr.y, fr.width, fr.height, 0, 0, fr.width, fr.height);\n        return ctx.getImageData(0, 0, IR.width, IR.height).data;\n    }\n}\n\n//--------- end of Class CollisionCanvas -------\n\nconst threshold = 1;\n\n/** @type PIXI.Rectangle; **/\nlet _RECT1;\nlet _RECT2;\n\n/** @type PIXI.Point. for global to local point **/\nlet _LP; //localPoint\n\n/** @type CollisionCanvas **/\nlet canvas1;\nlet canvas2;\n\n/** @private  use only debug. **/\nndgmr.___debugIntersectionRect = null;\n\nndgmr.initTempObject = function() {\n    _RECT1 = new PIXI.Rectangle();\n    _RECT2 = new PIXI.Rectangle();\n    _LP = new PIXI.Point();\n    canvas1 = new CollisionCanvas();\n    canvas2 = new CollisionCanvas();\n};\n\nfunction isContainer(obj) {\n    const isSprite = obj instanceof PIXI.Sprite;\n    if (isSprite) {\n        return false;\n    }\n    return obj instanceof PIXI.Container;\n}\n\nndgmr.checkPixelCollision = function(bitmap1, bitmap2, alphaThreshold, getRect) {\n    if (ndgmr.DEBUG || ndgmr.DEBUG_COLLISION) {\n        canvas2.__prepend('blue');\n        canvas1.__prepend('red');\n    }\n\n    bitmap1.getBounds(false, _RECT1);\n    bitmap2.getBounds(false, _RECT2);\n\n    if (!_collisionDistancePrecheck(_RECT1, _RECT2)) {\n        return false;\n    }\n\n    const intersection = _checkRectCollisionForPIXIRect(_RECT1, _RECT2);\n\n    ndgmr.___debugIntersectionRect = intersection;\n\n    if (!intersection) {\n        return false;\n    }\n\n    //글상자와 벽 충돌 체크\n    if (isContainer(bitmap1) || isContainer(bitmap2)) {\n        return intersection;\n    }\n\n    const iw = intersection.width;\n    const ih = intersection.height;\n\n    if (iw === 0 || ih === 0) {\n        return false;\n    }\n\n    //chrome float point number bug\n    if (iw / threshold < 1 || ih / threshold < 1) {\n        return false;\n    }\n\n    alphaThreshold = Math.min(0.99999, alphaThreshold || 0);\n\n    let imgData1;\n    let imgData2;\n\n    if (\n        !(imgData1 = canvas1.render(bitmap1, intersection)) ||\n        !(imgData2 = canvas2.render(bitmap2, intersection))\n    ) {\n        return false;\n    }\n\n    const pixelIntersection = _compareAlphaValues(\n        imgData1,\n        imgData2,\n        iw / threshold,\n        ih / threshold,\n        alphaThreshold,\n        getRect\n    );\n\n    if (!pixelIntersection) {\n        return false;\n    }\n\n    pixelIntersection.x += intersection.x;\n    pixelIntersection.x2 += intersection.x;\n    pixelIntersection.y += intersection.y;\n    pixelIntersection.y2 += intersection.y;\n\n    return pixelIntersection;\n};\n\n/**\n * precheck if objects are even close enough\n * @param {PIXI.Rectangle} ir1\n * @param {PIXI.Rectangle} ir2\n * @return {boolean}\n * @private\n */\nfunction _collisionDistancePrecheck(ir1, ir2) {\n    return (\n        Math.abs(ir2.x - ir1.x) < (ir1.x < ir2.x ? ir1.width : ir2.width) &&\n        Math.abs(ir2.y - ir1.y) < (ir1.y < ir2.y ? ir1.height : ir2.height)\n    );\n}\n\n/**\n * TODO createjs 코드 인데.. 사용하느곳이 있는지 확인.\n * createjs legacy interface. not use internally.\n * @param bitmap1\n * @param bitmap2\n * @return {null| Rect}\n */\nndgmr.checkRectCollision = function(bitmap1, bitmap2) {\n    let b1;\n    let b2;\n    if (bitmap1 instanceof createjs.Container || bitmap2 instanceof createjs.Container) {\n        b1 = bitmap1.getTransformedBounds();\n        b2 = bitmap2.getTransformedBounds();\n    } else {\n        b1 = getBounds(bitmap1);\n        b2 = getBounds(bitmap2);\n    }\n    return _checkRectCollisionForPIXIRect(b1, b2);\n};\n\nfunction _checkRectCollisionForPIXIRect(b1, b2) {\n    // 2018.12.14 박봉배 - 불필요한 연산이라 비활성화함. 상단에서 threshold 의 기본값을 1로 고정\n    // if (Math.min(b1.width, b1.height, b2.width, b2.height) < 2)\n    //     threshold = 1;\n    // else\n    //     threshold = 1;\n    return ndgmr.calculateIntersection(b1, b2);\n}\n\nndgmr.calculateIntersection = function(rect1, rect2) {\n    // first we have to calculate the\n    // center of each rectangle and half of\n    // width and height\n    let dx;\n    let dy;\n    const r1 = {};\n    const r2 = {};\n    r1.cx = rect1.x + (r1.hw = rect1.width / 2);\n    r1.cy = rect1.y + (r1.hh = rect1.height / 2);\n    r2.cx = rect2.x + (r2.hw = rect2.width / 2);\n    r2.cy = rect2.y + (r2.hh = rect2.height / 2);\n\n    dx = Math.abs(r1.cx - r2.cx) - (r1.hw + r2.hw);\n    dy = Math.abs(r1.cy - r2.cy) - (r1.hh + r2.hh);\n\n    if (dx < 0 && dy < 0) {\n        dx = Math.min(Math.min(rect1.width, rect2.width), -dx);\n        dy = Math.min(Math.min(rect1.height, rect2.height), -dy);\n        return {\n            x: Math.max(rect1.x, rect2.x),\n            y: Math.max(rect1.y, rect2.y),\n            width: dx,\n            height: dy,\n            rect1,\n            rect2,\n        };\n    } else {\n        return null;\n    }\n};\n\nconst _compareAlphaValues = function(\n    imageData1,\n    imageData2,\n    width,\n    height,\n    alphaThreshold,\n    getRect\n) {\n    let x;\n    let y;\n    let offset = 3;\n    const pixelRect = { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity };\n\n    const _alphaThreshold = Math.round(alphaThreshold * 255) | 0;\n    const _width = width | 0;\n    const _height = height | 0;\n    const _imgData1 = imageData1;\n    const _imgData2 = imageData2;\n    const LEN1 = _imgData1.length;\n    const LEN2 = _imgData2.length;\n\n    // parsing through the pixels checking for an alpha match\n    // TODO: intelligent parsing, not just from 0 to end!\n    for (y = 0; y < _height; ++y) {\n        for (x = 0; x < _width; ++x) {\n            if (\n                LEN1 > offset + 1 &&\n                LEN2 > offset + 1 &&\n                _imgData1[offset] > _alphaThreshold &&\n                _imgData2[offset] > _alphaThreshold\n            ) {\n                if (getRect) {\n                    if (x < pixelRect.x) {\n                        pixelRect.x = x;\n                    }\n                    if (x > pixelRect.x2) {\n                        pixelRect.x2 = x;\n                    }\n                    if (y < pixelRect.y) {\n                        pixelRect.y = y;\n                    }\n                    if (y > pixelRect.y2) {\n                        pixelRect.y2 = y;\n                    }\n                } else {\n                    return { x, y, width: 1, height: 1 };\n                }\n            }\n            offset += 4;\n        }\n    }\n\n    if (pixelRect.x != Infinity) {\n        pixelRect.width = pixelRect.x2 - pixelRect.x + 1;\n        pixelRect.height = pixelRect.y2 - pixelRect.y + 1;\n        return pixelRect;\n    }\n\n    return null;\n};\n\nexport const PIXICollision = ndgmr;\n"
  },
  {
    "path": "src/class/pixi/etc/PIXIBrushAdaptor.ts",
    "content": "import { DisplayObject } from 'pixi.js';\nimport { PIXIGraphics } from '../helper/PIXIHelper';\n\ninterface IRBG {\n    r: number;\n    g: number;\n    b: number;\n}\n\n/**\n * createjs.Graphics 스타일의 lagacy 메서드 호출을 pixi.Graphics 로 변경해주는 adaptor 클라스.\n */\nexport class PIXIBrushAdaptor {\n    //아래 값들은 다른 클래스에서 값을 할당해줌.\n    public rgb: IRBG;\n    public thickness: number;\n    public opacity: number;\n    /** [박봉배] 추측 - drawing 중인지 아닌지를 저장하는 값으로 생각 됨. */\n    public stop: boolean;\n\n    /** [박봉배] 추측 - 이 브러시가 따라다녀야 할 대상 */\n    public entity: DisplayObject;\n\n    //아래 값들은 내부에서만 사용함.\n    private _alpha: number = 1;\n    private _thickness: number;\n    private _color: number;\n\n    private _shape: PIXIGraphics;\n    private position: any = { x: 0, y: 0 };\n\n    endStroke() {\n        //#10141 때문에 closePath 사용안함.\n        // if(!this._shape || this._shape.destroyied) return;\n        // this._shape.closePath();\n    }\n\n    /**\n     * createjs 스타일. 문자열 파싱을 하기 때문에 느림. 블럭 몇몇곳에서 이 스타일을 사용하기 떄문에 남겨둠.\n     * @param color - \"#FF0000\", \"rgba(255,0,0,0.5)\"\n     */\n    beginStroke(color: string) {\n        this._parseRGBCssStyleColor(color);\n        this._setStyle();\n    }\n\n    /**\n     * pixi 엔진에 최적화된 함수. beginStroke() 보다 빠름.\n     * @param color\n     * @param alpha\n     */\n    beginStrokeFast(color: number, alpha: number): void {\n        this._color = color;\n        this._alpha = alpha;\n        this._setStyle();\n    }\n\n    endFill() {\n        // #10141 때문에 closePath 사용안함.\n        if (!this._shape || this._shape.destroyed) {\n            return;\n        }\n        this._shape.closePath();\n    }\n\n    beginFill(color: string) {\n        this._parseRGBCssStyleColor(color);\n        this._setStyle();\n    }\n\n    beginFillFast(color: number, alpha: number) {\n        this._color = color;\n        this._alpha = alpha;\n        this._setStyle();\n    }\n\n    setStrokeStyle(thickness: number) {\n        this._thickness = thickness;\n        this._setStyle();\n    }\n\n    moveTo(x: number, y: number) {\n        if (!this._shape || this._shape.destroyed) {\n            return;\n        }\n        this._shape.moveTo(Number(x), Number(y));\n        this.position = { x: Number(x), y: Number(y) };\n    }\n\n    lineTo(x: number, y: number) {\n        if (!this._shape || this._shape.destroyed) {\n            return;\n        }\n        //this._setStyle(); // pixi webgl 오류 때문에 이것을 함.\n        this._shape.moveTo(this.position.x, this.position.y);\n        this._shape.lineTo(Number(x), Number(y)); // 박봉배: #9374 x,y 좌표가 문자로 넘어와서 생긴 이슈\n        this.position = { x: Number(x), y: Number(y) };\n        this._shape.geometry.invalidate();\n    }\n\n    /** @param shape - drawing 을 할 대상을 지정 */\n    internalSetShape(shape: PIXIGraphics) {\n        this._shape = shape;\n        this._setStyle();\n    }\n\n    _setStyle() {\n        if (!this._shape || this._shape.destroyed) {\n            return;\n        }\n        this._shape.lineStyle(this._thickness, this._color, this._alpha);\n    }\n\n    _parseRGBCssStyleColor(colorOld: string) {\n        const color = colorOld.replace('/s/', '');\n        if (color[0] == '#') {\n            this._color = parseInt(color.replace('#', ''), 16);\n            return;\n        }\n\n        let result;\n\n        //rgb 보다 rgba 문자열을 더 많이 사용하는것 같아 이 조건문을 위로 올림\n        if ((result = /^rgba\\((\\d+),(\\d+),(\\d+),(\\d+(\\.?\\d*))\\)$/i.exec(color))) {\n            this._color = this._RGBToNumber(result);\n            this._alpha = Number(result[4]);\n            return;\n        }\n\n        if ((result = /^rgb\\((\\d+),(\\d+),(\\d+)\\)$/i.exec(color))) {\n            this._color = this._RGBToNumber(result);\n        }\n    }\n\n    _RGBToNumber(regexResult: any[]) {\n        const [x, r, g, b] = regexResult;\n        return (r << 16) + (g << 8) + Number(b);\n    }\n    // Matched the method name to createjs for fulfilling the purpose of wrapper class (#11626)\n    clear() {\n        const { x = 0, y = 0 } = this.entity || {};\n        this._shape.clear();\n        // Disconnect the previously continued path\n        this._shape.moveTo(x, -y);\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/etc/PIXICanvasInput.js",
    "content": "/*!\n *  CanvasInput v1.1.5\n *  http://goldfirestudios.com/blog/108/CanvasInput-HTML5-Canvas-Text-Input\n *\n *  (c) 2013-2014, James Simpson of GoldFire Studios\n *  goldfirestudios.com\n *\n *  MIT License\n */\nimport * as PIXI from 'pixi.js';\n(function() {\n    // create a buffer that stores all inputs so that tabbing\n    // between them is made possible.\n    const inputs = [];\n\n    // initialize the Canvas Input\n    // eslint-disable-next-line no-multi-assign\n    const CanvasInput = (window.PIXICanvasInput = function(o) {\n        const self = this;\n\n        o = o ? o : {};\n\n        // setup the defaults\n        self._canvas = o.canvas || null;\n        self._isHidden = true;\n        self._ctx = self._canvas ? self._canvas.getContext('2d') : null;\n        self._x = o.x || 0;\n        self._y = o.y || 0;\n        self._extraX = o.extraX || 0;\n        self._extraY = o.extraY || 0;\n        self._fontSize = o.fontSize || 14;\n        self._fontFamily = o.fontFamily || 'Arial';\n        self._fontColor = o.fontColor || '#000';\n        self._placeHolderColor = o.placeHolderColor || '#bfbebd';\n        self._fontWeight = o.fontWeight || 'normal';\n        self._fontStyle = o.fontStyle || 'normal';\n        self._readonly = o.readonly || false;\n        self._maxlength = o.maxlength || null;\n        self._width = o.width || 150;\n        self._height = o.height || self._fontSize;\n        self._padding = o.padding >= 0 ? o.padding : 5;\n        self._borderWidth = o.borderWidth >= 0 ? o.borderWidth : 1;\n        self._borderColor = o.borderColor || '#959595';\n        self._borderRadius = o.borderRadius >= 0 ? o.borderRadius : 3;\n        self._backgroundImage = o.backgroundImage || '';\n        self._boxShadow = o.boxShadow || '1px 1px 0px rgba(255, 255, 255, 1)';\n        self._innerShadow = o.innerShadow || '0px 0px 4px rgba(0, 0, 0, 0.4)';\n        self._selectionColor = o.selectionColor || 'rgba(179, 212, 253, 0.8)';\n        self._placeHolder = o.placeHolder || '';\n        self._value = `${o.value || self._placeHolder}`;\n        self._onsubmit = o.onsubmit || function() {};\n        self._onkeydown = o.onkeydown || function() {};\n        self._onkeyup = o.onkeyup || function() {};\n        self._onfocus = o.onfocus || function() {};\n        self._onblur = o.onblur || function() {};\n        self._cursor = false;\n        self._cursorPos = 0;\n        self._hasFocus = false;\n        self._selection = [0, 0];\n        self._wasOver = false;\n        self._topPosition = o.topPosition;\n\n        // parse box shadow\n        self.boxShadow(self._boxShadow, true);\n\n        // calculate the full width and height with padding, borders and shadows\n        self._calcWH();\n\n        // setup the off-DOM canvas\n        self._renderCanvas = document.createElement('canvas');\n        self._renderCanvas.setAttribute('width', self.outerW);\n        self._renderCanvas.setAttribute('height', self.outerH);\n        self._renderCtx = self._renderCanvas.getContext('2d');\n\n        const texture = PIXI.Texture.from(self._renderCanvas);\n        self._pixiView = new PIXI.Sprite(texture);\n        self._pixiView.interactive = false;\n\n        // setup another off-DOM canvas for inner-shadows\n        self._shadowCanvas = document.createElement('canvas');\n        self._shadowCanvas.setAttribute('width', self._width + self._padding * 2);\n        self._shadowCanvas.setAttribute('height', self._height + self._padding * 2);\n        self._shadowCtx = self._shadowCanvas.getContext('2d');\n\n        // setup the background color\n        if (typeof o.backgroundGradient !== 'undefined') {\n            self._backgroundColor = self._renderCtx.createLinearGradient(0, 0, 0, self.outerH);\n            self._backgroundColor.addColorStop(0, o.backgroundGradient[0]);\n            self._backgroundColor.addColorStop(1, o.backgroundGradient[1]);\n        } else {\n            self._backgroundColor = o.backgroundColor || '#fff';\n        }\n\n        // setup main canvas events\n        if (self._canvas) {\n            self._canvas.addEventListener(\n                'mousemove',\n                (e) => {\n                    e = e || window.event;\n                    self.mousemove(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'mousedown',\n                (e) => {\n                    e = e || window.event;\n                    self.mousedown(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'touchstart',\n                (e) => {\n                    e = e || window.event;\n                    self.mousedown(e, self);\n                },\n                false\n            );\n\n            self._canvas.addEventListener(\n                'mouseup',\n                (e) => {\n                    e = e || window.event;\n                    self.mouseup(e, self);\n                },\n                false\n            );\n        }\n\n        // setup a global mouseup to blur the input outside of the canvas\n        window.addEventListener(\n            'mouseup',\n            () => {\n                //e = e || window.event;\n                //if (self._hasFocus && !self._mouseDown) {\n                //self.blur();\n                //}\n            },\n            true\n        );\n\n        // create the hidden input element\n        self._hiddenInput = document.createElement('input');\n        self._hiddenInput.className = 'entryCanvasHiddenInput';\n        self._hiddenInput.type = 'text';\n        self._hiddenInput.style.position = 'absolute';\n        self._hiddenInput.style.opacity = 0;\n        self._hiddenInput.style.pointerEvents = 'none';\n        self._hiddenInput.style.left = '-500px';\n        self._hiddenInput.style.top = '0px';\n        self._hiddenInput.style.width = `${self._width}px`;\n        self._hiddenInput.style.height = `${self._height}px`;\n        self._hiddenInput.style.zIndex = -999;\n        if (self._maxlength) {\n            self._hiddenInput.maxLength = self._maxlength;\n        }\n        document.body.appendChild(self._hiddenInput);\n        self._hiddenInput.value = self._value;\n\n        // setup the keydown listener\n        self._hiddenInput.addEventListener('keydown', (e) => {\n            e = e || window.event;\n\n            if (self._hasFocus) {\n                self.keydown(e, self);\n            }\n        });\n\n        // setup the keyup listener\n        self._hiddenInput.addEventListener('keyup', (e) => {\n            e = e || window.event;\n\n            // update the canvas input state information from the hidden input\n            self._value = self._hiddenInput.value;\n            self._cursorPos = self._hiddenInput.selectionStart;\n            self.render();\n\n            if (self._hasFocus) {\n                self._onkeyup(e, self);\n            }\n        });\n\n        // add this to the buffer\n        inputs.push(self);\n        self._inputsIndex = inputs.length - 1;\n\n        // draw the text box\n        self.render();\n    });\n\n    // setup the prototype\n    CanvasInput.prototype = {\n        getPixiView() {\n            return this._pixiView;\n        },\n\n        /**\n         * Get/set the main canvas.\n         * @param  {Object} data Canvas reference.\n         * @return {Mixed}      CanvasInput or current canvas.\n         */\n        canvas(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                throw new Error('Deprecated: CanvasInput.canvas');\n                self._canvas = data;\n                self._ctx = self._canvas.getContext('2d');\n\n                return self.render();\n            } else {\n                return self._canvas;\n            }\n        },\n\n        /**\n         * Get/set the x-position.\n         * @param  {Number} data The pixel position along the x-coordinate.\n         * @return {Mixed}      CanvasInput or current x-value.\n         */\n        x(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._x = data;\n\n                return self.render();\n            } else {\n                return self._x;\n            }\n        },\n\n        /**\n         * Get/set the y-position.\n         * @param  {Number} data The pixel position along the y-coordinate.\n         * @return {Mixed}      CanvasInput or current y-value.\n         */\n        y(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._y = data;\n\n                return self.render();\n            } else {\n                return self._y;\n            }\n        },\n\n        /**\n         * Get/set the extra x-position (generally used when no canvas is specified).\n         * @param  {Number} data The pixel position along the x-coordinate.\n         * @return {Mixed}      CanvasInput or current x-value.\n         */\n        extraX(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._extraX = data;\n\n                return self.render();\n            } else {\n                return self._extraX;\n            }\n        },\n\n        /**\n         * Get/set the extra y-position (generally used when no canvas is specified).\n         * @param  {Number} data The pixel position along the y-coordinate.\n         * @return {Mixed}      CanvasInput or current y-value.\n         */\n        extraY(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._extraY = data;\n\n                return self.render();\n            } else {\n                return self._extraY;\n            }\n        },\n\n        /**\n         * Get/set the font size.\n         * @param  {Number} data Font size.\n         * @return {Mixed}      CanvasInput or current font size.\n         */\n        fontSize(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontSize = data;\n\n                return self.render();\n            } else {\n                return self._fontSize;\n            }\n        },\n\n        /**\n         * Get/set the font family.\n         * @param  {String} data Font family.\n         * @return {Mixed}      CanvasInput or current font family.\n         */\n        fontFamily(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontFamily = data;\n\n                return self.render();\n            } else {\n                return self._fontFamily;\n            }\n        },\n\n        /**\n         * Get/set the font color.\n         * @param  {String} data Font color.\n         * @return {Mixed}      CanvasInput or current font color.\n         */\n        fontColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontColor = data;\n\n                return self.render();\n            } else {\n                return self._fontColor;\n            }\n        },\n\n        /**\n         * Get/set the place holder font color.\n         * @param  {String} data Font color.\n         * @return {Mixed}      CanvasInput or current place holder font color.\n         */\n        placeHolderColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._placeHolderColor = data;\n\n                return self.render();\n            } else {\n                return self._placeHolderColor;\n            }\n        },\n\n        /**\n         * Get/set the font weight.\n         * @param  {String} data Font weight.\n         * @return {Mixed}      CanvasInput or current font weight.\n         */\n        fontWeight(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontWeight = data;\n\n                return self.render();\n            } else {\n                return self._fontWeight;\n            }\n        },\n\n        /**\n         * Get/set the font style.\n         * @param  {String} data Font style.\n         * @return {Mixed}      CanvasInput or current font style.\n         */\n        fontStyle(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._fontStyle = data;\n\n                return self.render();\n            } else {\n                return self._fontStyle;\n            }\n        },\n\n        /**\n         * Get/set the width of the text box.\n         * @param  {Number} data Width in pixels.\n         * @return {Mixed}      CanvasInput or current width.\n         */\n        width(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._width = data;\n                self._calcWH();\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._width;\n            }\n        },\n\n        /**\n         * Get/set the height of the text box.\n         * @param  {Number} data Height in pixels.\n         * @return {Mixed}      CanvasInput or current height.\n         */\n        height(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._height = data;\n                self._calcWH();\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._height;\n            }\n        },\n\n        /**\n         * Get/set the padding of the text box.\n         * @param  {Number} data Padding in pixels.\n         * @return {Mixed}      CanvasInput or current padding.\n         */\n        padding(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._padding = data;\n                self._calcWH();\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._padding;\n            }\n        },\n\n        /**\n         * Get/set the border width.\n         * @param  {Number} data Border width.\n         * @return {Mixed}      CanvasInput or current border width.\n         */\n        borderWidth(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderWidth = data;\n                self._calcWH();\n                self._updateCanvasWH();\n\n                return self.render();\n            } else {\n                return self._borderWidth;\n            }\n        },\n\n        /**\n         * Get/set the border color.\n         * @param  {String} data Border color.\n         * @return {Mixed}      CanvasInput or current border color.\n         */\n        borderColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderColor = data;\n\n                return self.render();\n            } else {\n                return self._borderColor;\n            }\n        },\n\n        /**\n         * Get/set the border radius.\n         * @param  {Number} data Border radius.\n         * @return {Mixed}      CanvasInput or current border radius.\n         */\n        borderRadius(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._borderRadius = data;\n\n                return self.render();\n            } else {\n                return self._borderRadius;\n            }\n        },\n\n        /**\n         * Get/set the background color.\n         * @param  {Number} data Background color.\n         * @return {Mixed}      CanvasInput or current background color.\n         */\n        backgroundColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._backgroundColor = data;\n\n                return self.render();\n            } else {\n                return self._backgroundColor;\n            }\n        },\n\n        /**\n         * Get/set the background gradient.\n         * @param  {Number} data Background gradient.\n         * @return {Mixed}      CanvasInput or current background gradient.\n         */\n        backgroundGradient(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._backgroundColor = self._renderCtx.createLinearGradient(0, 0, 0, self.outerH);\n                self._backgroundColor.addColorStop(0, data[0]);\n                self._backgroundColor.addColorStop(1, data[1]);\n\n                return self.render();\n            } else {\n                return self._backgroundColor;\n            }\n        },\n\n        /**\n         * Get/set the box shadow.\n         * @param  {String} data     Box shadow in CSS format (1px 1px 1px rgba(0, 0, 0.5)).\n         * @param  {Boolean} doReturn (optional) True to prevent a premature render.\n         * @return {Mixed}          CanvasInput or current box shadow.\n         */\n        boxShadow(data, doReturn) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                // parse box shadow\n                const boxShadow = data.split('px ');\n                self._boxShadow = {\n                    x: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[0], 10),\n                    y: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[1], 10),\n                    blur: self._boxShadow === 'none' ? 0 : parseInt(boxShadow[2], 10),\n                    color: self._boxShadow === 'none' ? '' : boxShadow[3],\n                };\n\n                // take into account the shadow and its direction\n                if (self._boxShadow.x < 0) {\n                    self.shadowL = Math.abs(self._boxShadow.x) + self._boxShadow.blur;\n                    self.shadowR = self._boxShadow.blur + self._boxShadow.x;\n                } else {\n                    self.shadowL = Math.abs(self._boxShadow.blur - self._boxShadow.x);\n                    self.shadowR = self._boxShadow.blur + self._boxShadow.x;\n                }\n                if (self._boxShadow.y < 0) {\n                    self.shadowT = Math.abs(self._boxShadow.y) + self._boxShadow.blur;\n                    self.shadowB = self._boxShadow.blur + self._boxShadow.y;\n                } else {\n                    self.shadowT = Math.abs(self._boxShadow.blur - self._boxShadow.y);\n                    self.shadowB = self._boxShadow.blur + self._boxShadow.y;\n                }\n\n                self.shadowW = self.shadowL + self.shadowR;\n                self.shadowH = self.shadowT + self.shadowB;\n\n                self._calcWH();\n\n                if (!doReturn) {\n                    self._updateCanvasWH();\n\n                    return self.render();\n                }\n            } else {\n                return self._boxShadow;\n            }\n        },\n\n        /**\n         * Get/set the inner shadow.\n         * @param  {String} data In the format of a CSS box shadow (1px 1px 1px rgba(0, 0, 0.5)).\n         * @return {Mixed}          CanvasInput or current inner shadow.\n         */\n        innerShadow(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._innerShadow = data;\n\n                return self.render();\n            } else {\n                return self._innerShadow;\n            }\n        },\n\n        /**\n         * Get/set the text selection color.\n         * @param  {String} data Color.\n         * @return {Mixed}      CanvasInput or current selection color.\n         */\n        selectionColor(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._selectionColor = data;\n\n                return self.render();\n            } else {\n                return self._selectionColor;\n            }\n        },\n\n        /**\n         * Get/set the place holder text.\n         * @param  {String} data Place holder text.\n         * @return {Mixed}      CanvasInput or current place holder text.\n         */\n        placeHolder(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._placeHolder = data;\n\n                return self.render();\n            } else {\n                return self._placeHolder;\n            }\n        },\n\n        /**\n         * Get/set the current text box value.\n         * @param  {String} data Text value.\n         * @return {Mixed}      CanvasInput or current text value.\n         */\n        value(data) {\n            const self = this;\n\n            if (typeof data !== 'undefined') {\n                self._value = `${data}`;\n                self._hiddenInput.value = `${data}`;\n\n                // update the cursor position\n                self._cursorPos = self._clipText().length;\n\n                self.render();\n\n                return self;\n            } else {\n                return self._value === self._placeHolder ? '' : self._value;\n            }\n        },\n\n        /**\n         * Set or fire the onsubmit event.\n         * @param  {Function} fn Custom callback.\n         */\n        onsubmit(fn) {\n            const self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onsubmit = fn;\n\n                return self;\n            } else {\n                self._onsubmit();\n            }\n        },\n\n        /**\n         * Set or fire the onkeydown event.\n         * @param  {Function} fn Custom callback.\n         */\n        onkeydown(fn) {\n            const self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onkeydown = fn;\n\n                return self;\n            } else {\n                self._onkeydown();\n            }\n        },\n\n        /**\n         * Set or fire the onkeyup event.\n         * @param  {Function} fn Custom callback.\n         */\n        onkeyup(fn) {\n            const self = this;\n\n            if (typeof fn !== 'undefined') {\n                self._onkeyup = fn;\n\n                return self;\n            } else {\n                self._onkeyup();\n            }\n        },\n\n        /**\n         * Place focus on the CanvasInput box, placing the cursor\n         * either at the end of the text or where the user clicked.\n         * @param  {Number} pos (optional) The position to place the cursor.\n         * @return {CanvasInput}\n         */\n        focus(pos) {\n            const self = this;\n            let input;\n\n            // if this is readonly, don't allow it to get focus\n            if (self._readonly) {\n                return;\n            }\n\n            // only fire the focus event when going from unfocussed\n            if (!self._hasFocus) {\n                self._onfocus(self);\n\n                // remove focus from all other inputs\n                for (let i = 0; i < inputs.length; i++) {\n                    if (inputs[i]._hasFocus) {\n                        inputs[i].blur();\n                    }\n                }\n            }\n\n            // remove selection\n            if (!self._selectionUpdated) {\n                self._selection = [0, 0];\n            } else {\n                delete self._selectionUpdated;\n            }\n\n            // update the cursor position\n            self._cursorPos = typeof pos === 'number' ? pos : self._clipText().length;\n\n            // clear the place holder\n            if (self._placeHolder === self._value) {\n                self._value = '';\n                self._hiddenInput.value = '';\n            }\n\n            self._hasFocus = true;\n            self._cursor = true;\n\n            // setup cursor interval\n            if (self._cursorInterval) {\n                clearInterval(self._cursorInterval);\n            }\n\n            requestAnimationFrame(() => {\n                self._cursorInterval = setInterval(() => {\n                    self._cursor = !self._cursor;\n                    self.render();\n                }, 500);\n            });\n\n            // check if this is Chrome for Android (there is a bug with returning incorrect character key codes)\n            const nav = navigator.userAgent.toLowerCase();\n            const isChromeMobile =\n                nav.indexOf('chrome') >= 0 &&\n                nav.indexOf('mobile') >= 0 &&\n                nav.indexOf('android') >= 0;\n\n            // add support for mobile\n            const isMobile = typeof window.orientation !== 'undefined';\n            var hasHiddenFocus = false;\n            if (\n                isMobile &&\n                !isChromeMobile &&\n                document &&\n                document.createElement &&\n                (input = document.createElement('input'))\n            ) {\n                input.type = 'text';\n                input.style.opacity = 0;\n                input.style.position = 'absolute';\n                input.style.left = `${self._x +\n                    self._extraX +\n                    (self._canvas ? self._canvas.offsetLeft : 0)}px`;\n                input.style.top = `${self._y +\n                    self._extraY +\n                    (self._canvas ? self._canvas.offsetTop : 0)}px`;\n                input.style.width = self._width;\n                input.style.height = 0;\n                const form = document.createElement('form');\n                form.appendChild(input);\n                document.body.appendChild(form);\n                input.focus();\n                input.addEventListener(\n                    'blur',\n                    () => {\n                        if (!hasHiddenFocus) {\n                            self.blur(self);\n                        }\n                    },\n                    false\n                );\n                input.addEventListener(\n                    'focus',\n                    () => {\n                        self.focus();\n                    },\n                    false\n                );\n            } else if (isMobile) {\n                self.value(prompt(self._placeHolder) || '');\n            }\n\n            // move the real focus to the hidden input\n            const hasSelection = self._selection[0] > 0 || self._selection[1] > 0;\n            hasHiddenFocus = true;\n            self._hiddenInput.focus();\n            hasHiddenFocus = false;\n            self._hiddenInput.selectionStart = hasSelection ? self._selection[0] : self._cursorPos;\n            self._hiddenInput.selectionEnd = hasSelection ? self._selection[1] : self._cursorPos;\n\n            return self.render();\n        },\n\n        /**\n         * Removes focus from the CanvasInput box.\n         * @param  {Object} _this Reference to this.\n         * @return {CanvasInput}\n         */\n        blur(_this) {\n            const self = _this || this;\n\n            self._onblur(self);\n\n            if (self._cursorInterval) {\n                clearInterval(self._cursorInterval);\n            }\n            self._hasFocus = false;\n            self._cursor = false;\n            self._selection = [0, 0];\n            self._hiddenInput.blur();\n\n            // fill the place holder\n            if (self._value === '') {\n                self._value = self._placeHolder;\n            }\n\n            if (self._isHidden) {\n                return;\n            }\n            return self.render();\n        },\n\n        /**\n         * Fired with the keydown event to draw the typed characters.\n         * @param  {Event}       e    The keydown event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        keydown(e, self) {\n            const keyCode = e.which;\n            const isShift = e.shiftKey;\n            const key = null;\n            let startText;\n            let endText;\n\n            // make sure the correct text field is being updated\n            if (!self._hasFocus) {\n                return;\n            }\n\n            // fire custom user event\n            self._onkeydown(e, self);\n\n            // add support for Ctrl/Cmd+A selection\n            if (keyCode === 65 && (e.ctrlKey || e.metaKey)) {\n                self._selection = [0, self._value.length];\n                self._hiddenInput.selectionStart = 0;\n                self._hiddenInput.selectionEnd = self._value.length;\n                e.preventDefault();\n                return self.render();\n            }\n\n            // block keys that shouldn't be processed\n            if (keyCode === 17 || e.metaKey || e.ctrlKey) {\n                return self;\n            }\n\n            if (keyCode === 13) {\n                // enter key\n                e.preventDefault();\n                self._onsubmit(e, self);\n                //Entry.dispatchEvent('canvasInputComplete');\n            } else if (keyCode === 9) {\n                // tab key\n                e.preventDefault();\n                if (inputs.length > 1) {\n                    const next = inputs[self._inputsIndex + 1] ? self._inputsIndex + 1 : 0;\n                    self.blur();\n                    setTimeout(() => {\n                        inputs[next].focus();\n                    }, 5);\n                }\n            }\n\n            // update the canvas input state information from the hidden input\n            self._value = self._hiddenInput.value;\n            self._cursorPos = self._hiddenInput.selectionStart;\n            self._selection = [0, 0];\n\n            if (!self._isHidden) {\n                return self.render();\n            }\n        },\n\n        /**\n         * Fired with the click event on the canvas, and puts focus on/off\n         * based on where the user clicks.\n         * @param  {Event}       e    The click event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        click(e, self) {\n            //var mouse = self._mousePos(e),\n            //x = mouse.x,\n            //y = mouse.y;\n\n            if (this._isFirstClick) {\n                delete this._isFirstClick;\n                return;\n            }\n            const roundRect = Entry.stage.canvas.canvas.getBoundingClientRect();\n            const x = ((e.x - roundRect.left) / roundRect.width - 0.5) * 480;\n            const y = ((e.y - roundRect.top) / roundRect.height - 0.5) * -270;\n\n            if (self._endSelection) {\n                delete self._endSelection;\n                delete self._selectionUpdated;\n                return;\n            }\n\n            if ((self._canvas && self._overInput(x, y)) || !self._canvas) {\n                if (self._isHidden) {\n                    return;\n                }\n                if (self._mouseDown) {\n                    self._mouseDown = false;\n                    self.click(e, self);\n                    return self.focus(self._clickPos(x, y));\n                }\n            } else {\n                return self.blur();\n            }\n        },\n\n        /**\n         * Fired with the mousemove event to update the default cursor.\n         * @param  {Event}       e    The mousemove event.\n         * @param  {CanvasInput} self\n         * @return {CanvasInput}\n         */\n        mousemove(e, self) {\n            const mouse = self._mousePos(e);\n            const x = mouse.x;\n            const y = mouse.y;\n            const isOver = self._overInput(x, y);\n\n            if (isOver && self._canvas) {\n                self._canvas.style.cursor = 'text';\n                self._wasOver = true;\n            } else if (self._wasOver && self._canvas) {\n                self._canvas.style.cursor = 'default';\n                self._wasOver = false;\n            }\n\n            if (self._hasFocus && self._selectionStart >= 0) {\n                const curPos = self._clickPos(x, y);\n                const start = Math.min(self._selectionStart, curPos);\n                const end = Math.max(self._selectionStart, curPos);\n\n                if (!isOver) {\n                    self._selectionUpdated = true;\n                    self._endSelection = true;\n                    delete self._selectionStart;\n                    self.render();\n                    return;\n                }\n\n                if (self._selection[0] !== start || self._selection[1] !== end) {\n                    self._selection = [start, end];\n                    self.render();\n                }\n            }\n        },\n\n        /**\n         * Fired with the mousedown event to start a selection drag.\n         * @param  {Event} e    The mousedown event.\n         * @param  {CanvasInput} self\n         */\n        mousedown(e, self) {\n            e = Entry.Utils.convertMouseEvent(e);\n            const roundRect = Entry.stage.getBoundRect();\n            const offsetX = e.offsetX || e.clientX - roundRect.left;\n            const offsetY = e.offsetY || e.clientY - roundRect.top;\n            const x = (offsetX / roundRect.width - 0.5) * 480;\n            const y = (offsetY / roundRect.height - 0.5) * -270;\n            const isOver = self._overInput(x, y);\n\n            // setup the 'click' event\n            self._mouseDown = isOver;\n\n            const inputField = Entry.stage.inputField;\n            if (isOver && !inputField._isHidden) {\n                self._hasFocus = true;\n                setTimeout(() => {\n                    inputField.focus();\n                }, 1);\n            } else if (!isOver && inputField) {\n                self._hasFocus = false;\n                inputField.blur();\n            }\n\n            // start the selection drag if inside the input\n            if (self._hasFocus && isOver) {\n                self._selectionStart = self._clickPos(x, y);\n            }\n        },\n\n        /**\n         * Fired with the mouseup event to end a selection drag.\n         * @param  {Event} e    The mouseup event.\n         * @param  {CanvasInput} self\n         */\n        mouseup(e, self) {\n            //var mouse = self._mousePos(e),\n            //x = mouse.x,\n            //y = mouse.y;\n            //// update selection if a drag has happened\n            //var isSelection = self._clickPos(x, y) !== self._selectionStart;\n            //if (self._hasFocus && self._selectionStart >= 0 && self._overInput(x, y) && isSelection) {\n            //self._selectionUpdated = true;\n            //delete self._selectionStart;\n            //self.render();\n            //} else {\n            //delete self._selectionStart;\n            //}\n            //self.click(e, self);\n            // if (self._isHidden)\n            //     return;\n            // self.render();\n            // self.click(e,self);\n            // var roundRect = Entry.stage.canvas.canvas.getBoundingClientRect();\n            // var x = ((e.clientX - roundRect.left) / roundRect.width - 0.5) * 480;\n            // var y = ((e.clientY - roundRect.top) / roundRect.height - 0.5) * -270;\n        },\n\n        /**\n         * Helper method to get the off-DOM canvas.\n         * @return {Object} Reference to the canvas.\n         */\n        renderCanvas() {\n            return this._renderCanvas;\n        },\n\n        show() {\n            const self = this;\n            self._isHidden = false;\n            self._isFirstClick = true;\n\n            self.value('');\n            self.focus();\n        },\n\n        hide() {\n            const self = this;\n\n            self._isHidden = true;\n            self.blur();\n        },\n\n        setPosition(x, y) {\n            const self = this;\n            self._isHidden = false;\n            self._isFirstClick = true;\n\n            self._x = x || 0;\n            self._y = y || 0;\n\n            self.value('');\n            self.focus();\n        },\n\n        /**\n         * Clears and redraws the CanvasInput on an off-DOM canvas,\n         * and if a main canvas is provided, draws it all onto that.\n         * @return {CanvasInput}\n         */\n        render() {\n            const self = this;\n            const ctx = self._renderCtx;\n            const w = self.outerW;\n            const h = self.outerH;\n            const br = self._borderRadius;\n            const bw = self._borderWidth;\n            const sw = self.shadowW;\n            const sh = self.shadowH;\n\n            // clear the canvas\n            ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n\n            // setup the box shadow\n            ctx.shadowOffsetX = self._boxShadow.x;\n            ctx.shadowOffsetY = self._boxShadow.y;\n            ctx.shadowBlur = self._boxShadow.blur;\n            ctx.shadowColor = self._boxShadow.color;\n\n            // draw the border\n            if (self._borderWidth > 0) {\n                ctx.fillStyle = self._borderColor;\n                // self._roundedRect(ctx, self.shadowL, self.shadowT, w - sw, h - sh, br);\n                self._roundedRect(ctx, self.shadowL, self.shadowT, w - sw, h - sh, br);\n                ctx.fill();\n\n                ctx.shadowOffsetX = 0;\n                ctx.shadowOffsetY = 0;\n                ctx.shadowBlur = 0;\n            }\n\n            // draw the text box background\n            self._drawTextBox(() => {\n                // make sure all shadows are reset\n                ctx.shadowOffsetX = 0;\n                ctx.shadowOffsetY = 0;\n                ctx.shadowBlur = 0;\n\n                // clip the text so that it fits within the box\n                let text = self._clipText();\n\n                // draw the selection\n                const paddingBorder = self._padding + self._borderWidth + self.shadowT;\n                if (self._selection[1] > 0) {\n                    const selectOffset = self._textWidth(text.substring(0, self._selection[0]));\n                    const selectWidth = self._textWidth(\n                        text.substring(self._selection[0], self._selection[1])\n                    );\n\n                    ctx.fillStyle = self._selectionColor;\n                    ctx.fillRect(\n                        paddingBorder + selectOffset,\n                        paddingBorder,\n                        selectWidth,\n                        self._height\n                    );\n                }\n\n                // draw the cursor\n                if (self._cursor) {\n                    const cursorOffset = self._textWidth(text.substring(0, self._cursorPos));\n                    ctx.fillStyle = self._fontColor;\n                    ctx.fillRect(paddingBorder + cursorOffset, paddingBorder, 1, self._height);\n                }\n\n                // draw the text\n                const textX = self._padding + self._borderWidth + self.shadowL;\n                const textY = Math.round(paddingBorder + self._height / 2);\n\n                // only remove the placeholder text if they have typed something\n                text = text === '' && self._placeHolder ? self._placeHolder : text;\n\n                ctx.fillStyle =\n                    self._value !== '' && self._value !== self._placeHolder\n                        ? self._fontColor\n                        : self._placeHolderColor;\n                ctx.font = `${self._fontStyle} ${self._fontWeight} ${self._fontSize}px ${self._fontFamily}`;\n                ctx.textAlign = 'left';\n                ctx.textBaseline = 'middle';\n                ctx.fillText(text, textX, textY);\n\n                // parse inner shadow\n                const innerShadow = self._innerShadow.split('px ');\n                const isOffsetX = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[0], 10);\n                const isOffsetY = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[1], 10);\n                const isBlur = self._innerShadow === 'none' ? 0 : parseInt(innerShadow[2], 10);\n                const isColor = self._innerShadow === 'none' ? '' : innerShadow[3];\n\n                // draw the inner-shadow (damn you canvas, this should be easier than this...)\n                if (isBlur > 0) {\n                    const shadowCtx = self._shadowCtx;\n                    const scw = shadowCtx.canvas.width;\n                    const sch = shadowCtx.canvas.height;\n\n                    shadowCtx.clearRect(0, 0, scw, sch);\n                    shadowCtx.shadowBlur = isBlur;\n                    shadowCtx.shadowColor = isColor;\n\n                    // top shadow\n                    shadowCtx.shadowOffsetX = 0;\n                    shadowCtx.shadowOffsetY = isOffsetY;\n                    shadowCtx.fillRect(-1 * w, -100, 3 * w, 100);\n\n                    // right shadow\n                    shadowCtx.shadowOffsetX = isOffsetX;\n                    shadowCtx.shadowOffsetY = 0;\n                    shadowCtx.fillRect(scw, -1 * h, 100, 3 * h);\n\n                    // bottom shadow\n                    shadowCtx.shadowOffsetX = 0;\n                    shadowCtx.shadowOffsetY = isOffsetY;\n                    shadowCtx.fillRect(-1 * w, sch, 3 * w, 100);\n\n                    // left shadow\n                    shadowCtx.shadowOffsetX = isOffsetX;\n                    shadowCtx.shadowOffsetY = 0;\n                    shadowCtx.fillRect(-100, -1 * h, 100, 3 * h);\n\n                    // create a clipping mask on the main canvas\n                    self._roundedRect(\n                        ctx,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        w - bw * 2 - sw,\n                        h - bw * 2 - sh,\n                        br\n                    );\n                    ctx.clip();\n\n                    // draw the inner-shadow from the off-DOM canvas\n                    ctx.drawImage(\n                        self._shadowCanvas,\n                        0,\n                        0,\n                        scw,\n                        sch,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        scw,\n                        sch\n                    );\n                }\n\n                // draw to the visible canvas\n                // if (self._ctx) {\n                //     // self._ctx.clearRect(self._x, self._y, ctx.canvas.width, ctx.canvas.height);\n                //     self._ctx.drawImage(self._renderCanvas, self._x, self._y);\n                // }\n                self._pixiView.texture.update();\n                Entry.requestUpdate = true;\n                return self;\n            });\n        },\n\n        /**\n         * Draw the text box area with either an image or background color.\n         * @param  {Function} fn Callback.\n         */\n        _drawTextBox(fn) {\n            const self = this;\n            const ctx = self._renderCtx;\n            const w = self.outerW;\n            const h = self.outerH;\n            const br = self._borderRadius;\n            const bw = self._borderWidth;\n            const sw = self.shadowW;\n            const sh = self.shadowH;\n\n            // only draw the background shape if no image is being used\n            if (self._backgroundImage === '') {\n                ctx.fillStyle = self._backgroundColor;\n                self._roundedRect(\n                    ctx,\n                    bw + self.shadowL,\n                    bw + self.shadowT,\n                    w - bw * 2 - sw,\n                    h - bw * 2 - sh,\n                    br\n                );\n                ctx.fill();\n\n                fn();\n            } else {\n                const img = new Image();\n                img.src = self._backgroundImage;\n                img.onload = function() {\n                    ctx.drawImage(\n                        img,\n                        0,\n                        0,\n                        img.width,\n                        img.height,\n                        bw + self.shadowL,\n                        bw + self.shadowT,\n                        w,\n                        h\n                    );\n\n                    fn();\n                };\n            }\n        },\n\n        /**\n         * Deletes selected text in selection range and repositions cursor.\n         * @return {Boolean} true if text removed.\n         */\n        _clearSelection() {\n            const self = this;\n\n            if (self._selection[1] > 0) {\n                // clear the selected contents\n                const start = self._selection[0];\n                const end = self._selection[1];\n\n                self._value = self._value.substr(0, start) + self._value.substr(end);\n                self._cursorPos = start;\n                self._cursorPos = self._cursorPos < 0 ? 0 : self._cursorPos;\n                self._selection = [0, 0];\n\n                return true;\n            }\n\n            return false;\n        },\n\n        /**\n         * Clip the text string to only return what fits in the visible text box.\n         * @param  {String} value The text to clip.\n         * @return {String} The clipped text.\n         */\n        _clipText(value) {\n            const self = this;\n            value = typeof value === 'undefined' ? self._value : value;\n\n            const textWidth = self._textWidth(value);\n            const fillPer = textWidth / (self._width - self._padding);\n            const text =\n                fillPer > 1 ? value.substr(-1 * Math.floor(value.length / fillPer)) : value;\n\n            return `${text}`;\n        },\n\n        /**\n         * Gets the pixel with of passed text.\n         * @param  {String} text The text to measure.\n         * @return {Number}      The measured width.\n         */\n        _textWidth(text) {\n            const self = this;\n            const ctx = self._renderCtx;\n\n            ctx.font = `${self._fontStyle} ${self._fontWeight} ${self._fontSize}px ${self._fontFamily}`;\n            ctx.textAlign = 'left';\n\n            return ctx.measureText(text).width;\n        },\n\n        /**\n         * Recalculate the outer with and height of the text box.\n         */\n        _calcWH() {\n            const self = this;\n\n            // calculate the full width and height with padding, borders and shadows\n            self.outerW = self._width + self._padding * 2 + self._borderWidth * 2 + self.shadowW;\n            self.outerH = self._height + self._padding * 2 + self._borderWidth * 2 + self.shadowH;\n        },\n\n        /**\n         * Update the width and height of the off-DOM canvas when attributes are changed.\n         */\n        _updateCanvasWH() {\n            const self = this;\n            const oldW = self._renderCanvas.width;\n            const oldH = self._renderCanvas.height;\n\n            // update off-DOM canvas\n            self._renderCanvas.setAttribute('width', self.outerW);\n            self._renderCanvas.setAttribute('height', self.outerH);\n            self._shadowCanvas.setAttribute('width', self._width + self._padding * 2);\n            self._shadowCanvas.setAttribute('height', self._height + self._padding * 2);\n\n            // clear the main canvas\n            //do nothing. entryjs will control main canvas.\n            // if (self._ctx) {\n            //     self._ctx.clearRect(self._x, self._y, oldW, oldH);\n            // }\n        },\n\n        /**\n         * Creates the path for a rectangle with rounded corners.\n         * Must call ctx.fill() after calling this to draw the rectangle.\n         * @param  {Object} ctx Canvas context.\n         * @param  {Number} x   x-coordinate to draw from.\n         * @param  {Number} y   y-coordinate to draw from.\n         * @param  {Number} w   Width of rectangle.\n         * @param  {Number} h   Height of rectangle.\n         * @param  {Number} r   Border radius.\n         */\n        _roundedRect(ctx, x, y, w, h, r) {\n            if (w < 2 * r) {\n                r = w / 2;\n            }\n            if (h < 2 * r) {\n                r = h / 2;\n            }\n\n            ctx.beginPath();\n\n            ctx.moveTo(x + r, y);\n            ctx.lineTo(x + w - r, y);\n            ctx.quadraticCurveTo(x + w, y, x + w, y + r);\n            ctx.lineTo(x + w, y + h - r);\n            ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);\n            ctx.lineTo(x + r, y + h);\n            ctx.quadraticCurveTo(x, y + h, x, y + h - r);\n            ctx.lineTo(x, y + r);\n            ctx.quadraticCurveTo(x, y, x + r, y);\n\n            ctx.closePath();\n        },\n\n        /**\n         * Checks if a coordinate point is over the input box.\n         * @param  {Number} x x-coordinate position.\n         * @param  {Number} y y-coordinate position.\n         * @return {Boolean}   True if it is over the input box.\n         */\n        _overInput(x, y) {\n            return x >= -226 && x <= 183 && y >= -110 && y <= -73;\n        },\n\n        /**\n         * Use the mouse's x & y coordinates to determine\n         * the position clicked in the text.\n         * @param  {Number} x X-coordinate.\n         * @param  {Number} y Y-coordinate.\n         * @return {Number}   Cursor position.\n         */\n        _clickPos(x, y) {\n            const self = this;\n            let value = self._value;\n\n            // don't count placeholder text in this\n            if (self._value === self._placeHolder) {\n                value = '';\n            }\n\n            // determine where the click was made along the string\n            const text = self._clipText(value);\n            let totalW = 0;\n            let pos = text.length;\n\n            if (x - (self._x + self._extraX) < self._textWidth(text)) {\n                // loop through each character to identify the position\n                for (let i = 0; i < text.length; i++) {\n                    totalW += self._textWidth(text[i]);\n                    if (totalW >= x - (self._x + self._extraX)) {\n                        pos = i;\n                        break;\n                    }\n                }\n            }\n\n            return pos;\n        },\n\n        /**\n         * Calculate the mouse position based on the event callback and the elements on the page.\n         * @param  {Event} e\n         * @return {Object}   x & y values\n         */\n        _mousePos(e) {\n            let elm = e.target;\n            const style = document.defaultView.getComputedStyle(elm, undefined);\n            const paddingLeft = parseInt(style.paddingLeft, 10) || 0;\n            const paddingTop = parseInt(style.paddingLeft, 10) || 0;\n            const borderLeft = parseInt(style.borderLeftWidth, 10) || 0;\n            const borderTop = parseInt(style.borderLeftWidth, 10) || 0;\n            const htmlTop = document.body.parentNode.offsetTop || 0;\n            const htmlLeft = document.body.parentNode.offsetLeft || 0;\n            let offsetX = 0;\n            let offsetY = 0;\n            let x;\n            let y;\n\n            // calculate the total offset\n            if (typeof elm.offsetParent !== 'undefined') {\n                do {\n                    offsetX += elm.offsetLeft;\n                    offsetY += elm.offsetTop;\n                } while ((elm = elm.offsetParent));\n            }\n\n            // take into account borders and padding\n            offsetX += paddingLeft + borderLeft + htmlLeft;\n            offsetY += paddingTop + borderTop + htmlTop;\n\n            return {\n                x: e.pageX - offsetX,\n                y: e.pageY - offsetY,\n            };\n        },\n        hasFocus() {\n            return this._hasFocus;\n        },\n    };\n})();\n"
  },
  {
    "path": "src/class/pixi/etc/PIXIPaintAdaptor.ts",
    "content": "import { DisplayObject } from 'pixi.js';\nimport { PIXIGraphics } from '../helper/PIXIHelper';\n\ninterface IRBG {\n    r: number;\n    g: number;\n    b: number;\n}\n\n/**\n * createjs.Graphics 스타일의 lagacy 메서드 호출을 pixi.Graphics 로 변경해주는 adaptor 클라스.\n */\nexport class PIXIPaintAdaptor {\n    //아래 값들은 다른 클래스에서 값을 할당해줌.\n    public rgb: IRBG;\n    public thickness: number;\n    public opacity: number;\n    /** [박봉배] 추측 - drawing 중인지 아닌지를 저장하는 값으로 생각 됨. */\n    public stop: boolean;\n\n    /** [박봉배] 추측 - 이 브러시가 따라다녀야 할 대상 */\n    public entity: DisplayObject;\n\n    //아래 값들은 내부에서만 사용함.\n    private _alpha: number = 1;\n    private _thickness: number;\n    private _color: number;\n\n    private _shape: PIXIGraphics;\n\n    private currentPath: PIXI.Polygon;\n\n    endFill() {\n        // #10141 때문에 closePath 사용안함.\n        if (!this._shape || this._shape.destroyed) {\n            return;\n        }\n        this.currentPath = null;\n        this._shape.closePath();\n    }\n\n    beginFill(color: string) {\n        this._parseRGBCssStyleColor(color);\n        this._shape.beginFill(this._color, this._alpha);\n    }\n\n    beginFillFast(color: number, alpha: number) {\n        this._color = color;\n        this._alpha = alpha;\n        this._shape.beginFill(color, alpha);\n    }\n\n    moveTo(x: number, y: number) {\n        if (!this._shape || this._shape.destroyed) {\n            return;\n        }\n        this._shape.moveTo(Number(x), Number(y));\n        this.currentPath = this._shape.currentPath;\n    }\n\n    lineTo(x: number, y: number) {\n        if (!this._shape || this._shape.destroyed) {\n            return;\n        }\n        if (!this.currentPath) {\n            this._shape.moveTo(0, 0);\n            this.currentPath = this._shape.currentPath;\n        }\n        const points = this.currentPath.points;\n        const fromX = points[points.length - 2];\n        const fromY = points[points.length - 1];\n        if (fromX !== x || fromY !== y) {\n            points.push(Number(x), Number(y));\n        }\n        this._shape.currentPath = this.currentPath;\n        this._shape.lineTo(Number(x), Number(y)); // 박봉배: #9374 x,y 좌표가 문자로 넘어와서 생긴 이슈\n        this._shape.geometry.invalidate();\n    }\n\n    /** @param shape - drawing 을 할 대상을 지정 */\n    internalSetShape(shape: PIXIGraphics) {\n        this._shape = shape;\n        this._setStyle();\n    }\n\n    _setStyle() {\n        if (!this._shape || this._shape.destroyed) {\n            return;\n        }\n        this._shape.lineStyle(this._thickness, this._color, this._alpha);\n    }\n\n    _parseRGBCssStyleColor(colorOld: string) {\n        const color = colorOld.replace('/s/', '');\n        if (color[0] == '#') {\n            this._color = parseInt(color.replace('#', ''), 16);\n            return;\n        }\n\n        let result;\n\n        //rgb 보다 rgba 문자열을 더 많이 사용하는것 같아 이 조건문을 위로 올림\n        if ((result = /^rgba\\((\\d+),(\\d+),(\\d+),(\\d+(\\.?\\d*))\\)$/i.exec(color))) {\n            this._color = this._RGBToNumber(result);\n            this._alpha = Number(result[4]);\n            return;\n        }\n\n        if ((result = /^rgb\\((\\d+),(\\d+),(\\d+)\\)$/i.exec(color))) {\n            this._color = this._RGBToNumber(result);\n        }\n    }\n\n    _RGBToNumber(regexResult: any[]) {\n        const [x, r, g, b] = regexResult;\n        return (r << 16) + (g << 8) + Number(b);\n    }\n    // Matched the method name to createjs for fulfilling the purpose of wrapper class (#11626)\n    clear() {\n        const { x = 0, y = 0 } = this.entity || {};\n        this._shape.clear();\n        // Disconnect the previously continued path\n        this._shape.moveTo(x, -y);\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/etc/PIXITempStore.ts",
    "content": "/**\n * 임시로 사용할 변수의 포인터 저장용.\n */\nimport { Point, Rectangle, Matrix } from 'pixi.js';\n\nexport class PIXITempStore {\n    static point1: Point;\n    static point2: Point;\n    static rect1: Rectangle;\n    static rect2: Rectangle;\n    static matrix1: Matrix;\n    static matrix2: Matrix;\n\n    static init() {\n        this.point1 = new Point();\n        this.point2 = new Point();\n        this.rect1 = new Rectangle();\n        this.rect2 = new Rectangle();\n        this.matrix1 = new Matrix();\n        this.matrix2 = new Matrix();\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/handle/PIXIHandle.js",
    "content": "/**\n * Resize handle on PIXI.js\n */\n\n'use strict';\n\nimport { Container, Graphics } from 'pixi.js';\nimport { PIXIHandleEdge } from './PIXIHandleEdge';\nimport { PIXIDragHelper } from '../helper/PIXIDragHelper';\nimport { PIXIGlobal } from '../init/PIXIGlobal';\n\nexport class PIXIHandle {\n    constructor(canvas) {\n        this.canvas = canvas;\n        this._baseAsset = PIXIGlobal.baseAsset;\n        this.color = '#c1c7cd';\n        //this.color = \"#6BD5FF\";\n        this.arrowColor = '#E79040';\n        this.centerColor = '#93440F';\n        this.rotateKnobColor = '#6B6B6B';\n\n        this.x = 0;\n        this.y = 0;\n        this.rotation = 0;\n        this.direction = 0;\n        this.width = 100;\n        this.height = 100;\n        this.flipX = false;\n        this.flipY = false;\n        this.visible = false;\n        this.draggable = true;\n\n        this.centerEditable = true;\n        this.rotationEditable = true;\n        this.directionEditable = true;\n        this.resizeEnable = true;\n\n        this.onChangeFunction = null;\n        this.callerObject = null;\n\n        this.createHandle();\n        this.render();\n        this.selectedObject = null;\n    }\n\n    setChangeListener(object, func) {\n        this.onChangeFunction = func;\n        this.callerObject = object;\n        return this;\n    }\n\n    /**\n     * for undo and redo\n     */\n    setEditStartListener(object, func) {\n        this.onEditStartFunction = func;\n        this.editStartCallerObject = object;\n        return this;\n    }\n\n    setEditEndListener(object, func) {\n        this.onEditEndFunction = func;\n        this.editEndCallerObject = object;\n        return this;\n    }\n\n    toggleCenter(isEnable) {\n        this.centerEditable = isEnable;\n        this.centerPoint.visible = isEnable;\n    }\n\n    toggleRotation(isEnable) {\n        this.rotationEditable = isEnable;\n        this.rotateKnob.visible = isEnable;\n    }\n\n    toggleDirection(isEnable) {\n        this.directionEditable = isEnable;\n        this.directionArrow.visible = isEnable;\n    }\n\n    toggleResize(isEnable) {\n        this.resizeEditable = isEnable;\n        for (let i = 0; i < 8; i++) {\n            this.knobs[i].visible = isEnable;\n        }\n    }\n\n    toggleFont(isEnable) {\n        this.fontEditable = isEnable;\n        this.fontKnob.visible = isEnable;\n    }\n\n    setX(xPos) {\n        this.x = xPos;\n        this.container.x = xPos;\n        this.background.x = xPos;\n    }\n\n    setY(yPos) {\n        this.y = yPos;\n        this.container.y = yPos;\n        this.background.y = yPos;\n    }\n\n    setWidth(width) {\n        this.width = width;\n        this.background.width = width;\n    }\n\n    setHeight(height) {\n        this.height = height;\n        this.background.height = height;\n    }\n\n    setRegX(regX) {\n        this.regX = regX;\n        this.centerPoint.x = regX;\n    }\n\n    setRegY(regY) {\n        this.regY = regY;\n        this.centerPoint.y = regY;\n    }\n\n    setRotation(rotation) {\n        rotation = (rotation + 360) % 360;\n        this.rotation = rotation;\n        const rad = (rotation * Math.PI) / 180;\n        this.container.rotation = rad;\n        this.background.rotation = rad;\n        this.updateKnobCursor();\n    }\n\n    setDirection(direction) {\n        direction = (direction + 360) % 360;\n        this.direction = direction;\n        this.directionArrow.rotation = (direction * Math.PI) / 180;\n    }\n\n    setVisible(visible) {\n        this.visible = visible;\n        this.container.visible = visible;\n        this.background.visible = visible;\n    }\n\n    setFont(fontSize) {\n        this.font = fontSize;\n        this.fontKnob.y = fontSize - this.height / 2;\n    }\n\n    createHandle() {\n        const handle = this;\n        const BASE_ASSET = this._baseAsset;\n        const container = new Container();\n\n        //border\n        const border = new Graphics();\n        container.addChild(border);\n        this.border = border;\n\n        //edge\n        const edge = new PIXIHandleEdge(BASE_ASSET);\n        edge.interactive = true;\n        edge.cursor = 'move';\n        edge.on(PIXIDragHelper.DOWN, function(e) {\n            PIXIDragHelper.handleDrag(edge);\n            const offset = handle.getEventCoordinate(e);\n            offset.x -= handle.x;\n            offset.y -= handle.y;\n            this.offset = offset;\n            handle.dispatchEditStartEvent();\n        });\n        edge.on(PIXIDragHelper.MOVE, function(e) {\n            if (handle.getDraggable()) {\n                const pos = handle.getEventCoordinate(e);\n                pos.x -= this.offset.x;\n                pos.y -= this.offset.y;\n                handle.setX(pos.x);\n                handle.setY(pos.y);\n                handle.dispatchOnChangeEvent();\n            }\n        });\n        edge.on(PIXIDragHelper.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(edge);\n        this.edge = edge;\n\n        //rotate knob\n        const rotateKnob = BASE_ASSET.newSprite('handle/rotateKnob');\n        rotateKnob.anchor.set(0.5, 1);\n        rotateKnob.interactive = true;\n        rotateKnob.cursor = 'crosshair';\n        rotateKnob.on(PIXIDragHelper.DOWN, (e) => {\n            PIXIDragHelper.handleDrag(rotateKnob);\n            handle.dispatchEditStartEvent();\n        });\n        rotateKnob.on(PIXIDragHelper.MOVE, (e) => {\n            const pos = handle.getEventCoordinate(e);\n            pos.x -= handle.x;\n            pos.y -= handle.y;\n            const rotation = (-Math.atan2(pos.x, pos.y) / Math.PI) * 180 - 180;\n            handle.setRotation(rotation);\n            handle.dispatchOnChangeEvent();\n        });\n        rotateKnob.on(PIXIDragHelper.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(rotateKnob);\n        container.setChildIndex(rotateKnob, 1);\n        this.rotateKnob = rotateKnob;\n\n        const directionArrow = BASE_ASSET.newSprite('handle/arrow');\n        directionArrow.interactive = true;\n        directionArrow.pivot.set(9, 42);\n\n        directionArrow.on(PIXIDragHelper.DOWN, (e) => {\n            PIXIDragHelper.handleDrag(directionArrow);\n            handle.dispatchEditStartEvent();\n        });\n        directionArrow.on(PIXIDragHelper.MOVE, (e) => {\n            const pos = handle.getLocalCoordinate(handle.getEventCoordinate(e));\n            const rotation = (-Math.atan2(pos.x, pos.y) / Math.PI) * 180 - 180;\n            handle.setDirection(rotation);\n            handle.dispatchOnChangeEvent();\n        });\n        directionArrow.on(PIXIDragHelper.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(directionArrow);\n        container.setChildIndex(directionArrow, 0);\n        this.directionArrow = directionArrow;\n\n        const centerPoint = BASE_ASSET.newSprite('handle/centerPoint');\n        centerPoint.interactive = true;\n        centerPoint.anchor.set(0.5, 0.5);\n\n        centerPoint.on(PIXIDragHelper.DOWN, (e) => {\n            PIXIDragHelper.handleDrag(centerPoint);\n            handle.dispatchEditStartEvent();\n        });\n        centerPoint.on(PIXIDragHelper.MOVE, (e) => {\n            let pos = handle.getEventCoordinate(e);\n            pos = handle.getLocalCoordinate(pos);\n            handle.setRegX(pos.x);\n            handle.setRegY(pos.y);\n            handle.dispatchOnChangeEvent();\n        });\n        centerPoint.on(PIXIDragHelper.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(centerPoint);\n        this.centerPoint = centerPoint;\n\n        //resize knobs\n        this.knobs = [];\n        for (let i = 0; i < 8; i++) {\n            const knob = BASE_ASSET.newSprite('handle/knob');\n            knob.pivot.set(4, 4);\n            knob.interactive = true;\n            knob.knobIndex = i;\n            knob.on(PIXIDragHelper.DOWN, function(e) {\n                const targetKnob = e.currentTarget;\n                PIXIDragHelper.handleDrag(targetKnob);\n                const otherKnobIndex =\n                    this.knobIndex + 4 > 7 ? this.knobIndex + 4 - 8 : this.knobIndex + 4;\n                const otherKnob = handle.knobs[otherKnobIndex];\n                const otherKnobPos = handle.getGlobalCoordinate(otherKnob);\n                this.otherKnobPos = otherKnobPos;\n                handle.dispatchEditStartEvent();\n            });\n            knob.on(PIXIDragHelper.MOVE, function(e) {\n                const pos = handle.getEventCoordinate(e);\n                if (handle.checkCenterPointState(handle.regX, handle.regY)) {\n                    handle.setRegX(0);\n                    handle.setRegY(0);\n                    handle.dispatchOnChangeEvent();\n                }\n                handle.adjust(this.knobIndex, this.otherKnobPos, pos);\n            });\n            knob.on(PIXIDragHelper.UP, (e) => {\n                handle.dispatchEditEndEvent();\n            });\n            container.addChild(knob);\n            this.knobs.push(knob);\n        }\n\n        const background = BASE_ASSET.newSprite('handle/bg');\n        background.interactive = true;\n        background.anchor.set(0.5, 0.5);\n\n        background.on(PIXIDragHelper.DOWN, function(e) {\n            PIXIDragHelper.handleDrag(background);\n            const offset = handle.getEventCoordinate(e);\n            offset.x -= handle.x;\n            offset.y -= handle.y;\n            this.offset = offset;\n            handle.dispatchEditStartEvent();\n        });\n        background.on(PIXIDragHelper.MOVE, function(e) {\n            if (handle.getDraggable()) {\n                const pos = handle.getEventCoordinate(e);\n                pos.x -= this.offset.x;\n                pos.y -= this.offset.y;\n                handle.setX(pos.x);\n                handle.setY(pos.y);\n                handle.dispatchOnChangeEvent();\n            }\n        });\n        background.on(PIXIDragHelper.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        this.canvas.addChildAt(background, 0);\n        this.background = background;\n\n        this.container = container;\n        this.canvas.addChild(this.container);\n    }\n\n    checkCenterPointState(x, y) {\n        const standard = 718;\n        const res = Math.sqrt(x * x + y * y);\n        if (res > standard && Entry.engine.isState('stop')) {\n            Entry.toast.warning(\n                Lang.Workspace.toast_error_title_object_center,\n                Lang.Workspace.toast_error_contents_object_center\n            );\n            return true;\n        }\n        return false;\n    }\n\n    render() {\n        this.renderBorder();\n        this.renderEdge();\n        this.renderRotateKnob();\n        this.renderKnobs();\n    }\n\n    renderEdge() {\n        this.edge.renderEdge(this.width, this.height);\n    }\n\n    renderRotateKnob() {\n        this.rotateKnob.y = -this.height / 2;\n    }\n\n    /**\n     * @deprecated 2018.09.19 박준배.\n     * graphics 에서 texture 로 변경하면서 border와 edge 를 합쳐버림.\n     * 그래서 보더가 필요 없음.\n     * 함수가 public naming 이라서 삭제를 못하겠음.\n     */\n    renderBorder() {}\n\n    renderKnobs() {\n        const width = this.width / 2;\n        const height = this.height / 2;\n        this.knobs.forEach((knob, i) => {\n            knob.x = Math.round(Math.sin((i / 4) * Math.PI)) * width;\n            knob.y = Math.round(Math.cos((i / 4) * Math.PI)) * height;\n        });\n    }\n\n    getEventCoordinate(e) {\n        const g = e.data.global;\n        return {\n            x: g.x * 0.75 - 240,\n            y: g.y * 0.75 - 135,\n        };\n    }\n\n    getGlobalCoordinate(childObject) {\n        const rotation = -this.container.rotation;\n        const cos = Math.cos(rotation);\n        const sin = Math.sin(rotation);\n        return {\n            x: this.x + childObject.x * cos + childObject.y * sin,\n            y: this.y + childObject.y * cos - childObject.x * sin,\n        };\n    }\n\n    getLocalCoordinate(pos) {\n        const rotation = this.container.rotation;\n        const cos = Math.cos(rotation);\n        const sin = Math.sin(rotation);\n        pos.x -= this.x;\n        pos.y -= this.y;\n        return {\n            x: pos.x * cos + pos.y * sin,\n            y: pos.y * cos - pos.x * sin,\n        };\n    }\n\n    adjust(knobIndex, otherKnobPos, pos) {\n        const newPoint = this.calcPos({ x: this.x, y: this.y }, otherKnobPos, pos);\n        const newCenter = {\n            x: (otherKnobPos.x + newPoint.x) / 2,\n            y: (otherKnobPos.y + newPoint.y) / 2,\n        };\n        const newLength = Math.sqrt(\n            Math.pow(newPoint.x - otherKnobPos.x, 2) + Math.pow(newPoint.y - otherKnobPos.y, 2)\n        );\n        if (knobIndex % 4 == 0) {\n            var ratio = newLength / this.height;\n            this.height = newLength;\n            this.setRegY(this.regY * ratio);\n        } else if (knobIndex % 4 == 2) {\n            var ratio = newLength / this.width;\n            this.width = newLength;\n            this.setRegX(this.regX * ratio);\n        } else {\n            const oldLength =\n                2 *\n                Math.sqrt(\n                    Math.pow(this.x - otherKnobPos.x, 2) + Math.pow(this.y - otherKnobPos.y, 2)\n                );\n            const newWidth = (this.width * newLength) / oldLength;\n            var ratio = newWidth / this.width;\n            this.setWidth(newWidth);\n            this.setRegX(this.regX * ratio);\n            const newHeight = (this.height * newLength) / oldLength;\n            ratio = newHeight / this.height;\n            this.setHeight((this.height * newLength) / oldLength);\n            this.setRegY(this.regY * ratio);\n        }\n        this.setX(newCenter.x);\n        this.setY(newCenter.y);\n\n        this.render();\n        this.dispatchOnChangeEvent();\n    }\n\n    updateKnobCursor() {\n        const rotation = this.rotation;\n        const cursorList = ['ns-resize', 'nwse-resize', 'ew-resize', 'nesw-resize'];\n        const iter = Math.round(rotation / 45);\n        for (var i = 0; i < iter; i++) {\n            cursorList.unshift(cursorList.pop());\n        }\n        for (var i = 0; i < 8; i++) {\n            this.knobs[i].cursor = cursorList[i % 4];\n        }\n    }\n\n    calcPos(pos1, pos2, targetPos) {\n        if (pos1.x == pos2.x) {\n            return {\n                x: pos1.x,\n                y: targetPos.y,\n            };\n        } else if (pos1.y == pos2.y) {\n            return {\n                x: targetPos.x,\n                y: pos1.y,\n            };\n        } else {\n            const a = pos1.y - pos2.y;\n            const b = pos2.x - pos1.x;\n            const c = pos1.x * pos2.y - pos2.x * pos1.y;\n            const k = -(a * targetPos.x + b * targetPos.y + c) / (a * a + b * b);\n            return {\n                x: targetPos.x + a * k,\n                y: targetPos.y + b * k,\n            };\n        }\n    }\n\n    dispatchOnChangeEvent() {\n        if (this.onChangeFunction) {\n            this.onChangeFunction.call(this.callerObject, this);\n        }\n    }\n\n    dispatchEditStartEvent() {\n        if (this.onEditStartFunction) {\n            this.onEditStartFunction.call(this.editStartCallerObject, this);\n        }\n    }\n\n    dispatchEditEndEvent() {\n        if (this.onEditEndFunction) {\n            this.onEditEndFunction.call(this.editEndCallerObject, this);\n        }\n    }\n\n    setDraggable(bool) {\n        this.draggable = bool;\n    }\n\n    getDraggable() {\n        return this.draggable;\n    }\n\n    destroy() {\n        this.onChangeFunction = null;\n        this.callerObject = null;\n        this.onEditStartFunction = null;\n        this.editStartCallerObject = null;\n        this.onEditEndFunction = null;\n        this.editEndCallerObject = null;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/handle/PIXIHandleEdge.js",
    "content": "import { Container } from 'pixi.js';\n\nexport class PIXIHandleEdge extends Container {\n    constructor(baseAsset) {\n        super();\n        const spriteFactory = () => {\n            const sp = baseAsset.newSprite('handle/border');\n            sp.pivot.set(0, 4);\n            this.addChild(sp);\n            return sp;\n        };\n        this._left = spriteFactory();\n        this._right = spriteFactory();\n        this._top = spriteFactory();\n        this._bottom = spriteFactory();\n    }\n\n    renderEdge(w, h) {\n        const hw = w / 2;\n        const hh = h / 2;\n\n        this._top.width = w;\n        this._top.position.set(-hw, -hh);\n\n        this._bottom.width = w;\n        this._bottom.position.set(-hw, hh);\n\n        this._left.width = h;\n        this._left.rotation = Math.PI / 2;\n        this._left.position.set(-hw, -hh);\n\n        this._right.width = h;\n        this._right.rotation = Math.PI / 2;\n        this._right.position.set(hw, -hh);\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/helper/PIXIDragHelper.js",
    "content": "/**\n * pixi 에는 createjs 의 pressmove 가 없어서 그것을 대신해주는 헬퍼 클라스.\n */\n\nexport class PIXIDragHelper {\n    /**\n     * @param {PIXI.DisplayObject} target\n     */\n    static handleDrag(target) {\n        const C = PIXIDragHelper;\n        const CE = this._convertEvent;\n\n        function _onMove(e) {\n            target.emit(C.MOVE, CE(e));\n        }\n\n        function _onUp(e) {\n            target.emit(C.UP, CE(e));\n            target.off('pointermove', _onMove);\n        }\n\n        function _onDown(e) {\n            target.emit(C.DOWN, CE(e));\n            target.on('pointermove', _onMove);\n        }\n\n        target.on('pointerdown', _onDown);\n        target.on('pointerup', _onUp);\n        target.on('pointerupoutside', _onUp);\n        target.on('pointercancel', _onUp);\n    }\n\n    static _convertEvent(e) {\n        const g = e.data.global;\n        return {\n            target: e.target,\n            currentTarget: e.currentTarget,\n            stageX: g.x,\n            stageY: g.y,\n            rawX: g.x,\n            rawY: g.y,\n        };\n    }\n}\n\nPIXIDragHelper.DOWN = '__pointerdown';\nPIXIDragHelper.MOVE = '__pointermove';\nPIXIDragHelper.UP = '__pointerup';\nPIXIDragHelper.OVER = 'pointerover';\n"
  },
  {
    "path": "src/class/pixi/helper/PIXIHelper.ts",
    "content": "import { Sprite, Container, Texture, Graphics } from 'pixi.js';\nimport { PIXISprite } from '../plugins/PIXISprite';\nimport { PIXITempStore } from '../etc/PIXITempStore';\nimport { PIXIText } from '../text/PIXIText';\n\nexport class PIXIGraphics extends Graphics {\n    destroyed: boolean = false;\n\n    destroy(options?: any) {\n        this.destroyed = true;\n        super.destroy(options);\n    }\n}\n\nexport default class PIXIHelper {\n    static sprite(debugName?: string, texture?: Texture): Sprite {\n        return new PIXISprite(texture);\n    }\n\n    static container(debugName?: string): Container {\n        return new Container();\n    }\n\n    static text(str: string, font: string, color: string, textBaseline: string, textAlign: string) {\n        // console.log(str, font);\n        const reg = /((\\d+)(pt|sp|px))?\\s*(.+)/gi;\n        const result: any[] = reg.exec(font) || [];\n        const fontName = result[4] || \"NanumGothic, 'Nanum Gothic'\";\n        const size = result[1] || '10pt';\n\n        const nColor = parseInt(color.replace('#', '0x')) || 0;\n        // var t = new PIXI.Text(str, {\n        const t = new PIXIText(str, {\n            fontFamily: fontName,\n            fontSize: size,\n            fill: nColor,\n            // textBaseline: textBaseline || 'alphabetic',\n            textBaseline: 'middle',\n            align: textAlign || 'left',\n            miterLimit: 2.5, //createjs default value,\n            padding: 5, //바운드를 삐져나오는 경우를 대비한 패딩\n        });\n        return t;\n    }\n\n    static getOffScreenCanvas(forceHTMLCanvas: boolean = false): HTMLCanvasElement {\n        forceHTMLCanvas = true;\n        const WIN: any = window;\n        if (!forceHTMLCanvas && 'OffscreenCanvas' in WIN) {\n            return new WIN.OffscreenCanvas(1, 1);\n        } else {\n            return document.createElement('canvas');\n        }\n    }\n\n    /**\n     * #ff00ff --> 0xff00ff\n     * @param strColor\n     */\n    static colorToUint(strColor: any) {\n        return strColor ? Number(strColor.replace('#', '0x')) : undefined;\n    }\n\n    static todo(msg: string) {}\n\n    static newPIXIGraphics() {\n        return new PIXIGraphics(false);\n    }\n\n    static randomRGBAString(alpha: number = 0.3): string {\n        const rr = this._rand255;\n        return `rgba(${rr()},${rr()},${rr()},${alpha})`;\n    }\n\n    private static _rand255(): number {\n        return Math.floor(Math.random() * 255);\n    }\n\n    /**\n     * createjs.DisplayObject#getTransformBound()\n     * @param {PIXI.DisplayObject} target\n     */\n    static getTransformBound(target: any) {\n        const bounds = target.getLocalBounds(PIXITempStore.rect1);\n\n        let x = bounds.x;\n        let y = bounds.y;\n        const width = bounds.width;\n        const height = bounds.height;\n        const mtx = PIXITempStore.matrix1;\n        target.localTransform.copyTo(mtx);\n\n        if (x || y) {\n            const mat2 = PIXITempStore.matrix2.identity().translate(-x, -y);\n            mtx.append(mat2);\n        }\n\n        const x_a = width * mtx.a;\n        const x_b = width * mtx.b;\n        const y_c = height * mtx.c;\n        const y_d = height * mtx.d;\n        const tx = mtx.tx;\n        const ty = mtx.ty;\n\n        let minX = tx;\n        let maxX = tx;\n        let minY = ty;\n        let maxY = ty;\n\n        if ((x = x_a + tx) < minX) {\n            minX = x;\n        } else if (x > maxX) {\n            maxX = x;\n        }\n        if ((x = x_a + y_c + tx) < minX) {\n            minX = x;\n        } else if (x > maxX) {\n            maxX = x;\n        }\n        if ((x = y_c + tx) < minX) {\n            minX = x;\n        } else if (x > maxX) {\n            maxX = x;\n        }\n\n        if ((y = x_b + ty) < minY) {\n            minY = y;\n        } else if (y > maxY) {\n            maxY = y;\n        }\n        if ((y = x_b + y_d + ty) < minY) {\n            minY = y;\n        } else if (y > maxY) {\n            maxY = y;\n        }\n        if ((y = y_d + ty) < minY) {\n            minY = y;\n        } else if (y > maxY) {\n            maxY = y;\n        }\n\n        bounds.x = minX;\n        bounds.y = minY;\n        bounds.width = maxX - minX;\n        bounds.height = maxY - minY;\n        return bounds;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/init/PIXIBaseAsset.ts",
    "content": "/**\n * 기본 텍스쳐 로드 되기 전에 객체를 생성 할 수 있도록 json은 함께 번들링함.\n */\nimport { Sprite, BaseTexture, Spritesheet, Texture } from 'pixi.js';\n\nclass PIXIBaseAssetSprite extends Sprite {\n    constructor(t?: any) {\n        super(t);\n    }\n}\n\n// var atlasJson = require(\"./../../../entry_texture/base_asset.json\");\nlet atlasJson: any;\n\nexport class PIXIBaseAsset {\n    private _sheet: Spritesheet;\n\n    constructor() {\n        const path = `${Entry.mediaFilePath}base_asset.png`;\n        const base = BaseTexture.from(path);\n        base.once('loaded', () => {\n            Entry.requestUpdate = true;\n        });\n        this._sheet = new Spritesheet(base, atlasJson);\n\n        //서브텍스쳐의 개수는 반드시 1000개보다 작아야 한다. 그렇지 않으면 parse 가 async 로 작동함.\n        //1000 이라는 숫자는 PIXI.Spritesheet.BATCH_SIZE getter 에 정의됨.\n        this._sheet.parse(() => {});\n    }\n\n    newSprite(key: string): Sprite {\n        // return new PIXI.Sprite(this._sheet.textures[key]);\n        return new PIXIBaseAssetSprite(this._sheet.textures[key]);\n    }\n\n    getTexture(key: string): Texture {\n        return this._sheet.textures[key];\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/init/PIXIFontLoadHandler.ts",
    "content": "/**\n * useWebGL 일때 font 로드가 끝나면 생성된 모든 text 오브젝트를 다시 draw 하도록 함.\n */\nimport { TextMetrics } from 'pixi.js';\n\nconst LOADED = 'fontLoaded';\n\nexport class PIXIFontLoadHandler {\n    private _items: any[] = [];\n    private _fontLoaded: boolean;\n\n    constructor() {\n        this._handleFontLoaded = this._handleFontLoaded.bind(this);\n        this._listen();\n    }\n\n    private _listen() {\n        if ((window as any).fontLoaded) {\n            this._fontLoaded = true;\n        } else {\n            Entry.addEventListener(LOADED, this._handleFontLoaded);\n        }\n    }\n\n    private _handleFontLoaded() {\n        this._fontLoaded = true;\n        Entry.removeEventListener(LOADED, this._handleFontLoaded);\n        TextMetrics.clearMetrics(null);\n        this._items.forEach((text: any) => {\n            //updateText() 는 private 함수이지만, override 했으므로, 호출하겠음.\n            text.updateText(false);\n        });\n        Entry.requestUpdate = true;\n        this._items = null;\n    }\n\n    /** @param {PIXIText} text */\n    manage(text: any) {\n        if (this._fontLoaded) {\n            return;\n        }\n        this._items.push(text);\n    }\n\n    /** @param {PIXIText} text */\n    unmanage(text: any) {\n        if (this._fontLoaded) {\n            return;\n        }\n        const arr = this._items;\n        const index = arr.indexOf(text);\n        if (index == -1) {\n            return;\n        }\n        arr.splice(index, 1);\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/init/PIXIGlobal.ts",
    "content": "import { Application, utils as PIXIUtils } from 'pixi.js';\nimport { PIXIBaseAsset } from './PIXIBaseAsset';\nimport { PIXICollision as ndgmr } from '../etc/PIXI-ndgmr.Collision';\nimport '../etc/PIXICanvasInput';\n\nimport { PIXIAtlasManager } from '../atlas/PIXIAtlasManager';\nimport { PIXIPixelPerfectInteractionPlugIn } from '../plugins/PIXIPixelPerfectInteractionPlugIn';\nimport { PIXITempStore } from '../etc/PIXITempStore';\nimport { PIXITextMetricsPlugIn } from '../plugins/PIXITextMetricsPlugIn';\nimport { PIXIShortPropPlugin } from '../plugins/PIXIShortPropPlugin';\nimport { PIXIGraphicOverride } from '../plugins/PIXIGraphicOverride';\nimport { PIXIFontLoadHandler } from './PIXIFontLoadHandler';\nimport { pixiGetChildAt } from '../plugins/pixiGetChildAt';\n\nclass _PIXIGlobal {\n    private _init: boolean;\n    /** @readonly */\n    baseAsset: PIXIBaseAsset;\n    atlasManager: PIXIAtlasManager;\n    fontLoadChecker: PIXIFontLoadHandler;\n\n    initOnce() {\n        if (this._init) {\n            return;\n        }\n        this._init = true;\n        this._isWebGLSupported();\n        this.fontLoadChecker = new PIXIFontLoadHandler();\n        //this.baseAsset = new PIXIBaseAsset();\n        ndgmr.initTempObject();\n        (window as any).ndgmr = ndgmr;\n        PIXITempStore.init();\n        this.atlasManager = new PIXIAtlasManager();\n        PIXIShortPropPlugin();\n        pixiGetChildAt();\n        PIXIPixelPerfectInteractionPlugIn();\n        PIXITextMetricsPlugIn();\n        PIXIGraphicOverride();\n    }\n\n    getNewApp(canvas: HTMLCanvasElement): Application {\n        PIXIUtils.skipHello();\n        const app = new Application({\n            view: canvas,\n            width: canvas.width,\n            height: canvas.height,\n            autoStart: false,\n            antialias: true,\n            transparent: true,\n        });\n        (app.stage as any).canvas = canvas;\n        return app;\n    }\n\n    private _isWebGLSupported() {\n        if (PIXIUtils.isWebGLSupported()) {\n            return;\n        }\n        throw new Error('webgl not supported');\n    }\n}\n\nexport const PIXIGlobal: _PIXIGlobal = new _PIXIGlobal();\n"
  },
  {
    "path": "src/class/pixi/mesh/PIXIH3Plane.js",
    "content": "import { Container } from 'pixi.js';\n\nexport class PIXIH3Plane extends Container {\n    /**\n     * assignTexture() 호출 이후, width, tint 를 호출해야 함.\n     * @param {PIXIBaseAsset} baseAsset\n     */\n    constructor(baseAsset) {\n        super();\n        this._baseAsset = baseAsset;\n        this._tint = 0xffffff;\n        this._prevTexturePrefix = '';\n    }\n\n    assignTexture(texturePrefix) {\n        if (this._prevTexturePrefix === texturePrefix) {\n            return;\n        }\n        this._prevTexturePrefix = texturePrefix;\n\n        this._tint = 0xffffff;\n        this._releaseSprite(this._sp0);\n        this._releaseSprite(this._sp1);\n        this._releaseSprite(this._sp2);\n\n        const ba = this._baseAsset;\n        this._sp0 = this._appendSprite(ba, texturePrefix, 0);\n        this._sp1 = this._appendSprite(ba, texturePrefix, 1);\n        this._sp2 = this._appendSprite(ba, texturePrefix, 2);\n        this._sideWidth = this._sp0.width + this._sp2.width;\n    }\n\n    /**\n     *\n     * @param {PIXIBaseAsset} baseAsset\n     * @param {string} texturePrefix\n     * @param {number} index\n     */\n    _appendSprite(baseAsset, texturePrefix, index) {\n        const sp = baseAsset.newSprite(texturePrefix + index);\n        this.addChild(sp);\n        return sp;\n    }\n\n    _releaseSprite(sp) {\n        if (!sp) {\n            return;\n        }\n        sp.destroy();\n    }\n\n    set width(value) {\n        const cw = value - this._sideWidth;\n        if (cw > 0) {\n            this._sp1.x = this._sp0.width;\n            this._sp1.width = cw;\n            this._sp2.x = value - this._sp2.width;\n        } else {\n            this._sp0.scale.x = this._sp2.scale.x = value / this._sideWidth;\n            this._sp2.x = this._sp0.width;\n            this._sp1.scale.x = 0;\n        }\n    }\n\n    /**\n     * @param {number} value\n     */\n    set tint(value) {\n        this._tint = value;\n        this._sp0.tint = this._sp1.tint = this._sp2.tint = value;\n    }\n\n    get tint() {\n        return this._tint;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/plugins/PIXIGraphicOverride.js",
    "content": "import { Graphics } from 'pixi.js';\n\n/**\n * PIXI.Graphics을 createjs.Shape와 비슷한 인터페이스로 구현하기 위한 함수\n *\n */\n\nclass GraphicsAdaptor {\n    constructor(gra) {\n        /**\n         * @private\n         * @type {PIXI.Graphics}\n         */\n        this._gra = gra;\n        this._lineStyleChanged = false;\n\n        this._lineStyle = {\n            alpha: 1,\n            color: 0,\n            thickness: 0,\n        };\n\n        this._fillStyle = {\n            alpha: 1,\n            color: 0,\n        };\n    }\n\n    moveTo(x, y) {\n        this._gra.moveTo(x, y);\n        return this;\n    }\n\n    beginFill(color) {\n        const style = this._fillStyle;\n        this._parseRGBCssStyleColor(color, style);\n        this._gra.beginFill(style.color, style.alpha);\n        return this;\n    }\n\n    beginStroke(color) {\n        this._parseRGBCssStyleColor(color, this._lineStyle);\n        this._lineStyleChanged = true;\n        this._setStrokeStyle();\n        return this;\n    }\n\n    drawRoundRect(x, y, w, h, r) {\n        this._gra.drawRoundedRect(x, y, w, h, r);\n        return this;\n    }\n\n    drawCircle(x, y, r) {\n        this._gra.drawCircle(x, y, r);\n        return this;\n    }\n\n    lineTo(x, y) {\n        this._gra.lineTo(x, y);\n        return this;\n    }\n\n    clear() {\n        this._gra.clear();\n        return this;\n    }\n\n    setStrokeStyle(thickness, caps = 0, joints = 0, miterLimit = 10) {\n        this._lineStyleChanged = true;\n        this._lineStyle.thickness = thickness;\n        this._setStrokeStyle();\n        return this;\n    }\n\n    drawRect(x, y, w, h) {\n        this._gra.drawRect(x, y, w, h);\n        return this;\n    }\n\n    closePath() {\n        this._gra.closePath();\n        return this;\n    }\n\n    endStroke() {\n        //todo [박준배] endStroke에 해당하는 pixi 메서드를 찾아서 넣어주긔.\n        return this;\n    }\n\n    _setStrokeStyle() {\n        if (!this._lineStyleChanged) {\n            return;\n        }\n        this._lineStyleChanged = false;\n        const s = this._lineStyle;\n        this._gra.lineStyle(s.thickness, s.color, s.alpha);\n    }\n\n    /**\n     * @param color {string}\n     * @param result\n     * @private\n     */\n    _parseRGBCssStyleColor(color, result) {\n        if (!color) {\n            return;\n        }\n        color = color.replace('/s/', '');\n        if (color[0] === '#') {\n            result.color = parseInt(color.substr(1), 16);\n            return;\n        }\n\n        let regexResult;\n\n        regexResult = /^rgba\\((\\d+),(\\d+),(\\d+),(\\d+(\\.?\\d*))\\)$/i.exec(color);\n        if (regexResult) {\n            result.color = this._RGBToNumber(regexResult);\n            result.alpha = Number(regexResult[4]);\n            return;\n        }\n\n        regexResult = /^rgb\\((\\d+),(\\d+),(\\d+)\\)$/i.exec(color);\n        if (regexResult) {\n            result.color = this._RGBToNumber(regexResult);\n        }\n    }\n\n    _RGBToNumber(regexResult) {\n        const [x, r, g, b] = regexResult;\n        return (r << 16) + (g << 8) + Number(b);\n    }\n\n    quadraticCurveTo(cpX, cpY, toX, toY) {\n        this._gra.quadraticCurveTo(cpX, cpY, toX, toY);\n        return this;\n    }\n\n    drawEllipse(x, y, width, height) {\n        this._gra.drawEllipse(x, y, width, height);\n        return this;\n    }\n}\n\n// createjs tiny api\nconst GP = GraphicsAdaptor.prototype;\nGP.mt = GP.moveTo;\nGP.f = GP.beginFill;\nGP.s = GP.beginStroke;\nGP.rr = GP.drawRoundRect;\nGP.dc = GP.drawCircle;\nGP.lt = GP.lineTo;\nGP.ss = GP.setStrokeStyle;\nGP.rect = GP.r = GP.dr = GP.drawRect;\nGP.cp = GP.closePath;\nGP.es = GP.endStroke;\nGP.qt = GP.quadraticCurveTo;\nGP.de = GP.drawEllipse;\n\nexport function PIXIGraphicOverride() {\n    const p = Graphics.prototype;\n\n    Object.defineProperties(p, {\n        graphics: {\n            get() {\n                if (!this.___adaptor___) {\n                    this.___adaptor___ = new GraphicsAdaptor(this);\n                }\n                return this.___adaptor___;\n            },\n        },\n    });\n}\n"
  },
  {
    "path": "src/class/pixi/plugins/PIXIPixelPerfectInteractionPlugIn.js",
    "content": "import { Sprite, Point } from 'pixi.js';\n\nconst tempPoint = new Point();\nconst hitTestCanvas = document.createElement('canvas');\nhitTestCanvas.width = 1;\nhitTestCanvas.height = 1;\nconst hitTestConText = hitTestCanvas.getContext('2d');\n\nexport function PIXIPixelPerfectInteractionPlugIn() {\n    const p = Sprite.prototype;\n\n    /**\n     * if true use pixel-perfect hit test\n     * @type {boolean}\n     */\n    p.pixelPerfect = false;\n\n    /** @type {number} not ratio. 16 bit value.\n     *  [박봉배] - createjs 에서 testAlpha > 1 이면 히트로 처리.\n     */\n    p.pixelPerfectAlpha = 1;\n    /**\n     * PIXISprite.ts 에서 override 함. 메서드명 바꾸지 말긔.\n     * @return {PIXI.BaseTexture | (HTMLImageElement | HTMLCanvasElement | HTMLVideoElement)}\n     */\n    p.internal_getOriginalTex = function() {\n        return this.texture;\n    };\n\n    p.containsPoint = function(point) {\n        //overwrite PIXI.Sprite.containsPoint\n        const tex = this.internal_getOriginalTex();\n        // if (!tex.baseTexture) {\n        //     return false;\n        // }\n        // if (!tex.baseTexture.source) {\n        //     return false;\n        // }\n\n        this.worldTransform.applyInverse(point, tempPoint);\n        const width = tex.orig.width;\n        const height = tex.orig.height;\n        const x1 = -width * this.anchor.x;\n        let y1 = 0;\n\n        if (tempPoint.x >= x1 && tempPoint.x < x1 + width) {\n            y1 = -height * this.anchor.y;\n            if (tempPoint.y >= y1 && tempPoint.y < y1 + height) {\n                if (this.pixelPerfect) {\n                    return this._pixelHasAlpha(tempPoint.x, tempPoint.y, tex);\n                }\n                return true;\n            }\n        }\n        return false;\n    }; // end p.containsPoint\n\n    p._pixelHasAlpha = function(x, y, tex) {\n        //add method into PIXI.Sprite\n        let left = x;\n        let top = y;\n        const { frame } = tex;\n        const anchor = this.anchor;\n\n        if (anchor.x !== 0) {\n            left -= -frame.width * anchor.x;\n        }\n\n        if (anchor.y !== 0) {\n            top -= -frame.height * anchor.y;\n        }\n\n        left += frame.x;\n        top += frame.y;\n        const { resource } = tex.baseTexture;\n        const { source } = resource || {};\n        if (!source) {\n            return false;\n        }\n        const ctx = hitTestConText;\n        ctx.clearRect(0, 0, 1, 1);\n        ctx.drawImage(source, left, top, 1, 1, 0, 0, 1, 1);\n        const rgba = ctx.getImageData(0, 0, 1, 1);\n        return rgba.data[3] > this.pixelPerfectAlpha;\n    }; //end p._checkPixel\n}\n"
  },
  {
    "path": "src/class/pixi/plugins/PIXIShortPropPlugin.js",
    "content": "import { DisplayObject, Container } from 'pixi.js';\n\nexport function PIXIShortPropPlugin() {\n    Object.defineProperties(DisplayObject.prototype, {\n        scaleX: {\n            get() {\n                return this.scale.x;\n            },\n            set(v) {\n                this.scale.x = v;\n            },\n        },\n        scaleY: {\n            get() {\n                return this.scale.y;\n            },\n            set(v) {\n                this.scale.y = v;\n            },\n        },\n        regX: {\n            get() {\n                return this.pivot.x;\n            },\n            set(v) {\n                this.pivot.x = v;\n            },\n        },\n        regY: {\n            get() {\n                return this.pivot.y;\n            },\n            set(v) {\n                this.pivot.y = v;\n            },\n        },\n        mouseEnabled: {\n            get() {\n                return this.interactive;\n            },\n            set(v) {\n                this.interactive = v;\n            },\n        },\n    });\n\n    Object.defineProperties(Container.prototype, {\n        mouseChildren: {\n            get() {\n                return this.interactiveChildren;\n            },\n            set(v) {\n                this.interactiveChildren = v;\n            },\n        },\n    });\n}\n"
  },
  {
    "path": "src/class/pixi/plugins/PIXISprite.ts",
    "content": "/**\n * PIXI.DisplayObject.cacheAsBitmap 이 원하는대로 작동을 안함.\n * var sp = new PIXI.Sprite(texture);\n * sp.scale.set(2)\n * sp.cacheAsBitmap = true; 이렇게 하면 케시된 텍스쳐가 localTransform에 영향을 받아서 스케일이 2배가 되어버림. 원본과 동일해야 하는데...\n *\n * 그래서 setFilterAndCache() 로 비슷하게 구현.\n */\nimport { Texture, Sprite, RenderTexture, Matrix, Renderer } from 'pixi.js';\nimport { EntryTextureBase } from '../atlas/texture/EntryTextureBase';\n\nclass FilterData {\n    private _orgTex: EntryTextureBase | RenderTexture;\n    private _renderTex: RenderTexture;\n\n    filters: any[];\n    invalidate: boolean;\n\n    setOrgTex(orgTex: EntryTextureBase) {\n        this._orgTex = orgTex;\n    }\n\n    isSameRenderTex(tex: any): boolean {\n        return tex == this._renderTex;\n    }\n\n    get orgTex(): EntryTextureBase | RenderTexture {\n        return this._orgTex;\n    }\n\n    getRenderTexture(width: number, height: number): RenderTexture {\n        if (!this._renderTex) {\n            this._renderTex = RenderTexture.create({ width, height });\n            return this._renderTex;\n        }\n        const tex = this._renderTex;\n        if (tex.width != width || tex.height != height) {\n            this.destroyRenderTexture();\n            return this.getRenderTexture(width, height);\n        }\n        return this._renderTex;\n    }\n\n    destroyRenderTexture() {\n        if (!this._renderTex) {\n            return;\n        }\n        this._renderTex.destroy(true);\n        this._renderTex = null;\n    }\n\n    destroy() {\n        this.destroyRenderTexture();\n        this._orgTex = null;\n        this.filters = null;\n    }\n}\n\nconst EMPTY_SP = new Sprite();\nconst MAT: any = new Matrix();\n\nexport class PIXISprite extends Sprite {\n    private _filterData: FilterData;\n    // public _filterData:FilterData;\n\n    //PIXIPixelPerfectInteractionPlugIn 에서 호출함.\n    internal_getOriginalTex() {\n        return (this._filterData && this._filterData.orgTex) || this.texture;\n    }\n\n    setFilterAndCache(filters: any[] | null) {\n        if (!filters || !filters.length) {\n            if (this._filterData) {\n                this.texture = this._filterData.orgTex;\n                this._filterData.destroy();\n                this._filterData = null;\n            }\n        } else {\n            if (!this._filterData) {\n                this._filterData = new FilterData();\n                this._filterData.setOrgTex(this.texture as EntryTextureBase);\n            } else if (!this._filterData.isSameRenderTex(this.texture)) {\n                this._filterData.setOrgTex(this.texture as EntryTextureBase);\n            }\n            this._filterData.filters = filters;\n            this._filterData.invalidate = true;\n        }\n    }\n\n    /**\n     * filter + cache 가 이미 설정되고, 다른 텍스쳐로 할당 되었을때 filter를 다시 설정하기 위한 메서드\n     * set texture 를 override 하지 못해서...\n     */\n    refreshFilter() {\n        if (!this._filterData) {\n            return;\n        }\n        if (!this._filterData.filters) {\n            return;\n        }\n        this.setFilterAndCache(this._filterData.filters);\n    }\n\n    destroy(options?: any) {\n        super.destroy(options);\n        if (this._filterData) {\n            this._filterData.destroy();\n            this._filterData = null;\n        }\n    }\n\n    render(renderer: Renderer): void {\n        if (this._filterData && this._filterData.invalidate) {\n            this._filterData.invalidate = false;\n            this._initFilterCache(renderer);\n        }\n        super.render(renderer);\n    }\n\n    private _initFilterCache(renderer: Renderer) {\n        const fd: FilterData = this._filterData;\n        const tex: Texture = fd.orgTex;\n\n        const w = tex.orig.width;\n        const h = tex.orig.height;\n        const renderTex: RenderTexture = fd.getRenderTexture(w, h);\n        if (!renderTex) {\n            return;\n        }\n        if (fd.orgTex instanceof EntryTextureBase) {\n            // filter 된 sprite 를 도장찍기 하면 sprite.texture 의 type 는 RenderTexture 가 된다.\n            fd.orgTex.assignTextureScaleFactor(renderTex);\n        }\n        const sp = EMPTY_SP;\n        sp.filters = this._filterData.filters;\n        sp.texture = tex;\n\n        const cachedRenderTarget = renderer.renderTexture.current;\n        renderer.batch.flush();\n        renderer.render(sp, renderTex, true, MAT, false);\n        renderer.renderTexture.bind(cachedRenderTarget);\n\n        this.texture = renderTex;\n        sp.texture = null;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/plugins/PIXITextMetricsPlugIn.js",
    "content": "import { TextMetrics } from 'pixi.js';\n\nexport function PIXITextMetricsPlugIn() {\n    const WordWrap = TextMetrics.wordWrap;\n    TextMetrics.__breakAllWordWrap = __breakAllWordWrap;\n\n    TextMetrics.wordWrap = function(text, style, canvas = TextMetrics._canvas) {\n        return style.wordBreakAll\n            ? TextMetrics.__breakAllWordWrap(text, style, canvas)\n            : WordWrap(text, style, canvas);\n    };\n\n    /**\n     *\n     * @param text\n     * @param {PIXI.TextStyle | PIXITextStyle} style\n     * @param canvas\n     * @return {string}\n     * @private\n     */\n    function __breakAllWordWrap(text, style, canvas) {\n        const context = canvas.getContext('2d');\n\n        let width = 0;\n        let line = '';\n        let lines = '';\n\n        const cache = {};\n        const { letterSpacing, whiteSpace } = style;\n\n        // How to handle whitespaces\n        const collapseSpaces = TextMetrics.collapseSpaces(whiteSpace);\n        const collapseNewlines = TextMetrics.collapseNewlines(whiteSpace);\n\n        // whether or not spaces may be added to the beginning of lines\n        let canPrependSpaces = !collapseSpaces;\n\n        // There is letterSpacing after every char except the last one\n        // t_h_i_s_' '_i_s_' '_a_n_' '_e_x_a_m_p_l_e_' '_!\n        // so for convenience the above needs to be compared to width + 1 extra letterSpace\n        // t_h_i_s_' '_i_s_' '_a_n_' '_e_x_a_m_p_l_e_' '_!_\n        // ________________________________________________\n        // And then the final space is simply no appended to each line\n        const wordWrapWidth = style.wordWrapWidth + letterSpacing;\n\n        // break text into words, spaces and newline chars\n        const tokens = TextMetrics.tokenize(text);\n\n        for (let i = 0; i < tokens.length; i++) {\n            // get the word, space or newlineChar\n            let token = tokens[i];\n\n            // if word is a new line\n            if (TextMetrics.isNewline(token)) {\n                // keep the new line\n                if (!collapseNewlines) {\n                    lines += TextMetrics.addLine(line);\n                    canPrependSpaces = !collapseSpaces;\n                    line = '';\n                    width = 0;\n                    continue;\n                }\n\n                // if we should collapse new lines\n                // we simply convert it into a space\n                token = ' ';\n            }\n\n            // if we should collapse repeated whitespaces\n            if (collapseSpaces) {\n                // check both this and the last tokens for spaces\n                const currIsBreakingSpace = TextMetrics.isBreakingSpace(token);\n                const lastIsBreakingSpace = TextMetrics.isBreakingSpace(line[line.length - 1]);\n\n                if (currIsBreakingSpace && lastIsBreakingSpace) {\n                    continue;\n                }\n            }\n\n            // get word width from cache if possible\n            const tokenWidth = TextMetrics.getFromCache(token, letterSpacing, cache, context);\n\n            // word is longer than desired bounds\n            if (width + tokenWidth > wordWrapWidth) {\n                const characters = token.split('');\n                for (let j = 0; j < characters.length; j++) {\n                    const char = characters[j];\n                    const characterWidth = TextMetrics.getFromCache(\n                        char,\n                        letterSpacing,\n                        cache,\n                        context\n                    );\n                    if (width + characterWidth > wordWrapWidth) {\n                        //newLine\n                        lines += TextMetrics.addLine(line);\n                        canPrependSpaces = false;\n                        line = '';\n                        width = 0;\n                    }\n                    line += char;\n                    width += characterWidth;\n                }\n            }\n\n            // word could fit\n            else {\n                // word won't fit because of existing words\n                // start a new line\n                if (tokenWidth + width > wordWrapWidth) {\n                    // if its a space we don't want it\n                    canPrependSpaces = false;\n\n                    // add a new line\n                    lines += TextMetrics.addLine(line);\n\n                    // start a new line\n                    line = '';\n                    width = 0;\n                }\n\n                // don't add spaces to the beginning of lines\n                if (line.length > 0 || !TextMetrics.isBreakingSpace(token) || canPrependSpaces) {\n                    // add the word to the current line\n                    line += token;\n\n                    // update width counter\n                    width += tokenWidth;\n                }\n            }\n        }\n\n        lines += TextMetrics.addLine(line, false);\n\n        return lines;\n    }\n\n    //createjs와 동일한 글씨 크기 측정을 위해\n    /**\n     *\n     * @param {PIXI.TextStyle} style\n     * @param text\n     * @return {number}\n     * @private\n     */\n    function _getMeasuredWidth(font, text) {\n        const ctx = TextMetrics._context;\n        ctx.save();\n        ctx.font = font;\n        const w = ctx.measureText(text).width;\n        ctx.restore();\n        return w;\n    }\n\n    //createjs와 동일한 글씨 크기 측정을 위해\n    TextMetrics.measureText = function(text, style, wordWrap, canvas = TextMetrics._canvas) {\n        wordWrap = wordWrap === undefined || wordWrap === null ? style.wordWrap : wordWrap;\n        const font = style.toFontString();\n        // const fontProperties = TextMetrics.measureFont(font); //skip for performance\n        const fontProperties = null;\n        const context = canvas.getContext('2d');\n\n        context.font = font;\n\n        const outputText = wordWrap ? TextMetrics.wordWrap(text, style, canvas) : text;\n        const lines = outputText.split(/(?:\\r\\n|\\r|\\n)/);\n        const lineWidths = new Array(lines.length);\n        let maxLineWidth = 0;\n\n        for (let i = 0; i < lines.length; i++) {\n            const lineWidth =\n                context.measureText(lines[i]).width + (lines[i].length - 1) * style.letterSpacing;\n\n            lineWidths[i] = lineWidth;\n            maxLineWidth = Math.max(maxLineWidth, lineWidth);\n        }\n        const width = maxLineWidth + style.strokeThickness;\n        const lineHeight = style.lineHeight || _getMeasuredWidth(font, 'M') * 1.2;\n        const height = lineHeight * lines.length;\n\n        return new TextMetrics(\n            text,\n            style,\n            width,\n            height,\n            lines,\n            lineWidths,\n            lineHeight + style.leading,\n            maxLineWidth,\n            fontProperties\n        );\n    };\n}\n"
  },
  {
    "path": "src/class/pixi/plugins/pixiGetChildAt.js",
    "content": "/**\n * PIXI.Container.getChildAt 은 잘못된 index를 넣으면 throw 함. createjs 는 안함.\n * 동일한 스펙을 맞추기 위해 새로 정의함.\n */\nimport { Container } from 'pixi.js';\n\nexport function pixiGetChildAt() {\n    const p = Container.prototype;\n    p.getChildAt = function(index) {\n        return this.children[index];\n    };\n\n    p.getChildIndex = function(child) {\n        return this.children.indexOf(child);\n    };\n\n    p.___addChildAt = p.addChildAt;\n    p.addChildAt = function(child, index) {\n        try {\n            return this.___addChildAt(child, index);\n        } catch (e) {\n            return child;\n        }\n    };\n}\n"
  },
  {
    "path": "src/class/pixi/text/PIXIText.js",
    "content": "/**\n * createjs 의 rendeeing 방식을 따라 하기 위해 fontProperty를 사용안함.\n * 뷰의 스케일 조정을 하더라도 깔끔하게 보이기 위해 fontScale 를 추가하여 텍스쳐의 크기를 조절함.\n */\nimport { TextMetrics, Text } from 'pixi.js';\nimport PIXITextStyle from './PIXITextStyle';\nimport { PIXIGlobal } from '../init/PIXIGlobal';\n\nlet $textCanvasContainer;\n\nexport class PIXIText extends Text {\n    constructor(text, style) {\n        const canvas = document.createElement('canvas');\n        if (!$textCanvasContainer) {\n            $textCanvasContainer = $('#textCanvasContainer');\n        }\n        $textCanvasContainer.append(canvas);\n        super(text, style, canvas);\n        this.setFontScaleX(1);\n        this.setFontScaleY(1);\n        PIXIGlobal.fontLoadChecker.manage(this);\n    }\n\n    set style(style) {\n        // eslint-disable-line require-jsdoc\n        style = style || {};\n\n        if (style instanceof PIXITextStyle) {\n            this._style = style;\n        } else {\n            this._style = new PIXITextStyle(style);\n        }\n\n        this.localStyleID = -1;\n        this.dirty = true;\n    }\n    get style() {\n        return super.style;\n    }\n\n    setFontScaleX(value) {\n        value = value * PIXIText.STAGE_SCALE;\n        this._fontScaleX = value;\n        this.scale.x = 1 / value;\n        this.dirty = true;\n    }\n    setFontScaleY(value) {\n        value = value * PIXIText.STAGE_SCALE;\n        this._fontScaleY = value;\n        this.scale.y = 1 / value;\n        this.dirty = true;\n    }\n\n    getMeasuredWidth() {\n        this.updateText(true);\n        return this._measuredWidth;\n    }\n\n    getMeasuredHeight() {\n        this.updateText(true);\n        return this._measuredHeight;\n    }\n    getMeasuredLineHeight() {\n        this.updateText(true);\n        return this._measuredLineHeight;\n    }\n\n    /** @deprecated */\n    get measuredWidth() {\n        this.updateText(true);\n        console.warn('[deprecated] - PIXIText.measuredWidth');\n        return this._measuredWidth;\n    }\n    /** @deprecated */\n    get measuredHeight() {\n        this.updateText(true);\n        console.warn('[deprecated] - PIXIText.measuredHeight');\n        return this._measuredHeight;\n    }\n    /** @deprecated */\n    get measuredLineHeight() {\n        this.updateText(true);\n        console.warn('[deprecated] - PIXIText.measuredLineHeight');\n        return this._measuredLineHeight;\n    }\n\n    /**\n     * Renders text and updates it when needed.\n     *\n     * @private\n     * @param {boolean} respectDirty - Whether to abort updating the text if the Text isn't dirty and the function is called.\n     */\n    updateText(respectDirty) {\n        const style = this._style;\n\n        // check if style has changed..\n        if (this.localStyleID !== style.styleID) {\n            this.dirty = true;\n            this.localStyleID = style.styleID;\n        }\n\n        if (!this.dirty && respectDirty) {\n            return;\n        }\n\n        this._font = this._style.toFontString();\n        const context = this.context;\n        const measured = TextMetrics.measureText(\n            this._text,\n            this._style,\n            this._style.wordWrap,\n            this.canvas\n        );\n        const width = (this._measuredWidth = measured.width);\n        const height = (this._measuredHeight = measured.height);\n        const lines = measured.lines;\n        const lineHeight = (this._measuredLineHeight = measured.lineHeight);\n        const lineWidths = measured.lineWidths;\n        const maxLineWidth = measured.maxLineWidth;\n        const fontProperties = measured.fontProperties;\n\n        const UN = undefined;\n        const FSX = this._fontScaleX === UN ? 1 : this._fontScaleX;\n        const FSY = this._fontScaleY === UN ? 1 : this._fontScaleY;\n\n        this.canvas.width = Math.ceil(\n            (Math.max(1, width) + style.padding * 2) * this.resolution * FSX\n        );\n        this.canvas.height = Math.ceil(\n            (Math.max(1, height) + style.padding * 2) * this.resolution * FSY\n        );\n\n        context.scale(this.resolution * FSX, this.resolution * FSY);\n\n        context.clearRect(0, 0, this.canvas.width, this.canvas.height);\n        //---------- DEBUG CODE ------------\n        // context.fillStyle = \"rgba(255, 0, 0, 0.3)\";\n        // context.fillRect(0, 0, this.canvas.width, this.canvas.height);\n        //---------- DEBUG CODE ------------\n\n        context.font = this._font;\n        context.strokeStyle = style.stroke;\n        context.lineWidth = style.strokeThickness;\n        context.textBaseline = style.textBaseline;\n        context.lineJoin = style.lineJoin;\n        context.miterLimit = style.miterLimit;\n\n        let linePositionX;\n        let linePositionY;\n\n        if (style.dropShadow) {\n            context.fillStyle = style.dropShadowColor;\n            context.globalAlpha = style.dropShadowAlpha;\n            context.shadowBlur = style.dropShadowBlur;\n\n            if (style.dropShadowBlur > 0) {\n                context.shadowColor = style.dropShadowColor;\n            }\n\n            const xShadowOffset = Math.cos(style.dropShadowAngle) * style.dropShadowDistance;\n            const yShadowOffset = Math.sin(style.dropShadowAngle) * style.dropShadowDistance;\n\n            for (let i = 0; i < lines.length; i++) {\n                linePositionX = style.strokeThickness / 2;\n                linePositionY = style.strokeThickness / 2 + i * lineHeight + fontProperties.ascent;\n\n                if (style.align === 'right') {\n                    linePositionX += maxLineWidth - lineWidths[i];\n                } else if (style.align === 'center') {\n                    linePositionX += (maxLineWidth - lineWidths[i]) / 2;\n                }\n\n                if (style.fill) {\n                    this.drawLetterSpacing(\n                        lines[i],\n                        linePositionX + xShadowOffset + style.padding,\n                        linePositionY + yShadowOffset + style.padding\n                    );\n\n                    if (style.stroke && style.strokeThickness) {\n                        context.strokeStyle = style.dropShadowColor;\n                        this.drawLetterSpacing(\n                            lines[i],\n                            linePositionX + xShadowOffset + style.padding,\n                            linePositionY + yShadowOffset + style.padding,\n                            true\n                        );\n                        context.strokeStyle = style.stroke;\n                    }\n                }\n            }\n        }\n\n        // reset the shadow blur and alpha that was set by the drop shadow, for the regular text\n        context.shadowBlur = 0;\n        context.globalAlpha = 1;\n\n        // set canvas text styles\n        context.fillStyle = this._generateFillStyle(style, lines);\n        const WORD_WRAP = style.wordWrap;\n        const H_LH = lineHeight * 0.5; // half line-height\n        const MAX_HEIGHT = style.maxHeight < 0 ? 0xffff : style.maxHeight - H_LH;\n        const PAD = style.padding;\n        // draw lines line by line\n        for (let i = 0; i < lines.length; i++) {\n            linePositionX = style.strokeThickness / 2;\n            linePositionY = style.strokeThickness / 2 + i * lineHeight + H_LH;\n\n            if (WORD_WRAP && linePositionY > MAX_HEIGHT) {\n                break;\n            }\n\n            if (style.align === 'right') {\n                linePositionX += maxLineWidth - lineWidths[i];\n            } else if (style.align === 'center') {\n                linePositionX += (maxLineWidth - lineWidths[i]) / 2;\n            }\n\n            if (style.stroke && style.strokeThickness) {\n                this.drawLetterSpacing(\n                    lines[i],\n                    linePositionX + style.padding,\n                    linePositionY + style.padding,\n                    true\n                );\n            }\n\n            if (style.fill) {\n                this.drawLetterSpacing(\n                    lines[i],\n                    linePositionX + style.padding,\n                    linePositionY + style.padding\n                );\n            }\n\n            //취소선 추가\n            if (style.cancelLine) {\n                this._drawLineAt(\n                    context,\n                    linePositionX + PAD,\n                    linePositionY + PAD,\n                    lineWidths[i],\n                    0\n                );\n            }\n\n            //밑줄\n            if (style.underLine) {\n                this._drawLineAt(\n                    context,\n                    linePositionX + PAD,\n                    linePositionY + PAD,\n                    lineWidths[i],\n                    lineHeight * 0.4\n                );\n            }\n        }\n\n        this.updateTexture();\n    }\n\n    updateTexture() {\n        const canvas = this.canvas;\n\n        // 박봉배- entryjs 에서 trim 기능 사용안함. 그리고 trimCanvas 의 참조를 pixi 라이브러리로부터 못갖고 오겠음.\n        /*\n        if (this._style.trim)\n        {\n            const trimmed = trimCanvas(canvas);\n\n            if (trimmed.data)\n            {\n                canvas.width = trimmed.width;\n                canvas.height = trimmed.height;\n                this.context.putImageData(trimmed.data, 0, 0);\n            }\n        }\n        */\n\n        const texture = this._texture;\n        const style = this._style;\n        const padding = style.trim ? 0 : style.padding;\n        const baseTexture = texture.baseTexture;\n\n        const UN = undefined;\n        const FSX = this._fontScaleX === UN ? 1 : this._fontScaleX;\n        const FSY = this._fontScaleY === UN ? 1 : this._fontScaleY;\n\n        baseTexture.hasLoaded = true;\n        baseTexture.resolution = this.resolution;\n        baseTexture.setRealSize(canvas.width, canvas.height);\n        baseTexture.setSize(canvas.width, canvas.height, this.resolution);\n\n        texture.trim.width = texture._frame.width = canvas.width / this.resolution;\n        texture.trim.height = texture._frame.height = canvas.height / this.resolution;\n        texture.trim.x = -padding * FSX;\n        texture.trim.y = -padding * FSY;\n\n        texture.orig.width = texture._frame.width - padding * 2 * FSX;\n        texture.orig.height = texture._frame.height - padding * 2 * FSY;\n\n        // call sprite onTextureUpdate to update scale if _width or _height were set\n        this._onTextureUpdate();\n\n        baseTexture.emit('update', baseTexture);\n\n        this.dirty = false;\n    }\n\n    /**\n     * 취소선 or 밑줄을 draw 하기 위한 함수.\n     * @private\n     * @param {CanvasRenderingContext2D} ctx\n     * @param x\n     * @param y\n     * @param width\n     * @param offsetY\n     */\n    _drawLineAt(ctx, x, y, width, offsetY) {\n        ctx.fillRect(x, y + offsetY, width, 1);\n    }\n\n    destroy() {\n        $(this.canvas).remove();\n        PIXIGlobal.fontLoadChecker.unmanage(this);\n        super.destroy({ children: false, baseTexture: true, texture: true });\n    }\n}\n\n// PIXIText.STAGE_SCALE = 1.51;\nPIXIText.STAGE_SCALE = 1.53;\n// PIXIText.STAGE_SCALE = 1.41;\n// console.log(`PIXIText.STAGE_SCALE1(${PIXIText.STAGE_SCALE})`);\n"
  },
  {
    "path": "src/class/pixi/text/PIXITextStyle.ts",
    "content": "/**\n * 취소선, 밑줄 추가 하기 위해 만튼 스타일.\n */\nimport { TextStyle } from 'pixi.js';\n\nexport default class PIXITextStyle extends TextStyle {\n    /** 취소선 */\n    private _cancelLine: boolean = false;\n    private _underLine: boolean = false;\n    /** 멀티 라인일때 ( wordWrap = true ) 글씨가 보여지는 최대 높이. 음수일때는 글씨를 모두 보여줌. */\n    private _maxHeight: number = -1;\n    private styleID: number = 0;\n\n    /**\n     *\n     * @return {boolean}\n     */\n    get cancelLine() {\n        return this._cancelLine;\n    }\n\n    set cancelLine(value) {\n        if (this._cancelLine !== value) {\n            this._cancelLine = value;\n            this.styleID++;\n        }\n    }\n\n    /** css wordBreak 의 break-all 속성을 구현하기 위함. entryjs 는 break-all 이 기본이기 때문에 return true 로 해버림. */\n    get wordBreakAll(): boolean {\n        return true;\n    }\n\n    /**\n     *\n     * @return {boolean}\n     */\n    get underLine() {\n        return this._underLine;\n    }\n\n    set underLine(value) {\n        if (this._underLine !== value) {\n            this._underLine = value;\n            this.styleID++;\n        }\n    }\n\n    get maxHeight() {\n        return this._maxHeight;\n    }\n\n    set maxHeight(value) {\n        if (this._maxHeight !== value) {\n            this._maxHeight = value;\n            this.styleID++;\n        }\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/utils/AutoFit.ts",
    "content": "export interface IRect {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n}\n\nexport namespace autoFit {\n    export enum ScaleMode {\n        NONE,\n        WIDTH,\n        HEIGHT,\n        INSIDE,\n        OUTSIDE,\n    }\n\n    export enum AlignMode {\n        TL,\n        TC,\n        CC,\n        BC,\n        BL,\n        NONE,\n    }\n\n    export function fit(\n        targetArea: IRect,\n        rSource: IRect,\n        scaleMode: ScaleMode,\n        alignMode: AlignMode = AlignMode.CC\n    ): IRect {\n        switch (scaleMode) {\n            case ScaleMode.NONE:\n                align(targetArea, rSource, alignMode);\n                break;\n            case ScaleMode.INSIDE:\n                align(targetArea, proportional_inside(targetArea, rSource), alignMode);\n                break;\n            case ScaleMode.OUTSIDE:\n                align(targetArea, proportional_outside(targetArea, rSource), alignMode);\n                break;\n            case ScaleMode.WIDTH:\n                align(targetArea, width_only(targetArea, rSource), alignMode);\n                break;\n            case ScaleMode.HEIGHT:\n                align(targetArea, height_only(targetArea, rSource), alignMode);\n                break;\n        }\n        return rSource;\n    }\n\n    function width_only(targetArea: IRect, rSource: IRect): IRect {\n        const s: number = targetArea.width / rSource.width;\n        rSource.width *= s;\n        rSource.height *= s;\n        return rSource;\n    }\n\n    function height_only(targetArea: IRect, rSource: IRect): IRect {\n        const s: number = targetArea.height / rSource.height;\n        rSource.width *= s;\n        rSource.height *= s;\n        return rSource;\n    }\n\n    function proportional_inside(targetArea: IRect, rSource: IRect): IRect {\n        const sx: number = targetArea.width / rSource.width;\n        const sy: number = targetArea.height / rSource.height;\n        const s: number = Math.min(sx, sy);\n        rSource.width *= s;\n        rSource.height *= s;\n        return rSource;\n    }\n\n    function proportional_outside(targetArea: IRect, rSource: IRect): IRect {\n        const sx: number = targetArea.width / rSource.width;\n        const sy: number = targetArea.height / rSource.height;\n        const s: number = Math.max(sx, sy);\n        rSource.width = rSource.width * s;\n        rSource.height = rSource.height * s;\n        return rSource;\n    }\n\n    function align(targetArea: IRect, rSource: IRect, strAlign: AlignMode): IRect {\n        switch (strAlign) {\n            case AlignMode.TC:\n                setCenter(targetArea, rSource, true, false);\n                rSource.x = targetArea.x;\n                break;\n            case AlignMode.CC:\n                setCenter(targetArea, rSource);\n                break;\n            case AlignMode.TL:\n                rSource.x = targetArea.x;\n                rSource.y = targetArea.y;\n                break;\n            case AlignMode.BC:\n                setCenter(targetArea, rSource, true, false);\n                rSource.y = targetArea.y + targetArea.height - rSource.height;\n                break;\n            case AlignMode.BL:\n                rSource.x = targetArea.x;\n                rSource.y = targetArea.y + targetArea.height - rSource.height;\n                break;\n            case AlignMode.NONE:\n                //아무것도 안함.\n                break;\n        }\n        return rSource;\n    }\n\n    export function setCenter(\n        targetArea: IRect,\n        rSource: IRect,\n        axisX: Boolean = true,\n        axisY: Boolean = true\n    ): void {\n        const r: IRect = targetArea;\n        if (axisX) {\n            rSource.x = r.x + r.width / 2 - rSource.width / 2;\n        }\n        if (axisY) {\n            rSource.y = r.y + r.height / 2 - rSource.height / 2;\n        }\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/utils/TimeoutTimer.ts",
    "content": "export class TimeoutTimer {\n    private _id: number;\n\n    timeout(timeMS: number, handler: () => void) {\n        this.reset();\n        this._id = window.setTimeout(() => {\n            handler();\n            this._id = 0;\n        }, timeMS);\n    }\n\n    get isRunning(): boolean {\n        return Boolean(this._id);\n    }\n\n    reset(): void {\n        if (!this._id) {\n            return;\n        }\n        clearTimeout(this._id);\n        this._id = 0;\n    }\n}\n"
  },
  {
    "path": "src/class/pixi/utils/logs.ts",
    "content": "type Ilog = (...arg:any[])=>void;\n\nlet emptyLog:Ilog = (...arg:any[])=>{};\n\nconst USE_NATIVE_LOG:boolean = false;\n\nlet nlog:Ilog = console.log.bind(console);\nexport let clog:Ilog = USE_NATIVE_LOG ? nlog : emptyLog;\n\nlet nwarn:Ilog = console.warn.bind(console);\nexport let cwarn:Ilog = USE_NATIVE_LOG ? nwarn : emptyLog;"
  },
  {
    "path": "src/class/playground.js",
    "content": "/**\n * Playground is block construct area.\n * @fileoverview This manage playground.\n */\n'use strict';\n\nimport { Backpack, ColorPicker, Dropdown, Sortable } from '@entrylabs/tool';\nimport Toast from '../playground/toast';\nimport EntryEvent from '@entrylabs/event';\nimport { Destroyer } from '../util/destroyer/Destroyer';\nimport DataTable from './DataTable';\nimport SoundEditor from './sound';\nimport _get from 'lodash/get';\n\nconst Entry = require('../entry');\n\n/**\n * Class for a playground.\n * This manage all view related with block.\n * @constructor\n */\nEntry.Playground = class Playground {\n    constructor() {\n        this._destroyer = this._destroyer || new Destroyer();\n        this._destroyer.destroy();\n        this.isTextBGMode_ = false;\n        this.dataTable = DataTable;\n\n        /**\n         * playground's current view type\n         * View types are 'default', 'code', 'picture', 'text', sound'\n         * @type {string}\n         */\n        this.viewMode_ = 'default';\n        Entry.addEventListener('textEdited', () => {\n            this.injectText();\n        });\n        Entry.addEventListener('commentVisibleChanged', this.toggleCommentButtonVisible.bind(this));\n\n        Entry.addEventListener('workspaceChangeMode', this.updateSelectedObjectTitle.bind(this));\n\n        Entry.windowResized.attach(this, this.clearClientRectMemo.bind(this));\n    }\n\n    setMode(mode) {\n        this.mainWorkspace.setMode(mode);\n    }\n\n    /**\n     * Control bar view generator.\n     * @param {!Element} playgroundView playgroundView from Entry.\n     * @param {?string} option for choose type of view.\n     */\n    generateView(playgroundView, option = 'workspace') {\n        /** @type {!Element} */\n        this.view_ = playgroundView;\n        this.view_.addClass('entryPlayground');\n        if (option === 'workspace' || option === 'playground') {\n            this.view_.addClass('entryPlaygroundWorkspace');\n\n            const tabView = Entry.createElement('div', 'entryCategoryTab')\n                .addClass('entryPlaygroundTabWorkspace')\n                .appendTo(this.view_);\n            this.generateTabView(tabView);\n            this.tabView_ = tabView;\n\n            const tabButtonView = Entry.createElement('div', 'entryButtonTab')\n                .addClass('entryPlaygroundButtonTabWorkspace')\n                .appendTo(this.view_);\n            this.tabButtonView_ = tabButtonView;\n            this.createButtonTabView(tabButtonView);\n\n            const curtainView = Entry.createElement('div', 'entryCurtain')\n                .addClass('entryPlaygroundCurtainWorkspace entryRemove')\n                .appendTo(this.view_);\n            curtainView.textContent = Lang.Workspace.cannot_edit_click_to_stop;\n            curtainView.addEventListener('click', () => {\n                Entry.engine.toggleStop();\n            });\n            this.curtainView_ = curtainView;\n\n            const pictureView = Entry.createElement('div', 'entryPicture')\n                .addClass('entryPlaygroundPictureWorkspace entryRemove')\n                .appendTo(this.view_);\n            this.generatePictureView(pictureView);\n            this.pictureView_ = pictureView;\n\n            const pictureCurtainView = Entry.createElement('div', 'entryPictureCurtain')\n                .addClass('entryPlaygroundPictureCurtainWorkspace entryRemove')\n                .appendTo(pictureView);\n            this.pictureCurtainView_ = pictureCurtainView;\n\n            const pictureCurtainText = Entry.createElement('span', 'entryPictureCurtainText')\n                .addClass('entryPlaygroundPictureCurtainWorkspaceText')\n                .appendTo(pictureCurtainView);\n            pictureCurtainText.textContent = Lang.Workspace.add_object_before_edit;\n\n            const textView = Entry.createElement('div', 'entryText')\n                .addClass('entryPlaygroundTextWorkspace entryRemove')\n                .appendTo(this.view_);\n            this.generateTextView(textView);\n            this.textView_ = textView;\n\n            const soundView = Entry.createElement('div', 'entrySound')\n                .addClass('entryPlaygroundSoundWorkspace entryRemove')\n                .appendTo(this.view_);\n            this.generateSoundView(soundView);\n            this.soundView_ = soundView;\n\n            const defaultView = Entry.createElement('div', 'entryDefault')\n                .addClass('entryPlaygroundDefaultWorkspace')\n                .appendTo(this.view_);\n            this.generateDefaultView(defaultView);\n            this.defaultView_ = defaultView;\n\n            //Code view must be append at last.\n            const codeView = Entry.createElement('div', 'entryCode')\n                .addClass('entryPlaygroundCodeWorkspace entryRemove')\n                .appendTo(this.view_);\n            this.generateCodeView(codeView);\n            this.codeView_ = codeView;\n\n            const backPackView = Entry.createElement('div', 'entryBackPackView')\n                .addClass('entryPlaygroundBackPackView')\n                .appendTo(this.view_);\n            this.backPackView = backPackView;\n            this.createBackPackView(backPackView);\n\n            const resizeHandle = Entry.createElement('div')\n                .addClass('entryPlaygroundResizeWorkspace', 'entryRemove')\n                .bindOnClick(() => {\n                    this.mainWorkspace.blockMenu.toggleBlockMenu();\n                })\n                .appendTo(codeView);\n            this.resizeHandle_ = resizeHandle;\n\n            /** @type {!Element} */\n            this.codeView_ = codeView;\n\n            Entry.addEventListener('run', () => {\n                Entry.playground.curtainView_.removeClass('entryRemove');\n            });\n            Entry.addEventListener('stop', () => {\n                Entry.playground.curtainView_.addClass('entryRemove');\n            });\n            this.applyTabOption();\n        }\n    }\n\n    /**\n     * Generate default view.\n     * default view is shown when object is not selected.\n     * @param {!Element} defaultView\n     * @return {Element}\n     */\n    generateDefaultView(defaultView) {\n        return defaultView;\n    }\n\n    /**\n     * generate tab menus\n     * @param {!Element} tabView\n     * @return {Element}\n     */\n    generateTabView(tabView) {\n        const that = this;\n        const tabList = Entry.createElement('ul').addClass('entryTabListWorkspace');\n        this.tabList_ = tabList;\n        tabView.appendChild(tabList);\n\n        this.tabViewElements = {};\n        const codeTab = Entry.createElement('li', 'entryCodeTab')\n            .addClass('entryTabListItemWorkspace entryTabSelected')\n            .bindOnClick(() => {\n                Entry.do('playgroundChangeViewMode', 'code', that.selectedViewMode);\n            })\n            .appendTo(tabList);\n        codeTab.textContent = Lang.Workspace.tab_code;\n        this.tabViewElements.code = codeTab;\n        this._codeTab = codeTab;\n\n        const pictureTab = Entry.createElement('li', 'entryPictureTab')\n            .addClass('entryTabListItemWorkspace')\n            .bindOnClick(() => {\n                Entry.do('playgroundChangeViewMode', 'picture', that.selectedViewMode);\n            })\n            .appendTo(tabList);\n        pictureTab.textContent = Lang.Workspace.tab_picture;\n        this.tabViewElements.picture = pictureTab;\n        this.pictureTab = pictureTab;\n\n        const textboxTab = Entry.createElement('li', 'entryTextboxTab')\n            .addClass('entryTabListItemWorkspace entryRemove')\n            .appendTo(tabList)\n            .bindOnClick(() => {\n                Entry.do('playgroundChangeViewMode', 'text', that.selectedViewMode);\n            });\n        textboxTab.textContent = Lang.Workspace.tab_text;\n        this.tabViewElements.text = textboxTab;\n        this.textboxTab = textboxTab;\n\n        const soundTab = Entry.createElement('li', 'entrySoundTab')\n            .addClass('entryTabListItemWorkspace')\n            .appendTo(tabList)\n            .bindOnClick(() => {\n                Entry.do('playgroundChangeViewMode', 'sound', that.selectedViewMode);\n            });\n        soundTab.textContent = Lang.Workspace.tab_sound;\n        this.tabViewElements.sound = soundTab;\n        this.soundTab = soundTab;\n\n        const variableTab = Entry.createElement('li', 'entryVariableTab')\n            .addClass('entryTabListItemWorkspace entryVariableTabWorkspace')\n            .appendTo(tabList)\n            .bindOnClick(() => {\n                Entry.do('playgroundChangeViewMode', 'variable', that.selectedViewMode);\n            });\n        variableTab.textContent = Lang.Workspace.tab_attribute;\n        this.tabViewElements.variable = variableTab;\n        this.variableTab = variableTab;\n    }\n\n    createButtonTabView(tabButtonView) {\n        const { options = {} } = Entry;\n        const { commentDisable, backpackDisable } = options;\n\n        if (!commentDisable) {\n            const commentToggleButton = Entry.createElement('div')\n                .addClass('entryPlaygroundCommentButtonWorkspace showComment enabled')\n                .appendTo(tabButtonView);\n            commentToggleButton.setAttribute('alt', Lang.Blocks.show_all_comment);\n            commentToggleButton.setAttribute('title', Lang.Blocks.show_all_comment);\n\n            this.commentToggleButton_ = commentToggleButton;\n            commentToggleButton.bindOnClick(() => {\n                this.toggleCommentButton();\n            });\n\n            const addCommentButton = Entry.createElement('div')\n                .addClass('entryPlaygroundCommentButtonWorkspace addComment enabled')\n                .appendTo(tabButtonView);\n            addCommentButton.setAttribute('alt', Lang.Blocks.add_comment);\n            addCommentButton.setAttribute('title', Lang.Blocks.add_comment);\n\n            this.addCommentButton_ = addCommentButton;\n            addCommentButton.bindOnClick(() => {\n                this.addComment();\n            });\n        }\n\n        // TODO: 백팩(나의보관함) 숨김처리\n        if (!backpackDisable) {\n            const backPackButton = Entry.createElement('div')\n                .addClass('entryPlaygroundBackPackButtonWorkspace')\n                .appendTo(tabButtonView);\n            backPackButton.setAttribute('alt', Lang.Workspace.my_storage);\n            backPackButton.setAttribute('title', Lang.Workspace.my_storage);\n\n            this.backPackButton_ = backPackButton;\n            backPackButton.bindOnClick(() => {\n                Entry.dispatchEvent('openBackPack');\n            });\n        }\n    }\n\n    createBackPackView(backPackView) {\n        this.backPack = new Backpack({\n            isShow: false,\n            data: {\n                items: [],\n                onClose: () => {\n                    Entry.dispatchEvent('closeBackPack');\n                },\n                onRemoveItem: (id) => {\n                    Entry.dispatchEvent('removeBackPackItem', id);\n                },\n                onChangeTitle: (id, title) => {\n                    Entry.dispatchEvent('changeBackPackTitle', id, title);\n                },\n                onCustomDragEnter: ({ type, value, onDragEnter }) => {\n                    if (Entry.GlobalSvg.isShow && Entry.GlobalSvg.canAddStorageBlock) {\n                        const { _view = {} } = Entry.GlobalSvg;\n                        onDragEnter({\n                            type: 'block',\n                            value: _view,\n                        });\n                    } else if (Entry.container.isObjectDragging) {\n                        onDragEnter({\n                            type: 'object',\n                            value: Entry.container.dragObjectKey,\n                        });\n                    }\n                },\n                onDropItem: ({ type, value }) => {\n                    if (type === 'object') {\n                        const object = Entry.container.getObject(value);\n                        object.addStorage();\n                    } else if (type === 'block') {\n                        if (value.addStorage) {\n                            value.addStorage();\n                        }\n                    }\n                },\n            },\n            container: this.backPackView,\n        });\n        this.blockBackPackArea = Entry.Dom('div')\n            .addClass('blockBackPackDrop')\n            .appendTo(backPackView);\n        this.objectBackPackArea = Entry.Dom('div')\n            .addClass('objectBackPackDrop')\n            .appendTo(backPackView);\n        const icon = Entry.Dom('div', {\n            class: 'blockBackPackIcon',\n        });\n        const desc = Entry.Dom('div', {\n            class: 'blockBackPackDesc',\n            text: Lang.Workspace.playground_block_drop,\n        });\n        const desc2 = Entry.Dom('div', {\n            class: 'objectBackPackDesc',\n            text: Lang.Workspace.container_object_drop,\n        });\n        this.blockBackPackArea.append(icon);\n        this.blockBackPackArea.append(desc);\n        this.objectBackPackArea.append(icon.clone());\n        this.objectBackPackArea.append(desc2);\n\n        const { view: blockView } = this.board || {};\n        if (blockView) {\n            const dom = blockView[0];\n            const eventDom = new EntryEvent(dom);\n            this.blockBackPackEvent = eventDom;\n            const areaDom = new EntryEvent(this.blockBackPackArea[0]);\n            this.blockBackPackAreaEvent = areaDom;\n            areaDom.on('dropitem', (e) => {\n                const data = this.backPack.getData('data');\n                Entry.dispatchEvent('addBackPackToEntry', 'block', data);\n                this.blockBackPackArea.css({\n                    display: 'none',\n                });\n            });\n            eventDom.on('enteritem', () => {\n                const isDragging = this.backPack.getData('isDragging');\n                const type = this.backPack.getData('dragType');\n                if (isDragging && type === 'block') {\n                    const { width, height, top, left } = blockView[0].getBoundingClientRect();\n                    this.blockBackPackArea.css({\n                        width: width - 134,\n                        height,\n                        top,\n                        left,\n                        display: 'flex',\n                    });\n                }\n            });\n            areaDom.on('leaveitem', (e) => {\n                this.blockBackPackArea.css({\n                    display: 'none',\n                });\n            });\n        }\n\n        const { modes = {} } = Entry.propertyPanel || {};\n        const { object = {} } = modes;\n        const { contentDom: objectView } = object;\n        if (objectView) {\n            const dom = objectView[0];\n            const eventDom = new EntryEvent(dom);\n            this.objectBackPackEvent = eventDom;\n            const areaDom = new EntryEvent(this.objectBackPackArea[0]);\n            this.objectBackPackAreaEvent = areaDom;\n\n            areaDom.on('dropitem', (e) => {\n                const data = this.backPack.getData('data');\n                Entry.dispatchEvent('addBackPackToEntry', 'object', data);\n                this.objectBackPackArea.css({\n                    display: 'none',\n                });\n            });\n\n            eventDom.on('enteritem', () => {\n                const isDragging = this.backPack.getData('isDragging');\n                const type = this.backPack.getData('dragType');\n                if (isDragging && type === 'object') {\n                    const { width, height, top, left } = objectView[0].getBoundingClientRect();\n                    this.objectBackPackArea.css({\n                        width,\n                        height,\n                        top,\n                        left,\n                        display: 'flex',\n                    });\n                }\n            });\n\n            areaDom.on('leaveitem', (e) => {\n                this.objectBackPackArea.css({\n                    display: 'none',\n                });\n            });\n        }\n\n        const globalEvent = new EntryEvent(document);\n        globalEvent.data = {};\n        this.globalEvent = globalEvent;\n\n        this.backPack.on('onChangeDragging', (isDragging) => {\n            if (isDragging) {\n                globalEvent.off().on(\n                    'touchmove.itemdrag mousemove.itemdrag',\n                    (e) => {\n                        const isDragging = this.backPack.getData('isDragging');\n                        if (isDragging) {\n                            const point = Entry.Utils.getPosition(e);\n                            const { data } = globalEvent;\n                            const { dom: objectDom } = this.objectBackPackEvent;\n                            const { dom: blockDom } = this.blockBackPackEvent;\n                            const objectRect = this.getBoundingClientRectMemo(objectDom);\n                            const blockRect = this.getBoundingClientRectMemo(blockDom, {\n                                width: -134,\n                                right: -134,\n                            });\n                            if (\n                                !data.isObjectMouseEnter &&\n                                Entry.Utils.isPointInRect(point, objectRect)\n                            ) {\n                                data.isObjectMouseEnter = true;\n                                this.objectBackPackEvent.trigger('enteritem');\n                            } else if (\n                                data.isObjectMouseEnter &&\n                                !Entry.Utils.isPointInRect(point, objectRect)\n                            ) {\n                                data.isObjectMouseEnter = false;\n                                this.objectBackPackAreaEvent.trigger('leaveitem');\n                            }\n                            if (Entry.getMainWS().mode === Entry.Workspace.MODE_BOARD) {\n                                if (\n                                    !data.isBlockMouseEnter &&\n                                    Entry.Utils.isPointInRect(point, blockRect)\n                                ) {\n                                    data.isBlockMouseEnter = true;\n                                    this.blockBackPackEvent.trigger('enteritem');\n                                } else if (\n                                    data.isBlockMouseEnter &&\n                                    !Entry.Utils.isPointInRect(point, blockRect)\n                                ) {\n                                    data.isBlockMouseEnter = false;\n                                    this.blockBackPackAreaEvent.trigger('leaveitem');\n                                }\n                            }\n                        } else {\n                            this.objectBackPackAreaEvent.trigger('leaveitem');\n                            this.blockBackPackAreaEvent.trigger('leaveitem');\n                        }\n                    },\n                    { passive: false }\n                );\n            } else {\n                globalEvent.off();\n            }\n        });\n\n        this.backPack.data = {\n            draggableOption: {\n                lockAxis: 'y',\n                distance: 30,\n                onDropItem: (e) => {\n                    const { data } = globalEvent;\n                    if (data.isObjectMouseEnter) {\n                        data.isObjectMouseEnter = false;\n                        this.objectBackPackAreaEvent.trigger('dropitem');\n                    } else if (data.isBlockMouseEnter) {\n                        data.isBlockMouseEnter = false;\n                        this.blockBackPackAreaEvent.trigger('dropitem');\n                    }\n                },\n            },\n        };\n    }\n\n    setBackpackPointEvent(canPointEvent) {\n        this.backPack.data = {\n            canPointEvent,\n        };\n    }\n\n    getBoundingClientRectMemo = _.memoize((target, offset = {}) => {\n        const rect = target.getBoundingClientRect();\n        const result = {\n            top: rect.top,\n            bottom: rect.bottom,\n            left: rect.left,\n            right: rect.right,\n        };\n        Object.keys(offset).forEach((key) => {\n            result[key] += offset[key];\n        });\n        return result;\n    });\n\n    clearClientRectMemo() {\n        this.getBoundingClientRectMemo.cache = new _.memoize.Cache();\n    }\n\n    showBackPack(args) {\n        this.backPack.setData({ ...args });\n        this.backPack.show();\n        this.backPackView.removeClass('entryRemove');\n    }\n\n    hideBackPack() {\n        this.backPack.hide();\n        this.backPackView.addClass('entryRemove');\n    }\n\n    toggleCommentButton() {\n        if (this.board.isVisibleComment) {\n            this.toast.show(Lang.Blocks.hide_all_comment);\n            Entry.do('hideAllComment', this.board);\n        } else {\n            this.toast.show(Lang.Blocks.show_all_comment);\n            Entry.do('showAllComment', this.board);\n        }\n        this.toggleCommentButtonVisible();\n    }\n\n    addComment() {\n        if (!Entry.options.commentDisable && this.board) {\n            const { svg, scale } = this.board;\n            const boardCenterX = svg.clientWidth / 2 / scale;\n            const boardCenterY = svg.clientHeight / 2 / scale;\n\n            Entry.do(\n                'createComment',\n                {\n                    id: Entry.Utils.generateId(),\n                    x: Math.max(boardCenterX - 80, 0),\n                    y: Math.max(boardCenterY - 80, 0),\n                },\n                this.board\n            );\n        }\n    }\n\n    toggleCommentButtonVisible() {\n        const button = this.commentToggleButton_;\n        const addButton = this.addCommentButton_;\n\n        if (this.board.isVisibleComment) {\n            addButton.addClass('enabled');\n            button.addClass('enabled');\n            button.setAttribute('alt', Lang.Blocks.show_all_comment);\n            button.setAttribute('title', Lang.Blocks.show_all_comment);\n        } else {\n            addButton.removeClass('enabled');\n            button.removeClass('enabled');\n            button.setAttribute('alt', Lang.Blocks.hide_all_comment);\n            button.setAttribute('title', Lang.Blocks.hide_all_comment);\n        }\n    }\n\n    /**\n     * Inject and generate code view\n     * @param {!Element} codeView\n     * @return {Element}\n     */\n    generateCodeView(codeView) {\n        const variableView = this.createVariableView();\n        codeView.appendChild(variableView);\n        this.variableView_ = variableView;\n\n        codeView = Entry.Dom(codeView);\n        const boardView = Entry.Dom('div', {\n            parent: codeView,\n            id: 'entryWorkspaceBoard',\n            class: 'entryWorkspaceBoard',\n        });\n        this.boardView_ = boardView;\n\n        const blockMenuView = Entry.Dom('div', {\n            parent: codeView,\n            id: 'entryWorkspaceBlockMenu',\n            class: 'entryWorkspaceBlockMenu',\n        });\n\n        const initOpts = {\n            blockMenu: {\n                dom: blockMenuView,\n                align: 'LEFT',\n                categoryData: EntryStatic.getAllBlocks(),\n                scroll: true,\n            },\n            board: {\n                dom: boardView,\n            },\n            readOnly: Entry.readOnly,\n        };\n        if (Entry.textCodingEnable) {\n            initOpts.vimBoard = { dom: boardView };\n        }\n\n        this.mainWorkspace = new Entry.Workspace(initOpts);\n        this.blockMenu = this.mainWorkspace.blockMenu;\n        this.board = this.mainWorkspace.board;\n        this.toast = new Toast(this.board);\n        this.blockMenu.banClass('checker');\n        Entry.Func?.initBlock(this.blockMenu);\n        Entry.expansion?.banAllExpansionBlock();\n        Entry.aiUtilize?.banAllAIUtilizeBlock();\n        DataTable?.banAllBlock();\n        Entry.aiLearning?.banBlocks();\n        this.vimBoard = this.mainWorkspace.vimBoard;\n\n        this._destroyer.add(this.mainWorkspace);\n        this._destroyer.add(this.toast);\n\n        if (Entry.hw) {\n            Entry.hw.refreshHardwareBlockMenu();\n        }\n        if (Entry.hwLite) {\n            Entry.hwLite.refreshHardwareLiteBlockMenu();\n        }\n        if (Entry.options.expansionDisable) {\n            Entry.playground.blockMenu.banCategory('expansion');\n        }\n        if (Entry.options.aiUtilizeDisable) {\n            Entry.playground.blockMenu.banCategory('ai_utilize');\n        }\n    }\n\n    /**\n     * Generate picture view.\n     * @param {!Element} pictureView\n     * @return {Element}\n     */\n    generatePictureView(PictureView) {\n        if (Entry.type === 'workspace') {\n            const pictureAdd = Entry.createElement('div', 'entryAddPicture')\n                .addClass('entryPlaygroundAddPicture')\n                .appendTo(PictureView);\n\n            const innerPictureAdd = Entry.createElement('div', 'entryAddPictureInner')\n                .addClass('entryPlaygroundAddPictureInner')\n                .bindOnClick(() => {\n                    if (!Entry.container || Entry.container.isSceneObjectsExist()) {\n                        Entry.do('playgroundClickAddPicture');\n                    } else {\n                        Entry.toast.alert(\n                            Lang.Workspace.add_object_alert,\n                            Lang.Workspace.add_object_alert_msg\n                        );\n                    }\n                })\n                .appendTo(pictureAdd);\n            innerPictureAdd.textContent = Lang.Workspace.picture_add;\n            this._pictureAddButton = innerPictureAdd;\n\n            const innerDrawNewPicture = Entry.createElement('div', 'entryNewPictureInner')\n                .addClass('entryPlaygroundNewPictureInner')\n                .bindOnClick(() => {\n                    this.painter.newPicture();\n                })\n                .appendTo(pictureAdd);\n            innerDrawNewPicture.textContent = Lang.Workspace.draw_new;\n            this._drawNewPictureButton = innerDrawNewPicture;\n\n            this.pictureListView_ = Entry.createElement('ul', 'entryPictureList')\n                .addClass('entryPlaygroundPictureList')\n                .appendTo(PictureView);\n\n            const painterDom = Entry.createElement('div', 'entryPainter')\n                .addClass('entryPlaygroundPainter')\n                .appendTo(PictureView);\n\n            switch (Entry.paintMode) {\n                case 'entry-paint':\n                    this.painter = new Entry.Painter(painterDom);\n                    break;\n                case 'literallycanvas':\n                    this.painter = new Entry.LiterallycanvasPainter(painterDom);\n                    break;\n            }\n        }\n    }\n\n    initSortablePictureWidget() {\n        if (this.pictureSortableListWidget) {\n            return;\n        }\n\n        this.pictureSortableListWidget = new Sortable({\n            data: {\n                height: '100%',\n                sortableTarget: ['entryPlaygroundPictureThumbnail'],\n                lockAxis: 'y',\n                items: this._getSortablePictureList(),\n            },\n            container: this.pictureListView_,\n        }).on('change', ([newIndex, oldIndex]) => {\n            Entry.playground.movePicture(newIndex, oldIndex);\n        });\n    }\n\n    updatePictureView() {\n        if (this.pictureSortableListWidget) {\n            this.pictureSortableListWidget.setData({ items: [] });\n            this.pictureSortableListWidget.setData({\n                items: this._getSortablePictureList(),\n            });\n        }\n        this.reloadPlayground();\n    }\n\n    _getSortablePictureList() {\n        if (!this.object || !this.object.pictures) {\n            return [];\n        }\n        const id = this.object.id;\n        return this.object.pictures.map((value) => ({\n            key: `${id}-${value.id}`,\n            item: value.view,\n        }));\n    }\n\n    /**\n     * Generate text view.\n     * @param {!Element} textView\n     * @return {Element}\n     */\n    generateTextView(textView) {\n        const that = this;\n        const wrap = Entry.createElement('div').addClass('write_box').appendTo(textView);\n        const writeSet = Entry.createElement('div').addClass('write_set');\n        const inputArea = Entry.createElement('div').addClass('input_box');\n        wrap.appendChild(writeSet);\n        wrap.appendChild(inputArea);\n\n        //write set 글 속성 탭\n        const fontSelect = Entry.createElement('div').addClass('pop_selectbox');\n        const fontLink = Entry.createElement('a', 'entryTextBoxAttrFontName').addClass(\n            'select_link imico_pop_select_arr_down'\n        );\n\n        fontLink.bindOnClick(() => {\n            const options = EntryStatic.fonts\n                .filter((font) => font.visible)\n                .map((font) => [font.name, font, font.style]);\n            fontLink.addClass('imico_pop_select_arr_up');\n            fontLink.removeClass('imico_pop_select_arr_down');\n            this.openDropDown(\n                options,\n                fontLink,\n                (value) => {\n                    let font = value[1];\n                    let textValue = textEditInput.value;\n                    if (that.object.entity.getLineBreak()) {\n                        textValue = textEditArea.value;\n                    }\n                    const { options = {} } = Entry;\n                    const { textOptions = {} } = options;\n                    const { hanjaEnable } = textOptions;\n                    if (!hanjaEnable) {\n                        if (/[\\u4E00-\\u9FFF]/.exec(textValue) != null) {\n                            font = options[0][1];\n                            Entry.modal.alert(Lang.Menus.not_supported_text);\n                        }\n                    }\n                    fontLink.innerText = font.name;\n                    this.textEditArea.style.fontFamily = font.family;\n                    this.textEditInput.style.fontFamily = font.family;\n                    $('#entryTextBoxAttrFontName').data('font', font);\n                    this.object.entity.setFontType(font.family);\n                },\n                () => {\n                    fontLink.removeClass('imico_pop_select_arr_up');\n                    fontLink.addClass('imico_pop_select_arr_down');\n                }\n            );\n        });\n        fontSelect.appendChild(fontLink);\n        writeSet.appendChild(fontSelect);\n\n        //스타일 박스\n        const alignBox = Entry.createElement('div').addClass('font_style_box');\n        writeSet.appendChild(alignBox);\n\n        const alignLeft = Entry.createElement('a')\n            .addClass('style_link imbtn_pop_font_align_left')\n            .bindOnClick(() => {\n                Entry.playground.setFontAlign(Entry.TEXT_ALIGN_LEFT);\n            });\n        alignLeft.setAttribute('title', Lang.Workspace.align_left);\n        alignBox.appendChild(alignLeft);\n        this.alignLeftBtn = alignLeft;\n        const alignMiddle = Entry.createElement('a')\n            .addClass('style_link imbtn_pop_font_align_middle')\n            .bindOnClick(() => {\n                Entry.playground.setFontAlign(Entry.TEXT_ALIGN_CENTER);\n            });\n        alignMiddle.setAttribute('title', Lang.Workspace.align_center);\n        alignBox.appendChild(alignMiddle);\n        this.alignCenterBtn = alignMiddle;\n        const alignRight = Entry.createElement('a')\n            .addClass('style_link imbtn_pop_font_align_right')\n            .bindOnClick(() => {\n                Entry.playground.setFontAlign(Entry.TEXT_ALIGN_RIGHT);\n            });\n        alignRight.setAttribute('title', Lang.Workspace.align_right);\n        alignBox.appendChild(alignRight);\n        this.alignRightBtn = alignRight;\n\n        const styleBox = Entry.createElement('div').addClass('font_style_box');\n        writeSet.appendChild(styleBox);\n\n        const bold = Entry.createElement('a')\n            .addClass('style_link imbtn_pop_font_bold')\n            .bindOnClick((e) => {\n                $(e.currentTarget).toggleClass('on');\n                Entry.playground.object.entity.toggleFontBold();\n                $(this.textEditArea).toggleClass('bold');\n                $(this.textEditInput).toggleClass('bold');\n            });\n        bold.setAttribute('title', Lang.Workspace.bold);\n        styleBox.appendChild(bold);\n\n        const underLine = Entry.createElement('a')\n            .addClass('style_link imbtn_pop_font_underline')\n            .bindOnClick((e) => {\n                const underLineState = !Entry.playground.object.entity.getUnderLine() || false;\n                $(e.currentTarget).toggleClass('on');\n                Entry.playground.object.entity.setUnderLine(underLineState);\n\n                const effect = `${underLineState ? 'underline' : ''} ${\n                    Entry.playground.object.entity.getStrike() ? 'line-through' : ''\n                }`.trim();\n                this.textEditArea.style.textDecoration = effect;\n                this.textEditInput.style.textDecoration = effect;\n            });\n        underLine.setAttribute('title', Lang.Workspace.font_underline);\n        styleBox.appendChild(underLine);\n\n        const italic = Entry.createElement('a')\n            .addClass('style_link imbtn_pop_font_italic')\n            .bindOnClick((e) => {\n                $(e.currentTarget).toggleClass('on');\n                Entry.playground.object.entity.toggleFontItalic();\n                $(this.textEditArea).toggleClass('italic');\n                $(this.textEditInput).toggleClass('italic');\n            });\n        italic.setAttribute('title', Lang.Workspace.font_tilt);\n        styleBox.appendChild(italic);\n\n        const through = Entry.createElement('a')\n            .addClass('style_link imbtn_pop_font_through')\n            .bindOnClick((e) => {\n                $(e.currentTarget).toggleClass('on');\n                const strikeState = !Entry.playground.object.entity.getStrike() || false;\n                Entry.playground.object.entity.setStrike(strikeState);\n\n                const effect = `${strikeState ? 'line-through' : ''} ${\n                    Entry.playground.object.entity.getUnderLine() ? 'underline' : ''\n                }`.trim();\n                this.textEditArea.style.textDecoration = effect;\n                this.textEditInput.style.textDecoration = effect;\n            });\n        through.setAttribute('title', Lang.Workspace.font_cancel);\n        styleBox.appendChild(through);\n\n        const color = Entry.createElement('a').addClass('imbtn_pop_font_color');\n        color.appendChild(Entry.createElement('em'));\n        color.bindOnClick(() =>\n            this.openColourPicker(\n                color,\n                this.object.entity.getColour(),\n                false,\n                this.setTextColour.bind(this)\n            )\n        );\n        color.setAttribute('title', Lang.Workspace.font_color);\n        styleBox.appendChild(color);\n\n        const backgroundColor = Entry.createElement('a').addClass('imbtn_pop_font_backgroundcolor');\n        backgroundColor.setAttribute('title', Lang.Workspace.font_fill);\n        backgroundColor.appendChild(Entry.createElement('em'));\n        backgroundColor.bindOnClick(() =>\n            this.openColourPicker(\n                backgroundColor,\n                this.object.entity.getBGColour(),\n                true,\n                this.setBackgroundColour.bind(this)\n            )\n        );\n        styleBox.appendChild(backgroundColor);\n\n        const writeTypeBox = Entry.createElement('div').addClass('write_type_box');\n        const singleLine = Entry.createElement('a');\n        singleLine.innerText = Lang.Buttons.single_line;\n        singleLine.bindOnClick(() => Entry.playground.toggleLineBreak(false));\n        const multiLine = Entry.createElement('a');\n        multiLine.innerText = Lang.Buttons.multi_line;\n        multiLine.bindOnClick(() => Entry.playground.toggleLineBreak(true));\n        writeTypeBox.appendChild(singleLine);\n        writeTypeBox.appendChild(multiLine);\n        inputArea.appendChild(writeTypeBox);\n\n        //글자 크기 조절 슬라이드.\n        const fontSizeWrapper = Entry.createElement('div').addClass(\n            'entryPlaygroundFontSizeWrapper multi'\n        );\n        inputArea.appendChild(fontSizeWrapper);\n        this.fontSizeWrapper = fontSizeWrapper;\n\n        const fontSizeLabel = Entry.createElement('div').addClass('entryPlaygroundFontSizeLabel');\n        fontSizeLabel.textContent = Lang.General.font_size;\n        fontSizeWrapper.appendChild(fontSizeLabel);\n\n        const fontSizeSlider = Entry.createElement('div').addClass('entryPlaygroundFontSizeSlider');\n        fontSizeWrapper.appendChild(fontSizeSlider);\n\n        const fontSizeIndiciator = Entry.createElement('div').addClass(\n            'entryPlaygroundFontSizeIndicator'\n        );\n        fontSizeSlider.appendChild(fontSizeIndiciator);\n        this.fontSizeIndiciator = fontSizeIndiciator;\n\n        const fontSizeKnob = Entry.createElement('div').addClass('entryPlaygroundFontSizeKnob');\n        fontSizeSlider.appendChild(fontSizeKnob);\n        this.fontSizeKnob = fontSizeKnob;\n\n        $(fontSizeKnob).bind('mousedown.fontKnob touchstart.fontKnob', () => {\n            const resizeOffset = $(fontSizeSlider).offset().left;\n\n            const doc = $(document);\n            doc.bind('mousemove.fontKnob touchmove.fontKnob', onMouseMove);\n            doc.bind('mouseup.fontKnob touchend.fontKnob', onMouseUp);\n\n            function onMouseMove(e) {\n                let x = e.pageX;\n                if (!x) {\n                    x = e.originalEvent.touches[0].pageX;\n                }\n                let left = x - resizeOffset;\n                left = Math.max(left, 5);\n                left = Math.min(left, 136);\n                fontSizeKnob.style.left = `${left}px`;\n                left /= 1.36;\n                fontSizeIndiciator.style.width = `${left}%`;\n                Entry.playground.object.entity.setFontSize(left);\n            }\n\n            function onMouseUp() {\n                $(document).unbind('.fontKnob');\n            }\n        });\n\n        const inputInner = Entry.createElement('div').addClass('input_inner');\n        inputArea.appendChild(inputInner);\n\n        const textEditInput = Entry.createElement('input').addClass(\n            'entryPlayground_textBox single'\n        );\n        textEditInput.type = 'text';\n        textEditInput.placeholder = Lang.Workspace.textbox_input;\n        const textChangeApply = function () {\n            const object = Entry.playground.object;\n            const entity = object.entity;\n            const selected = $('#entryTextBoxAttrFontName').data('font');\n            const defaultFont = EntryStatic.fonts[0];\n            const { options = {} } = Entry;\n            const { textOptions = {} } = options;\n            const { hanjaEnable } = textOptions;\n            if (\n                !hanjaEnable &&\n                (selected.family === 'Nanum Pen Script' || selected.family === 'Jeju Hallasan')\n            ) {\n                if (/[\\u4E00-\\u9FFF]/.exec(this.value) != null) {\n                    $('#entryTextBoxAttrFontName').text(defaultFont.name);\n                    entity.setFontType(defaultFont.family);\n                    Entry.modal.alert(Lang.Menus.not_supported_text);\n                }\n            }\n            object.setText(this.value);\n            entity.setText(this.value);\n        };\n        textEditInput.onkeyup = textChangeApply;\n        textEditInput.onchange = textChangeApply;\n\n        textEditInput.addEventListener('focusin', () => {\n            textEditInput.prevText = textEditInput.value;\n        });\n        textEditInput.onblur = function () {\n            if (textEditInput.value !== textEditInput.prevText) {\n                Entry.do('editText', textEditInput.value, textEditInput.prevText);\n            }\n            // Entry.dispatchEvent('textEdited');\n        };\n        this.textEditInput = textEditInput;\n        inputInner.appendChild(textEditInput);\n\n        const textEditArea = Entry.createElement('textarea');\n        textEditArea.placeholder = Lang.Workspace.textbox_input;\n        textEditArea.addClass('entryPlayground_textArea multi');\n        textEditArea.style.display = 'none';\n        textEditArea.onkeyup = textChangeApply;\n        textEditArea.onchange = textChangeApply;\n\n        textEditArea.addEventListener('focusin', () => {\n            textEditArea.prevText = textEditArea.value;\n        });\n        textEditArea.onblur = function () {\n            if (textEditArea.value !== textEditArea.prevText) {\n                Entry.do('editText', textEditArea.value, textEditArea.prevText);\n            }\n        };\n        this.textEditArea = textEditArea;\n        inputInner.appendChild(textEditArea);\n\n        const singleDesc = Entry.createElement('ul').addClass('list single');\n        singleDesc.appendChild(Entry.createElement('li').text(Lang.Menus.linebreak_off_desc_1));\n        singleDesc.appendChild(Entry.createElement('li').text(Lang.Menus.linebreak_off_desc_2));\n        singleDesc.appendChild(Entry.createElement('li').text(Lang.Menus.linebreak_off_desc_3));\n\n        const multiDesc = Entry.createElement('ul').addClass('list multi');\n        multiDesc.appendChild(Entry.createElement('li').text(Lang.Menus.linebreak_on_desc_1));\n        multiDesc.appendChild(Entry.createElement('li').text(Lang.Menus.linebreak_on_desc_2));\n        multiDesc.appendChild(Entry.createElement('li').text(Lang.Menus.linebreak_on_desc_3));\n\n        inputArea.appendChild(singleDesc);\n        inputArea.appendChild(multiDesc);\n    }\n\n    /**\n     * 소리 편집 기능 신규 개발시 해당 로직 삭제\n     * @private\n     */\n    _createSoundEditView() {\n        const soundEditView = Entry.createElement('div', 'entrySoundEdit').addClass(\n            'entryPlaygroundSoundEdit'\n        );\n\n        return soundEditView;\n    }\n\n    /**\n     * Generate sound view.\n     * default view is shown when object is not selected.\n     * @return {Element}\n     * @param soundView\n     */\n    generateSoundView(soundView) {\n        if (Entry.type === 'workspace') {\n            const soundAdd = Entry.createElement('div', 'entryAddSound');\n            soundAdd.addClass('entryPlaygroundAddSound');\n            const innerSoundAdd = Entry.createElement('div', 'entryAddSoundInner').addClass(\n                'entryPlaygroundAddSoundInner'\n            );\n            innerSoundAdd.bindOnClick(() => {\n                if (!Entry.container || Entry.container.isSceneObjectsExist()) {\n                    Entry.do('playgroundClickAddSound');\n                } else {\n                    Entry.toast.alert(\n                        Lang.Workspace.add_object_alert,\n                        Lang.Workspace.add_object_alert_msg\n                    );\n                }\n            });\n            innerSoundAdd.textContent = Lang.Workspace.sound_add;\n            soundAdd.appendChild(innerSoundAdd);\n            soundView.appendChild(soundAdd);\n            const soundList = Entry.createElement('ul', 'entrySoundList').addClass(\n                'entryPlaygroundSoundList'\n            );\n\n            soundView.appendChild(soundList);\n            this.soundListView_ = soundList;\n            this._soundAddButton = innerSoundAdd;\n\n            const soundEditView = this._createSoundEditView();\n            soundView.appendChild(soundEditView);\n            this.soundEditor = new SoundEditor(soundEditView);\n        }\n    }\n\n    initSortableSoundWidget() {\n        if (this.soundSortableListWidget) {\n            return;\n        }\n\n        this.soundSortableListWidget = new Sortable({\n            data: {\n                height: '100%',\n                sortableTarget: ['entryPlaygroundSoundThumbnail'],\n                lockAxis: 'y',\n                items: this._getSortableSoundList(),\n            },\n            container: this.soundListView_,\n        }).on('change', ([newIndex, oldIndex]) => {\n            Entry.playground.moveSound(newIndex, oldIndex);\n        });\n    }\n\n    updateSoundsView() {\n        if (this.soundSortableListWidget) {\n            this.soundSortableListWidget.setData({\n                items: this._getSortableSoundList(),\n            });\n        }\n\n        this.reloadPlayground();\n    }\n\n    _getSortableSoundList() {\n        if (!this.object || !this.object.sounds) {\n            return [];\n        }\n        const id = this.object.id;\n        return this.object.sounds.map((value) => ({\n            key: `${id}-${value.id}`,\n            item: value.view,\n        }));\n    }\n\n    /**\n     * Inject object\n     * @param {?Entry.EntryObject} object\n     */\n    injectObject(object) {\n        /** @type {Entry.Entryobject} */\n        if (!object) {\n            this.object = null; //[박봉배-2018.11.12] - 아래 위치에 있으면 죽은 object의 메서드를 호출함. 그래서 위로 올림.\n            this.changeViewMode('code');\n            return;\n        }\n        if (object === this.object) {\n            return;\n        }\n\n        this.object = object;\n\n        const objectType = object.objectType;\n        this.setMenu(objectType);\n\n        this.injectCode();\n\n        const { text: textTab, picture: pictureTab } = this.tabViewElements;\n        if (objectType === 'sprite' && Entry.pictureEditable) {\n            if (textTab) {\n                textTab.addClass('entryRemove');\n            }\n            if (pictureTab) {\n                pictureTab.removeClass('entryRemove');\n            }\n        } else if (objectType === 'textBox') {\n            if (pictureTab) {\n                pictureTab.addClass('entryRemove');\n            }\n            if (textTab) {\n                textTab.removeClass('entryRemove');\n            }\n        }\n\n        this.updateObjectTitle(object);\n\n        const viewMode = this.viewMode_;\n        if (viewMode === 'default') {\n            this.changeViewMode('code');\n        } else if (viewMode === 'variable') {\n            this.changeViewMode('variable');\n        } else if ((viewMode === 'picture' || viewMode === 'text') && objectType === 'textBox') {\n            this.changeViewMode('text');\n        } else if ((viewMode === 'text' || viewMode === 'picture') && objectType === 'sprite') {\n            this.changeViewMode('picture');\n        } else if (viewMode === 'sound') {\n            this.changeViewMode('sound');\n        }\n\n        _.result(this.blockMenu, 'clearRendered');\n        this.reloadPlayground();\n    }\n\n    /**\n     * Inject object\n     * @param {?Entry.EntryObject} object\n     */\n    injectEmptyObject() {\n        this.object = null;\n    }\n\n    /**\n     * Inject code\n     */\n    injectCode() {\n        const workspace = Entry.getMainWS();\n        if (!workspace) {\n            return;\n        }\n\n        const object = this.object;\n        const vimBoard = workspace.vimBoard;\n\n        if (vimBoard && Entry.textCodingEnable && !vimBoard._parser._onError) {\n            vimBoard._changedObject = object;\n            vimBoard._currentScene = object.scene;\n        }\n\n        const board = workspace.getBoard();\n        const engine = Entry.engine;\n        workspace.changeBoardCode(\n            object.script,\n            engine && engine.isState('run') ? undefined : board.adjustThreadsPosition.bind(board)\n        );\n    }\n\n    /**\n     * Inject picture\n     */\n    injectPicture(isSelect = true) {\n        const view = this.pictureListView_;\n        if (!view) {\n            return;\n        }\n\n        if (!this.object) {\n            this.painter.lc && this.painter.lc.pointerDown();\n            delete Entry.stage.selectedObject;\n            Entry.dispatchEvent('pictureSelected');\n        } else {\n            (this.object.pictures || []).forEach((picture, i) => {\n                !picture.view && Entry.playground.generatePictureElement(picture);\n                const element = picture.view;\n                element.orderHolder.textContent = i + 1;\n            });\n\n            isSelect && this.selectPicture(this.object.selectedPicture);\n        }\n\n        this.updatePictureView();\n    }\n\n    /**\n     * Add picture\n     * @param {picture model} picture\n     */\n    addPicture(picture, isNew, isSelect = true) {\n        const tempPicture = _.clone(picture);\n\n        if (isNew === true) {\n            delete tempPicture.id;\n        }\n        delete tempPicture.view;\n\n        picture = Entry.Utils.copy(tempPicture);\n        if (!picture.id) {\n            picture.id = Entry.generateHash();\n        }\n\n        picture.name = Entry.getOrderedName(picture.name, this.object.pictures);\n\n        this.generatePictureElement(picture);\n\n        Entry.do('objectAddPicture', picture.objectId || this.object.id, picture, isSelect);\n    }\n\n    /**\n     * set picture\n     * @param {picture}\n     */\n    setPicture(picture) {\n        const element = Entry.container.getPictureElement(picture.id, picture.objectId);\n        const $element = $(element);\n        if (element) {\n            picture.view = element;\n            element.picture = picture;\n\n            const thumbnailView = $element.find(`#t_${picture.id}`)[0];\n            if (picture.thumbUrl || picture.fileurl) {\n                thumbnailView.style.backgroundImage = `url(\"${picture.thumbUrl || picture.fileurl}\")`;\n            } else {\n                // deprecated\n                const fileName = picture.filename;\n                thumbnailView.style.backgroundImage = `url(\"${\n                    Entry.defaultPath\n                }/uploads/${fileName.substring(0, 2)}/${fileName.substring(\n                    2,\n                    4\n                )}/thumb/${fileName}.png\")`;\n            }\n            const sizeView = $element.find(`#s_${picture.id}`)[0];\n            sizeView.textContent = `${picture.dimension.width} X ${picture.dimension.height}`;\n        }\n\n        Entry.container.setPicture(picture);\n        // Entry.playground.object.setPicture(picture);\n    }\n\n    /**\n     * Download a picture\n     * @param {!String} pictureId\n     */\n    downloadPicture(pictureId) {\n        const picture = Entry.playground.object.getPicture(pictureId);\n        const { imageType = 'png' } = picture;\n        Entry.dispatchEvent('downloadPicture', picture);\n    }\n\n    /**\n     * Clone picture\n     * @param {!String} pictureId\n     */\n    clonePicture(pictureId) {\n        const sourcePicture = Entry.playground.object.getPicture(pictureId);\n        this.addPicture(sourcePicture, true);\n    }\n\n    /**\n     * Select picture\n     * @param {picture}\n     */\n    selectPicture(picture, removed) {\n        const pictures = this.object.pictures;\n        for (let i = 0, len = pictures.length; i < len; i++) {\n            const target = pictures[i];\n            const view = target.view;\n            if (target.id === picture.id) {\n                view.addClass('entryPictureSelected');\n            } else {\n                view.removeClass('entryPictureSelected');\n            }\n        }\n\n        let objectId_;\n        if (picture && picture.id) {\n            objectId_ = Entry.container.selectPicture(picture.id, picture.objectId);\n        }\n\n        if (this.object.id === objectId_) {\n            if (!picture.objectId) {\n                picture.objectId = this.object.id;\n            }\n            Entry.dispatchEvent('pictureSelected', picture, removed);\n        }\n\n        this.updateObjectTitle(this.object);\n    }\n\n    /**\n     * Move picture in this.object.pictures\n     * this method is for sortable\n     * @param {!number} start\n     * @param {!number} end\n     */\n    movePicture(start, end) {\n        this.object.pictures.splice(end, 0, this.object.pictures.splice(start, 1)[0]);\n        this.injectPicture();\n    }\n\n    /**\n     * Inject text\n     */\n    injectText() {\n        const object = this.object;\n\n        if (!object) {\n            return;\n        }\n        const entity = object.entity;\n\n        const text = entity.getText();\n        this.textEditInput.value = text;\n        this.textEditArea.value = text;\n\n        const font = EntryStatic.fonts\n            .filter((font) => font.visible)\n            .find((font) => font.family === entity.getFontName());\n        if (font) {\n            $('#entryText #entryTextBoxAttrFontName').text(font.name);\n            $('#entryText #entryTextBoxAttrFontName').data('font', font);\n            this.textEditInput.style.fontFamily = font.family;\n            this.textEditArea.style.fontFamily = font.family;\n        } else {\n            $('#entryText #entryTextBoxAttrFontName').text('');\n            $('#entryText #entryTextBoxAttrFontName').data('font', EntryStatic.fonts[0]);\n        }\n\n        if (entity.colour) {\n            this.setTextColour(entity.colour, true);\n        }\n        if (entity.bgColor) {\n            this.setBackgroundColour(entity.bgColor, true);\n        }\n\n        this.setTextBold(entity.fontBold);\n        this.setTextItalic(entity.fontItalic);\n        this.setTextDecoration(entity);\n        this.toggleLineBreak(entity.getLineBreak());\n\n        if (entity.getLineBreak()) {\n            const LANG = Lang.Menus;\n            $('.entryPlaygroundLinebreakDescription > p').html(LANG.linebreak_on_desc_1);\n            const pDoms = $('.entryPlaygroundLinebreakDescription > ul > li');\n            pDoms.eq(0).text(LANG.linebreak_on_desc_2);\n            pDoms.eq(1).text(LANG.linebreak_on_desc_3);\n            this._setFontFontUI();\n        }\n\n        this.setFontAlign(entity.getTextAlign());\n        Entry.stage.updateForce();\n    }\n\n    _setFontFontUI() {\n        const fontSize = this.object.entity.getFontSize();\n        this.fontSizeIndiciator.style.width = `${fontSize}%`;\n        this.fontSizeKnob.style.left = `${fontSize * 1.36}px`;\n    }\n\n    /**\n     * Inject sound\n     */\n    injectSound(isSelect = true) {\n        const view = this.soundListView_;\n        if (!view) {\n            return;\n        }\n\n        if (!this.object) {\n            delete Entry.stage.selectedObject;\n        } else {\n            (this.object.sounds || []).forEach((sound, i) => {\n                const soundLengthView = _get(sound, 'view.soundLengthView');\n                if (soundLengthView) {\n                    soundLengthView.textContent = `${sound.duration} ${Lang.General.second}`;\n                } else {\n                    Entry.playground.generateSoundElement(sound);\n                }\n\n                const element = sound.view;\n                element.orderHolder.textContent = i + 1;\n            });\n\n            if (isSelect) {\n                if (this.object.selectedSound) {\n                    this.selectSound(this.object.selectedSound);\n                } else {\n                    this.unselectSound();\n                }\n            }\n        }\n\n        this.updateSoundsView();\n    }\n\n    /**\n     * Move sound in this.object.sounds\n     * this method is for sortable\n     * @param {!number} start\n     * @param {!number} end\n     */\n    moveSound(start, end) {\n        if (this.object.sounds) {\n            this.object.sounds.splice(end, 0, this.object.sounds.splice(start, 1)[0]);\n            this.injectSound();\n        }\n    }\n\n    addHardwareLiteModule(module) {\n        Entry.hwLite.addHardwareLiteModule(module);\n    }\n\n    removeHardwareLiteModule() {\n        Entry.hwLite.removeHardwareLiteModule();\n    }\n\n    addExpansionBlocks(items) {\n        Entry.expansion.addExpansionBlocks(items.map(({ name }) => name));\n    }\n\n    removeExpansionBlocks(items) {\n        Entry.expansion.banExpansionBlocks(items.map(({ name }) => name));\n    }\n\n    addAIUtilizeBlocks(items) {\n        Entry.aiUtilize.addAIUtilizeBlocks(items.map(({ name }) => name));\n    }\n\n    removeAIUtilizeBlocks(items) {\n        Entry.aiUtilize.banAIUtilizeBlocks(items.map(({ name }) => name));\n    }\n\n    setAiLearningBlock(data) {\n        Entry.aiLearning.removeLearningBlocks();\n        Entry.aiLearning.load({ ...data });\n    }\n\n    /**\n     * Add sound\n     * @param {sound model} sound\n     * @param {boolean} NotForView if this is true, add element into object also.\n     */\n    addSound(sound, NotForView, isNew, isSelect = true) {\n        const tempSound = _.clone(sound);\n        delete tempSound.view;\n        if (isNew === true) {\n            delete tempSound.id;\n        }\n\n        sound = Entry.Utils.copy(tempSound);\n        if (!sound.id) {\n            sound.id = Entry.generateHash();\n        }\n        sound.name = Entry.getOrderedName(sound.name, this.object.sounds);\n\n        this.generateSoundElement(sound);\n        Entry.do('objectAddSound', sound.objectId || this.object.id, sound, isSelect);\n    }\n\n    downloadSound(soundId) {\n        const sound = Entry.playground.object.getSound(soundId);\n        Entry.dispatchEvent('downloadSound', sound);\n    }\n\n    /**\n     * select view mode\n     * @param {string} viewType\n     */\n    changeViewMode(viewType) {\n        if (!this.tabViewElements) {\n            return;\n        }\n\n        for (const i in this.tabViewElements) {\n            this.tabViewElements[i].removeClass('entryTabSelected');\n        }\n        if (viewType !== 'default') {\n            this.tabViewElements[viewType].addClass('entryTabSelected');\n        }\n        if (viewType === 'variable') {\n            Entry.playground.toggleOnVariableView();\n            this.tabViewElements.code.removeClass('entryTabSelected');\n            this.tabViewElements[viewType].addClass('entryTabSelected');\n            this.resizeHandle_.removeClass('unfolding');\n            this.resizeHandle_.addClass('entryRemove');\n            this.boardView_.addClass('wideView');\n            Entry.windowResized.notify();\n            return;\n        } else {\n            this.resizeHandle_.removeClass('entryRemove');\n            this.boardView_.removeClass('wideView');\n            Entry.windowResized.notify();\n        }\n        const views = this.view_.children;\n        for (let i = 0; i < views.length; i++) {\n            const view = views[i];\n            if (view.id.toUpperCase().indexOf(viewType.toUpperCase()) > -1) {\n                view.removeClass('entryRemove');\n            } else {\n                view.addClass('entryRemove');\n            }\n        }\n\n        if (Entry.pictureEditable) {\n            if (viewType === 'picture') {\n                this.painter.show();\n                this.initSortablePictureWidget();\n                if (!this.pictureView_.object || this.pictureView_.object != this.object) {\n                    this.pictureView_.object = this.object;\n                    this.injectPicture();\n                } else if (\n                    this.object &&\n                    this.pictureListView_ &&\n                    !this.pictureListView_.hasChildNodes()\n                ) {\n                    const pictures = this.object.pictures;\n                    if (pictures && pictures.length) {\n                        this.injectPicture();\n                    }\n                }\n            } else {\n                this.painter.hide();\n            }\n        }\n\n        if (Entry.soundEditable) {\n            if (viewType === 'sound') {\n                this.initSortableSoundWidget();\n                if (!this.soundView_.object || this.soundView_.object != this.object) {\n                    this.soundView_.object = this.object;\n                    this.injectSound();\n                } else if (\n                    this.object &&\n                    this.soundListView_ &&\n                    !this.soundListView_.hasChildNodes()\n                ) {\n                    const sounds = this.object.sounds;\n                    if (sounds && sounds.length) {\n                        this.injectSound();\n                    }\n                }\n            } else {\n                this.soundEditor.hide();\n            }\n        }\n\n        if (\n            (viewType === 'text' && this.object.objectType === 'textBox') ||\n            this.textView_.object != this.object\n        ) {\n            this.textView_.object = this.object;\n            this.injectText();\n        }\n\n        if (viewType === 'code') {\n            this.resizeHandle_ && this.resizeHandle_.removeClass('entryRemove');\n            this.tabButtonView_ && this.tabButtonView_.addClass('entryCode');\n            this.blockMenu.reDraw();\n        } else {\n            this.tabButtonView_ && this.tabButtonView_.removeClass('entryCode');\n        }\n\n        if (Entry.engine.isState('run')) {\n            this.curtainView_.removeClass('entryRemove');\n        }\n        this.viewMode_ = viewType;\n        this.selectedViewMode = viewType;\n        this.toggleOffVariableView();\n    }\n\n    /**\n     * render variable view\n     * @return {!Element}\n     */\n    createVariableView() {\n        const view = Entry.createElement('div');\n        if (!Entry.type || Entry.type === 'workspace') {\n            view.addClass('entryVariablePanelWorkspace');\n        } else if (Entry.type === 'phone') {\n            view.addClass('entryVariablePanelPhone');\n        }\n        this.variableViewWrapper_ = view;\n        Entry.variableContainer.createDom(view);\n        return view;\n    }\n\n    /**\n     * toggle on variable view\n     */\n    toggleOnVariableView() {\n        Entry.playground.changeViewMode('code');\n        this.hideBlockMenu();\n        this.variableView_.removeClass('entryRemove');\n        this.resizeHandle_.removeClass('entryRemove');\n        this.viewMode_ = 'variable';\n        this.selectedViewMode = 'variable';\n    }\n\n    toggleOffVariableView() {\n        this.showBlockMenu();\n        this.variableView_.addClass('entryRemove');\n    }\n\n    /**\n     * Generate category menu with object type.\n     * @param {!string} objectType\n     */\n    setMenu(objectType) {\n        if (this.currentObjectType == objectType) {\n            return;\n        }\n\n        const blockMenu = this.blockMenu;\n        blockMenu.unbanClass(this.currentObjectType, true);\n        blockMenu.banClass(objectType, true);\n        blockMenu.setMenu(true);\n        this.currentObjectType = objectType;\n    }\n\n    hideTabs() {\n        ['picture', 'text', 'sound', 'variable'].forEach(this.hideTab.bind(this));\n    }\n\n    hideTab(item) {\n        if (this.tabViewElements[item]) {\n            this.tabViewElements[item].addClass('hideTab');\n            this.tabViewElements[item].removeClass('showTab');\n        }\n    }\n\n    showTabs() {\n        ['picture', 'text', 'sound', 'variable'].forEach(this.showTab.bind(this));\n    }\n\n    showTab(item) {\n        if (this.tabViewElements[item]) {\n            this.tabViewElements[item].addClass('showTab');\n            this.tabViewElements[item].removeClass('hideTab');\n        }\n    }\n\n    /**\n     * Reload playground\n     */\n    reloadPlayground() {\n        const engine = Entry.engine;\n\n        if (engine && engine.isState('run')) {\n            return;\n        }\n        _.result(this.mainWorkspace, 'dReDraw');\n    }\n\n    /**\n     * flush playground when object is not exist\n     */\n    flushPlayground() {\n        this.object = null;\n        if (Entry.playground && Entry.playground.view_) {\n            this.injectPicture();\n            this.injectSound();\n\n            const mainWS = Entry.getMainWS();\n            if (mainWS) {\n                const board = mainWS.getBoard();\n                board.clear();\n                board.changeCode(null);\n            }\n        }\n    }\n\n    refreshPlayground() {\n        if (Entry.playground && Entry.playground.view_) {\n            if (this.getViewMode() === 'picture') {\n                this.injectPicture();\n            }\n            if (this.getViewMode() === 'sound') {\n                this.injectSound();\n            }\n        }\n    }\n\n    clear() {\n        this.flushPlayground();\n        if (this.painter) {\n            this.painter.clear();\n        }\n    }\n\n    nameViewBlur() {\n        if (!Entry.playground.nameViewFocus) {\n            return;\n        }\n        if (this.nameView.value.trim() === '') {\n            Entry.modal.alert(Lang.Workspace.enter_the_name).then(() => {\n                this.nameView.focus();\n            });\n            return true;\n        }\n\n        let nameViewArray = $('.entryPlaygroundPictureName');\n        if (nameViewArray.length !== Entry.playground.object.pictures.length) {\n            nameViewArray = nameViewArray.slice(0, -1); // pop last element (드래그 시 발생하는 임시 엘리먼트임)\n        }\n\n        for (let i = 0; i < nameViewArray.length; i++) {\n            if (\n                nameViewArray.eq(i).val() == this.nameView.value &&\n                nameViewArray[i] != this.nameView\n            ) {\n                Entry.modal.alert(Lang.Workspace.name_already_exists).then(() => {\n                    this.nameView.focus();\n                });\n                return true;\n            }\n        }\n        const newValue = this.nameView.value;\n        this.nameView.picture.name = newValue;\n        const playground = Entry.playground;\n        if (playground) {\n            if (playground.object) {\n                const pic = playground.object.getPicture(this.nameView.picture.id);\n                if (pic) {\n                    pic.name = newValue;\n                }\n            }\n            const painter = playground.painter;\n            if (painter && painter.file) {\n                painter.file.name = newValue;\n            }\n\n            playground.reloadPlayground();\n        }\n        Entry.dispatchEvent('pictureNameChanged', this.nameView.picture);\n        Entry.playground.nameViewFocus = false;\n    }\n\n    isDuplicatedTableName(name, selectedIndex = -1) {\n        let nameViewArray = $('.entryPlaygroundTableName');\n        if (nameViewArray.length !== Entry.playground.dataTable.tables.length) {\n            nameViewArray = nameViewArray.slice(0, -1);\n        }\n\n        for (let i = 0; i < nameViewArray.length; i++) {\n            if (nameViewArray.eq(i).val() == name && i != selectedIndex) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    generatePictureElement(picture) {\n        const element = Entry.createElement('li', picture.id)\n            .addClass('entryPlaygroundPictureElement')\n            .bindOnClick(function () {\n                Entry.playground.selectPicture(this.picture);\n            });\n        picture.view = element;\n        element.picture = picture;\n\n        Entry.Utils.disableContextmenu(picture.view);\n        Entry.ContextMenu.onContextmenu(picture.view, (coordinate) => {\n            const options = [\n                {\n                    text: Lang.Workspace.context_rename,\n                    callback() {\n                        nameView.focus();\n                    },\n                },\n                {\n                    text: Lang.Workspace.context_duplicate,\n                    callback() {\n                        Entry.playground.clonePicture(picture.id);\n                    },\n                },\n                {\n                    text: Lang.Workspace.context_remove,\n                    callback() {\n                        Entry.playground._removePicture(picture, element);\n                    },\n                },\n                {\n                    text: Lang.Workspace.context_download_image,\n                    callback() {\n                        Entry.playground.downloadPicture(picture.id);\n                    },\n                },\n            ];\n            Entry.ContextMenu.show(options, 'workspace-contextmenu', coordinate);\n        });\n\n        element.orderHolder = Entry.createElement('div')\n            .addClass('entryPlaygroundPictureOrder')\n            .appendTo(element);\n\n        const thumbnailView = Entry.createElement('div', `t_${picture.id}`).addClass(\n            'entryPlaygroundPictureThumbnail'\n        );\n\n        let mouseDownCoordinate;\n        const moveThreshold = 5;\n        thumbnailView.addEventListener('touchstart', (e) => {\n            const event = Entry.Utils.convertMouseEvent(e);\n            mouseDownCoordinate = { y: event.clientY };\n        });\n\n        thumbnailView.addEventListener('touchmove', (e) => {\n            e.preventDefault();\n            const event = Entry.Utils.convertMouseEvent(e);\n            if (Math.abs(event.clientY - mouseDownCoordinate.y) > moveThreshold) {\n                Entry.ContextMenu.hide();\n            }\n        });\n\n        if (picture.thumbUrl || picture.fileurl) {\n            thumbnailView.style.backgroundImage = `url(\"${picture.thumbUrl || picture.fileurl}\")`;\n        } else {\n            // deptecated\n            const fileName = picture.filename;\n            thumbnailView.style.backgroundImage = `url(\"${\n                Entry.defaultPath\n            }/uploads/${fileName.substring(0, 2)}/${fileName.substring(\n                2,\n                4\n            )}/thumb/${fileName}.png\")`;\n        }\n        element.appendChild(thumbnailView);\n        const nameView = Entry.createElement('input')\n            .addClass('entryPlaygroundPictureName')\n            .addClass('entryEllipsis');\n        nameView.picture = picture;\n        nameView.value = picture.name;\n        Entry.attachEventListener(nameView, 'blur', this.nameViewBlur.bind(this));\n        Entry.attachEventListener(nameView, 'focus', (e) => {\n            this.nameView = e.target;\n            this.nameViewFocus = true;\n        });\n\n        nameView.onkeypress = Entry.Utils.blurWhenEnter;\n        element.appendChild(nameView);\n        Entry.createElement('div', `s_${picture.id}`)\n            .addClass('entryPlaygroundPictureSize')\n            .appendTo(element).textContent =\n            `${picture.dimension.width} X ${picture.dimension.height}`;\n\n        const removeButton = Entry.createElement('div').addClass('entryPlayground_del');\n        const { Buttons = {} } = Lang || {};\n        const { delete: delText = '삭제' } = Buttons;\n        removeButton.appendTo(element).innerText = delText;\n        removeButton.bindOnClick((e) => {\n            try {\n                e.stopPropagation();\n                this._removePicture(picture, element);\n            } catch (e) {\n                Entry.toast.alert(\n                    Lang.Workspace.shape_remove_fail,\n                    Lang.Workspace.shape_remove_fail_msg\n                );\n            }\n        });\n    }\n\n    _removePicture(picture, element) {\n        if (Entry.playground.object.pictures.length > 1) {\n            Entry.do('objectRemovePicture', picture.objectId, picture);\n            Entry.removeElement(element);\n            Entry.toast.success(\n                Lang.Workspace.shape_remove_ok,\n                `${picture.name} ${Lang.Workspace.shape_remove_ok_msg}`\n            );\n        } else {\n            Entry.toast.alert(\n                Lang.Workspace.shape_remove_fail,\n                Lang.Workspace.shape_remove_fail_msg\n            );\n        }\n    }\n\n    generateSoundElement(sound) {\n        const element = Entry.createElement('sound', sound.id).addClass(\n            'entryPlaygroundSoundElement'\n        );\n        sound.view = element;\n        element.sound = sound;\n\n        Entry.Utils.disableContextmenu(sound.view);\n        Entry.ContextMenu.onContextmenu(sound.view, (coordinate) => {\n            const options = [\n                {\n                    text: Lang.Workspace.context_rename,\n                    callback() {\n                        nameView.focus();\n                    },\n                },\n                {\n                    text: Lang.Workspace.context_duplicate,\n                    callback() {\n                        const newSound = Entry.playground.object.getSound(sound.id);\n                        Entry.playground.addSound(newSound, true, true);\n                    },\n                },\n                {\n                    text: Lang.Workspace.context_remove,\n                    callback() {\n                        const result = Entry.do(\n                            'objectRemoveSound',\n                            Entry.playground.object.id,\n                            sound\n                        );\n                        if (result) {\n                            Entry.removeElement(element);\n                            Entry.dispatchEvent('removeSound', sound);\n                            Entry.toast.success(\n                                Lang.Workspace.sound_remove_ok,\n                                `${sound.name} ${Lang.Workspace.sound_remove_ok_msg}`\n                            );\n                        } else {\n                            Entry.toast.alert(Lang.Workspace.sound_remove_fail, '');\n                        }\n                        Entry.removeElement(element);\n                    },\n                },\n                {\n                    text: Lang.Workspace.context_download_sound,\n                    callback() {\n                        Entry.playground.downloadSound(sound.id);\n                    },\n                },\n            ];\n            Entry.ContextMenu.show(options, 'workspace-contextmenu', coordinate);\n        });\n\n        element.orderHolder = Entry.createElement('div')\n            .addClass('entryPlaygroundSoundOrder')\n            .appendTo(element);\n\n        const thumbnailView = Entry.createElement('div')\n            .addClass('entryPlaygroundSoundThumbnail entryPlaygroundSoundPlay')\n            .appendTo(element);\n        let isPlaying = false;\n        let soundInstance;\n\n        element.bindOnClick(() => {\n            if (!this.object.sounds || !this.object.sounds.length) {\n                return;\n            }\n            const isExist = this.object.sounds.some((os) => os.id === sound.id);\n            if (isExist) {\n                this.selectSound(sound);\n            }\n        });\n\n        let mouseDownCoordinate;\n        const moveThreshold = 5;\n        thumbnailView.addEventListener('touchstart', (e) => {\n            const event = Entry.Utils.convertMouseEvent(e);\n            mouseDownCoordinate = { y: event.clientY };\n        });\n\n        thumbnailView.addEventListener('touchmove', (e) => {\n            e.preventDefault();\n            const event = Entry.Utils.convertMouseEvent(e);\n            if (Math.abs(event.clientY - mouseDownCoordinate.y) > moveThreshold) {\n                Entry.ContextMenu.hide();\n            }\n        });\n\n        thumbnailView.bindOnClick(() => {\n            this.selectSound(sound);\n\n            if (isPlaying) {\n                isPlaying = false;\n                thumbnailView.removeClass('entryPlaygroundSoundStop');\n                thumbnailView.addClass('entryPlaygroundSoundPlay');\n                soundInstance.dispatchEvent('complete');\n                soundInstance.stop();\n                return;\n            } else {\n                isPlaying = true;\n                thumbnailView.removeClass('entryPlaygroundSoundPlay');\n                thumbnailView.addClass('entryPlaygroundSoundStop');\n                soundInstance = Entry.Utils.playSound(sound.id);\n                Entry.Utils.addSoundInstances(soundInstance);\n            }\n\n            soundInstance.addEventListener('complete', () => {\n                thumbnailView.removeClass('entryPlaygroundSoundStop');\n                thumbnailView.addClass('entryPlaygroundSoundPlay');\n                isPlaying = false;\n            });\n        });\n\n        const nameView = Entry.createElement('input')\n            .addClass('entryPlaygroundSoundName')\n            .appendTo(element);\n        nameView.sound = sound;\n        nameView.value = sound.name;\n\n        Entry.attachEventListener(nameView, 'blur', nameViewBlur);\n\n        function nameViewBlur() {\n            if (this.value.trim() === '') {\n                return Entry.modal.alert(Lang.Workspace.enter_the_name).then(() => {\n                    nameView.focus();\n                });\n            }\n\n            let nameViewArray = $('.entryPlaygroundSoundName');\n            if (nameViewArray.length !== Entry.playground.object.sounds.length) {\n                nameViewArray = nameViewArray.slice(0, -1); // pop last element (드래그 시 발생하는 임시 엘리먼트임)\n            }\n\n            for (let i = 0; i < nameViewArray.length; i++) {\n                if (nameViewArray.eq(i).val() == nameView.value && nameViewArray[i] != this) {\n                    return Entry.modal.alert(Lang.Workspace.name_already_exists).then(() => {\n                        nameView.focus();\n                    });\n                }\n            }\n            const newValue = this.value;\n            this.sound.name = newValue;\n            Entry.playground.reloadPlayground();\n        }\n\n        nameView.onkeypress = Entry.Utils.blurWhenEnter;\n        const soundLengthView = Entry.createElement('div')\n            .addClass('entryPlaygroundSoundLength')\n            .appendTo(element);\n        soundLengthView.textContent = `${sound.duration} ${Lang.General.second}`;\n        element.soundLengthView = soundLengthView;\n        const removeButton = Entry.createElement('div').addClass('entryPlayground_del');\n        const { Buttons = {} } = Lang || {};\n        const { delete: delText = '삭제' } = Buttons;\n        removeButton.appendTo(element).innerText = delText;\n        removeButton.bindOnClick(() => {\n            try {\n                Entry.Utils.forceStopSounds();\n                const result = Entry.do('objectRemoveSound', Entry.playground.object.id, sound);\n                if (result) {\n                    Entry.dispatchEvent('removeSound', sound);\n                    Entry.toast.success(\n                        Lang.Workspace.sound_remove_ok,\n                        `${sound.name} ${Lang.Workspace.sound_remove_ok_msg}`\n                    );\n                } else {\n                    Entry.toast.alert(Lang.Workspace.sound_remove_fail, '');\n                }\n                Entry.removeElement(element);\n            } catch (e) {\n                Entry.toast.alert(Lang.Workspace.sound_remove_fail, '');\n            }\n        });\n    }\n\n    openDropDown = (options, target, callback, closeCallback) => {\n        const containers = $('.entry-widget-dropdown');\n        if (containers.length > 0) {\n            closeCallback();\n            return containers.remove();\n        }\n\n        const container = Entry.Dom('div', {\n            class: 'entry-widget-dropdown',\n            parent: $('body'),\n        })[0];\n\n        const dropdownWidget = new Dropdown({\n            data: {\n                items: options,\n                positionDom: target,\n                outsideExcludeDom: [target],\n                onOutsideClick: () => {\n                    if (dropdownWidget) {\n                        closeCallback();\n                        dropdownWidget.hide();\n                        dropdownWidget.remove();\n                    }\n                    if (container) {\n                        container.remove();\n                    }\n                },\n            },\n            container,\n        }).on('select', (item) => {\n            callback(item);\n            closeCallback();\n            dropdownWidget.hide();\n        });\n        return dropdownWidget;\n    };\n\n    openColourPicker = (target, color, canTransparent, callback) => {\n        const containers = $('.entry-color-picker');\n        if (containers.length > 0) {\n            $(target).removeClass('on');\n            return containers.remove();\n        }\n        const container = Entry.Dom('div', {\n            class: 'entry-color-picker',\n            parent: $('body'),\n        })[0];\n        $(target).addClass('on');\n        const colorPicker = new ColorPicker({\n            data: {\n                color,\n                positionDom: target,\n                canTransparent,\n                outsideExcludeDom: [target],\n                onOutsideClick: (color) => {\n                    if (colorPicker) {\n                        $(target).removeClass('on');\n                        colorPicker.hide();\n                        colorPicker.remove();\n                    }\n\n                    if (container) {\n                        container.remove();\n                    }\n                },\n            },\n            container,\n        }).on('change', (color) => {\n            if (color) {\n                callback(color, true);\n            }\n        });\n        return colorPicker;\n    };\n\n    selectSound(sound) {\n        this.object.sounds.forEach((item) => {\n            if (item.id !== sound.id) {\n                item.view.removeClass('entrySoundSelected');\n            } else {\n                item.view.addClass('entrySoundSelected');\n            }\n        });\n\n        let objectId_;\n        if (sound && sound.id) {\n            objectId_ = Entry.container.selectSound(sound.id, sound.objectId);\n        }\n\n        if (this.object.id === objectId_) {\n            if (!sound.objectId) {\n                sound.objectId = this.object.id;\n            }\n            Entry.dispatchEvent('soundSelected', sound, this.object);\n        }\n    }\n\n    unselectSound() {\n        Entry.dispatchEvent('soundUnselected');\n    }\n\n    setTextColour(colour) {\n        $('.imbtn_pop_font_color em').css('background-color', colour);\n        this.object.entity.setColour(colour);\n        this.textEditArea.style.color = colour;\n        this.textEditInput.style.color = colour;\n    }\n\n    setTextBold(bold) {\n        $('.style_link.imbtn_pop_font_bold').toggleClass('on', bold);\n        $(this.textEditInput).removeClass('bold');\n        $(this.textEditArea).removeClass('bold');\n        if (bold) {\n            $(this.textEditInput).addClass('bold');\n            $(this.textEditArea).addClass('bold');\n        }\n    }\n\n    setTextItalic(fontItalic) {\n        $('.style_link.imbtn_pop_font_italic').toggleClass('on', fontItalic);\n        $(this.textEditInput).removeClass('italic');\n        $(this.textEditArea).removeClass('italic');\n        if (fontItalic) {\n            $(this.textEditInput).addClass('italic');\n            $(this.textEditArea).addClass('italic');\n        }\n    }\n\n    setTextDecoration(entity) {\n        $('.style_link.imbtn_pop_font_underline').toggleClass('on', entity.getUnderLine());\n        $('.style_link.imbtn_pop_font_through').toggleClass('on', entity.getStrike());\n        const effect = `${entity.getStrike() ? 'line-through' : ''} ${\n            entity.getUnderLine() ? 'underline' : ''\n        }`.trim();\n        this.textEditArea.style.textDecoration = effect;\n        this.textEditInput.style.textDecoration = effect;\n    }\n\n    setBackgroundColour(colour) {\n        $('.imbtn_pop_font_backgroundcolor em').css('background-color', colour);\n        $('.imbtn_pop_font_backgroundcolor').toggleClass(\n            'clear',\n            colour === 'transparent' || colour === '#ffffff'\n        );\n        this.object.entity.setBGColour(colour);\n        this.textEditArea.style.backgroundColor = colour;\n        this.textEditInput.style.backgroundColor = colour;\n    }\n\n    isTextBGMode() {\n        return this.isTextBGMode_;\n    }\n\n    checkVariables() {\n        if (Entry.forEBS) {\n            return;\n        }\n        const blockMenu = this.blockMenu;\n        const { lists_, variables_ } = Entry.variableContainer;\n\n        if (lists_.length) {\n            blockMenu.unbanClass('listNotExist');\n        } else {\n            blockMenu.banClass('listNotExist');\n        }\n\n        if (variables_.length) {\n            blockMenu.unbanClass('variableNotExist');\n        } else {\n            blockMenu.banClass('variableNotExist');\n        }\n    }\n\n    getViewMode() {\n        return this.viewMode_;\n    }\n\n    banExpansionBlock() {\n        const blockMenu = _.result(this.mainWorkspace, 'blockMenu');\n        if (!blockMenu) {\n            return;\n        }\n\n        Object.values(Entry.EXPANSION_BLOCK_LIST).forEach((block) => {\n            blockMenu.banClass(block.name, true);\n            blockMenu.banClass(`${block.name}_legacy`, true);\n        });\n    }\n\n    banAIUtilizeBlock() {\n        const blockMenu = _.result(this.mainWorkspace, 'blockMenu');\n        if (!blockMenu) {\n            return;\n        }\n\n        Object.values(Entry.ALL_AI_UTILIZE_BLOCK_LIST).forEach((block) => {\n            blockMenu.banClass(block.name, true);\n            blockMenu.banClass(`${block.name}_legacy`, true);\n        });\n    }\n\n    banHardwareLiteBlock() {\n        const blockMenu = _.result(this.mainWorkspace, 'blockMenu');\n        if (!blockMenu) {\n            return;\n        }\n\n        Object.values(Entry.HARDWARE_LITE_LIST).forEach((block) => {\n            blockMenu.banClass(block.name, true);\n            blockMenu.banClass(`${block.name}_legacy`, true);\n            blockMenu.banClass(`${block.name.toLowerCase()}`, true);\n        });\n    }\n\n    toggleLineBreak(isLineBreak) {\n        const { objectType, entity } = this.object || {};\n        if (objectType !== 'textBox') {\n            return;\n        }\n\n        $('.write_type_box a').removeClass('on');\n        if (isLineBreak) {\n            entity.setLineBreak(true);\n            $('.input_inner').height('228px');\n            $('.write_type_box a').eq(1).addClass('on');\n            $('.input_box .single').hide();\n            $('.input_box .multi').show();\n            this._setFontFontUI();\n        } else {\n            entity.setLineBreak(false);\n            $('.input_inner').height('40px');\n            $('.write_type_box a').eq(0).addClass('on');\n            $('.input_box .multi').hide();\n            $('.input_box .single').show();\n        }\n    }\n\n    setFontAlign(fontAlign) {\n        if (this.object.objectType !== 'textBox') {\n            return;\n        }\n        this.alignLeftBtn.removeClass('on');\n        this.alignCenterBtn.removeClass('on');\n        this.alignRightBtn.removeClass('on');\n        switch (fontAlign) {\n            case Entry.TEXT_ALIGN_LEFT:\n                this.alignLeftBtn.addClass('on');\n                break;\n            case Entry.TEXT_ALIGN_CENTER:\n                this.alignCenterBtn.addClass('on');\n                break;\n            case Entry.TEXT_ALIGN_RIGHT:\n                this.alignRightBtn.addClass('on');\n                break;\n        }\n        this.object.entity.setTextAlign(fontAlign);\n    }\n\n    showPictureCurtain() {\n        this.pictureCurtainView_ && this.pictureCurtainView_.removeClass('entryRemove');\n    }\n\n    hidePictureCurtain() {\n        this.pictureCurtainView_ && this.pictureCurtainView_.addClass('entryRemove');\n    }\n\n    hideBlockMenu() {\n        this.mainWorkspace.getBlockMenu().hide();\n    }\n\n    showBlockMenu() {\n        this.mainWorkspace.getBlockMenu().show();\n    }\n\n    getDom(query) {\n        if (query.length) {\n            switch (query.shift()) {\n                case 'tabViewElements':\n                    return this.tabViewElements[query.shift()];\n                case 'blockMenu':\n                    return this.blockMenu.getDom(query);\n                case 'board':\n                case 'overlayBoard':\n                    return this.mainWorkspace.getCurrentBoard().getDom(query);\n                case 'pictureAddButton':\n                    return this._pictureAddButton;\n                case 'soundAddButton':\n                    return this._soundAddButton;\n            }\n        } else {\n        }\n    }\n\n    applyTabOption() {\n        this.textboxTab.addClass('entryRemove');\n        this.pictureTab.addClass('entryRemove');\n        this.soundTab.addClass('entryRemove');\n        this.variableTab.addClass('entryRemove');\n        if (Entry.pictureEditable) {\n            this.pictureTab.removeClass('entryRemove');\n            this.textboxTab.removeClass('entryRemove');\n        }\n        if (Entry.soundEditable) {\n            this.soundTab.removeClass('entryRemove');\n        }\n        if (Entry.hasVariableManager) {\n            this.variableTab.removeClass('entryRemove');\n        }\n    }\n\n    updateObjectTitle(object) {\n        if (this.board) {\n            this.board.updateObjectTitle(object);\n        }\n    }\n\n    updateSelectedObjectTitle() {\n        if (\n            this.board &&\n            Entry.container.selectedObject &&\n            this.board.workspace.getMode() === Entry.Workspace.MODE_BOARD\n        ) {\n            this.board.updateObjectTitle(Entry.container.selectedObject);\n            Entry.Utils.doCodeChange();\n        }\n    }\n\n    setSound(sound) {\n        const objectSound = Entry.container.setSound(sound);\n        if (objectSound?.view) {\n            objectSound.view.sound = objectSound;\n        }\n        const soundLengthView = _get(objectSound, 'view.soundLengthView');\n        if (soundLengthView) {\n            soundLengthView.textContent = `${objectSound.duration} ${Lang.General.second}`;\n        }\n        return objectSound;\n    }\n\n    destroy() {\n        this.commentToggleButton_ && this.commentToggleButton_.unBindOnClick();\n        this.addCommentButton_ && this.addCommentButton_.unBindOnClick();\n        this.backPackButton_ && this.backPackButton_.unBindOnClick();\n        this.blockBackPackEvent && this.blockBackPackEvent.off();\n        this.blockBackPackAreaEvent && this.blockBackPackAreaEvent.off();\n        this.objectBackPackEvent && this.objectBackPackEvent.off();\n        this.objectBackPackAreaEvent && this.objectBackPackAreaEvent.off();\n        this.globalEvent && this.globalEvent.destroy();\n        this.soundEditor && this.soundEditor.destory();\n        this._destroyer.destroy();\n    }\n};\n"
  },
  {
    "path": "src/class/popup.js",
    "content": "/**\n * @fileoverview Popup object for generate popup.\n */\n'use strict';\n\n/**\n * Constructor of popup\n * @constructor\n */\nEntry.Popup = class Popup {\n    constructor(className) {\n        Entry.assert(!window.popup, 'Popup exist');\n\n        this.body_ = Entry.createElement('div');\n        this.body_.addClass('entryPopup');\n        if (className) {\n            this.body_.addClass(className);\n        }\n        this.body_.bindOnClick(function (e) {\n            if (e.target == this) {\n                this.popup.remove();\n            }\n        });\n        this.body_.popup = this;\n        Entry.modalContainer.appendChild(this.body_);\n        this.window_ = Entry.createElement('div');\n        this.window_.addClass('entryPopupWindow');\n        if (Entry.targetChecker && !Entry.targetChecker.statusViewDisabled) {\n            this.window_.addClass('targetCheckerPopup');\n        }\n        // if (Entry.device === 'tablet') this.window_.addClass('tablet');\n        this.window_.bindOnClick(() => {});\n        Entry.addEventListener('windowResized', this.resize);\n        window.popup = this;\n        this.resize();\n        this.body_.appendChild(this.window_);\n    }\n    /**\n     * Remove this popup\n     */\n    remove() {\n        Entry.dispatchEvent('onPopupClose');\n        while (this.window_.hasChildNodes()) {\n            if (Entry.type == 'workspace') {\n                Entry.engineContainer.insertBefore(\n                    Entry.engine.buttonWrapper,\n                    Entry.engineContainer.firstChild\n                );\n                Entry.engineContainer.insertBefore(\n                    this.window_.firstChild,\n                    Entry.engineContainer.firstChild\n                );\n            } else if (Entry.type == 'minimize') {\n                const child = this.window_.firstChild;\n\n                if (child === Entry.stage.canvas.canvas) {\n                    const wrapper = Entry.view_.querySelector('#entryCanvasWrapper');\n                    wrapper.insertBefore(child, wrapper.firstChild);\n                } else if (child === Entry.engine.runButton[0]) {\n                    Entry.view_\n                        .querySelector('.entryRunButtonBigMinimizeCurtain')\n                        .appendChild(child);\n                } else if (child === Entry.engine.view_) {\n                    Entry.view_.appendChild(child);\n                }\n            } else {\n                Entry.engineContainer.insertBefore(\n                    this.window_.lastChild,\n                    Entry.engineContainer.firstChild\n                );\n            }\n        }\n        $('body').css('overflow', 'auto');\n        Entry.removeElement(this.body_);\n        window.popup = null;\n        Entry.removeEventListener('windowResized', this.resize);\n        Entry.view_.removeClass('fullscreen');\n        Entry.engine.popup = null;\n        Entry.windowResized.notify();\n        if (\n            Entry.type === 'workspace' &&\n            Entry.targetChecker &&\n            !Entry.targetChecker.statusViewDisabled\n        ) {\n            Entry.targetChecker.getStatusView().remove();\n        }\n    }\n\n    /**\n     * Resize this view size when window size modified\n     * @param {event} e\n     */\n    resize(e) {\n        const popup = window.popup;\n        const popupWindow = popup.window_;\n        const bottomOffset =\n            Entry.targetChecker && !Entry.targetChecker.statusViewDisabled ? 91 + 48 : 48;\n        let maxWidth = 0;\n        let maxHeight = 0;\n        if (window.parent) {\n            try {\n                maxWidth = window.parent.innerWidth * 0.9;\n                maxHeight = window.parent.innerHeight * 0.9 - bottomOffset;\n            } catch (e) {\n                maxWidth = window.innerWidth * 0.9;\n                maxHeight = window.innerHeight * 0.9 - bottomOffset;\n            }\n        } else {\n            maxWidth = window.innerWidth * 0.9;\n            maxHeight = window.innerHeight * 0.9 - bottomOffset;\n        }\n        if (maxWidth * 9 <= maxHeight * 16) {\n            maxHeight = (maxWidth / 16) * 9;\n            maxHeight += bottomOffset;\n            popupWindow.style.width = `${String(maxWidth)}px`;\n            popupWindow.style.height = `${String(maxHeight)}px`;\n        } else {\n            maxWidth = (maxHeight * 16) / 9;\n            maxHeight += bottomOffset;\n            popupWindow.style.width = `${String(maxWidth)}px`;\n            popupWindow.style.height = `${String(maxHeight)}px`;\n        }\n\n        Entry.stage && Entry.stage.updateBoundRect();\n    }\n\n    removeMouseDispose(e) {\n        this.body_.unBindOnClick();\n    }\n};\n"
  },
  {
    "path": "src/class/popup_helper.ts",
    "content": "require('../util/utils');\n\nexport default class PopupHelper {\n    private popupList: any = {};\n    private nextPopupList: string[] = [];\n    private nowContent: any = undefined;\n    private body_: any;\n    private window_: any;\n    private popupWrapper_: any;\n\n    constructor(reset: boolean) {\n        if (reset) {\n            $('.entryPopup.popupHelper').remove();\n            window.popupHelper = null;\n        }\n        Entry.assert(!window.popupHelper, 'Popup exist');\n\n        const ignoreCloseType = ['confirm', 'spinner'];\n        const spanArea = [\n            'entryPopupHelperTopSpan',\n            'entryPopupHelperBottomSpan',\n            'entryPopupHelperLeftSpan',\n            'entryPopupHelperRightSpan',\n        ];\n\n        this.body_ = Entry.Dom('div', {\n            classes: ['entryPopup', 'hiddenPopup', 'popupHelper'],\n        });\n\n        const popupClickEvent = (e: JQuery.ClickEvent) => {\n            if (this.nowContent && ignoreCloseType.indexOf(this.nowContent.prop('type')) > -1) {\n                return;\n            }\n            const $target = $(e.target);\n            spanArea.forEach((className) => {\n                if ($target.hasClass(className)) {\n                    this.hide();\n                }\n            });\n            if (e.target == this) {\n                this.hide();\n            }\n        };\n\n        this.body_.bindOnClick(popupClickEvent);\n\n        window.popupHelper = this;\n        this.body_.prop('popup', this);\n\n        Entry.Dom('div', {\n            class: 'entryPopupHelperTopSpan',\n            parent: this.body_,\n        });\n        const middle = Entry.Dom('div', {\n            class: 'entryPopupHelperMiddleSpan',\n            parent: this.body_,\n        });\n        Entry.Dom('div', {\n            class: 'entryPopupHelperBottomSpan',\n            parent: this.body_,\n        });\n        Entry.Dom('div', {\n            class: 'entryPopupHelperLeftSpan',\n            parent: middle,\n        });\n        this.window_ = Entry.Dom('div', {\n            class: 'entryPopupHelperWindow',\n            parent: middle,\n        });\n        Entry.Dom('div', {\n            class: 'entryPopupHelperRightSpan',\n            parent: middle,\n        });\n\n        $('body').append(this.body_);\n    }\n\n    clearPopup() {\n        const maxCnt = this.popupWrapper_.children.length - 1;\n        for (let i = maxCnt; i > 2; i--) {\n            this.popupWrapper_.removeChild(this.popupWrapper_.children[i]);\n        }\n    }\n\n    addPopup(key: string, popupObject: any) {\n        const content_ = Entry.Dom('div');\n\n        const titleButton_ = Entry.Dom('div', {\n            class: 'entryPopupHelperCloseButton',\n        });\n\n        titleButton_.bindOnClick(() => {\n            if (popupObject.closeEvent) {\n                popupObject.closeEvent(this);\n            }\n            this.hide();\n        });\n\n        const popupWrapper_ = Entry.Dom('div', {\n            class: 'entryPopupHelperWrapper',\n        });\n\n        popupWrapper_.append(titleButton_);\n\n        if (popupObject.title) {\n            const title_ = Entry.Dom('div', {\n                class: 'entryPopupHelperTitle',\n            });\n            popupWrapper_.append(title_);\n            title_.text(popupObject.title);\n        }\n\n        content_.addClass(key);\n        content_.append(popupWrapper_);\n\n        // @ts-ignore\n        content_.popupWrapper_ = popupWrapper_;\n        content_.prop('type', popupObject.type);\n\n        if (typeof popupObject.setPopupLayout === 'function') {\n            popupObject.setPopupLayout(content_);\n        }\n\n        // @ts-ignore\n        content_._obj = popupObject;\n\n        this.popupList[key] = content_;\n    }\n\n    hasPopup(key: string) {\n        return !!this.popupList[key];\n    }\n\n    remove(key: string) {\n        if (key) {\n            this.window_.find(`> .${key}`).remove();\n        } else if (this.window_.children().length > 0) {\n            this.window_.children().remove();\n        }\n        // 지워지면 안되는 요소인데 지워지고 있었음. 이유는? 잠시동안만 유지.\n        // this.window_.remove();\n        delete this.popupList[key];\n\n        if (this.nowContent && this.nowContent.hasClass(key)) {\n            this.nowContent = undefined;\n            this.body_.addClass('hiddenPopup');\n            if (this.nextPopupList.length > 0) {\n                this.show(this.nextPopupList.shift());\n            }\n        }\n    }\n\n    // 왜있는 함수인지 알수없음 레거시임. 문제없는 경우 삭제해도 됨\n    resize(e: any) {}\n\n    show(key: string, isNext?: boolean) {\n        const that = this;\n\n        function showContent(key: string) {\n            that.window_.append(that.popupList[key]);\n            that.nowContent = that.popupList[key];\n            that.body_.removeClass('hiddenPopup');\n        }\n\n        if (!isNext) {\n            this.window_.children().detach();\n            showContent(key);\n        } else {\n            if (this.window_.children().length > 0) {\n                this.nextPopupList.push(key);\n            } else {\n                this.window_.children().detach();\n                showContent(key);\n            }\n        }\n        if (this.nowContent && this.nowContent._obj && this.nowContent._obj.onShow) {\n            this.nowContent._obj.onShow();\n        }\n    }\n\n    hide() {\n        const popup = this.nowContent && this.nowContent._obj;\n        if (popup && 'closeEvent' in popup) {\n            popup.closeEvent(this);\n        }\n        this.nowContent = undefined;\n        this.body_.addClass('hiddenPopup');\n        this.window_.children().detach();\n        if (this.nextPopupList.length > 0) {\n            this.show(this.nextPopupList.shift());\n        }\n    }\n\n    addClass(className?: string) {\n        className && this.body_.addClass(className);\n    }\n}\n\n// Entry Legacy 에서 사용 중\nEntry.popupHelper = PopupHelper;\n"
  },
  {
    "path": "src/class/popup_list.js",
    "content": "'use strict';\n\nEntry.PopupList = class PopupList {\n    constructor(dom) {\n        this.view = dom;\n    }\n    getView() {\n        return this.view;\n    }\n\n    resize() {}\n};\n"
  },
  {
    "path": "src/class/project.js",
    "content": "'use strict';\n\nimport get from 'lodash/get';\nimport isMatch from 'lodash/isMatch';\nimport pick from 'lodash/pick';\n\nfunction scriptCheck(script) {\n    if (script.length !== 1 || script[0].length !== 2) {\n        return false;\n    }\n\n    const whenRun = get(script, '0.0.type');\n    const repeat = get(script, '0.1.type');\n    const statements = get(script, '0.1.statements');\n    const move = get(script, '0.1.statements.0.0.type');\n\n    if (\n        whenRun !== 'when_run_button_click' ||\n        repeat !== 'repeat_basic' ||\n        statements.length !== 1 ||\n        statements[0].length !== 1 ||\n        move !== 'move_direction'\n    ) {\n        return false;\n    }\n\n    return true;\n}\n\nEntry.isDefaultProject = function (project) {\n    try {\n        if (Entry.stateManager.undoStack_.length) {\n            return false;\n        }\n\n        const script = JSON.parse(get(project, 'objects.0.script'));\n        const { scenes, variables, objects, tables } = project;\n        if (\n            scenes.length !== 1 ||\n            variables.length !== 2 ||\n            objects.length !== 1 ||\n            tables.length !== 0 ||\n            !scriptCheck(script)\n        ) {\n            return false;\n        }\n        const pickData = pick(project, [\n            'scenes.0.id',\n            'variables.0.id',\n            'variables.0.value',\n            'variables.0.variableType',\n            'variables.0.x',\n            'variables.0.y',\n            'variables.1.id',\n            'variables.1.value',\n            'variables.1.variableType',\n            'variables.1.x',\n            'variables.1.y',\n            'objects.0.id',\n            'objects.0.scene',\n            'objects.0.sprite.sounds.0.id',\n            'objects.0.sprite.sounds.length',\n            'objects.0.sprite.pictures.0.id',\n            'objects.0.sprite.pictures.1.id',\n            'objects.0.sprite.pictures.length',\n            'expansionBlocks',\n            'aiUtilizeBlocks',\n            'speed',\n        ]);\n        return isMatch(Entry.getStartProject(), pickData);\n    } catch (e) {\n        return false;\n    }\n};\n\nEntry.getStartProject = function (mediaFilePath) {\n    return {\n        category: Lang.Menus.other,\n        scenes: [\n            {\n                name: `${Lang.Blocks.SCENE} 1`,\n                id: '7dwq',\n            },\n        ],\n        variables: [\n            {\n                name: Lang.Workspace.Variable_Timer,\n                id: 'brih',\n                visible: false,\n                value: '0',\n                variableType: 'timer',\n                x: 134,\n                y: -70,\n                array: [],\n                object: null,\n                isCloud: false,\n            },\n            {\n                name: Lang.Blocks.VARIABLE_get_canvas_input_value,\n                id: '1vu8',\n                visible: false,\n                value: '0',\n                variableType: 'answer',\n                x: 150,\n                y: -100,\n                array: [],\n                object: null,\n                isCloud: false,\n            },\n        ],\n        objects: [\n            {\n                id: '7y0y',\n                name: Lang.Blocks.entry_bot_name,\n                label: {\n                    ko: '엔트리봇',\n                    en: 'Entrybot',\n                },\n                script: [\n                    [\n                        {\n                            type: 'when_run_button_click',\n                            x: 40,\n                            y: 50,\n                        },\n                        {\n                            type: 'repeat_basic',\n                            statements: [[{ type: 'move_direction' }]],\n                        },\n                    ],\n                ],\n                selectedPictureId: 'vx80',\n                objectType: 'sprite',\n                rotateMethod: 'free',\n                scene: '7dwq',\n                sprite: {\n                    sounds: [\n                        {\n                            duration: 1.3,\n                            ext: '.mp3',\n                            id: '8el5',\n                            fileurl: `${mediaFilePath}media/bark.mp3`,\n                            name: Lang.Blocks.doggi_bark,\n                            label: {\n                                ko: '강아지 짖는소리',\n                                en: \"Doggi's Bark\",\n                            },\n                        },\n                    ],\n                    pictures: [\n                        {\n                            id: 'vx80',\n                            fileurl: `${mediaFilePath}media/entrybot1.svg`,\n                            thumbUrl: `${mediaFilePath}media/entrybot1.svg`,\n                            name: `${Lang.Blocks.walking_entryBot}1`,\n                            imageType: 'svg',\n                            dimension: {\n                                width: 144,\n                                height: 246,\n                            },\n                        },\n                        {\n                            id: '4t48',\n                            fileurl: `${mediaFilePath}media/entrybot2.svg`,\n                            thumbUrl: `${mediaFilePath}media/entrybot2.svg`,\n                            name: `${Lang.Blocks.walking_entryBot}2`,\n                            imageType: 'svg',\n                            dimension: {\n                                width: 144,\n                                height: 246,\n                            },\n                        },\n                    ],\n                },\n                entity: {\n                    x: 0,\n                    y: 0,\n                    regX: 72,\n                    regY: 123,\n                    scaleX: 0.5128205128205128,\n                    scaleY: 0.5128205128205128,\n                    rotation: 0,\n                    direction: 90,\n                    width: 144,\n                    height: 246,\n                    visible: true,\n                },\n                lock: false,\n                active: true,\n            },\n        ],\n        expansionBlocks: [],\n        aiUtilizeBlocks: [],\n        speed: 60,\n    };\n};\n"
  },
  {
    "path": "src/class/property_panel.ts",
    "content": "import { EntryDom } from '../../types/index';\n\nclass PropertyPanel {\n    public modes: any = {};\n    public selected: string = undefined;\n\n    private _view: EntryDom;\n    private _tabView: EntryDom;\n    private _contentView: EntryDom;\n    private _cover: EntryDom & { _isVisible?: boolean };\n\n    generateView(parentDom: HTMLElement) {\n        const container = $(parentDom);\n        this._view = Entry.Dom('div', {\n            class: 'propertyPanel',\n            parent: container,\n        });\n\n        this._tabView = Entry.Dom('div', {\n            class: 'propertyTab',\n            parent: this._view,\n        });\n\n        this._contentView = Entry.Dom('div', {\n            class: 'propertyContent',\n            parent: this._view,\n        });\n\n        this._cover = Entry.Dom('div', {\n            classes: ['propertyPanelCover', 'entryRemove'],\n            parent: this._view,\n        });\n\n        const splitter = Entry.Dom('div', {\n            class: 'entryObjectSelectedImgWorkspace',\n            parent: container,\n        });\n        this._initializeSplitter(splitter);\n    }\n\n    addMode(mode: string, contentObj: any) {\n        if (this.modes[mode]) {\n            this.removeMode(mode);\n        }\n\n        let contentDom = contentObj.getView();\n        // will be removed after apply new Dom class\n        contentDom = Entry.Dom(contentDom, {\n            parent: this._contentView,\n        });\n\n        const tabDom = Entry.Dom(`<div>${Lang.Menus[mode]}</div>`, {\n            classes: ['propertyTabElement', `propertyTab${mode}`],\n            parent: this._tabView,\n        });\n        tabDom.bind('click', () => {\n            this.select(mode);\n        });\n\n        if (mode === 'console') {\n            contentObj.codeMirror.refresh();\n        }\n\n        this._removeDom(mode);\n\n        this.modes[mode] = {\n            obj: contentObj,\n            tabDom,\n            contentDom,\n        };\n\n        if (mode === 'hw') {\n            $('.propertyTabhw').bind('dblclick', () => {\n                Entry.dispatchEvent('hwModeChange');\n            });\n        }\n    }\n\n    removeMode(mode: string) {\n        this._removeDom(mode);\n\n        const keys = Object.keys(this.modes);\n        if (keys && keys.length > 0) {\n            this.select(keys[0]);\n        }\n    }\n\n    resize(canvasSize: number) {\n        const selected = this.selected;\n        if (!selected) {\n            return;\n        }\n        const canvasHeight = (canvasSize * 9) / 16;\n        this._view.css({\n            width: `${canvasSize}px`,\n            top: `${canvasHeight + 35 + 40 + 48 - 22}px`,\n        });\n        if (canvasSize >= 430) {\n            this._view.removeClass('collapsed');\n        } else {\n            this._view.addClass('collapsed');\n        }\n\n        Entry.dispatchEvent('windowResized');\n\n        const obj = this.modes[selected].obj;\n        if (selected === 'hw') {\n            if (this.modes.hw.obj.listPorts) {\n                obj.resizeList();\n            } else {\n                obj.resize && obj.resize();\n            }\n        } else {\n            obj.resize && obj.resize();\n        }\n    }\n\n    select(modeName: string) {\n        for (const key in this.modes) {\n            const mode = this.modes[key];\n            mode.tabDom.removeClass('selected');\n            mode.contentDom.addClass('entryRemove');\n            $(mode.contentDom).detach();\n            mode.obj.visible = false;\n        }\n\n        const selected = this.modes[modeName];\n        $(this._contentView).append(selected.contentDom);\n        selected.tabDom.addClass('selected');\n        selected.contentDom.removeClass('entryRemove');\n        if (selected.obj.resize) {\n            selected.obj.resize();\n        }\n        selected.obj.visible = true;\n        this.selected = modeName;\n    }\n\n    private _initializeSplitter(splitter: EntryDom) {\n        splitter.bind('mousedown touchstart', (e) => {\n            e.preventDefault();\n            if (Entry.disposeEvent) {\n                Entry.disposeEvent.notify();\n            }\n            const container = Entry.container;\n            splitter.addClass('enabled');\n            this._cover.removeClass('entryRemove');\n            this._cover._isVisible = true;\n            container.splitterEnable = true;\n            const beforeVisible = this._cover.width() >= Entry.CANVAS_DEFAULT_WIDTH - 24;\n            let isMoved = false;\n            if (Entry.documentMousemove) {\n                container.resizeEvent = Entry.documentMousemove.attach(this, (e: any) => {\n                    if (container.splitterEnable) {\n                        isMoved = true;\n                        Entry.resizeElement({\n                            canvasWidth: e.clientX || e.x,\n                        });\n                    }\n                });\n            }\n            $(document).bind('mouseup.container:splitter touchend.container:splitter', () => {\n                const container = Entry.container;\n                const listener = container.resizeEvent;\n                if (listener) {\n                    container.splitterEnable = false;\n                    listener.destroy();\n                    splitter.removeClass('enabled');\n                    delete container.resizeEvent;\n                }\n                if (this._cover._isVisible) {\n                    this._cover._isVisible = false;\n                    this._cover.addClass('entryRemove');\n                }\n                if (\n                    !isMoved &&\n                    !beforeVisible &&\n                    this._cover.width() < Entry.CANVAS_DEFAULT_WIDTH - 24\n                ) {\n                    Entry.resizeElement({ canvasWidth: Entry.CANVAS_MIN_WIDTH });\n                }\n                $(document).unbind('.container:splitter');\n            });\n        });\n    }\n\n    private _removeDom(mode: string) {\n        if (this.modes[mode]) {\n            this.modes[mode].tabDom.remove();\n            this.modes[mode].contentDom.remove();\n            if (mode === 'hw') {\n                $(this.modes).removeClass('.propertyTabhw');\n                $('.propertyTabhw').unbind('dblclick');\n            }\n        }\n    }\n}\n\nexport default PropertyPanel;\nEntry.PropertyPanel = PropertyPanel;\n"
  },
  {
    "path": "src/class/reporter.js",
    "content": "'use strict';\n/**\n * @fileoverview Show dialog on canvas\n */\n\nEntry.Reporter = class Reporter {\n    constructor(isRealTime) {\n        this.userId = null;\n        this.projectId = null;\n        this.isRealTime = isRealTime;\n        this.activities = [];\n    }\n\n    start(projectId, userId, startTime) {\n        //this.io = io(window.location.href.split(\"/\")[2]);\n        if (this.isRealTime) {\n            if (window.location.href.indexOf('localhost') > -1) {\n                this.io = io('localhost:7000');\n            } else {\n                this.io = io('play04.play-entry.com:7000');\n            }\n            this.io.emit('activity', {\n                message: 'start',\n                userId,\n                projectId,\n                time: startTime,\n            });\n        }\n        this.userId = userId;\n        this.projectId = projectId;\n    }\n\n    report(state) {\n        if (this.isRealTime && !this.io) {\n            return;\n        }\n        const params = [];\n        for (const i in state.params) {\n            const param = state.params[i];\n            if (typeof param !== 'object') {\n                params.push(param);\n            } else if (param.id) {\n                params.push(param.id);\n            }\n        }\n        const activity = {\n            message: state.message,\n            userId: this.userId,\n            projectId: this.projectId,\n            time: state.time,\n            params,\n        };\n        if (this.isRealTime) {\n            this.io.emit('activity', activity);\n        } else {\n            this.activities.push(activity);\n        }\n    }\n};\n"
  },
  {
    "path": "src/class/scene.js",
    "content": "/**\n * @fileoverview Scene controller for entry.\n */\n'use strict';\n\nimport { Sortable } from '@entrylabs/tool';\n\n/**\n * Class for a scene controller.\n * This have view for scenes.\n * @constructor\n */\nconst STATIC_SCENES_COUNT = 30;\n\nEntry.Scene = class {\n    constructor() {\n        this.scenes_ = [];\n        this.selectedScene = null;\n        this.maxCount = this.getMaxSceneCount() || 30;\n        $(window).on('resize', this.resize.bind(this));\n\n        this.disposeEvent = Entry.disposeEvent.attach(this, (e) => {\n            const elem = document.activeElement;\n            if (e && elem && elem !== e.target && $(elem).hasClass('entrySceneFieldWorkspace')) {\n                elem.blur();\n            }\n        });\n    }\n\n    /**\n     * Control bar view generator.\n     * @param {!Element} sceneView sceneView from Entry.\n     * @param {?string} option for choose type of view.\n     */\n    generateView(sceneView, option) {\n        this.view_ = sceneView;\n        this.view_.addClass('entryScene');\n        if (!option || option === 'workspace' || option === 'playground') {\n            this.view_.addClass('entrySceneWorkspace');\n\n            $(this.view_).on('mousedown touchstart', (e) => {\n                const offset = $(this.view_).offset();\n                const $window = $(window);\n\n                const slope = -40 / 55;\n                const selectedScene = this.selectedScene;\n                const selectedLeft = $(selectedScene.view)\n                    .find('.entrySceneRemoveButtonCoverWorkspace')\n                    .offset().left;\n\n                const x = e.pageX - offset.left + $window.scrollLeft() - selectedLeft;\n                const y = 40 - (e.pageY - offset.top + $window.scrollTop());\n\n                if (x < selectedLeft || x > selectedLeft + 55) {\n                    return;\n                }\n            });\n\n            const listView = this.createListView();\n            this.view_.appendChild(listView);\n            this.listView_ = listView;\n\n            if (Entry.sceneEditable) {\n                const addButton = this.createAddButton();\n                this.view_.appendChild(addButton);\n                this.addButton_ = addButton;\n\n                const scenePrevButton = this.scenePrevButton();\n                const sceneNextButton = this.sceneNextButton();\n                this.view_.appendChild(scenePrevButton);\n                this.view_.appendChild(sceneNextButton);\n\n                this.scenePrevButton = scenePrevButton;\n                this.sceneNextButton = sceneNextButton;\n\n                this.prevButton_ = scenePrevButton;\n                this.nextButton_ = sceneNextButton;\n\n                this.sceneListWidth = Entry.scene.listView_.offsetWidth;\n                this.updateView();\n            }\n        }\n    }\n\n    createAddButton() {\n        const addButton = Entry.createElement('span').addClass(\n            'entrySceneElementWorkspace entrySceneAddButtonWorkspace'\n        );\n\n        addButton.bindOnClick((e) => {\n            if (Entry.engine.isState('run')) {\n                return;\n            }\n            Entry.do('sceneAdd', Entry.generateHash());\n        });\n\n        return addButton;\n    }\n    /**\n     * prev scene button\n     */\n    scenePrevButton() {\n        const prevButton = Entry.createElement('span').addClass(\n            'entrySceneElementWorkspace entryScenePrevButtonWorkspace'\n        );\n\n        const prevBtn = document.createElement('span').addClass('prevBtn');\n        prevButton.bindOnClick((e) => {\n            this.selectScene(Entry.scene.getPrevScene());\n        });\n\n        prevButton.appendChild(prevBtn);\n\n        return prevButton;\n    }\n    /**\n     * next scene, add scene button\n     */\n    sceneNextButton() {\n        const nextButton = Entry.createElement('span').addClass(\n            'entrySceneElementWorkspace entrySceneNextButtonWorkspace'\n        );\n\n        const nextBtn = document.createElement('span').addClass('nextBtn');\n        nextBtn.bindOnClick((e) => {\n            this.selectScene(Entry.scene.getNextScene());\n        });\n\n        const addButton = document.createElement('span').addClass('addButton');\n        addButton.bindOnClick((e) => {\n            if (Entry.engine.isState('run')) {\n                return;\n            }\n            this.sceneListwidth = Entry.scene.listView_.offsetWidth;\n\n            Entry.do('sceneAdd', Entry.generateHash());\n        });\n\n        this.nextAddButton_ = addButton;\n        nextButton.appendChild(nextBtn);\n        nextButton.appendChild(addButton);\n\n        return nextButton;\n    }\n\n    createListView() {\n        const listView = Entry.createElement('div');\n        listView.addClass('entrySceneListWorkspace');\n        const observer = new ResizeObserver(() => {\n            this.updateView();\n        });\n        observer.observe(listView);\n\n        this.sceneSortableListWidget = new Sortable({\n            data: {\n                height: '100%',\n                sortableTarget: ['entrySceneRemoveButtonWorkspace', 'entrySceneInputCover'],\n                lockAxis: 'x',\n                axis: 'x',\n                items: this._getSortableSceneList(),\n            },\n            container: listView,\n        });\n        if (Entry.sceneEditable) {\n            this.sceneSortableListWidget.on('change', ([newIndex, oldIndex]) => {\n                Entry.scene.moveScene(newIndex, oldIndex);\n            });\n        }\n        return listView;\n    }\n\n    updateSceneView() {\n        const items = this._getSortableSceneList();\n        if (this.sceneSortableListWidget) {\n            setTimeout(() => this.sceneSortableListWidget.setData({ items }), 0);\n        }\n    }\n\n    _getSortableSceneList() {\n        if (!this.scenes_ || this.scenes_.length === 0) {\n            return [];\n        }\n\n        return this.scenes_.map((value) => ({\n            key: value.id,\n            item: value.view,\n        }));\n    }\n\n    /**\n     * generate li element for scene\n     * @param {!scene model} scene\n     */\n    generateElement(scene) {\n        const viewTemplate = this.createViewTemplate(scene);\n        Entry.Utils.disableContextmenu(viewTemplate);\n\n        const nameField = this.createNameField(scene);\n        viewTemplate.nameField = nameField;\n\n        const sceneLeft = this.createSceneLeft();\n        viewTemplate.appendChild(sceneLeft);\n\n        const divide = this.createSceneDivider();\n        viewTemplate.appendChild(divide);\n        scene.inputWrapper = divide;\n        divide.appendChild(nameField);\n\n        const removeButtonCover = this.createRemoveButtonCover();\n        viewTemplate.appendChild(removeButtonCover);\n\n        if (Entry.sceneEditable) {\n            scene.removeButton = this.createRemoveButton(scene, removeButtonCover);\n\n            Entry.ContextMenu.onContextmenu(viewTemplate, (coordinate) => {\n                const options = [\n                    {\n                        text: Lang.Workspace.duplicate_scene,\n                        enable: Entry.engine.isState('stop') && !this.isMax(),\n                        callback() {\n                            Entry.scene.cloneScene(scene);\n                        },\n                    },\n                ];\n                Entry.ContextMenu.show(options, 'workspace-contextmenu', coordinate);\n            });\n        }\n\n        scene.view = viewTemplate;\n\n        return viewTemplate;\n    }\n\n    createRemoveButton(scene, removeButtonCover) {\n        return Entry.createElement('button')\n            .addClass('entrySceneRemoveButtonWorkspace')\n            .bindOnClick((e) => {\n                if (Entry.engine.isState('run')) {\n                    return;\n                }\n                const isDeletable = Entry.scene.getScenes().length > 1;\n                if (!isDeletable) {\n                    Entry.toast.alert(\n                        Lang.Msgs.runtime_error,\n                        Lang.Workspace.Scene_delete_error,\n                        false\n                    );\n                    return;\n                }\n                Entry.do('sceneRemove', scene.id);\n            })\n            .appendTo(removeButtonCover);\n    }\n\n    createRemoveButtonCover() {\n        const removeButtonCover = Entry.createElement('span');\n        removeButtonCover.addClass('entrySceneRemoveButtonCoverWorkspace');\n        return removeButtonCover;\n    }\n\n    createSceneDivider() {\n        const divide = Entry.createElement('span');\n        divide.addClass('entrySceneInputCover');\n        if (!Entry.sceneEditable) {\n            divide.addClass('entryDisabledScene');\n        }\n        return divide;\n    }\n\n    createSceneLeft() {\n        const sceneLeft = Entry.createElement('span');\n        sceneLeft.addClass('entrySceneLeftWorkspace');\n        return sceneLeft;\n    }\n\n    createNameField(scene) {\n        const nameField = Entry.createElement('input');\n        nameField.addClass('entrySceneFieldWorkspace');\n        nameField.value = scene.name;\n\n        nameField.addEventListener('keyup', ({ keyCode: code }) => {\n            if (Entry.isArrowOrBackspace(code)) {\n                return;\n            }\n\n            const applyValue = (value) => {\n                value !== scene.name && Entry.do('sceneRename', scene.id, value);\n                nameField.blur();\n            };\n\n            let value = nameField.value;\n\n            if (code === 13) {\n                applyValue(value);\n            } else if (value.length > 10) {\n                value = value.substring(0, 10);\n                applyValue(value);\n            }\n        });\n        nameField.addEventListener('blur', (e) => {\n            if (nameField.value !== scene.name) {\n                Entry.do('sceneRename', scene.id, nameField.value);\n            }\n\n            const { playground = {} } = Entry;\n            const { mainWorkspace } = playground;\n            if (mainWorkspace) {\n                mainWorkspace.reDraw();\n            }\n        });\n\n        if (!Entry.sceneEditable) {\n            nameField.disabled = 'disabled';\n        }\n\n        return nameField;\n    }\n\n    createViewTemplate(scene) {\n        const viewTemplate = Entry.createElement('div', scene.id);\n        viewTemplate.addClass('entrySceneElementWorkspace  entrySceneButtonWorkspace minValue');\n        $(viewTemplate).on('mousedown touchstart', (e) => {\n            if (Entry.engine.isState('run')) {\n                return;\n            }\n            if (Entry.scene.selectedScene !== scene) {\n                Entry.do('sceneSelect', scene.id);\n                if (e.type === 'touchstart') {\n                    e.preventDefault();\n                }\n            }\n        });\n        return viewTemplate;\n    }\n\n    updateView() {\n        if (!Entry.type || Entry.type === 'workspace') {\n            const addBtnWidth = 72;\n            const sceneListWidth = this.sceneListWidth + addBtnWidth + 170;\n            const browserWidth = Entry.view_.offsetWidth;\n            const maxSceneCount = Entry.scene.scenes_.length || STATIC_SCENES_COUNT;\n            if (this.addButton_) {\n                if (maxSceneCount >= STATIC_SCENES_COUNT) {\n                    this.addButton_.addClass('entryRemove');\n                    this.nextAddButton_.addClass('entryRemove');\n                } else {\n                    this.addButton_.removeClass('entryRemove');\n                    this.prevButton_.removeClass('entryRemove');\n                    this.nextButton_.removeClass('entryRemove');\n\n                    if (sceneListWidth > browserWidth) {\n                        this.addButton_.addClass('entryRemove');\n                        this.nextAddButton_.removeClass('entryRemove');\n                    } else {\n                        this.nextButton_.addClass('entryRemove');\n                        this.prevButton_.addClass('entryRemove');\n                    }\n                }\n            }\n        }\n        this.updateSceneView();\n        this.resize();\n    }\n\n    /**\n     * add scenes\n     * @param {Array<scene model>} scenes\n     */\n    addScenes(scenes) {\n        this.scenes_ = scenes;\n        if (!scenes || scenes.length === 0) {\n            this.scenes_ = [];\n            this.scenes_.push(this.createScene());\n        } else {\n            for (let i = 0, len = scenes.length; i < len; i++) {\n                this.generateElement(scenes[i]);\n            }\n        }\n\n        this.selectScene(this.getScenes()[0]);\n    }\n    /**\n     * add scenes to this.scenes_\n     * @param {scene model} scene\n     */\n    addScene(scene, index) {\n        if (scene === undefined || typeof scene === 'string') {\n            scene = this.createScene(scene);\n        }\n\n        if (!scene.view) {\n            this.generateElement(scene);\n        }\n\n        if (!index && typeof index != 'number') {\n            this.getScenes().push(scene);\n        } else {\n            this.getScenes().splice(index, 0, scene);\n        }\n\n        Entry.stage.objectContainers.push(Entry.stage.createObjectContainer(scene));\n        this.selectScene(scene);\n\n        if (Entry.creationChangedEvent) {\n            Entry.creationChangedEvent.notify();\n        }\n        const { playground = {} } = Entry || {};\n        const { mainWorkspace } = playground;\n        if (mainWorkspace) {\n            mainWorkspace.reDraw();\n        }\n        return scene;\n    }\n\n    /**\n     * remove scene from this.scenes_\n     * @param {!scene model} scene\n     */\n    removeScene(scene) {\n        if (this.getScenes().length <= 1) {\n            Entry.toast.alert(Lang.Msgs.runtime_error, Lang.Workspace.Scene_delete_error, false);\n            return;\n        }\n        Entry.Utils.forceStopSounds();\n        scene = this.getSceneById(typeof scene === 'string' ? scene : scene.id);\n\n        this.getScenes().splice(this.getScenes().indexOf(scene), 1);\n        Entry.container\n            .getSceneObjects(scene)\n            .forEach((object) => Entry.container.removeObject(object, true));\n        Entry.stage.removeObjectContainer(scene);\n        $(scene.view).remove();\n        this.selectScene();\n\n        if (Entry.codeChangedEvent) {\n            Entry.codeChangedEvent.notify();\n        }\n    }\n\n    selectScene(scene) {\n        const targetScene = scene || this.getScenes()[0];\n        const container = Entry.container;\n\n        container.resetSceneDuringRun();\n\n        if (this.selectedScene && this.selectedScene.id === targetScene.id) {\n            return;\n        }\n        if (\n            Entry.playground.getViewMode() === 'picture' &&\n            Entry.playground.nameViewFocus &&\n            Entry.playground.nameViewBlur()\n        ) {\n            return;\n        }\n\n        const prevSelected = this.selectedScene;\n        if (prevSelected) {\n            const prevSelectedView = prevSelected.view;\n            prevSelectedView.removeClass('selectedScene');\n            const elem = document.activeElement;\n            elem === prevSelectedView.nameField && elem.blur();\n        }\n\n        this.selectedScene = targetScene;\n        targetScene.view.addClass('selectedScene');\n\n        const stage = Entry.stage;\n        const playground = Entry.playground;\n\n        container.setCurrentObjects();\n\n        stage.selectObjectContainer(targetScene);\n\n        const targetObject = container.getCurrentObjects()[0];\n\n        if (Entry.engine.isState('run')) {\n            Entry.Utils.forceStopSounds();\n        }\n\n        if (targetObject && Entry.type !== 'minimize') {\n            container.selectObject(targetObject.id);\n            playground.refreshPlayground();\n        } else {\n            if (Entry.isTextMode) {\n                const workspace = Entry.getMainWS();\n                const vimBoard = workspace && workspace.vimBoard;\n                if (vimBoard) {\n                    const sObject = vimBoard._currentObject;\n                    const sScene = vimBoard._currentScene;\n                    const parser = vimBoard._parser;\n                    try {\n                        if (targetScene.id != sScene.id) {\n                            workspace._syncTextCode();\n                        }\n                    } catch (e) {}\n\n                    if (parser._onError) {\n                        container.selectObject(sObject.id, true);\n                        return;\n                    }\n                }\n                vimBoard && vimBoard.clearText();\n            }\n\n            stage.selectObject(null);\n            playground.flushPlayground();\n            Entry.variableContainer.selected = null;\n            Entry.variableContainer.updateList();\n        }\n        !container.listView_ && stage.sortZorder();\n\n        container.updateListView();\n        if (Entry.type && Entry.type !== 'minimize' && Entry.scene.listView_) {\n            this.sceneListWidth = Entry.scene.listView_.offsetWidth;\n        }\n        this.updateView();\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * convert this scenes data to JSON.\n     * @return {JSON}\n     */\n    toJSON() {\n        return this.getScenes().map((scene) => _.pick(scene, ['id', 'name']));\n    }\n\n    /**\n     * Move scene in this.scenes_\n     * this method is for sortable\n     * @param {!number} start\n     * @param {!number} end\n     */\n    moveScene(start, end) {\n        this.getScenes().splice(end, 0, this.getScenes().splice(start, 1)[0]);\n        Entry.container.updateObjectsOrder();\n        Entry.stage.sortZorder();\n        this.updateSceneView();\n        //style properties are not removed sometimes\n        $('.entrySceneElementWorkspace').removeAttr('style');\n    }\n\n    /**\n     * get scene by scene id\n     * @param {!String} sceneId\n     * @return {scene modal}\n     */\n    getSceneById(id) {\n        return _.find(this.getScenes(), { id }) || false;\n    }\n\n    /**\n     * @return {Array<Entry scene>}\n     */\n    getScenes() {\n        return this.scenes_;\n    }\n\n    /**\n     * remember selectedScene before start\n     * in order to reset when stopped\n     */\n    takeStartSceneSnapshot() {\n        this.sceneBeforeRun = this.selectedScene;\n    }\n\n    /**\n     * select selectedScene before start\n     * before run start\n     */\n    loadStartSceneSnapshot() {\n        this.selectScene(this.sceneBeforeRun);\n        this.sceneBeforeRun = null;\n    }\n    /**\n     * create scene\n     * @return {scene modal} scene\n     */\n    createScene(sceneId) {\n        const regex = /[0-9]/;\n        let name = Entry.getOrderedName(`${Lang.Blocks.SCENE} `, this.scenes_, 'name');\n        if (!regex.test(name)) {\n            name += '1';\n        }\n        const scene = {\n            name,\n            id: sceneId || Entry.generateHash(),\n        };\n\n        this.generateElement(scene);\n        return scene;\n    }\n\n    /**\n     * clone scene by context menu\n     * @param {!scene model} scene\n     */\n    cloneScene(scene) {\n        if (this.isMax()) {\n            Entry.toast.alert(Lang.Msgs.runtime_error, Lang.Workspace.Scene_add_error, false);\n            return;\n        }\n\n        const clonedScene = {\n            name: (Lang.Workspace.cloned_scene + scene.name).substring(0, 10),\n            id: Entry.generateHash(),\n        };\n\n        this.generateElement(clonedScene);\n        this.addScene(clonedScene);\n\n        const container = Entry.container;\n        const objects = container.getSceneObjects(scene);\n\n        try {\n            const oldIds = [];\n            const newIds = [];\n            this.isSceneCloning = true;\n            for (let i = objects.length - 1; i >= 0; i--) {\n                const obj = objects[i];\n                const ret = container.addCloneObject(obj, clonedScene.id, true);\n                oldIds.push(obj.id);\n                newIds.push(ret.id);\n            }\n            container.adjustClonedValues(oldIds, newIds);\n            const WS = Entry.getMainWS();\n            WS && WS.board && WS.board.reDraw();\n            this.isSceneCloning = false;\n            container.setCurrentObjects();\n            container.updateObjectsOrder();\n            container.updateListView();\n            container.selectObject(newIds[newIds.length - 1]);\n            Entry.variableContainer.updateViews();\n        } catch (e) {\n            console.log('error', e);\n        }\n    }\n\n    /**\n     * resize html element by window size\n     * @param {!scene model} scene\n     */\n    resize() {\n        const scenes = this.getScenes();\n        const selectedScene = this.selectedScene;\n        const addButton = this.addButton_;\n        const firstScene = scenes[0];\n\n        if (scenes.length === 0 || !firstScene) {\n            return;\n        }\n\n        const startPos = $(firstScene.view).offset().left;\n        const marginLeft = parseFloat($(selectedScene.view).css('margin-left'));\n        let totalWidth = Math.floor($(this.view_).width() - startPos - 5);\n        const LEFT_MARGIN = -40;\n\n        let normWidth = startPos + 15;\n        let diff = 0;\n        let isSelectedView = false;\n        let selectedViewWidth = 0;\n        for (var i in scenes) {\n            var scene = scenes[i];\n            let view = scene.view;\n            view.addClass('minValue');\n            isSelectedView = view === this.selectedScene.view;\n            view = $(view);\n\n            const width = parseFloat(Entry.computeInputWidth(scene.name));\n            const adjusted = (width * 10) / 9;\n            if (scene === this.selectedScene) {\n                diff = adjusted - width;\n            }\n            // $(scene.inputWrapper).width(adjusted + 'px');\n            const viewWidth = view.width();\n            if (isSelectedView) {\n                selectedViewWidth = viewWidth;\n            }\n            normWidth += viewWidth + LEFT_MARGIN;\n        }\n\n        if (normWidth > totalWidth) {\n            align();\n        }\n\n        function align() {\n            const dummyWidth = 30.5;\n            const len = scenes.length - 1;\n            totalWidth =\n                totalWidth -\n                Math.round(selectedViewWidth || $(selectedScene.view).width()) -\n                dummyWidth * len -\n                diff;\n\n            const fieldWidth = Math.floor(totalWidth / len);\n            for (i in scenes) {\n                scene = scenes[i];\n                if (selectedScene.id != scene.id) {\n                    scene.view.removeClass('minValue');\n                    // $(scene.inputWrapper).width(fieldWidth);\n                } else {\n                    scene.view.addClass('minValue');\n                }\n            }\n        }\n    }\n\n    getPrevScene() {\n        const scenes = this.getScenes();\n        return scenes[scenes.indexOf(this.selectedScene) - 1];\n    }\n\n    getNextScene() {\n        const scenes = this.getScenes();\n        return scenes[scenes.indexOf(this.selectedScene) + 1];\n    }\n\n    getMaxSceneCount() {\n        return STATIC_SCENES_COUNT;\n    }\n\n    isMax() {\n        return Entry.scene.scenes_.length >= STATIC_SCENES_COUNT;\n    }\n\n    clear() {\n        this.scenes_.forEach((s) => Entry.stage.removeObjectContainer(s));\n        this.scenes_ = [];\n        this.selectedScene = null;\n        this.updateView();\n    }\n\n    getDom(query) {\n        let scene;\n        if (query.length > 1) {\n            scene = this.getSceneById(query[1]);\n        }\n\n        switch (query[0]) {\n            case 'addButton':\n                return this.addButton_;\n            case 'removeButton':\n                return scene.removeButton;\n            case 'nameField':\n                return scene.view.nameField;\n            case 'view':\n                return scene.view;\n            default:\n                return;\n        }\n    }\n\n    destroy() {\n        // 우선 interface 만 정의함.\n    }\n};\n"
  },
  {
    "path": "src/class/sound.ts",
    "content": "import {\n    renderSoundEditor,\n    loadSoundByUrl,\n    loadSound,\n    clearSound,\n    clearHistory,\n    registExportFunction,\n    unregistExportFunction,\n    undo,\n    redo,\n    isModified,\n    getAudioBuffer,\n    destroy,\n} from '@entrylabs/sound-editor';\nimport toWav from 'audiobuffer-to-wav';\n\ninterface ISound {\n    duration: number;\n    ext: string;\n    id: string;\n    filename: string;\n    fileurl: string;\n    name: string;\n    path: string;\n    objectId?: string;\n}\n\ninterface IObject {\n    id: string;\n}\n\ninterface ILastSound {\n    sound: ISound;\n    object: IObject;\n}\n\nclass SoundEditor {\n    sound?: ISound;\n    object?: IObject;\n    lastChangeSoundInfo?: ILastSound;\n\n    constructor(soundView: HTMLDivElement) {\n        this.initialize(soundView);\n    }\n\n    initialize(soundView: HTMLDivElement) {\n        renderSoundEditor(soundView);\n        Entry.addEventListener('soundSelected', this.changeSound.bind(this));\n        Entry.addEventListener('soundUnselected', this.clearSound.bind(this));\n        Entry.addEventListener('saveCompleteSound', this.saveAfterEvent.bind(this));\n        registExportFunction(this.saveSound.bind(this));\n    }\n\n    getEntryAudioBuffer(id: string) {\n        if (!Entry.soundQueue) {\n            return;\n        }\n        return Entry.soundQueue.getResult(id);\n    }\n\n    async updateSound(sound: ISound, object: IObject) {\n        try {\n            if (Entry.playground.object.id !== object.id) {\n                return;\n            }\n\n            this.sound = sound;\n            this.object = object;\n            const audioBuffer = this.getEntryAudioBuffer(sound.id);\n            if (!audioBuffer) {\n                Entry.dispatchEvent('startLoading', Lang.Msgs.sound_loading);\n                await loadSoundByUrl(sound.path);\n            } else {\n                loadSound(audioBuffer);\n            }\n        } catch (e) {\n            console.error(e);\n        } finally {\n            Entry.dispatchEvent('endLoading');\n        }\n    }\n\n    /**\n     * 이 메서드는 소리와 오브젝트를 매개변수로 받아,\n     * 소리가 없거나 소리의 경로가 없는 경우를 제외하고 현재 소리를 업데이트합니다.\n     * 만약 변경 사항이 있다면, 사용자에게 저장할지 확인한 후,\n     * 오디오 버퍼를 얻고 소리를 저장합니다.\n     * 변경 사항이 없다면, 소리와 오브젝트를 업데이트합니다.\n     * 메서드 실행 중에 오류가 발생하면, 오류를 콘솔에 기록합니다.\n     *\n     * @param {ISound} sound - 업데이트할 소리\n     * @param {IObject} object - 오브젝트\n     */\n    changeSound(sound: ISound, object: IObject) {\n        try {\n            if (!sound || !sound.path || (this.sound && this.sound.id === sound.id)) {\n                return;\n            }\n            if (isModified()) {\n                this.alertSaveModifiedSound(sound, object);\n            } else {\n                this.updateSound(sound, object);\n            }\n        } catch (e) {\n            console.error(e);\n        }\n    }\n\n    async clearSound() {\n        await this.alertSaveModifiedSound(this.sound, this.object);\n        this.sound = null;\n        this.object = null;\n        clearSound();\n    }\n\n    audioBufferToArrayBuffer(audioBuffer: AudioBuffer) {\n        const numberOfChannels = audioBuffer.numberOfChannels;\n        const length = audioBuffer.length * numberOfChannels * 2; // 16-bit PCM\n        const buffer = new ArrayBuffer(length);\n        const view = new DataView(buffer);\n\n        for (let channel = 0; channel < numberOfChannels; channel++) {\n            const channelData = audioBuffer.getChannelData(channel);\n            let offset = channel * 2;\n\n            for (let i = 0; i < channelData.length; i++) {\n                const sample = Math.max(-1, Math.min(1, channelData[i])); // Clamp to -1 to 1\n                // eslint-disable-next-line max-len\n                view.setInt16(offset, sample < 0 ? sample * 0x8000 : sample * 0x7fff, true); // 16-bit PCM\n                offset += numberOfChannels * 2;\n            }\n        }\n\n        return buffer;\n    }\n\n    writeUTFBytes(view: DataView, offset: number, string: string) {\n        for (let i = 0; i < string.length; i++) {\n            view.setUint8(offset + i, string.charCodeAt(i));\n        }\n    }\n\n    saveSound(audioBuffer: AudioBuffer, isSelect: boolean = true) {\n        if (!audioBuffer) {\n            return;\n        }\n        Entry.dispatchEvent(\n            'saveSoundBuffer',\n            toWav(audioBuffer),\n            {\n                ...this.sound,\n                objectId: this.object.id,\n            },\n            isSelect,\n            () => {\n                clearHistory();\n            }\n        );\n    }\n\n    saveAfterEvent(soundInfo: ISound) {\n        let sound: ISound;\n        let object: IObject;\n\n        if (this.lastChangeSoundInfo) {\n            sound = this.lastChangeSoundInfo.sound;\n            object = this.lastChangeSoundInfo.object;\n        } else if (soundInfo) {\n            sound = soundInfo;\n            object = {\n                id: soundInfo.objectId,\n            };\n        }\n\n        if (sound && object) {\n            this.updateSound(sound, object);\n        }\n        this.lastChangeSoundInfo = null;\n    }\n\n    alertSaveModifiedSound(sound: ISound, object: IObject) {\n        return new Promise<void>((res) => {\n            if (!isModified || !isModified()) {\n                res();\n                return;\n            }\n            Entry.modal.confirm(Lang.Menus.save_modified_shape).then(async (result: boolean) => {\n                if (result) {\n                    this.lastChangeSoundInfo = { sound, object };\n                    this.saveSound(await getAudioBuffer(), false);\n                } else {\n                    clearHistory();\n                    this.updateSound(sound, object);\n                }\n                res();\n            });\n        });\n    }\n\n    hide() {\n        this.alertSaveModifiedSound(this.sound, this.object);\n    }\n\n    destory() {\n        unregistExportFunction();\n        destroy();\n    }\n}\n\nexport default SoundEditor;\n"
  },
  {
    "path": "src/class/source/DataTableSource.js",
    "content": "import { dmetTable } from '../../extensions/dmet';\nimport CloudVariable from '../../extensions/CloudVariable';\nimport _throttle from 'lodash/throttle';\nimport _cloneDeep from 'lodash/cloneDeep';\n\nconst getColumns = (table, indexes, wrapper = (x) => x) =>\n    indexes.map((index) => table.map((field) => wrapper(field[index])));\n\nfunction corr(d1, d2) {\n    const { min, pow, sqrt } = Math;\n    const add = (a, b) => Number(a) + Number(b);\n    const n = min(d1.length, d2.length);\n    if (n === 0) {\n        return 0;\n    }\n    [d1, d2] = [d1.slice(0, n), d2.slice(0, n)];\n    const [sum1, sum2] = [d1, d2].map((l) => l.reduce(add));\n    const [pow1, pow2] = [d1, d2].map((l) => l.reduce((a, b) => a + pow(b, 2), 0));\n    const mulSum = d1.map((n, i) => n * d2[i]).reduce(add);\n    const dense = sqrt((pow1 - pow(sum1, 2) / n) * (pow2 - pow(sum2, 2) / n));\n    if (dense === 0) {\n        return 0;\n    }\n    return ((mulSum - (sum1 * sum2) / n) / dense).toFixed(2);\n}\nclass DataTableSource {\n    #id;\n    #name;\n    #data;\n    #object;\n    #isCloud = false;\n    #cloudDate = null;\n    #chart = [];\n    #cloudVariable = CloudVariable.getInstance();\n    #source;\n    #copiedChart;\n    summary;\n    provider;\n    description;\n    fieldInfos;\n    modals = [];\n    updated = new Date();\n    tab = 'summary';\n\n    constructor(source = {}) {\n        const {\n            name,\n            id = Entry.generateHash(),\n            object = null,\n            chart,\n            data,\n            tab = 'summary',\n            fields = [],\n            summary,\n            updatedAt,\n            provider,\n            description,\n            fieldInfos,\n        } = source;\n        this.#name = name;\n        this.#id = id;\n        this.#object = object;\n        this.#source = source;\n        this.#data = new dmetTable(source);\n        this.#chart = chart || [];\n        this.summary = summary;\n        this.provider = provider;\n        this.description = description;\n        this.fieldInfos = fieldInfos;\n        this.tab = tab;\n        this.updated = updatedAt ? new Date(updatedAt) : new Date();\n        // 정지시 data 초기화.\n        Entry.addEventListener('stop', () => {\n            this.modals = [];\n            this.#data.from({\n                ...source,\n                data: this.#data.origin,\n                fields: this.#data.originFields,\n            });\n            this.#copiedChart = undefined;\n        });\n\n        const apply = (force = false) => {\n            if (this.modals.length > 0 && (force || this.modals.some((modal) => modal.isShow))) {\n                this.modals.forEach((modal) =>\n                    modal.setData({\n                        source: {\n                            chart: this.copiedChart,\n                            fields: this.fields,\n                            origin: this.rows,\n                            tab: this.tab,\n                            summary: this.summary,\n                        },\n                    })\n                );\n            }\n        };\n        this.forceApply = () => apply(true);\n        this.applyChart = _throttle(apply, 1000);\n    }\n\n    get rows() {\n        return this.array.map(({ value }) => value);\n    }\n\n    get id() {\n        return this.#id;\n    }\n\n    get name() {\n        return this.#name;\n    }\n\n    set name(name) {\n        this.#name = name;\n    }\n\n    get fields() {\n        return this.#data.fields;\n    }\n\n    get array() {\n        const { array } = this.#data;\n        return array;\n    }\n\n    get chart() {\n        return this.#chart;\n    }\n\n    get table() {\n        return [this.fields, ...this.rows];\n    }\n\n    get origin() {\n        return this.#data.origin;\n    }\n\n    get copiedChart() {\n        if (!this.#copiedChart) {\n            this.#copiedChart = _cloneDeep(this.#chart);\n        }\n        return this.#copiedChart;\n    }\n\n    get dataTable() {\n        return {\n            id: this.id,\n            name: this.name,\n            chart: this.#chart,\n            table: this.table,\n        };\n    }\n\n    setArray({ chart, data, fields, name }) {\n        this.#chart = chart;\n        this.#name = name;\n        this.#source = { ...this.#source, fields, data, name };\n        this.#data.from(this.#source);\n    }\n\n    getValue(index) {\n        return this.#data.getValue(index);\n    }\n\n    isExist(index) {\n        const isExist = this.getValue(index);\n        return !!(isExist === null || isExist === 0 || isExist);\n    }\n\n    appendRow(data) {\n        return new Promise(async (resolve, reject) => {\n            try {\n                const appendOp = this.#data.getOperation({ type: 'appendRow', data });\n                this.#data.exec(appendOp);\n                resolve();\n                this.applyChart();\n            } catch (e) {\n                reject(e);\n            }\n        });\n    }\n\n    appendCol(data) {\n        return new Promise(async (resolve, reject) => {\n            try {\n                const appendOp = this.#data.getOperation({ type: 'appendCol', data });\n                this.#data.exec(appendOp);\n                resolve();\n                this.applyChart();\n            } catch (e) {\n                reject(e);\n            }\n        });\n    }\n\n    insertRow(index, data) {\n        return new Promise(async (resolve, reject) => {\n            try {\n                const insertOp = this.#data.getOperation({ type: 'insertRow', index, data });\n                this.#data.exec(insertOp);\n                resolve();\n                this.applyChart();\n            } catch (e) {\n                reject(e);\n            }\n        });\n    }\n\n    insertCol(index, data) {\n        return new Promise(async (resolve, reject) => {\n            try {\n                const insertOp = this.#data.getOperation({ type: 'insertCol', index, data });\n                this.#data.exec(insertOp);\n\n                this.#copiedChart = this.copiedChart.map((chart) => {\n                    if (chart.xIndex >= index) {\n                        chart.xIndex++;\n                    }\n                    if (chart.yIndex >= index) {\n                        chart.yIndex++;\n                    }\n                    for (let i = 0; i < chart.categoryIndexes.length; i++) {\n                        if (chart.categoryIndexes[i] >= index) {\n                            chart.categoryIndexes[i]++;\n                        }\n                    }\n                    return chart;\n                });\n                resolve();\n                this.applyChart();\n            } catch (e) {\n                reject(e);\n            }\n        });\n    }\n\n    deleteCol(index) {\n        return new Promise(async (resolve, reject) => {\n            try {\n                const deleteOp = this.#data.getOperation({ type: 'deleteCol', index });\n                this.#data.exec(deleteOp);\n                this.#copiedChart = this.copiedChart.map((chart) => {\n                    if (chart.xIndex == index) {\n                        chart.xIndex = -1;\n                        chart.yIndex = -1;\n                        chart.categoryIndexes = [];\n                    } else if (chart.xIndex > index) {\n                        chart.xIndex--;\n                    }\n                    if (chart.yIndex == index) {\n                        chart.yIndex = -1;\n                        chart.categoryIndexes = [];\n                    } else if (chart.yIndex > index) {\n                        chart.yIndex--;\n                    }\n                    for (let i = 0; i < chart.categoryIndexes.length; i++) {\n                        if (chart.categoryIndexes[i] == index) {\n                            chart.categoryIndexes.splice(i, 1);\n                            i--;\n                        } else if (chart.categoryIndexes[i] > index) {\n                            chart.categoryIndexes[i]--;\n                        }\n                    }\n                    return chart;\n                });\n                resolve();\n                this.applyChart();\n            } catch (e) {\n                reject(e);\n            }\n        });\n    }\n\n    deleteRow(index) {\n        return new Promise(async (resolve, reject) => {\n            try {\n                const deleteOp = this.#data.getOperation({ type: 'deleteRow', index });\n                this.#data.exec(deleteOp);\n                resolve();\n                this.applyChart();\n            } catch (e) {\n                reject(e);\n            }\n        });\n    }\n\n    replaceValue(index, data) {\n        return new Promise(async (resolve, reject) => {\n            try {\n                const replaceOp = this.#data.getOperation({ type: 'replace', index, data });\n                this.#data.exec(replaceOp);\n                resolve();\n                this.applyChart();\n            } catch (e) {\n                reject(e);\n            }\n        });\n    }\n\n    toJSON() {\n        return {\n            _id: this.#data._id,\n            id: this.#id,\n            project: Entry.projectId,\n            fields: this.fields,\n            name: this.#name,\n            object: this.#object,\n            data: this.array,\n            origin: this.#data.origin,\n            chart: this.#chart,\n            isCloud: this.#isCloud,\n            cloudDate: this.#cloudDate,\n            summary: this.summary,\n            updated: this.updated,\n        };\n    }\n\n    getCoefficient(colX, colY) {\n        return corr(...getColumns(this.rows, [colY, colX]));\n    }\n\n    clone() {\n        return {\n            name: this.#name,\n            fields: [...this.fields],\n            data: _cloneDeep(this.#data.origin),\n            chart: [...this.#chart],\n        };\n    }\n}\n\nexport default DataTableSource;\n"
  },
  {
    "path": "src/class/stage.js",
    "content": "/**\n * Stage is object to handle canvas\n * @fileoverview This manage canvas\n *\n */\n\n'use strict';\n\nimport Extension from '../extensions/extension';\nimport { GEHelper } from '../graphicEngine/GEHelper';\nimport { GEHandle } from '../graphicEngine/GEHandle';\nimport { PIXIAtlasManager } from './pixi/atlas/PIXIAtlasManager';\n\n/**\n * class for a canvas\n * @constructor\n */\nEntry.Stage = class Stage {\n    constructor() {\n        /** @type {Dictionary} */\n        this.variables = {};\n        this.objectContainers = [];\n        this.selectedObjectContainer = null;\n\n        /** @type {null|Entry.EntryObject} */\n        this.selectedObject = null;\n        this.isObjectClick = false;\n        this._entitySelectable = true;\n\n        /** @type {PIXI.Application | CreateJsApplication} */\n        this._app = null;\n\n        this.background = GEHelper.newGraphic();\n        this.background.graphics.beginFill('#ffffff').drawRect(-480, -240, 960, 480);\n        this.variableContainer = GEHelper.newContainer('variableContainer');\n        this.dialogContainer = GEHelper.newContainer('dialogContainer');\n    }\n\n    /**\n     * initialize stage with canvas\n     * @param {!Element} canvas for stage\n     */\n    initStage(canvas) {\n        this._app = GEHelper.newApp(canvas);\n        this.canvas = this._app.stage;\n        this.canvas.x = 960 / 1.5 / 2;\n        this.canvas.y = 540 / 1.5 / 2;\n        this.canvas.scaleX = this.canvas.scaleY = 2 / 1.5;\n\n        this.canvas.addChild(this.background);\n        this.canvas.addChild(this.variableContainer);\n        this.canvas.addChild(this.dialogContainer);\n        this.inputField = null;\n        this.initCoordinator();\n        this.initHandle();\n        this.mouseCoordinate = { x: 0, y: 0 };\n\n        const _addEventListener = Entry.addEventListener.bind(Entry);\n\n        if (Entry.isPhone()) {\n            canvas.ontouchstart = (e) => {\n                Entry.dispatchEvent('canvasClick', e);\n                Entry.stage.isClick = true;\n            };\n            canvas.ontouchend = (e) => {\n                Entry.stage.isClick = false;\n                Entry.dispatchEvent('canvasClickCanceled', e);\n            };\n        } else {\n            const downFunc = (e) => {\n                Entry.dispatchEvent('canvasClick', e);\n                if (e.which == 2) {\n                    console.log('mouse wheel click disabled');\n                    return;\n                }\n                Entry.stage.isClick = true;\n            };\n\n            canvas.onmousedown = downFunc;\n            canvas.ontouchstart = downFunc;\n\n            const upFunc = (e) => {\n                Entry.stage.isClick = false;\n                Entry.dispatchEvent('canvasClickCanceled', e);\n            };\n\n            canvas.onmouseup = upFunc;\n            canvas.ontouchend = upFunc;\n\n            $(document).click(({ target: { id } }) => {\n                this.focused = id === 'entryCanvas';\n            });\n        }\n\n        _addEventListener('canvasClick', () => (Entry.stage.isObjectClick = false));\n        _addEventListener('loadComplete', this.sortZorder.bind(this));\n\n        Entry.windowResized.attach(this, this.updateBoundRect.bind(this));\n\n        const razyScroll = _.debounce(() => {\n            Entry.windowResized.notify();\n        }, 200);\n\n        $(window).scroll(() => {\n            window.requestAnimationFrame(razyScroll);\n        });\n\n        const moveFunc = (e) => {\n            e.preventDefault();\n            const { offsetY, offsetX, clientX, clientY } = Entry.Utils.convertMouseEvent(e);\n            const roundRect = Entry.stage.getBoundRect();\n            const x = offsetX || (clientX && clientX - roundRect.left) || 0;\n            const y = offsetY || (clientY && clientY - roundRect.top) || 0;\n            this.mouseCoordinate = {\n                x: Entry.Utils.toFixed((x / roundRect.width - 0.5) * 480),\n                y: Entry.Utils.toFixed((y / roundRect.height - 0.5) * -270),\n            };\n            Entry.dispatchEvent('stageMouseMove');\n        };\n\n        canvas.onmousemove = moveFunc;\n        canvas.ontouchmove = moveFunc;\n\n        canvas.onmouseout = () => Entry.dispatchEvent('stageMouseOut');\n        const updateObjectFunc = () => {\n            if (Entry.engine.isState('stop')) {\n                Entry.stage.updateObject();\n            }\n        };\n        _addEventListener('updateObject', updateObjectFunc);\n        _addEventListener('run', () => Entry.removeEventListener('updateObject', updateObjectFunc));\n        _addEventListener('stop', () => _addEventListener('updateObject', updateObjectFunc));\n        _addEventListener('canvasInputComplete', () => {\n            try {\n                const inputValue = this.inputField.value();\n                this.hideInputField();\n                if (inputValue) {\n                    ((c) => {\n                        c.setInputValue(inputValue);\n                        c.inputValue.complete = true;\n                    })(Entry.container);\n                }\n            } catch (exception) {}\n        });\n\n        this.initWall();\n        this.initVideoContainer();\n        this.render();\n        this.dropper = Extension.getExtension('Dropper');\n    }\n\n    render = function stageRender() {\n        if (Entry.stage.timer) {\n            clearTimeout(Entry.stage.timer);\n        }\n        let time = _.now();\n        Entry.stage.update();\n        time = _.now() - time;\n        Entry.stage.timer = setTimeout(stageRender, 16 - (time % 16) + 16 * Math.floor(time / 16));\n    };\n\n    /**\n     * redraw canvas\n     */\n    update() {\n        if (Entry.type === 'invisible') {\n            return;\n        }\n\n        if (!Entry.requestUpdate) {\n            Entry.requestUpdate = false;\n            return;\n        }\n        this.updateForce();\n\n        if (Entry.engine.isState('stop') && this.objectUpdated) {\n            this.objectUpdated = false;\n        }\n\n        const inputField = this.inputField;\n        if (inputField && !inputField._isHidden) {\n            inputField.render();\n        }\n        if (Entry.requestUpdateTwice) {\n            Entry.requestUpdateTwice = false;\n        } else {\n            Entry.requestUpdate = false;\n        }\n    }\n\n    updateForce() {\n        this._app && this._app.render();\n    }\n\n    /**\n     * add object entity on canvas\n     * @param {Entry.EntryObject} object\n     */\n    loadObject({ entity: { object }, scene }) {\n        this.getObjectContainerByScene(scene).addChild(object);\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * add entity directly on canvas\n     * This is use for cloned entity\n     * @param {Entry.EntityObject} entity\n     */\n    loadEntity({ parent, object }, index) {\n        const objContainer = Entry.stage.getObjectContainerByScene(parent.scene);\n        if (index > -1) {\n            objContainer.addChildAt(object, index);\n        } else {\n            objContainer.addChild(object);\n        }\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * Remove entity directly on canvas\n     * @param {Entry.EntityObject} entity\n     */\n    unloadEntity({ parent, object }) {\n        Entry.stage.getObjectContainerByScene(parent.scene).removeChild(object);\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * add variable view on canvas\n     * @param {Entry.Variable} object\n     */\n    loadVariable({ view_, id }) {\n        this.variables[id] = view_;\n        this.variableContainer.addChild(view_);\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * remove variable view on canvas\n     * @param {Entry.Variable} object\n     */\n    removeVariable({ view_ }) {\n        this.variableContainer.removeChild(view_);\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * add dialog on canvas\n     * @param {Entry.Dialog} dialog\n     */\n    loadDialog({ object }) {\n        this.dialogContainer.addChild(object);\n    }\n\n    /**\n     * Remove entity directly on canvas\n     * @param {Entry.Dialog} dialog\n     */\n    unloadDialog({ object }) {\n        this.dialogContainer.removeChild(object);\n    }\n\n    setEntityIndex({ object }, index) {\n        if (index === -1) {\n            return;\n        }\n        const selectedObjectContainer = Entry.stage.selectedObjectContainer;\n        const currentIndex = selectedObjectContainer.getChildIndex(object);\n\n        if (currentIndex === -1 || currentIndex === index) {\n            return;\n        }\n        selectedObjectContainer.setChildIndex(object, index);\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * sort Z index of objects\n     */\n    sortZorder() {\n        const objects = Entry.container.getCurrentObjects().slice();\n        const length = objects.length;\n        const container = this.selectedObjectContainer;\n        let index = 0;\n\n        for (let i = length - 1; i >= 0; i--) {\n            const {\n                entity: { object },\n            } = objects[i];\n            container.setChildIndex(object, index++);\n        }\n\n        if (container) {\n            container.children.length = length;\n        }\n\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * sort Z index of objects while running\n     */\n    sortZorderRun() {\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * Initialize coordinate on canvas. It is toggle by Engine.\n     */\n    initCoordinator() {\n        const tex = GEHelper.newSpriteWithCallback(\n            `${Entry.mediaFilePath}workspace_coordinate.png`\n        );\n        this.coordinator = Object.assign(tex, {\n            scaleX: 0.5,\n            scaleY: 0.5,\n            x: -240,\n            y: -135,\n            visible: false,\n        });\n        if (!GEHelper.isWebGL) {\n            this.coordinator.tickEnabled = false;\n        }\n        this.canvas.addChild(this.coordinator);\n    }\n\n    /**\n     * Toggle coordinator\n     */\n    toggleCoordinator() {\n        this.coordinator.visible = !this.coordinator.visible;\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * Select handle object\n     * @param {?Entry.EntryObject} object\n     */\n    selectObject(object) {\n        //todo\n        if (!object) {\n            this.selectedObject = null;\n        } else {\n            this.selectedObject = object;\n        }\n        this.updateObject();\n    }\n\n    /**\n     * Initialize handle. Handle is use for transform object on canvas.\n     */\n    initHandle() {\n        this.handle = new GEHandle(this.canvas)\n            .setChangeListener(this, this.updateHandle)\n            .setEditStartListener(this, this.startEdit)\n            .setEditEndListener(this, this.endEdit);\n    }\n\n    /**\n     * Update handle object to modified object\n     * object -> handle\n     */\n    updateObject() {\n        if (Entry.type === 'invisible' || Entry.type === 'playground') {\n            return;\n        }\n        Entry.requestUpdate = true;\n        this.handle.setDraggable(true);\n        if (this.editEntity) {\n            return;\n        }\n        const object = this.selectedObject;\n        if (object) {\n            if (object.objectType == 'textBox') {\n                this.handle.toggleCenter(false);\n            } else {\n                this.handle.toggleCenter(true);\n            }\n            const rotateMethod = object.getRotateMethod();\n            if (rotateMethod == 'free') {\n                this.handle.toggleRotation(true);\n                this.handle.toggleDirection(true);\n            } else if (rotateMethod == 'vertical') {\n                this.handle.toggleRotation(false);\n                this.handle.toggleDirection(true);\n            } else {\n                this.handle.toggleRotation(false);\n                this.handle.toggleDirection(true);\n            }\n            if (object.getLock()) {\n                this.handle.toggleRotation(false);\n                this.handle.toggleDirection(false);\n                this.handle.toggleResize(false);\n                this.handle.toggleCenter(false);\n                this.handle.setDraggable(false);\n            } else {\n                this.handle.toggleResize(true);\n            }\n            this.handle.setVisible(Entry.objectEditable);\n            const entity = object.entity;\n            this.handle.setWidth(entity.getScaleX() * entity.getWidth());\n            this.handle.setHeight(entity.getScaleY() * entity.getHeight());\n            let regX;\n            let regY;\n            if (entity.type == 'textBox') {\n                // maybe 0.\n                if (entity.getLineBreak()) {\n                    regX = entity.regX * entity.scaleX;\n                    regY = -entity.regY * entity.scaleY;\n                } else {\n                    const fontAlign = entity.getTextAlign();\n                    regY = -entity.regY * entity.scaleY;\n                    switch (fontAlign) {\n                        case Entry.TEXT_ALIGN_LEFT:\n                            regX = (-entity.getWidth() / 2) * entity.scaleX;\n                            break;\n                        case Entry.TEXT_ALIGN_CENTER:\n                            regX = entity.regX * entity.scaleX;\n                            break;\n                        case Entry.TEXT_ALIGN_RIGHT:\n                            regX = (entity.getWidth() / 2) * entity.scaleX;\n                            break;\n                    }\n                }\n            } else {\n                regX = (entity.regX - entity.width / 2) * entity.scaleX;\n                regY = (entity.height / 2 - entity.regY) * entity.scaleY;\n            }\n\n            const rotation = (entity.getRotation() / 180) * Math.PI;\n\n            this.handle.setX(entity.getX() - regX * Math.cos(rotation) - regY * Math.sin(rotation));\n            this.handle.setY(\n                -entity.getY() - regX * Math.sin(rotation) + regY * Math.cos(rotation)\n            );\n            this.handle.setRegX((entity.regX - entity.width / 2) * entity.scaleX);\n            this.handle.setRegY((entity.regY - entity.height / 2) * entity.scaleY);\n            this.handle.setRotation(entity.getRotation());\n            this.handle.setDirection(entity.getDirection());\n            this.objectUpdated = true;\n\n            this.handle.setVisible(Entry.objectEditable && object.entity.getVisible());\n            if (object.entity.getVisible()) {\n                this.handle.render();\n            }\n        } else {\n            this.handle.setVisible(false);\n        }\n        //this.toggleHandleEditable(!object.getLock());\n    }\n\n    // handle -> object\n    updateHandle() {\n        this.editEntity = true;\n        const handle = this.handle;\n        const entity = this.selectedObject.entity;\n        if (entity.lineBreak) {\n            entity.setHeight(handle.height / entity.getScaleY());\n            entity.setWidth(handle.width / entity.getScaleX());\n        } else {\n            if (entity.width !== 0) {\n                let scaleX = Math.abs(handle.width / entity.width);\n                if (entity.flip) {\n                    scaleX *= -1;\n                }\n\n                entity.setScaleX(scaleX);\n            }\n\n            if (entity.height !== 0) {\n                entity.setScaleY(handle.height / entity.height);\n            }\n        }\n        const direction = (handle.rotation / 180) * Math.PI;\n        if (entity.type == 'textBox') {\n            entity.syncFont();\n            var newRegX = handle.regX / entity.scaleX;\n            var newRegY = handle.regY / entity.scaleY;\n\n            if (entity.getLineBreak()) {\n                entity.setX(handle.x);\n                entity.setY(-handle.y);\n            } else {\n                switch (entity.getTextAlign()) {\n                    case Entry.TEXT_ALIGN_LEFT:\n                        entity.setX(handle.x - (handle.width / 2) * Math.cos(direction));\n                        entity.setY(-handle.y + (handle.width / 2) * Math.sin(direction));\n                        break;\n                    case Entry.TEXT_ALIGN_CENTER:\n                        entity.setX(handle.x);\n                        entity.setY(-handle.y);\n                        break;\n                    case Entry.TEXT_ALIGN_RIGHT:\n                        entity.setX(handle.x + (handle.width / 2) * Math.cos(direction));\n                        entity.setY(-handle.y - (handle.width / 2) * Math.sin(direction));\n                        break;\n                }\n            }\n        } else {\n            var newRegX = entity.width / 2 + handle.regX / entity.scaleX;\n            entity.setX(\n                handle.x + handle.regX * Math.cos(direction) - handle.regY * Math.sin(direction)\n            );\n            entity.setRegX(newRegX);\n            var newRegY = entity.height / 2 + handle.regY / entity.scaleY;\n            entity.setY(\n                -handle.y - handle.regX * Math.sin(direction) - handle.regY * Math.cos(direction)\n            );\n            entity.setRegY(newRegY);\n        }\n        entity.setDirection(handle.direction);\n        entity.setRotation(handle.rotation);\n        this.editEntity = false;\n    }\n\n    startEdit() {\n        const { entity } = this.selectedObject || {};\n        _.result(entity, 'initCommand');\n    }\n\n    endEdit() {\n        const { entity } = this.selectedObject || {};\n        _.result(entity, 'checkCommand');\n    }\n\n    initWall() {\n        const wall = GEHelper.newContainer('wall');\n        wall.mouseEnabled = false;\n        const tex = GEHelper.newWallTexture(`${Entry.mediaFilePath}media/bound.png`);\n        const newSide = (x, y, sx, sy) => {\n            const sp = GEHelper.newWallSprite(tex);\n            sp.x = x;\n            sp.y = y;\n            sx ? (sp.scaleX = sx) : 0;\n            sy ? (sp.scaleY = sy) : 0;\n            wall.addChild(sp);\n            return sp;\n        };\n\n        wall.up = newSide(-240, -135 - 30, 480 / 30, 0);\n        wall.down = newSide(-240, 135, 480 / 30, 0);\n        wall.right = newSide(240, -135, 0, 270 / 30);\n        wall.left = newSide(-240 - 30, -135, 0, 270 / 30);\n\n        this.canvas.addChild(wall);\n        this.wall = wall;\n    }\n\n    initVideoContainer() {\n        this.videoContainer = GEHelper.getNewContainer();\n        this.canvas.addChildAt(this.videoContainer, 2);\n        this.overlayContainer = GEHelper.getNewContainer();\n        this.canvas.addChildAt(this.overlayContainer, 3);\n    }\n\n    getCanvasElement(id) {\n        let canvas = document.getElementById(id);\n        if (!canvas) {\n            canvas = window.top.document.getElementById(id);\n        }\n        return canvas;\n    }\n\n    /**\n     * show inputfield from the canvas\n     */\n    showInputField() {\n        const THIS = this;\n        const isWebGL = GEHelper.isWebGL;\n        GEHelper.disableTickByEngine();\n        if (!this.inputField) {\n            this.inputField = _createInputField();\n            this.inputSubmitButton = _createSubmitButton();\n        }\n\n        this.inputField.value('');\n        if (isWebGL) {\n            this.canvas.addChild(this.inputField.getPixiView());\n        }\n        this.inputField.show();\n        this.canvas.addChild(this.inputSubmitButton);\n\n        Entry.requestUpdateTwice = true;\n\n        function _createInputField() {\n            const posX = 15;\n            const posY = 275;\n            const isWebGL = GEHelper.isWebGL;\n            const classRef = isWebGL ? window.PIXICanvasInput : CanvasInput;\n            const inputField = new classRef({\n                canvas: THIS.getCanvasElement('entryCanvas'),\n                fontSize: 20,\n                fontFamily: EntryStatic.fontFamily || \"NanumGothic, 'Nanum Gothic'\",\n                fontColor: '#2c313d',\n                width: 520,\n                height: 24,\n                padding: 13,\n                borderWidth: 2,\n                borderColor: '#e2e2e2',\n                borderRadius: 10,\n                boxShadow: 'none',\n                innerShadow: 'none',\n                x: posX,\n                y: posY,\n                readonly: false,\n                topPosition: true,\n                onsubmit() {\n                    Entry.dispatchEvent('canvasInputComplete');\n                },\n            });\n\n            if (isWebGL) {\n                const canvas = THIS.canvas;\n                const globalScale = canvas.scale.x;\n                const textView = inputField.getPixiView();\n                textView.scale.set(1 / globalScale);\n                textView.position.set(\n                    posX / globalScale - canvas.x / globalScale,\n                    posY / globalScale - canvas.y / globalScale\n                );\n            }\n            return inputField;\n        } //_createInputField\n\n        function _createSubmitButton() {\n            const { confirm_button } = EntryStatic.images || {};\n            const path = confirm_button || `${Entry.mediaFilePath}stage/submit.png`;\n            const inputSubmitButton = GEHelper.newSpriteWithCallback(path, () => {\n                Entry.requestUpdate = true;\n            });\n            inputSubmitButton.mouseEnabled = true;\n            inputSubmitButton.x = 190;\n            inputSubmitButton.y = 71.5;\n            inputSubmitButton.scaleX = 0.84;\n            inputSubmitButton.scaleY = 0.84;\n            inputSubmitButton.cursor = 'pointer';\n\n            const eventType = isWebGL ? 'pointerdown' : 'mousedown';\n            inputSubmitButton.on(eventType, () => {\n                if (!THIS.inputField._readonly) {\n                    Entry.dispatchEvent('canvasInputComplete');\n                }\n            });\n            return inputSubmitButton;\n        } //_createSubmitButton\n    }\n\n    /**\n     * remove inputfield from the canvas\n     */\n    hideInputField() {\n        if (!this.inputField) {\n            return;\n        }\n        GEHelper.tickByEngine();\n        if (GEHelper.isWebGL) {\n            this.canvas.removeChild(this.inputField.getPixiView());\n        }\n        this.inputField.value('');\n        this.inputField.hide();\n\n        this.canvas.removeChild(this.inputSubmitButton);\n\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * init object containers\n     */\n    initObjectContainers() {\n        const scenes = Entry.scene.scenes_;\n        if (!_.isEmpty(scenes)) {\n            for (let i = 0; i < scenes.length; i++) {\n                this.objectContainers[i] = this.createObjectContainer(scenes[i]);\n            }\n            this.selectedObjectContainer = this.objectContainers[0];\n        } else {\n            const obj = this.createObjectContainer(Entry.scene.selectedScene);\n            this.objectContainers.push(obj);\n            this.selectedObjectContainer = obj;\n        }\n        if (Entry.type !== 'invisible' && Entry.type !== 'playground') {\n            this.canvas.addChild(this.selectedObjectContainer);\n        }\n        this.selectObjectContainer(Entry.scene.selectedScene);\n    }\n\n    /**\n     * select object container by scene\n     * @param {Entry.Scene} scene\n     */\n    selectObjectContainer(scene) {\n        const containers = this.objectContainers;\n        const canvas = this.canvas;\n\n        if (_.isEmpty(canvas) || _.isEmpty(containers)) {\n            return;\n        }\n        GEHelper.resManager.activateScene(scene && scene.id);\n        const newContainer = this.getObjectContainerByScene(scene);\n\n        containers.forEach(canvas.removeChild.bind(canvas));\n\n        this.selectedObjectContainer = newContainer;\n        canvas.addChildAt(newContainer, 4);\n    }\n\n    /**\n     * init object containers\n     */\n    createObjectContainer(scene) {\n        return Object.assign(GEHelper.newContainer('[Stage] SceneContainer'), { scene });\n    }\n\n    /**\n     * remove object container\n     * @param {scene model} scene\n     */\n    removeObjectContainer(scene) {\n        const containers = this.objectContainers;\n        const objContainer = this.getObjectContainerByScene(scene);\n        const canvas = this.canvas;\n        if (canvas) {\n            canvas.removeChild(objContainer);\n        }\n        GEHelper.resManager.removeScene(scene.id);\n        containers.splice(containers.indexOf(objContainer), 1);\n    }\n\n    /**\n     * get object container\n     * @param {scene model} scene\n     */\n    getObjectContainerByScene({ id }) {\n        return _.find(this.objectContainers, ({ scene } = {}) => scene.id === id);\n    }\n\n    moveSprite({ shiftKey, keyCode }) {\n        const selectedObject = this.selectedObject;\n        if (!selectedObject || !Entry.stage.focused || selectedObject.getLock()) {\n            return;\n        }\n\n        const distance = shiftKey ? 1 : 5;\n\n        const entity = selectedObject.entity;\n        switch (keyCode) {\n            case 38: //up\n                entity.setY(entity.getY() + distance);\n                break;\n            case 40: //down\n                entity.setY(entity.getY() - distance);\n                break;\n            case 37: //left\n                entity.setX(entity.getX() - distance);\n                break;\n            case 39: //right\n                entity.setX(entity.getX() + distance);\n                break;\n        }\n        this.updateObject();\n    }\n\n    getBoundRect(e) {\n        if (!this._boundRect) {\n            return this.updateBoundRect();\n        }\n        return this._boundRect;\n    }\n\n    updateBoundRect(e) {\n        return (this._boundRect = this.canvas.canvas.getBoundingClientRect());\n    }\n\n    getDom(query) {\n        const key = query.shift();\n        if (key === 'canvas') {\n            return this.canvas.canvas;\n        }\n    }\n\n    setEntitySelectable(value) {\n        this._entitySelectable = value;\n    }\n\n    isEntitySelectable() {\n        return Entry.engine.isState('stop') && this._entitySelectable && !this.dropper.isShow;\n    }\n\n    destroy() {\n        let destroyOption;\n        if (GEHelper.isWebGL) {\n            destroyOption = { children: true, texture: false, baseTexture: false };\n            this.objectContainers.forEach((c) => c.destroy(destroyOption));\n            //this.handle.destroy(); // 추상화 아직 안됨.\n            PIXIAtlasManager?.clearProject?.();\n        } else {\n            //do nothing\n        }\n        if (this._app) {\n            this._app.destroy(destroyOption);\n            this._app = null;\n        }\n        this.handle = null;\n        this.objectContainers = null;\n    }\n};\n"
  },
  {
    "path": "src/class/stamp_entity.js",
    "content": "/**\n * @fileoverview stamp entity object is class for entry stamp entity canvas view.\n */\n\n'use strict';\n\nimport { GEHelper } from '../graphicEngine/GEHelper';\n\n/**\n * Construct stamp entity class\n * @param {!Entry.EntryObject} object\n * @param {!Entry.EntityObject} entity\n * @constructor\n */\nEntry.StampEntity = class StampEntity extends Entry.EntityObject {\n    constructor(object, entity) {\n        /** @type {!string} */\n        super(object);\n        this.parent = object;\n        this.type = object.objectType;\n        this.isClone = true;\n        this.isStamp = true;\n        this.width = entity.getWidth();\n        this.height = entity.getHeight();\n        if (this.type == 'sprite') {\n            this.object = GEHelper.cloneStamp(entity);\n            if (entity.effect) {\n                this.effect = _.clone(entity.effect);\n                this.applyFilter();\n            }\n        } else if (this.type == 'textBox') {\n        }\n\n        this.object.entity = entity;\n    }\n};\n"
  },
  {
    "path": "src/class/time_wait.js",
    "content": "'use strict';\n\nEntry.TimeWaitManager = {\n    add(id, cb, ms) {\n        if (!Entry.timerInstances) {\n            Entry.timerInstances = [];\n        }\n\n        const instance = new Entry.TimeWait(id, cb, ms);\n        Entry.timerInstances.push(instance);\n    },\n    remove(id) {\n        if (!Entry.timerInstances || Entry.timerInstances.length == 0) {\n            return;\n        }\n        Entry.timerInstances = Entry.timerInstances.filter((instance) => {\n            if (instance.id === id) {\n                return false;\n            } else {\n                return true;\n            }\n        });\n    },\n};\n\nEntry.TimeWait = class TimeWait {\n    constructor(id, cb, ms) {\n        this.id = id;\n        this.cb = cb;\n        this.ms = ms;\n        this.startTime = performance.now();\n        this.timer = setTimeout(this.callback.bind(this), ms);\n    }\n\n    callback() {\n        if (this.cb) {\n            this.cb();\n            this.destroy();\n        }\n    }\n\n    pause() {\n        if (this.timer) {\n            this.ms = this.ms - (performance.now() - this.startTime);\n            clearTimeout(this.timer);\n        }\n    }\n\n    resume() {\n        this.timer = setTimeout(this.callback.bind(this), this.ms);\n        this.startTime = performance.now();\n    }\n\n    destroy() {\n        delete this.timer;\n        delete this.cb;\n        delete this.ms;\n        delete this.startTime;\n        Entry.TimeWaitManager.remove(this.id);\n    }\n};\n"
  },
  {
    "path": "src/class/toast.js",
    "content": "/**\n * @fileoverview Toast object for notification\n */\n'use strict';\n\n/**\n * Constructor of toast\n * @constructor\n */\nEntry.Toast = class Toast {\n    constructor() {\n        this.toasts_ = [];\n        /** @type {Element} */\n        const exist = document.getElementById('entryToastContainer');\n        if (exist) {\n            Entry.modalContainer.removeChild(exist);\n        }\n        this.body_ = Entry.createElement('div', 'entryToastContainer');\n        this.body_.addClass('entryToastContainer');\n        Entry.modalContainer.appendChild(this.body_);\n    }\n\n    warning(title, message, isNotAutoDispose) {\n        const toast = Entry.createElement('div', 'entryToast');\n        toast.addClass('entryToast');\n        toast.addClass('entryToastWarning');\n        toast.bindOnClick(() => {\n            Entry.toast.body_.removeChild(toast);\n        });\n        const toastTitle = Entry.createElement('div', 'entryToast');\n        toastTitle.addClass('entryToastTitle');\n        toastTitle.textContent = title;\n        toast.appendChild(toastTitle);\n        const toastMessage = Entry.createElement('p', 'entryToast');\n        toastMessage.addClass('entryToastMessage');\n        toastMessage.textContent = message;\n        toast.appendChild(toastMessage);\n        this.toasts_.push(toast);\n        this.body_.appendChild(toast);\n        const f = () => {\n            toast.style.opacity = 1;\n            var timer = setInterval(() => {\n                if (toast.style.opacity < 0.05) {\n                    clearInterval(timer);\n                    toast.style.display = 'none';\n                    Entry.removeElement(toast);\n                }\n                toast.style.opacity *= 0.9;\n            }, 20);\n        };\n        if (!isNotAutoDispose) {\n            window.setTimeout(f, 1000);\n        }\n    }\n\n    success(title, message, isNotAutoDispose) {\n        const toast = Entry.createElement('div', 'entryToast');\n        toast.addClass('entryToast');\n        toast.addClass('entryToastSuccess');\n        toast.bindOnClick(() => {\n            Entry.toast.body_.removeChild(toast);\n        });\n        const toastTitle = Entry.createElement('div', 'entryToast');\n        toastTitle.addClass('entryToastTitle');\n        toastTitle.textContent = title;\n        toast.appendChild(toastTitle);\n        const toastMessage = Entry.createElement('p', 'entryToast');\n        toastMessage.addClass('entryToastMessage');\n        toastMessage.textContent = message;\n        toast.appendChild(toastMessage);\n        this.toasts_.push(toast);\n        this.body_.appendChild(toast);\n        const f = () => {\n            toast.style.opacity = 1;\n            var timer = setInterval(() => {\n                if (toast.style.opacity < 0.05) {\n                    clearInterval(timer);\n                    toast.style.display = 'none';\n                    Entry.removeElement(toast);\n                }\n                toast.style.opacity *= 0.9;\n            }, 20);\n        };\n        if (!isNotAutoDispose) {\n            window.setTimeout(f, 1000);\n        }\n    }\n\n    alert(title, message, isNotAutoDispose) {\n        const toast = Entry.createElement('div', 'entryToast');\n        let timer;\n        toast.addClass('entryToast');\n        toast.addClass('entryToastAlert');\n        toast.bindOnClick(() => {\n            Entry.toast.body_.removeChild(toast);\n            if (timer) {\n                clearInterval(timer);\n            }\n        });\n        const toastTitle = Entry.createElement('div', 'entryToast');\n        toastTitle.addClass('entryToastTitle');\n        toastTitle.textContent = title;\n        toast.appendChild(toastTitle);\n        const toastMessage = Entry.createElement('p', 'entryToast');\n        toastMessage.addClass('entryToastMessage');\n\n        if (Array.isArray(message)) {\n            toastMessage.textContent = message.reduce(\n                (total, current) => `${total}\\n${current}`,\n                ''\n            );\n        } else {\n            toastMessage.textContent = message;\n        }\n\n        toast.appendChild(toastMessage);\n        this.toasts_.push(toast);\n        this.body_.appendChild(toast);\n        const f = () => {\n            toast.style.opacity = 1;\n            timer = setInterval(() => {\n                if (toast.style.opacity < 0.05) {\n                    clearInterval(timer);\n                    toast.style.display = 'none';\n                    //check element already removed from parent\n                    if (toast.parentElement) {\n                        Entry.toast.body_.removeChild(toast);\n                    }\n                }\n                toast.style.opacity *= 0.9;\n            }, 20);\n        };\n        if (!isNotAutoDispose) {\n            window.setTimeout(f, 5000);\n        }\n        return toast;\n    }\n\n    isOpen(target) {\n        const activated = this.toasts_.filter((toast) => toast.style.display !== 'none');\n        if (target) {\n            return activated.includes(target);\n        }\n        return activated.length > 0;\n    }\n};\n"
  },
  {
    "path": "src/class/variable/answerVariable.js",
    "content": "import Variable from './variable';\n\nclass AnswerVariable extends Variable {\n    constructor(variable) {\n        Entry.assert(variable.variableType === 'answer', 'Invalid variable type given');\n        super(variable);\n    }\n\n    updateView() {\n        if (!this.view_) {\n            return;\n        }\n\n        if (this.isVisible()) {\n            this._adjustSingleViewPosition();\n            this.textView_.text = this.getName();\n            if (this.isNumber()) {\n                const v = Number(this.getValue());\n                if (parseInt(this.getValue(), 10) == this.getValue()) {\n                    this.valueView_.text = v;\n                } else {\n                    this.valueView_.text = Number(v)\n                        .toFixed(1)\n                        .replace('.00', '');\n                }\n            } else {\n                this.valueView_.text = this.getValue();\n            }\n            if (this._nameWidth === null) {\n                this._nameWidth = this.textView_.getMeasuredWidth();\n            }\n            this._adjustSingleValueViewPosition();\n            if (this._valueWidth === null) {\n                this._valueWidth = this.valueView_.getMeasuredWidth();\n            }\n\n            this._adjustSingleViewBox('#F57DF1');\n            Entry.requestUpdate = true;\n        }\n    }\n}\n\nexport default AnswerVariable;\n"
  },
  {
    "path": "src/class/variable/index.js",
    "content": "import SttVariable from './sttVariable';\nimport AnswerVariable from './answerVariable';\nimport ListVariable from './listVariable';\nimport SlideVariable from './slideVariable';\nimport TimerVariable from './timerVariable';\nimport Variable from './variable';\n\nEntry.Variable = Variable;\nEntry.Variable.create = (variableMetadata) => {\n    const { variableType } = variableMetadata;\n    switch (variableType) {\n        case 'stt':\n            return new SttVariable(variableMetadata);\n        case 'answer':\n            return new AnswerVariable(variableMetadata);\n        case 'list':\n            return new ListVariable(variableMetadata);\n        case 'slide':\n            return new SlideVariable(variableMetadata);\n        case 'timer':\n            return new TimerVariable(variableMetadata);\n        case 'variable':\n        default:\n            return new Variable(variableMetadata);\n    }\n};\n"
  },
  {
    "path": "src/class/variable/listVariable.js",
    "content": "import Variable from './variable';\nimport { GEHelper } from '../../graphicEngine/GEHelper';\nimport { GEDragHelper } from '../../graphicEngine/GEDragHelper';\n\nclass ListVariable extends Variable {\n    get LIST_MAX_LENGTH() {\n        return 5000;\n    }\n\n    _trimToMaxLength() {\n        if (this.array_ && this.array_.length > this.LIST_MAX_LENGTH) {\n            this.array_ = this.array_.slice(-this.LIST_MAX_LENGTH);\n            this._showListFullWarning();\n        }\n    }\n\n    _showListFullWarning() {\n        Entry.toast?.alert(\n            Lang?.Workspace?.list_cant_add_item || 'Warning',\n            Lang?.Workspace?.list_max_length_exceeded ||\n                `You can add up to ${this.LIST_MAX_LENGTH} items to a list.`\n        );\n    }\n\n    constructor(variable) {\n        Entry.assert(variable.variableType === 'list', 'Invalid variable type given');\n        super(variable);\n\n        let array = variable.array ? variable.array : [];\n        if (array.length > this.LIST_MAX_LENGTH) {\n            array = array.slice(-this.LIST_MAX_LENGTH);\n            setTimeout(() => {\n                Entry.modal?.alert(\n                    Lang?.Workspace?.list_truncated_on_load ||\n                        `The list exceeded ${this.LIST_MAX_LENGTH} items.`,\n                    Lang?.Workspace?.list_truncated_on_load_title || 'Notice'\n                );\n            }, 100);\n        }\n        this.array_ = array;\n\n        if (!variable.isClone) {\n            this.width_ = variable.width ? variable.width : 100;\n            this.height_ = variable.height ? variable.height : 120;\n            this.scrollPosition = 0;\n        }\n    }\n\n    generateView(variableIndex) {\n        this.view_ = GEHelper.newContainer();\n        this.rect_ = GEHelper.newGraphic();\n        this.view_.addChild(this.rect_);\n        this.view_.variable = this;\n        this.view_.visible = this.visible_;\n        this.view_.mouseEnabled = true;\n        this.view_.mouseChildren = true;\n        GEDragHelper.handleDrag(this.view_);\n\n        this.titleView_ = GEHelper.textHelper.newText(\n            '',\n            this.FONT,\n            '#000000',\n            'alphabetic',\n            'center'\n        );\n\n        //todo [박봉배] textview_.width 를 $width 로 변경.\n        this.titleView_.$width = this.width_ - 2 * this.BORDER;\n        if (GEHelper.isWebGL) {\n            this.titleView_.x = (this.width_ - this.titleView_.width) / 2;\n            this.titleView_.y = this.BORDER - 1;\n        } else {\n            this.titleView_.x = this.width_ / 2;\n            this.titleView_.y = this.BORDER + 11;\n        }\n        this.view_.addChild(this.titleView_);\n        const { stage_list_resize_handle } = EntryStatic.images || {};\n        this.resizeHandle_ = GEHelper.newSpriteWithCallback(\n            stage_list_resize_handle || `${Entry.mediaFilePath}stage_list_resize_handle.png`,\n            () => {\n                Entry.requestUpdate = true;\n            }\n        );\n        this.resizeHandle_.mouseEnabled = true;\n        this.resizeHandle_.scaleX = 0.7;\n        this.resizeHandle_.scaleY = 0.7;\n        this.view_.addChild(this.resizeHandle_);\n\n        this.resizeHandle_.list = this;\n\n        GEDragHelper.handleDrag(this.resizeHandle_);\n        this.resizeHandle_.on(GEDragHelper.types.OVER, function () {\n            this.cursor = 'nwse-resize';\n        });\n\n        this.resizeHandle_.on(GEDragHelper.types.DOWN, function (evt) {\n            // if(Entry.type != 'workspace') return;\n            this.list.isResizing = true;\n            this.offset = {\n                x: evt.stageX * 0.75 - this.list.getWidth(),\n                y: evt.stageY * 0.75 - this.list.getHeight(),\n            };\n            this.parent.cursor = 'nwse-resize';\n        });\n        this.resizeHandle_.on(GEDragHelper.types.MOVE, function (evt) {\n            // if(Entry.type != 'workspace') return;\n            this.list.setWidth(evt.stageX * 0.75 - this.offset.x);\n            this.list.setHeight(evt.stageY * 0.75 - this.offset.y);\n            this.list.updateView();\n        });\n\n        this.view_.on(GEDragHelper.types.OVER, function () {\n            this.cursor = 'move';\n        });\n\n        this.view_.on(GEDragHelper.types.DOWN, function (evt) {\n            if (Entry.type !== 'workspace' || this.variable.isResizing) {\n                return;\n            }\n            this.offset = {\n                x: this.x - (evt.stageX * 0.75 - 240),\n                y: this.y - (evt.stageY * 0.75 - 135),\n            };\n            this.cursor = 'move';\n        });\n\n        this.view_.on(GEDragHelper.types.UP, function () {\n            this.cursor = 'initial';\n            this.variable.isResizing = false;\n        });\n\n        this.view_.on(GEDragHelper.types.MOVE, function (evt) {\n            if (Entry.type !== 'workspace' || this.variable.isResizing) {\n                return;\n            }\n            this.variable.setX(evt.stageX * 0.75 - 240 + this.offset.x);\n            this.variable.setY(evt.stageY * 0.75 - 135 + this.offset.y);\n            this.variable.updateView();\n        });\n\n        //todo [박봉배] 아래줄 삭제 하는게 맞겠죠? 리스트 아이템인데, 생성을 아래쪽에서 함.\n        //this.elementView = this._createListElementView();\n        this.scrollButton_ = GEHelper.newGraphic();\n        this.scrollButton_.mouseEnabled = true;\n        this.scrollButton_.cursor = 'pointer';\n        GEDragHelper.handleDrag(this.scrollButton_);\n        this.scrollButton_.graphics.f('#aaaaaa').rr(0, 0, 7, 30, 3.5);\n        this.view_.addChild(this.scrollButton_);\n        this.scrollButton_.y = 25;\n\n        this.scrollButton_.list = this;\n        this.scrollButton_.on(GEDragHelper.types.DOWN, function (evt) {\n            // if(Entry.type != 'workspace') return;\n            this.list.isResizing = true;\n            this.offsetY = evt.stageY - this.y / 0.75;\n        });\n        this.scrollButton_.on(GEDragHelper.types.MOVE, function (evt) {\n            // if(Entry.type != 'workspace') return;\n\n            const stageY = evt.stageY;\n            let yPos = (stageY - this.offsetY) * 0.75;\n            const min = 25;\n            const max = this.list.getHeight() - 30;\n            if (yPos < min) {\n                yPos = min;\n            }\n            if (yPos > max) {\n                yPos = max;\n            }\n            this.y = yPos;\n            this.list.updateView();\n        });\n\n        if (this.getX() && this.getY()) {\n            this.setX(this.getX());\n            this.setY(this.getY());\n        } else {\n            const listLength = Entry.variableContainer.lists_.length;\n            this.setX(-Math.floor((listLength % 24) / 6) * 110 + 120);\n            this.setY(variableIndex * 24 + 20 - 135 - Math.floor(listLength / 6) * 145);\n        }\n\n        this.setVisible(this.isVisible());\n        Entry.stage.loadVariable(this);\n    }\n\n    getArray() {\n        if (!this.isRealTime_) {\n            return this.array_;\n        } else {\n            const { array } =\n                this.cloudVariable.get({\n                    variableType: this.type,\n                    id: this.id_,\n                }) || {};\n            return array || this.array_;\n        }\n    }\n\n    setArray(array) {\n        if (!this.isRealTime_) {\n            this.array_ = array;\n            this.updateView();\n            Entry.requestUpdateTwice = true;\n        } else {\n            return new Promise(async (resolve, reject) => {\n                try {\n                    const target = {\n                        variableType: this.type,\n                        id: this.id_,\n                    };\n                    await this.cloudVariable.setArray(target, array);\n                    this.updateView();\n                    resolve();\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        }\n    }\n\n    appendValue(value) {\n        if (!this.isRealTime_) {\n            if (!this.array_) {\n                this.array_ = [];\n            }\n            this.array_.push({\n                data: value,\n            });\n            this._trimToMaxLength();\n            this.updateView();\n        } else {\n            return new Promise(async (resolve, reject) => {\n                try {\n                    const target = {\n                        variableType: this.type,\n                        id: this.id_,\n                    };\n                    await this.cloudVariable.append(target, value);\n                    const list = this.cloudVariable.get(target);\n                    if (list) {\n                        this.array_ = list.array;\n                    } else {\n                        this.array_.push({\n                            data: value,\n                        });\n                    }\n                    this.updateView();\n                    resolve();\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        }\n    }\n\n    deleteValue(index) {\n        if (!this.isRealTime_) {\n            this.array_.splice(index - 1, 1);\n            this.updateView();\n        } else {\n            return new Promise(async (resolve, reject) => {\n                try {\n                    const target = {\n                        variableType: this.type,\n                        id: this.id_,\n                    };\n                    await this.cloudVariable.delete(target, index - 1);\n                    const list = this.cloudVariable.get(target);\n                    if (list) {\n                        this.array_ = list.array;\n                    } else {\n                        this.array_.splice(index - 1, 1);\n                    }\n                    this.updateView();\n                    resolve();\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        }\n    }\n\n    insertValue(index, data) {\n        if (!this.isRealTime_) {\n            this.array_.splice(index - 1, 0, { data });\n            this._trimToMaxLength();\n            this.updateView();\n        } else {\n            return new Promise(async (resolve, reject) => {\n                try {\n                    const target = {\n                        variableType: this.type,\n                        id: this.id_,\n                    };\n                    await this.cloudVariable.insert(target, index - 1, data);\n                    const list = this.cloudVariable.get(target);\n                    if (list) {\n                        this.array_ = list.array;\n                    } else {\n                        this.array_.splice(index - 1, 0, { data });\n                    }\n                    this.updateView();\n                    resolve();\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        }\n    }\n\n    replaceValue(index, data) {\n        if (!this.isRealTime_) {\n            this.array_[index - 1].data = data;\n            this.updateView();\n        } else {\n            return new Promise(async (resolve, reject) => {\n                try {\n                    const target = {\n                        variableType: this.type,\n                        id: this.id_,\n                    };\n                    await this.cloudVariable.replace(target, index - 1, data);\n                    const list = this.cloudVariable.get(target);\n                    if (list) {\n                        this.array_ = list.array;\n                    } else {\n                        this.array_[index - 1].data = data;\n                    }\n                    this.updateView();\n                    resolve();\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        }\n    }\n\n    updateView() {\n        if (!this.view_) {\n            return;\n        }\n\n        if (this.isVisible()) {\n            this._adjustSingleViewPosition();\n            this.resizeHandle_.x = this.width_ - 10;\n            this.resizeHandle_.y = this.height_ + 16 - 10;\n            const arr = this.getArray();\n\n            let name = this.getName();\n            if (this.object_) {\n                const obj = Entry.container.getObject(this.object_);\n                if (obj) {\n                    name = `${obj.name}:${name}`;\n                }\n            }\n\n            this.titleView_.text = name;\n            if (this.titleView_.getMeasuredWidth() > this.width_) {\n                name = `${name}..`;\n                while (this.titleView_.getMeasuredWidth() > this.width_) {\n                    name = `${name.substr(0, name.length - 3)}..`;\n                    this.titleView_.text = name;\n                }\n            }\n            if (GEHelper.isWebGL) {\n                this.titleView_.x = (this.width_ - this.titleView_.width) / 2 + 3;\n            } else {\n                this.titleView_.x = this.width_ / 2 + 3;\n            }\n            const colorSet = EntryStatic.colorSet.canvas || {};\n            this.rect_.graphics\n                .clear()\n                .f('#ffffff')\n                .ss(1, 2, 0)\n                .s(colorSet.border || '#aac5d5')\n                .rr(0, 0, this.width_ + 7, this.height_ + 22, this.RECT_RADIUS);\n\n            let listChild;\n            while ((listChild = this.view_.children[4])) {\n                this.view_.removeChild(listChild);\n                listChild.destroy && listChild.destroy();\n            }\n            const maxView = Math.floor((this.getHeight() - 15) / 20);\n\n            const isOverFlow = maxView < arr.length;\n            const totalWidth = this.getWidth();\n            let wrapperWidth = totalWidth - 2 * this.BORDER - (isOverFlow ? 30 : 20);\n\n            if (isOverFlow) {\n                if (this.scrollButton_.y > this.getHeight() - 30) {\n                    this.scrollButton_.y = this.getHeight() - 30;\n                }\n                //todo [박봉배] _createListElementView 로 코드 이동\n                // this.elementView.valueWrapper.graphics\n                //     .clear()\n                //     .f('#1bafea')\n                //     .rr(20, -2, wrapperWidth, 17, 2);\n                this.scrollButton_.x = totalWidth - 6;\n                this.scrollPosition = Math.floor(\n                    ((this.scrollButton_.y - 25) / (this.getHeight() - 25 - 30)) *\n                        (arr.length - maxView)\n                );\n            } else {\n                //todo [박봉배] _createListElementView 로 코드 이동\n                // this.elementView.valueWrapper.graphics\n                //     .clear()\n                //     .f('#1bafea')\n                //     .rr(20, -2, wrapperWidth, 17, 2);\n                this.scrollPosition = 0;\n            }\n            this.scrollButton_.visible = isOverFlow;\n\n            const _cache = {};\n            //because of min Width of list\n            //maxLen can not be under 3\n            //so start from 3\n            let maxLen = 3;\n            wrapperWidth -= 6;\n\n            for (\n                let i = this.scrollPosition;\n                i < this.scrollPosition + maxView && i < arr.length;\n                i++\n            ) {\n                this.elementView = this._createListElementView(wrapperWidth + 14);\n                if (\n                    Entry.getMainWS() &&\n                    Entry.getMainWS().getMode() === Entry.Workspace.MODE_VIMBOARD\n                ) {\n                    this.elementView.indexView.text = i;\n                } else {\n                    this.elementView.indexView.text = i + 1;\n                }\n\n                const text = String(arr?.[i]?.data ?? 'undefined');\n                const valueView = this.elementView.valueView;\n                const cachedText = _cache[text.substr(0, 150)];\n\n                if (cachedText) {\n                    valueView.text = cachedText;\n                } else {\n                    let execText = text.substr(0, maxLen);\n                    let charIndex = maxLen;\n\n                    valueView.text = text;\n\n                    if (valueView.getMeasuredWidth() > wrapperWidth) {\n                        valueView.text = execText;\n\n                        while (\n                            valueView.getMeasuredWidth() < wrapperWidth &&\n                            text[charIndex] !== undefined\n                        ) {\n                            execText += text[charIndex++];\n                            valueView.text = execText;\n                        }\n\n                        let subCnt = 1;\n                        while (valueView.getMeasuredWidth() > wrapperWidth) {\n                            execText = `${execText.substr(0, execText.length - subCnt)}..`;\n                            valueView.text = execText;\n                            subCnt = 3;\n                        }\n                    } else {\n                        execText = text;\n                    }\n\n                    _cache[text.substr(0, 150)] = execText;\n                    maxLen = Math.max(execText.length, maxLen);\n                }\n\n                this.elementView.y = (i - this.scrollPosition) * 20 + 23;\n                this.view_.addChild(this.elementView);\n            }\n        }\n\n        Entry.requestUpdate = true;\n    }\n\n    _createListElementView(wrapperWidth) {\n        const elementView = GEHelper.newContainer();\n        const indexView = GEHelper.textHelper.newText('', this.FONT, '#000000', 'middle');\n        const colorSet = EntryStatic.colorSet.canvas || {};\n        if (GEHelper.isWebGL) {\n            indexView.y = this.GL_LIST_POS.INDEX_Y;\n        } else {\n            indexView.y = 12;\n        }\n        elementView.addChild(indexView);\n        elementView.indexView = indexView;\n        const valueWrapper = GEHelper.newGraphic();\n        elementView.addChild(valueWrapper);\n        elementView.valueWrapper = valueWrapper;\n        elementView.valueWrapper.graphics\n            .clear()\n            .f(colorSet.list || '#4f80ff')\n            .rr(18, 4, wrapperWidth, 17, 2);\n\n        const valueView = GEHelper.textHelper.newText('', this.VALUE_FONT, '#ffffff', 'middle');\n        valueView.x = 24;\n        if (GEHelper.isWebGL) {\n            valueView.y = this.GL_LIST_POS.VALUE_Y;\n        } else {\n            valueView.y = 12;\n        }\n        elementView.addChild(valueView);\n        elementView.valueView = valueView;\n        elementView.x = this.BORDER;\n\n        return elementView;\n    }\n\n    syncModel_(variableModel) {\n        if (!this.isCloud_ && !this.isRealTime_) {\n            this.array_ = variableModel.array;\n        }\n        this.setWidth(variableModel.width);\n        this.setHeight(variableModel.height);\n        super.syncModel_(variableModel);\n    }\n\n    toJSON() {\n        const json = super.toJSON();\n        json.width = this.getWidth();\n        json.height = this.getHeight();\n        json.array = JSON.parse(JSON.stringify(this.getArray()));\n\n        return json;\n    }\n}\n\nexport default ListVariable;\n"
  },
  {
    "path": "src/class/variable/slideVariable.js",
    "content": "import Variable from './variable';\nimport { GEHelper } from '../../graphicEngine/GEHelper';\nimport { GEDragHelper } from '../../graphicEngine/GEDragHelper';\n\nclass SlideVariable extends Variable {\n    constructor(variable) {\n        Entry.assert(variable.variableType === 'slide', 'Invalid variable type given');\n        super(variable);\n\n        this.setMinValue(variable.minValue);\n        this.setMaxValue(variable.maxValue);\n    }\n\n    generateView(variableIndex) {\n        const slide = this;\n        this.view_ = GEHelper.newContainer();\n        this.rect_ = GEHelper.newGraphic();\n        this.view_.addChild(this.rect_);\n        this.view_.variable = this;\n        this.view_.visible = this.visible_;\n        this.view_.mouseEnabled = true;\n        this.view_.mouseChildren = true;\n        GEDragHelper.handleDrag(this.view_);\n\n        this.wrapper_ = GEHelper.newGraphic();\n        this.view_.addChild(this.wrapper_);\n        this.textView_ = GEHelper.textHelper.newText('name', this.FONT, '#000000', 'alphabetic');\n        this.textView_.x = 4;\n        if (GEHelper.isWebGL) {\n            this.textView_.y = this.GL_VAR_POS.LABEL_Y;\n        } else {\n            this.textView_.y = 1;\n        }\n        this.view_.addChild(this.textView_);\n        this.valueView_ = GEHelper.textHelper.newText(\n            'value',\n            this.VALUE_FONT,\n            '#ffffff',\n            'alphabetic'\n        );\n\n        this.view_.on(GEDragHelper.types.DOWN, function(evt) {\n            if (Entry.type !== 'workspace') {\n                return;\n            }\n            this.offset = {\n                x: this.x - (evt.stageX * 0.75 - 240),\n                y: this.y - (evt.stageY * 0.75 - 135),\n            };\n        });\n\n        this.view_.on(GEDragHelper.types.MOVE, function(evt) {\n            if (Entry.type !== 'workspace' || slide.isAdjusting) {\n                return;\n            }\n            this.variable.setX(evt.stageX * 0.75 - 240 + this.offset.x);\n            this.variable.setY(evt.stageY * 0.75 - 135 + this.offset.y);\n            this.variable.updateView();\n        });\n        this.view_.addChild(this.valueView_);\n\n        let width = this.textView_.getMeasuredWidth() + this.valueView_.getMeasuredWidth() + 26;\n        width = Math.max(width, 90);\n        this.maxWidth = width - 20;\n\n        this.slideBar_ = GEHelper.newGraphic();\n        this.slideBar_.graphics\n            .beginFill('#d8d8d8')\n            .s('#d8d8d8')\n            .ss(1)\n            .rr(10, 10, this.maxWidth, 15, 4);\n        this.slideBar_.mouseEnabled = true;\n        GEDragHelper.handleDrag(this.slideBar_);\n        this.slideBar_.on(GEDragHelper.types.DOWN, (evt) => {\n            if (!Entry.engine.isState('run')) {\n                return;\n            }\n            const value = evt.stageX * 0.75 - (this.getX() + 240 + 5) + 5;\n            slide.setSlideCommandX(value);\n        });\n        this.view_.addChild(this.slideBar_);\n\n        const position = this.getSlidePosition(this.maxWidth);\n        const { stage_variable_slider } = EntryStatic.images || {};\n        this.valueSetter_ = GEHelper.newSpriteWithCallback(\n            stage_variable_slider || `${Entry.mediaFilePath}stage_variable_slider.png`,\n            () => {\n                Entry.requestUpdate = true;\n            }\n        );\n        this.valueSetter_.cursor = 'pointer';\n        this.valueSetter_.scaleX = 0.8;\n        this.valueSetter_.scaleY = 0.8;\n        this.valueSetter_.mouseEnabled = true;\n        this.valueSetter_.y = 9;\n        this.valueSetter_.regX = 0.5;\n\n        GEDragHelper.handleDrag(this.valueSetter_);\n        this.valueSetter_.on(GEDragHelper.types.DOWN, function(evt) {\n            if (!Entry.engine.isState('run')) {\n                return;\n            }\n            slide.isAdjusting = true;\n            this.offsetX = evt.stageX * 0.75 - this.x;\n        });\n\n        this.valueSetter_.on(GEDragHelper.types.MOVE, function(evt) {\n            if (!Entry.engine.isState('run')) {\n                return;\n            }\n            const value = (evt.stageX * 0.75) - this.offsetX + 5;\n            //박봉배 - value 값의 min/max 는 다른곳에서 체크 하므로, 이곳에서는 로직 삭제 하겠음.\n            slide.setSlideCommandX(value);\n        });\n        this.valueSetter_.on(GEDragHelper.types.UP, () => {\n            slide.isAdjusting = false;\n        });\n        this.view_.addChild(this.valueSetter_);\n        const variableLength = Entry.variableContainer.variables_.length;\n        if (this.getX() && this.getY()) {\n            this.setX(this.getX());\n            this.setY(this.getY());\n        } else {\n            this.setX(10 - 240 + Math.floor(variableLength / 11) * 80);\n            this.setY(variableIndex * 24 + 20 - 135 - Math.floor(variableLength / 11) * 264);\n        }\n\n        this.setVisible(this.isVisible());\n        Entry.stage.loadVariable(this);\n    }\n\n    updateView() {\n        if (!this.view_) {\n            return;\n        }\n\n        if (this.isVisible()) {\n            this._adjustSingleViewPosition();\n            const oldContent = this.textView_.text;\n            let newContent;\n            if (this.object_) {\n                const obj = Entry.container.getObject(this.object_);\n                if (obj) {\n                    newContent = `${obj.name}:${this.getName()}`;\n                } else {\n                    newContent = this.getName();\n                }\n            } else {\n                newContent = this.getName();\n            }\n\n            if (oldContent !== newContent) {\n                this.textView_.text = newContent;\n                this._nameWidth = null;\n            }\n\n            if (this._nameWidth === null) {\n                this._nameWidth = this.textView_.getMeasuredWidth();\n            }\n            this._adjustSingleValueViewPosition();\n            let value = String(this.getValue());\n\n            if (this.isFloatPoint()) {\n                const reg = /\\.(.*)/;\n\n                //check the value is float\n                const ret = reg.exec(value);\n                if (!ret) {\n                    value += '.00';\n                } else {\n                    while (reg.exec(value)[1].length < 2) {\n                        value += '0';\n                    }\n                }\n            }\n\n            this.valueView_.text = value;\n\n            if (this._valueWidth === null) {\n                this._valueWidth = this.valueView_.getMeasuredWidth();\n            }\n            let width = this._nameWidth + this._valueWidth + 35;\n            const colorSet = EntryStatic.colorSet.canvas || {};\n            width = Math.max(width, 90);\n            this.rect_.graphics\n                .clear()\n                .f('#ffffff')\n                .ss(1, 2, 0)\n                .s(colorSet.border || '#aac5d5')\n                .rr(0, -14, width, 42, 4);\n            this.wrapper_.graphics\n                .clear()\n                .f(colorSet.slideVariable || '#4f80ff')\n                .ss(1, 2, 0)\n                .s(colorSet.slideVariable || '#4f80ff')\n                .rr(this._nameWidth + 14, -10, this._valueWidth + 15, 16, this.RECT_RADIUS);\n\n            width = this._nameWidth + this._valueWidth + 26;\n            width = Math.max(width, 90);\n            this.maxWidth = width - 16;\n\n            this.slideBar_.graphics\n                .clear()\n                .beginFill('#d8d8d8')\n                .s('#d8d8d8')\n                .ss(1)\n                .rr(6, 16, this.maxWidth + 4, 5, 2);\n            this.valueSetter_.x = this.getSlidePosition(this.maxWidth);\n\n\n            // this.valueSetter_.graphics\n            //     .clear()\n            //     .beginFill('#1bafea')\n            //     .s('#A0A1A1')\n            //     .ss(1)\n            //     .dc(position, 10 + 0.5, 3);\n        }\n        Entry.requestUpdate = true;\n    }\n\n    getValue() {\n        const value = super.getValue();\n        if (this.isNumber()) {\n            return Number(value);\n        } else {\n            return value;\n        }\n    }\n\n    setValue(value) {\n        const numValue = Number(value);\n        if (numValue < this.minValue_) {\n            this.value_ = this.minValue_;\n        } else if (numValue > this.maxValue_) {\n            this.value_ = this.maxValue_;\n        } else {\n            this.value_ = numValue;\n        }\n        super.setValue(this.value_);\n    }\n\n    setSlideCommandX(value) {\n        if (!this.valueSetter_.command) {\n            this.valueSetter_.command = {};\n        }\n        let commandX = typeof value === 'undefined' ? 10 : value;\n        commandX = Math.max(commandX, 10);\n        commandX = Math.min(this.maxWidth + 10, commandX);\n        this.valueSetter_.command.x = commandX;\n        this.updateSlideValueByView();\n    }\n\n    updateSlideValueByView() {\n        const maxWidth = this.maxWidth;\n        const position = Math.max(this.valueSetter_.command.x - 10, 0);\n        let ratio = position / maxWidth;\n        if (ratio < 0) {\n            ratio = 0;\n        }\n        if (ratio > 1) {\n            ratio = 1;\n        }\n\n        const minValue = parseFloat(this.minValue_);\n        const maxValue = parseFloat(this.maxValue_);\n\n        let value = (minValue + Number(Math.abs(maxValue - minValue) * ratio)).toFixed(2);\n        value = parseFloat(value);\n\n        if (value < minValue) {\n            value = this.minValue_;\n        } else if (value > maxValue) {\n            value = this.maxValue_;\n        }\n        if (!this.isFloatPoint()) {\n            value = Math.round(value);\n        }\n\n        this.setValue(value);\n    }\n\n    getSlidePosition(width) {\n        const minValue = this.minValue_;\n        const maxValue = this.maxValue_;\n        const value = this.value_;\n        const ratio = Math.abs(value - minValue) / Math.abs(maxValue - minValue);\n        return width * ratio + 6;\n    }\n\n    toJSON() {\n        const json = super.toJSON();\n        json.minValue = this.minValue_;\n        json.maxValue = this.maxValue_;\n\n        return json;\n    }\n}\n\nexport default SlideVariable;\n"
  },
  {
    "path": "src/class/variable/sttVariable.js",
    "content": "import Variable from './variable';\nimport { GEHelper } from '../../graphicEngine/GEHelper';\n\nclass SttVariable extends Variable {\n    constructor(variable) {\n        Entry.assert(variable.variableType === 'stt', 'Invalid variable type given');\n        super(variable);\n    }\n\n    updateView() {\n        if (!this.view_) {\n            return;\n        }\n\n        if (this.isVisible()) {\n            this._adjustSingleViewPosition();\n            this.textView_.text = this.getName();\n            if (this.isNumber()) {\n                const v = Number(this.getValue());\n                if (parseInt(this.getValue(), 10) == this.getValue()) {\n                    this.valueView_.text = v;\n                } else {\n                    this.valueView_.text = Number(v)\n                        .toFixed(1)\n                        .replace('.00', '');\n                }\n            } else {\n                this.valueView_.text = this.getValue();\n            }\n            if (this._nameWidth === null) {\n                this._nameWidth = this.textView_.getMeasuredWidth();\n            }\n            this._adjustSingleValueViewPosition();\n            if (this._valueWidth === null) {\n                this._valueWidth = this.valueView_.getMeasuredWidth();\n            }\n\n            this._adjustSingleViewBox('#8222ff');\n        }\n        Entry.requestUpdate = true;\n    }\n\n    _adjustSingleValueViewPosition() {\n        this.valueView_.x = 12;\n        if (GEHelper.isWebGL) {\n            this.valueView_.y = this.GL_VAR_POS.VALUE_Y + 22;\n        } else {\n            this.valueView_.y = 1.5 + 22;\n        }\n    }\n\n    _adjustSingleViewBox(boxFillAndStrokeColor) {\n        const rectWidth = Math.max(this._valueWidth + 22, this._nameWidth + 10);\n        const colorSet = EntryStatic.colorSet.canvas || {};\n        this.rect_.graphics\n            .clear()\n            .f('#ffffff')\n            .ss(1, 2, 0)\n            .s(colorSet.border || '#aac5d5')\n            .rr(0, -14, rectWidth, 45, 4);\n        this.wrapper_.graphics\n            .clear()\n            .f(boxFillAndStrokeColor)\n            .ss(1, 2, 0)\n            .s(boxFillAndStrokeColor)\n            .rr(4, 10, this._valueWidth + 15, 16, this.RECT_RADIUS);\n    }\n\n    // @summary 음성 인식(STT) 블록의 종류를 반환합니다.\n    // @return {string[]} 음성 인식(STT) 블록의 종류\n    getSttTypes() {\n        if (!this.sttTypes) {\n            this.sttTypes = Object.entries(Entry.AI_UTILIZE_BLOCK.audio.getBlocks())\n                .filter(([, block]) => block.class === 'stt')\n                .map(([key]) => key);\n        }\n        return this.sttTypes;\n    }\n\n    checkVisible(removeBlock, notIncludeSelf) {\n        if (!this.isVisible() || Entry.engine.isState('run')) {\n            return;\n        }\n        const objects = Entry.container.getAllObjects();\n        const sttTypes = this.getSttTypes();\n\n        for (let i = 0, len = objects.length; i < len; i++) {\n            const code = objects[i].script;\n            for (let j = 0; j < sttTypes.length; j++) {\n                const blocks = code.getBlockList(false, sttTypes[j]);\n                if (notIncludeSelf) {\n                    const index = blocks.indexOf(removeBlock);\n                    if (index > -1) {\n                        blocks.splice(index, 1);\n                    }\n                }\n                if (blocks.length > 0) {\n                    return;\n                }\n            }\n        }\n        this.setVisible(false);\n    }\n\n    reset() {\n        this.setName(Lang.template.voice_title_text);\n        this.setValue('-');\n    }\n}\n\nexport default SttVariable;\n"
  },
  {
    "path": "src/class/variable/timerVariable.js",
    "content": "import Variable from './variable';\n\nclass TimerVariable extends Variable {\n    constructor(variable) {\n        Entry.assert(variable.variableType === 'timer', 'Invalid variable type given');\n        super(variable);\n    }\n\n    updateView() {\n        if (!this.view_) {\n            return;\n        }\n\n        if (this.isVisible()) {\n            this._adjustSingleViewPosition();\n            this.textView_.text = this.getName();\n\n            if (this._nameWidth === null) {\n                this._nameWidth = this.textView_.getMeasuredWidth();\n            }\n\n            this._adjustSingleValueViewPosition();\n            if (this.isNumber()) {\n                this.valueView_.text = Number(this.getValue())\n                    .toFixed(1)\n                    .replace('.00', '');\n            } else {\n                this.valueView_.text = this.getValue();\n            }\n\n            if (this._valueWidth === null) {\n                this._valueWidth = this.valueView_.getMeasuredWidth();\n            }\n\n            this._adjustSingleViewBox('#f4af18');\n        }\n        Entry.requestUpdate = true;\n    }\n}\n\nexport default TimerVariable;\n"
  },
  {
    "path": "src/class/variable/variable.js",
    "content": "'use strict';\n\nimport { GEHelper } from '../../graphicEngine/GEHelper';\nimport { GEDragHelper } from '../../graphicEngine/GEDragHelper';\nimport CloudVariable from '../../extensions/CloudVariable';\nimport _throttle from 'lodash/throttle';\nimport BinPacking from '../../util/binPacking';\n\nconst VariableBP = new BinPacking(460, 250);\nconst bpReplace = _throttle(VariableBP.replace.bind(VariableBP));\n\n/**\n * 기본 변수블록 객체\n * @param {Object} variable variableMetadata\n */\nclass Variable {\n    get RECT_RADIUS() {\n        return 7;\n    }\n\n    get GL_VAR_POS() {\n        return {\n            VALUE_Y: -8.5,\n            LABEL_Y: -9.5,\n        };\n    }\n\n    get GL_LIST_POS() {\n        return {\n            INDEX_Y: 5,\n            VALUE_Y: 6,\n        };\n    }\n\n    constructor(variable) {\n        Entry.assert(typeof variable.name === 'string', 'Variable name must be given');\n        /** @type {string} */\n        this.name_ = variable.name;\n        /** @type {string} */\n        this.id_ = variable.id ? variable.id : Entry.generateHash();\n        this.type = variable.variableType || 'variable';\n        /** @type {entry object.id} */\n        this.object_ = variable.object || null;\n        /** @type {boolean} */\n        this.isCloud_ = variable.isCloud || false;\n        this.isRealTime_ = variable.isRealTime || false;\n        this.cloudDate = variable.cloudDate || false;\n        this.cloudVariable = CloudVariable.getInstance();\n\n        this._nameWidth = null;\n        this._valueWidth = null;\n\n        /** @type {number||string} */\n        const parsedValue = Entry.parseNumber(variable.value);\n        if (typeof parsedValue === 'number') {\n            this.value_ = parsedValue;\n        } else if (!variable.value) {\n            this.value_ = 0;\n        } else {\n            this.value_ = variable.value;\n        }\n\n        if (!variable.isClone) {\n            /** @type {boolean} */\n            this.visible_ =\n                variable.visible || typeof variable.visible === 'boolean' ? variable.visible : true;\n            /** @type {number} */\n            this.x_ = variable.x ? variable.x : null;\n            /** @type {number} */\n            this.y_ = variable.y ? variable.y : null;\n            const fontFamily = EntryStatic.fontFamily || \"NanumGothic, 'Nanum Gothic'\";\n            this.BORDER = 6;\n            this.FONT = `10pt ${fontFamily}`;\n            this.VALUE_FONT = `9pt ${fontFamily}`;\n        }\n\n        Entry.addEventListener('workspaceChangeMode', this.updateView.bind(this));\n    }\n\n    /**\n     * Generate variable view on canvas\n     * @param {number} variableIndex index of this variable for render position\n     */\n    generateView(variableIndex) {\n        const type = this.type;\n        if (type === 'variable' || type === 'timer' || type === 'answer' || type === 'stt') {\n            this.view_ = GEHelper.newContainer();\n            this.rect_ = GEHelper.newGraphic();\n            this.view_.addChild(this.rect_);\n            this.view_.variable = this;\n            this.view_.visible = this.visible_;\n            this.view_.mouseEnabled = true;\n            GEDragHelper.handleDrag(this.view_);\n\n            // Stage 의 변수박스를 만든다.\n            this.wrapper_ = GEHelper.newGraphic();\n            this.view_.addChild(this.wrapper_);\n            this.textView_ = GEHelper.textHelper.newText(\n                'asdf',\n                this.FONT,\n                '#000000',\n                'alphabetic'\n            );\n            this.textView_.x = 4;\n            if (GEHelper.isWebGL) {\n                this.textView_.y = this.GL_VAR_POS.LABEL_Y;\n            } else {\n                this.textView_.y = 2.5;\n            }\n            this.view_.addChild(this.textView_);\n            this.valueView_ = GEHelper.textHelper.newText(\n                'asdf',\n                this.VALUE_FONT,\n                '#ffffff',\n                'alphabetic'\n            );\n            const variableLength = Entry.variableContainer.variables_.length;\n\n            const { x, y } = VariableBP.add(\n                this.id_,\n                this.x_,\n                this.y_,\n                this.getRealWidth(),\n                this.getRealHeight()\n            );\n\n            if (this.getX() && this.getY()) {\n                this.setX(this.getX());\n                this.setY(this.getY());\n            } else {\n                //TODO\n                // console.log(10 - 240 + Math.floor((variableLength % 66) / 11) * 80, x);\n                // console.log(\n                //     variableIndex * 28 + 20 - 135 - Math.floor(variableLength / 11) * 264,\n                //     y\n                // );\n                this.setX(x - 230);\n                this.setY(y - 105);\n                // this.setX(10 - 240 + Math.floor((variableLength % 66) / 11) * 80);\n                // this.setY(variableIndex * 28 + 20 - 135 - Math.floor(variableLength / 11) * 264);\n            }\n\n            this.view_.addChild(this.valueView_);\n            if (Entry.type === 'workspace') {\n                this.view_.cursor = 'move';\n            }\n            this.view_.on(GEDragHelper.types.DOWN, function(evt) {\n                if (Entry.type !== 'workspace') {\n                    return;\n                }\n                this.offset = {\n                    x: this.x - (evt.stageX * 0.75 - 240),\n                    y: this.y - (evt.stageY * 0.75 - 135),\n                };\n            });\n\n            this.view_.on(GEDragHelper.types.MOVE, function(evt) {\n                if (Entry.type !== 'workspace') {\n                    return;\n                }\n                this.variable.setX(evt.stageX * 0.75 - 240 + this.offset.x);\n                this.variable.setY(evt.stageY * 0.75 - 135 + this.offset.y);\n                this.variable.updateView();\n            });\n        }\n\n        this.setVisible(this.isVisible());\n        Entry.stage.loadVariable(this);\n    }\n\n    /**\n     * this.view_ 를 수정 후, 엔트리에 새로 그리기 요청을 한다.\n     * generateView 혹은 updateView 가 이상하게 그려진다면, 혹시 variableType 이 잘못되었는지 확인.\n     */\n    updateView() {\n        if (!this.view_) {\n            return;\n        }\n\n        if (this.isVisible()) {\n            this._adjustSingleViewPosition();\n            const oldContent = this.textView_.text;\n            let newContent;\n            if (this.object_) {\n                const obj = Entry.container.getObject(this.object_);\n                if (obj) {\n                    newContent = `${obj.name}:${this.getName()}`;\n                } else {\n                    newContent = this.getName();\n                }\n            } else {\n                newContent = this.getName();\n            }\n\n            if (oldContent !== newContent) {\n                this.textView_.text = newContent;\n                this._nameWidth = null;\n            }\n\n            if (this.isNumber()) {\n                if (this.value_[0] !== 0 && Entry.isInteger(this.value_)) {\n                    this.valueView_.text = `${this.getValue()}`;\n                } else {\n                    this.valueView_.text = Number(this.getValue())\n                        .toFixed(2)\n                        .replace('.00', '');\n                }\n            } else {\n                this.valueView_.text = this.getValue();\n            }\n\n            if (this._nameWidth === null) {\n                this._nameWidth = this.textView_.getMeasuredWidth();\n            }\n            this._adjustSingleValueViewPosition();\n\n            // INFO: Number체크는 slide 일때만 하도록 처리 기본 문자로 처리함(#4876)\n\n            if (this._valueWidth === null) {\n                this._valueWidth = this.valueView_.getMeasuredWidth();\n            }\n            const colorSet = EntryStatic.colorSet.canvas || {};\n            this._adjustSingleViewBox(colorSet.variable || '#4f80ff');\n        }\n\n        bpReplace(this.id_, this.x_, this.y_, this.getRealWidth(), this.getRealHeight());\n        Entry.requestUpdate = true;\n    }\n\n    /**\n     * stage 내 변수 / 타이머 / 대답 뷰의 크기와 위치를 조정한다.\n     * wrapper 의 이미지는 동일하다.\n     * rr(RectRadius) 의 인자는 각각 x, y, width, height, radius\n     * @param {string} boxFillAndStrokeColor\n     * @protected\n     */\n    _adjustSingleViewBox(boxFillAndStrokeColor) {\n        // TODO slider updateView 만 rect_.graphics 를 따로 씀. rr 인자 constants 로 묶을 것.\n        const colorSet = EntryStatic.colorSet.canvas || {};\n        this.rect_.graphics\n            .clear()\n            .f('#ffffff')\n            .ss(1, 2, 0)\n            .s(colorSet.border || '#aac5d5')\n            .rr(0, -14, this._nameWidth + this._valueWidth + 35, 24, 4);\n        this.wrapper_.graphics\n            .clear()\n            .f(boxFillAndStrokeColor)\n            .ss(1, 2, 0)\n            .s(boxFillAndStrokeColor)\n            .rr(this._nameWidth + 14, -10, this._valueWidth + 15, 16, this.RECT_RADIUS);\n    }\n\n    _adjustSingleViewPosition() {\n        this.view_.x = this.getX();\n        this.view_.y = this.getY();\n    }\n\n    _adjustSingleValueViewPosition() {\n        this.valueView_.x = this._nameWidth + 21;\n        if (GEHelper.isWebGL) {\n            this.valueView_.y = this.GL_VAR_POS.VALUE_Y;\n        } else {\n            this.valueView_.y = 1.5;\n        }\n    }\n\n    /**\n     * Variable name getter\n     * @return {string}\n     */\n    getName() {\n        return this.name_;\n    }\n\n    /**\n     * Variable name setter\n     * @param {!string} variableName\n     */\n    setName(variableName) {\n        Entry.assert(typeof variableName === 'string', 'Variable name must be string');\n        this.name_ = variableName;\n        this._nameWidth = null;\n        this.updateView();\n        Entry.requestUpdateTwice = true;\n    }\n\n    /**\n     * Variable id getter\n     * @return {string}\n     */\n    getId() {\n        return this.id_;\n    }\n\n    setId(id) {\n        this.id_ = id;\n    }\n\n    /**\n     * Variable value getter\n     * @return {number}\n     */\n    getValue() {\n        if (!this.isRealTime_) {\n            return this.value_;\n        } else {\n            const { value } =\n                this.cloudVariable.get({\n                    variableType: this.type,\n                    id: this.id_,\n                }) || {};\n            return value || this.value_;\n        }\n    }\n\n    /**\n     * Verify value is number\n     * @return {boolean}\n     */\n    isNumber() {\n        return Entry.Utils.isNumber(this.value_);\n    }\n\n    /**\n     * Variable value setter\n     * @param {!string} variableValue\n     */\n    setValue(value) {\n        if (!this.isRealTime_) {\n            this.value_ = value;\n            this._valueWidth = null;\n            this.updateView();\n            Entry.requestUpdateTwice = true;\n        } else {\n            return new Promise(async (resolve, reject) => {\n                try {\n                    await this.cloudVariable.set(\n                        {\n                            variableType: this.type,\n                            id: this.id_,\n                        },\n                        value\n                    );\n                    this.value_ = value;\n                    this._valueWidth = null;\n                    this.updateView();\n                    Entry.requestUpdateTwice = true;\n                    resolve();\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        }\n    }\n\n    /**\n     * Variable visible state getter\n     * @return {boolean}\n     */\n    isVisible() {\n        return this.visible_;\n    }\n\n    /**\n     * Variable visible state setter\n     * @param {!boolean} visibleState\n     */\n    setVisible(visibleState) {\n        Entry.assert(typeof visibleState === 'boolean', 'Variable visible state must be boolean');\n        if (this.visible_ === visibleState) {\n            return;\n        }\n        this.view_.visible = visibleState;\n        this.visible_ = visibleState;\n        this.updateView();\n    }\n\n    /**\n     * X coordinate setter\n     * @param {number} x\n     */\n    setX(x) {\n        /** @type {number} */\n        this.x_ = x;\n        this.updateView();\n    }\n\n    /**\n     * X coordinate getter\n     * @return {number}\n     */\n    getX() {\n        return this.x_;\n    }\n\n    /**\n     * Y coordinate setter\n     * @param {number} y\n     */\n    setY(y) {\n        /** @type {number} */\n        this.y_ = y;\n        this.updateView();\n    }\n\n    /**\n     * Y coordinate getter\n     * @return {number}\n     */\n    getY() {\n        return this.y_;\n    }\n\n    /**\n     * width setter\n     * @param {number} width\n     */\n    setWidth(width) {\n        /** @type {number} */\n        this.width_ = width < 100 ? 100 : width;\n        this.updateView();\n    }\n\n    /**\n     * width getter\n     * @return {number}\n     */\n    getWidth() {\n        return this.width_;\n    }\n\n    getRealWidth() {\n        return Math.ceil(\n            this.textView_.getMeasuredWidth(this.name_) +\n                this.textView_.getMeasuredWidth(this.getValue()) +\n                40\n        );\n    }\n\n    /**\n     * height setter\n     * @param {number} height\n     */\n    setHeight(height) {\n        /** @type {number} */\n        this.height_ = height < 100 ? 100 : height;\n        this.updateView();\n    }\n\n    /**\n     * height getter\n     * @return {number}\n     */\n    getHeight() {\n        return this.height_;\n    }\n\n    getRealHeight() {\n        return Math.ceil(this.textView_.getMeasuredHeight() + 12);\n    }\n\n    /**\n     * save current state data to 'snapshot_'\n     */\n    takeSnapshot() {\n        this.snapshot_ = this.toJSON();\n    }\n\n    /**\n     * load snapshot to current variable\n     */\n    loadSnapshot() {\n        this.snapshot_ && this.syncModel_(this.snapshot_);\n        delete this.snapshot_;\n    }\n\n    /**\n     * sync this model with parameter\n     * @param {!entity model}variableModel\n     * @protected\n     */\n    syncModel_(variableModel) {\n        if (!this.isCloud_ && !this.isRealTime_) {\n            this.setValue(variableModel.value);\n        }\n\n        this.setName(variableModel.name);\n        this.setX(variableModel.x);\n        this.setY(variableModel.y);\n        this.setVisible(variableModel.visible);\n        this.isCloud_ = variableModel.isCloud;\n        this.isRealTime_ = variableModel.isRealTime;\n        this.cloudDate = variableModel.cloudDate;\n    }\n\n    /**\n     * convert this variable's data to JSON.\n     * @return {JSON}\n     */\n    toJSON() {\n        const json = {};\n        json.name = this.name_;\n        json.id = this.id_;\n        json.visible = this.visible_;\n        json.value = this.value_;\n        json.variableType = this.type;\n        json.isCloud = this.isCloud_;\n        json.isRealTime = this.isRealTime_;\n        json.cloudDate = this.cloudDate;\n        json.object = this.object_;\n        json.x = this.x_;\n        json.y = this.y_;\n        return json;\n    }\n\n    /**\n     * Remove self\n     */\n    remove() {\n        //this.parent.dialog = null;\n        VariableBP.remove(this.id_);\n        Entry.stage.removeVariable(this);\n    }\n\n    /**\n     * clone self\n     */\n    clone() {\n        return Entry.Variable.create(Object.assign(this.toJSON(), { isClone: true }));\n    }\n\n    getType() {\n        return this.type;\n    }\n\n    getMinValue() {\n        return this.minValue_;\n    }\n\n    setMinValue(value) {\n        this._valueWidth = null;\n\n        const minValue = value || 0;\n        this.minValue_ = minValue;\n        if (this.value_ < minValue) {\n            this.setValue(minValue);\n        }\n        this.isMinFloat = Entry.isFloat(this.minValue_);\n        this.updateView();\n    }\n\n    getMaxValue() {\n        return this.maxValue_;\n    }\n\n    setMaxValue(value) {\n        this._valueWidth = null;\n\n        const maxValue = value || 100;\n        this.maxValue_ = maxValue;\n        if (this.value_ > maxValue) {\n            this.value_ = maxValue;\n        }\n        this.isMaxFloat = Entry.isFloat(this.maxValue_);\n        this.updateView();\n    }\n\n    isFloatPoint() {\n        return this.isMaxFloat || this.isMinFloat;\n    }\n\n    getCloudDate() {\n        return this.cloudDate;\n    }\n\n    setCloudDate(cloudDate) {\n        this.cloudDate = cloudDate;\n    }\n\n    getArray() {\n        return this.array_;\n    }\n\n    setArray(array) {\n        this.array_ = array;\n        this.updateView();\n        Entry.requestUpdateTwice = true;\n    }\n}\n\n// Entry.Variable = Variable;\n// add export\nexport default Variable;\n"
  },
  {
    "path": "src/class/variable_container.js",
    "content": "/**\n * @fileoverview Variable container for variable object\n */\n'use strict';\n\nimport SimpleBar from 'simplebar';\nimport xssFilters from 'xss-filters';\nimport CloudVariable from '../extensions/CloudVariable';\nimport _get from 'lodash/get';\nimport _isFunction from 'lodash/isFunction';\nimport _find from 'lodash/find';\nimport _includes from 'lodash/includes';\nimport _some from 'lodash/some';\nimport _memoize from 'lodash/memoize';\n\n/**\n * Block variable constructor\n * @param {variable model} variable\n * @constructor\n */\nEntry.VariableContainer = class VariableContainer {\n    constructor() {\n        this.cloudVariable = CloudVariable.getInstance();\n        this.variables_ = [];\n        this.messages_ = [];\n        this.lists_ = [];\n        this.functions_ = {};\n        this.viewMode_ = 'all';\n        this.selected = null;\n        this.variableAddPanel = {\n            isOpen: false,\n            info: {\n                object: null,\n                isCloud: false,\n                isRealTime: false,\n            },\n        };\n        this.listAddPanel = {\n            isOpen: false,\n            info: {\n                object: null,\n                isCloud: false,\n                isRealTime: false,\n            },\n        };\n        this.messageAddPanel = {\n            isOpen: false,\n            info: {\n                object: null,\n                isCloud: false,\n            },\n        };\n        this.selectedVariable = null;\n        this._variableRefs = [];\n        this._messageRefs = [];\n        this._functionRefs = [];\n        this._filterTabs = {};\n        this.listView_ = null;\n\n        Entry.addEventListener('workspaceChangeMode', this.updateList.bind(this));\n        Entry.addEventListener(\n            'changeFuncVariableListSize',\n            this.updateFuncVariableList.bind(this)\n        );\n    }\n\n    #removeChildrenClass({ children }, className) {\n        for (const index in children) {\n            const dom = children[index];\n            if (dom.removeClass) {\n                dom.removeClass(className);\n            }\n        }\n    }\n\n    createDom(view) {\n        const createElement = Entry.createElement;\n        const that = this;\n\n        this.filterElements = {};\n        this.view_ = view;\n        const selectView = createElement('table')\n            .addClass('entryVariableSelectorWorkspace')\n            .appendTo(this.view_);\n\n        $(selectView).on('click tab', 'td', function () {\n            if (this.disabled) {\n                return;\n            }\n\n            Entry.do(\n                'variableContainerSelectFilter',\n                this.getAttribute('data-type'),\n                that.viewMode_\n            );\n        });\n\n        let selectTrView = createElement('tr').appendTo(selectView);\n\n        const allButton = this.createSelectButton('all')\n            .addClass('selected', 'allButton')\n            .appendTo(selectTrView);\n        this.filterElements.all = allButton;\n\n        allButton.setAttribute('rowspan', '2');\n        this.filterElements.variable = this.createSelectButton(\n            'variable',\n            Entry.variableEnable\n        ).appendTo(selectTrView);\n        this.filterElements.message = this.createSelectButton(\n            'message',\n            Entry.messageEnable\n        ).appendTo(selectTrView);\n\n        selectTrView = createElement('tr').appendTo(selectView);\n        this.filterElements.list = this.createSelectButton('list', Entry.listEnable).appendTo(\n            selectTrView\n        );\n        this.filterElements.func = this.createSelectButton('func', Entry.functionEnable).appendTo(\n            selectTrView\n        );\n\n        const listViewContainer = createElement('div').addClass('entryVariableListWorkspace');\n        this.view_.appendChild(listViewContainer);\n\n        const listView = createElement('div')\n            .addClass('entryVariableAdd_box')\n            .appendTo(listViewContainer);\n\n        $(listView).on('mouseenter', '.entryVariableListElementWorkspace', function () {\n            this.addClass('active');\n        });\n\n        $(listView).on('mouseleave', '.entryVariableListElementWorkspace', function () {\n            this.removeClass('active');\n        });\n\n        this.listView_ = listView;\n\n        this.generateAddButtons();\n        this.generateVariableAddView();\n        this.generateListAddView();\n        this.generateMessageAddView();\n\n        return view;\n    }\n\n    generateAddButtons() {\n        const createElement = Entry.createElement;\n        const variableAddButton = createElement('button').addClass('entryVariableAddWorkspace');\n        variableAddButton.textContent = Lang.Workspace.variable_add;\n        this.variableAddButton_ = variableAddButton;\n\n        const messageAddButton = createElement('button').addClass('entryVariableAddWorkspace');\n        messageAddButton.textContent = Lang.Workspace.message_add;\n        this.messageAddButton_ = messageAddButton;\n\n        const listAddButton = createElement('button').addClass('entryVariableAddWorkspace');\n        listAddButton.textContent = Lang.Workspace.list_create;\n        this.listAddButton_ = listAddButton;\n\n        const functionAddButton = createElement('button')\n            .addClass('entryVariableAddWorkspace')\n            .addClass('funcAddButton');\n        functionAddButton.textContent = Lang.Workspace.function_add;\n        this.functionAddButton_ = functionAddButton;\n    }\n\n    /**\n     * @param {String} type\n     * @param {?Boolean} isEnable\n     */\n    createSelectButton(type, isEnable = true) {\n        const view = Entry.createElement('td').addClass('entryVariableSelectButtonWorkspace', type);\n        const textView = Entry.createElement('div');\n        const text = Entry.createElement('span').addClass('text').appendTo(textView);\n\n        view.setAttribute('data-type', type);\n        view.appendChild(textView);\n        text.innerText = Lang.Workspace[type];\n\n        if (isEnable === false) {\n            view.addClass('disabled');\n            view.disabled = true;\n        }\n\n        this._filterTabs[type] = view;\n        return view;\n    }\n\n    /**\n     * @param {String} type\n     */\n    selectFilter(type) {\n        _.each(this.view_.getElementsByTagName('td'), (elem) => {\n            if (elem.hasClass(type)) {\n                elem.addClass('selected');\n            } else {\n                elem.removeClass('selected');\n            }\n        });\n        this.viewMode_ = type;\n        this.select();\n        this.updateList();\n    }\n\n    updateVariableAddView(type = 'variable') {\n        const {\n            info: { isCloud, object, isRealTime },\n            view,\n        } = this._getAddPanel(type);\n        const { cloudCheck, globalCheck, localCheck, cloudWrapper } = view;\n\n        this.#removeChildrenClass(cloudCheck, 'on');\n        const [normal, cloud, realtime] = cloudCheck.children;\n        if (isCloud) {\n            cloud.addClass('on');\n        } else if (isRealTime) {\n            realtime.addClass('on');\n        } else {\n            normal.addClass('on');\n        }\n\n        if (object) {\n            globalCheck.removeClass('on');\n            localCheck.addClass('on');\n            cloudWrapper.addClass('entryVariableAddSpaceUnCheckedWorkspace');\n        } else {\n            globalCheck.addClass('on');\n            localCheck.removeClass('on');\n            cloudWrapper.removeClass('entryVariableAddSpaceUnCheckedWorkspace');\n        }\n    }\n\n    /**\n     * @param {object|Entry.Variable} object\n     */\n    select(object) {\n        object = this.selected == object ? null : object;\n        if (this.selected) {\n            this.selected.listElement.removeClass('unfold');\n            this.selected.listElement.addClass('fold');\n            this.selected.listElement.removeClass('selected');\n            if (this.selected.callerListElement) {\n                $(this.selected.callerListElement).remove();\n                delete this.selected.callerListElement;\n            }\n            this.selected = null;\n        }\n        if (!object) {\n            return;\n        }\n        object.listElement.addClass('selected');\n        this.selected = object;\n        this.selected.listElement.removeClass('fold');\n        this.selected.listElement.addClass('unfold');\n        if (object instanceof Entry.Variable) {\n            if (object.type === 'variable') {\n                this.generateVariableSettingView(object);\n                this.updateVariableSettingView(object);\n            } else if (object.type === 'list') {\n                this.generateListSettingView(object);\n                this.updateListSettingView(object);\n            }\n            if (object.object_) {\n                Entry.container.selectObject(object.object_, true);\n            }\n        } else if (object instanceof Entry.Func) {\n            this.generateFuncSettingView(object);\n            this.updateFuncSettingView(object);\n        } else {\n            this.renderMessageReference(object);\n        }\n    }\n\n    getMessage(id) {\n        return _.find(this.messages_, { id });\n    }\n\n    /**\n     * @param {object} message\n     */\n    renderMessageReference(message) {\n        const messageId = message.id;\n\n        const hasInFunction = this.hasParamBlockInFunction(messageId);\n        const callers = this._messageRefs.filter(({ block: { params } }) =>\n            _includes(params, messageId)\n        );\n\n        message.usedView && $(message.usedView).remove();\n        const usedWrapper = Entry.createElement('div').addClass('use_block');\n\n        const boxSubject = Entry.createElement('span').addClass('box_sjt').appendTo(usedWrapper);\n\n        if (callers.length) {\n            boxSubject.textContent = Entry.Utils.stringFormat(\n                Lang.Workspace.use_block_objects1,\n                callers.length\n            );\n\n            const listView = Entry.createElement('ul').addClass('obj_list').appendTo(usedWrapper);\n            const fragment = document.createDocumentFragment();\n            callers.forEach((caller) => {\n                const element = Entry.createElement('li');\n                const object = caller.object;\n                if (!object.entity) {\n                    return;\n                }\n                !caller.object.thumbnailView_ && caller.object.generateView();\n                const thumb = element.appendChild(caller.object.thumbnailView_.cloneNode());\n                thumb.addClass('thmb');\n                element.appendChild(thumb);\n                Entry.createElement('span').addClass('text').appendTo(element).textContent =\n                    `${caller.object.name} : ${Lang.Blocks[`START_${caller.block.type}`]}`;\n                element.bindOnClick((e) => {\n                    e.stopPropagation();\n                    if (Entry.playground.object !== caller.object) {\n                        Entry.container.selectObject();\n                        Entry.container.selectObject(caller.object.id, true);\n                    }\n                    const block = caller.block;\n                    const board = _.result(block.view, 'getBoard');\n                    if (board) {\n                        board.setSelectedBlock(block.view);\n                    }\n                    Entry.playground.toggleOnVariableView();\n                    Entry.playground.changeViewMode('variable');\n                });\n                fragment.appendChild(element);\n            });\n            listView.appendChild(fragment);\n        } else {\n            const caution = Entry.createElement('div')\n                .addClass('caution_dsc')\n                .appendTo(usedWrapper);\n            caution.textContent = Lang.Workspace.no_use;\n\n            boxSubject.textContent = Entry.Utils.stringFormat(\n                Lang.Workspace.use_block_objects2,\n                callers.length\n            );\n        }\n\n        if (hasInFunction) {\n            const usedInFunction = Entry.createElement('div')\n                .addClass('used_function_dsc')\n                .appendTo(usedWrapper);\n            usedInFunction.textContent = Lang.Workspace.use_block_function;\n        }\n\n        message.usedView = usedWrapper;\n        message.listElement.appendChild(usedWrapper);\n    }\n\n    /**\n     * @param {object} variable\n     */\n    renderVariableReference(variable) {\n        const variableId = variable.id_;\n\n        const hasInFunction = this.hasParamBlockInFunction(variableId);\n        const callers = this._variableRefs.filter(({ block: { params } }) =>\n            _includes(params, variableId)\n        );\n\n        const usedWrapper = Entry.createElement('div').addClass('use_obj');\n        const usedSubject = Entry.createElement('span').addClass('box_sjt').appendTo(usedWrapper);\n\n        const listView = Entry.createElement('ul').addClass('obj_list').appendTo(usedWrapper);\n\n        if (callers.length) {\n            usedSubject.textContent = Entry.Utils.stringFormat(\n                Lang.Workspace.use_block_objects1,\n                callers.length\n            );\n            const fragment = document.createDocumentFragment();\n\n            callers.forEach((caller) => {\n                const element = Entry.createElement('li');\n                const object = caller.object;\n                if (!object.entity) {\n                    return;\n                }\n                !caller.object.thumbnailView_ && caller.object.generateView();\n                const thumb = caller.object.thumbnailView_.cloneNode();\n                thumb.addClass('thmb');\n                element.appendChild(thumb);\n                Entry.createElement('span').addClass('text').appendTo(element).textContent =\n                    `${caller.object.name} : ${Lang.Blocks[`VARIABLE_${caller.block.type}`]}`;\n                element.variable = variable;\n                element.bindOnClick((e) => {\n                    e.stopPropagation();\n                    if (Entry.playground.object != caller.object) {\n                        Entry.container.selectObject();\n                        Entry.container.selectObject(caller.object.id, true);\n                    }\n                    const block = caller.block;\n                    const board = _.result(block.view, 'getBoard');\n                    if (board) {\n                        board.setSelectedBlock(block.view);\n                    }\n                    Entry.playground.toggleOnVariableView();\n                    Entry.playground.changeViewMode('variable');\n                });\n                fragment.appendChild(element);\n            });\n            listView.appendChild(fragment);\n        } else {\n            usedSubject.textContent = Entry.Utils.stringFormat(\n                Lang.Workspace.use_block_objects2,\n                callers.length\n            );\n            Entry.createElement('div').addClass('caution_dsc').appendTo(listView).textContent =\n                Lang.Workspace.no_use;\n        }\n\n        if (hasInFunction) {\n            const usedInFunction = Entry.createElement('div')\n                .addClass('used_function_dsc')\n                .appendTo(listView);\n            usedInFunction.textContent = Lang.Workspace.use_block_function;\n        }\n\n        this.variableSettingView && this.variableSettingView.appendChild(usedWrapper);\n        this.listSettingView && this.listSettingView.appendChild(usedWrapper);\n    }\n\n    generateFuncSettingView(func) {\n        const createElement = Entry.createElement;\n\n        const element = createElement('div')\n            .addClass('attr_inner_box')\n            .bindOnClick((e) => e.stopPropagation());\n\n        if (this.funcSettingView) {\n            $(this.funcSettingView).remove();\n            delete this.funcSettingView;\n        }\n        this.funcSettingView = element;\n\n        const funcAttr = createElement('div').addClass('func_attr').appendTo(element);\n        if (this._isPythonMode()) {\n            funcAttr.addClass('hidden');\n        }\n        const boxSubject = createElement('span').addClass('box_sjt').appendTo(funcAttr);\n        boxSubject.textContent = Lang.Workspace.func_property;\n\n        this.generateFuncDefaultView(funcAttr, func);\n        this.generateFuncLocalVariableView(funcAttr, func);\n        this.generateFuncValuesView(funcAttr, func);\n        this.renderFunctionReference(func);\n\n        this.funcSettingView.func = funcAttr;\n        func.listElement.appendChild(this.funcSettingView);\n    }\n\n    isUsedFunction(func) {\n        if ([...this._functionRefs].some((item) => item.block.data.type === `func_${func.id}`)) {\n            return true;\n        } else if (\n            Object.keys(this.functions_).some((key) => {\n                const item = this.functions_[key]?.content.findByType(`func_${func.id}`);\n                return Boolean(item);\n            })\n        ) {\n            return true;\n        }\n\n        return false;\n    }\n\n    generateFuncDefaultView(element, func) {\n        const createElement = Entry.createElement;\n\n        // 슬라이드 입력창\n        const checkInputBox = createElement('div').addClass('check_inpt').appendTo(element);\n\n        const resultCheckBox = createElement('div').addClass('chk_box').appendTo(checkInputBox);\n        element.resultCheck = createElement('span')\n            .addClass('entryFuncAddResultCheckWorkspace')\n            .bindOnClick(() => {\n                if (this.isUsedFunction(func)) {\n                    return Entry.modal.alert(Lang.Msgs.cannot_delete_function);\n                }\n                Entry.do('funcChangeType', func);\n            })\n            .appendTo(resultCheckBox);\n\n        const resultCheckText = createElement('span')\n            .addClass('chk_text')\n            .bindOnClick(() => {\n                if (this.isUsedFunction(func)) {\n                    return Entry.modal.alert(Lang.Msgs.cannot_delete_function);\n                }\n                Entry.do('funcChangeType', func);\n            })\n            .appendTo(resultCheckBox);\n        resultCheckText.textContent = Lang.Workspace.check_result_value;\n    }\n\n    generateFuncLocalVariableView(element, func) {\n        const createElement = Entry.createElement;\n\n        const checkInputBox = createElement('div').addClass('check_inpt').appendTo(element);\n\n        const localVarCheckBox = createElement('div').addClass('chk_box').appendTo(checkInputBox);\n\n        element.localVarCheck = createElement('span')\n            .addClass('entryFuncAddLocalVarCheckWorkspace')\n            .bindOnClick(() => {\n                const isUseBlock = func.content.hasBlockType([\n                    'set_func_variable',\n                    'get_func_variable',\n                ]);\n                if (isUseBlock) {\n                    Entry.modal\n                        .confirm(Lang.Msgs.local_variable_deletion_warning)\n                        .then((result) => {\n                            if (result) {\n                                func.content\n                                    .getBlockList(false, ['set_func_variable', 'get_func_variable'])\n                                    .map(\n                                        Entry.Utils.runAsyncCurry(async (block) => {\n                                            Entry.do('destroyBlock', block).isPass(true);\n                                        })\n                                    );\n                                Entry.do('toggleFuncUseLocalVariables', func);\n                            }\n                        });\n                } else {\n                    Entry.do('toggleFuncUseLocalVariables', func);\n                }\n            })\n            .appendTo(localVarCheckBox);\n\n        const localVarCheckText = createElement('span')\n            .addClass('chk_text')\n            .bindOnClick(() => {\n                element.localVarCheck.click();\n            })\n            .appendTo(localVarCheckBox);\n        localVarCheckText.textContent = Lang.Workspace.check_local_variable;\n\n        const countInputBox = createElement('div').addClass('cnt_inpt').appendTo(checkInputBox);\n\n        const buttonMinus = createElement('a')\n            .addClass('btn_cnt')\n            .bindOnClick((e) => {\n                const disabled = e?.target?.hasAttribute('disabled');\n                if (disabled) {\n                    return;\n                }\n                Entry.do('funcLocalVarChangeLength', func, 'minus');\n                Entry.dispatchEvent('changeFuncVariableListSize');\n            })\n            .appendTo(countInputBox);\n        this.funcSettingView.minus = buttonMinus;\n\n        const limitValue = 10;\n        const maxlength = 2;\n\n        const countInput = createElement('input').appendTo(countInputBox);\n        countInput.setAttribute('autocomplete', 'off');\n        countInput.setAttribute('type', 'text');\n        countInput.setAttribute('maxlength', maxlength);\n        countInput.value = func.localVariables?.length || 0;\n\n        countInput.onblur = (e) => {\n            const disabled = e?.target?.hasAttribute('disabled');\n            if (disabled) {\n                return;\n            }\n            let value = _get(e, 'target.value', 0);\n            if (value >= limitValue) {\n                value = limitValue;\n            }\n            Entry.do('funcLocalVarChangeLength', func, value);\n            Entry.dispatchEvent('changeFuncVariableListSize');\n        };\n        countInput.onkeypress = Entry.Utils.blurWhenEnter;\n\n        const buttonPlus = createElement('a')\n            .addClass('btn_cnt')\n            .addClass('plus')\n            .bindOnClick((e) => {\n                const disabled = e?.target?.hasAttribute('disabled');\n                if (disabled) {\n                    return;\n                }\n                const variableLength = func.localVariables.length;\n                if (variableLength < limitValue) {\n                    Entry.do('funcLocalVarChangeLength', func, 'plus');\n                    Entry.dispatchEvent('changeFuncVariableListSize');\n                }\n            })\n            .appendTo(countInputBox);\n        this.funcSettingView.plus = buttonPlus;\n\n        this.funcSettingView.lengthInput = countInput;\n    }\n\n    generateFuncValuesView(element, func) {\n        const localVariables = func.getLocalVariables() || [];\n\n        if (localVariables?.length === 0) {\n            return;\n        }\n\n        const createElement = Entry.createElement;\n\n        const countGroup = createElement('div').addClass('cnt_group').appendTo(element);\n        const countLabel = createElement('div').addClass('cnt_label').appendTo(countGroup);\n        countLabel.textContent = Lang.Workspace.local_variable;\n        const scrollBox = createElement('div')\n            .addClass('scroll_box simplebar-content-wrapper')\n            .appendTo(countGroup);\n        const el = new SimpleBar(scrollBox, { autoHide: false });\n        const parent = /* html */ `<ol class=\"cnt_list\">{1}</ol>`;\n        this.funcSettingView.countGroup = countGroup;\n        this.funcSettingView.scrollBox = scrollBox;\n        this.funcSettingView.simpleBar = el;\n        const listValues = el.getContentElement();\n        this.funcSettingView.listValues = listValues;\n        const infinityScroll = new Entry.VirtualScroll(listValues, {\n            dataWrapper: parent,\n            itemHeight: 24,\n            groupSize: 10,\n        });\n        this.funcSettingView.infinityScroll = infinityScroll;\n\n        const $listValues = $(listValues);\n        $listValues.empty();\n        $listValues.off();\n\n        const data = localVariables?.map((data, i) => {\n            const value = String(data.name).replace(/\\$/g, '&#36;');\n            return this.createListValueElement(i, value, 1);\n        });\n\n        infinityScroll.assignData(data);\n        infinityScroll.show();\n        $listValues.on(\n            'change',\n            'input',\n            _.debounce((e) => {\n                const { target } = e;\n                const index = target.getAttribute('data-index');\n                func.changeNameLocalVariable(target.value, index);\n            })\n        );\n        $listValues.on('focus', 'input', Entry.Utils.setFocused);\n        $listValues.on('keypress', 'input', Entry.Utils.blurWhenEnter);\n        $listValues.on('click', 'a', function () {\n            const index = this.getAttribute('data-index');\n            Entry.do('removeFuncLocalVariableByIndex', func, index);\n            Entry.dispatchEvent('changeFuncVariableListSize');\n        });\n    }\n\n    updateFuncScrollBar(func) {\n        const view = this.funcSettingView;\n        if (!view) {\n            return;\n        }\n\n        if (!view.infinityScroll) {\n            this.generateFuncValuesView(this.funcSettingView.func, func);\n            requestAnimationFrame(() => {\n                this.updateFuncScrollBar(func);\n            });\n            return;\n        }\n\n        const localVariables = func.getLocalVariables() || [];\n        const { infinityScroll, countGroup, lengthInput, simpleBar, scrollBox } = view;\n\n        lengthInput.value = func.localVariables?.length || 0;\n\n        if (localVariables?.length === 0) {\n            countGroup?.addClass('entryRemove');\n            return;\n        }\n        countGroup?.removeClass('entryRemove');\n\n        const data = localVariables?.map((data, i) => {\n            const value = String(data.name).replace(/\\$/g, '&#36;');\n            return this.createListValueElement(i, value, 1);\n        });\n\n        infinityScroll.assignData(data);\n        infinityScroll.show();\n\n        if (localVariables?.length > 4) {\n            scrollBox.addClass('on');\n        } else {\n            scrollBox.removeClass('on');\n        }\n        simpleBar.recalculate();\n    }\n\n    updateFuncSettingView(func) {\n        const view = this.funcSettingView;\n        if (!view) {\n            return;\n        }\n\n        if (func.type === 'value') {\n            view.func.resultCheck.addClass('on');\n        } else {\n            view.func.resultCheck.removeClass('on');\n        }\n\n        if (func.useLocalVariables) {\n            view.func.localVarCheck.addClass('on');\n            this.funcSettingView.minus.removeAttribute('disabled');\n            this.funcSettingView.plus.removeAttribute('disabled');\n            this.funcSettingView.lengthInput.removeAttribute('disabled');\n            this.funcSettingView?.countGroup?.removeAttribute('disabled');\n        } else {\n            view.func.localVarCheck.removeClass('on');\n            this.funcSettingView.minus.setAttribute('disabled', '');\n            this.funcSettingView.plus.setAttribute('disabled', '');\n            this.funcSettingView.lengthInput.setAttribute('disabled', '');\n            this.funcSettingView?.countGroup?.setAttribute('disabled', '');\n        }\n\n        this.updateFuncScrollBar(func);\n    }\n\n    /**\n     * @param {object} variable\n     */\n    renderFunctionReference(func) {\n        const createElement = Entry.createElement;\n        const funcId = func.id;\n        const hasInFunction = this.hasFuncBlockInFunction(funcId);\n        const callers = [...this._functionRefs].filter(\n            (item) => item.block.data.type === `func_${funcId}`\n        );\n\n        func.usedView && $(func.usedView).remove();\n        const wrapper = createElement('div').addClass('use_block');\n\n        const boxSubject = createElement('span').addClass('box_sjt').appendTo(wrapper);\n\n        if (callers.length) {\n            boxSubject.textContent = Entry.Utils.stringFormat(\n                Lang.Workspace.use_block_objects1,\n                callers.length\n            );\n            const listView = createElement('ul').addClass('obj_list').appendTo(wrapper);\n            const fragment = document.createDocumentFragment();\n            callers.forEach((caller) => {\n                const element = createElement('li');\n                const object = caller.object;\n                if (!object.entity) {\n                    return;\n                }\n                !caller.object.thumbnailView_ && caller.object.generateView();\n                const thumb = element.appendChild(caller.object.thumbnailView_.cloneNode());\n                thumb.addClass('thmb');\n                element.appendChild(thumb);\n                const nameElement = createElement('span').addClass('text');\n                nameElement.textContent = caller.object.name;\n                element.appendChild(nameElement);\n                element.bindOnClick(() => {\n                    if (Entry.playground.object != caller.object) {\n                        Entry.container.selectObject();\n                        Entry.container.selectObject(caller.object.id, true);\n                    }\n                    Entry.playground.toggleOnVariableView();\n                    const block = caller.block;\n                    const blockView = block.view;\n                    blockView && blockView.getBoard().setSelectedBlock(block.view);\n                    Entry.playground.changeViewMode('variable');\n                });\n                fragment.appendChild(element);\n            });\n            listView.appendChild(fragment);\n        } else {\n            const caution = createElement('div').addClass('caution_dsc').appendTo(wrapper);\n            caution.textContent = Lang.Workspace.no_use;\n            boxSubject.textContent = Lang.Workspace.use_block_objects2;\n        }\n\n        if (hasInFunction) {\n            const usedInFunction = createElement('div')\n                .addClass('used_function_dsc')\n                .appendTo(wrapper);\n            usedInFunction.textContent = Lang.Workspace.use_block_function;\n        }\n\n        func.usedView = wrapper;\n        this.funcSettingView && this.funcSettingView.appendChild(wrapper);\n    }\n\n    /**\n     * update list view\n     */\n    updateList() {\n        const listView = this.listView_;\n        if (!listView) {\n            return;\n        }\n\n        const isPythonMode = this._isPythonMode();\n        if (isPythonMode) {\n            listView.addClass('entryVariableContainerTextMode');\n        } else {\n            listView.removeClass('entryVariableContainerTextMode');\n        }\n\n        this.clearListElement();\n\n        switch (this.viewMode_) {\n            case 'all':\n                this.updateAllTab();\n                break;\n            case 'message':\n                this.updateMessageTab();\n                break;\n            case 'variable':\n                this.updateVariableTab();\n                break;\n            case 'list':\n                this.updateListTab();\n                break;\n            case 'func':\n                this.updateFuncTab();\n                break;\n        }\n        this.updateSelected();\n    }\n\n    updateFuncVariableList() {\n        [\n            ...(Entry.block?.set_func_variable?.events?.updateFuncVariableList || []),\n            ...(Entry.block?.get_func_variable?.events?.updateFuncVariableList || []),\n        ].forEach((fn) => {\n            if (_isFunction(fn)) {\n                fn();\n            }\n        });\n    }\n\n    makeChildVariableViews(arr, viewFunc, parent = this.listView_) {\n        return _.each(arr, (data) => {\n            !data.listElement && viewFunc(data);\n            if (this._isPythonMode()) {\n                $(data.listElement)\n                    .find('input')\n                    .each(function () {\n                        $(this).attr('disabled', 'disabled');\n                    });\n            } else {\n                $(data.listElement)\n                    .find('input')\n                    .each(function () {\n                        $(this).removeAttr('disabled');\n                    });\n            }\n            parent.appendChild(data.listElement);\n        });\n    }\n\n    clearListElement() {\n        const clearList = [this.listView_];\n        for (const elem of clearList) {\n            while (elem && elem.firstChild) {\n                elem.removeChild(elem.lastChild);\n            }\n        }\n\n        const arrItems = [this.messages_, this.variables_, this.lists_, this.functions_];\n        arrItems.forEach((items) => {\n            Object.values(items).forEach((item) => {\n                if (item.listElement) {\n                    item.listElement.removeClass('unfold').removeClass('selected').addClass('fold');\n                }\n            });\n        });\n\n        if (this.listSettingView) {\n            $(this.listSettingView).remove();\n            delete this.listSettingView;\n        }\n        if (this.variableSettingView) {\n            $(this.variableSettingView).remove();\n            delete this.variableSettingView;\n        }\n        if (this.funcSettingView) {\n            $(this.funcSettingView).remove();\n            delete this.funcSettingView;\n        }\n    }\n\n    updateAllTab() {\n        const createElement = Entry.createElement;\n        const listView = this.listView_;\n        const listWrapper = createElement('div').addClass(\n            'entryVariableSplitterWorkspace unfold all'\n        );\n\n        const listBox = createElement('div').addClass('attr_box unfold').appendTo(listWrapper);\n\n        const list = createElement('div').addClass('list').appendTo(listBox);\n\n        this.makeChildVariableViews(this.messages_, this.createMessageView.bind(this), list);\n        this.makeChildVariableViews(this.variables_, this.createVariableView.bind(this), list);\n        this.makeChildVariableViews(this.lists_, this.createListView.bind(this), list);\n        this.makeChildVariableViews(this.functions_, this.createFunctionView.bind(this), list);\n        listView.appendChild(listWrapper);\n    }\n\n    updateMessageTab() {\n        const createElement = Entry.createElement;\n        const listView = this.listView_;\n\n        if (Entry.isTextMode) {\n            this.messageAddButton_.unBindOnClick().addClass('disabled');\n        } else {\n            this.messageAddButton_\n                .unBindOnClick()\n                .bindOnClick(() => Entry.do('variableContainerClickMessageAddButton'))\n                .removeClass('disabled');\n        }\n        listView.appendChild(this.messageAddButton_);\n        listView.appendChild(this.messageAddPanel.view);\n\n        const messageList = createElement('div').addClass(\n            'entryVariableSplitterWorkspace message unfold'\n        );\n\n        const messageListBox = createElement('div').addClass('attr_box').appendTo(messageList);\n\n        const list = createElement('div').addClass('list').appendTo(messageListBox);\n\n        this.makeChildVariableViews(this.messages_, this.createMessageView.bind(this), list);\n        listView.appendChild(messageList);\n    }\n\n    updateVariableTab() {\n        const createElement = Entry.createElement;\n        const listView = this.listView_;\n        const info = this.variableAddPanel.info;\n        if (info.object && !Entry.playground.object) {\n            info.object = null;\n        }\n\n        if (Entry.isTextMode) {\n            this.variableAddButton_.unBindOnClick().addClass('disabled');\n        } else {\n            this.variableAddButton_\n                .unBindOnClick()\n                .bindOnClick(() => Entry.do('variableContainerClickVariableAddButton'))\n                .removeClass('disabled');\n        }\n\n        listView.appendChild(this.variableAddButton_);\n        listView.appendChild(this.variableAddPanel.view);\n\n        //global list container\n        const globalList = createElement('div').addClass(\n            'entryVariableSplitterWorkspace variable global'\n        );\n        let isGlobalFolded = false;\n\n        const globalListTitle = Entry.createElement('a')\n            .addClass('attr_link')\n            .bindOnClick(() => {\n                isGlobalFolded = !isGlobalFolded;\n                this.foldTab(globalList, isGlobalFolded, gLength);\n            })\n            .appendTo(globalList);\n\n        const globalListBox = createElement('div').addClass('attr_box').appendTo(globalList);\n\n        //local list container\n        const localList = createElement('div').addClass(\n            'entryVariableSplitterWorkspace variable local'\n        );\n        let isLocalFolded = false;\n\n        const localListTitle = Entry.createElement('a')\n            .addClass('attr_link')\n            .bindOnClick(() => {\n                isLocalFolded = !isLocalFolded;\n                this.foldTab(localList, isLocalFolded, lLength);\n            })\n            .appendTo(localList);\n\n        const localListBox = createElement('div').addClass('attr_box').appendTo(localList);\n\n        const { globalV, localV } = _.groupBy(this.variables_, ({ object_ }) =>\n            object_ ? 'localV' : 'globalV'\n        );\n\n        const gLength = (globalV || []).length;\n        const lLength = (localV || []).length;\n        globalListTitle.textContent = `${Lang.Workspace.Variable_used_at_all_objects} (${gLength})`;\n        // eslint-disable-next-line max-len\n        localListTitle.textContent = `${Lang.Workspace.Variable_used_at_special_object} (${lLength})`;\n        this.foldTab(globalList, isGlobalFolded, gLength);\n        this.foldTab(localList, isLocalFolded, lLength);\n\n        listView.appendChild(globalList);\n        this.makeChildVariableViews(globalV, this.createVariableView.bind(this), globalListBox);\n        listView.appendChild(localList);\n        this.makeChildVariableViews(localV, this.createVariableView.bind(this), localListBox);\n        this.updateVariableAddView('variable');\n    }\n\n    foldTab(tab, isFold, count = 0) {\n        if (!count) {\n            return;\n        }\n        if (isFold) {\n            tab.removeClass('unfold');\n            tab.addClass('fold');\n        } else {\n            tab.addClass('unfold');\n            tab.removeClass('fold');\n        }\n    }\n\n    updateListTab() {\n        const createElement = Entry.createElement;\n        const listView = this.listView_;\n        const info = this.listAddPanel.info;\n        if (info.object && !Entry.playground.object) {\n            info.object = null;\n        }\n\n        if (Entry.isTextMode) {\n            this.listAddButton_.unBindOnClick().addClass('disabled');\n        } else {\n            this.listAddButton_\n                .unBindOnClick()\n                .bindOnClick(() => Entry.do('variableContainerClickListAddButton'))\n                .removeClass('disabled');\n        }\n        listView.appendChild(this.listAddButton_);\n        listView.appendChild(this.listAddPanel.view);\n\n        //global list container\n        const globalList = createElement('div').addClass(\n            'entryVariableSplitterWorkspace list global'\n        );\n        let isGlobalFolded = false;\n\n        const globalListTitle = Entry.createElement('a')\n            .addClass('attr_link')\n            .bindOnClick(() => {\n                isGlobalFolded = !isGlobalFolded;\n                this.foldTab(globalList, isGlobalFolded, gLength);\n            })\n            .appendTo(globalList);\n\n        const globalListBox = createElement('div').addClass('attr_box').appendTo(globalList);\n\n        //local list container\n        const localList = createElement('div').addClass(\n            'entryVariableSplitterWorkspace list local'\n        );\n        let isLocalFolded = false;\n\n        const localListTitle = Entry.createElement('a')\n            .addClass('attr_link')\n            .bindOnClick(() => {\n                isLocalFolded = !isLocalFolded;\n                this.foldTab(localList, isLocalFolded, lLength);\n            })\n            .appendTo(localList);\n\n        const localListBox = createElement('div').addClass('attr_box').appendTo(localList);\n\n        const { localV, globalV } = _.groupBy(this.lists_, ({ object_ }) =>\n            object_ ? 'localV' : 'globalV'\n        );\n\n        const gLength = (globalV || []).length;\n        const lLength = (localV || []).length;\n        globalListTitle.textContent = `${Lang.Workspace.List_used_all_objects} (${gLength})`;\n        localListTitle.textContent = `${Lang.Workspace.list_used_specific_objects} (${lLength})`;\n        this.foldTab(globalList, isGlobalFolded, gLength);\n        this.foldTab(localList, isLocalFolded, lLength);\n\n        listView.appendChild(globalList);\n        this.makeChildVariableViews(globalV, this.createListView.bind(this), globalListBox);\n        listView.appendChild(localList);\n        this.makeChildVariableViews(localV, this.createListView.bind(this), localListBox);\n        this.updateVariableAddView('variable');\n    }\n\n    updateFuncTab() {\n        const createElement = Entry.createElement;\n        const listView = this.listView_;\n\n        if (Entry.isTextMode) {\n            this.functionAddButton_.unBindOnClick().addClass('disabled');\n        } else {\n            this.functionAddButton_\n                .unBindOnClick()\n                .bindOnClick(() => Entry.do('funcEditStart', Entry.generateHash()))\n                .removeClass('disabled');\n        }\n        listView.appendChild(this.functionAddButton_);\n\n        const funcList = createElement('div').addClass(\n            'entryVariableSplitterWorkspace func unfold'\n        );\n\n        const funcListBox = createElement('div').addClass('attr_box').appendTo(funcList);\n\n        this.makeChildVariableViews(\n            this.functions_,\n            this.createFunctionView.bind(this),\n            funcListBox\n        );\n        listView.appendChild(funcList);\n    }\n\n    /**\n     * @param {!Array.<message model>} objectModels\n     */\n    setMessages(messages = []) {\n        this.messages_ = messages.map((message) => {\n            if (!message.id) {\n                message.id = Entry.generateHash();\n            }\n            return message;\n        });\n        Entry.playground.reloadPlayground();\n    }\n\n    /**\n     * @param {!Array.<message model>} objectModels\n     */\n    appendMessages(messages) {\n        for (const i in messages) {\n            const message = messages[i];\n            if (!message.id) {\n                message.id = Entry.generateHash();\n            } else if (this.messages_.some((item) => item.id === message.id)) {\n                continue;\n            }\n            let name = message.name;\n            name = this.checkAllVariableName(name, 'messages_', 'name')\n                ? Entry.getOrderedName(name, this.messages_, 'name')\n                : name;\n            message.name = name;\n            this.messages_.push(message);\n        }\n        Entry.playground.reloadPlayground();\n    }\n\n    /**\n     * @param {!Array.<variable model>} variables\n     */\n    setVariables(variables = [], options) {\n        variables.forEach((variable) => {\n            variable = Entry.Variable.create(variable);\n            switch (variable.getType()) {\n                case 'variable':\n                case 'slide':\n                    variable.generateView(this.variables_.length);\n                    this.variables_.push(variable);\n                    break;\n                case 'list':\n                    variable.generateView(this.lists_.length);\n                    this.lists_.push(variable);\n                    break;\n                case 'timer':\n                    this.generateTimer(variable);\n                    break;\n                case 'answer':\n                    this.generateAnswer(variable);\n                    break;\n            }\n        });\n\n        if (_.isEmpty(Entry.engine.projectTimer)) {\n            this.generateTimer();\n        }\n        if (_.isEmpty(Entry.container.inputValue)) {\n            this.generateAnswer();\n        }\n        if (_.isEmpty(Entry.container.sttValue)) {\n            this.generateStt();\n            if (options?.aiUtilizeBlocks?.includes('audio')) {\n                Entry.container.sttValue.setVisible(true);\n            }\n        }\n\n        Entry.playground.reloadPlayground();\n    }\n\n    generateVariable(variable, data, key) {\n        const name = variable.name_;\n        variable.name_ = this.checkAllVariableName(name, key)\n            ? Entry.getOrderedName(name, data, 'name_')\n            : name;\n        variable.generateView(data.length);\n    }\n\n    /**\n     * @param {!Array.<variable model>} variables\n     */\n    appendVariables(variables) {\n        for (const i in variables) {\n            const variable = Entry.Variable.create(variables[i]);\n            if (!variable.id_) {\n                variable.id_ = Entry.generateHash();\n            }\n            const type = variable.getType();\n            if (type === 'variable' || type === 'slide') {\n                if (this.variables_.some((item) => item.id_ === variable.id_)) {\n                    continue;\n                }\n                this.generateVariable(variable, this.variables_, 'variables_');\n                this.variables_.push(variable);\n            } else if (type === 'list') {\n                if (this.lists_.some((item) => item.id_ === variable.id_)) {\n                    continue;\n                }\n                this.generateVariable(variable, this.lists_, 'lists_');\n                this.lists_.push(variable);\n            }\n        }\n        if (Entry.isEmpty(Entry.engine.projectTimer)) {\n            Entry.variableContainer.generateTimer();\n        }\n        if (Entry.isEmpty(Entry.container.inputValue)) {\n            Entry.variableContainer.generateAnswer();\n        }\n        if (Entry.isEmpty(Entry.container.sttValue)) {\n            Entry.variableContainer.generateStt();\n        }\n        Entry.playground.reloadPlayground();\n    }\n\n    /**\n     * @param {!Array.<function model>} variables\n     */\n    setFunctions(functions = []) {\n        functions.forEach((func) => {\n            func = new Entry.Func(func);\n            func.generateBlock();\n            this.functions_[func.id] = func;\n        });\n    }\n\n    /**\n     * @param {!Array.<function model>} variables\n     */\n    appendFunctions(functions = []) {\n        for (const i in functions) {\n            const func = functions[i];\n            if (!func.id) {\n                func.id = Entry.generateHash();\n            } else if (`${func.id}` in this.functions_) {\n                continue;\n            }\n            const parseFunc = new Entry.Func(func);\n            this.changeFunctionName(parseFunc);\n            parseFunc.generateBlock();\n            this.functions_[parseFunc.id] = parseFunc;\n        }\n    }\n\n    changeFunctionName(func) {\n        const params = func.content.getEventMap('funcDef')[0].params[0].data.params;\n        const funcParamInfo = this.getFunctionParamInfo(params);\n        const funcParamName = this.getFunctionParamName(funcParamInfo);\n        const funcKeys = Object.keys(this.functions_);\n        const funcsParamNames = funcKeys.map((key) => {\n            const func = this.functions_[key];\n            const params = func.content.getEventMap('funcDef')[0].params[0].data.params;\n            const info = this.getFunctionParamInfo(params);\n            return {\n                name: this.getFunctionParamName(info),\n            };\n        });\n\n        const isDuplecate = funcsParamNames.some(({ name }) => funcParamName === name);\n\n        if (isDuplecate) {\n            const orderedNumber = Entry.getOrderedNameNumber(\n                funcParamName,\n                funcsParamNames,\n                'name'\n            );\n            for (let i = funcParamInfo.length - 1; ; i--) {\n                const info = funcParamInfo[i];\n                if (info.type === 'string') {\n                    info.parent[0] += orderedNumber;\n                    break;\n                }\n            }\n\n            Entry.Func.generateWsBlock(func);\n        }\n    }\n\n    getFunctionParamName(info) {\n        return info.reduce((acc, { name }) => (acc += name), '');\n    }\n\n    getFunctionParamInfo(parentParams) {\n        const info = [];\n        parentParams.forEach((param, index) => {\n            if (typeof param === 'string') {\n                info[index] = {\n                    name: param,\n                    type: 'string',\n                    parent: parentParams,\n                };\n            } else if (param instanceof Entry.Block) {\n                const { data = {} } = param;\n                const { params = [], type } = data;\n\n                if (type.indexOf('stringParam') === 0 || type.indexOf('booleanParam') === 0) {\n                    const name = type.slice(0, -5);\n                    info[index] = {\n                        name,\n                        type: name,\n                        parent: parentParams,\n                    };\n                } else {\n                    const childParamInfo = this.getFunctionParamInfo(params);\n                    childParamInfo.forEach((childInfo, childIndex) => {\n                        info[childIndex + index] = childInfo;\n                    });\n                }\n            }\n        });\n        return info;\n    }\n\n    /**\n     * get func\n     * @return {Entry.Func}\n     */\n    getFunction(funcId) {\n        return this.functions_[funcId];\n    }\n\n    /**\n     * get variable on canvas\n     * @return {Entry.Variable}\n     */\n    getVariable(id_, entity = {}) {\n        const criteria = { id_ };\n        let variable = _.find(this.variables_, criteria);\n        if (entity.isClone && variable.object_) {\n            variable = _.find(entity.variables, criteria);\n        }\n\n        return variable;\n    }\n\n    /**\n     * get variable on canvas\n     * @return {Entry.List}\n     */\n    getList(listId, { isClone, lists } = {}) {\n        const criteria = { id_: listId };\n        let list = _.find(this.lists_, criteria);\n        if (isClone && list.object_) {\n            list = _.find(lists, criteria);\n        }\n\n        return list;\n    }\n\n    /**\n     * Create function\n     */\n    createFunction(data) {\n        if (Entry.Func.isEdit) {\n            Entry.modal.alert(\n                Lang.Msgs.warning_function_aleady_being_edited,\n                Lang.Workspace.function_create\n            );\n            return;\n        }\n        Entry.Func.edit(new Entry.Func(data));\n        Entry.Func.save();\n        this.select(Entry.Func.targetFunc);\n    }\n\n    removeBlocksInFunctionByType(blockType) {\n        Object.values(this.functions_).forEach((func) => {\n            Entry.do('funcEditStart', func.id).isPass(true);\n            func.content.getBlockList(false, blockType).forEach((b, index) => {\n                Entry.do('destroyBlock', b).isPass(true);\n            });\n            Entry.do('funcEditEnd', 'save').isPass(true);\n        });\n    }\n\n    removeBlocksInFunctionByType2(blockType) {\n        Object.values(this.functions_).forEach((func) => {\n            func.content.getBlockList(false, blockType).forEach((block, index) => {\n                block.destroy();\n            });\n        });\n    }\n\n    async removeBlocksInFunctionByTypeAsync(blockType) {\n        await Promise.all(\n            Object.values(this.functions_).map(async (func) => {\n                await Promise.all(\n                    func.content.getBlockList(false, blockType).map(\n                        Entry.Utils.runAsyncCurry((block) => {\n                            block.destroy();\n                        })\n                    )\n                );\n            })\n        );\n    }\n\n    isUsedBlockTypeInFunction(blockType) {\n        return Object.values(this.functions_).some(\n            (func) => func.content.getBlockList(false, blockType).length\n        );\n    }\n\n    /**\n     * Remove variable\n     * @param {Entry.Variable} variable\n     */\n    removeFunction({ id: functionId }) {\n        const functions = this.functions_;\n        functions[functionId].destroy();\n        delete functions[functionId];\n        const functionType = `func_${functionId}`;\n\n        Entry.container.removeFuncBlocks(functionType);\n        for (const id in functions) {\n            functions[id].content.removeBlocksByType(functionType);\n        }\n        this.updateList();\n    }\n\n    removeNotPythonSupportedFunction() {\n        const functions = this.functions_;\n        Object.values(functions).forEach((func) => {\n            const isNotPythonSupport = func.useLocalVariables || func.type === 'value';\n            if (isNotPythonSupport) {\n                const functionId = func.id;\n                func.destroy();\n                delete functions[functionId];\n                const functionType = `func_${functionId}`;\n                Entry.container.removeFuncBlocks(functionType);\n                for (const id in functions) {\n                    functions[id].content.removeBlocksByType(functionType);\n                }\n            }\n        });\n        this.updateList();\n    }\n\n    checkListPosition(list, mouse) {\n        const pos = {\n            start_w: list.x_,\n            area_w: list.x_ + list.width_,\n            start_h: -list.y_,\n            area_h: -list.y_ + -list.height_,\n        };\n\n        if (mouse.x > pos.start_w && mouse.x < pos.area_w) {\n            if (mouse.y < pos.start_h && mouse.y > pos.area_h) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    getListById(mouseevt) {\n        const lists = this.lists_;\n        const returnList = [];\n        if (lists.length > 0) {\n            for (let i = 0; i < lists.length; i++) {\n                if (this.checkListPosition(lists[i], mouseevt)) {\n                    returnList.push(lists[i]);\n                }\n            }\n            return returnList;\n        }\n        return false;\n    }\n\n    _getVariableByName(arr, variableName, isSelf, currentObjectId) {\n        const object = _.result(Entry.playground, 'object');\n        if (!currentObjectId && object) {\n            currentObjectId = object.id;\n        }\n\n        for (let i = 0; i < arr.length; i++) {\n            const v = arr[i];\n            if (isSelf === true) {\n                if (!v.object_ || v.object_ !== currentObjectId) {\n                    continue;\n                }\n            } else if (isSelf === false) {\n                if (v.object_) {\n                    continue;\n                }\n            }\n\n            if (v.getName() === variableName) {\n                return v;\n            }\n        }\n    }\n\n    getVariableByName(variableName, isSelf, currentObjectId) {\n        return this._getVariableByName(this.variables_, variableName, isSelf, currentObjectId);\n    }\n\n    getListByName(name, isSelf, currentObjectId) {\n        return this._getVariableByName(this.lists_, name, isSelf, currentObjectId);\n    }\n\n    /**\n     * Save variable\n     * @param {Entry.Func} func\n     */\n    saveFunction(func) {\n        this.hasBlockInFunction.cache.clear();\n        this.hasParamBlockInFunction.cache.clear();\n        this.hasFuncBlockInFunction.cache.clear();\n        /* add to function list when not exist */\n        const ws = Entry.getMainWS();\n\n        if (ws && ws.overlayModefrom == Entry.Workspace.MODE_VIMBOARD) {\n            if (func && func.description) {\n                const funcName = func.description.substring(1, func.description.length - 1);\n                const alertMsg = Entry.TextCodingUtil.validateNameIncludeSpace(\n                    funcName,\n                    'function'\n                );\n                if (alertMsg) {\n                    Entry.modal.alert(alertMsg);\n                    Entry.Func.cancelEdit();\n                    return;\n                }\n            }\n        }\n\n        if (!this.functions_[func.id]) {\n            this.functions_[func.id] = func;\n            this.createFunctionView(func);\n        }\n        if (func.listElement) {\n            func.listElement.nameField.textContent = func.description;\n        }\n\n        this.updateList();\n    }\n\n    /**\n     * @param {Entry.Func} func\n     */\n    createFunctionView(func) {\n        const createElement = Entry.createElement;\n\n        const view = Entry.createElement('div').addClass('list default_func');\n\n        const that = this;\n        const editBoxWrapper = createElement('div')\n            .addClass('inpt_box')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                if (!Entry.isTextMode) {\n                    if (Entry.Func.isEdit) {\n                        Entry.Func._backupContent = null;\n                        Entry.Func.save();\n                    }\n                    Entry.do('funcEditStart', func.id);\n                }\n\n                return this.select(func);\n            })\n            .appendTo(view);\n        const editBoxInputWrapper = createElement('div').addClass('inpt').appendTo(editBoxWrapper);\n        const editBoxInput = createElement('span').addClass('input').appendTo(editBoxInputWrapper);\n        editBoxInput.textContent = func.description;\n        editBoxInput.setAttribute('autocomplete', 'off');\n\n        const ArrowDownButton = createElement('div').addClass('arrowDown').appendTo(editBoxWrapper);\n\n        const delButton = createElement('a')\n            .addClass('del')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                Entry.modal.confirm(Lang.Workspace.will_you_delete_function).then((result) => {\n                    if (result === true) {\n                        this.destroyFunction(func);\n                        this.selected = null;\n                    }\n                });\n            })\n            .appendTo(editBoxWrapper);\n        delButton.href = '#';\n        view.nameField = editBoxInput;\n        func.listElement = view;\n    }\n\n    async destroyFunction(func) {\n        if (Entry.Func.targetFunc) {\n            Entry.do('funcEditEnd', 'cancel');\n        }\n        const currentObjectId = Entry.playground.object.id;\n        Entry.do('selectObject', currentObjectId);\n        const functionType = `func_${func.id}`;\n        await Entry.Utils.removeBlockByTypeAsync(functionType);\n        Entry.do('funcRemove', func).isPass(true);\n        Entry.do('selectObject', currentObjectId).isPass(true);\n    }\n\n    /**\n     * Add variable\n     * @param {Entry.Variable} variable\n     * @return {boolean} return true when success\n     */\n    checkAllVariableName(name, variable, key = 'name_') {\n        return this[variable].some(({ [key]: name_ }) => name_ === name);\n    }\n\n    _addVariableOrList(type, data) {\n        if (!type) {\n            return;\n        }\n        const panel = this._getAddPanel(type);\n        const name = panel.view.name.value.trim();\n\n        if (Entry.isTextMode) {\n            const alertMsg = Entry.TextCodingUtil.validateNameIncludeSpace(name, type);\n            if (alertMsg) {\n                Entry.modal.alert(alertMsg);\n                this.resetVariableAddPanel(type);\n                return;\n            }\n        }\n\n        const target = `${type}s_`;\n\n        data = data || this._makeVariableData(type);\n\n        this.resetVariableAddPanel(type);\n\n        if (!(data instanceof Entry.Variable)) {\n            data = Entry.Variable.create(data);\n        }\n\n        if (type === 'variable') {\n            this.createVariableView(data);\n        } else {\n            this.createListView(data);\n        }\n\n        data.generateView(this[target].length);\n\n        this[target].unshift(data);\n\n        const playground = Entry.playground;\n\n        if (playground) {\n            const { blockMenu } = playground;\n            if (blockMenu) {\n                blockMenu.deleteRendered('variable');\n            }\n            playground.reloadPlayground();\n        }\n\n        this.select(data);\n        this.updateList();\n    }\n\n    addVariable(variable) {\n        this._addVariableOrList.call(this, 'variable', variable);\n    }\n\n    /**\n     * Remove variable\n     * @param {Entry.Variable} variable\n     */\n    removeVariable(variable) {\n        if (!(variable instanceof Entry.Variable)) {\n            variable = this.getVariable(variable.id);\n        }\n\n        if (this.selected == variable) {\n            this.select(null);\n        }\n\n        variable.remove();\n        const variables = this.variables_;\n        variables.splice(variables.indexOf(variable), 1);\n        Entry.playground.reloadPlayground();\n        this.updateList();\n    }\n\n    /**\n     * @param {Entry.Variable} variable\n     * @param {String} name\n     */\n    changeVariableName(variable, name) {\n        if (variable.name_ == name) {\n            return;\n        }\n\n        if (Entry.isTextMode) {\n            const alertMsg = Entry.TextCodingUtil.validateNameIncludeSpace(name, 'variable');\n            if (alertMsg) {\n                Entry.modal.alert(alertMsg);\n                variable.listElement.nameField.value = variable.name_;\n                return;\n            }\n        }\n\n        if (Entry.isExist(name, 'name_', this.variables_)) {\n            return this.changeVariableNameDuplicated(variable, 'variable', name);\n        } else if (name.length > 10) {\n            variable.listElement.nameField.value = variable.name_;\n            return Entry.toast.alert(\n                Lang.Workspace.variable_rename_failed,\n                Lang.Workspace.variable_too_long\n            );\n        }\n        variable.setName(name);\n        variable.listElement.nameField.value = name;\n        Entry.playground.reloadPlayground();\n        Entry.toast.success(Lang.Workspace.variable_rename, Lang.Workspace.variable_rename_ok);\n    }\n\n    /**\n     * @param {Entry.Variable} list\n     * @param {String} name\n     */\n    changeListName(list, name) {\n        if (list.name_ == name) {\n            return;\n        }\n\n        if (Entry.isTextMode) {\n            const alertMsg = Entry.TextCodingUtil.validateNameIncludeSpace(name, 'list');\n            if (alertMsg) {\n                Entry.modal.alert(alertMsg);\n                list.listElement.nameField.value = list.name_;\n                return;\n            }\n        }\n\n        if (Entry.isExist(name, 'name_', this.lists_)) {\n            return this.changeVariableNameDuplicated(list, 'list', name);\n        } else if (name.length > 10) {\n            Entry.toast.alert(Lang.Workspace.list_rename_failed, Lang.Workspace.list_too_long);\n        } else {\n            //name successfully changed\n            list.name_ = name;\n            list.updateView();\n            Entry.playground.reloadPlayground();\n            Entry.toast.success(Lang.Workspace.list_rename, Lang.Workspace.list_rename_ok);\n        }\n\n        list.listElement.nameField.value = list.name_;\n    }\n\n    /**\n     * @param {Entry.Variable} variable or list\n     * @param {string} type [variable, list]\n     * @param {string} name\n     */\n    changeVariableNameDuplicated(variable, type, name) {\n        const variables = this[`${type}s_`].filter(({ id_ }) => id_ !== variable.id_);\n        const newName = Entry.getOrderedName(\n            this._truncName(name, type, this._maxNameLength),\n            variables,\n            'name_'\n        );\n\n        variable.setName(newName);\n        variable.listElement.nameField.value = newName;\n\n        Entry.playground.reloadPlayground();\n        Entry.toast.warning(Lang.Workspace[`${type}_rename`], Lang.Workspace[`${type}_dup`]);\n    }\n\n    /**\n     * Remove list\n     * @param {Entry.Variable} list\n     */\n    removeList(list) {\n        if (!(list instanceof Entry.Variable)) {\n            list = this.getList(list.id);\n        }\n\n        if (this.selected == list) {\n            this.select(null);\n        }\n        list.remove();\n        const lists = this.lists_;\n        lists.splice(lists.indexOf(list), 1);\n        Entry.playground.reloadPlayground();\n        this.updateList();\n    }\n\n    /**\n     * @param {Entry.Variable} variable\n     */\n    createVariableView(variable) {\n        const that = this;\n        const createElement = Entry.createElement;\n\n        const variableWrapper = createElement('div').addClass('list fold');\n\n        if (!variable.object_) {\n            if (variable.isCloud_) {\n                variableWrapper.addClass('cloud_variable');\n            } else if (variable.isRealTime_) {\n                variableWrapper.addClass('real_time_variable');\n            } else {\n                variableWrapper.addClass('default_val');\n            }\n        } else {\n            variableWrapper.addClass('local_val');\n        }\n\n        const editBoxWrapper = createElement('div')\n            .addClass('inpt_box')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n\n                if (that.variableSettingView) {\n                    $(that.variableSettingView).remove();\n                    delete that.variableSettingView;\n                }\n\n                if (that.selected === variable) {\n                    if (!that._isPythonMode()) {\n                        editBoxInput.blur();\n                    }\n                    that.select(variable);\n                    that.updateSelectedVariable(null, 'variable');\n                } else {\n                    Entry.do('setVariableEditable', variable.id_);\n                }\n            })\n            .appendTo(variableWrapper);\n        const watchButton = createElement('a')\n            .addClass('watch')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                Entry.do('variableSetVisibility', variable.id_, !variable.isVisible());\n                if (variable.isVisible()) {\n                    watchButton.addClass('on');\n                } else {\n                    watchButton.removeClass('on');\n                }\n            })\n            .appendTo(editBoxWrapper);\n        if (variable.isVisible()) {\n            watchButton.addClass('on');\n        } else {\n            watchButton.removeClass('on');\n        }\n        watchButton.href = '#';\n        const editBoxInputWrapper = createElement('div').addClass('inpt').appendTo(editBoxWrapper);\n        const editBoxInput = createElement('input')\n            .addClass('editBoxInput')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n            })\n            .appendTo(editBoxInputWrapper);\n        editBoxInput.setAttribute('autocomplete', 'off');\n        editBoxInput.setAttribute('type', 'text');\n        editBoxInput.setAttribute('name', 'inpt_name');\n        editBoxInput.value = variable.name_;\n        editBoxInput.onblur = function () {\n            const value = this.value.trim();\n            if (!value) {\n                Entry.toast.alert(Lang.Msgs.warn, Lang.Msgs.variable_can_not_space);\n                this.value = variable.getName();\n                return this.focus();\n            }\n            const targetVariable = that.getVariable(variable.getId());\n            targetVariable && Entry.do('variableSetName', targetVariable.getId(), value);\n        };\n        editBoxInput.onkeydown = Entry.Utils.blurWhenEnter;\n        const ArrowDownButton = createElement('div').addClass('arrowDown').appendTo(editBoxWrapper);\n        const delButton = createElement('a')\n            .addClass('del')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                Entry.do('variableContainerRemoveVariable', variable);\n            })\n            .appendTo(editBoxWrapper);\n        delButton.href = '#';\n        variableWrapper.nameField = editBoxInput;\n        variable.listElement = variableWrapper;\n    }\n\n    /**\n     * Add event for block\n     * @param {message model} message\n     * @return {boolean} return true when success\n     */\n    addMessage(message = {}) {\n        const messages = this.messages_;\n        if (!message.name) {\n            message.name = `${Lang.Workspace.message} ${messages.length + 1}`;\n        }\n        if (!message.id) {\n            message.id = Entry.generateHash();\n        }\n        this.createMessageView(message);\n        messages.unshift(message);\n\n        const { playground } = Entry;\n\n        if (playground) {\n            const { blockMenu } = playground;\n            if (blockMenu) {\n                blockMenu.deleteRendered('start');\n            }\n            playground.reloadPlayground();\n        }\n        this.updateList();\n        const nameField = message.listElement.nameField;\n\n        //flag for first time blur command\n        //focus first and value not changed\n        //command will be skipped\n        nameField.isFirst = true;\n    }\n\n    /**\n     * Add event\n     * @param {message model} message\n     */\n    removeMessage({ id }) {\n        const message = this.getMessage(id);\n        if (this.selected == message) {\n            this.select(null);\n        }\n        const messages_ = this.messages_;\n        messages_.splice(messages_.indexOf(message), 1);\n        this.updateList();\n        Entry.playground.reloadPlayground();\n    }\n\n    /**\n     * @param {object} message\n     * @param {String} name\n     */\n    changeMessageName({ id }, name) {\n        const message = this.getMessage(id);\n        if (message.name == name) {\n            return;\n        }\n\n        const messages = this.messages_;\n        const exist = Entry.isExist(name, 'name', messages);\n\n        const {\n            listElement: { nameField },\n        } = message;\n        const { playground, toast } = Entry;\n\n        if (exist) {\n            return failFunc(\n                message.name,\n                Lang.Workspace.message_rename_failed,\n                Lang.Workspace.message_dup\n            );\n        } else if (name.length > EntryStatic.messageMaxLength) {\n            return failFunc(\n                message.name,\n                Lang.Workspace.message_rename_failed,\n                Lang.Workspace.message_too_long_to_change\n            );\n        }\n\n        message.name = name;\n        nameField.value = message.name;\n        if (playground) {\n            playground.blockMenu.deleteRendered('start');\n            playground.reloadPlayground();\n        }\n        toast.success(Lang.Workspace.message_rename, Lang.Workspace.message_rename_ok);\n\n        function failFunc(value, title, message) {\n            nameField.value = value;\n            return toast.alert(title, message);\n        }\n    }\n\n    activateMessageEditView(message) {\n        $(message.listElement)\n            .find('.entryVariableListElementNameWorkspace')\n            .removeAttr('disabled')\n            .focus();\n    }\n\n    /**\n     * @param {object} message\n     */\n    createMessageView(message) {\n        const createElement = Entry.createElement;\n\n        const view = Entry.createElement('div').addClass('list default_message');\n\n        const editBoxWrapper = createElement('div')\n            .addClass('inpt_box')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                return this.select(message);\n            })\n            .appendTo(view);\n        const editBoxInputWrapper = createElement('div').addClass('inpt').appendTo(editBoxWrapper);\n        const editBoxInput = createElement('input')\n            .addClass('editBoxInput')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n            })\n            .appendTo(editBoxInputWrapper);\n        editBoxInput.setAttribute('autocomplete', 'off');\n        editBoxInput.setAttribute('type', 'text');\n        editBoxInput.value = message.name;\n        editBoxInput.onfocus = Entry.Utils.setFocused;\n        editBoxInput.onblur = Entry.Utils.setBlurredTimer(function () {\n            const value = this.value;\n            if (!value.trim()) {\n                Entry.toast.alert(Lang.Msgs.warn, Lang.Msgs.sign_can_not_space);\n                this.value = message.name;\n                return this.focus();\n            }\n\n            //check message exist currently\n            message = Entry.variableContainer.getMessage(message.id);\n            if (message && !(this.isFirst && value === message.name)) {\n                Entry.do('messageSetName', message.id, value);\n            }\n            delete this.isFirst;\n        }, 200);\n        editBoxInput.onkeydown = Entry.Utils.blurWhenEnter;\n\n        const ArrowDownButton = createElement('div').addClass('arrowDown').appendTo(editBoxWrapper);\n\n        const delButton = createElement('a')\n            .addClass('del')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                Entry.do('variableContainerRemoveMessage', message);\n            })\n            .appendTo(editBoxWrapper);\n        delButton.href = '#';\n        view.nameField = editBoxInput;\n        message.listElement = view;\n    }\n\n    /**\n     * Add list for block\n     * @param {list model} list\n     * @return {boolean} return true when success\n     */\n    addList(list) {\n        this._addVariableOrList.call(this, 'list', list);\n    }\n\n    /**\n     * @param {Entry.Variable} list\n     */\n    createListView(list) {\n        const that = this;\n        const createElement = Entry.createElement;\n\n        const listWrapper = createElement('div').addClass('list fold').appendTo(this.globalListBox);\n\n        if (!list.object_) {\n            if (list.isCloud_) {\n                listWrapper.addClass('cloud_list');\n            } else if (list.isRealTime_) {\n                listWrapper.addClass('real_time_list');\n            } else {\n                listWrapper.addClass('default_list');\n            }\n        } else {\n            listWrapper.addClass('local_list');\n        }\n\n        const editBoxWrapper = createElement('div')\n            .addClass('inpt_box')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n\n                if (that.listSettingView) {\n                    $(that.listSettingView).remove();\n                    delete that.listSettingView;\n                }\n\n                if (that.selected === list) {\n                    editBoxInput.blur();\n                    that.select(list);\n                    that.updateSelectedVariable(null, 'list');\n                } else {\n                    Entry.do('setListEditable', list.id_);\n                }\n            })\n            .appendTo(listWrapper);\n        const watchButton = createElement('a')\n            .addClass('watch')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                Entry.do('listSetVisibility', list.id_, !list.isVisible());\n                if (list.isVisible()) {\n                    watchButton.addClass('on');\n                } else {\n                    watchButton.removeClass('on');\n                }\n            })\n            .appendTo(editBoxWrapper);\n        if (list.isVisible()) {\n            watchButton.addClass('on');\n        } else {\n            watchButton.removeClass('on');\n        }\n        watchButton.href = '#';\n        const editBoxInputWrapper = createElement('div').addClass('inpt').appendTo(editBoxWrapper);\n        const editBoxInput = createElement('input')\n            .addClass('editBoxInput')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n            })\n            .appendTo(editBoxInputWrapper);\n        editBoxInput.setAttribute('autocomplete', 'off');\n        editBoxInput.setAttribute('type', 'text');\n        editBoxInput.setAttribute('name', 'inpt_name');\n        editBoxInput.value = list.name_;\n        editBoxInput.onblur = function () {\n            const value = this.value.trim();\n            if (!value) {\n                Entry.toast.alert(Lang.Msgs.warn, Lang.Msgs.list_can_not_space);\n                this.value = list.getName();\n                return this.focus();\n            }\n            const targetList = that.getList(list.getId());\n            targetList && Entry.do('listSetName', targetList.getId(), value);\n        };\n        editBoxInput.onkeydown = Entry.Utils.blurWhenEnter;\n        const ArrowDownButton = createElement('div').addClass('arrowDown').appendTo(editBoxWrapper);\n        const delButton = createElement('a')\n            .addClass('del')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                Entry.do('variableContainerRemoveList', list);\n            })\n            .appendTo(editBoxWrapper);\n        delButton.href = '#';\n        listWrapper.nameField = editBoxInput;\n        list.listElement = listWrapper;\n    }\n\n    /**\n     * Apply map function to variables. But this not replace object with returned one.\n     * So giving map function don't have to return object.\n     * And this support another arguments.\n     * @param {!function} mapFunction\n     * @param {} param\n     */\n    mapVariable(mapFunction, param) {\n        this.variables_.forEach(_.partial(mapFunction, _, param));\n    }\n\n    /**\n     * @param {!function} mapFunction\n     * @param {} param\n     */\n    mapList(mapFunction, param) {\n        this.lists_.forEach(_.partial(mapFunction, _, param));\n    }\n\n    mapFunc(mapFunction, param) {\n        Object.values(this.functions_).forEach(_.partial(mapFunction, _, param));\n    }\n\n    /**\n     * convert this variable's data to JSON.\n     * @return {JSON}\n     */\n    getVariableJSON() {\n        return [\n            ...this.variables_,\n            ...this.lists_,\n            _.result(Entry.engine, 'projectTimer'),\n            _.result(Entry.container, 'inputValue'),\n        ]\n            .filter(_.identity)\n            .map((v) => (v.toJSON ? v.toJSON() : v));\n    }\n\n    /**\n     * convert this message's data to JSON.\n     * @return {JSON}\n     */\n    getMessageJSON() {\n        return this.messages_.map(_.partial(_.pick, _, 'id', 'name'));\n    }\n\n    /**\n     * convert this function's data to JSON.\n     * @return {JSON}\n     */\n    getFunctionJSON() {\n        return _.reduce(\n            this.functions_,\n            (acc, { id, content, type = 'normal', useLocalVariables, localVariables }) => [\n                ...acc,\n                {\n                    id,\n                    type,\n                    localVariables,\n                    useLocalVariables,\n                    content: content.stringify(),\n                },\n            ],\n            []\n        );\n    }\n\n    resetVariableAddPanel(type = 'variable') {\n        const panel = this._getAddPanel(type);\n        if (!panel.view) {\n            return;\n        }\n        const info = panel.info;\n        info.isCloud = false;\n        info.isRealTime = false;\n        info.object = null;\n        panel.view.name.value = '';\n        panel.isOpen = false;\n        this.updateVariableAddView(type);\n    }\n\n    generateVariableAddView() {\n        const createElement = Entry.createElement;\n        const _whenEnter = Entry.Utils.whenEnter;\n        const _setFocused = Entry.Utils.setFocused;\n        const _setBlurredTimer = Entry.Utils.setBlurredTimer;\n\n        const that = this;\n\n        // 변수 만들기 폼\n        const variableAddSpace = createElement('div').addClass(\n            'entryVariableAddSpaceWorkspace off'\n        );\n        this.variableAddPanel.view = variableAddSpace;\n        this.variableAddPanel.isOpen = false;\n\n        const variableAddSpaceDataWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceDataWrapperWorkspace')\n            .appendTo(variableAddSpace);\n\n        // 입력 폼\n        const addSpaceNameWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceNameWrapperWorkspace')\n            .appendTo(variableAddSpaceDataWrapper);\n\n        const addSpaceInputLabel = createElement('label')\n            .addClass('entryVariableAddSpaceInputLabelWorkspace')\n            .appendTo(addSpaceNameWrapper);\n        addSpaceInputLabel.setAttribute('for', 'entryVariableAddSpaceInputWorkspace');\n        addSpaceInputLabel.innerText = Lang.Workspace.Variable_placeholder_name;\n\n        const addSpaceInput = createElement('input')\n            .addClass('entryVariableAddSpaceInputWorkspace')\n            .appendTo(addSpaceNameWrapper);\n        addSpaceInput.setAttribute('autocomplete', 'off');\n        addSpaceInput.setAttribute('type', 'text');\n        addSpaceInput.id = 'entryVariableAddSpaceInputWorkspace';\n        addSpaceInput.setAttribute('placeholder', Lang.Workspace.Variable_placeholder_content);\n        addSpaceInput.variableContainer = this;\n        addSpaceInput.onkeypress = _whenEnter(function () {\n            if (this.enterKeyDisabled) {\n                this.blur();\n            } else {\n                that._addVariable();\n            }\n        });\n        addSpaceInput.onfocus = _setFocused;\n        const doBlur = _setBlurredTimer(function () {\n            this.isBlurred = false;\n            Entry.do('variableAddSetName', this.value);\n            this.blurCallback && this.blurCallback();\n        });\n        addSpaceInput.onblur = () => {\n            this.isBlurred = true;\n            doBlur.apply(this);\n        };\n        this.variableAddPanel.view.name = addSpaceInput;\n\n        const addSpaceSelectWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceSelectWrapperWorkspace')\n            .appendTo(variableAddSpaceDataWrapper);\n        const addSpaceGlobalButton = createElement('a')\n            .addClass('button entryVariableAddSpaceGlobalButtonrWorkspace on')\n            .bindOnClick(() => {\n                addSpaceLocalButton.removeClass('on');\n                addSpaceGlobalButton.addClass('on');\n                variableTypeWrapper.addClass('on');\n                return Entry.do('variableAddSetScope', 'global');\n            })\n            .appendTo(addSpaceSelectWrapper);\n        addSpaceGlobalButton.textContent = Lang.Workspace.use_all_objects;\n        this.variableAddPanel.view.globalCheck = addSpaceGlobalButton;\n\n        const addSpaceLocalButton = createElement('a')\n            .addClass('button entryVariableAddSpaceLocalButtonrWorkspace')\n            .bindOnClick(() => {\n                addSpaceGlobalButton.removeClass('on');\n                addSpaceLocalButton.addClass('on');\n                variableTypeWrapper.removeClass('on');\n                return Entry.do('variableAddSetScope', 'local');\n            })\n            .appendTo(addSpaceSelectWrapper);\n        addSpaceLocalButton.textContent = Lang.Workspace.Variable_use_this_object;\n        this.variableAddPanel.view.localCheck = addSpaceLocalButton;\n\n        const variableTypeWrapper = createElement('div')\n            .addClass('entryVariableTypeBoxWrapper on')\n            .appendTo(variableAddSpaceDataWrapper);\n\n        ['normal', 'cloud', 'real_time'].forEach((type) => {\n            const wrapper = createElement('div')\n                .addClass(`entryVariableTypeWrapper`)\n                .appendTo(variableTypeWrapper)\n                .bindOnClick((e) => {\n                    e.stopImmediatePropagation();\n                    const { object, isCloud, isRealTime } = this.variableAddPanel.info;\n                    !object && Entry.do('variableAddSetCloud', type);\n                    this.#removeChildrenClass(variableTypeWrapper, 'on');\n                    wrapper.addClass('on');\n                });\n            if (type === 'normal') {\n                wrapper.addClass('on');\n            }\n            createElement('span')\n                .addClass(`entryVariable${type}RadioButton radioButton`)\n                .appendTo(wrapper);\n            createElement('span')\n                .addClass(`entryVariable${type}Text`, 'entryVariableAddSpaceCheckWorkspace')\n                .appendTo(wrapper).textContent = Lang.Workspace[`variable_create_${type}`];\n        });\n        variableAddSpace.cloudWrapper = variableTypeWrapper;\n        this.variableAddPanel.view.cloudCheck = variableTypeWrapper;\n\n        // 확인 취소 버튼\n        const addSpaceButtonWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceButtonWrapperWorkspace')\n            .appendTo(variableAddSpace);\n\n        const addSpaceCancelButton = createElement('a')\n            .addClass('entryVariableAddSpaceCancelWorkspace')\n            .addClass('entryVariableAddSpaceButtonWorkspace')\n            .bindOnClick(() => {\n                this.variableAddPanel.view.addClass('off');\n                this.resetVariableAddPanel('variable');\n            })\n            .appendTo(addSpaceButtonWrapper);\n        addSpaceCancelButton.href = '#';\n        addSpaceCancelButton.textContent = Lang.Buttons.cancel;\n\n        const addSpaceConfirmButton = createElement('a')\n            .addClass('entryVariableAddSpaceConfirmWorkspace')\n            .addClass('entryVariableAddSpaceButtonWorkspace')\n            .bindOnClick(() => {\n                that._addVariable();\n            })\n            .appendTo(addSpaceButtonWrapper);\n        addSpaceConfirmButton.textContent = Lang.Buttons.add_variable;\n        this.variableAddConfirmButton = addSpaceConfirmButton;\n    }\n\n    _addVariable() {\n        const variableInput = Entry.getDom(['variableContainer', 'variableAddInput']);\n        this.variableAddPanel.view.addClass('off');\n        const blurCallback = () => {\n            delete variableInput.blurCallback;\n            Entry.do(\n                'variableContainerAddVariable',\n                Entry.Variable.create(this._makeVariableData('variable'))\n            );\n            const [variable] = this.variables_;\n            this.updateSelectedVariable(variable);\n            const { nameField } = variable.listElement;\n            nameField.removeAttribute('disabled');\n        };\n        if (variableInput.isBlurred) {\n            variableInput.blurCallback = blurCallback;\n        } else {\n            blurCallback();\n        }\n        this.resetVariableAddPanel('variable');\n    }\n\n    _addList() {\n        const listInput = Entry.getDom(['variableContainer', 'listAddInput']);\n        this.listAddPanel.view.addClass('off');\n        const blurCallback = () => {\n            Entry.do(\n                'variableContainerAddList',\n                Entry.Variable.create(this._makeVariableData('list'))\n            );\n            const [list] = this.lists_;\n            this.updateSelectedVariable(list);\n            const { nameField } = list.listElement;\n            nameField.removeAttribute('disabled');\n        };\n\n        if (listInput.isBlurred) {\n            listInput.blurCallback = blurCallback;\n        } else {\n            blurCallback();\n        }\n        this.resetVariableAddPanel('list');\n    }\n\n    generateListAddView() {\n        const createElement = Entry.createElement;\n        const _setFocused = Entry.Utils.setFocused;\n        const _setBlurredTimer = Entry.Utils.setBlurredTimer;\n\n        const that = this;\n\n        // 리스트 만들기 폼\n        const listAddSpace = createElement('div').addClass('entryVariableAddSpaceWorkspace off');\n        this.listAddPanel.view = listAddSpace;\n        this.listAddPanel.isOpen = false;\n\n        const variableAddSpaceDataWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceDataWrapperWorkspace')\n            .appendTo(listAddSpace);\n\n        // 리스트 만들기\n        const addSpaceNameWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceNameWrapperWorkspace')\n            .appendTo(variableAddSpaceDataWrapper);\n\n        const addSpaceInputLabel = createElement('label')\n            .addClass('entryVariableAddSpaceInputLabelWorkspace')\n            .appendTo(addSpaceNameWrapper);\n        addSpaceInputLabel.innerText = Lang.Workspace.list_name;\n        addSpaceInputLabel.setAttribute('for', 'entryVariableAddSpaceInputWorkspace');\n\n        const addSpaceInput = createElement('input')\n            .addClass('entryVariableAddSpaceInputWorkspace')\n            .appendTo(addSpaceNameWrapper);\n        addSpaceInput.setAttribute('autocomplete', 'off');\n        addSpaceInput.setAttribute('type', 'text');\n        addSpaceInput.id = 'entryVariableAddSpaceInputWorkspace';\n        addSpaceInput.setAttribute('placeholder', Lang.Workspace.list_create_placeholder);\n        addSpaceInput.onkeypress = Entry.Utils.whenEnter(function () {\n            if (this.enterKeyDisabled) {\n                this.blur();\n            } else {\n                that._addList();\n            }\n        });\n        addSpaceInput.onfocus = _setFocused;\n        const doBlur = _setBlurredTimer(function () {\n            this.isBlurred = false;\n            Entry.do('listAddSetName', this.value);\n            this.blurCallback && this.blurCallback();\n        });\n        addSpaceInput.onblur = () => {\n            this.isBlurred = true;\n            doBlur.apply(this);\n        };\n        this.listAddPanel.view.name = addSpaceInput;\n\n        const addSpaceSelectWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceSelectWrapperWorkspace')\n            .appendTo(variableAddSpaceDataWrapper);\n\n        const addSpaceGlobalButton = createElement('a')\n            .addClass('button entryVariableAddSpaceGlobalButtonrWorkspace on')\n            .bindOnClick(() => {\n                addSpaceLocalButton.removeClass('on');\n                addSpaceGlobalButton.addClass('on');\n                variableTypeWrapper.addClass('on');\n                return Entry.do('listAddSetScope', 'global');\n            })\n            .appendTo(addSpaceSelectWrapper);\n        addSpaceGlobalButton.textContent = Lang.Workspace.use_all_objects;\n        this.listAddPanel.view.globalCheck = addSpaceGlobalButton;\n\n        const addSpaceLocalButton = createElement('a')\n            .addClass('button entryVariableAddSpaceLocalButtonrWorkspace')\n            .bindOnClick(() => {\n                addSpaceGlobalButton.removeClass('on');\n                addSpaceLocalButton.addClass('on');\n                variableTypeWrapper.removeClass('on');\n                return Entry.do('listAddSetScope', 'local');\n            })\n            .appendTo(addSpaceSelectWrapper);\n        addSpaceLocalButton.textContent = Lang.Workspace.Variable_use_this_object;\n        this.listAddPanel.view.localCheck = addSpaceLocalButton;\n\n        const variableTypeWrapper = createElement('div')\n            .addClass('entryVariableTypeBoxWrapper on')\n            .appendTo(variableAddSpaceDataWrapper);\n\n        ['normal', 'cloud', 'real_time'].forEach((type) => {\n            const wrapper = createElement('div')\n                .addClass(`entryVariableTypeWrapper`)\n                .appendTo(variableTypeWrapper)\n                .bindOnClick((e) => {\n                    e.stopImmediatePropagation();\n                    const { object } = this.listAddPanel.info;\n                    !object && Entry.do('listAddSetCloud', type);\n                    this.#removeChildrenClass(variableTypeWrapper, 'on');\n                    wrapper.addClass('on');\n                });\n            if (type === 'normal') {\n                wrapper.addClass('on');\n            }\n            createElement('span')\n                .addClass(`entryVariable${type}RadioButton radioButton`)\n                .appendTo(wrapper);\n            createElement('span')\n                .addClass(`entryVariable${type}Text`, 'entryVariableAddSpaceCheckWorkspace')\n                .appendTo(wrapper).textContent = Lang.Workspace[`list_create_${type}`];\n        });\n        listAddSpace.cloudWrapper = variableTypeWrapper;\n        this.listAddPanel.view.cloudCheck = variableTypeWrapper;\n\n        // 확인 취소 버튼\n        const addSpaceButtonWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceButtonWrapperWorkspace')\n            .appendTo(listAddSpace);\n\n        const addSpaceCancelButton = createElement('a')\n            .addClass('entryVariableAddSpaceCancelWorkspace')\n            .addClass('entryVariableAddSpaceButtonWorkspace')\n            .bindOnClick(() => {\n                this.listAddPanel.view.addClass('off');\n                this.resetVariableAddPanel('list');\n            })\n            .appendTo(addSpaceButtonWrapper);\n        addSpaceCancelButton.href = '#';\n        addSpaceCancelButton.textContent = Lang.Buttons.cancel;\n\n        const addSpaceConfirmButton = createElement('a')\n            .addClass('entryVariableAddSpaceConfirmWorkspace')\n            .addClass('entryVariableAddSpaceButtonWorkspace')\n            .bindOnClick(() => {\n                that._addList();\n            })\n            .appendTo(addSpaceButtonWrapper);\n        addSpaceConfirmButton.href = '#';\n        addSpaceConfirmButton.textContent = Lang.Buttons.add_list;\n        this.listAddConfirmButton = addSpaceConfirmButton;\n    }\n\n    generateMessageAddView() {\n        const createElement = Entry.createElement;\n        const that = this;\n\n        // 신호 만들기 폼\n        const msgAddSpace = createElement('div').addClass('message_inpt off');\n        this.messageAddPanel.view = msgAddSpace;\n        this.messageAddPanel.isOpen = false;\n\n        const msdAddSpaceWrapper = createElement('div')\n            .addClass('msdAddSpaceWrapper')\n            .appendTo(msgAddSpace);\n\n        const boxSubject = Entry.createElement('span')\n            .addClass('box_sjt')\n            .appendTo(msdAddSpaceWrapper);\n        boxSubject.textContent = Lang.Workspace.Message_placeholder_name;\n\n        const msgNameInput = createElement('input').appendTo(msdAddSpaceWrapper);\n        msgNameInput.setAttribute('autocomplete', 'off');\n        msgNameInput.setAttribute('type', 'text');\n        msgNameInput.setAttribute('placeholder', Lang.Workspace.message_create_placeholder);\n        msgNameInput.onkeydown = Entry.Utils.whenEnter(function () {\n            if (this.enterKeyDisabled) {\n                this.blur();\n            } else {\n                const value = msgNameInput.value;\n                if (value.length > EntryStatic.messageMaxLength) {\n                    return Entry.toast.alert(\n                        Lang.Workspace.message_add_fail,\n                        Lang.Workspace.message_too_long\n                    );\n                }\n                that.messageAddPanel.isOpen = false;\n                msgAddSpace.addClass('off');\n                msgNameInput.value = '';\n                Entry.do('variableContainerAddMessage', {\n                    id: Entry.generateHash(),\n                    name: Entry.getOrderedName(\n                        value || Lang.Workspace.message,\n                        that.messages_,\n                        'name'\n                    ),\n                });\n            }\n        });\n        this.messageAddPanel.view.name = msgNameInput;\n\n        const buttonWrapper = createElement('div')\n            .addClass('entryVariableAddSpaceButtonWrapperWorkspace')\n            .appendTo(msgAddSpace);\n\n        const msgCancel = createElement('a')\n            .addClass('entryVariableAddSpaceCancelWorkspace')\n            .addClass('entryVariableAddSpaceButtonWorkspace')\n            .bindOnClick(() => {\n                msgAddSpace.addClass('off');\n                msgNameInput.value = '';\n                this.messageAddPanel.isOpen = false;\n            })\n            .appendTo(buttonWrapper);\n        msgCancel.href = '#';\n        msgCancel.textContent = Lang.Buttons.cancel;\n\n        const msgConfirm = createElement('a')\n            .addClass('entryVariableAddSpaceConfirmWorkspace')\n            .addClass('entryVariableAddSpaceButtonWorkspace')\n            .bindOnClick(() => {\n                const value = msgNameInput.value;\n                if (value.length > EntryStatic.messageMaxLength) {\n                    return Entry.toast.alert(\n                        Lang.Workspace.message_add_fail,\n                        Lang.Workspace.message_too_long\n                    );\n                }\n                this.messageAddPanel.isOpen = false;\n                msgAddSpace.addClass('off');\n                msgNameInput.value = '';\n                Entry.do('variableContainerAddMessage', {\n                    id: Entry.generateHash(),\n                    name: Entry.getOrderedName(\n                        value || Lang.Workspace.message,\n                        this.messages_,\n                        'name'\n                    ),\n                });\n            })\n            .appendTo(buttonWrapper);\n        msgConfirm.href = '#';\n        msgConfirm.textContent = Lang.Buttons.add_message;\n\n        msgAddSpace.nameField = msgNameInput;\n    }\n\n    /**\n     * 자료형 블록메뉴에서 변수, 리스트 추가 버튼 클릭시 발생하는 함수\n     * 패널을 속성탭으로 옮기고 해당 타입의 컨테이너를 오픈한다.\n     * @param type {'variable'|'list'|'message'}\n     */\n    openVariableAddPanel(type = 'variable') {\n        Entry.playground.toggleOnVariableView();\n        Entry.playground.changeViewMode('variable');\n        switch (type) {\n            case 'variable':\n                this.selectFilter(type);\n                this.updateVariableAddView(type);\n                this.clickVariableAddButton(true);\n                break;\n            case 'list':\n                this.selectFilter(type);\n                this.updateVariableAddView(type);\n                this.clickListAddButton(true);\n                break;\n            case 'message':\n                this.selectFilter(type);\n                this.clickMessageAddButton(true);\n                break;\n        }\n    }\n\n    addCloneLocalVariables(param) {\n        const that = this;\n\n        //variables\n        this.variables_\n            .reduce((acc, variable) => {\n                const cloned = clone(variable, param, 'variables_');\n                cloned && acc.push(cloned);\n                return acc;\n            }, [])\n            .forEach(this.addVariable.bind(this));\n\n        //lists\n        this.lists_\n            .reduce((acc, list) => {\n                const cloned = clone(list, param, 'lists_');\n                cloned && acc.push(cloned);\n                return acc;\n            }, [])\n            .forEach(this.addList.bind(this));\n\n        function clone(variable, param, nameSpace) {\n            //not a local variable\n            const _object = variable.object_;\n            if (!_object || _object !== param.objectId) {\n                return;\n            }\n\n            const cloned = variable.toJSON();\n            cloned.originId = cloned.id;\n            cloned.id = Entry.generateHash();\n            cloned.object = param.newObjectId;\n            cloned.name = that.checkAllVariableName(cloned.name, nameSpace)\n                ? Entry.getOrderedName(cloned.name, that[nameSpace], 'name_')\n                : cloned.name;\n            delete cloned.x;\n            delete cloned.y;\n\n            const json = param.json;\n            json.script = json.script.replace(new RegExp(cloned.originId, 'g'), cloned.id);\n            return cloned;\n        }\n    }\n\n    generateTimer(timer) {\n        const x = 240 - (Lang.Workspace.Variable_Timer.length * 12 + 70);\n        timer =\n            timer ||\n            Entry.Variable.create({\n                id: Entry.generateHash(),\n                name: Lang.Workspace.Variable_Timer,\n                value: 0,\n                variableType: 'timer',\n                visible: false,\n                x,\n                y: -70,\n            });\n\n        timer.generateView();\n        timer.tick = null;\n        Entry.engine.projectTimer = timer;\n\n        Entry.addEventListener('stop', () => {\n            Entry.engine.stopProjectTimer();\n        });\n    }\n\n    //generate Answer\n    generateAnswer(answer) {\n        answer =\n            answer ||\n            Entry.Variable.create({\n                id: Entry.generateHash(),\n                name: Lang.Blocks.VARIABLE_get_canvas_input_value,\n                value: 0,\n                variableType: 'answer',\n                visible: false,\n                x: 150,\n                y: -100,\n            });\n\n        answer.generateView();\n        Entry.container.inputValue = answer;\n        Entry.container.inputValue.setName(Lang.Blocks.VARIABLE_get_canvas_input_value);\n    }\n\n    generateStt(answer) {\n        answer =\n            answer ||\n            Entry.Variable.create({\n                id: Entry.generateHash(),\n                name: Lang.template.voice_title_text,\n                value: '-',\n                variableType: 'stt',\n                visible: false,\n            });\n        answer.generateView();\n        Entry.container.sttValue = answer;\n    }\n\n    generateVariableSettingView(variable) {\n        const that = this;\n        const createElement = Entry.createElement;\n        const _setFocused = Entry.Utils.setFocused;\n        const _setBlurredTimer = Entry.Utils.setBlurredTimer;\n\n        // 변수 속성 설정\n        const element = createElement('div')\n            .addClass('attr_inner_box')\n            .bindOnClick((e) => e.stopPropagation());\n        if (this.variableSettingView) {\n            $(this.variableSettingView).remove();\n            delete this.variableSettingView;\n        }\n        this.variableSettingView = element;\n\n        const varAttr = createElement('div').addClass('val_attr').appendTo(element);\n        const boxSubject = createElement('span').addClass('box_sjt').appendTo(varAttr);\n        boxSubject.textContent = Lang.Workspace.Variable_property;\n\n        const valTypeText = Entry.createElement('span').addClass('val_type_txt').appendTo(varAttr);\n\n        if (variable.isRealTime_) {\n            valTypeText.textContent = Lang.Menus.realtime;\n        } else if (variable.isCloud_) {\n            valTypeText.textContent = Lang.Menus.cloud;\n        }\n\n        // 기본 값 입력 창\n        const attrInputBox = createElement('div').addClass('attr_inpt').appendTo(varAttr);\n        if (this._isPythonMode()) {\n            attrInputBox.addClass('hidden');\n        }\n\n        const attrInputLabel = createElement('label').appendTo(attrInputBox);\n        attrInputLabel.setAttribute('for', 'attr_cnt');\n        attrInputLabel.textContent = Lang.Workspace.variable_default_value;\n\n        const attrInputWrapper = createElement('span')\n            .appendTo(attrInputBox)\n            .addClass('val_inptbox');\n        const attrInput = createElement('input').appendTo(attrInputWrapper);\n        attrInput.setAttribute('autocomplete', 'off');\n        attrInput.setAttribute('type', 'text');\n        attrInput.value = 0;\n        attrInput.onkeypress = Entry.Utils.blurWhenEnter;\n        attrInput.onfocus = _setFocused;\n        attrInput.onblur = _setBlurredTimer(function () {\n            const v = that.selected;\n            if (!v) {\n                console.error('error: not selected');\n                return;\n            }\n            Entry.do('variableSetDefaultValue', v.id_, this.value);\n        });\n        element.initValueInput = attrInput;\n\n        // 슬라이드 입력창\n        const slideInputBox = createElement('div').addClass('slide_inpt').appendTo(varAttr);\n\n        const slideCheckBox = createElement('div').addClass('chk_box').appendTo(slideInputBox);\n        element.slideCheck = createElement('span')\n            .addClass('entryVariableAddSpaceCheckWorkspace')\n            .bindOnClick(() => {\n                const v = that.selected;\n                Entry.do(\n                    'variableSetSlidable',\n                    v.id_,\n                    v.getType() === 'variable' ? 'slide' : 'variable'\n                );\n            })\n            .appendTo(slideCheckBox);\n        const slideCheckText = createElement('span').addClass('chk_text').appendTo(slideCheckBox);\n        slideCheckText.textContent = Lang.Workspace.slide;\n\n        // 최소 최대 영역\n        const slideCountBox = createElement('div').addClass('cnt_box').appendTo(slideInputBox);\n\n        const minValueInput = createElement('input').appendTo(slideCountBox);\n        minValueInput.textContent = Lang.Workspace.min_value;\n        minValueInput.setAttribute('autocomplete', 'off');\n        minValueInput.setAttribute('type', 'text');\n\n        const v = that.selected;\n        const vType = _.result(v, 'type');\n\n        if (vType === 'slide') {\n            minValueInput.value = v.minValue_;\n        } else {\n            minValueInput.value = 0;\n        }\n        minValueInput.onkeypress = Entry.Utils.blurWhenEnter;\n        minValueInput.onfocus = _setFocused;\n        minValueInput.onblur = _setBlurredTimer(function () {\n            const v = that.selected;\n            let value = this.value;\n            value = Entry.Utils.isNumber(value) ? value : v.getMinValue();\n            Entry.do('variableSetMinValue', v.id_, value);\n        });\n        element.minValueInput = minValueInput;\n\n        createElement('span').addClass('dash').appendTo(slideCountBox).textContent = '~';\n\n        const maxValueInput = createElement('input').appendTo(slideCountBox);\n        maxValueInput.textContent = Lang.Workspace.max_value;\n        maxValueInput.setAttribute('type', 'text');\n        maxValueInput.setAttribute('autocomplete', 'off');\n\n        if (vType === 'slide') {\n            maxValueInput.value = v.maxValue_;\n        } else {\n            maxValueInput.value = 100;\n        }\n\n        maxValueInput.onkeypress = Entry.Utils.blurWhenEnter;\n        maxValueInput.onfocus = _setFocused;\n        maxValueInput.onblur = _setBlurredTimer(function () {\n            const v = that.selected;\n            let value = this.value;\n            value = Entry.Utils.isNumber(value) ? value : v.getMaxValue();\n            Entry.do('variableSetMaxValue', v.id_, value);\n        });\n        element.maxValueInput = maxValueInput;\n        this.renderVariableReference(variable);\n    }\n\n    /**\n     * @param {object|Entry.Variable} object\n     */\n    updateVariableSettingView(v) {\n        const view = this.variableSettingView;\n        if (!view) {\n            return;\n        }\n        const {\n            initValueInput: initValue,\n            slideCheck: slide,\n            minValueInput: minValue,\n            maxValueInput: maxValue,\n        } = view;\n\n        slide.removeClass('on');\n        if (v.getType() === 'slide') {\n            slide.addClass('on');\n            minValue.removeAttribute('disabled');\n            maxValue.removeAttribute('disabled');\n            minValue.value = v.getMinValue();\n            maxValue.value = v.getMaxValue();\n        } else {\n            minValue.setAttribute('disabled', 'disabled');\n            maxValue.setAttribute('disabled', 'disabled');\n        }\n\n        initValue.value = v.getValue();\n        v.listElement.appendChild(view);\n    }\n\n    /**\n     * 속성 > 리스트 편집창 표기\n     */\n    generateListSettingView(list) {\n        const createElement = Entry.createElement;\n\n        // 리스트 속성 설정\n        const element = createElement('div')\n            .addClass('attr_inner_box')\n            .bindOnClick((e) => e.stopPropagation());\n        if (this.listSettingView) {\n            $(this.listSettingView).remove();\n            delete this.listSettingView;\n        }\n        this.listSettingView = element;\n\n        const listAttr = createElement('div').addClass('list_attr').appendTo(element);\n        if (this._isPythonMode()) {\n            listAttr.addClass('hidden');\n        }\n        const boxSubject = createElement('span').addClass('box_sjt').appendTo(listAttr);\n        boxSubject.textContent = Lang.Workspace.list_property;\n\n        const valTypeText = Entry.createElement('span').addClass('val_type_txt').appendTo(listAttr);\n\n        if (list.isRealTime_) {\n            valTypeText.textContent = Lang.Menus.realtime;\n        } else if (list.isCloud_) {\n            valTypeText.textContent = Lang.Menus.cloud;\n        }\n\n        this.generateListImportExportView(listAttr);\n        this.generateListCountView(listAttr);\n        this.generateListValuesView(listAttr);\n        this.renderVariableReference(list);\n    }\n\n    generateListImportExportView(element) {\n        const that = this;\n        const createElement = Entry.createElement;\n\n        const buttonBox = createElement('div').addClass('btn_box').appendTo(element);\n\n        const buttonExport = createElement('a')\n            .addClass('btn_list')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                const { name_ } = that.selected;\n                const array_ = that.selected.getArray();\n                if (array_.length === 0) {\n                    Entry.modal.alert(Lang.Menus.nothing_to_export);\n                } else {\n                    Entry.dispatchEvent('openExportListModal', array_, name_);\n                }\n            })\n            .appendTo(buttonBox);\n        buttonExport.textContent = Lang.Workspace.list_export;\n\n        const buttonImport = createElement('a')\n            .addClass('btn_list')\n            .bindOnClick((e) => {\n                e.stopPropagation();\n                Entry.dispatchEvent('openImportListModal');\n            })\n            .appendTo(buttonBox);\n        buttonImport.textContent = Lang.Workspace.list_import;\n    }\n\n    generateListCountView(element) {\n        const that = this;\n        const createElement = Entry.createElement;\n\n        const listCount = createElement('div').addClass('list_cnt').appendTo(element);\n\n        const countSubject = createElement('span').addClass('cnt_sjt').appendTo(listCount);\n        countSubject.textContent = Lang.Workspace.number_of_list;\n\n        const countInputBox = createElement('div').addClass('cnt_inpt').appendTo(listCount);\n\n        const buttonMinus = createElement('a')\n            .addClass('btn_cnt')\n            .bindOnClick(() => {\n                const {\n                    selected: { id_ },\n                } = that;\n                Entry.do('listChangeLength', id_, 'minus');\n            })\n            .appendTo(countInputBox);\n        buttonMinus.href = '#';\n        buttonMinus.setAttribute('tabindex', '-1');\n        this.listSettingView.minus = buttonMinus;\n\n        //List limit setting. [default value:5000, length: 4]\n        let limitValue = 5000;\n        let maxlength = 4;\n\n        const countInput = createElement('input').appendTo(countInputBox);\n        countInput.setAttribute('autocomplete', 'off');\n        countInput.setAttribute('type', 'text');\n        countInput.setAttribute('maxlength', maxlength);\n\n        countInput.onblur = function () {\n            const v = that.selected;\n            let value = this.value;\n            const array_ = v.getArray();\n            value = Entry.Utils.isNumber(value) ? value : array_.length;\n\n            if (value >= limitValue) {\n                value = limitValue;\n                Entry.toast?.alert(\n                    Lang?.Workspace?.list_cant_add_item || 'Warning',\n                    Lang?.Workspace?.list_max_length_exceeded ||\n                        'You can add up to 5,000 items to a list.'\n                );\n            }\n\n            Entry.do('listChangeLength', v.id_, Number(value));\n        };\n        countInput.onkeypress = Entry.Utils.blurWhenEnter;\n        this.listSettingView.lengthInput = countInput;\n\n        const array_ = that.selected.getArray();\n        if (array_ && array_.length > 0) {\n            const currentLeng = array_.length.toString().length;\n            // 리스트 카운트가 5000 일떄만 설정\n            maxlength = currentLeng > maxlength ? currentLeng : maxlength;\n            limitValue = array_.length > limitValue ? array_.length : limitValue;\n        }\n\n        const buttonPlus = createElement('a')\n            .addClass('btn_cnt plus')\n            .bindOnClick(() => {\n                const {\n                    selected: { id_ },\n                } = that;\n\n                const array_ = Entry.variableContainer.selected.getArray();\n                const selectedLength = array_.length;\n\n                if (selectedLength >= limitValue) {\n                    Entry.toast?.alert(\n                        Lang?.Workspace?.list_cant_add_item || 'Warning',\n                        Lang?.Workspace?.list_max_length_exceeded ||\n                            'You can add up to 5,000 items to a list.'\n                    );\n                    Entry.do('listChangeLength', id_, '');\n                } else {\n                    Entry.do('listChangeLength', id_, 'plus');\n                }\n            })\n            .appendTo(countInputBox);\n        buttonPlus.href = '#';\n        buttonPlus.setAttribute('tabindex', '-1');\n        this.listSettingView.plus = buttonPlus;\n    }\n\n    generateListValuesView(element) {\n        const createElement = Entry.createElement;\n\n        const countGroup = createElement('div').addClass('cnt_group').appendTo(element);\n        const countLabel = createElement('div').addClass('cnt_label').appendTo(countGroup);\n        countLabel.textContent = Lang.Workspace.list_default_value;\n        const scrollBox = createElement('div').addClass('scroll_box').appendTo(countGroup);\n        const el = new SimpleBar(scrollBox, { autoHide: false });\n        const parent = /* html */ `<ol class=\"cnt_list\">{1}</ol>`;\n        this.listSettingView.countGroup = countGroup;\n        this.listSettingView.scrollBox = scrollBox;\n        this.listSettingView.simpleBar = el;\n        this.listSettingView.listValues = el.getContentElement();\n        this.listSettingView.infinityScroll = new Entry.VirtualScroll(\n            this.listSettingView.listValues,\n            {\n                dataWrapper: parent,\n                itemHeight: 35,\n                groupSize: 10,\n            }\n        );\n    }\n\n    createListValueElement(index, value, startIndex = 0) {\n        return `\n        <li>\n            <span class=\"cnt\">${+index + startIndex}</span>\n            <input value=\"${xssFilters.inDoubleQuotedAttr(\n                value\n            )}\" type=\"text\" data-index=\"${index}\"/>\n            <a class=\"del\" data-index=\"${index}\"></a>\n        </li>`.trim();\n    }\n\n    updateListSettingView(list) {\n        const view = this.listSettingView;\n        const that = this;\n        if (!view) {\n            return;\n        }\n        list = list || this.selected;\n        const { infinityScroll, countGroup, listValues, lengthInput, simpleBar, scrollBox } = view;\n        const arr = list.getArray() || [];\n        lengthInput.value = arr.length;\n\n        if (arr.length > 4) {\n            scrollBox.addClass('on');\n        } else {\n            scrollBox.removeClass('on');\n        }\n        list.listElement.appendChild(view);\n        //remove element and event bindings\n        const $listValues = $(listValues);\n        $listValues.empty();\n        $listValues.off();\n        const startIndex = Entry.getMainWS().mode === Entry.Workspace.MODE_VIMBOARD ? 0 : 1;\n\n        if (arr?.length === 0) {\n            countGroup?.addClass('entryRemove');\n            return;\n        }\n        countGroup?.removeClass('entryRemove');\n\n        if (arr.length) {\n            const data = arr.map((data, i) => {\n                const item = data?.data || '';\n                const value = String(item).replace(/\\$/g, '&#36;');\n                return this.createListValueElement(i, value, startIndex);\n            });\n            infinityScroll.assignData(data);\n            infinityScroll.show();\n            $listValues.on(\n                'keyup',\n                'input',\n                _.debounce((e) => {\n                    const { target } = e;\n                    const index = target.getAttribute('data-index');\n                    data[index] = this.createListValueElement(index, target.value, startIndex);\n                    list.getArray()[index] = { data: target.value };\n                    list.updateView();\n                })\n            );\n            $listValues.on('focus', 'input', Entry.Utils.setFocused);\n            $listValues.on('keypress', 'input', Entry.Utils.blurWhenEnter);\n            $listValues.on('click', 'a', function () {\n                const index = this.getAttribute('data-index');\n                arr.splice(index, 1);\n                that.updateListSettingView();\n            });\n        }\n        simpleBar.recalculate();\n        list.updateView();\n    }\n\n    setListLength(list, value) {\n        value = Number(value);\n        const arr = this.selected.getArray();\n        const times = value - arr.length;\n        if (times && Entry.Utils.isNumber(value)) {\n            if (times > 0) {\n                _.times(times, () => this.selected.appendValue(0));\n            } else {\n                arr.length = value;\n            }\n        }\n        this.updateListSettingView();\n    }\n\n    updateViews() {\n        [...this.variables_, ...this.lists_].forEach((v) => v.updateView());\n    }\n\n    updateSelectedVariable(object, type = 'variable') {\n        const objectType = _.result(object, 'type');\n        if (this.selected) {\n            this.selected.listElement.removeClass('unfold');\n            this.selected.listElement.addClass('fold');\n        }\n        if (!object) {\n            if (type === 'variable') {\n                this.selected = null;\n            } else {\n                this.selected = null;\n            }\n        } else if (objectType === 'variable' || objectType === 'slide') {\n            this.selected = object;\n            this.selected.listElement.removeClass('fold');\n            this.selected.listElement.addClass('unfold');\n            if (!this.variableSettingView) {\n                this.generateVariableSettingView(object);\n            }\n            this.updateVariableSettingView(object);\n        } else if (objectType === 'list') {\n            this.selected = object;\n            this.selected.listElement.removeClass('fold');\n            this.selected.listElement.addClass('unfold');\n            if (!this.listSettingView) {\n                this.generateListSettingView(object);\n            }\n            this.updateListSettingView(object);\n        }\n    }\n\n    removeLocalVariables(objectId) {\n        if (!objectId) {\n            return;\n        }\n\n        [...this.variables_].forEach((v) => {\n            if (v.object_ == objectId) {\n                this.removeVariable(v);\n            }\n        });\n    }\n\n    addRef(type, blockData) {\n        const wsMode = _.result(Entry.getMainWS(), 'getMode');\n        if (!this.view_ || wsMode !== Entry.Workspace.MODE_BOARD) {\n            return;\n        }\n\n        const datum = {\n            object: blockData.getCode().object,\n            block: blockData,\n        };\n\n        this[type].push(datum);\n        Entry.playground.viewMode_ !== 'default' && this.updateList();\n        return datum;\n    }\n\n    removeRef(type, block) {\n        if (!Entry.playground.mainWorkspace) {\n            return;\n        }\n        const wsMode = Entry.getMainWS().getMode();\n        if (wsMode !== Entry.Workspace.MODE_BOARD) {\n            return;\n        }\n\n        const arr = this[type];\n\n        for (let i = 0; i < arr.length; i++) {\n            if (arr[i].block == block) {\n                arr.splice(i, 1);\n                break;\n            }\n        }\n\n        Entry.playground.viewMode_ !== 'default' && this.updateList();\n    }\n\n    updateSelected() {\n        if (this.selected) {\n            const selected = this.selected;\n            this.selected = null;\n            this.select(selected);\n        }\n    }\n\n    getObjectVariables(blockList, keys) {\n        const findFuncKeys = keys || {};\n        let functions = [];\n        const jsonData = this.getVariableJSONByBlockList(blockList);\n        let variables = jsonData.variables;\n        let messages = jsonData.messages;\n\n        blockList.forEach((block) => {\n            const type = block.type;\n            if (type && type.indexOf('func_') === 0) {\n                const id = type.substr(5);\n                if (!findFuncKeys[id]) {\n                    const func = this.functions_[id];\n                    findFuncKeys[id] = true;\n                    functions.push({\n                        id,\n                        content: JSON.stringify(func.content.toJSON()),\n                        type: func.type,\n                        localVariables: func.localVariables,\n                        useLocalVariables: func.useLocalVariables,\n                    });\n\n                    const contentBlockList = func.content.getBlockList();\n                    const jsonData = this.getObjectVariables(contentBlockList, findFuncKeys);\n                    functions = _.unionBy(functions, jsonData.functions, 'id');\n                    variables = _.unionBy(variables, jsonData.variables, 'id');\n                    messages = _.unionBy(messages, jsonData.messages, 'id');\n                }\n            }\n        });\n\n        return {\n            functions,\n            variables,\n            messages,\n        };\n    }\n\n    getVariableJSONByBlockList(blockList) {\n        const variables = [];\n        const messages = [];\n        const variableSet = [...this.variables_, ...this.lists_, ...this.messages_].reduce(\n            (acc, data) => {\n                acc[data.id_ || data.id] = data;\n                return acc;\n            },\n            {}\n        );\n\n        blockList.forEach((block) => {\n            const data = block.data || {};\n            const type = data.type;\n            if (!type) {\n                return;\n            }\n            const isMessage = _includes(EntryStatic.messageBlockList, type);\n            const isVariable = _includes(EntryStatic.variableBlockList, type);\n\n            if (isMessage || isVariable) {\n                block.data.params.forEach((param) => {\n                    if (typeof param === 'string' && !!variableSet[param]) {\n                        const item = variableSet[param];\n                        if (isVariable) {\n                            variables.push(item.toJSON());\n                        } else {\n                            messages.push({\n                                id: item.id,\n                                name: item.name,\n                            });\n                        }\n                        variableSet[param] = undefined;\n                    }\n                });\n            }\n        });\n\n        return {\n            variables,\n            messages,\n        };\n    }\n\n    _getBlockMenu() {\n        return _.result(Entry.getMainWS(), 'getBlockMenu');\n    }\n\n    _truncName(name, type, maxLen) {\n        maxLen = maxLen || this._maxNameLength;\n\n        if (name.length <= maxLen) {\n            return name;\n        }\n\n        Entry.toast.warning(\n            Lang.Workspace[`${type}_name_auto_edited_title`],\n            Lang.Workspace[`${type}_too_long`]\n        );\n\n        return name.substring(0, maxLen);\n    }\n\n    _maxNameLength = 10;\n\n    clear() {\n        this.select(null);\n        const _removeFunc = _.partial(_.result, _, 'remove');\n        const { engine = {}, container = {}, playground } = Entry;\n\n        [...this.variables_, ...this.lists_].forEach(_removeFunc);\n        _removeFunc(engine.projectTimer);\n        _removeFunc(container.inputValue);\n        _.each(this.functions_, this.removeFunction.bind(this));\n\n        this.viewMode_ = 'all';\n        this.variables_ = [];\n        this.lists_ = [];\n        this.messages_ = [];\n        this.functions_ = {};\n\n        this._variableRefs = [];\n        this._messageRefs = [];\n        this._functionRefs = [];\n\n        Entry.Func.reset();\n        playground.reloadPlayground();\n        this.updateList();\n    }\n\n    _isPythonMode() {\n        return _.result(Entry.getMainWS(), 'isVimMode');\n    }\n\n    getDom(query) {\n        if (_.isEmpty(query)) {\n            return;\n        }\n\n        query = [...query];\n\n        switch (query.shift()) {\n            case 'filter':\n                return this.filterElements[query.shift()];\n            case 'functionAddButton':\n                return this.functionAddButton_;\n            case 'variableAddButton':\n                return this.variableAddButton_;\n            case 'listAddButton':\n                return this.listAddButton_;\n            case 'variableAddConfirmButton':\n                return this.variableAddConfirmButton;\n            case 'listAddConfirmButton':\n                return this.listAddConfirmButton;\n            case 'variableAddInput':\n                return this.variableAddPanel.view.name;\n            case 'listAddInput':\n                return this.listAddPanel.view.name;\n            case 'messageAddButton':\n                return this.messageAddButton_;\n            case 'variableSetVisibility':\n                return this.variableSettingView.visibleCheck;\n            case 'listSetVisibility':\n                return this.listSettingView.visibleCheck;\n            case 'variableSetDefaultValue':\n                return this.variableSettingView.initValueInput;\n            case 'slideCheck':\n                return this.variableSettingView.slideCheck;\n            case 'variableMinValue':\n                return this.variableSettingView.minValueInput;\n            case 'variableMaxValue':\n                return this.variableSettingView.maxValueInput;\n            case 'messageList':\n                return this.getMessage(query.shift()).listElement.nameField;\n            case 'variableScope': {\n                const { globalCheck, localCheck } = this._getAddPanel('variable').view;\n                return query.shift() === 'global' ? globalCheck : localCheck;\n            }\n            case 'listScope': {\n                const { globalCheck, localCheck } = this._getAddPanel('list').view;\n                return query.shift() === 'global' ? globalCheck : localCheck;\n            }\n            case 'variableCloud':\n                return this._getAddPanel('variable').view.cloudCheck;\n            case 'listCloud':\n                return this._getAddPanel('list').view.cloudCheck;\n            case 'listChangeLength':\n                return this.listSettingView[query.shift()];\n            case 'listDefaultValue':\n                return $('.entryListSettingEachInputWorkspace')[query.shift()];\n            case 'messageEditButton':\n                return $(this.getMessage(query.shift()).listElement).find('.editButton')[0];\n            case 'variableEditButton':\n                return $(this.getVariable(query.shift()).listElement).find(\n                    '.entryVariableListElementEditWorkspace'\n                )[0];\n            case 'listEditButton':\n                return $(this.getList(query.shift()).listElement).find(\n                    '.entryVariableListElementEditWorkspace'\n                )[0];\n            case 'variableName':\n                return this.getVariable(query.shift()).listElement.nameField;\n        }\n    }\n\n    _clickAddButton(type, forceOpen, doNotFocus) {\n        const panel = this._getAddPanel(type);\n        const panelView = panel.view;\n        const panelViewName = panelView.name;\n        if (panel.isOpen && !forceOpen) {\n            panelView.addClass('off');\n            panel.isOpen = false;\n        } else {\n            panelViewName.value = '';\n            panelView.removeClass('off');\n            !doNotFocus && Entry.Utils.focusIfNotActive(panelViewName);\n            panel.isOpen = true;\n        }\n    }\n\n    clickVariableAddButton(...args) {\n        this._clickAddButton.call(this, 'variable', ...args);\n        this.variableAddPanel.view.cloudCheck.addClass('on');\n    }\n\n    clickListAddButton(...args) {\n        this._clickAddButton.call(this, 'list', ...args);\n        this.listAddPanel.view.cloudCheck.addClass('on');\n    }\n\n    clickMessageAddButton(...args) {\n        this._clickAddButton.call(this, 'message', ...args);\n    }\n\n    _makeVariableData(type = 'variable') {\n        const {\n            view,\n            info: { isCloud, object, isRealTime },\n        } = this._getAddPanel(type);\n\n        let name = view.name.value.trim();\n        if (_.isEmpty(name)) {\n            name = Lang.Workspace[type];\n        }\n\n        name = this._truncName(name, type, this._maxNameLength);\n\n        const target = `${type}s_`;\n        if (this.checkAllVariableName(name, target)) {\n            name = Entry.getOrderedName(name, this[target], 'name_');\n            Entry.toast.warning(Lang.Workspace[`${type}_rename`], Lang.Workspace[`${type}_dup`]);\n        }\n\n        return {\n            name,\n            isCloud,\n            isRealTime,\n            object,\n            variableType: type,\n        };\n    }\n\n    applyOption() {\n        const { variable, message, list, func } = this._filterTabs;\n\n        process(variable, Entry.variableEnable);\n        process(message, Entry.messageEnable);\n        process(list, Entry.listEnable);\n        process(func, Entry.functionEnable);\n\n        function process(view, value) {\n            if (value) {\n                view.removeClass('disable');\n            } else {\n                view.addClass('disable');\n            }\n            view.disabled = !value;\n        }\n    }\n\n    setVariableSlidable(v, type, value) {\n        //no type changed\n        //just return\n        if (v.getType() === type) {\n            return;\n        }\n        const variables = this.variables_;\n        const variableJSON = v.toJSON();\n        variableJSON.variableType = type;\n        const newVariable = Entry.Variable.create(variableJSON);\n        variables.splice(variables.indexOf(v), 0, newVariable);\n        if (value !== undefined) {\n            variableJSON.value = value;\n        }\n        if (type === 'slide') {\n            if (newVariable.getValue() < 0) {\n                newVariable.setValue(0);\n            } else if (newVariable.getValue() > 100) {\n                newVariable.setValue(100);\n            }\n        }\n        this.createVariableView(newVariable);\n        this.removeVariable(v);\n        this.updateSelectedVariable(newVariable);\n        newVariable.generateView();\n    }\n\n    _getAddPanel(type = 'variable') {\n        return this[`${type}AddPanel`];\n    }\n\n    getFunctionByBlockId(blockId) {\n        return _find(this.functions_, (func) => func.getBlockById(blockId));\n    }\n\n    hasBlockInFunction = _memoize((blockId) =>\n        _some(this.functions_, (func) => Boolean(func.getBlockById(blockId)))\n    );\n\n    hasParamBlockInFunction = _memoize((paramId) =>\n        _some(this.functions_, (func) => Boolean(func.getBlockByParamId(paramId)))\n    );\n\n    hasFuncBlockInFunction = _memoize((funcId) =>\n        _some(this.functions_, (func) => Boolean(func.getFuncBlockByFuncId(`func_${funcId}`)))\n    );\n};\n"
  },
  {
    "path": "src/command/command.js",
    "content": "'use strict';\n\nEntry.Command = {};\n\n(function(c) {\n    c[Entry.STATIC.COMMAND_TYPES.do] = {\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        log(objectId) {\n            return [];\n        },\n        skipUndoStack: true,\n    };\n\n    c[Entry.STATIC.COMMAND_TYPES.undo] = {\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        log(objectId) {\n            return [];\n        },\n        skipUndoStack: true,\n    };\n\n    c[Entry.STATIC.COMMAND_TYPES.redo] = {\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        log(objectId) {\n            return [];\n        },\n        skipUndoStack: true,\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/command_util.js",
    "content": "'use strict';\n\nconst COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\nconst obj = {\n    createTooltip(title, content, target, callback, option = {}) {\n        return new Entry.Tooltip(\n            [\n                {\n                    title,\n                    content,\n                    target,\n                },\n            ],\n            Object.assign(\n                {\n                    restrict: true,\n                    dimmed: true,\n                    callBack: callback,\n                },\n                option\n            )\n        );\n    },\n    returnEmptyArr() {\n        return [];\n    },\n    getExpectedData(name, defaultValue) {\n        const expected = (Entry.expectedAction || []).concat();\n        if (!name || _.isEmpty(expected)) {\n            return defaultValue;\n        }\n\n        expected.shift();\n\n        const ret = _.find(expected, ([key]) => key === name);\n        if (ret) {\n            return ret[1];\n        }\n\n        return defaultValue;\n    },\n};\n\nEntry.Command[COMMAND_TYPES.dismissModal] = {\n    do() {\n        Entry.dispatchEvent('dismissModal');\n    },\n    state: obj.returnEmptyArr,\n    log: obj.returnEmptyArr,\n    undo: 'dismissModal',\n    recordable: Entry.STATIC.RECORDABLE.SKIP,\n    validate: false,\n    dom: [],\n};\n\nmodule.exports = obj;\n"
  },
  {
    "path": "src/command/commander.js",
    "content": "class EntryCommander {\n    constructor() {\n        Entry.do = this.do.bind(this);\n\n        Entry.undo = this.undo.bind(this);\n\n        this.editor = {};\n\n        this.reporters = [];\n\n        Entry.Command.editor = this.editor;\n\n        this.doEvent = new Entry.Event(this);\n        this.logEvent = new Entry.Event(this);\n\n        this.doCommandAll = Entry.doCommandAll;\n        this._storage = null;\n    }\n\n    do(commandType, ...args) {\n        const {\n            stateManager,\n            Command: EntryCommand,\n            STATIC: { COMMAND_TYPES, getCommandName },\n        } = Entry;\n\n        if (typeof commandType === 'string') {\n            commandType = COMMAND_TYPES[commandType];\n        }\n\n        //intentionally delay reporting\n        this.report(COMMAND_TYPES.do);\n        this.report(commandType, args);\n\n        const command = EntryCommand[commandType];\n\n        console.log('commandType', commandType, getCommandName(commandType));\n\n        let state;\n\n        if (stateManager && !this._checkIsSkip(commandType)) {\n            state = stateManager.addCommand(\n                ...[commandType, this, this.do, command.undo].concat(\n                    command.state.apply(this, args)\n                )\n            );\n        } else if (this.checkIsChange(commandType)) {\n            if (Entry.creationChangedEvent) {\n                Entry.creationChangedEvent.notify();\n            }\n        }\n        const value = command.do.apply(this, args);\n        this.doEvent.notify(commandType, args);\n        const id = state ? state.id : null;\n\n        return {\n            value,\n            isPass: function (isPass, skipCount) {\n                this.isPassById(id, isPass, skipCount);\n            }.bind(this),\n        };\n    }\n\n    undo(commandType, ...args) {\n        this.report(Entry.STATIC.COMMAND_TYPES.undo);\n\n        const command = Entry.Command[commandType];\n\n        let state;\n        if (Entry.stateManager && command.skipUndoStack !== true) {\n            state = Entry.stateManager.addCommand.apply(\n                Entry.stateManager,\n                [commandType, this, this.do, command.undo].concat(command.state.apply(this, args))\n            );\n        }\n        return {\n            value: command.do.apply(this, args),\n            isPass: function (isPass) {\n                this.isPassById(state.id, isPass);\n            }.bind(this),\n        };\n    }\n\n    redo(commandType, ...args) {\n        this.report(Entry.STATIC.COMMAND_TYPES.redo);\n\n        const command = Entry.Command[commandType];\n\n        if (Entry.stateManager && command.skipUndoStack !== true) {\n            Entry.stateManager.addCommand.apply(\n                Entry.stateManager,\n                [commandType, this, this.undo, commandType].concat(command.state.apply(null, args))\n            );\n        }\n        command.undo.apply(this, args);\n    }\n\n    setCurrentEditor(key, object) {\n        this.editor[key] = object;\n    }\n\n    isPass(isPass = true) {\n        if (!Entry.stateManager) {\n            return;\n        }\n\n        const lastCommand = Entry.stateManager.getLastCommand();\n        if (lastCommand) {\n            lastCommand.isPass = isPass;\n        }\n    }\n\n    isPassById(id, isPass = true, skipCount = 0) {\n        if (!id || !Entry.stateManager) {\n            return;\n        }\n\n        const lastCommand = Entry.stateManager.getLastCommandById(id);\n        if (lastCommand) {\n            lastCommand.isPass = isPass;\n            if (skipCount) {\n                lastCommand.skipCount = !!skipCount;\n            }\n        }\n    }\n\n    addReporter(reporter) {\n        reporter.logEventListener = this.logEvent.attach(reporter, reporter.add);\n    }\n\n    removeReporter(reporter) {\n        if (reporter.logEventListener) {\n            this.logEvent.detatch(reporter.logEventListener);\n        }\n        delete reporter.logEventListener;\n    }\n\n    report(commandType, argumentsArray) {\n        let data;\n\n        if (commandType && Entry.Command[commandType] && Entry.Command[commandType].log) {\n            data = Entry.Command[commandType].log.apply(this, argumentsArray);\n        } else {\n            data = argumentsArray;\n        }\n        data.unshift(commandType);\n        this.logEvent.notify(data);\n    }\n\n    applyOption() {\n        this.doCommandAll = Entry.doCommandAll;\n    }\n\n    _checkIsSkip(commandType) {\n        const { skipUndoStack } = Entry.Command[commandType];\n        return (\n            skipUndoStack === true ||\n            (!Entry.doCommandAll && _.includes(Entry.STATIC.COMMAND_TYPES_NOT_ALWAYS, commandType))\n        );\n    }\n\n    checkIsChange(commandType) {\n        return _.includes(Entry.STATIC.COMMAND_TYPES_CHANGE_CHECK, commandType);\n    }\n}\n\nEntry.Commander = EntryCommander;\n"
  },
  {
    "path": "src/command/commands/block.js",
    "content": "/*\n *\n */\n'use strict';\nimport isFunction from 'lodash/isFunction';\n\n(function (c) {\n    const COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n    let obj;\n\n    c[COMMAND_TYPES.addThread] = {\n        do(blocks, index) {\n            return this.editor.board.code.createThread(blocks, index);\n        },\n        state(blocks, index) {\n            if (index === undefined || index === null) {\n                index = this.editor.board.code.getThreadCount();\n            }\n            return [index];\n        },\n        log(blocks, index) {\n            if (blocks instanceof Entry.Thread) {\n                blocks = blocks.toJSON();\n            }\n            return [\n                ['blocks', blocks],\n                ['index', index],\n            ];\n        },\n        undo: 'destroyThread',\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        validate: false,\n        dom: ['playground', 'blockMenu', '&0'],\n    };\n\n    obj = _.clone(c[COMMAND_TYPES.addThread]);\n    obj.showMe = function (restrictor) {\n        if (restrictor.isTooltipFaded()) {\n            return;\n        }\n        restrictor.fadeOutTooltip();\n        const svgGroup = Entry.getDom(restrictor.processDomQuery(this.dom));\n        const nextCmd = restrictor.requestNextData().content;\n        const cmdType = nextCmd[0];\n        let targetDomQuery;\n        if (cmdType === COMMAND_TYPES.moveBlockFromBlockMenu) {\n            targetDomQuery = ['playground', 'board', 'coord', '&1', '&2'];\n        } else {\n            targetDomQuery = ['playground', 'board', '&1', 'magnet', 'next', 0];\n        }\n\n        const targetDom = Entry.getDom(restrictor.processDomQuery(targetDomQuery, nextCmd));\n        const { left, top } = targetDom.getBoundingClientRect();\n\n        Entry.Utils.glideBlock(svgGroup, left, top, () => {\n            restrictor.fadeInTooltip();\n        });\n    };\n    obj.followCmd = true;\n    obj.restrict = function (data, domQuery, callback, restrictor) {\n        const nextCmd = restrictor.requestNextData().content;\n        if (nextCmd[0] === Entry.STATIC.COMMAND_TYPES.insertBlockFromBlockMenu) {\n            Entry.Command.editor.board.scrollToPointer(nextCmd[2][1]);\n        }\n\n        const isDone = false;\n        const tooltip = new Entry.Tooltip(\n            [\n                {\n                    title: data.tooltip.title,\n                    content: data.tooltip.content,\n                    target: domQuery,\n                },\n            ],\n            {\n                dimmed: true,\n                restrict: true,\n                callBack: callback,\n            }\n        );\n        return tooltip;\n    };\n    c[COMMAND_TYPES.addThreadFromBlockMenu] = obj;\n\n    c[COMMAND_TYPES.destroyThread] = {\n        do(thread) {\n            // thread can be index\n            if (!(thread instanceof Entry.Thread)) {\n                thread = this.editor.board.code.getThread(thread);\n            }\n            if (thread) {\n                const block = thread.getFirstBlock();\n                block.destroy(true, true);\n            }\n        },\n        state(thread) {\n            if (!(thread instanceof Entry.Thread)) {\n                thread = this.editor.board.code.getThread(thread);\n            }\n            const index = this.editor.board.code.getThreadIndex(thread);\n            const json = thread ? thread.toJSON() : {};\n            return [json, index];\n        },\n        log(threadIndex) {\n            if (threadIndex instanceof Entry.Thread) {\n                threadIndex = this.editor.board.code.getThreadIndex(threadIndex);\n            }\n\n            return [['index', threadIndex]];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict(data, domQuery, callback) {\n            callback();\n        },\n        validate: false,\n        undo: 'addThread',\n    };\n\n    c[COMMAND_TYPES.destroyBlock] = {\n        do(block) {\n            block = this.editor.board.findBlock(block);\n            block.doDestroy();\n        },\n        state(block) {\n            let isThread = false;\n            block = this.editor.board.findBlock(block);\n            const pointer = block.targetPointer();\n            const blockJSON = block.toJSON();\n            if (pointer.length === 3) {\n                // 첫번째 블록 삭제\n                if (block.thread.getCount() === 1) {\n                    // 단일 블록 쓰레드 삭제\n                    isThread = true;\n                } else {\n                    pointer.push(-1);\n                } // targetPointer 결과값 보정\n            }\n            if (block.getBlockType() === 'output') {\n                blockJSON.params[1] = undefined;\n            }\n            return [blockJSON, pointer, isThread];\n        },\n        log(block) {\n            block = this.editor.board.findBlock(block);\n            return [['block', block.pointer ? block.pointer() : block]];\n        },\n        undo: 'recoverBlock',\n    };\n\n    c[COMMAND_TYPES.recoverBlock] = {\n        do(blockModel, pointer, isThread) {\n            if (isThread) {\n                return this.editor.board.code.createThread([blockModel], pointer[2]);\n            } else {\n                const block = this.editor.board.code.createThread([blockModel]).getFirstBlock();\n                this.editor.board.insert(block, pointer);\n            }\n        },\n        state(block) {\n            if (typeof block !== 'string') {\n                block = block.id;\n            }\n            return [block];\n        },\n        log(block, pointer) {\n            block = this.editor.board.findBlock(block.id);\n            return [\n                ['block', block],\n                ['pointer', pointer],\n            ];\n        },\n        undo: 'destroyBlock',\n    };\n\n    c[COMMAND_TYPES.insertBlock] = {\n        do(block, targetBlock, count) {\n            block = this.editor.board.findBlock(block);\n            let blockArgument;\n            if (block instanceof Entry.FieldBlock) {\n                blockArgument = block.value;\n            } else {\n                blockArgument = block;\n            }\n            this.editor.board.insert(blockArgument, targetBlock, count);\n            const { params = [] } = block._schema || {};\n            const shouldRerender = params.find(\n                ({ type, menuName }) => type === 'DropdownDynamic' && isFunction(menuName)\n            );\n            if (shouldRerender) {\n                block.view.reDraw();\n            }\n        },\n        state(block, targetBlock, count) {\n            block = this.editor.board.findBlock(block);\n            const data = [block, block.targetPointer()];\n\n            if (typeof block !== 'string' && block.getBlockType() === 'basic') {\n                data.push(block.thread.getCount(block));\n            } else if (typeof block !== 'string' && block.getBlockType() === 'output') {\n                data.push(count || block.getOutputBlockCount() + 1);\n            }\n            return data;\n        },\n        log(block, targetBlock, count) {\n            block = this.editor.board.findBlock(block);\n            if (!(targetBlock instanceof Array)) {\n                targetBlock = targetBlock.pointer();\n            }\n\n            const result = [\n                ['block', block ? block.pointer() : ''],\n                ['targetPointer', targetBlock],\n            ];\n            if (count) {\n                result.push(['count', count ? count : null]);\n            }\n            return result;\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'insertBlock',\n        restrict(data, domQuery, callback, restrictor) {\n            const board = Entry.Command.editor.board;\n            const block = board.code.getByPointer(data.content[1][1]);\n            let blockView;\n            board.scrollToPointer(data.content[1][1]);\n\n            if (restrictor.toolTipRender) {\n                restrictor.toolTipRender.titleIndex = 0;\n                restrictor.toolTipRender.contentIndex = 0;\n            }\n            const isDefault = data.tooltip.isDefault;\n            let isDone = false;\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    dimmed: true,\n                    restrict: true,\n                    callBack(isFromInit) {\n                        if (isDone || !isFromInit) {\n                            return;\n                        }\n                        isDone = true;\n                        callback();\n\n                        const ret = board.scrollToPointer(data.content[2][1]);\n                        if (block) {\n                            blockView = block.view;\n                        }\n                        if (blockView) {\n                            blockView = blockView.getSvgRoot().blockView;\n                            if (blockView && ret) {\n                                blockView.moveBy(-ret[0], -ret[1]);\n                            }\n                        }\n\n                        restrictor.toolTipRender.titleIndex = 1;\n\n                        if (restrictor.toolTipRender) {\n                            if (!isDefault) {\n                                restrictor.toolTipRender.contentIndex = 1;\n                            } else {\n                                const target = Entry.Command.editor.board.code.getTargetByPointer(\n                                    data.content[2][1]\n                                );\n\n                                if (target && target.isParamBlockType()) {\n                                    restrictor.toolTipRender.contentIndex = 2;\n                                } else {\n                                    restrictor.toolTipRender.contentIndex = 1;\n                                }\n                            }\n                        }\n\n                        const processedDomQuery = restrictor.processDomQuery([\n                            'playground',\n                            'board',\n                            '&1',\n                            'magnet',\n                        ]);\n\n                        tooltip.init(\n                            [\n                                {\n                                    title: data.tooltip.title,\n                                    content: data.tooltip.content,\n                                    target: processedDomQuery,\n                                },\n                            ],\n                            {\n                                indicator: true,\n                                callBack() {},\n                            }\n                        );\n                    },\n                }\n            );\n            return tooltip;\n        },\n        showMe(restrictor) {\n            if (restrictor.isTooltipFaded()) {\n                return;\n            }\n            restrictor.fadeOutTooltip();\n            const svgGroup = Entry.getDom(restrictor.processDomQuery(this.dom));\n            const targetDom = Entry.getDom(\n                restrictor.processDomQuery(['playground', 'board', '&1', 'magnet', 'next', 0])\n            );\n            const targetRect = targetDom.getBoundingClientRect();\n\n            Entry.Utils.glideBlock(svgGroup, targetRect.left, targetRect.top, () => {\n                restrictor.fadeInTooltip();\n            });\n        },\n        dom: ['playground', 'board', '&0'],\n    };\n\n    obj = _.clone(c[COMMAND_TYPES.insertBlock]);\n    obj.followCmd = true;\n    c[COMMAND_TYPES.insertBlockFollowSeparate] = obj;\n\n    obj = _.clone(c[COMMAND_TYPES.insertBlock]);\n    obj.restrict = function (data, domQuery, callback, restrictor) {\n        if (restrictor.toolTipRender) {\n            if (restrictor.toolTipRender) {\n                const target = Entry.Command.editor.board.code.getByPointer(data.content[2][1]);\n\n                if (!target || target.isParamBlockType()) {\n                    restrictor.toolTipRender.contentIndex = 1;\n                } else {\n                    restrictor.toolTipRender.contentIndex = 0;\n                }\n            }\n        }\n        callback();\n        return new Entry.Tooltip(\n            [\n                {\n                    title: data.tooltip.title,\n                    content: data.tooltip.content,\n                    target: domQuery,\n                },\n            ],\n            {\n                indicator: true,\n                callBack() {},\n            }\n        );\n    };\n    obj.dom = ['playground', 'board', '&1', 'magnet'];\n    c[COMMAND_TYPES.insertBlockFromBlockMenu] = obj;\n\n    obj = _.clone(c[COMMAND_TYPES.insertBlockFromBlockMenu]);\n    obj.followCmd = true;\n    c[COMMAND_TYPES.insertBlockFromBlockMenuFollowSeparate] = obj;\n\n    c[COMMAND_TYPES.separateBlock] = {\n        do(block, dragMode, y) {\n            block = this.editor.board.findBlock(block);\n            let blockView;\n            let blockArgument;\n            if (block instanceof Entry.FieldBlock) {\n                blockView = block.value.view;\n                blockArgument = block.value;\n            } else {\n                blockView = block.view;\n            }\n            if (typeof y === 'number') {\n                blockView.moveTo(dragMode, y);\n                dragMode = undefined;\n            }\n\n            dragMode = dragMode === undefined ? Entry.DRAG_MODE_DRAG : dragMode;\n\n            if (blockView) {\n                blockView._toGlobalCoordinate(dragMode);\n            }\n            block.doSeparate(blockArgument);\n            const { params = [] } = block._schema || {};\n            const shouldRerender = params.find(\n                ({ type, menuName }) => type === 'DropdownDynamic' && isFunction(menuName)\n            );\n            if (shouldRerender) {\n                block.view.reDraw();\n            }\n        },\n        state(block) {\n            block = this.editor.board.findBlock(block);\n            let blockArgument;\n            if (block instanceof Entry.FieldBlock) {\n                blockArgument = block.value;\n            } else {\n                blockArgument = block;\n            }\n            const data = [blockArgument];\n            const pointer = block.targetPointer();\n            data.push(pointer);\n\n            if (block.getBlockType() === 'basic') {\n                data.push(block.thread.getCount(block));\n            }\n            return data;\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        log(block) {\n            block = this.editor.board.findBlock(block);\n            const blockPointer = block.pointer();\n            if (block.view) {\n                block = block.view;\n            }\n\n            return [\n                ['block', blockPointer],\n                ['x', block.x],\n                ['y', block.y],\n            ];\n        },\n        restrict(data, domQuery, callback, restrictor) {\n            Entry.Command.editor.board.scrollToPointer(data.content[1][1]);\n            let isDone = false;\n            if (restrictor.toolTipRender) {\n                restrictor.toolTipRender.titleIndex = 0;\n                restrictor.toolTipRender.contentIndex = 0;\n            }\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    dimmed: true,\n                    restrict: true,\n                    callBack(isFromInit) {\n                        if (isDone || !isFromInit) {\n                            return;\n                        }\n                        if (restrictor.toolTipRender) {\n                            restrictor.toolTipRender.titleIndex = 1;\n                            restrictor.toolTipRender.contentIndex = 1;\n                        }\n                        callback();\n                        isDone = true;\n                        tooltip.init(\n                            [\n                                {\n                                    title: data.tooltip.title,\n                                    content: data.tooltip.content,\n                                    target: restrictor.processDomQuery([\n                                        'playground',\n                                        'board',\n                                        'coord',\n                                        '&1',\n                                        '&2',\n                                    ]),\n                                },\n                            ],\n                            {\n                                indicator: true,\n                                callBack() {\n                                    callback();\n                                },\n                            }\n                        );\n                    },\n                }\n            );\n            return tooltip;\n        },\n        undo: 'insertBlock',\n        dom: ['playground', 'board', '&0'],\n    };\n\n    obj = _.clone(c[COMMAND_TYPES.separateBlock]);\n    obj.restrict = function (data, domQuery, callback, restrictor) {\n        Entry.Command.editor.board.scrollToPointer(data.content[1][1]);\n        let isDone = false;\n        if (restrictor.toolTipRender) {\n            restrictor.toolTipRender.titleIndex = 0;\n            restrictor.toolTipRender.contentIndex = 0;\n        }\n        const tooltip = new Entry.Tooltip(\n            [\n                {\n                    title: data.tooltip.title,\n                    content: data.tooltip.content,\n                    target: domQuery,\n                },\n            ],\n            {\n                dimmed: true,\n                restrict: true,\n                callBack(isFromInit) {\n                    if (isDone || !isFromInit) {\n                        return;\n                    }\n                    callback();\n                    if (restrictor.toolTipRender) {\n                        restrictor.toolTipRender.titleIndex = 1;\n                        restrictor.toolTipRender.contentIndex = 1;\n                    }\n                    isDone = true;\n                    tooltip.init(\n                        [\n                            {\n                                title: data.tooltip.title,\n                                content: data.tooltip.content,\n                                target: ['playground', 'board', 'trashcan'],\n                            },\n                        ],\n                        {\n                            indicator: true,\n                            callBack() {\n                                callback();\n                            },\n                        }\n                    );\n                },\n            }\n        );\n        return tooltip;\n    };\n    obj.showMe = function (restrictor) {\n        if (restrictor.isTooltipFaded()) {\n            return;\n        }\n        restrictor.fadeOutTooltip();\n        const svgGroup = Entry.getDom(restrictor.processDomQuery(this.dom));\n        const targetDom = Entry.getDom(['playground', 'board', 'trashcan']);\n        const targetRect = targetDom.getBoundingClientRect();\n\n        Entry.Utils.glideBlock(svgGroup, targetRect.left, targetRect.top, () => {\n            restrictor.fadeInTooltip();\n        });\n    };\n    obj.followCmd = true;\n    c[COMMAND_TYPES.separateBlockForDestroy] = obj;\n\n    c[COMMAND_TYPES.moveBlock] = {\n        do(block, x, y) {\n            if (x !== undefined) {\n                // do from undo stack\n                block = this.editor.board.findBlock(block);\n                block.moveTo(x, y);\n            } else {\n                block._updatePos();\n            }\n        },\n        state(block) {\n            block = this.editor.board.findBlock(block);\n            return [block, block.x, block.y];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict(data, domQuery, callback, restrictor) {\n            let isDone = false;\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    dimmed: true,\n                    restrict: true,\n                    callBack(isFromInit) {\n                        if (isDone || !isFromInit) {\n                            return;\n                        }\n                        isDone = true;\n                        callback();\n                        tooltip.init(\n                            [\n                                {\n                                    title: data.tooltip.title,\n                                    content: data.tooltip.content,\n                                    target: restrictor.processDomQuery([\n                                        'playground',\n                                        'board',\n                                        'coord',\n                                        '&1',\n                                        '&2',\n                                    ]),\n                                },\n                            ],\n                            {\n                                indicator: true,\n                                callBack() {},\n                            }\n                        );\n                    },\n                }\n            );\n            return tooltip;\n        },\n        validate: false,\n        log(block, x, y) {\n            block = this.editor.board.findBlock(block);\n            if (!block || !block.view) {\n                console.error('moveBlock: target not exist ', block);\n                return [];\n            }\n            return [\n                ['block', block.pointer()],\n                ['x', block.view.x],\n                ['y', block.view.y],\n            ];\n        },\n        undo: 'moveBlock',\n        dom: ['playground', 'board', '&0'],\n    };\n\n    obj = _.clone(c[COMMAND_TYPES.moveBlock]);\n    obj.followCmd = true;\n    obj.restrict = function (data, domQuery, callback, restrictor) {\n        Entry.Command.editor.board.scrollToPointer(data.content[1][1]);\n        let isDone = false;\n        if (restrictor.toolTipRender) {\n            restrictor.toolTipRender.titleIndex = 0;\n            restrictor.toolTipRender.contentIndex = 0;\n        }\n        const tooltip = new Entry.Tooltip(\n            [\n                {\n                    title: data.tooltip.title,\n                    content: data.tooltip.content,\n                    target: domQuery,\n                },\n            ],\n            {\n                dimmed: true,\n                restrict: true,\n                callBack(isFromInit) {\n                    if (isDone || !isFromInit) {\n                        return;\n                    }\n                    isDone = true;\n                    callback();\n                    if (restrictor.toolTipRender) {\n                        restrictor.toolTipRender.titleIndex = 1;\n                        restrictor.toolTipRender.contentIndex = 1;\n                    }\n                    tooltip.init(\n                        [\n                            {\n                                title: data.tooltip.title,\n                                content: data.tooltip.content,\n                                target: ['playground', 'board', 'trashcan'],\n                            },\n                        ],\n                        {\n                            indicator: true,\n                            callBack() {\n                                callback();\n                            },\n                        }\n                    );\n                },\n            }\n        );\n        return tooltip;\n    };\n    c[COMMAND_TYPES.moveBlockForDestroy] = obj;\n\n    obj = _.clone(c[COMMAND_TYPES.moveBlock]);\n    obj.restrict = function (data, domQuery, callback) {\n        callback();\n        return new Entry.Tooltip(\n            [\n                {\n                    title: data.tooltip.title,\n                    content: data.tooltip.content,\n                    target: domQuery,\n                },\n            ],\n            {\n                callBack() {},\n            }\n        );\n    };\n    obj.dom = ['playground', 'board', 'coord', '&1', '&2'];\n    c[COMMAND_TYPES.moveBlockFromBlockMenu] = obj;\n\n    cloneCommand(COMMAND_TYPES.cloneBlock, COMMAND_TYPES.addThread, [\n        ['undo', 'uncloneBlock'],\n        ['dom', undefined],\n    ]);\n\n    cloneCommand(COMMAND_TYPES.uncloneBlock, COMMAND_TYPES.destroyThread, [['undo', 'cloneBlock']]);\n\n    c[COMMAND_TYPES.scrollBoard] = {\n        do(dx, dy, isPass) {\n            if (!isPass) {\n                this.editor.board.scroller._scroll(dx, dy);\n            }\n            delete this.editor.board.scroller._diffs;\n        },\n        state(dx, dy) {\n            return [-dx, -dy];\n        },\n        log(dx, dy) {\n            return [\n                ['dx', dx],\n                ['dy', dy],\n            ];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        undo: 'scrollBoard',\n    };\n\n    c[COMMAND_TYPES.setFieldValue] = {\n        do(pointer, value, code) {\n            let field;\n            if (code) {\n                field = code.getByPointer(pointer);\n            } else {\n                field = this.editor.board.findBlock(pointer);\n            }\n\n            field.setValue(value, true);\n            Entry.disposeEvent.notify(true);\n            field._blockView.disableMouseEvent = false;\n        },\n        state(pointer, value, code) {\n            let field;\n            if (code) {\n                field = code.getByPointer(pointer);\n            } else {\n                field = this.editor.board.findBlock(pointer);\n            }\n            return [pointer, field._startValue || field.getValue()];\n        },\n        log(pointer, value) {\n            return [\n                ['pointer', pointer],\n                ['value', value],\n            ];\n        },\n        restrict(data, domQuery, callback, restrictor) {\n            let isDone = false;\n            const isDefault = data.tooltip.isDefault;\n\n            Entry.Command.editor.board.scrollToPointer(data.content[1][1]);\n\n            const field = Entry.Command.editor.board.findBlock(data.content[1][1]);\n            const blockView = field._blockView;\n            blockView.disableMouseEvent = true;\n            const fieldType = field.getFieldRawType();\n\n            if (restrictor.toolTipRender) {\n                if (!isDefault) {\n                    restrictor.toolTipRender.contentIndex = 0;\n                } else {\n                    switch (fieldType) {\n                        case 'textInput':\n                            restrictor.toolTipRender.contentIndex = 0;\n                            break;\n                        case 'dropdown':\n                        case 'dropdownDynamic':\n                            restrictor.toolTipRender.contentIndex = 1;\n                            break;\n                        case 'keyboard':\n                            restrictor.toolTipRender.contentIndex = 2;\n                            break;\n                    }\n                }\n            }\n\n            const nextValue = data.content[2][1];\n            if (field instanceof Entry.FieldTextInput) {\n                field.fixNextValue(nextValue);\n            }\n\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        direction: 'left',\n                        target: domQuery,\n                    },\n                ],\n                {\n                    dimmed: true,\n                    restrict: true,\n                    callBack(isFromInit) {\n                        if (isDone || !isFromInit) {\n                            return;\n                        }\n                        isDone = true;\n                        callback();\n                        callback();\n                        restrictor.toolTipRender.replaceContent(\n                            /&value&/gi,\n                            field.getTextValueByValue(nextValue)\n                        );\n\n                        if (restrictor.toolTipRender) {\n                            const { renderData = {} } = restrictor.toolTipRender;\n                            renderData.isPrev = false;\n                            if (!isDefault) {\n                                restrictor.toolTipRender.titleIndex = 1;\n                                restrictor.toolTipRender.contentIndex = 1;\n                            } else {\n                                switch (fieldType) {\n                                    case 'textInput':\n                                        restrictor.toolTipRender.contentIndex = 3;\n                                        break;\n                                    case 'dropdown':\n                                    case 'dropdownDynamic':\n                                        restrictor.toolTipRender.contentIndex = 4;\n                                        break;\n                                    case 'keyboard':\n                                        restrictor.toolTipRender.contentIndex = 5;\n                                        break;\n                                }\n                            }\n                        }\n\n                        tooltip.init(\n                            [\n                                {\n                                    title: data.tooltip.title,\n                                    content: data.tooltip.content,\n                                    target: restrictor.processDomQuery([\n                                        'playground',\n                                        'board',\n                                        '&0',\n                                        'option',\n                                    ]),\n                                },\n                            ],\n                            {\n                                dimmed: true,\n                                restrict: true,\n                                callBack() {\n                                    blockView.disableMouseEvent = false;\n                                },\n                            }\n                        );\n                    },\n                }\n            );\n            return tooltip;\n        },\n        disableMouseUpDispose: true,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['playground', 'board', '&0'],\n        undo: 'setFieldValue',\n    };\n\n    c[COMMAND_TYPES.selectBlockMenu] = {\n        do(selector, doNotFold, doNotAlign) {\n            const blockMenu = Entry.getMainWS().blockMenu;\n            blockMenu.selectMenu(selector, doNotFold, doNotAlign);\n            blockMenu.align();\n        },\n        state(selector, doNotFold, doNotAlign) {\n            const blockMenu = Entry.getMainWS().blockMenu;\n            return [blockMenu.lastSelector, doNotFold, doNotAlign];\n        },\n        log(selector, doNotFold, doNotAlign) {\n            return [['selector', selector]];\n        },\n        skipUndoStack: true,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['playground', 'blockMenu', 'category', '&0'],\n        undo: 'selectBlockMenu',\n    };\n\n    c[COMMAND_TYPES.destroyThreads] = {\n        do() {\n            const threads = this.editor.board.code\n                .getThreads()\n                .filter((t) => t.getFirstBlock().isDeletable())\n                .forEach((t) => {\n                    t.destroy();\n                });\n        },\n        state() {\n            const threads = this.editor.board.code\n                .getThreads()\n                .filter((t) => t.getFirstBlock().isDeletable())\n                .map((t) => t.toJSON());\n\n            return [threads];\n        },\n        log() {\n            return [];\n        },\n        undo: 'addThreads',\n    };\n\n    c[COMMAND_TYPES.addThreads] = {\n        do(threads) {\n            const code = this.editor.board.code;\n            threads.forEach((t) => {\n                code.createThread(t);\n            });\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        undo: 'destroyThreads',\n    };\n\n    c[COMMAND_TYPES.destroyBlockBelow] = {\n        do(block) {\n            block = this.editor.board.findBlock(block);\n            block.doDestroyBelow(true);\n            if (block.isParamBlockType()) {\n                block.thread?.updateValueBlock?.();\n            }\n        },\n        state(block) {\n            block = this.editor.board.findBlock(block);\n            const thread = block.thread;\n            let data;\n            if (thread instanceof Entry.Thread) {\n                data = thread.toJSON(false, block);\n            } else {\n                data = [block.toJSON()];\n            }\n\n            return [data, block.targetPointer()];\n        },\n        log(block) {\n            return [];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'recoverBlockBelow',\n    };\n\n    c[COMMAND_TYPES.recoverBlockBelow] = {\n        do(thread, targetPointer) {\n            const board = this.editor.board;\n            var thread = board.code.createThread(thread);\n            board.insert(thread.getFirstBlock(), targetPointer);\n        },\n        state(thread, targetPointer) {\n            return [thread[0]];\n        },\n        log(thread, targetPointer) {\n            return [];\n        },\n        undo: 'destroyBlockBelow',\n    };\n\n    cloneCommand(COMMAND_TYPES.separateBlockByCommand, COMMAND_TYPES.separateBlock);\n\n    function cloneCommand(newType, oldType, props) {\n        c[newType] = _.clone(c[oldType]);\n        if (props && props instanceof Array) {\n            props.forEach((prop) => {\n                c[newType][prop[0]] = prop[1];\n            });\n        }\n        return c[newType];\n    }\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/comment.js",
    "content": "'use strict';\n\n(function(c) {\n    const COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.createComment] = {\n        do(data, board, block) {\n            const comment = new Entry.Comment(data, board, block);\n            if (block) {\n                block.connectComment(comment);\n            } else {\n                board.code.createThread([comment], 0);\n            }\n            board.set({ isVisibleComment: true });\n        },\n        state(data) {\n            return [data];\n        },\n        log() {\n            return [];\n        },\n        undo: 'removeComment',\n    };\n\n    c[COMMAND_TYPES.removeComment] = {\n        do(target) {\n            const comment = this.editor.board.findBlock(target);\n            comment.destroy();\n        },\n        state(target) {\n            const comment = this.editor.board.findBlock(target);\n            return [comment.toJSON(), comment.board, comment.block];\n        },\n        log() {\n            return [];\n        },\n        undo: 'createComment',\n    };\n\n    c[COMMAND_TYPES.showAllComment] = {\n        do(board) {\n            board.set({ isVisibleComment: true });\n        },\n        state(board) {\n            return [board];\n        },\n        log() {\n            return [];\n        },\n        undo: 'hideAllComment',\n    };\n\n    c[COMMAND_TYPES.hideAllComment] = {\n        do(board) {\n            board.set({ isVisibleComment: false });\n        },\n        state(board) {\n            return [board];\n        },\n        log() {\n            return [];\n        },\n        undo: 'showAllComment',\n    };\n\n    c[COMMAND_TYPES.moveComment] = {\n        do(target, x, y) {\n            const comment = this.editor.board.findBlock(target);\n            if (x) {\n                comment.moveTo(x, y);\n            } else {\n                comment.updatePos();\n            }\n        },\n        state(target) {\n            const comment = this.editor.board.findBlock(target);\n            return [comment, comment.x, comment.y];\n        },\n        log() {\n            return [];\n        },\n        undo: 'moveComment',\n    };\n\n    c[COMMAND_TYPES.toggleComment] = {\n        do(comment) {\n            comment.set({\n                isOpened: !comment.isOpened,\n            });\n        },\n        state(comment) {\n            return [comment];\n        },\n        log() {\n            return [];\n        },\n        undo: 'toggleComment',\n    };\n\n    c[COMMAND_TYPES.cloneComment] = {\n        do(data, board) {\n            const comment = new Entry.Comment(data, board);\n            board.code.createThread([comment], 0);\n            board.set({ isVisibleComment: true });\n        },\n        state(comment) {\n            return [comment];\n        },\n        log() {\n            return [];\n        },\n        undo: 'uncloneComment',\n    };\n\n    c[COMMAND_TYPES.uncloneComment] = {\n        do(target) {\n            const comment = this.editor.board.findBlock(target);\n            comment.destroy();\n        },\n        state(target) {\n            const comment = this.editor.board.findBlock(target);\n            return [target, comment.board];\n        },\n        log() {\n            return [];\n        },\n        undo: 'cloneComment',\n    };\n\n    c[COMMAND_TYPES.separateComment] = {\n        do(target) {\n            const comment = this.editor.board.findBlock(target);\n            comment.separateFromBlock();\n        },\n        state(target) {\n            const comment = this.editor.board.findBlock(target);\n            return [comment.toJSON(), comment.block];\n        },\n        log() {\n            return [];\n        },\n        undo: 'connectComment',\n    };\n\n    c[COMMAND_TYPES.connectComment] = {\n        do(target, block) {\n            const comment = this.editor.board.findBlock(target);\n            comment.connectToBlock(block);\n        },\n        state(target) {\n            const comment = this.editor.board.findBlock(target);\n            return [comment.toJSON()];\n        },\n        log() {\n            return [];\n        },\n        undo: 'separateComment',\n    };\n\n    c[COMMAND_TYPES.writeComment] = {\n        do(target, value) {\n            const comment = this.editor.board.findBlock(target);\n            comment.writeComment(value);\n        },\n        state(target) {\n            const comment = this.editor.board.findBlock(target);\n            const json = comment.toJSON();\n            return [json, json.value];\n        },\n        log() {\n            return [];\n        },\n        undo: 'writeComment',\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/container.js",
    "content": "'use strict';\n\nconst { createTooltip, returnEmptyArr, getExpectedData } = require('../command_util');\n\n(function(c) {\n    const COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.containerSelectObject] = {\n        do(objectId) {\n            Entry.container.selectObject(objectId);\n        },\n        state(objectId) {\n            return [Entry.playground.object.id, objectId];\n        },\n        log(objectId) {\n            return [\n                ['objectId', objectId],\n                ['objectIndex', Entry.container.getObjectIndex(objectId)],\n            ];\n        },\n        restrict(data, domQuery, callback) {\n            Entry.container.scrollToObject(data.content[1][1]);\n\n            return new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    dimmed: true,\n                    restrict: true,\n                    callBack() {\n                        callback();\n                    },\n                }\n            );\n        },\n        undo: 'containerSelectObject',\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['container', 'objectIndex', '&1'],\n    };\n\n    c[COMMAND_TYPES.removeObject] = {\n        do(objectId) {\n            Entry.Utils.forceStopSounds();\n            const { name } = Entry.container.getObject(objectId);\n            Entry.container.removeObject(objectId);\n            Entry.Utils.doCodeChange();\n\n            Entry.toast.success(\n                Lang.Workspace.remove_object,\n                `${name} ${Lang.Workspace.remove_object_msg}`\n            );\n        },\n        state(objectId) {\n            const object = Entry.container.getObject(objectId);\n            return [object.toJSON(), object.getIndex()];\n        },\n        log(objectId) {\n            return [['objectId', objectId]];\n        },\n        undo: 'addObject',\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['container', 'objectId', '&0', 'removeButton'],\n    };\n\n    c[COMMAND_TYPES.addObject] = {\n        do(objectModel, index) {\n            objectModel.id = getExpectedData('objectModel', {}).id || objectModel.id;\n            Entry.container.addObjectFunc(objectModel, index);\n            Entry.dispatchEvent('dismissModal');\n            Entry.Utils.doCodeChange();\n        },\n        state(objectModel, index) {\n            objectModel.id = getExpectedData('objectModel', {}).id || objectModel.id;\n            return [objectModel.id, index];\n        },\n        log(objectModel, index) {\n            const { sprite, options = {} } = objectModel;\n            const { font } = options;\n\n            //$$hashKey can't saved for db\n            const _omitFunc = _.partial(_.omit, _, '$$hashKey');\n\n            objectModel.sprite = _omitFunc(sprite);\n            if (_.isObject(font)) {\n                objectModel.options.font = _omitFunc(font);\n            }\n            return [\n                ['objectModel', objectModel],\n                ['objectIndex', index],\n                ['spriteId', sprite._id],\n            ];\n        },\n        dom: ['.btn_confirm_modal'],\n        restrict(data, domQuery, callback) {\n            Entry.dispatchEvent('dismissModal');\n            const {\n                tooltip: { title, content },\n            } = data;\n\n            const tooltip = createTooltip(title, content, '.btn_confirm_modal', callback, {\n                render: false,\n            });\n\n            const event = Entry.getMainWS().widgetUpdateEvent;\n\n            if (!data.skip) {\n                Entry.dispatchEvent(\n                    'openSpriteManager',\n                    getExpectedData('spriteId'),\n                    event.notify.bind(event)\n                );\n            }\n            return tooltip;\n        },\n        undo: 'removeObject',\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n    };\n\n    c[COMMAND_TYPES.addObjectButtonClick] = {\n        do() {\n            Entry.dispatchEvent('dismissModal');\n            Entry.dispatchEvent('openSpriteManager');\n        },\n        state: returnEmptyArr,\n        log: returnEmptyArr,\n        undo: 'dismissModal',\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        validate: false,\n        dom: ['engine', 'objectAddButton'],\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/dataTable.js",
    "content": "/*\n *\n */\n'use strict';\nimport DataTable from '../../class/DataTable';\n\n(function(c) {\n    const { COMMAND_TYPES, RECORDABLE } = Entry.STATIC;\n\n    c[COMMAND_TYPES.dataTableAddSource] = {\n        do(table) {\n            Entry.playground.selectTable(table);\n        },\n        state(table) {\n            return [table];\n        },\n        log(table) {\n            return [['table', table]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'dataTableRemoveSource',\n        dom: ['playground', 'tableAddButton'],\n    };\n\n    c[COMMAND_TYPES.dataTableRemoveSource] = {\n        do(table = {}) {\n            const index = DataTable.getIndex(table);\n            if (index < 0) {\n                console.warn('not found table', table);\n                return;\n            }\n            DataTable.tables.splice(index, 1);\n            const isWorkspace = Entry.type === 'workspace';\n            if (isWorkspace) {\n                Entry.playground.reloadPlayground();\n                Entry.playground.refreshPlayground();\n                !DataTable.tables.length && DataTable.banAllBlock();\n            }\n        },\n        state(table) {\n            return [table];\n        },\n        log(table) {\n            return [['table', table]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'dataTableAddSource',\n        dom: ['playground', 'tableAddButton'],\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/engine.js",
    "content": "/*\n *\n */\n'use strict';\n\n(function(c) {\n    var COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.toggleRun] = {\n        do: function(callerName) {\n            Entry.engine.toggleRun();\n        },\n        state: function() {\n            return [];\n        },\n        log: function(callerName) {\n            return [['callerName', callerName]];\n        },\n        restrict: function(data, domQuery, callback, restrictor) {\n            var engine = Entry.engine;\n            if (!engine.isState('stop')) engine.toggleStop();\n\n            var isDone = false;\n            return new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    dimmed: true,\n                    restrict: true,\n                    callBack: function(isFromInit) {},\n                }\n            );\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'toggleStop',\n        dom: ['engine', '&0'],\n    };\n\n    c[COMMAND_TYPES.toggleStop] = {\n        do: function(callerName) {\n            Entry.engine.toggleStop();\n        },\n        state: function() {\n            return [];\n        },\n        log: function(callerName) {\n            return [['callerName', callerName]];\n        },\n        restrict: function(data, domQuery, callback, restrictor) {\n            var engine = Entry.engine;\n            if (Entry.engine.popup) Entry.engine.closeFullScreen();\n            if (!engine.isState('run')) engine.toggleRun(false);\n\n            return new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    dimmed: true,\n                    restrict: true,\n                    callBack: function(isFromInit) {\n                        callback();\n                    },\n                }\n            );\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'toggleRun',\n        dom: ['engine', '&0'],\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/function.js",
    "content": "/*\n *\n */\n'use strict';\n\nconst { createTooltip, returnEmptyArr, getExpectedData } = require('../command_util');\n\n(function(c) {\n    const COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.funcCreateStart] = {\n        do(funcId) {\n            Entry.getMainWS().setMode(Entry.Workspace.MODE_BOARD, 'cancelEdit');\n            funcId = getExpectedData('funcId') || funcId;\n            Entry.playground.changeViewMode('code');\n            const blockMenu = Entry.variableContainer._getBlockMenu();\n            if (blockMenu.lastSelector !== 'func') {\n                blockMenu.selectMenu('func');\n            }\n            Entry.variableContainer.createFunction({ id: funcId });\n        },\n        state(funcId) {\n            return [getExpectedData('funcId', funcId), 'remove'];\n        },\n        log(funcId) {\n            return [['funcId', getExpectedData('funcId') || funcId]];\n        },\n        restrict(data, domQuery, callback) {\n            Entry.playground.changeViewMode('variable');\n            Entry.variableContainer.selectFilter('func');\n\n            const {\n                tooltip: { title, content },\n            } = data;\n            return createTooltip(title, content, domQuery, callback);\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['variableContainer', 'functionAddButton'],\n        undo: 'funcEditCancel',\n    };\n\n    c[COMMAND_TYPES.funcEditStart] = {\n        do(id, json, type) {\n            const func = Entry.variableContainer.getFunction(id);\n            if (func) {\n                Entry.Func.edit(id);\n            } else {\n                Entry.variableContainer.createFunction({ id, type });\n            }\n            if (json) {\n                Entry.Func.targetFunc.content.load(json);\n            }\n        },\n        state(id, json, type = 'cancel', isExist) {\n            if (type === 'save' && id && !isExist) {\n                Entry.variableContainer.removeFunction({ id });\n            }\n            return [type];\n        },\n        log(funcId) {\n            return [['funcId', funcId]];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['variableContainer', 'functionAddButton'],\n        undo: 'funcEditEnd',\n    };\n\n    c[COMMAND_TYPES.funcEditEnd] = {\n        do(type) {\n            Entry.Func.isEdit = false;\n            if (type === 'save') {\n                Entry.getMainWS().setMode(Entry.Workspace.MODE_BOARD, 'save');\n            } else {\n                Entry.getMainWS().setMode(Entry.Workspace.MODE_BOARD, 'cancelEdit');\n            }\n        },\n        state(type) {\n            const json = Entry.Func.targetFunc.content.toJSON();\n            const func = Entry.variableContainer.getFunction(Entry.Func.targetFunc.id);\n            return [Entry.Func.targetFunc.id, json, type, !!func];\n        },\n        log(type) {\n            return [['funcId', Entry.Func.targetFunc.id]];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['variableContainer', 'functionAddButton'],\n        undo: 'funcEditStart',\n    };\n\n    c[COMMAND_TYPES.funcRemove] = {\n        do({ id }) {\n            Entry.variableContainer.removeFunction({ id });\n        },\n        state({ id }) {\n            const func = Entry.variableContainer.getFunction(id);\n            return [func];\n        },\n        log(func) {\n            return [['funcId', func.id]];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['variableContainer', 'functionAddButton'],\n        undo: 'funcCreate',\n    };\n\n    c[COMMAND_TYPES.funcCreate] = {\n        do(func) {\n            Entry.variableContainer.saveFunction(func);\n            Entry.Func.registerFunction(func);\n            Entry.Func.updateMenu();\n        },\n        state({ id }) {\n            return [{ id }];\n        },\n        log(func) {\n            return [['funcId', func.id]];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['variableContainer', 'functionAddButton'],\n        undo: 'funcRemove',\n    };\n\n    c[COMMAND_TYPES.funcChangeType] = {\n        do(func) {\n            let type = 'value';\n            if (func.type === 'value') {\n                type = 'normal';\n            }\n            Entry.Func.changeType(func, type);\n        },\n        state(func) {\n            return [func];\n        },\n        log(func) {\n            return [['funcId', func.id]];\n        },\n        validate: false,\n        dom: ['variableContainer', 'functionAddButton'],\n        undo: 'funcChangeType',\n    };\n\n    c[COMMAND_TYPES.funcLocalVarChangeLength] = {\n        do(func, value) {\n            if (value === 'minus') {\n                func.removeLastLocalVariable();\n            } else if (value === 'plus') {\n                const value = func.defaultLocalVariable();\n                func.appendLocalVariable(value);\n            } else {\n                let length = func.localVariables?.length || 0;\n                if (Entry.Utils.isNumber(value) && value >= 0) {\n                    length = value;\n                }\n                func.setLocalVariableLength(length);\n            }\n        },\n        state(func, value) {\n            let prevValue;\n            if (value === 'minus') {\n                prevValue = 'plus';\n            } else if (value === 'plus') {\n                prevValue = 'minus';\n            } else {\n                prevValue = func.localVariables?.length || 0;\n            }\n            return [func, prevValue];\n        },\n        log(func, value) {\n            return [\n                ['funcId', func.id],\n                ['value', value],\n            ];\n        },\n        validate: false,\n        dom: ['variableContainer', 'funcLocalVarChangeLength', '&2'],\n        undo: 'funcLocalVarChangeLength',\n    };\n    c[COMMAND_TYPES.toggleFuncUseLocalVariables] = {\n        do(func) {\n            func.toggleFunctionUseLocalVariables();\n        },\n        state(func) {\n            return [func];\n        },\n        log(func, value) {\n            return [\n                ['funcId', func.id],\n                ['value', value],\n            ];\n        },\n        validate: false,\n        dom: ['variableContainer', 'toggleFuncUseLocalVariables', '&2'],\n        undo: 'toggleFuncUseLocalVariables',\n    };\n    c[COMMAND_TYPES.insertFuncLocalVariable] = {\n        do(func, value, index) {\n            func.insertFuncLocalVariable(value, index);\n        },\n        state(func, _value, index) {\n            return [func, index];\n        },\n        log(func, value, index) {\n            return [\n                ['funcId', func.id],\n                ['value', value],\n                ['index', index],\n            ];\n        },\n        validate: false,\n        dom: ['variableContainer', 'insertFuncLocalVariable', '&2'],\n        undo: 'removeFuncLocalVariableByIndex',\n    };\n    c[COMMAND_TYPES.removeFuncLocalVariableByIndex] = {\n        do(func, index) {\n            func.removeLocalVariable(index);\n        },\n        state(func, index) {\n            const value = func.localVariables[index];\n            return [func, value, index];\n        },\n        log(func, index) {\n            return [\n                ['funcId', func.id],\n                ['index', index],\n            ];\n        },\n        validate: false,\n        dom: ['variableContainer', 'removeFuncLocalVariableByIndex', '&2'],\n        undo: 'insertFuncLocalVariable',\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/object.js",
    "content": "/*\n *\n */\n'use strict';\n\nconst { returnEmptyArr, createTooltip } = require('../command_util');\nimport VideoUtils from '@entrylabs/legacy-video';\nimport WebUsbFlasher from '../../class/hardware/webUsbFlasher';\n\n(function (c) {\n    const COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.selectObject] = {\n        do(objectId) {\n            return Entry.container.selectObject(objectId);\n        },\n        state(objectId) {\n            const playground = Entry.playground;\n            if (playground && playground.object) {\n                return [playground.object.id];\n            }\n        },\n        log(objectId) {\n            return [objectId];\n        },\n        undo: 'selectObject',\n    };\n\n    c[COMMAND_TYPES.objectEditButtonClick] = {\n        do(objectId) {\n            Entry.container.getObject(objectId).toggleEditObject();\n        },\n        state(objectId) {\n            return [];\n        },\n        log(objectId) {\n            return [\n                ['objectId', objectId],\n                ['objectIndex', Entry.container.getObjectIndex(objectId)],\n            ];\n        },\n        skipUndoStack: true,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['container', 'objectIndex', '&1', 'editButton'],\n        undo: 'selectObject',\n    };\n\n    c[COMMAND_TYPES.objectAddPicture] = {\n        do(objectId, picture, isSelect = true) {\n            const hashId = c[COMMAND_TYPES.objectAddPicture].hashId;\n            if (hashId) {\n                picture.id = hashId;\n                delete c[COMMAND_TYPES.objectAddPicture].hashId;\n            }\n            Entry.container.getObject(objectId).addPicture(picture);\n            Entry.playground.injectPicture(isSelect);\n            isSelect && Entry.playground.selectPicture(picture);\n            Entry.dispatchEvent('dismissModal');\n        },\n        state(objectId, picture) {\n            return [objectId, picture];\n        },\n        log(objectId, picture) {\n            const o = {};\n            o._id = picture._id;\n            o.id = picture.id;\n            o.dimension = picture.dimension;\n            o.filename = picture.filename;\n            o.fileurl = picture.fileurl;\n            o.thumbUrl = picture.thumbUrl;\n            o.name = picture.name;\n            o.scale = picture.scale;\n            return [\n                ['objectId', objectId],\n                ['picture', o],\n            ];\n        },\n        dom: ['.btn_confirm_modal'],\n        restrict(data, domQuery, callback) {\n            this.hashId = data.content[2][1].id;\n\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: '.btn_confirm_modal',\n                    },\n                ],\n                {\n                    restrict: true,\n                    dimmed: true,\n                    render: false,\n                    callBack: callback,\n                }\n            );\n\n            const event = Entry.getMainWS().widgetUpdateEvent;\n\n            if (!data.skip) {\n                Entry.dispatchEvent(\n                    'openPictureManager',\n                    data.content[2][1]._id,\n                    event.notify.bind(event)\n                );\n            }\n\n            return tooltip;\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'objectRemovePicture',\n    };\n\n    c[COMMAND_TYPES.objectRemovePicture] = {\n        do(objectId, picture) {\n            Entry.container.getObject(objectId).removePicture(picture.id);\n        },\n        state(objectId, picture) {\n            return [objectId, picture];\n        },\n        log(objectId, picture) {\n            return [\n                ['objectId', objectId],\n                ['pictureId', picture._id],\n            ];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'objectAddPicture',\n    };\n\n    c[COMMAND_TYPES.objectAddSound] = {\n        do(objectId, sound, isSelect = true) {\n            const hashId = c[COMMAND_TYPES.objectAddSound].hashId;\n            if (hashId) {\n                sound.id = hashId;\n                delete c[COMMAND_TYPES.objectAddSound].hashId;\n            }\n            const object = Entry.container.getObject(objectId);\n            if (!object.selectedSound) {\n                object.selectedSound = sound;\n            }\n            object.addSound(sound);\n            Entry.playground.injectSound(isSelect);\n            isSelect && Entry.playground.selectSound(sound);\n            Entry.dispatchEvent('dismissModal');\n        },\n        state(objectId, sound) {\n            return [objectId, sound];\n        },\n        log(objectId, sound) {\n            const o = {};\n            o._id = sound._id;\n            o.duration = sound.duration;\n            o.ext = sound.ext;\n            o.id = sound.id;\n            o.filename = sound.filename;\n            o.fileurl = sound.fileurl;\n            o.name = sound.name;\n            return [\n                ['objectId', objectId],\n                ['sound', o],\n            ];\n        },\n        dom: ['.btn_confirm_modal'],\n        restrict(data, domQuery, callback) {\n            this.hashId = data.content[2][1].id;\n\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: '.btn_confirm_modal',\n                    },\n                ],\n                {\n                    callBack: callback,\n                    dimmed: true,\n                    restrict: true,\n                    render: false,\n                }\n            );\n\n            const event = Entry.getMainWS().widgetUpdateEvent;\n\n            if (!data.skip) {\n                Entry.dispatchEvent(\n                    'openSoundManager',\n                    data.content[2][1]._id,\n                    event.notify.bind(event)\n                );\n            }\n            return tooltip;\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'objectRemoveSound',\n    };\n\n    c[COMMAND_TYPES.objectRemoveSound] = {\n        do(objectId, sound) {\n            return Entry.container.getObject(objectId).removeSound(sound.id);\n        },\n        state(objectId, sound) {\n            return [objectId, sound];\n        },\n        log(objectId, sound) {\n            return [\n                ['objectId', objectId],\n                ['soundId', sound._id],\n            ];\n        },\n        dom: ['.btn_confirm_modal'],\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'objectAddSound',\n    };\n\n    c[COMMAND_TYPES.objectAddExpansionBlocks] = {\n        do(blockNames) {\n            blockNames.forEach((blockName) => {\n                if (\n                    typeof Entry.EXPANSION_BLOCK !== 'undefined' &&\n                    typeof Entry.EXPANSION_BLOCK[blockName] !== 'undefined'\n                ) {\n                    Entry.EXPANSION_BLOCK[blockName].init();\n                    if (typeof Entry.expansionBlocks == 'undefined') {\n                        Entry.expansionBlocks = [];\n                    }\n                    Entry.expansionBlocks = _.union(Entry.expansionBlocks, [blockName]);\n                }\n                Entry.playground.blockMenu.unbanClass(blockName);\n            });\n            // Entry.dispatchEvent('dismissModal');\n        },\n        state(blockNames) {\n            return [blockNames];\n        },\n        log(blockNames) {\n            return [['blockName', blockNames]];\n        },\n        dom: ['.btn_confirm_modal'],\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        validate: false,\n        undo: 'objectRemoveExpansionBlocks',\n    };\n\n    c[COMMAND_TYPES.objectRemoveExpansionBlocks] = {\n        do(blockNames) {\n            // 사용된 블록 전체에서 검색가능해질때 사용가능.\n            blockNames.forEach((blockName) => {\n                Entry.playground.blockMenu.banClass(blockName);\n            });\n            Entry.expansionBlocks = _.pullAll(Entry.expansionBlocks, blockNames);\n        },\n        state(blockNames) {\n            return [blockNames];\n        },\n        log(blockNames) {\n            return [['blockName', blockNames]];\n        },\n        dom: ['.btn_confirm_modal'],\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        validate: false,\n        undo: 'objectAddExpansionBlocks',\n    };\n    c[COMMAND_TYPES.objectAddAIUtilizeBlocks] = {\n        do(blockNames) {\n            blockNames.forEach((blockName) => {\n                if (\n                    typeof Entry.AI_UTILIZE_BLOCK !== 'undefined' &&\n                    typeof Entry.AI_UTILIZE_BLOCK[blockName] !== 'undefined'\n                ) {\n                    Entry.AI_UTILIZE_BLOCK[blockName].init();\n                    if (typeof Entry.aiUtilizeBlocks == 'undefined') {\n                        Entry.aiUtilizeBlocks = [];\n                    }\n                    Entry.aiUtilizeBlocks = _.union(Entry.aiUtilizeBlocks, [blockName]);\n                }\n                Entry.playground.blockMenu.unbanClass(blockName);\n            });\n            // Entry.dispatchEvent('dismissModal');\n        },\n        state(blockName) {\n            return [blockName];\n        },\n        log(blockName) {\n            return [['blockName', blockName]];\n        },\n        dom: ['.btn_confirm_modal'],\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        validate: false,\n        undo: 'objectRemoveAIUtilizeBlocks',\n    };\n\n    c[COMMAND_TYPES.objectRemoveAIUtilizeBlocks] = {\n        do(blockNames) {\n            // 사용된 블록 전체에서 검색가능해질때 사용가능.\n            // Entry.expansionBlocks = _.pull(Entry.expansionBlocks, blockName);\n            // 사용된 블록 전체에서 검색가능해질때 사용가능.\n            blockNames.forEach((blockName) => {\n                if (blockName === 'video') {\n                    VideoUtils.destroy();\n                }\n                Entry.playground.blockMenu.banClass(blockName);\n            });\n            Entry.aiUtilizeBlocks = _.pullAll(Entry.aiUtilizeBlocks, blockNames);\n        },\n        state(blockName) {\n            return [blockName];\n        },\n        log(blockName) {\n            return [['blockName', blockName]];\n        },\n        dom: ['.btn_confirm_modal'],\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        validate: false,\n        undo: 'objectAddAIUtilizeBlocks',\n    };\n\n    c[COMMAND_TYPES.objectAddHardwareLiteBlocks] = {\n        do(module) {\n            Entry.hwLite.getConnectFailedMenu();\n            if (typeof Entry.hardwareLiteBlocks == 'undefined') {\n                Entry.hardwareLiteBlocks = [];\n            }\n            Entry.hardwareLiteBlocks = _.union(Entry.hardwareLiteBlocks, [module.id]);\n            Entry.hwLite.setExternalModule(module);\n        },\n        state(module) {\n            return [module];\n        },\n        log(module) {\n            return [['module', module]];\n        },\n        dom: ['.btn_confirm_modal'],\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        validate: false,\n        undo: 'objectRemoveHardwareLiteBlocks',\n    };\n\n    c[COMMAND_TYPES.objectRemoveHardwareLiteBlocks] = {\n        do(module) {\n            Entry.hardwareLiteBlocks = [];\n            Entry.hwLite.disconnect();\n            Entry.hwLite.removeWebConnector();\n            Entry.hwLite.removeFlasher();\n        },\n        state(module) {\n            return [module];\n        },\n        log(module) {\n            return [['module', module]];\n        },\n        dom: ['.btn_confirm_modal'],\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        validate: false,\n        undo: 'objectAddHardwareLiteBlocks',\n    };\n\n    c[COMMAND_TYPES.objectNameEdit] = {\n        do(objectId, newName) {\n            const object = Entry.container.getObject(objectId);\n            object.setName(newName);\n            object.setInputBlurred('nameInput');\n            Entry.playground.updateObjectTitle(object);\n            Entry.playground.reloadPlayground();\n        },\n        state(objectId, newName) {\n            const object = Entry.container.getObject(objectId);\n            return [objectId, object.getName()];\n        },\n        log(objectId, newName) {\n            const object = Entry.container.getObject(objectId);\n            return [\n                ['objectId', objectId],\n                ['newName', newName],\n            ];\n        },\n        dom: ['container', 'objectId', '&0', 'nameInput'],\n        restrict: _inputRestrictor,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'objectNameEdit',\n    };\n\n    c[COMMAND_TYPES.objectReorder] = {\n        do(newIndex, oldIndex) {\n            Entry.container.moveElement(newIndex, oldIndex);\n        },\n        state(newIndex, oldIndex) {\n            return [oldIndex, newIndex];\n        },\n        log(newIndex, oldIndex) {\n            return [\n                ['newIndex', newIndex],\n                ['oldIndex', oldIndex],\n            ];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'objectReorder',\n    };\n\n    c[COMMAND_TYPES.objectUpdatePosX] = {\n        do(objectId, newX = 0) {\n            const object = Entry.container.getObject(objectId);\n            object.entity.setX(Number(newX));\n            object.updateCoordinateView();\n            object.setInputBlurred('xInput');\n            Entry.stage.updateObject();\n        },\n        state(objectId, newX) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [objectId, entity.getX()];\n        },\n        log(objectId, newX) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [\n                ['objectId', objectId],\n                ['newX', newX],\n            ];\n        },\n        dom: ['container', 'objectId', '&0', 'xInput'],\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict: _inputRestrictor,\n        undo: 'objectUpdatePosX',\n    };\n\n    c[COMMAND_TYPES.objectUpdatePosY] = {\n        do(objectId, newY = 0) {\n            const object = Entry.container.getObject(objectId);\n            object.entity.setY(Number(newY));\n            object.updateCoordinateView();\n            object.setInputBlurred('yInput');\n            Entry.stage.updateObject();\n        },\n        state(objectId, newY) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [objectId, entity.getY()];\n        },\n        log(objectId, newY) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [\n                ['objectId', objectId],\n                ['newY', newY],\n            ];\n        },\n        dom: ['container', 'objectId', '&0', 'yInput'],\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict: _inputRestrictor,\n        undo: 'objectUpdatePosY',\n    };\n\n    c[COMMAND_TYPES.objectUpdateSize] = {\n        do(objectId, newSize = 0) {\n            const object = Entry.container.getObject(objectId);\n            object.entity.setSize(Number(newSize));\n            object.updateCoordinateView();\n            object.setInputBlurred('sizeInput');\n            Entry.stage.updateObject();\n        },\n        state(objectId, newSize) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [objectId, entity.getSize()];\n        },\n        log(objectId, newSize) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [\n                ['objectId', objectId],\n                ['newSize', newSize],\n            ];\n        },\n        dom: ['container', 'objectId', '&0', 'sizeInput'],\n        restrict: _inputRestrictor,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'objectUpdateSize',\n    };\n\n    c[COMMAND_TYPES.objectUpdateRotationValue] = {\n        do(objectId, newValue = 0) {\n            const object = Entry.container.getObject(objectId);\n            object.entity.setRotation(Number(newValue));\n            object.updateCoordinateView();\n            object.setInputBlurred('rotationInput');\n            Entry.stage.updateObject();\n        },\n        state(objectId, newValue) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [objectId, entity.getRotation()];\n        },\n        log(objectId, newValue) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [\n                ['objectId', objectId],\n                ['newRotationValue', newValue],\n            ];\n        },\n        dom: ['container', 'objectId', '&0', 'rotationInput'],\n        restrict: _inputRestrictor,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'objectUpdateRotationValue',\n    };\n\n    c[COMMAND_TYPES.objectUpdateDirectionValue] = {\n        do(objectId, newValue = 0) {\n            const object = Entry.container.getObject(objectId);\n            object.entity.setDirection(Number(newValue));\n            object.updateCoordinateView();\n            object.setInputBlurred('directionInput');\n            Entry.stage.updateObject();\n        },\n        state(objectId, newValue) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [objectId, entity.getDirection()];\n        },\n        log(objectId, newValue) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [\n                ['objectId', objectId],\n                ['newDirectionValue', newValue],\n            ];\n        },\n        dom: ['container', 'objectId', '&0', 'directionInput'],\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict: _inputRestrictor,\n        undo: 'objectUpdateDirectionValue',\n    };\n\n    c[COMMAND_TYPES.objectUpdateRotateMethod] = {\n        do(objectId, newMethod, rotation) {\n            const object = Entry.container.getObject(objectId);\n            object.initRotateValue(newMethod);\n            object.setRotateMethod(newMethod);\n            if (rotation !== undefined) {\n                object.entity.setRotation(rotation);\n            }\n            Entry.stage.updateObject();\n        },\n        state(objectId, newMethod) {\n            const { entity, rotateMethod } = Entry.container.getObject(objectId);\n            return [objectId, rotateMethod, entity.getRotation()];\n        },\n        log(objectId, newValue) {\n            const { entity } = Entry.container.getObject(objectId);\n            return [\n                ['objectId', objectId],\n                ['newDirectionValue', newValue],\n            ];\n        },\n        dom: ['container', 'objectId', '&0', 'rotationMethod', '&1'],\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'objectUpdateRotateMethod',\n    };\n\n    c[COMMAND_TYPES.entitySetModel] = {\n        do(objectId, newModel, oldModel) {\n            const { entity } = Entry.container.getObject(objectId);\n            entity.setModel(newModel);\n        },\n        state(objectId, newModel, oldModel) {\n            return [objectId, oldModel, newModel];\n        },\n        log(objectId, newModel, oldModel) {\n            return [\n                ['objectId', objectId],\n                ['newModel', newModel],\n                ['oldModel', oldModel],\n            ];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'entitySetModel',\n    };\n\n    function _inputRestrictor({ tooltip, content }, domQuery, callback) {\n        const { title: tooltipTitle, content: tooltipContent } = tooltip;\n        _activateEdit(content[1][1], domQuery, callback);\n        return createTooltip(tooltipTitle, tooltipContent, domQuery, callback);\n    }\n\n    function _activateEdit(objectId, domQuery, callback) {\n        const object = Entry.container.getObject(objectId);\n\n        if (!object.isEditing) {\n            object.editObjectValues(true);\n        }\n\n        if (!_.isEmpty(domQuery)) {\n            domQuery = Entry.getDom(domQuery);\n            if (domQuery && !Entry.Utils.isDomActive(domQuery)) {\n                domQuery.focus();\n                callback();\n            }\n        }\n    }\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/painter.js",
    "content": "/*\n *\n */\n'use strict';\n\n(function(c) {\n    const COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.editPicture] = {\n        do() {\n            Entry.playground.painter.redo();\n        },\n        state() {},\n        log(objectId) {\n            return [objectId];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        undo: 'uneditPicture',\n    };\n\n    c[COMMAND_TYPES.uneditPicture] = {\n        type: Entry.STATIC.COMMAND_TYPES.uneditPicture,\n        do() {\n            Entry.playground.painter.undo();\n        },\n        state() {},\n        log(objectId) {\n            return [objectId];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        undo: 'editPicture',\n    };\n\n    c[COMMAND_TYPES.processPicture] = {\n        do() {\n            Entry.playground.painter.redo();\n        },\n        state() {},\n        log(objectId) {\n            return [objectId];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        undo: 'unprocessPicture',\n        isPass: true,\n    };\n\n    c[COMMAND_TYPES.unprocessPicture] = {\n        do() {\n            Entry.playground.painter.undo();\n        },\n        state() {},\n        log(objectId) {\n            return [objectId];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SKIP,\n        undo: 'processPicture',\n        isPass: true,\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/playground.js",
    "content": "/*\n *\n */\n'use strict';\n\n(function(c) {\n    const COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.playgroundChangeViewMode] = {\n        do(newType, oldType) {\n            Entry.variableContainer.selected = null;\n            Entry.variableContainer.updateList();\n            Entry.playground.changeViewMode(newType);\n            if (Entry.disposeEvent) {\n                Entry.disposeEvent.notify();\n            }\n            Entry.Utils.forceStopSounds();\n        },\n        state(newType, oldType) {\n            return [oldType, newType];\n        },\n        log(newType, oldType) {\n            oldType = oldType || 'code';\n            return [\n                ['newType', newType],\n                ['oldType', oldType],\n            ];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'playgroundChangeViewMode',\n        dom: ['playground', 'tabViewElements', '&0'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddPicture] = {\n        do() {\n            Entry.dispatchEvent('openPictureManager');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        //skipUndoStack: true,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict(data, domQuery, callback, restrictor) {\n            Entry.dispatchEvent('dismissModal');\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    restrict: true,\n                    dimmed: true,\n                    callBack: callback,\n                }\n            );\n            return tooltip;\n        },\n        undo: 'playgroundClickAddPictureCancel',\n        dom: ['playground', 'pictureAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddPictureCancel] = {\n        do() {\n            Entry.dispatchEvent('dismissModal');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        //skipUndoStack: true,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: '',\n        dom: ['playground', 'pictureAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddSound] = {\n        do() {\n            Entry.dispatchEvent('openSoundManager');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict(data, domQuery, callback, restrictor) {\n            Entry.dispatchEvent('dismissModal');\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    restrict: true,\n                    dimmed: true,\n                    callBack: callback,\n                }\n            );\n            return tooltip;\n        },\n        undo: 'playgroundClickAddSoundCancel',\n        dom: ['playground', 'soundAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddSoundCancel] = {\n        do() {\n            Entry.dispatchEvent('dismissModal');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: '',\n        dom: ['playground', 'soundAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddTable] = {\n        do() {\n            Entry.dispatchEvent('openTableManager');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        undo: 'playgroundClickAddTableCancel',\n        dom: ['playground', 'tableAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddTableCancel] = {\n        do() {\n            Entry.dispatchEvent('dismissModal');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: '',\n        dom: ['playground', 'tableAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddExpansionBlock] = {\n        do() {\n            Entry.dispatchEvent('openExpansionBlockManager');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict(data, domQuery, callback, restrictor) {\n            Entry.dispatchEvent('dismissModal');\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    restrict: true,\n                    dimmed: true,\n                    callBack: callback,\n                }\n            );\n            return tooltip;\n        },\n        undo: 'playgroundClickAddExpansionBlockCancel',\n        dom: ['playground', 'soundAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddExpansionBlockCancel] = {\n        do() {\n            Entry.dispatchEvent('dismissModal');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: '',\n        dom: ['playground', 'soundAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddAIUtilizeBlock] = {\n        do: function() {\n            Entry.dispatchEvent('openAIUtilizeBlockManager');\n        },\n        state: function() {\n            return [];\n        },\n        log: function() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict: function(data, domQuery, callback, restrictor) {\n            Entry.dispatchEvent('dismissModal');\n            var tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    restrict: true,\n                    dimmed: true,\n                    callBack: callback,\n                }\n            );\n            return tooltip;\n        },\n        undo: 'playgroundClickAddAIUtilizeBlockCancel',\n        dom: ['playground', 'soundAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddAIUtilizeBlockCancel] = {\n        do: function() {\n            Entry.dispatchEvent('dismissModal');\n        },\n        state: function() {\n            return [];\n        },\n        log: function() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: '',\n        dom: ['playground', 'soundAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddHardwareLiteBlock] = {\n        do() {\n            Entry.dispatchEvent('openHardwareLiteBlockManager');\n        },\n        state() {\n            return [];\n        },\n        log() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        restrict(data, domQuery, callback, restrictor) {\n            Entry.dispatchEvent('dismissModal');\n            const tooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    restrict: true,\n                    dimmed: true,\n                    callBack: callback,\n                }\n            );\n            return tooltip;\n        },\n        undo: 'playgroundClickAddHardwareLiteBlockCancel',\n        dom: ['playground', 'soundAddButton'],\n    };\n\n    c[COMMAND_TYPES.playgroundClickAddHardwareLiteBlockCancel] = {\n        do: function() {\n            Entry.dispatchEvent('dismissModal');\n        },\n        state: function() {\n            return [];\n        },\n        log: function() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: '',\n        dom: ['playground', 'soundAddButton'],\n    };\n\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/scene.js",
    "content": "/*\n *\n */\n'use strict';\n\nconst { createTooltip } = require('../command_util');\n\n(function(c) {\n    const COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.sceneAdd] = {\n        /**\n         * @param {!object|string} sceneId can be sceneId or scene object\n         * @param {?number} sceneIndex\n         * @param {?Array} objects will be add to new scene, for undo function\n         */\n        do(sceneId, sceneIndex, objects) {\n            if (Entry.expectedAction) {\n                sceneId = Entry.expectedAction[1][1];\n            }\n            Entry.scene.addScene(sceneId, sceneIndex);\n            if (objects) {\n                Entry.container.setObjects(objects);\n            }\n        },\n        state(sceneId, sceneIndex) {\n            if (!sceneIndex) {\n                sceneIndex = Entry.scene.getScenes().length;\n            }\n            if (Entry.expectedAction) {\n                sceneId = Entry.expectedAction[1][1];\n            }\n            if (typeof sceneId !== 'string') {\n                sceneId = sceneId.id;\n            }\n            return [sceneId];\n        },\n        log(sceneId) {\n            if (Entry.expectedAction) {\n                sceneId = Entry.expectedAction[1][1];\n            }\n            return [['sceneId', sceneId]];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['scene', 'addButton'],\n        undo: 'sceneRemove',\n    };\n\n    c[COMMAND_TYPES.sceneRemove] = {\n        do(sceneId) {\n            Entry.scene.removeScene(sceneId);\n        },\n        state(sceneId) {\n            const scene = Entry.scene.getSceneById(sceneId);\n            const sceneJSON = {\n                id: scene.id,\n                name: scene.name,\n            };\n            const sceneIndex = Entry.scene.getScenes().indexOf(scene);\n            const objects = Entry.container.getSceneObjects(scene).map((o) => o.toJSON());\n            return [sceneJSON, sceneIndex, objects];\n        },\n        log(sceneId) {\n            return [['sceneId', sceneId]];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['scene', 'removeButton', '&0'],\n        undo: 'sceneAdd',\n    };\n\n    c[COMMAND_TYPES.sceneRename] = {\n        do(sceneId, newName) {\n            const scene = Entry.scene.getSceneById(sceneId);\n            scene.name = newName;\n            scene.view.nameField.value = newName;\n            setTimeout(() => {\n                Entry.scene.resize();\n            }, 0);\n        },\n        state(sceneId) {\n            const scene = Entry.scene.getSceneById(sceneId);\n            return [sceneId, scene.name];\n        },\n        log(sceneId, newName) {\n            return [['sceneId', sceneId], ['newName', newName]];\n        },\n        restrict(data, domQuery, callback) {\n            const {\n                content: contentData,\n                tooltip: { title, content },\n            } = data;\n\n            callback();\n            const scene = Entry.scene.getSceneById(contentData[1][1]);\n            scene.view.nameField.focus();\n            return createTooltip(title, content, domQuery, callback);\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['scene', 'nameField', '&0'],\n        undo: 'sceneRename',\n    };\n\n    c[COMMAND_TYPES.sceneSelect] = {\n        do(sceneId) {\n            const scene = Entry.scene.getSceneById(sceneId);\n            Entry.scene.selectScene(scene);\n        },\n        state(sceneId) {\n            return [Entry.scene.selectedScene.id];\n        },\n        log(sceneId) {\n            return [['sceneId', sceneId]];\n        },\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        dom: ['scene', 'view', '&0'],\n        undo: 'sceneSelect',\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/textbox.js",
    "content": "/*\n *\n */\n'use strict';\n\n(function(c) {\n    var COMMAND_TYPES = Entry.STATIC.COMMAND_TYPES;\n\n    c[COMMAND_TYPES.editText] = {\n        do: function(text, prevText) {\n            Entry.playground.object.setText(text);\n            Entry.playground.object.entity.setText(text);\n            Entry.dispatchEvent('textEdited');\n        },\n        state: function(text, prevText) {\n            return [prevText, text];\n        },\n        log: function() {\n            return [];\n        },\n        validate: false,\n        recordable: Entry.STATIC.RECORDABLE.SUPPORT,\n        undo: 'editText',\n    };\n})(Entry.Command);\n"
  },
  {
    "path": "src/command/commands/variableContainer.js",
    "content": "/*\n *\n */\n'use strict';\n\nconst { createTooltip, returnEmptyArr, getExpectedData } = require('../command_util');\n\n(function(c) {\n    const { COMMAND_TYPES, RECORDABLE } = Entry.STATIC;\n\n    const {\n        variableContainerSelectFilter,\n        variableContainerClickVariableAddButton,\n        variableContainerAddVariable,\n        variableAddSetName,\n        variableContainerRemoveVariable,\n        variableContainerAddMessage,\n        variableContainerRemoveMessage,\n        messageSetName,\n        variableAddSetScope,\n        variableAddSetCloud,\n        variableSetVisibility,\n        variableSetDefaultValue,\n        variableSetSlidable,\n        variableSetMinValue,\n        variableSetMaxValue,\n        variableContainerClickListAddButton,\n        variableContainerAddList,\n        variableContainerRemoveList,\n        listAddSetName,\n        listAddSetScope,\n        listAddSetCloud,\n        listSetVisibility,\n        listChangeLength,\n        listSetDefaultValue,\n        setMessageEditable,\n        setVariableEditable,\n        setListEditable,\n        variableSetName,\n        listSetName,\n        variableContainerClickMessageAddButton,\n    } = COMMAND_TYPES;\n\n    c[variableContainerSelectFilter] = {\n        do(newType) {\n            getVC().selectFilter(newType);\n        },\n        state(newType, oldType) {\n            return [oldType, newType];\n        },\n        log(newType, oldType = 'all') {\n            return [\n                ['newType', newType],\n                ['oldType', oldType],\n            ];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableContainerSelectFilter',\n        dom: ['variableContainer', 'filter', '&0'],\n    };\n\n    c[variableContainerClickVariableAddButton] = {\n        do() {\n            getVC().clickVariableAddButton();\n        },\n        state: returnEmptyArr,\n        log: returnEmptyArr,\n        recordable: RECORDABLE.SUPPORT,\n        get undo() {\n            try {\n                getVC()._getAddPanel().view.name.value = '';\n            } catch (e) {}\n            return 'variableContainerClickVariableAddButton';\n        },\n        dom: ['variableContainer', 'variableAddButton'],\n    };\n\n    c[variableContainerClickMessageAddButton] = {\n        do() {\n            getVC().clickMessageAddButton();\n        },\n        state: returnEmptyArr,\n        log: returnEmptyArr,\n        recordable: RECORDABLE.SUPPORT,\n        get undo() {\n            try {\n                getVC()._getAddPanel().view.name.value = '';\n            } catch (e) {}\n            return 'variableContainerClickMessageAddButton';\n        },\n        dom: ['variableContainer', 'variableAddButton'],\n    };\n\n    c[variableContainerAddVariable] = {\n        do(variable) {\n            const id = _.result(getExpectedData('variable'), 'id');\n            if (id) {\n                variable.id_ = id;\n            }\n\n            getVC().addVariable(variable);\n        },\n        state(variable) {\n            variable = _toJSON(variable);\n            variable.id = _.result(getExpectedData('variable'), 'id') || variable.id;\n\n            return [variable];\n        },\n        log(variable) {\n            return [['variable', _toJSON(variable)]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'variableContainerRemoveVariable',\n        restrict(data, domQuery, callback) {\n            getVC().clickVariableAddButton(true, true);\n            $('.entryVariableAddSpaceInputWorkspace').val(\n                _.result(getExpectedData('variable'), 'name') || ''\n            );\n\n            const { title, content } = data.tooltip;\n\n            callback();\n            return createTooltip(title, content, domQuery, callback);\n        },\n        dom: ['variableContainer', 'variableAddConfirmButton'],\n    };\n\n    c[variableAddSetName] = {\n        do(value) {\n            let { dom } = c[variableAddSetName];\n\n            dom = Entry.getDom(dom);\n            dom._focused = false;\n            dom.value = getExpectedData('value', value);\n        },\n        state() {\n            return [''];\n        },\n        log(value) {\n            return [['value', getExpectedData('value', value)]];\n        },\n        restrict(data, domQuery, callback) {\n            getVC().clickVariableAddButton(true);\n            const dom = Entry.getDom(this.dom);\n            Entry.Utils.focusIfNotActive(dom);\n            dom.enterKeyDisabled = true;\n            const { title, content } = data.tooltip;\n            return createTooltip(title, content, domQuery, callback, {\n                noDispose: true,\n            });\n        },\n        validate: false,\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableAddSetName',\n        dom: ['variableContainer', 'variableAddInput'],\n    };\n\n    c[variableContainerRemoveVariable] = {\n        do(variable) {\n            getVC().removeVariable(variable);\n        },\n        state(variable) {\n            return [_toJSON(variable)];\n        },\n        log(variable) {\n            return [['variable', _toJSON(variable)]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'variableContainerAddVariable',\n        dom: ['variableContainer', 'variableAddConfirmButton'],\n    };\n\n    c[variableContainerAddMessage] = {\n        do(message) {\n            message.id = _.result(getExpectedData('message'), 'id') || message.id;\n            getVC().addMessage(message);\n        },\n        state(message) {\n            message.id = _.result(getExpectedData('message'), 'id') || message.id;\n            return [message];\n        },\n        log({ name, id }) {\n            return [['message', { name, id }]];\n        },\n        validate: false,\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableContainerRemoveMessage',\n        dom: ['variableContainer', 'messageAddButton'],\n    };\n\n    c[variableContainerRemoveMessage] = {\n        do({ id }) {\n            const VC = getVC();\n            VC.removeMessage(VC.getMessage(id));\n        },\n        state({ id, name }) {\n            return [{ id, name }];\n        },\n        log({ id, name }) {\n            return [['message', { name, id }]];\n        },\n        validate: false,\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableContainerAddMessage',\n        dom: ['variableContainer', 'messageAddButton'],\n    };\n\n    c[messageSetName] = {\n        do(id, newName) {\n            const VC = getVC();\n            const message = VC.getMessage(id);\n            const nameField = message.listElement.nameField;\n\n            nameField._focused = false;\n            VC.changeMessageName(message, newName);\n        },\n        state(id) {\n            const { name } = getVC().getMessage(id);\n            return [id, name];\n        },\n        log(id, newName) {\n            return [\n                ['id', id],\n                ['newName', newName],\n            ];\n        },\n        restrict(data, domQuery, callback) {\n            const {\n                tooltip: { title, content },\n            } = data;\n\n            callback();\n            const VC = getVC();\n            const message = VC.getMessage(domQuery[2]);\n            delete message.listElement.nameField.isFirst;\n            VC.activateMessageEditView(message);\n            return createTooltip(title, content, domQuery, callback);\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'messageSetName',\n        dom: ['variableContainer', 'messageList', '&0'],\n    };\n\n    c[variableAddSetScope] = {\n        do(type = 'global', isCloud = false) {\n            const VC = getVC();\n            const info = VC.variableAddPanel.info;\n            if (type === 'global') {\n                info.object = null;\n                info.isCloud = isCloud;\n            } else if (type === 'local') {\n                const { object } = Entry.playground;\n                if (!object) {\n                    return;\n                }\n                info.object = object.id;\n                info.isCloud = false;\n            }\n            VC.updateVariableAddView('variable');\n        },\n        state() {\n            const {\n                variableAddPanel: { object, isCloud },\n            } = getVC();\n            return [object ? 'local' : 'global', isCloud];\n        },\n        log(type) {\n            return [['type', type]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableAddSetScope',\n        dom: ['variableContainer', 'variableScope', '&0'],\n    };\n\n    c[variableAddSetCloud] = {\n        do(type) {\n            const VC = getVC();\n            let isCloud;\n            let isRealTime;\n            if (type === 'cloud') {\n                isCloud = true;\n            } else if (type === 'real_time') {\n                isRealTime = true;\n            }\n            VC.variableAddPanel.info.isCloud = isCloud;\n            VC.variableAddPanel.info.isRealTime = isRealTime;\n            VC.updateVariableAddView('variable');\n        },\n        state() {\n            const {\n                variableAddPanel: {\n                    info: { isCloud, isRealTime },\n                },\n            } = getVC();\n            return [isCloud, isRealTime];\n        },\n        log(type) {\n            return [['type', type]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableAddSetCloud',\n        dom: ['variableContainer', 'variableCloud'],\n    };\n\n    c[variableSetVisibility] = {\n        do(id, value) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            variable.setVisible(value);\n            VC.updateVariableSettingView(variable);\n        },\n        state(id) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            return [id, variable.isVisible()];\n        },\n        log(id, value) {\n            return [\n                ['id', id],\n                ['value', value],\n            ];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableSetVisibility',\n        dom: ['variableContainer', 'variableSetVisibility'],\n    };\n\n    c[variableSetDefaultValue] = {\n        do(id, value) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            Entry.getDom(['variableContainer', 'variableSetDefaultValue'])._focused = false;\n            variable.setValue(value);\n            VC.updateVariableSettingView(variable);\n        },\n        state(id) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            return [id, variable.getValue()];\n        },\n        log(id, value) {\n            return [\n                ['id', id],\n                ['value', value],\n            ];\n        },\n        restrict({ tooltip }, domQuery, callback) {\n            const { title: tooltipTitle, content: tooltipContent } = tooltip;\n            return createTooltip(tooltipTitle, tooltipContent, domQuery, callback, {\n                noDispose: true,\n            });\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableSetDefaultValue',\n        dom: ['variableContainer', 'variableSetDefaultValue'],\n    };\n\n    c[variableSetSlidable] = {\n        do(id, type, cValue) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            VC.setVariableSlidable(variable, type, cValue);\n        },\n        state(id) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            return [id, variable.getType(), variable.getValue()];\n        },\n        log(id, value) {\n            return [\n                ['id', id],\n                ['value', value],\n            ];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableSetSlidable',\n        dom: ['variableContainer', 'slideCheck'],\n    };\n\n    c[variableSetMinValue] = {\n        do(id, value) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            variable.setMinValue(value);\n            VC.updateVariableSettingView(variable);\n        },\n        state(id) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            return [id, variable.getMinValue()];\n        },\n        log(id) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            return [\n                ['id', id],\n                ['value', variable.getMinValue()],\n            ];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableSetMinValue',\n        dom: ['variableContainer', 'variableMinValue'],\n    };\n\n    c[variableSetMaxValue] = {\n        do(id, value) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            variable.setMaxValue(value);\n            VC.updateVariableSettingView(variable);\n        },\n        state(id) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            return [id, variable.getMaxValue()];\n        },\n        log(id) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            return [\n                ['id', id],\n                ['value', variable.getMaxValue()],\n            ];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableSetMaxValue',\n        dom: ['variableContainer', 'variableMaxValue'],\n    };\n\n    c[variableContainerClickListAddButton] = {\n        do() {\n            getVC().clickListAddButton();\n        },\n        state: returnEmptyArr,\n        log: returnEmptyArr,\n        recordable: RECORDABLE.SUPPORT,\n        get undo() {\n            try {\n                getVC()._getAddPanel('list').view.name.value = '';\n            } catch (e) {}\n            return 'variableContainerClickListAddButton';\n        },\n        dom: ['variableContainer', 'listAddButton'],\n    };\n\n    c[variableContainerAddList] = {\n        do(list) {\n            const id = _.result(getExpectedData('list'), 'id');\n            if (id) {\n                if (list.setId) {\n                    list.setId(id);\n                } else {\n                    list.id = id;\n                }\n            }\n            getVC().addList(list);\n        },\n        state(list) {\n            list = _toJSON(list);\n            list.id = _.result(getExpectedData('list'), 'id') || list.id;\n            return [list];\n        },\n        log(list) {\n            list = _toJSON(list);\n            list.id = _.result(getExpectedData('list'), 'id') || list.id;\n            return [['list', list]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'variableContainerRemoveList',\n        restrict(data, domQuery, callback) {\n            getVC().clickListAddButton(true, true);\n            Entry.getDom(['variableContainer', 'listAddInput']).value =\n                _.result(getExpectedData('list'), 'name') || '';\n\n            const { title, content } = data.tooltip;\n            callback();\n            return createTooltip(title, content, domQuery, callback);\n        },\n        dom: ['variableContainer', 'listAddConfirmButton'],\n    };\n\n    c[variableContainerRemoveList] = {\n        do(list) {\n            getVC().removeList(list);\n        },\n        state(list) {\n            return [_toJSON(list)];\n        },\n        log(list) {\n            return [['list', _toJSON(list)]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        validate: false,\n        undo: 'variableContainerAddList',\n        dom: ['variableContainer', 'listAddConfirmButton'],\n    };\n\n    c[listAddSetName] = {\n        do(value) {\n            let { dom } = c[listAddSetName];\n\n            dom = Entry.getDom(dom);\n            dom._focused = false;\n            dom.value = getExpectedData('value', value);\n        },\n        state() {\n            return [''];\n        },\n        log(value) {\n            return [['value', getExpectedData('value', value)]];\n        },\n        restrict(data, domQuery, callback) {\n            getVC().clickListAddButton(true);\n            const dom = Entry.getDom(this.dom);\n            Entry.Utils.focusIfNotActive(dom);\n            dom.enterKeyDisabled = true;\n            const { title, content } = data.tooltip;\n            return createTooltip(title, content, domQuery, callback, {\n                noDispose: true,\n            });\n        },\n        validate: false,\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'listAddSetName',\n        dom: ['variableContainer', 'listAddInput'],\n    };\n\n    c[listAddSetScope] = {\n        do(type = 'global', isCloud = false) {\n            const VC = getVC();\n            const info = VC.listAddPanel.info;\n            if (type === 'global') {\n                info.object = null;\n                info.isCloud = isCloud;\n            } else if (type === 'local') {\n                const { object } = Entry.playground;\n                if (!object) {\n                    return;\n                }\n                info.object = object.id;\n                info.isCloud = false;\n            }\n            VC.updateVariableAddView('list');\n        },\n        state() {\n            const {\n                listAddPanel: { object, isCloud },\n            } = getVC();\n            return [object ? 'local' : 'global', isCloud];\n        },\n        log(type) {\n            return [['type', type]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'listAddSetScope',\n        dom: ['variableContainer', 'listScope', '&0'],\n    };\n\n    c[listAddSetCloud] = {\n        do(type) {\n            const VC = getVC();\n            let isCloud;\n            let isRealTime;\n            if (type === 'cloud') {\n                isCloud = true;\n            } else if (type === 'real_time') {\n                isRealTime = true;\n            }\n            VC.listAddPanel.info.isCloud = isCloud;\n            VC.listAddPanel.info.isRealTime = isRealTime;\n            VC.updateVariableAddView('list');\n        },\n        state() {\n            const {\n                listAddPanel: {\n                    info: { isCloud, isRealTime },\n                },\n            } = getVC();\n            return [isCloud, isRealTime];\n        },\n        log(type) {\n            return [['type', type]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'listAddSetCloud',\n        dom: ['variableContainer', 'listCloud'],\n    };\n\n    c[listSetVisibility] = {\n        do(id, value) {\n            const VC = getVC();\n            const list = VC.getList(id);\n            list.setVisible(value);\n            VC.updateListSettingView(list);\n        },\n        state(id) {\n            return [\n                id,\n                getVC()\n                    .getList(id)\n                    .isVisible(),\n            ];\n        },\n        log(id, value) {\n            return [\n                ['id', id],\n                ['value', value],\n            ];\n        },\n        restrict: _listActiveRestrictor,\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'listSetVisibility',\n        dom: ['variableContainer', 'listSetVisibility'],\n    };\n\n    c[listChangeLength] = {\n        async do(id, value) {\n            const VC = getVC();\n            const list = VC.getList(id);\n            const length = list.getArray().length;\n            let result;\n            if (value === 'minus') {\n                result = Math.max(0, length - 1);\n                await list.deleteValue(result);\n            } else if (value === 'plus') {\n                result = length + 1;\n                await list.appendValue(0);\n            } else if (Entry.Utils.isNumber(value) && value >= 0) {\n                result = value;\n            } else {\n                result = length;\n            }\n\n            VC.setListLength(list, result);\n        },\n        state(id) {\n            return [id, getVC().getList(id).array_.length];\n        },\n        log(id, value) {\n            return [\n                ['id', id],\n                ['value', value],\n                ['dom', Entry.Utils.isNumber(value) ? 'lengthInput' : value],\n            ];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'listChangeLength',\n        restrict({ tooltip, content }, domQuery, callback) {\n            _updateSelected(content);\n            const { title: tooltipTitle, content: tooltipContent } = tooltip;\n            return createTooltip(tooltipTitle, tooltipContent, domQuery, callback, {\n                noDispose: true,\n            });\n        },\n        dom: ['variableContainer', 'listChangeLength', '&2'],\n    };\n\n    c[listSetDefaultValue] = {\n        do(id, idx = 0, data = '0') {\n            const VC = getVC();\n            const list = VC.getList(id);\n            list.getArray()[idx] = { data };\n            VC.updateListSettingView();\n            //list.updateView();\n        },\n        state(id, idx) {\n            const { array_ } = getVC().getList(id);\n            return [id, idx, array_[idx].data];\n        },\n        log(id, idx, data) {\n            return [\n                ['id', id],\n                ['idx', idx],\n                ['data', data],\n            ];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'listSetDefaultValue',\n        restrict(data, domQuery, callback) {\n            _updateSelected(data.content);\n            Entry.Utils.focusIfNotActive(Entry.getDom(domQuery));\n            const { title, content } = data.tooltip;\n            return createTooltip(title, content, domQuery, callback, {\n                noDispose: true,\n            });\n        },\n        dom: ['variableContainer', 'listDefaultValue', '&1'],\n    };\n\n    c[setMessageEditable] = {\n        do(id) {\n            const VC = getVC();\n            const message = VC.getMessage(id);\n            VC.activateMessageEditView(message);\n            message.listElement.removeClass('activeForce');\n        },\n        state(id) {\n            return [id];\n        },\n        log(id) {\n            return [['id', id]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'setMessageEditable',\n        restrict(data, domQuery, callback) {\n            Entry.Utils.blur();\n            getVC()\n                .getMessage(data.content[1][1])\n                .listElement.addClass('activeForce');\n            const { title, content } = data.tooltip;\n            return createTooltip(title, content, domQuery, callback);\n        },\n        dom: ['variableContainer', 'messageEditButton', '&0'],\n    };\n\n    c[setVariableEditable] = {\n        do(id, value = true) {\n            const VC = getVC();\n            const variable = VC.getVariable(id);\n            const { nameField } = variable.listElement;\n\n            if (value) {\n                VC.updateSelectedVariable(variable);\n            } else {\n                nameField.blur();\n                VC.updateSelectedVariable(null, 'variable');\n            }\n        },\n        state(id) {\n            return [id];\n        },\n        log(id) {\n            return [['id', id]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'setVariableEditable',\n        restrict(data, domQuery, callback) {\n            Entry.Utils.blur();\n            const VC = getVC();\n            VC.updateSelectedVariable(null, 'variable');\n            VC.getVariable(data.content[1][1]).listElement.addClass('activeForce');\n            const { title, content } = data.tooltip;\n            return createTooltip(title, content, domQuery, callback);\n        },\n        dom: ['variableContainer', 'variableEditButton', '&0'],\n    };\n\n    c[setListEditable] = {\n        do(id) {\n            const VC = getVC();\n            const variable = VC.getList(id);\n            // const { nameField } = variable.listElement;\n\n            // nameField.removeAttribute('disabled');\n            VC.updateSelectedVariable(variable);\n            // nameField.focus();\n        },\n        state(id) {\n            return [id];\n        },\n        log(id) {\n            return [['id', id]];\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'setListEditable',\n        restrict(data, domQuery, callback) {\n            Entry.Utils.blur();\n            getVC()\n                .getList(data.content[1][1])\n                .listElement.addClass('activeForce');\n            const { title, content } = data.tooltip;\n            return createTooltip(title, content, domQuery, callback);\n        },\n        dom: ['variableContainer', 'listEditButton', '&0'],\n    };\n\n    c[variableSetName] = {\n        do(id, value) {\n            const VC = getVC();\n            VC.changeVariableName(VC.getVariable(id), value);\n        },\n        state(id) {\n            return [\n                id,\n                getVC()\n                    .getVariable(id)\n                    .getName(),\n            ];\n        },\n        log(id, value) {\n            return [\n                ['id', id],\n                ['value', value],\n            ];\n        },\n        restrict({ tooltip, content }, domQuery, callback) {\n            _updateSelected(content);\n\n            Entry.Utils.focusIfNotActive(domQuery);\n\n            const { title: tooltipTitle, content: tooltipContent } = tooltip;\n            return createTooltip(tooltipTitle, tooltipContent, domQuery, callback, {\n                noDispose: true,\n            });\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'variableSetName',\n        dom: ['variableContainer', 'variableName', '&0'],\n    };\n\n    c[listSetName] = {\n        do(id, value) {\n            const VC = getVC();\n            VC.changeListName(VC.getList(id), value);\n        },\n        state(id) {\n            return [\n                id,\n                getVC()\n                    .getList(id)\n                    .getName(),\n            ];\n        },\n        log(id, value) {\n            return [\n                ['id', id],\n                ['value', value],\n            ];\n        },\n        restrict({ tooltip, content }, domQuery, callback) {\n            _updateSelected(content);\n\n            Entry.Utils.focusIfNotActive(domQuery);\n\n            const { title: tooltipTitle, content: tooltipContent } = tooltip;\n            return createTooltip(tooltipTitle, tooltipContent, domQuery, callback, {\n                noDispose: true,\n            });\n        },\n        recordable: RECORDABLE.SUPPORT,\n        undo: 'listSetName',\n        dom: ['variableContainer', 'listName', '&0'],\n    };\n\n    //utilities\n\n    //if data has toJSON method\n    //return data.toJSON()\n    //else just return data as is\n    function _toJSON(data) {\n        return _.result(data, 'toJSON') || data;\n    }\n\n    function getVC() {\n        return Entry.variableContainer;\n    }\n\n    function _updateSelected(content) {\n        const VC = getVC();\n        const vId = content[1][1];\n        const v = VC.getVariable(vId) || VC.getList(vId);\n        if (v) {\n            VC.updateSelectedVariable(v);\n        }\n    }\n\n    function _listActiveRestrictor({ tooltip, content }, domQuery, callback) {\n        _updateSelected(content);\n        const { title: tooltipTitle, content: tooltipContent } = tooltip;\n        return createTooltip(tooltipTitle, tooltipContent, domQuery, callback);\n    }\n})(Entry.Command);\n"
  },
  {
    "path": "src/core/collection.js",
    "content": "'use strict';\n\n/*\n * Entry Collection object constructor.\n */\n\nEntry.Collection = class Collection {\n    constructor(data) {\n        this.length = 0;\n\n        /*\n         * object for hashing data with id\n         * @private\n         */\n        this._hashMap = {};\n\n        /*\n         * observers\n         */\n        this._observers = [];\n        this.set(data);\n    }\n\n    /* setters */\n    set(data) {\n        while (this.length) {\n            Array.prototype.pop.call(this);\n        }\n\n        const hashMap = this._hashMap;\n        for (const key in hashMap) {\n            delete hashMap[key];\n        }\n\n        if (data !== undefined) {\n            for (let i = 0, len = data.length; i < len; i++) {\n                const datum = data[i];\n                hashMap[datum.id] = datum;\n                Array.prototype.push.call(this, datum);\n            }\n        }\n    }\n\n    push(elem) {\n        this._hashMap[elem.id] = elem;\n        Array.prototype.push.call(this, elem);\n    }\n\n    unshift() {\n        const args = Array.prototype.slice.call(arguments, 0);\n        const hashMap = this._hashMap;\n        for (let i = args.length - 1; i >= 0; i--) {\n            const datum = args[i];\n            Array.prototype.unshift.call(this, datum);\n            hashMap[datum.id] = datum;\n        }\n    }\n\n    insert(datum, index) {\n        Array.prototype.splice.call(this, index, 0, datum);\n        this._hashMap[datum.id] = datum;\n    }\n\n    has(id) {\n        return !!this._hashMap[id];\n    }\n\n    get(id) {\n        return this._hashMap[id];\n    }\n\n    at(index) {\n        return this[index];\n    }\n\n    getAll() {\n        const len = this.length;\n        const ret = [];\n        for (let i = 0; i < len; i++) {\n            ret.push(this[i]);\n        }\n        return ret;\n    }\n\n    indexOf(obj) {\n        return Array.prototype.indexOf.call(this, obj);\n    }\n\n    find(cond) {\n        const ret = [];\n        let flag;\n\n        for (let i = 0, len = this.length; i < len; i++) {\n            flag = true;\n            const datum = this[i];\n            for (const key in cond) {\n                if (cond[key] != datum[key]) {\n                    flag = false;\n                    break;\n                }\n            }\n            if (flag) {\n                ret.push(datum);\n            }\n        }\n        return ret;\n    }\n\n    pop() {\n        const datum = Array.prototype.pop.call(this);\n        delete this._hashMap[datum.id];\n        return datum;\n    }\n\n    shift() {\n        const datum = Array.prototype.shift.call(this);\n        delete this._hashMap[datum.id];\n        return datum;\n    }\n\n    slice(index, amount) {\n        const data = Array.prototype.slice.call(this, index, amount);\n        const hashMap = this._hashMap;\n        for (const i in data) {\n            delete hashMap[data[i].id];\n        }\n        return data;\n    }\n\n    remove = function(datum) {\n        const index = this.indexOf(datum);\n        if (index > -1) {\n            delete this._hashMap[datum.id];\n            this.splice(index, 1);\n        }\n    };\n\n    splice(index, amount) {\n        const args = Array.prototype.slice.call(arguments, 2);\n        const hashMap = this._hashMap;\n        amount = amount === undefined ? this.length - index : amount;\n\n        const splicedData = Array.prototype.splice.call(this, index, amount);\n\n        for (let i = 0, len = splicedData.length; i < len; i++) {\n            delete hashMap[splicedData[i].id];\n        }\n\n        for (let i = 0, len = args.length; i < len; i++) {\n            const datum = args[i];\n            Array.prototype.splice.call(this, index++, 0, datum);\n            this._hashMap[datum.id] = datum;\n        }\n\n        return splicedData;\n    }\n\n    clear() {\n        while (this.length) {\n            Array.prototype.pop.call(this);\n        }\n        this._hashMap = {};\n    }\n\n    map(fn, param) {\n        const array = [];\n        for (let i = 0, len = this.length; i < len; i++) {\n            array.push(fn(this[i], param));\n        }\n        return array;\n    }\n\n    moveFromTo(from, to) {\n        const max = this.length - 1;\n        if (from < 0 || to < 0 || from > max || to > max) {\n            return;\n        }\n        Array.prototype.splice.call(this, to, 0, Array.prototype.splice.call(this, from, 1)[0]);\n    }\n\n    sort() {}\n\n    /* import & export */\n    fromJSON() {}\n\n    toJSON() {\n        const json = [];\n        for (let i = 0, len = this.length; i < len; i++) {\n            json.push(this[i].toJSON());\n        }\n        return json;\n    }\n\n    /* observe methods */\n    observe() {}\n\n    unobserve() {}\n\n    notify() {}\n\n    /* end function */\n    destroy() {}\n};\n"
  },
  {
    "path": "src/core/db.js",
    "content": "'use strict';\n\nEntry.db = class DB {\n    constructor() {\n        this.data = {};\n        this.typeMap = {};\n    }\n    add(datum) {\n        this.data[datum.id] = datum;\n\n        const type = datum.type;\n        if (this.typeMap[type] === undefined) {\n            this.typeMap[type] = {};\n        }\n        this.typeMap[type][datum.id] = datum;\n    }\n\n    has(id) {\n        return this.data.hasOwnProperty(id);\n    }\n\n    remove(id) {\n        if (!this.has(id)) {\n            return;\n        }\n\n        const datum = this.data[id];\n        delete this.typeMap[datum.type][id];\n        delete this.data[id];\n    }\n\n    get(id) {\n        return this.data[id];\n    }\n\n    find() {}\n\n    clear() {\n        this.data = {};\n        this.typeMap = {};\n    }\n};\n"
  },
  {
    "path": "src/core/dom.ts",
    "content": "import { EntryDom, EntryDomConstructor } from '../../types/index';\n\ntype HandleableClickEvent = JQuery.ClickEvent & { handled: boolean };\n\nconst createEntryDom: EntryDomConstructor = function(tag, options) {\n    const tagRegex = /<(\\w+)>/;\n    let dom: EntryDom;\n\n    if (tag instanceof HTMLElement) {\n        dom = $(tag);\n    } else if (tag instanceof jQuery) {\n        dom = tag as JQuery;\n    } else if (typeof tag === 'string' && tagRegex.test(tag)) {\n        dom = $(tag);\n    } else {\n        dom = $(`<${tag}></${tag}>`);\n    }\n\n    //NOTE options 가 없으면 bindOnClick 이라는 함수가 없다. 의도한건지 모르겠음.\n    if (options === undefined) {\n        return dom;\n    }\n\n    options.id && dom.attr('id', options.id);\n    options.class && dom.addClass(options.class);\n    options.classes && options.classes.forEach(dom.addClass.bind(dom));\n    options.text && dom.text(options.text);\n    options.src && dom.attr('src', options.src);\n    options.href && dom.attr('href', options.href);\n    options.parent && options.parent.append(dom);\n\n    dom.bindOnClick = function() {\n        let child: any;\n        let func: Function;\n\n        const handler = function(e: HandleableClickEvent) {\n            e.stopImmediatePropagation();\n            if (e.handled) {\n                return;\n            }\n            e.handled = true;\n            func.call(this, e);\n        };\n\n        if (arguments.length > 1) {\n            func = arguments[1] instanceof Function ? arguments[1] : function() {};\n            child = typeof arguments[0] === 'string' ? arguments[0] : '';\n        } else {\n            func = arguments[0] instanceof Function ? arguments[0] : function() {};\n        }\n\n        if (child) {\n            $(this).on('click tab', child, handler);\n        } else {\n            $(this).on('click tab', handler);\n        }\n        return this;\n    };\n\n    return dom;\n};\n\nexport default createEntryDom;\nEntry.Dom = createEntryDom;\n"
  },
  {
    "path": "src/core/event.js",
    "content": "'use strict';\n\nEntry.Event = class Event {\n    constructor(sender) {\n        this._sender = sender;\n        this._listeners = [];\n    }\n\n    attach(obj, fn) {\n        const that = this;\n        const listener = {\n            obj,\n            fn,\n            destroy() {\n                that.detach(this);\n            },\n        };\n        this._listeners.push(listener);\n        return listener;\n    }\n\n    detach(listener) {\n        const listeners = this._listeners || [];\n        const index = listeners.indexOf(listener);\n        if (index > -1) {\n            return listeners.splice(index, 1);\n        }\n    }\n\n    clear() {\n        const listeners = this._listeners;\n        while (listeners.length) {\n            listeners.pop().destroy();\n        }\n    }\n\n    notify() {\n        const args = arguments;\n        this._listeners.slice().forEach(function(listener) {\n            try {\n                listener.fn.apply(listener.obj, args);\n            } catch (e) {\n                console.warn(e, listener, listener.fn);\n            }\n        });\n    }\n\n    hasListeners() {\n        return !!this._listeners.length;\n    }\n};\n"
  },
  {
    "path": "src/core/model.js",
    "content": "// 'use strict';\n\n/*\n * Entry Model object generator.\n * @param {object} obj\n */\nEntry.Model = function(obj, isSeal) {\n    const model = Entry.Model;\n    model.generateSchema(obj);\n    model.generateSetter(obj);\n    model.generateObserve(obj);\n    if (isSeal === undefined || isSeal) {\n        Object.seal(obj);\n    }\n\n    return obj;\n};\n\n(function(m) {\n    m.generateSchema = function(obj) {\n        let schema = obj.schema;\n        if (schema === undefined) {\n            return;\n        }\n        try {\n            schema = JSON.parse(JSON.stringify(schema));\n        } catch (e) {\n            console.log(schema);\n            console.error(e);\n        }\n        obj.data = {};\n        for (const key in schema) {\n            (function(localKey) {\n                obj.data[localKey] = schema[localKey];\n                Object.defineProperty(obj, localKey, {\n                    get() {\n                        return obj.data[localKey];\n                    },\n                });\n            })(key);\n        }\n        obj._toJSON = this._toJSON;\n    };\n\n    m.generateSetter = function(obj) {\n        obj.set = this.set;\n    };\n\n    m.set = function(data, isSilent) {\n        const oldValue = {};\n        const keys = Object.keys(data);\n        for (const key in this.data) {\n            if (data[key] !== undefined) {\n                if (data[key] === this.data[key]) {\n                    keys.splice(keys.indexOf(key), 1);\n                } else {\n                    oldValue[key] = this.data[key];\n                    if (data[key] instanceof Array) {\n                        this.data[key] = data[key].concat();\n                    } else {\n                        this.data[key] = data[key];\n                    }\n                }\n            }\n        }\n        if (!isSilent) {\n            this.notify(keys, oldValue);\n        }\n    };\n\n    m.generateObserve = function(obj) {\n        obj.observers = [];\n        obj.observe = this.observe;\n        obj.unobserve = this.unobserve;\n        obj.notify = this.notify;\n    };\n\n    /*\n     * @param {object} object that observe this model\n     * @param {string} eventFunc will be call when notify\n     * @param {?object} attrs includes which property to watch. Should be array or null.\n     * @param {boolean} isNotify\n     */\n    m.observe = function(object, funcName, attrs, isNotify) {\n        const observer = new Entry.Observer(this.observers, object, funcName, attrs);\n        if (isNotify !== false) {\n            object[funcName]([]);\n        }\n        return observer;\n    };\n\n    m.unobserve = function(observer) {\n        observer.destroy();\n    };\n\n    /*\n     * @param {object|string} key\n     * @param {} oldValue\n     */\n    m.notify = function(keys, oldValue) {\n        if (typeof keys === 'string') {\n            keys = [keys];\n        }\n\n        const that = this;\n        const observers = that.observers;\n\n        if (!observers.length) {\n            return;\n        }\n\n        observers.forEach((observeData) => {\n            let attrs = keys;\n            if (observeData.attrs !== undefined) {\n                attrs = _.intersection(observeData.attrs, keys);\n            }\n\n            if (!attrs.length) {\n                return;\n            }\n\n            observeData.object[observeData.funcName](\n                attrs.forEach((key) => ({\n                    name: key,\n                    object: that,\n                    oldValue: oldValue[key],\n                }))\n            );\n        });\n    };\n\n    m._toJSON = function() {\n        const json = {};\n        for (const key in this.data) {\n            json[key] = this.data[key];\n        }\n        return json;\n    };\n})(Entry.Model);\n"
  },
  {
    "path": "src/core/modelClass.ts",
    "content": "import intersection from 'lodash/intersection';\n\nexport default abstract class ModelClass<T extends { [key: string]: any }> {\n    public data: Partial<T>;\n    public observers: any[] = []; // new Entry.Observer\n    protected schema: T;\n\n    protected constructor(schema: T, isSeal?: boolean) {\n        this.schema = schema;\n        this.generateSchema();\n        if (isSeal === undefined || isSeal) {\n            Object.seal(this);\n        }\n    }\n\n    private generateSchema() {\n        let schema = this.schema;\n        if (schema === undefined) {\n            return;\n        }\n        try {\n            schema = JSON.parse(JSON.stringify(schema));\n        } catch (e) {\n            console.log(schema);\n            console.error(e);\n        }\n        this.data = {};\n        Object.keys(schema).forEach((key) => {\n            // @ts-ignore\n            this.data[key] = schema[key];\n            Object.defineProperty(this, key, {\n                get() {\n                    return this.data[key];\n                },\n            });\n        });\n    }\n\n    public set(data: Partial<T>, isSilent?: boolean) {\n        const oldValue: { [key: string]: any } = {};\n        const keys = Object.keys(data);\n        for (const key in this.data) {\n            if (data[key] !== undefined) {\n                if (data[key] === this.data[key]) {\n                    keys.splice(keys.indexOf(key), 1);\n                } else {\n                    oldValue[key] = this.data[key];\n                    // @ts-ignore\n                    if (data[key] instanceof Array) {\n                        this.data[key] = data[key].concat();\n                    } else {\n                        this.data[key] = data[key];\n                    }\n                }\n            }\n        }\n\n        !isSilent && this.notify(keys, oldValue);\n    }\n\n    public observe(object: any, funcName: string, attrs: any, isNotify?: boolean) {\n        // @ts-ignore\n        const observer = new Entry.Observer(this.observers, object, funcName, attrs);\n        if (isNotify !== false) {\n            object[funcName]([]);\n        }\n        return observer;\n    }\n\n    public unobserve(observer: any) {\n        observer.destroy();\n    }\n\n    public notify(key: string | string[], oldValue: any) {\n        const keys = typeof key === 'string' ? [key] : key;\n        const observers = this.observers;\n        if (!observers.length) {\n            return;\n        }\n\n        observers.forEach((observeData) => {\n            let attrs = keys;\n            if (observeData.attrs !== undefined) {\n                attrs = intersection(observeData.attrs, keys);\n            }\n\n            if (!attrs.length) {\n                return;\n            }\n\n            observeData.object[observeData.funcName](\n                attrs.forEach((key) => ({\n                    name: key,\n                    object: this,\n                    oldValue: oldValue[key],\n                }))\n            );\n        });\n    }\n\n    protected _toJSON() {\n        const json: { [key: string]: any } = {};\n        for (const key in this.data) {\n            json[key] = this.data[key];\n        }\n        return json;\n    }\n}\n"
  },
  {
    "path": "src/core/observer.js",
    "content": "'use strict';\n\n/*\n * Entry Observer object Constructor\n * @param {object} obj\n */\n\nEntry.Observer = class Observer {\n    constructor(parent, object, funcName, attrs) {\n        this.parent = parent;\n        this.object = object;\n        this.funcName = funcName;\n        this.attrs = attrs;\n        parent.push(this);\n    }\n\n    destroy = function() {\n        const parent = this.parent;\n        const index = parent.indexOf(this);\n        if (index > -1) {\n            parent.splice(index, 1);\n        }\n        return this;\n    };\n};\n"
  },
  {
    "path": "src/core/promiseManager.js",
    "content": "module.exports = class PromiseManager {\n    // default timeout value\n    get timeout() {\n        return 30000;\n    }\n\n    setPromiseTimer(resolve, reject, option) {\n        const { timeout = this.timeout, defaultValue } = option;\n        return setTimeout(() => {\n            if (Entry.engine.state === 'run') {\n                if (defaultValue !== undefined) {\n                    resolve(defaultValue);\n                } else {\n                    reject('timeout');\n                }\n            }\n        }, timeout);\n    }\n\n    /**\n     * 입력한 time 만큼 일시정지한다.\n     * pause 상태인 경우 로직을 수행하지 않고 멈춘다.\n     * 시간은 그대로 흐르기 때문에 timeout 후 재시작하면 다음블록이 바로 실행된다.\n     * \n     * @param time 일시정지할 ms\n     */\n    sleep(time) {\n        return new Promise((resolve) => {\n            setTimeout(async() => {\n                await waitWhilePause();\n                resolve();\n            }, time);\n        });\n\n        function waitWhilePause() {\n            return new Promise((resolve) => {\n                if (Entry.engine.state !== 'pause') {\n                    resolve();\n                }\n\n                const polling = setInterval(() => {\n                    if (Entry.engine.state !== 'pause') {\n                        window.clearInterval(polling);\n                        resolve();\n                    }\n                }, 1000 / Entry.FPS);\n            });\n        }\n    }\n\n    /**\n     * sample code\n     * Entry.addEventListener('callApi', ({url}, resolve, reject) => {\n     *     $.ajax(url).then((...args) => {\n     *         console.log(args);\n     *         resolve('asd');\n     *     }).fail(() => {\n     *         reject()\n     *     });\n     * });\n     */\n    async EventPromise(key, data, option) {\n        return this.Promise((resolve, reject) => {\n            const { defaultValue } = option;\n            const t = this.setPromiseTimer(resolve, reject, option);\n            Entry.dispatchEvent(\n                key,\n                data,\n                (value) => {\n                    clearTimeout(t);\n                    resolve(value);\n                },\n                (value) => {\n                    clearTimeout(t);\n                    if (defaultValue !== undefined) {\n                        resolve(defaultValue);\n                    } else {\n                        reject(value);\n                    }\n                }\n            );\n        });\n    }\n\n    Promise(f) {\n        return new Promise((resolve, reject) => {\n            const callback = (data) => {\n                if (Entry.engine.state !== 'run') {\n                    reject(new Entry.Utils.AsyncError('Engine 정지'));\n                } else {\n                    resolve(data);\n                }\n            };\n            f(callback, reject);\n        });\n    }\n};\n"
  },
  {
    "path": "src/core/singleInstance.js",
    "content": "function singleInstance(MyClass) {\n    function getInstance(...props) {\n        if (!MyClass.instance) {\n            MyClass.instance = new MyClass(...props);\n        }\n\n        return MyClass.instance;\n    }\n\n    return {\n        getInstance,\n    };\n}\n\nexport default singleInstance;\n"
  },
  {
    "path": "src/core/svg.js",
    "content": "/**\n * @fileoverview View element constructor\n * @author Kyumin Sim\n * @version 0.2\n */\n'use strict';\n\n/**\n * Function for construct html dom element.\n * @function\n * @param {string} tag or html to construct dom element.\n * @param {?object} options include id, classes, parent etc.\n */\nEntry.SVG = function(id, svgDom) {\n    const element = svgDom ? svgDom : document.getElementById(id);\n    return Entry.SVG.createElement(element);\n};\n\nEntry.SVG.NS = 'http://www.w3.org/2000/svg';\nEntry.SVG.NS_XLINK = 'http://www.w3.org/1999/xlink';\n\nEntry.SVG.createElement = function(tag, options) {\n    let el;\n    if (typeof tag === 'string') {\n        el = document.createElementNS(Entry.SVG.NS, tag);\n    } else {\n        el = tag;\n    }\n\n    if (options) {\n        if (options.href) {\n            el.setAttributeNS(Entry.SVG.NS_XLINK, 'href', options.href);\n            delete options.href;\n        }\n\n        for (const key in options) {\n            el.setAttribute(key, options[key]);\n        }\n    }\n\n    //add util functions\n    el.elem = Entry.SVG.createElement;\n    el.prepend = Entry.SVG.prepend;\n    el.attr = Entry.SVG.attr;\n    el.addClass = Entry.SVG.addClass;\n    el.removeClass = Entry.SVG.removeClass;\n    el.hasClass = Entry.SVG.hasClass;\n    el.remove = Entry.SVG.remove;\n    el.removeAttr = Entry.SVG.removeAttr;\n\n    if (tag === 'text') {\n        el.setAttributeNS(\n            'http://www.w3.org/XML/1998/namespace',\n            'xml:space',\n            'preserve'\n        );\n    }\n\n    if (this instanceof SVGElement) {\n        this.appendChild(el);\n    }\n\n    return el;\n};\n\nEntry.SVG.prepend = function(tag) {\n    let el;\n    if (typeof tag === 'string') {\n        el = document.createElementNS(Entry.SVG.NS, tag);\n    } else {\n        el = tag;\n    }\n    //add util functions\n    el.elem = Entry.SVG.createElement;\n    el.prepend = Entry.SVG.prepend;\n    el.attr = Entry.SVG.attr;\n    el.addClass = Entry.SVG.addClass;\n    el.removeClass = Entry.SVG.removeClass;\n    el.hasClass = Entry.SVG.hasClass;\n    el.remove = Entry.SVG.remove;\n    el.removeAttr = Entry.SVG.removeAttr;\n\n    if (this instanceof SVGElement) {\n        if (this.childNodes.length) {\n            this.insertBefore(el, this.childNodes[0]);\n        } else {\n            this.appendChild(el);\n        }\n    }\n    return el;\n};\n\nEntry.SVG.attr = function(options, property) {\n    if (typeof options === 'string') {\n        const o = {};\n        o[options] = property;\n        options = o;\n    }\n\n    if (options) {\n        if (options.href) {\n            this.setAttributeNS(Entry.SVG.NS_XLINK, 'href', options.href);\n            delete options.href;\n        }\n        for (const key in options) {\n            this.setAttribute(key, options[key]);\n        }\n    }\n\n    return this;\n};\n\nEntry.SVG.addClass = function(...classes) {\n    const className = classes.reduce((acc, className) => {\n        if (!this.hasClass(className)) {\n            acc += ` ${  className}`;\n        }\n        return acc;\n    }, this.getAttribute('class'));\n    this.setAttribute('class', className.replace(/\\s+/g, ' '));\n    return this;\n};\n\nEntry.SVG.removeClass = function(...classes) {\n    const className = classes.reduce((acc, className) => {\n        if (this.hasClass(className)) {\n            acc = acc.replace(\n                new RegExp(`(\\\\s|^)${  className  }(\\\\s|$)`),\n                ' '\n            );\n        }\n        return acc;\n    }, this.getAttribute('class'));\n    if (className) {\n        this.setAttribute('class', className.replace(/\\s+/g, ' '));\n    }\n    return this;\n};\n\nEntry.SVG.hasClass = function(className) {\n    const attr = this.getAttribute('class');\n    if (!attr) {\n        return false;\n    } else {\n        return attr.match(new RegExp(`(\\\\s|^)${  className  }(\\\\s|$)`));\n    }\n};\n\nEntry.SVG.remove = function() {\n    if (this.parentNode) {\n        this.parentNode.removeChild(this);\n    }\n};\n\nEntry.SVG.removeAttr = function(attrName) {\n    this.removeAttribute(attrName);\n};"
  },
  {
    "path": "src/css/codemirror_theme.less",
    "content": "/* BASICS */\n\n.CodeMirror {\n  /* Set height, width, borders, and global font properties here */\n  font-family: 'Nanum Gothic Coding' !important;\n  height: 100%;\n  color: black;\n}\n\n.CodeMirror *{\n  font-family: 'Nanum Gothic Coding' !important;\n}\n\n/* PADDING */\n\n.CodeMirror-sizer {\n    padding-top: 7px;\n}\n\n.CodeMirror-lines {\n  padding: 5px 0; /* Vertical padding around content */\n}\n.CodeMirror pre {\n  padding: 0 5px; /* Horizontal padding of content */\n}\n\n.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n  background-color: white; /* The little square between H and V scrollbars */\n}\n\n/* GUTTER */\n\n.CodeMirror-gutters {\n  border-right: 1px solid #ddd;\n  background-color: #f7f7f7;\n  white-space: nowrap;\n}\n.CodeMirror-linenumbers {}\n\n.CodeMirror-linenumber {\n  padding: 0 5px 0 5px;\n  min-width: 20px;\n  text-align: right;\n  color: #A0A0A0;\n  white-space: nowrap;\n  border-right: 1px solid #ddd;\n}\n\n.CodeMirror-guttermarker { color: black; }\n.CodeMirror-guttermarker-subtle { color: #999; }\n\n/* CURSOR */\n\n.CodeMirror-cursor {\n  border-left: 1px solid black;\n  border-right: none;\n  width: 0;\n}\n/* Shown when moving in bi-directional text */\n.CodeMirror div.CodeMirror-secondarycursor {\n  border-left: 1px solid silver;\n}\n.cm-fat-cursor .CodeMirror-cursor {\n  width: auto;\n  border: 0;\n  background: #7e7;\n}\n.cm-fat-cursor div.CodeMirror-cursors {\n  z-index: 1;\n}\n\n.cm-animate-fat-cursor {\n  width: auto;\n  border: 0;\n  -webkit-animation: blink 1.06s steps(1) infinite;\n  -moz-animation: blink 1.06s steps(1) infinite;\n  animation: blink 1.06s steps(1) infinite;\n  background-color: #7e7;\n}\n@-moz-keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n@-webkit-keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n@keyframes blink {\n  0% {}\n  50% { background-color: transparent; }\n  100% {}\n}\n\n/* Can style cursor different in overwrite (non-insert) mode */\n.CodeMirror-overwrite .CodeMirror-cursor {}\n\n.cm-tab { display: inline-block; text-decoration: inherit; }\n\n.CodeMirror-ruler {\n  border-left: 1px solid #ccc;\n  position: absolute;\n}\n\n/* DEFAULT THEME */\n\n.cm-s-default .cm-header {color: blue;}\n.cm-s-default .cm-quote {color: #090;}\n.cm-negative {color: #d44;}\n.cm-positive {color: #292;}\n.cm-header, .cm-strong {font-weight: bold;}\n.cm-em {font-style: italic;}\n.cm-link {text-decoration: underline;}\n.cm-strikethrough {text-decoration: line-through;}\n\n/*\n.cm-s-default .cm-keyword {color: #2BBFED ;}\n.cm-s-default .cm-atom {color: #FF9E00;}\n.cm-s-default .cm-number {color: #E22C0B;}\n.cm-s-default .cm-def {color: #4F39DB;}\n.cm-s-default .cm-variable,\n.cm-s-default .cm-punctuation,\n.cm-s-default .cm-property,\n.cm-s-default .cm-operator {color: #E22C0B;}\n.cm-s-default .cm-variable-2 {color: #0FC764;}\n.cm-s-default .cm-variable-3 {color: #085;}\n.cm-s-default .cm-comment {color: #a50;}\n.cm-s-default .cm-string {color: #4F39DB;}\n.cm-s-default .cm-string-2 {color: #f50;}\n.cm-s-default .cm-meta {color: #555;}\n.cm-s-default .cm-qualifier {color: #555;}\n.cm-s-default .cm-builtin {color: #30a;}\n.cm-s-default .cm-bracket {color: #997;}\n.cm-s-default .cm-tag {color: #170;}\n.cm-s-default .cm-attribute {color: #00c;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n.cm-s-default .cm-error {color: #f00;}\n.cm-invalidchar {color: #f00;} */\n\n/*Entry Textcoding Font*/\n.cm-s-default .cm-keyword {color: #2BBFED ;} /* applied */\n.cm-s-default .cm-atom {color: #FF9E00;}\n.cm-s-default .cm-number {color: #0FC764;} /* applied */\n.cm-s-default .cm-def {color: #4F39DB;} /* applied */\n.cm-s-default .cm-variable {color:#E22C0B;} /* applied */\n.cm-s-default .cm-punctuation,\n.cm-s-default .cm-property {color:#E22C0B;} /* applied */\n.cm-s-default .cm-operator {color: #000000;} /* applied */\n.cm-s-default .cm-variable-2 {color: #E22C0B;} /* applied */\n.cm-s-default .cm-variable-3 {color: #085;}\n.cm-s-default .cm-comment {color: #FF9E00;} /* applied */\n.cm-s-default .cm-string {color: #2A7DEF;} /* applied */\n.cm-s-default .cm-string-2 {color: #f50;}\n.cm-s-default .cm-meta {color: #555;}\n.cm-s-default .cm-qualifier {color: #555;}\n.cm-s-default .cm-builtin {color: #C93AD8;} /* applied */\n.cm-s-default .cm-bracket {color: #997;}\n.cm-s-default .cm-tag {color: #170;}\n.cm-s-default .cm-attribute {color: #00c;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n.cm-s-default .cm-error {color: #E22C0B;}\n.cm-invalidchar {color: #f00;} \n\n\n.CodeMirror-composing { border-bottom: 2px solid; }\n\n/* Default styles for common addons */\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }\n.CodeMirror-activeline-background {background: #E7F1FD;}\n\n/* STOP */\n\n/* The rest of this file contains styles related to the mechanics of\n   the editor. You probably shouldn't touch them. */\n\n.CodeMirror {\n  position: relative;\n  overflow: hidden;\n  background: white;\n}\n\n.CodeMirror-scroll {\n  overflow: scroll !important; /* Things will break if this is overridden */\n  /* 30px is the magic margin used to hide the element's real scrollbars */\n  /* See overflow: hidden in .CodeMirror */\n  margin-bottom: -30px; margin-right: -30px;\n  padding-bottom: 30px;\n  height: 100%;\n  outline: none; /* Prevent dragging from highlighting the element */\n  position: relative;\n}\n.CodeMirror-sizer {\n  position: relative;\n  border-right: 30px solid transparent;\n}\n\n/* The fake, visible scrollbars. Used to force redraw during scrolling\n   before actuall scrolling happens, thus preventing shaking and\n   flickering artifacts. */\n.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n  position: absolute;\n  z-index: 6;\n  display: none;\n}\n.CodeMirror-vscrollbar {\n  right: 0; top: 0;\n  overflow-x: hidden;\n  overflow-y: scroll;\n}\n.CodeMirror-hscrollbar {\n  bottom: 0; left: 0;\n  overflow-y: hidden;\n  overflow-x: scroll;\n}\n.CodeMirror-scrollbar-filler {\n  right: 0; bottom: 0;\n}\n.CodeMirror-gutter-filler {\n  left: 0; bottom: 0;\n}\n\n.CodeMirror-gutters {\n  position: absolute; left: 0; top: 0;\n  z-index: 3;\n  height: 100% !important;\n}\n.CodeMirror-gutter {\n  white-space: normal;\n  height: 100%;\n  display: inline-block;\n  margin-bottom: -30px;\n  margin-right: -1px;\n  /* Hack to make IE7 behave */\n  *zoom:1;\n  *display:inline;\n}\n.CodeMirror-gutter-wrapper {\n  position: absolute;\n  z-index: 4;\n  background: none !important;\n  border: none !important;\n}\n.CodeMirror-gutter-background {\n  position: absolute;\n  top: 0; bottom: 0;\n  z-index: 4;\n}\n.CodeMirror-gutter-elt {\n  position: absolute;\n  cursor: default;\n  z-index: 4;\n  background-color: #f7f7f7;\n  padding-right: 6px;\n}\n.CodeMirror-gutter-wrapper {\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  user-select: none;\n}\n\n.CodeMirror-lines {\n  cursor: text;\n  min-height: 1px; /* prevents collapsing before first draw */\n}\n.CodeMirror pre {\n  /* Reset some styles that the rest of the page might have set */\n  -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;\n  border-width: 0;\n  background: transparent;\n  font-family: inherit;\n  font-size: inherit;\n  margin: 0;\n  white-space: pre;\n  word-wrap: normal;\n  line-height: inherit;\n  color: inherit;\n  z-index: 2;\n  position: relative;\n  overflow: visible;\n  -webkit-tap-highlight-color: transparent;\n}\n.CodeMirror-wrap pre {\n  word-wrap: break-word;\n  white-space: pre-wrap;\n  word-break: normal;\n}\n\n.CodeMirror-linebackground {\n  position: absolute;\n  left: 0; right: 0; top: 0; bottom: 0;\n  z-index: 0;\n}\n\n.CodeMirror-linewidget {\n  position: relative;\n  z-index: 2;\n  overflow: auto;\n}\n\n.CodeMirror-widget {}\n\n.CodeMirror-code {\n  outline: none;\n}\n\n/* Force content-box sizing for the elements where we expect it */\n.CodeMirror-scroll,\n.CodeMirror-sizer,\n.CodeMirror-gutter,\n.CodeMirror-gutters,\n.CodeMirror-linenumber {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\n\n.CodeMirror-measure {\n  position: absolute;\n  width: 100%;\n  height: 0;\n  overflow: hidden;\n  visibility: hidden;\n}\n\n.CodeMirror-cursor { position: absolute; }\n.CodeMirror-measure pre { position: static; }\n\ndiv.CodeMirror-cursors {\n  visibility: hidden;\n  position: relative;\n  z-index: 3;\n}\ndiv.CodeMirror-dragcursors {\n  visibility: visible;\n}\n\n.CodeMirror-focused div.CodeMirror-cursors {\n  visibility: visible;\n}\n\n.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused .CodeMirror-selected { background: #E4F9ED; }\n.CodeMirror-crosshair { cursor: crosshair; }\n.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }\n.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }\n\n.cm-searching {\n  background: #ffa;\n  background: rgba(255, 255, 0, .4);\n}\n\n/* IE7 hack to prevent it from returning funny offsetTops on the spans */\n.CodeMirror span { *vertical-align: text-bottom; }\n\n/* Used to force a border model for a node */\n.cm-force-border { padding-right: .1px; }\n\n@media print {\n  /* Hide the cursor when printing */\n  .CodeMirror div.CodeMirror-cursors {\n    visibility: hidden;\n  }\n}\n\n/* See issue #2901 */\n.cm-tab-wrap-hack:after { content: ''; }\n\n/* Help users use markselection to safely style text background */\nspan.CodeMirror-selectedtext { background: none; }\n"
  },
  {
    "path": "src/css/common.less",
    "content": "@url: '../../img/';\n@image_url: '../../images/';\n@image_url2: '../images/';\n\nhtml,\nbody {\n    touch-action: none;\n    // position: fixed;\n    overflow: hidden;\n}\n\n* {\n    box-sizing: border-box;\n}\n\nimg,\nfieldset,\nbutton {\n    border: 0;\n}\n\n.blind {\n    overflow: hidden;\n    position: absolute;\n    top: 0;\n    left: 0;\n    margin: -1px;\n    padding: 0;\n    width: 1px;\n    height: 1px;\n    border: 0;\n    clip: rect(0, 0, 0, 0);\n}\n\n#__next {\n    position: absolute;\n    height: 100%;\n    width: 100%;\n}\n\nhtml,\nbody,\n.wrapper,\n.entry {\n    height: 100%;\n    margin: 0;\n    padding: 0;\n}\n.wrapper,\n.entry {\n    position: relative;\n    min-width: 1024px;\n}\n.engineContainer {\n    position: relative;\n    display: flex;\n    flex-direction: column;\n    float: left;\n    width: 294px;\n    height: 100%;\n    padding: 46px 16px 8px 8px;\n}\n.backgroundImage(@imageName) {\n    background-image: url('@{image_url2}@{imageName}');\n}\n\n.dragNone {\n    -webkit-touch-callout: none;\n    -webkit-user-select: none;\n    -khtml-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    user-select: none;\n}\n\n.entryHidden {\n    visibility: hidden;\n}\n\n.entryRemove {\n    display: none !important;\n}\n\n.entryHide {\n    visibility: hidden;\n}\n\n.entryRemoveCategory {\n    display: none !important;\n}\n\n.entryRemoveElement {\n    display: none !important;\n}\n\n.entryNoDeco {\n    text-decoration: none !important;\n}\n\n.entryBtn {\n    border: none;\n    margin: 0;\n    background-color: transparent;\n}\n\n.entryDimmed {\n    opacity: 0.5;\n    background-color: #767676;\n}\n\n.table-modal {\n    position: fixed;\n    left: 0;\n    top: 0;\n    bottom: 0;\n    right: 0;\n    z-index: 1000;\n}\n\n#entryInputForComputeWidth {\n    visibility: hidden;\n    position: fixed;\n    left: -9999px;\n    top: -9999px;\n}\n\ninput[type='number']::-webkit-inner-spin-button,\ninput[type='number']::-webkit-outer-spin-button {\n    -webkit-appearance: none;\n}\n\ninput[type='number'] {\n    -moz-appearance: textfield;\n}\n"
  },
  {
    "path": "src/css/components/block.less",
    "content": ".block.selected > g > .blockPath,\n.block.selected > g > .blockBackgroundPath {\n    // stroke-width: 3px;\n    // stroke: #798EB1;\n    -webkit-filter: none;\n    filter: none;\n\n    &:not([fill^='url(#blockHoverPattern']) {\n        -webkit-filter: url(#entryBlockSelectFilter_board);\n        filter: url(#entryBlockSelectFilter_board);\n    }\n}\n\n.block.outputHighlight > g > .blockPath {\n    stroke-width: 2px;\n    stroke: white;\n}\n\n.block.basicButtonView {\n    cursor: pointer;\n}\n\n.block.basicButtonView > g > path {\n    fill: #ffffff;\n    stroke: #4f80ff;\n    stroke-width: 1;\n}\n.block.basicButtonDisabledView {\n    cursor: auto;\n}\n.block.basicButtonDisabledView > g > path {\n    fill: #f9f9f9;\n    stroke: #e2e2e2;\n    stroke-width: 1;\n}\n\n.block.clickableText {\n    cursor: pointer;\n}\n\n.block.basicText {\n    cursor: default;\n}\n\n.block.basicText:hover > g > path {\n    fill: none;\n}\n\n.block.basicTextLight {\n    cursor: default;\n}\n\n.block.basicTextLight > g > text > tspan {\n    font-weight: lighter;\n}\n\n.block {\n    cursor: url('/media/handopen.cur'), auto;\n    -ms-touch-action: none;\n}\n\n.block.dragging {\n    cursor: url('/media/handclosed.cur'), auto;\n}\n\n.block.selected > path {\n    stroke-width: 3px;\n    stroke: #798eb1;\n}\n\n.block.activated > g > path {\n    stroke-width: 3px;\n    stroke: red;\n}\n\n@keyframes activationDash {\n    to {\n        stroke-dashoffset: 0;\n    }\n}\n\n@-webkit-keyframes activationDash {\n    to {\n        stroke-dashoffset: 0;\n    }\n}\n\n.block g text,\n.block g image {\n    pointer-events: none;\n}\n\nsvg .svgBlockGroup text {\n    white-space: pre;\n}\n\n.entry-field-color {\n    cursor: pointer;\n}\n\n.entry-input-field {\n    cursor: text;\n}\n\n.entry-input-field:hover rect {\n    stroke-width: 1.5px;\n    stroke: white;\n}\n\n.entry-widget-input-field {\n    position: fixed;\n    font-family: EntryFont, NanumGothic, 'Nanum Gothic';\n    font-weight: bold;\n    border: none;\n    border-radius: 5px;\n    outline: none;\n    line-height: normal;\n    z-index: 254;\n    color: #000000;\n}\n\n.entry-widget-input-field::-ms-clear,\n.entry-widget-input-field::-ms-reveal {\n    display: none;\n}\n\n.entry-widget-textarea {\n    position: absolute;\n    background-color: #ffda85;\n    resize: none;\n    line-height: 1.6em;\n    outline: none;\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none;\n    overflow: hidden;\n}\n\n.invisible {\n    visibility: hidden;\n}\n\n.entryWorkspaceBoard.invisibleComment {\n    .svgCommentGroup{\n        visibility: hidden;\n    }\n}\n\n.entry-field-angle {\n    cursor: default;\n}\n\n.entry-field-angle-circle {\n    stroke: #dbdbdb;\n    stroke-width: 1;\n    fill: #fbfbfb;\n    fill-opacity: 0.8;\n}\n\n.entry-angle-divider {\n    stroke: #bababa;\n    stroke-width: 1;\n}\n\n.entry-angle-indicator {\n    stroke: #333333;\n    stroke-width: 1;\n    stroke-linecap: round;\n}\n\n.entry-angle-fill-area {\n    fill: #5096f5;\n    fill-opacity: 0.3;\n}\n\n.entryWorkspaceFilters {\n    position: absolute;\n    left: -100px;\n    top: -100px;\n}\n\n.entry-widget-keyboard-input {\n    position: fixed;\n}\n\n.entry-comment-resize-arrow {\n    cursor: nwse-resize;\n}\n\n.entry-comment-toggle-arrow {\n    cursor: pointer;\n}\n\n.blockHoverPattern {\n    .pattern1 {\n        opacity: 0;\n        .animation-duration(0.7s);\n        .animation-direction(alternate);\n        .animation-name(blockPatternAnimation);\n        .animation-iteration-count(infinite);\n    }\n\n    .pattern2 {\n        opacity: 0;\n        .animation-delay(0.33s);\n        .animation-duration(0.7s);\n        .animation-direction(alternate);\n        .animation-name(blockPatternAnimation);\n        .animation-iteration-count(infinite);\n    }\n\n    .pattern3 {\n        opacity: 0;\n        .animation-delay(0.67s);\n        .animation-duration(0.7s);\n        .animation-direction(alternate);\n        .animation-name(blockPatternAnimation);\n        .animation-iteration-count(infinite);\n    }\n\n    .pattern4 {\n        opacity: 0;\n        .animation-delay(1s);\n        .animation-duration(0.7s);\n        .animation-direction(alternate);\n        .animation-name(blockPatternAnimation);\n        .animation-iteration-count(infinite);\n    }\n}\n\n//hover block background pattern animation\n@keyframes blockPatternAnimation {\n    from {\n        opacity: 0;\n    }\n    to {\n        opacity: 0.2;\n    }\n}\n\n@-webkit-keyframes blockPatternAnimation {\n    from {\n        opacity: 0;\n    }\n    to {\n        opacity: 0.2;\n    }\n}\n\ng.entry-field-dropdown {\n    cursor: default;\n}\n\n.guideGroup {\n    opacity: 0.3;\n}\n"
  },
  {
    "path": "src/css/components/block_menu.less",
    "content": ".entryWorkspaceBlockMenu {\n    background-color: #fff;\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    z-index: 2;\n}\n\n.entryWorkspaceBlockMenu.entryRemove.init {\n    opacity: 0 !important;\n    display: block !important;\n    z-index: -9999;\n}\n\n\n.entryCategoryListWorkspace {\n    .scrollIndicator {\n        position: absolute;\n        width: 58px;\n        height: 16px;\n        opacity: 0.8;\n        .backgroundImage(\"block_menu/scroll_indicator_arrow.svg\");\n        background-repeat: no-repeat;\n        background-position: center;\n        background-color: #aac5d5;\n        z-index: 6;\n        display: none;\n        cursor: pointer;\n        &.prepend {\n            top: 0;\n        }\n        &.append {\n            bottom: 0;\n            -webkit-transform: rotate(180deg);\n                    transform: rotate(180deg);\n        }\n        .active {\n            display: block;\n        }\n    }\n    position: relative;\n    min-width: 58px;\n    overflow: hidden;\n    height: 100%;\n    display: inline-block;\n    background-color: #ecf8ff;\n    list-style-type: none;\n    border-radius: 0 0 0 6px;\n    margin: 0;\n    padding: 0;\n    -ms-overflow-style: none;  // IE 10+\n    overflow: -moz-scrollbars-none;  // Firefox\n\n    .entryCategoryList {\n        height: 100%;\n        overflow: hidden;\n        overflow-y: scroll;\n        font-weight: bold;\n        &::-webkit-scrollbar {\n            display: none;  // Safari and Chrome\n        }\n\n        .visiblePoint {\n            margin: 0;\n        }\n\n        #entryCategoryarduino {\n            margin-bottom: 1px;\n        }\n    }\n}\n.entryCategoryListWorkspace:before {\n  position: absolute;\n  left: 0;\n  right: 0;\n  top: 0;\n  bottom: 0;\n  border: 1px solid #d6e9f4;\n  border-radius: 0 0 0 6px;\n  content: '';\n}\n\n.entryCategoryListWorkspace li {\n    position: relative;\n    background-color: #ecf8ff;\n    z-index: 5;\n}\n.entryCategoryListWorkspace li:first-child {\n    margin-top: 0;\n}\n.entrySelectedCategory {\n    position: relative;\n    z-index: 5;\n}\n\n.blockMenuContainer {\n    display: inline-block;\n    vertical-align: top;\n    width: 254px;\n    height: 100%;\n    background-color: #ecf8ff;\n    border:1px solid #d6e9f4;\n    border-left: none;\n\n    .blockMenuWrapper {\n        overflow: hidden;\n        width: 100%;\n        height: 100%;\n        -webkit-transition: width ease 0.2s;\n        transition: width ease 0.2s;\n    }\n\n    .blockMenuTrashcan {\n        position: absolute;\n        width: 100%;\n        top: 0;\n        left: 0;\n        opacity: 0.95;\n        background: #f7f2d1;\n        border: 2px dashed #ffc803;\n\n        &:before {\n            display: block;\n            content: ' ';\n            width: 62px;\n            height: 94px;\n            margin-top: 74px;\n            margin-left: calc(50% - 32px);\n            .backgroundImage(\"trashcan.svg\");\n        }\n\n        &.open:before {\n            display: block;\n            content: ' ';\n            width: 64px;\n            height: 102px;\n            margin-top: 66px;\n            margin-left: calc(50% - 31px);\n            .backgroundImage(\"trashcan_open.svg\");\n        }\n\n        span {\n            position: absolute;\n            top: 180px;\n            width: 100%;\n            font-family: NanumGothicBold, NanumGothic, 'Nanum Gothic';\n            font-size: 14px;\n            color: #555;\n            text-align: center;\n        }\n    }\n\n    .block.selected > g > .blockPath,\n    .block.selected > g > .blockBackgroundPath {\n        // stroke-width: 3px;\n        // stroke: #798EB1;\n        -webkit-filter: none;\n        filter: none;\n\n        &:not([fill^='url(#blockHoverPattern']) {\n            -webkit-filter: url(#entryBlockSelectFilter_blockMenu);\n            filter: url(#entryBlockSelectFilter_blockMenu);\n        }\n    }\n}\n\n.blockMenu {\n    height: 100%;\n    min-width: 700px;\n}\n\n.entryCategoryListPhone {\n    padding: 0;\n    margin: 0;\n    list-style-type: none;\n}\n\n.entryCategoryElementWorkspace {\n    padding: 34px 0 4px;\n    min-width: 58px;\n    text-align: center;\n    background-color: #ecf8ff;\n    font-size: 12px;\n    color: #595959;\n    border: 1px solid #d6e9f4;\n    border-bottom: transparent;\n    cursor: pointer;\n    font-family: EntryFont, NanumGothic, 'Nanum Gothic' !important;\n    line-height: 14px;\n    background-size: 32px auto;\n    background-position: 50% 4px;\n    position:relative;\n}\n\n.entryCategoryBetaTag{\n    .backgroundImage(\"beta_tag.svg\");\n    position:absolute;\n    bottom:18px;\n    right:3px;\n    width:26px;\n    height:14px;\n}\n\n.entryCategoryElementPhone {\n    height: 50px;\n    clear: both;\n    width: 56px;\n    padding-top: 30px;\n    text-align: center;\n    background-color: #E2E9F0;\n    font-size: 13px;\n    color: #474747;\n    float: left;\n    border-bottom: 1px solid #B7C4CC;\n    background-position: 5px 2px;\n    cursor: pointer;\n}\n\n.entryCategoryElementEndWorkspace {\n    clear: both;\n    width: 3px;\n    margin-left: 56px;\n    background-color: #515B7C;\n    height: 4000px;\n}\n\n.entryCategoryWorkspace {\n    width: 74px;\n    height: 100%;\n    display: block;\n}\n\n\n.entryBlockMenuWorkspace {\n    background-color: #e5e5e5;\n    position: absolute;\n    left: 64px;\n    top: 45px;\n    width: 186px;\n    bottom: 0px;\n    z-index: 100;\n}\n\n#entryCategorystart {\n    background-repeat: no-repeat;\n}\n\n.entryUnSelectedCategory#entryCategorystart {\n    .backgroundImage(\"start.svg\");\n}\n\n.entrySelectedCategory#entryCategorystart {\n    .backgroundImage(\"start_on.svg\");\n    background-color: #00b400;\n    border-color: #00b400;\n    color: #fff;\n}\n\n#entryCategoryflow {\n    .backgroundImage(\"flow.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryflow {\n    .backgroundImage(\"flow_on.svg\");\n    background-color: #17a6d1;\n    border-color: #17a6d1;\n    color: #fff;\n}\n\n#entryCategorymoving {\n    .backgroundImage(\"moving.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategorymoving {\n    .backgroundImage(\"moving_on.svg\");\n    background-color: #ad3efb;\n    border-color: #ad3efb;\n    color: #fff;\n}\n\n#entryCategorylooks {\n    /*border-right: 4px solid #EC4466;*/\n    .backgroundImage(\"looks.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategorylooks {\n    .backgroundImage(\"looks_on.svg\");\n    background-color: #ff3a61;\n    border-color: #ff3a61;\n    color: #fff;\n}\n\n#entryCategorybrush {\n    .backgroundImage(\"brush.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategorybrush {\n    .backgroundImage(\"brush_on.svg\");\n    background-color: #fc7e01;\n    border-color: #fc7e01;\n    color: #fff;\n}\n\n#entryCategorytext {\n    .backgroundImage(\"text.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategorytext {\n    .backgroundImage(\"text_on.svg\");\n    background-color: #e43500;\n    border-color: #e43500;\n    color: #fff;\n}\n\n#entryCategorysound {\n    .backgroundImage(\"sound.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategorysound {\n    .backgroundImage(\"sound_on.svg\");\n    background-color: #67b100;\n    border-color: #67b100;\n    color: #fff;\n}\n\n#entryCategoryjudgement {\n    .backgroundImage(\"judgement.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryjudgement {\n    .backgroundImage(\"judgement_on.svg\");\n    background-color: #4562f5;\n    border-color: #4562f5;\n    color: #fff;\n}\n\n#entryCategorycalc {\n    .backgroundImage(\"calc.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategorycalc {\n    .backgroundImage(\"calc_on.svg\");\n    background-color: #f4af18;\n    border-color: #f4af18;\n    color: #fff;\n}\n\n#entryCategoryvariable {\n    .backgroundImage(\"variable.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryvariable {\n    .backgroundImage(\"variable_on.svg\");\n    background-color: #dd47d8;\n    border-color: #dd47d8;\n    color: #fff;\n}\n\n#entryCategoryfunc {\n    .backgroundImage(\"func.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryfunc {\n    .backgroundImage(\"func_on.svg\");\n    background-color: #de5c04;\n    border-color: #de5c04;\n    color: #fff;\n}\n\n#entryCategoryanalysis {\n    .backgroundImage(\"analysis.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryanalysis {\n    .backgroundImage(\"analysis_on.svg\");\n    background-color: #17a6d1;\n    border-color: #17a6d1;\n    color: #fff;\n}\n\n#entryCategoryai {\n    .backgroundImage(\"ai.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryai {\n    .backgroundImage(\"ai_on.svg\");\n    background-color: #8222ff;\n    border-color: #8222ff;\n    color: #fff;\n}\n\n#entryCategoryexpansion {\n    .backgroundImage(\"expansion.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryexpansion {\n    .backgroundImage(\"expansion_on.svg\");\n    background-color: #ef6d6d;\n    border-color: #ef6d6d;\n    color: #fff;\n}\n\n#entryCategoryai_utilize {\n    .backgroundImage(\"ai_utilize.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryai_utilize {\n    .backgroundImage(\"ai_utilize_on.svg\");\n    background-color: #8222ff;\n    border-color: #670bdd;\n    color: #fff;\n}\n\n#entryCategoryscene {\n    .backgroundImage(\"scene.png\");\n    background-repeat: no-repeat;\n    border-right: none;\n}\n\n.entrySelectedCategory#entryCategoryscene {\n    border-left: none;\n    border-right: none;\n}\n\n#entryCategoryarduino {\n    .backgroundImage(\"hardware.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryarduino {\n    .backgroundImage(\"hardware_on.svg\");\n    background-color: #00b6b1;\n    border-color: #00b6b1;\n    color: #fff;\n}\n\n#entryCategoryhw_sensor {\n    .backgroundImage(\"sensor.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryhw_sensor {\n    .backgroundImage(\"sensor_on.svg\");\n    background-color: #00cfca;\n    border-color: #00cfca;\n    color: #fff;\n}\n\n#entryCategoryhw_led {\n    .backgroundImage(\"diode.svg\");\n    background-repeat: no-repeat;\n    font-size: 10px;\n}\n\n.entrySelectedCategory#entryCategoryhw_led {\n    .backgroundImage(\"diode_on.svg\");\n    background-color: #00cfca;\n    border-color: #00cfca;\n    color: #fff;\n}\n\n#entryCategoryhw_motor {\n    .backgroundImage(\"dcmotor.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryhw_motor {\n    .backgroundImage(\"dcmotor_on.svg\");\n    background-color: #00cfca;\n    border-color: #00cfca;\n    color: #fff;\n}\n\n#entryCategoryhw_melody {\n    .backgroundImage(\"melody.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryhw_melody {\n    .backgroundImage(\"melody_on.svg\");\n    background-color: #00cfca;\n    border-color: #00cfca;\n    color: #fff;\n}\n\n#entryCategoryhw_robot {\n    .backgroundImage(\"robot.svg\");\n    background-repeat: no-repeat;\n}\n\n.entrySelectedCategory#entryCategoryhw_robot {\n    .backgroundImage(\"robot_on.svg\");\n    background-color: #00cfca;\n    border-color: #00cfca;\n    color: #fff;\n}\n\n.entryBlocklyWorkspace {\n    position: absolute;\n    left: 250px;\n    top: 8px;\n    bottom: 0px;\n    right: 0px;\n    overflow: hidden;\n    border: solid 1px #C4C4B9;\n    border-top-left-radius: 10px;\n    .backgroundImage(\"entry_bg.svg\");\n}\n\n.entryBlocklyWorkspace.folding {\n    z-index: 300;\n    border-left: solid 1px #C4C4B9;\n    .animation-duration(0.7s);\n    .animation-name(foldBlockly);\n    .animation-fill-mode(forwards);\n}\n\n@keyframes foldBlockly {\n    from {}\n    to {left: 64px;}\n}\n\n@-webkit-keyframes foldBlockly {\n    from {}\n    to {left: 64px;}\n}\n\n.entryBlocklyWorkspace.foldOut {\n    z-index:300;\n    .animation-duration(0.7s);\n    .animation-name(foldOutBlockly);\n    .animation-fill-mode(forwards);\n}\n\n@keyframes foldOutBlockly {\n    from {left: 64px;}\n    to {}\n}\n\n@-webkit-keyframes foldOutBlockly {\n    from {left: 64px;}\n    to {}\n}\n\n.entryBlocklyPhone {\n    position: absolute;\n    top: 0px;\n    left: 56px;\n    right: 0px;\n    bottom: 0px;\n    overflow: hidden;\n    border: solid 1px #C4C4B9;\n    border-left: 0;\n    .backgroundImage(\"entry_bg_1.png\");\n}\n"
  },
  {
    "path": "src/css/components/board.less",
    "content": ".entryBoard {\n    cursor: move;\n    position: absolute;\n    -ms-touch-action: none;\n}\n\n.entryOverlayBoard {\n    background: rgba(138, 163, 178, 0.7);\n}\n\n.boardScrollbar {\n    opacity: 1;\n    cursor: move;\n    -ms-touch-action: none;\n\n    .scrollbar {\n        transition: opacity 0.5s;\n        cursor: pointer;\n    }\n}\n\n.boardScrollbar:hover {\n    opacity: 0.6;\n}\n\n.entryBoardWrapper {\n    position: absolute;\n    top: 0;\n    left: 0;\n    right: 0;\n    height: 100%;\n}\n\n.entryVimBoard {\n    z-index: 0;\n    position: absolute;\n    top: 0;\n    left: 0;\n    height: 100%;\n    width: 100%;\n}\n\n.entryFunctionButton {\n    font-family: ng !important;\n    font-size: 13 !important;\n    text-anchor: middle;\n    fill: #ffffff;\n    cursor: pointer !important;\n}\n\n.entryFunctionButtonText {\n    font-family: ng !important;\n    font-size: 13 !important;\n    text-anchor: middle;\n    fill: #4f80ff;\n    cursor: pointer !important;\n}\n\n.entryFunctionButtonBorder {\n    font-family: ng !important;\n    font-size: 13 !important;\n    text-anchor: middle;\n    fill: #ffffff;\n    cursor: pointer !important;\n    stroke: #4f80ff;\n    stroke-width: 1;\n}\n\n.entryWorkspaceBoard {\n    position: absolute;\n    left: 313px;\n    top: 0;\n    bottom: 0;\n    right: 0px;\n    border: 1px solid #d6e9f4;\n    border-width: 1px 0;\n    overflow: hidden;\n    .backgroundImage('entry_bg.svg');\n\n    &.wideView {\n        left: 254px;\n    }\n}\n\n.entryWorkspaceBoard.folding {\n    z-index: 251;\n    // border-left: solid 1px #c4c4b9;\n    .animation-duration(0.7s);\n    .animation-name(foldBoard);\n    .animation-fill-mode(forwards);\n}\n\n@keyframes foldBoard {\n    from {\n    }\n    to {\n        left: 59px;\n    }\n}\n\n@-ms-keyframes foldBoard {\n    from {\n    }\n    to {\n        left: 61px;\n    }\n}\n\n@-moz-keyframes foldBoard {\n    from {\n    }\n    to {\n        left: 61px;\n    }\n}\n\n@-webkit-keyframes foldBoard {\n    from {\n    }\n    to {\n        left: 61px;\n    }\n}\n\n.entryWorkspaceBoard.foldOut {\n    z-index: 300;\n    .animation-duration(0.7s);\n    .animation-name(foldOutBoard);\n    .animation-fill-mode(forwards);\n}\n\n@keyframes foldOutBoard {\n    from {\n        left: 64px;\n    }\n    to {\n    }\n}\n\n@-o-keyframes foldOutBoard {\n    from {\n        left: 61px;\n    }\n    to {\n    }\n}\n\n@-ms-keyframes foldOutBoard {\n    from {\n        left: 61px;\n    }\n    to {\n    }\n}\n\n@-moz-keyframes foldOutBoard {\n    from {\n        left: 61px;\n    }\n    to {\n    }\n}\n\n@-webkit-keyframes foldOutBoard {\n    from {\n        left: 61px;\n    }\n    to {\n    }\n}\n\n#invisibleBoard {\n    visibility: hidden;\n    position: fixed;\n    left: -1000px;\n    top: -1000px;\n}\n"
  },
  {
    "path": "src/css/components/console.less",
    "content": "#entryConsole {\n    height: 100%;\n}\n\n#entryConsole > .CodeMirror {\n    height: 100%;\n    background: #424b50;\n}\n\n#entryConsole .CodeMirror-cursor {\n    border-left: 1px solid white;\n}\n\n#entryConsole span {\n    color: white;\n}\n\n#entryConsole .speak span {\n    color: #fff2a4;\n}\n\n#entryConsole .ask span {\n    color: #bdd1ff;\n}\n"
  },
  {
    "path": "src/css/components/container.less",
    "content": ".sortable {\n    .sortableItem {\n        transform: translate3d(0, 0, 0);\n    }\n}\n\n.entryContainerWorkspace {\n    height: 100%;\n    background-color: #fff;\n\n    .simplebar-scrollbar {\n        right: 4px;\n        width: 8px;\n        &::before {\n            opacity: 1 !important;\n            background-color: #aac5d5;\n            border-radius: 2.5px;\n        }\n    }\n}\n\n.entryContainerPhone {\n    width: 100%;\n    background-color: #fff;\n}\n\n.entryAddObjectWorkspace {\n    display: block;\n    height: 48px;\n    background-color: #e7e7e7;\n    color: #757575;\n    text-align: center;\n    font-size: 11pt;\n    line-height: 44px;\n    margin: 10px;\n    border: 2px dashed #979797;\n    cursor: pointer;\n}\n\n.entryContainerListWorkspaceWrapper {\n    position: absolute;\n    bottom: 0;\n    padding: 0;\n    margin: 0;\n    // overflow: auto;\n    width: 100%;\n    top: 0;\n    background-color: #fff;\n}\n\n.entryContainerExtensions {\n    position: relative;\n    margin: 0px;\n    padding: 0px;\n    width: 100%;\n    background-color: #363c46;\n    list-style-type: none;\n}\n\n.entryContainerListWorkspace {\n    position: relative;\n    margin: 0px;\n    padding: 0px;\n    width: 100%;\n    height: 100%;\n    list-style-type: none;\n\n    .Draggable {\n        height: 100%;\n    }\n}\n\n.entryContainerListPhone {\n    position: relative;\n    margin: 0px;\n    padding: 0px;\n    width: 100%;\n    background-color: #363c46;\n    list-style-type: none;\n    border-top: 1pt solid #ebeff1;\n}\n\n.entryContainerListWorkspace::-webkit-scrollbar {\n    display: none;\n}\n\n.entryContainerListElementWorkspace {\n    background-color: #f7fcff;\n    display: block;\n    padding: 0;\n    margin: 0;\n    position: relative;\n    overflow: hidden;\n    min-height: 60px;\n    .box-sizing(border-box);\n    border: 1px solid #d6e9f4;\n    border-width: 1px 0;\n}\n\n.entryContainerListElementWorkspace.fold {\n    background-color: #f7fcff;\n}\n.entryContainerListElementWorkspace.selectedObject {\n    background-color: #d6e9f4;\n}\n\n.collapsed .selectedObject {\n    height: 149px;\n}\n\n.entryContainerListElementWorkspace:first-child,\n.entryContainerListElementWorkspace.selectedObject + .entryContainerListElementWorkspace {\n    border-top: 0;\n}\n\n.propertyTabhelper {\n    .backgroundImage('property/helper_off.png');\n}\n\n.propertyTabhelper.selected {\n    .backgroundImage('property/helper_on.png');\n\n    .practical_course_mode & {\n        .backgroundImage('property/helper_on_practical_course.png');\n    }\n}\n\n.propertyTabhint {\n    .backgroundImage('property/hint_off_property.png');\n}\n\n.propertyTabhint.selected {\n    .backgroundImage('property/hint_on.png');\n}\n\n.propertyTabContainer {\n    .backgroundImage('property/container_off.png');\n}\n.propertyTabContainer.selected {\n    .backgroundImage('property/container_on.png');\n}\n\n.entryContainerTabViewWorkspace {\n    width: 100%;\n    height: 45px;\n    border-bottom: 2px solid #1bafea;\n}\n\n.entryContainerTabItemWorkspace {\n    vertical-align: top;\n    height: 100%;\n    width: 25%;\n    text-align: center;\n    display: inline-block;\n    background-color: rgb(229, 229, 229);\n    color: rgb(158, 159, 159);\n    font-size: 13px;\n    cursor: pointer;\n    padding-top: 13px;\n}\n\n.entryContainerTabItemWorkspace:nth-child(2) {\n    border-left: 2px solid white;\n    border-right: 2px solid white;\n}\n\n.entryContainerTabItemWorkspace:nth-child(3) {\n    border-right: 2px solid white;\n}\n\n.entryContainerTabItemWorkspace.selected {\n    background-color: #1bafea;\n    color: white;\n}\n\n.entryContainerMovieWorkspace {\n    /*\n    position: absolute;\n    width: 100%;\n    top: 45px;\n    bottom: 0px;\n\n    z-index: 1000;\n*/\n    position: absolute;\n    background-color: #363c46;\n    top: 0px;\n    width: 100%;\n    overflow: scroll;\n}\n.entryContainerMovieWorkspace::-webkit-scrollbar {\n    display: none;\n}\n\n.entryContainerDoneWorkspace {\n    position: absolute;\n    width: 100%;\n    top: 0px;\n    background-color: #363c46;\n    overflow: hidden;\n    text-align: center;\n}\n\n.entryContainerHelperWorkspace {\n    position: absolute;\n    width: 100%;\n    top: 45px;\n    bottom: 0;\n    background-color: #fff;\n    z-index: 1000;\n    background: gray;\n}\n\n.tablet {\n    .entryContainerListElementWorkspace.selectedObject {\n        height: 128px;\n    }\n\n    .collapsed .selectedObject {\n        height: 159px;\n    }\n}\n"
  },
  {
    "path": "src/css/components/context_menu.less",
    "content": "#entry-contextmenu {\n    position: fixed;\n    display: inline-block;\n    list-style: none;\n    padding: 4px 0;\n    outline: none;\n    font-size: 13px;\n    z-index: 25000;\n    span {\n        width: 100%;\n        height: 100%;\n        display: inline-block;\n    }\n    .menuAble {\n        cursor: pointer;\n        padding: 3px 20px;\n    }\n    .menuAble:hover {\n        color: white;\n        background-color: #57e;\n    }\n    .menuDisable {\n        color: #ccc;\n        padding: 3px 20px;\n    }\n    .divider {\n        padding: 0;\n        height: 1px;\n        background-color: #ccc;\n    }\n}\n\n#entry-contextmenu.workspace-contextmenu {\n    font-size: 14px;\n    min-width: 160px;\n    .menuAble {\n        padding: 3px 20px;\n    }\n    .menuAble:hover {\n        color: white;\n        background-color: #57e;\n    }\n    .menuDisable {\n        color: #ccc;\n        padding: 3px 20px;\n    }\n}\n"
  },
  {
    "path": "src/css/components/curtain.less",
    "content": ".entryCurtainElem {\n    position: fixed;\n    background-color: #3b3b3b;\n    opacity: 0.7;\n    z-index: 5001;\n\n    &.top {\n        width: 100%;\n        top: 0;\n        left: 0;\n        right: 0;\n    }\n    &.right {\n        right: 0;\n        bottom: 0;\n    }\n    &.bottom {\n        left: 0;\n        bottom: 0;\n    }\n    &.left {\n        left: 0;\n    }\n    .transition(opacity 0.4s ease-in-out);\n}\n\n.hideTooltip>.entryCurtainElem {\n    opacity: 0;\n}\n\n.entryCurtainCloseBtn {\n    width: 22px;\n    height: 22px;\n    position: fixed;\n    z-index: 10001;\n    right: 22px;\n    top: 22px;\n    .backgroundImage(\"curtain_close.png\");\n    background-repeat: no-repeat;\n    background-color: transparent;\n    border: none;\n}\n"
  },
  {
    "path": "src/css/components/engine.less",
    "content": ".entryEngineWorkspace {\n    height: 35px;\n    width: 480px;\n    background-color: white;\n    border-top: 1pt solid #ebeff1;\n}\n\n.entryEngineWorkspace_w {\n    position: relative;\n    overflow: hidden;\n    width: 270px;\n    background-color: white;\n    border: 1px solid #d6e9f4;\n    border-radius: 6px;\n}\n.entryEngineWorkspace_w:after {\n    display: block;\n    clear: both;\n    content: '';\n}\n\n.entryPopupWindow > .entryEngineWorkspace {\n    position: absolute;\n    top: auto !important;\n    width: 100% !important;\n    bottom: 0px;\n}\n\n.entryPopupWindow > .entryEngineWorkspace_w {\n    position: absolute;\n    width: 100% !important;\n    top: 0px !important;\n}\n\n.entryPopupWindow > .entryEngineWorkspace_w > .entryRunButtonWorkspace_w {\n    display: none;\n    top: 37%;\n    left: 46%;\n}\n\n.entryPopupWindow > .entryEngineWorkspace_w > .entryRunButtonWorkspace_w2 {\n    display: block;\n    width: 111px;\n    height: 111px;\n    background-image: url('@{image_url}play_btn.png');\n    background-position: 40px center;\n    background-color: rgba(0, 0, 0, 0.5);\n    border-radius: 55px;\n    background-repeat: no-repeat;\n    right: 5px;\n    /*bottom: 5px;*/\n    bottom: -10px;\n    left: 44%;\n    top: 35%;\n}\n\n.entryPopupWindow > .entryEngineWorkspace_w > .entryStopButtonWorkspace_w2 {\n    display: block;\n    background-image: url('@{image_url}stop_btn.png');\n    background-repeat: no-repeat;\n    left: 20px;\n    color: transparent;\n    bottom: -10px;\n    width: 90px;\n    background-position: left;\n    color: @bora;\n}\n\n.entryPopupWindow > .entryEngineWorkspace_w > .entryStopButtonWorkspace_w {\n    display: none;\n}\n\n.entryPopupWindow > .entryEngineWorkspace_w > .entryCoordinateButtonWorkspace_w {\n    position: absolute;\n    right: 53px;\n    bottom: 12px;\n    margin: 0;\n    background-image: url('@{image_url}grid.png') !important;\n    background-size: 16px auto;\n}\n.entryPopupWindow > .entryEngineWorkspace_w > .entryCoordinateButtonWorkspace_w.toggleOn {\n    position: absolute;\n    right: 53px;\n    bottom: 12px;\n    margin: 0;\n    background-image: url('@{image_url}layers_icon_grid_nor_1.png') !important;\n    background-size: 16px auto;\n}\n\n.entryPopupWindow > .entryEngineWorkspace_w > .entryMaximizeButtonWorkspace_w {\n    position: absolute;\n    right: 6px;\n    bottom: 12px;\n    background-image: url('@{image_url}zoom_out_btn.png');\n    background-repeat: no-repeat;\n    background-size: 16px auto;\n}\n.entryPopupWindow > .entryEngineWorkspace_w > .entryEngineButtonWrapper {\n    display: block;\n    height: 48px;\n    border-top: 1px solid #d6e9f4;\n    box-sizing: border-box;\n    margin-top: 0;\n}\n\n.entryPopupWindow > .entryEngineWorkspace_w > .entryEngineButtonWrapper .entryRunButtonWorkspace_w,\n.entryPopupWindow > .entryEngineWorkspace_w > .entryEngineButtonWrapper .entryStopButtonWorkspace_w,\n.entryPopupWindow\n    > .entryEngineWorkspace_w\n    > .entryEngineButtonWrapper\n    .entryPauseButtonWorkspace_full,\n.entryPopupWindow\n    > .entryEngineWorkspace_w\n    > .entryEngineButtonWrapper\n    .entryRestartButtonWorkspace_full {\n    display: inline-block;\n    overflow: hidden;\n    flex: none;\n    width: auto;\n    height: auto;\n    border: 0;\n    margin-left: 24px;\n    border-radius: 0;\n    background: none;\n    font-size: 14px;\n    font-weight: 600;\n    color: #4f80ff;\n    line-height: 48px;\n}\n.entryPopupWindow\n    > .entryEngineWorkspace_w\n    > .entryEngineButtonWrapper\n    .entryRunButtonWorkspace_w:before,\n.entryPopupWindow\n    > .entryEngineWorkspace_w\n    > .entryEngineButtonWrapper\n    .entryRestartButtonWorkspace_full:before {\n    display: inline-block;\n    width: 14px;\n    height: 18px;\n    margin: 0 8px 0 0;\n    vertical-align: middle;\n    background-image: url('@{image_url}layers_icon_button_play_norx2.png');\n    background-repeat: no-repeat;\n    background-size: 14px auto;\n    content: '';\n}\n.entryPopupWindow\n    > .entryEngineWorkspace_w\n    > .entryEngineButtonWrapper\n    .entryStopButtonWorkspace_w:before {\n    display: inline-block;\n    width: 16px;\n    height: 16px;\n    margin: 0 8px 0 0;\n    vertical-align: middle;\n    background-image: url('@{image_url}layers_icon_button_stop_norx2.png');\n    background-repeat: no-repeat;\n    background-size: 16px auto;\n    content: '';\n}\n.entryPopupWindow\n    > .entryEngineWorkspace_w\n    > .entryEngineButtonWrapper\n    .entryPauseButtonWorkspace_full:before {\n    display: inline-block;\n    width: 16px;\n    height: 16px;\n    margin-right: 8px;\n    vertical-align: middle;\n    background-image: url('@{image_url}layers_icon_button_pause_norx2.png');\n    background-repeat: no-repeat;\n    background-size: 16px auto;\n    content: '';\n}\n\n.entryPopupWindow\n    > .entryEngineWorkspace_w\n    > .entryEngineButtonWrapper\n    > .entryAddButtonWorkspace_w {\n    display: none;\n}\n\n.entryEngineBlueWorkspace {\n    background-color: #61abdb;\n}\n\n.entryEngineButtonWorkspace {\n    border: none;\n    outline: none;\n    width: 25px;\n    height: 35px;\n    background-color: transparent;\n    background-repeat: no-repeat;\n    background-position: center;\n}\n\n.entryEngineButtonWorkspace_w {\n    border: none;\n    outline: none;\n    width: 25px;\n    height: 24px;\n    background-color: transparent;\n    background-repeat: no-repeat;\n    background-position: center;\n}\n\n.entryRunButtonPhone {\n    width: 100%;\n    height: 100%;\n    border: none;\n    background-color: transparent;\n    font-size: 12pt;\n    border-bottom: 2px solid #89c0d5;\n    .backgroundImage('layers_icon_button_play_nor.png');\n    background-position: 10px 50%;\n    background-repeat: no-repeat;\n}\n\n.entryStopButtonPhone {\n    width: 100%;\n    height: 100%;\n    border: none;\n    background-color: transparent;\n    font-size: 12pt;\n    border-bottom: 2px solid #89c0d5;\n    .backgroundImage('layers_icon_button_stop_nor.png');\n    background-position: 10px 50%;\n    background-repeat: no-repeat;\n}\n\n.entryRunButtonPhone.small {\n}\n\n.entryEnginePhone {\n    width: 100%;\n}\n\n.entryEngineHeaderPhone {\n    border-bottom: 1px solid #ccc;\n    width: 100%;\n    background-color: #fff;\n    height: 34px;\n}\n\n.entryEngineFooterPhone {\n    border-top: 1px solid #ccc;\n    width: 100%;\n    background-color: #fff;\n    height: 38px;\n}\n\n.entryMouseViewWorkspace {\n    position: relative;\n    font-size: 9pt;\n    margin: 0 auto;\n    width: 40%;\n    color: #61abdb;\n    line-height: 35px;\n    text-align: center;\n}\n\n.entryMouseViewWorkspace_w {\n    height: 32px;\n    font-size: 12px;\n    font-weight: bold;\n    margin: 0 auto;\n    padding: 10px 0 8px;\n    color: #4f80ff;\n    text-align: center;\n    letter-spacing: -0.4px;\n    line-height: 14px;\n\n    > input {\n        font-size: 10px;\n        line-height: 11px;\n        border: none;\n        font-weight: bold;\n        color: #555;\n        text-align: center;\n        letter-spacing: -0.4px;\n        user-select: none;\n    }\n}\n\n.entryEngineBlueWorkspace > .entryMouseViewWorkspace {\n    color: white;\n}\n\n.entryMaximizeButtonWorkspace {\n    float: left;\n    margin-left: 5px;\n    .backgroundImage('fullscreen_edit.png');\n}\n\n.entryMaximizeButtonPhone {\n    width: 20px;\n    height: 100%;\n    border: none;\n    float: right;\n    margin-right: 9px;\n    background-repeat: no-repeat;\n    background-position: center;\n    background-color: transparent;\n    .backgroundImage('layers_icon_fullmode01_nor.png');\n}\n\n.entryMaximizeButtonWorkspace_w {\n    float: right;\n    margin: 4px 6px 0 5px;\n    .backgroundImage('layers_icon_fullmode01_nor_1.png');\n    background-repeat: no-repeat;\n    background-size: 16px auto;\n}\n\n.entryEngineBlueWorkspace > .entryMaximizeButtonWorkspace {\n    .backgroundImage('fullscreen_play.png');\n}\n\n#entrySpeedPanelWorkspace {\n    width: 100%;\n    height: 0px;\n    background-color: #0e0;\n}\n\n.entrySpeedButtonWorkspace {\n    float: left;\n    background-size: contain;\n    width: 18px;\n    height: 16px;\n    margin-top: 8px;\n    margin-left: 10px;\n    .backgroundImage('speed_edit.png');\n    background-size: 18px auto;\n}\n\n.entrySpeedButtonWorkspace.on {\n    .backgroundImage('speed_edit_on.png');\n}\n\n.entryPopupWindow > div > .entrySpeedButtonWorkspace {\n    display: none;\n}\n\n.entryPopupWindow .entryMouseViewWorkspace_w {\n    position: absolute;\n    bottom: 0;\n    left: 50%;\n    width: 40%;\n    height: 48px;\n    margin: 0 auto;\n    padding: 0;\n    margin-left: -20%;\n    font-size: 14px;\n    font-weight: 600;\n    color: #4f80ff;\n    text-align: center;\n    line-height: 48px;\n}\n\n#entrySpeedProgressWorkspace {\n    overflow: hidden;\n    width: 100%;\n    height: 30px;\n    margin-top: 4px;\n    border-radius: 4px;\n    table-layout: fixed;\n    box-sizing: border-box;\n    border-spacing: 0;\n}\n#entrySpeedProgressWorkspace > tr > td {\n    height: 30px;\n    width: 20%;\n    cursor: pointer;\n}\n#entrySpeedProgressWorkspace .on {\n    background-size: 20px auto;\n    background-position: 50% 50%;\n    background-repeat: no-repeat;\n    .backgroundImage('ic_graph_chk.png');\n}\n\n#progressCell0 {\n    background-color: #cad8ff;\n}\n#progressCell1 {\n    background-color: #a7bfff;\n}\n#progressCell2 {\n    background-color: #95b3ff;\n}\n#progressCell3 {\n    background-color: #7299ff;\n}\n#progressCell4 {\n    background-color: #4f80ff;\n}\n\n#entrySpeedLabelWorkspace {\n    position: absolute;\n    left: 10px;\n    top: 12px;\n    font-size: 10px;\n    font-weight: 600;\n    color: #000;\n    letter-spacing: -0.4px;\n    line-height: 11px;\n}\n\n#entrySpeedHandleWorkspace {\n    position: absolute !important;\n    cursor: pointer;\n    width: 18px;\n    height: 16px;\n    top: 21px;\n    z-index: 100;\n    .backgroundImage('speed_handle.png');\n}\n.entrySpeedBox {\n    position: absolute;\n    box-sizing: border-box;\n    height: 39px;\n    margin: 0px 0 -1px;\n    padding: 0 10px 0 60px;\n    border: 1px solid #e2e2e2;\n    border-width: 1px 0;\n    background-color: #f9f9f9;\n    clear: both;\n    z-index: 10;\n}\n\n.entryCoordinateButtonWorkspace {\n    float: right;\n    .backgroundImage('coordinates_edit.png');\n}\n\n.entryCoordinateButtonWorkspace_w {\n    float: right;\n    margin-top: 4px;\n    .backgroundImage('layers_icon_grid_nor.png');\n    background-size: 16px auto;\n}\n\n.entryCoordinateButtonWorkspace.toggleOn {\n    .backgroundImage('coordinates_edit_on.png');\n}\n\n.entryCoordinateButtonWorkspace_w.toggleOn {\n    .backgroundImage('layers_icon_grid_nor_1.png');\n}\n\n.entryEngineBlueWorkspace > .entryCoordinateButtonWorkspace {\n    .backgroundImage('coordinates_play.png');\n}\n\n.entryEngineButtonWrapper {\n    display: flex;\n    margin: 0 -1px -1px;\n    margin-top: 12px;\n}\n\n.entryRunButtonWorkspace {\n    float: right;\n    width: 80px;\n    background-position: 7px 50%;\n    padding-right: 10px;\n    text-align: right;\n    font-size: 9pt;\n    color: #61abdb;\n    .backgroundImage('playbutton_edit.png');\n}\n\n.entryAddButtonWorkspace_w,\n.entryPauseButtonWorkspace_w,\n.entryRestartButtonWorkspace_w {\n    flex: none;\n    width: 50%;\n    height: 36px;\n    border: 1px solid #4f80ff;\n    border-radius: 4px;\n    background-color: #fff;\n    font-size: 12px;\n    font-weight: 600;\n    color: #4f80ff;\n    letter-spacing: -0.43px;\n    line-height: 34px;\n    text-align: center;\n    &:before {\n        .backgroundImage('layers_icon_button_plus_nor.png');\n        display: inline-block;\n        width: 12px;\n        height: 12px;\n        margin: 11px 2px 0 0;\n        background-size: 12px auto;\n        vertical-align: top;\n        content: '';\n    }\n}\n.entryRestartButtonWorkspace_w {\n    background-color: #4f80ff;\n    color: #fff;\n}\n.entryPauseButtonWorkspace_w:before {\n    .backgroundImage('layers_icon_button_pause_nor.png');\n}\n.entryRestartButtonWorkspace_w:before {\n    .backgroundImage('layers_icon_button_play_nor_1.png');\n    margin-right: 4px;\n}\n\n.entryRunButtonWorkspace_w {\n    flex: 1 1 auto;\n    position: relative;\n    height: 36px;\n    padding: 0;\n    margin-left: 4px;\n    border: 1px solid #4f80ff;\n    border-radius: 4px;\n    background-color: #4f80ff;\n    background-size: 10px auto;\n    font-size: 12px;\n    font-weight: 600;\n    color: #fff;\n    text-align: center;\n    line-height: 34px;\n    &:before {\n        .backgroundImage('layers_icon_button_play_nor_1.png');\n        display: inline-block;\n        width: 11px;\n        height: 12px;\n        background-size: 11px auto;\n        margin: 11px 4px 0 0;\n        vertical-align: top;\n        content: '';\n    }\n}\n\n.collapsed > .entryRunButtonWorkspace_w {\n    color: transparent;\n    background-position: 50% 43%;\n}\n\n.entryRunButtonWorkspace_w2 {\n    display: none;\n}\n\n.entryEngineBlueWorkspace > .entryRunButtonWorkspace {\n    .backgroundImage('playbutton_play.png');\n    color: white;\n}\n\n.entryStopButtonWorkspace {\n    float: right;\n    width: 80px;\n    background-position: 7px 50%;\n    border-top: 1px solid #ccc;\n    padding-right: 10px;\n    text-align: right;\n    font-size: 9pt;\n    color: #61abdb;\n    .backgroundImage('stopbutton_pause.png');\n}\n\n.entryStopButtonWorkspace_w {\n    flex: 1 1 auto;\n    position: relative;\n    height: 36px;\n    padding: 0;\n    margin-left: 4px;\n    border: 1px solid #4f80ff;\n    border-radius: 4px;\n    background-color: #fff;\n    background-size: 10px auto;\n    font-size: 12px;\n    font-weight: 600;\n    color: #4f80ff;\n    text-align: center;\n    line-height: 34px;\n    &:before {\n        .backgroundImage('layers_icon_button_stop_nor_2.png');\n        background-size: 12px auto;\n        display: inline-block;\n        width: 12px;\n        height: 12px;\n        margin: 10px 4px 0 0;\n        vertical-align: top;\n        content: '';\n    }\n}\n.entryStopButtonWorkspace_w2 {\n    display: none;\n}\n\n.entryEngineBigButtonMinimize_popup {\n    border: none;\n    display: none;\n    margin: 0;\n    padding: 0;\n    position: absolute;\n    left: 50%;\n    width: 111px;\n    height: 111px;\n    margin-left: -55.5px;\n    top: 50%;\n    margin-top: -55.5px;\n    background-repeat: no-repeat;\n    background-position: 40px center;\n    background-color: rgba(0, 0, 0, 0.5);\n    border-radius: 55px;\n}\n\n.entryEngineBigButtonMinimize_popup:hover {\n    opacity: 0.8;\n}\n\n.entryEngineBigButtonMinimize_popup:focus {\n    outline: none;\n}\n\n.entryEngineBigButtonMinimize_popup.entryEngineBigButtonMinimize_popup_run {\n    .backgroundImage('play_btn.png');\n}\n\n.entryPopupWindow .entryEngineBigButtonMinimize_popup {\n    display: block;\n}\n\n.entryPopupWindow .entryPauseButtonWorkspace_w {\n    flex: 2;\n    order: 2;\n    display: none;\n}\n\n.entryPopupWindow .entryRestartButtonWorkspace_w {\n    display: none;\n}\n\n.entryPauseButtonWorkspace_full {\n    display: none;\n}\n\n.entryRestartButtonWorkspace_full {\n    display: none;\n}\n\n.nav_right_wrapper {\n    right: 0;\n}\n\n.navbar-default {\n    background-color: #89c1e4;\n    border-color: #89c1e4;\n    /*background-color: #4accaa;\n    border-color: #4accaa;*/\n}\n\n#project_name.normal {\n    background-color: #89c1e4;\n    /*background-color: #4accaa;*/\n}\n\n.btn-group > .btn {\n    background-color: transparent;\n    border-color: transparent;\n    /*background-color: #4accaa;\n    border-color: #4accaa;*/\n}\n\n.art_project_name {\n    background-color: white !important;\n}\n\n.art_project_name:hover {\n    border: 1px solid #b4b4b4 !important;\n}\n\n.tablet {\n    .entrySpeedButtonWorkspace {\n        width: 27px;\n        height: 19px;\n        margin-top: 2px;\n        .backgroundImage('speed_edit_big.png');\n    }\n\n    .entrySpeedButtonWorkspace.on {\n        .backgroundImage('speed_edit_big.png');\n    }\n\n    .entryCoordinateButtonWorkspace_w {\n        .backgroundImage('layers_icon_grid_nor_big.png');\n    }\n\n    .entryMaximizeButtonWorkspace_w {\n        .backgroundImage('layers_icon_fullmode01_nor_1_big.png');\n    }\n}\n\n.entryPopupWindow.tablet {\n    .entryEngineWorkspace_w > .entryCoordinateButtonWorkspace_w {\n        bottom: 5px;\n        background-image: url('@{image_url}grid_big.png') !important;\n    }\n\n    .entryEngineWorkspace_w > .entryMaximizeButtonWorkspace_w {\n        right: 0;\n        bottom: 5px;\n        background-image: url('@{image_url}zoom_out_btn_big.png');\n    }\n}\n\n.practical_course_mode {\n    .entryRunButtonWorkspace_w {\n        border-color: @basePurple;\n        &:before {\n            .backgroundImage('layers_icon_button_play_nor_1.png');\n        }\n    }\n    .entryAddButtonWorkspace_w {\n        border-color: @basePurple;\n        &:before {\n            .backgroundImage('layers_icon_button_plus_nor_practical_course_mode.png');\n        }\n    }\n    .entryPauseButtonWorkspace_w {\n        border-color: @basePurple;\n        &:before {\n            .backgroundImage('layers_icon_button_pause_nor_practical_course_mode.png');\n        }\n    }\n\n    .entryStopButtonWorkspace_w {\n        border-color: @basePurple;\n        &:before {\n            .backgroundImage('layers_icon_button_stop_nor_2_practical_course_mode.png');\n        }\n    }\n}\n\n//audioShade\n.audioShadeCirclebox {\n    position: absolute;\n    margin: 0;\n    padding: 0;\n    background: rgba(255, 255, 255, 0.5);\n    text-align: center;\n    z-index: 10;\n    display: flex;\n    flex-direction: column;\n    -moz-flex-direction: column;\n    width: 100%;\n    height: calc(100%-32px);\n}\n.audioShadeCircle {\n    margin: auto;\n    margin-bottom: 6%;\n    padding: 0;\n    position: relative;\n    display: inline-block;\n    height: 34%;\n    width: auto;\n    aspect-ratio: 1 / 1;\n    border-radius: 50%;\n    background-color: #32d27d;\n    vertical-align: top;\n}\n.audioShadeInner {\n    margin: 0;\n    padding: 0;\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    width: 60%;\n    height: 60%;\n    margin: auto;\n    background-color: #32d27d;\n    border-radius: 50%;\n    transform: scale(0.5);\n    transform-origin: center center;\n    animation: ani 3s linear infinite;\n    content: '';\n}\n.audioShadeInner:nth-of-type(2) {\n    animation-delay: 1s;\n}\n.audioShadeInner:nth-of-type(3) {\n    animation-delay: 2s;\n}\n.audioShadeInner:nth-of-type(4) {\n    animation-delay: 3s;\n}\n.audioShadeImg {\n    margin: 0;\n    padding: 0;\n    position: absolute;\n    left: 23%;\n    top: 23%;\n    width: 54%;\n    height: 54%;\n    z-index: 10;\n}\n.audioShadeText {\n    width: 100%;\n    height: 20%;\n    font-family: NanumGothic, 'Nanum Gothic';\n    font-size: 1.1em;\n    font-weight: bold;\n    font-stretch: normal;\n    font-style: normal;\n    line-height: normal;\n    letter-spacing: normal;\n    text-align: center;\n}\n.audioProgress {\n    width: 64%;\n    height: 64%;\n    position: absolute;\n    left: 18%;\n    top: 18%;\n}\n\n@keyframes ani {\n    0% {\n        transform: scale(0.5);\n        opacity: 0;\n    }\n    50% {\n        opacity: 0.1;\n    }\n    70% {\n        opacity: 0.09;\n    }\n    100% {\n        transform: scale(3);\n        opacity: 0;\n    }\n}\n"
  },
  {
    "path": "src/css/components/extensions.less",
    "content": ".targetChecker {\n    height: 50px;\n    background-color: white;\n    border-bottom: 0.5px solid #5096f5;\n    cursor: pointer;\n    padding: 5px;\n}\n\n.targetChecker.success {\n    background-color: #5cb85c;\n}\n\n.targetChecker.fail {\n    background-color: #d9534f;\n}\n"
  },
  {
    "path": "src/css/components/function.less",
    "content": ".entryFunctionEdit {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    background-color: rgba(180,180,180, 0.4) !important;\n    z-index: 50;\n}\n\n.entryFunctionEdit {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    background-color: rgba(180,180,180, 0.4) !important;\n    z-index: 50;\n}\n\n#entryFunctionBtnWrapper {\n    position: absolute;\n    z-index: 100;\n    bottom: 90px;\n    margin: 0 auto;\n    left: 50%;\n}\n\n.entryFunctionBtn {\n    position: relative;\n    display: inline-block;\n    cursor: pointer;\n    border: solid 3px #888;\n    color: #666;\n    width: 55px; height: 55px;\n    border-radius: 27.5px;\n    text-align: center;\n    line-height: 48px;\n    left: -50%;\n}\n\n.entryFunctionBtn:hover {\n    border: solid 3px #555;\n    color: #222;\n}\n\n#entryFunctionCancel {\n}\n\n#entryFunctionSave {\n    margin-right: 20px;\n}\n"
  },
  {
    "path": "src/css/components/global_svg.less",
    "content": ".globalSvgSurface {\n    pointer-events: none;\n    position: fixed;\n    width: 100%;\n    height: 100%;\n    z-index: 10000;\n    top: 0;\n    left: 0;\n}\n\n#globalSvg {\n    position: fixed;\n    overflow: visible;\n    z-index: 10000;\n    opacity: 0.8;\n    will-change: transform;\n    max-width: 100%;\n    max-height: 100%;\n}\n"
  },
  {
    "path": "src/css/components/helper.less",
    "content": "/* helper */\n.entryBlockHelperIntro .renderViewContainer {\n    display: none;\n}\n\n#entryBlockHelperBlockWorkspace > .renderViewContainer {\n    width: 100%;\n\n    .renderView {\n        margin-right: 9px;\n    }\n}\n\n#entryBlockHelperBlockWorkspace > .renderViewContainer > svg {\n    overflow: visible;\n}\n\n/* helper */\n@keyframes blockHelperUp {\n    0% {\n        top: 100%;\n    }\n    100% {\n        top: 0%;\n    }\n}\n\n@-o-keyframes blockHelperUp {\n    0% {\n        top: 100%;\n    }\n    100% {\n        top: 0%;\n    }\n}\n\n@-ms-keyframes blockHelperUp {\n    0% {\n        top: 100%;\n    }\n    100% {\n        top: 0%;\n    }\n}\n\n@-moz-keyframes blockHelperUp {\n    0% {\n        top: 100%;\n    }\n    100% {\n        top: 0%;\n    }\n}\n\n@-webkit-keyframes blockHelperUp {\n    0% {\n        top: 100%;\n    }\n    100% {\n        top: 0%;\n    }\n}\n\n@keyframes blockHelperDown {\n    0% {\n        top: 0%;\n    }\n    100% {\n        top: 100%;\n    }\n}\n\n@-o-keyframes blockHelperDown {\n    0% {\n        top: 0%;\n    }\n    100% {\n        top: 100%;\n    }\n}\n\n@-ms-keyframes blockHelperDown {\n    0% {\n        top: 0%;\n    }\n    100% {\n        top: 100%;\n    }\n}\n\n@-moz-keyframes blockHelperDown {\n    0% {\n        top: 0%;\n    }\n    100% {\n        top: 100%;\n    }\n}\n\n@-webkit-keyframes blockHelperDown {\n    0% {\n        top: 0%;\n    }\n    100% {\n        top: 100%;\n    }\n}\n#entryBlockHelperWorkspaceWrapper {\n    background-color: #ecf8ff;\n    height: 100%;\n}\n\n#entryBlockHelperWorkspace {\n    position: absolute;\n    bottom: 0;\n    width: 100%;\n    height: 100%;\n    background-color: inherit;\n    .animation-name(blockHelperUp);\n    .animation-duration(0.6s);\n}\n\n#entryBlockHelperWorkspace.lecture {\n    .animation-duration(0s);\n}\n\n#entryBlockHelperWorkspace.dispose {\n    display: none;\n    .animation-name(blockHelperDown);\n}\n\n#entryBlockHelperHeaderWorkspace {\n    position: absolute;\n    width: 100%;\n    height: 40px;\n    background-color: #1bafea;\n    font-size: 16px;\n    line-height: 38px;\n    padding-left: 28px;\n    color: #fff;\n}\n\n#entryBlockHelperDisposeWorkspace {\n    float: right;\n    .backgroundImage('block_helper_dispose.png');\n    background-repeat: no-repeat;\n    background-position: center;\n    padding: 15px;\n    margin-top: 4px;\n    margin-right: 5px;\n}\n\n#entryBlockHelperContentWorkspace {\n    position: absolute;\n    width: 100%;\n    top: 40px;\n    bottom: 0px;\n    overflow-y: auto;\n    overflow-x: hidden;\n    white-space: pre-line;\n}\n\n.entryBlockHelperIntro {\n    .backgroundImage('block_help_icon_2.png');\n    background-size: 104px;\n    background-repeat: no-repeat;\n    background-position: center top;\n    margin-top: 64px;\n    padding-top: 100px;\n    text-align: center;\n    color: #707070;\n    font-size: 12px;\n}\n\n#entryBlockHelpBtn {\n    position: absolute;\n    .backgroundImage('block_help.png');\n    background-repeat: no-repeat;\n    background-position: center;\n    padding: 15px;\n    margin-top: 3px;\n    margin-left: 6px;\n    z-index: 100;\n}\n\n#entryBlockHelperBlockWorkspace {\n    width: 100%;\n    bottom: 0px;\n    overflow: hidden;\n    top: 16px;\n    text-align: center;\n}\n\n#entryBlockHelperBlockWorkspace > svg {\n    position: relative;\n}\n\n#entryBlockHelperDescriptionWorkspace {\n    line-height: 20px;\n    width: 100%;\n    font-size: 14px;\n    font-stretch: normal;\n    font-style: normal;\n    line-height: 18px;\n    letter-spacing: -0.33px;\n    padding: 0 20px;\n    color: #555555;\n    text-align: left;\n    margin-top: 24px;\n}\n\n.blockHelperLink {\n    width: 100%;\n    font-size: 14px;\n    font-stretch: normal;\n    font-style: normal;\n    line-height: 18px;\n    letter-spacing: -.33px;\n    padding: 0 20px;\n    color: #555;\n    text-align: left;\n    margin-top: 24px;\n}\n\n.linkTextElem {\n    font-size: 13px;\n    font-weight: bold;\n    color: #4F80FF;\n}\n\n.textModeElem {\n    display: none;\n}\n\n#entryBlockHelperContentWorkspace.textMode {\n    padding: 18px;\n    top: 0;\n\n    .textModeElem {\n        display: block;\n    }\n\n    .entryBlockHelperTitle {\n        font-family: EntryFont, NanumGothic, 'Nanum Gothic';\n        font-size: 18px;\n        font-weight: bold;\n        color: #3b3b3b;\n    }\n\n    .entryBlockHelperTitle:not(:first-child) {\n        margin-top: 20px;\n    }\n\n    .renderViewContainer {\n        text-align: left;\n        margin-top: 9px;\n    }\n\n    #entryBlockHelperBlockWorkspace {\n        height: auto;\n    }\n\n    #entryBlockHelperBlockWorkspace > div > svg {\n        position: relative;\n        left: auto;\n    }\n\n    #entryBlockHelperDescriptionWorkspace {\n        text-align: left;\n        padding: 0;\n    }\n\n    .entryBlockHelperContent {\n        font-family: EntryFont, NanumGothic, 'Nanum Gothic';\n        font-size: 14px;\n        color: #3b3b3b;\n        margin-top: 8px;\n    }\n\n    .entryBlockHelperElementsContainer {\n        .elementLeft {\n            display: inline-block;\n            vertical-align: top;\n        }\n\n        .elementRight {\n            display: inline-block;\n            margin-left: 15px;\n            max-width: 80%;\n        }\n    }\n\n    .entryBlockHelperElementsContainer:not(:first-child) {\n        margin-top: 12px;\n    }\n\n    #entryBlockHelperCodeMirrorContainer {\n        margin-top: 8px;\n    }\n}\n"
  },
  {
    "path": "src/css/components/hw_monitor.less",
    "content": ".hwMonitor {\n    background-color: #363c46;\n    position: absolute;\n}\n\n.hwComponent text {\n    font-size: 12px;\n}\n"
  },
  {
    "path": "src/css/components/object.less",
    "content": ".objectInfoView {\n    list-style: none;\n    padding: 0;\n    height: 60px;\n    width: 18px;\n    position: relative;\n    margin-left: 8px;\n    float: left;\n}\n\n.objectInfo_visible {\n    display: inline-block;\n    position: absolute;\n    top: 8px;\n    left: 0;\n    height: 18px;\n    width: 18px;\n    background-size: 18px auto;\n    cursor: pointer;\n    .box-sizing(border-box);\n    .backgroundImage('layers_icon_visible.png');\n}\n\n.objectInfo_unvisible {\n    .backgroundImage('layers_icon_unvisible.png');\n}\n\n.objectInfo_unlock {\n    display: inline-block;\n    position: absolute;\n    top: 34px;\n    left: 0;\n    height: 18px;\n    width: 18px;\n    background-size: 18px auto;\n    .backgroundImage('layers_icon_unlock.png');\n    cursor: pointer;\n    .box-sizing(border-box);\n}\n\n.objectInfo_lock {\n    .backgroundImage('layers_icon_lock.png');\n}\n\n.entryDisabled {\n    .objectInfo_visible {\n        .backgroundImage('layers_icon_visible_disabled.png');\n        cursor: default;\n    }\n    .objectInfo_unlock {\n        .backgroundImage('layers_icon_lock_disabled.png');\n        cursor: default;\n    }\n    .entryObjectDeleteWorkspace {\n        .backgroundImage('layers_icon_close_nor_new_disabled.png');\n        background-size: 24px auto;\n        cursor: default;\n    }\n    input {\n        color: #cbcbcb;\n    }\n    &.selectedObject {\n        .entryObjectWrapperWorkspace .entryObjectNameWorkspace {\n            color: #cbcbcb;\n        }\n    }\n}\n\n.entryObjectThumbnailWorkspace {\n    overflow: hidden;\n    cursor: move;\n    position: absolute;\n    top: 8px;\n    left: 34px;\n    width: 36px;\n    height: 40px;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px;\n    background-color: #fff;\n    background-size: 70%;\n    background-repeat: no-repeat;\n    background-position: center;\n    user-select: none;\n    -webkit-touch-callout: none;\n\n    &.entryObjectTextBox {\n        .backgroundImage('text_icon.svg');\n        background-size: cover;\n    }\n}\n\n.entryObjectWrapperWorkspace {\n    overflow: hidden;\n    position: relative;\n    margin: 16px 64px 0 76px;\n}\n\n.entryObjectNameWorkspace {\n    overflow: hidden;\n    box-sizing: border-box;\n    width: 100%;\n    padding: 7px 4px 6px;\n    border: 1px solid transparent;\n    border-radius: 4px;\n    background-color: transparent;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    white-space: nowrap;\n    text-overflow: ellipsis;\n    line-height: 12px;\n}\n\n.selectedObject {\n    .entryObjectNameWorkspace:focus {\n        border-color: #4f80ff;\n    }\n    .entryObjectNameWorkspace {\n        border-color: #aac5d5;\n        background-color: #f7fcff;\n    }\n}\n\n.editButtonToggle {\n    display: block;\n}\n.editButtonToggle_ {\n    display: none;\n}\n\n.selectedNotEditionObject {\n    background-color: transparent;\n}\n\n.selectedNotEditionObject:hover {\n    background-color: transparent;\n}\n\n.selectedNotEditionObject:focus {\n    background-color: transparent !important;\n}\n/*sj*/\n\n.selectedObject > .entryObjectWrapperWorkspace > .entryObjectNameWorkspace {\n    color: #2c313d;\n    font-family: EntryFont, NanumGothic, 'Nanum Gothic' !important;\n}\n\n.entryObjectNameWorkspace:disabled {\n    background-color: #fff;\n}\n\n.entryContainerListElementWorkspace.entryDisabled > .entryObjectWrapperWorkspace::before {\n    display: block;\n    content: \" \";\n    width: 100%;\n    height: 100%;\n    position: absolute;\n}\n\n.entryObjectDeleteWorkspace {\n    overflow: hidden;\n    position: absolute;\n    right: 3px;\n    top: 17px;\n    width: 24px;\n    height: 24px;\n    cursor: pointer;\n    background-size: 10px auto;\n    background-position: 50% 50%;\n    background-repeat: no-repeat;\n    .backgroundImage('layers_icon_close_nor_new.png');\n}\n\n.entryObjectDeletePhone {\n    float: left;\n    position: absolute;\n    width: 16px;\n    height: 16px;\n    right: 57px;\n    top: 25px;\n    cursor: pointer;\n    .backgroundImage('layers_icon_close_nor.png');\n}\n\n.entryObjectEditPhone {\n    float: left;\n    position: absolute;\n    width: 24px;\n    background-repeat: no-repeat;\n    height: 21px;\n    right: 17px;\n    background-color: transparent;\n    border: none;\n    top: 21px;\n    cursor: pointer;\n    .backgroundImage('glyphicons_150_edit.png');\n}\n\n.entryObjectSelectedImgWorkspace {\n    position: absolute;\n    width: 16px;\n    right: 0;\n    top: 45px;\n    bottom: 0;\n    cursor: col-resize;\n    .backgroundImage('entry_scroll.png');\n    background-repeat: no-repeat;\n    background-size: 6px auto;\n    background-position: 50% 50%;\n    z-index: 250;\n    &.enabled {\n        .backgroundImage('entry_scroll_enable.png')\n    }\n}\n\n.selectedObject .entryObjectSelectedImgWorkspace {\n    float: left;\n    position: absolute;\n    width: 14px;\n    height: 26px;\n    right: 0;\n    top: 20px;\n    cursor: col-resize;\n    .backgroundImage('entry_scroll.png');\n}\n\n.entryObjectCoordinateWorkspace {\n    display: block;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.4px;\n    width: auto;\n}\n.entryObjectCoordinateWorkspaceWrapper,\n.entryObjectCoordinateSizeWrapper {\n    display: inline-block;\n    position: relative;\n    margin-left: 6px;\n    vertical-align: top;\n    &:first-of-type {\n        margin-left: 0;\n    }\n}\n.entryObjectCoordinateSizeWrapper {\n    margin-left: 12px;\n}\n\n\n.entryObjectCoordinateSpanWorkspace {\n    position: absolute;\n    right: 6px;\n    top: 7px;\n    font-size: 10px;\n    font-weight: 600;\n    color: #979797;\n    &.degree {\n        top: 6px;\n        width: 4px;\n        height: 4px;\n        border: solid 1px #979797;\n        border-radius: 50%;\n    }\n}\n\n.selectedObject > .entryObjectWrapperWorkspace > .entryObjectCoordinateWorkspace {\n    color: black;\n}\n\n.entryObjectInformationWorkspace {\n    position: absolute;\n    right: 32px;\n    top: 18px;\n    width: 24px;\n    height: 24px;\n    background-size: 10px auto;\n    background-repeat: no-repeat;\n    background-position: center;\n    cursor: pointer;\n    .backgroundImage('layers_arrow_down_nor.png');\n}\n\n.selectedObject .entryObjectInformationWorkspace {\n    .backgroundImage('layers_arrow_up_nor.png');\n}\n\n.fold .entryObjectInformationWorkspace {\n    .backgroundImage('layers_arrow_down_nor.png');\n}\n\n.informationToggle > .entryObjectWrapperWorkspace > .entryObjectInformationWorkspace {\n    .backgroundImage('layers_arrow_down_nor_1.png');\n}\n\n.entryObjectButtonWorkspace {\n    display: none;\n    float: right;\n    position: relative;\n    width: 40px;\n    height: 40px;\n    background-color: #bcc3c9;\n    border-radius: 50%;\n    margin: 10px 10px 10px 5px;\n    background-position: center;\n    background-repeat: no-repeat;\n    background-position: 50% 35%;\n    color: white;\n    font-size: 7.5pt;\n    padding: 23px 0 0 0;\n    text-align: center;\n    outline: none;\n    border: none;\n}\n\n.informationToggle > .entryObjectButtonWorkspace {\n    display: none;\n}\n\n.entryObjectSoundWorkspace {\n    .backgroundImage('icon_sound.png');\n    background-color: #6a9a1f;\n}\n\n.entryObjectSoundWorkspace:hover {\n    background-color: #83af3d;\n}\n\n.entryObjectPictureWorkspace {\n    .backgroundImage('icon_picture.png');\n    background-color: #f26724;\n}\n\n.entryObjectPictureWorkspace:hover {\n    background-color: #f3783c;\n}\n\n.entryObjectCodeWorkspace {\n    .backgroundImage('icon_code.png');\n    background-color: #00ace9;\n}\n\n.entryObjectCodeWorkspace:hover {\n    background-color: #5fc8ee;\n}\n\n.entryObjectTextWorkspace {\n    .backgroundImage('text_icon_white.png');\n    background-color: #f3bb1d;\n    background-position: 50% 20%;\n    background-size: 75%;\n}\n\n.entryObjectRotationWrapperWorkspace {\n    position: relative;\n    display: none;\n    margin: 10px 10px 0;\n    padding-top: 9px;\n    border-top: 1px solid #aac5d5;\n    clear: both;\n}\n\n.collapsed .entryObjectRotationWrapperWorkspace {\n    height: 90px;\n}\n\n.selectedObject .entryObjectRotationWrapperWorkspace {\n    display: block;\n}\n\n.fold .entryObjectRotationWrapperWorkspace {\n    display: none;\n}\n\n.informationToggle > .entryObjectRotationWrapperWorkspace {\n    display: inline-block;\n}\n\n.rotationMethodWrapper {\n    display: inline-block;\n    position: relative;\n    margin-left: 12px;\n    padding-bottom: 32px;\n    vertical-align: top;\n}\n\n.collapsed .rotationMethodWrapper {\n    float: left;\n    position: absolute;\n    bottom: 9px;\n}\n\n.entryObjectRotateMethodLabelWorkspace {\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 13px;\n    font-size: 10px;\n    font-weight: 600;\n    color: #2c313d;\n    line-height: 12px;\n    text-align: center;\n    vertical-align: top;\n}\n\n.entryObjectRotateLabelWrapperWorkspace {\n    position: relative;\n    margin-top: 8px;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n}\n.entryObjectRotateWorkspaceWrapper,\n.entryObjectDirectionWorkspaceWrapper {\n    position: relative;\n    display: inline-block;\n    margin-left: 6px;\n    padding-bottom: 32px;\n    vertical-align: top;\n    &:first-of-type,\n    &.entryRemove + .entryObjectDirectionWorkspaceWrapper {\n        margin-left: 0;\n    }\n}\n\n.entryObjectRotateInputWorkspace,\n.entryObjectDirectionInputWorkspace {\n    width: 60px;\n    height: 24px;\n    box-sizing: border-box;\n    padding: 0 13px 0 8px;\n    background-color: #fff;\n    border: 1px solid #aac5d5;\n    border-radius: 4px;\n    font-size: 10px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.4px;\n    text-align: left;\n}\n.entryObjectRotateInputWorkspace:focus,\n.entryObjectRotateInputWorkspace:active,\n.entryObjectDirectionInputWorkspace:focus,\n.entryObjectDirectionInputWorkspace:active {\n    border-color: #4f80ff;\n}\n\n.entryObjectDirectionSpanWorkspace,\n.entryObjectRotateSpanWorkspace {\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 13px;\n    font-size: 10px;\n    font-weight: 600;\n    color: #2c313d;\n    text-align: center;\n    line-height: 12px;\n}\n.entryObjectRotateInputWorkspace + .entryObjectDirectionSpanWorkspace {\n    margin-left: 10px;\n}\n.entryObjectRotateInputWorkspace.entryRemove + .entryObjectDirectionSpanWorkspace {\n    margin-left: 0;\n}\n\n.entryObjectRotateModeWorkspace {\n    cursor: pointer;\n    display: inline-block;\n    width: 24px;\n    height: 24px;\n    vertical-align: top;\n    background-size: 24px auto;\n}\n\n.entryObjectRotateModeAWorkspace {\n    .backgroundImage('layers_icon_rotate01_nor.png');\n}\n\n.entryObjectRotateModeAWorkspace.selected {\n    .backgroundImage('layers_icon_rotate01_sel.png');\n}\n\n.entryObjectRotateModeBWorkspace {\n    margin-left: 6px;\n    .backgroundImage('layers_icon_rotate02_nor.png');\n}\n\n.entryObjectRotateModeBWorkspace.selected {\n    .backgroundImage('layers_icon_rotate02_sel.png');\n}\n\n.entryObjectRotateModeCWorkspace {\n    margin-left: 6px;\n    .backgroundImage('layers_icon_rotate03_nor.png');\n}\n\n.entryObjectRotateModeCWorkspace.selected {\n    .backgroundImage('layers_icon_rotate03_sel.png');\n}\n\n.entryObjectCoordinateSizeWorkspace {\n    display: inline-block;\n    position: relative;\n    margin-right: 6px;\n    font-size: 10px;\n    font-weight: 600;\n    vertical-align: top;\n    line-height: 24px;\n}\n\n.entryObjectCoordinateInputWorkspace {\n    width: 60px;\n    height: 24px;\n    padding: 0 13px 0 8px;\n    background-color: #fff;\n    border: 1px solid #aac5d5;\n    border-radius: 4px;\n    font-size: 10px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.4px;\n    text-align: left;\n    box-sizing: border-box;\n}\n.entryObjectCoordinateInputWorkspace:focus,\n.entryObjectCoordinateInputWorkspace:active {\n    border-color: #4f80ff;\n}\n\n.entryObjectCoordinateInputWorkspace_size {\n    float: none;\n    position: relative;\n}\n"
  },
  {
    "path": "src/css/components/painter.less",
    "content": ".entryPlaygroundPainter {\n    position: absolute;\n    left: 253px;\n    top: 0;\n    bottom: 0;\n    right: 0;\n    border-left: none;\n    background-color: #f9f9f9;\n    &.fullscreen {\n        min-height: 547px;\n        top: 42px;\n        left: 0;\n        z-index: 251;\n    }\n\n    .ControlPanel {\n        button {\n            vertical-align: top;\n        }\n    }\n}"
  },
  {
    "path": "src/css/components/pdf.less",
    "content": "#entryPdfWorkspace:extend(#entryBlockHelperWorkspace) {\n    iframe {\n         width: 100%;\n         height: 100%;\n    }\n}\n"
  },
  {
    "path": "src/css/components/playground.less",
    "content": ".entryPlayground_text_buttons {\n    display: inline-block;\n    list-style-type: none;\n    margin: 0;\n    padding: 0;\n}\n\n.entryPlayground_text_buttons > li {\n    float: left;\n    width: 32px;\n    height: 32px;\n    margin-left: 2px;\n    cursor: pointer;\n}\n\n.entryPlaygroundTextAlignLeft {\n    .backgroundImage('text_align_left_off.png');\n}\n.entryPlaygroundTextAlignLeft.toggle {\n    .backgroundImage('text_align_left_on.png');\n}\n\n.entryPlaygroundTextAlignCenter {\n    .backgroundImage('text_align_center_off.png');\n}\n.entryPlaygroundTextAlignCenter.toggle {\n    .backgroundImage('text_align_center_on.png');\n}\n\n.entryPlaygroundTextAlignRight {\n    .backgroundImage('text_align_right_off.png');\n}\n.entryPlaygroundTextAlignRight.toggle {\n    .backgroundImage('text_align_right_on.png');\n}\n\n.entryPlayground_fgColorDiv {\n    position: absolute;\n    width: 15px;\n    height: 4px;\n    margin-top: -10px;\n    margin-left: 8px;\n}\n\n.entryPlayground_bgColorDiv {\n    position: absolute;\n    width: 15px;\n    height: 4px;\n    margin-top: -10px;\n    margin-left: 8px;\n}\n.entryPlayground_textBox {\n    margin-top: 5px;\n    height: 33px;\n    width: 400px;\n}\n.entryPlayground_textArea {\n    margin-top: 5px;\n    height: 120px;\n    width: 400px;\n    resize: none;\n}\n\n.entryPlaygroundFontSizeWrapper {\n    position: absolute;\n    padding-left: 13px;\n    padding-top: 10px;\n    display: inline-block;\n    width: 244px;\n    height: 40px;\n    border-radius: 4px;\n    background-color: #ffffff;\n    right: 0px;\n    top: 0px;\n}\n\n.entryPlaygroundFontSizeLabel {\n    display: inline-block;\n    width: 65px;\n    height: 15px;\n    font-size: 14px;\n    font-weight: bold;\n    font-style: normal;\n    font-stretch: normal;\n    line-height: normal;\n    letter-spacing: -0.3px;\n    color: #2c313d;\n}\n\n#entryTextColourTable {\n    margin-top: 12px;\n    cursor: pointer;\n    border-collapse: collapse;\n}\n\n.entryTd {\n    width: 22px;\n    height: 22px;\n}\n\n.entryTdTransparent {\n    width: 20px;\n    height: 20px;\n    background-color: white;\n    background-image: -webkit-linear-gradient(\n        135deg,\n        transparent 11.5px,\n        rgb(255, 0, 0) 13px,\n        rgba(255, 255, 255, 0.5) 14.5px\n    );\n    border: 1px solid;\n}\n\n.entryPlaygroundSoundLength {\n    margin-top: 6px;\n    font-size: 10px;\n    line-height: 11px;\n}\n\n.entryPlaygroundDefaultWorkspace {\n    height: 100%;\n    background-color: white;\n    color: white;\n}\n\n@introHeight: 66px;\n.entryPlaygroundIntro.active {\n    position: relative;\n    overflow: hidden;\n    height: @introHeight;\n    top: 50px;\n    z-index: 1;\n}\n\n.entryPlaygroundWorkspace {\n    position: relative;\n    overflow: hidden;\n    height: 100%;\n    background-color: #fff;\n}\n\n.entryPlaygroundIntro.active + .entryPlaygroundWorkspace {\n    height: calc(100% - @introHeight);\n}\n\n.entryPlaygroundPhone {\n    width: 100%;\n    height: 500px;\n    background-color: #f5f5f5;\n}\n\n.entryPlaygroundResizeWorkspace {\n    position: absolute;\n    top: 50%;\n    height: 62px;\n    width: 36px;\n    left: 311px;\n    margin-top: -20px;\n    cursor: pointer;\n    border-left: none;\n    z-index: 1;\n    .backgroundImage('entry_scroll_02.svg');\n    background-size: 36px auto;\n    &.highIndex {\n        z-index: 300;\n    }\n    &.folding {\n        z-index: 253;\n        .animation-duration(0.7s);\n        .animation-name(foldBlockly);\n        .animation-fill-mode(forwards);\n        .backgroundImage('entry_scroll_03.svg');\n    }\n    &.unfolding {\n        .animation-duration(0.7s);\n        .animation-name(unfoldBlockly);\n        .animation-fill-mode(forwards);\n        .backgroundImage('entry_scroll_02.svg');\n    }\n}\n\n@keyframes unfoldBlockly {\n    from {left: 58px;}\n    to {left: 311px;}\n}\n\n@keyframes foldBlockly {\n    from {}\n    to {left: 58px;}\n}\n\n\n.entryPlaygroundTabWorkspace {\n    position: absolute;\n    left: 0;\n    top: 46px;\n    background-color: #fff;\n}\n\n.entryPlaygroundTabWorkspace.entryRemove {\n    display: block !important;\n}\n\n.entryPlaygroundTabPhone {\n    width: 100%;\n    height: 43px;\n    position: relative;\n    background-color: #f1f1f1;\n}\n\n.entryPlaygroundBackPackView {\n    height: calc(100% - 47px);\n    display: block;\n    right: 0;\n    top: 38px;\n    z-index: 299;\n    position: absolute;\n\n    .widget {\n        height: 100%;\n    }\n\n    .blockBackPackDrop,\n    .objectBackPackDrop {\n        position: fixed;\n        display: none;\n        top: 0;\n        left: 0;\n        z-index: 400;\n        background-color: rgba(248, 241, 204, 0.9);\n        border: 2px dashed #ffc800;\n        justify-content: center;\n        align-items: center;\n        flex-direction: column;\n\n        .blockBackPackIcon {\n            pointer-events: none;\n            width: 32px;\n            height: 32px;\n            margin-bottom: 11px;\n            .backgroundImage('img_backpack_plus.svg');\n        }\n        .objectBackPackDesc,\n        .blockBackPackDesc {\n            pointer-events: none;\n            font-family: EntryFont, NanumGothic, 'Nanum Gothic';\n            font-size: 12px;\n            font-weight: bold;\n            letter-spacing: -0.1px;\n            white-space: pre;\n            text-align: center;\n            color: #2c313d;\n        }\n    }\n}\n\n.entryPlaygroundButtonTabWorkspace {\n    position: absolute;\n    right: 0;\n    top: 43px;\n    height: auto;\n    background-color: #fff;\n\n    .entryPlaygroundCommentButtonWorkspace {\n        float: left;\n        background-repeat: no-repeat;\n        background-size: 32px auto;\n        background-position: 50% 50%;\n        cursor: pointer;\n        width: 32px;\n        height: 32px;\n\n        &.enabled {\n            background-size: 32px auto;\n            width: 32px;\n            height: 32px;\n            border: 0;\n            background-color: inherit;\n        }\n\n        &.showComment {\n            margin-right: 4px;\n            .backgroundImage('btn-toggle-comment-off.svg');\n            &.enabled {\n                .backgroundImage('btn-toggle-comment-select.svg');\n            }\n        }\n\n        &.addComment {\n            margin-right: 8px;\n            .backgroundImage('btn-add-comment-off.svg');\n            &.enabled {\n                .backgroundImage('btn-add-comment-select.svg');\n            }\n        }\n    }\n\n    .entryPlaygroundBackPackButtonWorkspace {\n        &::before {\n            content: '';\n            display: inline-block;\n            width: 1px;\n            height: 16px;\n            background: #bfd8e6;\n            margin: 8px 0 0 -9px;\n        }\n        float: left;\n        .backgroundImage('back_pack_button.svg');\n        background-repeat: no-repeat;\n        background-size: 32px auto;\n        background-position: 50% 50%;\n        cursor: pointer;\n        width: 32px;\n        height: 32px;\n        margin: 0 9px;\n    }\n\n    &.entryRemove.entryCode {\n        display: block !important;\n    }\n}\n\n.entryTabListWorkspace {\n    overflow: hidden;\n    list-style: none;\n    padding: 0;\n    margin: 0;\n}\n\n.entryTabListItemWorkspace {\n    float: left;\n    min-width: 58px;\n    margin-left: 2px;\n    padding: 0;\n    cursor: pointer;\n    background-color: #d7e8f4;\n    border-top-right-radius: 6px;\n    border-top-left-radius: 6px;\n    font-size: 12px;\n    font-weight: 600;\n    color: #8ba4b3;\n    text-align: center;\n    letter-spacing: -0.4px;\n    line-height: 32px;\n}\n.entryTabListItemWorkspace:first-child {\n    margin-left: 0;\n}\n\n.entryTabSelected {\n    color: #fff;\n    background-color: @baseblue;\n    font-size: 14px;\n}\n\n.entryTabListItemWorkspace:hover {\n}\n\n#entrySoundTab {\n    .animation-delay(0.1s);\n}\n#entryPictureTab.hideTab,\n#entryTextTab.hideTab {\n    .animation-delay(0.2s);\n}\n#entrySoundTab.hideTab {\n    .animation-delay(0.1s);\n}\n#entryVariableTab.showTab {\n    .animation-delay(0.2s);\n}\n\n.hideTab {\n    .animation-duration(0.7s);\n    .animation-name(hideTab);\n    .animation-fill-mode(forwards);\n}\n\n@keyframes hideTab {\n    from {\n    }\n    to {\n        margin-top: 44px;\n        opacity: 0;\n    }\n}\n\n@-webkit-keyframes hideTab {\n    from {\n    }\n    to {\n        margin-top: 44px;\n        opacity: 0;\n    }\n}\n\n.showTab {\n    opacity: 0;\n    .animation-duration(0.7s);\n    .animation-name(showTab);\n    .animation-fill-mode(forwards);\n}\n\n@keyframes showTab {\n    from {\n        margin-top: 44px;\n        opacity: 0;\n    }\n    to {\n        opacity: 1;\n    }\n}\n\n@-webkit-keyframes showTab {\n    from {\n        margin-top: 44px;\n        opacity: 0;\n    }\n    to {\n        opacity: 1;\n    }\n}\n\n.entryPlaygroundCurtainWorkspace {\n    position: absolute;\n    background-color: black;\n    color: white;\n    padding-top: 270px;\n    text-align: center;\n    font-size: 40px;\n    top: 38px;\n    left: 0;\n    right: 0;\n    bottom: 8px;\n    opacity: 0.5;\n    z-index: 500;\n    cursor: pointer;\n    white-space: pre-line;\n}\n\n.entryPlaygroundCurtainPhone {\n    position: absolute;\n    background-color: rgba(0, 0, 0, 0.8);\n    color: white;\n    padding-top: 100px;\n    text-align: center;\n    font-size: 17px;\n    height: 110%;\n    width: 100%;\n    opacity: 0.5;\n    z-index: 5000;\n    cursor: pointer;\n}\n\n.entryPlaygroundPictureCurtainWorkspace {\n    position: absolute;\n    background-color: black;\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    opacity: 0.6;\n    z-index: 255;\n    border-radius: 0 0 0 6px;\n}\n\n.entryPlaygroundPictureCurtainWorkspace .entryPlaygroundPictureCurtainWorkspaceText {\n    text-align: center;\n    height: 100%;\n    color: white;\n    font-family: NanumGothic, 'Nanum Gothic';\n    font-size: 24px;\n    font-weight: bold;\n    line-height: 1.33;\n    letter-spacing: -0.6px;\n    display: flex;\n    justify-content: center; /* align horizontal */\n    align-items: center; /* align vertical */\n    white-space: pre-line;\n}\n\n.entryPlaygroundTableCurtainWorkspace {\n    position: absolute;\n    background-color: black;\n    top: 0;\n    left: 0;\n    right: 0;\n    bottom: 0;\n    opacity: 0.6;\n    z-index: 255;\n    border-radius: 0 0 0 6px;\n}\n\n.entryPlaygroundTableCurtainWorkspace .entryPlaygroundTableCurtainWorkspaceText {\n    text-align: center;\n    height: 100%;\n    color: white;\n    font-family: NanumGothic, 'Nanum Gothic';\n    font-size: 24px;\n    font-weight: bold;\n    line-height: 1.33;\n    letter-spacing: -0.6px;\n    display: flex;\n    justify-content: center; /* align horizontal */\n    align-items: center; /* align vertical */\n}\n\n.entryPlaygroundCodeWorkspace {\n    overflow: unset;\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 80px;\n    bottom: 8px;\n    background-color: #fff;\n    border-radius: 0 0 0 6px;\n}\n\n.entryPlaygroundCodeWorkspace.entryRemove {\n    display: block !important;\n    visibility: hidden;\n}\n\n.entryPlaygroundCodePhone {\n    position: relative;\n    height: 100%;\n    background-color: #f5f5f5;\n}\n\n.entryPlaygroundCodePhone.entryRemove {\n    display: block !important;\n    visibility: hidden;\n}\n\n.entryPlaygroundPicturePhone {\n    margin-left: 0;\n    height: 100%;\n    background-color: #ececec;\n}\n\n.entryPlaygroundPictureWorkspace {\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 8px;\n    background-color: #f9f9f9;\n    top: 80px;\n    margin-left: 0;\n    border-radius: 0 0 0 6px;\n}\n\n.entryPlaygroundAddPicture {\n    width: 254px;\n    padding: 8px 0 7px;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n}\n\n.entryPlaygroundAddPicturePhone {\n    position: relative;\n    padding: 0;\n    margin: 0;\n    height: 50px;\n    cursor: pointer;\n    border-bottom: 1pt solid #ebeff1;\n}\n\n.entryPlaygroundAddPictureInner {\n    display: inline-block;\n    width: 116px;\n    height: 40px;\n    margin-left: 7px;\n    background-color: #fff;\n    border: 1px solid #4f80ff;\n    border-radius: 4px;\n    color: #4f80ff;\n    text-align: center;\n    font-size: 12px;\n    font-weight: 600;\n    line-height: 38px;\n    cursor: pointer;\n}\n\n.entryPlaygroundNewPictureInner {\n    display: inline-block;\n    width: 116px;\n    height: 40px;\n    margin-left: 6px;\n    background-color: #fff;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px;\n    color: #555;\n    text-align: center;\n    font-size: 12px;\n    font-weight: 600;\n    line-height: 38px;\n    cursor: pointer;\n}\n\n.entryPlaygroundAddPictureInnerPhone {\n    display: block;\n    height: 50px;\n    background-color: #cdcfc9;\n    color: #656565;\n    text-align: center;\n    font-size: 10.5pt;\n    line-height: 36px;\n    border: 2px dashed #737373;\n    width: 240px;\n    padding: 8px 10px 12px 10px;\n}\n\n.entryPlaygroundPictureList {\n    position: absolute;\n    padding: 0px;\n    margin: 0px;\n    width: 254px;\n    top: 56px;\n    bottom: 0px;\n    overflow-y: hidden;\n    list-style: none;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n    border-radius: 0 0 0 6px;\n}\n\n.entryPlaygroundPictureListPhone {\n    position: absolute;\n    padding: 0px;\n    margin: 0px;\n    width: 254px;\n    top: 56px;\n    bottom: 0px;\n    overflow: auto;\n    list-style: none;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n}\n\n.entryPlaygroundPictureElement {\n    display: block;\n    position: relative;\n    background-color: #ecf8ff;\n    border-bottom: 1px solid #d6e9f4;\n    padding: 0 56px 0 64px;\n    height: 61px;\n    color: #2c313d;\n    cursor: pointer;\n}\n\n.entryPlaygroundPictureElement::-moz-selection {\n    cursor: move;\n    background-color: #fff;\n}\n\n.entryPlaygroundPictureElement::selection {\n    cursor: move;\n    background-color: #fff;\n}\n\n.entryPlaygroundPictureOrder,\n.entryPlaygroundSoundOrder {\n    overflow: hidden;\n    position: absolute;\n    left: 19px;\n    top: 11px;\n    width: 14px;\n    height: 14px;\n    background-color: #4f80ff;\n    border-radius: 50%;\n    font-size: 10px;\n    color: #fff;\n    text-align: center;\n    line-height: 16px;\n    z-index: 10;\n}\n\n.entryPictureSelected {\n    background-color: #fff;\n}\n\n.entryPlaygroundPictureThumbnail {\n    position: absolute;\n    height: 44px;\n    width: 40px;\n    top: 8px;\n    left: 16px;\n    border: 1px solid #e2e2e2;\n    background-color: #fff;\n    border-radius: 4px;\n    background-size: contain;\n    background-repeat: no-repeat;\n    background-position: 50% 50%;\n    user-select: none;\n    -webkit-touch-callout: none;\n}\n\n.entryPlaygroundPictureName {\n    width: 100%;\n    height: 24px;\n    margin-top: 10px;\n    padding: 0 4px;\n    background-color: #fff;\n    outline: 0;\n    font-size: 12px;\n    text-overflow: ellipsis;\n    color: #2c313d;\n    font-weight: 600;\n    cursor: text;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px;\n    box-sizing: border-box;\n}\n.entryPlaygroundPictureName:focus,\n.entryPlaygroundPictureName:active {\n    border-color: #4f80ff;\n}\n\n.entryPlaygroundPictureSize {\n    margin-top: 6px;\n    font-size: 10px;\n    line-height: 11px;\n}\n.entryPlayground_del {\n    position: absolute;\n    right: 26px;\n    top: 18px;\n    width: 24px;\n    height: 24px;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px;\n    background-color: #fff;\n    background-size: 10px;\n    font-size: 0;\n    cursor: pointer;\n    background-size: 10px auto;\n    background-position: 50% 50%;\n    background-repeat: no-repeat;\n    .backgroundImage('layers_icon_close_nor_new.png');\n}\n\n.pop_selectbox {\n    position: relative;\n    .select_link {\n        display: block;\n        position: relative;\n        width: 142px;\n        height: 38px;\n        padding: 0 12px;\n        border: 1px solid #e2e2e2;\n        background-color: #fff;\n        border-radius: 4px;\n        font-weight: 600;\n        color: #555;\n        letter-spacing: -0.3px;\n        line-height: 40px;\n        cursor: pointer;\n    }\n    .select_link:after {\n        position: absolute;\n        right: 16px;\n        top: 50%;\n        width: 8px;\n        height: 6px;\n        margin-top: -3px;\n        vertical-align: top;\n        content: '';\n    }\n    & + .pop_selectbox {\n        margin-top: 40px;\n    }\n    & + .on {\n        z-index: 10;\n    }\n    & + .pop_inpt_text {\n        margin-top: 40px;\n    }\n    &.error .select_link {\n        border-color: #f00;\n    }\n}\n.pop_selectbox * {\n    box-sizing: content-box;\n}\n.pop_selectbox .tooltip_box {\n    display: none;\n}\n.pop_selectbox.on .tooltip_box {\n    display: block;\n    z-index: 10;\n    top: 52px;\n}\n\n.entryPlaygroundTextWorkspace {\n    position: absolute;\n    top: 80px;\n    left: 0;\n    right: 0;\n    bottom: 8px;\n    background-color: #ecf8ff;\n    border-radius: 0 0 0 6px;\n}\n// 글상자\n.entryPlaygroundTextWorkspace .write_box {\n    height: 568px;\n}\n.entryPlaygroundTextWorkspace .write_box .write_set {\n    position: relative;\n    padding: 8px 18px;\n    background-color: #f9f9f9;\n    border: 1px solid #e2e2e2;\n    z-index: 10;\n}\n.entryPlaygroundTextWorkspace .write_box .write_set:after {\n    display: block;\n    clear: both;\n    content: '';\n}\n.entryPlaygroundTextWorkspace .write_box .write_set .pop_selectbox {\n    float: left;\n    width: 168px;\n}\n.entryPlaygroundTextWorkspace .write_box .write_set .pop_selectbox .tooltip_inner {\n    max-height: 282px;\n    overflow: visible;\n    overflow-y: auto;\n}\n\n.entryPlaygroundTextWorkspace .write_box .write_set .font_style_box {\n    position: relative;\n    float: left;\n    padding-left: 24px;\n    font-size: 0;\n}\n\n.entryPlaygroundTextWorkspace .write_box .write_set .font_style_box .style_link {\n    display: inline-block;\n    overflow: hidden;\n    width: 40px;\n    height: 40px;\n    margin-left: 10px;\n    border: 1px solid #e2e2e2;\n    background-color: #fff;\n    border-radius: 4px;\n    cursor: pointer;\n}\n.entryPlaygroundTextWorkspace .write_box .write_set .font_style_box .style_link.on {\n    border: 1px solid #4f80ff;\n}\n.entryPlaygroundTextWorkspace .write_box .input_box .write_type_box {\n    display: inline-block;\n    border-radius: 4px;\n    width: 207px;\n    height: 40px;\n    font-size: 0;\n}\n.entryPlaygroundTextWorkspace .write_box .input_box .write_type_box a {\n    display: inline-block;\n    position: relative;\n    width: 102px;\n    height: 38px;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px 0 0 4px;\n    font-size: 14px;\n    font-weight: 600;\n    color: #979797;\n    background-color: #fff;\n    text-align: center;\n    letter-spacing: -0.3px;\n    line-height: 36px;\n    cursor: pointer;\n}\n.entryPlaygroundTextWorkspace .write_box .input_box .write_type_box a + a {\n    margin-left: -1px;\n    border-radius: 0 4px 4px 0;\n}\n.entryPlaygroundTextWorkspace .write_box .input_box .write_type_box .on {\n    color: #4f80ff;\n    border-color: #4f80ff;\n    z-index: 10;\n}\n.entryPlaygroundTextWorkspace .write_box .input_box {\n    margin: 24px 38px 0;\n    max-width: 654px;\n    position: relative;\n}\n.entryPlaygroundTextWorkspace .write_box .input_box .list {\n    padding: 4px 0px;\n    list-style: none;\n}\n.entryPlaygroundTextWorkspace .write_box .input_box .list li {\n    color: #555;\n    margin-top: 4px;\n    line-height: 18px;\n}\n.entryPlaygroundTextWorkspace .write_box .input_box .list li:before {\n    display: inline-block;\n    width: 3px;\n    height: 3px;\n    border-radius: 50%;\n    background-color: #555;\n    margin: 6px 8px 0 0;\n    vertical-align: top;\n    content: '';\n}\n.entryPlaygroundTextWorkspace .write_box .input_inner {\n    position: relative;\n    overflow: hidden;\n    height: 40px;\n    max-width: 654px;\n    background-color: #fff;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px;\n    margin-top: 24px;\n}\n\n.entryPlaygroundTextWorkspace .write_box .input_inner .bold {\n    font-weight: bold;\n}\n\n.entryPlaygroundTextWorkspace .write_box .input_inner .italic {\n    font-style: italic;\n}\n\n.entryPlaygroundTextWorkspace .write_box .input_inner input[type='text'] {\n    display: none;\n    width: 100%;\n    height: 100%;\n    margin: 0;\n    padding-left: 15px;\n    border: 0;\n    line-height: 40px;\n    outline: 0;\n    font-size: 14px;\n    letter-spacing: -0.3px;\n}\n.entryPlaygroundTextWorkspace .write_box .input_inner textarea {\n    width: 100%;\n    height: 100%;\n    margin: 0;\n    padding: 12px;\n    font-size: 14px;\n    border: 0;\n    line-height: 18px;\n    outline: 0;\n    letter-spacing: -0.3px;\n}\n.entryPlaygroundTextWorkspace .write_box .input_inner label {\n    position: absolute;\n    left: 16px;\n    right: 16px;\n    top: 13px;\n    color: #979797;\n    letter-spacing: -0.3px;\n}\n\n.imbtn_pop_font_bold {\n    .backgroundImage('btn_pop_font_bold.png');\n    background-size: 38px auto;\n    &.on {\n        .backgroundImage('btn_pop_font_bold_on.png');\n    }\n}\n.imbtn_pop_font_underline {\n    .backgroundImage('btn_pop_font_underline.png');\n    background-size: 38px auto;\n    &.on {\n        .backgroundImage('btn_pop_font_underline_on.png');\n    }\n}\n.imbtn_pop_font_italic {\n    .backgroundImage('btn_pop_font_italic.png');\n    background-size: 38px auto;\n    &.on {\n        .backgroundImage('btn_pop_font_italic_on.png');\n    }\n}\n.imbtn_pop_font_through {\n    .backgroundImage('btn_pop_font_through.png');\n    background-size: 38px auto;\n    &.on {\n        .backgroundImage('btn_pop_font_through_on.png');\n    }\n}\n.imbtn_pop_font_color {\n    display: inline-block;\n    position: relative;\n    overflow: hidden;\n    width: 66px;\n    height: 40px;\n    margin-left: 10px;\n    .backgroundImage('btn_pop_font_color.png');\n    background-size: 66px auto;\n    cursor: pointer;\n    em {\n        position: absolute;\n        left: 5px;\n        right: 5px;\n        top: 5px;\n        bottom: 5px;\n        background-color: #f9f9f9;\n        z-index: -1;\n    }\n    &.on {\n        .backgroundImage('btn_pop_font_color_on.png');\n    }\n}\n.imbtn_pop_font_paint,\n.imbtn_pop_font_backgroundcolor {\n    display: inline-block;\n    position: relative;\n    overflow: hidden;\n    width: 66px;\n    height: 40px;\n    margin-left: 10px;\n    .backgroundImage('btn_pop_font_paint.png');\n    background-size: 66px auto;\n    cursor: pointer;\n    em {\n        position: absolute;\n        left: 5px;\n        right: 5px;\n        top: 5px;\n        bottom: 5px;\n        z-index: -1;\n    }\n    &.on {\n        .backgroundImage('btn_pop_font_paint_on.png');\n        &.clear {\n            .backgroundImage('btn_pop_font_paint_clear_on.png');\n            em {\n                display: none;\n            }\n        }\n    }\n    &.clear {\n        .backgroundImage('btn_pop_font_paint_clear.png');\n        em {\n            display: none;\n        }\n    }\n    &.clear_on {\n        .backgroundImage('btn_pop_font_paint_clear_on.png');\n        em {\n            display: none;\n        }\n    }\n}\n\n.imbtn_pop_font_align_left {\n    .backgroundImage('btn_pop_font_align_left.png');\n    background-size: 38px auto;\n    &.on {\n        .backgroundImage('btn_pop_font_align_left_on.png');\n    }\n}\n\n.imbtn_pop_font_align_middle {\n    .backgroundImage('btn_pop_font_align_middle.png');\n    background-size: 38px auto;\n    &.on {\n        .backgroundImage('btn_pop_font_align_middle_on.png');\n    }\n}\n\n.imbtn_pop_font_align_right {\n    .backgroundImage('btn_pop_font_align_right.png');\n    background-size: 38px auto;\n    &.on {\n        .backgroundImage('btn_pop_font_align_right_on.png');\n    }\n}\n\n.imico_pop_select_arr_down:after {\n    .backgroundImage('ico_pop_select_arr_down.png');\n    background-size: 8px auto;\n}\n.imico_pop_select_arr_up:after {\n    .backgroundImage('ico_pop_select_arr_up.png');\n    background-size: 8px auto;\n}\n\n#entryFontColorToggle {\n    .backgroundImage('text_in_off.png');\n}\n\n#entryFontColorToggle.selected {\n    .backgroundImage('text_in_on.png');\n}\n\n#entryFontBGToggle {\n    margin-left: 6px;\n    .backgroundImage('text_out_off.png');\n}\n\n#entryFontBGToggle.selected {\n    .backgroundImage('text_out_on.png');\n}\n\n.entryPlaygroundSoundWorkspace {\n    overflow: hidden;\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 8px;\n    background-color: #f9f9f9;\n    border-radius: 0 0 0 6px;\n    top: 80px;\n    margin-left: 0;\n}\n\n.entryPlaygroundSoundEdit {\n    position: absolute;\n    left: 253px;\n    top: 0;\n    bottom: 0;\n    right: 0;\n    overflow: hidden;\n    border-left: 1px solid #e2e2e2;\n    background-color: #f2f2f2;\n\n    .entryPlaygroundSoundEditWrapper {\n        text-align: center;\n    }\n\n    .entryPlaygroundSoundEditImage {\n        .backgroundImage('sound_edit.gif');\n        width: 160px;\n        height: 160px;\n        -o-object-fit: contain;\n        object-fit: contain;\n        margin: 0 auto 24px;\n        background-size: 160px auto;\n    }\n\n    .entryPlaygroundSoundEditText {\n        margin: 0 auto;\n        font-size: 14px;\n        font-weight: bold;\n        font-style: normal;\n        font-stretch: normal;\n        line-height: normal;\n        letter-spacing: -0.3px;\n        text-align: center;\n        color: #555555;\n        -webkit-user-select: none;\n        -moz-user-select: none;\n        -ms-user-select: none;\n        user-select: none;\n        white-space: pre-line;\n    }\n}\n\n.entryPlaygroundAddSound {\n    width: 254px;\n    padding: 8px 0;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n}\n\n.entryPlaygroundAddSoundPhone {\n    position: relative;\n    height: 50px;\n    cursor: pointer;\n    border-bottom: 1pt solid #ebeff1;\n}\n\n.entryPlaygroundAddSoundInner {\n    display: block;\n    overflow: hidden;\n    width: calc(100% - 24px);\n    height: 40px;\n    margin: 0 auto;\n    background-color: #fff;\n    border: 1px solid #4f80ff;\n    border-radius: 4px;\n    color: #4f80ff;\n    text-align: center;  \n    letter-spacing: -0.32px;\n    font-size: 14px;\n    font-weight: 600;\n    line-height: 38px;\n    cursor: pointer;\n}\n\n.entryPlaygroundAddSoundInnerPhone {\n    display: block;\n    height: 40px;\n    background-color: #cdcfc9;\n    color: #656565;\n    text-align: center;\n    font-size: 10.5pt;\n    line-height: 36px;\n    margin: 10px;\n    border: 2px dashed #737373;\n    width: 220px;\n}\n\n.entryPlaygroundSoundList {\n    position: absolute;\n    padding: 0;\n    margin: 0;\n    width: 254px;\n    top: 57px;\n    bottom: 0;\n    overflow-y: hidden;\n    list-style: none;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n}\n\n.entryPlaygroundSoundListPhone {\n    position: absolute;\n    padding: 0px;\n    margin: 0px;\n    width: 254px;\n    top: 57px;\n    bottom: 0px;\n    overflow: hidden;\n    overflow-y: auto;\n    list-style: none;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n    border-radius: 0 0 0 6px;\n}\n\n.entryPlaygroundSoundElement {\n    display: block;\n    position: relative;\n    background-color: #ecf8ff;\n    border-bottom: 1px solid #d6e9f4;\n    padding: 0 56px 0 64px;\n    height: 61px;\n    color: #2c313d;\n    cursor: pointer;\n\n    &.entrySoundSelected {\n        background-color: #fff;\n    }\n}\n\n.entryPlaygroundSoundThumbnail {\n    position: absolute;\n    height: 44px;\n    width: 40px;\n    top: 8px;\n    left: 16px;\n    border: 1px solid #e2e2e2;\n    background-color: #fff;\n    border-radius: 4px;\n    background-size: 28px auto;\n    background-repeat: no-repeat;\n    background-position: 50% 50%;\n    user-select: none;\n    -webkit-touch-callout: none;\n\n    &.entryPlaygroundSoundPlay {\n        .backgroundImage('workspace_sound_play.svg');\n    }\n\n    &.entryPlaygroundSoundStop {\n        .backgroundImage('workspace_sound_stop.svg');\n    }\n}\n\n.entryPlaygroundSoundName {\n    width: 100%;\n    height: 24px;\n    box-sizing: border-box;\n    margin-top: 10px;\n    padding: 0 4px;\n    background-color: #fff;\n    outline: 0;\n    font-size: 12px;\n    text-overflow: ellipsis;\n    color: #2c313d;\n    font-weight: 600;\n    cursor: text;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px;\n}\n.entryPlaygroundSoundName:focus,\n.entryPlaygroundSoundName:active {\n    border-color: #4f80ff;\n}\n\n.entryPlayground_text_buttons {\n    display: inline-block;\n    list-style-type: none;\n    margin: 0;\n    padding: 0;\n}\n\n.entryPlayground_text_buttons > li {\n    float: left;\n    width: 32px;\n    height: 32px;\n    margin-left: 2px;\n    cursor: pointer;\n}\n\n.entryPlaygroundTextAlignLeft {\n    .backgroundImage('text_align_left_off.png');\n}\n.entryPlaygroundTextAlignLeft.toggle {\n    .backgroundImage('text_align_left_on.png');\n}\n\n.entryPlaygroundTextAlignCenter {\n    .backgroundImage('text_align_center_off.png');\n}\n.entryPlaygroundTextAlignCenter.toggle {\n    .backgroundImage('text_align_center_on.png');\n}\n\n.entryPlaygroundTextAlignRight {\n    .backgroundImage('text_align_right_off.png');\n}\n.entryPlaygroundTextAlignRight.toggle {\n    .backgroundImage('text_align_right_on.png');\n}\n\n.entryPlayground_fgColorDiv {\n    position: absolute;\n    width: 15px;\n    height: 4px;\n    margin-top: -10px;\n    margin-left: 8px;\n}\n\n.entryPlayground_bgColorDiv {\n    position: absolute;\n    width: 15px;\n    height: 4px;\n    margin-top: -10px;\n    margin-left: 8px;\n}\n\n.entryPlaygroundFontSizeSlider {\n    display: inline-block;\n    margin-left: 12px;\n    width: 136px;\n    height: 8px;\n    border-radius: 3px;\n    box-shadow: inset 1px 1px 1px 0 rgba(0, 0, 0, 0.03);\n    background-color: #d8d8d8;\n}\n\n.entryPlaygroundFontSizeIndicator {\n    height: 100%;\n    width: 45%;\n    border-radius: 3px;\n    background-color: #643cd9;\n}\n\n.entryPlaygroundFontSizeKnob {\n    width: 19px;\n    height: 30px;\n    -o-object-fit: contain;\n    object-fit: contain;\n    position: relative;\n    margin-top: -19px;\n    margin-left: -12px;\n    .backgroundImage('text_size_knob.png');\n    background-repeat: no-repeat;\n    background-position: center;\n    cursor: pointer;\n}\n\n.entryPlaygroundTextColoursWrapper {\n    width: 260px;\n    height: 226px;\n    z-index: 10;\n    cursor: pointer;\n    padding: 20px 5px;\n    position: absolute;\n    .backgroundImage('text_color_bg.png');\n    background-repeat: no-repeat;\n    background-size: 260px 226px;\n}\n.entryPlaygroundTextBackgroundsWrapper {\n    width: 260px;\n    height: 226px;\n    z-index: 10;\n    cursor: pointer;\n    padding: 20px 5px;\n    position: absolute;\n    .backgroundImage('text_color_bg_1.png');\n    background-repeat: no-repeat;\n    background-size: 260px 226px;\n}\n\n.entryPlaygroundLinebreakWrapper {\n    position: fixed;\n    top: 351px;\n}\n\n.entryPlaygroundLinebreakButtons {\n    display: inline;\n    font-size: 0;\n    img {\n        cursor: pointer;\n    }\n}\n\n.entryPlaygroundLinebreakHorizontal {\n    display: block;\n    border-top: 1px solid #808080;\n    margin: 0 0 12px 0;\n    padding: 0;\n    width: 260px;\n}\n\n.entryPlaygroundLinebreakDescription {\n    margin-top: 12px;\n    p {\n        color: #8888;\n        font-size: 11px;\n        margin-bottom: 5px;\n    }\n\n    ul {\n        padding-left: 20px;\n        li {\n            color: #b4b4b5;\n            font-size: 11px;\n        }\n    }\n}\n\n.tablet {\n    .entryPlaygroundResizeWorkspace {\n        .backgroundImage('entry_scroll_02.svg');\n        width: 36px;\n        height: 62px;\n        border-top: none;\n    }\n}\n\n.entrySceneListWorkspace {\n    .rcs-inner-container {\n        > div > div > div {\n            display: table;\n            table-layout: fixed;\n            .sortableItem {\n                display: table-cell;\n                vertical-align: top;\n                width: 76px;\n            }\n        }\n    }\n}\n\n.sortable {\n    height: 100%;\n\n    .rcs-custom-scrollbar {\n        width: 8px;\n        right: 4px;\n        opacity: 0.8;\n    }\n\n    .rcs-inner-handle {\n        background-color: #aac5d5 !important;\n        border-radius: 2.5px !important;\n        opacity: 0.8;\n    }\n}\n\n.entryPlaygroundTableWorkspace {\n    overflow: hidden;\n    position: absolute;\n    left: 0;\n    right: 0;\n    bottom: 8px;\n    background-color: #f9f9f9;\n    border-radius: 0 0 0 6px;\n    top: 80px;\n    margin-left: 0;\n}\n\n.entryPlaygroundTableEdit {\n    position: absolute;\n    left: 253px;\n    top: 0;\n    bottom: 0;\n    right: 0;\n    overflow: hidden;\n    border-left: 1px solid #e2e2e2;\n    background-color: #f2f2f2;\n    display: flex;\n    justify-content: center;\n    align-items: center;\n\n    .entryPlaygroundTableEditWrapper {\n        text-align: center;\n    }\n\n    .entryPlaygroundTableEditImage {\n        .backgroundImage('sound_edit.gif');\n        width: 160px;\n        height: 160px;\n        -o-object-fit: contain;\n        object-fit: contain;\n        margin: 0 auto 24px;\n        background-size: 160px auto;\n    }\n\n    .entryPlaygroundTableEditText {\n        margin: 0 auto;\n        font-size: 14px;\n        font-weight: bold;\n        font-style: normal;\n        font-stretch: normal;\n        line-height: normal;\n        letter-spacing: -0.3px;\n        text-align: center;\n        color: #555555;\n        -webkit-user-select: none;\n        -moz-user-select: none;\n        -ms-user-select: none;\n        user-select: none;\n    }\n}\n\n.entryPlaygroundAddTable {\n    width: 254px;\n    padding: 8px 0;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n}\n\n.entryPlaygroundAddTablePhone {\n    position: relative;\n    height: 50px;\n    cursor: pointer;\n    border-bottom: 1pt solid #ebeff1;\n}\n\n.entryPlaygroundAddTableInner {\n    display: block;\n    width: 146px;\n    height: 40px;\n    margin: 0 auto;\n    background-color: #fff;\n    border: 1px solid #4f80ff;\n    border-radius: 4px;\n    color: #4f80ff;\n    text-align: center;\n    font-size: 14px;\n    font-weight: 600;\n    line-height: 38px;\n    cursor: pointer;\n}\n\n.entryPlaygroundAddTableInnerPhone {\n    display: block;\n    height: 40px;\n    background-color: #cdcfc9;\n    color: #656565;\n    text-align: center;\n    font-size: 10.5pt;\n    line-height: 36px;\n    margin: 10px;\n    border: 2px dashed #737373;\n    width: 220px;\n}\n\n.entryPlaygroundTableList {\n    position: absolute;\n    padding: 0;\n    margin: 0;\n    width: 254px;\n    top: 57px;\n    bottom: 0;\n    overflow-y: hidden;\n    list-style: none;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n}\n\n.entryPlaygroundTableListPhone {\n    position: absolute;\n    padding: 0px;\n    margin: 0px;\n    width: 254px;\n    top: 57px;\n    bottom: 0px;\n    overflow: hidden;\n    overflow-y: auto;\n    list-style: none;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n    border-radius: 0 0 0 6px;\n}\n\n.entryPlaygroundTableList {\n    position: absolute;\n    padding: 0px;\n    margin: 0px;\n    width: 254px;\n    top: 56px;\n    bottom: 0px;\n    overflow-y: hidden;\n    list-style: none;\n    background-color: #ecf8ff;\n    border: 1px solid #d6e9f4;\n    border-radius: 0 0 0 6px;\n}\n\n.entryPlaygroundTableElement {\n    display: block;\n    position: relative;\n    background-color: #ecf8ff;\n    border-bottom: 1px solid #d6e9f4;\n    padding: 0 56px 0 36px;\n    height: 48px;\n    color: #2c313d;\n    cursor: pointer;\n\n    &.entryTableSelected {\n        background-color: #fff;\n    }\n\n    .entryPlaygroundTableThumbnail {\n        position: absolute;\n        height: 22px;\n        width: 22px;\n        top: 13px;\n        left: 8px;\n        .backgroundImage('workspace_table_icon.svg');\n        background-repeat: no-repeat;\n        background-position: 50% 50%;\n    }\n\n    .entryPlaygroundTableName {\n        width: 100%;\n        height: 24px;\n        box-sizing: border-box;\n        margin-top: 12px;\n        padding: 0 4px;\n        background-color: #fff;\n        outline: 0;\n        font-size: 12px;\n        text-overflow: ellipsis;\n        color: #2c313d;\n        font-weight: 600;\n        cursor: text;\n        border: 1px solid #e2e2e2;\n        border-radius: 4px;\n    }\n    .entryPlaygroundTableName:focus,\n    .entryPlaygroundTableName:active {\n        border-color: #4f80ff;\n    }\n\n    .entryPlaygroundTableRemove {\n        position: absolute;\n        right: 26px;\n        top: 12px;\n        width: 24px;\n        height: 24px;\n        border: 1px solid #e2e2e2;\n        border-radius: 4px;\n        background-color: #fff;\n        background-size: 10px;\n        font-size: 0;\n        cursor: pointer;\n        background-size: 10px auto;\n        background-position: 50% 50%;\n        background-repeat: no-repeat;\n        .backgroundImage('layers_icon_close_nor_new.png');\n    }\n}\n"
  },
  {
    "path": "src/css/components/popup.less",
    "content": ".entryPopup {\n    overflow: hidden;\n    position: fixed;\n    margin: 0;\n    padding: 0;\n    top: 0;\n    left: 0;\n    height: 100%;\n    width: 100%;\n    z-index: 7000;\n    background-color: rgba(0, 0, 0, 0.6);\n}\n\n.entryPopup.popupHelper {\n    position: fixed;\n    display: -webkit-box;\n    display: -moz-box;\n    display: -ms-flexbox;\n    display: -webkit-flex;\n    display: flex;\n    -webkit-box-direction: normal;\n    -moz-box-direction: normal;\n    -webkit-box-orient: vertical;\n    -moz-box-orient: vertical;\n    -webkit-flex-direction: column;\n    -ms-flex-direction: column;\n    flex-direction: column;\n}\n\n.entryPopupWindow {\n    width: 80%;\n    height: 80%;\n    overflow: hidden;\n    position: absolute;\n    left: 0; right: 0;\n    top: 0; bottom: 0;\n    border-radius: 6px;\n    border: 1px solid #d6e9f4;\n    margin: auto;\n    max-width: 100%;\n    max-height: 100%;\n    /*overflow: hidden;*/\n    z-index: 8000;\n    \n    background-color: @white;\n}\n\n.entryPopup.hiddenPopup {\n    display: none;\n}\n\n.entryPopupHelperTopSpan,\n.entryPopupHelperBottomSpan {\n    -webkit-box-flex: 1;\n    -moz-box-flex: 1;\n    -ms-flex: 1;\n    flex: 1;\n}\n\n.entryPopupHelperMiddleSpan {\n    display: -webkit-box;\n    display: -moz-box;\n    display: -ms-flexbox;\n    display: -webkit-flex;\n    display: flex;\n    -webkit-box-direction: normal;\n    -moz-box-direction: normal;\n    -webkit-box-orient: horizontal;\n    -moz-box-orient: horizontal;\n    -webkit-flex-direction: row;\n    -ms-flex-direction: row;\n    flex-direction: row;\n\n    .entryPopupHelperLeftSpan,\n    .entryPopupHelperRightSpan {\n        -webkit-box-flex: 1;\n        -moz-box-flex: 1;\n        -ms-flex: 1;\n        flex: 1;\n    }\n}\n\n.entryPopup.buttonsHidden .entryEngineButtonWorkspace_w {\n    display: none;\n}\n\n.entryPopup.learning_popup {\n    z-index: 7001;\n    .ai_learning {\n        overflow: hidden;\n        .learningInputPopup {\n            border: none;\n            height: 248px;\n            width: 294px;\n            background-color: #fff;\n            border-bottom-right-radius: 5px;\n            border-bottom-left-radius: 5px;\n        }\n        .learningInputPopup.text {\n            height: 165px;\n        }\n        .learningInputPopup.image {\n            height: 245px;\n        }\n        .learningInputPopup.speech {\n            height: 250px;\n        }\n    }\n}\n\n\n"
  },
  {
    "path": "src/css/components/property_panel.less",
    "content": ".propertyPanel {\n    // z-index: 10;\n    position: relative;\n    flex: 1;\n    margin-top: 16px;\n    left: 0px;\n    right: 16px;\n    bottom: 0px;\n    height: 1px;\n}\n\n.propertyTab {\n    overflow: hidden;\n    width: 25px;\n    height: 100%;\n}\n.propertyTabElement {\n    height: 38px;\n    margin-top: 4px;\n    cursor: pointer;\n    font-size: 0;\n    background-size: 25px auto;\n}\n.propertyTabElement:first-child {\n    margin-top: 0;\n}\n\n.collapsed .propertyTabElement {\n    background-position: 50% 9px;\n    height: 36px;\n    font-size: 0;\n}\n\n.propertyTabobject {\n    .backgroundImage('property/container_off.png');\n}\n.propertyTabobject.selected {\n    .backgroundImage('property/container_on.png');\n\n    .practical_course_mode & {\n        .backgroundImage('property/container_on_practical_course.png');\n    }\n}\n\n.propertyTabhw {\n    .backgroundImage('property/hw_off.png');\n}\n.propertyTabhw.selected {\n    .backgroundImage('property/hw_on.png');\n\n    .practical_course_mode & {\n        .backgroundImage('property/hw_on_practical_course.png');\n    }\n}\n\n.propertyTabtvCast {\n    .backgroundImage('property/vedio_off.png');\n}\n.propertyTabtvCast.selected {\n    .backgroundImage('property/vedio_on.png');\n}\n\n.propertyTabyoutube {\n    .backgroundImage('property/vedio_off.png');\n}\n.propertyTabyoutube.selected {\n    .backgroundImage('property/vedio_on.png');\n}\n\n.propertyTabgoal {\n    .backgroundImage('property/doneproject.png');\n}\n.propertyTabgoal.selected {\n    .backgroundImage('property/doneproject_on.png');\n}\n\n.propertyTabpdf {\n    .backgroundImage('property/pdf_off.png');\n}\n.propertyTabpdf.selected {\n    .backgroundImage('property/pdf_on.png');\n}\n\n.propertyTabconsole {\n    .backgroundImage('property/console_off.png');\n}\n.propertyTabhint {\n    .backgroundImage('property/hint_off_property.png');\n}\n.propertyTabhint.selected {\n    .backgroundImage('property/hint_on.png');\n}\n.propertyTabconsole.selected {\n    .backgroundImage('property/console_on.png');\n\n    .practical_course_mode & {\n        .backgroundImage('property/console_on_practical_course.png');\n    }\n}\n\n.propertyContent {\n    overflow: hidden;\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 25px;\n    right: 0;\n    background-color: #fff;\n    border: 1px solid #d6e9f4;\n    border-radius: 0 6px 6px 6px;\n}\n.propertyContent:after {\n    display: block;\n    clear: both;\n    content: '';\n}\n\n.propertyPanelCover {\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n}\n\n.collapsed .propertyContent {\n    left: 30px;\n}\n"
  },
  {
    "path": "src/css/components/scene.less",
    "content": "body {\n    & > .sortableItem {\n        z-index: 250;\n    }\n}\n\n.entryTopFloatingView {\n    display: flex;\n    position: absolute;\n    width: 100%;\n    flex-flow: row nowrap;\n\n    .entrySceneWorkspace {\n        flex: 1;\n        height: 38px;\n        padding-top: 1px;\n        background-color: @baseblue;\n        overflow: hidden;\n        z-index: 10;\n\n        .practical_course_mode & {\n            background-color: @basePurple;\n        }\n    }\n\n    .entryBlockCountView {\n        background-color: @baseblue;\n        z-index: 10;\n        display: flex;\n        flex-direction: row-reverse;\n        align-items: center;\n\n        .practical_course_mode & {\n            background-color: @basePurple;\n        }\n\n        .blockCountView {\n            height: 24px;\n            line-height: 24px;\n            border-radius: 14px;\n            margin-right: 12px;\n            padding: 0 8px;\n            background-color: @baseBluePoint;\n            font-size: 12px;\n            color: #ffffff;\n\n            .practical_course_mode & {\n                background-color: @basePurplePoint;\n            }\n        }\n    }\n}\n\n.entrySceneListWorkspace {\n    overflow: hidden;\n    float: left;\n    margin: 0;\n    padding: 0 0 0 26px;\n    max-width: calc(100% - 72px);\n\n    .rcs-custom-scroll .rcs-outer-container {\n        overflow: visible;\n        .rcs-inner-container {\n            overflow: visible;\n        }\n    }\n\n    .sortableItem {\n        z-index: 15;\n    }\n}\n\n.entrySceneElementWorkspace {\n    overflow: hidden;\n    margin: 5px 2px 0 0;\n    color: white;\n    cursor: move;\n    z-index: 10;\n}\n\n.entrySceneElementWorkspace.selectedScene {\n    position: relative;\n    margin-top: 0;\n    z-index: 888;\n}\n.entrySceneAddButtonWorkspace {\n    float: left;\n    position: relative;\n    margin: 3px 0px 0px -2px;\n    width: 44px;\n    height: 34px;\n    cursor: pointer;\n    .backgroundImage('btn_scene_add.png');\n    background-size: 44px 34px;\n}\n\n.entryScenePrevButtonWorkspace {\n    position: absolute;\n    width: 25px;\n    height: 39px;\n    left: 0px;\n    z-index: 299;\n    margin: 0px;\n\n    .prevBtn {\n        position: absolute;\n        width: 25px;\n        height: 37px;\n        content: '';\n        .backgroundImage('btn_scene_left.png');\n        background-position: 50%;\n        background-repeat: no-repeat;\n        background-color: transparent;\n        cursor: pointer;\n        z-index: 299;\n    }\n}\n\n.entrySceneNextButtonWorkspace {\n    position: relative;\n    display: inline-block;\n    background-color: #4f80ff;\n    width: 72px;\n    height: 37px;\n    right: 0px;\n    opacity: 0.8;\n    z-index: 299;\n    margin: 0px;\n\n    .nextBtn {\n        position: absolute;\n        width: 28px;\n        height: 37px;\n        content: '';\n        .backgroundImage('btn_scene_right.png');\n        background-position: 50%;\n        background-repeat: no-repeat;\n        background-color: transparent;\n        cursor: pointer;\n        z-index: 299;\n    }\n    .addButton {\n        float: left;\n        position: relative;\n        right: 0px;\n        margin: 3px 0px 0px 28px;\n        width: 44px;\n        height: 34px;\n        cursor: pointer;\n        .backgroundImage('btn_scene_add.png');\n        background-size: 44px 34px;\n    }\n}\n\n.selectedScene {\n    .entrySceneInputCover {\n        min-width: 97px;\n    }\n}\n\n.entrySceneInputCover {\n    display: block;\n    overflow: hidden;\n    height: 32px;\n    padding: 4px 10px 0;\n    border-bottom: 2px solid transparent;\n    background-color: #99c4ff;\n    border-radius: 10px 10px 0 0;\n}\n\n.entrySceneInputCover.entryDisabledScene::before {\n    display: block;\n    content: ' ';\n    width: 100%;\n    height: 100%;\n    position: absolute;\n    top: 0;\n    left: 0;\n}\n\n.entrySceneFieldWorkspace {\n    cursor: text !important;\n    display: inline-block;\n    overflow: hidden;\n    margin: 0px;\n    height: 24px;\n    width: 100%;\n    border: 1px solid transparent;\n    border-radius: 4px;\n    outline: 0;\n    background-color: transparent;\n    font-size: 12px;\n    font-weight: 600;\n    color: #fff;\n    line-height: 24px;\n}\n\n.selectedScene .entrySceneInputCover {\n    height: 37px;\n    padding: 7px 30px 0 10px;\n    background-color: #fff;\n    border-radius: 8px 8px 0 0;\n    border-bottom-color: #ffb500;\n}\n\n.selectedScene .entrySceneFieldWorkspace {\n    background-color: #fff;\n    font-size: 14px;\n    color: #ffb500;\n}\n.selectedScene .entrySceneFieldWorkspace:focus {\n    font-size: 12px;\n    border: 1px solid #e2e2e2;\n    color: #2c313d;\n}\n.entrySceneRemoveButtonWorkspace {\n    position: absolute;\n    right: 0;\n    top: 3px;\n    width: 30px;\n    height: 30px;\n    padding: 0;\n    border: 0;\n    display: none;\n    .backgroundImage('scene_delete_unselect.png');\n    background-size: 10px auto;\n    background-repeat: no-repeat;\n    background-position: center;\n    background-color: transparent;\n}\n\n.minValue .entrySceneRemoveButtonWorkspace {\n    display: none;\n}\n\n.selectedScene .entrySceneRemoveButtonWorkspace {\n    display: block;\n    top: 3px;\n    background-color: transparent;\n    .backgroundImage('scene_delete.png');\n}\n\n// .entrySceneRemoveButtonWorkspace:hover {\n//     .backgroundImage(\"scene_delete_hover.png\");\n// }\n\n.entrySceneDummyView {\n    width: 55px;\n    height: 40px;\n    background-color: orange;\n    display: inline-block;\n    opacity: 0.3;\n    position: absolute;\n    left: 0;\n    top: 0;\n    z-index: 889;\n    left: 100px;\n}\n\n.tablet {\n    .entrySceneRemoveButtonWorkspace {\n        width: 14px;\n        height: 14px;\n        right: 48px;\n        .backgroundImage('scene_delete_unselect_big.png');\n    }\n\n    .selectedScene .entrySceneRemoveButtonWorkspace {\n        .backgroundImage('scene_delete_big.png');\n    }\n\n    .entrySceneRemoveButtonWorkspace:hover {\n        .backgroundImage('scene_delete_hover_big.png');\n    }\n}\n"
  },
  {
    "path": "src/css/components/stage.less",
    "content": ".entryCanvasWrapper {\n    position: absolute;\n}\n\n.entryCanvasWorkspace {\n    position: relative;\n    top: 0px;\n    left: 0;\n    width: 268px;\n    background-color: white;\n    border-top: 1px solid #d6e9f4;\n    vertical-align: top;\n}\n\n.entryCanvasPhone {\n    width: 100%;\n    background-color: white;\n    display: block;\n}\n\n.entryPopupWindow > .entryCanvasWorkspace {\n    width: 100% !important;\n    position: relative;\n    border-bottom: 1px solid #d6e9f4;\n    border-top: 0px;\n}\n\n.entryPopupWindow > .entryEngine_w {\n    width: 100% !important;\n    height: 100% !important;\n    border: 0;\n}\n\n.entryPopupWindow > div > .entryCanvasWorkspace {\n    width: 100% !important;\n    top: 0 !important;\n    vertical-align: top;\n}\n"
  },
  {
    "path": "src/css/components/state_manager.less",
    "content": ".entryStateManagerWorkspace {\n    float: right;\n    height: 40px;\n    margin-right: 10px;\n}\n\n.entryStateManagerButtonWorkspace {\n    border:0;\n    margin: 3px;\n    padding-left: 26px;\n    height: 32px;\n    border-radius: 4px;\n    background-color: #BDC4C9;\n    color: #E2EBFA;\n    font-size: 10pt;\n    background-repeat: no-repeat;\n    background-position: 7px 8px;\n    border-bottom: 2pt solid #A0ACB2;\n    border-right: 2pt solid #A0ACB2;\n}\n\n.entryStateManagerButtonWorkspace.active:hover {\n    background-color: #7CC2EE;\n}\n\n.entryStateManagerButtonWorkspace.active {\n    background-color: #6AAFDA;\n    border-bottom: 2pt solid #639FBD;\n    border-right: 2pt solid #639FBD;\n}\n\n.entryUndoButtonWorkspace {\n    background-image: url(\"/img/assets/undo.png\");\n}\n\n.entryRedoButtonWorkspace {\n    background-image: url(\"/img/assets/redo.png\");\n}\n\n"
  },
  {
    "path": "src/css/components/table.less",
    "content": ".entryPlaygroundTable {\n    position: absolute;\n    left: 254px;\n    top: 0;\n    bottom: 0;\n    right: 0;\n    border-left: none;\n    background-color: #f9f9f9;\n}\n"
  },
  {
    "path": "src/css/components/target_checker.less",
    "content": ".entryTargetStatus {\n    font-family: EntryFont, NanumGothic, 'Nanum Gothic';\n    height: 54px;\n    width: 100%;\n    position: absolute;\n    bottom: 0;\n}\n\n.entryTargetStatus .innerWrapper {\n    width: auto;\n    position: absolute;\n    background-color: #f4f4f4;\n    border-radius: 3px;\n    height: 54px;\n}\n\n.entryPopupWindow .entryTargetStatus {\n    height: 91px;\n}\n\n.iframeWithTargetStatus .innerWrapper {\n    width: 100%;\n}\n\n.entryPopupWindow .innerWrapper {\n    left: 16px;\n    right: 16px;\n}\n\n.iframeWithTargetStatus #entryCanvasWrapper {\n    bottom: 89px;\n}\n\n.iframeWithTargetStatus .entryEngine {\n    bottom: 54px;\n}\n\n.entryTargetStatus .statusIndicator {\n    display: inline-block;\n    width: 43px;\n    height: 41px;\n    text-align: center;\n    line-height: 41px;\n    font-size: 14px;\n    color: #fff;\n    .backgroundImage('status_dialog.png');\n    margin-left: 14px;\n    margin-top: 6px;\n}\n\n.entryTargetStatus .statusMessage {\n    font-size: 14px;\n    color: #3b3b3b;\n    left: 71px;\n    top: 0;\n    bottom: 0;\n    right: 10px;\n    display: table;\n    position: absolute;\n    width: 100%;\n    height: 54px;\n}\n\n.statusMessage p {\n    display: table-cell;\n    vertical-align: middle;\n    padding-right: 81px;\n}\n\n.targetCheckerPopup .entryEngine_w {\n    height: auto !important;\n    bottom: 91px;\n}\n\n.blueWS {\n    .entryTargetStatus .statusIndicator {\n        .backgroundImage('status_dialog_blue.png');\n    }\n}\n\n.purpleWS {\n    .entryTargetStatus .statusIndicator {\n        .backgroundImage('status_dialog_purple.png');\n    }\n}\n"
  },
  {
    "path": "src/css/components/textcoding_helper.less",
    "content": ".propertyTabconsole {\n\n}\n\n#textCodingExampleView {\n    position: absolute;\n    width: 100%;\n    top: 150px;\n}\n\n"
  },
  {
    "path": "src/css/components/toast.less",
    "content": ".entryToastContainer {\n    position: fixed;\n    right: 0px;\n    bottom: 15px;\n    margin: 0px;\n    padding: 2px;\n    width: 300px;\n    max-height: 100%;\n    overflow: auto;\n    z-index: 9000;\n}\n\n.entryToast {\n    padding: 7px 16px;\n    margin-top: 8px;\n    width: 100%;\n    background-color: #eee;\n    box-shadow: #999 0 0 8px;\n    border: 2px solid;\n    .border-radius(4px);\n    .transition(opacity 0.25s ease-in-out);\n    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);\n    cursor: pointer;\n    opacity: 1;\n}\n\n.entryToastSuccess {\n    border-color: #d6e9c6;\n    background-color: #e5f3df;\n    color: #468847;\n}\n\n.entryToastWarning {\n    border-color: #7e7190;\n    background-color: #fff9ab;\n    color: #e07000;\n}\n\n.entryToastAlert {\n    color: #b94a48;\n    background-color: #f2dede;\n    border-color: #eed3d7;\n}\n\n.entryToastTitle {\n    font-size: 12pt;\n    font-weight: bold;\n}\n\n.entryToastMessage {\n    font-size: 9pt;\n    margin-top: 4px;\n    margin-bottom: 2px;\n    white-space: pre-line;\n}\n\n.entryMobileToastWrapper {\n    position: absolute;\n    margin-top: 24px;\n    width: 100%;\n    text-align: center;\n    pointer-events: none;\n    z-index: 1;\n    .entryMobileToast {\n        &::before {\n            content: '';\n            display: inline-block;\n            .backgroundImage('toast_left.svg');\n            width: 17px;\n            height: 38px;\n            margin-right: -4px;\n        }\n        &::after {\n            content: '';\n            display: inline-block;\n            .backgroundImage('toast_right.svg');\n            width: 20px;\n            height: 38px;\n            margin-left: -4px;\n        }\n        display: inline-block;\n        // width: 90px;\n        height: 38px;\n        font-size: 14px;\n        vertical-align: top;\n        font-weight: bold;\n        font-style: normal;\n        font-stretch: normal;\n        line-height: normal;\n        letter-spacing: -0.5px;\n        text-align: center;\n        color: #4f80ff;\n\n        .content {\n            display: inline-block;\n            height: 38px;\n            padding: 9px 8px;\n            vertical-align: top;\n            .backgroundImage('toast_bg.svg');\n        }\n    }\n}\n"
  },
  {
    "path": "src/css/components/tooltip.less",
    "content": "@keyframes fIn {\n    0% {\n        opacity: 0;\n    }\n    100% {\n        opacity: 0.5;\n    }\n}\n\n.entryTooltipBG {\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    z-index: 9990;\n    top: 0;\n    left: 0;\n    cursor: pointer;\n    animation-name: fIn;\n    animation-duration: 0.3s;\n    animation-timing-function: ease-out;\n}\n\n@keyframes stretch {\n    0% {\n        opacity: 0;\n        transform: translate(0, -10px);\n    }\n    100% {\n        opacity: 1;\n        transform: translate(0, 0);\n    }\n}\n\n.entryTooltipWrapper {\n    position: absolute;\n    z-index: 9999;\n    animation-name: stretch;\n    animation-duration: 0.5s;\n    animation-timing-function: ease-out;\n    .transition(opacity 0.4s ease-in-out);\n}\n\n.hideTooltip > .entryTooltipWrapper {\n    opacity: 0;\n}\n\n@balloon-arrow-width: 25px;\n@balloon-arrow-height: 11px;\n\n.mixin-svg-arrow(@width, @height, @degrees) {\n    @svg-arrow: ~'<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"@{width}\" height=\"@{height}\"><path fill=\"@{color}\" transform=\"rotate(@{degrees})\" d=\"M0,0 l10,10 c2.5 1.5 2.5 1.5 5 0 l10,-10 Z\"/></svg>';\n    @-svg-code: escape(~'@{svg-arrow}');\n    background: url('data:image/svg+xml;charset=utf-8,@{-svg-code}') no-repeat;\n    background-size: 100% auto;\n    height: @height;\n    width: @width;\n}\n\n.svg-arrow(@color, @position) {\n    & when (@position = down) {\n        @width: @balloon-arrow-width;\n        @height: @balloon-arrow-height;\n        @degrees: 180 12.5 5.5;\n        .mixin-svg-arrow(@width, @height, @degrees);\n    }\n    & when (@position = up) {\n        @width: @balloon-arrow-width;\n        @height: @balloon-arrow-height;\n        @degrees: 0;\n        .mixin-svg-arrow(@width, @height, @degrees);\n    }\n    & when (@position = right) {\n        @width: @balloon-arrow-height;\n        @height: @balloon-arrow-width;\n        @degrees: 90 5.5 5.5;\n        .mixin-svg-arrow(@width, @height, @degrees);\n    }\n    & when (@position = left) {\n        @width: @balloon-arrow-height;\n        @height: @balloon-arrow-width;\n        @degrees: -90 12.5 12.5;\n        .mixin-svg-arrow(@width, @height, @degrees);\n    }\n}\n\n.entryTooltip {\n    position: absolute;\n    white-space: nowrap;\n    padding: 25px;\n    background-color: #ffffff;\n    border-radius: 8px;\n    text-align: center;\n    font-size: 14px;\n    font-family: EntryFont, NanumGothic, 'Nanum Gothic';\n    color: #3b3b3b;\n    box-shadow: 2px 2px 10px 0 rgba(0, 0, 0, 0.19);\n    &:before {\n        position: absolute;\n        content: '';\n    }\n}\n\n.entryTooltip.up {\n    .transform(translate(-50%, -100%));\n    margin-top: -11px;\n    &:before {\n        .svg-arrow('#FFF', up);\n        top: 100%;\n        left: 50%;\n        margin-left: -@balloon-arrow-width * 0.5;\n    }\n}\n\n.entryTooltip.down {\n    margin-top: 11px;\n    .transform(translate(-50%, 0));\n    &:before {\n        .svg-arrow('#FFF', down);\n        top: -@balloon-arrow-height;\n        left: 50%;\n        margin-left: -@balloon-arrow-width * 0.5;\n    }\n}\n\n.entryTooltip.left {\n    margin-left: -11px;\n    .transform(translate(-100%, -50%));\n    &:before {\n        .svg-arrow('#FFF', left);\n        left: 100%;\n        margin-left: -1px;\n        top: 50%;\n        margin-top: -@balloon-arrow-width * 0.5;\n    }\n}\n\n.entryTooltip.right {\n    margin-left: 11px;\n    .transform(translate(0, -50%));\n    &:before {\n        .svg-arrow('#FFF', right);\n        top: 50%;\n        left: -@balloon-arrow-height;\n        margin-top: -@balloon-arrow-width * 0.5;\n    }\n}\n\n@keyframes IndicatorPop {\n    0% {\n        opacity: 1;\n        transform: scale(0);\n    }\n    75% {\n        opacity: 0;\n        transform: scale(1);\n    }\n    100% {\n        opacity: 0;\n        transform: scale(1);\n    }\n}\n\n.entryTooltipIndicator {\n    position: absolute;\n    padding-top: 25px;\n}\n\n.entryTooltipIndicator > div {\n    width: 50px;\n    height: 50px;\n    background-color: #ffffff;\n    margin: -100% -50%;\n    border-radius: 100%;\n    position: relative;\n    z-index: 9999;\n    animation-name: IndicatorPop;\n    animation-duration: 1.3s;\n    animation-iteration-count: infinite;\n    animation-timing-function: ease-out;\n    transform: scale(0);\n}\n\n.entryTooltipIndicator > div:nth-child(2) {\n    animation-delay: 0.3s;\n}\n\n.entryTooltipIndicator > div:nth-child(3) {\n    animation-delay: 0.6s;\n}\n\n//special\n\n.entryTooltip.left.edge_up {\n    .transform(translate(-100%, -25px));\n    &:before {\n        top: 25px;\n    }\n}\n\n.entryTooltip.left.edge_down {\n    .transform(translate(-100%, -100%));\n    margin-top: 25px;\n    &:before {\n        top: 100%;\n        margin-top: -37.5px;\n    }\n}\n\n.entryTooltip.right.edge_up {\n    .transform(translate(0, -25px));\n    &:before {\n        top: 25px;\n    }\n}\n\n.entryTooltip.right.edge_down {\n    .transform(translate(0, -100%));\n    margin-top: 25px;\n    &:before {\n        top: 100%;\n        margin-top: -37.5px;\n    }\n}\n\n.entryTooltip.up.edge_left {\n    .transform(translate(-25px, -100%));\n    &:before {\n        left: 25px;\n    }\n}\n\n.entryTooltip.up.edge_right {\n    .transform(translate(-100%, -100%));\n    margin-left: 25px;\n    &:before {\n        left: 100%;\n        margin-left: -37.5px;\n    }\n}\n\n.entryTooltip.down.edge_left {\n    .transform(translate(-25px, 0));\n    &:before {\n        left: 25px;\n    }\n}\n\n.entryTooltip.down.edge_right {\n    left: 0;\n    margin-left: 25px;\n    .transform(translate(-100%, 0));\n    &:before {\n        left: 100%;\n        margin-left: -37.5px;\n    }\n}\n"
  },
  {
    "path": "src/css/components/variable_container.less",
    "content": ".entryVariablePanelWorkspace {\n    position: absolute;\n    overflow: hidden;\n    overflow-y: auto;\n    width: 254px;\n    top: 0;\n    bottom: 0px;\n    padding: 16px 16px 0 8px;\n    background-color: #ecf8ff;\n    // border: 1px solid #d6e9f4;\n    box-shadow: 0 0 0 1px #d6e9f4 inset;\n    border-radius: 0 0 0 6px;\n}\n\n.entryVariablePanelPhone {\n    width: 250px;\n    top: 47px;\n    bottom: 0px;\n    padding: 6px 4px 0px 4px;\n}\n\n.entryVariableSelectorWorkspace {\n    width: 100%;\n    border-collapse: collapse;\n    border-spacing: 0;\n    border: 0;\n    padding: 0;\n    margin: 0;\n    table-layout: fixed;\n}\n.entryVariableSelectorWorkspace tr:first-child td:first-child {\n    width: 56px;\n}\n\n.entryVariableSelectButtonWorkspace {\n    font-family: EntryFont, NanumGothic, 'Nanum Gothic' !important;\n    width: 88px;\n    padding: 0;\n    margin: 0;\n    cursor: pointer;\n    vertical-align: top;\n\n    div {\n        &:before {\n            position: absolute;\n            left: 15px;\n            top: 9px;\n            width: 20px;\n            height: 20px;\n            background-size: 20px auto;\n            vertical-align: top;\n            content: '';\n        }\n\n        position: relative;\n        height: 40px;\n        padding-left: 8px;\n        font-size: 12px;\n        font-weight: 600;\n        color: #728997;\n        background-color: #fff;\n        letter-spacing: -0.4px;\n        line-height: 40px;\n    }\n\n    &.selected div {\n        color: #4f80ff;\n        z-index: 10;\n    }\n\n    &.allButton div {\n        height: 80px;\n        padding: 0;\n        border-radius: 4px 0 0 4px;\n        text-align: center;\n        line-height: 80px;\n\n        &:after {\n            right: -1px;\n            border-radius: 4px 0 0 4px;\n        }\n    }\n\n    .text {\n        display: block;\n        overflow: hidden;\n        margin: 0 8px 0 28px;\n        text-overflow: ellipsis;\n        white-space: nowrap;\n    }\n}\n\n.entryVariableSelectButtonWorkspace.message div {\n    border-radius: 0 6px 0 0;\n}\n\n.entryVariableSelectButtonWorkspace.func div {\n    border-radius: 0 0 6px 0;\n}\n\n.entryVariableSelectButtonWorkspace.disable div {\n    cursor: default;\n}\n\n.entryVariableSelectButtonWorkspace div:after {\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    border: 1px solid #d6e9f4;\n    content: '';\n}\n\n.entryVariableSelectButtonWorkspace.selected div:after {\n    border-color: #4f80ff;\n}\n\n.entryVariableSelectButtonWorkspace.allButton div .text {\n    margin: 0;\n}\n.entryVariableSelectButtonWorkspace.variable div:after {\n    right: -1px;\n}\n.entryVariableSelectButtonWorkspace.message div:after {\n    border-radius: 0 6px 0 0;\n}\n.entryVariableSelectButtonWorkspace.list div:after {\n    right: -1px;\n    top: -1px;\n}\n.entryVariableSelectButtonWorkspace.func div:after {\n    top: -1px;\n    border-radius: 0 0 6px 0;\n}\n\n.entryVariableSelectButtonWorkspace.allButton div:before {\n    display: none;\n}\n\n.entryVariableSelectButtonWorkspace.variable div:before {\n    .backgroundImage('ic_attr_variable.svg');\n}\n.entryVariableSelectButtonWorkspace.message div:before {\n    .backgroundImage('ic_attr_message.svg');\n}\n.entryVariableSelectButtonWorkspace.list div:before {\n    margin-right: 6px;\n    .backgroundImage('ic_attr_list.svg');\n}\n.entryVariableSelectButtonWorkspace.func div:before {\n    .backgroundImage('ic_attr_func.svg');\n}\n\n.entryVariableSelectButtonWorkspace.variable.selected div:before {\n    .backgroundImage('ic_attr_variable_on.svg');\n}\n.entryVariableSelectButtonWorkspace.message.selected div:before {\n    .backgroundImage('ic_attr_message_on.svg');\n}\n.entryVariableSelectButtonWorkspace.list.selected div:before {\n    margin-right: 6px;\n    .backgroundImage('ic_attr_list_on.svg');\n}\n.entryVariableSelectButtonWorkspace.func.selected div:before {\n    .backgroundImage('ic_attr_func_on.svg');\n}\n\n.entryVariableListElementWorkspace {\n    background-repeat: no-repeat;\n    background-position: 14px 10px;\n    background-color: #efefef;\n    border: solid 1px #a8a8a8;\n    margin-bottom: -1px;\n    min-height: 50px;\n}\n\n.entryVariableListWorkspace {\n    overflow: auto;\n    position: absolute;\n    top: 112px;\n    bottom: 0;\n    left: 0;\n    right: 0;\n    padding: 0;\n    margin: 0;\n    border-top: 1px solid #d5d6e9f4;\n}\n.entryVariableAdd_box .entryVariableAddWorkspace {\n    display: block;\n    overflow: hidden;\n    width: 146px;\n    height: 40px;\n    margin: 0 auto 16px;\n    margin-top: 16px;\n    border: 1px solid #4f80ff;\n    border-radius: 4px;\n    background-color: #fff;\n    font-size: 14px;\n    font-weight: 600;\n    color: #4f80ff;\n    text-align: center;\n    text-decoration: none;\n    line-height: 42px;\n    -webkit-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.entryVariableAdd_box .entryVariableAddWorkspace.disabled {\n    border: 1px solid #e2e2e2;\n    background-color: #f9f9f9;\n    color: #cbcbcb;\n    cursor: default;\n}\n.entryVariableAdd_box.entryVariableContainerTextMode .entryVariableAddSpaceWorkspace {\n    display: none;\n}\n.entryVariableAdd_box .message_inpt.off {\n    display: none;\n}\n.entryVariableAdd_box .message_inpt input[type='text']::placeholder {\n    color: #979797;\n}\n.entryVariableAdd_box .message_inpt .entryVariableAddSpaceButtonWrapperWorkspace {\n    border: 0;\n    margin: 0;\n}\n.entryVariableAdd_box .entryVariableAddSpaceWorkspace.off {\n    display: none;\n}\n.entryVariableAddSpaceNameWrapperWorkspace .entryVariableAddSpaceInputLabelWorkspace {\n    position: relative;\n    left: -10px;\n    margin-bottom: 8px;\n    display: inline-block;\n    font-size: 11px;\n    font-weight: 600;\n    color: #2c313d;\n    line-height: 11px;\n    vertical-align: top;\n}\n.entryVariableAddSpaceNameWrapperWorkspace .entryVariableAddSpaceInputLabelWorkspace:before {\n    content: '';\n    display: inline-block;\n    overflow: hidden;\n    border-radius: 50%;\n    margin: 3px 7px 0 0;\n    vertical-align: top;\n    width: 3px;\n    height: 3px;\n    background-color: #728997;\n}\n.entryVariableAddSpaceNameWrapperWorkspace .entryVariableAddSpaceInputWorkspace {\n    overflow: hidden;\n    width: 100%;\n    padding: 6px 8px 5px;\n    border: 1px solid #aac5d5;\n    border-radius: 4px;\n    outline: 0;\n    background-color: #fff;\n    font-size: 10px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.4px;\n    line-height: 11px;\n    -webkit-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.entryVariableAddSpaceNameWrapperWorkspace\n    .entryVariableAddSpaceInputWorkspace::-webkit-input-placeholder {\n    color: #979797;\n}\n.entryVariableAddSpaceNameWrapperWorkspace\n    .entryVariableAddSpaceInputWorkspace:-ms-input-placeholder {\n    color: #979797;\n}\n.entryVariableAddSpaceNameWrapperWorkspace\n    .entryVariableAddSpaceInputWorkspace::-ms-input-placeholder {\n    color: #979797;\n}\n.entryVariableAddSpaceNameWrapperWorkspace .entryVariableAddSpaceInputWorkspace::placeholder {\n    color: #979797;\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace {\n    position: relative;\n    margin: 16px 0 0 14px;\n    padding: 0 0 0 26px;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    cursor: pointer;\n    line-height: 14px;\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace + .entryVariableAddSpaceGlobalWrapperWorkspace {\n    margin-top: 22px;\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace .Workspace_text {\n    display: inline-block;\n    padding: 4px 0 2px;\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace .entryVariableAddSpaceCheckWorkspace {\n    position: absolute;\n    left: 0;\n    top: 0;\n    width: 20px;\n    height: 20px;\n    background-size: 20px auto;\n    .backgroundImage('btn_radio.png');\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace.on .entryVariableAddSpaceCheckWorkspace {\n    .backgroundImage('btn_radio_on.png');\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace .entryVariableAddSpaceCloudWrapperWorkspace {\n    display: none;\n    position: relative;\n    margin: 14px 0 -6px;\n    padding: 11px 0 11px 32px;\n    border: 1px solid #aac5d5;\n    border-width: 1px 0;\n    font-size: 12px;\n    color: #2c313d;\n    cursor: pointer;\n    letter-spacing: -0.5px;\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace\n    .entryVariableAddSpaceCloudWrapperWorkspace\n    .entryVariableAddSpaceCloudSpanWorkspace {\n    display: inline-block;\n    line-height: 1.33;\n    letter-spacing: -0.48px;\n    white-space: pre;\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace\n    .entryVariableAddSpaceCloudWrapperWorkspace\n    .entryCloudTypeWrapper\n    .entryVariableAddSpaceCheckWorkspace {\n    position: absolute;\n    left: -28px;\n    width: 20px;\n    height: 20px;\n    background-size: 20px auto;\n    .backgroundImage('btn_radio.png');\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace\n    .entryVariableAddSpaceCloudWrapperWorkspace\n    .entryCloudTypeWrapper.on\n    .entryVariableAddSpaceCheckWorkspace {\n    .backgroundImage('btn_radio_on.png');\n}\n.entryVariableAddSpaceGlobalWrapperWorkspace.on .entryVariableAddSpaceCloudWrapperWorkspace {\n    display: block;\n}\n\n.entryVariableAddSpaceCloudWrapperWorkspace {\n    .entryCloudTypeWrapper {\n        position: relative;\n        margin-bottom: 12px;\n        &:last-child {\n            margin-bottom: 0px;\n        }\n    }\n}\n\n.entryVariableSplitterWorkspace {\n    border: 1px solid #d6e9f4;\n    border-width: 1px 0;\n}\n.entryVariableSplitterWorkspace + .entryVariableSplitterWorkspace {\n    border-top: 0;\n}\n.entryVariableSplitterWorkspace .list + .list {\n    border-top: 1px solid #d6e9f4;\n}\n.entryVariableSplitterWorkspace.all .list + .list {\n    border-top: 1px solid #d6e9f4;\n}\n.entryVariableSplitterWorkspace.all {\n    border-top: none;\n}\n.entryVariableSplitterWorkspace.all .list .inpt_box {\n    background-color: #ecf8ff;\n}\n.entryVariableSplitterWorkspace.all .list.unfold .inpt_box {\n    background-color: #fff;\n}\n.entryVariableSplitterWorkspace .list .inpt .editBoxInput {\n    border: 1px solid #aac5d5;\n    background-color: #f9f9f9;\n    color: #cbcbcb;\n}\n.entryVariableSplitterWorkspace .list .inpt input[type='text'] {\n    width: 100%;\n    height: 24px;\n    padding: 6px 8px 5px;\n    border: 1px solid #aac5d5;\n    border-radius: 4px;\n    outline: 0;\n    background-color: #fff;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.2px;\n    line-height: 11px;\n    -webkit-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.entryVariableSplitterWorkspace .list .inpt span {\n    width: 100%;\n    padding: 6px 8px 5px;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.2px;\n    line-height: 11px;\n    -webkit-box-sizing: border-box;\n    box-sizing: border-box;\n    text-overflow: ellipsis;\n    overflow: hidden;\n    white-space: nowrap;\n    display: block;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box {\n    display: none;\n    border-top: 1px solid #aac5d5;\n    padding: 12px 26px 10px 26px;\n    background-color: #bfd8e6;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .box_sjt {\n    display: block;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.4px;\n    vertical-align: top;\n    line-height: 12px;\n    margin-bottom: 9px;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .box_sjt:before {\n    display: inline-block;\n    width: 4px;\n    height: 4px;\n    border-radius: 50%;\n    margin: 3px 8px 0 0;\n    background-color: #4f80ff;\n    vertical-align: top;\n    content: '';\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .val_attr .attr_inpt.hidden {\n    display: none;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .val_attr .slide_inpt .chk_box {\n    position: relative;\n    font-size: 0;\n    cursor: pointer;\n    margin-bottom: 3px;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .val_attr .slide_inpt .cnt_box {\n    overflow: hidden;\n    font-size: 0;\n    margin-left: 24px;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .val_attr .slide_inpt .cnt_box .dash {\n    padding: 0 2px;\n    font-size: 10px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.4px;\n    line-height: 24px;\n}\n.entryVariableSplitterWorkspace\n    .list\n    .attr_inner_box\n    .val_attr\n    .slide_inpt\n    .cnt_box\n    input[type='text']:disabled {\n    border: 1px solid #e2e2e2;\n    background-color: #f9f9f9;\n    color: #cbcbcb;\n}\n\n.entryVariableSplitterWorkspace .list .attr_inner_box .use_obj .obj_list .text {\n    display: block;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    height: 33px;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.4px;\n    word-break: break-all;\n    white-space: nowrap;\n    line-height: 34px;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .use_obj .obj_list .text.red {\n    color: #ff4b4b;\n    padding-left: 10px;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr.hidden {\n    display: none;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .scroll_box {\n    max-height: 160px;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .scroll_box.on {\n    padding-right: 20px;\n}\n.scroll_box:not(.on) .simplebar-vertical {\n    display: none;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .scroll_box .simplebar-scrollbar {\n    opacity: 0.8;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .cnt_list {\n    margin: 0;\n    padding: 0;\n    list-style: none;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .cnt_list li {\n    position: relative;\n    margin: 8px 0 0 0;\n    padding: 0 34px 0 28px;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .cnt_list li:first-child {\n    margin-top: 0;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .cnt_list .del {\n    right: 0;\n    top: 0;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .cnt_list input[type='text'] {\n    width: 100%;\n    padding: 6px 8px 5px;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px;\n    outline: 0;\n    background-color: #fff;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.2px;\n    line-height: 11px;\n    -webkit-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.obj_list {\n    overflow: hidden;\n    margin: 0;\n    padding: 0;\n    list-style: none;\n}\n.entryVariableSplitterWorkspace .list .use_block {\n    display: none;\n    padding: 4px 26px 4px 32px;\n    background-color: #d6e9f4;\n}\n.entryVariableSplitterWorkspace .list .use_block .obj_list li {\n    position: relative;\n    -webkit-box-sizing: content-box;\n    box-sizing: content-box;\n    list-style: none;\n    height: 33px;\n    margin: 0;\n    padding: 4px 4px 4px 42px;\n    border-top: 1px solid #aac5d5;\n}\n.entryVariableSplitterWorkspace .list .use_block .obj_list li:first-child {\n    border-top: 0;\n}\n.entryVariableSplitterWorkspace .list .use_block .obj_list .thmb {\n    overflow: hidden;\n    position: absolute;\n    top: 4px;\n    left: 4px;\n    height: 33px;\n    width: 30px;\n    border: 1px solid #e2e2e2;\n    border-radius: 4px;\n    background-color: #fff;\n    background-size: auto 80%;\n    background-repeat: no-repeat;\n    background-position: center;\n}\n.entryVariableSplitterWorkspace .list .use_block .obj_list .text {\n    display: block;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    height: 33px;\n    font-size: 12px;\n    font-weight: 600;\n    color: #2c313d;\n    letter-spacing: -0.4px;\n    word-break: break-all;\n    white-space: nowrap;\n    line-height: 34px;\n}\n.entryVariableSplitterWorkspace .list .watch.on {\n    .backgroundImage('layers_icon_visible24.svg');\n}\n.entryVariableSplitterWorkspace .list.default_val .inpt_box:before {\n    .backgroundImage('ic_attr_variable_on.svg');\n}\n.entryVariableSplitterWorkspace .list.cloud_val .inpt_box:before {\n    .backgroundImage('ic_attr_variable_cloud_on.png');\n}\n.entryVariableSplitterWorkspace .list.cloud_val .inpt_box:before {\n    .backgroundImage('ic_attr_variable_real_time_on.png');\n}\n.entryVariableSplitterWorkspace .list.local_val .inpt_box:before {\n    .backgroundImage('ic_attr_variable_local.svg');\n}\n.entryVariableSplitterWorkspace .list.default_list .inpt_box:before {\n    .backgroundImage('ic_attr_list.svg');\n}\n.entryVariableSplitterWorkspace .list.cloud_variable .inpt_box:before {\n    .backgroundImage('ic_attr_variable_cloud.svg');\n}\n.entryVariableSplitterWorkspace .list.cloud_list .inpt_box:before {\n    .backgroundImage('ic_attr_list_cloud.svg');\n}\n.entryVariableSplitterWorkspace .list.real_time_variable .inpt_box:before {\n    .backgroundImage('ic_attr_variable_real_time.svg');\n}\n.entryVariableSplitterWorkspace .list.real_time_list .inpt_box:before {\n    .backgroundImage('ic_attr_list_real_time.svg');\n}\n.entryVariableSplitterWorkspace .list.local_list .inpt_box:before {\n    .backgroundImage('ic_attr_list_local.svg');\n}\n.entryVariableSplitterWorkspace .list.default_message .inpt_box:before {\n    left: 10px;\n    .backgroundImage('ic_attr_message_on.svg');\n}\n.entryVariableSplitterWorkspace.fold .attr_link {\n    cursor: pointer;\n}\n.entryVariableSplitterWorkspace.unfold .attr_link {\n    background-color: #fff;\n    cursor: pointer;\n}\n.entryVariableSplitterWorkspace .attr_box {\n    display: none;\n}\n.entryVariableSplitterWorkspace.unfold .attr_box {\n    display: block;\n}\n.entryVariableSplitterWorkspace .list.unfold .attr_inner_box {\n    display: block;\n}\n.entryVariableSplitterWorkspace .list.unfold .use_block {\n    display: block;\n}\n.entryVariableSplitterWorkspace .list.unfold .caution_dsc {\n    display: block;\n}\n.entryVariableSplitterWorkspace .list.unfold .inpt:after {\n    .backgroundImage('layers_arrow_up_nor.png');\n}\n\n.entryVariableSplitterWorkspace .list.default_func .inpt_box,\n.entryVariableSplitterWorkspace .list.default_message .inpt_box {\n    padding: 13px 80px 13px 36px;\n    background-color: #ecf8ff;\n}\n.entryVariableSplitterWorkspace .list.default_func .inpt:after,\n.entryVariableSplitterWorkspace .list.default_message .inpt:after {\n    display: none;\n}\n.entryVariableSplitterWorkspace .list.default_message.unfold .inpt_box {\n    background-color: #fff;\n    -webkit-box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1);\n    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1);\n}\n.entryVariableAdd_box .message_inpt input[type='text']:focus,\n.entryVariableAdd_box .message_inpt input[type='text']:active {\n    border-color: #4f80ff;\n}\n.entryVariableAddSpaceNameWrapperWorkspace .entryVariableAddSpaceInputWorkspace:focus,\n.entryVariableAddSpaceNameWrapperWorkspace .entryVariableAddSpaceInputWorkspace:active {\n    border-color: #4f80ff;\n}\n.entryVariableSplitterWorkspace .list .inpt input[type='text']:focus,\n.entryVariableSplitterWorkspace .list .inpt input[type='text']:active {\n    border-color: #4f80ff;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .val_attr .attr_inpt input[type='text']:focus,\n.entryVariableSplitterWorkspace\n    .list\n    .attr_inner_box\n    .val_attr\n    .attr_inpt\n    input[type='text']:active {\n    border-color: #4f80ff;\n}\n.entryVariableSplitterWorkspace .list .attr_inner_box .list_attr .cnt_list input[type='text']:focus,\n.entryVariableSplitterWorkspace\n    .list\n    .attr_inner_box\n    .list_attr\n    .cnt_list\n    input[type='text']:active {\n    border-color: #4f80ff;\n}\n\n.simplebar-scrollbar {\n    right: 4px;\n    width: 8px;\n    &::before {\n        opacity: 1 !important;\n        background-color: #aac5d5;\n        border-radius: 2.5px;\n    }\n}\n\n// .entryVariableSplitterWorkspace .attr_box .list.default_message .inpt_box:before\n// .entryVariableSplitterWorkspace .attr_box .list>.list .inpt_box:before\n// .entryVariableSplitterWorkspace .list.default_message .inpt_box\n\n.entryVariableAdd_box {\n    .entryVariableAddWorkspace {\n        display: block;\n        overflow: hidden;\n        width: calc(100% - 24px);\n        height: 40px;\n        border: 1px solid #4f80ff;\n        border-radius: 4px;\n        background-color: #fff;\n        font-weight: 600;\n        color: #4f80ff;\n        text-align: center;\n        text-decoration: none;\n        -webkit-box-sizing: border-box;\n        box-sizing: border-box;\n        margin: 12px;\n        font-size: 12px;\n        letter-spacing: -0.28px;\n        line-height: 40px;\n    }\n}\n\n.entryVariableSplitterWorkspace {\n    background-color: #fff;\n    border: 1px solid #d6e9f4;\n\n    &.message,\n    &.func {\n        border-top: none;\n    }\n\n    .attr_box {\n        border-top: 1px solid #d6e9f4;\n\n        .default_message {\n            &.unfold {\n                border-color: #aac5d5;\n                outline: 1px solid #aac5d5;\n            }\n        }\n    }\n\n    &.list.global.fold,\n    &.variable.global.fold {\n        border-bottom: 1px solid #aac5d5;\n    }\n\n    &.entryVariableSplitterWorkspace.unfold {\n        .attr_box {\n            border-top: 1px solid #d6e9f4;\n\n            .list .list {\n                &:first-child {\n                    margin-top: 0;\n                }\n            }\n            .default_func,\n            .default_message,\n            .cloud_list,\n            .real_time_list,\n            .default_list,\n            .local_list,\n            .cloud_variable,\n            .real_time_variable,\n            .local_val,\n            .default_val {\n                &.unfold {\n                    border-color: #aac5d5;\n                    outline: 1px solid #aac5d5;\n                    border-top: none;\n                    margin-top: 1px;\n                }\n                .inpt_box {\n                    &::before {\n                        left: 8px;\n                    }\n                    .watch {\n                        margin-left: 2px;\n                        margin-right: 8px;\n                    }\n                }\n            }\n        }\n    }\n\n    &.unfold {\n        .attr_link {\n            &::after {\n                width: 24px;\n                height: 24px;\n                border-radius: 0;\n                .backgroundImage('folder_open.svg');\n                background-color: inherit;\n                background-size: auto;\n            }\n        }\n    }\n\n    .attr_link {\n        position: relative;\n        display: block;\n        height: 38px;\n        padding: 0 14px 0 12px;\n        font-size: 10px;\n        letter-spacing: -0.4px;\n        font-weight: 600;\n        color: #2c313d;\n        text-decoration: none;\n        word-break: break-all;\n        cursor: default;\n        line-height: 38px;\n        margin-bottom: 1px;\n\n        &::after {\n            display: inline-block;\n            position: absolute;\n            top: 7px;\n            right: 14px;\n            overflow: hidden;\n            background-color: #4f80ff;\n            content: '';\n            width: 24px;\n            height: 24px;\n            border-radius: 0;\n            .backgroundImage('folder_close.svg');\n            background-color: inherit;\n            background-size: auto;\n        }\n    }\n\n    .attr_box {\n        .list {\n            // > .list {\n            &.fold {\n                input {\n                    margin-left: 4px;\n                    pointer-events: none;\n                    border: none;\n                    background: transparent;\n                    padding: 0;\n                }\n            }\n\n            &.unfold {\n                .used_function_dsc,\n                .caution_dsc {\n                    background-color: #d6e9f4;\n                    font-size: 10px;\n                    font-weight: 600;\n                    letter-spacing: -0.4px;\n                    color: #4d616e;\n                    padding-top: 3px;\n                }\n\n                .inpt_box {\n                    &::after {\n                        .backgroundImage('layers_arrow_up_nor.svg');\n                    }\n                    background-color: #d6e9f4;\n\n                    .arrowDown {\n                        .backgroundImage('layers_arrow_up_nor.svg');\n                    }\n                }\n\n                .attr_inner_box {\n                    position: relative;\n                    background-color: #d6e9f4;\n\n                    .val_type_txt {\n                        position: absolute;\n                        top: 15px;\n                        right: 20px;\n                        font-size: 9px;\n                        font-weight: 600;\n                        letter-spacing: -0.36px;\n                        color: #4d616e;\n                    }\n                }\n            }\n\n            .inpt_box {\n                display: flex;\n                padding: 13px 0;\n                position: relative;\n                -webkit-box-sizing: content-box;\n                box-sizing: content-box;\n                background-color: #f7fcff;\n                align-items: center;\n\n                &::before {\n                    margin-left: 10px;\n                    width: 24px;\n                    height: 24px;\n                    background-size: 24px auto;\n                    content: '';\n                }\n\n                .watch {\n                    margin-left: 4px;\n                    width: 18px;\n                    height: 18px;\n                    font-size: 0;\n                    .backgroundImage('layers_icon_unvisible24.svg');\n                    background-size: 18px auto;\n\n                    &.on {\n                        .backgroundImage('layers_icon_visible24.svg');\n                    }\n                }\n\n                .inpt {\n                    position: relative;\n                    overflow: hidden;\n                    height: 24px;\n                    flex: 1;\n                    margin-right: 20px;\n\n                    input[type='text'],\n                    span {\n                        font-size: 10px;\n                        line-height: 10px;\n                    }\n                }\n\n                .arrowDown {\n                    width: 10px;\n                    height: 8px;\n                    margin-right: 20px;\n                    background-size: auto;\n                    .backgroundImage('layers_arrow_down_nor.svg');\n                }\n\n                .del {\n                    margin-right: 20px;\n                    width: 20px;\n                    height: 20px;\n                    background-position: 50%;\n                    background-size: auto;\n                    .backgroundImage('layers_icon_close_nor_new.svg');\n                    background-color: transparent;\n                    background-repeat: no-repeat;\n                    cursor: pointer;\n                }\n            }\n\n            .attr_inner_box {\n                padding: 0;\n\n                .box_sjt {\n                    &::before {\n                        width: 3px;\n                        height: 3px;\n                        background-color: #728997;\n                    }\n                    position: relative;\n                    left: -10px;\n                    margin-bottom: 12px;\n                    font-size: 11px;\n                    font-weight: 600;\n                    letter-spacing: -0.44px;\n                }\n\n                .list_attr {\n                    .btn_box {\n                        display: flex;\n\n                        .btn_list {\n                            flex: 1;\n                            display: inline-block;\n                            height: 28px;\n                            border-radius: 4px;\n                            border: 1px solid #aac5d5;\n                            background-color: #fff;\n                            font-size: 9px;\n                            letter-spacing: -0.36px;\n                            font-weight: 600;\n                            color: #2c313d;\n                            text-align: center;\n                            line-height: 26px;\n                            cursor: pointer;\n                            margin-bottom: 12px;\n\n                            & + .btn_list {\n                                margin-left: 4px;\n                            }\n                        }\n                    }\n\n                    .list_cnt {\n                        .cnt_sjt {\n                            font-size: 10px;\n                            font-weight: 600;\n                            letter-spacing: -0.4px;\n                            color: #4d616e;\n                            margin-bottom: 6px;\n                        }\n                        .cnt_inpt {\n                            overflow: hidden;\n                            position: relative;\n                            -webkit-box-sizing: content-box;\n                            box-sizing: content-box;\n                            width: 78px;\n                            height: 24px;\n                            border-radius: 4px;\n                            border: solid 1px #aac5d5;\n                            margin-bottom: 12px;\n\n                            .btn_cnt {\n                                display: inline-block;\n                                overflow: hidden;\n                                width: 24px;\n                                height: 24px;\n                                background-color: #ecf8ff;\n                                border-radius: 4px 0 0 4px;\n                                font-size: 24px;\n                                color: #2c313d;\n                                text-decoration: none;\n                                text-align: center;\n                                line-height: 24px;\n\n                                &::before {\n                                    content: ' ';\n                                    display: inline-block;\n                                    position: relative;\n                                    top: -3px;\n                                    width: 8px;\n                                    height: 8px;\n                                    .backgroundImage('btn_minus.svg');\n                                    background-position-y: center;\n                                    background-repeat: no-repeat;\n                                }\n\n                                &.plus {\n                                    &::before {\n                                        .backgroundImage('btn_plus.svg');\n                                    }\n                                    border-radius: 0 4px 4px 0;\n                                }\n\n                                &[disabled] {\n                                    opacity: 0.5;\n                                    cursor: not-allowed;\n                                }\n                            }\n\n                            input[type='text'] {\n                                width: 30px;\n                                height: 24px;\n                                background-color: #fff;\n                                outline: 0;\n                                font-size: 10px;\n                                letter-spacing: -0.4px;\n                                color: #2c313d;\n                                font-weight: 600;\n                                line-height: 14px;\n                                text-align: center;\n                                vertical-align: top;\n                                border: 0;\n\n                                &[disabled] {\n                                    opacity: 0.5;\n                                    cursor: not-allowed;\n                                }\n                            }\n                        }\n                    }\n                    .cnt_group {\n                        .cnt_label {\n                            font-size: 10px;\n                            font-weight: 600;\n                            letter-spacing: -0.4px;\n                            color: #4d616e;\n                            margin-bottom: 5px;\n                        }\n\n                        .cnt_list {\n                            margin: 0;\n                            padding: 0;\n                            list-style: none;\n\n                            li {\n                                position: relative;\n                                margin-top: 4px;\n                                padding: 0 32px 0 0;\n\n                                &:first-child {\n                                    margin-top: 0;\n                                }\n                            }\n\n                            .cnt {\n                                position: absolute;\n                                left: 10px;\n                                font-size: 10px;\n                                font-weight: 600;\n                                letter-spacing: -0.4px;\n                                color: #979797;\n                                line-height: 24px;\n                            }\n\n                            .del {\n                                right: 0;\n                                top: 0;\n                            }\n\n                            input[type='text'] {\n                                width: 100%;\n                                height: 24px;\n                                padding-left: 26px;\n                                border: 1px solid #aac5d5;\n                                border-radius: 4px;\n                                outline: 0;\n                                background-color: #fff;\n                                font-size: 10px;\n                                font-weight: 600;\n                                letter-spacing: -0.4px;\n                                color: #2c313d;\n                                line-height: 24px;\n                                -webkit-box-sizing: border-box;\n                                box-sizing: border-box;\n                            }\n                        }\n                    }\n                }\n\n                .val_attr,\n                .list_attr {\n                    padding: 15px 20px 15px 20px;\n\n                    .attr_inpt {\n                        display: block;\n                        margin-bottom: 12px;\n\n                        label {\n                            display: block;\n                            font-size: 10px;\n                            font-weight: 600;\n                            letter-spacing: -0.4px;\n                            color: #4d616e;\n                            line-height: 10px;\n                            margin-bottom: 5px;\n                        }\n\n                        .val_inptbox {\n                            display: block;\n\n                            input {\n                                width: 100%;\n                                padding: 7px 8px 6px;\n                                border: 1px solid #aac5d5;\n                                border-radius: 4px;\n                                background-color: #fff;\n                                font-size: 10px;\n                                font-weight: bold;\n                                font-stretch: normal;\n                                font-style: normal;\n                                line-height: normal;\n                                letter-spacing: -0.4px;\n                                color: #2c313d;\n                            }\n                        }\n                    }\n\n                    .slide_inpt {\n                        .entryVariableAddSpaceCheckWorkspace {\n                            &.on {\n                                .backgroundImage('btn_checkbox_on.svg');\n                            }\n                            display: inline-block;\n                            width: 18px;\n                            height: 18px;\n                            background-size: 18px auto;\n                            .backgroundImage('btn_checkbox.svg');\n                            vertical-align: top;\n                            margin-right: 8px;\n                        }\n\n                        .chk_text {\n                            display: inline-block;\n                            font-weight: 600;\n                            letter-spacing: -0.4px;\n                            vertical-align: top;\n                            font-size: 10px;\n                            line-height: 18px;\n                            letter-spacing: -0.4px;\n                            color: #4d616e;\n                        }\n\n                        .cnt_box {\n                            input {\n                                width: 56px;\n                                padding: 7px 8px 6px;\n                                border: 1px solid #aac5d5;\n                                border-radius: 4px;\n                                background-color: #fff;\n                                font-size: 10px;\n                                font-weight: bold;\n                                letter-spacing: -0.4px;\n                                color: #2c313d;\n                            }\n                        }\n                    }\n                }\n\n                .use_obj {\n                    padding: 15px 14px 12px 20px;\n\n                    .box_sjt {\n                        margin-bottom: 8px;\n                    }\n\n                    .obj_list {\n                        li {\n                            position: relative;\n                            height: 24px;\n                            margin-bottom: 6px;\n\n                            .thmb {\n                                position: static;\n                                display: inline-block;\n                                overflow: hidden;\n                                height: 24px;\n                                width: 22px;\n                                border: 1px solid #aac5d5;\n                                border-radius: 4px;\n                                background-color: #fff;\n                                background-size: auto 80%;\n                                background-repeat: no-repeat;\n                                background-position: center;\n                                margin-right: 8px;\n                                vertical-align: top;\n                            }\n\n                            .text {\n                                display: inline-block;\n                                overflow: hidden;\n                                text-overflow: ellipsis;\n                                color: #4d616e;\n                                white-space: nowrap;\n                                line-height: 24px;\n                                font-size: 10px;\n                                font-weight: 600;\n                                letter-spacing: -0.4px;\n                            }\n                        }\n                    }\n                }\n\n                .func_attr {\n                    padding: 15px 14px 15px 20px;\n                    border-bottom: 1px solid #aac5d5;\n\n                    .box_sjt {\n                        &::before {\n                            width: 3px;\n                            height: 3px;\n                            background-color: #728997;\n                        }\n                        position: relative;\n                        left: -10px;\n                        margin-bottom: 8px;\n                    }\n\n                    .check_inpt {\n                        margin: 3px 0 3px;\n\n                        .entryFuncAddLocalVarCheckWorkspace,\n                        .entryFuncAddResultCheckWorkspace {\n                            display: inline-block;\n                            width: 18px;\n                            height: 18px;\n                            background-size: 18px;\n                            vertical-align: top;\n                            .backgroundImage('btn_checkbox.svg');\n                        }\n\n                        .entryFuncAddLocalVarCheckWorkspace.on,\n                        .entryFuncAddResultCheckWorkspace.on {\n                            .backgroundImage('btn_checkbox_on.svg');\n                        }\n\n                        .chk_text {\n                            display: inline-block;\n                            margin-left: 10px;\n                            font-size: 10px;\n                            font-weight: bold;\n                            letter-spacing: -0.4px;\n                            color: #4d616e;\n                            line-height: 18px;\n                            font-weight: 600;\n                            vertical-align: top;\n                        }\n\n                        .cnt_inpt {\n                            margin: 3px 0 0 28px;\n                            overflow: hidden;\n                            position: relative;\n                            -webkit-box-sizing: content-box;\n                            box-sizing: content-box;\n                            width: 78px;\n                            height: 24px;\n                            border-radius: 4px;\n                            border: solid 1px #aac5d5;\n\n                            .btn_cnt {\n                                display: inline-block;\n                                overflow: hidden;\n                                width: 24px;\n                                height: 24px;\n                                background-color: #ecf8ff;\n                                border-radius: 4px 0 0 4px;\n                                font-size: 24px;\n                                color: #2c313d;\n                                text-decoration: none;\n                                text-align: center;\n                                line-height: 24px;\n\n                                &::before {\n                                    content: ' ';\n                                    display: inline-block;\n                                    position: relative;\n                                    top: -3px;\n                                    width: 8px;\n                                    height: 8px;\n                                    .backgroundImage('btn_minus.svg');\n                                    background-position-y: center;\n                                    background-repeat: no-repeat;\n                                }\n\n                                &.plus {\n                                    &::before {\n                                        .backgroundImage('btn_plus.svg');\n                                    }\n                                    border-radius: 0 4px 4px 0;\n                                }\n\n                                &[disabled] {\n                                    opacity: 0.5;\n                                    cursor: not-allowed;\n                                }\n                            }\n\n                            input[type='text'] {\n                                width: 30px;\n                                height: 24px;\n                                background-color: #fff;\n                                outline: 0;\n                                font-size: 10px;\n                                letter-spacing: -0.4px;\n                                color: #2c313d;\n                                font-weight: 600;\n                                line-height: 14px;\n                                text-align: center;\n                                vertical-align: top;\n                                border: 0;\n\n                                &[disabled] {\n                                    opacity: 0.5;\n                                    cursor: not-allowed;\n                                }\n                            }\n                        }\n                    }\n\n                    .cnt_group {\n                        margin-top: 10px;\n                        margin-left: 28px;\n\n                        .cnt_label {\n                            font-size: 10px;\n                            font-weight: 600;\n                            letter-spacing: -0.4px;\n                            color: #4d616e;\n                            margin-bottom: 5px;\n                        }\n\n                        &[disabled] {\n                            display: none;\n                        }\n\n                        .scroll_box {\n                            max-height: 135px;\n                        }\n\n                        .scroll_box.on {\n                            padding-right: 20px;\n                        }\n\n                        .cnt_list {\n                            margin: 0;\n                            padding: 0;\n                            list-style: none;\n\n                            li {\n                                position: relative;\n                                margin-top: 4px;\n                                padding: 0 32px 0 0;\n\n                                &:first-child {\n                                    margin-top: 0;\n                                }\n                            }\n\n                            .cnt {\n                                position: absolute;\n                                left: 10px;\n                                font-size: 10px;\n                                font-weight: 600;\n                                letter-spacing: -0.4px;\n                                color: #979797;\n                                line-height: 24px;\n                            }\n\n                            .del {\n                                right: 0;\n                                top: 0;\n                            }\n\n                            input[type='text'] {\n                                width: 100%;\n                                height: 24px;\n                                padding-left: 20px;\n                                border: 1px solid #aac5d5;\n                                border-radius: 4px;\n                                outline: 0;\n                                background-color: #fff;\n                                font-size: 10px;\n                                font-weight: 600;\n                                letter-spacing: -0.4px;\n                                color: #2c313d;\n                                line-height: 24px;\n                                -webkit-box-sizing: border-box;\n                                box-sizing: border-box;\n                            }\n                        }\n                    }\n                }\n\n                .use_obj {\n                    padding: 15px 14px 15px 20px;\n                    border-top: solid 1px #aac5d5;\n                }\n            }\n\n            .use_block {\n                padding: 15px 14px 11px 20px;\n\n                .box_sjt {\n                    &::before {\n                        content: '';\n                        display: inline-block;\n                        border-radius: 50%;\n                        margin: 3px 8px 0 0;\n                        vertical-align: top;\n                        width: 3px;\n                        height: 3px;\n                        background-color: #728997;\n                    }\n\n                    position: relative;\n                    left: -10px;\n                    margin-bottom: 5px;\n                    display: block;\n                    font-size: 12px;\n                    font-weight: 600;\n                    color: #2c313d;\n                    letter-spacing: -0.4px;\n                    line-height: 12px;\n                }\n\n                .obj_list {\n                    li {\n                        padding: 3px 4px 3px 42px;\n                        border: none;\n                        height: 24px;\n\n                        .thmb {\n                            border: solid 1px #aac5d5;\n                            width: 22px;\n                            height: 24px;\n                        }\n\n                        .text {\n                            height: 24px;\n                            font-size: 10px;\n                            line-height: 24px;\n                            color: #4d616e;\n                        }\n                    }\n                }\n            }\n\n            &.default_message {\n                &.unfold {\n                    .inpt_box {\n                        -webkit-box-shadow: 0 1px 1px 0 #aac5d5;\n                        box-shadow: 0 1px 1px 0 #aac5d5;\n                    }\n                }\n                .inpt_box {\n                    &::before {\n                        left: 10px;\n                        .backgroundImage('ic_attr_message.svg');\n                    }\n                }\n            }\n\n            &.default_val {\n                .inpt_box {\n                    &::before {\n                        left: 10px;\n                        .backgroundImage('ic_attr_variable.svg');\n                    }\n                }\n            }\n\n            &.real_time_list,\n            &.cloud_list,\n            &.default_list {\n                .cnt_group {\n                    .del {\n                        position: absolute;\n                        width: 22px;\n                        height: 22px;\n                        right: 6px;\n                        top: 0px;\n                        display: inline-block;\n                        background-position: 50%;\n                        .backgroundImage('layers_icon_close_nor_new.svg');\n                        background-color: transparent;\n                        background-repeat: no-repeat;\n                        background-position: 50%;\n                        border: none;\n                        cursor: pointer;\n                    }\n                }\n                .inpt_box {\n                    &::before {\n                        left: 10px;\n                    }\n                }\n            }\n\n            &.default_list {\n                .inpt_box {\n                    &::before {\n                        .backgroundImage('ic_attr_list.svg');\n                    }\n                }\n            }\n\n            &.default_func {\n                .del {\n                    .backgroundImage('layers_icon_close_nor_new.svg');\n                    background-color: transparent;\n                    background-repeat: no-repeat;\n                    background-position: 50%;\n                    border: none;\n                    cursor: pointer;\n                }\n\n                .cnt_group {\n                    .del {\n                        position: absolute;\n                        width: 22px;\n                        height: 22px;\n                        right: 6px;\n                        top: 0px;\n                        display: inline-block;\n                    }\n                }\n\n                &.unfold {\n                    .caution_dsc {\n                        background-color: #d6e9f4;\n                    }\n\n                    .inpt_box {\n                        &::after {\n                            .backgroundImage('layers_arrow_up_nor.svg');\n                        }\n                        background-color: #d6e9f4;\n                    }\n\n                    .attr_inner_box {\n                        background-color: #d6e9f4;\n                    }\n                }\n\n                .inpt_box {\n                    &::before {\n                        left: 10px;\n                        .backgroundImage('ic_attr_func.svg');\n                    }\n\n                    &::after {\n                        width: 10px;\n                        height: 8px;\n                        .backgroundImage('layers_arrow_down_nor.svg');\n                        background-size: auto;\n                        background-repeat: no-repeat;\n                    }\n\n                    background-color: #f7fcff;\n\n                    .inpt {\n                        input[type='text'],\n                        span {\n                            font-size: 10px;\n                            line-height: 10px;\n                        }\n                    }\n                }\n\n                .attr_inner_box {\n                    padding: 0;\n\n                    .func_attr {\n                        padding: 15px 14px 15px 20px;\n                        border-bottom: 1px solid #aac5d5;\n\n                        .box_sjt {\n                            &::before {\n                                width: 3px;\n                                height: 3px;\n                                background-color: #728997;\n                            }\n                            position: relative;\n                            left: -10px;\n                            margin-bottom: 8px;\n                        }\n\n                        .check_inpt {\n                            margin: 3px 0 3px;\n\n                            .entryFuncAddLocalVarCheckWorkspace,\n                            .entryFuncAddResultCheckWorkspace {\n                                display: inline-block;\n                                width: 18px;\n                                height: 18px;\n                                background-size: 18px;\n                                vertical-align: top;\n                                .backgroundImage('btn_checkbox.svg');\n                            }\n\n                            .entryFuncAddLocalVarCheckWorkspace.on,\n                            .entryFuncAddResultCheckWorkspace.on {\n                                .backgroundImage('btn_checkbox_on.svg');\n                            }\n\n                            .chk_text {\n                                display: inline-block;\n                                margin-left: 10px;\n                                font-size: 10px;\n                                font-weight: bold;\n                                letter-spacing: -0.4px;\n                                color: #4d616e;\n                                line-height: 18px;\n                                font-weight: 600;\n                                vertical-align: top;\n                            }\n\n                            .cnt_inpt {\n                                margin: 3px 0 0 28px;\n                                overflow: hidden;\n                                position: relative;\n                                -webkit-box-sizing: content-box;\n                                box-sizing: content-box;\n                                width: 78px;\n                                height: 24px;\n                                border-radius: 4px;\n                                border: solid 1px #aac5d5;\n\n                                .btn_cnt {\n                                    display: inline-block;\n                                    overflow: hidden;\n                                    width: 24px;\n                                    height: 24px;\n                                    background-color: #ecf8ff;\n                                    border-radius: 4px 0 0 4px;\n                                    font-size: 24px;\n                                    color: #2c313d;\n                                    text-decoration: none;\n                                    text-align: center;\n                                    line-height: 24px;\n\n                                    &::before {\n                                        content: ' ';\n                                        display: inline-block;\n                                        position: relative;\n                                        top: -3px;\n                                        width: 8px;\n                                        height: 8px;\n                                        .backgroundImage('btn_minus.svg');\n                                        background-position-y: center;\n                                        background-repeat: no-repeat;\n                                    }\n\n                                    &.plus {\n                                        &::before {\n                                            .backgroundImage('btn_plus.svg');\n                                        }\n                                        border-radius: 0 4px 4px 0;\n                                    }\n\n                                    &[disabled] {\n                                        opacity: 0.5;\n                                        cursor: not-allowed;\n                                    }\n                                }\n\n                                input[type='text'] {\n                                    width: 30px;\n                                    height: 24px;\n                                    background-color: #fff;\n                                    outline: 0;\n                                    font-size: 10px;\n                                    letter-spacing: -0.4px;\n                                    color: #2c313d;\n                                    font-weight: 600;\n                                    line-height: 14px;\n                                    text-align: center;\n                                    vertical-align: top;\n                                    border: 0;\n\n                                    &[disabled] {\n                                        opacity: 0.5;\n                                        cursor: not-allowed;\n                                    }\n                                }\n                            }\n                        }\n\n                        .cnt_group {\n                            margin-top: 10px;\n                            margin-left: 28px;\n\n                            .cnt_label {\n                                font-size: 10px;\n                                font-weight: 600;\n                                letter-spacing: -0.4px;\n                                color: #4d616e;\n                                margin-bottom: 5px;\n                            }\n\n                            &[disabled] {\n                                display: none;\n                            }\n\n                            .scroll_box {\n                                max-height: 135px;\n                            }\n\n                            .scroll_box.on {\n                                padding-right: 20px;\n                            }\n\n                            .cnt_list {\n                                margin: 0;\n                                padding: 0;\n                                list-style: none;\n\n                                li {\n                                    position: relative;\n                                    margin-top: 4px;\n                                    padding: 0 32px 0 0;\n\n                                    &:first-child {\n                                        margin-top: 0;\n                                    }\n                                }\n\n                                .cnt {\n                                    position: absolute;\n                                    left: 10px;\n                                    font-size: 10px;\n                                    font-weight: 600;\n                                    letter-spacing: -0.4px;\n                                    color: #979797;\n                                    line-height: 24px;\n                                }\n\n                                .del {\n                                    right: 0;\n                                    top: 0;\n                                }\n\n                                input[type='text'] {\n                                    width: 100%;\n                                    height: 24px;\n                                    padding-left: 20px;\n                                    border: 1px solid #aac5d5;\n                                    border-radius: 4px;\n                                    outline: 0;\n                                    background-color: #fff;\n                                    font-size: 10px;\n                                    font-weight: 600;\n                                    letter-spacing: -0.4px;\n                                    color: #2c313d;\n                                    line-height: 24px;\n                                    -webkit-box-sizing: border-box;\n                                    box-sizing: border-box;\n                                }\n                            }\n                        }\n                    }\n                }\n\n                .use_block {\n                    padding: 15px 14px 11px 20px;\n\n                    .box_sjt {\n                        &::before {\n                            content: '';\n                            display: inline-block;\n                            border-radius: 50%;\n                            margin: 3px 8px 0 0;\n                            vertical-align: top;\n                            width: 3px;\n                            height: 3px;\n                            background-color: #728997;\n                        }\n\n                        position: relative;\n                        left: -10px;\n                        margin-bottom: 5px;\n                        display: block;\n                        font-size: 12px;\n                        font-weight: 600;\n                        color: #2c313d;\n                        letter-spacing: -0.4px;\n                        line-height: 12px;\n                    }\n\n                    .obj_list {\n                        li {\n                            padding: 3px 4px 3px 42px;\n                            border: none;\n                            height: 24px;\n\n                            .thmb {\n                                border: solid 1px #aac5d5;\n                                width: 22px;\n                                height: 24px;\n                            }\n\n                            .text {\n                                height: 24px;\n                                font-size: 10px;\n                                line-height: 24px;\n                                color: #4d616e;\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n\n.entryVariableAdd_box {\n    .entryVariableSplitterWorkspace {\n        .attr_box {\n            .list.unfold {\n                outline: 1px solid #aac5d5;\n                border-color: #aac5d5;\n            }\n        }\n    }\n    .entryVariableAddSpaceWorkspace {\n        border: solid 1px #aac5d5;\n        background-color: #d6e9f4;\n\n        .entryVariableAddSpaceDataWrapperWorkspace {\n            padding: 18px 20px 0px 20px;\n        }\n\n        .entryVariableAddSpaceNameWrapperWorkspace {\n            margin-bottom: 6px;\n        }\n\n        .entryVariableAddSpaceSelectWrapperWorkspace {\n            height: 28px;\n            border: solid 1px #aac5d5;\n            border-radius: 4px;\n            background-color: #fff;\n            white-space: nowrap;\n            margin-bottom: 10px;\n\n            .button {\n                &.on {\n                    color: #4f80ff;\n                    border-color: #4f80ff;\n                    background-color: #ffffff;\n                }\n                &:nth-child(even) {\n                    border-radius: 0 4px 4px 0;\n                    margin-left: 2px;\n                }\n                display: inline-block;\n                height: 28px;\n                width: 50%;\n                margin-top: -1px;\n                margin-left: -1px;\n                color: #728997;\n                font-size: 9px;\n                font-weight: 600;\n                text-align: center;\n                line-height: 26px;\n                letter-spacing: -0.36px;\n                vertical-align: top;\n                border: solid 1px transparent;\n                border-radius: 4px 0 0 4px;\n                cursor: pointer;\n            }\n        }\n\n        .entryVariableTypeBoxWrapper {\n            &.on {\n                display: block;\n            }\n            display: none;\n            margin-bottom: 10px;\n\n            .entryVariableTypeWrapper {\n                &.on {\n                    .radioButton {\n                        .backgroundImage('btn_radio_on.svg');\n                    }\n                }\n                color: #4d616e;\n                font-size: 10px;\n                font-weight: 600;\n                line-height: 18px;\n                letter-spacing: -0.4px;\n                vertical-align: top;\n                .radioButton {\n                    display: inline-block;\n                    width: 18px;\n                    height: 18px;\n                    vertical-align: top;\n                    margin-right: 10px;\n                    margin-bottom: 6px;\n                    .backgroundImage('btn_radio.svg');\n                    cursor: pointer;\n                }\n\n                .entryVariableAddSpaceCheckWorkspace {\n                    cursor: pointer;\n                }\n            }\n        }\n\n        .entryVariableAddSpaceButtonWrapperWorkspace {\n            display: flex;\n            overflow: hidden;\n            margin-top: 10px;\n            border-top: 1px solid #aac5d5;\n            font-size: 0;\n            text-align: center;\n            padding: 15px 18px 18px 8px;\n\n            .entryVariableAddSpaceButtonWorkspace {\n                display: inline-block;\n                flex: 1;\n                height: 32px;\n                color: #2c313d;\n                font-size: 9px;\n                font-weight: 600;\n                letter-spacing: -0.36px;\n                border: 1px solid #aac5d5;\n                border-radius: 4px;\n                background-color: #fff;\n                text-align: center;\n                text-decoration: none;\n                line-height: 30px;\n                margin: 0 2px;\n                cursor: pointer;\n            }\n\n            .entryVariableAddSpaceConfirmWorkspace {\n                color: #fff;\n                background-color: #4f80ff;\n                border-color: #4f80ff;\n            }\n        }\n    }\n\n    .message_inpt {\n        border: solid 1px #aac5d5;\n        background-color: #d6e9f4;\n\n        .msdAddSpaceWrapper {\n            padding: 18px 20px 0 20px;\n            border-top: 1px solid #d6e9f4;\n            margin-bottom: 16px;\n\n            .box_sjt {\n                &::before {\n                    content: '';\n                    display: inline-block;\n                    border-radius: 50%;\n                    margin: 3px 8px 0 0;\n                    vertical-align: top;\n                    width: 3px;\n                    height: 3px;\n                    background-color: #728997;\n                }\n\n                position: relative;\n                left: -10px;\n                margin-bottom: 8px;\n                display: block;\n                font-size: 11px;\n                font-weight: 600;\n                color: #2c313d;\n                letter-spacing: -0.44px;\n                line-height: 11px;\n            }\n\n            input {\n                width: 100%;\n                padding: 7px 8px 6px;\n                border: 1px solid #aac5d5;\n                border-radius: 4px;\n                background-color: #fff;\n                color: #2c313d;\n                font-size: 10px;\n                font-weight: 600;\n                letter-spacing: -0.4px;\n            }\n        }\n\n        .entryVariableAddSpaceButtonWrapperWorkspace {\n            display: flex;\n            overflow: hidden;\n            margin-top: 10px;\n            border-top: 1px solid #aac5d5;\n            font-size: 0;\n            text-align: center;\n            padding: 15px 20px 18px 20px;\n\n            .entryVariableAddSpaceButtonWorkspace {\n                &.entryVariableAddSpaceConfirmWorkspace {\n                    color: #fff;\n                    background-color: #4f80ff;\n                    border-color: #4f80ff;\n                }\n                display: inline-block;\n                flex: 1;\n                height: 28px;\n                color: #2c313d;\n                font-size: 9px;\n                font-weight: 600;\n                letter-spacing: -0.36px;\n                border: 1px solid #aac5d5;\n                border-radius: 4px;\n                background-color: #fff;\n                text-align: center;\n                text-decoration: none;\n                line-height: 26px;\n                margin: 0 2px;\n                cursor: pointer;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/css/components/zoomController.less",
    "content": "@keyframes fadeToast {\n    0% {\n        opacity: 0;\n        visibility: hidden;\n        transform: translate3d(0, 7px, 0);\n    }\n    35% {\n        opacity: 1;\n        visibility: visible;\n        transform: none;\n    }\n    70% {\n        opacity: 1;\n        visibility: visible;\n        transform: none;\n    }\n    100% {\n        opacity: 0;\n        visibility: hidden;\n        transform: translate3d(0, 7px, 0);\n    }\n}\n\n.fadeToast {\n    animation-duration: 3s;\n    animation-fill-mode: both;\n    animation-name: fadeToast;\n}\n\n.hideToast {\n    visibility: hidden;\n    opacity: 0;\n}\n\n.toastText {\n    font-family: EntryFont, NanumGothic, 'Nanum Gothic';\n    font-size: 14px;\n    font-weight: bold;\n    font-style: normal;\n    font-stretch: normal;\n    line-height: normal;\n    letter-spacing: -0.5px;\n    text-align: center;\n}\n"
  },
  {
    "path": "src/css/entry.less",
    "content": "@import 'prefix.less';\n@import 'static.less';\n@import 'common.less';\n@import 'minimize.less';\n@import 'codemirror_theme.less';\n@import './components/block.less';\n@import './components/block_menu.less';\n@import './components/board.less';\n@import './components/container.less';\n@import './components/context_menu.less';\n@import './components/engine.less';\n@import './components/function.less';\n@import './components/global_svg.less';\n@import './components/helper.less';\n@import './components/hw_monitor.less';\n@import './components/object.less';\n@import \"./components/painter.less\";\n@import './components/playground.less';\n@import './components/popup.less';\n@import './components/property_panel.less';\n@import './components/scene.less';\n@import './components/stage.less';\n@import './components/state_manager.less';\n@import './components/table.less';\n@import './components/toast.less';\n@import './components/variable_container.less';\n@import './components/pdf.less';\n@import './components/extensions.less';\n@import './components/curtain.less';\n@import './components/console.less';\n@import './components/target_checker.less';\n@import './components/textcoding_helper.less';\n@import './components/tooltip.less';\n@import './components/zoomController.less';\n"
  },
  {
    "path": "src/css/minimize.less",
    "content": ".entryMinimizeWrapper {\n    display: flex;\n    justify-content: center;\n    align-items: flex-start;\n    width: 100%;\n    height: 100vh;\n    overflow: hidden;\n\n    .entry.minimize {\n        display: flex;\n        flex-direction: column;\n        justify-content: center;\n        background: #fff;\n        height: 0;\n        padding-top: 56.25%;\n\n        #entryCanvas {\n            position: absolute;\n        }\n\n        .entryEngineMinimize {\n            margin-top: 48px;\n        }\n    }\n}\n\n@media (min-aspect-ratio: 16/9) {\n    .entry.minimize {\n        min-width: calc((100vh - 48px) * 16 / 9);\n        padding-top: calc(100vh - 48px);\n    }\n}\n\n@media (max-aspect-ratio: 16/9) {\n    .entry.minimize {\n        min-width: unset;\n        max-height: 100vw * 9 / 16;\n        width: 100vw;\n        padding-top: calc(100vh + 48px);\n    }\n}\n\n.entryMinimizeWrapper,\n.entryPopup {\n    .entry.minimize,\n    .entryPopupWindow {\n        #entryCanvasWrapper {\n            background-color: #000;\n            overflow: hidden;\n            width: 100%;\n        }\n        .canvasButton {\n            display: none;\n            box-sizing: border-box;\n        }\n\n        .entryCanvasWorkspace {\n            width: 100%;\n        }\n        &:empty + .canvasButton {\n            display: none;\n        }\n        & + .canvasButton {\n            display: block;\n        }\n\n        &.fsView {\n            .entryMaximizeButtonMinimize {\n                .backgroundImage('minimize/reduce.svg');\n            }\n        }\n\n        &.fullscreen {\n            .entryRunButtonBigMinimizeCurtain {\n                background-color: unset;\n            }\n        }\n\n        &:fullscreen {\n            display: block;\n            #entryCanvasWrapper {\n                display: flex;\n                justify-content: center;\n                align-items: center;\n                height: calc(100% - 48px);\n                #entryCanvas {\n                    width: 100vw;\n                    height: calc(9 / 16 * 100vw);\n                    max-height: calc(100vh - 48px);\n                    max-width: calc(16 / 9 * (100vh - 48px));\n                }\n            }\n            .entryRunButtonBigMinimizeCurtain {\n                z-index: 1;\n            }\n            .entryEngineMinimize {\n                position: absolute;\n                bottom: 0;\n                right: 0;\n                left: 0;\n            }\n        }\n        .canvasButton {\n            display: none;\n        }\n        &:empty,\n        .minimize:empty {\n            z-index: 1;\n            background: #ffffff;\n            &::after {\n                position: relative;\n                content: '';\n                display: block;\n                width: 100%;\n                height: calc(100vh - 2px);\n                background-image: linear-gradient(\n                        90deg,\n                        rgba(255, 255, 255, 0) 0,\n                        rgba(255, 255, 255, 0.8) 50%,\n                        rgba(255, 255, 255, 0) 100%\n                    ),\n                    linear-gradient(#f2f2f2 calc(100% - 48px), transparent 0),\n                    linear-gradient(#f2f2f2 48px, transparent 0),\n                    linear-gradient(#f2f2f2 48px, transparent 0),\n                    linear-gradient(#f2f2f2 48px, transparent 0),\n                    linear-gradient(#f2f2f2 48px, transparent 0);\n                background-size:\n                    200px 100%,\n                    100% 100%,\n                    140px 20px,\n                    99px 20px,\n                    17px 20px,\n                    17px 20px;\n                background-position:\n                    -150% bottom,\n                    0px 0px,\n                    center bottom 14px,\n                    right 92px bottom 14px,\n                    right 57px bottom 14px,\n                    right 18px bottom 14px;\n                background-repeat: no-repeat;\n                animation: loading 2s infinite;\n            }\n        }\n        .entryRemove {\n            display: none;\n        }\n        .entryRunButtonBigMinimize {\n            .backgroundImage('minimize/play_big.svg');\n            position: absolute;\n            top: calc(50% - 55px);\n            left: calc(50% - 56px);\n            width: 111px;\n            height: 111px;\n            border: none;\n            background-repeat: no-repeat;\n            background-position: 50% center;\n            cursor: pointer;\n            z-index: 1;\n            background-color: unset;\n            &:hover {\n                opacity: 1;\n            }\n        }\n      \n        .entryRunButtonBigMinimizeCurtain {\n            position: absolute;\n            top: 0%;\n            width: 100%;\n            height: 100%;\n            border: none;\n            background-color: rgba(0, 0, 0, 0.5);\n            cursor: pointer;\n            z-index: 1;\n        }\n        .entryEngineMinimize {\n            height: 48px;\n            box-sizing: border-box;\n            position: relative;\n            background-color: #ffffff;\n            border-top: solid 1px #f2f2f2;\n            padding-left: 30px;\n            .entryEngineButtonMinimize {\n                border: none;\n                background-color: white;\n                position: relative;\n                margin-top: 16px;\n                margin-right: 24px;\n                float: left;\n                outline: none;\n                color: rgb(44, 49, 61);\n            }\n            .entryCoordinateButtonMinimize {\n                .backgroundImage('minimize/grid.svg');\n                width: 16px;\n                height: 16px;\n                border: 0px;\n                background-color: white;\n                float: right;\n                background-position: 0 0;\n                background-repeat: no-repeat;\n                background-size: 16px;\n            }\n            .entryMaximizeButtonMinimize {\n                .backgroundImage('minimize/fullscreen.svg');\n                width: 16px;\n                height: 16px;\n                border: 0px;\n                background-color: white;\n                float: right;\n                margin-right: 18px;\n                background-position: 0 0;\n                background-repeat: no-repeat;\n                background-size: 15px;\n            }\n            .entryStopButtonMinimize {\n                padding-left: 28px;\n                background-image: none;\n                &:before {\n                    .backgroundImage('minimize/stop.svg');\n                    position: absolute;\n                    left: 0px;\n                    width: 14px;\n                    height: 14px;\n                    background-position: 0 0;\n                    background-repeat: no-repeat;\n                    background-size: 14px auto;\n                    content: '';\n                }\n            }\n            .entryPauseButtonMinimize {\n                padding-left: 30px;\n                &:before {\n                    .backgroundImage('minimize/pause.svg');\n                    position: absolute;\n                    left: 0px;\n                    width: 14px;\n                    height: 14px;\n                    background-position: 0 0;\n                    background-repeat: no-repeat;\n                    background-size: 14px auto;\n                    content: '';\n                }\n            }\n            &.paused {\n                .entryPauseButtonMinimize:before {\n                    .backgroundImage('minimize/restart.svg');\n                    background-size: 14px 14px;\n                }\n            }\n        }\n        .entryMouseViewMinimize {\n            color: #f2f2f2;\n            font-size: 9pt;\n            margin: 0 auto;\n            width: 40%;\n            line-height: 52px;\n            text-align: center;\n        }\n\n        .audioShadeCirclebox {\n            position: absolute;\n            margin: 0;\n            padding: 0;\n            background: rgba(255, 255, 255, 0.5);\n            text-align: center;\n            z-index: 10;\n            display: flex;\n            flex-direction: column;\n            -moz-flex-direction: column;\n            width: 100%;\n            height: calc(100% - 32px);\n        }\n        .audioShadeCircle {\n            margin: auto;\n            margin-bottom: 6%;\n            padding: 0;\n            position: relative;\n            display: inline-block;\n            height: 34%;\n            width: auto;\n            aspect-ratio: 1 / 1;\n            border-radius: 50%;\n            background-color: #32d27d;\n            vertical-align: top;\n        }\n        .audioShadeInner {\n            margin: 0;\n            padding: 0;\n            position: absolute;\n            left: 0;\n            right: 0;\n            top: 0;\n            bottom: 0;\n            width: 60%;\n            height: 60%;\n            margin: auto;\n            background-color: #32d27d;\n            border-radius: 50%;\n            transform: scale(0.5);\n            transform-origin: center center;\n            animation: ani 3s linear infinite;\n            content: '';\n        }\n        .audioShadeInner:nth-of-type(2) {\n            animation-delay: 1s;\n        }\n        .audioShadeInner:nth-of-type(3) {\n            animation-delay: 2s;\n        }\n        .audioShadeInner:nth-of-type(4) {\n            animation-delay: 3s;\n        }\n        .audioShadeImg {\n            margin: 0;\n            padding: 0;\n            position: absolute;\n            left: 23%;\n            top: 23%;\n            width: 54%;\n            height: 54%;\n            z-index: 10;\n        }\n        .audioShadeText {\n            width: 100%;\n            height: 20%;\n            font-family: NanumGothic, 'Nanum Gothic';\n            font-size: 1.1em;\n            font-weight: bold;\n            font-stretch: normal;\n            font-style: normal;\n            line-height: normal;\n            letter-spacing: normal;\n            text-align: center;\n        }\n        .audioProgress {\n            width: 64%;\n            height: 64%;\n            position: absolute;\n            left: 18%;\n            top: 18%;\n        }\n    }\n}\n\n.entryPopup {\n    .entryPopupWindow {\n        .entryRunButtonBigMinimize {\n            position: absolute;\n            top: 0%;\n            left: 0%;\n            width: 100%;\n            height: calc(100% - 48px);\n            border: none;\n            background-repeat: no-repeat;\n            background-position: 50% center;\n            background-color: rgba(0, 0, 0, 0.5);\n        }\n    }\n}\n\n@keyframes ani {\n    0% {\n        transform: scale(0.5);\n        opacity: 0;\n    }\n    50% {\n        opacity: 0.1;\n    }\n    70% {\n        opacity: 0.09;\n    }\n    100% {\n        transform: scale(3);\n        opacity: 0;\n    }\n}\n\n@keyframes loading {\n    to {\n        background-position:\n            200% bottom,\n            0px 0px,\n            center bottom 14px,\n            right 92px bottom 14px,\n            right 57px bottom 14px,\n            right 18px bottom 14px;\n    }\n}\n"
  },
  {
    "path": "src/css/prefix.less",
    "content": "//---------------------------------------------------\n//  LESS Prefixer\n//---------------------------------------------------\n//\n//  All of the CSS3 fun, none of the prefixes!\n//\n//  As a rule, you can use the CSS properties you\n//  would expect just by adding a '.':\n//\n//  box-shadow => .box-shadow(@args)\n//\n//  Also, when shorthand is available, arguments are\n//  not parameterized. Learn CSS, not LESS Prefixer.\n//\n//  -------------------------------------------------\n//  TABLE OF CONTENTS\n//  (*) denotes a syntax-sugar helper\n//  -------------------------------------------------\n//\n//      .animation(@args)\n//          .animation-delay(@delay)\n//          .animation-direction(@direction)\n//          .animation-duration(@duration)\n//          .animation-fill-mode(@mode)\n//          .animation-iteration-count(@count)\n//          .animation-name(@name)\n//          .animation-play-state(@state)\n//          .animation-timing-function(@function)\n//      .background-size(@args)\n//      .border-radius(@args)\n//      .box-shadow(@args)\n//          .inner-shadow(@args) *\n//      .box-sizing(@args)\n//          .border-box() *\n//          .content-box() *\n//      .columns(@args)\n//          .column-count(@count)\n//          .column-gap(@gap)\n//          .column-rule(@args)\n//          .column-width(@width)\n//      .gradient(@default,@start,@stop) *\n//          .linear-gradient-top(@default,@color1,@stop1,@color2,@stop2,[@color3,@stop3,@color4,@stop4])*\n//          .linear-gradient-left(@default,@color1,@stop1,@color2,@stop2,[@color3,@stop3,@color4,@stop4])*\n//      .opacity(@factor)\n//      .transform(@args)\n//          .transform-origin(@args)\n//          .transform-style(@style)\n//          .rotate(@deg)\n//          .scale(@factor)\n//          .translate(@x,@y)\n//          .translate3d(@x,@y,@z)\n//          .translateHardware(@x,@y) *\n//      .text-shadow(@args)\n//      .transition(@args)\n//          .transition-delay(@delay)\n//          .transition-duration(@duration)\n//          .transition-property(@property)\n//          .transition-timing-function(@function)\n//      Flexbox:\n//          .flex-block()\n//          .flex-inline()\n//              .flex-flow(@direction: row, @wrap: nowrap)\n//                  .flex-direction(@direction: row)\n//                  .flex-wrap(@wrap: nowrap)\n//              .justify-content(@justification)\n//              .align-items(@mode)\n//              .align-content(@alignment)\n//              .flex(@args: none)\n//                  .flex-grow(@grow: 1)\n//                  .flex-shrink(@shrink: 1)\n//                  .flex-basis(@basis: auto)\n//              .order(@num: 0)\n//              .align-self(@align: auto)\n//\n//  Credit to LESS Elements for the motivation and\n//  to CSS3Please.com for implementation.\n//\n//  Copyright (c) 2012 Joel Sutherland\n//  MIT Licensed:\n//  http://www.opensource.org/licenses/mit-license.php\n//\n//---------------------------------------------------\n\n// Animation\n\n.animation(@args) {\n    -webkit-animation: @args;\n    -moz-animation: @args;\n    -ms-animation: @args;\n    -o-animation: @args;\n    animation: @args;\n}\n.animation-delay(@delay) {\n    -webkit-animation-delay: @delay;\n    -moz-animation-delay: @delay;\n    -ms-animation-delay: @delay;\n    -o-animation-delay: @delay;\n    animation-delay: @delay;\n}\n.animation-direction(@direction) {\n    -webkit-animation-direction: @direction;\n    -moz-animation-direction: @direction;\n    -ms-animation-direction: @direction;\n    -o-animation-direction: @direction;\n}\n.animation-duration(@duration) {\n    -webkit-animation-duration: @duration;\n    -moz-animation-duration: @duration;\n    -ms-animation-duration: @duration;\n    -o-animation-duration: @duration;\n}\n.animation-fill-mode(@mode) {\n    -webkit-animation-fill-mode: @mode;\n    -moz-animation-fill-mode: @mode;\n    -ms-animation-fill-mode: @mode;\n    -o-animation-fill-mode: @mode;\n    animation-fill-mode: @mode;\n}\n.animation-iteration-count(@count) {\n    -webkit-animation-iteration-count: @count;\n    -moz-animation-iteration-count: @count;\n    -ms-animation-iteration-count: @count;\n    -o-animation-iteration-count: @count;\n    animation-iteration-count: @count;\n}\n.animation-name(@name) {\n    -webkit-animation-name: @name;\n    -moz-animation-name: @name;\n    -ms-animation-name: @name;\n    -o-animation-name: @name;\n    animation-name: @name;\n}\n.animation-play-state(@state) {\n    -webkit-animation-play-state: @state;\n    -moz-animation-play-state: @state;\n    -ms-animation-play-state: @state;\n    -o-animation-play-state: @state;\n    animation-play-state: @state;\n}\n.animation-timing-function(@function) {\n    -webkit-animation-timing-function: @function;\n    -moz-animation-timing-function: @function;\n    -ms-animation-timing-function: @function;\n    -o-animation-timing-function: @function;\n    animation-timing-function: @function;\n}\n\n// Background Size\n\n.background-size(@args) {\n    -webkit-background-size: @args;\n    background-size: @args;\n}\n\n// Border Radius\n\n.border-radius(@args) {\n    -webkit-border-radius: @args;\n    border-radius: @args;\n\n    background-clip: padding-box;\n}\n\n// Box Shadows\n\n.box-shadow(@args) {\n    -webkit-box-shadow: @args;\n    box-shadow: @args;\n}\n.inner-shadow(@args) {\n    .box-shadow(inset @args);\n}\n\n// Box Sizing\n\n.box-sizing(@args) {\n    -webkit-box-sizing: @args;\n    -moz-box-sizing: @args;\n    box-sizing: @args;\n}\n.border-box() {\n    .box-sizing(border-box);\n}\n.content-box() {\n    .box-sizing(content-box);\n}\n\n// Columns\n\n.columns(@args) {\n    -webkit-columns: @args;\n    -moz-columns: @args;\n    columns: @args;\n}\n.column-count(@count) {\n    -webkit-column-count: @count;\n    -moz-column-count: @count;\n    column-count: @count;\n}\n.column-gap(@gap) {\n    -webkit-column-gap: @gap;\n    -moz-column-gap: @gap;\n    column-gap: @gap;\n}\n.column-width(@width) {\n    -webkit-column-width: @width;\n    -moz-column-width: @width;\n    column-width: @width;\n}\n.column-rule(@args) {\n    -webkit-column-rule: @args;\n    -moz-column-rule: @args;\n    column-rule: @args;\n}\n\n// Gradients\n\n.gradient(@default: #F5F5F5, @start: #EEE, @stop: #FFF) {\n    .linear-gradient-top(@default,@start,0%,@stop,100%);\n}\n.linear-gradient-top(@default,@color1,@stop1,@color2,@stop2) {\n    background-color: @default;\n    background-image: -webkit-gradient(\n        linear,\n        left top,\n        left bottom,\n        color-stop(@stop1, @color1),\n        color-stop(@stop2 @color2)\n    );\n    background-image: -webkit-linear-gradient(top, @color1 @stop1, @color2 @stop2);\n    background-image: -moz-linear-gradient(top, @color1 @stop1, @color2 @stop2);\n    background-image: -ms-linear-gradient(top, @color1 @stop1, @color2 @stop2);\n    background-image: -o-linear-gradient(top, @color1 @stop1, @color2 @stop2);\n    background-image: linear-gradient(top, @color1 @stop1, @color2 @stop2);\n}\n.linear-gradient-top(@default,@color1,@stop1,@color2,@stop2,@color3,@stop3) {\n    background-color: @default;\n    background-image: -webkit-gradient(\n        linear,\n        left top,\n        left bottom,\n        color-stop(@stop1, @color1),\n        color-stop(@stop2 @color2),\n        color-stop(@stop3 @color3)\n    );\n    background-image: -webkit-linear-gradient(top, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n    background-image: -moz-linear-gradient(top, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n    background-image: -ms-linear-gradient(top, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n    background-image: -o-linear-gradient(top, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n    background-image: linear-gradient(top, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n}\n.linear-gradient-top(@default,@color1,@stop1,@color2,@stop2,@color3,@stop3,@color4,@stop4) {\n    background-color: @default;\n    background-image: -webkit-gradient(\n        linear,\n        left top,\n        left bottom,\n        color-stop(@stop1, @color1),\n        color-stop(@stop2 @color2),\n        color-stop(@stop3 @color3),\n        color-stop(@stop4 @color4)\n    );\n    background-image: -webkit-linear-gradient(\n        top,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n    background-image: -moz-linear-gradient(\n        top,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n    background-image: -ms-linear-gradient(\n        top,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n    background-image: -o-linear-gradient(\n        top,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n    background-image: linear-gradient(\n        top,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n}\n.linear-gradient-left(@default,@color1,@stop1,@color2,@stop2) {\n    background-color: @default;\n    background-image: -webkit-gradient(\n        linear,\n        left top,\n        left top,\n        color-stop(@stop1, @color1),\n        color-stop(@stop2 @color2)\n    );\n    background-image: -webkit-linear-gradient(left, @color1 @stop1, @color2 @stop2);\n    background-image: -moz-linear-gradient(left, @color1 @stop1, @color2 @stop2);\n    background-image: -ms-linear-gradient(left, @color1 @stop1, @color2 @stop2);\n    background-image: -o-linear-gradient(left, @color1 @stop1, @color2 @stop2);\n    background-image: linear-gradient(left, @color1 @stop1, @color2 @stop2);\n}\n.linear-gradient-left(@default,@color1,@stop1,@color2,@stop2,@color3,@stop3) {\n    background-color: @default;\n    background-image: -webkit-gradient(\n        linear,\n        left top,\n        left top,\n        color-stop(@stop1, @color1),\n        color-stop(@stop2 @color2),\n        color-stop(@stop3 @color3)\n    );\n    background-image: -webkit-linear-gradient(left, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n    background-image: -moz-linear-gradient(left, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n    background-image: -ms-linear-gradient(left, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n    background-image: -o-linear-gradient(left, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n    background-image: linear-gradient(left, @color1 @stop1, @color2 @stop2, @color3 @stop3);\n}\n.linear-gradient-left(@default,@color1,@stop1,@color2,@stop2,@color3,@stop3,@color4,@stop4) {\n    background-color: @default;\n    background-image: -webkit-gradient(\n        linear,\n        left top,\n        left top,\n        color-stop(@stop1, @color1),\n        color-stop(@stop2 @color2),\n        color-stop(@stop3 @color3),\n        color-stop(@stop4 @color4)\n    );\n    background-image: -webkit-linear-gradient(\n        left,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n    background-image: -moz-linear-gradient(\n        left,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n    background-image: -ms-linear-gradient(\n        left,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n    background-image: -o-linear-gradient(\n        left,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n    background-image: linear-gradient(\n        left,\n        @color1 @stop1,\n        @color2 @stop2,\n        @color3 @stop3,\n        @color4 @stop4\n    );\n}\n\n// Opacity\n\n.opacity(@factor) {\n    @iefactor: @factor*100;\n    -ms-filter: 'progid:DXImageTransform.Microsoft.Alpha(Opacity=@{iefactor})';\n    filter: ~'alpha(opacity=(@{iefactor}))';\n    opacity: @factor;\n}\n\n// Text Shadow\n\n.text-shadow(@args) {\n    text-shadow: @args;\n}\n\n// Transforms\n\n.transform(@args) {\n    -webkit-transform: @args;\n    -moz-transform: @args;\n    -ms-transform: @args;\n    -o-transform: @args;\n    transform: @args;\n}\n.transform-origin(@args) {\n    -webkit-transform-origin: @args;\n    -moz-transform-origin: @args;\n    -ms-transform-origin: @args;\n    -o-transform-origin: @args;\n    transform-origin: @args;\n}\n.transform-style(@style) {\n    -webkit-transform-style: @style;\n    -moz-transform-style: @style;\n    -ms-transform-style: @style;\n    -o-transform-style: @style;\n    transform-style: @style;\n}\n.rotate(@deg:45deg) {\n    .transform(rotate(@deg));\n}\n.scale(@factor:0.5) {\n    .transform(scale(@factor));\n}\n.translate(@x,@y) {\n    .transform(translate(@x,@y));\n}\n.translate3d(@x,@y,@z) {\n    .transform(translate3d(@x,@y,@z));\n}\n.translateHardware(@x,@y) {\n    .translate(@x,@y);\n    -webkit-transform: translate3d(@x, @y, 0);\n    -moz-transform: translate3d(@x, @y, 0);\n    -o-transform: translate3d(@x, @y, 0);\n    -ms-transform: translate3d(@x, @y, 0);\n    transform: translate3d(@x, @y, 0);\n}\n\n// Transitions\n\n.transition(@args:200ms) {\n    -webkit-transition: @args;\n    -moz-transition: @args;\n    -o-transition: @args;\n    -ms-transition: @args;\n    transition: @args;\n}\n.transition-delay(@delay:0) {\n    -webkit-transition-delay: @delay;\n    -moz-transition-delay: @delay;\n    -o-transition-delay: @delay;\n    -ms-transition-delay: @delay;\n    transition-delay: @delay;\n}\n.transition-duration(@duration:200ms) {\n    -webkit-transition-duration: @duration;\n    -moz-transition-duration: @duration;\n    -o-transition-duration: @duration;\n    -ms-transition-duration: @duration;\n    transition-duration: @duration;\n}\n.transition-property(@property:all) {\n    -webkit-transition-property: @property;\n    -moz-transition-property: @property;\n    -o-transition-property: @property;\n    -ms-transition-property: @property;\n    transition-property: @property;\n}\n.transition-timing-function(@function:ease) {\n    -webkit-transition-timing-function: @function;\n    -moz-transition-timing-function: @function;\n    -o-transition-timing-function: @function;\n    -ms-transition-timing-function: @function;\n    transition-timing-function: @function;\n}\n\n// Flexbox\n.flex-block() {\n    display: -ms-flexbox;\n    display: -webkit-flex;\n    display: flex;\n}\n.flex-inline() {\n    display: -ms-inline-flexbox;\n    display: -webkit-inline-flex;\n    display: inline-flex;\n}\n.flex-flow(@direction: row, @wrap: nowrap) {\n    -moz-flex-flow: @direction @wrap;\n    -ms-flex-direction: @direction;\n    -ms-flex-wrap: @wrap;\n    -webkit-flex-flow: @direction @wrap;\n    flex-flow: @direction @wrap;\n}\n.align-content(@alignment) {\n    -moz-align-content: @alignment;\n    -ms-align-content: @alignment;\n    -webkit-align-content: @alignment;\n    align-content: @alignment;\n}\n.flex-direction(@direction: row) {\n    -webkit-flex-direction: @direction;\n    -moz-flex-direction: @direction;\n    -ms-flex-direction: @direction;\n    flex-direction: @direction;\n}\n.flex-wrap(@wrap: nowrap) {\n    -webkit-flex-wrap: @wrap;\n    -moz-flex-wrap: @wrap;\n    -ms-flex-wrap: @wrap;\n    flex-wrap: @wrap;\n}\n.justify-content(@justification) {\n    -webkit-box-pack: @justification;\n    -moz-box-pack: @justification;\n    -ms-flex-pack: @justification;\n    -webkit-justify-content: @justification;\n    justify-content: @justification;\n}\n.align-items(@mode) {\n    -webkit-box-align: @mode;\n    -moz-box-align: @mode;\n    -ms-flex-align: @mode;\n    -webkit-align-items: @mode;\n    align-items: @mode;\n}\n.flex(@args: none) {\n    -webkit-flex: @args;\n    -moz-flex: @args;\n    -ms-flex: @args;\n    -webkit-flex: @args;\n    flex: @args;\n}\n.order(@num: 0) {\n    -webkit-box-ordinal-group: @order;\n    -moz-box-ordinal-group: @order;\n    -ms-box-ordinal-group: @order;\n    -ms-flex-order: @order;\n    -webkit-order: @order;\n    -moz-order: @order;\n    -ms-order: @order;\n    order: @order;\n}\n.flex-grow(@grow: 1) {\n    -webkit-flex-grow: @grow;\n    -moz-flex-grow: @grow;\n    -ms-flex-grow: @grow;\n    -webkit-flex-grow: @grow;\n    flex-grow: @grow;\n}\n.flex-shrink(@shrink: 1) {\n    -webkit-flex-shrink: @shrink;\n    -moz-flex-shrink: @shrink;\n    -ms-flex-shrink: @shrink;\n    -webkit-flex-shrink: @shrink;\n    flex-shrink: @shrink;\n}\n.flex-basis(@basis: auto) {\n    -webkit-flex-basis: @basis;\n    -moz-flex-basis: @basis;\n    -ms-flex-basis: @basis;\n    -webkit-flex-basis: @basis;\n    flex-basis: @basis;\n}\n.align-self(@align: auto) {\n    -webkit-align-self: @align;\n    -moz-align-self: @align;\n    -ms-align-self: @align;\n    -webkit-align-self: @align;\n    align-self: @align;\n}\n"
  },
  {
    "path": "src/css/static.less",
    "content": "//main bora color\n@bora: #4b37a0;\n\n@parang: #103366;\n\n//main haneul color\n@haneul: #1bafea;\n\n//main pink background color\n@pink: #ffafb6;\n\n//common background color\n@beige: #f9f8f7;\n\n//border color\n@more: #cec5bc;\n\n//font colors\n@yeonbora: #6c5af2;\n\n@norang: #ffcf5f;\n\n@dahong: #fa5536;\n\n@lightGray: #e5e5e5;\n\n@grayFont: #9e9e9f;\n\n@lightHaneul: #42caf4;\n\n@lightBora: #6c5af2;\n\n@blueHaneul: #5096f5;\n\n//popup colors\n@titleBack: #2a7def;\n\n@stepBack: #f4810f;\n\n@exampleBack: #50a0ff;\n\n@stepBorder: #e8740c;\n\n@viewText: #004051;\n\n@viewUnder: #ffae0b;\n\n@viewShadow: #ffed08;\n\n@viewEmphasis: #f43900;\n\n@objectText: #494949;\n\n@indicatorOff: #828282;\n\n@indicatorOn: #2f50f4;\n\n@white: #ffffff;\n\n// 개편 color\n@baseblue: #4f80ff;\n@baseBluePoint: #3064ec;\n@basePurple: #8274ff;\n@basePurplePoint: #5e4dee;\n"
  },
  {
    "path": "src/entry.js",
    "content": "__webpack_public_path__ = global.PUBLIC_PATH_FOR_ENTRYJS || 'dist/';\nimport showConsoleBanner from './util/functions/showConsoleBanner';\nimport 'simplebar/dist/simplebar.css';\n\nconst Entry = {};\nEntry.EXPANSION_BLOCK = {};\nEntry.EXPANSION_BLOCK_LIST = {};\nEntry.AI_UTILIZE_BLOCK = {};\nEntry.AI_UTILIZE_BLOCK_LIST = {};\nEntry.AI_UTILIZE_BLOCK_LIST_DEPRECATED = {};\nEntry.ALL_AI_UTILIZE_BLOCK_LIST = {};\n\nmodule.exports = Entry;\nglobal.Entry = Entry;\n\nrequire('./core/collection');\nrequire('./core/db');\nrequire('./core/dom');\nrequire('./core/event');\nrequire('./core/model');\nrequire('./core/observer');\nrequire('./core/svg');\nrequire('core-js/stable/object/values');\nrequire('./graphicEngine/FakePIXI');\nrequire('./css/entry.less');\nrequire('./class/time_wait');\nrequire('./class/container');\nrequire('./class/dialog');\nrequire('./class/doneProject');\nrequire('./class/engine');\nrequire('./class/entity');\nrequire('./class/function');\nrequire('./class/helper');\nrequire('./class/intro');\nrequire('./class/object');\nrequire('./class/painter');\nrequire('./class/LiterallycanvasPainter');\nrequire('./class/pdf');\nrequire('./class/playground');\nrequire('./class/popup');\nrequire('./class/popup_helper');\nrequire('./class/popup_list');\nrequire('./class/hw');\nrequire('./class/hw_lite');\nrequire('./class/entryModuleLoader');\nrequire('./class/project');\nrequire('./class/property_panel');\nrequire('./class/reporter');\nrequire('./class/scene');\nrequire('./class/blockCountViewer');\nrequire('./class/stage');\nrequire('./class/stamp_entity');\nrequire('./class/toast');\nrequire('./class/variable');\nrequire('./class/variable_container');\nrequire('./command/command');\nrequire('./command/commander');\nrequire('./extensions/extension');\nrequire('./extensions/target_checker');\nrequire('./log/activity');\nrequire('./log/activityReporter');\nrequire('./log/recorder');\nrequire('./log/state');\nrequire('./log/state_manager');\nrequire('./model/block_model');\nrequire('./model/block_render_model');\nrequire('./model/box_model');\nrequire('./model/drag_instance');\nrequire('./model/thread_model');\nrequire('./parser-no/block');\nrequire('./parser-no/js');\nrequire('./parser-no/parser');\nrequire('./playground/block');\nrequire('./playground/block_entry');\nrequire('./playground/block_menu');\nrequire('./playground/block_menu_scroll');\nrequire('./playground/block_view');\nrequire('./playground/comment');\nrequire('./playground/board');\nrequire('./playground/code');\nrequire('./playground/code_view');\nrequire('./playground/connection_ripple');\nrequire('./playground/executors');\nrequire('./playground/scope');\nrequire('./playground/globalSvg');\nrequire('./playground/mutator');\nrequire('./playground/renderView');\nrequire('./playground/scroll');\nrequire('./playground/skeleton');\nrequire('./playground/skinner');\nrequire('./playground/thread');\nrequire('./playground/thread_view');\nrequire('./playground/trashcan');\nrequire('./playground/zoom_controller');\nrequire('./playground/vim');\nrequire('./playground/workspace');\nrequire('./textcoding/parser');\nrequire('./util/block_driver');\nrequire('./util/contextmenu');\nrequire('./util/curtain');\nrequire('./util/fuzzy');\nrequire('./util/init');\nrequire('./util/loader');\nrequire('./util/restrictor');\nrequire('./util/static');\nrequire('./util/tooltip');\nrequire('./util/tvCast');\nrequire('./util/virtualScroll');\nrequire('./util/htmlElementPatcher');\nrequire('./util/eventHandler');\nrequire('./util/utils');\nrequire('./util/youtube');\nrequire('./util/modal');\nrequire('./command/commands/block');\nrequire('./command/commands/comment');\nrequire('./command/commands/container');\nrequire('./command/commands/dataTable');\nrequire('./command/commands/engine');\nrequire('./command/commands/function');\nrequire('./command/commands/object');\nrequire('./command/commands/painter');\nrequire('./command/commands/playground');\nrequire('./command/commands/textbox');\nrequire('./command/commands/variableContainer');\nrequire('./command/commands/scene');\nrequire('./playground/extension/extension');\nrequire('./playground/extension/guide');\nrequire('./playground/extension/side_tag');\nrequire('./playground/field/field');\nrequire('./playground/field/angle');\nrequire('./playground/field/block');\nrequire('./playground/field/color');\nrequire('./playground/field/led');\nrequire('./playground/field/led2');\nrequire('./playground/field/musicScale');\nrequire('./playground/field/dropdown');\nrequire('./playground/field/dropdownDynamic');\nrequire('./playground/field/dropdownExtra');\nrequire('./playground/field/image');\nrequire('./playground/field/indicator');\nrequire('./playground/field/keyboardInput');\nrequire('./playground/field/lineBreak');\nrequire('./playground/field/output');\nrequire('./playground/field/statement');\nrequire('./playground/field/text');\nrequire('./playground/field/textDynamic');\nrequire('./playground/field/textInput');\nrequire('./textcoding/ast/jsAstGenerator');\nrequire('./textcoding/ast/pyAstGenerator');\nrequire('./textcoding/data_processing/map');\nrequire('./textcoding/data_processing/queue');\nrequire('./textcoding/error/textCodingError');\nrequire('./textcoding/hint/python');\nrequire('./textcoding/static/codeMap');\nrequire('./textcoding/static/keyboardCode');\nrequire('./textcoding/util/console');\nrequire('./textcoding/util/textCodingUtil');\n\nwindow.Entry = Entry;\nshowConsoleBanner();\n"
  },
  {
    "path": "src/extensions/CloudVariable.js",
    "content": "import io from 'socket.io-client';\nimport { dmet, dmetList, dmetTable, dmetVariable } from './dmet';\nimport singleInstance from '../core/singleInstance';\n\nclass CloudVariableExtension {\n    #cvSocket = null;\n    #data = null;\n    #defaultData = null;\n\n    get data() {\n        return this.#data;\n    }\n\n    setServerInfo(cvServer) {\n        this.cvServer = cvServer;\n    }\n\n    disable(target) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        this.#cvSocket.emit('changeMode', 'offline', target);\n    }\n\n    enable(target) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        this.#cvSocket.emit('changeMode', 'online', target);\n    }\n\n    async connect(cvServer) {\n        if (this.#cvSocket || !this.cvServer) {\n            return;\n        }\n        const { url, query, type } = this.cvServer;\n        const socket = io(url, {\n            path: '/cv',\n            query: {\n                type,\n                q: query,\n            },\n            transports: ['websocket'],\n            reconnectionAttempts: 2,\n            timeout: 5000,\n        });\n        socket.on('action', this.#execDmet.bind(this));\n        socket.on('create', this.#createVariable.bind(this));\n        socket.on('reset', (variables) => {\n            try {\n                this.#data = new dmet(variables);\n            } catch (e) {\n                console.warn(e);\n            }\n        });\n\n        this.#cvSocket = socket;\n        return new Promise((resolve) => {\n            socket.on('connect_error', () => {\n                console.log('connect_error');\n                if (!this.#data) {\n                    try {\n                        this.#data = new dmet(this.#defaultData);\n                    } catch (e) {\n                        console.warn(e);\n                    }\n                    resolve();\n                }\n            });\n            socket.on('check', (id) => {\n                socket.emit('imAlive', id);\n            });\n            socket.on('welcome', ({ variables = [], isOffline }) => {\n                try {\n                    this.#data = new dmet(variables);\n                    variables.forEach(this.#applyValue);\n                } catch (e) {\n                    console.warn(e);\n                }\n                if (isOffline) {\n                    socket.close();\n                }\n                resolve();\n            });\n            socket.on('disconnect', (reason) => {\n                console.log('disconnect', reason);\n                if (!this.#data) {\n                    this.#data = new dmet(this.#defaultData);\n                }\n                resolve();\n            });\n            socket.on('changeMode', (mode, target) => {\n                const isOffline = mode === 'offline';\n                if (isOffline) {\n                    socket.close();\n                }\n                resolve();\n            });\n        });\n    }\n\n    setDefaultData(defaultData) {\n        this.#defaultData = defaultData;\n        defaultData.forEach(this.#applyValue);\n    }\n\n    createDmet(object) {\n        this.#data.create(object);\n    }\n\n    async create(data) {\n        if (!this.#cvSocket) {\n            await this.connect();\n        }\n        const { id_, type, name } = data;\n        if (type === 'variable') {\n            await this.#createVariable(name, id_);\n        } else if (type === 'list') {\n            await this.#createList(name, id_);\n        } else if (type === 'table') {\n            await this.#createTable(name, id_);\n        }\n        // Entry.dispatchEvent('saveVariable');\n    }\n\n    #createVariable(name, id) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        const variable = new dmetVariable(\n            {\n                name,\n            },\n            id\n        );\n        return new Promise((resolve) => {\n            this.#cvSocket.emit('create', variable, (isCreate, variable) => {\n                if (isCreate) {\n                    this.createDmet(variable);\n                }\n                resolve();\n            });\n        });\n    }\n\n    #createList(name, id) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        const list = new dmetList(\n            {\n                name,\n            },\n            id\n        );\n        return new Promise((resolve) => {\n            this.#cvSocket.emit('create', list, (isCreate, list) => {\n                if (isCreate) {\n                    this.createDmet(list);\n                }\n                resolve();\n            });\n        });\n    }\n\n    #createTable(name, id) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        const table = new dmetTable(\n            {\n                name,\n            },\n            id\n        );\n        return new Promise((resolve) => {\n            this.#cvSocket.emit('create', table, (isCreate, table) => {\n                if (isCreate) {\n                    this.createDmet(table);\n                }\n                resolve();\n            });\n        });\n    }\n\n    #run(operation) {\n        return new Promise((resolve) => {\n            if (this.#cvSocket.connected) {\n                this.#cvSocket.emit('action', operation, (isUpdate, operation) => {\n                    if (isUpdate) {\n                        this.#data.exec(operation);\n                        resolve(operation);\n                    } else {\n                        resolve();\n                    }\n                });\n            } else {\n                this.#data.exec(operation);\n                resolve(operation);\n            }\n        }).then((operation) => {\n            if (operation) {\n                this.#applyValue(operation);\n            }\n        });\n    }\n\n    #execDmet(operation) {\n        this.#data.exec(operation);\n        this.#applyValue(operation);\n    }\n\n    #applyValue(operation) {\n        const { id, value, data, variableType } = operation;\n        if (variableType === 'variable' || variableType === 'slide') {\n            const variable = Entry.variableContainer.getVariable(id);\n            if (variable) {\n                variable.value_ = value;\n                variable._valueWidth = null;\n                variable.updateView();\n            }\n        } else if (variableType === 'list') {\n            const list = Entry.variableContainer.getList(id);\n            if (!list) {\n                return;\n            }\n            if (this && this.get) {\n                const { array } = this.get(operation);\n                list.array_ = array;\n            } else if (operation.array) {\n                list.array_ = operation.array;\n            } else if (operation.list) {\n                list.array_ = operation.list.map((key) => ({ data: operation.value[key] }));\n            }\n            list.updateView();\n        }\n    }\n\n    set(target, value) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        const variable = this.#data && this.#data.get(target);\n        if (!variable) {\n            return;\n        }\n        const operation = variable.getOperation({\n            type: 'set',\n            value,\n        });\n        return this.#run(operation);\n    }\n\n    get(target) {\n        return this.#data && this.#data.get(target);\n    }\n\n    // 워크스페이스에서만 동작하는 함수이기 때문에 run 생략\n    setArray(target, array) {\n        const dmetList = this.#data && this.#data.get(target);\n        if (!dmetList) {\n            console.error('no target ', target);\n        }\n        dmetList.from(array.map(({ data }) => data));\n    }\n\n    append(target, data) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        const variable = this?.#data?.get(target);\n        if (!variable) {\n            return;\n        }\n        const operation = variable.getOperation({\n            type: 'append',\n            data,\n        });\n        return this.#run(operation);\n    }\n\n    insert(target, index, data) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        const variable = this.#data.get(target);\n        if (!variable) {\n            return;\n        }\n        const operation = variable.getOperation({\n            type: 'insert',\n            index,\n            data,\n        });\n        return this.#run(operation);\n    }\n\n    delete(target, index) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        const variable = this.#data.get(target);\n        if (!variable) {\n            return;\n        }\n        const operation = variable.getOperation({\n            type: 'delete',\n            index,\n        });\n        return this.#run(operation);\n    }\n\n    replace(target, index, data) {\n        if (!this.#cvSocket) {\n            return;\n        }\n        const variable = this.#data.get(target);\n        if (!variable) {\n            return;\n        }\n        const operation = variable.getOperation({\n            type: 'replace',\n            index,\n            data,\n        });\n        return this.#run(operation);\n    }\n}\n\nexport default singleInstance(CloudVariableExtension);\n"
  },
  {
    "path": "src/extensions/dmet.js",
    "content": "import isPlainObject from 'lodash/isPlainObject';\nimport _mapValues from 'lodash/mapValues';\nimport _get from 'lodash/get';\nimport _cloneDeep from 'lodash/cloneDeep';\nimport CommonUtils, { toNumber } from '../util/common';\n\nclass dmetTable {\n    constructor(array = [], id) {\n        this.#id = id;\n        this.from(array);\n    }\n\n    _id = undefined;\n    __isUpdate = false;\n    #id = '';\n    #key = CommonUtils.generateId();\n    #object = {};\n    #array = [];\n    #origin = [];\n    #fields = [];\n    #originFields = [];\n    #info = {};\n    #maxRow = 3000;\n    #maxCol = 100;\n    #variableType = 'table';\n    #keyDelimter = '_';\n\n    get fields() {\n        return this.#fields;\n    }\n\n    get originFields() {\n        return this.#originFields;\n    }\n\n    get value() {\n        return this.#object;\n    }\n\n    get array() {\n        return this.#array;\n    }\n\n    get isDmet() {\n        return true;\n    }\n\n    get variableType() {\n        return this.#variableType;\n    }\n\n    get origin() {\n        return this.#origin;\n    }\n\n    setLabel(index, name) {\n        this.#fields[index] = name;\n    }\n\n    #fillArray(array, length) {\n        const start = array.length;\n        array.length = length;\n        array.fill(0, start, length);\n    }\n\n    from(data) {\n        const {\n            list = [],\n            data: array = [],\n            value,\n            _id,\n            id = this.#id,\n            fields = [],\n            ...info\n        } = data;\n        this.#object = {};\n        this.#array = [];\n        this.#origin = [];\n        if (Array.isArray(array)) {\n            array.forEach((row = []) => {\n                if (Array.isArray(row)) {\n                    const key = CommonUtils.generateId();\n                    const value = row.map(toNumber);\n                    this.#fillArray(value, fields.length);\n                    this.#array.push({ key, value });\n                    this.#object[key] = value;\n                    this.#origin.push(_cloneDeep(row));\n                } else if (typeof row === 'object' && row.key) {\n                    const newRow = {\n                        key: row.key,\n                        value: row.value.map(toNumber),\n                    };\n                    this.#array.push(newRow);\n                    this.#object[row.key] = newRow.value;\n                    this.#origin.push(_cloneDeep(row.value));\n                }\n            });\n        }\n        this._id = _id;\n        this.#id = id;\n        this.#fields = fields;\n        this.#originFields = [...fields];\n        this.#info = info;\n    }\n\n    toJSON() {\n        return {\n            _id: this._id || undefined,\n            id: this.#id,\n            key: this.#key,\n            data: this.#array,\n            origin: this.#origin,\n            fields: this.#fields,\n            isDmet: true,\n            variableType: this.variableType,\n        };\n    }\n\n    getRow(key) {\n        if (Array.isArray(key)) {\n            const [row, col = 0] = key;\n            const result = this.#array[row - 1] || {};\n            return { ...result, x: row - 1, y: col - 1 };\n        } else if (typeof key === 'number') {\n            const result = this.#array[key - 1] || {};\n            return { ...result, x: key - 1 };\n        } else if (typeof key === 'string') {\n            const [rowKey, col = 0] = key.split(this.#keyDelimter);\n            return {\n                key: rowKey,\n                value: this.#object[rowKey],\n                x: this.getIndex(rowKey),\n                y: col - 1,\n            };\n        }\n        throw { message: `not found tableData ${key} id: ${this.#id}` };\n    }\n\n    getValue(key) {\n        if (typeof key === 'number') {\n            return this.#array[key - 1].value;\n        } else if (Array.isArray(key)) {\n            const [rowKey, ...keys] = key;\n            let { value: row } = this.#array[rowKey - 1] || {};\n            if (rowKey === 0) {\n                row = this.#fields;\n            }\n            if (keys.length && row) {\n                return _get(row, `[${keys.map((x) => x - 1).join('][')}]`);\n            } else {\n                return row;\n            }\n        } else if (typeof key === 'string') {\n            const [rowKey, ...keys] = key.split(this.#keyDelimter);\n            if (keys.length) {\n                return _get(this.#object[rowKey], `[${keys.map((x) => x - 1).join('][')}]`);\n            }\n            return this.#object[rowKey];\n        }\n        throw { message: `not found tableData ${key} id: ${this.#id}` };\n    }\n\n    getIndex(key) {\n        if (Array.isArray(key)) {\n            return key;\n        } else if (typeof key === 'string') {\n            const [rowKey, ...keys] = key.split(this.#keyDelimter);\n            const rowIndex = this.#array.findIndex((x) => x.key === rowKey);\n            if (rowIndex >= 0) {\n                return [rowIndex, ...keys];\n            }\n        }\n        return [];\n    }\n\n    #skipOperation = ['appendRow', 'appendCol', 'insertRow', 'insertCol'];\n\n    getOperation({ type, key, index, data, newKey } = {}) {\n        if (this.#skipOperation.indexOf(type) === -1 && typeof index === 'number') {\n            const data = this.getRow(index);\n            key = data.key;\n        }\n        let attach = {};\n        switch (type) {\n            case 'appendRow':\n            case 'appendCol':\n            case 'insertRow':\n            case 'insertCol':\n                attach = {\n                    index,\n                    data,\n                };\n                break;\n            case 'deleteCol':\n            case 'deleteRow':\n                attach = { index };\n                break;\n            case 'replace':\n                attach = {\n                    data,\n                    index,\n                    newKey,\n                };\n                break;\n        }\n\n        return {\n            _id: this._id || undefined,\n            id: this.#id,\n            variableType: this.variableType,\n            key,\n            type,\n            ...attach,\n        };\n    }\n\n    exec(operation) {\n        const { type } = operation;\n        this.__isUpdate = true;\n        switch (type) {\n            case 'appendCol':\n                return this.#appendCol(operation);\n            case 'appendRow':\n                return this.#appendRow(operation);\n            case 'insertRow':\n                return this.#insertRow(operation);\n            case 'insertCol':\n                return this.#insertCol(operation);\n            case 'deleteCol':\n                return this.#deleteCol(operation);\n            case 'deleteRow':\n                return this.#deleteRow(operation);\n            case 'replace':\n                return this.#replace(operation);\n        }\n    }\n\n    #getDefaultData(isRow = true) {\n        if (isRow) {\n            return new Array(this.fields.length).fill(0);\n        }\n        return new Array(this.#array.length).fill(0);\n    }\n\n    #getNewColName() {\n        return Entry.getOrderedName(\n            Lang.DataAnalytics.new_attribute,\n            this.fields.map((name) => ({ name })),\n            'name'\n        );\n    }\n\n    #appendCol({ index, data = this.#getDefaultData(false) } = {}) {\n        this.fields.push(this.#getNewColName());\n        this.#array.forEach(({ value }, idx) => {\n            value.push(0);\n        });\n        return this.getOperation({ type: 'appendCol', index, data });\n    }\n\n    #insertCol({ index, data = this.#getDefaultData(false) } = {}) {\n        if (index < 1 || index > this.fields.length + 1) {\n            throw { message: `error: insertCol ${index}` };\n        }\n        this.fields.splice(index - 1, 0, this.#getNewColName());\n        this.#array.forEach(({ value }, idx) => {\n            value.splice(index - 1, 0, 0);\n        });\n        return this.getOperation({ type: 'insertCol', index, data });\n    }\n\n    #deleteCol({ index }) {\n        if (!index) {\n            throw { message: `error: deleteCol : ${index}` };\n        }\n        this.fields.splice(index - 1, 1);\n        this.#array.forEach(({ value }, idx) => {\n            value.splice(index - 1, 1);\n        });\n        return this.getOperation({ type: 'deleteCol', index });\n    }\n\n    #appendRow({ key = CommonUtils.generateId(), data = this.#getDefaultData() } = {}) {\n        const index = this.#array.length + 1;\n        if (Array.isArray(data)) {\n            this.#object[key] = data;\n            this.#array.splice(index, 0, { key, value: data });\n        } else {\n            console.warn('appendRow : ', key, data);\n        }\n        return this.getOperation({ type: 'appendRow', key, index, data });\n    }\n\n    #insertRow({ key = CommonUtils.generateId(), index, data = this.#getDefaultData() } = {}) {\n        const value = toNumber(data);\n        if (Array.isArray(data) || index > this.#array.length + 1 || index < 0) {\n            if (index === 0) {\n                const fields = [...data];\n                data = [...this.#fields];\n                this.#fields = fields;\n                index = 1;\n            }\n            this.#object[key] = Array.isArray(data) ? data : [value];\n            this.#array.splice(index - 1, 0, { key, value: this.#object[key] });\n        } else {\n            console.warn('insert row : ', key, data, index);\n        }\n        return this.getOperation({ type: 'insertRow', key, index, data: value });\n    }\n\n    #deleteRow({ key, index }) {\n        if (index === 0) {\n            index = 1;\n            const { value: row } = this.getRow(index);\n            this.#fields = [...row];\n        }\n        if (!key) {\n            key = index;\n        }\n        const { value: row, key: objKey, x, y } = this.getRow(key);\n        if (!row || (y > -1 && !row[y])) {\n            throw { message: 'not found data' };\n        }\n        if (y > -1) {\n            delete row[y];\n        } else {\n            delete this.#object[objKey];\n            this.#array.splice(x, 1);\n        }\n        return this.getOperation({ type: 'deleteRow', key });\n    }\n\n    #replace({ key, index, data, newKey = CommonUtils.generateId() }) {\n        const value = toNumber(data);\n        if (!key) {\n            key = index;\n        }\n        const { value: row, key: objKey, x, y } = this.getRow(key);\n        if (x === -1) {\n            this.#fields[y] = value;\n        } else {\n            if (!row) {\n                throw { message: `not found row ${y}` };\n            }\n            row[y] = value;\n        }\n        return this.getOperation({ type: 'replace', key, index, data: value, newKey });\n    }\n}\n\nclass dmetList {\n    constructor(array = [], id) {\n        this.#id = id;\n        this.from(array);\n    }\n\n    _id = undefined;\n    __isUpdate = false;\n    #id = '';\n    #key = CommonUtils.generateId();\n    #object = {};\n    #array = [];\n    #info = {};\n    #variableType = 'list';\n\n    get value() {\n        return this.#array;\n    }\n\n    get array() {\n        return this.#array;\n    }\n\n    get isDmet() {\n        return true;\n    }\n\n    get id() {\n        return this.#id;\n    }\n\n    get key() {\n        return this.#key;\n    }\n\n    get variableType() {\n        return this.#variableType;\n    }\n\n    set #data(array) {\n        this.#array = array.map((data) => {\n            const key = CommonUtils.generateId();\n            const item = {\n                key,\n                data,\n            };\n            this.#object[key] = item;\n            return item;\n        });\n    }\n\n    from(data) {\n        if (Array.isArray(data)) {\n            this.#data = data;\n        } else if (data.isDmet || isPlainObject(data)) {\n            const { list = [], array = [], value, _id, id = this.#id, ...info } = data;\n            if (data.array && Array.isArray(array)) {\n                this.#array = array;\n                this.#array.map((value) => {\n                    const { key, _key } = value;\n                    this.#object[key || _key] = value;\n                });\n            } else if (Array.isArray(list) && isPlainObject(value)) {\n                this.#array = list.map((key) => {\n                    const data = {\n                        key,\n                        data: value[key],\n                    };\n                    this.#object[key] = data;\n                    return data;\n                });\n            } else {\n                this.#array = [];\n                this.#object = {};\n            }\n            this._id = _id;\n            this.#id = id;\n            this.#info = info;\n        } else if ('toJSON' in data) {\n            const plainObject = data.toJSON();\n            const { array = [], _id, id = this.#id, ...info } = plainObject;\n            this.#array = array;\n            this._id = _id;\n            this.#id = id;\n            this.#info = info;\n            this.#array.map((value) => {\n                const { key, _key } = value;\n                this.#object[key || _key] = value;\n            });\n        } else {\n            throw 'data is wrong.';\n        }\n    }\n\n    get(key) {\n        if (typeof key === 'number') {\n            return this.#array[key];\n        } else if (typeof key === 'string') {\n            return this.#object[key];\n        }\n    }\n\n    getIndex(key) {\n        if (typeof key === 'number') {\n            return key;\n        } else if (typeof key === 'string') {\n            const oldData = this.#object[key];\n            return this.#array.indexOf(oldData);\n        } else {\n            return 0;\n        }\n    }\n\n    #skipOperation = ['append', 'insert'];\n\n    getOperation({ type, key, index, data, newKey } = {}) {\n        if (this.#skipOperation.indexOf(type) === -1 && typeof index === 'number') {\n            const data = this.get(index);\n            key = data.key;\n        }\n        let attach = {};\n        switch (type) {\n            case 'append':\n                attach = {\n                    data,\n                };\n                break;\n            case 'insert':\n                attach = {\n                    index,\n                    data,\n                };\n                break;\n            case 'delete':\n                attach = { index };\n                break;\n            case 'replace':\n                attach = {\n                    data,\n                    newKey,\n                };\n                break;\n        }\n\n        return {\n            _id: this._id || undefined,\n            id: this.#id,\n            variableType: this.variableType,\n            key,\n            type,\n            ...attach,\n        };\n    }\n\n    exec(operation) {\n        const { type } = operation;\n        this.__isUpdate = true;\n        switch (type) {\n            case 'append':\n                return this.#append(operation);\n            case 'insert':\n                return this.#insert(operation);\n            case 'delete':\n                return this.#delete(operation);\n            case 'replace':\n                return this.#replace(operation);\n        }\n    }\n\n    toJSON() {\n        return {\n            _id: this._id || undefined,\n            id: this.#id,\n            key: this.#key,\n            array: this.#array,\n            isDmet: true,\n            variableType: this.variableType,\n        };\n    }\n\n    #append({ key, data } = {}) {\n        if (!key) {\n            key = CommonUtils.generateId();\n        }\n        const newData = {\n            key,\n            data,\n        };\n        this.#object[key] = newData;\n        this.#array.push(newData);\n        return this.getOperation({ type: 'append', key, index: -1, data });\n    }\n\n    #insert({ key, index, data } = {}) {\n        if (!key) {\n            key = CommonUtils.generateId();\n        }\n        const newData = {\n            key,\n            data,\n        };\n        this.#object[key] = newData;\n        this.#array.splice(index, 0, newData);\n        return this.getOperation({ type: 'insert', key, index, data });\n    }\n\n    #delete({ key, index }) {\n        try {\n            if (!key) {\n                key = index;\n            }\n            const oldData = this.get(key);\n            if (!oldData) {\n                throw { message: 'not found data' };\n            }\n            const oldIndex = this.getIndex(key);\n            delete this.#object[oldData.key];\n            this.#array.splice(oldIndex, 1);\n            return this.getOperation({ type: 'delete', key });\n        } catch (e) {}\n    }\n\n    #replace({ key, data, newKey = CommonUtils.generateId() }) {\n        try {\n            const item = this.get(key);\n            if (!item) {\n                throw { message: 'not found data' };\n            }\n            delete this.#object[item.key];\n            item.key = newKey;\n            item.data = data;\n            this.#object[newKey] = item;\n            return this.getOperation({ type: 'replace', key, data, newKey });\n        } catch (e) {}\n    }\n}\n\nclass dmetVariable {\n    constructor(variable = '', id) {\n        this.#id = id;\n        this.from(variable);\n    }\n\n    _id = undefined;\n    #id = '';\n    #key = CommonUtils.generateId();\n    #info = {};\n    #value = '';\n    #variableType = 'variable';\n\n    get value() {\n        return this.#value;\n    }\n\n    get id() {\n        return this.#id;\n    }\n\n    get key() {\n        return this.#key;\n    }\n\n    get variableType() {\n        return this.#variableType;\n    }\n\n    toJSON() {\n        return {\n            ...this.#info,\n            _id: this._id || undefined,\n            id: this.#id,\n            key: this.#key,\n            value: this.value,\n            isDmet: true,\n            variableType: this.variableType,\n        };\n    }\n\n    from(data) {\n        if (typeof data === 'string') {\n            this.#value = data;\n        } else if (data.isDmet || isPlainObject(data)) {\n            const { value = '', _id, id = this.#id, ...info } = data;\n            this.#value = value;\n            this._id = _id;\n            this.#id = id;\n            this.#info = info;\n        } else if ('toJSON' in data) {\n            const plainObject = data.toJSON();\n            const { value = '', _id, id = this.#id, ...info } = plainObject;\n            this.#value = value;\n            this._id = _id;\n            this.#id = id;\n            this.#info = info;\n        } else {\n            throw 'data is wrong.';\n        }\n    }\n\n    get() {\n        return this.#value;\n    }\n\n    #set(operation) {\n        const { value } = operation;\n        this.#value = value;\n        return operation;\n    }\n\n    getOperation({ type, value } = {}) {\n        switch (type) {\n            case 'set':\n                return {\n                    _id: this._id,\n                    id: this.#id,\n                    variableType: this.variableType,\n                    type,\n                    value,\n                };\n        }\n    }\n\n    exec(operation) {\n        const { type } = operation;\n        switch (type) {\n            case 'set':\n                return this.#set(operation);\n        }\n    }\n}\n\nclass dmetSlideVariable extends dmetVariable {\n    constructor(variable, id) {\n        variable.variableType = 'slide';\n        super(variable, id);\n    }\n}\n\nclass dmet {\n    constructor(variables, options) {\n        this.from(variables, options);\n    }\n\n    #original = { list: {}, variable: {} };\n    #id = CommonUtils.generateId();\n    #list = {};\n    #variable = {};\n    #table = {};\n\n    get list() {\n        return this.#list;\n    }\n\n    get variable() {\n        return this.#variable;\n    }\n\n    get table() {\n        return this.#table;\n    }\n\n    get id() {\n        return this.#id;\n    }\n\n    get isDmet() {\n        return true;\n    }\n\n    get original() {\n        return this.#original;\n    }\n\n    #objectToJSON(object) {\n        for (const key in object) {\n            object[key] = object[key].toJSON();\n        }\n        return object;\n    }\n\n    toJSON() {\n        return {\n            id: this.#id,\n            list: this.list,\n            table: this.table,\n            variable: this.variable,\n            isDmet: true,\n        };\n    }\n\n    from(variables = []) {\n        if (Array.isArray(variables)) {\n            variables.forEach((variable) => {\n                const { variableType } = variable;\n                if (variableType === 'variable') {\n                    const result = new dmetVariable(variable);\n                    this.#variable[result.id] = result;\n                } else if (variableType === 'slide') {\n                    const result = new dmetSlideVariable(variable);\n                    this.#variable[result.id] = result;\n                } else if (variableType === 'list') {\n                    const result = new dmetList(variable);\n                    this.#list[result.id] = result;\n                } else if (variableType === 'table') {\n                    const result = new dmetTable(variable);\n                    this.#table[result.id] = result;\n                }\n            });\n        } else if (isPlainObject(variables) && variables.isDmet) {\n            this.#list = _mapValues(variables.list, (list) => new dmetList(list));\n            this.#variable = _mapValues(\n                variables.variable,\n                (variable) => new dmetVariable(variable)\n            );\n            this.#table = _mapValues(variables.table, (list) => new dmetTable(list));\n            this.#id = variables.id;\n        }\n    }\n\n    get({ variableType, id }) {\n        switch (variableType) {\n            case 'variable':\n                return this.#variable[id];\n            case 'slide':\n                return this.#variable[id];\n            case 'list':\n                return this.#list[id];\n            case 'table':\n                return this.#table[id];\n            case 'default':\n                return undefined;\n        }\n    }\n\n    create(object) {\n        const { id, variableType } = object;\n        if (!id) {\n            throw 'not found ID';\n        }\n        if (variableType === 'variable') {\n            this.#variable[id] = new dmetVariable(object);\n        } else if (variableType === 'slide') {\n            this.#variable[id] = new dmetSlideVariable(object);\n        } else if (variableType === 'list') {\n            this.#list[id] = new dmetList(object);\n        } else if (variableType === 'table') {\n            this.#table[id] = new dmetTable(object);\n        }\n    }\n\n    #subscriber = new Map();\n\n    subscribe(key, callback) {\n        this.#subscriber.set(key, callback);\n    }\n\n    unsubscribe(key) {\n        this.#subscriber.delete(key, callback);\n    }\n\n    notify(...args) {\n        for (const observer of this.#subscriber.values()) {\n            observer(...args);\n        }\n    }\n\n    exec(operation) {\n        try {\n            const { id, variableType } = operation;\n            if (variableType === 'variable') {\n                return this.#variable[id].exec(operation);\n            } else if (variableType === 'slide') {\n                return this.#variable[id].exec(operation);\n            } else if (variableType === 'list') {\n                return this.#list[id].exec(operation);\n            } else if (variableType === 'table') {\n                return this.#table[id].exec(operation);\n            }\n        } finally {\n            this.notify();\n        }\n    }\n}\n\nexport { dmetList, dmetVariable, dmet, dmetTable };\n"
  },
  {
    "path": "src/extensions/dropper.js",
    "content": "import singleInstance from '../core/singleInstance';\nimport { Dropper } from '@entrylabs/tool';\n\nclass DropperExtension {\n    #view = null;\n    #dropper = null;\n    constructor() {\n        return this.#createView();\n    }\n\n    #createView() {\n        this.#view = Entry.Dom('div', {\n            class: 'entryDropper',\n            parent: $('.entryExtension'),\n        });\n\n        this.#dropper = new Dropper({\n            isShow: false,\n            container: this.#view[0],\n        });\n\n        return this.#dropper;\n    }\n}\n\nexport default singleInstance(DropperExtension);\n"
  },
  {
    "path": "src/extensions/extension.js",
    "content": "import Dropper from './dropper';\n\nexport default class Extension {\n    #view = null;\n    constructor() {\n        this.renderView();\n    }\n\n    renderView() {\n        if (!this.#view) {\n            this.#view = Entry.Dom('div', {\n                class: 'entryExtension',\n                parent: $('body'),\n            });\n        }\n    }\n\n    static getExtension(key) {\n        switch (key) {\n            case 'Dropper':\n                return Dropper.getInstance();\n        }\n    }\n}\n"
  },
  {
    "path": "src/extensions/target_checker.js",
    "content": "/**\n * @fileoverview TargetChecker for courseware.\n */\n'use strict';\n\n\nrequire(\"../util/utils\")\nrequire(\"../extensions/extension\")\n\n/**\n * @constructor\n */\nEntry.TargetChecker = function(code, isForEdit, type) {\n    this.isForEdit = isForEdit;\n    this.goals = [];\n    this.publicGoals = [];\n    this.unachievedGoals = [];\n    this.listener = {};\n    this.remainPublicGoal = 0;\n    this.lastMessage = \"\";\n    if (this.isForEdit) {\n        this.watchingBlocks = [];\n        Entry.playground.mainWorkspace.blockMenu.unbanClass(\"checker\");\n        Entry.addEventListener(\"run\", this.reRegisterAll.bind(this));\n    }\n\n    this.type = type || \"mission\";\n\n    this.isFail = false;\n    this.isSuccess = false;\n\n    this.entity = this;\n    this.parent = this;\n\n    Entry.achieveEvent = new Entry.Event();\n    Entry.addEventListener(\"stop\", this.reset.bind(this));\n\n    Entry.registerAchievement = this.registerAchievement.bind(this);\n    this.script = new Entry.Code(code ? code : [], this);\n    Entry.targetChecker = this;\n};\n\n(function(p) {\n    p.renderView = function() {\n        this._view = Entry.Dom('li', {\n            class: \"targetChecker\"\n        });\n\n        this._view.bindOnClick(function(e) {\n            Entry.playground.injectObject(this);\n        }.bind(this));\n        this.updateView();\n        if (!this.isForEdit)\n            this._view.addClass(\"entryRemove\");\n        return this._view;\n    };\n\n    p.generateStatusView = function(isForIframe) {\n        if(this.statusViewDisabled) {\n            return ;\n        }\n        this._statusView = Entry.Dom('div', {\n            class: \"entryTargetStatus\"\n        });\n        var innerWrapper = Entry.Dom('div', {\n            class: \"innerWrapper\",\n            parent: this._statusView\n        });\n        this._statusViewIndicator = Entry.Dom('div', {\n            class: \"statusIndicator\",\n            parent: innerWrapper\n        });\n        var statusViewContentWrapper = Entry.Dom('div', {\n            class: \"statusMessage\",\n            parent: innerWrapper\n        });\n        this._statusViewContent = Entry.Dom('p', {\n            parent: statusViewContentWrapper\n        });\n        if (isForIframe) {\n            $(Entry.view_).addClass(\"iframeWithTargetStatus\")\n            Entry.view_.appendChild(this._statusView[0]);\n        }\n        this.updateView();\n        this.showDefaultMessage();\n    };\n\n    p.updateView = function() {\n        if (this._view) {\n            this.renderViewMessage();\n            if (this.isSuccess)\n                this._view.addClass(\"success\");\n            else\n                this._view.removeClass(\"success\");\n            if (this.isFail)\n                this._view.addClass(\"fail\");\n            else\n                this._view.removeClass(\"fail\");\n        }\n        if (this._statusView) {\n            this.renderIndicatorMessage();\n        }\n    };\n\n    p.getStatusView = function() {\n         if (!this._statusView)\n             this.generateStatusView();\n         return this._statusView;\n    }\n\n    p.showStatusMessage = function(message) {\n        this.lastMessage = message;\n        this.lastIndicatorMessage = null;\n        this.renderIndicatorMessage();\n        if (this._statusViewContent && !this.isFail)\n            this._statusViewContent.text(message);\n        this.renderViewMessage();\n    };\n\n    p.achieveCheck = function(isSuccess, id) {\n        if (this.isFail || !Entry.engine.achieveEnabled)\n            return;\n        if (isSuccess)\n            this.achieveGoal(id);\n        else\n            this.fail(id);\n    };\n\n    p.achieveGoal = function(id) {\n        if (this.isSuccess || this.isFail || this.unachievedGoals.indexOf(id) < 0)\n            return;\n        this.unachievedGoals.splice(this.unachievedGoals.indexOf(id), 1);\n        if (this.publicGoals.indexOf(id) > -1)\n            this.remainPublicGoal--;\n        if (this.remainPublicGoal === 0) {\n            this.isSuccess = true;\n            this.showSuccessMessage();\n            Entry.achieveEvent.notify(\"success\", id);\n        }\n        this.updateView()\n    };\n\n    p.fail = function(id) {\n        if (this.isSuccess || this.isFail)\n            return;\n        this.showStatusMessage(id);\n        this.isFail = true;\n        Entry.achieveEvent.notify(\"fail\", id);\n        this.updateView();\n    };\n\n    p.reset = function() {\n        this.unachievedGoals = this.goals.concat();\n        this.remainPublicGoal = this.publicGoals.length;\n        this.isFail = false;\n        this.isSuccess = false;\n        this.updateView();\n        this.showDefaultMessage();\n    };\n\n    p.showDefaultMessage = function() {\n        switch(this.type) {\n            case \"mission\":\n                this.showStatusMessage(\"작품을 실행 해봅시다.\");\n                break;\n            case \"mission_intro\":\n                this.showStatusMessage(\"작품을 실행하며 미션을 파악해 봅시다.\");\n                this.renderIndicatorMessage(\"미션\");\n                break;\n            case \"guide_intro\":\n                this.showStatusMessage(\"작품을 실행하며 무엇을 만들지 알아 봅시다.\");\n                this.renderIndicatorMessage(\"안내\");\n                break;\n        }\n    };\n\n    p.showSuccessMessage = function() {\n        switch(this.type) {\n            case \"mission\":\n                break;\n            case \"mission_intro\":\n                this.showStatusMessage(\"이제 작품을 만들며 미션을 해결해 봅시다.\");\n                this.renderIndicatorMessage(\"미션\");\n                break;\n            case \"guide_intro\":\n                this.showStatusMessage(\"이제 학습을 시작해 봅시다.\");\n                this.renderIndicatorMessage(\"안내\");\n                break;\n        }\n    };\n\n    p.checkGoal = function(goalName) {\n        return this.goals.indexOf(goalName) > -1 &&\n            this.unachievedGoals.indexOf(goalName) < 0;\n    };\n\n    p.registerAchievement = function(originBlock) {\n        const block = $.extend(true, {}, originBlock);\n        block.params = originBlock.params.map(p => p instanceof Entry.Block ? p.data.params[0] : p);\n\n        if (this.isForEdit)\n            this.watchingBlocks.push(block);\n        if (block.params[1] && this.goals.indexOf(block.params[0] + \"\") < 0) {\n            this.goals.push(block.params[0] + \"\");\n            if (block.params[2])\n                this.publicGoals.push(block.params[0] + \"\");\n            this.remainPublicGoal = this.publicGoals.length;\n        }\n        this.reset();\n    };\n\n    p.reRegisterAll = function() {\n        const blocks = this.script.getBlockList(false, 'check_lecture_goal').map(originBlock => {\n            const block = $.extend(true, {}, originBlock);\n            block.params = originBlock.params.map(p => p instanceof Entry.Block ? p.data.params[0] : p);\n            return block;\n        });\n\n        this.watchingBlocks = blocks;\n        this.goals = _.uniq(\n            blocks.filter(function(b) {return b.params[1] === 1})\n                  .map(function(b) {return b.params[0] + \"\"})\n        );\n        this.publicGoals = _.uniq(\n            blocks.filter(function(b) {return b.params[1] === 1 && b.params[2] === 1})\n                  .map(function(b) {return b.params[0] + \"\"})\n        );\n        this.remainPublicGoal = this.publicGoals.length;\n    };\n\n    p.clearExecutor = function() {\n        this.script.clearExecutors();\n    };\n\n    p.clearListener = function () {\n        Object.values(this.listener).forEach((listener) => {\n            listener.destroy();\n        });\n        this.listener = {};\n    }\n\n    p.destroy = function() {\n        this.reset();\n        Entry.achieveEvent.clear();\n        this.script.destroy();\n        $(this._view).remove();\n    };\n\n    p.renderViewMessage = function() {\n        var len = this.goals.length;\n        var publicLen = this.publicGoals.length;\n        if (this._view)\n            this._view.html(\"목표 : \" + (len - this.unachievedGoals.length) +\n                            \" / \" + len + \" , 공식 목표 : \" +\n                           (publicLen - this.remainPublicGoal) + \" / \" + publicLen + \"<br>\" +\n                           this.lastMessage);\n    };\n\n    p.renderIndicatorMessage = function(message) {\n        if (!this._statusViewIndicator)\n            return;\n        if (message)\n            this.lastIndicatorMessage = message;\n\n        var publicLen = this.publicGoals.length;\n        this._statusViewIndicator.text(\n            this.lastIndicatorMessage ||\n                Math.min(publicLen - this.remainPublicGoal + 1, publicLen) +\n                \"/\" + publicLen\n        )\n    }\n\n})(Entry.TargetChecker.prototype);\n"
  },
  {
    "path": "src/graphicEngine/EaselResManager.ts",
    "content": "import { IGEResManager } from './IGEResManager';\nimport { IRawPicture } from '../class/pixi/atlas/model/IRawPicture';\nimport { AtlasImageLoader, ImageLoaderHandler } from '../class/pixi/atlas/loader/AtlasImageLoader';\nimport { AtlasImageLoadingInfo } from '../class/pixi/atlas/loader/AtlasImageLoadingInfo';\nimport { PIXIAtlasHelper } from '../class/pixi/atlas/PIXIAtlasHelper';\n\nexport class EaselResManager implements IGEResManager {\n\n    private _imgLoader:AtlasImageLoader;\n    private _MAX_TEX_RECT = {x:0, y:0, width:99999, height:99999 };\n\n    INIT():void {\n        this._imgLoader = new AtlasImageLoader(this._onImageLoad.bind(this));\n    }\n\n    private _onImageLoad(info:AtlasImageLoadingInfo):void {\n        //do nothing\n    }\n\n    imageRemoved(reason:string):void {\n        this._imgLoader.requestSync();\n    }\n\n    activateScene(sceneID:string):void {\n        //do nothing\n    }\n\n    reqResource(spriteNullable:PIXI.Sprite | any, sceneID:string, pic:IRawPicture, callback:ImageLoaderHandler|null):void {\n        const loader = this._imgLoader;\n        let path = PIXIAtlasHelper.getRawPath(pic);\n        let info = loader.getImageInfo(path);\n        if(!info) {\n            let rect = PIXIAtlasHelper.getNewImageRect(pic, this._MAX_TEX_RECT);\n            loader.load(pic,  rect);\n            info = loader.getImageInfo(path);\n        }\n        if(spriteNullable) {\n            spriteNullable.image = info.source();\n        }\n        if(!info.isReady) {\n            info.addCallback(callback);\n        } else {\n            callback && callback(info);\n        }\n\n    }\n\n    clearProject():void {\n        this._imgLoader.empty();\n    }\n\n    removeScene(sceneID:string):void {\n        this._imgLoader.requestSync();\n    }\n\n}"
  },
  {
    "path": "src/graphicEngine/FakePIXI.js",
    "content": "(function() {\n    if(window.PIXI) {\n        return;\n    }\n\n    const emptyFn = ()=>{};\n    let names = [\"Rectangle\", \"Texture\", \"Sprite\", \"RenderTexture\", \"Matrix\", \"Graphics\", \"Container\", \"TextStyle\", \"TextMetrics\", \"Text\", \"BaseTexture\", \"Point\"];\n    let pixi = {};\n    names.forEach((v)=>{\n        pixi[v] = emptyFn;\n    });\n    window.PIXI = pixi;\n\n    /* //PIXI를 통해 참조하는 속성을 찾아내기 위한 함수\n    var arr = [];\n    window.pixinames = arr;\n    window.PIXI = new Proxy({}, {\n        get: (target, prop) => {\n            if(arr.indexOf(prop) < 0 ) {\n                arr.push(prop);\n            }\n            return emptyFn;\n        }\n    });\n    */\n})();"
  },
  {
    "path": "src/graphicEngine/GEDragHelper.ts",
    "content": "interface IEventType {\n    UP: string;\n    MOVE: string;\n    DOWN: string;\n    OVER: string;\n}\n\nfunction getPIXIEvent(): IEventType {\n    return {\n        UP: '__pointerdown',\n        DOWN: '__pointermove',\n        MOVE: '__pointerup',\n        OVER: 'pointerover',\n    };\n}\n\nfunction getCreatejsEvent(): IEventType {\n    return {\n        UP: 'pressup',\n        DOWN: 'mousedown',\n        MOVE: 'pressmove',\n        OVER: 'mouseover',\n    };\n}\n\n\nclass _GEDragHelper {\n\n    types: IEventType;\n    private _isWebGL: boolean;\n    public handleDrag: (target: any) => void;\n\n    INIT(isWebGL: boolean) {\n        this._isWebGL = isWebGL;\n        this.types = isWebGL ? getPIXIEvent() : getCreatejsEvent();\n        if (isWebGL) {\n            this.types = getPIXIEvent();\n            this.handleDrag = this._handleDragPIXI;\n        } else {\n            this.types = getCreatejsEvent();\n            this.handleDrag = this._handleCreateJs;\n        }\n    }\n\n    /**\n     * @since 190705 extracold1209\n     * common / move event 는 down / up 사이에 있도록 정리\n     * as-is / 모든 이벤트 등록, down 외 up, outside, cancel 은 up\n     * to-be /\n     * 최초 이벤트는 down 만 등록\n     * down 이벤트 발생시\n     * - move, outside, up 이벤트 등록\n     * - 그러나 outside 는 최초 down 한 포인트로 이벤트 발생\n     *\n     * TODO 기존 방식이 move 중 스테이지를 벗어난 경우 cancel 을 위한 onUpEvent 라면\n     *  다른 방법(스테이지안에 포인터가 있는것인지 체크)으로 확인해야 할 것같음.\n     *  현재 블록코딩시 webGL 을 사용하지 않고, minimize 에서는 move event 없으므로 개선보류\n     */\n    private _handleDragPIXI(target: any) {\n        const C = this.types;\n        const CE = this._convertPIXIEventToCreateJsStyle;\n\n        function _onMove(e: any) {\n            target.emit(C.MOVE, CE(e));\n        }\n\n        function _onUp(e: any) {\n            target.emit(C.UP, CE(e));\n            target.removeAllListeners('pointermove');\n            target.removeAllListeners('pointerup');\n            target.removeAllListeners('pointerupoutside');\n        }\n\n        function _onDown(e: any) {\n            target.emit(C.DOWN, CE(e));\n            target.on('pointermove', _onMove);\n            target.on('pointerupoutside', () => {\n                _onUp(e);\n            });\n            target.on('pointerup', _onUp);\n        }\n\n        target.on('pointerdown', _onDown);\n    }\n\n    private _convertPIXIEventToCreateJsStyle(e: any) {\n        let g = e.data.global;\n        return {\n            target: e.target,\n            currentTarget: e.currentTarget,\n            stageX: g.x,\n            stageY: g.y,\n            rawX: g.x,\n            rawY: g.y,\n        };\n    }\n\n    private _handleCreateJs(target: any) {\n        //do nothing;\n    }\n\n}\n\nexport let GEDragHelper = new _GEDragHelper();\n"
  },
  {
    "path": "src/graphicEngine/GEHandle.js",
    "content": "/**\n * Resize handle on Easel.js\n */\n\n'use strict';\n\nimport { GEDragHelper } from './GEDragHelper';\nimport { GEHelper } from './GEHelper';\n\nexport const GEHandle = function(canvas) {\n    if (typeof createjs != 'object') {\n        throw 'createjs is not founded';\n    }\n    const colorSet = EntryStatic.colorSet.canvas || {};\n    this.canvas = canvas;\n    this.borderColor = colorSet.handleBorder || '#e2e2e2';\n    this.knobColor = colorSet.handleKnob || '#4f80ff';\n    this.arrowColor = colorSet.handleArrow || '#ffb500';\n    this.centerColor = colorSet.handleCenter || '#4f80ff';\n    this.rotateKnobColor = colorSet.handleRotateKnob || '#ffb500';\n\n    this.x = 0;\n    this.y = 0;\n    this.rotation = 0;\n    this.direction = 0;\n    this.width = 100;\n    this.height = 100;\n    this.flipX = false;\n    this.flipY = false;\n    this.visible = false;\n    this.draggable = true;\n\n    this.centerEditable = true;\n    this.rotationEditable = true;\n    this.directionEditable = true;\n    this.resizeEnable = true;\n\n    this.onChangeFunction = null;\n    this.callerObject = null;\n\n    this.createHandle();\n    this.render();\n    this.selectedObject = null;\n};\n\n(function(p) {\n    p.setChangeListener = function(object, func) {\n        this.onChangeFunction = func;\n        this.callerObject = object;\n        return this;\n    };\n\n    /**\n     * for undo and redo\n     */\n    p.setEditStartListener = function(object, func) {\n        this.onEditStartFunction = func;\n        this.editStartCallerObject = object;\n        return this;\n    };\n\n    p.setEditEndListener = function(object, func) {\n        this.onEditEndFunction = func;\n        this.editEndCallerObject = object;\n        return this;\n    };\n\n    p.toggleCenter = function(isEnable) {\n        this.centerEditable = isEnable;\n        this.centerPoint.visible = isEnable;\n    };\n\n    p.toggleRotation = function(isEnable) {\n        this.rotationEditable = isEnable;\n        this.rotateKnob.visible = isEnable;\n    };\n\n    p.toggleDirection = function(isEnable) {\n        this.directionEditable = isEnable;\n        this.directionArrow.visible = isEnable;\n    };\n\n    p.toggleResize = function(isEnable) {\n        this.resizeEditable = isEnable;\n        for (let i = 0; i < 8; i++) {\n            this.knobs[i].visible = isEnable;\n        }\n    };\n\n    p.toggleFont = function(isEnable) {\n        this.fontEditable = isEnable;\n        this.fontKnob.visible = isEnable;\n    };\n\n    p.setX = function(xPos) {\n        this.x = xPos;\n        this.container.x = xPos;\n        this.background.x = xPos;\n    };\n\n    p.setY = function(yPos) {\n        this.y = yPos;\n        this.container.y = yPos;\n        this.background.y = yPos;\n    };\n\n    p.setWidth = function(width) {\n        this.width = width;\n        this.background.scaleX = width / 100;\n    };\n\n    p.setHeight = function(height) {\n        this.height = height;\n        this.background.scaleY = height / 100;\n    };\n\n    p.setRegX = function(regX) {\n        this.regX = regX;\n        this.centerPoint.x = regX;\n    };\n\n    p.setRegY = function(regY) {\n        this.regY = regY;\n        this.centerPoint.y = regY;\n    };\n\n    p.setRotation = function(rotation) {\n        rotation = (rotation + 360) % 360;\n        this.rotation = rotation;\n        rotation *= GEHelper.rotateWrite;\n        this.container.rotation = rotation;\n        this.background.rotation = rotation;\n        this.updateKnobCursor();\n    };\n\n    p.setDirection = function(direction) {\n        direction = (direction + 360) % 360;\n        this.direction = direction;\n        this.directionArrow.rotation = direction * GEHelper.rotateWrite;\n    };\n\n    p.setVisible = function(visible) {\n        this.visible = visible;\n        this.container.visible = visible;\n        this.background.visible = visible;\n    };\n\n    p.setFont = function(fontSize) {\n        this.font = fontSize;\n        this.fontKnob.y = fontSize - this.height / 2;\n    };\n\n    p.createHandle = function() {\n        const handle = this;\n        const container = GEHelper.newContainer();\n        container.mouseEnabled = true;\n        container.mouseChildren = true;\n\n        //border\n        const border = GEHelper.newGraphic();\n        container.addChild(border);\n        this.border = border;\n\n        //edge\n        const edge = GEHelper.newGraphic();\n        edge.cursor = 'move';\n        edge.mouseEnabled = true;\n        GEDragHelper.handleDrag(edge);\n\n        edge.on(GEDragHelper.types.DOWN, function(e) {\n            const offset = handle.getEventCoordinate(e);\n            offset.x -= handle.x;\n            offset.y -= handle.y;\n            this.offset = offset;\n            handle.dispatchEditStartEvent();\n        });\n        edge.on(GEDragHelper.types.MOVE, function(e) {\n            if (handle.getDraggable()) {\n                const pos = handle.getEventCoordinate(e);\n                pos.x -= this.offset.x;\n                pos.y -= this.offset.y;\n                handle.setX(pos.x);\n                handle.setY(pos.y);\n                handle.dispatchOnChangeEvent();\n            }\n        });\n        edge.on(GEDragHelper.types.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(edge);\n        container.setChildIndex(edge, 1);\n        this.edge = edge;\n\n        //rotate knob\n        const rotateKnob = GEHelper.newSpriteWithCallback(`${Entry.mediaFilePath}stage/rotate.png`);\n        rotateKnob.scaleX = 0.4;\n        rotateKnob.scaleY = 0.4;\n        rotateKnob.regX = 25;\n        rotateKnob.regY = 125;\n        rotateKnob.mouseEnabled = true;\n        GEDragHelper.handleDrag(rotateKnob);\n        rotateKnob.cursor = 'crosshair';\n        rotateKnob.on(GEDragHelper.types.DOWN, (e) => {\n            handle.dispatchEditStartEvent();\n        });\n        rotateKnob.on(GEDragHelper.types.MOVE, (e) => {\n            const pos = handle.getEventCoordinate(e);\n            pos.x -= handle.x;\n            pos.y -= handle.y;\n            const rotation = (-Math.atan2(pos.x, pos.y) / Math.PI) * 180 - 180;\n            handle.setRotation(rotation);\n            handle.dispatchOnChangeEvent();\n        });\n        rotateKnob.on(GEDragHelper.types.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(rotateKnob);\n        container.setChildIndex(rotateKnob, 1);\n        this.rotateKnob = rotateKnob;\n\n        const directionArrow = GEHelper.newGraphic();\n        directionArrow.mouseEnabled = true;\n        GEDragHelper.handleDrag(directionArrow);\n\n        if (GEHelper.isWebGL) {\n            const arrowLength = 7; // 이 값이 작아질수록 길어집니다\n            directionArrow.graphics\n                .f(this.arrowColor)\n                .mt(0, -40 + arrowLength)\n                .lt(9, -30 + arrowLength)\n                .lt(-9, -30 + arrowLength)\n                .closePath()\n                .dr(-2, -32 + arrowLength, 4, 25);\n        } else {\n            const arrowLength = 7;\n            directionArrow.graphics\n                .ss(4, 1, 1)\n                .s(this.arrowColor)\n                .f(this.arrowColor)\n                .dc(0, 0, this.DHANDLE_RADIUS)\n                .mt(0, 0)\n                .lt(0, -40 + arrowLength)\n                .lt(7, -32 + arrowLength)\n                .lt(-7, -32 + arrowLength)\n                .lt(0, -40 + arrowLength)\n                .es();\n        }\n\n        directionArrow.on(GEDragHelper.types.DOWN, (e) => {\n            handle.dispatchEditStartEvent();\n        });\n        directionArrow.on(GEDragHelper.types.MOVE, (e) => {\n            const pos = handle.getLocalCoordinate(handle.getEventCoordinate(e));\n            const rotation = (-Math.atan2(pos.x, pos.y) / Math.PI) * 180 - 180;\n            handle.setDirection(rotation);\n            handle.dispatchOnChangeEvent();\n        });\n        directionArrow.on(GEDragHelper.types.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(directionArrow);\n        this.directionArrow = directionArrow;\n\n        // center\n        const centerPoint = GEHelper.newGraphic();\n        centerPoint.mouseEnabled = true;\n        GEDragHelper.handleDrag(centerPoint);\n        centerPoint.scaleX = 1.52;\n        centerPoint.scaleY = 1.52;\n        centerPoint.graphics\n            .ss(3.5, 2, 0)\n            .s('#FFFFFF')\n            .beginFill(this.centerColor)\n            .dc(0, 0, 5.5);\n        centerPoint.on(GEDragHelper.types.DOWN, (e) => {\n            handle.dispatchEditStartEvent();\n        });\n        centerPoint.on(GEDragHelper.types.MOVE, (e) => {\n            let pos = handle.getEventCoordinate(e);\n            pos = handle.getLocalCoordinate(pos);\n            handle.setRegX(pos.x);\n            handle.setRegY(pos.y);\n            handle.dispatchOnChangeEvent();\n        });\n        centerPoint.on(GEDragHelper.types.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        container.addChild(centerPoint);\n        this.centerPoint = centerPoint;\n\n        //resize knobs\n        this.knobs = [];\n        for (let i = 0; i < 8; i++) {\n            const knob = GEHelper.newGraphic();\n            knob.mouseEnabled = true;\n            GEDragHelper.handleDrag(knob);\n            knob.scaleX = 1.52;\n            knob.scaleY = 1.52;\n            knob.graphics\n                .ss(0.2, 0, 0)\n                .s('#d8d8d8')\n                .beginFill('#ffffff')\n                .rr(-6, -6, 12, 12, 1)\n                .beginFill(this.knobColor)\n                .rr(-3.4, -3.4, 7, 7, 1);\n            knob.knobIndex = i;\n            //knob.cursor = \"move\";\n\n            knob.on(GEDragHelper.types.DOWN, function(e) {\n                const otherKnobIndex =\n                    this.knobIndex + 4 > 7 ? this.knobIndex + 4 - 8 : this.knobIndex + 4;\n                const otherKnob = handle.knobs[otherKnobIndex];\n                const otherKnobPos = handle.getGlobalCoordinate(otherKnob);\n                this.otherKnobPos = otherKnobPos;\n                handle.dispatchEditStartEvent();\n            });\n            knob.on(GEDragHelper.types.MOVE, function(e) {\n                const pos = handle.getEventCoordinate(e);\n                if (handle.checkCenterPointState(handle.regX, handle.regY)) {\n                    handle.setRegX(0);\n                    handle.setRegY(0);\n                    handle.dispatchOnChangeEvent();\n                }\n                handle.adjust(this.knobIndex, this.otherKnobPos, pos);\n            });\n            knob.on(GEDragHelper.types.UP, (e) => {\n                handle.dispatchEditEndEvent();\n            });\n            container.addChild(knob);\n            container.setChildIndex(knob, 3);\n            this.knobs.push(knob);\n        }\n\n        const background = GEHelper.newGraphic();\n        background.mouseEnabled = true;\n        GEDragHelper.handleDrag(background);\n        background.graphics\n            .ss(1, 2, 0)\n            .s('rgba(254,254,254,0.01)')\n            .beginFill('rgba(254,254,254,1)')\n            .dr(-50, -50, 100, 100);\n        background.on(GEDragHelper.types.DOWN, function(e) {\n            const offset = handle.getEventCoordinate(e);\n            offset.x -= handle.x;\n            offset.y -= handle.y;\n            this.offset = offset;\n            handle.dispatchEditStartEvent();\n        });\n        background.on(GEDragHelper.types.MOVE, function(e) {\n            if (handle.getDraggable()) {\n                const pos = handle.getEventCoordinate(e);\n                pos.x -= this.offset.x;\n                pos.y -= this.offset.y;\n                handle.setX(pos.x);\n                handle.setY(pos.y);\n                handle.dispatchOnChangeEvent();\n            }\n        });\n        background.on(GEDragHelper.types.UP, (e) => {\n            handle.dispatchEditEndEvent();\n        });\n        this.canvas.addChildAt(background, 0);\n        this.background = background;\n\n        this.container = container;\n        this.canvas.addChild(this.container);\n    };\n\n    p.checkCenterPointState = function(x, y) {\n        const standard = 718;\n        const res = Math.sqrt(x * x + y * y);\n        if (res > standard && Entry.engine.isState('stop')) {\n            Entry.toast.warning(\n                Lang.Workspace.toast_error_title_object_center,\n                Lang.Workspace.toast_error_contents_object_center\n            );\n            return true;\n        }\n        return false;\n    };\n\n    p.render = function() {\n        this.renderBorder();\n        this.renderEdge();\n        this.renderRotateKnob();\n        this.renderKnobs();\n    };\n\n    p.renderEdge = function() {\n        const width = this.width;\n        const height = this.height;\n        const t = 10; //thickness\n        const sx = -(width + t) / 2; //startX\n        const sy = -(height + t) / 2; //startY\n\n        this.edge.graphics\n            .clear()\n            .f('rgba(254,254,254,0.01)')\n            .dr(sx, sy, width + t, t)\n            .dr(sx, sy + height, width + t, t)\n            .dr(sx, sy + t, t, height - t)\n            .dr(sx + width, sy + t, t, height - t);\n    };\n\n    p.renderRotateKnob = function() {\n        this.rotateKnob.y = -this.height / 2;\n    };\n\n    p.renderBorder = function() {\n        const width = this.width;\n        const height = this.height;\n        this.border.graphics\n            .clear()\n            .ss(0.5, 2, 0)\n            .s(this.borderColor)\n            .mt(-width / 2, -height / 2)\n            .lt(0, -height / 2)\n            .lt(0, -height / 2)\n            .lt(+width / 2, -height / 2)\n            .lt(+width / 2, +height / 2)\n            .lt(-width / 2, +height / 2)\n            .cp();\n    };\n\n    p.renderKnobs = function() {\n        const width = this.width / 2;\n        const height = this.height / 2;\n        this.knobs.forEach((knob, i) => {\n            knob.x = Math.round(Math.sin((i / 4) * Math.PI)) * width;\n            knob.y = Math.round(Math.cos((i / 4) * Math.PI)) * height;\n        });\n    };\n\n    p.getEventCoordinate = function(e) {\n        return {\n            x: e.stageX * 0.75 - 240,\n            y: e.stageY * 0.75 - 135,\n        };\n    };\n\n    p.getGlobalCoordinate = function(childObject) {\n        const container = this.container;\n        const rotation = -(((this.container.rotation * Math.PI) / 180) * GEHelper.rotateRead);\n        return {\n            x: this.x + childObject.x * Math.cos(rotation) + childObject.y * Math.sin(rotation),\n            y: this.y + childObject.y * Math.cos(rotation) - childObject.x * Math.sin(rotation),\n        };\n    };\n\n    p.getLocalCoordinate = function(pos) {\n        const container = this.container;\n        const rotation = ((this.container.rotation * Math.PI) / 180) * GEHelper.rotateRead;\n        pos.x -= this.x;\n        pos.y -= this.y;\n        return {\n            x: pos.x * Math.cos(rotation) + pos.y * Math.sin(rotation),\n            y: pos.y * Math.cos(rotation) - pos.x * Math.sin(rotation),\n        };\n    };\n\n    p.adjust = function(knobIndex, otherKnobPos, pos) {\n        const newPoint = this.calcPos({ x: this.x, y: this.y }, otherKnobPos, pos);\n        const newCenter = {\n            x: (otherKnobPos.x + newPoint.x) / 2,\n            y: (otherKnobPos.y + newPoint.y) / 2,\n        };\n        const newLength = Math.sqrt(\n            Math.pow(newPoint.x - otherKnobPos.x, 2) + Math.pow(newPoint.y - otherKnobPos.y, 2)\n        );\n        if (knobIndex % 4 == 0) {\n            const ratio = newLength / this.height;\n            this.height = newLength;\n            this.setRegY(this.regY * ratio);\n        } else if (knobIndex % 4 == 2) {\n            const ratio = newLength / this.width;\n            this.width = newLength;\n            this.setRegX(this.regX * ratio);\n        } else {\n            const oldLength =\n                2 *\n                Math.sqrt(\n                    Math.pow(this.x - otherKnobPos.x, 2) + Math.pow(this.y - otherKnobPos.y, 2)\n                );\n            const newWidth = (this.width * newLength) / oldLength;\n            let ratio = newWidth / this.width;\n            this.setWidth(newWidth);\n            this.setRegX(this.regX * ratio);\n            const newHeight = (this.height * newLength) / oldLength;\n            ratio = newHeight / this.height;\n            this.setHeight((this.height * newLength) / oldLength);\n            this.setRegY(this.regY * ratio);\n        }\n        this.setX(newCenter.x);\n        this.setY(newCenter.y);\n\n        this.render();\n        this.dispatchOnChangeEvent();\n    };\n\n    p.updateKnobCursor = function() {\n        const rotation = this.rotation * GEHelper.rotateRead;\n        const cursorList = ['ns-resize', 'nwse-resize', 'ew-resize', 'nesw-resize'];\n        const iter = Math.round(rotation / 45);\n        for (let i = 0; i < iter; i++) {\n            cursorList.unshift(cursorList.pop());\n        }\n        for (let i = 0; i < 8; i++) {\n            this.knobs[i].cursor = cursorList[i % 4];\n        }\n    };\n\n    p.calcPos = function(pos1, pos2, targetPos) {\n        if (pos1.x == pos2.x) {\n            return {\n                x: pos1.x,\n                y: targetPos.y,\n            };\n        } else if (pos1.y == pos2.y) {\n            return {\n                x: targetPos.x,\n                y: pos1.y,\n            };\n        } else {\n            const a = pos1.y - pos2.y;\n            const b = pos2.x - pos1.x;\n            const c = pos1.x * pos2.y - pos2.x * pos1.y;\n            const k = -(a * targetPos.x + b * targetPos.y + c) / (a * a + b * b);\n            return {\n                x: targetPos.x + a * k,\n                y: targetPos.y + b * k,\n            };\n        }\n    };\n\n    p.dispatchOnChangeEvent = function() {\n        if (this.onChangeFunction) {\n            this.onChangeFunction.call(this.callerObject, this);\n        }\n    };\n\n    p.dispatchEditStartEvent = function() {\n        if (this.onEditStartFunction) {\n            this.onEditStartFunction.call(this.editStartCallerObject, this);\n        }\n    };\n\n    p.dispatchEditEndEvent = function() {\n        if (this.onEditEndFunction) {\n            this.onEditEndFunction.call(this.editEndCallerObject, this);\n        }\n    };\n\n    p.setDraggable = function(bool) {\n        this.draggable = bool;\n    };\n\n    p.getDraggable = function() {\n        return this.draggable;\n    };\n})(GEHandle.prototype);\n"
  },
  {
    "path": "src/graphicEngine/GEHelper.ts",
    "content": "import * as PIXI from 'pixi.js';\nimport PIXIHelper from '../class/pixi/helper/PIXIHelper';\nimport { PIXIGlobal } from '../class/pixi/init/PIXIGlobal';\nimport { GEDragHelper } from './GEDragHelper';\nimport { IGEResManager } from './IGEResManager';\nimport { EaselResManager } from './EaselResManager';\nimport { PIXIBrushAdaptor } from '../class/pixi/etc/PIXIBrushAdaptor';\nimport { PIXIPaintAdaptor } from '../class/pixi/etc/PIXIPaintAdaptor';\nimport { PIXIScaleAdaptor } from '../class/pixi/atlas/PIXIScaleAdaptor';\n\nconst INITIAL_VIDEO_PARAMS = {\n    WIDTH: 480,\n    HEIGHT: 270,\n    X: -240,\n    Y: -135,\n    SCALE_X: 0.75,\n    SCALE_Y: 0.75,\n    ALPHA: 0.5,\n};\n\nconst isFirefox = typeof InstallTrigger !== 'undefined';\ndeclare let createjs: any;\n\ninterface IGraphicsEngineApplication {\n    render(): void;\n    stage: PIXI.Container | any;\n    destroy(destroyOption: any): void;\n}\n\ninterface ITicker {\n    reset(): void;\n    setFPS(n: number): void;\n}\n\nclass CreateJsApplication implements IGraphicsEngineApplication {\n    stage: any;\n\n    constructor(canvas: HTMLCanvasElement) {\n        const stage = new createjs.Stage(canvas.id);\n        createjs.Touch.enable(stage);\n        stage.enableMouseOver(10);\n        stage.mouseMoveOutside = true;\n        this.stage = stage;\n    }\n\n    render(): void {\n        this.stage.update();\n    }\n\n    destroy(destroyOption: any) {\n        this.stage = null;\n    }\n}\n\nexport class GEHelperBase {\n    protected _isWebGL: boolean = false;\n\n    INIT(isWebGL: boolean) {\n        this._isWebGL = isWebGL;\n    }\n}\n\nconst emptyFn = (...arg: any[]) => {};\n\nclass _GEHelper extends GEHelperBase {\n    get isWebGL(): boolean {\n        return this._isWebGL;\n    }\n    public resManager: IGEResManager;\n    public textHelper: _TextHelper;\n    public colorFilter: _ColorFilterHelper;\n    public brushHelper: _BrushHelper;\n\n    /**  pixi 객체로부터 rotate를 읽을 때 사용할 값 */\n    public rotateRead: number = 1;\n\n    /**  pixi 객체에 rotate를 할당 할 때 사용할 값 */\n    public rotateWrite: number = 1;\n\n    public Ticker: ITicker;\n    private _isInitialized: boolean;\n\n    /**  pixi Graphics로 비디오 감지 표현하기 위한 PIXI.Graphics */\n    public poseIndicatorGraphic: PIXI.Graphics | createjs.Graphics;\n    public faceIndicatorGraphic: PIXI.Graphics | createjs.Graphics;\n    public objectIndicatorGraphic: PIXI.Graphics | createjs.Graphics;\n\n    /**\n     * issues/9422#issuecomment-2678582\n     * 최종 좌표 결정 단계에서 약간의 오차를 주어 이 현상을 막음.\n     */\n    public rndPosition: () => number;\n\n    /**\n     * 비디오 블록용 컨테이너, index = 2 , 기존의 오브젝트 컨테이너 = index3;\n     */\n    private videoContainer: PIXI.Container | createjs.Container;\n    private overlayContainer: PIXI.Container | createjs.Container;\n\n    INIT(isWebGL: boolean) {\n        super.INIT(isWebGL);\n        if (this._isInitialized) {\n            return;\n        }\n        this._isInitialized = true;\n        GEDragHelper.INIT(isWebGL);\n        (this.colorFilter = new _ColorFilterHelper()).INIT(isWebGL);\n        (this.textHelper = new _TextHelper()).INIT(isWebGL);\n        (this.brushHelper = new _BrushHelper()).INIT(isWebGL);\n        if (this._isWebGL) {\n            // this.rndPosition = ()=>{ return Math.random() * 0.8 - 0.4; };\n            this.rndPosition = () => 0;\n            this.rotateRead = 180 / Math.PI;\n            this.rotateWrite = Math.PI / 180;\n            PIXIGlobal.initOnce();\n            this.resManager = PIXIGlobal.atlasManager;\n            this.Ticker = {\n                reset: emptyFn,\n                setFPS: emptyFn,\n            };\n        } else {\n            this.rndPosition = () => 0;\n            this.resManager = new EaselResManager();\n            this.Ticker = {\n                reset: createjs.Ticker.reset,\n                setFPS: createjs.Ticker.setFPS,\n            };\n        }\n        this.resManager.INIT();\n    }\n\n    newApp(canvas: HTMLCanvasElement): IGraphicsEngineApplication {\n        let app: IGraphicsEngineApplication;\n        if (this._isWebGL) {\n            app = PIXIGlobal.getNewApp(canvas);\n        } else {\n            app = new CreateJsApplication(canvas);\n        }\n        return app;\n    }\n\n    cloneStamp(entity: any): any {\n        if (this._isWebGL) {\n            const orgObj = entity.object;\n            const orgTex = orgObj.internal_getOriginalTex && orgObj.internal_getOriginalTex();\n            const object = PIXIHelper.sprite('StampEntity', orgTex || orgObj.texture);\n            object.visible = orgObj.visible;\n            object.interactive = false;\n            object.interactiveChildren = false;\n            object.setTransform(\n                orgObj.x,\n                orgObj.y,\n                orgObj.scale.x,\n                orgObj.scale.y,\n                orgObj.rotation,\n                orgObj.skew.x,\n                orgObj.skew.y,\n                orgObj.pivot.x,\n                orgObj.pivot.y\n            );\n            return object;\n        } else {\n            const object = entity.object.clone();\n            object.mouseEnabled = false;\n            object.tickEnabled = false;\n            object.filters = null;\n            return object;\n        }\n    }\n\n    hitTestMouse(object: any): boolean {\n        if (this._isWebGL) {\n            const pixiApp: PIXI.Application = Entry.stage._app;\n            const im = pixiApp.renderer.plugins.interaction;\n            const hitObject = im.hitTest(im.mouse.global, object);\n            return !!hitObject;\n        } else {\n            if (object.alpha < 0.001) {\n                return false;\n            }\n            const stage = Entry.stage.canvas;\n            const pt = object.globalToLocal(stage.mouseX, stage.mouseY);\n            return object.hitTest(pt.x, pt.y);\n        }\n    }\n\n    tickByEngine() {\n        if (this._isWebGL) {\n            Entry.stage._app.ticker.start();\n        } else {\n            createjs.Ticker.addEventListener('tick', Entry.stage.canvas);\n        }\n    }\n    // for createJS ONLY issue, #12012\n    disableTickByEngine() {\n        if (this._isWebGL) {\n            return;\n        } else {\n            createjs.Ticker.removeEventListener('tick', Entry.stage.canvas);\n        }\n    }\n\n    getNewContainer(): any {\n        if (this._isWebGL) {\n            return new PIXI.Container();\n        } else {\n            return new createjs.Container();\n        }\n    }\n\n    // this function returns corresponding VideoElement,\n    getVideoElement(video: HTMLVideoElement): any {\n        console.log('getVideoElement');\n        let videoElement: any = null;\n        const { WIDTH, X, Y, SCALE_X, SCALE_Y, ALPHA } = INITIAL_VIDEO_PARAMS;\n        let HEIGHT = INITIAL_VIDEO_PARAMS.HEIGHT;\n\n        if (this._isWebGL) {\n            const videoTexture = PIXI.Texture.from(video);\n            videoElement = new PIXI.Sprite(videoTexture);\n            if (isFirefox) {\n                HEIGHT *= 1.33;\n            }\n        } else {\n            videoElement = new createjs.Bitmap(video);\n        }\n        videoElement.width = WIDTH;\n        videoElement.height = HEIGHT;\n        videoElement.x = X;\n        videoElement.y = Y;\n        videoElement.alpha = ALPHA;\n\n        if (this._isWebGL) {\n            videoElement.scale.x = SCALE_X;\n            videoElement.scale.y = SCALE_Y;\n        } else {\n            videoElement.scaleX = SCALE_X;\n            videoElement.scaleY = SCALE_Y;\n            videoElement.on('tick', () => {\n                if (videoElement.cacheCanvas) {\n                    videoElement.updateCache();\n                }\n            });\n        }\n        return videoElement;\n    }\n\n    getOverlayElement(canvas: HTMLCanvasElement): any {\n        let overlayElement: any = null;\n        const { WIDTH, X, Y, SCALE_X, SCALE_Y, ALPHA } = INITIAL_VIDEO_PARAMS;\n        let HEIGHT = INITIAL_VIDEO_PARAMS.HEIGHT;\n\n        if (this._isWebGL) {\n            const videoTexture = PIXI.Texture.from(canvas);\n            overlayElement = new PIXI.Sprite(videoTexture);\n            if (isFirefox) {\n                HEIGHT *= 1.33;\n            }\n        } else {\n            overlayElement = new createjs.Bitmap(canvas);\n        }\n        overlayElement.width = WIDTH;\n        overlayElement.height = HEIGHT;\n        overlayElement.x = X;\n        overlayElement.y = Y;\n        overlayElement.alpha = ALPHA;\n\n        if (this._isWebGL) {\n            overlayElement.scale.x = SCALE_X;\n            overlayElement.scale.y = SCALE_Y;\n        } else {\n            overlayElement.scaleX = SCALE_X;\n            overlayElement.scaleY = SCALE_Y;\n            overlayElement.on('tick', () => {\n                if (overlayElement.cacheCanvas) {\n                    overlayElement.updateCache();\n                }\n            });\n        }\n        return overlayElement;\n    }\n\n    createNewIndicatorGraphic() {\n        const graphic = this.newGraphic();\n        graphic.width = 640;\n        graphic.height = 360;\n        graphic.x = INITIAL_VIDEO_PARAMS.X;\n        graphic.y = INITIAL_VIDEO_PARAMS.Y;\n        return graphic;\n    }\n\n    drawVideoElement(videoElement: PIXI.Sprite | createjs.Bitmap): any {\n        if (!this.videoContainer) {\n            this.videoContainer = Entry.stage.canvas.getChildAt(2);\n        }\n\n        this.videoContainer.addChild(videoElement);\n        this.tickByEngine();\n    }\n\n    drawOverlayElement(overlayElement: PIXI.Sprite | createjs.Bitmap): any {\n        if (!this.overlayContainer) {\n            this.overlayContainer = Entry.stage.canvas.getChildAt(3);\n        }\n\n        const isAlready = this.overlayContainer.children.some(\n            (child: PIXI.Sprite | createjs.Bitmap) => {\n                child === overlayElement;\n            }\n        );\n        if (!isAlready) {\n            this.overlayContainer.addChild(overlayElement);\n        }\n        this.tickByEngine();\n    }\n\n    drawDetectedGraphic() {\n        if (!this.poseIndicatorGraphic) {\n            this.poseIndicatorGraphic = this.createNewIndicatorGraphic();\n            Entry.stage.canvas.addChildAt(this.poseIndicatorGraphic, 4);\n        }\n        if (!this.faceIndicatorGraphic) {\n            this.faceIndicatorGraphic = this.createNewIndicatorGraphic();\n            Entry.stage.canvas.addChildAt(this.faceIndicatorGraphic, 4);\n        }\n        if (!this.objectIndicatorGraphic) {\n            this.objectIndicatorGraphic = this.createNewIndicatorGraphic();\n            Entry.stage.canvas.addChildAt(this.objectIndicatorGraphic, 4);\n        }\n        this.tickByEngine();\n    }\n\n    turnOffWebcam(canvasVideo: PIXI.Sprite | createjs.Bitmap) {\n        if (!canvasVideo) {\n            return;\n        }\n        const targetContainer = Entry.stage.canvas.getChildAt(2);\n        targetContainer.removeChild(canvasVideo);\n    }\n\n    turnOffOverlay(overlayElement: PIXI.Sprite | createjs.Bitmap) {\n        if (!overlayElement) {\n            return;\n        }\n        const targetContainer = Entry.stage.canvas.getChildAt(3);\n        targetContainer.removeChild(overlayElement);\n    }\n\n    destroyWebcam() {\n        this.videoContainer = null;\n    }\n\n    destroyOverlay() {\n        this.overlayContainer = null;\n    }\n\n    destroy() {\n        this.videoContainer = null;\n        this.overlayContainer = null;\n        this.faceIndicatorGraphic = null;\n        this.poseIndicatorGraphic = null;\n        this.objectIndicatorGraphic = null;\n    }\n\n    hFlipVideoElement(\n        canvasVideo: PIXI.Sprite | createjs.Bitmap | PIXI.Sprite[] | createjs.Bitmap[]\n    ): any {\n        if (Array.isArray(canvasVideo)) {\n            canvasVideo.forEach((video: PIXI.Sprite | createjs.Bitmap) => {\n                if (!video) {\n                    return;\n                }\n                const { x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY } = video;\n                video.setTransform(-x, y, -scaleX, scaleY, rotation, skewX, skewY, regX, regY);\n            });\n        } else {\n            const { x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY } = canvasVideo;\n            canvasVideo.setTransform(-x, y, -scaleX, scaleY, rotation, skewX, skewY, regX, regY);\n        }\n    }\n\n    vFlipVideoElement(\n        canvasVideo: PIXI.Sprite | createjs.Bitmap | PIXI.Sprite[] | createjs.Bitmap[]\n    ): any {\n        if (Array.isArray(canvasVideo)) {\n            canvasVideo.forEach((video: PIXI.Sprite | createjs.Bitmap) => {\n                if (!video) {\n                    return;\n                }\n                const { x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY } = video;\n                video.setTransform(x, -y, scaleX, -scaleY, rotation, skewX, skewY, regX, regY);\n            });\n        } else {\n            const { x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY } = canvasVideo;\n            canvasVideo.setTransform(x, -y, scaleX, -scaleY, rotation, skewX, skewY, regX, regY);\n        }\n    }\n\n    setVideoAlpha(canvasVideo: PIXI.Sprite | createjs.Bitmap, value: number): any {\n        canvasVideo.alpha = (100 - value) / 100;\n    }\n\n    removeAllChildInHandler(handler: PIXI.Graphics | createjs.Graphics) {\n        while (handler.children.length > 0) {\n            const child = handler.getChildAt(0);\n            handler.removeChild(child);\n        }\n    }\n\n    resetHandlers() {\n        if (\n            !this.faceIndicatorGraphic ||\n            !this.poseIndicatorGraphic ||\n            !this.objectIndicatorGraphic\n        ) {\n            return;\n        }\n        if (this.isWebGL) {\n            this.faceIndicatorGraphic.clear();\n            this.poseIndicatorGraphic.clear();\n            this.objectIndicatorGraphic.clear();\n            this.removeAllChildInHandler(this.objectIndicatorGraphic);\n            this.removeAllChildInHandler(this.poseIndicatorGraphic);\n            this.removeAllChildInHandler(this.faceIndicatorGraphic);\n        } else {\n            this.faceIndicatorGraphic.graphics.clear();\n            this.poseIndicatorGraphic.graphics.clear();\n            this.objectIndicatorGraphic.graphics.clear();\n        }\n    }\n\n    async drawHumanPoints(poses: Array<any>, flipStatus: any) {\n        const R = 5;\n        let handler = this.poseIndicatorGraphic;\n        if (this._isWebGL) {\n            while (handler.children.length > 0) {\n                const child = handler.getChildAt(0);\n                handler.removeChild(child);\n            }\n        } else {\n            handler = this.poseIndicatorGraphic.graphics;\n        }\n        handler.clear();\n\n        poses.map((pose: any, index: Number) => {\n            const { x, y } = pose.keypoints[3].position;\n            if (this._isWebGL) {\n                const text = PIXIHelper.text(\n                    `${Lang.Blocks.video_human}-${index + 1}`,\n                    '20px Nanum Gothic',\n                    '',\n                    'middle',\n                    'center'\n                );\n                text.x = x - 20;\n                text.y = y - 20;\n                handler.addChild(text);\n            } else {\n                handler.append({\n                    exec: (ctx: any) => {\n                        ctx.font = '20px Nanum Gothic';\n                        ctx.color = 'blue';\n                        ctx.fillText(`${Lang.Blocks.video_human}-${index + 1}`, x - 20, y - 20);\n                    },\n                });\n            }\n            pose.keypoints.map((item: any) => {\n                const { x, y } = item.position;\n                const recalculatedY = flipStatus.vertical ? INITIAL_VIDEO_PARAMS.HEIGHT - y : y;\n\n                handler.beginFill(0x0000ff);\n                handler.drawCircle(x, recalculatedY, R);\n                handler.endFill();\n            });\n        });\n    }\n\n    async drawHumanSkeletons(adjacents: Array<any>, flipStatus: any) {\n        const coordList: any = [];\n        let handler = this.poseIndicatorGraphic;\n        adjacents.forEach((adjacentList: any) => {\n            adjacentList.forEach((pair: any) => {\n                const start = pair[0].position;\n                const end = pair[1].position;\n                if (flipStatus.vertical) {\n                    start.y = INITIAL_VIDEO_PARAMS.HEIGHT - start.y;\n                    end.y = INITIAL_VIDEO_PARAMS.HEIGHT - end.y;\n                }\n                coordList.push({ start, end });\n            });\n        });\n\n        if (this._isWebGL) {\n            handler.lineStyle(5, 0x0000ff);\n        } else {\n            handler = handler.graphics;\n            handler.setStrokeStyle(8, 'round').beginStroke('blue');\n        }\n        coordList.forEach((coord: any) => {\n            const { start, end } = coord;\n            handler.moveTo(start.x, start.y).lineTo(end.x, end.y);\n        });\n    }\n\n    async drawFaceEdges(faces: any, flipStatus: any) {\n        let handler = this.faceIndicatorGraphic;\n\n        if (this._isWebGL) {\n            handler.clear();\n            while (handler.children.length > 0) {\n                const child = handler.getChildAt(0);\n                handler.removeChild(child);\n            }\n            handler.lineStyle(2, 0xff0000);\n        } else {\n            handler = handler.graphics;\n            handler.clear();\n            handler.setStrokeStyle(2, 'round').beginStroke('red');\n        }\n        faces.forEach((face: { landmarks: { _positions: any[] } }, index: Number) => {\n            const positions = face.landmarks._positions;\n            positions.forEach((item, i) => {\n                if (\n                    i === 0 ||\n                    i === 17 ||\n                    i === 27 ||\n                    i === 31 ||\n                    i === 36 ||\n                    i === 42 ||\n                    i === 48\n                ) {\n                    return;\n                }\n\n                const prev = face.landmarks._positions[i - 1];\n                this.drawEdge(prev, item, handler, flipStatus);\n            });\n            // compensation for missing edges\n            this.drawEdge(positions[42], positions[47], handler, flipStatus);\n            this.drawEdge(positions[41], positions[36], handler, flipStatus);\n            this.drawEdge(positions[60], positions[67], handler, flipStatus);\n            this.drawEdge(positions[0], positions[17], handler, flipStatus);\n            this.drawEdge(positions[16], positions[26], handler, flipStatus);\n            this.drawEdge(positions[27], positions[31], handler, flipStatus);\n            this.drawEdge(positions[27], positions[35], handler, flipStatus);\n            this.drawEdge(positions[30], positions[31], handler, flipStatus);\n            this.drawEdge(positions[30], positions[35], handler, flipStatus);\n\n            const refPoint = positions[57];\n            let x = refPoint._x;\n            let y = refPoint._y;\n\n            const { WIDTH, HEIGHT } = INITIAL_VIDEO_PARAMS;\n            if (flipStatus.horizontal) {\n                x = WIDTH - x;\n            }\n            if (flipStatus.vertical) {\n                y = HEIGHT - y;\n            }\n            if (this._isWebGL) {\n                const text = PIXIHelper.text(\n                    `${Lang.Blocks.video_face}-${index + 1}`,\n                    '20px Nanum Gothic',\n                    '',\n                    'middle',\n                    'center'\n                );\n                text.x = x;\n                text.y = y - 10;\n                handler.addChild(text);\n            } else {\n                handler.append({\n                    exec: (ctx: any) => {\n                        ctx.font = '20px Nanum Gothic';\n                        ctx.color = '#0000ff';\n                        ctx.fillText(`${Lang.Blocks.video_face}-${index + 1}`, x, y - 10);\n                    },\n                });\n            }\n        });\n    }\n\n    drawEdge(\n        pos1: { _x: number; _y: number },\n        pos2: { _x: number; _y: number },\n        handler: PIXI.Graphics | createjs.Graphics,\n        flipStatus: any\n    ) {\n        const { WIDTH, HEIGHT } = INITIAL_VIDEO_PARAMS;\n\n        let { _x, _y } = pos2;\n        let prevX = pos1._x;\n        let prevY = pos1._y;\n        if (flipStatus.horizontal) {\n            _x = WIDTH - _x;\n            prevX = WIDTH - prevX;\n        }\n        if (flipStatus.vertical) {\n            _y = HEIGHT - _y;\n            prevY = HEIGHT - prevY;\n        }\n\n        handler.moveTo(prevX, prevY).lineTo(_x, _y);\n    }\n\n    async drawObjectBox(objects: Array<any>, flipStatus: any) {\n        const objectsList: any = [];\n        objects.forEach((object: any) => {\n            const bbox = object.bbox;\n            const name = object.class\n                ? `${Lang.Blocks.video_object}-${Lang.video_object_params[object.class]}`\n                : '';\n            let x = bbox[0];\n            let y = bbox[1];\n            const width = bbox[2];\n            const height = bbox[3];\n\n            if (flipStatus.horizontal) {\n                x = INITIAL_VIDEO_PARAMS.WIDTH - x - width;\n            }\n            if (flipStatus.vertical) {\n                y = INITIAL_VIDEO_PARAMS.HEIGHT - y - height;\n            }\n            const textpoint = { x: x + 20, y: y + 20 };\n            objectsList.push({ textpoint, name, x, y, width, height });\n        });\n\n        let handler = this.objectIndicatorGraphic;\n\n        if (this._isWebGL) {\n            handler.clear();\n            while (handler.children.length > 0) {\n                const child = handler.getChildAt(0);\n                handler.removeChild(child);\n            }\n            handler.lineStyle(5, 0xff0000);\n            objectsList.forEach((target: any, index: Number) => {\n                const { textpoint, name, x, y, width, height } = target;\n                if (name) {\n                    const text = PIXIHelper.text(\n                        `${name}-${index + 1}`,\n                        '20px Nanum Gothic',\n                        '',\n                        'middle',\n                        'center'\n                    );\n                    text.x = textpoint.x;\n                    text.y = textpoint.y;\n                    handler.addChild(text);\n                }\n\n                handler.drawRect(x, y, width, height);\n            });\n        } else {\n            handler = handler.graphics;\n            handler.clear();\n            objectsList.forEach((target: any, index: Number) => {\n                const { textpoint, name, x, y, width, height } = target;\n\n                if (name) {\n                    handler.append({\n                        exec: (ctx: any) => {\n                            ctx.font = '20px Nanum Gothic';\n                            ctx.fillText(`${name}-${index + 1}`, textpoint.x - 5, textpoint.y + 5);\n                        },\n                    });\n                }\n                handler\n                    .setStrokeStyle(8, 'round')\n                    .beginStroke('red')\n                    .drawRect(x, y, width, height);\n            });\n        }\n    }\n\n    getTransformedBounds(sprite: PIXI.Sprite | any): PIXI.Rectangle | any {\n        if (this._isWebGL) {\n            return sprite.getBounds(false);\n        } else {\n            return sprite.getTransformedBounds();\n        }\n    }\n\n    calcParentBound(obj: any): any {\n        if (this._isWebGL) {\n            return PIXIHelper.getTransformBound(obj);\n        } else {\n            return obj.getTransformedBounds();\n        }\n    }\n\n    newContainer(debugName?: string): PIXI.Container | any {\n        if (this._isWebGL) {\n            return PIXIHelper.container(debugName);\n        } else {\n            return new createjs.Container();\n        }\n    }\n\n    /**\n     * stage wall 생성만을 위한 함수\n     * @param path\n     */\n    newWallTexture(path: string): PIXI.Texture | HTMLImageElement {\n        if (this._isWebGL) {\n            return PIXI.Texture.from(path);\n        } else {\n            const img: HTMLImageElement = new Image();\n            img.src = path;\n            return img;\n        }\n    }\n\n    /**\n     * stage wall 생성만을 위한 함수\n     * @param tex\n     */\n    newWallSprite(tex: any) {\n        if (this._isWebGL) {\n            return new PIXI.Sprite(tex);\n        } else {\n            return new createjs.Bitmap(tex);\n        }\n    }\n\n    newEmptySprite() {\n        if (this._isWebGL) {\n            return PIXIHelper.sprite();\n        } else {\n            return new createjs.Bitmap();\n        }\n    }\n\n    newSpriteWithCallback(url: string, callback?: () => void) {\n        const img = new Image();\n        if (callback) {\n            const handle = () => {\n                img.removeEventListener('load', handle);\n                callback();\n            };\n            img.addEventListener('load', handle);\n        }\n        img.src = url;\n        if (this._isWebGL) {\n            const texture = PIXI.Texture.from(img);\n            return PIXI.Sprite.from(texture);\n        } else {\n            return new createjs.Bitmap(img);\n        }\n    }\n\n    newGraphic() {\n        if (this._isWebGL) {\n            return new PIXI.Graphics();\n        } else {\n            return new createjs.Shape();\n        }\n    }\n\n    newAScaleAdaptor(target: any): any {\n        if (this._isWebGL) {\n            return PIXIScaleAdaptor.factory(target);\n        }\n        //createjs 는 사용하는 코드측에서 분기 처리.\n        return null;\n    }\n}\n\nexport const GEHelper = new _GEHelper();\n\nclass _ColorFilterHelper extends GEHelperBase {\n    hue(value: number) {\n        if (this._isWebGL) {\n            const cmHue = new PIXI.filters.ColorMatrixFilter();\n            // @ts-ignore\n            return cmHue.hue(value);\n        } else {\n            const cmHue = new createjs.ColorMatrix();\n            cmHue.adjustColor(0, 0, 0, value);\n            const hueFilter = new createjs.ColorMatrixFilter(cmHue);\n            return hueFilter;\n        }\n    }\n\n    brightness(value: number) {\n        if (this._isWebGL) {\n            value /= 255;\n        }\n        // pixi 필터에 brightness 가 있지만, createjs 와 matrix 값이 달라 결과가 다르게 보임. 그래서 동일하게 구현함.\n        const matrix = [\n            1,\n            0,\n            0,\n            0,\n            value,\n            0,\n            1,\n            0,\n            0,\n            value,\n            0,\n            0,\n            1,\n            0,\n            value,\n            0,\n            0,\n            0,\n            1,\n            0,\n            0,\n            0,\n            0,\n            0,\n            1,\n        ];\n        return this.newColorMatrixFilter(matrix);\n    }\n\n    /**\n     * @param matrixValue\n     */\n    newColorMatrixFilter(matrixValue: number[]) {\n        if (this._isWebGL) {\n            matrixValue.length = 20; // pixi matrix 는 5 * 4\n            const m = new PIXI.filters.ColorMatrixFilter();\n            m._loadMatrix(matrixValue, false);\n            return m;\n        } else {\n            //createjs matrix 는 5*5\n            const cm = new createjs.ColorMatrix();\n            cm.copy(matrixValue);\n            return new createjs.ColorMatrixFilter(cm);\n        }\n    }\n\n    /**\n     *\n     * @param entity - EntityObject\n     * @param cache\n     */\n    setCache(entity: any, cache: boolean) {\n        if (this._isWebGL) {\n            //do nothing\n        } else {\n            cache ? entity.cache() : entity.object.uncache();\n        }\n    }\n}\n\nclass _TextHelper extends GEHelperBase {\n    setColor(target: PIXI.Text | any, color: string) {\n        if (this._isWebGL) {\n            target.style.fill = color;\n        } else {\n            target.color = color;\n        }\n    }\n\n    /**\n     * @param str\n     * @param font size & fontface - 10pt NanumGothic\n     * @param color css style color - #ffffff\n     * @param textBaseline\n     * @param textAlign\n     * @\n     */\n    newText(\n        str: string,\n        font: string,\n        color: string,\n        textBaseline?: string,\n        textAlign?: string\n    ): PIXI.Text | any {\n        if (this._isWebGL) {\n            return PIXIHelper.text(str, font, color, textBaseline, textAlign);\n        } else {\n            const text = new createjs.Text(str, font, color);\n            textBaseline ? (text.textBaseline = textBaseline) : 0;\n            textAlign ? (text.textAlign = textAlign) : 0;\n            return text;\n        }\n    }\n}\n\nclass _BrushHelper extends GEHelperBase {\n    newBrush() {\n        if (this._isWebGL) {\n            return new PIXIBrushAdaptor();\n        } else {\n            return new createjs.Graphics();\n        }\n    }\n\n    newPaint() {\n        if (this._isWebGL) {\n            return new PIXIPaintAdaptor();\n        } else {\n            return new createjs.Graphics();\n        }\n    }\n\n    newShape(brush: PIXIBrushAdaptor | any) {\n        if (this._isWebGL) {\n            const shape = PIXIHelper.newPIXIGraphics();\n            brush.internalSetShape(shape);\n            return shape;\n        } else {\n            const shape = new createjs.Shape(brush);\n            return shape;\n        }\n    }\n}\n"
  },
  {
    "path": "src/graphicEngine/IGEResManager.ts",
    "content": "import { IRawPicture } from '../class/pixi/atlas/model/IRawPicture';\nimport { ImageLoaderHandler } from '../class/pixi/atlas/loader/AtlasImageLoader';\n\nexport interface IGEResManager {\n    INIT():void;\n    activateScene(sceneID:string):void;\n    removeScene(sceneID:string):void;\n    imageRemoved(reason:string):void;\n    clearProject():void\n\n    /**\n     * textrue( or createjs.Bitmap ) 를 요청하고, spriteNullable 에 할당.\n     * @param spriteNullable\n     * @param sceneID\n     * @param pic\n     * @param callback\n     */\n    reqResource(spriteNullable:PIXI.Sprite|any, sceneID:string, pic:IRawPicture, callback:ImageLoaderHandler):void;\n}"
  },
  {
    "path": "src/log/activity.js",
    "content": "'use strict';\n\nEntry.Activity = function(name, data) {\n    this.name = name;\n    this.timestamp = new Date();\n    var arr = [];\n    if (data !== undefined) {\n        for (var i = 0, len = data.length; i < len; i++) {\n            var datum = data[i];\n            arr.push({\n                key: datum[0],\n                value: datum[1],\n            });\n        }\n    }\n    this.data = arr;\n};\n"
  },
  {
    "path": "src/log/activityReporter.js",
    "content": "'use strict';\n\nEntry.ActivityReporter = function() {\n    this._activities = [];\n};\n\n(function(p) {\n    p.add = function(data) {\n        if (!data || data.length === 0) return;\n        var activity;\n        if (data instanceof Entry.Activity) activity = data;\n        else {\n            var type = data.shift();\n            activity = new Entry.Activity(type, data);\n        }\n\n        this._activities.push(activity);\n    };\n\n    p.clear = function() {\n        this._activities = [];\n    };\n\n    p.get = function() {\n        return this._activities;\n    };\n\n    p.report = function() {};\n})(Entry.ActivityReporter.prototype);\n"
  },
  {
    "path": "src/log/recorder.js",
    "content": "'use strict';\n\nEntry.Recorder = function() {\n    this._recordData = [];\n    Entry.commander.addReporter(this);\n};\n\n(function(p) {\n    p.add = function(data) {\n        var commandType = data[0];\n        if (!commandType) return;\n        var command = Entry.Command[commandType];\n        switch (command.recordable) {\n            case Entry.STATIC.RECORDABLE.SUPPORT:\n                this._recordData.push(data);\n                Entry.toast.warning('Record', Lang.Command[commandType + '']);\n                return;\n            case Entry.STATIC.RECORDABLE.SKIP:\n                return;\n            case Entry.STATIC.RECORDABLE.ABANDON:\n                Entry.toast.alert('지원하지 않음');\n                return;\n        }\n    };\n\n    p.getData = function() {\n        return this._recordData;\n    };\n})(Entry.Recorder.prototype);\n"
  },
  {
    "path": "src/log/state.js",
    "content": "/**\n * @fileoverview State class for undo and redo.\n */\n'use strict';\n\n/**\n * @constructor\n */\nEntry.State = function(type, caller, func, param) {\n    /**\n     * function's caller.\n     * @type {!object}\n     */\n    this.caller = caller;\n    /**\n     * function to recover state.\n     * @type {!function}\n     */\n    this.func = func;\n    /**\n     * parameters for function.\n     * @type {Array}\n     */\n    if (arguments.length > 3)\n        this.params = Array.prototype.slice.call(arguments).slice(3);\n    /**\n     * message for interface.\n     * @type {?String}\n     * */\n    this.message = type;\n    /**\n     * born time\n     * @type {Number}\n     * */\n    this.time = Entry.getUpTime();\n\n    this.isPass = Entry.Command[type] ? Entry.Command[type].isPass : false;\n\n    this.id = Entry.generateHash();\n};\n\n/**\n * generate message for interface.\n */\nEntry.State.prototype.generateMessage = function() {\n\n};\n"
  },
  {
    "path": "src/log/state_manager.js",
    "content": "class EntryStateManager {\n    constructor() {\n        this.undoStack_ = [];\n        this.redoStack_ = [];\n\n        /** prevent add command when undo and redo */\n        this.isRestore = false;\n        this._isRedoing = false;\n        this.isIgnore = false;\n        Entry.addEventListener('cancelLastCommand', (e) => {\n            this.cancelLastCommand();\n        });\n        Entry.addEventListener('saveWorkspace', (e) => {\n            this.addStamp();\n        });\n        Entry.addEventListener('undo', (e) => {\n            this.undo();\n        });\n        Entry.addEventListener('redo', (e) => {\n            this.redo();\n        });\n    }\n\n    generateView(stateManagerView, option) {\n        console.warn('this method is nothing to do. please consider remove logic');\n    }\n\n    addCommand(type, caller, func, params) {\n        if (this.isIgnoring()) {\n            return;\n        }\n        const state = new Entry.State();\n        Entry.State.prototype.constructor.apply(state, Array.prototype.slice.call(arguments));\n\n        if (this.isRestoring()) {\n            this.redoStack_.push(state);\n        } else {\n            this.undoStack_.push(state);\n            if (!this._isRedoing) {\n                this.redoStack_ = [];\n            }\n        }\n        if (Entry.reporter) {\n            Entry.reporter.report(state);\n        }\n        if (Entry.creationChangedEvent) {\n            Entry.creationChangedEvent.notify();\n        }\n        return state;\n    }\n\n    cancelLastCommand() {\n        if (!this.canUndo()) {\n            return;\n        }\n        this.undoStack_.pop();\n        if (Entry.creationChangedEvent) {\n            Entry.creationChangedEvent.notify();\n        }\n    }\n\n    getLastCommand() {\n        return this.undoStack_[this.undoStack_.length - 1];\n    }\n\n    getLastCommandById(id) {\n        const undoStack = this.undoStack_;\n        const len = undoStack.length - 1;\n        for (let i = len; i >= 0; i--) {\n            const state = undoStack[i];\n            if (state.id === id) {\n                return state;\n            }\n        }\n    }\n\n    getLastRedoCommand() {\n        return this.redoStack_[this.redoStack_.length - 1];\n    }\n\n    removeAllPictureCommand() {\n        this.undoStack_ = this.undoStack_.filter(\n            (stack) => !(stack.message >= 400 && stack.message < 500)\n        );\n        this.redoStack_ = this.redoStack_.filter(\n            (stack) => !(stack.message >= 400 && stack.message < 500)\n        );\n    }\n\n    undo(count) {\n        if (!this.canUndo() || this.isRestoring()) {\n            return;\n        }\n        this.addActivity('undo');\n        this.startRestore();\n        let isFirst = true;\n        while (this.undoStack_.length) {\n            const state = this.undoStack_.pop();\n            state.func.apply(state.caller, state.params);\n\n            const command = this.getLastRedoCommand();\n\n            if (isFirst) {\n                command.isPass = false;\n                isFirst = !isFirst;\n            } else {\n                command.isPass = true;\n            }\n\n            if (count) {\n                count--;\n            }\n\n            if (!count && state.isPass !== true) {\n                break;\n            }\n        }\n        this.endRestore();\n        if (Entry.disposeEvent) {\n            Entry.disposeEvent.notify();\n        }\n        if (Entry.creationChangedEvent) {\n            Entry.creationChangedEvent.notify();\n        }\n    }\n\n    redo() {\n        if (!this.canRedo() || this.isRestoring()) {\n            return;\n        }\n\n        this._isRedoing = true;\n        this.addActivity('undo');\n        this.addActivity('redo');\n        let isFirst = true;\n        while (this.redoStack_.length) {\n            const state = this.redoStack_.pop();\n            const ret = state.func.apply(state.caller, state.params);\n\n            if (isFirst) {\n                ret.isPass(false);\n                isFirst = !isFirst;\n            } else {\n                ret.isPass(true);\n            }\n\n            if (state.isPass !== true) {\n                break;\n            }\n        }\n        this._isRedoing = false;\n        if (Entry.creationChangedEvent) {\n            Entry.creationChangedEvent.notify();\n        }\n    }\n\n    updateView() {\n        return;\n        if (this.undoButton && this.redoButton) {\n            if (this.canUndo()) {\n                this.undoButton.addClass('active');\n            } else {\n                this.undoButton.removeClass('active');\n            }\n\n            if (this.canRedo()) {\n                this.redoButton.addClass('active');\n            } else {\n                this.redoButton.removeClass('active');\n            }\n        }\n    }\n\n    startRestore() {\n        this.isRestore = true;\n    }\n\n    endRestore() {\n        this.isRestore = false;\n    }\n\n    isRestoring() {\n        return this.isRestore;\n    }\n\n    startIgnore() {\n        this.isIgnore = true;\n    }\n\n    endIgnore() {\n        this.isIgnore = false;\n    }\n\n    isIgnoring() {\n        return this.isIgnore;\n    }\n\n    canUndo() {\n        return this.undoStack_.length > 0 && Entry.engine.isState('stop');\n    }\n\n    canRedo() {\n        return this.redoStack_.length > 0 && Entry.engine.isState('stop');\n    }\n\n    /**\n     * mark state which one saved\n     */\n    addStamp() {\n        this.stamp = Entry.generateHash();\n        if (this.undoStack_.length) {\n            this.undoStack_[this.undoStack_.length - 1].stamp = this.stamp;\n        }\n    }\n\n    /**\n     * @return {!boolean} return true when project is up-to-date\n     */\n    isSaved() {\n        return (\n            this.undoStack_.length === 0 ||\n            (this.undoStack_[this.undoStack_.length - 1].stamp == this.stamp &&\n                typeof this.stamp == 'string')\n        );\n    }\n\n    /**\n     * @param {String} activityType\n     */\n    addActivity(activityType) {\n        if (Entry.reporter) {\n            Entry.reporter.report(new Entry.State(activityType));\n        }\n    }\n\n    getUndoStack() {\n        return this.undoStack_.slice(0);\n    }\n\n    changeLastCommandType(type) {\n        const cmd = this.getLastCommand();\n        if (cmd) {\n            cmd.message = type;\n        }\n        return cmd;\n    }\n\n    clear() {\n        while (this.undoStack_.length) {\n            this.undoStack_.pop();\n        }\n        while (this.redoStack_.length) {\n            this.redoStack_.pop();\n        }\n\n        if (Entry.creationChangedEvent) {\n            Entry.creationChangedEvent.notify();\n        }\n    }\n}\n\nEntry.StateManager = EntryStateManager;\n"
  },
  {
    "path": "src/model/block_model.js",
    "content": "'use strict';\n\nEntry.BlockModel = class BlockModel {\n    constructor(context) {\n        Entry.Model(this);\n        this.schema = {\n            id: null,\n            x: 0,\n            y: 0,\n            type: null,\n            params: {},\n            statements: {},\n            prev: null,\n            next: null,\n            view: null,\n        };\n    }\n};\n"
  },
  {
    "path": "src/model/block_render_model.js",
    "content": "'use strict';\n\nEntry.BlockRenderModel = class BlockRenderModel {\n    constructor() {\n        this.schema = {\n            id: 0,\n            type: Entry.STATIC.BLOCK_RENDER_MODEL,\n            x: 0,\n            y: 0,\n            width: 0,\n            height: 0,\n            magneting: false,\n        };\n        Entry.Model(this);\n    }\n};\n"
  },
  {
    "path": "src/model/box_model.js",
    "content": "'use strict';\n\nEntry.BoxModel = class BoxModel {\n    constructor() {\n        this.schema = {\n            id: 0,\n            type: Entry.STATIC.BOX_MODEL,\n            x: 0,\n            y: 0,\n            width: 0,\n            height: 0,\n        };\n        Entry.Model(this);\n    }\n};\n"
  },
  {
    "path": "src/model/drag_instance.js",
    "content": "'use strict';\n\nEntry.DragInstance = class DragInstance {\n    constructor(model) {\n        this.schema = {\n            type: Entry.STATIC.DRAG_INSTANCE,\n            startX: 0,\n            startY: 0,\n            offsetX: 0,\n            offsetY: 0,\n            absX: 0,\n            absY: 0,\n            prev: null,\n            height: 0,\n            mode: 0,\n            isNew: false,\n        };\n\n        Entry.Model(this);\n\n        this.set(model);\n    }\n};\n"
  },
  {
    "path": "src/model/thread_model.js",
    "content": "'use strict';\n\nEntry.ThreadModel = class ThreadModel {\n    constructor() {\n        this.schema = {\n            id: 0,\n            type: Entry.STATIC.THREAD_MODEL,\n            x: 0,\n            y: 0,\n            width: 0,\n            minWidth: 0,\n            height: 0,\n        };\n        Entry.Model(this);\n    }\n};\n"
  },
  {
    "path": "src/parser-no/block.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.BlockParser = function(syntax) {\n    this.syntax = syntax;\n\n    this._iterVariableCount = 0;\n    this._iterVariableChunk = ['i', 'j', 'k'];\n};\n\n(function(p) {\n    p.Code = function(code) {\n        if (code instanceof Entry.Thread) return this.Thread(code);\n        if (code instanceof Entry.Block) return this.Block(code);\n\n        var textCode = '',\n            threads = code.getThreads();\n\n        for (var i = 0; i < threads.length; i++) {\n            var thread = threads[i];\n            textCode += this.Thread(thread);\n        }\n\n        return textCode;\n    };\n\n    p.Thread = function(thread) {\n        if (thread instanceof Entry.Block) return this.Block(thread);\n        var code = '',\n            blocks = thread.getBlocks();\n\n        for (var i = 0; i < blocks.length; i++) {\n            var block = blocks[i];\n            code += this.Block(block);\n        }\n        return code;\n    };\n\n    p.Block = function(block) {\n        var syntax = block._schema.syntax;\n        if (!syntax) return '';\n        var syntaxType = syntax[0];\n        return this[syntaxType](block);\n    };\n\n    p.Program = function(block) {\n        return '';\n    };\n\n    p.Scope = function(block) {\n        var syntax = block._schema.syntax.concat();\n        return syntax.splice(1, syntax.length - 1).join('.') + '();\\n';\n    };\n\n    p.BasicFunction = function(block) {\n        var statementCode = this.Thread(block.statements[0]);\n        var code =\n            'function promise() {\\n' + this.indent(statementCode) + '}\\n';\n        return code;\n    };\n\n    p.BasicIteration = function(block) {\n        var iterateNumber = block.params[0];\n        var iterVariable = this.publishIterateVariable();\n        var statementCode = this.Thread(block.statements[0]);\n        this.unpublishIterateVariable();\n        var code =\n            'for (var ' +\n            iterVariable +\n            ' = 0; ' +\n            iterVariable +\n            ' < ' +\n            iterateNumber +\n            '; ' +\n            iterVariable +\n            '++){\\n' +\n            this.indent(statementCode) +\n            '}\\n';\n        return code;\n    };\n\n    p.BasicIf = function(block) {\n        var statementCode = this.Thread(block.statements[0]);\n        var syntax = block._schema.syntax.concat();\n        var code =\n            'if (' + syntax[1] + ') {\\n' + this.indent(statementCode) + '}\\n';\n        return code;\n    };\n\n    p.BasicWhile = function(block) {\n        var statementCode = this.Thread(block.statements[0]);\n        var syntax = block._schema.syntax.concat();\n        var code =\n            'while (' +\n            syntax[1] +\n            ') {\\n' +\n            this.indent(statementCode) +\n            '}\\n';\n        return code;\n    };\n\n    p.indent = function(textCode) {\n        var result = '    ';\n        var indentedCode = textCode.split('\\n');\n        indentedCode.pop();\n        result += indentedCode.join('\\n    ') + '\\n';\n        return result;\n    };\n\n    // iterate variable\n    p.publishIterateVariable = function() {\n        var iterVariable = '';\n        var iterVariableCount = this._iterVariableCount;\n        do {\n            var chunk = this._iterVariableChunk[iterVariableCount % 3];\n            iterVariable = chunk + iterVariable;\n            iterVariableCount = parseInt(iterVariableCount / 3) - 1;\n            if (iterVariableCount === 0)\n                iterVariable = this._iterVariableChunk[0] + iterVariable;\n        } while (iterVariableCount > 0);\n        this._iterVariableCount++;\n        return iterVariable;\n    };\n\n    p.unpublishIterateVariable = function() {\n        if (this._iterVariableCount) this._iterVariableCount--;\n    };\n})(Entry.BlockParser.prototype);\n"
  },
  {
    "path": "src/parser-no/js.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.JSParser = function(syntax) {\n    this.syntax = syntax;\n\n    this.scopeChain = [];\n    this.scope = null;\n};\n\n(function(p) {\n    p.Program = function(node) {\n        var code = [];\n        var block = [];\n        var body = node.body;\n\n        //block statement\n\n        block.push({\n            type: this.syntax.Program,\n        });\n\n        var separatedBlocks = this.initScope(node);\n\n        block = block.concat(this.BlockStatement(node));\n\n        this.unloadScope();\n\n        code.push(block);\n        code = code.concat(separatedBlocks);\n        return code;\n    };\n\n    p.Identifier = function(node, scope) {\n        if (scope) return scope[node.name];\n        else return this.scope[node.name];\n    };\n\n    // Statement\n    p.ExpressionStatement = function(node) {\n        var expression = node.expression;\n        return this[expression.type](expression);\n    };\n\n    p.ForStatement = function(node) {\n        var init = node.init,\n            test = node.test,\n            update = node.update,\n            body = node.body;\n\n        var contents = '';\n\n        var blockType = this.syntax.ForStatement;\n\n        if (!blockType) {\n            body = this[body.type](body);\n\n            var startVal = init.declarations[0].init.value;\n            var test = test;\n            var op = test.operator;\n            var endVal = test.right.value;\n            var updateOp = update.operator;\n\n            var res = 0;\n            if (!(updateOp == '++')) {\n                var temp = startVal;\n                var startVal = endVal;\n                var endVal = temp;\n            }\n\n            switch (op) {\n                case '<':\n                    res = endVal - startVal;\n                    break;\n\n                case '<=':\n                    res = endVal + 1 - startVal;\n                    break;\n\n                case '>':\n                    res = startVal - endVal;\n                    break;\n\n                case '>=':\n                    res = startVal + 1 - endVal;\n                    break;\n            }\n\n            return this.BasicIteration(node, res, body);\n        } else {\n            throw {\n                message: '지원하지 않는 표현식 입니다.',\n                node: node,\n            };\n        }\n    };\n\n    p.BlockStatement = function(node) {\n        var blocks = [];\n        var body = node.body;\n\n        for (var i = 0; i < body.length; i++) {\n            var childNode = body[i];\n\n            var block = this[childNode.type](childNode);\n            if (!block) {\n                continue;\n            } else if (block.type === undefined) {\n                throw {\n                    message: '해당하는 블록이 없습니다.',\n                    node: childNode,\n                };\n            } else if (block) blocks.push(block);\n        }\n\n        return blocks;\n    };\n\n    p.EmptyStatement = function(node) {\n        throw {\n            message: 'empty는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.DebuggerStatement = function(node) {\n        throw {\n            message: 'debugger는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.WithStatement = function(node) {\n        var object = node.object,\n            body = node.body;\n\n        throw {\n            message: 'with는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    //control flow\n    p.ReturnStaement = function(node) {\n        var args = node.arguments;\n\n        throw {\n            message: 'return은 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.LabeledStatement = function(node) {\n        var label = node.label,\n            body = node.body;\n\n        throw {\n            message: 'label은 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.BreakStatement = function(node) {\n        var label = node.label;\n\n        throw {\n            message: 'break는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.ContinueStatement = function(node) {\n        var label = node.label;\n\n        throw {\n            message: 'continue는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.IfStatement = function(node) {\n        var test = node.test,\n            consequent = node.consequent,\n            alternate = node.alternate;\n\n        var blockType = this.syntax.IfStatement;\n        if (!blockType) {\n            return this.BasicIf(node);\n        } else {\n            throw {\n                message: 'if는 지원하지 않는 표현식 입니다.',\n                node: node,\n            };\n        }\n    };\n\n    p.SwitchStatement = function(node) {\n        var discriminant = node.discriminant,\n            cases = node.cases;\n\n        throw {\n            message: 'switch는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.SwitchCase = function(node) {\n        var test = node.test,\n            consequent = node.consequent;\n\n        throw {\n            message: 'switch ~ case는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    //throwstatement\n\n    p.ThrowStatement = function(node) {\n        var args = node.arguments;\n\n        throw {\n            message: 'throw는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.TryStatement = function(node) {\n        var block = node.block,\n            handler = node.handler,\n            finalizer = node.finalizer;\n\n        throw {\n            message: 'try는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.CatchClause = function(node) {\n        var param = node.param,\n            body = node.body;\n\n        throw {\n            message: 'catch는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.WhileStatement = function(node) {\n        var test = node.test,\n            body = node.body;\n        var blockType = this.syntax.WhileStatement;\n        body = this[body.type](body);\n\n        if (!blockType) {\n            return this.BasicWhile(node, body);\n        } else {\n            throw {\n                message: 'while은 지원하지 않는 표현식 입니다.',\n                node: node,\n            };\n        }\n    };\n\n    p.DoWhileStatement = function(node) {\n        var body = node.body,\n            test = node.test;\n\n        throw {\n            message: 'do ~ while은 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.ForInStatement = function(node) {\n        var left = node.left,\n            right = node.right,\n            body = node.body;\n\n        throw {\n            message: 'for ~ in은 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    //Declaration\n\n    p.FunctionDeclaration = function(node) {\n        var id = node.id;\n\n        var blockType = this.syntax.FunctionDeclaration;\n\n        if (!blockType) {\n            return null;\n        } else {\n            throw {\n                message: 'function은 지원하지 않는 표현식 입니다.',\n                node: node,\n            };\n        }\n    };\n\n    p.VariableDeclaration = function(node) {\n        var declaration = node.declarations,\n            kind = node.kind;\n\n        throw {\n            message: 'var은 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    // Expression\n    p.ThisExpression = function(node) {\n        return this.scope.this;\n    };\n\n    p.ArrayExpression = function(node) {\n        var elements = node.elements;\n\n        throw {\n            message: 'array는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.ObjectExpression = function(node) {\n        var property = node.property;\n\n        throw {\n            message: 'object는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.Property = function(node) {\n        var key = node.key,\n            value = node.value,\n            kind = node.kind;\n\n        throw {\n            message: 'init, get, set은 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.FunctionExpression = function(node) {\n        throw {\n            message: 'function은 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n    // unary expression\n\n    p.UnaryExpression = function(node) {\n        var operator = node.operator,\n            prefix = node.prefix,\n            args = node.argument;\n\n        throw {\n            message: operator + '은(는) 지원하지 않는 명령어 입니다.',\n            node: node,\n        };\n    };\n\n    p.UnaryOperator = function() {\n        return ['-', '+', '!', '~', 'typeof', 'void', 'delete'];\n    };\n\n    p.updateOperator = function() {\n        return ['++', '--'];\n    };\n\n    //Binary expression\n    p.BinaryOperator = function() {\n        return [\n            '==',\n            '!=',\n            '===',\n            '!==',\n            '<',\n            '<=',\n            '>',\n            '>=',\n            '<<',\n            '>>',\n            '>>>',\n            '+',\n            '-',\n            '*',\n            '/',\n            '%',\n            ',',\n            '^',\n            '&',\n            'in',\n            'instanceof',\n        ];\n    };\n\n    p.AssignmentExpression = function(node) {\n        var operator = node.operator,\n            left = node.left,\n            right = node.right;\n\n        throw {\n            message: operator + '은(는) 지원하지 않는 명령어 입니다.',\n            node: node,\n        };\n    };\n\n    p.AssignmentOperator = function() {\n        return [\n            '=',\n            '+=',\n            '-=',\n            '*=',\n            '/=',\n            '%=',\n            '<<=',\n            '>>=',\n            '>>>=',\n            ',=',\n            '^=',\n            '&=',\n        ];\n    };\n\n    p.LogicalExpression = function(node) {\n        var operator = node.operator,\n            left = node.left,\n            right = node.right;\n        throw {\n            message: operator + '은(는) 지원하지 않는 명령어 입니다.',\n            node: node,\n        };\n    };\n\n    p.LogicalOperator = function() {\n        return ['||', '&&'];\n    };\n\n    p.MemberExpression = function(node) {\n        var object = node.object,\n            property = node.property,\n            computed = node.computed;\n\n        console.log(object.type);\n        object = this[object.type](object);\n        console.log(object);\n\n        property = this[property.type](property, object);\n\n        if (\n            !(\n                Object(object) === object &&\n                Object.getPrototypeOf(object) === Object.prototype\n            )\n        ) {\n            throw {\n                message: object + '은(는) 잘못된 멤버 변수입니다.',\n                node: node,\n            };\n        }\n\n        var blockType = property;\n        if (!blockType) {\n            throw {\n                message: property + '이(가) 존재하지 않습니다.',\n                node: node,\n            };\n        }\n        return blockType;\n    };\n\n    p.ConditionalExpression = function(node) {\n        var test = node.test,\n            alternate = node.alternate,\n            consequent = node.consequent;\n\n        throw {\n            message: '지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.UpdateExpression = function(node) {\n        var operator = node.operator,\n            args = node.argument,\n            prefix = node.prefix;\n\n        throw {\n            message: operator + '은(는) 지원하지 않는 명렁어 입니다.',\n            node: node,\n        };\n    };\n\n    p.CallExpression = function(node) {\n        var callee = node.callee,\n            args = node.arguments;\n        var blockType = this[callee.type](callee);\n        return {\n            type: blockType,\n        };\n    };\n\n    p.NewExpression = function(node) {\n        throw {\n            message: 'new는 지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    p.SequenceExpression = function(node) {\n        var expressions = node.expressions;\n\n        throw {\n            message: '지원하지 않는 표현식 입니다.',\n            node: node,\n        };\n    };\n\n    // scope method\n    p.initScope = function(node) {\n        if (this.scope === null) {\n            var scoper = function() {};\n            scoper.prototype = this.syntax.Scope;\n            this.scope = new scoper();\n        } else {\n            var scoper = function() {};\n            scoper.prototype = this.scope;\n            this.scope = new scoper();\n        }\n        this.scopeChain.push(this.scope);\n        return this.scanDefinition(node);\n    };\n\n    p.unloadScope = function() {\n        this.scopeChain.pop();\n        if (this.scopeChain.length)\n            this.scope = this.scopeChain[this.scopeChain.length - 1];\n        else this.scope = null;\n    };\n\n    p.scanDefinition = function(node) {\n        var body = node.body;\n        var separatedBlocks = [];\n        for (var i = 0; i < body.length; i++) {\n            var childNode = body[i];\n            if (childNode.type === 'FunctionDeclaration') {\n                this.scope[childNode.id.name] = this.scope.promise;\n                if (this.syntax.BasicFunction) {\n                    var childBody = childNode.body;\n                    separatedBlocks.push([\n                        {\n                            type: this.syntax.BasicFunction,\n                            statements: [this[childBody.type](childBody)],\n                        },\n                    ]);\n                }\n            }\n        }\n        return separatedBlocks;\n    };\n\n    p.BasicFunction = function(node, body) {\n        return null;\n    };\n\n    // custom node parser\n    p.BasicIteration = function(node, iterCount, body) {\n        var blockType = this.syntax.BasicIteration;\n        if (!blockType)\n            throw {\n                message: '지원하지 않는 표현식 입니다.',\n                node: node,\n            };\n        return {\n            params: [iterCount],\n            type: blockType,\n            statements: [body],\n        };\n    };\n\n    p.BasicWhile = function(node, body) {\n        var raw = node.test.raw;\n        if (this.syntax.BasicWhile[raw]) {\n            return {\n                type: this.syntax.BasicWhile[raw],\n                statements: [body],\n            };\n        } else {\n            throw {\n                message: '지원하지 않는 표현식 입니다.',\n                node: node.test,\n            };\n        }\n    };\n\n    p.BasicIf = function(node) {\n        var consequent = node.consequent;\n        consequent = this[consequent.type](consequent);\n        try {\n            var test = '';\n            var operator =\n                node.test.operator === '===' ? '==' : node.test.operator;\n\n            if (\n                node.test.left.type === 'Identifier' &&\n                node.test.right.type === 'Literal'\n            ) {\n                test =\n                    node.test.left.name +\n                    ' ' +\n                    operator +\n                    ' ' +\n                    node.test.right.raw;\n            } else if (\n                node.test.left.type === 'Literal' &&\n                node.test.right.type === 'Identifier'\n            ) {\n                test =\n                    node.test.right.name +\n                    ' ' +\n                    operator +\n                    ' ' +\n                    node.test.left.raw;\n            } else {\n                throw new Error();\n            }\n\n            if (this.syntax.BasicIf[test]) {\n                if (\n                    !Array.isArray(consequent) &&\n                    typeof consequent === 'object'\n                )\n                    consequent = [consequent];\n                return {\n                    type: this.syntax.BasicIf[test],\n                    statements: [consequent],\n                };\n            } else {\n                throw new Error();\n            }\n        } catch (e) {\n            throw {\n                message: '지원하지 않는 표현식 입니다.',\n                node: node.test,\n            };\n        }\n    };\n})(Entry.JSParser.prototype);\n"
  },
  {
    "path": "src/parser-no/parser.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.Parser = function(mode, syntax, cm) {\n    this._mode = mode; // maze ai workspace\n    this.syntax = {};\n    this.codeMirror = cm;\n    this._lang = syntax || 'js';\n    this.availableCode = [];\n\n    if (mode === 'maze') {\n        this._stageId = Number(Ntry.configManager.getConfig('stageId'));\n        if (typeof NtryData == 'object') {\n            var configCode = NtryData.config[this._stageId].availableCode;\n            var playerCode = NtryData.player[this._stageId].code;\n            this.setAvailableCode(configCode, playerCode);\n        }\n    }\n    this.mappingSyntax(mode);\n\n    switch (this._lang) {\n        case 'js':\n            this._parser = new Entry.JSParser(this.syntax);\n\n            var syntax = this.syntax;\n\n            var assistScope = {};\n\n            for (var key in syntax.Scope) {\n                assistScope[key + '();\\n'] = syntax.Scope[key];\n            }\n\n            if ('BasicIf' in syntax) {\n                assistScope['front'] = 'BasicIf';\n            }\n\n            CodeMirror.commands.javascriptComplete = function(cm) {\n                CodeMirror.showHint(cm, null, { globalScope: assistScope });\n            };\n\n            cm.on('keyup', function(cm, event) {\n                if (\n                    !cm.state.completionActive &&\n                    (event.keyCode >= 65 && event.keyCode <= 95)\n                ) {\n                    CodeMirror.showHint(cm, null, {\n                        completeSingle: false,\n                        globalScope: assistScope,\n                    });\n                }\n            });\n\n            break;\n        case 'block':\n            this._parser = new Entry.BlockParser(this.syntax);\n            break;\n    }\n};\n\n(function(p) {\n    p.parse = function(code) {\n        var result = null;\n\n        switch (this._lang) {\n            case 'js':\n                try {\n                    var astTree = acorn.parse(code);\n                    result = this._parser.Program(astTree);\n                } catch (error) {\n                    if (this.codeMirror) {\n                        var annotation;\n                        if (error instanceof SyntaxError) {\n                            annotation = {\n                                from: {\n                                    line: error.loc.line - 1,\n                                    ch: error.loc.column - 2,\n                                },\n                                to: {\n                                    line: error.loc.line - 1,\n                                    ch: error.loc.column + 1,\n                                },\n                            };\n                            error.message = '문법 오류입니다.';\n                        } else {\n                            annotation = this.getLineNumber(\n                                error.node.start,\n                                error.node.end\n                            );\n                            annotation.message = error.message;\n                            annotation.severity = 'error';\n                            this.codeMirror.markText(\n                                annotation.from,\n                                annotation.to,\n                                {\n                                    className: 'CodeMirror-lint-mark-error',\n                                    __annotation: annotation,\n                                    clearOnEnter: true,\n                                }\n                            );\n                        }\n\n                        Entry.toast.alert('Error', error.message);\n                    }\n                    result = [];\n                }\n                break;\n            case 'block':\n                var textCode = this._parser.Code(code);\n                var textArr = textCode.match(/(.*{.*[\\S|\\s]+?}|.+)/g);\n                if (Array.isArray(textArr)) {\n                    result = textArr.reduce(function(prev, current, index) {\n                        var temp = '';\n\n                        if (index === 1) {\n                            prev = prev + '\\n';\n                        }\n                        if (current.indexOf('function') > -1) {\n                            temp = current + prev;\n                        } else {\n                            temp = prev + current;\n                        }\n\n                        return temp + '\\n';\n                    });\n                } else {\n                    result = '';\n                }\n\n                break;\n        }\n\n        return result;\n    };\n\n    p.getLineNumber = function(start, end) {\n        var value = this.codeMirror.getValue();\n        var lines = {\n            from: {},\n            to: {},\n        };\n\n        var startline = value.substring(0, start).split(/\\n/gi);\n        lines.from.line = startline.length - 1;\n        lines.from.ch = startline[startline.length - 1].length;\n\n        var endline = value.substring(0, end).split(/\\n/gi);\n        lines.to.line = endline.length - 1;\n        lines.to.ch = endline[endline.length - 1].length;\n\n        return lines;\n    };\n\n    p.mappingSyntax = function(mode) {\n        var types = Object.keys(Entry.block);\n\n        for (var i = 0; i < types.length; i++) {\n            var type = types[i];\n            var block = Entry.block[type];\n            if (block.mode === mode && this.availableCode.indexOf(type) > -1) {\n                var syntaxArray = block.syntax;\n                if (!syntaxArray) continue;\n                var syntax = this.syntax;\n                for (var j = 0; j < syntaxArray.length; j++) {\n                    var key = syntaxArray[j];\n                    if (\n                        j === syntaxArray.length - 2 &&\n                        typeof syntaxArray[j + 1] === 'function'\n                    ) {\n                        syntax[key] = syntaxArray[j + 1];\n                        break;\n                    }\n                    if (!syntax[key]) {\n                        syntax[key] = {};\n                    }\n                    if (j === syntaxArray.length - 1) {\n                        syntax[key] = type;\n                    } else {\n                        syntax = syntax[key];\n                    }\n                }\n            }\n        }\n    };\n\n    p.setAvailableCode = function(configCode, playerCode) {\n        var availableList = [];\n        configCode.forEach(function(items, i) {\n            items.forEach(function(item, i) {\n                availableList.push(item.type);\n            });\n        });\n\n        if (playerCode instanceof Entry.Code) {\n            var blocks = playerCode.getBlockList();\n            blocks.forEach(function(item) {\n                if (\n                    item.type !== NtryData.START &&\n                    availableList.indexOf(item.type) === -1\n                )\n                    availableList.push(item.type);\n            });\n        } else {\n            playerCode.forEach(function(items, i) {\n                items.forEach(function(item, i) {\n                    if (\n                        item.type !== NtryData.START &&\n                        availableList.indexOf(item.type) === -1\n                    ) {\n                        availableList.push(item.type);\n                    }\n                });\n            });\n        }\n\n        this.availableCode = this.availableCode.concat(availableList);\n    };\n})(Entry.Parser.prototype);\n"
  },
  {
    "path": "src/playground/block.js",
    "content": "'use strict';\n\nEntry.Block = class Block {\n    schema = {\n        id: null,\n        x: 0,\n        y: 0,\n        type: null,\n        params: [],\n        statements: [],\n        view: null,\n        thread: null,\n        movable: null,\n        deletable: Entry.Block.DELETABLE_TRUE,\n        emphasized: false,\n        readOnly: null,\n        copyable: true,\n        assemble: true,\n        events: {},\n        extensions: [],\n    };\n\n    constructor(block, thread) {\n        const that = this;\n        Entry.Model(this, false);\n        this._schema = null;\n        this.defaultType = block.defaultType;\n\n        if (block._backupParams) {\n            this._backupParams = block._backupParams;\n        }\n\n        this.setThread(thread);\n        this.load(block);\n\n        const category = block.category;\n        if (category) {\n            this.category = category;\n            const entryBlock = Entry.block[this.type];\n            if (entryBlock) {\n                entryBlock.isFor = [`category_${category}`];\n            }\n        }\n\n        const code = this.getCode();\n\n        if (block.display !== undefined) {\n            this.display = block.display;\n        }\n\n        code.registerBlock(this);\n        if (code.object) {\n            (this.events.dataAdd || []).forEach((fn) => {\n                if (_.isFunction(fn)) {\n                    fn(that);\n                }\n            });\n        }\n\n        const board = code.board;\n        if (\n            Entry.getMainWS() &&\n            Entry.isTextMode &&\n            (!board || (board && board.constructor !== Entry.BlockMenu))\n        ) {\n            (this.events.viewAdd || []).forEach((fn) => {\n                if (_.isFunction(fn)) {\n                    fn.apply(that, [that]);\n                }\n            });\n        }\n\n        if (block.comment) {\n            this._comment = block.comment;\n        }\n    }\n\n    get comment() {\n        return this._comment;\n    }\n\n    load(block) {\n        if (!block.id) {\n            block.id = Entry.Utils.generateId();\n        }\n\n        this.set(block);\n        this.loadSchema();\n    }\n\n    changeSchema(diff, changeData) {\n        let params = [];\n\n        if (changeData) {\n            if (changeData.isRestore) {\n                params = this._backupParams || [];\n                delete this._backupParams;\n            } else {\n                switch (changeData.type) {\n                    case 'noChange':\n                        params = this.params;\n                        break;\n                    case 'cut': {\n                        const pos = changeData.pos;\n                        this.params.splice(pos);\n                        params = this.params;\n                        break;\n                    }\n                    case 'insert': {\n                        const startPos = changeData.startPos;\n                        const endPos = changeData.endPos;\n                        const schemaParams = Entry.block[this.type].params;\n                        params = new Array(schemaParams.length);\n\n                        for (let i = 0; i < startPos; i++) {\n                            params[i] = this.params[i];\n                        }\n\n                        const adjust = endPos - startPos + 1;\n                        for (let i = endPos + 1; i < schemaParams.length; i++) {\n                            params[i] = this.params[i - adjust];\n                        }\n                        break;\n                    }\n                }\n            }\n        }\n\n        params.forEach((p) => {\n            if (p instanceof Entry.Block) {\n                p.destroyView();\n            }\n        });\n\n        this.set({ params });\n\n        this.loadSchema();\n        this.view && this.view.changeType();\n    }\n\n    getSchema() {\n        // for lazy loading\n        if (!this._schema) {\n            this.loadSchema();\n        }\n        return this._schema;\n    }\n\n    loadSchema() {\n        const that = this;\n        this._schema = Entry.block[this.type];\n\n        if (!this._schema) {\n            return;\n        }\n\n        const { changeEvent, paramsBackupEvent, destroyParamsBackupEvent } = this._schema;\n\n        if (!this._schemaChangeEvent && changeEvent) {\n            this._schemaChangeEvent = changeEvent.attach(this, this.changeSchema);\n        }\n\n        if (!this._paramsBackupEvent && paramsBackupEvent) {\n            this._paramsBackupEvent = paramsBackupEvent.attach(this, this.paramsBackup);\n        }\n\n        if (!this._destroyParamsBackupEvent && destroyParamsBackupEvent) {\n            this._destroyParamsBackupEvent = destroyParamsBackupEvent.attach(\n                this,\n                this.destroyParamsBackup\n            );\n        }\n\n        const events = this._schema.events;\n        if (events) {\n            for (const key in events) {\n                if (!this.events[key]) {\n                    this.events[key] = [];\n                }\n                const funcs = events[key];\n                for (let i = 0; i < funcs.length; i++) {\n                    const func = funcs[i];\n                    if (!func) {\n                        continue;\n                    }\n                    if (this.events[key].indexOf(func) < 0) {\n                        this.events[key].push(func);\n                    }\n                }\n            }\n        }\n\n        if (this._schema.event) {\n            this.thread.registerEvent(this, this._schema.event);\n        }\n        const thisParams = this.params;\n\n        const params = this._schema.params;\n        for (let i = 0; params && i < params.length; i++) {\n            let value =\n                thisParams[i] === undefined || thisParams[i] === null\n                    ? params[i].value\n                    : thisParams[i];\n\n            const paramInjected = thisParams[i] || i < thisParams.length;\n\n            if (value && (params[i].type === 'Output' || params[i].type === 'Block')) {\n                if (typeof value !== 'object') {\n                    value = {\n                        type: 'number',\n                        params: [value],\n                    };\n                }\n                value = new Entry.Block(value, this.thread);\n            }\n\n            if (paramInjected) {\n                thisParams.splice(i, 1, value);\n            } else {\n                thisParams.push(value);\n            }\n        }\n\n        const statements = this._schema.statements || [];\n        for (let i = 0; i < statements.length; i++) {\n            if (!(this.statements[i] instanceof Entry.Thread)) {\n                this.statements.splice(\n                    i,\n                    1,\n                    new Entry.Thread(this.statements[i], that.getCode(), this)\n                );\n            }\n        }\n\n        return true;\n    }\n\n    changeType(type) {\n        const _destroyFunc = _.partial(_.result, _, 'destroy');\n\n        _destroyFunc(this._schemaChangeEvent);\n        _destroyFunc(this._backupEvent);\n        _destroyFunc(this._destroyBackupEvent);\n\n        this.set({ type });\n        this.loadSchema();\n        if (this.view) {\n            this.view.changeType(type);\n        }\n    }\n\n    setThread(thread) {\n        this.set({ thread });\n    }\n\n    getThread() {\n        return this.thread;\n    }\n\n    getStatements() {\n        return this.statements[0];\n    }\n\n    insertAfter(blocks) {\n        this.thread.insertByBlock(this, blocks);\n    }\n\n    _updatePos() {\n        if (!this.view) {\n            return;\n        }\n        this.set({\n            x: this.view.x,\n            y: this.view.y,\n        });\n    }\n\n    moveTo(x, y) {\n        if (this.view) {\n            this.view.moveTo(x, y);\n        }\n        this._updatePos();\n        this.getCode().changeEvent.notify();\n    }\n\n    createView(board, mode) {\n        board = board || this.getCode().view.board;\n        if (!this.view) {\n            this.set({\n                view: new Entry.BlockView(this, board, mode),\n            });\n            this._updatePos();\n        }\n        if (this.comment) {\n            const comment = this.comment;\n            if (comment instanceof Entry.Comment) {\n                if (!comment.svgGroup) {\n                    comment.createComment(board, comment.toJSON());\n                }\n            } else {\n                this.connectComment(new Entry.Comment(comment, board, this));\n            }\n        }\n    }\n\n    destroyView() {\n        _.result(this.view, 'destroy');\n        this.comment && this.comment.destroyView();\n    }\n\n    clone(thread) {\n        return new Entry.Block(this.toJSON(true), thread);\n    }\n\n    toJSON(isNew, excludeData = [], option = {}) {\n        const jsonBlackList = ['view', 'thread', 'events'];\n        const json = this._toJSON();\n        const view = this.view;\n\n        if (isNew) {\n            jsonBlackList.push('id');\n        }\n\n        json.params = json.params.map((p, i) => {\n            if (p instanceof Entry.Block) {\n                return p.toJSON(isNew, excludeData, option);\n            } else if (\n                option.captureDynamic &&\n                view.getParam(i) instanceof Entry.FieldDropdownDynamic\n            ) {\n                return view.getParam(i).getTextValue();\n            } else {\n                return p;\n            }\n        });\n\n        const params = [isNew, undefined, excludeData, option];\n        json.statements = json.statements.map((s) => {\n            return s.toJSON(...params);\n        });\n\n        if (this._backupParams) {\n            json._backupParams = this._backupParams.map(function (p) {\n                if (p instanceof Entry.Block) {\n                    return p.toJSON();\n                } else {\n                    return p;\n                }\n            });\n        }\n\n        if (this._comment) {\n            let comment = this._comment;\n            if (this._comment instanceof Entry.Comment) {\n                comment = this._comment.toJSON();\n                delete comment.id;\n            }\n            json.comment = comment;\n        }\n\n        return Object.assign(\n            _.omit(json, [...jsonBlackList, ...excludeData]),\n            _.pick(this, ['x', 'y', 'movable', 'deletable', 'emphasized', 'readOnly'])\n        );\n    }\n\n    destroy(animate, next, isNotForce) {\n        if (isNotForce && !this.isDeletable()) {\n            return;\n        }\n\n        this.comment && this.comment.destroy && this.comment.destroy();\n\n        const blockType = this.getBlockType();\n\n        if (blockType === 'output' && !next) {\n            const prevOutput = this.getPrevOutputBlock();\n            const nextOutput = this.getOutputBlock();\n\n            if (prevOutput) {\n                this.separate(1);\n\n                if (nextOutput) {\n                    nextOutput.separate();\n                    nextOutput.doInsert(prevOutput.view._contents[1]);\n                }\n            } else if (nextOutput) {\n                _.result(nextOutput.view, '_toGlobalCoordinate');\n                nextOutput.doInsert(this.getThread());\n            }\n        }\n\n        const that = this;\n        const params = this.params || [];\n        for (let i = 0; i < params.length; i++) {\n            const param = params[i];\n            if (param instanceof Entry.Block) {\n                param.doNotSplice = !(param.thread instanceof Entry.FieldOutput);\n                param.destroy(animate);\n            }\n        }\n\n        const statements = this.statements || [];\n        for (let i = 0; i < statements.length; i++) {\n            statements[i].destroy(animate);\n        }\n\n        const code = this.getCode();\n\n        code.unregisterBlock(this);\n\n        const thread = this.getThread();\n        if (this._schema && this._schema.event) {\n            thread.unregisterEvent(this, this._schema.event);\n        }\n\n        if (blockType === 'basic') {\n            const prevBlock = this.getPrevBlock();\n            const nextBlock = this.getNextBlock();\n            if (nextBlock) {\n                if (next) {\n                    nextBlock.destroy(animate, next);\n                } else {\n                    const nextBlockView = nextBlock.view;\n                    if (!prevBlock) {\n                        if (thread.view) {\n                            const parent = thread.view.getParent();\n                            const pConstructor = parent.constructor;\n                            if (pConstructor === Entry.FieldStatement) {\n                                nextBlockView && nextBlockView.bindPrev(parent);\n                                parent.insertTopBlock(nextBlock);\n                            } else if (pConstructor === Entry.FieldStatement) {\n                                nextBlock.replace(parent._valueBlock);\n                            } else {\n                                nextBlockView && nextBlockView._toGlobalCoordinate();\n                            }\n                        }\n                    } else {\n                        nextBlockView && nextBlockView.bindPrev(prevBlock, true);\n                    }\n                }\n            }\n        }\n\n        const notSpliced = this.doNotSplice;\n        if (!this.doNotSplice && thread.spliceBlock) {\n            thread.spliceBlock(this);\n        } else {\n            delete this.doNotSplice;\n        }\n\n        this.view && this.view.destroy(animate);\n\n        const _destroyFunc = _.partial(_.result, _, 'destroy');\n\n        _destroyFunc(this._schemaChangeEvent);\n        _destroyFunc(this._paramsBackupEvent);\n        _destroyFunc(this._destroyParamsBackupEvent);\n\n        let events = [];\n        if (code.object) {\n            events = events.concat(this.events.dataDestroy || []);\n        }\n\n        const board = this.getCode().board;\n        if (\n            Entry.getMainWS() &&\n            Entry.isTextMode &&\n            (!board || (board && board.constructor !== Entry.BlockMenu))\n        ) {\n            events = events.concat(this.events.viewDestroy || []);\n        }\n\n        events.forEach((fn) => {\n            if (_.isFunction(fn)) {\n                fn.apply(that, [that, notSpliced]);\n            }\n        });\n    }\n\n    getView() {\n        return this.view;\n    }\n\n    setMovable(movable) {\n        if (this.movable == movable) {\n            return;\n        }\n        this.set({ movable });\n    }\n\n    setCopyable(copyable) {\n        if (this.copyable == copyable) {\n            return;\n        }\n        this.set({ copyable });\n    }\n\n    isMovable() {\n        return this.movable;\n    }\n\n    isCopyable() {\n        return this.copyable;\n    }\n\n    setDeletable(deletable) {\n        if (this.deletable == deletable) {\n            return;\n        }\n        this.set({ deletable });\n    }\n\n    isDeletable() {\n        const deletable = this.deletable;\n        return deletable === Entry.Block.DELETABLE_TRUE || deletable === true;\n    }\n\n    isReadOnly() {\n        return this.readOnly;\n    }\n\n    isCommentable() {\n        const exclusion = ['basic_string_field', 'basic_boolean_field', 'basic_param'];\n        const skeleton = this._schema && this._schema.skeleton;\n        return !exclusion.includes(skeleton);\n    }\n\n    hasComment() {\n        return '_comment' in this;\n    }\n\n    getCode() {\n        return this.thread.getCode();\n    }\n\n    // command func\n    doAdd() {\n        this.getCode().changeEvent.notify();\n    }\n\n    doMove() {\n        this._updatePos();\n        this.getCode().changeEvent.notify();\n    }\n\n    doInsert(targetBlock) {\n        if (this.getBlockType() === 'basic') {\n            this.insert(targetBlock);\n        } else {\n            this.replace(targetBlock);\n        }\n    }\n\n    doDestroy(animate) {\n        this.destroy(animate);\n        if (this.thread && this.thread.updateValueBlock) {\n            this.thread.updateValueBlock();\n        }\n        this.getCode().changeEvent.notify();\n        return this;\n    }\n\n    doDestroyBelow(animate) {\n        this.destroy(animate, true);\n        this.getCode().changeEvent.notify();\n        return this;\n    }\n\n    copy() {\n        const thread = this.getThread();\n        const cloned = [];\n        if (thread instanceof Entry.Thread) {\n            const index = thread.getBlocks().indexOf(this);\n            const json = thread.toJSON(true, index);\n            for (let i = 0; i < json.length; i++) {\n                cloned.push(json[i]);\n            }\n        } else {\n            cloned.push(this.toJSON(true));\n        }\n\n        const { x, y } = this.view.getAbsoluteCoordinate();\n        const block = cloned[0];\n        block.x = x + 15;\n        block.y = y + 15;\n        block.id = Entry.Utils.generateId();\n\n        return cloned;\n    }\n\n    copyToClipboard() {\n        Entry.clipboard = this.copy();\n    }\n\n    separate(count, index) {\n        this.thread.separate(this, count, index);\n        this._updatePos();\n        this.getCode().changeEvent.notify();\n    }\n\n    doSeparate = this.separate;\n\n    insert(targetBlock) {\n        const blocks = this.thread.cut(this);\n        if (targetBlock instanceof Entry.Thread) {\n            targetBlock.insertByBlock(null, blocks);\n        } else {\n            targetBlock.insertAfter(blocks);\n        }\n        this._updatePos();\n        this.getCode().changeEvent.notify();\n    }\n\n    replace(targetBlock) {\n        if (!targetBlock) {\n            console.error('replace error: target not exist');\n            return;\n        }\n        this.thread.cut(this);\n        targetBlock.getThread().replace(this);\n        this.getCode().changeEvent.notify();\n    }\n\n    getPrevBlock() {\n        return this.thread.getPrevBlock(this);\n    }\n\n    getNextBlock() {\n        return this.thread.getNextBlock(this) || null;\n    }\n\n    getFirstBlock() {\n        return this.thread.getFirstBlock();\n    }\n\n    getLastBlock() {\n        return this.thread.getLastBlock();\n    }\n\n    getPrevOutputBlock() {\n        const thread = this.thread;\n        if (thread instanceof Entry.FieldOutput) {\n            return thread._block;\n        }\n        return null;\n    }\n\n    getOutputBlock() {\n        const params = this._schema.params;\n        for (let i = 0; params && i < params.length; i++) {\n            const paramDef = params[i];\n            if (paramDef.type === 'Output') {\n                return this.params[i];\n            }\n        }\n        return null;\n    }\n\n    getTerminateOutputBlock() {\n        let block = this;\n        while (true) {\n            const outputBlock = block.getOutputBlock();\n            if (!outputBlock) {\n                return block;\n            }\n            block = outputBlock;\n        }\n    }\n\n    getOutputBlockCount(count = 0) {\n        const outputBlock = this.getOutputBlock();\n        if (outputBlock) {\n            return outputBlock.getOutputBlockCount(count + 1);\n        } else {\n            return count;\n        }\n    }\n\n    getBlockType() {\n        if (!this.view) {\n            return null;\n        }\n        const skeleton = Entry.skeleton[this._schema.skeleton];\n\n        if (!skeleton.magnets) {\n            return null;\n        }\n\n        const magnet = skeleton.magnets(this.view);\n        if (magnet.next || magnet.previous) {\n            return 'basic';\n        } else if (magnet.boolean || magnet.string) {\n            return 'field';\n        } else if (magnet.output || magnet.param) {\n            return 'output';\n        } else {\n            return null;\n        }\n    }\n\n    indexOfStatements(statement) {\n        return this.statements.indexOf(statement);\n    }\n\n    pointer(pointer = []) {\n        return this.thread.pointer(pointer, this);\n    }\n\n    targetPointer() {\n        const pointer = this.thread.pointer([], this);\n        if (pointer.length === 4 && pointer[3] === 0) {\n            pointer.pop();\n        } else if (pointer[pointer.length - 2] > -1) {\n            if (pointer[pointer.length - 1] === 0) {\n                pointer.pop();\n            } else {\n                pointer[pointer.length - 1] = pointer[pointer.length - 1] - 1;\n            }\n        }\n        return pointer;\n    }\n\n    getDataByPointer(pointer) {\n        pointer = pointer.concat();\n        const data = this.params[pointer.shift()];\n        if (pointer.length) {\n            if (data.getDataByPointer) {\n                return data.getDataByPointer(pointer);\n            } else {\n                return null;\n            }\n        } else {\n            return data;\n        }\n    }\n\n    getBlockList(excludePrimitive, type) {\n        const blocks = [];\n        const currentType = type || this.type;\n\n        if (!this._schema && !this.loadSchema()) {\n            return blocks;\n        }\n\n        if (excludePrimitive && this._schema.isPrimitive) {\n            return blocks;\n        }\n\n        currentType === this.type && blocks.push(this);\n\n        return [...this.params, ...this.statements].reduce((blocks, value) => {\n            const constructor = value && value.constructor;\n            if (constructor !== Entry.Block && constructor !== Entry.Thread) {\n                return blocks;\n            }\n\n            return blocks.concat(value.getBlockList(excludePrimitive, type));\n        }, blocks);\n    }\n\n    stringify(excludeData) {\n        return JSON.stringify(this.toJSON(false, excludeData));\n    }\n\n    isInOrigin() {\n        return this.x === 0 && this.y === 0;\n    }\n\n    isSameParamWith(target) {\n        if (target.type.substr(0, 8) === 'wildcard' || this.type.substr(0, 8) === 'wildcard') {\n            return true;\n        }\n\n        const targetType = target.type;\n        const thisType = this.type;\n\n        if (\n            (targetType === 'number' && thisType === 'positive_number') ||\n            (targetType === 'number' && thisType === 'negative_number') ||\n            (targetType === 'angle' && thisType === 'text') ||\n            (targetType === 'text' && thisType === 'angle')\n        ) {\n        } else if (targetType !== thisType) {\n            return false;\n        }\n        for (let i = 0; i < this.params.length; i++) {\n            const param = this.params[i];\n            if (param instanceof Entry.Block) {\n                if (!param.isSameParamWith(target.params[i])) {\n                    return false;\n                }\n            } else {\n                let l = this.params[i];\n                let r = target.params[i];\n                //entry-js로 변경되며서 null로 오던 것이 undefined로 와서 맞춰 줌.\n                if (l === undefined) l = null;\n                l = typeof l === 'number' ? `${l}` : l;\n                r = typeof r === 'number' ? `${r}` : r;\n                if (l === 'positive') {\n                    return r > 0;\n                } else if (l === 'negative') {\n                    return r < 0;\n                } else if (l !== r) {\n                    return false;\n                }\n            }\n        }\n        return true;\n    }\n\n    paramsBackup() {\n        //do not backup params for blockMenu block\n        if (_.result(this.view, 'isInBlockMenu')) {\n            return;\n        }\n\n        this._backupParams = this.params.slice();\n    }\n\n    destroyParamsBackup() {\n        this._backupParams = null;\n    }\n\n    getDom(query = []) {\n        if (_.isEmpty(query)) {\n            return this.view.svgGroup;\n        }\n\n        query = [...query];\n\n        const key = query.shift();\n        if (key === 'magnet') {\n            return this.view.getMagnet(query);\n        }\n    }\n\n    getParam(index) {\n        return this.params[index];\n    }\n\n    isParamBlockType() {\n        return /^(basic_string_field|basic_boolean_field)$/.test(this._schema.skeleton);\n    }\n\n    getFuncId() {\n        const ret = /func_(.*)/.exec(this.type);\n        if (!ret) {\n            return;\n        }\n        return ret[1];\n    }\n\n    getRootBlock() {\n        let block = this;\n\n        while (block) {\n            const thread = block.getThread();\n            const parent = thread.parent;\n\n            if (!parent) {\n                //field block\n                block = thread._block;\n            } else if (parent instanceof Entry.Code) {\n                //thread\n                block = thread.getFirstBlock();\n                break;\n            } else if (parent instanceof Entry.Block) {\n                //statement\n                block = thread.parent;\n            } else if (parent instanceof Entry.FieldBlock) {\n                break;\n            } else {\n                block = undefined;\n            }\n        }\n\n        return block;\n    }\n\n    connectComment(comment) {\n        this._comment = comment;\n    }\n\n    disconnectComment() {\n        delete this._comment;\n    }\n\n    getCommentValue() {\n        return this._comment && this._comment.value;\n    }\n};\n\nEntry.Block.MAGNET_RANGE = 10;\nEntry.Block.MAGNET_OFFSET = 0.4;\n\nEntry.Block.DELETABLE_TRUE = 1;\nEntry.Block.DELETABLE_FALSE = 2;\nEntry.Block.DELETABLE_FALSE_LIGHTEN = 3;\n"
  },
  {
    "path": "src/playground/block_entry.js",
    "content": "'use strict';\n\nimport DataTable from '../class/DataTable';\nconst { getStateOptions, getCityOptions, locationData } = require('../util/location');\n\nif (typeof global.Entry !== 'object') {\n    global.Entry = {};\n}\n\nif (typeof exports === 'object') {\n    /* IGNORE_WEBPACK:START */\n    const Lang = require('../../extern/lang/ko.js').Lang;\n    global.Lang = Lang;\n    /* IGNORE_WEBPACK:END */\n    if (typeof EntryStatic !== 'object') {\n        global.EntryStatic = {};\n    }\n}\n\nif (!Entry.block) {\n    Entry.block = {};\n}\n\nfunction getConverters() {\n    const c = {};\n    c.keyboardCode = function (key, value) {\n        let code;\n\n        if (key) {\n            code = key.toUpperCase();\n        }\n\n        const map = {\n            32: 'space',\n            13: 'enter',\n            38: 'up',\n            37: 'left',\n            39: 'right',\n            40: 'down',\n        };\n\n        code = map[value] || code || value;\n        if (!Entry.Utils.isNumber(code)) {\n            return code;\n        } else {\n            return '\"()\"'.replace('\"()\"', code);\n        }\n    };\n\n    c.returnStringKey = function (key, value) {\n        if ((!value && typeof value !== 'number') || value === 'null') {\n            return 'None';\n        }\n        key = String(key);\n        if (value === 'mouse') {\n            key = 'mouse';\n        }\n\n        const name = Entry.TextCodingUtil.dropdownDynamicIdToNameConvertor(value, this.menuName);\n        if (name) {\n            key = name;\n        }\n        if (this.codeMap) {\n            var codeMap = eval(this.codeMap);\n        }\n        const codeMapKey = value;\n        if (codeMap) {\n            const codeMapValue = codeMap[codeMapKey];\n            if (codeMapValue) {\n                key = codeMapValue;\n            }\n        }\n\n        key = key.replace(/\\\"/gi, '');\n        return '\"()\"'.replace('()', key);\n    };\n\n    c.returnRawStringKey = function (key, value) {\n        if ((!value && typeof value !== 'number') || value === 'null') {\n            return 'None';\n        }\n        key = String(key);\n        if (value === 'mouse') {\n            key = value;\n        }\n        const name = Entry.TextCodingUtil.dropdownDynamicIdToNameConvertor(value, this.menuName);\n        if (name) {\n            key = name;\n        }\n        key = key.replace(/\\\"/gi, '');\n        return '\"()\"'.replace('\"()\"', key);\n    };\n\n    c.returnStringValue = function (key, value) {\n        if ((!value && typeof value !== 'number') || value === 'null') {\n            return 'None';\n        }\n\n        if (this.codeMap) {\n            var codeMap = eval(this.codeMap);\n        }\n        const codeMapKey = value;\n        if (codeMap) {\n            const codeMapValue = codeMap[codeMapKey];\n            if (codeMapValue) {\n                value = codeMapValue;\n            }\n        }\n        return '\"()\"'.replace('()', value);\n    };\n\n    c.returnOperator = function (key, value) {\n        const map = {\n            EQUAL: '==',\n            GREATER: '>',\n            LESS: '<',\n            GREATER_OR_EQUAL: '>=',\n            LESS_OR_EQUAL: '<=',\n            PLUS: '+',\n            MINUS: '-',\n            MULTI: '*',\n            DIVIDE: '/',\n            NOT_EQUAL: '!=',\n            '!=': 'NOT_EQUAL',\n            '==': 'EQUAL',\n            '>': 'GREATER',\n            '<': 'LESS',\n            '>=': 'GREATER_OR_EQUAL',\n            '<=': 'LESS_OR_EQUAL',\n            '+': 'PLUS',\n            '-': 'MINUS',\n            '*': 'MULTI',\n            '/': 'DIVIDE',\n            AND: 'and',\n            OR: 'or',\n            QUOTIENT: '//',\n            MOD: '%',\n        };\n        return map[value];\n    };\n\n    c.returnRawNumberValueByKey = function (key, value) {\n        //return String(key).replace(/\\D/, '');\n        return key;\n    };\n\n    c.returnStringOrNumberByValue = function (key, value) {\n        if (!Entry.Utils.isNumber(value)) {\n            value = value.replace(/\\\"/gi, '');\n            return '\"()\"'.replace('()', value);\n        } else {\n            return value;\n        }\n    };\n\n    c.returnObjectOrStringValue = function (key, value) {\n        if (Entry.container && Entry.container.getObject(value)) {\n            const objectName = Entry.container.getObject(value).name;\n            return '\"()\"'.replace('()', objectName);\n        } else {\n            if (this.codeMap) {\n                var codeMap = eval(this.codeMap);\n            }\n            const codeMapKey = value;\n            if (codeMap) {\n                const codeMapValue = codeMap[codeMapKey];\n                if (codeMapValue) {\n                    value = codeMapValue;\n                }\n            }\n            value = value.replace(/\\\"/gi, '');\n            return '\"()\"'.replace('()', value);\n        }\n    };\n\n    c.returnStringValueUpperCase = function (key, value) {\n        if (this.codeMap) {\n            var codeMap = eval(this.codeMap);\n        }\n        const codeMapKey = value;\n        if (codeMap) {\n            const codeMapValue = codeMap[codeMapKey];\n            if (codeMapValue) {\n                value = codeMapValue;\n            }\n        }\n        return '\"()\"'.replace('()', value).toUpperCase();\n    };\n\n    c.returnValueUpperCase = function (key, value) {\n        if (this.codeMap) {\n            var codeMap = eval(this.codeMap);\n        }\n        const codeMapKey = value;\n        if (codeMap) {\n            const codeMapValue = codeMap[codeMapKey];\n            if (codeMapValue) {\n                value = codeMapValue;\n            }\n        }\n        return value.toUpperCase();\n    };\n\n    c.returnStringValueLowerCase = function (key, value) {\n        if (this.codeMap) {\n            var codeMap = eval(this.codeMap);\n        }\n        const codeMapKey = value;\n        if (codeMap) {\n            const codeMapValue = codeMap[codeMapKey];\n            if (codeMapValue) {\n                value = codeMapValue;\n            }\n        }\n        return '\"()\"'.replace('()', value).toLowerCase();\n    };\n\n    c.returnValuePartialUpperCase = function (key, value) {\n        if (this.codeMap) {\n            var codeMap = eval(this.codeMap);\n        }\n        const codeMapKey = value;\n        if (codeMap) {\n            const codeMapValue = codeMap[codeMapKey];\n            if (codeMapValue) {\n                value = codeMapValue;\n            }\n        }\n        const dot = value.indexOf('.') + 1;\n        if (dot > 1) {\n            return (\n                value.charAt(0).toUpperCase() +\n                value.substring(1, dot) +\n                value.substring(dot).toUpperCase()\n            );\n        } else {\n            return value.toUpperCase();\n        }\n    };\n    return c;\n}\n\nconst blocks = require('./blocks');\n\nfunction getBlocks() {\n    return {\n        aiUtilizeModelTrainButton: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['functionInit'],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.load_ai_utilize_train_block,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'aiUtilizeModelTrainButton',\n            },\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.aiLearning.openManager();\n                    },\n                ],\n            },\n        },\n        aiUtilizeBlockAddButton: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['functionInit'],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.load_ai_utilize_block,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'aiUtilizeBlockAddButton',\n            },\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.do('playgroundClickAddAIUtilizeBlock');\n                    },\n                ],\n            },\n        },\n        expansionBlockAddButton: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['functionInit'],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.load_expansion_block,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'expansionBlockAddButton',\n            },\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.do('playgroundClickAddExpansionBlock');\n                    },\n                ],\n            },\n        },\n        arduino_lite_connect: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            isNotFor: ['arduinoLiteSupported'],\n            class: 'arduino_default_not_installed',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.arduino_lite_connect,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.do('playgroundClickAddHardwareLiteBlock');\n                    },\n                ],\n            },\n        },\n        arduino_lite_guide: {\n            skeleton: 'clickable_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            isNotFor: ['arduinoLiteGuide'],\n            class: 'arduino_default',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.arduino_lite_guide,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            events: {\n                mousedown: [\n                    function () {\n                        window.open(\n                            'https://docs.playentry.org/user/block_hardware.html#POINT-%EC%95%84%EB%91%90%EC%9D%B4%EB%85%B8-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0'\n                        );\n                    },\n                ],\n            },\n        },\n        arduino_lite_reconnect: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            isNotFor: ['arduinoLiteConnectFailed'],\n            class: 'arduino_default',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.arduino_lite_reconnect,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.hwLite.connect();\n                    },\n                ],\n            },\n        },\n        arduino_lite_download_firmware: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            isNotFor: ['arduinoLiteConnectFailed'],\n            class: 'arduino_default',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.arduino_lite_download_firmware,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            events: {\n                mousedown: [],\n            },\n        },\n        arduino_lite_disconnect: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            isNotFor: ['arduinoLiteConnectFailed', 'arduinoLiteConnected'],\n            class: 'arduino_default',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.arduino_lite_disconnect,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.hwLite.removeHardwareLiteModule();\n                    },\n                ],\n            },\n        },\n        hardware_device_name_title: {\n            skeleton: 'basic_text_light',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hardware_device_name_title,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                    fontWeight: '100',\n                },\n            ],\n            class: 'hardware_device_info',\n            isNotFor: [\n                'arduinoConnect',\n                'arduinoConnected',\n                'arduinoLiteConnectFailed',\n                'arduinoLiteConnected',\n            ],\n            events: {},\n        },\n        hardware_device_name_title_robot: {\n            parent: 'hardware_device_name_title',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hardware_device_name_title_robot,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                    fontWeight: '100',\n                },\n            ],\n            isNotFor: [\n                'arduinoConnect',\n                'arduinoConnected',\n                'arduinoLiteConnectFailed',\n                'arduinoLiteConnected',\n            ],\n        },\n        hardware_device_name_title_sensor: {\n            parent: 'hardware_device_name_title_robot',\n        },\n        hardware_device_name_title_motor: {\n            parent: 'hardware_device_name_title_robot',\n        },\n        hardware_device_name_title_led: {\n            parent: 'hardware_device_name_title_robot',\n        },\n        hardware_device_name_title_melody: {\n            parent: 'hardware_device_name_title_robot',\n        },\n        hardware_device_name_content: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetY: 10,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hardware_device_name_content,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            class: 'hardware_device_info',\n            isNotFor: [\n                'arduinoConnect',\n                'arduinoConnected',\n                'arduinoLiteConnectFailed',\n                'arduinoLiteConnected',\n            ],\n            events: {},\n        },\n        hardware_device_name_content_sensor: {\n            parent: 'hardware_device_name_content',\n        },\n        hardware_device_name_content_motor: {\n            parent: 'hardware_device_name_content',\n        },\n        hardware_device_name_content_led: {\n            parent: 'hardware_device_name_content',\n        },\n        hardware_device_name_content_melody: {\n            parent: 'hardware_device_name_content',\n        },\n        hardware_connected_noti: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetY: 10,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hardware_connected_noti,\n                    color: EntryStatic.colorSet.common.ALERT,\n                    align: 'center',\n                },\n            ],\n            class: 'hardware_device_alert',\n            isNotFor: ['arduinoConnect'],\n            events: {},\n        },\n        arduino_lite_connected_noti: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.arduino_lite_connected_noti,\n                    color: EntryStatic.colorSet.common.GRAY,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'arduino_lite_connected_noti',\n            },\n            class: 'hardware_device_info',\n            isNotFor: ['arduinoLiteConnectFailed', 'arduinoLiteConnected'],\n            events: {},\n        },\n        arduino_lite_alert: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.arduino_lite_alert,\n                    color: EntryStatic.colorSet.common.ALERT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'arduino_lite_alert',\n            },\n            class: 'arduino_lite_alert',\n            isNotFor: ['arduinoLiteConnectFailed'],\n            events: {},\n        },\n        arduino_noti: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.arduino_noti_text,\n                    color: EntryStatic.colorSet.common.GRAY,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'arduino_noti',\n            },\n            class: 'arduino_default_noti',\n            isNotFor: ['arduinoDisconnected'],\n            events: {},\n        },\n        arduino_connected: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['arduinoConnected'],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.ARDUINO_connected,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            events: {},\n        },\n\n        arduino_reconnect: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['arduinoDisconnected'],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.ARDUINO_reconnect,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            class: 'arduino_default_installed',\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.hw.retryConnect();\n                    },\n                ],\n            },\n        },\n        robot_connect_helper: {\n            skeleton: 'clickable_text',\n            skeletonOptions: {\n                box: {\n                    offsetY: -10,\n                },\n            },\n            template: '%1%2',\n            isNotFor: ['arduinoDisconnected'],\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            class: 'arduino_guide',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'question_in_round.svg',\n                    size: 9,\n                    position: {\n                        x: -45,\n                        y: 0,\n                    },\n                },\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.ROBOT_connect_helper,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                    fontSize: 13,\n                },\n            ],\n            events: {\n                mousedown: [\n                    function () {\n                        window.open('https://docs.playentry.org/user/block_hardware.html');\n                    },\n                ],\n            },\n        },\n        robot_noti: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.robot_noti_text,\n                    color: EntryStatic.colorSet.common.GRAY,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'robot_noti',\n            },\n            class: 'arduino_default_noti',\n            isNotFor: ['arduinoDisconnected'],\n            events: {},\n        },\n        robot_reconnect: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['arduinoDisconnected'],\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.ROBOT_reconnect,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.hw.retryConnect();\n                    },\n                ],\n            },\n        },\n        hardware_connect_helper: {\n            skeleton: 'clickable_text',\n            skeletonOptions: {\n                box: {\n                    offsetY: -10,\n                },\n            },\n            template: '%1%2',\n            isNotFor: ['arduinoDisconnected'],\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            class: 'arduino_guide',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'question_in_round.svg',\n                    size: 9,\n                    position: {\n                        x: -55,\n                        y: 0,\n                    },\n                },\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hardware_connect_helper,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                    fontSize: 13,\n                },\n            ],\n            events: {\n                mousedown: [\n                    function () {\n                        window.open('https://docs.playentry.org/user/block_hardware.html');\n                    },\n                ],\n            },\n        },\n        hardware_noti_installed: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hardware_noti_installed,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                    fontSize: 14,\n                },\n            ],\n            class: 'arduino_default_installed',\n            isNotFor: ['arduinoDisconnected'],\n            events: {},\n        },\n        arduino_open: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['arduinoDisconnected'],\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.ARDUINO_open_connector,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            class: 'arduino_default_installed',\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.hw.openHardwareProgram();\n                    },\n                ],\n            },\n        },\n        hardware_program_download: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['arduinoDisconnected'],\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hardware_program_download,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            class: 'arduino_default_installed',\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.hw.downloadConnector();\n                    },\n                ],\n            },\n        },\n        hardware_noti_not_installed: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hardware_noti_not_installed,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                    fontSize: 14,\n                },\n            ],\n            class: 'arduino_default_not_installed',\n            isNotFor: ['arduinoDisconnected'],\n            events: {},\n        },\n        arduino_cloud_pc_open: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            isNotFor: ['arduinoConnect', 'arduinoConnected'],\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.ARDUINO_cloud_pc_connector,\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n            class: 'arduino_default',\n            events: {\n                mousedown: [\n                    function () {\n                        Entry.hw.openHardwareProgram();\n                    },\n                ],\n            },\n        },\n        //endregion hardware 하드웨어 기본\n        //region basic 기본블록\n        change_opacity: {\n            color: EntryStatic.colorSet.block.default.BRUSH,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/brush_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'change_opacity',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'brush_opacity',\n            isNotFor: ['textBox'],\n            func(sprite, script) {\n                let opacity = script.getNumberValue('VALUE', script);\n\n                if (!sprite.brush || !sprite.shapes.length) {\n                    Entry.setBasicBrush(sprite);\n                    sprite.brush.stop = true;\n                }\n                opacity = Entry.adjustValueWithMaxMin(sprite.brush.opacity + opacity, 0, 100);\n\n                if (sprite.brush) {\n                    sprite.brush.opacity = opacity;\n                    sprite.brush.endStroke();\n                    const rgb = sprite.brush.rgb;\n                    sprite.brush.beginStroke(\n                        `rgba(${rgb.r},${rgb.g},${rgb.b},${sprite.brush.opacity / 100})`\n                    );\n                    sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        set_opacity: {\n            color: EntryStatic.colorSet.block.default.BRUSH,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/brush_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'set_opacity',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'brush_opacity',\n            isNotFor: ['textBox'],\n            func(sprite, script) {\n                const opacity = script.getNumberValue('VALUE', script);\n\n                if (!sprite.brush || !sprite.shapes.length) {\n                    Entry.setBasicBrush(sprite);\n                    sprite.brush.stop = true;\n                }\n\n                if (sprite.brush) {\n                    sprite.brush.opacity = Entry.adjustValueWithMaxMin(opacity, 0, 100);\n                    sprite.brush.endStroke();\n                    const rgb = sprite.brush.rgb;\n                    sprite.brush.beginStroke(\n                        `rgba(${rgb.r},${rgb.g},${rgb.b},${sprite.brush.opacity / 100})`\n                    );\n                    sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        number: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: 10,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NUM', script);\n            },\n            isPrimitive: true,\n            syntax: {\n                js: ['Scope', '%1'],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'number',\n                        textParams: [\n                            {\n                                type: 'TextInput',\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        angle: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: 90,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'angle',\n            },\n            paramsKeyMap: {\n                ANGLE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberField('ANGLE');\n            },\n            isPrimitive: true,\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'angle',\n                        textParams: [\n                            {\n                                type: 'Angle',\n                                converter: Entry.block.converters.returnRawNumberValueByKey,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        color: {\n            color: EntryStatic.colorSet.block.default.BRUSH,\n            outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'color',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'color',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Entry.set_color[0]',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        text_color: {\n            template: Lang.template.color,\n            color: EntryStatic.colorSet.block.default.TEXT,\n            outerLine: EntryStatic.colorSet.block.darken.TEXT,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'text_color',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'text_color',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Entry.set_text_color[0]',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        get_x_coordinate: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.CALC_get_x_coordinate,\n                    color: '#3D3D3D',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'get_x_coordinate',\n            },\n            class: 'calc',\n            isNotFor: [],\n            func(sprite, script) {\n                return sprite.getX();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        get_y_coordinate: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.CALC_get_y_coordinate,\n                    color: '#3D3D3D',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'get_y_coordinate',\n            },\n            class: 'calc',\n            isNotFor: [],\n            func(sprite, script) {\n                return sprite.getY();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        get_angle: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.CALC_get_angle,\n                    color: '#3D3D3D',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            func(sprite, script) {\n                return parseFloat(sprite.getRotation().toFixed(1));\n            },\n            syntax: { js: [], py: [''] },\n        },\n        get_rotation_direction: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CALC_rotation_value, 'ROTATION'],\n                        [Lang.Blocks.CALC_direction_value, 'DIRECTION'],\n                    ],\n                    value: 'ROTATION',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'get_rotation_direction',\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            class: 'calc',\n            isNotFor: [],\n            func(sprite, script) {\n                const o = script.getField('OPERATOR', script);\n                if (o.toUpperCase() == 'DIRECTION') {\n                    return parseFloat(sprite.getDirection().toFixed(1));\n                } else {\n                    return parseFloat(sprite.getRotation().toFixed(1));\n                }\n            },\n            syntax: { js: [], py: [''] },\n        },\n        calc_plus: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '+',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            func(sprite, script) {\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                return leftValue + rightValue;\n            },\n            syntax: { js: [], py: [''] },\n        },\n        calc_minus: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '-',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            func(sprite, script) {\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                return leftValue - rightValue;\n            },\n            syntax: { js: [], py: [''] },\n        },\n        calc_times: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: 'x',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            func(sprite, script) {\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                return leftValue * rightValue;\n            },\n            syntax: { js: [], py: [''] },\n        },\n        calc_divide: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '/',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            func(sprite, script) {\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                return leftValue / rightValue;\n            },\n            syntax: { js: [], py: [''] },\n        },\n        calc_mod: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '/',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.CALC_calc_mod_3,\n                    color: '#3D3D3D',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'calc_mod',\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            class: 'calc',\n            isNotFor: [],\n            func(sprite, script) {\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                return leftValue % rightValue;\n            },\n            syntax: { js: [], py: ['Entry.get_remainder(%1, %3)'] },\n        },\n        calc_share: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '/',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '의 몫',\n                    color: '#3D3D3D',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'calc_share',\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            class: 'calc',\n            isNotFor: [],\n            func(sprite, script) {\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                return Math.floor(leftValue / rightValue);\n            },\n            syntax: { js: [], py: [''] },\n        },\n        reset_project_timer: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: '초시계 초기화',\n                    color: '#3D3D3D',\n                },\n            ],\n            events: {\n                viewAdd: [\n                    function () {\n                        if (Entry.engine) {\n                            Entry.engine.showProjectTimer();\n                        }\n                    },\n                ],\n                viewDestroy: [\n                    function (block, notIncludeSelf) {\n                        if (Entry.engine) {\n                            Entry.engine.hideProjectTimer(block, notIncludeSelf);\n                        }\n                    },\n                ],\n            },\n            def: {\n                params: [null],\n                type: 'reset_project_timer',\n            },\n            class: 'calc_timer',\n            isNotFor: [],\n            func(sprite, script) {\n                Entry.engine.updateProjectTimer(0);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        set_visible_project_timer: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.CALC_timer_visible_1,\n                    color: '#000',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CALC_timer_visible_show, 'SHOW'],\n                        [Lang.Blocks.CALC_timer_visible_hide, 'HIDE'],\n                    ],\n                    value: 'SHOW',\n                    fontSize: 11,\n                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                },\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.CALC_timer_visible_2,\n                    color: '#000',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/calc_01.png',\n                    size: 12,\n                },\n            ],\n            events: {\n                viewAdd: [\n                    function () {\n                        if (Entry.engine) {\n                            Entry.engine.showProjectTimer();\n                        }\n                    },\n                ],\n                viewDestroy: [\n                    function (block, notIncludeSelf) {\n                        if (Entry.engine) {\n                            Entry.engine.hideProjectTimer(block, notIncludeSelf);\n                        }\n                    },\n                ],\n            },\n            def: {\n                params: [null, 'HIDE', null, null],\n                type: 'set_visible_project_timer',\n            },\n            pyHelpDef: {\n                params: [null, 'A&value', null, null],\n                type: 'set_visible_project_timer',\n            },\n            paramsKeyMap: {\n                ACTION: 1,\n            },\n            class: 'calc_timer',\n            isNotFor: [],\n            func(sprite, script) {\n                const action = script.getField('ACTION');\n                const timer = Entry.engine.projectTimer;\n                if (action === 'SHOW') {\n                    timer.setVisible(true);\n                } else {\n                    timer.setVisible(false);\n                }\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        template: '%1 %2 %3',\n                        syntax: 'Entry.timer_view(%2)',\n                        textParams: [\n                            {\n                                type: 'Text',\n                                text: 'Entry.timer_view(',\n                                color: '#000',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.CALC_timer_visible_show, 'SHOW'],\n                                    [Lang.Blocks.CALC_timer_visible_hide, 'HIDE'],\n                                ],\n                                value: 'SHOW',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                converter: Entry.block.converters.returnStringValueLowerCase,\n                                codeMap: 'Entry.CodeMap.Entry.set_visible_project_timer[1]',\n                            },\n                            {\n                                type: 'Text',\n                                text: ')',\n                                color: '#000',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        timer_variable: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: '초시계 값',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Text',\n                    text: ' ',\n                    color: '#3D3D3D',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n            },\n            func(sprite, script) {\n                return Entry.container.inputValue.getValue();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        stop_run: {\n            color: EntryStatic.colorSet.block.default.FLOW,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/flow_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            func(sprite, script) {\n                return Entry.engine.toggleStop();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        //endregion basic 기본블록\n        //region basic 기본\n        change_to_nth_shape: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'pictures',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/looks_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'change_to_nth_shape',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'shape',\n            isNotFor: [],\n            func(sprite, script) {\n                const imageId = script.getField('VALUE', script);\n                const picture = sprite.parent.getPicture(imageId);\n                sprite.setImage(picture);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        set_effect_volume: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            skeleton: 'basic',\n            statements: [],\n            deprecated: true,\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.color, 'color'],\n                        [Lang.Blocks.brightness, 'brightness'],\n                        [Lang.Blocks.opacity, 'opacity'],\n                    ],\n                    value: 'color',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/looks_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'set_effect_volume',\n            },\n            paramsKeyMap: {\n                EFFECT: 0,\n                VALUE: 1,\n            },\n            class: 'effect',\n            isNotFor: ['textBox'],\n            func(sprite, script) {\n                const effect = script.getField('EFFECT', script);\n                const effectValue = script.getNumberValue('VALUE', script);\n                let effectName = '';\n                if (effect === 'color') {\n                    sprite.effect.hue = effectValue + sprite.effect.hue;\n                    effectName = 'hue';\n                } else if (effect === 'lens') {\n                } else if (effect === 'swriling') {\n                } else if (effect === 'pixel') {\n                } else if (effect === 'mosaic') {\n                } else if (effect === 'brightness') {\n                    sprite.effect.brightness = effectValue + sprite.effect.brightness;\n                    effectName = 'brightness';\n                } else if (effect === 'blur') {\n                } else if (effect === 'opacity') {\n                    sprite.effect.alpha = sprite.effect.alpha + effectValue / 100;\n                    effectName = 'alpha';\n                }\n                sprite.applyFilter(true, [effectName]);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Entry.set_effect_volume(%1, %2)'] },\n        },\n        set_effect: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.color, 'color'],\n                        [Lang.Blocks.brightness, 'brightness'],\n                        [Lang.Blocks.opacity, 'opacity'],\n                    ],\n                    value: 'color',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/looks_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'set_effect',\n            },\n            paramsKeyMap: {\n                EFFECT: 0,\n                VALUE: 1,\n            },\n            class: 'effect',\n            isNotFor: ['textBox'],\n            func(sprite, script) {\n                const effect = script.getField('EFFECT', script);\n                const effectValue = script.getNumberValue('VALUE', script);\n                let effectName = '';\n                if (effect == 'color') {\n                    sprite.effect.hue = effectValue;\n                    effectName = 'hue';\n                } else if (effect == 'lens') {\n                } else if (effect == 'swriling') {\n                } else if (effect == 'pixel') {\n                } else if (effect == 'mosaic') {\n                } else if (effect == 'brightness') {\n                    sprite.effect.brightness = effectValue;\n                    effectName = 'brightness';\n                } else if (effect == 'blur') {\n                } else if (effect == 'opacity') {\n                    sprite.effect.alpha = effectValue / 100;\n                    effectName = 'alpha';\n                }\n                sprite.applyFilter(true, [effectName]);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Entry.set_effect(%1, %2)'] },\n        },\n        change_scale_percent: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/looks_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'change_scale_percent',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'scale',\n            isNotFor: [],\n            func(sprite, script) {\n                const scaleValue = (script.getNumberValue('VALUE', script) + 100) / 100;\n                sprite.setScaleX(sprite.getScaleX() * scaleValue);\n                sprite.setScaleY(sprite.getScaleY() * scaleValue);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        set_scale_percent: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/looks_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'set_scale_percent',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'scale',\n            isNotFor: [],\n            func(sprite, script) {\n                const scaleValue = script.getNumberValue('VALUE', script) / 100;\n                const snapshot = sprite.snapshot_;\n                sprite.setScaleX(scaleValue * snapshot.scaleX);\n                sprite.setScaleY(scaleValue * snapshot.scaleY);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        set_object_order: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'objectSequence',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/looks_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'set_object_order',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'z-index',\n            isNotFor: [],\n            func(sprite, script) {\n                const targetIndex = script.getField('VALUE', script);\n                const currentIndex = Entry.container.getCurrentObjects().indexOf(sprite.parent);\n\n                if (currentIndex > -1) {\n                    return script.callReturn();\n                } else {\n                    throw new Error('object is not available');\n                }\n            },\n            syntax: { js: [], py: [''] },\n        },\n        get_pictures: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'pictures',\n                    // defaultValue: 'null',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.LOOKS,\n                    arrowColor: EntryStatic.colorSet.arrow.default.LOOKS,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'get_pictures',\n                        textParams: [\n                            {\n                                type: 'DropdownDynamic',\n                                value: null,\n                                menuName: 'pictures',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.LOOKS,\n                                converter: Entry.block.converters.returnStringKey,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        get_table_fields: {\n            color: EntryStatic.colorSet.block.default.ANALYSIS,\n            outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n            template: '%1  ',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName() {\n                        const value = this.getTargetValue('dataTables', true);\n                        if (!value) {\n                            return [[Lang.Blocks.no_target, 'null']];\n                        }\n                        const { fields = [] } = DataTable.getSource(value) || {};\n                        return fields.map((label, index) => [label, index + 1]);\n                    },\n                    needDeepCopy: true,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    defaultValue: (value, options) => {\n                        if (options.length) {\n                            return options[0][1];\n                        }\n                        return null;\n                    },\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'get_table_fields',\n                        textParams: [\n                            {\n                                type: 'DropdownDynamic',\n                                value: null,\n                                menuName: 'fields',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.common.WHITE,\n                                converter: Entry.block.converters.returnStringKey,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        get_korea_area_code: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            template: '%1 %2 ',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: getStateOptions(),\n                    value: 'Seoul',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    dropdownSync: 'weather',\n                },\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName() {\n                        const value = this.getTargetValue('weather');\n                        if (!value) {\n                            return [[Lang.Blocks.no_target, 'null']];\n                        }\n                        return getCityOptions(value);\n                    },\n                    needDeepCopy: true,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    defaultValue: (value, options) => {\n                        if (options.length) {\n                            return options[0][1];\n                        }\n                        return null;\n                    },\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                STATE: 0,\n                SUB_LOC: 1,\n            },\n            func(sprite, script) {\n                return Entry.EXPANSION_BLOCK.weather.getCityCode({\n                    parent: script.getField('STATE'),\n                    sub: script.getField('SUB_LOC'),\n                });\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        type: 'Dropdown',\n                        options: getStateOptions(),\n                        value: 'Seoul',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        dropdownSync: 'weather',\n                        converter: Entry.block.converters.returnStringValue,\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName() {\n                            const value = this.getTargetValue('weather');\n                            if (!value) {\n                                return [[Lang.Blocks.no_target, 'null']];\n                            }\n                            return getCityOptions(value);\n                        },\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options.length) {\n                                return options[0][1];\n                            }\n                            return null;\n                        },\n                        converter: Entry.block.converters.returnStringValue,\n                    },\n                ],\n            },\n        },\n\n        set_effect_amount: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.color, 'color'],\n                        [Lang.Blocks.brightness, 'brightness'],\n                        [Lang.Blocks.transparency, 'transparency'],\n                    ],\n                    value: 'color',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/looks_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'set_effect_amount',\n            },\n            paramsKeyMap: {\n                EFFECT: 0,\n                VALUE: 1,\n            },\n            class: 'effect',\n            isNotFor: ['textBox'],\n            func(sprite, script) {\n                const effect = script.getField('EFFECT', script);\n                const effectValue = script.getNumberValue('VALUE', script);\n                let effectName = '';\n                if (effect === 'color') {\n                    sprite.effect.hue = effectValue + sprite.effect.hue;\n                    effectName = 'hue';\n                } else if (effect === 'brightness') {\n                    sprite.effect.brightness = effectValue + sprite.effect.brightness;\n                    effectName = 'brightness';\n                } else if (effect === 'transparency') {\n                    sprite.effect.alpha = sprite.effect.alpha - effectValue / 100;\n                    effectName = 'alpha';\n                }\n                sprite.applyFilter(true, [effectName]);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        set_entity_effect: {\n            color: EntryStatic.colorSet.block.default.LOOKS,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.color, 'color'],\n                        [Lang.Blocks.brightness, 'brightness'],\n                        [Lang.Blocks.transparency, 'transparency'],\n                    ],\n                    value: 'color',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/looks_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'set_entity_effect',\n            },\n            paramsKeyMap: {\n                EFFECT: 0,\n                VALUE: 1,\n            },\n            class: 'effect',\n            isNotFor: ['textBox'],\n            func(sprite, script) {\n                const effect = script.getField('EFFECT', script);\n                const effectValue = script.getNumberValue('VALUE', script);\n                let effectName = '';\n                if (effect == 'color') {\n                    sprite.effect.hue = effectValue;\n                    effectName = 'hue';\n                } else if (effect == 'brightness') {\n                    sprite.effect.brightness = effectValue;\n                    effectName = 'brightness';\n                } else if (effect == 'transparency') {\n                    sprite.effect.alpha = 1 - effectValue / 100;\n                    effectName = 'alpha';\n                }\n                sprite.applyFilter(true, [effectName]);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        rotate_by_angle: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'rotate_by_angle',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'rotate',\n            isNotFor: [],\n            func(sprite, script) {\n                const value = script.getNumberValue('VALUE', script);\n                sprite.setRotation(sprite.getRotation() + value);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        rotate_by_angle_dropdown: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['45', '45'],\n                        ['90', '90'],\n                        ['135', '135'],\n                        ['180', '180'],\n                    ],\n                    value: '45',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['45', null],\n                type: 'rotate_by_angle_dropdown',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'ebs',\n            isNotFor: [],\n            func(sprite, script) {\n                const value = script.getField('VALUE', script);\n                sprite.setRotation(sprite.getRotation() + Number(value));\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        see_angle: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'see_angle',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'rotate',\n            isNotFor: [],\n            func(sprite, script) {\n                const value = script.getNumberValue('VALUE', script);\n                sprite.setDirection(value);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        see_direction: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'sprites',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const targetId = script.getField('VALUE', script);\n                const targetEntity = Entry.container.getEntity(targetId);\n                const deltaX = targetEntity.getX() - sprite.getX();\n                const deltaY = targetEntity.getY() - sprite.getY();\n                if (deltaX >= 0) {\n                    sprite.setRotation((Math.atan(deltaY / deltaX) / Math.PI) * 180 + 90);\n                } else {\n                    sprite.setRotation((Math.atan(deltaY / deltaX) / Math.PI) * 180 + 270);\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        rotate_by_angle_time: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'angle',\n                    params: ['90'],\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'rotate_by_angle_time',\n            },\n            paramsKeyMap: {\n                VALUE: 1,\n            },\n            class: 'rotate',\n            isNotFor: [],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    let timeValue;\n                    timeValue = script.getNumberValue('VALUE', script);\n                    const angleValue = script.getNumberField('VALUE', script);\n                    script.isStart = true;\n                    script.frameCount = Math.floor(timeValue * Entry.FPS);\n                    script.dAngle = angleValue / script.frameCount;\n                }\n                if (script.frameCount != 0) {\n                    sprite.setRotation(sprite.getRotation() + script.dAngle);\n                    script.frameCount--;\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.frameCount;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [''] },\n        },\n        flip_arrow_horizontal: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            func(sprite, script) {\n                sprite.setDirection(sprite.getDirection() + 180);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        flip_arrow_vertical: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            func(sprite, script) {\n                sprite.setDirection(sprite.getDirection() + 180);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        see_angle_direction: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'see_angle_direction',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'rotate',\n            isNotFor: [],\n            func(sprite, script) {\n                const value = script.getNumberValue('VALUE', script);\n                const nativeDirection = sprite.getDirection() + sprite.getRotation();\n                sprite.setRotation(sprite.getRotation() + value - nativeDirection);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        rotate_direction: {\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'rotate_direction',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'rotate',\n            isNotFor: [],\n            func(sprite, script) {\n                const value = script.getNumberValue('VALUE', script);\n                sprite.setDirection(value + sprite.getDirection());\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        //endregion basic 기본\n        //region basic 기본\n        sound_something: {\n            color: EntryStatic.colorSet.block.default.SOUND,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'sounds',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/sound_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'sound_something',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'sound',\n            isNotFor: [],\n            func(sprite, script) {\n                const soundId = script.getField('VALUE', script);\n                const sounds = sprite.parent.sounds;\n                const isExist = Entry.isExist(soundId, 'id', sounds);\n                if (isExist) {\n                    Entry.Utils.playSound(soundId);\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        sound_something_second: {\n            color: EntryStatic.colorSet.block.default.SOUND,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'sounds',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/sound_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'sound_something_second',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                SECOND: 1,\n            },\n            class: 'sound',\n            isNotFor: [],\n            func(sprite, script) {\n                const soundId = script.getField('VALUE', script);\n                const timeValue = script.getNumberValue('SECOND', script);\n                const sounds = sprite.parent.sounds;\n                const isExist = Entry.isExist(soundId, 'id', sounds);\n                if (isExist) {\n                    const instance = Entry.Utils.playSound(soundId);\n                    Entry.Utils.addSoundInstances(instance);\n                    setTimeout(() => {\n                        instance.stop();\n                    }, timeValue * 1000);\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        sound_something_wait: {\n            color: EntryStatic.colorSet.block.default.SOUND,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'sounds',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/sound_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'sound_something_wait',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'sound',\n            isNotFor: [],\n            func(sprite, script) {\n                if (!script.isPlay) {\n                    script.isPlay = true;\n                    script.playState = 1;\n                    const soundId = script.getField('VALUE', script);\n                    const sound = sprite.parent.getSound(soundId);\n                    const sounds = sprite.parent.sounds;\n                    const isExist = Entry.isExist(soundId, 'id', sounds);\n                    if (isExist) {\n                        const duration = Math.floor(\n                            (sound.duration * 1000) / Entry.playbackRateValue\n                        );\n                        const instance = Entry.Utils.playSound(soundId);\n                        Entry.Utils.addSoundInstances(instance);\n                        setTimeout(() => {\n                            script.playState = 0;\n                        }, duration);\n                    }\n                    return script;\n                } else if (script.playState === 1) {\n                    return script;\n                } else {\n                    delete script.playState;\n                    delete script.isPlay;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [''] },\n        },\n        sound_something_second_wait: {\n            color: EntryStatic.colorSet.block.default.SOUND,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'sounds',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/sound_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'sound_something_second_wait',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                SECOND: 1,\n            },\n            class: 'sound',\n            isNotFor: [],\n            func(sprite, script) {\n                if (!script.isPlay) {\n                    script.isPlay = true;\n                    script.playState = 1;\n                    const soundId = script.getField('VALUE', script);\n                    const sounds = sprite.parent.sounds;\n                    const isExist = Entry.isExist(soundId, 'id', sounds);\n                    if (isExist) {\n                        const instance = Entry.Utils.playSound(soundId);\n                        const timeValue = script.getNumberValue('SECOND', script);\n                        Entry.Utils.addSoundInstances(instance);\n                        setTimeout(() => {\n                            instance.stop();\n                            script.playState = 0;\n                        }, timeValue * 1000);\n                        instance.addEventListener('complete', (e) => {});\n                    }\n                    return script;\n                } else if (script.playState == 1) {\n                    return script;\n                } else {\n                    delete script.isPlay;\n                    delete script.playState;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [''] },\n        },\n        get_sounds: {\n            color: EntryStatic.colorSet.block.default.SOUND,\n            outerLine: EntryStatic.colorSet.block.darken.SOUND,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: 'sounds',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.SOUND,\n                    arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'get_sounds',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'DropdownDynamic',\n                                value: null,\n                                menuName: 'sounds',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.SOUND,\n                                converter: Entry.block.converters.returnStringKey,\n                            },\n                        ],\n                        keyOption: 'get_sounds',\n                    },\n                ],\n            },\n        },\n        boolean_comparison: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['<', 'SMALLER'],\n                        ['>', 'BIGGER'],\n                    ],\n                    value: 'EQUAL',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'boolean_comparison',\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                OPERATOR: 1,\n                RIGHTHAND: 2,\n            },\n            func(sprite, script) {\n                const operator = script.getField('OPERATOR', script);\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                if (operator === 'EQUAL') {\n                    return leftValue === rightValue;\n                } else if (operator === 'BIGGER') {\n                    return leftValue > rightValue;\n                } else {\n                    return leftValue < rightValue;\n                }\n            },\n            syntax: { js: [], py: [''] },\n        },\n        boolean_equal: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '=',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                ],\n                type: 'boolean_equal',\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            class: 'boolean_compare',\n            isNotFor: [],\n            func(sprite, script) {\n                const leftValue = script.getStringValue('LEFTHAND', script);\n                const rightValue = script.getStringValue('RIGHTHAND', script);\n                return leftValue == rightValue;\n            },\n            syntax: { js: [], py: [''] },\n        },\n        boolean_bigger: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '>',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                ],\n                type: 'boolean_bigger',\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            class: 'boolean_compare',\n            isNotFor: [],\n            func(sprite, script) {\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                return leftValue > rightValue;\n            },\n            syntax: { js: [], py: [''] },\n        },\n        boolean_smaller: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Text',\n                    text: '<',\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                ],\n                type: 'boolean_smaller',\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            class: 'boolean_compare',\n            isNotFor: [],\n            func(sprite, script) {\n                const leftValue = script.getNumberValue('LEFTHAND', script);\n                const rightValue = script.getNumberValue('RIGHTHAND', script);\n                return leftValue < rightValue;\n            },\n            syntax: { js: [], py: [''] },\n        },\n        boolean_and: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.JUDGEMENT_boolean_and,\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'True',\n                    },\n                    null,\n                    {\n                        type: 'True',\n                    },\n                ],\n                type: 'boolean_and',\n            },\n            pyHelpDef: {\n                params: [\n                    {\n                        type: 'boolean_shell',\n                        params: ['A'],\n                    },\n                    null,\n                    {\n                        type: 'boolean_shell',\n                        params: ['B'],\n                    },\n                ],\n                type: 'boolean_and',\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            class: 'boolean',\n            isNotFor: [],\n            func(sprite, script) {\n                const leftValue = script.getBooleanValue('LEFTHAND', script);\n                const rightValue = script.getBooleanValue('RIGHTHAND', script);\n                return leftValue && rightValue;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '(%1 and %3)',\n                        template: '%1 and %3',\n                        blockType: 'param',\n                        dic: '&&',\n                    },\n                ],\n            },\n        },\n        boolean_or: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.JUDGEMENT_boolean_or,\n                    color: '#3D3D3D',\n                },\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n            ],\n            events: {},\n            def: {\n                params: [{ type: 'True' }, null, { type: 'False' }],\n                type: 'boolean_or',\n            },\n            pyHelpDef: {\n                params: [\n                    {\n                        type: 'boolean_shell',\n                        params: ['A'],\n                    },\n                    null,\n                    {\n                        type: 'boolean_shell',\n                        params: ['B'],\n                    },\n                ],\n                type: 'boolean_or',\n            },\n            paramsKeyMap: {\n                LEFTHAND: 0,\n                RIGHTHAND: 2,\n            },\n            class: 'boolean',\n            isNotFor: [],\n            func(sprite, script) {\n                const leftValue = script.getBooleanValue('LEFTHAND', script);\n                const rightValue = script.getBooleanValue('RIGHTHAND', script);\n                return leftValue || rightValue;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '(%1 or %3)',\n                        template: '%1 or %3',\n                        blockType: 'param',\n                        dic: '||',\n                    },\n                ],\n            },\n        },\n        true_or_false: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.JUDGEMENT_true, 'true'],\n                        [Lang.Blocks.JUDGEMENT_false, 'false'],\n                    ],\n                    value: 'true',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.children[0].textContent;\n                return value === 'true';\n            },\n            syntax: { js: [], py: [''] },\n        },\n        True: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.JUDGEMENT_true,\n                    color: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'True',\n            },\n            func(sprite, script) {\n                return true;\n            },\n            isPrimitive: true,\n            syntax: { js: ['Scope', 'true'], py: ['True'] },\n        },\n        False: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.JUDGEMENT_false,\n                    color: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'False',\n            },\n            func(sprite, script) {\n                return false;\n            },\n            isPrimitive: true,\n            syntax: { js: [], py: ['False'] },\n        },\n        press_some_key: {\n            color: EntryStatic.colorSet.block.default.START,\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_keyboard.png',\n                    size: 17,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['q', 81],\n                        ['w', 87],\n                        ['e', 69],\n                        ['r', 82],\n                        ['a', 65],\n                        ['s', 83],\n                        ['d', 68],\n                        ['위쪽 화살표', 38],\n                        ['아래쪽 화살표', 40],\n                        ['왼쪽 화살표', 37],\n                        ['오른쪽 화살표', 39],\n                        ['엔터', 13],\n                        ['스페이스', 32],\n                    ],\n                    value: 81,\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_03.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n            },\n            paramsKeyMap: {\n                VALUE: 1,\n            },\n            func(sprite, script) {\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [''] },\n        },\n        text: {\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: 10,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'text',\n            },\n            paramsKeyMap: {\n                NAME: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NAME', script);\n            },\n            isPrimitive: true,\n            syntax: {\n                js: ['Scope', '%1'],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'text',\n                        textParams: [\n                            {\n                                type: 'TextInput',\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        options_for_list: {\n            color: EntryStatic.colorSet.block.default.VARIABLE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['첫번째', 'FIRST'],\n                        ['마지막', 'LAST'],\n                        ['무작위', 'RANDOM'],\n                    ],\n                    value: 'FIRST',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OPERATOR', script);\n            },\n            syntax: { js: [], py: [''] },\n        },\n        //endregion basic 기본\n        //region basic 기본\n        run: {\n            skeleton: 'basic',\n            color: EntryStatic.colorSet.block.default.START,\n            contents: ['this is', 'basic block'],\n        },\n        mutant: {\n            skeleton: 'basic',\n            event: 'start',\n            color: EntryStatic.colorSet.block.default.START,\n            params: [],\n            changeEvent: {\n                _listeners: [],\n            },\n        },\n        jr_start: {\n            skeleton: 'pebble_event',\n            event: 'start',\n            color: EntryStatic.colorSet.block.default.START,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/ntry/bitmap/jr/block_play_image.png',\n                    highlightColor: EntryStatic.colorSet.block.default.START,\n                    position: {\n                        x: 0,\n                        y: 0,\n                    },\n                    size: 22,\n                },\n            ],\n            func() {\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                for (const key in entities) {\n                    this._unit = entities[key];\n                }\n\n                Ntry.unitComp = Ntry.entityManager.getComponent(this._unit.id, Ntry.STATIC.UNIT);\n            },\n        },\n        jr_repeat: {\n            skeleton: 'pebble_loop',\n            color: '#127CDB',\n            params: [\n                {\n                    type: 'Text',\n                    text: '',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 1],\n                        [2, 2],\n                        [3, 3],\n                        [4, 4],\n                        [5, 5],\n                        [6, 6],\n                        [7, 7],\n                        [8, 8],\n                        [9, 9],\n                        [10, 10],\n                    ],\n                    value: 3,\n                    fontSize: 14,\n                    roundValue: 3,\n                },\n            ],\n            statements: [{ accept: 'pebble_basic' }],\n            func() {\n                if (this.repeatCount === undefined) {\n                    this.repeatCount = this.block.params[1];\n                    return Entry.STATIC.BREAK;\n                } else if (this.repeatCount > 0) {\n                    this.repeatCount--;\n                    const statement = this.block.statements[0];\n                    if (statement.getBlocks().length === 0) {\n                        return;\n                    }\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.repeatCount;\n                }\n            },\n        },\n        jr_item: {\n            skeleton: 'pebble_basic',\n            color: '#F46C6C',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/ntry/bitmap/jr/block_item_image.png',\n                    highlightColor: EntryStatic.colorSet.common.WHITE,\n                    position: {\n                        x: 83,\n                        y: 0,\n                    },\n                    size: 22,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        Ntry.dispatchEvent('getItem');\n                        self.isAction = false;\n                    };\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.GET_ITEM, callBack);\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        cparty_jr_item: {\n            skeleton: 'pebble_basic',\n            color: '#8ABC1D',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/ntry/bitmap/cpartyjr/pen.png',\n                    highlightColor: EntryStatic.colorSet.common.WHITE,\n                    position: {\n                        x: 83,\n                        y: 0,\n                    },\n                    size: 22,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        Ntry.dispatchEvent('getItem');\n                        self.isAction = false;\n                    };\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.GET_ITEM, callBack);\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        jr_north: {\n            skeleton: 'pebble_basic',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/ntry/bitmap/jr/block_up_image.png',\n                    position: {\n                        x: 83,\n                        y: 0,\n                    },\n                    size: 22,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const STATIC = Ntry.STATIC;\n                    const self = this;\n                    const callBack = function () {\n                        window.setTimeout(() => {\n                            Ntry.dispatchEvent('unitAction', Ntry.STATIC.WALK, () => {\n                                self.isAction = false;\n                            });\n                        }, 3);\n                    };\n                    let actionType;\n                    switch (Ntry.unitComp.direction) {\n                        case Ntry.STATIC.EAST:\n                            actionType = STATIC.TURN_LEFT;\n                            break;\n                        case Ntry.STATIC.SOUTH:\n                            actionType = STATIC.HALF_ROTATION;\n                            break;\n                        case Ntry.STATIC.WEST:\n                            actionType = STATIC.TURN_RIGHT;\n                            break;\n                        default:\n                            callBack();\n                            break;\n                    }\n                    if (actionType) {\n                        Ntry.dispatchEvent('unitAction', actionType, callBack);\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        jr_east: {\n            skeleton: 'pebble_basic',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/ntry/bitmap/jr/block_right_image.png',\n                    position: {\n                        x: 83,\n                        y: 0,\n                    },\n                    size: 22,\n                },\n            ],\n            func() {\n                const STATIC = Ntry.STATIC;\n\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        window.setTimeout(() => {\n                            Ntry.dispatchEvent('unitAction', STATIC.WALK, () => {\n                                self.isAction = false;\n                            });\n                        }, 3);\n                    };\n\n                    // turn direction\n                    let actionType;\n                    switch (Ntry.unitComp.direction) {\n                        case STATIC.SOUTH:\n                            actionType = STATIC.TURN_LEFT;\n                            break;\n                        case STATIC.WEST:\n                            actionType = STATIC.HALF_ROTATION;\n                            break;\n                        case STATIC.NORTH:\n                            actionType = STATIC.TURN_RIGHT;\n                            break;\n                        default:\n                            callBack();\n                            break;\n                    }\n                    if (actionType) {\n                        Ntry.dispatchEvent('unitAction', actionType, callBack);\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        jr_south: {\n            skeleton: 'pebble_basic',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/ntry/bitmap/jr/block_down_image.png',\n                    position: {\n                        x: 83,\n                        y: 0,\n                    },\n                    size: 22,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const STATIC = Ntry.STATIC;\n                    const self = this;\n                    const callBack = function () {\n                        window.setTimeout(() => {\n                            Ntry.dispatchEvent('unitAction', Ntry.STATIC.WALK, () => {\n                                self.isAction = false;\n                            });\n                        }, 3);\n                    };\n\n                    // turn direction\n                    let actionType;\n                    switch (Ntry.unitComp.direction) {\n                        case STATIC.EAST:\n                            actionType = STATIC.TURN_RIGHT;\n                            break;\n                        case STATIC.NORTH:\n                            actionType = STATIC.HALF_ROTATION;\n                            break;\n                        case STATIC.WEST:\n                            actionType = STATIC.TURN_LEFT;\n                            break;\n                        default:\n                            callBack();\n                            break;\n                    }\n                    if (actionType) {\n                        Ntry.dispatchEvent('unitAction', actionType, callBack);\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        jr_west: {\n            skeleton: 'pebble_basic',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/ntry/bitmap/jr/block_left_image.png',\n                    position: {\n                        x: 83,\n                        y: 0,\n                    },\n                    size: 22,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const STATIC = Ntry.STATIC;\n                    const self = this;\n                    const callBack = function () {\n                        window.setTimeout(() => {\n                            Ntry.dispatchEvent('unitAction', STATIC.WALK, () => {\n                                self.isAction = false;\n                            });\n                        }, 3);\n                    };\n\n                    // turn direction\n                    let actionType;\n                    switch (Ntry.unitComp.direction) {\n                        case STATIC.SOUTH:\n                            actionType = STATIC.TURN_RIGHT;\n                            break;\n                        case STATIC.EAST:\n                            actionType = STATIC.HALF_ROTATION;\n                            break;\n                        case STATIC.NORTH:\n                            actionType = STATIC.TURN_LEFT;\n                            break;\n                        default:\n                            callBack();\n                            break;\n                    }\n                    if (actionType) {\n                        Ntry.dispatchEvent('unitAction', actionType, callBack);\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        jr_start_basic: {\n            skeleton: 'basic_event',\n            event: 'start',\n            color: EntryStatic.colorSet.block.default.START,\n            params: [\n                {\n                    type: 'Indicator',\n                    boxMultiplier: 2,\n                    img: '../../../img/assets/block_icon/start_icon_play.png',\n                    highlightColor: EntryStatic.colorSet.block.default.START,\n                    size: 17,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    text: '시작하기를 클릭했을때',\n                    type: 'Text',\n                },\n            ],\n            func() {\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                for (const key in entities) {\n                    this._unit = entities[key];\n                }\n\n                Ntry.unitComp = Ntry.entityManager.getComponent(this._unit.id, Ntry.STATIC.UNIT);\n            },\n        },\n        jr_go_straight: {\n            skeleton: 'basic',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/jr/cparty_go_straight.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.WALK, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n            syntax: ['Scope', 'move'],\n        },\n        jr_turn_left: {\n            skeleton: 'basic',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/jr/cparty_rotate_l.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.TURN_LEFT, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n            syntax: ['Scope', 'left'],\n        },\n        jr_turn_right: {\n            skeleton: 'basic',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/jr/cparty_rotate_r.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.TURN_RIGHT, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n            syntax: ['Scope', 'right'],\n        },\n        jr_go_slow: {\n            skeleton: 'basic',\n            color: '#f46c6c',\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/jr/cparty_go_slow.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.GO_SLOW, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n            syntax: ['Scope', 'move_slowly'],\n        },\n        jr_repeat_until_dest: {\n            skeleton: 'basic_loop',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicWhile', 'true'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/jr/jr_goal_image.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                const statement = this.block.statements[0];\n                if (statement.getBlocks().length === 0) {\n                    return;\n                }\n\n                this.executor.stepInto(statement);\n                return Entry.STATIC.BREAK;\n            },\n        },\n        jr_if_construction: {\n            skeleton: 'basic_loop',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', \"front == 'wall'\"],\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/jr/jr_construction_image.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_REPAIR,\n                    }\n                );\n\n                this.isContinue = true;\n\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        jr_if_speed: {\n            skeleton: 'basic_loop',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', \"front == 'hump'\"],\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/jr/jr_speed_image.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_SLOW,\n                    }\n                );\n\n                this.isContinue = true;\n\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_step_start: {\n            skeleton: 'basic_event',\n            mode: 'maze',\n            event: 'start',\n            color: EntryStatic.colorSet.block.default.START,\n            syntax: ['Program'],\n            params: [\n                {\n                    type: 'Indicator',\n                    boxMultiplier: 2,\n                    img: '../../../img/assets/block_icon/start_icon_play.png',\n                    highlightColor: EntryStatic.colorSet.block.default.START,\n                    size: 17,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n            ],\n            func() {\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                for (const key in entities) {\n                    this._unit = entities[key];\n                }\n\n                Ntry.unitComp = Ntry.entityManager.getComponent(this._unit.id, Ntry.STATIC.UNIT);\n                Ntry.unit = this._unit;\n            },\n        },\n        maze_step_jump: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#FF6E4B',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/jump.png',\n                    size: 24,\n                },\n            ],\n            syntax: ['Scope', 'jump'],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.JUMP, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_step_jump2: {\n            parent: 'maze_step_jump',\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                    let unitId;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                    });\n\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const checkGrid = {\n                        x: unitGrid.x,\n                        y: unitGrid.y,\n                    };\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_IRON],\n                        2\n                    );\n                    if (isCollisionPossible) {\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.FAIL_JUMP, callBack);\n                        Ntry.dispatchEvent('complete', false, Ntry.STATIC.CONTACT_IRON);\n                        return;\n                    }\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.JUMP, callBack);\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_step_jump_pinkbean: {\n            parent: 'maze_step_jump',\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n                    const unit = Ntry.getUnit();\n                    const components = unit.components || {};\n                    const unitComp = components[Ntry.STATIC.UNIT] || {};\n                    const unitGrid = $.extend({}, components[Ntry.STATIC.GRID]);\n                    const checkGrid = {\n                        x: unitGrid.x,\n                        y: unitGrid.y,\n                    };\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_MUSHROOM],\n                        1\n                    );\n                    if (isCollisionPossible) {\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.FAIL_JUMP, callBack);\n                        Ntry.dispatchEvent('complete', false, Ntry.STATIC.HIT_UNIT_BY_MUSHROOM);\n                        return;\n                    }\n\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.JUMP, callBack);\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_step_for: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIteration'],\n            params: [\n                {\n                    type: 'Dropdown',\n                    key: 'REPEAT',\n                    options: [\n                        [1, 1],\n                        [2, 2],\n                        [3, 3],\n                        [4, 4],\n                        [5, 5],\n                        [6, 6],\n                        [7, 7],\n                        [8, 8],\n                        [9, 9],\n                        [10, 10],\n                    ],\n                    value: 1,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.repeatCount === undefined) {\n                    this.repeatCount = this.block.params[0];\n                    return Entry.STATIC.BREAK;\n                } else if (this.repeatCount > 0) {\n                    this.repeatCount--;\n                    const statement = this.block.statements[0];\n                    if (statement.getBlocks().length === 0) {\n                        return;\n                    }\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.repeatCount;\n                }\n            },\n        },\n        test: {\n            skeleton: 'basic_boolean_field',\n            mode: 'maze',\n            color: '#127CDB',\n            params: [\n                {\n                    type: 'Angle',\n                    value: '90',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 1],\n                        [2, 2],\n                        [3, 3],\n                        [4, 4],\n                        [5, 5],\n                        [6, 6],\n                        [7, 7],\n                        [8, 8],\n                        [9, 9],\n                        [10, 10],\n                    ],\n                    value: 1,\n                },\n            ],\n        },\n        maze_repeat_until_1: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicWhile', 'true'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/ntry/block_inner/repeat_goal_1.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                const statement = this.block.statements[0];\n                if (statement.getBlocks().length === 0) {\n                    return;\n                }\n\n                this.executor.stepInto(statement);\n                return Entry.STATIC.BREAK;\n            },\n        },\n        maze_repeat_until_2: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicWhile', 'true'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/ntry/block_inner/repeat_goal_1.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                const statement = this.block.statements[0];\n                if (statement.getBlocks().length === 0) {\n                    return;\n                }\n\n                this.executor.stepInto(statement);\n                return Entry.STATIC.BREAK;\n            },\n        },\n        maze_step_if_1: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', \"front == 'wall'\"],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/ntry/block_inner/if_target_1.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const existEntities = Ntry.entityManager.find({\n                    type: Ntry.STATIC.GRID,\n                    x: grid.x,\n                    y: grid.y,\n                });\n\n                const statement = this.block.statements[0];\n\n                if (existEntities.length === 0) {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.WALL,\n                    }\n                );\n\n                this.isContinue = true;\n\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_step_if_2: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', \"front == 'bee'\"],\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/maze2/obstacle_01.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_BEE,\n                    }\n                );\n\n                this.isContinue = true;\n\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_call_function: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#B57242',\n            syntax: ['Scope', 'promise'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/function.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.funcExecutor) {\n                    const codes = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.CODE);\n\n                    for (const key in codes) {\n                        const code = codes[key].components[Ntry.STATIC.CODE].code;\n                        this.funcExecutor = new Entry.Executor(code.getEventMap('define')[0]);\n                    }\n                }\n\n                this.funcExecutor.execute();\n                if (this.funcExecutor.scope.block === null) {\n                    return;\n                } else {\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_define_function: {\n            skeleton: 'basic_define',\n            mode: 'maze',\n            color: '#B57242',\n            event: 'define',\n            syntax: ['BasicFunction'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/function.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func(executor) {\n                if (this.executed) {\n                    return;\n                }\n                const statement = this.block.statements[0];\n                if (statement.getBlocks().length === 0) {\n                    return;\n                }\n                this.executor.stepInto(statement);\n                this.executed = true;\n                return Entry.STATIC.BREAK;\n            },\n        },\n        maze_step_if_3: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'front == banana'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/ntry/block_inner/if_target_3.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_BANANA,\n                    }\n                );\n\n                this.isContinue = true;\n\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_step_if_4: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'front == wall'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/ntry/block_inner/if_target_2.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.WALL,\n                    }\n                );\n\n                this.isContinue = true;\n\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_step_move_step: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'move'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/moveStep.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.WALK, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_step_rotate_left: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'left'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/turnL.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.TURN_LEFT, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_step_rotate_right: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/turnR.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.TURN_RIGHT, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_step_forward: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'move'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/moveStep.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.WALK, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_turn_right: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'turn_right'],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/week/blocks/right_ic.png',\n                    size: 12,\n                },\n            ],\n            func() {\n                if (this.isDead) {\n                    return Entry.STATIC.BREAK;\n                } else if (this.executor.register.isTurned) {\n                    Ntry.dispatchEvent('startEnemyWalk', false, () => {});\n                    this.isDead = true;\n                    return Entry.STATIC.BREAK;\n                } else {\n                    Ntry.unit.components[Ntry.STATIC.UNIT].direction = Ntry.STATIC.EAST;\n                    this.executor.register.isTurned = true;\n                }\n            },\n        },\n        maze_turn_left: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'turn_left'],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/week/blocks/left_ic.png',\n                    size: 12,\n                },\n            ],\n            func() {\n                if (this.isDead) {\n                    return Entry.STATIC.BREAK;\n                } else if (this.executor.register.isTurned) {\n                    Ntry.dispatchEvent('startEnemyWalk', false, () => {});\n                    this.isDead = true;\n                    return Entry.STATIC.BREAK;\n                } else {\n                    Ntry.unit.components[Ntry.STATIC.UNIT].direction = Ntry.STATIC.WEST;\n                    this.executor.register.isTurned = true;\n                }\n            },\n        },\n        maze_step_if_left_monster: {\n            skeleton: 'basic_double_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'left == monster'],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/week/blocks/if.png',\n                    size: 12,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            statementsKeyMap: {\n                STACK_IF: 0,\n                STACK_ELSE: 1,\n            },\n            func(sprite, script) {\n                if (this.isContinue) {\n                    return;\n                }\n                const unitComp = Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x - 1, y: gridComp.y };\n                const fitEntities = Ntry.entityManager\n                    .find({\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    })\n                    .filter((e) => e.components[Ntry.STATIC.ENEMY]);\n                this.isContinue = true;\n                if (fitEntities.length === 0) {\n                    return script.getStatement('STACK_ELSE', script);\n                } else {\n                    return script.getStatement('STACK_IF', script);\n                }\n            },\n        },\n        maze_step_if_right_monster: {\n            skeleton: 'basic_double_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'right == monster'],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/week/blocks/if.png',\n                    size: 12,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            statementsKeyMap: {\n                STACK_IF: 0,\n                STACK_ELSE: 1,\n            },\n            func(sprite, script) {\n                if (this.isContinue) {\n                    return;\n                }\n                const unitComp = Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x + 1, y: gridComp.y };\n                const fitEntities = Ntry.entityManager\n                    .find({\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    })\n                    .filter((e) => e.components[Ntry.STATIC.ENEMY]);\n                this.isContinue = true;\n                if (fitEntities.length === 0) {\n                    return script.getStatement('STACK_ELSE', script);\n                } else {\n                    return script.getStatement('STACK_IF', script);\n                }\n            },\n        },\n        maze_step_if_yeti: {\n            skeleton: 'basic_double_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'front == yeti'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/yeti.png',\n                    size: 24,\n                },\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/week/blocks/if.png',\n                    size: 12,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            statementsKeyMap: {\n                STACK_IF: 0,\n                STACK_ELSE: 1,\n            },\n            func(sprite, script) {\n                if (this.isContinue) {\n                    return;\n                }\n                const unitComp = Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_YETI,\n                    }\n                );\n                this.isContinue = true;\n                if (fitEntities.length === 0) {\n                    return script.getStatement('STACK_ELSE', script);\n                } else {\n                    return script.getStatement('STACK_IF', script);\n                }\n            },\n        },\n        maze_repeat_until_beat_monster: {\n            parent: 'repeat_inf',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: '../../../img/assets/week/blocks/for.png',\n                    size: 12,\n                },\n            ],\n        },\n        maze_ladder_climb: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#71C11B',\n            emphasizedColor: '#9BDB40',\n            syntax: ['Scope', 'climb'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/ladder.png',\n                    size: 24,\n                },\n            ],\n            func(sprite, script) {\n                if (!script.isContinue) {\n                    script.isContinue = true;\n                    script.isAction = true;\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                    let unitId;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                    });\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    script.direction = unitComp.direction;\n                    const callBack = function () {\n                        unitComp.direction = script.direction;\n                        script.isAction = false;\n                    };\n                    let isCollisionPossible = false;\n                    if (unitGrid.y > 3) {\n                        unitComp.direction = Ntry.STATIC.NORTH;\n                        isCollisionPossible = Ntry.checkCollisionTile(\n                            unitGrid,\n                            unitComp.direction,\n                            [Ntry.STATIC.LADDER],\n                            2\n                        );\n                    } else {\n                        unitComp.direction = Ntry.STATIC.SOUTH;\n                        const tile = Ntry.getTileByGrid(unitGrid);\n                        if (tile.tileType === Ntry.STATIC.LADDER) {\n                            isCollisionPossible = true;\n                        }\n                    }\n                    if (isCollisionPossible) {\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.CLIMB, callBack);\n                    } else {\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.NOT_FOUND_LADDER, callBack);\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isContinue;\n                }\n            },\n        },\n        maze_attack_lupin: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#ef6d6a',\n            emphasizedColor: '#f29999',\n            syntax: ['Scope', 'yoyo'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/lupin.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/pinkbean_ic.png',\n                    size: 24,\n                },\n            ],\n            func(sprite, script) {\n                if (!script.isContinue) {\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                    let unitId;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                    });\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    script.isContinue = true;\n                    script.isAction = true;\n                    let isFoundMushroom = false;\n                    const grid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    for (let i = 0; i < 2; i++) {\n                        Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n                        const findTile = Ntry.entityManager.find(\n                            {\n                                type: Ntry.STATIC.GRID,\n                                x: grid.x,\n                                y: grid.y,\n                            },\n                            {\n                                type: Ntry.STATIC.TILE,\n                                tileType: Ntry.STATIC.OBSTACLE_MUSHROOM,\n                            }\n                        );\n                        if (findTile && findTile.length) {\n                            isFoundMushroom = true;\n                        }\n                    }\n                    if (isFoundMushroom) {\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.WRONG_ATTACK_OBSTACLE, () => {\n                            script.isAction = false;\n                        });\n                        return Entry.STATIC.BREAK;\n                    }\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_LUPIN],\n                        2\n                    );\n                    if (!isCollisionPossible) {\n                        Ntry.dispatchEvent(\n                            'unitAction',\n                            Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT,\n                            () => {\n                                script.isAction = false;\n                            }\n                        );\n                        return Entry.STATIC.BREAK;\n                    }\n                    const callBack = function () {\n                        Ntry.dispatchEvent('playSound', 'dieLupin');\n                        Ntry.dispatchEvent('destroyObstacle', 2, (state) => {\n                            script.isAction = false;\n                        });\n                    };\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.ATTACK_LUPIN, callBack);\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isContinue;\n                }\n            },\n        },\n        maze_attack_both_side: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#ef6d6a',\n            emphasizedColor: '#f29999',\n            syntax: ['Scope', 'both_side'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/pinkbean_ic.png',\n                    size: 24,\n                },\n            ],\n            func(sprite, script) {\n                if (!script.isContinue) {\n                    Ntry.dispatchEvent('stopEnemyWalk');\n                    this.executor.register.isTurned = false;\n                    script.isContinue = true;\n                    script.isAction = true;\n                    const grid = $.extend(\n                        { type: Ntry.STATIC.GRID },\n                        Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID)\n                    );\n                    const backGrid = $.extend(\n                        { type: Ntry.STATIC.GRID },\n                        Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID)\n                    );\n                    Ntry.addVectorByDirection(grid, Ntry.unitComp.direction, 1);\n                    Ntry.addVectorByDirection(backGrid, Ntry.unitComp.direction, -1);\n                    const frontExist = !!Ntry.entityManager\n                        .find(grid)\n                        .filter((e) => e.components[Ntry.STATIC.ENEMY]).length;\n                    const backExist = !!Ntry.entityManager\n                        .find(backGrid)\n                        .filter((e) => e.components[Ntry.STATIC.ENEMY]).length;\n                    if (!frontExist || !backExist) {\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.BOTH_SIDE_FAIL, () => {\n                            script.isAction = false;\n                        });\n                        return Entry.STATIC.BREAK;\n                    }\n                    Ntry.dispatchEvent('destroyObstacle', 1, (state) => {});\n                    Ntry.dispatchEvent('destroyObstacle', -1, (state) => {});\n                    const callBack = function () {\n                        Ntry.dispatchEvent('startEnemyWalk', true, () => {\n                            script.isAction = false;\n                        });\n                    };\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.BOTH_SIDE, callBack);\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isContinue;\n                }\n            },\n        },\n        maze_attack_pepe: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#ef6d6a',\n            emphasizedColor: '#f29999',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/pepe.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/pinkbean_ic.png',\n                    size: 24,\n                },\n            ],\n            func(sprite, script) {\n                if (!script.isContinue) {\n                    Ntry.dispatchEvent('stopEnemyWalk');\n                    this.executor.register.isTurned = false;\n                    script.isContinue = true;\n                    script.isAction = true;\n                    const grid = $.extend(\n                        { type: Ntry.STATIC.GRID },\n                        Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID)\n                    );\n                    const backGrid = $.extend(\n                        { type: Ntry.STATIC.GRID },\n                        Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID)\n                    );\n                    Ntry.addVectorByDirection(grid, Ntry.unitComp.direction, 1);\n                    const findTile = Ntry.entityManager.find(grid, {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_PEPE,\n                    });\n                    Ntry.addVectorByDirection(backGrid, Ntry.unitComp.direction, -1);\n                    const findBackTile = Ntry.entityManager\n                        .find(backGrid)\n                        .filter((e) => e.components[Ntry.STATIC.ENEMY]);\n                    const frontEnemyExist = !!Ntry.entityManager\n                        .find(grid)\n                        .filter((e) => e.components[Ntry.STATIC.ENEMY]).length;\n                    const frontEnemyValid = !!findTile.length;\n                    const backEnemyExist = !!findBackTile.length;\n                    if (frontEnemyValid && !backEnemyExist) {\n                        // success\n                        var callBack = function () {\n                            Ntry.dispatchEvent('destroyObstacle', 1, (state) => {});\n                            Ntry.dispatchEvent('startEnemyWalk', true, () => {\n                                script.isAction = false;\n                            });\n                        };\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.PEPE, callBack);\n                    } else if (frontEnemyValid && backEnemyExist) {\n                        // attack and dead\n                        var callBack = function () {\n                            Ntry.dispatchEvent('destroyObstacle', 1, (state) => {});\n                            Ntry.dispatchEvent('startEnemyWalk', false, () => {});\n                        };\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.PEPE, callBack);\n                    } else if (backEnemyExist) {\n                        // dead\n                        if (frontEnemyExist) {\n                            Ntry.dispatchEvent('unitAction', Ntry.STATIC.PEPE_FAIL, () => {\n                                script.isAction = false;\n                            });\n                        } else {\n                            Ntry.dispatchEvent('startEnemyWalk', false, () => {});\n                        }\n                    } else {\n                        // music time\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.PEPE_FAIL, () => {\n                            script.isAction = false;\n                        });\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isContinue;\n                }\n            },\n        },\n        maze_attack_yeti: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#ef6d6a',\n            emphasizedColor: '#f29999',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/yeti.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/pinkbean_ic.png',\n                    size: 24,\n                },\n            ],\n            func(sprite, script) {\n                if (!script.isContinue) {\n                    Ntry.dispatchEvent('stopEnemyWalk');\n                    this.executor.register.isTurned = false;\n                    script.isContinue = true;\n                    script.isAction = true;\n                    const grid = $.extend(\n                        { type: Ntry.STATIC.GRID },\n                        Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID)\n                    );\n                    const backGrid = $.extend(\n                        { type: Ntry.STATIC.GRID },\n                        Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID)\n                    );\n                    Ntry.addVectorByDirection(grid, Ntry.unitComp.direction, 1);\n                    const findTile = Ntry.entityManager.find(grid, {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_YETI,\n                    });\n                    Ntry.addVectorByDirection(backGrid, Ntry.unitComp.direction, -1);\n                    const findBackTile = Ntry.entityManager\n                        .find(backGrid)\n                        .filter((e) => e.components[Ntry.STATIC.ENEMY]);\n                    const frontEnemyExist = !!Ntry.entityManager\n                        .find(grid)\n                        .filter((e) => e.components[Ntry.STATIC.ENEMY]).length;\n                    const frontEnemyValid = !!findTile.length;\n                    const backEnemyExist = !!findBackTile.length;\n                    if (frontEnemyValid && !backEnemyExist) {\n                        // success\n                        var callBack = function () {\n                            Ntry.dispatchEvent('destroyObstacle', 1, (state) => {});\n                            Ntry.dispatchEvent('startEnemyWalk', true, () => {\n                                script.isAction = false;\n                            });\n                        };\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.PEPE, callBack);\n                    } else if (frontEnemyValid && backEnemyExist) {\n                        // attack and dead\n                        var callBack = function () {\n                            Ntry.dispatchEvent('destroyObstacle', 1, (state) => {});\n                            Ntry.dispatchEvent('startEnemyWalk', false, () => {});\n                        };\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.PEPE, callBack);\n                    } else if (backEnemyExist) {\n                        // dead\n                        if (frontEnemyExist) {\n                            Ntry.dispatchEvent('unitAction', Ntry.STATIC.YETI_FAIL, () => {\n                                script.isAction = false;\n                            });\n                        } else {\n                            Ntry.dispatchEvent('startEnemyWalk', false, () => {});\n                        }\n                    } else {\n                        // music time\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.YETI_FAIL, () => {\n                            script.isAction = false;\n                        });\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isContinue;\n                }\n            },\n        },\n        maze_attack_mushroom: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#ef6d6a',\n            emphasizedColor: '#f29999',\n            syntax: ['Scope', 'both_side'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/mushroom.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/pinkbean_ic.png',\n                    size: 24,\n                },\n            ],\n            func(sprite, script) {\n                if (!script.isContinue) {\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                    let unitId;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                    });\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_MUSHROOM],\n                        1\n                    );\n                    script.isContinue = true;\n                    script.isAction = true;\n                    if (!isCollisionPossible) {\n                        Ntry.dispatchEvent(\n                            'unitAction',\n                            Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT,\n                            () => {\n                                script.isAction = false;\n                            }\n                        );\n                        return Entry.STATIC.BREAK;\n                    }\n                    const callBack = function () {\n                        Ntry.dispatchEvent('destroyObstacle', 1, (state) => {\n                            script.isAction = false;\n                        });\n                    };\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.ATTACK_MUSHROOM, callBack);\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isContinue;\n                }\n            },\n        },\n        maze_attack_peti: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#ef6d6a',\n            emphasizedColor: '#f29999',\n            syntax: ['Scope', 'both_side'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/bigYeti.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/pinkbean_ic.png',\n                    size: 24,\n                },\n            ],\n            func(sprite, script) {\n                if (!script.isContinue) {\n                    Ntry.dispatchEvent('stopEnemyWalk');\n                    this.executor.register.isTurned = false;\n                    script.isContinue = true;\n                    script.isAction = true;\n                    const grid = $.extend(\n                        { type: Ntry.STATIC.GRID },\n                        Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID)\n                    );\n                    const backGrid = $.extend(\n                        { type: Ntry.STATIC.GRID },\n                        Ntry.entityManager.getComponent(Ntry.unit.id, Ntry.STATIC.GRID)\n                    );\n                    Ntry.addVectorByDirection(grid, Ntry.unitComp.direction, 1);\n                    const findTile = Ntry.entityManager.find(grid, {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_PETI,\n                    });\n                    Ntry.addVectorByDirection(backGrid, Ntry.unitComp.direction, -1);\n                    const findBackTile = Ntry.entityManager\n                        .find(backGrid)\n                        .filter((e) => e.components[Ntry.STATIC.ENEMY]);\n                    const frontEnemyExist = !!Ntry.entityManager\n                        .find(grid)\n                        .filter((e) => e.components[Ntry.STATIC.ENEMY]).length;\n                    const frontEnemyValid = !!findTile.length;\n                    const backEnemyExist = !!findBackTile.length;\n                    if (frontEnemyValid && !backEnemyExist) {\n                        // success\n                        Ntry.dispatchEvent('destroyObstacle', 1, (state) => {});\n                        var callBack = function () {\n                            Ntry.dispatchEvent('startEnemyWalk', true, () => {\n                                script.isAction = false;\n                            });\n                        };\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.PETI, callBack);\n                    } else if (frontEnemyValid && backEnemyExist) {\n                        // attack and dead\n                        Ntry.dispatchEvent('destroyObstacle', 1, (state) => {});\n                        var callBack = function () {\n                            Ntry.dispatchEvent('startEnemyWalk', false, () => {});\n                        };\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.PETI, callBack);\n                    } else if (backEnemyExist) {\n                        // dead\n                        if (frontEnemyExist) {\n                            Ntry.dispatchEvent('unitAction', Ntry.STATIC.PETI_FAIL, () => {\n                                script.isAction = false;\n                            });\n                        } else {\n                            Ntry.dispatchEvent('startEnemyWalk', false, () => {});\n                        }\n                    } else {\n                        // music time\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.PETI_FAIL, () => {\n                            script.isAction = false;\n                        });\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isContinue;\n                }\n            },\n        },\n        maze_eat_item: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#b2521d',\n            emphasizedColor: '#9BDB40',\n            syntax: ['Scope', 'item'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/eat.png',\n                    size: 24,\n                },\n            ],\n            func(sprite, script) {\n                if (!script.isContinue) {\n                    script.isContinue = true;\n                    script.isAction = true;\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                    let unitId;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                    });\n                    const callBack = function () {\n                        script.isAction = false;\n                    };\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const meatEntity = Ntry.checkTileByGrid(unitGrid, Ntry.STATIC.MEAT);\n                    if (!meatEntity || meatEntity.components[Ntry.STATIC.ITEM].isEaten) {\n                        Ntry.dispatchEvent('unitAction', Ntry.STATIC.NOT_FOUND_MEAT, callBack);\n                        return Entry.STATIC.BREAK;\n                    }\n                    Ntry.dispatchEvent('unlockItem');\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.EAT, callBack);\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isContinue;\n                }\n            },\n        },\n        maze_rotate_left: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'left'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/turnL.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.TURN_LEFT, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_rotate_right: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/turnR.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callBack = function () {\n                        self.isAction = false;\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.TURN_RIGHT, callBack);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_moon_kick: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#2EB0E8',\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/sprite/moon_icon.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                    let unitId;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                    });\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_BRICK],\n                        1\n                    );\n\n                    if (!isCollisionPossible) {\n                        Ntry.dispatchEvent('playSound', Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        Ntry.dispatchEvent('complete', false, Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        return;\n                    }\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const self = this;\n                    const callback = function () {\n                        Ntry.dispatchEvent('destroyObstacle', 1, (state) => {\n                            switch (state) {\n                                case Ntry.STATIC.OBSTACLE_DESTROY_SUCCESS:\n                                    self.isAction = false;\n                                    break;\n                            }\n                        });\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.ATTACK, callback);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_cony_flower_throw: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#D8617D',\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/sprite/cony_icon.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                const self = this;\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                    let unitId;\n                    let components;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                        components = entity.components;\n                    });\n\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_SPIDER]\n                    );\n                    let particleZIndex = 550;\n                    if (unitComp.direction === Ntry.STATIC.NORTH) {\n                        particleZIndex = 450;\n                    }\n                    if (!isCollisionPossible) {\n                        Ntry.dispatchEvent('playSound', Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        Ntry.dispatchEvent('complete', false, Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        return;\n                    }\n\n                    const particle = Ntry.entityManager.addEntity();\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.ATTACK, () => {\n                        $.each(components, (type, component) => {\n                            if (+type === Ntry.STATIC.SPRITE) {\n                                const cloneComponent = $.extend({}, component);\n                                cloneComponent.zIndex = particleZIndex;\n                                Ntry.entityManager.addComponent(particle.id, cloneComponent);\n                            } else if (+type != Ntry.STATIC.UNIT) {\n                                Ntry.entityManager.addComponent(particle.id, component);\n                            } else {\n                                Ntry.entityManager.addComponent(particle.id, {\n                                    type: Ntry.STATIC.PARTICLE,\n                                    direction: component.direction,\n                                    collisionList: [Ntry.STATIC.OBSTACLE_SPIDER],\n                                });\n                            }\n                        });\n                        Ntry.dispatchEvent('particleAction', {\n                            entityId: particle.id,\n                            actionType: Ntry.STATIC.FLOWER_ATTACK,\n                            callback() {\n                                Ntry.entityManager.removeEntity(particle.id);\n                                self.isAction = false;\n                            },\n                        });\n                    });\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_cony_flower_throw2: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#D8617D',\n            template: Lang.template.maze_cony_flower_throw,\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/sprite/cony_icon.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                const self = this;\n                if (!this.isContinue) {\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                    let unitId;\n                    let components;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                        components = entity.components;\n                    });\n\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_ENERMY5, Ntry.STATIC.OBSTACLE_ENERMY4],\n                        2\n                    );\n                    let particleZIndex = 550;\n                    if (unitComp.direction === Ntry.STATIC.NORTH) {\n                        particleZIndex = 450;\n                    }\n                    if (!isCollisionPossible) {\n                        Ntry.dispatchEvent('playSound', Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        Ntry.dispatchEvent('complete', false, Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        return;\n                    }\n\n                    this.isContinue = true;\n                    this.isAction = true;\n\n                    const particle = Ntry.entityManager.addEntity();\n\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.ATTACK, () => {\n                        $.each(components, (type, component) => {\n                            if (+type === Ntry.STATIC.SPRITE) {\n                                const cloneComponent = $.extend({}, component);\n                                cloneComponent.zIndex = particleZIndex;\n                                Ntry.entityManager.addComponent(particle.id, cloneComponent);\n                            } else if (+type != Ntry.STATIC.UNIT) {\n                                Ntry.entityManager.addComponent(particle.id, component);\n                            } else {\n                                Ntry.entityManager.addComponent(particle.id, {\n                                    type: Ntry.STATIC.PARTICLE,\n                                    direction: component.direction,\n                                    collisionList: [\n                                        Ntry.STATIC.OBSTACLE_ENERMY5,\n                                        Ntry.STATIC.OBSTACLE_ENERMY4,\n                                    ],\n                                    penetrationList: [Ntry.STATIC.WALL],\n                                });\n                            }\n                        });\n\n                        Ntry.dispatchEvent('particleAction', {\n                            entityId: particle.id,\n                            actionType: Ntry.STATIC.HEART_ATTACK,\n                            callback() {\n                                Ntry.entityManager.removeEntity(particle.id);\n                                self.isAction = false;\n                            },\n                        });\n                    });\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_james_heart: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#D39D18',\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/sprite/james_icon.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                const self = this;\n                if (!this.isContinue) {\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                    let unitId;\n                    let components;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                        components = entity.components;\n                    });\n\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [\n                            Ntry.STATIC.OBSTACLE_ENERMY1,\n                            Ntry.STATIC.OBSTACLE_ENERMY2,\n                            Ntry.STATIC.OBSTACLE_ENERMY3,\n                            Ntry.STATIC.OBSTACLE_ENERMY5,\n                        ]\n                    );\n                    let particleZIndex = 550;\n                    if (unitComp.direction === Ntry.STATIC.NORTH) {\n                        particleZIndex = 450;\n                    }\n                    if (!isCollisionPossible) {\n                        Ntry.dispatchEvent('playSound', Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        Ntry.dispatchEvent('complete', false, Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        return;\n                    }\n\n                    this.isContinue = true;\n                    this.isAction = true;\n\n                    const particle = Ntry.entityManager.addEntity();\n\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.ATTACK, () => {\n                        $.each(components, (type, component) => {\n                            if (+type === Ntry.STATIC.SPRITE) {\n                                const cloneComponent = $.extend({}, component);\n                                cloneComponent.zIndex = particleZIndex;\n                                Ntry.entityManager.addComponent(particle.id, cloneComponent);\n                            } else if (+type != Ntry.STATIC.UNIT) {\n                                Ntry.entityManager.addComponent(particle.id, component);\n                            } else {\n                                Ntry.entityManager.addComponent(particle.id, {\n                                    type: Ntry.STATIC.PARTICLE,\n                                    direction: component.direction,\n                                    collisionList: [\n                                        Ntry.STATIC.OBSTACLE_ENERMY1,\n                                        Ntry.STATIC.OBSTACLE_ENERMY2,\n                                        Ntry.STATIC.OBSTACLE_ENERMY3,\n                                        Ntry.STATIC.OBSTACLE_ENERMY5,\n                                    ],\n                                });\n                            }\n                        });\n\n                        Ntry.dispatchEvent('particleAction', {\n                            entityId: particle.id,\n                            actionType: Ntry.STATIC.HEART_ATTACK,\n                            callback() {\n                                Ntry.entityManager.removeEntity(particle.id);\n                                self.isAction = false;\n                            },\n                        });\n                    });\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_james_heart2: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#D39D18',\n            template: Lang.template.maze_james_heart,\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/sprite/james_icon.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                const self = this;\n                if (!this.isContinue) {\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                    let unitId;\n                    let components;\n                    $.each(entities, (id, entity) => {\n                        unitId = id;\n                        components = entity.components;\n                    });\n\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_ENERMY3, Ntry.STATIC.OBSTACLE_ENERMY4],\n                        2\n                    );\n                    let particleZIndex = 550;\n                    if (unitComp.direction === Ntry.STATIC.NORTH) {\n                        particleZIndex = 450;\n                    }\n                    if (!isCollisionPossible) {\n                        Ntry.dispatchEvent('playSound', Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        Ntry.dispatchEvent('complete', false, Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        return;\n                    }\n\n                    this.isContinue = true;\n                    this.isAction = true;\n\n                    const particle = Ntry.entityManager.addEntity();\n\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.ATTACK, () => {\n                        $.each(components, (type, component) => {\n                            if (+type === Ntry.STATIC.SPRITE) {\n                                const cloneComponent = $.extend({}, component);\n                                cloneComponent.zIndex = particleZIndex;\n                                Ntry.entityManager.addComponent(particle.id, cloneComponent);\n                            } else if (+type != Ntry.STATIC.UNIT) {\n                                Ntry.entityManager.addComponent(particle.id, component);\n                            } else {\n                                Ntry.entityManager.addComponent(particle.id, {\n                                    type: Ntry.STATIC.PARTICLE,\n                                    direction: component.direction,\n                                    collisionList: [\n                                        Ntry.STATIC.OBSTACLE_ENERMY3,\n                                        Ntry.STATIC.OBSTACLE_ENERMY4,\n                                        Ntry.STATIC.OBSTACLE_ENERMY_AREA,\n                                    ],\n                                    penetrationList: [Ntry.STATIC.OBSTACLE_ENERMY_AREA],\n                                });\n                            }\n                        });\n\n                        Ntry.dispatchEvent('particleAction', {\n                            entityId: particle.id,\n                            actionType: Ntry.STATIC.HEART_ATTACK,\n                            callback() {\n                                Ntry.entityManager.removeEntity(particle.id);\n                                self.isAction = false;\n                            },\n                        });\n                    });\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_iron_switch: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#748d69',\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/sprite/iron_icon.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    this.isContinue = true;\n                    this.isAction = true;\n                    const eventCount = 0;\n                    const self = this;\n                    const gridSize = Ntry.configManager.getConfig('gridSize');\n                    const tileSize = Ntry.configManager.getConfig('tileSize').width;\n                    const entities = Ntry.entityManager.getEntitiesByComponent(\n                        Ntry.STATIC.OBSTACLE\n                    );\n\n                    for (const id in entities) {\n                        const obstacleComp = Ntry.entityManager.getComponent(\n                            id,\n                            Ntry.STATIC.OBSTACLE\n                        );\n                        if (obstacleComp.tileType === Ntry.STATIC.OBSTACLE_IRON) {\n                            const obstacleGrid = Ntry.entityManager.getComponent(\n                                id,\n                                Ntry.STATIC.GRID\n                            );\n                            const grid = {\n                                x: obstacleGrid.x,\n                                y: obstacleGrid.y === 1 ? 3 : 1,\n                            };\n\n                            obstacleGrid.y = obstacleGrid.y === 1 ? 3 : 1;\n\n                            let deltaY = tileSize * 2;\n\n                            if (obstacleGrid.y === 1) {\n                                deltaY = -deltaY;\n                            }\n\n                            const deltaPos = {\n                                x: 0,\n                                y: deltaY * 0.5,\n                            };\n\n                            const deltaPos2 = {\n                                x: 0,\n                                y: deltaY,\n                            };\n\n                            const targetPos = {\n                                minY: 0,\n                                maxY: gridSize.height * tileSize,\n                            };\n\n                            if (deltaY > 0) {\n                                targetPos.maxY = obstacleGrid.y * tileSize + tileSize / 2;\n                            } else {\n                                targetPos.minY = obstacleGrid.y * tileSize + tileSize / 2;\n                            }\n\n                            (function (_id, _deltaPos, _deltaPos2, _targetPos, obstacleGrid) {\n                                const comp = Ntry.entityManager.getComponent(\n                                    _id,\n                                    Ntry.STATIC.ANIMATE\n                                );\n                                if (comp) {\n                                    if (eventCount === 0) {\n                                        self.isAction = false;\n                                    }\n                                    Ntry.entityManager.addComponent(_id, {\n                                        type: Ntry.STATIC.ANIMATE,\n                                        animateType: Ntry.STATIC.TRANSITION,\n                                        duration: 20,\n                                        option: {\n                                            deltaPos: _deltaPos2,\n                                            targetPos: _targetPos,\n                                        },\n                                        afterAnimate() {\n                                            const unitGrid = Ntry.getUtilGrid();\n\n                                            if (\n                                                obstacleGrid.x == unitGrid.x &&\n                                                obstacleGrid.y == unitGrid.y\n                                            ) {\n                                                Ntry.dispatchEvent(\n                                                    'unitAction',\n                                                    Ntry.STATIC.CONTACT_IRON2\n                                                );\n                                            }\n                                        },\n                                    });\n                                } else {\n                                    Ntry.entityManager.addComponent(_id, {\n                                        type: Ntry.STATIC.ANIMATE,\n                                        animateType: Ntry.STATIC.TRANSITION,\n                                        duration: 10,\n                                        option: {\n                                            deltaPos: _deltaPos,\n                                        },\n                                        afterAnimate() {\n                                            if (eventCount === 0) {\n                                                self.isAction = false;\n                                            }\n                                            Ntry.entityManager.addComponent(_id, {\n                                                type: Ntry.STATIC.ANIMATE,\n                                                animateType: Ntry.STATIC.TRANSITION,\n                                                duration: 10,\n                                                option: {\n                                                    deltaPos: _deltaPos,\n                                                    targetPos: _targetPos,\n                                                },\n                                                afterAnimate() {\n                                                    const unitGrid = Ntry.getUtilGrid();\n\n                                                    if (\n                                                        obstacleGrid.x == unitGrid.x &&\n                                                        obstacleGrid.y == unitGrid.y\n                                                    ) {\n                                                        Ntry.dispatchEvent(\n                                                            'unitAction',\n                                                            Ntry.STATIC.CONTACT_IRON2\n                                                        );\n                                                    }\n                                                },\n                                            });\n                                        },\n                                    });\n                                }\n                            })(id, deltaPos, deltaPos2, targetPos, obstacleGrid);\n                        }\n                    }\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_brown_punch: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#6C483A',\n            syntax: ['Scope', 'right'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/sprite/brown_icon.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                if (!this.isContinue) {\n                    const self = this;\n                    const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                    let unitId;\n                    $.each(entities, (id) => {\n                        unitId = id;\n                    });\n                    const unitComp = Ntry.entityManager.getComponent(unitId, Ntry.STATIC.UNIT);\n                    const unitGrid = $.extend(\n                        {},\n                        Ntry.entityManager.getComponent(unitId, Ntry.STATIC.GRID)\n                    );\n                    const isCollisionPossible = Ntry.checkCollisionTile(\n                        unitGrid,\n                        unitComp.direction,\n                        [Ntry.STATIC.OBSTACLE_ICE],\n                        1\n                    );\n\n                    if (!isCollisionPossible) {\n                        Ntry.dispatchEvent('playSound', Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        Ntry.dispatchEvent('complete', false, Ntry.STATIC.NOT_FOUND_DESTORY_OBJECT);\n                        return;\n                    }\n                    this.isContinue = true;\n                    this.isAction = true;\n\n                    const callback = function () {\n                        Ntry.dispatchEvent('destroyObstacle', 1, (state) => {\n                            switch (state) {\n                                case Ntry.STATIC.OBSTACLE_DESTROY_SUCCESS:\n                                    self.isAction = false;\n                                    break;\n                            }\n                        });\n                    };\n\n                    // turn direction\n                    Ntry.dispatchEvent('unitAction', Ntry.STATIC.ATTACK, callback);\n\n                    return Entry.STATIC.BREAK;\n                } else if (this.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete this.isAction;\n                    delete this.isContinue;\n                }\n            },\n        },\n        maze_repeat_until_3: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicWhile', 'true'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/tile_goal_01.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                let isGoal = false;\n                const statement = this.block.statements[0];\n                if (statement.getBlocks().length === 0) {\n                    return;\n                }\n\n                var entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                var entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n\n                if (unitComp.isStartedUnit) {\n                    const unitGrid = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                    var entities = Ntry.entityManager.getEntitiesByGrid(unitGrid.x, unitGrid.y);\n\n                    for (const idx in entities) {\n                        var entity = entities[idx];\n                        const tile = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.TILE);\n                        const item = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.ITEM);\n\n                        if (\n                            tile &&\n                            item &&\n                            tile.tileType === Ntry.STATIC.GOAL &&\n                            Ntry.STATIC.GOAL_ITEM_LIST.indexOf(item.itemType) > -1\n                        ) {\n                            isGoal = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (!isGoal) {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_repeat_until_4: {\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/tile_goal_02.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_5: {\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/tile_goal_03.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_6: {\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-1.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_7: {\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-4.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_8: {\n            template: Lang.template.maze_repeat_until_7,\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-5.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_9: {\n            template: Lang.template.maze_repeat_until_7,\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-6.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_10: {\n            template: Lang.template.maze_repeat_until_7,\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-7.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_11: {\n            template: Lang.template.maze_repeat_until_7,\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-9.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_12: {\n            template: Lang.template.maze_repeat_until_7,\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-10.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_13: {\n            template: Lang.template.maze_repeat_until_7,\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-11.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_14: {\n            template: Lang.template.maze_repeat_until_7,\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/blcok-12.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_15: {\n            template: Lang.template.maze_repeat_until_7,\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/bitmap/ws/tile_goal_04.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_repeat_until_goal: {\n            parent: 'maze_repeat_until_3',\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n        },\n        maze_radar_check: {\n            skeleton: 'basic_boolean_field',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Menus.maze_distance1, '1'],\n                        [Lang.Menus.maze_distance2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Menus.maze_object_trap, 'TRAP'],\n                        [Lang.Menus.maze_object_monster, 'MONSTER'],\n                        [Lang.Menus.maze_object_obstacle1, 'OBSTACLE'],\n                    ],\n                    value: 'TRAP',\n                    fontSize: 11,\n                },\n            ],\n            paramsKeyMap: {\n                DISTANCE: 0,\n                TYPE: 1,\n            },\n            func(sprite, script) {\n                const distance = script.getNumberField('DISTANCE', script);\n                const type = script.getField('TYPE', script);\n\n                const entityId = Ntry.getRadarEntityIdByDistance(distance);\n                let tileType;\n                if (entityId) {\n                    const tileComp = Ntry.entityManager.getComponent(entityId, Ntry.STATIC.TILE);\n                    switch (tileComp.tileType) {\n                        case Ntry.STATIC.OBSTACLE_HOLE:\n                            tileType = 'TRAP';\n                            break;\n                        case Ntry.STATIC.OBSTACLE_ENERMY1:\n                        case Ntry.STATIC.OBSTACLE_ENERMY2:\n                        case Ntry.STATIC.OBSTACLE_ENERMY3:\n                        case Ntry.STATIC.OBSTACLE_ENERMY4:\n                        case Ntry.STATIC.OBSTACLE_ENERMY5:\n                            tileType = 'MONSTER';\n                            break;\n                        case Ntry.STATIC.OBSTACLE_IRON:\n                            tileType = 'OBSTACLE';\n                            break;\n                    }\n                } else {\n                    tileType = 'TRAP';\n                }\n\n                if (type === tileType) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n        // TODO: 해당 부분 수정 필요\n        maze_step_if_5: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'front == bee'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/ntry/bitmap/maze2/obstacle_01.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_BEE,\n                    }\n                );\n\n                this.isContinue = true;\n\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        // TODO: 해당 부분 수정 필요\n        maze_step_if_6: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'front == bee'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/maze/bitmap/stage4/road_4_01.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.ROAD,\n                    }\n                );\n\n                this.isContinue = true;\n\n                const statement = this.block.statements[0];\n                if (fitEntities.length > 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        // TODO: 해당 부분 수정 필요\n        maze_step_if_7: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'front == ice'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '../../../img/assets/maze/bitmap/stage4/obj_ice_01.png',\n                    size: 18,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_ICE,\n                    }\n                );\n\n                this.isContinue = true;\n\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_step_if_8: {\n            parent: '_if',\n            class: '',\n            syntax: { js: [], py: [] },\n        },\n        maze_step_if_mushroom: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'front == mushroom'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/mushroom.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_MUSHROOM,\n                    }\n                );\n                this.isContinue = true;\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_step_if_lupin: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', 'front == lupin'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/lupin.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            func() {\n                if (this.isContinue) {\n                    return;\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 2);\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_LUPIN,\n                    }\n                );\n                this.isContinue = true;\n                const statement = this.block.statements[0];\n                if (fitEntities.length === 0) {\n                    return;\n                } else if (statement.getBlocks().length === 0) {\n                    return;\n                } else {\n                    this.executor.stepInto(statement);\n                    return Entry.STATIC.BREAK;\n                }\n            },\n        },\n        maze_step_if_else_road: {\n            skeleton: 'basic_double_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            statementsKeyMap: {\n                STACK_IF: 0,\n                STACK_ELSE: 1,\n            },\n            func(sprite, script) {\n                if (script.isCondition) {\n                    delete script.isCondition;\n                    return script.callReturn();\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.ROAD,\n                    }\n                );\n                script.isCondition = true;\n                if (fitEntities.length) {\n                    return script.getStatement('STACK_IF', script);\n                } else {\n                    return script.getStatement('STACK_ELSE', script);\n                }\n            },\n        },\n        maze_step_if_else_mushroom: {\n            skeleton: 'basic_double_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/mushroom.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            statementsKeyMap: {\n                STACK_IF: 0,\n                STACK_ELSE: 1,\n            },\n            func(sprite, script) {\n                if (script.isCondition) {\n                    delete script.isCondition;\n                    return script.callReturn();\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_MUSHROOM,\n                    }\n                );\n                script.isCondition = true;\n                if (fitEntities.length) {\n                    return script.getStatement('STACK_IF', script);\n                } else {\n                    return script.getStatement('STACK_ELSE', script);\n                }\n            },\n        },\n        maze_step_if_else_lupin: {\n            skeleton: 'basic_double_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/lupin.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            statementsKeyMap: {\n                STACK_IF: 0,\n                STACK_ELSE: 1,\n            },\n            func(sprite, script) {\n                if (script.isCondition) {\n                    delete script.isCondition;\n                    return script.callReturn();\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x, y: gridComp.y };\n                Ntry.addVectorByDirection(grid, unitComp.direction, 2);\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.OBSTACLE_LUPIN,\n                    }\n                );\n                script.isCondition = true;\n                if (fitEntities.length) {\n                    return script.getStatement('STACK_IF', script);\n                } else {\n                    return script.getStatement('STACK_ELSE', script);\n                }\n            },\n        },\n        maze_step_if_else_ladder: {\n            skeleton: 'basic_double_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/ic_ladder.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/if.png',\n                    size: 24,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            statementsKeyMap: {\n                STACK_IF: 0,\n                STACK_ELSE: 1,\n            },\n            func(sprite, script) {\n                if (script.isCondition) {\n                    delete script.isCondition;\n                    return script.callReturn();\n                }\n                const entities = Ntry.entityManager.getEntitiesByComponent(Ntry.STATIC.UNIT);\n                let entity;\n                for (const key in entities) {\n                    entity = entities[key];\n                }\n                const unitComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.UNIT);\n                const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                const grid = { x: gridComp.x, y: gridComp.y };\n                if (grid.y > 3) {\n                    grid.y = 2;\n                }\n                Ntry.addVectorByDirection(grid, unitComp.direction, 1);\n                const fitEntities = Ntry.entityManager.find(\n                    {\n                        type: Ntry.STATIC.GRID,\n                        x: grid.x,\n                        y: grid.y,\n                    },\n                    {\n                        type: Ntry.STATIC.TILE,\n                        tileType: Ntry.STATIC.LADDER,\n                    }\n                );\n                script.isCondition = true;\n                if (fitEntities.length) {\n                    return script.getStatement('STACK_IF', script);\n                } else {\n                    return script.getStatement('STACK_ELSE', script);\n                }\n            },\n        },\n        maze_step_if_else: {\n            parent: 'if_else',\n            class: '',\n            syntax: { js: [], py: [] },\n        },\n        test_wrapper: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.START,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'basic_boolean_field',\n                    value: [\n                        {\n                            type: 'test',\n                            params: [30, 50],\n                        },\n                    ],\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 1],\n                        [2, 2],\n                        [3, 3],\n                        [4, 4],\n                        [5, 5],\n                        [6, 6],\n                        [7, 7],\n                        [8, 8],\n                        [9, 9],\n                        [10, 10],\n                    ],\n                    value: 1,\n                },\n            ],\n        },\n        basic_button: {\n            skeleton: 'basic_button',\n            color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n            params: [\n                {\n                    type: 'Text',\n                    text: 'basic button',\n                    color: EntryStatic.colorSet.common.BUTTON,\n                    align: 'center',\n                },\n            ],\n        },\n        //endregion basic 기본\n        //region basic 기본\n        ebs_if: {\n            parent: '_if',\n            def: {\n                type: '_if',\n                params: [\n                    {\n                        type: 'reach_something',\n                        params: [null, 'wall'],\n                    },\n                ],\n            },\n            syntax: { js: [], py: [] },\n        },\n        ebs_if2: {\n            parent: '_if',\n            def: {\n                type: '_if',\n                params: [\n                    {\n                        type: 'reach_something',\n                        params: [null, 'cwz5'],\n                    },\n                ],\n            },\n            syntax: { js: [], py: [] },\n        },\n        ai_move_right: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'move'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/moveStep.png',\n                    size: 24,\n                },\n            ],\n            func(entity, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.isAction = true;\n                    Ntry.dispatchEvent('gridChange', () => {\n                        script.isAction = false;\n                    });\n                    const spaceShipComp = Ntry.entityManager.getComponent(\n                        entity.id,\n                        Ntry.STATIC.SPACE_SHIP\n                    );\n                    spaceShipComp.direction = Ntry.STATIC.EAST;\n                    const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                    Ntry.entityManager.addComponent(entity.id, {\n                        type: Ntry.STATIC.ANIMATE,\n                        animateType: Ntry.STATIC.ROTATE_TO,\n                        animateValue: 0,\n                    });\n                    gridComp.x++;\n                    return Entry.STATIC.BREAK;\n                } else if (script.isAction) {\n                    return Entry.STATIC.BREAK;\n                } else {\n                    delete script.isAction;\n                    delete script.isStart;\n                }\n            },\n        },\n        ai_move_up: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'up'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/ai_move_up.png',\n                    size: 24,\n                },\n            ],\n            func(entity, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.isAction = true;\n                    Ntry.dispatchEvent('gridChange', () => {\n                        script.isAction = false;\n                    });\n                    const spaceShipComp = Ntry.entityManager.getComponent(\n                        entity.id,\n                        Ntry.STATIC.SPACE_SHIP\n                    );\n                    spaceShipComp.direction = Ntry.STATIC.NORTH;\n                    const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                    Ntry.entityManager.addComponent(entity.id, {\n                        type: Ntry.STATIC.ANIMATE,\n                        animateType: Ntry.STATIC.ROTATE_TO,\n                        animateValue: -45,\n                    });\n                    gridComp.x++;\n                    gridComp.y--;\n                    return script;\n                } else if (script.isAction) {\n                    return script;\n                } else {\n                    delete script.isAction;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n        },\n        ai_move_down: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.MOVING,\n            syntax: ['Scope', 'down'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/ai_move_down.png',\n                    size: 24,\n                },\n            ],\n            func(entity, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.isAction = true;\n                    Ntry.dispatchEvent('gridChange', () => {\n                        script.isAction = false;\n                    });\n                    const spaceShipComp = Ntry.entityManager.getComponent(\n                        entity.id,\n                        Ntry.STATIC.SPACE_SHIP\n                    );\n                    spaceShipComp.direction = Ntry.STATIC.SOUTH;\n                    const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                    Ntry.entityManager.addComponent(entity.id, {\n                        type: Ntry.STATIC.ANIMATE,\n                        animateType: Ntry.STATIC.ROTATE_TO,\n                        animateValue: 45,\n                    });\n                    gridComp.x++;\n                    gridComp.y++;\n                    return script;\n                } else if (script.isAction) {\n                    return script;\n                } else {\n                    delete script.isAction;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n        },\n        ai_repeat_until_reach: {\n            skeleton: 'basic_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicWhile', 'true'],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n            ],\n            func() {\n                const statement = this.block.statements[0];\n                if (statement.getBlocks().length === 0) {\n                    return;\n                }\n\n                return this.executor.stepInto(statement);\n            },\n        },\n        ai_if_else_1: {\n            skeleton: 'basic_double_loop',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.default.FLOW,\n            syntax: ['BasicIf', \"front == 'stone'\"],\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/ntry/bitmap/ai/obstacle_1.png',\n                    size: 24,\n                },\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/for.png',\n                    size: 24,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            func(entity, script) {\n                if (script.isLooped) {\n                    delete script.isLooped;\n                    return script.callReturn();\n                }\n                const radar = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.RADAR);\n\n                const statements = this.block.statements;\n                let index = 1;\n                script.isLooped = true;\n                if (radar.center.type == Ntry.STATIC.AI_METEO && radar.center.distance == 1) {\n                    index = 0;\n                }\n                this.executor.stepInto(statements[index]);\n                return Entry.STATIC.BREAK;\n            },\n        },\n        ai_boolean_distance: {\n            skeleton: 'basic_boolean_field',\n            mode: 'maze',\n            color: '#2fc9f0',\n            fontColor: EntryStatic.colorSet.common.WHITE,\n            syntax: ['Scope', 'radar_%1 %2 %3#'],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Menus.ai_above, 'UP'],\n                        [Lang.Menus.ai_front, 'RIGHT'],\n                        [Lang.Menus.ai_under, 'DOWN'],\n                    ],\n                    value: 'RIGHT',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['>', 'BIGGER'],\n                        ['>=', 'BIGGER_EQUAL'],\n                        ['=', 'EQUAL'],\n                        ['<', 'SMALLER'],\n                        ['<=', 'SMALLER_EQUAL'],\n                    ],\n                    value: 'BIGGER',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            func(entity) {\n                const radar = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.RADAR);\n\n                const params = this.block.params;\n\n                const direction = params[0];\n                const operator = params[1];\n                const value = this.getParam(2);\n\n                let radarValue;\n                switch (direction) {\n                    case 'UP':\n                        radarValue = radar.left;\n                        break;\n                    case 'RIGHT':\n                        radarValue = radar.center;\n                        break;\n                    case 'DOWN':\n                        radarValue = radar.right;\n                        break;\n                }\n                if (radarValue.type == Ntry.STATIC.AI_GOAL) {\n                    radarValue = Number.MAX_VALUE;\n                } else {\n                    radarValue = radarValue.distance;\n                }\n\n                switch (operator) {\n                    case 'BIGGER':\n                        return radarValue > value;\n                    case 'BIGGER_EQUAL':\n                        return radarValue >= value;\n                    case 'EQUAL':\n                        return radarValue == value;\n                    case 'SMALLER':\n                        return radarValue < value;\n                    case 'SMALLER_EQUAL':\n                        return radarValue <= value;\n                }\n            },\n        },\n        ai_distance_value: {\n            skeleton: 'basic_string_field',\n            mode: 'maze',\n            color: EntryStatic.colorSet.block.lighten.CALC,\n            syntax: ['Scope', 'radar_%1#'],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Menus.ai_above, 'UP'],\n                        [Lang.Menus.ai_front, 'RIGHT'],\n                        [Lang.Menus.ai_under, 'DOWN'],\n                    ],\n                    value: 'RIGHT',\n                    fontSize: 11,\n                },\n            ],\n            func(entity, script) {\n                const radar = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.RADAR);\n                let radarValue = {};\n                switch (this.block.params[0]) {\n                    case 'UP':\n                        radarValue = radar.left;\n                        break;\n                    case 'RIGHT':\n                        radarValue = radar.center;\n                        break;\n                    case 'DOWN':\n                        radarValue = radar.right;\n                        break;\n                }\n                return radarValue.type == Ntry.STATIC.AI_GOAL\n                    ? Number.MAX_VALUE\n                    : radarValue.distance;\n            },\n        },\n        ai_boolean_object: {\n            skeleton: 'basic_boolean_field',\n            fontColor: EntryStatic.colorSet.common.WHITE,\n            mode: 'maze',\n            color: '#2fc9f0',\n            syntax: ['Scope', 'object_%1 == %2#'],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Menus.ai_above, 'UP'],\n                        [Lang.Menus.ai_front, 'RIGHT'],\n                        [Lang.Menus.ai_under, 'DOWN'],\n                    ],\n                    value: 'RIGHT',\n                    fontSize: 11,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Menus.asteroids, 'OBSTACLE'],\n                        [Lang.Menus.wall, 'WALL'],\n                        [Lang.Menus.item, 'ITEM'],\n                    ],\n                    value: 'OBSTACLE',\n                    fontSize: 11,\n                },\n            ],\n            func(entity) {\n                const radar = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.RADAR);\n\n                const params = this.block.params;\n\n                let radarValue;\n                switch (params[0]) {\n                    case 'UP':\n                        radarValue = radar.left.type;\n                        break;\n                    case 'RIGHT':\n                        radarValue = radar.center.type;\n                        break;\n                    case 'DOWN':\n                        radarValue = radar.right.type;\n                        break;\n                }\n                switch (params[1]) {\n                    case 'OBSTACLE':\n                        return radarValue == Ntry.STATIC.AI_METEO;\n                    case 'WALL':\n                        return radarValue == Ntry.STATIC.AI_WALL;\n                    case 'ITEM':\n                        return radarValue == Ntry.STATIC.AI_ITEM;\n                }\n            },\n        },\n        ai_use_item: {\n            skeleton: 'basic',\n            mode: 'maze',\n            color: '#EACF11',\n            syntax: ['Scope', 'use_item'],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/week/blocks/item.png',\n                    size: 24,\n                },\n            ],\n            func(entity, script) {\n                if (!script.isStart) {\n                    Ntry.dispatchEvent('triggerWeapon');\n                    script.isStart = true;\n                    script.isAction = true;\n                    Ntry.dispatchEvent('gridChange', () => {\n                        script.isAction = false;\n                    });\n                    const spaceShipComp = Ntry.entityManager.getComponent(\n                        entity.id,\n                        Ntry.STATIC.SPACE_SHIP\n                    );\n                    spaceShipComp.direction = Ntry.STATIC.EAST;\n                    const gridComp = Ntry.entityManager.getComponent(entity.id, Ntry.STATIC.GRID);\n                    Ntry.entityManager.addComponent(entity.id, {\n                        type: Ntry.STATIC.ANIMATE,\n                        animateType: Ntry.STATIC.ROTATE_TO,\n                        animateValue: 0,\n                    });\n                    gridComp.x++;\n                    return script;\n                } else if (script.isAction) {\n                    return script;\n                } else {\n                    delete script.isAction;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n        },\n        ai_boolean_and: {\n            color: '#2fc9f0',\n            skeleton: 'basic_boolean_field',\n            fontColor: EntryStatic.colorSet.common.WHITE,\n            statements: [],\n            syntax: ['Scope', '%1 && %3#'],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.JUDGEMENT_boolean_and,\n                    color: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n            ],\n            events: {},\n            func() {\n                return this.getParam(0) && this.getParam(2);\n            },\n        },\n        ai_True: {\n            color: '#2fc9f0',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.JUDGEMENT_true,\n                    color: '#3D3D3D',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'True',\n            },\n            func() {\n                return true;\n            },\n            isPrimitive: true,\n        },\n        ai_if_else: {\n            color: EntryStatic.colorSet.block.default.FLOW,\n            skeleton: 'basic_double_loop',\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/if.png',\n                    size: 12,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            func(sprite, script) {\n                if (script.isCondition) {\n                    delete script.isCondition;\n                    return script.callReturn();\n                }\n                const value = this.getParam(0);\n                script.isCondition = true;\n                const statement = this.block.statements[value ? 0 : 1];\n                //no blocks end execute\n                if (statement.getBlocks().length === 0) {\n                    return this.executor.end();\n                } else {\n                    return this.executor.stepInto(statement);\n                }\n            },\n            syntax: ['BasicIf', 'true'],\n        },\n        //endregion basic 기본\n        //region basic 기본\n        hidden: {\n            color: EntryStatic.colorSet.block.default.HIDDEN,\n            outerLine: EntryStatic.colorSet.block.darken.HIDDEN,\n            skeleton: 'basic',\n            template: '         %1       %2',\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: '?',\n                    clearBG: true,\n                    color: 'white',\n                    fontSize: 12,\n                },\n                {\n                    type: 'Indicator',\n                    color: '#6B6B6B',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hidden',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'etc',\n            isNotFor: [],\n            func() {},\n        },\n        hidden_event: {\n            color: EntryStatic.colorSet.block.default.HIDDEN,\n            outerLine: EntryStatic.colorSet.block.darken.HIDDEN,\n            skeleton: 'basic_event',\n            template: '         %1       ',\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: '?',\n                    clearBG: true,\n                    color: 'white',\n                    fontSize: 12,\n                },\n                {\n                    type: 'Indicator',\n                    color: '#6B6B6B',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hidden_event',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'etc',\n            isNotFor: [],\n            func() {},\n        },\n        hidden_loop: {\n            color: EntryStatic.colorSet.block.default.HIDDEN,\n            outerLine: EntryStatic.colorSet.block.darken.HIDDEN,\n            skeleton: 'basic_loop',\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            params: [\n                {\n                    type: 'Image',\n                    img: '/img/assets/maze/icon/group.png',\n                    size: {\n                        width: 47,\n                        height: 20,\n                    },\n                },\n                {\n                    type: 'Indicator',\n                    color: '#6B6B6B',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hidden_if',\n            },\n            class: 'etc',\n            isNotFor: [],\n            func() {},\n        },\n        hidden_loop2: {\n            color: EntryStatic.colorSet.block.default.HIDDEN,\n            outerLine: EntryStatic.colorSet.block.darken.HIDDEN,\n            skeleton: 'basic_loop',\n            template: '         %1       ',\n            statements: [\n                {\n                    accept: 'basic',\n                },\n            ],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: '?',\n                    clearBG: true,\n                    color: 'white',\n                    fontSize: 12,\n                },\n                {\n                    type: 'Indicator',\n                    color: '#6B6B6B',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hidden_loop2',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'etc',\n            isNotFor: [],\n            func() {},\n        },\n        hidden_if_else: {\n            color: EntryStatic.colorSet.block.default.HIDDEN,\n            outerLine: EntryStatic.colorSet.block.darken.HIDDEN,\n            skeleton: 'basic_double_loop',\n            template: '         %1       %2%3',\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: '?',\n                    clearBG: true,\n                    color: 'white',\n                    fontSize: 12,\n                },\n                {\n                    type: 'Indicator',\n                    color: '#6B6B6B',\n                    size: 12,\n                },\n                {\n                    type: 'LineBreak',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hidden_if',\n            },\n            class: 'etc',\n            isNotFor: [],\n            func() {},\n        },\n        hidden_if_else2: {\n            color: EntryStatic.colorSet.block.default.HIDDEN,\n            outerLine: EntryStatic.colorSet.block.darken.HIDDEN,\n            skeleton: 'basic_double_loop',\n            template: '         %1       %2%3      %4       ',\n            statements: [\n                {\n                    accept: 'basic',\n                },\n                {\n                    accept: 'basic',\n                },\n            ],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: '?',\n                    clearBG: true,\n                    color: 'white',\n                    fontSize: 12,\n                },\n                {\n                    type: 'Indicator',\n                    color: '#6B6B6B',\n                    size: 12,\n                },\n                {\n                    type: 'LineBreak',\n                },\n                {\n                    type: 'TextInput',\n                    value: '?',\n                    clearBG: true,\n                    color: 'white',\n                    fontSize: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hidden_if_else2',\n            },\n            class: 'etc',\n            isNotFor: [],\n            func() {},\n        },\n        hidden_string: {\n            color: EntryStatic.colorSet.block.default.HIDDEN,\n            outerLine: EntryStatic.colorSet.block.darken.HIDDEN,\n            skeleton: 'basic_string_field',\n            template: '    %1    ',\n            fontColor: EntryStatic.colorSet.common.WHITE,\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: '?',\n                    clearBG: true,\n                    color: 'white',\n                    fontSize: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'hidden_string',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'etc',\n            isNotFor: [],\n            func() {},\n        },\n        hidden_boolean: {\n            color: EntryStatic.colorSet.block.default.HIDDEN,\n            outerLine: EntryStatic.colorSet.block.darken.HIDDEN,\n            skeleton: 'basic_boolean_field',\n            template: '    %1    ',\n            fontColor: EntryStatic.colorSet.common.WHITE,\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                    value: '?',\n                    clearBG: true,\n                    color: 'white',\n                    fontSize: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'hidden_boolean',\n            },\n            paramsKeyMap: {},\n            class: 'etc',\n            isNotFor: [],\n            func() {},\n        },\n        //endregion basic 기본\n        //region basic 기본\n        boolean_shell: {\n            color: EntryStatic.colorSet.block.default.JUDGE,\n            skeleton: 'basic_boolean_field',\n            template: '%1',\n            isPrimitive: true,\n            params: [\n                {\n                    type: 'Text',\n                    text: 'A',\n                    color: '#3D3D3D',\n                },\n            ],\n            func() {},\n        },\n        //endregion basic 기본\n    };\n}\n\nfunction inheritBlockSchema() {\n    for (const type in Entry.block) {\n        const block = Entry.block[type];\n        if (!block.isNotFor) {\n            block.isNotFor = [];\n        }\n        if (block.parent) {\n            const F = function () {};\n            F.prototype = Entry.block[block.parent];\n            const schema = new F();\n            schema.syntax = undefined;\n            for (const key in block) {\n                schema[key] = block[key];\n            }\n            Entry.block[type] = schema;\n        }\n    }\n}\n\nfunction assignBlocks() {\n    Entry.block.converters = getConverters();\n    Entry.block.changeBlockText = function (key, text) {\n        const block = this[key];\n        if (block) {\n            block.params[0].text = text;\n        }\n    };\n    Entry.block.changeBlockEvent = function (key, event, callback) {\n        const block = this[key];\n        if (block) {\n            block.events[event] = [callback];\n        }\n    };\n    Entry.block = Object.assign(Entry.block, getBlocks(), blocks.getBlocks());\n}\n\nfunction applySetLanguage(hasSetLanguageObj) {\n    if ('setLanguage' in hasSetLanguageObj) {\n        const hwLang = hasSetLanguageObj.setLanguage();\n        const data = hwLang[Lang.type] || hwLang[Lang.fallbackType];\n        for (const key in data) {\n            Object.assign(Lang[key], data[key]);\n        }\n    }\n}\n\nEntry.reloadBlock = function () {\n    Object.values(Entry.HARDWARE_LIST).forEach(applySetLanguage);\n    Object.values(Entry.HARDWARE_LITE_LIST).forEach(applySetLanguage);\n    assignBlocks();\n    inheritBlockSchema();\n};\n\nEntry.reloadBlock();\n\nEntry.destroyBlock = function () {\n    blocks.destroyBlockList.forEach((fn) => {\n        fn();\n    });\n};\n\nif (typeof exports === 'object') {\n    exports.block = Entry.block;\n    exports.assignBlocks = assignBlocks;\n}\n"
  },
  {
    "path": "src/playground/block_entry_mini.js",
    "content": "const miniBlock = {\n    practical_course_dummy: {\n        color: '#7C7C7C',\n        skeleton: 'basic',\n        statements: [],\n        isNotFor: ['arduinoDisconnected'],\n        template: '%1',\n        params: [\n            {\n                type: 'Indicator',\n                color: '#6B6B6B',\n                size: 12,\n            },\n        ],\n        events: {},\n        def: {\n            params: [null],\n            type: 'practical_course_dummy',\n        },\n        paramsKeyMap: {\n            VALUE: 0,\n        },\n        func(sprite, script) {},\n    },\n    // roborobo_mini\n    /* Dream 블럭 추가*/\n};\n\nmodule.exports.practicalCourseBlock = miniBlock;\n// module.exports.setLanguage = () => ({\n//     ko: {\n//         Helper: {\n//             robotis_set_led: 'LED 모듈이 연결된 [포트]를 선택해 지정한 색의 LED를 켜거나 끕니다.',\n//             robotis_touch_value: '접촉센서가 연결된 [포트]의 값입니다.',\n//             robotis_touch_value_boolean:\n//                 '접촉센서가 연결된 [포트]를 선택해 [접촉되면/접촉 안되면]을 지정합니다.',\n//             robotis_irs_value: '적외선 센서가 연결된 [포트]의 값입니다.',\n//             robotis_irs_value_boolean:\n//                 '적외선 센서가 연결된 [포트]의 값을 [입력]한 숫자와 비교합니다.',\n//             robotis_light_value: '빛감지 센서가 연결된 [포트]의 값입니다.',\n//             robotis_light_value_boolean:\n//                 '빛감지 센서가 연결된 [포트]의값을 [입력]한 숫자와 비교합니다.',\n//             robotis_userbutton_value: '사용자 버튼의 값입니다.',\n//             robotis_userbutton_value_boolean: '사용자 버튼이 [접촉되면/접촉 안되면]을 지정합니다.',\n//             robotis_detectedsound_value: '소리 센서가 입력받은 실시간 소리 값입니다.',\n//             robotis_detectedsound_value_boolean:\n//                 '소리 센서의 실시간 소리 값과 [입력]한 숫자를 비교합니다.',\n//             robotis_detectedsound_value_init: '소리 센서의 최종 소리 값을 초기화합니다.',\n//             robotis_detectingsound_value: '소리 센서가 입력받은 최종 소리 값입니다.',\n//             robotis_detectingsound_value_boolean:\n//                 '소리 센서의 최종 소리 값과 [입력]한 숫자를 비교합니다.',\n//             robotis_color_value: '컬러 센서가 연결된 [포트]의 값입니다.',\n//             robotis_color_value_boolean:\n//                 '컬러 센서가 연결된 [포트]의 값을 [선택]한 숫자와 비교합니다.',\n//             robotis_humidity_value: '습도 센서가 연결된 [포트]의 값입니다.',\n//             robotis_humidity_value_boolean:\n//                 '습도 센서가 연결된 [포트]의 값을 [입력]한 숫자와 비교합니다.',\n//             robotis_temperature_value: '온도 센서가 연결된 [포트]의 값입니다.',\n//             robotis_temperature_value_boolean:\n//                 '온도 센서가 연결된 [포트]의 값을 [입력]한 숫자와 비교합니다.',\n//             robotis_move_for_secs:\n//                 '연결된 모터의 [방향/속도]를 선택하고 [입력]한 시간만큼 회전시킵니다.\\n입력한시간이 끝나면 모터는 정지합니다.',\n//             robotis_aux_move_for: '연결된 모터의 [방향/속도]를 선택해 회전시킵니다.',\n//             robotis_aux_stop_for: '모터를 선택해 정지시킵니다',\n//             robotis_set_servo_wheel: '서보모터의 [포트/방향/속도]를 선택해 회전시킵니다',\n//             robotis_set_servo_joint: '서보모터의 [포트/위치값/속도]를 입력해 동작시킵니다.',\n//             robotis_melody_note_for: '멜로디의 [음계/옥타브/길이]를 선택해 연주합니다.',\n//         },\n//     },\n//     en: {\n//         Helper: {\n//             robotis_aux_move_for: '',\n//         },\n//     },\n//     jp: {\n//         Helper: {\n//             robotis_aux_move_for: '',\n//         },\n//     },\n//     vn: {\n//         Helper: {\n//             robotis_aux_move_for: '',\n//         },\n//     },\n// });\n"
  },
  {
    "path": "src/playground/block_menu.ts",
    "content": "import Visible from '@egjs/visible';\nimport compact from 'lodash/compact';\nimport debounce from 'lodash/debounce';\nimport each from 'lodash/each';\nimport isEmpty from 'lodash/isEmpty';\nimport identity from 'lodash/identity';\nimport remove from 'lodash/remove';\nimport includes from 'lodash/includes';\nimport head from 'lodash/head';\nimport find from 'lodash/find';\nimport ModelClass from '../core/modelClass';\nimport Hammer from 'hammerjs';\n\nimport { EntryDom } from '../../types/index';\n\nconst VARIABLE = 'variable';\nconst HW = 'arduino';\nconst practicalCourseCategoryList = ['hw_motor', 'hw_melody', 'hw_sensor', 'hw_led', 'hw_robot'];\nconst splitterHPadding = EntryStatic.splitterHPadding || 20;\nconst BETA_LIST = [];\n\ntype BlockMenuAlignType = 'LEFT' | 'CENTER';\n\ntype CategoryData = {\n    category: string;\n    blocks: string[];\n    visible?: boolean;\n};\n\ntype Schema = {\n    code: any;\n    dragBlock: any;\n    closeBlock: any;\n    selectedBlockView: any;\n};\n\nclass BlockMenu extends ModelClass<Schema> {\n    public visible = true;\n    public hwCodeOutdated = false;\n    public code: any;\n    public view: EntryDom;\n    public changeEvent: any; // Entry.Event\n    public categoryDoneEvent: any; // Entry.Event\n    public codeListener: any; // Entry.Event\n    private readonly _svgId = `blockMenu${Date.now()}`;\n    private readonly suffix = 'blockMenu';\n    private readonly _dSelectMenu: any;\n    private readonly _scroll: boolean;\n    private readonly _scroller: any; // Entry.BlockMenuScroller\n    private readonly _bannedClass: string[];\n    private readonly _splitters: any[];\n    // view elements\n    private svg: any; // Entry.SVG\n    private svgDom: EntryDom;\n    private pattern: any;\n    private svgGroup: any;\n    private svgThreadGroup: any;\n    private svgBlockGroup: any;\n    private svgCommentGroup: any;\n    private _boardBlockView: any; // in block\n    private _categoryCol: EntryDom;\n    private _offset: JQuery.Coordinates;\n    private categoryWrapper: EntryDom;\n    private blockMenuContainer: EntryDom;\n    private blockMenuWrapper: EntryDom;\n    private blockMenuWrapperForTrashcan: EntryDom;\n    private objectAlert: any;\n    private _dynamicThreads: any[];\n    private _selectDynamic: boolean;\n    private _setDynamicTimer: any;\n    private _align: BlockMenuAlignType;\n    private _categories: any[];\n    private _categoryData: CategoryData[];\n    private _categoryElems: { [categoryName: string]: EntryDom };\n    private _selectedCategoryView?: EntryDom;\n    private _renderedCategories: { [key: string]: boolean };\n    private _threadsMap: { [key: string]: any }; // any => thread\n    private _svgWidth: number;\n    private _generateCodesTimer: NodeJS.Timeout;\n    private categoryIndicatorVisible: any; // egjs.visible\n    private widthBackup: number;\n    private lastSelector: string;\n\n    private firstSelector: string;\n    private workspace: any;\n    private dragInstance: any; // Entry.dragInstance\n    // schema\n    private selectedBlockView: any;\n    private dragBlock: any;\n\n    _setDynamic = debounce((blocks = []) => {\n        if (!this._isOn()) {\n            return;\n        }\n        let data;\n\n        this._dynamicThreads = blocks\n            .map((block: any) => {\n                if (typeof block === 'string') {\n                    return block;\n                } else if (block.constructor === Array) {\n                    const keyName = block[0];\n                    if (!this.getThreadByBlockKey(keyName)) {\n                        data = block[1];\n                        data.category = 'extra';\n                        this._createThread([data], undefined, keyName);\n                    }\n                    return keyName;\n                }\n            })\n            .filter(identity);\n\n        this._selectDynamic = true;\n        this.selectMenu(undefined, true);\n    }, 150);\n\n    reDraw = debounce(() => {\n        if (!this._isOn()) {\n            return;\n        }\n\n        let selector = this.lastSelector;\n        if (this._selectDynamic) {\n            selector = undefined;\n        }\n\n        this.selectMenu(selector, true);\n        this._getSortedBlocks()\n            .shift()\n            .forEach(({ view }) => view.reDraw());\n    }, 100);\n\n    constructor(\n        dom: EntryDom,\n        align: BlockMenuAlignType,\n        categoryData: CategoryData[],\n        scroll: boolean\n    ) {\n        super(\n            {\n                code: null,\n                dragBlock: null,\n                closeBlock: null,\n                selectedBlockView: null,\n            },\n            false\n        );\n        const { hardwareEnable } = Entry;\n\n        this._dSelectMenu = debounce(this.selectMenu, 0);\n\n        this._align = align || 'CENTER';\n        this._svgWidth = 254;\n        this._scroll = scroll !== undefined ? scroll : false;\n        this._bannedClass = [];\n        this._categories = [];\n        this._dynamicThreads = [];\n        this._setDynamicTimer = null;\n        this._renderedCategories = {};\n\n        this._threadsMap = {};\n        const $dom = typeof dom === 'string' ? $(`#${dom}`) : $(dom);\n        if ($dom.prop('tagName') !== 'DIV') {\n            throw new Error('Dom is not div element');\n        }\n\n        this.view = $dom;\n\n        this._clearCategory();\n\n        // hardwareEnable 인 경우, 하드웨어 카테고리와 실과형 로봇카테고리 전부를 제외한다.\n        this._categoryData = remove(\n            categoryData,\n            ({ category }) =>\n                hardwareEnable || [...practicalCourseCategoryList, HW].indexOf(category) <= -1\n        );\n\n        this._generateView(this._categoryData);\n\n        this._splitters = [];\n\n        this.svg = Entry.SVG(this._svgId);\n        Entry.Utils.addFilters(this.svg, this.suffix);\n        const { pattern } = Entry.Utils.addBlockPattern(this.svg, this.suffix);\n        this.pattern = pattern;\n\n        this.svgGroup = this.svg.elem('g');\n\n        this.svgThreadGroup = this.svgGroup.elem('g');\n        this.svgThreadGroup.board = this;\n\n        this.svgBlockGroup = this.svgGroup.elem('g');\n        this.svgBlockGroup.board = this;\n\n        this.svgCommentGroup = this.svgGroup.elem('g');\n        this.svgCommentGroup.board = this;\n\n        this.changeEvent = new Entry.Event(this);\n        this.categoryDoneEvent = new Entry.Event(this);\n\n        this.observe(this, '_handleDragBlock', ['dragBlock']);\n\n        this.changeCode(new Entry.Code([]));\n        this._categoryData && this._generateCategoryCodes();\n\n        if (this._scroll) {\n            this._scroller = new Entry.BlockMenuScroller(this);\n            this._addControl($dom.find('.blockMenuContainer'));\n        }\n\n        if (this.code && Entry.keyPressed) {\n            Entry.keyPressed.attach(this, this._captureKeyEvent);\n        }\n        if (Entry.windowResized) {\n            Entry.windowResized.attach(this, debounce(this.updateOffset, 200));\n        }\n\n        Entry.addEventListener(\n            'setBlockMenuDynamic',\n            function () {\n                this._setDynamicTimer = this._setDynamic.apply(this, arguments);\n            }.bind(this)\n        );\n\n        Entry.addEventListener('cancelBlockMenuDynamic', this._cancelDynamic.bind(this));\n        Entry.addEventListener('fontLoaded', this.reDraw.bind(this));\n        this.initBlockDoubleClickEvent();\n    }\n\n    initBlockDoubleClickEvent() {\n        const hammer = new Hammer(this.code.board.svgBlockGroup);\n        hammer.on('doubletap', (e: { target: HTMLElement }) => {\n            const blockId = e.target.getAttribute('blockId');\n            if (!blockId) {\n                return;\n            }\n            const targetBlock = this.code.findById(blockId);\n            if (\n                targetBlock.type.startsWith('func_') ||\n                ['basic_text', 'clickable_text', 'basic_button'].includes(\n                    targetBlock?._schema?.skeleton\n                )\n            ) {\n                return;\n            }\n            const { width, height } = targetBlock.view;\n            const { scale, svg } = this.workspace.board;\n            const { left, top, right, bottom } = svg.getBoundingClientRect();\n            const boardCenterX = (Math.min(window.innerWidth, right) - left) / 2;\n            const boardCenterY = (Math.min(window.innerHeight, bottom) - top) / 2;\n            const block = targetBlock.toJSON(true);\n            block.x = boardCenterX - (width * scale) / 2;\n            block.y = boardCenterY - (height * scale) / 2;\n\n            Entry.do('addThread', [block]);\n        });\n    }\n\n    foldBlockMenu() {\n        const playground = Entry.playground;\n        if (!playground || playground.resizing) {\n            return;\n        }\n\n        if (this._scroller) {\n            this._scroller.setOpacity(0);\n        }\n\n        const widthBackup = this.widthBackup;\n        if (widthBackup) {\n            $(this.blockMenuWrapper).css('width', widthBackup);\n        }\n        delete this.widthBackup;\n    }\n\n    changeCode(code: any) {\n        if (code instanceof Array) {\n            code = new Entry.Code(code);\n        }\n\n        if (!(code instanceof Entry.Code)) {\n            return console.error('You must inject code instance');\n        }\n\n        // this.codeListener?.destory();\n        this.codeListener?.destroy?.();\n\n        this.set({ code });\n        this.codeListener = this.code.changeEvent.attach(this, () => {\n            this.changeEvent.notify();\n        });\n        code.createView(this);\n\n        this.align();\n    }\n\n    bindCodeView(codeView: any) {\n        this.svgBlockGroup.remove();\n        this.svgThreadGroup.remove();\n        this.svgBlockGroup = codeView.svgBlockGroup;\n        this.svgThreadGroup = codeView.svgThreadGroup;\n        this.svgGroup.appendChild(this.svgThreadGroup);\n        this.svgGroup.appendChild(this.svgBlockGroup);\n        if (this._scroller) {\n            this.svgGroup.appendChild(this._scroller.svgGroup);\n        }\n    }\n\n    align() {\n        const code = this.code;\n        if (!(this._isOn() && code)) {\n            return;\n        }\n        this._clearSplitters();\n\n        const vPadding = 15;\n        let marginFromTop = 10;\n        const hPadding = this._align === 'LEFT' ? 10 : this.svgDom.width() / 2;\n\n        let pastClass: string;\n        const blocks = this._getSortedBlocks();\n        const [visibles = [], inVisibles = []] = blocks;\n\n        inVisibles.forEach(({ view: blockView } = {}) => {\n            if (!blockView) {\n                return;\n            }\n            blockView.set({ display: false });\n            blockView.detach();\n        });\n\n        const lastSelector = this.lastSelector;\n        const shouldReDraw = !this._renderedCategories[lastSelector];\n        visibles.forEach(({ view: blockView, type } = {}, index) => {\n            if (!blockView) {\n                return;\n            }\n            blockView.attach();\n            blockView.set({ display: true });\n            if (shouldReDraw || (Entry?.Func?.isEdit && blockView?.block?.data?.params?.length)) {\n                blockView.reDraw();\n            }\n            if (Entry.block[type]) {\n                const className = Entry.block[type].class;\n                if (pastClass && pastClass !== className) {\n                    this._createSplitter(marginFromTop);\n                    marginFromTop += vPadding;\n                }\n                pastClass = className;\n            }\n\n            let left = hPadding - blockView.offsetX;\n            if (this._align === 'CENTER') {\n                left -= blockView.width / 2;\n            }\n\n            marginFromTop -= blockView.offsetY;\n            blockView.moveTo(left, marginFromTop, false);\n            if (index > 0) {\n                marginFromTop += blockView.marginBottom || 0;\n            }\n            marginFromTop += blockView.height + vPadding;\n        });\n\n        this.updateSplitters();\n\n        if (this.workspace) {\n            const mode = this.workspace.getMode();\n            switch (mode) {\n                case Entry.Workspace.MODE_BOARD:\n                case Entry.Workspace.MODE_OVERLAYBOARD:\n                    this.renderBlock(blocks);\n                    break;\n                case Entry.Workspace.MODE_VIMBOARD:\n                    this.renderText(blocks);\n                    break;\n                default:\n                    this.renderBlock(blocks);\n            }\n        }\n\n        if (lastSelector !== 'func') {\n            this._renderedCategories[lastSelector] = true;\n        }\n        this.changeEvent.notify();\n    }\n\n    cloneToGlobal(e: any) {\n        const blockView = this.dragBlock;\n        if (this._boardBlockView || blockView === null) {\n            if (this.widthBackup) {\n                this.foldBlockMenu();\n            }\n            return;\n        }\n\n        const GS = Entry.GlobalSvg;\n        const workspace = this.workspace;\n        const workspaceMode = workspace.getMode();\n        const { MODE_BOARD, MODE_OVERLAYBOARD } = Entry.Workspace;\n\n        const svgWidth = this._svgWidth;\n\n        const board = workspace.selectedBoard;\n        const { x = 0, y = 0 } = blockView.mouseDownCoordinate || {};\n        const dx = e.pageX - x;\n        const dy = e.pageY - y;\n        if (board && (workspaceMode === MODE_BOARD || workspaceMode === MODE_OVERLAYBOARD)) {\n            if (!board.code) {\n                if (Entry.toast && !(this.objectAlert && Entry.toast.isOpen(this.objectAlert))) {\n                    this.objectAlert = Entry.toast.alert(\n                        Lang.Workspace.add_object_alert,\n                        Lang.Workspace.add_object_alert_msg\n                    );\n                }\n                if (this.selectedBlockView) {\n                    this.selectedBlockView.removeSelected();\n                    this.set({\n                        selectedBlockView: null,\n                        dragBlock: null,\n                    });\n                }\n                return;\n            }\n\n            const block = blockView.block;\n            const currentThread = block.getThread();\n            if (block && currentThread) {\n                const distance = this.offset().top - board.offset().top - $(window).scrollTop();\n\n                const datum = currentThread.toJSON(true);\n                const firstBlock: any = head(datum);\n                firstBlock.x = firstBlock.x - svgWidth + (dx || 0);\n                firstBlock.y = firstBlock.y + distance + (dy || 0);\n\n                const newBlock = Entry.do('addThreadFromBlockMenu', datum).value.getFirstBlock();\n                const newBlockView = newBlock?.view;\n\n                // if some error occured\n                // blockView is not exist\n                if (!newBlockView) {\n                    newBlock?.destory();\n                    return;\n                }\n\n                this._boardBlockView = newBlockView;\n\n                newBlockView.onMouseDown.call(newBlockView, e);\n                if (newBlockView.dragInstance) {\n                    newBlockView.dragInstance.set({\n                        isNew: true,\n                    });\n                }\n\n                GS.setView(newBlockView, workspaceMode);\n            } else {\n            }\n        } else {\n            if (GS.setView(blockView, workspaceMode)) {\n                GS.adjust(dx, dy);\n                GS.addControl(e);\n            }\n        }\n    }\n\n    terminateDrag() {\n        const boardBlockView = this._boardBlockView;\n\n        if (!boardBlockView) {\n            return;\n        }\n\n        this._boardBlockView = null;\n\n        //board block should be removed below the amount of range\n        const { left, width } = Entry.GlobalSvg;\n        return left < boardBlockView.getBoard().offset().left - width / 2;\n    }\n\n    getCode() {\n        return this.code;\n    }\n\n    setSelectedBlock(blockView?: any) {\n        this.selectedBlockView?.removeSelected();\n\n        if (blockView instanceof Entry.BlockView) {\n            blockView.addSelected();\n        } else {\n            blockView = null;\n        }\n\n        this.set({ selectedBlockView: blockView });\n    }\n\n    hide() {\n        this.view.addClass('entryRemove');\n    }\n\n    show() {\n        this.view.removeClass('entryRemove');\n    }\n\n    renderText(blocks?: any[]) {\n        if (!this._isOn()) {\n            return;\n        }\n\n        blocks = blocks || this._getSortedBlocks();\n        const targetMode = Entry.BlockView.RENDER_MODE_TEXT;\n\n        blocks[0].forEach((block: any) => {\n            if (targetMode === block.view.renderMode) {\n                return;\n            }\n            const thread = block.getThread();\n            const view = thread.view;\n            if (view) {\n                view.renderText();\n            } else {\n                thread.createView(this, Entry.BlockView.RENDER_MODE_TEXT);\n            }\n        });\n        return blocks;\n    }\n\n    renderBlock(blocks?: any[]) {\n        if (!this._isOn()) {\n            return;\n        }\n\n        blocks = blocks || this._getSortedBlocks();\n        const targetMode = Entry.BlockView.RENDER_MODE_BLOCK;\n\n        blocks[0].forEach((block: any) => {\n            if (targetMode === block.view.renderMode) {\n                return;\n            }\n            const thread = block.getThread();\n            const view = thread.view;\n            if (view) {\n                view.renderBlock();\n            } else {\n                thread.createView(this, Entry.BlockView.RENDER_MODE_BLOCK);\n            }\n        });\n        return blocks;\n    }\n\n    _createSplitter(topPos: number) {\n        const { common = {} } = EntryStatic.colorSet || {};\n        this._splitters.push(\n            this.svgBlockGroup.elem('line', {\n                x1: splitterHPadding,\n                y1: topPos,\n                x2: this._svgWidth - splitterHPadding,\n                y2: topPos,\n                stroke: common.SPLITTER || '#AAC5D5',\n            })\n        );\n    }\n\n    updateSplitters(y = 0) {\n        const xDest = this._svgWidth - splitterHPadding;\n        let yDest;\n        this._splitters.forEach((line) => {\n            yDest = parseFloat(line.getAttribute('y1')) + y;\n            line.attr({\n                x2: xDest,\n                y1: yDest,\n                y2: yDest,\n            });\n        });\n    }\n\n    setMenu(doNotAlign?: boolean) {\n        if (!this.hasCategory()) {\n            return;\n        }\n\n        const sorted: [any[], any[]] = [[], []];\n        this._categoryData.forEach(({ category, blocks: threads }) => {\n            if (category === 'func') {\n                const funcThreads = this.code\n                    .getThreadsByCategory('func')\n                    .map((thread: any) => thread.getFirstBlock().type);\n                threads = funcThreads.length ? funcThreads : threads;\n            }\n            const inVisible =\n                threads.reduce(\n                    (count, type) => (this.checkBanClass(Entry.block[type]) ? count - 1 : count),\n                    threads.length\n                ) === 0;\n            const elem = this._categoryElems[category];\n\n            if (inVisible) {\n                sorted[1].push(elem);\n            } else {\n                sorted[0].push(elem);\n            }\n        });\n\n        requestAnimationFrame(() => {\n            //visible\n            sorted[0].forEach((elem) => elem.removeClass('entryRemove'));\n            //invisible\n            sorted[1].forEach((elem) => elem.addClass('entryRemove'));\n            this.selectMenu(0, true, doNotAlign);\n        });\n    }\n\n    toggleBlockMenu() {\n        const board = this.workspace.board;\n        const boardView = board.view;\n\n        if (!boardView.hasClass('folding')) {\n            boardView.addClass('folding');\n            Entry.playground.resizeHandle_.addClass('highIndex');\n            Entry.playground.resizeHandle_.addClass('folding');\n            Entry.playground.resizeHandle_.removeClass('unfolding');\n            Entry.playground.hideTabs();\n            this.visible = false;\n        } else {\n            if (!this.visible) {\n                boardView.addClass('foldOut');\n                Entry.playground.showTabs();\n            }\n            boardView.removeClass('folding');\n            Entry.playground.resizeHandle_.addClass('highIndex');\n            Entry.playground.resizeHandle_.addClass('unfolding');\n            Entry.playground.resizeHandle_.removeClass('folding');\n            this.visible = true;\n        }\n        Entry.bindAnimationCallbackOnce(boardView, () => {\n            board.scroller.resizeScrollBar.call(board.scroller);\n            boardView.removeClass('foldOut');\n            Entry.playground.resizeHandle_.removeClass('highIndex');\n            Entry.windowResized.notify();\n        });\n\n        this.align();\n    }\n\n    selectMenu(selector: number | string, doNotFold: boolean, doNotAlign?: boolean) {\n        if (Entry.disposeEvent) {\n            Entry.disposeEvent.notify();\n        }\n        if (!this._isOn() || !this._categoryData) {\n            return;\n        }\n\n        const oldView = this._selectedCategoryView;\n        const name = this._convertSelector(selector);\n        if (selector !== undefined && !name) {\n            this.align();\n            return;\n        }\n\n        if (name) {\n            this.lastSelector = name;\n        }\n\n        switch (name) {\n            case VARIABLE:\n                Entry.playground.checkVariables();\n                break;\n            case HW:\n                this._generateHwCode();\n                this.align();\n                break;\n        }\n\n        const elem = this._categoryElems[name];\n        let animate = false;\n        const board = this.workspace.board;\n        const boardView = board.view;\n        const handle = Entry.playground.resizeHandle_;\n        const className = 'entrySelectedCategory';\n        const className2 = 'entryUnSelectedCategory';\n\n        if (oldView) {\n            oldView.removeClass(className);\n            oldView.addClass(className2);\n        }\n\n        if (elem === oldView && !(doNotFold || !this.hasCategory())) {\n            elem.removeClass(className);\n            elem.addClass(className2);\n        }\n\n        this._selectedCategoryView = elem;\n        if (elem) {\n            elem.removeClass(className2);\n            elem.addClass(className);\n        }\n\n        doNotAlign !== true && this.align();\n    }\n\n    banCategory(categoryName: string) {\n        const categoryElem = this._categoryElems[categoryName];\n        if (!categoryElem) {\n            return;\n        }\n        categoryElem.addClass('entryRemoveCategory');\n        if (this.lastSelector === categoryName) {\n            this._dSelectMenu(this.firstSelector, true);\n        }\n    }\n\n    unbanCategory(category: string) {\n        const blockList = this._getCategoryBlocks(category);\n\n        if (!blockList) {\n            return;\n        }\n\n        const count = blockList.reduce(\n            (count, block) => (this.checkBanClass(Entry.block[block]) ? count - 1 : count),\n            blockList.length\n        );\n\n        const categoryElem = this._categoryElems[category];\n        if (categoryElem && count > 0) {\n            categoryElem.removeClass('entryRemoveCategory');\n            categoryElem.removeClass('entryRemove');\n        }\n    }\n\n    banClass(className: string, doNotAlign?: boolean) {\n        const banned = this._bannedClass;\n        if (!includes(banned, className)) {\n            banned.push(className);\n            doNotAlign !== true && this.align();\n        }\n    }\n\n    unbanClass(className: string, doNotAlign?: boolean) {\n        const banned = this._bannedClass;\n        const index = banned.indexOf(className);\n        if (index > -1) {\n            banned.splice(index, 1);\n            doNotAlign !== true && this.align();\n        }\n    }\n\n    checkBanClass({ isNotFor = [] } = {}) {\n        if (isEmpty(isNotFor)) {\n            return false;\n        }\n\n        const banned = this._bannedClass;\n        const filteredIsNotFor = isNotFor.filter(identity);\n\n        for (let i = 0; i < filteredIsNotFor.length; i++) {\n            if (!includes(banned, filteredIsNotFor[i])) {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    checkCategory(blockInfo: any) {\n        if (!this.hasCategory() || !blockInfo) {\n            return;\n        }\n\n        if (!this.lastSelector || this._selectDynamic) {\n            return true;\n        }\n\n        return !includes(blockInfo.isFor || [], `category_${this.lastSelector}`);\n    }\n\n    /**\n     * 특정 카테고리에 특정 블록명을 추가한다.\n     * 카테고리가 존재하지 않거나 블록명이 이미 등록된 경우 스킵한다.\n     * Entry.block 목록에 실제 데이터가 있는지, blockMenu 의 그리기 갱신이 필요한지는 상관하지 않는다.\n     * @param categoryName {string}\n     * @param blockName {string}\n     */\n    addCategoryData(categoryName: string, blockName: string) {\n        const selectedCategory = this._categoryData.find(\n            (element) => element.category === categoryName\n        );\n        if (selectedCategory?.blocks.indexOf(blockName) === -1) {\n            selectedCategory.blocks.push(blockName);\n        }\n\n        if (!this.getThreadByBlockKey(blockName)) {\n            const threadDatum = this._buildCategoryCodes([blockName], categoryName);\n            this._createThread(threadDatum[0]);\n        }\n    }\n\n    destroy() {\n        this.categoryIndicatorVisible.off();\n        this._categoryCol.off();\n        $(document).off('.blockMenuScroll');\n    }\n\n    removeControl(eventType: string) {\n        this.svgDom.off(eventType);\n    }\n\n    onMouseMove(e: JQuery.MouseMoveEvent) {\n        e?.stopPropagation();\n\n        if (Entry.isMobile()) {\n            this._scroller.setOpacity(0.8);\n        }\n\n        const { pageY } = Entry.Utils.convertMouseEvent(e);\n\n        const dragInstance = this.dragInstance;\n        this._scroller.scroll(-pageY + dragInstance.offsetY);\n        dragInstance.set({ offsetY: pageY });\n    }\n\n    onMouseUp(e: JQuery.MouseUpEvent) {\n        if (Entry.isMobile()) {\n            this._scroller.setOpacity(0);\n        }\n        if (e.which == 2) {\n            console.log('mouse wheel click disabled');\n            return;\n        }\n        if (e.button != 1) {\n            $(document).unbind('.blockMenu');\n            delete this.dragInstance;\n        }\n    }\n\n    onMouseDown(e: JQuery.TouchMoveEvent) {\n        if (e.preventDefault) {\n            e.preventDefault();\n        }\n        if (e.which == 2) {\n            console.log('mouse wheel click disabled');\n            return;\n        }\n        if (e.button === 0 || e.originalEvent?.touches) {\n            const mouseEvent = Entry.Utils.convertMouseEvent(e);\n            if (Entry.documentMousedown) {\n                Entry.documentMousedown.notify(mouseEvent);\n            }\n            const doc = $(document);\n\n            doc.bind('mousemove.blockMenu touchmove.blockMenu', this.onMouseMove.bind(this));\n            doc.bind('mouseup.blockMenu touchend.blockMenu', this.onMouseUp.bind(this));\n\n            this.dragInstance = new Entry.DragInstance({\n                startY: mouseEvent.pageY,\n                offsetY: mouseEvent.pageY,\n            });\n        }\n    }\n\n    dominate({ view: { svgGroup } }: any) {\n        this.svgBlockGroup.appendChild(svgGroup);\n    }\n\n    _handleDragBlock() {\n        this._boardBlockView = null;\n        if (this._scroller) {\n            this._scroller.setOpacity(0);\n        }\n    }\n\n    _handleBoardDragBlock() {\n        this._toggleTrashcan(!!this.workspace?.board?.dragBlock);\n    }\n\n    _toggleTrashcan(visible: boolean) {\n        this.blockMenuWrapperForTrashcan?.toggleClass('entryRemove', !visible);\n    }\n\n    enablePattern() {\n        this.pattern.removeAttribute('style');\n    }\n\n    disablePattern() {\n        this.pattern.attr({ style: 'display: none' });\n    }\n\n    /**\n     * lms, entry-web 에서 사용 중\n     */\n    setCategoryData(data: CategoryData[]) {\n        this._clearCategory();\n        this._categoryData = data;\n        this._generateCategoryView(data);\n        this._generateCategoryCodes();\n        this.setMenu();\n        Entry.resizeElement();\n    }\n\n    /**\n     * lms 에서 사용 중\n     */\n    setNoCategoryData(data: any) {\n        this._clearCategory();\n        Entry.resizeElement();\n        this.changeCode(data);\n        this.categoryDoneEvent.notify();\n    }\n\n    makeScrollIndicator() {\n        ['append', 'prepend'].forEach((action) => {\n            const point = Entry.Dom('li', {\n                class: `visiblePoint ${action}`,\n            });\n            const indicator = Entry.Dom('a', {\n                class: `scrollIndicator ${action}`,\n            });\n            indicator.bindOnClick(() => {\n                point[0].scrollIntoView({\n                    behavior: 'smooth',\n                    block: 'nearest',\n                });\n            });\n            point.attr('data-action', action);\n            indicator.attr('data-action', action);\n            //@ts-ignore\n            this._categoryCol[action](point);\n            //@ts-ignore\n            this._categoryCol[action](indicator);\n        });\n\n        this.categoryIndicatorVisible = new Visible('.entryCategoryListWorkspace', {\n            targetClass: 'visiblePoint',\n            expandSize: 0,\n        });\n        this.categoryIndicatorVisible.on('change', (e: any) => {\n            e.visible.forEach((dom: any) => {\n                const { dataset } = dom;\n                const { action } = dataset;\n                $(`.scrollIndicator.${action}`).css('display', 'none');\n            });\n            e.invisible.forEach((dom: any) => {\n                const { dataset } = dom;\n                const { action } = dataset;\n                $(`.scrollIndicator.${action}`).css('display', 'block');\n            });\n        });\n        this._categoryCol.on(\n            'scroll',\n            debounce(() => {\n                this.categoryIndicatorVisible.check();\n            }, 100)\n        );\n        setTimeout(() => {\n            this.categoryIndicatorVisible.check();\n        }, 0);\n        if (Entry.windowResized) {\n            Entry.windowResized.attach(this, () => {\n                this.categoryIndicatorVisible.check();\n            });\n        }\n        $(document).on('visibilitychange.blockMenuScroll', (e) => {\n            if (document.visibilityState === 'visible') {\n                requestAnimationFrame(() => {\n                    this.categoryIndicatorVisible.check();\n                });\n            }\n        });\n    }\n\n    updateOffset() {\n        this._offset = this.svgDom.offset();\n    }\n\n    offset() {\n        const { top = 0, left = 0 } = this._offset || {};\n        if (top === 0 && left === 0) {\n            this.updateOffset();\n        }\n        return this._offset;\n    }\n\n    _generateHwCode(shouldHide?: boolean) {\n        const targetHwCategory = [HW];\n        const targetPracticalCategories = practicalCourseCategoryList.filter(\n            (category) => category != 'hw_robot'\n        );\n        EntryStatic.isPracticalCourse && targetHwCategory.push(...targetPracticalCategories);\n\n        targetHwCategory.map((hwCategory) => {\n            const threads = this.code.getThreadsByCategory(hwCategory);\n\n            if (!(this._categoryData && this.shouldGenerateHwCode(threads))) {\n                return;\n            }\n\n            threads.forEach((t: any) => {\n                this._deleteThreadsMap(t);\n                t.destroy();\n            });\n\n            const blocks = this._getCategoryBlocks(hwCategory);\n\n            if (isEmpty(blocks)) {\n                return;\n            }\n\n            this._buildCategoryCodes(\n                blocks.filter((b) => !this.checkBanClass(Entry.block[b])),\n                hwCategory\n            ).forEach((t: any) => {\n                if (shouldHide) {\n                    t[0].x = -99999;\n                }\n                this._createThread(t);\n                delete t[0].x;\n            });\n        });\n\n        this.hwCodeOutdated = false;\n        Entry.dispatchEvent('hwCodeGenerated');\n    }\n\n    /**\n     * Ntry systems/entryPlayground.js#loadConfig 에서 사용됨\n     * 그 외에는 쓸모없음\n     * @deprecated\n     */\n    setAlign(align: BlockMenuAlignType) {\n        this._align = align || 'CENTER';\n    }\n\n    _cancelDynamic(fromElement: boolean, cb?: () => void) {\n        if (this._setDynamicTimer) {\n            clearTimeout(this._setDynamicTimer);\n            this._setDynamicTimer = null;\n        }\n        this._selectDynamic = false;\n        this._dynamicThreads = [];\n        if (fromElement !== true) {\n            this.selectMenu(this.lastSelector, true);\n        }\n        cb && cb();\n    }\n\n    deleteRendered(name: string) {\n        delete this._renderedCategories[name];\n    }\n\n    clearRendered() {\n        this._renderedCategories = {};\n    }\n\n    hasCategory() {\n        return !!this._categoryData;\n    }\n\n    getDom(query: any) {\n        if (isEmpty(query)) {\n            return;\n        }\n        if (query[0] === 'category') {\n            return this._categoryElems[query[1]];\n        } else {\n            const { type, params = [] } = query[0][0];\n            this.align();\n            this.scrollToType(type, params);\n            return this.getSvgDomByType(type, params);\n        }\n    }\n\n    getSvgDomByType(blockType: string, params: any[]) {\n        const thread = find(this.code.getThreads(), (thread) => {\n            if (!thread) {\n                return;\n            }\n            const { type, params: threadParams } = thread.getFirstBlock();\n            let option = true;\n            if (\n                blockType === 'calc_basic' ||\n                blockType === 'boolean_basic_operator' ||\n                blockType === 'boolean_and_or'\n            ) {\n                option = type === blockType && threadParams[1] === params[1];\n            }\n            return type === blockType && option;\n        });\n\n        if (!thread) {\n            return;\n        }\n\n        return thread.getFirstBlock().view.svgGroup;\n    }\n\n    scrollToType(type: string, params: any[]) {\n        if (!type) {\n            return;\n        }\n\n        const block: any = head(this.code.getBlockList(false, type));\n        if (!block) {\n            return;\n        }\n\n        this.hasCategory() && this.selectMenu(block.category, true);\n\n        if (isOverFlow(this.getSvgDomByType(type, params).getBoundingClientRect())) {\n            this._scroller.scrollByPx(block.view.y - 20);\n        }\n\n        function isOverFlow({ bottom }: { bottom: number }) {\n            return bottom > $(window).height() - 10;\n        }\n    }\n\n    shouldGenerateHwCode(threads: any) {\n        return this.hwCodeOutdated || threads.length === 0;\n    }\n\n    getThreadByBlockKey(key: string) {\n        return this._threadsMap[key];\n    }\n\n    private _buildCategoryCodes(blocks: any, category: string) {\n        return blocks.reduce((threads: any, type: string) => {\n            const block = Entry.block[type];\n            if (!block || !block.def) {\n                return [...threads, [{ type, category }]];\n            } else {\n                return (block.defs || [block.def]).reduce(\n                    (threads: any, d: any) => [...threads, [Object.assign(d, { category })]],\n                    threads\n                );\n            }\n        }, []);\n    }\n\n    enableTrashcan() {\n        this.blockMenuWrapperForTrashcan = Entry.Dom('div', {\n            class: 'blockMenuWrapper blockMenuTrashcan entryRemove',\n            parent: this.blockMenuContainer,\n        })\n            .on('pointerenter', () => this.blockMenuWrapperForTrashcan.addClass('open'))\n            .on('pointerleave', () => this.blockMenuWrapperForTrashcan.removeClass('open'));\n\n        Entry.Dom('span')\n            .text(Lang.Workspace.drag_to_remove)\n            .appendTo(this.blockMenuWrapperForTrashcan);\n\n        this.workspace?.board?.observe(this, '_handleBoardDragBlock', ['dragBlock']);\n    }\n\n    changeTypeThreadByBlockKey(key: string) {\n        this.getThreadByBlockKey(key)?.getFirstBlock().changeType();\n    }\n\n    private _generateView(categoryData: CategoryData[]) {\n        categoryData && this._generateCategoryView(categoryData);\n\n        this.blockMenuContainer = Entry.Dom('div', {\n            class: 'blockMenuContainer',\n            parent: this.view,\n        }).css({\n            position: 'relative',\n        });\n        Entry.Utils.disableContextmenu(this.blockMenuContainer);\n        this.blockMenuWrapper = Entry.Dom('div', {\n            class: 'blockMenuWrapper',\n            parent: this.blockMenuContainer,\n        });\n\n        this.svgDom = Entry.Dom(\n            $(\n                // eslint-disable-next-line max-len\n                `<svg id=\"${this._svgId}\" class=\"blockMenu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"></svg>`\n            ),\n            { parent: this.blockMenuWrapper }\n        );\n        this.svgDom.mouseenter(() => {\n            this._scroller?.setOpacity(0.8);\n\n            const selectedBlockView = this.workspace.selectedBlockView;\n            if (\n                !Entry.playground ||\n                Entry.playground.resizing ||\n                selectedBlockView?.dragMode === Entry.DRAG_MODE_DRAG ||\n                Entry.GlobalSvg.isShow\n            ) {\n                return;\n            }\n            const bBox = this.svgGroup.getBBox();\n            const adjust = this.hasCategory() ? 64 : 0;\n            const expandWidth = bBox.width + bBox.x + adjust + 2;\n            const menuWidth = 319;\n            if (expandWidth > menuWidth) {\n                this.widthBackup = menuWidth - adjust - 2;\n                $(this.blockMenuWrapper).css('width', expandWidth - adjust);\n            }\n        });\n\n        this.svgDom.mouseleave(() => {\n            this.foldBlockMenu();\n        });\n\n        Entry.Utils.bindBlockViewHoverEvent(this, this.svgDom);\n        $(window).scroll(this.updateOffset.bind(this));\n    }\n\n    private _clearSplitters() {\n        while (this._splitters.length) {\n            this._splitters.pop().remove();\n        }\n    }\n\n    private _convertSelector(selector: number | string) {\n        if (!Entry.Utils.isNumber(selector)) {\n            return selector;\n        }\n\n        let selectorNumber = Number(selector);\n        const categories = this._categories;\n        const elems = this._categoryElems;\n        for (let i = 0; i < categories.length; i++) {\n            const key = categories[i];\n            const visible = !elems[key].hasClass('entryRemove');\n            if (visible) {\n                if (selectorNumber-- === 0) {\n                    return key;\n                }\n            }\n        }\n    }\n\n    private _generateCategoryCodes(elems?: any[]) {\n        let elemKeys: string[];\n        if (!elems) {\n            this.view.addClass('init');\n            elemKeys = Object.keys(this._categoryElems);\n        } else {\n            elemKeys = elems;\n        }\n\n        if (isEmpty(elemKeys)) {\n            return;\n        }\n        const key = elemKeys.shift();\n        if (key !== HW) {\n            this._generateCategoryCode(key);\n        } else {\n            this._generateHwCode(true);\n        }\n\n        if (elemKeys.length) {\n            this._generateCodesTimer = setTimeout(() => this._generateCategoryCodes(elemKeys), 0);\n        } else {\n            this._generateCodesTimer = null;\n            this.view.removeClass('init');\n            this.align();\n            this.categoryDoneEvent.notify();\n        }\n    }\n\n    private _generateCategoryCode(category: string) {\n        if (!this._categoryData) {\n            return;\n        }\n\n        const code = this.code;\n        const blocks = this._getCategoryBlocks(category);\n        if (!blocks) {\n            return;\n        }\n\n        this._categories.push(category);\n\n        let index: number;\n        if (category === 'func') {\n            const threads = this.code.getThreadsByCategory('func');\n            if (threads.length) {\n                index = this.code.getThreadIndex(threads[0]);\n            }\n        }\n\n        this._buildCategoryCodes(blocks, category).forEach((t: any) => {\n            if (!t || !t[0]) {\n                return;\n            }\n            t[0].x = -99999;\n            this._createThread(t, index);\n            if (index !== undefined) {\n                index++;\n            }\n            delete t[0].x;\n        });\n\n        code.changeEvent.notify();\n    }\n\n    private _addControl(dom: EntryDom) {\n        dom.on('wheel', this._mouseWheel.bind(this));\n\n        if (this._scroller) {\n            $(this.svg).bind('mousedown touchstart', this.onMouseDown.bind(this));\n        }\n    }\n\n    // WheelEvent?\n    private _mouseWheel(e: any) {\n        const originalEvent = e.originalEvent;\n        originalEvent.preventDefault();\n        const disposeEvent = Entry.disposeEvent;\n        if (disposeEvent) {\n            disposeEvent.notify(originalEvent);\n        }\n        this._scroller.scroll(-originalEvent.wheelDeltaY || originalEvent.deltaY / 3);\n    }\n\n    private _captureKeyEvent(e: KeyboardEvent) {\n        const keyCode = Entry.Utils.inputToKeycode(e);\n        if (!keyCode) {\n            return;\n        }\n        if (e.ctrlKey && Entry.type === 'workspace' && keyCode > 48 && keyCode < 58) {\n            e.preventDefault();\n            setTimeout(() => {\n                this._cancelDynamic(true);\n                this._dSelectMenu(keyCode, true);\n            }, 200);\n        }\n    }\n\n    private _clearCategory() {\n        if (this._generateCodesTimer) {\n            clearTimeout(this._generateCodesTimer);\n            this._generateCodesTimer = null;\n        }\n\n        this._selectedCategoryView = null;\n        this._categories = [];\n        this._threadsMap = {};\n\n        each(this._categoryElems, (elem) => elem.remove());\n        this._categoryElems = {};\n\n        const code = this.code;\n        if (code?.constructor == Entry.Code) {\n            code.clear();\n        }\n\n        this._categoryCol?.remove();\n        this._categoryData = null;\n    }\n\n    /**\n     * 카테고리의 목록 뷰를 그린다.\n     * @param data {{category: string, blocks: object[]}[]} EntryStatic.getAllBlocks\n     * @private\n     */\n    private _generateCategoryView(data: CategoryData[]) {\n        if (!data) {\n            return;\n        }\n\n        this._categoryCol?.remove();\n\n        // 카테고리가 이미 만들어져있는 상태에서 데이터만 새로 추가된 경우,\n        // categoryWrapper 는 살리고 내부 컬럼 엘리먼트만 치환한다.\n        if (!this.categoryWrapper) {\n            this.categoryWrapper = Entry.Dom('div', {\n                class: 'entryCategoryListWorkspace',\n            });\n        } else {\n            this.categoryWrapper.textContent = '';\n        }\n\n        this._categoryCol = Entry.Dom('ul', {\n            class: 'entryCategoryList',\n            parent: this.categoryWrapper,\n        });\n        this.view.prepend(this.categoryWrapper);\n\n        const fragment = document.createDocumentFragment();\n\n        /*\n        visible = static_mini 의 실과형 하드웨어에서만 사용됩니다. (EntryStatic 에 책임)\n         */\n        data.forEach(({ category, visible }) =>\n            fragment.appendChild(this._generateCategoryElement(category, visible)[0])\n        );\n        this.firstSelector = head(data).category;\n        this._categoryCol[0].appendChild(fragment);\n        this.makeScrollIndicator();\n    }\n\n    private _generateCategoryElement(name: string, visible: boolean) {\n        this._categoryElems[name] = Entry.Dom('li', {\n            id: `entryCategory${name}`,\n            classes: [\n                'entryCategoryElementWorkspace',\n                'entryRemove',\n                visible === false ? 'entryRemoveCategory' : '',\n            ],\n        })\n            .bindOnClick(() => {\n                this._cancelDynamic(true, () => {\n                    this.selectMenu(name, undefined, true);\n                    this.align();\n                });\n            })\n            .text(Lang.Blocks[name.toUpperCase()]);\n        if (BETA_LIST.includes(name)) {\n            this._categoryElems[name][0].appendChild(\n                Entry.Dom('div', {\n                    id: `entryCategory${name}BetaTag`,\n                    classes: ['entryCategoryBetaTag'],\n                })[0]\n            );\n        }\n\n        return this._categoryElems[name];\n    }\n\n    private _isNotVisible(blockInfo: any) {\n        return this.checkCategory(blockInfo) || this.checkBanClass(blockInfo);\n    }\n\n    private _getSortedBlocks(): [any[], any[]] {\n        let visibles: any[] = [];\n        let inVisibles: any[];\n        let block;\n\n        const allBlocks: any[] = compact(\n            this.code.getThreads().map((thread: any) => thread.getFirstBlock())\n        );\n\n        if (this._selectDynamic) {\n            const threadsMap = this._threadsMap;\n            visibles = this._dynamicThreads.reduce((visibles, type) => {\n                block = threadsMap[type].getFirstBlock();\n                if (block) {\n                    visibles.push(block);\n                }\n                return visibles;\n            }, []);\n\n            inVisibles = allBlocks;\n        } else {\n            inVisibles = [];\n            allBlocks.forEach((block) => {\n                if (!this._isNotVisible(Entry.block[block.type])) {\n                    visibles.push(block);\n                } else {\n                    inVisibles.push(block);\n                }\n            });\n        }\n\n        return [visibles, inVisibles];\n    }\n\n    private _isOn() {\n        return this.view.css('display') !== 'none';\n    }\n\n    private _registerThreadsMap(type: string, thread: any) {\n        if (!(type && thread?.getFirstBlock())) {\n            return;\n        }\n        this._threadsMap[type] = thread;\n    }\n\n    private _deleteThreadsMap(thread: any) {\n        const block = thread?.getFirstBlock();\n        if (!block) {\n            return;\n        }\n        delete this._threadsMap[block.type];\n    }\n\n    private _createThread(data: any, index?: number, keyName?: string) {\n        if (typeof keyName !== 'string') {\n            keyName = undefined;\n        }\n        keyName = keyName || data[0].type;\n\n        const thread = this.code.createThread(data, index);\n        this._registerThreadsMap(keyName, thread);\n        return thread;\n    }\n\n    private _getCategoryBlocks(category: string): string[] | undefined {\n        const selectedCategory = find(this._categoryData, { category });\n        return selectedCategory?.blocks;\n    }\n}\n\nexport default BlockMenu;\nEntry.BlockMenu = BlockMenu;\n"
  },
  {
    "path": "src/playground/block_menu_scroll.js",
    "content": "import debounce from 'lodash/debounce';\n\nclass BlockMenuScroller {\n    get SCROLL_WIDTH() {\n        return 8;\n    }\n    get RADIUS() {\n        return 2.5;\n    }\n    constructor(board) {\n        this.board = board;\n        this.board.changeEvent.attach(this, this.#reset);\n\n        this.svgGroup = null;\n\n        this.hX = 0;\n        this.vWidth = 0;\n        this.vY = 0;\n        this.vRatio = 0;\n        this._visible = true;\n        this._opacity = -1;\n\n        this.createScrollBar();\n        this.setOpacity(0);\n\n        $(this.vScrollbar).bind('mousedown', this.#onMouseDown.bind(this));\n\n        this._domHeight = 0;\n        this._dResizeScrollBar = debounce(this.resizeScrollBar, 50);\n        if (Entry.windowResized) {\n            Entry.windowResized.attach(this, this._dResizeScrollBar);\n        }\n    }\n\n    createScrollBar() {\n        const r = this.RADIUS;\n        const width = this.SCROLL_WIDTH;\n        const { common = {} } = EntryStatic.colorSet || {};\n\n        this.svgGroup = this.board.svgGroup.elem('g', {\n            class: 'boardScrollbar',\n        });\n\n        this.vScrollbar = this.svgGroup.elem('rect', {\n            width,\n            rx: r,\n            ry: r,\n            fill: common.SCROLL_BAR || '#aac5d5',\n            class: 'scrollbar',\n        });\n    }\n\n    resizeScrollBar() {\n        this.#updateRatio();\n\n        const dom = this.board.blockMenuContainer;\n        const newHeight = dom.height();\n        if (newHeight !== this._domHeight) {\n            this._domHeight = newHeight;\n            return this.board.align();\n        }\n        if (!this._visible || this.vRatio === 0) {\n            return;\n        }\n\n        if (this.vRatio === 0) {\n            return;\n        }\n\n        const width = this.SCROLL_WIDTH;\n        this.vScrollbar.attr({\n            width,\n            height: dom.height() / this.vRatio,\n            x: dom.width() - 13,\n        });\n    }\n\n    updateScrollBar(dy) {\n        this.vY += dy;\n        this.vScrollbar.attr({ y: this.vY });\n    }\n\n    scroll(dy) {\n        if (!this.isVisible()) {\n            return;\n        }\n        const dest = this.#adjustValue(dy);\n\n        dy = dest - this.vY;\n        if (dy === 0) {\n            return;\n        }\n\n        this.board.code.moveBy(0, -dy * this.vRatio);\n        this.updateScrollBar(dy);\n    }\n\n    scrollByPx(px) {\n        if (!this.vRatio) {\n            this.#updateRatio();\n        }\n        this.scroll(px / this.vRatio);\n    }\n\n    setVisible(visible) {\n        if (visible === this.isVisible()) {\n            return;\n        }\n        this._visible = visible;\n        this.svgGroup.attr({\n            display: visible === true ? 'block' : 'none',\n        });\n    }\n\n    getOpacity() {\n        return this._opacity;\n    }\n\n    setOpacity(value) {\n        if (this._opacity == value) {\n            return;\n        }\n        this.vScrollbar.attr({\n            opacity: value,\n        });\n        this._opacity = value;\n    }\n\n    isVisible() {\n        return this._visible;\n    }\n\n    #updateRatio() {\n        const board = this.board;\n        const bRect = board.svgBlockGroup.getBBox();\n        const realHeight = board.blockMenuContainer.height();\n\n        const vRatio = (bRect.height + 20) / realHeight;\n        this.vRatio = vRatio;\n        if (vRatio <= 1) {\n            this.setVisible(false);\n        } else {\n            this.setVisible(true);\n        }\n    }\n\n    #reset() {\n        this.vY = 0;\n        this.vScrollbar.attr({\n            y: this.vY,\n        });\n        this._dResizeScrollBar();\n    }\n\n    //adjust value by dy for min/max value\n    #adjustValue(dy) {\n        const domHeight = this.board.svgDom.height();\n        const limitBottom = domHeight - domHeight / this.vRatio;\n        let newY = this.vY + dy;\n\n        newY = Math.max(0, newY);\n        newY = Math.min(limitBottom, newY);\n\n        return newY;\n    }\n\n    #onMouseDown(e) {\n        const onMouseMove = (e) => {\n            if (e.stopPropagation) {\n                e.stopPropagation();\n            }\n            if (e.preventDefault) {\n                e.preventDefault();\n            }\n            if (e.which == 2) {\n                console.log('mouse wheel click disabled');\n                return;\n            }\n\n            let mouseEvent;\n            if (e.originalEvent && e.originalEvent.touches) {\n                mouseEvent = e.originalEvent.touches[0];\n            } else {\n                mouseEvent = e;\n            }\n\n            const dragInstance = this.dragInstance;\n            this.scroll(mouseEvent.pageY - dragInstance.offsetY);\n\n            dragInstance.set({\n                offsetY: mouseEvent.pageY,\n            });\n        };\n        const onMouseUp = () => {\n            $(document).unbind('.scroll');\n            delete this.dragInstance;\n        };\n\n        if (e.stopPropagation) {\n            e.stopPropagation();\n        }\n        if (e.preventDefault) {\n            e.preventDefault();\n        }\n\n        if (e.button === 0 || (e.originalEvent && e.originalEvent.touches)) {\n            if (Entry.documentMousedown) {\n                Entry.documentMousedown.notify(e);\n            }\n\n            let mouseEvent;\n            if (e.originalEvent && e.originalEvent.touches) {\n                mouseEvent = e.originalEvent.touches[0];\n            } else {\n                mouseEvent = e;\n            }\n\n            const doc = $(document);\n            doc.bind('mousemove.scroll', onMouseMove);\n            doc.bind('mouseup.scroll', onMouseUp);\n            this.dragInstance = new Entry.DragInstance({\n                startY: mouseEvent.pageY,\n                offsetY: mouseEvent.pageY,\n            });\n        }\n\n        e.stopPropagation();\n    }\n}\n\nEntry.BlockMenuScroller = BlockMenuScroller;\n\n(function(p) {})(Entry.BlockMenuScroller.prototype);\n"
  },
  {
    "path": "src/playground/block_view.js",
    "content": "import debounce from 'lodash/debounce';\nimport _get from 'lodash/get';\nimport Hammer from 'hammerjs';\n\nEntry.BlockView = class BlockView {\n    schema = {\n        id: 0,\n        type: Entry.STATIC.BLOCK_RENDER_MODEL,\n        x: 0,\n        y: 0,\n        offsetX: 0,\n        offsetY: 0,\n        width: 0,\n        height: 0,\n        contentWidth: 0,\n        contentHeight: 0,\n        topFieldHeight: 0,\n        marginBottom: 0,\n        magneting: false,\n        visible: true,\n        animating: false,\n        shadow: true,\n        display: true,\n    };\n\n    constructor(block, board, mode) {\n        const that = this;\n        Entry.Model(this, false);\n        this.block = block;\n        this._lazyUpdatePos = debounce(block._updatePos.bind(block), 200);\n        this.mouseUpEvent = new Entry.Event(this);\n        this.disableMouseEvent = false;\n\n        this.dAlignContent = this.alignContent;\n        this._board = board;\n        this._observers = [];\n        this.set(block);\n        const hash = Entry.generateHash();\n        this.svgGroup = board.svgBlockGroup.elem('g');\n        this.svgGroup.attr('id', hash);\n        this.svgGroup.blockView = this;\n        if (block.isCommentable() && board.svgCommentGroup) {\n            this.svgCommentGroup = board.svgCommentGroup.elem('g');\n            this.svgCommentGroup.attr('id', `${hash}C`);\n            this.svgCommentGroup.blockView = this;\n        }\n\n        this._schema = Entry.skinContainer.getSkin(block);\n\n        if (this._schema === undefined) {\n            this.block.destroy(false, false);\n            return;\n        }\n\n        if (mode === undefined) {\n            const workspace = this.getBoard().workspace;\n            if (workspace && workspace.getBlockViewRenderMode) {\n                this.renderMode = workspace.getBlockViewRenderMode();\n            } else {\n                this.renderMode = Entry.BlockView.RENDER_MODE_BLOCK;\n            }\n        } else {\n            this.renderMode = Entry.BlockView.RENDER_MODE_BLOCK;\n        }\n\n        if (this._schema.deletable) {\n            this.block.setDeletable(this._schema.deletable);\n        }\n        if (this._schema.copyable) {\n            this.block.setCopyable(this._schema.copyable);\n        }\n        if (this._schema.display === false || block.display === false) {\n            this.set({ display: false });\n        }\n        this._skeleton = Entry.skeleton[this._schema.skeleton];\n        const skeleton = this._skeleton;\n        this._contents = [];\n        this._statements = [];\n        this._extensions = [];\n        this.magnet = {};\n        this._paramMap = {};\n\n        if (skeleton.magnets && skeleton.magnets(this).next) {\n            this.svgGroup.nextMagnet = this.block;\n            this._nextGroup = this.svgGroup.elem('g');\n            this._nextCommentGroup = this.svgCommentGroup && this.svgCommentGroup.elem('g');\n            this._observers.push(this.observe(this, '_updateMagnet', ['contentHeight']));\n        }\n\n        this.isInBlockMenu = this.getBoard() instanceof Entry.BlockMenu;\n        this.mouseHandler = function(e) {\n            (_.result(that.block.events, 'mousedown') || []).forEach((fn) => {\n                if (Entry.documentMousedown) {\n                    Entry.documentMousedown.notify(e);\n                }\n                return fn(that);\n            });\n            that.onMouseDown(...arguments);\n        };\n\n        this._startRender(block, mode);\n\n        // observe\n        const thisBlock = this.block;\n        this._observers.push(thisBlock.observe(this, '_setMovable', ['movable']));\n        this._observers.push(thisBlock.observe(this, '_setReadOnly', ['movable']));\n        this._observers.push(thisBlock.observe(this, '_setCopyable', ['copyable']));\n        this._observers.push(thisBlock.observe(this, '_updateColor', ['deletable'], false));\n        this._observers.push(this.observe(this, '_updateBG', ['magneting'], false));\n\n        this._observers.push(this.observe(this, '_updateOpacity', ['visible'], false));\n        this._observers.push(this.observe(this, '_updateDisplay', ['display']));\n        this._observers.push(this.observe(this, '_updateMagnet', ['offsetY']));\n        this._observers.push(board.code.observe(this, '_setBoard', ['board'], false));\n\n        this.dragMode = Entry.DRAG_MODE_NONE;\n        Entry.Utils.disableContextmenu(this.svgGroup.node);\n        const events = block.events.viewAdd || [];\n        if (Entry.type === 'workspace' && this._board instanceof Entry.Board) {\n            events.forEach((fn) => {\n                if (_.isFunction(fn)) {\n                    fn(block);\n                }\n            });\n        }\n\n        this.onMouseMove = this.onMouseMove.bind(this);\n        this.onMouseUp = this.onMouseUp.bind(this);\n    }\n\n    _startRender(block, mode) {\n        const skeleton = this._skeleton;\n        const attr = { class: 'block' };\n\n        if (this.display === false) {\n            attr.display = 'none';\n        }\n\n        const svgGroup = this.svgGroup;\n\n        svgGroup.attr(attr);\n\n        (skeleton.classes || []).forEach((c) => svgGroup.addClass(c));\n\n        const path = skeleton.path(this);\n\n        this.pathGroup = svgGroup.prepend('g');\n        this._updateMagnet();\n\n        this._path = this.pathGroup.elem('path');\n\n        let fillColor = this._schema.color;\n        const { deletable, emphasized } = this.block;\n\n        if (deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN || emphasized) {\n            fillColor = this._schema.emphasizedColor || Entry.Utils.getEmphasizeColor(fillColor);\n        }\n\n        this._fillColor = fillColor;\n\n        const pathStyle = {\n            d: path,\n            fill: fillColor,\n            class: 'blockPath',\n            blockId: this.id,\n        };\n\n        const blockSchema = this._schema;\n        const { outerLine } = blockSchema;\n        pathStyle.stroke = outerLine || skeleton.outerLine;\n        pathStyle['stroke-linejoin'] = 'round';\n        pathStyle['stroke-linecap'] = 'round';\n\n        if (skeleton.stroke) {\n            pathStyle['stroke-width'] = '1';\n        }\n        this._path.attr(pathStyle);\n        this.moveTo(this.x, this.y, false);\n        this._startContentRender(mode);\n        this._startExtension(mode);\n        if (this._board.disableMouseEvent !== true) {\n            this._addControl();\n        }\n\n        const guide = this.guideSvgGroup;\n        guide && svgGroup.insertBefore(guide, svgGroup.firstChild);\n\n        this.bindPrev();\n    }\n\n    _startContentRender(mode) {\n        mode = _.isUndefined(mode) ? this.renderMode : mode;\n\n        const _removeFunc = _.partial(_.result, _, 'remove');\n\n        _removeFunc(this.contentSvgGroup);\n        _removeFunc(this.statementSvgGroup);\n        if (this.statementCommentGroup) {\n            _removeFunc(this.statementCommentGroup);\n        }\n\n        this.contentSvgGroup = this.svgGroup.elem('g');\n        this._contents = [];\n\n        const schema = this._schema;\n        const statements = schema.statements;\n\n        if (!_.isEmpty(statements)) {\n            this.statementSvgGroup = this.svgGroup.elem('g');\n            this.statementCommentGroup = this.svgCommentGroup && this.svgCommentGroup.elem('g');\n        }\n\n        const reg = /(%\\d+)/im;\n        const parsingReg = /%(\\d+)/im;\n        let parsingRet;\n\n        let template = this._getTemplate(mode) || '';\n        const params = this._getSchemaParams(mode);\n\n        if (mode === Entry.BlockView.RENDER_MODE_TEXT) {\n            if (\n                /(if)+(.|\\n)+(else)+/gim.test(template) &&\n                !reg.test(template) &&\n                this.isInBlockMenu\n            ) {\n                template = template.replace('else', `%${params.length} else`);\n            }\n        }\n\n        const _renderMode = mode || this.renderMode;\n        template &&\n            template.split(reg).forEach((param, i) => {\n                if (param[0] === ' ') {\n                    param = param.substring(1);\n                }\n                if (param[param.length - 1] === ' ') {\n                    param = param.substring(0, param.length - 1);\n                }\n                if (!param?.length) {\n                    return;\n                }\n\n                parsingRet = parsingReg.exec(param);\n                if (parsingRet) {\n                    const paramIndex = parsingRet[1] - 1;\n                    param = params[paramIndex];\n                    // params[paramIndex]= null||undefined 일 수 있는 경우에 대한 방어 코드\n                    if (!param) {\n                        return;\n                    }\n                    const field = new Entry[`Field${param.type}`](\n                        param,\n                        this,\n                        paramIndex,\n                        _renderMode,\n                        i\n                    );\n                    this._contents.push(field);\n                    this._paramMap[paramIndex] = field;\n                } else {\n                    this._contents.push(\n                        new Entry.FieldText({ text: param, color: schema.fontColor }, this)\n                    );\n                }\n            });\n\n        (schema.statements || []).forEach((s, i) => {\n            this._statements.push(new Entry.FieldStatement(s, this, i));\n        });\n\n        this.alignContent(false);\n    }\n\n    _startExtension(mode) {\n        this._extensions = this.block.extensions.map(\n            (e) => new Entry[`Ext${e.type}`](e, this, mode)\n        );\n    }\n\n    _updateSchema = this._startContentRender;\n\n    changeType(type) {\n        this._schema = Entry.block[type || this.type];\n        this._skeleton = Entry.skeleton[this._schema.skeleton];\n\n        this._updateSchema();\n    }\n\n    alignContent(animate) {\n        this.resetBackgroundPath();\n        if (animate !== true) {\n            animate = false;\n        }\n        const cursor = { x: 0, y: 0, height: 0 };\n        let statementIndex = 0;\n        let width = 0;\n        let secondLineHeight = 0;\n\n        for (let i = 0; i < this._contents.length; i++) {\n            const c = this._contents[i];\n            if (c instanceof Entry.FieldLineBreak) {\n                this._alignStatement(animate, statementIndex);\n                c.align(statementIndex);\n                statementIndex++;\n                cursor.y = c.box.y;\n                cursor.x = 8;\n            } else {\n                c.align(cursor.x, cursor.y, animate);\n                // space between content\n                if (\n                    i !== this._contents.length - 1 &&\n                    !(c instanceof Entry.FieldText && c._text.length === 0)\n                ) {\n                    cursor.x += Entry.BlockView.PARAM_SPACE;\n                }\n            }\n\n            const box = c.box;\n            if (statementIndex !== 0) {\n                secondLineHeight = Math.max(Math.round(box.height) * 1000000, secondLineHeight);\n            } else {\n                cursor.height = Math.max(box.height, cursor.height);\n            }\n\n            cursor.x += box.width;\n            width = Math.max(width, cursor.x);\n            if (this.contentWidth !== width || this.contentHeight !== cursor.height) {\n                this.set({\n                    contentWidth: width,\n                    contentHeight: cursor.height,\n                });\n            }\n        }\n\n        if (secondLineHeight) {\n            this.set({\n                contentHeight: cursor.height + secondLineHeight,\n            });\n        }\n\n        if (this._statements.length != statementIndex) {\n            this._alignStatement(animate, statementIndex);\n        }\n\n        const contentPos = this.getContentPos();\n        this.contentSvgGroup.attr('transform', `translate(${contentPos.x},${contentPos.y})`);\n        this.contentPos = contentPos;\n        this._render();\n        const comment = this.block.comment;\n        if (comment instanceof Entry.Comment) {\n            comment.updateParentPos();\n        }\n\n        this._updateMagnet();\n        const ws = this.getBoard().workspace;\n        if (ws && (this.isFieldEditing() || ws.widgetUpdateEveryTime)) {\n            ws.widgetUpdateEvent.notify();\n        }\n    }\n\n    isFieldEditing() {\n        const contents = this._contents;\n        for (let i = 0; i < contents.length; i++) {\n            const content = contents[i] || {};\n            if (content.isEditing && content.isEditing()) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    _alignStatement(animate, index) {\n        const positions = this._skeleton.statementPos ? this._skeleton.statementPos(this) : [];\n        const statement = this._statements[index];\n        if (!statement) {\n            return;\n        }\n        const pos = positions[index];\n        if (pos) {\n            statement.align(pos.x, pos.y, animate);\n        }\n    }\n\n    _render() {\n        this._renderPath();\n        this.set(this._skeleton.box(this));\n    }\n\n    _renderPath() {\n        const newPath = this._skeleton.path(this);\n\n        //no change occured\n        if (this._path.getAttribute('d') === newPath) {\n            return;\n        }\n\n        if (false && Entry.ANIMATION_DURATION !== 0) {\n            const that = this;\n            setTimeout(() => {\n                that._path.animate({ d: newPath }, Entry.ANIMATION_DURATION, mina.easeinout);\n            }, 0);\n        } else {\n            this._path.attr({ d: newPath });\n            this.animating === true && this.set({ animating: false });\n        }\n    }\n\n    _setPosition() {\n        const board = this.getBoard();\n        const { scale = 1 } = board || {};\n        if (!(this.x || this.y)) {\n            this.svgGroup.removeAttr('transform');\n            this.svgCommentGroup && this.svgCommentGroup.removeAttr('transform');\n        } else {\n            const transform = `translate(${this.x / scale},${this.y / scale})`;\n            this.svgGroup.attr('transform', transform);\n            this.svgCommentGroup && this.svgCommentGroup.attr('transform', transform);\n        }\n    }\n\n    moveTo(x, y, animate, doNotUpdatePos) {\n        const thisX = this.x;\n        const thisY = this.y;\n        if (!this.display) {\n            x = -99999;\n            y = -99999;\n        }\n        if (thisX !== x || thisY !== y) {\n            this.set({ x, y });\n        }\n\n        doNotUpdatePos !== true && this._lazyUpdatePos();\n\n        if (this.visible && this.display) {\n            this._setPosition(animate);\n        }\n    }\n\n    moveBy(x, y, animate, doNotUpdatePos) {\n        return this.moveTo(this.x + x, this.y + y, animate, doNotUpdatePos);\n    }\n\n    _addControl() {\n        this._mouseEnable = true;\n\n        const dblclick = _.result(this.block.events, 'dblclick');\n        if (dblclick) {\n            const hammer = new Hammer(this.pathGroup);\n            hammer.on('doubletap', () => {\n                if (this._board.readOnly) {\n                    return;\n                }\n                dblclick.forEach((fn) => {\n                    if (fn) {\n                        fn(this);\n                    }\n                });\n            });\n            $(this.pathGroup).dblclick(() => {\n                if (this._board.readOnly) {\n                    return;\n                }\n                dblclick.forEach((fn) => {\n                    if (fn) {\n                        fn(this);\n                    }\n                });\n            });\n        }\n\n        $(this.svgGroup).bind(\n            'mousedown.blockViewMousedown touchstart.blockViewMousedown',\n            this.mouseHandler\n        );\n    }\n\n    removeControl() {\n        this._mouseEnable = false;\n        $(this.svgGroup).unbind('.blockViewMousedown');\n    }\n\n    setSelectedBlock(board) {\n        const { workspace } = board;\n        const { selectedBlockView } = workspace;\n        const wsBoard = selectedBlockView ? selectedBlockView.getBoard() : board;\n        if (board !== wsBoard) {\n            wsBoard.setSelectedBlock(null);\n        } else {\n            board.setSelectedBlock(this);\n        }\n    }\n\n    onMouseDown(e) {\n        if (!this.isInBlockMenu && e.stopPropagation) {\n            e.stopPropagation();\n        }\n        if (e.preventDefault) {\n            e.preventDefault();\n        }\n        if (e.which == 2) {\n            console.log('mouse wheel click disabled');\n            return;\n        }\n        if (e.button == 1) {\n            return;\n        }\n        if (Entry.disposeEvent) {\n            Entry.disposeEvent.notify();\n        }\n\n        this.longPressTimer = null;\n\n        const board = this.getBoard();\n        if (board.workingEvent) {\n            return;\n        }\n\n        if (this.readOnly || board.viewOnly) {\n            return;\n        }\n\n        board.workingEvent = true;\n        this.setSelectedBlock(board);\n\n        //left mousedown\n        if (\n            (e.button === 0 || (e.originalEvent && e.originalEvent.touches) || e.touches) &&\n            !this._board.readOnly\n        ) {\n            const eventType = e.type;\n            let mouseEvent;\n            if (e.originalEvent && e.originalEvent.touches) {\n                mouseEvent = e.originalEvent.touches[0];\n            } else if (e.touches) {\n                mouseEvent = e.touches[0];\n            } else {\n                mouseEvent = e;\n            }\n\n            this.mouseDownCoordinate = {\n                x: mouseEvent.pageX,\n                y: mouseEvent.pageY,\n            };\n            const $doc = $(document);\n\n            if (!this.disableMouseEvent) {\n                $doc.bind('mousemove.block', this.onMouseMove);\n                document.addEventListener('touchmove', this.onMouseMove, { passive: false });\n            }\n            $doc.bind('mouseup.block', this.onMouseUp);\n            document.addEventListener('touchend', this.onMouseUp);\n            this.dragInstance = new Entry.DragInstance({\n                startX: mouseEvent.pageX,\n                startY: mouseEvent.pageY,\n                offsetX: mouseEvent.pageX,\n                offsetY: mouseEvent.pageY,\n                height: 0,\n                mode: true,\n            });\n            board.set({ dragBlock: this });\n            this.addDragging();\n            this.dragMode = Entry.DRAG_MODE_MOUSEDOWN;\n\n            if (eventType === 'touchstart' || Entry.isMobile()) {\n                this.longPressTimer = setTimeout(() => {\n                    if (this.longPressTimer) {\n                        this.longPressTimer = null;\n                        this.onMouseUp(e);\n                        this._rightClick(e, 'longPress');\n                    }\n                }, 700);\n            }\n        } else if (Entry.Utils.isRightButton(e)) {\n            this._rightClick(e);\n        }\n\n        if (board.workspace.getMode() === Entry.Workspace.MODE_VIMBOARD && e) {\n            document\n                .getElementsByClassName('CodeMirror')[0]\n                .dispatchEvent(Entry.Utils.createMouseEvent('dragStart', e));\n        }\n    }\n\n    getVerticalMove(mouseEvent, dragInstance) {\n        const dx = Math.abs(mouseEvent.pageX - dragInstance.offsetX);\n        const dy = Math.abs(mouseEvent.pageY - dragInstance.offsetY);\n        return dy / dx > 1.75;\n    }\n\n    onMouseMove(e) {\n        e.stopPropagation();\n        e.preventDefault();\n        const board = this.getBoard();\n        const workspaceMode = board.workspace.getMode();\n\n        let mouseEvent;\n        if (workspaceMode === Entry.Workspace.MODE_VIMBOARD) {\n            this.vimBoardEvent(e, 'dragOver');\n        }\n        if (e.originalEvent && e.originalEvent.touches) {\n            mouseEvent = e.originalEvent.touches[0];\n        } else if (e.touches) {\n            mouseEvent = e.touches[0];\n        } else {\n            mouseEvent = e;\n        }\n\n        const mouseDownCoordinate = this.mouseDownCoordinate;\n        const diff = Math.sqrt(\n            Math.pow(mouseEvent.pageX - mouseDownCoordinate.x, 2) +\n            Math.pow(mouseEvent.pageY - mouseDownCoordinate.y, 2)\n        );\n        if (this.dragMode == Entry.DRAG_MODE_DRAG || diff > Entry.BlockView.DRAG_RADIUS) {\n            const blockView = this;\n            if (\n                (blockView.isInBlockMenu &&\n                    this.longPressTimer &&\n                    this.getVerticalMove(mouseEvent, blockView.dragInstance)) ||\n                this.isVerticalMove\n            ) {\n                this.isVerticalMove = true;\n                return;\n            } else {\n                $(document).unbind('.blockMenu');\n            }\n\n            if (this.longPressTimer) {\n                clearTimeout(this.longPressTimer);\n                this.longPressTimer = null;\n            }\n            if (!this.movable) {\n                return;\n            }\n\n            if (!this.isInBlockMenu) {\n                let isFirst = false;\n\n                if (this.dragMode != Entry.DRAG_MODE_DRAG) {\n                    this._toGlobalCoordinate(undefined, true);\n                    this.dragMode = Entry.DRAG_MODE_DRAG;\n                    this.block.getThread().changeEvent.notify();\n                    Entry.GlobalSvg.setView(this, workspaceMode);\n                    isFirst = true;\n                    this.fromBlockMenu = this.dragInstance && this.dragInstance.isNew;\n                }\n\n                if (this.animating) {\n                    this.set({ animating: false });\n                }\n\n                if (this.dragInstance.height === 0) {\n                    const height = -1 + this.height;\n                    this.dragInstance.set({ height });\n                }\n\n                const dragInstance = this.dragInstance;\n                this.moveBy(\n                    mouseEvent.pageX - dragInstance.offsetX,\n                    mouseEvent.pageY - dragInstance.offsetY,\n                    false,\n                    true\n                );\n                Entry.GlobalSvg.position();\n\n                dragInstance.set({\n                    offsetX: mouseEvent.pageX,\n                    offsetY: mouseEvent.pageY,\n                });\n\n                if (!this.originPos) {\n                    this.originPos = {\n                        x: this.x,\n                        y: this.y,\n                    };\n                }\n                if (isFirst) {\n                    board.generateCodeMagnetMap();\n                }\n                this._updateCloseBlock();\n            } else {\n                board.cloneToGlobal(e);\n                // this.terminateEvent();\n            }\n        }\n    }\n\n    terminateEvent() {\n        const $doc = $(document);\n        document.removeEventListener('touchmove', this.onMouseMove, { passive: false });\n        document.removeEventListener('touchend', this.onMouseUp);\n        $doc.unbind('.block', this.onMouseUp);\n        $doc.unbind('.block', this.onMouseMove);\n    }\n\n    onMouseUp(e) {\n        if (e.which == 2) {\n            console.log('mouse wheel click disabled');\n            return;\n        }\n        if (e.button == 1) {\n            return;\n        }\n        if (this.longPressTimer) {\n            clearTimeout(this.longPressTimer);\n            this.longPressTimer = null;\n        }\n        this.terminateEvent();\n        this.terminateDrag(e);\n        const board = this.getBoard();\n        if (board) {\n            board.set({ dragBlock: null });\n            delete board.workingEvent;\n        }\n        this._setHoverBlockView({ that: this });\n        Entry.GlobalSvg.remove();\n        this.mouseUpEvent.notify();\n\n        delete this.isVerticalMove;\n        delete this.mouseDownCoordinate;\n        delete this.dragInstance;\n        delete this.magnetsOfThread;\n    }\n\n    vimBoardEvent(event, type, block) {\n        if (!event) {\n            return;\n        }\n        const dragEvent = Entry.Utils.createMouseEvent(type, event);\n        if (block) {\n            dragEvent.block = block;\n        }\n        $('.entryVimBoard>.CodeMirror')[0].dispatchEvent(dragEvent);\n    }\n\n    terminateDrag(e) {\n        const gs = Entry.GlobalSvg;\n        const board = this.getBoard();\n        const dragMode = this.dragMode;\n        const block = this.block;\n        const workspaceMode = board.workspace.getMode();\n        this.removeDragging();\n        this.set({ visible: true });\n        this.dragMode = Entry.DRAG_MODE_NONE;\n\n        const gsRet = gs.terminateDrag(this);\n\n        if (workspaceMode === Entry.Workspace.MODE_VIMBOARD) {\n            if (board instanceof Entry.BlockMenu) {\n                board.terminateDrag();\n                gsRet === gs.DONE && this.vimBoardEvent(e, 'dragEnd', block);\n            } else {\n                board.clear();\n            }\n        } else {\n            const fromBlockMenu = this.dragInstance && this.dragInstance.isNew;\n            if (dragMode === Entry.DRAG_MODE_DRAG) {\n                let ripple = false;\n                const prevBlock = this.block.getPrevBlock(this.block);\n                let suffix = this._board.workspace.trashcan.isOver ? 'ForDestroy' : '';\n                switch (gsRet) {\n                    case gs.DONE: {\n                        let closeBlock = board.magnetedBlockView;\n                        if (closeBlock instanceof Entry.BlockView) {\n                            closeBlock = closeBlock.block;\n                        }\n                        if (prevBlock && !closeBlock) {\n                            Entry.do(`separateBlock${suffix}`, block);\n                        } else if (!prevBlock && !closeBlock && !fromBlockMenu) {\n                            if (!block.getThread().view.isGlobal()) {\n                                Entry.do(`separateBlock${suffix}`, block);\n                            } else {\n                                Entry.do(`moveBlock${suffix}`, block);\n                                this.dominate();\n                            }\n                        } else {\n                            suffix = fromBlockMenu ? 'FromBlockMenu' : '';\n                            if (closeBlock) {\n                                if (closeBlock.view.magneting === 'next') {\n                                    this.dragMode = dragMode;\n                                    const targetPointer = closeBlock.pointer();\n                                    targetPointer[3] = -1;\n                                    Entry.do(`insertBlock${suffix}`, block, targetPointer).isPass(\n                                        fromBlockMenu\n                                    );\n\n                                    Entry.ConnectionRipple.setView(closeBlock.view).dispose();\n                                    this.dragMode = Entry.DRAG_MODE_NONE;\n                                } else {\n                                    if (closeBlock.getThread) {\n                                        const thread = closeBlock.getThread();\n                                        const closeBlockType = closeBlock.type;\n                                        if (\n                                            closeBlockType &&\n                                            thread instanceof Entry.FieldBlock &&\n                                            !Entry.block[closeBlockType].isPrimitive\n                                        ) {\n                                            suffix += 'FollowSeparate';\n                                        }\n                                    }\n                                    Entry.do(`insertBlock${suffix}`, block, closeBlock).isPass(\n                                        fromBlockMenu\n                                    );\n                                    ripple = true;\n                                }\n                                Entry.Utils.playSound('entryMagneting');\n                            } else {\n                                Entry.do(`moveBlock${suffix}`, block).isPass(fromBlockMenu);\n                                this.dominate();\n                            }\n                        }\n                        break;\n                    }\n                    case gs.RETURN: {\n                        const block = this.block;\n                        if (fromBlockMenu) {\n                            Entry.do('destroyBlockBelow', this.block).isPass(true);\n                        } else {\n                            if (prevBlock) {\n                                this.set({ animating: false });\n                                Entry.Utils.playSound('entryMagneting');\n                                this.bindPrev(prevBlock);\n                                block.insert(prevBlock);\n                            } else {\n                                const parent = block.getThread().view.getParent();\n\n                                if (!(parent instanceof Entry.Board)) {\n                                    Entry.Utils.playSound('entryMagneting');\n                                    Entry.do('insertBlock', block, parent);\n                                } else {\n                                    const originPos = this.originPos;\n                                    this.moveTo(originPos.x, originPos.y, false);\n                                    this.dominate();\n                                }\n                            }\n                        }\n                        break;\n                    }\n                    case gs.REMOVE:\n                        Entry.Utils.playSound('entryDelete');\n                        Entry.do('destroyBlockBelow', this.block).isPass(fromBlockMenu);\n                        break;\n                }\n\n                board.setMagnetedBlock(null);\n                if (ripple) {\n                    Entry.ConnectionRipple.setView(block.view).dispose();\n                }\n            } else if (\n                gsRet === gs.REMOVE &&\n                fromBlockMenu &&\n                dragMode === Entry.DRAG_MODE_MOUSEDOWN\n            ) {\n                Entry.do('destroyBlockBelow', this.block).isPass(true);\n            }\n        }\n\n        this.destroyShadow();\n        delete this.originPos;\n    }\n\n    _getMagnetsInThread() {\n        const magnet = { ...this.magnet };\n\n        const lastBlock = this.block.thread?.getLastBlock?.();\n        const next = lastBlock?.view?.magnet?.next;\n        if (next) {\n            magnet.next = next;\n        } else {\n            delete magnet.next;\n        }\n\n        return magnet;\n    }\n\n    _updateCloseBlock() {\n        if (!this._skeleton.magnets) {\n            return;\n        }\n\n        const board = this.getBoard();\n        const { scale = 1 } = board || {};\n        const x = this.x / scale;\n        const y = this.y / scale;\n        if (!this.magnetsOfThread) {\n            this.magnetsOfThread = this._getMagnetsInThread();\n        }\n        for (const type in this.magnetsOfThread) {\n            const view = _.result(\n                board.getNearestMagnet(x, type === 'next' ? y + this.getBelowHeight() : y, type),\n                'view'\n            );\n\n            if (view) {\n                return board.setMagnetedBlock(view, type);\n            }\n        }\n        board.setMagnetedBlock(null);\n    }\n\n    dominate() {\n        this.block.getThread().view.dominate();\n        const board = this.getBoard();\n        board.scroller.resizeScrollBar.call(board.scroller);\n    }\n\n    getSvgRoot() {\n        const svgBlockGroup = this.getBoard().svgBlockGroup;\n        let node = this.svgGroup;\n        while (node.parentNode !== svgBlockGroup) {\n            node = node.parentNode;\n        }\n        return node;\n    }\n\n    getBoard() {\n        return this._board;\n    }\n\n    getComment() {\n        return this.block.comment;\n    }\n\n    _setBoard() {\n        this._board = this._board.code.board;\n    }\n\n    destroy(animate) {\n        this.block.set({ view: null });\n        $(this.svgGroup).unbind('.blockViewMousedown');\n        this._destroyObservers();\n        const svgGroup = this.svgGroup;\n\n        const _destroyFunc = _.partial(_.result, _, 'destroy');\n\n        if (animate) {\n            $(svgGroup).fadeOut(100, () => svgGroup.remove());\n        } else {\n            svgGroup.remove();\n        }\n        this.svgCommentGroup && this.svgCommentGroup.remove();\n\n        (this._contents || []).forEach(_destroyFunc);\n        (this._statements || []).forEach(_destroyFunc);\n\n        const block = this.block;\n        if (Entry.type === 'workspace' && !this.isInBlockMenu) {\n            (block.events.viewDestroy || []).forEach((fn) => {\n                if (_.isFunction(fn)) {\n                    const notIncludeSelf = !!block?.thread?.acceptType;\n                    fn(block, notIncludeSelf);\n                }\n            });\n        }\n    }\n\n    getShadow() {\n        if (!this._shadow) {\n            this._shadow = Entry.SVG.createElement(this.svgGroup.cloneNode(true), { opacity: 0.5 });\n            this.getBoard().svgGroup.appendChild(this._shadow);\n        }\n        return this._shadow;\n    }\n\n    destroyShadow() {\n        _.result(this._shadow, 'remove');\n        delete this._shadow;\n    }\n\n    _updateMagnet() {\n        if (!this._skeleton.magnets) {\n            return;\n        }\n        const magnet = this._skeleton.magnets(this);\n\n        if (magnet.next) {\n            this._nextGroup &&\n                this._nextGroup.attr('transform', `translate(${magnet.next.x},${magnet.next.y})`);\n            this._nextCommentGroup &&\n                this._nextCommentGroup.attr(\n                    'transform',\n                    `translate(${magnet.next.x},${magnet.next.y})`\n                );\n        }\n        this.magnet = magnet;\n        this.block.getThread().changeEvent.notify();\n    }\n\n    _updateBG() {\n        const dragBlock = this._board.dragBlock;\n        if (!dragBlock || !dragBlock.dragInstance) {\n            return;\n        }\n\n        const blockView = this;\n        const svgGroup = blockView.svgGroup;\n        if (!(this.magnet.next || this.magnet.previous)) {\n            // field block\n            if (this.magneting) {\n                svgGroup.attr({\n                    filter: `url(#entryBlockHighlightFilter_${this.getBoard().suffix})`,\n                });\n                svgGroup.addClass('outputHighlight');\n            } else {\n                svgGroup.removeClass('outputHighlight');\n                svgGroup.removeAttr('filter');\n            }\n            return;\n        }\n        const magneting = blockView.magneting;\n        if (magneting) {\n            const shadow = dragBlock.getShadow();\n            const pos = this.getAbsoluteCoordinate();\n            let magnet;\n            let transform;\n            if (magneting === 'previous') {\n                magnet = this.magnet.next;\n                transform = `translate(${pos.scaleX + magnet.x},${pos.scaleY + magnet.y})`;\n            } else if (magneting === 'next') {\n                magnet = this.magnet.previous;\n                const dragHeight = dragBlock.getBelowHeight();\n                const nextX = _get(dragBlock, 'magnet.next.x');\n                transform = `translate(${pos.scaleX + magnet.x - nextX},${pos.scaleY + magnet.y - dragHeight\n                    })`;\n            }\n\n            const $shadow = $(shadow);\n            $shadow.attr({\n                transform,\n            });\n            $shadow.removeAttr('display');\n\n            this._clonedShadow = shadow;\n\n            if (blockView.background) {\n                blockView.background.remove();\n                blockView.nextBackground.remove();\n                delete blockView.background;\n                delete blockView.nextBackground;\n            }\n\n            if (magneting === 'previous' && dragBlock.block.thread instanceof Entry.Thread) {\n                const height = dragBlock.getBelowHeight() + this.offsetY;\n                blockView.originalHeight = blockView.offsetY;\n                blockView.set({\n                    offsetY: height,\n                });\n            }\n        } else {\n            if (this._clonedShadow) {\n                this._clonedShadow.attr({\n                    display: 'none',\n                });\n                delete this._clonedShadow;\n            }\n\n            const height = blockView.originalHeight;\n            if (height !== undefined) {\n                if (blockView.background) {\n                    blockView.background.remove();\n                    blockView.nextBackground.remove();\n                    delete blockView.background;\n                    delete blockView.nextBackground;\n                }\n                blockView.set({\n                    offsetY: height,\n                });\n                delete blockView.originalHeight;\n            }\n        }\n\n        _.result(blockView.block.thread.changeEvent, 'notify');\n    }\n\n    addDragging() {\n        this.svgGroup.addClass('dragging');\n        Entry.playground.setBackpackPointEvent(true);\n    }\n\n    removeDragging() {\n        this.svgGroup.removeClass('dragging');\n        Entry.playground.setBackpackPointEvent(false);\n    }\n\n    addSelected() {\n        document?.activeElement?.blur();\n        $(this.pathGroup).insertAfter(this._nextGroup);\n        this.svgGroup.removeClass('activated');\n        this.svgGroup.addClass('selected');\n    }\n\n    removeSelected() {\n        $(this.pathGroup).insertBefore(this._nextGroup);\n        this.svgGroup.removeClass('selected');\n    }\n\n    addActivated() {\n        $(this.pathGroup).insertAfter(this._nextGroup);\n        this.svgGroup.removeClass('selected');\n        this.svgGroup.addClass('activated');\n    }\n\n    removeActivated() {\n        $(this.pathGroup).insertBefore(this._nextGroup);\n        this.svgGroup.removeClass('activated');\n    }\n\n    getSkeleton() {\n        return this._skeleton;\n    }\n\n    getContentPos() {\n        return this._skeleton.contentPos(this);\n    }\n\n    renderText() {\n        this.renderMode = Entry.BlockView.RENDER_MODE_TEXT;\n        this._startContentRender(Entry.BlockView.RENDER_MODE_TEXT);\n    }\n\n    renderBlock() {\n        this.renderMode = Entry.BlockView.RENDER_MODE_BLOCK;\n        this._startContentRender(Entry.BlockView.RENDER_MODE_BLOCK);\n    }\n\n    renderByMode(mode, isReDraw) {\n        if (this.isRenderMode(mode) && !isReDraw) {\n            return;\n        }\n\n        this.renderMode = mode;\n        this._startContentRender(mode);\n    }\n\n    _updateOpacity() {\n        if (this.visible === false) {\n            this.svgGroup.attr({ opacity: 0 });\n            this.svgCommentGroup && this.svgCommentGroup.attr({ opacity: 0 });\n        } else {\n            this.svgGroup.removeAttr('opacity');\n            this.svgCommentGroup && this.svgCommentGroup.removeAttr('opacity');\n            this._setPosition();\n        }\n    }\n\n    _setMovable() {\n        if (this.block.isMovable() !== null) {\n            this.movable = this.block.isMovable();\n        } else if (this._skeleton.movable !== undefined) {\n            this.movable = this._skeleton.movable;\n        } else {\n            this.movable = true;\n        }\n    }\n\n    _setReadOnly() {\n        if (this.block.isReadOnly() !== null) {\n            this.readOnly = this.block.isReadOnly();\n        } else if (this._skeleton.readOnly !== undefined) {\n            this.readOnly = this._skeleton.readOnly;\n        } else {\n            this.readOnly = false;\n        }\n    }\n\n    _setCopyable() {\n        if (this.block.isCopyable() !== null) {\n            this.copyable = this.block.isCopyable();\n        } else if (this._skeleton.copyable !== undefined) {\n            this.copyable = this._skeleton.copyable;\n        } else {\n            this.copyable = true;\n        }\n    }\n\n    bumpAway(distance = 15, delay) {\n        const that = this;\n        if (delay) {\n            const oldX = this.x;\n            const oldY = this.y;\n            window.setTimeout(() => {\n                //only when position not changed\n                if (oldX === that.x && oldY === that.y) {\n                    that.moveBy(distance, distance, false);\n                }\n            }, delay);\n        } else {\n            that.moveBy(distance, distance, false);\n        }\n    }\n\n    _toLocalCoordinate(view) {\n        this.disableMouseEvent = false;\n        this.moveTo(0, 0, false);\n        const { _nextGroup: parentSvgGroup, _nextCommentGroup: parentCommentGroup } = view;\n        parentSvgGroup && parentSvgGroup.appendChild && parentSvgGroup.appendChild(this.svgGroup);\n        parentCommentGroup &&\n            parentCommentGroup.appendChild &&\n            parentCommentGroup.appendChild(this.svgCommentGroup);\n    }\n\n    _toGlobalCoordinate(dragMode, doNotUpdatePos) {\n        this.disableMouseEvent = false;\n        const { x, y } = this.getAbsoluteCoordinate(dragMode);\n        this.moveTo(x, y, false, doNotUpdatePos);\n        this.getBoard().svgBlockGroup.appendChild(this.svgGroup);\n        this.svgCommentGroup && this.getBoard().svgCommentGroup.appendChild(this.svgCommentGroup);\n    }\n\n    bindPrev(prevBlock, isDestroy) {\n        if (prevBlock) {\n            this._toLocalCoordinate(prevBlock.view);\n            const nextBlock = prevBlock.getNextBlock();\n            if (nextBlock) {\n                if (nextBlock && nextBlock !== this.block) {\n                    const endBlock = this.block.getLastBlock();\n                    if (isDestroy) {\n                        nextBlock.view._toLocalCoordinate(prevBlock.view);\n                    } else if (endBlock.view.magnet.next) {\n                        nextBlock.view._toLocalCoordinate(endBlock.view);\n                    } else {\n                        nextBlock.view._toGlobalCoordinate();\n                        nextBlock.separate();\n                        nextBlock.view.bumpAway(null, 100);\n                    }\n                }\n            }\n        } else {\n            prevBlock = this.block.getPrevBlock();\n            if (prevBlock) {\n                const prevBlockView = prevBlock.view;\n                this._toLocalCoordinate(prevBlockView);\n                const nextBlock = this.block.getNextBlock();\n                if (nextBlock && nextBlock.view) {\n                    nextBlock.view._toLocalCoordinate(this);\n                }\n            }\n        }\n    }\n\n    getAbsoluteCoordinate(dragMode) {\n        const board = this.getBoard();\n        const { scale = 1 } = board || {};\n        dragMode = dragMode !== undefined ? dragMode : this.dragMode;\n        if (dragMode === Entry.DRAG_MODE_DRAG) {\n            return {\n                x: this.x,\n                y: this.y,\n                scaleX: this.x / scale,\n                scaleY: this.y / scale,\n            };\n        }\n\n        const pos = this.block.getThread().view.requestAbsoluteCoordinate(this);\n        pos.x += this.x;\n        pos.y += this.y;\n        pos.scaleX = pos.x / scale;\n        pos.scaleY = pos.y / scale;\n        return pos;\n    }\n\n    getBelowHeight() {\n        return this.block.getThread().view.requestPartHeight(this);\n    }\n\n    _updateDisplay() {\n        if (this.display) {\n            $(this.svgGroup).removeAttr('display');\n            this._setPosition();\n        } else {\n            this.svgGroup.attr({\n                display: 'none',\n            });\n        }\n    }\n\n    _updateColor() {\n        let fillColor = this._schema.color;\n        const { deletable, emphasized } = this.block;\n\n        if (deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN || emphasized) {\n            const emphasizedColor = this._schema.emphasizedColor;\n            if (!emphasizedColor) {\n                fillColor = Entry.Utils.getEmphasizeColor(fillColor);\n            } else {\n                fillColor = emphasizedColor;\n            }\n        }\n        this._fillColor = fillColor;\n        this._path.attr({ fill: fillColor });\n        this._updateContents();\n    }\n\n    _updateContents(isReDraw) {\n        const params = [undefined, undefined, this.renderMode, isReDraw];\n        this._contents.forEach((c) => c.renderStart(...params));\n        this.alignContent(false);\n    }\n\n    _destroyObservers() {\n        const observers = this._observers;\n        while (observers.length) {\n            observers.pop().destroy();\n        }\n    }\n\n    reDraw() {\n        if (!(this.visible && this.display)) {\n            return;\n        }\n\n        this._updateContents(true);\n\n        //해당 블럭이 가진 파라미터가 다른 블럭인 경우 재귀로 동작. indicator(undefined), string 은 제외\n        (this.block.data.params || []).forEach((param) => {\n            if (_get(param, 'data.view')) {\n                param.data.view.reDraw();\n            }\n        });\n        (this.block.statements || []).forEach(({ view }) => view.reDraw());\n        (this._extensions || []).forEach((ext) => _.result(ext, 'updatePos'));\n    }\n\n    getParam(index) {\n        return this._paramMap[index];\n    }\n\n    getDataUrl(notClone, notPng) {\n        return new Promise((resolve, reject) => {\n            const svgGroup = notClone ? this.svgGroup : this.svgGroup.cloneNode(true);\n            const svgCommentGroup = notClone\n                ? this.svgCommentGroup\n                : this.svgCommentGroup && this.svgCommentGroup.cloneNode(true);\n\n            if (!notClone) {\n                svgGroup.removeAttribute('opacity');\n                svgGroup.setAttribute('class', 'block selected');\n            }\n            const box = this._skeleton.box(this);\n            const scale = this.getBoard()?.scale || 1;\n            let fontWeight = this.isWindow7() ? 0.9 : 0.95;\n            if (this.type.indexOf('func_') > -1) {\n                fontWeight *= 0.99;\n            }\n            svgGroup.setAttribute(\n                'transform',\n                'scale(%SCALE) translate(0,0)'.replace('%SCALE', scale)\n            );\n            this.svgCommentGroup &&\n                svgCommentGroup.setAttribute(\n                    'transform',\n                    'scale(%SCALE) translate(0,0)'.replace('%SCALE', scale)\n                );\n\n            const defs = this.getBoard().svgDom.find('defs');\n            const images = svgGroup.getElementsByTagName('image');\n            const texts = svgGroup.getElementsByTagName('text');\n\n            const fontFamily = EntryStatic.getDefaultFontFamily();\n            const boldTypes = ['≥', '≤'];\n            const notResizeTypes = ['≥', '≤', '-', '>', '<', '=', '+', '-', 'x', '/'];\n\n            _.toArray(texts).forEach((text) => {\n                text.setAttribute('font-family', fontFamily);\n                const size = parseInt(text.getAttribute('font-size'), 10);\n                const content = $(text).text();\n                if (_.includes(boldTypes, content)) {\n                    text.setAttribute('font-weight', '500');\n                }\n                if (_.includes(notResizeTypes, content)) {\n                    text.setAttribute('font-size', `${size}px`);\n                }\n                text.setAttribute('alignment-baseline', 'auto');\n            });\n\n            if (images.length) {\n                Array.from(images).forEach((image) => {\n                    const href = image.getAttribute('href');\n                    image.setAttribute('href', `${location.protocol}//${location.host}${href}`);\n                });\n            }\n            this.processSvg(svgGroup, scale, defs, notPng)\n                .then((data) => {\n                    resolve(data);\n                })\n                .catch((err) => {\n                    reject(err);\n                });\n        });\n    }\n\n    async downloadAsImage(i) {\n        const image = await this.getDataUrl();\n        Entry.dispatchEvent('saveBlockImages', {\n            images: [image],\n        });\n    }\n\n    _rightClick(e, eventSource) {\n        const disposeEvent = Entry.disposeEvent;\n        if (disposeEvent) {\n            disposeEvent.notify(e);\n        }\n\n        const block = this.block;\n        const board = this.getBoard();\n        delete board.workingEvent;\n        //if long pressed block is function_general block\n        //edit function\n        if (this.isInBlockMenu && eventSource === 'longPress' && block.getFuncId()) {\n            return this._schema.events.dblclick[0](this);\n        }\n\n        const { clientX: x, clientY: y } = Entry.Utils.convertMouseEvent(e);\n\n        return Entry.ContextMenu.show(_getOptions(this), null, { x, y });\n\n        //helper functon get get context options\n        function _getOptions(blockView) {\n            const isBoardReadOnly = blockView._board.readOnly;\n            const { block, isInBlockMenu, copyable } = blockView;\n            const { options: EntryOptions = {} } = Entry;\n            const {\n                Blocks: {\n                    AI_analyze_option,\n                    Duplication_option,\n                    CONTEXT_COPY_option,\n                    cut_blocks,\n                    Delete_Blocks,\n                },\n                Menus: { save_as_image },\n            } = Lang;\n\n            const aiAnalyze = {\n                text: AI_analyze_option,\n                enable: copyable && !isBoardReadOnly,\n                callback() {\n                    // NOTICE : Entry.do는 필요할지 고려 > 뒤로가기 적용이 필요한지\n                    const blocksData = { ...block.copy() };\n\n                    Entry.dispatchEvent('analyzeBlock', {\n                        data: JSON.stringify(blocksData),\n                    });\n                },\n            };\n\n            const copyAndPaste = {\n                text: Duplication_option,\n                enable: copyable && !isBoardReadOnly,\n                callback() {\n                    Entry.do('cloneBlock', block.copy());\n                },\n            };\n\n            const copy = {\n                text: CONTEXT_COPY_option,\n                enable: copyable && !isBoardReadOnly,\n                callback() {\n                    block.copyToClipboard();\n                },\n            };\n\n            const cut = {\n                text: cut_blocks,\n                enable: copyable && block.isDeletable() && !isBoardReadOnly,\n                callback() {\n                    block.copyToClipboard();\n                    Entry.do('destroyBlockBelow', block);\n                    blockView.getBoard().setSelectedBlock(null);\n                },\n            };\n\n            const remove = {\n                text: Delete_Blocks,\n                enable: block.isDeletable() && !isBoardReadOnly,\n                callback() {\n                    Entry.do('destroyBlock', block);\n                },\n            };\n\n            const addStorage = !EntryOptions.backpackDisable && {\n                text: Lang.Blocks.add_my_storage,\n                enable: copyable && !isBoardReadOnly && !!window.user,\n                callback() {\n                    Entry.dispatchEvent('addStorage', {\n                        type: 'block',\n                        data: block,\n                    });\n                },\n            };\n\n            const download = {\n                text: save_as_image,\n                callback() {\n                    blockView.downloadAsImage();\n                },\n            };\n\n            const hasComment = !!block._comment;\n            const comment = !EntryOptions.commentDisable && {\n                text: hasComment ? Lang.Blocks.delete_comment : Lang.Blocks.add_comment,\n                enable: block.isCommentable(),\n                callback() {\n                    hasComment\n                        ? Entry.do('removeComment', block._comment)\n                        : Entry.do('createComment', { id: Entry.Utils.generateId() }, board, block);\n                },\n            };\n\n            let options = [];\n            if (_isDownloadable()) {\n                options.push(download);\n            }\n\n            if (!isInBlockMenu) {\n                options = [\n                    Entry.aiAssistantEnable && aiAnalyze,\n                    copyAndPaste,\n                    copy,\n                    cut,\n                    remove,\n                    addStorage,\n                    ...options,\n                    comment,\n                ].filter((x) => x);\n            }\n\n            return options;\n\n            function _isDownloadable() {\n                return (\n                    Entry.blockSaveImageEnable &&\n                    Entry.Utils.isChrome() &&\n                    Entry.type === 'workspace' &&\n                    !Entry.isMobile()\n                );\n            }\n        }\n    }\n\n    addStorage() {\n        if (this.block.view) {\n            Entry.dispatchEvent('addStorage', {\n                type: 'block',\n                data: this.block,\n            });\n        }\n    }\n\n    clone() {\n        return this.svgGroup.cloneNode(true);\n    }\n\n    setBackgroundPath() {\n        const board = this.getBoard();\n        if (board.dragBlock) {\n            return;\n        }\n\n        this.resetBackgroundPath();\n\n        const originPath = this._path;\n\n        const clonedPath = originPath.cloneNode(true);\n        clonedPath.setAttribute('class', 'blockBackgroundPath');\n        clonedPath.setAttribute('fill', this._fillColor);\n\n        this._backgroundPath = clonedPath;\n        this.pathGroup.insertBefore(clonedPath, originPath);\n\n        board.enablePattern();\n        originPath.attr({\n            fill: `url(#blockHoverPattern_${board.suffix})`,\n        });\n    }\n\n    resetBackgroundPath() {\n        const board = this.getBoard();\n        if (!this._backgroundPath || !board || !board.disablePattern) {\n            return;\n        }\n\n        board.disablePattern();\n        _.result($(this._backgroundPath), 'remove');\n        this._backgroundPath = null;\n        this._path.attr({ fill: this._fillColor });\n    }\n\n    _getTemplate(renderMode) {\n        let template;\n\n        if (renderMode === Entry.BlockView.RENDER_MODE_TEXT) {\n            const board = this.getBoard();\n            let syntax;\n            const workspace = board.workspace;\n            if (workspace && workspace.vimBoard) {\n                syntax = workspace.vimBoard.getBlockSyntax(this);\n            } else {\n                if (board.getBlockSyntax) {\n                    syntax = board.getBlockSyntax(this, renderMode);\n                }\n            }\n\n            if (syntax) {\n                if (typeof syntax === 'string') {\n                    template = syntax;\n                } else {\n                    template = syntax.template;\n                }\n            }\n        }\n\n        return template || this._schema.template || Lang.template[this.block.type];\n    }\n\n    _getSchemaParams(mode) {\n        let params = this._schema.params;\n        if (mode === Entry.BlockView.RENDER_MODE_TEXT) {\n            const workspace = this.getBoard().workspace;\n            if (workspace && workspace.vimBoard) {\n                const syntax = workspace.vimBoard.getBlockSyntax(this);\n                if (syntax && syntax.textParams) {\n                    params = syntax.textParams;\n                }\n            }\n        }\n        return params;\n    }\n\n    detach() {\n        this.svgGroup.remove();\n    }\n\n    attach(target) {\n        (target || this._board.svgBlockGroup).appendChild(this.svgGroup);\n    }\n\n    getMagnet(query) {\n        const selector = query.shift() || 'next';\n        let halfWidth = query.shift();\n        if (halfWidth === undefined) {\n            halfWidth = 20;\n        }\n        return {\n            getBoundingClientRect: function() {\n                const coord = this.getAbsoluteCoordinate();\n                const boardOffset = this._board.relativeOffset;\n                const magnet = this.magnet[selector];\n\n                return {\n                    top: coord.y + boardOffset.top + magnet.y - halfWidth,\n                    left: coord.x + boardOffset.left + magnet.x - halfWidth,\n                    width: 2 * halfWidth,\n                    height: 2 * halfWidth,\n                };\n            }.bind(this),\n        };\n    }\n\n    isRenderMode(mode) {\n        return this.renderMode === mode;\n    }\n\n    _setHoverBlockView(data) {\n        if (!data) {\n            return;\n        }\n\n        const { that, blockView } = data;\n\n        const target = _.result(that.getBoard(), 'workspace');\n        if (!target) {\n            return;\n        }\n        target.setHoverBlockView(blockView);\n    }\n\n    setHoverBlockView = this._setHoverBlockView;\n\n    getFields() {\n        if (!this._schema) {\n            return [];\n        }\n\n        const THREAD = Entry.Thread;\n        const FIELD_BLOCK = Entry.FieldBlock;\n        const FIELD_OUTPUT = Entry.FieldOutput;\n\n        return (this._statements || []).reduce(\n            (fields, statement) => {\n                statement = statement && statement._thread;\n                if (!(statement instanceof THREAD)) {\n                    return fields;\n                }\n\n                return fields.concat(statement.view.getFields());\n            },\n            (this._contents || []).reduce((fields, c) => {\n                if (!c) {\n                    return fields;\n                }\n\n                fields.push(c);\n\n                if (c instanceof FIELD_BLOCK || c instanceof FIELD_OUTPUT) {\n                    //some output block doesn't have value block\n                    const valueBlock = c.getValueBlock && c.getValueBlock();\n                    if (!valueBlock) {\n                        return fields;\n                    }\n                    fields = fields.concat(valueBlock.view.getFields());\n                }\n\n                return fields;\n            }, [])\n        );\n    }\n\n    processSvg(svgGroup, scale = 1, defs) {\n        return new Promise((resolve, reject) => {\n            let svgData =\n                '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 %W %H\">(svgGroup)(defs)</svg>';\n            const bBox = this.svgGroup.getBoundingClientRect();\n            const boxWidth = bBox.width;\n            const boxHeight = bBox.height;\n            const offset = 2 * scale;\n            svgData = svgData\n                .replace('(svgGroup)', new XMLSerializer().serializeToString(svgGroup))\n                .replace('%W', Math.ceil(boxWidth) + offset)\n                .replace('%H', Math.ceil(boxHeight) + offset)\n                .replace('(defs)', new XMLSerializer().serializeToString(defs[0]))\n                .replace(/>\\s+/g, '>')\n                .replace(/\\s+</g, '<');\n            svgData = svgData.replace(/NS\\d+:href/gi, 'href');\n            const data = Entry.isOffline\n                ? `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svgData)))}`\n                : svgData;\n            resolve({\n                width: boxWidth,\n                height: boxHeight,\n                data,\n            });\n        });\n    }\n\n    loadImage(src, width, height, notPng, multiplier = 1) {\n        return new Promise((resolve, reject) => {\n            if (Entry.BlockView.pngMap[src] !== undefined) {\n                return resolve(Entry.BlockView.pngMap[src]);\n            }\n\n            if (notPng) {\n                return resolve(`${location.origin}${src}`);\n            }\n\n            width *= multiplier;\n            height *= multiplier;\n            //float point cropped\n            width = Math.ceil(width);\n            height = Math.ceil(height);\n\n            const img = document.createElement('img');\n            img.crossOrigin = 'Anonymous';\n            const canvas = document.createElement('canvas');\n\n            canvas.width = width;\n            canvas.height = height;\n            const ctx = canvas.getContext('2d');\n\n            img.onload = function() {\n                try {\n                    ctx.drawImage(img, 0, 0, width, height);\n                    const data = canvas.toDataURL('image/png');\n                    if (/\\.png$/.test(src)) {\n                        Entry.BlockView.pngMap[src] = data;\n                    }\n                    return resolve(data);\n                } catch (e) {\n                    return reject('error occured');\n                }\n            };\n\n            img.onerror = function() {\n                return reject('error occured');\n            };\n            img.src = src;\n        });\n    }\n\n    isWindow7() {\n        const platform = window.platform;\n        if (platform && platform.name.toLowerCase() === 'windows' && platform.version[0] === '7') {\n            return true;\n        }\n        return false;\n    }\n};\n\nEntry.BlockView.PARAM_SPACE = 7;\nEntry.BlockView.DRAG_RADIUS = 5;\nEntry.BlockView.pngMap = {};\n\nEntry.BlockView.RENDER_MODE_BLOCK = 1;\nEntry.BlockView.RENDER_MODE_TEXT = 2;\n"
  },
  {
    "path": "src/playground/blocks/block_ai_learning.js",
    "content": "import _floor from 'lodash/floor';\n\nconst DropDownDynamicGenerator = {\n    labels: () => {\n        if (Entry?.aiLearning?.labels?.length) {\n            return Entry.aiLearning.labels.map((name, index) => [name, index]);\n        } else {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n    },\n    tableAttrFields: () => {\n        const table = Entry.aiLearning?.getTableData?.();\n        if (table) {\n            const { select = [], fields } = table || {};\n            const attr = select?.[0] || [];\n            return attr.map((fieldIndex, idx) => [fields[fieldIndex], idx]);\n        } else {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n    },\n    valueMap: () => {\n        const valueMap =\n            Object.values(\n                Entry.aiLearning.getTrainResult()?.valueMap ||\n                    Entry.aiLearning?.result?.valueMap ||\n                    {}\n            ) || [];\n\n        if (valueMap?.length) {\n            return valueMap.map((name) => [name, name]);\n        } else {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n    },\n};\n\nconst createParamBlock = ({\n    name,\n    length,\n    createFunc,\n    skeleton = 'basic_string_field',\n    params = [],\n    type,\n}) => {\n    const result = {};\n    new Array(length).fill(0).forEach((_, idx) => {\n        const index = idx + 1;\n        const blockName = `${name}_${index}`;\n        const EmptyArray = new Array(index * 2).fill(0);\n        const lastAttr = {\n            key: 1,\n            value: 1,\n        };\n        const paramsKeyMap = EmptyArray.reduce((acc, cur, idx, array) => {\n            if (idx % 2 !== 0) {\n                return acc;\n            }\n            const index = idx / 2 + 1;\n            acc[`ATTR${index}`] = idx + 1;\n            lastAttr.key = index;\n            lastAttr.value = idx + 1;\n            return acc;\n        }, {});\n        if (params.length) {\n            params.forEach((p, i) => {\n                paramsKeyMap[`ATTR${lastAttr.key + i + 1}`] = lastAttr.value + 1;\n            });\n        }\n        result[blockName] = {\n            color: EntryStatic.colorSet.block.default.AI_LEARNING,\n            outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n            skeleton,\n            statements: [],\n            params: [\n                ...EmptyArray.map((_, i) => {\n                    if (i % 2 !== 0) {\n                        return {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        };\n                    }\n                    return {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return (\n                                    fields[select?.[0]?.[i / 2]] || Lang.AiLearning.model_attr_str\n                                );\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    };\n                }),\n                ...params,\n            ],\n            events: {},\n            def: {\n                type: blockName,\n            },\n            pyHelpDef: {\n                params: [],\n                type: blockName,\n            },\n            paramsKeyMap,\n            class: 'ai_learning',\n            isNotFor: Array.isArray(type) \n                ? type.map(element => `${element}_attr_${index}`) \n                : [`${type}_attr_${index}`],\n            func: createFunc(paramsKeyMap),\n            syntax: {\n                js: [],\n                py: [],\n            },\n        };\n    });\n    return result;\n};\n\nmodule.exports = {\n    DropDownDynamicGenerator,\n    createParamBlock,\n    getBlocks() {\n        return {\n            ...predictBlocks,\n            ...booleanPredictBlocks,\n            learning_title_image: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_image_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_image',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_image'],\n                events: {},\n                wikiClass: 'ai_image',\n            },\n            learning_title_speech: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_speech_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_speech',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_speech'],\n                events: {},\n                wikiClass: 'ai_speech',\n            },\n            learning_title_text: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_text_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_text',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_text'],\n                events: {},\n                wikiClass: 'ai_text',\n            },\n            insert_data_for_test: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'insert_data_for_test',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'insert_data_for_test',\n                },\n                paramsKeyMap: {},\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_classification'],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        script.isStart = true;\n                        Entry.aiLearning.openInputPopup();\n                        return script;\n                    }\n                    if (!Entry.aiLearning.isLoading) {\n                        delete script.isStart;\n                        return script.callReturn();\n                    }\n                    return script;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            video_capture_for_image_test: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.video_start, 'start'],\n                            [Lang.Blocks.video_end, 'stop'],\n                        ],\n                        value: 'on',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['start', null],\n                    type: 'video_capture_for_image_test',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'video_capture_for_image_test',\n                },\n                paramsKeyMap: {\n                    MODE: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_image'],\n                async func(sprite, script) {\n                    const mode = script.getField('MODE');\n                    if (mode === 'start') {\n                        Entry.aiLearning.startPredict();\n                    } else {\n                        Entry.aiLearning.stopPredict();\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_image',\n            },\n            insert_text_block_for_test: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.entry],\n                        },\n                        null,\n                    ],\n                    type: 'insert_text_block_for_test',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'insert_text_block_for_test',\n                },\n                paramsKeyMap: {\n                    TEXT: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_text'],\n                async func(sprite, script) {\n                    const text = script.getStringValue('TEXT', script);\n                    await Entry.aiLearning.predict(text);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_text',\n            },\n            test_result: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'test_result',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'test_result',\n                },\n                paramsKeyMap: {},\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_classification'],\n                func(sprite, script) {\n                    return Entry.aiLearning.getPredictResult().className;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            accuracy_of_result: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.labels,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0],\n                    type: 'accuracy_of_result',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'accuracy_of_result',\n                },\n                paramsKeyMap: {\n                    GROUP: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_classification'],\n                func(sprite, script) {\n                    const group = script.getNumberValue('GROUP', script);\n                    return Entry.aiLearning.getPredictResult(group).probability;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            is_group: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.labels,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0],\n                    type: 'is_group',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_classification'],\n                paramsKeyMap: {\n                    GROUP: 0,\n                },\n                func(sprite, script) {\n                    const group = script.getNumberValue('GROUP', script);\n                    const { labels } = Entry.aiLearning;\n                    const result = Entry.aiLearning.getPredictResult().className;\n                    return result === labels[group];\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            retrain_model: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'retrain_model',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'retrain_model',\n                },\n                paramsKeyMap: {\n                    TEXT: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_train'],\n                async func(sprite, script) {\n                    Entry.aiLearning.train();\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            model_is_trained: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    type: 'model_is_trained',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_train'],\n                func(sprite, script) {\n                    return Entry.aiLearning.isTrained();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            set_train_visible: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.show, 'show'],\n                            [Lang.AiLearning.hide, 'hide'],\n                        ],\n                        value: 'show',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['show', null],\n                    type: 'set_train_visible',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_train_visible',\n                },\n                paramsKeyMap: {\n                    VISIBLE: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_train'],\n                async func(sprite, script) {\n                    const visible = script.getField('VISIBLE');\n                    Entry.aiLearning.setVisible(visible === 'show');\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            set_train_chart: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.open, 'open'],\n                            [Lang.AiLearning.close, 'close'],\n                        ],\n                        value: 'open',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['open', null],\n                    type: 'set_train_chart',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_train_chart',\n                },\n                paramsKeyMap: {\n                    VISIBLE: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_train_chart'],\n                async func(sprite, script) {\n                    const visible = script.getField('VISIBLE');\n                    Entry.aiLearning.setChartVisible(visible === 'open');\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_result_info: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.accuracy, 'accuracy'],\n                            [Lang.AiLearning.f1, 'f1'],\n                            [Lang.AiLearning.precision, 'precision'],\n                            [Lang.AiLearning.recall, 'recall'],\n                        ],\n                        value: 'accuracy',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_result_info',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_result_info',\n                },\n                paramsKeyMap: {\n                    TYPE: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_svm', 'ai_learning_logistic_regression', 'ai_learning_decisiontree'],\n                async func(sprite, script) {\n                    const type = script.getField('TYPE', script);\n                    const result = Entry.aiLearning?.getTrainResult();\n                    return result?.[type];\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n        };\n    },\n};\n\nconst predictBlocks = createParamBlock({\n    type: ['svm', 'logistic_regression', 'decisiontree'],\n    name: 'get_predict',\n    length: 6,\n    createFunc: (paramsKeyMap) => async (sprite, script) => {\n        const params = Object.keys(paramsKeyMap).map((key) => script.getNumberValue(key, script));\n        await Entry.aiLearning.predict(params);\n        const result = Entry.aiLearning.getPredictResult();\n        return result.sort((a, b) => b.probability - a.probability)[0].className;\n    },\n});\nconst booleanPredictBlocks = createParamBlock({\n    type: ['svm', 'logistic_regression', 'decisiontree'],\n    name: 'is_result',\n    skeleton: 'basic_boolean_field',\n    length: 6,\n    createFunc: (paramsKeyMap) => async (sprite, script) => {\n        const keys = Object.keys(paramsKeyMap);\n        const predictKey = keys.pop();\n        const params = keys.map((key) => script.getNumberValue(key, script));\n        const predict = script.getStringField(predictKey, script);\n        await Entry.aiLearning.predict(params);\n        const predictResult = Entry.aiLearning.getPredictResult();\n        const result = predictResult.sort((a, b) => b.probability - a.probability)[0];\n        return result && !!result.probability && result.className === predict;\n    },\n    params: [\n        {\n            type: 'DropdownDynamic',\n            value: null,\n            menuName: DropDownDynamicGenerator.valueMap,\n            needDeepCopy: true,\n            fontSize: 11,\n            bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n            arrowColor: EntryStatic.colorSet.common.WHITE,\n            defaultValue: (value, options) => {\n                if (options[0] && options[0][1]) {\n                    return options[0][1];\n                }\n                return value || 0;\n            },\n        },\n    ],\n});"
  },
  {
    "path": "src/playground/blocks/block_ai_learning_cluster.js",
    "content": "import { DropDownDynamicGenerator } from './block_ai_learning';\n\nmodule.exports = {\n    getBlocks() {\n        return {\n            learning_title_cluster: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_cluster_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_cluster',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_cluster'],\n                events: {},\n            },\n            set_cluster_option_k: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0, null],\n                    type: 'set_cluster_option_k',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_cluster_option_k',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_cluster'],\n                async func(sprite, script) {\n                    const value = script.getStringValue('VALUE', script);\n                    Entry.aiLearning.setTrainOption('k', parseInt(value, 10));\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            set_cluster_option_centroids: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.cluster_option_centroids_kmpp, 'kmpp'],\n                            [Lang.AiLearning.cluster_option_centroids_random, 'random'],\n                        ],\n                        value: 'kmpp',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'set_cluster_option_centroids',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_cluster_option_centroids',\n                },\n                paramsKeyMap: {\n                    CENTRIOD_TYPE: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_cluster'],\n                async func(sprite, script) {\n                    const value = script.getField('CENTRIOD_TYPE');\n                    Entry.aiLearning.setTrainOption('initialCentroids', value);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            get_cluster_centriod_count: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'get_cluster_centriod_count',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_cluster_centriod_count',\n                },\n                paramsKeyMap: {},\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_cluster'],\n                func(sprite, script) {\n                    const { k = 0 } = Entry.aiLearning.getTrainOption() || {};\n                    return k;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            get_cluster_centriod_value: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.tableAttrFields,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [1, 0],\n                    type: 'get_cluster_centriod_value',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_cluster_centriod_value',\n                },\n                paramsKeyMap: {\n                    K: 0,\n                    ATTR: 1,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_cluster'],\n                func(sprite, script) {\n                    const k = script.getNumberValue('K');\n                    const attr = script.getField('ATTR');\n                    const { centroids } = Entry.aiLearning.getTrainResult();\n                    return centroids?.[k - 1]?.[attr] || NaN;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            get_cluster_centriod_index_1: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                def: {\n                    type: 'get_cluster_centriod_index_1',\n                },\n                events: {},\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_cluster_centriod_index_1',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                },\n                class: 'ai_learning',\n                isNotFor: ['cluster_attr_1'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    await Entry.aiLearning.predict([x]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            get_cluster_centriod_index_2: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                def: {\n                    type: 'get_cluster_centriod_index_2',\n                },\n                events: {},\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_cluster_centriod_index_2',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                },\n                class: 'ai_learning',\n                isNotFor: ['cluster_attr_2'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    await Entry.aiLearning.predict([x, y]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            get_cluster_centriod_index_3: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                def: {\n                    type: 'get_cluster_centriod_index_3',\n                },\n                events: {},\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_cluster_centriod_index_3',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                },\n                class: 'ai_learning',\n                isNotFor: ['cluster_attr_3'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    const z = script.getNumberValue('ATTR3', script);\n                    await Entry.aiLearning.predict([x, y, z]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            get_cluster_centriod_index_4: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                def: {\n                    type: 'get_cluster_centriod_index_4',\n                },\n                events: {},\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_cluster_centriod_index_4',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                },\n                class: 'ai_learning',\n                isNotFor: ['cluster_attr_4'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    await Entry.aiLearning.predict([a, b, c, d]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            get_cluster_centriod_index_5: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                def: {\n                    type: 'get_cluster_centriod_index_5',\n                },\n                events: {},\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_cluster_centriod_index_5',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                },\n                class: 'ai_learning',\n                isNotFor: ['cluster_attr_5'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n            get_cluster_centriod_index_6: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[5]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                def: {\n                    type: 'get_cluster_centriod_index_6',\n                },\n                events: {},\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_cluster_centriod_index_6',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                    ATTR6: 11,\n                },\n                class: 'ai_learning',\n                isNotFor: ['cluster_attr_6'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    const f = script.getNumberValue('ATTR6', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e, f]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_cluster',\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_learning_decisiontree.js",
    "content": "import { createParamBlock, DropDownDynamicGenerator } from './block_ai_learning';\n\nmodule.exports = {\n    getBlocks() {\n        return {\n            learning_title_decisiontree: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_decisiontree_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_decisiontree',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_decisiontree'],\n                events: {},\n            },\n            set_decisiontree_option: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.train_param_minNumSamples, 'minNumSamples'],\n                            [Lang.AiLearning.train_param_maxDepth, 'maxDepth'],\n                        ],\n                        value: 'minNumSamples',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'set_decisiontree_option',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_decisiontree_option',\n                },\n                paramsKeyMap: {\n                    OPTION: 0,\n                    VALUE: 1,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_decisiontree'],\n                func(sprite, script) {\n                    const option = script.getField('OPTION', script);\n                    const value = script.getNumberValue('VALUE', script);\n                    Entry.aiLearning.setTrainOption(option, parseFloat(value));\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            set_decisiontree_tree: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.open, 'open'],\n                            [Lang.AiLearning.close, 'close'],\n                        ],\n                        value: 'open',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['open', null],\n                    type: 'set_decisiontree_tree',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_decisiontree_tree',\n                },\n                paramsKeyMap: {\n                    VISIBLE: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_decisiontree'],\n                async func(sprite, script) {\n                    const visible = script.getField('VISIBLE');\n                    Entry.aiLearning.setChartVisible(visible === 'open');\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_learning_knn.js",
    "content": "import { DropDownDynamicGenerator } from './block_ai_learning';\n\nmodule.exports = {\n    getBlocks() {\n        return {\n            learning_title_number: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_number_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_number',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_number'],\n                events: {},\n            },\n            set_number_learning_option_k: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [10, null],\n                    type: 'set_number_learning_option_k',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_number_learning_option_k',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_number'],\n                async func(sprite, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    Entry.aiLearning.setTrainOption('neighbors', parseInt(value));\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_1: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_1',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_1',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_1'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    await Entry.aiLearning.predict([x]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_2: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_2',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_2',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_2'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    await Entry.aiLearning.predict([x, y]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_3: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_3',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_3',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_3'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    const z = script.getNumberValue('ATTR3', script);\n                    await Entry.aiLearning.predict([x, y, z]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_4: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_4',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_4',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_4'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    await Entry.aiLearning.predict([a, b, c, d]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_5: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_5',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_5',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_5'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_6: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[5]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_6',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_6',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                    ATTR6: 11,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_6'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    const f = script.getNumberValue('ATTR6', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e, f]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_param_1: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            // [Lang.AiLearning.probability, 'probability'],\n                            [Lang.AiLearning.neighbor_count, 'count'],\n                        ],\n                        value: 'count',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_param_1',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_param_1',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    CLASS: 2,\n                    OPTION: 3,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_1'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const clazz = script.getField('CLASS', script);\n                    const option = script.getField('OPTION', script);\n                    await Entry.aiLearning.predict([x]);\n                    const result = Entry.aiLearning.getPredictResult();\n                    const classData = result.find(({ className }) => className === clazz) || {};\n                    return classData[option] || 0;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_param_2: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            // [Lang.AiLearning.probability, 'probability'],\n                            [Lang.AiLearning.neighbor_count, 'count'],\n                        ],\n                        value: 'count',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_param_2',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_param_2',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    CLASS: 4,\n                    OPTION: 5,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_2'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    const clazz = script.getField('CLASS', script);\n                    const option = script.getField('OPTION', script);\n                    await Entry.aiLearning.predict([x, y]);\n                    const result = Entry.aiLearning.getPredictResult();\n                    const classData = result.find(({ className }) => className === clazz) || {};\n                    return classData[option] || 0;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_param_3: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            // [Lang.AiLearning.probability, 'probability'],\n                            [Lang.AiLearning.neighbor_count, 'count'],\n                        ],\n                        value: 'count',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_param_3',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_param_3',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    CLASS: 6,\n                    OPTION: 7,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_3'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    const z = script.getNumberValue('ATTR3', script);\n                    const clazz = script.getField('CLASS', script);\n                    const option = script.getField('OPTION', script);\n                    await Entry.aiLearning.predict([x, y, z]);\n                    const result = Entry.aiLearning.getPredictResult();\n                    const classData = result.find(({ className }) => className === clazz) || {};\n                    return classData[option] || 0;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_param_4: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            // [Lang.AiLearning.probability, 'probability'],\n                            [Lang.AiLearning.neighbor_count, 'count'],\n                        ],\n                        value: 'count',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_param_4',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_param_4',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    CLASS: 8,\n                    OPTION: 9,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_4'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const clazz = script.getField('CLASS', script);\n                    const option = script.getField('OPTION', script);\n                    await Entry.aiLearning.predict([a, b, c, d]);\n                    const result = Entry.aiLearning.getPredictResult();\n                    const classData = result.find(({ className }) => className === clazz) || {};\n                    return classData[option] || 0;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_param_5: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            // [Lang.AiLearning.probability, 'probability'],\n                            [Lang.AiLearning.neighbor_count, 'count'],\n                        ],\n                        value: 'count',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_param_5',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_param_5',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                    CLASS: 10,\n                    OPTION: 11,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_5'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    const clazz = script.getField('CLASS', script);\n                    const option = script.getField('OPTION', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e]);\n                    const result = Entry.aiLearning.getPredictResult();\n                    const classData = result.find(({ className }) => className === clazz) || {};\n                    return classData[option] || 0;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_number_learning_predict_param_6: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[5]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            // [Lang.AiLearning.probability, 'probability'],\n                            [Lang.AiLearning.neighbor_count, 'count'],\n                        ],\n                        value: 'count',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_number_learning_predict_param_6',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_number_learning_predict_param_6',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                    ATTR6: 11,\n                    CLASS: 12,\n                    OPTION: 13,\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_6'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    const f = script.getNumberValue('ATTR6', script);\n                    const clazz = script.getField('CLASS', script);\n                    const option = script.getField('OPTION', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e, f]);\n                    const result = Entry.aiLearning.getPredictResult();\n                    const classData = result.find(({ className }) => className === clazz) || {};\n                    return classData[option] || 0;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            is_number_learning_group_1: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0],\n                    type: 'is_number_learning_group_1',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'is_number_learning_group_1',\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_1'],\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    CLASS: 2,\n                },\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const clazz = script.getField('CLASS', script);\n                    await Entry.aiLearning.predict([x]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className === clazz;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            is_number_learning_group_2: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0],\n                    type: 'is_number_learning_group_2',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'is_number_learning_group_2',\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_2'],\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    CLASS: 4,\n                },\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    const clazz = script.getField('CLASS', script);\n                    await Entry.aiLearning.predict([x, y]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className === clazz;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            is_number_learning_group_3: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0],\n                    type: 'is_number_learning_group_3',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'is_number_learning_group_3',\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_3'],\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    CLASS: 6,\n                },\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    const z = script.getNumberValue('ATTR3', script);\n                    const clazz = script.getField('CLASS', script);\n                    await Entry.aiLearning.predict([x, y, z]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className === clazz;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            is_number_learning_group_4: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0],\n                    type: 'is_number_learning_group_4',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'is_number_learning_group_4',\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_4'],\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    CLASS: 8,\n                },\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const clazz = script.getField('CLASS', script);\n                    await Entry.aiLearning.predict([a, b, c, d]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className === clazz;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            is_number_learning_group_5: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0],\n                    type: 'is_number_learning_group_5',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'is_number_learning_group_5',\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_5'],\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                    CLASS: 10,\n                },\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    const clazz = script.getField('CLASS', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className === clazz;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            is_number_learning_group_6: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[5]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: DropDownDynamicGenerator.valueMap,\n                        needDeepCopy: true,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        defaultValue: (value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return value || 0;\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [0],\n                    type: 'is_number_learning_group_6',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'is_number_learning_group_6',\n                },\n                class: 'ai_learning',\n                isNotFor: ['number_learning_attr_6'],\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                    ATTR6: 11,\n                    CLASS: 12,\n                },\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    const f = script.getNumberValue('ATTR6', script);\n                    const clazz = script.getField('CLASS', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e, f]);\n                    const [{ className }] = Entry.aiLearning.getPredictResult();\n                    return className === clazz;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_learning_logistic_regression.js",
    "content": "import { createParamBlock, DropDownDynamicGenerator } from './block_ai_learning';\n\nmodule.exports = {\n    getBlocks() {\n        const probabilityBlocks = createParamBlock({\n            type: 'logistic_regression',\n            name: 'get_logistic_regression_probability',\n            length: 6,\n            createFunc: (paramsKeyMap) => async (sprite, script) => {\n                const keys = Object.keys(paramsKeyMap);\n                const predictKey = keys.pop();\n                const params = keys.map((key) => script.getNumberValue(key, script));\n                const predict = script.getStringField(predictKey, script);\n                await Entry.aiLearning.predict(params);\n                const predictResult = Entry.aiLearning.getPredictResult();\n                const result = predictResult.find((x) => x.className === predict);\n                return result?.probability || 0;\n            },\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: DropDownDynamicGenerator.valueMap,\n                    needDeepCopy: true,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    defaultValue: (value, options) => {\n                        if (options[0] && options[0][1]) {\n                            return options[0][1];\n                        }\n                        return value || 0;\n                    },\n                },\n            ],\n        });\n        return {\n            ...probabilityBlocks,\n            learning_title_logistic_regression: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_logistic_regression_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_logistic_regression',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_logistic_regression'],\n                events: {},\n            },\n            set_logistic_regression_option: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.train_param_learningRate, 'learningRate'],\n                            [Lang.AiLearning.train_param_epochs, 'epochs'],\n                            [Lang.AiLearning.train_param_validationRate, 'validationRate'],\n                        ],\n                        value: 'learningRate',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'set_logistic_regression_option',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_logistic_regression_option',\n                },\n                paramsKeyMap: {\n                    OPTION: 0,\n                    VALUE: 1,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_logistic_regression'],\n                func(sprite, script) {\n                    const option = script.getField('OPTION', script);\n                    const value = script.getNumberValue('VALUE', script);\n                    Entry.aiLearning.setTrainOption(option, parseFloat(value));\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            set_logistic_regression_optimizer: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.train_param_optimizer_adam, 'adam'],\n                            [Lang.AiLearning.train_param_optimizer_sgd, 'sgd'],\n                        ],\n                        value: 'adam',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'set_logistic_regression_optimizer',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_logistic_regression_optimizer',\n                },\n                paramsKeyMap: {\n                    OPTIMIZER: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_logistic_regression'],\n                func(sprite, script) {\n                    const optimizer = script.getField('OPTIMIZER', script);\n                    Entry.aiLearning.setTrainOption('optimizer', optimizer);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_learning_regression.js",
    "content": "module.exports = {\n    getBlocks() {\n        return {\n            learning_title_regression: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_regression_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_regression',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_regression'],\n                events: {},\n            },\n            set_regression_option: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.train_param_learningRate, 'learningRate'],\n                            [Lang.AiLearning.train_param_epochs, 'epochs'],\n                            [Lang.AiLearning.train_param_validationRate, 'validationRate'],\n                        ],\n                        value: 'learningRate',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'set_regression_option',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_regression_option',\n                },\n                paramsKeyMap: {\n                    OPTION: 0,\n                    VALUE: 1,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_regression'],\n                func(sprite, script) {\n                    const option = script.getField('OPTION', script);\n                    const value = script.getNumberValue('VALUE', script);\n                    Entry.aiLearning.setTrainOption(option, parseFloat(value));\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_regression',\n            },\n            get_regression_predict_1: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_regression_predict_1',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_regression_predict_1',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                },\n                class: 'ai_learning',\n                isNotFor: ['regression_attr_1'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    await Entry.aiLearning.predict(x);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_regression',\n            },\n            get_regression_predict_2: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_regression_predict_2',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_regression_predict_2',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                },\n                class: 'ai_learning',\n                isNotFor: ['regression_attr_2'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    await Entry.aiLearning.predict([x, y]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_regression',\n            },\n            get_regression_predict_3: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_regression_predict_3',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_regression_predict_3',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                },\n                class: 'ai_learning',\n                isNotFor: ['regression_attr_3'],\n                async func(sprite, script) {\n                    const x = script.getNumberValue('ATTR1', script);\n                    const y = script.getNumberValue('ATTR2', script);\n                    const z = script.getNumberValue('ATTR3', script);\n                    await Entry.aiLearning.predict([x, y, z]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_regression',\n            },\n            get_regression_predict_4: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_regression_predict_4',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_regression_predict_4',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                },\n                class: 'ai_learning',\n                isNotFor: ['regression_attr_4'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    await Entry.aiLearning.predict([a, b, c, d]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_regression',\n            },\n            get_regression_predict_5: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_regression_predict_5',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_regression_predict_5',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                },\n                class: 'ai_learning',\n                isNotFor: ['regression_attr_5'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_regression',\n            },\n            get_regression_predict_6: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[0]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[1]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[2]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[3]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[4]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'TextDynamic',\n                        setValue: () => {\n                            const table = Entry.aiLearning?.getTableData?.();\n                            if (table) {\n                                const {\n                                    select = [],\n                                    fields = [],\n                                } = Entry.aiLearning?.getTableData?.();\n                                return fields[select?.[0]?.[5]] || Lang.AiLearning.model_attr_str;\n                            }\n                            return Lang.AiLearning.model_attr_str;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'get_regression_predict_6',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_regression_predict_6',\n                },\n                paramsKeyMap: {\n                    ATTR1: 1,\n                    ATTR2: 3,\n                    ATTR3: 5,\n                    ATTR4: 7,\n                    ATTR5: 9,\n                    ATTR6: 11,\n                },\n                class: 'ai_learning',\n                isNotFor: ['regression_attr_6'],\n                async func(sprite, script) {\n                    const a = script.getNumberValue('ATTR1', script);\n                    const b = script.getNumberValue('ATTR2', script);\n                    const c = script.getNumberValue('ATTR3', script);\n                    const d = script.getNumberValue('ATTR4', script);\n                    const e = script.getNumberValue('ATTR5', script);\n                    const f = script.getNumberValue('ATTR6', script);\n                    await Entry.aiLearning.predict([a, b, c, d, e, f]);\n                    return Entry.aiLearning.getPredictResult();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_regression',\n            },\n            get_regression_accuracy: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    type: 'get_regression_accuracy',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'get_regression_accuracy',\n                },\n                paramsKeyMap: {},\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_regression'],\n                async func(sprite, script) {\n                    return Entry.aiLearning?.getTrainResult()?.rsquared;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'ai_regression',\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_learning_svm.js",
    "content": "import { createParamBlock, DropDownDynamicGenerator } from './block_ai_learning';\nimport { OPTION_DEFAULT_VALUE, KERNEL_STRING_TYPE } from '.././../class/learning/Svm';\n\n\nmodule.exports = {\n    getBlocks() {\n        const params = {\n            getKernelOption() {\n                const param = {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName() {\n                        const value = this.getTargetValue('kernel');\n                        if (value === KERNEL_STRING_TYPE.POLYNOMIAL) {\n                            return [[Lang.AiLearning.train_param_degree, 'degree']]\n                        } else if (value === KERNEL_STRING_TYPE.RBF) {\n                            return [[Lang.AiLearning.train_param_gamma, 'gamma']]\n                        } else {\n                            return;\n                        }\n                    },\n\n                    needDeepCopy: true,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    defaultValue: (value, options) => {\n                        if (options.length) {\n                            return options[0][1];\n                        }\n                        return null;\n                    }\n                }\n                return param;\n            }\n        }\n        return {\n            learning_title_svm: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.learning_title_svm_str,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'learning_title_svm',\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_svm'],\n                events: {},\n            },\n            set_svm_option: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.train_param_C, 'C'],\n                        ],\n                        value: 'C',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: OPTION_DEFAULT_VALUE.C\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    }\n                ],\n                def: {\n                    type: 'set_svm_option',\n                },\n                paramsKeyMap: {\n                    OPTION: 0,\n                    VALUE: 1,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_svm'],\n                func(sprite, script) {\n                    const option = script.getStringField('OPTION', script);\n                    const value = script.getNumberValue('VALUE', script);\n                    Entry.aiLearning.setTrainOption(option, parseFloat(value));\n                    return script.callReturn();\n                },\n                events: {},\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_svm_option',\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            set_kernel_linear: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'set_kernel_linear',\n                },\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_kernel_linear',\n                },\n                paramsKeyMap: {\n                    TEXT: 0,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_svm'],\n                async func(sprite, script) {\n                    const defaultValue = { degree: 3, gamma: 1 };\n                    Entry.aiLearning.setTrainOption('kernel', 'linear');\n                    Entry.aiLearning.setTrainOption('degree', defaultValue.degree);\n                    Entry.aiLearning.setTrainOption('gamma', defaultValue.gamma);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            set_kernel_option: {\n                color: EntryStatic.colorSet.block.default.AI_LEARNING,\n                outerLine: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.AiLearning.train_param_kernel_polynomial, KERNEL_STRING_TYPE.POLYNOMIAL],\n                            [Lang.AiLearning.train_param_kernel_rbf, KERNEL_STRING_TYPE.RBF],\n                        ],\n                        value: 'polynomial',\n                        bgColor: EntryStatic.colorSet.block.darken.AI_LEARNING,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                        dropdownSync: 'kernel',\n                    },\n                    params.getKernelOption(),\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: OPTION_DEFAULT_VALUE.degree\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/ai_utilize_icon.svg',\n                        size: 11,\n                    }\n                ],\n                def: {\n                    type: 'set_kernel_option',\n                },\n                paramsKeyMap: {\n                    KERNEL: 0,\n                    OPTION: 1,\n                    VALUE: 2,\n                },\n                class: 'ai_learning',\n                isNotFor: ['ai_learning_svm'],\n                func(sprite, script) {\n                    // 초기화\n                    Entry.aiLearning.setTrainOption('gamma', OPTION_DEFAULT_VALUE.gamma);\n                    Entry.aiLearning.setTrainOption('degree', OPTION_DEFAULT_VALUE.degree);\n\n                    const kernel = script.getStringField('KERNEL', script);\n                    const option = script.getStringField('OPTION', script);\n                    const value = script.getNumberValue('VALUE', script);\n                    Entry.aiLearning.setTrainOption('kernel', kernel);\n                    Entry.aiLearning.setTrainOption(option, parseFloat(value));\n                    return script.callReturn();\n                },\n                events: {},\n                pyHelpDef: {\n                    params: [],\n                    type: 'set_kernel_option',\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            }\n        };\n    }\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_audio.js",
    "content": "import AudioUtils from '../../util/audioUtils';\nimport _clamp from 'lodash/clamp';\n\nEntry.AI_UTILIZE_BLOCK.audio = {\n    name: 'audio',\n    imageName: 'audio.svg',\n    category: 'audio',\n    sponsorText: 'Powered by {image}',\n    sponsorImage: 'naverClova.png',\n    sponsorOnImage: 'naverClovaOn.png',\n    title: {\n        ko: '음성 인식',\n        en: 'Speech recognition',\n        jp: 'オーディオ検出',\n    },\n    titleKey: 'template.voice_title_text',\n    description: Lang.Msgs.ai_utilize_audio_description,\n    descriptionKey: 'Msgs.ai_utilize_audio_description',\n    isInitialized: false,\n    async init() {\n        await AudioUtils.initialize();\n        Entry.AI_UTILIZE_BLOCK.audio.isInitialized = true;\n    },\n};\n\nEntry.AI_UTILIZE_BLOCK.audio.getBlocks = function() {\n    return {\n        audio_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.audio_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'audio_title',\n            },\n            class: 'audio',\n            isNotFor: ['audio'],\n            events: {},\n        },\n        check_microphone: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'check_microphone',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'audio',\n            isNotFor: ['audio'],\n            async func(sprite, script) {\n                try {\n                    if (!AudioUtils.isInitialized) {\n                        await AudioUtils.initialize();\n                    }\n                    return AudioUtils.audioInputList.length > 0;\n                } catch (err) {\n                    return false;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_stt',\n        },\n        get_microphone_volume: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'get_microphone_volume',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'audio',\n            isNotFor: ['audio'],\n            async func(sprite, script) {\n                if (!AudioUtils.isInitialized) {\n                    await AudioUtils.initialize();\n                }\n                return AudioUtils.currentVolume;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_stt',\n        },\n        speech_to_text_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.voice_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'speech_to_text_title',\n            },\n            class: 'stt',\n            isNotFor: ['audio'],\n            events: {},\n        },\n        speech_to_text_convert: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.korean_s, 'Kor'],\n                        [Lang.Blocks.english_s, 'Eng'],\n                        [Lang.Blocks.japan_s, 'Jpn'],\n                    ],\n                    value: 'Kor',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/ai_utilize_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {\n                viewAdd: [\n                    function() {\n                        if (Entry.container.sttValue) {\n                            Entry.container.sttValue.setVisible(true);\n                        }\n                    },\n                ],\n                viewDestroy: [\n                    function(block, notIncludeSelf) {\n                        if (Entry.container.sttValue) {\n                            Entry.container.sttValue.checkVisible(block, notIncludeSelf);\n                        }\n                    },\n                ],\n            },\n            def: {\n                params: [null],\n                type: 'speech_to_text_convert',\n            },\n            paramsKeyMap: {\n                LANG: 0,\n            },\n            class: 'stt',\n            isNotFor: ['audio'],\n            async func(sprite, script) {\n                if (!AudioUtils.isInitialized) {\n                    await AudioUtils.initialize();\n                }\n                if (AudioUtils.isRecording) {\n                    return;\n                }\n                try {\n                    const language = script.getField('LANG', script);\n                    if (language === 'Kor') {\n                        Entry.container.sttValue.setName(\n                            `${Lang.template.voice_title_text}:${Lang.Blocks.korean_s}`\n                        );\n                    } else if (language === 'Eng') {\n                        Entry.container.sttValue.setName(\n                            `${Lang.template.voice_title_text}:${Lang.Blocks.english_s}`\n                        );\n                    } else if (language === 'Jpn') {\n                        Entry.container.sttValue.setName(\n                            `${Lang.template.voice_title_text}:${Lang.Blocks.japan_s}`\n                        );\n                    }\n                    AudioUtils.isRecording = true;\n                    Entry.container.enableSttValue();\n                    const result = await AudioUtils.startRecord(60 * 1000, language);\n                    Entry.dispatchEvent('audioRecordingDone');\n                    Entry.container.setSttValue(result || '-');\n                } catch (e) {\n                    Entry.container.setSttValue('-');\n                    throw e;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_stt',\n        },\n        timed_speech_to_text_convert: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '10',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.korean_s, 'Kor'],\n                        [Lang.Blocks.english_s, 'Eng'],\n                        [Lang.Blocks.japan_s, 'Jpn'],\n                    ],\n                    value: 'Kor',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/ai_utilize_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {\n                viewAdd: [\n                    function() {\n                        if (Entry.container.sttValue) {\n                            Entry.container.sttValue.setVisible(true);\n                        }\n                    },\n                ],\n                viewDestroy: [\n                    function(block, notIncludeSelf) {\n                        if (Entry.container.sttValue) {\n                            Entry.container.sttValue.checkVisible(block, notIncludeSelf);\n                        }\n                    },\n                ],\n            },\n            def: {\n                params: [null],\n                type: 'timed_speech_to_text_convert',\n            },\n            paramsKeyMap: {\n                TIME: 0,\n                LANG: 1,\n            },\n            class: 'stt',\n            isNotFor: ['audio'],\n            async func(sprite, script) {\n                if (!AudioUtils.isInitialized) {\n                    await AudioUtils.initialize();\n                }\n                if (AudioUtils.isRecording) {\n                    return;\n                }\n                try {\n                    const time = _clamp(script.getNumberValue('TIME'), 1, 60);\n\n                    const language = script.getField('LANG', script);\n                    if (language === 'Kor') {\n                        Entry.container.sttValue.setName(\n                            `${Lang.template.voice_title_text}:${Lang.Blocks.korean_s}`\n                        );\n                    } else if (language === 'Eng') {\n                        Entry.container.sttValue.setName(\n                            `${Lang.template.voice_title_text}:${Lang.Blocks.english_s}`\n                        );\n                    } else if (language === 'Jpn') {\n                        Entry.container.sttValue.setName(\n                            `${Lang.template.voice_title_text}:${Lang.Blocks.japan_s}`\n                        );\n                    }\n                    AudioUtils.isRecording = true;\n                    Entry.container.enableSttValue();\n                    const result = await AudioUtils.startTimedRecord(time * 1000, language);\n                    Entry.dispatchEvent('audioRecordingDone');\n                    Entry.container.setSttValue(result || '-');\n                } catch (e) {\n                    Entry.container.setSttValue('-');\n                    throw e;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_stt',\n        },\n        set_visible_speech_to_text: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CALC_timer_visible_show, 'SHOW'],\n                        [Lang.Blocks.CALC_timer_visible_hide, 'HIDE'],\n                    ],\n                    value: 'SHOW',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/ai_utilize_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {\n                viewAdd: [\n                    function() {\n                        if (Entry.container.sttValue) {\n                            Entry.container.sttValue.setVisible(true);\n                        }\n                    },\n                ],\n                viewDestroy: [\n                    function(block, notIncludeSelf) {\n                        if (Entry.container.sttValue) {\n                            Entry.container.sttValue.checkVisible(block, notIncludeSelf);\n                        }\n                    },\n                ],\n            },\n            def: {\n                type: 'set_visible_speech_to_text',\n            },\n            paramsKeyMap: {\n                ACTION: 0,\n            },\n            class: 'stt',\n            isNotFor: ['audio'],\n            func(sprite, script) {\n                const action = script.getField('ACTION');\n                const sttValue = Entry.container.sttValue;\n\n                if (!sttValue) {\n                    return script.callReturn();\n                } else if (action === 'SHOW') {\n                    sttValue.setVisible(true);\n                } else {\n                    sttValue.setVisible(false);\n                }\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_stt',\n        },\n        speech_to_text_get_value: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {\n                viewAdd: [\n                    function() {\n                        if (Entry.container.sttValue) {\n                            Entry.container.sttValue.setVisible(true);\n                        }\n                    },\n                ],\n                viewDestroy: [\n                    function(block, notIncludeSelf) {\n                        if (Entry.container.sttValue) {\n                            Entry.container.sttValue.checkVisible(block, notIncludeSelf);\n                        }\n                    },\n                ],\n            },\n            def: {\n                type: 'speech_to_text_get_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'stt',\n            isNotFor: ['audio'],\n            func(sprite, script) {\n                return Entry.container.getSttValue();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_stt',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_face_landmarker.js",
    "content": "import MediaPipeUtils from '../../util/mediaPipeUtils';\n\nconst mediaPipeUtils = MediaPipeUtils.getInstance();\nEntry.AI_UTILIZE_BLOCK.faceLandmarker = {\n    name: 'faceLandmarker',\n    imageName: 'faceLandmarker.svg',\n    category: 'video',\n    title: {\n        ko: '얼굴 인식',\n        en: 'Face Detection',\n    },\n    titleKey: 'Workspace.face_landmarker_title_text',\n    description: Lang.Msgs.ai_utilize_face_landmarker_description,\n    descriptionKey: 'Msgs.ai_utilize_face_landmarker_description',\n    isInitialized: false,\n    async init() {\n        await mediaPipeUtils.initialize();\n        Entry.AI_UTILIZE_BLOCK.faceLandmarker.isInitialized = true;\n    },\n    destroy() {\n        mediaPipeUtils.destroy();\n        Entry.AI_UTILIZE_BLOCK.faceLandmarker.isInitialized = false;\n    },\n};\n\nEntry.AI_UTILIZE_BLOCK.faceLandmarker.getBlocks = function() {\n    const params = {\n        getEventIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/start_icon_face.svg',\n                size: 14,\n                position: {\n                    x: 0,\n                    y: -2,\n                },\n            };\n        },\n        getCommonIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/ai_face_icon.svg',\n                size: 11,\n            };\n        },\n        getFaceNumber() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['1', 0],\n                    ['2', 1],\n                    ['3', 2],\n                    ['4', 3],\n                ],\n                value: 0,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getGender() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.video_gender.female, 'female'],\n                    [Lang.video_gender.male, 'male'],\n                ],\n                value: 'female',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getFaceCategory() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_gender, 'gender'],\n                    [Lang.Blocks.video_age, 'age'],\n                    [Lang.Blocks.video_emotion, 'emotion'],\n                ],\n                value: 'gender',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getOperators() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['=', 'EQUAL'],\n                    ['!=', 'NOT_EQUAL'],\n                    ['>', 'GREATER'],\n                    ['<', 'LESS'],\n                    ['≥', 'GREATER_OR_EQUAL'],\n                    ['≤', 'LESS_OR_EQUAL'],\n                ],\n                value: 'EQUAL',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getEmotions() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.video_emotion_params.angry, 'angry'],\n                    [Lang.video_emotion_params.disgust, 'disgust'],\n                    [Lang.video_emotion_params.fear, 'fear'],\n                    [Lang.video_emotion_params.happy, 'happy'],\n                    [Lang.video_emotion_params.neutral, 'neutral'],\n                    [Lang.video_emotion_params.sad, 'sad'],\n                    [Lang.video_emotion_params.surprise, 'surprise'],\n                ],\n                value: 'angry',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getFacePoint() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.video_body_coord_params.left_eye, 374],\n                    [Lang.video_body_coord_params.right_eye, 145],\n                    [Lang.video_body_coord_params.nose, 4],\n                    [Lang.video_body_coord_params.left_mouth, 291],\n                    [Lang.video_body_coord_params.right_mouth, 61],\n                    [Lang.video_body_coord_params.upper_lip, 0],\n                    [Lang.video_body_coord_params.lower_lip, 17],\n                ],\n                value: 374,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                dropdownSync: 'handPoint',\n            };\n        },\n        getAxis() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['x', 'x'],\n                    ['y', 'y'],\n                ],\n                value: 'x',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getStartStop() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_start, 'start'],\n                    [Lang.Blocks.video_end, 'stop'],\n                ],\n                value: 'start',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getShowHide() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_show_video, 'show'],\n                    [Lang.Blocks.video_hide_video, 'hide'],\n                ],\n                value: 'show',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n    };\n    return {\n        face_landmarker_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.face_landmarker_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'face_landmarker_title',\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            events: {},\n        },\n        when_face_landmarker: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_event',\n            statements: [],\n            params: [params.getEventIndicator()],\n            events: {},\n            def: {\n                params: [null],\n                type: 'when_face_landmarker',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            event: 'when_face_landmarker',\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        face_landmarker: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getStartStop(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'face_landmarker',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!mediaPipeUtils.isInitialized) {\n                    await mediaPipeUtils.initialize();\n                }\n                if (value === 'start') {\n                    await mediaPipeUtils.startFaceLandmarker(value);\n                } else {\n                    await mediaPipeUtils.stopFaceLandmarker(value);\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        draw_detected_face: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getShowHide(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'draw_detected_face',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!mediaPipeUtils.isInitialized) {\n                    await mediaPipeUtils.initialize();\n                }\n                if (value === 'show') {\n                    mediaPipeUtils.changeDrawDetectedFaceLandmarker(true);\n                } else {\n                    mediaPipeUtils.changeDrawDetectedFaceLandmarker(false);\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        check_detected_face: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'check_detected_face',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                return mediaPipeUtils.isPrevFaceLandmarker;\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        count_detected_face: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'count_detected_face',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                return mediaPipeUtils.countDetectedFace || 0;\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        locate_to_face: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getFaceNumber(), params.getFacePoint(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'locate_to_face',\n            },\n            paramsKeyMap: {\n                FACE: 0,\n                FACE_POINT: 1,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                const face = script.getField('FACE');\n                const point = script.getField('FACE_POINT');\n                const axis = mediaPipeUtils.getFacePointAxis(face, point);\n                if (axis) {\n                    sprite.setX(axis.x);\n                    sprite.setY(axis.y);\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(axis.x, axis.y * -1);\n                    }\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        locate_time_to_face: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getFaceNumber(),\n                params.getFacePoint(),\n                params.getCommonIndicator(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'locate_time_to_face',\n            },\n            paramsKeyMap: {\n                TIME: 0,\n                FACE: 1,\n                FACE_POINT: 2,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const time = script.getNumberValue('TIME', script);\n                    const frameCount = Math.floor(time * Entry.FPS);\n                    const face = script.getField('FACE', script);\n                    const point = script.getField('FACE_POINT', script);\n\n                    if (frameCount != 0) {\n                        const axis = mediaPipeUtils.getFacePointAxis(face, point);\n                        if (axis) {\n                            script.isStart = true;\n                            script.frameCount = frameCount;\n                            script.dX = (axis.x - sprite.getX()) / script.frameCount;\n                            script.dY = (axis.y - sprite.getY()) / script.frameCount;\n                        }\n                    } else {\n                        const axis = mediaPipeUtils.getFacePointAxis(face, point);\n                        if (axis) {\n                            sprite.setX(axis.x);\n                            sprite.setY(axis.y);\n                            if (sprite.brush && !sprite.brush.stop) {\n                                sprite.brush.lineTo(axis.x, axis.y * -1);\n                            }\n                        }\n                        return script.callReturn();\n                    }\n                }\n                if (script.frameCount != 0) {\n                    sprite.setX(sprite.getX() + script.dX);\n                    sprite.setY(sprite.getY() + script.dY);\n                    script.frameCount--;\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.frameCount;\n                    return script.callReturn();\n                }\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        check_detected_gender: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                { ...params.getFaceNumber(), fontSize: 10 },\n                { ...params.getGender(), fontSize: 10 },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'check_detected_gender',\n            },\n            paramsKeyMap: {\n                FACE: 0,\n                GENDER: 1,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                const face = script.getField('FACE', script);\n                const gender = script.getField('GENDER', script);\n                const result = mediaPipeUtils.getFaceGender(face);\n                return result === gender;\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        check_compare_age: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                { ...params.getFaceNumber(), fontSize: 10 },\n                { ...params.getOperators(), fontSize: 10 },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                ],\n                type: 'check_compare_age',\n            },\n            paramsKeyMap: {\n                FACE: 0,\n                OPERATOR: 1,\n                AGE: 2,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                const face = script.getField('FACE', script);\n                const operator = script.getField('OPERATOR', script);\n                const age = script.getNumberValue('AGE', script);\n                const result = mediaPipeUtils.getFaceAge(face);\n\n                switch (operator) {\n                    case 'EQUAL':\n                        return result === age;\n                    case 'NOT_EQUAL':\n                        return result != age;\n                    case 'GREATER':\n                        return result > age;\n                    case 'LESS':\n                        return result < age;\n                    case 'GREATER_OR_EQUAL':\n                        return result >= age;\n                    case 'LESS_OR_EQUAL':\n                        return result <= age;\n                }\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        check_detected_emotion: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                { ...params.getFaceNumber(), fontSize: 10 },\n                { ...params.getEmotions(), fontSize: 10 },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'check_detected_emotion',\n            },\n            paramsKeyMap: {\n                FACE: 0,\n                EMOTION: 1,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                const face = script.getField('FACE', script);\n                const emotion = script.getField('EMOTION', script);\n                const result = mediaPipeUtils.getFaceEmotion(face);\n                return result === emotion;\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        axis_detected_face: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { ...params.getFaceNumber(), fontSize: 10 },\n                { ...params.getFacePoint(), fontSize: 10 },\n                { ...params.getAxis(), fontSize: 10 },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'axis_detected_face',\n            },\n            paramsKeyMap: {\n                FACE: 0,\n                FACE_POINT: 1,\n                AXIS: 2,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                const face = script.getField('FACE', script);\n                const point = script.getField('FACE_POINT', script);\n                const axisName = script.getField('AXIS', script);\n                const axis = mediaPipeUtils.getFacePointAxis(face, point);\n                if (axis) {\n                    return axis[axisName] || 0;\n                }\n                return 0;\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n        get_detected_face_value: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { ...params.getFaceNumber(), fontSize: 10 },\n                { ...params.getFaceCategory(), fontSize: 10 },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'get_detected_face_value',\n            },\n            paramsKeyMap: {\n                FACE: 0,\n                CATEGORY: 1,\n            },\n            class: 'face',\n            isNotFor: ['faceLandmarker'],\n            func(sprite, script) {\n                const face = script.getField('FACE', script);\n                const category = script.getField('CATEGORY', script);\n\n                if (!mediaPipeUtils.isPrevFaceLandmarker) {\n                    if (['gender', 'emotion'].includes(category)) {\n                        return 'null';\n                    } else {\n                        return 0;\n                    }\n                }\n\n                switch (category) {\n                    case 'gender':\n                        return (\n                            Lang.video_gender[mediaPipeUtils.getFaceGender(face)] ||\n                            Lang.Blocks.unknown\n                        );\n                    case 'age':\n                        return mediaPipeUtils.getFaceAge(face) || 0;\n                    case 'emotion':\n                        return (\n                            Lang.video_emotion_params[mediaPipeUtils.getFaceEmotion(face)] ||\n                            Lang.Blocks.unknown\n                        );\n                }\n            },\n            wikiClass: 'ai_utilize_face',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_gesture_recognition.js",
    "content": "import MediaPipeUtils from '../../util/mediaPipeUtils';\n\nconst mediaPipeUtils = MediaPipeUtils.getInstance();\nEntry.AI_UTILIZE_BLOCK.gestureRecognition = {\n    name: 'gestureRecognition',\n    imageName: 'gestureRecognition.svg',\n    category: 'video',\n    title: {\n        ko: '손 인식',\n        en: 'Gesture Recognition',\n    },\n    titleKey: 'Workspace.gesture_recognition_title_text',\n    description: Lang.Msgs.ai_utilize_gesture_recognition_description,\n    descriptionKey: 'Msgs.ai_utilize_gesture_recognition_description',\n    isInitialized: false,\n    async init() {\n        await mediaPipeUtils.initialize();\n        Entry.AI_UTILIZE_BLOCK.gestureRecognition.isInitialized = true;\n    },\n    destroy() {\n        mediaPipeUtils.destroy();\n        Entry.AI_UTILIZE_BLOCK.gestureRecognition.isInitialized = false;\n    },\n};\n\nEntry.AI_UTILIZE_BLOCK.gestureRecognition.getBlocks = function() {\n    const params = {\n        getEventIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/start_icon_hand.svg',\n                size: 14,\n                position: {\n                    x: 0,\n                    y: -2,\n                },\n            };\n        },\n        getCommonIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/ai_hand_icon.svg',\n                size: 11,\n            };\n        },\n        getHandNumber() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['1', 0],\n                    ['2', 1],\n                ],\n                value: 0,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getHand() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.right_hand, 'Left'],\n                    [Lang.Blocks.left_hand, 'Right'],\n                ],\n                value: 'Left',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getGesture() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.gesture_list.closed_fist, 'Closed_Fist'],\n                    [Lang.gesture_list.open_palm, 'Open_Palm'],\n                    [Lang.gesture_list.pointing_up, 'Pointing_Up'],\n                    [Lang.gesture_list.thumb_down, 'Thumb_Down'],\n                    [Lang.gesture_list.thumb_up, 'Thumb_Up'],\n                    [Lang.gesture_list.victory, 'Victory'],\n                    [Lang.gesture_list.iloveyou, 'ILoveYou'],\n                ],\n                value: 'Closed_Fist',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getHandPoint() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.thumb, 1],\n                    [Lang.Blocks.index_finger, 5],\n                    [Lang.Blocks.middle_finger, 9],\n                    [Lang.Blocks.ring_finger, 13],\n                    [Lang.Blocks.little_finger, 17],\n                    [Lang.Blocks.wrist, 0],\n                ],\n                value: 1,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                dropdownSync: 'handPoint',\n            };\n        },\n        getHandDetailPoint() {\n            return {\n                type: 'DropdownDynamic',\n                menuName() {\n                    const handPoint = this.getTargetValue('handPoint');\n                    const value = this.getValue();\n                    if (handPoint === 1) {\n                        if (![2, 3].includes(value)) {\n                            this.setValue(3);\n                        }\n                        return [\n                            [Lang.Blocks.tip, 3],\n                            [Lang.Blocks.dip, 2],\n                        ];\n                    } else if (handPoint !== 0) {\n                        if (![1, 2, 3].includes(value)) {\n                            this.setValue(3);\n                        }\n                        return [\n                            [Lang.Blocks.tip, 3],\n                            [Lang.Blocks.dip, 2],\n                            [Lang.Blocks.pip, 1],\n                        ];\n                    } else {\n                        this.setValue(0);\n                        return [[Lang.Blocks.none, 0]];\n                    }\n                },\n                needDeepCopy: true,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getAxis() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['x', 'x'],\n                    ['y', 'y'],\n                ],\n                value: 'x',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getStartStop() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_start, 'start'],\n                    [Lang.Blocks.video_end, 'stop'],\n                ],\n                value: 'start',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getShowHide() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_show_video, 'show'],\n                    [Lang.Blocks.video_hide_video, 'hide'],\n                ],\n                value: 'show',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n    };\n    return {\n        hand_detection_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.hand_detection_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'hand_detection_title',\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            events: {},\n        },\n        when_hand_detection: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_event',\n            statements: [],\n            params: [params.getEventIndicator()],\n            events: {},\n            def: {\n                params: [null],\n                type: 'when_hand_detection',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            event: 'when_hand_detection',\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        hand_detection: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getStartStop(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'hand_detection',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!mediaPipeUtils.isInitialized) {\n                    await mediaPipeUtils.initialize();\n                }\n                if (value === 'start') {\n                    await mediaPipeUtils.startHandGestureRecognition(value);\n                } else {\n                    await mediaPipeUtils.stopHandGestureRecognition(value);\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        draw_detected_hand: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getShowHide(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'draw_detected_hand',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!mediaPipeUtils.isInitialized) {\n                    await mediaPipeUtils.initialize();\n                }\n                if (value === 'show') {\n                    mediaPipeUtils.changeDrawDetectedHand(true);\n                } else {\n                    mediaPipeUtils.changeDrawDetectedHand(false);\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        check_detected_hand: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'check_detected_hand',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                return mediaPipeUtils.isPrevHandDetected;\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        count_detected_hand: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'count_detected_hand',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                return mediaPipeUtils.countDetectedHand;\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        locate_to_hand: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                params.getHandNumber(),\n                params.getHandPoint(),\n                params.getHandDetailPoint(),\n                params.getCommonIndicator(),\n            ],\n            events: {},\n            def: {\n                type: 'locate_to_hand',\n            },\n            paramsKeyMap: {\n                HAND: 0,\n                HAND_POINT: 1,\n                HAND_DETAIL_POINT: 2,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                const hand = script.getField('HAND');\n                const point = script.getField('HAND_POINT');\n                const detail = script.getField('HAND_DETAIL_POINT');\n                const handPoint = point + detail;\n                const axis = mediaPipeUtils.getHandPointAxis(hand, handPoint);\n                if (axis) {\n                    sprite.setX(axis.x);\n                    sprite.setY(axis.y);\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(axis.x, axis.y * -1);\n                    }\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        locate_time_to_hand: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getHandNumber(),\n                params.getHandPoint(),\n                params.getHandDetailPoint(),\n                params.getCommonIndicator(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'locate_time_to_hand',\n            },\n            paramsKeyMap: {\n                TIME: 0,\n                HAND: 1,\n                HAND_POINT: 2,\n                HAND_DETAIL_POINT: 3,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const time = script.getNumberValue('TIME', script);\n                    const frameCount = Math.floor(time * Entry.FPS);\n                    const hand = script.getField('HAND', script);\n                    const point = script.getField('HAND_POINT', script);\n                    const detail = script.getField('HAND_DETAIL_POINT', script);\n                    const handPoint = point + detail;\n\n                    if (frameCount != 0) {\n                        const axis = mediaPipeUtils.getHandPointAxis(hand, handPoint);\n                        if (axis) {\n                            script.isStart = true;\n                            script.frameCount = frameCount;\n                            script.dX = (axis.x - sprite.getX()) / script.frameCount;\n                            script.dY = (axis.y - sprite.getY()) / script.frameCount;\n                        }\n                    } else {\n                        const axis = mediaPipeUtils.getHandPointAxis(hand, handPoint);\n                        if (axis) {\n                            sprite.setX(axis.x);\n                            sprite.setY(axis.y);\n                            if (sprite.brush && !sprite.brush.stop) {\n                                sprite.brush.lineTo(axis.x, axis.y * -1);\n                            }\n                        }\n                        return script.callReturn();\n                    }\n                }\n                if (script.frameCount != 0) {\n                    sprite.setX(sprite.getX() + script.dX);\n                    sprite.setY(sprite.getY() + script.dY);\n                    script.frameCount--;\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.frameCount;\n                    return script.callReturn();\n                }\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        axis_detected_hand: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { ...params.getHandNumber(), fontSize: 10 },\n                { ...params.getHandPoint(), fontSize: 10 },\n                { ...params.getHandDetailPoint(), fontSize: 10 },\n                { ...params.getAxis(), fontSize: 10 },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'axis_detected_hand',\n            },\n            paramsKeyMap: {\n                HAND: 0,\n                HAND_POINT: 1,\n                HAND_DETAIL_POINT: 2,\n                AXIS: 3,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                const hand = script.getField('HAND', script);\n                const point = script.getField('HAND_POINT', script);\n                const detail = script.getField('HAND_DETAIL_POINT', script);\n                const axisName = script.getField('AXIS', script);\n                const handPoint = point + detail;\n                const axis = mediaPipeUtils.getHandPointAxis(hand, handPoint);\n                if (axis) {\n                    return axis[axisName] || 0;\n                }\n                return 0;\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        is_which_hand: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                { ...params.getHandNumber(), fontSize: 10 },\n                { ...params.getHand(), fontSize: 10 },\n            ],\n            events: {},\n            def: { params: [null, null], type: 'is_which_hand' },\n            paramsKeyMap: {\n                HAND_NUM: 0,\n                HAND: 1,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                const handNum = script.getField('HAND_NUM', script);\n                const hand = script.getField('HAND', script);\n                const handedness = mediaPipeUtils.getHandedness(handNum);\n                if (!handedness) {\n                    return false;\n                }\n                return handedness.categoryName === hand;\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        get_which_hand: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{ ...params.getHandNumber(), fontSize: 10 }],\n            events: {},\n            def: { params: [null, null], type: 'get_which_hand' },\n            paramsKeyMap: {\n                HAND_NUM: 0,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                const handNum = script.getField('HAND_NUM', script);\n                const handedness = mediaPipeUtils.getHandedness(handNum);\n                if (!handedness) {\n                    return 'null';\n                } else if (handedness.categoryName === 'Left') {\n                    return Lang.Blocks.right_hand;\n                } else {\n                    return Lang.Blocks.left_hand;\n                }\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        is_which_gesture: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                { ...params.getHandNumber(), fontSize: 10 },\n                { ...params.getGesture(), fontSize: 10 },\n            ],\n            events: {},\n            def: { params: [null, null], type: 'is_which_gesture' },\n            paramsKeyMap: {\n                HAND_NUM: 0,\n                GESTURE: 1,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                const handNum = script.getField('HAND_NUM', script);\n                const gestureName = script.getField('GESTURE', script);\n                const gesture = mediaPipeUtils.getGesture(handNum);\n                if (!gesture) {\n                    return false;\n                }\n                return gesture.categoryName === gestureName;\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n        get_which_gesture: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{ ...params.getHandNumber(), fontSize: 10 }],\n            events: {},\n            def: { params: [null, null], type: 'get_which_gesture' },\n            paramsKeyMap: {\n                HAND_NUM: 0,\n            },\n            class: 'hand',\n            isNotFor: ['gestureRecognition'],\n            func(sprite, script) {\n                const handNum = script.getField('HAND_NUM', script);\n                const gesture = mediaPipeUtils.getGesture(handNum);\n\n                if (!gesture) {\n                    return 'null';\n                }\n                return Lang.gesture_list[gesture.categoryName.toLowerCase()] || Lang.Blocks.unknown;\n            },\n            wikiClass: 'ai_utilize_gesture',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_media_pipe.js",
    "content": "import MediaPipeUtils, { flipState } from '../../util/mediaPipeUtils';\nimport _clamp from 'lodash/clamp';\n\nconst mediaPipeUtils = MediaPipeUtils.getInstance();\nEntry.MediaPipeUtils = mediaPipeUtils;\n\nconst flipStateTransitions = {\n    hflip: [flipState.HORIZONTAL, flipState.NORMAL, flipState.BOTH, flipState.VERTICAL],\n    vflip: [flipState.VERTICAL, flipState.BOTH, flipState.NORMAL, flipState.HORIZONTAL],\n};\n\nmodule.exports = {\n    getBlocks() {\n        const params = {\n            getCommonIndicator() {\n                return {\n                    type: 'Indicator',\n                    img: 'block_icon/ai_video_icon.svg',\n                    size: 11,\n                };\n            },\n            getCameraOrder() {\n                return {\n                    type: 'DropdownDynamic',\n                    menuName: 'connectedCameras',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                };\n            },\n            getVideoFlipOptions() {\n                return {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.video_left_right, 'hflip'],\n                        [Lang.Blocks.video_top_bottom, 'vflip'],\n                    ],\n                    value: 'hflip',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                };\n            },\n            getOnOff() {\n                return {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.video_show_video, 'on'],\n                        [Lang.Blocks.video_hide_video, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                };\n            },\n        };\n\n        return {\n            media_pipe_title: {\n                template: '%1',\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.media_pipe_title_text,\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'media_pipe_title',\n                },\n                class: 'media_pipe',\n                isNotFor: [\n                    'gestureRecognition',\n                    'poseLandmarker',\n                    'faceLandmarker',\n                    'objectDetector',\n                ],\n                events: {},\n            },\n            media_pipe_video_screen: {\n                color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n                outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                skeleton: 'basic',\n                statements: [],\n                params: [params.getOnOff(), params.getCommonIndicator()],\n                events: {},\n                def: {\n                    type: 'media_pipe_video_screen',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'media_pipe',\n                isNotFor: [\n                    'gestureRecognition',\n                    'poseLandmarker',\n                    'faceLandmarker',\n                    'objectDetector',\n                ],\n                async func(sprite, script) {\n                    const value = script.getField('VALUE');\n                    if (!mediaPipeUtils.isInitialized) {\n                        await mediaPipeUtils.initialize();\n                    }\n                    mediaPipeUtils.cameraOnOff(value);\n                    return script.callReturn();\n                },\n                wikiClass: 'ai_utilize_video',\n            },\n            media_pipe_switch_camera: {\n                color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n                outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                skeleton: 'basic',\n                statements: [],\n                params: [params.getCameraOrder(), params.getCommonIndicator()],\n                events: {},\n                def: {\n                    type: 'media_pipe_switch_camera',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'media_pipe',\n                isNotFor: [\n                    'gestureRecognition',\n                    'poseLandmarker',\n                    'faceLandmarker',\n                    'objectDetector',\n                ],\n                async func(sprite, script) {\n                    const value = script.getField('VALUE');\n                    return await mediaPipeUtils.changeSource(value);\n                },\n                wikiClass: 'ai_utilize_video',\n            },\n            check_connected_camera: {\n                color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n                outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    type: 'check_connected_camera',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'media_pipe',\n                isNotFor: [\n                    'gestureRecognition',\n                    'poseLandmarker',\n                    'faceLandmarker',\n                    'objectDetector',\n                ],\n                async func(sprite, script) {\n                    return mediaPipeUtils.videoInputList.length;\n                },\n                wikiClass: 'ai_utilize_video',\n            },\n            media_pipe_flip_camera: {\n                color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n                outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                skeleton: 'basic',\n                statements: [],\n                params: [params.getVideoFlipOptions(), params.getCommonIndicator()],\n                events: {},\n                def: {\n                    type: 'media_pipe_flip_camera',\n                },\n                paramsKeyMap: {\n                    TARGET: 0,\n                },\n                class: 'media_pipe',\n                isNotFor: [\n                    'gestureRecognition',\n                    'poseLandmarker',\n                    'faceLandmarker',\n                    'objectDetector',\n                ],\n                async func(sprite, script) {\n                    const target = script.getField('TARGET');\n                    if (!mediaPipeUtils.isInitialized) {\n                        await mediaPipeUtils.initialize();\n                    }\n                    const flipState = flipStateTransitions[target][mediaPipeUtils.flipState];\n                    mediaPipeUtils.setFlipState(flipState);\n                    return script.callReturn();\n                },\n                wikiClass: 'ai_utilize_video',\n            },\n            media_pipe_set_opacity_camera: {\n                color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n                outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: '0',\n                    },\n                    params.getCommonIndicator(),\n                ],\n                events: {},\n                def: {\n                    type: 'media_pipe_set_opacity_camera',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'media_pipe',\n                isNotFor: [\n                    'gestureRecognition',\n                    'poseLandmarker',\n                    'faceLandmarker',\n                    'objectDetector',\n                ],\n                async func(sprite, script) {\n                    const value = _clamp(script.getNumberValue('VALUE'), 0, 100);\n                    if (!mediaPipeUtils.isInitialized) {\n                        await mediaPipeUtils.initialize();\n                    }\n                    mediaPipeUtils.setOpacityCamera(value);\n                    return script.callReturn();\n                },\n                wikiClass: 'ai_utilize_video',\n            },\n            media_pipe_motion_value: {\n                color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n                outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.video_motion_onself, 'self'],\n                            [Lang.Blocks.video_motion_onscreen, 'screen'],\n                        ],\n                        value: 'self',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.video_motion_scale, 'total'],\n                            [Lang.Blocks.video_motion_direction_horizontal, 'x'],\n                            [Lang.Blocks.video_motion_direction_vertical, 'y'],\n                        ],\n                        value: 'total',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                ],\n                events: {},\n                def: {\n                    type: 'media_pipe_motion_value',\n                },\n                paramsKeyMap: {\n                    TARGET: 0,\n                    TYPE: 1,\n                },\n                class: 'media_pipe',\n                isNotFor: [\n                    'gestureRecognition',\n                    'poseLandmarker',\n                    'faceLandmarker',\n                    'objectDetector',\n                ],\n                async func(sprite, script) {\n                    const target = script.getField('TARGET');\n                    const type = script.getField('TYPE');\n                    if (!mediaPipeUtils.isInitialized) {\n                        await mediaPipeUtils.initialize();\n                    }\n                    let detected = mediaPipeUtils.totalMotions;\n                    if (target === 'self') {\n                        detected = await mediaPipeUtils.motionDetect(sprite);\n                        if (!detected) {\n                            return 0;\n                        }\n                    }\n                    if (type === 'total') {\n                        return _clamp(detected.total / 10, 0, 100000).toString();\n                    }\n                    try {\n                        let rawX = detected.direction.x;\n                        if (!mediaPipeUtils.isFlipState('horizontal')) {\n                            rawX *= -1;\n                        }\n\n                        let rawY = detected.direction.y;\n                        if (mediaPipeUtils.isFlipState('vertical')) {\n                            rawY *= -1;\n                        }\n                        const absX = Math.abs(rawX);\n                        const absY = Math.abs(rawY);\n                        if (absX < 20 && absY < 20) {\n                            return 0;\n                        }\n                        if (type === 'x') {\n                            return rawX.toFixed(1).toString();\n                        } else if (type === 'y') {\n                            return rawY.toFixed(1).toString();\n                        }\n                        return 0;\n                    } catch (err) {\n                        console.log(detected, err);\n                    }\n                },\n                wikiClass: 'ai_utilize_video',\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_object_detector.js",
    "content": "import MediaPipeUtils from '../../util/mediaPipeUtils';\nimport _get from 'lodash/get';\n\nconst mediaPipeUtils = MediaPipeUtils.getInstance();\nEntry.AI_UTILIZE_BLOCK.objectDetector = {\n    name: 'objectDetector',\n    imageName: 'objectDetector.svg',\n    category: 'video',\n    title: {\n        ko: '사물 인식',\n        en: 'Object Detection',\n    },\n    titleKey: 'Workspace.object_detector_title_text',\n    description: Lang.Msgs.ai_utilize_object_detector_description,\n    descriptionKey: 'Msgs.ai_utilize_object_detector_description',\n    isInitialized: false,\n    async init() {\n        await mediaPipeUtils.initialize();\n        Entry.AI_UTILIZE_BLOCK.objectDetector.isInitialized = true;\n    },\n    destroy() {\n        mediaPipeUtils.destroy();\n        Entry.AI_UTILIZE_BLOCK.objectDetector.isInitialized = false;\n    },\n};\n\nEntry.AI_UTILIZE_BLOCK.objectDetector.getBlocks = function() {\n    const params = {\n        getEventIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/start_icon_object.svg',\n                size: 14,\n                position: {\n                    x: 0,\n                    y: -2,\n                },\n            };\n        },\n        getCommonIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/ai_object_icon.svg',\n                size: 11,\n            };\n        },\n        getObjectNumber() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['1', 0],\n                    ['2', 1],\n                    ['3', 2],\n                    ['4', 3],\n                ],\n                value: 0,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getStartStop() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_start, 'start'],\n                    [Lang.Blocks.video_end, 'stop'],\n                ],\n                value: 'start',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getShowHide() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_show_video, 'show'],\n                    [Lang.Blocks.video_hide_video, 'hide'],\n                ],\n                value: 'show',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getObjectList() {\n            return {\n                type: 'DropdownExtra',\n                options: [\n                    [Lang.video_object_params.person, 'person'],\n                    [Lang.video_object_params.bicycle, 'bicycle'],\n                    [Lang.video_object_params.car, 'car'],\n                    [Lang.video_object_params.motorcycle, 'motorcycle'],\n                    [Lang.video_object_params.airplane, 'airplane'],\n                    [Lang.video_object_params.bus, 'bus'],\n                    [Lang.video_object_params.train, 'train'],\n                    [Lang.video_object_params.truck, 'truck'],\n                    [Lang.video_object_params.boat, 'boat'],\n                    [Lang.video_object_params['traffic light'], 'traffic light'],\n                    [Lang.video_object_params['fire hydrant'], 'fire hydrant'],\n                    [Lang.video_object_params['stop sign'], 'stop sign'],\n                    [Lang.video_object_params['parking meter'], 'parking meter'],\n                    [Lang.video_object_params.bench, 'bench'],\n                    [Lang.video_object_params.bird, 'bird'],\n                    [Lang.video_object_params.cat, 'cat'],\n                    [Lang.video_object_params.dog, 'dog'],\n                    [Lang.video_object_params.horse, 'horse'],\n                    [Lang.video_object_params.sheep, 'sheep'],\n                    [Lang.video_object_params.cow, 'cow'],\n                    [Lang.video_object_params.elephant, 'elephant'],\n                    [Lang.video_object_params.bear, 'bear'],\n                    [Lang.video_object_params.zebra, 'zebra'],\n                    [Lang.video_object_params.giraffe, 'giraffe'],\n                    [Lang.video_object_params.backpack, 'backpack'],\n                    [Lang.video_object_params.umbrella, 'umbrella'],\n                    [Lang.video_object_params.handbag, 'handbag'],\n                    [Lang.video_object_params.tie, 'tie'],\n                    [Lang.video_object_params.suitcase, 'suitcase'],\n                    [Lang.video_object_params.frisbee, 'frisbee'],\n                    [Lang.video_object_params.skis, 'skis'],\n                    [Lang.video_object_params.snowboard, 'snowboard'],\n                    [Lang.video_object_params['sports ball'], 'sports ball'],\n                    [Lang.video_object_params.kite, 'kite'],\n                    [Lang.video_object_params['baseball bat'], 'baseball bat'],\n                    [Lang.video_object_params['baseball glove'], 'baseball glove'],\n                    [Lang.video_object_params.skateboard, 'skateboard'],\n                    [Lang.video_object_params.surfboard, 'surfboard'],\n                    [Lang.video_object_params['tennis racket'], 'tennis racket'],\n                    [Lang.video_object_params.bottle, 'bottle'],\n                    [Lang.video_object_params['wine glass'], 'wine glass'],\n                    [Lang.video_object_params.cup, 'cup'],\n                    [Lang.video_object_params.fork, 'fork'],\n                    [Lang.video_object_params.knife, 'knife'],\n                    [Lang.video_object_params.spoon, 'spoon'],\n                    [Lang.video_object_params.bowl, 'bowl'],\n                    [Lang.video_object_params.banana, 'banana'],\n                    [Lang.video_object_params.apple, 'apple'],\n                    [Lang.video_object_params.sandwich, 'sandwich'],\n                    [Lang.video_object_params.orange, 'orange'],\n                    [Lang.video_object_params.broccoli, 'broccoli'],\n                    [Lang.video_object_params.carrot, 'carrot'],\n                    [Lang.video_object_params['hot dog'], 'hot dog'],\n                    [Lang.video_object_params.pizza, 'pizza'],\n                    [Lang.video_object_params.donut, 'donut'],\n                    [Lang.video_object_params.cake, 'cake'],\n                    [Lang.video_object_params.chair, 'chair'],\n                    [Lang.video_object_params.couch, 'couch'],\n                    [Lang.video_object_params['potted plant'], 'potted plant'],\n                    [Lang.video_object_params.bed, 'bed'],\n                    [Lang.video_object_params['dining table'], 'dining table'],\n                    [Lang.video_object_params.toilet, 'toilet'],\n                    [Lang.video_object_params.tv, 'tv'],\n                    [Lang.video_object_params.laptop, 'laptop'],\n                    [Lang.video_object_params.mouse, 'mouse'],\n                    [Lang.video_object_params.remote, 'remote'],\n                    [Lang.video_object_params.keyboard, 'keyboard'],\n                    [Lang.video_object_params['cell phone'], 'cell phone'],\n                    [Lang.video_object_params.microwave, 'microwave'],\n                    [Lang.video_object_params.oven, 'oven'],\n                    [Lang.video_object_params.toaster, 'toaster'],\n                    [Lang.video_object_params.sink, 'sink'],\n                    [Lang.video_object_params.refrigerator, 'refrigerator'],\n                    [Lang.video_object_params.book, 'book'],\n                    [Lang.video_object_params.clock, 'clock'],\n                    [Lang.video_object_params.vase, 'vase'],\n                    [Lang.video_object_params.scissors, 'scissors'],\n                    [Lang.video_object_params['teddy bear'], 'teddy bear'],\n                    [Lang.video_object_params['hair drier'], 'hair drier'],\n                    [Lang.video_object_params.toothbrush, 'toothbrush'],\n                ],\n                value: 'bicycle',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n    };\n    return {\n        object_detector_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.object_detector_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'object_detector_title',\n            },\n            class: 'object',\n            isNotFor: ['objectDetector'],\n            events: {},\n        },\n        when_object_detector: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_event',\n            statements: [],\n            params: [params.getEventIndicator()],\n            events: {},\n            def: {\n                params: [null],\n                type: 'when_object_detector',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            event: 'when_object_detector',\n            class: 'object',\n            isNotFor: ['objectDetector'],\n            func(sprite, script) {\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_object',\n        },\n        object_detector: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getStartStop(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'object_detector',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'object',\n            isNotFor: ['objectDetector'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!mediaPipeUtils.isInitialized) {\n                    await mediaPipeUtils.initialize();\n                }\n                if (value === 'start') {\n                    await mediaPipeUtils.startObjectDetector(value);\n                } else {\n                    await mediaPipeUtils.stopObjectDetector(value);\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_object',\n        },\n        draw_detected_object: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getShowHide(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'draw_detected_object',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'object',\n            isNotFor: ['objectDetector'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!mediaPipeUtils.isInitialized) {\n                    await mediaPipeUtils.initialize();\n                }\n                if (value === 'show') {\n                    mediaPipeUtils.changeDrawDetectedObjectDetector(true);\n                } else {\n                    mediaPipeUtils.changeDrawDetectedObjectDetector(false);\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_object',\n        },\n        check_detected_object: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'check_detected_object',\n            },\n            paramsKeyMap: {},\n            class: 'object',\n            isNotFor: ['objectDetector'],\n            func(sprite, script) {\n                return mediaPipeUtils.isPrevObjectDetector;\n            },\n            wikiClass: 'ai_utilize_object',\n        },\n        count_detected_object: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'count_detected_object',\n            },\n            paramsKeyMap: {},\n            class: 'object',\n            isNotFor: ['objectDetector'],\n            func(sprite, script) {\n                return mediaPipeUtils.countDetectedObject || 0;\n            },\n            wikiClass: 'ai_utilize_object',\n        },\n        is_detected_among_objects: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [{ ...params.getObjectList(), fontSize: 10 }],\n            events: {},\n            def: {\n                type: 'is_detected_among_objects',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n            },\n            class: 'object',\n            isNotFor: ['objectDetector'],\n            func(sprite, script) {\n                const target = script.getField('TARGET');\n                const objectDetectorResult = mediaPipeUtils.prevObjectDetectorResult;\n                const detections = _get(objectDetectorResult, 'detections');\n                if (detections) {\n                    const isFound = detections.some((detect) =>\n                        detect.categories.some((category) => category.categoryName === target)\n                    );\n                    return isFound;\n                }\n                return false;\n            },\n            wikiClass: 'ai_utilize_object',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_pose_landmarker.js",
    "content": "import MediaPipeUtils from '../../util/mediaPipeUtils';\n\nconst mediaPipeUtils = MediaPipeUtils.getInstance();\nEntry.AI_UTILIZE_BLOCK.poseLandmarker = {\n    name: 'poseLandmarker',\n    imageName: 'poseLandmarker.svg',\n    category: 'video',\n    title: {\n        ko: '사람 인식',\n        en: 'Human Detection',\n    },\n    titleKey: 'Workspace.pose_landmarker_title_text',\n    description: Lang.Msgs.ai_utilize_pose_landmarker_description,\n    descriptionKey: 'Msgs.ai_utilize_pose_landmarker_description',\n    isInitialized: false,\n    async init() {\n        await mediaPipeUtils.initialize();\n        Entry.AI_UTILIZE_BLOCK.poseLandmarker.isInitialized = true;\n    },\n    destroy() {\n        mediaPipeUtils.destroy();\n        Entry.AI_UTILIZE_BLOCK.poseLandmarker.isInitialized = false;\n    },\n};\n\nEntry.AI_UTILIZE_BLOCK.poseLandmarker.getBlocks = function() {\n    const params = {\n        getEventIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/start_icon_pose.svg',\n                size: 14,\n                position: {\n                    x: 0,\n                    y: -2,\n                },\n            };\n        },\n        getCommonIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/ai_pose_icon.svg',\n                size: 11,\n            };\n        },\n        getPoseNumber() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['1', 0],\n                    ['2', 1],\n                    ['3', 2],\n                    ['4', 3],\n                ],\n                value: 0,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getPosePoint() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.pose_list.nose, 0],\n                    [Lang.pose_list.left_eye_inner, 1],\n                    [Lang.pose_list.left_eye, 2],\n                    [Lang.pose_list.left_eye_outer, 3],\n                    [Lang.pose_list.right_eye_inner, 4],\n                    [Lang.pose_list.right_eye, 5],\n                    [Lang.pose_list.right_eye_outer, 6],\n                    [Lang.pose_list.left_ear, 7],\n                    [Lang.pose_list.right_ear, 8],\n                    [Lang.pose_list.mouth_left, 9],\n                    [Lang.pose_list.mouth_right, 10],\n                    [Lang.pose_list.left_shoulder, 11],\n                    [Lang.pose_list.right_shoulder, 12],\n                    [Lang.pose_list.left_elbow, 13],\n                    [Lang.pose_list.right_elbow, 14],\n                    [Lang.pose_list.left_wrist, 15],\n                    [Lang.pose_list.right_wrist, 16],\n                    [Lang.pose_list.left_pinky, 17],\n                    [Lang.pose_list.right_pinky, 18],\n                    [Lang.pose_list.left_index, 19],\n                    [Lang.pose_list.right_index, 20],\n                    [Lang.pose_list.left_thumb, 21],\n                    [Lang.pose_list.right_thumb, 22],\n                    [Lang.pose_list.left_hip, 23],\n                    [Lang.pose_list.right_hip, 24],\n                    [Lang.pose_list.left_knee, 25],\n                    [Lang.pose_list.right_knee, 26],\n                    [Lang.pose_list.left_ankle, 27],\n                    [Lang.pose_list.right_ankle, 28],\n                    [Lang.pose_list.left_heel, 29],\n                    [Lang.pose_list.right_heel, 30],\n                    [Lang.pose_list.left_foot_index, 31],\n                    [Lang.pose_list.right_foot_index, 32],\n                ],\n                value: 0,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                dropdownSync: 'posePoint',\n            };\n        },\n        getAxis() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['x', 'x'],\n                    ['y', 'y'],\n                ],\n                value: 'x',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getStartStop() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_start, 'start'],\n                    [Lang.Blocks.video_end, 'stop'],\n                ],\n                value: 'start',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getShowHide() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_show_video, 'show'],\n                    [Lang.Blocks.video_hide_video, 'hide'],\n                ],\n                value: 'show',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n    };\n    return {\n        pose_landmarker_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.pose_landmarker_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'pose_landmarker_title',\n            },\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            events: {},\n        },\n        when_pose_landmarker: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_event',\n            statements: [],\n            params: [params.getEventIndicator()],\n            events: {},\n            def: {\n                params: [null],\n                type: 'when_pose_landmarker',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            event: 'when_pose_landmarker',\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            func(sprite, script) {\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_pose',\n        },\n        pose_landmarker: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getStartStop(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'pose_landmarker',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!mediaPipeUtils.isInitialized) {\n                    await mediaPipeUtils.initialize();\n                }\n                if (value === 'start') {\n                    await mediaPipeUtils.startPoseLandmarker(value);\n                } else {\n                    await mediaPipeUtils.stopPoseLandmarker(value);\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_pose',\n        },\n        draw_detected_pose: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getShowHide(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'draw_detected_pose',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!mediaPipeUtils.isInitialized) {\n                    await mediaPipeUtils.initialize();\n                }\n                if (value === 'show') {\n                    mediaPipeUtils.changeDrawDetectedPoseLandmarker(true);\n                } else {\n                    mediaPipeUtils.changeDrawDetectedPoseLandmarker(false);\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_pose',\n        },\n        check_detected_pose: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'check_detected_pose',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            func(sprite, script) {\n                return mediaPipeUtils.isPrevPoseLandmarker;\n            },\n            wikiClass: 'ai_utilize_pose',\n        },\n        count_detected_pose: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'count_detected_pose',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            func(sprite, script) {\n                return mediaPipeUtils.countDetectedPose || 0;\n            },\n            wikiClass: 'ai_utilize_pose',\n        },\n        locate_to_pose: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getPoseNumber(), params.getPosePoint(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'locate_to_pose',\n            },\n            paramsKeyMap: {\n                POSE: 0,\n                POSE_POINT: 1,\n            },\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            func(sprite, script) {\n                const pose = script.getField('POSE');\n                const point = script.getField('POSE_POINT');\n                const axis = mediaPipeUtils.getPosePointAxis(pose, point);\n                if (axis) {\n                    sprite.setX(axis.x);\n                    sprite.setY(axis.y);\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(axis.x, axis.y * -1);\n                    }\n                }\n                return script.callReturn();\n            },\n            wikiClass: 'ai_utilize_pose',\n        },\n        locate_time_to_pose: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getPoseNumber(),\n                params.getPosePoint(),\n                params.getCommonIndicator(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'locate_time_to_pose',\n            },\n            paramsKeyMap: {\n                TIME: 0,\n                POSE: 1,\n                POSE_POINT: 2,\n            },\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const time = script.getNumberValue('TIME', script);\n                    const frameCount = Math.floor(time * Entry.FPS);\n                    const pose = script.getField('POSE', script);\n                    const point = script.getField('POSE_POINT', script);\n\n                    if (frameCount != 0) {\n                        const axis = mediaPipeUtils.getPosePointAxis(pose, point);\n                        if (axis) {\n                            script.isStart = true;\n                            script.frameCount = frameCount;\n                            script.dX = (axis.x - sprite.getX()) / script.frameCount;\n                            script.dY = (axis.y - sprite.getY()) / script.frameCount;\n                        }\n                    } else {\n                        const axis = mediaPipeUtils.getPosePointAxis(pose, point);\n                        if (axis) {\n                            sprite.setX(axis.x);\n                            sprite.setY(axis.y);\n                            if (sprite.brush && !sprite.brush.stop) {\n                                sprite.brush.lineTo(axis.x, axis.y * -1);\n                            }\n                        }\n                        return script.callReturn();\n                    }\n                }\n                if (script.frameCount != 0) {\n                    sprite.setX(sprite.getX() + script.dX);\n                    sprite.setY(sprite.getY() + script.dY);\n                    script.frameCount--;\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.frameCount;\n                    return script.callReturn();\n                }\n            },\n            wikiClass: 'ai_utilize_pose',\n        },\n        axis_detected_pose: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { ...params.getPoseNumber(), fontSize: 10 },\n                { ...params.getPosePoint(), fontSize: 10 },\n                { ...params.getAxis(), fontSize: 10 },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'axis_detected_pose',\n            },\n            paramsKeyMap: {\n                POSE: 0,\n                POSE_POINT: 1,\n                AXIS: 2,\n            },\n            class: 'pose',\n            isNotFor: ['poseLandmarker'],\n            func(sprite, script) {\n                const pose = script.getField('POSE', script);\n                const point = script.getField('POSE_POINT', script);\n                const axisName = script.getField('AXIS', script);\n                const axis = mediaPipeUtils.getPosePointAxis(pose, point);\n                if (axis) {\n                    return axis[axisName] || 0;\n                }\n                return 0;\n            },\n            wikiClass: 'ai_utilize_pose',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_translate.js",
    "content": "'use strict';\n\nconst PromiseManager = require('../../core/promiseManager');\nconst { callApi } = require('../../util/common');\n\n/**\n * 비공식으로 엔트리에서 사용되고 있는 언어코드 (vn, ja)의 경우 공식 언어코드로 치환한다.\n * @param {string}originalLanguage\n */\nfunction replaceLanguageCode(originalLanguage) {\n    switch (originalLanguage) {\n        case 'jp':\n            return 'ja';\n        case 'vn':\n            return 'vi';\n        default:\n            return originalLanguage;\n    }\n}\n\nfunction getInitialCodeMap() {\n    return {\n        auto: {\n            lang: Lang.Blocks.auto,\n            sub: [\n                'en',\n                'ja',\n                'zh-CN',\n                'zh-TW',\n                'es',\n                'fr',\n                'de',\n                'ru',\n                'pt',\n                'th',\n                'vi',\n                'id',\n                'hi',\n                'ko',\n            ],\n        },\n        ko: {\n            lang: Lang.Blocks.korean,\n            sub: ['en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id'],\n        },\n        en: {\n            lang: Lang.Blocks.english,\n            sub: [\n                'ko',\n                'ja',\n                'zh-CN',\n                'zh-TW',\n                'es',\n                'fr',\n                'de',\n                'ru',\n                'pt',\n                'th',\n                'vi',\n                'id',\n                'hi',\n            ],\n        },\n        ja: {\n            lang: Lang.Blocks.japan,\n            sub: [\n                'ko',\n                'en',\n                'zh-CN',\n                'zh-TW',\n                'es',\n                'fr',\n                'de',\n                'ru',\n                'pt',\n                'th',\n                'vi',\n                'id',\n                'hi',\n            ],\n        },\n        'zh-CN': {\n            lang: Lang.Blocks.chinese_simplified,\n            sub: ['ko', 'en', 'ja', 'zh-TW', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id', 'hi'],\n        },\n        'zh-TW': {\n            lang: Lang.Blocks.chinese_traditional,\n            sub: ['ko', 'en', 'ja', 'zh-CN', 'es', 'fr', 'de', 'ru', 'pt', 'th', 'vi', 'id', 'hi'],\n        },\n        es: {\n            lang: Lang.Blocks.spanish,\n            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'fr', 'de', 'ru', 'th', 'vi', 'id'],\n        },\n        fr: {\n            lang: Lang.Blocks.french,\n            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'de', 'ru', 'th', 'vi', 'id'],\n        },\n        de: {\n            lang: Lang.Blocks.german,\n            sub: [\n                'ko',\n                'en',\n                'ja',\n                'zh-CN',\n                'zh-TW',\n                'es',\n                'fr',\n                'ru',\n                'pt',\n                'th',\n                'vi',\n                'id',\n                'hi',\n            ],\n        },\n        ru: {\n            lang: Lang.Blocks.russian,\n            sub: [\n                'ko',\n                'en',\n                'ja',\n                'zh-CN',\n                'zh-TW',\n                'es',\n                'fr',\n                'de',\n                'pt',\n                'th',\n                'vi',\n                'id',\n                'hi',\n            ],\n        },\n        pt: {\n            lang: Lang.Blocks.portuguese,\n            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'de', 'ru', 'hi'],\n        },\n        th: {\n            lang: Lang.Blocks.thai,\n            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'vi'],\n        },\n        vi: {\n            lang: Lang.Blocks.vietnamese,\n            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'th', 'id'],\n        },\n        id: {\n            lang: Lang.Blocks.indonesian,\n            sub: ['ko', 'en', 'zh-CN', 'zh-TW', 'es', 'fr', 'de', 'ru', 'th', 'vi'],\n        },\n        hi: {\n            lang: Lang.Blocks.hindi,\n            sub: ['ko', 'en', 'ja', 'zh-CN', 'zh-TW', 'de', 'ru', 'pt'],\n        },\n    };\n}\n\nEntry.AI_UTILIZE_BLOCK.translate = {\n    name: 'translate',\n    imageName: 'papago.svg',\n    category: 'general',\n    sponsorText: 'Powered by {image}',\n    sponsorImage: 'naver.png',\n    sponsorOnImage: 'naverOn.png',\n    title: {\n        ko: '번역',\n        en: 'translate',\n        jp: '翻訳',\n    },\n    titleKey: 'template.translate_title_text',\n    description: Lang.Msgs.expansion_translate_description,\n    descriptionKey: 'Msgs.expansion_translate_description',\n    isInitialized: false,\n    init() {\n        if (this.isInitialized) {\n            return;\n        }\n        Entry.AI_UTILIZE_BLOCK.translate.delayKey = Entry.projectId;\n        Entry.AI_UTILIZE_BLOCK.translate.isInitialized = true;\n    },\n    api: '/api/expansionBlock/papago/',\n    sponsor: 'papagoNaver',\n    sponsorLink: 'https://www.ncloud.com/product/aiService/papagoNmt',\n    typeMap: {\n        dictionary: 'nsmt',\n        artificial_intelligence: 'n2mt',\n    },\n    apiType: 'n2mt',\n};\n\nEntry.AI_UTILIZE_BLOCK.translate.getBlocks = function () {\n    const params = {\n        getType(isPython) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.dictionary, 'dictionary'],\n                    [Lang.Blocks.artificial_intelligence, 'artificial_intelligence'],\n                ],\n                value: 'dictionary',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getSourceLang(isPython) {\n            const value = replaceLanguageCode(Lang.type);\n            const options = [\n                [Lang.Blocks.korean, 'ko'],\n                [Lang.Blocks.english, 'en'],\n                [Lang.Blocks.japan, 'ja'],\n                [Lang.Blocks.chinese_simplified, 'zh-CN'],\n                [Lang.Blocks.chinese_traditional, 'zh-TW'],\n                [Lang.Blocks.spanish, 'es'],\n                [Lang.Blocks.french, 'fr'],\n                [Lang.Blocks.german, 'de'],\n                [Lang.Blocks.russian, 'ru'],\n                [Lang.Blocks.portuguese, 'pt'],\n                [Lang.Blocks.thai, 'th'],\n                [Lang.Blocks.vietnamese, 'vi'],\n                [Lang.Blocks.indonesian, 'id'],\n                [Lang.Blocks.hindi, 'hi'],\n            ];\n            const index = _.findIndex(options, (x) => x[1] === value);\n            if (index > 0) {\n                const temp = options[index];\n                options[index] = options[0];\n                options[0] = temp;\n            }\n            const param = {\n                type: 'Dropdown',\n                options,\n                value,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                dropdownSync: 'translate',\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getTargetLang(isPython = false) {\n            const param = {\n                type: 'DropdownDynamic',\n                value: null,\n                menuName() {\n                    const value = this.getTargetValue('translate');\n                    if (!value) {\n                        return [[Lang.Blocks.no_target, 'null']];\n                    }\n                    const langCodeMap = getInitialCodeMap();\n                    const convertedLangCode = replaceLanguageCode(value);\n                    return langCodeMap[convertedLangCode].sub.map((code) => [\n                        langCodeMap[code].lang,\n                        code,\n                    ]);\n                },\n                needDeepCopy: true,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                defaultValue: (value, options) => {\n                    if (options.length) {\n                        return options[0][1];\n                    }\n                    return null;\n                },\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n    };\n    const getProjectId = function () {\n        if (Entry.projectId) {\n            Entry.AI_UTILIZE_BLOCK.translate.delayKey = Entry.projectId;\n        }\n\n        if (Entry.AI_UTILIZE_BLOCK.translate.delayKey) {\n            return Entry.AI_UTILIZE_BLOCK.translate.delayKey;\n        }\n\n        Entry.AI_UTILIZE_BLOCK.translate.delayKey = _.uniqueId(Entry.generateHash());\n        return Entry.AI_UTILIZE_BLOCK.translate.delayKey;\n    };\n\n    const translate = (params, type, defaultValue) => {\n        params.projectId = getProjectId();\n        const key = `translate-${type}${JSON.stringify(params)}`;\n        return new PromiseManager()\n            .Promise(async (resolve) => {\n                callApi(\n                    key,\n                    {\n                        url: `${Entry.AI_UTILIZE_BLOCK.translate.api}translate/${type}`,\n                        params,\n                    },\n                    window.isOffline ? await window.getPapagoHeaderInfo() : {}\n                )\n                    .then((result) => {\n                        if (result.data) {\n                            return resolve(result.data.translatedText);\n                        }\n                        return resolve(defaultValue);\n                    })\n                    .catch(() => resolve(defaultValue));\n            })\n            .catch(() => defaultValue);\n    };\n\n    const checkLang = (query, defaultValue) => {\n        const langCodeMap = getInitialCodeMap();\n        return new PromiseManager()\n            .Promise((resolve) => {\n                callApi(\n                    `translate-detect-${query}`,\n                    {\n                        url: `${Entry.AI_UTILIZE_BLOCK.translate.api}dect/langs`,\n                        params: { query, projectId: getProjectId() },\n                    },\n                    window.isOffline ? window.getPapagoHeaderInfo() : {}\n                )\n                    .then((result) => {\n                        if (\n                            result.data &&\n                            result.data.langCode &&\n                            langCodeMap[result.data.langCode]\n                        ) {\n                            return resolve(langCodeMap[result.data.langCode].lang);\n                        }\n                        return resolve(defaultValue);\n                    })\n                    .catch(() => resolve(defaultValue));\n            })\n            .catch(() => defaultValue);\n    };\n\n    const checkText = function (text) {\n        const result = {\n            result: false,\n            message: Lang.Blocks.unknown_sentence,\n        };\n\n        if (!text) {\n            result.message = Lang.Blocks.no_sentence;\n            return result;\n        }\n\n        if (text.length > 3000) {\n            result.message = Lang.Blocks.sentence_over_3000_charactor;\n            return result;\n        }\n\n        return {\n            result: true,\n            message: text,\n        };\n    };\n    return {\n        translate_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.translate_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'translate_title',\n            },\n            class: 'translate',\n            isNotFor: ['translate'],\n            events: {},\n        },\n        get_translated_string: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                params.getSourceLang(),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                params.getTargetLang(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    params.getSourceLang().value,\n                    {\n                        type: 'text',\n                        params: [Lang.Blocks.entry],\n                    },\n                    null,\n                ],\n                type: 'get_translated_string',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_translated_string',\n            },\n            paramsKeyMap: {\n                SOURCE: 0,\n                TEXT: 1,\n                TARGET: 2,\n            },\n            class: 'translate',\n            isNotFor: ['translate'],\n            func(sprite, script) {\n                const textObj = checkText(script.getStringValue('TEXT', script));\n                if (!textObj.result) {\n                    return textObj.message;\n                }\n\n                const type = Entry.AI_UTILIZE_BLOCK.translate.apiType;\n                const params = {\n                    text: textObj.message,\n                    target: script.getField('TARGET', script),\n                    source: script.getField('SOURCE', script),\n                };\n\n                if (params.target == params.source) {\n                    return params.text;\n                }\n\n                return translate(params, type, Lang.Blocks.unknown_sentence);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Translate.do(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            params.getSourceLang(true),\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            params.getTargetLang(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'ai_utilize_translate',\n        },\n        check_language: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: [Lang.Blocks.entry],\n                    },\n                ],\n                type: 'check_language',\n            },\n            pyHelpDef: {\n                params: ['A&value'],\n                type: 'check_language',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                LANG: 1,\n            },\n            class: 'translate',\n            isNotFor: ['translate'],\n            func(sprite, script) {\n                const text = script.getStringValue('TEXT', script);\n                const textObj = checkText(text);\n                if (!textObj.result) {\n                    return textObj.message;\n                }\n\n                return checkLang(textObj.message, Lang.Blocks.unknown_sentence);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Translate.getLang(%1)',\n                        params: [null],\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'ai_utilize_translate',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_tts.js",
    "content": "'use strict';\n\nconst { toQueryString } = require('../../util/common');\nconst _trim = require('lodash/trim');\n\nEntry.AI_UTILIZE_BLOCK.tts = {\n    name: 'tts',\n    imageName: 'tts.svg',\n    category: 'general',\n    sponsorText: 'Powered by {image}',\n    sponsorImage: 'naverClova.png',\n    sponsorOnImage: 'naverClovaOn.png',\n    title: {\n        ko: '읽어주기',\n        en: 'read',\n        jp: 'を読み上げる',\n    },\n    titleKey: 'template.tts_title_text',\n    description: Lang.Msgs.ai_utilize_tts_description,\n    descriptionKey: 'Msgs.ai_utilize_tts_description',\n    isInitialized: true,\n    init() {},\n    api: '/api/expansionBlock/tts/read',\n    sponsor: 'clovaNaver',\n    sponsorLink: 'https://www.ncloud.com/product/aiService/css',\n    loadQueue: [],\n};\n\nEntry.AI_UTILIZE_BLOCK.tts.getBlocks = function() {\n    const params = {\n        getSpeaker(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.tts_female, 'kyuri'],\n                    [Lang.Blocks.tts_male, 'jinho'],\n                    [Lang.Blocks.tts_kind, 'hana'],\n                    [Lang.Blocks.tts_sweet, 'dinna'],\n                    [Lang.Blocks.tts_echo, 'brown'],\n                    [Lang.Blocks.tts_mischievous, 'minions'],\n                    [Lang.Blocks.tts_dainty, 'sally'],\n                    [Lang.Blocks.tts_sabina, 'nsabina'],\n                    [Lang.Blocks.tts_mammon, 'nmammon'],\n                    [Lang.Blocks.tts_kitty, 'nmeow'],\n                    [Lang.Blocks.tts_doggy, 'nwoof'],\n                ],\n                value: 'kyuri',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getSpeed(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.tts_veryslow, '5'],\n                    [Lang.Blocks.tts_slow, '3'],\n                    [Lang.Blocks.tts_normal, '0'],\n                    [Lang.Blocks.tts_fast, '-3'],\n                    [Lang.Blocks.tts_veryfast, '-5'],\n                ],\n                value: '0',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getPitch(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.tts_verylow, '5'],\n                    [Lang.Blocks.tts_low, '3'],\n                    [Lang.Blocks.tts_normal, '0'],\n                    [Lang.Blocks.tts_high, '-3'],\n                    [Lang.Blocks.tts_veryhigh, '-5'],\n                ],\n                value: '0',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n    };\n\n    const hashCode = (s) =>\n        s.split('').reduce(function(a, b) {\n            a = (a << 5) - a + b.charCodeAt(0);\n            return a & a;\n        }, 0);\n\n    const checkText = function(text) {\n        const result = {\n            result: false,\n            message: Lang.Blocks.unknown_sentence,\n        };\n\n        if (!text) {\n            result.message = Lang.Blocks.no_sentence;\n            return result;\n        }\n\n        if (text.length > 2500) {\n            result.message = Lang.Blocks.sentence_over_2500_charactor;\n            return result;\n        }\n\n        return {\n            result: true,\n            message: _trim(text),\n            hash: hashCode(text + new Date().getTime()),\n        };\n    };\n\n    /**\n     * wodnjs6512: 로드를 새로 할때는 queue를 다시 만든다고 하네요\n     * 기존 코드에서 하나의 로더로 로드를 2개를 콜하면 하나는 정상 로드가 되지 않는 이슈가 있다고 합니다\n     * 한번에 로드가 가능하도록 매번 로더를 따로 만들어서 사용하도록 수정\n     * https://github.com/CreateJS/PreloadJS/issues/232#issuecomment-338739115\n     *  */\n    const read = function(args) {\n        return new Promise((resolve) => {\n            const { message, hash, prop } = args;\n            const tts = Entry.AI_UTILIZE_BLOCK.tts;\n            const id = `tts-${hash}-${JSON.stringify(prop)}`;\n            const type = createjs.LoadQueue.SOUND;\n\n            const soundQueue = new createjs.LoadQueue(true);\n            soundQueue.installPlugin(createjs.Sound);\n            soundQueue.maintainScriptOrder = true;\n            const src = `${Entry.baseUrl}${Entry.AI_UTILIZE_BLOCK.tts.api}.mp3?${toQueryString({\n                text: message,\n                ...prop,\n            })}`;\n            const loadHandler = ({ currentTarget }) => {\n                const items = currentTarget.getItems().map(({ item }) => item);\n                tts.loadQueue = tts.loadQueue.filter((id) => {\n                    const filtered = items.find((item) => item.id === id);\n                    if (filtered) {\n                        const instance = Entry.Utils.playSound(id, filtered.prop);\n                        instance.soundType = 'tts';\n                        Entry.Utils.addSoundInstances(instance);\n                        const duration =\n                            instance.duration > 0 ? instance.duration : filtered.duration * 300;\n                        setTimeout(() => {\n                            resolve();\n                        }, duration);\n                    }\n                    return true;\n                });\n            };\n            // 읽어주기 오류 발생 시, 다음 블록 실행\n            const errorHandler = async () => {\n                soundQueue.removeEventListener('complete', loadHandler);\n                soundQueue.removeEventListener('error', errorHandler);\n                soundQueue.destroy();\n                resolve();\n            };\n            soundQueue.on('complete', loadHandler);\n            soundQueue.on('error', errorHandler);\n            soundQueue.loadFile({ id, src, type, prop, duration: message.length });\n            tts.loadQueue.push(id);\n        });\n    };\n\n    return {\n        tts_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.tts_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'tts_title',\n            },\n            class: 'tts',\n            isNotFor: ['tts'],\n            events: {},\n        },\n        read_text: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/ai_utilize_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: [Lang.Blocks.entry],\n                    },\n                    null,\n                ],\n                type: 'read_text',\n            },\n            pyHelpDef: {\n                params: ['A&value'],\n                type: 'read_text',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n            },\n            class: 'tts',\n            isNotFor: ['tts'],\n            func(sprite, script) {\n                const { result, message, hash } = checkText(script.getStringValue('TEXT', script));\n                if (result) {\n                    const prop = sprite.getVoiceProp();\n                    read({\n                        message,\n                        hash,\n                        prop,\n                    });\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'TTS.read(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'ai_utilize_tts',\n        },\n        read_text_wait_with_block: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/ai_utilize_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: [Lang.Blocks.entry],\n                    },\n                    null,\n                ],\n                type: 'read_text_wait_with_block',\n            },\n            pyHelpDef: {\n                params: ['A&value'],\n                type: 'read_text_wait_with_block',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n            },\n            class: 'tts',\n            isNotFor: ['tts'],\n            async func(sprite, script) {\n                const { result, message, hash } = checkText(script.getStringValue('TEXT', script));\n                const prop = sprite.getVoiceProp();\n                if (result) {\n                    await read({\n                        message,\n                        hash,\n                        prop,\n                    });\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        passTest: true,\n                        syntax: 'TTS.read_and_wait(%1)',\n                    },\n                ],\n            },\n            wikiClass: 'ai_utilize_tts',\n        },\n        set_tts_property: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                params.getSpeaker(),\n                params.getSpeed(),\n                params.getPitch(),\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/ai_utilize_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    params.getSpeaker().value,\n                    params.getSpeed().value,\n                    params.getPitch().value,\n                    null,\n                ],\n                type: 'set_tts_property',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'set_tts_property',\n            },\n            paramsKeyMap: {\n                SPEAKER: 0,\n                SPEED: 1,\n                PITCH: 2,\n            },\n            class: 'tts',\n            isNotFor: ['tts'],\n            func(sprite, script) {\n                const speaker = script.getField('SPEAKER', script);\n                const speed = script.getField('SPEED', script);\n                const pitch = script.getField('PITCH', script);\n                const volume = 1;\n                sprite.setVoiceProp({ speaker, speed, pitch, volume });\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'TTS.set(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            params.getSpeaker(true),\n                            params.getSpeed(true),\n                            params.getPitch(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'ai_utilize_tts',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_ai_utilize_video.js",
    "content": "import VideoUtils from '@entrylabs/legacy-video';\nimport clamp from 'lodash/clamp';\nimport { GEHelper } from '../../graphicEngine/GEHelper';\n\nEntry.VideoUtils = VideoUtils;\nEntry.AI_UTILIZE_BLOCK.video = {\n    name: 'video',\n    imageName: 'video.svg',\n    category: 'video',\n    title: {\n        ko: '비디오 감지',\n        en: 'Video Detection',\n        jp: 'ビデオ検出',\n    },\n    titleKey: 'template.video_title_text',\n    description: Lang.Msgs.ai_utilize_video_description,\n    descriptionKey: 'Msgs.ai_utilize_video_description',\n    isInitialized: false,\n    async init() {\n        await VideoUtils.initialize(GEHelper);\n        Entry.AI_UTILIZE_BLOCK.video.isInitialized = true;\n    },\n    destroy() {\n        VideoUtils.destroy();\n        Entry.AI_UTILIZE_BLOCK.video.isInitialized = false;\n    },\n};\n\nEntry.AI_UTILIZE_BLOCK.video.getBlocks = function() {\n    const params = {\n        getCommonIndicator() {\n            return {\n                type: 'Indicator',\n                img: 'block_icon/ai_utilize_icon.svg',\n                size: 11,\n            };\n        },\n        getCameraOrder() {\n            return {\n                type: 'DropdownDynamic',\n                menuName: 'connectedCameras',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getNumbers() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['1', 0],\n                    ['2', 1],\n                    ['3', 2],\n                    ['4', 3],\n                ],\n                value: 0,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getOnOff() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_show_video, 'on'],\n                    [Lang.Blocks.video_hide_video, 'off'],\n                ],\n                value: 'on',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getVideoFlipOptions() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_left_right, 'hflip'],\n                    [Lang.Blocks.video_top_bottom, 'vflip'],\n                ],\n                value: 'hflip',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getAiModelOptions() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_human, 'pose'],\n                    [Lang.Blocks.video_face, 'face'],\n                    [Lang.Blocks.video_object, 'object'],\n                ],\n                value: 'pose',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getSwitchOptions() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_start, 'on'],\n                    [Lang.Blocks.video_end, 'off'],\n                ],\n                value: 'on',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getFaceInfoOptions() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.video_gender, 'gender'],\n                    [Lang.Blocks.video_age, 'age'],\n                    [Lang.Blocks.video_emotion, 'emotion'],\n                ],\n                value: 'gender',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getFaceCoords() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.video_body_coord_params.left_eye, 45],\n                    [Lang.video_body_coord_params.right_eye, 36],\n                    [Lang.video_body_coord_params.nose, 30],\n                    [Lang.video_body_coord_params.left_mouth, 54],\n                    [Lang.video_body_coord_params.right_mouth, 48],\n                    [Lang.video_body_coord_params.upper_lip, 62],\n                    [Lang.video_body_coord_params.lower_lip, 66],\n                ],\n                value: 45,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getBodyCoords() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    [Lang.video_body_coord_params.face, 0],\n                    [Lang.video_body_coord_params.neck, 21],\n                    [Lang.video_body_coord_params.left_eye, 1],\n                    [Lang.video_body_coord_params.right_eye, 2],\n                    [Lang.video_body_coord_params.left_ear, 3],\n                    [Lang.video_body_coord_params.right_ear, 4],\n                    [Lang.video_body_coord_params.left_shoulder, 5],\n                    [Lang.video_body_coord_params.right_shoulder, 6],\n                    [Lang.video_body_coord_params.left_elbow, 7],\n                    [Lang.video_body_coord_params.right_elbow, 8],\n                    [Lang.video_body_coord_params.left_wrist, 9],\n                    [Lang.video_body_coord_params.right_wrist, 10],\n                    [Lang.video_body_coord_params.left_hip, 11],\n                    [Lang.video_body_coord_params.right_hip, 12],\n                    [Lang.video_body_coord_params.left_knee, 13],\n                    [Lang.video_body_coord_params.right_knee, 14],\n                    [Lang.video_body_coord_params.left_ankle, 15],\n                    [Lang.video_body_coord_params.right_ankle, 16],\n                ],\n                value: 0,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getCoordXYOptions() {\n            return {\n                type: 'Dropdown',\n                options: [\n                    ['x', 'x'],\n                    ['y', 'y'],\n                ],\n                value: 'x',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n        getObjectList() {\n            return {\n                type: 'DropdownExtra',\n                options: [\n                    [Lang.video_object_params.person, 'person'],\n                    [Lang.video_object_params.bicycle, 'bicycle'],\n                    [Lang.video_object_params.car, 'car'],\n                    [Lang.video_object_params.motorcycle, 'motorcycle'],\n                    [Lang.video_object_params.airplane, 'airplane'],\n                    [Lang.video_object_params.bus, 'bus'],\n                    [Lang.video_object_params.train, 'train'],\n                    [Lang.video_object_params.truck, 'truck'],\n                    [Lang.video_object_params.boat, 'boat'],\n                    [Lang.video_object_params['traffic light'], 'traffic light'],\n                    [Lang.video_object_params['fire hydrant'], 'fire hydrant'],\n                    [Lang.video_object_params['stop sign'], 'stop sign'],\n                    [Lang.video_object_params['parking meter'], 'parking meter'],\n                    [Lang.video_object_params.bench, 'bench'],\n                    [Lang.video_object_params.bird, 'bird'],\n                    [Lang.video_object_params.cat, 'cat'],\n                    [Lang.video_object_params.dog, 'dog'],\n                    [Lang.video_object_params.horse, 'horse'],\n                    [Lang.video_object_params.sheep, 'sheep'],\n                    [Lang.video_object_params.cow, 'cow'],\n                    [Lang.video_object_params.elephant, 'elephant'],\n                    [Lang.video_object_params.bear, 'bear'],\n                    [Lang.video_object_params.zebra, 'zebra'],\n                    [Lang.video_object_params.giraffe, 'giraffe'],\n                    [Lang.video_object_params.backpack, 'backpack'],\n                    [Lang.video_object_params.umbrella, 'umbrella'],\n                    [Lang.video_object_params.handbag, 'handbag'],\n                    [Lang.video_object_params.tie, 'tie'],\n                    [Lang.video_object_params.suitcase, 'suitcase'],\n                    [Lang.video_object_params.frisbee, 'frisbee'],\n                    [Lang.video_object_params.skis, 'skis'],\n                    [Lang.video_object_params.snowboard, 'snowboard'],\n                    [Lang.video_object_params['sports ball'], 'sports ball'],\n                    [Lang.video_object_params.kite, 'kite'],\n                    [Lang.video_object_params['baseball bat'], 'baseball bat'],\n                    [Lang.video_object_params['baseball glove'], 'baseball glove'],\n                    [Lang.video_object_params.skateboard, 'skateboard'],\n                    [Lang.video_object_params.surfboard, 'surfboard'],\n                    [Lang.video_object_params['tennis racket'], 'tennis racket'],\n                    [Lang.video_object_params.bottle, 'bottle'],\n                    [Lang.video_object_params['wine glass'], 'wine glass'],\n                    [Lang.video_object_params.cup, 'cup'],\n                    [Lang.video_object_params.fork, 'fork'],\n                    [Lang.video_object_params.knife, 'knife'],\n                    [Lang.video_object_params.spoon, 'spoon'],\n                    [Lang.video_object_params.bowl, 'bowl'],\n                    [Lang.video_object_params.banana, 'banana'],\n                    [Lang.video_object_params.apple, 'apple'],\n                    [Lang.video_object_params.sandwich, 'sandwich'],\n                    [Lang.video_object_params.orange, 'orange'],\n                    [Lang.video_object_params.broccoli, 'broccoli'],\n                    [Lang.video_object_params.carrot, 'carrot'],\n                    [Lang.video_object_params['hot dog'], 'hot dog'],\n                    [Lang.video_object_params.pizza, 'pizza'],\n                    [Lang.video_object_params.donut, 'donut'],\n                    [Lang.video_object_params.cake, 'cake'],\n                    [Lang.video_object_params.chair, 'chair'],\n                    [Lang.video_object_params.couch, 'couch'],\n                    [Lang.video_object_params['potted plant'], 'potted plant'],\n                    [Lang.video_object_params.bed, 'bed'],\n                    [Lang.video_object_params['dining table'], 'dining table'],\n                    [Lang.video_object_params.toilet, 'toilet'],\n                    [Lang.video_object_params.tv, 'tv'],\n                    [Lang.video_object_params.laptop, 'laptop'],\n                    [Lang.video_object_params.mouse, 'mouse'],\n                    [Lang.video_object_params.remote, 'remote'],\n                    [Lang.video_object_params.keyboard, 'keyboard'],\n                    [Lang.video_object_params['cell phone'], 'cell phone'],\n                    [Lang.video_object_params.microwave, 'microwave'],\n                    [Lang.video_object_params.oven, 'oven'],\n                    [Lang.video_object_params.toaster, 'toaster'],\n                    [Lang.video_object_params.sink, 'sink'],\n                    [Lang.video_object_params.refrigerator, 'refrigerator'],\n                    [Lang.video_object_params.book, 'book'],\n                    [Lang.video_object_params.clock, 'clock'],\n                    [Lang.video_object_params.vase, 'vase'],\n                    [Lang.video_object_params.scissors, 'scissors'],\n                    [Lang.video_object_params['teddy bear'], 'teddy bear'],\n                    [Lang.video_object_params['hair drier'], 'hair drier'],\n                    [Lang.video_object_params.toothbrush, 'toothbrush'],\n                ],\n                value: 'bicycle',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n        },\n    };\n    return {\n        video_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.video_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'video_title',\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            events: {},\n        },\n        video_change_cam: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getCameraOrder(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'video_change_cam',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const VALUE = script.getField('VALUE');\n                return await VideoUtils.changeSource(VALUE);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_check_webcam: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'video_check_webcam',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            func(sprite, script) {\n                return VideoUtils.videoInputList.length > 0;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_draw_webcam: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getOnOff(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'video_draw_webcam',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const value = script.getField('VALUE');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                VideoUtils.cameraSwitch(value);\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_set_camera_opacity_option: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '0',\n                },\n                params.getCommonIndicator(),\n            ],\n            events: {},\n            def: {\n                type: 'video_set_camera_opacity_option',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const value = clamp(script.getNumberValue('VALUE'), 0, 100);\n                try {\n                    if (!VideoUtils.isInitialized) {\n                        await VideoUtils.initialize(GEHelper);\n                    }\n                    VideoUtils.setOptions('transparency', value);\n\n                    return script.callReturn();\n                } catch (err) {\n                    console.log(err);\n                    throw err;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_flip_camera: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getVideoFlipOptions(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'video_flip_camera',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const target = script.getField('TARGET');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                VideoUtils.setOptions(target);\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_toggle_model: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                params.getAiModelOptions(),\n                params.getSwitchOptions(),\n                params.getCommonIndicator(),\n            ],\n            events: {},\n            def: {\n                type: 'video_toggle_model',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                MODE: 1,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const target = script.getField('TARGET');\n                const mode = script.getField('MODE');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                VideoUtils.manageModel(target, mode);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_toggle_ind: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic',\n            statements: [],\n            params: [params.getAiModelOptions(), params.getOnOff(), params.getCommonIndicator()],\n            events: {},\n            def: {\n                type: 'video_toggle_ind',\n            },\n            paramsKeyMap: {\n                CRITERIA: 0,\n                OPTION: 1,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const criteria = script.getField('CRITERIA');\n                const option = script.getField('OPTION');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                if (option === 'on') {\n                    VideoUtils.showIndicator(criteria);\n                } else {\n                    VideoUtils.removeIndicator(criteria);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_number_detect: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getAiModelOptions()],\n            events: {},\n            def: {\n                type: 'video_number_detect',\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const target = script.getField('TARGET');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                switch (target) {\n                    case 'face':\n                        return VideoUtils.faces.length || 0;\n                    case 'pose':\n                        return (VideoUtils.poses && VideoUtils.poses.predictions.length) || 0;\n                    case 'object':\n                        return VideoUtils.objects.length || 0;\n                }\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_object_detected: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [params.getObjectList()],\n            events: {},\n            def: {\n                type: 'video_object_detected',\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const target = script.getField('TARGET');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                let result = false;\n                VideoUtils.objects.forEach((detected) => {\n                    if (detected.class === target) {\n                        result = true;\n                    }\n                });\n\n                return result;\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        // 원래는 video_is_model_detected 로 나가야 하나, 해당 부분에 있어서 기존 하위 호환성때문에... 이름을 못바꿈...\n        video_is_model_loaded: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [params.getAiModelOptions()],\n            events: {},\n            def: {\n                type: 'video_is_model_loaded',\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const target = script.getField('TARGET');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                    return false;\n                }\n                switch (target) {\n                    case 'face':\n                        return VideoUtils.faces.length > 0;\n                    case 'pose':\n                        return VideoUtils.poses && VideoUtils.poses.predictions.length > 0;\n                    case 'object':\n                        return VideoUtils.objects.length > 0;\n                }\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_detected_face_info: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getNumbers(), params.getFaceInfoOptions()],\n            events: {},\n            def: {\n                type: 'video_detected_face_info',\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const index = script.getField('INDEX');\n                const info = script.getField('INFO');\n                const faces = VideoUtils.faces;\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                if (faces.length <= index) {\n                    return 0;\n                }\n\n                const target = VideoUtils.faces[index];\n                if (!target) {\n                    return 0;\n                }\n                switch (info) {\n                    case 'gender':\n                        return Lang.video_gender[target.gender];\n                    case 'age':\n                        return target.age.toFixed(0).toString();\n                    case 'emotion':\n                        let emotion = '';\n                        let maxVal = 0;\n                        for (const status in target.expressions) {\n                            const emotionVal = target.expressions[status];\n                            if (emotionVal > maxVal) {\n                                maxVal = emotionVal;\n                                emotion = status;\n                            }\n                        }\n                        return Lang.video_emotion_params[emotion];\n                }\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                INFO: 1,\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_motion_value: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.video_motion_onself, 'self'],\n                        [Lang.Blocks.video_motion_onscreen, 'screen'],\n                    ],\n                    value: 'self',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.video_motion_scale, 'total'],\n                        [Lang.Blocks.video_motion_direction_horizontal, 'x'],\n                        [Lang.Blocks.video_motion_direction_vertical, 'y'],\n                    ],\n                    value: 'total',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                type: 'video_motion_value',\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const target = script.getField('TARGET');\n                const type = script.getField('TYPE');\n                let detected = VideoUtils.totalMotions;\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                if (target === 'self') {\n                    detected = VideoUtils.motionDetect(sprite);\n                }\n                if (type === 'total') {\n                    return clamp(detected.total / 10, 0, 100000).toString();\n                }\n                try {\n                    let rawX = detected.direction.x;\n                    if (!VideoUtils.flipStatus.horizontal) {\n                        rawX *= -1;\n                    }\n\n                    let rawY = detected.direction.y;\n                    if (VideoUtils.flipStatus.vertical) {\n                        rawY *= -1;\n                    }\n                    const absX = Math.abs(rawX);\n                    const absY = Math.abs(rawY);\n                    if (absX < 20 && absY < 20) {\n                        return 0;\n                    }\n                    if (type === 'x') {\n                        return rawX.toFixed(1).toString();\n                    } else if (type === 'y') {\n                        return rawY.toFixed(1).toString();\n                    }\n                    return 0;\n                } catch (err) {\n                    console.log(detected);\n                }\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                TYPE: 1,\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_face_part_coord: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getNumbers(), params.getFaceCoords(), params.getCoordXYOptions()],\n            events: {},\n            def: {\n                type: 'video_face_part_coord',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PART: 1,\n                COORD: 2,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const index = script.getField('INDEX');\n                const part = script.getField('PART');\n                const coord = script.getField('COORD');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                if (!VideoUtils.faces) {\n                    return 0;\n                }\n                try {\n                    const faces = VideoUtils.faces;\n                    if (faces.length <= index) {\n                        return 0;\n                    }\n                    // offset since value shown starts from 1;\n                    const rawValue = faces[index].landmarks._positions[part][`_${coord}`];\n                    if (!rawValue) {\n                        return 0;\n                    }\n                    let returningValue = 0;\n                    if (coord === 'x') {\n                        returningValue = rawValue - VideoUtils.CANVAS_WIDTH / 2;\n                        if (VideoUtils.flipStatus.horizontal) {\n                            returningValue *= -1;\n                        }\n                    } else {\n                        returningValue = VideoUtils.CANVAS_HEIGHT / 2 - rawValue;\n                        if (VideoUtils.flipStatus.vertical) {\n                            returningValue *= -1;\n                        }\n                    }\n                    return returningValue.toFixed(1);\n                } catch (err) {\n                    return 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n        video_body_part_coord: {\n            color: EntryStatic.colorSet.block.default.AI_UTILIZE,\n            outerLine: EntryStatic.colorSet.block.darken.AI_UTILIZE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getNumbers(), params.getBodyCoords(), params.getCoordXYOptions()],\n            events: {},\n            def: {\n                type: 'video_body_part_coord',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PART: 1,\n                COORD: 2,\n            },\n            class: 'video',\n            isNotFor: ['video'],\n            async func(sprite, script) {\n                const index = script.getField('INDEX');\n                const part = script.getField('PART');\n                const coord = script.getField('COORD');\n                if (!VideoUtils.isInitialized) {\n                    await VideoUtils.initialize(GEHelper);\n                }\n                if (!VideoUtils.poses || !VideoUtils.poses.predictions) {\n                    return 0;\n                }\n                try {\n                    const poses = VideoUtils.poses.predictions;\n                    if (poses.length < index) {\n                        return 0;\n                    }\n                    // offset since value shown starts from 1;\n                    const rawValue = poses[index].keypoints[part].position[coord];\n                    if (!rawValue) {\n                        return 0;\n                    }\n                    let returningValue = 0;\n                    if (coord === 'x') {\n                        returningValue = rawValue - VideoUtils.CANVAS_WIDTH / 2;\n                    } else {\n                        returningValue = VideoUtils.CANVAS_HEIGHT / 2 - rawValue;\n                        if (VideoUtils.flipStatus.vertical) {\n                            returningValue *= -1;\n                        }\n                    }\n                    return returningValue.toFixed(1);\n                } catch (err) {\n                    return 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'ai_utilize_video',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_analysis.js",
    "content": "// import _chain from 'lodash/chain';\nimport _isNumber from 'lodash/isNumber';\nimport DataTable from '../../class/DataTable';\nimport { toNumber } from '../../util/common';\n\nmodule.exports = {\n    getBlocks() {\n        const getSubMenus = (value) => {\n            const { fields = [] } = DataTable.getSource(value) || {};\n            return fields.map((label, index) => [label, index + 1]);\n        };\n\n        const getColumnNumber = (str) => {\n            if (/\\d/.test(str)) {\n                return -1;\n            }\n            return (\n                // _chain(str)\n                // did not work..\n                _.chain(str)\n                    .toUpper()\n                    .reduce((prev, curr) => prev * 26 + curr.charCodeAt() - 64, 0)\n                    .value()\n            );\n        };\n\n        return {\n            analizyDataAddButton: {\n                skeleton: 'basic_button',\n                color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Workspace.open_analizy_data_import,\n                        color: EntryStatic.colorSet.common.BUTTON,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'analizyDataAddButton',\n                },\n                events: {\n                    mousedown: [\n                        function () {\n                            Entry.playground.dataTable.show();\n                        },\n                    ],\n                },\n                syntax: { js: [], py: [''] },\n            },\n            append_row_to_table: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.table_row, 'ROW'],\n                            [Lang.Blocks.table_col, 'COL'],\n                        ],\n                        value: 'ROW',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'append_row_to_table',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                    ],\n                    type: 'append_row_to_table',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    PROPERTY: 1,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                async func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const property = script.getStringValue('PROPERTY', script);\n                    const table = DataTable.getSource(tableId, sprite);\n                    if (property === 'ROW') {\n                        await table.appendRow();\n                    } else {\n                        await table.appendCol();\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            insert_row_to_table: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.table_row, 'ROW'],\n                            [Lang.Blocks.table_col, 'COL'],\n                        ],\n                        value: 'ROW',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['2'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'insert_row_to_table',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'insert_row_to_table',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    NUMBER: 1,\n                    PROPERTY: 2,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                async func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const number = script.getNumberValue('NUMBER', script);\n                    const property = script.getStringValue('PROPERTY', script);\n                    const table = DataTable.getSource(tableId, sprite);\n                    if (property === 'ROW') {\n                        await table.insertRow(number - 1);\n                    } else {\n                        await table.insertCol(number);\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            delete_row_from_table: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.table_row, 'ROW'],\n                            [Lang.Blocks.table_col, 'COL'],\n                        ],\n                        value: 'ROW',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['2'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'delete_row_from_table',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'delete_row_from_table',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    NUMBER: 1,\n                    PROPERTY: 2,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const number = script.getNumberValue('NUMBER', script);\n                    const property = script.getStringValue('PROPERTY', script);\n                    const table = DataTable.getSource(tableId, sprite);\n                    if (property === 'ROW') {\n                        table.deleteRow(number - 1);\n                    } else {\n                        table.deleteCol(number);\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            set_value_from_table: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['2'],\n                        },\n                        {\n                            type: 'get_table_fields',\n                        },\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'set_value_from_table',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['D&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'set_value_from_table',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    NUMBER: 1,\n                    FIELD: 2,\n                    VALUE: 3,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const row = script.getNumberValue('NUMBER', script) - 1;\n                    const col = DataTable.getColumnIndex(script.getValue('FIELD', script));\n\n                    const value = script.getValue('VALUE', script);\n                    const table = DataTable.getSource(tableId, sprite);\n                    if (table.isExist([row, col])) {\n                        table.replaceValue([row, col], value);\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            // 테이블 $1의 현재 상태를 저장하기\n            save_current_table: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'save_current_table',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['D&value'],\n                        },\n                        null,\n                    ],\n                    type: 'save_current_table',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const table = DataTable.getSource(tableId);\n                    DataTable.saveTable({ selected: table.dataTable });\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            // 테이블 %1 %2 개수\n            get_table_count: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.table_row, 'ROW'],\n                            [Lang.Blocks.table_col, 'COL'],\n                        ],\n                        value: 'ROW',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                ],\n                events: {},\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['D&value'],\n                        },\n                        null,\n                    ],\n                    type: 'get_table_count',\n                },\n                def: {\n                    params: [null, null],\n                    type: 'get_table_count',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    PROPERTY: 1,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const property = script.getStringValue('PROPERTY', script);\n                    const table = DataTable.getSource(tableId, sprite);\n                    if (property === 'ROW') {\n                        const { array } = table;\n                        return array.length + 1;\n                    } else if (property === 'COL') {\n                        const labels = table.fields;\n                        return labels.length;\n                    }\n                    return 0;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            // 테이블 %1 행 %2 속성 %3 의 값\n            get_value_from_table: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['2'],\n                        },\n                        {\n                            type: 'get_table_fields',\n                        },\n                    ],\n                    type: 'get_value_from_table',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    ROW: 1,\n                    COL: 2,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const row = script.getNumberValue('ROW', script) - 1;\n                    const col = DataTable.getColumnIndex(script.getValue('COL', script));\n                    const table = DataTable.getSource(tableId, sprite);\n\n                    if (table.isExist([row, col])) {\n                        return table.getValue([row, col]);\n                    }\n                    return null;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_value_from_last_row: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'get_table_fields',\n                        },\n                    ],\n                    type: 'get_value_from_last_row',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    COL: 1,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const col = DataTable.getColumnIndex(script.getValue('COL', script));\n                    const table = DataTable.getSource(tableId, sprite);\n                    const row = table && table.array.length;\n                    if (table.isExist([row, col])) {\n                        return table.getValue([row, col]);\n                    }\n                    return null;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            // 테이블 %1 속성 %1의 합\n            calc_values_from_table: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.table_sum, 'SUM'],\n                            [Lang.Blocks.table_max, 'MAX'],\n                            [Lang.Blocks.table_min, 'MIN'],\n                            [Lang.Blocks.table_avg, 'AVG'],\n                            [Lang.Blocks.table_stdev, 'STDEV'],\n                            [Lang.Blocks.table_median, 'MEDIAN'],\n                        ],\n                        value: 'SUM',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'get_table_fields',\n                        },\n                        null,\n                    ],\n                    type: 'calc_values_from_table',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    COL: 1,\n                    CALC: 2,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const calc = script.getField('CALC', script);\n                    const col = DataTable.getColumnIndex(script.getValue('COL', script));\n                    const table = DataTable.getSource(tableId, sprite);\n                    const array = table.array.map(({ value = [] }) => {\n                        const parsed = toNumber(value[col - 1]);\n                        return _isNumber(parsed) ? parsed : 0;\n                    });\n                    const total = array.length;\n                    const sum = (x, y) => x + y;\n                    const square = (x) => x * x;\n                    if (!total) {\n                        return 0;\n                    }\n                    switch (calc) {\n                        case 'SUM':\n                            return array.reduce(sum);\n                        case 'MAX':\n                            return array.reduce((x, y) => Math.max(x, y));\n                        case 'MIN':\n                            return array.reduce((x, y) => Math.min(x, y));\n                        case 'AVG':\n                            return array.reduce(sum) / total;\n                        case 'STDEV': {\n                            const avg = array.reduce(sum) / total;\n                            const deviations = array.map((x) => x - avg);\n                            return Math.sqrt(deviations.map(square).reduce(sum) / (total - 1));\n                        }\n                        case 'MEDIAN': {\n                            const sorted = array.sort((a, b) => a - b);\n                            const n = Math.floor(array.length / 2);\n                            return (sorted[n] + sorted[array.length - 1 - n]) / 2;\n                        }\n                        default:\n                            return 0;\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            // 테이블 %1 창 열기\n            open_table: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'open_table',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value', 'B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'open_table',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    CHART_INDEX: 1,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    DataTable.showTable(tableId);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            // 테이블 %1 창을 %2 초 동안 열기\n            open_table_wait: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['4'],\n                        },\n                        null,\n                    ],\n                    type: 'open_table_wait',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value', 'B&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'open_table_wait',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    SECOND: 1,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const timeValue = script.getNumberValue('SECOND', script);\n                    DataTable.showTable(tableId);\n                    Entry.engine.setTimeout(() => {\n                        DataTable.closeModal();\n                    }, timeValue * 1000);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            // 테이블 %1 의 %2 차트 창 열기\n            open_table_chart: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName() {\n                            const value = this.getTargetValue('dataTables');\n                            const source = DataTable.getSource(value);\n                            const { chart: charts = [] } = source || {};\n                            return charts.map(({ title }, index) => [title, index]);\n                        },\n                        needDeepCopy: true,\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                        defaultValue: (value, options) => {\n                            if (options.length) {\n                                return options[0][1];\n                            }\n                            return null;\n                        },\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'open_table_chart',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value', 'B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'open_table_chart',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    CHART_INDEX: 1,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const chartIndex = script.getField('CHART_INDEX', script);\n                    DataTable.showChart(tableId, chartIndex);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            close_table_chart: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'close_table_chart',\n                },\n                pyHelpDef: {\n                    params: [null],\n                    type: 'close_table_chart',\n                },\n                paramsKeyMap: {},\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    DataTable.closeModal();\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_coefficient: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'get_table_fields',\n                        },\n                        {\n                            type: 'get_table_fields',\n                        },\n                    ],\n                    type: 'get_coefficient',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'get_coefficient',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    FIELD1: 1,\n                    FIELD2: 2,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const x = DataTable.getColumnIndex(script.getValue('FIELD1', script));\n                    const y = DataTable.getColumnIndex(script.getValue('FIELD2', script));\n                    const table = DataTable.getSource(tableId, sprite);\n                    return table.getCoefficient(x - 1, y - 1);\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            set_value_from_cell: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/block_analysis.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A2'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'set_value_from_cell',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    CELL: 1,\n                    VALUE: 2,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const cell = script.getValue('CELL', script) || '';\n                    const value = script.getValue('VALUE', script);\n                    const table = DataTable.getSource(tableId, sprite);\n\n                    const { col, row } = Entry.Utils.cellToRowCol(cell.toUpperCase());\n                    if (table.isExist([row, col])) {\n                        table.replaceValue([row, col], value);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_value_from_cell: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A2'],\n                        },\n                    ],\n                    type: 'get_value_from_cell',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    CELL: 1,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const cell = script.getValue('CELL', script) || '';\n                    const { col, row } = Entry.Utils.cellToRowCol(cell.toUpperCase());\n                    const table = DataTable.getSource(tableId, sprite);\n\n                    if (table.isExist([row, col])) {\n                        return table.getValue([row, col]);\n                    }\n                    return null;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            get_value_v_lookup: {\n                color: EntryStatic.colorSet.block.default.ANALYSIS,\n                outerLine: EntryStatic.colorSet.block.darken.ANALYSIS,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'tables',\n                        dropdownSync: 'dataTables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.ANALYSIS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'get_table_fields',\n                        },\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        {\n                            type: 'get_table_fields',\n                        },\n                    ],\n                    type: 'get_value_v_lookup',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0,\n                    FIELD: 1,\n                    VALUE: 2,\n                    RETURN: 3,\n                },\n                class: 'analysis',\n                isNotFor: ['analysis'],\n                func(sprite, script) {\n                    const tableId = script.getField('MATRIX', script);\n                    const col = DataTable.getColumnIndex(script.getValue('FIELD', script));\n                    const returnCol = DataTable.getColumnIndex(script.getValue('RETURN', script));\n                    const value = script.getValue('VALUE', script);\n                    const table = DataTable.getSource(tableId, sprite);\n\n                    let foundIndex;\n                    for (let i = 0; i < table?.table?.length || 0; i++) {\n                        if (table.getValue([i, col]) == value) {\n                            foundIndex = i;\n                            break;\n                        }\n                    }\n\n                    if (table.isExist([foundIndex, returnCol])) {\n                        return table.getValue([foundIndex, returnCol]);\n                    }\n                    return null;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_brush.js",
    "content": "module.exports = {\n    getBlocks() {\n        return {\n            brush_stamp: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'brush_stamp',\n                },\n                class: 'stamp',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    sprite.addStamp();\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.stamp()'] },\n            },\n            start_drawing: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'start_drawing',\n                },\n                class: 'brush_control',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    if (sprite.brush) {\n                        sprite.brush.stop = false;\n                    } else {\n                        Entry.setBasicBrush(sprite);\n                    }\n\n                    sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.start_drawing()'] },\n            },\n            stop_drawing: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'stop_drawing',\n                },\n                class: 'brush_control',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    if (sprite.brush) {\n                        sprite.brush.stop = true;\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.stop_drawing()'] },\n            },\n            start_fill: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'start_fill',\n                },\n                class: 'fill_control',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    if (sprite.paint) {\n                        sprite.paint.stop = false;\n                        const rgb = sprite.paint.rgb;\n                        sprite.paint.beginFill(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.paint.opacity / 100})`\n                        );\n                    } else {\n                        Entry.setBasicPaint(sprite);\n                    }\n\n                    sprite.paint.moveTo(sprite.getX(), sprite.getY() * -1);\n                    return script.callReturn();\n                },\n            },\n            stop_fill: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'stop_fill',\n                },\n                class: 'fill_control',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    if (sprite.paint) {\n                        sprite.paint.endFill();\n                        sprite.paint.stop = true;\n                    }\n\n                    return script.callReturn();\n                },\n            },\n            set_color: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'color',\n                        },\n                        null,\n                    ],\n                    type: 'set_color',\n                },\n                pyHelpDef: {\n                    params: ['A&value'],\n                    type: 'set_color',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'brush_control',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const colour = script.getStringValue('VALUE', script);\n\n                    if (!sprite.brush || !sprite.shapes.length) {\n                        Entry.setBasicBrush(sprite);\n                        sprite.brush.stop = true;\n                    }\n\n                    if (sprite.brush) {\n                        const rgb = Entry.hex2rgb(colour);\n                        sprite.brush.rgb = rgb;\n                        sprite.brush.endStroke();\n                        sprite.brush.beginStroke(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.brush.opacity / 100})`\n                        );\n\n                        sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.set_brush_color_to(%1)',\n                            textParams: [\n                                {\n                                    type: 'Color',\n                                    converter: Entry.block.converters.returnStringValueUpperCase,\n                                    codeMap: 'Entry.CodeMap.Entry.set_color[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            set_random_color: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'set_random_color',\n                },\n                class: 'brush_color',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    if (!sprite.brush || !sprite.shapes.length) {\n                        Entry.setBasicBrush(sprite);\n                        sprite.brush.stop = true;\n                    }\n\n                    if (sprite.brush) {\n                        const rgb = Entry.generateRgb();\n                        sprite.brush.rgb = rgb;\n                        sprite.brush.endStroke();\n                        sprite.brush.beginStroke(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.brush.opacity / 100})`\n                        );\n\n                        sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    if (!sprite.paint || !sprite.paintShapes.length) {\n                        Entry.setBasicPaint(sprite);\n                        sprite.paint.stop = true;\n                    }\n\n                    if (sprite.paint) {\n                        const rgb = Entry.generateRgb();\n                        sprite.paint.rgb = rgb;\n                        sprite.paint.endFill();\n                        sprite.paint.beginFill(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.paint.opacity / 100})`\n                        );\n                        sprite.paint.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_brush_color_to_random()'] },\n            },\n            set_fill_color: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'color',\n                        },\n                        null,\n                    ],\n                    type: 'set_fill_color',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'fill_control',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const colour = script.getStringValue('VALUE', script);\n\n                    if (!sprite.paint || !sprite.paintShapes.length) {\n                        Entry.setBasicPaint(sprite);\n                        sprite.paint.stop = true;\n                    }\n\n                    if (sprite.paint) {\n                        const rgb = Entry.hex2rgb(colour);\n                        sprite.paint.rgb = rgb;\n                        sprite.paint.endFill();\n                        sprite.paint.beginFill(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.paint.opacity / 100})`\n                        );\n                        sprite.paint.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    return script.callReturn();\n                },\n            },\n            change_thickness: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                        null,\n                    ],\n                    type: 'change_thickness',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'change_thickness',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'brush_control',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const thickness = script.getNumberValue('VALUE', script);\n\n                    if (!sprite.brush || !sprite.shapes.length) {\n                        Entry.setBasicBrush(sprite);\n                        sprite.brush.stop = true;\n                    }\n\n                    if (sprite.brush) {\n                        sprite.brush.thickness += thickness;\n                        if (sprite.brush.thickness < 1) {\n                            sprite.brush.thickness = 1;\n                        }\n\n                        sprite.brush.setStrokeStyle(sprite.brush.thickness);\n\n                        sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.add_brush_size(%1)'] },\n            },\n            set_thickness: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                        null,\n                    ],\n                    type: 'set_thickness',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'set_thickness',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'brush_control',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const thickness = script.getNumberValue('VALUE', script);\n\n                    if (!sprite.brush || !sprite.shapes.length) {\n                        Entry.setBasicBrush(sprite);\n                        sprite.brush.stop = true;\n                    }\n\n                    if (sprite.brush) {\n                        sprite.brush.thickness = thickness;\n                        sprite.brush.setStrokeStyle(sprite.brush.thickness);\n\n                        sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_brush_size(%1)'] },\n            },\n            change_brush_transparency: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'change_brush_transparency',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'change_brush_transparency',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'brush_color',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const opacity = script.getNumberValue('VALUE', script);\n\n                    if (!sprite.brush || !sprite.shapes.length) {\n                        Entry.setBasicBrush(sprite);\n                        sprite.brush.stop = true;\n                    }\n\n                    if (!sprite.paint || !sprite.paintShapes.length) {\n                        Entry.setBasicPaint(sprite);\n                        sprite.paint.stop = true;\n                    }\n\n                    if (sprite.brush) {\n                        const newOpacity = Entry.adjustValueWithMaxMin(\n                            sprite.brush.opacity + opacity,\n                            0,\n                            100\n                        );\n                        sprite.brush.opacity = newOpacity;\n                        sprite.brush.endStroke();\n                        const rgb = sprite.brush.rgb;\n                        sprite.brush.beginStroke(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.brush.opacity / 100})`\n                        );\n                        sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    if (sprite.paint) {\n                        const newOpacity = Entry.adjustValueWithMaxMin(\n                            sprite.paint.opacity + opacity,\n                            0,\n                            100\n                        );\n                        sprite.paint.opacity = newOpacity;\n                        sprite.paint.endFill();\n                        const rgb = sprite.paint.rgb;\n                        sprite.paint.beginFill(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.paint.opacity / 100})`\n                        );\n                        sprite.paint.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.add_brush_transparency(%1)'] },\n            },\n            set_brush_tranparency: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['50'],\n                        },\n                        null,\n                    ],\n                    type: 'set_brush_tranparency',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'set_brush_tranparency',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'brush_color',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const opacityValue = script.getNumberValue('VALUE', script);\n\n                    if (!sprite.brush || !sprite.shapes.length) {\n                        Entry.setBasicBrush(sprite);\n                        sprite.brush.stop = true;\n                    }\n\n                    const opacity = Entry.adjustValueWithMaxMin(opacityValue, 0, 100);\n                    if (sprite.brush) {\n                        sprite.brush.opacity = opacity;\n                        sprite.brush.endStroke();\n                        const rgb = sprite.brush.rgb;\n                        sprite.brush.beginStroke(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.brush.opacity / 100})`\n                        );\n                        sprite.brush.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    if (!sprite.paint || !sprite.paintShapes.length) {\n                        Entry.setBasicPaint(sprite);\n                        sprite.paint.stop = true;\n                    }\n                    if (sprite.paint) {\n                        sprite.paint.opacity = opacity;\n                        sprite.paint.endFill();\n                        const rgb = sprite.paint.rgb;\n                        sprite.paint.beginFill(\n                            `rgba(${rgb.r},${rgb.g},${rgb.b},${1 - sprite.paint.opacity / 100})`\n                        );\n                        sprite.paint.moveTo(sprite.getX(), sprite.getY() * -1);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_brush_transparency(%1)'] },\n            },\n            brush_erase_all: {\n                color: EntryStatic.colorSet.block.default.BRUSH,\n                outerLine: EntryStatic.colorSet.block.darken.BRUSH,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/brush_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'brush_erase_all',\n                },\n                class: 'brush_clear',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    sprite.eraseBrush && sprite.eraseBrush();\n                    sprite.erasePaint && sprite.erasePaint();\n                    sprite.removeStamps();\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.clear_drawing()'] },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_calc.js",
    "content": "import _get from 'lodash/get';\n\nconst calcOperationOptions = EntryStatic.isPracticalCourse\n    ? [\n          [Lang.Blocks.CALC_calc_operation_unnatural, 'unnatural'],\n          [Lang.Blocks.CALC_calc_operation_floor, 'floor'],\n          [Lang.Blocks.CALC_calc_operation_ceil, 'ceil'],\n          [Lang.Blocks.CALC_calc_operation_round, 'round'],\n      ]\n    : [\n          [Lang.Blocks.CALC_calc_operation_square, 'square'],\n          [Lang.Blocks.CALC_calc_operation_root, 'root'],\n          [Lang.Blocks.CALC_calc_operation_sin, 'sin'],\n          [Lang.Blocks.CALC_calc_operation_cos, 'cos'],\n          [Lang.Blocks.CALC_calc_operation_tan, 'tan'],\n          [Lang.Blocks.CALC_calc_operation_asin, 'asin_radian'],\n          [Lang.Blocks.CALC_calc_operation_acos, 'acos_radian'],\n          [Lang.Blocks.CALC_calc_operation_atan, 'atan_radian'],\n          [Lang.Blocks.CALC_calc_operation_log, 'log'],\n          [Lang.Blocks.CALC_calc_operation_ln, 'ln'],\n          [Lang.Blocks.CALC_calc_operation_unnatural, 'unnatural'],\n          [Lang.Blocks.CALC_calc_operation_floor, 'floor'],\n          [Lang.Blocks.CALC_calc_operation_ceil, 'ceil'],\n          [Lang.Blocks.CALC_calc_operation_round, 'round'],\n          [Lang.Blocks.CALC_calc_operation_factorial, 'factorial'],\n          [Lang.Blocks.CALC_calc_operation_abs, 'abs'],\n      ];\n\nmodule.exports = {\n    getBlocks() {\n        return {\n            calc_basic: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['+', 'PLUS'],\n                            ['-', 'MINUS'],\n                            ['x', 'MULTI'],\n                            ['/', 'DIVIDE'],\n                        ],\n                        value: 'PLUS',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        noArrow: true,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        'PLUS',\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                    ],\n                    type: 'calc_basic',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        'PLUS',\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                    ],\n                    type: 'calc_basic',\n                },\n                defs: [\n                    {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                            'PLUS',\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'calc_basic',\n                    },\n                    {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                            'MINUS',\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'calc_basic',\n                    },\n                    {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                            'MULTI',\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'calc_basic',\n                    },\n                    {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                            'DIVIDE',\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'calc_basic',\n                    },\n                ],\n                paramsKeyMap: {\n                    LEFTHAND: 0,\n                    OPERATOR: 1,\n                    RIGHTHAND: 2,\n                },\n                class: 'calc',\n                isNotFor: [],\n                func(sprite, script) {\n                    const operator = script.getField('OPERATOR', script);\n                    let leftValue = script.getNumberValue('LEFTHAND', script);\n                    let rightValue = script.getNumberValue('RIGHTHAND', script);\n                    if (operator === 'PLUS') {\n                        const leftStringValue = script.getValue('LEFTHAND', script);\n                        const rightStringValue = script.getValue('RIGHTHAND', script);\n                        if (!Entry.Utils.isNumber(leftStringValue)) {\n                            leftValue = leftStringValue;\n                        }\n                        if (!Entry.Utils.isNumber(rightStringValue)) {\n                            rightValue = rightStringValue;\n                        }\n                        if (typeof leftValue === 'number' && typeof rightValue === 'number') {\n                            return new BigNumber(leftValue).plus(rightValue).toNumber();\n                        } else {\n                            return leftValue + rightValue;\n                        }\n                    }\n                    // below statements assume both arguments are number\n                    leftValue = new BigNumber(leftValue);\n                    rightValue = new BigNumber(rightValue);\n\n                    if (operator === 'MINUS') {\n                        return leftValue.minus(rightValue).toNumber();\n                    } else if (operator === 'MULTI') {\n                        return leftValue.times(rightValue).toNumber();\n                    } else {\n                        return leftValue.dividedBy(rightValue).toNumber();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '(%1 %2 %3)',\n                            template: '%1 %2 %3',\n                            keyOption: 'calc_basic',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        ['+', 'PLUS'],\n                                        ['-', 'MINUS'],\n                                        ['x', 'MULTI'],\n                                        ['/', 'DIVIDE'],\n                                    ],\n                                    value: 'PLUS',\n                                    fontSize: 11,\n                                    noArrow: true,\n                                    converter: Entry.block.converters.returnOperator,\n                                    paramType: 'operator',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            calc_rand: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_calc_rand_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_calc_rand_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_calc_rand_3,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'calc_rand',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'calc_rand',\n                },\n                paramsKeyMap: {\n                    LEFTHAND: 1,\n                    RIGHTHAND: 3,\n                },\n                class: 'calc',\n                isNotFor: [],\n                func(sprite, script) {\n                    const leftValue = script.getStringValue('LEFTHAND', script);\n                    const rightValue = script.getStringValue('RIGHTHAND', script);\n                    const left = Math.min(leftValue, rightValue);\n                    const right = Math.max(leftValue, rightValue);\n                    const isLeftFloat = Entry.isFloat(leftValue);\n                    const isRightFloat = Entry.isFloat(rightValue);\n                    if (isRightFloat || isLeftFloat) {\n                        return (Math.random() * (right - left) + left).toFixed(2);\n                    } else {\n                        return Math.floor(Math.random() * (right - left + 1) + left);\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'random.randint(%2, %4)',\n                            blockType: 'param',\n                            textParams: [\n                                null,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'integer',\n                                },\n                                null,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'integer',\n                                },\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'random.uniform(%2, %4)',\n                            blockType: 'param',\n                            textParams: [\n                                null,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'float',\n                                },\n                                null,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'float',\n                                },\n                                null,\n                            ],\n                        },\n                    ],\n                },\n            },\n            coordinate_mouse: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_coordinate_mouse_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['x', 'x'],\n                            ['y', 'y'],\n                        ],\n                        value: 'x',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_coordinate_mouse_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'coordinate_mouse',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null],\n                    type: 'coordinate_mouse',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'calc',\n                isNotFor: [],\n                func(sprite, script) {\n                    const targetCoordinate = script.getField('VALUE', script);\n                    if (targetCoordinate === 'x') {\n                        return Number(Entry.stage.mouseCoordinate.x);\n                    } else {\n                        return Number(Entry.stage.mouseCoordinate.y);\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_mouse_pointer(%2)',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Text',\n                                    text: Lang.Blocks.CALC_coordinate_mouse_1,\n                                    color: '#FFF',\n                                },\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        ['x', 'x'],\n                                        ['y', 'y'],\n                                    ],\n                                    value: 'x',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnStringKey,\n                                    codeMap: 'Entry.CodeMap.Entry.coordinate_mouse[1]',\n                                },\n                                {\n                                    type: 'Text',\n                                    text: Lang.Blocks.CALC_coordinate_mouse_2,\n                                    color: '#FFF',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            coordinate_object: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_coordinate_object_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'spritesWithSelf',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_coordinate_object_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.CALC_coordinate_x_value, 'x'],\n                            [Lang.Blocks.CALC_coordinate_y_value, 'y'],\n                            [Lang.Blocks.CALC_coordinate_rotation_value, 'rotation'],\n                            [Lang.Blocks.CALC_coordinate_direction_value, 'direction'],\n                            [Lang.Blocks.CALC_coordinate_size_value, 'size'],\n                            [Lang.Blocks.CALC_picture_index, 'picture_index'],\n                            [Lang.Blocks.CALC_picture_name, 'picture_name'],\n                        ],\n                        value: 'x',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null, null],\n                    type: 'coordinate_object',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null, 'B&value'],\n                    type: 'coordinate_object',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                    COORDINATE: 3,\n                },\n                class: 'calc',\n                isNotFor: [],\n                func(sprite, script) {\n                    const targetId = script.getField('VALUE', script);\n                    let targetEntity;\n                    if (targetId === 'self') {\n                        targetEntity = sprite;\n                    } else {\n                        targetEntity = Entry.container.getEntity(targetId);\n                    }\n\n                    const targetCoordinate = script.getField('COORDINATE', script);\n                    switch (targetCoordinate) {\n                        case 'x':\n                            return targetEntity.getX();\n                        case 'y':\n                            return targetEntity.getY();\n                        case 'rotation':\n                            return targetEntity.getRotation();\n                        case 'direction':\n                            return targetEntity.getDirection();\n                        case 'picture_index': {\n                            const object = targetEntity.parent;\n                            const pictures = object.pictures;\n                            return pictures.indexOf(targetEntity.picture) + 1;\n                        }\n                        case 'size':\n                            return Number(targetEntity.getSize().toFixed(1));\n                        case 'picture_name': {\n                            const object = targetEntity.parent;\n                            const pictures = object.pictures;\n                            const picture = pictures[pictures.indexOf(targetEntity.picture)];\n                            return picture.name;\n                        }\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_object(%2, %4)',\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'spritesWithSelf',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnObjectOrStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.coordinate_object[1]',\n                                },\n                                undefined,\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.CALC_coordinate_x_value, 'x'],\n                                        [Lang.Blocks.CALC_coordinate_y_value, 'y'],\n                                        [Lang.Blocks.CALC_coordinate_rotation_value, 'rotation'],\n                                        [Lang.Blocks.CALC_coordinate_direction_value, 'direction'],\n                                        [Lang.Blocks.CALC_coordinate_size_value, 'size'],\n                                        [Lang.Blocks.CALC_picture_index, 'picture_index'],\n                                        [Lang.Blocks.CALC_picture_name, 'picture_name'],\n                                    ],\n                                    value: 'x',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.coordinate_object[3]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            quotient_and_mod: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_quotient_and_mod_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_quotient_and_mod_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_quotient_and_mod_3,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.CALC_quotient_and_mod_sub_1, 'QUOTIENT'],\n                            [Lang.Blocks.CALC_quotient_and_mod_sub_2, 'MOD'],\n                        ],\n                        value: 'QUOTIENT',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'quotient_and_mod',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'quotient_and_mod',\n                },\n                paramsKeyMap: {\n                    LEFTHAND: 1,\n                    RIGHTHAND: 3,\n                    OPERATOR: 5,\n                },\n                class: 'calc',\n                isNotFor: [],\n                func(sprite, script) {\n                    const left = script.getNumberValue('LEFTHAND', script);\n                    const right = script.getNumberValue('RIGHTHAND', script);\n                    const operator = script.getField('OPERATOR', script);\n                    if (operator === 'QUOTIENT') {\n                        return Math.floor(left / right);\n                    } else {\n                        return left - right * Math.floor(left / right);\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '(%2 %6 %4)',\n                            template: '%2 %6 %4',\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.CALC_quotient_and_mod_sub_1, 'QUOTIENT'],\n                                        [Lang.Blocks.CALC_quotient_and_mod_sub_2, 'MOD'],\n                                    ],\n                                    value: 'QUOTIENT',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnOperator,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            calc_operation: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_calc_operation_of_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_calc_operation_of_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: calcOperationOptions,\n                        value: EntryStatic.isPracticalCourse ? 'unnatural' : 'square',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'calc_operation',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'calc_operation',\n                },\n                paramsKeyMap: {\n                    LEFTHAND: 1,\n                    VALUE: 3,\n                },\n                class: 'calc',\n                isNotFor: [],\n                func(sprite, script) {\n                    const value = script.getNumberValue('LEFTHAND', script);\n                    let operator = script.getField('VALUE', script);\n                    const xRangeCheckList = ['asin_radian', 'acos_radian'];\n                    if (xRangeCheckList.indexOf(operator) > -1 && (value > 1 || value < -1)) {\n                        throw new Error('x range exceeded');\n                    }\n\n                    if (!calcOperationOptions.some((option) => option[1] === operator)) {\n                        operator = 'round';\n                    }\n\n                    if (operator.indexOf('_')) {\n                        operator = operator.split('_')[0];\n                    }\n\n                    let returnVal = 0;\n                    switch (operator) {\n                        case 'square':\n                            returnVal = value * value;\n                            break;\n                        case 'factorial':\n                            returnVal = Entry.factorial(value);\n                            break;\n                        case 'root':\n                            returnVal = Math.sqrt(value);\n                            break;\n                        case 'log':\n                            returnVal = Math.log(value) / Math.LN10;\n                            break;\n                        case 'ln':\n                            returnVal = Math.log(value);\n                            break;\n                        case 'asin':\n                        case 'acos':\n                        case 'atan':\n                            returnVal = Entry.toDegrees(Math[operator](value));\n                            break;\n                        case 'sin':\n                        case 'cos':\n                        case 'tan':\n                            returnVal = Entry.preciseTrig(value, operator);\n                            break;\n                        case 'unnatural': {\n                            returnVal = new BigNumber(value).minus(Math.floor(value));\n                            returnVal = returnVal.toNumber();\n                            if (value < 0 && returnVal !== 0) {\n                                returnVal = 1 - returnVal;\n                            }\n                            break;\n                        }\n                        default:\n                            returnVal = Math[operator](value);\n                    }\n\n                    return returnVal;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '(%2 ** 2)',\n                            template: '%2 ** 2',\n                            params: [null, null, null, 'square'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            // for square\n                            syntax: 'math.pow(%2)',\n                            params: [null, null, null, 'square'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.sqrt(%2)',\n                            params: [null, null, null, 'root'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    isListIndex: true,\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.sin(%2)',\n                            params: [null, null, null, 'sin'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.cos(%2)',\n                            params: [null, null, null, 'cos'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.tan(%2)',\n                            params: [null, null, null, 'tan'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.asin(%2)',\n                            params: [null, null, null, 'asin_radian'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.acos(%2)',\n                            params: [null, null, null, 'acos_radian'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.atan(%2)',\n                            params: [null, null, null, 'atan_radian'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.log10(%2)',\n                            params: [null, null, null, 'log'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.log(%2)',\n                            params: [null, null, null, 'ln'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: '%2 - math.floor(%2)',\n                            params: [null, null, null, 'unnatural'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.floor(%2)',\n                            params: [null, null, null, 'floor'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.ceil(%2)',\n                            params: [null, null, null, 'ceil'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.round(%2)',\n                            params: [null, null, null, 'round'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.factorial(%2)',\n                            params: [null, null, null, 'factorial'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                        {\n                            syntax: 'math.fabs(%2)',\n                            params: [null, null, null, 'abs'],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                null,\n                            ],\n                        },\n                    ],\n                },\n            },\n            get_project_timer_value: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_get_timer_value,\n                        color: '#FFF',\n                    },\n                ],\n                events: {\n                    viewAdd: [\n                        function () {\n                            if (Entry.engine) {\n                                Entry.engine.showProjectTimer();\n                            }\n                        },\n                    ],\n                    viewDestroy: [\n                        function (block, notIncludeSelf) {\n                            if (Entry.engine) {\n                                Entry.engine.hideProjectTimer(block, notIncludeSelf);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null],\n                    type: 'get_project_timer_value',\n                },\n                class: 'calc_timer',\n                isNotFor: [],\n                func() {\n                    return Entry.engine.projectTimer.getValue();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_timer()',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            choose_project_timer_action: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_choose_project_timer_action_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.CALC_choose_project_timer_action_sub_1, 'START'],\n                            [Lang.Blocks.CALC_choose_project_timer_action_sub_2, 'STOP'],\n                            [Lang.Blocks.CALC_choose_project_timer_action_sub_3, 'RESET'],\n                        ],\n                        value: 'START',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_choose_project_timer_action_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/calc_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    viewAdd: [\n                        function () {\n                            if (Entry.engine) {\n                                Entry.engine.showProjectTimer();\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function (block) {\n                            if (Entry.engine) {\n                                Entry.engine.hideProjectTimer(block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, 'START', null, null],\n                    type: 'choose_project_timer_action',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null, null],\n                    type: 'choose_project_timer_action',\n                },\n                paramsKeyMap: {\n                    ACTION: 1,\n                },\n                class: 'calc_timer',\n                isNotFor: [],\n                func(sprite, script) {\n                    const engine = Entry.engine;\n                    const timer = engine.projectTimer;\n                    const isPaused = timer.isPaused;\n                    const isInit = timer.isInit;\n                    const currentTime = new Date().getTime();\n\n                    switch (script.getField('ACTION')) {\n                        case 'START':\n                            if (!isInit) {\n                                engine.startProjectTimer();\n                            } else if (isInit && isPaused) {\n                                if (timer.pauseStart) {\n                                    timer.pausedTime += currentTime - timer.pauseStart;\n                                }\n                                delete timer.pauseStart;\n                                timer.isPaused = false;\n                            }\n                            break;\n                        case 'STOP':\n                            if (isInit && !isPaused) {\n                                timer.isPaused = true;\n                                timer.pauseStart = currentTime;\n                            }\n                            break;\n                        case 'RESET':\n                            engine.resetTimer();\n                            break;\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            template: '%1 %2 %3',\n                            syntax: 'Entry.timer(%2)',\n                            textParams: [\n                                {\n                                    type: 'Text',\n                                    text: 'Entry.timer(',\n                                    color: EntryStatic.colorSet.common.WHITE,\n                                },\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [\n                                            Lang.Blocks.CALC_choose_project_timer_action_sub_1,\n                                            'START',\n                                        ],\n                                        [\n                                            Lang.Blocks.CALC_choose_project_timer_action_sub_2,\n                                            'STOP',\n                                        ],\n                                        [\n                                            Lang.Blocks.CALC_choose_project_timer_action_sub_3,\n                                            'RESET',\n                                        ],\n                                    ],\n                                    value: 'START',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnStringValueLowerCase,\n                                    codeMap: 'Entry.CodeMap.Entry.choose_project_timer_action[1]',\n                                },\n                                {\n                                    type: 'Text',\n                                    text: ')',\n                                    color: EntryStatic.colorSet.common.WHITE,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            set_visible_project_timer: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_timer_visible_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.CALC_timer_visible_show, 'SHOW'],\n                            [Lang.Blocks.CALC_timer_visible_hide, 'HIDE'],\n                        ],\n                        value: 'SHOW',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_choose_project_timer_action_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/calc_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    viewAdd: [\n                        function () {\n                            if (Entry.engine) {\n                                Entry.engine.showProjectTimer();\n                            }\n                        },\n                    ],\n                    viewDestroy: [\n                        function (block, notIncludeSelf) {\n                            if (Entry.engine) {\n                                Entry.engine.hideProjectTimer(block, notIncludeSelf);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, 'HIDE', null, null],\n                    type: 'set_visible_project_timer',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null, null],\n                    type: 'set_visible_project_timer',\n                },\n                paramsKeyMap: {\n                    ACTION: 1,\n                },\n                class: 'calc_timer',\n                isNotFor: [],\n                func(sprite, script) {\n                    const action = script.getField('ACTION');\n                    const timer = Entry.engine.projectTimer;\n                    if (action === 'SHOW') {\n                        timer.setVisible(true);\n                    } else {\n                        timer.setVisible(false);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            template: '%1 %2 %3',\n                            syntax: 'Entry.timer_view(%2)',\n                            textParams: [\n                                {\n                                    type: 'Text',\n                                    text: 'Entry.timer_view(',\n                                    color: EntryStatic.colorSet.common.WHITE,\n                                },\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.CALC_timer_visible_show, 'SHOW'],\n                                        [Lang.Blocks.CALC_timer_visible_hide, 'HIDE'],\n                                    ],\n                                    value: 'SHOW',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnStringValueLowerCase,\n                                    codeMap: 'Entry.CodeMap.Entry.set_visible_project_timer[1]',\n                                },\n                                {\n                                    type: 'Text',\n                                    text: ')',\n                                    color: EntryStatic.colorSet.common.WHITE,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            get_date: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_get_date_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.CALC_get_date_year, 'YEAR'],\n                            [Lang.Blocks.CALC_get_date_month, 'MONTH'],\n                            [Lang.Blocks.CALC_get_date_day, 'DAY'],\n                            [Lang.Blocks.CALC_get_date_day_of_week, 'DAY_OF_WEEK'],\n                            [Lang.Blocks.CALC_get_date_hour, 'HOUR'],\n                            [Lang.Blocks.CALC_get_date_minute, 'MINUTE'],\n                            [Lang.Blocks.CALC_get_date_second, 'SECOND'],\n                        ],\n                        value: 'YEAR',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_get_date_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, 'YEAR', null],\n                    type: 'get_date',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null],\n                    type: 'get_date',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'calc_date',\n                isNotFor: [],\n                func(sprite, script) {\n                    const operator = script.getField('VALUE', script);\n                    const dateTime = new Date();\n                    if (operator === 'YEAR') {\n                        return dateTime.getFullYear();\n                    } else if (operator === 'MONTH') {\n                        return dateTime.getMonth() + 1;\n                    } else if (operator === 'DAY') {\n                        return dateTime.getDate();\n                    } else if (operator === 'HOUR') {\n                        return dateTime.getHours();\n                    } else if (operator === 'MINUTE') {\n                        return dateTime.getMinutes();\n                    } else if (operator === 'DAY_OF_WEEK') {\n                        return dateTime.getDay();\n                    } else {\n                        return dateTime.getSeconds();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_current_time(%2)',\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.CALC_get_date_year, 'YEAR'],\n                                        [Lang.Blocks.CALC_get_date_month, 'MONTH'],\n                                        [Lang.Blocks.CALC_get_date_day, 'DAY'],\n                                        [Lang.Blocks.CALC_get_date_hour, 'HOUR'],\n                                        [Lang.Blocks.CALC_get_date_minute, 'MINUTE'],\n                                        [Lang.Blocks.CALC_get_date_second, 'SECOND'],\n                                        [Lang.Blocks.CALC_get_date_day_of_week, 'DAY_OF_WEEK'],\n                                    ],\n                                    value: 'YEAR',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnStringValueLowerCase,\n                                    codeMap: 'Entry.CodeMap.Entry.get_date[1]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            distance_something: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_distance_something_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'spritesWithMouse',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_distance_something_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'distance_something',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null],\n                    type: 'distance_something',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'calc_distance',\n                isNotFor: [],\n                func(sprite, script) {\n                    const targetId = script.getField('VALUE', script);\n                    if (targetId === 'mouse') {\n                        const mousePos = Entry.stage.mouseCoordinate;\n                        return Math.sqrt(\n                            Math.pow(sprite.getX() - mousePos.x, 2) +\n                                Math.pow(sprite.getY() - mousePos.y, 2)\n                        );\n                    } else {\n                        const targetEntity = Entry.container.getEntity(targetId);\n                        return Math.sqrt(\n                            Math.pow(sprite.getX() - targetEntity.getX(), 2) +\n                                Math.pow(sprite.getY() - targetEntity.getY(), 2)\n                        );\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_distance_to(%2)',\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'spritesWithMouse',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnStringKey,\n                                    codeMap: 'Entry.CodeMap.Entry.distance_something[1]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            get_user_name: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                fontColor: '#FFF',\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'get_user_name',\n                },\n                class: 'calc_user',\n                isNotFor: [],\n                func() {\n                    return window.user ? window.user.username : ' ';\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_username()',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            get_nickname: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                fontColor: '#FFF',\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'get_nickname',\n                },\n                class: 'calc_user',\n                isNotFor: [],\n                func() {\n                    return window.user ? window.user.nickname : ' ';\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_nickname()',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            length_of_string: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_length_of_string_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_length_of_string_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.entry],\n                        },\n                        null,\n                    ],\n                    type: 'length_of_string',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'length_of_string',\n                },\n                paramsKeyMap: {\n                    STRING: 1,\n                },\n                class: 'calc_string',\n                isNotFor: [],\n                func(sprite, script) {\n                    return script.getStringValue('STRING', script).length;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'len(%2)',\n                            blockType: 'param',\n                            keyOption: 'length_of_string',\n                        },\n                    ],\n                },\n            },\n            reverse_of_string: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_reverse_of_string_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_reverse_of_string_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.entry],\n                        },\n                        null,\n                    ],\n                    type: 'reverse_of_string',\n                },\n                paramsKeyMap: {\n                    STRING: 1,\n                },\n                class: 'calc_string',\n                isNotFor: ['python_disable'],\n                func(sprite, script) {\n                    const originStr = script.getStringValue('STRING', script);\n                    const reversedStr = originStr.split('').reverse().join('');\n                    return reversedStr;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            combine_something: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_combine_something_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_combine_something_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_combine_something_3,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.block_hi],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.entry],\n                        },\n                        null,\n                    ],\n                    type: 'combine_something',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'combine_something',\n                },\n                paramsKeyMap: {\n                    VALUE1: 1,\n                    VALUE2: 3,\n                },\n                class: 'calc_string',\n                isNotFor: [],\n                func(sprite, script) {\n                    const leftValue = script.getStringValue('VALUE1', script);\n                    const rightValue = script.getStringValue('VALUE2', script);\n\n                    return `${leftValue}${rightValue}`;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '(%2 + %4)',\n                            template: '%2 + %4',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            char_at: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_char_at_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_char_at_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        isListIndex: true,\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_char_at_3,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.hi_entry],\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                        null,\n                    ],\n                    type: 'char_at',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'char_at',\n                },\n                paramsKeyMap: {\n                    LEFTHAND: 1,\n                    RIGHTHAND: 3,\n                },\n                class: 'calc_string',\n                isNotFor: [],\n                func(sprite, script) {\n                    const str = script.getStringValue('LEFTHAND', script);\n                    const index = script.getNumberValue('RIGHTHAND', script) - 1;\n                    if (index < 0 || index > str.length - 1) {\n                        throw new Error();\n                    } else {\n                        return str[index];\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%2[%4]',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Text',\n                                    text: Lang.Blocks.CALC_char_at_1,\n                                    color: '#FFF',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Text',\n                                    text: Lang.Blocks.CALC_char_at_2,\n                                    color: '#FFF',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'index',\n                                },\n                                {\n                                    type: 'Text',\n                                    text: Lang.Blocks.CALC_char_at_3,\n                                    color: '#FFF',\n                                },\n                            ],\n                            keyOption: 'char_at',\n                        },\n                    ],\n                },\n            },\n            substring: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_substring_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_substring_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        isListIndex: true,\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_substring_3,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_substring_4,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.hi_entry],\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['2'],\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['5'],\n                        },\n                        null,\n                    ],\n                    type: 'substring',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'substring',\n                },\n                paramsKeyMap: {\n                    STRING: 1,\n                    START: 3,\n                    END: 5,\n                },\n                class: 'calc_string',\n                isNotFor: [],\n                func(sprite, script) {\n                    const str = script.getStringValue('STRING', script);\n                    const start = script.getNumberValue('START', script) - 1;\n                    const end = script.getNumberValue('END', script) - 1;\n                    const strLen = str.length - 1;\n                    if (start < 0 || end < 0 || start > strLen || end > strLen) {\n                        throw new Error();\n                    } else {\n                        return str.substring(Math.min(start, end), Math.max(start, end) + 1);\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%2[%4:%6]',\n                            blockType: 'param',\n                            textParams: [\n                                null,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                null,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'index',\n                                },\n                                null,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                null,\n                            ],\n                        },\n                    ],\n                },\n            },\n            count_match_string: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_count_match_string_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_count_match_string_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.hi_entry_en],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: ['e'],\n                        },\n                        null,\n                    ],\n                    type: 'count_match_string',\n                },\n                paramsKeyMap: {\n                    STRING: 0,\n                    TARGET: 2,\n                },\n                class: 'calc_string',\n                isNotFor: ['python_disable'],\n                func(sprite, script) {\n                    const originStr = script.getStringValue('STRING', script);\n                    const targetStr = script.getStringValue('TARGET', script);\n                    return originStr.split(targetStr).length - 1;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            index_of_string: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_index_of_string_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_index_of_string_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_index_of_string_3,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.hi_entry],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.entry],\n                        },\n                        null,\n                    ],\n                    type: 'index_of_string',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'index_of_string',\n                },\n                paramsKeyMap: {\n                    LEFTHAND: 1,\n                    RIGHTHAND: 3,\n                },\n                class: 'calc_string',\n                isNotFor: [],\n                func(sprite, script) {\n                    const str = script.getStringValue('LEFTHAND', script);\n                    const target = script.getStringValue('RIGHTHAND', script);\n                    const index = str.indexOf(target);\n                    return index + 1;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%2.find(%4)',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            replace_string: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_replace_string_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_replace_string_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_replace_string_3,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_replace_string_4,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.hi_entry],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.hello],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.nice],\n                        },\n                        null,\n                    ],\n                    type: 'replace_string',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'replace_string',\n                },\n                paramsKeyMap: {\n                    STRING: 1,\n                    OLD_WORD: 3,\n                    NEW_WORD: 5,\n                },\n                class: 'calc_string',\n                isNotFor: [],\n                func(sprite, script) {\n                    const oldWord = script.getStringValue('OLD_WORD', script);\n                    const newWord = script.getStringValue('NEW_WORD', script);\n                    const originalString = script.getStringValue('STRING', script);\n                    return originalString.split(oldWord).join(newWord);\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%2.replace(%4, %6)',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            change_string_case: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_change_string_case_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_change_string_case_2,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.CALC_change_string_case_sub_1, 'toUpperCase'],\n                            [Lang.Blocks.CALC_change_string_case_sub_2, 'toLowerCase'],\n                        ],\n                        value: 'toUpperCase',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_change_string_case_3,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['Hello Entry!'],\n                        },\n                        null,\n                        null,\n                        null,\n                    ],\n                    type: 'change_string_case',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                        null,\n                        null,\n                    ],\n                    type: 'change_string_case',\n                },\n                paramsKeyMap: {\n                    STRING: 1,\n                    CASE: 3,\n                },\n                class: 'calc_string',\n                isNotFor: [],\n                func(sprite, script) {\n                    const str = script.getStringValue('STRING', script);\n                    const caseType = script.getField('CASE', script);\n                    if (caseType === 'toUpperCase') {\n                        return str.toUpperCase();\n                    } else if (caseType === 'toLowerCase') {\n                        return str.toLowerCase();\n                    }\n                    return str;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%2.upper()',\n                            params: [null, null, null, 'toUpperCase', null],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.CALC_change_string_case_sub_1, 'toUpperCase'],\n                                        [Lang.Blocks.CALC_change_string_case_sub_2, 'toLowerCase'],\n                                    ],\n                                    value: 'toUpperCase',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnStringValue,\n                                },\n                            ],\n                        },\n                        {\n                            syntax: '%2.lower()',\n                            params: [null, null, null, 'toLowerCase', null],\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                undefined,\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.CALC_change_string_case_sub_1, 'toUpperCase'],\n                                        [Lang.Blocks.CALC_change_string_case_sub_2, 'toLowerCase'],\n                                    ],\n                                    value: 'toUpperCase',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.CALC,\n                                    converter: Entry.block.converters.returnStringValue,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            get_block_count: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'blockCount',\n                        fontSize: 10,\n                        textColor: '#fff',\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'get_block_count',\n                },\n                pyHelpDef: {\n                    params: ['A&value'],\n                    type: 'get_block_count',\n                },\n                paramsKeyMap: {\n                    OBJECT: 0,\n                },\n                class: 'block',\n                isNotFor: [],\n                async func(sprite, script) {\n                    const objectKey = script.getField('OBJECT', script);\n                    if (!objectKey) {\n                        return 0;\n                    }\n                    let object;\n                    if (objectKey.indexOf('scene-') === 0) {\n                        const blocks = await Entry.Utils.getObjectsBlocksBySceneId(\n                            objectKey.substr(6)\n                        );\n                        return _get(blocks, 'length', 0);\n                    } else if (objectKey === 'all') {\n                        object = undefined;\n                    } else if (objectKey === 'self') {\n                        object = sprite.parent;\n                    } else if (objectKey.indexOf('object-') === 0) {\n                        object = Entry.container.getObject(objectKey.substr(7));\n                    } else {\n                        return 0;\n                    }\n\n                    const blocks = await Entry.Utils.getObjectsBlocksForEventThread(object);\n                    const count = _get(blocks, 'length', 0);\n                    return count;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.get_block_count(%1)',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'blockCount',\n                                    fontSize: 11,\n                                    textColor: '#fff',\n                                    arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                                    converter: Entry.block.converters.returnStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.get_block_count[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            change_rgb_to_hex: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['255'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                    ],\n                    type: 'change_rgb_to_hex',\n                },\n                paramsKeyMap: {\n                    RED: 0,\n                    GREEN: 1,\n                    BLUE: 2,\n                },\n                class: 'color',\n                isNotFor: [],\n                func(sprite, script) {\n                    const red = script.getNumberValue('RED', script);\n                    const greeb = script.getNumberValue('GREEN', script);\n                    const blue = script.getNumberValue('BLUE', script);\n                    return Entry.rgb2hex(red, greeb, blue);\n                },\n            },\n            change_hex_to_rgb: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['R', 'r'],\n                            ['G', 'g'],\n                            ['B', 'b'],\n                        ],\n                        value: 'RED',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.CALC,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['#ff0000'],\n                        },\n                        'r',\n                    ],\n                    type: 'change_hex_to_rgb',\n                },\n                paramsKeyMap: {\n                    HEX: 0,\n                    COLOR: 1,\n                },\n                class: 'color',\n                isNotFor: [],\n                func(sprite, script) {\n                    const color = script.getField('COLOR', script);\n                    const value = script.getValue('HEX', script);\n                    return Entry.hex2rgb(value)[color];\n                },\n            },\n            get_boolean_value: {\n                color: EntryStatic.colorSet.block.default.CALC,\n                fontColor: '#FFF',\n                outerLine: EntryStatic.colorSet.block.darken.CALC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [{ type: 'True' }],\n                    type: 'get_boolean_value',\n                },\n                class: 'calc_boolean',\n                isNotFor: [],\n                paramsKeyMap: {\n                    BOOLEAN: 0,\n                },\n                func(sprite, script) {\n                    const bool = script.getValue('BOOLEAN', script);\n                    if (Boolean(bool)) {\n                        return 'TRUE';\n                    }\n                    return 'FALSE';\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_username()',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_expansion_behaviorconduct_disaster.js",
    "content": "'use strict';\n\nconst PromiseManager = require('../../core/promiseManager');\nconst { callApi } = require('../../util/common');\n\nfunction getInitialCategoryMap() {\n    return {\n        '01001': {\n            lang: Lang.Blocks.behaviorConduct01001,\n            sub: ['01001001', '01001002', '01001003'],\n        },\n        '01002': {\n            lang: Lang.Blocks.behaviorConduct01002,\n            sub: ['01002002', '01002003', '01002004'],\n        },\n        '01003': {\n            lang: Lang.Blocks.behaviorConduct01003,\n            sub: ['01003002', '01003003', '01003004'],\n        },\n        '01004': {\n            lang: Lang.Blocks.behaviorConduct01004,\n            sub: ['01004001', '01004002'],\n        },\n        '01005': {\n            lang: Lang.Blocks.behaviorConduct01005,\n            sub: ['01005002', '01005003', '01005004'],\n        },\n        '01006': {\n            lang: Lang.Blocks.behaviorConduct01006,\n            sub: ['01006001', '01006002'],\n        },\n        '01007': {\n            lang: Lang.Blocks.behaviorConduct01007,\n            sub: ['01007001'],\n        },\n        '01008': {\n            lang: Lang.Blocks.behaviorConduct01008,\n            sub: ['01008001', '01008002', '01008003'],\n        },\n        '01009': {\n            lang: Lang.Blocks.behaviorConduct01009,\n            sub: ['01009001', '01009002'],\n        },\n        '01010': {\n            lang: Lang.Blocks.behaviorConduct01010,\n            sub: ['01010001'],\n        },\n        '01011': {\n            lang: Lang.Blocks.behaviorConduct01011,\n            sub: ['01011009', '01011010', '01011012'],\n        },\n        '01013': {\n            lang: Lang.Blocks.behaviorConduct01013,\n            sub: ['01013002', '01013003'],\n        },\n        '01014': {\n            lang: Lang.Blocks.behaviorConduct01014,\n            sub: ['01014001'],\n        },\n    };\n}\n\nEntry.EXPANSION_BLOCK.behaviorConductDisaster = {\n    name: 'behaviorConductDisaster',\n    imageName: 'disaster.png',\n    title: {\n        ko: '자연재난',\n        en: 'Disaster',\n        jp: '自然災害',\n    },\n    titleKey: 'template.behaviorConductDisaster_title_text',\n    description: Lang.Msgs.expansion_behaviorConductDisaster_description,\n    descriptionKey: 'Msgs.expansion_behaviorConductDisaster_description',\n    isInitialized: false,\n    disabled: true,\n    init() {\n        if (this.isInitialized) {\n            return;\n        }\n        Entry.EXPANSION_BLOCK.behaviorConductDisaster.isInitialized = true;\n    },\n    api: '/api/expansionBlock/behaviorConduct',\n    apiType: '01',\n};\n\nEntry.EXPANSION_BLOCK.behaviorConductDisaster.getBlocks = function () {\n    const categoryMap = getInitialCategoryMap();\n    const getCategory = function () {\n        return Object.keys(categoryMap).map((category) => [categoryMap[category].lang, category]);\n    };\n    const defaultCategory = Object.keys(categoryMap)[0];\n    const params = {\n        getCategory(isPython) {\n            const param = {\n                type: 'Dropdown',\n                options: getCategory(),\n                value: defaultCategory,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                dropdownSync: 'disaster',\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getSubCategory(isPython = false) {\n            const param = {\n                type: 'DropdownDynamic',\n                value: null,\n                menuName() {\n                    const value = this.getTargetValue('disaster');\n                    if (!value) {\n                        return [[Lang.Blocks.no_target, 'null']];\n                    }\n                    return categoryMap[value].sub.map((category) => [\n                        Lang.Blocks[`behaviorConduct${category}`],\n                        category,\n                    ]);\n                },\n                needDeepCopy: true,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                defaultValue: (value, options) => {\n                    if (options.length) {\n                        return options[0][1];\n                    }\n                    return null;\n                },\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n    };\n\n    const getBehavior = (params, defaultValue, index = null) => {\n        const key = `behaviorConduct-${params.category}/${params.subCategory}`;\n        return new PromiseManager()\n            .Promise((resolve) => {\n                callApi(key, {\n                    url: `${Entry.EXPANSION_BLOCK.behaviorConductDisaster.api}/${params.category}/${params.subCategory}`,\n                })\n                    .then((result) => {\n                        if (result) {\n                            const items = result.data.response.body.items.item.filter(\n                                (i) =>\n                                    i.hasOwnProperty('actRmks') &&\n                                    i.safetyCate3 == params.subCategory2\n                            );\n                            if (index) {\n                                return resolve(items[index - 1].actRmks);\n                            }\n                            return resolve(items.length);\n                        }\n                        return resolve(defaultValue);\n                    })\n                    .catch(() => resolve(defaultValue));\n            })\n            .catch(() => defaultValue);\n    };\n\n    return {\n        behaviorConductDisaster_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.behaviorConductDisaster_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'behaviorConductDisaster_title',\n            },\n            class: 'behaviorConductDisaster',\n            isNotFor: ['behaviorConductDisaster'],\n            events: {},\n        },\n        count_disaster_behavior: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getCategory(), params.getSubCategory()],\n            events: {},\n            def: {\n                params: [params.getCategory().value, null],\n                type: 'count_disaster_behavior',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value'],\n                type: 'count_disaster_behavior',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n            },\n            class: 'behaviorConductDisaster',\n            isNotFor: ['behaviorConductDisaster'],\n            func(sprite, script) {\n                const params = {\n                    category: Entry.EXPANSION_BLOCK.behaviorConductDisaster.apiType,\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getBehavior(params, 0);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n        get_disaster_behavior: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                params.getCategory(),\n                params.getSubCategory(),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [params.getCategory().value, null, 1],\n                type: 'get_disaster_behavior',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_disaster_behavior',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n                NUMBER: 2,\n            },\n            class: 'behaviorConductDisaster',\n            isNotFor: ['behaviorConductDisaster'],\n            func(sprite, script) {\n                const number = script.getStringValue('NUMBER', script);\n                const defaultValue = Lang.Blocks.deprecated;\n                const params = {\n                    category: Entry.EXPANSION_BLOCK.behaviorConductDisaster.apiType,\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getBehavior(params, defaultValue, number);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_expansion_behaviorconduct_lifesafety.js",
    "content": "'use strict';\n\nconst PromiseManager = require('../../core/promiseManager');\nconst { callApi } = require('../../util/common');\n\nfunction getInitialCategoryMap() {\n    return {\n        '03002': {\n            lang: Lang.Blocks.behaviorConduct03002,\n            sub: ['03002002', '03002003', '03002004', '03002005', '03002006'],\n        },\n        '03003': {\n            lang: Lang.Blocks.behaviorConduct03003,\n            sub: ['03003001', '03003002', '03003003'],\n        },\n        '03004': {\n            lang: Lang.Blocks.behaviorConduct03004,\n            sub: ['03004001'],\n        },\n        '03016': {\n            lang: Lang.Blocks.behaviorConduct03016,\n            sub: ['03016001'],\n        },\n        '03005': {\n            lang: Lang.Blocks.behaviorConduct03005,\n            sub: ['03005001'],\n        },\n        '03006': {\n            lang: Lang.Blocks.behaviorConduct03006,\n            sub: ['03006004', '03006005', '03006002', '03006003'],\n        },\n        '03008': {\n            lang: Lang.Blocks.behaviorConduct03008,\n            sub: ['03008001'],\n        },\n        '03009': {\n            lang: Lang.Blocks.behaviorConduct03009,\n            sub: ['03009001'],\n        },\n        '03010': {\n            lang: Lang.Blocks.behaviorConduct03010,\n            sub: ['03010001'],\n        },\n        '03011': {\n            lang: Lang.Blocks.behaviorConduct03011,\n            sub: ['03011001'],\n        },\n        '03012': {\n            lang: Lang.Blocks.behaviorConduct03012,\n            sub: ['03012001'],\n        },\n        '03013': {\n            lang: Lang.Blocks.behaviorConduct03013,\n            sub: ['03013002', '03013005'],\n        },\n        '03014': {\n            lang: Lang.Blocks.behaviorConduct03014,\n            sub: ['03014001', '03014003', '03014004'],\n        },\n        '03015': {\n            lang: Lang.Blocks.behaviorConduct03015,\n            sub: ['03015007', '03015003'],\n        },\n    };\n}\n\nEntry.EXPANSION_BLOCK.behaviorConductLifeSafety = {\n    name: 'behaviorConductLifeSafety',\n    imageName: 'firstaid.png',\n    title: {\n        ko: '생활안전',\n        en: 'LifeSafety',\n        jp: '生活安全',\n    },\n    titleKey: 'template.behaviorConductLifeSafety_title_text',\n    description: Lang.Msgs.expansion_behaviorConductLifeSafety_description,\n    descriptionKey: 'Msgs.expansion_behaviorConductLifeSafety_description',\n    isInitialized: false,\n    disabled: true,\n    init() {\n        if (this.isInitialized) {\n            return;\n        }\n        Entry.EXPANSION_BLOCK.behaviorConductLifeSafety.isInitialized = true;\n    },\n    api: '/api/expansionBlock/behaviorConduct',\n    apiType: '03',\n};\n\nEntry.EXPANSION_BLOCK.behaviorConductLifeSafety.getBlocks = function () {\n    const categoryMap = getInitialCategoryMap();\n    const getCategory = function () {\n        return Object.keys(categoryMap).map((category) => [categoryMap[category].lang, category]);\n    };\n    const defaultCategory = Object.keys(categoryMap)[0];\n    const params = {\n        getCategory(isPython) {\n            const param = {\n                type: 'Dropdown',\n                options: getCategory(),\n                value: defaultCategory,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                dropdownSync: 'lifesafety',\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getSubCategory(isPython = false) {\n            const param = {\n                type: 'DropdownDynamic',\n                value: null,\n                menuName() {\n                    const value = this.getTargetValue('lifesafety');\n                    if (!value) {\n                        return [[Lang.Blocks.no_target, 'null']];\n                    }\n                    return categoryMap[value].sub.map((category) => [\n                        Lang.Blocks[`behaviorConduct${category}`],\n                        category,\n                    ]);\n                },\n                needDeepCopy: true,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                defaultValue: (value, options) => {\n                    if (options.length) {\n                        return options[0][1];\n                    }\n                    return null;\n                },\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n    };\n\n    const getBehavior = (params, defaultValue, index = null) => {\n        const key = `behaviorConduct-${params.category}/${params.subCategory}`;\n        return new PromiseManager()\n            .Promise((resolve) => {\n                callApi(key, {\n                    url: `${Entry.EXPANSION_BLOCK.behaviorConductLifeSafety.api}/${params.category}/${params.subCategory}`,\n                })\n                    .then((result) => {\n                        if (result) {\n                            const items = result.data.response.body.items.item.filter(\n                                (i) =>\n                                    i.hasOwnProperty('actRmks') &&\n                                    i.safetyCate3 == params.subCategory2\n                            );\n                            if (index) {\n                                return resolve(items[index - 1].actRmks);\n                            }\n                            return resolve(items.length);\n                        }\n                        return resolve(defaultValue);\n                    })\n                    .catch(() => resolve(defaultValue));\n            })\n            .catch(() => defaultValue);\n    };\n\n    return {\n        behaviorConductLifeSafety_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.behaviorConductLifeSafety_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'behaviorConductLifeSafety_title',\n            },\n            class: 'behaviorConductLifeSafety',\n            isNotFor: ['behaviorConductLifeSafety'],\n            events: {},\n        },\n        count_lifeSafety_behavior: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getCategory(), params.getSubCategory()],\n            events: {},\n            def: {\n                params: [params.getCategory().value, null],\n                type: 'count_lifeSafety_behavior',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value'],\n                type: 'count_lifeSafety_behavior',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n            },\n            class: 'behaviorConductLifeSafety',\n            isNotFor: ['behaviorConductLifeSafety'],\n            func(sprite, script) {\n                const params = {\n                    category: Entry.EXPANSION_BLOCK.behaviorConductLifeSafety.apiType,\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getBehavior(params, 0);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n        get_lifeSafety_behavior: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                params.getCategory(),\n                params.getSubCategory(),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [params.getCategory().value, null, 1],\n                type: 'get_lifeSafety_behavior',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_lifeSafety_behavior',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n                NUMBER: 2,\n            },\n            class: 'behaviorConductLifeSafety',\n            isNotFor: ['behaviorConductLifeSafety'],\n            func(sprite, script) {\n                const number = script.getStringValue('NUMBER', script);\n                const defaultValue = Lang.Blocks.deprecated;\n                const params = {\n                    category: Entry.EXPANSION_BLOCK.behaviorConductLifeSafety.apiType,\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getBehavior(params, defaultValue, number);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_expansion_disasterAlert.js",
    "content": "'use strict';\n\nconst PromiseManager = require('../../core/promiseManager');\nconst { callApi } = require('../../util/common');\n\nEntry.EXPANSION_BLOCK.disasterAlert = {\n    name: 'disasterAlert',\n    imageName: 'disasterAlert.png',\n    title: {\n        ko: '재난문자',\n        en: 'Disaster alert',\n    },\n    titleKey: 'template.disaster_alert_title_text',\n    description: Lang.Msgs.expansion_disasterAlert_description,\n    descriptionKey: 'Msgs.expansion_disasterAlert_description',\n    isInitialized: false,\n    init() {\n        if (this.isInitialized) {\n            return;\n        }\n        Entry.EXPANSION_BLOCK.disasterAlert.isInitialized = true;\n    },\n    api: '/api/expansionBlock/disasterAlert',\n    apiType: '01',\n};\n\nconst EMERGENCY_CATEGORY_MAP = {\n    info: Lang.Blocks.disasterAlertTypeInfo,\n    exigency: Lang.Blocks.disasterAlertTypeExigency,\n    urgency: Lang.Blocks.disasterAlertTypeUrgency,\n};\n\nconst getDisasterAlert = (params, defaultValue) => {\n    const now = new Date();\n    const hour = now.getHours();\n    const day = now.getDay();\n    const key = `disasterAlert-${day}-${hour}`;\n    const promiseManager = new PromiseManager();\n    const job = promiseManager\n        // eslint-disable-next-line new-cap\n        .Promise((resolve) => {\n            callApi(key, {\n                url: `${Entry.EXPANSION_BLOCK.disasterAlert.api}`,\n            })\n                .then((result) => {\n                    if (result) {\n                        let items = result?.data?.body || [];\n                        const category = EMERGENCY_CATEGORY_MAP?.[params?.category];\n                        if (category) {\n                            items = items.filter((item) => item.EMRG_STEP_NM === category);\n                        }\n                        switch (params.command) {\n                            case 'count':\n                                return resolve(items?.length || defaultValue || 0);\n                            case 'get':\n                                const result = items?.[params?.index - 1]?.[params.option];\n                                if (!result) {\n                                    return resolve(defaultValue);\n                                }\n                                if (params?.option === 'REG_YMD') {\n                                    return resolve(new Date(result).toLocaleString());\n                                }\n                                return resolve(result);\n                            case 'exist':\n                                return resolve(items?.length > 0);\n                            default:\n                                return resolve(defaultValue);\n                        }\n                    }\n                    return resolve(defaultValue);\n                })\n                .catch(() => resolve(defaultValue));\n        })\n        .catch(() => defaultValue);\n\n    return job;\n};\n\nEntry.EXPANSION_BLOCK.disasterAlert.getBlocks = function () {\n    // 전체, 안전안내, 긴급재난, 위급재난\n    const DisasterAlertCategory = {\n        type: 'Dropdown',\n        options: [\n            [Lang.Blocks.disasterAlertTypeAll, 'all'],\n            [Lang.Blocks.disasterAlertTypeInfo, 'info'],\n            [Lang.Blocks.disasterAlertTypeExigency, 'exigency'],\n            [Lang.Blocks.disasterAlertTypeUrgency, 'urgency'],\n        ],\n        value: 'all',\n        fontSize: 11,\n        bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n        arrowColor: EntryStatic.colorSet.common.WHITE,\n    };\n    // 내용, 수신지역, 긴급단계, 재해구분, 생성일시\n    const DisasterAlertOptions = {\n        type: 'Dropdown',\n        options: [\n            [Lang.Blocks.disasterAlertContents, 'MSG_CN'],\n            [Lang.Blocks.disasterAlertRegeion, 'RCPTN_RGN_NM'],\n            [Lang.Blocks.disasterAlertStep, 'EMRG_STEP_NM'],\n            [Lang.Blocks.disasterAlertDisaster, 'DST_SE_NM'],\n            [Lang.Blocks.disasterAlertRegisterDate, 'REG_YMD'],\n        ],\n        value: 'MSG_CN',\n        fontSize: 11,\n        bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n        arrowColor: EntryStatic.colorSet.common.WHITE,\n    };\n\n    return {\n        disaster_alert_title: {\n            template: '%1',\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.disaster_alert_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'disaster_alert_title',\n            },\n            class: 'disasterAlert',\n            isNotFor: ['disasterAlert'],\n            events: {},\n        },\n        count_disaster_alert: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [DisasterAlertCategory],\n            events: {},\n            def: {\n                params: [DisasterAlertCategory.value],\n                type: 'count_disaster_alert',\n            },\n            pyHelpDef: {\n                params: ['A&value'],\n                type: 'count_disaster_alert',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n            },\n            class: 'disasterAlert',\n            isNotFor: ['disasterAlert'],\n            func(sprite, script) {\n                const category = script.getField('CATEGORY', script);\n                return getDisasterAlert(\n                    {\n                        command: 'count',\n                        category,\n                    },\n                    0\n                );\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'disasterAlert',\n        },\n        get_disaster_alert: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                DisasterAlertCategory,\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                DisasterAlertOptions,\n            ],\n            events: {},\n            def: {\n                params: [DisasterAlertCategory.value, 1, DisasterAlertOptions.value],\n                type: 'get_disaster_alert',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_disaster_alert',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                NUMBER: 1,\n                OPTION: 2,\n            },\n            class: 'disasterAlert',\n            isNotFor: ['disasterAlert'],\n            func(sprite, script) {\n                const number = script.getStringValue('NUMBER', script);\n                const category = script.getField('CATEGORY', script);\n                const option = script.getField('OPTION', script);\n                return getDisasterAlert({\n                    command: 'get',\n                    category,\n                    index: number,\n                    option,\n                });\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'disasterAlert',\n        },\n        check_disaster_alert: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [DisasterAlertCategory],\n            events: {},\n            def: {\n                params: [DisasterAlertCategory.value],\n                type: 'check_disaster_alert',\n            },\n            pyHelpDef: {\n                params: ['B&value', null],\n                type: 'check_disaster_alert',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n            },\n            class: 'disasterAlert',\n            isNotFor: ['disasterAlert'],\n            async func(sprite, script) {\n                const category = script.getField('CATEGORY', script);\n                return getDisasterAlert({\n                    command: 'exist',\n                    category,\n                });\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'disasterAlert',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_expansion_emergencyActionGuidelines.js",
    "content": "'use strict';\n\nconst PromiseManager = require('../../core/promiseManager');\nconst { callApi } = require('../../util/common');\n\nfunction getInitialCategoryMap() {\n    return {\n        '01': {\n            '01001': {\n                lang: Lang.Blocks.emergencyActionGuidelines01001,\n                sub: ['01001001', '01001002', '01001003'],\n            },\n            '01002': {\n                lang: Lang.Blocks.emergencyActionGuidelines01002,\n                sub: ['01002001', '01002002', '01002003', '01002004'],\n            },\n            '01003': {\n                lang: Lang.Blocks.emergencyActionGuidelines01003,\n                sub: ['01003001', '01003002', '01003003', '01003004'],\n            },\n            '01004': {\n                lang: Lang.Blocks.emergencyActionGuidelines01004,\n                sub: ['01004001', '01004002', '01004003'],\n            },\n            '01005': {\n                lang: Lang.Blocks.emergencyActionGuidelines01005,\n                sub: ['01005001', '01005002', '01005003', '01005004'],\n            },\n            '01006': {\n                lang: Lang.Blocks.emergencyActionGuidelines01006,\n                sub: ['01006001', '01006002'],\n            },\n            '01007': {\n                lang: Lang.Blocks.emergencyActionGuidelines01007,\n                sub: ['01007001'],\n            },\n            '01008': {\n                lang: Lang.Blocks.emergencyActionGuidelines01008,\n                sub: ['01008001', '01008002', '01008003', '01008004'],\n            },\n            '01009': {\n                lang: Lang.Blocks.emergencyActionGuidelines01009,\n                sub: ['01009001', '01009002', '01009003'],\n            },\n            '01010': {\n                lang: Lang.Blocks.emergencyActionGuidelines01010,\n                sub: ['01010001', '01010002'],\n            },\n            '01011': {\n                lang: Lang.Blocks.emergencyActionGuidelines01011,\n                sub: ['01011007', '01011008', '01011009', '01011010', '01011012'],\n            },\n            '01012': {\n                lang: Lang.Blocks.emergencyActionGuidelines01012,\n                sub: ['01012005', '01012006'],\n            },\n            '01013': {\n                lang: Lang.Blocks.emergencyActionGuidelines01013,\n                sub: ['01013001', '01013002', '01013003', '01013004', '01013005'],\n            },\n            '01014': {\n                lang: Lang.Blocks.emergencyActionGuidelines01014,\n                sub: ['01014001', '01014002', '01014003', '01014004'],\n            },\n            '01015': {\n                lang: Lang.Blocks.emergencyActionGuidelines01015,\n                sub: ['01015001', '01015002', '01015003'],\n            },\n        },\n        '02': {\n            '02001': {\n                lang: Lang.Blocks.emergencyActionGuidelines02001,\n                sub: ['02001001', '02001002', '02001003'],\n            },\n            '02002': {\n                lang: Lang.Blocks.emergencyActionGuidelines02002,\n                sub: ['02002001', '02002002'],\n            },\n            '02003': {\n                lang: Lang.Blocks.emergencyActionGuidelines02003,\n                sub: ['02003001', '02003002', '02003003'],\n            },\n            '02004': {\n                lang: Lang.Blocks.emergencyActionGuidelines02004,\n                sub: ['02004001', '02004002'],\n            },\n            '02005': {\n                lang: Lang.Blocks.emergencyActionGuidelines02005,\n                sub: ['02005001', '02005002', '02005003', '02005004', '02005005'],\n            },\n            '02006': {\n                lang: Lang.Blocks.emergencyActionGuidelines02006,\n                sub: ['02006001', '02006002', '02006003'],\n            },\n            '02007': {\n                lang: Lang.Blocks.emergencyActionGuidelines02007,\n                sub: ['02007001', '02007002', '02007003'],\n            },\n            '02008': {\n                lang: Lang.Blocks.emergencyActionGuidelines02008,\n                sub: ['02008001', '02008002'],\n            },\n            '02009': {\n                lang: Lang.Blocks.emergencyActionGuidelines02009,\n                sub: ['02009001', '02009002', '02009003'],\n            },\n            '02010': {\n                lang: Lang.Blocks.emergencyActionGuidelines02010,\n                sub: ['02010001', '02010002', '02010003', '02010004'],\n            },\n            '02011': {\n                lang: Lang.Blocks.emergencyActionGuidelines02011,\n                sub: [\n                    '02011001',\n                    '02011002',\n                    '02011003',\n                    '02011004',\n                    '02011005',\n                    '02011006',\n                    '02011007',\n                    '02011008',\n                    '02011009',\n                    '02011010',\n                    '02011011',\n                    '02011012',\n                    '02011013',\n                    '02011014',\n                    '02011015',\n                ],\n            },\n            '02012': {\n                lang: Lang.Blocks.emergencyActionGuidelines02012,\n                sub: [\n                    '02012001',\n                    '02012002',\n                    '02012003',\n                    '02012004',\n                    '02012005',\n                    '02012006',\n                    '02012007',\n                ],\n            },\n            '02013': {\n                lang: Lang.Blocks.emergencyActionGuidelines02013,\n                sub: [\n                    '02013001',\n                    '02013002',\n                    '02013003',\n                    '02013004',\n                    '02013005',\n                    '02013007',\n                    '02013008',\n                    '02013009',\n                    '02013010',\n                ],\n            },\n            '02014': {\n                lang: Lang.Blocks.emergencyActionGuidelines02014,\n                sub: ['02014001', '02014002', '02014003'],\n            },\n            '02015': {\n                lang: Lang.Blocks.emergencyActionGuidelines02015,\n                sub: ['02015001', '02015004'],\n            },\n            '02016': {\n                lang: Lang.Blocks.emergencyActionGuidelines02016,\n                sub: ['02016001'],\n            },\n            '02017': {\n                lang: Lang.Blocks.emergencyActionGuidelines02017,\n                sub: ['02017001'],\n            },\n            '02018': {\n                lang: Lang.Blocks.emergencyActionGuidelines02018,\n                sub: ['02018001', '02018002', '02018003'],\n            },\n            '02019': {\n                lang: Lang.Blocks.emergencyActionGuidelines02019,\n                sub: [\n                    '02019001',\n                    '02019002',\n                    '02019003',\n                    '02019004',\n                    '02019005',\n                    '02019006',\n                    '02019007',\n                    '02019008',\n                    '02019009',\n                    '02019010',\n                    '02019011',\n                    '02019012',\n                    '02019013',\n                    '02019014',\n                    '02019015',\n                    '02019016',\n                ],\n            },\n            '02020': {\n                lang: Lang.Blocks.emergencyActionGuidelines02020,\n                sub: ['02020001', '02020002'],\n            },\n            '02021': {\n                lang: Lang.Blocks.emergencyActionGuidelines02021,\n                sub: [\n                    '02021001',\n                    '02021002',\n                    '02021003',\n                    '02021004',\n                    '02021005',\n                    '02021006',\n                    '02021007',\n                    '02021008',\n                    '02021009',\n                    '02021010',\n                    '02021011',\n                ],\n            },\n            '02022': {\n                lang: Lang.Blocks.emergencyActionGuidelines02022,\n                sub: [\n                    '02022007',\n                    '02022008',\n                    '02022009',\n                    '02022010',\n                    '02022011',\n                    '02022012',\n                    '02022013',\n                    '02022014',\n                    '02022015',\n                    '02022016',\n                    '02022017',\n                ],\n            },\n            '02023': {\n                lang: Lang.Blocks.emergencyActionGuidelines02023,\n                sub: ['02023001'],\n            },\n        },\n        '03': {\n            '03002': {\n                lang: Lang.Blocks.emergencyActionGuidelines03002,\n                sub: [\n                    '03002001',\n                    '03002002',\n                    '03002003',\n                    '03002004',\n                    '03002005',\n                    '03002006',\n                    '03002007',\n                ],\n            },\n            '03003': {\n                lang: Lang.Blocks.emergencyActionGuidelines03003,\n                sub: ['03003001', '03003002', '03003003'],\n            },\n            '03004': {\n                lang: Lang.Blocks.emergencyActionGuidelines03004,\n                sub: ['03004001', '03004002', '03004003', '03004004'],\n            },\n            '03005': {\n                lang: Lang.Blocks.emergencyActionGuidelines03005,\n                sub: ['03005001', '03005002'],\n            },\n            '03006': {\n                lang: Lang.Blocks.emergencyActionGuidelines03006,\n                sub: ['03006001', '03006002', '03006003'],\n            },\n            '03007': {\n                lang: Lang.Blocks.emergencyActionGuidelines03007,\n                sub: [\n                    '03007001',\n                    '03007002',\n                    '03007003',\n                    '03007004',\n                    '03007005',\n                    '03007006',\n                    '03007007',\n                ],\n            },\n            '03008': {\n                lang: Lang.Blocks.emergencyActionGuidelines03008,\n                sub: ['03008001'],\n            },\n            '03009': {\n                lang: Lang.Blocks.emergencyActionGuidelines03009,\n                sub: ['03009001'],\n            },\n            '03010': {\n                lang: Lang.Blocks.emergencyActionGuidelines03010,\n                sub: ['03010001'],\n            },\n            '03011': {\n                lang: Lang.Blocks.emergencyActionGuidelines03011,\n                sub: ['03011001'],\n            },\n            '03012': {\n                lang: Lang.Blocks.emergencyActionGuidelines03012,\n                sub: ['03012001'],\n            },\n            '03013': {\n                lang: Lang.Blocks.emergencyActionGuidelines03013,\n                sub: ['03013001', '03013002', '03013003', '03013004', '03013005'],\n            },\n            '03014': {\n                lang: Lang.Blocks.emergencyActionGuidelines03014,\n                sub: ['03014001', '03014002', '03014003', '03014004', '03014005', '03014006'],\n            },\n            '03015': {\n                lang: Lang.Blocks.emergencyActionGuidelines03015,\n                sub: [\n                    '03015001',\n                    '03015002',\n                    '03015003',\n                    '03015004',\n                    '03015005',\n                    '03015006',\n                    '03015007',\n                ],\n            },\n            '03016': {\n                lang: Lang.Blocks.emergencyActionGuidelines03016,\n                sub: ['03016001', '03016002'],\n            },\n        },\n    };\n}\n\nconst defaultCategory = {\n    '01': '01001',\n    '02': '02001',\n    '03': '03002',\n};\n\nEntry.EXPANSION_BLOCK.emergencyActionGuidelines = {\n    name: 'emergencyActionGuidelines',\n    imageName: 'guideline.png',\n    title: {\n        ko: '국민행동요령',\n        en: 'Emergency action guidelines',\n    },\n    titleKey: 'template.emergencyActionGuidelines_title_text',\n    description: Lang.Msgs.expansion_emergencyActionGuidelines_description,\n    descriptionKey: 'Msgs.expansion_emergencyActionGuidelines_description',\n    isInitialized: false,\n    init() {\n        if (this.isInitialized) {\n            return;\n        }\n        Entry.EXPANSION_BLOCK.emergencyActionGuidelines.isInitialized = true;\n    },\n    api: '/api/expansionBlock/emergencyActionGuidelines',\n    apiType: '01',\n};\n\nconst getGuideline = (params, defaultValue, index = null) => {\n    const key = `emergencyActionGuidelines-${params.category}-${params.subCategory}`;\n    const promiseManager = new PromiseManager();\n    const job = promiseManager\n        // eslint-disable-next-line new-cap\n        .Promise((resolve) => {\n            callApi(key, {\n                // eslint-disable-next-line max-len\n                url: `${Entry.EXPANSION_BLOCK.emergencyActionGuidelines.api}/${params.category}/${params.subCategory}`,\n            })\n                .then((result) => {\n                    if (result) {\n                        const items = result.data.body.filter(\n                            (i) =>\n                                i.hasOwnProperty('actRmks') && i.safety_cate3 == params.subCategory2\n                        );\n                        if (index) {\n                            return resolve(items[index - 1].actRmks);\n                        }\n                        return resolve(items.length);\n                    }\n                    return resolve(defaultValue);\n                })\n                .catch(() => resolve(defaultValue));\n        })\n        .catch(() => defaultValue);\n\n    return job;\n};\n\nEntry.EXPANSION_BLOCK.emergencyActionGuidelines.getBlocks = function () {\n    const categoryMap = getInitialCategoryMap();\n    const categoryDisasterMap = getInitialCategoryMap();\n    const getCategories = function (cate1) {\n        return Object.keys(categoryMap[cate1]).map((cate2) => [\n            categoryMap[cate1][cate2].lang,\n            cate2,\n        ]);\n    };\n\n    const getCategory = (cate1 = '01', isPython) => {\n        const param = {\n            type: 'Dropdown',\n            options: getCategories(cate1),\n            value: defaultCategory[cate1],\n            fontSize: 11,\n            bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n            arrowColor: EntryStatic.colorSet.common.WHITE,\n            dropdownSync: 'emergencyAction',\n        };\n        if (isPython) {\n            param.converter = Entry.block.converters.returnStringValue;\n        }\n        return param;\n    };\n\n    const getSubCategory = (cate1 = '01', isPython = false) => {\n        const param = {\n            type: 'DropdownDynamic',\n            value: null,\n            menuName() {\n                const value = this.getTargetValue('emergencyAction');\n                if (!value) {\n                    return [[Lang.Blocks.no_target, 'null']];\n                }\n                return categoryMap[cate1][value].sub.map((category) => [\n                    Lang.Blocks[`emergencyActionGuidelines${category}`],\n                    category,\n                ]);\n            },\n            needDeepCopy: true,\n            fontSize: 11,\n            bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n            arrowColor: EntryStatic.colorSet.common.WHITE,\n            defaultValue: (value, options) => {\n                if (options.length) {\n                    return options[0][1];\n                }\n                return null;\n            },\n        };\n        if (isPython) {\n            param.converter = Entry.block.converters.returnStringValue;\n        }\n        return param;\n    };\n\n    return {\n        emergencyActionGuidelines_title: {\n            template: '%1',\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.emergencyActionGuidelines_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'emergencyActionGuidelines_title',\n            },\n            class: 'emergencyActionGuidelines',\n            isNotFor: ['emergencyActionGuidelines'],\n            events: {},\n        },\n        count_disaster_guideline: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [getCategory('01'), getSubCategory('01')],\n            events: {},\n            def: {\n                params: [getCategory('01').value, null],\n                type: 'count_disaster_guideline',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value'],\n                type: 'count_disaster_guideline',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n            },\n            class: 'emergencyActionGuidelines',\n            isNotFor: ['emergencyActionGuidelines'],\n            func(sprite, script) {\n                const params = {\n                    category: '01',\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getGuideline(params, 0);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n        get_disaster_guideline: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                getCategory('01'),\n                getSubCategory('01'),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [getCategory('01').value, null, 1],\n                type: 'get_disaster_guideline',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_disaster_guideline',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n                NUMBER: 2,\n            },\n            class: 'emergencyActionGuidelines',\n            isNotFor: ['emergencyActionGuidelines'],\n            func(sprite, script) {\n                const number = script.getStringValue('NUMBER', script);\n                const defaultValue = Lang.Blocks.no_data;\n                const params = {\n                    category: '01',\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getGuideline(params, defaultValue, number);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n        count_social_disaster_guideline: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [getCategory('02'), getSubCategory('02')],\n            events: {},\n            def: {\n                params: [getCategory('02').value, null],\n                type: 'count_social_disaster_guideline',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value'],\n                type: 'count_social_disaster_guideline',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n            },\n            class: 'emergencyActionGuidelines',\n            isNotFor: ['emergencyActionGuidelines'],\n            func(sprite, script) {\n                const params = {\n                    category: '02',\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getGuideline(params, 0);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n        get_social_disaster_guideline: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                getCategory('02'),\n                getSubCategory('02'),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [getCategory('02').value, null, 1],\n                type: 'get_social_disaster_guideline',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_social_disaster_guideline',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n                NUMBER: 2,\n            },\n            class: 'emergencyActionGuidelines',\n            isNotFor: ['emergencyActionGuidelines'],\n            func(sprite, script) {\n                const number = script.getStringValue('NUMBER', script);\n                const defaultValue = Lang.Blocks.no_data;\n                const params = {\n                    category: '02',\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getGuideline(params, defaultValue, number);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n        count_safety_accident_guideline: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [getCategory('03'), getSubCategory('03')],\n            events: {},\n            def: {\n                params: [getCategory('03').value, null],\n                type: 'count_safety_accident_guideline',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value'],\n                type: 'count_safety_accident_guideline',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n            },\n            class: 'emergencyActionGuidelines',\n            isNotFor: ['emergencyActionGuidelines'],\n            func(sprite, script) {\n                const params = {\n                    category: '03',\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getGuideline(params, 0);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n        get_safety_accident_guideline: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                getCategory('03'),\n                getSubCategory('03'),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [getCategory('03').value, null, 1],\n                type: 'get_safety_accident_guideline',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_safety_accident_guideline',\n            },\n            paramsKeyMap: {\n                CATEGORY: 0,\n                SUB_CATEGORY: 1,\n                NUMBER: 2,\n            },\n            class: 'emergencyActionGuidelines',\n            isNotFor: ['emergencyActionGuidelines'],\n            func(sprite, script) {\n                const number = script.getStringValue('NUMBER', script);\n                const defaultValue = Lang.Blocks.no_data;\n                const params = {\n                    category: '03',\n                    subCategory: script.getField('CATEGORY', script),\n                    subCategory2: script.getField('SUB_CATEGORY', script),\n                };\n\n                return getGuideline(params, defaultValue, number);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'emergencyActionGuidelines',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_expansion_festival.js",
    "content": "'use strict';\n\nconst PromiseManager = require('../../core/promiseManager');\nconst { callApi } = require('../../util/common');\n\nfunction getLocationMap() {\n    return {\n        Seoul: {\n            code: 1,\n            sub: [\n                '강남구',\n                '강동구',\n                '강북구',\n                '강서구',\n                '관악구',\n                '광진구',\n                '구로구',\n                '금천구',\n                '노원구',\n                '도봉구',\n                '동대문구',\n                '동작구',\n                '마포구',\n                '서대문구',\n                '서초구',\n                '성동구',\n                '성북구',\n                '송파구',\n                '양천구',\n                '영등포구',\n                '용산구',\n                '은평구',\n                '종로구',\n                '중구',\n                '중랑구',\n            ],\n        },\n        Incheon: {\n            code: 2,\n            sub: [\n                '강화군',\n                '계양구',\n                '남구',\n                '남동구',\n                '동구',\n                '부평구',\n                '서구',\n                '연수구',\n                '옹진군',\n                '중구',\n            ],\n        },\n        Daejeon: {\n            code: 3,\n            sub: ['대덕구', '동구', '서구', '유성구', '중구'],\n        },\n        Daegu: {\n            code: 4,\n            sub: ['남구', '달서구', '달성군', '동구', '북구', '서구', '수성구', '중구'],\n        },\n        Gwangju: {\n            code: 5,\n            sub: ['광산구', '남구', '동구', '북구', '서구'],\n        },\n\n        Busan: {\n            code: 6,\n            sub: [\n                '강서구',\n                '금정구',\n                '기장군',\n                '남구',\n                '동구',\n                '동래구',\n                '부산진구',\n                '북구',\n                '사상구',\n                '사하구',\n                '서구',\n                '수영구',\n                '연제구',\n                '영도구',\n                '중구',\n                '해운대구',\n            ],\n        },\n        Ulsan: {\n            code: 7,\n            sub: ['중구', '남구', '동구', '북구', '울주군'],\n        },\n        Sejong: {\n            code: 8,\n            sub: ['세종특별자치시'],\n        },\n        'Gyeonggi-do': {\n            code: 31,\n            sub: [\n                '가평군',\n                '고양시',\n                '과천시',\n                '광명시',\n                '광주시',\n                '구리시',\n                '군포시',\n                '김포시',\n                '남양주시',\n                '동두천시',\n                '부천시',\n                '성남시',\n                '수원시',\n                '시흥시',\n                '안산시',\n                '안성시',\n                '안양시',\n                '양주시',\n                '양평군',\n                '여주시',\n                '연천군',\n                '오산시',\n                '용인시',\n                '의왕시',\n                '의정부시',\n                '이천시',\n                '파주시',\n                '평택시',\n                '포천시',\n                '하남시',\n                '화성시',\n            ],\n        },\n        Gangwon: {\n            code: 32,\n            sub: [\n                '강릉시',\n                '고성군',\n                '동해시',\n                '삼척시',\n                '속초시',\n                '양구군',\n                '양양군',\n                '영월군',\n                '원주시',\n                '인제군',\n                '정선군',\n                '철원군',\n                '춘천시',\n                '태백시',\n                '평창군',\n                '홍천군',\n                '화천군',\n                '횡성군',\n            ],\n        },\n        'Chungcheongbuk-do': {\n            code: 33,\n            sub: [\n                '괴산군',\n                '단양군',\n                '보은군',\n                '영동군',\n                '옥천군',\n                '음성군',\n                '제천시',\n                '진천군',\n                '청원군',\n                '청주시',\n                '충주시',\n                '증평군',\n            ],\n        },\n        'Chungcheongnam-do': {\n            code: 34,\n            sub: [\n                '공주시',\n                '금산군',\n                '논산시',\n                '당진시',\n                '보령시',\n                '부여군',\n                '서산시',\n                '서천군',\n                '아산시',\n                '예산군',\n                '천안시',\n                '청양군',\n                '태안군',\n                '홍성군',\n                '계룡시',\n            ],\n        },\n        'Gyeongsangbuk-do': {\n            code: 35,\n            sub: [\n                '경산시',\n                '경주시',\n                '고령군',\n                '구미시',\n                '군위군',\n                '김천시',\n                '문경시',\n                '봉화군',\n                '상주시',\n                '성주군',\n                '안동시',\n                '영덕군',\n                '영양군',\n                '영주시',\n                '영천시',\n                '예천군',\n                '울릉군',\n                '울진군',\n                '의성군',\n                '청도군',\n                '청송군',\n                '칠곡군',\n                '포항시',\n            ],\n        },\n        'Gyeongsangnam-do': {\n            code: 36,\n            sub: [\n                '거제시',\n                '거창군',\n                '고성군',\n                '김해시',\n                '남해군',\n                '마산시',\n                '밀양시',\n                '사천시',\n                '산청군',\n                '양산시',\n                '의령군',\n                '진주시',\n                '진해시',\n                '창녕군',\n                '창원시',\n                '통영시',\n                '하동군',\n                '함안군',\n                '함양군',\n                '합천군',\n            ],\n        },\n        'Jeollabuk-do': {\n            code: 37,\n            sub: [\n                '고창군',\n                '군산시',\n                '김제시',\n                '남원시',\n                '무주군',\n                '부안군',\n                '순창군',\n                '완주군',\n                '익산시',\n                '임실군',\n                '장수군',\n                '전주시',\n                '정읍시',\n                '진안군',\n            ],\n        },\n        'Jeollanam-do': {\n            code: 38,\n            sub: [\n                '강진군',\n                '고흥군',\n                '곡성군',\n                '광양시',\n                '구례군',\n                '나주시',\n                '담양군',\n                '목포시',\n                '무안군',\n                '보성군',\n                '순천시',\n                '신안군',\n                '여수시',\n                '영광군',\n                '영암군',\n                '완도군',\n                '장성군',\n                '장흥군',\n                '진도군',\n                '함평군',\n                '해남군',\n                '화순군',\n            ],\n        },\n        Jeju: {\n            code: 39,\n            sub: ['남제주군', '북제주군', '서귀포시', '제주시'],\n        },\n    };\n}\n\nEntry.EXPANSION_BLOCK.festival = {\n    name: 'festival',\n    imageName: 'festival.png',\n    title: {\n        ko: '행사',\n        en: 'festival',\n        jp: 'イベント',\n    },\n    titleKey: 'template.festival_title_text',\n    description: Lang.Msgs.expansion_festival_description,\n    descriptionKey: 'Msgs.expansion_festival_description',\n    isInitialized: false,\n    init() {\n        if (this.isInitialized) {\n            return;\n        }\n        Entry.EXPANSION_BLOCK.festival.isInitialized = true;\n    },\n    api: '/api/expansionBlock/ko/festival',\n    locationMap: getLocationMap(),\n    infoTypeMap: {\n        title: 'title',\n        address: 'addr1',\n        start_date: 'eventstartdate',\n        end_date: 'eventenddate',\n        coordinatex: 'mapx',\n        coordinatey: 'mapy',\n        area: 'sigungucode',\n        homepage: 'homepage',\n        overview: 'overview',\n    },\n    strip(html) {\n        return Entry.Utils.extractTextFromHTML(html);\n    },\n    monthMap: {\n        January: 1,\n        'Febuary ': 2,\n        March: 3,\n        April: 4,\n        May: 5,\n        June: 6,\n        July: 7,\n        August: 8,\n        September: 9,\n        October: 10,\n        November: 11,\n        December: 12,\n    },\n};\n\nEntry.EXPANSION_BLOCK.festival.getBlocks = function () {\n    const params = {\n        getLocation(isPython) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.location_seoul, 'Seoul'],\n                    [Lang.Blocks.location_gangwon, 'Gangwon'],\n                    [Lang.Blocks.location_gyeonggi, 'Gyeonggi-do'],\n                    [Lang.Blocks.location_gyeongsangnam, 'Gyeongsangnam-do'],\n                    [Lang.Blocks.location_gyeongsangbuk, 'Gyeongsangbuk-do'],\n                    [Lang.Blocks.location_gwangju, 'Gwangju'],\n                    [Lang.Blocks.location_daegu, 'Daegu'],\n                    [Lang.Blocks.location_daejeon, 'Daejeon'],\n                    [Lang.Blocks.location_busan, 'Busan'],\n                    [Lang.Blocks.location_sejong, 'Sejong'],\n                    [Lang.Blocks.location_ulsan, 'Ulsan'],\n                    [Lang.Blocks.location_incheon, 'Incheon'],\n                    [Lang.Blocks.location_jeollanam, 'Jeollanam-do'],\n                    [Lang.Blocks.location_jeollabuk, 'Jeollabuk-do'],\n                    [Lang.Blocks.location_jeju, 'Jeju'],\n                    [Lang.Blocks.location_chungcheongnam, 'Chungcheongnam-do'],\n                    [Lang.Blocks.location_chungcheongbuk, 'Chungcheongbuk-do'],\n                ],\n                value: 'Seoul',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getMonth(isPython) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Menus.jan, 'January'],\n                    [Lang.Menus.feb, 'Febuary '],\n                    [Lang.Menus.mar, 'March'],\n                    [Lang.Menus.apr, 'April'],\n                    [Lang.Menus.may, 'May'],\n                    [Lang.Menus.jun, 'June'],\n                    [Lang.Menus.jul, 'July'],\n                    [Lang.Menus.aug, 'August'],\n                    [Lang.Menus.sep, 'September'],\n                    [Lang.Menus.oct, 'October'],\n                    [Lang.Menus.nov, 'November'],\n                    [Lang.Menus.dec, 'December'],\n                ],\n                value: 'January',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getInfoType(isPython) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.EXPANSION_FESTIVAL_title, 'title'],\n                    [Lang.Blocks.EXPANSION_FESTIVAL_area, 'area'],\n                    [Lang.Blocks.EXPANSION_FESTIVAL_start_date, 'start_date'],\n                    [Lang.Blocks.EXPANSION_FESTIVAL_end_date, 'end_date'],\n                    [Lang.Blocks.EXPANSION_FESTIVAL_address, 'address'],\n                    //[Lang.Blocks.EXPANSION_FESTIVAL_coordinate, 'coordinate'],\n                    [Lang.Blocks.EXPANSION_FESTIVAL_overview, 'overview'],\n                    [Lang.Blocks.EXPANSION_FESTIVAL_homepage, 'homepage'],\n                ],\n                value: 'title',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n    };\n\n    const getDetailInfo = (contentid, defaultValue, infoType) => {\n        const key = `festival.api.detail_${contentid}`;\n        return new PromiseManager().Promise((resolve) => {\n            callApi(key, { url: `${Entry.EXPANSION_BLOCK.festival.api}/${contentid}` })\n                .then((response) => {\n                    let item = response.data.response.body.items.item;\n                    if (Array.isArray(item)) {\n                        item = item[0];\n                    }\n                    if (item && item[infoType]) {\n                        return resolve(Entry.EXPANSION_BLOCK.festival.strip(item[infoType]));\n                    }\n                    return resolve(defaultValue);\n                })\n                .catch(() => resolve(defaultValue));\n        });\n    };\n\n    const getFestivalCount = (params, defaultValue) => {\n        const key = `festival.api-${JSON.stringify(params)}`;\n        return new PromiseManager().Promise((resolve) => {\n            callApi(key, { url: Entry.EXPANSION_BLOCK.festival.api, params })\n                .then((result) => {\n                    if (result && result.hasOwnProperty('data')) {\n                        return resolve(result?.data?.response?.body?.totalCount);\n                    }\n                    resolve(defaultValue);\n                })\n                .catch(() => resolve(defaultValue));\n        });\n    };\n\n    const getFestivals = (number, params, defaultValue) => {\n        if (number < 1) {\n            return defaultValue;\n        }\n\n        const num = number % 10 || 10;\n        params.page = Math.floor((number - 1) / 10 + 1);\n        const key = `festival.api-${JSON.stringify(params)}`;\n        return new PromiseManager().Promise((resolve) => {\n            callApi(key, { url: Entry.EXPANSION_BLOCK.festival.api, params })\n                .then((result) => {\n                    const items = result?.data?.response?.body?.items?.item;\n                    let item = null;\n                    if (items.constructor == Array) {\n                        item = items[num - 1];\n                    } else {\n                        item = items;\n                    }\n                    return resolve(item);\n                })\n                .catch(() => resolve(defaultValue));\n        });\n    };\n\n    return {\n        festival_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.festival_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'festival_title',\n            },\n            class: 'festival',\n            isNotFor: ['festival'],\n            events: {},\n        },\n        count_festival: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getLocation(), params.getMonth()],\n            events: {},\n            def: {\n                params: [params.getLocation().value, params.getMonth().value],\n                type: 'count_festival',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value'],\n                type: 'count_festival',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                MONTH: 1,\n            },\n            class: 'festival',\n            isNotFor: ['festival'],\n            func(sprite, script) {\n                const defaultValue = 0;\n                const params = {\n                    area: Entry.EXPANSION_BLOCK.festival.locationMap[\n                        script.getField('LOCATION', script)\n                    ].code,\n                    month: Entry.EXPANSION_BLOCK.festival.monthMap[\n                        script.getField('MONTH', script)\n                    ],\n                    list: 'N',\n                };\n                return getFestivalCount(params, defaultValue);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Event.get_len(%1, %2)',\n                        blockType: 'param',\n                        textParams: [params.getLocation(true), params.getMonth(true)],\n                    },\n                ],\n            },\n            wikiClass: 'festival',\n        },\n        get_festival_info: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                params.getLocation(),\n                params.getMonth(),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getInfoType(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    params.getLocation().value,\n                    params.getMonth().value,\n                    1,\n                    params.getInfoType().value,\n                ],\n                type: 'get_festival_info',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value', 'D&value'],\n                type: 'get_festival_info',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                MONTH: 1,\n                NUMBER: 2,\n                TYPE: 3,\n            },\n            class: 'festival',\n            isNotFor: ['festival'],\n            func(sprite, script) {\n                const number = script.getStringValue('NUMBER', script);\n                const type = script.getField('TYPE', script);\n                const infoType = Entry.EXPANSION_BLOCK.festival.infoTypeMap[type];\n                const location =\n                    Entry.EXPANSION_BLOCK.festival.locationMap[script.getField('LOCATION', script)];\n                const defaultValue = Lang.Blocks.no_data;\n                const params = {\n                    area: location.code,\n                    month: Entry.EXPANSION_BLOCK.festival.monthMap[\n                        script.getField('MONTH', script)\n                    ],\n                };\n\n                return getFestivals(number, params, {}).then((festival) => {\n                    switch (type) {\n                        case 'area':\n                            return location.sub[festival[infoType] - 1] || defaultValue;\n                        case 'homepage':\n                        case 'overview':\n                            return getDetailInfo(festival.contentid, defaultValue, infoType);\n                        default:\n                            return festival[infoType] || defaultValue;\n                    }\n                });\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Event.get_info(%1, %2, %3, %4)',\n                        blockType: 'param',\n                        textParams: [\n                            params.getLocation(true),\n                            params.getMonth(true),\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            params.getInfoType(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'festival',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_expansion_weather.js",
    "content": "'use strict';\nconst { getStateOptions, getCityOptions, locationData } = require('../../util/location');\nconst { callApi } = require('../../util/common');\n\nfunction resolveData(weatherData, type, dateStr) {\n    const defaultData = Entry.EXPANSION_BLOCK.weather.defaultData;\n    try {\n        let key = Entry.EXPANSION_BLOCK.weather.getDate(dateStr);\n        if (type === 'now') {\n            key = Object.keys(weatherData)[0];\n        } else if (type === 'hour') {\n            key = dateStr;\n        }\n        return weatherData[key] || defaultData;\n    } catch (e) {\n        return defaultData;\n    }\n}\n\nEntry.EXPANSION_BLOCK.weather = {\n    isInitialized: false,\n    api: '/api/expansionBlock/weather/',\n    date: new Date(),\n    apiFail: {},\n    name: 'weather',\n    imageName: 'weather.png',\n    title: {\n        ko: '날씨',\n        en: 'weather',\n        jp: '拡張ブロックを追加する',\n    },\n    titleKey: 'template.weather_title_text',\n    description: Lang.Msgs.expansion_weather_description,\n    descriptionKey: 'Msgs.expansion_weather_description',\n    init() {\n        if (this.isInitialized) {\n            return;\n        }\n        Entry.EXPANSION_BLOCK.weather.date = new Date();\n        const localDate = new Date();\n        const localDateYear = localDate.getFullYear();\n        const localDateMonth = String(localDate.getMonth() + 1).padStart(2, '0');\n        const localDateDay = String(localDate.getDate()).padStart(2, '0');\n        // eslint-disable-next-line max-len\n        Entry.EXPANSION_BLOCK.weather.localDate = `${localDateYear}${localDateMonth}${localDateDay}`;\n        Entry.EXPANSION_BLOCK.weather.getData('week', 'Seoul', 'today');\n        Entry.EXPANSION_BLOCK.weather.getData('hour', 'Seoul', '00');\n        Entry.EXPANSION_BLOCK.weather.getData('now', 'Seoul');\n        Entry.EXPANSION_BLOCK.weather.isInitialized = true;\n    },\n    getCityCode(location) {\n        let cityCode = null;\n        if (typeof location === 'string') {\n            cityCode = this.locationMap[location].code;\n        } else {\n            if (location.sub == locationData.initialData[1]) {\n                cityCode = this.locationMap[location.parent].code;\n            } else {\n                cityCode = this.locationMap[location.parent].sub[location.sub];\n            }\n        }\n        return cityCode;\n    },\n    async getData(type, location, dateStr) {\n        let cityCode = null;\n        if (typeof location === 'string') {\n            cityCode = this.locationMap[location].code;\n        } else {\n            if (location.sub == locationData.initialData[1]) {\n                cityCode = this.locationMap[location.parent].code;\n            } else {\n                cityCode = this.locationMap[location.parent].sub[location.sub];\n            }\n        }\n\n        const url = this.api + type;\n        try {\n            const response = await callApi(url, { url });\n            Entry.EXPANSION_BLOCK.weather.apiFail[type] = false;\n            return resolveData(response.data[cityCode], type, dateStr);\n        } catch (e) {\n            Entry.EXPANSION_BLOCK.weather.apiFail[type] = { error: e };\n            return Entry.EXPANSION_BLOCK.weather.defaultData;\n        }\n    },\n    async getDataWithCityCode(type, cityCode, dateStr) {\n        const url = this.api + type;\n        try {\n            const response = await callApi(url, { url });\n            Entry.EXPANSION_BLOCK.weather.apiFail[type] = false;\n            return resolveData(response.data[cityCode], type, dateStr);\n        } catch (e) {\n            Entry.EXPANSION_BLOCK.weather.apiFail[type] = { error: e };\n            return Entry.EXPANSION_BLOCK.weather.defaultData;\n        }\n    },\n    checkWeather(sky_code, weather) {\n        if (Entry.EXPANSION_BLOCK.weather.apiFail.week) {\n            return true;\n        }\n\n        const skyCodeMap = {\n            1: 'sunny', //\"맑음\",\n            2: 'partly_cloudy', //\"구름조금\",\n            3: 'cloudy', //\"흐림\",\n            4: 'rainy', //\"비\",\n            5: 'snowy', //\"눈\",\n            6: 'sleet', //\"눈비\",\n\n            7: 'rainy', //\"소나기\",\n            8: 'snowy', //\"소낙눈\",\n            9: 'cloudy', //\"안개\",\n            10: 'rainy', //\"뇌우\",\n            11: 'cloudy', //\"차차 흐려짐\",\n            12: 'rainy', //\"흐려져 뇌우\",\n            13: 'rainy', //\"흐려져 비\",\n            14: 'snowy', //\"흐려져 눈\",\n            15: 'sleet', //\"흐려져 눈비\",\n            16: 'cloudy', //\"흐린 후 갬\",\n            17: 'rainy', //\"뇌우 후 갬\",\n            18: 'rainy', //\"비 후 갬\",\n            19: 'snowy', //\"눈 후 갬\",\n            20: 'sleet', //\"눈비 후 갬\",\n            21: 'mostly_cloudy', //\"구름많음\",\n            22: 'cloudy',\n        };\n\n        if (skyCodeMap[sky_code]) {\n            return skyCodeMap[sky_code] === weather;\n        } else {\n            return 'sunny' === weather;\n        }\n    },\n    checkFineDust(pm10, finedust) {\n        if (Entry.EXPANSION_BLOCK.weather.apiFail.now) {\n            return true;\n        }\n\n        const fineDustMap = {\n            good: { min: 0, max: 30 },\n            normal: { min: 31, max: 80 },\n            bad: { min: 81, max: 150 },\n            very_bad: { min: 150, max: 9999 },\n        };\n\n        for (const key in fineDustMap) {\n            if (fineDustMap[key].min <= pm10 && pm10 <= fineDustMap[key].max) {\n                return key === finedust;\n            }\n        }\n        return 'very_bad' === finedust;\n    },\n    getDate(key) {\n        Entry.EXPANSION_BLOCK.weather.date = Entry.EXPANSION_BLOCK.weather.date || new Date();\n        const date = new Date(Entry.EXPANSION_BLOCK.weather.date);\n        switch (key) {\n            case 'yesterday':\n                date.setDate(date.getDate() - 1);\n                break;\n            case 'today':\n                break;\n            case 'tomorrow':\n                date.setDate(date.getDate() + 1);\n                break;\n            case 'After_2_days':\n                date.setDate(date.getDate() + 2);\n                break;\n            case 'After_3_days':\n                date.setDate(date.getDate() + 3);\n                break;\n            case 'After_4_days':\n                date.setDate(date.getDate() + 4);\n                break;\n            case 'After_5_days':\n                date.setDate(date.getDate() + 5);\n                break;\n            case 'After_6_days':\n                date.setDate(date.getDate() + 6);\n                break;\n            default:\n                break;\n        }\n        const year = date.getFullYear();\n        const month = String(date.getMonth() + 1).padStart(2, '0');\n        const day = String(date.getDate()).padStart(2, '0');\n        return `${year}${month}${day}`;\n    },\n    locationMap: {\n        Seoul: {\n            code: '1100000000',\n            sub: {\n                jongno_gu: '1111000000',\n                jung_gu: '1114000000',\n                yongsan_gu: '1117000000',\n                seongdong_gu: '1120000000',\n                gwangjin_gu: '1121500000',\n                dongdaemun_gu: '1123000000',\n                jungnang_gu: '1126000000',\n                seongbuk_gu: '1129000000',\n                gangbuk_gu: '1130500000',\n                dobong_gu: '1132000000',\n                nowon_gu: '1135000000',\n                eunpyeong_gu: '1138000000',\n                seodaemun_gu: '1141000000',\n                mapo_gu: '1144000000',\n                yangcheon_gu: '1147000000',\n                gangseo_gu: '1150000000',\n                guro_gu: '1153000000',\n                geumcheon_gu: '1154500000',\n                yeongdeungpo_gu: '1156000000',\n                dongjak_gu: '1159000000',\n                gwanak_gu: '1162000000',\n                seocho_gu: '1165000000',\n                gangnam_gu: '1168000000',\n                songpa_gu: '1171000000',\n                gangdong_gu: '1174000000',\n            },\n        },\n        Busan: {\n            code: '2600000000',\n            sub: {\n                jung_gu: '2611000000',\n                seo_gu: '2614000000',\n                dong_gu: '2617000000',\n                yeongdo_gu: '2620000000',\n                busanjin_gu: '2623000000',\n                dongnae_gu: '2626000000',\n                nam_gu: '2629000000',\n                buk_gu: '2632000000',\n                haeundae_gu: '2635000000',\n                saha_gu: '2638000000',\n                geumjeong_gu: '2641000000',\n                gangseo_gu: '2644000000',\n                yeonje: '2647000000',\n                suyeong_gu: '2650000000',\n                sasang_gu: '2653000000',\n                gijang: '2671000000',\n            },\n        },\n        Daegu: {\n            code: '2700000000',\n            sub: {\n                jung_gu: '2711000000',\n                dong_gu: '2714000000',\n                seo_gu: '2717000000',\n                nam_gu: '2720000000',\n                buk_gu: '2723000000',\n                suseong_gu: '2726000000',\n                dalseo_gu: '2729000000',\n                dalseong: '2771000000',\n                gunwi: '2772000000',\n            },\n        },\n        Incheon: {\n            code: '2800000000',\n            sub: {\n                jung_gu: '2811000000',\n                dong_gu: '2814000000',\n                nam_gu: '2817000000',\n                yeonsu_gu: '2818500000',\n                namdong_gu: '2820000000',\n                bupyeong_gu: '2823700000',\n                gyeyang_gu: '2824500000',\n                seo_gu: '2826000000',\n                ganghwa: '2871000000',\n                ongjin_gun: '2872000000',\n            },\n        },\n        Gwangju: {\n            code: '2900000000',\n            sub: {\n                dong_gu: '2911000000',\n                seo_gu: '2914000000',\n                nam_gu: '2915500000',\n                buk_gu: '2917000000',\n                gwangsan_gu: '2920000000',\n            },\n        },\n        Daejeon: {\n            code: '3000000000',\n            sub: {\n                dong_gu: '3011000000',\n                jung_gu: '3014000000',\n                western: '3017000000',\n                yuseong_gu: '3020000000',\n                daedeok_gu: '3023000000',\n            },\n        },\n        Ulsan: {\n            code: '3100000000',\n            sub: {\n                jung_gu: '3111000000',\n                nam_gu: '3114000000',\n                dong_gu: '3117000000',\n                buk_gu: '3120000000',\n                ulju: '3171000000',\n            },\n        },\n        Sejong: {\n            code: '3600000000',\n            sub: {},\n        },\n\n        'Gyeonggi-do': {\n            code: '4100000000',\n            sub: {\n                suwon_si: '4111000000',\n                seongnam: '4113000000',\n                uijeongbu: '4115000000',\n                anyang_si: '4117000000',\n                bucheon_si: '4119000000',\n                gwangmyeong_si: '4121000000',\n                pyeongtaek_si: '4122000000',\n                dongducheon_si: '4125000000',\n                ansan_si: '4127000000',\n                goyang_si: '4128000000',\n                gwacheon_si: '4129000000',\n                guri: '4131000000',\n                namyangju_si: '4136000000',\n                osan: '4137000000',\n                siheung: '4139000000',\n                gunpo_si: '4141000000',\n                uiwang_si: '4143000000',\n                hanam: '4145000000',\n                yongin_si: '4146000000',\n                paju: '4148000000',\n                icheon: '4150000000',\n                anseong_si: '4155000000',\n                gimpo: '4157000000',\n                hwaseong_si: '4159000000',\n                gwangju: '4161000000',\n                yangju_si: '4163000000',\n                pocheon: '4165000000',\n                yeoju: '4167000000',\n                yeoncheon_gun: '4180000000',\n                gapyeong_gun: '4182000000',\n                yangpyeong: '4183000000',\n            },\n        },\n        Gangwon: {\n            code: '5100000000',\n            sub: {\n                chuncheon: '5111000000',\n                wonju: '5113000000',\n                gangneung_si: '5115000000',\n                donghae: '5117000000',\n                taebaek_si: '5119000000',\n                'sokcho city': '5121000000',\n                samcheok_si: '5123000000',\n                hongcheon: '5172000000',\n                hoengseong_gun: '5173000000',\n                yeongwol_gun: '5175000000',\n                pyeongchang: '5176000000',\n                jeongseon: '5177000000',\n                cheolwon: '5178000000',\n                hwacheon: '5179000000',\n                yanggu: '5180000000',\n                inje: '5181000000',\n                goseong: '5182000000',\n                yangyang: '5183000000',\n            },\n        },\n        'Chungcheongbuk-do': {\n            code: '4300000000',\n            sub: {\n                cheongju: '4311000000',\n                chungju: '4313000000',\n                jecheon: '4315000000',\n                boeun: '4372000000',\n                okcheon: '4373000000',\n                yeongdong: '4374000000',\n                jeungpyeong: '4374500000',\n                jincheon: '4375000000',\n                goesan: '4376000000',\n                eumseong: '4377000000',\n                danyang: '4380000000',\n            },\n        },\n        'Chungcheongnam-do': {\n            code: '4400000000',\n            sub: {\n                cheonan: '4413000000',\n                gongju: '4415000000',\n                boryeong: '4418000000',\n                asan: '4420000000',\n                seosan: '4421000000',\n                nonsan: '4423000000',\n                gyeryong: '4425000000',\n                dangjin: '4427000000',\n                geumsan: '4471000000',\n                buyeo: '4476000000',\n                seocheon: '4477000000',\n                cheongyang: '4479000000',\n                hongseong: '4480000000',\n                yesan: '4481000000',\n                taean: '4482500000',\n            },\n        },\n        'Jeollabuk-do': {\n            code: '4500000000',\n            sub: {\n                jeonju: '4511000000',\n                gunsan_si: '4513000000',\n                iksan: '4514000000',\n                jeongeup: '4518000000',\n                namwon: '4519000000',\n                gimje_si: '4521000000',\n                wanju: '4571000000',\n                jinan: '4572000000',\n                muju: '4573000000',\n                jangsu: '4574000000',\n                imsil: '4575000000',\n                sunchang: '4577000000',\n                gochang: '4579000000',\n                buan: '4580000000',\n            },\n        },\n        // 'Jeollabuk-do': {\n        //     code: '5200000000',\n        //     sub: {\n        //         jeonju: '5211000000',\n        //         gunsan_si: '5213000000',\n        //         iksan: '5214000000',\n        //         jeongeup: '5218000000',\n        //         namwon: '5219000000',\n        //         gimje_si: '5221000000',\n        //         wanju: '5271000000',\n        //         jinan: '5272000000',\n        //         muju: '5273000000',\n        //         jangsu: '5274000000',\n        //         imsil: '5275000000',\n        //         sunchang: '5277000000',\n        //         gochang: '5279000000',\n        //         buan: '5280000000',\n        //     },\n        // },\n        'Jeollanam-do': {\n            code: '4600000000',\n            sub: {\n                mokpo: '4611000000',\n                yosu: '4613000000',\n                suncheon_si: '4615000000',\n                naju: '4617000000',\n                gwangyang_si: '4623000000',\n                damyang: '4671000000',\n                gokseong: '4672000000',\n                gurye: '4673000000',\n                goheung: '4677000000',\n                boseong: '4678000000',\n                hwasun: '4679000000',\n                jangheung: '4680000000',\n                gangjin: '4681000000',\n                haenam: '4682000000',\n                yeongam: '4683000000',\n                muan: '4684000000',\n                hampyeong: '4686000000',\n                yeonggwang: '4687000000',\n                jangseong: '4688000000',\n                wando: '4689000000',\n                jindo: '4690000000',\n                sinan: '4691000000',\n            },\n        },\n        'Gyeongsangbuk-do': {\n            code: '4700000000',\n            sub: {\n                pohang_si: '4711000000',\n                gyeongju_si: '4713000000',\n                gimcheon_si: '4715000000',\n                andong_si: '4717000000',\n                gumi_si: '4719000000',\n                yeongju_si: '4721000000',\n                yeongcheon_si: '4723000000',\n                sangju_si: '4725000000',\n                mungyeong_si: '4728000000',\n                gyeongsan_si: '4729000000',\n                uiseong: '4773000000',\n                cheongsong: '4775000000',\n                goryong: '4776000000',\n                yeongdeok: '4777000000',\n                cheongdo: '4782000000',\n                golyeong: '4783000000',\n                seongju: '4784000000',\n                chilgok: '4785000000',\n                yecheon: '4790000000',\n                bonghwa: '4792000000',\n                uljin: '4793000000',\n                ulleung: '4794000000',\n            },\n        },\n        'Gyeongsangnam-do': {\n            code: '4800000000',\n            sub: {\n                changwon_si: '4811000000',\n                jinju: '4817000000',\n                tongyeong_si: '4822000000',\n                sacheon_si: '4824000000',\n                gimhae_si: '4825000000',\n                miryang_si: '4827000000',\n                geoje_si: '4831000000',\n                yangsan_si: '4833000000',\n                uiryeong: '4872000000',\n                haman: '4873000000',\n                changnyeong: '4874000000',\n                goseong: '4882000000',\n                namhae: '4884000000',\n                hadong: '4885000000',\n                sancheong: '4886000000',\n                hamyang: '4887000000',\n                geochang: '4888000000',\n                hapcheon: '4889000000',\n            },\n        },\n        Jeju: {\n            code: '5000000000',\n            sub: {\n                jeju_si: '5011000000',\n                seogwipo: '5013000000',\n            },\n        },\n    },\n    propertyMap: {\n        //날짜별\n        the_lowest_temperature: 'min_temp',\n        the_highest_temperature: 'max_temp',\n        humidity: 'humidity',\n        precipitation: 'rain',\n        precipitation_probability: 'rain_p',\n        wind_speed: 'windspd',\n        //현재\n        temperature: 'temp',\n        concentration_of_fine_dust: 'pm10',\n    },\n    // 시간만 강수량 파라미터가 달라서 따로 맵을 만듬.\n    propertyHourMap: {\n        //날짜별\n        the_lowest_temperature: 'min_temp',\n        the_highest_temperature: 'max_temp',\n        humidity: 'humidity',\n        precipitation: 'rainAmt',\n        precipitation_probability: 'rain',\n        wind_speed: 'windspd',\n        //현재\n        temperature: 'temp',\n        concentration_of_fine_dust: 'pm10',\n    },\n    defaultData: {\n        //week\n        //aplYmd: 20180905,\n        max_temp: 0,\n        min_temp: 0,\n        sky: '구름조금',\n        sky_code: '2',\n        winddir: 'W',\n        windspd: 0,\n        rain: 0,\n        rain_p: 0,\n        humidity: 0,\n        locationCode: '1100000000',\n        updated: '2018-09-05T03:27:42.804Z',\n        //hour\n        //aplYmdt: \"2018090500\",\n        rainAmt: 0,\n        temp: 0,\n        //now\n        pm10: 0,\n        pm10_s: '좋음',\n    },\n};\n\nEntry.EXPANSION_BLOCK.weather.getBlocks = function () {\n    const params = {\n        getDate(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.date_yesterday, 'yesterday'],\n                    [Lang.Blocks.date_today, 'today'],\n                    [Lang.Blocks.date_tomorrow, 'tomorrow'],\n                    [Lang.Blocks.date_after_2_days, 'After_2_days'],\n                    [Lang.Blocks.date_after_3_days, 'After_3_days'],\n                    [Lang.Blocks.date_after_4_days, 'After_4_days'],\n                    [Lang.Blocks.date_after_5_days, 'After_5_days'],\n                    [Lang.Blocks.date_after_6_days, 'After_6_days'],\n                ],\n                value: 'today',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getLocation(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: getStateOptions(),\n                value: 'Seoul',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                dropdownSync: 'weather',\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getSubLocation(isPython = false) {\n            const param = {\n                type: 'DropdownDynamic',\n                value: null,\n                menuName() {\n                    const value = this.getTargetValue('weather');\n                    if (!value) {\n                        return [[Lang.Blocks.no_target, 'null']];\n                    }\n                    return getCityOptions(value);\n                },\n                needDeepCopy: true,\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n                defaultValue: (value, options) => {\n                    if (options.length) {\n                        return options[0][1];\n                    }\n                    return null;\n                },\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getSky(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.EXPANSION_WEATHER_sunny, 'sunny'],\n                    [Lang.Blocks.EXPANSION_WEATHER_partly_cloudy, 'partly_cloudy'],\n                    [Lang.Blocks.EXPANSION_WEATHER_mostly_cloudy, 'mostly_cloudy'],\n                    [Lang.Blocks.EXPANSION_WEATHER_cloudy, 'cloudy'],\n                    [Lang.Blocks.EXPANSION_WEATHER_rainy, 'rainy'],\n                    [Lang.Blocks.EXPANSION_WEATHER_sleet, 'sleet'],\n                    [Lang.Blocks.EXPANSION_WEATHER_snowy, 'snowy'],\n                ],\n                value: 'sunny',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getFineDust(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.EXPANSION_WEATHER_finedust_good, 'good'],\n                    [Lang.Blocks.EXPANSION_WEATHER_finedust_normal, 'normal'],\n                    [Lang.Blocks.EXPANSION_WEATHER_finedust_bad, 'bad'],\n                    [Lang.Blocks.EXPANSION_WEATHER_finedust_very_bad, 'very_bad'],\n                ],\n                value: 'good',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getWeatherElements(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.EXPANSION_WEATHER_lowest_temperature, 'the_lowest_temperature'],\n                    [Lang.Blocks.EXPANSION_WEATHER_highest_temperature, 'the_highest_temperature'],\n                    [Lang.Blocks.EXPANSION_WEATHER_humidity, 'humidity'],\n                    [Lang.Blocks.EXPANSION_WEATHER_precipitation, 'precipitation'],\n                    [\n                        Lang.Blocks.EXPANSION_WEATHER_precipitation_probability,\n                        'precipitation_probability',\n                    ],\n                    [Lang.Blocks.EXPANSION_WEATHER_wind_speed, 'wind_speed'],\n                ],\n                value: 'the_lowest_temperature',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getNowWeatherElement(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.EXPANSION_WEATHER_temperature, 'temperature'],\n                    [Lang.Blocks.EXPANSION_WEATHER_finedust, 'concentration_of_fine_dust'],\n                ],\n                value: 'temperature',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getTimeWeatherElement(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    [Lang.Blocks.EXPANSION_WEATHER_temperature, 'temperature'],\n                    [Lang.Blocks.EXPANSION_WEATHER_precipitation, 'precipitation'],\n                    [Lang.Blocks.EXPANSION_WEATHER_wind_speed, 'wind_speed'],\n                    [Lang.Blocks.EXPANSION_WEATHER_humidity, 'humidity'],\n                    [\n                        Lang.Blocks.EXPANSION_WEATHER_precipitation_probability,\n                        'precipitation_probability',\n                    ],\n                ],\n                value: 'temperature',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringValue;\n            }\n            return param;\n        },\n        getTime(isPython = false) {\n            const param = {\n                type: 'Dropdown',\n                options: [\n                    ['00', '00'],\n                    ['03', '03'],\n                    ['06', '06'],\n                    ['09', '09'],\n                    ['12', '12'],\n                    ['15', '15'],\n                    ['18', '18'],\n                    ['21', '21'],\n                ],\n                value: '00',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.EXPANSION,\n                arrowColor: EntryStatic.colorSet.common.WHITE,\n            };\n            if (isPython) {\n                param.converter = Entry.block.converters.returnStringOrNumberByValue;\n            }\n            return param;\n        },\n    };\n\n    function pad2(n) {\n        return n < 10 ? `0${n}` : n;\n    }\n\n    return {\n        weather_title: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.weather_title_text,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'center',\n                },\n            ],\n            def: {\n                type: 'weather_title',\n            },\n            class: 'weather',\n            isNotFor: ['weather'],\n            events: {},\n        },\n        check_city_weather: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                params.getDate(),\n                params.getLocation(),\n                params.getSubLocation(),\n                params.getSky(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    params.getDate().value,\n                    params.getLocation().value,\n                    params.getSubLocation().value,\n                    params.getSky().value,\n                ],\n                type: 'check_city_weather',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', 'D&value', null],\n                type: 'check_city_weather',\n            },\n            paramsKeyMap: {\n                DATE: 0,\n                LOCATION: 1,\n                SUBLOCATION: 2,\n                WEATHER: 3,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const location = {\n                    parent: script.getField('LOCATION', script),\n                    sub: script.getField('SUBLOCATION', script),\n                };\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'week',\n                    location,\n                    script.getField('DATE', script)\n                );\n\n                return Entry.EXPANSION_BLOCK.weather.checkWeather(\n                    apiResult.sky_code,\n                    script.getField('WEATHER', script)\n                );\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Weather.is_condition_sunny(%1, %2, %3)',\n                        params: [null, null, null, 'sunny'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_condition_partly_cloudy(%1, %2, %3)',\n                        params: [null, null, null, 'partly_cloudy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_condition_mostly_cloudy(%1, %2, %3)',\n                        params: [null, null, null, 'mostly_cloudy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_condition_cloudy(%1, %2, %3)',\n                        params: [null, null, null, 'cloudy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_condition_rainy(%1, %2, %3)',\n                        params: [null, null, null, 'rainy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_condition_sleet(%1, %2, %3)',\n                        params: [null, null, null, 'sleet'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_condition_snowy(%1, %2, %3)',\n                        params: [null, null, null, 'snowy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        check_city_finedust: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [params.getLocation(), params.getSubLocation(), params.getFineDust()],\n            events: {},\n            def: {\n                params: [params.getLocation().value, null, params.getFineDust().value],\n                type: 'check_city_finedust',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'check_city_finedust',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                SUBLOCATION: 1,\n                FINEDUST: 2,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const location = {\n                    parent: script.getField('LOCATION', script),\n                    sub: script.getField('SUBLOCATION', script),\n                };\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'now',\n                    location,\n                    null\n                );\n                return Entry.EXPANSION_BLOCK.weather.checkFineDust(\n                    apiResult.pm10,\n                    script.getField('FINEDUST', script)\n                );\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Weather.is_current_finedust_grade_good(%1, %2)',\n                        params: [null, null, 'good'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getFineDust(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_current_finedust_grade_normal(%1, %2)',\n                        params: [null, null, 'normal'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getFineDust(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_current_finedust_grade_bad(%1, %2)',\n                        params: [null, null, 'bad'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getFineDust(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.is_current_finedust_grade_very_bad(%1, %2)',\n                        params: [, null, null, 'very_bad'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getFineDust(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        get_city_weather_data: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                params.getDate(),\n                params.getLocation(),\n                params.getSubLocation(),\n                params.getWeatherElements(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    params.getDate().value,\n                    params.getLocation().value,\n                    null,\n                    params.getWeatherElements().value,\n                ],\n                type: 'get_city_weather_data',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', 'D&value', null],\n                type: 'get_city_weather_data',\n            },\n            paramsKeyMap: {\n                DATE: 0,\n                LOCATION: 1,\n                SUBLOCATION: 2,\n                TYPE: 3,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const location = {\n                    parent: script.getField('LOCATION', script),\n                    sub: script.getField('SUBLOCATION', script),\n                };\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'week',\n                    location,\n                    script.getField('DATE', script)\n                );\n\n                const type =\n                    Entry.EXPANSION_BLOCK.weather.propertyMap[script.getField('TYPE', script)];\n                return apiResult[type];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Weather.get_lowest_temperature(%1, %2, %3)',\n                        params: [null, null, null, 'the_lowest_temperature'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.get_highest_temperature(%1, %2, %3)',\n                        params: [null, null, null, 'the_highest_temperature'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.get_humidity(%1, %2, %3)',\n                        params: [null, null, null, 'humidity'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.get_precipitation(%1, %2, %3)',\n                        params: [null, null, null, 'precipitation'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.get_precipitation_probability(%1, %2, %3)',\n                        params: [null, null, null, 'precipitation_probability'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.get_wind_speed(%1, %2, %3)',\n                        params: [null, null, null, 'wind_speed'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        get_current_city_weather_data: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getLocation(), params.getSubLocation(), params.getNowWeatherElement()],\n            events: {},\n            def: {\n                params: [params.getLocation().value, null, params.getNowWeatherElement().value],\n                type: 'get_current_city_weather_data',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'get_current_city_weather_data',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                SUBLOCATION: 1,\n                TYPE: 2,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            func(sprite, script) {\n                const location = {\n                    parent: script.getField('LOCATION', script),\n                    sub: script.getField('SUBLOCATION', script),\n                };\n                const type =\n                    Entry.EXPANSION_BLOCK.weather.propertyMap[script.getField('TYPE', script)];\n\n                return new Promise((resolve) => {\n                    Entry.EXPANSION_BLOCK.weather\n                        .getData('now', location, null)\n                        .then((data) => resolve(data[type]));\n                });\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Weather.get_current_finedust(%1, %2)',\n                        params: [null, null, 'concentration_of_fine_dust'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getNowWeatherElement(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Weather.get_current_temperature(%1, %2)',\n                        params: [null, null, 'temperature'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getNowWeatherElement(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        get_today_city_temperature: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getLocation(), params.getSubLocation(), params.getTime()],\n            events: {},\n            def: {\n                params: [params.getLocation().value, null, params.getTime().value],\n                type: 'get_today_city_temperature',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_today_city_temperature',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                SUBLOCATION: 1,\n                TIME: 2,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const location = {\n                    parent: script.getField('LOCATION', script),\n                    sub: script.getField('SUBLOCATION', script),\n                };\n                const date = Entry.EXPANSION_BLOCK.weather.localDate;\n                let time = script.getField('TIME', script);\n                // db에 저장하지 않으면서 00시가 없어져서 03시부터 가능..\n                if (time == '00') {\n                    time = '03';\n                }\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'hour',\n                    location,\n                    date + pad2(time - (time % 3))\n                );\n\n                return apiResult.temp;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Weather.get_today_temperature(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            params.getLocation(true),\n                            params.getSubLocation(true),\n                            params.getTime(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n\n        //시군구 추가로 인한 legacy code 기존 블럭유지를 위해 필요.\n        check_weather: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [params.getDate(), params.getLocation(), params.getSky()],\n            events: {},\n            def: {\n                params: [params.getDate().value, params.getLocation().value, params.getSky().value],\n                type: 'check_weather',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'check_weather',\n            },\n            paramsKeyMap: {\n                DATE: 0,\n                LOCATION: 1,\n                WEATHER: 2,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'week',\n                    script.getField('LOCATION', script),\n                    script.getField('DATE', script)\n                );\n                return Entry.EXPANSION_BLOCK.weather.checkWeather(\n                    apiResult.sky_code,\n                    script.getField('WEATHER', script)\n                );\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Legacy.Weather.is_condition_sunny(%1, %2)',\n                        params: [null, null, 'sunny'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_condition_partly_cloudy(%1, %2)',\n                        params: [null, null, 'partly_cloudy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_condition_mostly_cloudy(%1, %2)',\n                        params: [null, null, 'mostly_cloudy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_condition_cloudy(%1, %2)',\n                        params: [null, null, 'cloudy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_condition_rainy(%1, %2)',\n                        params: [null, null, 'rainy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_condition_sleet(%1, %2)',\n                        params: [null, null, 'sleet'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_condition_snowy(%1, %2)',\n                        params: [null, null, 'snowy'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getSky(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        check_finedust: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [params.getLocation(), params.getFineDust()],\n            events: {},\n            def: {\n                params: [params.getLocation().value, params.getFineDust().value],\n                type: 'check_finedust',\n            },\n            pyHelpDef: {\n                params: ['B&value', null],\n                type: 'check_finedust',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                FINEDUST: 1,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'now',\n                    script.getField('LOCATION', script),\n                    null\n                );\n                return Entry.EXPANSION_BLOCK.weather.checkFineDust(\n                    apiResult.pm10,\n                    script.getField('FINEDUST', script)\n                );\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Legacy.Weather.is_current_finedust_grade_good(%1)',\n                        params: [null, 'good'],\n                        blockType: 'param',\n                        textParams: [params.getLocation(true), params.getFineDust(true)],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_current_finedust_grade_normal(%1)',\n                        params: [null, 'normal'],\n                        blockType: 'param',\n                        textParams: [params.getLocation(true), params.getFineDust(true)],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_current_finedust_grade_bad(%1)',\n                        params: [null, 'bad'],\n                        blockType: 'param',\n                        textParams: [params.getLocation(true), params.getFineDust(true)],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.is_current_finedust_grade_very_bad(%1)',\n                        params: [, null, 'very_bad'],\n                        blockType: 'param',\n                        textParams: [params.getLocation(true), params.getFineDust(true)],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        get_weather_data: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getDate(), params.getLocation(), params.getWeatherElements()],\n            events: {},\n            def: {\n                params: [\n                    params.getDate().value,\n                    params.getLocation().value,\n                    params.getWeatherElements().value,\n                ],\n                type: 'get_weather_data',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'get_weather_data',\n            },\n            paramsKeyMap: {\n                DATE: 0,\n                LOCATION: 1,\n                TYPE: 2,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'week',\n                    script.getField('LOCATION', script),\n                    script.getField('DATE', script)\n                );\n                const type =\n                    Entry.EXPANSION_BLOCK.weather.propertyMap[script.getField('TYPE', script)];\n                return apiResult[type];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Legacy.Weather.get_lowest_temperature(%1, %2)',\n                        params: [null, null, 'the_lowest_temperature'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.get_highest_temperature(%1, %2)',\n                        params: [null, null, 'the_highest_temperature'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.get_humidity(%1, %2)',\n                        params: [null, null, 'humidity'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.get_precipitation(%1, %2)',\n                        params: [null, null, 'precipitation'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.get_precipitation_probability(%1, %2)',\n                        params: [null, null, 'precipitation_probability'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.get_wind_speed(%1, %2)',\n                        params: [null, null, 'wind_speed'],\n                        blockType: 'param',\n                        textParams: [\n                            params.getDate(true),\n                            params.getLocation(true),\n                            params.getWeatherElements(true),\n                        ],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        get_current_weather_data: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getLocation(), params.getNowWeatherElement()],\n            events: {},\n            def: {\n                params: [params.getLocation().value, params.getNowWeatherElement().value],\n                type: 'get_current_weather_data',\n            },\n            pyHelpDef: {\n                params: ['B&value', null],\n                type: 'get_current_weather_data',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                TYPE: 1,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'now',\n                    script.getField('LOCATION', script),\n                    null\n                );\n                const type =\n                    Entry.EXPANSION_BLOCK.weather.propertyMap[script.getField('TYPE', script)];\n\n                return apiResult[type];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Legacy.Weather.get_current_finedust(%1)',\n                        params: [null, 'concentration_of_fine_dust'],\n                        blockType: 'param',\n                        textParams: [params.getLocation(true), params.getNowWeatherElement(true)],\n                    },\n                    {\n                        syntax: 'Legacy.Weather.get_current_temperature(%1)',\n                        params: [null, 'temperature'],\n                        blockType: 'param',\n                        textParams: [params.getLocation(true), params.getNowWeatherElement(true)],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        get_today_temperature: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [params.getLocation(), params.getTime()],\n            events: {},\n            def: {\n                params: [params.getLocation().value, params.getTime().value],\n                type: 'get_today_temperature',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value'],\n                type: 'get_today_temperature',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                TIME: 1,\n            },\n            class: 'weather_legacy',\n            isNotFor: ['weather_legacy'],\n            async func(sprite, script) {\n                const date = Entry.EXPANSION_BLOCK.weather.localDate;\n                let time = script.getField('TIME', script);\n                // db에 저장하지 않으면서 00시가 없어져서 03시부터 가능..\n                if (time == '00') {\n                    time = '03';\n                }\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getData(\n                    'hour',\n                    script.getField('LOCATION', script),\n                    date + pad2(time - (time % 3))\n                );\n\n                return apiResult.temp;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Legacy.Weather.get_today_temperature(%1, %2)',\n                        blockType: 'param',\n                        textParams: [params.getLocation(true), params.getTime(true)],\n                    },\n                ],\n            },\n            wikiClass: 'weather',\n        },\n        get_cur_weather: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                ],\n                type: 'get_cur_weather',\n            },\n            pyHelpDef: {\n                params: ['A&value'],\n                type: 'get_cur_weather',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n            },\n            class: 'weather',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'now',\n                    location,\n                    null\n                );\n                return apiResult.sky;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        get_cur_wind: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                ],\n                type: 'get_cur_wind',\n            },\n            pyHelpDef: {\n                params: ['A&value'],\n                type: 'get_cur_wind',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n            },\n            class: 'weather',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'now',\n                    location,\n                    null\n                );\n                return apiResult.winddir;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        get_cur_weather_data: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getNowWeatherElement(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                    params.getNowWeatherElement().value,\n                ],\n                type: 'get_cur_weather_data',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value'],\n                type: 'get_cur_weather_data',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                TYPE: 1,\n            },\n            class: 'weather',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const type =\n                    Entry.EXPANSION_BLOCK.weather.propertyMap[script.getField('TYPE', script)];\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'now',\n                    location,\n                    null\n                );\n                return apiResult[type];\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        check_cur_weather: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getSky(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                    params.getSky().value,\n                ],\n                type: 'check_cur_weather',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', 'D&value', null],\n                type: 'check_cur_weather',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                WEATHER: 1,\n            },\n            class: 'weather',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'now',\n                    location,\n                    null\n                );\n                return Entry.EXPANSION_BLOCK.weather.checkWeather(\n                    apiResult.sky_code,\n                    script.getField('WEATHER', script)\n                );\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        check_cur_finddust: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getFineDust(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                    params.getFineDust().value,\n                ],\n                type: 'check_cur_finddust',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'check_cur_finddust',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                FINEDUST: 1,\n            },\n            class: 'weather',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'now',\n                    location,\n                    null\n                );\n                return Entry.EXPANSION_BLOCK.weather.checkFineDust(\n                    apiResult.pm10,\n                    script.getField('FINEDUST', script)\n                );\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        get_day_weather: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                params.getDate(),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    params.getDate().value,\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                ],\n                type: 'get_day_weather',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'get_day_weather',\n            },\n            paramsKeyMap: {\n                DATE: 0,\n                LOCATION: 1,\n            },\n            class: 'weather_day',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'week',\n                    location,\n                    script.getField('DATE', script)\n                );\n\n                return apiResult.sky;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        get_day_weather_data: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                params.getDate(),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getWeatherElements(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    params.getDate().value,\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                    params.getWeatherElements().value,\n                ],\n                type: 'get_day_weather_data',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'get_day_weather_data',\n            },\n            paramsKeyMap: {\n                DATE: 0,\n                LOCATION: 1,\n                TYPE: 2,\n            },\n            class: 'weather_day',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const type =\n                    Entry.EXPANSION_BLOCK.weather.propertyMap[script.getField('TYPE', script)];\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'week',\n                    location,\n                    script.getField('DATE', script)\n                );\n                return apiResult[type];\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        check_day_weather: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                params.getDate(),\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getSky(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    params.getDate().value,\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                    params.getSky().value,\n                ],\n                type: 'check_day_weather',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'check_day_weather',\n            },\n            paramsKeyMap: {\n                DATE: 0,\n                LOCATION: 1,\n                WEATHER: 2,\n            },\n            class: 'weather_day',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'week',\n                    location,\n                    script.getField('DATE', script)\n                );\n                return Entry.EXPANSION_BLOCK.weather.checkWeather(\n                    apiResult.sky_code,\n                    script.getField('WEATHER', script)\n                );\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        get_time_weather: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getTime(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                    params.getTime().value,\n                ],\n                type: 'get_time_weather',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_time_weather',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                TIME: 1,\n            },\n            class: 'weather_time',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const date = Entry.EXPANSION_BLOCK.weather.localDate;\n                let time = script.getField('TIME', script);\n                // db에 저장하지 않으면서 00시가 없어져서 03시부터 가능..\n                if (time == '00') {\n                    time = '03';\n                }\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'hour',\n                    location,\n                    date + pad2(time - (time % 3))\n                );\n                return apiResult.sky;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        get_time_weather_data: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getTime(),\n                params.getTimeWeatherElement(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                    params.getTime().value,\n                    params.getTimeWeatherElement().value,\n                ],\n                type: 'get_time_weather_data',\n            },\n            pyHelpDef: {\n                params: ['A&value', 'B&value', 'C&value'],\n                type: 'get_time_weather_data',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                TIME: 1,\n                TYPE: 2,\n            },\n            class: 'weather_time',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const type =\n                    Entry.EXPANSION_BLOCK.weather.propertyHourMap[script.getField('TYPE', script)];\n                const date = Entry.EXPANSION_BLOCK.weather.localDate;\n                let time = script.getField('TIME', script);\n                // db에 저장하지 않으면서 00시가 없어져서 03시부터 가능..\n                if (time == '00') {\n                    time = '03';\n                }\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'hour',\n                    location,\n                    date + pad2(time - (time % 3))\n                );\n                return apiResult[type];\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n        check_time_weather: {\n            color: EntryStatic.colorSet.block.default.EXPANSION,\n            outerLine: EntryStatic.colorSet.block.darken.EXPANSION,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                params.getTime(),\n                params.getSky(),\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_korea_area_code',\n                    },\n                    params.getTime().value,\n                    params.getSky().value,\n                ],\n                type: 'check_time_weather',\n            },\n            pyHelpDef: {\n                params: ['B&value', 'C&value', null],\n                type: 'check_time_weather',\n            },\n            paramsKeyMap: {\n                LOCATION: 0,\n                TIME: 1,\n                WEATHER: 2,\n            },\n            class: 'weather_time',\n            isNotFor: ['weather'],\n            async func(sprite, script) {\n                const location = script.getValue('LOCATION', script);\n                const date = Entry.EXPANSION_BLOCK.weather.localDate;\n                let time = script.getField('TIME', script);\n                // db에 저장하지 않으면서 00시가 없어져서 03시부터 가능..\n                if (time == '00') {\n                    time = '03';\n                }\n                const apiResult = await Entry.EXPANSION_BLOCK.weather.getDataWithCityCode(\n                    'hour',\n                    location,\n                    date + pad2(time - (time % 3))\n                );\n                return Entry.EXPANSION_BLOCK.weather.checkWeather(\n                    apiResult.sky_code,\n                    script.getField('WEATHER', script)\n                );\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n            wikiClass: 'weather',\n        },\n    };\n};\n"
  },
  {
    "path": "src/playground/blocks/block_flow.js",
    "content": "module.exports = {\n    getBlocks() {\n        return {\n            wait_second: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['2'],\n                        },\n                        null,\n                    ],\n                    type: 'wait_second',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'wait_second',\n                },\n                paramsKeyMap: {\n                    SECOND: 0,\n                },\n                class: 'delay',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        let timeValue = script.getNumberValue('SECOND', script);\n                        const fps = Entry.FPS || 60;\n                        timeValue = (60 / fps) * timeValue * 1000;\n\n                        const blockId = script.block.id;\n                        Entry.TimeWaitManager.add(\n                            blockId,\n                            () => {\n                                script.timeFlag = 0;\n                            },\n                            timeValue\n                        );\n\n                        return script;\n                    } else if (script.timeFlag == 1) {\n                        return script;\n                    } else {\n                        delete script.timeFlag;\n                        delete script.isStart;\n                        Entry.engine.isContinue = false;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.wait_for_sec(%1)',\n                        },\n                    ],\n                },\n            },\n            repeat_basic: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic_loop',\n                statements: [\n                    {\n                        accept: 'basic',\n                    },\n                ],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'repeat_basic',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'repeat_basic',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                statementsKeyMap: {\n                    DO: 0,\n                },\n                class: 'repeat',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isLooped) {\n                        const iterNumber = script.getNumberValue('VALUE', script);\n                        script.isLooped = true;\n                        if (iterNumber < 0) {\n                            throw new Error(Lang.Blocks.FLOW_repeat_basic_errorMsg);\n                        }\n                        script.iterCount = Math.floor(iterNumber);\n                    }\n                    if (script.iterCount !== 0 && !(script.iterCount < 0)) {\n                        script.iterCount--;\n                        return script.getStatement('DO', script);\n                    } else {\n                        delete script.isLooped;\n                        delete script.iterCount;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'for i in range(%1):\\n$1',\n                            template: 'for i in range(%1):',\n                            idChar: ['i', 'j', 'k'],\n                        },\n                    ],\n                },\n            },\n            repeat_inf: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic_loop',\n                statements: [\n                    {\n                        accept: 'basic',\n                    },\n                ],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'Boolean',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'repeat_inf',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        {\n                            type: 'boolean_shell',\n                            params: ['A'],\n                        },\n                    ],\n                    type: 'repeat_inf',\n                },\n                statementsKeyMap: {\n                    DO: 0,\n                },\n                class: 'repeat',\n                isNotFor: [],\n                func(sprite, script) {\n                    script.isLooped = true;\n                    return script.getStatement('DO');\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'while True:\\n$1',\n                            template: 'while %2\\n:',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'boolean',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            repeat_while_true: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic_loop',\n                statements: [\n                    {\n                        accept: 'basic',\n                    },\n                ],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.FLOW_repeat_while_true_until, 'until'],\n                            [Lang.Blocks.FLOW_repeat_while_true_while, 'while'],\n                        ],\n                        value: 'until',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.FLOW,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'True',\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'repeat_while_true',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'boolean_shell',\n                            params: ['A'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'repeat_while_true',\n                },\n                paramsKeyMap: {\n                    BOOL: 0,\n                    OPTION: 1,\n                },\n                statementsKeyMap: {\n                    DO: 0,\n                },\n                class: 'repeat',\n                isNotFor: [],\n                func(sprite, script) {\n                    let value = script.getBooleanValue('BOOL', script);\n\n                    if (script.getField('OPTION', script) === 'until') {\n                        value = !value;\n                    }\n                    script.isLooped = value;\n\n                    return value ? script.getStatement('DO', script) : script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'while %1 %2:\\n$1',\n                            template: 'while not %1:',\n                        },\n                    ],\n                },\n            },\n            stop_repeat: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'stop_repeat',\n                },\n                class: 'repeat',\n                isNotFor: [],\n                func(sprite, script) {\n                    return this.executor.breakLoop();\n                },\n                syntax: { js: [], py: ['break'] },\n            },\n            continue_repeat: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'continue_repeat',\n                },\n                class: 'repeat',\n                isNotFor: [],\n                func(sprite, script) {\n                    return this.executor.continueLoop();\n                },\n                syntax: { js: [], py: ['continue'] },\n            },\n            _if: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic_loop',\n                statements: [\n                    {\n                        accept: 'basic',\n                    },\n                ],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'True',\n                        },\n                        null,\n                    ],\n                    type: '_if',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'boolean_shell',\n                            params: ['A'],\n                        },\n                        null,\n                    ],\n                    type: '_if',\n                },\n                paramsKeyMap: {\n                    BOOL: 0,\n                },\n                statementsKeyMap: {\n                    STACK: 0,\n                },\n                class: 'condition',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (script.isCondition) {\n                        delete script.isCondition;\n                        return script.callReturn();\n                    }\n                    const value = script.getBooleanValue('BOOL', script);\n                    if (value) {\n                        script.isCondition = true;\n                        return script.getStatement('STACK', script);\n                    } else {\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [{ syntax: 'if %1:\\n$1', template: 'if %1:' }],\n                },\n            },\n            if_else: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic_double_loop',\n                statements: [\n                    {\n                        accept: 'basic',\n                    },\n                    {\n                        accept: 'basic',\n                    },\n                ],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                    {\n                        type: 'LineBreak',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'True',\n                        },\n                        null,\n                    ],\n                    type: 'if_else',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'boolean_shell',\n                            params: ['A'],\n                        },\n                        null,\n                    ],\n                    type: 'if_else',\n                },\n                paramsKeyMap: {\n                    BOOL: 0,\n                },\n                statementsKeyMap: {\n                    STACK_IF: 0,\n                    STACK_ELSE: 1,\n                },\n                class: 'condition',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (script.isCondition) {\n                        delete script.isCondition;\n                        return script.callReturn();\n                    }\n                    const value = script.getBooleanValue('BOOL', script);\n                    script.isCondition = true;\n                    if (value) {\n                        return script.getStatement('STACK_IF', script);\n                    } else {\n                        return script.getStatement('STACK_ELSE', script);\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'if %1:\\n$1\\nelse:\\n$2',\n                            template: 'if %1: %3 else:',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'boolean',\n                                },\n                                undefined,\n                                {\n                                    type: 'LineBreak',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            wait_until_true: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'True',\n                        },\n                        null,\n                    ],\n                    type: 'wait_until_true',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'boolean_shell',\n                            params: ['A'],\n                        },\n                        null,\n                    ],\n                    type: 'wait_until_true',\n                },\n                paramsKeyMap: {\n                    BOOL: 0,\n                },\n                class: 'wait',\n                isNotFor: [],\n                func(sprite, script) {\n                    const value = script.getBooleanValue('BOOL', script);\n                    if (value) {\n                        return script.callReturn();\n                    } else {\n                        return script;\n                    }\n                },\n                syntax: { js: [], py: ['Entry.wait_until(%1)'] },\n            },\n            stop_object: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.FLOW_stop_object_all, 'all'],\n                            [Lang.Blocks.FLOW_stop_object_this_object, 'thisOnly'],\n                            [Lang.Blocks.FLOW_stop_object_this_thread, 'thisThread'],\n                            [Lang.Blocks.FLOW_stop_object_other_thread, 'otherThread'],\n                            [Lang.Blocks.FLOW_stop_object_other_objects, 'other_objects'],\n                        ],\n                        value: 'all',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.FLOW,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'stop_object',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'stop_object',\n                },\n                paramsKeyMap: {\n                    TARGET: 0,\n                },\n                class: 'terminate',\n                isNotFor: [],\n                func(sprite, script) {\n                    const object = sprite.parent;\n\n                    switch (script.getField('TARGET', script)) {\n                        case 'all':\n                            Entry.container.mapObject(function(obj) {\n                                if (!obj.objectType) {\n                                    return;\n                                }\n\n                                obj.script.clearExecutors();\n                            });\n                            return this.die();\n                        case 'thisOnly':\n                            object.script.clearExecutorsByEntity(sprite);\n                            return this.die();\n                        case 'thisObject':\n                            object.script.clearExecutors();\n                            return this.die();\n                        case 'thisThread':\n                            return this.die();\n                        case 'otherThread': {\n                            const executor = this.executor;\n                            const code = object.script;\n                            const executors = code.executors;\n                            const spriteId = sprite.id;\n                            for (let i = 0; i < executors.length; i++) {\n                                const currentExecutor = executors[i];\n                                if (\n                                    currentExecutor !== executor &&\n                                    currentExecutor.entity.id === spriteId\n                                ) {\n                                    code.removeExecutor(currentExecutor);\n                                    --i;\n                                }\n                            }\n                            return script.callReturn();\n                        }\n                        case 'other_objects':\n                            Entry.container.mapObject(function(obj) {\n                                if (!obj.objectType || obj === object) {\n                                    return;\n                                }\n\n                                obj.script.clearExecutors();\n                            });\n                            return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.stop_code(%1)',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.FLOW_stop_object_all, 'all'],\n                                        [Lang.Blocks.FLOW_stop_object_this_object, 'thisOnly'],\n                                        [Lang.Blocks.FLOW_stop_object_this_thread, 'thisThread'],\n                                        [Lang.Blocks.FLOW_stop_object_other_thread, 'otherThread'],\n                                        [\n                                            Lang.Blocks.FLOW_stop_object_other_objects,\n                                            'other_objects',\n                                        ],\n                                    ],\n                                    value: 'all',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.FLOW,\n                                    converter: Entry.block.converters.returnStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.stop_object[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            restart_project: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic_without_next',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'restart_project',\n                },\n                class: 'terminate',\n                isNotFor: [],\n                func(sprite, script) {\n                    Entry.engine.toggleStop().then(() => {\n                        Entry.engine.toggleRun();\n                    });\n                },\n                syntax: { js: [], py: ['Entry.start_again()'] },\n            },\n            when_clone_start: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_clone.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'when_clone_start',\n                },\n                class: 'clone',\n                isNotFor: [],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'when_clone_start',\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_make_clone():',\n                            blockType: 'event',\n                        },\n                    ],\n                },\n            },\n            create_clone: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'clone',\n                        fontSize: 10,\n                        textColor: '#fff',\n                        bgColor: EntryStatic.colorSet.block.darken.FLOW,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'create_clone',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'create_clone',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'clone',\n                isNotFor: [],\n                func(sprite, script) {\n                    const targetSpriteId = script.getField('VALUE', script);\n                    const returnBlock = script.callReturn();\n                    if (targetSpriteId === 'self') {\n                        sprite.parent.addCloneEntity(sprite.parent, sprite, null);\n                    } else {\n                        const object = Entry.container.getObject(targetSpriteId);\n                        object.addCloneEntity(sprite.parent, null, null);\n                    }\n                    return returnBlock;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.make_clone_of(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'clone',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.FLOW,\n                                    converter: Entry.block.converters.returnStringKey,\n                                    codeMap: 'Entry.CodeMap.Entry.create_clone[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            delete_clone: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic_without_next',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'delete_clone',\n                },\n                class: 'clone',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!sprite.isClone) {\n                        return script.callReturn();\n                    }\n                    sprite.removeClone();\n                    return this.die();\n                },\n                syntax: { js: [], py: ['Entry.remove_this_clone()'] },\n            },\n            remove_all_clones: {\n                color: EntryStatic.colorSet.block.default.FLOW,\n                outerLine: EntryStatic.colorSet.block.darken.FLOW,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/flow_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'remove_all_clones',\n                },\n                class: 'clone',\n                isNotFor: [],\n                func(sprite, script) {\n                    let clonedEntities = sprite.parent.getClonedEntities();\n                    clonedEntities.map(function(entity) {\n                        entity.removeClone();\n                    });\n                    clonedEntities = null;\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.remove_all_clone()'] },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_func.js",
    "content": "import _cloneDeep from 'lodash/cloneDeep';\n\nmodule.exports = {\n    getBlocks() {\n        return {\n            functionAddButton: {\n                skeleton: 'basic_button',\n                color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n                isNotFor: ['functionInit'],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Workspace.function_create,\n                        color: EntryStatic.colorSet.common.BUTTON,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'functionAddButton',\n                },\n                events: {\n                    mousedown: [\n                        function () {\n                            Entry.do('funcEditStart', Entry.generateHash());\n                        },\n                    ],\n                },\n            },\n            function_name: {\n                template: '%1',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: EntryStatic.colorSet.common.TEXT,\n                params: [\n                    {\n                        type: 'Text',\n                        text: '',\n                        color: EntryStatic.colorSet.common.TEXT,\n                        align: 'left',\n                    },\n                ],\n                class: 'properties',\n                isNotFor: ['functionEdit'],\n                events: {},\n            },\n            showFunctionPropsButton: {\n                template: '%1',\n                skeleton: 'basic_button',\n                color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n                class: 'properties',\n                isNotFor: ['functionEdit'],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Workspace.function_attribute,\n                        color: EntryStatic.colorSet.common.BUTTON,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'showFunctionPropsButton',\n                },\n                events: {\n                    mousedown: [\n                        function () {\n                            Entry.do(\n                                'playgroundChangeViewMode',\n                                'variable',\n                                Entry.playground.selectedViewMode\n                            );\n                            Entry.variableContainer.selectFilter('func');\n                            Entry.variableContainer.select(Entry.Func.targetFunc);\n                        },\n                    ],\n                },\n                wikiClass: 'function',\n            },\n            set_func_variable: {\n                template: Lang.template.set_variable,\n                color: EntryStatic.colorSet.block.default.FUNC,\n                outerLine: EntryStatic.colorSet.block.darken.FUNC,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName(block) {\n                            const func =\n                                Entry.variableContainer.getFunctionByBlockId(block.id) ||\n                                Entry.Func.targetFunc ||\n                                {};\n                            const localVariables = func.localVariables || [];\n                            if (localVariables.length) {\n                                return localVariables.map((localVariable) => {\n                                    const { id, name } = localVariable;\n                                    if (!id) {\n                                        localVariable.id = `${func.id}_${Entry.generateHash()}`;\n                                    }\n                                    return [name, localVariable.id];\n                                });\n                            } else {\n                                return [[Lang.Blocks.no_target, 'null']];\n                            }\n                        },\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.FUNC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                        defaultValue: (_value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return null;\n                        },\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/func_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    updateFuncVariableList: [\n                        function () {\n                            const func = Entry.Func.targetFunc || {};\n                            func?.content\n                                ?.getBlockList(false, 'set_func_variable')\n                                ?.forEach((block) => {\n                                    block?.view?.getParam(0)?.updateValue(true);\n                                });\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'set_func_variable',\n                },\n                paramsKeyMap: {\n                    VARIABLE: 0,\n                    VALUE: 1,\n                },\n                class: 'local_variable',\n                isNotFor: ['useLocalVariables'],\n                func(sprite, script) {\n                    const variableId = script.getField('VARIABLE', script);\n                    const value = script.getValue('VALUE', script);\n                    const [funcId, idx] = variableId.split('_');\n                    const func = Entry.variableContainer.getFunction(funcId, idx);\n\n                    func.setValue(value, variableId, script.executor.localVariables);\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1 = %2',\n                            passTest: true,\n                            blockType: 'variable',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'variables',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n                wikiClass: 'function',\n            },\n            get_func_variable: {\n                template: '%1 %2',\n                color: EntryStatic.colorSet.block.default.FUNC,\n                outerLine: EntryStatic.colorSet.block.darken.FUNC,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName(block) {\n                            const func =\n                                Entry.variableContainer.getFunctionByBlockId(block.id) ||\n                                Entry.Func.targetFunc ||\n                                {};\n                            const localVariables = func.localVariables || [];\n                            if (localVariables.length) {\n                                return localVariables.map((localVariable) => {\n                                    const { id, name } = localVariable;\n                                    if (!id) {\n                                        localVariable.id = `${func.id}_${Entry.generateHash()}`;\n                                    }\n                                    return [name, localVariable.id];\n                                });\n                            } else {\n                                return [[Lang.Blocks.no_target, 'null']];\n                            }\n                        },\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.FUNC,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                        defaultValue: (_value, options) => {\n                            if (options[0] && options[0][1]) {\n                                return options[0][1];\n                            }\n                            return null;\n                        },\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_get_variable_1,\n                        color: 'white',\n                    },\n                ],\n                events: {\n                    updateFuncVariableList: [\n                        function () {\n                            const func = Entry.Func.targetFunc || {};\n                            func?.content\n                                ?.getBlockList(false, 'get_func_variable')\n                                ?.forEach((block) => {\n                                    block?.view?.getParam(0)?.updateValue(true);\n                                });\n                        },\n                    ],\n                },\n                def: {\n                    params: [null],\n                    type: 'get_func_variable',\n                },\n                paramsKeyMap: {\n                    VARIABLE: 0,\n                },\n                class: 'local_variable',\n                isNotFor: ['useLocalVariables'],\n                func(sprite, script) {\n                    const variableId = script.getField('VARIABLE', script);\n                    const [funcId] = variableId.split('_');\n                    const func = Entry.variableContainer.getFunction(funcId);\n                    return func.getValue(variableId, script.executor.localVariables);\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n                wikiClass: 'function',\n            },\n            function_create_value: {\n                skeleton: 'basic_create_value',\n                statements: [\n                    {\n                        accept: 'basic',\n                    },\n                ],\n                color: EntryStatic.colorSet.block.default.FUNC,\n                outerLine: EntryStatic.colorSet.block.darken.FUNC,\n                event: 'funcDef',\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'param',\n                        value: {\n                            type: 'function_field_label',\n                            params: [Lang.Blocks.FUNC],\n                            copyable: false,\n                        },\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/func_icon.svg',\n                        size: 11,\n                    },\n                    {\n                        type: 'LineBreak',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                paramsKeyMap: {\n                    FIELD: 0,\n                    VALUE: 3,\n                },\n                statementsKeyMap: {\n                    DO: 0,\n                },\n                func(sprite, script) {\n                    if (!script.isFunc) {\n                        script.isFunc = true;\n                        script.executor.result = script;\n                        return script.getStatement('DO', script);\n                    } else {\n                        delete script.isFunc;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1',\n                            keyOption: 'function_create_value',\n                        },\n                    ],\n                },\n                wikiClass: 'function',\n            },\n            function_general: {\n                skeleton: 'basic',\n                color: EntryStatic.colorSet.block.default.FUNC,\n                outerLine: EntryStatic.colorSet.block.darken.FUNC,\n                class: 'function_executor',\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/func_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function (block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_functionRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function (block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_functionRefs', block);\n                            }\n                        },\n                    ],\n                    dblclick: [\n                        function (blockView) {\n                            const mode = blockView.getBoard().workspace.getMode();\n                            if (mode !== Entry.Workspace.MODE_BOARD) {\n                                return;\n                            }\n                            if (Entry.type !== 'workspace') {\n                                return;\n                            }\n                            const block = blockView.block;\n                            const id = block.getFuncId();\n                            Entry.do('funcEditStart', id);\n                        },\n                    ],\n                },\n                func(entity, script) {\n                    if (!this.initiated) {\n                        this.initiated = true;\n                        Entry.callStackLength++;\n                        const func = Entry.variableContainer.getFunction(this.block.getFuncId());\n                        this.funcCode = func.content;\n                        this.funcExecutor = this.funcCode.raiseEvent('funcDef', entity)[0];\n                        this.funcExecutor.register.params = this.values;\n                        this.funcExecutor.register.paramMap = func.paramMap;\n                        this.funcExecutor.parentExecutor = this.executor;\n                        this.funcExecutor.parentScope = script;\n                        this.funcExecutor.isFuncExecutor = true;\n                        this.funcExecutor.localVariables = _cloneDeep(func.localVariables);\n                    }\n\n                    const { promises } = this.funcExecutor.execute();\n\n                    if (!this.funcExecutor.isEnd()) {\n                        if (promises.length) {\n                            return Entry.Code.funcAsyncExecute(\n                                this.funcCode,\n                                this.funcExecutor,\n                                promises\n                            );\n                        } else {\n                            this.funcCode.removeExecutor(this.funcExecutor);\n                            return Entry.STATIC.BREAK;\n                        }\n                    } else {\n                        this.funcCode.removeExecutor(this.funcExecutor);\n                    }\n\n                    Entry.callStackLength--;\n                },\n                syntax: { js: [], py: [''] },\n                wikiClass: 'function',\n            },\n            function_value: {\n                skeleton: 'basic_string_field',\n                color: EntryStatic.colorSet.block.default.FUNC,\n                outerLine: EntryStatic.colorSet.block.darken.FUNC,\n                class: 'function_executor',\n                params: [],\n                events: {\n                    dataAdd: [\n                        function (block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_functionRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function (block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_functionRefs', block);\n                            }\n                        },\n                    ],\n                    dblclick: [\n                        function (blockView) {\n                            const mode = blockView.getBoard().workspace.getMode();\n                            if (mode !== Entry.Workspace.MODE_BOARD) {\n                                return;\n                            }\n                            if (Entry.type !== 'workspace') {\n                                return;\n                            }\n                            const block = blockView.block;\n                            const id = block.getFuncId();\n                            Entry.do('funcEditStart', id);\n                        },\n                    ],\n                },\n                func(entity, script) {\n                    if (!this.initiated) {\n                        this.initiated = true;\n                        Entry.callStackLength++;\n                        const func = Entry.variableContainer.getFunction(this.block.getFuncId());\n                        this.funcCode = func.content;\n                        this.funcExecutor = this.funcCode.raiseEvent('funcDef', entity)[0];\n                        this.funcExecutor.register.params = this.values;\n                        this.funcExecutor.register.paramMap = func.paramMap;\n                        this.funcExecutor.parentExecutor = this.executor;\n                        this.funcExecutor.parentScope = script;\n                        this.funcExecutor.isFuncExecutor = true;\n                        this.funcExecutor.localVariables = _cloneDeep(func.localVariables);\n                    }\n\n                    this.funcExecutor.result = this.funcExecutor.scope;\n\n                    const firstBlock =\n                        this.funcExecutor?.scope?.block?.statements[0]?.getFirstBlock();\n                    if (firstBlock) {\n                        this.funcExecutor.scope = new Entry.Scope(firstBlock, this.funcExecutor);\n                    }\n                    const { promises } = this.funcExecutor.execute();\n\n                    if (!this.funcExecutor.isEnd()) {\n                        if (promises.length) {\n                            return Entry.Code.funcValueAsyncExecute(\n                                this.funcCode,\n                                this.funcExecutor,\n                                promises\n                            );\n                        } else {\n                            return Entry.Code.funcRestExecute(this.funcCode, this.funcExecutor);\n                        }\n                    } else {\n                        this.funcCode.removeExecutor(this.funcExecutor);\n                    }\n\n                    Entry.callStackLength--;\n                    const scope = this.funcExecutor.result;\n                    scope.values = scope.getParams();\n                    return scope.getValue('VALUE', scope);\n                },\n                syntax: { js: [], py: [''] },\n                wikiClass: 'function',\n            },\n            function_field_label: {\n                skeleton: 'basic_param',\n                isNotFor: ['functionEdit'],\n                color: '#f9c535',\n                params: [\n                    {\n                        type: 'TextInput',\n                        value: Lang.Blocks.FUNCTION_explanation_1,\n                    },\n                    {\n                        type: 'Output',\n                        accept: 'param',\n                    },\n                ],\n                paramsKeyMap: {\n                    NAME: 0,\n                    NEXT: 1,\n                },\n                def: {\n                    params: [Lang.Blocks.FUNCTION_explanation_1],\n                    type: 'function_field_label',\n                },\n                //\"syntax\": {\"js\": [], \"py\": [\"%1function_field_label#\"]}\n                syntax: { js: [], py: ['name'] },\n                wikiClass: 'function',\n            },\n            function_field_string: {\n                skeleton: 'basic_param',\n                isNotFor: ['functionEdit'],\n                color: EntryStatic.colorSet.block.lighten.CALC,\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        restore: true,\n                    },\n                    {\n                        type: 'Output',\n                        accept: 'param',\n                    },\n                ],\n                paramsKeyMap: {\n                    PARAM: 0,\n                    NEXT: 1,\n                },\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.template.function_param_string],\n                        },\n                    ],\n                    type: 'function_field_string',\n                },\n                syntax: { js: [], py: ['value'] },\n                wikiClass: 'function',\n            },\n            function_field_boolean: {\n                skeleton: 'basic_param',\n                isNotFor: ['functionEdit'],\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                        restore: true,\n                    },\n                    {\n                        type: 'Output',\n                        accept: 'param',\n                    },\n                ],\n                paramsKeyMap: {\n                    PARAM: 0,\n                    NEXT: 1,\n                },\n                def: {\n                    params: [\n                        {\n                            type: 'True',\n                            params: [Lang.template.function_param_boolean],\n                        },\n                    ],\n                    type: 'function_field_boolean',\n                },\n                syntax: { js: [], py: ['boolean'] },\n                wikiClass: 'function',\n            },\n            function_param_string: {\n                skeleton: 'basic_string_field',\n                color: EntryStatic.colorSet.block.lighten.CALC,\n                fontColor: '#000',\n                template: '%1 %2',\n                events: {\n                    viewAdd: [\n                        function () {\n                            if (Entry.Func.isEdit) {\n                                Entry.Func.refreshMenuCode();\n                            }\n                        },\n                    ],\n                },\n                func() {\n                    return this.executor.register.params[\n                        this.executor.register.paramMap[this.block.type]\n                    ];\n                },\n                syntax: { js: [], py: [''] },\n                wikiClass: 'function',\n            },\n            function_param_boolean: {\n                skeleton: 'basic_boolean_field',\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                template: '%1 %2',\n                events: {\n                    viewAdd: [\n                        function () {\n                            if (Entry.Func.isEdit) {\n                                Entry.Func.refreshMenuCode();\n                            }\n                        },\n                    ],\n                },\n                func() {\n                    return this.executor.register.params[\n                        this.executor.register.paramMap[this.block.type]\n                    ];\n                },\n                syntax: { js: [], py: [''] },\n                wikiClass: 'function',\n            },\n            function_create: {\n                skeleton: 'basic_create',\n                statements: [\n                    {\n                        accept: 'basic',\n                    },\n                ],\n                color: EntryStatic.colorSet.block.default.FUNC,\n                outerLine: EntryStatic.colorSet.block.darken.FUNC,\n                event: 'funcDef',\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'param',\n                        value: {\n                            type: 'function_field_label',\n                            params: [Lang.Blocks.FUNC],\n                            copyable: false,\n                        },\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/func_icon.svg',\n                        size: 11,\n                    },\n                ],\n                paramsKeyMap: {\n                    FIELD: 0,\n                },\n                statementsKeyMap: {\n                    DO: 0,\n                },\n                func(sprite, script) {\n                    if (!script.isFunc) {\n                        script.isFunc = true;\n                        script.executor.result = script;\n                        return script.getStatement('DO', script);\n                    } else {\n                        delete script.isFunc;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1',\n                            keyOption: 'function_create',\n                        },\n                    ],\n                },\n                wikiClass: 'function',\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_judgement.js",
    "content": "import { GEHelper } from '../../graphicEngine/GEHelper';\nimport { keyInputList } from './inputs/keyboard';\n\nmodule.exports = {\n    getBlocks() {\n        return {\n            is_clicked: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_is_clicked,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'is_clicked',\n                },\n                class: 'boolean_input',\n                isNotFor: [],\n                func(sprite, script) {\n                    return Entry.stage.isClick;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.is_mouse_clicked()',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            is_object_clicked: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_is_object_clicked,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'is_object_clicked',\n                },\n                class: 'boolean_input',\n                isNotFor: ['python_disable'],\n                func(sprite, script) {\n                    const objId = sprite.id;\n                    if (Entry.stage.clickedObjectId == objId) {\n                        return true;\n                    }\n                    return false;\n                },\n                syntax: { js: [], py: [] },\n            },\n            is_press_some_key: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Keyboard',\n                        options: keyInputList,\n                        value: 'next',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.JUDGE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_is_press_some_key_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['81', null],\n                    type: 'is_press_some_key',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'is_press_some_key',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'boolean_input',\n                isNotFor: [],\n                func(sprite, script) {\n                    const keycode = Number(script.getField('VALUE', script));\n                    return Entry.pressedKeys.indexOf(keycode) >= 0;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.is_key_pressed(%1)',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    value: 'next',\n                                    options: keyInputList,\n                                    converter: Entry.block.converters.keyboardCode,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            reach_something: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_reach_something_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'collision',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.JUDGE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_reach_something_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'reach_something',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null],\n                    type: 'reach_something',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'boolean_collision',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (sprite.getVisible && !sprite.getVisible()) {\n                        return false;\n                    }\n                    const targetSpriteId = script.getField('VALUE', script);\n                    const reg = /wall/;\n                    const ath = 0.2;\n                    const object = sprite.object;\n                    const isWall = reg.test(targetSpriteId);\n                    const collision = ndgmr.checkPixelCollision;\n                    if (isWall) {\n                        const wall = Entry.stage.wall;\n                        switch (targetSpriteId) {\n                            case 'wall':\n                                return !!(\n                                    collision(object, wall.up, ath, false) ||\n                                    collision(object, wall.down, ath, false) ||\n                                    collision(object, wall.left, ath, false) ||\n                                    collision(object, wall.right, ath, false)\n                                );\n                            case 'wall_up':\n                                return !!collision(object, wall.up, ath, false);\n                            case 'wall_down':\n                                return !!collision(object, wall.down, ath, false);\n                            case 'wall_right':\n                                return !!collision(object, wall.right, ath, false);\n                            case 'wall_left':\n                                return !!collision(object, wall.left, ath, false);\n                        }\n                    } else if (targetSpriteId === 'mouse') {\n                        return GEHelper.hitTestMouse(object);\n                    } else {\n                        const targetSprite = Entry.container.getEntity(targetSpriteId);\n                        if (targetSprite.type === 'textBox' || sprite.type === 'textBox') {\n                            const targetBound = GEHelper.getTransformedBounds(targetSprite.object);\n                            const bound = GEHelper.getTransformedBounds(object);\n                            if (Entry.checkCollisionRect(bound, targetBound)) {\n                                return true;\n                            }\n                            const clonedEntities = targetSprite.parent.clonedEntities;\n                            for (let i = 0, len = clonedEntities.length; i < len; i++) {\n                                const entity = clonedEntities[i];\n                                if (entity.isStamp || !entity.getVisible()) {\n                                    continue;\n                                }\n                                if (\n                                    Entry.checkCollisionRect(\n                                        bound,\n                                        GEHelper.getTransformedBounds(entity.object)\n                                    )\n                                ) {\n                                    return true;\n                                }\n                            }\n                        } else {\n                            if (\n                                targetSprite.getVisible() &&\n                                collision(object, targetSprite.object, ath, false)\n                            ) {\n                                return true;\n                            }\n                            const clonedEntities = targetSprite.parent.clonedEntities;\n                            for (let i = 0, len = clonedEntities.length; i < len; i++) {\n                                const entity = clonedEntities[i];\n                                if (entity.isStamp || !entity.getVisible()) {\n                                    continue;\n                                }\n                                if (collision(object, entity.object, ath, false)) {\n                                    return true;\n                                }\n                            }\n                        }\n                    }\n                    return false;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.is_touched(%2)',\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'collision',\n                                    fontSize: 11,\n                                    converter: Entry.block.converters.returnObjectOrStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.reach_something[1]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            is_type: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_is_type_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.is_type_number, 'number'],\n                            [Lang.Blocks.is_type_en, 'en'],\n                            [Lang.Blocks.is_type_ko, 'ko'],\n                        ],\n                        value: 'number',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.JUDGE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_is_type_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['10', null, 'number', null],\n                    type: 'is_type',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    TYPE: 2,\n                },\n                class: 'boolean_type',\n                isNotFor: ['python_disable'],\n                func(sprite, script) {\n                    const value = script.getStringValue('VALUE', script);\n                    const type = script.getField('TYPE', script);\n\n                    if (type === 'number') {\n                        return Entry.Utils.isNumber(value);\n                    } else if (type === 'en') {\n                        const pattern = /^[a-zA-Z]+$/;\n                        return pattern.test(value);\n                    } else if (type === 'ko') {\n                        const pattern = /^[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]+$/;\n                        return pattern.test(value);\n                    }\n                    return false;\n                },\n                syntax: {\n                    js: [],\n                    py: [],\n                },\n            },\n            boolean_basic_operator: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['=', 'EQUAL'],\n                            ['!=', 'NOT_EQUAL'],\n                            ['>', 'GREATER'],\n                            ['<', 'LESS'],\n                            ['≥', 'GREATER_OR_EQUAL'],\n                            ['≤', 'LESS_OR_EQUAL'],\n                        ],\n                        value: 'EQUAL',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.JUDGE,\n                        noArrow: true,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        'EQUAL',\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                    ],\n                    type: 'boolean_basic_operator',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        'EQUAL',\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                    ],\n                    type: 'boolean_basic_operator',\n                },\n                defs: [\n                    {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            'EQUAL',\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'boolean_basic_operator',\n                    },\n                    {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            'NOT_EQUAL',\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'boolean_basic_operator',\n                    },\n                    {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            'GREATER',\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'boolean_basic_operator',\n                    },\n                    {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            'LESS',\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'boolean_basic_operator',\n                    },\n                    {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            'GREATER_OR_EQUAL',\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'boolean_basic_operator',\n                    },\n                    {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            'LESS_OR_EQUAL',\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                        ],\n                        type: 'boolean_basic_operator',\n                    },\n                ],\n                paramsKeyMap: {\n                    LEFTHAND: 0,\n                    OPERATOR: 1,\n                    RIGHTHAND: 2,\n                },\n                class: 'boolean_compare',\n                isNotFor: [],\n                func(sprite, script) {\n                    const operator = script.getField('OPERATOR', script);\n                    let [leftValue, rightValue] = script.getValues(\n                        ['LEFTHAND', 'RIGHTHAND'],\n                        script\n                    );\n                    if (typeof leftValue === 'string' && leftValue.length) {\n                        const leftNumber = Number(leftValue);\n                        if (!isNaN(leftNumber)) {\n                            leftValue = leftNumber;\n                        }\n                    }\n                    if (typeof rightValue === 'string' && rightValue.length) {\n                        const rightNumber = Number(rightValue);\n                        if (!isNaN(rightNumber)) {\n                            rightValue = rightNumber;\n                        }\n                    }\n\n                    switch (operator) {\n                        case 'EQUAL':\n                            return leftValue === rightValue;\n                        case 'NOT_EQUAL':\n                            return leftValue != rightValue;\n                        case 'GREATER':\n                            return leftValue > rightValue;\n                        case 'LESS':\n                            return leftValue < rightValue;\n                        case 'GREATER_OR_EQUAL':\n                            return leftValue >= rightValue;\n                        case 'LESS_OR_EQUAL':\n                            return leftValue <= rightValue;\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '(%1 %2 %3)',\n                            template: '%1 %2 %3',\n                            keyOption: 'boolean_basic_operator',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        ['=', 'EQUAL'],\n                                        ['!=', 'NOT_EQUAL'],\n                                        ['>', 'GREATER'],\n                                        ['<', 'LESS'],\n                                        ['≥', 'GREATER_OR_EQUAL'],\n                                        ['≤', 'LESS_OR_EQUAL'],\n                                    ],\n                                    value: 'EQUAL',\n                                    fontSize: 11,\n                                    noArrow: true,\n                                    converter: Entry.block.converters.returnOperator,\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            boolean_and_or: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.JUDGEMENT_boolean_and, 'AND'],\n                            [Lang.Blocks.JUDGEMENT_boolean_or, 'OR'],\n                        ],\n                        value: 'AND',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.JUDGE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [{ type: 'True' }, 'AND', { type: 'True' }],\n                    type: 'boolean_and_or',\n                },\n                defs: [\n                    {\n                        params: [{ type: 'True' }, 'AND', { type: 'True' }],\n                        type: 'boolean_and_or',\n                    },\n                    {\n                        params: [{ type: 'True' }, 'OR', { type: 'False' }],\n                        type: 'boolean_and_or',\n                    },\n                ],\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'boolean_shell',\n                            params: ['A'],\n                        },\n                        'AND',\n                        {\n                            type: 'boolean_shell',\n                            params: ['B'],\n                        },\n                    ],\n                    type: 'boolean_and_or',\n                },\n                paramsKeyMap: {\n                    LEFTHAND: 0,\n                    OPERATOR: 1,\n                    RIGHTHAND: 2,\n                },\n                func(sprite, script) {\n                    const operator = script.getField('OPERATOR', script);\n                    let [leftValue, rightValue] = script.getValues(\n                        ['LEFTHAND', 'RIGHTHAND'],\n                        script\n                    );\n                    leftValue = Boolean(leftValue);\n                    rightValue = Boolean(rightValue);\n\n                    if (operator === 'AND') {\n                        return leftValue && rightValue;\n                    } else {\n                        return leftValue || rightValue;\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '(%1 %2 %3)',\n                            template: '%1 %2 %3',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'boolean',\n                                },\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.JUDGEMENT_boolean_and, 'AND'],\n                                        [Lang.Blocks.JUDGEMENT_boolean_or, 'OR'],\n                                    ],\n                                    converter: Entry.block.converters.returnOperator,\n                                    value: 'AND',\n                                    fontSize: 11,\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'boolean',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            boolean_not: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_boolean_not_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'boolean',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_boolean_not_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, { type: 'True' }, null],\n                    type: 'boolean_not',\n                },\n                pyHelpDef: {\n                    params: [null, { type: 'boolean_shell' }, null],\n                    type: 'boolean_not',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'boolean',\n                isNotFor: [],\n                func(sprite, script) {\n                    return !script.getBooleanValue('VALUE', script);\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'not (%2)',\n                            template: 'not %2',\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'Boolean',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            is_boost_mode: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.JUDGEMENT_is_boost_mode,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'is_boost_mode',\n                },\n                class: 'boolean_input',\n                isNotFor: [],\n                func() {\n                    return !!Entry.options.useWebGL;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.is_boost_mode()',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            is_current_device_type: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.desktop, 'desktop'],\n                            [Lang.Blocks.tablet, 'tablet'],\n                            [Lang.Blocks.smartphone, 'mobile'],\n                        ],\n                        value: 'desktop',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.JUDGE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'is_current_device_type',\n                },\n                pyHelpDef: {\n                    params: ['A&value'],\n                    type: 'is_current_device_type',\n                },\n                class: 'boolean_device',\n                isNotFor: [],\n                paramsKeyMap: {\n                    DEVICE: 0,\n                },\n                func(sprite, script) {\n                    const device = script.getField('DEVICE', script);\n                    const deviceType = Entry.Utils.getDeviceType();\n                    if (device !== 'desktop') {\n                        return deviceType === device;\n                    } else if (deviceType !== 'mobile' && deviceType !== 'tablet') {\n                        return true;\n                    }\n                    return false;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.is_current_device_type(%1)',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.desktop, 'desktop'],\n                                        [Lang.Blocks.tablet, 'tablet'],\n                                        [Lang.Blocks.smartphone, 'mobile'],\n                                    ],\n                                    value: 'desktop',\n                                    fontSize: 11,\n                                    converter: Entry.block.converters.returnStringValue,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            is_touch_supported: {\n                color: EntryStatic.colorSet.block.default.JUDGE,\n                outerLine: EntryStatic.colorSet.block.darken.JUDGE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'is_touch_supported',\n                },\n                class: 'boolean_device',\n                isNotFor: [],\n                func() {\n                    return (\n                        'ontouchstart' in window ||\n                        navigator.maxTouchPoints > 0 ||\n                        navigator.msMaxTouchPoints > 0\n                    );\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.is_touch_supported()',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_looks.js",
    "content": "module.exports = {\n    getBlocks() {\n        return {\n            show: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'show',\n                },\n                class: 'visibility',\n                isNotFor: [],\n                func(sprite, script) {\n                    sprite.setVisible(true);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.show()'] },\n            },\n            hide: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'hide',\n                },\n                class: 'visibility',\n                isNotFor: [],\n                func(sprite, script) {\n                    sprite.setVisible(false);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.hide()'] },\n            },\n            dialog_time: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.speak, 'speak'],\n                            [Lang.Blocks.think, 'think'],\n                            // [Lang.Blocks.yell, 'yell'],\n                        ],\n                        value: 'speak',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.LOOKS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.block_hi],\n                        },\n                        {\n                            type: 'number',\n                            params: ['4'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'dialog_time',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'dialog_time',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    SECOND: 1,\n                    OPTION: 2,\n                },\n                class: 'say',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        let [timeValue, message] = script.getValues(['SECOND', 'VALUE'], script);\n                        timeValue = Number(timeValue);\n\n                        const mode = script.getField('OPTION', script);\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        if (message === '') {\n                            message = '    ';\n                        } else if (typeof message === 'boolean') {\n                            message = message ? 'True' : 'False';\n                        } else {\n                            message = `${message}`;\n                        }\n                        message = Entry.convertToRoundedDecimals(message, 3);\n                        new Entry.Dialog(sprite, message, mode);\n                        sprite.syncDialogVisible(sprite.getVisible());\n                        let timeoutId = 0;\n                        const stopDialog = () => {\n                            script.timeFlag = 0;\n                            if (timeoutId) {\n                                clearTimeout(timeoutId);\n                                timeoutId = 0;\n                            }\n                        };\n                        sprite.stopDialog = stopDialog;\n                        timeoutId = Entry.engine.setTimeout(stopDialog, timeValue * 1000);\n                    }\n                    if (script.timeFlag == 0) {\n                        delete script.timeFlag;\n                        delete script.isStart;\n                        if (sprite.dialog) {\n                            sprite.dialog.remove();\n                            sprite.stopDialog = undefined;\n                        }\n                        return script.callReturn();\n                    }\n                    return script;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.print_for_sec(%1, %2)',\n                            params: [null, null, 'speak'],\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.speak, 'speak'],\n                                        [Lang.Blocks.think, 'think'],\n                                        // [Lang.Blocks.yell, 'yell'],\n                                    ],\n                                    value: 'speak',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.LOOKS,\n                                    converter: Entry.block.converters.returnStringValue,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            dialog: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.speak, 'speak'],\n                            [Lang.Blocks.think, 'think'],\n                            // [Lang.Blocks.yell, 'yell'],\n                        ],\n                        value: 'speak',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.LOOKS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.block_hi],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'dialog',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'dialog',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    OPTION: 1,\n                },\n                class: 'say',\n                isNotFor: [],\n                func(sprite, script) {\n                    let message = script.getValue('VALUE', script);\n                    if (message === '') {\n                        message = '    ';\n                    } else if (typeof message === 'boolean') {\n                        message = message ? 'True' : 'False';\n                    } else {\n                        message = `${message}`;\n                    }\n                    const mode = script.getField('OPTION', script);\n                    message = Entry.convertToRoundedDecimals(message, 3);\n                    new Entry.Dialog(sprite, message, mode);\n                    sprite.syncDialogVisible(sprite.getVisible());\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.print(%1)',\n                            params: [null, 'speak'],\n                        },\n                    ],\n                },\n            },\n            remove_dialog: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'remove_dialog',\n                },\n                class: 'say',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (sprite.stopDialog) {\n                        sprite.stopDialog();\n                    }\n                    if (sprite.dialog) {\n                        sprite.dialog.remove();\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.clear_print()'] },\n            },\n            change_to_some_shape: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'get_pictures',\n                            id: 'z4jm',\n                        },\n                        null,\n                    ],\n                    type: 'change_to_some_shape',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'get_pictures',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'change_to_some_shape',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'shape',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const imageId = script.getStringValue('VALUE');\n                    const picture = sprite.parent.getPicture(imageId);\n\n                    sprite.setImage(picture);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            passTest: true,\n                            syntax: 'Entry.change_shape(%1)',\n                        },\n                    ],\n                },\n            },\n            change_to_next_shape: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.LOOKS_change_shape_next, 'next'],\n                            [Lang.Blocks.LOOKS_change_shape_prev, 'prev'],\n                        ],\n                        value: 'next',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.LOOKS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'change_to_next_shape',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'change_to_next_shape',\n                },\n                paramsKeyMap: {\n                    DRIECTION: 0,\n                },\n                class: 'shape',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    let picture;\n                    if (script.getStringField('DRIECTION') !== 'prev') {\n                        picture = sprite.parent.getNextPicture(sprite.picture.id);\n                    } else {\n                        picture = sprite.parent.getPrevPicture(sprite.picture.id);\n                    }\n                    sprite.setImage(picture);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.change_shape_to(%1)',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.LOOKS_change_shape_next, 'next'],\n                                        [Lang.Blocks.LOOKS_change_shape_prev, 'prev'],\n                                    ],\n                                    value: 'next',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.LOOKS,\n                                    converter: Entry.block.converters.returnStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.change_to_next_shape[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            add_effect_amount: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.color, 'color'],\n                            [Lang.Blocks.brightness, 'brightness'],\n                            [Lang.Blocks.transparency, 'transparency'],\n                        ],\n                        value: 'color',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.LOOKS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'add_effect_amount',\n                },\n                pyHelpDef: {\n                    params: [\n                        'A&value',\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'add_effect_amount',\n                },\n                paramsKeyMap: {\n                    EFFECT: 0,\n                    VALUE: 1,\n                },\n                class: 'effect',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const effect = script.getField('EFFECT', script);\n                    const effectValue = script.getNumberValue('VALUE', script);\n                    let effectName = '';\n                    if (effect === 'color') {\n                        sprite.effect.hsv = effectValue + sprite.effect.hsv;\n                        effectName = 'hsv';\n                    } else if (effect === 'brightness') {\n                        sprite.effect.brightness = effectValue + sprite.effect.brightness;\n                        effectName = 'brightness';\n                    } else if (effect === 'transparency') {\n                        sprite.effect.alpha = sprite.effect.alpha - effectValue / 100;\n                        effectName = 'alpha';\n                    }\n                    sprite.applyFilter(true, [effectName]);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.add_effect(%1, %2)',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.color, 'color'],\n                                        [Lang.Blocks.brightness, 'brightness'],\n                                        [Lang.Blocks.transparency, 'transparency'],\n                                    ],\n                                    value: 'color',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.LOOKS,\n                                    converter: Entry.block.converters.returnStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.add_effect_amount[0]',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            change_effect_amount: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.color, 'color'],\n                            [Lang.Blocks.brightness, 'brightness'],\n                            [Lang.Blocks.transparency, 'transparency'],\n                        ],\n                        value: 'color',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.LOOKS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                        null,\n                    ],\n                    type: 'change_effect_amount',\n                },\n                pyHelpDef: {\n                    params: [\n                        'A&value',\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'change_effect_amount',\n                },\n                paramsKeyMap: {\n                    EFFECT: 0,\n                    VALUE: 1,\n                },\n                class: 'effect',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    const effect = script.getField('EFFECT', script);\n                    const effectValue = script.getNumberValue('VALUE', script);\n                    let effectName = '';\n                    if (effect === 'color') {\n                        sprite.effect.hsv = effectValue;\n                        effectName = 'hsv';\n                    } else if (effect === 'brightness') {\n                        sprite.effect.brightness = effectValue;\n                        effectName = 'brightness';\n                    } else if (effect === 'transparency') {\n                        sprite.effect.alpha = 1 - effectValue / 100;\n                        effectName = 'alpha';\n                    }\n                    sprite.applyFilter(true, [effectName]);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.set_effect(%1, %2)',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.color, 'color'],\n                                        [Lang.Blocks.brightness, 'brightness'],\n                                        [Lang.Blocks.transparency, 'transparency'],\n                                    ],\n                                    value: 'color',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.LOOKS,\n                                    converter: Entry.block.converters.returnStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.change_effect_amount[0]',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            erase_all_effects: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'erase_all_effects',\n                },\n                class: 'effect',\n                isNotFor: ['textBox'],\n                func(sprite, script) {\n                    sprite.resetFilter();\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.clear_effect()'] },\n            },\n            change_scale_size: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'change_scale_size',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'change_scale_size',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'scale',\n                isNotFor: [],\n                func(sprite, script) {\n                    const sizeValue = script.getNumberValue('VALUE', script);\n                    sprite.setSize(sprite.getSize() + sizeValue);\n                    // sprite.setWidth(sprite.getWidth() * 2);\n                    // sprite.setScaleX(sprite.getScaleX() * 2);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.add_size(%1)'] },\n            },\n            set_scale_size: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                        null,\n                    ],\n                    type: 'set_scale_size',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'set_scale_size',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'scale',\n                isNotFor: [],\n                func(sprite, script) {\n                    const sizeValue = script.getNumberValue('VALUE', script);\n                    sprite.setSize(sizeValue);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_size(%1)'] },\n            },\n            stretch_scale_size: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.width, 'WIDTH'],\n                            [Lang.Blocks.height, 'HEIGHT'],\n                        ],\n                        value: 'WIDTH',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.LOOKS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'stretch_scale_size',\n                },\n                paramsKeyMap: {\n                    DIMENSION: 0,\n                    VALUE: 1,\n                },\n                class: 'scale',\n                isNotFor: [],\n                func(sprite, script) {\n                    const dimension = script.getValue('DIMENSION', script);\n                    const sizeValue = script.getNumberValue('VALUE', script);\n                    if (dimension === 'WIDTH') {\n                        sprite.setXSize(sprite.getSize() + sizeValue);\n                    } else {\n                        sprite.setYSize(sprite.getSize() + sizeValue);\n                    }\n                    return script.callReturn();\n                },\n            },\n            reset_scale_size: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'reset_scale_size',\n                },\n                paramsKeyMap: {},\n                class: 'scale',\n                isNotFor: [],\n                func(sprite, script) {\n                    sprite.resetSize();\n                    return script.callReturn();\n                },\n            },\n            flip_x: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'flip_x',\n                },\n                class: 'flip',\n                isNotFor: [],\n                func(sprite, script) {\n                    sprite.setScaleY(-1 * sprite.getScaleY());\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.flip_horizontal()'] },\n            },\n            flip_y: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'flip_y',\n                },\n                class: 'flip',\n                isNotFor: [],\n                func(sprite, script) {\n                    sprite.setScaleX(-1 * sprite.getScaleX());\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.flip_vertical()'] },\n            },\n            change_object_index: {\n                color: EntryStatic.colorSet.block.default.LOOKS,\n                outerLine: EntryStatic.colorSet.block.darken.LOOKS,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.LOOKS_change_object_index_sub_1, 'FRONT'],\n                            [Lang.Blocks.LOOKS_change_object_index_sub_2, 'FORWARD'],\n                            [Lang.Blocks.LOOKS_change_object_index_sub_3, 'BACKWARD'],\n                            [Lang.Blocks.LOOKS_change_object_index_sub_4, 'BACK'],\n                        ],\n                        value: 'FRONT',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.LOOKS,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/looks_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'change_object_index',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'change_object_index',\n                },\n                paramsKeyMap: {\n                    LOCATION: 0,\n                },\n                class: 'z-index',\n                isNotFor: [],\n                func(sprite, script) {\n                    const location = script.getField('LOCATION', script);\n                    const selectedObjectContainer = Entry.stage.selectedObjectContainer;\n                    const currentIndex = selectedObjectContainer.getChildIndex(sprite.object);\n                    const max = selectedObjectContainer.children.length - 1;\n                    let targetIndex = currentIndex;\n\n                    switch (location) {\n                        case 'FRONT':\n                            targetIndex = max;\n                            break;\n                        case 'FORWARD': {\n                            if (currentIndex === max) {\n                                break;\n                            }\n\n                            const frontEntity = selectedObjectContainer.getChildAt(\n                                currentIndex + 1\n                            ).entity;\n\n                            const offsetCount =\n                                1 +\n                                (sprite.shapes.length ? 1 : 0) +\n                                (sprite.paintShapes.length ? 1 : 0);\n                            targetIndex += offsetCount + frontEntity.stamps.length;\n                            break;\n                        }\n                        case 'BACKWARD': {\n                            const offsetCount =\n                                1 +\n                                (sprite.shapes.length ? 1 : 0) +\n                                (sprite.paintShapes.length ? 1 : 0);\n                            const backIndex = targetIndex - offsetCount + sprite.stamps.length;\n                            let backEntity = selectedObjectContainer.getChildAt(backIndex);\n                            if (!backEntity) {\n                                targetIndex = 0;\n                                break;\n                            }\n                            backEntity = backEntity.entity;\n                            targetIndex -= offsetCount + backEntity.stamps.length;\n                            break;\n                        }\n                        case 'BACK':\n                            targetIndex = 0;\n                            break;\n                    }\n                    Entry.stage.setEntityIndex(sprite, targetIndex);\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.send_layer_to(%1)',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.LOOKS_change_object_index_sub_1, 'FRONT'],\n                                        [Lang.Blocks.LOOKS_change_object_index_sub_2, 'FORWARD'],\n                                        [Lang.Blocks.LOOKS_change_object_index_sub_3, 'BACKWARD'],\n                                        [Lang.Blocks.LOOKS_change_object_index_sub_4, 'BACK'],\n                                    ],\n                                    value: 'FRONT',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.LOOKS,\n                                    converter: Entry.block.converters.returnStringValueLowerCase,\n                                    codeMap: 'Entry.CodeMap.Entry.change_object_index[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_moving.js",
    "content": "module.exports = {\n    getBlocks() {\n        function moveInToBound(object, wall) {\n            if (wall.up.y > object.y) {\n                object.y = wall.up.y;\n            }\n\n            if (wall.down.y < object.y) {\n                object.y = wall.down.y;\n            }\n\n            if (wall.right.x < object.x) {\n                object.x = wall.right.x;\n            }\n\n            if (wall.left.x > object.x) {\n                object.x = wall.left.x;\n            }\n        }\n\n        return {\n            move_direction: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'move_direction',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'move_direction',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'walk',\n                isNotFor: [],\n                func(sprite, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    sprite.setX(\n                        sprite.getX() +\n                            value *\n                                Math.cos(\n                                    ((sprite.getRotation() + sprite.getDirection() - 90) / 180) *\n                                        Math.PI\n                                )\n                    );\n                    sprite.setY(\n                        sprite.getY() -\n                            value *\n                                Math.sin(\n                                    ((sprite.getRotation() + sprite.getDirection() - 90) / 180) *\n                                        Math.PI\n                                )\n                    );\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    if (sprite.paint && !sprite.paint.stop) {\n                        sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.move_to_direction(%1)'] },\n            },\n            bounce_wall: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'bounce_wall',\n                },\n                class: 'walk',\n                isNotFor: [],\n                func(sprite, script) {\n                    const threshold = 0;\n                    const method = sprite.parent.getRotateMethod();\n\n                    let angle;\n                    if (method === 'free') {\n                        angle = (sprite.getRotation() + sprite.getDirection()).mod(360);\n                    } else {\n                        angle = sprite.getDirection();\n                    }\n\n                    let skip = Entry.Utils.COLLISION.NONE;\n                    if ((angle < 90 && angle >= 0) || (angle < 360 && angle >= 270)) {\n                        skip = sprite.collision == Entry.Utils.COLLISION.UP;\n                        let up = ndgmr.checkPixelCollision(\n                            Entry.stage.wall.up,\n                            sprite.object,\n                            threshold,\n                            false\n                        );\n                        if (!up && skip) {\n                            sprite.collision = Entry.Utils.COLLISION.NONE;\n                        }\n\n                        if (up && skip) {\n                            up = false;\n                        }\n\n                        if (up) {\n                            if (method === 'free') {\n                                sprite.setRotation(\n                                    -sprite.getRotation() - sprite.getDirection() * 2 + 180\n                                );\n                            } else {\n                                sprite.setDirection(-sprite.getDirection() + 180);\n                            }\n\n                            sprite.collision = Entry.Utils.COLLISION.UP;\n                        } else {\n                            skip = sprite.collision == Entry.Utils.COLLISION.DOWN;\n                            let down = ndgmr.checkPixelCollision(\n                                Entry.stage.wall.down,\n                                sprite.object,\n                                threshold,\n                                false\n                            );\n                            if (!down && skip) {\n                                sprite.collision = Entry.Utils.COLLISION.NONE;\n                            }\n\n                            if (down && skip) {\n                                down = false;\n                            }\n\n                            if (down) {\n                                if (method === 'free') {\n                                    sprite.setRotation(\n                                        -sprite.getRotation() - sprite.getDirection() * 2 + 180\n                                    );\n                                } else {\n                                    sprite.setDirection(-sprite.getDirection() + 180);\n                                }\n\n                                sprite.collision = Entry.Utils.COLLISION.DOWN;\n                            }\n                        }\n                    } else if (angle < 270 && angle >= 90) {\n                        skip = sprite.collision == Entry.Utils.COLLISION.DOWN;\n                        let down = ndgmr.checkPixelCollision(\n                            Entry.stage.wall.down,\n                            sprite.object,\n                            threshold,\n                            false\n                        );\n                        if (!down && skip) {\n                            sprite.collision = Entry.Utils.COLLISION.NONE;\n                        }\n\n                        if (down && skip) {\n                            down = false;\n                        }\n\n                        if (down) {\n                            if (method === 'free') {\n                                sprite.setRotation(\n                                    -sprite.getRotation() - sprite.getDirection() * 2 + 180\n                                );\n                            } else {\n                                sprite.setDirection(-sprite.getDirection() + 180);\n                            }\n\n                            sprite.collision = Entry.Utils.COLLISION.DOWN;\n                            //sprite.setY(-135 + bound.height/2 + 1);\n                        } else {\n                            skip = sprite.collision == Entry.Utils.COLLISION.UP;\n                            let up = ndgmr.checkPixelCollision(\n                                Entry.stage.wall.up,\n                                sprite.object,\n                                threshold,\n                                false\n                            );\n                            if (!up && skip) {\n                                sprite.collision = Entry.Utils.COLLISION.NONE;\n                            }\n\n                            if (up && skip) {\n                                up = false;\n                            }\n\n                            if (up) {\n                                if (method === 'free') {\n                                    sprite.setRotation(\n                                        -sprite.getRotation() - sprite.getDirection() * 2 + 180\n                                    );\n                                } else {\n                                    sprite.setDirection(-sprite.getDirection() + 180);\n                                }\n\n                                sprite.collision = Entry.Utils.COLLISION.UP;\n                                //sprite.setY(135 - bound.height/2 - 1);\n                            }\n                        }\n                    }\n                    if (angle < 360 && angle >= 180) {\n                        skip = sprite.collision == Entry.Utils.COLLISION.LEFT;\n                        let left = ndgmr.checkPixelCollision(\n                            Entry.stage.wall.left,\n                            sprite.object,\n                            threshold,\n                            false\n                        );\n                        if (!left && skip) {\n                            sprite.collision = Entry.Utils.COLLISION.NONE;\n                        }\n\n                        if (left && skip) {\n                            left = false;\n                        }\n\n                        if (left) {\n                            if (method === 'free') {\n                                sprite.setRotation(\n                                    -sprite.getRotation() - sprite.getDirection() * 2\n                                );\n                            } else {\n                                sprite.setDirection(-sprite.getDirection() + 360);\n                            }\n\n                            sprite.collision = Entry.Utils.COLLISION.LEFT;\n                        } else {\n                            skip = sprite.collision == Entry.Utils.COLLISION.RIGHT;\n                            let right = ndgmr.checkPixelCollision(\n                                Entry.stage.wall.right,\n                                sprite.object,\n                                threshold,\n                                false\n                            );\n                            if (!right && skip) {\n                                sprite.collision = Entry.Utils.COLLISION.NONE;\n                            }\n\n                            if (right && skip) {\n                                right = false;\n                            }\n\n                            if (right) {\n                                if (method === 'free') {\n                                    sprite.setRotation(\n                                        -sprite.getRotation() - sprite.getDirection() * 2\n                                    );\n                                } else {\n                                    sprite.setDirection(-sprite.getDirection() + 360);\n                                }\n\n                                sprite.collision = Entry.Utils.COLLISION.RIGHT;\n                            }\n                        }\n                    } else if (angle < 180 && angle >= 0) {\n                        skip = sprite.collision == Entry.Utils.COLLISION.RIGHT;\n                        let right = ndgmr.checkPixelCollision(\n                            Entry.stage.wall.right,\n                            sprite.object,\n                            threshold,\n                            false\n                        );\n                        if (!right && skip) {\n                            sprite.collision = Entry.Utils.COLLISION.NONE;\n                        }\n\n                        if (right && skip) {\n                            right = false;\n                        }\n\n                        if (right) {\n                            if (method === 'free') {\n                                sprite.setRotation(\n                                    -sprite.getRotation() - sprite.getDirection() * 2\n                                );\n                            } else {\n                                sprite.setDirection(-sprite.getDirection() + 360);\n                            }\n\n                            sprite.collision = Entry.Utils.COLLISION.RIGHT;\n                        } else {\n                            skip = sprite.collision == Entry.Utils.COLLISION.LEFT;\n                            let left = ndgmr.checkPixelCollision(\n                                Entry.stage.wall.left,\n                                sprite.object,\n                                threshold,\n                                false\n                            );\n                            if (!left && skip) {\n                                sprite.collision = Entry.Utils.COLLISION.NONE;\n                            }\n\n                            if (left && skip) {\n                                left = false;\n                            }\n\n                            if (left) {\n                                if (method === 'free') {\n                                    sprite.setRotation(\n                                        -sprite.getRotation() - sprite.getDirection() * 2\n                                    );\n                                } else {\n                                    sprite.setDirection(-sprite.getDirection() + 360);\n                                }\n\n                                sprite.collision = Entry.Utils.COLLISION.LEFT;\n                            }\n                        }\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.bounce_on_edge()'] },\n            },\n            move_x: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'move_x',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'move_x',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'move_relative',\n                isNotFor: [],\n                func(sprite, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    sprite.setX(sprite.getX() + value);\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    if (sprite.paint && !sprite.paint.stop) {\n                        sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.add_x(%1)'] },\n            },\n            move_y: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'move_y',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'move_y',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'move_relative',\n                isNotFor: [],\n                func(sprite, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    sprite.setY(sprite.getY() + value);\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    if (sprite.paint && !sprite.paint.stop) {\n                        sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.add_y(%1)'] },\n            },\n            move_xy_time: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['2'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'move_xy_time',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['C&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'move_xy_time',\n                },\n                paramsKeyMap: {\n                    VALUE1: 0,\n                    VALUE2: 1,\n                    VALUE3: 2,\n                },\n                class: 'move_relative',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        let [timeValue, xValue, yValue] = script.getValues(\n                            ['VALUE1', 'VALUE2', 'VALUE3'],\n                            script\n                        );\n                        timeValue = Number(timeValue);\n                        xValue = Number(xValue);\n                        yValue = Number(yValue);\n\n                        script.isStart = true;\n                        script.frameCount = Math.max(Math.floor(timeValue * Entry.FPS), 1);\n                        script.dX = xValue / script.frameCount;\n                        script.dY = yValue / script.frameCount;\n\n                        if (script.frameCount == 1) {\n                            action();\n                        }\n                    }\n\n                    if (script.frameCount != 0) {\n                        action();\n                        return script;\n                    } else {\n                        delete script.isStart;\n                        delete script.frameCount;\n                        return script.callReturn();\n                    }\n\n                    function action() {\n                        sprite.setX(sprite.getX() + script.dX);\n                        sprite.setY(sprite.getY() + script.dY);\n                        script.frameCount--;\n                        if (sprite.brush && !sprite.brush.stop) {\n                            sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                        }\n                        if (sprite.paint && !sprite.paint.stop) {\n                            sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                        }\n                    }\n                },\n                syntax: { js: [], py: ['Entry.add_xy_for_sec(%2, %3, %1)'] },\n            },\n            locate_x: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'locate_x',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'locate_x',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'move_absolute',\n                isNotFor: [],\n                func(sprite, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    sprite.setX(value);\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    if (sprite.paint && !sprite.paint.stop) {\n                        sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_x(%1)'] },\n            },\n            locate_y: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'locate_y',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'locate_y',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'move_absolute',\n                isNotFor: [],\n                func(sprite, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    sprite.setY(value);\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    if (sprite.paint && !sprite.paint.stop) {\n                        sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_y(%1)'] },\n            },\n            locate_xy: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        null,\n                    ],\n                    type: 'locate_xy',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                    ],\n                    type: 'locate_xy',\n                },\n                paramsKeyMap: {\n                    VALUE1: 0,\n                    VALUE2: 1,\n                },\n                class: 'move_absolute',\n                isNotFor: [],\n                func(sprite, script) {\n                    let [value1, value2] = script.getValues(['VALUE1', 'VALUE2'], script);\n                    value1 = Number(value1);\n                    value2 = Number(value2);\n\n                    sprite.setX(value1);\n                    sprite.setY(value2);\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    if (sprite.paint && !sprite.paint.stop) {\n                        sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_xy(%1, %2)'] },\n            },\n            locate_xy_time: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['2'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'locate_xy_time',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['C&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'locate_xy_time',\n                },\n                paramsKeyMap: {\n                    VALUE1: 0,\n                    VALUE2: 1,\n                    VALUE3: 2,\n                },\n                class: 'move_absolute',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        let [timeValue, xValue, yValue] = script.getValues(\n                            ['VALUE1', 'VALUE2', 'VALUE3'],\n                            script\n                        );\n                        timeValue = Number(timeValue);\n                        xValue = Number(xValue);\n                        yValue = Number(yValue);\n\n                        script.x = xValue;\n                        script.y = yValue;\n                        script.isStart = true;\n                        script.frameCount = Math.max(Math.floor(timeValue * Entry.FPS), 1);\n                        if (script.frameCount == 1) {\n                            action();\n                        }\n                    }\n\n                    if (script.frameCount != 0) {\n                        action();\n                        return script;\n                    } else {\n                        delete script.isStart;\n                        delete script.frameCount;\n                        return script.callReturn();\n                    }\n\n                    function action() {\n                        let dX = script.x - sprite.getX();\n                        let dY = script.y - sprite.getY();\n                        dX /= script.frameCount;\n                        dY /= script.frameCount;\n                        sprite.setX(sprite.getX() + dX);\n                        sprite.setY(sprite.getY() + dY);\n                        script.frameCount--;\n                        if (sprite.brush && !sprite.brush.stop) {\n                            sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                        }\n                        if (sprite.paint && !sprite.paint.stop) {\n                            sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                        }\n                    }\n                },\n                syntax: { js: [], py: ['Entry.set_xy_for_sec(%2, %3, %1)'] },\n            },\n            locate: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'spritesWithMouse',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.MOVING,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'locate',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'locate',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'move_absolute',\n                isNotFor: [],\n                func(sprite, script) {\n                    const targetId = script.getField('VALUE', script);\n                    let x;\n                    let y;\n                    if (targetId === 'mouse') {\n                        x = Entry.stage.mouseCoordinate.x;\n                        y = Entry.stage.mouseCoordinate.y;\n                    } else {\n                        const targetEntity = Entry.container.getEntity(targetId);\n                        x = targetEntity.getX();\n                        y = targetEntity.getY();\n                    }\n                    sprite.setX(Number(x));\n                    sprite.setY(Number(y));\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(x, y * -1);\n                    }\n                    if (sprite.paint && !sprite.paint.stop) {\n                        sprite.paint.lineTo(x, y * -1);\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.move_to(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'spritesWithMouse',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.MOVING,\n                                    converter: Entry.block.converters.returnStringKey,\n                                    codeMap: 'Entry.CodeMap.Entry.locate[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            locate_object_time: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'spritesWithMouse',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.MOVING,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['2'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'locate_object_time',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        'A&value',\n                    ],\n                    type: 'locate_object_time',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    TARGET: 1,\n                },\n                class: 'move_absolute',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        let xValue;\n                        let yValue;\n                        const targetId = script.getField('TARGET', script);\n                        const timeValue = script.getNumberValue('VALUE', script);\n                        const frameCount = Math.floor(timeValue * Entry.FPS);\n                        const mouseCoordi = Entry.stage.mouseCoordinate;\n\n                        if (frameCount != 0) {\n                            if (targetId === 'mouse') {\n                                xValue = mouseCoordi.x - sprite.getX();\n                                yValue = mouseCoordi.y - sprite.getY();\n                            } else {\n                                const targetEntity = Entry.container.getEntity(targetId);\n                                xValue = targetEntity.getX() - sprite.getX();\n                                yValue = targetEntity.getY() - sprite.getY();\n                            }\n                            script.isStart = true;\n                            script.frameCount = frameCount;\n                            script.dX = xValue / script.frameCount;\n                            script.dY = yValue / script.frameCount;\n                        } else {\n                            //frame count is zero so execute immediately\n                            if (targetId === 'mouse') {\n                                xValue = Number(mouseCoordi.x);\n                                yValue = Number(mouseCoordi.y);\n                            } else {\n                                const targetEntity = Entry.container.getEntity(targetId);\n                                xValue = targetEntity.getX();\n                                yValue = targetEntity.getY();\n                            }\n                            sprite.setX(xValue);\n                            sprite.setY(yValue);\n                            if (sprite.brush && !sprite.brush.stop) {\n                                sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                            }\n                            if (sprite.paint && !sprite.paint.stop) {\n                                sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                            }\n                            return script.callReturn();\n                        }\n                    }\n                    if (script.frameCount != 0) {\n                        sprite.setX(sprite.getX() + script.dX);\n                        sprite.setY(sprite.getY() + script.dY);\n                        script.frameCount--;\n                        if (sprite.brush && !sprite.brush.stop) {\n                            sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                        }\n                        if (sprite.paint && !sprite.paint.stop) {\n                            sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                        }\n                        return script;\n                    } else {\n                        delete script.isStart;\n                        delete script.frameCount;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.move_to_for_sec(%2, %1)',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'spritesWithMouse',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.MOVING,\n                                    converter: Entry.block.converters.returnStringKey,\n                                    codeMap: 'Entry.CodeMap.Entry.locate_object_time[1]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            rotate_relative: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'angle',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['90'],\n                        },\n                        null,\n                    ],\n                    type: 'rotate_relative',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['A&value'],\n                        },\n                    ],\n                    type: 'rotate_relative',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'rotate',\n                isNotFor: [],\n                func(entity, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    entity.setRotation(value + entity.getRotation());\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.add_rotation(%1)'] },\n            },\n            direction_relative: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        defaultType: 'angle',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['90'],\n                        },\n                        null,\n                    ],\n                    type: 'direction_relative',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'direction_relative',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'rotate',\n                isNotFor: [],\n                func(entity, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    entity.setDirection(value + entity.getDirection());\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.add_direction(%1)'] },\n            },\n            rotate_by_time: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'angle',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['2'],\n                        },\n                        {\n                            type: 'angle',\n                            params: ['90'],\n                        },\n                        null,\n                    ],\n                    type: 'rotate_by_time',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'angle',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'rotate_by_time',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    ANGLE: 1,\n                },\n                class: 'rotate',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        let [timeValue, angleValue] = script.getValues(['VALUE', 'ANGLE'], script);\n                        timeValue = Number(timeValue);\n                        angleValue = Number(angleValue);\n\n                        script.isStart = true;\n                        script.frameCount = Math.max(Math.floor(timeValue * Entry.FPS), 1);\n                        script.dAngle = angleValue / script.frameCount;\n\n                        if (script.frameCount == 1) {\n                            action();\n                        }\n                    }\n                    if (script.frameCount != 0) {\n                        action();\n                        return script;\n                    } else {\n                        delete script.isStart;\n                        delete script.frameCount;\n                        return script.callReturn();\n                    }\n\n                    function action() {\n                        sprite.setRotation(sprite.getRotation() + script.dAngle);\n                        script.frameCount--;\n                    }\n                },\n                syntax: { js: [], py: ['Entry.add_rotation_for_sec(%2, %1)'] },\n            },\n            direction_relative_duration: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'angle',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['2'],\n                        },\n                        {\n                            type: 'angle',\n                            params: ['90'],\n                        },\n                        null,\n                    ],\n                    type: 'direction_relative_duration',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'angle',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'direction_relative_duration',\n                },\n                paramsKeyMap: {\n                    DURATION: 0,\n                    AMOUNT: 1,\n                },\n                class: 'rotate',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        let [timeValue, directionValue] = script.getValues(\n                            ['DURATION', 'AMOUNT'],\n                            script\n                        );\n                        timeValue = Number(timeValue);\n                        directionValue = Number(directionValue);\n\n                        script.isStart = true;\n                        script.frameCount = Math.max(Math.floor(timeValue * Entry.FPS), 1);\n                        script.dDirection = directionValue / script.frameCount;\n\n                        if (script.frameCount == 1) {\n                            action();\n                        }\n                    }\n                    if (script.frameCount != 0) {\n                        action();\n                        return script;\n                    } else {\n                        delete script.isStart;\n                        delete script.frameCount;\n                        delete script.dDirection;\n                        return script.callReturn();\n                    }\n\n                    function action() {\n                        sprite.setDirection(sprite.getDirection() + script.dDirection);\n                        script.frameCount--;\n                    }\n                },\n                syntax: { js: [], py: ['Entry.add_direction_for_sec(%2, %1)'] },\n            },\n            rotate_absolute: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        defaultType: 'angle',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['90'],\n                        },\n                        null,\n                    ],\n                    type: 'rotate_absolute',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'rotate_absolute',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'rotate_absolute',\n                isNotFor: [],\n                func(entity, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    entity.setRotation(value);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_rotation(%1)'] },\n            },\n            direction_absolute: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        defaultType: 'angle',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['90'],\n                        },\n                        null,\n                    ],\n                    type: 'direction_absolute',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'direction_absolute',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'rotate_absolute',\n                isNotFor: [],\n                func(entity, script) {\n                    const value = script.getNumberValue('VALUE', script);\n                    entity.setDirection(value);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_direction(%1)'] },\n            },\n            see_angle_object: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'spritesWithMouse',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.MOVING,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'see_angle_object',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'see_angle_object',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'rotate_absolute',\n                isNotFor: [],\n                func(sprite, script) {\n                    const targetId = script.getField('VALUE', script);\n                    const spriteX = sprite.getX();\n                    const spriteY = sprite.getY();\n                    let deltaX;\n                    let deltaY;\n                    let value;\n\n                    if (sprite.parent.id == targetId) {\n                        return script.callReturn();\n                    }\n\n                    if (targetId === 'mouse') {\n                        const mX = Entry.stage.mouseCoordinate.x;\n                        const mY = Entry.stage.mouseCoordinate.y;\n\n                        deltaX = mX - spriteX;\n                        deltaY = mY - spriteY;\n                    } else {\n                        const targetEntity = Entry.container.getEntity(targetId);\n                        deltaX = targetEntity.getX() - spriteX;\n                        deltaY = targetEntity.getY() - spriteY;\n                    }\n\n                    if (deltaX === 0 && deltaY === 0) {\n                        value = sprite.getDirection() + sprite.getRotation();\n                    } else if (deltaX >= 0) {\n                        value = (-Math.atan(deltaY / deltaX) / Math.PI) * 180 + 90;\n                    } else {\n                        value = (-Math.atan(deltaY / deltaX) / Math.PI) * 180 + 270;\n                    }\n                    if (this.entity.parent.getRotateMethod() === 'free') {\n                        const nativeDirection = sprite.getDirection() + sprite.getRotation();\n                        sprite.setRotation(sprite.getRotation() + value - nativeDirection);\n                    } else {\n                        sprite.setDirection(value);\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.look_at(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'spritesWithMouse',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.MOVING,\n                                    converter: Entry.block.converters.returnStringKey,\n                                    codeMap: 'Entry.CodeMap.Entry.see_angle_object[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            move_to_angle: {\n                color: EntryStatic.colorSet.block.default.MOVING,\n                outerLine: EntryStatic.colorSet.block.darken.MOVING,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'angle',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/moving_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['90'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'move_to_angle',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'angle',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'move_to_angle',\n                },\n                paramsKeyMap: {\n                    ANGLE: 0,\n                    VALUE: 1,\n                },\n                class: 'move_rotate',\n                isNotFor: [],\n                func(sprite, script) {\n                    let [value, angle] = script.getValues(['VALUE', 'ANGLE'], script);\n                    value = Number(value);\n                    angle = Number(angle);\n\n                    sprite.setX(sprite.getX() + value * Math.cos(((angle - 90) / 180) * Math.PI));\n                    sprite.setY(sprite.getY() - value * Math.sin(((angle - 90) / 180) * Math.PI));\n                    if (sprite.brush && !sprite.brush.stop) {\n                        sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    if (sprite.paint && !sprite.paint.stop) {\n                        sprite.paint.lineTo(sprite.getX(), sprite.getY() * -1);\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.move_to_degree(%2, %1)'] },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_sound.js",
    "content": "import _clamp from 'lodash/clamp';\n\nEntry.playbackRateValue = 1;\n\nmodule.exports = {\n    getBlocks() {\n        return {\n            sound_something_with_block: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                        },\n                        null,\n                    ],\n                    type: 'sound_something_with_block',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_something_with_block',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'sound_play',\n                isNotFor: [],\n                func(sprite, script) {\n                    const soundId = script.getStringValue('VALUE', script);\n                    const sound = sprite.parent.getSound(soundId);\n\n                    if (sound) {\n                        const instance = Entry.Utils.playSound(sound.id);\n                        Entry.Utils.addSoundInstances(instance, sprite);\n                    }\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            passTest: true,\n                            syntax: 'Entry.play_sound(%1)',\n                        },\n                    ],\n                },\n            },\n            sound_something_second_with_block: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                            id: '95dw',\n                        },\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_something_second_with_block',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_something_second_with_block',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    SECOND: 1,\n                },\n                class: 'sound_play',\n                isNotFor: [],\n                func(sprite, script) {\n                    let [soundId, timeValue] = script.getValues(['VALUE', 'SECOND'], script);\n                    soundId = String(soundId);\n                    timeValue = Number(timeValue);\n\n                    const sound = sprite.parent.getSound(soundId);\n                    if (sound) {\n                        const instance = Entry.Utils.playSound(sound.id, {\n                            startTime: 0,\n                            duration: timeValue * 1000,\n                        });\n                        Entry.Utils.addSoundInstances(instance, sprite);\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            passTest: true,\n                            syntax: 'Entry.play_sound_for_sec(%1, %2)',\n                        },\n                    ],\n                },\n            },\n            sound_from_to: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                        },\n                        {\n                            type: 'text',\n                            params: ['1'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_from_to',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_from_to',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    START: 1,\n                    END: 2,\n                },\n                class: 'sound_play',\n                isNotFor: [],\n                func(sprite, script) {\n                    const soundId = script.getStringValue('VALUE', script);\n                    const sound = sprite.parent.getSound(soundId);\n\n                    if (sound) {\n                        let [start, end] = script.getValues(['START', 'END'], script);\n                        start = Number(start) * 1000;\n                        end = Number(end) * 1000;\n                        const instance = Entry.Utils.playSound(sound.id, {\n                            startTime: Math.min(start, end),\n                            duration: Math.max(start, end) - Math.min(start, end),\n                        });\n                        Entry.Utils.addSoundInstances(instance, sprite);\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            passTest: true,\n                            syntax: 'Entry.play_sound_from_to(%1, %2, %3)',\n                        },\n                    ],\n                },\n            },\n            sound_something_wait_with_block: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                        },\n                        null,\n                    ],\n                    type: 'sound_something_wait_with_block',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_something_wait_with_block',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'sound_wait',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isPlay) {\n                        script.isPlay = true;\n                        const soundId = script.getStringValue('VALUE', script);\n                        const sound = sprite.parent.getSound(soundId);\n                        if (sound) {\n                            script.playState = 1;\n                            const instance = Entry.Utils.playSound(sound.id);\n                            Entry.Utils.addSoundInstances(instance, sprite);\n                            const duration = Math.floor(\n                                (sound.duration * 1000) / Entry.playbackRateValue\n                            );\n                            Entry.engine.setTimeout(() => {\n                                script.playState = 0;\n                            }, duration);\n                        }\n                        return script;\n                    } else if (script.playState == 1) {\n                        return script;\n                    } else {\n                        delete script.playState;\n                        delete script.isPlay;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            passTest: true,\n                            syntax: 'Entry.play_sound_and_wait(%1)',\n                        },\n                    ],\n                },\n            },\n            sound_something_second_wait_with_block: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                        },\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_something_second_wait_with_block',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_something_second_wait_with_block',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    SECOND: 1,\n                },\n                class: 'sound_wait',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isPlay) {\n                        script.isPlay = true;\n                        const soundId = script.getStringValue('VALUE', script);\n                        const sound = sprite.parent.getSound(soundId);\n                        if (sound) {\n                            script.playState = 1;\n                            const instance = Entry.Utils.playSound(sound.id);\n                            Entry.Utils.addSoundInstances(instance, sprite);\n                            const timeValue = script.getNumberValue('SECOND', script);\n                            Entry.engine.setTimeout(() => {\n                                instance.stop();\n                                script.playState = 0;\n                            }, timeValue * 1000);\n                            instance.addEventListener('complete', (e) => {});\n                        }\n                        return script;\n                    } else if (script.playState == 1) {\n                        return script;\n                    } else {\n                        delete script.isPlay;\n                        delete script.playState;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            passTest: true,\n                            syntax: 'Entry.play_sound_for_sec_and_wait(%1, %2)',\n                        },\n                    ],\n                },\n            },\n            sound_from_to_and_wait: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                        },\n                        {\n                            type: 'text',\n                            params: ['1'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_from_to_and_wait',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                            params: ['A&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_from_to_and_wait',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    START: 1,\n                    END: 2,\n                },\n                class: 'sound_wait',\n                isNotFor: [],\n                func(sprite, script) {\n                    if (!script.isPlay) {\n                        script.isPlay = true;\n                        const soundId = script.getStringValue('VALUE', script);\n                        const sound = sprite.parent.getSound(soundId);\n                        if (sound) {\n                            script.playState = 1;\n                            let [start, end] = script.getValues(['START', 'END'], script);\n                            start = Number(start) * 1000;\n                            end = Number(end) * 1000;\n\n                            const startValue = Math.min(start, end);\n                            const endValue = Math.max(start, end);\n                            const duration = endValue - startValue;\n                            const instance = Entry.Utils.playSound(sound.id, {\n                                startTime: startValue,\n                                duration,\n                            });\n                            Entry.Utils.addSoundInstances(instance, sprite);\n\n                            Entry.engine.setTimeout(() => {\n                                script.playState = 0;\n                            }, duration);\n                        }\n                        return script;\n                    } else if (script.playState == 1) {\n                        return script;\n                    } else {\n                        delete script.isPlay;\n                        delete script.playState;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: ['Entry.play_sound_from_to_and_wait(%1, %2, %3)'],\n                },\n            },\n            sound_volume_change: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_volume_change',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_volume_change',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'sound_volume',\n                isNotFor: [],\n                func(sprite, script) {\n                    let value = script.getNumberValue('VALUE', script) / 100;\n                    value = value + Entry.Utils.getVolume();\n                    if (value > 1) {\n                        value = 1;\n                    }\n                    if (value < 0) {\n                        value = 0;\n                    }\n                    Entry.Utils.setVolume(value);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.add_sound_volume(%1)'] },\n            },\n            sound_volume_set: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_volume_set',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_volume_set',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'sound_volume',\n                isNotFor: [],\n                func(sprite, script) {\n                    let value = script.getNumberValue('VALUE', script) / 100;\n                    if (value > 1) {\n                        value = 1;\n                    }\n                    if (value < 0) {\n                        value = 0;\n                    }\n                    Entry.Utils.setVolume(value);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.set_sound_volume(%1)'] },\n            },\n            get_sound_speed: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'get_sound_speed',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'sound_speed',\n                isNotFor: [],\n                func() {\n                    return Entry.playbackRateValue;\n                },\n                syntax: { js: [], py: ['Entry.stop_sound()'] },\n            },\n            sound_speed_change: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['0.1'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_speed_change',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'sound_speed',\n                isNotFor: [],\n                func(sprite, script) {\n                    const value = script.getNumberValue('VALUE');\n                    if (!Entry.Utils.isNumber(value)) {\n                        return;\n                    }\n                    Entry.playbackRateValue = _clamp(value + Entry.playbackRateValue, 0.5, 2);\n                    const instances = Entry.soundInstances.getAllValues();\n                    instances.forEach((instance) => {\n                        if (instance.sourceNode?.playbackRate) {\n                            instance.sourceNode.playbackRate.value = Entry.playbackRateValue;\n                        }\n                    });\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.stop_sound()'] },\n            },\n            sound_speed_set: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                        null,\n                    ],\n                    type: 'sound_speed_set',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'sound_speed',\n                isNotFor: [],\n                func(sprite, script) {\n                    let value = _clamp(script.getNumberValue('VALUE'), 0.5, 2);\n                    if (!Entry.Utils.isNumber(value)) {\n                        value = 1;\n                    }\n                    Entry.playbackRateValue = value;\n                    const instances = Entry.soundInstances.getAllValues();\n                    instances.forEach((instance) => {\n                        if (instance.sourceNode?.playbackRate) {\n                            instance.sourceNode.playbackRate.value = Entry.playbackRateValue;\n                        }\n                    });\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.stop_sound()'] },\n            },\n            sound_silent_all: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.FLOW_stop_object_all, 'all'],\n                            [Lang.Blocks.FLOW_stop_object_this_object, 'thisOnly'],\n                            [Lang.Blocks.FLOW_stop_object_other_objects, 'other_objects'],\n                        ],\n                        value: 'all',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.SOUND,\n                        arrowColor: EntryStatic.colorSet.common.WHITE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'sound_silent_all',\n                },\n                paramsKeyMap: {\n                    TARGET: 0,\n                },\n                class: 'sound_stop',\n                isNotFor: [],\n                func(sprite, script) {\n                    switch (script.getField('TARGET', script)) {\n                        case 'all':\n                            Entry.Utils.forceStopSounds();\n                            return script.callReturn();\n                        case 'thisOnly': {\n                            const instances = [...Entry.soundInstances.getAll(sprite)];\n                            instances.forEach((instance) => {\n                                instance?.dispatchEvent?.('complete');\n                                instance.stop();\n                            });\n                            return script.callReturn();\n                        }\n                        case 'other_objects': {\n                            const instances = [...Entry.soundInstances.getAllExcept(sprite)];\n                            instances.forEach((instance) => {\n                                instance?.dispatchEvent?.('complete');\n                                instance.stop();\n                            });\n                            return script.callReturn();\n                        }\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.stop_sound()'] },\n            },\n            play_bgm: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'get_sounds',\n                        },\n                        null,\n                    ],\n                    type: 'play_bgm',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'bgm',\n                isNotFor: [],\n                func(sprite, script) {\n                    const soundId = script.getStringValue('VALUE', script);\n                    const sound = sprite.parent.getSound(soundId);\n\n                    if (sound) {\n                        Entry.Utils.forceStopBGM();\n                        const instance = Entry.Utils.playBGM(sound.id);\n                        Entry.Utils.addBGMInstances(instance);\n                    }\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.stop_sound()'] },\n            },\n            stop_bgm: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/sound_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'stop_bgm',\n                },\n                paramsKeyMap: {\n                    TARGET: 0,\n                },\n                class: 'bgm',\n                isNotFor: [],\n                func(sprite, script) {\n                    Entry.Utils.forceStopBGM();\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.stop_sound()'] },\n            },\n            get_sound_volume: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_get_sound_volume,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'get_sound_volume',\n                },\n                class: 'sound_volume',\n                isNotFor: [],\n                func() {\n                    return Entry.Utils.getVolume() * 100;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_sound_volume()',\n                            blockType: 'param',\n                        },\n                    ],\n                },\n            },\n            get_sound_duration: {\n                color: EntryStatic.colorSet.block.default.SOUND,\n                outerLine: EntryStatic.colorSet.block.darken.SOUND,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_get_sound_duration_1,\n                        color: '#FFF',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'sounds',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.SOUND,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.CALC_get_sound_duration_2,\n                        color: '#FFF',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'get_sound_duration',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null],\n                    type: 'get_sound_duration',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'sound_duration',\n                isNotFor: [],\n                func(sprite, script) {\n                    const soundId = script.getField('VALUE', script);\n                    const soundsArr = sprite.parent.sounds;\n\n                    for (let i = 0; i < soundsArr.length; i++) {\n                        if (soundsArr[i].id === soundId) {\n                            return soundsArr[i].duration;\n                        }\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.value_of_sound_length_of(%2)',\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'sounds',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.SOUND,\n                                    converter: Entry.block.converters.returnStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_start.js",
    "content": "import { keyInputList } from './inputs/keyboard';\n\nmodule.exports = {\n    getBlocks() {\n        return {\n            messageAddButton: {\n                skeleton: 'basic_button',\n                color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Workspace.message_create,\n                        color: EntryStatic.colorSet.common.BUTTON,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'messageAddButton',\n                },\n                events: {\n                    mousedown: [\n                        function() {\n                            Entry.variableContainer.openVariableAddPanel('message');\n                        },\n                    ],\n                },\n                syntax: { js: [], py: [''] },\n            },\n            when_run_button_click: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_play.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'when_run_button_click',\n                },\n                class: 'event',\n                isNotFor: [],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'start',\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_start():',\n                            blockType: 'event',\n                        },\n                    ],\n                },\n            },\n            when_some_key_pressed: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_keyboard.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                    {\n                        type: 'Keyboard',\n                        options: keyInputList,\n                        value: 'q',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.START,\n                        arrowColor: EntryStatic.colorSet.arrow.default.START,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, '81'],\n                    type: 'when_some_key_pressed',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value'],\n                    type: 'when_some_key_pressed',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'event',\n                isNotFor: [],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'keyPress',\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_press_key(%2):',\n                            passTest: true,\n                            blockType: 'event',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'Dropdown',\n                                    value: 'q',\n                                    options: keyInputList,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.START,\n                                    converter: Entry.block.converters.keyboardCode,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            mouse_clicked: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_mouse.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'mouse_clicked',\n                },\n                class: 'event',\n                isNotFor: [],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'mouse_clicked',\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_click_mouse_on():',\n                            blockType: 'event',\n                        },\n                    ],\n                },\n            },\n            mouse_click_cancled: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_mouse.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'mouse_click_cancled',\n                },\n                class: 'event',\n                isNotFor: [],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'mouse_click_cancled',\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_click_mouse_off():',\n                            blockType: 'event',\n                        },\n                    ],\n                },\n            },\n            when_object_click: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_mouse.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'when_object_click',\n                },\n                class: 'event',\n                isNotFor: [],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'when_object_click',\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_click_object_on():',\n                            blockType: 'event',\n                        },\n                    ],\n                },\n            },\n            when_object_click_canceled: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_mouse.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'when_object_click_canceled',\n                },\n                class: 'event',\n                isNotFor: [],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'when_object_click_canceled',\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_click_object_off():',\n                            blockType: 'event',\n                        },\n                    ],\n                },\n            },\n            when_message_cast: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_signal.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'messages',\n                        fontSize: 10,\n                        textColor: '#FFFFFF',\n                        bgColor: EntryStatic.colorSet.block.darken.START,\n                        arrowColor: EntryStatic.colorSet.arrow.default.START,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_messageRefs', block);\n                            }\n                        },\n                    ],\n                    viewDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_messageRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null],\n                    type: 'when_message_cast',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value'],\n                    type: 'when_message_cast',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'message',\n                isNotFor: ['message'],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'when_message_cast',\n\n                //\"syntax\": {\"js\": [], \"py\": [\"def entry_event_signal():\\n\\tif signal == %2:\"]}\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_get_signal(%2):',\n                            blockType: 'event',\n                            passTest: true,\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'messages',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.START,\n                                    converter: Entry.block.converters.returnStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            message_cast: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'messages',\n                        fontSize: 10,\n                        textColor: '#fff',\n                        bgColor: EntryStatic.colorSet.block.darken.START,\n                        arrowColor: EntryStatic.colorSet.arrow.default.START,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_messageRefs', block);\n                            }\n                        },\n                    ],\n                    viewDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_messageRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null],\n                    type: 'message_cast',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'message_cast',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'message',\n                isNotFor: ['message'],\n                func(sprite, script) {\n                    const value = script.getField('VALUE', script);\n\n                    const arr = Entry.variableContainer.messages_;\n                    const isExist = Entry.isExist(value, 'id', arr);\n\n                    if (value == 'null' || !isExist) {\n                        throw new Error('value can not be null or undefined');\n                    }\n\n                    setTimeout(() => {\n                        Entry.engine.raiseMessage(value);\n                    });\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.send_signal(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'messages',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.START,\n                                    converter: Entry.block.converters.returnStringKey,\n                                    paramType: 'signal',\n                                },\n                                undefined,\n                            ],\n                        },\n                    ],\n                },\n            },\n            message_cast_wait: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'messages',\n                        fontSize: 10,\n                        textColor: '#fff',\n                        bgColor: EntryStatic.colorSet.block.darken.START,\n                        arrowColor: EntryStatic.colorSet.arrow.default.START,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_messageRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_messageRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null],\n                    type: 'message_cast_wait',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'message_cast_wait',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'message',\n                isNotFor: ['message'],\n                func(sprite, script) {\n                    if (script.runningScript) {\n                        const runningScript = script.runningScript;\n                        const length = runningScript.length;\n                        for (let i = 0; i < length; i++) {\n                            const executor = runningScript.shift();\n                            if (executor && !executor.isEnd()) {\n                                runningScript.push(executor);\n                            }\n                        }\n                        if (runningScript.length) {\n                            return script;\n                        } else {\n                            return script.callReturn();\n                        }\n                    } else {\n                        const value = script.getField('VALUE', script);\n                        const arr = Entry.variableContainer.messages_;\n                        const isExist = Entry.isExist(value, 'id', arr);\n                        if (value == 'null' || !isExist) {\n                            throw new Error('value can not be null or undefined');\n                        }\n                        const data = Entry.engine.raiseMessage(value);\n                        let runningScript = [];\n                        while (data.length) {\n                            const executor = data.shift();\n                            if (executor) {\n                                runningScript = runningScript.concat(executor);\n                            }\n                        }\n\n                        script.runningScript = runningScript;\n                        return script;\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.send_signal_wait(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'messages',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.START,\n                                    converter: Entry.block.converters.returnStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            when_scene_start: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_scene.svg',\n                        size: 14,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'when_scene_start',\n                },\n                class: 'scene',\n                isNotFor: ['scene'],\n                func(sprite, script) {\n                    return script.callReturn();\n                },\n                event: 'when_scene_start',\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'def when_start_scene():',\n                            blockType: 'event',\n                        },\n                    ],\n                },\n            },\n            start_scene: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_without_next',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'scenes',\n                        fontSize: 10,\n                        textColor: '#fff',\n                        bgColor: EntryStatic.colorSet.block.darken.START,\n                        arrowColor: EntryStatic.colorSet.arrow.default.START,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'start_scene',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'start_scene',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'scene',\n                isNotFor: ['scene'],\n                func(sprite, script) {\n                    const value = script.getField('VALUE', script);\n                    const scene = Entry.scene.getSceneById(value);\n                    if (scene) {\n                        Entry.scene.selectScene(scene);\n                        Entry.engine.fireEvent('when_scene_start');\n                    }\n                    return null;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.start_scene(%1)',\n                            blockType: 'last',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'scenes',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.START,\n                                    converter: Entry.block.converters.returnStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            start_neighbor_scene: {\n                color: EntryStatic.colorSet.block.default.START,\n                outerLine: EntryStatic.colorSet.block.darken.START,\n                skeleton: 'basic_without_next',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.SCENE_start_scene_next, 'next'],\n                            [Lang.Blocks.SCENE_start_scene_pre, 'prev'],\n                        ],\n                        value: 'next',\n                        fontSize: 10,\n                        textColor: '#fff',\n                        bgColor: EntryStatic.colorSet.block.darken.START,\n                        arrowColor: EntryStatic.colorSet.arrow.default.START,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'start_neighbor_scene',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'start_neighbor_scene',\n                },\n                paramsKeyMap: {\n                    OPERATOR: 0,\n                },\n                class: 'scene',\n                isNotFor: ['scene'],\n                func(sprite, script) {\n                    const currentScene = Entry.scene.selectedScene;\n                    const scenes = Entry.scene.getScenes();\n                    const index = scenes.indexOf(currentScene);\n                    const o = script.getField('OPERATOR', script);\n                    if (o == 'next') {\n                        if (index + 1 < scenes.length) {\n                            const nextScene = Entry.scene.getSceneById(scenes[index + 1].id);\n                            if (nextScene) {\n                                Entry.scene.selectScene(nextScene);\n                                Entry.engine.fireEvent('when_scene_start');\n                            }\n                        }\n                    } else {\n                        if (index > 0) {\n                            const nextScene = Entry.scene.getSceneById(scenes[index - 1].id);\n                            if (nextScene) {\n                                Entry.scene.selectScene(nextScene);\n                                Entry.engine.fireEvent('when_scene_start');\n                            }\n                        }\n                    }\n                    return null;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.start_scene_of(%1)',\n                            blockType: 'last',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.SCENE_start_scene_next, 'next'],\n                                        [Lang.Blocks.SCENE_start_scene_pre, 'prev'],\n                                    ],\n                                    value: 'next',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.START,\n                                    converter: Entry.block.converters.returnStringValue,\n                                    codeMap: 'Entry.CodeMap.Entry.start_neighbor_scene[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            check_object_property: {\n                color: '#7C7C7C',\n                skeleton: 'basic',\n                template: '%1 가 %2 %3 %4 %5 %6',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'sprites',\n                        fontSize: 11,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['언젠가', 0],\n                            ['지금', 1],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['x', 'x'],\n                            ['y', 'y'],\n                            ['크기', 'size'],\n                            ['방향', 'rotation'],\n                            ['이동 방향', 'direction'],\n                            ['텍스트', 'text'],\n                        ],\n                        value: 'x',\n                        fontSize: 11,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['=', 'EQUAL'],\n                            ['>', 'GREATER'],\n                            ['<', 'LESS'],\n                            ['≥', 'GREATER_OR_EQUAL'],\n                            ['≤', 'LESS_OR_EQUAL'],\n                        ],\n                        value: 'EQUAL',\n                        fontSize: 11,\n                        noArrow: true,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        color: '#6B6B6B',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'check_object_property',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    const obj = Entry.container.getObject(this.block.params[0]);\n                    const flow = this.block.params[1];\n                    let propertyKey = this.block.params[2];\n                    const rightValue = this.getParam(4);\n                    propertyKey = propertyKey[0].toUpperCase() + propertyKey.substr(1);\n                    const leftValue = obj.entity[`get${propertyKey}`].call(obj.entity);\n                    let returnVal;\n\n                    switch (this.block.params[3]) {\n                        case 'EQUAL':\n                            returnVal = leftValue == rightValue;\n                            break;\n                        case 'GREATER':\n                            returnVal = Number(leftValue) > Number(rightValue);\n                            break;\n                        case 'LESS':\n                            returnVal = Number(leftValue) < Number(rightValue);\n                            break;\n                        case 'GREATER_OR_EQUAL':\n                            returnVal = Number(leftValue) >= Number(rightValue);\n                            break;\n                        case 'LESS_OR_EQUAL':\n                            returnVal = Number(leftValue) <= Number(rightValue);\n                            break;\n                    }\n                    if (returnVal) {\n                        return;\n                    } else if (flow == 0) {\n                        return Entry.STATIC.BREAK;\n                    } else {\n                        this.die();\n                    }\n                },\n            },\n            check_block_execution: {\n                color: '#7C7C7C',\n                skeleton: 'basic_loop',\n                template: '%1 에서 아래 블록이 %2 %3 번 실행되었는가 %4',\n                statements: [\n                    {\n                        accept: 'basic',\n                    },\n                ],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'allSprites',\n                        fontSize: 11,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['비슷하게', 0],\n                            ['똑같이', 1],\n                        ],\n                        value: '16',\n                        fontSize: 11,\n                    },\n                    {\n                        type: 'TextInput',\n                        value: 1,\n                    },\n                    {\n                        type: 'Indicator',\n                        color: '#6B6B6B',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, 0, '1'],\n                    type: 'check_block_execution',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    const { block = {} } = this;\n                    const { data = {} } = block;\n                    const { id = '' } = data;\n                    if (this.entity.listener[id]) {\n                        if (this.remainCheck === 0) {\n                            this.entity.listener[id].destroy();\n                            delete this.entity.listener[id];\n                            return;\n                        } else {\n                            return Entry.STATIC.BREAK;\n                        }\n                    }\n                    const code = Entry.container.getObject(this.block.params[0]).script;\n                    const accuracy = this.block.params[1];\n                    const statements = this.block.statements[0].getBlocks();\n                    let lastBlock = null;\n                    this.remainCheck = Number(this.block.params[2]);\n                    let index = 0;\n                    this.entity.listener[id] = code.watchEvent.attach(this, (blocks) => {\n                        //dangerous\n                        blocks = blocks.concat();\n                        let block;\n                        let isFirst = true;\n                        while (blocks.length && index < statements.length) {\n                            block = blocks.shift();\n                            if (isFirst && block === lastBlock) {\n                                continue;\n                            }\n                            if (accuracy === 0 && statements[index].type === block.type) {\n                                index++;\n                            } else if (accuracy === 1 && statements[index].isSameParamWith(block)) {\n                                index++;\n                            } else {\n                                index = 0;\n                            }\n                            isFirst = false;\n                        }\n                        lastBlock = block;\n                        if (index === statements.length) {\n                            this.remainCheck = this.remainCheck - 1;\n                            index = 0;\n                        }\n                    });\n                    return Entry.STATIC.BREAK;\n                },\n            },\n            switch_scope: {\n                color: '#7C7C7C',\n                skeleton: 'basic',\n                template: '%1 오브젝트 기준으로 실행하기 %2',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'sprites',\n                        fontSize: 11,\n                    },\n                    {\n                        type: 'Indicator',\n                        color: '#6B6B6B',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'switch_scope',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    const obj = Entry.container.getObject(this.block.params[0]);\n                    this.executor.entity = obj.entity;\n                },\n            },\n            is_answer_submited: {\n                color: '#7C7C7C',\n                skeleton: 'basic',\n                template: '대답을 입력 받을때 까지 기다리기 %1',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        color: '#6B6B6B',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'is_answer_submited',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    if (this.isSubmitted) {\n                        Entry.removeEventListener('answerSubmitted', checkFunc);\n                        return;\n                    } else if (this.isSubmitted === false) {\n                        return Entry.STATIC.BREAK;\n                    }\n                    const checkFunc = function() {\n                        that.isSubmitted = true;\n                    };\n                    this.isSubmitted = false;\n                    const that = this;\n                    Entry.addEventListener('answerSubmitted', checkFunc);\n                    return Entry.STATIC.BREAK;\n                },\n            },\n            check_lecture_goal: {\n                color: '#7C7C7C',\n                skeleton: 'basic',\n                template: '목표 %1 %2 ( %3 ) %4',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextInput',\n                        value: 0,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['달성', 1],\n                            ['실패', 0],\n                        ],\n                        fontSize: 11,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['공식', 1],\n                            ['비공식', 0],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                    },\n                    {\n                        type: 'Indicator',\n                        color: '#6B6B6B',\n                        size: 12,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            Entry.registerAchievement(block);\n                        },\n                    ],\n                },\n                def: {\n                    params: [0, 1, 1],\n                    type: 'check_lecture_goal',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    Entry.targetChecker.achieveCheck(\n                        this.block.params[1],\n                        `${this.block.params[0]}`\n                    );\n                },\n            },\n            check_variable_by_name: {\n                color: '#7C7C7C',\n                skeleton: 'basic_string_field',\n                template: '%1 이름의 변수',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextInput',\n                        value: '?',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['변수'],\n                    type: 'check_variable_by_name',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    const variableName = `${this.block.params[0]}`;\n                    const variable = Entry.variableContainer.getVariableByName(variableName);\n                    if (variable) {\n                        return variable.getValue();\n                    } else {\n                        return;\n                    }\n                },\n            },\n            show_prompt: {\n                color: '#7C7C7C',\n                skeleton: 'basic',\n                template: '%1 안내하기 %2',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextInput',\n                        value: '',\n                    },\n                    {\n                        type: 'Indicator',\n                        color: '#6B6B6B',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [' '],\n                    type: 'show_prompt',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    if (Entry.targetChecker) {\n                        Entry.targetChecker.showStatusMessage(this.block.params[0]);\n                    }\n                },\n            },\n            check_goal_success: {\n                color: '#7C7C7C',\n                skeleton: 'basic_boolean_field',\n                template: '목표 %1 이 성공?',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextInput',\n                        value: '',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['0'],\n                    type: 'check_goal_success',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    const goalName = `${this.block.params[0]}`;\n                    return Entry.targetChecker.checkGoal(goalName);\n                },\n            },\n            positive_number: {\n                color: '#7C7C7C',\n                skeleton: 'basic_string_field',\n                template: '양수',\n                fontColor: '#fff',\n                statements: [],\n                params: ['positive'],\n                events: {},\n                def: {\n                    params: ['positive'],\n                    type: 'positive_number',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    return 'positive';\n                },\n            },\n            negative_number: {\n                color: '#7C7C7C',\n                skeleton: 'basic_string_field',\n                template: '음수',\n                fontColor: '#fff',\n                statements: [],\n                params: ['negative'],\n                events: {},\n                def: {\n                    params: ['negative'],\n                    type: 'negative_number',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    return 'negative';\n                },\n            },\n            wildcard_string: {\n                color: '#7C7C7C',\n                skeleton: 'basic_string_field',\n                template: '    *    ',\n                fontColor: '#fff',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'wildcard_string',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {},\n            },\n            wildcard_boolean: {\n                color: '#7C7C7C',\n                skeleton: 'basic_boolean_field',\n                template: '    *    ',\n                fontColor: '#fff',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'wildcard_boolean',\n                },\n                paramsKeyMap: {},\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {},\n            },\n            register_score: {\n                color: '#7C7C7C',\n                skeleton: 'basic',\n                template: '%1를 %2로 정하기 %3',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextInput',\n                        value: 'score',\n                    },\n                    {\n                        type: 'TextInput',\n                        value: '1',\n                    },\n                    {\n                        type: 'Indicator',\n                        color: '#6B6B6B',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['score', 1],\n                    type: 'register_score',\n                },\n                class: 'checker',\n                isNotFor: ['checker'],\n                func(sprite, script) {\n                    const obj = {};\n                    obj[this.block.params[0]] = this.block.params[1];\n                    if (typeof entrylms !== 'undefined') {\n                        entrylms.emit('registerScore', obj);\n                    }\n                    return script.callReturn();\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_text.js",
    "content": "const { type } = Lang || {};\nconst filename = type === 'ko' ? 'text_icon_ko.svg' : 'text_icon.svg';\nmodule.exports = {\n    getBlocks() {\n        return {\n            text_read: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                fontColor: EntryStatic.colorSet.common.WHITE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'textBoxWithSelf',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.TEXT,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'text_read',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'text_read',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    const targetId = script.getField('VALUE', script);\n                    let targetEntity;\n                    if (targetId === 'self') {\n                        if (sprite.type !== 'textBox') {\n                            throw new Error('textBox가 아닙니다.');\n                        }\n                        targetEntity = sprite;\n                    } else {\n                        targetEntity = Entry.container.getEntity(targetId);\n                    }\n                    let value = targetEntity.getText() || '';\n                    value = value.replace(/\\n/gim, ' ');\n                    return value;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.contents_of_textbox(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'textBoxWithSelf',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.TEXT,\n                                    converter: Entry.block.converters.returnStringKey,\n                                    codeMap: 'Entry.CodeMap.Entry.text_read[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            text_write: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: `block_icon/${filename}`,\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.entry],\n                        },\n                        null,\n                    ],\n                    type: 'text_write',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'text_write',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    const text = script.getStringValue('VALUE', script);\n                    sprite.setText(text);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.write_text(%1)'] },\n            },\n            text_append: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: `block_icon/${filename}`,\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.entry],\n                        },\n                        null,\n                    ],\n                    type: 'text_append',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'text_append',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    const text = script.getStringValue('VALUE', script);\n                    sprite.setText(`${sprite.getText()}${text}`);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.append_text(%1)'] },\n            },\n            text_prepend: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: `block_icon/${filename}`,\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.entry],\n                        },\n                        null,\n                    ],\n                    type: 'text_prepend',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'text_prepend',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    const text = script.getStringValue('VALUE', script);\n                    sprite.setText(`${text}${sprite.getText()}`);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.prepend_text(%1)'] },\n            },\n            text_change_effect: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            // display, actual value\n                            [Lang.Workspace.font_textblock_strikethrough, 'strike'],\n                            [Lang.Workspace.font_textblock_underline, 'underLine'],\n                            [Lang.Workspace.font_textblock_italic, 'fontItalic'],\n                            [Lang.Workspace.font_textblock_bold, 'fontBold'],\n                        ],\n                        value: 'strike',\n                        fontSize: 10,\n                        textColor: '#fff',\n                        bgColor: EntryStatic.colorSet.block.darken.TEXT,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.General.apply, 'on'],\n                            [Lang.General.clear, 'off'],\n                        ],\n                        value: 'on',\n                        fontSize: 10,\n                        textColor: '#fff',\n                        bgColor: EntryStatic.colorSet.block.darken.TEXT,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: `block_icon/${filename}`,\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'text_change_effect',\n                },\n                paramsKeyMap: {\n                    EFFECT: 0,\n                    MODE: 1,\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    const effect = script.getField('EFFECT');\n                    const mode = script.getField('MODE');\n                    sprite.setTextEffect(effect, mode);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.changeTextEffect(\"%1\", \"%2\")'] },\n            },\n            text_change_font: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'fonts',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.TEXT,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: `block_icon/${filename}`,\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'text_change_font',\n                },\n                paramsKeyMap: {\n                    FONT: 0,\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    const font = script.getField('FONT');\n                    sprite.setFontWithLog(`${sprite.getFontSize()} ${font}`, false);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.text_change_font(\"%1\")'] },\n            },\n            text_change_font_color: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: `block_icon/${filename}`,\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text_color',\n                        },\n                        null,\n                    ],\n                    type: 'text_change_font_color',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    let color = script.getStringValue('VALUE', script);\n\n                    if (color.indexOf('#') !== 0) {\n                        color = `#${color}`;\n                    }\n                    sprite.setColorWithLog(color);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.text_change_font_color(\"%1\")'] },\n            },\n            text_change_bg_color: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: `block_icon/${filename}`,\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'text_color',\n                        },\n                        null,\n                    ],\n                    type: 'text_change_bg_color',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    let color = script.getStringValue('VALUE', script);\n                    if (color.indexOf('#') !== 0) {\n                        color = `#${color}`;\n                    }\n                    sprite.setBGColourWithLog(color);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.text_change_bg_color(\"%1\")'] },\n            },\n            text_flush: {\n                color: EntryStatic.colorSet.block.default.TEXT,\n                outerLine: EntryStatic.colorSet.block.darken.TEXT,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: `block_icon/${filename}`,\n                        size: 11,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'text_flush',\n                },\n                class: 'text',\n                isNotFor: ['sprite'],\n                func(sprite, script) {\n                    sprite.setText('');\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['Entry.clear_text()'] },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/block_variable.js",
    "content": "module.exports = {\n    getBlocks() {\n        return {\n            variableAddButton: {\n                skeleton: 'basic_button',\n                color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Workspace.variable_create,\n                        color: EntryStatic.colorSet.common.BUTTON,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'variableAddButton',\n                },\n                events: {\n                    mousedown: [\n                        function() {\n                            Entry.variableContainer.openVariableAddPanel('variable');\n                        },\n                    ],\n                },\n                syntax: { js: [], py: [''] },\n            },\n            listAddButton: {\n                skeleton: 'basic_button',\n                color: EntryStatic.colorSet.common.BUTTON_BACKGROUND,\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Workspace.create_list_block,\n                        color: EntryStatic.colorSet.common.BUTTON,\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'listAddButton',\n                },\n                events: {\n                    mousedown: [\n                        function() {\n                            Entry.variableContainer.openVariableAddPanel('list');\n                        },\n                    ],\n                },\n            },\n            ask_and_wait: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    viewAdd: [\n                        function() {\n                            if (Entry.container) {\n                                Entry.container.showProjectAnswer();\n                            }\n                        },\n                    ],\n                    viewDestroy: [\n                        function(block, notIncludeSelf) {\n                            if (Entry.container) {\n                                Entry.container.hideProjectAnswer(block, notIncludeSelf);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: [Lang.Blocks.block_hi],\n                        },\n                        null,\n                    ],\n                    type: 'ask_and_wait',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'ask_and_wait',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'ask',\n                isNotFor: [],\n                func(sprite, script) {\n                    const inputModel = Entry.container.inputValue;\n                    const inputView = Entry.stage.inputField;\n                    const message = script.getValue('VALUE', script);\n\n                    if (_.isUndefined(message) || message === '') {\n                        throw new Error('message can not be empty');\n                    }\n\n                    if (inputModel.sprite == sprite && inputView && !inputView._isHidden) {\n                        return script;\n                    } else if (inputModel.sprite != sprite && script.isInit) {\n                        if (sprite.dialog) {\n                            sprite.dialog.remove();\n                        }\n                        delete script.isInit;\n                        return script.callReturn();\n                    } else if (\n                        inputModel.complete &&\n                        inputModel.sprite == sprite &&\n                        inputView._isHidden &&\n                        script.isInit\n                    ) {\n                        if (sprite.dialog) {\n                            sprite.dialog.remove();\n                        }\n                        delete inputModel.complete;\n                        delete script.isInit;\n                        return script.callReturn();\n                    } else {\n                        Entry.stage.showInputField();\n                        new Entry.Dialog(sprite, Entry.convertToRoundedDecimals(message, 3), 'ask');\n                        inputModel.script = script;\n                        inputModel.sprite = sprite;\n                        inputModel.complete = false;\n                        script.isInit = true;\n                        return script;\n                    }\n                },\n                syntax: { js: [], py: ['Entry.input(%1)'] },\n            },\n            get_canvas_input_value: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_get_canvas_input_value,\n                        color: '#fff',\n                    },\n                ],\n                events: {\n                    viewAdd: [\n                        function() {\n                            if (Entry.container) {\n                                Entry.container.showProjectAnswer();\n                            }\n                        },\n                    ],\n                    viewDestroy: [\n                        function(block, notIncludeSelf) {\n                            if (Entry.container) {\n                                Entry.container.hideProjectAnswer(block, notIncludeSelf);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null],\n                    type: 'get_canvas_input_value',\n                },\n                class: 'ask',\n                isNotFor: [],\n                func(sprite, script) {\n                    return Entry.container.getInputValue();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            template: '%1',\n                            syntax: 'Entry.answer()',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Text',\n                                    text: 'Entry.answer()',\n                                    color: '#fff',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            set_visible_answer: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.CALC_timer_visible_show, 'SHOW'],\n                            [Lang.Blocks.CALC_timer_visible_hide, 'HIDE'],\n                        ],\n                        value: 'SHOW',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    viewAdd: [\n                        function() {\n                            if (Entry.container) {\n                                Entry.container.showProjectAnswer();\n                            }\n                        },\n                    ],\n                    viewDestroy: [\n                        function(block, notIncludeSelf) {\n                            if (Entry.container) {\n                                Entry.container.hideProjectAnswer(block, notIncludeSelf);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: ['HIDE', null],\n                    type: 'set_visible_answer',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'set_visible_answer',\n                },\n                paramsKeyMap: {\n                    BOOL: 0,\n                },\n                class: 'ask',\n                isNotFor: [],\n                func(sprite, script) {\n                    const bool = script.getField('BOOL', script);\n                    if (bool === 'HIDE') {\n                        Entry.container.inputValue.setVisible(false);\n                    } else {\n                        Entry.container.inputValue.setVisible(true);\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.answer_view(%1)',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.CALC_timer_visible_show, 'SHOW'],\n                                        [Lang.Blocks.CALC_timer_visible_hide, 'HIDE'],\n                                    ],\n                                    value: 'SHOW',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnStringValueLowerCase,\n                                    codeMap: 'Entry.CodeMap.Entry.set_visible_answer[0]',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            get_variable: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'variables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_get_variable_1,\n                        color: 'white',\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null],\n                    type: 'get_variable',\n                },\n                pyHelpDef: {\n                    params: ['A&value'],\n                    type: 'get_variable',\n                },\n                paramsKeyMap: {\n                    VARIABLE: 0,\n                },\n                class: 'variable',\n                isNotFor: ['variableNotExist'],\n                func(sprite, script) {\n                    const variableId = script.getField('VARIABLE', script);\n                    const variable = Entry.variableContainer.getVariable(variableId, sprite);\n                    return variable.getValue();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1',\n                            passTest: true,\n                            keyOption: 'get_variable',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'variables',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            change_variable: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'variables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'change_variable',\n                },\n                pyHelpDef: {\n                    params: [\n                        'A&value',\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'change_variable',\n                },\n                paramsKeyMap: {\n                    VARIABLE: 0,\n                    VALUE: 1,\n                },\n                class: 'variable',\n                isNotFor: ['variableNotExist'],\n                func(sprite, script) {\n                    const variableId = script.getField('VARIABLE', script);\n                    let value = script.getValue('VALUE', script);\n                    let fixed = 0;\n\n                    if (value == false && typeof value === 'boolean') {\n                        throw new Error('Type is not correct');\n                    }\n\n                    const variable = Entry.variableContainer.getVariable(variableId, sprite);\n                    const { isRealTime_ } = variable;\n                    let variableValue = variable.getValue();\n                    let sumValue;\n                    if (Entry.Utils.isNumber(value) && variable.isNumber()) {\n                        value = Entry.parseNumber(value);\n                        variableValue = Entry.parseNumber(variableValue);\n                        fixed = Entry.getMaxFloatPoint([value, variable.getValue()]);\n                        sumValue = new BigNumber(value)\n                            .plus(variableValue)\n                            .toNumber()\n                            .toFixed(fixed);\n                    } else {\n                        sumValue = `${variableValue}${value}`;\n                    }\n                    if (!isRealTime_) {\n                        variable.setValue(sumValue);\n                        return script.callReturn();\n                    } else {\n                        return new Promise(async (resolve, reject) => {\n                            try {\n                                await variable.setValue(sumValue);\n                                resolve();\n                            } catch (e) {\n                                reject(e);\n                            }\n                        });\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1 += %2',\n                            passTest: true,\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'variables',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                        {\n                            syntax: '%1 = %1 + %2',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'variables',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            set_variable: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'variables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'set_variable',\n                },\n                pyHelpDef: {\n                    params: [\n                        'A&value',\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'set_variable',\n                },\n                paramsKeyMap: {\n                    VARIABLE: 0,\n                    VALUE: 1,\n                },\n                class: 'variable',\n                isNotFor: ['variableNotExist'],\n                func(sprite, script) {\n                    const variableId = script.getField('VARIABLE', script);\n                    const value = script.getValue('VALUE', script);\n                    const variable = Entry.variableContainer.getVariable(variableId, sprite);\n                    const { isRealTime_ } = variable;\n\n                    if (!isRealTime_) {\n                        variable.setValue(value);\n                        return script.callReturn();\n                    } else {\n                        return new Promise(async (resolve, reject) => {\n                            try {\n                                await variable.setValue(value);\n                                resolve();\n                            } catch (e) {\n                                reject(e);\n                            }\n                        });\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1 = %2',\n                            passTest: true,\n                            blockType: 'variable',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'variables',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            show_variable: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'variables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null],\n                    type: 'show_variable',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'show_variable',\n                },\n                paramsKeyMap: {\n                    VARIABLE: 0,\n                },\n                class: 'variable_visibility',\n                isNotFor: ['variableNotExist'],\n                func(sprite, script) {\n                    const variableId = script.getField('VARIABLE', script);\n                    const variable = Entry.variableContainer.getVariable(variableId, sprite);\n                    variable.setVisible(true);\n                    variable.updateView();\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.show_variable(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'variables',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            hide_variable: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'variables',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null],\n                    type: 'hide_variable',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'hide_variable',\n                },\n                paramsKeyMap: {\n                    VARIABLE: 0,\n                },\n                class: 'variable_visibility',\n                isNotFor: ['variableNotExist'],\n                func(sprite, script) {\n                    const variableId = script.getField('VARIABLE', script);\n                    const variable = Entry.variableContainer.getVariable(variableId, sprite);\n                    variable.setVisible(false);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.hide_variable(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'variables',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            value_of_index_from_list: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_value_of_index_from_list_1,\n                        color: 'white',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_value_of_index_from_list_2,\n                        color: 'white',\n                    },\n                    {\n                        type: 'Block',\n                        isListIndex: true,\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_value_of_index_from_list_3,\n                        color: 'white',\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        null,\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                    ],\n                    type: 'value_of_index_from_list',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        'A&value',\n                        null,\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                    ],\n                    type: 'value_of_index_from_list',\n                },\n                paramsKeyMap: {\n                    LIST: 1,\n                    INDEX: 3,\n                },\n                class: 'list_element',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    let index = script.getValue('INDEX', script);\n                    const list = Entry.variableContainer.getList(listId, sprite);\n                    index = Entry.getListRealIndex(index, list);\n                    const array = list.getArray();\n                    if (!array || !Entry.Utils.isNumber(index) || index > array.length) {\n                        throw new Error('can not insert value to array');\n                    }\n\n                    return array[index - 1].data;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%2[%4]',\n                            passTest: true,\n                            blockType: 'param',\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'index',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            add_value_to_list: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'add_value_to_list',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        'A&value',\n                        null,\n                    ],\n                    type: 'add_value_to_list',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    LIST: 1,\n                },\n                class: 'list',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    const value = script.getValue('VALUE', script);\n                    const list = Entry.variableContainer.getList(listId, sprite);\n\n                    if (!list.isCloud_) {\n                        list.appendValue(value);\n                        return script.callReturn();\n                    } else {\n                        return new Promise(async (resolve, reject) => {\n                            try {\n                                await list.appendValue(value);\n                                resolve();\n                            } catch (e) {\n                                reject(e);\n                            }\n                        });\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            passTest: true,\n                            syntax: '%2.append(%1)',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            remove_value_from_list: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        isListIndex: true,\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'remove_value_from_list',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['B&value'],\n                        },\n                        'A&value',\n                        null,\n                    ],\n                    type: 'remove_value_from_list',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    LIST: 1,\n                },\n                class: 'list',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    const value = script.getValue('VALUE', script);\n                    const list = Entry.variableContainer.getList(listId, sprite);\n                    const array = list.getArray();\n                    if (!array || !Entry.Utils.isNumber(value) || value > array.length) {\n                        throw new Error('can not remove value from array');\n                    }\n\n                    const { isRealTime_ } = list;\n                    if (!isRealTime_) {\n                        list.deleteValue(+value);\n                        return script.callReturn();\n                    } else {\n                        return new Promise(async (resolve, reject) => {\n                            try {\n                                await list.deleteValue(+value);\n                                resolve();\n                            } catch (e) {\n                                reject(e);\n                            }\n                        });\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%2.pop(%1)',\n                            passTest: true,\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'index',\n                                },\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            insert_value_to_list: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        isListIndex: true,\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                        {\n                            type: 'text',\n                            params: ['1'],\n                        },\n                        null,\n                    ],\n                    type: 'insert_value_to_list',\n                },\n                pyHelpDef: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        'A&value',\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        null,\n                    ],\n                    type: 'insert_value_to_list',\n                },\n                paramsKeyMap: {\n                    DATA: 0,\n                    LIST: 1,\n                    INDEX: 2,\n                },\n                class: 'list',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    const [data, index] = script.getValues(['DATA', 'INDEX'], script);\n                    const list = Entry.variableContainer.getList(listId, sprite);\n                    const array = list.getArray();\n                    if (\n                        !array ||\n                        !Entry.Utils.isNumber(index) ||\n                        index == 0 ||\n                        index > array.length + 1\n                    ) {\n                        throw new Error('can not insert value to array');\n                    }\n\n                    const { isRealTime_ } = list;\n                    if (!isRealTime_) {\n                        list.insertValue(index, data);\n                        return script.callReturn();\n                    } else {\n                        return new Promise(async (resolve, reject) => {\n                            try {\n                                await list.insertValue(index, data);\n                                resolve();\n                            } catch (e) {\n                                reject(e);\n                            }\n                        });\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%2.insert(%3, %1)',\n                            passTest: true,\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'index',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            change_value_list_index: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Block',\n                        isListIndex: true,\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'text',\n                            params: ['1'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'change_value_list_index',\n                },\n                pyHelpDef: {\n                    params: [\n                        'A&value',\n                        {\n                            type: 'text',\n                            params: ['B&value'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['C&value'],\n                        },\n                        null,\n                    ],\n                    type: 'change_value_list_index',\n                },\n                paramsKeyMap: {\n                    LIST: 0,\n                    INDEX: 1,\n                    DATA: 2,\n                },\n                class: 'list',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    const [data, index] = script.getValues(['DATA', 'INDEX'], script);\n                    const list = Entry.variableContainer.getList(listId, sprite);\n                    const array = list.getArray();\n                    if (!array || !Entry.Utils.isNumber(index) || index > array.length) {\n                        throw new Error('can not insert value to array');\n                    }\n\n                    const { isRealTime_ } = list;\n                    if (!isRealTime_) {\n                        list.replaceValue(index, data);\n                        return script.callReturn();\n                    } else {\n                        return new Promise(async (resolve, reject) => {\n                            try {\n                                await list.replaceValue(index, data);\n                                resolve();\n                            } catch (e) {\n                                reject(e);\n                            }\n                        });\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1[%2] = %3',\n                            passTest: true,\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                    paramType: 'index',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            length_of_list: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_length_of_list_1,\n                        color: 'white',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_length_of_list_2,\n                        color: 'white',\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null, null],\n                    type: 'length_of_list',\n                },\n                pyHelpDef: {\n                    params: [null, 'A&value', null],\n                    type: 'length_of_list',\n                },\n                paramsKeyMap: {\n                    LIST: 1,\n                },\n                class: 'list',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    const list = Entry.variableContainer.getList(listId, sprite);\n                    return list.getArray().length;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'len(%2)',\n                            blockType: 'param',\n                            passTest: true,\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            is_included_in_list: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                fontColor: '#fff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_is_included_in_list_1,\n                        color: 'white',\n                    },\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_is_included_in_list_2,\n                        color: 'white',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Text',\n                        text: Lang.Blocks.VARIABLE_is_included_in_list_3,\n                        color: 'white',\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [\n                        null,\n                        null,\n                        null,\n                        {\n                            type: 'text',\n                            params: ['10'],\n                        },\n                        null,\n                    ],\n                    type: 'is_included_in_list',\n                },\n                pyHelpDef: {\n                    params: [\n                        null,\n                        'B&value',\n                        null,\n                        {\n                            type: 'text',\n                            params: ['A&value'],\n                        },\n                        null,\n                    ],\n                    type: 'is_included_in_list',\n                },\n                paramsKeyMap: {\n                    LIST: 1,\n                    DATA: 3,\n                },\n                class: 'list',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    const data = script.getStringValue('DATA', script);\n                    const list = Entry.variableContainer.getList(listId, sprite);\n                    if (!list) {\n                        return false;\n                    }\n                    const arr = list.getArray();\n\n                    for (let i = 0, len = arr.length; i < len; i++) {\n                        if (arr[i].data.toString() == data.toString()) {\n                            return true;\n                        }\n                    }\n                    return false;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%4 in %2',\n                            blockType: 'param',\n                            passTest: true,\n                            textParams: [\n                                undefined,\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnRawStringKey,\n                                },\n                                undefined,\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            show_list: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null],\n                    type: 'show_list',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'show_list',\n                },\n                paramsKeyMap: {\n                    LIST: 0,\n                },\n                class: 'list_visibility',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    const list = Entry.variableContainer.getList(listId);\n\n                    list.setVisible(true);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.show_list(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            hide_list: {\n                color: EntryStatic.colorSet.block.default.VARIABLE,\n                outerLine: EntryStatic.colorSet.block.darken.VARIABLE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'DropdownDynamic',\n                        value: null,\n                        menuName: 'lists',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.VARIABLE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.DEFAULT,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/variable_icon.svg',\n                        size: 11,\n                    },\n                ],\n                events: {\n                    dataAdd: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.addRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            const vc = Entry.variableContainer;\n                            if (vc) {\n                                vc.removeRef('_variableRefs', block);\n                            }\n                        },\n                    ],\n                },\n                def: {\n                    params: [null, null],\n                    type: 'hide_list',\n                },\n                pyHelpDef: {\n                    params: ['A&value', null],\n                    type: 'hide_list',\n                },\n                paramsKeyMap: {\n                    LIST: 0,\n                },\n                class: 'list_visibility',\n                isNotFor: ['listNotExist'],\n                func(sprite, script) {\n                    const listId = script.getField('LIST', script);\n                    const list = Entry.variableContainer.getList(listId);\n\n                    list.setVisible(false);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Entry.hide_list(%1)',\n                            textParams: [\n                                {\n                                    type: 'DropdownDynamic',\n                                    value: null,\n                                    menuName: 'lists',\n                                    fontSize: 11,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.VARIABLE,\n                                    converter: Entry.block.converters.returnStringKey,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_0uboard.js",
    "content": "'use strict';\n\nEntry.pyocoding = {\n    id: ['52.1'],\n    name: '0uboard',\n    url: 'https://www.pyocoding.co.kr',\n    imageName: '0uboard.png',\n    title: {\n        ko: '0U보드',\n        en: '0UBOARD',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n      ALIVE: 0,\n      DIGITAL: 1,\n      ANALOG: 2,\n      PWM: 3,\n      SERVO_PIN: 4,\n      TONE: 5,\n      PULSEIN: 6,\n      ULTRASONIC: 7,\n      TIMER: 8,\n      OLED: 241,\n      COM: 242,\n    \tNEOPIXELCOLOR: 243,\n      DOTMATRIX: 245,\n    },\n    duration: {\n          TIME_1ms: 1,\n          TIME_5ms: 5,\n          TIME_10ms: 10,\n          TIME_20ms: 20,\n          TIME_50ms: 50,\n          TIME_100ms: 100,\n          TIME_200ms: 200,\n          TIME_500ms: 500,\n          TIME_600ms: 600,\n      },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    BlockState: {},\n};\n\nEntry.pyocoding.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n              GreenColor: '초록색',\n              BlueColor: '파랑색',\n              YellowColor: '노랑색',\n              RedColor: '빨강색',\n              GreenButton: '초록 버튼',\n              BlueButton: '파랑 버튼',\n              YellowButton: '노랑 버튼',\n              RedButton: '빨강 버튼',\n            },\n            template: {\n                pyocoding_serial_set: '시리얼 통신으로 설정하고 %1 속도로 전송하기',\n                pyocoding_ble_set: '블루투스 통신으로 설정하고 %1 속도로 전송하기',\n                pyocoding_get_analog_value: '아날로그 %1 센서값',\n                pyocoding_toggle_pin: '디지털 %1 번핀 %2',\n                pyocoding_port_number: '%1',\n                pyocoding_ultrasonic_get_value:'초음파 송신 %1 핀 수신 %2 핀',\n                pyocoding_get_digital_button: '%1 누름',\n                pyocoding_get_digital: '디지털 %1번 센서값',\n                pyocoding_toggle_led: 'LED %1 을 %2',\n                pyocoding_get_port_number1: '%1',\n                pyocoding_get_port_number: '%1',\n                pyocoding_get_ultrasonic_port_number: '%1',\n                pyocoding_set_servo: '서보모터 %1번 핀을 %2 도로 정하기',\n                pyocoding_oled_set: 'OLED %1 번째 줄의 %2 표시하기',\n                pyocoding_pw_get_port_number: '%1',\n                pyocoding_neopixel_set: '디지털 %1 번 핀에 연결된 %2 번째 네오픽셀 %3 개 사용하기',\n                pyocoding_neopixel_led: '네오픽셀 %1 번에 %2 번째 LED R: %3 , G: %4 , B: %5 색을 밝기 %6 으로 켜기',\n                pyocoding_neopixel_all_led: '네오픽셀 %1 번에 LED R: %2 , G: %3 , B: %4 색을 밝기 %5 으로 켜기',\n                pyocoding_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                pyocoding_set_tone: '디지털 %1 번 핀을 %2 음으로 %3 옥타브로 %4 만큼 연주하기 %5',\n                pyocoding_change_4095to255_value: '%1 값 %2을 %3로 변환하기',\n                pyocoding_change_analog_to_temperature_tc_value: '아날로그 온도 변환 %1',\n                pyocoding_get_touch_value : '터치 %1 센서값',\n                pyocoding_dotmatrix : '도트매트릭스 %1 번 배열에 %2 을 그리기',\n            },\n        },\n        en: {\n            Blocks: {\n              GreenColor: 'Green Color',\n              BlueColor: 'Blue Color',\n              YellowColor: 'Yellow Color',\n              RedColor: 'Red Color',\n              GreenButton: 'Green Button',\n              BlueButton: 'Blue Button',\n              YellowButton: 'Yellow Button',\n              RedButton: 'Red Button',\n            },\n            template: {\n              pyocoding_serial_set: 'Set Serial COMM %1 boardrates',\n              pyocoding_ble_set: 'Set Bluetooth COMM %1 boardrates',\n              pyocoding_get_analog_value: 'Analog %1 Value',\n              pyocoding_toggle_pin: 'Digital %1 PIN %2',\n              pyocoding_port_number: '%1',\n              pyocoding_ultrasonic_get_value:'Ultrasonic Trigger %1 PIN echo %2 PIN Value',\n              pyocoding_get_digital_button: '%1 Push',\n              pyocoding_get_digital: 'Digital %1 PIN Value',\n              pyocoding_toggle_led: '%1 LED %2',\n              pyocoding_get_port_number1: '%1',\n              pyocoding_get_port_number: '%1',\n              pyocoding_get_ultrasonic_port_number: '%1',\n              pyocoding_set_servo: 'Servo %1 PIN %2 degree set',\n              pyocoding_oled_set: 'OLE %1 line %2 Display',\n              pyocoding_pw_get_port_number: '%1',\n              pyocoding_neopixel_set: '디지털 %1 번핀에 연결된 %2 개의 네오픽셀 LED 사용하기',\n              pyocoding_neopixel_led: '디지털 %1 번핀에 연결된 %2  번째 네오픽셀 LED R: %3 , G: %4 , B: %5 색으로 켜기',\n              pyocoding_neopixel_all_led: '디지털 %1 번 핀에 연결된 %2  번째 네오픽셀 LED R: %3 , G: %4 , B: %5 색으로 켜기',\n              pyocoding_digital_pwm: 'Digital %1 Pin %2 %3',\n              pyocoding_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n              pyocoding_change_4095to255_value: 'Analog 4095to255 %1',\n              pyocoding_change_analog_to_temperature_tc_value: 'Analog to Tc %1',\n              pyocoding_get_touch_value : 'touch %1 value',\n              pyocoding_dotmatrix : '도트매트릭스 %1 번 배열에 %2 을 그리기',\n            },\n        },\n    };\n};\n\nEntry.pyocoding.blockMenuBlocks = [\n    //'pyocoding_serial_set',\n    //'pyocoding_ble_set',\n    'pyocoding_get_analog_value',\n    'pyocoding_ultrasonic_get_value',\n    'pyocoding_get_digital_button',\n    'pyocoding_get_digital',\n    'pyocoding_toggle_pin',\n    'pyocoding_toggle_led',\n    'pyocoding_digital_pwm',\n    'pyocoding_set_tone',\n    'pyocoding_set_servo',\n    'pyocoding_oled_set',\n    'pyocoding_neopixel_set',\n    'pyocoding_neopixel_led',\n    'pyocoding_neopixel_all_led',\n    'pyocoding_change_4095to255_value',\n    'pyocoding_change_analog_to_temperature_tc_value',\n    'pyocoding_get_touch_value',\n    'pyocoding_dotmatrix',\n\n];\n\nEntry.pyocoding.getBlocks = function() {\n    return {\n        pyocoding_serial_set: {\n          color: EntryStatic.colorSet.block.default.HARDWARE,\n          outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n          skeleton: 'basic',\n          statements: [],\n          params : [\n            {\n                  type: 'Dropdown',\n                  options: [\n                   ['1','1'],\n                   ['2','2'],\n                   ['3','3'],\n                   ['4','4'],\n                   ['5','5'],\n                   ['6','6'],\n                   ['7','7'],\n                   ['8','8'],\n                   ['9','9'],\n                   ['10','10'],\n                  ],\n                  value:'10',\n                  fontSize:11,\n                  bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                  arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n              },\n          ],\n          events: {},\n          def: {\n              params: [null],\n              type: 'pyocoding_serial_set',\n          },\n          isNotFor: [ '0uboard' ],\n          syntax: undefined,\n          paramsKeyMap: {\n              NOTE: 0,\n          },\n          class: 'COM',\n          func: function (sprite, script) {\n              var data = script.getField('NOTE');\n\n              if(!Entry.hw.sendQueue['SET']) {\n                  Entry.hw.sendQueue['SET'] = {};\n              }\n              Entry.hw.sendQueue['SET'][0] = {\n                  type: 242,\n                  data: data,\n                  time: new Date().getTime()\n              };\n              return script.callReturn();\n          },\n        },\n        pyocoding_ble_set: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic',\n              statements: [],\n              params: [\n          \t\t{\n                      \"type\": \"Dropdown\",\n                      \"options\": [\n                       [\"1\",\"1\"],\n                       [\"2\",\"2\"],\n                       [\"3\",\"3\"],\n                      ],\n                      \"value\":\"3\",\n                      \"fontSize\":11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n              ],\n              events: {},\n              def: {\n                  \"params\": [\n                      null,\n                  ],\n                  \"type\": \"pyocoding_ble_set\"\n              },\n              isNotFor: [ '0uboard' ],\n              paramsKeyMap: {\n                  \"VALUE1\": 0,\n              },\n              class: \"COM\",\n              func: function (sprite, script) {\n                  var data = script.getField(\"VALUE1\");\n\n                  if(!Entry.hw.sendQueue['SET']) {\n                      Entry.hw.sendQueue['SET'] = {};\n                  }\n                  Entry.hw.sendQueue['SET'][1] = {\n                      type: 242,\n                      data: data,\n                      time: new Date().getTime()\n                  };\n                  return script.callReturn();\n\n              },\n          },\n          pyocoding_get_analog_value: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic_string_field',\n              statements: [],\n              events: {},\n              params: [\n                    {\n                        \"type\": \"Dropdown\",\n                        \"options\": [\n                            [ \"A0\", \"0\" ],\n                            [ \"A1\", \"1\" ],\n                            [ \"A2\", \"2\" ],\n                            [ \"A3\", \"3\" ],\n                            [ \"A4\", \"4\" ],\n                            //[ \"A5\", \"5\" ],\n                        ],\n                        \"value\": \"0\",\n                        \"fontSize\": 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n              def: {\n                params: [ null ],\n                \"type\": \"pyocoding_get_analog_value\"\n              },\n              isNotFor: [ '0uboard' ],\n              class: \"SENSOR\",\n              paramsKeyMap: {\n                  \"PORT\": 0,\n              },\n              func: function (sprite, script) {\n                var port = script.getValue(\"PORT\", script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                //console.log(port,ANALOG)\n                if (port[0] === \"A\")\n                    port = port.substring(1)\n                return ANALOG ? ANALOG[port] || 0 : 0;\n              },\n          },\n          pyocoding_change_4095to255_value: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic_string_field',\n              statements: [],\n              events: {},\n              params: [\n                  {\n                      \"type\": \"Block\",\n                      \"accept\": \"string\"\n                  },\n                  {\n                      \"type\": \"Block\",\n                      \"accept\": \"string\"\n                  },\n                  {\n                      \"type\": \"Block\",\n                      \"accept\": \"string\"\n                  },\n                ],\n              def: {\n                params: [\n                    {\n                        \"type\": \"text\",\n                        \"params\": [ \"0\" ]\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"params\": [ \"4095\" ]\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"params\": [ \"255\" ]\n                    },\n                ],\n                \"type\": \"pyocoding_change_4095to255_value\"\n              },\n              isNotFor: [ '0uboard' ],\n              class: \"ext\",\n              paramsKeyMap: {\n                  \"VALUE\": 0,\n                  \"VALUE2\": 1,\n                  \"VALUE3\": 2,\n              },\n              func: function (sprite, script) {\n                var value = script.getNumberValue(\"VALUE\");\n                var value2 = script.getNumberValue(\"VALUE2\");\n                var value3 = script.getNumberValue(\"VALUE3\");\n                console.log(value,value2,value3);\n                var dividedValue = Math.floor(value / (value2 / value3));\n                \n                return dividedValue;\n              },\n          },\n          pyocoding_change_analog_to_temperature_tc_value: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic_string_field',\n              statements: [],\n              events: {},\n              params: [\n                  {\n                      \"type\": \"Block\",\n                      \"accept\": \"string\"\n                  },\n                ],\n              def: {\n                params: [\n                    {\n                        \"type\": \"text\",\n                        \"params\": [ \"0\" ]\n                    },\n                    null\n                ],\n                \"type\": \"pyocoding_change_analog_to_temperature_tc_value\"\n              },\n              isNotFor: [ '0uboard' ],\n              class: \"ext\",\n              paramsKeyMap: {\n                  \"VALUE\": 0,\n              },\n              func: function (sprite, script) {\n                \n                var R1 = 10000;\n                var logR2, R2, T, Tc, Tf;\n                var c1 = 1.106836861e-03, c2 = 2.384641754e-04, c3 = 0.6507394466e-07;\n\n                var Vo = script.getNumberValue(\"VALUE\");\n\n                R2 = R1 * ((4095.0 / Vo) - 1.0);\n                logR2 = Math.log(R2);\n                T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2));\n                Tc = T - 273.15; //섭씨\n                //Tf = (Tc * 9.0)/ 5.0 + 32.0; //화씨\n\n                // Print the result to the console\n                //console.log(\"vo:\",Vo,\"Tc:\",Tc);\n\n                // You can return the value in Fahrenheit as well\n                return Tc;\n              },\n          },\n          pyocoding_get_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: \"basic_string_field\",\n              statements: [],\n              params: [\n                  {\n                      \"type\": \"Dropdown\",\n                      \"options\": [\n                          [ \"2\", \"2\" ],\n                          [ \"3\", \"3\" ],\n                          [ \"4\", \"4\" ],\n                          [ \"5\", \"5\" ],\n                          [ \"6\", \"6\" ],\n                          [ \"7\", \"7\" ],\n                          //[ \"8\", \"8\" ],\n                          //[ \"9\", \"9\" ],\n                      ],\n                      \"value\": \"2\",\n                      \"fontSize\": 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  }\n              ],\n              events: {},\n              def: {\n                  \"params\": [ null ]\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0\n              },\n              func: function (sprite, script) {\n                  return script.getStringField(\"PORT\");\n              },\n          },\n          pyocoding_get_ultrasonic_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: \"basic_string_field\",\n              statements: [],\n              params: [\n                  {\n                      \"type\": \"Dropdown\",\n                      \"options\": [\n                          [ \"6\", \"6\" ],\n                          [ \"7\", \"7\" ],\n                          //[ \"8\", \"8\" ],\n                          //[ \"9\", \"9\" ],\n                      ],\n                      \"value\": \"2\",\n                      \"fontSize\": 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  }\n              ],\n              events: {},\n              def: {\n                  \"params\": [ null ]\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0\n              },\n              func: function (sprite, script) {\n                  return script.getStringField(\"PORT\");\n              },\n          },\n          pyocoding_port_number: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: \"basic_string_field\",\n              statements: [],\n              params: [\n                  {\n                    \"type\": \"Dropdown\",\n                    \"options\": [\n                      [ Lang.Blocks.RedButton, \"6\" ],\n                      [ Lang.Blocks.BlueButton, \"7\" ],\n                      [ Lang.Blocks.GreenButton, \"8\" ],\n                      [ Lang.Blocks.YellowButton, \"9\" ],\n                    ],\n                      value: \"6\",\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  }\n              ],\n              events: {},\n              def: {\n                  \"params\": [ null ]\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0\n              },\n              func: function (sprite, script) {\n                  return script.getStringField(\"PORT\");\n              },\n          },\n          pyocoding_toggle_pin: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                }\n            ],\n             events: {},\n              def: {\n                  \"params\": [\n                      {\n                          \"type\": \"pyocoding_get_port_number\"\n                      },\n                      {\n                          \"type\": \"arduino_get_digital_toggle\",\n                          \"params\": [ \"on\" ],\n                      },\n                      null\n                  ],\n                  \"type\": \"pyocoding_toggle_pin\"\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0,\n                  \"VALUE\": 1,\n              },\n              isNotFor: [ '0uboard' ],\n              class: \"run\",\n              func: function (sprite, script) {\n                  var port = script.getNumberValue(\"PORT\");\n                  var value = script.getValue(\"VALUE\");\n\n                  if(typeof value === 'string') {\n                      value = value.toLowerCase();\n                  }\n                  if(Entry.ArduinoExt.highList.indexOf(value) > -1) {\n                      value = 255;\n                  } else if(Entry.ArduinoExt.lowList.indexOf(value) > -1) {\n                      value = 0;\n                  } else {\n                      throw new Error();\n                  }\n                  if(!Entry.hw.sendQueue['SET']) {\n                      Entry.hw.sendQueue['SET'] = {};\n                  }\n                  Entry.hw.sendQueue['SET'][port] = {\n                      type: Entry.pyocoding.sensorTypes.DIGITAL,\n                      data: value,\n                      time: new Date().getTime()\n                  };\n                  return script.callReturn();\n              },\n          },\n          pyocoding_ultrasonic_get_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic_string_field\",\n            params: [\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                }\n            ],\n            def: {\n                params: [{\n                    type: 'pyocoding_get_ultrasonic_port_number',\n                    params: [ '6' ],\n                }, {\n                    type: 'pyocoding_get_ultrasonic_port_number',\n                    params: [ '7' ],\n                }],\n                type: \"pyocoding_ultrasonic_get_value\"\n            },\n            paramsKeyMap: {\n                \"PORT1\": 0,\n                \"PORT2\": 1,\n            },\n            func: function (sprite, script) {\n                var port1 = script.getNumberValue(\"PORT1\", script);\n                var port2 = script.getNumberValue(\"PORT2\", script);\n\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if(!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.pyocoding.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime()\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            isNotFor: [ '0uboard' ],\n            class: \"SENSOR\",\n        },\n        pyocoding_get_digital_button: {\n          color: EntryStatic.colorSet.block.default.HARDWARE,\n          outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic_boolean_field\",\n            params: [{\n                \"type\": \"Block\",\n                \"accept\": \"string\"\n            }],\n            def: {\n                \"params\": [\n                    {\n                        \"type\": \"pyocoding_port_number\",\n                        \"params\": [6]\n                    }\n                ],\n                \"type\": \"pyocoding_get_digital_button\"\n            },\n            paramsKeyMap: {\n                \"PORT\": 0\n            },\n            class: \"digital\",\n            isNotFor: [ '0uboard' ],\n            func: function (sprite, script) {\n                var port = script.getNumberValue(\"PORT\", script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if(!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.pyocoding.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime()\n                };\n                return (DIGITAL) ? DIGITAL[port] || 0 : 0;\n            },\n        },\n        pyocoding_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic_boolean_field\",\n            params: [{\n                \"type\": \"Block\",\n                \"accept\": \"string\"\n            }],\n            def: {\n                \"params\": [\n                    {\n                        \"type\": \"pyocoding_get_port_number\"\n                    }\n                ],\n                \"type\": \"pyocoding_get_digital\"\n            },\n            paramsKeyMap: {\n                 \"PORT\": 0\n             },\n            isNotFor: [ '0uboard' ],\n            class: \"digital\",\n            func: function (sprite, script) {\n                var port = script.getNumberValue(\"PORT\", script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if(!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.pyocoding.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime()\n                };\n                return (DIGITAL) ? DIGITAL[port] || 0 : 0;\n            },\n        },\n        pyocoding_get_port_number1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic_string_field\",\n            statements: [],\n            params: [\n                {\n                    \"type\": \"Dropdown\",\n                    \"options\": [\n                        [ Lang.Blocks.RedColor, \"2\" ],\n                        [ Lang.Blocks.BlueColor, \"3\" ],\n                        [ Lang.Blocks.GreenColor, \"4\" ],\n                        [ Lang.Blocks.YellowColor, \"5\" ],\n                    ],\n                    \"value\": \"2\",\n                    \"fontSize\": 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            \"events\": {},\n            \"def\": {\n                \"params\": [ null ]\n            },\n            \"paramsKeyMap\": {\n                \"PORT\": 0\n            },\n            \"func\": function (sprite, script) {\n                return script.getStringField(\"PORT\");\n            },\n            \"class\": \"ArduinoExt\"\n        },\n        pyocoding_toggle_led: {\n          color: EntryStatic.colorSet.block.default.HARDWARE,\n          outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n          skeleton: 'basic',\n          params: [\n              {\n                  \"type\": \"Block\",\n                  \"accept\": \"string\"\n              },\n              {\n                  \"type\": \"Block\",\n                  \"accept\": \"string\"\n              }\n          ],\n          def: {\n              \"params\": [\n                  {\n                      \"type\": \"pyocoding_get_port_number1\"\n                  },\n                  {\n                      \"type\": \"arduino_get_digital_toggle\",\n                      \"params\": [ \"on\" ],\n                  },\n              ],\n              \"type\": \"pyocoding_toggle_led\"\n            },\n            \"paramsKeyMap\": {\n                \"PORT\": 0,\n                \"VALUE\": 1\n            },\n            \"isNotFor\": [ '0uboard' ],\n            \"class\": \"run\",\n            \"func\": function (sprite, script) {\n                var port = script.getNumberValue(\"PORT\");\n                var value = script.getValue(\"VALUE\");\n\n                if(typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if(Entry.ArduinoExt.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if(Entry.ArduinoExt.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.pyocoding.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime()\n                };\n                return script.callReturn();\n            },\n        },\n        pyocoding_pw_get_port_number: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: \"basic_string_field\",\n              statements: [],\n              params: [\n                  {\n                      \"type\": \"Dropdown\",\n                      \"options\": [\n                          [ \"5\", \"5\" ]\n                      ],\n                      \"value\": \"5\",\n                      \"fontSize\": 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  }\n              ],\n              events: {},\n              def: {\n                  \"params\": [ null ]\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0\n              },\n              func: function (sprite, script) {\n                  return script.getStringField(\"PORT\");\n              },\n          },\n        pyocoding_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'pyocoding_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'pwm',\n            isNotFor: ['0uboard'],\n            func: function(sprite, script) {\n                //var port = script.getNumberValue(\"PORT\");\n                var port = script.getField('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.DaduBlock.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Arduino.analogWrite(%1, %2)'] },\n        },\n        pyocoding_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['10', '10'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['무음', '0'],\n                        ['도', '1'],\n                        ['도#(레♭)', '2'],\n                        ['레', '3'],\n                        ['레#(미♭)', '4'],\n                        ['미', '5'],\n                        ['파', '6'],\n                        ['파#(솔♭)', '7'],\n                        ['솔', '8'],\n                        ['솔#(라♭)', '9'],\n                        ['라', '10'],\n                        ['라#(시♭)', '11'],\n                        ['시', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'pyocoding_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'pwm',\n            isNotFor: ['0uboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                //var port = script.getNumberValue(\"PORT\", script);\n                var port = script.getField('PORT', script);\n\n                if (!script.isStart) {\n                    var note = script.getNumberField('NOTE', script);\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (note === 0 || duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.DaduBlock.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberField('OCTAVE', script);\n                    var value = Entry.DaduBlock.toneMap[note][octave];\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq['SET'][port] = {\n                        type: Entry.DaduBlock.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.DaduBlock.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        pyocoding_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic\",\n            statements: [],\n            params: [\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                    type: \"pyocoding_pw_get_port_number\"\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"params\": [ \"0\" ]\n                    },\n                    null\n                ],\n                type: \"pyocoding_set_servo\"\n            },\n            paramsKeyMap: {\n                \"PORT\": 0,\n                \"VALUE\": 1\n            },\n            class: \"ext\",\n            isNotFor: [ '0uboard' ],\n            func: function (sprite, script) {\n                var port = script.getNumberValue(\"PORT\");\n                var value = script.getNumberValue(\"VALUE\");\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 180);\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: 4,\n                    data: value,\n                    time: new Date().getTime()\n                };\n                return script.callReturn();\n            },\n            \"syntax\": {}\n        },\n        pyocoding_oled_set: {\n          color: EntryStatic.colorSet.block.default.HARDWARE,\n          outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n          skeleton: \"basic\",\n          statements: [],\n          params: [\n              {\n                  \"type\": \"Dropdown\",\n                  \"options\": [\n                   [\"1\",\"1\"],\n                   [\"2\",\"2\"],\n                   [\"3\",\"3\"]\n                  ],\n                  \"value\":\"1\",\n                  \"fontSize\":11,\n                  bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                  arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n              },\n      \t\t    {\n                  \"type\": \"Block\",\n                  \"accept\": \"string\"\n              }\n          ],\n          events: {},\n          def: {\n              \"params\": [\n                  null,\n                  {\n                      \"type\":\"text\",\n                      \"params\": [ \"1\" ],\n                  },\n              ],\n              \"type\": \"pyocoding_oled_set\"\n          },\n          isNotFor: [ '0uboard' ],\n          paramsKeyMap: {\n              \"VALUE1\": 0,\n              \"VALUE2\": 1\n          },\n          class: \"ext\",\n          func: function (sprite, script) {\n              var line = script.getField(\"VALUE1\");\n              var text = script.getValue(\"VALUE2\");\n\n              if(!Entry.hw.sendQueue['SET']) {\n                  Entry.hw.sendQueue['SET'] = {};\n              }\n              Entry.hw.sendQueue['SET'][line] = {\n                  type: 241,\n                  data: text,\n                  time: new Date().getTime()\n              };\n              return script.callReturn();\n\n          },\n          \"syntax\": {}\n          },\n          pyocoding_neopixel_set: {\n                  color: EntryStatic.colorSet.block.default.HARDWARE,\n                  outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                  skeleton: 'basic',\n                  statements: [],\n                  params: [\n                      {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n                      {\n                              \"type\": \"Dropdown\",\n                              \"options\": [\n                               [\"1\",\"1\"],\n                               [\"2\",\"2\"],\n                              ],\n                              \"value\":\"1\",\n                              \"fontSize\":11,\n                              bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                              arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                      },\n                      {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n                      {\n                          type: 'Indicator',\n                          img: 'block_icon/hardware_icon.svg',\n                          size: 12,\n                      },\n                  ],\n                  events: {},\n      \t\t\tdef: {\n                      params: [\n                          {\n                              type: 'arduino_get_port_number',\n                              params: ['9'],\n                          },\n                          null,\n      \t\t\t\t\t          {\n                              type: 'number',\n                              params: ['12'],\n                          },\n                          null,\n                      ],\n                      type: 'pyocoding_neopixel_set',\n                  },\n                  paramsKeyMap: {\n                      PORT: 0,\n                      INDEX: 1,\n                      VALUE: 2,\n                  },\n                  class: 'neopixel',\n                  isNotFor: ['0uboard'],\n                  func(sprite, script) {\n                    var port = script.getNumberValue(\"PORT\");\n                    var mode = 1;\n                    var index = script.getNumberValue(\"INDEX\");\n                    var value = script.getNumberValue(\"VALUE\");\n\n                    if (!script.isStart)\n                    {\n\n                    if(!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.Orange.duration.TIME_10ms;\n          \t\t\t\t\t\tscript.isStart = true;\n          \t\t\t\t\t\tscript.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.pyocoding.sensorTypes.NEOPIXELCOLOR,\n                        data:\n                        {\n                          value : value,\n                          mode: mode,\n                          index: index,\n                        },\n                        time: new Date().getTime()\n                    };\n                    setTimeout(function() {\n                                  script.timeFlag = 0;\n                              }, duration );\n                              return script;\n          \t\t\t\t}\n          \t\t\t\telse if (script.timeFlag == 1)\n                          {\n                              return script;\n                          }\n                          else\n                          {\n                              delete script.timeFlag;\n                              delete script.isStart;\n\n                              Entry.engine.isContinue = false;\n                              return script.callReturn();\n                          }\n                  },\n                  syntax: {\n                  },\n              },\n      \t\tpyocoding_neopixel_led: {\n                  color: EntryStatic.colorSet.block.default.HARDWARE,\n                  outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                  skeleton: 'basic',\n                  statements: [],\n                  params: [\n                      {\n                              \"type\": \"Dropdown\",\n                              \"options\": [\n                               [\"1\",\"1\"],\n                               [\"2\",\"2\"],\n                              ],\n                              \"value\":\"1\",\n                              \"fontSize\":11,\n                              bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                              arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                      },\n                      {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n      \t\t\t\t{\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n      \t\t\t\t{\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n      \t\t\t\t        {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n                      {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n                      {\n                          type: 'Indicator',\n                          img: 'block_icon/hardware_icon.svg',\n                          size: 12,\n                      },\n                  ],\n                  events: {},\n      \t\t\tdef: {\n                      params: [\n                          null,\n      \t\t\t\t\t          {\n                              type: 'number',\n                              params: ['1'],\n                          },\n      \t\t\t\t\t          {\n                              type: 'number',\n                              params: ['255'],\n                          },\n      \t\t\t\t\t{\n                              type: 'number',\n                              params: ['255'],\n                          },\n      \t\t\t\t\t{\n                              type: 'number',\n                              params: ['255'],\n                          },\n                          {\n                              type: 'number',\n                              params: ['100'],\n                          },\n                          null,\n                      ],\n                      type: 'pyocoding_neopixel_led',\n                  },\n                  paramsKeyMap: {\n                      INDEX : 0,\n                      POS: 1,\n              \t\t\t\tRED: 2,\n              \t\t\t\tGREEN: 3,\n              \t\t\t\tBLUE: 4,\n                      BRIG: 5,\n                  },\n                  class: 'neopixel',\n                  isNotFor: ['0uboard'],\n                  func(sprite, script) {\n                    var port = script.getNumberValue(\"INDEX\");\n                    var pos = script.getNumberValue(\"POS\");\n                    var red = script.getNumberValue(\"RED\");\n                    var green = script.getNumberValue(\"GREEN\");\n                    var blue = script.getNumberValue(\"BLUE\");\n                    var brig = script.getNumberValue(\"BRIG\");\n                    var mode = 2;\n\n\n                    if (!script.isStart)\n                    {\n\n                    if(!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    var duration = Entry.Orange.duration.TIME_10ms;\n                      script.isStart = true;\n                      script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.pyocoding.sensorTypes.NEOPIXELCOLOR,\n                        data:\n                        {\n                          index : port,\n                          pos : pos,\n                          mode: mode,\n                          red: red,\n                          green: green,\n                          blue: blue,\n                          brig: brig,\n                        },\n                        time: new Date().getTime()\n                    };\n                    setTimeout(function() {\n                                  script.timeFlag = 0;\n                              }, duration );\n                              return script;\n          \t\t\t\t}\n          \t\t\t\telse if (script.timeFlag == 1)\n                          {\n                              return script;\n                          }\n                          else\n                          {\n                              delete script.timeFlag;\n                              delete script.isStart;\n\n                              Entry.engine.isContinue = false;\n                              return script.callReturn();\n                          }\n                  },\n                  syntax: {\n                  },\n              },\n              pyocoding_neopixel_all_led: {\n                      color: EntryStatic.colorSet.block.default.HARDWARE,\n                      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                      skeleton: 'basic',\n                      statements: [],\n                      params: [\n                          {\n                                  \"type\": \"Dropdown\",\n                                  \"options\": [\n                                   [\"1\",\"1\"],\n                                   [\"2\",\"2\"],\n                                  ],\n                                  \"value\":\"1\",\n                                  \"fontSize\":11,\n                                  bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                  arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                          },\n                          {\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n          \t\t\t\t{\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n          \t\t\t\t{\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n          \t\t\t\t        {\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n                          {\n                              type: 'Indicator',\n                              img: 'block_icon/hardware_icon.svg',\n                              size: 12,\n                          },\n                      ],\n                      events: {},\n          \t\t\tdef: {\n                          params: [\n                              null,\n          \t\t\t\t\t          {\n                                  type: 'number',\n                                  params: ['255'],\n                              },\n          \t\t\t\t\t{\n                                  type: 'number',\n                                  params: ['255'],\n                              },\n          \t\t\t\t\t{\n                                  type: 'number',\n                                  params: ['255'],\n                              },\n                              {\n                                  type: 'number',\n                                  params: ['100'],\n                              },\n                              null,\n                          ],\n                          type: 'pyocoding_neopixel_all_led',\n                      },\n                      paramsKeyMap: {\n                          INDEX : 0,\n                  \t\t\t\tRED: 1,\n                  \t\t\t\tGREEN: 2,\n                  \t\t\t\tBLUE: 3,\n                          BRIG: 4,\n                      },\n                      class: 'neopixel',\n                      isNotFor: ['0uboard'],\n                      func(sprite, script) {\n                        var port = script.getNumberValue(\"INDEX\");\n                        var red = script.getNumberValue(\"RED\");\n                        var green = script.getNumberValue(\"GREEN\");\n                        var blue = script.getNumberValue(\"BLUE\");\n                        var brig = script.getNumberValue(\"BRIG\");\n                        var mode = 3;\n\n                        if (!script.isStart)\n                        {\n\n                        if(!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        var duration = Entry.Orange.duration.TIME_10ms;\n                          script.isStart = true;\n                          script.timeFlag = 1;\n\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.pyocoding.sensorTypes.NEOPIXELCOLOR,\n                            data:\n                            {\n                              index : port,\n                              mode: mode,\n                              red: red,\n                              green: green,\n                              blue: blue,\n                              brig: brig,\n                            },\n                            time: new Date().getTime()\n                        };\n                        setTimeout(function() {\n                                      script.timeFlag = 0;\n                                  }, duration );\n                                  return script;\n                      }\n                      else if (script.timeFlag == 1)\n                              {\n                                  return script;\n                              }\n                              else\n                              {\n                                  delete script.timeFlag;\n                                  delete script.isStart;\n\n                                  Entry.engine.isContinue = false;\n                                  return script.callReturn();\n                              }\n                      },\n                      syntax: {\n                      },\n                  },\n                  pyocoding_dotmatrix: {\n                      color: EntryStatic.colorSet.block.default.HARDWARE,\n                      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                      skeleton: 'basic',\n                      statements: [],\n                      params: [\n                          {\n                                  \"type\": \"Dropdown\",\n                                  \"options\": [\n                                   [\"0\",\"0\"],\n                                   [\"1\",\"1\"],\n                                   [\"2\",\"2\"],\n                                   [\"3\",\"3\"],\n                                   [\"4\",\"4\"],\n                                   [\"5\",\"5\"],\n                                   [\"6\",\"6\"],\n                                   [\"7\",\"7\"],\n                                  ],\n                                  \"value\":\"0\",\n                                  \"fontSize\":11,\n                                  bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                  arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                          },\n                          {\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n                  {\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n                  {\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n                          {\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n                          {\n                              type: 'Indicator',\n                              img: 'block_icon/hardware_icon.svg',\n                              size: 12,\n                          },\n                      ],\n                      events: {},\n                def: {\n                          params: [\n                              null,\n                              {\n                                  type: 'number',\n                                  params: ['00001111'],\n                              },\n                    {\n                                  type: 'number',\n                                  params: ['255'],\n                              },\n                    {\n                                  type: 'number',\n                                  params: ['255'],\n                              },\n                              {\n                                  type: 'number',\n                                  params: ['100'],\n                              },\n                              null,\n                          ],\n                          type: 'pyocoding_dotmatrix',\n                      },\n                      paramsKeyMap: {\n                          INDEX : 0,\n                          RED: 1,\n                          GREEN: 2,\n                          BLUE: 3,\n                          BRIG: 4,\n                      },\n                      class: 'neopixel',\n                      isNotFor: ['0uboard'],\n                      func(sprite, script) {\n                        var port = script.getNumberValue(\"INDEX\");\n                        var red = script.getNumberValue(\"RED\");\n                        var green = script.getNumberValue(\"GREEN\");\n                        var blue = script.getNumberValue(\"BLUE\");\n                        var brig = script.getNumberValue(\"BRIG\");\n                        var mode = 3;\n\n                        let str = parseInt(String(red), 2);\n                        red = str;\n\n                        if(red > 255) red=255;\n                        console.log(red);\n\n\n                        if (!script.isStart)\n                        {\n\n                        if(!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        var duration = Entry.Orange.duration.TIME_10ms;\n                          script.isStart = true;\n                          script.timeFlag = 1;\n\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.pyocoding.sensorTypes.DOTMATRIX,\n                            data:\n                            {\n                              index : port,\n                              mode: mode,\n                              red: red,\n                              green: green,\n                              blue: blue,\n                              brig: brig,\n                            },\n                            time: new Date().getTime()\n                        };\n                        setTimeout(function() {\n                                      script.timeFlag = 0;\n                                  }, duration );\n                                  return script;\n                      }\n                      else if (script.timeFlag == 1)\n                              {\n                                  return script;\n                              }\n                              else\n                              {\n                                  delete script.timeFlag;\n                                  delete script.isStart;\n\n                                  Entry.engine.isContinue = false;\n                                  return script.callReturn();\n                              }\n                      },\n                      syntax: {\n                      },\n                  },\n    }   //return\n};  //function\n\nmodule.exports = Entry.pyocoding;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_CloverSEntry1.js",
    "content": "﻿\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'use strict';\n\n\n\n\nEntry.CloverSEntry1 = {\n    id: '38.1',\n    name: 'CloverSEntry1',\n    url: 'http://www.edu-rabbit.com',\n    imageName: 'CloverSEntry1.png',\n    title: {\n        ko: '에듀래빗_클로버',\n        en: 'Edurabbit_Clover',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET && !Entry.hw.sendQueue.SET_CLOVER && !Entry.hw.sendQueue.GET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n                GET_CLOVER: {},\n                SET_CLOVER: {},\n            };\n        }\n        else\n        {            \n            var self = this;\n            \n            if(Entry.hw.sendQueue.SET)\n            {\n                var keySet = Object.keys(Entry.hw.sendQueue.SET);\n                var keyInt = null;\n                keySet.forEach(function(key) \n                {\n                    keyInt = parseInt(key);\n                    switch(keyInt)\n                    {\n                        case self.pinMaps.Digital_Port0 :                                  \n                        case self.pinMaps.Digital_Port1 :                                  \n                            Entry.hw.sendQueue.SET[key].data = 1;\n                            break;\n                        case self.pinMaps.Digital_Port2 :                                  \n                        case self.pinMaps.Digital_Port3 :                                  \n                        case self.pinMaps.Digital_Port4 :                                  \n                        case self.pinMaps.Digital_Port5 :                                  \n                        case self.pinMaps.Digital_Port6 :                                  \n                            Entry.hw.sendQueue.SET[key].data = 0;\n                            break;\n                        \n                        default :\n                            Entry.hw.sendQueue.SET[key].data = 0xFF;\n                            break;\n                    }\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                });\n            }\n            \n            if(Entry.hw.sendQueue.GET)\n            {\n                var keySet = Object.keys(Entry.hw.sendQueue.GET);\n                var keyInt = null;\n                keySet.forEach(function(key) \n                {\n                    keyInt = parseInt(key);\n                    switch(keyInt)\n                    {\n                        case self.sensorTypes.ULTRASONIC :\n                            Entry.hw.sendQueue.GET[key].port = [self.pinMaps.Ultrasonic_TRIG, self.pinMaps.Ultrasonic_ECHO];\n                            Entry.hw.sendQueue.GET[key].data = 1;\n                            break;\n                    }\n                    Entry.hw.sendQueue.GET[key].time = new Date().getTime();\n                });\n            }\n\n            if(Entry.hw.sendQueue.SET_CLOVER)\n            {\n                var keySet = Object.keys(Entry.hw.sendQueue.SET_CLOVER);\n                var keyInt = null;\n                keySet.forEach(function(key) \n                {\n                    keyInt = parseInt(key);\n                    if(key == 0)  \n                    {\n                        Entry.hw.sendQueue.SET_CLOVER[key].data = 0;\n                    }\n                    else if (key <= 80)  \n                    {\n                        Entry.hw.sendQueue.SET_CLOVER[key].data = 1;\n                    }\n                    else if (key <= 100)  \n                    {\n                        Entry.hw.sendQueue.SET_CLOVER[key].data = 0;\n                    }\n                    else if(key == 101)  \n                    {\n                        Entry.hw.sendQueue.SET_CLOVER[key].data = 0;\n                    }\n                    Entry.hw.sendQueue.SET_CLOVER[key].time = new Date().getTime();\n                });\n            }\n            \n            if(Entry.hw.sendQueue.GET_CLOVER)\n            {\n                var keySet = Object.keys(Entry.hw.sendQueue.GET_CLOVER);\n                var keyInt = null;\n                keySet.forEach(function(key) \n                {\n                    keyInt = parseInt(key);\n                    Entry.hw.sendQueue.GET_CLOVER[key].time = new Date().getTime();\n                });\n            }\n        }\n           \n        Entry.hw.update();\n    },\n    \n    \n    \n    \n\tmonitorTemplate: { \n        imgPath: 'hw/CloverSEntry1.png',                        \n        width: 420,\n        height: 420,\n        listPorts: {  \n            M_SW1: { name: '스위치1', type: 'input', pos: { x: 0, y: 0 }},\n            M_SW2: { name: '스위치2', type: 'input', pos: { x: 0, y: 0 }},\n            M_ANALOG1: { name: '아날로그1', type: 'input', pos: { x: 0, y: 0 }},\n            M_ANALOG2: { name: '아날로그2', type: 'input', pos: { x: 0, y: 0 }},\n            M_ULTRASONIC: { name: '초음파센서', type: 'input', pos: { x: 0, y: 0 }},\n            M_CDS: { name: '조도센서', type: 'input', pos: { x: 0, y: 0 }},\n            M_TEMP: { name: '온도센서', type: 'input', pos: { x: 0, y: 0 }},\n            M_C_SW1: { name: '클로버 스위치1', type: 'input', pos: { x: 0, y: 0 }},\n            M_C_SW2: { name: '클로버 스위치2', type: 'input', pos: { x: 0, y: 0 }},\n            M_C_SW3: { name: '클로버 스위치3', type: 'input', pos: { x: 0, y: 0 }},\n            M_C_SW4: { name: '클로버 스위치4', type: 'input', pos: { x: 0, y: 0 }},\n            M_C_SW5: { name: '클로버 스위치5', type: 'input', pos: { x: 0, y: 0 }},\n            M_C_SW6: { name: '클로버 스위치6', type: 'input', pos: { x: 0, y: 0 }},\n            M_C_SW7: { name: '클로버 스위치7', type: 'input', pos: { x: 0, y: 0 }},\n            M_C_SW8: { name: '클로버 스위치8', type: 'input', pos: { x: 0, y: 0 }},\n        },\n        \n        ports : {\n            \n        },\n\t\t\t\n\t\t\n\t\t\n\t\t\n        mode: 'both',\n    },\n    \n   \n\t\n    \n\tactionType :\n\t{\n        GET :            1,\n        SET :            2,\n        RESET :          3,\n\t},\n\t\n\t\n\tsensorTypes :\n    {\n\t\tALIVE :          0,               \n        DIGITAL :        1,               \n        ANALOG :         2,               \n        PWM :            3,               \n        SERVO :          4,               \n        TONE :           5,               \n        PULSEIN :        6,               \n        ULTRASONIC :     7,               \n        TIMER :          8,               \n        MOTOR_L :        9,               \n        MOTOR_R :        10,              \n        \n        CLOVER_FND :     11,              \n        CLOVER_SW :      12,              \n        CLOVER_LED :     13,              \n        CLOVER_RGB :     14,              \n        CLOVER_TEMP :    15,              \n\t},\n    \n    \n    \n    pinMaps : \n    {\n        SW1 :             2,               \n        SW2 :             7,               \n        LED_G :           17,              \n        LED_B :           16,              \n        BUZZ :            4,               \n        CDS :             7,               \n                          \n        Digital_Port0 :   17,              \n        Digital_Port1 :   16,              \n        Digital_Port2 :   3,               \n        Digital_Port3 :   5,               \n        Digital_Port4 :   6,               \n        Digital_Port5 :   9,               \n        Digital_Port6 :   10,              \n        Digital_Port7 :   11,              \n        Digital_Port8 :   12,              \n        Digital_Port9 :   13,              \n                          \n        Analog_Port0 :    14,              \n        Analog_Port1 :    15,              \n                          \n        DIR_L :           5,              \n        EN_L :            6,              \n        DIR_R :           9,              \n        EN_R :            10,             \n        \n        Ultrasonic_TRIG : 13,             \n        Ultrasonic_ECHO : 12,             \n    },\n    \n    CloverMaps :\n    {\n        FND :             0,              \n        MODULE0 :         39,             \n        MODULE1 :         38,             \n        MODULE2 :         37,             \n        MODULE3 :         36,             \n        MODULE4 :         35,             \n        MODULE5 :         34,             \n        MODULE6 :         33,             \n        MODULE7 :         32,             \n    },\n      \n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    \n    directionTable: {\n        Forward: 0,\n        Backward: 1,\n    },\n  \n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\n\nEntry.CloverSEntry1.blockMenuBlocks = [\n    \n    'CloverSEntry1_set_digital',\n    'CloverSEntry1_set_digital1',\n    'CloverSEntry1_set_tone',\n    'CloverSEntry1_set_servo',\n    'CloverSEntry1_set_motor',\n    'CloverSEntry1_set_rgb',\n    'CloverSEntry1_set_fnd',\n    'CloverSEntry1_clover_set_led',\n    'CloverSEntry1_get_digital',\n    'CloverSEntry1_get_digital_servo',\n    'CloverSEntry1_get_analog_value',\n    'CloverSEntry1_get_analog_value_map',\n    'CloverSEntry1_get_ultrasonic_value',\n    'CloverSEntry1_get_cds_value',\n    'CloverSEntry1_get_temp_value',\n    'CloverSEntry1_clover_get_sw',\n];\n\n\nEntry.CloverSEntry1.setLanguage = () => {\n\treturn {\n\t\tko: {\n\t\t\ttemplate: \n            {\n\t\t\t\tCloverSEntry1_set_digital :          '%1 을 %2 %3',  \n                CloverSEntry1_set_digital1 :         '%1 을 %2 %3',\n                CloverSEntry1_set_tone :             '부저를  %1 %2 음으로 %3초 연주하기 %4',\n                CloverSEntry1_set_servo :            '%1 번 서보모터를 %2 의 각도로 정하기 %3',\n                CloverSEntry1_set_motor :            '%1 모터를 %2 으로 %3 회전 속도로 정하기 %4',\n                CloverSEntry1_set_fnd :              '클로버 숫자표시기(FND)에 %1 출력하기 %2',\n                CloverSEntry1_clover_set_led :       '클로버 LED %1 을 %2 %3',\n                CloverSEntry1_get_digital :          '스위치 %1 번 값',\n                CloverSEntry1_get_digital_servo :    '디지털 %1 번 값',\n                CloverSEntry1_get_analog_value :     '아날로그 %1 번 센서값',\n                CloverSEntry1_get_analog_value_map : '아날로그 %1 번 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                CloverSEntry1_get_ultrasonic_value : '초음파센서 센서값',\n                CloverSEntry1_get_cds_value :        '조도센서 센서값',\n                CloverSEntry1_get_temp_value :       '온도센서 센서값',\n                CloverSEntry1_clover_get_sw :        '클로버 버튼 %1 번 값',\n                CloverSEntry1_set_rgb :              '컬러LED를 빨강%1 초록%2 파랑%3 밝기%4로 켜기 %5',\n\t\t\t}\n\t\t},\n\t\t\n\t\t\t\n            \n\t\t\t\t\n\t\t\t\n\t\t\n        \n\t\t\t\n            \n\t\t\t\t\n\t\t\t\n\t\t\n        \n\t\t\t\n            \n\t\t\t\t\n\t\t\t\n\t\t\n\t}\n};\n\nEntry.CloverSEntry1.getBlocks = function() {\n    return {\n        \n        \n        CloverSEntry1_set_digital: \n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: \n            [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        [\"녹색\",    this.pinMaps.Digital_Port0],\n                        [\"파랑색\",  this.pinMaps.Digital_Port1],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options :\n                    [\n                        [\"켠다\",0],\n                        [\"끈다\",1]\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                     type: 'Indicator',\n                     img: 'block_icon/hardware_icon.svg',\n                     size: 12,\n                },\n            ],\n            events: {},\n            def: \n            {\n                params: [\n                this.pinMaps.Digital_Port0,\n                0,\n                null,\n                ],\n                type: 'CloverSEntry1_set_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'setBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script)\n            {\n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                \n                var sq = Entry.hw.sendQueue;\n                var port = script.getField('PORT', script);\n                var value = script.getField('VALUE', script);\n                \n                if (!sq['SET']) { sq['SET'] = {}; }\n                \n                sq['SET'][port] = {\n                   type: self.sensorTypes.DIGITAL,\n                   data: value,\n                   time: new Date().getTime(),\n                };\n            },\n            \n        },\n        \n        \n        \n        \n        CloverSEntry1_set_digital1: \n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: \n            [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        [\"디지털3\", this.pinMaps.Digital_Port2],\n                        [\"디지털5\", this.pinMaps.Digital_Port3],\n                        [\"디지털6\", this.pinMaps.Digital_Port4],\n                        [\"디지털9\", this.pinMaps.Digital_Port5],\n                        [\"디지털10\", this.pinMaps.Digital_Port6],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options :\n                    [\n                        [\"HIGH\",1],\n                        [\"LOW\",0]\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                     type: 'Indicator',\n                     img: 'block_icon/hardware_icon.svg',\n                     size: 12,\n                },\n            ],\n            events: {},\n            def: \n            {\n                params: [\n                this.pinMaps.Digital_Port2,\n                0,\n                null,\n                ],\n                type: 'CloverSEntry1_set_digital1',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'setBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script)\n            {\n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                \n                var sq = Entry.hw.sendQueue;\n                var port = script.getField('PORT', script);\n                var value = script.getField('VALUE', script);\n                \n                if (!sq['SET']) { sq['SET'] = {}; }\n                \n                sq['SET'][port] = {\n                   type: self.sensorTypes.DIGITAL,\n                   data: value,\n                   time: new Date().getTime(),\n                };\n            },\n            \n        },\n         \n         \n         \n        \n        CloverSEntry1_tone_list:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: \n            [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        CloverSEntry1_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'CloverSEntry1_tone_list',\n                    },\n                ],\n                type: 'CloverSEntry1_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        CloverSEntry1_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '3',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        CloverSEntry1_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'CloverSEntry1_tone_list',\n                    },\n                    {\n                        type: 'CloverSEntry1_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'CloverSEntry1_set_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'setBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                \n                var sq = Entry.hw.sendQueue;\n                var port = self.pinMaps.BUZZ;\n                \n                if (!script.isStart)\n                {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) note = Entry.CloverSEntry1.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    \n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.CloverSEntry1.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var value = 0;\n\n                    if (note != 0) {\n                        value = Entry.CloverSEntry1.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.CloverSEntry1.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } \n                else if (script.timeFlag == 1)\n                {\n                    return script;\n                } \n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.CloverSEntry1.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n                return null;\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        \n        CloverSEntry1_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        ['1', this.pinMaps.Digital_Port2],\n                        ['2', this.pinMaps.Digital_Port3],\n                        ['3', this.pinMaps.Digital_Port4],\n                        ['4', this.pinMaps.Digital_Port5],\n                        ['5', this.pinMaps.Digital_Port6],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    this.pinMaps.Digital_Port2,\n                    90,\n                    null,\n                ],\n                type: 'CloverSEntry1_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'setBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                \n                \n                \n              \n                var self = Entry.CloverSEntry1;\n                \n                var sq = Entry.hw.sendQueue;\n                var port = script.getField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                \n                if(value < 0) value = 0;\n                else if (value > 180) value = 180;\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: self.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        \n        CloverSEntry1_set_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        ['왼쪽', 0],\n                        ['오른쪽', 1],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        ['앞', 0],\n                        ['뒤', 1],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    0,\n                    0,\n                    {\n                        type: 'number',\n                        params: ['200'],\n                    },\n                    null,\n                ],\n                type: 'CloverSEntry1_set_motor',\n            },\n            paramsKeyMap: {\n                MOTOR_ANGLE: 0,\n                MOTOR_DIRECTION: 1,\n                MOTOR_SPEED: 2,\n            },\n            class: 'setBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                \n                var angle = script.getField('MOTOR_ANGLE', script);\n                var direction = script.getField('MOTOR_DIRECTION', script);\n                var speed = script.getNumberValue('MOTOR_SPEED', script) - 1;\n                \n                \n                if (speed < 0) \n                {\n                    speed = 0;\n                }\n                else if (speed > 254) \n                {\n                    speed = 254;\n                }\n                \n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                \n                if(angle == 0)\n                {\n                    Entry.hw.sendQueue['SET'][0] = \n                    {\n                        type: Entry.CloverSEntry1.sensorTypes.MOTOR_L,\n                        data: {\n                            direction: direction,\n                            speed: speed,\n                        },\n                        time: new Date().getTime(),\n                    };\n                }\n                else\n                {\n                    Entry.hw.sendQueue['SET'][1] = \n                    {\n                        type: Entry.CloverSEntry1.sensorTypes.MOTOR_R,\n                        data: {\n                            direction: direction,\n                            speed: speed,\n                        },\n                        time: new Date().getTime(),\n                    };\n                }\n                \n\n                setTimeout(function() {\n                    script.timeFlag = 0;\n                }, 10);\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        \n        CloverSEntry1_set_fnd: \n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: \n            [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    \n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                     type: 'Indicator',\n                     img: 'block_icon/hardware_icon.svg',\n                     size: 12,\n                },\n            ],\n            events: {},\n            def: \n            {\n                params: [\n                0,\n                null,\n                ],\n                type: 'CloverSEntry1_set_fnd',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'setBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script)\n            {\n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                \n                var sq = Entry.hw.sendQueue;\n                var port = 0; \n                var value = script.getNumberValue('VALUE', script);\n                \n                if (!sq['SET_CLOVER']) { sq['SET_CLOVER'] = {}; }\n                \n                sq['SET_CLOVER'][port] = {\n                   type: self.sensorTypes.CLOVER_FND,\n                   data: value,\n                   time: new Date().getTime(),\n                };\n            },\n            \n        },\n        \n        \n        \n        \n        CloverSEntry1_set_rgb: \n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: \n            [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    \n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    \n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    \n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    \n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                     type: 'Indicator',\n                     img: 'block_icon/hardware_icon.svg',\n                     size: 12,\n                },\n            ],\n            events: {},\n            def: \n            {\n                params: [\n                100,\n                100,\n                100,\n                10,\n                null,\n                ],\n                type: 'CloverSEntry1_set_rgb',\n            },\n            paramsKeyMap: {\n                COLOR_R: 0,\n                COLOR_G: 1,\n                COLOR_B: 2,\n                COLOR_W: 3,\n            },\n            class: 'setBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script)\n            {\n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                var color_r = script.getNumberValue('COLOR_R', script);\n                var color_g = script.getNumberValue('COLOR_G', script);\n                var color_b = script.getNumberValue('COLOR_B', script);\n                var color_w = script.getNumberValue('COLOR_W', script);\n                var sq = Entry.hw.sendQueue;\n                var port = 101;  \n                var value;\n                \n                \n                if(isNaN(color_r)) { color_r = 0; }\n                if(isNaN(color_g)) { color_g = 0; }\n                if(isNaN(color_b)) { color_b = 0; }\n                if(isNaN(color_w)) { color_w = 0; }\n                \n                if(color_r < 0) { color_r = 0; }; if(color_r > 255) { color_r = 255; }\n                if(color_g < 0) { color_g = 0; }; if(color_g > 255) { color_g = 255; }\n                if(color_b < 0) { color_b = 0; }; if(color_b > 255) { color_b = 255; }\n                if(color_w < 0) { color_w = 0; }; if(color_w > 255) { color_w = 255; }\n                \n                \n                value = 0;  \n                value = (color_r << 24) | (color_g << 16) | (color_b << 8) | (color_w << 0);\n                \n                if (!sq['SET_CLOVER']) { sq['SET_CLOVER'] = {}; }\n                \n                sq['SET_CLOVER'][port] = {\n                  type: self.sensorTypes.CLOVER_RGB,\n                  data: value,\n                  time: new Date().getTime(),\n                };\n                \n            },\n            \n        },\n        \n        \n        \n        \n        CloverSEntry1_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        ['1', this.pinMaps.SW1],\n                        ['2', this.pinMaps.SW2],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    this.pinMaps.SW1,\n                ],\n                type: 'CloverSEntry1_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'getBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.CloverSEntry1.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                \n                if( DIGITAL[port] == 0) { return true; }\n                else { return false;}\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        \n        \n        CloverSEntry1_get_digital_servo: \n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        [\"3\", 3],\n                        [\"5\", 5],\n                        [\"6\", 6],\n                        [\"9\", 9],\n                        [\"10\", 10],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    3,\n                ],\n                type: 'CloverSEntry1_get_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'getBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                \n                Entry.hw.sendQueue['GET'][Entry.CloverSEntry1.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                \n                if( DIGITAL[port] != 0) { return true; }\n                else { return false;}\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        \n        CloverSEntry1_get_analog_value: \n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        [\"1\", 0],\n                        [\"2\", 1],\n\t\t\t\t\t],\n                    value : 0,\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [ null ],\n                type: 'CloverSEntry1_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'getBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                return ANALOG[port];\n            },\n            syntax: { js: [], py: [] },\n        },\n            \n            \n\n        \n        CloverSEntry1_get_analog_value_map:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        [\"1\", 0],\n                        [\"2\", 1],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    0,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'CloverSEntry1_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'getBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var org_value;      \n                var org_percent;    \n                var org_range;      \n                var dest_range;     \n                var dest_value;     \n                var swap = 0;\n                \n                \n                if(value2 > value3)\n                {\n                    swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) \n                {\n                    swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                \n                \n                org_value = ANALOG[port] - value2;\n                org_range = value3 - value2;\n                \n                dest_range = value5 - value4;\n                \n                \n                if(org_range <= 0) { return 0; }\n                if(dest_range <= 0) { return 0; }\n                if(org_value <= 0) {return 0; }\n                \n                \n                org_percent = (org_value / org_range) * 100;\n                dest_value = value4 + (dest_range * (org_percent / 100));\n                \n                \n                if(dest_value < value4) { dest_value = value4; }\n                if(dest_value > value5) { dest_value = value5; }\n                \n                return dest_value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        \n        CloverSEntry1_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'CloverSEntry1_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n            },\n            class: 'getBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                var port1 = Entry.CloverSEntry1.pinMaps.Ultrasonic_TRIG;\n                var port2 = Entry.CloverSEntry1.pinMaps.Ultrasonic_ECHO;\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.CloverSEntry1.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    data : 0,\n                    time: new Date().getTime(),\n                };\n                \n                return Entry.hw.portData.ULTRASONIC;\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        \n        CloverSEntry1_get_cds_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'CloverSEntry1_get_cds_value',\n            },\n            paramsKeyMap: {\n            },\n            class: 'getBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                \n                var port = self.pinMaps.CDS;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                \n                return ANALOG[port];\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n        \n        CloverSEntry1_get_temp_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'CloverSEntry1_get_temp_value',\n            },\n            paramsKeyMap: {\n            },\n            class: 'getBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                \n                var port = self.pinMaps.CDS;\n                var temp = Entry.hw.portData.TEMP;\n                \n                return temp;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        \n        \n        \n        CloverSEntry1_clover_set_led: \n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: \n            [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        [\"1\",  1],\n                        [\"2\",  2],\n                        [\"3\",  3],\n                        [\"4\",  4],\n                        [\"5\",  5],\n                        [\"6\",  6],\n                        [\"7\",  7],\n                        [\"8\",  8],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options :\n                    [\n                        [\"켠다\",0],\n                        [\"끈다\",1]\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                     type: 'Indicator',\n                     img: 'block_icon/hardware_icon.svg',\n                     size: 12,\n                },\n            ],\n            events: {},\n            def: \n            {\n                params: [\n                1,\n                0,\n                null,\n                ],\n                type: 'CloverSEntry1_clover_set_led',\n            },\n            paramsKeyMap: {\n                NUM : 0,\n                VALUE: 1,\n            },\n            class: 'setBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script)\n            {\n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                \n                var sq = Entry.hw.sendQueue;\n                var port;\n                var id = self.CloverMaps.MODULE1; \n                var num = script.getField('NUM', script);\n                var value = script.getField('VALUE', script);\n                \n                switch (id)\n                {\n                    case self.CloverMaps.MODULE0 :\n                        port = (0*10) + num;\n                        break;\n                        \n                    case self.CloverMaps.MODULE1 :\n                        port = (1*10) + num;\n                        break;\n                        \n                    case self.CloverMaps.MODULE2 :\n                        port = (2*10) + num;\n                        break;\n                        \n                    case self.CloverMaps.MODULE3 :\n                        port = (3*10) + num;\n                        break;\n                        \n                    case self.CloverMaps.MODULE4 :\n                        port = (4*10) + num;\n                        break;\n                        \n                    case self.CloverMaps.MODULE5 :\n                        port = (5*10) + num;\n                        break;\n                        \n                    case self.CloverMaps.MODULE6 :\n                        port = (6*10) + num;\n                        break;\n                        \n                    case self.CloverMaps.MODULE7 :\n                        port = (7*10) + num;\n                        break;\n                }\n                \n                if (!sq['SET_CLOVER']) { sq['SET_CLOVER'] = {}; }\n                \n                sq['SET_CLOVER'][port] = {\n                   type: self.sensorTypes.CLOVER_LED,\n                   data: value,\n                   num :  num - 1,\n                   time: new Date().getTime(),\n                };\n            },\n            \n        },\n        \n        \n        \n        \n        CloverSEntry1_clover_get_sw: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options : \n                    [\n                        [\"1\",  1],\n                        [\"2\",  2],\n                        [\"3\",  3],\n                        [\"4\",  4],\n                        [\"5\",  5],\n                        [\"6\",  6],\n                        [\"7\",  7],\n                        [\"8\",  8],\n\t\t\t\t\t],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    1,\n                ],\n                type: 'CloverSEntry1_clover_get_sw',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'getBlock',\n            isNotFor: ['CloverSEntry1'],\n            func: function(sprite, script) {\n                \n                \n                \n                \n                var self = Entry.CloverSEntry1;\n                \n                var port = self.CloverMaps.MODULE0;\n                var num = script.getField('PORT', script) - 1;\n                var id = self.CloverMaps.MODULE0 - port + 1;\n                var CLOVER = Entry.hw.portData.CLOVER;\n                var value;\n                                \n                if (!Entry.hw.sendQueue['GET_CLOVER']) {\n                    Entry.hw.sendQueue['GET_CLOVER'] = {};\n                }\n                Entry.hw.sendQueue['GET_CLOVER'][Entry.CloverSEntry1.sensorTypes.CLOVER_SW] = {\n                    port: port,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                \n                value = (CLOVER[id] & (0x01 << num)) >> num;\n                \n                if(value == 1) { return true; }\n                else { return false; }\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n        \n        \n    };\n};\n\nmodule.exports = Entry.CloverSEntry1;\n\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_ITPLE_board.js",
    "content": "'use strict';\n\nEntry.ITPLE = {\n    // 이전 버튼 상태 저장\n    prevButtonState: {\n        'A0': 1, 'A1': 1, '7': 1, '8': 1,\n    },\n    afterReceive(pd) {\n        if (!Entry.engine.isState('run')) {\n            return;\n        }\n        \n        // 버튼 상태 확인\n        const portConfigs = [\n            { key: 'A0', type: 'ANALOG', index: 0 },\n            { key: 'A1', type: 'ANALOG', index: 1 },\n            { key: '7', type: 'DIGITAL', index: 7 },\n            { key: '8', type: 'DIGITAL', index: 8 },\n        ];\n        \n        let buttonPressed = false;\n        for (const config of portConfigs) {\n            const currentValue = Entry.hw.portData[config.type]?.[config.index] ?? 1;\n            const prevValue = Entry.ITPLE.prevButtonState[config.key];\n            \n            // 버튼이 눌린 순간 감지 (1 → 0)\n            if (prevValue !== 0 && currentValue === 0) {\n                buttonPressed = true;\n            }\n            Entry.ITPLE.prevButtonState[config.key] = currentValue;\n        }\n        \n        // 버튼이 눌린 순간에만 이벤트 발생\n        if (buttonPressed) {\n            Entry.engine.fireEvent('ITPLE_press_button');\n        }\n    },\n    id: '5E.1',\n    name: 'ITPLE',\n    url: 'http://www.itpleinfo.com/',\n    imageName: 'ITPLE.png',\n    title: {\n        ko: '잇플보드',\n        en: 'ITPLE board',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        }\n\n        // 기존 큐 초기화\n        const keySet = Object.keys(Entry.hw.sendQueue.SET);\n        keySet.forEach((key) => {\n            const portNum = parseInt(key);\n            // 네오픽셀 관련 포트(100-103, 200-205)와 물리 포트 9는 별도 처리\n            // 206(BLINK), 207(BLINK_STOP)은 명시적으로 삭제\n            if (portNum === 206 || portNum === 207) {\n                delete Entry.hw.sendQueue.SET[key];\n            } else if (portNum !== 9 && !(portNum >= 100 && portNum <= 103) && !(portNum >= 200 && portNum <= 205)) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            }\n        });\n\n        // 깜박이기 중지 명령 전송 (전체) - INIT보다 먼저 실행\n        const stopTime = new Date().getTime();\n        Entry.hw.sendQueue.SET[206] = {\n            type: 15, // NEOPIXEL_BLINK_STOP\n            data: { side: 2 }, // 전체\n            time: stopTime,\n        };\n        console.log('[ITPLE] setZero - BLINK_STOP sent at', stopTime);\n        Entry.hw.update(); // 즉시 전송\n\n        // NEOPIXEL_INIT 명령 전송 (네오픽셀 끄기)\n        // 깜박이기 중지 후 약간의 시간차를 두고 INIT 실행\n        setTimeout(() => {\n            const initTime = new Date().getTime();\n            Entry.hw.sendQueue.SET[200] = {\n                type: 9, // NEOPIXEL_INIT\n                data: 0,\n                time: initTime,\n            };\n            console.log('[ITPLE] setZero - NEOPIXEL_INIT sent at', initTime);\n            Entry.hw.update();\n        }, 20);\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        NEOPIXEL_INIT: 9,\n        NEOPIXEL_COLOR: 10,\n        NEOPIXEL_BRIGHTNESS: 11,\n        NEOPIXEL_SHIFT: 12,\n        NEOPIXEL_ROTATE: 13,\n        NEOPIXEL_BLINK: 14,\n        NEOPIXEL_BLINK_STOP: 15,\n    },\n    toneTable: {\n        0: 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        4: [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        5: [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        6: [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    duration: {\n        TIME_1ms: 1,\n        TIME_5ms: 5,\n        TIME_10ms: 10,\n        TIME_20ms: 20,\n        TIME_50ms: 50,\n        TIME_100ms: 100,\n        TIME_200ms: 200,\n        TIME_500ms: 500,\n        TIME_600ms: 600,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n    EdgeFlag: {\n        'A0': false,\n        'A1': false,\n        '7': false,\n        '8': false,\n    },\n    timeSeq: 0,\n};\n\nEntry.ITPLE.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                ITPLE_push_button: '%1 %2 버튼을 눌렀을 때',\n                ITPLE_get_button_value: '%1 버튼 값',\n                ITPLE_get_sensor_value: '%1 센서 값',\n                ITPLE_get_ultrasonic_value: '초음파 센서 값',\n                ITPLE_is_key_pressed: '%1 키가 눌러져 있는가?',\n                ITPLE_value_sensor: '%1 센서 값이 %2보다 %3',\n                ITPLE_turn_led: '%1 LED %2 %3',\n                ITPLE_set_tone: '버저를 %1 %2 음으로 %3 초 연주하기 %4',\n                ITPLE_set_motor_direction: '%1 모터 %2 방향으로 정하기 %3',\n                ITPLE_set_motor_speed: '%1 모터 %2 빠르기로 정하기 %3',\n                ITPLE_set_servo: '서보모터를 %2 도로 정하기 %3',\n                ITPLE_set_neopixel_init: '네오픽셀 모두 끄기 %1',\n                ITPLE_set_neopixel: '%1 번째 네오픽셀 LED를 %2 색으로 켜기 %3',\n                ITPLE_set_neopixel_all: '네오픽셀 전체의 색상을 %1 (으)로 켜기 %2',\n                ITPLE_set_neopixel_range: '%1 번부터 %2 번까지 네오픽셀을 %3 색상으로 켜기 %4',\n                ITPLE_set_neopixel_rotate: '네오픽셀 %1 방향으로 %2 칸 이동 %3',\n                ITPLE_set_neopixel_brightness: '네오픽셀 최대 밝기를 %1 (으)로 정하기 %2',\n                ITPLE_set_neopixel_blink: '%1 네오픽셀 %2 색으로 깜박이기 (간격: %3초) %4',\n                ITPLE_stop_neopixel_blink: '%1 네오픽셀 깜박이기 중지 %2',\n                ITPLE_color_picker_value: '색상 선택 %1',\n                ITPLE_rgb_to_color_value: 'R: %1 G: %2 B: %3 색상값',\n            },\n        },\n        en: {\n            template: {\n                ITPLE_push_button: '%1 When %2 button is pressed',\n                ITPLE_get_button_value: '%1 button value',\n                ITPLE_get_sensor_value: '%1 sensor value',\n                ITPLE_get_ultrasonic_value: 'Ultrasonic sensor value',\n                ITPLE_is_key_pressed: '%1 key pressed',\n                ITPLE_value_sensor: 'Is %1 sensor value %3 than %2',\n                ITPLE_turn_led: '%1 LED %2 %3',\n                ITPLE_set_tone: 'Play tone on note %1 octave %2 beat %3 %4',\n                ITPLE_set_motor_direction: '%1 motor %2 direction %3',\n                ITPLE_set_motor_speed: '%1 motor %2 speed %3',\n                ITPLE_set_servo: 'Set servo motor to %2 degree %3',\n                ITPLE_set_neopixel_init: 'Turn off all NeoPixels %1',\n                ITPLE_set_neopixel: 'Set NeoPixel %1 to %2 color %3',\n                ITPLE_set_neopixel_all: 'Set all NeoPixels to %1 color %2',\n                ITPLE_set_neopixel_range: 'Fill NeoPixels from %1 to %2 with %3 color %4',\n                ITPLE_set_neopixel_rotate: 'Shift NeoPixels %1 by %2 steps %3',\n                ITPLE_set_neopixel_brightness: 'Set NeoPixel max brightness to %1 %2',\n                ITPLE_set_neopixel_blink: 'Blink %1 NeoPixels %2 color (interval: %3s) %4',\n                ITPLE_stop_neopixel_blink: 'Stop %1 NeoPixel blinking %2',\n                ITPLE_color_picker_value: 'Pick color %1',\n                ITPLE_rgb_to_color_value: 'Color from R:%1 G:%2 B:%3',\n            },\n        },\n    };\n};\n\nEntry.ITPLE.blockMenuBlocks = [\n    'ITPLE_push_button',\n    'ITPLE_get_button_value',\n    'ITPLE_get_sensor_value',\n    'ITPLE_get_ultrasonic_value',\n    'ITPLE_color_picker_value',\n    'ITPLE_rgb_to_color_value',\n    'ITPLE_is_key_pressed',\n    'ITPLE_value_sensor',\n    'ITPLE_turn_led',\n    'ITPLE_set_tone',\n    'ITPLE_set_motor_direction',\n    'ITPLE_set_motor_speed',\n    'ITPLE_set_servo',\n    'ITPLE_set_neopixel_init',\n    'ITPLE_set_neopixel',\n    'ITPLE_set_neopixel_all',\n    'ITPLE_set_neopixel_range',\n    'ITPLE_set_neopixel_rotate',\n    'ITPLE_set_neopixel_brightness',\n    'ITPLE_set_neopixel_blink',\n    'ITPLE_stop_neopixel_blink',\n];\n\n//region ITPLE 보드\nEntry.ITPLE.getBlocks = function () {\n    return {\n        ITPLE_push_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['위쪽', 'A0'], ['아래쪽', 'A1'], ['왼쪽', '7'], ['오른쪽', '8']],\n                    value: 'A0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, 'A0'], \n                type: 'ITPLE_push_button'\n            },\n            paramsKeyMap: {\n                PORT: 1 \n            },\n            class: 'ITPLEStart',\n            isNotFor: ['ITPLE'], \n            event: 'ITPLE_press_button',\n            func(sprite, script) {\n                const portConfigMap = {\n                    'A0': { type: 'ANALOG', index: 0 },\n                    'A1': { type: 'ANALOG', index: 1 },\n                    '7':  { type: 'DIGITAL', index: 7 },\n                    '8':  { type: 'DIGITAL', index: 8 },\n                };\n\n                const portKey = script.getField('PORT', script);\n                const config = portConfigMap[portKey];\n                \n                if (!config) {\n                    return this.die();\n                }\n                \n                const value = Entry.hw.portData[config.type]?.[config.index] ?? 1;\n\n                // 버튼이 눌렸을 때 (value === 0) 실행\n                if (value === 0) {\n                    return script.callReturn();\n                }\n\n                return this.die();\n            },\n            \n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'def when_push_button(%2):',\n                        passTest: true,\n                        blockType: 'event',\n                        textParams: [\n                            undefined,\n                            {\n                                type: 'Dropdown',\n                                options: [['위쪽', 'A0'], ['아래쪽', 'A1'], ['왼쪽', '7'], ['오른쪽', '8']],\n                                value: 'A0',\n                                arrowColor: EntryStatic.colorSet.arrow.default.START,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        ITPLE_get_button_value: {\n            color: EntryStatic.colorSet.block[\"default\"].HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Dropdown',\n                options: [['위쪽', 'A0'], ['아래쪽', 'A1'], ['왼쪽', '7'], ['오른쪽', '8']],\n                value: 'A0',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                arrowColor: EntryStatic.colorSet.arrow[\"default\"].HARDWARE\n            }],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ITPLE_get_button_value'\n            },\n            paramsKeyMap: {\n                PORT: 0\n            },\n            \"class\": 'ITPLEGet',\n            isNotFor: ['ITPLE'],\n            func: function func(sprite, script) {\n                const portConfigMap = {\n                    'A0': { type: 'ANALOG', index: 0 },\n                    'A1': { type: 'ANALOG', index: 1 },\n                    '7':  { type: 'DIGITAL', index: 7 },\n                    '8':  { type: 'DIGITAL', index: 8 },\n                };\n                const portKey = script.getValue('PORT', script);\n                const config = portConfigMap[portKey];\n                if (!config) return 0;\n                return Entry.hw.portData[config.type]?.[config.index] ?? 0;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Arduino.digitalRead(%1)',\n                    blockType: 'param',\n                    textParams: [{ type: 'Block', accept: 'string' }]\n                }]\n            }\n        },\n        ITPLE_get_sensor_value: {\n            color: EntryStatic.colorSet.block[\"default\"].HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Dropdown',\n                options: [['조도', 'A2'], ['소리', 'A3'], ['왼쪽 라인', 'A6'], ['오른쪽 라인', 'A7']],\n                value: 'A2',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                arrowColor: EntryStatic.colorSet.arrow[\"default\"].HARDWARE\n            }],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ITPLE_get_sensor_value'\n            },\n            paramsKeyMap: {\n                PORT: 0\n            },\n            \"class\": 'ITPLEGet',\n            isNotFor: ['ITPLE'],\n            func: function func(sprite, script) {\n                const portConfigMap = {\n                    'A2': { type: 'ANALOG', index: 2 },\n                    'A3': { type: 'ANALOG', index: 3 },\n                    'A6': { type: 'ANALOG', index: 6 },\n                    'A7': { type: 'ANALOG', index: 7 },\n                };\n                const portKey = script.getValue('PORT', script);\n                const config = portConfigMap[portKey];\n                if (!config) return 0;\n                return Entry.hw.portData[config.type]?.[config.index] ?? 0;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Arduino.analogRead(%1)',\n                    blockType: 'param',\n                    textParams: [{ type: 'Block', accept: 'string' }]\n                }]\n            }\n        },\n        ITPLE_is_key_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [{\n                type: 'Dropdown',\n                options: [\n                    ['위쪽', 'A0'],\n                    ['아래쪽', 'A1'],\n                    ['왼쪽', '7'],\n                    ['오른쪽', '8'],\n                ],\n                value: 'A0',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n            },],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ITPLE_is_key_pressed',\n            },\n            paramsKeyMap: {\n                KEY: 0,\n            },\n            \"class\": 'ITPLEGet',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                // 각 키에 대한 하드웨어 포트 정보를 객체로 관리하여 확장성을 높입니다.\n                const keyToPortMap = {\n                    'A0': { type: 'ANALOG', index: 0 },\n                    'A1': { type: 'ANALOG', index: 1 },\n                    '7':  { type: 'DIGITAL', index: 7 },\n                    '8':  { type: 'DIGITAL', index: 8 },\n              };\n\n              const selectedKey = script.getField('KEY');\n              const portConfig = keyToPortMap[selectedKey];\n\n              // 유효하지 않은 키는 즉시 false를 반환합니다.\n              if (!portConfig) {\n                  return false;\n              }\n              \n              // 옵셔널 체이닝(?.)과 null 병합 연산자(??)를 사용해\n              // 하드웨어 데이터 존재 여부를 확인하고 값을 안전하게 가져옵니다.\n              const value = Entry.hw.portData[portConfig.type]?.[portConfig.index] ?? 1;\n\n              // 버튼이 눌렸을 때의 값(0)과 일치하는지 확인하여 boolean 값을 반환합니다.\n              return value === 0;\n          },\n          syntax: {\n              js: [],\n              py: [\n                  {\n                      syntax: 'Arduino.digitalRead(\"%1\")==0',\n                  },\n              ],\n          },\n        },\n        ITPLE_value_sensor: { // 저학년을 위한 센서 블록 생성\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n\n            skeleton: 'basic_boolean_field',\n\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['조도', '2'],\n                        ['소리', '3'],\n                        ['왼쪽 라인', '6'],\n                        ['오른쪽 라인', '7'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'number',\n                },\n                {\n                  type: 'Dropdown',\n                  options: [\n                    ['크다', '>'],\n                    ['크거나같다', '>='],\n                    ['같다', '=='],\n                    ['작거나같다', '<='],\n                    ['작다', '<'],\n                  ],\n                  value: '>',\n                  fontSize: 11,\n                  bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                  arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n\n            events: {},\n\n            def: {\n                params: [null, {\n                    type: 'number',\n                    params: ['500']\n                }, null],\n                type: 'ITPLE_value_sensor',\n            },\n\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n                COMPARISON: 2,\n            },\n            class: 'ITPLEGet',\n            isNotFor: ['ITPLE'],\n            \n            func(sprite, script) {\n                const pin = script.getValue('PIN');\n                const value = script.getValue('VALUE');\n                const comparison = script.getValue('COMPARISON');\n\n                const analogPortData = Entry.hw.portData.ANALOG;\n\n                if (analogPortData) {\n                    switch (comparison) {\n                        case '>':\n                            return analogPortData[pin] > value;\n                        case '<':\n                            return analogPortData[pin] < value;\n                        case '==':\n                            return analogPortData[pin] === value;\n                    }\n                }\n                return false;\n            },\n\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1) %3 %2',\n                    },\n                ],\n            },\n        },\n        ITPLE_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block[\"default\"].HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Block',\n                accept: 'string',\n                defaultType: 'number'\n            }, {\n                type: 'Block',\n                accept: 'string',\n                defaultType: 'number'\n            }],\n            events: {},\n            def: {\n                params: [{\n                    type: 'arduino_get_port_number',\n                    params: ['13']\n                }, {\n                    type: 'arduino_get_port_number',\n                    params: ['12']\n                }],\n                type: 'ITPLE_get_ultrasonic_value'\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1\n            },\n            \"class\": 'ITPLEGet',\n            isNotFor: ['ITPLE'],\n            func: function func(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.ITPLE.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime()\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                    blockType: 'param',\n                    textParams: [{\n                        type: 'Block',\n                        accept: 'string'\n                    }, {\n                        type: 'Block',\n                        accept: 'string'\n                    }]\n                }],\n            }\n        },\n        ITPLE_color_picker_value: {\n            color: EntryStatic.colorSet.block[\"default\"].HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Color' },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ITPLE_color_picker_value',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                // Color 파라미터는 이미 hex 문자열을 반환\n                return script.getStringValue('COLOR', script);\n            },\n            syntax: {\n                js: [],\n                py: []\n            },\n        },\n        ITPLE_rgb_to_color_value: {\n            color: EntryStatic.colorSet.block[\"default\"].HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Block', accept: 'string', defaultType: 'number' },\n                { type: 'Block', accept: 'string', defaultType: 'number' },\n                { type: 'Block', accept: 'string', defaultType: 'number' },\n            ],\n            events: {},\n            def: {\n                params: [\n                    { type: 'number', params: ['255'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                ],\n                type: 'ITPLE_rgb_to_color_value',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                let r = script.getNumberValue('RED', script);\n                let g = script.getNumberValue('GREEN', script);\n                let b = script.getNumberValue('BLUE', script);\n                // clamp\n                r = Math.min(255, Math.max(0, Math.floor(r)));\n                g = Math.min(255, Math.max(0, Math.floor(g)));\n                b = Math.min(255, Math.max(0, Math.floor(b)));\n                const toHex = (v) => v.toString(16).padStart(2, '0').toUpperCase();\n                return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n            },\n            syntax: {\n                js: [],\n                py: []\n            },\n        },\n        ITPLE_turn_led: { // 저학년 학생을 위한, 핀 번호 없는 LED 켜기 블록\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n\n            skeleton: 'basic',\n\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빨강', 10],\n                        ['파랑', 11],\n                    ],\n                    value: 10,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', 'on'],\n                        ['끄기', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            events: {},\n\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'ITPLE_turn_led',\n            },\n\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ITPLE',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.ITPLE.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.ITPLE.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ITPLE.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        ITPLE_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'ITPLE_tone_list',\n                    },\n                ],\n            },\n        },\n        ITPLE_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'ITPLE_tone_list',\n                    },\n                ],\n                type: 'ITPLE_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'ITPLE_tone_value',\n                    },\n                ],\n            },\n        },\n        ITPLE_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'ITPLE_octave_list',\n                    },\n                ],\n            },\n        },\n        ITPLE_set_tone: {\n            // 버저 핀번호 가림 업데이트\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'ITPLE_tone_list',\n                    },\n                    {\n                        type: 'ITPLE_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'ITPLE_set_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'ITPLE',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 3;\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.ITPLE.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.ITPLE.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.ITPLE.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(3, %1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        ITPLE_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'ITPLE_octave_list',\n                    },\n                ],\n            },\n        },\n        ITPLE_set_motor_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '2'],\n                        ['오른쪽', '4'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞쪽', '0'],\n                        ['뒤쪽', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['2', '0', null],\n                type: 'ITPLE_set_motor_direction',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ITPLE_motor',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.ITPLE.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.ITPLE.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ITPLE.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        ITPLE_set_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '5'],\n                        ['오른쪽', '6'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '5',\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'ITPLE_set_motor_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ITPLE_motor',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ITPLE.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        ITPLE_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '9',\n                    {\n                        type: 'text',\n                        params: ['180'],\n                    },\n                    null,\n                ],\n                type: 'ITPLE_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ITPLE_motor',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.ITPLE.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Arduino.servomotorWrite(%1, %2)',\n                    textParams: [{\n                        type: 'Block',\n                        accept: 'string',\n                    },{\n                        type: 'Block',\n                        accept: 'string',\n                    },],\n                },],\n            },\n        },\n        ITPLE_set_neopixel_init: {\n            color: EntryStatic.colorSet.block[\"default\"].HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [{\n                type: 'Indicator',\n                img: 'block_icon/hardware_icon.svg',\n                size: 12\n            }],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ITPLE_set_neopixel_init'\n            },\n            \"class\": 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 200;\n    \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n    \n                    // 시퀀스 번호로 고유한 시간 보장\n                    Entry.ITPLE.timeSeq++;\n                    const uniqueTime = new Date().getTime() + Entry.ITPLE.timeSeq;\n    \n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.NEOPIXEL_INIT,\n                        data: uniqueTime % 10000,\n                        time: uniqueTime,\n                    };\n    \n                    script.isStart = true;\n                    script.timeFlag = Date.now();\n                    return script;\n                }\n    \n                // 10ms 대기\n                if (Date.now() - script.timeFlag < 2) {\n                    return script;\n                }\n    \n                delete script.isStart;\n                delete script.timeFlag;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Arduino.neopixelInit(9, 4)'\n                }]\n            }\n        },\n        ITPLE_set_neopixel: {\n            color: EntryStatic.colorSet.block[\"default\"].HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [{\n                type: 'Dropdown',\n                options: [['1', '0'], ['2', '1'], ['3', '2'], ['4', '3']],\n                value: '0',\n                fontSize: 11,\n                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                arrowColor: EntryStatic.colorSet.arrow[\"default\"].HARDWARE\n            }, {\n                type: 'Block',\n                accept: 'string',\n                defaultType: 'text'\n            }, {\n                type: 'Indicator',\n                img: 'block_icon/hardware_icon.svg',\n                size: 12\n            }],\n            events: {},\n            def: {\n                params: [null, {\n                    type: 'ITPLE_color_picker_value', params: ['#FF0000']\n                }, null],\n                type: 'ITPLE_set_neopixel'\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                COLOR: 1,\n            },\n            \"class\": 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const num = script.getNumberValue('NUM', script);\n                const port = 100 + num;\n                const color = script.getStringValue('COLOR', script);\n    \n                const rgb = Entry.hex2rgb(color);\n                let r = rgb.r || 0;\n                let g = rgb.g || 0;\n                let b = rgb.b || 0;\n    \n                r = Math.min(255, Math.max(0, r));\n                g = Math.min(255, Math.max(0, g));\n                b = Math.min(255, Math.max(0, b));\n    \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n    \n                    // 시퀀스 번호로 고유한 시간 보장\n                    Entry.ITPLE.timeSeq++;\n                    const uniqueTime = new Date().getTime() + Entry.ITPLE.timeSeq;\n    \n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.NEOPIXEL_COLOR,\n                        data: { num, r, g, b },\n                        time: uniqueTime,\n                    };\n    \n                    script.isStart = true;\n                    script.timeFlag = Date.now();\n                    return script;\n                }\n    \n                // 10ms 대기\n                if (Date.now() - script.timeFlag < 2) {\n                    return script;\n                }\n    \n                delete script.isStart;\n                delete script.timeFlag;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Arduino.neopixelColor(9, %1, %2)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                }]\n            }\n        },\n        ITPLE_set_neopixel_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                { type: 'Block', accept: 'string', defaultType: 'text' },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    { type: 'ITPLE_color_picker_value', params: ['#00FF00'] },\n                    null,\n                ],\n                type: 'ITPLE_set_neopixel_all',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 202; // 전체 설정용 가상 포트\n                const color = script.getStringValue('COLOR', script);\n    \n                const rgb = Entry.hex2rgb(color);\n                let r = rgb.r || 0;\n                let g = rgb.g || 0;\n                let b = rgb.b || 0;\n    \n                r = Math.min(255, Math.max(0, r));\n                g = Math.min(255, Math.max(0, g));\n                b = Math.min(255, Math.max(0, b));\n    \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n    \n                    // 시퀀스 번호로 고유한 시간 보장\n                    Entry.ITPLE.timeSeq++;\n                    const uniqueTime = new Date().getTime() + Entry.ITPLE.timeSeq;\n    \n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.NEOPIXEL_COLOR,\n                        data: { num: 255, r, g, b }, // num: 255는 전체를 의미\n                        time: uniqueTime,\n                    };\n    \n                    script.isStart = true;\n                    script.timeFlag = Date.now();\n                    return script;\n                }\n    \n                // 10ms 대기\n                if (Date.now() - script.timeFlag < 2) {\n                    return script;\n                }\n    \n                delete script.isStart;\n                delete script.timeFlag;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixelColorAll(9, %1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ]\n            },\n        },\n        ITPLE_set_neopixel_range: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string', defaultType: 'text' },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    { type: 'ITPLE_color_picker_value', params: ['#0000FF'] },\n                    null,\n                ],\n                type: 'ITPLE_set_neopixel_range',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                COLOR: 2,\n            },\n            class: 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 203; // 범위 설정용 가상 포트\n                let start = script.getNumberValue('START', script);\n                let end = script.getNumberValue('END', script);\n                const color = script.getStringValue('COLOR', script);\n    \n                const rgb = Entry.hex2rgb(color);\n                let r = rgb.r || 0;\n                let g = rgb.g || 0;\n                let b = rgb.b || 0;\n    \n                // 범위 자동 조절 (0~3)\n                start = Math.min(3, Math.max(0, start));\n                end = Math.min(3, Math.max(0, end));\n    \n                // start > end인 경우 swap\n                if (start > end) {\n                    const temp = start;\n                    start = end;\n                    end = temp;\n                }\n    \n                // RGB 값 조절\n                r = Math.min(255, Math.max(0, r));\n                g = Math.min(255, Math.max(0, g));\n                b = Math.min(255, Math.max(0, b));\n    \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n    \n                    // 시퀀스 번호로 고유한 시간 보장\n                    Entry.ITPLE.timeSeq++;\n                    const uniqueTime = new Date().getTime() + Entry.ITPLE.timeSeq;\n    \n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.NEOPIXEL_COLOR,\n                        data: { num: 254, start, end, r, g, b }, // num: 254는 범위를 의미\n                        time: uniqueTime,\n                    };\n    \n                    script.isStart = true;\n                    script.timeFlag = Date.now();\n                    return script;\n                }\n    \n                // 10ms 대기\n                if (Date.now() - script.timeFlag < 2) {\n                    return script;\n                }\n    \n                delete script.isStart;\n                delete script.timeFlag;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixelColorRange(9, %1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ]\n            },\n        },\n        ITPLE_set_neopixel_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '-1'],\n                        ['오른쪽', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'ITPLE_set_neopixel_rotate',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                STEPS: 1,\n            },\n            class: 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 205; // 회전용 가상 포트\n                let direction = script.getNumberValue('DIRECTION', script);\n                let steps = script.getNumberValue('STEPS', script);\n    \n                // steps 범위 조절 (0~4)\n                steps = Math.min(4, Math.max(0, Math.floor(steps)));\n    \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n    \n                    // 시퀀스 번호로 고유한 시간 보장\n                    Entry.ITPLE.timeSeq++;\n                    const uniqueTime = new Date().getTime() + Entry.ITPLE.timeSeq;\n    \n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.NEOPIXEL_ROTATE,\n                        data: { direction, steps },\n                        time: uniqueTime,\n                    };\n    \n                    script.isStart = true;\n                    script.timeFlag = Date.now();\n                    return script;\n                }\n    \n                // 10ms 대기\n                if (Date.now() - script.timeFlag < 10) {\n                    return script;\n                }\n    \n                delete script.isStart;\n                delete script.timeFlag;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixelRotate(9, %1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ]\n            },\n        },\n        ITPLE_set_neopixel_brightness: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'ITPLE_set_neopixel_brightness',\n            },\n            paramsKeyMap: {\n                BRIGHTNESS: 0,\n            },\n            class: 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 201;\n                let brightness = script.getNumberValue('BRIGHTNESS', script);\n    \n                brightness = Math.min(255, Math.max(0, brightness));\n    \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n    \n                    // 시퀀스 번호로 고유한 시간 보장\n                    Entry.ITPLE.timeSeq++;\n                    const uniqueTime = new Date().getTime() + Entry.ITPLE.timeSeq;\n    \n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.NEOPIXEL_BRIGHTNESS,\n                        data: brightness,\n                        time: uniqueTime,\n                    };\n    \n                    script.isStart = true;\n                    script.timeFlag = Date.now();\n                    return script;\n                }\n    \n                // 10ms 대기\n                if (Date.now() - script.timeFlag < 2) {\n                    return script;\n                }\n    \n                delete script.isStart;\n                delete script.timeFlag;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixelBrightness(9, %1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ]\n            },\n        },\n        ITPLE_set_neopixel_blink: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '0'],\n                        ['오른쪽', '1'],\n                        ['전체', '2'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string', defaultType: 'text' },\n                { type: 'Block', accept: 'string', defaultType: 'number' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    { type: 'ITPLE_color_picker_value', params: ['#FFFFFF'] },\n                    { type: 'number', params: ['0.5'] },\n                    null,\n                ],\n                type: 'ITPLE_set_neopixel_blink',\n            },\n            paramsKeyMap: {\n                SIDE: 0,\n                COLOR: 1,\n                INTERVAL: 2,\n            },\n            class: 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 206; // BLINK 가상 포트\n    \n                const side = script.getNumberValue('SIDE', script); // 2: 전체, 0: 왼쪽, 1: 오른쪽\n                const count = 0; // 무한 깜박임\n                const color = script.getStringValue('COLOR', script);\n                let intervalSec = script.getNumberValue('INTERVAL', script);\n    \n                const rgb = Entry.hex2rgb(color);\n                let r = rgb.r || 0;\n                let g = rgb.g || 0;\n                let b = rgb.b || 0;\n    \n                r = Math.min(255, Math.max(0, r));\n                g = Math.min(255, Math.max(0, g));\n                b = Math.min(255, Math.max(0, b));\n                const interval = Math.max(0.1, intervalSec) * 1000; // ms\n    \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n    \n                    // 시퀀스 번호로 고유한 시간 보장 (다른 네오픽셀 동작과 통일)\n                    Entry.ITPLE.timeSeq++;\n                    const uniqueTime = new Date().getTime() + Entry.ITPLE.timeSeq;\n    \n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.NEOPIXEL_BLINK,\n                        data: { side, count, r, g, b, interval },\n                        time: uniqueTime,\n                    };\n    \n                    script.isStart = true;\n                    script.timeFlag = Date.now();\n                    return script;\n                }\n    \n                if (Date.now() - script.timeFlag < 2) {\n                    return script;\n                }\n    \n                delete script.isStart;\n                delete script.timeFlag;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixelBlink(%1, %2, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            { type: 'Block', accept: 'string' },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ]\n            },\n        },\n        ITPLE_stop_neopixel_blink: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '0'],\n                        ['오른쪽', '1'],\n                        ['전체', '2'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'ITPLE_stop_neopixel_blink',\n            },\n            paramsKeyMap: {\n                SIDE: 0,\n            },\n            class: 'ITPLE_neopixel',\n            isNotFor: ['ITPLE'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 206; // BLINK/STOP 통합 가상 포트\n    \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n    \n                    const side = script.getNumberValue('SIDE', script);\n    \n                    // 시퀀스 번호로 고유한 시간 보장\n                    Entry.ITPLE.timeSeq++;\n                    const uniqueTime = new Date().getTime() + Entry.ITPLE.timeSeq;\n    \n                    sq.SET[port] = {\n                        type: Entry.ITPLE.sensorTypes.NEOPIXEL_BLINK_STOP,\n                        data: { side },\n                        time: uniqueTime,\n                    };\n    \n                    script.isStart = true;\n                    script.timeFlag = Date.now();\n                    return script;\n                }\n    \n                if (Date.now() - script.timeFlag < 2) {\n                    return script;\n                }\n    \n                delete script.isStart;\n                delete script.timeFlag;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    { syntax: 'Arduino.neopixelBlinkStop(9, %1)' },\n                ]\n            },\n        },\n    };\n};\n//endregion ITPLE 아두이노 확장모드\n\nmodule.exports = Entry.ITPLE;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_KKMOO.js",
    "content": "'use strict';\n\nEntry.kkmoo = {\n    id: '53.1',\n    name: 'kkmoo',\n    url: '',\n    imageName: 'kkmoo.png',\n    title: {\n        ko: 'kkmoo',\n        en: 'kkmoo',\n    },\n    isReceive: 0,\n    motData: [\n        { num: 0, angle: 0 },\n        { num: 1, angle: 0 },\n        { num: 2, angle: 0 },\n        { num: 3, angle: 0 },\n        { num: 4, angle: 0 },\n        { num: 5, angle: 0 },\n        { num: 6, angle: 0 },\n        { num: 7, angle: 0 },\n        { num: 8, angle: 0 },\n        { num: 9, angle: 0 },\n        { num: 10, angle: 0 },\n        { num: 11, angle: 0 },\n        { num: 12, angle: 0 },\n        { num: 13, angle: 0 },\n        { num: 14, angle: 0 },\n        { num: 15, angle: 0 },\n        { num: 16, angle: 0 },\n        { num: 17, angle: 0 },\n    ],\n    runningStart: false,\n    isMotionRunning: false,\n    motionFrame: [\n        { frame: 0, data: null, time: 0 },\n        { frame: 1, data: null, time: 0 },\n        { frame: 2, data: null, time: 0 },\n        { frame: 3, data: null, time: 0 },\n        { frame: 4, data: null, time: 0 },\n        { frame: 5, data: null, time: 0 },\n        { frame: 6, data: null, time: 0 },\n        { frame: 7, data: null, time: 0 },\n        { frame: 8, data: null, time: 0 },\n        { frame: 9, data: null, time: 0 },\n        { frame: 10, data: null, time: 0 },\n        { frame: 11, data: null, time: 0 },\n        { frame: 12, data: null, time: 0 },\n        { frame: 13, data: null, time: 0 },\n        { frame: 14, data: null, time: 0 },\n        { frame: 15, data: null, time: 0 },\n        { frame: 16, data: null, time: 0 },\n        { frame: 17, data: null, time: 0 },\n        { frame: 18, data: null, time: 0 },\n        { frame: 19, data: null, time: 0 },\n    ],\n    playcnt: 0,\n    checkTimeout: 0,\n    timeoutCnt: 0,\n    setTimeout: function (time) {\n        this.timeoutCnt = time;\n        this.checkTimeout = new Date();\n    },\n    timeOut: function () {\n        if (new Date() - this.checkTimeout > this.timeoutCnt) {\n            return true;\n        } else {\n            return false;\n        }\n    },\n    setZero: function () {\n        for (var i of this.motData) {\n            i.angle = 0;\n        }\n        for (var i of this.motionFrame) {\n            i.data = null;\n            i.time = 0;\n        }\n        Entry.hw.sendQueue.msg = { prot: 'RT', data: null };\n        this.playcnt = 0;\n        this.checkTimeout = 0;\n        this.timeoutCnt = 0;\n    },\n    copyObj: function (obj) {\n        const result = {};\n        for (let key in obj) {\n            if (typeof obj[key] === 'object') {\n                result[key] = this.copyObj(obj[key]);\n            } else {\n                result[key] = obj[key];\n            }\n        }\n        return result;\n    },\n};\nEntry.kkmoo.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                kkmoo_rotate_motor: '%1번 모터의 각도를 %2도로 회전 %3',\n                //kkmoo_isPlaying: '동작이 실행중인가?',\n                kkmoo_motion_play_basic: '기본 %1번 동작 실행 %2',\n                kkmoo_motion_play_custom: '커스텀 %1번 동작 실행 %2',\n                kkmoo_rotate_motor_time: '%1번 모터의 각도를 %2도로 %3밀리초 동안 회전 %4',\n                kkmoo_set_motor_degree: '%1번 모터의 각도를 %2도로 설정 %3',\n                kkmoo_run_set_value_time: '설정값 %1밀리초 동안 실행%2',\n                kkmoo_set_frame: '설정값을 임시동작 %1 번 프레임으로 지정 %2',\n                kkmoo_set_frame_time: '임시동작의 %1 번 프레임의 시간을 %2 밀리초로 설정 %3',\n                kkmoo_play_temp_motion: '임시동작 실행 %1',\n                kkmoo_save_to_robot: '임시동작을 까무 커스텀동작 %1 번에 %2 으로 저장 %3',\n            },\n            Menus: {\n                kkmoo: '까무',\n            },\n        },\n        en: {\n            template: {\n                kkmoo_rotate_motor: 'Rotate motor %1 to %2 degrees %3',\n                //kkmoo_isPlaying: 'Is motion running?',\n                kkmoo_motion_play_basic: 'Play basic motion number %1 %2',\n                kkmoo_motion_play_custom: 'Play custom motion number %1 %2',\n                kkmoo_rotate_motor_time: 'Rotate motor %1 to %2 degrees for%3 milliseconds %4',\n                kkmoo_set_motor_degree: 'Set motor %1 to %2 degrees %3',\n                kkmoo_run_set_value_time: 'Run setting value for %1 milliseconds %2',\n                kkmoo_set_frame: 'Set the setting value as frame number %1 for temporary-motion %2',\n                kkmoo_set_frame_time:\n                    'Set the time of frame number %1 of temporary-motion to %2 milliseconds %3',\n                kkmoo_play_temp_motion: 'Run temporary-Motion %1',\n                kkmoo_save_to_robot:\n                    'Save the temporary-motion to Kamu-Custom-Motion number %1, name as %2 %3',\n            },\n            Menus: {\n                kkmoo: 'kkmoo',\n            },\n        },\n    };\n};\n\nEntry.kkmoo.blockMenuBlocks = [\n    'kkmoo_rotate_motor',\n    //'kkmoo_isPlaying',\n    'kkmoo_motion_play_basic',\n    'kkmoo_motion_play_custom',\n    'kkmoo_rotate_motor_time',\n    'kkmoo_set_motor_degree',\n    'kkmoo_run_set_value_time',\n    'kkmoo_set_frame',\n    'kkmoo_set_frame_time',\n    'kkmoo_play_temp_motion',\n    'kkmoo_save_to_robot',\n];\n\nEntry.kkmoo.getBlocks = function () {\n    return {\n        // 까무_모터 개별회전\n        kkmoo_rotate_motor: {\n            template: Lang.template.kkmoo_rotate_motor,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['17', '17'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                MOTNUM: 0,\n                ANGLE: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    '0', //dropdown의 경우 VALUE값이 초기값\n                    {\n                        type: 'number', //최대최소값설정?\n                        params: ['0'],\n                    },\n                ],\n                type: 'kkmoo_rotate_motor',\n            },\n            class: 'Basic',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const prot = 'EC';\n                const motnum = script.getField('MOTNUM', script);\n                const angle = script.getValue('ANGLE', script);\n                var msg = null;\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    if (Entry.hw.portData.data == 'true') {\n                        return script;\n                    } else {\n                        script.isStart = true;\n                        if (angle >= -90 && angle <= 90) {\n                            msg = { MOT: motnum, ANG: angle };\n                        }\n                        Entry.hw.sendQueue.msg = { prot: prot, data: msg };\n                        Entry.kkmoo.setTimeout(600);\n                        return script;\n                    }\n                } else {\n                    if (Entry.hw.portData.data == 'true' || Entry.kkmoo.timeOut()) {\n                        delete script.isStart;\n                        delete Entry.hw.sendQueue.msg;\n                        return script.callReturn();\n                    } else {\n                        return script;\n                    }\n                }\n\n                //return null;\n                //return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.rotateMotor(%1,%2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                    ['16', '16'],\n                                    ['17', '17'],\n                                ],\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        kkmoo_motion_play_basic: {\n            template: Lang.template.kkmoo_motion_play_basic,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                MOTIONNUM: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n\n                type: 'kkmoo_motion_play_basic',\n            },\n            class: 'Basic',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const prot = 'PM';\n                const motionnum = script.getValue('MOTIONNUM', script);\n                var msg = motionnum;\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    if (Entry.hw.portData.data == 'true') {\n                        return script;\n                    } else {\n                        script.isStart = true;\n                        Entry.hw.sendQueue.msg = { prot: prot, data: msg };\n                        Entry.kkmoo.setTimeout(600);\n                        return script;\n                    }\n                } else {\n                    if (Entry.hw.portData.data == 'true' || Entry.kkmoo.timeOut()) {\n                        delete script.isStart;\n                        delete Entry.hw.sendQueue.msg;\n                        return script.callReturn();\n                    } else {\n                        console.log('!!');\n                        return script;\n                    }\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.playBasicMotion(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        kkmoo_motion_play_custom: {\n            template: Lang.template.kkmoo_motion_play_custom,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                MOTIONNUM: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n\n                type: 'kkmoo_motion_play_custom',\n            },\n            class: 'Basic',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const prot = 'CM';\n                const motionnum = script.getValue('MOTIONNUM', script);\n                var msg = motionnum;\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    if (Entry.hw.portData.data == 'true') {\n                        return script;\n                    } else {\n                        script.isStart = true;\n                        Entry.hw.sendQueue.msg = { prot: prot, data: msg };\n                        Entry.kkmoo.setTimeout(600);\n                        return script;\n                    }\n                } else {\n                    if (Entry.hw.portData.data == 'true' || Entry.kkmoo.timeOut()) {\n                        delete script.isStart;\n                        delete Entry.hw.sendQueue.msg;\n                        return script.callReturn();\n                    } else {\n                        return script;\n                    }\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.playCustomMotion(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        kkmoo_rotate_motor_time: {\n            template: Lang.template.kkmoo_rotate_motor_time,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['17', '17'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                MOTNUM: 0,\n                ANGLE: 1,\n                TIME: 2,\n            },\n            events: {},\n            def: {\n                params: [\n                    '0', //dropdown의 경우 VALUE값이 초기값\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'kkmoo_rotate_motor_time',\n            },\n            class: 'Basic',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const prot = 'AD';\n                const motnum = script.getField('MOTNUM', script);\n                const angle = script.getValue('ANGLE', script);\n                const time = script.getValue('TIME', script);\n                var msg = null;\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    if (Entry.hw.portData.data == 'true') {\n                        return script;\n                    } else {\n                        script.isStart = true;\n                        if (angle >= -90 && angle <= 90) {\n                            msg = { MOT: motnum, ANG: angle, TME: time };\n                        }\n                        Entry.hw.sendQueue.msg = { prot: prot, data: msg };\n                        Entry.kkmoo.setTimeout(600);\n                        return script;\n                    }\n                } else {\n                    if (\n                        Entry.hw.portData.data == 'true' ||\n                        script.getValue('TIME', script) == 0 ||\n                        Entry.kkmoo.timeOut()\n                    ) {\n                        delete script.isStart;\n                        delete Entry.hw.sendQueue.msg;\n                        return script.callReturn();\n                    } else {\n                        return script;\n                    }\n                }\n                //return null;\n                //return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.rotateMotorforSeconds(%1,%2,%3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                    ['16', '16'],\n                                    ['17', '17'],\n                                ],\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //===================================================================동작 만들기=============================================\n        kkmoo_set_motor_degree: {\n            template: Lang.template.kkmoo_set_motor_degree,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['17', '17'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                MOTNUM: 0,\n                ANGLE: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    '0', //dropdown의 경우 VALUE값이 초기값\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'kkmoo_set_motor_degree',\n            },\n            class: 'Make_Motion',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const motnum = script.getField('MOTNUM', script);\n                const angle = script.getValue('ANGLE', script);\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    script.isStart = true;\n                    if (angle >= -90 && angle <= 90) {\n                        Entry.kkmoo.motData[motnum].angle = angle;\n                    } else if (angle > 90) {\n                        Entry.kkmoo.motData[motnum].angle = 90;\n                    } else {\n                        Entry.kkmoo.motData[motnum].angle = -90;\n                    }\n                    return script;\n                } else {\n                    delete script.isStart;\n                    console.log(Entry.kkmoo.motData);\n                    return script.callReturn();\n                }\n\n                //return null;\n                //return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.setBuffer(%1,%2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                    ['16', '16'],\n                                    ['17', '17'],\n                                ],\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        kkmoo_run_set_value_time: {\n            template: Lang.template.kkmoo_run_set_value_time,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                TIME: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'kkmoo_run_set_value_time',\n            },\n            class: 'Make_Motion',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const prot = 'MP';\n                var msg = [];\n                Entry.hw.update();\n                console.log(Entry.hw.portData.data);\n                if (script.isStart != true) {\n                    if (Entry.hw.portData.data == 'true') {\n                        return script;\n                    } else {\n                        script.isStart = true;\n                        for (var i of Entry.kkmoo.motData) {\n                            var angle = i.angle;\n                            var motnum = i.num;\n                            msg.push({ MOT: motnum, ANG: angle });\n                        }\n                        msg.push(script.getValue('TIME', script));\n                        Entry.hw.sendQueue.msg = { prot: prot, data: msg };\n                        Entry.kkmoo.setTimeout(600);\n                        return script;\n                    }\n                } else {\n                    if (\n                        Entry.hw.portData.data == 'true' ||\n                        script.getValue('TIME', script) == 0 ||\n                        Entry.kkmoo.timeOut()\n                    ) {\n                        delete script.isStart;\n                        delete Entry.hw.sendQueue.msg;\n                        return script.callReturn();\n                    } else {\n                        return script;\n                    }\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.runBufferforSeconds(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        kkmoo_set_frame: {\n            template: Lang.template.kkmoo_set_frame,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['17', '17'],\n                        ['18', '18'],\n                        ['19', '19'],\n                        ['20', '20'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                FRAME: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    '0', //dropdown의 경우 VALUE값이 초기값\n                ],\n                type: 'kkmoo_set_frame',\n            },\n            class: 'Save_Motion',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const motnum = script.getField('FRAME', script);\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    script.isStart = true;\n                    var data = Entry.kkmoo.copyObj(Entry.kkmoo.motData);\n                    Entry.kkmoo.motionFrame[motnum].data = data;\n                    return script;\n                } else {\n                    delete script.isStart;\n                    console.log(Entry.kkmoo.motionFrame);\n                    return script.callReturn();\n                }\n\n                //return null;\n                //return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.setBuffertoFrame(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                    ['16', '16'],\n                                    ['17', '17'],\n                                ],\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        kkmoo_set_frame_time: {\n            template: Lang.template.kkmoo_set_frame_time,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['17', '17'],\n                        ['18', '18'],\n                        ['19', '19'],\n                        ['20', '20'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                FRAME: 0,\n                TIME: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    '0', //dropdown의 경우 VALUE값이 초기값\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'kkmoo_set_frame_time',\n            },\n            class: 'Save_Motion',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const motnum = script.getField('FRAME', script);\n                const time = script.getValue('TIME', script);\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    script.isStart = true;\n                    Entry.kkmoo.motionFrame[motnum].time = time;\n                    return script;\n                } else {\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n\n                //return null;\n                //return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.setFrameTime(%1,%2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                    ['16', '16'],\n                                    ['17', '17'],\n                                ],\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        kkmoo_play_temp_motion: {\n            template: Lang.template.kkmoo_play_temp_motion,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {},\n            events: {},\n            def: {\n                params: [],\n                type: 'kkmoo_play_temp_motion',\n            },\n            class: 'Save_Motion',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const prot = 'PT';\n                var msg = [];\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    if (Entry.hw.portData.data == 'true') {\n                        return script;\n                    } else {\n                        script.isStart = true;\n\n                        for (var dat of Entry.kkmoo.motionFrame) {\n                            //frame,data,time\n                            if (dat.data != null && dat.time != 0) {\n                                Entry.kkmoo.playcnt++;\n                                msg.push(dat);\n                            }\n                        }\n                        Entry.hw.sendQueue.msg = { prot: prot, data: msg };\n                        Entry.kkmoo.setTimeout(600);\n                        return script;\n                    }\n                } else {\n                    if (\n                        Entry.hw.portData.data == 'true' ||\n                        Entry.kkmoo.playcnt == 0 ||\n                        Entry.kkmoo.timeOut()\n                    ) {\n                        delete script.isStart;\n                        delete Entry.hw.sendQueue.msg;\n                        Entry.kkmoo.playcnt = 0;\n                        return script.callReturn();\n                    } else {\n                        return script;\n                    }\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.runTempMotion()',\n                        blockType: 'param',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        kkmoo_save_to_robot: {\n            template: Lang.template.kkmoo_save_to_robot,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_without_next',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                SLOT: 0,\n                NAME: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['이름'],\n                    },\n                ],\n                type: 'kkmoo_save_to_robot',\n            },\n            class: 'Save_Motion',\n            isNotFor: ['kkmoo'],\n            func: function (sprite, script) {\n                const prot = 'SV';\n                var msg = [];\n                var my_json = { name: '', frame_length: '', frames: [] };\n                Entry.hw.update();\n                if (script.isStart != true) {\n                    if (Entry.hw.portData.data == 'true') {\n                        return script;\n                    } else {\n                        script.isStart = true;\n\n                        for (var dat of Entry.kkmoo.motionFrame) {\n                            //frame,data,time\n                            if (dat.data != null && dat.time != 0) {\n                                msg.push(dat);\n                                var frame = { index: '', transition_time: '', outputs: [] };\n                                frame.index = Entry.kkmoo.playcnt;\n                                frame.transition_time = parseInt(dat.time);\n                                Entry.kkmoo.playcnt++;\n                                var my_data = [\n                                    { device: 'left_shoulder_pitch', value: '' },\n                                    { device: 'left_thigh_yaw', value: '' },\n                                    { device: 'left_shoulder_roll', value: '' },\n                                    { device: 'left_elbow_roll', value: '' },\n                                    { device: 'left_thigh_roll', value: '' },\n                                    { device: 'left_thigh_pitch', value: '' },\n                                    { device: 'left_knee_pitch', value: '' },\n                                    { device: 'left_foot_pitch', value: '' },\n                                    { device: 'left_foot_roll', value: '' },\n                                    { device: 'right_shoulder_pitch', value: '' },\n                                    { device: 'right_thigh_yaw', value: '' },\n                                    { device: 'right_shoulder_roll', value: '' },\n                                    { device: 'right_elbow_roll', value: '' },\n                                    { device: 'right_thigh_roll', value: '' },\n                                    { device: 'right_thigh_pitch', value: '' },\n                                    { device: 'right_knee_pitch', value: '' },\n                                    { device: 'right_foot_pitch', value: '' },\n                                    { device: 'right_foot_roll', value: '' },\n                                ];\n                                for (var i in dat.data) {\n                                    my_data[i].value = parseInt(dat.data[i].angle);\n                                }\n                                frame.outputs = my_data;\n                                my_json.frames.push(frame);\n                            }\n                        }\n                        var slot = script.getValue('SLOT', script);\n                        var name = script.getValue('NAME', script);\n                        var namelength = 0;\n                        var result = '';\n                        for (var i of name) {\n                            var buf = Buffer.from(i, 'utf-8').toString('hex');\n                            var length = buf.length;\n                            if (namelength + length > 40) {\n                                break;\n                            } else {\n                                namelength += length;\n                                result += buf;\n                            }\n                        }\n                        result = result.padEnd(40, '20');\n                        var numBytes = result.length / 2;\n                        var byteArray = new Uint8Array(numBytes);\n                        for (var i = 0; i < numBytes; i++) {\n                            byteArray[i] = parseInt(result.substr(i * 2, 2), 16);\n                        }\n                        const decoder = new TextDecoder('utf-8');\n                        var name_string = decoder.decode(byteArray);\n                        my_json.name = name_string;\n                        my_json.frame_length = msg.length;\n                        const CryptoJS = require('crypto-js');\n                        var hash = CryptoJS.SHA256(JSON.stringify(my_json))\n                            .toString()\n                            .substring(0, 10);\n                        Entry.hw.sendQueue.msg = {\n                            prot: prot,\n                            data: msg,\n                            slot: slot,\n                            name: name_string,\n                            hash: hash,\n                        };\n                        Entry.kkmoo.setTimeout(600);\n                        return script;\n                    }\n                } else {\n                    if (\n                        Entry.hw.portData.data == 'true' ||\n                        Entry.kkmoo.playcnt == 0 ||\n                        Entry.kkmoo.timeOut()\n                    ) {\n                        delete script.isStart;\n                        delete Entry.hw.sendQueue.msg;\n                        Entry.kkmoo.playcnt = 0;\n                        return script.callReturn();\n                    } else {\n                        return script;\n                    }\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kkmoo.SaveMotion(%1,%2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.kkmoo;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_KRC.js",
    "content": "'use strict';\r\n\r\nconst DelayTime = 0;\r\nlet LmotorSpeed = 0;\r\nlet RmotorSpeed = 0;\r\n\r\nEntry.krc = {\r\n    id: '3A.2',\r\n    name: 'KRC',\r\n    url: 'http://www.kairobot.co.kr/',\r\n    imageName: 'KRC.png',\r\n    title: {\r\n        ko: 'KRC_S',\r\n        en: 'KRC_S',\r\n    },\r\n\r\n    setZero: () => {\r\n        //  하드웨어 초기화 로직\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[parseInt(key, 10)].data = 0;\r\n                Entry.hw.sendQueue.SET[parseInt(key, 10)].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n        LmotorSpeed = 0;\r\n        RmotorSpeed = 0;\r\n    },\r\n    Static: {\r\n        //        krc_BLOCK_COLOR: '#00979D', // gray(#848484)\r\n        //        krc_ARROW_COLOR_HW: '#00979D',\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        BUZZER: 3,\r\n        SERVO: 4,\r\n        TONE: 5,\r\n        USONIC: 7,\r\n        MOTOR: 12,\r\n        USONIC_SET: 33,\r\n        LCD_SET: 40,\r\n    },\r\n    BlockState: {},\r\n};\r\n\r\nEntry.krc.blockMenuBlocks = [\r\n    /// 하드웨어 블록 등록 , 여기에 등록된 블록이 순서대로 나열되며 설정한 이름으로 화면에 보임\r\n    'KrcBuzzerOnOff',\r\n    // 스피커 삐 소리\r\n    'KrcSetMotorSpeed',\r\n    // DC모터 속도제어\r\n    'KrcMotorStop',\r\n    // DC모터 정지하기\r\n    'KrcSetServo',\r\n    // 서보모터 제어\r\n    'KrcDigitalOnOff',\r\n    /// 디지털 포트 제어\r\n    'KrcGetDgitalValue',\r\n    //디지탈 입력\r\n    'KrcGetAnalogValue',\r\n    // 아날로그 입력\r\n    'KrcGetUsonicValue',\r\n    //초음파센서 읽기\r\n    'KrcSetLcdString',\r\n    'KrcSetLcdBacklight',\r\n    'KrcSetLcdClear',\r\n    'KrcGetAnalogMapping',\r\n];\r\n\r\nEntry.krc.setLanguage = function() {\r\n    // 블록 이름  번역\r\n    return {\r\n        ko: {\r\n            template: {\r\n                KrcBuzzerOnOff: '스피커 삐 소리 %1 초 연주하기 %2',\r\n                KrcSetMotorSpeed: 'DC모터 왼쪽 속도%1 오른쪽 속도%2 으로 정하기 %3',\r\n                KrcMotorStop: 'DC모터 정지하기 %1',\r\n                KrcSetServo: '서보모터 %1포트,  각도%2도,  속도%3%로 이동 %4',\r\n\r\n                KrcDigitalOnOff: '디지털 %1 포트 %2 설정하기 %3',\r\n                KrcGetDgitalValue: '디지털 %1 포트 읽기',\r\n                KrcGetAnalogValue: '아날로그 %1 포트 읽기',\r\n                KrcGetUsonicValue: '아날로그형 (US-016)초음파센서 %1포트 읽기',\r\n\r\n                KrcSetLcdString: 'lcd 세로%1줄,  가로%2줄 에  %3 표시하기 %4',\r\n                KrcSetLcdBacklight: 'lcd 후광(백라이트) %1 하기 %2',\r\n                KrcSetLcdClear: 'lcd 지우기 %1',\r\n\r\n                KrcGetAnalogMapping: ' %1 값 %2 ~ %3 에서 %4 ~ %5 으로 변환값',\r\n            },\r\n            Blocks: {\r\n                OnBlock: '켜짐(HIGH, 5V)',\r\n                OffBlock: '꺼짐(LOW, 0V)',\r\n                AllOnBlock: '모두 켜짐',\r\n                AllOffBlock: '모두 꺼짐',\r\n                BacklightOn: '켜기',\r\n                BacklightOff: '끄기',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                KrcBuzzerOnOff: 'Speakers Beep %1 Playing Second %2',\r\n                KrcSetMotorSpeed: 'Set DC motor left speed %1  right speed %2 %3',\r\n                KrcMotorStop: 'Stop DC Motor %1',\r\n                KrcSetServo: 'Servo motor %1 port angle %2 movement %3',\r\n\r\n                KrcDigitalOnOff: 'Setting up digital %1 port %2 %3',\r\n                KrcGetDgitalValue: 'Read digital %1 port',\r\n                KrcGetAnalogValue: 'Analog %1 port read',\r\n                KrcGetUsonicValue: 'Analog type (US-016)High sound sensor %1 port read',\r\n\r\n                KrcSetLcdString: 'lcd Display %3 on line %1 and line %2 %4',\r\n                KrcSetLcdBacklight: 'Enter lcd backlight %1 %2',\r\n                KrcSetLcdClear: 'Clear lcd %1',\r\n\r\n                KrcGetAnalogMapping: '%1 value %2 to %3 ; to %4 to %5 conversion value ',\r\n            },\r\n            Blocks: {\r\n                OnBlock: 'On(HIGH, 5V)',\r\n                OffBlock: 'Off(LOW, 0V)',\r\n                AllOnBlock: 'ALL ON',\r\n                AllOffBlock: 'ALL OFF',\r\n                BacklightOn: 'ON',\r\n                BacklightOff: 'OFF',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.krc.getBlocks = function() {\r\n    return {\r\n        KrcDigitalPortOnOffList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.OnBlock, '1'],\r\n                        [Lang.Blocks.OffBlock, '0'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        KrcBacklightOnoffList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.BacklightOn, '0'],\r\n                        [Lang.Blocks.BacklightOff, '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n        KrcDigitalPortList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['D1', '9'],\r\n                        ['D2', '10'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                        ['A3', '3'],\r\n                        ['A4', '4'],\r\n                        ['A5', '5'],\r\n                        ['A6', '6'],\r\n                        ['A7', '7'],\r\n                        ['A8', '8'],\r\n                        ['S1', '11'],\r\n                        ['S2', '12'],\r\n                        ['S3', '13'],\r\n                        ['S4', '14'],\r\n                        ['S5', '15'],\r\n                        ['S6', '6'],\r\n                    ],\r\n                    value: '9',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n        KrcServoPortList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['S1', '1'],\r\n                        ['S2', '2'],\r\n                        ['S3', '3'],\r\n                        ['S4', '4'],\r\n                        ['S5', '5'],\r\n                        ['S6', '6'],\r\n                        ['S7', '7'],\r\n                    ],\r\n                    value: '1', // 기본 표시값\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n\r\n        KrcAllOnOffList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.AllOffBlock, '2'],\r\n                        [Lang.Blocks.AllOnBlock, '3'],\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('VALUE');\r\n            },\r\n        },\r\n        KrcAnalogPortList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A1', '0'],\r\n                        ['A2', '1'],\r\n                        ['A3', '2'],\r\n                        ['A4', '3'],\r\n                        ['A5', '4'],\r\n                        ['A6', '5'],\r\n                        ['A7', '6'],\r\n                        ['A8', '7'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n        // 1. 삐소리\r\n        KrcBuzzerOnOff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'KrcBuzzerOnOff',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'krc_LV1',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                const port = 10;\r\n                let duration = script.getNumberValue('VALUE');\r\n                // 길이\r\n                const value2 = 2400;\r\n                //698;   // 음 주파수\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    if (duration === 0) {\r\n                        // 음 길이가 0 이면\r\n                        Entry.hw.sendQueue.SET[parseInt(port, 10)] = {\r\n                            type: Entry.krc.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n                    if (duration > 300) {\r\n                        duration = 300;\r\n                    }\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    // 출력 시작 플래그 셋\r\n                    script.timeFlag = 1;\r\n                    // 시간플래그 셋\r\n\r\n                    Entry.hw.sendQueue.SET[parseInt(port, 10)] = {\r\n                        type: Entry.krc.sensorTypes.TONE,\r\n                        data: {\r\n                            value: value2,\r\n                            duration: duration / 10,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag === 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue.SET[parseInt(port, 10)] = {\r\n                        type: Entry.krc.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 3. DC 모터 속도 정하기\r\n        KrcSetMotorSpeed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'KrcSetMotorSpeed',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                RSPEED: 1,\r\n            },\r\n            class: 'krc_LV1',\r\n            isNotFor: ['KRC'],\r\n            func(sprite, script) {\r\n                let rspeed = script.getNumberValue('RSPEED', script);\r\n                let lspeed = script.getNumberValue('LSPEED', script);\r\n                const port = 3;\r\n                lspeed = Math.min(100, lspeed);\r\n                lspeed = Math.max(-100, lspeed);\r\n                rspeed = Math.min(100, rspeed);\r\n                rspeed = Math.max(-100, rspeed);\r\n\r\n                if (!(LmotorSpeed === lspeed) || !(RmotorSpeed === rspeed)) {\r\n                    if (!script.isStart) {\r\n                        if (!Entry.hw.sendQueue.SET) {\r\n                            Entry.hw.sendQueue.SET = {};\r\n                        }\r\n                        Entry.hw.sendQueue.SET[parseInt(port, 10)] = {\r\n                            type: Entry.krc.sensorTypes.MOTOR,\r\n                            data: [lspeed, rspeed],\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        LmotorSpeed = lspeed;\r\n                        RmotorSpeed = rspeed;\r\n                        script.isStart = true;\r\n                        // 출력 시작 플래그 셋\r\n                        script.timeFlag = 1;\r\n                        // 시간플래그 셋\r\n                        setTimeout(() => {\r\n                            script.timeFlag = 0;\r\n                        }, DelayTime);\r\n                        return script;\r\n                    } else if (script.timeFlag === 1) {\r\n                        return script;\r\n                    } else {\r\n                        // 설정 시간이 지나면 출력 리셋\r\n                        delete script.timeFlag;\r\n                        delete script.isStart;\r\n                        Entry.engine.isContinue = false;\r\n                        return script.callReturn();\r\n                    }\r\n                } else {\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 4. DC 모터 정지하기\r\n        KrcMotorStop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'KrcMotorStop',\r\n            },\r\n            paramsKeyMap: {\r\n                //PORT: 0,\r\n            },\r\n            class: 'krc_LV1',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                const port = 19;\r\n                //port += 2;\r\n                const lspeed = 0;\r\n                const rspeed = 0;\r\n\r\n                if (!(LmotorSpeed === 0) || !(RmotorSpeed === 0)) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(port, 10)] = {\r\n                        type: Entry.krc.sensorTypes.MOTOR,\r\n                        data: [lspeed, rspeed],\r\n                        time: new Date().getTime(),\r\n                    };\r\n                }\r\n\r\n                LmotorSpeed = 0;\r\n                RmotorSpeed = 0;\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 5.  서보 모터 각도 설정하기\r\n        KrcSetServo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'KrcServoPortList',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'KrcSetServo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                ANGLE: 1,\r\n                SPEED: 2,\r\n            },\r\n            class: 'krc_LV1',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                const port = script.getNumberValue('PORT', script);\r\n                let angle = script.getNumberValue('ANGLE', script);\r\n                let speed = script.getNumberValue('SPEED', script);\r\n                //\t\t\t\tport += 2;\r\n                //\t\t\t\tvar mode = 1;\r\n\r\n                angle = Math.min(180, angle);\r\n                angle = Math.max(0, angle);\r\n                speed = Math.min(100, speed);\r\n                speed = Math.max(0, speed);\r\n                speed *= speed * 255;\r\n                //angle += 1;\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[parseInt(port, 10)] = {\r\n                    type: Entry.krc.sensorTypes.SERVO,\r\n                    data: [angle, speed],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 10. 디지털  출력\r\n        KrcDigitalOnOff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'KrcDigitalPortList',\r\n                    },\r\n                    {\r\n                        type: 'KrcDigitalPortOnOffList',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'KrcDigitalOnOff',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'krc_LV3', // 블록을 묶는 그룹 이름. 이 값이 다르면 사이에 가로줄이 생깁니다\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                const port = script.getNumberValue('PORT');\r\n                const value = script.getNumberValue('VALUE');\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[parseInt(port, 10)] = {\r\n                    type: Entry.krc.sensorTypes.DIGITAL,\r\n                    /// 출력 디바이스\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 11. 디지털입력\r\n        KrcGetDgitalValue: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            //basic_boolean_field\r\n            statements: [],\r\n            template: Lang.template.KrcGetDgitalValue,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'KrcDigitalPortList',\r\n                    },\r\n                ],\r\n                type: 'KrcGetDgitalValue',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'krc_LV3',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                const port = script.getNumberValue('PORT');\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.krc.sensorTypes.DIGITAL] = {\r\n                    port: port,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.DIGITAL[parseInt(port)];\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 12. 아날로그 읽기\r\n        KrcGetAnalogValue: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.KrcGetAnalogValue,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'KrcAnalogPortList',\r\n                    },\r\n                ],\r\n                type: 'KrcGetAnalogValue',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'krc_LV3',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                const BtnIndex = script.getNumberValue('PORT');\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                return ANALOG[parseInt(BtnIndex)];\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 15. 초음파 센서 값\r\n        KrcGetUsonicValue: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.KrcGetUsonicValue,\r\n            statements: [],\r\n\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'KrcAnalogPortList',\r\n                    },\r\n                ],\r\n                type: 'KrcGetUsonicValue',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'krc_LV3',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                const BtnIndex = script.getNumberValue('PORT');\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                return (ANALOG[parseInt(BtnIndex)] * 4 * 3) / 10;\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 21. LCD글자출력\r\n        KrcSetLcdString: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['Hello'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'KrcSetLcdString',\r\n            },\r\n            paramsKeyMap: {\r\n                COLUMN: 0,\r\n                LINE: 1,\r\n                STRING: 2,\r\n            },\r\n            class: 'krc_LV5',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                //var sq = Entry.hw.sendQueue;\r\n                const line2 = script.getValue('LINE', script);\r\n                const column2 = script.getValue('COLUMN', script);\r\n                const string = script.getValue('STRING', script);\r\n                const text = [];\r\n                let buf;\r\n\r\n                if (!script.isStart) {\r\n                    if (typeof string === 'string') {\r\n                        for (let i = 0; i < string.length; i++) {\r\n                            buf = Entry.memaker.toByte(string[parseInt(i, 10)]);\r\n                            text[parseInt(i, 10)] = buf;\r\n                            //text[i] = Entry.memaker.toByte(string[i]);\r\n                            //text.i = Entry.memaker.toByte(string.i);\r\n                        }\r\n                    } else {\r\n                        text[0] = string;\r\n                    }\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    //var fps = Entry.FPS || 60;\r\n                    // var timeValue = 60 / fps * 50;\r\n\r\n                    Entry.hw.sendQueue.SET[3] = {\r\n                        type: Entry.krc.sensorTypes.LCD_SET,\r\n                        data: {\r\n                            line: line2,\r\n                            column: column2,\r\n                            text0: text[0],\r\n                            text1: text[1],\r\n                            text2: text[2],\r\n                            text3: text[3],\r\n                            text4: text[4],\r\n                            text5: text[5],\r\n                            text6: text[6],\r\n                            text7: text[7],\r\n                            text8: text[8],\r\n                            text9: text[9],\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, DelayTime);\r\n                    return script;\r\n                } else if (script.timeFlag === 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = true;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // . LCD 백라이트\r\n        KrcSetLcdBacklight: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'KrcBacklightOnoffList',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'KrcSetLcdBacklight',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'krc_LV5',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                const value = script.getNumberValue('VALUE');\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[1] = {\r\n                    type: Entry.krc.sensorTypes.LCD_SET,\r\n                    data: [value, 1, 1],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 23. LCD 지우기\r\n        KrcSetLcdClear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'KrcSetLcdClear',\r\n            },\r\n            class: 'krc_LV5',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                //var port = 0;\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[4] = {\r\n                    type: Entry.krc.sensorTypes.LCD_SET,\r\n                    data: [4, 4, 4],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 3. 소리/빛/가변저항 - 2) mapping 값\r\n        KrcGetAnalogMapping: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.KrcGetAnalogMapping,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'KrcGetAnalogMapping',\r\n            },\r\n            paramsKeyMap: {\r\n                IDATA: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'krc_ANA',\r\n            isNotFor: ['KRC'],\r\n            func: (sprite, script) => {\r\n                let result = script.getNumberValue('IDATA', script);\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                let swap;\r\n                if (value2 > value3) {\r\n                    swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                return Math.round(result);\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n    };\r\n};\r\nmodule.exports = Entry.krc;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_LineCoding.js",
    "content": "'use strict';\r\n\r\nlet LmotorSpeed = 0;\r\nlet RmotorSpeed = 0;\r\nlet LineNum = 20;\r\nlet WheelNum = 18;\r\nlet LineInit = 0;\r\nlet LineSaveFlag = 0;\r\nlet LineOneFlag = 1;\r\nconst ServeAngle = [0, 0, 0, 0, 0, 0, 0, 0];\r\nconst OutPort = [0, 0, 0, 0, 0, 0, 0, 0];\r\n\r\nEntry.LineCoding = {\r\n    id: '3D.1',\r\n    name: 'LineCoding',\r\n    url: 'http://www.ssmake.co.kr/',\r\n    imageName: 'LineCoding.png',\r\n    title: {\r\n        ko: '라인코딩',\r\n        en: 'LineCoding',\r\n    },\r\n\r\n    setZero: () => {\r\n        //  하드웨어 초기화 로직\r\n        /*       if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[parseInt(key)].data = 0;\r\n                Entry.hw.sendQueue.SET[parseInt(key)].time = new Date().getTime();\r\n            });\r\n        } */\r\n\r\n        Entry.hw.sendQueue = {\r\n            GET: {},\r\n            SET: {},\r\n        };\r\n        Entry.hw.sendQueue.SET[9] = {\r\n            type: Entry.LineCoding.sensorTypes.LINE_EASY,\r\n            data: 0,\r\n            time: new Date().getTime(),\r\n        };\r\n        Entry.hw.update();\r\n        LmotorSpeed = 0;\r\n        RmotorSpeed = 0;\r\n        LineNum = 20;\r\n        LineInit = 0;\r\n        LineSaveFlag = 0;\r\n        LineOneFlag = 1;\r\n        ServeAngle[0] = 0;\r\n        ServeAngle[1] = 0;\r\n        ServeAngle[2] = 0;\r\n        ServeAngle[3] = 0;\r\n        ServeAngle[4] = 0;\r\n        ServeAngle[5] = 0;\r\n        ServeAngle[6] = 0;\r\n        ServeAngle[7] = 0;\r\n        OutPort[0] = 0;\r\n        OutPort[1] = 0;\r\n        OutPort[2] = 0;\r\n        OutPort[3] = 0;\r\n        OutPort[4] = 0;\r\n        OutPort[5] = 0;\r\n        OutPort[6] = 0;\r\n        OutPort[7] = 0;\r\n    },\r\n    Static: {\r\n        //        LineCoding_BLOCK_COLOR: '#00979D', // gray(#848484)\r\n        //        LineCoding_ARROW_COLOR_HW: '#00979D',\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        BUZZER: 3,\r\n        TONE: 34,\r\n        USONIC: 7,\r\n        USONIC_SET: 33,\r\n        LCD_SET: 40,\r\n        LINE_EASY: 51,\r\n        LINE_FW_SPEED: 55,\r\n        LINE_TURN_SPEED: 56,\r\n        LINE_CROSS_TIME: 57,\r\n        LINE_EASY_MOTOR: 58,\r\n        LINE_RESTART: 60,\r\n        LINE_DELAY: 61,\r\n        LINE_LINE: 62,\r\n        LINE_TURN: 63,\r\n        LINE_MOTOR: 64,\r\n        LINE_BMOTOR: 65,\r\n        LINE_BWMOTOR: 66,\r\n        LINE_WHEEL: 67,\r\n        LINE_SERVO: 70,\r\n        LINE_SSERVO: 71,\r\n        LINE_PORT: 72,\r\n        LINE_BUZZER: 73,\r\n        LINE_LED: 74,\r\n        LINE_LINEDELAY: 75,\r\n        LINE_SLINE: 76,\r\n        LINE_LINEFIND: 77,\r\n        LINE_LINELOST: 78,\r\n        LINE_CLINE: 79,\r\n        LINE_CLINE2: 80,\r\n        LINE_FFMOTOR: 90,\r\n        LINE_BBMOTOR: 91,\r\n        LINE_MOTORSTOP: 92,\r\n        LINE_PLINE: 93,\r\n        LINE_START: 94,\r\n        LINE_TIMER: 95,\r\n        LINE_COLOR: 96,\r\n        LINE_ABSH: 97,\r\n        LINE_BLACKFORWARDF: 98,\r\n        LINE_REMOT: 100,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [7644, 3821, 1910, 955, 477],\r\n        '2': [7214, 3607, 1803, 901, 450],\r\n        '3': [6810, 3404, 1702, 850, 425],\r\n        '4': [6247, 3213, 1606, 803, 401],\r\n        '5': [6066, 3033, 1516, 757, 378],\r\n        '6': [5726, 2862, 1431, 715, 357],\r\n        '7': [5404, 2702, 1350, 675, 337],\r\n        '8': [5101, 2550, 1275, 637, 318],\r\n        '9': [4815, 2407, 1203, 601, 300],\r\n        '10': [4544, 2272, 1135, 567, 283],\r\n        '11': [4289, 2144, 1072, 535, 267],\r\n        '12': [4049, 2024, 1011, 505, 252],\r\n    },\r\n    BlockState: {},\r\n};\r\n\r\nEntry.LineCoding.blockMenuBlocks = [\r\n    /// 하드웨어 블록 등록 , 여기에 등록된 블록이 순서대로 나열되며 설정한 이름으로 화면에 보임\r\n    'LineCodingStart',\r\n    'LineCodingStop',\r\n    'LineCodingLineEasy',\r\n    'LineCodingEasySet',\r\n    'LineCodingEasyTimeSet',\r\n    'LineCodingEasyMotor',\r\n    'LineCodingRestart',\r\n    'LineCodingDelay',\r\n    'LineCodingLine',\r\n    'LineCodingTurn',\r\n    'LineCodingMotor',\r\n    'LineCodingBmotor',\r\n    //    'LineCodingBwMotor',\r\n    'LineCodingWheel',\r\n    //    'LineCodingSServo',\r\n    //    'LineCodingBmotor',\r\n    /// 디지털 포트 제어\r\n    'LineCodingGetDgitalValue',\r\n    'LineCodingGetAnalogValue',\r\n    'LineCodingDigitalOnOff',\r\n    'LineCodingServo',\r\n    'LineCodingMelody',\r\n    //    'LineCodingSline',\r\n    //    'LineCodingLineFind',\r\n    //    'LineCodingLineLost',\r\n    //    'LineCodingCline',\r\n    //    'LineCodingCline2',\r\n    //    'LineCodingPline',\r\n    //    'LineCodingStart',\r\n    //    'LineCodingTimer',\r\n    //    'LineCodingLineColor',\r\n    //    'LineCodingMotorStop',\r\n    // DC모터 정지하기\r\n\r\n    // 서보모터 제어\r\n\r\n    //디지탈 입력\r\n\r\n    // 아날로그 입력\r\n    //    'LineCodingGetUsonicValue',\r\n    //초음파센서 읽기\r\n    'LineCodingSetLcdString',\r\n    //    'LineCodingSetLcdBacklight',\r\n    'LineCodingSetLcdClear',\r\n    'LineCodingGetAnalogMapping',\r\n    'LineCodingRemotRx',\r\n    'LineCodingLineDelay',\r\n    'LineCodingBlackForwardF',\r\n    'LineCodingBuzzerOnOff',\r\n    'LineCodingLED',\r\n    'LineCodingABSH',\r\n    'LineCodingFFmotor',\r\n    'LineCodingBBmotor',\r\n    'LineCodingMotorStop',\r\n];\r\n\r\nEntry.LineCoding.setLanguage = function() {\r\n    // 블록 이름  번역\r\n    return {\r\n        ko: {\r\n            template: {\r\n                LineCodingStart: '%1 저장하기 시작 %2',\r\n                LineCodingStop: '라인트레이서에 저장하기 종료 %1',\r\n                LineCodingLineEasy: '%1 하기 %2',\r\n                LineCodingEasySet: '%1 %2 로 정하기 %3',\r\n                LineCodingEasyTimeSet: '교차로에서 %1mS 더 직진하도록 설정하기 %2',\r\n                LineCodingEasyMotor: '모터 %1 방향으로  %2mS 이동하기 %3',\r\n                LineCodingRestart: 'restart(%1); %2',\r\n                LineCodingDelay: 'delay(%1); %2',\r\n                LineCodingLine: 'line(%1, %2, %3); %4',\r\n                LineCodingTurn: '%1(%2, %3); %4',\r\n                LineCodingMotor: 'motor(%1, %2, %3); %4',\r\n                LineCodingBmotor: '%1(%2, %3, %4); %5',\r\n                LineCodingWheel: 'wheel(%1, %2); %3',\r\n                LineCodingServo: 'sservo(%1, %2, %3); %4',\r\n                LineCodingDigitalOnOff: '디지털 %1 포트 %2 설정하기 %3',\r\n                LineCodingMelody: '스피커 %1 옥타브 %2음 %3 초 연주하기 %4',\r\n                LineCodingMotorStop: 'DC모터 정지하기 %1',\r\n                LineCodingBlackForwardF: 'blackforwardf(%1,%2,%3,%4,%5); %6',\r\n                LineCodingGetDgitalValue: '디지털 %1 포트 읽기',\r\n                LineCodingGetAnalogValue: '아날로그 %1 포트 읽기',\r\n                LineCodingGetAnalogMapping: ' %1 값 %2 ~ %3 에서 %4 ~ %5 으로 변환값',\r\n                LineCodingRemotRx: ' 조종기버튼 %1,  %2 눌리면 실행하는 코드 %3',\r\n                LineCodingLineDelay: 'linedelay(%1, %2, %3); %4',\r\n                LineCodingABSH: 'lineabsh(%1, %2, %3, %4, %5, %6); %7',\r\n                LineCodingBuzzerOnOff: 'buzzer(%1, %2, %3); %4',\r\n                LineCodingLED: 'led(%1, %2, %3, %4); %5',\r\n                LineCodingSetLcdString: 'lcd 세로%1줄,  가로%2줄 에  %3 표시하기 %4',\r\n                LineCodingSetLcdClear: 'lcd 지우기 %1',\r\n                LineCodingFFmotor: 'ffmotor(%1, %2); %3',\r\n                LineCodingBBmotor: 'bbmotor(%1, %2); %3',\r\n                LineCodingMotorStop: 'motorstop(%1, %2); %3',\r\n            },\r\n            Blocks: {\r\n                OnBlock: '켜짐(HIGH, 5V)',\r\n                OffBlock: '꺼짐(LOW, 0V)',\r\n                AllOnBlock: '모두 켜짐',\r\n                AllOffBlock: '모두 꺼짐',\r\n                BacklightOn: '켜기',\r\n                BacklightOff: '끄기',\r\n                lineForward: '직진',\r\n                Left: '좌회전',\r\n                Right: '우회전',\r\n                LineBack: '후진',\r\n                ForwardSpeed: '직진속도',\r\n                TurnSpeed: '회전속도',\r\n                ForwardOverTime: '교차로 직진시간',\r\n                Tracer: '라인트레이서',\r\n                RemotBit: '조종기(비트수신)',\r\n                RemotPs2: '조종기(PS2)',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                LineCodingStart: 'Start saving to the %1 %2',\r\n                LineCodingStop: 'End saving to lint racer %1',\r\n                LineCodingLineEasy: 'Go %1 %2',\r\n                LineCodingEasySet: 'To set the %1 %2 %3',\r\n                LineCodingEasyTimeSet: 'Set %1mS to go straight at the intersection %2',\r\n                LineCodingEasyMotor: 'Moving %2mS in the direction of motor %1 %3',\r\n                LineCodingRestart: 'restart(%1); %2 %2',\r\n                LineCodingDelay: 'delay(%1); %2',\r\n                LineCodingLine: 'line(%1, %2, %3); %4',\r\n                LineCodingTurn: '%1(%2, %3); %4',\r\n                LineCodingMotor: 'motor(%1, %2, %3); %4',\r\n                LineCodingBmotor: '%1(%2, %3, %4); %5',\r\n                LineCodingWheel: 'wheel(%1, %2); %3',\r\n                LineCodingServo: 'sservo(%1, %2, %3); %4',\r\n                LineCodingDigitalOnOff: 'Setting up digital %1 port %2 %3',\r\n                LineCodingMelody: 'Play speaker %1 octave %2 sound %3 seconds %4',\r\n                LineCodingMotorStop: 'Stop DC Motor %1',\r\n                LineCodingBlackForwardF: 'blackforwardf(%1,%2,%3,%4);%5',\r\n                LineCodingGetDgitalValue: 'Read digital %1 port',\r\n                LineCodingGetAnalogValue: 'Analog %1 port read',\r\n                LineCodingGetAnalogMapping: '%1 value %2 to %3 ; to %4 to %5 conversion value ',\r\n                LineCodingRemotRx: ' Code that runs when controller button %1, %2 is pressed %3',\r\n                LineCodingLineDelay: 'linedelay(%1, %2, %3); %4',\r\n                LineCodingABSH: 'lineabsh(%1, %2, %3, %4, %5, %6); %7',\r\n                LineCodingBuzzerOnOff: 'buzzer(%1, %2, %3); %4',\r\n                LineCodingLED: 'led(%1, %2, %3, %4); %5',\r\n                LineCodingSetLcdString: 'lcd Display %3 on line %1 and line %2 %4',\r\n                LineCodingSetLcdClear: 'Clear lcd %1',\r\n                LineCodingFFmotor: 'ffmotor(%1, %2); %3',\r\n                LineCodingBBmotor: 'bbmotor(%1, %2); %3',\r\n                LineCodingMotorStop: 'motorstop(%1, %2); %3',\r\n            },\r\n            Blocks: {\r\n                OnBlock: 'On(HIGH, 5V)',\r\n                OffBlock: 'Off(LOW, 0V)',\r\n                AllOnBlock: 'ALL ON',\r\n                AllOffBlock: 'ALL OFF',\r\n                BacklightOn: 'ON',\r\n                BacklightOff: 'OFF',\r\n                lineForward: 'FORWARD',\r\n                Left: 'LEFT',\r\n                Right: 'RIGHT',\r\n                LineBack: 'BACK',\r\n                ForwardSpeed: 'driving speed',\r\n                TurnSpeed: 'rotational speed',\r\n                ForwardOverTime: 'Intersection Driving Time',\r\n                Tracer: 'Line Tracer',\r\n                RemotBit: 'Remot(bit)',\r\n                RemotPs2: 'Remot(PS2)',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.LineCoding.getBlocks = function() {\r\n    return {\r\n        LineCodingDigitalPortOnOffList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.OnBlock, '1'],\r\n                        [Lang.Blocks.OffBlock, '0'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingBacklightOnoffList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.BacklightOn, '0'],\r\n                        [Lang.Blocks.BacklightOff, '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingEasylineList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.lineForward, '3'],\r\n                        [Lang.Blocks.Left, '4'],\r\n                        [Lang.Blocks.Right, '5'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingEasyMotorList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.lineForward, '3'],\r\n                        [Lang.Blocks.Left, '4'],\r\n                        [Lang.Blocks.Right, '5'],\r\n                        [Lang.Blocks.LineBack, '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingStartList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.Tracer, '1'],\r\n                        [Lang.Blocks.RemotBit, '10'],\r\n                        [Lang.Blocks.RemotPs2, '11'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingEasySetList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.ForwardSpeed, '55'],\r\n                        [Lang.Blocks.TurnSpeed, '56'],\r\n                    ],\r\n                    value: '55',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingCrossroadList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['T1', '21'],\r\n                        ['L1', '1'],\r\n                        ['R1', '4'],\r\n                        ['LR1', '7'],\r\n                        ['SL1', '11'],\r\n                        ['SR1', '14'],\r\n                    ],\r\n                    value: '21',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingRemotKeyList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['NONE', '0'],\r\n                        ['L_UP', '1'],\r\n                        ['L_LEFT', '2'],\r\n                        ['L_RIGHT', '3'],\r\n                        ['L_DN', '4'],\r\n                        ['L1', '5'],\r\n                        ['L2', '6'],\r\n                        ['R_UP', '7'],\r\n                        ['R_LEFT', '8'],\r\n                        ['R_RIGHT', '9'],\r\n                        ['R_DN', '10'],\r\n                        ['R1', '11'],\r\n                        ['R2', '12'],\r\n                        ['START', '13'],\r\n                        ['SELECT', '14'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingOctaveList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['3', '0'],\r\n                        ['4', '1'],\r\n                        ['5', '2'],\r\n                        ['6', '3'],\r\n                        ['7', '4'],\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n        },\r\n        LineCodingToneList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n        },\r\n        LineCodingTurnList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['lt1', '1'],\r\n                        ['rt8', '8'],\r\n                        ['lt2', '2'],\r\n                        ['rt7', '7'],\r\n                        ['lt3', '3'],\r\n                        ['rt6', '6'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n        LineCodingMotorList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['B Motor', '1'],\r\n                        ['BW Motor', '2'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        LineCodingLineSensortList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['S1', '1'],\r\n                        ['S2', '2'],\r\n                        ['S3', '4'],\r\n                        ['S4', '8'],\r\n                        ['S5', '16'],\r\n                        ['S6', '32'],\r\n                        ['S7', '64'],\r\n                        ['S8', '128'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n        LineCodingSensorNumtList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['S1', '0'],\r\n                        ['S2', '1'],\r\n                        ['S3', '2'],\r\n                        ['S4', '3'],\r\n                        ['S5', '4'],\r\n                        ['S6', '5'],\r\n                        ['S7', '6'],\r\n                        ['S8', '7'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n\r\n        LineCodingDigitalPortList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['IN1', '1'],\r\n                        ['IN2', '2'],\r\n                        ['IN3', '3'],\r\n                        ['IN4', '4'],\r\n                        ['IN5', '5'],\r\n                        ['IN6', '6'],\r\n                        ['IN7', '7'],\r\n                        ['IN8', '8'],\r\n                        ['FW1', '9'],\r\n                        ['FW2', '10'],\r\n                        ['FW3', '11'],\r\n                        ['FW4', '12'],\r\n                        ['FW5', '13'],\r\n                        ['FW6', '14'],\r\n                        ['FW7', '15'],\r\n                        ['FW8', '16'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n        LineCodingServoPortList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['OUT1', '1'],\r\n                        ['OUT2', '2'],\r\n                        ['OUT3', '3'],\r\n                        ['OUT4', '4'],\r\n                        ['OUT5', '5'],\r\n                        ['OUT6', '6'],\r\n                        ['OUT7', '7'],\r\n                        ['OUT8', '8'],\r\n                    ],\r\n                    value: '1', // 기본 표시값\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n\r\n        LineCodingAllOnOffList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.AllOffBlock, '2'],\r\n                        [Lang.Blocks.AllOnBlock, '3'],\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('VALUE');\r\n            },\r\n        },\r\n        LineCodingAnalogPortList: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['IN1', '1'],\r\n                        ['IN2', '2'],\r\n                        ['IN3', '3'],\r\n                        ['IN4', '4'],\r\n                        ['IN5', '5'],\r\n                        ['IN6', '6'],\r\n                        ['IN7', '7'],\r\n                        ['IN8', '8'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        // 1. 저장 시작하기\r\n        LineCodingStart: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingStartList',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingStart',\r\n            },\r\n            paramsKeyMap: {\r\n                STAY: 0,\r\n            },\r\n            class: 'LineCoding_EASY',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                ++LineNum;\r\n                LineSaveFlag = 1;\r\n                // 1 시작\r\n                // delay(100);\r\n                const value = script.getNumberValue('STAY');\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                    type: Entry.LineCoding.sensorTypes.LINE_EASY,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 2. 저장 종료\r\n        LineCodingStop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'LineCodingStop',\r\n            },\r\n            paramsKeyMap: {\r\n                //PORT: 0,\r\n            },\r\n            class: 'LineCoding_EASY',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                ++LineNum;\r\n                LineSaveFlag = 0;\r\n                // 2 종료\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[400] = {\r\n                    type: Entry.LineCoding.sensorTypes.LINE_EASY,\r\n                    data: 2,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 3. 쉬운주행\r\n        LineCodingLineEasy: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingEasylineList',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingLineEasy',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'LineCoding_EASY',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const value = script.getNumberValue('VALUE');\r\n                if (LineOneFlag == 1) {\r\n                    if (LineSaveFlag == 1) {\r\n                        ++LineNum;\r\n                    }\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_EASY,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 4. 쉬운주행 설정\r\n        LineCodingEasySet: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingEasySetList',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingEasySet',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NUM: 1,\r\n            },\r\n            class: 'LineCoding_EASY',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const port = script.getNumberValue('PORT', script);\r\n                const num = script.getNumberValue('NUM', script);\r\n                if (!script.isStart) {\r\n                    if (LineSaveFlag == 1) {\r\n                        ++LineNum;\r\n                    }\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    if (port == 55) {\r\n                        Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                            type: Entry.LineCoding.sensorTypes.LINE_FW_SPEED,\r\n                            data: [num],\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    } else {\r\n                        Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                            type: Entry.LineCoding.sensorTypes.LINE_TURN_SPEED,\r\n                            data: [num],\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    }\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, 0.1);\r\n                    return script;\r\n                } else if (script.timeFlag === 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 직진시간설정\r\n        LineCodingEasyTimeSet: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingEasyTimeSet',\r\n            },\r\n            paramsKeyMap: {\r\n                TIME: 0,\r\n            },\r\n            class: 'LineCoding_EASY',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let time2 = script.getNumberValue('TIME');\r\n                if (!script.isStart) {\r\n                    if (LineSaveFlag == 1) {\r\n                        ++LineNum;\r\n                    }\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    time2 = Math.min(2500, time2);\r\n                    time2 = Math.max(0, time2);\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_CROSS_TIME,\r\n                        data: {\r\n                            time: time2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, 0.1);\r\n                    return script;\r\n                } else if (script.timeFlag === 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 5.  쉬운 모터이동\r\n        LineCodingEasyMotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingEasyMotorList',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingEasyMotor',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION: 0,\r\n                TIME: 1,\r\n            },\r\n            class: 'LineCoding_EASY',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let direction2 = script.getNumberValue('DIRECTION', script);\r\n                let time2 = script.getNumberValue('TIME', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    time2 = Math.min(10000, time2);\r\n                    time2 = Math.max(0, time2);\r\n                    direction2 = Math.min(6, direction2);\r\n                    direction2 = Math.max(3, direction2);\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_EASY_MOTOR,\r\n                        data: {\r\n                            direction: direction2,\r\n                            time: time2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 리스타트\r\n        LineCodingRestart: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingRestart',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n            },\r\n            class: 'LineCoding_LINE1',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const num = script.getNumberValue('NUM', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_RESTART,\r\n                        data: [num],\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 딜레이\r\n        LineCodingDelay: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingDelay',\r\n            },\r\n            paramsKeyMap: {\r\n                TIME: 0,\r\n            },\r\n            class: 'LineCoding_LINE1',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let time2 = script.getNumberValue('TIME', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    time2 = Math.min(10000, time2);\r\n                    time2 = Math.max(0, time2);\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_DELAY,\r\n                        data: {\r\n                            time: time2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 5.  line\r\n        LineCodingLine: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingCrossroadList',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingLine',\r\n            },\r\n            paramsKeyMap: {\r\n                CROSS: 0,\r\n                SPEED: 1,\r\n                TIME: 2,\r\n            },\r\n            class: 'LineCoding_LINE1',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const cross2 = script.getNumberValue('CROSS', script);\r\n                let speed2 = script.getNumberValue('SPEED', script);\r\n                let time2 = script.getNumberValue('TIME', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    time2 = Math.min(10000, time2);\r\n                    time2 = Math.max(-10000, time2);\r\n                    speed2 = Math.min(20, speed2);\r\n                    speed2 = Math.max(0, speed2);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_LINE,\r\n                        data: {\r\n                            cross: cross2,\r\n                            speed: speed2,\r\n                            time: time2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n                //return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //  turn lt rt\r\n        LineCodingTurn: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingTurnList',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingTurn',\r\n            },\r\n            paramsKeyMap: {\r\n                CROSS: 0,\r\n                SPEED: 1,\r\n                TIME: 2,\r\n            },\r\n            class: 'LineCoding_LINE1',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let cross2 = script.getNumberValue('CROSS', script);\r\n                let speed2 = script.getNumberValue('SPEED', script);\r\n                let time2 = script.getNumberValue('TIME', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    cross2 = Math.min(8, cross2);\r\n                    cross2 = Math.max(1, cross2);\r\n                    time2 = Math.min(1000, time2);\r\n                    time2 = Math.max(0, time2);\r\n                    speed2 = Math.min(20, speed2);\r\n                    speed2 = Math.max(0, speed2);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_TURN,\r\n                        data: {\r\n                            cross: cross2,\r\n                            speed: speed2,\r\n                            time: time2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //  motor\r\n        LineCodingMotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingMotor',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                RSPEED: 1,\r\n                TIME: 2,\r\n            },\r\n            class: 'LineCoding_LINE1',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let cross2 = script.getNumberValue('LSPEED', script);\r\n                let speed2 = script.getNumberValue('RSPEED', script);\r\n                let time2 = script.getNumberValue('TIME', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    time2 = Math.min(1000, time2);\r\n                    time2 = Math.max(0, time2);\r\n                    cross2 = Math.min(20, cross2);\r\n                    cross2 = Math.max(-20, cross2);\r\n                    speed2 = Math.min(20, speed2);\r\n                    speed2 = Math.max(-20, speed2);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_MOTOR,\r\n                        data: {\r\n                            cross: cross2,\r\n                            speed: speed2,\r\n                            time: time2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //  bmotor bwmotor\r\n        LineCodingBmotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingMotorList',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'LineCodingLineSensortList',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingBmotor',\r\n            },\r\n            paramsKeyMap: {\r\n                MODE: 0,\r\n                LSPEED: 1,\r\n                RSPEED: 2,\r\n                SENSOR: 3,\r\n            },\r\n            class: 'LineCoding_LINE1',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let mode2 = script.getNumberValue('MODE', script);\r\n                let lspeed2 = script.getNumberValue('LSPEED', script);\r\n                let rspeed2 = script.getNumberValue('RSPEED', script);\r\n                let sensor2 = script.getNumberValue('SENSOR', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    mode2 = Math.min(2, mode2);\r\n                    mode2 = Math.max(1, mode2);\r\n                    lspeed2 = Math.min(20, lspeed2);\r\n                    lspeed2 = Math.max(-20, lspeed2);\r\n                    rspeed2 = Math.min(20, rspeed2);\r\n                    rspeed2 = Math.max(-20, rspeed2);\r\n                    sensor2 = Math.min(8, sensor2);\r\n                    sensor2 = Math.max(1, sensor2);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    if (mode2 == 1) {\r\n                        Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                            type: Entry.LineCoding.sensorTypes.LINE_BMOTOR,\r\n                            data: {\r\n                                mode: mode2,\r\n                                lspeed: lspeed2,\r\n                                rspeed: rspeed2,\r\n                                sensor: sensor2,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    } else {\r\n                        Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                            type: Entry.LineCoding.sensorTypes.LINE_BWMOTOR,\r\n                            data: {\r\n                                mode: mode2,\r\n                                lspeed: lspeed2,\r\n                                rspeed: rspeed2,\r\n                                sensor: sensor2,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    }\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //DC 모터 속도 정하기 wheel\r\n        LineCodingWheel: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingWheel',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                RSPEED: 1,\r\n            },\r\n            class: 'LineCoding_LINE1',\r\n            isNotFor: ['LineCoding'],\r\n            func(sprite, script) {\r\n                let rspeed2 = script.getNumberValue('RSPEED', script);\r\n                let lspeed2 = script.getNumberValue('LSPEED', script);\r\n                lspeed2 = Math.min(20, lspeed2);\r\n                lspeed2 = Math.max(-20, lspeed2);\r\n                rspeed2 = Math.min(20, rspeed2);\r\n                rspeed2 = Math.max(-20, rspeed2);\r\n\r\n                if (!(LmotorSpeed === lspeed2) || !(RmotorSpeed === rspeed2) || LineSaveFlag == 1) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    if (LineSaveFlag == 1) {\r\n                        ++LineNum;\r\n                        WheelNum = LineNum;\r\n                    } else {\r\n                        if (WheelNum == 18) {\r\n                            WheelNum = 19;\r\n                        } else {\r\n                            WheelNum = 18;\r\n                        }\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(WheelNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_WHEEL,\r\n                        data: {\r\n                            lspeed: lspeed2,\r\n                            rspeed: rspeed2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LmotorSpeed = lspeed2;\r\n                    RmotorSpeed = rspeed2;\r\n                    return script.callReturn();\r\n                } else {\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 5.  서보 모터 각도 설정하기\r\n        LineCodingServo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingServoPortList',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingServo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                ANGLE: 1,\r\n                SPEED: 2,\r\n            },\r\n            class: 'LineCoding_LINE2',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const sport2 = script.getNumberValue('PORT', script);\r\n                let angle2 = script.getNumberValue('ANGLE', script);\r\n                let speed2 = script.getNumberValue('SPEED', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                //\t\t\t\tport += 2;\r\n                //\t\t\t\tvar mode = 1;\r\n\r\n                angle2 = Math.min(180, angle2);\r\n                angle2 = Math.max(0, angle2);\r\n                speed2 = Math.min(100, speed2);\r\n                speed2 = Math.max(0, speed2);\r\n                //speed *= speed * 255;\r\n                //angle += 1;\r\n                if (ServeAngle[sport2 - 1] != angle2) {\r\n                    ServeAngle[sport2 - 1] = angle2;\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    if (LineSaveFlag == 1) {\r\n                        Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                            type: Entry.LineCoding.sensorTypes.LINE_SERVO,\r\n                            data: {\r\n                                sport: sport2,\r\n                                angle: angle2,\r\n                                speed: speed2,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    } else {\r\n                        Entry.hw.sendQueue.SET[parseInt(sport2, 10)] = {\r\n                            type: Entry.LineCoding.sensorTypes.LINE_SERVO,\r\n                            data: {\r\n                                sport: sport2,\r\n                                angle: angle2,\r\n                                speed: speed2,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    }\r\n                    return script.callReturn();\r\n                } else {\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 디지털  출력\r\n        LineCodingDigitalOnOff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingServoPortList',\r\n                    },\r\n                    {\r\n                        type: 'LineCodingDigitalPortOnOffList',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingDigitalOnOff',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'LineCoding_LINE2', // 블록을 묶는 그룹 이름. 이 값이 다르면 사이에 가로줄이 생깁니다\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const dport2 = script.getNumberValue('PORT');\r\n                const value2 = script.getNumberValue('VALUE');\r\n                if (OutPort[dport2 - 1] != value2) {\r\n                    OutPort[dport2 - 1] = value2;\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    if (LineSaveFlag == 1) {\r\n                        ++LineNum;\r\n                        Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {  //18\r\n                            type: Entry.LineCoding.sensorTypes.LINE_PORT,\r\n                            /// 출력 디바이스\r\n                            data: {\r\n                                dport: dport2,\r\n                                value: value2,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    }\r\n                    else {\r\n                        Entry.hw.sendQueue.SET[parseInt(dport2, 10)] = {  //18\r\n                            type: Entry.LineCoding.sensorTypes.LINE_PORT,\r\n                            /// 출력 디바이스\r\n                            data: {\r\n                                dport: dport2,\r\n                                value: value2,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    }\r\n                    return script.callReturn();\r\n                } else {\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //  스피커 멜로디\r\n        LineCodingMelody: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingOctaveList',\r\n                    },\r\n                    {\r\n                        type: 'LineCodingToneList',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0.25'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingMelody',\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n                NOTE: 1,\r\n                DURATION: 2,\r\n            },\r\n            class: 'LineCoding_LINE2',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let duration2 = script.getNumberValue('DURATION');\r\n                let octave = script.getNumberValue('OCTAVE');\r\n                let value2 = 0;\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (!script.isStart) {\r\n                    let note = script.getValue('NOTE');\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.LineCoding.toneTable[note];\r\n                    }\r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    } else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n                    if (duration2 < 0) {\r\n                        duration2 = 0;\r\n                    }\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    if (duration2 === 0) {\r\n                        // 음 길이가 0 이면\r\n                        Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                            type: Entry.LineCoding.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    } else if (octave > 4) {\r\n                        octave = 4;\r\n                    }\r\n                    if (note != 0) {\r\n                        value2 = Entry.LineCoding.toneMap[note][octave];\r\n                    }\r\n                    if (duration2 > 30) {\r\n                        duration2 = 30;\r\n                    }\r\n                    duration2 = duration2 * 1000;\r\n                    script.isStart = true;\r\n                    // 출력 시작 플래그 셋\r\n                    script.timeFlag = 1;\r\n                    // 시간플래그 셋\r\n\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.TONE,\r\n                        data: {\r\n                            value: value2,\r\n                            duration: duration2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration2 + 32);\r\n                    return script;\r\n                } else if (script.timeFlag === 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 11. 디지털입력\r\n        LineCodingGetDgitalValue: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            //basic_boolean_field\r\n            statements: [],\r\n            template: Lang.template.LineCodingGetDgitalValue,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingDigitalPortList',\r\n                    },\r\n                ],\r\n                type: 'LineCodingGetDgitalValue',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'LineCoding_LINE3',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const port2 = script.getNumberValue('PORT');\r\n                //const DIGITAL = Entry.hw.portData.DIGITAL;\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.LineCoding.sensorTypes.DIGITAL] = {\r\n                    port: port2,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.DIGITAL[parseInt(port2, 10)];\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 12. 아날로그 읽기\r\n        LineCodingGetAnalogValue: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.LineCodingGetAnalogValue,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingAnalogPortList',\r\n                    },\r\n                ],\r\n                type: 'LineCodingGetAnalogValue',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'LineCoding_LINE3',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const BtnIndex = script.getNumberValue('PORT');\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                return ANALOG[parseInt(BtnIndex, 10)];\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // LCD글자출력\r\n        LineCodingSetLcdString: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'text', \r\n                        params: ['Hi, LineCoding'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingSetLcdString',\r\n            },\r\n            paramsKeyMap: {\r\n                COLUMN: 0,\r\n                LINE: 1,\r\n                STRING: 2,\r\n            },\r\n            class: 'LineCoding_LINE3',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                // var sq = Entry.hw.sendQueue;\r\n                const line2 = script.getValue('LINE', script);\r\n                const column2 = script.getValue('COLUMN', script);\r\n                const string = script.getValue('STRING', script);\r\n                let text = [];\r\n                let buf;\r\n\r\n                if (!script.isStart) {\r\n                    if (typeof string === 'string') {\r\n                        for (var i = 0; i < string.length; i++) {\r\n                            buf = Entry.memaker.toByte(string[parseInt(i, 10)]);\r\n                            text[parseInt(i, 10)] = buf;\r\n                        }\r\n                    } else {\r\n                        text[0] = string;\r\n                    }\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    //var fps = Entry.FPS || 60;\r\n                   // var timeValue = 60 / fps * 50;\r\n\r\n                    Entry.hw.sendQueue.SET[3] = {\r\n                        type: Entry.LineCoding.sensorTypes.LCD_SET,\r\n                        data: {\r\n                            line: line2,\r\n                            column: column2,\r\n                            text0: text[0],\r\n                            text1: text[1],\r\n                            text2: text[2],\r\n                            text3: text[3],\r\n                            text4: text[4],\r\n                            text5: text[5],\r\n                            text6: text[6],\r\n                            text7: text[7],\r\n                            text8: text[8],\r\n                            text9: text[9],\r\n                            text10: text[10],\r\n                            text11: text[11],\r\n                            text12: text[12],\r\n                            text13: text[13],\r\n                            text14: text[14],\r\n                            text15: text[15],\r\n                            text16: text[16],\r\n                            text17: text[17],\r\n                            text18: text[18],\r\n                            text19: text[19],\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, 0);\r\n                    return script;\r\n                } else if (script.timeFlag === 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = true;\r\n                    return script.callReturn();\r\n                }\r\n                 \r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // LCD 지우기\r\n        LineCodingSetLcdClear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'LineCodingSetLcdClear',\r\n            },\r\n            paramsKeyMap: {\r\n\r\n            },\r\n            class: 'LineCoding_LINE3',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                //var port = 0;\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[4] = {\r\n                    type: Entry.LineCoding.sensorTypes.LCD_SET,\r\n                    data: [4, 4, 4,],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //  mapping 값\r\n        LineCodingGetAnalogMapping: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.LineCodingGetAnalogMapping,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'LineCodingGetAnalogMapping',\r\n            },\r\n            paramsKeyMap: {\r\n                IDATA: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let result = script.getNumberValue('IDATA', script);\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                let swap;\r\n                if (value2 > value3) {\r\n                    swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                return Math.round(result);\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        // 조종기 수신\r\n        LineCodingRemotRx: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'LineCodingRemotKeyList',\r\n                    },\r\n                    {\r\n                        type: 'LineCodingRemotKeyList',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingRemotRx',\r\n            },\r\n            paramsKeyMap: {\r\n                KEY1: 0,\r\n                KEY2: 1,\r\n            },\r\n            class: 'LineCoding_LINE5', // 블록을 묶는 그룹 이름. 이 값이 다르면 사이에 가로줄이 생깁니다\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                const dport2 = script.getNumberValue('KEY1');\r\n                const value2 = script.getNumberValue('KEY2');\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                    type: Entry.LineCoding.sensorTypes.LINE_REMOT,\r\n                    data: {\r\n                        dport: dport2,\r\n                        value: value2,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //.  linedelay\r\n        LineCodingLineDelay: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingLineDelay',\r\n            },\r\n            paramsKeyMap: {\r\n                LINETIME: 0,\r\n                SPEED: 1,\r\n                TIME: 2,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let linetime2 = script.getNumberValue('LINETIME', script);\r\n                let speed2 = script.getNumberValue('SPEED', script);\r\n                let time2 = script.getNumberValue('TIME', script);\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    linetime2 = Math.min(10000, linetime2);\r\n                    linetime2 = Math.max(0, linetime2);\r\n                    time2 = Math.min(2550, time2);\r\n                    time2 = Math.max(0, time2);\r\n                    speed2 = Math.min(20, speed2);\r\n                    speed2 = Math.max(0, speed2);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_LINEDELAY,\r\n                        data: {\r\n                            linetime: linetime2,\r\n                            speed: speed2,\r\n                            time: time2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n                //return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //absh\r\n        LineCodingABSH: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['18'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['12'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['10'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['8'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingABSH',\r\n            },\r\n            paramsKeyMap: {\r\n                ABSH1: 0,\r\n                ABSH2: 1,\r\n                ABSH3: 2,\r\n                ABSH4: 3,\r\n                ABSH5: 4,\r\n                ABSH6: 5,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let absh1 = script.getNumberValue('ABSH1', script);\r\n                let absh2 = script.getNumberValue('ABSH2', script);\r\n                let absh3 = script.getNumberValue('ABSH3', script);\r\n                let absh4 = script.getNumberValue('ABSH4', script);\r\n                let absh5 = script.getNumberValue('ABSH5', script);\r\n                let absh6 = script.getNumberValue('ABSH6', script);\r\n                if (!script.isStart) {\r\n                    if (LineSaveFlag == 1) {\r\n                      ++LineNum;\r\n                    }\r\n                    absh1 = Math.min(20, absh1);\r\n                    absh1 = Math.max(0, absh1);\r\n                    absh2 = Math.min(20, absh2);\r\n                    absh2 = Math.max(0, absh2);\r\n                    absh3 = Math.min(20, absh3);\r\n                    absh3 = Math.max(0, absh3);\r\n                    absh4 = Math.min(20, absh4);\r\n                    absh4 = Math.max(0, absh4);\r\n                    absh5 = Math.min(20, absh5);\r\n                    absh5 = Math.max(0, absh5);\r\n                    absh6 = Math.min(20, absh6);\r\n                    absh6 = Math.max(0, absh6);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_ABSH,\r\n                        data: {\r\n                            absh1,\r\n                            absh2,\r\n                            absh3,\r\n                            absh4,\r\n                            absh5,\r\n                            absh6,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, 0.1);\r\n                    return script;\r\n                } else if (script.timeFlag === 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //  부저명령\r\n        LineCodingBuzzerOnOff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['300'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['300'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingBuzzerOnOff',\r\n            },\r\n            paramsKeyMap: {\r\n                COUNT: 0,\r\n                ONTIME: 1,\r\n                OFFTIME: 2,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let ontime = script.getNumberValue('ONTIME');\r\n                let offtime = script.getNumberValue('OFFTIME');\r\n                let count = script.getValue('COUNT');\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    ontime = Math.min(2550, ontime);\r\n                    ontime = Math.max(0, ontime);\r\n                    offtime = Math.min(2550, offtime);\r\n                    offtime = Math.max(0, offtime);\r\n                    count = Math.min(255, count);\r\n                    count = Math.max(0, count);\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_BUZZER,\r\n                        data: {\r\n                            linetime: ontime,\r\n                            speed: count,\r\n                            time: offtime,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //  LED명령\r\n        LineCodingLED: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['300'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['300'],\r\n                    },\r\n                    {\r\n                        type: 'LineCodingServoPortList',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingLED',\r\n            },\r\n            paramsKeyMap: {\r\n                COUNT: 0,\r\n                ONTIME: 1,\r\n                OFFTIME: 2,\r\n                PORT: 3,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let ontime2 = script.getNumberValue('ONTIME');\r\n                let offtime2 = script.getNumberValue('OFFTIME');\r\n                let count2 = script.getValue('COUNT');\r\n                let outport2 = script.getValue('PORT');\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    ontime2 = Math.min(2550, ontime2);\r\n                    ontime2 = Math.max(0, ontime2);\r\n                    offtime2 = Math.min(2550, offtime2);\r\n                    offtime2 = Math.max(0, offtime2);\r\n                    count2 = Math.min(255, count2);\r\n                    count2 = Math.max(0, count2);\r\n                    outport2 = Math.min(8, outport2);\r\n                    outport2 = Math.max(1, outport2);\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_LED,\r\n                        data: {\r\n                            ontime: ontime2,\r\n                            offtime: offtime2,\r\n                            count: count2,\r\n                            outport: outport2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        LineCodingBlackForwardF: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['6'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['-4'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['3'],\r\n                    },\r\n                    {\r\n                        type: 'LineCodingSensorNumtList',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'LineCodingSensorNumtList',\r\n                        params: ['7'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingBlackForwardF',\r\n            },\r\n            paramsKeyMap: {\r\n                SP: 0,\r\n                BSP: 1,\r\n                COUNT: 2,\r\n                LSEN: 3,\r\n                RSEN: 4,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func: (sprite, script) => {\r\n                let fsp2 = script.getNumberValue('SP');\r\n                let bsp2 = script.getNumberValue('BSP');\r\n                let count2 = script.getValue('COUNT');\r\n                let lsen2 = script.getValue('LSEN');\r\n                let rsen2 = script.getValue('RSEN');\r\n                if (LineSaveFlag == 1) {\r\n                    ++LineNum;\r\n                }\r\n                if (LineOneFlag == 1) {\r\n                    fsp2 = Math.min(20, fsp2);\r\n                    fsp2 = Math.max(0, fsp2);\r\n                    bsp2 = Math.min(20, bsp2);\r\n                    bsp2 = Math.max(-20, bsp2);\r\n                    count2 = Math.min(10, count2);\r\n                    count2 = Math.max(0, count2);\r\n                    lsen2 = Math.min(7, lsen2);\r\n                    lsen2 = Math.max(0, lsen2);\r\n                    rsen2 = Math.min(7, rsen2);\r\n                    rsen2 = Math.max(0, rsen2);\r\n                    LineInit = Entry.hw.portData.DIGITAL[0];\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                        type: Entry.LineCoding.sensorTypes.LINE_BLACKFORWARDF,\r\n                        data: {\r\n                            fsp: fsp2,\r\n                            bsp: bsp2,\r\n                            count: count2,\r\n                            lsen: lsen2,\r\n                            rsen: rsen2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    LineOneFlag = 0;\r\n                }\r\n                if (Entry.hw.portData.DIGITAL[0] == LineInit && LineSaveFlag == 0) {\r\n                    return script;\r\n                } else {\r\n                    LineOneFlag = 1;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //DC 모터 직진편차보정 ffmotor\r\n        LineCodingFFmotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingFFmotor',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                RSPEED: 1,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func(sprite, script) {\r\n                let rspeed2 = script.getNumberValue('RSPEED', script);\r\n                let lspeed2 = script.getNumberValue('LSPEED', script);\r\n                ++LineNum;\r\n                \r\n                lspeed2 = Math.min(255, lspeed2);\r\n                lspeed2 = Math.max(0, lspeed2);\r\n                rspeed2 = Math.min(255, rspeed2);\r\n                rspeed2 = Math.max(0, rspeed2);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                    type: Entry.LineCoding.sensorTypes.LINE_FFMOTOR,\r\n                    data: {\r\n                        lspeed: lspeed2,\r\n                        rspeed: rspeed2,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n                ++LineNum;\r\n                LmotorSpeed = lspeed2;\r\n                RmotorSpeed = rspeed2;\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //DC 모터 후진편차보정 bbmotor\r\n        LineCodingBBmotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingBBmotor',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                RSPEED: 1,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func(sprite, script) {\r\n                let rspeed2 = script.getNumberValue('RSPEED', script);\r\n                let lspeed2 = script.getNumberValue('LSPEED', script);\r\n                ++LineNum;\r\n                \r\n                lspeed2 = Math.min(255, lspeed2);\r\n                lspeed2 = Math.max(0, lspeed2);\r\n                rspeed2 = Math.min(255, rspeed2);\r\n                rspeed2 = Math.max(0, rspeed2);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                    type: Entry.LineCoding.sensorTypes.LINE_BBMOTOR,\r\n                    data: {\r\n                        lspeed: lspeed2,\r\n                        rspeed: rspeed2,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n                ++LineNum;\r\n                LmotorSpeed = lspeed2;\r\n                RmotorSpeed = rspeed2;\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        //DC 모터 정지보정 motorstop\r\n        LineCodingMotorStop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['255'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'LineCodingMotorStop',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                RSPEED: 1,\r\n            },\r\n            class: 'LineCoding_LINE5',\r\n            isNotFor: ['LineCoding'],\r\n            func(sprite, script) {\r\n                let rspeed2 = script.getNumberValue('RSPEED', script);\r\n                let lspeed2 = script.getNumberValue('LSPEED', script);\r\n                \r\n                lspeed2 = Math.min(255, lspeed2);\r\n                lspeed2 = Math.max(0, lspeed2);\r\n                rspeed2 = Math.min(255, rspeed2);\r\n                rspeed2 = Math.max(0, rspeed2);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n\r\n                ++LineNum;\r\n                Entry.hw.sendQueue.SET[parseInt(LineNum, 10)] = {\r\n                    type: Entry.LineCoding.sensorTypes.LINE_MOTORSTOP,\r\n                    data: {\r\n                        lspeed: lspeed2,\r\n                        rspeed: rspeed2,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n                ++LineNum;\r\n                LmotorSpeed = lspeed2;\r\n                RmotorSpeed = rspeed2;\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n    };\r\n};\r\nmodule.exports = Entry.LineCoding;"
  },
  {
    "path": "src/playground/blocks/hardware/block_Lline.js",
    "content": "'use strict';\n\nEntry.Lline = {\n    id: '6C.1',\n    name: 'Lline',\n    url: 'https://Lline.co.kr/',\n    imageName: 'Lline.png',\n    title: {\n        ko: '엘라인',\n        en: 'Lline',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        METRIX: 9, //점찍는거\n        // 10은 비어있음\n        METRIXCLEAR: 11,\n        METRIXROWCOLCLEAR: 12,\n        METRIXDRAW: 13,\n        NEOPIXEL: 14,\n        NEOPIXELCLEAR: 15,\n        NEOPIXELINIT: 16,\n        NEOPIXELRAINBOW: 17,\n        NEOPIXELEACH: 18,\n\n        LCDINIT: 19,\n        LCD_BACKLIGHT:20,\n        LCD: 21,\n        LCDCLEAR: 22,\n\n\n        TEMPCHECK: 23,\n        HUMICHECK: 24,\n    \n        // Stepper Motor 관련 추가\n        STEPPER_INIT: 25,       // steps & pin 설정\n        STEPPER_SPEED: 26,      // 속도 설정\n        STEPPER_STEP: 27,       // 회전\n        STEPPER_STOP: 28,        // 정지\n\n        IR: 29,  // 적외선센서\n        \n        COLOR_SENSOR_INIT: 30,\n        COLOR_SENSOR: 31,\n        \n        DC_MOTOR_INIT: 32,\n        DC_MOTOR_CONTROL: 33,\n        \n        DC_MOTOR_INIT2: 40,\n        DC_MOTOR_CONTROL2: 41,\n\n\n        HC06_INIT: 34,\n        HC06_SEND: 35,\n        HC06_RECEIVE: 36,\n\n\n        HM10_INIT: 37,\n        HM10_SEND: 38,\n        HM10_RECEIVE: 39,\n\n\n    },\n    \n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3, \n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.Lline.setLanguage = function() {\n\n    return {\n        ko: {\n            template: {\n                arduino_Lline_get_analog_value: '아날로그 %1 번 센서값',\n                arduino_Lline_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                arduino_Lline_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                arduino_Lline_toggle_led: '디지털 %1 번 핀 %2 %3',\n                arduino_Lline_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                arduino_Lline_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                arduino_Lline_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                arduino_Lline_get_digital: '디지털 %1 번 센서값',\n\n                arduino_Lline_get_temp: '온습도 센서 %1 온도 값 ',\n                arduino_Lline_get_humi: '온습도 센서 %1 습도 값 ',\n\n                arduino_Lline_set_neopixel_init: '네오픽셀 설정 (%1 핀) led %2 개를 %3 밝기로 설정하기 %4',\n                arduino_Lline_set_neopixel: '네오픽셀 (%1 핀) RGB ( %2, %3, %4) %5',\n                arduino_Lline_set_neopixel_each: '네오픽셀(%1 핀) LED (%2 번 쨰) RGB ( %3, %4, %5) %6',\n                arduino_Lline_set_neopixel_rainbow: '무지개 표현하기 (%1 핀)',\n                arduino_Lline_set_neopixel_clear: '네오픽셀 지우기 (%1 핀) %2',\n\n                arduino_Lline_set_metrix: '도트매트릭스 그리기 (열 %1 - 행 %2) %3',\n                arduino_Lline_set_metrix_draw: '도트매트릭스 그리기 %1 %2',\n                arduino_Lline_set_metrix_rowcol_clear: '도트매트릭스 지우기 (열 %1 - 행 %2) %3',\n                arduino_Lline_set_metrix_clear: '도트매트릭스 전체 지우기 %1',\n\n                arduino_Lline_set_lcd_init: 'I2C LCD 초기화 (주소 %1, 열: 16, 행: 2) %2',\n                arduino_Lline_lcd_backlight: 'LCD 백라이트 %1 ',\n                arduino_Lline_lcd_row_col: 'LCD %1 행 %2 열 부터 \"%3\" 출력 %4',\n                arduino_Lline_lcd_clear: 'LCD 화면 지우기 %1',\n\n\n                 // 스텝모터 관련\n                arduino_Lline_stepper_init: '스텝모터 핀 steps/rev: %1 PIN1: %2 PIN2: %3 PIN3: %4 PIN4: %5 설정',\n                arduino_Lline_stepper_speed: '스텝모터 속도 %1 rpm 설정 %2',\n                arduino_Lline_stepper_step: '스텝모터 %1 스텝 회전 %2',\n                arduino_Lline_stepper_stop: '스텝모터 정지 %1',\n\n                arduino_Lline_get_ir_value: '적외선 센서 %1 센서값',\n\n                arduino_Lline_init_color_sensor: '컬러 센서 초기화 (S0: %1, S1: %2, S2: %3, S3: %4, OUT: %5, LED: %6)',\n                arduino_Lline_get_color_rgb: '컬러 센서에서 %1 값 읽기',\n                \n\n                //블루투스 HM10\n                arduino_Lline_hm10_init: 'HM-10 연결 설정 TX: %1 RX: %2',\n                arduino_Lline_hm10_send: 'HM-10 데이터 보내기 %1',\n                arduino_Lline_hm10_receive: 'HM-10 수신 데이터',\n\n                arduino_Lline_hc06_init: 'HC-06 연결 설정 TX: %1 RX: %2',\n                arduino_Lline_hc06_send: 'HC-06 데이터 보내기 %1',\n                arduino_Lline_hc06_receive: 'HC-06 수신 데이터',\n\n                arduino_Lline_DC_motor_init: 'DC 모터A 설정 EN: %1 IN1: %2 IN2: %3',\n                arduino_Lline_DC_motor_control: 'DC 모터A  %1 속도 %2',\n\n                arduino_Lline_DC_motor_init2: 'DC 모터B 설정 EN: %1 IN3: %2 IN4: %3',\n                arduino_Lline_DC_motor_control2: 'DC 모터B  %1 속도 %2',\n\n                \n\n            \n\n            },\n        },\n        en: {\n            template: {\n                arduino_Lline_get_analog_value: 'Analog %1 Sensor value',\n                arduino_Lline_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                arduino_Lline_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                arduino_Lline_toggle_led: 'Digital %1 Pin %2 %3',\n                arduino_Lline_digital_pwm: 'Digital %1 Pin %2 %3',\n                arduino_Lline_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                arduino_Lline_set_servo: 'Set servo pin %1 angle as %2 %3',\n                arduino_Lline_get_digital: 'Digital %1 Sensor value',\n\n                arduino_Lline_get_temp: '온습도 센서 %1 온도 값 ',\n                arduino_Lline_get_humi: '온습도 센서 %1 습도 값 ',\n\n\n                arduino_Lline_set_neopixel_init: 'set neopixel pin: %1 led-count: %2 bright: %3 %4',\n                arduino_Lline_set_neopixel: 'neopixel pin: %1 (R:%2 G:%3 B:%4) %5',\n                arduino_Lline_set_neopixel_each: 'neopixel pin: %1 LED %2 RGB ( %3, %4, %5) %6',\n                arduino_Lline_set_neopixel_rainbow: 'neopixel pin: %1 %2 %4',\n                arduino_Lline_set_neopixel_clear: 'clear neopixel pin: %1 %2',\n\n                arduino_Lline_set_metrix: '8x8 paint dot-merix (row : %1, col: %2) %3',\n                arduino_Lline_set_metrix_draw: '8x8 paint dot-merix %1 %2',\n                arduino_Lline_set_metrix_rowcol_clear: 'Clear dot-metrix (row : %1, col: %2) %3',\n                arduino_Lline_set_metrix_clear: 'Clear all dot-metrix %1',\n\n                arduino_Lline_set_lcd_init: 'I2C LCD 초기화 (주소 %1, 열: 16, 행: 2) %2',\n                arduino_Lline_lcd_backlight: 'LCD 백라이트 %1 ',\n                arduino_Lline_lcd_row_col: 'LCD %1 행 %2 열 부터 \"%3\" 출력 %4',\n                arduino_Lline_lcd_clear: 'LCD 화면 지우기 %1',\n\n\n                // Stepper motor related\n                arduino_Lline_stepper_init: 'Setup Stepper motor pins (%1, %2, %3, %4) steps/rev: %5 %6',\n                arduino_Lline_stepper_speed: 'Set stepper motor speed to %1 rpm %2',\n                arduino_Lline_stepper_step: 'Rotate stepper motor %1 steps %2',\n                arduino_Lline_stepper_stop: 'Stop stepper motor %1',\n\n                arduino_Lline_get_ir_value: 'IR Sensor value from %1',\n\n                arduino_Lline_init_color_sensor: 'Initialize color sensor (S0: %1, S1: %2, S2: %3, S3: %4, OUT: %5, LED: %6)',\n                arduino_Lline_get_color_rgb: 'Read color sensor %1 value',\n\n                arduino_Lline_hm10_init: 'Setup HM-10 TX: %1 RX: %2',\n                arduino_Lline_hm10_send: 'Send HM-10 data %1',\n                arduino_Lline_hm10_receive: 'HM-10 received data',\n\n\n                arduino_Lline_hc06_init: 'Setup HC-06 TX: %1 RX: %2',\n                arduino_Lline_hc06_send: 'Send HC-06 data %1',\n                arduino_Lline_hc06_receive: 'HC-06 received data',\n\n                arduino_Lline_DC_motor_init: 'Setup DC motorA EN: %1 IN1: %2 IN2: %3',\n                arduino_Lline_DC_motor_control: 'DC motor A %1 speed %2',\n\n                arduino_Lline_DC_motor_init2: 'Setup DC motorB EN: %1 IN3: %2 IN4: %3',\n                arduino_Lline_DC_motor_control2: 'DC motor B %1 speed %2',\n\n\n\n\n              \n               \n            },\n        },\n    };\n};\n\nEntry.Lline.blockMenuBlocks = [\n    'arduino_Lline_get_analog_value',\n    'arduino_Lline_get_analog_value_map',\n    'arduino_Lline_get_ultrasonic_value',\n    'arduino_Lline_get_digital',\n    'arduino_Lline_toggle_led',\n    'arduino_Lline_digital_pwm',\n    'arduino_Lline_set_servo',\n    'arduino_Lline_set_tone',\n    'arduino_Lline_get_temp',\n    'arduino_Lline_get_humi',\n    'arduino_Lline_set_neopixel_init',\n    'arduino_Lline_set_neopixel',\n    'arduino_Lline_set_neopixel_each',\n    'arduino_Lline_set_neopixel_rainbow',\n    'arduino_Lline_set_neopixel_clear',\n    'arduino_Lline_set_metrix',\n    'arduino_Lline_set_metrix_draw',\n    'arduino_Lline_set_metrix_rowcol_clear',\n    'arduino_Lline_set_metrix_clear',\n    'arduino_Lline_set_lcd_init',\n    'arduino_Lline_lcd_backlight',\n    'arduino_Lline_lcd_row_col',\n    'arduino_Lline_lcd_clear',\n\n    // ✅ 스텝모터 관련 블록 추가\n    'arduino_Lline_stepper_init',\n    'arduino_Lline_stepper_speed',\n    'arduino_Lline_stepper_step',\n    'arduino_Lline_stepper_stop',\n    \n    'arduino_Lline_get_ir_value',\n\n    'arduino_Lline_init_color_sensor',\n    'arduino_Lline_get_color_rgb',\n\n    'arduino_Lline_hm10_init',\n    'arduino_Lline_hm10_send',\n    'arduino_Lline_hm10_receive',\n\n\n    'arduino_Lline_hc06_init',\n    'arduino_Lline_hc06_send',\n    'arduino_Lline_hc06_receive',\n\n    'arduino_Lline_DC_motor_init',\n    'arduino_Lline_DC_motor_control',\n\n    'arduino_Lline_DC_motor_init2',\n    'arduino_Lline_DC_motor_control2',\n\n\n\n   \n];\n\n//region Lline 아두이노 확장모드\nEntry.Lline.getBlocks = function() {\n    return {\n        arduino_Lline_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_Lline_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_Lline_analog_list',\n                    },\n                ],\n            },\n        },\n        arduino_Lline_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_Lline_analog_list',\n                    },\n                ],\n                type: 'arduino_Lline_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_Lline_get_analog_value',\n                        params: [\n                            {\n                                type: 'arduino_Lline_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'arduino_Lline_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['5'],\n                    },\n                ],\n                type: 'arduino_Lline_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                \n\n\n                Entry.hw.sendQueue.GET[Entry.Lline.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                \n\n\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'arduino_Lline_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Lline' || name === 'ArduinoNano') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Lline.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_get_digital_toggle[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_digital_toggle',\n                    },\n                ],\n            },\n        },\n        arduino_Lline_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'arduino_Lline_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Lline.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Lline.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Lline.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'arduino_Lline_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Lline.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_Lline_tone_list',\n                    },\n                ],\n            },\n        },\n        arduino_Lline_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_Lline_tone_list',\n                    },\n                ],\n                type: 'arduino_Lline_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'arduino_Lline_tone_value',\n                    },\n                ],\n            },\n        },\n        arduino_Lline_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'arduino_Lline_octave_list',\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_Lline_tone_list',\n                    },\n                    {\n                        type: 'arduino_Lline_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'arduino_Lline_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.Lline.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.Lline.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.Lline.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_neopixel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    {\n                        type: 'number',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                ],\n                type: 'arduino_Lline_set_neopixel_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value1 = script.getNumberValue('VALUE1', script);\n                let value2 = script.getNumberValue('VALUE2', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.NEOPIXELINIT,\n                        data:{value1,value2},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixel_init(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_Lline_set_neopixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                R: 1,\n                G: 2,\n                B: 3,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let R_val = script.getNumberValue('R', script);\n                let G_val = script.getNumberValue('G', script);\n                let B_val = script.getNumberValue('B', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.NEOPIXEL,\n                        data:{R_val,G_val,B_val},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixel(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_neopixel_each: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_Lline_set_neopixel_each',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                CNT: 1,\n                R: 2,\n                G: 3,\n                B: 4,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let CNT_val = script.getNumberValue('CNT', script);\n                let R_val = script.getNumberValue('R', script);\n                let G_val = script.getNumberValue('G', script);\n                let B_val = script.getNumberValue('B', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.NEOPIXELEACH,\n                        data:{CNT_val,R_val,G_val,B_val},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixel_each(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_neopixel_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['무지개', '1'],\n                        ['조명효과', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['무지개', '1'],\n                                    ['조명효과', '2'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_Lline_set_neopixel_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_Lline_set_neopixel_list',\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_neopixel_rainbow: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [ \n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_Lline_set_neopixel_rainbow',\n            },\n            paramsKeyMap: {\n                PORT : 0,\n                VALUE: 1,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.NEOPIXELRAINBOW,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixel_rainbow(%1)',\n                        \n                        textParams: \n                        [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ]\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_neopixel_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    \n                ],\n                type: 'arduino_Lline_set_neopixel_clear',\n            },\n            paramsKeyMap: {\n                PORT : 0,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port =  script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.NEOPIXELCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    { \n\n                        syntax: 'Arduino.neopixeclear(%1)',\n                        textParams: \n                        [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ]\n                    }\n                ],\n            },\n        },\n        arduino_Lline_set_metrix: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_Lline_set_metrix',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let value1 = script.getNumberValue('VALUE1', script) +10;\n                let value2 = script.getNumberValue('VALUE2', script) + 10;\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[12] = {\n                        type: Entry.Lline.sensorTypes.METRIX,\n                        data:{value1,value2},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.metrix(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_metrix_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '10'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '10'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_Lline_set_metrix_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_Lline_set_metrix_list',\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_metrix_draw: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [ \n                    {\n                        type: 'arduino_Lline_set_metrix_list',\n                    }\n                ],\n                type: 'arduino_Lline_set_metrix_draw',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                let value = script.getNumberValue('VALUE', script);\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n\n                    sq.SET[12] = {\n                        type: Entry.Lline.sensorTypes.METRIXDRAW,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.draw(%1)',\n                        textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ]\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_metrix_rowcol_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_Lline_set_metrix_rowcol_clear',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let value1 = script.getNumberValue('VALUE1', script) + 10;\n                let value2 = script.getNumberValue('VALUE2', script) + 10;\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[12] = {\n                        type: Entry.Lline.sensorTypes.METRIXROWCOLCLEAR,\n                        data:{value1,value2},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.metrix_rowcol_clear(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_Lline_set_metrix_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    \n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \n                ],\n                type: 'arduino_Lline_set_metrix_clear',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12;\n\n                if (!script.isStart) {\n             \n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.METRIXCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    { }\n                ],\n            },\n        },\n        arduino_Lline_lcd_list_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x27', '0'],\n                        ['0x3F', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        arduino_Lline_lcd_row_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        arduino_Lline_lcd_col_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        arduino_Lline_set_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_Lline_lcd_list_init',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_Lline_set_lcd_init',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const list = script.getNumberValue('LIST', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n \n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n\n                    sq.SET[1] = {\n                        type: Entry.Lline.sensorTypes.LCDINIT,\n                        data: {\n                            list: list,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.lcd_init(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        arduino_Lline_lcd_backlight: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'arduino_get_digital_toggle', // 기존 토글 블럭\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],  // 기본은 ON\n                    },\n                    null,\n                ],\n                type: 'arduino_Lline_lcd_backlight',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const lcdAddress = 0x27;  // 고정 주소 또는 39\n\n                let value = script.getValue('VALUE');  // 'on' / 'off' 가져옴\n                if (typeof value === 'string') value = value.toLowerCase();\n\n                if (Entry.Lline.highList.indexOf(value) > -1) {\n                    value = 1;\n                } else if (Entry.Lline.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    value = 0;  // 기본 OFF 처리\n                }\n\n                if (!sq.SET) sq.SET = {};\n\n                sq.SET[1] = {\n                    type: Entry.Lline.sensorTypes.LCD_BACKLIGHT,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.lcd_backlight(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n\n\n\n\n\n\n\n        arduino_Lline_lcd_row_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [ \n                    {\n                        type: 'arduino_Lline_lcd_row_list',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'arduino_Lline_lcd_col_list',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Lline'],\n                    },\n                ],\n                type: 'arduino_Lline_lcd_row_col',\n            },\n            paramsKeyMap: {\n                ROW: 0,\n                COL: 1,\n                VALUE: 2,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                let row = script.getNumberValue('ROW', script);\n                let col = script.getNumberValue('COL', script);\n                let value = script.getValue('VALUE', script);\n                value += '';\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n\n                    sq.SET[1] = {\n                        type: Entry.Lline.sensorTypes.LCD,\n                        data: {row, col, value},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.lcd(%1,%2,%3)',\n                        textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ]\n                    },\n                ],\n            },\n        },\n        arduino_Lline_lcd_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    \n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \n                ],\n                type: 'arduino_Lline_lcd_clear',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 1;\n\n                if (!script.isStart) {\n            \n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Lline.sensorTypes.LCDCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    { }\n                ],\n            },\n        },\n        arduino_Lline_get_temp: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'arduino_Lline_analog_list',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_Lline_analog_list',\n                    },\n                ],\n                type: 'arduino_Lline_get_temp',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const port = Number(script.getValue('PORT', script));\n                const tempValue = Entry.hw.portData.TEMPCHECK || 0;\n        \n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n        \n                Entry.hw.sendQueue.GET[Entry.Lline.sensorTypes.TEMPCHECK] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n        \n                return tempValue;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.temp_read(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        \n        \n\n        arduino_Lline_get_humi: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'arduino_Lline_analog_list',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_Lline_analog_list',\n                    },\n                ],\n                type: 'arduino_Lline_get_humi',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const port = Number(script.getValue('PORT', script));  // 드롭다운 값 받아오기\n                const humiValue = Entry.hw.portData.HUMICHECK || 0;\n        \n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n        \n                Entry.hw.sendQueue.GET[Entry.Lline.sensorTypes.HUMICHECK] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n        \n                return humiValue;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.humi_read(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        \n        \n\n        \n\n        arduino_Lline_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'arduino_Lline_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Lline',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.Lline.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        arduino_Lline_stepper_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                }, // steps/rev 입력칸\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10'], ['11','11'], ['12','12'], ['13','13']],\n                    value: '8',\n                }, // PIN1\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10'], ['11','11'], ['12','12'], ['13','13']],\n                    value: '9',\n                }, // PIN2\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10'], ['11','11'], ['12','12'], ['13','13']],\n                    value: '10',\n                }, // PIN3\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10'], ['11','11'], ['12','12'], ['13','13']],\n                    value: '11',\n                }, // PIN4\n            ],\n            def: {\n                params: [\n                    { type: 'text', params: ['200'] },\n                    { type: 'Dropdown', value: '8' },\n                    { type: 'Dropdown', value: '9' },\n                    { type: 'Dropdown', value: '10' },\n                    { type: 'Dropdown', value: '11' },\n                ],\n                type: 'arduino_Lline_stepper_init',\n            },\n            paramsKeyMap: {\n                STEPS: 0,\n                PIN1: 1,\n                PIN2: 2,\n                PIN3: 3,\n                PIN4: 4,\n            },\n            class: 'LlineMotor',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const steps = script.getNumberValue('STEPS');\n\n                const pin1 = Number(script.getField('PIN1'));\n                const pin2 = Number(script.getField('PIN2'));\n                const pin3 = Number(script.getField('PIN3'));\n                const pin4 = Number(script.getField('PIN4'));\n\n                if (\n                    isNaN(steps) || steps <= 0 ||\n                    isNaN(pin1) || isNaN(pin2) || isNaN(pin3) || isNaN(pin4)\n                ) {\n                    console.warn('❗ [STEPPER_INIT] 유효하지 않은 값:', {\n                        steps, pins: [pin1, pin2, pin3, pin4]\n                    });\n                    return script.callReturn();\n                }\n\n                if (!sq.SET) sq.SET = {};\n                sq.SET[1] = {\n                    type: Entry.Lline.sensorTypes.STEPPER_INIT,\n                    data: {\n                        steps,\n                        pins: [pin1, pin2, pin3, pin4],\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n\n            syntax: {\n                text: '스텝모터 설정 steps/rev: %1 PIN1: %2 PIN2: %3 PIN3: %4 PIN4: %5',\n                textParams: [\n                  { type: 'Block', name: 'STEPS' },\n                  { type: 'Dropdown', name: 'PIN1' },\n                  { type: 'Dropdown', name: 'PIN2' },\n                  { type: 'Dropdown', name: 'PIN3' },\n                  { type: 'Dropdown', name: 'PIN4' },\n                ],\n              },\n              \n        },\n        \n        \n        \n        \n        \n        \n        \n        \n        \n        \n\n        arduino_Lline_stepper_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    name: 'SPEED',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { type: 'text', params: ['60'] },\n                    null,\n                ],\n                type: 'arduino_Lline_stepper_speed',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'LlineMotor',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const speed = script.getNumberValue('SPEED');\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.STEPPER_SPEED,\n                    data: { speed },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        \n\n        \n        arduino_Lline_stepper_step: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    name: 'STEP',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { type: 'text', params: ['200'] },\n                    null,\n                ],\n                type: 'arduino_Lline_stepper_step',\n            },\n            paramsKeyMap: {\n                STEP: 0,\n            },\n            class: 'LlineMotor',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const step = script.getNumberValue('STEP');\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.STEPPER_STEP,\n                    data: { step },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        \n\n        \n        arduino_Lline_stepper_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'arduino_Lline_stepper_stop',\n            },\n            class: 'LlineMotor',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.STEPPER_STOP,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        \n        \n\n        \n        arduino_Lline_get_ir_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'arduino_Lline_get_ir_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const port = Number(script.getField('PORT'));\n                const value = Entry.hw.portData.IR || 0;\n        \n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n        \n                Entry.hw.sendQueue.GET[Entry.Lline.sensorTypes.IR] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n        \n                return value;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ir_read(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        \n        \n\n        arduino_Lline_init_color_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8']],\n                    value: '6',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8']],\n                    value: '5',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8']],\n                    value: '4',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8']],\n                    value: '3',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8']],\n                    value: '2',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8']],\n                    value: '7',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    { type: 'Dropdown', value: '6' },\n                    { type: 'Dropdown', value: '5' },\n                    { type: 'Dropdown', value: '4' },\n                    { type: 'Dropdown', value: '3' },\n                    { type: 'Dropdown', value: '2' },\n                    { type: 'Dropdown', value: '7' },\n                ],\n                type: 'arduino_Lline_init_color_sensor',\n            },\n            paramsKeyMap: {\n                S0: 0,\n                S1: 1,\n                S2: 2,\n                S3: 3,\n                OUT: 4,\n                LED: 5,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const s0 = Number(script.getField('S0'));\n                const s1 = Number(script.getField('S1'));\n                const s2 = Number(script.getField('S2'));\n                const s3 = Number(script.getField('S3'));\n                const out = Number(script.getField('OUT'));\n                const led = Number(script.getField('LED'));\n\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.COLOR_SENSOR_INIT,\n                    data: {\n                        s0,\n                        s1,\n                        s2,\n                        s3,\n                        out,\n                        led,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.init_color_sensor(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            { type: 'Dropdown', options: [['2','2'],['3','3'],['4','4'],['5','5'],['6','6']], value: '6' },\n                            { type: 'Dropdown', options: [['2','2'],['3','3'],['4','4'],['5','5'],['6','6']], value: '5' },\n                            { type: 'Dropdown', options: [['2','2'],['3','3'],['4','4'],['5','5'],['6','6']], value: '4' },\n                            { type: 'Dropdown', options: [['2','2'],['3','3'],['4','4'],['5','5'],['6','6']], value: '3' },\n                            { type: 'Dropdown', options: [['2','2'],['3','3'],['4','4'],['5','5'],['6','6']], value: '2' },\n                            { type: 'Dropdown', options: [['2','2'],['3','3'],['4','4'],['5','5'],['6','6']], value: '7' },\n                        ],\n                    },\n                ],\n            },\n        },\n\n\n        arduino_Lline_get_color_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Red', 'R'],\n                        ['Green', 'G'],\n                        ['Blue', 'B'],\n                    ],\n                    value: 'R',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'arduino_Lline_get_color_rgb',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'LlineGet',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const color = script.getField('COLOR');\n                const colorObj = Entry.hw.portData.COLOR || {}; // COLOR: {R, G, B}\n        \n                \n                 // colorIndex: R=0, G=1, B=2로 매핑\n                const colorIndexMap = { R: 0, G: 1, B: 2 };\n                const colorIndex = colorIndexMap[color];\n\n\n                if (!Entry.hw.sendQueue.GET) Entry.hw.sendQueue.GET = {};\n                Entry.hw.sendQueue.GET[Entry.Lline.sensorTypes.COLOR_SENSOR] = {\n                    port: [1],\n                    data: colorIndex,\n                    time: new Date().getTime(),\n                };\n        \n                return colorObj[color] || 0; // colorObj['R'], 'G', 'B'\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.color_read(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Red', 'R'],\n                                    ['Green', 'G'],\n                                    ['Blue', 'B'],\n                                ],\n                                value: 'R',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n\n        \n        \n        \n\n        arduino_Lline_hm10_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['0', '0'], ['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'], ['9', '9']],\n                    value: '0',\n                }, // TX 핀\n                {\n                    type: 'Dropdown',\n                    options: [['0', '0'], ['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'], ['9', '9']],\n                    value: '1',\n                }, // RX 핀\n            ],\n            def: {\n                params: [\n                    { type: 'Dropdown', value: '0' },\n                    { type: 'Dropdown', value: '1' },\n                ],\n                type: 'arduino_Lline_hm10_init',\n            },\n            paramsKeyMap: {\n                TX: 0,\n                RX: 1,\n            },\n            class: 'LlineComm',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const tx = Number(script.getField('TX'));\n                const rx = Number(script.getField('RX'));\n        \n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.HM10_INIT,\n                    data: { tx, rx },\n                    time: new Date().getTime(),\n                };\n        \n                return script.callReturn();\n            },\n            syntax: {\n                text: 'HM-10 연결 설정 TX: %1 RX: %2',\n                textParams: [\n                    { type: 'Dropdown', name: 'TX' },\n                    { type: 'Dropdown', name: 'RX' },\n                ],\n            },\n        },\n\n\n        arduino_Lline_hm10_send: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                { type: 'Block', accept: 'string' }, // 보낼 문자열\n            ],\n            def: {\n                params: [\n                    { type: 'text', params: ['Hello'] },\n                ],\n                type: 'arduino_Lline_hm10_send',\n            },\n            paramsKeyMap: {\n                DATA: 0,\n            },\n            class: 'LlineComm',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const data = script.getStringValue('DATA');\n        \n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.HM10_SEND,\n                    data: data,\n                    time: new Date().getTime(),\n                };\n        \n                return script.callReturn();\n            },\n            syntax: {\n                text: 'HM-10 데이터 보내기 %1',\n                textParams: [\n                    { type: 'Block', name: 'DATA' },\n                ],\n            },\n        },\n\n        \n        arduino_Lline_hm10_receive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            def: {\n                params: [],\n                type: 'arduino_Lline_hm10_receive',\n            },\n            class: 'LlineComm',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const value = Entry.hw.portData.HM10_RECEIVE || '';\n\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.HM10_RECEIVE,\n                    time: new Date().getTime(),\n                };\n\n\n                return value;\n            },\n            syntax: {\n                text: 'HM-10 수신 데이터',\n                textParams: [],\n            },\n        },\n\n\n\n\n        arduino_Lline_hc06_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['0', '0'], ['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'], ['9', '9']],\n                    value: '0',\n                }, // TX 핀\n                {\n                    type: 'Dropdown',\n                    options: [['0', '0'], ['1', '1'], ['2', '2'], ['3', '3'], ['4', '4'], ['5', '5'], ['6', '6'], ['7', '7'], ['8', '8'], ['9', '9']],\n                    value: '1',\n                }, // RX 핀\n            ],\n            def: {\n                params: [\n                    { type: 'Dropdown', value: '0' },\n                    { type: 'Dropdown', value: '1' },\n                ],\n                type: 'arduino_Lline_hc06_init',\n            },\n            paramsKeyMap: {\n                TX: 0,\n                RX: 1,\n            },\n            class: 'LlineComm',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const tx = Number(script.getField('TX'));\n                const rx = Number(script.getField('RX'));\n        \n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.HC06_INIT,\n                    data: { tx, rx },\n                    time: new Date().getTime(),\n                };\n        \n                return script.callReturn();\n            },\n            syntax: {\n                text: 'HC-06 연결 설정 TX: %1 RX: %2',\n                textParams: [\n                    { type: 'Dropdown', name: 'TX' },\n                    { type: 'Dropdown', name: 'RX' },\n                ],\n            },\n        },\n\n        \n\n        arduino_Lline_hc06_send: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                { type: 'Block', accept: 'string' }, // 보낼 문자열\n            ],\n            def: {\n                params: [\n                    { type: 'text', params: ['Hello'] },\n                ],\n                type: 'arduino_Lline_hc06_send',\n            },\n            paramsKeyMap: {\n                DATA: 0,\n            },\n            class: 'LlineComm',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const data = script.getStringValue('DATA');\n        \n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.HC06_SEND,\n                    data: data,\n                    time: new Date().getTime(),\n                };\n        \n                return script.callReturn();\n            },\n            syntax: {\n                text: 'HC-06 데이터 보내기 %1',\n                textParams: [\n                    { type: 'Block', name: 'DATA' },\n                ],\n            },\n        },\n        \n\n        arduino_Lline_hc06_receive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            def: {\n                params: [],\n                type: 'arduino_Lline_hc06_receive',\n            },\n            class: 'LlineComm',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const value = Entry.hw.portData.HC06_RECEIVE || '';\n\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.HC06_RECEIVE,\n                    time: new Date().getTime(),\n                };\n\n\n                return value;\n            },\n            syntax: {\n                text: 'HC-06 수신 데이터',\n                textParams: [],\n            },\n        },\n\n\n\n        arduino_Lline_DC_motor_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10']],\n                    value: '2',\n                }, // ENA\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10']],\n                    value: '3',\n                }, // A-1A\n\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10']],\n                    value: '4',\n                }, // A-1B\n               \n            ],\n            def: {\n                params: [\n                    { type: 'Dropdown', value: '2' },\n                    { type: 'Dropdown', value: '3' },\n                    { type: 'Dropdown', value: '4' },\n                ],\n                type: 'arduino_Lline_DC_motor_init',\n            },\n            paramsKeyMap: {\n                ENA: 0,\n                A1A: 1,\n                A1B: 2,\n            },\n            class: 'LlineMotor',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const ena = Number(script.getField('ENA'));\n                const a1a = Number(script.getField('A1A'));\n                const a1b = Number(script.getField('A1B'));\n                \n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.DC_MOTOR_INIT,\n                    data: { ena, a1a, a1b},\n                    time: new Date().getTime(),\n                };\n        \n                return script.callReturn();\n            },\n            syntax: {\n                text: 'DC 모터 설정 ENA: %1 IN1: %2 IN2: %3',\n                textParams: [\n                    { type: 'Dropdown', name: 'ENA' },\n                    { type: 'Dropdown', name: 'A1A' },\n                    { type: 'Dropdown', name: 'A1B' },\n                ],\n            },\n        },\n\n        \n        \n\n\n        arduino_Lline_DC_motor_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['정방향', 'FORWARD'], ['역방향', 'BACKWARD'], ['정지', 'STOP']],\n                    value: 'FORWARD',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            def: {\n                params: [\n                    { type: 'Dropdown', value: 'FORWARD' },\n                    { type: 'text', params: ['150'] },\n                ],\n                type: 'arduino_Lline_DC_motor_control',\n            },\n            paramsKeyMap: {\n                DIR_A: 0,\n                SPEED_A: 1,\n            },\n            class: 'LlineMotor',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const dirA = script.getField('DIR_A');\n                const speedA = script.getNumberValue('SPEED_A');\n                \n        \n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.DC_MOTOR_CONTROL,\n                    data: { dirA, speedA},\n                    time: new Date().getTime(),\n                };\n        \n                return script.callReturn();\n            },\n            syntax: {\n                text: 'DC 모터 A %1 속도 %2',\n                textParams: [\n                    { type: 'Dropdown', name: 'DIR_A' },\n                    { type: 'Block', name: 'SPEED_A' },\n                ],\n            },\n        },\n\n\n        arduino_Lline_DC_motor_init2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10']],\n                    value: '2',\n                }, // ENA\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10']],\n                    value: '3',\n                }, // A-1A\n\n                {\n                    type: 'Dropdown',\n                    options: [['2','2'], ['3','3'], ['4','4'], ['5','5'], ['6','6'], ['7','7'], ['8','8'], ['9','9'], ['10','10']],\n                    value: '4',\n                }, // A-1B\n               \n            ],\n            def: {\n                params: [\n                    { type: 'Dropdown', value: '2' },\n                    { type: 'Dropdown', value: '3' },\n                    { type: 'Dropdown', value: '4' },\n                ],\n                type: 'arduino_Lline_DC_motor_init2',\n            },\n            paramsKeyMap: {\n                ENB: 0,\n                B1A: 1,\n                B1B: 2,\n            },\n            class: 'LlineMotor',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const enb = Number(script.getField('ENB'));\n                const b1a = Number(script.getField('B1A'));\n                const b1b = Number(script.getField('B1B'));\n                \n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.DC_MOTOR_INIT2,\n                    data: { enb, b1a, b1b},\n                    time: new Date().getTime(),\n                };\n        \n                return script.callReturn();\n            },\n            syntax: {\n                text: 'DC 모터 설정 ENA: %1 IN3: %2 IN4: %3',\n                textParams: [\n                    { type: 'Dropdown', name: 'ENB' },\n                    { type: 'Dropdown', name: 'B1A' },\n                    { type: 'Dropdown', name: 'B1B' },\n                ],\n            },\n        },\n\n        \n        \n\n\n        arduino_Lline_DC_motor_control2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['정방향', 'FORWARD'], ['역방향', 'BACKWARD'], ['정지', 'STOP']],\n                    value: 'FORWARD',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            def: {\n                params: [\n                    { type: 'Dropdown', value: 'FORWARD' },\n                    { type: 'text', params: ['150'] },\n                ],\n                type: 'arduino_Lline_DC_motor_control2',\n            },\n            paramsKeyMap: {\n                DIR_B: 0,\n                SPEED_B: 1,\n            },\n            class: 'LlineMotor',\n            isNotFor: ['Lline'],\n            func(sprite, script) {\n                const dirB = script.getField('DIR_B');\n                const speedB = script.getNumberValue('SPEED_B');\n                \n        \n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.Lline.sensorTypes.DC_MOTOR_CONTROL2,\n                    data: { dirB, speedB},\n                    time: new Date().getTime(),\n                };\n        \n                return script.callReturn();\n            },\n            syntax: {\n                text: 'DC 모터 B %1 속도 %2',\n                textParams: [\n                    { type: 'Dropdown', name: 'DIR_B' },\n                    { type: 'Block', name: 'SPEED_B' },\n                ],\n            },\n        },\n        \n\n        \n\n        \n        \n        \n\n\n        \n\n\n        \n\n\n\n\n        \n\n    };\n};\n//endregion Lline 아두이노 확장모드\n\nmodule.exports = Entry.Lline;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_RichShield.js",
    "content": "'use strict';\n\nEntry.RichShield = {\n    id: '36.2',\n    name: 'RichShield',\n    url: 'https://gorillacell.kr/',\n    imageName: 'RichShield.png',\n    title: {\n        ko: '아두이노 부자실드',\n        en: 'Arduino RichShield',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                if (Entry.hw.sendQueue.SET[key].type == Entry.RichShield.sensorTypes.DCMOTOR) {\n                    Entry.hw.sendQueue.SET[key].data.value1 = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else {\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.hw.sendQueue.GET = {};\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        READ_BLUETOOTH: 9,\n        WRITE_BLUETOOTH: 10,\n        LCD: 11,\n        DHT: 12,\n        DCMOTOR: 13,\n        OLED: 14,\n        PIR: 15,\n        FND: 16,\n        IRREMOTE : 19,\n        DHT2 : 17,\n        RGBLED: 18,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.RichShield.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n                RichShield_pulldown: '기본',\n                RichShield_pullup: '풀업',\n                chocopi_control_event_pressed: '누를 때',\n                chocopi_control_event_released: '뗄 때',\n                chocopi_joystick_X: '조이스틱 좌우',\n                chocopi_joystick_Y: '조이스틱 상하',\n                chocopi_motion_photogate_event_blocked: '막았을 때',\n                chocopi_motion_photogate_event_unblocked: '열었을 때',\n                chocopi_motion_photogate_time_blocked: '막은 시간',\n                chocopi_motion_photogate_time_unblocked: '연 시간',\n                chocopi_motion_angle_x: '각도X',\n                chocopi_motion_angle_y: '각도Y',\n                chocopi_motion_angle_z: '각도Z',\n                chocopi_port: '포트',\n                chocopi_pot: '볼륨',\n                chocopi_touch_event_touch: '만질 때',\n                chocopi_touch_event_untouch: '뗄 때',\n                RichShield_lcd_first_line: '첫 번째',\n                RichShield_lcd_seconds_line: '두 번째',\n                RichShield_toggle_on: '켜기',\n                RichShield_toggle_off: '끄기',\n            },\n            template: {\n                RichShield_get_Analog_value: '아날로그 %1 번 핀의 값',\n                RichShield_set_digital_toggle: '디지털 %1 번 핀 %2 %3',\n                RichShield_get_digital: '디지털 %1 번 핀 센서 %2 값',\n                RichShield_get_digital_toggle: '디지털 %1 번 핀 센서 %2 값',\n                RichShield_set_digital_pwm: '디지털 PWM %1 번 핀을 %2 (으)로 정하기 %3',\n\n                RichShield_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n\n                RichShield_set_digital_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                RichShield_set_digital_buzzer: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n\n                RichShield_rgbled_event: '네오픽셀 ( 8 Cell ) - 디지털 13번 핀',\n                RichShield_rgbled_clr: '네오픽셀  off',\n                RichShield_rgbled_set: '%1번 네오픽셀을 빨강 %2 초록 %3 파랑 %4 로 정하기 %5',\n                RichShield_rgbled_show: '네오픽셀 적용(표시)',\n\n                RichShield_LCD_event: 'LCD Display(1602-)-I2C',\n                RichShield_LCD_Control_init: 'LCD %1 번 : 주소 %2 로 설정',\n                RichShield_LCD_Control_Display: 'LCD %1 번 : %2 행 %3 열에 %4 출력 %5',\n                RichShield_LCD_Control_Clear: 'LCD %1 번 : 지우기',\n                RichShield_LCD_Control_Scroll: 'LCD %1 번 : 화면스크롤 %2',\n\n                RichShield_FND_event: 'FND 4digit (TM1637)- CLK:D5, DIO:D4',\n                RichShield_FND_Control_init: 'FND %1 번 : 디지털 CLK %2, DIO %3 번 핀으로 설정',\n                RichShield_FND_Control_diplay_brightness: 'FND %1 번 : 밝기 %2 단계로 설정',\n                RichShield_FND_Control_display_onoff: 'FND %1 번 : 전원 %2',\n                RichShield_FND_Control_diplay_char:\n                    'FND %1 번 : %2 출력하기:나머지0채우기 %3  %4 초 대기',\n                RichShield_DHT_event: '온습도센서(DHT11/22)-디지털 12번 핀',\n                RichShield_DHT_Control_Init_Process: '온습도 %1 번 : 디지털 %2 번 핀 / 버전 %3',\n                RichShield_DHT_Control_Get_Temper: '온습도 %1 번  온도값  읽기',\n                RichShield_DHT2: '온습도 %1 번 : 습도값 읽기',\n\n                RichShield_OLED_event: 'OLED Display(0.96\"16*08)-I2C',\n                RichShield_OLED_init: 'OLED : I2C 주소 0X3C로 설정하고, 초기화',\n                RichShield_OLED_Display_String: 'OLED : %1 행, %2 열 %3 출력',\n\n                RichShield_IRREMOTE_event: '적외선수신-RECV',\n                RichShield_IRREMOTE_init: '적외선 %1번: 디지털 %2번 핀으로 설정~',\n                RichShield_IRREMOTE_recv: '적외선 %1 번: 자료 읽기',\n\n            },\n\n        },\n        en: {\n            Blocks: {\n                RichShield_pulldown: 'Pull Down',\n                RichShield_pullup: 'Pull Up',\n                chocopi_control_event_pressed: 'pressed',\n                chocopi_control_event_released: 'released',\n                chocopi_joystick_X: 'joystick X',\n                chocopi_joystick_Y: 'joystick Y',\n                chocopi_motion_photogate_event_blocked: 'blocked',\n                chocopi_motion_photogate_event_unblocked: 'unblocked',\n                chocopi_motion_photogate_time_blocked: 'blocked',\n                chocopi_motion_photogate_time_unblocked: 'unblocked',\n                chocopi_motion_angle_x: 'angle X',\n                chocopi_motion_angle_y: 'angle Y',\n                chocopi_motion_angle_z: 'angle Z',\n                chocopi_port: 'P',\n                chocopi_pot: 'potentiometer',\n                chocopi_touch_event_touch: 'touched',\n                chocopi_touch_event_untouch: 'untouched',\n                RichShield_lcd_first_line: 'first',\n                RichShield_lcd_seconds_line: 'second',\n                RichShield_toggle_on: 'on',\n                RichShield_toggle_off: 'off',\n            },\n            template: {\n                RichShield_get_Analog_value: 'Get Analog %1 pin value',\n                RichShield_set_digital_toggle: 'Digital %1 pin %2 %3',\n                RichShield_get_digital: 'Digital %1 pin sensor value %2',\n                RichShield_get_digital_toggle: 'Digital %1 pin sensor value %2',\n                RichShield_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n\n                RichShield_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n\n                RichShield_set_digital_servo: 'Set servo pin %1 angle as %2 %3',\n                RichShield_set_digital_buzzer: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n\n                RichShield_rgbled_event: 'NeoPixel ( 8 Cell ) - Digital 13 pin',\n                RichShield_rgbled_clr: 'NeoPixel off',\n                RichShield_rgbled_set: '#%1 NeoPixel Red %2 Green %3 Blue %4 %5',\n                RichShield_rgbled_show: 'NeoPixel Update',\n\n                RichShield_LCD_event: 'LCD Display(1602-)-I2C',\n                RichShield_LCD_Control_init: 'LCD %1 :  Address set to %2',\n                RichShield_LCD_Control_Display: 'LCD %1  : row %2  column %3 display %4 %5',\n                RichShield_LCD_Control_Clear: 'LCD %1 : Clear Display',\n                RichShield_LCD_Control_Scroll: 'LCD %1 : Display Scroll to %2',\n\n                RichShield_FND_event: 'FND 4digit (TM1637)- CLK:D5, DIO:D4',\n                RichShield_FND_Control_init: 'FND %1 : Digital CLK %2  , DIO %3 pin setting',\n                RichShield_FND_Control_diplay_brightness: 'FND %1 : Brightness %2 level setting',\n                RichShield_FND_Control_display_onoff: 'FND %1 : Power %2',\n                RichShield_FND_Control_diplay_char:\n                    'FND %1 : %2 display:zero-fill %3  %4 sec waiting',\n                RichShield_DHT_event: 'Humidity/Temperature(DHT11/22)-Digital 12 pin',\n                RichShield_DHT_Control_Init_Process:\n                    'Humidity/Temperature %1 : Digital %2 Pin, Version %3',\n                RichShield_DHT_Control_Get_Temper: 'DHT %1 : read Temperature',\n                RichShield_DHT2: 'DHT %1 : read Humid',\n\n                RichShield_OLED_event: 'OLED Display(0.96\"16*08)-I2C',\n                RichShield_OLED_init: 'OLED : I2C adress 0X3C set, initialize',\n                RichShield_OLED_Display_String: 'OLED : %1 Row, %2 Col %3 Display',\n\n                RichShield_IRREMOTE_event: 'IR RECV-RECV pin:D2',\n                RichShield_IRREMOTE_init: 'IR %1 : Digital recv pin set to %2',\n                RichShield_IRREMOTE_recv: 'IR %1 : IR recv',\n\n            },\n         },\n    };\n};\n\nEntry.RichShield.blockMenuBlocks = [\n    'RichShield_get_digital',\n    'RichShield_get_Analog_value',\n    'RichShield_get_digital_toggle',\n    'RichShield_get_digital_ultrasonic',\n\n    'RichShield_set_digital_toggle', \n    'RichShield_set_digital_pwm',\n    'RichShield_set_digital_servo',\n    'RichShield_set_digital_buzzer',\n\n\n    \n    'RichShield_rgbled_event',\n    'RichShield_rgbled_clr',\n    'RichShield_rgbled_set',\n    'RichShield_rgbled_show',\n\n    'RichShield_LCD_event',\n    'RichShield_LCD_Control_init',\n    'RichShield_LCD_Control_Display',\n    'RichShield_LCD_Control_Clear',\n\n    'RichShield_FND_event',\n    'RichShield_FND_Control_diplay_brightness',\n    'RichShield_FND_Control_display_onoff',\n    'RichShield_FND_Control_diplay_char',\n\n    'RichShield_DHT_event',\n    'RichShield_DHT_Control_Get_Temper',\n    'RichShield_DHT2',\n\n\n    'RichShield_OLED_event',\n    'RichShield_OLED_Display_String',\n\n    'RichShield_IRREMOTE_event',\n    'RichShield_IRREMOTE_recv',\n\n];\n\nEntry.RichShield.getBlocks = function() {\n    return {\n        RichShield_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown1',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n \n        RichShield_list_pullup_setting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RichShield_pulldown, '0'],\n                        [Lang.Blocks.RichShield_pullup, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        RichShield_get_digital_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.RichShield_get_digital_ultrasonic,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['7'],\n                    },\n                ],\n                type: 'RichShield_get_digital_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'RichShieldGet',\n            isNotFor: ['RichShield'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.RichShield.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['RichShield.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n        RichShield_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.RichShield_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'RichShield_list_digital_switch',\n                    },\n                    {\n                        type: 'RichShield_list_pullup_setting',\n                    },\n                ],\n                type: 'RichShield_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'RichShieldGet',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                const opr = script.getNumberValue('OPERATOR');\n                //\"down = 0\" or \"up = 2\"\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue.GET[Entry.RichShield.sensorTypes.DIGITAL] = {\n                        port,\n                        data: opr,\n                        time: new Date().getTime(),\n                    };\n                }\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['RichShield_get_digital(%1,%2)'] },\n        },\n        RichShield_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.RichShield_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'RichShield_list_digital_switch',\n                    },\n                    {\n                        type: 'RichShield_list_pullup_setting',\n                    },\n                ],\n                type: 'RichShield_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'RichShieldGet',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                const opr = script.getNumberValue('OPERATOR');\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue.GET[Entry.Hasseam.sensorTypes.DIGITAL] = {\n                        port,\n                        data: opr,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['RichShield_get_digital_toggle(%1 %2)'] },\n        },\n        RichShield_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        RichShield_get_Analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.RichShield_get_Analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'RichShield_list_analog_basic',\n                    },\n                ],\n                type: 'RichShield_get_Analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'RichShieldGet',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.RichShield.sensorTypes.ANALOG] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['RichShield.Get_Light_Value(%1, %2)'] },\n        },\n        RichShield_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        RichShield_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['~3', '3'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                        ['~11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        RichShield_list_digital_pwm2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n\n                        ['~9', '9'],\n                        ['~10', '10'],\n                        ['~11', '11'],\n                    ],\n                    value: '9',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        RichShield_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        RichShield_list_digital_switch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '4'],\n                        ['5', '5'],                        \n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        RichShield_rgbled_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n            ],\n            def: { params: [], type: 'RichShield_rgbled_event' },\n            class: 'RichShield_rgbled',\n            isNotFor: ['RichShield'],\n        },\n        RichShield_rgbled_clr: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [          \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'RichShield_rgbled_clr',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NO: 1,\n                VALUE0: 2,\n                VALUE1: 3,\n                VALUE2: 4,\n            },\n            class: 'RichShield_rgbled',\n            isNotFor: ['RichShield'],\n            func: function(sprite, script) {\n                var port = 13;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) ;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.RichShield.sensorTypes.RGBLED,\n                        data: {\n                            block_Index: 1,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['RichShield_rgbled_clr(%1)'] },\n        },\n        RichShield_rgbled_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'RichShield_rgbled_set',\n            },\n            paramsKeyMap: {\n                NO: 0,\n                VALUE0: 1,\n                VALUE1: 2,\n                VALUE2: 3,\n            },\n            class: 'RichShield_rgbled',\n            isNotFor: ['RichShield'],\n            func: function(sprite, script) {\n                var port = 13;\n                var no = script.getNumberValue('NO');\n                var value = [3];\n                var noValue1;\n\n                let time = new Date().getTime();\n\n                if (!script.isStart) {\n                    noValue1 = no - 1;\n                    value[0] = script.getNumberValue('VALUE0');\n                    value[1] = script.getNumberValue('VALUE1');\n                    value[2] = script.getNumberValue('VALUE2');\n\n                    for (var i = 0; i < 3; i++) {\n                        value[i] = Math.round(value[i]);\n                        value[i] = Math.min(value[i], 255);\n                        value[i] = Math.max(value[i], 0);\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) ;\n\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.RichShield.sensorTypes.RGBLED,\n                        data: {\n                            block_Index: 2,\n                            noValue: noValue1,\n                            redValue: value[0],\n                            greenValue: value[1],\n                            blueValue: value[2],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, timeValue*20);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield_rgbled_set(%1, %2, %3, %4, %5)'] },\n        },\n        RichShield_rgbled_show: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'RichShield_rgbled_show',\n            },\n            paramsKeyMap: {\n\n            },\n            class: 'RichShield_rgbled',\n            isNotFor: ['RichShield'],\n            func: function(sprite, script) {\n                var port = 13;\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RichShield.sensorTypes.RGBLED,\n                    data: {\n                        block_Index: 3,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield_rgbled_show(%1)'] },\n        },\n        RichShield_list_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['6', '6'],\n                    ],\n                    value: '6',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        RichShield_list_digital_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        RichShield_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        RichShield_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RichShield_toggle_on, 'on'],\n                        [Lang.Blocks.RichShield_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        RichShield_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.RichShield_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'RichShield_list_digital_basic',\n                    },\n                    {\n                        type: 'RichShield_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'RichShield_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'RichShield_set',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.RichShield.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.RichShield.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.RichShield.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield.Set_Digital_Toggle(%1, %2)'] },\n        },\n        RichShield_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.RichShield_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'RichShield_list_digital_pwm2',\n                    },\n                 \n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'RichShield_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'RichShield_Set',\n            isNotFor: ['RichShield'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                let time = new Date().getTime();\n\n            if (!script.isStart) {\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * 50;\n\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RichShield.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                setTimeout(() => {\n                        script.timeFlag = 0;\n                }, timeValue);\n            } else if (script.timeFlag == 1) {\n                    return script;\n            } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n            }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield.set_digital_pwm(%1, %2)'] },\n        },\n        RichShield_set_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.RichShield_set_digital_servo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'RichShield_list_digital_servo',\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'RichShield_set_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'RichShield_Set',\n            isNotFor: ['RichShield'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RichShield.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield.set_digital_servo(%1, %2)'] },\n        },\n        RichShield_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.RichShield_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'RichShield_list_digital_sound',\n                    },\n                    {\n                        type: 'RichShield_list_digital_tone',\n                    },\n                    {\n                        type: 'RichShield_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'RichShield_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'RichShield_Set',\n            isNotFor: ['RichShield'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.RichShield.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.RichShield.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.RichShield.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.RichShield.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.RichShield.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['RichShield.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        RichShield_LCD_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n            ],\n            def: { params: [], type: 'RichShield_LCD_event' },\n            class: 'RichShield_LCD',\n            isNotFor: ['RichShield'],\n        },\n        RichShield_LCD_Control_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x20', 32],\n                        ['0x27', 39],\n                        ['0x3f', 63],\n                    ],\n                    value: 32,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_LCD_Control_init' },\n            paramsKeyMap: { lcd_device: 0, address: 1 },\n            class: 'RichShield_LCD',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('lcd_device', script);\n                const addr_val = script.getNumberValue('address', script);\n\n                const text = [];\n\n                // index number patched by Remoted 2020-11-20\n                if (!script.isStart) {\n                    if (typeof addr_val === 'string') {\n                        for (let i = 0; i < 16; i++) {\n                            text[i] = string.charAt(i);\n                        }\n                    } else if (typeof addr_val === 'number') {\n                        text[0] = 1;\n                        text[1] = addr_val / 1;\n                    } else {\n                        text[0] = addr_val;\n                    }\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * 50;\n\n                    // LCD_Init type data protocol defined\n                    Entry.hw.sendQueue.SET[device] = {\n                        type: Entry.RichShield.sensorTypes.LCD,\n                        data: {\n                            block_index:1,\n                            text0: text[0],\n                            text1: text[1],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['RichShield_LCD_init(%1, %2)'] },\n        },\n        RichShield_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RichShield_lcd_first_line, '0'],\n                        [Lang.Blocks.RichShield_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n\n        RichShield_LCD_Control_Display: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: Lang.template.RichShield_LCD_Control_Display,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [1],\n                    },\n                    {\n                        type: 'number',\n                        params: [1],\n                    },\n                    {\n                        type: 'number',\n                        params: [1],\n                    },\n                    {\n                        type: 'text',\n                        params: ['RichShield !!'],\n                    },\n                    null,\n                ],\n                type: 'RichShield_LCD_Control_Display',\n            },\n            paramsKeyMap: {\n                line: 0,\n                Row: 1,\n                Col: 2,\n                STRING: 3,\n            },\n            class: 'RichShield_LCD',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const line = script.getNumberValue('line'); // No used this data in RichShield\n                const Row = parseInt(script.getNumberValue('Row'));\n                const Col = parseInt(script.getNumberValue('Col'));\n                const string = script.getValue('STRING');\n                const text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (let i = 0; i < 16; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * 60;\n\n                    console.log(\n                        `Row : ${Row} / Col : ${Col} / text : ${text}`\n                    );\n\n                    Entry.hw.sendQueue.SET[line] = {\n                        type: Entry.RichShield.sensorTypes.LCD,\n                        data: {\n                            block_index: 2,\n                            displayRow: Row,\n                            displayCol: Col,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield.LCD_Display(%1, %2, %3, %4)'] },\n        },\n        RichShield_LCD_Control_Clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 1]],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_LCD_Control_Clear' },\n            paramsKeyMap: { lcd_device: 0 },\n            class: 'RichShield_LCD',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('lcd_device', script);\n                \n                let time = new Date().getTime();\n\n                if (!script.isStart) {\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * 50;\n\n                    // LCD_Init type data protocol defined\n                    Entry.hw.sendQueue.SET[device] = {\n                        type: Entry.RichShield.sensorTypes.LCD,\n                        data: {\n                            block_index: 3,\n                        },\n                        time: time,\n                    };\n\n                    setTimeout(() => {\n                            script.timeFlag = 0;\n                    }, timeValue);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield_LCD_Control_Clear(%1)'] },\n        },\n        RichShield_LCD_Control_Scroll: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 1]],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', 1],\n                        ['오른쪽', 2],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_LCD_Control_Scroll' },\n            paramsKeyMap: {\n                lcd_device: 0,\n                direction: 1,\n            },\n            class: 'RichShield_LCD',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('lcd_device', script);\n                const direction = script.getNumberValue('direction', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n\n                // LCD_Init type data protocol defined\n                Entry.hw.sendQueue.SET[device] = {\n                    type: Entry.RichShield.sensorTypes.LCD,\n                    data: {\n                        block_index: 4,\n                        direction,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield_LCD_Control_Scroll(%1)'] },\n        },\n        RichShield_FND_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n            ],\n            def: { params: [], type: 'RichShield_FND_event' },\n            class: 'RichShield_FND',\n            isNotFor: ['RichShield'],\n        },\n        RichShield_FND_Control_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 1]],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['5', 5]],\n                    value: 5,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['4', 4]],\n                    value: 4,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_FND_Control_init' },\n            paramsKeyMap: { fnd_device: 0, CLK: 1, DIO: 2 },\n            class: 'RichShield_FND',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('fnd_device', script);\n                const clk_val = script.getNumberValue('CLK', script);\n                const dio_val = script.getNumberValue('DIO', script);\n\n                // index number patched by Remoted 2020-11-20\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                // FND_Init type data protocol defined\n                Entry.hw.sendQueue.SET[device] = {\n                    type: Entry.RichShield.sensorTypes.FND,\n                    data: {\n                        clk_pin: clk_val,\n                        dio_pin: dio_val,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield_FND_init(%1, %2)'] },\n        },\n        RichShield_FND_Control_diplay_brightness: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 1]],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        ['5', 5],\n                        ['6', 6],\n                        ['7', 7],\n                    ],\n                    value: 3,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_FND_Control_diplay_brightness' },\n            paramsKeyMap: { fnd_device: 0, level: 1 },\n            class: 'RichShield_FND',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('fnd_device', script);\n                const level_val = script.getNumberValue('level', script);\n\n                if (!script.isStart) {\n                    // index number patched by Remoted 2020-11-20\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * 50;\n\n                    // FND_Init type data protocol defined\n                    Entry.hw.sendQueue.SET[device] = {\n                        type: Entry.RichShield.sensorTypes.FND,\n                        data: {\n                            level_val,\n                            block_index: 1,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['RichShield_FND_Control_diplay_brightness(%1, %2)'] },\n        },\n        RichShield_FND_Control_display_onoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 1]],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RichShield_toggle_off, 0],\n                        [Lang.Blocks.RichShield_toggle_on, 1],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_FND_Control_display_onoff' },\n            paramsKeyMap: { fnd_device: 0, onoff: 1 },\n            class: 'RichShield_FND',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('fnd_device', script);\n                const onoff = script.getNumberValue('onoff', script);\n\n                if (!script.isStart) {\n                    // index number patched by Remoted 2020-11-20\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * 50;\n\n                    // FND_Init type data protocol defined\n                    Entry.hw.sendQueue.SET[device] = {\n                        type: Entry.RichShield.sensorTypes.FND,\n                        data: {\n                            onoff,\n                            block_index: 2,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    \n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n\n            },\n            syntax: { js: [], py: ['RichShield_FND_Control_display_onoff(%1, %2)'] },\n        },\n        RichShield_FND_Control_diplay_char: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 1]],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RichShield_toggle_off, 0],\n                        [Lang.Blocks.RichShield_toggle_on, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '1',\n                    {\n                        type: 'number',\n                        params: ['1234'],\n                    },\n                    '0',\n                    {\n                        type: 'number',\n                        params: ['0.1'],\n                    },\n                ],\n                type: 'RichShield_FND_Control_diplay_char',\n            },\n            events: {},\n            paramsKeyMap: { fnd_device: 0, display_value: 1, onoff: 2, delay_ms: 3 },\n            class: 'RichShield_FND',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('fnd_device', script);\n                const display_str = script.getNumberValue('display_value', script);\n                const onoff = script.getNumberValue('onoff', script);\n                const delay_ms_sec = script.getNumberValue('delay_ms', script);\n                const splited_array = [];\n                let display_str_converted = 0;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n\n                    display_str_converted = display_str.toString();\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * 100;\n\n                    for (let i = 0; i < display_str_converted.length; i++) {\n                        splited_array.push(parseInt(display_str_converted.charAt(i)));\n                    }\n\n                    console.log(`splited_array :${splited_array}`);\n\n                    // FND_Init type data protocol defined\n                    Entry.hw.sendQueue.SET[device] = {\n                        type: Entry.RichShield.sensorTypes.FND,\n                        data: {\n                            display_str,\n                            onoff,\n                            block_index: 3,\n                            str_length: display_str_converted.length,\n                            data_0: splited_array[0],\n                            data_1: splited_array[1],\n                            data_2: splited_array[2],\n                            data_3: splited_array[3],\n                            delay_ms: delay_ms_sec,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                        \n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['RichShield_FND_Control_diplay_char(%1, %2, %3, %4)'] },\n        },\n        RichShield_DHT_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n            ],\n            def: { params: [], type: 'RichShield_DHT_event' },\n            class: 'RichShield_DHT',\n            isNotFor: ['RichShield'],\n        },\n        RichShield_DHT_Control_Init_Process: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['13', 13]],\n                    value: 13,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['DHT11', 4]],\n                    value: 4,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_DHT_Control_Init_Process' },\n            class: 'RichShield_DHT',\n            isNotFor: ['RichShield'],\n            paramsKeyMap: { dht_device: 0, pin: 1, ver: 2 },\n            class: 'RichShield_DHT',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('dht_device', script);\n                const dht_val = script.getNumberValue('pin', script);\n                const ver_val = script.getNumberValue('ver', script);\n\n                // index number patched by Remoted 2020-11-20\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                // DHT_Init type data protocol defined\n                Entry.hw.sendQueue.SET[device] = {\n                    type: Entry.RichShield.sensorTypes.DHT,\n                    data: {\n                        dht_pin: dht_val,\n                        ver_info: ver_val,\n                        dht_block_index: 0,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield_DHT_Control_Init_Process(%1, %2, %3)'] },\n        },\n\n        RichShield_DHT_Control_Get_Temper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_DHT_Control_Get_Temper' },\n            paramsKeyMap: { dht_device: 0},\n            class: 'RichShield_DHT',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('dht_device', script);\n                const port = 12;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n\n                // DHT Temp-Reader type data protocol defined\n                Entry.hw.sendQueue.GET[Entry.RichShield.sensorTypes.DHT] = {\n                    port,\n                    //tempMode: tempType,\n                    dht_block_index: 0,\n                    time: new Date().getTime(),\n                };\n\n                console.log((Entry.hw.portData.DHT || 0).toFixed(1));\n                return (Entry.hw.portData.DHT || 0).toFixed(0);\n            },\n            syntax: { js: [], py: ['RichShield_DHT_Control_Get_Temper(%1, %2)'] },\n        },\n\n        RichShield_OLED_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n            ],\n            def: { params: [], type: 'RichShield_OLED_event' },\n            class: 'RichShield_OLED',\n            isNotFor: ['RichShield'],\n        },\n        RichShield_OLED_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n            ],\n            def: { params: [], type: 'RichShield_OLED_init' },\n            paramsKeyMap: {},\n            class: 'RichShield_OLED',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = 1;\n                // OLED Block Added By Remoted 2021-03-16\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n\n                // DHT Temp-Reader type data protocol defined\n                Entry.hw.sendQueue.SET[device] = {\n                    type: Entry.RichShield.sensorTypes.OLED,\n                    data: {\n                        oled_block_index: 0,\n                    },\n                    time: new Date().getTime(),\n                };\n            },\n            syntax: { js: [], py: ['RichShield_OLED_init(0x3C)'] },\n        },\n        RichShield_OLED_Display_String: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [1],\n                    },\n                    {\n                        type: 'number',\n                        params: [1],\n                    },\n                    {\n                        type: 'text',\n                        params: ['RichShield !!'],\n                    },\n                    null,\n                ],\n                type: 'RichShield_OLED_Display_String',\n            },\n            paramsKeyMap: {\n                Row: 0,\n                Col: 1,\n                STRING: 2,\n            },\n            class: 'RichShield_OLED',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = 1;\n                const Row = parseInt(script.getNumberValue('Row'));\n                const Col = parseInt(script.getNumberValue('Col'));\n                const string = script.getValue('STRING');\n                const text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (let i = 0; i < 16; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * 50;\n\n                    console.log(\n                        `Row : ${Row} / Col : ${Col} / text : ${text}`\n                    );\n\n                    Entry.hw.sendQueue.SET[device] = {\n                        type: Entry.RichShield.sensorTypes.OLED,\n                        data: {\n                            oled_block_index: 1,\n                            displayRow: Row,\n                            displayCol: Col,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['RichShield_OLED_Display_String(%1, %2, %3)'] },\n        },\n                \n        RichShield_IRREMOTE_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n            ],\n            def: { params: [], type: 'RichShield_IRREMOTE_event' },\n            class: 'RichShield_IR',\n            isNotFor: ['RichShield'],\n        },\n\n        RichShield_IRREMOTE_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    value: 2,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_IRREMOTE_init' },\n            paramsKeyMap: { ir_device: 0, pin: 1 },\n            class: 'RichShield_IR',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('ir_device', script);\n                const ir_val = script.getNumberValue('pin', script);\n                let time = new Date().getTime();\n\n                // index number patched by Remoted 2020-11-20\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                // IR_Init type data protocol defined\n                Entry.hw.sendQueue.SET[device] = {\n                    type: Entry.RichShield.sensorTypes.IRREMOTE,\n                    data: {\n                        ir_pin: ir_val,\n                        ir_block_index: 0,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['RichShield_IRREMOTE_init(%1, %2)'] },\n        },\n\n\n        RichShield_IRREMOTE_recv: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    value: 2,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_IRREMOTE_recv' },\n            paramsKeyMap: { ir_device: 0 },\n            class: 'RichShield_IR',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('ir_device', script);\n                const port = 12;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n\n                // DHT Temp-Reader type data protocol defined\n                Entry.hw.sendQueue.GET[Entry.RichShield.sensorTypes.IRREMOTE] = {\n                    port,\n                    dir:123,\n                    //dht_block_index: 2,\n                    time: new Date().getTime(),\n                };\n\n                console.log((Entry.hw.portData.IRREMOTE || 0).toFixed(1));\n\n                return (Entry.hw.portData.IRREMOTE || 0).toFixed(0);\n\n            },\n            syntax: { js: [], py: ['RichShield_IRREMOTE_recv(%1, %2)'], },\n        },\n\n        RichShield_DHT2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'RichShield_DHT2' },\n            paramsKeyMap: { ir_device: 0 },\n            class: 'RichShield_DHT',\n            isNotFor: ['RichShield'],\n            func(sprite, script) {\n                const device = script.getNumberValue('ir_device', script);\n                const port = 12;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n\n                // DHT Temp-Reader type data protocol defined\n                Entry.hw.sendQueue.GET[Entry.RichShield.sensorTypes.DHT2] = {\n                    port,\n                    dir:123,\n                    time: new Date().getTime(),\n                };\n\n                console.log((Entry.hw.portData.DHT2 || 0).toFixed(1));\n\n                return (Entry.hw.portData.DHT2 || 0).toFixed(0);\n            },\n            syntax: { js: [], py: ['RichShield_DHT2(%1, %2)'] },\n        },    \n\n    };\n};\nmodule.exports = Entry.RichShield;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_abilix_Krypton0.js",
    "content": "'use strict';\n\nEntry.Krypton0 = {\n    SENSOR_PORT_MAP: {\n        '1': undefined,\n        '2': undefined,\n        '3': undefined,\n        '4': undefined,\n    },\n    deviceTypes: {\n        NONE: 0x01,\n        BUTTON: 0x02,\n        GRAY_INFRARED: 0x03,\n        LIGHT: 0x07,\n        MICROPHONE: 0x08,\n        LED: 0x09,\n        LMOTOR: 0x0a,\n        RMOTOR: 0x0b,\n\n        Initializing: 0x7d,\n        WrongPort: 0x7f,\n        Unknown: 0xff,\n    },\n\n    timeouts: [],\n    removeTimeout(id) {\n        clearTimeout(id);\n        const timeouts = this.timeouts;\n        const index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n\n    setZero() {\n        Object.keys(this.SENSOR_PORT_MAP).forEach((port) => {\n            Entry.hw.sendQueue[port] = {\n                type: Entry.Krypton0.deviceTypes.NONE,\n                port_values: 0,\n            };\n        });\n        Entry.hw.sendQueue.LMOTOR = 0;\n        Entry.hw.sendQueue.RMOTOR = 0;\n        Entry.hw.sendQueue.INTERSND = 'none';\n\n        Entry.hw.update();\n    },\n\n    abilix_controller: {\n        MIN_MOTOR_SPEED: -50,\n        MAX_MOTOR_SPEED: 50,\n\n        check_max_speed(speedvalue) {\n            let adjspeed;\n\n            if (speedvalue > this.MAX_MOTOR_SPEED) {\n                adjspeed = this.MAX_MOTOR_SPEED;\n            } else if (speedvalue < this.MIN_MOTOR_SPEED) {\n                adjspeed = this.MAX_MOTOR_SPEED;\n            } else {\n                adjspeed = speedvalue;\n            }\n\n            return adjspeed;\n        },\n    },\n\n    id: '30.1',\n    name: 'ABILIX Krypton 0 for School',\n    url: 'http://abilix.co.kr',\n    imageName: 'abilix_Krypton0.png',\n    title: {\n        ko: '크립톤 0',\n        en: 'Krypton 0 for School',\n    },\n};\n\nEntry.Krypton0.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                Krypton0_turnon_motor: '모터를 %1(으)로 %2 속도로 움직이기 %3',\n                Krypton0_move_to_direction_during_secs: '모터를 %1(으)로 %2 초동안 움직이기 %3',\n\n                Krypton0_turnoff_motor: '모터를 정지 시키기 %1',\n                Krypton0_change_direction_during_secs: '모터를 %1 방향으로 %2초 동안 움직이기 %3',\n                Krypton0_change_speed: '모터 %1의 속도를 %2로 변경하기 %3',\n\n                Krypton0_play_sound: '크립톤에서 %1 을 재생하기 %2',\n\n                Krypton0_get_sensor_data: '포트 %1에서 센서 %2 의 값을 읽기',\n\n                //Krypton0_get_sensor_value: '센서 %1 의 값을 읽기',\n                Krypton0_button_pressed: '포트 %1의 버튼이 눌려져있는가? %2',\n                Krypton0_turnon_led: '포트 %1의 LED를 %2 %3',\n            },\n        },\n        en: {\n            template: {\n                Krypton0_turnon_motor: 'Motors move to %1 as %2 speed %3',\n                Krypton0_move_to_direction_during_secs: 'Motors move to %1 during %2 sec %3',\n\n                Krypton0_turnoff_motor: 'Stop Motors %1',\n                Krypton0_change_direction_during_secs: 'Motors go to %1 during %2 secs %3',\n                Krypton0_change_speed: 'Motor change from speed of %1 to %2 %3',\n\n                Krypton0_play_sound: 'Kripton play %1 audio %2',\n\n                Krypton0_get_sensor_data: 'Port %1 read sensor %2 value',\n\n                //Krypton0_get_sensor_value: 'Read sensor %1 value',\n                Krypton0_button_pressed: 'Port %1 of Button is pressed? %2',\n                Krypton0_turnon_led: 'Port %1 of LED Turn %2 %3',\n            },\n        },\n    };\n};\n\nEntry.Krypton0.blockMenuBlocks = [\n    'Krypton0_turnon_motor',\n    'Krypton0_move_to_direction_during_secs',\n\n    'Krypton0_turnoff_motor',\n    'Krypton0_change_direction_during_secs',\n    'Krypton0_change_speed',\n\n    'Krypton0_play_sound',\n\n    'Krypton0_get_sensor_data',\n\n    //'Krypton0_get_sensor_value',\n    'Krypton0_button_pressed',\n    'Krypton0_turnon_led',\n];\n\nEntry.Krypton0.getBlocks = function() {\n    return {\n        //region Krypton0\n        //*************************************************************************\n        // Name: Krypton0_turnon_motor\n        //\n        // Description: Turn on Motor.\n        //               \"Motors move to %1 as %2 speed %3\"\n        //*************************************************************************/\n        Krypton0_turnon_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞', 'Forward'],\n                        ['뒤', 'Backward'],\n                    ],\n                    value: '앞',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                ],\n                type: 'Krypton0_turnon_motor',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE_SPD: 1,\n            },\n            class: 'Krypton0_motor_control',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                const direction = script.getStringField('DIRECTION', script);\n                let speedValue = script.getNumberValue('VALUE_SPD');\n                if (direction == 'Forward') {\n                    speedValue = Entry.Krypton0.abilix_controller.check_max_speed(speedValue);\n                } else {\n                    speedValue = Entry.Krypton0.abilix_controller.check_max_speed(speedValue * -1);\n                }\n                Entry.hw.sendQueue.LMOTOR = speedValue;\n                Entry.hw.sendQueue.RMOTOR = speedValue;\n                return script.callReturn();\n            },\n        },\n\n        //*************************************************************************\n        // Name: Krypton0_move_to_direction_during_secs\n        //\n        // Description: Moter move to Forward / Backword during some sec.\n        //               \"Motors move to %1 during %2 sec %3\"\n        //*************************************************************************/\n        Krypton0_move_to_direction_during_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞', 'Forward'],\n                        ['뒤', 'Backward'],\n                    ],\n                    value: '앞',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                ],\n                type: 'Krypton0_move_to_direction_during_secs',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE_SEC: 1,\n            },\n            class: 'Krypton0_motor_control',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const direction = script.getStringField('DIRECTION', script);\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    if (direction == 'Forward') {\n                        Entry.hw.sendQueue.LMOTOR = 30;\n                        Entry.hw.sendQueue.RMOTOR = 30;\n                    } else {\n                        Entry.hw.sendQueue.LMOTOR = -30;\n                        Entry.hw.sendQueue.RMOTOR = -30;\n                    }\n\n                    const timeValue = script.getNumberValue('VALUE_SEC') * 1000;\n                    const timer = setTimeout(() => {\n                        script.timeFlag = 0;\n                        Entry.Krypton0.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.Krypton0.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    Entry.hw.sendQueue.LMOTOR = 0;\n                    Entry.hw.sendQueue.RMOTOR = 0;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        //*************************************************************************\n        // Name: Krypton0_turnoff_motor\n        //\n        // Description: Turn off motor.\n        //               \"Stop Motors %1\"\n        //*************************************************************************/\n        Krypton0_turnoff_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'Krypton0_turnoff_motor',\n            },\n            class: 'Krypton0_motor_control',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.LMOTOR = 0;\n                Entry.hw.sendQueue.RMOTOR = 0;\n                return script.callReturn();\n            },\n        },\n\n        //*************************************************************************\n        // Name: Krypton0_change_direction_during_secs\n        //\n        // Description: Turn left or right during some sec.\n        //               \"Motors go to %1 during %2 secs %3\"\n        //*************************************************************************/\n        Krypton0_change_direction_during_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', 'LEFT'],\n                        ['오른쪽', 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'Krypton0_change_direction_during_secs',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n            },\n            class: 'Krypton0_motor_control',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const direction = script.getField('DIRECTION', script);\n                    if (direction == 'LEFT') {\n                        Entry.hw.sendQueue.LMOTOR = -30;\n                        Entry.hw.sendQueue.RMOTOR = 30;\n                    } else {\n                        Entry.hw.sendQueue.LMOTOR = 30;\n                        Entry.hw.sendQueue.RMOTOR = -30;\n                    }\n                    const timeValue = script.getNumberValue('VALUE') * 1000;\n                    const timer = setTimeout(() => {\n                        script.timeFlag = 0;\n                        Entry.Krypton0.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.Krypton0.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    Entry.hw.sendQueue.LMOTOR = 0;\n                    Entry.hw.sendQueue.RMOTOR = 0;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        //*************************************************************************\n        // Name: Krypton0_change_speed\n        //\n        // Description: change motor speed about left, right and both.\n        //               \"Motor change from speed of %1 to %2 %3\"\n        //*************************************************************************/\n        Krypton0_change_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                        ['양쪽', 'BOTH'],\n                    ],\n                    value: 'BOTH',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                ],\n                type: 'Krypton0_change_speed',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n            },\n            class: 'Krypton0_motor_control',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                const direction = script.getField('DIRECTION');\n                const value = script.getNumberValue('VALUE');\n                if (direction == 'A') {\n                    Entry.hw.sendQueue.LMOTOR = value;\n                    if (Entry.hw.sendQueue.RMOTOR != undefined) {\n                        Entry.hw.sendQueue.RMOTOR = Entry.hw.sendQueue.RMOTOR;\n                    } else {\n                        Entry.hw.sendQueue.RMOTOR = 0;\n                    }\n                } else if (direction == 'B') {\n                    Entry.hw.sendQueue.RMOTOR = value;\n                    if (Entry.hw.sendQueue.LMOTOR != undefined) {\n                        Entry.hw.sendQueue.LMOTOR = Entry.hw.sendQueue.LMOTOR;\n                    } else {\n                        Entry.hw.sendQueue.LMOTOR = 0;\n                    }\n                } else {\n                    Entry.hw.sendQueue.LMOTOR = value;\n                    Entry.hw.sendQueue.RMOTOR = value;\n                }\n                return script.callReturn();\n            },\n        },\n\n        //*************************************************************************\n        // Name: Krypton0_play_sound\n        //\n        // Description: play internal sound - hello, by, welcom, cheer.\n        //               \"Kripton play %1 audio %2\"\n        //*************************************************************************/\n        Krypton0_play_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['hello', 'hello'],\n                        ['bye', 'bye'],\n                        ['welcome', 'welcome'],\n                        ['cheer', 'cheer'],\n                    ],\n                    value: 'hello',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'Krypton0_play_sound',\n            },\n            paramsKeyMap: {\n                SOUND_VALUE: 0,\n            },\n            class: 'Krypton0_motor_control',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const audiofile = script.getField('SOUND_VALUE', script);\n                    Entry.hw.sendQueue.INTERSND = audiofile;\n                    const timeValue = 500;\n                    const timer = setTimeout(() => {\n                        script.timeFlag = 0;\n                        Entry.Krypton0.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.Krypton0.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    Entry.hw.sendQueue.INTERSND = 'none';\n                    return script.callReturn();\n                }\n            },\n        },\n\n        //*************************************************************************\n        // Name: Krypton0_get_sensor_data\n        //\n        // Description: Get sensor values - GRAY_INFRARED, ULTRASONIC,\n        //                                  COLOR, LIGHT, MICROPHONE, LANTERN, BUTTON\n        //               \"Port %1 read sensor %2 value\"\n        //*************************************************************************/\n        Krypton0_get_sensor_data: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['적외선', 'GRAY_INFRARED'],\n                        ['빛', 'LIGHT'],\n                        ['소리센서', 'MICROPHONE'],\n                        ['LED', 'LED'],\n                        ['버튼', 'BUTTON'],\n                    ],\n                    value: 'GRAY_INFRARED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'Krypton0_get_sensor_data',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DEVICE: 1,\n            },\n            class: 'Krypton0_sensor',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                const port = script.getField('PORT');\n                const dev = script.getField('DEVICE');\n                let portdata;\n                let devtype;\n\n                switch (port) {\n                    case '1':\n                        portdata = Entry.hw.getDigitalPortValue('1');\n                        break;\n                    case '2':\n                        portdata = Entry.hw.getDigitalPortValue('2');\n                        break;\n                    case '3':\n                        portdata = Entry.hw.getDigitalPortValue('3');\n                        break;\n                    case '4':\n                        portdata = Entry.hw.getDigitalPortValue('4');\n                        break;\n                }\n\n                switch (dev) {\n                    case 'GRAY_INFRARED':\n                        devtype = Entry.Krypton0.deviceTypes.GRAY_INFRARED;\n                        break;\n                    case 'LIGHT':\n                        devtype = Entry.Krypton0.deviceTypes.LIGHT;\n                        break;\n                    case 'MICROPHONE':\n                        devtype = Entry.Krypton0.deviceTypes.MICROPHONE;\n                        break;\n                    case 'LED':\n                        devtype = Entry.Krypton0.deviceTypes.LED;\n                        break;\n                    case 'BUTTON':\n                        devtype = Entry.Krypton0.deviceTypes.BUTTON;\n                        break;\n                    default:\n                        break;\n                }\n\n                if (portdata.type == devtype) {\n                    return portdata.port_values.toString();\n                } else {\n                    console.log('Krypton0_get_sensor_value : differenct dev type');\n                    return '';\n                }\n            },\n        },\n\n        //*************************************************************************\n        // Name: Krypton0_button_pressed\n        //\n        // Description: Is Button pressed?.\n        //               \"Port %1 of Button is pressed? %2\"\n        //*************************************************************************/\n        Krypton0_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'Krypton0_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Krypton0_sensor',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                const port = script.getField('PORT');\n                let portdata = Entry.hw.getDigitalPortValue(port);\n\n                switch (port) {\n                    case '1':\n                        portdata = Entry.hw.getDigitalPortValue('1');\n                        break;\n                    case '2':\n                        portdata = Entry.hw.getDigitalPortValue('2');\n                        break;\n                    case '3':\n                        portdata = Entry.hw.getDigitalPortValue('3');\n                        break;\n                    case '4':\n                        portdata = Entry.hw.getDigitalPortValue('4');\n                        break;\n                }\n\n                if (portdata.type == Entry.Krypton0.deviceTypes.BUTTON) {\n                    if (portdata.port_values == 1) {\n                        console.log('Krypton0_button_pressed');\n                        return true;\n                    }\n                } else {\n                    console.log('Krypton0_get_sensor_data : differenct dev type');\n                }\n\n                return false;\n            },\n        },\n\n        //*************************************************************************\n        // Name: Krypton0_turnon_led\n        //\n        // Description: Turn on / off LED\n        //               \"Port %1 of LED Turn %2 %3\"\n        //*************************************************************************/\n        Krypton0_turnon_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켠다', 'ON'],\n                        ['끈다', 'OFF'],\n                    ],\n                    value: 'ON',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'Krypton0_turnon_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                LED_VALUE: 1,\n            },\n            class: 'Krypton0_sensor',\n            isNotFor: ['ABILIX Krypton 0 for School'],\n            func(sprite, script) {\n                const port = script.getField('PORT');\n                const ledvalue = script.getField('LED_VALUE');\n                let portvalue;\n\n                if (ledvalue == 'ON') {\n                    portvalue = 0;\n                } else {\n                    portvalue = 1;\n                }\n\n                Entry.hw.sendQueue[port] = {\n                    type: Entry.Krypton0.deviceTypes.LED,\n                    port_values: portvalue,\n                };\n                return script.callReturn();\n            },\n        },\n        //endregion\n    };\n};\n\nmodule.exports = Entry.Krypton0;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_aidrone.js",
    "content": "'use strict';\n\nEntry.AIDrone = {\n    Cmd: {\n        CMD_LED: 1,\n        CMD_TUNE: 2,\n        CMD_TUNEDUR: 3,\n        CMD_ROLL_LOW: 4,\n        CMD_ROLL_HIGH: 5,\n        CMD_PITCH_LOW: 6,\n        CMD_PITCH_HIGH: 7,\n        CMD_OPTION_LOW: 8,\n        CMD_MOTOR0: 9,\n        CMD_MOTOR1: 10,\n        CMD_MOTOR2: 11,\n        CMD_MOTOR3: 12,\n        CMD_EXTPIN1: 13,\n        CMD_EXTPIN2: 14,\n        CMD_EXTPIN3: 15,\n        CMD_PWM: 16,\n        CMD_SERVOPORT: 17,\n        CMD_SERVODGREE: 18,\n        CMD_OPTION_HIGH: 19,\n        CMD_YAW_LOW: 20,\n        CMD_YAW_HIGH: 21,\n        CMD_THROTTLE_LOW: 22,\n        CMD_THROTTLE_HIGH: 23,\n        CMD_POSVEL_LOW: 24,\n        CMD_POSVEL_HIGH: 25,\n        CMD_YAWVEL_LOW: 26,\n        CMD_YAWVEL_HIGH: 27,\n        CMD_ULTRASONIC: 28,\n    },\n    Sensor: {\n        SENSOR_JOYSTICK_LLR: 1,\n        SENSOR_JOYSTICK_LTB: 2,\n        SENSOR_JOYSTICK_RLR: 3,\n        SENSOR_JOYSTICK_RTB: 4,\n        SENSOR_BUTTON: 5,\n        SENSOR_DRONECONNECT: 6,\n        SENSOR_DRONEALT: 7,\n        SENSOR_GYRO_X: 8,\n        SENSOR_GYRO_Y: 9,\n        SENSOR_DRONEREADY: 10,\n        SENSOR_EXTPIN1: 11,\n        SENSOR_EXTPIN2: 12,\n        SENSOR_ANALOG4: 13,\n        SENSOR_ANALOG5: 14,\n        SENSOR_JDKITMAX: 15,\n        SENSOR_BATTERY: 15,\n        SENSOR_POSX_L: 16,\n        SENSOR_POSX_H: 17,\n        SENSOR_POSY_L: 18,\n        SENSOR_POSY_H: 19,\n        SENSOR_ULTRASONIC: 20,\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.CMD = [\n            0xf0, 0, 0, 0, 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,\n        ];\n        Entry.hw.update();\n    },\n    id: '6B.1',\n    name: 'AIDrone',\n    url: 'http://www.aidrone.store',\n    imageName: 'aidrone.png',\n    title: {\n        'en': 'AIDrone',\n        'ko': 'AI드론',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/jdrc.png',\n        width: 600,\n        height: 355,\n        listPorts: {\n            'A6': {\n                name: '드론연결상태',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A10': {\n                name: '드론준비상태',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A15': {\n                name: '배터리(%)',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A8': {\n                name: '드론좌우기울기',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A9': {\n                name: '드론앞뒤기울기',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A7': {\n                name: '드론높이',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A16': {\n                name: '드론좌우이동',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A18': {\n                name: '드론앞뒤이동',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n        },\n        ports: {\n            'A1': {\n                name: '왼쪽 조이스틱 좌우',\n                type: 'input',\n                pos: {\n                    x: 140,\n                    y: 140,\n                },\n            },\n\n            'A2': {\n                name: '왼쪽 조이스틱 상하',\n                type: 'input',\n                pos: {\n                    x: 140,\n                    y: 140,\n                },\n            },\n            'A3': {\n                name: '오른쪽 조이스틱 좌우',\n                type: 'input',\n                pos: {\n                    x: 450,\n                    y: 140,\n                },\n            },\n\n            'A4': {\n                name: '오른쪽 조이스틱 상하',\n                type: 'input',\n                pos: {\n                    x: 450,\n                    y: 140,\n                },\n            },\n            'A5': {\n                name: '버튼',\n                type: 'input',\n                pos: {\n                    x: 430,\n                    y: 250,\n                },\n            },\n\n\n        },\n        mode: 'both',\n    },\n};\n\n\nEntry.AIDrone.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                'aidrone_takeoff': '드론 이륙하기 %1',\n                'aidrone_landing': '드론 착륙하기 %1',\n                'aidrone_altitude': '%1cm 높이로 비행%2',\n                'aidrone_throttle': '프로펠러를 %1 % 세기로 돌리기 %2',\n                'aidrone_velocity': '%1(으)로 %2속도(cm/s)로 비행%3',\n                'aidrone_distance': '%1(으)로 %2cm 거리를 %3속도(cm/s)로 비행%4',\n                'aidrone_degree': '%1으로 %2도를 %3각속도(deg/s)로 회전 %4',\n                'aidrone_motor': '%1 모터를 %2 세기로 돌리기 %3',\n                'aidrone_emergency': '드론 즉시멈추기 %1',\n                'aidrone_connect': '드론 연결상태',\n                'aidrone_ready': '드론 준비상태',\n                'aidrone_battery': '배터리(%)',\n                'aidrone_dronealt': '드론 높이',\n                'aidrone_gyrox': '드론 좌우 기울기',\n                'aidrone_gyroy': '드론 앞뒤 기울기',\n                'aidrone_posx': '드론 좌우 이동',\n                'aidrone_posy': '드론 앞뒤 이동',\n                'aidrone_led': '%1 LED %2 %3',\n                'aidrone_tune': '%1 음을  %2 초동안 소리내기 %3',\n                'aidrone_joystick': '조이스틱 %1 읽기',\n                'aidrone_button': '%1번 버튼 값 읽어오기',\n                'aidrone_dir_front': '앞',\n                'aidrone_dir_back': '뒤',\n                'aidrone_dir_right': '오른쪽',\n                'aidrone_dir_left': '왼쪽',\n                'aidrone_alt': '드론 높이',\n                'aidrone_tiltx': '드론좌우기울기',\n                'aidrone_tilty': '드론앞뒤기울기',\n                'aidrone_battery': '배터리',\n                'aidrone_detect_marker': '화면에서 마커 찾기 %1',\n                'aidrone_get_marker_data': '인식된 마커의 %1 값',\n                'aidrone_color_track_start': '%1 색상 추적 시작 %2',\n                'aidrone_color_track_stop': '색상 추적 중지 %1',\n                'aidrone_color_detected': '색상이 감지됨?',\n                'aidrone_get_color_x': '감지된 색상 X좌표',\n                'aidrone_get_color_y': '감지된 색상 Y좌표',\n                'aidrone_get_color_size': '감지된 색상 크기',\n                'aidrone_get_color_data': '색상 추적 %1',\n                'aidrone_face_detect': '얼굴 인식하기 %1',\n                'aidrone_face_detected': '얼굴이 감지됨?',\n                'aidrone_get_face_x': '얼굴 X좌표',\n                'aidrone_get_face_y': '얼굴 Y좌표',\n                'aidrone_get_face_size': '얼굴 크기',\n                'aidrone_get_face_data': '얼굴 %1',\n                'aidrone_get_landmark': '얼굴 랜드마크 %1번 %2 좌표',\n                'aidrone_marker_detected': '마커가 감지됨?',\n            },\n        },\n        en: {\n            template: {\n                'aidrone_takeoff': '드론 이륙하기 %1',\n                'aidrone_landing': '드론 착륙하기 %1',\n                'aidrone_altitude': '%1cm 높이로 비행%2',\n                'aidrone_throttle': '프로펠러를 %1 % 세기로 돌리기 %2',\n                'aidrone_velocity': '%1(으)로 %2속도(cm/s)로 비행%3',\n                'aidrone_distance': '%1(으)로 %2cm 거리를 %3속도(cm/s)로 비행%4',\n                'aidrone_degree': '%1으로 %2도를 %3각속도(deg/s)로 회전 %4',\n                'aidrone_motor': '%1 모터를 %2 세기로 돌리기 %3',\n                'aidrone_emergency': '드론 즉시멈추기 %1',\n                'aidrone_connect': '드론 연결상태',\n                'aidrone_ready': '드론 준비상태',\n                'aidrone_battery': '배터리(%)',\n                'aidrone_dronealt': '드론 높이',\n                'aidrone_gyrox': '드론 좌우 기울기',\n                'aidrone_gyroy': '드론 앞뒤 기울기',\n                'aidrone_posx': '드론 좌우 이동',\n                'aidrone_posy': '드론 앞뒤 이동',\n                'aidrone_led': '%1 LED %2 %3',\n                'aidrone_tune': '%1 음을  %2 초동안 소리내기 %3',\n                'aidrone_joystick': '조이스틱 %1 읽기',\n                'aidrone_button': '%1번 버튼 값 읽어오기',\n                'aidrone_dir_front': '앞',\n                'aidrone_dir_back': '뒤',\n                'aidrone_dir_right': '오른쪽',\n                'aidrone_dir_left': '왼쪽',\n                'aidrone_alt': '드론 높이',\n                'aidrone_tiltx': '드론좌우기울기',\n                'aidrone_tilty': '드론앞뒤기울기',\n                'aidrone_battery': '배터리',\n                'aidrone_detect_marker': '화면에서 마커 찾기 %1',\n                'aidrone_get_marker_data': '인식된 마커의 %1 값',\n                'aidrone_color_track_start': '%1 color track start %2',\n                'aidrone_color_track_stop': 'color track stop %1',\n                'aidrone_color_detected': 'color detected?',\n                'aidrone_get_color_x': 'color X',\n                'aidrone_get_color_y': 'color Y',\n                'aidrone_get_color_size': 'color size',\n                'aidrone_get_color_data': 'color track %1',\n                'aidrone_face_detect': 'detect face %1',\n                'aidrone_face_detected': 'face detected?',\n                'aidrone_get_face_x': 'face X',\n                'aidrone_get_face_y': 'face Y',\n                'aidrone_get_face_size': 'face size',\n                'aidrone_get_face_data': 'face %1',\n                'aidrone_get_landmark': 'landmark %1 %2',\n                'aidrone_marker_detected': 'marker detected?',\n            },\n        },\n    };\n};\n\n\nEntry.AIDrone.blockMenuBlocks = [\n    'aidrone_takeoff',\n    'aidrone_landing',\n    'aidrone_altitude',\n    'aidrone_throttle',\n    'aidrone_velocity',\n    'aidrone_distance',\n    'aidrone_degree',\n    'aidrone_emergency',\n    'aidrone_connect',\n    'aidrone_ready',\n    'aidrone_battery',\n    'aidrone_dronealt',\n    'aidrone_gyrox',\n    'aidrone_gyroy',\n    'aidrone_posx',\n    'aidrone_posy',\n    'aidrone_led',\n    'aidrone_tune',\n    'aidrone_motor',\n    'aidrone_joystick',\n    'aidrone_button',\n    'aidrone_detect_marker',\n    'aidrone_get_marker_data',\n    // tracking.js 기반 비전 블록 ─ 색상 추적\n    'aidrone_color_track_start',\n    'aidrone_color_track_stop',\n    'aidrone_color_detected',\n    'aidrone_get_color_x',\n    'aidrone_get_color_y',\n    'aidrone_get_color_size',\n    'aidrone_get_color_data',\n    // tracking.js 기반 비전 블록 ─ 얼굴 인식\n    'aidrone_face_detect',\n    'aidrone_face_detected',\n    'aidrone_get_face_x',\n    'aidrone_get_face_y',\n    'aidrone_get_face_size',\n    'aidrone_get_face_data',\n    // tracking.js 기반 비전 블록 ─ 랜드마크\n    'aidrone_get_landmark',\n    // AR 마커 조건 블록\n    'aidrone_marker_detected',\n];\n\n// --- [여기부터] 1단계 코드: 마커 데이터 저장 변수 ---\nEntry.AIDrone.visionData = {\n    id: -1,      // 마커 ID (없으면 -1)\n    x: 0,        // 화면 X좌표 (-240 ~ 240)\n    y: 0,        // 화면 Y좌표 (-135 ~ 135)\n    dist: 0,     // 거리 (cm 추정치)\n    width: 0     // 마커의 크기(픽셀)\n};\n// --- [여기까지] 1단계 코드 ---\n\n// -------------------------------------------------------\n// tracking.js 전용 데이터 저장 변수\n// -------------------------------------------------------\n\n// 색상 추적 데이터\nEntry.AIDrone.colorTrackData = {\n    detected: false,  // 감지 여부\n    x: 0,             // 감지된 색상 영역 중심 X (엔트리 좌표계)\n    y: 0,             // 감지된 색상 영역 중심 Y (엔트리 좌표계)\n    width: 0,         // 영역 가로 크기(pixel)\n    height: 0         // 영역 세로 크기(pixel)\n};\nEntry.AIDrone._colorTrackerTask    = null;\nEntry.AIDrone._colorTrackerRunning = false;\nEntry.AIDrone._colorTrackerStop    = null;\nEntry.AIDrone._arDetector          = null;  // AR.Detector 재사용\n\n// ----------------------------------------------------------------\n// _getVisionCanvas(): 비전 분석에 사용할 canvas 반환\n//\n// 동작 우선순위:\n//   1순위: Entry.cam.canvas\n//          → 엔트리 [비디오 화면 보이기] + [MJPEG Camera로 바꾸기] 블록\n//            실행 후 생성되는 공식 비디오 캔버스\n//            (매 프레임 Entry.cam.video → Entry.cam.canvas에 그려짐)\n//\n//   2순위: Entry.cam.video → 오프스크린 canvas\n//          → Entry.cam.canvas가 없을 때 video를 직접 그려서 분석\n//\n//   3순위: document의 재생 중인 <video> 탐색 → 오프스크린 canvas\n//          → Entry.cam 자체가 없을 때 (다른 방식으로 연결된 경우)\n//\n//   4순위: Entry.stage.canvas.canvas (최후 fallback)\n// ----------------------------------------------------------------\nEntry.AIDrone._offCanvas = null;\nEntry.AIDrone._offCtx    = null;\n\nEntry.AIDrone._getVisionCanvas = function() {\n    // ── 1순위: Entry.cam.canvas (엔트리 공식 비디오 canvas) ──\n    // 엔트리 비디오 블록이 활성화되면 Entry.cam.canvas에\n    // 매 프레임 드론 카메라 영상이 그려진 상태\n    if (typeof Entry !== 'undefined' &&\n        Entry.cam &&\n        Entry.cam.isVideo &&\n        Entry.cam.canvas &&\n        Entry.cam.canvas.width > 0) {\n        return Entry.cam.canvas;\n    }\n\n    // ── 오프스크린 canvas 준비 (2순위, 3순위 공용) ──\n    // OffscreenCanvas: DOM에 엘리먼트를 추가하지 않는 순수 메모리 캔버스.\n    // 엔트리가 동작하는 Chrome 환경(69+)은 OffscreenCanvas를 지원하므로\n    // document.createElement('canvas')를 사용하지 않습니다.\n    if (!Entry.AIDrone._offCanvas) {\n        Entry.AIDrone._offCanvas = new OffscreenCanvas(640, 480);\n        Entry.AIDrone._offCtx    = Entry.AIDrone._offCanvas.getContext('2d');\n    }\n    var oc = Entry.AIDrone._offCanvas;\n    var ox = Entry.AIDrone._offCtx;\n\n    // ── 2순위: Entry.cam.video → 오프스크린 canvas ──\n    if (typeof Entry !== 'undefined' &&\n        Entry.cam &&\n        Entry.cam.video &&\n        Entry.cam.video.readyState >= 2 &&\n        Entry.cam.video.videoWidth > 0) {\n        var v = Entry.cam.video;\n        if (oc.width !== v.videoWidth || oc.height !== v.videoHeight) {\n            oc.width  = v.videoWidth;\n            oc.height = v.videoHeight;\n        }\n        try {\n            ox.drawImage(v, 0, 0, oc.width, oc.height);\n            return oc;\n        } catch(e) {}\n    }\n\n    // ── 3순위: DOM에서 재생 중인 <video> 탐색 ──\n    var videos = document.querySelectorAll('video');\n    for (var i = 0; i < videos.length; i++) {\n        var vid = videos[i];\n        if (!vid.paused && vid.readyState >= 2 && vid.videoWidth > 0) {\n            if (oc.width !== vid.videoWidth || oc.height !== vid.videoHeight) {\n                oc.width  = vid.videoWidth;\n                oc.height = vid.videoHeight;\n            }\n            try {\n                ox.drawImage(vid, 0, 0, oc.width, oc.height);\n                return oc;\n            } catch(e) {}\n            break;\n        }\n    }\n\n    // ── 4순위: Entry.stage.canvas (최후 fallback) ──\n    try {\n        if (Entry.stage && Entry.stage.canvas && Entry.stage.canvas.canvas) {\n            return Entry.stage.canvas.canvas;\n        }\n    } catch(e) {}\n    return null;\n};\n\n// 얼굴 인식 데이터\nEntry.AIDrone.faceData = {\n    detected: false,  // 감지 여부\n    x: 0,             // 얼굴 중심 X (엔트리 좌표계)\n    y: 0,             // 얼굴 중심 Y (엔트리 좌표계)\n    width: 0,         // 얼굴 폭(pixel)\n    height: 0         // 얼굴 높이(pixel)\n};\nEntry.AIDrone._faceTrackerTask = null;   // 실행 중인 얼굴 TrackerTask\nEntry.AIDrone._faceTrackerVideo = null;  // 웹캠 video 엘리먼트\n\n// 얼굴 랜드마크 데이터 (68점 배열)  landmarks[i] = {x, y}\nEntry.AIDrone.landmarkData = [];\n\n\nEntry.AIDrone.getBlocks = function() {\n    return {\n        //region AIDrone\n        aidrone_takeoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_takeoff',\n            },\n            paramsKeyMap: {},\n            class: 'AIDrone_Command',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                }\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.AIDrone.Cmd.CMD_THROTTLE_LOW] = 70;\n                cmd[Entry.AIDrone.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.AIDrone.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_LOW] = 0x2F;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_HIGH] = 0;\n\n                Entry.hw.sendQueue.rollCnt = 0;\n                Entry.hw.sendQueue.pitchCnt = 0;\n                Entry.hw.sendQueue.yawCnt = 0;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_landing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_landing',\n            },\n            paramsKeyMap: {},\n            class: 'AIDrone_Command',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.AIDrone.Cmd.CMD_THROTTLE_LOW] = 0;\n                cmd[Entry.AIDrone.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.AIDrone.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_LOW] = 0x2F;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_HIGH] = 0;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_altitude: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '100',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_altitude',\n            },\n            paramsKeyMap: {\n                THROTTLE: 0,\n            },\n            class: 'AIDrone_Command',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var throttle = script.getNumberValue('THROTTLE', script);\n                cmd[Entry.AIDrone.Cmd.CMD_THROTTLE_LOW] = throttle & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_THROTTLE_HIGH] = (throttle >> 8) & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_LOW] = 0x2F;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_throttle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_throttle',\n            },\n            paramsKeyMap: {\n                THROTTLE: 0,\n            },\n            class: 'AIDrone_Command',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var throttle = script.getNumberValue('THROTTLE', script);\n                // 0~100 범위로 클리핑 후 ×10 하여 0~1000 스케일로 변환\n                throttle = Math.round(Math.min(100, Math.max(0, throttle)) * 10);\n                cmd[Entry.AIDrone.Cmd.CMD_THROTTLE_LOW] = throttle & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_THROTTLE_HIGH] = (throttle >> 8) & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_LOW] = 0x09;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        aidrone_velocity: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.aidrone_dir_front, 0],\n                        [Lang.template.aidrone_dir_back, 1],\n                        [Lang.template.aidrone_dir_right, 2],\n                        [Lang.template.aidrone_dir_left, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_velocity',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VELOCITY: 1,\n            },\n            class: 'AIDrone_Command',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if ((direction == 1) || (direction == 3))\n                    velocity = velocity * -1;\n                if (direction < 2) {\n                    cmd[Entry.AIDrone.Cmd.CMD_PITCH_LOW] = velocity & 0xFF;\n                    cmd[Entry.AIDrone.Cmd.CMD_PITCH_HIGH] = (velocity >> 8) & 0xFF;\n                } else {\n                    cmd[Entry.AIDrone.Cmd.CMD_ROLL_LOW] = velocity & 0xFF;\n                    cmd[Entry.AIDrone.Cmd.CMD_ROLL_HIGH] = (velocity >> 8) & 0xFF;\n                }\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_LOW] = cmd[Entry.AIDrone.Cmd.CMD_OPTION_LOW] & 0xDF;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_distance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.aidrone_dir_front, 0],\n                        [Lang.template.aidrone_dir_back, 1],\n                        [Lang.template.aidrone_dir_right, 2],\n                        [Lang.template.aidrone_dir_left, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '100',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_distance',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DISTANCE: 1,\n                VELOCITY: 2,\n            },\n            class: 'AIDrone_Command',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var distance = script.getNumberValue('DISTANCE', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if ((direction == 1) || (direction == 3))\n                    distance = distance * -1;\n                if (direction < 2) {\n                    cmd[Entry.AIDrone.Cmd.CMD_PITCH_LOW] = distance & 0xFF;\n                    cmd[Entry.AIDrone.Cmd.CMD_PITCH_HIGH] = (distance >> 8) & 0xFF;\n                    var pitchCnt = Entry.hw.sendQueue.pitchCnt;\n                    Entry.hw.sendQueue.pitchCnt = typeof pitchCnt == 'undefined' ? 1 : pitchCnt + 1;\n\n                } else {\n                    cmd[Entry.AIDrone.Cmd.CMD_ROLL_LOW] = distance & 0xFF;\n                    cmd[Entry.AIDrone.Cmd.CMD_ROLL_HIGH] = (distance >> 8) & 0xFF;\n                    var rollCnt = Entry.hw.sendQueue.rollCnt;\n                    Entry.hw.sendQueue.rollCnt = typeof rollCnt == 'undefined' ? 1 : rollCnt + 1;\n                }\n                cmd[Entry.AIDrone.Cmd.CMD_POSVEL_LOW] = velocity & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_POSVEL_HIGH] = (velocity >> 8) & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_LOW] = 0x2F;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', 0],\n                        ['반시계방향', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '90',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_degree',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DEGREE: 1,\n                VELOCITY: 2,\n            },\n            class: 'AIDrone_Command',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var degree = script.getNumberValue('DEGREE', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if (direction == 1)\n                    degree = degree * -1;\n                cmd[Entry.AIDrone.Cmd.CMD_YAW_LOW] = degree & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_YAW_HIGH] = (degree >> 8) & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_YAWVEL_LOW] = velocity & 0xFF;\n                cmd[Entry.AIDrone.Cmd.CMD_YAWVEL_HIGH] = (velocity >> 8) & 0xFF;\n                var yawCnt = Entry.hw.sendQueue.yawCnt;\n                Entry.hw.sendQueue.yawCnt = typeof yawCnt == 'undefined' ? 1 : yawCnt + 1;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_emergency: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_emergency',\n            },\n            paramsKeyMap: {},\n            class: 'AIDrone_Command',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.AIDrone.Cmd.CMD_THROTTLE_LOW] = 0;\n                cmd[Entry.AIDrone.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.AIDrone.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_LOW] = 0x00;\n                cmd[Entry.AIDrone.Cmd.CMD_OPTION_HIGH] = 0;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_connect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_connect',\n            },\n            class: 'AIDrone_Sensor',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                return sensorData[Entry.AIDrone.Sensor.SENSOR_DRONECONNECT];\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_ready: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_ready',\n            },\n            class: 'AIDrone_Sensor',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData ? sensorData[Entry.AIDrone.Sensor.SENSOR_DRONEREADY] : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_battery: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_battery',\n            },\n            class: 'AIDrone_Sensor',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                return sensorData[Entry.AIDrone.Sensor.SENSOR_BATTERY];\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_dronealt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_dronealt',\n            },\n            class: 'AIDrone_Sensor',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                return sensorData[Entry.AIDrone.Sensor.SENSOR_DRONEALT];\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_gyrox: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_gyrox',\n            },\n            class: 'AIDrone_Sensor',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                var x = sensorData[Entry.AIDrone.Sensor.SENSOR_GYRO_X];\n                if (x > 127)\n                    x = -1 * (256 - x);\n                return x;\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_gyroy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_gyroy',\n            },\n            class: 'AIDrone_Sensor',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                var y = sensorData[Entry.AIDrone.Sensor.SENSOR_GYRO_Y];\n                if (y > 127)\n                    y = -1 * (256 - y);\n                return y;\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_posx: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_posx',\n            },\n            class: 'AIDrone_Sensor',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                var posx = sensorData[Entry.AIDrone.Sensor.SENSOR_POSX_L] + sensorData[Entry.AIDrone.Sensor.SENSOR_POSX_H] * 256;\n                if (posx > 32767)\n                    posx = -1 * (65536 - posx);\n                return posx;\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_posy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_posy',\n            },\n            class: 'AIDrone_Sensor',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                var posy = sensorData[Entry.AIDrone.Sensor.SENSOR_POSY_L] + sensorData[Entry.AIDrone.Sensor.SENSOR_POSY_H] * 256;\n                if (posy > 32767)\n                    posy = -1 * (65536 - posy);\n                return posy;\n\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        aidrone_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '1',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'aidrone_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'AIDrone_CodeRC',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var value = script.getNumberValue('VALUE', script);\n                cmd[Entry.AIDrone.Cmd.CMD_LED] = value > 255 ? 255 : value < 0 ? 0 : value;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_tune: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '4',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '1',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'aidrone_tune',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                DURATION: 1,\n            },\n            class: 'AIDrone_CodeRC',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var note = script.getNumberValue('NOTE', script);\n                var duration = script.getNumberValue('DURATION', script);\n                cmd[Entry.AIDrone.Cmd.CMD_TUNE] = note > 255 ? 255 : note < 0 ? 0 : note;\n                cmd[Entry.AIDrone.Cmd.CMD_TUNEDUR] = duration > 255 ? 255 : duration < 0 ? 0 : duration;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['모터 앞-왼쪽', 1],\n                        ['모터 뒤-왼쪽', 2],\n                        ['모터 앞-오른쪽', 0],\n                        ['모터 뒤-오른쪽', 3],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '15',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'aidrone_motor',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                POWER: 1,\n            },\n            class: 'AIDrone_CodeRC',\n            isNotFor: ['AIDrone'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var motor = script.getField('MOTOR', script);\n                var power = script.getNumberValue('POWER', script);\n\n                cmd[Entry.AIDrone.Cmd.CMD_MOTOR0 + motor] =\n                    power > 100 ? 100 : power < 0 ? 0 : power;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        aidrone_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽 좌우', 1],\n                        ['왼쪽 상하', 2],\n                        ['오른쪽 좌우', 3],\n                        ['오른쪽 상하', 4],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_joystick',\n            },\n            paramsKeyMap: {\n                CHANNEL: 0,\n            },\n            class: 'AIDrone_CodeRC',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                var channel = script.getField('CHANNEL', script);\n                var sensorMap = {\n                    1: Entry.AIDrone.Sensor.SENSOR_JOYSTICK_LLR,\n                    2: Entry.AIDrone.Sensor.SENSOR_JOYSTICK_LTB,\n                    3: Entry.AIDrone.Sensor.SENSOR_JOYSTICK_RLR,\n                    4: Entry.AIDrone.Sensor.SENSOR_JOYSTICK_RTB,\n                };\n                return sensorData[sensorMap[channel]] || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        aidrone_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '1',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'aidrone_button',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'AIDrone_CodeRC',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                if (!sensorData) return 0;\n                return sensorData[Entry.AIDrone.Sensor.SENSOR_BUTTON] || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        // 1. [기능 블록] 화면에서 마커 찾기\n        aidrone_detect_marker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_detect_marker' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                // 1) 라이브러리 로딩 체크\n                if (typeof AR === 'undefined' || typeof CV === 'undefined') {\n                    // 라이브러리가 없으면 아무것도 안 함\n                    return script.callReturn();\n                }\n\n                // 2) 비전 소스 canvas 획득 (video 스프라이트 우선)\n                var canvas = Entry.AIDrone._getVisionCanvas();\n                if (!canvas) return script.callReturn();\n\n                try {\n                    var ctx = canvas.getContext('2d');\n                    var width = canvas.width;\n                    var height = canvas.height;\n\n                    // 3) 현재 프레임 캡처\n                    var imageData = ctx.getImageData(0, 0, width, height);\n\n                    // 4) AR.Detector 재사용 (매번 생성하면 메모리 낭비)\n                    if (!Entry.AIDrone._arDetector) {\n                        Entry.AIDrone._arDetector = new AR.Detector();\n                    }\n                    var detector = Entry.AIDrone._arDetector;\n                    var markers = detector.detect(imageData);\n\n                    // 5) 결과 저장\n                    if (markers.length > 0) {\n                        var m = markers[0]; // 가장 먼저 발견된 마커 1개만 사용\n                        Entry.AIDrone.visionData.id = m.id;\n\n                        // 중심점 계산 (4개 모서리의 평균)\n                        var cx = (m.corners[0].x + m.corners[1].x + m.corners[2].x + m.corners[3].x) / 4;\n                        var cy = (m.corners[0].y + m.corners[1].y + m.corners[2].y + m.corners[3].y) / 4;\n\n                        // 엔트리 좌표계로 변환 (중앙이 0,0)\n                        Entry.AIDrone.visionData.x = cx - (width / 2);\n                        Entry.AIDrone.visionData.y = (height / 2) - cy;\n\n                        // 거리 계산 (마커가 클수록 가까움)\n                        // corners[0]~corners[2]는 대각선 방향 → 정확한 변 길이 계산으로 수정\n                        var dx01 = m.corners[1].x - m.corners[0].x;\n                        var dy01 = m.corners[1].y - m.corners[0].y;\n                        var dx12 = m.corners[2].x - m.corners[1].x;\n                        var dy12 = m.corners[2].y - m.corners[1].y;\n                        var side1 = Math.sqrt(dx01*dx01 + dy01*dy01);\n                        var side2 = Math.sqrt(dx12*dx12 + dy12*dy12);\n                        var pixelWidth = Math.round((side1 + side2) / 2); // 평균 변 길이\n                        Entry.AIDrone.visionData.width = pixelWidth;\n                        Entry.AIDrone.visionData.dist = pixelWidth > 0 ? Math.round(3000 / pixelWidth) : 0;\n\n                    } else {\n                        // 마커가 없으면 ID를 -1로 초기화\n                        Entry.AIDrone.visionData.id = -1;\n                    }\n                } catch (e) {\n                    console.log(\"Marker detect error: \", e);\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // 2. [값 블록] 인식된 마커 정보 가져오기\n        aidrone_get_marker_data: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['마커ID', 'id'],\n                        ['X좌표', 'x'],\n                        ['Y좌표', 'y'],\n                        ['거리(cm)', 'dist'],\n                        ['크기(pixel)', 'width']\n                    ],\n                    value: 'id',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_marker_data' },\n            paramsKeyMap: { DATA_TYPE: 0 },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var key = script.getField('DATA_TYPE', script);\n                return Entry.AIDrone.visionData[key];\n            },\n            syntax: { js: [], py: [] }\n        },\n        // --- [여기까지] 3단계 코드 끝 ---\n\n        // ===================================================\n        // tracking.js 기반 비전 블록 (4단계)\n        // 의존 라이브러리: block_aidrone_tracking.js (window.tracking, window.AR, window.CV)\n        // ===================================================\n\n        // -----------------------------------------------\n        // [블록 1] 색상 추적 시작\n        //   - 드롭다운으로 색상 선택 (cyan / magenta / yellow)\n        //   - 웹캠 영상에서 해당 색상 영역을 지속 감지\n        //   - 결과는 Entry.AIDrone.colorTrackData 에 저장\n        // -----------------------------------------------\n        aidrone_color_track_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['청록색(cyan)', 'cyan'],\n                        ['자홍색(magenta)', 'magenta'],\n                        ['노란색(yellow)', 'yellow']\n                    ],\n                    value: 'cyan',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null, null], type: 'aidrone_color_track_start' },\n            paramsKeyMap: { COLOR: 0 },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                if (typeof tracking === 'undefined') {\n                    console.warn('tracking.js 라이브러리가 로드되지 않았습니다.');\n                    return script.callReturn();\n                }\n\n                // 이미 실행 중이면 중지 후 재시작\n                if (Entry.AIDrone._colorTrackerRunning) {\n                    Entry.AIDrone._colorTrackerRunning = false;\n                    if (Entry.AIDrone._colorTrackerStop) {\n                        Entry.AIDrone._colorTrackerStop();\n                        Entry.AIDrone._colorTrackerStop = null;\n                    }\n                }\n\n                var colorName = script.getField('COLOR', script);\n\n                var tracker = new tracking.ColorTracker([colorName]);\n                tracker.setMinDimension(20);\n                tracker.setMinGroupSize(30);\n\n                tracker.on('track', function(event) {\n                    // 매번 최신 canvas 크기 참조 (클로저 캡처 제거)\n                    var src = Entry.AIDrone._getVisionCanvas();\n                    var w = src ? src.width  : 480;\n                    var h = src ? src.height : 270;\n                    if (event.data.length > 0) {\n                        var biggest = event.data.reduce(function(a, b) {\n                            return (a.width * a.height >= b.width * b.height) ? a : b;\n                        });\n                        var cx = biggest.x + biggest.width  / 2;\n                        var cy = biggest.y + biggest.height / 2;\n                        Entry.AIDrone.colorTrackData.detected = true;\n                        Entry.AIDrone.colorTrackData.x       = Math.round(cx - w / 2);\n                        Entry.AIDrone.colorTrackData.y       = Math.round(h / 2 - cy);\n                        Entry.AIDrone.colorTrackData.width   = Math.round(biggest.width);\n                        Entry.AIDrone.colorTrackData.height  = Math.round(biggest.height);\n                    } else {\n                        Entry.AIDrone.colorTrackData.detected = false;\n                    }\n                });\n\n                // requestAnimationFrame 루프로 매 프레임 분석\n                var raf;\n                function colorLoop() {\n                    if (!Entry.AIDrone._colorTrackerRunning) return;\n                    try {\n                        var src = Entry.AIDrone._getVisionCanvas();\n                        if (!src || !src.width || !src.height) {\n                            raf = requestAnimationFrame(colorLoop);\n                            return;\n                        }\n                        var w = src.width, h = src.height;\n                        var imgData = src.getContext('2d').getImageData(0, 0, w, h);\n                        tracker.track(imgData.data, w, h);\n                    } catch(e) {}\n                    raf = requestAnimationFrame(colorLoop);\n                }\n                Entry.AIDrone._colorTrackerRunning = true;\n                Entry.AIDrone._colorTrackerStop = function() {\n                    Entry.AIDrone._colorTrackerRunning = false;\n                    if (raf) cancelAnimationFrame(raf);\n                };\n                colorLoop();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 2] 색상 추적 중지\n        // -----------------------------------------------\n        aidrone_color_track_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_color_track_stop' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                // RAF 루프 중지\n                if (Entry.AIDrone._colorTrackerStop) {\n                    Entry.AIDrone._colorTrackerStop();\n                    Entry.AIDrone._colorTrackerStop = null;\n                } else {\n                    Entry.AIDrone._colorTrackerRunning = false;\n                }\n                Entry.AIDrone.colorTrackData = { detected: false, x: 0, y: 0, width: 0, height: 0 };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 3] 색상 추적 데이터 읽기 (값 블록)\n        //   반환: detected(감지여부) / x / y / width / height\n        // -----------------------------------------------\n        aidrone_get_color_data: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['감지여부', 'detected'],\n                        ['X좌표',   'x'],\n                        ['Y좌표',   'y'],\n                        ['가로크기', 'width'],\n                        ['세로크기', 'height']\n                    ],\n                    value: 'detected',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_color_data' },\n            paramsKeyMap: { DATA_TYPE: 0 },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var key = script.getField('DATA_TYPE', script);\n                var val = Entry.AIDrone.colorTrackData[key];\n                // detected 는 boolean → 1/0 으로 변환해서 반환\n                if (key === 'detected') return val ? 1 : 0;\n                return val !== undefined ? val : 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 4] 얼굴 인식 (1회 감지)\n        //   - 엔트리 캔버스 현재 프레임에서 ViolaJones 얼굴 감지\n        //   - 결과는 Entry.AIDrone.faceData 에 저장\n        //   - 얼굴이 여러 개면 가장 큰 얼굴 하나만 저장\n        // -----------------------------------------------\n        aidrone_face_detect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_face_detect' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                if (typeof tracking === 'undefined') {\n                    console.warn('tracking.js 라이브러리가 로드되지 않았습니다.');\n                    return script.callReturn();\n                }\n\n                // 비전 소스 canvas 획득 (video 스프라이트 우선)\n                var canvas = Entry.AIDrone._getVisionCanvas();\n                if (!canvas) return script.callReturn();\n\n                try {\n                    var ctx     = canvas.getContext('2d');\n                    var width   = canvas.width;\n                    var height  = canvas.height;\n                    var imgData = ctx.getImageData(0, 0, width, height);\n\n                    // ViolaJones 분류기가 로드되어 있어야 함 (block_aidrone_tracking.js 내 포함)\n                    var faces = tracking.ViolaJones.detect(\n                        imgData.data, width, height,\n                        1,    // initialScale\n                        1.25, // scaleFactor\n                        1.5,  // stepSize\n                        0.1,  // edgesDensity\n                        tracking.ViolaJones.classifiers.face\n                    );\n\n                    if (faces && faces.length > 0) {\n                        // 가장 큰 얼굴 선택\n                        var biggest = faces.reduce(function(a, b) {\n                            return (a.width * a.height >= b.width * b.height) ? a : b;\n                        });\n                        var cx = biggest.x + biggest.width  / 2;\n                        var cy = biggest.y + biggest.height / 2;\n                        Entry.AIDrone.faceData.detected = true;\n                        Entry.AIDrone.faceData.x        = cx - width  / 2;\n                        Entry.AIDrone.faceData.y        = height / 2  - cy;\n                        Entry.AIDrone.faceData.width    = biggest.width;\n                        Entry.AIDrone.faceData.height   = biggest.height;\n\n                        // 랜드마크도 함께 계산 (LBF 모델 활용)\n                        if (tracking.LBF && tracking.LBF.align) {\n                            var gray = tracking.Image.grayscale(imgData.data, width, height, false);\n                            gray = tracking.Image.equalizeHist(gray, width, height);\n                            var bbox = [{\n                                x: biggest.x, y: biggest.y,\n                                width: biggest.width, height: biggest.height\n                            }];\n                            // LBF.align은 그레이스케일 배열을 받아야 함\n                            var landmarks = tracking.LBF.align(gray, width, height, bbox);\n                            if (landmarks && landmarks[0]) {\n                                Entry.AIDrone.landmarkData = landmarks[0].map(function(pt) {\n                                    return {\n                                        x: pt[0] - width  / 2,\n                                        y: height / 2 - pt[1]\n                                    };\n                                });\n                            }\n                        }\n                    } else {\n                        Entry.AIDrone.faceData.detected = false;\n                        Entry.AIDrone.landmarkData = [];\n                    }\n                } catch(e) {\n                    console.log('Face detect error:', e);\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 5] 얼굴 인식 데이터 읽기 (값 블록)\n        //   반환: detected / x / y / width / height\n        // -----------------------------------------------\n        aidrone_get_face_data: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['감지여부', 'detected'],\n                        ['X좌표',   'x'],\n                        ['Y좌표',   'y'],\n                        ['가로크기', 'width'],\n                        ['세로크기', 'height']\n                    ],\n                    value: 'detected',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_face_data' },\n            paramsKeyMap: { DATA_TYPE: 0 },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var key = script.getField('DATA_TYPE', script);\n                var val = Entry.AIDrone.faceData[key];\n                if (key === 'detected') return val ? 1 : 0;\n                return val !== undefined ? val : 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 6] 얼굴 랜드마크 좌표 읽기 (값 블록)\n        //   - 점 번호(0~67) 선택, X 또는 Y 좌표 반환\n        //   - aidrone_face_detect 블록 실행 후 유효\n        //   - 점 번호 의미: 0-16 턱선, 17-21 왼눈썹,\n        //     22-26 오른눈썹, 27-30 코등, 31-35 콧구멍,\n        //     36-41 왼눈, 42-47 오른눈, 48-67 입\n        // -----------------------------------------------\n        aidrone_get_landmark: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string'\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X좌표', 'x'],\n                        ['Y좌표', 'y']\n                    ],\n                    value: 'x',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: { params: [{ type: 'text', params: ['0'] }, null], type: 'aidrone_get_landmark' },\n            paramsKeyMap: { INDEX: 0, AXIS: 1 },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var idx  = parseInt(script.getStringValue('INDEX', script), 10);\n                var axis = script.getField('AXIS', script);\n                if (\n                    isNaN(idx) || idx < 0 || idx > 67 ||\n                    !Entry.AIDrone.landmarkData ||\n                    Entry.AIDrone.landmarkData.length === 0\n                ) {\n                    return 0;\n                }\n                var pt = Entry.AIDrone.landmarkData[idx];\n                return pt ? (pt[axis] !== undefined ? pt[axis] : 0) : 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // ===================================================\n        // ===================================================\n        // 추가 편의 블록 (조건 블록 + 개별 값 블록)\n        // ===================================================\n\n        // -----------------------------------------------\n        // [블록 A] 마커 감지됨? (조건 블록)\n        // -----------------------------------------------\n        aidrone_marker_detected: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_marker_detected' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                return Entry.AIDrone.visionData.id !== -1;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 B] 색상 감지됨? (조건 블록)\n        // -----------------------------------------------\n        aidrone_color_detected: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_color_detected' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                return Entry.AIDrone.colorTrackData.detected === true;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 C] 감지된 색상 X좌표 (값 블록)\n        // -----------------------------------------------\n        aidrone_get_color_x: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_color_x' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                return Entry.AIDrone.colorTrackData.x || 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 D] 감지된 색상 Y좌표 (값 블록)\n        // -----------------------------------------------\n        aidrone_get_color_y: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_color_y' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                return Entry.AIDrone.colorTrackData.y || 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 E] 감지된 색상 크기 (값 블록)\n        // -----------------------------------------------\n        aidrone_get_color_size: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_color_size' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                var d = Entry.AIDrone.colorTrackData;\n                return d.width && d.height ? Math.round((d.width + d.height) / 2) : 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 F] 얼굴 감지됨? (조건 블록)\n        // -----------------------------------------------\n        aidrone_face_detected: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_face_detected' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                return Entry.AIDrone.faceData.detected === true;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 G] 얼굴 X좌표 (값 블록)\n        // -----------------------------------------------\n        aidrone_get_face_x: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_face_x' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                return Entry.AIDrone.faceData.x || 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 H] 얼굴 Y좌표 (값 블록)\n        // -----------------------------------------------\n        aidrone_get_face_y: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_face_y' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                return Entry.AIDrone.faceData.y || 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // -----------------------------------------------\n        // [블록 I] 얼굴 크기 (값 블록)\n        // -----------------------------------------------\n        aidrone_get_face_size: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def: { params: [null], type: 'aidrone_get_face_size' },\n            class: 'AIDrone_Vision',\n            isNotFor: ['AIDrone'],\n            func: function(sprite, script) {\n                // 1. 객체가 존재하는지 먼저 확인\n                if (Entry.AIDrone && Entry.AIDrone.faceData) {\n                    return Entry.AIDrone.faceData.y || 0;\n                }\n                // 2. 객체가 없으면 안전하게 0을 반환하여 에러 방지\n                return 0;\n            },\n            syntax: { js: [], py: [] }\n        },\n\n        // tracking.js 블록 끝\n        // ===================================================\n\n        //endregion AIDrone\n    };\n};\n\nmodule.exports = Entry.AIDrone;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_aidrone_tracking.js",
    "content": "/**\n * tracking - A modern approach for Computer Vision on the web.\n * @author Eduardo Lundgren <edu@rdo.io>\n * @version v1.1.3\n * @link http://trackingjs.com\n * @license BSD\n */\n!function(t,r){t.tracking=t.tracking||{},tracking.inherits=function(t,r){function n(){}n.prototype=r.prototype,t.superClass_=r.prototype,t.prototype=new n,t.prototype.constructor=t,t.base=function(t,n){var e=Array.prototype.slice.call(arguments,2);return r.prototype[n].apply(t,e)}},tracking.initUserMedia_=function(r,n){t.navigator.mediaDevices.getUserMedia({video:!0,audio:!(!n||!n.audio)}).then(function(t){r.srcObject=t})[\"catch\"](function(t){throw Error(\"Cannot capture user camera.\")})},tracking.isNode=function(t){return t.nodeType||this.isWindow(t)},tracking.isWindow=function(t){return!!(t&&t.alert&&t.document)},tracking.one=function(t,r){return this.isNode(t)?t:(r||document).querySelector(t)},tracking.track=function(t,r,n){if(t=tracking.one(t),!t)throw new Error(\"Element not found, try a different element or selector.\");if(!r)throw new Error(\"Tracker not specified, try `tracking.track(element, new tracking.FaceTracker())`.\");switch(t.nodeName.toLowerCase()){case\"canvas\":return this.trackCanvas_(t,r,n);case\"img\":return this.trackImg_(t,r,n);case\"video\":return n&&n.camera&&this.initUserMedia_(t,n),this.trackVideo_(t,r,n);default:throw new Error(\"Element not supported, try in a canvas, img, or video.\")}},tracking.trackCanvas_=function(t,r){var n=this,e=new tracking.TrackerTask(r);return e.on(\"run\",function(){n.trackCanvasInternal_(t,r)}),e.run()},tracking.trackCanvasInternal_=function(t,r){var n=t.width,e=t.height,a=t.getContext(\"2d\"),i=a.getImageData(0,0,n,e);r.track(i.data,n,e)},tracking.trackImg_=function(t,r){var n=t.width,e=t.height,a=document.createElement(\"canvas\");a.width=n,a.height=e;var i=new tracking.TrackerTask(r);return i.on(\"run\",function(){tracking.Canvas.loadImage(a,t.src,0,0,n,e,function(){tracking.trackCanvasInternal_(a,r)})}),i.run()},tracking.trackVideo_=function(r,n){var e,a,i=document.createElement(\"canvas\"),o=i.getContext(\"2d\"),c=function(){e=r.offsetWidth,a=r.offsetHeight,i.width=e,i.height=a};c(),r.addEventListener(\"resize\",c);var s,g=function(){s=t.requestAnimationFrame(function(){if(r.readyState===r.HAVE_ENOUGH_DATA){try{o.drawImage(r,0,0,e,a)}catch(t){}tracking.trackCanvasInternal_(i,n)}g()})},h=new tracking.TrackerTask(n);return h.on(\"stop\",function(){t.cancelAnimationFrame(s)}),h.on(\"run\",function(){g()}),h.run()},t.URL||(t.URL=t.URL||t.webkitURL||t.msURL||t.oURL),navigator.getUserMedia||(navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia)}(window),function(){tracking.EventEmitter=function(){},tracking.EventEmitter.prototype.events_=null,tracking.EventEmitter.prototype.addListener=function(t,r){if(\"function\"!=typeof r)throw new TypeError(\"Listener must be a function\");return this.events_||(this.events_={}),this.emit(\"newListener\",t,r),this.events_[t]||(this.events_[t]=[]),this.events_[t].push(r),this},tracking.EventEmitter.prototype.listeners=function(t){return this.events_&&this.events_[t]},tracking.EventEmitter.prototype.emit=function(t){var r=this.listeners(t);if(r){for(var n=Array.prototype.slice.call(arguments,1),e=0;e<r.length;e++)r[e]&&r[e].apply(this,n);return!0}return!1},tracking.EventEmitter.prototype.on=tracking.EventEmitter.prototype.addListener,tracking.EventEmitter.prototype.once=function(t,r){var n=this;n.on(t,function e(){n.removeListener(t,e),r.apply(this,arguments)})},tracking.EventEmitter.prototype.removeAllListeners=function(t){return this.events_?(t?delete this.events_[t]:delete this.events_,this):this},tracking.EventEmitter.prototype.removeListener=function(t,r){if(\"function\"!=typeof r)throw new TypeError(\"Listener must be a function\");if(!this.events_)return this;var n=this.listeners(t);if(Array.isArray(n)){var e=n.indexOf(r);if(e<0)return this;n.splice(e,1)}return this},tracking.EventEmitter.prototype.setMaxListeners=function(){throw new Error(\"Not implemented\")}}(),function(){tracking.Canvas={},tracking.Canvas.loadImage=function(t,r,n,e,a,i,o){var c=this,s=new window.Image;s.crossOrigin=\"*\",s.onload=function(){var r=t.getContext(\"2d\");t.width=a,t.height=i,r.drawImage(s,n,e,a,i),o&&o.call(c),s=null},s.src=r}}(),function(){tracking.DisjointSet=function(t){if(void 0===t)throw new Error(\"DisjointSet length not specified.\");this.length=t,this.parent=new Uint32Array(t);for(var r=0;r<t;r++)this.parent[r]=r},tracking.DisjointSet.prototype.length=null,tracking.DisjointSet.prototype.parent=null,tracking.DisjointSet.prototype.find=function(t){return this.parent[t]===t?t:this.parent[t]=this.find(this.parent[t])},tracking.DisjointSet.prototype.union=function(t,r){var n=this.find(t),e=this.find(r);this.parent[n]=e}}(),function(){tracking.Image={},tracking.Image.blur=function(t,r,n,e){if(e=Math.abs(e),e<=1)throw new Error(\"Diameter should be greater than 1.\");for(var a=e/2,i=Math.ceil(e)+(1-Math.ceil(e)%2),o=new Float32Array(i),c=(a+.5)/3,s=c*c,g=1/Math.sqrt(2*Math.PI*s),h=-1/(2*c*c),k=0,f=Math.floor(i/2),u=0;u<i;u++){var l=u-f,m=g*Math.exp(l*l*h);o[u]=m,k+=m}for(var d=0;d<o.length;d++)o[d]/=k;return this.separableConvolve(t,r,n,o,o,!1)},tracking.Image.computeIntegralImage=function(t,r,n,e,a,i,o){if(arguments.length<4)throw new Error(\"You should specify at least one output array in the order: sum, square, tilted, sobel.\");var c;o&&(c=tracking.Image.sobel(t,r,n));for(var s=0;s<n;s++)for(var g=0;g<r;g++){var h=s*r*4+4*g,k=~~(.299*t[h]+.587*t[h+1]+.114*t[h+2]);if(e&&this.computePixelValueSAT_(e,r,s,g,k),a&&this.computePixelValueSAT_(a,r,s,g,k*k),i){var f=h-4*r,u=~~(.299*t[f]+.587*t[f+1]+.114*t[f+2]);this.computePixelValueRSAT_(i,r,s,g,k,u||0)}o&&this.computePixelValueSAT_(o,r,s,g,c[h])}},tracking.Image.computePixelValueRSAT_=function(t,r,n,e,a,i){var o=n*r+e;t[o]=(t[o-r-1]||0)+(t[o-r+1]||0)-(t[o-r-r]||0)+a+i},tracking.Image.computePixelValueSAT_=function(t,r,n,e,a){var i=n*r+e;t[i]=(t[i-r]||0)+(t[i-1]||0)+a-(t[i-r-1]||0)},tracking.Image.grayscale=function(t,r,n,e){for(var a=new Uint8ClampedArray(e?t.length:t.length>>2),i=0,o=0,c=0;c<n;c++)for(var s=0;s<r;s++){var g=.299*t[o]+.587*t[o+1]+.114*t[o+2];a[i++]=g,e&&(a[i++]=g,a[i++]=g,a[i++]=t[o+3]),o+=4}return a},tracking.Image.horizontalConvolve=function(t,r,n,e,a){for(var i=e.length,o=Math.floor(i/2),c=new Float32Array(r*n*4),s=a?1:0,g=0;g<n;g++)for(var h=0;h<r;h++){for(var k=g,f=h,u=4*(g*r+h),l=0,m=0,d=0,v=0,p=0;p<i;p++){var y=k,w=Math.min(r-1,Math.max(0,f+p-o)),T=4*(y*r+w),x=e[p];l+=t[T]*x,m+=t[T+1]*x,d+=t[T+2]*x,v+=t[T+3]*x}c[u]=l,c[u+1]=m,c[u+2]=d,c[u+3]=v+s*(255-v)}return c},tracking.Image.verticalConvolve=function(t,r,n,e,a){for(var i=e.length,o=Math.floor(i/2),c=new Float32Array(r*n*4),s=a?1:0,g=0;g<n;g++)for(var h=0;h<r;h++){for(var k=g,f=h,u=4*(g*r+h),l=0,m=0,d=0,v=0,p=0;p<i;p++){var y=Math.min(n-1,Math.max(0,k+p-o)),w=f,T=4*(y*r+w),x=e[p];l+=t[T]*x,m+=t[T+1]*x,d+=t[T+2]*x,v+=t[T+3]*x}c[u]=l,c[u+1]=m,c[u+2]=d,c[u+3]=v+s*(255-v)}return c},tracking.Image.separableConvolve=function(t,r,n,e,a,i){var o=this.verticalConvolve(t,r,n,a,i);return this.horizontalConvolve(o,r,n,e,i)},tracking.Image.sobel=function(t,r,n){t=this.grayscale(t,r,n,!0);for(var e=new Float32Array(r*n*4),a=new Float32Array([-1,0,1]),i=new Float32Array([1,2,1]),o=this.separableConvolve(t,r,n,a,i),c=this.separableConvolve(t,r,n,i,a),s=0;s<e.length;s+=4){var g=o[s],h=c[s],k=Math.sqrt(h*h+g*g);e[s]=k,e[s+1]=k,e[s+2]=k,e[s+3]=255}return e},tracking.Image.equalizeHist=function(t,r,n){for(var e=new Uint8ClampedArray(t.length),a=new Array(256),i=0;i<256;i++)a[i]=0;for(var i=0;i<t.length;i++)e[i]=t[i],a[t[i]]++;for(var o=a[0],i=0;i<256;i++)a[i]+=o,o=a[i];for(var c=255/t.length,i=0;i<t.length;i++)e[i]=a[t[i]]*c+.5|0;return e}}(),function(){tracking.ViolaJones={},tracking.ViolaJones.REGIONS_OVERLAP=.5,tracking.ViolaJones.classifiers={},tracking.ViolaJones.detect=function(t,r,n,e,a,i,o,c){var s,g=0,h=[],k=new Int32Array(r*n),f=new Int32Array(r*n),u=new Int32Array(r*n);o>0&&(s=new Int32Array(r*n)),tracking.Image.computeIntegralImage(t,r,n,k,f,u,s);for(var l=c[0],m=c[1],d=e*a,v=d*l|0,p=d*m|0;v<r&&p<n;){for(var y=d*i+.5|0,w=0;w<n-p;w+=y)for(var T=0;T<r-v;T+=y)o>0&&this.isTriviallyExcluded(o,s,w,T,r,v,p)||this.evalStages_(c,k,f,u,w,T,r,v,p,d)&&(h[g++]={width:v,height:p,x:T,y:w});d*=a,v=d*l|0,p=d*m|0}return this.mergeRectangles_(h)},tracking.ViolaJones.isTriviallyExcluded=function(t,r,n,e,a,i,o){var c=n*a+e,s=c+i,g=c+o*a,h=g+i,k=(r[c]-r[s]-r[g]+r[h])/(i*o*255);return k<t},tracking.ViolaJones.evalStages_=function(t,r,n,e,a,i,o,c,s,g){var h=1/(c*s),k=a*o+i,f=k+c,u=k+s*o,l=u+c,m=(r[k]-r[f]-r[u]+r[l])*h,d=(n[k]-n[f]-n[u]+n[l])*h-m*m,v=1;d>0&&(v=Math.sqrt(d));for(var p=t.length,y=2;y<p;){for(var w=0,T=t[y++],x=t[y++];x--;){for(var M=0,_=t[y++],C=t[y++],E=0;E<C;E++){var F,B,L,S,A=i+t[y++]*g+.5|0,I=a+t[y++]*g+.5|0,R=t[y++]*g+.5|0,b=t[y++]*g+.5|0,D=t[y++];_?(F=A-b+R+(I+R+b-1)*o,B=A+(I-1)*o,L=A-b+(I+b-1)*o,S=A+R+(I+R-1)*o,M+=(e[F]+e[B]-e[L]-e[S])*D):(F=I*o+A,B=F+R,L=F+b*o,S=L+R,M+=(r[F]-r[B]-r[L]+r[S])*D)}var O=t[y++],N=t[y++],j=t[y++];w+=M*h<O*v?N:j}if(w<T)return!1}return!0},tracking.ViolaJones.mergeRectangles_=function(t){for(var r=new tracking.DisjointSet(t.length),n=0;n<t.length;n++)for(var e=t[n],a=0;a<t.length;a++){var i=t[a];if(tracking.Math.intersectRect(e.x,e.y,e.x+e.width,e.y+e.height,i.x,i.y,i.x+i.width,i.y+i.height)){var o=Math.max(e.x,i.x),c=Math.max(e.y,i.y),s=Math.min(e.x+e.width,i.x+i.width),g=Math.min(e.y+e.height,i.y+i.height),h=(o-s)*(c-g),k=e.width*e.height,f=i.width*i.height;h/(k*(k/f))>=this.REGIONS_OVERLAP&&h/(f*(k/f))>=this.REGIONS_OVERLAP&&r.union(n,a)}}for(var u={},l=0;l<r.length;l++){var m=r.find(l);u[m]?(u[m].total++,u[m].width+=t[l].width,u[m].height+=t[l].height,u[m].x+=t[l].x,u[m].y+=t[l].y):u[m]={total:1,width:t[l].width,height:t[l].height,x:t[l].x,y:t[l].y}}var d=[];return Object.keys(u).forEach(function(t){var r=u[t];d.push({total:r.total,width:r.width/r.total+.5|0,height:r.height/r.total+.5|0,x:r.x/r.total+.5|0,y:r.y/r.total+.5|0})}),d}}(),function(){tracking.Brief={},tracking.Brief.N=512,tracking.Brief.randomImageOffsets_={},tracking.Brief.randomWindowOffsets_=null,tracking.Brief.getDescriptors=function(t,r,n){for(var e=new Int32Array((n.length>>1)*(this.N>>5)),a=0,i=this.getRandomOffsets_(r),o=0,c=0;c<n.length;c+=2)for(var s=r*n[c+1]+n[c],g=0,h=0,k=this.N;h<k;h++)t[i[g++]+s]<t[i[g++]+s]&&(a|=1<<(31&h)),h+1&31||(e[o++]=a,a=0);return e},tracking.Brief.match=function(t,r,n,e){for(var a=t.length>>1,i=n.length>>1,o=new Array(a),c=0;c<a;c++){for(var s=1/0,g=0,h=0;h<i;h++){for(var k=0,f=0,u=this.N>>5;f<u;f++)k+=tracking.Math.hammingWeight(r[c*u+f]^e[h*u+f]);k<s&&(s=k,g=h)}o[c]={index1:c,index2:g,keypoint1:[t[2*c],t[2*c+1]],keypoint2:[n[2*g],n[2*g+1]],confidence:1-s/this.N}}return o},tracking.Brief.reciprocalMatch=function(t,r,n,e){var a=[];if(0===t.length||0===n.length)return a;for(var i=tracking.Brief.match(t,r,n,e),o=tracking.Brief.match(n,e,t,r),c=0;c<i.length;c++)o[i[c].index2].index2===c&&a.push(i[c]);return a},tracking.Brief.getRandomOffsets_=function(t){if(!this.randomWindowOffsets_){for(var r=0,n=new Int32Array(4*this.N),e=0;e<this.N;e++)n[r++]=Math.round(tracking.Math.uniformRandom(-15,16)),n[r++]=Math.round(tracking.Math.uniformRandom(-15,16)),n[r++]=Math.round(tracking.Math.uniformRandom(-15,16)),n[r++]=Math.round(tracking.Math.uniformRandom(-15,16));this.randomWindowOffsets_=n}if(!this.randomImageOffsets_[t]){for(var a=0,i=new Int32Array(2*this.N),o=0;o<this.N;o++)i[a++]=this.randomWindowOffsets_[4*o]*t+this.randomWindowOffsets_[4*o+1],i[a++]=this.randomWindowOffsets_[4*o+2]*t+this.randomWindowOffsets_[4*o+3];this.randomImageOffsets_[t]=i}return this.randomImageOffsets_[t]}}(),function(){tracking.Fast={},tracking.Fast.THRESHOLD=40,tracking.Fast.circles_={},tracking.Fast.findCorners=function(t,r,n,e){var a=this.getCircleOffsets_(r),i=new Int32Array(16),o=[];void 0===e&&(e=this.THRESHOLD);for(var c=3;c<n-3;c++)for(var s=3;s<r-3;s++){for(var g=c*r+s,h=t[g],k=0;k<16;k++)i[k]=t[g+a[k]];this.isCorner(h,i,e)&&(o.push(s,c),s+=3)}return o},tracking.Fast.isBrighter=function(t,r,n){return t-r>n},tracking.Fast.isCorner=function(t,r,n){if(this.isTriviallyExcluded(r,t,n))return!1;for(var e=0;e<16;e++){for(var a=!0,i=!0,o=0;o<9;o++){var c=r[e+o&15];if(!this.isBrighter(t,c,n)&&(i=!1,a===!1))break;if(!this.isDarker(t,c,n)&&(a=!1,i===!1))break}if(i||a)return!0}return!1},tracking.Fast.isDarker=function(t,r,n){return r-t>n},tracking.Fast.isTriviallyExcluded=function(t,r,n){var e=0,a=t[8],i=t[12],o=t[4],c=t[0];return this.isBrighter(c,r,n)&&e++,this.isBrighter(o,r,n)&&e++,this.isBrighter(a,r,n)&&e++,this.isBrighter(i,r,n)&&e++,e<3&&(e=0,this.isDarker(c,r,n)&&e++,this.isDarker(o,r,n)&&e++,this.isDarker(a,r,n)&&e++,this.isDarker(i,r,n)&&e++,e<3)},tracking.Fast.getCircleOffsets_=function(t){if(this.circles_[t])return this.circles_[t];var r=new Int32Array(16);return r[0]=-t-t-t,r[1]=r[0]+1,r[2]=r[1]+t+1,r[3]=r[2]+t+1,r[4]=r[3]+t,r[5]=r[4]+t,r[6]=r[5]+t-1,r[7]=r[6]+t-1,r[8]=r[7]-1,r[9]=r[8]-1,r[10]=r[9]-t-1,r[11]=r[10]-t-1,r[12]=r[11]-t,r[13]=r[12]-t,r[14]=r[13]-t+1,r[15]=r[14]-t+1,this.circles_[t]=r,r}}(),function(){tracking.Math={},tracking.Math.distance=function(t,r,n,e){var a=n-t,i=e-r;return Math.sqrt(a*a+i*i)},tracking.Math.hammingWeight=function(t){return t-=t>>1&1431655765,t=(858993459&t)+(t>>2&858993459),16843009*(t+(t>>4)&252645135)>>24},tracking.Math.uniformRandom=function(t,r){return t+Math.random()*(r-t)},tracking.Math.intersectRect=function(t,r,n,e,a,i,o,c){return!(a>n||o<t||i>e||c<r)}}(),function(){tracking.Matrix={},tracking.Matrix.forEach=function(t,r,n,e,a){a=a||1;for(var i=0;i<n;i+=a)for(var o=0;o<r;o+=a){var c=i*r*4+4*o;e.call(this,t[c],t[c+1],t[c+2],t[c+3],c,i,o)}},tracking.Matrix.sub=function(t,r){for(var n=tracking.Matrix.clone(t),e=0;e<n.length;e++)for(var a=0;a<n[e].length;a++)n[e][a]-=r[e][a];return n},tracking.Matrix.add=function(t,r){for(var n=tracking.Matrix.clone(t),e=0;e<n.length;e++)for(var a=0;a<n[e].length;a++)n[e][a]+=r[e][a];return n},tracking.Matrix.clone=function(t,r,n){r=r||t[0].length,n=n||t.length;for(var e=new Array(n),a=n;a--;){e[a]=new Array(r);for(var i=r;i--;)e[a][i]=t[a][i]}return e},tracking.Matrix.mulScalar=function(t,r){for(var n=tracking.Matrix.clone(r),e=0;e<r.length;e++)for(var a=0;a<r[e].length;a++)n[e][a]*=t;return n},tracking.Matrix.transpose=function(t){for(var r=new Array(t[0].length),n=0;n<t[0].length;n++){r[n]=new Array(t.length);for(var e=0;e<t.length;e++)r[n][e]=t[e][n]}return r},tracking.Matrix.mul=function(t,r){for(var n=new Array(t.length),e=0;e<t.length;e++){n[e]=new Array(r[0].length);for(var a=0;a<r[0].length;a++){n[e][a]=0;for(var i=0;i<t[0].length;i++)n[e][a]+=t[e][i]*r[i][a]}}return n},tracking.Matrix.norm=function(t){for(var r=0,n=0;n<t.length;n++)for(var e=0;e<t[n].length;e++)r+=t[n][e]*t[n][e];return Math.sqrt(r)},tracking.Matrix.calcCovarMatrix=function(t){for(var r=new Array(t.length),n=0;n<t.length;n++){r[n]=[0];for(var e=0;e<t[n].length;e++)r[n][0]+=t[n][e]/t[n].length}for(var a=tracking.Matrix.clone(r),n=0;n<a.length;n++)for(var e=0;e<t[0].length-1;e++)a[n].push(a[n][0]);var i=tracking.Matrix.sub(t,a),o=tracking.Matrix.transpose(i),c=tracking.Matrix.mul(o,i);return[c,r]}}(),function(){tracking.EPnP={},tracking.EPnP.solve=function(t,r,n){}}(),function(){tracking.Tracker=function(){tracking.Tracker.base(this,\"constructor\")},tracking.inherits(tracking.Tracker,tracking.EventEmitter),tracking.Tracker.prototype.track=function(){}}(),function(){tracking.TrackerTask=function(t){if(tracking.TrackerTask.base(this,\"constructor\"),!t)throw new Error(\"Tracker instance not specified.\");this.setTracker(t)},tracking.inherits(tracking.TrackerTask,tracking.EventEmitter),tracking.TrackerTask.prototype.tracker_=null,tracking.TrackerTask.prototype.running_=!1,tracking.TrackerTask.prototype.getTracker=function(){return this.tracker_},tracking.TrackerTask.prototype.inRunning=function(){return this.running_},tracking.TrackerTask.prototype.setRunning=function(t){this.running_=t},tracking.TrackerTask.prototype.setTracker=function(t){this.tracker_=t},tracking.TrackerTask.prototype.run=function(){var t=this;if(!this.inRunning())return this.setRunning(!0),this.reemitTrackEvent_=function(r){t.emit(\"track\",r)},this.tracker_.on(\"track\",this.reemitTrackEvent_),this.emit(\"run\"),this},tracking.TrackerTask.prototype.stop=function(){if(this.inRunning())return this.setRunning(!1),this.emit(\"stop\"),this.tracker_.removeListener(\"track\",this.reemitTrackEvent_),this}}(),function(){tracking.ColorTracker=function(t){tracking.ColorTracker.base(this,\"constructor\"),\"string\"==typeof t&&(t=[t]),t&&(t.forEach(function(t){if(!tracking.ColorTracker.getColor(t))throw new Error('Color not valid, try `new tracking.ColorTracker(\"magenta\")`.')}),this.setColors(t))},tracking.inherits(tracking.ColorTracker,tracking.Tracker),tracking.ColorTracker.knownColors_={},tracking.ColorTracker.neighbours_={},tracking.ColorTracker.registerColor=function(t,r){tracking.ColorTracker.knownColors_[t]=r},tracking.ColorTracker.getColor=function(t){return tracking.ColorTracker.knownColors_[t]},tracking.ColorTracker.prototype.colors=[\"magenta\"],tracking.ColorTracker.prototype.minDimension=20,tracking.ColorTracker.prototype.maxDimension=1/0,tracking.ColorTracker.prototype.minGroupSize=30,tracking.ColorTracker.prototype.calculateDimensions_=function(t,r){for(var n=-1,e=-1,a=1/0,i=1/0,o=0;o<r;o+=2){var c=t[o],s=t[o+1];c<a&&(a=c),c>n&&(n=c),s<i&&(i=s),s>e&&(e=s)}return{width:n-a,height:e-i,x:a,y:i}},tracking.ColorTracker.prototype.getColors=function(){return this.colors},tracking.ColorTracker.prototype.getMinDimension=function(){return this.minDimension},tracking.ColorTracker.prototype.getMaxDimension=function(){return this.maxDimension},tracking.ColorTracker.prototype.getMinGroupSize=function(){return this.minGroupSize},tracking.ColorTracker.prototype.getNeighboursForWidth_=function(t){if(tracking.ColorTracker.neighbours_[t])return tracking.ColorTracker.neighbours_[t];var r=new Int32Array(8);return r[0]=4*-t,r[1]=4*-t+4,r[2]=4,r[3]=4*t+4,r[4]=4*t,r[5]=4*t-4,r[6]=-4,r[7]=4*-t-4,tracking.ColorTracker.neighbours_[t]=r,r},tracking.ColorTracker.prototype.mergeRectangles_=function(t){for(var r,n=[],e=this.getMinDimension(),a=this.getMaxDimension(),i=0;i<t.length;i++){var o=t[i];r=!0;for(var c=i+1;c<t.length;c++){var s=t[c];if(tracking.Math.intersectRect(o.x,o.y,o.x+o.width,o.y+o.height,s.x,s.y,s.x+s.width,s.y+s.height)){r=!1;var g=Math.min(o.x,s.x),h=Math.min(o.y,s.y),k=Math.max(o.x+o.width,s.x+s.width),f=Math.max(o.y+o.height,s.y+s.height);s.height=f-h,s.width=k-g,s.x=g,s.y=h;break}}r&&o.width>=e&&o.height>=e&&o.width<=a&&o.height<=a&&n.push(o)}return n},tracking.ColorTracker.prototype.setColors=function(t){this.colors=t},tracking.ColorTracker.prototype.setMinDimension=function(t){this.minDimension=t},tracking.ColorTracker.prototype.setMaxDimension=function(t){this.maxDimension=t},tracking.ColorTracker.prototype.setMinGroupSize=function(t){this.minGroupSize=t},tracking.ColorTracker.prototype.track=function(t,r,n){var e=this,a=this.getColors();if(!a)throw new Error('Colors not specified, try `new tracking.ColorTracker(\"magenta\")`.');var i=[];a.forEach(function(a){i=i.concat(e.trackColor_(t,r,n,a))}),this.emit(\"track\",{data:i})},tracking.ColorTracker.prototype.trackColor_=function(n,e,a,i){var o,c,s,g,h,k=tracking.ColorTracker.knownColors_[i],f=new Int32Array(n.length>>2),u=new Int8Array(n.length),l=this.getMinGroupSize(),m=this.getNeighboursForWidth_(e),d=new Int32Array(n.length),v=[],p=-4;if(!k)return v;for(var y=0;y<a;y++)for(var w=0;w<e;w++)if(p+=4,!u[p]){for(o=0,h=-1,d[++h]=p,d[++h]=y,d[++h]=w,u[p]=1;h>=0;)if(s=d[h--],c=d[h--],g=d[h--],k(n[g],n[g+1],n[g+2],n[g+3],g,c,s)){f[o++]=s,f[o++]=c;for(var T=0;T<m.length;T++){var x=g+m[T],M=c+t[T],_=s+r[T];!u[x]&&M>=0&&M<a&&_>=0&&_<e&&(d[++h]=x,d[++h]=M,d[++h]=_,u[x]=1)}}if(o>=l){var C=this.calculateDimensions_(f,o);C&&(C.color=i,v.push(C))}}return this.mergeRectangles_(v)},tracking.ColorTracker.registerColor(\"cyan\",function(t,r,n){var e=50,a=70,i=t-0,o=r-255,c=n-255;return r-t>=e&&n-t>=a||i*i+o*o+c*c<6400}),tracking.ColorTracker.registerColor(\"magenta\",function(t,r,n){var e=50,a=t-255,i=r-0,o=n-255;return t-r>=e&&n-r>=e||a*a+i*i+o*o<19600}),tracking.ColorTracker.registerColor(\"yellow\",function(t,r,n){var e=50,a=t-255,i=r-255,o=n-0;return t-n>=e&&r-n>=e||a*a+i*i+o*o<1e4});var t=new Int32Array([-1,-1,0,1,1,1,0,-1]),r=new Int32Array([0,1,1,1,0,-1,-1,-1])}(),function(){tracking.ObjectTracker=function(t){tracking.ObjectTracker.base(this,\"constructor\"),t&&(Array.isArray(t)||(t=[t]),Array.isArray(t)&&t.forEach(function(r,n){if(\"string\"==typeof r&&(t[n]=tracking.ViolaJones.classifiers[r]),!t[n])throw new Error('Object classifier not valid, try `new tracking.ObjectTracker(\"face\")`.')})),this.setClassifiers(t)},tracking.inherits(tracking.ObjectTracker,tracking.Tracker),tracking.ObjectTracker.prototype.edgesDensity=.2,tracking.ObjectTracker.prototype.initialScale=1,tracking.ObjectTracker.prototype.scaleFactor=1.25,tracking.ObjectTracker.prototype.stepSize=1.5,tracking.ObjectTracker.prototype.getClassifiers=function(){return this.classifiers},tracking.ObjectTracker.prototype.getEdgesDensity=function(){return this.edgesDensity},tracking.ObjectTracker.prototype.getInitialScale=function(){return this.initialScale},tracking.ObjectTracker.prototype.getScaleFactor=function(){return this.scaleFactor},tracking.ObjectTracker.prototype.getStepSize=function(){return this.stepSize},tracking.ObjectTracker.prototype.track=function(t,r,n){var e=this,a=this.getClassifiers();if(!a)throw new Error('Object classifier not specified, try `new tracking.ObjectTracker(\"face\")`.');var i=[];a.forEach(function(a){i=i.concat(tracking.ViolaJones.detect(t,r,n,e.getInitialScale(),e.getScaleFactor(),e.getStepSize(),e.getEdgesDensity(),a))}),this.emit(\"track\",{data:i})},tracking.ObjectTracker.prototype.setClassifiers=function(t){this.classifiers=t},tracking.ObjectTracker.prototype.setEdgesDensity=function(t){this.edgesDensity=t},tracking.ObjectTracker.prototype.setInitialScale=function(t){this.initialScale=t},tracking.ObjectTracker.prototype.setScaleFactor=function(t){this.scaleFactor=t},tracking.ObjectTracker.prototype.setStepSize=function(t){this.stepSize=t}}(),function(){tracking.LandmarksTracker=function(){tracking.LandmarksTracker.base(this,\"constructor\")},tracking.inherits(tracking.LandmarksTracker,tracking.ObjectTracker),tracking.LandmarksTracker.prototype.track=function(t,r,n){var e=tracking.ViolaJones.classifiers.face,a=tracking.ViolaJones.detect(t,r,n,this.getInitialScale(),this.getScaleFactor(),this.getStepSize(),this.getEdgesDensity(),e),i=tracking.LBF.align(t,r,n,a);this.emit(\"track\",{data:{faces:a,landmarks:i}})}}(),function(){tracking.LBF={},tracking.LBF.Regressor=function(t){this.maxNumStages=t,this.rfs=new Array(t),this.models=new Array(t);for(var r=0;r<t;r++)this.rfs[r]=new tracking.LBF.RandomForest(r),this.models[r]=tracking.LBF.RegressorData[r].models;this.meanShape=tracking.LBF.LandmarksData},tracking.LBF.Regressor.prototype.predict=function(t,r,n,e){var a=[],i=[],o=[],c=tracking.Matrix.clone(this.meanShape);a.push({data:t,width:r,height:n}),o.push(e),i.push(tracking.LBF.projectShapeToBoundingBox_(c,e));for(var s=0;s<this.maxNumStages;s++){var g=tracking.LBF.Regressor.deriveBinaryFeat(this.rfs[s],a,i,o,c);this.applyGlobalPrediction(g,this.models[s],i,o)}return i[0]},tracking.LBF.Regressor.prototype.applyGlobalPrediction=function(t,r,n,e){for(var a=2*n[0].length,i=new Array(a/2),o=0;o<a/2;o++)i[o]=[0,0];for(var o=0;o<n.length;o++){for(var c=0;c<a;c++){for(var s=0,g=0,h=0;(h=t[o][g].index)!=-1;g++)h<=r[c].nr_feature&&(s+=r[c].data[h-1]*t[o][g].value);c<a/2?i[c][0]=s:i[c-a/2][1]=s}var k=tracking.LBF.similarityTransform_(tracking.LBF.unprojectShapeToBoundingBox_(n[o],e[o]),this.meanShape),f=(tracking.Matrix.transpose(k[0]),tracking.LBF.unprojectShapeToBoundingBox_(n[o],e[o]));f=tracking.Matrix.add(f,i),n[o]=tracking.LBF.projectShapeToBoundingBox_(f,e[o])}},tracking.LBF.Regressor.deriveBinaryFeat=function(t,r,n,e,a){for(var i=new Array(r.length),o=0;o<r.length;o++){var c=t.maxNumTrees*t.landmarkNum+1;i[o]=new Array(c);for(var s=0;s<c;s++)i[o][s]={}}for(var g=1<<t.maxDepth-1,o=0;o<r.length;o++){for(var h=tracking.LBF.unprojectShapeToBoundingBox_(n[o],e[o]),k=tracking.LBF.similarityTransform_(h,a),s=0;s<t.landmarkNum;s++)for(var f=0;f<t.maxNumTrees;f++){var u=tracking.LBF.Regressor.getCodeFromTree(t.rfs[s][f],r[o],n[o],e[o],k[0],k[1]),l=s*t.maxNumTrees+f;i[o][l].index=g*l+u,i[o][l].value=1}i[o][t.landmarkNum*t.maxNumTrees].index=-1,i[o][t.landmarkNum*t.maxNumTrees].value=-1}return i},tracking.LBF.Regressor.getCodeFromTree=function(t,r,n,e,a,i){for(var o=0,c=0;;){var s=Math.cos(t.nodes[o].feats[0])*t.nodes[o].feats[2]*t.maxRadioRadius*e.width,g=Math.sin(t.nodes[o].feats[0])*t.nodes[o].feats[2]*t.maxRadioRadius*e.height,h=Math.cos(t.nodes[o].feats[1])*t.nodes[o].feats[3]*t.maxRadioRadius*e.width,k=Math.sin(t.nodes[o].feats[1])*t.nodes[o].feats[3]*t.maxRadioRadius*e.height,f=a[0][0]*s+a[0][1]*g,u=a[1][0]*s+a[1][1]*g,l=Math.floor(f+n[t.landmarkID][0]),m=Math.floor(u+n[t.landmarkID][1]);l=Math.max(0,Math.min(l,r.height-1)),m=Math.max(0,Math.min(m,r.width-1));var d=a[0][0]*h+a[0][1]*k,v=a[1][0]*h+a[1][1]*k,p=Math.floor(d+n[t.landmarkID][0]),y=Math.floor(v+n[t.landmarkID][1]);p=Math.max(0,Math.min(p,r.height-1)),y=Math.max(0,Math.min(y,r.width-1));var w=Math.floor(r.data[m*r.width+l])-Math.floor(r.data[y*r.width+p]);if(o=w<t.nodes[o].thresh?t.nodes[o].cnodes[0]:t.nodes[o].cnodes[1],1==t.nodes[o].is_leafnode){c=1;for(var T=0;T<t.leafnodes.length;T++){if(t.leafnodes[T]==o)return c;c++}return c}}return c}}(),function(){tracking.LBF.maxNumStages=4,tracking.LBF.regressor_=null,tracking.LBF.align=function(t,r,n,e){null==tracking.LBF.regressor_&&(tracking.LBF.regressor_=new tracking.LBF.Regressor(tracking.LBF.maxNumStages)),t=tracking.Image.grayscale(t,r,n,!1),t=tracking.Image.equalizeHist(t,r,n);var a=new Array(e.length);for(var i in e){e[i].height=e[i].width;var o={};o.startX=e[i].x,o.startY=e[i].y,o.width=e[i].width,o.height=e[i].height,a[i]=tracking.LBF.regressor_.predict(t,r,n,o)}return a},tracking.LBF.unprojectShapeToBoundingBox_=function(t,r){for(var n=new Array(t.length),e=0;e<t.length;e++)n[e]=[(t[e][0]-r.startX)/r.width,(t[e][1]-r.startY)/r.height];return n},tracking.LBF.projectShapeToBoundingBox_=function(t,r){for(var n=new Array(t.length),e=0;e<t.length;e++)n[e]=[t[e][0]*r.width+r.startX,t[e][1]*r.height+r.startY];return n},tracking.LBF.similarityTransform_=function(t,r){for(var n=[0,0],e=[0,0],a=0;a<t.length;a++)n[0]+=t[a][0],n[1]+=t[a][1],e[0]+=r[a][0],e[1]+=r[a][1];n[0]/=t.length,n[1]/=t.length,e[0]/=r.length,e[1]/=r.length;for(var i=tracking.Matrix.clone(t),o=tracking.Matrix.clone(r),a=0;a<t.length;a++)i[a][0]-=n[0],i[a][1]-=n[1],o[a][0]-=e[0],o[a][1]-=e[1];var c,s,g,h,k=tracking.Matrix.calcCovarMatrix(i);c=k[0],g=k[1],k=tracking.Matrix.calcCovarMatrix(o),s=k[0],h=k[1];var f=Math.sqrt(tracking.Matrix.norm(c)),u=Math.sqrt(tracking.Matrix.norm(s)),l=f/u;i=tracking.Matrix.mulScalar(1/f,i),o=tracking.Matrix.mulScalar(1/u,o);for(var m=0,d=0,a=0;a<t.length;a++)m=m+i[a][1]*o[a][0]-i[a][0]*o[a][1],d=d+i[a][0]*o[a][0]+i[a][1]*o[a][1];var v=Math.sqrt(m*m+d*d),p=m/v,y=d/v,w=[[y,-p],[p,y]];return[w,l]},tracking.LBF.RandomForest=function(t){this.maxNumTrees=tracking.LBF.RegressorData[t].max_numtrees,this.landmarkNum=tracking.LBF.RegressorData[t].num_landmark,this.maxDepth=tracking.LBF.RegressorData[t].max_depth,this.stages=tracking.LBF.RegressorData[t].stages,this.rfs=new Array(this.landmarkNum);for(var r=0;r<this.landmarkNum;r++){this.rfs[r]=new Array(this.maxNumTrees);for(var n=0;n<this.maxNumTrees;n++)this.rfs[r][n]=new tracking.LBF.Tree(t,r,n)}},tracking.LBF.Tree=function(t,r,n){var e=tracking.LBF.RegressorData[t].landmarks[r][n];this.maxDepth=e.max_depth,this.maxNumNodes=e.max_numnodes,this.nodes=e.nodes,this.landmarkID=e.landmark_id,this.numLeafnodes=e.num_leafnodes,this.numNodes=e.num_nodes,this.maxNumFeats=e.max_numfeats,this.maxRadioRadius=e.max_radio_radius,this.leafnodes=e.id_leafnodes}}();\n\n/*\nCopyright (c) 2011 Juan Mellado\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/*\nReferences:\n- \"OpenCV: Open Computer Vision Library\"\n  http://sourceforge.net/projects/opencvlibrary/\n- \"Stack Blur: Fast But Goodlooking\"\n  http://incubator.quasimondo.com/processing/fast_blur_deluxe.php\nvar CV = CV || {};\n\nCV.Image = function(width, height, data){\n  this.width = width || 0;\n  this.height = height || 0;\n  this.data = data || [];\n};\n\nCV.grayscale = function(imageSrc, imageDst){\n  var src = imageSrc.data, dst = imageDst.data, len = src.length,\n      i = 0, j = 0;\n\n  for (; i < len; i += 4){\n    dst[j ++] =\n      (src[i] * 0.299 + src[i + 1] * 0.587 + src[i + 2] * 0.114 + 0.5) & 0xff;\n  }\n  \n  imageDst.width = imageSrc.width;\n  imageDst.height = imageSrc.height;\n  \n  return imageDst;\n};\n\nCV.threshold = function(imageSrc, imageDst, threshold){\n  var src = imageSrc.data, dst = imageDst.data,\n      len = src.length, tab = [], i;\n\n  for (i = 0; i < 256; ++ i){\n    tab[i] = i <= threshold? 0: 255;\n  }\n\n  for (i = 0; i < len; ++ i){\n    dst[i] = tab[ src[i] ];\n  }\n\n  imageDst.width = imageSrc.width;\n  imageDst.height = imageSrc.height;\n\n  return imageDst;\n};\n\nCV.adaptiveThreshold = function(imageSrc, imageDst, kernelSize, threshold){\n  var src = imageSrc.data, dst = imageDst.data, len = src.length, tab = [], i;\n\n  CV.stackBoxBlur(imageSrc, imageDst, kernelSize);\n\n  for (i = 0; i < 768; ++ i){\n    tab[i] = (i - 255 <= -threshold)? 255: 0;\n  }\n\n  for (i = 0; i < len; ++ i){\n    dst[i] = tab[ src[i] - dst[i] + 255 ];\n  }\n\n  imageDst.width = imageSrc.width;\n  imageDst.height = imageSrc.height;\n  \n  return imageDst;\n};\n\nCV.otsu = function(imageSrc){\n  var src = imageSrc.data, len = src.length, hist = [],\n      threshold = 0, sum = 0, sumB = 0, wB = 0, wF = 0, max = 0,\n      mu, between, i;\n\n  for (i = 0; i < 256; ++ i){\n    hist[i] = 0;\n  }\n  \n  for (i = 0; i < len; ++ i){\n    hist[ src[i] ] ++;\n  }\n\n  for (i = 0; i < 256; ++ i){\n    sum += hist[i] * i;\n  }\n\n  for (i = 0; i < 256; ++ i){\n    wB += hist[i];\n    if (0 !== wB){\n    \n      wF = len - wB;\n      if (0 === wF){\n        break;\n      }\n\n      sumB += hist[i] * i;\n      \n      mu = (sumB / wB) - ( (sum - sumB) / wF );\n\n      between = wB * wF * mu * mu;\n      \n      if (between > max){\n        max = between;\n        threshold = i;\n      }\n    }\n  }\n\n  return threshold;\n};\n\nCV.stackBoxBlurMult =\n  [1, 171, 205, 293, 57, 373, 79, 137, 241, 27, 391, 357, 41, 19, 283, 265];\n\nCV.stackBoxBlurShift =\n  [0, 9, 10, 11, 9, 12, 10, 11, 12, 9, 13, 13, 10, 9, 13, 13];\n\nCV.BlurStack = function(){\n  this.color = 0;\n  this.next = null;\n};\n\nCV.stackBoxBlur = function(imageSrc, imageDst, kernelSize){\n  var src = imageSrc.data, dst = imageDst.data,\n      height = imageSrc.height, width = imageSrc.width,\n      heightMinus1 = height - 1, widthMinus1 = width - 1,\n      size = kernelSize + kernelSize + 1, radius = kernelSize + 1,\n      mult = CV.stackBoxBlurMult[kernelSize],\n      shift = CV.stackBoxBlurShift[kernelSize],\n      stack, stackStart, color, sum, pos, start, p, x, y, i;\n\n  stack = stackStart = new CV.BlurStack();\n  for (i = 1; i < size; ++ i){\n    stack = stack.next = new CV.BlurStack();\n  }\n  stack.next = stackStart;\n\n  pos = 0;\n\n  for (y = 0; y < height; ++ y){\n    start = pos;\n    \n    color = src[pos];\n    sum = radius * color;\n    \n    stack = stackStart;\n    for (i = 0; i < radius; ++ i){\n      stack.color = color;\n      stack = stack.next;\n    }\n    for (i = 1; i < radius; ++ i){\n      stack.color = src[pos + i];\n      sum += stack.color;\n      stack = stack.next;\n    }\n  \n    stack = stackStart;\n    for (x = 0; x < width; ++ x){\n      dst[pos ++] = (sum * mult) >>> shift;\n      \n      p = x + radius;\n      p = start + (p < widthMinus1? p: widthMinus1);\n      sum -= stack.color - src[p];\n      \n      stack.color = src[p];\n      stack = stack.next;\n    }\n  }\n\n  for (x = 0; x < width; ++ x){\n    pos = x;\n    start = pos + width;\n    \n    color = dst[pos];\n    sum = radius * color;\n    \n    stack = stackStart;\n    for (i = 0; i < radius; ++ i){\n      stack.color = color;\n      stack = stack.next;\n    }\n    for (i = 1; i < radius; ++ i){\n      stack.color = dst[start];\n      sum += stack.color;\n      stack = stack.next;\n      \n      start += width;\n    }\n    \n    stack = stackStart;\n    for (y = 0; y < height; ++ y){\n      dst[pos] = (sum * mult) >>> shift;\n      \n      p = y + radius;\n      p = x + ( (p < heightMinus1? p: heightMinus1) * width );\n      sum -= stack.color - dst[p];\n      \n      stack.color = dst[p];\n      stack = stack.next;\n      \n      pos += width;\n    }\n  }\n\n  return imageDst;\n};\n\nCV.gaussianBlur = function(imageSrc, imageDst, imageMean, kernelSize){\n  var kernel = CV.gaussianKernel(kernelSize);\n\n  imageDst.width = imageSrc.width;\n  imageDst.height = imageSrc.height;\n  \n  imageMean.width = imageSrc.width;\n  imageMean.height = imageSrc.height;\n\n  CV.gaussianBlurFilter(imageSrc, imageMean, kernel, true);\n  CV.gaussianBlurFilter(imageMean, imageDst, kernel, false);\n\n  return imageDst;\n};\n\nCV.gaussianBlurFilter = function(imageSrc, imageDst, kernel, horizontal){\n  var src = imageSrc.data, dst = imageDst.data,\n      height = imageSrc.height, width = imageSrc.width,\n      pos = 0, limit = kernel.length >> 1,\n      cur, value, i, j, k;\n      \n  for (i = 0; i < height; ++ i){\n    \n    for (j = 0; j < width; ++ j){\n      value = 0.0;\n    \n      for (k = -limit; k <= limit; ++ k){\n\n        if (horizontal){\n          cur = pos + k;\n          if (j + k < 0){\n            cur = pos;\n          }\n          else if (j + k >= width){\n            cur = pos;\n          }\n        }else{\n          cur = pos + (k * width);\n          if (i + k < 0){\n            cur = pos;\n          }\n          else if (i + k >= height){\n            cur = pos;\n          }\n        }\n\n        value += kernel[limit + k] * src[cur];\n      }\n    \n      dst[pos ++] = horizontal? value: (value + 0.5) & 0xff;\n    }\n  }\n\n  return imageDst;\n};\n\nCV.gaussianKernel = function(kernelSize){\n  var tab =\n    [ [1],\n      [0.25, 0.5, 0.25],\n      [0.0625, 0.25, 0.375, 0.25, 0.0625],\n      [0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125] ],\n    kernel = [], center, sigma, scale2X, sum, x, i;\n\n  if ( (kernelSize <= 7) && (kernelSize % 2 === 1) ){\n    kernel = tab[kernelSize >> 1];\n  }else{\n    center = (kernelSize - 1.0) * 0.5;\n    sigma = 0.8 + (0.3 * (center - 1.0) );\n    scale2X = -0.5 / (sigma * sigma);\n    sum = 0.0;\n    for (i = 0; i < kernelSize; ++ i){\n      x = i - center;\n      sum += kernel[i] = Math.exp(scale2X * x * x);\n    }\n    sum = 1 / sum;\n    for (i = 0; i < kernelSize; ++ i){\n      kernel[i] *= sum;\n    }  \n  }\n\n  return kernel;\n};\n\nCV.findContours = function(imageSrc, binary){\n  var width = imageSrc.width, height = imageSrc.height, contours = [],\n      src, deltas, pos, pix, nbd, outer, hole, i, j;\n  \n  src = CV.binaryBorder(imageSrc, binary);\n\n  deltas = CV.neighborhoodDeltas(width + 2);\n\n  pos = width + 3;\n  nbd = 1;\n\n  for (i = 0; i < height; ++ i, pos += 2){\n  \n    for (j = 0; j < width; ++ j, ++ pos){\n      pix = src[pos];\n\n      if (0 !== pix){\n        outer = hole = false;\n\n        if (1 === pix && 0 === src[pos - 1]){\n          outer = true;\n        }\n        else if (pix >= 1 && 0 === src[pos + 1]){\n          hole = true;\n        }\n\n        if (outer || hole){\n          ++ nbd;\n          \n          contours.push( CV.borderFollowing(src, pos, nbd, {x: j, y: i}, hole, deltas) );\n        }\n      }\n    }\n  }  \n\n  return contours;\n};\n\nCV.borderFollowing = function(src, pos, nbd, point, hole, deltas){\n  var contour = [], pos1, pos3, pos4, s, s_end, s_prev;\n\n  contour.hole = hole;\n      \n  s = s_end = hole? 0: 4;\n  do{\n    s = (s - 1) & 7;\n    pos1 = pos + deltas[s];\n    if (src[pos1] !== 0){\n      break;\n    }\n  }while(s !== s_end);\n  \n  if (s === s_end){\n    src[pos] = -nbd;\n    contour.push( {x: point.x, y: point.y} );\n\n  }else{\n    pos3 = pos;\n    s_prev = s ^ 4;\n\n    while(true){\n      s_end = s;\n    \n      do{\n        pos4 = pos3 + deltas[++ s];\n      }while(src[pos4] === 0);\n      \n      s &= 7;\n      \n      if ( ( (s - 1) >>> 0) < (s_end >>> 0) ){\n        src[pos3] = -nbd;\n      }\n      else if (src[pos3] === 1){\n        src[pos3] = nbd;\n      }\n\n      contour.push( {x: point.x, y: point.y} );\n      \n      s_prev = s;\n\n      point.x += CV.neighborhood[s][0];\n      point.y += CV.neighborhood[s][1];\n\n      if ( (pos4 === pos) && (pos3 === pos1) ){\n        break;\n      }\n      \n      pos3 = pos4;\n      s = (s + 4) & 7;\n    }\n  }\n\n  return contour;\n};\n\nCV.neighborhood = \n  [ [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1], [0, 1], [1, 1] ];\n\nCV.neighborhoodDeltas = function(width){\n  var deltas = [], len = CV.neighborhood.length, i = 0;\n  \n  for (; i < len; ++ i){\n    deltas[i] = CV.neighborhood[i][0] + (CV.neighborhood[i][1] * width);\n  }\n  \n  return deltas.concat(deltas);\n};\n\nCV.approxPolyDP = function(contour, epsilon){\n  var slice = {start_index: 0, end_index: 0},\n      right_slice = {start_index: 0, end_index: 0},\n      poly = [], stack = [], len = contour.length,\n      pt, start_pt, end_pt, dist, max_dist, le_eps,\n      dx, dy, i, j, k;\n  \n  epsilon *= epsilon;\n  \n  k = 0;\n  \n  for (i = 0; i < 3; ++ i){\n    max_dist = 0;\n    \n    k = (k + right_slice.start_index) % len;\n    start_pt = contour[k];\n    if (++ k === len) {k = 0;}\n  \n    for (j = 1; j < len; ++ j){\n      pt = contour[k];\n      if (++ k === len) {k = 0;}\n    \n      dx = pt.x - start_pt.x;\n      dy = pt.y - start_pt.y;\n      dist = dx * dx + dy * dy;\n\n      if (dist > max_dist){\n        max_dist = dist;\n        right_slice.start_index = j;\n      }\n    }\n  }\n\n  if (max_dist <= epsilon){\n    poly.push( {x: start_pt.x, y: start_pt.y} );\n\n  }else{\n    slice.start_index = k;\n    slice.end_index = (right_slice.start_index += slice.start_index);\n  \n    right_slice.start_index -= right_slice.start_index >= len? len: 0;\n    right_slice.end_index = slice.start_index;\n    if (right_slice.end_index < right_slice.start_index){\n      right_slice.end_index += len;\n    }\n    \n    stack.push( {start_index: right_slice.start_index, end_index: right_slice.end_index} );\n    stack.push( {start_index: slice.start_index, end_index: slice.end_index} );\n  }\n\n  while(stack.length !== 0){\n    slice = stack.pop();\n    \n    end_pt = contour[slice.end_index % len];\n    start_pt = contour[k = slice.start_index % len];\n    if (++ k === len) {k = 0;}\n    \n    if (slice.end_index <= slice.start_index + 1){\n      le_eps = true;\n    \n    }else{\n      max_dist = 0;\n\n      dx = end_pt.x - start_pt.x;\n      dy = end_pt.y - start_pt.y;\n      \n      for (i = slice.start_index + 1; i < slice.end_index; ++ i){\n        pt = contour[k];\n        if (++ k === len) {k = 0;}\n        \n        dist = Math.abs( (pt.y - start_pt.y) * dx - (pt.x - start_pt.x) * dy);\n\n        if (dist > max_dist){\n          max_dist = dist;\n          right_slice.start_index = i;\n        }\n      }\n      \n      le_eps = max_dist * max_dist <= epsilon * (dx * dx + dy * dy);\n    }\n    \n    if (le_eps){\n      poly.push( {x: start_pt.x, y: start_pt.y} );\n\n    }else{\n      right_slice.end_index = slice.end_index;\n      slice.end_index = right_slice.start_index;\n\n      stack.push( {start_index: right_slice.start_index, end_index: right_slice.end_index} );\n      stack.push( {start_index: slice.start_index, end_index: slice.end_index} );\n    }\n  }\n  \n  return poly;\n};\n\nCV.warp = function(imageSrc, imageDst, contour, warpSize){\n  var src = imageSrc.data, dst = imageDst.data,\n      width = imageSrc.width, height = imageSrc.height,\n      pos = 0,\n      sx1, sx2, dx1, dx2, sy1, sy2, dy1, dy2, p1, p2, p3, p4,\n      m, r, s, t, u, v, w, x, y, i, j;\n  \n  m = CV.getPerspectiveTransform(contour, warpSize - 1);\n\n  r = m[8];\n  s = m[2];\n  t = m[5];\n  \n  for (i = 0; i < warpSize; ++ i){\n    r += m[7];\n    s += m[1];\n    t += m[4];\n\n    u = r;\n    v = s;\n    w = t;\n    \n    for (j = 0; j < warpSize; ++ j){\n      u += m[6];\n      v += m[0];\n      w += m[3];\n\n      x = v / u;\n      y = w / u;\n\n      sx1 = x >>> 0;\n      sx2 = (sx1 === width - 1)? sx1: sx1 + 1;\n      dx1 = x - sx1;\n      dx2 = 1.0 - dx1;\n\n      sy1 = y >>> 0;\n      sy2 = (sy1 === height - 1)? sy1: sy1 + 1;\n      dy1 = y - sy1;\n      dy2 = 1.0 - dy1;\n\n      p1 = p2 = sy1 * width;\n      p3 = p4 = sy2 * width;\n\n      dst[pos ++] = \n        (dy2 * (dx2 * src[p1 + sx1] + dx1 * src[p2 + sx2]) +\n         dy1 * (dx2 * src[p3 + sx1] + dx1 * src[p4 + sx2]) ) & 0xff;\n\n    }\n  }\n\n  imageDst.width = warpSize;\n  imageDst.height = warpSize;\n\n  return imageDst;\n};\n\nCV.getPerspectiveTransform = function(src, size){\n  var rq = CV.square2quad(src);\n  \n  rq[0] /= size;\n  rq[1] /= size;\n  rq[3] /= size;\n  rq[4] /= size;\n  rq[6] /= size;\n  rq[7] /= size;\n  \n  return rq;\n};\n\nCV.square2quad = function(src){\n  var sq = [], px, py, dx1, dx2, dy1, dy2, den;\n  \n  px = src[0].x - src[1].x + src[2].x - src[3].x;\n  py = src[0].y - src[1].y + src[2].y - src[3].y;\n  \n  if (0 === px && 0 === py){\n    sq[0] = src[1].x - src[0].x;\n    sq[1] = src[2].x - src[1].x;\n    sq[2] = src[0].x;\n    sq[3] = src[1].y - src[0].y;\n    sq[4] = src[2].y - src[1].y;\n    sq[5] = src[0].y;\n    sq[6] = 0;\n    sq[7] = 0;\n    sq[8] = 1;\n\n  }else{\n    dx1 = src[1].x - src[2].x;\n    dx2 = src[3].x - src[2].x;\n    dy1 = src[1].y - src[2].y;\n    dy2 = src[3].y - src[2].y;\n    den = dx1 * dy2 - dx2 * dy1;\n  \n    sq[6] = (px * dy2 - dx2 * py) / den;\n    sq[7] = (dx1 * py - px * dy1) / den;\n    sq[8] = 1;\n    sq[0] = src[1].x - src[0].x + sq[6] * src[1].x;\n    sq[1] = src[3].x - src[0].x + sq[7] * src[3].x;\n    sq[2] = src[0].x;\n    sq[3] = src[1].y - src[0].y + sq[6] * src[1].y;\n    sq[4] = src[3].y - src[0].y + sq[7] * src[3].y;\n    sq[5] = src[0].y;\n  }\n\n  return sq;\n};\n\nCV.isContourConvex = function(contour){\n  var orientation = 0, convex = true,\n      len = contour.length, i = 0, j = 0,\n      cur_pt, prev_pt, dxdy0, dydx0, dx0, dy0, dx, dy;\n\n  prev_pt = contour[len - 1];\n  cur_pt = contour[0];\n\n  dx0 = cur_pt.x - prev_pt.x;\n  dy0 = cur_pt.y - prev_pt.y;\n\n  for (; i < len; ++ i){\n    if (++ j === len) {j = 0;}\n\n    prev_pt = cur_pt;\n    cur_pt = contour[j];\n\n    dx = cur_pt.x - prev_pt.x;\n    dy = cur_pt.y - prev_pt.y;\n    dxdy0 = dx * dy0;\n    dydx0 = dy * dx0;\n\n    orientation |= dydx0 > dxdy0? 1: (dydx0 < dxdy0? 2: 3);\n\n    if (3 === orientation){\n        convex = false;\n        break;\n    }\n\n    dx0 = dx;\n    dy0 = dy;\n  }\n\n  return convex;\n};\n\nCV.perimeter = function(poly){\n  var len = poly.length, i = 0, j = len - 1,\n      p = 0.0, dx, dy;\n\n  for (; i < len; j = i ++){\n    dx = poly[i].x - poly[j].x;\n    dy = poly[i].y - poly[j].y;\n    \n    p += Math.sqrt(dx * dx + dy * dy) ;\n  }\n\n  return p;\n};\n\nCV.minEdgeLength = function(poly){\n  var len = poly.length, i = 0, j = len - 1, \n      min = Infinity, d, dx, dy;\n\n  for (; i < len; j = i ++){\n    dx = poly[i].x - poly[j].x;\n    dy = poly[i].y - poly[j].y;\n\n    d = dx * dx + dy * dy;\n\n    if (d < min){\n      min = d;\n    }\n  }\n  \n  return Math.sqrt(min);\n};\n\nCV.countNonZero = function(imageSrc, square){\n  var src = imageSrc.data, height = square.height, width = square.width,\n      pos = square.x + (square.y * imageSrc.width),\n      span = imageSrc.width - width,\n      nz = 0, i, j;\n  \n  for (i = 0; i < height; ++ i){\n\n    for (j = 0; j < width; ++ j){\n    \n      if ( 0 !== src[pos ++] ){\n        ++ nz;\n      }\n    }\n    \n    pos += span;\n  }\n\n  return nz;\n};\n\nCV.binaryBorder = function(imageSrc, dst){\n  var src = imageSrc.data, height = imageSrc.height, width = imageSrc.width,\n      posSrc = 0, posDst = 0, i, j;\n\n  for (j = -2; j < width; ++ j){\n    dst[posDst ++] = 0;\n  }\n\n  for (i = 0; i < height; ++ i){\n    dst[posDst ++] = 0;\n    \n    for (j = 0; j < width; ++ j){\n      dst[posDst ++] = (0 === src[posSrc ++]? 0: 1);\n    }\n    \n    dst[posDst ++] = 0;\n  }\n\n  for (j = -2; j < width; ++ j){\n    dst[posDst ++] = 0;\n  }\n  \n  return dst;\n};\n\n/*\nCopyright (c) 2011 Juan Mellado\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/*\nReferences:\n- \"ArUco: a minimal library for Augmented Reality applications based on OpenCv\"\n  http://www.uco.es/investiga/grupos/ava/node/26\n*/\n\nvar AR = AR || {};\n\nAR.Marker = function(id, corners){\n  this.id = id;\n  this.corners = corners;\n};\n\nAR.Detector = function(){\n  this.grey = new CV.Image();\n  this.thres = new CV.Image();\n  this.homography = new CV.Image();\n  this.binary = [];\n  this.contours = [];\n  this.polys = [];\n  this.candidates = [];\n};\n\nAR.Detector.prototype.detect = function(image){\n  CV.grayscale(image, this.grey);\n  CV.adaptiveThreshold(this.grey, this.thres, 2, 7);\n  \n  this.contours = CV.findContours(this.thres, this.binary);\n\n  this.candidates = this.findCandidates(this.contours, image.width * 0.20, 0.05, 10);\n  this.candidates = this.clockwiseCorners(this.candidates);\n  this.candidates = this.notTooNear(this.candidates, 10);\n\n  return this.findMarkers(this.grey, this.candidates, 49);\n};\n\nAR.Detector.prototype.findCandidates = function(contours, minSize, epsilon, minLength){\n  var candidates = [], len = contours.length, contour, poly, i;\n\n  this.polys = [];\n  \n  for (i = 0; i < len; ++ i){\n    contour = contours[i];\n\n    if (contour.length >= minSize){\n      poly = CV.approxPolyDP(contour, contour.length * epsilon);\n\n      this.polys.push(poly);\n\n      if ( (4 === poly.length) && ( CV.isContourConvex(poly) ) ){\n\n        if ( CV.minEdgeLength(poly) >= minLength){\n          candidates.push(poly);\n        }\n      }\n    }\n  }\n\n  return candidates;\n};\n\nAR.Detector.prototype.clockwiseCorners = function(candidates){\n  var len = candidates.length, dx1, dx2, dy1, dy2, swap, i;\n\n  for (i = 0; i < len; ++ i){\n    dx1 = candidates[i][1].x - candidates[i][0].x;\n    dy1 = candidates[i][1].y - candidates[i][0].y;\n    dx2 = candidates[i][2].x - candidates[i][0].x;\n    dy2 = candidates[i][2].y - candidates[i][0].y;\n\n    if ( (dx1 * dy2 - dy1 * dx2) < 0){\n      swap = candidates[i][1];\n      candidates[i][1] = candidates[i][3];\n      candidates[i][3] = swap;\n    }\n  }\n\n  return candidates;\n};\n\nAR.Detector.prototype.notTooNear = function(candidates, minDist){\n  var notTooNear = [], len = candidates.length, dist, dx, dy, i, j, k;\n\n  for (i = 0; i < len; ++ i){\n  \n    for (j = i + 1; j < len; ++ j){\n      dist = 0;\n      \n      for (k = 0; k < 4; ++ k){\n        dx = candidates[i][k].x - candidates[j][k].x;\n        dy = candidates[i][k].y - candidates[j][k].y;\n      \n        dist += dx * dx + dy * dy;\n      }\n      \n      if ( (dist / 4) < (minDist * minDist) ){\n      \n        if ( CV.perimeter( candidates[i] ) < CV.perimeter( candidates[j] ) ){\n          candidates[i].tooNear = true;\n        }else{\n          candidates[j].tooNear = true;\n        }\n      }\n    }\n  }\n\n  for (i = 0; i < len; ++ i){\n    if ( !candidates[i].tooNear ){\n      notTooNear.push( candidates[i] );\n    }\n  }\n\n  return notTooNear;\n};\n\nAR.Detector.prototype.findMarkers = function(imageSrc, candidates, warpSize){\n  var markers = [], len = candidates.length, candidate, marker, i;\n\n  for (i = 0; i < len; ++ i){\n    candidate = candidates[i];\n\n    CV.warp(imageSrc, this.homography, candidate, warpSize);\n  \n    CV.threshold(this.homography, this.homography, CV.otsu(this.homography) );\n\n    marker = this.getMarker(this.homography, candidate);\n    if (marker){\n      markers.push(marker);\n    }\n  }\n  \n  return markers;\n};\n\nAR.Detector.prototype.getMarker = function(imageSrc, candidate){\n  var width = (imageSrc.width / 7) >>> 0,\n      minZero = (width * width) >> 1,\n      bits = [], rotations = [], distances = [],\n      square, pair, inc, i, j;\n\n  for (i = 0; i < 7; ++ i){\n    inc = (0 === i || 6 === i)? 1: 6;\n    \n    for (j = 0; j < 7; j += inc){\n      square = {x: j * width, y: i * width, width: width, height: width};\n      if ( CV.countNonZero(imageSrc, square) > minZero){\n        return null;\n      }\n    }\n  }\n\n  for (i = 0; i < 5; ++ i){\n    bits[i] = [];\n\n    for (j = 0; j < 5; ++ j){\n      square = {x: (j + 1) * width, y: (i + 1) * width, width: width, height: width};\n      \n      bits[i][j] = CV.countNonZero(imageSrc, square) > minZero? 1: 0;\n    }\n  }\n\n  rotations[0] = bits;\n  distances[0] = this.hammingDistance( rotations[0] );\n  \n  pair = {first: distances[0], second: 0};\n  \n  for (i = 1; i < 4; ++ i){\n    rotations[i] = this.rotate( rotations[i - 1] );\n    distances[i] = this.hammingDistance( rotations[i] );\n    \n    if (distances[i] < pair.first){\n      pair.first = distances[i];\n      pair.second = i;\n    }\n  }\n\n  if (0 !== pair.first){\n    return null;\n  }\n\n  return new AR.Marker(\n    this.mat2id( rotations[pair.second] ), \n    this.rotate2(candidate, 4 - pair.second) );\n};\n\nAR.Detector.prototype.hammingDistance = function(bits){\n  var ids = [ [1,0,0,0,0], [1,0,1,1,1], [0,1,0,0,1], [0,1,1,1,0] ],\n      dist = 0, sum, minSum, i, j, k;\n\n  for (i = 0; i < 5; ++ i){\n    minSum = Infinity;\n    \n    for (j = 0; j < 4; ++ j){\n      sum = 0;\n\n      for (k = 0; k < 5; ++ k){\n          sum += bits[i][k] === ids[j][k]? 0: 1;\n      }\n\n      if (sum < minSum){\n        minSum = sum;\n      }\n    }\n\n    dist += minSum;\n  }\n\n  return dist;\n};\n\nAR.Detector.prototype.mat2id = function(bits){\n  var id = 0, i;\n  \n  for (i = 0; i < 5; ++ i){\n    id <<= 1;\n    id |= bits[i][1];\n    id <<= 1;\n    id |= bits[i][3];\n  }\n\n  return id;\n};\n\nAR.Detector.prototype.rotate = function(src){\n  var dst = [], len = src.length, i, j;\n  \n  for (i = 0; i < len; ++ i){\n    dst[i] = [];\n    for (j = 0; j < src[i].length; ++ j){\n      dst[i][j] = src[src[i].length - j - 1][i];\n    }\n  }\n\n  return dst;\n};\n\nAR.Detector.prototype.rotate2 = function(src, rotation){\n  var dst = [], len = src.length, i;\n  \n  for (i = 0; i < len; ++ i){\n    dst[i] = src[ (rotation + i) % len ];\n  }\n\n  return dst;\n};\n\n// 메인\n\n// -------------------------------------------------------\n// tracking.js face classifier data (ViolaJones)\n// source: tracking.js v1.0.0 build/data/face-min.js\n// -------------------------------------------------------\n/**\n * tracking.js - A modern approach for Computer Vision on the web.\n * @author Eduardo Lundgren <edu@rdo.io>\n * @version v1.0.0\n * @link http://trackingjs.com\n * @license BSD\n */\ntracking.ViolaJones.classifiers.face=new Float64Array([20,20,.822689414024353,3,0,2,3,7,14,4,-1,3,9,14,2,2,.004014195874333382,.0337941907346249,.8378106951713562,0,2,1,2,18,4,-1,7,2,6,4,3,.0151513395830989,.1514132022857666,.7488812208175659,0,2,1,7,15,9,-1,1,10,15,3,3,.004210993181914091,.0900492817163467,.6374819874763489,6.956608772277832,16,0,2,5,6,2,6,-1,5,9,2,3,2,.0016227109590545297,.0693085864186287,.7110946178436279,0,2,7,5,6,3,-1,9,5,2,3,3,.002290664939209819,.1795803010463715,.6668692231178284,0,2,4,0,12,9,-1,4,3,12,3,3,.005002570804208517,.1693672984838486,.6554006934165955,0,2,6,9,10,8,-1,6,13,10,4,2,.007965989410877228,.5866332054138184,.0914145186543465,0,2,3,6,14,8,-1,3,10,14,4,2,-.003522701095789671,.1413166970014572,.6031895875930786,0,2,14,1,6,10,-1,14,1,3,10,2,.0366676896810532,.3675672113895416,.7920318245887756,0,2,7,8,5,12,-1,7,12,5,4,3,.009336147457361221,.6161385774612427,.2088509947061539,0,2,1,1,18,3,-1,7,1,6,3,3,.008696131408214569,.2836230993270874,.6360273957252502,0,2,1,8,17,2,-1,1,9,17,1,2,.0011488880263641477,.2223580926656723,.5800700783729553,0,2,16,6,4,2,-1,16,7,4,1,2,-.002148468978703022,.2406464070081711,.5787054896354675,0,2,5,17,2,2,-1,5,18,2,1,2,.002121906029060483,.5559654831886292,.136223703622818,0,2,14,2,6,12,-1,14,2,3,12,2,-.0939491465687752,.8502737283706665,.4717740118503571,0,3,4,0,4,12,-1,4,0,2,6,2,6,6,2,6,2,.0013777789426967502,.5993673801422119,.2834529876708984,0,2,2,11,18,8,-1,8,11,6,8,3,.0730631574988365,.4341886043548584,.7060034275054932,0,2,5,7,10,2,-1,5,8,10,1,2,.00036767389974556863,.3027887940406799,.6051574945449829,0,2,15,11,5,3,-1,15,12,5,1,3,-.0060479710809886456,.17984339594841,.5675256848335266,9.498542785644531,21,0,2,5,3,10,9,-1,5,6,10,3,3,-.0165106896311045,.6644225120544434,.1424857974052429,0,2,9,4,2,14,-1,9,11,2,7,2,.002705249935388565,.6325352191925049,.1288477033376694,0,2,3,5,4,12,-1,3,9,4,4,3,.002806986914947629,.1240288019180298,.6193193197250366,0,2,4,5,12,5,-1,8,5,4,5,3,-.0015402400167658925,.1432143002748489,.5670015811920166,0,2,5,6,10,8,-1,5,10,10,4,2,-.0005638627917505801,.1657433062791824,.5905207991600037,0,2,8,0,6,9,-1,8,3,6,3,3,.0019253729842603207,.2695507109165192,.5738824009895325,0,2,9,12,1,8,-1,9,16,1,4,2,-.005021484103053808,.1893538981676102,.5782774090766907,0,2,0,7,20,6,-1,0,9,20,2,3,.0026365420781075954,.2309329062700272,.5695425868034363,0,2,7,0,6,17,-1,9,0,2,17,3,-.0015127769438549876,.2759602069854736,.5956642031669617,0,2,9,0,6,4,-1,11,0,2,4,3,-.0101574398577213,.1732538044452667,.5522047281265259,0,2,5,1,6,4,-1,7,1,2,4,3,-.011953660286963,.1339409947395325,.5559014081954956,0,2,12,1,6,16,-1,14,1,2,16,3,.004885949194431305,.3628703951835632,.6188849210739136,0,3,0,5,18,8,-1,0,5,9,4,2,9,9,9,4,2,-.0801329165697098,.0912110507488251,.5475944876670837,0,3,8,15,10,4,-1,13,15,5,2,2,8,17,5,2,2,.0010643280111253262,.3715142905712128,.5711399912834167,0,3,3,1,4,8,-1,3,1,2,4,2,5,5,2,4,2,-.0013419450260698795,.5953313708305359,.331809788942337,0,3,3,6,14,10,-1,10,6,7,5,2,3,11,7,5,2,-.0546011403203011,.1844065934419632,.5602846145629883,0,2,2,1,6,16,-1,4,1,2,16,3,.0029071690514683723,.3594244122505188,.6131715178489685,0,2,0,18,20,2,-1,0,19,20,1,2,.0007471871795132756,.5994353294372559,.3459562957286835,0,2,8,13,4,3,-1,8,14,4,1,3,.004301380831748247,.4172652065753937,.6990845203399658,0,2,9,14,2,3,-1,9,15,2,1,3,.004501757211983204,.4509715139865875,.7801457047462463,0,2,0,12,9,6,-1,0,14,9,2,3,.0241385009139776,.5438212752342224,.1319826990365982,18.4129695892334,39,0,2,5,7,3,4,-1,5,9,3,2,2,.001921223010867834,.1415266990661621,.6199870705604553,0,2,9,3,2,16,-1,9,11,2,8,2,-.00012748669541906565,.6191074252128601,.1884928941726685,0,2,3,6,13,8,-1,3,10,13,4,2,.0005140993162058294,.1487396955490112,.5857927799224854,0,2,12,3,8,2,-1,12,3,4,2,2,.004187860991805792,.2746909856796265,.6359239816665649,0,2,8,8,4,12,-1,8,12,4,4,3,.005101571790874004,.5870851278305054,.2175628989934921,0,3,11,3,8,6,-1,15,3,4,3,2,11,6,4,3,2,-.002144844038411975,.5880944728851318,.2979590892791748,0,2,7,1,6,19,-1,9,1,2,19,3,-.0028977119363844395,.2373327016830444,.5876647233963013,0,2,9,0,6,4,-1,11,0,2,4,3,-.0216106791049242,.1220654994249344,.5194202065467834,0,2,3,1,9,3,-1,6,1,3,3,3,-.004629931878298521,.263123095035553,.5817409157752991,0,3,8,15,10,4,-1,13,15,5,2,2,8,17,5,2,2,.000593937118537724,.363862007856369,.5698544979095459,0,2,0,3,6,10,-1,3,3,3,10,2,.0538786612451077,.4303531050682068,.7559366226196289,0,2,3,4,15,15,-1,3,9,15,5,3,.0018887349870055914,.2122603058815002,.561342716217041,0,2,6,5,8,6,-1,6,7,8,2,3,-.0023635339457541704,.563184916973114,.2642767131328583,0,3,4,4,12,10,-1,10,4,6,5,2,4,9,6,5,2,.0240177996456623,.5797107815742493,.2751705944538117,0,2,6,4,4,4,-1,8,4,2,4,2,.00020543030404951423,.2705242037773132,.575256884098053,0,2,15,11,1,2,-1,15,12,1,1,2,.0008479019743390381,.5435624718666077,.2334876954555512,0,2,3,11,2,2,-1,3,12,2,1,2,.0014091329649090767,.5319424867630005,.2063155025243759,0,2,16,11,1,3,-1,16,12,1,1,3,.0014642629539594054,.5418980717658997,.3068861067295075,0,3,3,15,6,4,-1,3,15,3,2,2,6,17,3,2,2,.0016352549428120255,.3695372939109802,.6112868189811707,0,2,6,7,8,2,-1,6,8,8,1,2,.0008317275205627084,.3565036952495575,.6025236248970032,0,2,3,11,1,3,-1,3,12,1,1,3,-.0020998890977352858,.1913982033729553,.5362827181816101,0,2,6,0,12,2,-1,6,1,12,1,2,-.0007421398186124861,.3835555016994476,.552931010723114,0,2,9,14,2,3,-1,9,15,2,1,3,.0032655049581080675,.4312896132469177,.7101895809173584,0,2,7,15,6,2,-1,7,16,6,1,2,.0008913499186746776,.3984830975532532,.6391963958740234,0,2,0,5,4,6,-1,0,7,4,2,3,-.0152841797098517,.2366732954978943,.5433713793754578,0,2,4,12,12,2,-1,8,12,4,2,3,.004838141147047281,.5817500948905945,.3239189088344574,0,2,6,3,1,9,-1,6,6,1,3,3,-.0009109317907132208,.5540593862533569,.2911868989467621,0,2,10,17,3,2,-1,11,17,1,2,3,-.006127506028860807,.1775255054235458,.5196629166603088,0,2,9,9,2,2,-1,9,10,2,1,2,-.00044576259097084403,.3024170100688934,.5533593893051147,0,2,7,6,6,4,-1,9,6,2,4,3,.0226465407758951,.4414930939674377,.6975377202033997,0,2,7,17,3,2,-1,8,17,1,2,3,-.0018804960418492556,.2791394889354706,.5497952103614807,0,2,10,17,3,3,-1,11,17,1,3,3,.007088910788297653,.5263199210166931,.2385547012090683,0,2,8,12,3,2,-1,8,13,3,1,2,.0017318050377070904,.4319379031658173,.6983600854873657,0,2,9,3,6,2,-1,11,3,2,2,3,-.006848270073533058,.3082042932510376,.5390920042991638,0,2,3,11,14,4,-1,3,13,14,2,2,-15062530110299122e-21,.552192211151123,.3120366036891937,0,3,1,10,18,4,-1,10,10,9,2,2,1,12,9,2,2,.0294755697250366,.5401322841644287,.1770603060722351,0,2,0,10,3,3,-1,0,11,3,1,3,.008138732984662056,.5178617835044861,.121101900935173,0,2,9,1,6,6,-1,11,1,2,6,3,.0209429506212473,.5290294289588928,.3311221897602081,0,2,8,7,3,6,-1,9,7,1,6,3,-.009566552937030792,.7471994161605835,.4451968967914581,15.324139595031738,33,0,2,1,0,18,9,-1,1,3,18,3,3,-.00028206960996612906,.2064086049795151,.6076732277870178,0,2,12,10,2,6,-1,12,13,2,3,2,.00167906004935503,.5851997137069702,.1255383938550949,0,2,0,5,19,8,-1,0,9,19,4,2,.0006982791237533092,.094018429517746,.5728961229324341,0,2,7,0,6,9,-1,9,0,2,9,3,.0007895901217125356,.1781987994909287,.5694308876991272,0,2,5,3,6,1,-1,7,3,2,1,3,-.002856049919500947,.1638399064540863,.5788664817810059,0,2,11,3,6,1,-1,13,3,2,1,3,-.0038122469559311867,.2085440009832382,.5508564710617065,0,2,5,10,4,6,-1,5,13,4,3,2,.0015896620461717248,.5702760815620422,.1857215017080307,0,2,11,3,6,1,-1,13,3,2,1,3,.0100783398374915,.5116943120956421,.2189770042896271,0,2,4,4,12,6,-1,4,6,12,2,3,-.0635263025760651,.7131379842758179,.4043813049793243,0,2,15,12,2,6,-1,15,14,2,2,3,-.009103149175643921,.2567181885242462,.54639732837677,0,2,9,3,2,2,-1,10,3,1,2,2,-.002403500024229288,.1700665950775147,.559097409248352,0,2,9,3,3,1,-1,10,3,1,1,3,.001522636041045189,.5410556793212891,.2619054019451141,0,2,1,1,4,14,-1,3,1,2,14,2,.0179974399507046,.3732436895370483,.6535220742225647,0,3,9,0,4,4,-1,11,0,2,2,2,9,2,2,2,2,-.00645381910726428,.2626481950283051,.5537446141242981,0,2,7,5,1,14,-1,7,12,1,7,2,-.0118807600811124,.2003753930330277,.5544745922088623,0,2,19,0,1,4,-1,19,2,1,2,2,.0012713660253211856,.5591902732849121,.303197592496872,0,2,5,5,6,4,-1,8,5,3,4,2,.0011376109905540943,.2730407118797302,.5646508932113647,0,2,9,18,3,2,-1,10,18,1,2,3,-.00426519988104701,.1405909061431885,.5461820960044861,0,2,8,18,3,2,-1,9,18,1,2,3,-.0029602861031889915,.1795035004615784,.5459290146827698,0,2,4,5,12,6,-1,4,7,12,2,3,-.008844822645187378,.5736783146858215,.280921995639801,0,2,3,12,2,6,-1,3,14,2,2,3,-.006643068976700306,.2370675951242447,.5503826141357422,0,2,10,8,2,12,-1,10,12,2,4,3,.003999780863523483,.5608199834823608,.3304282128810883,0,2,7,18,3,2,-1,8,18,1,2,3,-.004122172016650438,.1640105992555618,.5378993153572083,0,2,9,0,6,2,-1,11,0,2,2,3,.0156249096617103,.5227649211883545,.2288603931665421,0,2,5,11,9,3,-1,5,12,9,1,3,-.0103564197197557,.7016193866729736,.4252927899360657,0,2,9,0,6,2,-1,11,0,2,2,3,-.008796080946922302,.2767347097396851,.5355830192565918,0,2,1,1,18,5,-1,7,1,6,5,3,.1622693985700607,.434224009513855,.744257926940918,0,3,8,0,4,4,-1,10,0,2,2,2,8,2,2,2,2,.0045542530715465546,.5726485848426819,.2582125067710877,0,2,3,12,1,3,-1,3,13,1,1,3,-.002130920998752117,.2106848061084747,.5361018776893616,0,2,8,14,5,3,-1,8,15,5,1,3,-.0132084200158715,.7593790888786316,.4552468061447144,0,3,5,4,10,12,-1,5,4,5,6,2,10,10,5,6,2,-.0659966766834259,.125247597694397,.5344039797782898,0,2,9,6,9,12,-1,9,10,9,4,3,.007914265617728233,.3315384089946747,.5601043105125427,0,3,2,2,12,14,-1,2,2,6,7,2,8,9,6,7,2,.0208942797034979,.5506049990653992,.2768838107585907,21.010639190673828,44,0,2,4,7,12,2,-1,8,7,4,2,3,.0011961159761995077,.1762690991163254,.6156241297721863,0,2,7,4,6,4,-1,7,6,6,2,2,-.0018679830245673656,.6118106842041016,.1832399964332581,0,2,4,5,11,8,-1,4,9,11,4,2,-.00019579799845814705,.0990442633628845,.5723816156387329,0,2,3,10,16,4,-1,3,12,16,2,2,-.0008025565766729414,.5579879879951477,.2377282977104187,0,2,0,0,16,2,-1,0,1,16,1,2,-.0024510810617357492,.2231457978487015,.5858935117721558,0,2,7,5,6,2,-1,9,5,2,2,3,.0005036185029894114,.2653993964195252,.5794103741645813,0,3,3,2,6,10,-1,3,2,3,5,2,6,7,3,5,2,.0040293349884450436,.5803827047348022,.2484865039587021,0,2,10,5,8,15,-1,10,10,8,5,3,-.0144517095759511,.1830351948738098,.5484204888343811,0,3,3,14,8,6,-1,3,14,4,3,2,7,17,4,3,2,.0020380979403853416,.3363558948040009,.6051092743873596,0,2,14,2,2,2,-1,14,3,2,1,2,-.0016155190533027053,.2286642044782639,.5441246032714844,0,2,1,10,7,6,-1,1,13,7,3,2,.0033458340913057327,.5625913143157959,.2392338067293167,0,2,15,4,4,3,-1,15,4,2,3,2,.0016379579901695251,.3906993865966797,.5964621901512146,0,3,2,9,14,6,-1,2,9,7,3,2,9,12,7,3,2,.0302512105554342,.524848222732544,.1575746983289719,0,2,5,7,10,4,-1,5,9,10,2,2,.037251990288496,.4194310903549194,.6748418807983398,0,3,6,9,8,8,-1,6,9,4,4,2,10,13,4,4,2,-.0251097902655602,.1882549971342087,.5473451018333435,0,2,14,1,3,2,-1,14,2,3,1,2,-.005309905856847763,.133997306227684,.5227110981941223,0,2,1,4,4,2,-1,3,4,2,2,2,.0012086479691788554,.3762088119983673,.6109635829925537,0,2,11,10,2,8,-1,11,14,2,4,2,-.0219076797366142,.266314297914505,.5404006838798523,0,2,0,0,5,3,-1,0,1,5,1,3,.0054116579703986645,.5363578796386719,.2232273072004318,0,3,2,5,18,8,-1,11,5,9,4,2,2,9,9,4,2,.069946326315403,.5358232855796814,.2453698068857193,0,2,6,6,1,6,-1,6,9,1,3,2,.00034520021290518343,.2409671992063522,.5376930236816406,0,2,19,1,1,3,-1,19,2,1,1,3,.0012627709656953812,.5425856709480286,.3155693113803864,0,2,7,6,6,6,-1,9,6,2,6,3,.0227195098996162,.4158405959606171,.6597865223884583,0,2,19,1,1,3,-1,19,2,1,1,3,-.001811100053600967,.2811253070831299,.5505244731903076,0,2,3,13,2,3,-1,3,14,2,1,3,.0033469670452177525,.526002824306488,.1891465038061142,0,3,8,4,8,12,-1,12,4,4,6,2,8,10,4,6,2,.00040791751234792173,.5673509240150452,.3344210088253021,0,2,5,2,6,3,-1,7,2,2,3,3,.0127347996458411,.5343592166900635,.2395612001419067,0,2,6,1,9,10,-1,6,6,9,5,2,-.007311972789466381,.6010890007019043,.4022207856178284,0,2,0,4,6,12,-1,2,4,2,12,3,-.0569487512111664,.8199151158332825,.4543190896511078,0,2,15,13,2,3,-1,15,14,2,1,3,-.005011659115552902,.2200281023979187,.5357710719108582,0,2,7,14,5,3,-1,7,15,5,1,3,.006033436860889196,.4413081109523773,.7181751132011414,0,2,15,13,3,3,-1,15,14,3,1,3,.0039437441155314445,.547886073589325,.2791733145713806,0,2,6,14,8,3,-1,6,15,8,1,3,-.0036591119132936,.635786771774292,.3989723920822144,0,2,15,13,3,3,-1,15,14,3,1,3,-.0038456181064248085,.3493686020374298,.5300664901733398,0,2,2,13,3,3,-1,2,14,3,1,3,-.007192626129835844,.1119614988565445,.5229672789573669,0,3,4,7,12,12,-1,10,7,6,6,2,4,13,6,6,2,-.0527989417314529,.2387102991342545,.54534512758255,0,2,9,7,2,6,-1,10,7,1,6,2,-.007953766733407974,.7586917877197266,.4439376890659332,0,2,8,9,5,2,-1,8,10,5,1,2,-.0027344180271029472,.2565476894378662,.5489321947097778,0,2,8,6,3,4,-1,9,6,1,4,3,-.0018507939530536532,.6734347939491272,.4252474904060364,0,2,9,6,2,8,-1,9,10,2,4,2,.0159189198166132,.548835277557373,.2292661964893341,0,2,7,7,3,6,-1,8,7,1,6,3,-.0012687679845839739,.6104331016540527,.4022389948368073,0,2,11,3,3,3,-1,12,3,1,3,3,.006288391072303057,.5310853123664856,.1536193042993546,0,2,5,4,6,1,-1,7,4,2,1,3,-.0062259892001748085,.1729111969470978,.524160623550415,0,2,5,6,10,3,-1,5,7,10,1,3,-.0121325999498367,.659775972366333,.4325182139873505,23.918790817260742,50,0,2,7,3,6,9,-1,7,6,6,3,3,-.0039184908382594585,.6103435158729553,.1469330936670303,0,2,6,7,9,1,-1,9,7,3,1,3,.0015971299726516008,.2632363140583038,.5896466970443726,0,2,2,8,16,8,-1,2,12,16,4,2,.0177801102399826,.587287425994873,.1760361939668655,0,2,14,6,2,6,-1,14,9,2,3,2,.0006533476989716291,.1567801982164383,.5596066117286682,0,2,1,5,6,15,-1,1,10,6,5,3,-.00028353091329336166,.1913153976202011,.5732036232948303,0,2,10,0,6,9,-1,10,3,6,3,3,.0016104689566418529,.2914913892745972,.5623080730438232,0,2,6,6,7,14,-1,6,13,7,7,2,-.0977506190538406,.194347694516182,.5648233294487,0,2,13,7,3,6,-1,13,9,3,2,3,.0005518235848285258,.3134616911411285,.5504639744758606,0,2,1,8,15,4,-1,6,8,5,4,3,-.0128582203760743,.253648191690445,.5760142803192139,0,2,11,2,3,10,-1,11,7,3,5,2,.004153023939579725,.5767722129821777,.36597740650177,0,2,3,7,4,6,-1,3,9,4,2,3,.0017092459602281451,.2843191027641296,.5918939113616943,0,2,13,3,6,10,-1,15,3,2,10,3,.007521735969930887,.4052427113056183,.6183109283447266,0,3,5,7,8,10,-1,5,7,4,5,2,9,12,4,5,2,.0022479810286313295,.578375518321991,.3135401010513306,0,3,4,4,12,12,-1,10,4,6,6,2,4,10,6,6,2,.0520062111318111,.5541312098503113,.1916636973619461,0,2,1,4,6,9,-1,3,4,2,9,3,.0120855299755931,.4032655954360962,.6644591093063354,0,2,11,3,2,5,-1,11,3,1,5,2,14687820112158079e-21,.3535977900028229,.5709382891654968,0,2,7,3,2,5,-1,8,3,1,5,2,7139518857002258e-21,.3037444949150085,.5610269904136658,0,2,10,14,2,3,-1,10,15,2,1,3,-.0046001640148460865,.7181087136268616,.4580326080322266,0,2,5,12,6,2,-1,8,12,3,2,2,.0020058949012309313,.5621951818466187,.2953684031963348,0,2,9,14,2,3,-1,9,15,2,1,3,.004505027085542679,.4615387916564941,.7619017958641052,0,2,4,11,12,6,-1,4,14,12,3,2,.0117468303069472,.5343837141990662,.1772529035806656,0,2,11,11,5,9,-1,11,14,5,3,3,-.0583163388073444,.1686245948076248,.5340772271156311,0,2,6,15,3,2,-1,6,16,3,1,2,.00023629379575140774,.3792056143283844,.6026803851127625,0,2,11,0,3,5,-1,12,0,1,5,3,-.007815618067979813,.151286706328392,.5324323773384094,0,2,5,5,6,7,-1,8,5,3,7,2,-.0108761601150036,.2081822007894516,.5319945216178894,0,2,13,0,1,9,-1,13,3,1,3,3,-.0027745519764721394,.4098246991634369,.5210328102111816,0,3,3,2,4,8,-1,3,2,2,4,2,5,6,2,4,2,-.0007827638182789087,.5693274140357971,.3478842079639435,0,2,13,12,4,6,-1,13,14,4,2,3,.0138704096898437,.5326750874519348,.2257698029279709,0,2,3,12,4,6,-1,3,14,4,2,3,-.0236749108880758,.1551305055618286,.5200707912445068,0,2,13,11,3,4,-1,13,13,3,2,2,-14879409718560055e-21,.5500566959381104,.3820176124572754,0,2,4,4,4,3,-1,4,5,4,1,3,.00361906411126256,.4238683879375458,.6639748215675354,0,2,7,5,11,8,-1,7,9,11,4,2,-.0198171101510525,.2150038033723831,.5382357835769653,0,2,7,8,3,4,-1,8,8,1,4,3,-.0038154039066284895,.6675711274147034,.4215297102928162,0,2,9,1,6,1,-1,11,1,2,1,3,-.0049775829538702965,.2267289012670517,.5386328101158142,0,2,5,5,3,3,-1,5,6,3,1,3,.002244102070108056,.4308691024780273,.6855735778808594,0,3,0,9,20,6,-1,10,9,10,3,2,0,12,10,3,2,.0122824599966407,.5836614966392517,.3467479050159454,0,2,8,6,3,5,-1,9,6,1,5,3,-.002854869933798909,.7016944885253906,.4311453998088837,0,2,11,0,1,3,-1,11,1,1,1,3,-.0037875669077038765,.2895345091819763,.5224946141242981,0,2,4,2,4,2,-1,4,3,4,1,2,-.0012201230274513364,.2975570857524872,.5481644868850708,0,2,12,6,4,3,-1,12,7,4,1,3,.010160599835217,.4888817965984345,.8182697892189026,0,2,5,0,6,4,-1,7,0,2,4,3,-.0161745697259903,.1481492966413498,.5239992737770081,0,2,9,7,3,8,-1,10,7,1,8,3,.0192924607545137,.4786309897899628,.7378190755844116,0,2,9,7,2,2,-1,10,7,1,2,2,-.003247953951358795,.7374222874641418,.4470643997192383,0,3,6,7,14,4,-1,13,7,7,2,2,6,9,7,2,2,-.009380348026752472,.3489154875278473,.5537996292114258,0,2,0,5,3,6,-1,0,7,3,2,3,-.0126061299815774,.2379686981439591,.5315443277359009,0,2,13,11,3,4,-1,13,13,3,2,2,-.0256219301372766,.1964688003063202,.5138769745826721,0,2,4,11,3,4,-1,4,13,3,2,2,-7574149640277028e-20,.5590522885322571,.3365853130817413,0,3,5,9,12,8,-1,11,9,6,4,2,5,13,6,4,2,-.0892108827829361,.0634046569466591,.516263484954834,0,2,9,12,1,3,-1,9,13,1,1,3,-.002767048077657819,.732346773147583,.4490706026554108,0,2,10,15,2,4,-1,10,17,2,2,2,.0002715257869567722,.411483496427536,.5985518097877502,24.52787971496582,51,0,2,7,7,6,1,-1,9,7,2,1,3,.001478621968999505,.266354501247406,.6643316745758057,0,3,12,3,6,6,-1,15,3,3,3,2,12,6,3,3,2,-.001874165958724916,.6143848896026611,.2518512904644013,0,2,0,4,10,6,-1,0,6,10,2,3,-.001715100952424109,.5766341090202332,.2397463023662567,0,3,8,3,8,14,-1,12,3,4,7,2,8,10,4,7,2,-.0018939269939437509,.5682045817375183,.2529144883155823,0,2,4,4,7,15,-1,4,9,7,5,3,-.005300605203956366,.1640675961971283,.5556079745292664,0,3,12,2,6,8,-1,15,2,3,4,2,12,6,3,4,2,-.0466625317931175,.6123154163360596,.4762830138206482,0,3,2,2,6,8,-1,2,2,3,4,2,5,6,3,4,2,-.000794313324149698,.5707858800888062,.2839404046535492,0,2,2,13,18,7,-1,8,13,6,7,3,.0148916700854898,.4089672863483429,.6006367206573486,0,3,4,3,8,14,-1,4,3,4,7,2,8,10,4,7,2,-.0012046529445797205,.5712450742721558,.2705289125442505,0,2,18,1,2,6,-1,18,3,2,2,3,.006061938125640154,.526250422000885,.3262225985527039,0,2,9,11,2,3,-1,9,12,2,1,3,-.0025286648888140917,.6853830814361572,.4199256896972656,0,2,18,1,2,6,-1,18,3,2,2,3,-.005901021882891655,.3266282081604004,.5434812903404236,0,2,0,1,2,6,-1,0,3,2,2,3,.005670276004821062,.5468410849571228,.2319003939628601,0,2,1,5,18,6,-1,1,7,18,2,3,-.003030410036444664,.557066798210144,.2708238065242767,0,2,0,2,6,7,-1,3,2,3,7,2,.002980364952236414,.3700568974018097,.5890625715255737,0,2,7,3,6,14,-1,7,10,6,7,2,-.0758405104279518,.2140070050954819,.5419948101043701,0,2,3,7,13,10,-1,3,12,13,5,2,.0192625392228365,.5526772141456604,.2726590037345886,0,2,11,15,2,2,-1,11,16,2,1,2,.00018888259364757687,.3958011865615845,.6017209887504578,0,3,2,11,16,4,-1,2,11,8,2,2,10,13,8,2,2,.0293695498257875,.5241373777389526,.1435758024454117,0,3,13,7,6,4,-1,16,7,3,2,2,13,9,3,2,2,.0010417619487270713,.3385409116744995,.5929983258247375,0,2,6,10,3,9,-1,6,13,3,3,3,.0026125640142709017,.5485377907752991,.3021597862243652,0,2,14,6,1,6,-1,14,9,1,3,2,.0009697746718302369,.3375276029109955,.553203284740448,0,2,5,10,4,1,-1,7,10,2,1,2,.0005951265920884907,.563174307346344,.3359399139881134,0,2,3,8,15,5,-1,8,8,5,5,3,-.1015655994415283,.0637350380420685,.5230425000190735,0,2,1,6,5,4,-1,1,8,5,2,2,.0361566990613937,.5136963129043579,.1029528975486755,0,2,3,1,17,6,-1,3,3,17,2,3,.003462414024397731,.3879320025444031,.5558289289474487,0,2,6,7,8,2,-1,10,7,4,2,2,.0195549800992012,.5250086784362793,.1875859946012497,0,2,9,7,3,2,-1,10,7,1,2,3,-.0023121440317481756,.667202889919281,.4679641127586365,0,2,8,7,3,2,-1,9,7,1,2,3,-.001860528951510787,.7163379192352295,.4334670901298523,0,2,8,9,4,2,-1,8,10,4,1,2,-.0009402636205777526,.302136093378067,.5650203227996826,0,2,8,8,4,3,-1,8,9,4,1,3,-.005241833161562681,.1820009052753449,.5250256061553955,0,2,9,5,6,4,-1,9,5,3,4,2,.00011729019752237946,.3389188051223755,.544597327709198,0,2,8,13,4,3,-1,8,14,4,1,3,.0011878840159624815,.4085349142551422,.6253563165664673,0,3,4,7,12,6,-1,10,7,6,3,2,4,10,6,3,2,-.0108813596889377,.3378399014472961,.5700082778930664,0,2,8,14,4,3,-1,8,15,4,1,3,.0017354859737679362,.4204635918140411,.6523038744926453,0,2,9,7,3,3,-1,9,8,3,1,3,-.00651190523058176,.2595216035842896,.5428143739700317,0,2,7,4,3,8,-1,8,4,1,8,3,-.0012136430013924837,.6165143847465515,.3977893888950348,0,2,10,0,3,6,-1,11,0,1,6,3,-.010354240424931,.1628028005361557,.5219504833221436,0,2,6,3,4,8,-1,8,3,2,8,2,.0005585883045569062,.3199650943279266,.5503574013710022,0,2,14,3,6,13,-1,14,3,3,13,2,.0152996499091387,.4103994071483612,.6122388243675232,0,2,8,13,3,6,-1,8,16,3,3,2,-.021588210016489,.103491298854351,.519738495349884,0,2,14,3,6,13,-1,14,3,3,13,2,-.1283462941646576,.8493865132331848,.4893102943897247,0,3,0,7,10,4,-1,0,7,5,2,2,5,9,5,2,2,-.0022927189711481333,.3130157887935638,.5471575260162354,0,2,14,3,6,13,-1,14,3,3,13,2,.0799151062965393,.4856320917606354,.6073989272117615,0,2,0,3,6,13,-1,3,3,3,13,2,-.0794410929083824,.8394674062728882,.462453305721283,0,2,9,1,4,1,-1,9,1,2,1,2,-.00528000108897686,.1881695985794067,.5306698083877563,0,2,8,0,2,1,-1,9,0,1,1,2,.0010463109938427806,.5271229147911072,.2583065927028656,0,3,10,16,4,4,-1,12,16,2,2,2,10,18,2,2,2,.00026317298761568964,.4235304892063141,.5735440850257874,0,2,9,6,2,3,-1,10,6,1,3,2,-.0036173160187900066,.6934396028518677,.4495444893836975,0,2,4,5,12,2,-1,8,5,4,2,3,.0114218797534704,.590092122554779,.4138193130493164,0,2,8,7,3,5,-1,9,7,1,5,3,-.0019963278900831938,.6466382741928101,.4327239990234375,27.153350830078125,56,0,2,6,4,8,6,-1,6,6,8,2,3,-.00996912457048893,.6142324209213257,.2482212036848068,0,2,9,5,2,12,-1,9,11,2,6,2,.0007307305932044983,.5704951882362366,.2321965992450714,0,2,4,6,6,8,-1,4,10,6,4,2,.0006404530140571296,.2112251967191696,.5814933180809021,0,2,12,2,8,5,-1,12,2,4,5,2,.004542401991784573,.2950482070446014,.586631178855896,0,2,0,8,18,3,-1,0,9,18,1,3,9247744310414419e-20,.2990990877151489,.5791326761245728,0,2,8,12,4,8,-1,8,16,4,4,2,-.008660314604640007,.2813029885292053,.5635542273521423,0,2,0,2,8,5,-1,4,2,4,5,2,.008051581680774689,.3535369038581848,.6054757237434387,0,2,13,11,3,4,-1,13,13,3,2,2,.00043835240649059415,.5596532225608826,.2731510996818543,0,2,5,11,6,1,-1,7,11,2,1,3,-981689736363478e-19,.5978031754493713,.3638561069965363,0,2,11,3,3,1,-1,12,3,1,1,3,-.0011298790341243148,.2755252122879028,.5432729125022888,0,2,7,13,5,3,-1,7,14,5,1,3,.006435615010559559,.4305641949176788,.7069833278656006,0,2,11,11,7,6,-1,11,14,7,3,2,-.0568293295800686,.2495242953300476,.5294997096061707,0,2,2,11,7,6,-1,2,14,7,3,2,.004066816996783018,.5478553175926208,.2497723996639252,0,2,12,14,2,6,-1,12,16,2,2,3,481647984997835e-19,.3938601016998291,.5706356167793274,0,2,8,14,3,3,-1,8,15,3,1,3,.00617950176820159,.440760612487793,.7394766807556152,0,2,11,0,3,5,-1,12,0,1,5,3,.006498575210571289,.5445243120193481,.2479152977466583,0,2,6,1,4,9,-1,8,1,2,9,2,-.0010211090557277203,.2544766962528229,.5338971018791199,0,2,10,3,6,1,-1,12,3,2,1,3,-.005424752831459045,.2718858122825623,.5324069261550903,0,2,8,8,3,4,-1,8,10,3,2,2,-.0010559899965301156,.3178288042545319,.553450882434845,0,2,8,12,4,2,-1,8,13,4,1,2,.0006646580877713859,.4284219145774841,.6558194160461426,0,2,5,18,4,2,-1,5,19,4,1,2,-.00027524109464138746,.5902860760688782,.3810262978076935,0,2,2,1,18,6,-1,2,3,18,2,3,.004229320213198662,.381648987531662,.5709385871887207,0,2,6,0,3,2,-1,7,0,1,2,3,-.0032868210691958666,.1747743934392929,.5259544253349304,0,3,13,8,6,2,-1,16,8,3,1,2,13,9,3,1,2,.0001561187964398414,.3601722121238709,.5725612044334412,0,2,6,10,3,6,-1,6,13,3,3,2,-7362138148891972e-21,.540185809135437,.3044497072696686,0,3,0,13,20,4,-1,10,13,10,2,2,0,15,10,2,2,-.014767250046134,.3220770061016083,.5573434829711914,0,2,7,7,6,5,-1,9,7,2,5,3,.0244895908981562,.4301528036594391,.6518812775611877,0,2,11,0,2,2,-1,11,1,2,1,2,-.000376520911231637,.356458306312561,.5598236918449402,0,3,1,8,6,2,-1,1,8,3,1,2,4,9,3,1,2,736576885174145e-20,.3490782976150513,.556189775466919,0,3,0,2,20,2,-1,10,2,10,1,2,0,3,10,1,2,-.0150999398902059,.1776272058486939,.5335299968719482,0,2,7,14,5,3,-1,7,15,5,1,3,-.0038316650316119194,.6149687767028809,.4221394062042236,0,3,7,13,6,6,-1,10,13,3,3,2,7,16,3,3,2,.0169254001230001,.5413014888763428,.2166585028171539,0,2,9,12,2,3,-1,9,13,2,1,3,-.003047785023227334,.6449490785598755,.4354617893695831,0,2,16,11,1,6,-1,16,13,1,2,3,.003214058931916952,.5400155186653137,.3523217141628265,0,2,3,11,1,6,-1,3,13,1,2,3,-.004002320114523172,.2774524092674255,.5338417291641235,0,3,4,4,14,12,-1,11,4,7,6,2,4,10,7,6,2,.0074182129465043545,.567673921585083,.3702817857265472,0,2,5,4,3,3,-1,5,5,3,1,3,-.008876458741724491,.7749221920967102,.4583688974380493,0,2,12,3,3,3,-1,13,3,1,3,3,.002731173997744918,.5338721871376038,.3996661007404327,0,2,6,6,8,3,-1,6,7,8,1,3,-.0025082379579544067,.5611963272094727,.377749890089035,0,2,12,3,3,3,-1,13,3,1,3,3,-.008054107427597046,.291522890329361,.5179182887077332,0,3,3,1,4,10,-1,3,1,2,5,2,5,6,2,5,2,-.0009793881326913834,.5536432862281799,.3700192868709564,0,2,5,7,10,2,-1,5,7,5,2,2,-.005874590948224068,.3754391074180603,.5679376125335693,0,2,8,7,3,3,-1,9,7,1,3,3,-.00449367193505168,.7019699215888977,.4480949938297272,0,2,15,12,2,3,-1,15,13,2,1,3,-.00543892290443182,.2310364991426468,.5313386917114258,0,2,7,8,3,4,-1,8,8,1,4,3,-.0007509464048780501,.5864868760108948,.4129343032836914,0,2,13,4,1,12,-1,13,10,1,6,2,14528800420521293e-21,.3732407093048096,.5619621276855469,0,3,4,5,12,12,-1,4,5,6,6,2,10,11,6,6,2,.0407580696046352,.5312091112136841,.2720521986484528,0,2,7,14,7,3,-1,7,15,7,1,3,.006650593131780624,.4710015952587128,.6693493723869324,0,2,3,12,2,3,-1,3,13,2,1,3,.0045759351924061775,.5167819261550903,.1637275964021683,0,3,3,2,14,2,-1,10,2,7,1,2,3,3,7,1,2,.0065269311890006065,.5397608876228333,.2938531935214996,0,2,0,1,3,10,-1,1,1,1,10,3,-.0136603796854615,.7086488008499146,.453220009803772,0,2,9,0,6,5,-1,11,0,2,5,3,.0273588690906763,.5206481218338013,.3589231967926025,0,2,5,7,6,2,-1,8,7,3,2,2,.0006219755159690976,.3507075905799866,.5441123247146606,0,2,7,1,6,10,-1,7,6,6,5,2,-.0033077080734074116,.5859522819519043,.402489185333252,0,2,1,1,18,3,-1,7,1,6,3,3,-.0106311095878482,.6743267178535461,.4422602951526642,0,2,16,3,3,6,-1,16,5,3,2,3,.0194416493177414,.5282716155052185,.1797904968261719,34.55411148071289,71,0,2,6,3,7,6,-1,6,6,7,3,2,-.005505216773599386,.5914731025695801,.2626559138298035,0,2,4,7,12,2,-1,8,7,4,2,3,.001956227933987975,.2312581986188889,.5741627216339111,0,2,0,4,17,10,-1,0,9,17,5,2,-.008892478421330452,.1656530052423477,.5626654028892517,0,2,3,4,15,16,-1,3,12,15,8,2,.0836383774876595,.5423449873924255,.1957294940948486,0,2,7,15,6,4,-1,7,17,6,2,2,.0012282270472496748,.3417904078960419,.5992503762245178,0,2,15,2,4,9,-1,15,2,2,9,2,.0057629169896245,.3719581961631775,.6079903841018677,0,2,2,3,3,2,-1,2,4,3,1,2,-.0016417410224676132,.2577486038208008,.5576915740966797,0,2,13,6,7,9,-1,13,9,7,3,3,.0034113149158656597,.2950749099254608,.5514171719551086,0,2,8,11,4,3,-1,8,12,4,1,3,-.0110693201422691,.7569358944892883,.4477078914642334,0,3,0,2,20,6,-1,10,2,10,3,2,0,5,10,3,2,.0348659716546535,.5583708882331848,.2669621109962463,0,3,3,2,6,10,-1,3,2,3,5,2,6,7,3,5,2,.0006570109981112182,.5627313256263733,.2988890111446381,0,2,13,10,3,4,-1,13,12,3,2,2,-.0243391301482916,.2771185040473938,.5108863115310669,0,2,4,10,3,4,-1,4,12,3,2,2,.0005943520227447152,.5580651760101318,.3120341897010803,0,2,7,5,6,3,-1,9,5,2,3,3,.0022971509024500847,.3330250084400177,.5679075717926025,0,2,7,6,6,8,-1,7,10,6,4,2,-.0037801829166710377,.2990534901618958,.5344808101654053,0,2,0,11,20,6,-1,0,14,20,3,2,-.13420669734478,.1463858932256699,.5392568111419678,0,3,4,13,4,6,-1,4,13,2,3,2,6,16,2,3,2,.0007522454834543169,.3746953904628754,.5692734718322754,0,3,6,0,8,12,-1,10,0,4,6,2,6,6,4,6,2,-.040545541793108,.2754747867584229,.5484297871589661,0,2,2,0,15,2,-1,2,1,15,1,2,.0012572970008477569,.3744584023952484,.5756075978279114,0,2,9,12,2,3,-1,9,13,2,1,3,-.007424994837492704,.7513859272003174,.4728231132030487,0,2,3,12,1,2,-1,3,13,1,1,2,.0005090812919661403,.540489673614502,.2932321131229401,0,2,9,11,2,3,-1,9,12,2,1,3,-.001280845026485622,.6169779896736145,.4273349046707153,0,2,7,3,3,1,-1,8,3,1,1,3,-.0018348860321566463,.2048496007919312,.5206472277641296,0,2,17,7,3,6,-1,17,9,3,2,3,.0274848695844412,.5252984762191772,.1675522029399872,0,2,7,2,3,2,-1,8,2,1,2,3,.0022372419480234385,.5267782807350159,.2777658104896545,0,2,11,4,5,3,-1,11,5,5,1,3,-.008863529190421104,.69545578956604,.4812048971652985,0,2,4,4,5,3,-1,4,5,5,1,3,.004175397101789713,.4291887879371643,.6349195837974548,0,2,19,3,1,2,-1,19,4,1,1,2,-.0017098189564421773,.2930536866188049,.5361248850822449,0,2,5,5,4,3,-1,5,6,4,1,3,.006532854866236448,.4495325088500977,.7409694194793701,0,2,17,7,3,6,-1,17,9,3,2,3,-.009537290781736374,.3149119913578033,.5416501760482788,0,2,0,7,3,6,-1,0,9,3,2,3,.0253109894692898,.5121892094612122,.1311707943677902,0,2,14,2,6,9,-1,14,5,6,3,3,.0364609695971012,.5175911784172058,.2591339945793152,0,2,0,4,5,6,-1,0,6,5,2,3,.0208543296903372,.5137140154838562,.1582316011190414,0,2,10,5,6,2,-1,12,5,2,2,3,-.0008720774785615504,.5574309825897217,.439897894859314,0,2,4,5,6,2,-1,6,5,2,2,3,-15227000403683633e-21,.5548940896987915,.3708069920539856,0,2,8,1,4,6,-1,8,3,4,2,3,-.0008431650931015611,.3387419879436493,.5554211139678955,0,2,0,2,3,6,-1,0,4,3,2,3,.0036037859972566366,.5358061790466309,.3411171138286591,0,2,6,6,8,3,-1,6,7,8,1,3,-.006805789191275835,.6125202775001526,.4345862865447998,0,2,0,1,5,9,-1,0,4,5,3,3,-.0470216609537601,.2358165979385376,.519373893737793,0,2,16,0,4,15,-1,16,0,2,15,2,-.0369541086256504,.7323111295700073,.4760943949222565,0,2,1,10,3,2,-1,1,11,3,1,2,.0010439479956403375,.5419455170631409,.3411330878734589,0,2,14,4,1,10,-1,14,9,1,5,2,-.00021050689974799752,.2821694016456604,.5554947257041931,0,2,0,1,4,12,-1,2,1,2,12,2,-.0808315873146057,.9129930138587952,.4697434902191162,0,2,11,11,4,2,-1,11,11,2,2,2,-.0003657905908767134,.6022670269012451,.3978292942047119,0,2,5,11,4,2,-1,7,11,2,2,2,-.00012545920617412776,.5613213181495667,.384553998708725,0,2,3,8,15,5,-1,8,8,5,5,3,-.0687864869832993,.2261611968278885,.5300496816635132,0,2,0,0,6,10,-1,3,0,3,10,2,.0124157899990678,.4075691998004913,.5828812122344971,0,2,11,4,3,2,-1,12,4,1,2,3,-.004717481788247824,.2827253937721252,.5267757773399353,0,2,8,12,3,8,-1,8,16,3,4,2,.0381368584930897,.5074741244316101,.1023615971207619,0,2,8,14,5,3,-1,8,15,5,1,3,-.0028168049175292253,.6169006824493408,.4359692931175232,0,2,7,14,4,3,-1,7,15,4,1,3,.008130360394716263,.4524433016777039,.76060950756073,0,2,11,4,3,2,-1,12,4,1,2,3,.006005601957440376,.5240408778190613,.185971200466156,0,3,3,15,14,4,-1,3,15,7,2,2,10,17,7,2,2,.0191393196582794,.5209379196166992,.2332071959972382,0,3,2,2,16,4,-1,10,2,8,2,2,2,4,8,2,2,.0164457596838474,.5450702905654907,.3264234960079193,0,2,0,8,6,12,-1,3,8,3,12,2,-.0373568907380104,.6999046802520752,.4533241987228394,0,2,5,7,10,2,-1,5,7,5,2,2,-.0197279006242752,.2653664946556091,.54128098487854,0,2,9,7,2,5,-1,10,7,1,5,2,.0066972579807043076,.4480566084384918,.7138652205467224,0,3,13,7,6,4,-1,16,7,3,2,2,13,9,3,2,2,.0007445752853527665,.4231350123882294,.5471320152282715,0,2,0,13,8,2,-1,0,14,8,1,2,.0011790640419349074,.5341702103614807,.3130455017089844,0,3,13,7,6,4,-1,16,7,3,2,2,13,9,3,2,2,.0349806100130081,.5118659734725952,.343053013086319,0,3,1,7,6,4,-1,1,7,3,2,2,4,9,3,2,2,.0005685979267582297,.3532187044620514,.5468639731407166,0,2,12,6,1,12,-1,12,12,1,6,2,-.0113406497985125,.2842353880405426,.5348700881004333,0,2,9,5,2,6,-1,10,5,1,6,2,-.00662281084805727,.6883640289306641,.4492664933204651,0,2,14,12,2,3,-1,14,13,2,1,3,-.008016033098101616,.1709893941879273,.5224308967590332,0,2,4,12,2,3,-1,4,13,2,1,3,.0014206819469109178,.5290846228599548,.299338310956955,0,2,8,12,4,3,-1,8,13,4,1,3,-.002780171111226082,.6498854160308838,.4460499882698059,0,3,5,2,2,4,-1,5,2,1,2,2,6,4,1,2,2,-.0014747589593753219,.3260438144207001,.5388113260269165,0,2,5,5,11,3,-1,5,6,11,1,3,-.0238303393125534,.7528941035270691,.4801219999790192,0,2,7,6,4,12,-1,7,12,4,6,2,.00693697901442647,.5335165858268738,.3261427879333496,0,2,12,13,8,5,-1,12,13,4,5,2,.008280625566840172,.458039402961731,.5737829804420471,0,2,7,6,1,12,-1,7,12,1,6,2,-.0104395002126694,.2592320144176483,.5233827829360962,39.1072883605957,80,0,2,1,2,6,3,-1,4,2,3,3,2,.0072006587870419025,.325888603925705,.6849808096885681,0,3,9,5,6,10,-1,12,5,3,5,2,9,10,3,5,2,-.002859358908608556,.5838881134986877,.2537829875946045,0,3,5,5,8,12,-1,5,5,4,6,2,9,11,4,6,2,.0006858052802272141,.5708081722259521,.2812424004077911,0,2,0,7,20,6,-1,0,9,20,2,3,.007958019152283669,.2501051127910614,.5544260740280151,0,2,4,2,2,2,-1,4,3,2,1,2,-.0012124150525778532,.2385368049144745,.5433350205421448,0,2,4,18,12,2,-1,8,18,4,2,3,.00794261321425438,.3955070972442627,.6220757961273193,0,2,7,4,4,16,-1,7,12,4,8,2,.0024630590341985226,.5639708042144775,.2992357909679413,0,2,7,6,7,8,-1,7,10,7,4,2,-.006039659958332777,.218651294708252,.541167676448822,0,2,6,3,3,1,-1,7,3,1,1,3,-.0012988339876756072,.23507060110569,.5364584922790527,0,2,11,15,2,4,-1,11,17,2,2,2,.00022299369447864592,.380411297082901,.572960615158081,0,2,3,5,4,8,-1,3,9,4,4,2,.0014654280385002494,.2510167956352234,.5258268713951111,0,2,7,1,6,12,-1,7,7,6,6,2,-.0008121004211716354,.5992823839187622,.3851158916950226,0,2,4,6,6,2,-1,6,6,2,2,3,-.0013836020370945334,.5681396126747131,.3636586964130402,0,2,16,4,4,6,-1,16,6,4,2,3,-.0279364492744207,.1491317003965378,.5377560257911682,0,2,3,3,5,2,-1,3,4,5,1,2,-.0004691955109592527,.3692429959774017,.5572484731674194,0,2,9,11,2,3,-1,9,12,2,1,3,-.004982965998351574,.6758509278297424,.4532504081726074,0,2,2,16,4,2,-1,2,17,4,1,2,.001881530974060297,.5368022918701172,.2932539880275726,0,3,7,13,6,6,-1,10,13,3,3,2,7,16,3,3,2,-.0190675500780344,.1649377048015595,.5330067276954651,0,2,7,0,3,4,-1,8,0,1,4,3,-.0046906559728085995,.1963925957679749,.5119361877441406,0,2,8,15,4,3,-1,8,16,4,1,3,.005977713968604803,.467117190361023,.7008398175239563,0,2,0,4,4,6,-1,0,6,4,2,3,-.0333031304180622,.1155416965484619,.5104162096977234,0,2,5,6,12,3,-1,9,6,4,3,3,.0907441079616547,.5149660110473633,.1306173056364059,0,2,7,6,6,14,-1,9,6,2,14,3,.0009355589863844216,.3605481088161469,.543985903263092,0,2,9,7,3,3,-1,10,7,1,3,3,.0149016501381993,.4886212050914764,.7687569856643677,0,2,6,12,2,4,-1,6,14,2,2,2,.0006159411859698594,.5356813073158264,.3240939080715179,0,2,10,12,7,6,-1,10,14,7,2,3,-.0506709888577461,.1848621964454651,.5230404138565063,0,2,1,0,15,2,-1,1,1,15,1,2,.0006866574985906482,.3840579986572266,.5517945885658264,0,2,14,0,6,6,-1,14,0,3,6,2,.008371243253350258,.4288564026355743,.6131753921508789,0,2,5,3,3,1,-1,6,3,1,1,3,-.0012953069526702166,.2913674116134644,.528073787689209,0,2,14,0,6,6,-1,14,0,3,6,2,-.0419416800141335,.7554799914360046,.4856030941009522,0,2,0,3,20,10,-1,0,8,20,5,2,-.0235293805599213,.2838279902935028,.5256081223487854,0,2,14,0,6,6,-1,14,0,3,6,2,.0408574491739273,.4870935082435608,.6277297139167786,0,2,0,0,6,6,-1,3,0,3,6,2,-.0254068691283464,.7099707722663879,.4575029015541077,0,2,19,15,1,2,-1,19,16,1,1,2,-.00041415440500713885,.4030886888504028,.5469412207603455,0,2,0,2,4,8,-1,2,2,2,8,2,.0218241196125746,.4502024054527283,.6768701076507568,0,3,2,1,18,4,-1,11,1,9,2,2,2,3,9,2,2,.0141140399500728,.5442860722541809,.3791700005531311,0,2,8,12,1,2,-1,8,13,1,1,2,6721459067193791e-20,.4200463891029358,.5873476266860962,0,3,5,2,10,6,-1,10,2,5,3,2,5,5,5,3,2,-.00794176384806633,.3792561888694763,.5585265755653381,0,2,9,7,2,4,-1,10,7,1,4,2,-.00721444096416235,.7253103852272034,.4603548943996429,0,2,9,7,3,3,-1,10,7,1,3,3,.002581733977422118,.4693301916122437,.5900238752365112,0,2,4,5,12,8,-1,8,5,4,8,3,.1340931951999664,.5149213075637817,.1808844953775406,0,2,15,15,4,3,-1,15,16,4,1,3,.0022962710354477167,.5399743914604187,.3717867136001587,0,2,8,18,3,1,-1,9,18,1,1,3,-.002157584996894002,.2408495992422104,.5148863792419434,0,2,9,13,4,3,-1,9,14,4,1,3,-.004919618833810091,.6573588252067566,.4738740026950836,0,2,7,13,4,3,-1,7,14,4,1,3,.0016267469618469477,.4192821979522705,.6303114295005798,0,2,19,15,1,2,-1,19,16,1,1,2,.00033413388882763684,.5540298223495483,.3702101111412048,0,2,0,15,8,4,-1,0,17,8,2,2,-.0266980808228254,.1710917949676514,.5101410746574402,0,2,9,3,6,4,-1,11,3,2,4,3,-.0305618792772293,.1904218047857285,.5168793797492981,0,2,8,14,4,3,-1,8,15,4,1,3,.002851154888048768,.4447506964206696,.6313853859901428,0,2,3,14,14,6,-1,3,16,14,2,3,-.0362114794552326,.2490727007389069,.5377349257469177,0,2,6,3,6,6,-1,6,6,6,3,2,-.002411518944427371,.5381243228912354,.3664236962795258,0,2,5,11,10,6,-1,5,14,10,3,2,-.0007725320174358785,.5530232191085815,.3541550040245056,0,2,3,10,3,4,-1,4,10,1,4,3,.0002948172914329916,.4132699072360992,.5667243003845215,0,2,13,9,2,2,-1,13,9,1,2,2,-.006233456078916788,.0987872332334518,.5198668837547302,0,2,5,3,6,4,-1,7,3,2,4,3,-.0262747295200825,.0911274924874306,.5028107166290283,0,2,9,7,3,3,-1,10,7,1,3,3,.005321226082742214,.4726648926734924,.6222720742225647,0,2,2,12,2,3,-1,2,13,2,1,3,-.004112905822694302,.2157457023859024,.5137804746627808,0,2,9,8,3,12,-1,9,12,3,4,3,.0032457809429615736,.5410770773887634,.3721776902675629,0,3,3,14,4,6,-1,3,14,2,3,2,5,17,2,3,2,-.0163597092032433,.7787874937057495,.4685291945934296,0,2,16,15,2,2,-1,16,16,2,1,2,.00032166109303943813,.5478987097740173,.4240373969078064,0,2,2,15,2,2,-1,2,16,2,1,2,.000644524407107383,.5330560803413391,.3501324951648712,0,2,8,12,4,3,-1,8,13,4,1,3,-.0078909732401371,.6923521161079407,.4726569056510925,0,2,0,7,20,1,-1,10,7,10,1,2,.048336211591959,.50559002161026,.0757492035627365,0,2,7,6,8,3,-1,7,6,4,3,2,-.000751781277358532,.3783741891384125,.5538573861122131,0,2,5,7,8,2,-1,9,7,4,2,2,-.002495391061529517,.3081651031970978,.5359612107276917,0,2,9,7,3,5,-1,10,7,1,5,3,-.0022385010961443186,.663395881652832,.4649342894554138,0,2,8,7,3,5,-1,9,7,1,5,3,-.0017988430336117744,.6596844792366028,.4347187876701355,0,2,11,1,3,5,-1,12,1,1,5,3,.008786091580986977,.523183286190033,.2315579950809479,0,2,6,2,3,6,-1,7,2,1,6,3,.003671538084745407,.520425021648407,.2977376878261566,0,2,14,14,6,5,-1,14,14,3,5,2,-.0353364497423172,.7238878011703491,.4861505031585693,0,2,9,8,2,2,-1,9,9,2,1,2,-.0006918924045749009,.3105022013187408,.5229824781417847,0,2,10,7,1,3,-1,10,8,1,1,3,-.003394610946998,.3138968050479889,.5210173726081848,0,3,6,6,2,2,-1,6,6,1,1,2,7,7,1,1,2,.0009856928372755647,.4536580145359039,.6585097908973694,0,3,2,11,18,4,-1,11,11,9,2,2,2,13,9,2,2,-.0501631014049053,.1804454028606415,.5198916792869568,0,3,6,6,2,2,-1,6,6,1,1,2,7,7,1,1,2,-.0022367259953171015,.7255702018737793,.4651359021663666,0,2,0,15,20,2,-1,0,16,20,1,2,.0007432628772221506,.4412921071052551,.5898545980453491,0,2,4,14,2,3,-1,4,15,2,1,3,-.0009348518215119839,.3500052988529205,.5366017818450928,0,2,8,14,4,3,-1,8,15,4,1,3,.0174979399889708,.4912194907665253,.8315284848213196,0,2,8,7,2,3,-1,8,8,2,1,3,-.0015200000489130616,.3570275902748108,.537056028842926,0,2,9,10,2,3,-1,9,11,2,1,3,.0007800394087098539,.4353772103786469,.5967335104942322,50.61048126220703,103,0,2,5,4,10,4,-1,5,6,10,2,2,-.00999455526471138,.6162583231925964,.3054533004760742,0,3,9,7,6,4,-1,12,7,3,2,2,9,9,3,2,2,-.001108522992581129,.5818294882774353,.3155578076839447,0,2,4,7,3,6,-1,4,9,3,2,3,.001036438043229282,.2552052140235901,.5692911744117737,0,3,11,15,4,4,-1,13,15,2,2,2,11,17,2,2,2,.000682113110087812,.3685089945793152,.5934931039810181,0,2,7,8,4,2,-1,7,9,4,1,2,-.0006805734010413289,.2332392036914825,.5474792122840881,0,2,13,1,4,3,-1,13,1,2,3,2,.0002606878988444805,.325745701789856,.5667545795440674,0,3,5,15,4,4,-1,5,15,2,2,2,7,17,2,2,2,.0005160737200640142,.3744716942310333,.5845472812652588,0,2,9,5,4,7,-1,9,5,2,7,2,.0008500752155669034,.3420371115207672,.5522807240486145,0,2,5,6,8,3,-1,9,6,4,3,2,-.0018607829697430134,.2804419994354248,.5375424027442932,0,2,9,9,2,2,-1,9,10,2,1,2,-.001503397012129426,.2579050958156586,.5498952269554138,0,2,7,15,5,3,-1,7,16,5,1,3,.0023478909861296415,.4175156056880951,.6313710808753967,0,2,11,10,4,3,-1,11,10,2,3,2,-.00028880240279249847,.5865169763565063,.4052666127681732,0,2,6,9,8,10,-1,6,14,8,5,2,.008940547704696655,.5211141109466553,.231865406036377,0,2,10,11,6,2,-1,10,11,3,2,2,-.0193277392536402,.2753432989120483,.5241525769233704,0,2,4,11,6,2,-1,7,11,3,2,2,-.0002020206011366099,.5722978711128235,.3677195906639099,0,2,11,3,8,1,-1,11,3,4,1,2,.002117906929925084,.4466108083724976,.5542430877685547,0,2,6,3,3,2,-1,7,3,1,2,3,-.0017743760254234076,.2813253104686737,.5300959944725037,0,2,14,5,6,5,-1,14,5,3,5,2,.004223445896059275,.439970999956131,.5795428156852722,0,2,7,5,2,12,-1,7,11,2,6,2,-.0143752200528979,.2981117963790894,.5292059183120728,0,2,8,11,4,3,-1,8,12,4,1,3,-.0153491804376245,.7705215215682983,.4748171865940094,0,2,4,1,2,3,-1,5,1,1,3,2,15152279956964776e-21,.3718844056129456,.5576897263526917,0,2,18,3,2,6,-1,18,5,2,2,3,-.009129391983151436,.3615196049213409,.5286766886711121,0,2,0,3,2,6,-1,0,5,2,2,3,.0022512159775942564,.5364704728126526,.3486298024654388,0,2,9,12,2,3,-1,9,13,2,1,3,-.0049696918576955795,.6927651762962341,.4676836133003235,0,2,7,13,4,3,-1,7,14,4,1,3,-.0128290103748441,.7712153792381287,.4660735130310059,0,2,18,0,2,6,-1,18,2,2,2,3,-.009366006590425968,.3374983966350555,.5351287722587585,0,2,0,0,2,6,-1,0,2,2,2,3,.0032452319283038378,.5325189828872681,.3289610147476196,0,2,8,14,6,3,-1,8,15,6,1,3,-.0117235602810979,.6837652921676636,.4754300117492676,0,2,7,4,2,4,-1,8,4,1,4,2,2925794069597032e-20,.357208788394928,.5360502004623413,0,2,8,5,4,6,-1,8,7,4,2,3,-22244219508138485e-21,.5541427135467529,.3552064001560211,0,2,6,4,2,2,-1,7,4,1,2,2,.005088150966912508,.5070844292640686,.1256462037563324,0,3,3,14,14,4,-1,10,14,7,2,2,3,16,7,2,2,.0274296794086695,.5269560217857361,.1625818014144898,0,3,6,15,6,2,-1,6,15,3,1,2,9,16,3,1,2,-.00641428679227829,.7145588994026184,.4584197103977203,0,2,14,15,6,2,-1,14,16,6,1,2,.003347995923832059,.5398612022399902,.3494696915149689,0,2,2,12,12,8,-1,2,16,12,4,2,-.0826354920864105,.2439192980527878,.5160226225852966,0,2,7,7,7,2,-1,7,8,7,1,2,.0010261740535497665,.3886891901493073,.5767908096313477,0,2,0,2,18,2,-1,0,3,18,1,2,-.0016307090409100056,.3389458060264587,.5347700715065002,0,2,9,6,2,5,-1,9,6,1,5,2,.0024546680506318808,.4601413905620575,.638724684715271,0,2,7,5,3,8,-1,8,5,1,8,3,-.0009947651997208595,.5769879221916199,.4120396077632904,0,2,9,6,3,4,-1,10,6,1,4,3,.0154091902077198,.4878709018230438,.7089822292327881,0,2,4,13,3,2,-1,4,14,3,1,2,.001178440055809915,.5263553261756897,.2895244956016541,0,2,9,4,6,3,-1,11,4,2,3,3,-.0277019198983908,.149882897734642,.5219606757164001,0,2,5,4,6,3,-1,7,4,2,3,3,-.0295053999871016,.024893319234252,.4999816119670868,0,2,14,11,5,2,-1,14,12,5,1,2,.0004515943001024425,.5464622974395752,.4029662907123566,0,2,1,2,6,9,-1,3,2,2,9,3,.007177263963967562,.4271056950092316,.5866296887397766,0,2,14,6,6,13,-1,14,6,3,13,2,-.0741820484399796,.6874179244041443,.4919027984142304,0,3,3,6,14,8,-1,3,6,7,4,2,10,10,7,4,2,-.0172541607171297,.3370676040649414,.534873902797699,0,2,16,0,4,11,-1,16,0,2,11,2,.0148515598848462,.4626792967319489,.6129904985427856,0,3,3,4,12,12,-1,3,4,6,6,2,9,10,6,6,2,.0100020002573729,.5346122980117798,.3423453867435455,0,2,11,4,5,3,-1,11,5,5,1,3,.0020138120744377375,.4643830060958862,.5824304223060608,0,2,4,11,4,2,-1,4,12,4,1,2,.0015135470312088728,.5196396112442017,.2856149971485138,0,2,10,7,2,2,-1,10,7,1,2,2,.003138143103569746,.4838162958621979,.5958529710769653,0,2,8,7,2,2,-1,9,7,1,2,2,-.005145044066011906,.8920302987098694,.4741412103176117,0,2,9,17,3,2,-1,10,17,1,2,3,-.004473670851439238,.2033942937850952,.5337278842926025,0,2,5,6,3,3,-1,5,7,3,1,3,.001962847076356411,.457163393497467,.6725863218307495,0,2,10,0,3,3,-1,11,0,1,3,3,.005426045041531324,.5271108150482178,.2845670878887177,0,3,5,6,6,2,-1,5,6,3,1,2,8,7,3,1,2,.0004961146041750908,.4138312935829163,.5718597769737244,0,2,12,16,4,3,-1,12,17,4,1,3,.009372878819704056,.5225151181221008,.2804847061634064,0,2,3,12,3,2,-1,3,13,3,1,2,.0006050089723430574,.523676872253418,.3314523994922638,0,2,9,12,3,2,-1,9,13,3,1,2,.0005679255118593574,.4531059861183167,.6276971101760864,0,3,1,11,16,4,-1,1,11,8,2,2,9,13,8,2,2,.0246443394571543,.5130851864814758,.2017143964767456,0,2,12,4,3,3,-1,12,5,3,1,3,-.0102904504165053,.7786595225334167,.4876641035079956,0,2,4,4,5,3,-1,4,5,5,1,3,.002062941901385784,.4288598895072937,.5881264209747314,0,2,12,16,4,3,-1,12,17,4,1,3,-.005051948130130768,.3523977994918823,.5286008715629578,0,2,5,4,3,3,-1,5,5,3,1,3,-.0057692620903253555,.6841086149215698,.4588094055652618,0,2,9,0,2,2,-1,9,1,2,1,2,-.0004578994121402502,.356552004814148,.5485978126525879,0,2,8,9,4,2,-1,8,10,4,1,2,-.0007591883768327534,.336879312992096,.5254197120666504,0,2,8,8,4,3,-1,8,9,4,1,3,-.001773725962266326,.3422161042690277,.5454015135765076,0,2,0,13,6,3,-1,2,13,2,3,3,-.008561046794056892,.6533612012863159,.4485856890678406,0,2,16,14,3,2,-1,16,15,3,1,2,.0017277270089834929,.5307580232620239,.3925352990627289,0,2,1,18,18,2,-1,7,18,6,2,3,-.0281996093690395,.685745894908905,.4588584005832672,0,2,16,14,3,2,-1,16,15,3,1,2,-.001778110978193581,.4037851095199585,.5369856953620911,0,2,1,14,3,2,-1,1,15,3,1,2,.00033177141449414194,.539979875087738,.3705750107765198,0,2,7,14,6,3,-1,7,15,6,1,3,.0026385399978607893,.4665437042713165,.6452730894088745,0,2,5,14,8,3,-1,5,15,8,1,3,-.0021183069329708815,.5914781093597412,.4064677059650421,0,2,10,6,4,14,-1,10,6,2,14,2,-.0147732896730304,.3642038106918335,.5294762849807739,0,2,6,6,4,14,-1,8,6,2,14,2,-.0168154407292604,.2664231956005096,.5144972801208496,0,2,13,5,2,3,-1,13,6,2,1,3,-.006337014026939869,.6779531240463257,.4852097928524017,0,2,7,16,6,1,-1,9,16,2,1,3,-44560048991115764e-21,.5613964796066284,.4153054058551788,0,2,9,12,3,3,-1,9,13,3,1,3,-.0010240620467811823,.5964478254318237,.4566304087638855,0,2,7,0,3,3,-1,8,0,1,3,3,-.00231616897508502,.2976115047931671,.5188159942626953,0,2,4,0,16,18,-1,4,9,16,9,2,.5321757197380066,.5187839269638062,.220263198018074,0,2,1,1,16,14,-1,1,8,16,7,2,-.1664305031299591,.1866022944450378,.5060343146324158,0,2,3,9,15,4,-1,8,9,5,4,3,.112535297870636,.5212125182151794,.1185022965073586,0,2,6,12,7,3,-1,6,13,7,1,3,.009304686449468136,.4589937031269074,.6826149225234985,0,2,14,15,2,3,-1,14,16,2,1,3,-.004625509958714247,.3079940974712372,.5225008726119995,0,3,2,3,16,14,-1,2,3,8,7,2,10,10,8,7,2,-.1111646965146065,.2101044058799744,.5080801844596863,0,3,16,2,4,18,-1,18,2,2,9,2,16,11,2,9,2,-.0108884396031499,.5765355229377747,.4790464043617249,0,2,4,15,2,3,-1,4,16,2,1,3,.005856430158019066,.5065100193023682,.1563598960638046,0,3,16,2,4,18,-1,18,2,2,9,2,16,11,2,9,2,.0548543892800808,.49669149518013,.7230510711669922,0,2,1,1,8,3,-1,1,2,8,1,3,-.0111973397433758,.2194979041814804,.5098798274993896,0,2,8,11,4,3,-1,8,12,4,1,3,.004406907130032778,.4778401851654053,.6770902872085571,0,2,5,11,5,9,-1,5,14,5,3,3,-.0636652931571007,.1936362981796265,.5081024169921875,0,2,16,0,4,11,-1,16,0,2,11,2,-.009808149188756943,.599906325340271,.4810341000556946,0,2,7,0,6,1,-1,9,0,2,1,3,-.0021717099007219076,.3338333964347839,.5235472917556763,0,2,16,3,3,7,-1,17,3,1,7,3,-.0133155202493072,.6617069840431213,.4919213056564331,0,2,1,3,3,7,-1,2,3,1,7,3,.002544207964092493,.4488744139671326,.6082184910774231,0,2,7,8,6,12,-1,7,12,6,4,3,.0120378397405148,.540939211845398,.3292432129383087,0,2,0,0,4,11,-1,2,0,2,11,2,-.0207010507583618,.6819120049476624,.4594995975494385,0,2,14,0,6,20,-1,14,0,3,20,2,.0276082791388035,.4630792140960693,.5767282843589783,0,2,0,3,1,2,-1,0,4,1,1,2,.0012370620388537645,.5165379047393799,.2635016143321991,0,3,5,5,10,8,-1,10,5,5,4,2,5,9,5,4,2,-.037669338285923,.2536393105983734,.5278980135917664,0,3,4,7,12,4,-1,4,7,6,2,2,10,9,6,2,2,-.0018057259730994701,.3985156118869782,.5517500042915344,54.62007141113281,111,0,2,2,1,6,4,-1,5,1,3,4,2,.004429902881383896,.2891018092632294,.633522629737854,0,3,9,7,6,4,-1,12,7,3,2,2,9,9,3,2,2,-.0023813319858163595,.621178925037384,.3477487862110138,0,2,5,6,2,6,-1,5,9,2,3,2,.0022915711160749197,.2254412025213242,.5582118034362793,0,3,9,16,6,4,-1,12,16,3,2,2,9,18,3,2,2,.0009945794008672237,.3711710870265961,.5930070877075195,0,2,9,4,2,12,-1,9,10,2,6,2,.0007716466789133847,.565172016620636,.334799587726593,0,2,7,1,6,18,-1,9,1,2,18,3,-.001138641033321619,.3069126009941101,.5508630871772766,0,2,4,12,12,2,-1,8,12,4,2,3,-.0001640303962631151,.576282799243927,.3699047863483429,0,2,8,8,6,2,-1,8,9,6,1,2,29793529392918572e-21,.2644244134426117,.5437911152839661,0,2,8,0,3,6,-1,9,0,1,6,3,.008577490225434303,.5051138997077942,.1795724928379059,0,2,11,18,3,2,-1,11,19,3,1,2,-.0002603268949314952,.5826969146728516,.4446826875209808,0,2,1,1,17,4,-1,1,3,17,2,2,-.006140463054180145,.3113852143287659,.5346971750259399,0,2,11,8,4,12,-1,11,8,2,12,2,-.0230869501829147,.32779461145401,.533119797706604,0,2,8,14,4,3,-1,8,15,4,1,3,-.0142436502501369,.7381709814071655,.4588063061237335,0,2,12,3,2,17,-1,12,3,1,17,2,.0194871295243502,.5256630778312683,.2274471968412399,0,2,4,7,6,1,-1,6,7,2,1,3,-.0009668110869824886,.5511230826377869,.3815006911754608,0,2,18,3,2,3,-1,18,4,2,1,3,.003147470997646451,.5425636768341064,.2543726861476898,0,2,8,4,3,4,-1,8,6,3,2,2,-.00018026070029009134,.5380191802978516,.3406304121017456,0,2,4,5,12,10,-1,4,10,12,5,2,-.006026626098901033,.3035801947116852,.54205721616745,0,2,5,18,4,2,-1,7,18,2,2,2,.00044462960795499384,.3990997076034546,.5660110116004944,0,2,17,2,3,6,-1,17,4,3,2,3,.002260976005345583,.5562806725502014,.3940688073635101,0,2,7,7,6,6,-1,9,7,2,6,3,.0511330589652061,.4609653949737549,.7118561863899231,0,2,17,2,3,6,-1,17,4,3,2,3,-.0177863091230392,.2316166013479233,.5322144031524658,0,2,8,0,3,4,-1,9,0,1,4,3,-.004967962857335806,.233077198266983,.5122029185295105,0,2,9,14,2,3,-1,9,15,2,1,3,.002066768938675523,.4657444059848785,.6455488204956055,0,2,0,12,6,3,-1,0,13,6,1,3,.007441376801580191,.5154392123222351,.236163392663002,0,2,8,14,4,3,-1,8,15,4,1,3,-.003627727972343564,.6219773292541504,.4476661086082459,0,2,3,12,2,3,-1,3,13,2,1,3,-.005353075917810202,.1837355047464371,.5102208256721497,0,2,5,6,12,7,-1,9,6,4,7,3,.1453091949224472,.5145987272262573,.1535930931568146,0,2,0,2,3,6,-1,0,4,3,2,3,.0024394490756094456,.5343660116195679,.3624661862850189,0,2,14,6,1,3,-1,14,7,1,1,3,-.003128339070826769,.6215007901191711,.4845592081546783,0,2,2,0,3,14,-1,3,0,1,14,3,.0017940260004252195,.4299261868000031,.5824198126792908,0,2,12,14,5,6,-1,12,16,5,2,3,.0362538211047649,.5260334014892578,.1439467966556549,0,2,4,14,5,6,-1,4,16,5,2,3,-.005174672231078148,.350653886795044,.5287045240402222,0,3,11,10,2,2,-1,12,10,1,1,2,11,11,1,1,2,.0006538329762406647,.4809640944004059,.6122040152549744,0,2,5,0,3,14,-1,6,0,1,14,3,-.0264802295714617,.1139362007379532,.5045586228370667,0,2,10,15,2,3,-1,10,16,2,1,3,-.0030440660193562508,.6352095007896423,.4794734120368958,0,2,0,2,2,3,-1,0,3,2,1,3,.0036993520334362984,.5131118297576904,.2498510926961899,0,2,5,11,12,6,-1,5,14,12,3,2,-.0003676293126773089,.54213947057724,.3709532022476196,0,2,6,11,3,9,-1,6,14,3,3,3,-.041382260620594,.1894959956407547,.5081691741943359,0,3,11,10,2,2,-1,12,10,1,1,2,11,11,1,1,2,-.0010532729793339968,.645436704158783,.4783608913421631,0,2,5,6,1,3,-1,5,7,1,1,3,-.0021648600231856108,.6215031147003174,.449982613325119,0,2,4,9,13,3,-1,4,10,13,1,3,-.0005674774874933064,.3712610900402069,.5419334769248962,0,2,1,7,15,6,-1,6,7,5,6,3,.173758402466774,.5023643970489502,.1215742006897926,0,2,4,5,12,6,-1,8,5,4,6,3,-.0029049699660390615,.3240267932415009,.5381883978843689,0,2,8,10,4,3,-1,8,11,4,1,3,.0012299539521336555,.4165507853031158,.5703486204147339,0,2,15,14,1,3,-1,15,15,1,1,3,-.0005432923790067434,.3854042887687683,.554754912853241,0,2,1,11,5,3,-1,1,12,5,1,3,-.008329725824296474,.2204494029283524,.5097082853317261,0,2,7,1,7,12,-1,7,7,7,6,2,-.00010417630255687982,.560706615447998,.4303036034107208,0,3,0,1,6,10,-1,0,1,3,5,2,3,6,3,5,2,.0312047004699707,.4621657133102417,.6982004046440125,0,2,16,1,4,3,-1,16,2,4,1,3,.007894350215792656,.5269594192504883,.226906806230545,0,2,5,5,2,3,-1,5,6,2,1,3,-.004364531021565199,.6359223127365112,.4537956118583679,0,2,12,2,3,5,-1,13,2,1,5,3,.007679305970668793,.5274767875671387,.274048388004303,0,2,0,3,4,6,-1,0,5,4,2,3,-.0254311393946409,.2038519978523254,.5071732997894287,0,2,8,12,4,2,-1,8,13,4,1,2,.0008200060110539198,.4587455093860626,.6119868159294128,0,2,8,18,3,1,-1,9,18,1,1,3,.002928460016846657,.5071274042129517,.2028204947710037,0,3,11,10,2,2,-1,12,10,1,1,2,11,11,1,1,2,4525647091213614e-20,.4812104105949402,.5430821776390076,0,3,7,10,2,2,-1,7,10,1,1,2,8,11,1,1,2,.0013158309739083052,.4625813961029053,.6779323220252991,0,2,11,11,4,4,-1,11,13,4,2,2,.0015870389761403203,.5386291742324829,.3431465029716492,0,2,8,12,3,8,-1,9,12,1,8,3,-.0215396601706743,.025942500680685,.5003222823143005,0,2,13,0,6,3,-1,13,1,6,1,3,.014334480278194,.5202844738960266,.1590632945299149,0,2,8,8,3,4,-1,9,8,1,4,3,-.008388138376176357,.728248119354248,.4648044109344482,0,3,5,7,10,10,-1,10,7,5,5,2,5,12,5,5,2,.00919068418443203,.556235671043396,.3923191130161285,0,3,3,18,8,2,-1,3,18,4,1,2,7,19,4,1,2,-.005845305975526571,.6803392767906189,.4629127979278565,0,2,10,2,6,8,-1,12,2,2,8,3,-.0547077991068363,.2561671137809753,.5206125974655151,0,2,4,2,6,8,-1,6,2,2,8,3,.009114277549088001,.518962025642395,.3053877055644989,0,2,11,0,3,7,-1,12,0,1,7,3,-.0155750000849366,.1295074969530106,.5169094800949097,0,2,7,11,2,1,-1,8,11,1,1,2,-.0001205060034408234,.5735098123550415,.4230825006961823,0,2,15,14,1,3,-1,15,15,1,1,3,.0012273970060050488,.5289878249168396,.4079791903495789,0,3,7,15,2,2,-1,7,15,1,1,2,8,16,1,1,2,-.0012186600361019373,.6575639843940735,.4574409127235413,0,2,15,14,1,3,-1,15,15,1,1,3,-.0033256649039685726,.3628047108650208,.5195019841194153,0,2,6,0,3,7,-1,7,0,1,7,3,-.0132883097976446,.1284265965223312,.504348874092102,0,2,18,1,2,7,-1,18,1,1,7,2,-.0033839771058410406,.6292240023612976,.475750595331192,0,2,2,0,8,20,-1,2,10,8,10,2,-.2195422053337097,.148773193359375,.5065013766288757,0,2,3,0,15,6,-1,3,2,15,2,3,.004911170806735754,.425610214471817,.5665838718414307,0,2,4,3,12,2,-1,4,4,12,1,2,-.00018744950648397207,.4004144072532654,.5586857199668884,0,2,16,0,4,5,-1,16,0,2,5,2,-.00521786417812109,.6009116172790527,.4812706112861633,0,2,7,0,3,4,-1,8,0,1,4,3,-.0011111519997939467,.3514933884143829,.5287089943885803,0,2,16,0,4,5,-1,16,0,2,5,2,.004403640050441027,.4642275869846344,.5924085974693298,0,2,1,7,6,13,-1,3,7,2,13,3,.1229949966073036,.5025529265403748,.0691524818539619,0,2,16,0,4,5,-1,16,0,2,5,2,-.0123135102912784,.5884591937065125,.4934012889862061,0,2,0,0,4,5,-1,2,0,2,5,2,.004147103987634182,.4372239112854004,.589347779750824,0,2,14,12,3,6,-1,14,14,3,2,3,-.003550264984369278,.4327551126480103,.5396270155906677,0,2,3,12,3,6,-1,3,14,3,2,3,-.0192242693156004,.1913134008646011,.5068330764770508,0,2,16,1,4,3,-1,16,2,4,1,3,.0014395059552043676,.5308178067207336,.424353301525116,0,3,8,7,2,10,-1,8,7,1,5,2,9,12,1,5,2,-.00677519990131259,.6365395784378052,.4540086090564728,0,2,11,11,4,4,-1,11,13,4,2,2,.007011963054537773,.5189834237098694,.302619993686676,0,2,0,1,4,3,-1,0,2,4,1,3,.005401465110480785,.5105062127113342,.2557682991027832,0,2,13,4,1,3,-1,13,5,1,1,3,.0009027498890645802,.4696914851665497,.5861827731132507,0,2,7,15,3,5,-1,8,15,1,5,3,.0114744501188397,.5053645968437195,.152717798948288,0,2,9,7,3,5,-1,10,7,1,5,3,-.006702343001961708,.6508980989456177,.4890604019165039,0,2,8,7,3,5,-1,9,7,1,5,3,-.0020462959073483944,.6241816878318787,.4514600038528442,0,2,10,6,4,14,-1,10,6,2,14,2,-.009995156899094582,.3432781100273132,.5400953888893127,0,2,0,5,5,6,-1,0,7,5,2,3,-.0357007086277008,.1878059059381485,.5074077844619751,0,2,9,5,6,4,-1,9,5,3,4,2,.0004558456130325794,.3805277049541473,.5402569770812988,0,2,0,0,18,10,-1,6,0,6,10,3,-.0542606003582478,.6843714714050293,.4595097005367279,0,2,10,6,4,14,-1,10,6,2,14,2,.0060600461438298225,.5502905249595642,.450052797794342,0,2,6,6,4,14,-1,8,6,2,14,2,-.006479183211922646,.3368858098983765,.5310757160186768,0,2,13,4,1,3,-1,13,5,1,1,3,-.0014939469983801246,.6487640142440796,.4756175875663757,0,2,5,1,2,3,-1,6,1,1,3,2,14610530342906713e-21,.403457909822464,.5451064109802246,0,3,18,1,2,18,-1,19,1,1,9,2,18,10,1,9,2,-.00723219383507967,.6386873722076416,.4824739992618561,0,2,2,1,4,3,-1,2,2,4,1,3,-.004064581822603941,.2986421883106232,.5157335996627808,0,3,18,1,2,18,-1,19,1,1,9,2,18,10,1,9,2,.0304630808532238,.5022199749946594,.7159956097602844,0,3,1,14,4,6,-1,1,14,2,3,2,3,17,2,3,2,-.008054491132497787,.6492452025413513,.4619275033473969,0,2,10,11,7,6,-1,10,13,7,2,3,.0395051389932632,.5150570869445801,.2450613975524902,0,3,0,10,6,10,-1,0,10,3,5,2,3,15,3,5,2,.008453020825982094,.4573669135570526,.6394037008285522,0,2,11,0,3,4,-1,12,0,1,4,3,-.0011688120430335402,.3865512013435364,.548366129398346,0,2,5,10,5,6,-1,5,13,5,3,2,.002807067008689046,.5128579139709473,.2701480090618134,0,2,14,6,1,8,-1,14,10,1,4,2,.000473652093205601,.4051581919193268,.5387461185455322,0,3,1,7,18,6,-1,1,7,9,3,2,10,10,9,3,2,.0117410803213716,.5295950174331665,.3719413876533508,0,2,9,7,2,2,-1,9,7,1,2,2,.0031833238899707794,.4789406955242157,.6895126104354858,0,2,5,9,4,5,-1,7,9,2,5,2,.0007024150108918548,.5384489297866821,.3918080925941467,50.16973114013672,102,0,2,7,6,6,3,-1,9,6,2,3,3,.0170599296689034,.3948527872562408,.7142534852027893,0,2,1,0,18,4,-1,7,0,6,4,3,.0218408405780792,.3370316028594971,.6090016961097717,0,2,7,15,2,4,-1,7,17,2,2,2,.00024520049919374287,.3500576019287109,.5987902283668518,0,2,1,0,19,9,-1,1,3,19,3,3,.008327260613441467,.3267528116703033,.5697240829467773,0,2,3,7,3,6,-1,3,9,3,2,3,.0005714829894714057,.3044599890708923,.5531656742095947,0,3,13,7,4,4,-1,15,7,2,2,2,13,9,2,2,2,.0006737398798577487,.3650012016296387,.567263126373291,0,3,3,7,4,4,-1,3,7,2,2,2,5,9,2,2,2,3468159047770314e-20,.3313541114330292,.5388727188110352,0,2,9,6,10,8,-1,9,10,10,4,2,-.005856339819729328,.2697942852973938,.5498778820037842,0,2,3,8,14,12,-1,3,14,14,6,2,.00851022731512785,.5269358158111572,.2762879133224487,0,3,6,5,10,12,-1,11,5,5,6,2,6,11,5,6,2,-.0698172077536583,.2909603118896484,.5259246826171875,0,2,9,11,2,3,-1,9,12,2,1,3,-.0008611367084085941,.5892577171325684,.4073697924613953,0,2,9,5,6,5,-1,9,5,3,5,2,.0009714924963191152,.3523564040660858,.5415862202644348,0,2,9,4,2,4,-1,9,6,2,2,2,-1472749045206001e-20,.5423017740249634,.3503156006336212,0,2,9,5,6,5,-1,9,5,3,5,2,.0484202913939953,.51939457654953,.3411195874214172,0,2,5,5,6,5,-1,8,5,3,5,2,.0013257140526548028,.315776914358139,.5335376262664795,0,2,11,2,6,1,-1,13,2,2,1,3,1492214960308047e-20,.4451299905776978,.5536553859710693,0,2,3,2,6,1,-1,5,2,2,1,3,-.002717339899390936,.3031741976737976,.5248088836669922,0,2,13,5,2,3,-1,13,6,2,1,3,.0029219500720500946,.4781453013420105,.6606041789054871,0,2,0,10,1,4,-1,0,12,1,2,2,-.0019804988987743855,.3186308145523071,.5287625193595886,0,2,13,5,2,3,-1,13,6,2,1,3,-.004001210909336805,.6413596868515015,.4749928116798401,0,2,8,18,3,2,-1,9,18,1,2,3,-.004349199123680592,.1507498025894165,.5098996758460999,0,2,6,15,9,2,-1,6,16,9,1,2,.0013490889687091112,.4316158890724182,.5881167054176331,0,2,8,14,4,3,-1,8,15,4,1,3,.0185970701277256,.4735553860664368,.9089794158935547,0,2,18,4,2,4,-1,18,6,2,2,2,-.001856237999163568,.3553189039230347,.5577837228775024,0,2,5,5,2,3,-1,5,6,2,1,3,.002294043079018593,.4500094950199127,.6580877900123596,0,2,15,16,3,2,-1,15,17,3,1,2,.00029982850537635386,.5629242062568665,.3975878953933716,0,2,0,0,3,9,-1,0,3,3,3,3,.0035455459728837013,.5381547212600708,.3605485856533051,0,2,9,7,3,3,-1,9,8,3,1,3,.009610472247004509,.5255997180938721,.1796745955944061,0,2,8,7,3,3,-1,8,8,3,1,3,-.0062783220782876015,.227285698056221,.5114030241966248,0,2,9,5,2,6,-1,9,5,1,6,2,.0034598479978740215,.4626308083534241,.6608219146728516,0,2,8,6,3,4,-1,9,6,1,4,3,-.0013112019514665008,.6317539811134338,.4436857998371124,0,3,7,6,8,12,-1,11,6,4,6,2,7,12,4,6,2,.002687617903575301,.5421109795570374,.4054022133350372,0,3,5,6,8,12,-1,5,6,4,6,2,9,12,4,6,2,.003911816980689764,.5358477830886841,.3273454904556274,0,2,12,4,3,3,-1,12,5,3,1,3,-.014206450432539,.7793576717376709,.4975781142711639,0,2,2,16,3,2,-1,2,17,3,1,2,.0007170552853494883,.5297319889068604,.3560903966426849,0,2,12,4,3,3,-1,12,5,3,1,3,.001663501956500113,.467809408903122,.5816481709480286,0,2,2,12,6,6,-1,2,14,6,2,3,.0033686188980937004,.5276734232902527,.3446420133113861,0,2,7,13,6,3,-1,7,14,6,1,3,.0127995302900672,.4834679961204529,.7472159266471863,0,2,6,14,6,3,-1,6,15,6,1,3,.0033901201095432043,.4511859118938446,.6401721239089966,0,2,14,15,5,3,-1,14,16,5,1,3,.004707077983766794,.533565878868103,.355522096157074,0,2,5,4,3,3,-1,5,5,3,1,3,.0014819339849054813,.4250707030296326,.5772724151611328,0,2,14,15,5,3,-1,14,16,5,1,3,-.0069995759986341,.3003320097923279,.5292900204658508,0,2,5,3,6,2,-1,7,3,2,2,3,.0159390103071928,.5067319273948669,.1675581932067871,0,2,8,15,4,3,-1,8,16,4,1,3,.007637734990566969,.4795069992542267,.7085601091384888,0,2,1,15,5,3,-1,1,16,5,1,3,.006733404006808996,.5133113265037537,.2162470072507858,0,3,8,13,4,6,-1,10,13,2,3,2,8,16,2,3,2,-.012858809903264,.1938841938972473,.525137186050415,0,2,7,8,3,3,-1,8,8,1,3,3,-.0006227080011740327,.5686538219451904,.419786810874939,0,2,12,0,5,4,-1,12,2,5,2,2,-.0005265168147161603,.4224168956279755,.5429695844650269,0,3,0,2,20,2,-1,0,2,10,1,2,10,3,10,1,2,.0110750999301672,.5113775134086609,.2514517903327942,0,2,1,0,18,4,-1,7,0,6,4,3,-.0367282517254353,.7194662094116211,.4849618971347809,0,2,4,3,6,1,-1,6,3,2,1,3,-.00028207109426148236,.3840261995792389,.539444625377655,0,2,4,18,13,2,-1,4,19,13,1,2,-.0027489690110087395,.593708872795105,.4569182097911835,0,2,2,10,3,6,-1,2,12,3,2,3,.0100475195795298,.5138576030731201,.2802298069000244,0,3,14,12,6,8,-1,17,12,3,4,2,14,16,3,4,2,-.008149784058332443,.6090037226676941,.4636121094226837,0,3,4,13,10,6,-1,4,13,5,3,2,9,16,5,3,2,-.006883388850837946,.3458611071109772,.5254660248756409,0,2,14,12,1,2,-1,14,13,1,1,2,-140393603942357e-19,.5693104267120361,.4082083106040955,0,2,8,13,4,3,-1,8,14,4,1,3,.001549841952510178,.4350537061691284,.5806517004966736,0,2,14,12,2,2,-1,14,13,2,1,2,-.006784149911254644,.1468873023986816,.5182775259017944,0,2,4,12,2,2,-1,4,13,2,1,2,.00021705629478674382,.5293524265289307,.345617413520813,0,2,8,12,9,2,-1,8,13,9,1,2,.00031198898795992136,.4652450978755951,.5942413806915283,0,2,9,14,2,3,-1,9,15,2,1,3,.005450753029435873,.4653508961200714,.7024846076965332,0,2,11,10,3,6,-1,11,13,3,3,2,-.00025818689027801156,.5497295260429382,.3768967092037201,0,2,5,6,9,12,-1,5,12,9,6,2,-.0174425393342972,.3919087946414948,.5457497835159302,0,2,11,10,3,6,-1,11,13,3,3,2,-.045343529433012,.1631357073783875,.5154908895492554,0,2,6,10,3,6,-1,6,13,3,3,2,.0019190689781680703,.514589786529541,.2791895866394043,0,2,5,4,11,3,-1,5,5,11,1,3,-.006017786916345358,.6517636179924011,.4756332933902741,0,2,7,1,5,10,-1,7,6,5,5,2,-.004072073847055435,.5514652729034424,.4092685878276825,0,2,2,8,18,2,-1,2,9,18,1,2,.00039855059003457427,.316524088382721,.5285550951957703,0,2,7,17,5,3,-1,7,18,5,1,3,-.0065418570302426815,.6853377819061279,.4652808904647827,0,2,5,9,12,1,-1,9,9,4,1,3,.003484508953988552,.5484588146209717,.4502759873867035,0,3,0,14,6,6,-1,0,14,3,3,2,3,17,3,3,2,-.0136967804282904,.6395779848098755,.4572555124759674,0,2,5,9,12,1,-1,9,9,4,1,3,-.017347140237689,.2751072943210602,.5181614756584167,0,2,3,9,12,1,-1,7,9,4,1,3,-.004088542889803648,.3325636088848114,.5194984078407288,0,2,14,10,6,7,-1,14,10,3,7,2,-.009468790143728256,.5942280888557434,.485181987285614,0,2,1,0,16,2,-1,1,1,16,1,2,.0017084840219467878,.4167110919952393,.5519806146621704,0,2,10,9,10,9,-1,10,12,10,3,3,.009480909444391727,.5433894991874695,.4208514988422394,0,2,0,1,10,2,-1,5,1,5,2,2,-.004738965071737766,.6407189965248108,.4560655057430267,0,2,17,3,2,3,-1,17,4,2,1,3,.006576105020940304,.5214555263519287,.2258227020502091,0,2,1,3,2,3,-1,1,4,2,1,3,-.0021690549328923225,.3151527941226959,.5156704783439636,0,2,9,7,3,6,-1,10,7,1,6,3,.014660170301795,.4870837032794952,.668994128704071,0,2,6,5,4,3,-1,8,5,2,3,2,.00017231999663636088,.3569748997688294,.5251078009605408,0,2,7,5,6,6,-1,9,5,2,6,3,-.0218037609010935,.8825920820236206,.496632993221283,0,3,3,4,12,12,-1,3,4,6,6,2,9,10,6,6,2,-.0947361066937447,.1446162015199661,.5061113834381104,0,2,9,2,6,15,-1,11,2,2,15,3,.0055825551971793175,.5396478772163391,.4238066077232361,0,2,2,2,6,17,-1,4,2,2,17,3,.001951709040440619,.4170410931110382,.5497786998748779,0,2,14,10,6,7,-1,14,10,3,7,2,.0121499001979828,.4698367118835449,.5664274096488953,0,2,0,10,6,7,-1,3,10,3,7,2,-.007516962010413408,.6267772912979126,.4463135898113251,0,2,9,2,6,15,-1,11,2,2,15,3,-.0716679096221924,.3097011148929596,.5221003293991089,0,2,5,2,6,15,-1,7,2,2,15,3,-.0882924199104309,.0811238884925842,.5006365180015564,0,2,17,9,3,6,-1,17,11,3,2,3,.0310630798339844,.5155503749847412,.1282255947589874,0,2,6,7,6,6,-1,8,7,2,6,3,.0466218404471874,.4699777960777283,.736396074295044,0,3,1,10,18,6,-1,10,10,9,3,2,1,13,9,3,2,-.0121894897893071,.3920530080795288,.5518996715545654,0,2,0,9,10,9,-1,0,12,10,3,3,.0130161102861166,.5260658264160156,.3685136139392853,0,2,8,15,4,3,-1,8,16,4,1,3,-.003495289944112301,.6339294910430908,.4716280996799469,0,2,5,12,3,4,-1,5,14,3,2,2,-4401503974804655e-20,.5333027243614197,.3776184916496277,0,2,3,3,16,12,-1,3,9,16,6,2,-.1096649020910263,.1765342056751251,.5198346972465515,0,3,1,1,12,12,-1,1,1,6,6,2,7,7,6,6,2,-.0009027955820783973,.5324159860610962,.3838908076286316,0,3,10,4,2,4,-1,11,4,1,2,2,10,6,1,2,2,.0007112664170563221,.4647929966449738,.5755224227905273,0,3,0,9,10,2,-1,0,9,5,1,2,5,10,5,1,2,-.003125027986243367,.323670893907547,.5166770815849304,0,2,9,11,3,3,-1,9,12,3,1,3,.002414467977359891,.4787439107894898,.6459717750549316,0,2,3,12,9,2,-1,3,13,9,1,2,.00044391240226104856,.4409308135509491,.6010255813598633,0,2,9,9,2,2,-1,9,10,2,1,2,-.0002261118934256956,.4038113951683044,.5493255853652954,66.66912078857422,135,0,2,3,4,13,6,-1,3,6,13,2,3,-.0469012893736362,.660017192363739,.3743801116943359,0,3,9,7,6,4,-1,12,7,3,2,2,9,9,3,2,2,-.001456834957934916,.578399121761322,.3437797129154205,0,2,1,0,6,8,-1,4,0,3,8,2,.005559836979955435,.3622266948223114,.5908216238021851,0,2,9,5,2,12,-1,9,11,2,6,2,.0007317048730328679,.550041913986206,.2873558104038239,0,2,4,4,3,10,-1,4,9,3,5,2,.001331800944171846,.267316997051239,.5431019067764282,0,2,6,17,8,3,-1,6,18,8,1,3,.00024347059661522508,.3855027854442596,.574138879776001,0,2,0,5,10,6,-1,0,7,10,2,3,-.0030512469820678234,.5503209829330444,.3462845087051392,0,2,13,2,3,2,-1,13,3,3,1,2,-.0006865719915367663,.3291221857070923,.5429509282112122,0,2,7,5,4,5,-1,9,5,2,5,2,.001466820016503334,.3588382005691528,.5351811051368713,0,2,12,14,3,6,-1,12,16,3,2,3,.0003202187072020024,.429684191942215,.5700234174728394,0,2,1,11,8,2,-1,1,12,8,1,2,.0007412218837998807,.5282164812088013,.3366870880126953,0,2,7,13,6,3,-1,7,14,6,1,3,.0038330298848450184,.4559567868709564,.6257336139678955,0,2,0,5,3,6,-1,0,7,3,2,3,-.0154564399272203,.2350116968154907,.512945294380188,0,2,13,2,3,2,-1,13,3,3,1,2,.002679677912965417,.5329415202140808,.4155062139034271,0,3,4,14,4,6,-1,4,14,2,3,2,6,17,2,3,2,.0028296569362282753,.4273087978363037,.5804538130760193,0,2,13,2,3,2,-1,13,3,3,1,2,-.0039444249123334885,.2912611961364746,.5202686190605164,0,2,8,2,4,12,-1,8,6,4,4,3,.002717955969274044,.5307688117027283,.3585677146911621,0,3,14,0,6,8,-1,17,0,3,4,2,14,4,3,4,2,.005907762795686722,.470377504825592,.5941585898399353,0,2,7,17,3,2,-1,8,17,1,2,3,-.004224034957587719,.2141567021608353,.5088796019554138,0,2,8,12,4,2,-1,8,13,4,1,2,.0040725888684391975,.4766413867473602,.6841061115264893,0,3,6,0,8,12,-1,6,0,4,6,2,10,6,4,6,2,.0101495301350951,.5360798835754395,.3748497068881989,0,3,14,0,2,10,-1,15,0,1,5,2,14,5,1,5,2,-.00018864999583456665,.5720130205154419,.3853805065155029,0,3,5,3,8,6,-1,5,3,4,3,2,9,6,4,3,2,-.0048864358104765415,.3693122863769531,.5340958833694458,0,3,14,0,6,10,-1,17,0,3,5,2,14,5,3,5,2,.0261584799736738,.4962374866008759,.6059989929199219,0,2,9,14,1,2,-1,9,15,1,1,2,.0004856075975112617,.4438945949077606,.6012468934059143,0,2,15,10,4,3,-1,15,11,4,1,3,.0112687097862363,.5244250297546387,.1840388029813767,0,2,8,14,2,3,-1,8,15,2,1,3,-.0028114619199186563,.6060283780097961,.4409897029399872,0,3,3,13,14,4,-1,10,13,7,2,2,3,15,7,2,2,-.005611272994428873,.3891170918941498,.5589237213134766,0,2,1,10,4,3,-1,1,11,4,1,3,.008568009361624718,.5069345831871033,.2062619030475617,0,2,9,11,6,1,-1,11,11,2,1,3,-.00038172779022715986,.5882201790809631,.41926109790802,0,2,5,11,6,1,-1,7,11,2,1,3,-.00017680290329735726,.5533605813980103,.400336891412735,0,2,3,5,16,15,-1,3,10,16,5,3,.006511253770440817,.3310146927833557,.5444191098213196,0,2,6,12,4,2,-1,8,12,2,2,2,-6594868318643421e-20,.5433831810951233,.3944905996322632,0,3,4,4,12,10,-1,10,4,6,5,2,4,9,6,5,2,.006993905175477266,.5600358247756958,.4192714095115662,0,2,8,6,3,4,-1,9,6,1,4,3,-.0046744439750909805,.6685466766357422,.4604960978031158,0,3,8,12,4,8,-1,10,12,2,4,2,8,16,2,4,2,.0115898502990603,.5357121229171753,.2926830053329468,0,2,8,14,4,3,-1,8,15,4,1,3,.013007840141654,.4679817855358124,.730746328830719,0,2,12,2,3,2,-1,13,2,1,2,3,-.0011008579749614,.3937501013278961,.5415065288543701,0,2,8,15,3,2,-1,8,16,3,1,2,.0006047264905646443,.4242376089096069,.5604041218757629,0,2,6,0,9,14,-1,9,0,3,14,3,-.0144948400557041,.3631210029125214,.5293182730674744,0,2,9,6,2,3,-1,10,6,1,3,2,-.005305694881826639,.686045229434967,.4621821045875549,0,2,10,8,2,3,-1,10,9,2,1,3,-.00081829127157107,.3944096863269806,.542043924331665,0,2,0,9,4,6,-1,0,11,4,2,3,-.0190775208175182,.1962621957063675,.5037891864776611,0,2,6,0,8,2,-1,6,1,8,1,2,.00035549470339901745,.4086259007453919,.5613973140716553,0,2,6,14,7,3,-1,6,15,7,1,3,.0019679730758070946,.448912113904953,.5926123261451721,0,2,8,10,8,9,-1,8,13,8,3,3,.006918914150446653,.5335925817489624,.3728385865688324,0,2,5,2,3,2,-1,6,2,1,2,3,.002987277926877141,.5111321210861206,.2975643873214722,0,3,14,1,6,8,-1,17,1,3,4,2,14,5,3,4,2,-.006226461846381426,.5541489720344543,.4824537932872772,0,3,0,1,6,8,-1,0,1,3,4,2,3,5,3,4,2,.013353300280869,.4586423933506012,.6414797902107239,0,3,1,2,18,6,-1,10,2,9,3,2,1,5,9,3,2,.0335052385926247,.5392425060272217,.3429994881153107,0,2,9,3,2,1,-1,10,3,1,1,2,-.0025294460356235504,.1703713983297348,.5013315081596375,0,3,13,2,4,6,-1,15,2,2,3,2,13,5,2,3,2,-.001280162949115038,.5305461883544922,.4697405099868774,0,2,5,4,3,3,-1,5,5,3,1,3,.007068738806992769,.4615545868873596,.643650472164154,0,2,13,5,1,3,-1,13,6,1,1,3,.0009688049904070795,.4833599030971527,.6043894290924072,0,2,2,16,5,3,-1,2,17,5,1,3,.003964765928685665,.5187637209892273,.323181688785553,0,3,13,2,4,6,-1,15,2,2,3,2,13,5,2,3,2,-.022057730704546,.4079256951808929,.520098090171814,0,3,3,2,4,6,-1,3,2,2,3,2,5,5,2,3,2,-.0006690631271339953,.533160924911499,.3815600872039795,0,2,13,5,1,2,-1,13,6,1,1,2,-.0006700932863168418,.5655422210693359,.4688901901245117,0,2,5,5,2,2,-1,5,6,2,1,2,.000742845528293401,.4534381031990051,.6287400126457214,0,2,13,9,2,2,-1,13,9,1,2,2,.0022227810695767403,.5350633263587952,.3303655982017517,0,2,5,9,2,2,-1,6,9,1,2,2,-.005413052160292864,.1113687008619309,.500543475151062,0,2,13,17,3,2,-1,13,18,3,1,2,-14520040167553816e-21,.5628737807273865,.4325133860111237,0,3,6,16,4,4,-1,6,16,2,2,2,8,18,2,2,2,.00023369169502984732,.4165835082530975,.5447791218757629,0,2,9,16,2,3,-1,9,17,2,1,3,.004289454780519009,.4860391020774841,.6778649091720581,0,2,0,13,9,6,-1,0,15,9,2,3,.0059103150852024555,.52623051404953,.3612113893032074,0,2,9,14,2,6,-1,9,17,2,3,2,.0129005396738648,.5319377183914185,.32502880692482,0,2,9,15,2,3,-1,9,16,2,1,3,.004698297940194607,.461824506521225,.6665925979614258,0,2,1,10,18,6,-1,1,12,18,2,3,.0104398597031832,.550567090511322,.3883604109287262,0,2,8,11,4,2,-1,8,12,4,1,2,.0030443191062659025,.4697853028774262,.7301844954490662,0,2,7,9,6,2,-1,7,10,6,1,2,-.0006159375188872218,.3830839097499847,.5464984178543091,0,2,8,8,2,3,-1,8,9,2,1,3,-.0034247159492224455,.256630003452301,.5089530944824219,0,2,17,5,3,4,-1,18,5,1,4,3,-.009353856556117535,.6469966173171997,.49407958984375,0,2,1,19,18,1,-1,7,19,6,1,3,.0523389987647533,.4745982885360718,.787877082824707,0,2,9,0,3,2,-1,10,0,1,2,3,.0035765620414167643,.5306664705276489,.2748498022556305,0,2,1,8,1,6,-1,1,10,1,2,3,.0007155531784519553,.541312575340271,.4041908979415894,0,2,12,17,8,3,-1,12,17,4,3,2,-.0105166798457503,.6158512234687805,.4815283119678497,0,2,0,5,3,4,-1,1,5,1,4,3,.007734792772680521,.4695805907249451,.7028980851173401,0,2,9,7,2,3,-1,9,8,2,1,3,-.004322677850723267,.2849566042423248,.5304684042930603,0,3,7,11,2,2,-1,7,11,1,1,2,8,12,1,1,2,-.0025534399319440126,.7056984901428223,.4688892066478729,0,2,11,3,2,5,-1,11,3,1,5,2,.00010268510231981054,.3902932107448578,.5573464035987854,0,2,7,3,2,5,-1,8,3,1,5,2,7139518857002258e-21,.368423193693161,.526398777961731,0,2,15,13,2,3,-1,15,14,2,1,3,-.0016711989883333445,.3849175870418549,.5387271046638489,0,2,5,6,2,3,-1,5,7,2,1,3,.004926044959574938,.4729771912097931,.7447251081466675,0,2,4,19,15,1,-1,9,19,5,1,3,.0043908702209591866,.4809181094169617,.5591921806335449,0,2,1,19,15,1,-1,6,19,5,1,3,-.0177936293184757,.6903678178787231,.4676927030086517,0,2,15,13,2,3,-1,15,14,2,1,3,.002046966925263405,.5370690226554871,.3308162093162537,0,2,5,0,4,15,-1,7,0,2,15,2,.0298914890736341,.5139865279197693,.3309059143066406,0,2,9,6,2,5,-1,9,6,1,5,2,.0015494900289922953,.466023713350296,.6078342795372009,0,2,9,5,2,7,-1,10,5,1,7,2,.001495696953497827,.4404835999011993,.5863919854164124,0,2,16,11,3,3,-1,16,12,3,1,3,.0009588592802174389,.5435971021652222,.4208523035049439,0,2,1,11,3,3,-1,1,12,3,1,3,.0004964370164088905,.5370578169822693,.4000622034072876,0,2,6,6,8,3,-1,6,7,8,1,3,-.00272808107547462,.5659412741661072,.4259642958641052,0,2,0,15,6,2,-1,0,16,6,1,2,.0023026480339467525,.5161657929420471,.3350869119167328,0,2,1,0,18,6,-1,7,0,6,6,3,.2515163123607636,.4869661927223206,.714730978012085,0,2,6,0,3,4,-1,7,0,1,4,3,-.004632802214473486,.27274489402771,.5083789825439453,0,3,14,10,4,10,-1,16,10,2,5,2,14,15,2,5,2,-.0404344908893108,.6851438879966736,.5021767020225525,0,2,3,2,3,2,-1,4,2,1,2,3,14972220014897175e-21,.428446501493454,.5522555112838745,0,2,11,2,2,2,-1,11,3,2,1,2,-.00024050309730228037,.4226118922233582,.5390074849128723,0,3,2,10,4,10,-1,2,10,2,5,2,4,15,2,5,2,.0236578397452831,.4744631946086884,.7504366040229797,0,3,0,13,20,6,-1,10,13,10,3,2,0,16,10,3,2,-.00814491044729948,.424505889415741,.5538362860679626,0,2,0,5,2,15,-1,1,5,1,15,2,-.003699213033542037,.5952357053756714,.4529713094234467,0,3,1,7,18,4,-1,10,7,9,2,2,1,9,9,2,2,-.0067718601785600185,.4137794077396393,.5473399758338928,0,2,0,0,2,17,-1,1,0,1,17,2,.004266953095793724,.4484114944934845,.5797994136810303,0,3,2,6,16,6,-1,10,6,8,3,2,2,9,8,3,2,.0017791989957913756,.5624858736991882,.4432444870471954,0,2,8,14,1,3,-1,8,15,1,1,3,.0016774770338088274,.4637751877307892,.63642418384552,0,2,8,15,4,2,-1,8,16,4,1,2,.0011732629500329494,.4544503092765808,.5914415717124939,0,3,5,2,8,2,-1,5,2,4,1,2,9,3,4,1,2,.000869981711730361,.5334752798080444,.3885917961597443,0,2,6,11,8,6,-1,6,14,8,3,2,.0007637834060005844,.5398585200309753,.374494194984436,0,2,9,13,2,2,-1,9,14,2,1,2,.00015684569370932877,.4317873120307922,.5614616274833679,0,2,18,4,2,6,-1,18,6,2,2,3,-.0215113703161478,.1785925030708313,.5185542702674866,0,2,9,12,2,2,-1,9,13,2,1,2,.00013081369979772717,.4342499077320099,.5682849884033203,0,2,18,4,2,6,-1,18,6,2,2,3,.021992040798068,.5161716938018799,.2379394024610519,0,2,9,13,1,3,-1,9,14,1,1,3,-.0008013650076463819,.598676323890686,.4466426968574524,0,2,18,4,2,6,-1,18,6,2,2,3,-.008273609913885593,.410821795463562,.5251057147979736,0,2,0,4,2,6,-1,0,6,2,2,3,.0036831789184361696,.5173814296722412,.339751809835434,0,2,9,12,3,3,-1,9,13,3,1,3,-.007952568121254444,.6888983249664307,.4845924079418182,0,2,3,13,2,3,-1,3,14,2,1,3,.0015382299898192286,.5178567171096802,.3454113900661469,0,2,13,13,4,3,-1,13,14,4,1,3,-.0140435304492712,.1678421050310135,.518866777420044,0,2,5,4,3,3,-1,5,5,3,1,3,.0014315890148282051,.436825692653656,.5655773878097534,0,2,5,2,10,6,-1,5,4,10,2,3,-.0340142287313938,.7802296280860901,.4959217011928558,0,2,3,13,4,3,-1,3,14,4,1,3,-.0120272999629378,.1585101038217545,.503223180770874,0,2,3,7,15,5,-1,8,7,5,5,3,.1331661939620972,.5163304805755615,.2755128145217896,0,2,3,7,12,2,-1,7,7,4,2,3,-.0015221949433907866,.372831791639328,.5214552283287048,0,2,10,3,3,9,-1,11,3,1,9,3,-.000939292716793716,.5838379263877869,.4511165022850037,0,2,8,6,4,6,-1,10,6,2,6,2,.0277197398245335,.4728286862373352,.7331544756889343,0,2,9,7,4,3,-1,9,8,4,1,3,.003103015013039112,.5302202105522156,.4101563096046448,0,2,0,9,4,9,-1,2,9,2,9,2,.0778612196445465,.4998334050178528,.127296194434166,0,2,9,13,3,5,-1,10,13,1,5,3,-.0158549398183823,.0508333593606949,.5165656208992004,0,2,7,7,6,3,-1,9,7,2,3,3,-.00497253006324172,.6798133850097656,.4684231877326965,0,2,9,7,3,5,-1,10,7,1,5,3,-.0009767650626599789,.6010771989822388,.4788931906223297,0,2,5,7,8,2,-1,9,7,4,2,2,-.0024647710379213095,.3393397927284241,.5220503807067871,0,2,5,9,12,2,-1,9,9,4,2,3,-.006793770007789135,.4365136921405792,.5239663124084473,0,2,5,6,10,3,-1,10,6,5,3,2,.0326080210506916,.505272388458252,.2425214946269989,0,2,10,12,3,1,-1,11,12,1,1,3,-.0005851442110724747,.5733973979949951,.4758574068546295,0,2,0,1,11,15,-1,0,6,11,5,3,-.0296326000243425,.3892289102077484,.5263597965240479,67.69892120361328,137,0,2,1,0,18,6,-1,7,0,6,6,3,.0465508513152599,.3276950120925903,.6240522861480713,0,2,7,7,6,1,-1,9,7,2,1,3,.007953712716698647,.4256485104560852,.6942939162254333,0,3,5,16,6,4,-1,5,16,3,2,2,8,18,3,2,2,.0006822156137786806,.3711487054824829,.59007328748703,0,2,6,5,9,8,-1,6,9,9,4,2,-.00019348249770700932,.2041133940219879,.53005450963974,0,2,5,10,2,6,-1,5,13,2,3,2,-.0002671050897333771,.5416126251220703,.3103179037570953,0,3,7,6,8,10,-1,11,6,4,5,2,7,11,4,5,2,.0027818060480058193,.5277832746505737,.3467069864273071,0,3,5,6,8,10,-1,5,6,4,5,2,9,11,4,5,2,-.000467790785478428,.5308231115341187,.3294492065906525,0,2,9,5,2,2,-1,9,6,2,1,2,-30335160772665404e-21,.577387273311615,.3852097094058991,0,2,5,12,8,2,-1,5,13,8,1,2,.0007803800981491804,.4317438900470734,.6150057911872864,0,2,10,2,8,2,-1,10,3,8,1,2,-.004255385138094425,.2933903932571411,.5324292778968811,0,3,4,0,2,10,-1,4,0,1,5,2,5,5,1,5,2,-.0002473561035003513,.5468844771385193,.3843030035495758,0,2,9,10,2,2,-1,9,11,2,1,2,-.00014724259381182492,.4281542897224426,.5755587220191956,0,2,2,8,15,3,-1,2,9,15,1,3,.0011864770203828812,.374730110168457,.5471466183662415,0,2,8,13,4,3,-1,8,14,4,1,3,.0023936580400913954,.4537783861160278,.6111528873443604,0,2,7,2,3,2,-1,8,2,1,2,3,-.0015390539774671197,.2971341907978058,.518953800201416,0,2,7,13,6,3,-1,7,14,6,1,3,-.007196879014372826,.6699066758155823,.4726476967334747,0,2,9,9,2,2,-1,9,10,2,1,2,-.0004149978922214359,.3384954035282135,.5260317921638489,0,2,17,2,3,6,-1,17,4,3,2,3,.004435983020812273,.539912223815918,.3920140862464905,0,2,1,5,3,4,-1,2,5,1,4,3,.0026606200262904167,.4482578039169312,.6119617819786072,0,2,14,8,4,6,-1,14,10,4,2,3,-.0015287200221791863,.3711237907409668,.5340266227722168,0,2,1,4,3,8,-1,2,4,1,8,3,-.0047397250309586525,.603108823299408,.4455145001411438,0,2,8,13,4,6,-1,8,16,4,3,2,-.0148291299119592,.2838754057884216,.5341861844062805,0,2,3,14,2,2,-1,3,15,2,1,2,.0009227555710822344,.5209547281265259,.3361653983592987,0,2,14,8,4,6,-1,14,10,4,2,3,.0835298076272011,.5119969844818115,.0811644494533539,0,2,2,8,4,6,-1,2,10,4,2,3,-.0007563314866274595,.331712007522583,.5189831256866455,0,2,10,14,1,6,-1,10,17,1,3,2,.009840385988354683,.524759829044342,.233495905995369,0,2,7,5,3,6,-1,8,5,1,6,3,-.0015953830443322659,.5750094056129456,.4295622110366821,0,3,11,2,2,6,-1,12,2,1,3,2,11,5,1,3,2,34766020689858124e-21,.4342445135116577,.5564029216766357,0,2,6,6,6,5,-1,8,6,2,5,3,.0298629105091095,.4579147100448608,.6579188108444214,0,2,17,1,3,6,-1,17,3,3,2,3,.0113255903124809,.5274311900138855,.3673888146877289,0,2,8,7,3,5,-1,9,7,1,5,3,-.008782864548265934,.7100368738174438,.4642167091369629,0,2,9,18,3,2,-1,10,18,1,2,3,.004363995976746082,.5279216170310974,.2705877125263214,0,2,8,18,3,2,-1,9,18,1,2,3,.004180472809821367,.5072525143623352,.2449083030223846,0,2,12,3,5,2,-1,12,4,5,1,2,-.0004566851130221039,.4283105134963989,.5548691153526306,0,2,7,1,5,12,-1,7,7,5,6,2,-.0037140368949621916,.5519387722015381,.4103653132915497,0,2,1,0,18,4,-1,7,0,6,4,3,-.025304289534688,.6867002248764038,.48698890209198,0,2,4,2,2,2,-1,4,3,2,1,2,-.0003445408074185252,.3728874027729034,.528769314289093,0,3,11,14,4,2,-1,13,14,2,1,2,11,15,2,1,2,-.0008393523166887462,.6060152053833008,.4616062045097351,0,2,0,2,3,6,-1,0,4,3,2,3,.0172800496220589,.5049635767936707,.1819823980331421,0,2,9,7,2,3,-1,9,8,2,1,3,-.006359507795423269,.1631239950656891,.5232778787612915,0,2,5,5,1,3,-1,5,6,1,1,3,.0010298109846189618,.446327805519104,.6176549196243286,0,2,10,10,6,1,-1,10,10,3,1,2,.0010117109632119536,.5473384857177734,.4300698935985565,0,2,4,10,6,1,-1,7,10,3,1,2,-.010308800265193,.1166985034942627,.5000867247581482,0,2,9,17,3,3,-1,9,18,3,1,3,.005468201823532581,.4769287109375,.6719213724136353,0,2,4,14,1,3,-1,4,15,1,1,3,-.0009169646073132753,.3471089899539948,.5178164839744568,0,2,12,5,3,3,-1,12,6,3,1,3,.002392282010987401,.4785236120223999,.6216310858726501,0,2,4,5,12,3,-1,4,6,12,1,3,-.007557381875813007,.5814796090126038,.4410085082054138,0,2,9,8,2,3,-1,9,9,2,1,3,-.0007702403236180544,.387800008058548,.546572208404541,0,2,4,9,3,3,-1,5,9,1,3,3,-.00871259905397892,.1660051047801971,.4995836019515991,0,2,6,0,9,17,-1,9,0,3,17,3,-.0103063201531768,.4093391001224518,.5274233818054199,0,2,9,12,1,3,-1,9,13,1,1,3,-.002094097901135683,.6206194758415222,.4572280049324036,0,2,9,5,2,15,-1,9,10,2,5,3,.006809905171394348,.5567759275436401,.4155600070953369,0,2,8,14,2,3,-1,8,15,2,1,3,-.0010746059706434608,.5638927817344666,.4353024959564209,0,2,10,14,1,3,-1,10,15,1,1,3,.0021550289820879698,.4826265871524811,.6749758124351501,0,2,7,1,6,5,-1,9,1,2,5,3,.0317423194646835,.5048379898071289,.188324898481369,0,2,0,0,20,2,-1,0,0,10,2,2,-.0783827230334282,.2369548976421356,.5260158181190491,0,2,2,13,5,3,-1,2,14,5,1,3,.005741511937230825,.5048828721046448,.2776469886302948,0,2,9,11,2,3,-1,9,12,2,1,3,-.0029014600440859795,.6238604784011841,.4693317115306854,0,2,2,5,9,15,-1,2,10,9,5,3,-.0026427931152284145,.3314141929149628,.5169777274131775,0,3,5,0,12,10,-1,11,0,6,5,2,5,5,6,5,2,-.1094966009259224,.2380045056343079,.5183441042900085,0,2,5,1,2,3,-1,6,1,1,3,2,7407591328956187e-20,.406963586807251,.5362150073051453,0,2,10,7,6,1,-1,12,7,2,1,3,-.0005059380200691521,.5506706237792969,.437459409236908,0,3,3,1,2,10,-1,3,1,1,5,2,4,6,1,5,2,-.0008213177789002657,.5525709986686707,.4209375977516174,0,2,13,7,2,1,-1,13,7,1,1,2,-60276539443293586e-21,.5455474853515625,.4748266041278839,0,2,4,13,4,6,-1,4,15,4,2,3,.006806514225900173,.5157995820045471,.3424577116966248,0,2,13,7,2,1,-1,13,7,1,1,2,.0017202789895236492,.5013207793235779,.6331263780593872,0,2,5,7,2,1,-1,6,7,1,1,2,-.0001301692973356694,.5539718270301819,.4226869940757752,0,3,2,12,18,4,-1,11,12,9,2,2,2,14,9,2,2,-.004801638890057802,.4425095021724701,.5430780053138733,0,3,5,7,2,2,-1,5,7,1,1,2,6,8,1,1,2,-.002539931097999215,.7145782113075256,.4697605073451996,0,2,16,3,4,2,-1,16,4,4,1,2,-.0014278929447755218,.4070445001125336,.539960503578186,0,3,0,2,2,18,-1,0,2,1,9,2,1,11,1,9,2,-.0251425504684448,.7884690761566162,.4747352004051209,0,3,1,2,18,4,-1,10,2,9,2,2,1,4,9,2,2,-.0038899609353393316,.4296191930770874,.5577110052108765,0,2,9,14,1,3,-1,9,15,1,1,3,.004394745919853449,.4693162143230438,.702394425868988,0,3,2,12,18,4,-1,11,12,9,2,2,2,14,9,2,2,.0246784202754498,.5242322087287903,.3812510073184967,0,3,0,12,18,4,-1,0,12,9,2,2,9,14,9,2,2,.0380476787686348,.5011739730834961,.1687828004360199,0,2,11,4,5,3,-1,11,5,5,1,3,.007942486554384232,.4828582108020783,.6369568109512329,0,2,6,4,7,3,-1,6,5,7,1,3,-.0015110049862414598,.5906485915184021,.4487667977809906,0,2,13,17,3,3,-1,13,18,3,1,3,.0064201741479337215,.5241097807884216,.2990570068359375,0,2,8,1,3,4,-1,9,1,1,4,3,-.0029802159406244755,.3041465878486633,.5078489780426025,0,2,11,4,2,4,-1,11,4,1,4,2,-.0007458007894456387,.4128139019012451,.5256826281547546,0,2,0,17,9,3,-1,3,17,3,3,3,-.0104709500446916,.5808395147323608,.4494296014308929,0,3,11,0,2,8,-1,12,0,1,4,2,11,4,1,4,2,.009336920455098152,.524655282497406,.265894889831543,0,3,0,8,6,12,-1,0,8,3,6,2,3,14,3,6,2,.0279369000345469,.4674955010414124,.7087256908416748,0,2,10,7,4,12,-1,10,13,4,6,2,.007427767850458622,.5409486889839172,.3758518099784851,0,2,5,3,8,14,-1,5,10,8,7,2,-.0235845092684031,.3758639991283417,.5238550901412964,0,2,14,10,6,1,-1,14,10,3,1,2,.0011452640173956752,.4329578876495361,.5804247260093689,0,2,0,4,10,4,-1,0,6,10,2,2,-.0004346866044215858,.5280618071556091,.3873069882392883,0,2,10,0,5,8,-1,10,4,5,4,2,.0106485402211547,.4902113080024719,.5681251883506775,0,3,8,1,4,8,-1,8,1,2,4,2,10,5,2,4,2,-.0003941805043723434,.5570880174636841,.4318251013755798,0,2,9,11,6,1,-1,11,11,2,1,3,-.00013270479394122958,.5658439993858337,.4343554973602295,0,2,8,9,3,4,-1,9,9,1,4,3,-.002012551063671708,.6056739091873169,.4537523984909058,0,2,18,4,2,6,-1,18,6,2,2,3,.0024854319635778666,.5390477180480957,.4138010144233704,0,2,8,8,3,4,-1,9,8,1,4,3,.0018237880431115627,.4354828894138336,.5717188715934753,0,2,7,1,13,3,-1,7,2,13,1,3,-.0166566595435143,.3010913133621216,.521612286567688,0,2,7,13,6,1,-1,9,13,2,1,3,.0008034955826587975,.5300151109695435,.3818396925926209,0,2,12,11,3,6,-1,12,13,3,2,3,.003417037893086672,.5328028798103333,.4241400063037872,0,2,5,11,6,1,-1,7,11,2,1,3,-.00036222729249857366,.5491728186607361,.418697714805603,0,3,1,4,18,10,-1,10,4,9,5,2,1,9,9,5,2,-.1163002029061317,.1440722048282623,.522645115852356,0,2,8,6,4,9,-1,8,9,4,3,3,-.0146950101479888,.7747725248336792,.4715717136859894,0,2,8,6,4,3,-1,8,7,4,1,3,.0021972130052745342,.5355433821678162,.3315644860267639,0,2,8,7,3,3,-1,9,7,1,3,3,-.00046965209185145795,.5767235159873962,.4458136856555939,0,2,14,15,4,3,-1,14,16,4,1,3,.006514499895274639,.5215674042701721,.3647888898849487,0,2,5,10,3,10,-1,6,10,1,10,3,.0213000606745481,.4994204938411713,.1567950993776321,0,2,8,15,4,3,-1,8,16,4,1,3,.0031881409231573343,.4742200076580048,.6287270188331604,0,2,0,8,1,6,-1,0,10,1,2,3,.0009001977741718292,.5347954034805298,.394375205039978,0,2,10,15,1,3,-1,10,16,1,1,3,-.005177227780222893,.6727191805839539,.5013138055801392,0,2,2,15,4,3,-1,2,16,4,1,3,-.004376464989036322,.3106675148010254,.5128793120384216,0,3,18,3,2,8,-1,19,3,1,4,2,18,7,1,4,2,.002629996044561267,.488631010055542,.5755215883255005,0,3,0,3,2,8,-1,0,3,1,4,2,1,7,1,4,2,-.002045868895947933,.6025794148445129,.4558076858520508,0,3,3,7,14,10,-1,10,7,7,5,2,3,12,7,5,2,.0694827064871788,.5240747928619385,.2185259014368057,0,2,0,7,19,3,-1,0,8,19,1,3,.0240489393472672,.501186728477478,.2090622037649155,0,2,12,6,3,3,-1,12,7,3,1,3,.003109534038230777,.4866712093353272,.7108548283576965,0,2,0,6,1,3,-1,0,7,1,1,3,-.00125032605137676,.3407891094684601,.5156195163726807,0,2,12,6,3,3,-1,12,7,3,1,3,-.0010281190043315291,.557557225227356,.443943202495575,0,2,5,6,3,3,-1,5,7,3,1,3,-.008889362215995789,.6402000784873962,.4620442092418671,0,2,8,2,4,2,-1,8,3,4,1,2,-.0006109480164013803,.3766441941261292,.5448899865150452,0,2,6,3,4,12,-1,8,3,2,12,2,-.005768635775893927,.3318648934364319,.5133677124977112,0,2,13,6,2,3,-1,13,7,2,1,3,.0018506490159779787,.4903570115566254,.6406934857368469,0,2,0,10,20,4,-1,0,12,20,2,2,-.0997994691133499,.1536051034927368,.5015562176704407,0,2,2,0,17,14,-1,2,7,17,7,2,-.3512834906578064,.0588231310248375,.5174378752708435,0,3,0,0,6,10,-1,0,0,3,5,2,3,5,3,5,2,-.0452445708215237,.6961488723754883,.4677872955799103,0,2,14,6,6,4,-1,14,6,3,4,2,.0714815780520439,.5167986154556274,.1038092970848084,0,2,0,6,6,4,-1,3,6,3,4,2,.0021895780228078365,.4273078143596649,.5532060861587524,0,2,13,2,7,2,-1,13,3,7,1,2,-.0005924265133216977,.46389439702034,.5276389122009277,0,2,0,2,7,2,-1,0,3,7,1,2,.0016788389766588807,.530164897441864,.3932034969329834,0,3,6,11,14,2,-1,13,11,7,1,2,6,12,7,1,2,-.0022163488902151585,.5630694031715393,.4757033884525299,0,3,8,5,2,2,-1,8,5,1,1,2,9,6,1,1,2,.00011568699846975505,.4307535886764526,.5535702705383301,0,2,13,9,2,3,-1,13,9,1,3,2,-.007201728876680136,.144488200545311,.5193064212799072,0,2,1,1,3,12,-1,2,1,1,12,3,.0008908127201721072,.4384432137012482,.5593621134757996,0,2,17,4,1,3,-1,17,5,1,1,3,.00019605009583756328,.5340415835380554,.4705956876277924,0,2,2,4,1,3,-1,2,5,1,1,3,.0005202214233577251,.5213856101036072,.3810079097747803,0,2,14,5,1,3,-1,14,6,1,1,3,.0009458857239224017,.4769414961338043,.6130738854408264,0,2,7,16,2,3,-1,7,17,2,1,3,916984718060121e-19,.4245009124279022,.5429363250732422,0,3,8,13,4,6,-1,10,13,2,3,2,8,16,2,3,2,.002183320000767708,.5457730889320374,.419107586145401,0,2,5,5,1,3,-1,5,6,1,1,3,-.0008603967144154012,.5764588713645935,.4471659958362579,0,2,16,0,4,20,-1,16,0,2,20,2,-.0132362395524979,.6372823119163513,.4695009887218475,0,3,5,1,2,6,-1,5,1,1,3,2,6,4,1,3,2,.0004337670106906444,.5317873954772949,.394582986831665,69.22987365722656,140,0,2,5,4,10,4,-1,5,6,10,2,2,-.024847149848938,.6555516719818115,.3873311877250671,0,2,15,2,4,12,-1,15,2,2,12,2,.006134861148893833,.374807208776474,.5973997712135315,0,2,7,6,4,12,-1,7,12,4,6,2,.006449849810451269,.542549192905426,.2548811137676239,0,2,14,5,1,8,-1,14,9,1,4,2,.0006349121103994548,.2462442070245743,.5387253761291504,0,3,1,4,14,10,-1,1,4,7,5,2,8,9,7,5,2,.0014023890253156424,.5594322085380554,.3528657853603363,0,3,11,6,6,14,-1,14,6,3,7,2,11,13,3,7,2,.0003004400059580803,.3958503901958466,.576593816280365,0,3,3,6,6,14,-1,3,6,3,7,2,6,13,3,7,2,.00010042409849120304,.3698996901512146,.5534998178482056,0,2,4,9,15,2,-1,9,9,5,2,3,-.005084149073809385,.3711090981960297,.5547800064086914,0,2,7,14,6,3,-1,7,15,6,1,3,-.0195372607558966,.7492755055427551,.4579297006130219,0,3,6,3,14,4,-1,13,3,7,2,2,6,5,7,2,2,-7453274065483129e-21,.5649787187576294,.390406996011734,0,2,1,9,15,2,-1,6,9,5,2,3,-.0036079459823668003,.3381088078022003,.5267801284790039,0,2,6,11,8,9,-1,6,14,8,3,3,.002069750102236867,.5519291162490845,.3714388906955719,0,2,7,4,3,8,-1,8,4,1,8,3,-.0004646384040825069,.5608214735984802,.4113566875457764,0,2,14,6,2,6,-1,14,9,2,3,2,.0007549045258201659,.3559206128120422,.532935619354248,0,3,5,7,6,4,-1,5,7,3,2,2,8,9,3,2,2,-.0009832223877310753,.5414795875549316,.3763205111026764,0,2,1,1,18,19,-1,7,1,6,19,3,-.0199406407773495,.634790301322937,.4705299139022827,0,2,1,2,6,5,-1,4,2,3,5,2,.0037680300883948803,.3913489878177643,.5563716292381287,0,2,12,17,6,2,-1,12,18,6,1,2,-.009452850557863712,.2554892897605896,.5215116739273071,0,2,2,17,6,2,-1,2,18,6,1,2,.002956084907054901,.5174679160118103,.3063920140266419,0,2,17,3,3,6,-1,17,5,3,2,3,.009107873775064945,.5388448238372803,.2885963022708893,0,2,8,17,3,3,-1,8,18,3,1,3,.0018219229532405734,.4336043000221252,.58521968126297,0,2,10,13,2,6,-1,10,16,2,3,2,.0146887395530939,.5287361741065979,.2870005965232849,0,2,7,13,6,3,-1,7,14,6,1,3,-.0143879903480411,.701944887638092,.4647370874881744,0,2,17,3,3,6,-1,17,5,3,2,3,-.0189866498112679,.2986552119255066,.5247011780738831,0,2,8,13,2,3,-1,8,14,2,1,3,.0011527639580890536,.4323473870754242,.593166172504425,0,2,9,3,6,2,-1,11,3,2,2,3,.0109336702153087,.5286864042282104,.3130319118499756,0,2,0,3,3,6,-1,0,5,3,2,3,-.0149327302351594,.2658419013023377,.508407711982727,0,2,8,5,4,6,-1,8,7,4,2,3,-.0002997053961735219,.5463526844978333,.374072402715683,0,2,5,5,3,2,-1,5,6,3,1,2,.004167762119323015,.4703496992588043,.7435721755027771,0,2,10,1,3,4,-1,11,1,1,4,3,-.00639053201302886,.2069258987903595,.5280538201332092,0,2,1,2,5,9,-1,1,5,5,3,3,.004502960946410894,.518264889717102,.348354309797287,0,2,13,6,2,3,-1,13,7,2,1,3,-.009204036556184292,.680377721786499,.4932360053062439,0,2,0,6,14,3,-1,7,6,7,3,2,.0813272595405579,.5058398842811584,.2253051996231079,0,2,2,11,18,8,-1,2,15,18,4,2,-.150792807340622,.2963424921035767,.5264679789543152,0,2,5,6,2,3,-1,5,7,2,1,3,.0033179009333252907,.4655495882034302,.7072932124137878,0,3,10,6,4,2,-1,12,6,2,1,2,10,7,2,1,2,.0007740280125290155,.4780347943305969,.5668237805366516,0,3,6,6,4,2,-1,6,6,2,1,2,8,7,2,1,2,.0006819954141974449,.4286996126174927,.5722156763076782,0,2,10,1,3,4,-1,11,1,1,4,3,.0053671570494771,.5299307107925415,.3114621937274933,0,2,7,1,2,7,-1,8,1,1,7,2,9701866656541824e-20,.3674638867378235,.5269461870193481,0,2,4,2,15,14,-1,4,9,15,7,2,-.1253408938646317,.2351492047309876,.5245791077613831,0,2,8,7,3,2,-1,9,7,1,2,3,-.005251626949757338,.7115936875343323,.4693767130374908,0,3,2,3,18,4,-1,11,3,9,2,2,2,5,9,2,2,-.007834210991859436,.4462651014328003,.5409085750579834,0,2,9,7,2,2,-1,10,7,1,2,2,-.001131006982177496,.5945618748664856,.4417662024497986,0,2,13,9,2,3,-1,13,9,1,3,2,.0017601120052859187,.5353249907493591,.3973453044891357,0,2,5,2,6,2,-1,7,2,2,2,3,-.00081581249833107,.3760268092155457,.5264726877212524,0,2,9,5,2,7,-1,9,5,1,7,2,-.003868758911266923,.6309912800788879,.4749819934368134,0,2,5,9,2,3,-1,6,9,1,3,2,.0015207129763439298,.5230181813240051,.3361223936080933,0,2,6,0,14,18,-1,6,9,14,9,2,.545867383480072,.5167139768600464,.1172635033726692,0,2,2,16,6,3,-1,2,17,6,1,3,.0156501904129982,.4979439079761505,.1393294930458069,0,2,9,7,3,6,-1,10,7,1,6,3,-.0117318602278829,.7129650712013245,.4921196103096008,0,2,7,8,4,3,-1,7,9,4,1,3,-.006176512222737074,.2288102954626083,.5049701929092407,0,2,7,12,6,3,-1,7,13,6,1,3,.0022457661107182503,.4632433950901032,.6048725843429565,0,2,9,12,2,3,-1,9,13,2,1,3,-.005191586911678314,.6467421054840088,.4602192938327789,0,2,7,12,6,2,-1,9,12,2,2,3,-.0238278806209564,.1482000946998596,.5226079225540161,0,2,5,11,4,6,-1,5,14,4,3,2,.0010284580057486892,.5135489106178284,.3375957012176514,0,2,11,12,7,2,-1,11,13,7,1,2,-.0100788502022624,.2740561068058014,.5303567051887512,0,3,6,10,8,6,-1,6,10,4,3,2,10,13,4,3,2,.002616893034428358,.533267080783844,.3972454071044922,0,2,11,10,3,4,-1,11,12,3,2,2,.000543853675480932,.5365604162216187,.4063411951065064,0,2,9,16,2,3,-1,9,17,2,1,3,.005351051222532988,.4653759002685547,.6889045834541321,0,2,13,3,1,9,-1,13,6,1,3,3,-.0015274790348485112,.5449501276016235,.3624723851680756,0,2,1,13,14,6,-1,1,15,14,2,3,-.0806244164705276,.1656087040901184,.5000287294387817,0,2,13,6,1,6,-1,13,9,1,3,2,.0221920292824507,.5132731199264526,.2002808004617691,0,2,0,4,3,8,-1,1,4,1,8,3,.007310063112527132,.4617947936058044,.6366536021232605,0,2,18,0,2,18,-1,18,0,1,18,2,-.006406307220458984,.5916250944137573,.4867860972881317,0,2,2,3,6,2,-1,2,4,6,1,2,-.0007641504053026438,.388840913772583,.5315797924995422,0,2,9,0,8,6,-1,9,2,8,2,3,.0007673448999412358,.4159064888954163,.5605279803276062,0,2,6,6,1,6,-1,6,9,1,3,2,.0006147450185380876,.3089022040367127,.5120148062705994,0,2,14,8,6,3,-1,14,9,6,1,3,-.005010527092963457,.3972199857234955,.5207306146621704,0,2,0,0,2,18,-1,1,0,1,18,2,-.008690913207828999,.6257408261299133,.4608575999736786,0,3,1,18,18,2,-1,10,18,9,1,2,1,19,9,1,2,-.016391459852457,.2085209935903549,.5242266058921814,0,2,3,15,2,2,-1,3,16,2,1,2,.00040973909199237823,.5222427248954773,.3780320882797241,0,2,8,14,5,3,-1,8,15,5,1,3,-.002524228999391198,.5803927183151245,.4611890017986298,0,2,8,14,2,3,-1,8,15,2,1,3,.0005094531225040555,.4401271939277649,.5846015810966492,0,2,12,3,3,3,-1,13,3,1,3,3,.001965641975402832,.5322325229644775,.4184590876102448,0,2,7,5,6,2,-1,9,5,2,2,3,.0005629889783449471,.3741844892501831,.5234565734863281,0,2,15,5,5,2,-1,15,6,5,1,2,-.0006794679793529212,.4631041884422302,.5356478095054626,0,2,0,5,5,2,-1,0,6,5,1,2,.007285634987056255,.5044670104980469,.2377564013004303,0,2,17,14,1,6,-1,17,17,1,3,2,-.0174594894051552,.7289121150970459,.5050435066223145,0,2,2,9,9,3,-1,5,9,3,3,3,-.0254217498004436,.6667134761810303,.4678100049495697,0,2,12,3,3,3,-1,13,3,1,3,3,-.0015647639520466328,.4391759037971497,.532362699508667,0,2,0,0,4,18,-1,2,0,2,18,2,.0114443600177765,.4346440136432648,.5680012106895447,0,2,17,6,1,3,-1,17,7,1,1,3,-.0006735255010426044,.44771409034729,.5296812057495117,0,2,2,14,1,6,-1,2,17,1,3,2,.009319420903921127,.4740200042724609,.7462607026100159,0,2,19,8,1,2,-1,19,9,1,1,2,.00013328490604180843,.536506175994873,.475213497877121,0,2,5,3,3,3,-1,6,3,1,3,3,-.007881579920649529,.1752219051122665,.5015255212783813,0,2,9,16,2,3,-1,9,17,2,1,3,-.005798568017780781,.7271236777305603,.4896200895309448,0,2,2,6,1,3,-1,2,7,1,1,3,-.0003892249951604754,.4003908932209015,.5344941020011902,0,3,12,4,8,2,-1,16,4,4,1,2,12,5,4,1,2,-.0019288610201328993,.5605612993240356,.4803955852985382,0,3,0,4,8,2,-1,0,4,4,1,2,4,5,4,1,2,.008421415463089943,.4753246903419495,.7623608708381653,0,2,2,16,18,4,-1,2,18,18,2,2,.008165587671101093,.5393261909484863,.419164389371872,0,2,7,15,2,4,-1,7,17,2,2,2,.00048280550981871784,.4240800142288208,.5399821996688843,0,2,4,0,14,3,-1,4,1,14,1,3,-.002718663075938821,.4244599938392639,.5424923896789551,0,2,0,0,4,20,-1,2,0,2,20,2,-.0125072300434113,.5895841717720032,.4550411105155945,0,3,12,4,4,8,-1,14,4,2,4,2,12,8,2,4,2,-.0242865197360516,.2647134959697723,.518917977809906,0,3,6,7,2,2,-1,6,7,1,1,2,7,8,1,1,2,-.0029676330741494894,.734768271446228,.4749749898910523,0,2,10,6,2,3,-1,10,7,2,1,3,-.0125289997085929,.2756049931049347,.5177599787712097,0,2,8,7,3,2,-1,8,8,3,1,2,-.0010104000102728605,.3510560989379883,.5144724249839783,0,2,8,2,6,12,-1,8,8,6,6,2,-.0021348530426621437,.5637925863265991,.466731995344162,0,2,4,0,11,12,-1,4,4,11,4,3,.0195642597973347,.4614573121070862,.6137639880180359,0,2,14,9,6,11,-1,16,9,2,11,3,-.0971463471651077,.2998378872871399,.5193555951118469,0,2,0,14,4,3,-1,0,15,4,1,3,.00450145686045289,.5077884793281555,.3045755922794342,0,2,9,10,2,3,-1,9,11,2,1,3,.006370697170495987,.486101895570755,.6887500882148743,0,2,5,11,3,2,-1,5,12,3,1,2,-.009072152897715569,.1673395931720734,.5017563104629517,0,2,9,15,3,3,-1,10,15,1,3,3,-.005353720858693123,.2692756950855255,.524263322353363,0,2,8,8,3,4,-1,9,8,1,4,3,-.0109328404068947,.7183864116668701,.4736028909683228,0,2,9,15,3,3,-1,10,15,1,3,3,.008235607296228409,.5223966836929321,.2389862984418869,0,2,7,7,3,2,-1,8,7,1,2,3,-.0010038160253316164,.5719355940818787,.4433943033218384,0,3,2,10,16,4,-1,10,10,8,2,2,2,12,8,2,2,.004085912834852934,.5472841858863831,.4148836135864258,0,2,2,3,4,17,-1,4,3,2,17,2,.1548541933298111,.4973812103271484,.0610615983605385,0,2,15,13,2,7,-1,15,13,1,7,2,.00020897459762636572,.4709174036979675,.542388916015625,0,2,2,2,6,1,-1,5,2,3,1,2,.0003331699117552489,.4089626967906952,.5300992131233215,0,2,5,2,12,4,-1,9,2,4,4,3,-.0108134001493454,.6104369759559631,.4957334101200104,0,3,6,0,8,12,-1,6,0,4,6,2,10,6,4,6,2,.0456560105085373,.5069689154624939,.2866660058498383,0,3,13,7,2,2,-1,14,7,1,1,2,13,8,1,1,2,.0012569549726322293,.484691709280014,.631817102432251,0,2,0,12,20,6,-1,0,14,20,2,3,-.120150700211525,.0605261400341988,.4980959892272949,0,2,14,7,2,3,-1,14,7,1,3,2,-.00010533799650147557,.5363109707832336,.4708042144775391,0,2,0,8,9,12,-1,3,8,3,12,3,-.2070319056510925,.059660330414772,.497909814119339,0,2,3,0,16,2,-1,3,0,8,2,2,.00012909180077258497,.4712977111339569,.5377997756004333,0,2,6,15,3,3,-1,6,16,3,1,3,.000388185289921239,.4363538026809692,.5534191131591797,0,2,8,15,6,3,-1,8,16,6,1,3,-.0029243610333651304,.5811185836791992,.4825215935707092,0,2,0,10,1,6,-1,0,12,1,2,3,.0008388233254663646,.5311700105667114,.403813898563385,0,2,10,9,4,3,-1,10,10,4,1,3,-.0019061550265178084,.3770701885223389,.526001513004303,0,2,9,15,2,3,-1,9,16,2,1,3,.00895143486559391,.4766167998313904,.7682183980941772,0,2,5,7,10,1,-1,5,7,5,1,2,.0130834598094225,.5264462828636169,.3062222003936768,0,2,4,0,12,19,-1,10,0,6,19,2,-.2115933001041412,.6737198233604431,.4695810079574585,0,3,0,6,20,6,-1,10,6,10,3,2,0,9,10,3,2,.0031493250280618668,.5644835233688354,.4386953115463257,0,3,3,6,2,2,-1,3,6,1,1,2,4,7,1,1,2,.00039754100725986063,.4526061117649078,.5895630121231079,0,3,15,6,2,2,-1,16,6,1,1,2,15,7,1,1,2,-.0013814480043947697,.6070582270622253,.4942413866519928,0,3,3,6,2,2,-1,3,6,1,1,2,4,7,1,1,2,-.0005812218878418207,.5998213291168213,.4508252143859863,0,2,14,4,1,12,-1,14,10,1,6,2,-.002390532987192273,.420558899641037,.5223848223686218,0,3,2,5,16,10,-1,2,5,8,5,2,10,10,8,5,2,.0272689294070005,.5206447243690491,.3563301861286163,0,2,9,17,3,2,-1,10,17,1,2,3,-.0037658358924090862,.3144704103469849,.5218814015388489,0,2,1,4,2,2,-1,1,5,2,1,2,-.0014903489500284195,.338019609451294,.5124437212944031,0,2,5,0,15,5,-1,10,0,5,5,3,-.0174282304942608,.5829960703849792,.4919725954532623,0,2,0,0,15,5,-1,5,0,5,5,3,-.0152780301868916,.6163144707679749,.4617887139320374,0,2,11,2,2,17,-1,11,2,1,17,2,.0319956094026566,.5166357159614563,.171276405453682,0,2,7,2,2,17,-1,8,2,1,17,2,-.003825671039521694,.3408012092113495,.5131387710571289,0,2,15,11,2,9,-1,15,11,1,9,2,-.00851864367723465,.6105518937110901,.4997941851615906,0,2,3,11,2,9,-1,4,11,1,9,2,.0009064162150025368,.4327270984649658,.5582311153411865,0,2,5,16,14,4,-1,5,16,7,4,2,.0103448498994112,.4855653047561646,.5452420115470886,79.24907684326172,160,0,2,1,4,18,1,-1,7,4,6,1,3,.007898182608187199,.333252489566803,.5946462154388428,0,3,13,7,6,4,-1,16,7,3,2,2,13,9,3,2,2,.0016170160379260778,.3490641117095947,.5577868819236755,0,2,9,8,2,12,-1,9,12,2,4,3,-.0005544974119402468,.5542566180229187,.3291530013084412,0,2,12,1,6,6,-1,12,3,6,2,3,.001542898011393845,.3612579107284546,.5545979142189026,0,3,5,2,6,6,-1,5,2,3,3,2,8,5,3,3,2,-.0010329450014978647,.3530139029026032,.5576140284538269,0,3,9,16,6,4,-1,12,16,3,2,2,9,18,3,2,2,.0007769815856590867,.3916778862476349,.5645321011543274,0,2,1,2,18,3,-1,7,2,6,3,3,.143203005194664,.4667482078075409,.7023633122444153,0,2,7,4,9,10,-1,7,9,9,5,2,-.007386649027466774,.3073684871196747,.5289257764816284,0,2,5,9,4,4,-1,7,9,2,4,2,-.0006293674232438207,.562211811542511,.4037049114704132,0,2,11,10,3,6,-1,11,13,3,3,2,.0007889352855272591,.5267661213874817,.3557874858379364,0,2,7,11,5,3,-1,7,12,5,1,3,-.0122280502691865,.6668320894241333,.4625549912452698,0,3,7,11,6,6,-1,10,11,3,3,2,7,14,3,3,2,.0035420239437371492,.5521438121795654,.3869673013687134,0,2,0,0,10,9,-1,0,3,10,3,3,-.0010585320414975286,.3628678023815155,.5320926904678345,0,2,13,14,1,6,-1,13,16,1,2,3,14935660146875307e-21,.4632444977760315,.5363323092460632,0,2,0,2,3,6,-1,0,4,3,2,3,.005253770854324102,.5132231712341309,.3265708982944489,0,2,8,14,4,3,-1,8,15,4,1,3,-.008233802393078804,.6693689823150635,.4774140119552612,0,2,6,14,1,6,-1,6,16,1,2,3,2186681012972258e-20,.405386209487915,.5457931160926819,0,2,9,15,2,3,-1,9,16,2,1,3,-.0038150229956954718,.645499587059021,.4793178141117096,0,2,6,4,3,3,-1,7,4,1,3,3,.0011105879675596952,.5270407199859619,.3529678881168366,0,2,9,0,11,3,-1,9,1,11,1,3,-.005770768970251083,.3803547024726868,.5352957844734192,0,2,0,6,20,3,-1,0,7,20,1,3,-.003015833906829357,.533940315246582,.3887133002281189,0,2,10,1,1,2,-1,10,2,1,1,2,-.0008545368909835815,.3564616143703461,.5273603796958923,0,2,9,6,2,6,-1,10,6,1,6,2,.0110505102202296,.4671907126903534,.6849737763404846,0,2,5,8,12,1,-1,9,8,4,1,3,.0426058396697044,.51514732837677,.0702200904488564,0,2,3,8,12,1,-1,7,8,4,1,3,-.0030781750101596117,.3041661083698273,.5152602195739746,0,2,9,7,3,5,-1,10,7,1,5,3,-.005481572821736336,.6430295705795288,.4897229969501495,0,2,3,9,6,2,-1,6,9,3,2,2,.003188186092302203,.5307493209838867,.3826209902763367,0,2,12,9,3,3,-1,12,10,3,1,3,.00035947180003859103,.4650047123432159,.5421904921531677,0,2,7,0,6,1,-1,9,0,2,1,3,-.004070503171533346,.2849679887294769,.5079116225242615,0,2,12,9,3,3,-1,12,10,3,1,3,-.0145941702648997,.2971645891666412,.5128461718559265,0,2,7,10,2,1,-1,8,10,1,1,2,-.00011947689927183092,.563109815120697,.4343082010746002,0,2,6,4,9,13,-1,9,4,3,13,3,-.0006934464909136295,.4403578042984009,.5359959006309509,0,2,6,8,4,2,-1,6,9,4,1,2,14834799912932795e-21,.3421008884906769,.5164697766304016,0,2,16,2,4,6,-1,16,2,2,6,2,.009029698558151722,.4639343023300171,.6114075183868408,0,2,0,17,6,3,-1,0,18,6,1,3,-.008064081892371178,.2820158898830414,.5075494050979614,0,2,10,10,3,10,-1,10,15,3,5,2,.0260621197521687,.5208905935287476,.2688778042793274,0,2,8,7,3,5,-1,9,7,1,5,3,.0173146594315767,.4663713872432709,.6738539934158325,0,2,10,4,4,3,-1,10,4,2,3,2,.0226666405797005,.5209349989891052,.2212723940610886,0,2,8,4,3,8,-1,9,4,1,8,3,-.002196592977270484,.6063101291656494,.4538190066814423,0,2,6,6,9,13,-1,9,6,3,13,3,-.009528247639536858,.4635204970836639,.5247430801391602,0,3,6,0,8,12,-1,6,0,4,6,2,10,6,4,6,2,.00809436198323965,.5289440155029297,.3913882076740265,0,2,14,2,6,8,-1,16,2,2,8,3,-.0728773325681686,.7752001881599426,.4990234971046448,0,2,6,0,3,6,-1,7,0,1,6,3,-.006900952197611332,.2428039014339447,.5048090219497681,0,2,14,2,6,8,-1,16,2,2,8,3,-.0113082397729158,.5734364986419678,.4842376112937927,0,2,0,5,6,6,-1,0,8,6,3,2,.0596132017672062,.5029836297035217,.2524977028369904,0,3,9,12,6,2,-1,12,12,3,1,2,9,13,3,1,2,-.0028624620754271746,.6073045134544373,.4898459911346436,0,2,8,17,3,2,-1,9,17,1,2,3,.00447814492508769,.5015289187431335,.2220316976308823,0,3,11,6,2,2,-1,12,6,1,1,2,11,7,1,1,2,-.001751324045471847,.6614428758621216,.4933868944644928,0,2,1,9,18,2,-1,7,9,6,2,3,.0401634201407433,.5180878043174744,.3741044998168945,0,3,11,6,2,2,-1,12,6,1,1,2,11,7,1,1,2,.0003476894926279783,.4720416963100433,.5818032026290894,0,2,3,4,12,8,-1,7,4,4,8,3,.00265516503714025,.3805010914802551,.5221335887908936,0,2,13,11,5,3,-1,13,12,5,1,3,-.008770627900958061,.294416606426239,.5231295228004456,0,2,9,10,2,3,-1,9,11,2,1,3,-.005512209143489599,.7346177101135254,.4722816944122315,0,2,14,7,2,3,-1,14,7,1,3,2,.0006867204210720956,.5452876091003418,.424241304397583,0,2,5,4,1,3,-1,5,5,1,1,3,.0005601966986432672,.439886212348938,.5601285099983215,0,2,13,4,2,3,-1,13,5,2,1,3,.0024143769405782223,.4741686880588532,.6136621832847595,0,2,5,4,2,3,-1,5,5,2,1,3,-.0015680900542065501,.604455292224884,.4516409933567047,0,2,9,8,2,3,-1,9,9,2,1,3,-.0036827491130679846,.2452459037303925,.5294982194900513,0,2,8,9,2,2,-1,8,10,2,1,2,-.000294091907562688,.3732838034629822,.5251451134681702,0,2,15,14,1,4,-1,15,16,1,2,2,.00042847759323194623,.5498809814453125,.4065535068511963,0,2,3,12,2,2,-1,3,13,2,1,2,-.004881707020103931,.2139908969402313,.4999957084655762,0,3,12,15,2,2,-1,13,15,1,1,2,12,16,1,1,2,.00027272020815871656,.465028703212738,.581342875957489,0,2,9,13,2,2,-1,9,14,2,1,2,.00020947199664078653,.4387486875057221,.5572792887687683,0,2,4,11,14,9,-1,4,14,14,3,3,.0485011897981167,.5244972705841064,.3212889134883881,0,2,7,13,4,3,-1,7,14,4,1,3,-.004516641143709421,.605681300163269,.4545882046222687,0,2,15,14,1,4,-1,15,16,1,2,2,-.0122916800901294,.2040929049253464,.5152214169502258,0,2,4,14,1,4,-1,4,16,1,2,2,.0004854967992287129,.5237604975700378,.3739503026008606,0,2,14,0,6,13,-1,16,0,2,13,3,.0305560491979122,.4960533976554871,.5938246250152588,0,3,4,1,2,12,-1,4,1,1,6,2,5,7,1,6,2,-.00015105320198927075,.5351303815841675,.4145204126834869,0,3,11,14,6,6,-1,14,14,3,3,2,11,17,3,3,2,.0024937440175563097,.4693366885185242,.5514941215515137,0,3,3,14,6,6,-1,3,14,3,3,2,6,17,3,3,2,-.012382130138576,.6791396737098694,.4681667983531952,0,2,14,17,3,2,-1,14,18,3,1,2,-.005133346188813448,.3608739078044891,.5229160189628601,0,2,3,17,3,2,-1,3,18,3,1,2,.0005191927775740623,.5300073027610779,.3633613884449005,0,2,14,0,6,13,-1,16,0,2,13,3,.1506042033433914,.515731692314148,.2211782038211823,0,2,0,0,6,13,-1,2,0,2,13,3,.007714414969086647,.4410496950149536,.5776609182357788,0,2,10,10,7,6,-1,10,12,7,2,3,.009444352239370346,.5401855111122131,.375665009021759,0,3,6,15,2,2,-1,6,15,1,1,2,7,16,1,1,2,.00025006249779835343,.4368270933628082,.5607374906539917,0,3,6,11,8,6,-1,10,11,4,3,2,6,14,4,3,2,-.003307715058326721,.4244799017906189,.551823079586029,0,3,7,6,2,2,-1,7,6,1,1,2,8,7,1,1,2,.0007404891075566411,.4496962130069733,.5900576710700989,0,3,2,2,16,6,-1,10,2,8,3,2,2,5,8,3,2,.0440920516848564,.5293493270874023,.3156355023384094,0,2,5,4,3,3,-1,5,5,3,1,3,.0033639909233897924,.4483296871185303,.5848662257194519,0,2,11,7,3,10,-1,11,12,3,5,2,-.003976007923483849,.4559507071971893,.5483639240264893,0,2,6,7,3,10,-1,6,12,3,5,2,.0027716930489987135,.534178614616394,.3792484104633331,0,2,10,7,3,2,-1,11,7,1,2,3,-.00024123019829858094,.5667188763618469,.4576973021030426,0,2,8,12,4,2,-1,8,13,4,1,2,.0004942566738463938,.4421244859695435,.5628787279129028,0,2,10,1,1,3,-1,10,2,1,1,3,-.0003887646889779717,.4288370907306671,.5391063094139099,0,3,1,2,4,18,-1,1,2,2,9,2,3,11,2,9,2,-.0500488989055157,.6899513006210327,.4703742861747742,0,2,12,4,4,12,-1,12,10,4,6,2,-.0366354808211327,.2217779010534287,.5191826224327087,0,2,0,0,1,6,-1,0,2,1,2,3,.0024273579474538565,.5136224031448364,.3497397899627686,0,2,9,11,2,3,-1,9,12,2,1,3,.001955803018063307,.4826192855834961,.640838086605072,0,2,8,7,4,3,-1,8,8,4,1,3,-.0017494610510766506,.3922835886478424,.5272685289382935,0,2,10,7,3,2,-1,11,7,1,2,3,.0139550799503922,.507820188999176,.8416504859924316,0,2,7,7,3,2,-1,8,7,1,2,3,-.00021896739781368524,.5520489811897278,.4314234852790833,0,2,9,4,6,1,-1,11,4,2,1,3,-.0015131309628486633,.3934605121612549,.5382571220397949,0,2,8,7,2,3,-1,9,7,1,3,2,-.004362280014902353,.7370628714561462,.4736475944519043,0,3,12,7,8,6,-1,16,7,4,3,2,12,10,4,3,2,.0651605874300003,.5159279704093933,.328159511089325,0,3,0,7,8,6,-1,0,7,4,3,2,4,10,4,3,2,-.0023567399475723505,.3672826886177063,.5172886252403259,0,3,18,2,2,10,-1,19,2,1,5,2,18,7,1,5,2,.0151466596871614,.5031493902206421,.6687604188919067,0,2,0,2,6,4,-1,3,2,3,4,2,-.0228509604930878,.676751971244812,.4709596931934357,0,2,9,4,6,1,-1,11,4,2,1,3,.004886765033006668,.5257998108863831,.4059878885746002,0,3,7,15,2,2,-1,7,15,1,1,2,8,16,1,1,2,.0017619599821045995,.4696272909641266,.6688278913497925,0,2,11,13,1,6,-1,11,16,1,3,2,-.0012942519970238209,.4320712983608246,.5344281792640686,0,2,8,13,1,6,-1,8,16,1,3,2,.0109299495816231,.4997706115245819,.1637486070394516,0,2,14,3,2,1,-1,14,3,1,1,2,2995848990394734e-20,.4282417893409729,.5633224248886108,0,2,8,15,2,3,-1,8,16,2,1,3,-.0065884361974895,.677212119102478,.4700526893138886,0,2,12,15,7,4,-1,12,17,7,2,2,.0032527779694646597,.531339704990387,.4536148905754089,0,2,4,14,12,3,-1,4,15,12,1,3,-.00404357397928834,.5660061836242676,.4413388967514038,0,2,10,3,3,2,-1,11,3,1,2,3,-.0012523540062829852,.3731913864612579,.5356451869010925,0,2,4,12,2,2,-1,4,13,2,1,2,.00019246719602961093,.5189986228942871,.3738811016082764,0,2,10,11,4,6,-1,10,14,4,3,2,-.038589671254158,.2956373989582062,.51888108253479,0,3,7,13,2,2,-1,7,13,1,1,2,8,14,1,1,2,.0001548987056594342,.4347135126590729,.5509533286094666,0,3,4,11,14,4,-1,11,11,7,2,2,4,13,7,2,2,-.0337638482451439,.3230330049991608,.5195475816726685,0,2,1,18,18,2,-1,7,18,6,2,3,-.008265706710517406,.5975489020347595,.4552114009857178,0,3,11,18,2,2,-1,12,18,1,1,2,11,19,1,1,2,14481440302915871e-21,.4745678007602692,.5497426986694336,0,3,7,18,2,2,-1,7,18,1,1,2,8,19,1,1,2,14951299817766994e-21,.4324473142623901,.5480644106864929,0,2,12,18,8,2,-1,12,19,8,1,2,-.018741799518466,.1580052971839905,.517853319644928,0,2,7,14,6,2,-1,7,15,6,1,2,.0017572239739820361,.4517636895179749,.5773764252662659,0,3,8,12,4,8,-1,10,12,2,4,2,8,16,2,4,2,-.0031391119118779898,.4149647951126099,.5460842251777649,0,2,4,9,3,3,-1,4,10,3,1,3,6665677938144654e-20,.4039090871810913,.5293084979057312,0,2,7,10,6,2,-1,9,10,2,2,3,.006774342153221369,.4767651855945587,.612195611000061,0,2,5,0,4,15,-1,7,0,2,15,2,-.0073868161998689175,.3586258888244629,.5187280774116516,0,2,8,6,12,14,-1,12,6,4,14,3,.0140409301966429,.4712139964103699,.5576155781745911,0,2,5,16,3,3,-1,5,17,3,1,3,-.005525832995772362,.2661027014255524,.5039281249046326,0,2,8,1,12,19,-1,12,1,4,19,3,.3868423998355866,.5144339799880981,.2525899112224579,0,2,3,0,3,2,-1,3,1,3,1,2,.0001145924034062773,.4284994900226593,.5423371195793152,0,2,10,12,4,5,-1,10,12,2,5,2,-.0184675697237253,.3885835111141205,.5213062167167664,0,2,6,12,4,5,-1,8,12,2,5,2,-.0004590701137203723,.541256308555603,.4235909879207611,0,3,11,11,2,2,-1,12,11,1,1,2,11,12,1,1,2,.0012527540093287826,.4899305105209351,.6624091267585754,0,2,0,2,3,6,-1,0,4,3,2,3,.001491060946136713,.5286778211593628,.4040051996707916,0,3,11,11,2,2,-1,12,11,1,1,2,11,12,1,1,2,-.0007543556275777519,.6032990217208862,.4795120060443878,0,2,7,6,4,10,-1,7,11,4,5,2,-.0069478838704526424,.408440113067627,.5373504161834717,0,3,11,11,2,2,-1,12,11,1,1,2,11,12,1,1,2,.0002809292054735124,.4846062958240509,.5759382247924805,0,2,2,13,5,2,-1,2,14,5,1,2,.0009607371757738292,.5164741277694702,.3554979860782623,0,3,11,11,2,2,-1,12,11,1,1,2,11,12,1,1,2,-.0002688392996788025,.5677582025527954,.4731765985488892,0,3,7,11,2,2,-1,7,11,1,1,2,8,12,1,1,2,.0021599370520561934,.4731487035751343,.7070567011833191,0,2,14,13,3,3,-1,14,14,3,1,3,.005623530130833387,.5240243077278137,.2781791985034943,0,2,3,13,3,3,-1,3,14,3,1,3,-.005024399142712355,.2837013900279999,.5062304139137268,0,2,9,14,2,3,-1,9,15,2,1,3,-.009761163964867592,.7400717735290527,.4934569001197815,0,2,8,7,3,3,-1,8,8,3,1,3,.004151510074734688,.5119131207466125,.3407008051872253,0,2,13,5,3,3,-1,13,6,3,1,3,.006246508099138737,.4923788011074066,.6579058766365051,0,2,0,9,5,3,-1,0,10,5,1,3,-.007059747818857431,.2434711009263992,.503284215927124,0,2,13,5,3,3,-1,13,6,3,1,3,-.0020587709732353687,.590031087398529,.469508707523346,0,3,9,12,2,8,-1,9,12,1,4,2,10,16,1,4,2,-.0024146060459315777,.3647317886352539,.5189201831817627,0,3,11,7,2,2,-1,12,7,1,1,2,11,8,1,1,2,-.0014817609917372465,.6034948229789734,.4940128028392792,0,2,0,16,6,4,-1,3,16,3,4,2,-.0063016400672495365,.5818989872932434,.4560427963733673,0,2,10,6,2,3,-1,10,7,2,1,3,.00347634288482368,.5217475891113281,.3483993113040924,0,2,9,5,2,6,-1,9,7,2,2,3,-.0222508702427149,.2360700070858002,.5032082796096802,0,2,12,15,8,4,-1,12,15,4,4,2,-.030612550675869,.6499186754226685,.4914919137954712,0,2,0,14,8,6,-1,4,14,4,6,2,.013057479634881,.4413323104381561,.5683764219284058,0,2,9,0,3,2,-1,10,0,1,2,3,-.0006009574281051755,.4359731078147888,.5333483219146729,0,2,4,15,4,2,-1,6,15,2,2,2,-.0004151425091549754,.550406277179718,.4326060116291046,0,2,12,7,3,13,-1,13,7,1,13,3,-.013776290230453,.4064112901687622,.5201548933982849,0,2,5,7,3,13,-1,6,7,1,13,3,-.0322965085506439,.0473519712686539,.4977194964885712,0,2,9,6,3,9,-1,9,9,3,3,3,.0535569787025452,.4881733059883118,.666693925857544,0,2,4,4,7,12,-1,4,10,7,6,2,.008188954554498196,.5400037169456482,.4240820109844208,0,3,12,12,2,2,-1,13,12,1,1,2,12,13,1,1,2,.00021055320394225419,.4802047908306122,.5563852787017822,0,3,6,12,2,2,-1,6,12,1,1,2,7,13,1,1,2,-.00243827304802835,.7387793064117432,.4773685038089752,0,3,8,9,4,2,-1,10,9,2,1,2,8,10,2,1,2,.003283557016402483,.5288546085357666,.3171291947364807,0,3,3,6,2,2,-1,3,6,1,1,2,4,7,1,1,2,.00237295706756413,.4750812947750092,.7060170769691467,0,2,16,6,3,2,-1,16,7,3,1,2,-.0014541699783876538,.3811730146408081,.533073902130127,87.69602966308594,177,0,2,0,7,19,4,-1,0,9,19,2,2,.0557552389800549,.4019156992435455,.6806036829948425,0,2,10,2,10,1,-1,10,2,5,1,2,.002473024884238839,.3351148962974548,.5965719819068909,0,2,9,4,2,12,-1,9,10,2,6,2,-.00035031698644161224,.5557708144187927,.3482286930084229,0,2,12,18,4,1,-1,12,18,2,1,2,.0005416763015091419,.426085889339447,.5693380832672119,0,3,1,7,6,4,-1,1,7,3,2,2,4,9,3,2,2,.0007719367858953774,.3494240045547485,.5433688759803772,0,2,12,0,6,13,-1,14,0,2,13,3,-.0015999219613149762,.4028499126434326,.5484359264373779,0,2,2,0,6,13,-1,4,0,2,13,3,-.00011832080053864047,.3806901872158051,.5425465106964111,0,2,10,5,8,8,-1,10,9,8,4,2,.0003290903114248067,.262010008096695,.5429521799087524,0,2,8,3,2,5,-1,9,3,1,5,2,.0002951810893137008,.379976898431778,.5399264097213745,0,2,8,4,9,1,-1,11,4,3,1,3,9046671038959175e-20,.4433645009994507,.5440226197242737,0,2,3,4,9,1,-1,6,4,3,1,3,15007190086180344e-21,.3719654977321625,.5409119725227356,0,2,1,0,18,10,-1,7,0,6,10,3,.1393561065196991,.552539587020874,.4479042887687683,0,2,7,17,5,3,-1,7,18,5,1,3,.0016461990308016539,.4264501035213471,.5772169828414917,0,2,7,11,6,1,-1,9,11,2,1,3,.0004998443182557821,.4359526038169861,.5685871243476868,0,2,2,2,3,2,-1,2,3,3,1,2,-.001097128028050065,.3390136957168579,.5205408930778503,0,2,8,12,4,2,-1,8,13,4,1,2,.0006691989256069064,.4557456076145172,.598065972328186,0,2,6,10,3,6,-1,6,13,3,3,2,.0008647104259580374,.5134841203689575,.2944033145904541,0,2,11,4,2,4,-1,11,4,1,4,2,-.0002718259929679334,.3906578123569489,.5377181172370911,0,2,7,4,2,4,-1,8,4,1,4,2,3024949910468422e-20,.3679609894752502,.5225688815116882,0,2,9,6,2,4,-1,9,6,1,4,2,-.008522589690983295,.7293102145195007,.4892365038394928,0,2,6,13,8,3,-1,6,14,8,1,3,.0016705560265108943,.43453249335289,.5696138143539429,0,2,9,15,3,4,-1,10,15,1,4,3,-.0071433838456869125,.2591280043125153,.5225623846054077,0,2,9,2,2,17,-1,10,2,1,17,2,-.0163193698972464,.6922279000282288,.4651575982570648,0,2,7,0,6,1,-1,9,0,2,1,3,.004803426098078489,.5352262854576111,.3286302983760834,0,2,8,15,3,4,-1,9,15,1,4,3,-.0075421929359436035,.2040544003248215,.5034546256065369,0,2,7,13,7,3,-1,7,14,7,1,3,-.0143631100654602,.6804888844490051,.4889059066772461,0,2,8,16,3,3,-1,9,16,1,3,3,.0008906358852982521,.5310695767402649,.3895480930805206,0,2,6,2,8,10,-1,6,7,8,5,2,-.004406019113957882,.5741562843322754,.4372426867485046,0,2,2,5,8,8,-1,2,9,8,4,2,-.0001886254030978307,.2831785976886749,.5098205208778381,0,2,14,16,2,2,-1,14,17,2,1,2,-.0037979281041771173,.3372507989406586,.5246580243110657,0,2,4,16,2,2,-1,4,17,2,1,2,.00014627049677073956,.5306674242019653,.391171008348465,0,2,10,11,4,6,-1,10,14,4,3,2,-49164638767251745e-21,.5462496280670166,.3942720890045166,0,2,6,11,4,6,-1,6,14,4,3,2,-.0335825011134148,.2157824039459229,.5048211812973022,0,2,10,14,1,3,-1,10,15,1,1,3,-.0035339309833943844,.6465312242507935,.4872696995735169,0,2,8,14,4,3,-1,8,15,4,1,3,.005014411173760891,.4617668092250824,.6248074769973755,0,3,10,0,4,6,-1,12,0,2,3,2,10,3,2,3,2,.0188173707574606,.5220689177513123,.2000052034854889,0,2,0,3,20,2,-1,0,4,20,1,2,-.001343433978036046,.4014537930488586,.53016197681427,0,3,12,0,8,2,-1,16,0,4,1,2,12,1,4,1,2,.001755796023644507,.4794039130210877,.5653169751167297,0,2,2,12,10,8,-1,2,16,10,4,2,-.0956374630331993,.2034195065498352,.5006706714630127,0,3,17,7,2,10,-1,18,7,1,5,2,17,12,1,5,2,-.0222412291914225,.7672473192214966,.5046340227127075,0,3,1,7,2,10,-1,1,7,1,5,2,2,12,1,5,2,-.0155758196488023,.7490342259407043,.4755851030349731,0,2,15,10,3,6,-1,15,12,3,2,3,.005359911825507879,.5365303754806519,.4004670977592468,0,2,4,4,6,2,-1,6,4,2,2,3,-.0217634998261929,.0740154981613159,.4964174926280975,0,2,0,5,20,6,-1,0,7,20,2,3,-.165615901350975,.2859103083610535,.5218086242675781,0,3,0,0,8,2,-1,0,0,4,1,2,4,1,4,1,2,.0001646132004680112,.4191615879535675,.5380793213844299,0,2,1,0,18,4,-1,7,0,6,4,3,-.008907750248908997,.6273192763328552,.4877404868602753,0,2,1,13,6,2,-1,1,14,6,1,2,.0008634644909761846,.5159940719604492,.3671025931835175,0,2,10,8,3,4,-1,11,8,1,4,3,-.0013751760125160217,.5884376764297485,.4579083919525147,0,2,6,1,6,1,-1,8,1,2,1,3,-.0014081239933148026,.3560509979724884,.5139945149421692,0,2,8,14,4,3,-1,8,15,4,1,3,-.003934288863092661,.5994288921356201,.466427206993103,0,2,1,6,18,2,-1,10,6,9,2,2,-.0319669283926487,.3345462083816528,.5144183039665222,0,2,15,11,1,2,-1,15,12,1,1,2,-15089280168467667e-21,.5582656264305115,.441405713558197,0,2,6,5,1,2,-1,6,6,1,1,2,.0005199447041377425,.4623680114746094,.6168993711471558,0,2,13,4,1,3,-1,13,5,1,1,3,-.0034220460802316666,.6557074785232544,.4974805116653442,0,2,2,15,1,2,-1,2,16,1,1,2,.00017723299970384687,.5269501805305481,.3901908099651337,0,2,12,4,4,3,-1,12,5,4,1,3,.0015716759953647852,.4633373022079468,.5790457725524902,0,2,0,0,7,3,-1,0,1,7,1,3,-.00890413299202919,.2689608037471771,.5053591132164001,0,2,9,12,6,2,-1,9,12,3,2,2,.00040677518700249493,.5456603169441223,.4329898953437805,0,2,5,4,2,3,-1,5,5,2,1,3,.0067604780197143555,.4648993909358978,.6689761877059937,0,2,18,4,2,3,-1,18,5,2,1,3,.0029100088868290186,.5309703946113586,.3377839922904968,0,2,3,0,8,6,-1,3,2,8,2,3,.0013885459629818797,.4074738919734955,.5349133014678955,0,3,0,2,20,6,-1,10,2,10,3,2,0,5,10,3,2,-.0767642632126808,.1992176026105881,.522824227809906,0,2,4,7,2,4,-1,5,7,1,4,2,-.00022688310127705336,.5438501834869385,.4253072142601013,0,2,3,10,15,2,-1,8,10,5,2,3,-.006309415213763714,.4259178936481476,.5378909707069397,0,2,3,0,12,11,-1,9,0,6,11,2,-.1100727990269661,.6904156804084778,.4721749126911163,0,2,13,0,2,6,-1,13,0,1,6,2,.0002861965913325548,.4524914920330048,.5548306107521057,0,2,0,19,2,1,-1,1,19,1,1,2,2942532955785282e-20,.5370373725891113,.4236463904380798,0,3,16,10,4,10,-1,18,10,2,5,2,16,15,2,5,2,-.0248865708708763,.6423557996749878,.4969303905963898,0,2,4,8,10,3,-1,4,9,10,1,3,.0331488512456417,.4988475143909454,.1613811999559403,0,2,14,12,3,3,-1,14,13,3,1,3,.0007849169196560979,.541602611541748,.4223009049892426,0,3,0,10,4,10,-1,0,10,2,5,2,2,15,2,5,2,.004708718974143267,.4576328992843628,.6027557849884033,0,2,18,3,2,6,-1,18,5,2,2,3,.0024144479539245367,.530897319316864,.4422498941421509,0,2,6,6,1,3,-1,6,7,1,1,3,.0019523180089890957,.4705634117126465,.666332483291626,0,2,7,7,7,2,-1,7,8,7,1,2,.0013031980488449335,.4406126141548157,.5526962280273438,0,2,0,3,2,6,-1,0,5,2,2,3,.004473549779504538,.5129023790359497,.3301498889923096,0,2,11,1,3,1,-1,12,1,1,1,3,-.002665286883711815,.3135471045970917,.5175036191940308,0,2,5,0,2,6,-1,6,0,1,6,2,.0001366677024634555,.4119370877742767,.530687689781189,0,2,1,1,18,14,-1,7,1,6,14,3,-.0171264503151178,.6177806258201599,.4836578965187073,0,2,4,6,8,3,-1,8,6,4,3,2,-.0002660143072716892,.3654330968856812,.5169736742973328,0,2,9,12,6,2,-1,9,12,3,2,2,-.022932380437851,.349091500043869,.5163992047309875,0,2,5,12,6,2,-1,8,12,3,2,2,.0023316550068557262,.5166299939155579,.3709389865398407,0,2,10,7,3,5,-1,11,7,1,5,3,.016925660893321,.501473605632782,.8053988218307495,0,2,7,7,3,5,-1,8,7,1,5,3,-.008985882624983788,.6470788717269897,.465702086687088,0,2,13,0,3,10,-1,14,0,1,10,3,-.0118746999651194,.3246378898620606,.5258755087852478,0,2,4,11,3,2,-1,4,12,3,1,2,.00019350569345988333,.5191941857337952,.3839643895626068,0,2,17,3,3,6,-1,18,3,1,6,3,.005871349014341831,.4918133914470673,.6187043190002441,0,2,1,8,18,10,-1,1,13,18,5,2,-.2483879029750824,.1836802959442139,.4988150000572205,0,2,13,0,3,10,-1,14,0,1,10,3,.0122560001909733,.5227053761482239,.3632029891014099,0,2,9,14,2,3,-1,9,15,2,1,3,.0008399017970077693,.4490250051021576,.5774148106575012,0,2,16,3,3,7,-1,17,3,1,7,3,.002540736924856901,.4804787039756775,.5858299136161804,0,2,4,0,3,10,-1,5,0,1,10,3,-.0148224299773574,.2521049976348877,.5023537278175354,0,2,16,3,3,7,-1,17,3,1,7,3,-.005797395948320627,.5996695756912231,.4853715002536774,0,2,0,9,1,2,-1,0,10,1,1,2,.000726621481589973,.5153716802597046,.3671779930591583,0,2,18,1,2,10,-1,18,1,1,10,2,-.0172325801104307,.6621719002723694,.4994656145572662,0,2,0,1,2,10,-1,1,1,1,10,2,.007862408645451069,.4633395075798035,.6256101727485657,0,2,10,16,3,4,-1,11,16,1,4,3,-.004734362009912729,.3615573048591614,.5281885266304016,0,2,2,8,3,3,-1,3,8,1,3,3,.0008304847870022058,.4442889094352722,.5550957918167114,0,3,11,0,2,6,-1,12,0,1,3,2,11,3,1,3,2,.00766021991148591,.5162935256958008,.2613354921340942,0,3,7,0,2,6,-1,7,0,1,3,2,8,3,1,3,2,-.004104837775230408,.2789632081985474,.5019031763076782,0,2,16,3,3,7,-1,17,3,1,7,3,.004851257894188166,.4968984127044678,.5661668181419373,0,2,1,3,3,7,-1,2,3,1,7,3,.0009989645332098007,.4445607960224152,.5551813244819641,0,2,14,1,6,16,-1,16,1,2,16,3,-.2702363133430481,.0293882098048925,.515131413936615,0,2,0,1,6,16,-1,2,1,2,16,3,-.0130906803533435,.5699399709701538,.4447459876537323,0,3,2,0,16,8,-1,10,0,8,4,2,2,4,8,4,2,-.009434279054403305,.4305466115474701,.5487895011901855,0,2,6,8,5,3,-1,6,9,5,1,3,-.0015482039889320731,.3680317103862763,.512808084487915,0,2,9,7,3,3,-1,10,7,1,3,3,.005374613218009472,.4838916957378388,.6101555824279785,0,2,8,8,4,3,-1,8,9,4,1,3,.0015786769799888134,.5325223207473755,.4118548035621643,0,2,9,6,2,4,-1,9,6,1,4,2,.003685605013743043,.4810948073863983,.6252303123474121,0,2,0,7,15,1,-1,5,7,5,1,3,.009388701990246773,.520022988319397,.3629410862922669,0,2,8,2,7,9,-1,8,5,7,3,3,.0127926301211119,.4961709976196289,.673801600933075,0,3,1,7,16,4,-1,1,7,8,2,2,9,9,8,2,2,-.003366104094311595,.4060279130935669,.5283598899841309,0,2,6,12,8,2,-1,6,13,8,1,2,.00039771420415490866,.4674113988876343,.5900775194168091,0,2,8,11,3,3,-1,8,12,3,1,3,.0014868030557408929,.4519116878509522,.6082053780555725,0,3,4,5,14,10,-1,11,5,7,5,2,4,10,7,5,2,-.0886867493391037,.2807899117469788,.5180991888046265,0,2,4,12,3,2,-1,4,13,3,1,2,-7429611287079751e-20,.5295584201812744,.408762514591217,0,2,9,11,6,1,-1,11,11,2,1,3,-14932939848222304e-21,.5461400151252747,.4538542926311493,0,2,4,9,7,6,-1,4,11,7,2,3,.005916223861277103,.5329161286354065,.4192134141921997,0,2,7,10,6,3,-1,7,11,6,1,3,.001114164013415575,.4512017965316773,.5706217288970947,0,2,9,11,2,2,-1,9,12,2,1,2,8924936264520511e-20,.4577805995941162,.5897638201713562,0,2,0,5,20,6,-1,0,7,20,2,3,.0025319510605186224,.5299603939056396,.3357639014720917,0,2,6,4,6,1,-1,8,4,2,1,3,.0124262003228068,.4959059059619904,.1346601992845535,0,2,9,11,6,1,-1,11,11,2,1,3,.0283357501029968,.5117079019546509,.0006104363710619509,0,2,5,11,6,1,-1,7,11,2,1,3,.006616588216274977,.4736349880695343,.7011628150939941,0,2,10,16,3,4,-1,11,16,1,4,3,.008046876639127731,.5216417908668518,.3282819986343384,0,2,8,7,3,3,-1,9,7,1,3,3,-.001119398046284914,.5809860825538635,.4563739001750946,0,2,2,12,16,8,-1,2,16,16,4,2,.0132775902748108,.5398362278938293,.4103901088237763,0,2,0,15,15,2,-1,0,16,15,1,2,.0004879473999608308,.424928605556488,.5410590767860413,0,2,15,4,5,6,-1,15,6,5,2,3,.0112431701272726,.526996374130249,.3438215851783752,0,2,9,5,2,4,-1,10,5,1,4,2,-.0008989666821435094,.5633075833320618,.4456613063812256,0,2,8,10,9,6,-1,8,12,9,2,3,.006667715962976217,.5312889218330383,.4362679123878479,0,2,2,19,15,1,-1,7,19,5,1,3,.0289472993463278,.4701794981956482,.657579779624939,0,2,10,16,3,4,-1,11,16,1,4,3,-.0234000496566296,0,.5137398838996887,0,2,0,15,20,4,-1,0,17,20,2,2,-.0891170501708984,.0237452797591686,.4942430853843689,0,2,10,16,3,4,-1,11,16,1,4,3,-.0140546001493931,.3127323091030121,.511751115322113,0,2,7,16,3,4,-1,8,16,1,4,3,.008123939856886864,.50090491771698,.2520025968551636,0,2,9,16,3,3,-1,9,17,3,1,3,-.004996465053409338,.6387143731117249,.4927811920642853,0,2,8,11,4,6,-1,8,14,4,3,2,.0031253970228135586,.5136849880218506,.3680452108383179,0,2,9,6,2,12,-1,9,10,2,4,3,.006766964215785265,.5509843826293945,.4363631904125214,0,2,8,17,4,3,-1,8,18,4,1,3,-.002371144015341997,.6162335276603699,.4586946964263916,0,3,9,18,8,2,-1,13,18,4,1,2,9,19,4,1,2,-.005352279171347618,.6185457706451416,.4920490980148315,0,2,1,18,8,2,-1,1,19,8,1,2,-.0159688591957092,.1382617950439453,.4983252882957459,0,2,13,5,6,15,-1,15,5,2,15,3,.004767606034874916,.4688057899475098,.5490046143531799,0,2,9,8,2,2,-1,9,9,2,1,2,-.002471469109877944,.2368514984846115,.5003952980041504,0,2,9,5,2,3,-1,9,5,1,3,2,-.0007103378884494305,.5856394171714783,.4721533060073853,0,2,1,5,6,15,-1,3,5,2,15,3,-.1411755979061127,.0869000628590584,.4961591064929962,0,3,4,1,14,8,-1,11,1,7,4,2,4,5,7,4,2,.1065180972218514,.5138837099075317,.1741005033254623,0,3,2,4,4,16,-1,2,4,2,8,2,4,12,2,8,2,-.0527447499334812,.7353636026382446,.4772881865501404,0,2,12,4,3,12,-1,12,10,3,6,2,-.00474317604675889,.3884406089782715,.5292701721191406,0,3,4,5,10,12,-1,4,5,5,6,2,9,11,5,6,2,.0009967676596716046,.5223492980003357,.4003424048423767,0,2,9,14,2,3,-1,9,15,2,1,3,.00802841316908598,.4959106147289276,.7212964296340942,0,2,5,4,2,3,-1,5,5,2,1,3,.0008602585876360536,.4444884061813355,.55384761095047,0,3,12,2,4,10,-1,14,2,2,5,2,12,7,2,5,2,.0009319150121882558,.539837121963501,.4163244068622589,0,2,6,4,7,3,-1,6,5,7,1,3,-.002508206060156226,.5854265093803406,.456250011920929,0,3,2,0,18,2,-1,11,0,9,1,2,2,1,9,1,2,-.0021378761157393456,.4608069062232971,.5280259251594543,0,3,0,0,18,2,-1,0,0,9,1,2,9,1,9,1,2,-.002154604997485876,.3791126906871796,.5255997180938721,0,3,13,13,4,6,-1,15,13,2,3,2,13,16,2,3,2,-.007621400989592075,.5998609066009521,.4952073991298676,0,3,3,13,4,6,-1,3,13,2,3,2,5,16,2,3,2,.002205536002293229,.4484206140041351,.5588530898094177,0,2,10,12,2,6,-1,10,15,2,3,2,.0012586950324475765,.5450747013092041,.4423840939998627,0,3,5,9,10,10,-1,5,9,5,5,2,10,14,5,5,2,-.005092672072350979,.4118275046348572,.5263035893440247,0,3,11,4,4,2,-1,13,4,2,1,2,11,5,2,1,2,-.0025095739401876926,.5787907838821411,.4998494982719421,0,2,7,12,6,8,-1,10,12,3,8,2,-.0773275569081306,.8397865891456604,.481112003326416,0,3,12,2,4,10,-1,14,2,2,5,2,12,7,2,5,2,-.041485819965601,.240861102938652,.5176993012428284,0,2,8,11,2,1,-1,9,11,1,1,2,.00010355669655837119,.4355360865592957,.5417054295539856,0,2,10,5,1,12,-1,10,9,1,4,3,.0013255809899419546,.5453971028327942,.4894095063209534,0,2,0,11,6,9,-1,3,11,3,9,2,-.00805987324565649,.5771024227142334,.4577918946743012,0,3,12,2,4,10,-1,14,2,2,5,2,12,7,2,5,2,.019058620557189,.5169867873191833,.3400475084781647,0,3,4,2,4,10,-1,4,2,2,5,2,6,7,2,5,2,-.0350578911602497,.2203243970870972,.5000503063201904,0,3,11,4,4,2,-1,13,4,2,1,2,11,5,2,1,2,.005729605909436941,.5043408274650574,.6597570776939392,0,2,0,14,6,3,-1,0,15,6,1,3,-.0116483299061656,.2186284959316254,.4996652901172638,0,3,11,4,4,2,-1,13,4,2,1,2,11,5,2,1,2,.0014544479781761765,.5007681846618652,.5503727793693542,0,2,6,1,3,2,-1,7,1,1,2,3,-.00025030909455381334,.4129841029644013,.524167001247406,0,3,11,4,4,2,-1,13,4,2,1,2,11,5,2,1,2,-.000829072727356106,.541286826133728,.4974496066570282,0,3,5,4,4,2,-1,5,4,2,1,2,7,5,2,1,2,.0010862209601327777,.460552990436554,.5879228711128235,0,3,13,0,2,12,-1,14,0,1,6,2,13,6,1,6,2,.0002000050008064136,.5278854966163635,.4705209136009216,0,2,6,0,3,10,-1,7,0,1,10,3,.0029212920926511288,.5129609704017639,.375553697347641,0,2,3,0,17,8,-1,3,4,17,4,2,.0253874007612467,.4822691977024078,.5790768265724182,0,2,0,4,20,4,-1,0,6,20,2,2,-.00319684692658484,.5248395204544067,.3962840139865875,90.25334930419922,182,0,2,0,3,8,2,-1,4,3,4,2,2,.005803173873573542,.3498983979225159,.596198320388794,0,2,8,11,4,3,-1,8,12,4,1,3,-.009000306949019432,.6816636919975281,.4478552043437958,0,3,5,7,6,4,-1,5,7,3,2,2,8,9,3,2,2,-.00115496595390141,.5585706233978271,.3578251004219055,0,2,8,3,4,9,-1,8,6,4,3,3,-.0011069850297644734,.5365036129951477,.3050428032875061,0,2,8,15,1,4,-1,8,17,1,2,2,.00010308309720130637,.363909512758255,.5344635844230652,0,2,4,5,12,7,-1,8,5,4,7,3,-.005098483990877867,.2859157025814056,.5504264831542969,0,3,4,2,4,10,-1,4,2,2,5,2,6,7,2,5,2,.0008257220033556223,.5236523747444153,.3476041853427887,0,2,3,0,17,2,-1,3,1,17,1,2,.009978332556784153,.4750322103500366,.621964693069458,0,2,2,2,16,15,-1,2,7,16,5,3,-.0374025292694569,.334337592124939,.527806282043457,0,2,15,2,5,2,-1,15,3,5,1,2,.0048548257909715176,.5192180871963501,.3700444102287293,0,2,9,3,2,2,-1,10,3,1,2,2,-.001866447040811181,.2929843962192535,.5091944932937622,0,2,4,5,16,15,-1,4,10,16,5,3,.0168888904154301,.3686845898628235,.5431225895881653,0,2,7,13,5,6,-1,7,16,5,3,2,-.005837262142449617,.3632183969020844,.5221335887908936,0,2,10,7,3,2,-1,11,7,1,2,3,-.00147137395106256,.5870683789253235,.4700650870800018,0,2,8,3,3,1,-1,9,3,1,1,3,-.0011522950371727347,.3195894956588745,.5140954256057739,0,2,9,16,3,3,-1,9,17,3,1,3,-.004256030078977346,.6301859021186829,.4814921021461487,0,2,0,2,5,2,-1,0,3,5,1,2,-.006737829186022282,.1977048069238663,.5025808215141296,0,2,12,5,4,3,-1,12,6,4,1,3,.0113826701417565,.495413213968277,.6867045760154724,0,2,1,7,12,1,-1,5,7,4,1,3,.005179470870643854,.5164427757263184,.3350647985935211,0,2,7,5,6,14,-1,7,12,6,7,2,-.1174378991127014,.2315246015787125,.5234413743019104,0,3,0,0,8,10,-1,0,0,4,5,2,4,5,4,5,2,.0287034492939711,.4664297103881836,.6722521185874939,0,2,9,1,3,2,-1,10,1,1,2,3,.004823103081434965,.5220875144004822,.2723532915115356,0,2,8,1,3,2,-1,9,1,1,2,3,.0026798530016094446,.5079277157783508,.2906948924064636,0,2,12,4,3,3,-1,12,5,3,1,3,.008050408214330673,.4885950982570648,.6395021080970764,0,2,7,4,6,16,-1,7,12,6,8,2,.004805495962500572,.5197256803512573,.365666389465332,0,2,12,4,3,3,-1,12,5,3,1,3,-.0022420159075409174,.6153467893600464,.4763701856136322,0,2,2,3,2,6,-1,2,5,2,2,3,-.0137577103450894,.2637344896793366,.5030903220176697,0,2,14,2,6,9,-1,14,5,6,3,3,-.1033829972147942,.2287521958351135,.5182461142539978,0,2,5,4,3,3,-1,5,5,3,1,3,-.009443208575248718,.6953303813934326,.4694949090480804,0,2,9,17,3,2,-1,10,17,1,2,3,.0008027118165045977,.5450655221939087,.4268783926963806,0,2,5,5,2,3,-1,5,6,2,1,3,-.004194566980004311,.6091387867927551,.4571642875671387,0,2,13,11,3,6,-1,13,13,3,2,3,.0109422104433179,.5241063237190247,.3284547030925751,0,2,3,14,2,6,-1,3,17,2,3,2,-.0005784106906503439,.5387929081916809,.4179368913173676,0,2,14,3,6,2,-1,14,4,6,1,2,-.002088862005621195,.4292691051959992,.5301715731620789,0,2,0,8,16,2,-1,0,9,16,1,2,.0032383969519287348,.379234790802002,.5220744013786316,0,2,14,3,6,2,-1,14,4,6,1,2,.004907502792775631,.5237283110618591,.4126757979393005,0,2,0,0,5,6,-1,0,2,5,2,3,-.0322779417037964,.1947655975818634,.4994502067565918,0,2,12,5,4,3,-1,12,6,4,1,3,-.008971123024821281,.6011285185813904,.4929032027721405,0,2,4,11,3,6,-1,4,13,3,2,3,.0153210898861289,.5009753704071045,.2039822041988373,0,2,12,5,4,3,-1,12,6,4,1,3,.002085556974634528,.4862189888954163,.5721694827079773,0,2,9,5,1,3,-1,9,6,1,1,3,.005061502102762461,.5000218749046326,.1801805943250656,0,2,12,5,4,3,-1,12,6,4,1,3,-.0037174751050770283,.5530117154121399,.4897592961788178,0,2,6,6,8,12,-1,6,12,8,6,2,-.0121705001220107,.4178605973720551,.5383723974227905,0,2,12,5,4,3,-1,12,6,4,1,3,.004624839872121811,.4997169971466065,.5761327147483826,0,2,5,12,9,2,-1,8,12,3,2,3,-.0002104042941937223,.5331807136535645,.4097681045532227,0,2,12,5,4,3,-1,12,6,4,1,3,-.0146417804062366,.5755925178527832,.5051776170730591,0,2,4,5,4,3,-1,4,6,4,1,3,.00331994891166687,.4576976895332336,.6031805872917175,0,2,6,6,9,2,-1,9,6,3,2,3,.003723687957972288,.4380396902561188,.541588306427002,0,2,4,11,1,3,-1,4,12,1,1,3,.0008295116131193936,.5163031816482544,.3702219128608704,0,2,14,12,6,6,-1,14,12,3,6,2,-.0114084901288152,.6072946786880493,.4862565100193024,0,2,7,0,3,7,-1,8,0,1,7,3,-.004532012157142162,.3292475938796997,.5088962912559509,0,2,9,8,3,3,-1,10,8,1,3,3,.00512760179117322,.4829767942428589,.6122708916664124,0,2,8,8,3,3,-1,9,8,1,3,3,.00985831581056118,.4660679996013641,.6556177139282227,0,2,5,10,11,3,-1,5,11,11,1,3,.036985918879509,.5204849243164062,.1690472066402435,0,2,5,7,10,1,-1,10,7,5,1,2,.004649116192013025,.5167322158813477,.3725225031375885,0,2,9,7,3,2,-1,10,7,1,2,3,-.004266470205038786,.6406493186950684,.4987342953681946,0,2,8,7,3,2,-1,9,7,1,2,3,-.0004795659042429179,.5897293090820312,.4464873969554901,0,2,11,9,4,2,-1,11,9,2,2,2,.0036827160511165857,.5441560745239258,.347266286611557,0,2,5,9,4,2,-1,7,9,2,2,2,-.0100598800927401,.2143162935972214,.500482976436615,0,2,14,10,2,4,-1,14,12,2,2,2,-.0003036184061784297,.538642406463623,.4590323865413666,0,2,7,7,3,2,-1,8,7,1,2,3,-.0014545479789376259,.5751184225082397,.4497095048427582,0,2,14,17,6,3,-1,14,18,6,1,3,.0016515209572389722,.5421937704086304,.4238520860671997,0,3,4,5,12,12,-1,4,5,6,6,2,10,11,6,6,2,-.007846863940358162,.4077920913696289,.5258157253265381,0,3,6,9,8,8,-1,10,9,4,4,2,6,13,4,4,2,-.005125985015183687,.422927588224411,.5479453206062317,0,2,0,4,15,4,-1,5,4,5,4,3,-.0368909612298012,.6596375703811646,.4674678146839142,0,2,13,2,4,1,-1,13,2,2,1,2,.0002403563994448632,.4251135885715485,.5573202967643738,0,2,4,12,2,2,-1,4,13,2,1,2,-15150169929256663e-21,.5259246826171875,.4074114859104157,0,2,8,13,4,3,-1,8,14,4,1,3,.0022108471021056175,.4671722948551178,.5886352062225342,0,2,9,13,2,3,-1,9,14,2,1,3,-.0011568620102480054,.5711066126823425,.4487161934375763,0,2,13,11,2,3,-1,13,12,2,1,3,.004999629221856594,.5264198184013367,.2898327112197876,0,3,7,12,4,4,-1,7,12,2,2,2,9,14,2,2,2,-.0014656189596280456,.3891738057136536,.5197871923446655,0,3,10,11,2,2,-1,11,11,1,1,2,10,12,1,1,2,-.0011975039960816503,.5795872807502747,.4927955865859985,0,2,8,17,3,2,-1,9,17,1,2,3,-.0044954330660402775,.2377603054046631,.5012555122375488,0,3,10,11,2,2,-1,11,11,1,1,2,10,12,1,1,2,.00014997160178609192,.4876626133918762,.5617607831954956,0,2,0,17,6,3,-1,0,18,6,1,3,.002639150945469737,.516808807849884,.3765509128570557,0,3,10,11,2,2,-1,11,11,1,1,2,10,12,1,1,2,-.0002936813107226044,.5446649193763733,.4874630868434906,0,3,8,11,2,2,-1,8,11,1,1,2,9,12,1,1,2,.0014211760135367513,.4687897861003876,.669133186340332,0,2,12,5,8,4,-1,12,5,4,4,2,.0794276371598244,.5193443894386292,.273294597864151,0,2,0,5,8,4,-1,4,5,4,4,2,.0799375027418137,.4971731007099152,.1782083958387375,0,2,13,2,4,1,-1,13,2,2,1,2,.0110892597585917,.5165994763374329,.3209475874900818,0,2,3,2,4,1,-1,5,2,2,1,2,.00016560709627810866,.4058471918106079,.5307276248931885,0,3,10,0,4,2,-1,12,0,2,1,2,10,1,2,1,2,-.0053354292176663876,.3445056974887848,.5158129930496216,0,2,7,12,3,1,-1,8,12,1,1,3,.0011287260567769408,.4594863057136536,.6075533032417297,0,3,8,11,4,8,-1,10,11,2,4,2,8,15,2,4,2,-.0219692196696997,.1680400967597961,.5228595733642578,0,2,9,9,2,2,-1,9,10,2,1,2,-.00021775320055894554,.3861596882343292,.5215672850608826,0,2,3,18,15,2,-1,3,19,15,1,2,.00020200149447191507,.5517979264259338,.4363039135932922,0,3,2,6,2,12,-1,2,6,1,6,2,3,12,1,6,2,-.0217331498861313,.7999460101127625,.4789851009845734,0,2,9,8,2,3,-1,9,9,2,1,3,-.0008439993252977729,.4085975885391235,.5374773144721985,0,2,7,10,3,2,-1,8,10,1,2,3,-.00043895249837078154,.5470405220985413,.4366143047809601,0,2,11,11,3,1,-1,12,11,1,1,3,.0015092400135472417,.4988996982574463,.5842149257659912,0,2,6,11,3,1,-1,7,11,1,1,3,-.003554783994331956,.6753690242767334,.4721005856990814,0,3,9,2,4,2,-1,11,2,2,1,2,9,3,2,1,2,.00048191400128416717,.541585385799408,.4357109069824219,0,2,4,12,2,3,-1,4,13,2,1,3,-.00602643983438611,.2258509993553162,.499188095331192,0,2,2,1,18,3,-1,8,1,6,3,3,-.0116681400686502,.625655472278595,.4927498996257782,0,2,5,1,4,14,-1,7,1,2,14,2,-.0028718370012938976,.3947784900665283,.524580180644989,0,2,8,16,12,3,-1,8,16,6,3,2,.0170511696487665,.4752511084079742,.5794224143028259,0,2,1,17,18,3,-1,7,17,6,3,3,-.0133520802482963,.6041104793548584,.4544535875320435,0,2,9,14,2,6,-1,9,17,2,3,2,-.0003930180100724101,.4258275926113129,.5544905066490173,0,2,9,12,1,8,-1,9,16,1,4,2,.0030483349692076445,.5233420133590698,.3780272901058197,0,2,9,14,2,3,-1,9,15,2,1,3,-.00435792887583375,.6371889114379883,.4838674068450928,0,2,9,6,2,12,-1,9,10,2,4,3,.0056661018170416355,.5374705791473389,.4163666069507599,0,2,12,9,3,3,-1,12,10,3,1,3,6067733920644969e-20,.4638795852661133,.5311625003814697,0,2,0,1,4,8,-1,2,1,2,8,2,.0367381609976292,.4688656032085419,.6466524004936218,0,3,9,1,6,2,-1,12,1,3,1,2,9,2,3,1,2,.008652813732624054,.5204318761825562,.2188657969236374,0,2,1,3,12,14,-1,1,10,12,7,2,-.1537135988473892,.1630371958017349,.4958840012550354,0,3,8,12,4,2,-1,10,12,2,1,2,8,13,2,1,2,-.00041560421232134104,.577445924282074,.4696458876132965,0,3,1,9,10,2,-1,1,9,5,1,2,6,10,5,1,2,-.0012640169588848948,.3977175951004028,.5217198133468628,0,2,8,15,4,3,-1,8,16,4,1,3,-.003547334112226963,.6046528220176697,.480831503868103,0,2,6,8,8,3,-1,6,9,8,1,3,3001906952704303e-20,.3996723890304565,.5228201150894165,0,2,9,15,5,3,-1,9,16,5,1,3,.00131130195222795,.4712158143520355,.5765997767448425,0,2,8,7,4,3,-1,8,8,4,1,3,-.0013374709524214268,.4109584987163544,.5253170132637024,0,2,7,7,6,2,-1,7,8,6,1,2,.0208767093718052,.5202993750572205,.1757981926202774,0,3,5,7,8,2,-1,5,7,4,1,2,9,8,4,1,2,-.007549794856458902,.6566609740257263,.4694975018501282,0,2,12,9,3,3,-1,12,10,3,1,3,.0241885501891375,.5128673911094666,.3370220959186554,0,2,4,7,4,2,-1,4,8,4,1,2,-.002935882890596986,.658078670501709,.4694541096687317,0,2,14,2,6,9,-1,14,5,6,3,3,.0575579293072224,.5146445035934448,.2775259912014008,0,2,4,9,3,3,-1,5,9,1,3,3,-.0011343370424583554,.3836601972579956,.5192667245864868,0,2,12,9,3,3,-1,12,10,3,1,3,.0168169997632504,.5085592865943909,.6177260875701904,0,2,0,2,6,9,-1,0,5,6,3,3,.005053517874330282,.5138763189315796,.3684791922569275,0,2,17,3,3,6,-1,18,3,1,6,3,-.004587471019476652,.5989655256271362,.4835202097892761,0,2,0,3,3,6,-1,1,3,1,6,3,.001688246033154428,.4509486854076386,.5723056793212891,0,2,17,14,1,2,-1,17,15,1,1,2,-.0016554000321775675,.3496770858764648,.5243319272994995,0,2,4,9,4,3,-1,6,9,2,3,2,-.0193738006055355,.1120536997914314,.496871292591095,0,2,12,9,3,3,-1,12,10,3,1,3,.0103744501248002,.5148196816444397,.4395213127136231,0,2,5,9,3,3,-1,5,10,3,1,3,.00014973050565458834,.4084999859333038,.526988685131073,0,3,9,5,6,8,-1,12,5,3,4,2,9,9,3,4,2,-.042981930077076,.6394104957580566,.501850426197052,0,3,5,5,6,8,-1,5,5,3,4,2,8,9,3,4,2,.008306593634188175,.470755398273468,.6698353290557861,0,2,16,1,4,6,-1,16,4,4,3,2,-.0041285790503025055,.4541369080543518,.5323647260665894,0,2,1,0,6,20,-1,3,0,2,20,3,.0017399420030415058,.433396190404892,.5439866185188293,0,2,12,11,3,2,-1,13,11,1,2,3,.00011739750334527344,.4579687118530273,.5543426275253296,0,2,5,11,3,2,-1,6,11,1,2,3,.00018585780344437808,.4324643909931183,.5426754951477051,0,2,9,4,6,1,-1,11,4,2,1,3,.005558769218623638,.525722086429596,.3550611138343811,0,2,0,0,8,3,-1,4,0,4,3,2,-.007985156029462814,.6043018102645874,.4630635976791382,0,2,15,0,2,5,-1,15,0,1,5,2,.0006059412262402475,.4598254859447479,.55331951379776,0,2,4,1,3,2,-1,5,1,1,2,3,-.0002298304025316611,.4130752086639404,.5322461128234863,0,2,7,0,6,15,-1,9,0,2,15,3,.0004374021082185209,.4043039977550507,.5409289002418518,0,2,6,11,3,1,-1,7,11,1,1,3,.0002948202018160373,.4494963884353638,.5628852248191833,0,2,12,0,3,4,-1,13,0,1,4,3,.0103126596659422,.5177510976791382,.2704316973686218,0,2,5,4,6,1,-1,7,4,2,1,3,-.007724110968410969,.1988019049167633,.4980553984642029,0,2,12,7,3,2,-1,12,8,3,1,2,-.004679720848798752,.6644750237464905,.5018296241760254,0,2,0,1,4,6,-1,0,4,4,3,2,-.005075545981526375,.3898304998874664,.5185269117355347,0,2,12,7,3,2,-1,12,8,3,1,2,.00224797404371202,.4801808893680573,.5660336017608643,0,2,2,16,3,3,-1,2,17,3,1,3,.0008332700817845762,.5210919976234436,.3957188129425049,0,3,13,8,6,10,-1,16,8,3,5,2,13,13,3,5,2,-.0412793308496475,.6154541969299316,.5007054209709167,0,2,0,9,5,2,-1,0,10,5,1,2,-.0005093018990010023,.3975942134857178,.5228403806686401,0,3,12,11,2,2,-1,13,11,1,1,2,12,12,1,1,2,.0012568780221045017,.4979138076305389,.5939183235168457,0,2,3,15,3,3,-1,3,16,3,1,3,.008004849776625633,.4984497129917145,.1633366048336029,0,2,12,7,3,2,-1,12,8,3,1,2,-.0011879300000146031,.5904964804649353,.4942624866962433,0,2,5,7,3,2,-1,5,8,3,1,2,.0006194895249791443,.4199557900428772,.5328726172447205,0,2,9,5,9,9,-1,9,8,9,3,3,.006682985927909613,.5418602824211121,.490588903427124,0,2,5,0,3,7,-1,6,0,1,7,3,-.0037062340416014194,.3725939095020294,.5138000249862671,0,2,5,2,12,5,-1,9,2,4,5,3,-.0397394113242626,.6478961110115051,.5050346851348877,0,3,6,11,2,2,-1,6,11,1,1,2,7,12,1,1,2,.0014085009461268783,.4682339131832123,.6377884149551392,0,2,15,15,3,2,-1,15,16,3,1,2,.0003932268882635981,.5458530187606812,.415048211812973,0,2,2,15,3,2,-1,2,16,3,1,2,-.0018979819724336267,.3690159916877747,.5149704217910767,0,3,14,12,6,8,-1,17,12,3,4,2,14,16,3,4,2,-.0139704402536154,.6050562858581543,.4811357855796814,0,2,2,8,15,6,-1,7,8,5,6,3,-.1010081991553307,.2017080038785934,.4992361962795258,0,2,2,2,18,17,-1,8,2,6,17,3,-.0173469204455614,.5713148713111877,.4899486005306244,0,2,5,1,4,1,-1,7,1,2,1,2,.000156197595060803,.4215388894081116,.5392642021179199,0,2,5,2,12,5,-1,9,2,4,5,3,.1343892961740494,.5136151909828186,.3767612874507904,0,2,3,2,12,5,-1,7,2,4,5,3,-.0245822407305241,.7027357816696167,.4747906923294067,0,3,4,9,12,4,-1,10,9,6,2,2,4,11,6,2,2,-.0038553720805794,.4317409098148346,.5427716970443726,0,3,5,15,6,2,-1,5,15,3,1,2,8,16,3,1,2,-.002316524973139167,.594269871711731,.4618647992610931,0,2,10,14,2,3,-1,10,15,2,1,3,-.004851812031120062,.6191568970680237,.4884895086288452,0,3,0,13,20,2,-1,0,13,10,1,2,10,14,10,1,2,.002469993894919753,.5256664752960205,.4017199873924255,0,3,4,9,12,8,-1,10,9,6,4,2,4,13,6,4,2,.0454969592392445,.5237867832183838,.2685773968696594,0,2,8,13,3,6,-1,8,16,3,3,2,-.0203195996582508,.213044598698616,.4979738891124725,0,2,10,12,2,2,-1,10,13,2,1,2,.0002699499891605228,.481404185295105,.5543122291564941,0,3,9,12,2,2,-1,9,12,1,1,2,10,13,1,1,2,-.0018232699949294329,.6482579708099365,.4709989130496979,0,3,4,11,14,4,-1,11,11,7,2,2,4,13,7,2,2,-.006301579065620899,.4581927955150604,.5306236147880554,0,2,8,5,4,2,-1,8,6,4,1,2,-.0002413949987385422,.5232086777687073,.4051763117313385,0,2,10,10,6,3,-1,12,10,2,3,3,-.001033036969602108,.5556201934814453,.4789193868637085,0,2,2,14,1,2,-1,2,15,1,1,2,.0001804116036510095,.5229442715644836,.4011810123920441,0,3,13,8,6,12,-1,16,8,3,6,2,13,14,3,6,2,-.0614078603684902,.62986820936203,.5010703206062317,0,3,1,8,6,12,-1,1,8,3,6,2,4,14,3,6,2,-.0695439130067825,.7228280901908875,.4773184061050415,0,2,10,0,6,10,-1,12,0,2,10,3,-.0705426633358002,.2269513010978699,.5182529091835022,0,3,5,11,8,4,-1,5,11,4,2,2,9,13,4,2,2,.0024423799477517605,.5237097144126892,.4098151028156281,0,3,10,16,8,4,-1,14,16,4,2,2,10,18,4,2,2,.0015494349645450711,.4773750901222229,.5468043088912964,0,2,7,7,6,6,-1,9,7,2,6,3,-.0239142198115587,.7146975994110107,.4783824980258942,0,2,10,2,4,10,-1,10,2,2,10,2,-.0124536901712418,.2635296881198883,.5241122841835022,0,2,6,1,4,9,-1,8,1,2,9,2,-.00020760179904755205,.3623757064342499,.5113608837127686,0,2,12,19,2,1,-1,12,19,1,1,2,29781080229440704e-21,.4705932140350342,.5432801842689514,104.74919891357422,211,0,2,1,2,4,9,-1,3,2,2,9,2,.0117727499455214,.3860518932342529,.6421167254447937,0,2,7,5,6,4,-1,9,5,2,4,3,.0270375702530146,.4385654926300049,.675403892993927,0,2,9,4,2,4,-1,9,6,2,2,2,-3641950024757534e-20,.5487101078033447,.34233158826828,0,2,14,5,2,8,-1,14,9,2,4,2,.001999540952965617,.3230532109737396,.5400317907333374,0,2,7,6,5,12,-1,7,12,5,6,2,.0045278300531208515,.5091639757156372,.2935043871402741,0,2,14,6,2,6,-1,14,9,2,3,2,.00047890920541249216,.4178153872489929,.5344064235687256,0,2,4,6,2,6,-1,4,9,2,3,2,.0011720920447260141,.2899182140827179,.5132070779800415,0,3,8,15,10,4,-1,13,15,5,2,2,8,17,5,2,2,.0009530570241622627,.428012490272522,.5560845136642456,0,2,6,18,2,2,-1,7,18,1,2,2,15099150004971307e-21,.4044871926307678,.5404760241508484,0,2,11,3,6,2,-1,11,4,6,1,2,-.0006081790197640657,.4271768927574158,.5503466129302979,0,2,2,0,16,6,-1,2,2,16,2,3,.003322452073916793,.3962723910808563,.5369734764099121,0,2,11,3,6,2,-1,11,4,6,1,2,-.0011037490330636501,.4727177917957306,.5237749814987183,0,2,4,11,10,3,-1,4,12,10,1,3,-.0014350269921123981,.5603008270263672,.4223509132862091,0,2,11,3,6,2,-1,11,4,6,1,2,.0020767399109899998,.5225917100906372,.4732725918292999,0,2,3,3,6,2,-1,3,4,6,1,2,-.00016412809782195836,.3999075889587402,.5432739853858948,0,2,16,0,4,7,-1,16,0,2,7,2,.008830243721604347,.4678385853767395,.6027327179908752,0,2,0,14,9,6,-1,0,16,9,2,3,-.0105520701035857,.3493967056274414,.5213974714279175,0,2,9,16,3,3,-1,9,17,3,1,3,-.00227316003292799,.6185818910598755,.4749062955379486,0,2,4,6,6,2,-1,6,6,2,2,3,-.0008478633244521916,.5285341143608093,.3843482136726379,0,2,15,11,1,3,-1,15,12,1,1,3,.0012081359745934606,.536064088344574,.3447335958480835,0,2,5,5,2,3,-1,5,6,2,1,3,.002651273040100932,.4558292031288147,.6193962097167969,0,2,10,9,2,2,-1,10,10,2,1,2,-.0011012479662895203,.368023008108139,.5327628254890442,0,2,3,1,4,3,-1,5,1,2,3,2,.0004956151824444532,.396059513092041,.5274940729141235,0,2,16,0,4,7,-1,16,0,2,7,2,-.0439017713069916,.7020444869995117,.4992839097976685,0,2,0,0,20,1,-1,10,0,10,1,2,.0346903502941132,.5049164295196533,.276660293340683,0,2,15,11,1,3,-1,15,12,1,1,3,-.002744219033047557,.2672632932662964,.5274971127510071,0,2,0,4,3,4,-1,1,4,1,4,3,.003331658896058798,.4579482972621918,.6001101732254028,0,2,16,3,3,6,-1,16,5,3,2,3,-.0200445707887411,.3171594142913818,.523571789264679,0,2,1,3,3,6,-1,1,5,3,2,3,.0013492030557245016,.5265362858772278,.4034324884414673,0,3,6,2,12,6,-1,12,2,6,3,2,6,5,6,3,2,.0029702018946409225,.5332456827163696,.4571984112262726,0,2,8,10,4,3,-1,8,11,4,1,3,.006303998176008463,.4593310952186585,.6034635901451111,0,3,4,2,14,6,-1,11,2,7,3,2,4,5,7,3,2,-.0129365902394056,.4437963962554932,.5372971296310425,0,2,9,11,2,3,-1,9,12,2,1,3,.004014872945845127,.4680323898792267,.6437833905220032,0,2,15,13,2,3,-1,15,14,2,1,3,-.002640167949721217,.3709631860256195,.5314332842826843,0,2,8,12,4,3,-1,8,13,4,1,3,.0139184398576617,.4723555147647858,.713080883026123,0,2,15,11,1,3,-1,15,12,1,1,3,-.00045087869511917233,.4492394030094147,.5370404124259949,0,2,7,13,5,2,-1,7,14,5,1,2,.00025384349282830954,.4406864047050476,.5514402985572815,0,2,7,12,6,3,-1,7,13,6,1,3,.002271000063046813,.4682416915893555,.5967984199523926,0,2,5,11,4,4,-1,5,13,4,2,2,.002412077970802784,.5079392194747925,.3018598854541779,0,2,11,4,3,3,-1,12,4,1,3,3,-3602567085181363e-20,.560103714466095,.4471096992492676,0,2,6,4,3,3,-1,7,4,1,3,3,-.0074905529618263245,.2207535058259964,.4989944100379944,0,2,16,5,3,6,-1,17,5,1,6,3,-.017513120546937,.6531215906143188,.5017648935317993,0,2,3,6,12,7,-1,7,6,4,7,3,.1428163051605225,.4967963099479675,.1482062041759491,0,2,16,5,3,6,-1,17,5,1,6,3,.005534526892006397,.4898946881294251,.5954223871231079,0,2,3,13,2,3,-1,3,14,2,1,3,-.0009632359142415226,.3927116990089417,.519607424736023,0,2,16,5,3,6,-1,17,5,1,6,3,-.0020370010752230883,.5613325238227844,.4884858131408691,0,2,1,5,3,6,-1,2,5,1,6,3,.0016614829655736685,.4472880065441132,.5578880906105042,0,2,1,9,18,1,-1,7,9,6,1,3,-.0031188090797513723,.3840532898902893,.5397477746009827,0,2,0,9,8,7,-1,4,9,4,7,2,-.006400061771273613,.5843983888626099,.4533218145370483,0,2,12,11,8,2,-1,12,12,8,1,2,.0003131960111204535,.5439221858978271,.4234727919101715,0,2,0,11,8,2,-1,0,12,8,1,2,-.0182220991700888,.1288464963436127,.4958404898643494,0,2,9,13,2,3,-1,9,14,2,1,3,.008796924725174904,.49512979388237,.7153480052947998,0,3,4,10,12,4,-1,4,10,6,2,2,10,12,6,2,2,-.004239507019519806,.3946599960327148,.5194936990737915,0,2,9,3,3,7,-1,10,3,1,7,3,.009708627127110958,.4897503852844238,.6064900159835815,0,2,7,2,3,5,-1,8,2,1,5,3,-.003993417136371136,.3245440125465393,.5060828924179077,0,3,9,12,4,6,-1,11,12,2,3,2,9,15,2,3,2,-.0167850591242313,.1581953018903732,.5203778743743896,0,2,8,7,3,6,-1,9,7,1,6,3,.018272090703249,.4680935144424439,.6626979112625122,0,2,15,4,4,2,-1,15,5,4,1,2,.00568728381767869,.5211697816848755,.3512184917926788,0,2,8,7,3,3,-1,9,7,1,3,3,-.0010739039862528443,.5768386125564575,.4529845118522644,0,2,14,2,6,4,-1,14,4,6,2,2,-.00370938703417778,.4507763087749481,.5313581228256226,0,2,7,16,6,1,-1,9,16,2,1,3,-.0002111070934915915,.5460820198059082,.4333376884460449,0,2,15,13,2,3,-1,15,14,2,1,3,.0010670139454305172,.5371856093406677,.4078390896320343,0,2,8,7,3,10,-1,9,7,1,10,3,.0035943021066486835,.4471287131309509,.5643836259841919,0,2,11,10,2,6,-1,11,12,2,2,3,-.005177603103220463,.4499393105506897,.5280330181121826,0,2,6,10,4,1,-1,8,10,2,1,2,-.00025414369883947074,.5516173243522644,.4407708048820496,0,2,10,9,2,2,-1,10,10,2,1,2,.006352256052196026,.5194190144538879,.2465227991342545,0,2,8,9,2,2,-1,8,10,2,1,2,-.00044205080484971404,.3830705881118774,.5139682292938232,0,3,12,7,2,2,-1,13,7,1,1,2,12,8,1,1,2,.0007448872784152627,.4891090989112854,.5974786877632141,0,3,5,7,2,2,-1,5,7,1,1,2,6,8,1,1,2,-.0035116379149258137,.7413681745529175,.4768764972686768,0,2,13,0,3,14,-1,14,0,1,14,3,-.0125409103929996,.3648819029331207,.5252826809883118,0,2,4,0,3,14,-1,5,0,1,14,3,.009493185207247734,.5100492835044861,.362958699464798,0,2,13,4,3,14,-1,14,4,1,14,3,.0129611501470208,.5232442021369934,.4333561062812805,0,2,9,14,2,3,-1,9,15,2,1,3,.004720944911241531,.4648149013519287,.6331052780151367,0,2,8,14,4,3,-1,8,15,4,1,3,-.0023119079414755106,.5930309891700745,.4531058073043823,0,2,4,2,3,16,-1,5,2,1,16,3,-.002826229901984334,.3870477974414825,.5257101058959961,0,2,7,2,8,10,-1,7,7,8,5,2,-.0014311339473351836,.552250325679779,.4561854898929596,0,2,6,14,7,3,-1,6,15,7,1,3,.0019378310535103083,.4546220898628235,.5736966729164124,0,3,9,2,10,12,-1,14,2,5,6,2,9,8,5,6,2,.00026343559147790074,.5345739126205444,.4571875035762787,0,2,6,7,8,2,-1,6,8,8,1,2,.0007825752254575491,.3967815935611725,.5220187902450562,0,2,8,13,4,6,-1,8,16,4,3,2,-.0195504408329725,.282964289188385,.5243508219718933,0,2,6,6,1,3,-1,6,7,1,1,3,.00043914958951063454,.4590066969394684,.589909017086029,0,2,16,2,4,6,-1,16,4,4,2,3,.0214520003646612,.523141086101532,.2855378985404968,0,3,6,6,4,2,-1,6,6,2,1,2,8,7,2,1,2,.0005897358059883118,.4397256970405579,.550642192363739,0,2,16,2,4,6,-1,16,4,4,2,3,-.0261576101183891,.3135079145431519,.5189175009727478,0,2,0,2,4,6,-1,0,4,4,2,3,-.0139598604291677,.3213272988796234,.5040717720985413,0,2,9,6,2,6,-1,9,6,1,6,2,-.006369901821017265,.6387544870376587,.4849506914615631,0,2,3,4,6,10,-1,3,9,6,5,2,-.008561382070183754,.2759132087230682,.5032019019126892,0,2,9,5,2,6,-1,9,5,1,6,2,.000966229010373354,.4685640931129456,.5834879279136658,0,2,3,13,2,3,-1,3,14,2,1,3,.0007655026856809855,.5175207257270813,.389642208814621,0,2,13,13,3,2,-1,13,14,3,1,2,-.008183334022760391,.2069136947393417,.5208122134208679,0,3,2,16,10,4,-1,2,16,5,2,2,7,18,5,2,2,-.009397693909704685,.6134091019630432,.4641222953796387,0,3,5,6,10,6,-1,10,6,5,3,2,5,9,5,3,2,.004802898038178682,.5454108119010925,.439521998167038,0,2,7,14,1,3,-1,7,15,1,1,3,-.003568056970834732,.6344485282897949,.4681093990802765,0,2,14,16,6,3,-1,14,17,6,1,3,.0040733120404183865,.5292683243751526,.4015620052814484,0,2,5,4,3,3,-1,5,5,3,1,3,.0012568129459396005,.4392988085746765,.5452824831008911,0,2,7,4,10,3,-1,7,5,10,1,3,-.0029065010603517294,.5898832082748413,.4863379895687103,0,2,0,4,5,4,-1,0,6,5,2,2,-.00244093406945467,.4069364964962006,.5247421860694885,0,2,13,11,3,9,-1,13,14,3,3,3,.0248307008296251,.5182725787162781,.3682524859905243,0,2,4,11,3,9,-1,4,14,3,3,3,-.0488540083169937,.1307577937841415,.496128112077713,0,2,9,7,2,1,-1,9,7,1,1,2,-.001611037994734943,.6421005725860596,.4872662127017975,0,2,5,0,6,17,-1,7,0,2,17,3,-.0970094799995422,.0477693490684032,.495098888874054,0,2,10,3,6,3,-1,10,3,3,3,2,.0011209240183234215,.4616267085075378,.5354745984077454,0,2,2,2,15,4,-1,7,2,5,4,3,-.001306409016251564,.626185417175293,.4638805985450745,0,3,8,2,8,2,-1,12,2,4,1,2,8,3,4,1,2,.00045771620352752507,.5384417772293091,.4646640121936798,0,2,8,1,3,6,-1,8,3,3,2,3,-.0006314995116554201,.3804047107696533,.51302570104599,0,2,9,17,2,2,-1,9,18,2,1,2,.0001450597046641633,.4554310142993927,.5664461851119995,0,2,0,0,2,14,-1,1,0,1,14,2,-.0164745505899191,.6596958041191101,.4715859889984131,0,2,12,0,7,3,-1,12,1,7,1,3,.0133695797994733,.519546627998352,.3035964965820313,0,2,1,14,1,2,-1,1,15,1,1,2,.00010271780047332868,.522917628288269,.4107066094875336,0,3,14,12,2,8,-1,15,12,1,4,2,14,16,1,4,2,-.0055311559699475765,.6352887749671936,.4960907101631165,0,2,1,0,7,3,-1,1,1,7,1,3,-.0026187049224972725,.3824546039104462,.5140984058380127,0,3,14,12,2,8,-1,15,12,1,4,2,14,16,1,4,2,.005083426833152771,.4950439929962158,.6220818758010864,0,3,6,0,8,12,-1,6,0,4,6,2,10,6,4,6,2,.0798181593418121,.4952335953712463,.1322475969791412,0,2,6,1,8,9,-1,6,4,8,3,3,-.0992265865206718,.7542728781700134,.5008416771888733,0,2,5,2,2,2,-1,5,3,2,1,2,-.0006517401780001819,.3699302971363068,.5130121111869812,0,3,13,14,6,6,-1,16,14,3,3,2,13,17,3,3,2,-.018996849656105,.6689178943634033,.4921202957630158,0,3,0,17,20,2,-1,0,17,10,1,2,10,18,10,1,2,.0173468999564648,.4983300864696503,.1859198063611984,0,3,10,3,2,6,-1,11,3,1,3,2,10,6,1,3,2,.0005508210160769522,.4574424028396606,.5522121787071228,0,2,5,12,6,2,-1,8,12,3,2,2,.002005605027079582,.5131744742393494,.3856469988822937,0,2,10,7,6,13,-1,10,7,3,13,2,-.007768819108605385,.4361700117588043,.5434309244155884,0,2,5,15,10,5,-1,10,15,5,5,2,.0508782789111137,.4682720899581909,.6840639710426331,0,2,10,4,4,10,-1,10,4,2,10,2,-.0022901780903339386,.4329245090484619,.5306099057197571,0,2,5,7,2,1,-1,6,7,1,1,2,-.00015715380141045898,.5370057225227356,.4378164112567902,0,2,10,3,6,7,-1,10,3,3,7,2,.1051924005150795,.5137274265289307,.0673614665865898,0,2,4,3,6,7,-1,7,3,3,7,2,.002719891956076026,.4112060964107513,.5255665183067322,0,2,1,7,18,5,-1,7,7,6,5,3,.0483377799391747,.5404623746871948,.4438967108726502,0,2,3,17,4,3,-1,5,17,2,3,2,.0009570376132614911,.4355969130992889,.5399510860443115,0,3,8,14,12,6,-1,14,14,6,3,2,8,17,6,3,2,-.0253712590783834,.5995175242424011,.5031024813652039,0,3,0,13,20,4,-1,0,13,10,2,2,10,15,10,2,2,.0524579510092735,.4950287938117981,.1398351043462753,0,3,4,5,14,2,-1,11,5,7,1,2,4,6,7,1,2,-.0123656298965216,.639729917049408,.496410608291626,0,3,1,2,10,12,-1,1,2,5,6,2,6,8,5,6,2,-.1458971947431564,.1001669988036156,.494632214307785,0,2,6,1,14,3,-1,6,2,14,1,3,-.0159086007624865,.3312329947948456,.5208340883255005,0,2,8,16,2,3,-1,8,17,2,1,3,.00039486068999394774,.4406363964080811,.5426102876663208,0,2,9,17,3,2,-1,10,17,1,2,3,-.0052454001270234585,.2799589931964874,.5189967155456543,0,3,5,15,4,2,-1,5,15,2,1,2,7,16,2,1,2,-.005042179953306913,.6987580060958862,.4752142131328583,0,2,10,15,1,3,-1,10,16,1,1,3,.0029812189750373363,.4983288943767548,.6307479739189148,0,3,8,16,4,4,-1,8,16,2,2,2,10,18,2,2,2,-.007288430817425251,.298233300447464,.5026869773864746,0,2,6,11,8,6,-1,6,14,8,3,2,.0015094350092113018,.5308442115783691,.3832970857620239,0,2,2,13,5,2,-1,2,14,5,1,2,-.009334079921245575,.2037964016199112,.4969817101955414,0,3,13,14,6,6,-1,16,14,3,3,2,13,17,3,3,2,.0286671407520771,.5025696754455566,.6928027272224426,0,2,1,9,18,4,-1,7,9,6,4,3,.1701968014240265,.4960052967071533,.1476442962884903,0,3,13,14,6,6,-1,16,14,3,3,2,13,17,3,3,2,-.003261447884142399,.5603063702583313,.4826056063175201,0,2,0,2,1,6,-1,0,4,1,2,3,.0005576927796937525,.5205562114715576,.4129633009433746,0,2,5,0,15,20,-1,5,10,15,10,2,.3625833988189697,.5221652984619141,.3768612146377564,0,3,1,14,6,6,-1,1,14,3,3,2,4,17,3,3,2,-.0116151301190257,.6022682785987854,.4637489914894104,0,3,8,14,4,6,-1,10,14,2,3,2,8,17,2,3,2,-.004079519771039486,.4070447087287903,.5337479114532471,0,2,7,11,2,1,-1,8,11,1,1,2,.0005720430053770542,.4601835012435913,.5900393128395081,0,2,9,17,3,2,-1,10,17,1,2,3,.000675433489959687,.5398252010345459,.4345428943634033,0,2,8,17,3,2,-1,9,17,1,2,3,.0006329569732770324,.5201563239097595,.4051358997821808,0,3,12,14,4,6,-1,14,14,2,3,2,12,17,2,3,2,.00124353205319494,.4642387926578522,.5547441244125366,0,3,4,14,4,6,-1,4,14,2,3,2,6,17,2,3,2,-.004736385773867369,.6198567152023315,.4672552049160004,0,3,13,14,2,6,-1,14,14,1,3,2,13,17,1,3,2,-.006465846206992865,.6837332844734192,.5019000768661499,0,3,5,14,2,6,-1,5,14,1,3,2,6,17,1,3,2,.000350173213519156,.4344803094863892,.5363622903823853,0,2,7,0,6,12,-1,7,4,6,4,3,.00015754920605104417,.4760079085826874,.5732020735740662,0,2,0,7,12,2,-1,4,7,4,2,3,.009977436624467373,.5090985894203186,.3635039925575256,0,2,10,3,3,13,-1,11,3,1,13,3,-.0004146452993154526,.5570064783096313,.4593802094459534,0,2,7,3,3,13,-1,8,3,1,13,3,-.00035888899583369493,.5356845855712891,.4339134991168976,0,2,10,8,6,3,-1,10,9,6,1,3,.0004046325047966093,.4439803063869476,.5436776876449585,0,2,3,11,3,2,-1,4,11,1,2,3,-.0008218478760682046,.4042294919490814,.5176299214363098,0,3,13,12,6,8,-1,16,12,3,4,2,13,16,3,4,2,.005946741905063391,.4927651882171631,.5633779764175415,0,2,7,6,6,5,-1,9,6,2,5,3,-.0217533893883228,.8006293773651123,.480084091424942,0,2,17,11,2,7,-1,17,11,1,7,2,-.0145403798669577,.3946054875850678,.5182222723960876,0,2,3,13,8,2,-1,7,13,4,2,2,-.0405107699334621,.0213249903172255,.4935792982578278,0,2,6,9,8,3,-1,6,10,8,1,3,-.0005845826817676425,.4012795984745026,.5314025282859802,0,2,4,3,4,3,-1,4,4,4,1,3,.005515180062502623,.4642418920993805,.5896260738372803,0,2,11,3,4,3,-1,11,4,4,1,3,-.006062622182071209,.6502159237861633,.5016477704048157,0,2,1,4,17,12,-1,1,8,17,4,3,.0945358425378799,.5264708995819092,.4126827120780945,0,2,11,3,4,3,-1,11,4,4,1,3,.004731505177915096,.4879199862480164,.5892447829246521,0,2,4,8,6,3,-1,4,9,6,1,3,-.0005257147131487727,.391728013753891,.5189412832260132,0,2,12,3,5,3,-1,12,4,5,1,3,-.002546404954046011,.5837599039077759,.498570591211319,0,2,1,11,2,7,-1,2,11,1,7,2,-.0260756891220808,.1261983960866928,.4955821931362152,0,3,15,12,2,8,-1,16,12,1,4,2,15,16,1,4,2,-.00547797093167901,.5722513794898987,.5010265707969666,0,2,4,8,11,3,-1,4,9,11,1,3,.005133774131536484,.527326226234436,.4226376116275787,0,3,9,13,6,2,-1,12,13,3,1,2,9,14,3,1,2,.000479449809063226,.4450066983699799,.5819587111473083,0,2,6,13,4,3,-1,6,14,4,1,3,-.0021114079281687737,.5757653117179871,.451171487569809,0,2,9,12,3,3,-1,10,12,1,3,3,-.0131799904629588,.1884381026029587,.5160734057426453,0,2,5,3,3,3,-1,5,4,3,1,3,-.004796809982508421,.6589789986610413,.4736118912696838,0,2,9,4,2,3,-1,9,5,2,1,3,.0067483168095350266,.5259429812431335,.3356395065784454,0,2,0,2,16,3,-1,0,3,16,1,3,.0014623369788751006,.5355271100997925,.4264092147350311,0,3,15,12,2,8,-1,16,12,1,4,2,15,16,1,4,2,.004764515906572342,.5034406781196594,.5786827802658081,0,3,3,12,2,8,-1,3,12,1,4,2,4,16,1,4,2,.0068066660314798355,.475660502910614,.6677829027175903,0,2,14,13,3,6,-1,14,15,3,2,3,.0036608621012419462,.5369611978530884,.4311546981334686,0,2,3,13,3,6,-1,3,15,3,2,3,.0214496403932571,.4968641996383667,.1888816058635712,0,3,6,5,10,2,-1,11,5,5,1,2,6,6,5,1,2,.004167890176177025,.4930733144283295,.5815368890762329,0,2,2,14,14,6,-1,2,17,14,3,2,.008646756410598755,.5205205082893372,.4132595062255859,0,2,10,14,1,3,-1,10,15,1,1,3,-.0003611407882999629,.5483555197715759,.4800927937030792,0,3,4,16,2,2,-1,4,16,1,1,2,5,17,1,1,2,.0010808729566633701,.4689902067184448,.6041421294212341,0,2,10,6,2,3,-1,10,7,2,1,3,.005771995987743139,.5171142220497131,.3053277134895325,0,3,0,17,20,2,-1,0,17,10,1,2,10,18,10,1,2,.001572077046148479,.5219978094100952,.4178803861141205,0,2,13,6,1,3,-1,13,7,1,1,3,-.0019307859474793077,.5860369801521301,.4812920093536377,0,2,8,13,3,2,-1,9,13,1,2,3,-.007892627269029617,.1749276965856552,.497173398733139,0,2,12,2,3,3,-1,13,2,1,3,3,-.002222467912361026,.434258908033371,.521284818649292,0,3,3,18,2,2,-1,3,18,1,1,2,4,19,1,1,2,.0019011989934369922,.4765186905860901,.689205527305603,0,2,9,16,3,4,-1,10,16,1,4,3,.0027576119173318148,.5262191295623779,.4337486028671265,0,2,6,6,1,3,-1,6,7,1,1,3,.005178744904696941,.4804069101810455,.7843729257583618,0,2,13,1,5,2,-1,13,2,5,1,2,-.0009027334162965417,.412084698677063,.5353423953056335,0,3,7,14,6,2,-1,7,14,3,1,2,10,15,3,1,2,.005179795902222395,.4740372896194458,.6425960063934326,0,2,11,3,3,4,-1,12,3,1,4,3,-.0101140001788735,.2468792051076889,.5175017714500427,0,2,1,13,12,6,-1,5,13,4,6,3,-.0186170600354671,.5756294131278992,.4628978967666626,0,2,14,11,5,2,-1,14,12,5,1,2,.0059225959703326225,.5169625878334045,.3214271068572998,0,3,2,15,14,4,-1,2,15,7,2,2,9,17,7,2,2,-.006294507998973131,.3872014880180359,.5141636729240417,0,3,3,7,14,2,-1,10,7,7,1,2,3,8,7,1,2,.0065353019163012505,.4853048920631409,.6310489773750305,0,2,1,11,4,2,-1,1,12,4,1,2,.0010878399480134249,.5117315053939819,.3723258972167969,0,2,14,0,6,14,-1,16,0,2,14,3,-.0225422400981188,.5692740082740784,.4887112975120544,0,2,4,11,1,3,-1,4,12,1,1,3,-.003006566083058715,.2556012868881226,.5003992915153503,0,2,14,0,6,14,-1,16,0,2,14,3,.007474127225577831,.4810872972011566,.5675926804542542,0,2,1,10,3,7,-1,2,10,1,7,3,.0261623207479715,.4971194863319397,.1777237057685852,0,2,8,12,9,2,-1,8,13,9,1,2,.0009435273823328316,.4940010905265808,.549125075340271,0,2,0,6,20,1,-1,10,6,10,1,2,.0333632417023182,.5007612109184265,.2790724039077759,0,2,8,4,4,4,-1,8,4,2,4,2,-.0151186501607299,.7059578895568848,.4973031878471375,0,2,0,0,2,2,-1,0,1,2,1,2,.0009864894673228264,.5128620266914368,.3776761889457703,105.76110076904297,213,0,2,5,3,10,9,-1,5,6,10,3,3,-.0951507985591888,.6470757126808167,.4017286896705627,0,2,15,2,4,10,-1,15,2,2,10,2,.006270234007388353,.399982213973999,.574644923210144,0,2,8,2,2,7,-1,9,2,1,7,2,.000300180894555524,.355877012014389,.5538809895515442,0,2,7,4,12,1,-1,11,4,4,1,3,.0011757409665733576,.425653487443924,.5382617712020874,0,2,3,4,9,1,-1,6,4,3,1,3,4423526843311265e-20,.3682908117771149,.5589926838874817,0,2,15,10,1,4,-1,15,12,1,2,2,-29936920327600092e-21,.5452470183372498,.4020367860794067,0,2,4,10,6,4,-1,7,10,3,4,2,.003007319988682866,.5239058136940002,.3317843973636627,0,2,15,9,1,6,-1,15,12,1,3,2,-.0105138896033168,.4320689141750336,.5307983756065369,0,2,7,17,6,3,-1,7,18,6,1,3,.008347682654857635,.4504637122154236,.6453298926353455,0,3,14,3,2,16,-1,15,3,1,8,2,14,11,1,8,2,-.0031492270063608885,.4313425123691559,.5370525121688843,0,2,4,9,1,6,-1,4,12,1,3,2,-1443564997316571e-20,.5326603055000305,.381797194480896,0,2,12,1,5,2,-1,12,2,5,1,2,-.00042855090578086674,.430516391992569,.5382009744644165,0,3,6,18,4,2,-1,6,18,2,1,2,8,19,2,1,2,.00015062429883982986,.4235970973968506,.5544965267181396,0,3,2,4,16,10,-1,10,4,8,5,2,2,9,8,5,2,.0715598315000534,.5303059816360474,.2678802907466888,0,2,6,5,1,10,-1,6,10,1,5,2,.0008409518050029874,.3557108938694,.5205433964729309,0,2,4,8,15,2,-1,9,8,5,2,3,.0629865005612373,.5225362777709961,.2861376106739044,0,2,1,8,15,2,-1,6,8,5,2,3,-.0033798629883676767,.3624185919761658,.5201697945594788,0,2,9,5,3,6,-1,9,7,3,2,3,-.00011810739670181647,.547447681427002,.3959893882274628,0,2,5,7,8,2,-1,9,7,4,2,2,-.0005450560129247606,.3740422129631043,.5215715765953064,0,2,9,11,2,3,-1,9,12,2,1,3,-.0018454910023137927,.5893052220344543,.4584448933601379,0,2,1,0,16,3,-1,1,1,16,1,3,-.0004383237101137638,.4084582030773163,.5385351181030273,0,2,11,2,7,2,-1,11,3,7,1,2,-.002400083001703024,.377745509147644,.5293580293655396,0,2,5,1,10,18,-1,5,7,10,6,3,-.0987957417964935,.2963612079620361,.5070089101791382,0,2,17,4,3,2,-1,18,4,1,2,3,.0031798239797353745,.4877632856369019,.6726443767547607,0,2,8,13,1,3,-1,8,14,1,1,3,.00032406419632025063,.4366911053657532,.5561109781265259,0,2,3,14,14,6,-1,3,16,14,2,3,-.0325472503900528,.31281578540802,.5308616161346436,0,2,0,2,3,4,-1,1,2,1,4,3,-.007756113074719906,.6560224890708923,.4639872014522553,0,2,12,1,5,2,-1,12,2,5,1,2,.0160272493958473,.5172680020332336,.3141897916793823,0,2,3,1,5,2,-1,3,2,5,1,2,710023505234858e-20,.4084446132183075,.5336294770240784,0,2,10,13,2,3,-1,10,14,2,1,3,.007342280820012093,.4966922104358673,.660346508026123,0,2,8,13,2,3,-1,8,14,2,1,3,-.0016970280557870865,.5908237099647522,.4500182867050171,0,2,14,12,2,3,-1,14,13,2,1,3,.0024118260480463505,.5315160751342773,.3599720895290375,0,2,7,2,2,3,-1,7,3,2,1,3,-.005530093796551228,.2334040999412537,.4996814131736755,0,3,5,6,10,4,-1,10,6,5,2,2,5,8,5,2,2,-.0026478730142116547,.5880935788154602,.4684734046459198,0,2,9,13,1,6,-1,9,16,1,3,2,.0112956296652555,.4983777105808258,.1884590983390808,0,3,10,12,2,2,-1,11,12,1,1,2,10,13,1,1,2,-.000669528788421303,.5872138142585754,.4799019992351532,0,2,4,12,2,3,-1,4,13,2,1,3,.0014410680159926414,.5131189227104187,.350101113319397,0,2,14,4,6,6,-1,14,6,6,2,3,.0024637870956212282,.5339372158050537,.4117639064788818,0,2,8,17,2,3,-1,8,18,2,1,3,.0003311451873742044,.4313383102416992,.5398246049880981,0,2,16,4,4,6,-1,16,6,4,2,3,-.0335572697222233,.26753368973732,.5179154872894287,0,2,0,4,4,6,-1,0,6,4,2,3,.0185394193977118,.4973869919776917,.2317177057266235,0,2,14,6,2,3,-1,14,6,1,3,2,-.00029698139405809343,.552970826625824,.4643664062023163,0,2,4,9,8,1,-1,8,9,4,1,2,-.0004557725915219635,.5629584193229675,.4469191133975983,0,2,8,12,4,3,-1,8,13,4,1,3,-.0101589802652597,.6706212759017944,.4925918877124786,0,2,5,12,10,6,-1,5,14,10,2,3,-22413829356082715e-21,.5239421725273132,.3912901878356934,0,2,11,12,1,2,-1,11,13,1,1,2,7203496352303773e-20,.4799438118934631,.5501788854598999,0,2,8,15,4,2,-1,8,16,4,1,2,-.006926720961928368,.6930009722709656,.4698084890842438,0,3,6,9,8,8,-1,10,9,4,4,2,6,13,4,4,2,-.007699783891439438,.409962385892868,.5480883121490479,0,3,7,12,4,6,-1,7,12,2,3,2,9,15,2,3,2,-.007313054986298084,.3283475935459137,.5057886242866516,0,2,10,11,3,1,-1,11,11,1,1,3,.0019650589674711227,.4978047013282776,.6398249864578247,0,3,9,7,2,10,-1,9,7,1,5,2,10,12,1,5,2,.007164760027080774,.4661160111427307,.6222137212753296,0,2,8,0,6,6,-1,10,0,2,6,3,-.0240786392241716,.2334644943475723,.5222162008285522,0,2,3,11,2,6,-1,3,13,2,2,3,-.0210279691964388,.1183653995394707,.4938226044178009,0,2,16,12,1,2,-1,16,13,1,1,2,.00036017020465806127,.5325019955635071,.4116711020469666,0,3,1,14,6,6,-1,1,14,3,3,2,4,17,3,3,2,-.0172197297215462,.6278762221336365,.4664269089698792,0,2,13,1,3,6,-1,14,1,1,6,3,-.007867214269936085,.3403415083885193,.5249736905097961,0,2,8,8,2,2,-1,8,9,2,1,2,-.000447773898486048,.3610411882400513,.5086259245872498,0,2,9,9,3,3,-1,10,9,1,3,3,.005548601038753986,.4884265959262848,.6203498244285583,0,2,8,7,3,3,-1,8,8,3,1,3,-.00694611482322216,.262593001127243,.5011097192764282,0,2,14,0,2,3,-1,14,0,1,3,2,.00013569870498031378,.4340794980525971,.5628312230110168,0,2,1,0,18,9,-1,7,0,6,9,3,-.0458802506327629,.6507998704910278,.4696274995803833,0,2,11,5,4,15,-1,11,5,2,15,2,-.0215825606137514,.3826502859592438,.5287616848945618,0,2,5,5,4,15,-1,7,5,2,15,2,-.0202095396816731,.3233368098735809,.5074477195739746,0,2,14,0,2,3,-1,14,0,1,3,2,.005849671084433794,.5177603960037231,.4489670991897583,0,2,4,0,2,3,-1,5,0,1,3,2,-5747637987951748e-20,.4020850956439972,.5246363878250122,0,3,11,12,2,2,-1,12,12,1,1,2,11,13,1,1,2,-.001151310047134757,.6315072178840637,.490515410900116,0,3,7,12,2,2,-1,7,12,1,1,2,8,13,1,1,2,.0019862831104546785,.4702459871768951,.6497151255607605,0,2,12,0,3,4,-1,13,0,1,4,3,-.005271951202303171,.3650383949279785,.5227652788162231,0,2,4,11,3,3,-1,4,12,3,1,3,.0012662699446082115,.5166100859642029,.387761801481247,0,2,12,7,4,2,-1,12,8,4,1,2,-.006291944067925215,.737589418888092,.5023847818374634,0,2,8,10,3,2,-1,9,10,1,2,3,.000673601112794131,.4423226118087769,.5495585799217224,0,2,9,9,3,2,-1,10,9,1,2,3,-.0010523450328037143,.5976396203041077,.4859583079814911,0,2,8,9,3,2,-1,9,9,1,2,3,-.00044216238893568516,.5955939292907715,.4398930966854096,0,2,12,0,3,4,-1,13,0,1,4,3,.0011747940443456173,.5349888205528259,.4605058133602142,0,2,5,0,3,4,-1,6,0,1,4,3,.005245743785053492,.5049191117286682,.2941577136516571,0,3,4,14,12,4,-1,10,14,6,2,2,4,16,6,2,2,-.0245397202670574,.2550177872180939,.5218586921691895,0,2,8,13,2,3,-1,8,14,2,1,3,.0007379304151982069,.4424861073493958,.5490816235542297,0,2,10,10,3,8,-1,10,14,3,4,2,.0014233799884095788,.5319514274597168,.4081355929374695,0,3,8,10,4,8,-1,8,10,2,4,2,10,14,2,4,2,-.0024149110540747643,.4087659120559692,.5238950252532959,0,2,10,8,3,1,-1,11,8,1,1,3,-.0012165299849584699,.567457914352417,.4908052980899811,0,2,9,12,1,6,-1,9,15,1,3,2,-.0012438809499144554,.4129425883293152,.5256118178367615,0,2,10,8,3,1,-1,11,8,1,1,3,.006194273941218853,.5060194134712219,.7313653230667114,0,2,7,8,3,1,-1,8,8,1,1,3,-.0016607169527560472,.5979632139205933,.4596369862556458,0,2,5,2,15,14,-1,5,9,15,7,2,-.0273162592202425,.4174365103244782,.5308842062950134,0,3,2,1,2,10,-1,2,1,1,5,2,3,6,1,5,2,-.00158455700147897,.56158047914505,.4519486129283905,0,2,14,14,2,3,-1,14,15,2,1,3,-.0015514739789068699,.4076187014579773,.5360785126686096,0,2,2,7,3,3,-1,3,7,1,3,3,.0003844655875582248,.4347293972969055,.5430442094802856,0,2,17,4,3,3,-1,17,5,3,1,3,-.0146722598001361,.1659304946660996,.5146093964576721,0,2,0,4,3,3,-1,0,5,3,1,3,.008160888217389584,.4961819052696228,.1884745955467224,0,3,13,5,6,2,-1,16,5,3,1,2,13,6,3,1,2,.0011121659772470593,.4868263900279999,.6093816161155701,0,2,4,19,12,1,-1,8,19,4,1,3,-.007260377053171396,.6284325122833252,.4690375924110413,0,2,12,12,2,4,-1,12,14,2,2,2,-.00024046430189628154,.5575000047683716,.4046044051647186,0,2,3,15,1,3,-1,3,16,1,1,3,-.00023348190006799996,.4115762114524841,.5252848267555237,0,2,11,16,6,4,-1,11,16,3,4,2,.005573648028075695,.4730072915554047,.5690100789070129,0,2,2,10,3,10,-1,3,10,1,10,3,.0306237693876028,.4971886873245239,.1740095019340515,0,2,12,8,2,4,-1,12,8,1,4,2,.0009207479888573289,.5372117757797241,.4354872107505798,0,2,6,8,2,4,-1,7,8,1,4,2,-4355073906481266e-20,.5366883873939514,.4347316920757294,0,2,10,14,2,3,-1,10,14,1,3,2,-.006645271088927984,.3435518145561218,.516053318977356,0,2,5,1,10,3,-1,10,1,5,3,2,.0432219989597797,.4766792058944702,.7293652892112732,0,2,10,7,3,2,-1,11,7,1,2,3,.0022331769578158855,.5029315948486328,.5633171200752258,0,2,5,6,9,2,-1,8,6,3,2,3,.0031829739455133677,.4016092121601105,.5192136764526367,0,2,9,8,2,2,-1,9,9,2,1,2,-.00018027749320026487,.4088315963745117,.5417919754981995,0,3,2,11,16,6,-1,2,11,8,3,2,10,14,8,3,2,-.0052934689447283745,.407567709684372,.5243561863899231,0,3,12,7,2,2,-1,13,7,1,1,2,12,8,1,1,2,.0012750959722325206,.4913282990455627,.6387010812759399,0,2,9,5,2,3,-1,9,6,2,1,3,.004338532220572233,.5031672120094299,.2947346866130829,0,2,9,7,3,2,-1,10,7,1,2,3,.00852507445961237,.4949789047241211,.6308869123458862,0,2,5,1,8,12,-1,5,7,8,6,2,-.0009426635224372149,.5328366756439209,.4285649955272675,0,2,13,5,2,2,-1,13,6,2,1,2,.0013609660090878606,.4991525113582611,.5941501259803772,0,2,5,5,2,2,-1,5,6,2,1,2,.0004478250921238214,.4573504030704498,.5854480862617493,0,2,12,4,3,3,-1,12,5,3,1,3,.001336005050688982,.4604358971118927,.584905207157135,0,2,4,14,2,3,-1,4,15,2,1,3,-.0006096754805184901,.3969388902187347,.522942304611206,0,2,12,4,3,3,-1,12,5,3,1,3,-.002365678083151579,.5808320045471191,.4898357093334198,0,2,5,4,3,3,-1,5,5,3,1,3,.001073434017598629,.435121089220047,.5470039248466492,0,3,9,14,2,6,-1,10,14,1,3,2,9,17,1,3,2,.0021923359017819166,.535506010055542,.3842903971672058,0,2,8,14,3,2,-1,9,14,1,2,3,.005496861878782511,.5018138885498047,.2827191948890686,0,2,9,5,6,6,-1,11,5,2,6,3,-.0753688216209412,.1225076019763947,.5148826837539673,0,2,5,5,6,6,-1,7,5,2,6,3,.0251344703137875,.4731766879558563,.702544629573822,0,2,13,13,1,2,-1,13,14,1,1,2,-2935859993158374e-20,.5430532097816467,.465608686208725,0,2,0,2,10,2,-1,0,3,10,1,2,-.0005835591000504792,.4031040072441101,.5190119743347168,0,2,13,13,1,2,-1,13,14,1,1,2,-.0026639450807124376,.4308126866817474,.5161771178245544,0,3,5,7,2,2,-1,5,7,1,1,2,6,8,1,1,2,-.0013804089976474643,.621982991695404,.4695515930652618,0,2,13,5,2,7,-1,13,5,1,7,2,.0012313219485804439,.5379363894462585,.4425831139087677,0,2,6,13,1,2,-1,6,14,1,1,2,-14644179827882908e-21,.5281640291213989,.4222503006458283,0,2,11,0,3,7,-1,12,0,1,7,3,-.0128188095986843,.2582092881202698,.5179932713508606,0,3,0,3,2,16,-1,0,3,1,8,2,1,11,1,8,2,.0228521898388863,.4778693020343781,.7609264254570007,0,2,11,0,3,7,-1,12,0,1,7,3,.0008230597013607621,.5340992212295532,.4671724140644074,0,2,6,0,3,7,-1,7,0,1,7,3,.0127701200544834,.4965761005878449,.1472366005182266,0,2,11,16,8,4,-1,11,16,4,4,2,-.0500515103340149,.641499400138855,.5016592144966125,0,2,1,16,8,4,-1,5,16,4,4,2,.0157752707600594,.4522320032119751,.5685362219810486,0,2,13,5,2,7,-1,13,5,1,7,2,-.0185016207396984,.2764748930931091,.5137959122657776,0,2,5,5,2,7,-1,6,5,1,7,2,.0024626250378787518,.5141941905021667,.3795408010482788,0,2,18,6,2,14,-1,18,13,2,7,2,.0629161670804024,.5060648918151855,.658043384552002,0,2,6,10,3,4,-1,6,12,3,2,2,-21648500478477217e-21,.5195388197898865,.401988685131073,0,2,14,7,1,2,-1,14,8,1,1,2,.0021180990152060986,.4962365031242371,.5954458713531494,0,3,0,1,18,6,-1,0,1,9,3,2,9,4,9,3,2,-.0166348908096552,.3757933080196381,.517544686794281,0,2,14,7,1,2,-1,14,8,1,1,2,-.002889947034418583,.6624013781547546,.5057178735733032,0,2,0,6,2,14,-1,0,13,2,7,2,.076783262193203,.4795796871185303,.8047714829444885,0,2,17,0,3,12,-1,18,0,1,12,3,.003917067777365446,.4937882125377655,.5719941854476929,0,2,0,6,18,3,-1,0,7,18,1,3,-.0726706013083458,.0538945607841015,.4943903982639313,0,2,6,0,14,16,-1,6,8,14,8,2,.5403950214385986,.5129774212837219,.1143338978290558,0,2,0,0,3,12,-1,1,0,1,12,3,.0029510019812732935,.4528343975543976,.5698574185371399,0,2,13,0,3,7,-1,14,0,1,7,3,.0034508369863033295,.5357726812362671,.4218730926513672,0,2,5,7,1,2,-1,5,8,1,1,2,-.0004207793972454965,.5916172862052917,.4637925922870636,0,2,14,4,6,6,-1,14,6,6,2,3,.0033051050268113613,.5273385047912598,.438204288482666,0,2,5,7,7,2,-1,5,8,7,1,2,.0004773506079800427,.4046528041362763,.5181884765625,0,2,8,6,6,9,-1,8,9,6,3,3,-.0259285103529692,.7452235817909241,.5089386105537415,0,2,5,4,6,1,-1,7,4,2,1,3,-.002972979098558426,.3295435905456543,.5058795213699341,0,3,13,0,6,4,-1,16,0,3,2,2,13,2,3,2,2,.005850832909345627,.4857144057750702,.5793024897575378,0,2,1,2,18,12,-1,1,6,18,4,3,-.0459675192832947,.4312731027603149,.5380653142929077,0,2,3,2,17,12,-1,3,6,17,4,3,.1558596044778824,.5196170210838318,.1684713959693909,0,2,5,14,7,3,-1,5,15,7,1,3,.0151648297905922,.4735757112503052,.6735026836395264,0,2,10,14,1,3,-1,10,15,1,1,3,-.0010604249546304345,.5822926759719849,.4775702953338623,0,2,3,14,3,3,-1,3,15,3,1,3,.006647629197686911,.4999198913574219,.231953501701355,0,2,14,4,6,6,-1,14,6,6,2,3,-.0122311301529408,.4750893115997315,.5262982249259949,0,2,0,4,6,6,-1,0,6,6,2,3,.005652888212352991,.5069767832756042,.3561818897724152,0,2,12,5,4,3,-1,12,6,4,1,3,.0012977829901501536,.4875693917274475,.5619062781333923,0,2,4,5,4,3,-1,4,6,4,1,3,.0107815898954868,.4750770032405853,.6782308220863342,0,2,18,0,2,6,-1,18,2,2,2,3,.002865477930754423,.5305461883544922,.4290736019611359,0,2,8,1,4,9,-1,10,1,2,9,2,.0028663428965955973,.4518479108810425,.5539351105690002,0,2,6,6,8,2,-1,6,6,4,2,2,-.005198332015424967,.4149119853973389,.5434188842773438,0,3,6,5,4,2,-1,6,5,2,1,2,8,6,2,1,2,.005373999010771513,.471789687871933,.6507657170295715,0,2,10,5,2,3,-1,10,6,2,1,3,-.0146415298804641,.2172164022922516,.5161777138710022,0,2,9,5,1,3,-1,9,6,1,1,3,-15042580344015732e-21,.533738374710083,.4298836886882782,0,2,9,10,2,2,-1,9,11,2,1,2,-.0001187566012958996,.4604594111442566,.5582447052001953,0,2,0,8,4,3,-1,0,9,4,1,3,.0169955305755138,.4945895075798035,.0738800764083862,0,2,6,0,8,6,-1,6,3,8,3,2,-.0350959412753582,.70055091381073,.4977591037750244,0,3,1,0,6,4,-1,1,0,3,2,2,4,2,3,2,2,.0024217350874096155,.4466265141963959,.5477694272994995,0,2,13,0,3,7,-1,14,0,1,7,3,-.0009634033776819706,.4714098870754242,.5313338041305542,0,2,9,16,2,2,-1,9,17,2,1,2,.00016391130338888615,.4331546127796173,.5342242121696472,0,2,11,4,6,10,-1,11,9,6,5,2,-.0211414601653814,.2644700109958649,.5204498767852783,0,2,0,10,19,2,-1,0,11,19,1,2,.0008777520270086825,.5208349823951721,.4152742922306061,0,2,9,5,8,9,-1,9,8,8,3,3,-.0279439203441143,.6344125270843506,.5018811821937561,0,2,4,0,3,7,-1,5,0,1,7,3,.006729737855494022,.5050438046455383,.3500863909721375,0,3,8,6,4,12,-1,10,6,2,6,2,8,12,2,6,2,.0232810396701097,.4966318011283875,.6968677043914795,0,2,0,2,6,4,-1,0,4,6,2,2,-.0116449799388647,.3300260007381439,.5049629807472229,0,2,8,15,4,3,-1,8,16,4,1,3,.0157643090933561,.4991598129272461,.7321153879165649,0,2,8,0,3,7,-1,9,0,1,7,3,-.001361147966235876,.3911735117435455,.5160670876502991,0,2,9,5,3,4,-1,10,5,1,4,3,-.0008152233785949647,.5628911256790161,.49497190117836,0,2,8,5,3,4,-1,9,5,1,4,3,-.0006006627227179706,.585359513759613,.4550595879554749,0,2,7,6,6,1,-1,9,6,2,1,3,.0004971551825292408,.4271470010280609,.5443599224090576,0,3,7,14,4,4,-1,7,14,2,2,2,9,16,2,2,2,.0023475370835512877,.5143110752105713,.3887656927108765,0,3,13,14,4,6,-1,15,14,2,3,2,13,17,2,3,2,-.008926156908273697,.6044502258300781,.497172087430954,0,2,7,8,1,8,-1,7,12,1,4,2,-.013919910416007,.2583160996437073,.5000367760658264,0,3,16,0,2,8,-1,17,0,1,4,2,16,4,1,4,2,.0010209949687123299,.4857374131679535,.5560358166694641,0,3,2,0,2,8,-1,2,0,1,4,2,3,4,1,4,2,-.0027441629208624363,.5936884880065918,.464577704668045,0,2,6,1,14,3,-1,6,2,14,1,3,-.0162001308053732,.3163014948368073,.5193495154380798,0,2,7,9,3,10,-1,7,14,3,5,2,.004333198070526123,.5061224102973938,.3458878993988037,0,2,9,14,2,2,-1,9,15,2,1,2,.0005849793087691069,.4779017865657806,.5870177745819092,0,2,7,7,6,8,-1,7,11,6,4,2,-.0022466450463980436,.4297851026058197,.5374773144721985,0,2,9,7,3,6,-1,9,10,3,3,2,.0023146099410951138,.5438671708106995,.4640969932079315,0,2,7,13,3,3,-1,7,14,3,1,3,.008767912164330482,.472689300775528,.6771789789199829,0,2,9,9,2,2,-1,9,10,2,1,2,-.00022448020172305405,.4229173064231873,.5428048968315125,0,2,0,1,18,2,-1,6,1,6,2,3,-.007433602120727301,.6098880767822266,.4683673977851868,0,2,7,1,6,14,-1,7,8,6,7,2,-.0023189240600913763,.5689436793327332,.4424242079257965,0,2,1,9,18,1,-1,7,9,6,1,3,-.0021042178850620985,.3762221038341522,.5187087059020996,0,2,9,7,2,2,-1,9,7,1,2,2,.000460348412161693,.4699405133724213,.5771207213401794,0,2,9,3,2,9,-1,10,3,1,9,2,.0010547629790380597,.4465216994285584,.5601701736450195,0,2,18,14,2,3,-1,18,15,2,1,3,.0008714881842024624,.544980525970459,.3914709091186523,0,2,7,11,3,1,-1,8,11,1,1,3,.00033364820410497487,.4564009010791779,.5645738840103149,0,2,10,8,3,4,-1,11,8,1,4,3,-.0014853250468149781,.5747377872467041,.4692778885364533,0,2,7,14,3,6,-1,8,14,1,6,3,.0030251620337367058,.5166196823120117,.3762814104557037,0,2,10,8,3,4,-1,11,8,1,4,3,.005028074141591787,.5002111792564392,.6151527166366577,0,2,7,8,3,4,-1,8,8,1,4,3,-.0005816451157443225,.5394598245620728,.4390751123428345,0,2,7,9,6,9,-1,7,12,6,3,3,.0451415292918682,.5188326835632324,.206303596496582,0,2,0,14,2,3,-1,0,15,2,1,3,-.001079562003724277,.3904685080051422,.5137907266616821,0,2,11,12,1,2,-1,11,13,1,1,2,.00015995999274309725,.4895322918891907,.5427504181861877,0,2,4,3,8,3,-1,8,3,4,3,2,-.0193592701107264,.6975228786468506,.4773507118225098,0,2,0,4,20,6,-1,0,4,10,6,2,.207255095243454,.5233635902404785,.3034991919994354,0,2,9,14,1,3,-1,9,15,1,1,3,-.00041953290929086506,.5419396758079529,.4460186064243317,0,2,8,14,4,3,-1,8,15,4,1,3,.0022582069505006075,.4815764129161835,.6027408838272095,0,2,0,15,14,4,-1,0,17,14,2,2,-.0067811207845807076,.3980278968811035,.5183305740356445,0,2,1,14,18,6,-1,1,17,18,3,2,.0111543098464608,.543123185634613,.4188759922981262,0,3,0,0,10,6,-1,0,0,5,3,2,5,3,5,3,2,.0431624315679073,.4738228023052216,.6522961258888245]);\n\n// -------------------------------------------------------\n// tracking.js eye classifier data (ViolaJones)\n// -------------------------------------------------------\n/**\n * tracking.js - A modern approach for Computer Vision on the web.\n * @author Eduardo Lundgren <edu@rdo.io>\n * @version v1.0.0\n * @link http://trackingjs.com\n * @license BSD\n */\ntracking.ViolaJones.classifiers.eye=new Float64Array([20,20,-1.4562760591506958,6,0,2,0,8,20,12,-1,0,14,20,6,2,.129639595746994,-.7730420827865601,.6835014820098877,0,2,9,1,4,15,-1,9,6,4,5,3,-.0463268086314201,.5735275149345398,-.4909768998622894,0,2,6,10,9,2,-1,9,10,3,2,3,-.0161730907857418,.6025434136390686,-.3161070942878723,0,2,7,0,10,9,-1,7,3,10,3,3,-.0458288416266441,.6417754888534546,-.1554504036903381,0,2,12,2,2,18,-1,12,8,2,6,3,-.0537596195936203,.5421931743621826,-.2048082947731018,0,2,8,6,8,6,-1,8,9,8,3,2,.0341711901128292,-.2338819056749344,.4841090142726898,-1.2550230026245117,12,0,2,2,0,17,18,-1,2,6,17,6,3,-.2172762006521225,.7109889984130859,-.5936073064804077,0,2,10,10,1,8,-1,10,14,1,4,2,.0120719699189067,-.2824048101902008,.5901355147361755,0,2,7,10,9,2,-1,10,10,3,2,3,-.0178541392087936,.5313752293586731,-.2275896072387695,0,2,5,1,6,6,-1,5,3,6,2,3,.0223336108028889,-.1755609959363937,.633561372756958,0,2,3,1,15,9,-1,3,4,15,3,3,-.091420017182827,.6156309247016907,-.1689953058958054,0,2,6,3,9,6,-1,6,5,9,2,3,.028973650187254,-.1225007995963097,.7440117001533508,0,2,8,17,6,3,-1,10,17,2,3,3,.007820346392691135,.1697437018156052,-.6544165015220642,0,2,9,10,9,1,-1,12,10,3,1,3,.0203404892235994,-.1255664974451065,.8271045088768005,0,2,1,7,6,11,-1,3,7,2,11,3,-.0119261499494314,.3860568106174469,-.2099234014749527,0,2,9,18,3,1,-1,10,18,1,1,3,-.000972811016254127,-.6376119256019592,.129523903131485,0,2,16,16,1,2,-1,16,17,1,1,2,18322050891583785e-21,-.3463147878646851,.2292426973581314,0,2,9,17,6,3,-1,11,17,2,3,3,-.008085441775619984,-.6366580128669739,.1307865977287293,-1.372818946838379,9,0,2,8,0,5,18,-1,8,6,5,6,3,-.1181226968765259,.6784452199935913,-.5004578232765198,0,2,6,7,9,7,-1,9,7,3,7,3,-.0343327596783638,.6718636155128479,-.3574487864971161,0,2,14,6,6,10,-1,16,6,2,10,3,-.0215307995676994,.7222070097923279,-.1819241940975189,0,2,9,8,9,5,-1,12,8,3,5,3,-.0219099707901478,.6652938723564148,-.2751022875308991,0,2,3,7,9,6,-1,6,7,3,6,3,-.0287135392427444,.6995570063591003,-.1961558014154434,0,2,1,7,6,6,-1,3,7,2,6,3,-.0114674801006913,.5926734805107117,-.2209735065698624,0,2,16,0,4,18,-1,16,6,4,6,3,-.0226111691445112,.3448306918144226,-.3837955892086029,0,2,0,17,3,3,-1,0,18,3,1,3,-.0019308089977130294,-.794457197189331,.1562865972518921,0,2,16,0,2,1,-1,17,0,1,1,2,5641991083393805e-20,-.3089601099491119,.3543108999729157,-1.2879480123519897,16,0,2,0,8,20,12,-1,0,14,20,6,2,.1988652050495148,-.5286070108413696,.3553672134876251,0,2,6,6,9,8,-1,9,6,3,8,3,-.0360089391469955,.4210968911647797,-.393489807844162,0,2,5,3,12,9,-1,5,6,12,3,3,-.0775698497891426,.4799154102802277,-.2512216866016388,0,2,4,16,1,2,-1,4,17,1,1,2,8263085328508168e-20,-.3847548961639404,.318492203950882,0,2,18,10,2,1,-1,19,10,1,1,2,.00032773229759186506,-.2642731964588165,.3254724144935608,0,2,9,8,6,5,-1,11,8,2,5,3,-.0185748506337404,.4673658907413483,-.1506727039813995,0,2,0,0,2,1,-1,1,0,1,1,2,-7000876212259755e-20,.2931315004825592,-.2536509931087494,0,2,6,8,6,6,-1,8,8,2,6,3,-.0185521300882101,.4627366065979004,-.1314805001020432,0,2,11,7,6,7,-1,13,7,2,7,3,-.0130304200574756,.4162721931934357,-.1775148957967758,0,2,19,14,1,2,-1,19,15,1,1,2,6569414108525962e-20,-.2803510129451752,.2668074071407318,0,2,6,17,1,2,-1,6,18,1,1,2,.00017005260451696813,-.2702724933624268,.2398165017366409,0,2,14,7,2,7,-1,15,7,1,7,2,-.0033129199873656034,.4441143870353699,-.1442888975143433,0,2,6,8,2,4,-1,7,8,1,4,2,.0017583490116521716,-.1612619012594223,.4294076859951019,0,2,5,8,12,6,-1,5,10,12,2,3,-.0251947492361069,.4068729877471924,-.1820258051156998,0,2,2,17,1,3,-1,2,18,1,1,3,.0014031709870323539,.0847597867250443,-.8001856803894043,0,2,6,7,3,6,-1,7,7,1,6,3,-.007399172987788916,.5576609969139099,-.1184315979480743,-1.2179850339889526,23,0,2,6,7,9,12,-1,9,7,3,12,3,-.0299430806189775,.3581081032752991,-.3848763108253479,0,2,6,2,11,12,-1,6,6,11,4,3,-.1256738007068634,.3931693136692047,-.3001225888729096,0,2,1,12,5,8,-1,1,16,5,4,2,.0053635272197425365,-.4390861988067627,.1925701051950455,0,2,14,7,6,7,-1,16,7,2,7,3,-.008097182027995586,.399066686630249,-.2340787053108215,0,2,10,8,6,6,-1,12,8,2,6,3,-.0165979098528624,.4209528863430023,-.2267484068870544,0,2,16,18,4,2,-1,16,19,4,1,2,-.0020199299324303865,-.7415673136711121,.1260118931531906,0,2,18,17,2,3,-1,18,18,2,1,3,-.0015202340437099338,-.7615460157394409,.0863736122846603,0,2,9,7,3,7,-1,10,7,1,7,3,-.004966394044458866,.4218223989009857,-.1790491938591003,0,2,5,6,6,8,-1,7,6,2,8,3,-.0192076005041599,.4689489901065826,-.1437875032424927,0,2,2,6,6,11,-1,4,6,2,11,3,-.0122226802632213,.3284207880496979,-.218021497130394,0,2,8,10,12,8,-1,8,14,12,4,2,.0575486682355404,-.3676880896091461,.2435711026191711,0,2,7,17,6,3,-1,9,17,2,3,3,-.00957940798252821,-.7224506735801697,.0636645630002022,0,2,10,9,3,3,-1,11,9,1,3,3,-.002954574069008231,.358464390039444,-.1669632941484451,0,2,8,8,3,6,-1,9,8,1,6,3,-.004201799165457487,.390948086977005,-.1204179003834724,0,2,7,0,6,5,-1,9,0,2,5,3,-.0136249903589487,-.5876771807670593,.0884047299623489,0,2,6,17,1,3,-1,6,18,1,1,3,6285311246756464e-20,-.2634845972061157,.2141927927732468,0,2,0,18,4,2,-1,0,19,4,1,2,-.0026782939676195383,-.7839016914367676,.0805269628763199,0,2,4,1,11,9,-1,4,4,11,3,3,-.0705971792340279,.414692610502243,-.1398995965719223,0,2,3,1,14,9,-1,3,4,14,3,3,.0920936465263367,-.1305518001317978,.5043578147888184,0,2,0,9,6,4,-1,2,9,2,4,3,-.008800438605248928,.3660975098609924,-.1403664946556091,0,2,18,13,1,2,-1,18,14,1,1,2,750809776945971e-19,-.2970443964004517,.207029402256012,0,2,13,5,3,11,-1,14,5,1,11,3,-.002987045096233487,.3561570048332214,-.1544596999883652,0,3,0,18,8,2,-1,0,18,4,1,2,4,19,4,1,2,-.002644150983542204,-.5435351729393005,.1029511019587517,-1.2905240058898926,27,0,2,5,8,12,5,-1,9,8,4,5,3,-.0478624701499939,.4152823984622955,-.3418582081794739,0,2,4,7,11,10,-1,4,12,11,5,2,.087350532412529,-.3874978125095367,.2420420050621033,0,2,14,9,6,4,-1,16,9,2,4,3,-.0168494991958141,.5308247804641724,-.1728291064500809,0,2,0,7,6,8,-1,3,7,3,8,2,-.0288700293749571,.3584350943565369,-.2240259051322937,0,2,0,16,3,3,-1,0,17,3,1,3,.00256793899461627,.1499049961566925,-.6560940742492676,0,2,7,11,12,1,-1,11,11,4,1,3,-.0241166595369577,.5588967800140381,-.148102805018425,0,2,4,8,9,4,-1,7,8,3,4,3,-.0328266583383083,.4646868109703064,-.1078552976250649,0,2,5,16,6,4,-1,7,16,2,4,3,-.0152330603450537,-.7395442724227905,.056236881762743,0,2,18,17,1,3,-1,18,18,1,1,3,-.0003020951116923243,-.4554882049560547,.0970698371529579,0,2,18,17,1,3,-1,18,18,1,1,3,.0007536510820500553,.0951472967863083,-.5489501953125,0,3,4,9,4,10,-1,4,9,2,5,2,6,14,2,5,2,-.0106389503926039,.4091297090053558,-.1230840981006622,0,2,4,8,6,4,-1,6,8,2,4,3,-.007521783001720905,.4028914868831635,-.1604878008365631,0,2,10,2,2,18,-1,10,8,2,6,3,-.1067709997296333,.6175932288169861,-.0730911865830421,0,3,0,5,8,6,-1,0,5,4,3,2,4,8,4,3,2,.0162569191306829,-.1310368031263351,.3745365142822266,0,2,6,0,6,5,-1,8,0,2,5,3,-.020679360255599,-.71402907371521,.0523900091648102,0,2,18,0,2,14,-1,18,7,2,7,2,.0170523691922426,.1282286047935486,-.3108068108558655,0,2,8,18,4,2,-1,10,18,2,2,2,-.0057122060097754,-.605565071105957,.0818847566843033,0,2,1,17,6,3,-1,1,18,6,1,3,20851430235779844e-21,-.2681298851966858,.1445384025573731,0,2,11,8,3,5,-1,12,8,1,5,3,.007928443141281605,-.078795351088047,.5676258206367493,0,2,11,8,3,4,-1,12,8,1,4,3,-.0025217379443347454,.3706862926483154,-.1362057030200958,0,2,11,0,6,5,-1,13,0,2,5,3,-.0224261991679668,-.6870499849319458,.0510628595948219,0,2,1,7,6,7,-1,3,7,2,7,3,-.007645144127309322,.2349222004413605,-.1790595948696137,0,2,0,13,1,3,-1,0,14,1,1,3,-.0011175329564139247,-.5986905097961426,.0743244364857674,0,2,3,2,9,6,-1,3,4,9,2,3,.0192127898335457,-.1570255011320114,.2973746955394745,0,2,8,6,9,2,-1,8,7,9,1,2,.00562934298068285,-.0997690185904503,.4213027060031891,0,2,0,14,3,6,-1,0,16,3,2,3,-.00956718623638153,-.6085879802703857,.0735062584280968,0,2,1,11,6,4,-1,3,11,2,4,3,.0112179601565003,-.103208102285862,.4190984964370728,-1.160048007965088,28,0,2,6,9,9,3,-1,9,9,3,3,3,-.0174864400178194,.3130728006362915,-.3368118107318878,0,2,6,0,9,6,-1,6,2,9,2,3,.0307146497070789,-.1876619011163712,.5378080010414124,0,2,8,5,6,6,-1,8,7,6,2,3,-.0221887193620205,.3663788139820099,-.1612481027841568,0,2,1,12,2,1,-1,2,12,1,1,2,-50700771680567414e-21,.2124571055173874,-.2844462096691132,0,2,10,10,6,2,-1,12,10,2,2,3,-.007017042022198439,.3954311013221741,-.1317359060049057,0,2,13,8,6,6,-1,15,8,2,6,3,-.00685636093840003,.3037385940551758,-.2065781950950623,0,2,6,16,6,4,-1,8,16,2,4,3,-.0141292596235871,-.7650300860404968,.0982131883502007,0,2,8,0,9,9,-1,8,3,9,3,3,-.047915481030941,.483073890209198,-.1300680935382843,0,2,18,17,1,3,-1,18,18,1,1,3,47032979637151584e-21,-.2521657049655914,.2438668012619019,0,2,18,17,1,3,-1,18,18,1,1,3,.0010221180273219943,.0688576027750969,-.6586114168167114,0,2,7,10,3,3,-1,8,10,1,3,3,-.002605610992759466,.4294202923774719,-.1302246004343033,0,3,9,14,2,2,-1,9,14,1,1,2,10,15,1,1,2,5450534081319347e-20,-.1928862035274506,.2895849943161011,0,3,9,14,2,2,-1,9,14,1,1,2,10,15,1,1,2,-6672115705441684e-20,.3029071092605591,-.1985436975955963,0,2,0,8,19,12,-1,0,14,19,6,2,.2628143131732941,-.2329394072294235,.2369246035814285,0,2,7,6,9,14,-1,10,6,3,14,3,-.0235696695744991,.1940104067325592,-.2848461866378784,0,2,13,8,3,4,-1,14,8,1,4,3,-.003912017215043306,.5537897944450378,-.0956656783819199,0,2,4,17,1,3,-1,4,18,1,1,3,5078879985376261e-20,-.239126592874527,.217994898557663,0,2,4,9,6,3,-1,6,9,2,3,3,-.007873201742768288,.4069742858409882,-.1276804059743881,0,2,2,18,5,2,-1,2,19,5,1,2,-.0016778609715402126,-.5774465799331665,.0973247885704041,0,3,7,8,2,2,-1,7,8,1,1,2,8,9,1,1,2,-.0002683243073988706,.2902188003063202,-.1683126986026764,0,3,7,8,2,2,-1,7,8,1,1,2,8,9,1,1,2,7868718239478767e-20,-.1955157071352005,.2772096991539002,0,2,5,10,13,2,-1,5,11,13,1,2,.0129535002633929,-.0968383178114891,.4032387137413025,0,2,10,8,1,9,-1,10,11,1,3,3,-.0130439596250653,.4719856977462769,-.0892875492572784,0,3,15,8,2,12,-1,15,8,1,6,2,16,14,1,6,2,.0030261781066656113,-.1362338066101074,.3068627119064331,0,2,4,0,3,5,-1,5,0,1,5,3,-.006043803878128529,-.779541015625,.0573163107037544,0,2,12,6,3,7,-1,13,6,1,7,3,-.0022507249377667904,.3087705969810486,-.1500630974769592,0,2,7,16,6,4,-1,9,16,2,4,3,.0158268101513386,.0645518898963928,-.7245556712150574,0,2,9,16,2,1,-1,10,16,1,1,2,6586450763279572e-20,-.1759884059429169,.2321038991212845,-1.2257250547409058,36,0,2,6,10,9,2,-1,9,10,3,2,3,-.0278548691421747,.4551844894886017,-.1809991002082825,0,2,0,6,15,14,-1,0,13,15,7,2,.1289504021406174,-.5256553292274475,.1618890017271042,0,2,9,1,5,6,-1,9,3,5,2,3,.0244031809270382,-.1497496068477631,.4235737919807434,0,2,3,9,3,4,-1,4,9,1,4,3,-.0024458570405840874,.3294866979122162,-.1744769066572189,0,2,5,7,3,6,-1,6,7,1,6,3,-.0035336529836058617,.4742664098739624,-.0736183598637581,0,2,17,16,1,2,-1,17,17,1,1,2,5135815081303008e-20,-.3042193055152893,.1563327014446259,0,2,9,8,6,12,-1,11,8,2,12,3,-.0162256807088852,.2300218045711517,-.2035982012748718,0,2,6,10,6,1,-1,8,10,2,1,3,-.004600700922310352,.4045926928520203,-.1348544061183929,0,2,7,17,9,3,-1,10,17,3,3,3,-.0219289995729923,-.6872448921203613,.0806842669844627,0,2,14,18,6,2,-1,14,19,6,1,2,-.002897121012210846,-.6961960792541504,.0485452190041542,0,2,9,5,3,14,-1,10,5,1,14,3,-.0044074649922549725,.2516626119613648,-.1623664945363998,0,2,8,16,9,4,-1,11,16,3,4,3,.0284371692687273,.0603942610323429,-.6674445867538452,0,2,0,0,4,14,-1,0,7,4,7,2,.0832128822803497,.0643579214811325,-.5362604260444641,0,2,8,1,6,3,-1,10,1,2,3,3,-.0124193299561739,-.708168625831604,.0575266107916832,0,2,6,8,3,4,-1,7,8,1,4,3,-.004699259996414185,.5125433206558228,-.0873508006334305,0,2,4,8,3,4,-1,5,8,1,4,3,-.0007802580948919058,.266876608133316,-.1796150952577591,0,2,5,1,6,5,-1,7,1,2,5,3,-.0197243392467499,-.6756373047828674,.0729419067502022,0,2,1,18,1,2,-1,1,19,1,1,2,.001026925048790872,.0539193190634251,-.5554018020629883,0,2,7,0,6,6,-1,7,2,6,2,3,-.0259571895003319,.5636252760887146,-.0718983933329582,0,2,0,18,4,2,-1,0,19,4,1,2,-.0012552699772641063,-.5034663081169128,.0896914526820183,0,2,12,3,8,12,-1,12,7,8,4,3,-.0499705784022808,.1768511980772018,-.2230195999145508,0,2,12,9,3,4,-1,13,9,1,4,3,-.002989961067214608,.391224205493927,-.1014975011348724,0,2,12,8,3,5,-1,13,8,1,5,3,.004854684229940176,-.1177017986774445,.4219093918800354,0,2,16,0,2,1,-1,17,0,1,1,2,.0001044886012095958,-.1733397990465164,.223444402217865,0,2,5,17,1,3,-1,5,18,1,1,3,5968926052446477e-20,-.2340963035821915,.1655824035406113,0,2,10,2,3,6,-1,10,4,3,2,3,-.0134239196777344,.4302381873130798,-.0997236520051956,0,2,4,17,2,3,-1,4,18,2,1,3,.002258199965581298,.0727209895849228,-.5750101804733276,0,2,12,7,1,9,-1,12,10,1,3,3,-.0125462803989649,.3618457913398743,-.1145701035857201,0,2,7,6,3,9,-1,8,6,1,9,3,-.002870576921850443,.2821053862571716,-.1236755028367043,0,2,17,13,3,6,-1,17,15,3,2,3,.0197856407612562,.0478767491877079,-.806662380695343,0,2,7,7,3,8,-1,8,7,1,8,3,.004758893046528101,-.1092538982629776,.3374697864055634,0,2,5,0,3,5,-1,6,0,1,5,3,-.006997426971793175,-.8029593825340271,.0457067005336285,0,2,4,6,9,8,-1,7,6,3,8,3,-.0130334803834558,.18680439889431,-.176889106631279,0,2,2,9,3,3,-1,3,9,1,3,3,-.0013742579612880945,.2772547900676727,-.1280900985002518,0,2,16,18,4,2,-1,16,19,4,1,2,.0027657810132950544,.0907589420676231,-.4259473979473114,0,2,17,10,3,10,-1,17,15,3,5,2,.0002894184144679457,-.388163298368454,.089267797768116,-1.2863140106201172,47,0,2,8,9,6,4,-1,10,9,2,4,3,-.0144692296162248,.3750782907009125,-.2492828965187073,0,2,5,2,10,12,-1,5,6,10,4,3,-.1331762969493866,.3016637861728668,-.2241407036781311,0,2,6,9,6,3,-1,8,9,2,3,3,-.010132160037756,.3698559105396271,-.1785001009702683,0,2,11,7,3,7,-1,12,7,1,7,3,-.007851118221879005,.4608676135540009,-.1293139010667801,0,2,12,8,6,4,-1,14,8,2,4,3,-.0142958397045732,.4484142959117889,-.1022624000906944,0,2,14,8,6,5,-1,16,8,2,5,3,-.005960694048553705,.279279887676239,-.1532382965087891,0,2,12,12,2,4,-1,12,14,2,2,2,.010932769626379,-.1514174044132233,.3988964855670929,0,2,3,15,1,2,-1,3,16,1,1,2,50430990086169913e-21,-.2268157005310059,.2164438962936401,0,2,12,7,3,4,-1,13,7,1,4,3,-.0058431681245565414,.4542014896869659,-.1258715987205505,0,2,10,0,6,6,-1,12,0,2,6,3,-.0223462097346783,-.6269019246101379,.0824031233787537,0,2,10,6,3,8,-1,11,6,1,8,3,-.00488366698846221,.2635925114154816,-.1468663066625595,0,2,16,17,1,2,-1,16,18,1,1,2,7550600275862962e-20,-.2450702041387558,.1667888015508652,0,2,16,16,1,3,-1,16,17,1,1,3,-.0004902699729427695,-.426499605178833,.0899735614657402,0,2,11,11,1,2,-1,11,12,1,1,2,.0014861579984426498,-.1204025000333786,.3009765148162842,0,2,3,7,6,9,-1,5,7,2,9,3,-.0119883399456739,.278524786233902,-.122443400323391,0,2,4,18,9,1,-1,7,18,3,1,3,.0105022396892309,.0404527597129345,-.7405040860176086,0,2,0,11,4,9,-1,0,14,4,3,3,-.0309630092233419,-.6284269094467163,.048013761639595,0,2,9,17,6,3,-1,11,17,2,3,3,.0114145204424858,.0394052118062973,-.7167412042617798,0,2,7,8,6,12,-1,9,8,2,12,3,-.0123370001092553,.1994132995605469,-.1927430033683777,0,2,6,8,3,4,-1,7,8,1,4,3,-.005994226783514023,.5131816267967224,-.0616580583155155,0,2,3,17,1,3,-1,3,18,1,1,3,-.0011923230485990644,-.72605299949646,.0506527200341225,0,2,11,9,6,4,-1,13,9,2,4,3,-.0074582789093256,.2960307896137238,-.1175478994846344,0,2,6,1,3,2,-1,7,1,1,2,3,.0027877509128302336,.0450687110424042,-.6953541040420532,0,2,1,0,2,1,-1,2,0,1,1,2,-.0002250320976600051,.200472503900528,-.1577524989843369,0,3,1,0,2,14,-1,1,0,1,7,2,2,7,1,7,2,-.005036788992583752,.292998194694519,-.1170049980282784,0,2,5,5,11,8,-1,5,9,11,4,2,.0747421607375145,-.1139231994748116,.3025662004947662,0,2,9,3,5,6,-1,9,5,5,2,3,.0202555190771818,-.1051589027047157,.4067046046257019,0,2,7,9,5,10,-1,7,14,5,5,2,.0442145094275475,-.2763164043426514,.1236386969685555,0,2,15,10,2,2,-1,16,10,1,2,2,-.0008725955849513412,.2435503005981445,-.1330094933509827,0,2,0,18,8,2,-1,0,19,8,1,2,-.0024453739169985056,-.5386617183685303,.062510646879673,0,2,7,17,1,3,-1,7,18,1,1,3,827253534225747e-19,-.2077220976352692,.1627043932676315,0,2,7,2,11,6,-1,7,4,11,2,3,-.036627110093832,.3656840920448303,-.0903302803635597,0,2,8,3,9,3,-1,8,4,9,1,3,.0030996399000287056,-.1318302005529404,.2535429894924164,0,2,0,9,2,2,-1,0,10,2,1,2,-.0024709280114620924,-.5685349702835083,.0535054318606853,0,2,0,5,3,6,-1,0,7,3,2,3,-.0141146704554558,-.4859901070594788,.0584852509200573,0,3,6,7,2,2,-1,6,7,1,1,2,7,8,1,1,2,.0008453726186417043,-.0800936371088028,.4026564955711365,0,2,7,6,3,6,-1,8,6,1,6,3,-.007109863217920065,.4470323920249939,-.0629474371671677,0,2,12,1,6,4,-1,14,1,2,4,3,-.0191259607672691,-.6642286777496338,.0498227700591087,0,2,9,11,6,8,-1,11,11,2,8,3,-.005077301058918238,.1737940013408661,-.168505996465683,0,2,17,15,3,3,-1,17,16,3,1,3,-.002919828984886408,-.6011028289794922,.0574279390275478,0,2,6,6,3,9,-1,6,9,3,3,3,-.0249021500349045,.233979806303978,-.1181845963001251,0,3,0,5,8,6,-1,0,5,4,3,2,4,8,4,3,2,.02014777995646,-.0894598215818405,.3602440059185028,0,2,0,6,1,3,-1,0,7,1,1,3,.001759764039888978,.0494584403932095,-.6310262084007263,0,2,17,0,2,6,-1,18,0,1,6,2,.0013812039978802204,-.1521805971860886,.1897173970937729,0,2,10,17,6,3,-1,12,17,2,3,3,-.0109045403078198,-.5809738039970398,.0448627285659313,0,3,13,15,2,2,-1,13,15,1,1,2,14,16,1,1,2,7515717879869044e-20,-.1377734988927841,.1954316049814224,0,2,4,0,12,3,-1,4,1,12,1,3,.003864977043122053,-.1030222997069359,.2537496984004974,-1.1189440488815308,48,0,2,5,3,10,9,-1,5,6,10,3,3,-.102158896625042,.4168125987052918,-.1665562987327576,0,2,7,7,9,7,-1,10,7,3,7,3,-.051939819008112,.3302395045757294,-.2071571052074432,0,2,5,8,9,6,-1,8,8,3,6,3,-.0427177809178829,.2609373033046722,-.1601389050483704,0,2,0,16,6,2,-1,0,17,6,1,2,.00043890418601222336,-.3475053012371063,.1391891986131668,0,2,12,6,7,14,-1,12,13,7,7,2,.0242643896490335,-.4255205988883972,.1357838064432144,0,2,13,7,6,8,-1,15,7,2,8,3,-.0238205995410681,.3174980878829956,-.1665204018354416,0,2,2,10,6,3,-1,4,10,2,3,3,-.007051818072795868,.3094717860221863,-.1333830058574677,0,2,18,17,1,3,-1,18,18,1,1,3,-.0006851715734228492,-.6008226275444031,.0877470001578331,0,2,7,1,6,2,-1,7,2,6,1,2,.0053705149330198765,-.1231144964694977,.3833355009555817,0,2,6,0,6,4,-1,6,2,6,2,2,-.0134035395458341,.3387736976146698,-.1014048978686333,0,2,8,18,6,2,-1,10,18,2,2,3,-.006685636006295681,-.6119359731674194,.0477402210235596,0,2,7,6,5,2,-1,7,7,5,1,2,-.0042887418530881405,.2527579069137573,-.1443451046943665,0,2,6,7,3,6,-1,7,7,1,6,3,-.0108767496421933,.5477573275566101,-.0594554804265499,0,3,18,18,2,2,-1,18,18,1,1,2,19,19,1,1,2,.0003788264002650976,.0834103003144264,-.4422636926174164,0,2,16,8,3,7,-1,17,8,1,7,3,-.002455014968290925,.2333099991083145,-.1396448016166687,0,2,0,16,2,3,-1,0,17,2,1,3,.0012721839593723416,.0604802891612053,-.4945608973503113,0,2,5,19,6,1,-1,7,19,2,1,3,-.004893315955996513,-.6683326959609985,.0462184995412827,0,2,9,5,6,6,-1,9,7,6,2,3,.0264499895274639,-.0732353627681732,.4442596137523651,0,2,0,10,2,4,-1,0,12,2,2,2,-.003370607038959861,-.4246433973312378,.0686765611171722,0,2,0,9,4,3,-1,2,9,2,3,2,-.0029559480026364326,.1621803939342499,-.1822299957275391,0,2,1,10,6,9,-1,3,10,2,9,3,.0306199099868536,-.0586433410644531,.532636284828186,0,2,9,0,6,2,-1,11,0,2,2,3,-.009576590731739998,-.6056268215179443,.0533459894359112,0,2,14,1,2,1,-1,15,1,1,1,2,6637249316554517e-20,-.1668083965778351,.1928416043519974,0,2,0,8,1,4,-1,0,10,1,2,2,.005097595043480396,.0441195107996464,-.574588418006897,0,3,15,6,2,2,-1,15,6,1,1,2,16,7,1,1,2,.0003711271856445819,-.1108639985322952,.2310539036989212,0,2,7,5,3,6,-1,8,5,1,6,3,-.008660758845508099,.4045628905296326,-.062446091324091,0,2,19,17,1,3,-1,19,18,1,1,3,.0008748915861360729,.0648751482367516,-.4487104117870331,0,2,7,10,3,1,-1,8,10,1,1,3,.0011120870476588607,-.09386146068573,.3045391142368317,0,2,12,1,6,6,-1,14,1,2,6,3,-.0238378196954727,-.5888742804527283,.0466594211757183,0,2,15,5,2,1,-1,16,5,1,1,2,.00022272899514064193,-.1489859968423843,.1770195066928864,0,2,8,2,7,4,-1,8,4,7,2,2,.0244674701243639,-.0557896010577679,.4920830130577087,0,2,4,0,14,15,-1,4,5,14,5,3,-.1423932015895844,.1519200056791306,-.1877889931201935,0,2,7,8,6,6,-1,9,8,2,6,3,-.0201231203973293,.2178010046482086,-.1208190023899078,0,2,11,17,1,3,-1,11,18,1,1,3,.00011513679783092812,-.1685658991336823,.1645192950963974,0,3,12,16,2,4,-1,12,16,1,2,2,13,18,1,2,2,-.0027556740678846836,-.6944203972816467,.039449468255043,0,2,10,13,2,1,-1,11,13,1,1,2,-7584391278214753e-20,.1894136965274811,-.151838406920433,0,2,11,8,3,3,-1,12,8,1,3,3,-.0070697711780667305,.4706459939479828,-.0579276196658611,0,2,2,0,6,8,-1,4,0,2,8,3,-.0373931787908077,-.7589244842529297,.0341160483658314,0,3,3,5,6,6,-1,3,5,3,3,2,6,8,3,3,2,-.0159956105053425,.3067046999931335,-.0875255763530731,0,2,10,8,3,3,-1,11,8,1,3,3,-.003118399064987898,.2619537115097046,-.0912148877978325,0,2,5,17,4,2,-1,5,18,4,1,2,.001065136049874127,-.1742756068706513,.1527764052152634,0,2,8,16,5,2,-1,8,17,5,1,2,-.0016029420075938106,.3561263084411621,-.0766299962997437,0,2,0,4,3,3,-1,0,5,3,1,3,.004361990839242935,.04935697093606,-.5922877192497253,0,2,6,3,6,2,-1,8,3,2,2,3,-.0107799097895622,-.6392217874526978,.0332045406103134,0,2,4,4,9,3,-1,7,4,3,3,3,-.004359086975455284,.1610738933086395,-.1522132009267807,0,2,0,13,1,4,-1,0,15,1,2,2,.007459606975317001,.0331729613244534,-.7500774264335632,0,2,0,17,8,3,-1,0,18,8,1,3,.008138544857501984,.0263252798467875,-.7173116207122803,0,2,6,1,11,6,-1,6,3,11,2,3,-.0333384908735752,.3353661000728607,-.070803590118885,-1.1418989896774292,55,0,2,4,10,6,2,-1,6,10,2,2,3,.0195539798587561,-.1043972000479698,.5312895178794861,0,2,10,8,1,12,-1,10,14,1,6,2,.0221229195594788,-.2474727034568787,.2084725052118301,0,2,5,8,3,4,-1,6,8,1,4,3,-.004182938951998949,.3828943967819214,-.1471157968044281,0,2,0,17,1,3,-1,0,18,1,1,3,-.0008638172876089811,-.6263288855552673,.1199325993657112,0,2,0,17,1,3,-1,0,18,1,1,3,.0007995861233212054,.0925734713673592,-.5516883134841919,0,2,13,8,3,4,-1,14,8,1,4,3,.009152757003903389,-.0729298070073128,.5551251173019409,0,2,1,5,5,4,-1,1,7,5,2,2,-.003938868176192045,.2019603997468948,-.2091203927993774,0,2,18,14,1,2,-1,18,15,1,1,2,.00014613410166930407,-.278618186712265,.1381741017103195,0,2,13,8,2,4,-1,14,8,1,4,2,-.0031691689509898424,.3668589890003204,-.0763082429766655,0,2,10,6,6,8,-1,12,6,2,8,3,-.0221893899142742,.39096599817276,-.1097154021263123,0,2,8,6,6,10,-1,10,6,2,10,3,-.007452360820025206,.1283859014511108,-.2415986955165863,0,2,17,16,1,3,-1,17,17,1,1,3,.000779970025178045,.0719780698418617,-.4397650063037872,0,2,1,7,2,10,-1,2,7,1,10,2,-.004678363911807537,.2156984955072403,-.1420592069625855,0,2,5,9,6,3,-1,7,9,2,3,3,-.0151886399835348,.364587813615799,-.08267592638731,0,2,0,8,5,12,-1,0,14,5,6,2,.0050619798712432384,-.3438040912151337,.0920682325959206,0,2,0,11,1,3,-1,0,12,1,1,3,-.0017351920250803232,-.6172549724578857,.0492144785821438,0,2,6,16,6,4,-1,8,16,2,4,3,-.012423450127244,-.5855895280838013,.0461126007139683,0,2,0,6,2,6,-1,0,8,2,2,3,-.0130314296111465,-.5971078872680664,.0406724587082863,0,2,11,18,2,1,-1,12,18,1,1,2,-.0012369629694148898,-.6833416819572449,.0331561788916588,0,2,5,1,9,2,-1,5,2,9,1,2,.006102210842072964,-.0947292372584343,.3010224103927612,0,2,0,0,1,2,-1,0,1,1,1,2,.0006695284973829985,.0818168669939041,-.351960301399231,0,2,15,9,3,3,-1,16,9,1,3,3,-.001797058037482202,.2371897995471954,-.1176870986819267,0,2,18,16,1,3,-1,18,17,1,1,3,-.0007107452838681638,-.4476378858089447,.0576824806630611,0,2,11,10,6,1,-1,13,10,2,1,3,-.005912647116929293,.4342541098594666,-.0668685734272003,0,2,1,3,4,4,-1,3,3,2,4,2,-.003313214983791113,.181500107049942,-.1418032050132752,0,2,11,2,1,18,-1,11,8,1,6,3,-.0608146600425243,.4722171127796173,-.0614106394350529,0,2,9,1,5,12,-1,9,5,5,4,3,-.0967141836881638,.2768316864967346,-.0944900363683701,0,2,12,0,8,1,-1,16,0,4,1,2,.003907355014234781,-.1227853000164032,.2105740010738373,0,2,8,6,3,10,-1,9,6,1,10,3,-.009043186902999878,.3564156889915466,-.0778062269091606,0,2,19,2,1,6,-1,19,4,1,2,3,-.004880003165453672,-.4103479087352753,.0696943774819374,0,2,18,6,2,2,-1,18,7,2,1,2,-.00435474282130599,-.7301788926124573,.0366551503539085,0,2,7,7,3,4,-1,8,7,1,4,3,-.009650062769651413,.5518112778663635,-.0531680807471275,0,2,5,0,6,5,-1,7,0,2,5,3,-.0173973105847836,-.5708423256874084,.0502140894532204,0,2,0,3,7,3,-1,0,4,7,1,3,-.006830432917922735,-.4618028104305267,.0502026900649071,0,2,1,6,2,1,-1,2,6,1,1,2,.00033255619928240776,-.0953627303242683,.2598375976085663,0,3,4,8,2,10,-1,4,8,1,5,2,5,13,1,5,2,-.0023100529797375202,.2287247031927109,-.1053353026509285,0,3,2,18,18,2,-1,2,18,9,1,2,11,19,9,1,2,-.0075426651164889336,-.5699051022529602,.0488634593784809,0,3,2,7,4,4,-1,2,7,2,2,2,4,9,2,2,2,-.0052723060362041,.3514518141746521,-.0823901072144508,0,2,17,3,3,4,-1,18,3,1,4,3,-.004857896827161312,-.6041762232780457,.0445394404232502,0,3,16,9,2,8,-1,16,9,1,4,2,17,13,1,4,2,.001586731057614088,-.1034090965986252,.2328201979398727,0,2,15,7,1,6,-1,15,9,1,2,3,-.004742781165987253,.284902811050415,-.0980904996395111,0,2,14,2,2,2,-1,14,3,2,1,2,-.0013515240279957652,.2309643030166626,-.113618403673172,0,2,17,0,2,3,-1,17,1,2,1,3,.0022526069078594446,.0644783228635788,-.4220589101314545,0,3,16,18,2,2,-1,16,18,1,1,2,17,19,1,1,2,-.0003803865984082222,-.3807620108127594,.0600432902574539,0,2,10,4,4,3,-1,10,5,4,1,3,.004904392175376415,-.076104998588562,.3323217034339905,0,2,0,2,8,6,-1,4,2,4,6,2,-.009096967056393623,.1428779065608978,-.1688780039548874,0,2,7,14,6,6,-1,7,16,6,2,3,-.0069317929446697235,.2725540995597839,-.0928795635700226,0,2,11,15,2,2,-1,11,16,2,1,2,.0011471060570329428,-.1527305990457535,.1970240026712418,0,2,7,1,9,4,-1,10,1,3,4,3,-.0376628898084164,-.5932043790817261,.0407386012375355,0,2,9,7,3,7,-1,10,7,1,7,3,-.006816557142883539,.2549408972263336,-.0940819606184959,0,3,6,17,2,2,-1,6,17,1,1,2,7,18,1,1,2,.0006620556232519448,.0467957183718681,-.4845437109470367,0,2,4,6,3,9,-1,5,6,1,9,3,-.004220255184918642,.2468214929103851,-.0946739763021469,0,2,0,10,19,10,-1,0,15,19,5,2,-.0689865127205849,-.6651480197906494,.0359263904392719,0,2,5,17,6,1,-1,7,17,2,1,3,.006170760840177536,.0258333198726177,-.7268627285957336,0,2,0,12,6,3,-1,3,12,3,3,2,.0105362497270107,-.0818289965391159,.2976079881191254,-1.1255199909210205,32,0,2,2,5,18,5,-1,8,5,6,5,3,-.0627587288618088,.2789908051490784,-.2965610921382904,0,2,1,15,6,4,-1,1,17,6,2,2,.003451647935435176,-.3463588058948517,.2090384066104889,0,2,14,10,6,6,-1,16,10,2,6,3,-.007869948633015156,.2414488941431046,-.1920557022094727,0,2,0,14,4,3,-1,0,15,4,1,3,-.0034624869003891945,-.5915178060531616,.1248644962906838,0,2,1,7,6,11,-1,3,7,2,11,3,-.009481876157224178,.1839154064655304,-.2485826015472412,0,2,13,17,7,2,-1,13,18,7,1,2,.00023226840130519122,-.3304725885391235,.1099926009774208,0,2,0,14,2,3,-1,0,15,2,1,3,.0018101120367646217,.0987440124154091,-.4963478147983551,0,2,0,0,6,2,-1,3,0,3,2,2,-.005442243069410324,.2934441864490509,-.1309475004673004,0,2,0,1,6,3,-1,3,1,3,3,2,.007414812222123146,-.1476269960403442,.3327716886997223,0,2,0,8,2,6,-1,0,10,2,2,3,-.0155651401728392,-.6840490102767944,.0998726934194565,0,3,1,2,6,14,-1,1,2,3,7,2,4,9,3,7,2,.0287205204367638,-.148332804441452,.3090257942676544,0,3,17,5,2,2,-1,17,5,1,1,2,18,6,1,1,2,9668739221524447e-20,-.1743104010820389,.2140295952558518,0,2,11,10,9,4,-1,14,10,3,4,3,.0523710586130619,-.0701568573713303,.4922299087047577,0,2,2,9,12,4,-1,6,9,4,4,3,-.0864856913685799,.5075724720954895,-.0752942115068436,0,2,7,10,12,2,-1,11,10,4,2,3,-.0421698689460754,.4568096101284027,-.0902199000120163,0,2,2,13,1,2,-1,2,14,1,1,2,45369830331765115e-21,-.2653827965259552,.1618953943252564,0,2,16,7,4,3,-1,16,8,4,1,3,.0052918000146746635,.0748901516199112,-.540546715259552,0,2,19,16,1,3,-1,19,17,1,1,3,-.0007551165181212127,-.4926199018955231,.0587239488959312,0,2,18,11,1,2,-1,18,12,1,1,2,7510813884437084e-20,-.2143210023641586,.1407776027917862,0,3,12,7,8,2,-1,12,7,4,1,2,16,8,4,1,2,.004998120944947004,-.0905473381280899,.3571606874465942,0,2,14,9,2,4,-1,15,9,1,4,2,-.0014929979806765914,.2562345862388611,-.1422906965017319,0,3,14,2,6,4,-1,14,2,3,2,2,17,4,3,2,2,.0027239411137998104,-.1564925014972687,.2108871042728424,0,2,14,0,6,1,-1,17,0,3,1,2,.002221832051873207,-.1507298946380615,.2680186927318573,0,2,3,12,2,1,-1,4,12,1,1,2,-.0007399307214654982,.2954699099063873,-.1069239005446434,0,2,17,2,3,1,-1,18,2,1,1,3,.0020113459322601557,.0506143495440483,-.7168337106704712,0,2,1,16,18,2,-1,7,16,6,2,3,.0114528704434633,-.1271906942129135,.241527795791626,0,2,2,19,8,1,-1,6,19,4,1,2,-.0010782170575112104,.2481300979852676,-.1346119940280914,0,2,1,17,4,3,-1,1,18,4,1,3,.00334176910109818,.0535783097147942,-.5227416753768921,0,2,19,13,1,2,-1,19,14,1,1,2,6939865124877542e-20,-.2169874012470245,.1281217932701111,0,3,9,16,10,4,-1,9,16,5,2,2,14,18,5,2,2,-.0040982551872730255,.2440188974142075,-.1157058998942375,0,3,12,9,2,4,-1,12,9,1,2,2,13,11,1,2,2,-.0016289720078930259,.2826147079467773,-.1065946966409683,0,2,19,11,1,9,-1,19,14,1,3,3,.0139848599210382,.0427158996462822,-.7364631295204163,-1.1729990243911743,30,0,2,6,6,14,14,-1,6,13,14,7,2,.164165198802948,-.4896030128002167,.1760770976543427,0,2,2,17,4,2,-1,2,18,4,1,2,.0008341306238435209,-.2822043001651764,.2419957965612412,0,2,0,2,1,3,-1,0,3,1,1,3,-.0017193210078403354,-.714858889579773,.0861622169613838,0,2,0,12,1,3,-1,0,13,1,1,3,-.001565495040267706,-.7297238111495972,.0940706729888916,0,2,15,15,4,4,-1,15,17,4,2,2,.0019124479731544852,-.3118715882301331,.1814339011907578,0,2,2,5,18,7,-1,8,5,6,7,3,-.1351236999034882,.2957729995250702,-.2217925041913986,0,2,1,16,5,3,-1,1,17,5,1,3,-.004030054900795221,-.6659513711929321,.0854310169816017,0,2,0,4,2,3,-1,0,5,2,1,3,-.002864046022295952,-.6208636164665222,.0531060211360455,0,2,0,6,2,6,-1,1,6,1,6,2,-.0014065420255064964,.2234628945589066,-.2021100968122482,0,2,16,14,4,3,-1,16,15,4,1,3,-.0035820449702441692,-.5403040051460266,.0682136192917824,0,3,0,0,10,6,-1,0,0,5,3,2,5,3,5,3,2,.04154447093606,-.0652158409357071,.6210923194885254,0,2,2,2,3,6,-1,3,2,1,6,3,-.009170955047011375,-.75553297996521,.0526404492557049,0,2,2,0,3,10,-1,3,0,1,10,3,.006155273877084255,.0909394025802612,-.4424613118171692,0,2,5,5,2,2,-1,5,6,2,1,2,-.0010043520014733076,.242923304438591,-.1866979002952576,0,2,12,6,4,4,-1,12,8,4,2,2,.0115198297426105,-.1176315024495125,.3672345876693726,0,2,13,5,7,3,-1,13,6,7,1,3,-.008904073387384415,-.4893133044242859,.1089702025055885,0,2,10,13,1,2,-1,10,14,1,1,2,.0005397367058321834,-.2185039967298508,.1848998963832855,0,2,16,16,4,2,-1,18,16,2,2,2,.0013727260520681739,-.1507291048765183,.2917312979698181,0,2,16,12,4,7,-1,18,12,2,7,2,-.0108073903247714,.4289745092391968,-.1028013974428177,0,2,16,17,1,3,-1,16,18,1,1,3,.0012670770520344377,.0741921588778496,-.6420825123786926,0,2,19,9,1,3,-1,19,10,1,1,3,.002299112966284156,.0471002794802189,-.723352313041687,0,2,18,7,2,6,-1,19,7,1,6,2,.002718751085922122,-.1708686947822571,.235135093331337,0,2,8,1,3,4,-1,9,1,1,4,3,-.006661918014287949,-.7897542715072632,.0450846701860428,0,2,14,0,6,9,-1,16,0,2,9,3,-.0482666492462158,-.6957991719245911,.0419760793447495,0,2,4,2,10,2,-1,9,2,5,2,2,.0152146900072694,-.1081828027963638,.3646062016487122,0,3,2,12,8,4,-1,2,12,4,2,2,6,14,4,2,2,-.006008013151586056,.309709906578064,-.1135921031236649,0,2,0,4,7,3,-1,0,5,7,1,3,.006612715777009726,.0806653425097466,-.4665853083133698,0,2,14,14,3,3,-1,15,14,1,3,3,-.007960701361298561,-.8720194101333618,.0367745906114578,0,2,0,3,4,3,-1,2,3,2,3,2,.003884719917550683,-.11666289716959,.3307026922702789,0,2,1,0,2,7,-1,2,0,1,7,2,-.001098881009966135,.2387257069349289,-.1765675991773605,-1.036829948425293,44,0,2,15,16,4,4,-1,15,18,4,2,2,.0035903379321098328,-.2368807941675186,.2463164031505585,0,2,5,8,12,4,-1,5,10,12,2,2,.006481593009084463,-.3137362003326416,.1867575943470001,0,2,3,17,1,2,-1,3,18,1,1,2,7304840255528688e-20,-.2764435112476349,.1649623960256577,0,2,6,1,3,4,-1,7,1,1,4,3,-.00385146401822567,-.5601450800895691,.1129473969340324,0,2,6,2,3,4,-1,7,2,1,4,3,.003858821000903845,.0398489981889725,-.5807185769081116,0,2,6,8,9,12,-1,9,8,3,12,3,-.0246512200683355,.1675501018762589,-.2534367144107819,0,2,8,1,8,6,-1,8,3,8,2,3,.0472455210983753,-.1066208034753799,.3945198059082031,0,2,14,2,6,3,-1,17,2,3,3,2,.00659646512940526,-.1774425059556961,.2728019058704376,0,2,0,6,1,3,-1,0,7,1,1,3,-.0013177490327507257,-.5427265167236328,.0486065894365311,0,2,10,0,10,2,-1,15,0,5,2,2,-.005026170983910561,.2439424991607666,-.1314364969730377,0,2,11,0,3,2,-1,12,0,1,2,3,.003463276894763112,.0690493434667587,-.7033624053001404,0,2,3,19,10,1,-1,8,19,5,1,2,.0021692588925361633,-.1328946053981781,.2209852933883667,0,2,0,4,7,16,-1,0,12,7,8,2,.0293958708643913,-.2853052020072937,.1354399025440216,0,2,2,16,1,3,-1,2,17,1,1,3,-.0009618144831620157,-.580413818359375,.0374506488442421,0,2,7,8,12,6,-1,11,8,4,6,3,-.1082099974155426,.3946728110313416,-.078655943274498,0,2,14,9,6,7,-1,16,9,2,7,3,-.0180248692631722,.2735562920570374,-.1341529935598373,0,2,12,17,6,1,-1,14,17,2,1,3,.006250984035432339,.023388059809804,-.8008859157562256,0,2,16,1,3,1,-1,17,1,1,1,3,-.0016088379779830575,-.5676252245903015,.0412156693637371,0,3,0,17,8,2,-1,0,17,4,1,2,4,18,4,1,2,.0007756475242786109,-.1489126980304718,.1908618062734604,0,2,17,0,2,1,-1,18,0,1,1,2,8712233830010518e-20,-.155575305223465,.194282203912735,0,2,4,15,6,5,-1,6,15,2,5,3,-.0207553207874298,-.6300653219223022,.0361343808472157,0,2,7,2,8,2,-1,7,3,8,1,2,-.0062931738793849945,.2560924887657166,-.1058826968073845,0,2,4,1,8,4,-1,4,3,8,2,2,.0108441496267915,-.1012485027313232,.3032212853431702,0,2,5,19,2,1,-1,6,19,1,1,2,-6375277735060081e-20,.1911157965660095,-.1384923011064529,0,2,5,19,2,1,-1,6,19,1,1,2,6648096314165741e-20,-.1520525068044663,.2170630991458893,0,2,16,17,1,3,-1,16,18,1,1,3,.0013560829684138298,.0494317896664143,-.6427984237670898,0,2,0,11,2,3,-1,1,11,1,3,2,-.0009066255879588425,.1798201054334641,-.1404460966587067,0,2,0,19,4,1,-1,2,19,2,1,2,.0010473709553480148,-.1093354970216751,.242659404873848,0,2,0,18,4,2,-1,2,18,2,2,2,-.0010243969736620784,.2716268002986908,-.1182091981172562,0,2,2,17,1,3,-1,2,18,1,1,3,-.0012024149764329195,-.701511025428772,.0394898988306522,0,2,5,7,11,2,-1,5,8,11,1,2,.007691164966672659,-.0922189131379128,.3104628920555115,0,2,9,2,4,10,-1,9,7,4,5,2,-.139665499329567,.6897938847541809,-.0397061184048653,0,2,0,2,4,3,-1,0,3,4,1,3,.0021276050247251987,.0972776114940643,-.2884179949760437,0,2,10,19,10,1,-1,15,19,5,1,2,-.0027594310231506824,.2416867017745972,-.1127782016992569,0,2,11,17,8,3,-1,15,17,4,3,2,.005223613232374191,-.1143027991056442,.2425678074359894,0,2,8,19,3,1,-1,9,19,1,1,3,-.0012590440455824137,-.5967938899993896,.0476639606058598,0,2,14,0,3,4,-1,15,0,1,4,3,-.0037192099262028933,-.464141309261322,.0528476908802986,0,2,10,6,4,3,-1,10,7,4,1,3,.005969615187495947,-.0732442885637283,.3874309062957764,0,2,0,8,3,2,-1,0,9,3,1,2,-.005177672021090984,-.7419322729110718,.0404967106878757,0,2,7,12,3,6,-1,7,14,3,2,3,.005003510043025017,-.1388880014419556,.1876762062311173,0,2,1,18,1,2,-1,1,19,1,1,2,-.0005201345775276423,-.5494061708450317,.0494178496301174,0,2,0,12,4,4,-1,2,12,2,4,2,.00531687680631876,-.0824829787015915,.3174056112766266,0,2,1,8,6,7,-1,3,8,2,7,3,-.0147745897993445,.2081609964370728,-.1211555972695351,0,2,0,8,4,5,-1,2,8,2,5,2,-.0414164513349533,-.8243780732154846,.0333291888237,-1.0492420196533203,53,0,2,19,16,1,3,-1,19,17,1,1,3,.0009096252033486962,.0845799669623375,-.5611841082572937,0,2,1,5,18,6,-1,7,5,6,6,3,-.0561397895216942,.1534174978733063,-.2696731984615326,0,2,2,15,4,2,-1,2,16,4,1,2,.0010292009683325887,-.2048998028039932,.2015317976474762,0,2,18,6,2,11,-1,19,6,1,11,2,.00287830107845366,-.1735114008188248,.2129794955253601,0,2,0,12,2,6,-1,0,14,2,2,3,-.0074144392274320126,-.5962486863136292,.0470779500901699,0,2,12,5,3,2,-1,12,6,3,1,2,-.0014831849839538336,.1902461051940918,-.1598639041185379,0,2,1,3,2,3,-1,1,4,2,1,3,.0045968941412866116,.0314471311867237,-.6869434118270874,0,2,16,14,4,4,-1,16,16,4,2,2,.0024255330208688974,-.23609359562397,.1103610992431641,0,2,6,8,12,5,-1,10,8,4,5,3,-.0849505662918091,.2310716062784195,-.1377653032541275,0,2,13,7,2,7,-1,14,7,1,7,2,-.005014568101614714,.3867610991001129,-.0562173798680305,0,2,1,8,2,6,-1,2,8,1,6,2,-.002148206112906337,.1819159984588623,-.1761569976806641,0,2,15,0,3,7,-1,16,0,1,7,3,-.0103967702016234,-.7535138130187988,.0240919701755047,0,2,4,2,6,2,-1,6,2,2,2,3,-.0134667502716184,-.7211886048316956,.0349493697285652,0,2,0,9,20,9,-1,0,12,20,3,3,-.0844354778528214,-.3379263877868652,.0711138173937798,0,2,10,14,2,2,-1,10,15,2,1,2,.00247714901342988,-.1176510974764824,.225419893860817,0,2,6,5,10,4,-1,6,7,10,2,2,.015828050673008,-.0695362165570259,.313953697681427,0,2,6,1,5,9,-1,6,4,5,3,3,.0649169832468033,-.0750435888767242,.4067733883857727,0,3,16,18,2,2,-1,16,18,1,1,2,17,19,1,1,2,.00029652469675056636,.0739533603191376,-.3454400897026062,0,2,0,14,2,4,-1,0,16,2,2,2,.001312952022999525,-.1690943986177445,.1525837033987045,0,2,10,8,2,5,-1,11,8,1,5,2,-.0058032129891216755,.3526014983654022,-.0834440663456917,0,2,3,7,12,7,-1,7,7,4,7,3,-.1479167938232422,.4300465881824493,-.0573099292814732,0,2,0,0,6,6,-1,3,0,3,6,2,-.016584150493145,.2343268990516663,-.1090764030814171,0,2,1,0,4,4,-1,3,0,2,4,2,.003018327057361603,-.1360093951225281,.264092892408371,0,2,0,0,6,8,-1,2,0,2,8,3,-.0364719182252884,-.628097414970398,.0435451082885265,0,2,0,0,2,1,-1,1,0,1,1,2,-7311922672670335e-20,.1647063046693802,-.1646378040313721,0,2,0,0,3,3,-1,0,1,3,1,3,-.003671945072710514,-.4742136001586914,.0485869199037552,0,2,5,4,2,4,-1,5,6,2,2,2,-.004015117883682251,.1822218000888825,-.1409751027822495,0,2,2,10,9,1,-1,5,10,3,1,3,.0199480205774307,-.0697876587510109,.3670746088027954,0,2,1,17,1,3,-1,1,18,1,1,3,.0007669943734072149,.0557292997837067,-.4458543062210083,0,2,0,17,2,3,-1,0,18,2,1,3,-.0011806039838120341,-.4687662124633789,.0489022210240364,0,2,0,15,16,3,-1,8,15,8,3,2,.0158473495393991,-.1212020963430405,.2056653052568436,0,2,0,5,4,1,-1,2,5,2,1,2,-.0011985700111836195,.2026209980249405,-.1282382011413574,0,2,1,0,6,20,-1,3,0,2,20,3,-.1096495985984802,-.8661919236183167,.0303518492728472,0,3,2,5,4,6,-1,2,5,2,3,2,4,8,2,3,2,-.009253260679543018,.2934311926364899,-.0853619500994682,0,2,9,16,6,3,-1,11,16,2,3,3,.0146865304559469,.0327986218035221,-.7755656242370605,0,2,11,17,6,1,-1,14,17,3,1,2,-.0013514430029317737,.244269996881485,-.1150325015187264,0,2,3,17,15,2,-1,8,17,5,2,3,-.004372809082269669,.2168767005205154,-.1398448050022125,0,2,18,0,2,3,-1,18,1,2,1,3,.0034263390116393566,.0456142202019691,-.545677125453949,0,2,13,1,7,4,-1,13,3,7,2,2,-.0038404068909585476,.149495005607605,-.1506250947713852,0,3,13,6,4,4,-1,13,6,2,2,2,15,8,2,2,2,.0037988980766385794,-.0873016268014908,.2548153102397919,0,2,17,6,3,4,-1,17,8,3,2,2,-.0020094281062483788,.1725907027721405,-.1428847014904022,0,2,14,9,2,2,-1,15,9,1,2,2,-.002437070943415165,.2684809863567352,-.0818982198834419,0,2,17,17,1,3,-1,17,18,1,1,3,.001048539998009801,.0461132600903511,-.4724327921867371,0,2,3,19,8,1,-1,7,19,4,1,2,.00174607802182436,-.1103043034672737,.2037972956895828,0,2,0,9,3,6,-1,0,12,3,3,2,.005860862787812948,-.1561965942382813,.1592743992805481,0,2,4,7,15,5,-1,9,7,5,5,3,-.0277249794453382,.1134911999106407,-.2188514024019241,0,2,6,9,9,5,-1,9,9,3,5,3,.0470806397497654,-.0416887290775776,.5363004803657532,0,2,8,1,6,2,-1,10,1,2,2,3,-.007928377017378807,-.5359513163566589,.0442375093698502,0,2,4,0,12,2,-1,10,0,6,2,2,-.0128805404528975,.2323794960975647,-.102462500333786,0,2,7,0,10,3,-1,12,0,5,3,2,.0236047692596912,-.0882914364337921,.3056105971336365,0,2,5,0,9,6,-1,5,2,9,2,3,.0159022007137537,-.1223810985684395,.1784912049770355,0,2,8,3,6,4,-1,8,5,6,2,2,.007993949577212334,-.0837290063500404,.3231959044933319,0,2,17,4,2,3,-1,17,5,2,1,3,.005710086785256863,.038479208946228,-.6813815236091614,-1.1122100353240967,51,0,2,5,2,4,3,-1,5,3,4,1,3,.002248072065412998,-.1641687005758286,.4164853096008301,0,2,5,9,2,6,-1,6,9,1,6,2,.004581355024129152,-.1246595978736877,.4038512110710144,0,2,14,10,2,6,-1,15,10,1,6,2,-.0016073239967226982,.260824590921402,-.202825203537941,0,2,7,4,3,3,-1,7,5,3,1,3,.0025205370038747787,-.1055722981691361,.3666911125183106,0,3,12,4,8,2,-1,12,4,4,1,2,16,5,4,1,2,.0024119189474731684,-.1387760043144226,.2995991110801697,0,2,15,8,1,6,-1,15,10,1,2,3,.005715617910027504,-.0776834636926651,.4848192036151886,0,2,4,17,11,3,-1,4,18,11,1,3,.0031093840952962637,-.1122900024056435,.2921550869941711,0,2,3,0,16,20,-1,3,10,16,10,2,-.0868366286158562,-.367796003818512,.0725972428917885,0,2,12,4,4,6,-1,12,6,4,2,3,.0052652182057499886,-.1089029014110565,.3179126083850861,0,2,11,0,6,6,-1,13,0,2,6,3,-.0199135299772024,-.5337343811988831,.0705857127904892,0,3,13,1,6,4,-1,13,1,3,2,2,16,3,3,2,2,.00382978399284184,-.135759100317955,.2278887927532196,0,2,11,0,6,4,-1,13,0,2,4,3,.0104318596422672,.0887979120016098,-.4795897006988525,0,2,8,6,6,9,-1,10,6,2,9,3,-.0200404394418001,.1574553996324539,-.1777157038450241,0,2,7,0,3,4,-1,8,0,1,4,3,-.005296729039400816,-.6843491792678833,.0356714613735676,0,3,0,17,14,2,-1,0,17,7,1,2,7,18,7,1,2,-.0021624139044433832,.2831803858280182,-.098511278629303,0,3,6,18,2,2,-1,6,18,1,1,2,7,19,1,1,2,-.00035464888787828386,-.3707734048366547,.0809329524636269,0,2,18,17,1,3,-1,18,18,1,1,3,-.00018152060511056334,-.322070300579071,.0775510594248772,0,3,17,18,2,2,-1,17,18,1,1,2,18,19,1,1,2,-.000275630212854594,-.3244127929210663,.0879494771361351,0,2,5,7,1,9,-1,5,10,1,3,3,.006382381077855825,-.0889247134327888,.3172721862792969,0,2,5,3,6,4,-1,7,3,2,4,3,.0111509095877409,.0710198432207108,-.4049403965473175,0,3,1,9,6,2,-1,1,9,3,1,2,4,10,3,1,2,-.0010593760525807738,.2605066895484924,-.1176564022898674,0,2,6,9,2,3,-1,7,9,1,3,2,.002390648005530238,-.0843886211514473,.3123055100440979,0,2,6,8,6,12,-1,8,8,2,12,3,-.0110007496550679,.1915224939584732,-.1521002054214478,0,3,4,18,2,2,-1,4,18,1,1,2,5,19,1,1,2,-.00024643228971399367,-.3176515996456146,.0865822583436966,0,2,9,1,6,6,-1,9,3,6,2,3,.0230532698333263,-.1008976027369499,.2576929032802582,0,2,6,17,6,2,-1,6,18,6,1,2,-.0022135660983622074,.4568921029567719,-.0524047911167145,0,2,3,18,16,2,-1,3,19,16,1,2,-.000971397093962878,-.3551838099956513,.0800943821668625,0,2,3,0,3,11,-1,4,0,1,11,3,.0015676229959353805,.1009142026305199,-.2160304039716721,0,2,13,18,3,1,-1,14,18,1,1,3,.0007546080159954727,.0578961782157421,-.4046111106872559,0,2,6,0,9,6,-1,6,2,9,2,3,-.0206989701837301,.3154363036155701,-.0807130485773087,0,3,1,2,12,4,-1,1,2,6,2,2,7,4,6,2,2,-.0206199400126934,.271816611289978,-.0763586163520813,0,2,3,3,6,4,-1,5,3,2,4,3,.0216111298650503,.0394934490323067,-.5942965149879456,0,2,12,0,8,1,-1,16,0,4,1,2,.006567674223333597,-.0983536690473557,.2364927977323532,0,2,9,0,6,2,-1,11,0,2,2,3,-.008843479678034782,-.5252342820167542,.0430999211966991,0,2,3,3,12,1,-1,9,3,6,1,2,-.009426074102520943,.2466513067483902,-.0941307172179222,0,3,2,7,6,2,-1,2,7,3,1,2,5,8,3,1,2,-.001983023015782237,.2674370110034943,-.0900693163275719,0,2,0,8,4,6,-1,0,10,4,2,3,-.001735839992761612,.1594001948833466,-.157894104719162,0,2,9,6,3,7,-1,10,6,1,7,3,-.0135138696059585,.4079233109951019,-.0642231181263924,0,2,9,6,6,13,-1,11,6,2,13,3,-.0193940103054047,.1801564991474152,-.1373140066862106,0,2,11,12,6,1,-1,13,12,2,1,3,-.003268477041274309,.2908039093017578,-.0801619067788124,0,2,18,9,2,6,-1,18,12,2,3,2,.00041773589327931404,-.2141298055648804,.1127343997359276,0,2,17,2,3,9,-1,18,2,1,9,3,-.007635111920535564,-.4536595940589905,.0546250604093075,0,3,13,8,4,6,-1,13,8,2,3,2,15,11,2,3,2,-.008365297690033913,.2647292017936707,-.0943341106176376,0,2,4,2,12,6,-1,10,2,6,6,2,.027768449857831,-.1013671010732651,.2074397951364517,0,2,4,14,16,6,-1,12,14,8,6,2,-.0548912286758423,.2884030938148499,-.075312040746212,0,2,6,19,10,1,-1,11,19,5,1,2,.002579333959147334,-.1108852997422218,.2172496020793915,0,2,6,17,1,3,-1,6,18,1,1,3,6619651685468853e-20,-.1887210011482239,.1444068998098373,0,2,4,14,10,3,-1,4,15,10,1,3,.005090725142508745,-.0776012316346169,.2939837872982025,0,2,6,0,12,12,-1,6,4,12,4,3,-.1044425964355469,.2013310939073563,-.1090397015213966,0,3,5,7,4,2,-1,5,7,2,1,2,7,8,2,1,2,-.0006727309082634747,.1794590055942535,-.1202367022633553,0,2,17,5,3,2,-1,18,5,1,2,3,.0032412849832326174,.0406881310045719,-.5460057258605957,-1.2529590129852295,44,0,2,8,13,6,3,-1,8,14,6,1,3,.005296532064676285,-.1215452998876572,.6442037224769592,0,2,8,13,5,3,-1,8,14,5,1,3,-.002532626036554575,.5123322010040283,-.111082598567009,0,2,13,2,1,18,-1,13,11,1,9,2,-.0029183230362832546,-.5061542987823486,.1150197982788086,0,2,6,10,9,2,-1,9,10,3,2,3,-.0236923396587372,.3716728091239929,-.1467268019914627,0,2,11,0,7,4,-1,11,2,7,2,2,.0201774705201387,-.1738884001970291,.4775949120521545,0,2,1,0,6,8,-1,3,0,2,8,3,-.021723210811615,-.4388009011745453,.1357689946889877,0,2,9,15,3,3,-1,9,16,3,1,3,.0028369780629873276,-.1251206994056702,.4678902924060822,0,2,9,17,9,3,-1,9,18,9,1,3,.002714842092245817,-.0880188569426537,.3686651885509491,0,2,12,12,3,3,-1,12,13,3,1,3,.003262568963691592,-.0853353068232536,.5164473056793213,0,2,4,1,3,5,-1,5,1,1,5,3,-.0035618850961327553,-.445039302110672,.0917381718754768,0,2,10,14,2,3,-1,10,15,2,1,3,.001922774943523109,-.1107731014490128,.3941699862480164,0,3,18,17,2,2,-1,18,17,1,1,2,19,18,1,1,2,-.0003511196991894394,-.3777570128440857,.1216617003083229,0,3,18,18,2,2,-1,18,18,1,1,2,19,19,1,1,2,.0001912177976919338,.0748160183429718,-.4076710045337677,0,3,18,18,2,2,-1,18,18,1,1,2,19,19,1,1,2,-.00026525629800744355,-.3315171897411346,.1129112020134926,0,2,4,10,9,1,-1,7,10,3,1,3,.0200867000967264,-.0615981183946133,.5612881779670715,0,2,3,9,6,5,-1,5,9,2,5,3,.0367832481861115,-.0602513886988163,.5219249129295349,0,2,18,8,1,12,-1,18,14,1,6,2,.0013941619545221329,-.3550305068492889,.1086302027106285,0,3,0,2,8,6,-1,0,2,4,3,2,4,5,4,3,2,-.0151816699653864,.2273965030908585,-.1625299006700516,0,2,9,4,3,3,-1,9,5,3,1,3,.0046796840615570545,-.0575350411236286,.4812423884868622,0,3,3,18,2,2,-1,3,18,1,1,2,4,19,1,1,2,-.00017988319450523704,-.3058767020702362,.1086815968155861,0,2,6,4,4,3,-1,6,5,4,1,3,-.0035850999411195517,.3859694004058838,-.0921940729022026,0,3,16,7,4,2,-1,16,7,2,1,2,18,8,2,1,2,.001079336041584611,-.1119038984179497,.31125208735466,0,2,5,17,1,3,-1,5,18,1,1,3,7328580250032246e-20,-.2023991048336029,.155866801738739,0,2,2,0,15,20,-1,2,10,15,10,2,.1367873996496201,-.2167285978794098,.1442039012908936,0,3,8,11,6,4,-1,8,11,3,2,2,11,13,3,2,2,-.0117292599752545,.4350377023220062,-.0748865306377411,0,2,8,16,4,3,-1,8,17,4,1,3,.003923084121197462,-.0502893291413784,.5883116126060486,0,3,8,18,2,2,-1,8,18,1,1,2,9,19,1,1,2,-.0002981912111863494,-.3823240101337433,.0924511328339577,0,2,2,16,13,3,-1,2,17,13,1,3,-.004799277056008577,.4848878979682922,-.0731365233659744,0,3,16,16,2,2,-1,16,16,1,1,2,17,17,1,1,2,-.0003015589027199894,-.3575735986232758,.1058188006281853,0,2,8,1,6,3,-1,10,1,2,3,3,.0103907696902752,.0529204681515694,-.5724965929985046,0,3,16,7,2,2,-1,16,7,1,1,2,17,8,1,1,2,-.0009448804194107652,.449668288230896,-.0830755233764648,0,3,14,7,4,2,-1,14,7,2,1,2,16,8,2,1,2,.0012651870492845774,-.0966954380273819,.3130227029323578,0,2,4,0,14,1,-1,11,0,7,1,2,.0170945394784212,-.081248976290226,.3611383140087128,0,3,10,4,8,2,-1,10,4,4,1,2,14,5,4,1,2,.002597335958853364,-.1133835017681122,.2223394960165024,0,2,8,2,3,2,-1,9,2,1,2,3,.0014527440071105957,.0697504431009293,-.3672071099281311,0,2,12,11,6,3,-1,12,12,6,1,3,.00476386584341526,-.0657889619469643,.383285403251648,0,2,1,5,1,4,-1,1,7,1,2,2,-.006250108126550913,-.7075446844100952,.038350198417902,0,2,1,1,1,18,-1,1,7,1,6,3,-.003176532918587327,.1375540047883987,-.2324002981185913,0,2,11,13,3,2,-1,11,14,3,1,2,.003219116944819689,-.1293545067310333,.2273788005113602,0,3,0,1,12,2,-1,0,1,6,1,2,6,2,6,1,2,-.005636557936668396,.380671501159668,-.0672468394041061,0,3,10,18,2,2,-1,10,18,1,1,2,11,19,1,1,2,-.00023844049428589642,-.3112238049507141,.0838383585214615,0,3,4,5,4,4,-1,4,5,2,2,2,6,7,2,2,2,-.004101756028831005,.2606728076934815,-.1044974029064179,0,2,6,7,1,3,-1,6,8,1,1,3,.0013336989795789123,-.0582501403987408,.4768244028091431,0,2,14,10,6,2,-1,16,10,2,2,3,-.0012090239906683564,.148345097899437,-.1732946932315826,-1.118873953819275,72,0,2,16,8,3,6,-1,17,8,1,6,3,-.003176093101501465,.3333333134651184,-.166423499584198,0,2,4,10,6,2,-1,6,10,2,2,3,.0248580798506737,-.0727288722991943,.5667458176612854,0,2,6,5,3,7,-1,7,5,1,7,3,-.007759728003293276,.4625856876373291,-.0931121781468391,0,2,0,13,6,6,-1,0,16,6,3,2,.007823902182281017,-.2741461098194122,.1324304938316345,0,2,12,5,1,9,-1,12,8,1,3,3,-.010948839597404,.2234548032283783,-.1496544927358627,0,2,5,9,3,3,-1,6,9,1,3,3,-.0034349008928984404,.3872498869895935,-.0661217272281647,0,2,7,5,6,13,-1,9,5,2,13,3,-.0311562903225422,.2407827973365784,-.1140690967440605,0,2,19,8,1,10,-1,19,13,1,5,2,.001110051991418004,-.2820797860622406,.1327542960643768,0,2,11,18,6,1,-1,13,18,2,1,3,.003176274010911584,.0345859304070473,-.5137431025505066,0,2,9,7,6,12,-1,11,7,2,12,3,-.0279774591326714,.2392677962779999,-.1325591951608658,0,2,12,7,6,6,-1,14,7,2,6,3,-.0230979397892952,.3901962041854858,-.0784780085086823,0,2,15,8,3,4,-1,16,8,1,4,3,-.003973193001002073,.3069106936454773,-.0706014037132263,0,2,6,11,4,2,-1,6,12,4,1,2,.003033574903383851,-.1400219053030014,.191348597407341,0,2,1,6,6,8,-1,3,6,2,8,3,-.0108443703502417,.1654873043298721,-.1565777957439423,0,2,11,15,6,5,-1,13,15,2,5,3,-.0181505102664232,-.6324359178543091,.0395618192851543,0,2,15,17,4,2,-1,15,18,4,1,2,.0007105229888111353,-.1851557046175003,.1340880990028381,0,2,13,11,6,1,-1,15,11,2,1,3,.0108933402225375,-.0267302300781012,.6097180247306824,0,3,5,18,2,2,-1,5,18,1,1,2,6,19,1,1,2,-.0002878090017475188,-.3006514012813568,.0731714591383934,0,3,4,8,4,4,-1,4,8,2,2,2,6,10,2,2,2,-.0035855069290846586,.2621760964393616,-.0797140970826149,0,2,11,7,9,3,-1,11,8,9,1,3,-.0197592806071043,-.5903922915458679,.0406989715993404,0,3,0,3,10,4,-1,0,3,5,2,2,5,5,5,2,2,-.010845210403204,.1636455953121185,-.1258606016635895,0,2,7,18,6,1,-1,9,18,2,1,3,-.004318309016525745,-.5747488141059875,.0376443117856979,0,2,0,8,3,3,-1,0,9,3,1,3,.0014913700288161635,.0609134696424007,-.3022292852401733,0,3,0,0,6,8,-1,0,0,3,4,2,3,4,3,4,2,.0156756993383169,-.0731459110975266,.2937945127487183,0,2,7,6,3,8,-1,8,6,1,8,3,-.0110335601493716,.393188089132309,-.0470843203365803,0,2,13,7,7,3,-1,13,8,7,1,3,.008855575695633888,.0376013815402985,-.4910849034786224,0,2,3,3,2,2,-1,3,4,2,1,2,-.0008966567111201584,.1795202046632767,-.1108623966574669,0,2,0,3,3,3,-1,0,4,3,1,3,-.0030592409893870354,-.4442946016788483,.0510054305195808,0,2,9,3,5,2,-1,9,4,5,1,2,.006320117972791195,-.0528410896658897,.3719710111618042,0,2,6,5,9,4,-1,9,5,3,4,3,.020682830363512,.0576671697199345,-.3690159916877747,0,2,3,10,12,3,-1,7,10,4,3,3,.0998226627707481,-.037377018481493,.5816559195518494,0,2,8,7,3,6,-1,9,7,1,6,3,-.006585422903299332,.2850944101810455,-.0609780699014664,0,2,5,5,6,5,-1,8,5,3,5,2,-.0609003007411957,-.5103176832199097,.0377874001860619,0,2,0,5,2,3,-1,0,6,2,1,3,-.0029991709161549807,-.4794301092624664,.0388338901102543,0,2,9,7,3,4,-1,10,7,1,4,3,-.009890643879771233,.4060907959938049,-.047869648784399,0,2,1,0,6,15,-1,3,0,2,15,3,-.0826889276504517,-.7067118287086487,.0274877492338419,0,2,15,1,3,5,-1,16,1,1,5,3,.00500603998079896,.028208440169692,-.5290969014167786,0,2,9,2,3,10,-1,10,2,1,10,3,.006169503089040518,-.0545548610389233,.3283798098564148,0,2,8,8,6,12,-1,10,8,2,12,3,-.0033914761152118444,.0921176671981812,-.2163711041212082,0,2,16,4,3,4,-1,16,6,3,2,2,-.0026131230406463146,.1365101933479309,-.1378113031387329,0,3,16,7,2,2,-1,16,7,1,1,2,17,8,1,1,2,.0008049065945670009,-.0686371102929115,.3358106911182404,0,2,13,0,6,9,-1,13,3,6,3,3,-.0381065085530281,.2944543063640595,-.068239226937294,0,2,7,17,1,3,-1,7,18,1,1,3,7245079905260354e-20,-.167501300573349,.1217823028564453,0,2,12,1,4,2,-1,12,2,4,1,2,.0015837959945201874,-.0920428484678268,.213489904999733,0,2,17,3,1,3,-1,17,4,1,1,3,.0012924340553581715,.0629172325134277,-.3617450892925263,0,2,0,16,9,3,-1,0,17,9,1,3,.00991467759013176,.0195340607315302,-.8101503849029541,0,3,3,6,2,4,-1,3,6,1,2,2,4,8,1,2,2,-.0017086310544982553,.2552523910999298,-.0682294592261314,0,2,13,18,3,1,-1,14,18,1,1,3,.002184439916163683,.0233140494674444,-.8429678082466125,0,2,0,18,4,2,-1,2,18,2,2,2,-.003424433059990406,.2721368968486786,-.0763952285051346,0,2,1,19,2,1,-1,2,19,1,1,2,.00027591470279730856,-.1074284017086029,.2288897037506104,0,2,0,18,4,2,-1,0,19,4,1,2,-.0006000517751090229,-.2985421121120453,.0634797364473343,0,2,2,17,1,3,-1,2,18,1,1,3,-.00025001438916660845,-.2717896997928619,.0696150064468384,0,2,4,8,3,5,-1,5,8,1,5,3,.006875139195472002,-.0571858994662762,.3669595122337341,0,2,2,1,6,7,-1,4,1,2,7,3,.0127619002014399,.0679556876420975,-.2853415012359619,0,3,3,6,2,8,-1,3,6,1,4,2,4,10,1,4,2,-.0014752789866179228,.2068066000938416,-.1005939021706581,0,2,4,5,11,10,-1,4,10,11,5,2,.1213881969451904,-.0971267968416214,.1978961974382401,0,2,0,13,20,2,-1,10,13,10,2,2,-.0500812791287899,.2841717898845673,-.0678799971938133,0,2,1,13,16,3,-1,9,13,8,3,2,.0314549505710602,-.0894686728715897,.2129842042922974,0,3,16,4,4,4,-1,16,4,2,2,2,18,6,2,2,2,.0018878319533541799,-.1165644004940987,.166635200381279,0,3,16,0,4,12,-1,16,0,2,6,2,18,6,2,6,2,-.005721196066588163,.2370214015245438,-.0907766073942184,0,2,14,15,3,1,-1,15,15,1,1,3,-.00018076719425152987,.1795192956924439,-.1079348027706146,0,2,3,4,12,10,-1,3,9,12,5,2,-.1976184993982315,.4567429125308991,-.0404801592230797,0,3,9,18,2,2,-1,9,18,1,1,2,10,19,1,1,2,-.00023846809926908463,-.2373300939798355,.0759221613407135,0,3,9,18,2,2,-1,9,18,1,1,2,10,19,1,1,2,.00021540730085689574,.0816880166530609,-.2868503034114838,0,3,13,4,2,14,-1,13,4,1,7,2,14,11,1,7,2,.0101630901917815,-.0412500202655792,.4803834855556488,0,2,4,2,6,4,-1,7,2,3,4,2,-.007218487095087767,.1745858043432236,-.1014650017023087,0,3,0,0,18,20,-1,0,0,9,10,2,9,10,9,10,2,.2426317036151886,.05342648178339,-.3231852948665619,0,2,15,11,1,2,-1,15,12,1,1,2,.0006930410163477063,-.1149917989969254,.1479393988847733,0,3,16,10,2,4,-1,16,10,1,2,2,17,12,1,2,2,.003547519911080599,-.0394249781966209,.5312618017196655,0,3,18,17,2,2,-1,18,17,1,1,2,19,18,1,1,2,.00021403690334409475,.0697538331151009,-.2731958031654358,0,2,9,17,1,2,-1,9,18,1,1,2,-.0005711946287192404,.3436990082263947,-.0576990097761154,0,2,8,4,9,6,-1,11,4,3,6,3,-.006629006937146187,.1175848990678787,-.1502013951539993,-1.088881015777588,66,0,2,6,9,9,10,-1,9,9,3,10,3,-.0265134498476982,.2056864053010941,-.2647390067577362,0,2,5,0,5,4,-1,5,2,5,2,2,.00977274589240551,-.111928403377533,.325705498456955,0,2,5,7,11,4,-1,5,9,11,2,2,.0322903506457806,-.0985747575759888,.3177917003631592,0,2,2,4,2,14,-1,3,4,1,14,2,-.00281032407656312,.1521389931440353,-.1968640983104706,0,2,8,6,3,5,-1,9,6,1,5,3,-.0109914299100637,.5140765905380249,-.0437072105705738,0,2,8,4,3,9,-1,9,4,1,9,3,.006313383113592863,-.0927810221910477,.3470247089862824,0,2,0,8,20,6,-1,0,10,20,2,3,.0871059820055962,.030053649097681,-.8281481862068176,0,2,14,16,6,1,-1,17,16,3,1,2,.0011799359926953912,-.1292842030525208,.2064612060785294,0,2,17,18,2,2,-1,17,19,2,1,2,-.0009305689018219709,-.5002143979072571,.0936669930815697,0,2,8,17,6,3,-1,10,17,2,3,3,-.0136871701106429,-.793581485748291,-.006673363968729973,0,2,4,1,9,15,-1,7,1,3,15,3,-.0759174525737762,.3046964108943939,-.0796558931469917,0,2,11,5,3,12,-1,12,5,1,12,3,-.0028559709899127483,.2096146047115326,-.1273255050182343,0,2,0,15,4,3,-1,0,16,4,1,3,-.004023151006549597,-.6581727862358093,.0506836399435997,0,2,0,0,15,1,-1,5,0,5,1,3,.0175580400973558,-.0853826925158501,.3617455959320068,0,2,6,0,6,4,-1,8,0,2,4,3,.0219882391393185,.062943696975708,-.7089633941650391,0,2,2,0,9,3,-1,5,0,3,3,3,-.002859958913177252,.1468378007411957,-.1646597981452942,0,2,13,6,3,7,-1,14,6,1,7,3,-.0100308498367667,.4957993924617767,-.0271883402019739,0,2,7,6,4,2,-1,7,7,4,1,2,-.006956032942980528,.2797777950763702,-.0779533311724663,0,2,6,18,6,1,-1,8,18,2,1,3,-.0038356808945536613,-.58163982629776,.0357399396598339,0,2,18,6,2,2,-1,18,7,2,1,2,-.0032647319603711367,-.4994508028030396,.0469864904880524,0,2,6,4,7,3,-1,6,5,7,1,3,-.007841235026717186,.34532830119133,-.0688104033470154,0,2,12,7,3,1,-1,13,7,1,1,3,-8171811350621283e-20,.1504171043634415,-.1414667963981628,0,3,15,1,2,10,-1,15,1,1,5,2,16,6,1,5,2,-.0032448628917336464,.227245107293129,-.0928602069616318,0,2,0,18,2,2,-1,0,19,2,1,2,-.0007856115116737783,-.4431901872158051,.0578124411404133,0,2,19,4,1,8,-1,19,8,1,4,2,-.0006247424753382802,.1395238935947418,-.1466871947050095,0,2,1,17,1,3,-1,1,18,1,1,3,-.0003294294874649495,-.2990157008171082,.0760667398571968,0,3,0,15,6,4,-1,0,15,3,2,2,3,17,3,2,2,.0012605739757418633,-.1612560003995895,.1395380049943924,0,2,19,0,1,18,-1,19,6,1,6,3,-.0516670197248459,-.5314283967018127,.0407195203006268,0,2,10,2,6,2,-1,12,2,2,2,3,-.0152856195345521,-.7820637822151184,.0271837692707777,0,2,2,8,12,2,-1,6,8,4,2,3,.0690298229455948,-.0364270210266113,.7110251784324646,0,2,16,0,4,1,-1,18,0,2,1,2,.001452274969778955,-.0968905165791512,.2166842073202133,0,2,8,4,2,6,-1,8,7,2,3,2,-.0024765590205788612,.1164531037211418,-.1822797954082489,0,2,14,5,2,10,-1,15,5,1,10,2,-.0015134819550439715,.1786397993564606,-.1221496984362602,0,2,13,4,2,2,-1,13,5,2,1,2,-.0015099470037966967,.1808623969554901,-.1144606992602348,0,2,11,1,3,6,-1,11,3,3,2,3,-.006705462001264095,.2510659992694855,-.0918714627623558,0,2,6,9,12,2,-1,10,9,4,2,3,-.014075200073421,.1370750963687897,-.173335000872612,0,2,9,16,4,2,-1,9,17,4,1,2,-.0022400720044970512,.4009298086166382,-.0475768782198429,0,2,5,14,15,4,-1,5,16,15,2,2,.0197823699563742,-.1904035061597824,.1492341011762619,0,2,18,16,2,2,-1,18,17,2,1,2,.002600287087261677,.0469717681407928,-.4330765902996063,0,3,16,18,2,2,-1,16,18,1,1,2,17,19,1,1,2,-.0005344562814570963,-.4374423027038574,.0415201894938946,0,2,6,4,3,8,-1,7,4,1,8,3,-.0174665097147226,.6581817269325256,-.0344474911689758,0,2,5,9,3,1,-1,6,9,1,1,3,-.00204255897551775,.3965792953968048,-.044052429497242,0,2,0,8,1,6,-1,0,10,1,2,3,.0026661779265850782,.0587709583342075,-.3280636966228485,0,2,11,2,9,6,-1,14,2,3,6,3,-.0559823699295521,-.5173547267913818,.0357918404042721,0,2,12,2,6,4,-1,14,2,2,4,3,-.0015066330088302493,.1512386947870255,-.1252018064260483,0,2,1,7,2,4,-1,1,9,2,2,2,-.0114723695442081,-.6293053030967712,.0347043313086033,0,2,13,1,6,4,-1,13,3,6,2,2,.0234096292406321,-.0580633506178856,.3866822123527527,0,3,4,10,2,10,-1,4,10,1,5,2,5,15,1,5,2,-.002324372995644808,.1875409930944443,-.0983946695923805,0,2,2,16,9,3,-1,5,16,3,3,3,-.0290392991155386,-.5448690056800842,.0409263409674168,0,2,1,2,3,9,-1,2,2,1,9,3,-.014474649913609,-.6724839210510254,.0231288503855467,0,2,19,7,1,4,-1,19,9,1,2,2,-.005208609160035849,-.4327144026756287,.0437806509435177,0,3,14,11,6,8,-1,14,11,3,4,2,17,15,3,4,2,.004938289988785982,-.1087862029671669,.1934258937835693,0,3,15,12,4,6,-1,15,12,2,3,2,17,15,2,3,2,-.004319393076002598,.2408093065023422,-.1038080006837845,0,3,16,15,2,2,-1,16,15,1,1,2,17,16,1,1,2,.0002370566944591701,-.087349072098732,.2046623975038528,0,3,17,16,2,2,-1,17,16,1,1,2,18,17,1,1,2,.0004785807977896184,.0456245802342892,-.3885467052459717,0,3,17,16,2,2,-1,17,16,1,1,2,18,17,1,1,2,-.0008534283842891455,-.550779402256012,.0358258895576,0,3,2,3,2,2,-1,2,3,1,1,2,3,4,1,1,2,5477212107507512e-20,-.1122523993253708,.1750351935625076,0,2,10,10,3,3,-1,11,10,1,3,3,-.0038445889949798584,.2452670037746429,-.0811325684189796,0,2,5,9,7,8,-1,5,13,7,4,2,-.0401284582912922,-.6312270760536194,.0269726701080799,0,3,7,16,2,2,-1,7,16,1,1,2,8,17,1,1,2,-.0001788636000128463,.1985509991645813,-.1033368036150932,0,3,7,16,2,2,-1,7,16,1,1,2,8,17,1,1,2,.00017668239888735116,-.0913590118288994,.1984872072935104,0,2,9,8,10,3,-1,14,8,5,3,2,.0727633833885193,.0500755794346333,-.3385263085365295,0,3,6,7,4,8,-1,6,7,2,4,2,8,11,2,4,2,.0101816300302744,-.0932299792766571,.2005959004163742,0,2,1,6,4,3,-1,1,7,4,1,3,.0024409969337284565,.0646366328001022,-.2692174017429352,0,2,6,10,6,10,-1,8,10,2,10,3,-.003622748889029026,.1316989064216614,-.1251484006643295,0,2,4,6,3,6,-1,5,6,1,6,3,-.0013635610230267048,.1635046005249023,-.106659397482872,-1.0408929586410522,69,0,3,3,10,4,4,-1,3,10,2,2,2,5,12,2,2,2,-.009699116460978985,.6112532019615173,-.0662253126502037,0,3,3,10,4,4,-1,3,10,2,2,2,5,12,2,2,2,-.009642653167247772,-1,.0027699959464371204,0,3,3,10,4,4,-1,3,10,2,2,2,5,12,2,2,2,-.009638186544179916,1,-.00029904270195402205,0,2,14,8,2,6,-1,15,8,1,6,2,-.004255393985658884,.2846438884735107,-.1554012000560761,0,3,3,10,4,4,-1,3,10,2,2,2,5,12,2,2,2,-.009622352197766304,-1,.0439991801977158,0,3,3,10,4,4,-1,3,10,2,2,2,5,12,2,2,2,-.009123124182224274,.8686934113502502,-.0027267890982329845,0,2,12,4,3,9,-1,13,4,1,9,3,-.008624043315649033,.4535248875617981,-.0860713794827461,0,2,12,3,1,12,-1,12,7,1,4,3,-.008932414464652538,.1337555944919586,-.2601251900196075,0,2,2,0,18,1,-1,8,0,6,1,3,-.0142078101634979,.3207764029502869,-.0972264111042023,0,3,10,0,10,6,-1,10,0,5,3,2,15,3,5,3,2,.0259110108017921,-.1296408027410507,.2621864974498749,0,2,18,16,2,2,-1,18,17,2,1,2,.00020531509653665125,-.1240428015589714,.2106295973062515,0,3,3,5,4,2,-1,3,5,2,1,2,5,6,2,1,2,-54795680625829846e-21,.1197429969906807,-.2320127934217453,0,2,11,8,3,3,-1,12,8,1,3,3,.006855519954115152,-.0632761269807816,.4104425013065338,0,2,11,7,3,5,-1,12,7,1,5,3,-.0122530404478312,.5488333106040955,-.0397311002016068,0,2,3,19,15,1,-1,8,19,5,1,3,-.0039058770053088665,.2419098019599915,-.0970960110425949,0,2,8,13,3,2,-1,8,14,3,1,2,.0027560980524867773,-.1256967931985855,.1945665031671524,0,3,2,12,8,4,-1,2,12,4,2,2,6,14,4,2,2,-.0077662160620093346,.2976570129394531,-.0968181565403938,0,3,16,16,2,2,-1,16,16,1,1,2,17,17,1,1,2,.00038997188676148653,.0621884018182755,-.4204089939594269,0,2,7,0,3,2,-1,8,0,1,2,3,.0033579880837351084,.0474981404840946,-.6321688294410706,0,2,6,7,2,5,-1,7,7,1,5,2,-.0167455393821001,.7109813094139099,-.0391573496162891,0,2,18,0,2,17,-1,19,0,1,17,2,-.0065409899689257145,-.3504317104816437,.0706169530749321,0,2,16,16,1,3,-1,16,17,1,1,3,.0003001634031534195,.091902457177639,-.2461867034435272,0,2,14,8,3,7,-1,15,8,1,7,3,.0149189904332161,-.0519094504415989,.5663604140281677,0,3,10,17,2,2,-1,10,17,1,1,2,11,18,1,1,2,.00048153079114854336,.064659558236599,-.3659060895442963,0,2,4,9,1,3,-1,4,10,1,1,3,-.00030211321427486837,.1792656928300858,-.1141066029667854,0,2,18,10,2,3,-1,18,11,2,1,3,.0003852141962852329,.1034561991691589,-.2007246017456055,0,2,12,1,3,10,-1,13,1,1,10,3,.008083713240921497,-.0660734623670578,.3028424978256226,0,2,8,12,9,1,-1,11,12,3,1,3,-.0228049699217081,.5296235084533691,-.0401189997792244,0,3,5,18,2,2,-1,5,18,1,1,2,6,19,1,1,2,.00019440450705587864,.0818548202514648,-.2466336041688919,0,2,19,6,1,9,-1,19,9,1,3,3,-.0128480903804302,-.3497331142425537,.0569162294268608,0,3,4,7,2,4,-1,4,7,1,2,2,5,9,1,2,2,-.001093729049898684,.2336868047714233,-.0916048064827919,0,2,1,4,6,14,-1,3,4,2,14,3,.0010032650316134095,.1185218021273613,-.1846919059753418,0,2,10,5,9,3,-1,13,5,3,3,3,-.0446884296834469,-.6436246037483215,.0303632691502571,0,2,18,7,2,6,-1,18,9,2,2,3,.00816575437784195,.0436746589839458,-.4300208985805512,0,2,5,6,2,7,-1,6,6,1,7,2,-.0117178102955222,.4178147912025452,-.0482336990535259,0,2,10,4,6,8,-1,13,4,3,8,2,.0842771306633949,.053461279720068,-.379521906375885,0,2,0,8,2,9,-1,0,11,2,3,3,.0142118399962783,.0449009388685226,-.4298149943351746,0,2,0,7,5,3,-1,0,8,5,1,3,.001502834027633071,.0822276398539543,-.2470639944076538,0,2,8,1,7,2,-1,8,2,7,1,2,.0100035797804594,-.057221669703722,.3460937142372131,0,2,7,5,3,5,-1,8,5,1,5,3,-.009070632047951221,.450580894947052,-.0427953191101551,0,2,19,2,1,2,-1,19,3,1,1,2,-.0003314162022434175,.1833691000938416,-.1075994968414307,0,2,6,7,10,11,-1,11,7,5,11,2,.19723279774189,-.030363829806447,.6642342805862427,0,2,9,19,6,1,-1,11,19,2,1,3,-.007125880103558302,-.8922504782676697,.0256699901074171,0,2,3,0,12,1,-1,7,0,4,1,3,.00869213417172432,-.0707643702626228,.2821052968502045,0,2,4,1,6,5,-1,6,1,2,5,3,.008926212787628174,.0710782334208488,-.3023256063461304,0,2,6,12,12,6,-1,10,12,4,6,3,.0572860091924667,.0509741306304932,-.3919695019721985,0,2,16,13,2,3,-1,16,14,2,1,3,.0037920880131423473,.0338419415056705,-.510162889957428,0,2,7,14,4,2,-1,7,15,4,1,2,-.0014508679741993546,.3087914884090424,-.063845083117485,0,2,7,14,2,2,-1,7,15,2,1,2,.00098390132188797,-.1302956938743591,.1460441052913666,0,3,3,10,2,4,-1,3,10,1,2,2,4,12,1,2,2,-.0017221809830516577,.2915700972080231,-.0685495585203171,0,2,0,3,2,6,-1,0,5,2,2,3,.0109482500702143,.0343514084815979,-.4770225882530212,0,3,1,10,2,2,-1,1,10,1,1,2,2,11,1,1,2,-1717630948405713e-20,.1605526953935623,-.1169084012508392,0,2,16,4,4,3,-1,16,5,4,1,3,-.005488420836627483,-.4341588914394379,.0461062416434288,0,3,5,10,2,4,-1,5,10,1,2,2,6,12,1,2,2,-.0030975250992923975,.3794333934783936,-.05686055123806,0,2,5,11,13,2,-1,5,12,13,1,2,.006418208125978708,-.1585821062326431,.1233541965484619,0,2,10,2,3,11,-1,11,2,1,11,3,.0118312397971749,-.0409292913973331,.458789587020874,0,2,10,2,4,4,-1,10,4,4,2,2,.013540499843657,-.0537255592644215,.3505612015724182,0,2,8,8,6,2,-1,10,8,2,2,3,-.002593215089291334,.1101052016019821,-.1675221025943756,0,2,11,2,3,3,-1,12,2,1,3,3,.0016856270376592875,.0665743574500084,-.3083502054214478,0,3,6,18,14,2,-1,6,18,7,1,2,13,19,7,1,2,.002652469091117382,.0663184821605682,-.2786133885383606,0,2,17,7,1,12,-1,17,11,1,4,3,-.007734172977507114,.1971835941076279,-.1078291982412338,0,2,10,5,10,3,-1,10,6,10,1,3,.005094427149742842,.0853374898433685,-.2484700977802277,0,2,6,1,3,3,-1,7,1,1,3,3,-.0029162371065467596,-.4747635126113892,.033566489815712,0,2,13,8,3,1,-1,14,8,1,1,3,.0030121419113129377,-.0475753806531429,.4258680045604706,0,2,10,14,2,6,-1,10,16,2,2,3,.0031694869976490736,-.1051945015788078,.1716345995664597,0,2,4,1,12,14,-1,8,1,4,14,3,.2232756018638611,-.0143702095374465,.9248365163803101,0,2,14,1,6,14,-1,16,1,2,14,3,-.0955850481987,-.7420663833618164,.0278189703822136,0,3,3,16,2,2,-1,3,16,1,1,2,4,17,1,1,2,3477372956695035e-20,-.1276578009128571,.129266694188118,0,2,0,16,2,2,-1,0,17,2,1,2,7245977030834183e-20,-.1651857942342758,.1003680974245071,-1.0566600561141968,59,0,3,15,6,4,6,-1,15,6,2,3,2,17,9,2,3,2,-.006577827036380768,.3381525874137878,-.1528190970420837,0,2,12,5,2,2,-1,12,6,2,1,2,-.0010922809597104788,.2228236943483353,-.1930849999189377,0,2,7,6,6,13,-1,9,6,2,13,3,-.0297595895826817,.2595987021923065,-.1540940999984741,0,2,1,9,6,5,-1,3,9,2,5,3,-.0131475403904915,.1903381049633026,-.1654399931430817,0,2,0,5,3,4,-1,0,7,3,2,2,-.0014396329643204808,.200717106461525,-.1233894005417824,0,3,4,1,16,2,-1,4,1,8,1,2,12,2,8,1,2,-.0035928250290453434,.2398552000522614,-.129221498966217,0,3,1,18,4,2,-1,1,18,2,1,2,3,19,2,1,2,-.0015314699849113822,-.4901489913463593,.102750301361084,0,2,7,7,3,4,-1,8,7,1,4,3,-.0062372139655053616,.31214639544487,-.114056296646595,0,2,3,4,9,3,-1,6,4,3,3,3,-.033364649862051,-.4952087998390198,.0513284504413605,0,2,4,6,6,10,-1,6,6,2,10,3,-.0228276997804642,.3255882859230042,-.0650893077254295,0,2,9,0,8,10,-1,13,0,4,10,2,-.0861990973353386,-.6764633059501648,.0269856993108988,0,2,8,0,8,1,-1,12,0,4,1,2,-.002106598112732172,.2245243042707443,-.1261022984981537,0,3,6,2,8,16,-1,6,2,4,8,2,10,10,4,8,2,.0391201488673687,.1132939979434013,-.2686063051223755,0,3,14,10,2,10,-1,14,10,1,5,2,15,15,1,5,2,.0035082739777863026,-.1135995984077454,.2564977109432221,0,2,12,11,1,2,-1,12,12,1,1,2,.0005928989849053323,-.1494296938180924,.164098396897316,0,2,16,0,3,8,-1,17,0,1,8,3,.0007176685030572116,.0999056920409203,-.2196796983480454,0,2,14,0,6,10,-1,17,0,3,10,2,-.0218036007136106,-.3171172142028809,.082889586687088,0,2,16,0,3,5,-1,17,0,1,5,3,-.003296277951449156,-.3804872930049896,.0608193799853325,0,2,4,5,11,2,-1,4,6,11,1,2,.0024196270387619734,-.0960130169987679,.2854058146476746,0,2,1,0,2,1,-1,2,0,1,1,2,-.00044187481398694217,.2212793976068497,-.0974349081516266,0,2,0,0,2,3,-1,0,1,2,1,3,.0034523929934948683,.0375531204044819,-.5796905159950256,0,2,11,6,6,11,-1,13,6,2,11,3,-.0218346007168293,.295621395111084,-.0800483003258705,0,2,14,0,3,1,-1,15,0,1,1,3,-.00021309500152710825,.2281450927257538,-.1011418998241425,0,2,19,7,1,2,-1,19,8,1,1,2,-.0016166249988600612,-.5054119825363159,.0447645410895348,0,2,17,0,3,9,-1,18,0,1,9,3,.007595960982143879,.0459865406155586,-.4119768142700195,0,2,12,7,3,4,-1,13,7,1,4,3,.003860180964693427,-.0865631699562073,.2480999976396561,0,3,0,1,14,2,-1,0,1,7,1,2,7,2,7,1,2,.006062223110347986,-.0755573734641075,.2843326032161713,0,2,3,1,3,2,-1,4,1,1,2,3,-.0017097420059144497,-.3529582023620606,.0584104992449284,0,2,4,0,15,2,-1,9,0,5,2,3,.0165155790746212,-.0804869532585144,.2353743016719818,0,2,10,2,6,1,-1,12,2,2,1,3,.004846510011702776,.041895218193531,-.4844304919242859,0,2,9,4,6,11,-1,11,4,2,11,3,-.0311671700328588,.1919230967760086,-.1026815995573998,0,2,2,16,2,4,-1,2,18,2,2,2,.0006189228151924908,-.210857704281807,.0938869267702103,0,2,6,17,6,3,-1,8,17,2,3,3,.0119463102892041,.0390961691737175,-.6224862933158875,0,2,7,9,6,2,-1,9,9,2,2,3,-.0075677200220525265,.1593683958053589,-.1225078031420708,0,2,6,8,9,2,-1,9,8,3,2,3,-.0537474118173122,-.5562217831611633,.0411900095641613,0,3,6,6,2,10,-1,6,6,1,5,2,7,11,1,5,2,.0155135300010443,-.0398268811404705,.6240072846412659,0,2,0,11,2,3,-1,0,12,2,1,3,.0015246650436893106,.0701386779546738,-.3078907132148743,0,2,11,15,4,1,-1,13,15,2,1,2,-.0004831510013900697,.178876593708992,-.109586201608181,0,2,6,17,1,2,-1,6,18,1,1,2,.0027374739293009043,.0274785906076431,-.8848956823348999,0,2,0,0,6,20,-1,2,0,2,20,3,-.0657877177000046,-.4643214046955109,.0350371487438679,0,2,3,10,2,2,-1,4,10,1,2,2,.0012409730115905404,-.0964792370796204,.2877922058105469,0,2,4,7,3,5,-1,5,7,1,5,3,.0008139880956150591,.1151171997189522,-.1676616072654724,0,2,3,12,6,2,-1,5,12,2,2,3,.0239018201828003,-.0326031893491745,.6001734733581543,0,2,6,15,7,4,-1,6,17,7,2,2,.0275566000491381,-.0661373436450958,.2999447882175446,0,3,17,16,2,2,-1,17,16,1,1,2,18,17,1,1,2,-.00038070970913395286,-.3388118147850037,.0644507706165314,0,2,15,1,3,16,-1,16,1,1,16,3,-.0013335429830476642,.1458866000175476,-.1321762055158615,0,2,6,16,6,3,-1,8,16,2,3,3,-.009350799024105072,-.5117782950401306,.0349694713950157,0,2,15,14,3,2,-1,15,15,3,1,2,.00762152299284935,.0232495293021202,-.6961941123008728,0,2,12,16,1,2,-1,12,17,1,1,2,-5340786083252169e-20,.2372737973928452,-.0869107097387314,0,3,0,2,4,4,-1,0,2,2,2,2,2,4,2,2,2,-.0015332329785451293,.192284107208252,-.1042239964008331,0,3,1,1,6,4,-1,1,1,3,2,2,4,3,3,2,2,.004313589073717594,-.0962195470929146,.2560121119022369,0,2,1,18,1,2,-1,1,19,1,1,2,-.000230428806389682,-.3156475126743317,.0588385984301567,0,2,4,7,2,3,-1,4,8,2,1,3,-.007841182872653008,-.6634092926979065,.0245009995996952,0,2,1,0,9,14,-1,1,7,9,7,2,.1710374057292938,.033831499516964,-.4561594128608704,0,3,4,9,2,6,-1,4,9,1,3,2,5,12,1,3,2,-.001601114054210484,.2157489061355591,-.0836225301027298,0,2,3,9,4,3,-1,5,9,2,3,2,-.0105357803404331,.2455231994390488,-.0823844894766808,0,2,0,9,2,4,-1,0,11,2,2,2,-.005835163872689009,-.4780732989311218,.0440862216055393,0,2,16,6,3,10,-1,17,6,1,10,3,-.0187061093747616,-.6002402901649475,.0214100405573845,0,2,16,11,2,1,-1,17,11,1,1,2,-.0009330743923783302,.2432359009981155,-.0741657167673111,-.9769343137741089,88,0,2,5,7,4,4,-1,5,9,4,2,2,.0106462296098471,-.1386138945817947,.2649407088756561,0,2,10,11,9,2,-1,13,11,3,2,3,.0352982692420483,-.075821727514267,.3902106881141663,0,3,15,10,2,2,-1,15,10,1,1,2,16,11,1,1,2,.0007563838735222816,-.095521442592144,.2906199991703033,0,2,10,6,6,14,-1,10,13,6,7,2,.092497706413269,-.2770423889160156,.0794747024774551,0,2,14,7,3,5,-1,15,7,1,5,3,-.002934087999165058,.2298953980207443,-.0785500109195709,0,2,6,11,12,3,-1,10,11,4,3,3,-.0865358486771584,.4774481058120728,-.006823122035712004,0,2,17,16,1,2,-1,17,17,1,1,2,54699288739357144e-21,-.2264260947704315,.0881921127438545,0,2,8,5,5,4,-1,8,7,5,2,2,-.0365925207734108,.2735387086868286,-.0986067429184914,0,2,11,6,4,2,-1,11,7,4,1,2,.0026469118893146515,-.0440839789807796,.3144528865814209,0,3,3,4,8,2,-1,3,4,4,1,2,7,5,4,1,2,-.004427181091159582,.2382272928953171,-.0867842733860016,0,2,0,8,6,6,-1,2,8,2,6,3,-.005188248120248318,.1504276990890503,-.1267210990190506,0,2,7,4,6,2,-1,7,5,6,1,2,.004553040023893118,-.0559450201690197,.3650163114070892,0,2,7,3,6,3,-1,9,3,2,3,3,.0145624103024602,.0363977700471878,-.5355919003486633,0,2,2,17,3,3,-1,2,18,3,1,3,6867756746942177e-20,-.1747962981462479,.1106870993971825,0,2,3,10,6,1,-1,5,10,2,1,3,-.005974490195512772,.3107787072658539,-.0665302276611328,0,2,7,2,6,2,-1,9,2,2,2,3,-.0058691250160336494,-.3190149068832398,.063931830227375,0,2,4,11,9,1,-1,7,11,3,1,3,-.0111403102055192,.2436479032039642,-.0809351801872253,0,2,7,7,11,12,-1,7,13,11,6,2,-.0586435310542583,-.7608326077461243,.0308096297085285,0,2,3,2,3,4,-1,4,2,1,4,3,-.0046097282320261,-.45315021276474,.0298790596425533,0,2,9,7,9,3,-1,12,7,3,3,3,-.00930321030318737,.1451337933540344,-.1103316992521286,0,3,15,11,2,6,-1,15,11,1,3,2,16,14,1,3,2,.0013253629440441728,-.0976989567279816,.196464404463768,0,2,0,5,5,3,-1,0,6,5,1,3,.004980076104402542,.0336480811238289,-.3979220986366272,0,2,8,1,6,12,-1,10,1,2,12,3,-.007654216140508652,.090841993689537,-.1596754938364029,0,2,3,7,15,13,-1,8,7,5,13,3,-.3892059028148651,-.6657109260559082,.0190288294106722,0,2,0,9,9,9,-1,0,12,9,3,3,-.1001966968178749,-.5755926966667175,.0242827795445919,0,2,16,0,3,8,-1,17,0,1,8,3,.0007354121189564466,.0879198014736176,-.161953404545784,0,2,16,2,4,2,-1,18,2,2,2,2,-.0034802639856934547,.2606449127197266,-.0602008104324341,0,2,13,0,6,5,-1,16,0,3,5,2,.008400042541325092,-.1097972989082336,.1570730954408646,0,2,15,1,3,2,-1,16,1,1,2,3,.0023786011151969433,.0360582396388054,-.4727719128131867,0,2,11,8,3,2,-1,12,8,1,2,3,.007383168209344149,-.0357563607394695,.4949859082698822,0,3,1,8,2,12,-1,1,8,1,6,2,2,14,1,6,2,.003211562056094408,-.1012556031346321,.1574798971414566,0,2,0,1,6,12,-1,2,1,2,12,3,-.0782096683979034,-.7662708163261414,.0229658298194408,0,2,19,17,1,3,-1,19,18,1,1,3,5330398926162161e-20,-.1341435015201569,.1111491993069649,0,2,11,3,3,10,-1,12,3,1,10,3,-.009641915559768677,.2506802976131439,-.0666081383824348,0,2,8,1,9,8,-1,11,1,3,8,3,-.0710926726460457,-.4005681872367859,.0402977913618088,0,3,18,16,2,2,-1,18,16,1,1,2,19,17,1,1,2,.00035171560011804104,.041861180216074,-.3296119868755341,0,3,18,16,2,2,-1,18,16,1,1,2,19,17,1,1,2,-.0003345815057400614,-.2602983117103577,.0678927376866341,0,2,6,13,2,6,-1,6,15,2,2,3,-.0041451421566307545,.2396769970655441,-.0720933377742767,0,2,9,14,2,2,-1,9,15,2,1,2,.003175450023263693,-.0712352693080902,.241284504532814,0,3,14,10,2,4,-1,14,10,1,2,2,15,12,1,2,2,-.005518449004739523,.5032023787498474,-.0296866800636053,0,3,0,15,2,2,-1,0,15,1,1,2,1,16,1,1,2,-.00030242869979701936,.2487905025482178,-.0567585788667202,0,3,6,7,2,2,-1,6,7,1,1,2,7,8,1,1,2,-.0013125919504091144,.3174780011177063,-.0418458618223667,0,3,11,18,2,2,-1,11,18,1,1,2,12,19,1,1,2,-.00027123570907860994,-.2704207003116608,.0568289905786514,0,3,0,0,6,4,-1,0,0,3,2,2,3,2,3,2,2,-.007324177771806717,.2755667865276337,-.0542529709637165,0,2,4,1,6,6,-1,6,1,2,6,3,-.0168517101556063,-.3485291004180908,.0453689992427826,0,2,15,13,5,4,-1,15,15,5,2,2,.0299021005630493,.0316210798919201,-.4311437010765076,0,2,7,17,6,1,-1,9,17,2,1,3,.0028902660124003887,.0380299612879753,-.3702709972858429,0,2,16,19,4,1,-1,18,19,2,1,2,-.0019242949783802032,.2480027973651886,-.059333298355341,0,2,16,16,4,4,-1,18,16,2,4,2,.004935414995998144,-.0830684006214142,.2204380929470062,0,2,7,8,9,4,-1,10,8,3,4,3,.0820756033062935,-.0194134395569563,.6908928751945496,0,3,16,18,2,2,-1,16,18,1,1,2,17,19,1,1,2,-.0002469948958605528,-.2466056942939758,.0647764503955841,0,3,2,9,2,4,-1,2,9,1,2,2,3,11,1,2,2,-.0018365769647061825,.2883616089820862,-.0533904582262039,0,3,0,3,8,4,-1,0,3,4,2,2,4,5,4,2,2,-.004955381155014038,.1274082958698273,-.1255941987037659,0,2,0,1,8,1,-1,4,1,4,1,2,-.008308662101626396,.2347811013460159,-.07167649269104,0,2,0,5,8,9,-1,4,5,4,9,2,-.1087991967797279,-.2599223852157593,.0586897395551205,0,2,7,18,6,2,-1,9,18,2,2,3,-.009678645059466362,-.707204282283783,.0187492594122887,0,2,0,4,1,12,-1,0,8,1,4,3,-.0271368306130171,-.5838422775268555,.021684130653739,0,2,19,13,1,6,-1,19,15,1,2,3,-.006538977846503258,-.5974891185760498,.0214803107082844,0,2,2,8,6,8,-1,4,8,2,8,3,-.0120956301689148,.1326903998851776,-.099722720682621,0,2,0,0,9,17,-1,3,0,3,17,3,-.1677609980106354,-.5665506720542908,.0321230888366699,0,2,7,9,6,8,-1,9,9,2,8,3,-.0132625503465533,.1149559020996094,-.1173838973045349,0,2,5,10,9,4,-1,8,10,3,4,3,.076744519174099,-.0314132310450077,.5993549227714539,0,2,5,0,8,3,-1,5,1,8,1,3,.005078522954136133,-.0529119409620762,.2334239929914475,0,3,16,6,4,4,-1,16,6,2,2,2,18,8,2,2,2,.0031800279393792152,-.0777343884110451,.1765290945768356,0,3,17,4,2,8,-1,17,4,1,4,2,18,8,1,4,2,-.0017729829996824265,.1959162950515747,-.0797521993517876,0,2,2,16,1,3,-1,2,17,1,1,3,-.00048560940194875,-.2880037128925324,.0490471199154854,0,2,2,16,1,3,-1,2,17,1,1,3,.00036554320831783116,.0679228976368904,-.2249943017959595,0,2,11,0,1,3,-1,11,1,1,1,3,-.0002693867136258632,.1658217012882233,-.0897440984845161,0,2,11,2,9,7,-1,14,2,3,7,3,.0786842331290245,.0260816793888807,-.5569373965263367,0,2,10,2,3,6,-1,11,2,1,6,3,-.0007377481088042259,.1403687000274658,-.1180030032992363,0,2,5,9,15,2,-1,5,10,15,1,2,.0239578299224377,.0304707400500774,-.4615997970104218,0,2,8,16,6,2,-1,8,17,6,1,2,-.001623908057808876,.2632707953453064,-.0567653700709343,0,3,9,16,10,2,-1,9,16,5,1,2,14,17,5,1,2,-.0009081974858418107,.1546245962381363,-.1108706966042519,0,3,9,17,2,2,-1,9,17,1,1,2,10,18,1,1,2,.0003980624896939844,.0556303709745407,-.2833195924758911,0,3,10,15,6,4,-1,10,15,3,2,2,13,17,3,2,2,.002050644950941205,-.0916048362851143,.1758553981781006,0,2,4,5,15,12,-1,9,5,5,12,3,.0267425496131182,.062003031373024,-.2448700070381165,0,2,11,13,2,3,-1,11,14,2,1,3,-.0021497008856385946,.2944929897785187,-.0532181486487389,0,2,8,13,7,3,-1,8,14,7,1,3,.005667165853083134,-.0642982423305511,.249056801199913,0,2,1,12,1,2,-1,1,13,1,1,2,6831790233263746e-20,-.1681963056325913,.0965485796332359,0,3,16,18,2,2,-1,16,18,1,1,2,17,19,1,1,2,.0001760043960530311,.0653080120682716,-.2426788061857224,0,2,1,19,18,1,-1,7,19,6,1,3,.004186160862445831,-.0979885831475258,.1805288940668106,0,2,1,17,6,1,-1,4,17,3,1,2,-.0021808340679854155,.192312702536583,-.0941239297389984,0,2,1,3,1,12,-1,1,9,1,6,2,.021730400621891,.0355785116553307,-.4508853852748871,0,2,0,9,3,6,-1,0,11,3,2,3,-.0147802699357271,-.4392701089382172,.0317355915904045,0,2,5,4,3,10,-1,6,4,1,10,3,-.0036145891062915325,.1981147974729538,-.0777014195919037,0,2,6,17,2,1,-1,7,17,1,1,2,.0018892709631472826,.0199624393135309,-.7204172015190125,0,2,1,0,6,12,-1,3,0,2,12,3,-.0013822480104863644,.0984669476747513,-.1488108038902283,0,2,4,7,9,2,-1,7,7,3,2,3,-.0039505911991000175,.1159323006868362,-.1279197037220001,-1.012935996055603,58,0,2,6,11,9,1,-1,9,11,3,1,3,-.0193955395370722,.474747508764267,-.1172109022736549,0,2,17,10,2,10,-1,17,15,2,5,2,.013118919916451,-.255521297454834,.1637880057096481,0,3,4,10,2,10,-1,4,10,1,5,2,5,15,1,5,2,-.0005160680157132447,.1945261955261231,-.17448890209198,0,2,12,3,3,12,-1,13,3,1,12,3,-.0131841599941254,.441814512014389,-.0900487527251244,0,3,15,3,4,6,-1,15,3,2,3,2,17,6,2,3,2,.0034657081123441458,-.1347709000110626,.1805634051561356,0,2,12,8,3,3,-1,13,8,1,3,3,.006298020016402006,-.0541649796068668,.3603338003158569,0,2,4,14,2,4,-1,4,16,2,2,2,.0016879989998415112,-.1999794989824295,.1202159970998764,0,2,6,16,1,3,-1,6,17,1,1,3,.00036039709812030196,.1052414029836655,-.2411606013774872,0,2,1,1,2,3,-1,2,1,1,3,2,-.001527684973552823,.2813552916049957,-.0689648166298866,0,2,0,2,4,1,-1,2,2,2,1,2,.00350335706025362,-.0825195834040642,.4071359038352966,0,2,8,17,12,3,-1,12,17,4,3,3,-.004733716137707233,.1972700953483582,-.117101401090622,0,2,9,16,6,4,-1,11,16,2,4,3,-.0115571497008204,-.5606111288070679,.0681709572672844,0,2,4,6,3,6,-1,4,9,3,3,2,-.0274457205086946,.4971862137317658,-.0623801499605179,0,2,6,2,12,9,-1,6,5,12,3,3,-.0528257787227631,.169212207198143,-.1309355050325394,0,3,6,0,14,20,-1,6,0,7,10,2,13,10,7,10,2,-.2984969913959503,-.6464967131614685,.0400768183171749,0,3,15,16,2,2,-1,15,16,1,1,2,16,17,1,1,2,-.00026307269581593573,.2512794137001038,-.0894948393106461,0,3,15,16,2,2,-1,15,16,1,1,2,16,17,1,1,2,.00023261709429789335,-.0868439897894859,.2383197993040085,0,2,19,8,1,3,-1,19,9,1,1,3,.00023631360090803355,.1155446022748947,-.189363494515419,0,2,13,4,1,2,-1,13,5,1,1,2,.0020742209162563086,-.0485948510468006,.5748599171638489,0,2,0,4,4,2,-1,0,5,4,1,2,-.007030888926237822,-.5412080883979797,.0487437509000301,0,2,19,5,1,6,-1,19,7,1,2,3,.00826522707939148,.0264945197850466,-.6172845959663391,0,2,16,0,2,1,-1,17,0,1,1,2,.0002004276029765606,-.1176863014698029,.1633386015892029,0,2,13,1,1,3,-1,13,2,1,1,3,.0016470040427520871,-.0599549189209938,.3517970144748688,0,2,17,17,1,3,-1,17,18,1,1,3,-.0003564253856893629,-.344202995300293,.0649482533335686,0,3,5,4,8,8,-1,5,4,4,4,2,9,8,4,4,2,-.0309358704835176,.1997970044612885,-.0976936966180801,0,3,1,2,2,2,-1,1,2,1,1,2,2,3,1,1,2,-.0006357877282425761,-.3148139119148254,.0594250410795212,0,3,0,0,8,6,-1,0,0,4,3,2,4,3,4,3,2,-.0118621801957488,.2004369050264359,-.0894475430250168,0,2,6,3,4,2,-1,6,4,4,1,2,.007150893099606037,-.0390060618519783,.5332716107368469,0,2,1,0,3,3,-1,1,1,3,1,3,-.0020059191156178713,-.2846972048282623,.0707236081361771,0,2,6,1,7,2,-1,6,2,7,1,2,.0036412389017641544,-.1066031977534294,.2494480013847351,0,2,2,6,12,6,-1,6,6,4,6,3,-.1346742957830429,.4991008043289185,-.0403322204947472,0,2,1,16,9,2,-1,4,16,3,2,3,-.002254765946418047,.1685169041156769,-.1111928001046181,0,2,7,15,6,4,-1,9,15,2,4,3,.004384228959679604,.0861394926905632,-.2743177115917206,0,2,6,15,12,1,-1,12,15,6,1,2,-.007336116861552,.2487521022558212,-.0959191620349884,0,2,17,17,1,3,-1,17,18,1,1,3,.0006466691265814006,.0674315765500069,-.3375408053398132,0,3,17,15,2,2,-1,17,15,1,1,2,18,16,1,1,2,.0002298376930411905,-.0839030519127846,.24584099650383,0,2,3,13,3,3,-1,3,14,3,1,3,.006703907158225775,.0290793292224407,-.6905593872070312,0,2,10,17,1,3,-1,10,18,1,1,3,5073488864582032e-20,-.1569671928882599,.1196542978286743,0,2,4,0,14,8,-1,11,0,7,8,2,-.2033555954694748,-.6950634717941284,.0275075193494558,0,2,2,0,12,2,-1,6,0,4,2,3,.009493941441178322,-.0874493718147278,.2396833002567291,0,2,2,0,4,3,-1,4,0,2,3,2,-.002405524021014571,.2115096002817154,-.1314893066883087,0,2,13,1,1,2,-1,13,2,1,1,2,-.00011342419747961685,.1523378938436508,-.1272590011358261,0,2,7,5,3,6,-1,8,5,1,6,3,.0149922100827098,-.0341279692947865,.506240725517273,0,3,18,2,2,2,-1,18,2,1,1,2,19,3,1,1,2,.0007406820077449083,.0487647503614426,-.4022532105445862,0,2,15,1,2,14,-1,16,1,1,14,2,-.004245944786816835,.2155476063489914,-.0871269926428795,0,3,15,6,2,2,-1,15,6,1,1,2,16,7,1,1,2,.0006865510949864984,-.0754187181591988,.2640590965747833,0,2,3,1,6,3,-1,5,1,2,3,3,-.0167514607310295,-.6772903203964233,.0329187288880348,0,3,7,16,2,2,-1,7,16,1,1,2,8,17,1,1,2,-.00026301678735762835,.2272586971521378,-.0905348733067513,0,3,5,17,2,2,-1,5,17,1,1,2,6,18,1,1,2,.0004339861043263227,.0558943785727024,-.3559266924858093,0,2,9,10,6,10,-1,11,10,2,10,3,-.0201501492410898,.1916276067495346,-.0949299708008766,0,2,10,17,6,3,-1,12,17,2,3,3,-.0144521296024323,-.6851034164428711,.0254221707582474,0,2,14,5,2,10,-1,14,10,2,5,2,-.0211497396230698,.3753319084644318,-.0514965802431107,0,2,11,12,6,2,-1,11,13,6,1,2,.0211377702653408,.0290830805897713,-.8943036794662476,0,2,8,1,1,3,-1,8,2,1,1,3,.0011524349683895707,-.0696949362754822,.2729980051517487,0,3,12,15,2,2,-1,12,15,1,1,2,13,16,1,1,2,-.00019070580310653895,.1822811961174011,-.0983670726418495,0,3,6,8,6,4,-1,6,8,3,2,2,9,10,3,2,2,-.0363496318459511,-.8369309902191162,.0250557605177164,0,2,7,5,3,5,-1,8,5,1,5,3,-.009063207544386387,.4146350026130676,-.0544134490191936,0,2,0,5,7,3,-1,0,6,7,1,3,-.0020535490475594997,-.1975031048059464,.1050689965486527,-.9774749279022217,93,0,2,7,9,6,6,-1,9,9,2,6,3,-.0227170195430517,.2428855001926422,-.1474552005529404,0,2,5,7,8,8,-1,5,11,8,4,2,.0255059506744146,-.2855173945426941,.1083720996975899,0,3,4,9,2,6,-1,4,9,1,3,2,5,12,1,3,2,-.0026640091091394424,.2927573025226593,-.1037271022796631,0,2,10,11,6,1,-1,12,11,2,1,3,-.003811528906226158,.2142689973115921,-.1381113976240158,0,2,13,6,6,11,-1,15,6,2,11,3,-.0167326908558607,.2655026018619537,-.0439113304018974,0,3,8,17,2,2,-1,8,17,1,1,2,9,18,1,1,2,.0004927701083943248,.02110455930233,-.4297136068344116,0,2,4,12,12,1,-1,8,12,4,1,3,-.0366911105811596,.5399242043495178,-.0436488017439842,0,2,11,17,3,2,-1,11,18,3,1,2,.0012615970335900784,-.1293386965990067,.1663877069950104,0,2,8,17,6,1,-1,10,17,2,1,3,-.008410685695707798,-.9469841122627258,.0214658491313457,0,2,4,1,14,6,-1,4,3,14,2,3,.0649027228355408,-.0717277601361275,.2661347985267639,0,2,14,2,2,12,-1,14,8,2,6,2,.0303050000220537,-.0827824920415878,.2769432067871094,0,2,12,13,3,2,-1,12,14,3,1,2,.0025875340215861797,-.1296616941690445,.1775663048028946,0,2,6,1,6,1,-1,8,1,2,1,3,-.00702404510229826,-.6424317955970764,.0399432107806206,0,2,10,6,6,1,-1,12,6,2,1,3,-.0010099769569933414,.1417661011219025,-.1165997013449669,0,2,3,19,2,1,-1,4,19,1,1,2,-4117907155887224e-20,.1568766981363297,-.1112734004855156,0,3,18,16,2,2,-1,18,16,1,1,2,19,17,1,1,2,-.0004729315114673227,-.3355455994606018,.0459777303040028,0,2,16,11,3,7,-1,17,11,1,7,3,-.0017178079579025507,.1695290952920914,-.1057806983590126,0,2,19,5,1,6,-1,19,8,1,3,2,-.0133331697434187,-.5825781226158142,.0309784300625324,0,2,9,8,4,3,-1,9,9,4,1,3,-.0018783430568873882,.1426687985658646,-.111312597990036,0,3,16,8,4,4,-1,16,8,2,2,2,18,10,2,2,2,-.006576598156243563,.2756136059761047,-.0531003288924694,0,3,2,8,2,2,-1,2,8,1,1,2,3,9,1,1,2,-7721038127783686e-20,.1324024051427841,-.111677996814251,0,3,3,5,6,4,-1,3,5,3,2,2,6,7,3,2,2,.0219685398042202,-.0269681606441736,.5006716847419739,0,3,2,3,8,16,-1,2,3,4,8,2,6,11,4,8,2,-.027445750311017,-.240867406129837,.0604782700538635,0,2,17,17,1,3,-1,17,18,1,1,3,7830584945622832e-20,-.1333488970994949,.1012346968054771,0,2,7,2,8,11,-1,11,2,4,11,2,.0701906830072403,-.0548637807369232,.2480994015932083,0,2,13,3,6,14,-1,16,3,3,14,2,-.0719021335244179,-.3784669041633606,.0422109998762608,0,2,0,9,18,2,-1,6,9,6,2,3,-.1078097969293594,-.3748658895492554,.0428334400057793,0,2,6,10,14,3,-1,6,11,14,1,3,.0014364200178533792,.0804763585329056,-.1726378947496414,0,2,10,9,9,3,-1,13,9,3,3,3,.068289190530777,-.0355957895517349,.4076131880283356,0,3,3,5,4,6,-1,3,5,2,3,2,5,8,2,3,2,-.00680371792986989,.1923379004001617,-.0823680236935616,0,2,3,7,3,7,-1,4,7,1,7,3,-.0005619348958134651,.1305712014436722,-.1435514986515045,0,2,2,8,11,6,-1,2,10,11,2,3,-.0582766495645046,-.3012543916702271,.0528196506202221,0,2,8,9,6,3,-1,8,10,6,1,3,-.006120571866631508,.2204390019178391,-.0756917521357536,0,2,3,3,3,11,-1,4,3,1,11,3,-.0135943097993732,-.3904936015605927,.0418571084737778,0,2,0,19,6,1,-1,3,19,3,1,2,.0013626200379803777,-.0953634232282639,.1497032046318054,0,2,18,18,1,2,-1,18,19,1,1,2,-.0001507421984570101,-.2394558042287827,.0647983327507973,0,3,8,0,12,6,-1,8,0,6,3,2,14,3,6,3,2,-.077414259314537,.5594198107719421,-.0245168805122375,0,2,19,5,1,3,-1,19,6,1,1,3,.0009211787255480886,.0549288615584373,-.2793481051921845,0,2,5,8,2,1,-1,6,8,1,1,2,.001025078003294766,-.0621673092246056,.249763697385788,0,2,13,11,2,1,-1,14,11,1,1,2,-.000811747508123517,.2343793958425522,-.0657258108258247,0,2,3,6,15,13,-1,8,6,5,13,3,.0834310203790665,.0509548000991344,-.3102098107337952,0,2,4,3,6,2,-1,6,3,2,2,3,-.009201445616781712,-.3924253880977631,.0329269506037235,0,2,0,18,1,2,-1,0,19,1,1,2,-.00029086650465615094,-.3103975057601929,.0497118197381496,0,2,7,8,2,6,-1,8,8,1,6,2,.00775768980383873,-.0440407507121563,.3643135130405426,0,2,3,0,6,19,-1,5,0,2,19,3,-.1246609017252922,-.819570779800415,.0191506408154964,0,2,3,1,6,5,-1,5,1,2,5,3,.0132425501942635,.0389888398349285,-.3323068022727966,0,2,17,14,3,6,-1,17,16,3,2,3,-.006677012890577316,-.357901394367218,.0404602102935314,0,2,17,13,2,6,-1,18,13,1,6,2,-.0027479929849505424,.2525390088558197,-.0564278215169907,0,2,17,18,2,2,-1,18,18,1,2,2,.0008265965152531862,-.07198865711689,.2278047949075699,0,2,11,14,9,4,-1,14,14,3,4,3,-.0501534007489681,-.630364716053009,.027462050318718,0,3,15,8,4,6,-1,15,8,2,3,2,17,11,2,3,2,.007420314941555262,-.0666107162833214,.2778733968734741,0,2,1,16,1,3,-1,1,17,1,1,3,-.0006795178051106632,-.3632706105709076,.0427954308688641,0,2,7,0,3,14,-1,8,0,1,14,3,-.0019305750029161572,.1419623047113419,-.1075998023152351,0,2,12,0,2,1,-1,13,0,1,1,2,-.0003813267103396356,.2159176021814346,-.0702026635408401,0,2,7,9,6,5,-1,10,9,3,5,2,-.0709903463721275,.4526660144329071,-.0407504811882973,0,2,15,5,4,9,-1,17,5,2,9,2,-.0533680804073811,-.6767405867576599,.0192883405834436,0,2,11,0,6,6,-1,13,0,2,6,3,-.0200648494064808,-.4336543083190918,.0318532884120941,0,3,16,15,2,2,-1,16,15,1,1,2,17,16,1,1,2,.001197636011056602,-.0265598706901073,.5079718232154846,0,3,16,15,2,2,-1,16,15,1,1,2,17,16,1,1,2,-.0002269730030093342,.1801259964704514,-.0836065486073494,0,2,13,2,2,18,-1,13,11,2,9,2,.0152626996859908,-.2023892998695374,.067422017455101,0,2,8,4,8,10,-1,8,9,8,5,2,-.2081176936626434,.6694386005401611,-.0224521104246378,0,2,8,3,2,3,-1,8,4,2,1,3,.001551436958834529,-.0751218423247337,.17326919734478,0,2,11,1,6,9,-1,11,4,6,3,3,-.0529240109026432,.2499251961708069,-.0628791674971581,0,2,15,4,5,6,-1,15,6,5,2,3,-.0216488502919674,-.2919428050518036,.0526144914329052,0,3,12,18,2,2,-1,12,18,1,1,2,13,19,1,1,2,-.00022905069636180997,-.2211730033159256,.0631683394312859,0,2,1,17,1,3,-1,1,18,1,1,3,5017007060814649e-20,-.1151070967316628,.1161144003272057,0,2,12,19,2,1,-1,13,19,1,1,2,-.0001641606941120699,.1587152034044266,-.0826006010174751,0,2,8,10,6,6,-1,10,10,2,6,3,-.0120032895356417,.1221809014678001,-.112296998500824,0,2,14,2,6,5,-1,16,2,2,5,3,-.0177841000258923,-.3507278859615326,.0313419215381145,0,2,9,5,2,6,-1,9,7,2,2,3,-.006345758214592934,.1307806968688965,-.1057441011071205,0,2,1,15,2,2,-1,2,15,1,2,2,-.0007952324231155217,.1720467060804367,-.086001992225647,0,2,18,17,1,3,-1,18,18,1,1,3,-.00031029590172693133,-.2843317091464996,.0518171191215515,0,2,10,14,4,6,-1,10,16,4,2,3,-.0170537102967501,.3924242854118347,-.0401432700455189,0,2,9,7,3,2,-1,10,7,1,2,3,.004650495946407318,-.031837560236454,.4123769998550415,0,3,6,9,6,2,-1,6,9,3,1,2,9,10,3,1,2,-.0103587601333857,-.5699319839477539,.0292483791708946,0,2,0,2,1,12,-1,0,6,1,4,3,-.0221962407231331,-.4560528993606567,.0262859892100096,0,2,4,0,15,1,-1,9,0,5,1,3,-.0070536029525101185,.1599832028150559,-.091594859957695,0,3,9,0,8,2,-1,9,0,4,1,2,13,1,4,1,2,-.0005709429970011115,-.1407632976770401,.1028741970658302,0,2,12,2,8,1,-1,16,2,4,1,2,-.0022152599412947893,.1659359931945801,-.0852739885449409,0,2,7,1,10,6,-1,7,3,10,2,3,-.0280848909169436,.2702234089374542,-.0558738112449646,0,2,18,6,2,3,-1,18,7,2,1,3,.0021515151020139456,.0424728915095329,-.3200584948062897,0,3,4,12,2,2,-1,4,12,1,1,2,5,13,1,1,2,-.00029733829433098435,.1617716997861862,-.0851155892014503,0,2,6,6,6,2,-1,8,6,2,2,3,-.0166947804391384,-.4285877048969269,.0305416099727154,0,2,0,9,9,6,-1,3,9,3,6,3,.1198299005627632,-.0162772908806801,.7984678149223328,0,2,17,18,2,2,-1,18,18,1,2,2,-.000354994204826653,.1593593955039978,-.0832728818058968,0,2,11,2,6,16,-1,13,2,2,16,3,-.0182262696325779,.1952728033065796,-.0739398896694183,0,2,2,4,15,13,-1,7,4,5,13,3,-.00040238600922748446,.0791018083691597,-.2080612927675247,0,2,16,2,3,10,-1,17,2,1,10,3,.0004089206049684435,.1003663018345833,-.1512821018695831,0,2,6,10,2,1,-1,7,10,1,1,2,.0009536811267025769,-.0730116665363312,.2175202071666718,0,2,1,1,18,16,-1,10,1,9,16,2,.4308179914951325,-.0274506993591785,.570615828037262,0,2,14,4,3,15,-1,15,4,1,15,3,.0005356483161449432,.1158754006028175,-.1279056072235107,0,2,19,13,1,2,-1,19,14,1,1,2,2443073026370257e-20,-.1681662946939468,.0804499834775925,0,2,2,6,5,8,-1,2,10,5,4,2,-.0553456507623196,.4533894956111908,-.0312227793037891]);\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_aiot.js",
    "content": "'use strict';\r\n\r\nEntry.AIoT = {\r\n    id: '26.2',\r\n    name: 'AIoT',\r\n    url: 'http://wonn.co.kr/',\r\n    imageName: 'aiot.png',\r\n    title: {\r\n        ko: 'AIoT 보드',\r\n        en: 'AIoT board',\r\n    },\r\n   \r\n    setZero() {  \r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[key].data = 0;\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO_PIN: 4,\r\n        TONE: 5,\r\n        PULSE_IN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n        NEOPIXEL_INIT: 9,\r\n        NEOPIXEL_COLOR: 10,\r\n        DHT_INIT: 21,\r\n        DHT_TEMP: 22,\r\n        DHT_HUMI: 23,\r\n        NO_TONE: 24,\r\n        LCD_INIT: 41,\r\n        LCD: 42,\r\n        LCD_CLEAR: 43,\r\n        LCD_EMOTICON: 44,\t\t\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    highList: ['high', '1', 'on'],\r\n    lowList: ['low', '0', 'off'],\r\n\tduration: {\r\n        TIME_1ms: 1,\r\n        TIME_5ms: 5,\r\n        TIME_10ms: 10,\r\n        TIME_20ms: 20,\r\n        TIME_50ms: 50,\r\n        TIME_100ms: 100,\r\n        TIME_200ms: 200, \r\n        TIME_500ms: 500,    \r\n        TIME_600ms: 600,   \r\n    }, \r\n\ttoByte: function(data) {\r\n        switch (data) {\r\n            case ' ':\r\n                data = 32;\r\n                break;\r\n            case '!':\r\n                data = 33;\r\n                break;\r\n            case '\"':\r\n                data = 34;\r\n                break;\r\n            case '#':\r\n                data = 35;\r\n                break;\r\n            case '$':\r\n                data = 36;\r\n                break;\r\n            case '%':\r\n                data = 37;\r\n                break;\r\n            case '&':\r\n                data = 38;\r\n                break;\r\n            case \"'\":\r\n                data = 39;\r\n                break;\r\n            case '(':\r\n                data = 40;\r\n                break;\r\n            case ')':\r\n                data = 41;\r\n                break;\r\n            case '*':\r\n                data = 42;\r\n                break;\r\n            case '+':\r\n                data = 43;\r\n                break;\r\n            case ',':\r\n                data = 44;\r\n                break;\r\n            case '-':\r\n                data = 45;\r\n                break;\r\n            case '.':\r\n                data = 46;\r\n                break;\r\n            case '/':\r\n                data = 47;\r\n                break;\r\n            case '0':\r\n                data = 48;\r\n                break;\r\n            case '1':\r\n                data = 49;\r\n                break;\r\n            case '2':\r\n                data = 50;\r\n                break;\r\n            case '3':\r\n                data = 51;\r\n                break;\r\n            case '4':\r\n                data = 52;\r\n                break;\r\n            case '5':\r\n                data = 53;\r\n                break;\r\n            case '6':\r\n                data = 54;\r\n                break;\r\n            case '7':\r\n                data = 55;\r\n                break;\r\n            case '8':\r\n                data = 56;\r\n                break;\r\n            case '9':\r\n                data = 57;\r\n                break;\r\n            case ':':\r\n                data = 58;\r\n                break;\r\n            case ';':\r\n                data = 59;\r\n                break;\r\n            case '<':\r\n                data = 60;\r\n                break;\r\n            case '=':\r\n                data = 61;\r\n                break;\r\n            case '>':\r\n                data = 62;\r\n                break;\r\n            case '?':\r\n                data = 63;\r\n                break;\r\n            case '@':\r\n                data = 64;\r\n                break;\r\n            case 'A':\r\n                data = 65;\r\n                break;\r\n            case 'B':\r\n                data = 66;\r\n                break;\r\n            case 'C':\r\n                data = 67;\r\n                break;\r\n            case 'D':\r\n                data = 68;\r\n                break;\r\n            case 'E':\r\n                data = 69;\r\n                break;\r\n            case 'F':\r\n                data = 70;\r\n                break;\r\n            case 'G':\r\n                data = 71;\r\n                break;\r\n            case 'H':\r\n                data = 72;\r\n                break;\r\n            case 'I':\r\n                data = 73;\r\n                break;\r\n            case 'J':\r\n                data = 74;\r\n                break;\r\n            case 'K':\r\n                data = 75;\r\n                break;\r\n            case 'L':\r\n                data = 76;\r\n                break;\r\n            case 'M':\r\n                data = 77;\r\n                break;\r\n            case 'N':\r\n                data = 78;\r\n                break;\r\n            case 'O':\r\n                data = 79;\r\n                break;\r\n            case 'P':\r\n                data = 80;\r\n                break;\r\n            case 'Q':\r\n                data = 81;\r\n                break;\r\n            case 'R':\r\n                data = 82;\r\n                break;\r\n            case 'S':\r\n                data = 83;\r\n                break;\r\n            case 'T':\r\n                data = 84;\r\n                break;\r\n            case 'U':\r\n                data = 85;\r\n                break;\r\n            case 'V':\r\n                data = 86;\r\n                break;\r\n            case 'W':\r\n                data = 87;\r\n                break;\r\n            case 'X':\r\n                data = 88;\r\n                break;\r\n            case 'Y':\r\n                data = 89;\r\n                break;\r\n            case 'Z':\r\n                data = 90;\r\n                break;\r\n            case '[':\r\n                data = 91;\r\n                break;\r\n            case '\\\\':\r\n                data = 92;\r\n                break;\r\n            case ']':\r\n                data = 93;\r\n                break;\r\n            case '^':\r\n                data = 94;\r\n                break;\r\n            case '_':\r\n                data = 95;\r\n                break;\r\n            case '`':\r\n                data = 96;\r\n                break;\r\n            case 'a':\r\n                data = 97;\r\n                break;\r\n            case 'b':\r\n                data = 98;\r\n                break;\r\n            case 'c':\r\n                data = 99;\r\n                break;\r\n            case 'd':\r\n                data = 100;\r\n                break;\r\n            case 'e':\r\n                data = 101;\r\n                break;\r\n            case 'f':\r\n                data = 102;\r\n                break;\r\n            case 'g':\r\n                data = 103;\r\n                break;\r\n            case 'h':\r\n                data = 104;\r\n                break;\r\n            case 'i':\r\n                data = 105;\r\n                break;\r\n            case 'j':\r\n                data = 106;\r\n                break;\r\n            case 'k':\r\n                data = 107;\r\n                break;\r\n            case 'l':\r\n                data = 108;\r\n                break;\r\n            case 'm':\r\n                data = 109;\r\n                break;\r\n            case 'n':\r\n                data = 110;\r\n                break;\r\n            case 'o':\r\n                data = 111;\r\n                break;\r\n            case 'p':\r\n                data = 112;\r\n                break;\r\n            case 'q':\r\n                data = 113;\r\n                break;\r\n            case 'r':\r\n                data = 114;\r\n                break;\r\n            case 's':\r\n                data = 115;\r\n                break;\r\n            case 't':\r\n                data = 116;\r\n                break;\r\n            case 'u':\r\n                data = 117;\r\n                break;\r\n            case 'v':\r\n                data = 118;\r\n                break;\r\n            case 'w':\r\n                data = 119;\r\n                break;\r\n            case 'x':\r\n                data = 120;\r\n                break;\r\n            case 'y':\r\n                data = 121;\r\n                break;\r\n            case 'z':\r\n                data = 122;\r\n                break;\r\n            case '{':\r\n                data = 123;\r\n                break;\r\n            case '|':\r\n                data = 124;\r\n                break;\r\n            case '}':\r\n                data = 125;\r\n                break;\r\n            case '~':\r\n                data = 126;\r\n                break;\r\n        }\r\n\r\n        return data;\r\n    },\r\n    BlockState: {},\r\n};\r\n// 하드웨어 블록 등록\r\n// 여기에 등록된 블록이 순서대로 나열되며 설정한 이름으로 화면에 보임\r\nEntry.AIoT.blockMenuBlocks = [\r\n    'aiot_get_analog_value',        // 아날로그 값 읽기\r\n    'aiot_get_analog_value_map',\r\n    'aiot_get_ultrasonic_value', \r\n    'aiot_get_digital',       // 디지털 입력                     \r\n    'aiot_toggle_led',\r\n    'aiot_digital_pwm',     \r\n    'aiot_set_tone',\r\n\t'aiot_set_noTone',\r\n    'aiot_set_servo',    \r\n\t'aiot_set_neopixel_init',\r\n\t'aiot_set_neopixel',\r\n\t'aiot_set_dht_init',\r\n\t'aiot_get_dht_temp_value',\r\n\t'aiot_get_dht_humi_value',\r\n\t'aiot_get_lcd_row',\r\n\t'aiot_get_lcd_col',\r\n\t'aiot_set_I2CLCD_init',\r\n\t'aiot_set_I2CLCD_print',\r\n\t'aiot_set_I2CLCD_clear',\r\n\t'aiot_set_I2CLCD_emoticon',\r\n];\r\n// 블록 이름  번역\r\nEntry.AIoT.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                aiot_get_analog_value: '아날로그 %1 번 센서값',\r\n                aiot_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 변환값',\r\n                aiot_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 거리값',                 \r\n                aiot_get_digital: '디지털 %1 번 입력값',               \r\n                aiot_toggle_led: '디지털 %1 번 핀 %2 %3',                \r\n                aiot_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',                \r\n                aiot_set_tone: '디지털 %1 번 핀의 부저를 %3 옥타브 %2 음으로 %4 초 연주하기 %5',\r\n\t\t\t\taiot_set_noTone: '디지털 %1 번 핀의 부저 소리 끄기 %2',\r\n                aiot_set_servo: '디지털 %1 번 핀의 서보모터를 %2도 각도로 회전하기 %3',                                \r\n\t\t\t\taiot_set_neopixel_init: '디지털 %1 번 핀에 연결된 %2 개의 네오픽셀 사용하기 %3',\r\n\t\t\t\taiot_set_neopixel: '디지털 %1 번 핀에 연결된 %2 번째 네오픽셀 LED를 R: %3 , G: %4 , B: %5 색으로 켜기 %6',\r\n\t\t\t\taiot_set_dht_init: '디지털 %1 번 핀에 연결된 DHT11 온습도센서 사용하기 %2',\r\n\t\t\t\taiot_get_dht_temp_value: 'DHT11 온습도센서의 온도값',\r\n\t\t\t\taiot_get_dht_humi_value: 'DHT11 온습도센서의 습도값',\t\t\t\t\r\n\t\t\t\taiot_get_lcd_row: '%1',\r\n\t\t\t\taiot_get_lcd_col: '%1',\r\n\t\t\t\taiot_set_I2CLCD_init: 'I2C LCD 사용하기 %3',\r\n\t\t\t\taiot_set_I2CLCD_print: 'I2C LCD %1 번째 줄, %2 번째 칸에 %3 출력하기 %4',\r\n\t\t\t\taiot_set_I2CLCD_clear: 'I2C LCD 화면 모두 지우기 %3',\r\n\t\t\t\taiot_set_I2CLCD_emoticon: 'I2C LCD %1 번째 줄, %2 번째 칸에 %3 이모티콘 출력하기 %4',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                aiot_get_analog_value: 'Analog %1 Sensor value',\r\n                aiot_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\r\n                aiot_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',                \r\n                aiot_get_digital: 'Digital %1 Input value',\r\n                aiot_toggle_led: 'Digital %1 Pin %2 %3',                \r\n                aiot_digital_pwm: 'Digital %1 Pin %2 %3',                \r\n                aiot_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\r\n\t\t\t\taiot_set_noTone: 'Digital %1 No.Pin Buzzer Off %2',\r\n                aiot_set_servo: 'Set Servo Motor pin %1 angle as %2 %3',                \r\n\t\t\t\taiot_set_neopixel_init: 'Digital %1 No.Pin %2 NeonPixel Initialize %3',\r\n\t\t\t\taiot_set_neopixel: 'Digital %1 No.Pin %2  NeonPixel LED R: %3 , G: %4 , B: %5 색으로 켜기 %6',\r\n\t\t\t\taiot_set_dht_init: 'Digital %1 No. Pin DHT11 Senosr Module Initialize %2',\r\n\t\t\t\taiot_get_dht_temp_value: 'DHT11 Snesor Temp.Value',\r\n\t\t\t\taiot_get_dht_humi_value: 'DHT11 Sensor Humidity Value',\t\t\t\t\r\n\t\t\t\taiot_get_lcd_row: '%1',\r\n\t\t\t\taiot_get_lcd_col: '%1',\r\n\t\t\t\taiot_set_I2CLCD_init: 'I2C LCD Initialize %3',\r\n\t\t\t\taiot_set_I2CLCD_print: 'I2C LCD %1 Row, %2 Col %3 Print %4',\r\n\t\t\t\taiot_set_I2CLCD_clear: 'I2C LCD Screen All Clean %3',\r\n\t\t\t\taiot_set_I2CLCD_emoticon: 'I2C LCD의 %1 Row, %2 Col %3 Emoticon Print %4',\r\n            },\r\n        },\r\n    };\r\n};\r\n//region arduinoExt 아두이노 확장모드\r\nEntry.AIoT.getBlocks = function() {\r\n    return {\r\n        aiot_analog_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A0', '0'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                        ['A3', '3'],\r\n                        ['A4', '4'],\r\n                        ['A5', '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['A0', '0'],\r\n                                    ['A1', '1'],\r\n                                    ['A2', '2'],\r\n                                    ['A3', '3'],\r\n                                    ['A4', '4'],\r\n                                    ['A5', '5'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                codeMap: 'Entry.CodeMap.Arduino.aiot_analog_list[0]',\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'aiot_analog_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        aiot_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'aiot_analog_list',\r\n                    },\r\n                ],\r\n                type: 'aiot_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'AIoTGet',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                let port = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                if (port[0] === 'A') {\r\n                    port = port.substring(1);\r\n                }\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        aiot_get_analog_value_map: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'aiot_get_analog_value',\r\n                        params: [\r\n                            {\r\n                                type: 'aiot_analog_list',\r\n                            },\r\n                        ],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'aiot_get_analog_value_map',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'AIoTGet',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                let result = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                const stringValue4 = script.getValue('VALUE4', script);\r\n                const stringValue5 = script.getValue('VALUE5', script);\r\n                let isFloat = false;\r\n\r\n                if (\r\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\r\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\r\n                ) {\r\n                    isFloat = true;\r\n                }\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                if (isFloat) {\r\n                    result = Math.round(result * 100) / 100;\r\n                } else {\r\n                    result = Math.round(result);\r\n                }\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        aiot_get_ultrasonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['4'],\r\n                    },\r\n                ],\r\n                type: 'aiot_get_ultrasonic_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'AIoTGet',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                const port1 = script.getNumberValue('PORT1', script);\r\n                const port2 = script.getNumberValue('PORT2', script);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[port1];\r\n                delete Entry.hw.sendQueue.SET[port2];\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.AIoT.sensorTypes.ULTRASONIC] = {\r\n                    port: [port1, port2],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.ULTRASONIC || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        aiot_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [2],\r\n                    },\r\n                ],\r\n                type: 'aiot_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'AIoTGet',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                const { hwModule = {} } = Entry.hw;\r\n                const { name } = hwModule;\r\n                if (name === 'AIoT' || name === 'ArduinoNano') {\r\n                    const port = script.getNumberValue('PORT', script);\r\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                    if (!Entry.hw.sendQueue.GET) {\r\n                        Entry.hw.sendQueue.GET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.GET[Entry.AIoT.sensorTypes.DIGITAL] = {\r\n                        port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n                } else {\r\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        arduino_get_digital_toggle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OPERATOR: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('OPERATOR');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\r\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 11,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_digital_toggle[0]',\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'arduino_get_digital_toggle',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n      \r\n        aiot_toggle_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_digital_toggle',\r\n                        params: ['on'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_toggle_led',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'AIoT',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.AIoT.highList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else if (Entry.AIoT.lowList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.AIoT.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        aiot_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_pwm_port_number',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_digital_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'AIoT',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.AIoT.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        aiot_tone_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.silent, '0'],\r\n                                    [Lang.Blocks.do_name, 'C'],\r\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\r\n                                    [Lang.Blocks.re_name, 'D'],\r\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\r\n                                    [Lang.Blocks.mi_name, 'E'],\r\n                                    [Lang.Blocks.fa_name, 'F'],\r\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                                    [Lang.Blocks.sol_name, 'G'],\r\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                                    [Lang.Blocks.la_name, 'A'],\r\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\r\n                                    [Lang.Blocks.si_name, 'B'],\r\n                                ],\r\n                                value: 'C',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'aiot_tone_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        aiot_octave_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'aiot_octave_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        aiot_tone_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'aiot_tone_list',\r\n                    },\r\n                ],\r\n                type: 'aiot_tone_value',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getNumberValue('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'aiot_tone_value',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        \r\n        aiot_set_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'aiot_tone_list',\r\n                    },\r\n                    {\r\n                        type: 'aiot_octave_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_set_tone',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NOTE: 1,\r\n                OCTAVE: 2,\r\n                DURATION: 3,\r\n            },\r\n            class: 'AIoT',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n\r\n                if (!script.isStart) {\r\n                    let note = script.getValue('NOTE', script);\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.AIoT.toneTable[note];\r\n                    }\r\n\r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    } else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n\r\n                    let duration = script.getNumberValue('DURATION', script);\r\n\r\n                    if (duration < 0) {\r\n                        duration = 0;\r\n                    }\r\n\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n\r\n                    if (duration === 0) {\r\n                        sq.SET[port] = {\r\n                            type: Entry.AIoT.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n\r\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    } else if (octave > 5) {\r\n                        octave = 5;\r\n                    }\r\n\r\n                    let value = 0;\r\n\r\n                    if (note != 0) {\r\n                        value = Entry.AIoT.toneMap[note][octave];\r\n                    }\r\n\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    sq.SET[port] = {\r\n                        type: Entry.AIoT.sensorTypes.TONE,\r\n                        data: {\r\n                            value,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    sq.SET[port] = {\r\n                        type: Entry.AIoT.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n\t\taiot_set_noTone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n\t\t\tdef: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_set_noTone',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'AIoT',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                var sq = Entry.hw.sendQueue;\r\n                var port = script.getNumberValue('PORT', script);\r\n\r\n\t\t\t\tif (!script.isStart) \r\n                {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar duration = Entry.AIoT.duration.TIME_100ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\t\t\t\t\t\r\n\t\t\t\t\tsq.SET[port] = {\r\n\t\t\t\t\t\t\ttype: Entry.AIoT.sensorTypes.NO_TONE,\r\n\t\t\t\t\t\t\tdata: port,\r\n\t\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script;\r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else \r\n                {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n\t\t\t\t\t\t\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\t\t        \r\n        aiot_set_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_set_servo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'AIoT',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                let value = script.getNumberValue('VALUE', script);\r\n                value = Math.min(180, value);\r\n                value = Math.max(0, value);\r\n\r\n                if (!sq.SET) {\r\n                    sq.SET = {};\r\n                }\r\n                sq.SET[port] = {\r\n                    type: Entry.AIoT.sensorTypes.SERVO_PIN,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\t\t\r\n\t\t        \r\n\t\taiot_set_neopixel_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n\t\t\tdef: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['6'],\r\n                    },\r\n\t\t\t\t\t{\r\n                        type: 'number',\r\n                        params: ['25'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_set_neopixel_init',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NUM: 1,\r\n            },\r\n            class: 'other',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                var sq = Entry.hw.sendQueue;\r\n                var port = script.getNumberValue('PORT', script);\r\n                var value = script.getNumberValue('NUM', script);\r\n\r\n\t\t\t\tif (!script.isStart)\r\n                {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar duration = Entry.AIoT.duration.TIME_200ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1; \r\n\t\t\t\t\t\r\n\t\t\t\t\tsq.SET[port] = {\r\n\t\t\t\t\t\t\ttype: Entry.AIoT.sensorTypes.NEOPIXEL_INIT,\r\n\t\t\t\t\t\t\tdata: value,\r\n\t\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script;\r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1) \r\n                {\r\n                    return script;\r\n                } \r\n                else \r\n                {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                } \r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n\t\t\t\t\t\t\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n\t\taiot_set_neopixel: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n\t\t\tdef: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['6'],\r\n                    },\r\n\t\t\t\t\t{\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n\t\t\t\t\t{\r\n                        type: 'number',\r\n                        params: ['255'],\r\n                    },\r\n\t\t\t\t\t{\r\n                        type: 'number',\r\n                        params: ['255'],\r\n                    },\r\n\t\t\t\t\t{\r\n                        type: 'number',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_set_neopixel',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NUM: 1,\r\n\t\t\t\tRED: 2,\r\n\t\t\t\tGREEN: 3,\r\n\t\t\t\tBLUE: 4,\r\n            },\r\n            class: 'other',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                var sq = Entry.hw.sendQueue;\r\n                var port = script.getNumberValue('PORT', script);\r\n                var num = script.getNumberValue('NUM', script);\r\n\t\t\t\tvar r = script.getNumberValue('RED', script);\r\n\t\t\t\tvar g = script.getNumberValue('GREEN', script);\r\n\t\t\t\tvar b = script.getNumberValue('BLUE', script);\r\n\r\n\t\t\t\tif (!script.isStart) \r\n                {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar duration = Entry.AIoT.duration.TIME_10ms;\r\n\t\t\t\t\t\tscript.isStart = true;\r\n\t\t\t\t\t\tscript.timeFlag = 1;\r\n\t\t\t\t\t\r\n\t\t\t\t\tsq.SET[num] = {\r\n\t\t\t\t\t\ttype: Entry.AIoT.sensorTypes.NEOPIXEL_COLOR,\r\n\t\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t\t\tport: port,\r\n\t\t\t\t\t\t\t\tnum: num,\r\n\t\t\t\t\t\t\t\tr: r,\r\n\t\t\t\t\t\t\t\tg: g,\r\n\t\t\t\t\t\t\t\tb: b,\r\n\t\t\t\t\t\t\t  },\r\n\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script; \r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1) \r\n                {\r\n                    return script;\r\n                } \r\n                else \r\n                {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n\t\taiot_set_dht_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n\t\t\tdef: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_set_dht_init',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'dht',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                var sq = Entry.hw.sendQueue;\r\n                var port = script.getNumberValue('PORT', script);\r\n\r\n\t\t\t\tif (!script.isStart) \r\n                {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar duration = Entry.AIoT.duration.TIME_500ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\t\t\t\t\t\r\n\t\t\t\t\tsq.SET[port] = {\r\n\t\t\t\t\t\t\ttype: Entry.AIoT.sensorTypes.DHT_INIT,\r\n\t\t\t\t\t\t\tdata: port,\r\n\t\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script;\r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else \r\n                {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n\t\t\t\t\t\t\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n\t\taiot_get_dht_temp_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n\t\t\t\t\t'0',\r\n                ],\r\n                type: 'aiot_get_dht_temp_value',\r\n            },\r\n            paramsKeyMap: {\r\n                TEMP: 0,\r\n            },\r\n            class: 'dht',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                const temp = script.getNumberValue('TEMP', script);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[temp];\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n\t\t\t\t\r\n                Entry.hw.sendQueue.GET[Entry.AIoT.sensorTypes.DHT_TEMP] = {\r\n                    port: temp,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.DHT_TEMP || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                       \r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\t\t\r\n\t\taiot_get_dht_humi_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n\t\t\t\t\t'1',\r\n                ],\r\n                type: 'aiot_get_dht_humi_value',\r\n            },\r\n            paramsKeyMap: {\r\n                HUMI: 0,\r\n            },\r\n            class: 'dht',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                const humi = script.getNumberValue('HUMI', script);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[humi];\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n\t\t\t\t\r\n                Entry.hw.sendQueue.GET[Entry.AIoT.sensorTypes.DHT_HUMI] = {\r\n                    port: humi,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.DHT_HUMI || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                       \r\n                    },\r\n                ],\r\n            },\r\n        },\t\t\r\n        \r\n\t\taiot_get_lcd_row: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                ROW: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('ROW');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['0', '0'],\r\n                                    ['1', '1'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'aiot_get_lcd_row',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\t\t\r\n\t\taiot_get_lcd_col: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n\t\t\t\t\t\t['2', '2'],\r\n                        ['3', '3'],\r\n\t\t\t\t\t\t['4', '4'],\r\n                        ['5', '5'],\r\n\t\t\t\t\t\t['6', '6'],\r\n                        ['7', '7'],\r\n\t\t\t\t\t\t['8', '8'],\r\n                        ['9', '9'],\r\n\t\t\t\t\t\t['10', '10'],\r\n                        ['11', '11'],\r\n\t\t\t\t\t\t['12', '12'],\r\n                        ['13', '13'],\r\n\t\t\t\t\t\t['14', '14'],\r\n                        ['15', '15'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                ROW: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('ROW');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['0', '0'],\r\n\t\t\t\t\t\t\t\t\t['1', '1'],\r\n\t\t\t\t\t\t\t\t\t['2', '2'],\r\n\t\t\t\t\t\t\t\t\t['3', '3'],\r\n\t\t\t\t\t\t\t\t\t['4', '4'],\r\n\t\t\t\t\t\t\t\t\t['5', '5'],\r\n\t\t\t\t\t\t\t\t\t['6', '6'],\r\n\t\t\t\t\t\t\t\t\t['7', '7'],\r\n\t\t\t\t\t\t\t\t\t['8', '8'],\r\n\t\t\t\t\t\t\t\t\t['9', '9'],\r\n\t\t\t\t\t\t\t\t\t['10', '10'],\r\n\t\t\t\t\t\t\t\t\t['11', '11'],\r\n\t\t\t\t\t\t\t\t\t['12', '12'],\r\n\t\t\t\t\t\t\t\t\t['13', '13'],\r\n\t\t\t\t\t\t\t\t\t['14', '14'],\r\n\t\t\t\t\t\t\t\t\t['15', '15'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'aiot_get_lcd_col',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\t\t\r\n\t\taiot_set_I2CLCD_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n\t\t\tdef: {\r\n                params: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'number',\r\n\t\t\t\t\t\tparams: ['14'],\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'number',\r\n\t\t\t\t\t\tparams: ['1'],\r\n\t\t\t\t\t},\r\n\t\t\t\t\tnull,\r\n                ],\r\n                type: 'aiot_set_I2CLCD_init',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tPORT: 0,\r\n\t\t\t\tPORT1: 1,\r\n            },\r\n            class: 'LCD',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                var sq = Entry.hw.sendQueue;\r\n                var port = script.getNumberValue('PORT', script);\r\n\t\t\t\tvar port1 = script.getNumberValue('PORT1', script);\r\n\r\n\t\t\t\tif (!script.isStart) \r\n                {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar duration = Entry.AIoT.duration.TIME_200ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\t\t\t\t\t\r\n\t\t\t\t\tsq.SET[port] = {\r\n\t\t\t\t\t\t\ttype: Entry.AIoT.sensorTypes.LCD_INIT,\r\n\t\t\t\t\t\t\tdata: port1,\r\n\t\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script;\r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else \r\n                {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n\t\t\t\t\t\t\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\t\t\r\n\t\taiot_set_I2CLCD_print: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n\t\t\tdef: {\r\n                params: [\r\n\t\t\t\t\t{\r\n                        type: 'aiot_get_lcd_row',\r\n\t\t\t\t\t\tparams: ['0'],\r\n\r\n                    },\r\n\t\t\t\t\t{\r\n                        type: 'aiot_get_lcd_col',\r\n                        params: ['0'],\r\n                    },\r\n\t\t\t\t\t{\r\n                        type: 'text',\r\n                        params: ['Wonn'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'aiot_set_I2CLCD_print',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tROW: 0,\r\n\t\t\t\tCOL: 1,\r\n\t\t\t\tSTRING: 2,\r\n            },\r\n            class: 'LCD',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                var sq = Entry.hw.sendQueue;\r\n                var port = script.getNumberValue('ROW', script);\r\n\t\t\t\tvar col = script.getNumberValue('COL', script);\r\n\t\t\t\tvar string = script.getValue('STRING', script);\r\n\t\t\t\tvar text = [];\r\n\r\n\t\t\t\tif (!script.isStart) \r\n                {\r\n\t\t\t\t\tif (typeof string === 'string') \r\n                    {\r\n                        for (var i = 0; i < string.length; i++) {\r\n                            text[i] = Entry.AIoT.toByte(string[i]);\r\n                        }\r\n                    }\r\n                    else if (typeof string === 'number') \r\n                    {\r\n                        //console.log(\"string\");\r\n                        //console.log(string);\r\n                        var num_to_string = string.toString();\r\n                        for (var i = 0; i < num_to_string.length; i++) {\r\n                            text[i] = Entry.AIoT.toByte(num_to_string[i]);\r\n                        }\r\n                        //console.log(\"num_to_string\");\r\n                        //console.log(num_to_string);\r\n                        //text[0] = 1;\r\n                        //text[1] = string / 1;\r\n                    } \r\n                    else \r\n                    {\r\n                        text[0] = string;\r\n                    }\r\n\t\t\t\t\t\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar duration = Entry.AIoT.duration.TIME_500ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\t\t\t\t\t\r\n\t\t\t\t\tsq.SET['15'] = {\r\n\t\t\t\t\t\t\ttype: Entry.AIoT.sensorTypes.LCD,\r\n\t\t\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t\t\trow: port,\r\n\t\t\t\t\t\t\t\tcol: col,\r\n\t\t\t\t\t\t\t\ttext0: text[0],\r\n\t\t\t\t\t\t\t\ttext1: text[1],\r\n\t\t\t\t\t\t\t\ttext2: text[2],\r\n\t\t\t\t\t\t\t\ttext3: text[3],\r\n\t\t\t\t\t\t\t\ttext4: text[4],\r\n\t\t\t\t\t\t\t\ttext5: text[5],\r\n\t\t\t\t\t\t\t\ttext6: text[6],\r\n\t\t\t\t\t\t\t\ttext7: text[7],\r\n\t\t\t\t\t\t\t\ttext8: text[8],\r\n\t\t\t\t\t\t\t\ttext9: text[9],\r\n\t\t\t\t\t\t\t\ttext10: text[10],\r\n\t\t\t\t\t\t\t\ttext11: text[11],\r\n\t\t\t\t\t\t\t\ttext12: text[12],\r\n\t\t\t\t\t\t\t\ttext13: text[13],\r\n\t\t\t\t\t\t\t\ttext14: text[14],\r\n\t\t\t\t\t\t\t\ttext15: text[15],\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script;\r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else \r\n                {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n\t\t\t\t\t\t\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\t\t\r\n\t\taiot_set_I2CLCD_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n\t\t\tdef: {\r\n                params: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'number',\r\n\t\t\t\t\t\tparams: ['15'],\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'number',\r\n\t\t\t\t\t\tparams: ['1'],\r\n\t\t\t\t\t},\r\n\t\t\t\t\tnull,\r\n                ],\r\n                type: 'aiot_set_I2CLCD_clear',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tPORT: 0,\r\n\t\t\t\tPORT1: 1,\r\n            },\r\n            class: 'LCD',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                var sq = Entry.hw.sendQueue;\r\n                var port = script.getNumberValue('PORT', script);\r\n\t\t\t\tvar port1 = script.getNumberValue('PORT1', script);\r\n\r\n\t\t\t\tif (!script.isStart) \r\n                {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar duration = Entry.AIoT.duration.TIME_200ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\t\t\t\t\t\r\n\t\t\t\t\tsq.SET[port] = {\r\n\t\t\t\t\t\t\ttype: Entry.AIoT.sensorTypes.LCD_CLEAR,\r\n\t\t\t\t\t\t\tdata: port1,\r\n\t\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script;\r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else \r\n                {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n\t\t\t\t\t\t\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\t\t\r\n\t\taiot_set_I2CLCD_emoticon: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n\t\t\t\t{\r\n                    type: \"Dropdown\",\r\n\t\t\t\t\toptions: [\r\n\t\t\t\t\t\t[ \"온도\", '1' ],\r\n\t\t\t\t\t\t[ \"습도\", '2' ],\r\n\t\t\t\t\t],\r\n\t\t\t\t\tfontSize: 11,\r\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t\t\t},\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n\t\t\tdef: {\r\n                params: [\r\n\t\t\t\t\t{\r\n                        type: 'aiot_get_lcd_row',\r\n\t\t\t\t\t\tparams: ['0'],\r\n\r\n                    },\r\n\t\t\t\t\t{\r\n                        type: 'aiot_get_lcd_col',\r\n                        params: ['0'],\r\n                    },\r\n\t\t\t\t\t'1',\r\n                    null,\r\n                ],\r\n                type: 'aiot_set_I2CLCD_emoticon',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tROW: 0,\r\n\t\t\t\tCOL: 1,\r\n\t\t\t\tEMOTICON: 2,\r\n            },\r\n            class: 'LCD',\r\n            isNotFor: ['AIoT'],\r\n            func(sprite, script) {\r\n                var sq = Entry.hw.sendQueue;\r\n                var row = script.getNumberValue('ROW', script);\r\n\t\t\t\tvar col = script.getNumberValue('COL', script);\r\n\t\t\t\tvar emoticon = script.getValue('EMOTICON', script);\r\n\r\n\t\t\t\tif (!script.isStart) \r\n                {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\t\r\n\t\t\t\t\tvar duration = Entry.AIoT.duration.TIME_200ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\t\t\t\t\t\r\n\t\t\t\t\tsq.SET['15'] = {\r\n\t\t\t\t\t\t\ttype: Entry.AIoT.sensorTypes.LCD_EMOTICON,\r\n\t\t\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t\t\trow: row,\r\n\t\t\t\t\t\t\t\tcol: col,\r\n\t\t\t\t\t\t\t\temoticon: emoticon,\r\n\t\t\t\t\t\t\t},\r\n\t\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script;\r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else \r\n                {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n\t\t\t\t\t\t\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n    };\r\n};\r\n//endregion arduinoExt 아두이노 확장모드\r\n\r\nmodule.exports = Entry.AIoT;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_aiservo.js",
    "content": "'use strict';\r\n\r\n/***************************************************************************************\r\n * AI 로봇집게 플레이그라운드 블록 정의 (사양 업데이트)\r\n * - 수정 사항:\r\n * 1. 관절(좌우): 왼쪽(180), 가운데(90), 오른쪽(0)\r\n * 2. 관절(상하): 위(0), 가운데(90), 아래(180)\r\n * 3. 관절(집게): 열기(0), 가운데(90), 닫기(180)\r\n * 4. 관절(버켓): 담기(0), 가운데(90), 붓기(180) - 바스켓에서 버켓으로 명칭 변경\r\n ***************************************************************************************/\r\n\r\nif (typeof global.Entry !== 'object') {\r\n    global.Entry = {};\r\n}\r\n\r\nEntry.aiservo = {\r\n    id: '41.3',\r\n    name: 'aiservo',\r\n    isNotFor: [],\r\n    url: 'http://neo3ds.com',\r\n    imageName: 'aiservo.png',\r\n    title: { ko: 'AI로봇집게', en: 'AIROBOTARM' },\r\n    poses: {},\r\n    setZero: function() {\r\n        if (!Entry.hw.sendQueue) Entry.hw.sendQueue = {};\r\n        var resetValues = {\r\n            MODE: 1,\r\n            SERVO1: 90,\r\n            SERVO2: 90,\r\n            SERVO3: 90,\r\n            PIXEL_IDX: 2,\r\n            RED: 0,\r\n            GREEN: 0,\r\n            BLUE: 0,\r\n            BUZZER: 0,\r\n            BLUE_LED: 0,\r\n        };\r\n        Object.keys(resetValues).forEach(function(key) {\r\n            Entry.hw.sendQueue[key] = resetValues[key];\r\n        });\r\n        Entry.hw.update();\r\n    },\r\n};\r\n\r\nEntry.aiservo.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                aiservo_get_sensor_value: '%1 값',\r\n                aiservo_get_cds_value: '밝기센서(CDS) %1 값',\r\n                aiservo_set_servo: '%1 각도를 %2 도로 이동 %3',\r\n                aiservo_set_servo_lr: '관절(좌우)를 %1 (으)로 이동 %2',\r\n                aiservo_set_servo_ud: '관절(상하)를 %1 (으)로 이동 %2',\r\n                aiservo_set_gripper: '집게를 %1 %2',\r\n                aiservo_set_basket: '버켓을 %1 %2', // 바스켓 -> 버켓\r\n                aiservo_save_pose: '현재 포즈를 %1 번에 저장하기 %2',\r\n                aiservo_load_pose: '%1 번 포즈로 이동하기 %2',\r\n                aiservo_set_led_color: '네오픽셀 %1 색상을 %2 (으)로 켜기 %3',\r\n                aiservo_set_led_rgb: '네오픽셀 %1 색상을 R:%2 G:%3 B:%4 (으)로 켜기 %5',\r\n                aiservo_set_led_off: '네오픽셀 전체 끄기 %1',\r\n                aiservo_set_blue_led_onoff: '파란 LED(D6) %1 %2',\r\n                aiservo_set_blue_led_pwm: '파란 LED(D6) 밝기를 %1 (으)로 설정 %2',\r\n                aiservo_set_buzzer: '버저 %1 옥타브 %2 음을 %3 초 동안 연주 %4',\r\n            },\r\n            Blocks: {\r\n                aiservo_pot1: '조종기(왼쪽)',\r\n                aiservo_pot2: '조종기(가운데)',\r\n                aiservo_pot3: '조종기(오른쪽)',\r\n                aiservo_cds1: '1번',\r\n                aiservo_cds2: '2번',\r\n                aiservo_joint_1: '관절(상하)',\r\n                aiservo_joint_2: '관절(좌우)',\r\n                aiservo_joint_3: '관절(집게)',\r\n                aiservo_joint_4: '관절(버켓)', // 바스켓 -> 버켓\r\n                aiservo_left: '왼쪽',\r\n                aiservo_right: '오른쪽',\r\n                aiservo_up: '위',\r\n                aiservo_down: '아래',\r\n                aiservo_middle: '가운데',\r\n                aiservo_open: '열기',\r\n                aiservo_close: '닫기',\r\n                aiservo_pour: '붓기',\r\n                aiservo_release: '담기',\r\n                aiservo_on: '켜기',\r\n                aiservo_off: '끄기',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.aiservo.blockMenuBlocks = [\r\n    'aiservo_get_sensor_value',\r\n    'aiservo_get_cds_value',\r\n    'aiservo_set_servo',\r\n    'aiservo_set_servo_lr',\r\n    'aiservo_set_servo_ud',\r\n    'aiservo_set_gripper',\r\n    'aiservo_set_basket',\r\n    'aiservo_save_pose',\r\n    'aiservo_load_pose',\r\n    'aiservo_set_led_color',\r\n    'aiservo_set_led_rgb',\r\n    'aiservo_set_led_off',\r\n    'aiservo_set_blue_led_onoff',\r\n    'aiservo_set_blue_led_pwm',\r\n    'aiservo_set_buzzer',\r\n];\r\n\r\nEntry.aiservo.getBlocks = function() {\r\n    var hwrColor = '#15b59f';\r\n    var hwrDarken = '#129a88';\r\n\r\n    return {\r\n        aiservo_get_sensor_value: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic_string_field',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.aiservo_pot1, 'POT1'],\r\n                        [Lang.Blocks.aiservo_pot2, 'POT2'],\r\n                        [Lang.Blocks.aiservo_pot3, 'POT3'],\r\n                    ],\r\n                    value: 'POT1',\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n            ],\r\n            def: { params: [null], type: 'aiservo_get_sensor_value' },\r\n            paramsKeyMap: { SIGNAL: 0 },\r\n            class: 'aiservo_sensor',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                return Entry.hw.portData[script.getField('SIGNAL', script)] || 0;\r\n            },\r\n        },\r\n        aiservo_get_cds_value: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic_string_field',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.aiservo_cds1, 'CDS1'],\r\n                        [Lang.Blocks.aiservo_cds2, 'CDS2'],\r\n                    ],\r\n                    value: 'CDS1',\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n            ],\r\n            def: { params: [null], type: 'aiservo_get_cds_value' },\r\n            paramsKeyMap: { SIGNAL: 0 },\r\n            class: 'aiservo_sensor',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                var val = Entry.hw.portData[script.getField('SIGNAL', script)] || 0;\r\n                var result = (255 - val) * 4 - 400;\r\n                return Math.min(1023, result);\r\n            },\r\n        },\r\n        aiservo_set_servo: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.aiservo_joint_1, 'SERVO1'],\r\n                        [Lang.Blocks.aiservo_joint_2, 'SERVO2'],\r\n                        [Lang.Blocks.aiservo_joint_3, 'SERVO3'],\r\n                        [Lang.Blocks.aiservo_joint_4, 'SERVO3'],\r\n                    ],\r\n                    value: 'SERVO1',\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n                { type: 'Block', accept: 'string' },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: {\r\n                params: [null, { type: 'number', params: ['90'] }, null],\r\n                type: 'aiservo_set_servo',\r\n            },\r\n            paramsKeyMap: { PORT: 0, VALUE: 1 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                var port = script.getField('PORT', script);\r\n                var val = Math.max(0, Math.min(180, script.getNumberValue('VALUE', script)));\r\n                Entry.hw.sendQueue[port] = val;\r\n                Entry.hw.sendQueue['MODE'] = 1;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_servo_lr: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.aiservo_left, 180], // 왼쪽: 180\r\n                        [Lang.Blocks.aiservo_middle, 90],\r\n                        [Lang.Blocks.aiservo_right, 0], // 오른쪽: 0\r\n                    ],\r\n                    value: 90,\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: { params: [null, null], type: 'aiservo_set_servo_lr' },\r\n            paramsKeyMap: { VALUE: 0 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                Entry.hw.sendQueue['SERVO2'] = script.getField('VALUE', script);\r\n                Entry.hw.sendQueue['MODE'] = 1;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_servo_ud: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.aiservo_up, 0], // 위: 0\r\n                        [Lang.Blocks.aiservo_middle, 90],\r\n                        [Lang.Blocks.aiservo_down, 180], // 아래: 180\r\n                    ],\r\n                    value: 90,\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: { params: [null, null], type: 'aiservo_set_servo_ud' },\r\n            paramsKeyMap: { VALUE: 0 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                Entry.hw.sendQueue['SERVO1'] = script.getField('VALUE', script);\r\n                Entry.hw.sendQueue['MODE'] = 1;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_gripper: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.aiservo_open, 0], // 열기: 0\r\n                        [Lang.Blocks.aiservo_middle, 90],\r\n                        [Lang.Blocks.aiservo_close, 180], // 닫기: 180\r\n                    ],\r\n                    value: 90,\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: { params: [null, null], type: 'aiservo_set_gripper' },\r\n            paramsKeyMap: { VALUE: 0 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                Entry.hw.sendQueue['SERVO3'] = script.getField('VALUE', script);\r\n                Entry.hw.sendQueue['MODE'] = 1;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_basket: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.aiservo_release, 0], // 담기: 0\r\n                        [Lang.Blocks.aiservo_middle, 90],\r\n                        [Lang.Blocks.aiservo_pour, 180], // 붓기: 180\r\n                    ],\r\n                    value: 90,\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: { params: [null, null], type: 'aiservo_set_basket' },\r\n            paramsKeyMap: { VALUE: 0 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                Entry.hw.sendQueue['SERVO3'] = script.getField('VALUE', script);\r\n                Entry.hw.sendQueue['MODE'] = 1;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_save_pose: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                { type: 'Block', accept: 'string' },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: { params: [{ type: 'number', params: ['1'] }, null], type: 'aiservo_save_pose' },\r\n            paramsKeyMap: { ID: 0 },\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                var id = script.getNumberValue('ID', script);\r\n                Entry.aiservo.poses[id] = {\r\n                    s1: Entry.hw.sendQueue['SERVO1'] || 90,\r\n                    s2: Entry.hw.sendQueue['SERVO2'] || 90,\r\n                    s3: Entry.hw.sendQueue['SERVO3'] || 90,\r\n                };\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_load_pose: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                { type: 'Block', accept: 'string' },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: { params: [{ type: 'number', params: ['1'] }, null], type: 'aiservo_load_pose' },\r\n            paramsKeyMap: { ID: 0 },\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                var id = script.getNumberValue('ID', script);\r\n                var pose = Entry.aiservo.poses[id];\r\n                if (pose) {\r\n                    Entry.hw.sendQueue['SERVO1'] = pose.s1;\r\n                    Entry.hw.sendQueue['SERVO2'] = pose.s2;\r\n                    Entry.hw.sendQueue['SERVO3'] = pose.s3;\r\n                    Entry.hw.sendQueue['MODE'] = 1;\r\n                }\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_led_color: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1번', 0],\r\n                        ['2번', 1],\r\n                        ['모두', 2],\r\n                    ],\r\n                    value: 2,\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n                { type: 'Color' },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: { params: [null, '#ff0000', null], type: 'aiservo_set_led_color' },\r\n            paramsKeyMap: { INDEX: 0, COLOR: 1 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.startTime = Date.now();\r\n                    var color = script.getField('COLOR', script);\r\n                    Entry.hw.sendQueue['PIXEL_IDX'] = script.getField('INDEX', script);\r\n                    if (color && color.length >= 7) {\r\n                        Entry.hw.sendQueue['RED'] = parseInt(color.substr(1, 2), 16);\r\n                        Entry.hw.sendQueue['GREEN'] = parseInt(color.substr(3, 2), 16);\r\n                        Entry.hw.sendQueue['BLUE'] = parseInt(color.substr(5, 2), 16);\r\n                    }\r\n                    Entry.hw.sendQueue['MODE'] = 1;\r\n                    return script;\r\n                }\r\n                if (Date.now() - script.startTime < 30) return script;\r\n                delete script.isStart;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_led_rgb: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1번', 0],\r\n                        ['2번', 1],\r\n                        ['모두', 2],\r\n                    ],\r\n                    value: 2,\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n                { type: 'Block', accept: 'string' },\r\n                { type: 'Block', accept: 'string' },\r\n                { type: 'Block', accept: 'string' },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    { type: 'number', params: ['255'] },\r\n                    { type: 'number', params: ['0'] },\r\n                    { type: 'number', params: ['0'] },\r\n                    null,\r\n                ],\r\n                type: 'aiservo_set_led_rgb',\r\n            },\r\n            paramsKeyMap: { INDEX: 0, R: 1, G: 2, B: 3 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.startTime = Date.now();\r\n                    Entry.hw.sendQueue['PIXEL_IDX'] = script.getField('INDEX', script);\r\n                    Entry.hw.sendQueue['RED'] = Math.max(\r\n                        0,\r\n                        Math.min(255, script.getNumberValue('R', script))\r\n                    );\r\n                    Entry.hw.sendQueue['GREEN'] = Math.max(\r\n                        0,\r\n                        Math.min(255, script.getNumberValue('G', script))\r\n                    );\r\n                    Entry.hw.sendQueue['BLUE'] = Math.max(\r\n                        0,\r\n                        Math.min(255, script.getNumberValue('B', script))\r\n                    );\r\n                    Entry.hw.sendQueue['MODE'] = 1;\r\n                    return script;\r\n                }\r\n                if (Date.now() - script.startTime < 30) return script;\r\n                delete script.isStart;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_led_off: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\r\n            def: { params: [null], type: 'aiservo_set_led_off' },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                Entry.hw.sendQueue['PIXEL_IDX'] = 2;\r\n                Entry.hw.sendQueue['RED'] = 0;\r\n                Entry.hw.sendQueue['GREEN'] = 0;\r\n                Entry.hw.sendQueue['BLUE'] = 0;\r\n                Entry.hw.sendQueue['MODE'] = 1;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_blue_led_onoff: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.aiservo_on, 255],\r\n                        [Lang.Blocks.aiservo_off, 0],\r\n                    ],\r\n                    value: 255,\r\n                    fontSize: 11,\r\n                    bgColor: hwrDarken,\r\n                    arrowColor: hwrColor,\r\n                },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: { params: [null, null], type: 'aiservo_set_blue_led_onoff' },\r\n            paramsKeyMap: { VALUE: 0 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                Entry.hw.sendQueue['BLUE_LED'] = script.getField('VALUE', script);\r\n                Entry.hw.sendQueue['MODE'] = 1;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_blue_led_pwm: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                { type: 'Block', accept: 'string' },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: {\r\n                params: [{ type: 'number', params: ['255'] }, null],\r\n                type: 'aiservo_set_blue_led_pwm',\r\n            },\r\n            paramsKeyMap: { VALUE: 0 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                Entry.hw.sendQueue['BLUE_LED'] = Math.max(\r\n                    0,\r\n                    Math.min(255, script.getNumberValue('VALUE', script))\r\n                );\r\n                Entry.hw.sendQueue['MODE'] = 1;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        aiservo_set_buzzer: {\r\n            color: hwrColor,\r\n            outerLine: hwrDarken,\r\n            skeleton: 'basic',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                    ],\r\n                    value: '4',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['도', '33'],\r\n                        ['레', '37'],\r\n                        ['미', '41'],\r\n                        ['파', '44'],\r\n                        ['솔', '49'],\r\n                        ['라', '55'],\r\n                        ['시', '62'],\r\n                    ],\r\n                    value: '33',\r\n                },\r\n                { type: 'Block', accept: 'string' },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            def: {\r\n                params: [null, null, { type: 'number', params: ['0.1'] }, null],\r\n                type: 'aiservo_set_buzzer',\r\n            },\r\n            paramsKeyMap: { OCTAVE: 0, NOTE: 1, DURATION: 2 },\r\n            class: 'aiservo_control',\r\n            isNotFor: ['aiservo'],\r\n            func: function(sprite, script) {\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.startTime = Date.now();\r\n                    var note = Math.round(\r\n                        Number(script.getField('NOTE', script)) *\r\n                            Math.pow(2, Number(script.getField('OCTAVE', script)) - 4)\r\n                    );\r\n                    Entry.hw.sendQueue['BUZZER'] = note;\r\n                    Entry.hw.sendQueue['MODE'] = 1;\r\n                    Entry.hw.update();\r\n                    return script;\r\n                }\r\n                if (\r\n                    Date.now() - script.startTime <\r\n                    script.getNumberValue('DURATION', script) * 1000\r\n                )\r\n                    return script;\r\n                Entry.hw.sendQueue['BUZZER'] = 0;\r\n                Entry.hw.update();\r\n                delete script.isStart;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.aiservo;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_albert.js",
    "content": "'use strict';\n\nfunction AlbertSchoolController() {\n    this.prevDirection = 0;\n    this.prevDirectionFinal = 0;\n    this.directionCount = 0;\n    this.directionCountFinal = 0;\n    this.positionCount = 0;\n    this.positionCountFinal = 0;\n    this.isBackward = false;\n}\n\nAlbertSchoolController.prototype.PI = 3.14159265;\nAlbertSchoolController.prototype.PI2 = 6.2831853;\nAlbertSchoolController.prototype.GAIN_ANGLE = 30;\nAlbertSchoolController.prototype.GAIN_ANGLE_FINE = 30;\nAlbertSchoolController.prototype.GAIN_POSITION_FINE = 30;\nAlbertSchoolController.prototype.STRAIGHT_SPEED = 30;\nAlbertSchoolController.prototype.MAX_BASE_SPEED = 30;\nAlbertSchoolController.prototype.GAIN_BASE_SPEED = 1.5;\nAlbertSchoolController.prototype.GAIN_POSITION = 52.5;\nAlbertSchoolController.prototype.POSITION_TOLERANCE_FINE = 3;\nAlbertSchoolController.prototype.POSITION_TOLERANCE_FINE_LARGE = 5;\nAlbertSchoolController.prototype.POSITION_TOLERANCE_ROUGH = 5;\nAlbertSchoolController.prototype.POSITION_TOLERANCE_ROUGH_LARGE = 10;\nAlbertSchoolController.prototype.ORIENTATION_TOLERANCE_FINAL = 0.087;\nAlbertSchoolController.prototype.ORIENTATION_TOLERANCE_FINAL_LARGE = 0.122;\nAlbertSchoolController.prototype.ORIENTATION_TOLERANCE_FINAL_LARGE_LARGE = 0.262;\nAlbertSchoolController.prototype.ORIENTATION_TOLERANCE_ROUGH = 0.122;\nAlbertSchoolController.prototype.ORIENTATION_TOLERANCE_ROUGH_LARGE = 0.262;\nAlbertSchoolController.prototype.ORIENTATION_TOLERANCE_ROUGH_LARGE_LARGE = 0.524;\nAlbertSchoolController.prototype.MINIMUM_WHEEL_SPEED = 18;\nAlbertSchoolController.prototype.MINIMUM_WHEEL_SPEED_FINE = 15;\n\nAlbertSchoolController.prototype.clear = function() {\n    this.prevDirection = 0;\n    this.prevDirectionFinal = 0;\n    this.directionCount = 0;\n    this.directionCountFinal = 0;\n    this.positionCount = 0;\n    this.positionCountFinal = 0;\n};\n\nAlbertSchoolController.prototype.setBackward = function(backward) {\n    this.isBackward = backward;\n};\n\nAlbertSchoolController.prototype.controlAngleInitial = function(\n    wheels,\n    currentRadian,\n    targetRadian\n) {\n    if (this.isBackward) {\n        currentRadian += this.PI;\n    }\n    var diff = this.validateRadian(targetRadian - currentRadian);\n    var mag = Math.abs(diff);\n    if (mag < this.ORIENTATION_TOLERANCE_ROUGH) return true;\n\n    var direction = diff > 0 ? 1 : -1;\n    if (mag < this.ORIENTATION_TOLERANCE_ROUGH_LARGE && direction * this.prevDirection < 0)\n        return true;\n    this.prevDirection = direction;\n\n    var value = 0;\n    if (diff > 0) {\n        value = Math.log(1 + mag) * this.GAIN_ANGLE;\n        if (value < this.MINIMUM_WHEEL_SPEED) value = this.MINIMUM_WHEEL_SPEED;\n    } else {\n        value = -Math.log(1 + mag) * this.GAIN_ANGLE;\n        if (value > -this.MINIMUM_WHEEL_SPEED) value = -this.MINIMUM_WHEEL_SPEED;\n    }\n    value = parseInt(value);\n    wheels.left = -value;\n    wheels.right = value;\n    return false;\n};\n\nAlbertSchoolController.prototype.controlAngleFinal = function(wheels, currentRadian, targetRadian) {\n    var diff = this.validateRadian(targetRadian - currentRadian);\n    var mag = Math.abs(diff);\n    if (mag < this.ORIENTATION_TOLERANCE_FINAL) return true;\n\n    var direction = diff > 0 ? 1 : -1;\n    if (mag < this.ORIENTATION_TOLERANCE_FINAL_LARGE && direction * this.prevDirectionFinal < 0)\n        return true;\n    if (\n        mag < this.ORIENTATION_TOLERANCE_FINAL_LARGE_LARGE &&\n        direction * this.prevDirectionFinal < 0\n    ) {\n        if (++this.directionCountFinal > 3) return true;\n    }\n    this.prevDirectionFinal = direction;\n\n    var value = 0;\n    if (diff > 0) {\n        value = Math.log(1 + mag) * this.GAIN_ANGLE_FINE;\n        if (value < this.MINIMUM_WHEEL_SPEED) value = this.MINIMUM_WHEEL_SPEED;\n    } else {\n        value = -Math.log(1 + mag) * this.GAIN_ANGLE_FINE;\n        if (value > -this.MINIMUM_WHEEL_SPEED) value = -this.MINIMUM_WHEEL_SPEED;\n    }\n    value = parseInt(value);\n    wheels.left = -value;\n    wheels.right = value;\n    return false;\n};\n\nAlbertSchoolController.prototype.controlPositionFine = function(\n    wheels,\n    currentX,\n    currentY,\n    currentRadian,\n    targetX,\n    targetY\n) {\n    var targetRadian = Math.atan2(targetY - currentY, targetX - currentX);\n    if (this.isBackward) {\n        currentRadian += this.PI;\n    }\n    var diff = this.validateRadian(targetRadian - currentRadian);\n    var mag = Math.abs(diff);\n    var ex = targetX - currentX;\n    var ey = targetY - currentY;\n    var dist = Math.sqrt(ex * ex + ey * ey);\n    if (dist < this.POSITION_TOLERANCE_FINE) return true;\n    if (dist < this.POSITION_TOLERANCE_FINE_LARGE) {\n        if (++this.positionCountFinal > 5) {\n            this.positionCountFinal = 0;\n            return true;\n        }\n    }\n    var value = 0;\n    if (diff > 0) value = Math.log(1 + mag) * this.GAIN_POSITION_FINE;\n    else value = -Math.log(1 + mag) * this.GAIN_POSITION_FINE;\n    if (this.isBackward) {\n        value = -value;\n    }\n    value = parseInt(value);\n    wheels.left = this.MINIMUM_WHEEL_SPEED_FINE - value;\n    wheels.right = this.MINIMUM_WHEEL_SPEED_FINE + value;\n    if (this.isBackward) {\n        wheels.left = -wheels.left;\n        wheels.right = -wheels.right;\n    }\n    return false;\n};\n\nAlbertSchoolController.prototype.controlPosition = function(\n    wheels,\n    currentX,\n    currentY,\n    currentRadian,\n    targetX,\n    targetY\n) {\n    var targetRadian = Math.atan2(targetY - currentY, targetX - currentX);\n    if (this.isBackward) {\n        currentRadian += this.PI;\n    }\n    var diff = this.validateRadian(targetRadian - currentRadian);\n    var mag = Math.abs(diff);\n    var ex = targetX - currentX;\n    var ey = targetY - currentY;\n    var dist = Math.sqrt(ex * ex + ey * ey);\n    if (dist < this.POSITION_TOLERANCE_ROUGH) return true;\n    if (dist < this.POSITION_TOLERANCE_ROUGH_LARGE) {\n        if (++this.positionCount > 10) {\n            this.positionCount = 0;\n            return true;\n        }\n    } else {\n        this.positionCount = 0;\n    }\n    if (mag < 0.01) {\n        wheels.left = this.STRAIGHT_SPEED;\n        wheels.right = this.STRAIGHT_SPEED;\n    } else {\n        var base = (this.MINIMUM_WHEEL_SPEED + 0.5 / mag) * this.GAIN_BASE_SPEED;\n        if (base > this.MAX_BASE_SPEED) base = this.MAX_BASE_SPEED;\n\n        var value = 0;\n        if (diff > 0) value = Math.log(1 + mag) * this.GAIN_POSITION;\n        else value = -Math.log(1 + mag) * this.GAIN_POSITION;\n        if (this.isBackward) {\n            value = -value;\n        }\n        base = parseInt(base);\n        value = parseInt(value);\n        wheels.left = base - value;\n        wheels.right = base + value;\n    }\n    if (this.isBackward) {\n        wheels.left = -wheels.left;\n        wheels.right = -wheels.right;\n    }\n    return false;\n};\n\nAlbertSchoolController.prototype.validateRadian = function(radian) {\n    if (radian > this.PI) return radian - this.PI2;\n    else if (radian < -this.PI) return radian + this.PI2;\n    return radian;\n};\n\nAlbertSchoolController.prototype.toRadian = function(degree) {\n    return (degree * 3.14159265) / 180.0;\n};\n\nfunction AlbertSchoolNavigator() {\n    this.controller = new AlbertSchoolController();\n    this.mode = 0;\n    this.state = 0;\n    this.initialized = false;\n    this.boardWidth = 0;\n    this.boardHeight = 0;\n    this.currentX = -1;\n    this.currentY = -1;\n    this.currentTheta = -200;\n    this.targetX = -1;\n    this.targetY = -1;\n    this.targetTheta = -200;\n    this.wheels = { completed: false, left: 0, right: 0 };\n}\n\nAlbertSchoolNavigator.prototype.clear = function() {\n    this.mode = 0;\n    this.state = 0;\n    this.initialized = false;\n    this.currentX = -1;\n    this.currentY = -1;\n    this.currentTheta = -200;\n    this.targetX = -1;\n    this.targetY = -1;\n    this.targetTheta = -200;\n    this.wheels.completed = false;\n    this.wheels.left = 0;\n    this.wheels.right = 0;\n    this.controller.clear();\n};\n\nAlbertSchoolNavigator.prototype.getBoardWidth = function() {\n    return this.boardWidth;\n};\n\nAlbertSchoolNavigator.prototype.getBoardHeight = function() {\n    return this.boardHeight;\n};\n\nAlbertSchoolNavigator.prototype.setBoardSize = function(width, height) {\n    this.boardWidth = width;\n    this.boardHeight = height;\n};\n\nAlbertSchoolNavigator.prototype.setBackward = function(backward) {\n    this.controller.setBackward(backward);\n};\n\nAlbertSchoolNavigator.prototype.moveTo = function(x, y) {\n    this.clear();\n    this.targetX = x;\n    this.targetY = y;\n    this.state = 1;\n    this.mode = 1;\n};\n\nAlbertSchoolNavigator.prototype.turnTo = function(deg) {\n    this.clear();\n    this.targetTheta = deg;\n    this.state = 1;\n    this.mode = 2;\n};\n\nAlbertSchoolNavigator.prototype.handleSensory = function(sensory) {\n    if (this.mode == 1) {\n        var x = sensory.positionX;\n        var y = sensory.positionY;\n        if (x >= 0) this.currentX = x;\n        if (y >= 0) this.currentY = y;\n        this.currentTheta = sensory.orientation;\n        switch (this.state) {\n            case 1: {\n                if (this.initialized == false) {\n                    if (this.currentX < 0 || this.currentY < 0) {\n                        this.wheels.left = 20;\n                        this.wheels.right = -20;\n                    } else {\n                        this.initialized = true;\n                    }\n                }\n                if (this.initialized) {\n                    var currentRadian = this.controller.toRadian(this.currentTheta);\n                    var dx = this.targetX - this.currentX;\n                    var dy = this.targetY - this.currentY;\n                    var targetRadian = Math.atan2(dy, dx);\n                    if (\n                        this.controller.controlAngleInitial(\n                            this.wheels,\n                            currentRadian,\n                            targetRadian\n                        )\n                    ) {\n                        this.state = 2;\n                    }\n                }\n                break;\n            }\n            case 2: {\n                var currentRadian = this.controller.toRadian(this.currentTheta);\n                if (\n                    this.controller.controlPosition(\n                        this.wheels,\n                        this.currentX,\n                        this.currentY,\n                        currentRadian,\n                        this.targetX,\n                        this.targetY\n                    )\n                ) {\n                    this.state = 3;\n                }\n                break;\n            }\n            case 3: {\n                var currentRadian = this.controller.toRadian(this.currentTheta);\n                if (\n                    this.controller.controlPositionFine(\n                        this.wheels,\n                        this.currentX,\n                        this.currentY,\n                        currentRadian,\n                        this.targetX,\n                        this.targetY\n                    )\n                ) {\n                    this.clear();\n                    this.wheels.completed = true;\n                }\n                break;\n            }\n        }\n    } else if (this.mode == 2) {\n        this.currentTheta = sensory.orientation;\n        switch (this.state) {\n            case 1: {\n                var currentRadian = this.controller.toRadian(this.currentTheta);\n                var targetRadian = this.controller.toRadian(this.targetTheta);\n                if (this.controller.controlAngleInitial(this.wheels, currentRadian, targetRadian)) {\n                    this.state = 2;\n                }\n                break;\n            }\n            case 2: {\n                var currentRadian = this.controller.toRadian(this.currentTheta);\n                var targetRadian = this.controller.toRadian(this.targetTheta);\n                if (this.controller.controlAngleFinal(this.wheels, currentRadian, targetRadian)) {\n                    this.clear();\n                    this.wheels.completed = true;\n                }\n                break;\n            }\n        }\n    }\n    return this.wheels;\n};\n\nfunction AlbertSchoolRobot(index) {\n    this.sensory = {\n        signalStrength: 0,\n        leftProximity: 0,\n        rightProximity: 0,\n        accelerationX: 0,\n        accelerationY: 0,\n        accelerationZ: 0,\n        positionX: -1,\n        positionY: -1,\n        orientation: -200,\n        light: 0,\n        temperature: 0,\n        frontOid: -1,\n        backOid: -1,\n        batteryState: 2,\n        tilt: 0,\n    };\n    this.motoring = {\n        group: 'albertschool',\n        module: 'albertschool',\n        index,\n    };\n    this.blockId = 0;\n    this.wheelBlockId = 0;\n    this.wheelTimer = undefined;\n    this.navigationCallback = undefined;\n    this.navigator = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.tempo = 60;\n    this.timeouts = [];\n}\n\nAlbertSchoolRobot.prototype.__PORT_MAP = {\n    group: 'albertschool',\n    module: 'albertschool',\n    motion: 0,\n    leftWheel: 0,\n    rightWheel: 0,\n    buzzer: 0,\n    leftEye: 0,\n    rightEye: 0,\n    note: 0,\n    bodyLed: 0,\n    frontLed: 0,\n    padWidth: 0,\n    padHeight: 0,\n};\n\nAlbertSchoolRobot.prototype.setZero = function() {\n    var portMap = this.__PORT_MAP;\n    var motoring = this.motoring;\n    for (var port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    this.blockId = 0;\n    this.wheelBlockId = 0;\n    this.wheelTimer = undefined;\n    this.navigationCallback = undefined;\n    this.navigator = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.tempo = 60;\n    this.__removeAllTimeouts();\n};\n\nAlbertSchoolRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nAlbertSchoolRobot.prototype.afterSend = function(sq) {};\n\nAlbertSchoolRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nAlbertSchoolRobot.prototype.__setModule = function() {\n    this.motoring.group = 'albertschool';\n    this.motoring.module = 'albertschool';\n};\n\nAlbertSchoolRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    var idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nAlbertSchoolRobot.prototype.__removeAllTimeouts = function() {\n    var timeouts = this.timeouts;\n    for (var i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nAlbertSchoolRobot.prototype.__issueWheelBlockId = function() {\n    this.wheelBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.wheelBlockId;\n};\n\nAlbertSchoolRobot.prototype.__cancelWheel = function() {\n    this.wheelBlockId = 0;\n    if (this.wheelTimer !== undefined) {\n        this.__removeTimeout(this.wheelTimer);\n    }\n    this.wheelTimer = undefined;\n};\n\nAlbertSchoolRobot.prototype.__getNavigator = function() {\n    if (this.navigator == undefined) {\n        this.navigator = new AlbertSchoolNavigator();\n    }\n    return this.navigator;\n};\n\nAlbertSchoolRobot.prototype.__cancelNavigation = function() {\n    this.navigationCallback = undefined;\n    if (this.navigator) {\n        this.navigator.clear();\n    }\n};\n\nAlbertSchoolRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nAlbertSchoolRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nAlbertSchoolRobot.prototype.handleSensory = function() {\n    if (this.navigationCallback) {\n        if (this.navigator) {\n            var result = this.navigator.handleSensory(this.sensory);\n            this.motoring.leftWheel = result.left;\n            this.motoring.rightWheel = result.right;\n            if (result.completed) {\n                var callback = this.navigationCallback;\n                this.__cancelNavigation();\n                if (callback) callback();\n            }\n        }\n    }\n};\n\nAlbertSchoolRobot.prototype.__SENSORS = {\n    SIGNAL_STRENGTH: 'signalStrength',\n    LEFT_PROXIMITY: 'leftProximity',\n    RIGHT_PROXIMITY: 'rightProximity',\n    ACCELERATION_X: 'accelerationX',\n    ACCELERATION_Y: 'accelerationY',\n    ACCELERATION_Z: 'accelerationZ',\n    POSITION_X: 'positionX',\n    POSITION_Y: 'positionY',\n    ORIENTATION: 'orientation',\n    LIGHT: 'light',\n    TEMPERATURE: 'temperature',\n    FRONT_OID: 'frontOid',\n    REAR_OID: 'backOid',\n    BATTERY_STATE: 'batteryState',\n    TILT: 'tilt',\n};\n\nAlbertSchoolRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    var dev = script.getField('DEVICE');\n\n    var sensor = this.__SENSORS[dev] || dev;\n    return this.sensory[sensor];\n};\n\nAlbertSchoolRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    var sensory = this.sensory;\n    var value = 0;\n    var dev = script.getField('DEVICE');\n    if (dev.startsWith('TILT')) {\n        if (sensory.tilt === undefined) {\n            if (\n                sensory.accelerationZ < 2048 &&\n                sensory.accelerationX > 2048 &&\n                sensory.accelerationY > -1024 &&\n                sensory.accelerationY < 1024\n            )\n                value = 1;\n            else if (\n                sensory.accelerationZ < 2048 &&\n                sensory.accelerationX < -2048 &&\n                sensory.accelerationY > -1024 &&\n                sensory.accelerationY < 1024\n            )\n                value = -1;\n            else if (\n                sensory.accelerationZ < 2048 &&\n                sensory.accelerationY > 2048 &&\n                sensory.accelerationX > -1024 &&\n                sensory.accelerationX < 1024\n            )\n                value = 2;\n            else if (\n                sensory.accelerationZ < 2048 &&\n                sensory.accelerationY < -2048 &&\n                sensory.accelerationX > -1024 &&\n                sensory.accelerationX < 1024\n            )\n                value = -2;\n            else if (\n                sensory.accelerationZ > 3072 &&\n                sensory.accelerationX > -2048 &&\n                sensory.accelerationX < 2048 &&\n                sensory.accelerationY > -2048 &&\n                sensory.accelerationY < 2048\n            )\n                value = 3;\n            else if (\n                sensory.accelerationZ < -3072 &&\n                sensory.accelerationX > -1024 &&\n                sensory.accelerationX < 1024 &&\n                sensory.accelerationY > -1024 &&\n                sensory.accelerationY < 1024\n            )\n                value = -3;\n            else value = 0;\n        } else {\n            value = sensory.tilt;\n        }\n        switch (dev) {\n            case 'TILT_FORWARD':\n                return value == 1;\n            case 'TILT_BACKWARD':\n                return value == -1;\n            case 'TILT_LEFT':\n                return value == 2;\n            case 'TILT_RIGHT':\n                return value == -2;\n            case 'TILT_FLIP':\n                return value == 3;\n            case 'TILT_NOT':\n                return value == -3;\n        }\n        return false;\n    } else {\n        switch (dev) {\n            case 'BATTERY_NORMAL':\n                return sensory.batteryState === 2;\n            case 'BATTERY_LOW':\n                return sensory.batteryState === 1;\n            case 'BATTERY_EMPTY':\n                return sensory.batteryState === 0;\n        }\n        return false;\n    }\n};\n\nAlbertSchoolRobot.prototype.checkHandFound = function(script) {\n    this.__setModule();\n    var sensory = this.sensory;\n    return sensory.handFound === undefined\n        ? sensory.leftProximity > 40 || sensory.rightProximity > 40\n        : sensory.handFound;\n};\n\nAlbertSchoolRobot.prototype.checkOid = function(script) {\n    this.__setModule();\n    var sensory = this.sensory;\n    var oid = script.getField('OID', script);\n    var value = script.getNumberValue('VALUE');\n    if (oid == 'FRONT') return sensory.frontOid == value;\n    else return sensory.backOid == value;\n};\n\nAlbertSchoolRobot.prototype.__motion = function(type, leftVelocity, rightVelocity, secs, callback) {\n    var self = this;\n    var motoring = self.motoring;\n    self.__cancelNavigation();\n    self.__cancelWheel();\n\n    secs = parseFloat(secs);\n    if (secs && secs > 0) {\n        var id = self.__issueWheelBlockId();\n        motoring.leftWheel = leftVelocity;\n        motoring.rightWheel = rightVelocity;\n        motoring.motion = type;\n        self.wheelTimer = setTimeout(() => {\n            if (self.wheelBlockId == id) {\n                motoring.leftWheel = 0;\n                motoring.rightWheel = 0;\n                motoring.motion = 0;\n                self.__cancelWheel();\n                callback();\n            }\n        }, secs * 1000);\n        self.timeouts.push(self.wheelTimer);\n    } else {\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        motoring.motion = 0;\n        callback();\n    }\n};\n\nAlbertSchoolRobot.prototype.moveForwardSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        var secs = script.getNumberValue('SECS');\n        if (secs < 0) {\n            this.__motion(2, -30, -30, -secs, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motion(1, 30, 30, secs, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertSchoolRobot.prototype.moveBackwardSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        var secs = script.getNumberValue('SECS');\n        if (secs < 0) {\n            this.__motion(1, 30, 30, -secs, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motion(2, -30, -30, secs, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertSchoolRobot.prototype.turnSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        var direction = script.getField('DIRECTION');\n        var secs = script.getNumberValue('SECS');\n        if (direction == 'LEFT') {\n            if (secs < 0) {\n                this.__motion(4, 30, -30, -secs, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motion(3, -30, 30, secs, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (secs < 0) {\n                this.__motion(3, -30, 30, -secs, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motion(4, 30, -30, secs, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertSchoolRobot.prototype.setWheels = function(script) {\n    var motoring = this.motoring;\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelWheel();\n\n    var leftVelocity = script.getNumberValue('LEFT');\n    var rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel = leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel = rightVelocity;\n    }\n    motoring.motion = 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.changeWheels = function(script) {\n    var motoring = this.motoring;\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelWheel();\n\n    var leftVelocity = script.getNumberValue('LEFT');\n    var rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel =\n            motoring.leftWheel !== undefined ? motoring.leftWheel + leftVelocity : leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel =\n            motoring.rightWheel !== undefined ? motoring.rightWheel + rightVelocity : rightVelocity;\n    }\n    motoring.motion = 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.setWheel = function(script) {\n    var motoring = this.motoring;\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelWheel();\n\n    var wheel = script.getField('WHEEL');\n    var velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel = velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel = velocity;\n        } else {\n            motoring.leftWheel = velocity;\n            motoring.rightWheel = velocity;\n        }\n    }\n    motoring.motion = 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.changeWheel = function(script) {\n    var motoring = this.motoring;\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelWheel();\n\n    var wheel = script.getField('WHEEL');\n    var velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        } else {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        }\n    }\n    motoring.motion = 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.stop = function(script) {\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelWheel();\n\n    var motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    motoring.motion = 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.setBoardSize = function(script) {\n    var motoring = this.motoring;\n    this.__setModule();\n\n    var width = script.getNumberValue('WIDTH');\n    var height = script.getNumberValue('HEIGHT');\n    width = parseInt(width);\n    height = parseInt(height);\n    if (width && height && width > 0 && height > 0) {\n        var navi = this.__getNavigator();\n        navi.setBoardSize(width, height);\n        motoring.padWidth = width;\n        motoring.padHeight = height;\n    }\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.moveToOnBoard = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelNavigation();\n        this.__cancelWheel();\n        var toward = script.getField('TOWARD');\n        var x = script.getNumberValue('X');\n        var y = script.getNumberValue('Y');\n        x = parseInt(x);\n        y = parseInt(y);\n        var navi = this.__getNavigator();\n        if (\n            typeof x == 'number' &&\n            typeof y == 'number' &&\n            x >= 0 &&\n            x < navi.getBoardWidth() &&\n            y >= 0 &&\n            y < navi.getBoardHeight()\n        ) {\n            this.motoring.motion = 0;\n            navi.setBackward(toward == 'BACKWARD');\n            navi.moveTo(x, y);\n            this.navigationCallback = () => {\n                script.isMoving = false;\n            };\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertSchoolRobot.prototype.setOrientationToOnBoard = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelNavigation();\n        this.__cancelWheel();\n        var degree = script.getNumberValue('DEGREE');\n        degree = parseInt(degree);\n        if (typeof degree == 'number') {\n            var navi = this.__getNavigator();\n            this.motoring.motion = 0;\n            navi.setBackward(false);\n            navi.turnTo(degree);\n            this.navigationCallback = () => {\n                script.isMoving = false;\n            };\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertSchoolRobot.prototype.__COLORS = {\n    RED: 4,\n    ORANGE: 4,\n    YELLOW: 6,\n    GREEN: 2,\n    SKY_BLUE: 3,\n    BLUE: 1,\n    VIOLET: 5,\n    PURPLE: 5,\n    WHITE: 7,\n    '4': 4,\n    '6': 6,\n    '2': 2,\n    '3': 3,\n    '1': 1,\n    '5': 5,\n    '7': 7,\n};\n\nAlbertSchoolRobot.prototype.setEye = function(script) {\n    this.__setModule();\n    var eye = script.getField('EYE');\n    var color = script.getField('COLOR');\n    color = parseInt(this.__COLORS[color]);\n\n    if (color && color > 0) {\n        if (eye == 'LEFT') {\n            this.motoring.leftEye = color;\n        } else if (eye == 'RIGHT') {\n            this.motoring.rightEye = color;\n        } else {\n            this.motoring.leftEye = color;\n            this.motoring.rightEye = color;\n        }\n    }\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.clearEye = function(script) {\n    this.__setModule();\n    var eye = script.getField('EYE');\n\n    if (eye == 'LEFT') {\n        this.motoring.leftEye = 0;\n    } else if (eye == 'RIGHT') {\n        this.motoring.rightEye = 0;\n    } else {\n        this.motoring.leftEye = 0;\n        this.motoring.rightEye = 0;\n    }\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.turnBodyLed = function(script) {\n    this.__setModule();\n    var value = script.getField('VALUE');\n    this.motoring.bodyLed = value == 'ON' ? 1 : 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.turnFrontLed = function(script) {\n    this.__setModule();\n    var value = script.getField('VALUE');\n    this.motoring.frontLed = value == 'ON' ? 1 : 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.__runBeep = function(count, id, callback) {\n    if (count) {\n        var self = this;\n        var motoring = self.motoring;\n        motoring.buzzer = 440;\n        motoring.note = 0;\n        self.noteTimer1 = setTimeout(() => {\n            if (!id || self.noteBlockId == id) {\n                motoring.buzzer = 0;\n                if (self.noteTimer1 !== undefined) {\n                    self.__removeTimeout(self.noteTimer1);\n                }\n                self.noteTimer1 = undefined;\n            }\n        }, 100);\n        self.timeouts.push(self.noteTimer1);\n        self.noteTimer2 = setTimeout(() => {\n            if (!id || self.noteBlockId == id) {\n                motoring.buzzer = 0;\n                if (self.noteTimer2 !== undefined) {\n                    self.__removeTimeout(self.noteTimer2);\n                }\n                self.noteTimer2 = undefined;\n                if (count < 0) {\n                    self.__runBeep(-1, id, callback);\n                } else if (count == 1) {\n                    self.__cancelNote();\n                    if (id && callback) {\n                        callback();\n                    }\n                } else {\n                    self.__runBeep(count - 1, id, callback);\n                }\n            }\n        }, 200);\n        self.timeouts.push(self.noteTimer2);\n    }\n};\n\nAlbertSchoolRobot.prototype.beep = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        var id = this.__issueNoteBlockId();\n        this.__runBeep(1, id, () => {\n            script.isPlaying = false;\n        });\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertSchoolRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    var hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.motoring.note = 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    var hz = script.getNumberValue('HZ');\n\n    var motoring = this.motoring;\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    motoring.note = 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.clearBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.__NOTES = {\n    C: 4,\n    'C#': 5,\n    Db: 5,\n    D: 6,\n    'D#': 7,\n    Eb: 7,\n    E: 8,\n    F: 9,\n    'F#': 10,\n    Gb: 10,\n    G: 11,\n    'G#': 12,\n    Ab: 12,\n    A: 13,\n    'A#': 14,\n    Bb: 14,\n    B: 15,\n    '4': 4,\n    '5': 5,\n    '6': 6,\n    '7': 7,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n    '11': 11,\n    '12': 12,\n    '13': 13,\n    '14': 14,\n    '15': 15,\n};\n\nAlbertSchoolRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n\n    var note = script.getField('NOTE');\n    var octave = script.getNumberField('OCTAVE');\n\n    note = parseInt(this.__NOTES[note]);\n    octave = parseInt(octave);\n    var motoring = this.motoring;\n    motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        motoring.note = note + (octave - 1) * 12;\n    } else {\n        motoring.note = 0;\n    }\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.playNoteBeat = function(script) {\n    var self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n\n        var motoring = self.motoring;\n        var note = script.getField('NOTE');\n        var octave = script.getNumberField('OCTAVE');\n        var beat = script.getNumberValue('BEAT');\n\n        note = parseInt(this.__NOTES[note]);\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            var id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            motoring.note = note;\n            var timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        motoring.note = 0;\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    motoring.note = 0;\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n        } else {\n            motoring.note = 0;\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.motoring.note = 0;\n        return script.callReturn();\n    }\n};\n\nAlbertSchoolRobot.prototype.restBeat = function(script) {\n    var self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        var beat = script.getNumberValue('BEAT');\n\n        var motoring = self.motoring;\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        motoring.note = 0;\n        if (beat && beat > 0 && self.tempo > 0) {\n            var id = self.__issueNoteBlockId();\n            var timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertSchoolRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    var bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nAlbertSchoolRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    var bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nEntry.Albert = {\n    robot: undefined,\n    getRobot() {\n        if (Entry.Albert.robot == undefined) Entry.Albert.robot = new AlbertSchoolRobot(0);\n        Entry.Albert.robot.setMotoring(Entry.hw.sendQueue);\n        return Entry.Albert.robot;\n    },\n    setZero() {\n        if (Entry.Albert.robot) Entry.Albert.robot.setZero();\n        Entry.hw.update();\n    },\n    afterReceive(pd) {\n        var robot = Entry.Albert.getRobot();\n        if (robot) robot.afterReceive(pd);\n    },\n    id: '2.5',\n    name: 'albert',\n    url: 'http://albert.school',\n    imageName: 'albertschool.png',\n    title: {\n        ko: '알버트 스쿨',\n        en: 'Albert School',\n        jp: 'アルバートスクール',\n        vn: 'Albert School',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/albert.png',\n        width: 387,\n        height: 503,\n        listPorts: {\n            accelerationX: {\n                name: Lang.Blocks.ALBERT_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.ALBERT_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.ALBERT_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            frontOid: {\n                name: Lang.Blocks.ALBERT_sensor_front_oid,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            backOid: {\n                name: Lang.Blocks.ALBERT_sensor_back_oid,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            positionX: {\n                name: Lang.Blocks.ALBERT_sensor_position_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            positionY: {\n                name: Lang.Blocks.ALBERT_sensor_position_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            orientation: {\n                name: Lang.Blocks.ALBERT_sensor_orientation,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            temperature: {\n                name: Lang.Blocks.ALBERT_sensor_temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            signalStrength: {\n                name: Lang.Blocks.ALBERT_sensor_signal_strength,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Hw.buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: { name: Lang.Hw.note, type: 'output', pos: { x: 0, y: 0 } },\n        },\n        ports: {\n            leftProximity: {\n                name: Lang.Blocks.ALBERT_sensor_left_proximity,\n                type: 'input',\n                pos: { x: 178, y: 401 },\n            },\n            rightProximity: {\n                name: Lang.Blocks.ALBERT_sensor_right_proximity,\n                type: 'input',\n                pos: { x: 66, y: 359 },\n            },\n            light: {\n                name: Lang.Blocks.ALBERT_sensor_light,\n                type: 'input',\n                pos: { x: 127, y: 391 },\n            },\n            leftWheel: {\n                name: Lang.Hw.leftWheel,\n                type: 'output',\n                pos: { x: 299, y: 406 },\n            },\n            rightWheel: {\n                name: Lang.Hw.rightWheel,\n                type: 'output',\n                pos: { x: 22, y: 325 },\n            },\n            leftEye: {\n                name: Lang.Hw.leftEye,\n                type: 'output',\n                pos: { x: 260, y: 26 },\n            },\n            rightEye: {\n                name: Lang.Hw.rightEye,\n                type: 'output',\n                pos: { x: 164, y: 13 },\n            },\n            bodyLed: {\n                name: Lang.Hw.body + ' ' + Lang.Hw.led_en,\n                type: 'output',\n                pos: { x: 367, y: 308 },\n            },\n            frontLed: {\n                name: Lang.Hw.front + ' ' + Lang.Hw.led_en,\n                pos: { x: 117, y: 410 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.Albert.setLanguage = () => ({\n    ko: {\n        template: {\n            albert_value: '%1',\n            albert_hand_found: '손 찾음?',\n            albert_is_oid_value: '%1 OID가 %2인가?',\n            albert_boolean: '%1?',\n            albert_move_forward_for_secs: '앞으로 %1초 이동하기 %2',\n            albert_move_backward_for_secs: '뒤로 %1초 이동하기 %2',\n            albert_turn_for_secs: '%1 으로 %2초 돌기 %3',\n            albert_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            albert_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            albert_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            albert_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            albert_stop: '정지하기 %1',\n            albert_set_pad_size_to: '말판 크기를 폭 %1 높이 %2(으)로 정하기 %3',\n            albert_move_to_x_y_on_board: '밑판 %1 x: %2 y: %3 위치로 이동하기 %4',\n            albert_set_orientation_on_board: '말판 %1도 방향으로 돌기 %2',\n            albert_set_eye_to: '%1 눈을 %2 으로 정하기 %3',\n            albert_clear_eye: '%1 눈 끄기 %2',\n            albert_body_led: '몸통 LED %1 %2',\n            albert_front_led: '앞쪽 LED %1 %2',\n            albert_beep: '삐 소리내기 %1',\n            albert_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            albert_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            albert_clear_buzzer: '버저 끄기 %1',\n            albert_play_note: '%1 %2 음을 연주하기 %3',\n            albert_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n            albert_rest_for: '%1 박자 쉬기 %2',\n            albert_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            albert_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n            albert_move_forward: '앞으로 이동하기 %1',\n            albert_move_backward: '뒤로 이동하기 %1',\n            albert_turn_around: '%1 으로 돌기 %2',\n            albert_set_led_to: '%1 %2 으로 정하기 %3',\n            albert_clear_led: '%1 %2',\n            albert_change_wheels_by: '%1 %2 %3',\n            albert_set_wheels_to: '%1 %2 %3',\n        },\n        Helper: {\n            albert_value:\n                '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>앞쪽 OID: 앞쪽 OID 센서의 값 (값의 범위: -1 ~ 65535, 초기값: -1)<br/>뒤쪽 OID: 뒤쪽 OID 센서의 값 (값의 범위: -1 ~ 65535, 초기값: -1)<br/>x 위치: 말판 위에서 로봇의 위치 x좌표 값 (값의 범위: -1 ~ 39999, 초기값: -1)<br/>y 위치: 말판 위에서 로봇의 위치 y좌표 값 (값의 범위: -1 ~ 39999, 초기값: -1)<br/>방향: 말판 위에서 로봇의 방향 값 (값의 범위: -179 ~ 180, 초기값: -200)<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.',\n            albert_hand_found:\n                \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            albert_is_oid_value:\n                \"앞쪽/뒤쪽 OID 센서가 감지한 OID 값이 입력한 숫자와 같으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            albert_boolean:\n                \"앞으로 기울임: 앞으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집었으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않았으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            albert_move_forward_for_secs: '입력한 시간(초)만큼 앞으로 이동합니다.',\n            albert_move_backward_for_secs: '입력한 시간(초)만큼 뒤로 이동합니다.',\n            albert_turn_for_secs: '입력한 시간(초)만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            albert_change_both_wheels_by:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            albert_set_both_wheels_to:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            albert_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            albert_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            albert_stop: '양쪽 바퀴를 정지합니다.',\n            albert_set_pad_size_to: '말판의 폭과 높이를 입력한 값으로 설정합니다.',\n            albert_move_to_x_y_on_board: '밑판 위에서 입력한 x, y 위치로 이동합니다.',\n            albert_set_orientation_on_board: '말판 위에서 입력한 각도 방향으로 회전합니다.',\n            albert_set_eye_to: '왼쪽/오른쪽/양쪽 눈을 선택한 색깔로 켭니다.',\n            albert_clear_eye: '왼쪽/오른쪽/양쪽 눈을 끕니다.',\n            albert_body_led: '몸통 LED를 켜거나 끕니다.',\n            albert_front_led: '앞쪽 LED를 켜거나 끕니다.',\n            albert_beep: '버저 소리를 짧게 냅니다.',\n            albert_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            albert_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n            albert_clear_buzzer: '버저 소리를 끕니다.',\n            albert_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            albert_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            albert_rest_for: '입력한 박자만큼 쉽니다.',\n            albert_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            albert_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n        },\n        Blocks: {\n            ROBOID_sensor_left_proximity: '왼쪽 근접 센서',\n            ROBOID_sensor_right_proximity: '오른쪽 근접 센서',\n            ROBOID_sensor_acceleration_x: 'x축 가속도',\n            ROBOID_sensor_acceleration_y: 'y축 가속도',\n            ROBOID_sensor_acceleration_z: 'z축 가속도',\n            ROBOID_sensor_front_oid: '앞쪽 OID',\n            ROBOID_sensor_rear_oid: '뒤쪽 OID',\n            ROBOID_sensor_position_x: 'x 위치',\n            ROBOID_sensor_position_y: 'y 위치',\n            ROBOID_sensor_orientation: '방향',\n            ROBOID_sensor_light: '밝기',\n            ROBOID_sensor_temperature: '온도',\n            ROBOID_sensor_signal_strength: '신호 세기',\n            ROBOID_left: '왼쪽',\n            ROBOID_right: '오른쪽',\n            ROBOID_both: '양쪽',\n            ROBOID_front: '앞쪽',\n            ROBOID_rear: '뒤쪽',\n            ROBOID_forward2: '앞으로',\n            ROBOID_backward2: '뒤로',\n            ROBOID_tilt_forward: '앞으로 기울임',\n            ROBOID_tilt_backward: '뒤로 기울임',\n            ROBOID_tilt_left: '왼쪽으로 기울임',\n            ROBOID_tilt_right: '오른쪽으로 기울임',\n            ROBOID_tilt_flip: '거꾸로 뒤집음',\n            ROBOID_tilt_not: '기울이지 않음',\n            ROBOID_battery_normal: '배터리 정상',\n            ROBOID_battery_low: '배터리 부족',\n            ROBOID_battery_empty: '배터리 없음',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_turn_on: '켜기',\n            ROBOID_turn_off: '끄기',\n            ROBOID_note_c: '도',\n            ROBOID_note_c_sharp: '도♯(레♭)',\n            ROBOID_note_d: '레',\n            ROBOID_note_d_sharp: '레♯(미♭)',\n            ROBOID_note_e: '미',\n            ROBOID_note_f: '파',\n            ROBOID_note_f_sharp: '파♯(솔♭)',\n            ROBOID_note_g: '솔',\n            ROBOID_note_g_sharp: '솔♯(라♭)',\n            ROBOID_note_a: '라',\n            ROBOID_note_a_sharp: '라♯(시♭)',\n            ROBOID_note_b: '시',\n        },\n        Menus: {\n            albert: '알버트',\n        },\n    },\n    en: {\n        template: {\n            albert_value: '%1',\n            albert_hand_found: 'hand found?',\n            albert_is_oid_value: '%1 oid %2?',\n            albert_boolean: '%1?',\n            albert_move_forward_for_secs: 'move forward %1 secs %2',\n            albert_move_backward_for_secs: 'move backward %1 secs %2',\n            albert_turn_for_secs: 'turn %1 %2 secs %3',\n            albert_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            albert_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            albert_change_wheel_by: 'change %1 wheel by %2 %3',\n            albert_set_wheel_to: 'set %1 wheel to %2 %3',\n            albert_stop: 'stop %1',\n            albert_set_pad_size_to: 'set board size to width: %1 height: %2 %3',\n            albert_move_to_x_y_on_board: 'move %1 to x: %2 y: %3 on board %4',\n            albert_set_orientation_on_board: 'turn towards %1 degrees on board %2',\n            albert_set_eye_to: 'set %1 eye to %2 %3',\n            albert_clear_eye: 'clear %1 eye %2',\n            albert_body_led: 'turn body led %1 %2',\n            albert_front_led: 'turn front led %1 %2',\n            albert_beep: 'beep %1',\n            albert_change_buzzer_by: 'change buzzer by %1 %2',\n            albert_set_buzzer_to: 'set buzzer to %1 %2',\n            albert_clear_buzzer: 'clear buzzer %1',\n            albert_play_note: 'play note %1 %2 %3',\n            albert_play_note_for: 'play note %1 %2 for %3 beats %4',\n            albert_rest_for: 'rest for %1 beats %2',\n            albert_change_tempo_by: 'change tempo by %1 %2',\n            albert_set_tempo_to: 'set tempo to %1 bpm %2',\n            albert_move_forward: 'move forward %1',\n            albert_move_backward: 'move backward %1',\n            albert_turn_around: 'turn %1 %2',\n            albert_set_led_to: 'set %1 led %2 %3',\n            albert_clear_led: 'clear %1 led %2',\n            albert_change_wheels_by: '%1 %2 %3',\n            albert_set_wheels_to: '%1 %2 %3',\n        },\n        Helper: {\n            albert_value:\n                \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>front oid: value of front oid sensor (range: -1 ~ 65535, initial value: -1)<br/>rear oid: value of rear oid sensor (range: -1 ~ 65535, initial value: -1)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>orientation: orientation angle value (degree) of robot on the board (range: -179 ~ 180, initial value: -200)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            albert_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            albert_is_oid_value:\n                'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            albert_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            albert_move_forward_for_secs: 'Moves forward for the entered seconds.',\n            albert_move_backward_for_secs: 'Moves backward for the entered seconds.',\n            albert_turn_for_secs: 'Turns left/right in place for the entered seconds.',\n            albert_change_both_wheels_by:\n                'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albert_set_both_wheels_to:\n                'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albert_change_wheel_by:\n                'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albert_set_wheel_to:\n                'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albert_stop: 'Stops both wheels.',\n            albert_set_pad_size_to: 'Sets the width and height of the board.',\n            albert_move_to_x_y_on_board: 'Moves to the entered x, y position on the board.',\n            albert_set_orientation_on_board:\n                'Turns toward the entered angle (degrees) on the board.',\n            albert_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            albert_clear_eye: 'Turns off the left/right/both eyes.',\n            albert_body_led: 'Turns on/off the body led.',\n            albert_front_led: 'Turns on/off the front led.',\n            albert_beep: 'Plays beep sound.',\n            albert_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            albert_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            albert_clear_buzzer: 'Turns off buzzer sound.',\n            albert_play_note: 'It sounds the selected tone and octave.',\n            albert_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            albert_rest_for: 'Rests as much as the beat you entered.',\n            albert_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            albert_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_sensor_left_proximity: 'left proximity',\n            ROBOID_sensor_right_proximity: 'right proximity',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_front_oid: 'front oid',\n            ROBOID_sensor_rear_oid: 'rear oid',\n            ROBOID_sensor_position_x: 'x position',\n            ROBOID_sensor_position_y: 'y position',\n            ROBOID_sensor_orientation: 'orientation',\n            ROBOID_sensor_light: 'light',\n            ROBOID_sensor_temperature: 'temperature',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_front: 'front',\n            ROBOID_rear: 'rear',\n            ROBOID_forward2: 'forward',\n            ROBOID_backward2: 'backward',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_color_red: 'red',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_turn_on: 'on',\n            ROBOID_turn_off: 'off',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n        Menus: {\n            albert: 'albert',\n        },\n    },\n    jp: {\n        template: {\n            albert_value: '%1',\n            albert_hand_found: '手を見つけたか?',\n            albert_is_oid_value: '%1 OIDが %2ですか?',\n            albert_boolean: '%1?',\n            albert_move_forward_for_secs: '前へ%1秒移動する %2',\n            albert_move_backward_for_secs: '後ろへ%1秒移動する %2',\n            albert_turn_for_secs: '%1へ%2秒回す %3',\n            albert_change_both_wheels_by: '左車輪を%1右車輪を%2ずつ変える %3',\n            albert_set_both_wheels_to: '左車輪を%1右車輪を%2にする %3',\n            albert_change_wheel_by: '%1車輪を%2ずつ変える %3',\n            albert_set_wheel_to: '%1車輪を%2にする %3',\n            albert_stop: '停止する %1',\n            albert_set_pad_size_to: 'ボード板幅を%1高さを%2にする %3',\n            albert_move_to_x_y_on_board: 'ボード板上で %1 x: %2 y: %3 位置に移動する %4',\n            albert_set_orientation_on_board: 'ボード板上で %1 度に向ける %2',\n            albert_set_eye_to: '%1眼を%2にする %3',\n            albert_clear_eye: '%1眼を消す %2',\n            albert_body_led: '胴体LEDを %1 %2',\n            albert_front_led: '前方LEDを %1 %2',\n            albert_beep: 'ビープ %1',\n            albert_change_buzzer_by: 'ブザー音を%1ずつ変える %2',\n            albert_set_buzzer_to: 'ブザー音を%1にする %2',\n            albert_clear_buzzer: 'ブザー音を消す %1',\n            albert_play_note: '%1%2音を鳴らす %3',\n            albert_play_note_for: '%1%2音を%3拍鳴らす %4',\n            albert_rest_for: '%1拍休む %2',\n            albert_change_tempo_by: 'テンポを%1ずつ変える %2',\n            albert_set_tempo_to: 'テンポを%1BPMにする %2',\n        },\n        Helper: {\n            albert_value:\n                \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>front oid: value of front oid sensor (range: -1 ~ 65535, initial value: -1)<br/>rear oid: value of rear oid sensor (range: -1 ~ 65535, initial value: -1)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>orientation: orientation angle value (degree) of robot on the board (range: -179 ~ 180, initial value: -200)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            albert_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            albert_is_oid_value:\n                'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            albert_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            albert_move_forward_for_secs: 'Moves forward for the entered seconds.',\n            albert_move_backward_for_secs: 'Moves backward for the entered seconds.',\n            albert_turn_for_secs: 'Turns left/right in place for the entered seconds.',\n            albert_change_both_wheels_by:\n                'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albert_set_both_wheels_to:\n                'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albert_change_wheel_by:\n                'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albert_set_wheel_to:\n                'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albert_stop: 'Stops both wheels.',\n            albert_set_pad_size_to: 'Sets the width and height of the board.',\n            albert_move_to_x_y_on_board: 'Moves to the entered x, y position on the board.',\n            albert_set_orientation_on_board:\n                'Turns toward the entered angle (degrees) on the board.',\n            albert_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            albert_clear_eye: 'Turns off the left/right/both eyes.',\n            albert_body_led: 'Turns on/off the body led.',\n            albert_front_led: 'Turns on/off the front led.',\n            albert_beep: 'Plays beep sound.',\n            albert_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            albert_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            albert_clear_buzzer: 'Turns off buzzer sound.',\n            albert_play_note: 'It sounds the selected tone and octave.',\n            albert_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            albert_rest_for: 'Rests as much as the beat you entered.',\n            albert_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            albert_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_sensor_left_proximity: '左近接センサー',\n            ROBOID_sensor_right_proximity: '右近接センサー',\n            ROBOID_sensor_acceleration_x: 'x軸加速度',\n            ROBOID_sensor_acceleration_y: 'y軸加速度',\n            ROBOID_sensor_acceleration_z: 'z軸加速度',\n            ROBOID_sensor_front_oid: '前OID',\n            ROBOID_sensor_rear_oid: '後OID',\n            ROBOID_sensor_position_x: 'x位置',\n            ROBOID_sensor_position_y: 'y位置',\n            ROBOID_sensor_orientation: '方向',\n            ROBOID_sensor_light: '照度',\n            ROBOID_sensor_temperature: '温度',\n            ROBOID_sensor_signal_strength: '信号強度',\n            ROBOID_left: '左',\n            ROBOID_right: '右',\n            ROBOID_both: '両',\n            ROBOID_front: '前',\n            ROBOID_rear: '後',\n            ROBOID_forward2: '前へ',\n            ROBOID_backward2: '後ろへ',\n            ROBOID_tilt_forward: '前に傾けたか',\n            ROBOID_tilt_backward: '後に傾けたか',\n            ROBOID_tilt_left: '左に傾けたか',\n            ROBOID_tilt_right: '右に傾けたか',\n            ROBOID_tilt_flip: '上下裏返したか',\n            ROBOID_tilt_not: '傾けなかったか',\n            ROBOID_battery_normal: '電池が正常か',\n            ROBOID_battery_low: '電池が足りないか',\n            ROBOID_battery_empty: '電池がないか',\n            ROBOID_color_red: '赤色',\n            ROBOID_color_yellow: '黄色',\n            ROBOID_color_green: '緑色',\n            ROBOID_color_sky_blue: '水色',\n            ROBOID_color_blue: '青色',\n            ROBOID_color_purple: '紫色',\n            ROBOID_color_white: '白色',\n            ROBOID_turn_on: '点灯',\n            ROBOID_turn_off: '消す',\n            ROBOID_note_c: 'ド',\n            ROBOID_note_c_sharp: 'ド♯(レ♭)',\n            ROBOID_note_d: 'レ',\n            ROBOID_note_d_sharp: 'レ♯(ミ♭)',\n            ROBOID_note_e: 'ミ',\n            ROBOID_note_f: 'ファ',\n            ROBOID_note_f_sharp: 'ファ♯(ソ♭)',\n            ROBOID_note_g: 'ソ',\n            ROBOID_note_g_sharp: 'ソ♯(ラ♭)',\n            ROBOID_note_a: 'ラ',\n            ROBOID_note_a_sharp: 'ラ♯(シ♭)',\n            ROBOID_note_b: 'シ',\n        },\n    },\n    vn: {\n        template: {\n            albert_value: '%1',\n            albert_hand_found: 'hand found?',\n            albert_is_oid_value: '%1 oid %2?',\n            albert_boolean: '%1?',\n            albert_move_forward_for_secs: 'move forward %1 secs %2',\n            albert_move_backward_for_secs: 'move backward %1 secs %2',\n            albert_turn_for_secs: 'turn %1 %2 secs %3',\n            albert_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            albert_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            albert_change_wheel_by: 'change %1 wheel by %2 %3',\n            albert_set_wheel_to: 'set %1 wheel to %2 %3',\n            albert_stop: 'stop %1',\n            albert_set_pad_size_to: 'set board size to width: %1 height: %2 %3',\n            albert_move_to_x_y_on_board: 'move %1 to x: %2 y: %3 on board %4',\n            albert_set_orientation_on_board: 'turn towards %1 degrees on board %2',\n            albert_set_eye_to: 'set %1 eye to %2 %3',\n            albert_clear_eye: 'clear %1 eye %2',\n            albert_body_led: 'turn %1 body led %2',\n            albert_front_led: 'turn %1 front led %2',\n            albert_beep: 'beep %1',\n            albert_change_buzzer_by: 'change buzzer by %1 %2',\n            albert_set_buzzer_to: 'set buzzer to %1 %2',\n            albert_clear_buzzer: 'clear buzzer %1',\n            albert_play_note: 'play note %1 %2 %3',\n            albert_play_note_for: 'play note %1 %2 for %3 beats %4',\n            albert_rest_for: 'rest for %1 beats %2',\n            albert_change_tempo_by: 'change tempo by %1 %2',\n            albert_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            albert_value:\n                \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>front oid: value of front oid sensor (range: -1 ~ 65535, initial value: -1)<br/>rear oid: value of rear oid sensor (range: -1 ~ 65535, initial value: -1)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>orientation: orientation angle value (degree) of robot on the board (range: -179 ~ 180, initial value: -200)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            albert_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            albert_is_oid_value:\n                'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            albert_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            albert_move_forward_for_secs: 'Moves forward for the entered seconds.',\n            albert_move_backward_for_secs: 'Moves backward for the entered seconds.',\n            albert_turn_for_secs: 'Turns left/right in place for the entered seconds.',\n            albert_change_both_wheels_by:\n                'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albert_set_both_wheels_to:\n                'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albert_change_wheel_by:\n                'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albert_set_wheel_to:\n                'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albert_stop: 'Stops both wheels.',\n            albert_set_pad_size_to: 'Sets the width and height of the board.',\n            albert_move_to_x_y_on_board: 'Moves to the entered x, y position on the board.',\n            albert_set_orientation_on_board:\n                'Turns toward the entered angle (degrees) on the board.',\n            albert_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            albert_clear_eye: 'Turns off the left/right/both eyes.',\n            albert_body_led: 'Turns on/off the body led.',\n            albert_front_led: 'Turns on/off the front led.',\n            albert_beep: 'Plays beep sound.',\n            albert_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            albert_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            albert_clear_buzzer: 'Turns off buzzer sound.',\n            albert_play_note: 'It sounds the selected tone and octave.',\n            albert_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            albert_rest_for: 'Rests as much as the beat you entered.',\n            albert_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            albert_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_sensor_left_proximity: 'left proximity',\n            ROBOID_sensor_right_proximity: 'right proximity',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_front_oid: 'front oid',\n            ROBOID_sensor_rear_oid: 'rear oid',\n            ROBOID_sensor_position_x: 'x position',\n            ROBOID_sensor_position_y: 'y position',\n            ROBOID_sensor_orientation: 'orientation',\n            ROBOID_sensor_light: 'light',\n            ROBOID_sensor_temperature: 'temperature',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_front: 'front',\n            ROBOID_rear: 'rear',\n            ROBOID_forward2: 'forward',\n            ROBOID_backward2: 'backward',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_color_red: 'red',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_turn_on: 'on',\n            ROBOID_turn_off: 'off',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n});\n\nEntry.Albert.blockMenuBlocks = [\n    'albert_value',\n    'albert_hand_found',\n    'albert_is_oid_value',\n    'albert_boolean',\n    'albert_move_forward_for_secs',\n    'albert_move_backward_for_secs',\n    'albert_turn_for_secs',\n    'albert_change_both_wheels_by',\n    'albert_set_both_wheels_to',\n    'albert_change_wheel_by',\n    'albert_set_wheel_to',\n    'albert_stop',\n    'albert_set_pad_size_to',\n    'albert_move_to_x_y_on_board',\n    'albert_set_orientation_on_board',\n    'albert_set_eye_to',\n    'albert_clear_eye',\n    'albert_body_led',\n    'albert_front_led',\n    'albert_beep',\n    'albert_change_buzzer_by',\n    'albert_set_buzzer_to',\n    'albert_clear_buzzer',\n    'albert_play_note',\n    'albert_play_note_for',\n    'albert_rest_for',\n    'albert_change_tempo_by',\n    'albert_set_tempo_to',\n];\n\nEntry.Albert.getBlocks = function() {\n    return {\n        albert_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sensor_left_proximity, 'leftProximity'],\n                        [Lang.Blocks.ROBOID_sensor_right_proximity, 'rightProximity'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_x, 'accelerationX'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_y, 'accelerationY'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_z, 'accelerationZ'],\n                        [Lang.Blocks.ROBOID_sensor_front_oid, 'frontOid'],\n                        [Lang.Blocks.ROBOID_sensor_rear_oid, 'backOid'],\n                        [Lang.Blocks.ROBOID_sensor_position_x, 'positionX'],\n                        [Lang.Blocks.ROBOID_sensor_position_y, 'positionY'],\n                        [Lang.Blocks.ROBOID_sensor_orientation, 'orientation'],\n                        [Lang.Blocks.ROBOID_sensor_light, 'light'],\n                        [Lang.Blocks.ROBOID_sensor_temperature, 'temperature'],\n                        [Lang.Blocks.ROBOID_sensor_signal_strength, 'signalStrength'],\n                    ],\n                    value: 'leftProximity',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albert_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'albert_sensor',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                if (robot) return robot.getValue(script);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sensor_left_proximity, 'leftProximity'],\n                                    [Lang.Blocks.ROBOID_sensor_right_proximity, 'rightProximity'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_x, 'accelerationX'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_y, 'accelerationY'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_z, 'accelerationZ'],\n                                    [Lang.Blocks.ROBOID_sensor_front_oid, 'frontOid'],\n                                    [Lang.Blocks.ROBOID_sensor_rear_oid, 'backOid'],\n                                    [Lang.Blocks.ROBOID_sensor_position_x, 'positionX'],\n                                    [Lang.Blocks.ROBOID_sensor_position_y, 'positionY'],\n                                    [Lang.Blocks.ROBOID_sensor_orientation, 'orientation'],\n                                    [Lang.Blocks.ROBOID_sensor_light, 'light'],\n                                    [Lang.Blocks.ROBOID_sensor_temperature, 'temperature'],\n                                    [Lang.Blocks.ROBOID_sensor_signal_strength, 'signalStrength'],\n                                ],\n                                value: 'leftProximity',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_hand_found: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'albert_hand_found',\n            },\n            class: 'albert_sensor',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.checkHandFound(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.hand_found()',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        albert_is_oid_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_front, 'FRONT'],\n                        [Lang.Blocks.ROBOID_rear, 'BACK'],\n                    ],\n                    value: 'FRONT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'albert_is_oid_value',\n            },\n            paramsKeyMap: {\n                OID: 0,\n                VALUE: 1,\n            },\n            class: 'albert_sensor',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.checkOid(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.is_oid(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_front, 'FRONT'],\n                                    [Lang.Blocks.ROBOID_rear, 'BACK'],\n                                ],\n                                value: 'FRONT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        albert_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albert_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'albert_sensor',\n            isNotFor: ['albert'],\n            func(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_move_forward_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'albert_move_forward_for_secs',\n            },\n            paramsKeyMap: {\n                SECS: 0,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.moveForwardSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.move_forward(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_move_backward_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'albert_move_backward_for_secs',\n            },\n            paramsKeyMap: {\n                SECS: 0,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.moveBackwardSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.move_backward(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_turn_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'albert_turn_for_secs',\n                id: 'como',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                SECS: 1,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.turnSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.turn(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_change_both_wheels_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'albert_change_both_wheels_by',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_set_both_wheels_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'albert_set_both_wheels_to',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'albert_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'albert_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albert_stop',\n                id: '4adb',\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.stop()',\n                    },\n                ],\n            },\n        },\n        albert_set_pad_size_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['108'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['76'],\n                    },\n                    null,\n                ],\n                type: 'albert_set_pad_size_to',\n                id: '5mhg',\n            },\n            paramsKeyMap: {\n                WIDTH: 0,\n                HEIGHT: 1,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.setBoardSize(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.set_board_size(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_move_to_x_y_on_board: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_forward2, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_backward2, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'albert_move_to_x_y_on_board',\n            },\n            paramsKeyMap: {\n                TOWARD: 0,\n                X: 1,\n                Y: 2,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.moveToOnBoard(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.move_to(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_forward2, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_backward2, 'BACKWARD'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_set_orientation_on_board: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'albert_set_orientation_on_board',\n            },\n            paramsKeyMap: {\n                DEGREE: 0,\n            },\n            class: 'albert_wheel',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.setOrientationToOnBoard(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.set_orientation(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_set_eye_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, '4'],\n                        [Lang.Blocks.ROBOID_color_yellow, '6'],\n                        [Lang.Blocks.ROBOID_color_green, '2'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, '3'],\n                        [Lang.Blocks.ROBOID_color_blue, '1'],\n                        [Lang.Blocks.ROBOID_color_purple, '5'],\n                        [Lang.Blocks.ROBOID_color_white, '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'albert_set_eye_to',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                COLOR: 1,\n            },\n            class: 'albert_led',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.setEye(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.set_eye(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, '4'],\n                                    [Lang.Blocks.ROBOID_color_yellow, '6'],\n                                    [Lang.Blocks.ROBOID_color_green, '2'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, '3'],\n                                    [Lang.Blocks.ROBOID_color_blue, '1'],\n                                    [Lang.Blocks.ROBOID_color_purple, '5'],\n                                    [Lang.Blocks.ROBOID_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_clear_eye: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'albert_clear_eye',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n            },\n            class: 'albert_led',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.clearEye(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.clear_eye(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_body_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_turn_on, 'ON'],\n                        [Lang.Blocks.ROBOID_turn_off, 'OFF'],\n                    ],\n                    value: 'ON',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'albert_body_led',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'albert_led',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.turnBodyLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.body_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_turn_on, 'ON'],\n                                    [Lang.Blocks.ROBOID_turn_off, 'OFF'],\n                                ],\n                                value: 'ON',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_front_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_turn_on, 'ON'],\n                        [Lang.Blocks.ROBOID_turn_off, 'OFF'],\n                    ],\n                    value: 'ON',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'albert_front_led',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'albert_led',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.turnFrontLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.front_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_turn_on, 'ON'],\n                                    [Lang.Blocks.ROBOID_turn_off, 'OFF'],\n                                ],\n                                value: 'ON',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_beep: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albert_beep',\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.beep(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.beep()',\n                    },\n                ],\n            },\n        },\n        albert_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'albert_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.add_buzzer(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'albert_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.set_buzzer(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_clear_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albert_clear_buzzer',\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.clearBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.clear_buzzer()',\n                        params: [null],\n                    },\n                ],\n            },\n        },\n        albert_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, '4'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, '5'],\n                        [Lang.Blocks.ROBOID_note_d, '6'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, '7'],\n                        [Lang.Blocks.ROBOID_note_e, '8'],\n                        [Lang.Blocks.ROBOID_note_f, '9'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, '10'],\n                        [Lang.Blocks.ROBOID_note_g, '11'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, '12'],\n                        [Lang.Blocks.ROBOID_note_a, '13'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, '14'],\n                        [Lang.Blocks.ROBOID_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'albert_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.play_note(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, '4'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, '5'],\n                                    [Lang.Blocks.ROBOID_note_d, '6'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, '7'],\n                                    [Lang.Blocks.ROBOID_note_e, '8'],\n                                    [Lang.Blocks.ROBOID_note_f, '9'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, '10'],\n                                    [Lang.Blocks.ROBOID_note_g, '11'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, '12'],\n                                    [Lang.Blocks.ROBOID_note_a, '13'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, '14'],\n                                    [Lang.Blocks.ROBOID_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, '4'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, '5'],\n                        [Lang.Blocks.ROBOID_note_d, '6'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, '7'],\n                        [Lang.Blocks.ROBOID_note_e, '8'],\n                        [Lang.Blocks.ROBOID_note_f, '9'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, '10'],\n                        [Lang.Blocks.ROBOID_note_g, '11'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, '12'],\n                        [Lang.Blocks.ROBOID_note_a, '13'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, '14'],\n                        [Lang.Blocks.ROBOID_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'albert_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.play_note_beat(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, '4'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, '5'],\n                                    [Lang.Blocks.ROBOID_note_d, '6'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, '7'],\n                                    [Lang.Blocks.ROBOID_note_e, '8'],\n                                    [Lang.Blocks.ROBOID_note_f, '9'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, '10'],\n                                    [Lang.Blocks.ROBOID_note_g, '11'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, '12'],\n                                    [Lang.Blocks.ROBOID_note_a, '13'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, '14'],\n                                    [Lang.Blocks.ROBOID_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'albert_rest_for',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.rest_beat(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'albert_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albert_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'albert_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'albert_buzzer',\n            isNotFor: ['albert'],\n            func: function(sprite, script) {\n                var robot = Entry.Albert.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Albert.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Albert;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_albert_ai.js",
    "content": "'use strict';\n\nfunction AlbertAiController() {\n\tthis.prevDirection = 0;\n\tthis.prevDirectionFinal = 0;\n\tthis.directionCount = 0;\n\tthis.directionCountFinal = 0;\n\tthis.positionCount = 0;\n\tthis.positionCountFinal = 0;\n\tthis.isBackward = false;\n}\n\nAlbertAiController.prototype.PI = 3.14159265;\nAlbertAiController.prototype.PI2 = 6.2831853;\nAlbertAiController.prototype.GAIN_ANGLE = 30;\nAlbertAiController.prototype.GAIN_ANGLE_FINE = 30;\nAlbertAiController.prototype.GAIN_POSITION_FINE = 30;\nAlbertAiController.prototype.STRAIGHT_SPEED = 50;//30;\nAlbertAiController.prototype.MAX_BASE_SPEED = 50;//30;\nAlbertAiController.prototype.GAIN_BASE_SPEED = 2;//1.5;\nAlbertAiController.prototype.GAIN_POSITION = 70;//52.5;\nAlbertAiController.prototype.POSITION_TOLERANCE_FINE = 3;\nAlbertAiController.prototype.POSITION_TOLERANCE_FINE_LARGE = 5;\nAlbertAiController.prototype.POSITION_TOLERANCE_ROUGH = 5;\nAlbertAiController.prototype.POSITION_TOLERANCE_ROUGH_LARGE = 10;\nAlbertAiController.prototype.ORIENTATION_TOLERANCE_FINAL = 0.087;\nAlbertAiController.prototype.ORIENTATION_TOLERANCE_FINAL_LARGE = 0.122;\nAlbertAiController.prototype.ORIENTATION_TOLERANCE_FINAL_LARGE_LARGE = 0.262;\nAlbertAiController.prototype.ORIENTATION_TOLERANCE_ROUGH = 0.122;\nAlbertAiController.prototype.ORIENTATION_TOLERANCE_ROUGH_LARGE = 0.262;\nAlbertAiController.prototype.ORIENTATION_TOLERANCE_ROUGH_LARGE_LARGE = 0.524;\nAlbertAiController.prototype.MINIMUM_WHEEL_SPEED = 18;\nAlbertAiController.prototype.MINIMUM_WHEEL_SPEED_FINE = 15;\n\nAlbertAiController.prototype.clear = function() {\n\tthis.prevDirection = 0;\n\tthis.prevDirectionFinal = 0;\n\tthis.directionCount = 0;\n\tthis.directionCountFinal = 0;\n\tthis.positionCount = 0;\n\tthis.positionCountFinal = 0;\n};\n\nAlbertAiController.prototype.setBackward = function(backward) {\n\tthis.isBackward = backward;\n};\n\nAlbertAiController.prototype.controlAngleInitial = function(wheels, currentRadian, targetRadian) {\n\tif(this.isBackward) {\n\t\tcurrentRadian += this.PI;\n\t}\n\tvar diff = this.validateRadian(targetRadian - currentRadian);\n\tvar mag = Math.abs(diff);\n\tif (mag < this.ORIENTATION_TOLERANCE_ROUGH) return true;\n\t\n\tvar direction = diff > 0 ? 1 : -1;\n\tif(mag < this.ORIENTATION_TOLERANCE_ROUGH_LARGE && direction * this.prevDirection < 0) return true;\n\tthis.prevDirection = direction;\n\t\n\tvar value = 0;\n\tif(diff > 0) {\n\t\tvalue = Math.log(1 + mag) * this.GAIN_ANGLE;\n\t\tif(value < this.MINIMUM_WHEEL_SPEED) value = this.MINIMUM_WHEEL_SPEED;\n\t} else {\n\t\tvalue = -Math.log(1 + mag) * this.GAIN_ANGLE;\n\t\tif(value > -this.MINIMUM_WHEEL_SPEED) value = -this.MINIMUM_WHEEL_SPEED;\n\t}\n\tvalue = parseInt(value);\n\twheels.left = -value;\n\twheels.right = value;\n\treturn false;\n};\n\nAlbertAiController.prototype.controlAngleFinal = function(wheels, currentRadian, targetRadian) {\n\tvar diff = this.validateRadian(targetRadian - currentRadian);\n\tvar mag = Math.abs(diff);\n\tif(mag < this.ORIENTATION_TOLERANCE_FINAL) return true;\n\n\tvar direction = diff > 0 ? 1 : -1;\n\tif(mag < this.ORIENTATION_TOLERANCE_FINAL_LARGE && direction * this.prevDirectionFinal < 0) return true;\n\tif(mag < this.ORIENTATION_TOLERANCE_FINAL_LARGE_LARGE && direction * this.prevDirectionFinal < 0) {\n\t\tif(++this.directionCountFinal > 3) return true;\n\t}\n\tthis.prevDirectionFinal = direction;\n\t\n\tvar value = 0;\n\tif(diff > 0) {\n\t\tvalue = Math.log(1 + mag) * this.GAIN_ANGLE_FINE;\n\t\tif(value < this.MINIMUM_WHEEL_SPEED) value = this.MINIMUM_WHEEL_SPEED;\n\t} else {\n\t\tvalue = -Math.log(1 + mag) * this.GAIN_ANGLE_FINE;\n\t\tif(value > -this.MINIMUM_WHEEL_SPEED) value = -this.MINIMUM_WHEEL_SPEED;\n\t}\n\tvalue = parseInt(value);\n\twheels.left = -value;\n\twheels.right = value;\n\treturn false;\n};\n\nAlbertAiController.prototype.controlPositionFine = function(wheels, currentX, currentY, currentRadian, targetX, targetY) {\n\tvar targetRadian = -Math.atan2(targetY - currentY, targetX - currentX);\n\tif(this.isBackward) {\n\t\tcurrentRadian += this.PI;\n\t}\n\tvar diff = this.validateRadian(targetRadian - currentRadian);\n\tvar mag = Math.abs(diff);\n\tvar ex = targetX - currentX;\n\tvar ey = targetY - currentY;\n\tvar dist = Math.sqrt(ex * ex + ey * ey);\n\tif(dist < this.POSITION_TOLERANCE_FINE) return true;\n\tif(dist < this.POSITION_TOLERANCE_FINE_LARGE) {\n\t\tif (++this.positionCountFinal > 5) {\n\t\t\tthis.positionCountFinal = 0;\n\t\t\treturn true;\n\t\t}\n\t}\n\tvar value = 0;\n\tif (diff > 0) value = Math.log(1 + mag) * this.GAIN_POSITION_FINE;\n\telse value = -Math.log(1 + mag) * this.GAIN_POSITION_FINE;\n\tif(this.isBackward) {\n\t\tvalue = -value;\n\t}\n\tvalue = parseInt(value);\n\twheels.left = this.MINIMUM_WHEEL_SPEED_FINE - value;\n\twheels.right = this.MINIMUM_WHEEL_SPEED_FINE + value;\n\tif(this.isBackward) {\n\t\twheels.left = -wheels.left;\n\t\twheels.right = -wheels.right;\n\t}\n\treturn false;\n};\n\nAlbertAiController.prototype.controlPosition = function(wheels, currentX, currentY, currentRadian, targetX, targetY) {\n\tvar targetRadian = -Math.atan2(targetY - currentY, targetX - currentX);\n\tif(this.isBackward) {\n\t\tcurrentRadian += this.PI;\n\t}\n\tvar diff = this.validateRadian(targetRadian - currentRadian);\n\tvar mag = Math.abs(diff);\n\tvar ex = targetX - currentX;\n\tvar ey = targetY - currentY;\n\tvar dist = Math.sqrt(ex * ex + ey * ey);\n\tif(dist < this.POSITION_TOLERANCE_ROUGH) return true;\n\tif(dist < this.POSITION_TOLERANCE_ROUGH_LARGE) {\n\t\tif(++this.positionCount > 10) {\n\t\t\tthis.positionCount = 0;\n\t\t\treturn true;\n\t\t}\n\t} else {\n\t\tthis.positionCount = 0;\n\t}\n\tif(mag < 0.01) {\n\t\twheels.left = this.STRAIGHT_SPEED;\n\t\twheels.right = this.STRAIGHT_SPEED;\n\t} else {\n\t\tvar base = (this.MINIMUM_WHEEL_SPEED + 0.5 / mag) * this.GAIN_BASE_SPEED;\n\t\tif(base > this.MAX_BASE_SPEED) base = this.MAX_BASE_SPEED;\n\t\t\n\t\tvar value = 0;\n\t\tif(diff > 0) value = Math.log(1 + mag) * this.GAIN_POSITION;\n\t\telse value = -Math.log(1 + mag) * this.GAIN_POSITION;\n\t\tif(this.isBackward) {\n\t\t\tvalue = -value;\n\t\t}\n\t\tbase = parseInt(base);\n\t\tvalue = parseInt(value);\n\t\twheels.left = base - value;\n\t\twheels.right = base + value;\n\t}\n\tif(this.isBackward) {\n\t\twheels.left = -wheels.left;\n\t\twheels.right = -wheels.right;\n\t}\n\treturn false;\n};\n\nAlbertAiController.prototype.validateRadian = function(radian) {\n\tif(radian > this.PI) return radian - this.PI2;\n\telse if(radian < -this.PI) return radian + this.PI2;\n\treturn radian;\n};\n\nAlbertAiController.prototype.toRadian = function(degree) {\n\treturn degree * 3.14159265 / 180.0;\n};\n\nfunction AlbertAiNavigator() {\n\tthis.controller = new AlbertAiController();\n\tthis.mode = 0;\n\tthis.state = 0;\n\tthis.initialized = false;\n\tthis.currentX = -1;\n\tthis.currentY = -1;\n\tthis.currentTheta = -200;\n\tthis.targetX = -1;\n\tthis.targetY = -1;\n\tthis.targetTheta = -200;\n\tthis.wheels = { completed: false, left: 0, right: 0 };\n}\n\nAlbertAiNavigator.prototype.clear = function() {\n\tthis.mode = 0;\n\tthis.state = 0;\n\tthis.initialized = false;\n\tthis.currentX = -1;\n\tthis.currentY = -1;\n\tthis.currentTheta = -200;\n\tthis.targetX = -1;\n\tthis.targetY = -1;\n\tthis.targetTheta = -200;\n\tthis.wheels.completed = false;\n\tthis.wheels.left = 0;\n\tthis.wheels.right = 0;\n\tthis.controller.clear();\n};\n\nAlbertAiNavigator.prototype.setBackward = function(backward) {\n\tthis.controller.setBackward(backward);\n};\n\nAlbertAiNavigator.prototype.moveTo = function(x, y) {\n\tthis.clear();\n\tthis.targetX = x;\n\tthis.targetY = y;\n\tthis.state = 1;\n\tthis.mode = 1;\n};\n\nAlbertAiNavigator.prototype.turnTo = function(deg) {\n\tthis.clear();\n\tthis.targetTheta = deg;\n\tthis.state = 1;\n\tthis.mode = 2;\n};\n\nAlbertAiNavigator.prototype.handleSensory = function(sensory) {\n\tif(this.mode == 1) {\n\t\tvar x = sensory.positionX;\n\t\tvar y = sensory.positionY;\n\t\tif(x >= 0) this.currentX = x;\n\t\tif(y >= 0) this.currentY = y;\n\t\tthis.currentTheta = sensory.orientation;\n\t\tswitch(this.state) {\n\t\t\tcase 1: {\n\t\t\t\tif(this.initialized == false) {\n\t\t\t\t\tif(this.currentX < 0 || this.currentY < 0) {\n\t\t\t\t\t\tthis.wheels.left = 20;\n\t\t\t\t\t\tthis.wheels.right = -20;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.initialized = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(this.initialized) {\n\t\t\t\t\tvar currentRadian = this.controller.toRadian(this.currentTheta);\n\t\t\t\t\tvar dx = this.targetX - this.currentX;\n\t\t\t\t\tvar dy = this.targetY - this.currentY;\n\t\t\t\t\tvar targetRadian = -Math.atan2(dy, dx);\n\t\t\t\t\tif(this.controller.controlAngleInitial(this.wheels, currentRadian, targetRadian)) {\n\t\t\t\t\t\tthis.state = 2;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 2: {\n\t\t\t\tvar currentRadian = this.controller.toRadian(this.currentTheta);\n\t\t\t\tif(this.controller.controlPosition(this.wheels, this.currentX, this.currentY, currentRadian, this.targetX, this.targetY)) {\n\t\t\t\t\tthis.state = 3;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 3: {\n\t\t\t\tvar currentRadian = this.controller.toRadian(this.currentTheta);\n\t\t\t\tif(this.controller.controlPositionFine(this.wheels, this.currentX, this.currentY, currentRadian, this.targetX, this.targetY)) {\n\t\t\t\t\tthis.clear();\n\t\t\t\t\tthis.wheels.completed = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else if(this.mode == 2) {\n\t\tthis.currentTheta = sensory.orientation;\n\t\tswitch(this.state) {\n\t\t\tcase 1: {\n\t\t\t\tvar currentRadian = this.controller.toRadian(this.currentTheta);\n\t\t\t\tvar targetRadian = this.controller.toRadian(this.targetTheta);\n\t\t\t\tif(this.controller.controlAngleInitial(this.wheels, currentRadian, targetRadian)) {\n\t\t\t\t\tthis.state = 2;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 2: {\n\t\t\t\tvar currentRadian = this.controller.toRadian(this.currentTheta);\n\t\t\t\tvar targetRadian = this.controller.toRadian(this.targetTheta);\n\t\t\t\tif(this.controller.controlAngleFinal(this.wheels, currentRadian, targetRadian)) {\n\t\t\t\t\tthis.clear();\n\t\t\t\t\tthis.wheels.completed = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\treturn this.wheels;\n};\n\nfunction AlbertAiRobot(index) {\n    this.sensory = {\n        signalStrength: 0,\n        leftProximity: 0,\n        rightProximity: 0,\n        accelerationX: 0,\n        accelerationY: 0,\n        accelerationZ: 0,\n        positionX: -1,\n        positionY: -1,\n        orientation: -200,\n        light: 0,\n        micTouch: 0,\n        volumeUpTouch: 0,\n        volumeDownTouch: 0,\n        playTouch: 0,\n        backTouch: 0,\n        oidMode: 0,\n        oid: -1,\n        lift: 0,\n        pulseCount: 0,\n        batteryState: 2,\n        tilt: 0,\n    };\n    this.motoring = {\n        group: 'albertai',\n        module: 'albertai',\n        index,\n    };\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.motionId = 0;\n    this.micClickedId = -1;\n    this.volumeUpClickedId = -1;\n    this.volumeDownClickedId = -1;\n    this.playClickedId = -1;\n    this.backClickedId = -1;\n    this.micLongPressedId = -1;\n    this.volumeUpLongPressedId = -1;\n    this.volumeDownLongPressedId = -1;\n    this.playLongPressedId = -1;\n    this.backLongPressedId = -1;\n    this.micLongLongPressedId = -1;\n    this.volumeUpLongLongPressedId = -1;\n    this.volumeDownLongLongPressedId = -1;\n    this.playLongLongPressedId = -1;\n    this.backLongLongPressedId = -1;\n    this.tapId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.blockId = 0;\n    this.navigationCallback = undefined;\n    this.navigator = undefined;\n    this.motionCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.micClicked = false;\n    this.volumeUpClicked = false;\n    this.volumeDownClicked = false;\n    this.playClicked = false;\n    this.backClicked = false;\n    this.micLongPressed = false;\n    this.volumeUpLongPressed = false;\n    this.volumeDownLongPressed = false;\n    this.playLongPressed = false;\n    this.backLongPressed = false;\n    this.micLongLongPressed = false;\n    this.volumeUpLongLongPressed = false;\n    this.volumeDownLongLongPressed = false;\n    this.playLongLongPressed = false;\n    this.backLongLongPressed = false;\n    this.tap = false;\n    this.tempo = 60;\n    this.timeouts = [];\n}\n\nAlbertAiRobot.prototype.__PORT_MAP = {\n    group: 'albertai',\n    module: 'albertai',\n    leftWheel: 0,\n    rightWheel: 0,\n    leftRgb: '0,0,0',\n    leftRed: 0,\n    leftGreen: 0,\n    leftBlue: 0,\n    rightRgb: '0,0,0',\n    rightRed: 0,\n    rightGreen: 0,\n    rightBlue: 0,\n    buzzer: 0,\n    pulse: 0,\n    pulseId: 0,\n    note: 0,\n    sound: 0,\n    soundRepeat: 1,\n    soundId: 0,\n    boardWidth: 0,\n    boardHeight: 0,\n    motionId: 0,\n    motionType: 0,\n    motionUnit: 0,\n    motionSpeed: 0,\n    motionValue: 0,\n    motionRadius: 0,\n};\n\nAlbertAiRobot.prototype.setZero = function() {\n    const portMap = this.__PORT_MAP;\n    const motoring = this.motoring;\n    for (const port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.motionId = 0;\n    this.micClickedId = -1;\n    this.volumeUpClickedId = -1;\n    this.volumeDownClickedId = -1;\n    this.playClickedId = -1;\n    this.backClickedId = -1;\n    this.micLongPressedId = -1;\n    this.volumeUpLongPressedId = -1;\n    this.volumeDownLongPressedId = -1;\n    this.playLongPressedId = -1;\n    this.backLongPressedId = -1;\n    this.micLongLongPressedId = -1;\n    this.volumeUpLongLongPressedId = -1;\n    this.volumeDownLongLongPressedId = -1;\n    this.playLongLongPressedId = -1;\n    this.backLongLongPressedId = -1;\n    this.tapId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.blockId = 0;\n    this.navigationCallback = undefined;\n    this.navigator = undefined;\n    this.motionCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.micClicked = false;\n    this.volumeUpClicked = false;\n    this.volumeDownClicked = false;\n    this.playClicked = false;\n    this.backClicked = false;\n    this.micLongPressed = false;\n    this.volumeUpLongPressed = false;\n    this.volumeDownLongPressed = false;\n    this.playLongPressed = false;\n    this.backLongPressed = false;\n    this.micLongLongPressed = false;\n    this.volumeUpLongLongPressed = false;\n    this.volumeDownLongLongPressed = false;\n    this.playLongLongPressed = false;\n    this.backLongLongPressed = false;\n    this.tap = false;\n    this.tempo = 60;\n    this.__removeAllTimeouts();\n};\n\nAlbertAiRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nAlbertAiRobot.prototype.afterSend = function(sq) {\n    this.micClicked = false;\n    this.volumeUpClicked = false;\n    this.volumeDownClicked = false;\n    this.playClicked = false;\n    this.backClicked = false;\n    this.micLongPressed = false;\n    this.volumeUpLongPressed = false;\n    this.volumeDownLongPressed = false;\n    this.playLongPressed = false;\n    this.backLongPressed = false;\n    this.micLongLongPressed = false;\n    this.volumeUpLongLongPressed = false;\n    this.volumeDownLongLongPressed = false;\n    this.playLongLongPressed = false;\n    this.backLongLongPressed = false;\n    this.tap = false;\n};\n\nAlbertAiRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nAlbertAiRobot.prototype.__setModule = function() {\n    this.motoring.group = 'albertai';\n    this.motoring.module = 'albertai';\n};\n\nAlbertAiRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    const idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nAlbertAiRobot.prototype.__removeAllTimeouts = function() {\n    const timeouts = this.timeouts;\n    for (const i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nAlbertAiRobot.prototype.__setPulse = function(pulse) {\n    this.pulseId = (this.pulseId % 255) + 1;\n    this.motoring.pulse = pulse;\n    this.motoring.pulseId = this.pulseId;\n};\n\nAlbertAiRobot.prototype.__getNavigator = function() {\n    if(this.navigator == undefined) {\n        this.navigator = new AlbertAiNavigator();\n    }\n    return this.navigator;\n};\n\nAlbertAiRobot.prototype.__cancelNavigation = function() {\n    this.navigationCallback = undefined;\n    if(this.navigator) {\n        this.navigator.clear();\n    }\n};\n\nAlbertAiRobot.prototype.__setMotion = function(type, unit, speed, value, radius) {\n    this.motionId = (this.motionId % 255) + 1;\n    const motoring = this.motoring;\n    motoring.motionType = type;\n    motoring.motionUnit = unit;\n    motoring.motionSpeed = speed;\n    motoring.motionValue = value;\n    motoring.motionRadius = radius;\n    motoring.motionId = this.motionId;\n};\n\nAlbertAiRobot.prototype.__cancelMotion = function() {\n    this.motionCallback = undefined;\n};\n\nAlbertAiRobot.prototype.__runSound = function(sound, count) {\n    if (typeof count != 'number') {\n        count = 1;\n    }\n    if (count < 0) {\n        count = -1;\n    }\n    if (count) {\n        this.soundId = (this.soundId % 255) + 1;\n        const motoring = this.motoring;\n        motoring.sound = sound;\n        motoring.soundRepeat = count;\n        motoring.soundId = this.soundId;\n    }\n};\n\nAlbertAiRobot.prototype.__cancelSound = function() {\n    this.soundCallback = undefined;\n};\n\nAlbertAiRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nAlbertAiRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nAlbertAiRobot.prototype.handleSensory = function() {\n    const self = this;\n    const sensory = self.sensory;\n    \n    self.micClicked = sensory.micClicked == 1;\n    self.volumeUpClicked = sensory.volumeUpClicked == 1;\n    self.volumeDownClicked = sensory.volumeDownClicked == 1;\n    self.playClicked = sensory.playClicked == 1;\n    self.backClicked = sensory.backClicked == 1;\n    self.micLongPressed = sensory.micLongPressed == 1;\n    self.volumeUpLongPressed = sensory.volumeUpLongPressed == 1;\n    self.volumeDownLongPressed = sensory.volumeDownLongPressed == 1;\n    self.playLongPressed = sensory.playLongPressed == 1;\n    self.backLongPressed = sensory.backLongPressed == 1;\n    self.micLongLongPressed = sensory.micLongLongPressed == 1;\n    self.volumeUpLongLongPressed = sensory.volumeUpLongLongPressed == 1;\n    self.volumeDownLongLongPressed = sensory.volumeDownLongLongPressed == 1;\n    self.playLongLongPressed = sensory.playLongLongPressed == 1;\n    self.backLongLongPressed = sensory.backLongLongPressed == 1;\n    self.tap = sensory.tap == 1;\n\n    if (self.motionCallback) {\n        if (sensory.wheelStateId != self.wheelStateId) {\n            self.wheelStateId = sensory.wheelStateId;\n            if (sensory.wheelState == 2) {\n                self.motoring.leftWheel = 0;\n                self.motoring.rightWheel = 0;\n                const callback = self.motionCallback;\n                self.__cancelMotion();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n    if(this.navigationCallback) {\n        if(this.navigator) {\n            var result = this.navigator.handleSensory(this.sensory);\n            this.motoring.leftWheel = result.left;\n            this.motoring.rightWheel = result.right;\n            if(result.completed) {\n                var callback = this.navigationCallback;\n                this.__cancelNavigation();\n                if(callback) callback();\n            }\n        }\n    }\n    if (self.soundCallback) {\n        if (sensory.soundStateId != self.soundStateId) {\n            self.soundStateId = sensory.soundStateId;\n            if (sensory.soundState == 0) {\n                const callback = self.soundCallback;\n                self.__cancelSound();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n};\n\nAlbertAiRobot.prototype.__SENSORS = {\n    SIGNAL_STRENGTH: 'signalStrength',\n    LEFT_PROXIMITY: 'leftProximity',\n    RIGHT_PROXIMITY: 'rightProximity',\n    ACCELERATION_X: 'accelerationX',\n    ACCELERATION_Y: 'accelerationY',\n    ACCELERATION_Z: 'accelerationZ',\n    POSITION_X: 'positionX',\n    POSITION_Y: 'positionY',\n    ORIENTATION: 'orientation',\n    LIGHT: 'light',\n    MIC_TOUCH: 'micTouch',\n    VOLUME_UP_TOUCH: 'volumeUpTouch',\n    VOLUME_DOWN_TOUCH: 'volumeDownTouch',\n    PLAY_TOUCH: 'playTouch',\n    BACK_TOUCH: 'backTouch',\n    OID_MODE: 'oidMode',\n    OID: 'oid',\n    LIFT: 'lift',\n    PULSE_COUNT: 'pulseCount',\n    BATTERY_STATE: 'batteryState',\n    TILT: 'tilt',\n};\n\nAlbertAiRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n\n    const sensor = this.__SENSORS[dev] || dev;\n    return this.sensory[sensor];\n};\n\nAlbertAiRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    const sensory = this.sensory;\n    const dev = script.getField('DEVICE');\n    let value = 0;\n    if(dev.startsWith('TILT')) {\n        if(sensory.tilt === undefined) {\n            if(sensory.accelerationZ < 8192 && sensory.accelerationX > 8192 && sensory.accelerationY > -4096 && sensory.accelerationY < 4096) value = 1;\n            else if(sensory.accelerationZ < 8192 && sensory.accelerationX < -8192 && sensory.accelerationY > -4096 && sensory.accelerationY < 4096) value = -1;\n            else if(sensory.accelerationZ < 8192 && sensory.accelerationY > 8192 && sensory.accelerationX > -4096 && sensory.accelerationX < 4096) value = 2;\n            else if(sensory.accelerationZ < 8192 && sensory.accelerationY < -8192 && sensory.accelerationX > -4096 && sensory.accelerationX < 4096) value = -2;\n            else if(sensory.accelerationZ > 12288 && sensory.accelerationX > -8192 && sensory.accelerationX < 8192 && sensory.accelerationY > -8192 && sensory.accelerationY < 8192) value = 3;\n            else if(sensory.accelerationZ < -12288 && sensory.accelerationX > -4096 && sensory.accelerationX < 4096 && sensory.accelerationY > -4096 && sensory.accelerationY < 4096) value = -3;\n            else value = 0;\n        } else {\n            value = sensory.tilt;\n        }\n        switch(dev) {\n            case 'TILT_FORWARD': return value == 1;\n            case 'TILT_BACKWARD': return value == -1;\n            case 'TILT_LEFT': return value == 2;\n            case 'TILT_RIGHT': return value == -2;\n            case 'TILT_FLIP': return value == 3;\n            case 'TILT_NOT': return value == -3;\n        }\n        return false;\n    } else {\n        switch (dev) {\n            case 'TAP': return this.tap;\n            case 'LIFT': return sensory.lift === 1;\n            case 'BATTERY_NORMAL': return sensory.batteryState === 2;\n            case 'BATTERY_LOW': return sensory.batteryState === 1;\n            case 'BATTERY_EMPTY': return sensory.batteryState === 0;\n        }\n        return false;\n    }\n};\n\nAlbertAiRobot.prototype.checkHandFound = function(script) {\n    this.__setModule();\n    const sensory = this.sensory;\n    return sensory.handFound === undefined ? sensory.leftProximity > 40 || sensory.rightProximity > 40 : sensory.handFound;\n};\n\nAlbertAiRobot.prototype.checkTouchState = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n    const state = script.getField('STATE');\n    switch(dev) {\n        case 'MIC':\n            switch(state) {\n                case 'CLICKED': return this.micClicked;\n                case 'LONG_PRESSED': return this.micLongPressed;\n                case 'LONG_LONG_PRESSED': return this.micLongLongPressed;\n            }\n            break;\n        case 'VOLUME_UP':\n            switch(state) {\n                case 'CLICKED': return this.volumeUpClicked;\n                case 'LONG_PRESSED': return this.volumeUpLongPressed;\n                case 'LONG_LONG_PRESSED': return this.volumeUpLongLongPressed;\n            }\n            break;\n        case 'VOLUME_DOWN':\n            switch(state) {\n                case 'CLICKED': return this.volumeDownClicked;\n                case 'LONG_PRESSED': return this.volumeDownLongPressed;\n                case 'LONG_LONG_PRESSED': return this.volumeDownLongLongPressed;\n            }\n            break;\n        case 'PLAY':\n            switch(state) {\n                case 'CLICKED': return this.playClicked;\n                case 'LONG_PRESSED': return this.playLongPressed;\n                case 'LONG_LONG_PRESSED': return this.playLongLongPressed;\n            }\n            break;\n        case 'BACK':\n            switch(state) {\n                case 'CLICKED': return this.backClicked;\n                case 'LONG_PRESSED': return this.backLongPressed;\n                case 'LONG_LONG_PRESSED': return this.backLongLongPressed;\n            }\n            break;\n    }\n    return false;\n};\n\nAlbertAiRobot.prototype.checkOid = function(script) {\n    this.__setModule();\n    const value = script.getNumberValue('VALUE');\n    return this.sensory.oid == value;\n};\n\nAlbertAiRobot.prototype.__motionUnit = function(type, unit, value, callback) {\n    const motoring = this.motoring;\n    this.__cancelNavigation();\n    this.__cancelMotion();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    if (value && value > 0) {\n        this.__setMotion(type, unit, 0, value, 0); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        callback();\n    }\n};\n\nAlbertAiRobot.prototype.__UNITS = {\n    CM: 1,\n    DEG: 1,\n    SEC: 2,\n    PULSE: 3,\n};\n\nAlbertAiRobot.prototype.moveForwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(2, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(1, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.moveBackwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(1, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(2, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.turnUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (direction == 'LEFT') {\n            if (value < 0) {\n                this.__motionUnit(4, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(3, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (value < 0) {\n                this.__motionUnit(3, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(4, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.pivotUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const wheel = script.getField('WHEEL');\n        const value = script.getNumberValue('VALUE');\n        let unit = script.getField('UNIT');\n        const toward = script.getField('TOWARD');\n\n        unit = this.__UNITS[unit];\n        if (wheel == 'LEFT') {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(6, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(5, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(5, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(6, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(8, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(7, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(7, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(8, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.setWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel = leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel = rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.changeWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel =\n            motoring.leftWheel !== undefined ? motoring.leftWheel + leftVelocity : leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel =\n            motoring.rightWheel !== undefined ? motoring.rightWheel + rightVelocity : rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.setWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel = velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel = velocity;\n        } else {\n            motoring.leftWheel = velocity;\n            motoring.rightWheel = velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.changeWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        } else {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.stop = function(script) {\n    this.__setModule();\n    this.__cancelNavigation();\n    this.__cancelMotion();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.moveToOnBoard = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelNavigation();\n        this.__cancelMotion();\n        const toward = script.getField('TOWARD');\n        let x = script.getNumberValue('X');\n        let y = script.getNumberValue('Y');\n        x = parseInt(x);\n        y = parseInt(y);\n        const navi = this.__getNavigator();\n        if((typeof x == 'number') && (typeof y == 'number') && x >= 0 && y >= 0) {\n            const motoring = this.motoring;\n            motoring.leftWheel = 0;\n            motoring.rightWheel = 0;\n            this.__setPulse(0);\n            this.__setMotion(0, 0, 0, 0, 0);\n            navi.setBackward(toward == 'BACKWARD');\n            navi.moveTo(x, y);\n            this.navigationCallback = () => {\n                script.isMoving = false;\n            };\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.setOrientationToOnBoard = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelNavigation();\n        this.__cancelMotion();\n        let degree = script.getNumberValue('DEGREE');\n        degree = parseInt(degree);\n        if(typeof degree == 'number') {\n            const navi = this.__getNavigator();\n            const motoring = this.motoring;\n            motoring.leftWheel = 0;\n            motoring.rightWheel = 0;\n            this.__setPulse(0);\n            this.__setMotion(0, 0, 0, 0, 0);\n            navi.setBackward(false);\n            navi.turnTo(degree);\n            this.navigationCallback = () => {\n                script.isMoving = false;\n            };\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.__RGB_COLORS = {\n    RED: [255, 0, 0],\n    ORANGE: [255, 63, 0],\n    YELLOW: [255, 255, 0],\n    GREEN: [0, 255, 0],\n    SKY_BLUE: [0, 255, 255],\n    BLUE: [0, 0, 255],\n    VIOLET: [63, 0, 255],\n    PURPLE: [255, 0, 255],\n    WHITE: [255, 255, 255],\n};\n\nAlbertAiRobot.prototype.setEyeColor = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n    const color = script.getField('COLOR');\n\n    const rgb = this.__RGB_COLORS[color];\n    if (rgb) {\n        const motoring = this.motoring;\n        if (eye == 'LEFT') {\n            motoring.leftRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.leftRed = rgb[0];\n            motoring.leftGreen = rgb[1];\n            motoring.leftBlue = rgb[2];\n        } else if (eye == 'RIGHT') {\n            motoring.rightRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.rightRed = rgb[0];\n            motoring.rightGreen = rgb[1];\n            motoring.rightBlue = rgb[2];\n        } else {\n            motoring.leftRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.leftRed = rgb[0];\n            motoring.leftGreen = rgb[1];\n            motoring.leftBlue = rgb[2];\n            motoring.rightRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.rightRed = rgb[0];\n            motoring.rightGreen = rgb[1];\n            motoring.rightBlue = rgb[2];\n        }\n    }\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.pickEyeColor = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n    const color = script.getField('COLOR');\n\n    const red = parseInt(color.slice(1, 3), 16);\n    const green = parseInt(color.slice(3, 5), 16);\n    const blue = parseInt(color.slice(5, 7), 16);\n\n    const motoring = this.motoring;\n    if (eye == 'LEFT') {\n        motoring.leftRgb = `${red},${green},${blue}`;\n        motoring.leftRed = red;\n        motoring.leftGreen = green;\n        motoring.leftBlue = blue;\n    } else if (eye == 'RIGHT') {\n        motoring.rightRgb = `${red},${green},${blue}`;\n        motoring.rightRed = red;\n        motoring.rightGreen = green;\n        motoring.rightBlue = blue;\n    } else {\n        motoring.leftRgb = `${red},${green},${blue}`;\n        motoring.leftRed = red;\n        motoring.leftGreen = green;\n        motoring.leftBlue = blue;\n        motoring.rightRgb = `${red},${green},${blue}`;\n        motoring.rightRed = red;\n        motoring.rightGreen = green;\n        motoring.rightBlue = blue;\n    }\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.setEyeRgb = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    const motoring = this.motoring;\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if (eye == 'LEFT') {\n        if (typeof red == 'number') {\n            motoring.leftRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue = blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n    } else if (eye == 'RIGHT') {\n        if (typeof red == 'number') {\n            motoring.rightRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.rightGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.rightBlue = blue;\n        }\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    } else {\n        if (typeof red == 'number') {\n            motoring.leftRed = red;\n            motoring.rightRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen = green;\n            motoring.rightGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue = blue;\n            motoring.rightBlue = blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    }\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.changeEyeRgb = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    const motoring = this.motoring;\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if (eye == 'LEFT') {\n        if (typeof red == 'number') {\n            motoring.leftRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue += blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n    } else if (eye == 'RIGHT') {\n        if (typeof red == 'number') {\n            motoring.rightRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.rightGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.rightBlue += blue;\n        }\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    } else {\n        if (typeof red == 'number') {\n            motoring.leftRed += red;\n            motoring.rightRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen += green;\n            motoring.rightGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue += blue;\n            motoring.rightBlue += blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    }\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.clearEye = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n\n    const motoring = this.motoring;\n    if (eye == 'LEFT') {\n        motoring.leftRgb = '0,0,0';\n        motoring.leftRed = 0;\n        motoring.leftGreen = 0;\n        motoring.leftBlue = 0;\n    } else if (eye == 'RIGHT') {\n        motoring.rightRgb = '0,0,0';\n        motoring.rightRed = 0;\n        motoring.rightGreen = 0;\n        motoring.rightBlue = 0;\n    } else {\n        motoring.leftRgb = '0,0,0';\n        motoring.leftRed = 0;\n        motoring.leftGreen = 0;\n        motoring.leftBlue = 0;\n        motoring.rightRgb = '0,0,0';\n        motoring.rightRed = 0;\n        motoring.rightGreen = 0;\n        motoring.rightBlue = 0;\n    }\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.__SOUNDS = {\n    BEEP: 1,\n    RANDOM_BEEP: 2,\n    NOISE: 10,\n    SIREN: 3,\n    ENGINE: 4,\n    ROBOT: 5,\n    MARCH: 6,\n    BIRTHDAY: 7,\n    DIBIDIBIDIP: 8,\n    GOOD_JOB: 9,\n};\n\nAlbertAiRobot.prototype.playSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let sound = script.getField('SOUND');\n    let count = script.getNumberValue('COUNT');\n\n    sound = this.__SOUNDS[sound];\n    count = parseInt(count);\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    if (sound && count) {\n        this.__runSound(sound, count);\n    } else {\n        this.__runSound(0);\n    }\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.playSoundUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.__cancelSound();\n\n        let sound = script.getField('SOUND');\n        let count = script.getNumberValue('COUNT');\n        \n        sound = this.__SOUNDS[sound];\n        count = parseInt(count);\n        this.motoring.buzzer = 0;\n        this.motoring.note = 0;\n        if (sound && count) {\n            this.__runSound(sound, count);\n            this.soundCallback = function() {\n                script.isPlaying = false;\n            };\n        } else {\n            this.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    const motoring = this.motoring;\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.clearSound = function(script, motoring) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.__NOTES = {\n    C: 4,\n    'C#': 5,\n    Db: 5,\n    D: 6,\n    'D#': 7,\n    Eb: 7,\n    E: 8,\n    F: 9,\n    'F#': 10,\n    Gb: 10,\n    G: 11,\n    'G#': 12,\n    Ab: 12,\n    A: 13,\n    'A#': 14,\n    Bb: 14,\n    B: 15,\n};\n\nAlbertAiRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let note = script.getField('NOTE');\n    let octave = script.getNumberField('OCTAVE');\n\n    note = parseInt(this.__NOTES[note]);\n    octave = parseInt(octave);\n    const motoring = this.motoring;\n    motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        motoring.note = note + (octave - 1) * 12;\n    } else {\n        motoring.note = 0;\n    }\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.playNoteBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n\n        const motoring = self.motoring;\n        let note = script.getField('NOTE');\n        let octave = script.getNumberField('OCTAVE');\n        let beat = script.getNumberValue('BEAT');\n\n        note = parseInt(this.__NOTES[note]);\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            motoring.note = note;\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        motoring.note = 0;\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    motoring.note = 0;\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n            self.__runSound(0);\n        } else {\n            motoring.note = 0;\n            self.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.motoring.note = 0;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.restBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n        let beat = script.getNumberValue('BEAT');\n\n        const motoring = self.motoring;\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        motoring.note = 0;\n        self.__runSound(0);\n        if (beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nAlbertAiRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nAlbertAiRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nEntry.AlbertAi = {\n    robot: undefined,\n    getRobot() {\n        if(Entry.AlbertAi.robot == undefined) Entry.AlbertAi.robot = new AlbertAiRobot(0);\n        Entry.AlbertAi.robot.setMotoring(Entry.hw.sendQueue);\n        return Entry.AlbertAi.robot;\n    },\n    setZero() {\n        if(Entry.AlbertAi.robot) Entry.AlbertAi.robot.setZero();\n        Entry.hw.update();\n    },\n    afterReceive(pd) {\n        const robot = Entry.AlbertAi.getRobot();\n        if(robot) robot.afterReceive(pd);\n    },\n    afterSend(sq) {\n        const robot = Entry.AlbertAi.getRobot();\n        if(robot) robot.afterSend(sq);\n    },\n    id: '2.A',\n    name: 'albertai',\n    url: 'http://albert.school',\n    imageName: 'albertai.png',\n    title: {\n        en: 'Albert AI',\n        ko: '알버트 AI',\n        jp: 'アルバートAI',\n        vn: 'Albert AI',\n    },\n    monitorTemplate: () => ({\n        imgPath: 'hw/albertai.png',\n        width: 297,\n        height: 512,\n        listPorts: {\n            accelerationX: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            oidMode: {\n                name: Lang.Blocks.ROBOID_sensor_oid_mode,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            oid: {\n                name: Lang.Blocks.ROBOID_sensor_oid,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            lift: {\n                name: Lang.Blocks.ROBOID_sensor_lift,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            positionX: {\n                name: Lang.Blocks.ROBOID_sensor_position_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            positionY: {\n                name: Lang.Blocks.ROBOID_sensor_position_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            orientation: {\n                name: Lang.Blocks.ROBOID_sensor_orientation,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            signalStrength: {\n                name: Lang.Blocks.ROBOID_sensor_signal_strength,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Blocks.ROBOID_monitor_buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: {\n                name: Lang.Blocks.ROBOID_monitor_note,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            leftProximity: {\n                name: Lang.Blocks.ROBOID_sensor_left_proximity,\n                type: 'input',\n                pos: { x: 221, y: 459 },\n            },\n            rightProximity: {\n                name: Lang.Blocks.ROBOID_sensor_right_proximity,\n                type: 'input',\n                pos: { x: 77, y: 459 },\n            },\n            micTouch: {\n                name: Lang.Blocks.ROBOID_sensor_mic_touch,\n                type: 'input',\n                pos: { x: 148, y: 334 },\n            },\n            volumeUpTouch: {\n                name: Lang.Blocks.ROBOID_sensor_volume_up_touch,\n                type: 'input',\n                pos: { x: 204, y: 338 },\n            },\n            volumeDownTouch: {\n                name: Lang.Blocks.ROBOID_sensor_volume_down_touch,\n                type: 'input',\n                pos: { x: 93, y: 338 },\n            },\n            playTouch: {\n                name: Lang.Blocks.ROBOID_sensor_play_touch,\n                type: 'input',\n                pos: { x: 224, y: 418 },\n            },\n            backTouch: {\n                name: Lang.Blocks.ROBOID_sensor_back_touch,\n                type: 'input',\n                pos: { x: 73, y: 418 },\n            },\n            light: {\n                name: Lang.Blocks.ROBOID_sensor_light,\n                type: 'input',\n                pos: { x: 148, y: 463 },\n            },\n            leftWheel: {\n                name: Lang.Blocks.ROBOID_monitor_left_wheel,\n                type: 'output',\n                pos: { x: 260, y: 500 },\n            },\n            rightWheel: {\n                name: Lang.Blocks.ROBOID_monitor_right_wheel,\n                type: 'output',\n                pos: { x: 35, y: 500 },\n            },\n            leftRgb: {\n                name: Lang.Blocks.ROBOID_monitor_left_eye,\n                type: 'output',\n                pos: { x: 214, y: 141 },\n            },\n            rightRgb: {\n                name: Lang.Blocks.ROBOID_monitor_right_eye,\n                type: 'output',\n                pos: { x: 80, y: 141 },\n            },\n        },\n        mode: 'both',\n    }),\n};\n\nEntry.AlbertAi.setLanguage = () => ({\n    ko: {\n        template: {\n            albertai_value: '%1',\n            albertai_hand_found: '손 찾음?',\n            albertai_touch_state: '%1 터치 센서를 %2 ?',\n            albertai_is_oid: 'OID가 %1인가?',\n            albertai_boolean: '%1?',\n            albertai_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n            albertai_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n            albertai_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n            albertai_pivot_around_unit_in_direction: '%1 바퀴 중심으로 %2 %3 %4 방향으로 돌기 %5',\n            albertai_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            albertai_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            albertai_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            albertai_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            albertai_stop: '정지하기 %1',\n            albertai_move_to_x_y_on_board: '밑판 %1 x: %2 y: %3 위치로 이동하기 %4',\n            albertai_set_orientation_on_board: '말판 %1도 방향으로 돌기 %2',\n            albertai_set_eye_to: '%1 눈을 %2 으로 정하기 %3',\n            albertai_pick_eye: '%1 눈을 %2로 정하기 %3',\n            albertai_change_eye_by_rgb: '%1 눈을 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n            albertai_set_eye_to_rgb: '%1 눈을 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n            albertai_clear_eye: '%1 눈 끄기 %2',\n            albertai_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n            albertai_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n            albertai_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            albertai_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            albertai_clear_sound: '소리 끄기 %1',\n            albertai_play_note: '%1 %2 음을 연주하기 %3',\n            albertai_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n            albertai_rest_for: '%1 박자 쉬기 %2',\n            albertai_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            albertai_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n        },\n        Helper: {\n            albertai_value: '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>마이크 터치: 마이크 터치 센서의 값 (터치하면 1, 아니면 0, 초기값: 0)<br/>소리 크게 터치: 소리 크게 터치 센서의 값 (터치하면 1, 아니면 0, 초기값: 0)<br/>소리 작게 터치: 소리 작게 터치 센서의 값 (터치하면 1, 아니면 0, 초기값: 0)<br/>실행 터치: 실행 터치 센서의 값 (터치하면 1, 아니면 0, 초기값: 0)<br/>뒤로 터치: 뒤로 터치 센서의 값 (터치하면 1, 아니면 0, 초기값: 0)<br/>OID 모드: OID 모드의 값 (0: 멀리 떨어짐, 1: 위치 모드, 2: OID 버전 2, 3: OID 버전 3, 15: OID 아님, 초기값: 0)<br/>OID: OID 센서의 값 (값의 범위: -1 ~ 268435455, 초기값: -1)<br/>들어올림: 들어올림 센서의 값 (들어올리면 1, 아니면 0, 초기값: 0)<br/>x 위치: 말판 위에서 로봇의 위치 x좌표 값 (값의 범위: -1 ~ 268435454, 초기값: -1)<br/>y 위치: 말판 위에서 로봇의 위치 y좌표 값 (값의 범위: -1 ~ 268435454, 초기값: -1)<br/>방향: 말판 위에서 로봇의 방향 값 (값의 범위: -179 ~ 180, 초기값: -200)<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.',\n            albertai_hand_found: \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            albertai_touch_state: \"터치 센서를 클릭했으면/길게 눌렀으면/아주 길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            albertai_is_oid: \"OID 센서가 감지한 OID 값이 입력한 숫자와 같으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            albertai_boolean: \"앞으로 기울임: 앞으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집었으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않았으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>두드림: 두드렸으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>들어올림: 들어올렸으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            albertai_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            albertai_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            albertai_turn_unit_in_place: '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            albertai_pivot_around_unit_in_direction: '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 앞쪽/뒤쪽 방향으로 회전합니다.',\n            albertai_change_both_wheels_by: '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            albertai_set_both_wheels_to: '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            albertai_change_wheel_by: '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            albertai_set_wheel_to: '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            albertai_stop: '양쪽 바퀴를 정지합니다.',\n            albertai_move_to_x_y_on_board: '밑판 위에서 입력한 x, y 위치로 이동합니다.',\n            albertai_set_orientation_on_board: '말판 위에서 입력한 각도 방향으로 회전합니다.',\n            albertai_set_eye_to: '왼쪽/오른쪽/양쪽 눈을 선택한 색깔로 켭니다.',\n            albertai_pick_eye: '왼쪽/오른쪽/양쪽 눈을 선택한 색깔로 켭니다.',\n            albertai_change_eye_by_rgb: '왼쪽/오른쪽/양쪽 눈의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            albertai_set_eye_to_rgb: '왼쪽/오른쪽/양쪽 눈의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            albertai_clear_eye: '왼쪽/오른쪽/양쪽 눈을 끕니다.',\n            albertai_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            albertai_play_sound_times_until_done: '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            albertai_change_buzzer_by: '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            albertai_set_buzzer_to: '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n            albertai_clear_sound: '소리를 끕니다.',\n            albertai_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            albertai_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            albertai_rest_for: '입력한 박자만큼 쉽니다.',\n            albertai_change_tempo_by: '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            albertai_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n        },\n        Blocks: {\n            ROBOID_monitor_left_wheel: '왼쪽 바퀴',\n            ROBOID_monitor_right_wheel: '오른쪽 바퀴',\n            ROBOID_monitor_left_eye: '왼쪽 눈',\n            ROBOID_monitor_right_eye: '오른쪽 눈',\n            ROBOID_monitor_buzzer: '버저',\n            ROBOID_monitor_note: '음표',\n            ROBOID_sensor_signal_strength: '신호 세기',\n            ROBOID_sensor_left_proximity: '왼쪽 근접 센서',\n            ROBOID_sensor_right_proximity: '오른쪽 근접 센서',\n            ROBOID_sensor_acceleration_x: 'x축 가속도',\n            ROBOID_sensor_acceleration_y: 'y축 가속도',\n            ROBOID_sensor_acceleration_z: 'z축 가속도',\n            ROBOID_sensor_position_x: 'x 위치',\n            ROBOID_sensor_position_y: 'y 위치',\n            ROBOID_sensor_orientation: '방향',\n            ROBOID_sensor_light: '밝기',\n            ROBOID_sensor_mic_touch: '마이크 터치',\n            ROBOID_sensor_volume_up_touch: '소리 크게 터치',\n            ROBOID_sensor_volume_down_touch: '소리 작게 터치',\n            ROBOID_sensor_play_touch: '실행 터치',\n            ROBOID_sensor_back_touch: '뒤로 터치',\n            ROBOID_sensor_oid_mode: 'OID 모드',\n            ROBOID_sensor_oid: 'OID',\n            ROBOID_sensor_lift: '들어올림',\n            ROBOID_button_mic: '마이크',\n            ROBOID_button_volume_up: '소리 크게',\n            ROBOID_button_volume_down: '소리 작게',\n            ROBOID_button_play: '실행',\n            ROBOID_button_back: '뒤로',\n            ROBOID_button_clicked: '클릭했는가',\n            ROBOID_button_long_pressed: '오래 눌렀는가(1.5초)',\n            ROBOID_button_long_long_pressed: '아주 오래 눌렀는가(3초)',\n            ROBOID_tilt_forward: '앞으로 기울임',\n            ROBOID_tilt_backward: '뒤로 기울임',\n            ROBOID_tilt_left: '왼쪽으로 기울임',\n            ROBOID_tilt_right: '오른쪽으로 기울임',\n            ROBOID_tilt_flip: '거꾸로 뒤집음',\n            ROBOID_tilt_not: '기울이지 않음',\n            ROBOID_tap: '두드림',\n            ROBOID_lift: '들어올림',\n            ROBOID_battery_normal: '배터리 정상',\n            ROBOID_battery_low: '배터리 부족',\n            ROBOID_battery_empty: '배터리 없음',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '초',\n            ROBOID_unit_pulse: '펄스',\n            ROBOID_unit_deg: '도',\n            ROBOID_left: '왼쪽',\n            ROBOID_right: '오른쪽',\n            ROBOID_both: '양쪽',\n            ROBOID_forward: '앞쪽',\n            ROBOID_backward: '뒤쪽',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_orange: '주황색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_violet: '보라색',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_sound_beep: '삐',\n            ROBOID_sound_random_beep: '무작위 삐',\n            ROBOID_sound_noise: '지지직',\n            ROBOID_sound_siren: '사이렌',\n            ROBOID_sound_engine: '엔진',\n            ROBOID_sound_robot: '로봇',\n            ROBOID_sound_dibidibidip: '디비디비딥',\n            ROBOID_sound_good_job: '잘 했어요',\n            ROBOID_sound_march: '행진',\n            ROBOID_sound_birthday: '생일',\n            ROBOID_note_c: '도',\n            ROBOID_note_c_sharp: '도♯(레♭)',\n            ROBOID_note_d: '레',\n            ROBOID_note_d_sharp: '레♯(미♭)',\n            ROBOID_note_e: '미',\n            ROBOID_note_f: '파',\n            ROBOID_note_f_sharp: '파♯(솔♭)',\n            ROBOID_note_g: '솔',\n            ROBOID_note_g_sharp: '솔♯(라♭)',\n            ROBOID_note_a: '라',\n            ROBOID_note_a_sharp: '라♯(시♭)',\n            ROBOID_note_b: '시',\n        },\n    },\n    en: {\n        template: {\n            albertai_value: '%1',\n            albertai_hand_found: 'hand found?',\n            albertai_touch_state: '%1 touch sensor %2 ?',\n            albertai_is_oid: 'oid %1?',\n            albertai_boolean: '%1?',\n            albertai_move_forward_unit: 'move forward %1 %2 %3',\n            albertai_move_backward_unit: 'move backward %1 %2 %3',\n            albertai_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            albertai_pivot_around_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n            albertai_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            albertai_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            albertai_change_wheel_by: 'change %1 wheel by %2 %3',\n            albertai_set_wheel_to: 'set %1 wheel to %2 %3',\n            albertai_stop: 'stop %1',\n            albertai_move_to_x_y_on_board: 'move %1 to x: %2 y: %3 on board %4',\n            albertai_set_orientation_on_board: 'turn towards %1 degrees on board %2',\n            albertai_set_eye_to: 'set %1 eye to %2 %3',\n            albertai_pick_eye: 'set %1 eye to %2 %3',\n            albertai_change_eye_by_rgb: 'change %1 eye by r: %2 g: %3 b: %4 %5',\n            albertai_set_eye_to_rgb: 'set %1 eye to r: %2 g: %3 b: %4 %5',\n            albertai_clear_eye: 'clear %1 eye %2',\n            albertai_play_sound_times: 'play sound %1 %2 times %3',\n            albertai_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            albertai_change_buzzer_by: 'change buzzer by %1 %2',\n            albertai_set_buzzer_to: 'set buzzer to %1 %2',\n            albertai_clear_sound: 'clear sound %1',\n            albertai_play_note: 'play note %1 %2 %3',\n            albertai_play_note_for: 'play note %1 %2 for %3 beats %4',\n            albertai_rest_for: 'rest for %1 beats %2',\n            albertai_change_tempo_by: 'change tempo by %1 %2',\n            albertai_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            albertai_value: \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>mic touch: value of mic touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>volume up touch: value of volume up touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>volume down touch: value of volume down touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>play touch: value of play touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>back touch: value of back touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>oid mode: oid mode value (0: far, 1: position mode, 2: oid version 2, 3: oid version 3, 15: not oid, initial value: 0)<br/>oid: value of oid sensor (range: -1 ~ 268435455, initial value: -1)<br/>lift: value of lift sensor (when lifted 1, otherwise 0, initial value: 0)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 268435454, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 268435454, initial value: -1)<br/>orientation: orientation angle value (degree) of robot on the board (range: -179 ~ 180, initial value: -200)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            albertai_hand_found: 'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            albertai_touch_state: 'If the touch sensor clicked/long-pressed/long-long-pressed, true, otherwise false.',\n            albertai_is_oid: 'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            albertai_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>tap: If tapped, true, otherwise false<br/>lift: If lifted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            albertai_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            albertai_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            albertai_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            albertai_pivot_around_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            albertai_change_both_wheels_by: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albertai_set_both_wheels_to: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albertai_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albertai_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albertai_stop: 'Stops both wheels.',\n            albertai_move_to_x_y_on_board: 'Moves to the entered x, y position on the board.',\n            albertai_set_orientation_on_board: 'Turns toward the entered angle (degrees) on the board.',\n            albertai_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            albertai_pick_eye: 'Turns left/right/both eyes to the selected color.',\n            albertai_change_eye_by_rgb: 'Adds the entered values to the current R, G, B values of left/right/both eyes, respectively.',\n            albertai_set_eye_to_rgb: 'Sets the R, G, B values of left/right/both eyes to the entered values.',\n            albertai_clear_eye: 'Turns off the left/right/both eyes.',\n            albertai_play_sound_times: 'Plays the selected sound as many times as entered.',\n            albertai_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            albertai_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            albertai_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            albertai_clear_sound: 'Turns off sound.',\n            albertai_play_note: 'It sounds the selected tone and octave.',\n            albertai_play_note_for: 'It sounds the selected tone and octave as much as the beat you entered.',\n            albertai_rest_for: 'Rests as much as the beat you entered.',\n            albertai_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            albertai_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_monitor_left_eye: 'left eye',\n            ROBOID_monitor_right_eye: 'right eye',\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_left_proximity: 'left proximity',\n            ROBOID_sensor_right_proximity: 'right proximity',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_position_x: 'x position',\n            ROBOID_sensor_position_y: 'y position',\n            ROBOID_sensor_orientation: 'orientation',\n            ROBOID_sensor_light: 'light',\n            ROBOID_sensor_mic_touch: 'mic touch',\n            ROBOID_sensor_volume_up_touch: 'volume up touch',\n            ROBOID_sensor_volume_down_touch: 'volume down touch',\n            ROBOID_sensor_play_touch: 'play touch',\n            ROBOID_sensor_back_touch: 'back touch',\n            ROBOID_sensor_oid_mode: 'oid mode',\n            ROBOID_sensor_oid: 'oid',\n            ROBOID_sensor_lift: 'lift',\n            ROBOID_button_mic: 'mic',\n            ROBOID_button_volume_up: 'volume up',\n            ROBOID_button_volume_down: 'volume down',\n            ROBOID_button_play: 'play',\n            ROBOID_button_back: 'back',\n            ROBOID_button_clicked: 'clicked',\n            ROBOID_button_long_pressed: 'long-pressed (1.5 secs)',\n            ROBOID_button_long_long_pressed: 'long-long-pressed (3 secs)',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_tap: 'tap',\n            ROBOID_lift: 'lift',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_forward: 'forward',\n            ROBOID_backward: 'backward',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n    jp: {\n        template: {\n            albertai_value: '%1',\n            albertai_hand_found: '手を見つけたか?',\n            albertai_touch_state: '%1 タッチセンサーを %2 ?',\n            albertai_is_oid: 'OIDが %1ですか?',\n            albertai_boolean: '%1?',\n            albertai_move_forward_unit: '前へ%1%2移動する %3',\n            albertai_move_backward_unit: '後ろへ%1%2移動する %3',\n            albertai_turn_unit_in_place: '%1へ%2%3その場で回す %4',\n            albertai_pivot_around_unit_in_direction: '%1車輪を中心に%2%3%4方向に回す %5',\n            albertai_change_both_wheels_by: '左車輪を%1右車輪を%2ずつ変える %3',\n            albertai_set_both_wheels_to: '左車輪を%1右車輪を%2にする %3',\n            albertai_change_wheel_by: '%1車輪を%2ずつ変える %3',\n            albertai_set_wheel_to: '%1車輪を%2にする %3',\n            albertai_stop: '停止する %1',\n            albertai_move_to_x_y_on_board: 'ボード板上で %1 x: %2 y: %3 位置に移動する %4',\n            albertai_set_orientation_on_board: 'ボード板上で %1 度に向ける %2',\n            albertai_set_eye_to: '%1眼を%2にする %3',\n            albertai_pick_eye: '%1眼を%2にする %3',\n            albertai_change_eye_by_rgb: '%1眼をR:%2G:%3B:%4ずつ変える %5',\n            albertai_set_eye_to_rgb: '%1眼をR:%2G:%3B:%4にする %5',\n            albertai_clear_eye: '%1眼を消す %2',\n            albertai_play_sound_times: '%1音を%2回鳴らす %3',\n            albertai_play_sound_times_until_done: '終わるまで%1音を%2回鳴らす %3',\n            albertai_change_buzzer_by: 'ブザー音を%1ずつ変える %2',\n            albertai_set_buzzer_to: 'ブザー音を%1にする %2',\n            albertai_clear_sound: '音を消す %1',\n            albertai_play_note: '%1%2音を鳴らす %3',\n            albertai_play_note_for: '%1%2音を%3拍鳴らす %4',\n            albertai_rest_for: '%1拍休む %2',\n            albertai_change_tempo_by: 'テンポを%1ずつ変える %2',\n            albertai_set_tempo_to: 'テンポを%1BPMにする %2',\n        },\n        Helper: {\n            albertai_value: \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>mic touch: value of mic touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>volume up touch: value of volume up touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>volume down touch: value of volume down touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>play touch: value of play touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>back touch: value of back touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>oid mode: oid mode value (0: far, 1: position mode, 2: oid version 2, 3: oid version 3, 15: not oid, initial value: 0)<br/>oid: value of oid sensor (range: -1 ~ 268435455, initial value: -1)<br/>lift: value of lift sensor (when lifted 1, otherwise 0, initial value: 0)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 268435454, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 268435454, initial value: -1)<br/>orientation: orientation angle value (degree) of robot on the board (range: -179 ~ 180, initial value: -200)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            albertai_hand_found: 'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            albertai_touch_state: 'If the touch sensor clicked/long-pressed/long-long-pressed, true, otherwise false.',\n            albertai_is_oid: 'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            albertai_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>tap: If tapped, true, otherwise false<br/>lift: If lifted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            albertai_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            albertai_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            albertai_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            albertai_pivot_around_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            albertai_change_both_wheels_by: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albertai_set_both_wheels_to: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albertai_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albertai_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albertai_stop: 'Stops both wheels.',\n            albertai_move_to_x_y_on_board: 'Moves to the entered x, y position on the board.',\n            albertai_set_orientation_on_board: 'Rotates toward the entered angle (degrees) on the board.',\n            albertai_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            albertai_pick_eye: 'Turns left/right/both eyes to the selected color.',\n            albertai_change_eye_by_rgb: 'Adds the entered values to the current R, G, B values of left/right/both eyes, respectively.',\n            albertai_set_eye_to_rgb: 'Sets the R, G, B values of left/right/both eyes to the entered values.',\n            albertai_clear_eye: 'Turns off the left/right/both eyes.',\n            albertai_play_sound_times: 'Plays the selected sound as many times as entered.',\n            albertai_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            albertai_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            albertai_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            albertai_clear_sound: 'Turns off sound.',\n            albertai_play_note: 'It sounds the selected tone and octave.',\n            albertai_play_note_for: 'It sounds the selected tone and octave as much as the beat you entered.',\n            albertai_rest_for: 'Rests as much as the beat you entered.',\n            albertai_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            albertai_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_left_wheel: '左車輪',\n            ROBOID_monitor_right_wheel: '右車輪',\n            ROBOID_monitor_left_eye: '左眼',\n            ROBOID_monitor_right_eye: '右眼',\n            ROBOID_monitor_buzzer: 'ブザー',\n            ROBOID_monitor_note: '音符',\n            ROBOID_sensor_signal_strength: '信号強度',\n            ROBOID_sensor_left_proximity: '左近接センサー',\n            ROBOID_sensor_right_proximity: '右近接センサー',\n            ROBOID_sensor_acceleration_x: 'x軸加速度',\n            ROBOID_sensor_acceleration_y: 'y軸加速度',\n            ROBOID_sensor_acceleration_z: 'z軸加速度',\n            ROBOID_sensor_position_x: 'x位置',\n            ROBOID_sensor_position_y: 'y位置',\n            ROBOID_sensor_orientation: '方向',\n            ROBOID_sensor_light: '照度',\n            ROBOID_sensor_mic_touch: 'マイクタッチ',\n            ROBOID_sensor_volume_up_touch: '音量大タッチ',\n            ROBOID_sensor_volume_down_touch: '音量小タッチ',\n            ROBOID_sensor_play_touch: '実行タッチ',\n            ROBOID_sensor_back_touch: 'もどるタッチ',\n            ROBOID_sensor_oid_mode: 'OIDモード',\n            ROBOID_sensor_oid: 'OID',\n            ROBOID_sensor_lift: '持ち上ぐ',\n            ROBOID_button_mic: 'マイク',\n            ROBOID_button_volume_up: '音量大',\n            ROBOID_button_volume_down: '音量小',\n            ROBOID_button_play: '実行',\n            ROBOID_button_back: 'もどる',\n            ROBOID_button_clicked: 'クリックしたか',\n            ROBOID_button_long_pressed: '長く押したか(1.5秒)',\n            ROBOID_button_long_long_pressed: '非常に長く押したか(3秒)',\n            ROBOID_tilt_forward: '前に傾けたか',\n            ROBOID_tilt_backward: '後に傾けたか',\n            ROBOID_tilt_left: '左に傾けたか',\n            ROBOID_tilt_right: '右に傾けたか',\n            ROBOID_tilt_flip: '上下裏返したか',\n            ROBOID_tilt_not: '傾けなかったか',\n            ROBOID_tap: '叩いたか',\n            ROBOID_lift: '持ち上げるか',\n            ROBOID_battery_normal: '電池が正常か',\n            ROBOID_battery_low: '電池が足りないか',\n            ROBOID_battery_empty: '電池がないか',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '秒',\n            ROBOID_unit_pulse: 'パルス',\n            ROBOID_unit_deg: '度',\n            ROBOID_left: '左',\n            ROBOID_right: '右',\n            ROBOID_both: '両',\n            ROBOID_forward: '前',\n            ROBOID_backward: '後',\n            ROBOID_color_red: '赤色',\n            ROBOID_color_orange: '橙色',\n            ROBOID_color_yellow: '黄色',\n            ROBOID_color_green: '緑色',\n            ROBOID_color_sky_blue: '水色',\n            ROBOID_color_blue: '青色',\n            ROBOID_color_violet: '青紫色',\n            ROBOID_color_purple: '紫色',\n            ROBOID_color_white: '白色',\n            ROBOID_sound_beep: 'ビープ',\n            ROBOID_sound_random_beep: 'ランダムビープ',\n            ROBOID_sound_noise: 'ノイズ',\n            ROBOID_sound_siren: 'サイレン',\n            ROBOID_sound_engine: 'エンジン',\n            ROBOID_sound_robot: 'ロボット',\n            ROBOID_sound_dibidibidip: 'ディバディバディップ',\n            ROBOID_sound_good_job: 'よくやった',\n            ROBOID_sound_march: '行進',\n            ROBOID_sound_birthday: '誕生',\n            ROBOID_note_c: 'ド',\n            ROBOID_note_c_sharp: 'ド♯(レ♭)',\n            ROBOID_note_d: 'レ',\n            ROBOID_note_d_sharp: 'レ♯(ミ♭)',\n            ROBOID_note_e: 'ミ',\n            ROBOID_note_f: 'ファ',\n            ROBOID_note_f_sharp: 'ファ♯(ソ♭)',\n            ROBOID_note_g: 'ソ',\n            ROBOID_note_g_sharp: 'ソ♯(ラ♭)',\n            ROBOID_note_a: 'ラ',\n            ROBOID_note_a_sharp: 'ラ♯(シ♭)',\n            ROBOID_note_b: 'シ',\n        },\n    },\n    vn: {\n        template: {\n            albertai_value: '%1',\n            albertai_hand_found: 'hand found?',\n            albertai_touch_state: '%1 touch sensor %2 ?',\n            albertai_is_oid: 'oid %1?',\n            albertai_boolean: '%1?',\n            albertai_move_forward_unit: 'move forward %1 %2 %3',\n            albertai_move_backward_unit: 'move backward %1 %2 %3',\n            albertai_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            albertai_pivot_around_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n            albertai_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            albertai_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            albertai_change_wheel_by: 'change %1 wheel by %2 %3',\n            albertai_set_wheel_to: 'set %1 wheel to %2 %3',\n            albertai_stop: 'stop %1',\n            albertai_set_eye_to: 'set %1 eye to %2 %3',\n            albertai_pick_eye: 'set %1 eye to %2 %3',\n            albertai_change_eye_by_rgb: 'change %1 eye by r: %2 g: %3 b: %4 %5',\n            albertai_set_eye_to_rgb: 'set %1 eye to r: %2 g: %3 b: %4 %5',\n            albertai_clear_eye: 'clear %1 eye %2',\n            albertai_play_sound_times: 'play sound %1 %2 times %3',\n            albertai_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            albertai_change_buzzer_by: 'change buzzer by %1 %2',\n            albertai_set_buzzer_to: 'set buzzer to %1 %2',\n            albertai_clear_sound: 'clear sound %1',\n            albertai_play_note: 'play note %1 %2 %3',\n            albertai_play_note_for: 'play note %1 %2 for %3 beats %4',\n            albertai_rest_for: 'rest for %1 beats %2',\n            albertai_change_tempo_by: 'change tempo by %1 %2',\n            albertai_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            albertai_value: \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>mic touch: value of mic touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>volume up touch: value of volume up touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>volume down touch: value of volume down touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>play touch: value of play touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>back touch: value of back touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>oid mode: oid mode value (0: far, 1: position mode, 2: oid version 2, 3: oid version 3, 15: not oid, initial value: 0)<br/>oid: value of oid sensor (range: -1 ~ 268435455, initial value: -1)<br/>lift: value of lift sensor (when lifted 1, otherwise 0, initial value: 0)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 268435454, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 268435454, initial value: -1)<br/>orientation: orientation angle value (degree) of robot on the board (range: -179 ~ 180, initial value: -200)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            albertai_hand_found: 'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            albertai_touch_state: 'If the touch sensor clicked/long-pressed/long-long-pressed, true, otherwise false.',\n            albertai_is_oid: 'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            albertai_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>tap: If tapped, true, otherwise false<br/>lift: If lifted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            albertai_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            albertai_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            albertai_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            albertai_pivot_around_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            albertai_change_both_wheels_by: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albertai_set_both_wheels_to: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albertai_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            albertai_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            albertai_stop: 'Stops both wheels.',\n            albertai_move_to_x_y_on_board: 'Moves to the entered x, y position on the board.',\n            albertai_set_orientation_on_board: 'Rotates toward the entered angle (degrees) on the board.',\n            albertai_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            albertai_pick_eye: 'Turns left/right/both eyes to the selected color.',\n            albertai_change_eye_by_rgb: 'Adds the entered values to the current R, G, B values of left/right/both eyes, respectively.',\n            albertai_set_eye_to_rgb: 'Sets the R, G, B values of left/right/both eyes to the entered values.',\n            albertai_clear_eye: 'Turns off the left/right/both eyes.',\n            albertai_play_sound_times: 'Plays the selected sound as many times as entered.',\n            albertai_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            albertai_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            albertai_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            albertai_clear_sound: 'Turns off sound.',\n            albertai_play_note: 'It sounds the selected tone and octave.',\n            albertai_play_note_for: 'It sounds the selected tone and octave as much as the beat you entered.',\n            albertai_rest_for: 'Rests as much as the beat you entered.',\n            albertai_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            albertai_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_monitor_left_eye: 'left eye',\n            ROBOID_monitor_right_eye: 'right eye',\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_left_proximity: 'left proximity',\n            ROBOID_sensor_right_proximity: 'right proximity',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_position_x: 'x position',\n            ROBOID_sensor_position_y: 'y position',\n            ROBOID_sensor_orientation: 'orientation',\n            ROBOID_sensor_light: 'light',\n            ROBOID_sensor_mic_touch: 'mic touch',\n            ROBOID_sensor_volume_up_touch: 'volume up touch',\n            ROBOID_sensor_volume_down_touch: 'volume down touch',\n            ROBOID_sensor_play_touch: 'play touch',\n            ROBOID_sensor_back_touch: 'back touch',\n            ROBOID_sensor_oid_mode: 'oid mode',\n            ROBOID_sensor_oid: 'oid',\n            ROBOID_sensor_lift: 'lift',\n            ROBOID_button_mic: 'mic',\n            ROBOID_button_volume_up: 'volume up',\n            ROBOID_button_volume_down: 'volume down',\n            ROBOID_button_play: 'play',\n            ROBOID_button_back: 'back',\n            ROBOID_button_clicked: 'clicked',\n            ROBOID_button_long_pressed: 'long-pressed (1.5 secs)',\n            ROBOID_button_long_long_pressed: 'long-long-pressed (3 secs)',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_tap: 'tap',\n            ROBOID_lift: 'lift',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_forward: 'forward',\n            ROBOID_backward: 'backward',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n});\n\nEntry.AlbertAi.blockMenuBlocks = [\n    'albertai_value',\n    'albertai_hand_found',\n    'albertai_touch_state',\n    'albertai_is_oid',\n    'albertai_boolean',\n    'albertai_move_forward_unit',\n    'albertai_move_backward_unit',\n    'albertai_turn_unit_in_place',\n    'albertai_pivot_around_unit_in_direction',\n    'albertai_change_both_wheels_by',\n    'albertai_set_both_wheels_to',\n    'albertai_change_wheel_by',\n    'albertai_set_wheel_to',\n    'albertai_stop',\n    'albertai_move_to_x_y_on_board',\n    'albertai_set_orientation_on_board',\n    'albertai_set_eye_to',\n    'albertai_pick_eye',\n    'albertai_change_eye_by_rgb',\n    'albertai_set_eye_to_rgb',\n    'albertai_clear_eye',\n    'albertai_play_sound_times',\n    'albertai_play_sound_times_until_done',\n    'albertai_change_buzzer_by',\n    'albertai_set_buzzer_to',\n    'albertai_clear_sound',\n    'albertai_play_note',\n    'albertai_play_note_for',\n    'albertai_rest_for',\n    'albertai_change_tempo_by',\n    'albertai_set_tempo_to',\n];\n\nEntry.AlbertAi.getBlocks = function() {\n    return {\n        albertai_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                        [Lang.Blocks.ROBOID_sensor_right_proximity, 'RIGHT_PROXIMITY'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                        [Lang.Blocks.ROBOID_sensor_mic_touch, 'MIC_TOUCH'],\n                        [Lang.Blocks.ROBOID_sensor_volume_up_touch, 'VOLUME_UP_TOUCH'],\n                        [Lang.Blocks.ROBOID_sensor_volume_down_touch, 'VOLUME_DOWN_TOUCH'],\n                        [Lang.Blocks.ROBOID_sensor_play_touch, 'PLAY_TOUCH'],\n                        [Lang.Blocks.ROBOID_sensor_back_touch, 'BACK_TOUCH'],\n                        [Lang.Blocks.ROBOID_sensor_oid_mode, 'OID_MODE'],\n                        [Lang.Blocks.ROBOID_sensor_oid, 'OID'],\n                        [Lang.Blocks.ROBOID_sensor_lift, 'LIFT'],\n                        [Lang.Blocks.ROBOID_sensor_position_x, 'POSITION_X'],\n                        [Lang.Blocks.ROBOID_sensor_position_y, 'POSITION_Y'],\n                        [Lang.Blocks.ROBOID_sensor_orientation, 'ORIENTATION'],\n                        [Lang.Blocks.ROBOID_sensor_light, 'LIGHT'],\n                        [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                    ],\n                    value: 'LEFT_PROXIMITY',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albertai_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'albertai_sensor',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                                    [Lang.Blocks.ROBOID_sensor_right_proximity, 'RIGHT_PROXIMITY'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                                    [Lang.Blocks.ROBOID_sensor_mic_touch, 'MIC_TOUCH'],\n                                    [Lang.Blocks.ROBOID_sensor_volume_up_touch, 'VOLUME_UP_TOUCH'],\n                                    [Lang.Blocks.ROBOID_sensor_volume_down_touch, 'VOLUME_DOWN_TOUCH'],\n                                    [Lang.Blocks.ROBOID_sensor_play_touch, 'PLAY_TOUCH'],\n                                    [Lang.Blocks.ROBOID_sensor_back_touch, 'BACK_TOUCH'],\n                                    [Lang.Blocks.ROBOID_sensor_oid_mode, 'OID_MODE'],\n                                    [Lang.Blocks.ROBOID_sensor_oid, 'OID'],\n                                    [Lang.Blocks.ROBOID_sensor_lift, 'LIFT'],\n                                    [Lang.Blocks.ROBOID_sensor_position_x, 'POSITION_X'],\n                                    [Lang.Blocks.ROBOID_sensor_position_y, 'POSITION_Y'],\n                                    [Lang.Blocks.ROBOID_sensor_orientation, 'ORIENTATION'],\n                                    [Lang.Blocks.ROBOID_sensor_light, 'LIGHT'],\n                                    [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                                ],\n                                value: 'LEFT_PROXIMITY',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_hand_found: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'albertai_hand_found',\n            },\n            class: 'albertai_sensor',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.checkHandFound(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.hand_found()',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        albertai_touch_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_button_mic, 'MIC'],\n                        [Lang.Blocks.ROBOID_button_volume_up, 'VOLUME_UP'],\n                        [Lang.Blocks.ROBOID_button_volume_down, 'VOLUME_DOWN'],\n                        [Lang.Blocks.ROBOID_button_play, 'PLAY'],\n                        [Lang.Blocks.ROBOID_button_back, 'BACK'],\n                    ],\n                    value: 'MIC',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_button_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_button_long_pressed, 'LONG_PRESSED'],\n                        [Lang.Blocks.ROBOID_button_long_long_pressed, 'LONG_LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'albertai_touch_state',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                STATE: 1,\n            },\n            class: 'albertai_sensor',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.checkTouchState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.is_touch(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_button_mic, 'MIC'],\n                                    [Lang.Blocks.ROBOID_button_volume_up, 'VOLUME_UP'],\n                                    [Lang.Blocks.ROBOID_button_volume_down, 'VOLUME_DOWN'],\n                                    [Lang.Blocks.ROBOID_button_play, 'PLAY'],\n                                    [Lang.Blocks.ROBOID_button_back, 'BACK'],\n                                ],\n                                value: 'MIC',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_button_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_button_long_pressed, 'LONG_PRESSED'],\n                                    [Lang.Blocks.ROBOID_button_long_long_pressed, 'LONG_LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_is_oid: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'albertai_is_oid',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'albertai_sensor',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.checkOid(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.is_oid(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        albertai_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.ROBOID_tap, 'TAP'],\n                        [Lang.Blocks.ROBOID_lift, 'LIFT'],\n                        [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albertai_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'albertai_sensor',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.ROBOID_tap, 'TAP'],\n                                    [Lang.Blocks.ROBOID_lift, 'LIFT'],\n                                    [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'albertai_move_forward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.move_forward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'albertai_move_backward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.move_backward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'albertai_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_pivot_around_unit_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_backward, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'albertai_pivot_around_unit_in_direction',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VALUE: 1,\n                UNIT: 2,\n                TOWARD: 3,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.pivotUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.pivot(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_backward, 'BACKWARD'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_change_both_wheels_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'albertai_change_both_wheels_by',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_set_both_wheels_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'albertai_set_both_wheels_to',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'albertai_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'albertai_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albertai_stop',\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.stop()',\n                    },\n                ],\n            },\n        },\n        albertai_move_to_x_y_on_board: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_forward2, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_backward2, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'albertai_move_to_x_y_on_board',\n            },\n            paramsKeyMap: {\n                TOWARD: 0,\n                X: 1,\n                Y: 2,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func: function(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.moveToOnBoard(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.move_to(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_forward2, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_backward2, 'BACKWARD'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_set_orientation_on_board: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'albertai_set_orientation_on_board',\n            },\n            paramsKeyMap: {\n                DEGREE: 0,\n            },\n            class: 'albertai_wheel',\n            isNotFor: ['albertai'],\n            func: function(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.setOrientationToOnBoard(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.set_orientation(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_set_eye_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'albertai_set_eye_to',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                COLOR: 1,\n            },\n            class: 'albertai_eye',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.setEyeColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.set_eye(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_pick_eye: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'albertai_pick_eye',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                COLOR: 1,\n            },\n            class: 'albertai_eye',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.pickEyeColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.pick_eye(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_change_eye_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'albertai_change_eye_by_rgb',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'albertai_eye',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.changeEyeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.add_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_set_eye_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'albertai_set_eye_to_rgb',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'albertai_eye',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.setEyeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.set_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_clear_eye: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'albertai_clear_eye',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n            },\n            class: 'albertai_eye',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.clearEye(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.clear_eye(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'albertai_play_sound_times',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.play_sound(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'albertai_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.play_sound_until_done(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'albertai_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.add_buzzer(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'albertai_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.set_buzzer(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'albertai_clear_sound',\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.clear_sound()',\n                        params: [null],\n                    },\n                ],\n            },\n        },\n        albertai_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'albertai_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.play_note(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'albertai_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.play_note_beat(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'albertai_rest_for',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.rest_beat(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'albertai_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        albertai_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'albertai_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'albertai_sound',\n            isNotFor: ['albertai'],\n            func(sprite, script) {\n                const robot = Entry.AlbertAi.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AlbertAi.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.AlbertAi;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_altino.js",
    "content": "'use strict';\n\nEntry.Altino = {\n    PORT_MAP: {\n        rightWheel: 0,\n        leftWheel: 0,\n        steering: 0,\n        ascii: 0,\n        led: 0,\n        led2: 0,\n        note: 0,\n        dot1: 0,\n        dot2: 0,\n        dot3: 0,\n        dot4: 0,\n        dot5: 0,\n        dot6: 0,\n        dot7: 0,\n        dot8: 0,\n        command: 0,\n    },\n    setZero: function() {\n        var portMap = Entry.Altino.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        var Altino = Entry.Altino;\n        Altino.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    id: '18.1',\n    name: 'altino',\n    url: 'http://saeon.co.kr/',\n    imageName: 'altino.png',\n    title: {\n        en: 'altino',\n        ko: '알티노',\n    },\n};\n\nEntry.Altino.blockMenuBlocks = [\n    'altino_analogValue',\n    'altino_stopAll',\n    'altino_rear_wheel',\n    'altino_steering',\n    'altino_sound',\n    'altino_light',\n    'altino_dot_display',\n    'altino_dot_display_line',\n    'altino_steering_hex',\n    'altino_light_hex',\n    'altino_sound_hex',\n    'altino_dot_display_hex',\n    'altino_dot_display_matrix_on',\n    'altino_dot_display_matrix_off',\n    'altino_ir_reset',\n];\n\nEntry.Altino.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                ALTINO_ACCX: '가속도-X',\n                ALTINO_ACCY: '가속도-Y',\n                ALTINO_ACCZ: '가속도-Z',\n                ALTINO_BAT: '배터리 전압',\n                ALTINO_CDS: '조도',\n                ALTINO_GYROX: '자이로-X',\n                ALTINO_GYROY: '자이로-Y',\n                ALTINO_GYROZ: '자이로-Z',\n                ALTINO_IR1: '적외선-1',\n                ALTINO_IR2: '적외선-2',\n                ALTINO_IR3: '적외선-3',\n                ALTINO_IR4: '적외선-4',\n                ALTINO_IR5: '적외선-5',\n                ALTINO_IR6: '적외선-6',\n                ALTINO_Led_Brake_Light: '브레이크',\n                ALTINO_Led_Forward_Light: '전방',\n                ALTINO_Led_Reverse_Light: '후진',\n                ALTINO_Led_Turn_Left_Light: '왼쪽 방향지시',\n                ALTINO_Led_Turn_Right_Light: '오른쪽 방향지시',\n                ALTINO_Line: '번째 줄',\n                ALTINO_MAGX: '지자기-X',\n                ALTINO_MAGY: '지자기-Y',\n                ALTINO_MAGZ: '지자기-Z',\n                ALTINO_REMOTE: '리모콘 수신 값',\n                ALTINO_STTOR: '조향전류',\n                ALTINO_STVAR: '조향 가변저항',\n                ALTINO_Steering_Angle_Center: '중앙',\n                ALTINO_Steering_Angle_Left10: '왼쪽으로-10',\n                ALTINO_Steering_Angle_Left15: '왼쪽으로-15',\n                ALTINO_Steering_Angle_Left20: '왼쪽으로-20',\n                ALTINO_Steering_Angle_Left5: '왼쪽으로-5',\n                ALTINO_Steering_Angle_Right10: '오른쪽으로-10',\n                ALTINO_Steering_Angle_Right15: '오른쪽으로-15',\n                ALTINO_Steering_Angle_Right20: '오른쪽으로-20',\n                ALTINO_Steering_Angle_Right5: '오른쪽으로-5',\n                ALTINO_TEM: '온도',\n                ALTINO_TOR1: '오른쪽 뒷바퀴 전류',\n                ALTINO_TOR2: '왼쪽 뒷바퀴 전류',\n                ALTINO_Value: '출력 값',\n                ALTINO_a: 'A(라)',\n                ALTINO_a2: 'A#(라#)',\n                ALTINO_b: 'B(시)',\n                ALTINO_c: 'C(도)',\n                ALTINO_c2: 'C#(도#)',\n                ALTINO_d: 'D(레)',\n                ALTINO_d2: 'D#(레#)',\n                ALTINO_dot_display_1: '한문자',\n                ALTINO_dot_display_2: '출력하기',\n                ALTINO_e: 'E(미)',\n                ALTINO_f: 'F(파)',\n                ALTINO_f2: 'F#(파#)',\n                ALTINO_g: 'G(솔)',\n                ALTINO_g2: 'G#(솔#)',\n                ALTINO_sound_oct: '옥타브',\n                ALTINO_h: '끄기',\n                ALTINO_h2: '켜기',\n                ALTINO_leftWheel: '왼쪽',\n                ALTINO_melody_ms: '연주하기',\n                ALTINO_outputValue: '출력 값',\n                ALTINO_rightWheel: '오른쪽',\n                ALTINO_set: '로 정하기',\n                ALTINO_stopAll: '모두',\n                ALTINO_stopDrive: '주행',\n                ALTINO_stopSteering: '조향',\n                ALTINO_stopSound: '소리',\n                ALTINO_stopLight: '라이트',\n                ALTINO_stopDisplay: '표시하기',\n                ALTINO_dot_line_1: '1행',\n                ALTINO_dot_line_2: '2행',\n                ALTINO_dot_line_3: '3행',\n                ALTINO_dot_line_4: '4행',\n                ALTINO_dot_line_5: '5행',\n                ALTINO_dot_line_6: '6행',\n                ALTINO_dot_line_7: '7행',\n                ALTINO_dot_line_8: '8행',\n            },\n            template: {\n                altino_analogValue: '알티노 %1 센서값',\n                altino_stopAll: '정지 %1%2',\n                altino_dot_display: '표시하기 %1 %2',\n                altino_dot_display_line: '표시하기 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n                altino_dot_display_hex: '표시하기 %1 %2 %3 %4 %5 %6 %7 %8 %9',\n                altino_dot_display_matrix_on: '표시하기 켜기 X:%1 Y:%2 %3',\n                altino_dot_display_matrix_off: '표시하기 끄기 X:%1 Y:%2 %3',\n                altino_light: '라이트%1 %2 %3',\n                altino_light_hex: '라이트%1 %2 %3',\n                altino_sound_hex: '소리%1 %2',\n                altino_rear_wheel: '뒷바퀴 구동 좌:%1 우:%2%3',\n                altino_sound: '소리 %1 %2 %3',\n                altino_steering_hex: '조향 %1%2',\n                altino_steering: '조향 %1°%2',\n                altino_ir_reset: '알티노 IR 센서 초기화%1',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                ALTINO_ACCX: 'Accel-X',\n                ALTINO_ACCY: 'Accel-Y',\n                ALTINO_ACCZ: 'Accel-Z',\n                ALTINO_BAT: 'BAT',\n                ALTINO_CDS: 'CDS',\n                ALTINO_GYROX: 'Gyro-X',\n                ALTINO_GYROY: 'Gyro-Y',\n                ALTINO_GYROZ: 'Gyro-Z',\n                ALTINO_IR1: 'IR-1',\n                ALTINO_IR2: 'IR-2',\n                ALTINO_IR3: 'IR-3',\n                ALTINO_IR4: 'IR-4',\n                ALTINO_IR5: 'IR-5',\n                ALTINO_IR6: 'IR-6',\n                ALTINO_Led_Brake_Light: 'Brake',\n                ALTINO_Led_Forward_Light: 'Forward',\n                ALTINO_Led_Reverse_Light: 'Reverse',\n                ALTINO_Led_Turn_Left_Light: 'Turn Left',\n                ALTINO_Led_Turn_Right_Light: 'Turn Right',\n                ALTINO_Line: 'line',\n                ALTINO_MAGX: 'Magnet-X',\n                ALTINO_MAGY: 'Magnet-Y',\n                ALTINO_MAGZ: 'Magnet-Z',\n                ALTINO_REMOTE: 'remote control',\n                ALTINO_STTOR: 'S-Current',\n                ALTINO_STVAR: 'steering potentiometer',\n                ALTINO_Steering_Angle_Center: 'Center-0',\n                ALTINO_Steering_Angle_Left10: 'Left-10',\n                ALTINO_Steering_Angle_Left15: 'Left-15',\n                ALTINO_Steering_Angle_Left20: 'Left-20',\n                ALTINO_Steering_Angle_Left5: 'Left-5',\n                ALTINO_Steering_Angle_Right10: 'Right-10',\n                ALTINO_Steering_Angle_Right15: 'Right-15',\n                ALTINO_Steering_Angle_Right20: 'Right-20',\n                ALTINO_Steering_Angle_Right5: 'Right-5',\n                ALTINO_TEM: 'Temperature',\n                ALTINO_TOR1: 'M-Current Right',\n                ALTINO_TOR2: 'M-Current Left',\n                ALTINO_Value: 'output value',\n                ALTINO_a: 'A(la)',\n                ALTINO_a2: 'A#(la#)',\n                ALTINO_b: 'B(si)',\n                ALTINO_c: 'C(do)',\n                ALTINO_c2: 'C#(do#)',\n                ALTINO_d: 'D(re)',\n                ALTINO_d2: 'D#(re#)',\n                ALTINO_dot_display_1: 'one char',\n                ALTINO_dot_display_2: 'display',\n                ALTINO_e: 'E(mi)',\n                ALTINO_f: 'F(fa)',\n                ALTINO_f2: 'F#(fa#)',\n                ALTINO_g: 'G(sol)',\n                ALTINO_g2: 'G#(sol#)',\n                ALTINO_sound_oct: 'Oct',\n                ALTINO_h: 'Off',\n                ALTINO_h2: 'On',\n                ALTINO_leftWheel: 'left',\n                ALTINO_melody_ms: 'play',\n                ALTINO_outputValue: 'output',\n                ALTINO_rightWheel: 'right',\n                ALTINO_set: ' display',\n                ALTINO_stopAll: 'All',\n                ALTINO_stopDrive: 'Drive',\n                ALTINO_stopSteering: 'Steering',\n                ALTINO_stopSound: 'Sound',\n                ALTINO_stopLight: 'Light',\n                ALTINO_stopDisplay: 'Display',\n                ALTINO_dot_line_1: 'Line-1',\n                ALTINO_dot_line_2: 'Line-2',\n                ALTINO_dot_line_3: 'Line-3',\n                ALTINO_dot_line_4: 'Line-4',\n                ALTINO_dot_line_5: 'Line-5',\n                ALTINO_dot_line_6: 'Line-6',\n                ALTINO_dot_line_7: 'Line-7',\n                ALTINO_dot_line_8: 'Line-8',\n            },\n            template: {\n                altino_analogValue: 'Altino %1 sensor value',\n                altino_stopAll: 'Stop %1%2',\n                altino_dot_display: 'Display %1 %2',\n                altino_dot_display_line: 'Display %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n                altino_dot_display_hex: 'Display %1 %2 %3 %4 %5 %6 %7 %8 %9',\n                altino_dot_display_matrix_on: 'Display On X:%1 Y:%2 %3',\n                altino_dot_display_matrix_off: 'Display Off X:%1 Y:%2 %3',\n                altino_light: 'Light %1 %2 %3',\n                altino_light_hex: 'Light %1 %2 %3',\n                altino_sound_hex: 'Sound %1 %2',\n                altino_rear_wheel: 'Go L:%1 R:%2%3',\n                altino_sound: 'Sound %1 %2 %3',\n                altino_steering_hex: 'Steering %1%2',\n                altino_steering: 'Steering %1°%2',\n                altino_ir_reset: 'Reset Altino IR Sensor%1',\n            },\n        },\n    };\n};\n\nEntry.Altino.getBlocks = function() {\n    return {\n        //region Altino 알티노\n        altino_analogValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_CDS, 'cds'],\n                        [Lang.Blocks.ALTINO_IR1, 'ir1'],\n                        [Lang.Blocks.ALTINO_IR2, 'ir2'],\n                        [Lang.Blocks.ALTINO_IR3, 'ir3'],\n                        [Lang.Blocks.ALTINO_IR4, 'ir4'],\n                        [Lang.Blocks.ALTINO_IR5, 'ir5'],\n                        [Lang.Blocks.ALTINO_IR6, 'ir6'],\n                        [Lang.Blocks.ALTINO_ACCX, 'accx'],\n                        [Lang.Blocks.ALTINO_ACCY, 'accy'],\n                        [Lang.Blocks.ALTINO_ACCZ, 'accz'],\n                        [Lang.Blocks.ALTINO_MAGX, 'magx'],\n                        [Lang.Blocks.ALTINO_MAGY, 'magy'],\n                        [Lang.Blocks.ALTINO_MAGZ, 'magz'],\n                        [Lang.Blocks.ALTINO_GYROX, 'gyrox'],\n                        [Lang.Blocks.ALTINO_GYROY, 'gyroy'],\n                        [Lang.Blocks.ALTINO_GYROZ, 'gyroz'],\n                        [Lang.Blocks.ALTINO_TEM, 'tem'],\n                        [Lang.Blocks.ALTINO_TOR2, 'tor2'],\n                        [Lang.Blocks.ALTINO_TOR1, 'tor1'],\n                        //[Lang.Blocks.ALTINO_STVAR, 'stvar'],\n                        [Lang.Blocks.ALTINO_STTOR, 'sttor'],\n                        [Lang.Blocks.ALTINO_BAT, 'bat'],\n                        //[Lang.Blocks.ALTINO_REMOTE, 'remote'],\n                    ],\n                    value: 'cds',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'altino_analogValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'altino_sensor',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['Altino.analog_value(%1)'] },\n        },\n        altino_stopAll: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_stopAll, 'All'],\n                        [Lang.Blocks.ALTINO_stopDrive, 'Drive'],\n                        [Lang.Blocks.ALTINO_stopSteering, 'Steering'],\n                        [Lang.Blocks.ALTINO_stopSound, 'Sound'],\n                        [Lang.Blocks.ALTINO_stopLight, 'Light'],\n                        [Lang.Blocks.ALTINO_stopDisplay, 'Display'],\n                    ],\n                    value: 'All',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'altino_stopAll',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'altino_output',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'All') {\n                    sq.steering = 0;\n                    sq.rightWheel = 0;\n                    sq.leftWheel = 0;\n                    sq.note = 0;\n                    sq.led = 0;\n                    sq.led2 = sq.led2 & 0x3f;\n                    sq.ascii = 0;\n                    sq.dot1 = 0;\n                    sq.dot2 = 0;\n                    sq.dot3 = 0;\n                    sq.dot4 = 0;\n                    sq.dot5 = 0;\n                    sq.dot6 = 0;\n                    sq.dot7 = 0;\n                    sq.dot8 = 0;\n                } else if (direction == 'Drive') {\n                    sq.rightWheel = 0;\n                    sq.leftWheel = 0;\n                } else if (direction == 'Steering') {\n                    sq.steering = 0;\n                } else if (direction == 'Sound') {\n                    sq.note = 0;\n                } else if (direction == 'Light') {\n                    sq.led = 0;\n                    sq.led2 = sq.led2 & 0x3f;\n                    /*\n                    sq.led = sq.led & 0xfc;\n                    sq.led = sq.led & 0xf3;\n                    sq.led2 = sq.led2 & 0x3f;\n                    sq.led = sq.led & 0x5f;\n                    sq.led = sq.led & 0xaf;\n                    */\n                } else if (direction == 'Display') {\n                    sq.ascii = 0;\n                    sq.dot1 = 0;\n                    sq.dot2 = 0;\n                    sq.dot3 = 0;\n                    sq.dot4 = 0;\n                    sq.dot5 = 0;\n                    sq.dot6 = 0;\n                    sq.dot7 = 0;\n                    sq.dot8 = 0;\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [],  py: ['Altino.stop(%1)']},\n        },\n        altino_steering: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_Steering_Angle_Center, 'Center'],\n                        [Lang.Blocks.ALTINO_Steering_Angle_Left5, 'Left5'],\n                        [Lang.Blocks.ALTINO_Steering_Angle_Left10, 'Left10'],\n                        [Lang.Blocks.ALTINO_Steering_Angle_Left15, 'Left15'],\n                        [Lang.Blocks.ALTINO_Steering_Angle_Left20, 'Left20'],\n                        [Lang.Blocks.ALTINO_Steering_Angle_Right5, 'Right5'],\n                        [Lang.Blocks.ALTINO_Steering_Angle_Right10, 'Right10'],\n                        [Lang.Blocks.ALTINO_Steering_Angle_Right15, 'Right15'],\n                        [Lang.Blocks.ALTINO_Steering_Angle_Right20, 'Right20'],\n                    ],\n                    value: 'Center',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'altino_steering',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'altino_output',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'Center') {\n                    sq.steering = 2;\n                } else if (direction == 'Left5') {\n                    sq.steering = 160;\n                } else if (direction == 'Left10') {\n                    sq.steering = 192;\n                } else if (direction == 'Left15') {\n                    sq.steering = 224;\n                } else if (direction == 'Left20') {\n                    sq.steering = 255;\n                } else if (direction == 'Right5') {\n                    sq.steering = 32;\n                } else if (direction == 'Right10') {\n                    sq.steering = 64;\n                } else if (direction == 'Right15') {\n                    sq.steering = 96;\n                } else if (direction == 'Right20') {\n                    sq.steering = 127;\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.steering(%1)'] },\n        },\n        altino_steering_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'altino_steering_hex',\n            },\n            paramsKeyMap: {\n                steerVal: 0,\n            },\n            class: 'altino_expert',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                console.log(parseInt(Number(script.getStringValue('steerVal')), 10));\n                sq.steering = parseInt(Number(script.getStringValue('steerVal')), 10);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.steering_hex(%1)'] },\n        },\n        altino_sound_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'altino_sound_hex',\n            },\n            paramsKeyMap: {\n                soundVal: 0,\n            },\n            class: 'altino_expert',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.note = parseInt(Number(script.getStringValue('soundVal')), 10);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.sound_hex(%1)'] },\n        },\n        altino_rear_wheel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'altino_rear_wheel',\n            },\n            paramsKeyMap: {\n                leftWheel: 0,\n                rightWheel: 1,\n            },\n            class: 'altino_output',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                sq.rightWheel = script.getNumberValue('rightWheel');\n                sq.leftWheel = script.getNumberValue('leftWheel');\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.rear_wheel(%1, %2)'] },\n        },\n        altino_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1-' + Lang.Blocks.ALTINO_sound_oct, '1'],\n                        ['2-' + Lang.Blocks.ALTINO_sound_oct, '2'],\n                        ['3-' + Lang.Blocks.ALTINO_sound_oct, '3'],\n                        ['4-' + Lang.Blocks.ALTINO_sound_oct, '4'],\n                        ['5-' + Lang.Blocks.ALTINO_sound_oct, '5'],\n                        ['6-' + Lang.Blocks.ALTINO_sound_oct, '6'],\n                        ['7-' + Lang.Blocks.ALTINO_sound_oct, '7'],\n                        ['8-' + Lang.Blocks.ALTINO_sound_oct, '8'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h, 'NOT'],\n                        [Lang.Blocks.ALTINO_c, 'C'],\n                        [Lang.Blocks.ALTINO_c2, 'C#'],\n                        [Lang.Blocks.ALTINO_d, 'D'],\n                        [Lang.Blocks.ALTINO_d2, 'D#'],\n                        [Lang.Blocks.ALTINO_e, 'E'],\n                        [Lang.Blocks.ALTINO_f, 'F'],\n                        [Lang.Blocks.ALTINO_f2, 'F#'],\n                        [Lang.Blocks.ALTINO_g, 'G'],\n                        [Lang.Blocks.ALTINO_g2, 'G#'],\n                        [Lang.Blocks.ALTINO_a, 'A'],\n                        [Lang.Blocks.ALTINO_a2, 'A#'],\n                        [Lang.Blocks.ALTINO_b, 'B'],\n                    ],\n                    value: 'NOT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'altino_sound',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                NOTE: 1,\n            },\n            class: 'altino_output',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var octave = script.getStringField('OCTAVE', script);\n                var note = script.getStringField('NOTE', script);\n                var octave_int = octave + note;\n\n                if (note == 'NOT') sq.note = 0;\n                else if (octave_int == '1C') sq.note = 1;\n                else if (octave_int == '1C#') sq.note = 2;\n                else if (octave_int == '1D') sq.note = 3;\n                else if (octave_int == '1D#') sq.note = 4;\n                else if (octave_int == '1E') sq.note = 5;\n                else if (octave_int == '1F') sq.note = 6;\n                else if (octave_int == '1F#') sq.note = 7;\n                else if (octave_int == '1G') sq.note = 8;\n                else if (octave_int == '1G#') sq.note = 9;\n                else if (octave_int == '1A') sq.note = 10;\n                else if (octave_int == '1A#') sq.note = 11;\n                else if (octave_int == '1B') sq.note = 12;\n                else if (octave_int == '2C') sq.note = 13;\n                else if (octave_int == '2C#') sq.note = 14;\n                else if (octave_int == '2D') sq.note = 15;\n                else if (octave_int == '2D#') sq.note = 16;\n                else if (octave_int == '2E') sq.note = 17;\n                else if (octave_int == '2F') sq.note = 18;\n                else if (octave_int == '2F#') sq.note = 19;\n                else if (octave_int == '2G') sq.note = 20;\n                else if (octave_int == '2G#') sq.note = 21;\n                else if (octave_int == '2A') sq.note = 22;\n                else if (octave_int == '2A#') sq.note = 23;\n                else if (octave_int == '2B') sq.note = 24;\n                else if (octave_int == '3C') sq.note = 25;\n                else if (octave_int == '3C#') sq.note = 26;\n                else if (octave_int == '3D') sq.note = 27;\n                else if (octave_int == '3D#') sq.note = 28;\n                else if (octave_int == '3E') sq.note = 29;\n                else if (octave_int == '3F') sq.note = 30;\n                else if (octave_int == '3F#') sq.note = 31;\n                else if (octave_int == '3G') sq.note = 32;\n                else if (octave_int == '3G#') sq.note = 33;\n                else if (octave_int == '3A') sq.note = 34;\n                else if (octave_int == '3A#') sq.note = 35;\n                else if (octave_int == '3B') sq.note = 36;\n                else if (octave_int == '4C') sq.note = 37;\n                else if (octave_int == '4C#') sq.note = 38;\n                else if (octave_int == '4D') sq.note = 39;\n                else if (octave_int == '4D#') sq.note = 40;\n                else if (octave_int == '4E') sq.note = 41;\n                else if (octave_int == '4F') sq.note = 42;\n                else if (octave_int == '4F#') sq.note = 43;\n                else if (octave_int == '4G') sq.note = 44;\n                else if (octave_int == '4G#') sq.note = 45;\n                else if (octave_int == '4A') sq.note = 46;\n                else if (octave_int == '4A#') sq.note = 47;\n                else if (octave_int == '4B') sq.note = 48;\n                else if (octave_int == '5C') sq.note = 49;\n                else if (octave_int == '5C#') sq.note = 50;\n                else if (octave_int == '5D') sq.note = 51;\n                else if (octave_int == '5D#') sq.note = 52;\n                else if (octave_int == '5E') sq.note = 53;\n                else if (octave_int == '5F') sq.note = 54;\n                else if (octave_int == '5F#') sq.note = 55;\n                else if (octave_int == '5G') sq.note = 56;\n                else if (octave_int == '5G#') sq.note = 57;\n                else if (octave_int == '5A') sq.note = 58;\n                else if (octave_int == '5A#') sq.note = 59;\n                else if (octave_int == '5B') sq.note = 60;\n                else if (octave_int == '6C') sq.note = 61;\n                else if (octave_int == '6C#') sq.note = 62;\n                else if (octave_int == '6D') sq.note = 63;\n                else if (octave_int == '6D#') sq.note = 64;\n                else if (octave_int == '6E') sq.note = 65;\n                else if (octave_int == '6F') sq.note = 66;\n                else if (octave_int == '6F#') sq.note = 67;\n                else if (octave_int == '6G') sq.note = 68;\n                else if (octave_int == '6G#') sq.note = 69;\n                else if (octave_int == '6A') sq.note = 70;\n                else if (octave_int == '6A#') sq.note = 71;\n                else if (octave_int == '6B') sq.note = 72;\n                else if (octave_int == '7C') sq.note = 73;\n                else if (octave_int == '7C#') sq.note = 74;\n                else if (octave_int == '7D') sq.note = 75;\n                else if (octave_int == '7D#') sq.note = 76;\n                else if (octave_int == '7E') sq.note = 77;\n                else if (octave_int == '7F') sq.note = 78;\n                else if (octave_int == '7F#') sq.note = 79;\n                else if (octave_int == '7G') sq.note = 80;\n                else if (octave_int == '7G#') sq.note = 81;\n                else if (octave_int == '7A') sq.note = 82;\n                else if (octave_int == '7A#') sq.note = 83;\n                else if (octave_int == '7B') sq.note = 84;\n                else if (octave_int == '8C') sq.note = 85;\n                else if (octave_int == '8C#') sq.note = 86;\n                else if (octave_int == '8D') sq.note = 87;\n                else if (octave_int == '8D#') sq.note = 88;\n                else if (octave_int == '8E') sq.note = 89;\n                else if (octave_int == '8F') sq.note = 90;\n                else if (octave_int == '8F#') sq.note = 91;\n                else if (octave_int == '8G') sq.note = 92;\n                else if (octave_int == '8G#') sq.note = 93;\n                else if (octave_int == '8A') sq.note = 94;\n                else if (octave_int == '8A#') sq.note = 95;\n                else if (octave_int == '8B') sq.note = 96;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.sound(%1, %2)'] },\n        },\n        altino_light: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_Led_Forward_Light, '2'],\n                        [Lang.Blocks.ALTINO_Led_Turn_Left_Light, '5'],\n                        [Lang.Blocks.ALTINO_Led_Turn_Right_Light, '6'],\n                        [Lang.Blocks.ALTINO_Led_Brake_Light, '4'],\n                        [Lang.Blocks.ALTINO_Led_Reverse_Light, '3'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '255'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'altino_light',\n            },\n            paramsKeyMap: {\n                SELECT: 0,\n                ONOFF: 1,\n            },\n            class: 'altino_output',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var select = script.getStringField('SELECT', script);\n                var onoff = script.getStringField('ONOFF', script);\n\n                if (select == '2' && onoff == '255') {\n                    sq.led = sq.led | 0x03;\n                } else if (select == '2' && onoff == '0') {\n                    sq.led = sq.led & 0xfc;\n                }\n\n                if (select == '3' && onoff == '255') {\n                    sq.led = sq.led | 0x0c;\n                } else if (select == '3' && onoff == '0') {\n                    sq.led = sq.led & 0xf3;\n                }\n\n                if (select == '4' && onoff == '255') {\n                    sq.led2 = sq.led2 | 0xc0;\n                } else if (select == '4' && onoff == '0') {\n                    sq.led2 = sq.led2 & 0x3f;\n                }\n\n                if (select == '5' && onoff == '255') {\n                    sq.led = sq.led | 0xa0;\n                } else if (select == '5' && onoff == '0') {\n                    sq.led = sq.led & 0x5f;\n                }\n\n                if (select == '6' && onoff == '255') {\n                    sq.led = sq.led | 0x50;\n                } else if (select == '6' && onoff == '0') {\n                    sq.led = sq.led & 0xaf;\n                }\n\n                //sq.led = 0xff;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.light(%1, %2)'] },\n        },\n        altino_dot_display_matrix_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'altino_dot_display_matrix_on',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'altino_expert',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var nx = script.getNumberValue('VALUE1');\n                var ny = script.getNumberValue('VALUE2');\n                var mask = 1;\n\n                if (ny >= 1 && ny <= 8) {\n                    ny = ny - 1;\n                    mask = mask << ny;\n                    if (nx == 1) {\n                        sq.dot8 |= mask;\n                    } else if (nx == 2) {\n                        sq.dot7 |= mask;\n                    } else if (nx == 3) {\n                        sq.dot6 |= mask;\n                    } else if (nx == 4) {\n                        sq.dot5 |= mask;\n                    } else if (nx == 5) {\n                        sq.dot4 |= mask;\n                    } else if (nx == 6) {\n                        sq.dot3 |= mask;\n                    } else if (nx == 7) {\n                        sq.dot2 |= mask;\n                    } else if (nx == 8) {\n                        sq.dot1 |= mask;\n                    }\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.dot_display_matrix_on(%1, %2)'] },\n        },\n        altino_dot_display_matrix_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'altino_dot_display_matrix_off',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'altino_expert',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var nx = script.getNumberValue('VALUE1');\n                var ny = script.getNumberValue('VALUE2');\n                var mask = 1;\n\n                if (ny >= 1 && ny <= 8) {\n                    ny = ny - 1;\n                    mask = mask << ny;\n                    if (nx == 1) {\n                        sq.dot8 &= ~mask;\n                    } else if (nx == 2) {\n                        sq.dot7 &= ~mask;\n                    } else if (nx == 3) {\n                        sq.dot6 &= ~mask;\n                    } else if (nx == 4) {\n                        sq.dot5 &= ~mask;\n                    } else if (nx == 5) {\n                        sq.dot4 &= ~mask;\n                    } else if (nx == 6) {\n                        sq.dot3 &= ~mask;\n                    } else if (nx == 7) {\n                        sq.dot2 &= ~mask;\n                    } else if (nx == 8) {\n                        sq.dot1 &= ~mask;\n                    }\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.dot_display_matrix_off(%1, %2)'] },\n        },\n        altino_light_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    null,\n                ],\n                type: 'altino_light_hex',\n            },\n            paramsKeyMap: {\n                MSB: 0,\n                LSB: 1,\n            },\n            class: 'altino_expert',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var msb = parseInt(Number(script.getStringValue('MSB')), 10);\n                var lsb = parseInt(Number(script.getStringValue('LSB')), 10);\n\n                sq.led2 = (msb & 0xc0) | (sq.led2 & 0x3f);\n                sq.led = lsb;\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.light_hex(%1, %2)'] },\n        },\n        altino_dot_display: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['A'],\n                    },\n                    null,\n                ],\n                type: 'altino_dot_display',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'altino_output',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var str = script.getStringValue('VALUE');\n                var code = str.charCodeAt(0) | 0x80;\n                sq.ascii = code;\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Altino.dot_display(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        altino_dot_display_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_dot_line_1, '1'],\n                        [Lang.Blocks.ALTINO_dot_line_2, '2'],\n                        [Lang.Blocks.ALTINO_dot_line_3, '3'],\n                        [Lang.Blocks.ALTINO_dot_line_4, '4'],\n                        [Lang.Blocks.ALTINO_dot_line_5, '5'],\n                        [Lang.Blocks.ALTINO_dot_line_6, '6'],\n                        [Lang.Blocks.ALTINO_dot_line_7, '7'],\n                        [Lang.Blocks.ALTINO_dot_line_8, '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '1'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '1'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '1'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '1'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '1'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '1'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '1'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALTINO_h2, '1'],\n                        [Lang.Blocks.ALTINO_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null, null, null, null, null, null, null],\n                type: 'altino_dot_display_line',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                SW1: 1,\n                SW2: 2,\n                SW3: 3,\n                SW4: 4,\n                SW5: 5,\n                SW6: 6,\n                SW7: 7,\n                SW8: 8,\n            },\n            class: 'altino_output',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var line = script.getStringField('LINE', script);\n                var dots = [\n                    script.getStringField('SW1', script),\n                    script.getStringField('SW2', script),\n                    script.getStringField('SW3', script),\n                    script.getStringField('SW4', script),\n                    script.getStringField('SW5', script),\n                    script.getStringField('SW6', script),\n                    script.getStringField('SW7', script),\n                    script.getStringField('SW8', script),\n                ];\n\n                var mask = 0;\n\n                if (line == '1') {\n                    mask = 0x01;\n                } else if (line == '2') {\n                    mask = 0x02;\n                } else if (line == '3') {\n                    mask = 0x04;\n                } else if (line == '4') {\n                    mask = 0x08;\n                } else if (line == '5') {\n                    mask = 0x10;\n                } else if (line == '6') {\n                    mask = 0x20;\n                } else if (line == '7') {\n                    mask = 0x40;\n                } else if (line == '8') {\n                    mask = 0x80;\n                }\n\n                if (dots[7] == '1') {\n                    sq.dot1 |= mask;\n                } else {\n                    sq.dot1 &= ~mask;\n                }\n\n                if (dots[6] == '1') {\n                    sq.dot2 |= mask;\n                } else {\n                    sq.dot2 &= ~mask;\n                }\n\n                if (dots[5] == '1') {\n                    sq.dot3 |= mask;\n                } else {\n                    sq.dot3 &= ~mask;\n                }\n\n                if (dots[4] == '1') {\n                    sq.dot4 |= mask;\n                } else {\n                    sq.dot4 &= ~mask;\n                }\n\n                if (dots[3] == '1') {\n                    sq.dot5 |= mask;\n                } else {\n                    sq.dot5 &= ~mask;\n                }\n\n                if (dots[2] == '1') {\n                    sq.dot6 |= mask;\n                } else {\n                    sq.dot6 &= ~mask;\n                }\n\n                if (dots[1] == '1') {\n                    sq.dot7 |= mask;\n                } else {\n                    sq.dot7 &= ~mask;\n                }\n\n                if (dots[0] == '1') {\n                    sq.dot8 |= mask;\n                } else {\n                    sq.dot8 &= ~mask;\n                }\n\n                //sq.led = 0xff;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.dot_display_line(%1, %2, %3, %4, %5, %6, %7, %8)'] },\n        },\n        altino_dot_display_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    null,\n                ],\n                type: 'altino_dot_display_hex',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n                VALUE6: 5,\n                VALUE7: 6,\n                VALUE8: 7,\n            },\n            class: 'altino_expert',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.ascii = 0;\n                sq.dot1 = parseInt(Number(script.getStringValue('VALUE8')), 10);\n                sq.dot2 = parseInt(Number(script.getStringValue('VALUE7')), 10);\n                sq.dot3 = parseInt(Number(script.getStringValue('VALUE6')), 10);\n                sq.dot4 = parseInt(Number(script.getStringValue('VALUE5')), 10);\n                sq.dot5 = parseInt(Number(script.getStringValue('VALUE4')), 10);\n                sq.dot6 = parseInt(Number(script.getStringValue('VALUE3')), 10);\n                sq.dot7 = parseInt(Number(script.getStringValue('VALUE2')), 10);\n                sq.dot8 = parseInt(Number(script.getStringValue('VALUE1')), 10);\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.dot_display_hex(%1, %2, %3, %4, %5, %6, %7, %8)'] },\n        },\n        altino_ir_reset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'altino_ir_reset',\n            },\n            paramsKeyMap: {\n                DEVICE : 0,\n            },\n            class: 'altino_output',\n            isNotFor: ['altino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                sq.command = 252;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Altino.ir_reset'] },\n        },\n        //endregion Altino 알티노\n    };\n};\n\nmodule.exports = Entry.Altino;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_altino_lite.js",
    "content": "'use strict';\n\nEntry.AltinoLite = {\n    PORT_MAP: {\n        rightWheel: 0,\n        leftWheel: 0,\n        steering: 0,\n        ascii: 0,\n        led: 0,\n        note: 0,\n        dot1: 0,\n        dot2: 0,\n        dot3: 0,\n        dot4: 0,\n        dot5: 0,\n        dot6: 0,\n        dot7: 0,\n        dot8: 0,\n        ir: 0\n    },\n    setZero: function() {\n        var portMap = Entry.AltinoLite.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        // var Altino = Entry.Altino;\n        // Altino.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    id: '18.2',\n    name: 'altino_lite',\n    url: 'http://saeon.co.kr/',\n    imageName: 'altino_lite.png',\n    title: {\n        en: 'Altino Lite',\n        ko: '알티노 라이트',\n    },\n};\n\nEntry.AltinoLite.blockMenuBlocks = [\n    'altino_lite_analogValue',\n    'altino_lite_stopAll',\n    'altino_lite_rear_wheel',\n    'altino_lite_steering',\n    'altino_lite_sound',\n    'altino_lite_light',\n    'altino_lite_dot_display',\n    'altino_lite_dot_display_line',\n    'altino_lite_steering_hex',\n    'altino_lite_light_hex',\n    'altino_lite_sound_hex',\n    'altino_lite_dot_display_hex',\n    'altino_lite_dot_display_matrix_on',\n    'altino_lite_dot_display_matrix_off',\n    'altino_lite_ir_reset',\n];\n\nEntry.AltinoLite.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                altino_lite_BAT: '배터리',\n                altino_lite_CDS: '조도',\n                altino_lite_IR1: '적외선-1',\n                altino_lite_IR2: '적외선-2',\n                altino_lite_IR3: '적외선-3',\n                altino_lite_IR4: '적외선-4',\n                altino_lite_IR5: '적외선-5',\n                altino_lite_IR6: '적외선-6',\n                altino_lite_Led_Brake_Light: '브레이크',\n                altino_lite_Led_Forward_Light: '전방',\n                altino_lite_Led_Turn_Left_Light: '왼쪽 방향지시',\n                altino_lite_Led_Turn_Right_Light: '오른쪽 방향지시',\n                altino_lite_Line: '번째 줄',\n                altino_lite_Steering_Angle_Center: '중앙',\n                altino_lite_Steering_Angle_Left10: '왼쪽으로-10',\n                altino_lite_Steering_Angle_Left15: '왼쪽으로-15',\n                altino_lite_Steering_Angle_Left20: '왼쪽으로-20',\n                altino_lite_Steering_Angle_Left5: '왼쪽으로-5',\n                altino_lite_Steering_Angle_Right10: '오른쪽으로-10',\n                altino_lite_Steering_Angle_Right15: '오른쪽으로-15',\n                altino_lite_Steering_Angle_Right20: '오른쪽으로-20',\n                altino_lite_Steering_Angle_Right5: '오른쪽으로-5',\n                altino_lite_Value: '출력 값',\n                altino_lite_a: 'A(라)',\n                altino_lite_a2: 'A#(라#)',\n                altino_lite_b: 'B(시)',\n                altino_lite_c: 'C(도)',\n                altino_lite_c2: 'C#(도#)',\n                altino_lite_d: 'D(레)',\n                altino_lite_d2: 'D#(레#)',\n                altino_lite_dot_display_1: '한문자',\n                altino_lite_dot_display_2: '출력하기',\n                altino_lite_e: 'E(미)',\n                altino_lite_f: 'F(파)',\n                altino_lite_f2: 'F#(파#)',\n                altino_lite_g: 'G(솔)',\n                altino_lite_g2: 'G#(솔#)',\n                altino_lite_sound_oct: '옥타브',\n                altino_lite_h: '끄기',\n                altino_lite_h2: '켜기',\n                altino_lite_leftWheel: '왼쪽',\n                altino_lite_melody_ms: '연주하기',\n                altino_lite_outputValue: '출력 값',\n                altino_lite_rightWheel: '오른쪽',\n                altino_lite_set: '로 정하기',\n                altino_lite_stopAll: '모두',\n                altino_lite_stopDrive: '주행',\n                altino_lite_stopSteering: '조향',\n                altino_lite_stopSound: '소리',\n                altino_lite_stopLight: '라이트',\n                altino_lite_stopDisplay: '표시하기',\n                altino_lite_dot_line_1: '1행',\n                altino_lite_dot_line_2: '2행',\n                altino_lite_dot_line_3: '3행',\n                altino_lite_dot_line_4: '4행',\n                altino_lite_dot_line_5: '5행',\n                altino_lite_dot_line_6: '6행',\n                altino_lite_dot_line_7: '7행',\n                altino_lite_dot_line_8: '8행',\n            },\n            template: {\n                altino_lite_analogValue: '알티노 라이트 %1 센서값',\n                altino_lite_stopAll: '정지 %1 %2',\n                altino_lite_dot_display: '표시하기 %1 %2',\n                altino_lite_dot_display_line: '표시하기 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n                altino_lite_dot_display_hex: '표시하기 %1 %2 %3 %4 %5 %6 %7 %8 %9',\n                altino_lite_dot_display_matrix_on: '표시하기 켜기 X:%1 Y:%2 %3',\n                altino_lite_dot_display_matrix_off: '표시하기 끄기 X:%1 Y:%2 %3',\n                altino_lite_light: '라이트%1 %2 %3',\n                altino_lite_light_hex: '라이트%1 %2',\n                altino_lite_sound_hex: '소리%1 %2',\n                altino_lite_rear_wheel: '뒷바퀴 구동 좌:%1 우:%2%3',\n                altino_lite_sound: '소리 %1 %2 %3',\n                altino_lite_steering_hex: '조향 %1%2',\n                altino_lite_steering: '조향 %1°%2',\n                altino_lite_ir_reset: '알티노 라이트 IR 센서 초기화%1',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                altino_lite_BAT: 'BAT',\n                altino_lite_CDS: 'CDS',\n                altino_lite_IR1: 'IR-1',\n                altino_lite_IR2: 'IR-2',\n                altino_lite_IR3: 'IR-3',\n                altino_lite_IR4: 'IR-4',\n                altino_lite_IR5: 'IR-5',\n                altino_lite_IR6: 'IR-6',\n                altino_lite_Led_Brake_Light: 'Brake',\n                altino_lite_Led_Forward_Light: 'Forward',\n                altino_lite_Led_Turn_Left_Light: 'Turn Left',\n                altino_lite_Led_Turn_Right_Light: 'Turn Right',\n                altino_lite_Line: 'line',\n                altino_lite_Steering_Angle_Center: 'Center-0',\n                altino_lite_Steering_Angle_Left10: 'Left-10',\n                altino_lite_Steering_Angle_Left15: 'Left-15',\n                altino_lite_Steering_Angle_Left20: 'Left-20',\n                altino_lite_Steering_Angle_Left5: 'Left-5',\n                altino_lite_Steering_Angle_Right10: 'Right-10',\n                altino_lite_Steering_Angle_Right15: 'Right-15',\n                altino_lite_Steering_Angle_Right20: 'Right-20',\n                altino_lite_Steering_Angle_Right5: 'Right-5',\n                altino_lite_Value: 'output value',\n                altino_lite_a: 'A(la)',\n                altino_lite_a2: 'A#(la#)',\n                altino_lite_b: 'B(si)',\n                altino_lite_c: 'C(do)',\n                altino_lite_c2: 'C#(do#)',\n                altino_lite_d: 'D(re)',\n                altino_lite_d2: 'D#(re#)',\n                altino_lite_dot_display_1: 'one char',\n                altino_lite_dot_display_2: 'display',\n                altino_lite_e: 'E(mi)',\n                altino_lite_f: 'F(fa)',\n                altino_lite_f2: 'F#(fa#)',\n                altino_lite_g: 'G(sol)',\n                altino_lite_g2: 'G#(sol#)',\n                altino_lite_sound_oct: 'Oct',\n                altino_lite_h: 'Off',\n                altino_lite_h2: 'On',\n                altino_lite_leftWheel: 'left',\n                altino_lite_melody_ms: 'play',\n                altino_lite_outputValue: 'output',\n                altino_lite_rightWheel: 'right',\n                altino_lite_set: ' display',\n                altino_lite_stopAll: 'All',\n                altino_lite_stopDrive: 'Drive',\n                altino_lite_stopSteering: 'Steering',\n                altino_lite_stopSound: 'Sound',\n                altino_lite_stopLight: 'Light',\n                altino_lite_stopDisplay: 'Display',\n                altino_lite_dot_line_1: 'Line-1',\n                altino_lite_dot_line_2: 'Line-2',\n                altino_lite_dot_line_3: 'Line-3',\n                altino_lite_dot_line_4: 'Line-4',\n                altino_lite_dot_line_5: 'Line-5',\n                altino_lite_dot_line_6: 'Line-6',\n                altino_lite_dot_line_7: 'Line-7',\n                altino_lite_dot_line_8: 'Line-8',\n            },\n            template: {\n                altino_lite_analogValue: 'Altino lite %1 sensor value',\n                altino_lite_stopAll: 'Stop %1°%2',\n                altino_lite_dot_display: 'Display %1 %2',\n                altino_lite_dot_display_line: 'Display %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n                altino_lite_dot_display_hex: 'Display %1 %2 %3 %4 %5 %6 %7 %8 %9',\n                altino_lite_dot_display_matrix_on: 'Display On X:%1 Y:%2 %3',\n                altino_lite_dot_display_matrix_off: 'Display Off X:%1 Y:%2 %3',\n                altino_lite_light: 'Light %1 %2 %3',\n                altino_lite_light_hex: 'Light %1 %2',\n                altino_lite_sound_hex: 'Sound %1 %2',\n                altino_lite_rear_wheel: 'Go L:%1 R:%2%3',\n                altino_lite_sound: 'Sound %1 %2 %3',\n                altino_lite_steering_hex: 'Steering %1%2',\n                altino_lite_steering: 'Steering %1°%2',\n                altino_lite_ir_reset: 'Reset Altino lite IR Sensor%1',\n            },\n        },\n    };\n};\n\nEntry.AltinoLite.getBlocks = function() {\n    return {\n        //region Altino 알티노\n        altino_lite_analogValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_CDS, 'cds'],\n                        [Lang.Blocks.altino_lite_IR1, 'ir1'],\n                        [Lang.Blocks.altino_lite_IR2, 'ir2'],\n                        [Lang.Blocks.altino_lite_IR3, 'ir3'],\n                        [Lang.Blocks.altino_lite_IR4, 'ir4'],\n                        [Lang.Blocks.altino_lite_IR5, 'ir5'],\n                        [Lang.Blocks.altino_lite_IR6, 'ir6'],\n                        [Lang.Blocks.altino_lite_BAT, 'bat'],\n                    ],\n                    value: 'cds',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'altino_lite_analogValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'altino_lite_sensor',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['AltinoLite.analog_value(%1)'] },\n        },\n        altino_lite_stopAll: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_stopAll, 'All'],\n                        [Lang.Blocks.altino_lite_stopDrive, 'Drive'],\n                        [Lang.Blocks.altino_lite_stopSteering, 'Steering'],\n                        [Lang.Blocks.altino_lite_stopSound, 'Sound'],\n                        [Lang.Blocks.altino_lite_stopLight, 'Light'],\n                        [Lang.Blocks.altino_lite_stopDisplay, 'Display'],\n                    ],\n                    value: 'All',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'altino_lite_stopAll',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'altino_lite_output',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'All') {\n                    sq.steering = 0;\n                    sq.rightWheel = 0;\n                    sq.leftWheel = 0;\n                    sq.note = 0;\n                    sq.led = 0;\n                    sq.ascii = 0;\n                    sq.dot1 = 0;\n                    sq.dot2 = 0;\n                    sq.dot3 = 0;\n                    sq.dot4 = 0;\n                    sq.dot5 = 0;\n                    sq.dot6 = 0;\n                    sq.dot7 = 0;\n                    sq.dot8 = 0;\n                } else if (direction == 'Drive') {\n                    sq.rightWheel = 0;\n                    sq.leftWheel = 0;\n                } else if (direction == 'Steering') {\n                    sq.steering = 0;\n                } else if (direction == 'Sound') {\n                    sq.note = 0;\n                } else if (direction == 'Light') {\n                    sq.led = 0;\n                } else if (direction == 'Display') {\n                    sq.ascii = 0;\n                    sq.dot1 = 0;\n                    sq.dot2 = 0;\n                    sq.dot3 = 0;\n                    sq.dot4 = 0;\n                    sq.dot5 = 0;\n                    sq.dot6 = 0;\n                    sq.dot7 = 0;\n                    sq.dot8 = 0;\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.stop(%1)'] },\n        },\n        altino_lite_steering: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_Steering_Angle_Center, 'Center'],\n                        [Lang.Blocks.altino_lite_Steering_Angle_Left5, 'Left5'],\n                        [Lang.Blocks.altino_lite_Steering_Angle_Left10, 'Left10'],\n                        [Lang.Blocks.altino_lite_Steering_Angle_Left15, 'Left15'],\n                        [Lang.Blocks.altino_lite_Steering_Angle_Left20, 'Left20'],\n                        [Lang.Blocks.altino_lite_Steering_Angle_Right5, 'Right5'],\n                        [Lang.Blocks.altino_lite_Steering_Angle_Right10, 'Right10'],\n                        [Lang.Blocks.altino_lite_Steering_Angle_Right15, 'Right15'],\n                        [Lang.Blocks.altino_lite_Steering_Angle_Right20, 'Right20'],\n                    ],\n                    value: 'Center',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'altino_lite_steering',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'altino_lite_output',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'Center') {\n                    sq.steering = 0;\n                } else if (direction == 'Left5') {\n                    sq.steering = 0xe0;\n                } else if (direction == 'Left10') {\n                    sq.steering = 0xc0;\n                } else if (direction == 'Left15') {\n                    sq.steering = 0xa1;\n                } else if (direction == 'Left20') {\n                    sq.steering = 0x81;\n                } else if (direction == 'Right5') {\n                    sq.steering = 31;\n                } else if (direction == 'Right10') {\n                    sq.steering = 63;\n                } else if (direction == 'Right15') {\n                    sq.steering = 94;\n                } else if (direction == 'Right20') {\n                    sq.steering = 126;\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.steering(%1)'] },\n        },\n        altino_lite_steering_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'altino_lite_steering_hex',\n            },\n            paramsKeyMap: {\n                steerVal: 0,\n            },\n            class: 'altino_lite_expert',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.steering = parseInt(Number(script.getStringValue('steerVal')), 10);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.steering_hex(%1)'] },\n        },\n        altino_lite_sound_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'altino_lite_sound_hex',\n            },\n            paramsKeyMap: {\n                soundVal: 0,\n            },\n            class: 'altino_lite_expert',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.note = parseInt(Number(script.getStringValue('soundVal')), 10);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.sound_hex(%1)'] },\n        },\n        altino_lite_rear_wheel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'altino_lite_rear_wheel',\n            },\n            paramsKeyMap: {\n                leftWheel: 0,\n                rightWheel: 1,\n            },\n            class: 'altino_lite_output',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                sq.rightWheel = script.getNumberValue('rightWheel');\n                sq.leftWheel = script.getNumberValue('leftWheel');\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.rear_wheel(%1, %2)'] },\n        },\n        altino_lite_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {                    \n                    type: 'Dropdown',\n                    options: [\n                        ['1-' + Lang.Blocks.altino_lite_sound_oct, '1'],\n                        ['2-' + Lang.Blocks.altino_lite_sound_oct, '2'],\n                        ['3-' + Lang.Blocks.altino_lite_sound_oct, '3'],\n                        ['4-' + Lang.Blocks.altino_lite_sound_oct, '4'],\n                        ['5-' + Lang.Blocks.altino_lite_sound_oct, '5'],\n                        ['6-' + Lang.Blocks.altino_lite_sound_oct, '6'],\n                        ['7-' + Lang.Blocks.altino_lite_sound_oct, '7'],\n                        ['8-' + Lang.Blocks.altino_lite_sound_oct, '8'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h, 'NOT'],\n                        [Lang.Blocks.altino_lite_c, 'C'],\n                        [Lang.Blocks.altino_lite_c2, 'C#'],\n                        [Lang.Blocks.altino_lite_d, 'D'],\n                        [Lang.Blocks.altino_lite_d2, 'D#'],\n                        [Lang.Blocks.altino_lite_e, 'E'],\n                        [Lang.Blocks.altino_lite_f, 'F'],\n                        [Lang.Blocks.altino_lite_f2, 'F#'],\n                        [Lang.Blocks.altino_lite_g, 'G'],\n                        [Lang.Blocks.altino_lite_g2, 'G#'],\n                        [Lang.Blocks.altino_lite_a, 'A'],\n                        [Lang.Blocks.altino_lite_a2, 'A#'],\n                        [Lang.Blocks.altino_lite_b, 'B'],\n                    ],\n                    value: 'NOT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'altino_lite_sound',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                NOTE: 1,\n            },\n            class: 'altino_lite_output',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var octave = script.getStringField('OCTAVE', script);\n                var note = script.getStringField('NOTE', script);\n                var octave_int = octave + note;\n\n                if (note == 'NOT') sq.note = 0;\n                else if (octave_int == '1C') sq.note = 1;\n                else if (octave_int == '1C#') sq.note = 2;\n                else if (octave_int == '1D') sq.note = 3;\n                else if (octave_int == '1D#') sq.note = 4;\n                else if (octave_int == '1E') sq.note = 5;\n                else if (octave_int == '1F') sq.note = 6;\n                else if (octave_int == '1F#') sq.note = 7;\n                else if (octave_int == '1G') sq.note = 8;\n                else if (octave_int == '1G#') sq.note = 9;\n                else if (octave_int == '1A') sq.note = 10;\n                else if (octave_int == '1A#') sq.note = 11;\n                else if (octave_int == '1B') sq.note = 12;\n                else if (octave_int == '2C') sq.note = 13;\n                else if (octave_int == '2C#') sq.note = 14;\n                else if (octave_int == '2D') sq.note = 15;\n                else if (octave_int == '2D#') sq.note = 16;\n                else if (octave_int == '2E') sq.note = 17;\n                else if (octave_int == '2F') sq.note = 18;\n                else if (octave_int == '2F#') sq.note = 19;\n                else if (octave_int == '2G') sq.note = 20;\n                else if (octave_int == '2G#') sq.note = 21;\n                else if (octave_int == '2A') sq.note = 22;\n                else if (octave_int == '2A#') sq.note = 23;\n                else if (octave_int == '2B') sq.note = 24;\n                else if (octave_int == '3C') sq.note = 25;\n                else if (octave_int == '3C#') sq.note = 26;\n                else if (octave_int == '3D') sq.note = 27;\n                else if (octave_int == '3D#') sq.note = 28;\n                else if (octave_int == '3E') sq.note = 29;\n                else if (octave_int == '3F') sq.note = 30;\n                else if (octave_int == '3F#') sq.note = 31;\n                else if (octave_int == '3G') sq.note = 32;\n                else if (octave_int == '3G#') sq.note = 33;\n                else if (octave_int == '3A') sq.note = 34;\n                else if (octave_int == '3A#') sq.note = 35;\n                else if (octave_int == '3B') sq.note = 36;\n                else if (octave_int == '4C') sq.note = 37;\n                else if (octave_int == '4C#') sq.note = 38;\n                else if (octave_int == '4D') sq.note = 39;\n                else if (octave_int == '4D#') sq.note = 40;\n                else if (octave_int == '4E') sq.note = 41;\n                else if (octave_int == '4F') sq.note = 42;\n                else if (octave_int == '4F#') sq.note = 43;\n                else if (octave_int == '4G') sq.note = 44;\n                else if (octave_int == '4G#') sq.note = 45;\n                else if (octave_int == '4A') sq.note = 46;\n                else if (octave_int == '4A#') sq.note = 47;\n                else if (octave_int == '4B') sq.note = 48;\n                else if (octave_int == '5C') sq.note = 49;\n                else if (octave_int == '5C#') sq.note = 50;\n                else if (octave_int == '5D') sq.note = 51;\n                else if (octave_int == '5D#') sq.note = 52;\n                else if (octave_int == '5E') sq.note = 53;\n                else if (octave_int == '5F') sq.note = 54;\n                else if (octave_int == '5F#') sq.note = 55;\n                else if (octave_int == '5G') sq.note = 56;\n                else if (octave_int == '5G#') sq.note = 57;\n                else if (octave_int == '5A') sq.note = 58;\n                else if (octave_int == '5A#') sq.note = 59;\n                else if (octave_int == '5B') sq.note = 60;\n                else if (octave_int == '6C') sq.note = 61;\n                else if (octave_int == '6C#') sq.note = 62;\n                else if (octave_int == '6D') sq.note = 63;\n                else if (octave_int == '6D#') sq.note = 64;\n                else if (octave_int == '6E') sq.note = 65;\n                else if (octave_int == '6F') sq.note = 66;\n                else if (octave_int == '6F#') sq.note = 67;\n                else if (octave_int == '6G') sq.note = 68;\n                else if (octave_int == '6G#') sq.note = 69;\n                else if (octave_int == '6A') sq.note = 70;\n                else if (octave_int == '6A#') sq.note = 71;\n                else if (octave_int == '6B') sq.note = 72;\n                else if (octave_int == '7C') sq.note = 73;\n                else if (octave_int == '7C#') sq.note = 74;\n                else if (octave_int == '7D') sq.note = 75;\n                else if (octave_int == '7D#') sq.note = 76;\n                else if (octave_int == '7E') sq.note = 77;\n                else if (octave_int == '7F') sq.note = 78;\n                else if (octave_int == '7F#') sq.note = 79;\n                else if (octave_int == '7G') sq.note = 80;\n                else if (octave_int == '7G#') sq.note = 81;\n                else if (octave_int == '7A') sq.note = 82;\n                else if (octave_int == '7A#') sq.note = 83;\n                else if (octave_int == '7B') sq.note = 84;\n                else if (octave_int == '8C') sq.note = 85;\n                else if (octave_int == '8C#') sq.note = 86;\n                else if (octave_int == '8D') sq.note = 87;\n                else if (octave_int == '8D#') sq.note = 88;\n                else if (octave_int == '8E') sq.note = 89;\n                else if (octave_int == '8F') sq.note = 90;\n                else if (octave_int == '8F#') sq.note = 91;\n                else if (octave_int == '8G') sq.note = 92;\n                else if (octave_int == '8G#') sq.note = 93;\n                else if (octave_int == '8A') sq.note = 94;\n                else if (octave_int == '8A#') sq.note = 95;\n                else if (octave_int == '8B') sq.note = 96;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.sound(%1, %2)'] },\n        },\n        altino_lite_light: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_Led_Forward_Light, '2'],\n                        [Lang.Blocks.altino_lite_Led_Turn_Left_Light, '4'],\n                        [Lang.Blocks.altino_lite_Led_Turn_Right_Light, '5'],\n                        [Lang.Blocks.altino_lite_Led_Brake_Light, '3'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '255'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'altino_lite_light',\n            },\n            paramsKeyMap: {\n                SELECT: 0,\n                ONOFF: 1,\n            },\n            class: 'altino_lite_output',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var select = script.getStringField('SELECT', script);\n                var onoff = script.getStringField('ONOFF', script);\n\n                if (select == '2' && onoff == '255') {\n                    sq.led = sq.led | 0x01;\n                } else if (select == '2' && onoff == '0') {\n                    sq.led = sq.led & 0xfe;\n                }\n\n                if (select == '3' && onoff == '255') {\n                    sq.led = sq.led | 0x02;\n                } else if (select == '3' && onoff == '0') {\n                    sq.led = sq.led & 0xfd;\n                }\n\n                if (select == '4' && onoff == '255') {\n                    sq.led = sq.led | 0x04;\n                } else if (select == '4' && onoff == '0') {\n                    sq.led = sq.led & 0xfb;\n                }\n\n                if (select == '5' && onoff == '255') {\n                    sq.led = sq.led | 0x08;\n                } else if (select == '5' && onoff == '0') {\n                    sq.led = sq.led & 0xf7;\n                }\n                //sq.led = 0xff;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.light(%1, %2)'] },\n        },\n        altino_lite_dot_display_matrix_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'altino_lite_dot_display_matrix_on',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'altino_lite_expert',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var nx = script.getNumberValue('VALUE1');\n                var ny = script.getNumberValue('VALUE2');\n                var mask = 1;\n\n                sq.ascii = 0xff;\n\n                if (ny >= 1 && ny <= 8) {\n                    ny = ny - 1;\n                    mask = mask << ny;\n                    if (nx == 1) {\n                        sq.dot8 |= mask;\n                    } else if (nx == 2) {\n                        sq.dot7 |= mask;\n                    } else if (nx == 3) {\n                        sq.dot6 |= mask;\n                    } else if (nx == 4) {\n                        sq.dot5 |= mask;\n                    } else if (nx == 5) {\n                        sq.dot4 |= mask;\n                    } else if (nx == 6) {\n                        sq.dot3 |= mask;\n                    } else if (nx == 7) {\n                        sq.dot2 |= mask;\n                    } else if (nx == 8) {\n                        sq.dot1 |= mask;\n                    }\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.dot_display_matrix_on(%1, %2)'] },\n        },\n        altino_lite_dot_display_matrix_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'altino_lite_dot_display_matrix_off',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'altino_lite_expert',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var nx = script.getNumberValue('VALUE1');\n                var ny = script.getNumberValue('VALUE2');\n                var mask = 1;\n\n                sq.ascii = 0xff;\n\n                if (ny >= 1 && ny <= 8) {\n                    ny = ny - 1;\n                    mask = mask << ny;\n                    if (nx == 1) {\n                        sq.dot8 &= ~mask;\n                    } else if (nx == 2) {\n                        sq.dot7 &= ~mask;\n                    } else if (nx == 3) {\n                        sq.dot6 &= ~mask;\n                    } else if (nx == 4) {\n                        sq.dot5 &= ~mask;\n                    } else if (nx == 5) {\n                        sq.dot4 &= ~mask;\n                    } else if (nx == 6) {\n                        sq.dot3 &= ~mask;\n                    } else if (nx == 7) {\n                        sq.dot2 &= ~mask;\n                    } else if (nx == 8) {\n                        sq.dot1 &= ~mask;\n                    }\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.dot_display_matrix_off(%1, %2)'] },\n        },\n        altino_lite_light_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    null,\n                ],\n                type: 'altino_lite_light_hex'\n            },\n            paramsKeyMap: {\n                LSB: 0\n            },\n            class: 'altino_lite_expert',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var lsb = parseInt(Number(script.getStringValue('LSB')), 10);\n                sq.led = lsb;\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.light_hex(%1)'] },\n        },\n        altino_lite_dot_display: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['A'],\n                    },\n                    null,\n                ],\n                type: 'altino_lite_dot_display',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'altino_lite_output',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var str = script.getStringValue('VALUE');\n                sq.ascii = str.charCodeAt(0);\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AltinoLite.dot_display(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        altino_lite_dot_display_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_dot_line_1, '1'],\n                        [Lang.Blocks.altino_lite_dot_line_2, '2'],\n                        [Lang.Blocks.altino_lite_dot_line_3, '3'],\n                        [Lang.Blocks.altino_lite_dot_line_4, '4'],\n                        [Lang.Blocks.altino_lite_dot_line_5, '5'],\n                        [Lang.Blocks.altino_lite_dot_line_6, '6'],\n                        [Lang.Blocks.altino_lite_dot_line_7, '7'],\n                        [Lang.Blocks.altino_lite_dot_line_8, '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '1'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '1'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '1'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '1'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '1'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '1'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '1'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_lite_h2, '1'],\n                        [Lang.Blocks.altino_lite_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null, null, null, null, null, null, null],\n                type: 'altino_lite_dot_display_line',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                SW1: 1,\n                SW2: 2,\n                SW3: 3,\n                SW4: 4,\n                SW5: 5,\n                SW6: 6,\n                SW7: 7,\n                SW8: 8,\n            },\n            class: 'altino_lite_output',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var line = script.getStringField('LINE', script);\n\n                sq.ascii = 0xff;\n\n                var dots = [\n                    script.getStringField('SW1', script),\n                    script.getStringField('SW2', script),\n                    script.getStringField('SW3', script),\n                    script.getStringField('SW4', script),\n                    script.getStringField('SW5', script),\n                    script.getStringField('SW6', script),\n                    script.getStringField('SW7', script),\n                    script.getStringField('SW8', script),\n                ];\n\n                var mask = 0;\n\n                if (line == '1') {\n                    mask = 0x01;\n                } else if (line == '2') {\n                    mask = 0x02;\n                } else if (line == '3') {\n                    mask = 0x04;\n                } else if (line == '4') {\n                    mask = 0x08;\n                } else if (line == '5') {\n                    mask = 0x10;\n                } else if (line == '6') {\n                    mask = 0x20;\n                } else if (line == '7') {\n                    mask = 0x40;\n                } else if (line == '8') {\n                    mask = 0x80;\n                }\n\n                if (dots[7] == '1') {\n                    sq.dot1 |= mask;\n                } else {\n                    sq.dot1 &= ~mask;\n                }\n\n                if (dots[6] == '1') {\n                    sq.dot2 |= mask;\n                } else {\n                    sq.dot2 &= ~mask;\n                }\n\n                if (dots[5] == '1') {\n                    sq.dot3 |= mask;\n                } else {\n                    sq.dot3 &= ~mask;\n                }\n\n                if (dots[4] == '1') {\n                    sq.dot4 |= mask;\n                } else {\n                    sq.dot4 &= ~mask;\n                }\n\n                if (dots[3] == '1') {\n                    sq.dot5 |= mask;\n                } else {\n                    sq.dot5 &= ~mask;\n                }\n\n                if (dots[2] == '1') {\n                    sq.dot6 |= mask;\n                } else {\n                    sq.dot6 &= ~mask;\n                }\n\n                if (dots[1] == '1') {\n                    sq.dot7 |= mask;\n                } else {\n                    sq.dot7 &= ~mask;\n                }\n\n                if (dots[0] == '1') {\n                    sq.dot8 |= mask;\n                } else {\n                    sq.dot8 &= ~mask;\n                }\n\n                //sq.led = 0xff;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.dot_display_line(%1, %2, %3, %4, %5, %6, %7, %8)'] },\n        },\n        altino_lite_dot_display_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    null,\n                ],\n                type: 'altino_lite_dot_display_hex',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n                VALUE6: 5,\n                VALUE7: 6,\n                VALUE8: 7,\n            },\n            class: 'altino_lite_expert',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.ascii = 0xff;\n                sq.dot1 = parseInt(Number(script.getStringValue('VALUE8')), 10);\n                sq.dot2 = parseInt(Number(script.getStringValue('VALUE7')), 10);\n                sq.dot3 = parseInt(Number(script.getStringValue('VALUE6')), 10);\n                sq.dot4 = parseInt(Number(script.getStringValue('VALUE5')), 10);\n                sq.dot5 = parseInt(Number(script.getStringValue('VALUE4')), 10);\n                sq.dot6 = parseInt(Number(script.getStringValue('VALUE3')), 10);\n                sq.dot7 = parseInt(Number(script.getStringValue('VALUE2')), 10);\n                sq.dot8 = parseInt(Number(script.getStringValue('VALUE1')), 10);\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.dot_display_hex(%1, %2, %3, %4, %5, %6, %7, %8)'] },\n        },\n        altino_lite_ir_reset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'altino_lite_ir_reset',\n            },\n            paramsKeyMap: {\n                DEVICE : 0,\n            },\n            class: 'altino_lite_output',\n            isNotFor: ['altino_lite'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                sq.ir = 6;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoLite.ir_reset'] },\n        },\n        //endregion Altino 알티노\n    };\n};\n\nmodule.exports = Entry.AltinoLite;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_altino_neo.js",
    "content": "'use strict';\n\nEntry.AltinoNeo = {\n    PORT_MAP: {\n        rightWheel: 0,\n        leftWheel: 0,\n        steering: 0,\n        led1: 0,\n        led2: 0,\n        note: 0,\n        ascii: 0,\n        dot1: 0,\n        dot2: 0,\n        dot3: 0,\n        dot4: 0,\n        dot5: 0,\n        dot6: 0,\n        dot7: 0,\n        dot8: 0,\n    },\n    setZero: function() {\n        var portMap = Entry.AltinoNeo.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        // var Altino = Entry.Altino;\n        // Altino.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    id: '18.4',\n    name: 'altino_neo',\n    url: 'http://saeon.co.kr/',\n    imageName: 'altino_neo.png',\n    title: {\n        en: 'Altino Neo',\n        ko: '알티노 네오',\n    },\n};\n\nEntry.AltinoNeo.blockMenuBlocks = [\n    'altino_neo_analogValue',\n    'altino_neo_stopAll',\n    'altino_neo_rear_wheel',\n    'altino_neo_steering',\n    'altino_neo_sound',\n    'altino_neo_light',\n    'altino_neo_dot_display',\n    'altino_neo_dot_display_line',\n    'altino_neo_steering_hex',\n    'altino_neo_light_hex',\n    'altino_neo_sound_hex',\n    'altino_neo_dot_display_hex',\n    'altino_neo_dot_display_matrix_on',\n    'altino_neo_dot_display_matrix_off',\n];\n\nEntry.AltinoNeo.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                altino_neo_BAT: '배터리',\n                altino_neo_CDS: '조도',\n                altino_neo_TOF1: 'TOF-1',\n                altino_neo_TOF2: 'TOF-2',\n                altino_neo_TOF3: 'TOF-3',\n                altino_neo_TOF4: 'TOF-4',\n                altino_neo_TOF5: 'TOF-5',\n                altino_neo_TOF6: 'TOF-6',\n                altino_neo_ACC_X: '가속도-X',\n                altino_neo_ACC_Y: '가속도-Y',\n                altino_neo_ACC_Z: '가속도-Z',\n                altino_neo_MAG_X: '지자기-X',\n                altino_neo_MAG_Y: '지자기-Y',\n                altino_neo_MAG_Z: '지자기-Z',\n                altino_neo_GYRO_X: '자이로-X',\n                altino_neo_GYRO_Y: '자이로-Y',\n                altino_neo_GYRO_Z: '자이로-Z',\n                altino_neo_AHRS_Roll: '횡전각',\n                altino_neo_AHRS_Pitch: '종전각',\n                altino_neo_AHRS_Yaw: '편향각',\n                altino_neo_Temp: '온도',\n                altino_neo_Left_Wheel_Torque: '왼쪽 뒷바퀴 전류',\n                altino_neo_Right_Wheel_Torque: '오른쪽 뒷바퀴 전류',\n                altino_neo_Led_Brake_Light: '브레이크',\n                altino_neo_Led_Forward_Light: '전방',\n                altino_neo_Led_Backward_Light: '후방',\n                altino_neo_Led_Turn_Left_Light: '왼쪽 방향지시',\n                altino_neo_Led_Turn_Right_Light: '오른쪽 방향지시',\n                altino_neo_Line: '번째 줄',\n                altino_neo_Steering_Angle_Center: '중앙',\n                altino_neo_Steering_Angle_Left10: '왼쪽으로-10',\n                altino_neo_Steering_Angle_Left15: '왼쪽으로-15',\n                altino_neo_Steering_Angle_Left20: '왼쪽으로-20',\n                altino_neo_Steering_Angle_Left5: '왼쪽으로-5',\n                altino_neo_Steering_Angle_Right10: '오른쪽으로-10',\n                altino_neo_Steering_Angle_Right15: '오른쪽으로-15',\n                altino_neo_Steering_Angle_Right20: '오른쪽으로-20',\n                altino_neo_Steering_Angle_Right5: '오른쪽으로-5',\n                altino_neo_Value: '출력 값',\n                altino_neo_a: 'A(라)',\n                altino_neo_a2: 'A#(라#)',\n                altino_neo_b: 'B(시)',\n                altino_neo_c: 'C(도)',\n                altino_neo_c2: 'C#(도#)',\n                altino_neo_d: 'D(레)',\n                altino_neo_d2: 'D#(레#)',\n                altino_neo_dot_display_1: '한문자',\n                altino_neo_dot_display_2: '출력하기',\n                altino_neo_e: 'E(미)',\n                altino_neo_f: 'F(파)',\n                altino_neo_f2: 'F#(파#)',\n                altino_neo_g: 'G(솔)',\n                altino_neo_g2: 'G#(솔#)',\n                altino_neo_sound_oct: '옥타브',\n                altino_neo_h: '끄기',\n                altino_neo_h2: '켜기',\n                altino_neo_leftWheel: '왼쪽',\n                altino_neo_melody_ms: '연주하기',\n                altino_neo_outputValue: '출력 값',\n                altino_neo_rightWheel: '오른쪽',\n                altino_neo_set: '로 정하기',\n                altino_neo_stopAll: '모두',\n                altino_neo_stopDrive: '주행',\n                altino_neo_stopSteering: '조향',\n                altino_neo_stopSound: '소리',\n                altino_neo_stopLight: '라이트',\n                altino_neo_stopDisplay: '표시하기',\n                altino_neo_dot_line_1: '1행',\n                altino_neo_dot_line_2: '2행',\n                altino_neo_dot_line_3: '3행',\n                altino_neo_dot_line_4: '4행',\n                altino_neo_dot_line_5: '5행',\n                altino_neo_dot_line_6: '6행',\n                altino_neo_dot_line_7: '7행',\n                altino_neo_dot_line_8: '8행',\n            },\n            template: {\n                altino_neo_analogValue: '알티노 네오 %1 센서값',\n                altino_neo_stopAll: '정지 %1 %2',\n                altino_neo_dot_display: '표시하기 %1 %2',\n                altino_neo_dot_display_line: '표시하기 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n                altino_neo_dot_display_hex: '표시하기 %1 %2 %3 %4 %5 %6 %7 %8 %9',\n                altino_neo_dot_display_matrix_on: '표시하기 켜기 X:%1 Y:%2 %3',\n                altino_neo_dot_display_matrix_off: '표시하기 끄기 X:%1 Y:%2 %3',\n                altino_neo_light: '라이트%1 %2 %3',\n                altino_neo_light_hex: '라이트%1 %2 %3',\n                altino_neo_sound_hex: '소리%1 %2',\n                altino_neo_rear_wheel: '뒷바퀴 구동 좌:%1 우:%2%3',\n                altino_neo_sound: '소리 %1 %2 %3',\n                altino_neo_steering_hex: '조향 %1%2',\n                altino_neo_steering: '조향 %1°%2',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                altino_neo_BAT: 'BAT',\n                altino_neo_CDS: 'CDS',\n                altino_neo_TOF1: 'TOF-1',\n                altino_neo_TOF2: 'TOF-2',\n                altino_neo_TOF3: 'TOF-3',\n                altino_neo_TOF4: 'TOF-4',\n                altino_neo_TOF5: 'TOF-5',\n                altino_neo_TOF6: 'TOF-6',\n                altino_neo_ACC_X: 'ACC-X',\n                altino_neo_ACC_Y: 'ACC-Y',\n                altino_neo_ACC_Z: 'ACC-Z',\n                altino_neo_MAG_X: 'MAG-X',\n                altino_neo_MAG_Y: 'MAG-Y',\n                altino_neo_MAG_Z: 'MAG-Z',\n                altino_neo_GYRO_X: 'GYRO-X',\n                altino_neo_GYRO_Y: 'GYRO-Y',\n                altino_neo_GYRO_Z: 'GYRO-Z',\n                altino_neo_AHRS_Roll: 'ROLL',\n                altino_neo_AHRS_Pitch: 'PITCH',\n                altino_neo_AHRS_Yaw: 'YAW',\n                altino_neo_Temp: 'TEMP',\n                altino_neo_Left_Wheel_Torque: 'LEFT TORQUE',\n                altino_neo_Right_Wheel_Torque: 'RIGHT TORQUE',\n                altino_neo_Led_Brake_Light: 'Brake',\n                altino_neo_Led_Forward_Light: 'Forward',\n                altino_neo_Led_Backward_Light: 'Backward',\n                altino_neo_Led_Turn_Left_Light: 'Turn Left',\n                altino_neo_Led_Turn_Right_Light: 'Turn Right',\n                altino_neo_Line: 'line',\n                altino_neo_Steering_Angle_Center: 'Center-0',\n                altino_neo_Steering_Angle_Left10: 'Left-10',\n                altino_neo_Steering_Angle_Left15: 'Left-15',\n                altino_neo_Steering_Angle_Left20: 'Left-20',\n                altino_neo_Steering_Angle_Left5: 'Left-5',\n                altino_neo_Steering_Angle_Right10: 'Right-10',\n                altino_neo_Steering_Angle_Right15: 'Right-15',\n                altino_neo_Steering_Angle_Right20: 'Right-20',\n                altino_neo_Steering_Angle_Right5: 'Right-5',\n                altino_neo_Value: 'output value',\n                altino_neo_a: 'A(la)',\n                altino_neo_a2: 'A#(la#)',\n                altino_neo_b: 'B(si)',\n                altino_neo_c: 'C(do)',\n                altino_neo_c2: 'C#(do#)',\n                altino_neo_d: 'D(re)',\n                altino_neo_d2: 'D#(re#)',\n                altino_neo_dot_display_1: 'one char',\n                altino_neo_dot_display_2: 'display',\n                altino_neo_e: 'E(mi)',\n                altino_neo_f: 'F(fa)',\n                altino_neo_f2: 'F#(fa#)',\n                altino_neo_g: 'G(sol)',\n                altino_neo_g2: 'G#(sol#)',\n                altino_neo_sound_oct: 'Oct',\n                altino_neo_h: 'Off',\n                altino_neo_h2: 'On',\n                altino_neo_leftWheel: 'left',\n                altino_neo_melody_ms: 'play',\n                altino_neo_outputValue: 'output',\n                altino_neo_rightWheel: 'right',\n                altino_neo_set: ' display',\n                altino_neo_stopAll: 'All',\n                altino_neo_stopDrive: 'Drive',\n                altino_neo_stopSteering: 'Steering',\n                altino_neo_stopSound: 'Sound',\n                altino_neo_stopLight: 'Light',\n                altino_neo_stopDisplay: 'Display',\n                altino_neo_dot_line_1: 'Line-1',\n                altino_neo_dot_line_2: 'Line-2',\n                altino_neo_dot_line_3: 'Line-3',\n                altino_neo_dot_line_4: 'Line-4',\n                altino_neo_dot_line_5: 'Line-5',\n                altino_neo_dot_line_6: 'Line-6',\n                altino_neo_dot_line_7: 'Line-7',\n                altino_neo_dot_line_8: 'Line-8',\n            },\n            template: {\n                altino_neo_analogValue: 'Altino neo %1 sensor value',\n                altino_neo_stopAll: 'Stop %1°%2',\n                altino_neo_dot_display: 'Display %1 %2',\n                altino_neo_dot_display_line: 'Display %1 %2 %3 %4 %5 %6 %7 %8 %9 %10',\n                altino_neo_dot_display_hex: 'Display %1 %2 %3 %4 %5 %6 %7 %8 %9',\n                altino_neo_dot_display_matrix_on: 'Display On X:%1 Y:%2 %3',\n                altino_neo_dot_display_matrix_off: 'Display Off X:%1 Y:%2 %3',\n                altino_neo_light: 'Light %1 %2 %3',\n                altino_neo_light_hex: 'Light %1 %2 %3',\n                altino_neo_sound_hex: 'Sound %1 %2',\n                altino_neo_rear_wheel: 'Go L:%1 R:%2%3',\n                altino_neo_sound: 'Sound %1 %2 %3',\n                altino_neo_steering_hex: 'Steering %1%2',\n                altino_neo_steering: 'Steering %1°%2',\n            },\n        },\n    };\n};\n\nEntry.AltinoNeo.getBlocks = function() {\n    return {\n        //region Altino 알티노\n        altino_neo_analogValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_CDS, 'cds'],\n                        [Lang.Blocks.altino_neo_TOF1, 'tof1'],\n                        [Lang.Blocks.altino_neo_TOF2, 'tof2'],\n                        [Lang.Blocks.altino_neo_TOF3, 'tof3'],\n                        [Lang.Blocks.altino_neo_TOF4, 'tof4'],\n                        [Lang.Blocks.altino_neo_TOF5, 'tof5'],\n                        [Lang.Blocks.altino_neo_TOF6, 'tof6'],\n                        [Lang.Blocks.altino_neo_BAT, 'bat'],\n                        [Lang.Blocks.altino_neo_ACC_X, 'accx'],\n                        [Lang.Blocks.altino_neo_ACC_Y, 'accy'],\n                        [Lang.Blocks.altino_neo_ACC_Z, 'accz'],\n                        [Lang.Blocks.altino_neo_MAG_X, 'magx'],\n                        [Lang.Blocks.altino_neo_MAG_Y, 'magy'],\n                        [Lang.Blocks.altino_neo_MAG_Z, 'magz'],\n                        [Lang.Blocks.altino_neo_GYRO_X, 'gyrox'],\n                        [Lang.Blocks.altino_neo_GYRO_Y, 'gyroy'],\n                        [Lang.Blocks.altino_neo_GYRO_Z, 'gyroz'],\n                        [Lang.Blocks.altino_neo_AHRS_Roll, 'roll'],\n                        [Lang.Blocks.altino_neo_AHRS_Pitch, 'pitch'],\n                        [Lang.Blocks.altino_neo_AHRS_Yaw, 'yaw'],\n                        [Lang.Blocks.altino_neo_Temp, 'temp'],\n                        [Lang.Blocks.altino_neo_Left_Wheel_Torque, 'leftTorque'],\n                        [Lang.Blocks.altino_neo_Right_Wheel_Torque, 'rightTorque'],\n                    ],\n                    value: 'cds',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'altino_neo_analogValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'altino_neo_sensor',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['AltinoNeo.analog_value(%1)'] },\n        },\n        altino_neo_stopAll: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_stopAll, 'All'],\n                        [Lang.Blocks.altino_neo_stopDrive, 'Drive'],\n                        [Lang.Blocks.altino_neo_stopSteering, 'Steering'],\n                        [Lang.Blocks.altino_neo_stopSound, 'Sound'],\n                        [Lang.Blocks.altino_neo_stopLight, 'Light'],\n                        [Lang.Blocks.altino_neo_stopDisplay, 'Display'],\n                    ],\n                    value: 'All',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'altino_neo_stopAll',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'altino_neo_output',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'All') {\n                    sq.steering = 0;\n                    sq.rightWheel = 0;\n                    sq.leftWheel = 0;\n                    sq.note = 0;\n                    sq.led1 = 0;\n                    sq.led2 = 0;\n                    sq.ascii = 0;\n                    sq.dot1 = 0;\n                    sq.dot2 = 0;\n                    sq.dot3 = 0;\n                    sq.dot4 = 0;\n                    sq.dot5 = 0;\n                    sq.dot6 = 0;\n                    sq.dot7 = 0;\n                    sq.dot8 = 0;\n                } else if (direction == 'Drive') {\n                    sq.rightWheel = 0;\n                    sq.leftWheel = 0;\n                } else if (direction == 'Steering') {\n                    sq.steering = 0;\n                } else if (direction == 'Sound') {\n                    sq.note = 0;\n                } else if (direction == 'Light') {\n                    sq.led1 = 0;\n                    sq.led2 = 0;\n                } else if (direction == 'Display') {\n                    sq.ascii = 0;\n                    sq.dot1 = 0;\n                    sq.dot2 = 0;\n                    sq.dot3 = 0;\n                    sq.dot4 = 0;\n                    sq.dot5 = 0;\n                    sq.dot6 = 0;\n                    sq.dot7 = 0;\n                    sq.dot8 = 0;\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.stop(%1)'] },\n        },\n        altino_neo_steering: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_Steering_Angle_Center, 'Center'],\n                        [Lang.Blocks.altino_neo_Steering_Angle_Left5, 'Left5'],\n                        [Lang.Blocks.altino_neo_Steering_Angle_Left10, 'Left10'],\n                        [Lang.Blocks.altino_neo_Steering_Angle_Left15, 'Left15'],\n                        [Lang.Blocks.altino_neo_Steering_Angle_Left20, 'Left20'],\n                        [Lang.Blocks.altino_neo_Steering_Angle_Right5, 'Right5'],\n                        [Lang.Blocks.altino_neo_Steering_Angle_Right10, 'Right10'],\n                        [Lang.Blocks.altino_neo_Steering_Angle_Right15, 'Right15'],\n                        [Lang.Blocks.altino_neo_Steering_Angle_Right20, 'Right20'],\n                    ],\n                    value: 'Center',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'altino_neo_steering',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'altino_neo_output',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'Center') {\n                    sq.steering = 0;\n                } else if (direction == 'Left5') {\n                    sq.steering = 0xe0;\n                } else if (direction == 'Left10') {\n                    sq.steering = 0xc0;\n                } else if (direction == 'Left15') {\n                    sq.steering = 0xa1;\n                } else if (direction == 'Left20') {\n                    sq.steering = 0x81;\n                } else if (direction == 'Right5') {\n                    sq.steering = 31;\n                } else if (direction == 'Right10') {\n                    sq.steering = 63;\n                } else if (direction == 'Right15') {\n                    sq.steering = 94;\n                } else if (direction == 'Right20') {\n                    sq.steering = 126;\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.steering(%1)'] },\n        },\n        altino_neo_steering_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'altino_neo_steering_hex',\n            },\n            paramsKeyMap: {\n                steerVal: 0,\n            },\n            class: 'altino_neo_expert',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.steering = parseInt(Number(script.getStringValue('steerVal')), 10);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.steering_hex(%1)'] },\n        },\n        altino_neo_sound_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'altino_neo_sound_hex',\n            },\n            paramsKeyMap: {\n                soundVal: 0,\n            },\n            class: 'altino_neo_expert',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.note = parseInt(Number(script.getStringValue('soundVal')), 10);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.sound_hex(%1)'] },\n        },\n        altino_neo_rear_wheel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'altino_neo_rear_wheel',\n            },\n            paramsKeyMap: {\n                leftWheel: 0,\n                rightWheel: 1,\n            },\n            class: 'altino_neo_output',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                sq.rightWheel = script.getNumberValue('rightWheel');\n                sq.leftWheel = script.getNumberValue('leftWheel');\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.rear_wheel(%1, %2)'] },\n        },\n        altino_neo_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {                    \n                    type: 'Dropdown',\n                    options: [\n                        ['1-' + Lang.Blocks.altino_neo_sound_oct, '1'],\n                        ['2-' + Lang.Blocks.altino_neo_sound_oct, '2'],\n                        ['3-' + Lang.Blocks.altino_neo_sound_oct, '3'],\n                        ['4-' + Lang.Blocks.altino_neo_sound_oct, '4'],\n                        ['5-' + Lang.Blocks.altino_neo_sound_oct, '5'],\n                        ['6-' + Lang.Blocks.altino_neo_sound_oct, '6'],\n                        ['7-' + Lang.Blocks.altino_neo_sound_oct, '7'],\n                        ['8-' + Lang.Blocks.altino_neo_sound_oct, '8'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h, 'NOT'],\n                        [Lang.Blocks.altino_neo_c, 'C'],\n                        [Lang.Blocks.altino_neo_c2, 'C#'],\n                        [Lang.Blocks.altino_neo_d, 'D'],\n                        [Lang.Blocks.altino_neo_d2, 'D#'],\n                        [Lang.Blocks.altino_neo_e, 'E'],\n                        [Lang.Blocks.altino_neo_f, 'F'],\n                        [Lang.Blocks.altino_neo_f2, 'F#'],\n                        [Lang.Blocks.altino_neo_g, 'G'],\n                        [Lang.Blocks.altino_neo_g2, 'G#'],\n                        [Lang.Blocks.altino_neo_a, 'A'],\n                        [Lang.Blocks.altino_neo_a2, 'A#'],\n                        [Lang.Blocks.altino_neo_b, 'B'],\n                    ],\n                    value: 'NOT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'altino_neo_sound',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                NOTE: 1,\n            },\n            class: 'altino_neo_output',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var octave = script.getStringField('OCTAVE', script);\n                var note = script.getStringField('NOTE', script);\n                var octave_int = octave + note;\n\n                if (note == 'NOT') sq.note = 0;\n                else if (octave_int == '1C') sq.note = 1;\n                else if (octave_int == '1C#') sq.note = 2;\n                else if (octave_int == '1D') sq.note = 3;\n                else if (octave_int == '1D#') sq.note = 4;\n                else if (octave_int == '1E') sq.note = 5;\n                else if (octave_int == '1F') sq.note = 6;\n                else if (octave_int == '1F#') sq.note = 7;\n                else if (octave_int == '1G') sq.note = 8;\n                else if (octave_int == '1G#') sq.note = 9;\n                else if (octave_int == '1A') sq.note = 10;\n                else if (octave_int == '1A#') sq.note = 11;\n                else if (octave_int == '1B') sq.note = 12;\n                else if (octave_int == '2C') sq.note = 13;\n                else if (octave_int == '2C#') sq.note = 14;\n                else if (octave_int == '2D') sq.note = 15;\n                else if (octave_int == '2D#') sq.note = 16;\n                else if (octave_int == '2E') sq.note = 17;\n                else if (octave_int == '2F') sq.note = 18;\n                else if (octave_int == '2F#') sq.note = 19;\n                else if (octave_int == '2G') sq.note = 20;\n                else if (octave_int == '2G#') sq.note = 21;\n                else if (octave_int == '2A') sq.note = 22;\n                else if (octave_int == '2A#') sq.note = 23;\n                else if (octave_int == '2B') sq.note = 24;\n                else if (octave_int == '3C') sq.note = 25;\n                else if (octave_int == '3C#') sq.note = 26;\n                else if (octave_int == '3D') sq.note = 27;\n                else if (octave_int == '3D#') sq.note = 28;\n                else if (octave_int == '3E') sq.note = 29;\n                else if (octave_int == '3F') sq.note = 30;\n                else if (octave_int == '3F#') sq.note = 31;\n                else if (octave_int == '3G') sq.note = 32;\n                else if (octave_int == '3G#') sq.note = 33;\n                else if (octave_int == '3A') sq.note = 34;\n                else if (octave_int == '3A#') sq.note = 35;\n                else if (octave_int == '3B') sq.note = 36;\n                else if (octave_int == '4C') sq.note = 37;\n                else if (octave_int == '4C#') sq.note = 38;\n                else if (octave_int == '4D') sq.note = 39;\n                else if (octave_int == '4D#') sq.note = 40;\n                else if (octave_int == '4E') sq.note = 41;\n                else if (octave_int == '4F') sq.note = 42;\n                else if (octave_int == '4F#') sq.note = 43;\n                else if (octave_int == '4G') sq.note = 44;\n                else if (octave_int == '4G#') sq.note = 45;\n                else if (octave_int == '4A') sq.note = 46;\n                else if (octave_int == '4A#') sq.note = 47;\n                else if (octave_int == '4B') sq.note = 48;\n                else if (octave_int == '5C') sq.note = 49;\n                else if (octave_int == '5C#') sq.note = 50;\n                else if (octave_int == '5D') sq.note = 51;\n                else if (octave_int == '5D#') sq.note = 52;\n                else if (octave_int == '5E') sq.note = 53;\n                else if (octave_int == '5F') sq.note = 54;\n                else if (octave_int == '5F#') sq.note = 55;\n                else if (octave_int == '5G') sq.note = 56;\n                else if (octave_int == '5G#') sq.note = 57;\n                else if (octave_int == '5A') sq.note = 58;\n                else if (octave_int == '5A#') sq.note = 59;\n                else if (octave_int == '5B') sq.note = 60;\n                else if (octave_int == '6C') sq.note = 61;\n                else if (octave_int == '6C#') sq.note = 62;\n                else if (octave_int == '6D') sq.note = 63;\n                else if (octave_int == '6D#') sq.note = 64;\n                else if (octave_int == '6E') sq.note = 65;\n                else if (octave_int == '6F') sq.note = 66;\n                else if (octave_int == '6F#') sq.note = 67;\n                else if (octave_int == '6G') sq.note = 68;\n                else if (octave_int == '6G#') sq.note = 69;\n                else if (octave_int == '6A') sq.note = 70;\n                else if (octave_int == '6A#') sq.note = 71;\n                else if (octave_int == '6B') sq.note = 72;\n                else if (octave_int == '7C') sq.note = 73;\n                else if (octave_int == '7C#') sq.note = 74;\n                else if (octave_int == '7D') sq.note = 75;\n                else if (octave_int == '7D#') sq.note = 76;\n                else if (octave_int == '7E') sq.note = 77;\n                else if (octave_int == '7F') sq.note = 78;\n                else if (octave_int == '7F#') sq.note = 79;\n                else if (octave_int == '7G') sq.note = 80;\n                else if (octave_int == '7G#') sq.note = 81;\n                else if (octave_int == '7A') sq.note = 82;\n                else if (octave_int == '7A#') sq.note = 83;\n                else if (octave_int == '7B') sq.note = 84;\n                else if (octave_int == '8C') sq.note = 85;\n                else if (octave_int == '8C#') sq.note = 86;\n                else if (octave_int == '8D') sq.note = 87;\n                else if (octave_int == '8D#') sq.note = 88;\n                else if (octave_int == '8E') sq.note = 89;\n                else if (octave_int == '8F') sq.note = 90;\n                else if (octave_int == '8F#') sq.note = 91;\n                else if (octave_int == '8G') sq.note = 92;\n                else if (octave_int == '8G#') sq.note = 93;\n                else if (octave_int == '8A') sq.note = 94;\n                else if (octave_int == '8A#') sq.note = 95;\n                else if (octave_int == '8B') sq.note = 96;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.sound(%1, %2)'] },\n        },\n        altino_neo_light: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_Led_Forward_Light, '2'],\n                        [Lang.Blocks.altino_neo_Led_Turn_Left_Light, '5'],\n                        [Lang.Blocks.altino_neo_Led_Turn_Right_Light, '6'],\n                        [Lang.Blocks.altino_neo_Led_Brake_Light, '4'],\n                        [Lang.Blocks.altino_neo_Led_Backward_Light, '3'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '255'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'altino_neo_light',\n            },\n            paramsKeyMap: {\n                SELECT: 0,\n                ONOFF: 1,\n            },\n            class: 'altino_neo_output',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var select = script.getStringField('SELECT', script);\n                var onoff = script.getStringField('ONOFF', script);\n\n                if (select == '2' && onoff == '255') {\n                    sq.led2 = sq.led2 | 0x03;\n                } else if (select == '2' && onoff == '0') {\n                    sq.led2 = sq.led2 & 0xfc;\n                }\n\n                if (select == '3' && onoff == '255') {\n                    sq.led2 = sq.led2 | 0x0c;\n                } else if (select == '3' && onoff == '0') {\n                    sq.led2 = sq.led2 & 0xf3;\n                }\n\n                if (select == '4' && onoff == '255') {\n                    sq.led1 = sq.led1 | 0x03;\n                } else if (select == '4' && onoff == '0') {\n                    sq.led1 = sq.led1 & 0xfc;\n                }\n\n                if (select == '5' && onoff == '255') {\n                    sq.led2 = sq.led2 | 0xa0;\n                } else if (select == '5' && onoff == '0') {\n                    sq.led2 = sq.led2 & 0x5f;\n                }\n\n                if (select == '6' && onoff == '255') {\n                    sq.led2 = sq.led2 | 0x50;\n                } else if (select == '6' && onoff == '0') {\n                    sq.led2 = sq.led2 & 0xaf;\n                }\n                //sq.led = 0xff;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.light(%1, %2)'] },\n        },\n        altino_neo_dot_display_matrix_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'altino_neo_dot_display_matrix_on',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'altino_neo_expert',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var nx = script.getNumberValue('VALUE1');\n                var ny = script.getNumberValue('VALUE2');\n                var mask = 1;\n\n                sq.ascii = 0xff;\n\n                if (ny >= 1 && ny <= 8) {\n                    ny = ny - 1;\n                    mask = mask << ny;\n                    if (nx == 1) {\n                        sq.dot8 |= mask;\n                    } else if (nx == 2) {\n                        sq.dot7 |= mask;\n                    } else if (nx == 3) {\n                        sq.dot6 |= mask;\n                    } else if (nx == 4) {\n                        sq.dot5 |= mask;\n                    } else if (nx == 5) {\n                        sq.dot4 |= mask;\n                    } else if (nx == 6) {\n                        sq.dot3 |= mask;\n                    } else if (nx == 7) {\n                        sq.dot2 |= mask;\n                    } else if (nx == 8) {\n                        sq.dot1 |= mask;\n                    }\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.dot_display_matrix_on(%1, %2)'] },\n        },\n        altino_neo_dot_display_matrix_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'altino_neo_dot_display_matrix_off',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'altino_neo_expert',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var nx = script.getNumberValue('VALUE1');\n                var ny = script.getNumberValue('VALUE2');\n                var mask = 1;\n\n                sq.ascii = 0xff;\n\n                if (ny >= 1 && ny <= 8) {\n                    ny = ny - 1;\n                    mask = mask << ny;\n                    if (nx == 1) {\n                        sq.dot8 &= ~mask;\n                    } else if (nx == 2) {\n                        sq.dot7 &= ~mask;\n                    } else if (nx == 3) {\n                        sq.dot6 &= ~mask;\n                    } else if (nx == 4) {\n                        sq.dot5 &= ~mask;\n                    } else if (nx == 5) {\n                        sq.dot4 &= ~mask;\n                    } else if (nx == 6) {\n                        sq.dot3 &= ~mask;\n                    } else if (nx == 7) {\n                        sq.dot2 &= ~mask;\n                    } else if (nx == 8) {\n                        sq.dot1 &= ~mask;\n                    }\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.dot_display_matrix_off(%1, %2)'] },\n        },\n        altino_neo_light_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    null,\n                ],\n                type: 'altino_neo_light_hex'\n            },\n            paramsKeyMap: {\n                MSB: 0,\n                LSB: 1,            \n            },\n            class: 'altino_neo_expert',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                // var sq = Entry.hw.sendQueue;\n                // var lsb = parseInt(Number(script.getStringValue('LSB')), 10);\n                // sq.led = lsb;\n\n                var sq = Entry.hw.sendQueue;\n                var msb = parseInt(Number(script.getStringValue('MSB')), 10);\n                var lsb = parseInt(Number(script.getStringValue('LSB')), 10);\n\n                sq.led1 = (msb & 0x03) | (sq.led1 & 0xfc);\n                sq.led2 = lsb;\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.light_hex(%1, %2)'] },\n        },\n        altino_neo_dot_display: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['A'],\n                    },\n                    null,\n                ],\n                type: 'altino_neo_dot_display',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'altino_neo_output',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var str = script.getStringValue('VALUE');\n                sq.ascii = str.charCodeAt(0);\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'AltinoNeo.dot_display(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        altino_neo_dot_display_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_dot_line_1, '1'],\n                        [Lang.Blocks.altino_neo_dot_line_2, '2'],\n                        [Lang.Blocks.altino_neo_dot_line_3, '3'],\n                        [Lang.Blocks.altino_neo_dot_line_4, '4'],\n                        [Lang.Blocks.altino_neo_dot_line_5, '5'],\n                        [Lang.Blocks.altino_neo_dot_line_6, '6'],\n                        [Lang.Blocks.altino_neo_dot_line_7, '7'],\n                        [Lang.Blocks.altino_neo_dot_line_8, '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '1'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '1'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '1'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '1'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '1'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '1'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '1'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.altino_neo_h2, '1'],\n                        [Lang.Blocks.altino_neo_h, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null, null, null, null, null, null, null],\n                type: 'altino_neo_dot_display_line',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                SW1: 1,\n                SW2: 2,\n                SW3: 3,\n                SW4: 4,\n                SW5: 5,\n                SW6: 6,\n                SW7: 7,\n                SW8: 8,\n            },\n            class: 'altino_neo_output',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var line = script.getStringField('LINE', script);\n\n                sq.ascii = 0xff;\n\n                var dots = [\n                    script.getStringField('SW1', script),\n                    script.getStringField('SW2', script),\n                    script.getStringField('SW3', script),\n                    script.getStringField('SW4', script),\n                    script.getStringField('SW5', script),\n                    script.getStringField('SW6', script),\n                    script.getStringField('SW7', script),\n                    script.getStringField('SW8', script),\n                ];\n\n                var mask = 0;\n\n                if (line == '1') {\n                    mask = 0x01;\n                } else if (line == '2') {\n                    mask = 0x02;\n                } else if (line == '3') {\n                    mask = 0x04;\n                } else if (line == '4') {\n                    mask = 0x08;\n                } else if (line == '5') {\n                    mask = 0x10;\n                } else if (line == '6') {\n                    mask = 0x20;\n                } else if (line == '7') {\n                    mask = 0x40;\n                } else if (line == '8') {\n                    mask = 0x80;\n                }\n\n                if (dots[7] == '1') {\n                    sq.dot1 |= mask;\n                } else {\n                    sq.dot1 &= ~mask;\n                }\n\n                if (dots[6] == '1') {\n                    sq.dot2 |= mask;\n                } else {\n                    sq.dot2 &= ~mask;\n                }\n\n                if (dots[5] == '1') {\n                    sq.dot3 |= mask;\n                } else {\n                    sq.dot3 &= ~mask;\n                }\n\n                if (dots[4] == '1') {\n                    sq.dot4 |= mask;\n                } else {\n                    sq.dot4 &= ~mask;\n                }\n\n                if (dots[3] == '1') {\n                    sq.dot5 |= mask;\n                } else {\n                    sq.dot5 &= ~mask;\n                }\n\n                if (dots[2] == '1') {\n                    sq.dot6 |= mask;\n                } else {\n                    sq.dot6 &= ~mask;\n                }\n\n                if (dots[1] == '1') {\n                    sq.dot7 |= mask;\n                } else {\n                    sq.dot7 &= ~mask;\n                }\n\n                if (dots[0] == '1') {\n                    sq.dot8 |= mask;\n                } else {\n                    sq.dot8 &= ~mask;\n                }\n\n                //sq.led = 0xff;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.dot_display_line(%1, %2, %3, %4, %5, %6, %7, %8)'] },\n        },\n        altino_neo_dot_display_hex: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0x00'],\n                    },\n                    null,\n                ],\n                type: 'altino_neo_dot_display_hex',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n                VALUE6: 5,\n                VALUE7: 6,\n                VALUE8: 7,\n            },\n            class: 'altino_neo_expert',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.ascii = 0xff;\n                sq.dot1 = parseInt(Number(script.getStringValue('VALUE8')), 10);\n                sq.dot2 = parseInt(Number(script.getStringValue('VALUE7')), 10);\n                sq.dot3 = parseInt(Number(script.getStringValue('VALUE6')), 10);\n                sq.dot4 = parseInt(Number(script.getStringValue('VALUE5')), 10);\n                sq.dot5 = parseInt(Number(script.getStringValue('VALUE4')), 10);\n                sq.dot6 = parseInt(Number(script.getStringValue('VALUE3')), 10);\n                sq.dot7 = parseInt(Number(script.getStringValue('VALUE2')), 10);\n                sq.dot8 = parseInt(Number(script.getStringValue('VALUE1')), 10);\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.dot_display_hex(%1, %2, %3, %4, %5, %6, %7, %8)'] },\n        },\n        altino_neo_ir_reset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'altino_neo_ir_reset',\n            },\n            paramsKeyMap: {\n                DEVICE : 0,\n            },\n            class: 'altino_neo_output',\n            isNotFor: ['altino_neo'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                sq.ir = 6;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['AltinoNeo.ir_reset'] },\n        },\n        //endregion Altino 알티노\n    };\n};\n\nmodule.exports = Entry.AltinoNeo;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_alux_connect.js",
    "content": "'use strict';\n\nEntry.ProboConnect = {\n    afterReceive(pd) {\n        if(Entry.engine.isState('run')) {\n            Entry.engine.fireEvent('event_remote_input');\n            Entry.engine.fireEvent('event_digital_input');\n        }\n    },\n\n    id: '27.1',\n    name: 'ProboConnect',\n    url: 'https://www.aluxonline.com',\n    imageName: 'ProboConnect.png',\n    blockIndex: 0,\n    title: {\n        ko: '프로보커넥트',\n        en: 'ProboConnect',\n    },\n    Color: [\n        [13, 37],   // 빨강\n        [38, 62],   // 초록\n        [63, 87],   // 파랑\n        [88, 112],  // 노랑\n        [113, 137], // 검정\n        [138, 162], // 하양\n    ],\n    \n    Note:{\n        n32\t: 48,   // = 1*3*4*4,\n        n16\t: 96,   // = 2*3*4*4,\n        n16d: 144,  // = 3*3*4*4,\n        n16t: 64,   // = 2*2*4*4,\n        n8\t: 192,  // = 4*3*4*4,\n        n8d\t: 288,  // = 6*3*4*4,\n        n8t\t: 128,  // = 4*2*4*4,\n        n4\t: 384,  // = 8*3*4*4,\n        n4d\t: 576,  // = 12*3*4*4,\n        n4t\t: 256,  // = 8*2*4*4,\n        n2\t: 768,  // = 16*3*4*4,\n        n2d\t: 1152, // = 24*3*4*4,\n        n2t\t: 512,  // = 16*2*4*4,\n        n1\t: 1536, // = 32*3*4*4\n    },\n\n    RGB_LED:{\n        red :\t    1,\t\t//RED ON\n        red1: \t    2,\t\t//RED 0.05 ON  -> OFF 반복\n        red2: \t    3,\t\t//RED 0.1  ON  -> OFF 반복\n        red3: \t    4,\t\t//RED 0.2  ON  -> OFF 반복\n        red4: \t    5,\t\t//RED 0.5  ON  -> OFF 반복\n        red5: \t    6,\t\t//RED 1    ON  -> OFF 반복\n        _red1: \t    7,\t\t//RED 0.05 OFF -> ON 반복\n        _red2: \t    8,\t\t//RED 0.1  OFF -> ON 반복\n        _red3: \t    9,\t\t//RED 0.2  OFF -> ON 반복\n        _red4: \t    10,\t\t//RED 0.5  OFF -> ON 반복\n        _red5: \t    11,\t\t//RED 1    OFF -> ON 반복\n                    \n        yellow: \t12,\t\t//YELLOW ON\n        yellow1: \t13,\t\t//YELLOW 0.05 ON  -> OFF 반복\n        yellow2: \t14,\t\t//YELLOW 0.1  ON  -> OFF 반복\n        yellow3: \t15,\t\t//YELLOW 0.2  ON  -> OFF 반복\n        yellow4: \t16,\t\t//YELLOW 0.5  ON  -> OFF 반복\n        yellow5: \t17,\t\t//YELLOW 1    ON  -> OFF 반복\n        _yellow1: \t18,\t\t//YELLOW 0.05 OFF -> ON 반복\n        _yellow2: \t19,\t\t//YELLOW 0.1  OFF -> ON 반복\n        _yellow3: \t20,\t\t//YELLOW 0.2  OFF -> ON 반복\n        _yellow4: \t21,\t\t//YELLOW 0.5  OFF -> ON 반복\n        _yellow5: \t22,\t\t//YELLOW 1    OFF -> ON 반복\n                    \n        green :\t    23,\t\t//GREEN ON\n        green1: \t24,\t\t//GREEN 0.05 ON  -> OFF 반복\n        green2: \t25,\t\t//GREEN 0.1  ON  -> OFF 반복\n        green3: \t26,\t\t//GREEN 0.2  ON  -> OFF 반복\n        green4: \t27,\t\t//GREEN 0.5  ON  -> OFF 반복\n        green5: \t28,\t\t//GREEN 1    ON  -> OFF 반복\n        _green1: \t29,\t\t//GREEN 0.05 OFF -> ON 반복\n        _green2: \t30,\t\t//GREEN 0.1  OFF -> ON 반복\n        _green3: \t31,\t\t//GREEN 0.2  OFF -> ON 반복\n        _green4: \t32,\t\t//GREEN 0.5  OFF -> ON 반복\n        _green5: \t33,\t\t//GREEN 1    OFF -> ON 반복\n                    \n        cyan :\t    34,\t\t//CYAN ON\n        cyan1: \t    35,\t\t//CYAN 0.05 ON  -> OFF 반복\n        cyan2: \t    36,\t\t//CYAN 0.1  ON  -> OFF 반복\n        cyan3: \t    37,\t\t//CYAN 0.2  ON  -> OFF 반복\n        cyan4: \t    38,\t\t//CYAN 0.5  ON  -> OFF 반복\n        cyan5: \t    39,\t\t//CYAN 1    ON  -> OFF 반복\n        _cyan1: \t40,\t\t//CYAN 0.05 OFF -> ON 반복\n        _cyan2: \t41,\t\t//CYAN 0.1  OFF -> ON 반복\n        _cyan3: \t42,\t\t//CYAN 0.2  OFF -> ON 반복\n        _cyan4: \t43,\t\t//CYAN 0.5  OFF -> ON 반복\n        _cyan5: \t44,\t\t//CYAN 1    OFF -> ON 반복\n                    \n        blue:\t    45,\t\t//BLUE ON\n        blue1: \t    46,\t\t//BLUE 0.05 ON  -> OFF 반복\n        blue2: \t    47,\t\t//BLUE 0.1  ON  -> OFF 반복\n        blue3: \t    48,\t\t//BLUE 0.2  ON  -> OFF 반복\n        blue4: \t    49,\t\t//BLUE 0.5  ON  -> OFF 반복\n        blue5: \t    50,\t\t//BLUE 1    ON  -> OFF 반복\n        _blue1: \t51,\t\t//BLUE 0.05 OFF -> ON 반복\n        _blue2: \t52,\t\t//BLUE 0.1  OFF -> ON 반복\n        _blue3: \t53,\t\t//BLUE 0.2  OFF -> ON 반복\n        _blue4: \t54,\t\t//BLUE 0.5  OFF -> ON 반복\n        _blue5: \t55,\t\t//BLUE 1    OFF -> ON 반복\n                    \n        magenta: \t56,\t\t//MAGENTA ON\n        magenta1: \t57,\t\t//MAGENTA 0.05 ON  -> OFF 반복\n        magenta2: \t58,\t\t//MAGENTA 0.1  ON  -> OFF 반복\n        magenta3: \t59,\t\t//MAGENTA 0.2  ON  -> OFF 반복\n        magenta4: \t60,\t\t//MAGENTA 0.5  ON  -> OFF 반복\n        magenta5: \t61,\t\t//MAGENTA 1    ON  -> OFF 반복\n        _magenta1: \t62,\t\t//MAGENTA 0.05 OFF -> ON 반복\n        _magenta2: \t63,\t\t//MAGENTA 0.1  OFF -> ON 반복\n        _magenta3: \t64,\t\t//MAGENTA 0.2  OFF -> ON 반복\n        _magenta4: \t65,\t\t//MAGENTA 0.5  OFF -> ON 반복\n        _magenta5: \t66,\t\t//MAGENTA 1    OFF -> ON 반복\n                    \n        white:\t    67,\t\t//WHITE ON\n        white1: \t68,\t\t//WHITE 0.05 ON  -> OFF 반복\n        white2: \t69,\t\t//WHITE 0.1  ON  -> OFF 반복\n        white3: \t70,\t\t//WHITE 0.2  ON  -> OFF 반복\n        white4: \t71,\t\t//WHITE 0.5  ON  -> OFF 반복\n        white5: \t72,\t\t//WHITE 1    ON  -> OFF 반복\n        _white1: \t73,\t\t//WHITE 0.05 OFF -> ON 반복\n        _white2: \t74,\t\t//WHITE 0.1  OFF -> ON 반복\n        _white3: \t75,\t\t//WHITE 0.2  OFF -> ON 반복\n        _white4: \t76,\t\t//WHITE 0.5  OFF -> ON 반복\n        _white5: \t77,\t\t//WHITE 1    OFF -> ON 반복\n                    \n        rgbrnd1:\t78,\t\t//RANDOM 1\n        rgbrnd2:\t79,\t\t//RANDOM 2\n                    \n        red_d:\t\t90,\t//RED \n        yellow_d:\t91,\t//YELLOW \n        green_d:\t92,\t//GREEN\n        cyan_d:\t\t93,\t//CYAN\n        blue_d:\t\t94,\t//BLUE\n        magenta_d:\t95,\t//MAGENTA\n        white_d:\t96,\t//WHITE\n                    \n        rgboff:\t\t100\t//RGB LED OFF\n    },\n\n    Melody: [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748],\n    Melody_S: [0, 35391, 31530, 28090, 26513, 23621, 21044, 18748],\n\n    Track:[\n        [0x451F, 0x3D95, 0x36DD, 0x33C8, 0x2E22, 0x291A, 0x249E],// Start : size 7,\n        [0x228F, 0x249E, 0x291A, 0x2E22, 0x33C8, 0x36DD, 0x3D95, 0x451F],// End : size 8,\n        [0x228F, 0x1B6E, 0x1711, 0x1147 ],// LevelUp : size 4,\n        [0x1147, 0x1711, 0x1B6E, 0x228F ],// LevelDwon : size 4,\n    ],\n    \n    Infinite_Buff: {\n        AA1: 0,\n        AA2: 0,\n        AA3: 0,\n        AA4: 0\n    },\n    Infinite_Count: {\n        AA1: 0,\n        AA2: 0,\n        AA3: 0,\n        AA4: 0\n    },\n    Infinite_Start: {\n        AA1: 0,\n        AA2: 0,\n        AA3: 0,\n        AA4: 0\n    },\n\n    SenserSet:{\n        AA1: 0,\n        AA2: 0,\n        AA3: 0,\n        AA4: 0\n    },\n\n    InputData: {\n        Analog: {\n            AA1: 0,\n            AA2: 0,\n            AA3: 0,\n            AA4: 0,\n        },\n        Digital: {\n            A1: 0,\n            A2: 0,\n            A3: 0,\n            A4: 0,\n            FEA1: 0,\n            FEA2: 0,\n            FEA3: 0,\n            FEA4: 0,\n            REA1: 0,\n            REA2: 0,\n            REA3: 0,\n            REA4: 0,\n            BEA1: 0,\n            BEA2: 0,\n            BEA3: 0,\n            BEA4: 0,\n        },\n        Remote: {\n            R_1: 0,\n            R_2: 0,\n            R_3: 0,\n            R_4: 0,\n            R_5: 0,\n            R_6: 0,\n            R_7: 0,\n            R_8: 0,\n            R_L1: 0,\n            R_L2: 0,\n            R_R1: 0,\n            R_R2: 0,\n        },\n        EEPROM: {\n            EC: 0,\n            EEPR2: 0,\n            EEPR1: 0,\n        },\n        Infinite:{\n            ROTATION_1: 0,\n            ROTATION_2: 0,\n            ROTATION_3: 0,\n            ROTATION_4: 0\n        },\n        Acceler:{\n            AXIS_X1: 0,\n            AXIS_X2: 0,\n            AXIS_X3: 0,\n            AXIS_X4: 0,\n            AXIS_Y1: 0,\n            AXIS_Y2: 0,\n            AXIS_Y3: 0,\n            AXIS_Y4: 0,\n            AXIS_Z1: 0,\n            AXIS_Z2: 0,\n            AXIS_Z3: 0,\n            AXIS_Z4: 0,\n        }\n    },\n    RemoteData: {\n        B1: 0,\n        B2: 0,\n        B3: 0,\n        B4: 0,\n        Servo1: 0,\n        Servo2: 0,\n        Servo3: 0,\n        Servo4: 0,\n        DC1: 0,\n        DC2: 0,\n        DC3: 0,\n        DC4: 0,\n        MEL2: 0,\n        MEL1: 0,\n        FND: 100,\n        EEPR4: 0,\n        EEPR3: 0,\n        EEPR2: 0,\n        EEPR1: 0,\n        ASET2: 0,\n        ASET1: 0,\n    },\n    EdgeFlag: {\n        FEA1: 0,\n        FEA2: 0,\n        FEA3: 0,\n        FEA4: 0,\n        REA1: 0,\n        REA2: 0,\n        REA3: 0,\n        REA4: 0,\n        BEA1: 0,\n        BEA2: 0,\n        BEA3: 0,\n        BEA4: 0,\n    },\n    EEPROM: {\n        EEPROM_Buff: 0,\n        EEPROM_Count: 0,\n    },\n\n    setZero: function() {\n        for (let key in this.EdgeFlag) {\n            this.EdgeFlag[key] = 0;\n        }\n        for (let key in this.RemoteData) {\n            Entry.hw.sendQueue[key] = this.RemoteData[key];\n        }\n        for (let key in this.SenserSet) {\n            this.SenserSet[key] = 0;\n        }\n        Entry.hw.update();\n    },\n    convertDropdownRemote(value) {\n        switch (value) {\n            case '1':\n                return 'R_1';\n            case '2':\n                return 'R_2';\n            case '3':\n                return 'R_3';\n            case '4':\n                return 'R_4';\n            case '5':\n                return 'R_5';\n            case '6':\n                return 'R_6';\n            case '7':\n                return'R_7';\n            case '8':\n                return'R_8';\n            case '9':\n                return 'R_L1';\n            case '10':\n                return 'R_L2';\n            case '11':\n                return 'R_R1';\n            case '12':\n                return 'R_R2';\n            default:\n                return value;\n        }\n    },\n    convertDropdownDigital(value) {\n        switch (value) {\n            case '1':\n                return 'A1';\n            case '2':\n                return 'A2';\n            case '3':\n                return 'A3';\n            case '4':\n                return 'A4';\n            case '5':\n                return 'FEA1';\n            case '6':\n                return 'FEA2';\n            case '7':\n                return 'FEA3';\n            case '8':\n                return 'FEA4';\n            case '9':\n                return 'REA1';\n            case '10':\n                return 'REA2';\n            case '11':\n                return 'REA3';\n            case '12':\n                return 'REA4';\n            case '13':\n                return 'BEA1';\n            case '14':\n                return 'BEA2';\n            case '15':\n                return 'BEA3';\n            case '16':\n                return 'BEA4';\n            default:\n                return value;\n        }\n    },\n    convertDropdownAnalog(value) {\n        switch (value) {\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n                return 'AA' + value;\n            default:\n                return value;\n        }\n    },\n    convertDropdownAxis(value, axis) {\n        switch (value) {\n            case 'AA1':\n            case 'AA2':\n            case 'AA3':\n            case 'AA4':\n                value = value.substr(2, 2);\n                break;\n        }\n        return \"AXIS_\" + axis + value;\n    },\n    convertDropdownSensor1(value) {\n        switch (value) {\n            case Lang.template.item_switch:\n            case '1':\n                return 1;\n            case Lang.template.item_infrared:\n            case '2':\n                return 2;\n            case Lang.template.item_magnetic:\n            case '3':\n                return 3;\n            case Lang.template.item_rotation:\n            case '4':\n                return 4;\n            case Lang.template.item_color:\n            case '5':\n                return 5;\n            case Lang.template.item_acceleration:\n            case '6':\n                return 6;\n            case Lang.template.item_ultrasonic:\n            case '7':\n                return 7;\n            case Lang.template.item_heart_rate:\n            case '8':\n                return 8;\n            case Lang.template.item_illuminance:\n            case '9':\n                return 9;\n            case Lang.template.item_sound:\n            case '10':\n                return 10;\n            case Lang.template.item_tilt:\n            case '11':\n                return 11;\n            case Lang.template.item_pressure:\n            case '12':\n                return 12;\n            case Lang.template.item_multi_touch:\n            case '13':\n                return 13;        \n            case Lang.template.item_compass:\n            case '14':\n                return 14;\n            case Lang.template.item_3acceleration:\n            case '15':\n                return 15;        \n            case Lang.template.item_multi_switch:\n            case '16':\n                return 16;\n        }\n    },\n    convertDropdownSensor2(value) {\n        switch (value) {\n            case Lang.template.item_infinite_rotation:\n            case '1':\n                return 1;\n            case Lang.template.item_compass:\n            case '2':\n                return 2;\n            default:\n                return value;\n        }\n    },\n    convertDropdownKey(value) {\n        switch (value) {\n            case Lang.template.item_key_1:\n            case '1':\n                return 0;\n            case Lang.template.item_key_2:\n            case '2':\n                return 1;\n            case Lang.template.item_key_3:\n            case '3':\n                return 2;\n            case Lang.template.item_key_4:\n            case '4':\n                return 3;\n            case Lang.template.item_key_5:\n            case '5':\n                return 4;\n            case Lang.template.item_key_6:\n            case '6':\n                return 5;\n            case Lang.template.item_key_7:\n            case '7':\n                return 6;\n            case Lang.template.item_key_8:\n            case '8':\n                return 7;\n            default:\n                return value;\n        }\n    },\n    convertDropdownOnOff(value) {\n        switch (value) {\n            case Lang.template.item_on:\n            case '1':\n                return 1;\n            case Lang.template.item_off:\n            case '0':\n                return 0;\n            default:\n                return value\n        }\n        \n    },\n    convertDropdownDC(value) {\n        switch (value) {\n            case '1':\n            case '2':            \n            case '3':\n            case '4':\n            case '5':\n            case '6':\n            case '7':\n                return 'DC' + value;\n            default:\n                return value;\n        }\n    },\n    convertDropdownServo(value) {\n        switch (value) {\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n                return 'Servo' + value;\n            default:\n                return value;\n        }\n    },\n    convertDropdownPort(value) {\n        switch (value) {\n            case '1':\n            case '2':\n            case '3':\n            case '4':\n                return 'B' + value;\n            default:\n                return value;\n        }\n    },\n    convertDropdownSensorTransfer(value) {\n        switch (value) {\n            case '1':\n            case Lang.template.item_value:\n                return 1;\n            case '2':\n            case Lang.template.item_angle:\n                return 2;\n            case '3':\n            case Lang.template.item_absolute_angle:\n                return 3;\n            case '4':\n            case Lang.template.item_number_of_rotations:\n                return 4;\n            default:\n                value;\n        }\n    },\n    convertDropdownPitch(pitch) {\n        // 배열의 인덱스 1번부터 음표\n        const index = (pitch % 12) + 1;\n\n        let value = 0;\n        if (36 <= pitch && pitch <= 47) {\n            value = Entry.ProboConnect.Melody[index];\n        } else if (48 <= pitch && pitch <= 59) {\n            value = Entry.ProboConnect.Melody[index] >> 1;\n        } else if (60 <= pitch && pitch <= 71) {\n            value = Entry.ProboConnect.Melody[index] >> 2;\n        } else if (72 <= pitch && pitch <= 83) {\n            value = Entry.ProboConnect.Melody[index] >> 3;\n        } else {\n            value = Entry.ProboConnect.Melody[0];\n        }\n        return value;\n    },\n    convertDropdownNote(value) {\n        switch (value) {\n            case Lang.template.item_note_whole:\n            case '1':\n                return 'n1';\n            case Lang.template.item_note_half:\n            case '2':\n                return 'n2';\n            case Lang.template.item_note_quarter:\n            case '4':\n                return 'n4';\n            case Lang.template.item_note_eighth:\n            case '8':\n                return 'n8';\n            case Lang.template.item_note_sixteenth:\n            case '16':\n                return 'n16';\n            case Lang.template.item_note_thirty_second:\n            case '32':\n                return 'n32';\n            default:\n                return value;\n        }\n    },\n    convertDropdownMelody(value) {\n        switch (value) {\n            case Lang.template.item_melody_start:\n            case '1':\n                return 0;\n            case Lang.template.item_melody_end:\n            case '2':\n                return 1;\n            case Lang.template.item_melody_level_up:\n            case '3':\n                return 2;\n            case Lang.template.item_melody_level_down:\n            case '4':\n                return 3;\n            default:\n                return value;\n        }\n    },    \n    convertDropdownColor1(value) {\n        switch (value) {\n            case Lang.template.item_color_red:\n                return 0;\n            case Lang.template.item_color_green:\n                return 1;\n            case Lang.template.item_color_blue:\n                return 2;\n            case Lang.template.item_color_yellow:\n                return 3;\n            case Lang.template.item_color_black:\n                return 4;\n            case Lang.template.item_color_white:\n                return 5;\n            default:\n                return value - 1;\n        }\n    },\n    convertDropdownColor2(value) {\n        switch (value) {\n            case Lang.template.item_color_red:\n            case '1':\n                return 1;\n            case Lang.template.item_color_green:\n            case '2':\n                return 23;\n            case Lang.template.item_color_blue:\n            case '3':\n                return 45;\n            case Lang.template.item_color_cyan:\n            case '4':\n                return 34;\n            case Lang.template.item_color_magenta:\n            case '5':\n                return 56;\n            case Lang.template.item_color_yellow:\n            case '6':\n                return 12;\n            case '7':\n            case Lang.template.item_color_white:\n                return 67;\n            default:\n                return value;\n        }\n    },\n};\n\nEntry.ProboConnect.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                item_switch: '스위치',\n                item_infrared: '적외선',\n                item_magnetic: '자석',\n                item_rotation: '회전',\n                item_color: '컬러',\n                item_acceleration: '가속도',\n                item_ultrasonic: '초음파',\n                item_heart_rate: '심박',\n                item_illuminance: '조도',\n                item_temperature: '온도',\n                item_sound: '소리',\n                item_tilt: '기울기',\n                item_pressure: '압력',\n                item_multi_touch: '멀티키',\n                item_compass: '나침반',\n                item_3acceleration: '3가속',\n                item_multi_switch: '분배기',\n                item_infinite_rotation: '무한회전',\n                item_color_red: '빨간색',\n                item_color_green: '초록색',\n                item_color_blue: '파란색',\n                item_color_cyan: '청녹색',\n                item_color_magenta: '자홍색',\n                item_color_yellow: '노란색',\n                item_color_black: '검정색',\n                item_color_white: '하얀색',\n                item_value: '값',\n                item_angle: '각도',\n                item_absolute_angle: '절대각도',\n                item_number_of_rotations: '회전 수',\n                item_key_1: '키1',\n                item_key_2: '키2',\n                item_key_3: '키3',\n                item_key_4: '키4',\n                item_key_5: '키5',\n                item_key_6: '키6',\n                item_key_7: '키7',\n                item_key_8: '키8',\n                item_all: '모두',\n                item_on: '켜기',\n                item_off: '끄기',\n                item_note_whole: '온',\n                item_note_half: '2분',\n                item_note_quarter: '4분',\n                item_note_eighth: '8분',\n                item_note_sixteenth: '16분',\n                item_note_thirty_second: '32분',\n                item_pitch_do: '도',\n                item_pitch_do_sharp: '도#',\n                item_pitch_re: '레',\n                item_pitch_re_sharp: '레#',\n                item_pitch_mi: '미',\n                item_pitch_fa: '파',\n                item_pitch_fa_sharp: '파#',\n                item_pitch_sol: '솔',\n                item_pitch_sol_sharp: '솔#',\n                item_pitch_ra: '라',\n                item_pitch_ra_sharp: '라#',\n                item_pitch_si: '시',\n                item_melody_start: '시작음',\n                item_melody_end: '종료음',\n                item_melody_level_up: '레벨 업',\n                item_melody_level_down: '레벨 다운',\n\n                connect_remote_event: '%1 리모컨 %2 키를 눌렀을 때',\n                connect_digital_event: '%1 디지털 입력 %2 이(가) 들어왔을 때',\n\n                connect_senser_setting: '입력포트 %1 을(를) %2 센서로 설정 %3',\n\n                connect_remote_input: '리모컨 입력 %1',\n                connect_digital_input: '디지털 입력 %1',\n                connect_analog_input: '아날로그 입력 %1',\n                connect_3axis_acceler_x: '3가속도 %1의 X축',\n                connect_3axis_acceler_y: '3가속도 %1의 Y축',\n                connect_3axis_acceler_z: '3가속도 %1의 Z축',\n                connect_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환',\n                connect_color_input_b: '컬러 센서 %1 이(가) %2 인가?',\n                connect_color_input_r: '컬러 센서 %1 의 색상',\n                connect_infinite_setting: '%1 센서 %2 을 %3 값으로 정하기 %4',\n                connect_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값',\n                connect_infinite_transform_input: '%1 센서 %2 의  %3',\n                connect_multi_sensor: '멀티키 센서 %1의 %2',\n                connect_multi_switch: '분배 스위치 %1의 %2',\n                connect_eeprom_buffset: 'EEPROM %1 주소의 값 호출하기 %2',\n                connect_eeprom_address_value: 'EEPROM 주소의 값',      \n\n                connect_port_output: '출력핀 %1 을(를) %2 %3',\n                connect_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3',\n                connect_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3',\n                connect_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3',\n                connect_melody_note_output: '%1 을(를) %2 음표로 연주하기 %3',\n                connect_melody_sec_output: '%1 을(를) %2 초 동안 연주하기 %3',\n                connect_melody_output: '%1 을(를) 연주하기 %2',\n                connect_value_sec_output: '%1 값을(를) %2 초 동안 연주하기 %3',\n                connect_value_output: '%1 값을(를) 연주하기 %2',\n                connect_melody_track_output: '%1 을(를) %2초 간격으로 재생하기 %3',\n                connect_melody_off: '멜로디 중지 %1',\n                connect_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3',\n                connect_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2',\n                connect_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3',\n                connect_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4',\n                connect_fnd_output: 'FND를 %1 (으)로 설정 %2',\n                connect_fnd_off: 'FND 끄기 %1',\n                connect_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3',\n            },\n        },\n        en: {\n            template: {\n                item_switch: 'Switch',\n                item_infrared: 'Infrared',\n                item_magnetic: 'Magnetic',\n                item_rotation: 'Rotation',\n                item_color: 'Color',\n                item_acceleration: 'Acceleration',\n                item_ultrasonic: 'Ultrasonic',\n                item_heart_rate: 'Heart Rate',\n                item_illuminance: 'Illuminance',\n                item_temperature: 'Temperature',\n                item_sound: 'Sound',\n                item_tilt: 'Tilt',\n                item_pressure: 'Pressure',\n                item_multi_touch: 'Multi Touch',\n                item_compass: 'Compass',\n                item_3acceleration: '3Acceleration',\n                item_multi_switch: 'Multi Switch',\n                item_infinite_rotation: 'Infinite Rotation',\n                item_color_red: 'Red',\n                item_color_green: 'Green',\n                item_color_blue: 'Blue',\n                item_color_cyan: 'Cyan',\n                item_color_magenta: 'Magenta',\n                item_color_yellow: 'Yellow',\n                item_color_black: 'Black',\n                item_color_white: 'White',\n                item_value: 'Value',\n                item_angle: 'Angle',\n                item_absolute_angle: 'Absolute Angle',\n                item_number_of_rotations: 'Number of Rotations',\n                item_key_1: 'Key1',\n                item_key_2: 'Key2',\n                item_key_3: 'Key3',\n                item_key_4: 'Key4',\n                item_key_5: 'Key5',\n                item_key_6: 'Key6',\n                item_key_7: 'Key7',\n                item_key_8: 'Key8',\n                item_all: 'All',\n                item_on: 'On',\n                item_off: 'Off',\n                item_note_whole: 'Whole',\n                item_note_half: 'Half',\n                item_note_quarter: 'Quarter',\n                item_note_eighth: 'Eighth',\n                item_note_sixteenth: 'Sixteenth',\n                item_note_thirty_second: 'Thirty-Second',\n                item_pitch_do: 'do',\n                item_pitch_do_sharp: 'xdo',\n                item_pitch_re: 're',\n                item_pitch_re_sharp: 'xre',\n                item_pitch_mi: 'mi',\n                item_pitch_fa: 'fa',\n                item_pitch_fa_sharp: 'xfa',\n                item_pitch_sol: 'sol',\n                item_pitch_sol_sharp: 'xsol',\n                item_pitch_ra: 'ra',\n                item_pitch_ra_sharp: 'xra',\n                item_pitch_si: 'si',\n                item_melody_start: 'Start',\n                item_melody_end: 'End',\n                item_melody_level_up: 'Level up',\n                item_melody_level_down: 'Level down',\n\n                connect_remote_event: '%1 When %2 remote control key pressed',\n                connect_digital_event: '%1 When %2 digital pin input',\n\n                connect_senser_setting: 'Set input port %1 to %2 sensor %3',\n\n                connect_remote_input: 'Remote control %1',\n                connect_digital_input: 'Read digital pin %1',\n                connect_analog_input: 'Read analog pin %1',\n                connect_3axis_acceler_x: '3acceleration %1 and X',\n                connect_3axis_acceler_y: '3acceleration %1 and Y',\n                connect_3axis_acceler_z: '3acceleration %1 and Z',\n                connect_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5',\n                connect_color_input_b: 'Is color sensor %1 %2 ?',\n                connect_color_input_r: 'Color of color sensor %1',\n                connect_infinite_setting: 'Set %1 sensor %2 to %3 value %4',\n                connect_infinite_mm_diameter: 'The move distance(in mm) when the %1 sensor %2 is %3 mm in diameter',\n                connect_infinite_transform_input: '%1 rotation sensor %2 to %3',\n                connect_multi_sensor: 'Multi sensor %1 key %2',\n                connect_multi_switch: 'A key number of the multi-switch sensor %1 = %2',\n                connect_eeprom_buffset:'Calling the value of EEPROM %1 address',\n                connect_eeprom_address_value: 'Value of EEPROM address',\n\n                connect_dc_output: 'DC motor %1 velocity %2 %3',\n                connect_servo_output: 'Servo motor %1 position %2 %3',\n                connect_s_dc_output: 'Servo motor %1 speed %2 %3',\n                connect_port_output: 'Set digital pint %1 as %2 %3',\n                connect_melody_note_output: 'Play key %1 for %2 note %3',\n                connect_melody_sec_output: 'Play key %1 for %2 secs %3',\n                connect_melody_output: 'Play key %1 %2',\n                connect_value_sec_output: 'Play value %1 for %2 secs %3',\n                connect_value_output: 'Play value %1 %2',\n                connect_melody_track_output: 'Play sound %1 for %2 secs %3',\n                connect_melody_off: 'Stop tone %1',\n                connect_rgbled_on_output: 'Turn on RGB LED %1 to %2 %3',\n                connect_rgbled_off_output: 'Turn off RGB LED %1 %2',\n                connect_rgbled_dimming_output: 'Dimming RGB LED %1 to %2 %3',\n                connect_rgbled_flashing_output: 'RGB LED %1 Blinking %2 at %3 second intervals %4',\n                connect_fnd_output: 'Set FND to %1 %2',\n                connect_fnd_off: 'Turn off FND %1',\n                connect_eeprom_write: 'Set EEPROM %1 address to %2 %3',\n            },\n        },\n    };\n};\n\nEntry.ProboConnect.blockMenuBlocks = [\n    'connect_dropdown_remote',\n    'connect_dropdown_digital',\n    'connect_dropdown_analog',\n    'connect_dropdown_sensor_1',\n    'connect_dropdown_sensor_2',\n    'connect_dropdown_color_1',\n    'connect_dropdown_color_2',\n    'connect_dropdown_sensor_transfer',\n    'connect_dropdown_key',\n    'connect_dropdown_dc_1_all',\n    'connect_dropdown_servo_1_4',\n    'connect_dropdown_port_1_4',\n    'connect_dropdown_on_off',\n    'connect_dropdown_velocity',\n    'connect_dropdown_servo_position',\n    'connect_dropdown_note',\n    'connect_dropdown_time_1',\n    'connect_dropdown_time_2',\n    'connect_dropdown_time_3',\n    'connect_dropdown_pitch',\n    'connect_dropdown_melody',\n\n    //event\n    'connect_remote_event',\n    'connect_digital_event',\n\n    //input\n    'connect_senser_setting',\n    'connect_remote_input',\n    'connect_digital_input',\n    'connect_analog_input',\n    'connect_3axis_acceler_x',\n    'connect_3axis_acceler_y',\n    'connect_3axis_acceler_z',\n    'connect_value_mapping',\n    'connect_color_input_b',\n    'connect_color_input_r',\n    'connect_infinite_setting',\n    'connect_infinite_mm_diameter',\n    'connect_infinite_transform_input',\n    'connect_multi_sensor',\n    'connect_multi_switch',\n    'connect_eeprom_buffset',\n    'connect_eeprom_address_value',\n\n    //output\n    'connect_dc_output',\n    'connect_servo_output',\n    'connect_s_dc_output',\n    'connect_port_output',\n    'connect_melody_note_output',\n    'connect_melody_sec_output',\n    'connect_melody_output',\n    'connect_value_sec_output',\n    'connect_value_output',    \n    'connect_melody_track_output',\n    'connect_melody_off',\n    'connect_rgbled_on_output',\n    'connect_rgbled_off_output',\n    'connect_rgbled_flashing_output',\n    'connect_rgbled_dimming_output',\n    'connect_fnd_output',\n    'connect_fnd_off',\n    // EEPROM\n    'connect_eeprom_write',\n];\n\n// 블록 생성\nEntry.ProboConnect.getBlocks = function() {\n    return {\n        ///========================================================================================\n        /// Dropdown block\n        ///========================================================================================\n        connect_dropdown_remote: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['R_1', '1'],\n                        ['R_2', '2'],\n                        ['R_3', '3'],\n                        ['R_4', '4'],\n                        ['R_5', '5'],\n                        ['R_6', '6'],\n                        ['R_7', '7'],\n                        ['R_8', '8'],\n                        ['R_L1', '9'],\n                        ['R_L2', '10'],\n                        ['R_R1', '11'],\n                        ['R_R2', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['FEA1', '5'],\n                        ['FEA2', '6'],\n                        ['FEA3', '7'],\n                        ['FEA4', '8'],\n                        ['REA1', '9'],\n                        ['REA2', '10'],\n                        ['REA3', '11'],\n                        ['REA4', '12'],\n                        ['BEA1', '13'],\n                        ['BEA2', '14'],\n                        ['BEA3', '15'],\n                        ['BEA4', '16'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_analog: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['AA1', '1'],\n                        ['AA2', '2'],\n                        ['AA3', '3'],\n                        ['AA4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_sensor_1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_switch, '1'],\n                        [Lang.template.item_infrared, '2'],\n                        [Lang.template.item_magnetic, '3'],\n                        [Lang.template.item_rotation, '4'],\n                        [Lang.template.item_color, '5'],\n                        [Lang.template.item_acceleration, '6'],\n                        [Lang.template.item_ultrasonic, '7'],\n                        [Lang.template.item_heart_rate, '8'],\n                        [Lang.template.item_illuminance, '9'],\n                        [Lang.template.item_sound, '10'],\n                        [Lang.template.item_tilt, '11'],\n                        [Lang.template.item_pressure, '12'],\n                        [Lang.template.item_multi_touch, '13'],\n                        [Lang.template.item_compass, '14'],\n                        [Lang.template.item_3acceleration, '15'],\n                        [Lang.template.item_multi_switch, '16'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_sensor_2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_infinite_rotation, '1'],\n                        [Lang.template.item_compass, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_color_1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_color_red, '1'],\n                        [Lang.template.item_color_green, '2'],\n                        [Lang.template.item_color_blue, '3'],\n                        [Lang.template.item_color_yellow, '4'],\n                        [Lang.template.item_color_black, '5'],\n                        [Lang.template.item_color_white, '6'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_color_2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_color_red, '1'],\n                        [Lang.template.item_color_green, '2'],\n                        [Lang.template.item_color_blue, '3'],\n                        [Lang.template.item_color_cyan, '4'],\n                        [Lang.template.item_color_magenta, '5'],\n                        [Lang.template.item_color_yellow, '6'],\n                        [Lang.template.item_color_white, '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_sensor_transfer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_value, '1'],\n                        [Lang.template.item_angle, '2'],\n                        [Lang.template.item_absolute_angle, '3'],\n                        [Lang.template.item_number_of_rotations, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_key: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_key_1, '1'],\n                        [Lang.template.item_key_2, '2'],\n                        [Lang.template.item_key_3, '3'],\n                        [Lang.template.item_key_4, '4'],\n                        [Lang.template.item_key_5, '5'],\n                        [Lang.template.item_key_6, '6'],\n                        [Lang.template.item_key_7, '7'],\n                        [Lang.template.item_key_8, '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_dc_1_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 'DC1'],\n                        ['2', 'DC2'],\n                        ['3', 'DC3'],\n                        ['4', 'DC4'],\n                        ['1,2', 'DC5'],\n                        ['3,4', 'DC6'],\n                        [Lang.template.item_all, 'DC7'],\n                    ],\n                    value: 'DC1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_servo_1_4: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 'Servo1'],\n                        ['2', 'Servo2'],\n                        ['3', 'Servo3'],\n                        ['4', 'Servo4'],\n                    ],\n                    value: 'Servo1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_velocity: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['20', '20'],\n                        ['15', '15'],\n                        ['10', '10'],\n                        ['5', '5'],\n                        ['0', '0'],\n                        ['-5', '-5'],\n                        ['-10', '-10'],\n                        ['-15', '-15'],\n                        ['-20', '-20'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_servo_position: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['20', '20'],\n                        ['40', '40'],\n                        ['60', '60'],\n                        ['80', '80'],\n                        ['100', '100'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_port_1_4: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 'B1'],\n                        ['2', 'B2'],\n                        ['3', 'B3'],\n                        ['4', 'B4'],\n                    ],\n                    value: 'B1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },           \n        connect_dropdown_on_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_on, '1'],\n                        [Lang.template.item_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_note_whole, '1'],\n                        [Lang.template.item_note_half, '2'],\n                        [Lang.template.item_note_quarter, '4'],\n                        [Lang.template.item_note_eighth, '8'],\n                        [Lang.template.item_note_sixteenth, '16'],\n                        [Lang.template.item_note_thirty_second, '32'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_time_1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.1', '0.1'],\n                        ['0.3', '0.3'],\n                        ['0.5', '0.5'],\n                        ['0.7', '0.7'],\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '0.5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_time_2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.1', '0.1'],\n                        ['0.3', '0.3'],\n                        ['0.5', '0.5'],\n                        ['0.7', '0.7'],\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_time_3: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.05', '0.05'],\n                        ['0.1', '0.1'],\n                        ['0.2', '0.2'],\n                        ['0.5', '0.5'],\n                        ['1', '1'],\n                    ],\n                    value: '0.5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        connect_dropdown_pitch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'DropdownExtra',\n                    options: [\n                        [Lang.template.item_pitch_do + ' (36)', '36'],\n                        [Lang.template.item_pitch_do_sharp + ' (37)', '37'],\n                        [Lang.template.item_pitch_re + ' (38)', '38'],\n                        [Lang.template.item_pitch_re_sharp + ' (39)', '39'],\n                        [Lang.template.item_pitch_mi + ' (40)', '40'],\n                        [Lang.template.item_pitch_fa + ' (41)', '41'],\n                        [Lang.template.item_pitch_fa_sharp + ' (42)', '42'],\n                        [Lang.template.item_pitch_sol + ' (43)', '43'],\n                        [Lang.template.item_pitch_sol_sharp + ' (44)', '44'],\n                        [Lang.template.item_pitch_ra + ' (45)', '45'],\n                        [Lang.template.item_pitch_ra_sharp + ' (46)', '46'],\n                        [Lang.template.item_pitch_si + ' (47)', '47'],\n\n                        [Lang.template.item_pitch_do + ' (48)', '48'],\n                        [Lang.template.item_pitch_do_sharp + ' (49)', '49'],\n                        [Lang.template.item_pitch_re + ' (50)', '50'],\n                        [Lang.template.item_pitch_re_sharp + ' (51)', '51'],\n                        [Lang.template.item_pitch_mi + ' (52)', '52'],\n                        [Lang.template.item_pitch_fa + ' (53)', '53'],\n                        [Lang.template.item_pitch_fa_sharp + ' (54)', '54'],\n                        [Lang.template.item_pitch_sol + ' (55)', '55'],\n                        [Lang.template.item_pitch_sol_sharp + ' (56)', '56'],\n                        [Lang.template.item_pitch_ra + ' (57)', '57'],\n                        [Lang.template.item_pitch_ra_sharp + ' (58)', '58'],\n                        [Lang.template.item_pitch_si + ' (59)', '59'],\n\n                        [Lang.template.item_pitch_do + ' (60)', '60'],\n                        [Lang.template.item_pitch_do_sharp + ' (61)', '61'],\n                        [Lang.template.item_pitch_re + ' (62)', '62'],\n                        [Lang.template.item_pitch_re_sharp + ' (63)', '63'],\n                        [Lang.template.item_pitch_mi + ' (64)', '64'],\n                        [Lang.template.item_pitch_fa + ' (65)', '65'],\n                        [Lang.template.item_pitch_fa_sharp + ' (66)', '66'],\n                        [Lang.template.item_pitch_sol + ' (67)', '67'],\n                        [Lang.template.item_pitch_sol_sharp + ' (68)', '68'],\n                        [Lang.template.item_pitch_ra + ' (69)', '69'],\n                        [Lang.template.item_pitch_ra_sharp + ' (70)', '70'],\n                        [Lang.template.item_pitch_si + ' (71)', '71'],\n\n                        [Lang.template.item_pitch_do + ' (72)', '72'],\n                        [Lang.template.item_pitch_do_sharp + ' (73)', '73'],\n                        [Lang.template.item_pitch_re + ' (74)', '74'],\n                        [Lang.template.item_pitch_re_sharp + ' (75)', '75'],\n                        [Lang.template.item_pitch_mi + ' (76)', '76'],\n                        [Lang.template.item_pitch_fa + ' (77)', '77'],\n                        [Lang.template.item_pitch_fa_sharp + ' (78)', '78'],\n                        [Lang.template.item_pitch_sol + ' (79)', '79'],\n                        [Lang.template.item_pitch_sol_sharp + ' (80)', '80'],\n                        [Lang.template.item_pitch_ra + ' (81)', '81'],\n                        [Lang.template.item_pitch_ra_sharp + ' (82)', '82'],\n                        [Lang.template.item_pitch_si + ' (83)', '83'],\n                    ],\n                    value: '60',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                const value = script.getField('PARAM0');\n                return value;\n            }\n        },\n        connect_dropdown_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_melody_start, '1'],\n                        [Lang.template.item_melody_end, '2'],\n                        [Lang.template.item_melody_level_up, '3'],\n                        [Lang.template.item_melody_level_down, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        ///========================================================================================\n        /// Event block\n        ///========================================================================================\n        // 리모컨 R_1 키를 눌렀을 때\n        connect_remote_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'connect_dropdown_remote',\n                    },\n                ],\n                type: 'connect_remote_event',\n            },\n            paramsKeyMap: {\n                PARAM1: 1,\n            },\n            class: 'event',\n            isNotFor: ['ProboConnect'],\n            event: 'event_remote_input',\n            func(sprite, script) {\n                const btn = Entry.ProboConnect.convertDropdownRemote(\n                    script.getStringValue('PARAM1')\n                );\n                if (Entry.hw.portData.InputData.Remote[btn] == 1 ) {\n                    return script.callReturn();\n                }\n                return this.die();\n            },\n        },        \n        // 디지털 입력 A1 이(가) 들어왔을 때\n        connect_digital_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'connect_dropdown_digital',\n                    },\n                ],\n                type: 'connect_digital_event',\n            },\n            paramsKeyMap: {\n                PARAM1: 1,\n            },\n            class: 'event',\n            isNotFor: ['ProboConnect'],\n            event: 'event_digital_input',\n            func(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownDigital(\n                    script.getStringValue('PARAM1')\n                );\n                switch(port) {\n                    case 'FEA1':\n                    case 'FEA2':\n                    case 'FEA3':\n                    case 'FEA4':\n                    case 'REA1':\n                    case 'REA2':\n                    case 'REA3':\n                    case 'REA4':\n                    case 'BEA1':\n                    case 'BEA2':\n                    case 'BEA3':\n                    case 'BEA4':\n                        if (Entry.hw.portData.InputData.Digital[port] == 1) {\n                            if (Entry.ProboConnect.EdgeFlag[port] == 0) {\n                                Entry.ProboConnect.EdgeFlag[port] = 1;\n                                return script.callReturn();\n                            }\n                        } else {\n                            Entry.ProboConnect.EdgeFlag[port] = 0;\n                        }\n                        break;\n                    default:\n                        if (Entry.hw.portData.InputData.Digital[port] == 1 ) {\n                            return script.callReturn();\n                        }\n                        break;\n                }\n\n                return this.die();\n            },\n        },\n        ///========================================================================================\n        /// Input block\n        ///========================================================================================\n        // 입력포트 AA1 을(를) 스위치 센서로 설정\n        connect_senser_setting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                    {\n                        type: 'connect_dropdown_sensor_1',\n                    },\n                    null,\n                ],\n                type: 'connect_senser_setting',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'setting',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const port = Entry.ProboConnect.convertDropdownAnalog(\n                        script.getStringValue('PARAM0')\n                    );\n                    const sensor = Entry.ProboConnect.convertDropdownSensor1(\n                        script.getStringValue('PARAM1')\n                    );                    \n                    let index = 0;\n                    switch (port) {\n                        case 'AA1':\n                            index = 0;\n                            break;\n                        case 'AA2':\n                            index = 1;\n                            break;\n                        case 'AA3':\n                            index = 2;\n                            break;\n                        case 'AA4':\n                            index = 3;\n                            break;\n                    }\n\n                    let Aset = [0, 0, 0, 0];\n                    let value = [0, 0, 0, 0];\n\n                    Aset[index] = sensor;\n                    for (let i = 0; i < 4; i++) {\n                        switch (Aset[i]) {\n                            case 1: // 스위치\n                            case 2: // 적외선\n                            case 3: // 자석\n                            case 16: // 분배기\n                                value[i] = 1;\n                                break;\n                            case 4: // 회전\n                            case 9: // 조도\n                            case 7: // 초음파\n                                value[i] = 2;\n                                break;\n                            case 10: // 소리\n                                value[i] = 3;\n                                break;                                \n                            case 11: // 기울기\n                                value[i] = 4;\n                                break;\n                            case 12: // 압력\n                                value[i] = 5;\n                                break;\n                            case 8: // 심박\n                                value[i] = 6;\n                                break;\n                            case 5: // 컬러\n                                value[i] = 7;\n                                break;\n                            case 6: // 가속도\n                                value[i] = 8;\n                                break;\n                            case 14: // 나침반\n                            case 15: // 3가속\n                                value[i] = 9;\n                                break;\n                            case 13: // 멀티터치(멀티키)\n                                value[i] = 11;\n                                break;\n                        }\n                    }\n\n                    Entry.ProboConnect.SenserSet.AA1 = value[0];\n                    Entry.ProboConnect.SenserSet.AA2 = value[1];\n                    Entry.ProboConnect.SenserSet.AA3 = value[2];\n                    Entry.ProboConnect.SenserSet.AA4 = value[3];\n\n                    Entry.hw.sendQueue['ASET2'] = (value[0] << 4) | value[1];\n                    Entry.hw.sendQueue['ASET1'] = (value[2] << 4) | value[3];\n\n                    let fps = Entry.FPS || 60;\n                    let timeValue = 60 / fps * 200; // 0.2초\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n\n            },\n        },\n        // 리모컨 입력 R_1\n        connect_remote_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_remote',\n                    },\n                ],\n                type: 'connect_remote_input',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const btn = Entry.ProboConnect.convertDropdownRemote(\n                    script.getStringValue('PARAM0')\n                );\n                return Entry.hw.portData.InputData.Remote[btn] == 1 ? true : false;\n            },\n        },\n        // 디지털 입력 A1\n        connect_digital_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_digital',\n                    },\n                ],\n                type: 'connect_digital_input',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownDigital(\n                    script.getStringValue('PARAM0')\n                );                \n                let rt = false;\n                switch(port) {\n                    case 'FEA1':\n                    case 'FEA2':\n                    case 'FEA3':\n                    case 'FEA4':\n                    case 'REA1':\n                    case 'REA2':\n                    case 'REA3':\n                    case 'REA4':\n                    case 'BEA1':\n                    case 'BEA2':\n                    case 'BEA3':\n                    case 'BEA4':\n                        if (Entry.hw.portData.InputData.Digital[port] == 1) {\n                            if (Entry.ProboConnect.EdgeFlag[port] == 0) {\n                                Entry.ProboConnect.EdgeFlag[port] = 1;\n                                rt = true;\n                            }\n                        } else {\n                            Entry.ProboConnect.EdgeFlag[port] = 0;\n                        }\n                        break;\n                    default:\n                        rt = Entry.hw.portData.InputData.Digital[port] == 1 ? true : false;\n                        break;\n                }\n                return rt;\n            },\n        },\n        // 아날로그 입력 AA1\n        connect_analog_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                ],\n                type: 'connect_analog_input',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                let value = Entry.ProboConnect.SenserSet[port] == 5\n                    ? 255 - Entry.hw.portData.InputData.Analog[port]\n                    : Entry.hw.portData.InputData.Analog[port];\n                return value;\n            },\n        },\n        // 3가속도 AA1 의 X축\n        connect_3axis_acceler_x: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                ],\n                type: 'connect_3axis_acceler_x',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const axis = Entry.ProboConnect.convertDropdownAxis(\n                    script.getStringValue('PARAM0'),\n                    \"X\"\n                );\n                let value = (Entry.hw.portData.InputData.Acceler[axis]);\n                if (value & 0x80) {\n                    value = (value - 255);\n                }\n                return Number(value / 10).toFixed(1);\n            },\n        },\n        // 3가속도 AA1의 Y축\n        connect_3axis_acceler_y: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                ],\n                type: 'connect_3axis_acceler_y',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const axis = Entry.ProboConnect.convertDropdownAxis(\n                    script.getStringValue('PARAM0'),\n                    \"Y\"\n                );\n                let value = (Entry.hw.portData.InputData.Acceler[axis]);\n                if (value & 0x80) {\n                    value = (value - 255);\n                }\n                return Number(value / 10).toFixed(1);\n            },\n        },\n        // 3가속도 AA1 의 Z축\n        connect_3axis_acceler_z: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                ],\n                type: 'connect_3axis_acceler_z',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const axis = Entry.ProboConnect.convertDropdownAxis(\n                    script.getStringValue('PARAM0'),\n                    \"Z\"\n                );\n                let value = (Entry.hw.portData.InputData.Acceler[axis]);\n                if (value & 0x80) {\n                    value = (value - 255);\n                }\n                return Number(value / 10).toFixed(1);\n            },\n        },\n        // AA1의 0 ~ 255 값을 0 ~ 100 (으)로 변환\n        connect_value_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 255 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 100 ],\n                    },\n                ],\n                type: 'connect_value_mapping',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n                PARAM2: 2,\n                PARAM3: 3,\n                PARAM4: 4,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const source1 = script.getNumberValue('PARAM1');\n                const source2 = script.getNumberValue('PARAM2');\n                const target1 = script.getNumberValue('PARAM3');\n                const target2 = script.getNumberValue('PARAM4');\n\n                // Port 라는 key값을 가진 정보를 읽는다.\n                let data = 0;\n                if (Entry.ProboConnect.SenserSet[port] == 5) {\n                    data = 255 - Entry.hw.portData.InputData.Analog[port];\n                } else {\n                    data = Entry.hw.portData.InputData.Analog[port];\n                }\n                let value = 0;\n                let rate = (data - source1) / (source2 - source1);\n                let num = 0;\n\n                if (target1 < target2) {\n                    value = (target2 - target1) * rate;\n                    num = value % 1;\n                    if (num < 0.5) {\n                        value -= num;\n                    }\n                    else {\n                        value += 1 - num;\n                    }\n                    value = target1 + value;\n                    if (value < target1) {\n                        value = target1;\n                    } else if (value > target2) {\n                        value = target2;\n                    }\n                } else {\n                    value = (target1 - target2) * rate;\n                    num = value % 1;\n                    if (num < 0.5) {\n                        value -= num;\n                    } else {\n                        value += 1 - num;\n                    }\n                    value = target1 - value;\n                    if (value > target1) {\n                        value = target1;\n                    } else if (value < target2) {\n                        value = target2;\n                    }\n                }\n                return value;\n            },\n        },\n        // 컬러센서 AA1 이(가) 빨간색 색인가?\n        connect_color_input_b: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                    {\n                        type: 'connect_dropdown_color_1',\n                    },\n                ],\n                type: 'connect_color_input_b',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const target = Entry.ProboConnect.convertDropdownColor1(\n                    script.getNumberValue('PARAM1')\n                );\n                const value = Entry.hw.portData.InputData.Analog[port];\n                const color = Entry.ProboConnect.Color;\n                return color[target][0] <= value && value <= color[target][1];\n            },\n        },\n        // 컬러센서 AA1 의 색상\n        connect_color_input_r: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            def: {\n                params: [                    \n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                ],\n                type: 'connect_color_input_r',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const value = Entry.hw.portData.InputData.Analog[port];\n                const color = Entry.ProboConnect.Color;\n                let colorName = '';\n                for (let i = 0; i < 6; i++) {\n                    if (color[i][0] <= value && value <= color[i][1]) {\n                        switch (i) {\n                            case 0:\n                                colorName = Lang.template.item_color_red;\n                                break;\n                            case 1:\n                                colorName = Lang.template.item_color_green;\n                                break;\n                            case 2:\n                                colorName = Lang.template.item_color_blue;\n                                break;\n                            case 3:\n                                colorName = Lang.template.item_color_yellow;\n                                break;\n                            case 4:\n                                colorName = Lang.template.item_color_black;\n                                break;\n                            case 5:\n                                colorName = Lang.template.item_color_white;\n                                break;\n                        }\n                    }\n                }\n                return colorName;\n            },\n        },\n        // 무한회전 센서 AA1 을 0 값으로 정하기\n        connect_infinite_setting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_sensor_2',\n                    },\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    null\n                ],\n                type: 'connect_infinite_setting',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n                PARAM2: 2,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM1')\n                );\n                let value = script.getNumberValue('PARAM2');\n                let count = 0;\n                \n                if (value != 0) {\n                    count = Number(value / 255).toFixed(0);\n                    value = value % 255;\n                } else {\n                    value = 0;\n                    count = 0;\n                }\n                \n                Entry.ProboConnect.Infinite_Buff[port] = Entry.hw.portData.InputData.Analog[port];\n                Entry.ProboConnect.Infinite_Start[port] = Entry.hw.portData.InputData.Analog[port]-value;\n                Entry.ProboConnect.Infinite_Count[port] = count;\n\n                return script.callReturn();\n            },\n        },\n        // 무한회전 센서 AA1 지름 53.5 의 mm 값\n        connect_infinite_mm_diameter: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_sensor_2',\n                    },\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                    {\n                        type: 'number',\n                        params: [ 53.5 ],\n                    },\n                ],\n                type: 'connect_infinite_mm_diameter',\n            },\n            paramsKeyMap: {\n                PARAM1: 1,\n                PARAM2: 2,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM1')\n                );\n                const diameter = script.getNumberValue('PARAM2');\n                let value = Entry.hw.portData.InputData.Analog[port];\n\n                if (value < Entry.ProboConnect.Infinite_Buff[port] - 150) {\n\n                    Entry.ProboConnect.Infinite_Count[port]++;\n                } else if (value > Entry.ProboConnect.Infinite_Buff[port] + 150) {\n                    Entry.ProboConnect.Infinite_Count[port]--;\n                }                    \n                Entry.ProboConnect.Infinite_Buff[port] = value;\n                value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255);\n\n                return Number(\n                    2 *\n                    3.141592 *\n                    (diameter / 2) /\n                    255 *\n                    value\n                ).toFixed(3);\n            },\n        },\n        // 무한회전 센서 AA1 의 값\n        connect_infinite_transform_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [                    \n                    {\n                        type: 'connect_dropdown_sensor_2',\n                    },\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                    {\n                        type: 'connect_dropdown_sensor_transfer',\n                    },\n                ],\n                type: 'connect_infinite_transform_input',\n            },\n            paramsKeyMap: {\n                PARAM1: 1,\n                PARAM2: 2,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM1')\n                );\n                const select = Entry.ProboConnect.convertDropdownSensorTransfer(\n                    script.getStringValue('PARAM2')\n                );\n\n                let value = Entry.hw.portData.InputData.Analog[port];\n\n                if (value < (Entry.ProboConnect.Infinite_Buff[port] - 150)) {\n                    Entry.ProboConnect.Infinite_Count[port]++;\n                } else if (value > (Entry.ProboConnect.Infinite_Buff[port] + 150)) {\n                    Entry.ProboConnect.Infinite_Count[port]--;\n                }\n                Entry.ProboConnect.Infinite_Buff[port] = value;\n                value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255);\n\n                switch (select) {\n                    case 2:\n                        if (value > 0) {\n                            return Math.floor((value%255) * 1.41732);\n                        } else {\n                            return Math.ceil((value%255) * 1.41732);\n                        }                            \n                    case 3:\n                        return Number((360/255) * Entry.hw.portData.InputData.Analog[port]).toFixed(0);\n                    case 4:\n                        if (value > 0) {\n                            return Math.floor(value / 255);\n                        } else {\n                            return Math.ceil(value / 255);\n                        }\n                    default:\n                        return value;\n                }\n            },\n        },\n        // 멀티키 센서 AA1 의 키1\n        connect_multi_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                    {\n                        type: 'connect_dropdown_key',\n                    },\n                ],\n                type: 'connect_multi_sensor',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const key = Entry.ProboConnect.convertDropdownKey(\n                    script.getStringValue('PARAM1')\n                );\n                const value = Entry.hw.portData.InputData.Analog[port] & (0x1 << key)? 1 : 0;\n                return value;\n            },\n        },\n        // 분배스위치 센서 AA1의 키1\n        connect_multi_switch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'connect_dropdown_analog',\n                    },\n                    {\n                        type: 'connect_dropdown_key',\n                    },\n                ],\n                type: 'connect_multi_switch',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const key = Entry.ProboConnect.convertDropdownKey(\n                    script.getStringValue('PARAM1')\n                );\n                const analog = Entry.hw.portData.InputData.Analog[port];\n                let  value = -1;\n                if (1 <= analog && analog <= 19) {\n                    value = 0;\n                } else if (26 <= analog && analog <= 44) {\n                    value = 1;\n                } else if (53 <= analog && analog <= 77) {\n                    value = 2;\n                } else if (83 <= analog && analog <= 101) {\n                    value = 3;\n                } else if (107 <= analog && analog <= 125) {\n                    value = 4;\n                } else if (139 <= analog && analog <= 157) {\n                    value = 5;\n                } else if (160 <= analog && analog <= 178) {\n                    value = 6;\n                } else if (191 <= analog && analog <= 209) {\n                    value = 7;\n                }\n                return key === value ? 1 : 0;\n            },\n        },\n        connect_eeprom_buffset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [{ type: 'number', params: ['0'] }, null],\n                type: 'connect_eeprom_buffset',\n            },\n            paramsKeyMap: {\n                ADDRESS: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const address = script.getNumberValue('ADDRESS', script);\n                if (!script.isStart) {\n                    Entry.ProboConnect.EEPROM.EEPROM_Count = Entry.hw.portData.InputData.EEPROM.EC;\n                    Entry.hw.sendQueue['EEPR4'] = 0x40;\n                    Entry.hw.sendQueue['EEPR3'] = address;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue = 0.05;\n                    var fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    var blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.ProboConnect.EEPROM.EEPROM_Buff =\n                        (Entry.hw.portData.InputData.EEPROM.EEPR2 << 8) +\n                        Entry.hw.portData.InputData.EEPROM.EEPR1;\n                    Entry.hw.sendQueue['EEPR4'] = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // EEPROM 주소의 값\n        connect_eeprom_address_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            def: {\n                type: 'connect_eeprom_address_value',\n            },\n            class: 'input',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                var value = 0;\n                const count = Entry.ProboConnect.EEPROM.EEPROM_Count;\n                if (Entry.hw.portData.InputData.EEPROM.EC != count) {\n                    value = Entry.ProboConnect.EEPROM.EEPROM_Buff;\n                }\n                return value;\n            },\n        },\n        ///========================================================================================\n        /// output block\n        ///========================================================================================\n        // DC 모터 1을(를) 0 속도로 회전\n        connect_dc_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_dc_1_all',\n                    },\n                    {\n                        type: 'connect_dropdown_velocity',\n                    },\n                    null,\n                ],\n                type: 'connect_dc_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const motor = Entry.ProboConnect.convertDropdownDC(\n                    script.getStringValue('PARAM0')\n                ); \n                const value = script.getNumberValue('PARAM1');\n                switch (motor) {\n                    case 'DC5':\n                        Entry.hw.sendQueue['DC1'] = value;\n                        Entry.hw.sendQueue['DC2'] = value;\n                        break;\n                    case 'DC6':\n                        Entry.hw.sendQueue['DC3'] = value;\n                        Entry.hw.sendQueue['DC4'] = value;\n                        break;\n                    case 'DC7':\n                        Entry.hw.sendQueue['DC1'] = value;\n                        Entry.hw.sendQueue['DC2'] = value;\n                        Entry.hw.sendQueue['DC3'] = value;\n                        Entry.hw.sendQueue['DC4'] = value;\n                        break;\n                    default:\n                        Entry.hw.sendQueue[motor] = value;\n                        break;\n                }\n                return script.callReturn();\n            },\n        },\n        // 서보모터 1 의 위치를 1 로 이동 \n        connect_servo_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_servo_1_4',\n                    },\n                    {\n                        type: 'connect_dropdown_servo_position',\n                    },\n                    null,\n                ],\n                type: 'connect_servo_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const servo = Entry.ProboConnect.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                let value = script.getNumberValue('PARAM1');\n                if (value < 1) {\n                    value = 0;\n                } else if (value > 100) {\n                    value = 100;\n                }\n\n                Entry.hw.sendQueue[servo] = value;\n                return script.callReturn();\n            },\n        },\n        // S 모터 1 을(를) 0 속도로 회전\n        connect_s_dc_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_servo_1_4',\n                    },\n                    {\n                        type: 'connect_dropdown_velocity',\n                    },\n                    null,\n                ],\n                type: 'connect_s_dc_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const motor = Entry.ProboConnect.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                let value = script.getNumberValue('PARAM1');\n\n                if (value > 20) {\n                    value = 20;\n                } else if (value < -20) {\n                    value = -20;\n                }\n                value += 148;\n\n                switch (motor) {\n                    case 'Servo5':\n                        Entry.hw.sendQueue['Servo1'] = value;\n                        Entry.hw.sendQueue['Servo2'] = value;\n                        break;\n                    case 'Servo6':\n                        Entry.hw.sendQueue['Servo3'] = value;\n                        Entry.hw.sendQueue['Servo4'] = value;\n                        break;\n                    default:\n                        Entry.hw.sendQueue[motor] = value;\n                        break;\n                }\n                return script.callReturn();\n            },\n        },\n        // 출력핀 1 을(를) 켜기\n        connect_port_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_port_1_4',\n                    },\n                    {\n                        type: 'connect_dropdown_on_off',\n                    },\n                    null\n                ],\n                type: 'connect_port_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const motor = Entry.ProboConnect.convertDropdownPort(\n                    script.getStringValue('PARAM0')\n                );\n                const value = Entry.ProboConnect.convertDropdownOnOff(\n                    script.getNumberValue('PARAM1')\n                );\n\n                Entry.hw.sendQueue[motor] = value;\n                return script.callReturn();\n            },\n        },\n        // 도(60) 을(를) 4분 음표로 연주하기\n        connect_melody_note_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_pitch',\n                    },\n                    {\n                        type: 'connect_dropdown_note',\n                    },\n                    null\n                ],\n                type: 'connect_melody_note_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const pitch = Entry.ProboConnect.convertDropdownPitch(\n                        script.getNumberValue('PARAM0')\n                    );\n                    const note = Entry.ProboConnect.convertDropdownNote(\n                        script.getStringValue('PARAM1')\n                    );\n                    \n                    let timeValue = Entry.ProboConnect.Note[note];\n\n                    Entry.hw.sendQueue['MEL2'] = pitch >> 8;\n                    Entry.hw.sendQueue['MEL1'] = pitch;\n\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue;\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['MEL2'] = 0;\n                    Entry.hw.sendQueue['MEL1'] = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // 도(60) 을(를) 0.5 초 동안 연주하기\n        connect_melody_sec_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_pitch',\n                    },\n                    {\n                        type: 'connect_dropdown_time_1',\n                    },\n                    null\n                ],\n                type: 'connect_melody_sec_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const pitch = Entry.ProboConnect.convertDropdownPitch(\n                        script.getNumberValue('PARAM0')\n                    );\n                    let timeValue = script.getNumberValue('PARAM1');\n                   \n                    Entry.hw.sendQueue['MEL2'] = pitch >> 8;\n                    Entry.hw.sendQueue['MEL1'] = pitch;\n\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['MEL2'] = 0;\n                    Entry.hw.sendQueue['MEL1'] = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // 도(60) 을(를) 연주하기\n        connect_melody_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_pitch',\n                    },\n                    null\n                ],\n                type: 'connect_melody_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const pitch = Entry.ProboConnect.convertDropdownPitch(\n                    script.getNumberValue('PARAM0')\n                );\n\n                Entry.hw.sendQueue['MEL2'] = pitch >> 8;\n                Entry.hw.sendQueue['MEL1'] = pitch;\n                return script.callReturn();\n            },\n        },\n        // 35391 값을 0.5 초 동안 연주하기\n        connect_value_sec_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 35391 ],\n                    },\n                    {\n                        type: 'connect_dropdown_time_1',\n                    },\n                    null\n                ],\n                type: 'connect_value_sec_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    let melody = script.getNumberValue('PARAM0');\n                    let timeValue = script.getNumberValue('PARAM1');\n\n                    Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff;\n                    Entry.hw.sendQueue['MEL1'] = melody & 0xff;\n\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['MEL2'] = 0;\n                    Entry.hw.sendQueue['MEL1'] = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // 35391 값을(를) 연주하기\n        connect_value_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 35391 ],\n                    },\n                    null\n                ],\n                type: 'connect_value_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                let melody = script.getNumberValue('PARAM0');\n                Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff;\n                Entry.hw.sendQueue['MEL1'] = melody & 0xff;\n                return script.callReturn();\n            },\n        },\n        // 시작음 을(를) 1 초 간격으로 재생하기\n        connect_melody_track_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_melody',\n                    },\n                    { \n                        type: 'connect_dropdown_time_2',\n                    },\n                    null\n                ],\n                type: 'connect_melody_track_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                function getTrackStep(track,script){\n                    if(!script.isStart){\n                        script.isStart = true;\n                        script.trackStep = 0;\n                    }\n                    else {\n                        script.trackStep++;\n                    }\n                    let timeValue = script.getNumberValue('PARAM1');\n                    script.timeFlag = 1;\n                    let melody = Entry.ProboConnect.Track[track][script.trackStep];\n                    Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff;\n                    Entry.hw.sendQueue['MEL1'] = melody & 0xff;\n\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    Entry.TimeWaitManager.add(\n                        script.block.id,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                }\n                const TR = Entry.ProboConnect.convertDropdownMelody(\n                    script.getStringValue('PARAM0')\n                );\n                if (!script.isStart) {\n                    switch(TR) {\n                        case 0 :\n                            script.maxStep = 6;\n                            break;\n                        case 1 :\n                            script.maxStep = 7;\n                            break;\n                        case 2 :\n                            script.maxStep = 3;\n                            break;\n                        case 3 :\n                            script.maxStep = 3;\n                            break;\n                    }\n                    getTrackStep(TR,script);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else if (script.trackStep < script.maxStep){\n                    getTrackStep(TR,script);\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['MEL2'] = 0;\n                    Entry.hw.sendQueue['MEL1'] = 0;\n\n                    delete script.trackStep;\n                    delete script.maxStep;\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // 멜로디 중지\n        connect_melody_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n                type: 'connect_melody_off',\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue['MEL2'] = 0;\n                Entry.hw.sendQueue['MEL1'] = 0;\n                return script.callReturn();\n            },\n        },\n        // RGB LED 1 을(를) 빨간색 으로 켜기\n        connect_rgbled_on_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_servo_1_4',\n                    },\n                    {\n                        type: 'connect_dropdown_color_2',\n                    },\n                    null\n                ],\n                type: 'connect_rgbled_on_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                const color = Entry.ProboConnect.convertDropdownColor2(\n                    script.getStringValue('PARAM1')\n                );\n                Entry.hw.sendQueue[port] = color;\n                return script.callReturn();\n            },\n        },    \n        // RGB LED 을(를) 끄기    \n        connect_rgbled_off_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_servo_1_4',\n                    },\n                    null\n                ],\n                type: 'connect_rgbled_off_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                Entry.hw.sendQueue[port] = 0;\n            },\n        },\n        // RGB LED 1 빨간색으로 0.5초 간격\n        connect_rgbled_flashing_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_servo_1_4',\n                    },\n                    { \n                        type: 'connect_dropdown_color_2',\n                    },\n                    { \n                        type: 'connect_dropdown_time_3',\n                    },\n                    null\n                ],\n                type: 'connect_rgbled_flashing_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n                PARAM2: 2,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                const color = Entry.ProboConnect.convertDropdownColor2(\n                    script.getStringValue('PARAM1')\n                );\n                const sec = script.getNumberValue('PARAM2');\n                let value = 0;\n                switch (sec) {\n                    case 0.05:\n                        value = color + 0;\n                        break;\n                    case 0.1:\n                        value = color + 1;\n                        break;\n                    case 0.2:\n                        value = color + 2;\n                        break;                    \n                    case 0.5:\n                        value = color + 3;\n                        break;                        \n                    case 1:\n                        value = color + 4;\n                        break;\n                }\n                Entry.hw.sendQueue[port] = value;\n                return script.callReturn();\n            },\n        },\n        // RGB LED 1을(를) 빨간색으로 디밍\n        connect_rgbled_dimming_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'connect_dropdown_servo_1_4',\n                    },\n                    { \n                        type: 'connect_dropdown_color_2',\n                    },\n                    null\n                ],\n                type: 'connect_rgbled_dimming_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const port = Entry.ProboConnect.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                let color = 0;\n                switch (script.getStringValue('PARAM1')) {\n                    case '1':\n                        color = 90;\n                        break;\n                    case '2':\n                        color = 92;\n                        break;\n                    case '3':\n                        color = 94;\n                        break;\n                    case '4':\n                        color = 93;\n                        break;\n                    case '5':\n                        color = 95;\n                        break;\n                    case '6':\n                        color = 91;\n                        break;\n                    case '7':\n                        color = 96;\n                        break;\n                }\n                Entry.hw.sendQueue[port] = color;\n                return script.callReturn();\n            },\n        },\n        // FND를 0 (으)로 설정\n        connect_fnd_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    null\n                ],\n                type: 'connect_fnd_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const fnd = script.getNumberValue('PARAM0');\n                Entry.hw.sendQueue['FND'] = fnd;\n                return script.callReturn();\n            },\n        },\n        // FND 끄기\n        connect_fnd_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n                type: 'connect_fnd_off',\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue['FND'] = 100;\n                return script.callReturn();\n            },\n        },\n        // EEPROM 0 주소에 0 값 설정하기\n        connect_eeprom_write: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'number',\n                        params: [ 0 ]\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ]\n                    },\n                    null,\n                ],\n                type: 'connect_eeprom_write',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboConnect'],\n            func: function(sprite, script) {\n                const address = script.getNumberValue('PARAM0');\n                const value = script.getNumberValue('PARAM1');\n                if (!script.isStart) {\n                    Entry.hw.update();\n                    Entry.hw.sendQueue['EEPR4'] = 0x80;\n                    Entry.hw.sendQueue['EEPR3'] = address;\n                    Entry.hw.sendQueue['EEPR2'] = (value >> 8) & 0xff;\n                    Entry.hw.sendQueue['EEPR1'] = value & 0xff;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    let timeValue = 0.05;\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.update();\n                    Entry.hw.sendQueue['EEPR4'] = 0x40;\n                    Entry.hw.sendQueue['EEPR3'] = address;\n                    Entry.hw.sendQueue['EEPR2'] = 0;\n                    Entry.hw.sendQueue['EEPR1'] = 0;\n\n                    setTimeout(function() {  \n                        Entry.hw.update();                      \n                        Entry.hw.sendQueue['EEPR4'] = 0;\n                        Entry.hw.sendQueue['EEPR3'] = 0;\n                        Entry.hw.sendQueue['EEPR2'] = 0;\n                        Entry.hw.sendQueue['EEPR1'] = 0;\n                    }, 100);\n                    \n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.ProboConnect;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_alux_nemo.js",
    "content": "'use strict';\n\nEntry.nemo = {\n    id: ['63.1'],\n    name: 'nemo',\n    url: 'https://www.aluxonline.com',\n    imageName: 'alux_nemo.png',\n    title: {\n        ko: '네모',\n        en: 'NEMO',\n    },\n    delayTime: 0.001,\n    setZero: function() {\n        Entry.hw.sendQueue['NEMO_INIT'] = {\n            id: Math.random(),\n            setZero: 1,\n        };\n        Entry.hw.update();\n        this.setCount = 0;\n    },\n    numToMS(num) {\n        let ms = 0;\n        if (num < 0) {\n            ms = 0;\n        } else if (0 <= num && num <= 5) {\n            switch(num) {\n                case 0:\n                    ms = 0;\n                    break;\n                case 1:\n                    ms = 500;\n                    break;\n                case 2:\n                    ms = 200;\n                    break;\n                case 3:\n                    ms = 100;\n                    break;\n                case 4:\n                    ms = 50;\n                    break;\n                case 5:\n                    ms = 20;\n                    break;\n            }\n        } else {\n            ms = 500;\n        }\n        return ms;\n    },\n    afterReceive(portData) {\n        const motion = portData['NEMO_EVENT_MOTION'];\n        const button = portData['NEMO_EVENT_BUTTON'];        \n        const temp = Entry.hw.portData['NEMO_DEVICE'].anSwitch;\n        if (button === true) {\n            Entry.engine.fireEvent('aluxNemoButtonEventReceived');\n        }\n        if (motion === true) {\n            Entry.engine.fireEvent('aluxNemoMotionEventReceived');\n        }\n    },\n    setProcessor(script, delayTime, code) {\n        if (!script.isStart) {\n            script.isStart = true;\n            script.timeFlag = 1;\n            const fps = Entry.FPS || 60;\n            const timeValue = (60 / fps) * delayTime * 1000;\n            Entry.TimeWaitManager.add(\n                Math.random(),\n                () => {\n                    script.timeFlag = 0;\n                },\n                timeValue\n            );\n            Entry.toybot.scoreFlag = code();\n            return script;\n        } else if (script.timeFlag == 1) {\n            return script;\n        } else {\n            delete script.timeFlag;\n            delete script.isStart;\n            Entry.engine.isContinue = false;\n            return script.callReturn();\n        }\n    },\n};\n\nEntry.nemo.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                title_namo_input: '네모 입력',\n                title_namo_output: '네모 출력',\n                title_namo_extension: '네모 확장',\n                line_emtpy: ' ',\n\n                list_s1: 'S1',\n                list_s2: 'S2',\n                list_s3: 'S3',\n                list_s4: 'S4',\n                list_motion_1: '앞으로 기울임',\n                list_motion_2: '뒤로 기울임',\n                list_motion_3: '왼쪽으로 기울임',\n                list_motion_4: '오른쪽으로 기울임',\n                list_motion_5: '위로 놓음',\n                list_motion_6: '아래로 놓음',\n                list_motion_7: '세워 놓음',\n                list_motion_8: '충격 받음',\n                list_smile: '웃음',\n                list_not_much: '별로',\n                list_good: '좋음',\n                list_bad: '나쁨',\n                list_wink: '윙크',\n                list_cry: '울음',\n                list_absurd: '어이없음',\n                list_peck: '뽀뽀',\n                list_arrow_1: '화살표 1',\n                list_arrow_2: '화살표 2',\n                list_arrow_3: '화살표 3',\n                list_arrow_4: '화살표 4',\n                list_arrow_5: '화살표 5',\n                list_arrow_6: '화살표 6',\n                list_arrow_7: '화살표 7',\n                list_arrow_8: '화살표 8',\n                list_spade: '스페이드',\n                list_club: '클럽',\n                list_diamond: '다이아몬드',\n                list_heart: '하트',\n                list_circle: '원',\n                list_x: '엑스',\n                list_triangle: '세모',\n                list_square: '네모',\n                list_note_1: '음표 1',\n                list_note_2: '음표 2',\n                list_note_3: '음표 3',\n                list_dice_1: '주사위 1',\n                list_dice_2: '주사위 2',\n                list_dice_3: '주사위 3',\n                list_dice_4: '주사위 4',\n                list_dice_5: '주사위 5',\n                list_dice_6: '주사위 6',\n                list_is_pressing: '눌려 있을 때',\n                list_pressed: '눌렀을 때',\n                list_released: '뗐을 때',\n                list_has_prssing: '눌려 있는가',\n                list_has_pressed: '눌렀는가',\n                list_has_released: '뗐는가',\n                list_axis_x: 'X축',\n                list_axis_y: 'Y축',\n                list_axis_z: 'Z축',\n                list_linear_acceleration: '선형 가속도',\n                list_off1: '끄기',\n                list_on1: '켜기',\n                list_off2: '□',\n                list_on2: '■',\n                list_toggle: '토글',\n                list_do_re_mi_song: '도레미송',\n                list_an_island_baby: '섬집아기',\n                list_twinkle_twinkle_little_star: '작은별',\n                list_spring_in_my_hometown: '고향의 봄',\n                list_for_elise: '엘리제를 위하여',\n                list_celebrated_chop_waltz: '젓가락 행진곡',\n                list_happy_birthday_to_you: '생일 축하곡',\n                list_lc: 'C(0)',\n                list_lcs: 'C#(1)',\n                list_ld: 'D(2)',\n                list_lds: 'D#(3)',\n                list_le: 'E(4)',\n                list_lf: 'F(5)',\n                list_lfs: 'F#(6)',\n                list_lg: 'G(7)',\n                list_lgs: 'G#(8)',\n                list_la: 'A(9)',\n                list_las: 'A#(10)',\n                list_lb: 'B(11)',\n                list_mc: 'C(12)',\n                list_mcs: 'C#(13)',\n                list_md: 'D(14)',\n                list_mds: 'D#(15)',\n                list_me: 'E(16)',\n                list_mf: 'F(17)',\n                list_mfs: 'F#(18)',\n                list_mg: 'G(19)',\n                list_mgs: 'G#(20)',\n                list_ma: 'A(21)',\n                list_mas: 'A#(22)',\n                list_mb: 'B(23)',\n                list_hc: 'C(24)',\n                list_switch: '스위치',\n                list_infrared_ray: '적외선',\n                list_magnet: '자석',\n                list_rotation: '회전',\n                list_brightness: '밝기',\n                list_sound: '소리',\n                list_tilt: '기울기',\n                list_pressure: '압력',\n                list_heart_rate: '심박',\n                list_value: '값',\n                list_angle: '각도',\n                list_absolute_angle: '절대 각도',\n                list_rotation_value: '회전 수',\n                list_east: '동쪽',\n                list_west: '서쪽',\n                list_south: '남쪽',\n                list_north: '북쪽',\n\n                input_event_button_state: '%1 %2 버튼 %3',\n                input_event_motion_sensing: '%1 %2 이 감지되었을 때',\n                input_bool_button_state: '%1 버튼 %2 ?',\n                input_bool_motion_sensing: '%1 이 감지되었는가?',\n                input_bool_led_state_value: 'LED X: %1 Y: %2 상태값',\n                input_field_button_analog_value: '%1 버튼의 아날로그 값',\n                input_field_acceleration_value: '가속도 센서 %1 의 값',\n                input_field_brightness_value: '밝기 센서의 값',\n                input_field_convert_value: '%1 의 값 %2 ~ %3 을 %4 ~ %5 으(로) 변환',\n\n                output_basic_display_led_icon: 'LED 아이콘 %1 을 %2 속도로 출력 %3',\n                output_basic_diplay_led_custom_icon: 'LED %1 줄의 %2%3%4%5%6%7%8 을 %9 속도로 출력 %10',\n                output_basic_display_led_string: 'LED %1 문자열을 %2 속도로 출력 %3',\n                output_basic_delete_all_led: 'LED 출력 지우기 %1',\n                output_basic_coordinate_value: 'LED X: %1 Y: %2 %3 %4',\n                output_basic_play_melody: '멜로디 %1 재생하기 %2',\n                output_basic_play_melody_to_the_end: '멜로디 %1 끝까지 재생하기 %2',\n                output_basic_play_note: '%1 음을 재생하기 %2',\n                output_basic_play_note_for_seconds: '%1 음을 %2 초동안 재생하기 %3',\n                output_basic_stop_all_sound: '모든 소리 정지 %1',\n\n                extension_basic_set_expension: '확장센서를 %1 (으)로 설정 %2',\n                extension_basic_set_expension_value: '확장센서를 %1 값으로 정하기',\n                extension_bool_expension_state: '확장센서 %1 ? %2',\n                extension_field_expension_anlog_value: '확장센서의 아날로그 값 %1',\n                extension_field_expension_custom_value: '확장센서의 %1',\n                extension_basic_set_compass_value: '나침반센서를 %1 값으로 정하기',\n                extension_field_compass_analog_value: '나침반센서의 아날로그 값 %1',\n                extension_field_compass_custom_value: '나침반센서의 %1',\n                extension_bool_compass_state: '나침반센서의 방향이 %1 인가 ?',\n            },\n        },\n        en: {\n            template: {\n                title_namo_input: 'NAMO INPUT',\n                title_namo_output: 'NAMO OUTPUT',\n                title_namo_extension: 'NAMO EXTENSION',\n                line_emtpy: ' ',\n\n                list_s1: 'S1',\n                list_s2: 'S2',\n                list_s3: 'S3',\n                list_s4: 'S4',                \n                list_motion_1: 'Tilting forward',\n                list_motion_2: 'Tilting back',\n                list_motion_3: 'Tilting to the left',\n                list_motion_4: 'Tilting to the right',\n                list_motion_5: 'Put it up',\n                list_motion_6: 'Put it down',\n                list_motion_7: 'Standing up',\n                list_motion_8: 'Impacted',\n                list_smile: 'Smile',\n                list_not_much: 'Not much',\n                list_good: 'Good',\n                list_bad: 'Bad',\n                list_wink: 'Wink',\n                list_cry: 'Cry',\n                list_absurd: 'Absurd',\n                list_peck: 'Peck',\n                list_arrow_1: 'Arrow 1',\n                list_arrow_2: 'Arrow 2',\n                list_arrow_3: 'Arrow 3',\n                list_arrow_4: 'Arrow 4',\n                list_arrow_5: 'Arrow 5',\n                list_arrow_6: 'Arrow 6',\n                list_arrow_7: 'Arrow 7',\n                list_arrow_8: 'Arrow 8',\n                list_spade: 'Spade',\n                list_club: 'Club',\n                list_diamond: 'Diamond',\n                list_heart: 'heart',\n                list_circle: 'Circle',\n                list_x: 'X',\n                list_triangle: 'Triangle',\n                list_square: 'Square',\n                list_note_1: 'note 1',\n                list_note_2: 'note 2',\n                list_note_3: 'note 3',\n                list_dice_1: 'dice 1',\n                list_dice_2: 'dice 2',\n                list_dice_3: 'dice 3',\n                list_dice_4: 'dice 4',\n                list_dice_5: 'dice 5',\n                list_dice_6: 'dice 6',\n                list_is_pressing: 'Is pressing',\n                list_pressed: 'Pressed',\n                list_released: 'released',\n                list_has_prssing: 'has be pressing',\n                list_has_pressed: 'has pressed',\n                list_has_released: 'has released',\n                list_axis_x: 'X axis',\n                list_axis_y: 'Y axis',\n                list_axis_z: 'Z axis',\n                list_linear_acceleration: 'Linear acceleration',\n                list_off1: 'Off',\n                list_on1: 'On',\n                list_off2: '□',\n                list_on2: '■',\n                list_toggle: 'Toggle',\n                list_do_re_mi_song: 'Do Re Mi Song',\n                list_an_island_baby: 'An Island Baby',\n                list_twinkle_twinkle_little_star: 'Twinkle Twinkle Little Star',\n                list_spring_in_my_hometown: 'Spring in My Hometwon',\n                list_for_elise: 'For Elise',\n                list_celebrated_chop_waltz: 'Celebrate Chop Waltz',\n                list_happy_birthday_to_you: 'Happy Birthday To You',\n                list_lc: 'C(0)',\n                list_lcs: 'C#(1)',\n                list_ld: 'D(2)',\n                list_lds: 'D#(3)',\n                list_le: 'E(4)',\n                list_lf: 'F(5)',\n                list_lfs: 'F#(6)',\n                list_lg: 'G(7)',\n                list_lgs: 'G#(8)',\n                list_la: 'A(9)',\n                list_las: 'A#(10)',\n                list_lb: 'B(11)',\n                list_mc: 'C(12)',\n                list_mcs: 'C#(13)',\n                list_md: 'D(14)',\n                list_mds: 'D#(15)',\n                list_me: 'E(16)',\n                list_mf: 'F(17)',\n                list_mfs: 'F#(18)',\n                list_mg: 'G(19)',\n                list_mgs: 'G#(20)',\n                list_ma: 'A(21)',\n                list_mas: 'A#(22)',\n                list_mb: 'B(23)',\n                list_hc: 'C(24)',\n                list_switch: 'Switch',\n                list_infrared_ray: 'Infrared ray',\n                list_magnet: 'Magnet',\n                list_rotation: 'Rotation',\n                list_brightness: 'Brightness',\n                list_sound: 'Sound',\n                list_tilt: 'Tilt',\n                list_pressure: 'Pressure',\n                list_heart_rate: 'Heart rate',\n                list_value: 'Value',\n                list_angle: 'Angle',\n                list_absolute_angle: 'Absolute angle',\n                list_rotation_value: 'Rotation value',\n                list_east: 'East',\n                list_west: 'West',\n                list_south: 'South',\n                list_north: 'North',\n\n                input_event_button_state: 'When %1 button %2',\n                input_event_button_motion_sensing: 'When %1 motion is detected',\n                input_bool_button_state: 'Is %1 button %2 ?',\n                input_bool_motion_sensing: 'Is %1 motion detected',\n                input_bool_led_state_value: ' LED X: %1 Y: %2 status',\n                input_field_button_analog_value: 'Analog value of %1 button',\n                input_field_acceleration_value: 'Acceleration sensor %1 value',\n                input_field_brightness_value: 'Value of illuminance sensor',\n                input_field_convert_value: 'change the value of %1 from %2 ~ %3 to %4 ~ %5',\n\n                output_basic_display_led_icon: 'LED icon %1 output %2 speed %3',\n                output_basic_diplay_led_custom_icon: 'LED %1 line %2%3%4%5%6%7%8 at %9 speed %10',\n                output_basic_display_led_string: 'LED %1 string output %2 speed %3',\n                output_basic_delete_all_led: 'Clear LED output %1',\n                output_basic_coordinate_value: 'LED X: %1 Y: %2 %3 %4',\n                output_basic_play_melody: 'Play melody %1 %2',\n                output_basic_play_melody_to_the_end: 'melody %1 play to the end %2',\n                output_basic_play_note: 'Playing note %1 %2',\n                output_basic_play_note_for_seconds: 'Play note %1 for %2 second(s) %3',\n                output_basic_stop_all_sound: 'Stop all sound %1',\n\n                extension_basic_set_expension: 'Expansion type set %1 %2',\n                extension_basic_set_expension_value: 'Expansion sensor set %1 value ? %2',\n                extension_bool_expension_state: 'Is extended sensor %1',\n                extension_field_expension_anlog_value: 'Value of extended sensor %1',\n                extension_field_expension_custom_value: 'Exansion sensor value of %1',\n                extension_basic_set_compass_value: 'Compass sensor value Set %1',\n                extension_field_compass_analog_value: 'Value of compass sensor %1',\n                extension_field_compass_custom_value: 'compass sensor value of %1',\n                extension_bool_compass_state: 'Does the rotation sensor point %1 ?',\n            },\n        },\n    };\n};\n\nEntry.nemo.blockMenuBlocks = [\n    'nemo_dropdown_button',\n    'nemo_dropdown_button_now_state',\n    'nemo_dropdown_button_state_question',\n    'nemo_dropdown_motion',\n    'nemo_dropdown_coordinate_acceleration',\n    'nemo_dropdown_led_icon',\n    'nemo_dropdown_switch',\n    'nemo_dropdown_melody',\n    'nemo_dropdown_keyboard',\n    'nemo_dropdown_expension_sensor_mode',\n    'nemo_dropdown_compass_sensor_mode',\n    'nemo_dropdown_direction',\n    'nemo_dropdown_index_0_5',\n    'nemo_dropdown_index_1_5',\n    'nemo_dropdown_index_1_7',\n    'nemo_dropdown_toggle',\n    'nemo_dropdown_toggle2',\n    \n    'nemo_title_namo_input',\n    'nemo_block_input_event_button_state',\n    'nemo_block_input_event_motion_sensing',\n    'nemo_block_input_bool_button_state',\n    'nemo_block_input_bool_motion_sensing',\n    'nemo_block_input_bool_led_state_value',\n    'nemo_block_input_field_button_analog_value',\n    'nemo_block_input_field_acceleration_value',\n    'nemo_block_input_field_brightness_value',\n    'nemo_block_input_field_convert_value',\n\n    'nemo_title_namo_output',\n    'nemo_block_output_basic_display_led_icon',\n    'nemo_block_output_basic_diplay_led_custom_icon',\n    'nemo_block_output_basic_display_led_string',\n    'nemo_block_output_basic_delete_all_led',\n    'nemo_block_output_basic_coordinate_value',\n    'nemo_block_output_basic_play_melody',\n    'nemo_block_output_basic_play_melody_to_the_end',\n    'nemo_block_output_basic_play_note',\n    'nemo_block_output_basic_play_note_for_seconds',\n    'nemo_block_output_basic_stop_all_sound',\n\n    'nemo_title_namo_extension',\n    'nemo_block_extension_basic_set_expension',\n    'nemo_block_extension_basic_set_expension_value',\n    'nemo_block_extension_bool_expension_state',\n    'nemo_block_extension_field_expension_anlog_value',\n    'nemo_block_extension_field_expension_custom_value',\n    'nemo_block_extension_basic_set_compass_value',\n    'nemo_block_extension_field_compass_analog_value',\n    'nemo_block_extension_field_compass_custom_value',\n    'nemo_block_extension_bool_compass_state',\n];\n\nEntry.nemo.getBlocks = function() {\n    return {\n        ///========================================================================================\n        /// Dropdown block\n        ///========================================================================================\n        nemo_dropdown_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_s1, 0],\n                        [Lang.template.list_s2, 1],\n                        [Lang.template.list_s3, 2],\n                        [Lang.template.list_s4, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_button_now_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_is_pressing, 0],\n                        [Lang.template.list_pressed, 1],\n                        [Lang.template.list_released, 2],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },        \n        nemo_dropdown_button_state_question: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_has_prssing, 0],\n                        [Lang.template.list_has_pressed, 1],\n                        [Lang.template.list_has_released, 2],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_motion: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_motion_1, 0],\n                        [Lang.template.list_motion_2, 1],\n                        [Lang.template.list_motion_3, 2],\n                        [Lang.template.list_motion_4, 3],\n                        [Lang.template.list_motion_5, 4],\n                        [Lang.template.list_motion_6, 5],\n                        [Lang.template.list_motion_7, 6],\n                        [Lang.template.list_motion_8, 7],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_coordinate_acceleration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_axis_x, 0],\n                        [Lang.template.list_axis_y, 1],\n                        [Lang.template.list_axis_z, 2],\n                        [Lang.template.list_linear_acceleration, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_led_icon: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'DropdownExtra',\n                    options: [\n                        [Lang.template.list_smile, 1],\n                        [Lang.template.list_not_much, 2],\n                        [Lang.template.list_good, 3],\n                        [Lang.template.list_bad, 4],\n                        [Lang.template.list_wink, 5],\n                        [Lang.template.list_cry, 6],\n                        [Lang.template.list_absurd, 7],\n                        [Lang.template.list_peck, 8],\n                        [Lang.template.list_arrow_1, 9],\n                        [Lang.template.list_arrow_2, 10],\n                        [Lang.template.list_arrow_3, 11],\n                        [Lang.template.list_arrow_4, 12],\n                        [Lang.template.list_arrow_5, 13],\n                        [Lang.template.list_arrow_6, 14],\n                        [Lang.template.list_arrow_7, 15],\n                        [Lang.template.list_arrow_8, 16],                        \n                        [Lang.template.list_spade, 17],\n                        [Lang.template.list_club, 18],\n                        [Lang.template.list_diamond, 19],\n                        [Lang.template.list_heart, 20],\n                        [Lang.template.list_circle, 21],\n                        [Lang.template.list_x, 22],\n                        [Lang.template.list_triangle, 23],\n                        [Lang.template.list_square, 24],\n                        [Lang.template.list_note_1, 25],\n                        [Lang.template.list_note_2, 26],\n                        [Lang.template.list_note_3, 27],\n                        [Lang.template.list_dice_1, 28],\n                        [Lang.template.list_dice_2, 29],\n                        [Lang.template.list_dice_3, 30],\n                        [Lang.template.list_dice_4, 31],\n                        [Lang.template.list_dice_5, 32],\n                        [Lang.template.list_dice_6, 33],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_switch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_off1, 1],\n                        [Lang.template.list_on1, 2],\n                        [Lang.template.list_toggle, 3],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_do_re_mi_song, 1],\n                        [Lang.template.list_an_island_baby, 2],\n                        [Lang.template.list_twinkle_twinkle_little_star, 3],\n                        [Lang.template.list_spring_in_my_hometown, 4],\n                        [Lang.template.list_for_elise, 5],\n                        [Lang.template.list_celebrated_chop_waltz, 6],\n                        [Lang.template.list_happy_birthday_to_you, 7],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_keyboard: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'DropdownExtra',\n                    options: [\n                        [Lang.template.list_lc, 0],\n                        [Lang.template.list_lcs, 1],\n                        [Lang.template.list_ld, 2],\n                        [Lang.template.list_lds, 3],\n                        [Lang.template.list_le, 4],\n                        [Lang.template.list_lf, 5],\n                        [Lang.template.list_lfs, 6],\n                        [Lang.template.list_lg, 7],\n                        [Lang.template.list_lgs, 8],\n                        [Lang.template.list_la, 9],\n                        [Lang.template.list_las, 10],\n                        [Lang.template.list_lb, 11],\n                        [Lang.template.list_mc, 12],\n                        [Lang.template.list_mcs, 13],\n                        [Lang.template.list_md, 14],\n                        [Lang.template.list_mds, 15],\n                        [Lang.template.list_me, 16],\n                        [Lang.template.list_mf, 17],\n                        [Lang.template.list_mfs, 18],\n                        [Lang.template.list_mg, 19],\n                        [Lang.template.list_mgs, 20],\n                        [Lang.template.list_ma, 21],\n                        [Lang.template.list_mas, 22],\n                        [Lang.template.list_mb, 23],\n                        [Lang.template.list_hc, 24]\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_expension_sensor_mode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_switch, 0],\n                        [Lang.template.list_infrared_ray, 1],\n                        [Lang.template.list_magnet, 2],\n                        [Lang.template.list_rotation, 3],\n                        [Lang.template.list_brightness, 4],\n                        [Lang.template.list_sound, 5],\n                        [Lang.template.list_tilt, 6],\n                        [Lang.template.list_pressure, 7],\n                        [Lang.template.list_heart_rate, 8]\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_compass_sensor_mode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_value, 0],\n                        [Lang.template.list_angle, 1],\n                        [Lang.template.list_absolute_angle, 2],\n                        [Lang.template.list_rotation_value, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_east, 0],\n                        [Lang.template.list_west, 1],\n                        [Lang.template.list_south, 2],\n                        [Lang.template.list_north, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_index_0_5: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', 0],\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        ['5', 5],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_index_1_5: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        ['5', 5],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },        \n        nemo_dropdown_index_1_7: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                        ['3', 2],\n                        ['4', 3],\n                        ['5', 4],\n                        ['6', 5],\n                        ['7', 6],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_off1, 0],\n                        [Lang.template.list_on1, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        nemo_dropdown_toggle2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_off2, 0],\n                        [Lang.template.list_on2, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        ///========================================================================================\n        /// Input block\n        ///========================================================================================\n        nemo_title_namo_input: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            template: Lang.template.title_namo_input,\n            skeletonOptions: {\n                box: {\n                    offsetX: 20,\n                },\n            },\n            def: {\n                type: 'nemo_title_namo_input',\n              },\n            isNotFor: ['nemo'],\n            class : 'inputBlock',\n        },\n        nemo_block_input_event_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            template: Lang.template.input_event_button_state,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'nemo_dropdown_button',\n                    },\n                    {\n                        type: 'nemo_dropdown_button_now_state',\n                    },\n                ],\n                type: 'nemo_block_input_event_button_state',\n            },\n            paramsKeyMap: {\n                DUMMY: 0,\n                INDEX: 1,\n                STATE: 2,\n            },\n            event: 'aluxNemoButtonEventReceived',\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const state = script.getNumberValue('STATE');\n                const getState = Entry.hw.portData['NEMO_DEVICE_EX'].button[index].state[state];\n                return getState === true ? script.callReturn() : this.die();\n            }\n        },\n        nemo_block_input_event_motion_sensing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            template: Lang.template.input_event_motion_sensing,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'nemo_dropdown_motion',\n                    },\n                ],\n                type: 'nemo_block_input_event_motion_sensing',\n            },\n            paramsKeyMap: {\n                DUMMY: 0,\n                INDEX: 1,\n            },\n            event: 'aluxNemoMotionEventReceived',\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const motion = Entry.hw.portData['NEMO_DEVICE'].accelD;\n                if (motion[index] === true) {\n                    return script.callReturn();\n                } else {\n                    return this.die();\n                }\n            }\n        },\n        nemo_block_input_bool_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.input_bool_button_state,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_button',\n                    },\n                    {\n                        type: 'nemo_dropdown_button_state_question',\n                    },\n                ],\n                type: 'nemo_block_input_bool_button_state',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                STATE: 1,\n            },\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const state = script.getNumberValue('STATE');\n                const getState = Entry.hw.portData['NEMO_DEVICE_EX'].button[index].state[state];\n                return getState;\n            }\n        },\n        nemo_block_input_bool_motion_sensing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.input_bool_motion_sensing,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_motion',\n                    },\n                ],\n                type: 'nemo_block_input_bool_motion_sensing',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const motion = Entry.hw.portData['NEMO_DEVICE'].accelD;\n                return motion[index];\n            }\n        },\n        nemo_block_input_bool_led_state_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.input_bool_led_state_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                ],\n                type: 'nemo_block_input_bool_led_state_value',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n            },\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const x = script.getNumberValue('X');\n                const y = script.getNumberValue('Y');\n                const index = x * 7 + y + 1;\n\n                Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                    id: Math.random(),\n                    index: 10,\n                    readLED: {                        \n                        index: index\n                    },\n                };\n                Entry.hw.update();\n\n                const led = Entry.hw.portData['NEMO_DEVICE'].ledRead;\n                return led.state;\n            }\n        },\n        nemo_block_input_field_button_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.input_field_button_analog_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_button',\n                    },\n                ],\n                type: 'nemo_block_input_field_button_analog_value',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const button = Entry.hw.portData['NEMO_DEVICE'].anSwitch;\n                return button[index];\n            }\n        },\n        nemo_block_input_field_acceleration_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.input_field_acceleration_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_coordinate_acceleration',\n                    },\n                ],\n                type: 'nemo_block_input_field_acceleration_value',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const accel = Entry.hw.portData['NEMO_DEVICE'].accelA;\n                return accel[index];\n            }\n        },\n        nemo_block_input_field_brightness_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.input_field_brightness_value,\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'nemo_block_input_field_brightness_value',\n            },\n            paramsKeyMap: {},\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const illuminance = Entry.hw.portData['NEMO_DEVICE'].illumi;\n                return illuminance;\n            }\n        },\n        nemo_block_input_field_convert_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.input_field_convert_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                ],\n                type: 'nemo_block_input_field_convert_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                IN_MIN: 1,\n                IN_MAX: 2,\n                OUT_MIN: 3,\n                OUT_MAX: 4,\n            },\n            class: 'inputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const value = script.getNumberValue('VALUE');\n                const inMin = script.getNumberValue('IN_MIN');\n                const inMax = script.getNumberValue('IN_MAX');\n                const outMin = script.getNumberValue('OUT_MIN');\n                const outMax = script.getNumberValue('OUT_MAX');\n                let result = Math.round(((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin);\n                if (result < outMin) {\n                    result = outMin;\n                } else if (result > outMax) {\n                    result = outMax;\n                }\n                return result;\n            }\n        },\n        ///========================================================================================\n        /// Output block\n        ///========================================================================================\n        nemo_title_namo_output: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            template: Lang.template.title_namo_output,\n            skeletonOptions: {\n                box: {\n                    offsetX: 20,\n                },\n            },\n            def: {\n                type: 'nemo_title_namo_output',\n              },\n            isNotFor: ['nemo'],\n            class : 'outputBlock',\n        },\n        nemo_block_output_basic_display_led_icon: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_display_led_icon,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_led_icon',\n                    },\n                    {\n                        type: 'nemo_dropdown_index_0_5',\n                    },\n                    null,\n                ],\n                type: 'nemo_block_output_basic_display_led_icon',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPEED: 1,\n            },\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    const index = script.getNumberValue('INDEX');\n                    const speed = script.getNumberValue('SPEED');\n                    const time = Entry.nemo.numToMS(speed);\n                    Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                        id: Math.random(),\n                        index: 0,\n                        iconLED: {\n                            index: index,\n                            time: time,\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        nemo_block_output_basic_diplay_led_custom_icon: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_diplay_led_custom_icon,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_index_1_7',\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'nemo_dropdown_index_0_5',\n                    },\n                    null,\n                ],\n                type: 'nemo_block_output_basic_diplay_led_custom_icon',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n                VALUE3: 3,\n                VALUE4: 4,\n                VALUE5: 5,\n                VALUE6: 6,\n                VALUE7: 7,\n                SPEED: 8,\n            },\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    const index = script.getNumberValue('INDEX');\n                    const value1 = script.getNumberValue('VALUE1');\n                    const value2 = script.getNumberValue('VALUE2');\n                    const value3 = script.getNumberValue('VALUE3');\n                    const value4 = script.getNumberValue('VALUE4');\n                    const value5 = script.getNumberValue('VALUE5');\n                    const value6 = script.getNumberValue('VALUE6');\n                    const value7 = script.getNumberValue('VALUE7');\n                    const speed = script.getNumberValue('SPEED');\n                    const time = Entry.nemo.numToMS(speed);\n                    Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                        id: Math.random(),\n                        index: 1,\n                        customLED: {\n                            icon: index,\n                            value: [value1, value2, value3, value4, value5, value6, value7],\n                            time: time,\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        nemo_block_output_basic_display_led_string: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_display_led_string,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: [ 'Hello' ],\n                    },\n                    {\n                        type: 'nemo_dropdown_index_1_5',\n                    },\n                    null,\n                ],\n                type: 'nemo_block_output_basic_display_led_string',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                SPEED: 1,\n            },\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    const text = script.getValue('TEXT');\n                    const speed = script.getNumberValue('SPEED');\n                    const time = Entry.nemo.numToMS(speed);    \n                    Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                        id: Math.random(),\n                        index: 2,\n                        textLED: {\n                            text: text,\n                            time: time,\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        nemo_block_output_basic_delete_all_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_delete_all_led,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'nemo_block_output_basic_delete_all_led',\n            },\n            paramsKeyMap: {},\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                    id: Math.random(),\n                    index: 3,\n                    deleteLED: {\n                        value: true,\n                    },\n                };\n                \n                return script.callReturn();\n            }\n        },\n        nemo_block_output_basic_coordinate_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_coordinate_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'nemo_dropdown_switch',\n                    },\n                    null,\n                ],\n                type: 'nemo_block_output_basic_coordinate_value',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                STATE: 2,\n            },\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    const x = script.getNumberValue('X');\n                    const y = script.getNumberValue('Y');\n                    const index = x * 7 + y + 1;\n                    const state = script.getNumberValue('STATE');    \n                    Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                        id: Math.random(),\n                        index: 4,\n                        coordinateLED: {\n                            index: index,\n                            state: state,\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        nemo_block_output_basic_play_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_play_melody,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_melody',\n                    },\n                    null,\n                ],\n                type: 'nemo_block_output_basic_play_melody',\n            },\n            paramsKeyMap: {\n                TITLE: 0,\n            },\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const title = script.getNumberValue('TITLE');\n                \n                Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                    id: Math.random(),\n                    index: 5,\n                    playMelody: {\n                        title: title,\n                    },\n                };\n                \n                return script.callReturn();\n            }\n        },\n        nemo_block_output_basic_play_melody_to_the_end: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_play_melody_to_the_end,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_melody',\n                    },\n                    null,\n                ],\n                type: 'nemo_block_output_basic_play_melody_to_the_end',\n            },\n            paramsKeyMap: {\n                TITLE: 0,\n            },\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const title = script.getNumberValue('TITLE');\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                        id: Math.random(),\n                        index: 6,\n                        playMelody: {\n                            title: title,\n                        },\n                    };\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    const finished = Entry.hw.portData['NEMO_DEVICE_EX'].timeCheck[1];\n                    if (finished.state) {\n                        script.timeFlag = 2;\n                    }\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            }\n        },\n        nemo_block_output_basic_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_play_note,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_keyboard',\n                    },\n                    null,\n                ],\n                type: 'nemo_block_output_basic_play_note',\n            },\n            paramsKeyMap: {\n                PITCH: 0,\n            },\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    const pitch = script.getNumberValue('PITCH');                    \n                    Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                        id: Math.random(),\n                        index: 7,\n                        playNote: {\n                            pitch: pitch\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        nemo_block_output_basic_play_note_for_seconds: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_play_note_for_seconds,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_keyboard',\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'nemo_block_output_basic_play_note_for_seconds',\n            },\n            paramsKeyMap: {\n                PITCH: 0,\n                TIME: 1,\n            },\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const pitch = script.getNumberValue('PITCH');\n                const time = script.getNumberValue('TIME');\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const fps = Entry.FPS || 60;\n                    const timeValue = (60 / fps) * time * 1000;\n                    Entry.TimeWaitManager.add(\n                        Math.random(),\n                        () => {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                \n                    Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                        id: Math.random(),\n                        index: 7,\n                        playNote: {\n                            pitch: pitch\n                        },\n                    };\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();     \n                }\n            }\n        },\n        nemo_block_output_basic_stop_all_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.output_basic_stop_all_sound,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'nemo_block_output_basic_stop_all_sound',\n            },\n            paramsKeyMap: {},\n            class: 'outputBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    Entry.hw.sendQueue['NEMO_OUTPUT'] = {\n                        id: Math.random(),\n                        index: 9,\n                        playNote: {\n                            pitch: -1,\n                        },\n                        playMelody: {\n                            title: 0,\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        ///========================================================================================\n        /// Extension block\n        ///========================================================================================  \n        nemo_title_namo_extension: {\n            skeleton: 'basic_text',\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            template: Lang.template.title_namo_extension,\n            skeletonOptions: {\n                box: {\n                    offsetX: 20,\n                },\n            },\n            def: {\n                type: 'nemo_title_namo_extension',\n              },\n            isNotFor: ['nemo'],\n            class : 'extensionBlock',\n        },\n        nemo_block_extension_basic_set_expension: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.extension_basic_set_expension,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_expension_sensor_mode',\n                    },\n                    null,\n                ],\n                type: 'nemo_block_extension_basic_set_expension',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    const type = script.getNumberValue('TYPE');   \n                    const sensorIndex = type <= 2 ? type + 1 : type + 2;\n                    Entry.hw.sendQueue['NEMO_EXTENSION'] = {\n                        id: Math.random(),\n                        index: 0,\n                        setExpansion: {\n                            type: sensorIndex,\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        nemo_block_extension_basic_set_expension_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.extension_basic_set_expension_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'nemo_block_extension_basic_set_expension_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    const value = script.getNumberValue('VALUE');\n                    Entry.hw.sendQueue['NEMO_EXTENSION'] = {\n                        id: Math.random(),\n                        index: 1,\n                        setExpansionValue: {\n                            value: value,\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        nemo_block_extension_bool_expension_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.extension_bool_expension_state,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_button_state_question',\n                    },\n                    null\n                ],\n                type: 'nemo_block_extension_bool_expension_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const state = script.getNumberValue('STATE') + 4;\n                const exPort = Entry.hw.portData['NEMO_DEVICE_EX'].exPort;\n                return exPort.state[state];\n            }\n        },\n        nemo_block_extension_field_expension_anlog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.extension_field_expension_anlog_value,\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'nemo_block_extension_field_expension_anlog_value',\n            },\n            paramsKeyMap: {},\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const value = Entry.hw.portData['NEMO_DEVICE'].exPort;\n                return value;\n            }\n        },\n        nemo_block_extension_field_expension_custom_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.extension_field_expension_custom_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_compass_sensor_mode',\n                    },\n                ],\n                type: 'nemo_block_extension_field_expension_custom_value',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const type = script.getNumberValue('TYPE');\n                const exPort = Entry.hw.portData['NEMO_DEVICE_EX'].exPort;\n                return exPort.state[type];\n            }\n        },        \n        nemo_block_extension_basic_set_compass_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.extension_basic_set_compass_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'nemo_block_extension_basic_set_compass_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() {\n                    const value = script.getNumberValue('VALUE');    \n                    Entry.hw.sendQueue['NEMO_EXTENSION'] = {\n                        id: Math.random(),\n                        index: 2,\n                        setCompassValue: {\n                            value: value,\n                        },\n                    };\n                    return false;\n                });\n            }\n        },\n        \n        nemo_block_extension_field_compass_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.extension_field_compass_analog_value,\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'nemo_block_extension_field_compass_analog_value',\n            },\n            paramsKeyMap: {},\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const value = Entry.hw.portData['NEMO_DEVICE'].compass;\n                return value;\n            }\n        },\n        nemo_block_extension_field_compass_custom_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.extension_field_compass_custom_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_compass_sensor_mode',\n                    },\n                ],\n                type: 'nemo_block_extension_field_compass_custom_value',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const type = script.getNumberValue('TYPE');\n                const compass = Entry.hw.portData['NEMO_DEVICE_EX'].compass;\n                return compass.state[type];\n            }\n        },        \n        nemo_block_extension_bool_compass_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.extension_bool_compass_state,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'nemo_dropdown_direction',\n                    },\n                ],\n                type: 'nemo_block_extension_bool_compass_state',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'extensionBlock',\n            isNotFor: ['nemo'],\n            func: function(sprite, script) {\n                const direction = script.getNumberValue('DIRECTION');\n                const compass = Entry.hw.portData['NEMO_DEVICE_EX'].compass;\n                return compass.state[4] === direction ? true : false;\n            }\n        },\n    };\n};\n\nmodule.exports = Entry.nemo;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_alux_technic.js",
    "content": "'use strict';\n\nEntry.ProboTechnic = {\n    id: ['63.2', '63.3'], // 파워: 63.2, 일반: 63.3\n    name: 'ProboTechnic',\n    url: 'https://www.aluxonline.com',\n    imageName: 'ProboConnect.png',\n    blockIndex: 0,\n    title: {\n        ko: '프로보테크닉',\n        en: 'ProboTechnic'\n    },\n    Color: [\n        [13, 37],   // 빨강\n        [38, 62],   // 초록\n        [63, 87],   // 파랑\n        [88, 112],  // 노랑\n        [113, 137], // 검정\n        [138, 162] // 하양\n    ],\n    /**\n     * 48   = 1*3*4*4:    32분음표\n     * 96   = 2*3*4*4:    16분음표\n     * 144  = 3*3*4*4:  점16분음표\n     * 64   = 2*2*4*4:    16분음표 스타카토\n     * 192  = 4*3*4*4:    8분음표\n     * 288  = 6*3*4*4:  점8분음표\n     * 128  = 4*2*4*4:    8분음표 스타카토\n     * 384  = 8*3*4*4:    4분음표\n     * 576  = 12*3*4*4: 점4분음표\n     * 256  = 8*2*4*4:    4분음표 스타카토\n     * 768  = 16*3*4*4:   2분음표\n     * 1152 = 24*3*4*4: 점2분음표\n     * 512  = 16*2*4*4:   2분음표 스타카토\n     * 1536 = 32*3*4*4:   온음표\n     **/\n    Note:{\n        n32\t: 48,\n        n16\t: 96,  n16d: 144,   n16t: 64,\n        n8\t: 192, n8d\t: 288,  n8t\t: 128,\n        n4\t: 384, n4d\t: 576,  n4t\t: 256,\n        n2\t: 768, n2d\t: 1152, n2t\t: 512,\n        n1\t: 1536\n    },\n\n    RGB_LED:{\n        red :\t    1,\t\t//RED ON\n        red1: \t    2,\t\t//RED 0.05 ON  -> OFF 반복\n        red2: \t    3,\t\t//RED 0.1  ON  -> OFF 반복\n        red3: \t    4,\t\t//RED 0.2  ON  -> OFF 반복\n        red4: \t    5,\t\t//RED 0.5  ON  -> OFF 반복\n        red5: \t    6,\t\t//RED 1    ON  -> OFF 반복\n        _red1: \t    7,\t\t//RED 0.05 OFF -> ON 반복\n        _red2: \t    8,\t\t//RED 0.1  OFF -> ON 반복\n        _red3: \t    9,\t\t//RED 0.2  OFF -> ON 반복\n        _red4: \t    10,\t\t//RED 0.5  OFF -> ON 반복\n        _red5: \t    11,\t\t//RED 1    OFF -> ON 반복\n                    \n        yellow: \t12,\t\t//YELLOW ON\n        yellow1: \t13,\t\t//YELLOW 0.05 ON  -> OFF 반복\n        yellow2: \t14,\t\t//YELLOW 0.1  ON  -> OFF 반복\n        yellow3: \t15,\t\t//YELLOW 0.2  ON  -> OFF 반복\n        yellow4: \t16,\t\t//YELLOW 0.5  ON  -> OFF 반복\n        yellow5: \t17,\t\t//YELLOW 1    ON  -> OFF 반복\n        _yellow1: \t18,\t\t//YELLOW 0.05 OFF -> ON 반복\n        _yellow2: \t19,\t\t//YELLOW 0.1  OFF -> ON 반복\n        _yellow3: \t20,\t\t//YELLOW 0.2  OFF -> ON 반복\n        _yellow4: \t21,\t\t//YELLOW 0.5  OFF -> ON 반복\n        _yellow5: \t22,\t\t//YELLOW 1    OFF -> ON 반복\n                    \n        green :\t    23,\t\t//GREEN ON\n        green1: \t24,\t\t//GREEN 0.05 ON  -> OFF 반복\n        green2: \t25,\t\t//GREEN 0.1  ON  -> OFF 반복\n        green3: \t26,\t\t//GREEN 0.2  ON  -> OFF 반복\n        green4: \t27,\t\t//GREEN 0.5  ON  -> OFF 반복\n        green5: \t28,\t\t//GREEN 1    ON  -> OFF 반복\n        _green1: \t29,\t\t//GREEN 0.05 OFF -> ON 반복\n        _green2: \t30,\t\t//GREEN 0.1  OFF -> ON 반복\n        _green3: \t31,\t\t//GREEN 0.2  OFF -> ON 반복\n        _green4: \t32,\t\t//GREEN 0.5  OFF -> ON 반복\n        _green5: \t33,\t\t//GREEN 1    OFF -> ON 반복\n                    \n        cyan :\t    34,\t\t//CYAN ON\n        cyan1: \t    35,\t\t//CYAN 0.05 ON  -> OFF 반복\n        cyan2: \t    36,\t\t//CYAN 0.1  ON  -> OFF 반복\n        cyan3: \t    37,\t\t//CYAN 0.2  ON  -> OFF 반복\n        cyan4: \t    38,\t\t//CYAN 0.5  ON  -> OFF 반복\n        cyan5: \t    39,\t\t//CYAN 1    ON  -> OFF 반복\n        _cyan1: \t40,\t\t//CYAN 0.05 OFF -> ON 반복\n        _cyan2: \t41,\t\t//CYAN 0.1  OFF -> ON 반복\n        _cyan3: \t42,\t\t//CYAN 0.2  OFF -> ON 반복\n        _cyan4: \t43,\t\t//CYAN 0.5  OFF -> ON 반복\n        _cyan5: \t44,\t\t//CYAN 1    OFF -> ON 반복\n                    \n        blue:\t    45,\t\t//BLUE ON\n        blue1: \t    46,\t\t//BLUE 0.05 ON  -> OFF 반복\n        blue2: \t    47,\t\t//BLUE 0.1  ON  -> OFF 반복\n        blue3: \t    48,\t\t//BLUE 0.2  ON  -> OFF 반복\n        blue4: \t    49,\t\t//BLUE 0.5  ON  -> OFF 반복\n        blue5: \t    50,\t\t//BLUE 1    ON  -> OFF 반복\n        _blue1: \t51,\t\t//BLUE 0.05 OFF -> ON 반복\n        _blue2: \t52,\t\t//BLUE 0.1  OFF -> ON 반복\n        _blue3: \t53,\t\t//BLUE 0.2  OFF -> ON 반복\n        _blue4: \t54,\t\t//BLUE 0.5  OFF -> ON 반복\n        _blue5: \t55,\t\t//BLUE 1    OFF -> ON 반복\n                    \n        magenta: \t56,\t\t//MAGENTA ON\n        magenta1: \t57,\t\t//MAGENTA 0.05 ON  -> OFF 반복\n        magenta2: \t58,\t\t//MAGENTA 0.1  ON  -> OFF 반복\n        magenta3: \t59,\t\t//MAGENTA 0.2  ON  -> OFF 반복\n        magenta4: \t60,\t\t//MAGENTA 0.5  ON  -> OFF 반복\n        magenta5: \t61,\t\t//MAGENTA 1    ON  -> OFF 반복\n        _magenta1: \t62,\t\t//MAGENTA 0.05 OFF -> ON 반복\n        _magenta2: \t63,\t\t//MAGENTA 0.1  OFF -> ON 반복\n        _magenta3: \t64,\t\t//MAGENTA 0.2  OFF -> ON 반복\n        _magenta4: \t65,\t\t//MAGENTA 0.5  OFF -> ON 반복\n        _magenta5: \t66,\t\t//MAGENTA 1    OFF -> ON 반복\n                    \n        white:\t    67,\t\t//WHITE ON\n        white1: \t68,\t\t//WHITE 0.05 ON  -> OFF 반복\n        white2: \t69,\t\t//WHITE 0.1  ON  -> OFF 반복\n        white3: \t70,\t\t//WHITE 0.2  ON  -> OFF 반복\n        white4: \t71,\t\t//WHITE 0.5  ON  -> OFF 반복\n        white5: \t72,\t\t//WHITE 1    ON  -> OFF 반복\n        _white1: \t73,\t\t//WHITE 0.05 OFF -> ON 반복\n        _white2: \t74,\t\t//WHITE 0.1  OFF -> ON 반복\n        _white3: \t75,\t\t//WHITE 0.2  OFF -> ON 반복\n        _white4: \t76,\t\t//WHITE 0.5  OFF -> ON 반복\n        _white5: \t77,\t\t//WHITE 1    OFF -> ON 반복\n                    \n        rgbrnd1:\t78,\t\t//RANDOM 1\n        rgbrnd2:\t79,\t\t//RANDOM 2\n                    \n        red_d:\t\t90,\t//RED \n        yellow_d:\t91,\t//YELLOW \n        green_d:\t92,\t//GREEN\n        cyan_d:\t\t93,\t//CYAN\n        blue_d:\t\t94,\t//BLUE\n        magenta_d:\t95,\t//MAGENTA\n        white_d:\t96,\t//WHITE\n                    \n        rgboff:\t\t100\t//RGB LED OFF\n    },\n\n    Melody: [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748],\n    Melody_S: [0, 35391, 31530, 28090, 26513, 23621, 21044, 18748],\n\n    Track:[\n        [0x451F, 0x3D95, 0x36DD, 0x33C8, 0x2E22, 0x291A, 0x249E], // Start : size 7,\n        [0x228F, 0x249E, 0x291A, 0x2E22, 0x33C8, 0x36DD, 0x3D95, 0x451F], // End : size 8,\n        [0x228F, 0x1B6E, 0x1711, 0x1147 ], // LevelUp : size 4,\n        [0x1147, 0x1711, 0x1B6E, 0x228F ]  // LevelDwon : size 4,\n    ],\n    \n    Infinite_Buff: {\n        AA1: 0, AA2: 0, AA3: 0, AA4: 0\n    },\n    Infinite_Count: {\n        AA1: 0, AA2: 0, AA3: 0, AA4: 0\n    },\n    Infinite_Start: {\n        AA1: 0, AA2: 0, AA3: 0, AA4: 0\n    },\n\n    SenserSet:{\n        AA1: 0, AA2: 0, AA3: 0, AA4: 0\n    },\n\n    InputData: {\n        Analog: {\n            AA1: 0, AA2: 0, AA3: 0, AA4: 0\n        },\n        Digital: {\n            A1: 0, A2: 0, A3: 0, A4: 0,\n            FEA1: 0, FEA2: 0, FEA3: 0, FEA4: 0,\n            REA1: 0, REA2: 0, REA3: 0, REA4: 0,\n            BEA1: 0, BEA2: 0, BEA3: 0, BEA4: 0\n        },\n        Remote: {\n            R_1: 0, R_2: 0, R_3: 0, R_4: 0,\n            R_5: 0, R_6: 0, R_7: 0, R_8: 0,\n            R_L1: 0, R_L2: 0, R_R1: 0, R_R2: 0\n        },\n        EEPROM: {\n            EC: 0,\n            EEPR2: 0, EEPR1: 0\n        },\n        Infinite: {\n            ROTATION_1: 0, ROTATION_2: 0, ROTATION_3: 0, ROTATION_4: 0\n        },\n        Acceler:{\n            AXIS_X1: 0, AXIS_X2: 0, AXIS_X3: 0, AXIS_X4: 0,\n            AXIS_Y1: 0, AXIS_Y2: 0, AXIS_Y3: 0, AXIS_Y4: 0,\n            AXIS_Z1: 0, AXIS_Z2: 0, AXIS_Z3: 0, AXIS_Z4: 0\n        }\n    },\n    RemoteData: {\n        B1: 0, B2: 0, B3: 0, B4: 0,\n        Servo1: 0, Servo2: 0, Servo3: 0, Servo4: 0,\n        DC1: 0, DC2: 0, DC3: 0, DC4: 0,\n        MEL2: 0, MEL1: 0,\n        FND: 100,\n        EEPR4: 0, EEPR3: 0, EEPR2: 0, EEPR1: 0,\n        ASET2: 0, ASET1: 0\n    },\n    EdgeFlag: {\n        FEA1: 0, FEA2: 0, FEA3: 0, FEA4: 0,\n        REA1: 0, REA2: 0, REA3: 0, REA4: 0,\n        BEA1: 0, BEA2: 0, BEA3: 0, BEA4: 0\n    },\n    EEPROM: {\n        EEPROM_Buff: 0,\n        EEPROM_Count: 0\n    },\n\n    setZero: function() {\n        for (let key in this.EdgeFlag) {\n            this.EdgeFlag[key] = 0;\n        }\n        for (let key in this.RemoteData) {\n            Entry.hw.sendQueue[key] = this.RemoteData[key];\n        }\n        for (let key in this.SenserSet) {\n            this.SenserSet[key] = 0;\n        }\n        Entry.hw.update();\n    },\n    afterReceive(pd) {\n        if(Entry.engine.isState('run')) {\n            Entry.engine.fireEvent('event_remote_input');\n            Entry.engine.fireEvent('event_digital_input');\n        }\n    },\n    convertDropdownRemote(value) {\n        switch (value) {\n            case '1':\n            case 'R_1':\n                return 'R_1';\n            case '2':\n            case 'R_2':\n                return 'R_2';\n            case '3':\n            case 'R_3':\n                return 'R_3';\n            case '4':\n            case 'R_4':\n                return 'R_4';\n            case '5':\n            case 'R_5':\n                return 'R_5';\n            case '6':\n            case 'R_6':\n                return 'R_6';\n            case '7':\n            case 'R_7':\n                return 'R_7';\n            case '8':\n            case 'R_8':\n                return 'R_8';\n            case '9':\n            case 'R_L1':\n                return 'R_L1';\n            case '10':\n            case 'R_L2':\n                return 'R_L2';\n            case '11':\n            case 'R_R1':\n                return 'R_R1';\n            case '12':\n            case 'R_R2':\n                return 'R_R2';\n            default:\n                return Lang.template.value_error;\n        }\n    },    \n    convertDropdownDigital(value) {\n        switch (value) {\n            case '1':\n            case 'A1':\n                return 'A1';\n            case '2':\n            case 'A2':\n                return 'A2';\n            case '3':\n            case 'A3':\n                return 'A3';\n            case '4':\n            case 'A4':\n                return 'A4';\n            case '5':\n            case 'FEA1':\n                return 'FEA1';\n            case '6':\n            case 'FEA2':\n                return 'FEA2';\n            case '7':\n            case 'FEA3':\n                return 'FEA3';\n            case '8':\n            case 'FEA4':\n                return 'FEA4';\n            case '9':\n            case 'REA1':\n                return 'REA1';\n            case '10':\n            case 'REA2':\n                return 'REA2';\n            case '11':\n            case 'REA3':\n                return 'REA3';\n            case '12':\n            case 'REA4':\n                return 'REA4';\n            case '13':\n            case 'BEA1':\n                return 'BEA1';\n            case '14':\n            case 'BEA2':\n                return 'BEA2';\n            case '15':\n            case 'BEA3':\n                return 'BEA3';\n            case '16':\n            case 'BEA4':\n                return 'BEA4';\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownAnalog(value) {\n        switch (value) {\n            case '1':\n            case 'AA1':\n                return 'AA1';\n            case '2':\n            case 'AA2':\n                return 'AA2';\n            case '3':\n            case 'AA3':\n                return 'AA3';\n            case '4':\n            case 'AA4':\n                return 'AA4';\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownAxis(value, axis) {\n        switch (value) {\n            case '1':\n            case 'AA1':\n                return \"AXIS_\" + axis + \"1\";\n            case '2':\n            case 'AA2':\n                return \"AXIS_\" + axis + \"2\";\n            case '3':\n            case 'AA3':\n                return \"AXIS_\" + axis + \"3\";\n            case '4':\n            case 'AA4':\n                return \"AXIS_\" + axis + \"4\";\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownSensor1(value) {\n        switch (value) {\n            case '1':\n            case Lang.template.item_switch:\n                return 1;\n            case '2':\n            case Lang.template.item_infrared:\n                return 2;\n            case '3':\n            case Lang.template.item_magnetic:\n                return 3;\n            case '4':\n            case Lang.template.item_rotation:\n                return 4;\n            case '5':\n            case Lang.template.item_color:\n                return 5;\n            case '6':\n            case Lang.template.item_acceleration:\n                return 6;\n            case '7':\n            case Lang.template.item_ultrasonic:\n                return 7;\n            case '8':\n            case Lang.template.item_heart_rate:\n                return 8;\n            case '9':\n            case Lang.template.item_illuminance:\n                return 9;\n            case '10':\n            case Lang.template.item_sound:\n                return 10;\n            case '11':\n            case Lang.template.item_tilt:\n                return 11;\n            case '12':\n            case Lang.template.item_pressure:\n                return 12;\n            case '13':\n            case Lang.template.item_multi_touch:\n                return 13;\n            case '14':\n            case Lang.template.item_compass:\n                return 14;\n            case '15':\n            case Lang.template.item_3acceleration:\n                return 15;        \n            case '16':\n            case Lang.template.item_multi_switch:\n                return 16;\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownSensor2(value) {        \n        switch (value) {\n            case '1':\n            case Lang.template.item_infinite_rotation:\n                return 1;\n            case '2':\n            case Lang.template.item_compass:\n                return 2;\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownKey(value) {\n        switch (value) {\n            case '1':\n            case Lang.template.item_key_1:\n                return 0;\n            case '2':\n            case Lang.template.item_key_2:\n                return 1;\n            case '3':\n            case Lang.template.item_key_3:\n                return 2;\n            case '4':\n            case Lang.template.item_key_4:\n                return 3;\n            case '5':\n            case Lang.template.item_key_5:\n                return 4;\n            case '6':\n            case Lang.template.item_key_6:\n                return 5;\n            case '7':\n            case Lang.template.item_key_7:\n                return 6;\n            case '8':\n            case Lang.template.item_key_8:\n                return 7;\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownOnOff(value) {\n        switch (value) {\n            case '0':\n            case Lang.template.item_off:\n                return 0;\n            case '1':\n            case Lang.template.item_on:\n                return 1;\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownDC(value) {\n        switch (value) {\n            case '1':\n            case 'DC1':\n                return 'DC1';\n            case '2':\n            case 'DC2':\n                return 'DC2';\n            case '3':\n            case 'DC3':\n                return 'DC3';\n            case '4':\n            case 'DC4':\n                return 'DC4';\n            case '5':\n            case 'DC5':\n                return 'DC5';\n            case '6':\n            case 'DC6':\n                return 'DC6';\n            case '7':\n            case 'DC7':\n                return 'DC7';\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownServo(value) {\n        switch (value) {\n            case '1':\n            case 'Servo1':\n                return 'Servo1';\n            case '2':\n            case 'Servo2':\n                return 'Servo2';\n            case '3':\n            case 'Servo3':\n                return 'Servo3';\n            case '4':\n            case 'Servo4':\n                return 'Servo4';\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownPort(value) {\n        switch (value) {\n            case '1':\n            case 'B1':\n                return 'B1';\n            case '2':\n            case 'B2':\n                return 'B2';\n            case '3':\n            case 'B3':\n                return 'B3';\n            case '4':\n            case 'B4':\n                return 'B4';\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownSensorTransfer(value) {\n        switch (value) {\n            case '1':\n            case Lang.template.item_value:\n                return 1;\n            case '2':\n            case Lang.template.item_angle:\n                return 2;\n            case '3':\n            case Lang.template.item_absolute_angle:\n                return 3;\n            case '4':\n            case Lang.template.item_number_of_rotations:\n                return 4;\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownPitch(pitch) {\n        // 배열의 인덱스 1번부터 음표\n        if (typeof(pitch) === 'number') {\n            const index = (pitch % 12) + 1;\n            let value = 0;\n            if (36 <= pitch && pitch <= 47)\n                value = Entry.ProboTechnic.Melody[index];\n            else if (48 <= pitch && pitch <= 59)\n                value = Entry.ProboTechnic.Melody[index] >> 1;\n            else if (60 <= pitch && pitch <= 71)\n                value = Entry.ProboTechnic.Melody[index] >> 2;\n            else if (72 <= pitch && pitch <= 83)\n                value = Entry.ProboTechnic.Melody[index] >> 3;\n            else\n                value = Entry.ProboTechnic.Melody[0];            \n            return value;\n        } else {\n            return Lang.template.value_error;\n        }\n    },\n    convertDropdownNote(value) {        \n        switch (value) {\n            case '1':\n            case Lang.template.item_note_whole:\n                return 'n1';\n            case '2':\n            case Lang.template.item_note_half:\n                return 'n2';\n            case '4':\n            case Lang.template.item_note_quarter:\n                return 'n4';\n            case '8':\n            case Lang.template.item_note_eighth:\n                return 'n8';\n            case '16':\n            case Lang.template.item_note_sixteenth:\n                return 'n16';\n            case '32':\n            case Lang.template.item_note_thirty_second:\n                return 'n32';\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownMelody(value) {\n        switch (value) {\n            case '1':\n            case Lang.template.item_melody_start:\n                return 0;\n            case '2':\n            case Lang.template.item_melody_end: \n                return 1;\n            case '3':\n            case Lang.template.item_melody_level_up: \n                return 2;\n            case '4':\n            case Lang.template.item_melody_level_down:\n                return 3;\n            default:\n                return Lang.template.value_error;\n        }\n    },  \n    convertDropdownColor1(value) {\n        \n        switch (value) {\n            case '1':\n            case Lang.template.item_color_red:\n                return 0;\n            case '2':\n            case Lang.template.item_color_green:\n                return 1;\n            case '3':\n            case Lang.template.item_color_blue:\n                return 2;\n            case '4':\n            case Lang.template.item_color_yellow:\n                return 3;\n            case '5':\n            case Lang.template.item_color_black:\n                return 4;\n            case '6':\n            case Lang.template.item_color_white:\n                return 5;\n            default:\n                return Lang.template.value_error;\n        }\n    },\n    convertDropdownColor2(value) {\n        switch (value) {\n            case '1':\n            case Lang.template.item_color_red:\n                return this.RGB_LED.red;\n            case '2':\n            case Lang.template.item_color_green:\n                return this.RGB_LED.green;\n            case '3':\n            case Lang.template.item_color_blue:\n                return this.RGB_LED.blue;\n            case '4':\n            case Lang.template.item_color_cyan:\n                return this.RGB_LED.cyan;\n            case '5':\n            case Lang.template.item_color_magenta:\n                return this.RGB_LED.magenta;\n            case '6':\n            case Lang.template.item_color_yellow:\n                return this.RGB_LED.yellow;\n            case '7':\n            case Lang.template.item_color_white:\n                return this.RGB_LED.white;\n            default:\n                return Lang.template.value_error;\n        }\n    }\n};\n\nEntry.ProboTechnic.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                value_error: '값 오류',\n                item_switch: '스위치',\n                item_infrared: '적외선',\n                item_magnetic: '자석',\n                item_rotation: '회전',\n                item_color: '컬러',\n                item_acceleration: '가속도',\n                item_ultrasonic: '초음파',\n                item_heart_rate: '심박',\n                item_illuminance: '조도',\n                item_temperature: '온도',\n                item_sound: '소리',\n                item_tilt: '기울기',\n                item_pressure: '압력',\n                item_multi_touch: '멀티키',\n                item_compass: '나침반',\n                item_3acceleration: '3가속',\n                item_multi_switch: '분배기',\n                item_infinite_rotation: '무한회전',\n                item_color_red: '빨간색',\n                item_color_green: '초록색',\n                item_color_blue: '파란색',\n                item_color_cyan: '청녹색',\n                item_color_magenta: '자홍색',\n                item_color_yellow: '노란색',\n                item_color_black: '검정색',\n                item_color_white: '하얀색',\n                item_value: '값',\n                item_angle: '각도',\n                item_absolute_angle: '절대각도',\n                item_number_of_rotations: '회전 수',\n                item_key_1: '키1',\n                item_key_2: '키2',\n                item_key_3: '키3',\n                item_key_4: '키4',\n                item_key_5: '키5',\n                item_key_6: '키6',\n                item_key_7: '키7',\n                item_key_8: '키8',\n                item_all: '모두',\n                item_on: '켜기',\n                item_off: '끄기',\n                item_note_whole: '온',\n                item_note_half: '2분',\n                item_note_quarter: '4분',\n                item_note_eighth: '8분',\n                item_note_sixteenth: '16분',\n                item_note_thirty_second: '32분',\n                item_pitch_do: '도',\n                item_pitch_do_sharp: '도#',\n                item_pitch_re: '레',\n                item_pitch_re_sharp: '레#',\n                item_pitch_mi: '미',\n                item_pitch_fa: '파',\n                item_pitch_fa_sharp: '파#',\n                item_pitch_sol: '솔',\n                item_pitch_sol_sharp: '솔#',\n                item_pitch_ra: '라',\n                item_pitch_ra_sharp: '라#',\n                item_pitch_si: '시',\n                item_melody_start: '시작음',\n                item_melody_end: '종료음',\n                item_melody_level_up: '레벨 업',\n                item_melody_level_down: '레벨 다운',\n\n                technic_remote_event: '%1 리모컨 %2 키를 눌렀을 때',\n                technic_digital_event: '%1 디지털 입력 %2 이(가) 들어왔을 때',\n\n                technic_senser_setting: '입력포트 %1 을(를) %2 센서로 설정 %3',\n\n                technic_remote_input: '리모컨 입력 %1',\n                technic_digital_input: '디지털 입력 %1',\n                technic_analog_input: '아날로그 입력 %1',\n                technic_3axis_acceler_x: '3가속도 %1의 X축',\n                technic_3axis_acceler_y: '3가속도 %1의 Y축',\n                technic_3axis_acceler_z: '3가속도 %1의 Z축',\n                technic_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환',\n                technic_color_input_b: '컬러 센서 %1 이(가) %2 인가?',\n                technic_color_input_r: '컬러 센서 %1 의 색상',\n                technic_infinite_setting: '%1 센서 %2 을 %3 값으로 정하기 %4',\n                technic_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값',\n                technic_infinite_transform_input: '%1 센서 %2 의  %3',\n                technic_multi_sensor: '멀티키 센서 %1의 %2',\n                technic_multi_switch: '분배 스위치 %1의 %2',\n                technic_eeprom_buffset: 'EEPROM %1 주소의 값 호출하기 %2',\n                technic_eeprom_address_value: 'EEPROM 주소의 값',      \n\n                technic_port_output: '출력핀 %1 을(를) %2 %3',\n                technic_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3',\n                technic_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3',\n                technic_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3',\n                technic_melody_note_output: '%1 을(를) %2 음표로 연주하기 %3',\n                technic_melody_sec_output: '%1 을(를) %2 초 동안 연주하기 %3',\n                technic_melody_output: '%1 을(를) 연주하기 %2',\n                technic_value_sec_output: '%1 값을(를) %2 초 동안 연주하기 %3',\n                technic_value_output: '%1 값을(를) 연주하기 %2',\n                technic_melody_track_output: '%1 을(를) %2초 간격으로 재생하기 %3',\n                technic_melody_off: '멜로디 중지 %1',\n                technic_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3',\n                technic_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2',\n                technic_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3',\n                technic_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4',\n                technic_fnd_output: 'FND를 %1 (으)로 설정 %2',\n                technic_fnd_off: 'FND 끄기 %1',\n                technic_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3'\n            }\n        },\n        en: {\n            template: {\n                value_error: 'value Error',\n                item_switch: 'Switch',\n                item_infrared: 'Infrared',\n                item_magnetic: 'Magnetic',\n                item_rotation: 'Rotation',\n                item_color: 'Color',\n                item_acceleration: 'Acceleration',\n                item_ultrasonic: 'Ultrasonic',\n                item_heart_rate: 'Heart Rate',\n                item_illuminance: 'Illuminance',\n                item_temperature: 'Temperature',\n                item_sound: 'Sound',\n                item_tilt: 'Tilt',\n                item_pressure: 'Pressure',\n                item_multi_touch: 'Multi Touch',\n                item_compass: 'Compass',\n                item_3acceleration: '3Acceleration',\n                item_multi_switch: 'Multi Switch',\n                item_infinite_rotation: 'Infinite Rotation',\n                item_color_red: 'Red',\n                item_color_green: 'Green',\n                item_color_blue: 'Blue',\n                item_color_cyan: 'Cyan',\n                item_color_magenta: 'Magenta',\n                item_color_yellow: 'Yellow',\n                item_color_black: 'Black',\n                item_color_white: 'White',\n                item_value: 'Value',\n                item_angle: 'Angle',\n                item_absolute_angle: 'Absolute Angle',\n                item_number_of_rotations: 'Number of Rotations',\n                item_key_1: 'Key1',\n                item_key_2: 'Key2',\n                item_key_3: 'Key3',\n                item_key_4: 'Key4',\n                item_key_5: 'Key5',\n                item_key_6: 'Key6',\n                item_key_7: 'Key7',\n                item_key_8: 'Key8',\n                item_all: 'All',\n                item_on: 'On',\n                item_off: 'Off',\n                item_note_whole: 'Whole',\n                item_note_half: 'Half',\n                item_note_quarter: 'Quarter',\n                item_note_eighth: 'Eighth',\n                item_note_sixteenth: 'Sixteenth',\n                item_note_thirty_second: 'Thirty-Second',\n                item_pitch_do: 'do',\n                item_pitch_do_sharp: 'xdo',\n                item_pitch_re: 're',\n                item_pitch_re_sharp: 'xre',\n                item_pitch_mi: 'mi',\n                item_pitch_fa: 'fa',\n                item_pitch_fa_sharp: 'xfa',\n                item_pitch_sol: 'sol',\n                item_pitch_sol_sharp: 'xsol',\n                item_pitch_ra: 'ra',\n                item_pitch_ra_sharp: 'xra',\n                item_pitch_si: 'si',\n                item_melody_start: 'Start',\n                item_melody_end: 'End',\n                item_melody_level_up: 'Level up',\n                item_melody_level_down: 'Level down',\n\n                technic_remote_event: '%1 When %2 remote control key pressed',\n                technic_digital_event: '%1 When %2 digital pin input',\n\n                technic_senser_setting: 'Set input port %1 to %2 sensor %3',\n\n                technic_remote_input: 'Remote control %1',\n                technic_digital_input: 'Read digital pin %1',\n                technic_analog_input: 'Read analog pin %1',\n                technic_3axis_acceler_x: '3acceleration %1 and X',\n                technic_3axis_acceler_y: '3acceleration %1 and Y',\n                technic_3axis_acceler_z: '3acceleration %1 and Z',\n                technic_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5',\n                technic_color_input_b: 'Is color sensor %1 %2 ?',\n                technic_color_input_r: 'Color of color sensor %1',\n                technic_infinite_setting: 'Set %1 sensor %2 to %3 value %4',\n                technic_infinite_mm_diameter: 'The move distance(in mm) when the %1 sensor %2 is %3 mm in diameter',\n                technic_infinite_transform_input: '%1 rotation sensor %2 to %3',\n                technic_multi_sensor: 'Multi sensor %1 key %2',\n                technic_multi_switch: 'A key number of the multi-switch sensor %1 = %2',\n                technic_eeprom_buffset:'Calling the value of EEPROM %1 address',\n                technic_eeprom_address_value: 'Value of EEPROM address',\n\n                technic_dc_output: 'DC motor %1 velocity %2 %3',\n                technic_servo_output: 'Servo motor %1 position %2 %3',\n                technic_s_dc_output: 'Servo motor %1 speed %2 %3',\n                technic_port_output: 'Set digital pint %1 as %2 %3',\n                technic_melody_note_output: 'Play key %1 for %2 note %3',\n                technic_melody_sec_output: 'Play key %1 for %2 secs %3',\n                technic_melody_output: 'Play key %1 %2',\n                technic_value_sec_output: 'Play value %1 for %2 secs %3',\n                technic_value_output: 'Play value %1 %2',\n                technic_melody_track_output: 'Play sound %1 for %2 secs %3',\n                technic_melody_off: 'Stop tone %1',\n                technic_rgbled_on_output: 'Turn on RGB LED %1 to %2 %3',\n                technic_rgbled_off_output: 'Turn off RGB LED %1 %2',\n                technic_rgbled_dimming_output: 'Dimming RGB LED %1 to %2 %3',\n                technic_rgbled_flashing_output: 'RGB LED %1 Blinking %2 at %3 second intervals %4',\n                technic_fnd_output: 'Set FND to %1 %2',\n                technic_fnd_off: 'Turn off FND %1',\n                technic_eeprom_write: 'Set EEPROM %1 address to %2 %3'\n            }\n        }\n    };\n};\n\nEntry.ProboTechnic.blockMenuBlocks = [\n    'technic_dropdown_remote',\n    'technic_dropdown_digital',\n    'technic_dropdown_analog',\n    'technic_dropdown_sensor_1',\n    'technic_dropdown_sensor_2',\n    'technic_dropdown_color_1',\n    'technic_dropdown_color_2',\n    'technic_dropdown_sensor_transfer',\n    'technic_dropdown_key',\n    'technic_dropdown_dc_1_all',\n    'technic_dropdown_servo_1_4',\n    'technic_dropdown_port_1_4',\n    'technic_dropdown_on_off',\n    'technic_dropdown_velocity',\n    'technic_dropdown_servo_position',\n    'technic_dropdown_note',\n    'technic_dropdown_time_1',\n    'technic_dropdown_time_2',\n    'technic_dropdown_time_3',\n    'technic_dropdown_pitch',\n    'technic_dropdown_melody',\n\n    //event\n    'technic_remote_event',\n    'technic_digital_event',\n\n    //input\n    'technic_senser_setting',\n    'technic_remote_input',\n    'technic_digital_input',\n    'technic_analog_input',\n    //'technic_3axis_acceler_x', // 테크닉 에서 사용하지 않음\n    //'technic_3axis_acceler_y', // 테크닉 에서 사용하지 않음\n    //'technic_3axis_acceler_z', // 테크닉 에서 사용하지 않음\n    'technic_value_mapping',\n    'technic_color_input_b',\n    'technic_color_input_r',\n    'technic_infinite_setting',\n    'technic_infinite_mm_diameter',\n    'technic_infinite_transform_input',\n    //'technic_multi_sensor', // 테크닉 에서 사용하지 않음\n    'technic_multi_switch',\n    'technic_eeprom_buffset',\n    'technic_eeprom_address_value',\n\n    //output\n    'technic_dc_output',\n    'technic_servo_output',\n    //'technic_s_dc_output', // 테크닉 에서 사용하지 않음\n    'technic_port_output',\n    'technic_melody_note_output',\n    'technic_melody_sec_output',\n    'technic_melody_output',\n    'technic_value_sec_output',\n    'technic_value_output',    \n    'technic_melody_track_output',\n    'technic_melody_off',\n    'technic_rgbled_on_output',\n    'technic_rgbled_off_output',\n    'technic_rgbled_flashing_output',\n    'technic_rgbled_dimming_output',\n    //'technic_fnd_output', // 테크닉 에서 사용하지 않음\n    //'technic_fnd_off',    // 테크닉 에서 사용하지 않음\n    // EEPROM\n    'technic_eeprom_write'\n];\n\n// 블록 생성\nEntry.ProboTechnic.getBlocks = function() {\n    return {\n        ///========================================================================================\n        /// Dropdown block\n        ///========================================================================================\n        technic_dropdown_remote: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['R_1', '1'],\n                        ['R_2', '2'],\n                        ['R_3', '3'],\n                        ['R_4', '4'],\n                        ['R_5', '5'],\n                        ['R_6', '6'],\n                        ['R_7', '7'],\n                        ['R_8', '8'],\n                        ['R_L1', '9'],\n                        ['R_L2', '10'],\n                        ['R_R1', '11'],\n                        ['R_R2', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['FEA1', '5'],\n                        ['FEA2', '6'],\n                        ['FEA3', '7'],\n                        ['FEA4', '8'],\n                        ['REA1', '9'],\n                        ['REA2', '10'],\n                        ['REA3', '11'],\n                        ['REA4', '12'],\n                        ['BEA1', '13'],\n                        ['BEA2', '14'],\n                        ['BEA3', '15'],\n                        ['BEA4', '16'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_analog: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['AA1', '1'],\n                        ['AA2', '2'],\n                        ['AA3', '3'],\n                        ['AA4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_sensor_1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_switch, '1'],\n                        [Lang.template.item_infrared, '2'],\n                        [Lang.template.item_magnetic, '3'],\n                        [Lang.template.item_rotation, '4'],\n                        [Lang.template.item_color, '5'],\n                        //[Lang.template.item_acceleration, '6'], // 테크닉 에서 사용하지 않음\n                        [Lang.template.item_ultrasonic, '7'],\n                        [Lang.template.item_heart_rate, '8'],\n                        [Lang.template.item_illuminance, '9'],\n                        [Lang.template.item_sound, '10'],\n                        [Lang.template.item_tilt, '11'],\n                        [Lang.template.item_pressure, '12'],\n                        //[Lang.template.item_multi_touch, '13'], // 테크닉 에서 사용하지 않음\n                        //[Lang.template.item_compass, '14'], // 테크닉 에서 사용하지 않음\n                        //[Lang.template.item_3acceleration, '15'], // 테크닉에서 사용하지 않음\n                        [Lang.template.item_multi_switch, '16'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_sensor_2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_infinite_rotation, '1'],\n                        //[Lang.template.item_compass, '2'], // 테크닉 에서 사용하지 않음\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_color_1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_color_red, '1'],\n                        [Lang.template.item_color_green, '2'],\n                        [Lang.template.item_color_blue, '3'],\n                        [Lang.template.item_color_yellow, '4'],\n                        [Lang.template.item_color_black, '5'],\n                        [Lang.template.item_color_white, '6'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_color_2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_color_red, '1'],\n                        [Lang.template.item_color_green, '2'],\n                        [Lang.template.item_color_blue, '3'],\n                        [Lang.template.item_color_cyan, '4'],\n                        [Lang.template.item_color_magenta, '5'],\n                        [Lang.template.item_color_yellow, '6'],\n                        [Lang.template.item_color_white, '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_sensor_transfer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_value, '1'],\n                        [Lang.template.item_angle, '2'],\n                        [Lang.template.item_absolute_angle, '3'],\n                        [Lang.template.item_number_of_rotations, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_key: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_key_1, '1'],\n                        [Lang.template.item_key_2, '2'],\n                        [Lang.template.item_key_3, '3'],\n                        [Lang.template.item_key_4, '4'],\n                        [Lang.template.item_key_5, '5'],\n                        [Lang.template.item_key_6, '6'],\n                        [Lang.template.item_key_7, '7'],\n                        [Lang.template.item_key_8, '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_dc_1_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 'DC1'],\n                        ['2', 'DC2'],\n                        ['3', 'DC3'],\n                        ['4', 'DC4'],\n                        ['1,2', 'DC5'],\n                        ['3,4', 'DC6'],\n                        [Lang.template.item_all, 'DC7'],\n                    ],\n                    value: 'DC1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_servo_1_4: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 'Servo1'],\n                        ['2', 'Servo2'],\n                        ['3', 'Servo3'],\n                        ['4', 'Servo4'],\n                    ],\n                    value: 'Servo1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_velocity: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['20', '20'],\n                        ['15', '15'],\n                        ['10', '10'],\n                        ['5', '5'],\n                        ['0', '0'],\n                        ['-5', '-5'],\n                        ['-10', '-10'],\n                        ['-15', '-15'],\n                        ['-20', '-20'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_servo_position: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['20', '20'],\n                        ['40', '40'],\n                        ['60', '60'],\n                        ['80', '80'],\n                        ['100', '100'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_port_1_4: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 'B1'],\n                        ['2', 'B2'],\n                        ['3', 'B3'],\n                        ['4', 'B4'],\n                    ],\n                    value: 'B1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },           \n        technic_dropdown_on_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_on, '1'],\n                        [Lang.template.item_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_note_whole, '1'],\n                        [Lang.template.item_note_half, '2'],\n                        [Lang.template.item_note_quarter, '4'],\n                        [Lang.template.item_note_eighth, '8'],\n                        [Lang.template.item_note_sixteenth, '16'],\n                        [Lang.template.item_note_thirty_second, '32'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_time_1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.1', '0.1'],\n                        ['0.3', '0.3'],\n                        ['0.5', '0.5'],\n                        ['0.7', '0.7'],\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '0.5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_time_2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.1', '0.1'],\n                        ['0.3', '0.3'],\n                        ['0.5', '0.5'],\n                        ['0.7', '0.7'],\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_time_3: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.05', '0.05'],\n                        ['0.1', '0.1'],\n                        ['0.2', '0.2'],\n                        ['0.5', '0.5'],\n                        ['1', '1'],\n                    ],\n                    value: '0.5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        technic_dropdown_pitch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'DropdownExtra',\n                    options: [\n                        [Lang.template.item_pitch_do + ' (36)', '36'],\n                        [Lang.template.item_pitch_do_sharp + ' (37)', '37'],\n                        [Lang.template.item_pitch_re + ' (38)', '38'],\n                        [Lang.template.item_pitch_re_sharp + ' (39)', '39'],\n                        [Lang.template.item_pitch_mi + ' (40)', '40'],\n                        [Lang.template.item_pitch_fa + ' (41)', '41'],\n                        [Lang.template.item_pitch_fa_sharp + ' (42)', '42'],\n                        [Lang.template.item_pitch_sol + ' (43)', '43'],\n                        [Lang.template.item_pitch_sol_sharp + ' (44)', '44'],\n                        [Lang.template.item_pitch_ra + ' (45)', '45'],\n                        [Lang.template.item_pitch_ra_sharp + ' (46)', '46'],\n                        [Lang.template.item_pitch_si + ' (47)', '47'],\n\n                        [Lang.template.item_pitch_do + ' (48)', '48'],\n                        [Lang.template.item_pitch_do_sharp + ' (49)', '49'],\n                        [Lang.template.item_pitch_re + ' (50)', '50'],\n                        [Lang.template.item_pitch_re_sharp + ' (51)', '51'],\n                        [Lang.template.item_pitch_mi + ' (52)', '52'],\n                        [Lang.template.item_pitch_fa + ' (53)', '53'],\n                        [Lang.template.item_pitch_fa_sharp + ' (54)', '54'],\n                        [Lang.template.item_pitch_sol + ' (55)', '55'],\n                        [Lang.template.item_pitch_sol_sharp + ' (56)', '56'],\n                        [Lang.template.item_pitch_ra + ' (57)', '57'],\n                        [Lang.template.item_pitch_ra_sharp + ' (58)', '58'],\n                        [Lang.template.item_pitch_si + ' (59)', '59'],\n\n                        [Lang.template.item_pitch_do + ' (60)', '60'],\n                        [Lang.template.item_pitch_do_sharp + ' (61)', '61'],\n                        [Lang.template.item_pitch_re + ' (62)', '62'],\n                        [Lang.template.item_pitch_re_sharp + ' (63)', '63'],\n                        [Lang.template.item_pitch_mi + ' (64)', '64'],\n                        [Lang.template.item_pitch_fa + ' (65)', '65'],\n                        [Lang.template.item_pitch_fa_sharp + ' (66)', '66'],\n                        [Lang.template.item_pitch_sol + ' (67)', '67'],\n                        [Lang.template.item_pitch_sol_sharp + ' (68)', '68'],\n                        [Lang.template.item_pitch_ra + ' (69)', '69'],\n                        [Lang.template.item_pitch_ra_sharp + ' (70)', '70'],\n                        [Lang.template.item_pitch_si + ' (71)', '71'],\n\n                        [Lang.template.item_pitch_do + ' (72)', '72'],\n                        [Lang.template.item_pitch_do_sharp + ' (73)', '73'],\n                        [Lang.template.item_pitch_re + ' (74)', '74'],\n                        [Lang.template.item_pitch_re_sharp + ' (75)', '75'],\n                        [Lang.template.item_pitch_mi + ' (76)', '76'],\n                        [Lang.template.item_pitch_fa + ' (77)', '77'],\n                        [Lang.template.item_pitch_fa_sharp + ' (78)', '78'],\n                        [Lang.template.item_pitch_sol + ' (79)', '79'],\n                        [Lang.template.item_pitch_sol_sharp + ' (80)', '80'],\n                        [Lang.template.item_pitch_ra + ' (81)', '81'],\n                        [Lang.template.item_pitch_ra_sharp + ' (82)', '82'],\n                        [Lang.template.item_pitch_si + ' (83)', '83'],\n                    ],\n                    value: '60',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                const value = script.getField('PARAM0');\n                return value;\n            }\n        },\n        technic_dropdown_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.item_melody_start, '1'],\n                        [Lang.template.item_melody_end, '2'],\n                        [Lang.template.item_melody_level_up, '3'],\n                        [Lang.template.item_melody_level_down, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('PARAM0');\n            }\n        },\n        ///========================================================================================\n        /// Event block\n        ///========================================================================================\n        // 리모컨 R_1 키를 눌렀을 때\n        technic_remote_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'technic_dropdown_remote',\n                    },\n                ],\n                type: 'technic_remote_event',\n            },\n            paramsKeyMap: {\n                PARAM1: 1,\n            },\n            class: 'event',\n            isNotFor: ['ProboTechnic'],\n            event: 'event_remote_input',\n            func(sprite, script) {\n                const btn = Entry.ProboTechnic.convertDropdownRemote(\n                    script.getStringValue('PARAM1')\n                );\n                if (Entry.hw.portData.InputData.Remote[btn] == 1 ) {\n                    return script.callReturn();\n                }\n                return this.die();\n            },\n        },        \n        // 디지털 입력 A1 이(가) 들어왔을 때\n        technic_digital_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'technic_dropdown_digital',\n                    },\n                ],\n                type: 'technic_digital_event',\n            },\n            paramsKeyMap: {\n                PARAM1: 1,\n            },\n            class: 'event',\n            isNotFor: ['ProboTechnic'],\n            event: 'event_digital_input',\n            func(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownDigital(\n                    script.getStringValue('PARAM1')\n                );\n                switch(port) {\n                    case 'FEA1':\n                    case 'FEA2':\n                    case 'FEA3':\n                    case 'FEA4':\n                    case 'REA1':\n                    case 'REA2':\n                    case 'REA3':\n                    case 'REA4':\n                    case 'BEA1':\n                    case 'BEA2':\n                    case 'BEA3':\n                    case 'BEA4':\n                        if (Entry.hw.portData.InputData.Digital[port] == 1) {\n                            if (Entry.ProboTechnic.EdgeFlag[port] == 0) {\n                                Entry.ProboTechnic.EdgeFlag[port] = 1;\n                                return script.callReturn();\n                            }\n                        } else {\n                            Entry.ProboTechnic.EdgeFlag[port] = 0;\n                        }\n                        break;\n                    default:\n                        if (Entry.hw.portData.InputData.Digital[port] == 1 ) {\n                            return script.callReturn();\n                        }\n                        break;\n                }\n\n                return this.die();\n            },\n        },\n        ///========================================================================================\n        /// Input block\n        ///========================================================================================\n        // 입력포트 AA1 을(를) 스위치 센서로 설정\n        technic_senser_setting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                    {\n                        type: 'technic_dropdown_sensor_1',\n                    },\n                    null,\n                ],\n                type: 'technic_senser_setting',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'setting',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const port = Entry.ProboTechnic.convertDropdownAnalog(\n                        script.getStringValue('PARAM0')\n                    );\n                    const sensor = Entry.ProboTechnic.convertDropdownSensor1(\n                        script.getStringValue('PARAM1')\n                    );\n                    let index = 0;\n                    switch (port) {\n                        case 'AA1':\n                            index = 0;\n                            break;\n                        case 'AA2':\n                            index = 1;\n                            break;\n                        case 'AA3':\n                            index = 2;\n                            break;\n                        case 'AA4':\n                            index = 3;\n                            break;\n                    }\n\n                    let Aset = [0, 0, 0, 0];\n                    let value = [0, 0, 0, 0];\n\n                    Aset[index] = sensor;\n                    for (let i = 0; i < 4; i++) {\n                        switch (Aset[i]) {\n                            case 1: // 스위치\n                            case 2: // 적외선\n                            case 3: // 자석\n                            case 16: // 분배기\n                                value[i] = 1;\n                                break;\n                            case 4: // 회전\n                            case 9: // 조도\n                            case 7: // 초음파\n                                value[i] = 2;\n                                break;\n                            case 10: // 소리\n                                value[i] = 3;\n                                break;                                \n                            case 11: // 기울기\n                                value[i] = 4;\n                                break;\n                            case 12: // 압력\n                                value[i] = 5;\n                                break;\n                            case 8: // 심박\n                                value[i] = 6;\n                                break;\n                            case 5: // 컬러\n                                value[i] = 7;\n                                break;\n                            case 6: // 가속도\n                                value[i] = 8;\n                                break;\n                            case 14: // 나침반\n                            case 15: // 3가속\n                                value[i] = 9;\n                                break;\n                            case 13: // 멀티터치(멀티키)\n                                value[i] = 11;\n                                break;\n                        }\n                    }\n\n                    Entry.ProboTechnic.SenserSet.AA1 = value[0];\n                    Entry.ProboTechnic.SenserSet.AA2 = value[1];\n                    Entry.ProboTechnic.SenserSet.AA3 = value[2];\n                    Entry.ProboTechnic.SenserSet.AA4 = value[3];\n\n                    Entry.hw.sendQueue['ASET2'] = (value[0] << 4) | value[1];\n                    Entry.hw.sendQueue['ASET1'] = (value[2] << 4) | value[3];\n\n                    let fps = Entry.FPS || 60;\n                    let timeValue = 60 / fps * 200; // 0.2초\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n\n            },\n        },\n        // 리모컨 입력 R_1\n        technic_remote_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_remote',\n                    },\n                ],\n                type: 'technic_remote_input',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const btn = Entry.ProboTechnic.convertDropdownRemote(\n                    script.getStringValue('PARAM0')\n                );\n                return Entry.hw.portData.InputData.Remote[btn] == 1 ? true : false;\n            },\n        },\n        // 디지털 입력 A1\n        technic_digital_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_digital',\n                    },\n                ],\n                type: 'technic_digital_input',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownDigital(\n                    script.getStringValue('PARAM0')\n                );                \n                let rt = false;\n                switch(port) {\n                    case 'FEA1':\n                    case 'FEA2':\n                    case 'FEA3':\n                    case 'FEA4':\n                    case 'REA1':\n                    case 'REA2':\n                    case 'REA3':\n                    case 'REA4':\n                    case 'BEA1':\n                    case 'BEA2':\n                    case 'BEA3':\n                    case 'BEA4':\n                        if (Entry.hw.portData.InputData.Digital[port] == 1) {\n                            if (Entry.ProboTechnic.EdgeFlag[port] == 0) {\n                                Entry.ProboTechnic.EdgeFlag[port] = 1;\n                                rt = true;\n                            }\n                        } else {\n                            Entry.ProboTechnic.EdgeFlag[port] = 0;\n                        }\n                        break;\n                    default:\n                        rt = Entry.hw.portData.InputData.Digital[port] == 1 ? true : false;\n                        break;\n                }\n                return rt;\n            },\n        },\n        // 아날로그 입력 AA1\n        technic_analog_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                ],\n                type: 'technic_analog_input',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                let value = Entry.ProboTechnic.SenserSet[port] == 5\n                    ? 255 - Entry.hw.portData.InputData.Analog[port]\n                    : Entry.hw.portData.InputData.Analog[port];\n                return value;\n            },\n        },\n        // 3가속도 AA1 의 X축\n        technic_3axis_acceler_x: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                ],\n                type: 'technic_3axis_acceler_x',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const axis = Entry.ProboTechnic.convertDropdownAxis(\n                    script.getStringValue('PARAM0'),\n                    \"X\"\n                );\n                let value = (Entry.hw.portData.InputData.Acceler[axis]);\n                if (value & 0x80) {\n                    value = (value - 255);\n                }\n                return Number(value / 10).toFixed(1);\n            },\n        },\n        // 3가속도 AA1의 Y축\n        technic_3axis_acceler_y: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                ],\n                type: 'technic_3axis_acceler_y',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const axis = Entry.ProboTechnic.convertDropdownAxis(\n                    script.getStringValue('PARAM0'),\n                    \"Y\"\n                );\n                let value = (Entry.hw.portData.InputData.Acceler[axis]);\n                if (value & 0x80) {\n                    value = (value - 255);\n                }\n                return Number(value / 10).toFixed(1);\n            },\n        },\n        // 3가속도 AA1 의 Z축\n        technic_3axis_acceler_z: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                ],\n                type: 'technic_3axis_acceler_z',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const axis = Entry.ProboTechnic.convertDropdownAxis(\n                    script.getStringValue('PARAM0'),\n                    \"Z\"\n                );\n                let value = (Entry.hw.portData.InputData.Acceler[axis]);\n                if (value & 0x80) {\n                    value = (value - 255);\n                }\n                return Number(value / 10).toFixed(1);\n            },\n        },\n        // AA1의 0 ~ 255 값을 0 ~ 100 (으)로 변환\n        technic_value_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 255 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    {\n                        type: 'number',\n                        params: [ 100 ],\n                    },\n                ],\n                type: 'technic_value_mapping',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n                PARAM2: 2,\n                PARAM3: 3,\n                PARAM4: 4,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const source1 = script.getNumberValue('PARAM1');\n                const source2 = script.getNumberValue('PARAM2');\n                const target1 = script.getNumberValue('PARAM3');\n                const target2 = script.getNumberValue('PARAM4');\n\n                // Port 라는 key값을 가진 정보를 읽는다.\n                let data = 0;\n                if (Entry.ProboTechnic.SenserSet[port] == 5) {\n                    data = 255 - Entry.hw.portData.InputData.Analog[port];\n                } else {\n                    data = Entry.hw.portData.InputData.Analog[port];\n                }\n                let value = 0;\n                let rate = (data - source1) / (source2 - source1);\n                let num = 0;\n\n                if (target1 < target2) {\n                    value = (target2 - target1) * rate;\n                    num = value % 1;\n                    if (num < 0.5) {\n                        value -= num;\n                    }\n                    else {\n                        value += 1 - num;\n                    }\n                    value = target1 + value;\n                    if (value < target1) {\n                        value = target1;\n                    } else if (value > target2) {\n                        value = target2;\n                    }\n                } else {\n                    value = (target1 - target2) * rate;\n                    num = value % 1;\n                    if (num < 0.5) {\n                        value -= num;\n                    } else {\n                        value += 1 - num;\n                    }\n                    value = target1 - value;\n                    if (value > target1) {\n                        value = target1;\n                    } else if (value < target2) {\n                        value = target2;\n                    }\n                }\n                return value;\n            },\n        },\n        // 컬러센서 AA1 이(가) 빨간색 색인가?\n        technic_color_input_b: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                    {\n                        type: 'technic_dropdown_color_1',\n                    },\n                ],\n                type: 'technic_color_input_b',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const target = Entry.ProboTechnic.convertDropdownColor1(\n                    script.getStringValue('PARAM1')\n                );\n                const value = Entry.hw.portData.InputData.Analog[port];\n                const color = Entry.ProboTechnic.Color;\n                return color[target][0] <= value && value <= color[target][1];\n            },\n        },\n        // 컬러센서 AA1 의 색상\n        technic_color_input_r: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            def: {\n                params: [                    \n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                ],\n                type: 'technic_color_input_r',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const value = Entry.hw.portData.InputData.Analog[port];\n                const color = Entry.ProboTechnic.Color;\n                let colorName = '';\n                for (let i = 0; i < 6; i++) {\n                    if (color[i][0] <= value && value <= color[i][1]) {\n                        switch (i) {\n                            case 0:\n                                colorName = Lang.template.item_color_red;\n                                break;\n                            case 1:\n                                colorName = Lang.template.item_color_green;\n                                break;\n                            case 2:\n                                colorName = Lang.template.item_color_blue;\n                                break;\n                            case 3:\n                                colorName = Lang.template.item_color_yellow;\n                                break;\n                            case 4:\n                                colorName = Lang.template.item_color_black;\n                                break;\n                            case 5:\n                                colorName = Lang.template.item_color_white;\n                                break;\n                        }\n                    }\n                }\n                return colorName;\n            },\n        },\n        // 무한회전 센서 AA1 을 0 값으로 정하기\n        technic_infinite_setting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_sensor_2',\n                    },\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    null\n                ],\n                type: 'technic_infinite_setting',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n                PARAM2: 2,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM1')\n                );\n                let value = script.getNumberValue('PARAM2');\n                let count = 0;\n                \n                if (value != 0) {\n                    count = Number(value / 255).toFixed(0);\n                    value = value % 255;\n                } else {\n                    value = 0;\n                    count = 0;\n                }\n                \n                Entry.ProboTechnic.Infinite_Buff[port] = Entry.hw.portData.InputData.Analog[port];\n                Entry.ProboTechnic.Infinite_Start[port] = Entry.hw.portData.InputData.Analog[port]-value;\n                Entry.ProboTechnic.Infinite_Count[port] = count;\n\n                return script.callReturn();\n            },\n        },\n        // 무한회전 센서 AA1 지름 53.5 의 mm 값\n        technic_infinite_mm_diameter: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_sensor_2',\n                    },\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                    {\n                        type: 'number',\n                        params: [ 53.5 ],\n                    },\n                ],\n                type: 'technic_infinite_mm_diameter',\n            },\n            paramsKeyMap: {\n                PARAM1: 1,\n                PARAM2: 2,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM1')\n                );\n                const diameter = script.getNumberValue('PARAM2');\n                let value = Entry.hw.portData.InputData.Analog[port];\n\n                if (value < Entry.ProboTechnic.Infinite_Buff[port] - 150) {\n\n                    Entry.ProboTechnic.Infinite_Count[port]++;\n                } else if (value > Entry.ProboTechnic.Infinite_Buff[port] + 150) {\n                    Entry.ProboTechnic.Infinite_Count[port]--;\n                }                    \n                Entry.ProboTechnic.Infinite_Buff[port] = value;\n                value = (Entry.ProboTechnic.Infinite_Buff[port] - Entry.ProboTechnic.Infinite_Start[port]) + (Entry.ProboTechnic.Infinite_Count[port] * 255);\n\n                return Number(\n                    2 *\n                    3.141592 *\n                    (diameter / 2) /\n                    255 *\n                    value\n                ).toFixed(3);\n            },\n        },\n        // 무한회전 센서 AA1 의 값\n        technic_infinite_transform_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [                    \n                    {\n                        type: 'technic_dropdown_sensor_2',\n                    },\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                    {\n                        type: 'technic_dropdown_sensor_transfer',\n                    },\n                ],\n                type: 'technic_infinite_transform_input',\n            },\n            paramsKeyMap: {\n                PARAM1: 1,\n                PARAM2: 2,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM1')\n                );\n                const select = Entry.ProboTechnic.convertDropdownSensorTransfer(\n                    script.getStringValue('PARAM2')\n                );\n                let value = Entry.hw.portData.InputData.Analog[port];\n\n                if (value < (Entry.ProboTechnic.Infinite_Buff[port] - 150)) {\n                    Entry.ProboTechnic.Infinite_Count[port]++;\n                } else if (value > (Entry.ProboTechnic.Infinite_Buff[port] + 150)) {\n                    Entry.ProboTechnic.Infinite_Count[port]--;\n                }\n                Entry.ProboTechnic.Infinite_Buff[port] = value;\n                value = (Entry.ProboTechnic.Infinite_Buff[port] - Entry.ProboTechnic.Infinite_Start[port]) + (Entry.ProboTechnic.Infinite_Count[port] * 255);\n\n                switch (select) {\n                    case 2:\n                        if (value > 0) {\n                            return Math.floor((value%255) * 1.41732);\n                        } else {\n                            return Math.ceil((value%255) * 1.41732);\n                        }                            \n                    case 3:\n                        return Number((360/255) * Entry.hw.portData.InputData.Analog[port]).toFixed(0);\n                    case 4:\n                        if (value > 0) {\n                            return Math.floor(value / 255);\n                        } else {\n                            return Math.ceil(value / 255);\n                        }\n                    default:\n                        return value;\n                }\n            },\n        },\n        // 멀티키 센서 AA1 의 키1\n        technic_multi_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                    {\n                        type: 'technic_dropdown_key',\n                    },\n                ],\n                type: 'technic_multi_sensor',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const key = Entry.ProboTechnic.convertDropdownKey(\n                    script.getStringValue('PARAM1')\n                );\n                const value = Entry.hw.portData.InputData.Analog[port] & (0x1 << key)? 1 : 0;\n                return value;\n            },\n        },\n        // 분배스위치 센서 AA1의 키1\n        technic_multi_switch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'technic_dropdown_analog',\n                    },\n                    {\n                        type: 'technic_dropdown_key',\n                    },\n                ],\n                type: 'technic_multi_switch',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownAnalog(\n                    script.getStringValue('PARAM0')\n                );\n                const key = Entry.ProboTechnic.convertDropdownKey(\n                    script.getStringValue('PARAM1')\n                );\n                const analog = Entry.hw.portData.InputData.Analog[port];\n                let  value = -1;\n                if (1 <= analog && analog <= 19) {\n                    value = 0;\n                } else if (26 <= analog && analog <= 44) {\n                    value = 1;\n                } else if (53 <= analog && analog <= 77) {\n                    value = 2;\n                } else if (83 <= analog && analog <= 101) {\n                    value = 3;\n                } else if (107 <= analog && analog <= 125) {\n                    value = 4;\n                } else if (139 <= analog && analog <= 157) {\n                    value = 5;\n                } else if (160 <= analog && analog <= 178) {\n                    value = 6;\n                } else if (191 <= analog && analog <= 209) {\n                    value = 7;\n                }\n                return key === value ? 1 : 0;\n            },\n        },\n        technic_eeprom_buffset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [{ type: 'number', params: ['0'] }, null],\n                type: 'technic_eeprom_buffset',\n            },\n            paramsKeyMap: {\n                ADDRESS: 0,\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const address = script.getNumberValue('ADDRESS', script);\n                if (!script.isStart) {\n                    Entry.ProboTechnic.EEPROM.EEPROM_Count = Entry.hw.portData.InputData.EEPROM.EC;\n                    Entry.hw.sendQueue['EEPR4'] = 0x40;\n                    Entry.hw.sendQueue['EEPR3'] = address;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue = 0.05;\n                    var fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    var blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.ProboTechnic.EEPROM.EEPROM_Buff =\n                        (Entry.hw.portData.InputData.EEPROM.EEPR2 << 8) +\n                        Entry.hw.portData.InputData.EEPROM.EEPR1;\n                    Entry.hw.sendQueue['EEPR4'] = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // EEPROM 주소의 값\n        technic_eeprom_address_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            def: {\n                type: 'technic_eeprom_address_value',\n            },\n            class: 'input',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                var value = 0;\n                const count = Entry.ProboTechnic.EEPROM.EEPROM_Count;\n                if (Entry.hw.portData.InputData.EEPROM.EC != count) {\n                    value = Entry.ProboTechnic.EEPROM.EEPROM_Buff;\n                }\n                return value;\n            },\n        },\n        ///========================================================================================\n        /// output block\n        ///========================================================================================\n        // DC 모터 1을(를) 0 속도로 회전\n        technic_dc_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_dc_1_all',\n                    },\n                    {\n                        type: 'technic_dropdown_velocity',\n                    },\n                    null,\n                ],\n                type: 'technic_dc_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const motor = Entry.ProboTechnic.convertDropdownDC(\n                    script.getStringValue('PARAM0')\n                ); \n                const value = script.getNumberValue('PARAM1');\n                switch (motor) {\n                    case 'DC5':\n                        Entry.hw.sendQueue['DC1'] = value;\n                        Entry.hw.sendQueue['DC2'] = value;\n                        break;\n                    case 'DC6':\n                        Entry.hw.sendQueue['DC3'] = value;\n                        Entry.hw.sendQueue['DC4'] = value;\n                        break;\n                    case 'DC7':\n                        Entry.hw.sendQueue['DC1'] = value;\n                        Entry.hw.sendQueue['DC2'] = value;\n                        Entry.hw.sendQueue['DC3'] = value;\n                        Entry.hw.sendQueue['DC4'] = value;\n                        break;\n                    default:\n                        Entry.hw.sendQueue[motor] = value;\n                        break;\n                }\n                return script.callReturn();\n            },\n        },\n        // 서보모터 1 의 위치를 1 로 이동 \n        technic_servo_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_servo_1_4',\n                    },\n                    {\n                        type: 'technic_dropdown_servo_position',\n                    },\n                    null,\n                ],\n                type: 'technic_servo_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const servo = Entry.ProboTechnic.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                let value = script.getNumberValue('PARAM1');\n                if (value < 1) {\n                    value = 0;\n                } else if (value > 100) {\n                    value = 100;\n                }\n\n                Entry.hw.sendQueue[servo] = value;\n                return script.callReturn();\n            },\n        },\n        // S 모터 1 을(를) 0 속도로 회전\n        technic_s_dc_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_servo_1_4',\n                    },\n                    {\n                        type: 'technic_dropdown_velocity',\n                    },\n                    null,\n                ],\n                type: 'technic_s_dc_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const motor = Entry.ProboTechnic.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                let value = script.getNumberValue('PARAM1');\n\n                if (value > 20) {\n                    value = 20;\n                } else if (value < -20) {\n                    value = -20;\n                }\n                value += 148;\n\n                switch (motor) {\n                    case 'Servo5':\n                        Entry.hw.sendQueue['Servo1'] = value;\n                        Entry.hw.sendQueue['Servo2'] = value;\n                        break;\n                    case 'Servo6':\n                        Entry.hw.sendQueue['Servo3'] = value;\n                        Entry.hw.sendQueue['Servo4'] = value;\n                        break;\n                    default:\n                        Entry.hw.sendQueue[motor] = value;\n                        break;\n                }\n                return script.callReturn();\n            },\n        },\n        // 출력핀 1 을(를) 켜기\n        technic_port_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_port_1_4',\n                    },\n                    {\n                        type: 'technic_dropdown_on_off',\n                    },\n                    null\n                ],\n                type: 'technic_port_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const motor = Entry.ProboTechnic.convertDropdownPort(\n                    script.getStringValue('PARAM0')\n                );\n                const value = Entry.ProboTechnic.convertDropdownOnOff(\n                    script.getStringValue('PARAM1')\n                );\n                Entry.hw.sendQueue[motor] = value;\n                return script.callReturn();\n            },\n        },\n        // 도(60) 을(를) 4분 음표로 연주하기\n        technic_melody_note_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_pitch',\n                    },\n                    {\n                        type: 'technic_dropdown_note',\n                    },\n                    null\n                ],\n                type: 'technic_melody_note_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const pitch = Entry.ProboTechnic.convertDropdownPitch(\n                        script.getNumberValue('PARAM0')\n                    );\n                    const note = Entry.ProboTechnic.convertDropdownNote(\n                        script.getStringValue('PARAM1')\n                    );\n                    \n                    let timeValue = Entry.ProboTechnic.Note[note];\n\n                    Entry.hw.sendQueue['MEL2'] = pitch >> 8;\n                    Entry.hw.sendQueue['MEL1'] = pitch;\n\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue;\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['MEL2'] = 0;\n                    Entry.hw.sendQueue['MEL1'] = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // 도(60) 을(를) 0.5 초 동안 연주하기\n        technic_melody_sec_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_pitch',\n                    },\n                    {\n                        type: 'technic_dropdown_time_1',\n                    },\n                    null\n                ],\n                type: 'technic_melody_sec_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const pitch = Entry.ProboTechnic.convertDropdownPitch(\n                        script.getNumberValue('PARAM0')\n                    );\n                    let timeValue = script.getNumberValue('PARAM1');\n                   \n                    Entry.hw.sendQueue['MEL2'] = pitch >> 8;\n                    Entry.hw.sendQueue['MEL1'] = pitch;\n\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['MEL2'] = 0;\n                    Entry.hw.sendQueue['MEL1'] = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // 도(60) 을(를) 연주하기\n        technic_melody_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_pitch',\n                    },\n                    null\n                ],\n                type: 'technic_melody_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const pitch = Entry.ProboTechnic.convertDropdownPitch(\n                    script.getNumberValue('PARAM0')\n                );\n\n                Entry.hw.sendQueue['MEL2'] = pitch >> 8;\n                Entry.hw.sendQueue['MEL1'] = pitch;\n                return script.callReturn();\n            },\n        },\n        // 35391 값을 0.5 초 동안 연주하기\n        technic_value_sec_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 35391 ],\n                    },\n                    {\n                        type: 'technic_dropdown_time_1',\n                    },\n                    null\n                ],\n                type: 'technic_value_sec_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    let melody = script.getNumberValue('PARAM0');\n                    let timeValue = script.getNumberValue('PARAM1');\n\n                    Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff;\n                    Entry.hw.sendQueue['MEL1'] = melody & 0xff;\n\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['MEL2'] = 0;\n                    Entry.hw.sendQueue['MEL1'] = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // 35391 값을(를) 연주하기\n        technic_value_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 35391 ],\n                    },\n                    null\n                ],\n                type: 'technic_value_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                let melody = script.getNumberValue('PARAM0');\n                Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff;\n                Entry.hw.sendQueue['MEL1'] = melody & 0xff;\n                return script.callReturn();\n            },\n        },\n        // 시작음 을(를) 1 초 간격으로 재생하기\n        technic_melody_track_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_melody',\n                    },\n                    { \n                        type: 'technic_dropdown_time_2',\n                    },\n                    null\n                ],\n                type: 'technic_melody_track_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                function getTrackStep(track,script){\n                    if(!script.isStart){\n                        script.isStart = true;\n                        script.trackStep = 0;\n                    }\n                    else {\n                        script.trackStep++;\n                    }\n                    let timeValue = script.getNumberValue('PARAM1');\n                    script.timeFlag = 1;\n                    let melody = Entry.ProboTechnic.Track[track][script.trackStep];\n                    Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff;\n                    Entry.hw.sendQueue['MEL1'] = melody & 0xff;\n\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    Entry.TimeWaitManager.add(\n                        script.block.id,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                }\n                const TR = Entry.ProboConnect.convertDropdownMelody(\n                    script.getStringValue('PARAM0')\n                );\n                if (!script.isStart) {\n                    switch(TR) {\n                        case 0 :\n                            script.maxStep = 6;\n                            break;\n                        case 1 :\n                            script.maxStep = 7;\n                            break;\n                        case 2 :\n                            script.maxStep = 3;\n                            break;\n                        case 3 :\n                            script.maxStep = 3;\n                            break;\n                    }\n                    getTrackStep(TR,script);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else if (script.trackStep < script.maxStep){\n                    getTrackStep(TR,script);\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['MEL2'] = 0;\n                    Entry.hw.sendQueue['MEL1'] = 0;\n\n                    delete script.trackStep;\n                    delete script.maxStep;\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // 멜로디 중지\n        technic_melody_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n                type: 'technic_melody_off',\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue['MEL2'] = 0;\n                Entry.hw.sendQueue['MEL1'] = 0;\n                return script.callReturn();\n            },\n        },\n        // RGB LED 1 을(를) 빨간색 으로 켜기\n        technic_rgbled_on_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_servo_1_4',\n                    },\n                    {\n                        type: 'technic_dropdown_color_2',\n                    },\n                    null\n                ],\n                type: 'technic_rgbled_on_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                const color = Entry.ProboTechnic.convertDropdownColor2(\n                    script.getStringValue('PARAM1')\n                );\n                Entry.hw.sendQueue[port] = color;\n                return script.callReturn();\n            },\n        },    \n        // RGB LED 을(를) 끄기    \n        technic_rgbled_off_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_servo_1_4',\n                    },\n                    null\n                ],\n                type: 'technic_rgbled_off_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                Entry.hw.sendQueue[port] = 0;\n            },\n        },\n        // RGB LED 1 빨간색으로 0.5초 간격\n        technic_rgbled_flashing_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_servo_1_4',\n                    },\n                    { \n                        type: 'technic_dropdown_color_2',\n                    },\n                    { \n                        type: 'technic_dropdown_time_3',\n                    },\n                    null\n                ],\n                type: 'technic_rgbled_flashing_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n                PARAM2: 2,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                const color = Entry.ProboTechnic.convertDropdownColor2(\n                    script.getStringValue('PARAM1')\n                );\n                const sec = script.getNumberValue('PARAM2');\n                let value = 0;\n                switch (sec) {\n                    case 0.05:\n                        value = color + 0;\n                        break;\n                    case 0.1:\n                        value = color + 1;\n                        break;\n                    case 0.2:\n                        value = color + 2;\n                        break;                    \n                    case 0.5:\n                        value = color + 3;\n                        break;                        \n                    case 1:\n                        value = color + 4;\n                        break;\n                }\n                Entry.hw.sendQueue[port] = value;\n                return script.callReturn();\n            },\n        },\n        // RGB LED 1을(를) 빨간색으로 디밍\n        technic_rgbled_dimming_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'technic_dropdown_servo_1_4',\n                    },\n                    { \n                        type: 'technic_dropdown_color_2',\n                    },\n                    null\n                ],\n                type: 'technic_rgbled_dimming_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const port = Entry.ProboTechnic.convertDropdownServo(\n                    script.getStringValue('PARAM0')\n                );\n                let color = 0;\n                switch (script.getStringValue('PARAM1')) {\n                    case '1':\n                        color = 90;\n                        break;\n                    case '2':\n                        color = 92;\n                        break;\n                    case '3':\n                        color = 94;\n                        break;\n                    case '4':\n                        color = 93;\n                        break;\n                    case '5':\n                        color = 95;\n                        break;\n                    case '6':\n                        color = 91;\n                        break;\n                    case '7':\n                        color = 96;\n                        break;\n                }\n                Entry.hw.sendQueue[port] = color;\n                return script.callReturn();\n            },\n        },\n        // FND를 0 (으)로 설정\n        technic_fnd_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 0 ],\n                    },\n                    null\n                ],\n                type: 'technic_fnd_output',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const fnd = script.getNumberValue('PARAM0');\n                Entry.hw.sendQueue['FND'] = fnd;\n                return script.callReturn();\n            },\n        },\n        // FND 끄기\n        technic_fnd_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null\n                ],\n                type: 'technic_fnd_off',\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue['FND'] = 100;\n                return script.callReturn();\n            },\n        },\n        // EEPROM 0 주소에 0 값 설정하기\n        technic_eeprom_write: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    { \n                        type: 'number',\n                        params: [ 0 ]\n                    },\n                    {\n                        type: 'number',\n                        params: [ 0 ]\n                    },\n                    null,\n                ],\n                type: 'technic_eeprom_write',\n            },\n            paramsKeyMap: {\n                PARAM0: 0,\n                PARAM1: 1,\n            },\n            class: 'output',\n            isNotFor: ['ProboTechnic'],\n            func: function(sprite, script) {\n                const address = script.getNumberValue('PARAM0');\n                const value = script.getNumberValue('PARAM1');\n                if (!script.isStart) {\n                    Entry.hw.update();\n                    Entry.hw.sendQueue['EEPR4'] = 0x80;\n                    Entry.hw.sendQueue['EEPR3'] = address;\n                    Entry.hw.sendQueue['EEPR2'] = (value >> 8) & 0xff;\n                    Entry.hw.sendQueue['EEPR1'] = value & 0xff;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    let timeValue = 0.05;\n                    let fps = Entry.FPS || 60;\n                    timeValue = 60 / fps * timeValue * 1000;\n\n                    let blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        function() {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.update();\n                    Entry.hw.sendQueue['EEPR4'] = 0x40;\n                    Entry.hw.sendQueue['EEPR3'] = address;\n                    Entry.hw.sendQueue['EEPR2'] = 0;\n                    Entry.hw.sendQueue['EEPR1'] = 0;\n\n                    setTimeout(function() {  \n                        Entry.hw.update();                      \n                        Entry.hw.sendQueue['EEPR4'] = 0;\n                        Entry.hw.sendQueue['EEPR3'] = 0;\n                        Entry.hw.sendQueue['EEPR2'] = 0;\n                        Entry.hw.sendQueue['EEPR1'] = 0;\n                    }, 100);\n                    \n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.ProboTechnic;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_ardublock.js",
    "content": "'use strict';\n\nEntry.ardublock = {\n    id: '1.8',\n    name: 'ardublock',\n    url: 'http://www.jkelec.co.kr/',\n    imageName: 'ardublock.png',\n    title: {\n        ko: '아두블럭',\n        en: 'ardublock',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        MOTOR_LEFT: 9,\n        MOTOR_RIGHT: 10,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    directionTable: {\n        Forward: 0,\n        Backward: 1,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.ardublock.blockMenuBlocks = [\n    'ardublock_get_analog_value',\n    'ardublock_get_analog_value_map',\n    'ardublock_get_ultrasonic_value',\n    'ardublock_get_digital',\n    'ardublock_toggle_led',\n    'ardublock_digital_pwm',\n    'ardublock_set_servo',\n    'ardublock_set_tone',\n    'ardublock_set_left_motor',\n    'ardublock_set_right_motor',\n    'ardublock_get_left_cds_analog_value',\n    'ardublock_get_right_cds_analog_value',\n    'ardublock_toggle_left_led',\n    'ardublock_toggle_right_led',\n    'ardublock_get_sound_analog_value',\n];\n\nEntry.ardublock.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                ardublock_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                ardublock_get_digital_value: '디지털 %1 번 센서값  ',\n                ardublock_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                ardublock_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                ardublock_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                ardublock_get_analog_value: '아날로그 %1 번 센서값',\n                ardublock_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                ardublock_get_digital: '디지털 %1 번 센서값',\n                ardublock_get_left_cds_analog_value: '왼쪽 조도센서 %1 센서값',\n                ardublock_get_right_cds_analog_value: '오른쪽 조도센서 %1 센서값',\n                ardublock_get_sound_analog_value: '사운드(소리) 센서 %1 센서값',\n                ardublock_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n                ardublock_set_left_motor: '왼쪽모터를 %1 으로 %2 회전 속도로 정하기 %3',\n                ardublock_set_right_motor: '오른쪽모터를 %1 으로 %2 회전 속도로 정하기 %3',\n                ardublock_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                ardublock_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                ardublock_toggle_led: '디지털 %1 번 핀 %2 %3',\n                ardublock_toggle_left_led: '왼쪽 라이트 %1 번 핀 %2 %3',\n                ardublock_toggle_right_led: '오른쪽 라이트 %1 번 핀 %2 %3',\n            },\n            Blocks: {\n                ardublock_motor_forward: '앞',\n                ardublock_motor_backward: '뒤',\n            },\n            Menus: {\n                ardublock: '아두블럭',\n            },\n        },\n        en: {\n            template: {\n                ardublock_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                ardublock_get_digital_value: 'Digital %1 Sensor value  ',\n                ardublock_toggle_pwm: 'Digital %1 Pin %2 %3',\n                ardublock_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n                ardublock_digital_pwm: 'Digital %1 Pin %2 %3',\n                ardublock_get_analog_value: 'Analog %1 Sensor value',\n                ardublock_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                ardublock_get_digital: 'Digital %1 Sensor value',\n                ardublock_get_left_cds_analog_value: 'Left CDS %1 Sensor value',\n                ardublock_get_right_cds_analog_value: 'Left CDS  %1 Sensor value',\n                ardublock_get_sound_analog_value: 'Analog Sound %1 Sensor value',\n                ardublock_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                ardublock_set_left_motor: 'Left motor direction to %1 speed %2 set %3',\n                ardublock_set_right_motor: 'Right motor direction to %1 speed %2 set %3',\n                ardublock_set_servo: 'Set servo pin %1 angle as %2 %3',\n                ardublock_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                ardublock_toggle_led: 'Digital %1 Pin %2 %3',\n                ardublock_toggle_left_led: 'Left Light %1 Pin %2 %3',\n                ardublock_toggle_right_led: 'Right Light %1 Pin %2 %3',\n            },\n            Blocks: {\n                ardublock_motor_forward: 'Forward',\n                ardublock_motor_backward: 'Backward',\n            },\n            Menus: {\n                ardublock: 'ardublock',\n            },\n        },\n    };\n};\n\nEntry.ardublock.getBlocks = function() {\n    return {\n        //region ardublock 아두블록\n        ardublock_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_ext_analog_list',\n                    },\n                ],\n                type: 'ardublock_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ardublockGet',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'ardublock_get_analog_value',\n                        params: [\n                            {\n                                type: 'arduino_ext_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'ardublock_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'ardublockGet',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var result = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['13'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['12'],\n                    },\n                ],\n                type: 'ardublock_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'ardublockGet',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.ardublock.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'ardublock_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ardublockGet',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.ardublock.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'ardublock_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ardublock',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.ardublock.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.ardublock.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ardublock.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'ardublock_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ardublock',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ardublock.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'ardublock_tone_list',\n                    },\n                ],\n                type: 'ardublock_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        value: 4,\n                        params: ['11'],\n                    },\n                    {\n                        type: 'ardublock_tone_list',\n                    },\n                    {\n                        type: 'ardublock_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'ardublock_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'ardublock',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) note = Entry.ardublock.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.ardublock.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var value = 0;\n\n                    if (note != 0) {\n                        value = Entry.ardublock.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.ardublock.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.ardublock.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'ardublock_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ardublock',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.ardublock.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_motor_direction_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ardublock_motor_forward, '0'],\n                        [Lang.Blocks.ardublock_motor_backward, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                MOTOR_DIRECTION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('MOTOR_DIRECTION');\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_set_left_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'ardublock_motor_direction_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'ardublock_set_left_motor',\n            },\n            paramsKeyMap: {\n                MOTOR_DIRECTION: 0,\n                MOTOR_SPEED: 1,\n            },\n            class: 'ardublock',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                // var sq = Entry.hw.sendQueue;\n                var direction = script.getValue('MOTOR_DIRECTION', script);\n                if (!Entry.Utils.isNumber(direction))\n                    direction = Entry.ardublock.directionTable[direction];\n\n                if (direction < 0) {\n                    direction = 0;\n                } else if (direction > 1) {\n                    direction = 1;\n                }\n\n                var speed = script.getNumberValue('MOTOR_SPEED', script) - 1;\n                if (speed < 0) {\n                    speed = 0;\n                } else if (speed > 254) {\n                    speed = 254;\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                Entry.hw.sendQueue['SET'][0] = {\n                    type: Entry.ardublock.sensorTypes.MOTOR_LEFT,\n                    data: {\n                        direction: direction,\n                        speed: speed,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                setTimeout(function() {\n                    script.timeFlag = 0;\n                }, 10);\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_set_right_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'ardublock_motor_direction_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'ardublock_set_right_motor',\n            },\n            paramsKeyMap: {\n                MOTOR_DIRECTION: 0,\n                MOTOR_SPEED: 1,\n            },\n            class: 'ardublock',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                // var sq = Entry.hw.sendQueue;\n                var direction = script.getValue('MOTOR_DIRECTION', script);\n                if (!Entry.Utils.isNumber(direction))\n                    direction = Entry.ardublock.directionTable[direction];\n\n                if (direction < 0) {\n                    direction = 0;\n                } else if (direction > 1) {\n                    direction = 1;\n                }\n\n                var speed = script.getNumberValue('MOTOR_SPEED', script) - 1;\n                if (speed < 0) {\n                    speed = 0;\n                } else if (speed > 254) {\n                    speed = 254;\n                }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                Entry.hw.sendQueue['SET'][1] = {\n                    type: Entry.ardublock.sensorTypes.MOTOR_RIGHT,\n                    data: {\n                        direction: direction,\n                        speed: speed,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                setTimeout(function() {\n                    script.timeFlag = 0;\n                }, 10);\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_get_left_cds_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_ext_analog_list',\n                        params: ['0'],\n                    },\n                ],\n                type: 'ardublock_get_left_cds_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ardublockGet',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_get_right_cds_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_ext_analog_list',\n                        params: ['1'],\n                    },\n                ],\n                type: 'ardublock_get_right_cds_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ardublockGet',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_toggle_left_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'ardublock_toggle_left_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ardublock',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.ardublock.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.ardublock.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ardublock.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_toggle_right_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'ardublock_toggle_right_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ardublock',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.ardublock.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.ardublock.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ardublock.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        ardublock_get_sound_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_ext_analog_list',\n                        params: ['2'],\n                    },\n                ],\n                type: 'ardublock_get_sound_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ardublockGet',\n            isNotFor: ['ardublock'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        //endregion ardublock 아두블록\n    };\n};\n\nmodule.exports = Entry.ardublock;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_arduino.js",
    "content": "'use strict';\n\nEntry.Arduino = {\n    id: ['1.1', '4.2', '8.1'],\n    name: 'arduino',\n    url: 'http://www.arduino.cc/',\n    imageName: 'arduino.png',\n    title: {\n        ko: '아두이노',\n        en: 'Arduino',\n    },\n    setZero() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (let port = 0; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/arduino.png',\n        width: 605,\n        height: 434,\n        listPorts: {\n            2: {\n                name: `${Lang.Hw.port_en} 2 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            3: {\n                name: `${Lang.Hw.port_en} 3 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            4: {\n                name: `${Lang.Hw.port_en} 4 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            5: {\n                name: `${Lang.Hw.port_en} 5 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            6: {\n                name: `${Lang.Hw.port_en} 6 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            7: {\n                name: `${Lang.Hw.port_en} 7 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            8: {\n                name: `${Lang.Hw.port_en} 8 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            9: {\n                name: `${Lang.Hw.port_en} 9 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            10: {\n                name: `${Lang.Hw.port_en} 10 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            11: {\n                name: `${Lang.Hw.port_en} 11 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            12: {\n                name: `${Lang.Hw.port_en} 12 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            13: {\n                name: `${Lang.Hw.port_en} 13 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: `${Lang.Hw.port_en} A0 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: `${Lang.Hw.port_en} A1 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a2: {\n                name: `${Lang.Hw.port_en} A2 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a3: {\n                name: `${Lang.Hw.port_en} A3 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a4: {\n                name: `${Lang.Hw.port_en} A4 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a5: {\n                name: `${Lang.Hw.port_en} A5 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.Arduino.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                arduino_get_number_sensor_value: '아날로그 %1 번 값 ',\n                arduino_get_digital_value: '디지털 %1 번 값',\n                arduino_toggle_led: '디지털 %1 번 핀 %2 %3',\n                arduino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                arduino_convert_scale: '%1 번 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼 값',\n            },\n            Device: {\n                arduino: '아두이노',\n            },\n            Menus: {\n                arduino: '아두이노',\n            },\n            Helper: {\n                arduino_get_number_sensor_value: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)',\n                arduino_convert_scale: '선택한 핀의 아날로그 값을 입력한 범위로 바꾼 값입니다.',\n                arduino_get_digital_value:\n                    '선택한 핀의 디지털 값입니다. 핀이 켜진 경우 \"참\"으로 판단합니다.',\n                arduino_toggle_led: '선택한 핀을 켜거나 끕니다.',\n                arduino_toggle_pwm: '선택한 핀을 입력한 값으로 정합니다.',\n            },\n        },\n        en: {\n            template: {\n                arduino_get_number_sensor_value: 'analog %1 value  ',\n                arduino_get_digital_value: 'digital %1 value  ',\n                arduino_toggle_led: '%2 digital %1 pin %3',\n                arduino_toggle_pwm: 'Set digital %1 pin to %2 %3',\n                arduino_convert_scale: 'mapped value of analog %1 that %2 ~ %3 to %4 ~ %5',\n            },\n            Device: {\n                arduino: 'arduino',\n            },\n            Menus: {\n                arduino: 'Arduino',\n            },\n            Helper: {\n                arduino_get_number_sensor_value:\n                    'Reports the value that analog signal of the selected pin. (0 ~ 1023)',\n                arduino_convert_scale:\n                    'Reports the value that analog signal of the selected pin mapping original range onto input range.',\n                arduino_get_digital_value:\n                    'Checks whether the selected pin is turned on. If it turned on, it is judged as \"True\".',\n                arduino_toggle_led: 'Turn on or turn off the selected pin.',\n                arduino_toggle_pwm: 'Set the selected pin to input value.',\n            },\n        },\n    };\n};\n\nEntry.Arduino.blockMenuBlocks = [\n    'arduino_get_number_sensor_value',\n    'arduino_get_digital_value',\n    'arduino_toggle_led',\n    'arduino_toggle_pwm',\n    'arduino_convert_scale',\n];\n\nEntry.Arduino.getBlocks = function () {\n    return {\n        //region arduino 아두이노\n        arduino_text: {\n            color: '#FFD974',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['10'],\n            },\n            paramsKeyMap: {\n                NAME: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('NAME');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'TextInput',\n                                value: 10,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'arduino_text',\n                    },\n                ],\n            },\n        },\n        arduino_get_sensor_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', 'A0'],\n                        ['A1', 'A1'],\n                        ['A2', 'A2'],\n                        ['A3', 'A3'],\n                        ['A4', 'A4'],\n                        ['A5', 'A5'],\n                    ],\n                    value: 'A0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', 'A0'],\n                                    ['1', 'A1'],\n                                    ['2', 'A2'],\n                                    ['3', 'A3'],\n                                    ['4', 'A4'],\n                                    ['5', 'A5'],\n                                ],\n                                value: 'A0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        keyOption: 'arduino_get_sensor_number',\n                    },\n                ],\n            },\n        },\n        arduino_get_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_port_number',\n                    },\n                ],\n            },\n        },\n        arduino_get_pwm_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['3', '3'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'arduino_get_pwm_port_number',\n                    },\n                ],\n            },\n        },\n        arduino_get_number_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'arduino_get_number_sensor_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'arduino_value',\n            isNotFor: ['arduino'],\n            func(sprite, script) {\n                const signal = script.getValue('VALUE', script);\n                return Entry.hw.getAnalogPortValue(signal[1]);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_get_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'arduino_get_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'arduino_value',\n            isNotFor: ['arduino'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'ArduinoExt') {\n                    return Entry.block.arduino_ext_get_digital.func(sprite, script);\n                } else {\n                    const signal = script.getNumberValue('PORT', script);\n                    return Entry.hw.getDigitalPortValue(signal);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        replaceBlockType: 'arduino_ext_get_digital',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, 'on'],\n                        [Lang.Blocks.ARDUINO_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'arduino_toggle_led',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                OPERATOR: 1,\n            },\n            class: 'arduino_set',\n            isNotFor: ['arduino'],\n            func(sprite, script) {\n                const port = script.getNumberValue('VALUE');\n                const operator = script.getField('OPERATOR');\n                const value = operator == 'on' ? 255 : 0;\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.pin_digital(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_toggle_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'arduino_text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'arduino_toggle_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'arduino_set',\n            isNotFor: ['arduino'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.set_pin_digital(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_number_sensor_value',\n                        params: [\n                            {\n                                type: 'arduino_get_sensor_number',\n                                id: 'bl5e',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'arduino_convert_scale',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'arduino',\n            isNotFor: ['arduino'],\n            func(sprite, script) {\n                const value1 = script.getNumberValue('VALUE1', script);\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                let result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.convert_scale(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //endregion arduino 아두이노\n    };\n};\n\nmodule.exports = Entry.Arduino;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_arduino_cake.js",
    "content": "'use strict';\n\nEntry.ArduinoCake = {\n    id: ['40.1'],\n    name: 'ArduinoCake',\n    url: 'http://www.arduino.cc/',\n    imageName: 'ArduinoCake.png',\n    title: {\n        ko: '아두이노 케이크',\n        en: 'Arduino Cake',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.ArduinoCake.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                arduino_cake_get_analog_value: '아날로그 %1 번 센서값',\n                arduino_cake_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                arduino_cake_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                arduino_cake_toggle_led: '디지털 %1 번 핀 %2 %3',\n                arduino_cake_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                arduino_cake_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                arduino_cake_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                arduino_cake_get_digital: '디지털 %1 번 센서값',\n            },\n        },\n        en: {\n            template: {\n                arduino_cake_get_analog_value: 'Analog %1 Sensor value',\n                arduino_cake_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                arduino_cake_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                arduino_cake_toggle_led: 'Digital %1 Pin %2 %3',\n                arduino_cake_digital_pwm: 'Digital %1 Pin %2 %3',\n                arduino_cake_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                arduino_cake_set_servo: 'Set servo pin %1 angle as %2 %3',\n                arduino_cake_get_digital: 'Digital %1 Sensor value',\n            },\n        },\n    };\n};\n\nEntry.ArduinoCake.blockMenuBlocks = [\n    'arduino_cake_get_analog_value',\n    'arduino_cake_get_analog_value_map',\n    'arduino_cake_get_ultrasonic_value',\n    'arduino_cake_get_digital',\n    'arduino_cake_toggle_led',\n    'arduino_cake_digital_pwm',\n    'arduino_cake_set_servo',\n    'arduino_cake_set_tone',\n];\n\nEntry.ArduinoCake.getBlocks = function() {\n    return {\n        //region arduinoCake 아두이노 나노\n        arduino_cake_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['pinA1', '2'],\n                        ['pinA2', '3'],\n                        ['pinA3', '6'],\n                        ['pinA4', '7'],\n                        ['pinB1', '0'],\n                        ['pinB2', '1'],\n                        ['pinSD', '4'],\n                        ['pinSC', '5'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['pinA1', '2'],\n                                    ['pinA2', '3'],\n                                    ['pinA3', '6'],\n                                    ['pinA4', '7'],\n                                    ['pinB1', '0'],\n                                    ['pinB2', '1'],\n                                    ['pinSD', '4'],\n                                    ['pinSC', '5'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_cake_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_cake_analog_list',\n                    },\n                ],\n            },\n        },\n\n        arduino_cake_digital_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['pinBD', '10'], \n                        ['pinA1', '16'], \n                        ['pinA2', '17'], \n                        ['pinB1', '14'], \n                        ['pinB2', '15'],\n                        ['pinB3', '2'], \n                        ['pinB4', '9'],\n                        ['pinC1', '3'], \n                        ['pinC2', '12'],\n                        ['pinC3', '11'], \n                        ['pinC4', '13'],\n                        ['pinC5', '5'], \n                        ['pinC6', '4'],\n                        ['pinC7', '6'], \n                        ['pinC8', '7'],\n                        ['pinSD', '18'], \n                        ['pinSC', '19'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['pinBD', '10'], \n                                    ['pinA1', '16'], \n                                    ['pinA2', '17'], \n                                    ['pinB1', '14'], \n                                    ['pinB2', '15'],\n                                    ['pinB3', '2'], \n                                    ['pinB4', '9'],\n                                    ['pinC1', '3'], \n                                    ['pinC2', '12'],\n                                    ['pinC3', '11'], \n                                    ['pinC4', '13'],\n                                    ['pinC5', '5'], \n                                    ['pinC6', '4'],\n                                    ['pinC7', '6'], \n                                    ['pinC8', '7'],\n                                    ['pinSD', '18'], \n                                    ['pinSC', '19'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_cake_digital_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_cake_digital_list',\n                    },\n                ],\n            },\n        },\n        \n        arduino_cake_pwm_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['pinBD', '10'],\n                        ['pinB4', '9'],\n                        ['pinC1', '3'], \n                        ['pinC3', '11'],\n                        ['pinC5', '5'], \n                        ['pinC6', '4'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['pinBD', '10'],\n                                    ['pinB4', '9'],\n                                    ['pinC1', '3'], \n                                    ['pinC3', '11'],\n                                    ['pinC5', '5'], \n                                    ['pinC6', '4'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_cake_pwm_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_cake_pwm_list',\n                    },\n                ],\n            },\n        },\n        \n        arduino_cake_buz_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['pinBD', '8'],\n                    ],\n                    value: '8',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['pinBD', '8'],\n                                ],\n                                value: '8',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_cake_pwm_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_cake_buz_list',\n                    },\n                ],\n            },\n        },\n        \n        \n        arduino_cake_get_analog_value: {\n            parent: 'arduino_ext_get_analog_value',\n            template: Lang.template.arduino_ext_get_analog_value,\n            def: {\n                params: [\n                    {\n                        type: 'arduino_cake_analog_list',\n                    },\n                ],\n                type: 'arduino_cake_get_analog_value',\n            },\n            isNotFor: ['ArduinoCake'],\n            syntax: undefined,\n        },\n        arduino_cake_get_analog_value_map: {\n            parent: 'arduino_ext_get_analog_value_map',\n            template: Lang.template.arduino_ext_get_analog_value_map,\n            def: {\n                params: [\n                    {\n                        type: 'arduino_cake_get_analog_value',\n                        params: [\n                            {\n                                type: 'arduino_cake_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'arduino_cake_get_analog_value_map',\n            },\n            isNotFor: ['ArduinoCake'],\n            syntax: undefined,\n        },\n        arduino_cake_get_ultrasonic_value: {\n            template: Lang.template.arduino_ext_get_ultrasonic_value,\n            parent: 'arduino_ext_get_ultrasonic_value',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_cake_digital_list',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'arduino_cake_digital_list',\n                        params: ['17'],\n                    },\n                ],\n                type: 'arduino_cake_get_ultrasonic_value',\n            },\n            isNotFor: ['ArduinoCake'],\n            syntax: undefined,\n        },\n        arduino_cake_get_digital: {\n            template: Lang.template.arduino_ext_get_digital,\n            parent: 'arduino_ext_get_digital',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_cake_digital_list',\n                    },\n                ],\n                type: 'arduino_cake_get_digital',\n            },\n            isNotFor: ['ArduinoCake'],\n            syntax: undefined,\n        },\n        arduino_cake_toggle_led: {\n            template: Lang.template.arduino_ext_toggle_led,\n            parent: 'arduino_ext_toggle_led',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_cake_digital_list',\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'arduino_cake_toggle_led',\n            },\n            isNotFor: ['ArduinoCake'],\n            syntax: undefined,\n        },\n        arduino_cake_digital_pwm: {\n            template: Lang.template.arduino_ext_digital_pwm,\n            parent: 'arduino_ext_digital_pwm',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_cake_pwm_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'arduino_cake_digital_pwm',\n            },\n            isNotFor: ['ArduinoCake'],\n            syntax: undefined,\n        },\n        arduino_cake_set_tone: {\n            template: Lang.template.arduino_ext_set_tone,\n            parent: 'arduino_ext_set_tone',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_cake_buz_list',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'arduino_ext_tone_list',\n                    },\n                    {\n                        type: 'arduino_ext_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'arduino_cake_set_tone',\n            },\n            isNotFor: ['ArduinoCake'],\n            syntax: undefined,\n        },\n        arduino_cake_set_servo: {\n            template: Lang.template.arduino_ext_set_servo,\n            parent: 'arduino_ext_set_servo',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_cake_digital_list',\n                        params: ['9'],\n                    },\n                    null,\n                ],\n                type: 'arduino_cake_set_servo',\n            },\n            isNotFor: ['ArduinoCake'],\n            syntax: undefined,\n        },\n        //endregion arduinoCake 아두이노 케이크\n    };\n};\n\nmodule.exports = Entry.ArduinoCake;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_arduino_ext.js",
    "content": "'use strict';\n\nEntry.ArduinoExt = {\n    id: '1.9',\n    name: 'ArduinoExt',\n    url: 'http://www.arduino.cc/',\n    imageName: 'arduinoExt.png',\n    title: {\n        ko: '아두이노 Uno 확장모드',\n        en: 'ArduinoExt Uno',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        0: 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        4: [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        5: [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        6: [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.ArduinoExt.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                arduino_ext_get_analog_value: '아날로그 %1 번 값',\n                arduino_ext_get_analog_value_map:\n                    '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼 값',\n                arduino_ext_get_ultrasonic_value:\n                    '디지털 %1 번 핀을 Trig에 디지털 %2 번 핀을 Echo에 연결한 초음파 센서 값',\n                arduino_ext_toggle_led: '디지털 %1 번 핀 %2 %3',\n                arduino_ext_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                arduino_ext_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 울리기 %5',\n                arduino_ext_set_servo: '디지털 %1 번 핀의 서보모터를 %2 도로 정하기 %3',\n                arduino_ext_get_digital: '디지털 %1 번 값',\n            },\n            Helper: {\n                arduino_ext_get_analog_value: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)',\n                arduino_ext_get_analog_value_map:\n                    '선택한 핀의 아날로그 값을 입력한 범위로 바꾼 값입니다.',\n                arduino_ext_get_ultrasonic_value: '선택한 핀에 연결한 초음파 센서 값입니다.',\n                arduino_ext_set_servo: '선택한 핀에 연결한 서보모터의 각도를 정합니다.',\n                arduino_ext_set_tone:\n                    '선택한 핀에 연결한 버저를 선택한 음으로 입력한 시간 동안 울립니다.',\n                arduino_ext_get_digital:\n                    '선택한 핀의 디지털 값입니다. 핀이 켜진 경우 \"참\"으로 판단합니다.',\n                arduino_ext_toggle_led: '선택한 핀을 켜거나 끕니다.',\n                arduino_ext_digital_pwm: '선택한 핀을 입력한 값으로 정합니다.',\n            },\n        },\n        en: {\n            template: {\n                arduino_ext_get_analog_value: 'analog %1 value',\n                arduino_ext_get_analog_value_map:\n                    'mapped value of analog %1 that %2 ~ %3 to %4 ~ %5',\n                arduino_ext_get_ultrasonic_value:\n                    'ultrasonic sensor value that connects pin %1 to Trig and pin %2 to Echo',\n                arduino_ext_toggle_led: '%2 digital %1 pin %3',\n                arduino_ext_digital_pwm: 'Set digital %1 pin to %2 %3',\n                arduino_ext_set_tone:\n                    'Ring buzzer of pin %1 on note %2 octave %3 for %4 second(s) %5',\n                arduino_ext_set_servo: 'Set servo motor of pin %1 to %2 degree %3',\n                arduino_ext_get_digital: 'digital %1 value',\n            },\n            Helper: {\n                arduino_ext_get_analog_value:\n                    'Reports the value that analog signal of the selected pin. (0 ~ 1023)',\n                arduino_ext_get_analog_value_map:\n                    'Reports the value that analog signal of the selected pin mapping original range onto input range.',\n                arduino_ext_get_ultrasonic_value:\n                    'Reports the value of ultrasonic sensor that connects pin.',\n                arduino_ext_set_servo:\n                    'Set the degree of servo motor that connected with selected pin.',\n                arduino_ext_set_tone:\n                    'Rings buzzer connected with selected pin during input seconds.',\n                arduino_ext_get_digital:\n                    'Checks whether the selected pin is turned on. If it turned on, it is judged as \"True\".',\n                arduino_ext_toggle_led: 'Turn on or turn off the selected pin.',\n                arduino_ext_digital_pwm: 'Set the selected pin to input value.',\n            },\n        },\n    };\n};\n\nEntry.ArduinoExt.blockMenuBlocks = [\n    'arduino_ext_get_analog_value',\n    'arduino_ext_get_analog_value_map',\n    'arduino_ext_get_ultrasonic_value',\n    'arduino_ext_get_digital',\n    'arduino_ext_toggle_led',\n    'arduino_ext_digital_pwm',\n    'arduino_ext_set_servo',\n    'arduino_ext_set_tone',\n];\n\n//region arduinoExt 아두이노 확장모드\nEntry.ArduinoExt.getBlocks = function () {\n    return {\n        arduino_ext_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_ext_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_ext_analog_list',\n                    },\n                ],\n            },\n        },\n        arduino_ext_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_ext_analog_list',\n                    },\n                ],\n                type: 'arduino_ext_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ArduinoExtGet',\n            isNotFor: ['ArduinoExt'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_ext_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_ext_get_analog_value',\n                        params: [\n                            {\n                                type: 'arduino_ext_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'arduino_ext_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'ArduinoExtGet',\n            isNotFor: ['ArduinoExt'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_ext_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'arduino_ext_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'ArduinoExtGet',\n            isNotFor: ['ArduinoExt'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.ArduinoExt.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_ext_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'arduino_ext_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ArduinoExtGet',\n            isNotFor: ['ArduinoExt'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'ArduinoExt' || name === 'ArduinoNano') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.ArduinoExt.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, 'on'],\n                        [Lang.Blocks.ARDUINO_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_get_digital_toggle[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_digital_toggle',\n                    },\n                ],\n            },\n        },\n        arduino_ext_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'arduino_ext_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ArduinoExt',\n            isNotFor: ['ArduinoExt'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.ArduinoExt.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.ArduinoExt.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_ext_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'arduino_ext_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ArduinoExt',\n            isNotFor: ['ArduinoExt'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_ext_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_ext_tone_list',\n                    },\n                ],\n            },\n        },\n        arduino_ext_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_ext_tone_list',\n                    },\n                ],\n                type: 'arduino_ext_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'arduino_ext_tone_value',\n                    },\n                ],\n            },\n        },\n        arduino_ext_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'arduino_ext_octave_list',\n                    },\n                ],\n            },\n        },\n        arduino_ext_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_ext_tone_list',\n                    },\n                    {\n                        type: 'arduino_ext_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'arduino_ext_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'ArduinoExt',\n            isNotFor: ['ArduinoExt'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.ArduinoExt.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.ArduinoExt.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.ArduinoExt.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_ext_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'arduino_ext_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ArduinoExt',\n            isNotFor: ['ArduinoExt'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n//endregion arduinoExt 아두이노 확장모드\n\nmodule.exports = Entry.ArduinoExt;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_arduino_nano.js",
    "content": "'use strict';\n\nEntry.ArduinoNano = {\n    id: ['1.10', '1A.1'],\n    name: 'ArduinoNano',\n    url: 'http://www.arduino.cc/',\n    imageName: 'arduinoNano.png',\n    title: {\n        ko: '아두이노 Nano',\n        en: 'Arduino Nano',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        0: 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        4: [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        5: [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        6: [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.ArduinoNano.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                arduino_nano_get_analog_value: '아날로그 %1 번 값',\n                arduino_nano_get_analog_value_map:\n                    '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼 값',\n                arduino_nano_get_ultrasonic_value:\n                    '디지털 %1 번 핀을 Trig에 디지털 %2 번 핀을 Echo에 연결한 초음파 센서 값',\n                arduino_nano_toggle_led: '디지털 %1 번 핀 %2 %3',\n                arduino_nano_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                arduino_nano_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 울리기 %5',\n                arduino_nano_set_servo: '디지털 %1 번 핀의 서보모터를 %2 도로 정하기 %3',\n                arduino_nano_get_digital: '디지털 %1 번 값',\n            },\n            Device: {\n                arduinonano: '아두이노 Nano',\n            },\n            Helper: {\n                arduino_nano_get_analog_value: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)',\n                arduino_nano_get_analog_value_map:\n                    '선택한 핀의 아날로그 값을 입력한 범위로 바꾼 값입니다.',\n                arduino_nano_get_digital:\n                    '선택한 핀의 디지털 값입니다. 핀이 켜진 경우 \"참\"으로 판단합니다.',\n                arduino_nano_toggle_led: '선택한 핀을 켜거나 끕니다.',\n                arduino_nano_digital_pwm: '선택한 핀을 입력한 값으로 정합니다.',\n                arduino_nano_get_ultrasonic_value: '선택한 핀에 연결한 초음파 센서 값입니다.',\n                arduino_nano_set_servo: '선택한 핀에 연결한 서보모터의 각도를 정합니다.',\n                arduino_nano_set_tone:\n                    '선택한 핀에 연결한 버저를 선택한 음으로 입력한 시간 동안 울립니다.',\n            },\n        },\n        en: {\n            template: {\n                arduino_nano_get_analog_value: 'analog %1 value',\n                arduino_nano_get_analog_value_map:\n                    'mapped value of analog %1 that %2 ~ %3 to %4 ~ %5',\n                arduino_nano_get_ultrasonic_value:\n                    'ultrasonic sensor value that connects pin %1 to Trig and pin %2 to Echo',\n                arduino_nano_toggle_led: '%2 digital %1 pin %3',\n                arduino_nano_digital_pwm: 'Set digital %1 pin to %2 %3',\n                arduino_nano_set_tone:\n                    'Ring buzzer of pin %1 on note %2 octave %3 for %4 second(s) %5',\n                arduino_nano_set_servo: 'Set servo motor of pin %1 to %2 degree %3',\n                arduino_nano_get_digital: 'digital %1 value',\n            },\n            Helper: {\n                arduino_nano_get_analog_value:\n                    'Reports the value that analog signal of the selected pin. (0 ~ 1023)',\n                arduino_nano_get_analog_value_map:\n                    'Reports the value that analog signal of the selected pin mapping original range onto input range.',\n                arduino_nano_get_digital:\n                    'Checks whether the selected pin is turned on. If it turned on, it is judged as \"True\".',\n                arduino_nano_toggle_led: 'Turn on or turn off the selected pin.',\n                arduino_nano_digital_pwm: 'Set the selected pin to input value.',\n                arduino_nano_set_servo:\n                    'Set the degree of servo motor that connected with selected pin.',\n                arduino_nano_set_tone:\n                    'Rings buzzer connected with selected pin during input seconds.',\n                arduino_nano_get_ultrasonic_value:\n                    'Reports the value of ultrasonic sensor that connects pin.',\n            },\n        },\n    };\n};\n\nEntry.ArduinoNano.blockMenuBlocks = [\n    'arduino_nano_get_analog_value',\n    'arduino_nano_get_analog_value_map',\n    'arduino_nano_get_ultrasonic_value',\n    'arduino_nano_get_digital',\n    'arduino_nano_toggle_led',\n    'arduino_nano_digital_pwm',\n    'arduino_nano_set_servo',\n    'arduino_nano_set_tone',\n];\n\nEntry.ArduinoNano.getBlocks = function () {\n    return {\n        //region arduinoNano 아두이노 나노\n        arduino_nano_analog_list: {\n            parent: 'arduino_ext_analog_list',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                        ['A6', '6'],\n                        ['A7', '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            syntax: undefined,\n        },\n        arduino_nano_get_analog_value: {\n            parent: 'arduino_ext_get_analog_value',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_nano_analog_list',\n                    },\n                ],\n                type: 'arduino_nano_get_analog_value',\n            },\n            isNotFor: ['ArduinoNano'],\n            syntax: undefined,\n        },\n        arduino_nano_get_analog_value_map: {\n            parent: 'arduino_ext_get_analog_value_map',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_nano_get_analog_value',\n                        params: [\n                            {\n                                type: 'arduino_nano_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'arduino_nano_get_analog_value_map',\n            },\n            isNotFor: ['ArduinoNano'],\n            syntax: undefined,\n        },\n        arduino_nano_get_ultrasonic_value: {\n            parent: 'arduino_ext_get_ultrasonic_value',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'arduino_nano_get_ultrasonic_value',\n            },\n            isNotFor: ['ArduinoNano'],\n            syntax: undefined,\n        },\n        arduino_nano_get_digital: {\n            parent: 'arduino_ext_get_digital',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'arduino_nano_get_digital',\n            },\n            isNotFor: ['ArduinoNano'],\n            syntax: undefined,\n        },\n        arduino_nano_toggle_led: {\n            parent: 'arduino_ext_toggle_led',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'arduino_nano_toggle_led',\n            },\n            isNotFor: ['ArduinoNano'],\n            syntax: undefined,\n        },\n        arduino_nano_digital_pwm: {\n            template: Lang.template.arduino_ext_digital_pwm,\n            parent: 'arduino_ext_digital_pwm',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'arduino_nano_digital_pwm',\n            },\n            isNotFor: ['ArduinoNano'],\n            syntax: undefined,\n        },\n        arduino_nano_set_tone: {\n            parent: 'arduino_ext_set_tone',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        value: 4,\n                    },\n                    {\n                        type: 'arduino_ext_tone_list',\n                    },\n                    {\n                        type: 'arduino_ext_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'arduino_nano_set_tone',\n            },\n            isNotFor: ['ArduinoNano'],\n            syntax: undefined,\n        },\n        arduino_nano_set_servo: {\n            parent: 'arduino_ext_set_servo',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    null,\n                ],\n                type: 'arduino_nano_set_servo',\n            },\n            isNotFor: ['ArduinoNano'],\n            syntax: undefined,\n        },\n        //endregion arduinoNano 아두이노 나노\n    };\n};\n\nmodule.exports = Entry.ArduinoNano;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_armz.js",
    "content": "﻿'use strict';\r\n\r\nconst _set = require('lodash/set');\r\nconst _get = require('lodash/get');\r\nconst _merge = require('lodash/merge');\r\n\r\nEntry.Armz = new class Armz {\r\n    constructor() {\r\n//        this.id = 'FF.FF'; \r\n        this.id = '2C.1';       \r\n        this.url = 'http://www.myarmz.com';\r\n        this.imageName = 'armz.png';\r\n\t\t    this.title = {\r\n\t\t        ko: '암즈', \r\n\t\t        en: 'armz',\r\n\t\t    }; \r\n        this.name = 'armz'; \r\n        this.timeouts = [];\r\n    }\r\n\r\n    getHashKey() {\r\n        let key = new Date().getSeconds().toString(16);\r\n        if (key.length === 1) {\r\n            key += ((Math.random() * 16) | 0).toString(16); \r\n        }\r\n        return Entry.generateHash() + key;\r\n    }\r\n\r\n    setZero() {\r\n        Entry.hw.sendQueue = {\r\n            [this.getHashKey()]: {\r\n                type: 'RST',\r\n            },\r\n        };\r\n        Entry.hw.update();\r\n    }\r\n\r\n    sendMessage({ socket, sendQueue = {} }) {\r\n        if (!_.isEmpty(sendQueue)) {\r\n            const keys = Object.keys(sendQueue);\r\n            const uniqueKey = this.getHashKey();\r\n            socket.emit(\r\n                'message',\r\n                {\r\n                    data: JSON.stringify(sendQueue),\r\n                    mode: socket.mode,\r\n                    type: 'utf8',\r\n                    key: uniqueKey,\r\n                },\r\n                (data) => {\r\n                    if (data === uniqueKey) {\r\n                        keys.forEach((key) => {\r\n                            delete sendQueue[key];\r\n                        });\r\n                    }\r\n                }\r\n            );\r\n        }\r\n    }\r\n\r\n    removeTimeout(id) {\r\n        clearTimeout(id);\r\n        var timeouts = this.timeouts;\r\n        var index = timeouts.indexOf(id);\r\n        if (index >= 0) {\r\n            timeouts.splice(index, 1);\r\n        }\r\n    }\r\n    \r\n    removeAllTimeouts() {\r\n        var timeouts = this.timeouts;\r\n        for (var i in timeouts) {\r\n            clearTimeout(timeouts[i]);\r\n        }\r\n        this.timeouts = [];\r\n    }   \r\n    \r\n\t\tcheckInterval(script, delay)\t{\r\n\t\t\t\tif (!script.isStart) {\r\n\t\t\t\t\t\tscript.isStart = true;\r\n\t\t\t\t\t\tscript.timeFlag = 1;\r\n\t\t\t\t\t\t\r\n\t\t\t\t    var timeValue = delay * 1000; \r\n            setTimeout(function() {\r\n                script.timeFlag = 0;\r\n            }, timeValue);\r\n/*\r\n\t\t\t\t    var timer = setTimeout(function() {\r\n\t\t\t\t        script.timeFlag = 0;\r\n\t\t\t\t        Entry.Armz.removeTimeout(timer);\r\n\t\t\t\t    }, timeValue);\r\n\t\t\t\t    Entry.Armz.timeouts.push(timer);  \r\n*/\t    \r\n\t\t\t\t    return 'Start'; \r\n\t\t\t\t} else if (script.timeFlag == 1) {\r\n\t\t\t\t    return 'Run'; \r\n\t\t\t\t} else { \r\n\t\t\t\t    delete script.isStart;\r\n\t\t\t\t    delete script.timeFlag;\r\n\t\t\t\t    Entry.engine.isContinue = false;\r\n\t\t\t\t    return 'Finish';\r\n\t\t\t\t}\r\n\t\t} \r\n\r\n    postSendQueue({ script, data }, scope) {\r\n\t\t\t\tconst blockId = this.getHashKey();\r\n\t\t\t\t_merge(Entry.hw.sendQueue, {\r\n\t\t\t\t    [blockId]: data,\r\n\t\t\t\t});\r\n    }\r\n\r\n    postCallReturn(args) { \r\n        const { script } = args;\r\n        this.postSendQueue(args, script);\r\n\t\t} \r\n \r\n    postCallReturnDelay(args, delay) {\r\n        const { script } = args;\r\n\r\n        switch (this.checkInterval(script, delay)) { \r\n            case 'Start':\r\n                {\r\n                    this.postSendQueue(args, script); \r\n                }\r\n                return script; \r\n\r\n            case 'Run':\r\n                return script;\r\n\r\n            case 'Finish':\r\n                return script.callReturn();\r\n\r\n            default:\r\n                return script.callReturn();\r\n        }        \r\n    }     \r\n};\r\n\r\nEntry.Armz.setLanguage = function() { \r\n    return {\r\n        en: {\r\n            Blocks: {\r\n                Action: 'Action',\r\n                Sound: 'Sound',\r\n                Right: 'Right',\r\n                Left: 'Left',  \r\n                Back: 'Back',\r\n                Red: 'Red',\r\n                Green: 'Green',\r\n                Blue: 'Blue',                        \r\n                Cheer: 'Cheer',\r\n                Glad: 'Glad',\r\n                Dissatisfaction: 'Dissatisfaction',\r\n                Angry: 'Angry',  \r\n                Laughter: 'Laughter',\r\n                Praise: 'Praise',\r\n                Praise2: 'Praise2',                \r\n                Consolation: 'Consolation',\r\n                Surprised: 'Surprised',    \r\n                Warning: 'Warning',\r\n                Fear: 'Fear',                                           \r\n            },        \t\r\n            template: {\r\n                armz_run_action: \"%1 : Number %2 Run %3\", \r\n                armz_block_coding_MF: \"Move to forward %1sec %2\",\r\n                armz_block_coding_MB: \"Move to backward %1sec %2\",\r\n                armz_block_coding_T: \"Turn %1 %2\",  \r\n                armz_block_coding_LO: \"LED %1 Color Turn on 1sec %2\",        \r\n                armz_block_coding_LB: \"LED %1 Color Blink %2\",    \r\n                armz_block_coding_LR: \"LED Rainbow Color Turn on 3sec %1\",                    \r\n                armz_block_coding_E: \"Eexpression of %1 Emotion %2\",                                                                      \r\n            },\r\n        },\r\n        ko: { \r\n            Blocks: {\r\n                Action: '동작',\r\n                Sound: '소리',\r\n                Right: '오른쪽',\r\n                Left: '왼쪽',  \r\n                Back: '뒤쪽',\r\n                Red: '빨강',\r\n                Green: '초록',\r\n                Blue: '파랑',    \r\n                Cheer: '환호',\r\n                Glad: '반가움',\r\n                Dissatisfaction: '불만',\r\n                Angry: '화남',  \r\n                Laughter: '웃음',\r\n                Praise: '칭찬',\r\n                Praise2: '칭찬2',                \r\n                Consolation: '위로',\r\n                Surprised: '놀람',    \r\n                Warning: '경고',\r\n                Fear: '공포',                                 \r\n            },        \t\r\n            template: {\r\n                armz_run_action: \"%1 : 번호 %2 실행 %3\",  \r\n                armz_block_coding_MF: \"앞으로 %1초간 이동 %2\",\r\n                armz_block_coding_MB: \"뒤로 %1초간 이동 %2\",\r\n                armz_block_coding_T: \"%1 방향으로 회전 %2\",  \r\n                armz_block_coding_LO: \"%1 색깔 램프 1초간 켜기 %2\", \r\n                armz_block_coding_LB: \"%1 색깔 램프 깜박이기 %2\",   \r\n                armz_block_coding_LR: \"무지개 색깔 램프 3초간 켜기 %1\",                                                 \r\n                armz_block_coding_E: \"%1의 감정 표현하기 %2\",                                       \r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.Armz.blockMenuBlocks = [\r\n\t\t'armz_run_action',\r\n\t\t'armz_block_coding_MF',\r\n\t\t'armz_block_coding_MB',\r\n\t\t'armz_block_coding_T',\r\n\t\t'armz_block_coding_LO',\r\n\t\t'armz_block_coding_LB',\t\t\t\t\t\r\n\t\t'armz_block_coding_LR',\r\n\t\t'armz_block_coding_E',\t\r\n];\r\n\r\nEntry.Armz.getBlocks = function() { \r\n    return {\r\n        armz_run_action: { \r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.Action, 'ACTION'], [Lang.Blocks.Sound, 'SOUND']],\r\n                    value: 'ACTION',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number', \r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                ],\r\n                type: 'armz_run_action',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'output',\r\n            isNotFor: ['armz'],\r\n       \t\t\tfunc: function(sprite, script) {\r\n                var port = script.getStringField('PORT', script);\r\n                var value = script.getValue('VALUE', script);\r\n                const data = {\r\n                    type: 'RUN_PLAY',  \r\n                    data: {\r\n                        port,\r\n                        value,\r\n                    },\r\n                };  \r\n\t\t\t\t\t\t\t\treturn Entry.Armz.postCallReturnDelay({script, data}, 3);  \r\n            },\r\n        },    \t\r\n        armz_block_coding_MF: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [['0.5', 51], ['1', 52], ['2', 53], ['3', 54]],\r\n                    value: 51, \r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },           \r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg', \r\n                    size: 12,\r\n                }, \r\n            ],\r\n            events: {},\r\n            def: {\r\n                type: 'armz_block_coding_MF',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },            \r\n            class: 'block',\r\n            isNotFor: ['armz'], \r\n       \t\t\tfunc: function(sprite, script) {\r\n                var port = 'ACTION'; \r\n                var value = script.getNumberField('VALUE', script);\r\n                var time = value - 50; \r\n                const data = {\r\n                    type: 'RUN_PLAY',\r\n                    data: {\r\n                        port,\r\n                        value,\r\n                    },\r\n                };\r\n\t\t\t\t\t\t\t\treturn Entry.Armz.postCallReturnDelay({script, data}, time); \r\n            },\r\n        },     \r\n        armz_block_coding_MB: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [['0.5', 55], ['1', 56], ['2', 57], ['3', 58]],\r\n                    value: 55,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },           \r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                }, \r\n            ],\r\n            events: {},\r\n            def: {\r\n                type: 'armz_block_coding_MB', \r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },             \r\n            class: 'block',\r\n            isNotFor: ['armz'], \r\n       \t\t\tfunc: function(sprite, script) {\r\n                var port = 'ACTION'; \r\n                var value = script.getNumberField('VALUE', script);\r\n                var time = value - 54; \r\n                const data = {\r\n                    type: 'RUN_PLAY', \r\n                    data: {\r\n                        port,\r\n                        value,\r\n                    },\r\n                };   \r\n\t\t\t\t\t\t\t\treturn Entry.Armz.postCallReturnDelay({script, data}, time);                   \t\t\t\t\r\n            },\r\n        },       \r\n        armz_block_coding_T: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.Right, 59], [Lang.Blocks.Left, 60], [Lang.Blocks.Back, 61]], \r\n                    value: 59,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, \r\n                },           \r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                }, \r\n            ],\r\n            events: {}, \r\n            def: {\r\n                type: 'armz_block_coding_T', \r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },             \r\n            class: 'block',\r\n            isNotFor: ['armz'], \r\n       \t\t\tfunc: function(sprite, script) {\r\n                var port = 'ACTION';\r\n                var value = script.getNumberField('VALUE', script);\r\n                const data = {\r\n                    type: 'RUN_PLAY', \r\n                    data: {\r\n                        port, \r\n                        value,\r\n                    },\r\n                };\r\n                return Entry.Armz.postCallReturnDelay({script, data}, 2);\r\n            },\r\n        },  \r\n\t\t\t\tarmz_block_coding_LO: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.Red, 62], [Lang.Blocks.Green, 64], [Lang.Blocks.Blue, 66]], \r\n                    value: 62,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },          \r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                }, \r\n            ],\r\n            events: {}, \r\n            def: {\r\n                type: 'armz_block_coding_LO',  \r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },             \r\n            class: 'block',\r\n            isNotFor: ['armz'], \r\n       \t\t\tfunc: function(sprite, script) {\r\n                var port = 'ACTION'; \r\n                var value = script.getNumberField('VALUE', script);\r\n                const data = {\r\n                    type: 'RUN_PLAY', \r\n                    data: {\r\n                        port,\r\n                        value,\r\n                    },\r\n                };       \t\t\t\t\r\n                return Entry.Armz.postCallReturnDelay({script, data}, 2); \r\n            },\r\n        },             \r\n\t\t\t\tarmz_block_coding_LB: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.Red, 63], [Lang.Blocks.Green, 65], [Lang.Blocks.Blue, 67]], \r\n                    value: 63, \r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },          \r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                }, \r\n            ],\r\n            events: {}, \r\n            def: {\r\n                type: 'armz_block_coding_LB', \r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },             \r\n            class: 'block',\r\n            isNotFor: ['armz'], \r\n       \t\t\tfunc: function(sprite, script) {\r\n                var port = 'ACTION';\r\n                var value = script.getNumberField('VALUE', script);\r\n                const data = {\r\n                    type: 'RUN_PLAY', \r\n                    data: {\r\n                        port,\r\n                        value,\r\n                    },\r\n                };\r\n                return Entry.Armz.postCallReturnDelay({script, data}, 3); \r\n            },\r\n        },          \r\n\t\t\t\tarmz_block_coding_LR: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                }, \r\n            ],\r\n            events: {}, \r\n            def: {\r\n                type: 'armz_block_coding_LR',  \r\n            },\r\n            class: 'block',\r\n            isNotFor: ['armz'], \r\n       \t\t\tfunc: function(sprite, script) {\r\n                var port = 'ACTION'; \r\n                var value = 68;\t\t\t \r\n\t\t                const data = {\r\n\t\t                    type: 'RUN_PLAY', \r\n\t\t                    data: {\r\n\t\t                        port,\r\n\t\t                        value, \r\n\t\t                    },\r\n\t\t                };       \t\t\t\t\r\n\t\t\t\t\t\t\t\treturn Entry.Armz.postCallReturnDelay({script, data}, 3); \r\n            },                  \r\n        },  \r\n\t\t\t\tarmz_block_coding_E: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.Cheer, 200], [Lang.Blocks.Glad, 201], [Lang.Blocks.Dissatisfaction, 202],\r\n\t\t\t\t\t                    [Lang.Blocks.Angry, 203], [Lang.Blocks.Laughter, 204], [Lang.Blocks.Praise, 205],\r\n\t\t\t\t\t                    [Lang.Blocks.Praise2, 206], [Lang.Blocks.Consolation, 207], [Lang.Blocks.Surprised, 208], \r\n\t\t\t\t\t                    [Lang.Blocks.Warning, 209], [Lang.Blocks.Fear, 210]\r\n                    ], \r\n                    value: 200, \r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },          \r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg', \r\n                    size: 12,\r\n                }, \r\n            ],\r\n            events: {}, \r\n            def: {\r\n                type: 'armz_block_coding_E',  \r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0, \r\n            },             \r\n            class: 'block',\r\n            isNotFor: ['armz'], \r\n       \t\t\tfunc: function(sprite, script) {\r\n              \tvar port = 'ACTION'; \r\n                var value = script.getNumberField('VALUE', script);\r\n                const data = {\r\n                    type: 'RUN_PLAY', \r\n                    data: {\r\n                        port,\r\n                        value,\r\n                    },\r\n                };\r\n\t\t\t\t\t\t\t\treturn Entry.Armz.postCallReturnDelay({script, data}, 3);\r\n            },\r\n        },          \r\n    };\r\n};\r\n\r\nmodule.exports = Entry.Armz; \r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_asomebot.js",
    "content": "'use strict';\n\nfunction format_str() {\n    var s = arguments[0];\n    for (var i = 0; i < arguments.length - 1; i++) {\n        var reg = new RegExp('\\\\{' + i + '\\\\}', 'gm');\n        s = s.replace(reg, arguments[i + 1]);\n    }\n    return s;\n}\n\nfunction random_str(count) {\n    var text = '';\n    var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n    for (var i = 0; i < count; i++)\n        text += possible.charAt(Math.floor(Math.random() * possible.length));\n\n    return text;\n}\n\nEntry.AsomeBot = {\n    id: '32.1',\n    name: 'AsomeBot',\n    url: 'http://www.asomeit.com/',\n    imageName: 'AsomeBot.png',\n    title: {\n        ko: 'AsomeBot',\n        en: 'AsomeBot',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    getHashKey: function() {\n        let key = new Date().getSeconds().toString(16);\n        if (key.length === 1) {\n            key += ((Math.random() * 16) | 0).toString(16);\n        }\n        return Entry.generateHash() + key;\n    },\n    asyncFlowControl: function({ script, data }, scope) {\n        if (!this.isExecBlock && !scope.isStart) {\n            const blockId = this.getHashKey();\n            this.isExecBlock = true;\n            scope.isStart = true;\n            scope.timeFlag = 1;\n            this.nowBlockId = blockId;\n            this.blockIds[blockId] = false;\n            _merge(Entry.hw.sendQueue, {\n                [blockId]: data,\n            });\n            Entry.hw.update();\n            setTimeout(() => {\n                scope.timeFlag = 0;\n            });\n            return false;\n        } else if (this.blockIds[this.nowBlockId] && scope.timeFlag === 0) {\n            delete this.blockIds[this.nowBlockId];\n            delete scope.isStart;\n            this.execTimeFlag = 0;\n            this.execTimeFlag = undefined;\n            this.isExecBlock = false;\n            Entry.engine.isContinue = false;\n            return true;\n        }\n        return false;\n    },\n    postCallReturn: function(args) {\n        const { script } = args;\n        if (!this.asyncFlowControl(args, script)) {\n            return Entry.STATIC.BREAK;\n        }\n    },\n};\n\nEntry.AsomeBot.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                asomebot_toggle_led: '파란 LED %1 (Zet보드) %2',\n                asomebot_prepare_led: '키고 끄는 LED 준비 %1',\n                asomebot_prepare_duty_led: '밝기 조절 LED 준비 %1',\n                asomebot_led_color: '키고 끄는 %1 LED %2 %3',\n                asomebot_led_duty: '밝기 조절 %1 LED %2 %3',\n                asomebot_get_ultrasonic_value: '초음파 센서 거리 센서값',\n\n                asomebot_buzzer_open: '부저 켜기 %1',\n                asomebot_buzzer_note: '부저를 %1음으로 %2초 연주하기 %3',\n                asomebot_buzzer_tone: '부저를 %1주파수로 %2초 연주하기 %3',\n                asomebot_buzzer_close: '부저 끄기 %1',\n\n                asomebot_align: '중심잡기 %1 %2 %3 %4 %5',\n                asomebot_home: '차렷 %1',\n                asomebot_angle: '%1번 모터를 %2도로 %3초 동안 회전 %4',\n\n                asomebot_forward: '앞으로 전진 %1',\n                asomebot_forward2: '앞으로 전진 %1 %2 %3',\n\n                asomebot_backward: '뒤로 후진 %1',\n                asomebot_backward2: '뒤로 후진 %1 %2 %3',\n\n                asomebot_turn_left: '왼쪽으로 회전 %1',\n                asomebot_turn_left2: '왼쪽으로 회전 %1 %2',\n\n                asomebot_turn_right: '오른쪽으로 회전 %1',\n                asomebot_turn_right2: '오른쪽으로 회전 %1 %2',\n\n                asomebot_mouse: '발인사하기 %1 %2', // 왼쪽, 오른쪽\n                asomebot_flap: '깡총 뛰기 %1',\n                asomebot_warigari: '트위스트 춤추기 %1',\n                asomebot_tock: '발바닥 까닥하기 %1 %2', // 왼쪽, 오른쪽\n                asomebot_tick_tock: '발목 비틀어서 까닥하기 %1',\n                asomebot_wiggle: '좌우로 흔들 #1 %1',\n                asomebot_swing2: '좌우로 흔들 #2 %1',\n                asomebot_ballet: '발바닥 모으기 %1',\n                asomebot_swing: '발목 비틀어서 발바닥 들기 %1 %2', // 왼쪽(left_swing), 오른쪽(right_swing)\n                asomebot_yaho: '야호 %1',\n                asomebot_moonwalk: '문워크 춤추기 %1',\n\n                internet_connect: '인터넷 연결하기 %1 %2 %3',\n                internet_open_ap: '공유기 모드로 변경하기 %1 %2',\n                internet_open_udp: '%1번 포트로 UDP 소켓 열기 %2',\n                internet_udp_msg: 'UDP 수신값',\n                internet_send_msg: '%1코드로 %2메시지를 전송하기 %3',\n            },\n            Menus: {\n                awesomebot: '어썸봇',\n            },\n        },\n        en: {\n            template: {\n                asomebot_toggle_led: 'Blue LED %1 %2',\n                asomebot_prepare_led: 'Prepare On, Off LED %1',\n                asomebot_prepare_duty_led: 'Prepare adjustable in brightness LED %1',\n                asomebot_led_color: '%1 LED %2 %3',\n                asomebot_led_duty: '%1 LED %2 %3',\n                asomebot_get_ultrasonic_value: 'distance',\n\n                asomebot_buzzer_open: 'Buzzer on %1',\n                asomebot_buzzer_note: 'Play note %1 in %2 sec %3',\n                asomebot_buzzer_tone: 'Mkae sound on %1 Hz in %2 sec %3',\n                asomebot_buzzer_close: 'Buzzer off %1',\n\n                asomebot_align: 'Set align %1 %2 %3 %4 %5',\n                asomebot_home: 'Attention %1',\n                asomebot_angle: 'Set angle of motor %1 to %2 degree in %3 sec %4',\n\n                asomebot_forward: 'Moving forward %1',\n                asomebot_forward2: 'Moving forward %1 %2 %3',\n\n                asomebot_backward: 'Moving backward %1',\n                asomebot_backward2: 'Moving backward %1 %2 %3',\n\n                asomebot_turn_left: 'Turn left %1',\n                asomebot_turn_left2: 'Turn left %1 %2',\n\n                asomebot_turn_right: 'Turn right %1',\n                asomebot_turn_right2: 'Turn right %1 %2',\n\n                asomebot_mouse: 'Greeting %1 %2',\n                asomebot_flap: 'Flap %1',\n                asomebot_warigari: 'Twist %1',\n                asomebot_tock: 'Tock %1 %2',\n                asomebot_tick_tock: 'Tick tock %1',\n                asomebot_wiggle: 'Wiggle %1',\n                asomebot_swing2: 'Swing %1',\n                asomebot_ballet: 'Ballet %1',\n                asomebot_swing: 'Swing %1 %2',\n                asomebot_yaho: 'Yaho %1',\n                asomebot_moonwalk: 'Moonwalk %1',\n\n                internet_connect: 'Connect to internet - %1 %2 %3',\n                internet_open_ap: 'Change to access point mode - %1 %2',\n                internet_open_udp: 'Open UDP socket on post %1 %2',\n                internet_udp_msg: 'UDP message',\n                internet_send_msg: 'Send message %2 to %1 %3',\n            },\n            Menus: {\n                awesomebot: 'AsomeBot',\n            },\n        },\n    };\n};\n\nEntry.AsomeBot.blockMenuBlocks = [\n    'asomebot_toggle_led',\n    'asomebot_prepare_led',\n    'asomebot_prepare_duty_led',\n    'asomebot_led_color',\n    'asomebot_led_duty',\n    'asomebot_get_ultrasonic_value',\n\n    'asomebot_buzzer_open',\n    'asomebot_buzzer_note',\n    'asomebot_buzzer_tone',\n    'asomebot_buzzer_close',\n\n    'asomebot_angle',\n    'asomebot_align',\n    'asomebot_home',\n\n    'asomebot_forward',\n    'asomebot_forward2',\n\n    'asomebot_backward',\n    'asomebot_backward2',\n\n    'asomebot_turn_left',\n    'asomebot_turn_left2',\n\n    'asomebot_turn_right',\n    'asomebot_turn_right2',\n\n    'asomebot_mouse',\n    'asomebot_flap',\n    'asomebot_warigari',\n    'asomebot_tock',\n    'asomebot_tick_tock',\n    'asomebot_wiggle',\n    'asomebot_swing2',\n    'asomebot_ballet',\n    'asomebot_swing',\n    'asomebot_yaho',\n    'asomebot_moonwalk',\n\n    'internet_connect',\n    'internet_open_ap',\n    'internet_open_udp',\n    'internet_udp_msg',\n    'internet_send_msg',\n];\n\nEntry.AsomeBot.getBlocks = function() {\n    return {\n        // Basic\n        asomebot_toggle_led: {\n            template: Lang.template.asomebot_toggle_led,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_toggle_led',\n            },\n            class: 'Basic',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getValue('VALUE');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n\n                    // 어썸보드 built-in LED가 반대로 연결되어 있음\n                    if (value == 'on') {\n                        value = 'off';\n                    } else {\n                        value = 'on';\n                    }\n\n                    sq.msg = format_str('OutputPin(4).{0}()', value);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_prepare_led: {\n            template: Lang.template.asomebot_prepare_led,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_prepare_led',\n            },\n            class: 'Basic',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = 'import battery;battery.exit();r=OutputPin(15);g=OutputPin(13);';\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_prepare_duty_led: {\n            template: Lang.template.asomebot_prepare_duty_led,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_prepare_duty_led',\n            },\n            class: 'Basic',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = 'import battery;battery.exit();r=ServoPin(15);g=ServoPin(13);';\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_led_color: {\n            template: Lang.template.asomebot_led_color,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"Red\", \"r\" ],\n                        [ \"Green\", \"g\" ],\n                    ],\n                    value: 'r',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"On\", \"on\" ],\n                        [ \"Off\", \"off\" ]\n                    ],\n                    value: 'on', \n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    null, null, null\n                ],\n                type: 'asomebot_led_color',\n            },\n            class: 'Basic',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                var value2 = script.getStringValue('VALUE2');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('{0}.{1}()', value1,value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_led_duty: {\n            template: Lang.template.asomebot_led_duty,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"Red\", \"r\" ],\n                        [ \"Green\", \"g\" ],\n                    ],\n                    value: 'r',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: [298],\n                    },\n                    null,\n                ],\n                type: 'asomebot_led_duty',\n            },\n            class: 'Basic',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                var value2 = script.getNumberValue('VALUE2');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('{0}.duty({1})', value1,value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_get_ultrasonic_value: {\n            template: Lang.template.asomebot_get_ultrasonic_value,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_get_ultrasonic_value',\n            },\n            class: 'Basic',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!sprite.old_tick) {\n                    sprite.old_tick = new Date().getTime() - 1000;\n                }\n                var tick = new Date().getTime();\n\n                if (tick - sprite.old_tick > 500) {\n                    sq.msg_id = random_str(16);\n                    sq.msg = \"print('#' + 'DT ' + str(hcsr04.get_distance()) + '  ###')\";\n                    sprite.old_tick = tick;\n                }\n\n                return pd.distance;\n            },\n            syntax: undefined,\n        },\n\n        // Buzzer\n        asomebot_buzzer_open: {\n            template: Lang.template.asomebot_buzzer_open,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_buzzer_open',\n            },\n            class: 'Buzzer',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = 'turnoff_pins( (1, 5, 6, 7, 8) ); import music; music.open(1)';\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_buzzer_note: {\n            template: Lang.template.asomebot_buzzer_note,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['C4'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.3'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_buzzer_note',\n            },\n            class: 'Buzzer',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = parseInt(parseFloat(script.getValue('VALUE2')) * 1000);\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(\"music.note('{0}', {1})\", value1, String(value2));\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_buzzer_tone: {\n            template: Lang.template.asomebot_buzzer_tone,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['400'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.3'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_buzzer_tone',\n            },\n            class: 'Buzzer',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = parseInt(parseFloat(script.getValue('VALUE2')) * 1000);\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('music.tone({0}, {1})', value1, String(value2));\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_buzzer_close: {\n            template: Lang.template.asomebot_buzzer_close,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_buzzer_close',\n            },\n            class: 'Buzzer',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg =\n                        'turnoff_pins( (1, 5, 6, 7, 8) ); import asomebot; asomebot.ready(5, 6, 7,8)';\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n\n        // Moving\n        asomebot_align: {\n            template: Lang.template.asomebot_align,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_align',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                var value3 = script.getValue('VALUE3');\n                var value4 = script.getValue('VALUE4');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(\n                        'asomebot.align({0}, {1}, {2}, {3})',\n                        value1,\n                        value2,\n                        value3,\n                        value4\n                    );\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_home: {\n            template: Lang.template.asomebot_home,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_home',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.home()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_angle: {\n            template: Lang.template.asomebot_angle,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_angle',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                var value3 = parseInt(parseFloat(script.getValue('VALUE3')) * 1000);\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(\n                        'asomebot.angles( [{0}], [{1}], {2})',\n                        value1,\n                        value2,\n                        String(value3)\n                    );\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_forward: {\n            template: Lang.template.asomebot_forward,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_forward',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.forward()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_backward: {\n            template: Lang.template.asomebot_backward,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_backward',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.backward()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_turn_left: {\n            template: Lang.template.asomebot_turn_left,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_turn_left',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.turn_left()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_turn_right: {\n            template: Lang.template.asomebot_turn_right,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_turn_right',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.turn_right()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_forward2: {\n            template: Lang.template.asomebot_forward2,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['150'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_forward2',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.forward(s1={0}, s2={1})', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_backward2: {\n            template: Lang.template.asomebot_backward2,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['150'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_backward2',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.backward(s1={0}, s2={1})', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_turn_left2: {\n            template: Lang.template.asomebot_turn_left2,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_turn_left2',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.turn_left(s={0})', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_turn_right2: {\n            template: Lang.template.asomebot_turn_right2,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'asomebot_turn_right2',\n            },\n            class: 'Moving',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.turn_right(s={0})', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n\n        // Dancing\n        asomebot_mouse: {\n            template: Lang.template.asomebot_mouse,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Left', '1'],\n                        ['Right', '-1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'asomebot_mouse',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getStringField('VALUE');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.mouse({0})', value);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_flap: {\n            template: Lang.template.asomebot_flap,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_flap',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.flap()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_warigari: {\n            template: Lang.template.asomebot_warigari,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_warigari',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.warigari()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_tock: {\n            template: Lang.template.asomebot_tock,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Left', '1'],\n                        ['Right', '-1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'asomebot_tock',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getStringField('VALUE');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.tock({0})', value);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_tick_tock: {\n            template: Lang.template.asomebot_tick_tock,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_tick_tock',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.tick_tock()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_wiggle: {\n            template: Lang.template.asomebot_wiggle,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_wiggle',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.wiggle()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_swing2: {\n            template: Lang.template.asomebot_swing2,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'asomebot_swing2',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.swing()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_ballet: {\n            template: Lang.template.asomebot_ballet,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_ballet',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.ballet()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_yaho: {\n            template: Lang.template.asomebot_yaho,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_yaho',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.yaho()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_swing: {\n            template: Lang.template.asomebot_swing,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Left', '1'],\n                        ['Right', '-1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_swing',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getStringField('VALUE');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    if (value == '1') {\n                        sq.msg = format_str('asomebot.left_swing()');\n                    } else {\n                        sq.msg = format_str('asomebot.right_swing()');\n                    }\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomebot_moonwalk: {\n            template: Lang.template.asomebot_moonwalk,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomebot_moonwalk',\n            },\n            class: 'Dancing',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('asomebot.moonwalk()');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n\n        // Internet\n        internet_connect: {\n            template: Lang.template.internet_connect,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['SSID'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Password'],\n                    },\n                    null,\n                ],\n                type: 'internet_connect',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                var value2 = script.getStringValue('VALUE2');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(\n                        \"import internet; internet.connect('{0}', '{1}')\",\n                        value1,\n                        value2\n                    );\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        internet_open_ap: {\n            template: Lang.template.internet_open_ap,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['SSID'],\n                    },\n                    null,\n                ],\n                type: 'internet_open_ap',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getStringValue('VALUE');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(\"import internet; internet.open_ap('{0}')\", value);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        internet_open_udp: {\n            template: Lang.template.internet_open_udp,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        defaultType: 'number',\n                        params: ['1234'],\n                    },\n                    null,\n                ],\n                type: 'internet_open_udp',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getValue('VALUE');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import udp_socket; udp_socket.open({0})', value);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        internet_udp_msg: {\n            template: Lang.template.internet_udp_msg,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'internet_udp_msg',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!sprite.old_tick) {\n                    sprite.old_id = '';\n                    sprite.old_tick = new Date().getTime() - 1000;\n                }\n                var tick = new Date().getTime();\n\n                if (tick - sprite.old_tick > 300) {\n                    sq.msg_id = random_str(16);\n                    sq.msg = 'udp_socket.read_text()';\n                    sprite.old_tick = tick;\n                }\n\n                if (sprite.old_id != pd.udp_id) {\n                    sprite.old_id = pd.udp_id;\n                    return pd.udp_msg;\n                } else {\n                    return pd.udp_id;\n                }\n            },\n            syntax: undefined,\n        },\n        internet_send_msg: {\n            template: Lang.template.internet_send_msg,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['Code'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Message'],\n                    },\n                    null,\n                ],\n                type: 'internet_send_msg',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeBot'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                var value2 = script.getStringValue('VALUE2');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(\n                        \"import internet; internet.send_msg('{0}', '{1}')\",\n                        value1,\n                        value2\n                    );\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n    };\n};\n\nmodule.exports = Entry.AsomeBot;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_asomekit.js",
    "content": "'use strict';\n\nfunction format_str() {\n    var s = arguments[0];\n    for (var i = 0; i < arguments.length - 1; i++) {\n        var reg = new RegExp('\\\\{' + i + '\\\\}', 'gm');\n        s = s.replace(reg, arguments[i + 1]);\n    }\n    return s;\n}\n\nfunction random_str(count) {\n    var text = '';\n    var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n    for (var i = 0; i < count; i++)\n        text += possible.charAt(Math.floor(Math.random() * possible.length));\n\n    return text;\n}\n\nEntry.AsomeKit = {\n    id: '32.2',\n    name: 'AsomeKit',\n    url: 'http://www.asomeit.com/',\n    imageName: 'AsomeKit.png',\n    title: {\n        ko: 'AsomeKit',\n        en: 'AsomeKit',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    getHashKey: function() {\n        let key = new Date().getSeconds().toString(16);\n        if (key.length === 1) {\n            key += ((Math.random() * 16) | 0).toString(16);\n        }\n        return Entry.generateHash() + key;\n    },\n    asyncFlowControl: function({ script, data }, scope) {\n        if (!this.isExecBlock && !scope.isStart) {\n            const blockId = this.getHashKey();\n            this.isExecBlock = true;\n            scope.isStart = true;\n            scope.timeFlag = 1;\n            this.nowBlockId = blockId;\n            this.blockIds[blockId] = false;\n            _merge(Entry.hw.sendQueue, {\n                [blockId]: data,\n            });\n            Entry.hw.update();\n            setTimeout(() => {\n                scope.timeFlag = 0;\n            });\n            return false;\n        } else if (this.blockIds[this.nowBlockId] && scope.timeFlag === 0) {\n            delete this.blockIds[this.nowBlockId];\n            delete scope.isStart;\n            this.execTimeFlag = 0;\n            this.execTimeFlag = undefined;\n            this.isExecBlock = false;\n            Entry.engine.isContinue = false;\n            return true;\n        }\n        return false;\n    },\n    postCallReturn: function(args) {\n        const { script } = args;\n        if (!this.asyncFlowControl(args, script)) {\n            return Entry.STATIC.BREAK;\n        }\n    },\n};\n\nEntry.AsomeKit.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                asomekit_turnoff_pin: '핀 초기화 %1',\n                \n                asomekit_led_ready: 'LED 준비하기 %1 %2 %3 %4 %5',\n                asomekit_red_led_ready: '빨간색 LED 준비하기 %1 %2',\n                asomekit_yellow_led_ready: '노란색 LED 준비하기 %1 %2',\n                asomekit_green_led_ready: '초록색 LED 준비하기 %1 %2',\n                asomekit_bright_led_ready: '고휘도 LED 준비하기 %1 %2',\n                asomekit_rgb_led_ready: 'RGB LED 준비하기 %1 %2 %3 %4',\n                asomekit_button_ready: '버튼 준비하기 %1 %2',\n                asomekit_music_ready: '음악 준비하기 %1 %2',\n                asomekit_buzzer_ready: '부저 준비하기 %1 %2',\n                asomekit_dht_ready: '온습도 센서 준비하기 %1 %2',\n                asomekit_led_tube_ready: 'LED 튜브 준비하기 %1 %2 %3',\n                asomekit_vibration_ready: '진동 센서 준비하기 %1 %2 %3',\n                asomekit_ultrasound_ready: '초음파 센서 준비하기 %1 %2 %3',\n                asomekit_brightness_ready: '조도 센서 준비하기 %1 %2',\n                asomekit_sound_ready: '소리 센서 준비하기 %1 %2',\n                asomekit_180servo_ready: '180도 서보모터 준비하기 %1 %2',\n                asomekit_360servo_ready: '360도 서보모터 준비하기 %1 %2',\n                asomekit_sound_effect_ready: '효과음 부저 준비하기 %1 %2',\n                asomekit_neopixel_ready: '네오픽셀 준비하기 %1 %2',\n                \n                asomekit_led: '%1 LED %2 %3',\n                asomekit_rgb_brightness: '%1 밝기 설정 %2 %3',\n                asomekit_led_tube: 'LED 튜브에 %1 표시 %2',\n                asomekit_led_tube_time: 'LED 튜브에 시간표시 %1 %2 %3 %4',\n                asomekit_neopixel_off: '네오픽셀 끄기 %1',\n                asomekit_neopixel_on: '네오픽셀 %1 칸 켜기 %2 %3 %4 %5',\n                asomekit_neopixel_all: '네오픽셀 동시에 모두 켜기 %1 %2 %3 %4',\n                asomekit_neopixel_relay: '네오픽셀 순서대로 켜기 %1 %2 %3 %4',\n                asomekit_neopixel_rainbow: '네오픽셀 무지개 켜기 %1 %2',\n\n                asomekit_180servo_angle: '180도 서보모터 각도 변경 %1 %2',\n                asomekit_360servo_off: '360도 서보모터 끄기 %1',\n                asomekit_360servo_duty: '360도 서보모터 켜기 %1',\n                \n                asomekit_ultrasound_measurement: '초음파 센서 거리측정 %1',\n                asomekit_humidity_measurement: '습도 재기 %1',\n                asomekit_temperature_measurement: '온도 재기 %1',\n                asomekit_brightness_measurement: '밝기 재기 %1',\n                asomekit_vibration_detection: '진동 센서 감지 %1',\n                asomekit_button_read: '버튼 정보 읽기 %1',\n                asomekit_sound_measurement: '소리 감지 %1',\n                \n                asomekit_ultrasound_measurement_value: '초음파 센서 측정 거리 값',\n                asomekit_humidity_measurement_value: '습도',\n                asomekit_temperature_measurement_value: '온도',\n                asomekit_brightness_measurement_value: '밝기',\n                asomekit_vibration_detection_value: '진동',\n                asomekit_bt_value: '버튼',\n                asomekit_sound_measurement_value: '소리',\n                \n                asomekit_buzzer_onoff: '부저 %1 %2',\n                asomekit_buzzer_note: '음계로 소리내기 %1 %2 연주시간 %3초 %4',\n                asomekit_buzzer_tone: '주파수로 소리내기 %1Hz 연주시간 %2초 %3',\n                asomekit_sound_effect_play: '효과음 내기 %1 %2',\n                \n                asomekit_input_num: '%1',\n                asomekit_input_text: '\"%1\"',\n                asomekit_variable: '변수 %1 = %2 %3',\n                \n                asomekit_internet_connect: '인터넷 접속하기 | 아이디%1 비밀번호%2 %3',\n                asomekit_wifi_connect: '비밀번호 없는 와이파이 연결하기 | 아이디%1 %2',\n                asomekit_port: '메시지 받을 준비 %1 포트 %2',\n                asomekit_read_message: '메시지 읽어오기 %1',\n                asomekit_send_message: '메시지 보내기 | 보낼 메시지 %1, 보낼 대상%2 %3',\n                asomekit_weather: '날씨 데이터 가져오기 [%1 %2]%3'\n            },\n            Menus: {\n                awesomekit: '어썸키트',\n            },\n        },\n        en: {\n            template: {\n                asomekit_turnoff_pin: 'Turn off pins %1',\n                \n                asomekit_led_ready: 'Prepare LED %1 %2 %3 %4 %5',\n                asomekit_red_led_ready: 'Prepare Red LED %1 %2',\n                asomekit_yellow_led_ready: 'Prepare Yellow LED %1 %2',\n                asomekit_green_led_ready: 'Prepare Green LED %1 %2',\n                asomekit_bright_led_ready: 'Prepare Bright LED %1 %2',\n                asomekit_rgb_led_ready: 'Prepare RGB %1 %2 %3 %4',\n                asomekit_button_ready: 'Prepare button %1 %2',\n                asomekit_music_ready: 'Prepare sound %1 %2',\n                asomekit_buzzer_ready: 'Prepare buzzer %1 %2',\n                asomekit_dht_ready: 'Prepare temperature and humidity sensor %1 %2',\n                asomekit_led_tube_ready: 'Prepare LED tube %1 %2 %3',\n                asomekit_vibration_ready: 'Prepare vibration sensor %1 %2 %3',\n                asomekit_ultrasound_ready: 'Prepare ultrasonic sensor %1 %2 %3',\n                asomekit_brightness_ready: 'Prepare light sensor %1 %2',\n                asomekit_sound_ready: 'Prepare sound sensor %1 %2',\n                asomekit_180servo_ready: 'Prepare 180 Servo %1 %2',\n                asomekit_360servo_ready: 'Prepare 360 Servo %1 %2',\n                asomekit_sound_effect_ready: 'Prepare sound effect %1 %2',\n                asomekit_neopixel_ready: 'Prepare Neopixel %1 %2',\n                \n                asomekit_led: '%1 LED %2 %3',\n                asomekit_rgb_brightness: 'Set brightness of %1 to %2 %3',\n                asomekit_led_tube: 'Display %1 on LED tube %2',\n                asomekit_led_tube_time: 'Display time %1 %2 %3 on LED tube %4',\n                asomekit_neopixel_off: 'Neopixel off %1',\n                asomekit_neopixel_on: 'Neopixel on %1 %2 %3 %4 %5',\n                asomekit_neopixel_all: 'Neopixel all on %1 %2 %3 %4',\n                asomekit_neopixel_relay: 'Neopixel relay on %1 %2 %3 %4',\n                asomekit_neopixel_rainbow: 'Neopixel rainbow %1 %2',\n\n                asomekit_180servo_angle: '180 Servo Angle %1 %2',\n                asomekit_360servo_off: '360 Servo Off %1',\n                asomekit_360servo_duty: '360 Servo On %1',\n                \n                asomekit_ultrasound_measurement: 'Measure distance %1',\n                asomekit_humidity_measurement: 'Measure humidity %1',\n                asomekit_temperature_measurement: 'Measure temperature %1',\n                asomekit_brightness_measurement: 'Check light sensor %1',\n                asomekit_vibration_detection: 'Check vibration sensor %1',\n                asomekit_button_read: 'Check button value %1',\n                asomekit_sound_measurement: 'Check sound sensor %1',\n                \n                asomekit_ultrasound_measurement_value: 'distance',\n                asomekit_humidity_measurement_value: 'humidity',\n                asomekit_temperature_measurement_value: 'temperature',\n                asomekit_brightness_measurement_value: 'brightness',\n                asomekit_vibration_detection_value: 'vibration',\n                asomekit_bt_value: 'button',\n                asomekit_sound_measurement_value: 'sound',\n                \n                asomekit_buzzer_onoff: 'buzzer %1 %2',\n                asomekit_buzzer_note: 'Play %1 %2 for %3 seconds %4',\n                asomekit_buzzer_tone: 'Make sound of %1 for %2 seconds %3',\n                asomekit_sound_effect_play: 'Sound Effect %1 %2',\n\n                asomekit_input_num: '%1',\n                asomekit_input_text: '\"%1\"',\n                asomekit_variable: 'Variable %1 = %2 %3',\n                \n                asomekit_internet_connect: 'internet connect | ID%1PW%2 %3',\n                asomekit_wifi_connect: 'Connecting to Wi-Fi without a password | ID%2 %3',\n                asomekit_port: 'Get Ready to Receive Messages %1 port%2',\n                asomekit_read_message: 'Read Message %1',\n                asomekit_send_message: 'Send Message | Message %1, recipient%2 %3',\n                asomekit_weather: 'Get weater date[%1 %2]%3'\n            },\n            Menus: {\n                awesomekit: 'AsomeKit',\n            },\n        },\n    };\n};\n\nEntry.AsomeKit.blockMenuBlocks = [\n    'asomekit_turnoff_pin',\n    \n    'asomekit_led_ready',\n    'asomekit_red_led_ready',\n    'asomekit_yellow_led_ready',\n    'asomekit_green_led_ready',\n    'asomekit_bright_led_ready',\n    'asomekit_rgb_led_ready',\n    'asomekit_button_ready',\n    'asomekit_music_ready',\n    'asomekit_buzzer_ready',\n    'asomekit_dht_ready',\n    'asomekit_led_tube_ready',\n    'asomekit_vibration_ready',\n    'asomekit_ultrasound_ready',\n    'asomekit_brightness_ready',\n    'asomekit_sound_ready',\n    'asomekit_180servo_ready',\n    'asomekit_360servo_ready',\n    'asomekit_sound_effect_ready',\n    'asomekit_neopixel_ready',\n    \n    'asomekit_led',\n    'asomekit_rgb_brightness',\n    'asomekit_led_tube',\n    'asomekit_led_tube_time',\n    'asomekit_neopixel_off',\n    'asomekit_neopixel_on',\n    'asomekit_neopixel_all',\n    'asomekit_neopixel_relay',\n    'asomekit_neopixel_rainbow',\n\n    'asomekit_180servo_angle',\n    'asomekit_360servo_duty',\n    'asomekit_360servo_off',\n    \n    'asomekit_ultrasound_measurement',\n    'asomekit_humidity_measurement',\n    'asomekit_temperature_measurement',\n    'asomekit_brightness_measurement',\n    'asomekit_vibration_detection',\n    'asomekit_button_read',\n    'asomekit_sound_measurement',\n    \n    'asomekit_ultrasound_measurement_value',\n    'asomekit_humidity_measurement_value',\n    'asomekit_temperature_measurement_value',\n    'asomekit_brightness_measurement_value',\n    'asomekit_vibration_detection_value',\n    'asomekit_bt_value',\n    'asomekit_sound_measurement_value',\n    \n    'asomekit_buzzer_onoff',\n    'asomekit_buzzer_note',\n    'asomekit_buzzer_tone',\n    'asomekit_sound_effect_play',\n    \n    'asomekit_input_num',\n    'asomekit_input_text',\n    'asomekit_variable',\n    \n    'asomekit_internet_connect',\n    'asomekit_wifi_connect',\n    'asomekit_port',\n    'asomekit_read_message',\n    'asomekit_send_message',\n    'asomekit_weather',\n];\n\nEntry.AsomeKit.getBlocks = function() {\n    return {\n        asomekit_turnoff_pin: {\n            template: Lang.template.asomekit_turnoff_pin,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomekit_turnoff_pin',\n            },\n            class: 'PIN',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = 'turnoff_pins()';\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_led_ready: {\n            template: Lang.template.asomekit_led_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['13'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['14'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['15'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_led_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                var value3 = script.getValue('VALUE3');\n                var value4 = script.getValue('VALUE4');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('red = OutputPin({0}); yellow = OutputPin({1}); green = OutputPin({2}); bright = OutputPin({3});', value1, value2, value3, value4);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_red_led_ready: {\n            template: Lang.template.asomekit_red_led_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['13'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_red_led_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('red = OutputPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_yellow_led_ready: {\n            template: Lang.template.asomekit_yellow_led_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['14'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_yellow_led_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('yellow = OutputPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_green_led_ready: {\n            template: Lang.template.asomekit_green_led_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['15'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_green_led_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('green = OutputPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_bright_led_ready: {\n            template: Lang.template.asomekit_bright_led_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_bright_led_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('bright = OutputPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_rgb_led_ready: {\n            template: Lang.template.asomekit_rgb_led_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['17'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['18'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['19'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_rgb_led_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                var value3 = script.getValue('VALUE3');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('r = ServoPin({0}); g = ServoPin({1}); b = ServoPin({2});', value1, value2, value3);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_button_ready: {\n            template: Lang.template.asomekit_button_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_button_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import button; bt = button.create({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_music_ready: {\n            template: Lang.template.asomekit_music_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['12'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_music_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import music; music.open({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_buzzer_ready: {\n            template: Lang.template.asomekit_buzzer_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_buzzer_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('buzzer = OutputPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_dht_ready: {\n            template: Lang.template.asomekit_dht_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_dht_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import dht11; ht = dht11.create({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_led_tube_ready: {\n            template: Lang.template.asomekit_led_tube_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['3'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_led_tube_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import tm1637; tm1637.open({0},{1});', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_vibration_ready: {\n            template: Lang.template.asomekit_vibration_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_vibration_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import vibration_sensor; vs = vibration_sensor.create({0}, {1});', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_ultrasound_ready: {\n            template: Lang.template.asomekit_ultrasound_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_ultrasound_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import hcsr04; hcsr04.open({0}, {1});', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_brightness_ready: {\n            template: Lang.template.asomekit_brightness_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_brightness_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('brightness=AnalogPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_sound_ready: {\n            template: Lang.template.asomekit_sound_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_sound_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('sound_sensor = AnalogPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_180servo_ready: {\n            template: Lang.template.asomekit_180servo_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_180servo_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('servo180 = ServoPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_360servo_ready: {\n            template: Lang.template.asomekit_360servo_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_360servo_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('servo360 = ServoPin({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_sound_effect_ready: {\n            template: Lang.template.asomekit_sound_effect_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['12'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_sound_effect_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import sound_effect; sound_effect.open({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_neopixel_ready: {\n            template: Lang.template.asomekit_neopixel_ready,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_neopixel_ready',\n            },\n            class: 'READY',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import asomeneopixel; asomeneopixel.ready({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        \n        // LED\n        asomekit_led: {\n            template: Lang.template.asomekit_led,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"Red\", \"red\" ],\n                        [ \"Yellow\", \"yellow\" ],\n                        [ \"Green\", \"green\" ],\n                        [ \"Bright\", \"bright\"],\n                    ],\n                    value: 'red',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"On\", \"on\" ],\n                        [ \"Off\", \"off\" ]\n                    ],\n                    value: 'on', \n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    null, null, null\n                ],\n                type: 'asomekit_led',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                var value2 = script.getStringValue('VALUE2');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('{0}.{1}()', value1,value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_rgb_brightness: {\n            template: Lang.template.asomekit_rgb_brightness,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"Red\", \"r\" ],\n                        [ \"Green\", \"g\" ],\n                        [ \"Blue\", \"b\" ],\n                    ],\n                    value: 'r',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_rgb_brightness',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('{0}.duty({1})', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_led_tube: {\n            template: Lang.template.asomekit_led_tube,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_led_tube',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                \n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('tm1637.number({0})', String(value1));\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_led_tube_time: {\n            template: Lang.template.asomekit_led_tube_time,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"True\", \"True\" ],\n                        [ \"False\", \"False\" ],\n                    ],\n                    value: 'True',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['h'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['m'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_led_tube_time',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                var value3 = script.getStringValue('VALUE3');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(\"tm1637.time({0},{1},{2})\", value1, value2, value3);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_neopixel_off: {\n            template: Lang.template.asomekit_neopixel_off,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n            },\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'asomekit_neopixel_off',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(`asomeneopixel.NeoPixel.fill((0,0,0)); asomeneopixel.NeoPixel.write();`,);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_neopixel_on: {\n            template: Lang.template.asomekit_neopixel_on,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"1\", \"0\" ],\n                        [ \"2\", \"1\" ],\n                        [ \"3\", \"2\" ],\n                        [ \"4\", \"3\" ],\n                        [ \"5\", \"4\" ],\n                        [ \"6\", \"5\" ],\n                        [ \"7\", \"6\" ],\n                        [ \"8\", \"7\" ],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n            },\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null\n                ],\n                type: 'asomekit_neopixel_on',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                var value3 = script.getValue('VALUE3');\n                var value4 = script.getValue('VALUE4');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(`asomeneopixel.NeoPixel[{0}] = ({1}, {2}, {3});asomeneopixel.NeoPixel.write();`, value1, value2, value3, value4);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_neopixel_all: {\n            template: Lang.template.asomekit_neopixel_all,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null\n                ],\n                type: 'asomekit_neopixel_all',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                var value3 = script.getValue('VALUE3');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(`a = 'for pixel in range (0, 8):asomeneopixel.NeoPixel[pixel] = ({0}, {1}, {2});asomeneopixel.NeoPixel.write();';exec(a)`, value1, value2, value3);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_neopixel_relay: {\n            template: Lang.template.asomekit_neopixel_relay,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null\n                ],\n                type: 'asomekit_neopixel_relay',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n                var value3 = script.getValue('VALUE3');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(`a = 'for pixel in range (0, 8):asomeneopixel.NeoPixel[pixel] = ({0}, {1}, {2});asomeneopixel.NeoPixel.write();delay(1);';exec(a)`, value1, value2, value3);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_neopixel_rainbow: {\n            template: Lang.template.asomekit_neopixel_rainbow,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null\n                ],\n                type: 'asomekit_neopixel_rainbow',\n            },\n            class: 'LED',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(`asomeneopixel.rainbow(775*{0});`,value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n\n\n        // Servo\n        asomekit_180servo_angle: {\n            template: Lang.template.asomekit_180servo_angle,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_180servo_angle',\n            },\n            class: 'SERVO',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('servo180.angle({0});', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_360servo_off: {\n            template: Lang.template.asomekit_360servo_off,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'asomekit_360servo_off',\n            },\n            class: 'SERVO',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('servo360.off();');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_360servo_duty: {\n            template: Lang.template.asomekit_360servo_duty,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'asomekit_360servo_duty',\n            },\n            class: 'SERVO',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('servo360.duty(250);');\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n\n        asomekit_ultrasound_measurement: {\n            template: Lang.template.asomekit_ultrasound_measurement,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomekit_ultrasound_measurement',\n            },\n            class: 'Measurment',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = \"cm = hcsr04.get_distance(); print('#' + 'CM ' + str(cm) + '  ###')\";\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_humidity_measurement: {\n            template: Lang.template.asomekit_humidity_measurement,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomekit_humidity_measurement',\n            },\n            class: 'Measurment',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = \"ht.measure(); humidity = ht.humidity(); print('#' + 'HD ' + str(humidity) + '  ###')\";\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_temperature_measurement: {\n            template: Lang.template.asomekit_temperature_measurement,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomekit_temperature_measurement',\n            },\n            class: 'Measurment',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = \"ht.measure(); temperature = ht.temperature(); print('#' + 'TP ' + str(temperature) + '  ###')\";\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_brightness_measurement: {\n            template: Lang.template.asomekit_brightness_measurement,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomekit_brightness_measurement',\n            },\n            class: 'Measurment',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = \"light = brightness.read(); print('#' + 'BN ' + str(light) + '  ###')\";\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_button_read: {\n            template: Lang.template.asomekit_button_read,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomekit_button_read',\n            },\n            class: 'Measurment',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = \"bt_value = bt.value(); print('#' + 'BT ' + str(bt_value) + '  ###')\";\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_vibration_detection: {\n            template: Lang.template.asomekit_vibration_detection,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomekit_vibration_detection',\n            },\n            class: 'Measurment',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = \"vibration = vs.is_active(); print('#' + 'VT ' + str(vibration) + '  ###')\";\n                    console.log(pd.vibration);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_sound_measurement: {\n            template: Lang.template.asomekit_sound_measurement,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'asomekit_sound_measurement',\n            },\n            class: 'Measurment',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = \"sound = sound_sensor.read(); print('#' + 'SO ' + str(sound) + '  ###')\";\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_temperature_measurement_value: {\n            template: Lang.template.asomekit_temperature_measurement_value,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'asomekit_temperature_measurement_value',\n            },\n            class: 'Value',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n\n                return pd.temperature;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'temperature',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_brightness_measurement_value: {\n            template: Lang.template.asomekit_brightness_measurement_value,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'asomekit_brightness_measurement_value',\n            },\n            class: 'Value',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n\n                return pd.light;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'light',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_ultrasound_measurement_value: {\n            template: Lang.template.asomekit_ultrasound_measurement_value,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'asomekit_ultrasound_measurement_value',\n            },\n            class: 'Value',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n\n                return pd.cm;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'cm',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_humidity_measurement_value: {\n            template: Lang.template.asomekit_humidity_measurement_value,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'asomekit_humidity_measurement_value',\n            },\n            class: 'Value',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n\n                return pd.humidity;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'humidity',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_vibration_detection_value: {\n            template: Lang.template.asomekit_vibration_detection_value,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'asomekit_vibration_detection_value',\n            },\n            class: 'Value',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                console.log(pd.vibration);\n                return pd.vibration;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'vibration',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_bt_value: {\n            template: Lang.template.asomekit_bt_value,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'asomekit_bt_value',\n            },\n            class: 'Value',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n\n                return pd.bt_value;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'bt_value',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_sound_measurement_value: {\n            template: Lang.template.asomekit_sound_measurement_value,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'asomekit_sound_measurement_value',\n            },\n            class: 'Value',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n\n                return pd.sound;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'sound',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_buzzer_onoff: {\n            template: Lang.template.asomekit_buzzer_onoff,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"On\", \"on\" ],\n                        [ \"Off\", \"off\" ],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    null,null\n                ],\n                type: 'asomekit_buzzer_onoff',\n            },\n            class: 'Buzzer',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('buzzer.{0}()', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_buzzer_note: {\n            template: Lang.template.asomekit_buzzer_note,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"C\", \"C\" ],\n                        [ \"C#\", \"C#\" ],\n                        [ \"D\", \"D\" ],\n                        [ \"D#\", \"D#\" ],\n                        [ \"Db\", \"Db\" ],\n                        [ \"E\", \"E\" ],\n                        [ \"Eb\", \"Eb\" ],\n                        [ \"F\", \"F\" ],\n                        [ \"F#\", \"F#\" ],\n                        [ \"G\", \"G\" ],\n                        [ \"G#\", \"G#\" ],\n                        [ \"Gb\", \"Gb\" ],\n                        [ \"A\", \"A\" ],\n                        [ \"A#\", \"A#\" ],\n                        [ \"Ab\", \"Ab\" ],\n                        [ \"B\", \"B\" ],\n                        [ \"Bb\", \"Bb\" ],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"1\", \"1\" ],\n                        [ \"2\", \"2\" ],\n                        [ \"3\", \"3\" ],\n                        [ \"4\", \"4\" ],\n                        [ \"5\", \"5\" ],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'asomekit_buzzer_note',\n            },\n            class: 'Buzzer',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                var value2 = script.getStringValue('VALUE2');\n                var value3 = parseInt(parseFloat(script.getValue('VALUE3')) * 1000);\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str(\"music.note('{0}{1}', {2})\", value1, value2, String(value3));\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_buzzer_tone: {\n            template: Lang.template.asomekit_buzzer_tone,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'asomekit_buzzer_tone',\n            },\n            class: 'Buzzer',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getValue('VALUE1');\n                var value2 = parseInt(parseFloat(script.getValue('VALUE2')) * 1000);\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('music.tone({0}, {1})', value1, String(value2));\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_sound_effect_play: {\n            template: Lang.template.asomekit_sound_effect_play,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ \"1\", \"level_up\" ],\n                        [ \"2\", \"so_sad\" ],\n                        [ \"3\", \"ariel\" ],\n                        [ \"4\", \"laugh\"],\n                        [ \"5\", \"sad\"],\n                        [ \"6\", \"victory\"],\n                        [ \"7\", \"get_ready\"],\n                    ],\n                    value: 'level_up',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    null, null\n                ],\n                type: 'asomekit_sound_effect_play',\n            },\n            class: 'Buzzer',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value1 = script.getStringValue('VALUE1');\n                    \n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('sound_effect.{0}()', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n\n\n\n\n        asomekit_input_num: {\n            template: Lang.template.asomekit_input_num,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'asomekit_input_num',\n            },\n            class: 'Advance',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var value1 = script.getValue('VALUE1');\n                \n                return '{0}', value1;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'sound',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_input_text: {\n            template: Lang.template.asomekit_input_text,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'asomekit_input_text',\n            },\n            class: 'Advance',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var value1 = script.getValue('VALUE1');\n                \n                return '\"{0}\"', value1;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'sound',\n                        blockType: 'param',\n                    }\n                ]\n            }\n        },\n        asomekit_variable: {\n            template: Lang.template.asomekit_variable,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['i'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'asomekit_variable',\n            },\n            class: 'Advance',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = '{0}={1}';\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_internet_connect: {\n            template: Lang.template.asomekit_internet_connect,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'text',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'text',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: [''],\n                    },\n                    {\n                        type: 'text',\n                        params: [''],\n                    },\n                ],\n                type: 'asomekit_internet_connect',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                \n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import internet; internet.connect(\"{0}\",\"{1}\")', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_wifi_connect: {\n            template: Lang.template.asomekit_wifi_connect,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'text',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: [''],\n                    },\n                ],\n                type: 'asomekit_wifi_connect',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                \n                var value1 = script.getValue('VALUE1');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import internet; internet.open_ap(\"{0}\")', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_port: {\n            template: Lang.template.asomekit_port,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1234'],\n                    },\n                ],\n                type: 'asomekit_port',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                \n                var value1 = script.getValue('VALUE1');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import udp_socket; udp_socket.open({0})', value1);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_read_message: {\n            template: Lang.template.asomekit_read_message,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'asomekit_read_message',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = 'msg = udp_socket.read_text()';\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_send_message: {\n            template: Lang.template.asomekit_send_message,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'text',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: [''],\n                    },\n                    {\n                        type: 'text',\n                        params: [''],\n                    },\n                ],\n                type: 'asomekit_send_message',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                \n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import http_utils; http_utils.send_msg(\"{1}\",\"{0}\")', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n        asomekit_weather: {\n            template: Lang.template.asomekit_weather,\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'text',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'text',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: [''],\n                    },\n                    {\n                        type: 'text',\n                        params: [''],\n                    },\n                ],\n                type: 'asomekit_weather',\n            },\n            class: 'Internet',\n            isNotFor: ['AsomeKit'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                \n                var value1 = script.getValue('VALUE1');\n                var value2 = script.getValue('VALUE2');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    script.msg_id = random_str(16);\n                    sq.msg_id = script.msg_id;\n                    sq.msg = format_str('import internet; weather_data = internet.get_weather(\"{0}}\",\"{1}\"); weather = weather_data[0]; temp = weather_data[1]; humidity = weather_data[2]', value1, value2);\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    return script.callReturn();\n                }\n\n                return script;\n            },\n            syntax: undefined,\n        },\n    };\n};\n\nmodule.exports = Entry.AsomeKit;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_avatarbot.js",
    "content": "'use strict';\n\nEntry.avatarbot = {\n    id: ['64.1'], // 엔트리에서 발급받은 하드웨어 번호를 기술합니다.\n    name: 'avatarbot', // isNotFor 속성과 대소문자까지 정확하게 매치되어야 합니다.\n    url: 'http://avatarmecha.co.kr', // 생략 가능합니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    imageName: 'avatarbot.png', // images/hardware, images/hw 폴더 내에 존재하는 이미지입니다.\n    title: {\n        ko: 'AvatarBot',\n        // en: 'AvatarBot',\n    },\n    /*\n    setZero() { \n\t\t// 엔트리 정지시 하드웨어 초기화 로직\n        Entry.hw.sendQueue.readablePorts = [];\n        for (let port = 0; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n    },\n    */\n   \tsendBuffer: new Array(210).fill(0),\n    avatarBotDataSet : 210,\n    setZero() { \n\t\t// 엔트리 정지시 하드웨어 초기화 로직\n\t\tthis.dataTableReset();\n    },\n    \n    dataTableReset() {\n\t\tthis.sendBuffer.fill(0);\n\t\tEntry.hw.sendQueue.CMD = this.sendBuffer;\n\t\t\n        this.dc_m_index.fill(0);\n        this.buzzer_index = 0;\n        /*\n        Entry.hw.sendQueue.readablePorts = [];\n        // data buffer 23*10 table value.\n        for (let index = 0; index < 230; index++) {\n            Entry.hw.sendQueue[index] = 0;\n            Entry.hw.sendQueue.readablePorts.push(index);\n        }\n        */\n        //\n        \n        var index = Entry.avatarbot.BoardFunType.Info;\n\t\tEntry.hw.sendQueue.CMD[index+0] = 0x99;\n\t\tEntry.hw.sendQueue.CMD[index+1] = 0x01;\n\t\tEntry.hw.sendQueue.CMD[index+2] = 0x01;\n\t\tEntry.hw.sendQueue.CMD[index+3] = Entry.avatarbot.avatarBotDataSet;\n\t\t\n\t\t// pwm. 2~5 pad\n\t\tindex = Entry.avatarbot.BoardFunType.GPIO_PWM_SET;\n\t\tEntry.hw.sendQueue.CMD[index+1] = (Entry.avatarbot.Board_PWM.Freq)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+2] = (Entry.avatarbot.Board_PWM.Freq>>8)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+3] = (Entry.avatarbot.Board_PWM.Freq>>16)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+4] = (Entry.avatarbot.Board_PWM.Resolution)&0xff;\n\t\t\n\t\t// adc\n\t\tindex = Entry.avatarbot.BoardFunType.ADC;\n\t\tEntry.hw.sendQueue.CMD[index+4] = (Entry.avatarbot.Board_ADC.Attenuation_11db)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+5] = (Entry.avatarbot.Board_ADC.Resolution)&0xff;\n\t\t\n        // ir receiver \n        index = Entry.avatarbot.BoardFunType.IR_Remote;\n        Entry.hw.sendQueue.CMD[index+1] = (Entry.avatarbot.Board_IR_Remote.Value)&0xff;\n\t\t\n\t\t// pca9568\n\t\tindex = Entry.avatarbot.BoardFunType.PCA9568;\n\t\tEntry.hw.sendQueue.CMD[index+1] = (Entry.avatarbot.Board_PCA9568.Freq)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+2] = (Entry.avatarbot.Board_PCA9568.Freq>>8)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+3] = (Entry.avatarbot.Board_PCA9568.Freq>>16)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+4] = (Entry.avatarbot.Board_PCA9568.Freq>>24)&0xff;\n\t\t\n\t\tEntry.hw.sendQueue.CMD[index+5] = (Entry.avatarbot.Board_PCA9568.Osci)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+6] = (Entry.avatarbot.Board_PCA9568.Osci>>8)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+7] = (Entry.avatarbot.Board_PCA9568.Osci>>16)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+8] = (Entry.avatarbot.Board_PCA9568.Osci>>24)&0xff;\n\n        this.servo_on.fill(0);\n        this.servo_init.fill(0);\n        this.servo_speed.fill(3);\n\t\t\n        // servo moter\n\t\tfor(var i=0; i<8; i++)\n\t\t{\n\t\t\tindex = Entry.avatarbot.BoardFunType.Servo_M0 + (i*10);\n\t\t\tEntry.hw.sendQueue.CMD[index+1] = (Entry.avatarbot.Board_Servo.Pulse_Min)&0xff;\t\n\t\t\tEntry.hw.sendQueue.CMD[index+2] = (Entry.avatarbot.Board_Servo.Pulse_Min>>8)&0xff;\t\n\t\t\t\n\t\t\tEntry.hw.sendQueue.CMD[index+3] = (Entry.avatarbot.Board_Servo.Pulse_Max)&0xff;\t\n\t\t\tEntry.hw.sendQueue.CMD[index+4] = (Entry.avatarbot.Board_Servo.Pulse_Max>>8)&0xff;\t\n\t\t\t\n\t\t\tEntry.hw.sendQueue.CMD[index+5] = (Entry.avatarbot.Board_Servo.us_Min)&0xff;\t\n\t\t\tEntry.hw.sendQueue.CMD[index+6] = (Entry.avatarbot.Board_Servo.us_Min>>8)&0xff;\t\n\t\t\t\n\t\t\tEntry.hw.sendQueue.CMD[index+7] = (Entry.avatarbot.Board_Servo.us_Max)&0xff;\t\n\t\t\tEntry.hw.sendQueue.CMD[index+8] = (Entry.avatarbot.Board_Servo.us_Max>>8)&0xff;\t\n\n            Entry.hw.sendQueue.CMD[index+9] = (Entry.avatarbot.Board_Servo.angle)&0xff;\n\t\t}\n\t\t\n\t\t// led \n\t\tindex = Entry.avatarbot.BoardFunType.LED_Strip;\n\t\tEntry.hw.sendQueue.CMD[index+2] = (Entry.avatarbot.Board_LED_Strip.led_num)&0xff;\n\t\tEntry.hw.sendQueue.CMD[index+7] = (Entry.avatarbot.Board_LED_Strip.brightness)&0xff;\n\t\t\n        //\n        /*\n        for(var i=0; i<(data.length/10); i++)\n\t\t{\n\t\t\tvar index = i*10;\n\t\t\tconsole.log('[jhkim] setZero - DataSet[', i, ']: ', \n\t\t\t\tEntry.hw.sendQueue.CMD[index+0], ' | ', Entry.hw.sendQueue.CMD[index+1], ' | ', Entry.hw.sendQueue.CMD[index+2], ' | ', \n\t\t\t\tEntry.hw.sendQueue.CMD[index+3], ' | ', Entry.hw.sendQueue.CMD[index+4], ' | ', Entry.hw.sendQueue.CMD[index+5], ' | ', \n\t\t\t\tEntry.hw.sendQueue.CMD[index+6], ' | ', Entry.hw.sendQueue.CMD[index+7], ' | ', Entry.hw.sendQueue.CMD[index+8], ' | ', \n\t\t\t\tEntry.hw.sendQueue.CMD[index+9]);\n\t\t}\n\t\t*/\n        //\n        Entry.hw.update();\n\t},\n    BoardFunType : {\n    \tInfo: 0,\n        Info_isConnect: 5,\n    \tButton:10,\n        OLED:12, // OLED : 12(EN),13(Sample)\n        GPIO_PWM_SET: 20,\n        GPIO_PWM: 30,\n        ADC: 40,\n        IR_Remote: 50,\n        Buzzer: 60,\n        PCA9568: 70,\n        Servo_M0: 80,\n        Servo_M1: 90,\n        Servo_M2: 100,\n        Servo_M3: 110,\n        Servo_M4: 120,\n        Servo_M5: 130,\n        Servo_M6: 140,\n        Servo_M7: 150,\n        DC_M: 160,\n        MPU6050_1: 170,\n        MPU6050_2: 180,\n        LED_Strip: 190,\n        ULTRA_SONIC: 200\n\t},\n\t\n\tBoard_Buttton:{\n\t\tEn: 0,\n\t\tgetValue:0\n\t},\n\t\n\tBoard_GPIO :{\n\t\t// gpio0\n\t\tEn0: 0,\n\t\tType0: 0, // gpio(0), ledc(1), pwm(2)\n\t\tvalue0: 0, //0~255, duty or value\n\t\tgetValue0: 0, // input value\n\t\t\n\t\t// gpio1\n\t\tEn1: 0,\n\t\tType1: 0,\n\t\tvalue1: 0,\n\t\tgetValue1: 0,\n\t},\n\t\n\tBoard_PWM : { // default gpio resolution, freq\n\t\tResolution: 13,\n\t\tFreq: 5000\n\t},\n\t\n\tBoard_ADC : {\n\t\tEn0: 0,\n\t\tgetValue0: 0, // 12bit default. 0 ~ 4095\n\t\tEn1: 0,\n\t\tgetValue1: 0, \n\t\t// common\n\t\tResolution: 12,\n\t\tAttenuation_0db: 0,\n\t\tAttenuation_2_5db: 1,\n\t\tAttenuation_6db: 2,\n\t\tAttenuation_11db: 3 // default db value.\n\t},\n\t\n\tBoard_IR_Remote : {\n\t\tFlag: 0,\n        Value: 0xff,\n        Repeat: 0,\n        Address: 0,\n        Command: 0,\n        Raw_data: 0\n\t},\n\n\tbuzzer_index: 0,\n\tBoard_Buzzer : {\n\t\tEn: 0,\n\t\tsample: 0,\n\t\ttone0: 0,\n\t\ttone1: 0,\n\t\ttone2: 0,\n\t\ttone3: 0,\n\t\ttime0: 0,\n\t\ttone1: 0,\n\t\ttone2: 0,\n\t\ttone3: 0,\n\t},\n\t\n\tBoard_PCA9568 : {\n\t\tOsci: 27000000,\n\t\tFreq: 50\n\t},\n\t\n    // default - sg90\n    servo_on: new Array(8).fill(0),\n    servo_init: new Array(8).fill(0),\n    servo_speed: new Array(8).fill(3),\n\tBoard_Servo : {\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\n\tBoard_Servo_SelectType : {\n\t\t// sg90\n        sg90_us_min: 400,\n\t\tsg90_us_max: 2100,\n        // mg996r\n        mg996r_us_min: 400,\n\t\tmg996r_us_max: 2360,\n\t},\n    //\n\tBoard_Servo_M0 : {\n\t\tEn:0,\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\t\n\tBoard_Servo_M1 : {\n\t\tEn:0,\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\t\n\tBoard_Servo_M2 : {\n\t\tEn:0,\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\t\n\tBoard_Servo_M3 : {\n\t\tEn:0,\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\t\n\tBoard_Servo_M4 : {\n\t\tEn:0,\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\t\n\tBoard_Servo_M5 : {\n\t\tEn:0,\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\t\n\tBoard_Servo_M6 : {\n\t\tEn:0,\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\t\n\tBoard_Servo_M7 : {\n\t\tEn:0,\n\t\tPulse_Min: 150,\n\t\tPulse_Max: 600,\n\t\tus_Min: 400,\n\t\tus_Max: 2100,\n        angle: 90\n\t},\n\t\n    dc_m_index: new Array(4).fill(0),\n\tBoard_DC_M : {\n\t\tEn0:0,\n\t\tCCW0:0,\n\t\tEn1:0,\n\t\tCCW1:0,\n\t\tEn2:0,\n\t\tCCW2:0,\n\t\tEn3:0,\n\t\tCCW3:0\n\t},\n    //\n    dc_lineCar_index: new Array(16).fill(0), // 4(control)*4(index)\n\tdc_lineCar_ir_index: new Array(2).fill(0),\n    //\n\tBoard_MPU6050 : {\n\t\tEn:0,\n\t\t// get value list\n\t\tacceleration_x:0,\n\t\tacceleration_y:0,\n\t\tacceleration_z:0,\n\t\trotation_x:0,\n\t\trotation_y:0,\n\t\trotation_z:0,\n\t\ttemperature:0\n\t},\n\tBoard_LED_Strip : {\n\t\tEn:0,\n\t\tsample: 0,\n\t\tled_num: 64,\n\t\tcolor_order: 0,\n\t\tr: 0,\n\t\tg: 0,\n\t\tb: 0,\n\t\tbrightness:63,\n\t\tset_en: 0,\n\t},\n\t\n\tBoard_ultraSonic : {\n\t\tEn0:0,\n\t\tEn1: 0,\n\t\t// get value\n\t\tch0_cm: 0,\n\t\tch0_inch: 0,\n\t\tch1_cm: 0,\n\t\tch2_inch: 0\n\t},\n    \n\t/*\n    monitorTemplate: {\n        imgPath: 'hardware/avatarbot.png',\n        width: 605,\n        height: 434,\n        listPorts: {\n            '2': {\n                name: `${Lang.Hw.port_en} 2 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '3': {\n                name: `${Lang.Hw.port_en} 3 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '4': {\n                name: `${Lang.Hw.port_en} 4 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '5': {\n                name: `${Lang.Hw.port_en} 5 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '6': {\n                name: `${Lang.Hw.port_en} 6 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '7': {\n                name: `${Lang.Hw.port_en} 7 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '8': {\n                name: `${Lang.Hw.port_en} 8 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '9': {\n                name: `${Lang.Hw.port_en} 9 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '10': {\n                name: `${Lang.Hw.port_en} 10 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '11': {\n                name: `${Lang.Hw.port_en} 11 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '12': {\n                name: `${Lang.Hw.port_en} 12 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '13': {\n                name: `${Lang.Hw.port_en} 13 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: `${Lang.Hw.port_en} A0 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: `${Lang.Hw.port_en} A1 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a2: {\n                name: `${Lang.Hw.port_en} A2 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a3: {\n                name: `${Lang.Hw.port_en} A3 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a4: {\n                name: `${Lang.Hw.port_en} A4 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a5: {\n                name: `${Lang.Hw.port_en} A5 ${Lang.Hw.port_ko}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n    */\n};\n\n// 언어 적용\nEntry.avatarbot.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n\t\t\t\t// global.\n\t\t\t\tavatarbot: 'avatarbot',\n\t\t\t\tavatarbot_text: '%1',\n                avatarbot_get_timer_number: '%1  ',\n\t\t\t    avatarbot_get_adc_dac_sonic_number: '%1  ',\n\t\t\t    avatarbot_get_gpio_dc_number: '%1  ',\n\t\t\t    avatarbot_get_serve_number: '%1  ',\n                avatarbot_get_oled_number: '%1  ',\n\t\t\t    avatarbot_get_pwm_port_number: '%1  ',\n\t\t\t    avatarbot_get_buzzer_tone_number: '%1 ',\n\t\t\t    avatarbot_get_buzzer_time_number: '%1 ',\n                avatarbot_get_servo_speed_number: '%1 ',\n\t\t\t    avatarbot_get_sensor_number: '%1  ',\n\t\t\t    avatarbot_get_port_number: '%1  ',\n\t\t\t    avatarbot_get_digital_toggle: '%1  ',\n\t\t\t    avatarbot_get_pwm_port_number: '%1  ',\n\t\t\t    avatarbot_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n\t\t\t    avatarbot_ext_get_analog_value: '아날로그 %1 번 센서값',\n\t\t\t    avatarbot_ext_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n\t\t\t    avatarbot_ext_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n\t\t\t    avatarbot_ext_toggle_led: '디지털 %1 번 핀 %2 %3',\n\t\t\t    avatarbot_ext_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n\t\t\t    avatarbot_ext_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n\t\t\t    avatarbot_ext_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n\t\t\t    avatarbot_ext_get_digital: '디지털 %1 번 센서값',\n\t\t\t    avatarbot_DC_CW: '정회전',\n    \t\t\tavatarbot_DC_CCW: '역회전',\n                //\n                avatarbot_DC_CAR_F: ' 앞 ',\n    \t\t\tavatarbot_DC_CAR_B: ' 뒷 ',\n                //\n                avatarbot_func_on: '시작',\n    \t\t\tavatarbot_func_off: '정지',\n    \t\t\t//\n                avatarbot_DC_LINECAR_STOP: '정지',\n                avatarbot_DC_LINECAR_RUN: '전진',\n                avatarbot_DC_LINECAR_BACK: '후진',\n                avatarbot_DC_LINECAR_LEFT: '왼쪽',\n                avatarbot_DC_LINECAR_RIGHT: '오른쪽',\n                //\n                avatarbot_DC_LINECAR_DETECTION_BOTH: '라인 둘 다 감지',\n                avatarbot_DC_LINECAR_DETECTION_LEFT: '라인 왼쪽 감지',\n                avatarbot_DC_LINECAR_DETECTION_RIGHT: '라인 오른쪽 감지',\n                avatarbot_DC_LINECAR_DETECTION_NONE: '라인 잃어버림',\n                //\n                avatarbot_servo_type_sg90: 'SG90',\n    \t\t\tavatarbot_servo_type_mg996r: 'MG996R',\n\t\t\t\t//\n\t\t\t   \t// avatarbot_hw_test: 'AvatarBot HW Test %1 번 값 ',\n                //\n                // avatarbot_get_button: '버튼 값 가져오기 ',\n                avatarbot_get_number_sensor_value: '아날로그 %1 번 센서값 가져오기 ', // adc\n                avatarbot_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값 가져오기 ',\n                avatarbot_get_digital_value: '디지털 %1 번 센서값 가져오기 ',\n                avatarbot_toggle_led: 'LED %1 번 핀 %2 ',\n                avatarbot_toggle_pwm: 'PWM %1 번 핀을 %2 % 로 %3 ',\n                //\n                // avatarbot_pca9568: '모터 컨트롤 주파수 %1 와 오실레이터 %2 (으)로 설정 ',\n                avatarbot_servo: '서보 모터 %1 을 %2 속도, PWM 시간(us) %3 ~ %4 로 %5 ° %6 ',\n                avatarbot_servo_sample: '서보 모터 %1 을 %2 속도, %3 로 %4 ° %5 ',\n                avatarbot_dc: 'DC 모터 %1 을 %2 방향으로 %3 % %4 동작 ',\n                avatarbot_robot_arm_on: '로봇 팔 %1(주의! 시작 전 초기 위치에 각 관절을 위치해주세요.)',\n                avatarbot_robot_arm_speed: '로봇 팔 몸통 %1, 팔[축1 %2, 축2 %3], 헤드[축1 %4, 축2 %5], 집게 %6 속도 설정',\n                avatarbot_robot_arm: '로봇 팔 몸통 %1°, 팔[축1 %2°, 축2 %3°], 헤드[축1 %4°, 축2 %5°], 집게 %6° 동작',            \n                avatarbot_dc_car: '자동차 앞[%1 방향, 속도(좌 %2 %, 우 %3 %)], 뒷[%4 방향, 속도(좌 %5 %, 우 %6 %)] %7 동작',\n                //\n                avatarbot_line_car_ir_init: '라인트레이서 좌측 센서 %1 %, 우측 센서 %2 % 감도 설정',\n                avatarbot_line_car_motor_init: '라인트레이서 %1 조건일 때 앞[좌 %2 %, 우 %3 %], 뒷[좌 %4 %, 우 %5 %] 속도 설정',\n                avatarbot_line_car: '라인트레이서 %1',\n                //\n                avatarbot_buzzer_sample: '부저 샘플 %1 %2 초 동안 시작 ',\n                avatarbot_buzzer: '부저 %1 소리로 %2 초 동안 시작 ',\n                //\n                avatarbot_led_strip_sample: 'LED 스트립 샘플 %1 동작',\n                avatarbot_led_strip_set: 'LED 스트립 LED %1 개, 밝기 %2 % 설정 ',\n                avatarbot_led_strip_indexOn: 'LED 스트립 LED %1 번 R %2, G %3, B %4 %5',\n\n                // avatarbot_ir_remote: '리모컨 %1 (으)로 동작 ',\n                avatarbot_get_mpu6050: '자이로 가속도 센서 %1 정보 확인 ',\n                avatarbot_get_mpu6050_detail: '자이로 가속도 센서 %1 의 %2 값 가져오기 ',\n                avatarbot_ultra_sonic:'초음파 %1 번 센서 정보 확인 ',\n                avatarbot_ultra_sonic_detail:'초음파 %1 번 센서 값(%2)',\n                //\n                avatarbot_ir_receiver:'리모컨 %1 모드로 값 가져오기 ',\n\n                avatarbot_oled_sample:'OLED %1 화면으로 %2 ',\n                //\n            },\n            Device: {\n                avatarbot: 'avatarbot',\n            },\n            Menus: {\n                avatarbot: 'avatarbot',\n            },\n        },\n        /*\n        en: {\n            template: {\n                avatarbot_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                avatarbot_get_digital_value: 'Digital %1 Sensor value  ',\n                avatarbot_toggle_led: 'Digital %1 Pin %2 %3',\n                avatarbot_toggle_pwm: 'PWM %1 Pin %2 %3',\n                avatarbot_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n            },\n            Device: {\n                avatarbot: 'avatarbot',\n            },\n            Menus: {\n                avatarbot: 'avatarbot',\n            },\n        },\n        */\n    };\n};\n\n// 엔트리에 등록할 블록들의 블록명 작성\nEntry.avatarbot.blockMenuBlocks = [\n    // hw data 통신 test\n    // 'avatarbot_hw_test',\n    // base block\n    // 'avatarbot_get_button',\n    'avatarbot_get_number_sensor_value',\n    'avatarbot_convert_scale',\n    //\n    'avatarbot_get_digital_value',\n    'avatarbot_toggle_led',\n    'avatarbot_toggle_pwm',\n    //\n    // 'avatarbot_pca9568',\n    'avatarbot_servo',\n    'avatarbot_servo_sample',\n    'avatarbot_dc',\n    'avatarbot_robot_arm_on',\n    'avatarbot_robot_arm_speed',\n    'avatarbot_robot_arm',\n    'avatarbot_dc_car',\n    //\n    'avatarbot_line_car_ir_init',\n    'avatarbot_line_car_motor_init',\n    'avatarbot_line_car',\n    //\n    'avatarbot_buzzer_sample',\n    'avatarbot_buzzer',\n    \n    'avatarbot_led_strip_sample',\n    'avatarbot_led_strip_set',\n    'avatarbot_led_strip_indexOn',\n    // 'avatarbot_led_strip',\n    \n    // 'avatarbot_ir_remote',\n    'avatarbot_get_mpu6050',\n    'avatarbot_get_mpu6050_detail',\n    'avatarbot_ultra_sonic',\n    'avatarbot_ultra_sonic_detail',\n    //\n    'avatarbot_ir_receiver',\n    'avatarbot_oled_sample',\n];\n\n// 블록 생성\nEntry.avatarbot.getBlocks = function() {\n    return {\n\t\t//---------------------------------------------------------------\n        //region avatarbot 아두이노\n        //---------------------------------------------------------------\n        // 공용 function.\n        //---------------------------------------------------------------\n        avatarbot_text: {\n            color: '#FFD974',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['10'],\n            },\n            paramsKeyMap: {\n                NAME: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('NAME');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'TextInput',\n                                value: 10,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'avatarbot_text',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        /*\n        avatarbot_get_sensor_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    // Dropdown 생성 기준은\n                \t// [[\"key1\", \"value1\"], [\"key2\", \"value2\"]]\n                \t// 처럼 구성이 됩니다.\n                    options: [\n                        ['0', 'A0'],\n                        ['1', 'A1'],\n                    ],\n                    value: 'A0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, // 기본 컬러는 EntryStatic.ARROW_COLOR_VARIABLE 입니다.\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', 'A0'],\n                                    ['1', 'A1'],\n                                ],\n                                value: 'A0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_sensor_number',\n                    },\n                ],\n            },\n        },\n        */\n\t   \t//\n        avatarbot_get_buzzer_tone_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    // Dropdown 생성 기준은\n                \t// [[\"key1\", \"value1\"], [\"key2\", \"value2\"]]\n                \t// 처럼 구성이 됩니다.\n                    options: [\n                            ['B0', '0'],\n\t\t\t\t\t\t    ['C1', '1'],\n\t\t\t\t\t\t    ['CS1', '2'],\n\t\t\t\t\t\t    ['D1', '3'],\n\t\t\t\t\t\t    ['DS1', '4'],\n\t\t\t\t\t\t    ['E1', '5'],\n\t\t\t\t\t\t    ['F1', '6'],\n\t\t\t\t\t\t    ['FS1', '7'],\n\t\t\t\t\t\t    ['G1', '8'],\n\t\t\t\t\t\t    ['GS1', '9'],\n\t\t\t\t\t\t    ['A1', '10'],\n\t\t\t\t\t\t    ['AS1', '11'],\n\t\t\t\t\t\t    ['B1', '12'],\n\t\t\t\t\t\t    ['C2', '13'],\n\t\t\t\t\t\t    ['CS2', '14'],\n\t\t\t\t\t\t    ['D2', '15'],\n\t\t\t\t\t\t    ['DS2', '16'],\n\t\t\t\t\t\t    ['E2', '17'],\n\t\t\t\t\t\t    ['F2', '18'],\n\t\t\t\t\t\t    ['FS2', '19'],\n\t\t\t\t\t\t    ['G2', '20'],\n\t\t\t\t\t\t    ['GS2', '21'],\n\t\t\t\t\t\t    ['A2', '22'],\n\t\t\t\t\t\t    ['AS2', '23'],\n\t\t\t\t\t\t    ['B2', '24'],\n\t\t\t\t\t\t    ['C3', '25'],\n\t\t\t\t\t\t    ['CS3', '26'],\n\t\t\t\t\t\t    ['D3', '27'],\n\t\t\t\t\t\t    ['DS3', '28'],\n\t\t\t\t\t\t    ['E3', '29'],\n\t\t\t\t\t\t    ['F3', '30'],\n\t\t\t\t\t\t    ['FS3', '31'],\n\t\t\t\t\t\t    ['G3', '32'],\n\t\t\t\t\t\t    ['GS3', '33'],\n\t\t\t\t\t\t    ['A3', '34'],\n\t\t\t\t\t\t    ['AS3', '35'],\n\t\t\t\t\t\t    ['B3', '36'],\n\t\t\t\t\t\t    ['C4', '37'],\n\t\t\t\t\t\t    ['CS4', '38'],\n\t\t\t\t\t\t    ['D4', '39'],\n\t\t\t\t\t\t    ['DS4', '40'],\n\t\t\t\t\t\t    ['E4', '41'],\n\t\t\t\t\t\t    ['F4', '42'],\n\t\t\t\t\t\t    ['FS4', '43'],\n\t\t\t\t\t\t    ['G4', '44'],\n\t\t\t\t\t\t    ['GS4', '45'],\n\t\t\t\t\t\t    ['A4', '46'],\n\t\t\t\t\t\t    ['AS4', '47'],\n\t\t\t\t\t\t    ['B4', '48'],\n\t\t\t\t\t\t    ['C5', '49'],\n\t\t\t\t\t\t    ['CS5', '50'],\n\t\t\t\t\t\t    ['D5', '51'],\n\t\t\t\t\t\t    ['DS5', '52'],\n\t\t\t\t\t\t    ['E5', '53'],\n\t\t\t\t\t\t    ['F5', '54'],\n\t\t\t\t\t\t    ['FS5', '55'],\n\t\t\t\t\t\t    ['G5', '56'],\n\t\t\t\t\t\t    ['GS5', '57'],\n\t\t\t\t\t\t    ['A5', '58'],\n\t\t\t\t\t\t    ['AS5', '59'],\n\t\t\t\t\t\t    ['B5', '60'],\n\t\t\t\t\t\t    ['C6', '61'],\n\t\t\t\t\t\t    ['CS6', '62'],\n\t\t\t\t\t\t    ['D6', '63'],\n\t\t\t\t\t\t    ['DS6', '64'],\n\t\t\t\t\t\t    ['E6', '65'],\n\t\t\t\t\t\t    ['F6', '66'],\n\t\t\t\t\t\t    ['FS6', '67'],\n\t\t\t\t\t\t    ['G6', '68'],\n\t\t\t\t\t\t    ['GS6', '69'],\n\t\t\t\t\t\t    ['A6', '70'],\n\t\t\t\t\t\t    ['AS6', '71'],\n\t\t\t\t\t\t    ['B6', '72'],\n\t\t\t\t\t\t    ['C7', '73'],\n\t\t\t\t\t\t    ['CS7', '74'],\n\t\t\t\t\t\t    ['D7', '75'],\n\t\t\t\t\t\t    ['DS7', '76'],\n\t\t\t\t\t\t    ['E7', '77'],\n\t\t\t\t\t\t    ['F7', '78'],\n\t\t\t\t\t\t    ['FS7', '79'],\n\t\t\t\t\t\t    ['G7', '80'],\n\t\t\t\t\t\t    ['GS7', '81'],\n\t\t\t\t\t\t    ['A7', '82'],\n\t\t\t\t\t\t    ['AS7', '83'],\n\t\t\t\t\t\t    ['B7', '84'],\n\t\t\t\t\t\t    ['C8', '85'],\n\t\t\t\t\t\t    ['CS8', '86'],\n\t\t\t\t\t\t    ['D8', '87'],\n\t\t\t\t\t\t    ['DS8', '88']\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, // 기본 컬러는 EntryStatic.ARROW_COLOR_VARIABLE 입니다.\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                TONE: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('TONE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t                                    ['B0', '0'],\n\t\t\t\t\t\t\t\t\t    ['C1', '1'],\n\t\t\t\t\t\t\t\t\t    ['CS1', '2'],\n\t\t\t\t\t\t\t\t\t    ['D1', '3'],\n\t\t\t\t\t\t\t\t\t    ['DS1', '4'],\n\t\t\t\t\t\t\t\t\t    ['E1', '5'],\n\t\t\t\t\t\t\t\t\t    ['F1', '6'],\n\t\t\t\t\t\t\t\t\t    ['FS1', '7'],\n\t\t\t\t\t\t\t\t\t    ['G1', '8'],\n\t\t\t\t\t\t\t\t\t    ['GS1', '9'],\n\t\t\t\t\t\t\t\t\t    ['A1', '10'],\n\t\t\t\t\t\t\t\t\t    ['AS1', '11'],\n\t\t\t\t\t\t\t\t\t    ['B1', '12'],\n\t\t\t\t\t\t\t\t\t    ['C2', '13'],\n\t\t\t\t\t\t\t\t\t    ['CS2', '14'],\n\t\t\t\t\t\t\t\t\t    ['D2', '15'],\n\t\t\t\t\t\t\t\t\t    ['DS2', '16'],\n\t\t\t\t\t\t\t\t\t    ['E2', '17'],\n\t\t\t\t\t\t\t\t\t    ['F2', '18'],\n\t\t\t\t\t\t\t\t\t    ['FS2', '19'],\n\t\t\t\t\t\t\t\t\t    ['G2', '20'],\n\t\t\t\t\t\t\t\t\t    ['GS2', '21'],\n\t\t\t\t\t\t\t\t\t    ['A2', '22'],\n\t\t\t\t\t\t\t\t\t    ['AS2', '23'],\n\t\t\t\t\t\t\t\t\t    ['B2', '24'],\n\t\t\t\t\t\t\t\t\t    ['C3', '25'],\n\t\t\t\t\t\t\t\t\t    ['CS3', '26'],\n\t\t\t\t\t\t\t\t\t    ['D3', '27'],\n\t\t\t\t\t\t\t\t\t    ['DS3', '28'],\n\t\t\t\t\t\t\t\t\t    ['E3', '29'],\n\t\t\t\t\t\t\t\t\t    ['F3', '30'],\n\t\t\t\t\t\t\t\t\t    ['FS3', '31'],\n\t\t\t\t\t\t\t\t\t    ['G3', '32'],\n\t\t\t\t\t\t\t\t\t    ['GS3', '33'],\n\t\t\t\t\t\t\t\t\t    ['A3', '34'],\n\t\t\t\t\t\t\t\t\t    ['AS3', '35'],\n\t\t\t\t\t\t\t\t\t    ['B3', '36'],\n\t\t\t\t\t\t\t\t\t    ['C4', '37'],\n\t\t\t\t\t\t\t\t\t    ['CS4', '38'],\n\t\t\t\t\t\t\t\t\t    ['D4', '39'],\n\t\t\t\t\t\t\t\t\t    ['DS4', '40'],\n\t\t\t\t\t\t\t\t\t    ['E4', '41'],\n\t\t\t\t\t\t\t\t\t    ['F4', '42'],\n\t\t\t\t\t\t\t\t\t    ['FS4', '43'],\n\t\t\t\t\t\t\t\t\t    ['G4', '44'],\n\t\t\t\t\t\t\t\t\t    ['GS4', '45'],\n\t\t\t\t\t\t\t\t\t    ['A4', '46'],\n\t\t\t\t\t\t\t\t\t    ['AS4', '47'],\n\t\t\t\t\t\t\t\t\t    ['B4', '48'],\n\t\t\t\t\t\t\t\t\t    ['C5', '49'],\n\t\t\t\t\t\t\t\t\t    ['CS5', '50'],\n\t\t\t\t\t\t\t\t\t    ['D5', '51'],\n\t\t\t\t\t\t\t\t\t    ['DS5', '52'],\n\t\t\t\t\t\t\t\t\t    ['E5', '53'],\n\t\t\t\t\t\t\t\t\t    ['F5', '54'],\n\t\t\t\t\t\t\t\t\t    ['FS5', '55'],\n\t\t\t\t\t\t\t\t\t    ['G5', '56'],\n\t\t\t\t\t\t\t\t\t    ['GS5', '57'],\n\t\t\t\t\t\t\t\t\t    ['A5', '58'],\n\t\t\t\t\t\t\t\t\t    ['AS5', '59'],\n\t\t\t\t\t\t\t\t\t    ['B5', '60'],\n\t\t\t\t\t\t\t\t\t    ['C6', '61'],\n\t\t\t\t\t\t\t\t\t    ['CS6', '62'],\n\t\t\t\t\t\t\t\t\t    ['D6', '63'],\n\t\t\t\t\t\t\t\t\t    ['DS6', '64'],\n\t\t\t\t\t\t\t\t\t    ['E6', '65'],\n\t\t\t\t\t\t\t\t\t    ['F6', '66'],\n\t\t\t\t\t\t\t\t\t    ['FS6', '67'],\n\t\t\t\t\t\t\t\t\t    ['G6', '68'],\n\t\t\t\t\t\t\t\t\t    ['GS6', '69'],\n\t\t\t\t\t\t\t\t\t    ['A6', '70'],\n\t\t\t\t\t\t\t\t\t    ['AS6', '71'],\n\t\t\t\t\t\t\t\t\t    ['B6', '72'],\n\t\t\t\t\t\t\t\t\t    ['C7', '73'],\n\t\t\t\t\t\t\t\t\t    ['CS7', '74'],\n\t\t\t\t\t\t\t\t\t    ['D7', '75'],\n\t\t\t\t\t\t\t\t\t    ['DS7', '76'],\n\t\t\t\t\t\t\t\t\t    ['E7', '77'],\n\t\t\t\t\t\t\t\t\t    ['F7', '78'],\n\t\t\t\t\t\t\t\t\t    ['FS7', '79'],\n\t\t\t\t\t\t\t\t\t    ['G7', '80'],\n\t\t\t\t\t\t\t\t\t    ['GS7', '81'],\n\t\t\t\t\t\t\t\t\t    ['A7', '82'],\n\t\t\t\t\t\t\t\t\t    ['AS7', '83'],\n\t\t\t\t\t\t\t\t\t    ['B7', '84'],\n\t\t\t\t\t\t\t\t\t    ['C8', '85'],\n\t\t\t\t\t\t\t\t\t    ['CS8', '86'],\n\t\t\t\t\t\t\t\t\t    ['D8', '87'],\n\t\t\t\t\t\t\t\t\t    ['DS8', '88']\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_buzzer_tone_number',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_buzzer_time_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n\t\t\t\t\t\t['정지', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                TIME: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('TIME');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t\t\t\t\t\t\t\t\t['정지', '0'],\n\t\t\t                        ['1', '1'],\n\t\t\t                        ['2', '2'],\n\t\t\t                        ['3', '3'],\n\t\t\t                        ['4', '4'],\n\t\t\t                        ['5', '5'],\n\t\t\t                        ['6', '6'],\n\t\t\t                        ['7', '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_buzzer_time_number',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_servo_speed_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n\t\t\t\t\t\t['1단계', '1'],\n                        ['2단계', '2'],\n                        ['3단계', '3'],\n                        ['4단계', '4'],\n                        ['5단계', '5'],\n                        ['6단계', '6'],\n                        ['7단계', '7'],\n                        ['8단계', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('SPEED');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t\t\t\t\t\t\t\t\t['1단계', '1'],\n                                    ['2단계', '2'],\n                                    ['3단계', '3'],\n                                    ['4단계', '4'],\n                                    ['5단계', '5'],\n                                    ['6단계', '6'],\n                                    ['7단계', '7'],\n                                    ['8단계', '8'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_servo_speed_number',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        // get port(module, function) number\n        // - gpio(4), pwm(3), adc(2), dac(2), servo_m(8), dc_m(4), ulrasonic(2) \n        //---------------------------------------------------------------\n        avatarbot_get_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t\t\t                        ['1', '0'],\n\t\t\t                        ['2', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_port_number',\n                    },\n                ],\n            },\n        },\n        //\n        //\n        avatarbot_get_led_strip_type: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    // Dropdown 생성 기준은\n                \t// [[\"key1\", \"value1\"], [\"key2\", \"value2\"]]\n                \t// 처럼 구성이 됩니다.\n                    options: [\n                            ['LPD6803', '0'],\n\t\t\t\t\t\t    ['LPD8806', '1'],\n\t\t\t\t\t\t    ['WS2801', '2'],\n\t\t\t\t\t\t    ['WS2803', '3'],\n\t\t\t\t\t\t    ['SM16716', '4'],\n\t\t\t\t\t\t    ['P9813', '5'],\n\t\t\t\t\t\t    ['APA102', '6'],\n\t\t\t\t\t\t    ['SK9822', '7'],\n\t\t\t\t\t\t    ['SK9822HD', '8'],\n\t\t\t\t\t\t    ['DOTSTAR', '9'],\n\t\t\t\t\t\t    ['DOTSTARHD', '10'],\n\t\t\t\t\t\t    ['APA102HD', '11']\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, // 기본 컬러는 EntryStatic.ARROW_COLOR_VARIABLE 입니다.\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('TYPE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t                                    ['LPD6803', '0'],\n\t\t\t\t\t\t\t\t\t    ['LPD8806', '1'],\n\t\t\t\t\t\t\t\t\t    ['WS2801', '2'],\n\t\t\t\t\t\t\t\t\t    ['WS2803', '3'],\n\t\t\t\t\t\t\t\t\t    ['SM16716', '4'],\n\t\t\t\t\t\t\t\t\t    ['P9813', '5'],\n\t\t\t\t\t\t\t\t\t    ['APA102', '6'],\n\t\t\t\t\t\t\t\t\t    ['SK9822', '7'],\n\t\t\t\t\t\t\t\t\t    ['SK9822HD', '8'],\n\t\t\t\t\t\t\t\t\t    ['DOTSTAR', '9'],\n\t\t\t\t\t\t\t\t\t    ['DOTSTARHD', '10'],\n\t\t\t\t\t\t\t\t\t    ['APA102HD', '11']\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_led_strip_type',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_gpio_dc_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t\t\t                        ['1', '0'],\n\t\t\t                        ['2', '1'],\n\t\t\t                        ['3', '2'],\n\t\t\t                        ['4', '3'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_gpio_dc_number',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_serve_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t\t\t                        ['1', '0'],\n\t\t\t                        ['2', '1'],\n\t\t\t                        ['3', '2'],\n\t\t\t                        ['4', '3'],\n\t\t\t                        ['5', '4'],\n\t\t\t                        ['6', '5'],\n                                    ['7', '6'],\n                                    ['8', '7'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_serve_number',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_oled_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['none', '0'],\n                        ['lines', '1'],\n                        ['rectangles', '2'],\n                        ['fill rectangles', '3'],\n                        ['circles', '4'],\n                        ['fill circles', '5'],\n                        ['round', '6'],\n                        ['fill round', '7'],\n                        ['triangles', '8'],\n                        ['fill triangles', '9'],\n                        ['text', '10'],\n                        ['stylized text', '11'],\n                        ['scroll text', '12'],\n                        ['bitmap', '13'],\n                        ['snow bitmap', '14'],\n                        ['logo text', '15'],\n                        ['image', '16'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t\t\t                        ['none', '0'],\n                                    ['lines', '1'],\n                                    ['rectangles', '2'],\n                                    ['fill rectangles', '3'],\n                                    ['circles', '4'],\n                                    ['fill circles', '5'],\n                                    ['round', '6'],\n                                    ['fill round', '7'],\n                                    ['triangles', '8'],\n                                    ['fill triangles', '9'],\n                                    ['text', '10'],\n                                    ['stylized text', '11'],\n                                    ['scroll text', '12'],\n                                    ['bitmap', '13'],\n                                    ['snow bitmap', '14'],\n                                    ['logo text', '15'],\n                                    ['image', '16'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_oled_number',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_timer_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['정지', '0'],\n                        ['1 초', '1'],\n                        ['2 초', '2'],\n                        ['3 초', '3'],\n                        ['4 초', '4'],\n                        ['5 초', '5'],\n                        ['6 초', '6'],\n                        ['7 초', '7'],\n                        ['8 초', '8'],\n                        ['9 초', '9'],\n                        ['10초', '10'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                TIME: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('TIME');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n\t\t\t                        ['정지', '0'],\n                                    ['1 초', '1'],\n                                    ['2 초', '2'],\n                                    ['3 초', '3'],\n                                    ['4 초', '4'],\n                                    ['5 초', '5'],\n                                    ['6 초', '6'],\n                                    ['7 초', '7'],\n                                    ['8 초', '8'],\n                                    ['9 초', '9'],\n                                    ['10초', '10'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_timer_number',\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        /*\n        avatarbot_get_pwm_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'avatarbot_get_pwm_port_number',\n                    },\n                ],\n            },\n        },\n        */\n        //---------------------------------------------------------------\n        // hw test\n        //---------------------------------------------------------------\n        /*\n        avatarbot_hw_test:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_gpio_dc_number',\n                    },\n                ],\n                type: 'avatarbot_hw_test',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'avatarbot_value',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n                const signal = script.getNumberValue('PORT', script);\n                // console.log(\"avatarbot_hw_test : %d\", Entry.hw.portData[signal]);\n                // console.log(\"avatarbot value test....\");\n                // console.log(\"%d %d\", \twhat, speed);\n                \n                // return Entry.hw.portData[signal];\n                // Entry.hw.update();\n                \n                return Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.GPIO_LED_PWM0+signal];\n                // return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.hw_test(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },     \t\t   \n\t   \t},\n\t   \t*/\n\t   \t//---------------------------------------------------------------\n\t   \t// base function.\n\t   \t//---------------------------------------------------------------\n        /*\n        avatarbot_get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE, //블록 색상\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, //경계선 색상\n            fontColor: '#fff', // 폰트색상 basic_string_field는 기본 색상이 검정색(#000) 입니다.\n            skeleton: 'basic_string_field', // 블록 모양 정의\n            statements: [],\n            params: [\n                \n            ],\n            events: {},\n            def: { // 보여질 블록 정의\n            \t// def의 params의 경우는 초기값을 지정할수 있습니다.\n            \t// TextInput의 경우에도 def > params을 통해 값을 지정할수 있습니다.\n                type: 'avatarbot_get_button', // func name\n            },\n            paramsKeyMap: { // 파라미터를 사용 할때 쓰는 Key값 정의\n                // VALUE: 0,\n            },\n            class: 'avatarbot_button',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) { // 블록 기능정의\n            \tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                let sensorData = Entry.hw.portData.CMD[Entry.avatarbot.BoardFunType.Button+1] == 0 ? 0 : 1;\n                Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.Button+1] = 0;\n                Entry.hw.update();\n            \treturn sensorData;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.get_button()',\n                        blockType: 'param',\n                        textParams: [\n                        ],\n                    },\n                ],\n            },\n        },\n        */\n        //---------------------------------------------------------------\n        avatarbot_get_number_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE, //블록 색상\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, //경계선 색상\n            fontColor: '#fff', // 폰트색상 basic_string_field는 기본 색상이 검정색(#000) 입니다.\n            skeleton: 'basic_string_field', // 블록 모양 정의\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: { // 보여질 블록 정의\n            \t// def의 params의 경우는 초기값을 지정할수 있습니다.\n            \t// TextInput의 경우에도 def > params을 통해 값을 지정할수 있습니다.\n                params: [\n                    {\n                        type: 'avatarbot_get_port_number', // 상단 func 가져와서 사용.\n                    },\n                ],\n                type: 'avatarbot_get_number_sensor_value', // func name\n            },\n            paramsKeyMap: { // 파라미터를 사용 할때 쓰는 Key값 정의\n                VALUE: 0,\n            },\n            class: 'avatarbot_adc',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) { // 블록 기능정의\n\t            if (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                const signal = script.getNumberValue('VALUE', script);\n                let index = (signal*2) + Entry.avatarbot.BoardFunType.ADC;\n                let sensorData_low = Entry.hw.portData.CMD[index + 6]; // low\n                let sensorData_high = Entry.hw.portData.CMD[index + 7]<<8; // high\n                let sensorData = sensorData_low + sensorData_high;\n                \n                Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.ADC + signal] = 1;\n                Entry.hw.update();\n            \t\n                return sensorData;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_number_sensor_value',\n                        params: [\n                            {\n                                type: 'avatarbot_get_port_number',\n                                id: 'bl5e',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['4095'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'avatarbot_convert_scale',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'avatarbot_adc',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n                const value1 = script.getNumberValue('VALUE1', script);\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                let result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.convert_scale(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field', //'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_port_number',\n                    },\n                ],\n                type: 'avatarbot_get_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'avatarbot_gpio_pwm',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                const signal = script.getNumberValue('PORT', script);\n                // return Entry.hw.getDigitalPortValue(signal);\n                let index = (signal*4) + Entry.avatarbot.BoardFunType.GPIO_PWM;\n                let sensorData = Entry.hw.portData.CMD[index+3] == 0 ? 0 : 1; // ch0, ch1 value\n                \n                // digital setting\n                Entry.hw.sendQueue.CMD[index] = 1; // ch en\n                Entry.hw.sendQueue.CMD[index+1] = 0; // duty\n                Entry.hw.sendQueue.CMD[index+2] = 0; // type in(0)\n                Entry.hw.update();\n                \n            \treturn sensorData;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.digitalRead(%1)',\n                        blockType: 'param',\n                        // replaceBlockType: 'avatarbot_ext_get_digital',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, 'on'],\n                        [Lang.Blocks.ARDUINO_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                /*{\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },*/\n                /*\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                */\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_port_number',\n                    },\n                    null,\n                    // null,\n                ],\n                type: 'avatarbot_toggle_led',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                OPERATOR: 1,\n                // RUN:2,\n            },\n            class: 'avatarbot_gpio_pwm',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n                //\n                if (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                const signal = script.getNumberValue('VALUE', script);\n                const operator = script.getField('OPERATOR');\n                // const run = script.getField('RUN');\n                const value = operator == 'on' ? 255 : 0;\n                // const on = run == '1' ? 1 : 0;\n                const on = operator == 'on' ? 1 : 0;\n\n                let index = (signal*4) + Entry.avatarbot.BoardFunType.GPIO_PWM;\n                // let sensorData = Entry.hw.portData.CMD[index+3] == 0 ? 0 : 1; // ch0, ch1 value\n                \n                // digital setting\n                Entry.hw.sendQueue.CMD[index] = on; // 1; // ch en\n                Entry.hw.sendQueue.CMD[index+1] = value; // duty or value\n                Entry.hw.sendQueue.CMD[index+2] = 1; // type out(0)\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.pin_digital(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            /*\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            */\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_toggle_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, 'on'],\n                        [Lang.Blocks.ARDUINO_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_port_number',\n                    },\n                    {\n                        type: 'avatarbot_text',\n                        params: ['50'],\n                    },\n                ],\n                type: 'avatarbot_toggle_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n                RUN:2,\n            },\n            class: 'avatarbot_gpio_pwm',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                const signal = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                const run = script.getField('RUN');\n                const on = run == 'on' ? 1 : 0;\n                \n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n                \n                let index = (signal*4) + Entry.avatarbot.BoardFunType.GPIO_PWM;\n                \n                // digital setting\n                Entry.hw.sendQueue.CMD[index] = on; // 1; // ch en\n                Entry.hw.sendQueue.CMD[index+1] = value; // duty or value : 0 ~ 255\n                Entry.hw.sendQueue.CMD[index+2] = 2; // type pwm(2)\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.set_pin_digital(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        \n        //---------------------------------------------------------------\n        /*\n        avatarbot_pca9568: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_text',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'avatarbot_text',\n                        params: ['27000000'],\n                    },\n                    null,\n                ],\n                type: 'avatarbot_pca9568',\n            },\n            paramsKeyMap: {\n                FREQ: 0,\n                OSC: 1,\n            },\n            class: 'avatarbot_set',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n                const freq = script.getNumberValue('FREQ');\n                const osci = script.getNumberValue('OSC');\n                \n                let index = Entry.avatarbot.BoardFunType.PCA9568;\n                \n                // digital setting\n                Entry.hw.sendQueue.CMD[index] = 1; // PCA9568 en            \n                Entry.hw.sendQueue.CMD[index+1] = (freq)&0xff; // PCA9568 freq0\n                Entry.hw.sendQueue.CMD[index+2] = (freq>>8)&0xff; // PCA9568 freq1\n                Entry.hw.sendQueue.CMD[index+3] = (freq>>16)&0xff; // PCA9568 freq2\n                Entry.hw.sendQueue.CMD[index+4] = (freq>>24)&0xff; // PCA9568 freq3\n                Entry.hw.sendQueue.CMD[index+5] = (osci)&0xff; // PCA9568 osci0\n                Entry.hw.sendQueue.CMD[index+6] = (osci>>8)&0xff; // PCA9568 osci1\n                Entry.hw.sendQueue.CMD[index+7] = (osci>>16)&0xff; // PCA9568 osci2\n                Entry.hw.sendQueue.CMD[index+8] = (osci>>24)&0xff; // PCA9568 osci3\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.set_pca9568(%1 %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        */\n        //---------------------------------------------------------------\n\t\tavatarbot_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_serve_number',\n                    },\n                    {\n                        type: 'avatarbot_get_servo_speed_number', \n                    },\n                    {\n                        type: 'number',\n                        params: ['400'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['2100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'avatarbot_servo',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                SPEED:1,\n                VALUE2: 2,\n                VALUE3: 3,\n                VALUE4: 4,\n                RUN:5,\n            },\n            class: 'avatarbot_serbo',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                const speed = script.getNumberValue('SPEED', script);\n                const signal = script.getNumberValue('VALUE1', script);\n                let us_min = script.getNumberValue('VALUE2', script);\n                let us_max = script.getNumberValue('VALUE3', script);\n                let value = script.getNumberValue('VALUE4', script);\n                const run = script.getField('RUN');\n                const on = run == '1' ? 1 : 0;\n\n                us_min = Math.round(us_min);\n                us_max = Math.round(us_max);\n                value = Math.round(value);\n                \n                us_min = Math.max(us_min, 200); //150  최소 값.\n                us_max = Math.max(us_max, 700); // 600 최소 값.\n                \n                us_min = Math.min(us_min, us_max); // us_min < us_max :: check.\n                us_max = Math.max(us_min, us_max);\n                \n                value = Math.max(value, 0); //150 \n                value = Math.min(value, 180); // 600\n\n                Entry.avatarbot.servo_speed[signal] = speed&0xf;\n\n                let index = (signal*10) + Entry.avatarbot.BoardFunType.Servo_M0; // base+10,20,30,...n\n                \n                // digital setting\n                Entry.hw.sendQueue.CMD[index] = on + (Entry.avatarbot.servo_speed[signal]<<4); // 1; // ch en\n                // Entry.hw.sendQueue.CMD[index+1] = 0; // pulse min low\n                // Entry.hw.sendQueue.CMD[index+2] = 0; // pulse min high\n                // Entry.hw.sendQueue.CMD[index+3] = 0; // pulse max low\n                // Entry.hw.sendQueue.CMD[index+4] = 0; // pulse max high\n                Entry.hw.sendQueue.CMD[index+5] = (us_min)&0xff; // us min low\n                Entry.hw.sendQueue.CMD[index+6] = (us_min>>8)&0xff; // us min high\n                Entry.hw.sendQueue.CMD[index+7] = (us_max)&0xff; // us max low\n                Entry.hw.sendQueue.CMD[index+8] = (us_max>>8)&0xff; // us max high\n                Entry.hw.sendQueue.CMD[index+9] = (value)&0xff; // angle value. 0 ~ 180\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.servo(%1, %2, %3, %4, %5, %6)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n\t\tavatarbot_servo_sample: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_servo_type_sg90, '0'],\n                        [Lang.template.avatarbot_servo_type_mg996r, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_serve_number',\n                    },\n                    {\n                        type: 'avatarbot_get_servo_speed_number',\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'avatarbot_servo_sample',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                SPEED:1,\n                VALUE2: 2,\n                VALUE3: 3,\n                RUN:4,\n            },\n            class: 'avatarbot_serbo_sample',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n\n                const speed = script.getNumberValue('SPEED', script);\n                const signal = script.getNumberValue('VALUE1', script);\n                let servo_type = script.getNumberValue('VALUE2', script);\n                let value = script.getNumberValue('VALUE3', script);\n                const run = script.getField('RUN');\n                const on = run == '1' ? 1 : 0;\n                let us_min = Entry.avatarbot.Board_Servo_SelectType.sg90_us_min;\n                let us_max = Entry.avatarbot.Board_Servo_SelectType.sg90_us_max;\n\n                value = Math.round(value);\n                value = Math.max(value, 0); //150 \n                value = Math.min(value, 180); // 600\n                \n                switch(servo_type)\n                {\n                    case 0: // sg90 servo motor\n                        us_min = Entry.avatarbot.Board_Servo_SelectType.sg90_us_min;\n                        us_max = Entry.avatarbot.Board_Servo_SelectType.sg90_us_max;\n                        break;\n                    case 1: // mg996r servo motor\n                        us_min = Entry.avatarbot.Board_Servo_SelectType.mg996r_us_min;\n                        us_max = Entry.avatarbot.Board_Servo_SelectType.mg996r_us_max;\n                        break;\n                    default:\n                        break;\n                }\n                Entry.avatarbot.servo_speed[signal] = speed&0xf;\n\n                let index = (signal*10) + Entry.avatarbot.BoardFunType.Servo_M0; // base+10,20,30,...n\n                \n                // digital setting\n                // Entry.hw.sendQueue.CMD[index] = on; // 1; // ch en\n                Entry.hw.sendQueue.CMD[index] = on + (Entry.avatarbot.servo_speed[signal]<<4); // 1; // ch en\n                // Entry.hw.sendQueue.CMD[index+1] = 0; // pulse min low\n                // Entry.hw.sendQueue.CMD[index+2] = 0; // pulse min high\n                // Entry.hw.sendQueue.CMD[index+3] = 0; // pulse max low\n                // Entry.hw.sendQueue.CMD[index+4] = 0; // pulse max high\n                Entry.hw.sendQueue.CMD[index+5] = (us_min)&0xff; // us min low\n                Entry.hw.sendQueue.CMD[index+6] = (us_min>>8)&0xff; // us min high\n                Entry.hw.sendQueue.CMD[index+7] = (us_max)&0xff; // us max low\n                Entry.hw.sendQueue.CMD[index+8] = (us_max>>8)&0xff; // us max high\n                Entry.hw.sendQueue.CMD[index+9] = (value)&0xff; // angle value. 0 ~ 180\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.servo_sample(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_servo_type_sg90, '0'],\n                                    [Lang.template.avatarbot_servo_type_mg996r, '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n       \t//---------------------------------------------------------------\n       \tavatarbot_dc: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_DC_CW, '0'],\n                        [Lang.template.avatarbot_DC_CCW, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                /*\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                */\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_gpio_dc_number',\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    // null,\n                    {\n                        type: 'avatarbot_get_timer_number',\n                    },\n                ],\n                type: 'avatarbot_dc',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                // RUN:3,\n                TIME: 3,\n            },\n            class: 'avatarbot_dc',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                // const dc_m = script.getNumberValue('VALUE1', script); // Channel\n                // let cw = script.getNumberValue('VALUE2', script); // cw, ccw\n                // let speed = script.getNumberValue('VALUE3', script); // duty speed\n                // const cw_value = cw == '정회전' ? 1 : 0;\n                const signal = script.getNumberValue('VALUE1', script);\n                let cw = script.getNumberValue('VALUE2', script);\n                let speed = script.getNumberValue('VALUE3', script);\n                // const run = script.getField('RUN');\n                // const on = run == '1' ? 1 : 0;\n                const time = script.getNumberValue('TIME', script);\n                const on = time>0? 1:0; // 100ms ~ 1s = 1, 0ms = 0\n\n                speed = Math.round(speed);\n                speed = Math.max(speed, 0); \n                speed = Math.min(speed, 100);\n                \n                Entry.avatarbot.dc_m_index[signal] += 1;\n                if(Entry.avatarbot.dc_m_index[signal] > 3)\n                {\n                    Entry.avatarbot.dc_m_index[signal] = 0;\n                }\n                \n                if(on == 0)\n                {\n                    Entry.avatarbot.dc_m_index[signal] = 0;\n                }\n\n                let index = (signal*2) + Entry.avatarbot.BoardFunType.DC_M; // base+2,4,6,8\n                \n                // Entry.hw.sendQueue.CMD[index] = (1 + (cw<<4))&0xff; // ch en\n                Entry.hw.sendQueue.CMD[index] = (on + (cw<<1) + (Entry.avatarbot.dc_m_index[signal]<<2) + (time<<4))&0xff; // ch en\n                Entry.hw.sendQueue.CMD[index+1] = speed&0xff;\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.dc(%1, %2, %3, %4)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_DC_CW, '0'],\n\t                        \t\t[Lang.template.avatarbot_DC_CCW, '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            /*\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            */\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_robot_arm_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'avatarbot_robot_arm_on',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'avatarbot_robotArm',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                const on = script.getNumberValue('VALUE1', script);\n\n                //\n                let value =  [90,    180,  180,   90,    0,    0];\n                let us_min = [400,   400,  400,  400,  400,  400];\n                let us_max = [2360, 2360, 2360, 2100, 2100, 2100];\n\n                for (let i = 0; i < 6; i++) {\n                    // Entry.avatarbot.servo_on[i] = on;\n                    Entry.avatarbot.servo_on[i] = 0;\n\n                    value[i] = Math.round(value[i]);\n                    value[i] = Math.max(value[i], 0); //150 \n                    value[i] = Math.min(value[i], 180); // 600\n                    let index = (i*10) + Entry.avatarbot.BoardFunType.Servo_M0; // base+10,20,30,...n\n                    \n                    // digital setting\n                    // Entry.hw.sendQueue.CMD[index] = 1; // 1; // ch en\n                    if(Entry.avatarbot.servo_init[i] == 0)\n                    {\n                        Entry.hw.sendQueue.CMD[index] = Entry.avatarbot.servo_on[i] + (1<<1) + (Entry.avatarbot.servo_speed[i]<<4); // 1; // ch en\n                    }else{\n                        Entry.hw.sendQueue.CMD[index] = Entry.avatarbot.servo_on[i] + (Entry.avatarbot.servo_speed[i]<<4); // 1; // ch en\n                    }\n                    Entry.avatarbot.servo_init[i] = 1;\n                    Entry.hw.sendQueue.CMD[index+5] = (us_min[i])&0xff; // us min low\n                    Entry.hw.sendQueue.CMD[index+6] = (us_min[i]>>8)&0xff; // us min high\n                    Entry.hw.sendQueue.CMD[index+7] = (us_max[i])&0xff; // us max low\n                    Entry.hw.sendQueue.CMD[index+8] = (us_max[i]>>8)&0xff; // us max high\n                    Entry.hw.sendQueue.CMD[index+9] = (value[i])&0xff; // angle value. 0 ~ 180\n                }\n                //\n                Entry.hw.update();\n                /*\n                setTimeout(() => {\n                    for (let i = 0; i < 6; i++) {\n                        Entry.avatarbot.servo_on[i] = on;\n                        value[i] = Math.round(value[i]);\n                        value[i] = Math.max(value[i], 0); //150 \n                        value[i] = Math.min(value[i], 180); // 600\n                        let index = (i*10) + Entry.avatarbot.BoardFunType.Servo_M0; // base+10,20,30,...n\n                        Entry.hw.sendQueue.CMD[index] = Entry.avatarbot.servo_on[i] + (Entry.avatarbot.servo_speed[i]<<4); // 1; // ch en\n                    }\n                    Entry.hw.update();\n                    script.callReturn();\n                }, 3000); // 1000ms = 1초\n                \n                // return script.callReturn();\n                return;\n                */\n\n                if (!script.isStart) {\n                    // 스크립트 시작 플래그 설정\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    \n                    // 3000ms 대기 설정\n                    setTimeout(() => {\n                        script.timeFlag = 0; // 대기 종료\n                    }, 3000);\n                    return script;\n                } else if (script.timeFlag === 1) {\n                    // 대기 중인 경우, 스크립트를 멈춤 상태로 유지\n                    return script;\n                } else {\n                    // 대기 종료 후, 다음 블록 실행\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    for (let i = 0; i < 6; i++) \n                    {\n                        Entry.avatarbot.servo_on[i] = on;\n                        value[i] = Math.round(value[i]);\n                        value[i] = Math.max(value[i], 0);\n                        value[i] = Math.min(value[i], 180);\n                        let index = (i * 10) + Entry.avatarbot.BoardFunType.Servo_M0;\n                        Entry.hw.sendQueue.CMD[index] = Entry.avatarbot.servo_on[i] + (Entry.avatarbot.servo_speed[i] << 4);\n                    }\n                    Entry.hw.update();\n                    return script.callReturn();\n                }\n\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.robot_arm_on(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_robot_arm_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_servo_speed_number',\n                    },\n                    {\n                        type: 'avatarbot_get_servo_speed_number',\n                    },\n                    {\n                        type: 'avatarbot_get_servo_speed_number',\n                    },\n                    {\n                        type: 'avatarbot_get_servo_speed_number',\n                    },\n                    {\n                        type: 'avatarbot_get_servo_speed_number',\n                    },\n                    {\n                        type: 'avatarbot_get_servo_speed_number',\n                    },\n                ],\n                type: 'avatarbot_robot_arm_speed',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n                VALUE6: 5,\n            },\n            class: 'avatarbot_robotArm',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                for (let i = 0; i < 6; i++) {\n                    Entry.avatarbot.servo_speed[i] = script.getNumberValue(`VALUE${i + 1}`, script);\n                    let index = (i*10) + Entry.avatarbot.BoardFunType.Servo_M0; // base+10,20,30,...n\n                    // digital setting\n                    // Entry.hw.sendQueue.CMD[index] = 1; // 1; // ch en\n                    Entry.hw.sendQueue.CMD[index] = Entry.avatarbot.servo_on[i] + (Entry.avatarbot.servo_speed[i]<<4); // 1; // ch en\n                }\n\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.robot_arm_speed(%1, %2, %3, %4, %5, %6)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_robot_arm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['180'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['180'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'avatarbot_robot_arm',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n                VALUE6: 5,\n            },\n            class: 'avatarbot_robotArm',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                // const signal = script.getNumberValue('VALUE1', script);\n                // let us_min = script.getNumberValue('VALUE2', script);\n                // let us_max = script.getNumberValue('VALUE3', script);\n                // const int usMinTable[] = {USMIN, 400, 400};\n                // const int usMaxTable[] = {USMAX, 2100, 2360};\n\n                let value =  [0,       0,    0,    0,    0,    0];\n                let us_min = [400,   400,  400,  400,  400,  400];\n                let us_max = [2360, 2360, 2360, 2100, 2100, 2100];\n\n                for (let i = 0; i < 6; i++) {\n                    value[i] = script.getNumberValue(`VALUE${i + 1}`, script);\n                    value[i] = Math.round(value[i]);\n                    value[i] = Math.max(value[i], 0); //150 \n                    value[i] = Math.min(value[i], 180); // 600\n                    let index = (i*10) + Entry.avatarbot.BoardFunType.Servo_M0; // base+10,20,30,...n\n                    // digital setting\n                    // Entry.hw.sendQueue.CMD[index] = 1; // 1; // ch en\n                    Entry.hw.sendQueue.CMD[index] = Entry.avatarbot.servo_on[i] + (Entry.avatarbot.servo_speed[i]<<4); // 1; // ch en\n                    Entry.hw.sendQueue.CMD[index+5] = (us_min[i])&0xff; // us min low\n                    Entry.hw.sendQueue.CMD[index+6] = (us_min[i]>>8)&0xff; // us min high\n                    Entry.hw.sendQueue.CMD[index+7] = (us_max[i])&0xff; // us max low\n                    Entry.hw.sendQueue.CMD[index+8] = (us_max[i]>>8)&0xff; // us max high\n                    Entry.hw.sendQueue.CMD[index+9] = (value[i])&0xff; // angle value. 0 ~ 180\n                }\n\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.robot_arm(%1, %2, %3, %4, %5, %6)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_dc_car: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                // front\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_DC_CAR_F, '0'],\n                        [Lang.template.avatarbot_DC_CAR_B, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                // back\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_DC_CAR_F, '0'],\n                        [Lang.template.avatarbot_DC_CAR_B, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                // on/off\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    // front\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    // back\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    // on/off\n                    {\n                        type: 'avatarbot_get_timer_number',\n                    },\n                ],\n                type: 'avatarbot_dc_car',\n            },\n            paramsKeyMap: {\n                // front\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                // back\n                VALUE4: 3,\n                VALUE5: 4,\n                VALUE6: 5,\n                // on/off - timer\n                TIME: 6,\n            },\n            class: 'avatarbot_dcCar',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                // const cw_value = cw == '정회전' ? 1 : 0;\n                // const signal = script.getNumberValue('VALUE1', script);\n                let f_cw = script.getNumberValue('VALUE1', script);\n                let f_speed_l = script.getNumberValue('VALUE2', script); // dc_1\n                let f_speed_r = script.getNumberValue('VALUE3', script); // dc_2\n                \n                let b_cw = script.getNumberValue('VALUE4', script);\n                let b_speed_l = script.getNumberValue('VALUE5', script); // dc_1\n                let b_speed_r = script.getNumberValue('VALUE6', script); // dc_2\n\n                // const run = script.getField('RUN');\n                // const on = run == '1' ? 1 : 0;\n                const time = script.getNumberValue('TIME', script);\n                const on = time>0? 1:0; // 100ms ~ 1s = 1, 0ms = 0\n                \n                //\n                f_speed_l = Math.round(f_speed_l);\n                f_speed_l = Math.max(f_speed_l, 0); \n                f_speed_l = Math.min(f_speed_l, 100);\n                //\n                f_speed_r = Math.round(f_speed_r);\n                f_speed_r = Math.max(f_speed_r, 0); \n                f_speed_r = Math.min(f_speed_r, 100);\n                //\n                b_speed_l = Math.round(b_speed_l);\n                b_speed_l = Math.max(b_speed_l, 0); \n                b_speed_l = Math.min(b_speed_l, 100);\n                //\n                b_speed_r = Math.round(b_speed_r);\n                b_speed_r = Math.max(b_speed_r, 0); \n                b_speed_r = Math.min(b_speed_r, 100);\n                //\n                let cw = [0, 0, 0, 0];\n                cw[0] = f_cw;\n                cw[1] = (f_cw==0)?1:0;\n                cw[2] = b_cw;\n                cw[3] = (b_cw==0)?1:0;\n                \n                let index = Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                Entry.hw.sendQueue.CMD[index+1] = f_speed_l&0xff;\n                \n                index = 2 + Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                Entry.hw.sendQueue.CMD[index+1] = f_speed_r&0xff;\n                \n                index = 4 + Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                Entry.hw.sendQueue.CMD[index+1] = b_speed_l&0xff;\n                \n                index = 6 + Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                Entry.hw.sendQueue.CMD[index+1] = b_speed_r&0xff;\n\n                for (let i = 0; i < 4; i++) { // 0 ~ 3\n                    Entry.avatarbot.dc_m_index[i] += 1; // 0 ~ 3 => 1 ~ 4\n                    if(Entry.avatarbot.dc_m_index[i] > 3) \n                    {\n                        Entry.avatarbot.dc_m_index[i] = 0; // 3, 4 => 0\n                    }\n                    \n                    if(on == 0)\n                    {\n                        Entry.avatarbot.dc_m_index[i] = 0; // 0\n                    }\n\n                    index = (i*2) + Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                    // \n                    Entry.hw.sendQueue.CMD[index] = (on + (cw[i]<<1) + (Entry.avatarbot.dc_m_index[i]<<2) + (time<<4))&0xff; // ch en\n                }\n                //\n                // Entry.hw.sendQueue.CMD[index+1] = speed&0xff;\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.dc_car(%1, %2, %3, %4, %5, %6, %7)',\n                        blockType: 'param',\n                        textParams: [\n                            // front\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_DC_CAR_F, '0'],\n\t                        \t\t[Lang.template.avatarbot_DC_CAR_B, '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            // back\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_DC_CAR_F, '0'],\n\t                        \t\t[Lang.template.avatarbot_DC_CAR_B, '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            // on/off - timer\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_line_car_ir_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['30'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['30'],\n                    },\n                ],\n                type: 'avatarbot_line_car_ir_init',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'avatarbot_LineCar',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                let ir1 = script.getNumberValue('VALUE1', script);\n                let ir2 = script.getNumberValue('VALUE2', script);\n                \n                let result = ir1;\n                result = Math.min(100, result);\n                result = Math.max(0, result);\n                Entry.avatarbot.dc_lineCar_ir_index[0] = Math.round(result*4095/100); // 0 ~ 100 -> 0 ~ 4095\n                //\n                result = ir2;\n                result = Math.min(100, result);\n                result = Math.max(0, result);\n                Entry.avatarbot.dc_lineCar_ir_index[1] = Math.round(result*4095/100); // 0 ~ 100 -> 0 ~ 4095\n                \n                // ir adc sensor on\n                // Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.ADC] = 1;\n                // Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.ADC + 1] = 1;\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.dc_lineCar_ir_init(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_line_car_motor_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_DC_LINECAR_DETECTION_BOTH, '0'],\n                        [Lang.template.avatarbot_DC_LINECAR_DETECTION_LEFT, '1'],\n                        [Lang.template.avatarbot_DC_LINECAR_DETECTION_RIGHT, '2'],\n                        [Lang.template.avatarbot_DC_LINECAR_DETECTION_NONE, '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'avatarbot_line_car_motor_init',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'avatarbot_LineCar',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                //\n                let i = 0;\n                let result = 0;\n                let speed = [0, 0, 0, 0];\n                \n                let type = script.getNumberValue('VALUE1', script);\n                speed[0] = script.getNumberValue('VALUE2', script); // f_speed_l\n                speed[1] = script.getNumberValue('VALUE3', script); // f_speed_r\n                speed[2] = script.getNumberValue('VALUE4', script); // b_speed_l\n                speed[3] = script.getNumberValue('VALUE5', script); // b_speed_r\n                \n                let index = type*4; // type = 0 ~ 3 => 0, 4, 8, 12+a\n                for(i=0; i<4; i++)\n                {\n                    result = speed[i];\n                    result = Math.min(100, result);\n                    result = Math.max(0, result);\n                    Entry.avatarbot.dc_lineCar_index[index+i] = result;\n                } \n                //\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.dc_lineCar_motor_init(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_DC_LINECAR_DETECTION_BOTH, '0'],\n                                    [Lang.template.avatarbot_DC_LINECAR_DETECTION_LEFT, '1'],\n                                    [Lang.template.avatarbot_DC_LINECAR_DETECTION_RIGHT, '2'],\n                                    [Lang.template.avatarbot_DC_LINECAR_DETECTION_NONE, '3'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_line_car: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_off, '0'],\n                        [Lang.template.avatarbot_func_on, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                \n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'avatarbot_line_car',\n            },\n            paramsKeyMap: {\n                VALUE1: 0\n            },\n            class: 'avatarbot_LineCar',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                //\n                const lineCar_On = script.getNumberValue('VALUE1', script);\n                \n                if(lineCar_On == 0)\n                {\n                    // stop ir adc sensor\n                    Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.ADC] = 0;\n                    Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.ADC + 1] = 0;\n                    \n                    // stop motor\n                    Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.DC_M] = (0)&0xff; // ch en\n                    Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.DC_M + 2] = (0)&0xff; // ch en\n                    Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.DC_M + 4] = (0)&0xff; // ch en\n                    Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.DC_M + 6] = (0)&0xff; // ch en\n\n                    Entry.hw.update();\n                    return script.callReturn();\n                }\n\n                let i = 0;\n                let ir_index =[0, 0];\n                let ir_sensorData = [0, 0];\n                ir_index[0] = Entry.avatarbot.BoardFunType.ADC;\n                ir_index[1] = Entry.avatarbot.BoardFunType.ADC + 2;\n                for(i=0; i<2; i++)\n                {\n                    let sensorData_low = Entry.hw.portData.CMD[ir_index[i] + 6]; // low\n                    let sensorData_high = Entry.hw.portData.CMD[ir_index[i] + 7]<<8; // high\n                    ir_sensorData[i] = sensorData_low + sensorData_high;\n                }\n\n                // lineCar ir init 에서 on\n                Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.ADC] = 1;\n                Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.ADC + 1] = 1;\n                //\n                const time = 2; // default time set.\n                const on = time>0? 1:0; // 100ms ~ 1s = 1, 0ms = 0\n\n                let f_cw = 0; // 0 = front, 1 = back\n                let b_cw = 0; // 0 = front, 1 = back\n\n                let f_speed_l = 0;\n                let f_speed_r = 0;\n                let b_speed_l = 0;\n                let b_speed_r = 0;\n                \n                if(ir_sensorData[0] > Entry.avatarbot.dc_lineCar_ir_index[0] && ir_sensorData[1] > Entry.avatarbot.dc_lineCar_ir_index[1])\n                {\n                    // 라인 감지\n                    f_cw = 0;\n                    b_cw = 0;\n                    f_speed_l = Entry.avatarbot.dc_lineCar_index[0];\n                    f_speed_r = Entry.avatarbot.dc_lineCar_index[1];\n                    b_speed_l = Entry.avatarbot.dc_lineCar_index[2];\n                    b_speed_r = Entry.avatarbot.dc_lineCar_index[3];\n                }else if(ir_sensorData[0] > Entry.avatarbot.dc_lineCar_ir_index[0]){\n                    // 왼쪽 센서 감지\n                    f_cw = 0;\n                    b_cw = 0;\n                    f_speed_l = Entry.avatarbot.dc_lineCar_index[4];\n                    f_speed_r = Entry.avatarbot.dc_lineCar_index[5];\n                    b_speed_l = Entry.avatarbot.dc_lineCar_index[6];\n                    b_speed_r = Entry.avatarbot.dc_lineCar_index[7];\n                }else if(ir_sensorData[1] > Entry.avatarbot.dc_lineCar_ir_index[1]){\n                    // 오른쪽 센서 감지\n                    f_cw = 0;\n                    b_cw = 0;\n                    f_speed_l = Entry.avatarbot.dc_lineCar_index[8];\n                    f_speed_r = Entry.avatarbot.dc_lineCar_index[9];\n                    b_speed_l = Entry.avatarbot.dc_lineCar_index[10];\n                    b_speed_r = Entry.avatarbot.dc_lineCar_index[11];\n                }else{\n                    // 라인을 잃음.\n                    f_cw = 0;\n                    b_cw = 0;\n                    f_speed_l = Entry.avatarbot.dc_lineCar_index[12];\n                    f_speed_r = Entry.avatarbot.dc_lineCar_index[13];\n                    b_speed_l = Entry.avatarbot.dc_lineCar_index[14];\n                    b_speed_r = Entry.avatarbot.dc_lineCar_index[15];\n                }\n\n                // 백터\n                let cw = [0, 0, 0, 0];\n                cw[0] = f_cw;\n                cw[1] = (f_cw==0)?1:0;\n                cw[2] = b_cw;\n                cw[3] = (b_cw==0)?1:0;\n\n                // speed setting. base = 160\n                let index = Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                Entry.hw.sendQueue.CMD[index+1] = f_speed_l&0xff;\n                \n                index = 2 + Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                Entry.hw.sendQueue.CMD[index+1] = f_speed_r&0xff;\n                \n                index = 4 + Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                Entry.hw.sendQueue.CMD[index+1] = b_speed_l&0xff;\n                \n                index = 6 + Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                Entry.hw.sendQueue.CMD[index+1] = b_speed_r&0xff;\n\n                // dc motor run\n                for (let i = 0; i < 4; i++) { // 0 ~ 3\n                    Entry.avatarbot.dc_m_index[i] += 1; // 0 ~ 3 => 1 ~ 4\n                    if(Entry.avatarbot.dc_m_index[i] > 3) \n                    {\n                        Entry.avatarbot.dc_m_index[i] = 0; // 3, 4 => 0\n                    }\n                    \n                    if(on == 0)\n                    {\n                        Entry.avatarbot.dc_m_index[i] = 0; // 0\n                    }\n\n                    index = (i*2) + Entry.avatarbot.BoardFunType.DC_M; // base+0,2,4,6\n                    // \n                    Entry.hw.sendQueue.CMD[index] = (on + (cw[i]<<1) + (Entry.avatarbot.dc_m_index[i]<<2) + (time<<4))&0xff; // ch en\n                }\n                //\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.dc_lineCar(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n       \t//---------------------------------------------------------------\n        avatarbot_buzzer_sample: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                /*\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                */\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    // null,\n                    {\n                        type: 'avatarbot_get_buzzer_time_number', // 0 ~ 4s\n                    },\n                ],\n                type: 'avatarbot_buzzer_sample',\n            },\n            paramsKeyMap: {\n                // PORT: 0,\n                // VALUE: 0,\n                // RUN:0,\n                TIME:0,\n            },\n            class: 'avatarbot_buzzer',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                let index = Entry.avatarbot.BoardFunType.Buzzer;\n                /*\n                const run = script.getField('RUN');\n                const on = run == '1' ? 1 : 0;\n                */\n                const time = script.getNumberValue('TIME', script);\n                const on = time>0? 1:0; // 100ms ~ 1s = 1, 0ms = 0\n                \n                Entry.avatarbot.buzzer_index += 1;\n                if(Entry.avatarbot.buzzer_index > 7)\n                {\n                    Entry.avatarbot.buzzer_index = 0;\n                }\n                \n                if(on == 0)\n                {\n                    Entry.avatarbot.buzzer_index = 0;\n                }\n                \n                // digital setting\n                // Entry.hw.sendQueue.CMD[index] = on; // 1; // buzzer en\n                Entry.hw.sendQueue.CMD[index] = on + (Entry.avatarbot.buzzer_index<<1) + (time<<4); // 1; // buzzer en\n                Entry.hw.sendQueue.CMD[index+1] = 1; // buzzer sample\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.buzzer_sample()',\n                        textParams: [\n                            /*\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            */\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            // skeleton: 'basic',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                /*\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                */\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_buzzer_tone_number',\n                    },\n                    {\n                        type: 'avatarbot_get_buzzer_time_number', // 0 ~ 4s\n                    },\n                    // null,\n                ],\n                type: 'avatarbot_buzzer',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                // VALUE2: 1,\n                TIME: 1,\n                // RUN: 2,\n\n            },\n            class: 'avatarbot_buzzer',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                const tone = script.getNumberValue('VALUE1');\n                /*\n                const time = script.getNumberValue('VALUE2');\n                const run = script.getField('RUN');\n                const on = run == '1' ? 1 : 0;\n                */\n                const time = script.getNumberValue('TIME', script);\n                const on = time>0? 1:0; // 100ms ~ 1s = 1, 0ms = 0\n                \n                Entry.avatarbot.buzzer_index += 1;\n                if(Entry.avatarbot.buzzer_index > 7)\n                {\n                    Entry.avatarbot.buzzer_index = 0;\n                }\n                \n                if(on == 0)\n                {\n                    Entry.avatarbot.buzzer_index = 0;\n                }\n                \n                let index = Entry.avatarbot.BoardFunType.Buzzer;\n                // digital setting\n                Entry.hw.sendQueue.CMD[index] = on + (Entry.avatarbot.buzzer_index<<1) + (time<<4); // 1; // buzzer en\n                Entry.hw.sendQueue.CMD[index+1] = 0; // buzzer sample\n                Entry.hw.sendQueue.CMD[index+2] = tone; // tone0\n                // Entry.hw.sendQueue.CMD[index+3] = 0; // tone1\n                // Entry.hw.sendQueue.CMD[index+4] = 0; // tone2\n                // Entry.hw.sendQueue.CMD[index+5] = 0; // tone3\n                Entry.hw.sendQueue.CMD[index+6] = time; // time0\n                // Entry.hw.sendQueue.CMD[index+7] = 0; // time1\n                // Entry.hw.sendQueue.CMD[index+8] = 0; // time2\n                // Entry.hw.sendQueue.CMD[index+9] = 0; // time3\n                Entry.hw.update();\n                \n                return script.callReturn();\n                // return tone;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.set_buzzer(%1 %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            /*\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            */\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        /*\n        avatarbot_led_strip: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'avatarbot_led_strip',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'avatarbot_led',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 10);\n                // Entry.hw.setDigitalPortValue(port, value);\n                \n                let index = Entry.avatarbot.BoardFunType.LED_Strip;\n                Entry.hw.sendQueue.CMD[index] = 1; // ch en\n                Entry.hw.sendQueue.CMD[index+1] = value; // sample 0, 1~other...\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.set_led_strip(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        */\n        //---------------------------------------------------------------\n        avatarbot_led_strip_sample: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'avatarbot_led_strip_sample',\n            },\n            paramsKeyMap: {\n                RUN: 0,\n            },\n            class: 'avatarbot_led',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                let index = Entry.avatarbot.BoardFunType.LED_Strip;\n                const run = script.getField('RUN');\n                const on = run == '1' ? 1 : 0;\n\n                Entry.hw.sendQueue.CMD[index] = on; // 1; // ch en\n                Entry.hw.sendQueue.CMD[index+1] = 1; // 0 : not run, sample 1, 1~other...\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.set_led_strip_sample()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        \n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_led_strip_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_text',\n                        params: ['64'],\n                    },\n                    {\n                        type: 'avatarbot_text',\n                        params: ['64'],\n                    },\n                ],\n                type: 'avatarbot_led_strip_set',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n             \tVALUE2: 1,\n            },\n            class: 'avatarbot_led',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                let value = script.getNumberValue('VALUE1'); // led number\n                let brightness = script.getNumberValue('VALUE2'); // brighteness\n                value = Math.round(value);\n                value = Math.max(value, 1);\n                value = Math.min(value, 100);\n                //\n                brightness = Math.round(brightness);\n                brightness = Math.max(brightness, 0);\n                brightness = Math.min(brightness, 100);\n                // Entry.hw.setDigitalPortValue(port, value);\n                \n                let index = Entry.avatarbot.BoardFunType.LED_Strip;\n                Entry.hw.sendQueue.CMD[index] = 1; // ch en\n                Entry.hw.sendQueue.CMD[index+1] = 0; // sample 0, 1~other...\n                Entry.hw.sendQueue.CMD[index+2] = value;\n                Entry.hw.sendQueue.CMD[index+7] = brightness;\n                Entry.hw.sendQueue.CMD[index+8] = 1; // setting enable.\n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.set_led_strip_set(%1 %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_led_strip_indexOn: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'avatarbot_text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'avatarbot_text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'avatarbot_text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'avatarbot_led_strip_indexOn',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n             \tVALUE2: 1,\n                VALUE3: 2,\n             \tVALUE4: 3,\n                RUN: 4,\n            },\n            class: 'avatarbot_led_indexOn',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n\n                //\n                let i = 0;\n                let ledNum = script.getNumberValue('VALUE1'); // led number\n                let ledRGB = [0,0,0];\n                ledRGB[0] = script.getNumberValue('VALUE2'); // Red\n                ledRGB[1] = script.getNumberValue('VALUE3'); // Green\n                ledRGB[2] = script.getNumberValue('VALUE4'); // Blue\n                let on = script.getNumberValue('RUN', script);\n                //\n                ledNum = Math.round(ledNum);\n                ledNum = Math.max(ledNum, 0);\n                ledNum = Math.min(ledNum, 99);\n                \n                if(on == 1)\n                {\n                    for(i=0; i<3; i++)\n                    {\n                        ledRGB[i] = Math.round(ledRGB[i]);\n                        ledRGB[i] = Math.max(ledRGB[i], 0);\n                        ledRGB[i] = Math.min(ledRGB[i], 255);\n                    }    \n                }else{\n                    ledRGB[0] = 0;\n                    ledRGB[1] = 0;\n                    ledRGB[2] = 0;\n                }\n                \n                //\n                let index = Entry.avatarbot.BoardFunType.LED_Strip;\n                \n                Entry.hw.sendQueue.CMD[index] = 1; // 1; // led strip on\n                Entry.hw.sendQueue.CMD[index+1] = 2; // sample type 2\n                Entry.hw.sendQueue.CMD[index+3] = ledNum; // led number.\n                Entry.hw.sendQueue.CMD[index+4] = ledRGB[0]; // red\n                Entry.hw.sendQueue.CMD[index+5] = ledRGB[1]; // green\n                Entry.hw.sendQueue.CMD[index+6] = ledRGB[2]; // blue\n                \n                Entry.hw.update();\n                \n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.set_led_strip_indexOn(%1 %2 %3 %4 %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                                defaultType: 'number',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        \n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_mpu6050: {\n            color: EntryStatic.colorSet.block.default.HARDWARE, //블록 색상\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, //경계선 색상\n            fontColor: '#fff', // 폰트색상 basic_string_field는 기본 색상이 검정색(#000) 입니다.\n            skeleton: 'basic_string_field', // 블록 모양 정의\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Acceleration', '0'],\n                        ['Rotation', '1'],\n                        ['Temperature', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: { // 보여질 블록 정의\n            \t// def의 params의 경우는 초기값을 지정할수 있습니다.\n            \t// TextInput의 경우에도 def > params을 통해 값을 지정할수 있습니다.\n            \tparams: [\n                    null,\n                ],\n                type: 'avatarbot_get_mpu6050', // func name\n            },\n            paramsKeyMap: { // 파라미터를 사용 할때 쓰는 Key값 정의\n                VALUE: 0,\n            },\n            class: 'avatarbot_mpu',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) { // 블록 기능정의\n            \tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n\t            // 해당 값을 getField, getValue로 가져오고\n\t            // 가져 올때 paramsKeyMap에서\n\t            // 정의한 VALUE라는 키값으로 데이터를 가져옵니다.\n                // const signal = script.getValue('VALUE', script);\n                // return Entry.hw.getAnalogPortValue(signal[1]);\n                const type = script.getNumberValue('VALUE', script);\n                let index = Entry.avatarbot.BoardFunType.MPU6050_1;\n                // 가속도 값\n                let acceleration_x = ((Entry.hw.portData.CMD[index+1]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+1]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+2]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+2];\n                let acceleration_y = ((Entry.hw.portData.CMD[index+3]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+3]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+4]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+4];\n                let acceleration_z = ((Entry.hw.portData.CMD[index+5]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+5]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+6]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+6];\n                let temperature = ((Entry.hw.portData.CMD[index+7]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+7]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+8]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+8];\n                //\n                index = Entry.avatarbot.BoardFunType.MPU6050_2;\n                // 회전값\n                let rotation_x = ((Entry.hw.portData.CMD[index+1]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+1]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+2]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+2];\n                let rotation_y = ((Entry.hw.portData.CMD[index+3]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+3]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+4]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+4];\n                let rotation_z = ((Entry.hw.portData.CMD[index+5]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+5]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+6]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+6];\n                \n                // let mpu6050 = `Acceleration X: ${acceleration_x}, Y: ${acceleration_y}, Z: ${acceleration_z} m/s^2\\nRotation X: ${rotation_x}, Y: ${rotation_y}, Z: ${rotation_z} rad/s\\nTemperature: ${temperature} degC`;\n\t\t\t\tlet mpu6050 = \"\";\n\t\t\t\tif(type == 0){\n\t\t\t\t\tmpu6050 = `Acceleration X: ${acceleration_x}, Y: ${acceleration_y}, Z: ${acceleration_z} m/s^2`;\n\t\t\t\t}else if(type == 1){\n\t\t\t\t\tmpu6050 = `Rotation X: ${rotation_x}, Y: ${rotation_y}, Z: ${rotation_z} rad/s`;\n\t\t\t\t}else if(type == 2){\n\t\t\t\t\tmpu6050 = `Temperature: ${temperature} degC`;\n\t\t\t\t}\n\t\t\t\t\n                // \n                index = Entry.avatarbot.BoardFunType.MPU6050_1;\n                Entry.hw.sendQueue.CMD[index] = 1; // ch en\n                Entry.hw.update();\n                \n                return mpu6050;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.get_mpu6050()',\n                        blockType: 'param',\n                        textParams: [\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_get_mpu6050_detail: {\n            color: EntryStatic.colorSet.block.default.HARDWARE, //블록 색상\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, //경계선 색상\n            fontColor: '#fff', // 폰트색상 basic_string_field는 기본 색상이 검정색(#000) 입니다.\n            skeleton: 'basic_string_field', // 블록 모양 정의\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Acceleration', '0'],\n                        ['Rotation', '1'],\n                        // ['Temperature', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', '0'],\n                        ['y', '1'],\n                        ['z', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: { // 보여질 블록 정의\n            \t// def의 params의 경우는 초기값을 지정할수 있습니다.\n            \t// TextInput의 경우에도 def > params을 통해 값을 지정할수 있습니다.\n            \tparams: [\n                    null,\n                ],\n                type: 'avatarbot_get_mpu6050_detail', // func name\n            },\n            paramsKeyMap: { // 파라미터를 사용 할때 쓰는 Key값 정의\n                VALUE1: 0,\n                VALUE2: 1,\n                \n            },\n            class: 'avatarbot_mpu',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) { // 블록 기능정의\n            \tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n\t            // 해당 값을 getField, getValue로 가져오고\n\t            // 가져 올때 paramsKeyMap에서\n\t            // 정의한 VALUE라는 키값으로 데이터를 가져옵니다.\n                // const signal = script.getValue('VALUE', script);\n                // return Entry.hw.getAnalogPortValue(signal[1]);\n                const type = script.getNumberValue('VALUE1', script);\n                let index = Entry.avatarbot.BoardFunType.MPU6050_1;\n                // 가속도 값\n                let acceleration_x = ((Entry.hw.portData.CMD[index+1]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+1]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+2]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+2];\n                let acceleration_y = ((Entry.hw.portData.CMD[index+3]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+3]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+4]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+4];\n                let acceleration_z = ((Entry.hw.portData.CMD[index+5]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+5]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+6]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+6];\n                // let temperature = ((Entry.hw.portData.CMD[index+7]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+7]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+8]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+8];\n                //\n                index = Entry.avatarbot.BoardFunType.MPU6050_2;\n                // 회전값\n                let rotation_x = ((Entry.hw.portData.CMD[index+1]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+1]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+2]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+2];\n                let rotation_y = ((Entry.hw.portData.CMD[index+3]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+3]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+4]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+4];\n                let rotation_z = ((Entry.hw.portData.CMD[index+5]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+5]&0x7f) +\".\"+ ((Entry.hw.portData.CMD[index+6]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+6];\n                \n                // let mpu6050 = `Acceleration X: ${acceleration_x}, Y: ${acceleration_y}, Z: ${acceleration_z} m/s^2\\nRotation X: ${rotation_x}, Y: ${rotation_y}, Z: ${rotation_z} rad/s\\nTemperature: ${temperature} degC`;\n\t\t\t\tlet mpu6050 = \"\";\n                const unit = script.getNumberValue('VALUE2', script);\n\n\t\t\t\tif(type == 0){\n\t\t\t\t\t// mpu6050 = `Acceleration X: ${acceleration_x}, Y: ${acceleration_y}, Z: ${acceleration_z} m/s^2`;\n                    if(unit == 0)\n                    {\n                        mpu6050 = `${acceleration_x}`;\n                    }else if(unit == 1){\n                        mpu6050 = `${acceleration_y}`;\n                    }else if(unit == 2){\n                        mpu6050 = `${acceleration_z}`;\n                    }\n\t\t\t\t}else if(type == 1){\n\t\t\t\t\t// mpu6050 = `Rotation X: ${rotation_x}, Y: ${rotation_y}, Z: ${rotation_z} rad/s`;\n                    if(unit == 0)\n                    {\n                        mpu6050 = `${rotation_x}`;\n                    }else if(unit == 1){\n                        mpu6050 = `${rotation_y}`;\n                    }else if(unit == 2){\n                        mpu6050 = `${rotation_z}`;\n                    }\n\t\t\t\t}else if(type == 2){\n\t\t\t\t\t// mpu6050 = `Temperature: ${temperature} degC`;\n\t\t\t\t}\n\t\t\t\t\n                // \n                index = Entry.avatarbot.BoardFunType.MPU6050_1;\n                Entry.hw.sendQueue.CMD[index] = 1; // ch en\n                Entry.hw.update();\n                \n                return mpu6050;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.get_mpu6050_detail(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_ultra_sonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE, //블록 색상\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, //경계선 색상\n            fontColor: '#fff', // 폰트색상 basic_string_field는 기본 색상이 검정색(#000) 입니다.\n            skeleton: 'basic_string_field', // 블록 모양 정의\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: { // 보여질 블록 정의\n            \t// def의 params의 경우는 초기값을 지정할수 있습니다.\n            \t// TextInput의 경우에도 def > params을 통해 값을 지정할수 있습니다.\n                params: [\n                    {\n                        type: 'avatarbot_get_port_number', // 상단 func 가져와서 사용.\n                    },\n                ],\n                type: 'avatarbot_ultra_sonic', // func name\n            },\n            paramsKeyMap: { // 파라미터를 사용 할때 쓰는 Key값 정의\n                VALUE: 0,\n            },\n            class: 'avatarbot_sonic',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) { // 블록 기능정의\n            \tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n\t            // 해당 값을 getField, getValue로 가져오고\n\t            // 가져 올때 paramsKeyMap에서\n\t            // 정의한 VALUE라는 키값으로 데이터를 가져옵니다.\n                const signal = script.getNumberValue('VALUE');\n                let index = (signal*5) + Entry.avatarbot.BoardFunType.ULTRA_SONIC;\n                let cm = ((Entry.hw.portData.CMD[index+1]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+1]&0x7f) +\".\" + ((Entry.hw.portData.CMD[index+2]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+2];\n                let inch = ((Entry.hw.portData.CMD[index+3]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+3]&0x7f) +\".\" + ((Entry.hw.portData.CMD[index+4]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+4];\n                \n                Entry.hw.sendQueue.CMD[index] = 1; // ch en\n                Entry.hw.update();\n                \n                let sonic = `${cm} cm, ${inch} inch`;\n                return sonic;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.get_ultra_sonic(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n       \t//---------------------------------------------------------------\n           avatarbot_ultra_sonic_detail: {\n            color: EntryStatic.colorSet.block.default.HARDWARE, //블록 색상\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, //경계선 색상\n            fontColor: '#fff', // 폰트색상 basic_string_field는 기본 색상이 검정색(#000) 입니다.\n            skeleton: 'basic_string_field', // 블록 모양 정의\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['cm', '0'],\n                        ['inch', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: { // 보여질 블록 정의\n            \t// def의 params의 경우는 초기값을 지정할수 있습니다.\n            \t// TextInput의 경우에도 def > params을 통해 값을 지정할수 있습니다.\n                params: [\n                    {\n                        type: 'avatarbot_get_port_number', // 상단 func 가져와서 사용.\n                    },\n                    null\n                ],\n                type: 'avatarbot_ultra_sonic_detail', // func name\n            },\n            paramsKeyMap: { // 파라미터를 사용 할때 쓰는 Key값 정의\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'avatarbot_sonic',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) { // 블록 기능정의\n            \tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n\t            // 해당 값을 getField, getValue로 가져오고\n\t            // 가져 올때 paramsKeyMap에서\n\t            // 정의한 VALUE라는 키값으로 데이터를 가져옵니다.\n                const signal = script.getNumberValue('VALUE1');\n                let index = (signal*5) + Entry.avatarbot.BoardFunType.ULTRA_SONIC;\n                let cm = ((Entry.hw.portData.CMD[index+1]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+1]&0x7f) +\".\" + ((Entry.hw.portData.CMD[index+2]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+2];\n                let inch = ((Entry.hw.portData.CMD[index+3]&0x80)==0?\"\":\"-\") + (Entry.hw.portData.CMD[index+3]&0x7f) +\".\" + ((Entry.hw.portData.CMD[index+4]>9)?\"\":\"0\") + Entry.hw.portData.CMD[index+4];\n                \n                Entry.hw.sendQueue.CMD[index] = 1; // ch en\n                Entry.hw.sendQueue.CMD[index+1] = Entry.hw.portData.CMD[index+1];\n                Entry.hw.sendQueue.CMD[index+2] = Entry.hw.portData.CMD[index+2];\n                Entry.hw.sendQueue.CMD[index+3] = Entry.hw.portData.CMD[index+3];\n                Entry.hw.sendQueue.CMD[index+4] = Entry.hw.portData.CMD[index+4];\n                Entry.hw.update();\n                //\n                let sonic = ``;\n                const type = script.getNumberValue('VALUE2', script);\n                if(type == 0){\n\t\t\t\t\tsonic = `${cm}`;\n\t\t\t\t}else if(type == 1){\n\t\t\t\t\tsonic = `${inch}`;\n\t\t\t\t}\n                \n                return sonic;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.get_ultra_sonic_detail(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n       \t//---------------------------------------------------------------\n        avatarbot_ir_receiver: {\n            color: EntryStatic.colorSet.block.default.HARDWARE, //블록 색상\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, //경계선 색상\n            fontColor: '#fff', // 폰트색상 basic_string_field는 기본 색상이 검정색(#000) 입니다.\n            skeleton: 'basic_string_field', // 블록 모양 정의\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['기본', '0'],\n                        ['상세', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: { // 보여질 블록 정의\n            \t// def의 params의 경우는 초기값을 지정할수 있습니다.\n            \t// TextInput의 경우에도 def > params을 통해 값을 지정할수 있습니다.\n                params: [\n                    null,\n                ],\n                type: 'avatarbot_ir_receiver', // func name\n            },\n            paramsKeyMap: { // 파라미터를 사용 할때 쓰는 Key값 정의\n                VALUE: 0,\n            },\n            class: 'avatarbot_ir_receiver_data',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) { // 블록 기능정의\n            \tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                // let sensorData = Entry.hw.portData.CMD[Entry.avatarbot.BoardFunType.Button+1] == 0 ? 0 : 1;\n                // Entry.hw.sendQueue.CMD[Entry.avatarbot.BoardFunType.Button+1] = 0;\n                // Entry.hw.update();\n            \t// return sensorData;\n                //---\n                // 해당 값을 getField, getValue로 가져오고\n\t            // 가져 올때 paramsKeyMap에서\n\t            // 정의한 VALUE라는 키값으로 데이터를 가져옵니다.\n                // const signal = script.getValue('VALUE', script);\n                // return Entry.hw.getAnalogPortValue(signal[1]);\n                const type = script.getNumberValue('VALUE', script);\n\n                let index = Entry.avatarbot.BoardFunType.IR_Remote;\n                // data list\n                let ir_flag = Entry.hw.portData.CMD[index+0]; // 0 or 1\n                let ir_value = Entry.hw.portData.CMD[index+1]; // 0 or 1\n                let ir_repeat = Entry.hw.portData.CMD[index+2]; // 0 or 1\n                let ir_address = Entry.hw.portData.CMD[index+3]; // 0 or 1\n                let ir_command = Entry.hw.portData.CMD[index+4]; // 0 or 1\n\n                let ir_raw_data = 0x00000000; // unsigned int\n                ir_raw_data = Entry.hw.portData.CMD[index+5]; // unsigned int\n                ir_raw_data += (Entry.hw.portData.CMD[index+6]<<8);     \n                ir_raw_data += (Entry.hw.portData.CMD[index+7]<<16);\n                ir_raw_data += (Entry.hw.portData.CMD[index+8]<<24);\n                \n                // let mpu6050 = `Acceleration X: ${acceleration_x}, Y: ${acceleration_y}, Z: ${acceleration_z} m/s^2\\nRotation X: ${rotation_x}, Y: ${rotation_y}, Z: ${rotation_z} rad/s\\nTemperature: ${temperature} degC`;\n\t\t\t\t\n                let ir_revicer = \"\";\n                if(ir_flag == 1)\n                {\n                    if(type == 1)\n                    {\n                        ir_revicer = `장치(${ir_address}), 값(${ir_command}), `;\n                    } \n\n                    switch(ir_value)\n                    {\n                        case 0: // power\n                            ir_revicer += `전원`;\n                            break;\n                        case 1: // up\n                            ir_revicer += `위`;\n                            break;\n                        case 2: // down\n                            ir_revicer += `아래`;\n                            break;\n                        case 3: // left\n                            ir_revicer += `왼쪽`;\n                            break;\n                        case 4: // right\n                            ir_revicer += `오른쪽`;\n                            break;\n                        case 5: // ok\n                            ir_revicer += `ok`;\n                            break;\n                        case 6: // *\n                            ir_revicer += `*`;\n                            break;\n                        case 7: // #\n                            ir_revicer += `#`;\n                            break;\n                        case 8: // nb0\n                            ir_revicer += `0`;\n                            break;\n                        case 9: // 1\n                            ir_revicer += `1`;\n                            break;\n                        case 10:// 2\n                            ir_revicer += `2`;\n                            break;\n                        case 11: // 3\n                            ir_revicer += `3`;\n                            break;\n                        case 12: // 4s\n                            ir_revicer += `4`;\n                            break;\n                        case 13: // 5\n                            ir_revicer += `5`;\n                            break;\n                        case 14: // 6\n                            ir_revicer += `6`;\n                            break;\n                        case 15: // 7\n                            ir_revicer += `7`;\n                            break;\n                        case 16: // 8\n                            ir_revicer += `8`;\n                            break;\n                        case 17: // 9\n                            ir_revicer += `9`;\n                            break;\n                        default:\n                            break;        \n                    }\n                }\n                \n                Entry.hw.sendQueue.CMD[index] = 0; // flag clear x -> 0\n                Entry.hw.update();\n                return ir_revicer;\n\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.get_ir_receiver()',\n                        blockType: 'param',\n                        textParams: [\n                        ],\n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        avatarbot_oled_sample: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                \n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.avatarbot_func_on, '1'],\n                        [Lang.template.avatarbot_func_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                \n               /*\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                */\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'avatarbot_get_oled_number',\n                    },\n                    /*\n                    {\n                        type: 'avatarbot_get_timer_number',\n                    },\n                    */\n                ],\n                type: 'avatarbot_oled_sample',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                RUN: 1,\n                // TIME: 1,\n            },\n            class: 'avatarbot_oled',\n            isNotFor: ['avatarbot'],\n            func(sprite, script) {\n\t\t\t\tif (!Entry.hw.sendQueue.CMD) {\n                    Entry.avatarbot.dataTableReset();\n                }\n                \n                const sample = script.getNumberValue('VALUE1', script);\n                const run = script.getField('RUN');\n                const on = run == '1' ? 1 : 0;\n                // const time = script.getNumberValue('TIME', script);\n                // const on = time>0? 1:0; // 100ms ~ 1s = 1, 0ms = 0\n\n                let index = Entry.avatarbot.BoardFunType.OLED;\n\n                Entry.hw.sendQueue.CMD[index] = on; // 1; // ch en + ch time\n                Entry.hw.sendQueue.CMD[index+1] = sample; // 0 : not run, sample 1~n\n                Entry.hw.update();\n                \n                return script.callReturn();\n\n                /*\n                if (!script.isStart) {\n                    const sample = script.getNumberValue('VALUE1', script);\n                    // const run = script.getField('RUN');\n                    // const on = run == '1' ? 1 : 0;\n                    const time = script.getNumberValue('TIME', script);\n                    const on = time>0? 1:0; // 100ms ~ 1s = 1, 0ms = 0\n\n                    let index = Entry.avatarbot.BoardFunType.OLED;\n\n                    Entry.hw.sendQueue.CMD[index] = on + (time<<1); // 1; // ch en + ch time\n                    Entry.hw.sendQueue.CMD[index+1] = sample; // 0 : not run, sample 1~n\n                    Entry.hw.update();\n                    if(time == 0)\n                    {\n                        return script.callReturn;\n                    }\n                    var duration = time;\n                    duration = duration * 100;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    \n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n\n                    let index = Entry.avatarbot.BoardFunType.OLED;\n                    Entry.hw.sendQueue.CMD[index] = 0; // 1; // ch en + ch time\n                    Entry.hw.sendQueue.CMD[index+1] = 0; // 0 : not run, sample 1~n\n                    Entry.hw.update();\n                    return script.callReturn();\n                }\n                */\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'avatarbot.set_oled_sample(%1 %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            \n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.template.avatarbot_func_on, '1'],\n                                    [Lang.template.avatarbot_func_off, '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            \n                           /*\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            */\n                        ],\n                        \n                    },\n                ],\n            },\n        },\n        //---------------------------------------------------------------\n        //endregion avatarbot 아두이노\n        //---------------------------------------------------------------\n    };\n};\n\n// 엔트리에서 하드웨어 블록 클래스를 인식할 수 있도록 내보내기\nmodule.exports = Entry.avatarbot;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_bingles.js",
    "content": "'use strict';\n\nEntry.BINGLES = {\n    id: '1.D',\n    name: 'BINGLES',\n    url: 'http://www.xbot.co.kr/',\n    imageName: 'bingles.png',\n    title: {\n        ko: '빙글S',\n        en: 'BINGLES',\n    },\n    PORT_MAP: {\n        RIGHT_WHEEL: 0,\n        LEFT_WHEEL: 0,\n        HEAD: 90,\n        ARMR: 90,\n        ARML: 90,\n        HEAD_LED: 0,\n        ledR: 0,\n        ledG: 0,\n        ledB: 0,\n        lcdNum: 0,\n        lcdTxt: ' ',\n        note: 'C4',\n        duration: 0,\n        motor_direction: 'Forward',\n        motor_duration: 0,\n        OLEDImage: 0,\n    },\n    setZero: function() {\n        var portMap = Entry.BINGLES.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        var BINGLES = Entry.BINGLES;\n        BINGLES.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n};\n\nEntry.BINGLES.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n                Forward: '앞',\n                Back: '뒤',\n                Left: '좌회전',\n                Right: '우회전',\n                LightSensorValue: '광센서 값',\n                MicSensorValue: '마이크 값',\n                IR0Value: 'IR 0 값',\n                IR1Value: 'IR 1 값',\n                IR2Value: 'IR 2 값',\n                IR3Value: 'IR 3 값',\n                Remocon: '리모컨',\n                Head: '머리',\n                LeftArm: '왼 팔',\n                RightArm: '오른 팔',\n            },\n            template: {\n                bingles_analogValue: '%1',\n                bingles_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n                bingles_servo: '서보 모터 %1 , 각도 %2 %3',\n                bingles_twoWheel: '바퀴(DC) 모터 오른쪽(2) 속도: %1 왼쪽(1) 속도: %2',\n                bingles_lcd: 'LCD %1 번째 줄 ,  출력 값 %2 %3',\n                bingles_remotecontrol: '리모콘',\n                bingles_rgb: 'RGB LED 켜기 R 값 %1 G 값 %2 B 값 %3',\n                bingles_rgb_picker: 'RGB LED색 %1로 정하기',\n                bingles_buzzer: '%1 %2 음을 %3초 연주하기',\n                bingles_oled: '얼굴 %1 번 표현 나타내기',\n                bingles_motorgo: '방향 %1 %2 초 움직이기',\n            },\n            Menus: {\n                bingles: '빙글S',\n            },\n        },\n        en: {\n            Blocks: {\n                Forward: 'Forward',\n                Back: 'Back',\n                Left: 'Left Turn',\n                Right: 'Right Turn',\n                LightSensorValue: 'Light Sensor Value',\n                MicSensorValue: 'Mic Sensor Value',\n                IR0Value: 'IR 0 Value',\n                IR1Value: 'IR 1 Value',\n                IR2Value: 'IR 2 Value',\n                IR3Value: 'IR 3 Value',\n                Remocon: 'Remote control',\n                Head: 'Head',\n                LeftArm: 'Left',\n                RightArm: 'Right',\n            },\n            template: {\n                bingles_analogValue: '%1',\n                bingles_digitalOutput: 'Digital %1 PIN, Output Value %2 %3',\n                bingles_servo: 'Servo Motor %1 , Angle %2 %3',\n                bingles_twoWheel: 'Wheel(DC) Motor %1 , Speed %2 %3',\n                bingles_lcd: 'LCD Line %1 , Text %2 %3',\n                bingles_remotecontrol: 'Remote control',\n                bingles_rgb: 'RGB LED Color from Red %1 Green %2 Blue %3',\n                bingles_rgb_picker: 'RGB LED Color from %1',\n                bingles_buzzer: 'Play Tone %1 %2 for %3sec of Melody Playing',\n                bingles_oled: 'Set Facial Icon %1',\n                bingles_motorgo: 'Move Robot %1 %2 sec',\n            },\n            Menus: {\n                bingles: \"bingles: 'BINGLE · S'\",\n            },\n        },\n    };\n};\n\nEntry.BINGLES.blockMenuBlocks = [\n    'bingles_analogValue',\n    'bingles_digitalOutput',\n    'bingles_rgb',\n    'bingles_rgb_picker',\n    'bingles_buzzer',\n    'bingles_servo',\n    'bingles_twoWheel',\n    'bingles_lcd',\n    'bingles_remotecontrol',\n    'bingles_oled',\n    'bingles_motorgo',\n];\n\nEntry.BINGLES.getBlocks = function() {\n    return {\n        //region xbot 엑스봇\n        bingles_analogValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.LightSensorValue, 'light'],\n                        [Lang.Blocks.MicSensorValue, 'mic'],\n                        [Lang.Blocks.IR0Value, 'ir0'],\n                        [Lang.Blocks.IR1Value, 'ir1'],\n                        [Lang.Blocks.IR2Value, 'ir2'],\n                        [Lang.Blocks.IR3Value, 'ir3'],\n                    ],\n                    value: 'light',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'bingles_analogValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'bingles_sensor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['bingles.analog_value(%1)'] },\n        },\n\n        bingles_remotecontrol: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            fontColor: '#ffffff',\n            params: [\n                {\n                    type: 'default_value',\n                    options: [[Lang.Blocks.Remocon, 'remocon']],\n                    value: 'remocon',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'bingles_remotecontrol',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'bingles_sensor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['bingles.analog_value(%1)'] },\n        },\n\n        bingles_digitalOutput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['LED', 'HEAD_LED']],\n                    value: 'HEAD_LED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_High, 'HIGH'],\n                        [Lang.Blocks.XBOT_Low, 'LOW'],\n                    ],\n                    value: 'HIGH',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'bingles_digitalOutput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'bingles_sensor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getStringField('VALUE', script);\n\n                if (dev == 'HEAD_LED' && value == 'HIGH') {\n                    sq.HEAD_LED = 1;\n                } else {\n                    sq.HEAD_LED = 0;\n                }\n                //sq.D13 = 1;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['bingles.digital_output(%1, %2)'] },\n        },\n\n        bingles_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.Head, 'head'],\n                        [Lang.Blocks.RightArm, 'right'],\n                        [Lang.Blocks.LeftArm, 'left'],\n                    ],\n                    value: 'head',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'bingles_servo',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'bingles_motor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var mtype = script.getStringField('DEVICE', script);\n                var angle = script.getNumberValue('VALUE', script);\n\n                if (mtype == 'head') {\n                    sq.HEAD = angle;\n                } else if (mtype == 'right') {\n                    sq.ARMR = angle;\n                } else if (mtype == 'left') {\n                    sq.ARML = angle;\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['bingles.servo(%1, %2)'] },\n        },\n\n        bingles_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['Hello'],\n                    },\n                    null,\n                ],\n                type: 'bingles_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                VALUE: 1,\n            },\n            class: 'bingles_sensor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var line = script.getNumberField('LINE', script);\n                var str = script.getStringValue('VALUE', script);\n\n                sq.lcdNum = line;\n                sq.lcdTxt = str;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['bingles.lcd(%1, %2)'] },\n        },\n\n        bingles_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_c, 'C'],\n                        [Lang.Blocks.XBOT_d, 'D'],\n                        [Lang.Blocks.XBOT_e, 'E'],\n                        [Lang.Blocks.XBOT_f, 'F'],\n                        [Lang.Blocks.XBOT_g, 'G'],\n                        [Lang.Blocks.XBOT_a, 'A'],\n                        [Lang.Blocks.XBOT_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'bingles_buzzer',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                VALUE: 2,\n            },\n            class: 'bingles_sensor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    var note = script.getStringField('NOTE', script);\n                    var octave = script.getStringField('OCTAVE', script);\n                    var duration = script.getNumberValue('VALUE', script);\n                    var noteOctave = note + octave; // 'C'+ 2 = \"C2\"\n                    //console.log('xbot_buzzer ' + noteOctave + ' ' + duration);\n\n                    sq.note = noteOctave;\n\n                    sq.duration = duration * 10; //  convert to 100mSec\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    var timeValue = duration * 1000;\n                    console.log('timeValue' + timeValue);\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.BINGLES.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.BINGLES.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    sq.duration = 0;\n\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['bingles.buzzer(%1, %2, %3)'] },\n        },\n\n        bingles_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'bingles_rgb',\n            },\n            paramsKeyMap: {\n                ledR: 0,\n                ledG: 1,\n                ledB: 2,\n            },\n            class: 'bingles_rgb',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                sq.ledR = script.getNumberValue('ledR');\n                sq.ledG = script.getNumberValue('ledG');\n                sq.ledB = script.getNumberValue('ledB');\n\n                //console.log('ledR' + sq.ledR + ' ledG ' + sq.ledG +' ledB ' + sq.ledB);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['bingles.rgb(%1, %2, %3)'] },\n        },\n\n        bingles_rgb_picker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'bingles_rgb_picker',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'bingles_rgb',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var port = script.getStringField('VALUE');\n                var sq = Entry.hw.sendQueue;\n\n                sq.ledR = parseInt(parseInt(port.substr(1, 2), 16) * 0.3);\n                sq.ledG = parseInt(parseInt(port.substr(3, 2), 16) * 0.3);\n                sq.ledB = parseInt(parseInt(port.substr(5, 2), 16) * 0.3);\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['bingles.rgb_picker(%1)'] },\n        },\n\n        bingles_twoWheel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'bingles_twoWheel',\n            },\n            paramsKeyMap: {\n                rightWheel: 0,\n                leftWheel: 1,\n            },\n            class: 'bingles_motor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                //console.log('xbot_move_forward_for_secs');\n                var sq = Entry.hw.sendQueue;\n\n                sq.RIGHT_WHEEL = script.getNumberValue('rightWheel');\n                sq.LEFT_WHEEL = script.getNumberValue('leftWheel');\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['bingles.two_wheel(%1, %2)'] },\n        },\n\n        bingles_motorgo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.Forward, 'Forward'],\n                        [Lang.Blocks.Back, 'Backward'],\n                        [Lang.Blocks.Left, 'Left Turn'],\n                        [Lang.Blocks.Right, 'Right Turn'],\n                    ],\n                    value: 'Forward',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'bingles_motorgo',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'bingles_motor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var motorDir = script.getStringField('DEVICE', script);\n                var motorDur = script.getNumberValue('VALUE', script);\n                //console.log('xbot_direction ' + motorDir + ' ' + motorDur);\n\n                sq.motor_direction = motorDir;\n                sq.motor_duration = motorDur * 10; //  convert to 100mSec*/\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['bingles.motorgo(%1, %2, %3)'] },\n        },\n\n        bingles_oled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['17', '17'],\n                        ['18', '18'],\n                        ['19', '19'],\n                        ['20', '20'],\n                        ['21', '21'],\n                        ['22', '22'],\n                        ['23', '23'],\n                        ['24', '24'],\n                        ['25', '25'],\n                        ['26', '26'],\n                        ['27', '27'],\n                        ['28', '28'],\n                        ['29', '29'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'bingles_oled',\n            },\n            paramsKeyMap: {\n                oledImage: 0,\n            },\n            class: 'bingles_sensor',\n            isNotFor: ['BINGLES'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var OLEDImage = script.getNumberField('oledImage', script);\n\n                sq.OLEDImage = OLEDImage;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['bingles.lcd(%1, %2)'] },\n        },\n        //endregion xbot 엑스봇\n    };\n};\n\nmodule.exports = Entry.BINGLES;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_bitbrick.js",
    "content": "'use strict';\n\nEntry.Bitbrick = {\n    SENSOR_MAP: {\n        1: 'light',\n        2: 'IR',\n        3: 'touch',\n        4: 'potentiometer',\n        5: 'MIC',\n        6: 'ultrasonicSensor',\n        10: 'vibrationSensor',\n        21: 'UserSensor',\n        11: 'UserInput',\n        20: 'LED',\n        19: 'SERVO',\n        18: 'DC',\n    },\n    PORT_MAP: {\n        buzzer: 2,\n        '5': 4,\n        '6': 6,\n        '7': 8,\n        '8': 10,\n        LEDR: 12,\n        LEDG: 14,\n        LEDB: 16,\n    },\n    INEQ_SIGN: [\n        [\"<\", \"<\"],\n        [\">\", \">\"],\n        [\"=\", \"=\"]\n    ],\n    sensorList: function() {\n        var list = [];\n        var portData = Entry.hw.portData;\n        for (var i = 1; i < 5; i++) {\n            var data = portData[i];\n            if (data && (data.value || data.value === 0)) {\n                list.push([i + ' - ' + Lang.Blocks['BITBRICK_' + data.type], i.toString()]);\n            }\n        }\n\n        if (list.length == 0) return [[Lang.Blocks.no_target, 'null']];\n        return list;\n    },\n    touchList: function() {\n        var list = [];\n        var portData = Entry.hw.portData;\n        for (var i = 1; i < 5; i++) {\n            var data = portData[i];\n            if (data && data.type === 'touch') list.push([i.toString(), i.toString()]);\n        }\n        if (list.length == 0) return [[Lang.Blocks.no_target, 'null']];\n        return list;\n    },\n    servoList: function() {\n        var list = [];\n        var portData = Entry.hw.portData;\n        for (var i = 5; i < 9; i++) {\n            var data = portData[i];\n            if (data && data.type === 'SERVO') list.push(['ABCD'[i - 5], i.toString()]);\n        }\n        if (list.length == 0) return [[Lang.Blocks.no_target, 'null']];\n        return list;\n    },\n    dcList: function() {\n        var list = [];\n        var portData = Entry.hw.portData;\n        for (var i = 5; i < 9; i++) {\n            var data = portData[i];\n            if (data && data.type === 'DC') list.push(['ABCD'[i - 5], i.toString()]);\n        }\n        if (list.length == 0) return [[Lang.Blocks.no_target, 'null']];\n        return list;\n    },\n    /**\n     * 엔트리가 중지 되면 호출된다.\n     */\n    setZero: function() {\n        let sq = Entry.hw.sendQueue;\n        for (let port in Entry.Bitbrick.PORT_MAP) {\n            let portData    = Entry.hw.portData[port];\n            if( portData != null ) {\n                if( portData.type == Entry.Bitbrick.SENSOR_MAP[18] ) {     // DC모터 인 경우, 129로 세팅하여 바로 멈추기    \n                    sq[port] = 129;\n                } else {\n                    sq[port] = 0;    \n                }\n            } else {\n                sq[port] = 0;\n            }\n        }\n        Entry.hw.update();\n    },\n    id: '3.1',\n    name: 'bitbrick',\n    url: 'http://www.bitbrick.cc/',\n    imageName: 'bitbrick.png',\n    title: {\n        ko: '비트브릭',\n        en: 'bitbrick',\n    },\n    servoMaxValue: 181,\n    servoMinValue: 1,\n    dcMaxValue: 100,\n    dcMinValue: -100,\n    monitorTemplate: {\n        keys: ['value'],\n        imgPath: 'hw/bitbrick.png',\n        width: 400,\n        height: 400,\n        listPorts: {\n            '1': {\n                name: Lang.Hw.port_en + ' 1 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '2': {\n                name: Lang.Hw.port_en + ' 2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '3': {\n                name: Lang.Hw.port_en + ' 3 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '4': {\n                name: Lang.Hw.port_en + ' 4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        // },\n        // ports : {\n        //     \"1\":{name: \"light\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"2\":{name: \"IR\", type: \"input\", pos: {x : 0, y: 0}},\n        //     \"3\":{name: \"touch\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"4\":{name: \"potentiometer\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"5\":{name: \"MIC\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"21\":{name: \"UserSensor\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"11\":{name: \"USER INPUT\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"20\":{name: \"LED\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"19\":{name: \"SERVO\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"18\":{name: \"DC\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"buzzer\":{name: \"부저\", type: \"input\", pos: {x: 0, y: 0}},\n        //     \"LEDR\":{name: \"LEDR\", type: \"output\", pos: {x: 0, y: 0}},\n        //     \"LEDG\":{name: \"LEDG\", type: \"output\", pos: {x: 0, y: 0}},\n        //     \"LEDB\":{name: \"LEDG\", type: \"output\", pos: {x: 0, y: 0}}\n        // },\n        mode: 'both',\n    },\n    /**\n     * 콜백 함수. 계속해서 센서 데이터를 받는다.\n     * @param {*} pd \n     */\n    afterReceive(pd) {\n        for( let i = 1; i < 5; i++ ) {      // 오직 센서만 받기\n            let obj = pd[ i ];              // ex) null or { type: \"touch\", value: 1023 }\n            if( obj != null ) {\n                if( obj.type == 'touch' && obj.value == 0 ) {\n                    Entry.engine.fireEvent('bitbrickButtonEventReceive');\n                }\n                Entry.engine.fireEvent('bitbrickSensorGetValueEventReceive');\n            }\n        }\n    },\n    calculateDCMotorValue: function( value ) {\n        let val = 0;\n        if ( value > 0 ) { \n            val  = Math.floor( ( value * 0.8 ) + 16 );\n        } else if ( value < 0 ) {\n            val  = Math.ceil( ( value * 0.8 ) - 19 );\n        } else { \n            val  = 0; \n        }\n        // DC_MOTOR_ADJUSTMENT  128\n        val = 128 + val;\n        if ( val == 128 ) {\n            val = 129;\n        }\n        return val;\n    }\n};\n\nEntry.Bitbrick.blockMenuBlocks = [\n    'bitbrick_when_button_pressed',\n    'bitbrick_when_sensor_get_value',\n    'bitbrick_is_touch_pressed',\n    'bitbrick_is_sensor_value_compare',\n    'bitbrick_sensor_value',\n    'bitbrick_convert_scale',\n    'bitbrick_turn_on_color_led_by_rgb',\n    'bitbrick_turn_on_color_led_by_picker',\n    'bitbrick_turn_on_color_led_by_value',\n    'bitbrick_turn_off_color_led',\n    'bitbrick_buzzer',    \n    'bitbrick_servomotor_angle',\n    'bitbrick_dc_direction_speed',\n    'bitbrick_dc_speed',\n    'bitbrick_turn_off_all_motors',\n];\n\nEntry.Bitbrick.getBlocks = function() {\n    let options_BITBRICK_button2    = \n    [\n        [Lang.Blocks.BITBRICK_button_pressed,  'pressed'],\n        [Lang.Blocks.BITBRICK_button_released, 'released'],\n    ];\n    return {\n        //region bitbrick 비트브릭\n        bitbrick_when_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                    position: {\n                        x: 0,\n                        y: 0\n                    }\n                },                                \n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    menuName: Entry.Bitbrick.touchList,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'bitbrick_when_button_pressed',\n            },\n            paramsKeyMap: {\n                DUMMY: 0,\n                PORT: 1,\n            },\n            class: 'event',\n            isNotFor: ['bitbrick'],\n            event: 'bitbrickButtonEventReceive',\n            func: function(sprite, script) {\n                if( script.values.length > 0 ) {\n                    let selectedSensor  = script.values[ 1 ];\n                    let port = script.getStringField('PORT');\n                    let val  = Entry.hw.portData[port].value;       // 0이면 누름, 1023이면 누르지 않음\n                    if( selectedSensor == port ) {\n                        if (val == 0) {\n                            return script.callReturn();\n                        } else {\n                            return this.die();\n                        }                        \n                    } else {\n                        return this.die();\n                    }\n                } else {\n                    return this.die();\n                }\n            },\n            syntax: { js: [], py: ['Bitbrick.when_button_pressed(%2)'] },\n        },        \n        bitbrick_when_sensor_get_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                    position: {\n                        x: 0,\n                        y: 0\n                    }\n                },                \n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    menuName: Entry.Bitbrick.sensorList,\n                },\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: Entry.Bitbrick.INEQ_SIGN,\n                    value: '>',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    }\n                ],\n                type: 'bitbrick_when_sensor_get_value',\n            },\n            paramsKeyMap: {\n                DUMMY: 0,\n                PORT: 1,\n                INEQ_SIGN: 2,\n                VALUE: 3\n            },\n            class: 'event',\n            isNotFor: ['bitbrick'],\n            event: 'bitbrickSensorGetValueEventReceive',\n            func: function(sprite, script) {\n                let selectedPort    = script.values[ 1 ];\n                let ineqSign        = script.values[ 2 ];\n                let value           = script.values[ 3 ];\n                let port    = script.getStringField('PORT');\n                let val     = Entry.hw.portData[port].value;\n                if( selectedPort == port && ineqSign == '<' && val < value ) {\n                    return script.callReturn();\n                } else if( selectedPort == port && ineqSign == '>' && val > value ) {\n                    return script.callReturn();\n                } else if( selectedPort == port && ineqSign == '=' && val == value ) {\n                    return script.callReturn();\n                } else {\n                    return this.die();\n                }\n            },\n            syntax: { js: [], py: ['Bitbrick.when_sensor_get_value(%2,%3,%4)'] },\n        },        \n        bitbrick_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    menuName: Entry.Bitbrick.sensorList,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'bitbrick_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'button',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port].value;\n            },\n            syntax: { js: [], py: ['Bitbrick.sensor_value(%1)'] },\n        },\n        bitbrick_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Bitbrick.sensorList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'bitbrick_convert_scale',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'button',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                var port = script.getNumberField('PORT');\n                var value1 = Entry.hw.portData[port].value;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var result = value1;\n\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n                return Math.round(result);\n            },\n            syntax: {\n                js: [],\n                py: ['Bitbrick.convert_scale(%1, %2, %3, %4, %5)'],\n            },\n        },\n        bitbrick_is_touch_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Bitbrick.touchList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_BITBRICK_button2,\n                    value: 'pressed',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'bitbrick_is_touch_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                PRESSED: 1\n            },\n            class: 'button',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                console.info(\"bitbrick_is_touch_pressed\");\n                let port = script.getStringField('PORT');\n                let val  = Entry.hw.portData[port].value;\n                let pressed = script.getStringField('PRESSED');\n                if ((pressed == 'pressed') && (val == 0)) {\n                    return true;\n                } else if ((pressed == 'released') && (val == 1023)) {\n                    return true;\n                } else {\n                    return false;\n                }                        \n            },\n            syntax: { js: [], py: ['Bitbrick.is_touch_pressed(%1, %2)'] },\n        },\n        bitbrick_is_sensor_value_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    menuName: Entry.Bitbrick.sensorList,\n                },\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: Entry.Bitbrick.INEQ_SIGN,\n                    value: '>',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    }\n                ],\n                type: 'bitbrick_is_sensor_value_compare',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                INEQ_SIGN: 1,\n                VALUE: 2\n            },\n            class: 'button',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                let selectedPort    = script.values[ 0 ];\n                let ineqSign        = script.values[ 1 ];\n                let value           = script.values[ 2 ];\n                let port    = script.getStringField('PORT');\n                let val     = Entry.hw.portData[port].value;\n                if( selectedPort == port && ineqSign == '<' && val < value ) {\n                    return true;\n                } else if( selectedPort == port && ineqSign == '>' && val > value ) {\n                    return true;\n                } else if( selectedPort == port && ineqSign == '=' && val == value ) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: ['Bitbrick.is_sensor_value_compare(%1,%2,%3)'] },\n        },\n        bitbrick_turn_off_color_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'bitbrick_turn_off_color_led',\n                id: 'i3je',\n            },\n            class: 'led',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue['LEDR'] = 0;\n                Entry.hw.sendQueue['LEDG'] = 0;\n                Entry.hw.sendQueue['LEDB'] = 0;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Bitbrick.turn_off_color_led()'] },\n        },\n        bitbrick_turn_on_color_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'bitbrick_turn_on_color_led_by_rgb',\n            },\n            paramsKeyMap: {\n                rValue: 0,\n                gValue: 1,\n                bValue: 2,\n            },\n            class: 'led',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                var red = script.getNumberValue('rValue'),\n                    green = script.getNumberValue('gValue'),\n                    blue = script.getNumberValue('bValue'),\n                    min = 0,\n                    max = 255,\n                    adjustor = Entry.adjustValueWithMaxMin,\n                    sq = Entry.hw.sendQueue;\n\n                sq['LEDR'] = adjustor(red, min, max);\n                sq['LEDG'] = adjustor(green, min, max);\n                sq['LEDB'] = adjustor(blue, min, max);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Bitbrick.color_led_by_rgb(%1, %2, %3)'] },\n        },\n        bitbrick_turn_on_color_led_by_picker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'bitbrick_turn_on_color_led_by_picker',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'led',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                var port = script.getStringField('VALUE');\n                Entry.hw.sendQueue['LEDR'] = parseInt(port.substr(1, 2), 16);\n                Entry.hw.sendQueue['LEDG'] = parseInt(port.substr(3, 2), 16);\n                Entry.hw.sendQueue['LEDB'] = parseInt(port.substr(5, 2), 16);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Bitbrick.color_led_by_picker(%1)'] },\n        },\n        bitbrick_turn_on_color_led_by_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'bitbrick_turn_on_color_led_by_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'led',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var red, green, blue;\n                value = value % 200;\n                if (value < 67) {\n                    red = 200 - value * 3;\n                    green = value * 3;\n                    blue = 0;\n                } else if (value < 134) {\n                    value = value - 67;\n                    red = 0;\n                    green = 200 - value * 3;\n                    blue = value * 3;\n                } else if (value < 201) {\n                    value = value - 134;\n                    red = value * 3;\n                    green = 0;\n                    blue = 200 - value * 3;\n                }\n                Entry.hw.sendQueue['LEDR'] = red;\n                Entry.hw.sendQueue['LEDG'] = green;\n                Entry.hw.sendQueue['LEDB'] = blue;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Bitbrick.color_led_by_value(%1)'] },\n        },\n        bitbrick_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'bitbrick_buzzer',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'buzzer',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var value = script.getNumberValue('VALUE');\n                    Entry.hw.sendQueue['buzzer'] = value;\n                    script.isStart = true;\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['buzzer'] = 0;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Bitbrick.buzzer(%1)'] },\n        },\n        bitbrick_turn_off_all_motors: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'bitbrick_turn_off_all_motors',\n            },\n            class: 'motor',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var bitbrick = Entry.Bitbrick;\n                bitbrick.servoList().map(function(servo) {\n                    sq[servo[1]] = 0;\n                });\n                bitbrick.dcList().map(function(dc) {\n                    sq[dc[1]] = 129;\n                });\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Bitbrick.turn_off_all_motors()'] },\n        },\n        bitbrick_dc_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Bitbrick.dcList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'bitbrick_dc_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, Entry.Bitbrick.dcMaxValue);\n                value = Math.max(value, Entry.Bitbrick.dcMinValue);\n                let val = Entry.Bitbrick.calculateDCMotorValue( value );\n                Entry.hw.sendQueue[script.getStringField('PORT')] = val;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Bitbrick.dc_speed(%1, %2)'] },\n        },\n        bitbrick_dc_direction_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Bitbrick.dcList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.BITBRICK_dc_direction_cw, 'CW'],\n                        [Lang.Blocks.BITBRICK_dc_direction_ccw, 'CCW'],\n                    ],\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'bitbrick_dc_direction_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n            },\n            class: 'motor',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                let isFront = script.getStringField('DIRECTION') === 'CW';\n                let value   = script.getNumberValue('VALUE');\n                value = Math.min(value, Entry.Bitbrick.dcMaxValue);\n                value = Math.max(value, 0);\n                if ( !isFront ) {\n                    value = -1 * value;\n                }\n                let val = Entry.Bitbrick.calculateDCMotorValue( value );\n                Entry.hw.sendQueue[script.getStringField('PORT')] = val;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Bitbrick.dc_direction_speed(%1, %2, %3)'] },\n        },\n        bitbrick_servomotor_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Bitbrick.servoList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'bitbrick_servomotor_angle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['bitbrick'],\n            func: function(sprite, script) {\n                var value = Entry.Bitbrick.servoMaxValue - (script.getNumberValue('VALUE') + 1);\n                value = Math.min(value, Entry.Bitbrick.servoMaxValue);\n                value = Math.max(value, Entry.Bitbrick.servoMinValue);\n                Entry.hw.sendQueue[script.getStringField('PORT')] = value;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Bitbrick.servomotor_angle(%1, %2)'] },\n        },\n        //endregion bitbrick 비트브릭\n    };\n};\n// 언어 적용\nEntry.Bitbrick.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            template: {\n                bitbrick_when_button_pressed: '%1 버튼 %2 눌러졌을 때',\n                bitbrick_when_sensor_get_value: '%1 %2 값 %3 %4 일 때',\n                bitbrick_is_touch_pressed: '버튼 %1 이(가) %2 인가?',\n                bitbrick_is_sensor_value_compare: '%1 값 %2 %3 인가?',\n                bitbrick_sensor_value: '%1 값',\n                bitbrick_convert_scale: '변환 %1 값 %2 ~ %3 에서 %4 ~ %5',\n                bitbrick_turn_on_color_led_by_rgb: '엘이디를 빨강 %1 초록 %2 파랑 %3 %4 (으)로 켜기',\n                bitbrick_turn_on_color_led_by_picker: '엘이디를 %1 (으)로 켜기 %2',\n                bitbrick_turn_on_color_led_by_value: '엘이디를 %1 (으)로 켜기 %2',\n                bitbrick_turn_off_color_led: '엘이디 끄기 %1',\n                bitbrick_buzzer: '버저음 %1 내기 %2',\n                bitbrick_servomotor_angle: '서보모터 %1 각도 %2 %3',\n                bitbrick_dc_direction_speed: '디씨모터 %1 방향 %2 속력 %3 %4',\n                bitbrick_dc_speed: '디씨모터 %1 속도 %2 %3',\n                bitbrick_turn_off_all_motors: '모든 모터 멈추기 %1',\n            },\n            Blocks: {\n                BITBRICK_button_pressed: '누름',\n                BITBRICK_button_released: '누르지 않음',\n                BITBRICK_light: '밝기 센서',\n                BITBRICK_IR: '적외선 센서',\n                BITBRICK_touch: '버튼',\n                BITBRICK_ultrasonicSensor: '초음파센서',\n                BITBRICK_vibrationSensor: '진동 센서',\n                BITBRICK_potentiometer: '가변저항',\n                BITBRICK_MIC: '소리 센서',\n                BITBRICK_UserSensor: '사용자 입력',\n                BITBRICK_UserInput: '사용자 입력',\n                BITBRICK_dc_direction_ccw: '반시계',\n                BITBRICK_dc_direction_cw: '시계',\n            },\n            Menus: {\n                bitbrick: '비트브릭',\n            },\n            Device: {\n                bitbrick: '비트브릭',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                bitbrick_when_button_pressed: '%1 when button %2',\n                bitbrick_when_sensor_get_value: '%1 when %2 value %3 %4',\n                bitbrick_is_touch_pressed: 'button %1 %2?',\n                bitbrick_is_sensor_value_compare: '%1 %2 %3? ',\n                bitbrick_sensor_value: '%1 value',\n                bitbrick_convert_scale: 'map %1 value from %2 ~ %3 to %4 ~ %5',\n                bitbrick_turn_on_color_led_by_rgb: 'set LED color to Red %1 Green %2 Blue %3 %4',\n                bitbrick_turn_on_color_led_by_picker: 'set LED color to %1 %2',\n                bitbrick_turn_on_color_led_by_value: 'set LED color %1 %2',\n                bitbrick_turn_off_color_led: 'turn off LED %1',\n                bitbrick_buzzer: 'buzz note %1 %2',\n                bitbrick_servomotor_angle: 'servo motor %1 degree %2 %3',\n                bitbrick_dc_direction_speed: 'dc motor %1 direction %2 speed %3 %4',\n                bitbrick_dc_speed: 'dc motor %1 velocity %2 %3',\n                bitbrick_turn_off_all_motors: 'stop all motors %1',\n            },\n            Blocks: {\n                BITBRICK_button_pressed: 'pressed',\n                BITBRICK_button_released: 'released',                \n                BITBRICK_light: 'light',\n                BITBRICK_IR: 'IR',\n                BITBRICK_touch: 'touch',\n                BITBRICK_ultrasonicSensor: 'ultrasonicSenso',\n                BITBRICK_vibrationSensor: 'vibrationSensor',\n                BITBRICK_potentiometer: 'potentiometer',\n                BITBRICK_MIC: 'MIC',\n                BITBRICK_UserSensor: 'UserSensor',\n                BITBRICK_UserInput: 'UserInput',\n                BITBRICK_dc_direction_ccw: 'CCW',\n                BITBRICK_dc_direction_cw: 'CW',\n            },\n            Menus: {\n                bitbrick: 'bitbrick',\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Bitbrick;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_blacksmith.js",
    "content": "'use strict';\n\nEntry.Blacksmith = {\n    id: '1.B',\n    name: 'blacksmith',\n    url: 'http://www.hanibot.com',\n    imageName: 'blacksmith.png',\n    title: {\n        ko: '대장장이 보드',\n        en: 'Blacksmith Board',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                if (Entry.hw.sendQueue.SET[key].type == Entry.Blacksmith.sensorTypes.DCMOTOR) {\n                    Entry.hw.sendQueue.SET[key].data.value1 = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else {\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.hw.sendQueue.GET = {};\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        READ_BLUETOOTH: 9,\n        WRITE_BLUETOOTH: 10,\n        LCD: 11,\n        RGBLED: 12,\n        DCMOTOR: 13,\n        OLED: 14,\n        PIR: 15,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\nEntry.Blacksmith.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                blacksmith_toggle_on: '켜기',\n                blacksmith_toggle_off: '끄기',\n                blacksmith_lcd_first_line: '첫 번째',\n                blacksmith_lcd_seconds_line: '두 번째',\n                blacksmith_dcmotor_direction_forward: '정방향',\n                blacksmith_dcmotor_direction_reverse: '역방향',\n                blacksmith_btData_select_number: '숫자',\n                blacksmith_btData_select_character: '문자',\n                blacksmith_set_digital_lcd: 'LCD화면 %1 줄에 %2 나타내기 %3',\n                blacksmith_set_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n                blacksmith_get_analog_value: '아날로그 %1 번 핀 센서 값',\n                blacksmith_get_analog_mapping:\n                    '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n                blacksmith_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\n                blacksmith_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n                blacksmith_get_digital: '디지털 %1 번 핀 센서 값',\n                blacksmith_get_digital_toggle: '디지털 %1 번 핀 센서 값',\n                blacksmith_get_digital_pir: 'PIR %1 번 핀 센서 값',\n                blacksmith_set_digital_toggle: '디지털 %1 번 핀 %2 %3',\n                blacksmith_set_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                blacksmith_set_digital_rgbled:\n                    '디지털 %1 번 핀의 RGB LED를 빨강 %2 초록 %3 파랑 %4 로 정하기 %5',\n                blacksmith_set_digital_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                blacksmith_set_digital_buzzer:\n                    '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                blacksmith_set_digital_dcmotor:\n                    'DC모터 %1 번 핀을 %2 %3 번 핀의 속도를 %4 로 정하기 %5',\n                blacksmith_module_digital_lcd: 'LCD화면 %1 줄에 %2 나타내기 %3',\n                blacksmith_module_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n                blacksmith_module_digital_oled: 'OLED화면 X 좌표 %1  Y 좌표 %2 에 %3 나타내기 %4',\n            },\n            Blocks: {\n                blacksmith_toggle_on: '켜기',\n                blacksmith_toggle_off: '끄기',\n                blacksmith_lcd_first_line: '첫 번째',\n                blacksmith_lcd_seconds_line: '두 번째',\n            },\n            Menus: {\n                blacksmith: '대장장이 보드',\n            },\n        },\n        en: {\n            template: {\n                blacksmith_toggle_on: 'on',\n                blacksmith_toggle_off: 'off',\n                blacksmith_lcd_first_line: 'first',\n                blacksmith_lcd_seconds_line: 'seconds',\n                blacksmith_dcmotor_direction_forward: 'forward',\n                blacksmith_dcmotor_direction_reverse: 'reverse',\n                blacksmith_btData_select_number: 'number',\n                blacksmith_btData_select_character: 'character',\n                blacksmith_get_analog_value: 'Read analog %1 pin sensor value',\n                blacksmith_get_analog_mapping:\n                    'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\n                blacksmith_get_digital_bluetooth: 'Bluetooth RX 2 value',\n                blacksmith_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n                blacksmith_get_digital: 'Digital %1 pin sensor value',\n                blacksmith_get_digital_toggle: 'Digital %1 pin sensor value',\n                blacksmith_set_digital_toggle: 'Digital %1 pin %2 %3',\n                blacksmith_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n                blacksmith_set_digital_rgbled: 'Digital %1 pin RGB LED Red %2 Green %3 Blue %4 %5',\n                blacksmith_set_digital_servo: 'Set servo pin %1 angle as %2 %3',\n                blacksmith_set_digital_buzzer: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                blacksmith_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5',\n                blacksmith_module_digital_lcd: 'LCD %1 line %2 appear %3',\n                blacksmith_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\n                blacksmith_module_digital_oled: 'OLED X codinate %1 Y coodinate %2 appear %3 %4',\n            },\n            Blocks: {\n                blacksmith_toggle_on: 'on',\n                blacksmith_toggle_off: 'off',\n                blacksmith_lcd_first_line: 'first',\n                blacksmith_lcd_seconds_line: 'seconds',\n            },\n            Menus: {\n                blacksmith: 'Blacksmith Board',\n            },\n        },\n    };\n};\nEntry.Blacksmith.blockMenuBlocks = [\n    'blacksmith_get_analog_value',\n    'blacksmith_get_analog_mapping',\n    'blacksmith_get_digital_bluetooth',\n    'blacksmith_get_digital_ultrasonic',\n    'blacksmith_get_digital',\n    'blacksmith_get_digital_toggle',\n    'blacksmith_get_digital_pir',\n    'blacksmith_set_digital_toggle',\n    'blacksmith_set_digital_pwm',\n    'blacksmith_set_digital_rgbled',\n    'blacksmith_set_digital_servo',\n    'blacksmith_set_digital_buzzer',\n    'blacksmith_set_digital_dcmotor',\n    'blacksmith_module_digital_lcd',\n    'blacksmith_module_digital_bluetooth',\n    'blacksmith_module_digital_oled',\n];\nEntry.Blacksmith.getBlocks = function() {\n    return {\n        //region blacksmith 대장장이보드\n        blacksmith_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        blacksmith_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        blacksmith_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        blacksmith_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['~3', '3'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                        ['~11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        blacksmith_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.blacksmith_toggle_on, 'on'],\n                        [Lang.template.blacksmith_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        blacksmith_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        blacksmith_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.blacksmith_lcd_first_line, '0'],\n                        [Lang.template.blacksmith_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        blacksmith_list_digital_dcmotor_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.blacksmith_dcmotor_direction_reverse, '0'],\n                        [Lang.template.blacksmith_dcmotor_direction_forward, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIRECTION');\n            },\n        },\n        blacksmith_list_digital_btData_select: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.blacksmith_btData_select_number, '0'],\n                        [Lang.template.blacksmith_btData_select_character, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIRECTION');\n            },\n        },\n        blacksmith_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.blacksmith_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_analog_basic',\n                    },\n                ],\n                type: 'blacksmith_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'blacksmithGet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['blacksmith.get_analog_value(%1)'] },\n        },\n        blacksmith_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.blacksmith_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_analog_basic',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'blacksmith_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'blacksmithGet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                result = ANALOG ? ANALOG[port] || 0 : 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['blacksmith.get_analog_mapping(%1, %2, %3, %4, %5)'],\n            },\n        },\n        blacksmith_get_digital_bluetooth: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.blacksmith_get_digital_bluetooth,\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'blacksmith_get_digital_bluetooth',\n            },\n            paramsKeyMap: {},\n            class: 'blacksmithGet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = 2;\n                var getString = Entry.hw.portData.READ_BLUETOOTH;\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Blacksmith.sensorTypes.READ_BLUETOOTH] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return getString ? getString.slice(0, getString.length - 1) : ' ';\n            },\n            syntax: { js: [], py: ['blacksmith.get_digital_bluetooth()'] },\n        },\n        blacksmith_get_digital_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.blacksmith_get_digital_ultrasonic,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['4'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                ],\n                type: 'blacksmith_get_digital_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'blacksmithGet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Blacksmith.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['blacksmith.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n        blacksmith_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.blacksmith_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_basic',\n                    },\n                ],\n                type: 'blacksmith_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'blacksmithGet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.Blacksmith.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['blacksmith.get_digital(%1)'] },\n        },\n        blacksmith_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.blacksmith_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_basic',\n                    },\n                ],\n                type: 'blacksmith_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'blacksmithGet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Blacksmith.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['blacksmith.get_digital_toggle(%1)'] },\n        },\n        blacksmith_get_digital_pir: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.blacksmith_get_digital_pir,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_basic',\n                    },\n                ],\n                type: 'blacksmith_get_digital_pir',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'blacksmithGet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Blacksmith.sensorTypes.PIR] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['blacksmith.get_digital_pir(%1)'] },\n        },\n        blacksmith_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.blacksmith_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_basic',\n                    },\n                    {\n                        type: 'blacksmith_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'blacksmith_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'blacksmithSet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Blacksmith.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Blacksmith.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Blacksmith.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['blacksmith.set_digital_toggle(%1, %2)'] },\n        },\n        blacksmith_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.blacksmith_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_pwm',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'blacksmith_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'blacksmithSet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Blacksmith.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['blacksmith.set_digital_pwm(%1, %2)'] },\n        },\n        blacksmith_set_digital_rgbled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.blacksmith_set_digital_rgbled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_basic',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'blacksmith_set_digital_rgbled',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE0: 1,\n                VALUE1: 2,\n                VALUE2: 3,\n            },\n            class: 'blacksmithSet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = [3];\n                value[0] = script.getNumberValue('VALUE0');\n                value[1] = script.getNumberValue('VALUE1');\n                value[2] = script.getNumberValue('VALUE2');\n\n                for (var i = 0; i < 3; i++) {\n                    value[i] = Math.round(value[i]);\n                    value[i] = Math.min(value[i], 200);\n                    value[i] = Math.max(value[i], 0);\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Blacksmith.sensorTypes.RGBLED,\n                    data: {\n                        redValue: value[0],\n                        greenValue: value[1],\n                        blueValue: value[2],\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['blacksmith.set_digital_pwm(%1, %2)'] },\n        },\n        blacksmith_set_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.blacksmith_set_digital_servo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_basic',\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'blacksmith_set_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'blacksmithSet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Blacksmith.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['blacksmith.set_digital_servo(%1, %2)'] },\n        },\n        blacksmith_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.blacksmith_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_basic',\n                    },\n                    {\n                        type: 'blacksmith_list_digital_tone',\n                    },\n                    {\n                        type: 'blacksmith_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'blacksmith_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'blacksmithSet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.Blacksmith.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.Blacksmith.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.Blacksmith.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Blacksmith.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Blacksmith.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['blacksmith.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        blacksmith_set_digital_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.blacksmith_set_digital_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_basic',\n                    },\n                    {\n                        type: 'blacksmith_list_digital_dcmotor_direction',\n                    },\n                    {\n                        type: 'blacksmith_list_digital_pwm',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'blacksmith_set_digital_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT0: 0,\n                VALUE0: 1,\n                PORT1: 2,\n                VALUE1: 3,\n            },\n            class: 'blacksmithSet',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = 0; // port value is dummy;\n                var directionPort = script.getNumberValue('PORT0');\n                var speedPort = script.getNumberValue('PORT1');\n                var directionValue = script.getNumberValue('VALUE0');\n                var speedValue = script.getNumberValue('VALUE1');\n\n                speedValue = Math.round(speedValue);\n                speedValue = Math.min(speedValue, 255);\n                speedValue = Math.max(speedValue, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Blacksmith.sensorTypes.DCMOTOR,\n                    data: {\n                        port0: directionPort,\n                        port1: speedPort,\n                        value0: directionValue,\n                        value1: speedValue,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['blacksmith.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        blacksmith_module_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: Lang.template.blacksmith_module_digital_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'blacksmith_list_digital_lcd',\n                    },\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'blacksmith_module_digital_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                STRING: 1,\n            },\n            class: 'blacksmithModule',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var line = script.getNumberValue('LINE');\n                var string = script.getValue('STRING');\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][line] = {\n                        type: Entry.Blacksmith.sensorTypes.LCD,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['blacksmith.module_digital_lcd(%1, %2)'] },\n        },\n        blacksmith_module_digital_oled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.blacksmith_module_digital_oled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'blacksmith_module_digital_oled',\n            },\n            paramsKeyMap: {\n                VALUE0: 0,\n                VALUE1: 1,\n                STRING: 2,\n            },\n            class: 'blacksmithModule',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var port = 0; // port value is dummy;\n                var coodinate_x = script.getNumberValue('VALUE0');\n                var coodinate_y = script.getNumberValue('VALUE1');\n                var string = script.getValue('STRING');\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    coodinate_x = Math.min(coodinate_x, 127);\n                    coodinate_x = Math.max(coodinate_x, 0);\n                    coodinate_y = Math.min(coodinate_y, 63);\n                    coodinate_y = Math.max(coodinate_y, 0);\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Blacksmith.sensorTypes.OLED,\n                        data: {\n                            value0: coodinate_x,\n                            value1: coodinate_y,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['blacksmith.Module_digital_oled(%1, %2, %3)'] },\n        },\n        blacksmith_module_digital_bluetooth: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: Lang.template.blacksmith_module_digital_bluetooth,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'blacksmith_module_digital_bluetooth',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'blacksmithModule',\n            isNotFor: ['blacksmith'],\n            func: function(sprite, script) {\n                var string = script.getValue('STRING');\n                var port = 3;\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else {\n                        text[0] = string;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Blacksmith.sensorTypes.WRITE_BLUETOOTH,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['blacksmith.module_digital_bluetooth(%1)'] },\n        },\n        //endregion blacksmith 대장장이보드\n    };\n};\n\nmodule.exports = Entry.Blacksmith;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_bridge.js",
    "content": "'use strict';\n\nEntry.Bridge = {\n    id: '55.1',\n    name: 'Bridge',\n    imageName: 'bridge.png',\n    title: {\n        ko: '브릿지',\n        en: 'Bridge',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        DIGITAL: 1,\n    },\n    BlockState: {},\n};\n\nEntry.Bridge.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                bridge_get_digital1: ' 도 누름 ',\n                bridge_get_digital2: ' 레 누름 ',\n                bridge_get_digital3: ' 미 누름 ',\n                bridge_get_digital4: ' 파 누름 ',\n                bridge_get_digital5: ' 솔 누름 ',\n                bridge_get_digital6: ' 라 누름 ',\n                bridge_get_digital7: ' 시 누름 ',\n                bridge_get_digital8: ' 윗 도 누름 ',\n                bridge_get_digital9: ' 도# 누름 ',\n                bridge_get_digital10: ' 레# 누름 ',\n                bridge_get_digital11: ' 파# 누름 ',\n                bridge_get_digital12: ' 솔# 누름 ',\n                bridge_get_digital13: ' 라# 누름 ',\n            },\n        },\n    };\n};\n\nEntry.Bridge.blockMenuBlocks = [\n    'bridge_get_digital1',\n    'bridge_get_digital2',\n    'bridge_get_digital3',\n    'bridge_get_digital4',\n    'bridge_get_digital5',\n    'bridge_get_digital6',\n    'bridge_get_digital7',\n    'bridge_get_digital8',\n    'bridge_get_digital9',\n    'bridge_get_digital10',\n    'bridge_get_digital11',\n    'bridge_get_digital12',\n    'bridge_get_digital13',\n];\n\nEntry.Bridge.getBlocks = function() {\n    return {\n        bridge_get_digital1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 0;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        bridge_get_digital2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 1;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        bridge_get_digital3: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 2;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        bridge_get_digital4: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 3;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        bridge_get_digital5: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 4;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        bridge_get_digital6: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 5;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        bridge_get_digital7: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 6;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        bridge_get_digital8: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 7;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        bridge_get_digital9: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 8;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        bridge_get_digital10: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 9;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        bridge_get_digital11: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 10;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        bridge_get_digital12: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 11;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        bridge_get_digital13: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'BridgeGet',\n            isNotFor: ['Bridge'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Bridge' || name === 'ArduinoNano') {\n                    const port = 12;\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Bridge.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Bridge;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_brown.js",
    "content": "'use strict';\n\nEntry.Brown = {\n    setZero() {\n        Entry.Robomation.setZero();\n    },\n    afterReceive(pd) {\n        Entry.Robomation.afterReceive(pd, false);\n    },\n    afterSend(sq) {\n        Entry.Robomation.afterSend(sq);\n    },\n    getRobot() {\n        const robot = Entry.Robomation.getRobot('line', 0);\n        if (robot) {\n            robot.setMotoring(Entry.hw.sendQueue);\n        }\n        return robot;\n    },\n    id: '2.10',\n    name: 'brown',\n    url: 'http://robomation.jp',\n    imageName: 'brown.png',\n    title: {\n        en: 'Brown',\n        ko: '브라운',\n        jp: 'ブラウン',\n        vn: 'Brown',\n    },\n    monitorTemplate: () => ({\n        imgPath: 'hw/brown.png',\n        width: 300,\n        height: 387,\n        listPorts: {\n            colorNumber: {\n                name: Lang.Blocks.ROBOID_sensor_color_number,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorRed: {\n                name: Lang.Blocks.ROBOID_sensor_color_r,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorGreen: {\n                name: Lang.Blocks.ROBOID_sensor_color_g,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorBlue: {\n                name: Lang.Blocks.ROBOID_sensor_color_b,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationX: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            temperature: {\n                name: Lang.Blocks.ROBOID_sensor_temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            button: {\n                name: Lang.Blocks.ROBOID_sensor_button,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Blocks.ROBOID_monitor_buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: {\n                name: Lang.Blocks.ROBOID_monitor_note,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            floor: {\n                name: Lang.Blocks.ROBOID_sensor_floor,\n                type: 'input',\n                pos: { x: 95, y: 383 },\n            },\n            ledRed: {\n                name: `LED R`,\n                type: 'output',\n                pos: { x: 93, y: 278 },\n            },\n            ledGreen: {\n                name: `LED G`,\n                type: 'output',\n                pos: { x: 93, y: 278 },\n            },\n            ledBlue: {\n                name: `LED B`,\n                type: 'output',\n                pos: { x: 93, y: 278 },\n            },\n            leftWheel: {\n                name: Lang.Blocks.ROBOID_monitor_left_wheel,\n                type: 'output',\n                pos: { x: 288, y: 322 },\n            },\n            rightWheel: {\n                name: Lang.Blocks.ROBOID_monitor_right_wheel,\n                type: 'output',\n                pos: { x: 10, y: 322 },\n            },\n        },\n        mode: 'both',\n    }),\n};\n\nEntry.Brown.setLanguage = () => ({\n    ko: {\n        template: {\n            brown_touching_color: '%1 에 닿았는가?',\n            brown_is_color_pattern: '색깔 패턴이 %1 %2 인가?',\n            brown_button_state: '버튼을 %1 ?',\n            brown_boolean: '%1?',\n            brown_value: '%1',\n            brown_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n            brown_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n            brown_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n            brown_pivot_around_wheel_unit_in_direction: '%1 바퀴 중심으로 %2 %3 %4 방향으로 돌기 %5',\n            brown_turn_unit_with_radius_in_direction: '%1 으로 %2 %3 반지름 %4 cm를 %5 방향으로 돌기 %6',\n            brown_change_wheels_by_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            brown_set_wheels_to_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            brown_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            brown_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            brown_follow_line: '선 따라가기 %1',\n            brown_follow_line_until: '선을 따라 %1 까지 이동하기 %2',\n            brown_follow_line_until_intersection: '선을 따라 교차로까지 이동하기 %1',\n            brown_cross_intersection: '교차로 건너가기 %1',\n            brown_turn_at_intersection: '교차로에서 %1 으로 돌기 %2',\n            brown_jump_line: '%1 선으로 건너가기 %2',\n            brown_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n            brown_stop: '정지하기 %1',\n            brown_set_led_to: 'LED를 %1 으로 정하기 %2',\n            brown_pick_led: 'LED를 %1로 정하기 %2',\n            brown_change_led_by_rgb: 'LED를 R: %1 G: %2 B: %3 만큼 바꾸기 %4',\n            brown_set_led_to_rgb: 'LED를 R: %1 G: %2 B: %3 (으)로 정하기 %4',\n            brown_clear_led: 'LED 끄기 %1',\n            brown_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n            brown_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n            brown_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            brown_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            brown_clear_sound: '소리 끄기 %1',\n            brown_play_note: '%1 %2 음을 연주하기 %3',\n            brown_play_note_for_beats: '%1 %2 음을 %3 박자 연주하기 %4',\n            brown_rest_for_beats: '%1 박자 쉬기 %2',\n            brown_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            brown_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n        },\n        Helper: {\n            brown_touching_color: \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            brown_is_color_pattern: \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            brown_button_state: \"버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            brown_boolean: \"앞으로 기울임: 앞으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집었으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않았으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>두드림: 두드렸으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>자유 낙하: 자유 낙하했으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            brown_value: '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -2 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>색깔 R: 컬러 센서가 감지한 색깔의 빨간색(R) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>색깔 G: 컬러 센서가 감지한 색깔의 초록색(G) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>색깔 B: 컬러 센서가 감지한 색깔의 파란색(B) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -41 ~ 87도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.',\n            brown_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            brown_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            brown_turn_unit_in_place: '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            brown_pivot_around_wheel_unit_in_direction: '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 앞쪽/뒤쪽 방향으로 회전합니다.',\n            brown_turn_unit_with_radius_in_direction: '입력한 반지름의 원을 그리면서 입력한 시간(초)/펄스만큼 왼쪽/오른쪽, 앞쪽/뒤쪽 방향으로 회전합니다.',\n            brown_change_wheels_by_left_right: '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            brown_set_wheels_to_left_right: '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            brown_change_wheel_by: '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            brown_set_wheel_to: '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            brown_follow_line: '하얀색 바탕 위에서 검은색 선을 따라 이동합니다.',\n            brown_follow_line_until: '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n            brown_follow_line_until_intersection: '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 교차로에 도착하면 정지합니다.',\n            brown_cross_intersection: '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾습니다.',\n            brown_turn_at_intersection: '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾습니다.',\n            brown_jump_line: '제자리에서 왼쪽/오른쪽으로 90도 회전한 후 앞으로 이동하다가 컬러 센서가 검은색 선을 감지하면 원래 방향으로 다시 회전합니다.',\n            brown_set_following_speed_to: '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            brown_stop: '양쪽 바퀴를 정지합니다.',\n            brown_set_led_to: 'LED를 선택한 색깔로 켭니다.',\n            brown_pick_led: 'LED를 선택한 색깔로 켭니다.',\n            brown_change_led_by_rgb: 'LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            brown_set_led_to_rgb: 'LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            brown_clear_led: 'LED를 끕니다.',\n            brown_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            brown_play_sound_times_until_done: '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            brown_change_buzzer_by: '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            brown_set_buzzer_to: '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n            brown_clear_sound: '소리를 끕니다.',\n            brown_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            brown_play_note_for_beats: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            brown_rest_for_beats: '입력한 박자만큼 쉽니다.',\n            brown_change_tempo_by: '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            brown_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: '버저',\n            ROBOID_monitor_note: '음표',\n            ROBOID_monitor_left_wheel: '왼쪽 바퀴',\n            ROBOID_monitor_right_wheel: '오른쪽 바퀴',\n            ROBOID_sensor_signal_strength: '신호 세기',\n            ROBOID_sensor_color_r: '색깔 R',\n            ROBOID_sensor_color_g: '색깔 G',\n            ROBOID_sensor_color_b: '색깔 B',\n            ROBOID_sensor_floor: '바닥 센서',\n            ROBOID_sensor_acceleration_x: 'x축 가속도',\n            ROBOID_sensor_acceleration_y: 'y축 가속도',\n            ROBOID_sensor_acceleration_z: 'z축 가속도',\n            ROBOID_sensor_temperature: '온도',\n            ROBOID_sensor_button: '버튼',\n            ROBOID_sensor_color_number: '색깔 번호',\n            ROBOID_sensor_color_pattern: '색깔 패턴',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_orange: '주황색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_violet: '보라색',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_color_black: '검은색',\n            ROBOID_color_any: '아무 색',\n            ROBOID_clicked: '클릭했는가',\n            ROBOID_double_clicked: '더블클릭했는가',\n            ROBOID_long_pressed: '오래 눌렀는가',\n            ROBOID_tilt_forward: '앞으로 기울임',\n            ROBOID_tilt_backward: '뒤로 기울임',\n            ROBOID_tilt_left: '왼쪽으로 기울임',\n            ROBOID_tilt_right: '오른쪽으로 기울임',\n            ROBOID_tilt_flip: '거꾸로 뒤집음',\n            ROBOID_tilt_not: '기울이지 않음',\n            ROBOID_battery_normal: '배터리 정상',\n            ROBOID_battery_low: '배터리 부족',\n            ROBOID_battery_empty: '배터리 없음',\n            ROBOID_free_fall: '자유 낙하',\n            ROBOID_tap: '두드림',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '초',\n            ROBOID_unit_pulse: '펄스',\n            ROBOID_unit_deg: '도',\n            ROBOID_left: '왼쪽',\n            ROBOID_right: '오른쪽',\n            ROBOID_both: '양쪽',\n            ROBOID_back: '뒤쪽',\n            ROBOID_forward: '앞쪽',\n            ROBOID_backward: '뒤쪽',\n            ROBOID_sound_beep: '삐',\n            ROBOID_sound_random_beep: '무작위 삐',\n            ROBOID_sound_noise: '지지직',\n            ROBOID_sound_siren: '사이렌',\n            ROBOID_sound_engine: '엔진',\n            ROBOID_sound_chop: '쩝',\n            ROBOID_sound_robot: '로봇',\n            ROBOID_sound_dibidibidip: '디비디비딥',\n            ROBOID_sound_good_job: '잘 했어요',\n            ROBOID_sound_happy: '행복',\n            ROBOID_sound_angry: '화남',\n            ROBOID_sound_sad: '슬픔',\n            ROBOID_sound_sleep: '졸림',\n            ROBOID_sound_march: '행진',\n            ROBOID_sound_birthday: '생일',\n            ROBOID_note_c: '도',\n            ROBOID_note_c_sharp: '도♯(레♭)',\n            ROBOID_note_d: '레',\n            ROBOID_note_d_sharp: '레♯(미♭)',\n            ROBOID_note_e: '미',\n            ROBOID_note_f: '파',\n            ROBOID_note_f_sharp: '파♯(솔♭)',\n            ROBOID_note_g: '솔',\n            ROBOID_note_g_sharp: '솔♯(라♭)',\n            ROBOID_note_a: '라',\n            ROBOID_note_a_sharp: '라♯(시♭)',\n            ROBOID_note_b: '시',\n        },\n    },\n    en: {\n        template: {\n            brown_touching_color: 'touching %1 ?',\n            brown_is_color_pattern: 'color pattern %1 %2 ?',\n            brown_button_state: 'button %1 ?',\n            brown_boolean: '%1?',\n            brown_value: '%1',\n            brown_move_forward_unit: 'move forward %1 %2 %3',\n            brown_move_backward_unit: 'move backward %1 %2 %3',\n            brown_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            brown_pivot_around_wheel_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n            brown_turn_unit_with_radius_in_direction: 'turn %1 %2 %3 with radius %4 cm in %5 direction %6',\n            brown_change_wheels_by_left_right: 'change wheels by left: %1 right: %2 %3',\n            brown_set_wheels_to_left_right: 'set wheels to left: %1 right: %2 %3',\n            brown_change_wheel_by: 'change %1 wheel by %2 %3',\n            brown_set_wheel_to: 'set %1 wheel to %2 %3',\n            brown_follow_line: 'follow line %1',\n            brown_follow_line_until: 'follow line until %1 %2',\n            brown_follow_line_until_intersection: 'follow line until intersection %1',\n            brown_cross_intersection: 'cross intersection %1',\n            brown_turn_at_intersection: 'turn %1 at intersection %2',\n            brown_jump_line: 'jump to %1 line %2',\n            brown_set_following_speed_to: 'set following speed to %1 %2',\n            brown_stop: 'stop %1',\n            brown_set_led_to: 'set led to %1 %2',\n            brown_pick_led: 'set led to %1 %2',\n            brown_change_led_by_rgb: 'change led by r: %1 g: %2 b: %3 %4',\n            brown_set_led_to_rgb: 'set led to r: %1 g: %2 b: %3 %4',\n            brown_clear_led: 'clear led %1',\n            brown_play_sound_times: 'play sound %1 %2 times %3',\n            brown_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            brown_change_buzzer_by: 'change buzzer by %1 %2',\n            brown_set_buzzer_to: 'set buzzer to %1 %2',\n            brown_clear_sound: 'clear sound %1',\n            brown_play_note: 'play note %1 %2 %3',\n            brown_play_note_for_beats: 'play note %1 %2 for %3 beats %4',\n            brown_rest_for_beats: 'rest for %1 beats %2',\n            brown_change_tempo_by: 'change tempo by %1 %2',\n            brown_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            brown_touching_color: 'If the color sensor detects the selected color, true, otherwise false.',\n            brown_is_color_pattern: 'If the color sensor detects the selected color pattern, true, otherwise false.',\n            brown_button_state: 'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            brown_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>tap: If tapped, true, otherwise false<br/>free fall: If free fall, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            brown_value: 'color number: color number detected by the color sensor (range: -2 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1)<br/>color r: red component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color g: green component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color b: blue component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>temperature: temperature value inside the robot (range: -41 to 87 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.',\n            brown_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            brown_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            brown_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            brown_pivot_around_wheel_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            brown_turn_unit_with_radius_in_direction: 'Turns left/right drawing the circle of the entered radius in the forward/backward direction for the number of seconds/pulses entered.',\n            brown_change_wheels_by_left_right: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            brown_set_wheels_to_left_right: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            brown_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            brown_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            brown_follow_line: 'Moves along the black line on a white background.',\n            brown_follow_line_until: 'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            brown_follow_line_until_intersection: 'Moves along the black line on a white background and stops when the robot reaches the intersection.',\n            brown_cross_intersection: 'Moves forward for a moment at the black intersection, then finds the black line.',\n            brown_turn_at_intersection: 'Moves forward for a moment at the black intersection, then turns left/right/back in place and finds the black line.',\n            brown_jump_line: 'Turns left/right 90 degrees in place and moves forward. Stops when the color sensor detects the black line and turns to its original direction.',\n            brown_set_following_speed_to: 'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            brown_stop: 'Stops both wheels.',\n            brown_set_led_to: 'Turns the LED to the selected color.',\n            brown_pick_led: 'Turns the LED to the selected color.',\n            brown_change_led_by_rgb: 'Adds the entered values to the current R, G, B values of the LED, respectively.',\n            brown_set_led_to_rgb: 'Sets the R, G, B values of the LED to the entered values.',\n            brown_clear_led: 'Turns off the LED.',\n            brown_play_sound_times: 'Plays the selected sound as many times as entered.',\n            brown_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            brown_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            brown_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            brown_clear_sound: 'Turns off sound.',\n            brown_play_note: 'It sounds the selected tone and octave.',\n            brown_play_note_for_beats: 'It sounds the selected tone and octave as much as the beat you entered.',\n            brown_rest_for_beats: 'Rests as much as the beat you entered.',\n            brown_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            brown_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_color_r: 'color r',\n            ROBOID_sensor_color_g: 'color g',\n            ROBOID_sensor_color_b: 'color b',\n            ROBOID_sensor_floor: 'floor',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_temperature: 'temperature',\n            ROBOID_sensor_button: 'button',\n            ROBOID_sensor_color_number: 'color number',\n            ROBOID_sensor_color_pattern: 'color pattern',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_color_black: 'black',\n            ROBOID_color_any: 'any color',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_free_fall: 'free fall',\n            ROBOID_tap: 'tap',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_back: 'back',\n            ROBOID_forward: 'forward',\n            ROBOID_backward: 'backward',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n    jp: {\n        template: {\n            brown_touching_color: '%1 に着いたか？',\n            brown_is_color_pattern: '色パターンが %1 %2 か？',\n            brown_button_state: 'ボタンを %1 ?',\n            brown_boolean: '%1?',\n            brown_value: '%1',\n            brown_move_forward_unit: '前へ %1 %2 移動する %3',\n            brown_move_backward_unit: '後ろへ %1 %2 移動する %3',\n            brown_turn_unit_in_place: '%1 へ %2 %3 その場で回る %4',\n            brown_pivot_around_wheel_unit_in_direction: '%1 車輪を中心に %2 %3 %4 方向に回る %5',\n            brown_turn_unit_with_radius_in_direction: '%1 へ %2 %3 半径 %4 cmを %5 方向に回る %6',\n            brown_change_wheels_by_left_right: '左車輪を %1 右車輪を %2 ずつ変える %3',\n            brown_set_wheels_to_left_right: '左車輪を %1 右車輪を %2 にする %3',\n            brown_change_wheel_by: '%1 車輪を %2 ずつ変える %3',\n            brown_set_wheel_to: '%1 車輪を %2 にする %3',\n            brown_follow_line: '線にそって移動する %1',\n            brown_follow_line_until: '線にそって %1 まで移動する %2',\n            brown_follow_line_until_intersection: '線にそって交差点まで移動する %1',\n            brown_cross_intersection: '交差点を渡る %1',\n            brown_turn_at_intersection: '交差点で %1 へ回る %2',\n            brown_jump_line: '%1 線へわたる %2',\n            brown_set_following_speed_to: '線にそって移動する速さを %1 にする %2',\n            brown_stop: '停止する %1',\n            brown_set_led_to: 'LEDを %1 にする %2',\n            brown_pick_led: 'LEDを %1 にする %2',\n            brown_change_led_by_rgb: 'LEDをR: %1 G: %2 B: %3 ずつ変える %4',\n            brown_set_led_to_rgb: 'LEDをR: %1 G: %2 B: %3 にする %4',\n            brown_clear_led: 'LEDをオフにする %1',\n            brown_play_sound_times: '%1 音を %2 回再生する %3',\n            brown_play_sound_times_until_done: '%1 音を %2 回再生して待つ %3',\n            brown_change_buzzer_by: 'ブザー音を %1 ずつ変える %2',\n            brown_set_buzzer_to: 'ブザー音を %1 にする %2',\n            brown_clear_sound: '音をオフにする %1',\n            brown_play_note: '%1 %2 音をならす %3',\n            brown_play_note_for_beats: '%1 %2 音を %3 拍子ならす %4',\n            brown_rest_for_beats: '%1 拍子休む %2',\n            brown_change_tempo_by: '演奏のテンポを %1 ずつ変える %2',\n            brown_set_tempo_to: '演奏のテンポを %1 BPMにする %2',\n        },\n        Helper: {\n            brown_touching_color: '選択した色をカラーセンサーが感知したら「正しい」と判断してその他は｢正しくない｣と判断します。',\n            brown_is_color_pattern: '選択した色パターンをカラーセンサーが感知したら「正しい」と判断してその他は｢正しくない｣と判断します。',\n            brown_button_state: 'ボタンをクリックしたら、/ダブルクリックしたら、/長く押したら「正しい」と判断してその他は｢正しくない｣と判断します。',\n            brown_boolean: \"前にかたむけたか：前にかたむいたら「正しい」と判断してその他は「正しくない」と判断します。<br/>後にかたむけたか: 後ろにかたむいたら「正しい」と判断してその他は「正しくない」と判断します。<br/>左にかたむけたか：左にかたむいたら「正しい」と判断してその他は「正しくない」と判断します。<br/>右にかたむけたか：右にかたむいたら「正しい」と判断してその他は「正しくない」と判断します。<br/>うら返したか: うら裏返しになったら「正しい」と判断してその他は「正しくない」と判断します。<br/>かたむいてないか：かたむいてなかったら「正しい」と判断してその他は「正しくない」と判断します。<br/>叩いたか：叩いたら「正しい」と判断してその他は「正しくない」と判断します。<br/>落下したか：落下したら「正しい」と判断してその他は「正しくない」と判断します。<br/>電池残量が充分か：電池の残量が充分であれば「正しい」と判断してその他は「正しくない」と判断します。<br/>電池残量が足りないか：電池の残量が不足すると「正しい」と判断してその他は「正しくない」と判断します。<br/>電池残量がなくなったか：電池の残量がない場合「正しい」と判断してその他は「正しくない」と判断します。\",\n            brown_value: '色番号：カラーセンサーが感知した色の番号（値の範囲：-2〜8、初期値：-1）<br/>色パターン：カラーセンサーが感知した色パターンの値（値の範囲：-1〜88、初期値：-1）<br/>色R：カラーセンサーが感知した色の赤（R）成分（値の範囲：0〜255、初期値：0）<br/>色G：カラーセンサーが感知した色の緑（G）成分（値の範囲：0〜255、初期値：0）<br/>色B：カラーセンサーが感知した色の青色（B）成分（値の範囲：0〜255、初期値：0）<br/>床面センサー：床面センサーの値（値の範囲：0〜100、初期値：0）<br/>ボタン：ボタンの状態値（押すと1、違うと0、初期値：0）<br/>x軸の加速度：加速度センサーのX軸の値（値の範囲：-32768〜32767、初期値：0）ロボットが前進する方向がX軸の正の値方向です。<br/>y軸の加速度：加速度センサーのY軸の値（値の範囲：-32768〜32767、初期値：0）ロボットの左方向がY軸の正の値方向です。<br/>z軸の加速度：加速度センサーのZ軸の値（値の範囲：-32768〜32767、初期値：0）ロボットの上部方向がZ軸の正の値方向です。<br/>温度：ロボット内部の温度値（値の範囲：摂氏-41〜87度、初期値：0）<br/>信号の強さ：Bluetoothワイヤレス通信の信号強度（値の範囲：-128〜0 dBm、初期値：0）信号の強度が強いほど値が大きくなります。',\n            brown_move_forward_unit: '入力された距離(cm)/時間(秒)/パルスだけ前方に移動します。',\n            brown_move_backward_unit: '入力された距離(cm)/時間(秒)/パルスだけ後方に移動します。',\n            brown_turn_unit_in_place: '入力した角度(度)/時間(秒)/パルスだけ左/右方向にその場で回転します。',\n            brown_pivot_around_wheel_unit_in_direction: '左/右の車輪中心に入力した角度(度)/時間(秒)/パルスだけ前方/後方の方向に回転します。',\n            brown_turn_unit_with_radius_in_direction: '入力された半径の円形を描きながら入力した時間(秒)/パルスだけ左/右、前方/後方の方向に回転します。',\n            brown_change_wheels_by_left_right: '左と右の車輪の現在の速度値(％)で入力した値をそれぞれ加算します。加算した結果が正の値であれば、車輪が前方に回転し、負の値であれば後ろに回転します。',\n            brown_set_wheels_to_left_right: '左と右の車輪の速度を入力した値(-100〜100％)でそれぞれ設定します。正の値を入力すると車輪が前方に回転し、負の値を入力すると後ろに回転します。「0」を入力すると停止します。',\n            brown_change_wheel_by: '左/右/両方車輪の現在速度値(％)で入力した値を加算します。加算した結果が正の値であれば車輪が前方に回転し、負の値であれば後ろに回転します。',\n            brown_set_wheel_to: '左/右/両方車輪の速度を入力した値(-100〜100％)に設定します。正の値を入力すると車輪が前方に回転し、負の値を入力すると後ろに回転します。「0」を入力すると停止します。',\n            brown_follow_line: '白地にある黒い線にそって移動します。',\n            brown_follow_line_until: '白地にある黒い線にそって移動している途中で、選択した色をカラーセンサーが感知すると停止します。',\n            brown_follow_line_until_intersection: '白地にある黒い線にそって移動している途中で、交差点に到達すると停止します。',\n            brown_cross_intersection: '黒い線の交差点で少し前に移動した後、黒い線を探します。',\n            brown_turn_at_intersection: '黒い線の交差点で少し前に移動した後、その場で左/右/後ろに回転して黒い線を探します。',\n            brown_jump_line: 'その場で左/右に90度回転した後、前方に移動している途中で、黒い線をカラーセンサーが感知すると停止し、元の方向に回転します。',\n            brown_set_following_speed_to: '線にそって移動する速度(1〜8)を設定します。数字が大きいほど移動速度が速くなります。',\n            brown_stop: '両方の車輪を停止します。',\n            brown_set_led_to: 'LEDの色を選択した色に設定します。',\n            brown_pick_led: 'LEDの色を選択した色に設定します。',\n            brown_change_led_by_rgb: '現在のLEDの色に入力したR・G・Bの値をそれぞれ加算します。',\n            brown_set_led_to_rgb: 'LEDの色を入力したR・G・Bの値に設定します。',\n            brown_clear_led: 'LEDをオフにします。',\n            brown_play_sound_times: '選択された音を入力した回数だけ再生し、再生が完了するまで待ちます。',\n            brown_play_sound_times_until_done: '選択された音を入力した回数だけ再生し、再生が完了するまで待ちます。',\n            brown_change_buzzer_by: '現在のブザー音の高さ（Hz)に入力した値を加算します。 小数点以下2桁まで入力できます。',\n            brown_set_buzzer_to: 'ブザー音の高さを入力した値（Hz）に設定します。 小数点以下2桁まで入力できます。「0」を入力すると音がオフになります。',\n            brown_clear_sound: '音をオフにします。',\n            brown_play_note: '選択した音階（音名、オクターブ）の音をならします。',\n            brown_play_note_for_beats: '選択した音階（音名、オクターブ）の音を入力した拍子だけならします。',\n            brown_rest_for_beats: '入力した拍子だけ止めます。',\n            brown_change_tempo_by: '現在の演奏のBPM(毎分拍数)に入力した値を加算します。',\n            brown_set_tempo_to: '演奏の速度を入力したBPM(毎分拍数)に設定します。',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'ブザー',\n            ROBOID_monitor_note: '音符',\n            ROBOID_monitor_left_wheel: '左車輪',\n            ROBOID_monitor_right_wheel: '右車輪',\n            ROBOID_sensor_signal_strength: '信号の強さ',\n            ROBOID_sensor_color_r: '色R',\n            ROBOID_sensor_color_g: '色G',\n            ROBOID_sensor_color_b: '色B',\n            ROBOID_sensor_floor: '床面センサー',\n            ROBOID_sensor_acceleration_x: 'x軸の加速度',\n            ROBOID_sensor_acceleration_y: 'y軸の加速度',\n            ROBOID_sensor_acceleration_z: 'z軸の加速度',\n            ROBOID_sensor_temperature: '温度',\n            ROBOID_sensor_button: 'ボタン',\n            ROBOID_sensor_color_number: '色番号',\n            ROBOID_sensor_color_pattern: '色パターン',\n            ROBOID_color_red: '赤色',\n            ROBOID_color_orange: 'オレンジ色',\n            ROBOID_color_yellow: '黄色',\n            ROBOID_color_green: '緑色',\n            ROBOID_color_sky_blue: '水色',\n            ROBOID_color_blue: '青色',\n            ROBOID_color_violet: '青むらさき色',\n            ROBOID_color_purple: 'むらさき色',\n            ROBOID_color_white: '白色',\n            ROBOID_color_black: '黒色',\n            ROBOID_color_any: '全ての色',\n            ROBOID_clicked: 'クリックしたか',\n            ROBOID_double_clicked: 'ダブルクリックしたか',\n            ROBOID_long_pressed: '長く押したか',\n            ROBOID_tilt_forward: '前にかたむけたか',\n            ROBOID_tilt_backward: '後にかたむけたか',\n            ROBOID_tilt_left: '左にかたむけたか',\n            ROBOID_tilt_right: '右にかたむけたか',\n            ROBOID_tilt_flip: 'うら返したか',\n            ROBOID_tilt_not: 'かたむいてないか',\n            ROBOID_battery_normal: '電池残量が充分か',\n            ROBOID_battery_low: '電池残量が足りないか',\n            ROBOID_battery_empty: '電池残量がなくなったか',\n            ROBOID_free_fall: '落下したか',\n            ROBOID_tap: '叩いたか',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '秒',\n            ROBOID_unit_pulse: 'パルス',\n            ROBOID_unit_deg: '度',\n            ROBOID_left: '左',\n            ROBOID_right: '右',\n            ROBOID_both: '両方',\n            ROBOID_back: '後ろ',\n            ROBOID_forward: '前',\n            ROBOID_backward: '後',\n            ROBOID_sound_beep: 'ビープ',\n            ROBOID_sound_random_beep: 'ランダムビープ',\n            ROBOID_sound_noise: 'ノイズ',\n            ROBOID_sound_siren: 'サイレン',\n            ROBOID_sound_engine: 'エンジン',\n            ROBOID_sound_chop: 'チョップ',\n            ROBOID_sound_robot: 'ロボット',\n            ROBOID_sound_dibidibidip: 'ディビディビディ',\n            ROBOID_sound_good_job: 'よくできました',\n            ROBOID_sound_happy: 'よろこび',\n            ROBOID_sound_angry: 'いかり',\n            ROBOID_sound_sad: 'かなしみ',\n            ROBOID_sound_sleep: 'ねむい',\n            ROBOID_sound_march: 'マーチ',\n            ROBOID_sound_birthday: 'たんじょうび',\n            ROBOID_note_c: 'ド',\n            ROBOID_note_c_sharp: 'ド♯(レ♭)',\n            ROBOID_note_d: 'レ',\n            ROBOID_note_d_sharp: 'レ♯(ミ♭)',\n            ROBOID_note_e: 'ミ',\n            ROBOID_note_f: 'ファ',\n            ROBOID_note_f_sharp: 'ファ♯(ソ♭)',\n            ROBOID_note_g: 'ソ',\n            ROBOID_note_g_sharp: 'ソ♯(ラ♭)',\n            ROBOID_note_a: 'ラ',\n            ROBOID_note_a_sharp: 'ラ♯(シ♭)',\n            ROBOID_note_b: 'シ',\n        },\n    },\n    vn: {\n        template: {\n            brown_touching_color: 'touching %1 ?',\n            brown_is_color_pattern: 'color pattern %1 %2 ?',\n            brown_button_state: 'button %1 ?',\n            brown_boolean: '%1?',\n            brown_value: '%1',\n            brown_move_forward_unit: 'move forward %1 %2 %3',\n            brown_move_backward_unit: 'move backward %1 %2 %3',\n            brown_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            brown_pivot_around_wheel_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n            brown_turn_unit_with_radius_in_direction: 'turn %1 %2 %3 with radius %4 cm in %5 direction %6',\n            brown_change_wheels_by_left_right: 'change wheels by left: %1 right: %2 %3',\n            brown_set_wheels_to_left_right: 'set wheels to left: %1 right: %2 %3',\n            brown_change_wheel_by: 'change %1 wheel by %2 %3',\n            brown_set_wheel_to: 'set %1 wheel to %2 %3',\n            brown_follow_line: 'follow line %1',\n            brown_follow_line_until: 'follow line until %1 %2',\n            brown_follow_line_until_intersection: 'follow line until intersection %1',\n            brown_cross_intersection: 'cross intersection %1',\n            brown_turn_at_intersection: 'turn %1 at intersection %2',\n            brown_jump_line: 'jump to %1 line %2',\n            brown_set_following_speed_to: 'set following speed to %1 %2',\n            brown_stop: 'stop %1',\n            brown_set_led_to: 'set led to %1 %2',\n            brown_pick_led: 'set led to %1 %2',\n            brown_change_led_by_rgb: 'change led by r: %1 g: %2 b: %3 %4',\n            brown_set_led_to_rgb: 'set led to r: %1 g: %2 b: %3 %4',\n            brown_clear_led: 'clear led %1',\n            brown_play_sound_times: 'play sound %1 %2 times %3',\n            brown_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            brown_change_buzzer_by: 'change buzzer by %1 %2',\n            brown_set_buzzer_to: 'set buzzer to %1 %2',\n            brown_clear_sound: 'clear sound %1',\n            brown_play_note: 'play note %1 %2 %3',\n            brown_play_note_for_beats: 'play note %1 %2 for %3 beats %4',\n            brown_rest_for_beats: 'rest for %1 beats %2',\n            brown_change_tempo_by: 'change tempo by %1 %2',\n            brown_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            brown_touching_color: 'If the color sensor detects the selected color, true, otherwise false.',\n            brown_is_color_pattern: 'If the color sensor detects the selected color pattern, true, otherwise false.',\n            brown_button_state: 'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            brown_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>tap: If tapped, true, otherwise false<br/>free fall: If free fall, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            brown_value: 'color number: color number detected by the color sensor (range: -2 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1)<br/>color r: red component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color g: green component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color b: blue component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>temperature: temperature value inside the robot (range: -41 to 87 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.',\n            brown_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            brown_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            brown_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            brown_pivot_around_wheel_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            brown_turn_unit_with_radius_in_direction: 'Turns left/right drawing the circle of the entered radius in the forward/backward direction for the number of seconds/pulses entered.',\n            brown_change_wheels_by_left_right: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            brown_set_wheels_to_left_right: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            brown_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            brown_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            brown_follow_line: 'Moves along the black line on a white background.',\n            brown_follow_line_until: 'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            brown_follow_line_until_intersection: 'Moves along the black line on a white background and stops when the robot reaches the intersection.',\n            brown_cross_intersection: 'Moves forward for a moment at the black intersection, then finds the black line.',\n            brown_turn_at_intersection: 'Moves forward for a moment at the black intersection, then turns left/right/back in place and finds the black line.',\n            brown_jump_line: 'Turns left/right 90 degrees in place and moves forward. Stops when the color sensor detects the black line and turns to its original direction.',\n            brown_set_following_speed_to: 'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            brown_stop: 'Stops both wheels.',\n            brown_set_led_to: 'Turns the LED to the selected color.',\n            brown_pick_led: 'Turns the LED to the selected color.',\n            brown_change_led_by_rgb: 'Adds the entered values to the current R, G, B values of the LED, respectively.',\n            brown_set_led_to_rgb: 'Sets the R, G, B values of the LED to the entered values.',\n            brown_clear_led: 'Turns off the LED.',\n            brown_play_sound_times: 'Plays the selected sound as many times as entered.',\n            brown_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            brown_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            brown_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            brown_clear_sound: 'Turns off sound.',\n            brown_play_note: 'It sounds the selected tone and octave.',\n            brown_play_note_for_beats: 'It sounds the selected tone and octave as much as the beat you entered.',\n            brown_rest_for_beats: 'Rests as much as the beat you entered.',\n            brown_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            brown_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_color_r: 'color r',\n            ROBOID_sensor_color_g: 'color g',\n            ROBOID_sensor_color_b: 'color b',\n            ROBOID_sensor_floor: 'floor',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_temperature: 'temperature',\n            ROBOID_sensor_button: 'button',\n            ROBOID_sensor_color_number: 'color number',\n            ROBOID_sensor_color_pattern: 'color pattern',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_color_black: 'black',\n            ROBOID_color_any: 'any color',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_free_fall: 'free fall',\n            ROBOID_tap: 'tap',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_back: 'back',\n            ROBOID_forward: 'forward',\n            ROBOID_backward: 'backward',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n});\n\nEntry.Brown.blockMenuBlocks = [\n    'brown_value',\n    'brown_touching_color',\n    'brown_is_color_pattern',\n    'brown_button_state',\n    'brown_boolean',\n    'brown_move_forward_unit',\n    'brown_move_backward_unit',\n    'brown_turn_unit_in_place',\n    'brown_pivot_around_wheel_unit_in_direction',\n    'brown_turn_unit_with_radius_in_direction',\n    'brown_change_wheels_by_left_right',\n    'brown_set_wheels_to_left_right',\n    'brown_change_wheel_by',\n    'brown_set_wheel_to',\n    'brown_follow_line',\n    'brown_follow_line_until',\n    'brown_follow_line_until_intersection',\n    'brown_cross_intersection',\n    'brown_turn_at_intersection',\n    'brown_jump_line',\n    'brown_set_following_speed_to',\n    'brown_stop',\n    'brown_set_led_to',\n    'brown_pick_led',\n    'brown_change_led_by_rgb',\n    'brown_set_led_to_rgb',\n    'brown_clear_led',\n    'brown_play_sound_times',\n    'brown_play_sound_times_until_done',\n    'brown_change_buzzer_by',\n    'brown_set_buzzer_to',\n    'brown_clear_sound',\n    'brown_play_note',\n    'brown_play_note_for_beats',\n    'brown_rest_for_beats',\n    'brown_change_tempo_by',\n    'brown_set_tempo_to',\n];\n\nEntry.Brown.getBlocks = function() {\n    return {\n        brown_touching_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_touching_color',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'brown_sensor',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.checkTouchingColor(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.is_color(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_is_color_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'brown_is_color_pattern',\n            },\n            paramsKeyMap: {\n                COLOR1: 0,\n                COLOR2: 1,\n            },\n            class: 'brown_sensor',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.checkColorPattern(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.is_color_pattern(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_double_clicked, 'DOUBLE_CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_button_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'brown_sensor',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.checkButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.is_button(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_double_clicked, 'DOUBLE_CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.ROBOID_tap, 'TAP'],\n                        [Lang.Blocks.ROBOID_free_fall, 'FREE_FALL'],\n                        [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'brown_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'brown_sensor',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.ROBOID_tap, 'TAP'],\n                                    [Lang.Blocks.ROBOID_free_fall, 'FREE_FALL'],\n                                    [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sensor_color_number, 'COLOR_NUMBER'],\n                        [Lang.Blocks.ROBOID_sensor_color_pattern, 'COLOR_PATTERN'],\n                        [Lang.Blocks.ROBOID_sensor_color_r, 'COLOR_R'],\n                        [Lang.Blocks.ROBOID_sensor_color_g, 'COLOR_G'],\n                        [Lang.Blocks.ROBOID_sensor_color_b, 'COLOR_B'],\n                        [Lang.Blocks.ROBOID_sensor_floor, 'FLOOR'],\n                        [Lang.Blocks.ROBOID_sensor_button, 'BUTTON'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                        [Lang.Blocks.ROBOID_sensor_temperature, 'TEMPERATURE'],\n                        [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                    ],\n                    value: 'COLOR_NUMBER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'brown_sensor',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sensor_color_number, 'COLOR_NUMBER'],\n                                    [Lang.Blocks.ROBOID_sensor_color_pattern, 'COLOR_PATTERN'],\n                                    [Lang.Blocks.ROBOID_sensor_color_r, 'COLOR_R'],\n                                    [Lang.Blocks.ROBOID_sensor_color_g, 'COLOR_G'],\n                                    [Lang.Blocks.ROBOID_sensor_color_b, 'COLOR_B'],\n                                    [Lang.Blocks.ROBOID_sensor_floor, 'FLOOR'],\n                                    [Lang.Blocks.ROBOID_sensor_button, 'BUTTON'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                                    [Lang.Blocks.ROBOID_sensor_temperature, 'TEMPERATURE'],\n                                    [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                                ],\n                                value: 'COLOR_NUMBER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'brown_move_forward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.move_forward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'brown_move_backward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.move_backward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'brown_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_pivot_around_wheel_unit_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_backward, 'BACKWARD']\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'brown_pivot_around_wheel_unit_in_direction',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VALUE: 1,\n                UNIT: 2,\n                TOWARD: 3,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.pivotUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.pivot(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_backward, 'BACKWARD']\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_turn_unit_with_radius_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'SEC',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_backward, 'BACKWARD']\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['3'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'brown_turn_unit_with_radius_in_direction',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n                RADIUS: 3,\n                TOWARD: 4,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.circleUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.circle(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'SEC',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_backward, 'BACKWARD']\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_change_wheels_by_left_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'brown_change_wheels_by_left_right',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_set_wheels_to_left_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['40'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['40'],\n                    },\n                    null,\n                ],\n                type: 'brown_set_wheels_to_left_right',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'brown_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['40'],\n                    },\n                    null,\n                ],\n                type: 'brown_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_follow_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_follow_line',\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.follow_line()',\n                    },\n                ],\n            },\n        },\n        brown_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_any, 'ANY'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'brown_follow_line_until',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.follow_line_until(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_any, 'ANY'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_follow_line_until_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_follow_line_until_intersection',\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.followLineUntilIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.follow_line_until_intersection()',\n                    },\n                ],\n            },\n        },\n        brown_cross_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_cross_intersection',\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.crossIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.cross_forward()',\n                    },\n                ],\n            },\n        },\n        brown_turn_at_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_back, 'BACK'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'brown_turn_at_intersection',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.turnAtIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.cross_turn(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_back, 'BACK'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_jump_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'brown_jump_line',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.jumpLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.jump_line(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4', null],\n                type: 'brown_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.set_line_speed(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_stop',\n            },\n            class: 'brown_wheel',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.stop()',\n                    },\n                ],\n            },\n        },\n        brown_set_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'brown_set_led_to',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'brown_led',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.setLedColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.set_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_pick_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'brown_pick_led',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'brown_led',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.pickLedColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.pick_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'brown_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'brown_led',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.changeLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.add_rgb(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_set_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'brown_set_led_to_rgb',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'brown_led',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.setLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.set_rgb(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_clear_led',\n            },\n            class: 'brown_led',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.clear_led()',\n                    },\n                ],\n            },\n        },\n        brown_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'brown_play_sound_times',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.play_sound(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'brown_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.play_sound_until_done(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'brown_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.add_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        brown_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'brown_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.set_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        brown_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'brown_clear_sound',\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.clear_sound()',\n                    },\n                ],\n            },\n        },\n        brown_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'brown_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.play_pitch(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_play_note_for_beats: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'brown_play_note_for_beats',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.play_note(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_rest_for_beats: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'brown_rest_for_beats',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.rest(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'brown_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        brown_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'brown_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'brown_sound',\n            isNotFor: ['brown'],\n            func(sprite, script) {\n                const robot = Entry.Brown.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Brown.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Brown;"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_base.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_base = \n{\n    /***************************************************************************************\n     *  시간 지연 함수\n     ***************************************************************************************/\n\n    // 시간 지연\n    checkFinish(script, ms)\n    {\n        const _ms = this.fit(0, ms, 60000);\n\n        if (!script.isStart)\n        {\n            script.isStart  = true;\n            script.timeFlag = 1;\n\n            const fps       = Entry.FPS || 60;\n            const timeValue = (60 / fps) * _ms;\n\n            setTimeout(() => {\n                script.timeFlag = 0;\n            }, timeValue);\n\n            return 'Start';\n        }\n        else if (script.timeFlag == 1)\n        {\n            return 'Running';\n        }\n        else\n        {\n            delete script.timeFlag;\n            delete script.isStart;\n            Entry.engine.isContinue = false;\n            return 'Finish';\n        }\n    },\n\n\n    /***************************************************************************************\n     *  기능 함수\n     ***************************************************************************************/\n\n    transferBufferClear()\n    {\n        Entry.hw.sendQueue.buffer_clear = 0;\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.buffer_clear;\n    },\n\n\n    fit(min, value, max)\n    {\n        return Math.max(Math.min(value, max), min);\n    },\n\n\n    /***************************************************************************************\n     *  데이터 전송 함수 (Entry -> Hardware)\n     ***************************************************************************************/\n\n    // -- IR -----------------------------------------------------------------------------\n    transferIrMessage(target, irmessage)\n    {\n        // 전송\n        Entry.hw.sendQueue.target            = target;\n        Entry.hw.sendQueue.battle_ir_message = irmessage;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.battle_ir_message;\n    },\n\n\n    // -- Light -----------------------------------------------------------------------------\n    transferLightManual(target, flags, brightness)\n    {\n        Entry.hw.sendQueue.target                  = target;\n        Entry.hw.sendQueue.light_manual_flags      = flags;\n        Entry.hw.sendQueue.light_manual_brightness = brightness;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.light_manual_flags;\n        delete Entry.hw.sendQueue.light_manual_brightness;\n    },\n\n\n    transferLightMode(target, mode, interval)\n    {\n        Entry.hw.sendQueue.target              = target;\n        Entry.hw.sendQueue.light_mode_mode     = mode;\n        Entry.hw.sendQueue.light_mode_interval = interval;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.light_mode_mode;\n        delete Entry.hw.sendQueue.light_mode_interval;\n    },\n\n\n    transferLightModeColor(target, mode, interval, red, green, blue)\n    {\n        Entry.hw.sendQueue.target              = target;\n        Entry.hw.sendQueue.light_mode_mode     = mode;\n        Entry.hw.sendQueue.light_mode_interval = interval;\n        Entry.hw.sendQueue.light_color_r       = red;\n        Entry.hw.sendQueue.light_color_g       = green;\n        Entry.hw.sendQueue.light_color_b       = blue;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.light_mode_mode;\n        delete Entry.hw.sendQueue.light_mode_interval;\n        delete Entry.hw.sendQueue.light_color_r;\n        delete Entry.hw.sendQueue.light_color_g;\n        delete Entry.hw.sendQueue.light_color_b;\n    },\n\n\n    transferLightEvent(target, event, interval, repeat)\n    {\n        Entry.hw.sendQueue.target               = target;\n        Entry.hw.sendQueue.light_event_event    = event;\n        Entry.hw.sendQueue.light_event_interval = interval;\n        Entry.hw.sendQueue.light_event_repeat   = repeat;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.light_event_event;\n        delete Entry.hw.sendQueue.light_event_interval;\n        delete Entry.hw.sendQueue.light_event_repeat;\n    },\n\n\n    transferLightEventColor(target, event, interval, repeat, red, green, blue)\n    {\n        Entry.hw.sendQueue.target               = target;\n        Entry.hw.sendQueue.light_event_event    = event;\n        Entry.hw.sendQueue.light_event_interval = interval;\n        Entry.hw.sendQueue.light_event_repeat   = repeat;\n        Entry.hw.sendQueue.light_color_r        = red;\n        Entry.hw.sendQueue.light_color_g        = green;\n        Entry.hw.sendQueue.light_color_b        = blue;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.light_event_event;\n        delete Entry.hw.sendQueue.light_event_interval;\n        delete Entry.hw.sendQueue.light_event_repeat;\n        delete Entry.hw.sendQueue.light_color_r;\n        delete Entry.hw.sendQueue.light_color_g;\n        delete Entry.hw.sendQueue.light_color_b;\n    },\n\n\n    // -- Display -----------------------------------------------------------------------------\n    transferDisplayClearAll(target, pixel)\n    {\n        Entry.hw.sendQueue.target                  = target;\n        Entry.hw.sendQueue.display_clear_all_pixel = pixel;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_clear_all_pixel;\n    },\n\n\n    transferDisplayClear(target, pixel, x, y, width, height)\n    {\n        Entry.hw.sendQueue.target               = target;\n        Entry.hw.sendQueue.display_clear_x      = x;\n        Entry.hw.sendQueue.display_clear_y      = y;\n        Entry.hw.sendQueue.display_clear_width  = width;\n        Entry.hw.sendQueue.display_clear_height = height;\n        Entry.hw.sendQueue.display_clear_pixel  = pixel;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_clear_x;\n        delete Entry.hw.sendQueue.display_clear_y;\n        delete Entry.hw.sendQueue.display_clear_width;\n        delete Entry.hw.sendQueue.display_clear_height;\n        delete Entry.hw.sendQueue.display_clear_pixel;\n    },\n\n\n    transferDisplayInvert(target, x, y, width, height)\n    {\n        Entry.hw.sendQueue.target                = target;\n        Entry.hw.sendQueue.display_invert_x      = x;\n        Entry.hw.sendQueue.display_invert_y      = y;\n        Entry.hw.sendQueue.display_invert_width  = width;\n        Entry.hw.sendQueue.display_invert_height = height;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_invert_x;\n        delete Entry.hw.sendQueue.display_invert_y;\n        delete Entry.hw.sendQueue.display_invert_width;\n        delete Entry.hw.sendQueue.display_invert_height;\n    },\n\n\n    transferDisplayDrawPoint(target, x, y, pixel)\n    {\n        Entry.hw.sendQueue.target                   = target;\n        Entry.hw.sendQueue.display_draw_point_x     = x;\n        Entry.hw.sendQueue.display_draw_point_y     = y;\n        Entry.hw.sendQueue.display_draw_point_pixel = pixel;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_draw_point_x;\n        delete Entry.hw.sendQueue.display_draw_point_y;\n        delete Entry.hw.sendQueue.display_draw_point_pixel;\n    },\n\n\n    transferDisplayDrawLine(target, x1, y1, x2, y2, pixel, line)\n    {\n        Entry.hw.sendQueue.target                  = target;\n        Entry.hw.sendQueue.display_draw_line_x1    = x1;\n        Entry.hw.sendQueue.display_draw_line_y1    = y1;\n        Entry.hw.sendQueue.display_draw_line_x2    = x2;\n        Entry.hw.sendQueue.display_draw_line_y2    = y2;\n        Entry.hw.sendQueue.display_draw_line_pixel = pixel;\n        Entry.hw.sendQueue.display_draw_line_line  = line;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_draw_line_x1;\n        delete Entry.hw.sendQueue.display_draw_line_y1;\n        delete Entry.hw.sendQueue.display_draw_line_x2;\n        delete Entry.hw.sendQueue.display_draw_line_y2;\n        delete Entry.hw.sendQueue.display_draw_line_pixel;\n        delete Entry.hw.sendQueue.display_draw_line_line;\n    },\n\n\n    transferDisplayDrawRect(target, x, y, width, height, pixel, flagFill, line)\n    {\n        Entry.hw.sendQueue.target                     = target;\n        Entry.hw.sendQueue.display_draw_rect_x        = x;\n        Entry.hw.sendQueue.display_draw_rect_y        = y;\n        Entry.hw.sendQueue.display_draw_rect_width    = width;\n        Entry.hw.sendQueue.display_draw_rect_height   = height;\n        Entry.hw.sendQueue.display_draw_rect_pixel    = pixel;\n        Entry.hw.sendQueue.display_draw_rect_flagfill = flagFill;\n        Entry.hw.sendQueue.display_draw_rect_line     = line;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_draw_rect_x;\n        delete Entry.hw.sendQueue.display_draw_rect_y;\n        delete Entry.hw.sendQueue.display_draw_rect_width;\n        delete Entry.hw.sendQueue.display_draw_rect_height;\n        delete Entry.hw.sendQueue.display_draw_rect_pixel;\n        delete Entry.hw.sendQueue.display_draw_rect_flagfill;\n        delete Entry.hw.sendQueue.display_draw_rect_line;\n    },\n\n\n    transferDisplayDrawCircle(target, x, y, radius, pixel, flagFill)\n    {\n        Entry.hw.sendQueue.target                       = target;\n        Entry.hw.sendQueue.display_draw_circle_x        = x;\n        Entry.hw.sendQueue.display_draw_circle_y        = y;\n        Entry.hw.sendQueue.display_draw_circle_radius   = radius;\n        Entry.hw.sendQueue.display_draw_circle_pixel    = pixel;\n        Entry.hw.sendQueue.display_draw_circle_flagfill = flagFill;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_draw_circle_x;\n        delete Entry.hw.sendQueue.display_draw_circle_y;\n        delete Entry.hw.sendQueue.display_draw_circle_radius;\n        delete Entry.hw.sendQueue.display_draw_circle_pixel;\n        delete Entry.hw.sendQueue.display_draw_circle_flagfill;\n    },\n\n\n    transferDisplayDrawString(target, x, y, font, pixel, string)\n    {\n        Entry.hw.sendQueue.target                     = target;\n        Entry.hw.sendQueue.display_draw_string_x      = x;\n        Entry.hw.sendQueue.display_draw_string_y      = y;\n        Entry.hw.sendQueue.display_draw_string_font   = font;\n        Entry.hw.sendQueue.display_draw_string_pixel  = pixel;\n        Entry.hw.sendQueue.display_draw_string_string = string;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_draw_string_x;\n        delete Entry.hw.sendQueue.display_draw_string_y;\n        delete Entry.hw.sendQueue.display_draw_string_font;\n        delete Entry.hw.sendQueue.display_draw_string_pixel;\n        delete Entry.hw.sendQueue.display_draw_string_string;\n    },\n\n\n    transferDisplayDrawStringAlign(target, xStart, xEnd, y, align, font, pixel, string)\n    {\n        Entry.hw.sendQueue.target                            = target;\n        Entry.hw.sendQueue.display_draw_string_align_x_start = xStart;\n        Entry.hw.sendQueue.display_draw_string_align_x_end   = xEnd;\n        Entry.hw.sendQueue.display_draw_string_align_y       = y;\n        Entry.hw.sendQueue.display_draw_string_align_align   = align;\n        Entry.hw.sendQueue.display_draw_string_align_font    = font;\n        Entry.hw.sendQueue.display_draw_string_align_pixel   = pixel;\n        Entry.hw.sendQueue.display_draw_string_align_string  = string;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.display_draw_string_align_x_start;\n        delete Entry.hw.sendQueue.display_draw_string_align_x_end;\n        delete Entry.hw.sendQueue.display_draw_string_align_y;\n        delete Entry.hw.sendQueue.display_draw_string_align_align;\n        delete Entry.hw.sendQueue.display_draw_string_align_font;\n        delete Entry.hw.sendQueue.display_draw_string_align_pixel;\n        delete Entry.hw.sendQueue.display_draw_string_align_string;\n    },\n\n\n    // -- Buzzer -----------------------------------------------------------------------------\n    transferBuzzer(target, mode, value, time)\n    {\n        Entry.hw.sendQueue.target       = target;\n        Entry.hw.sendQueue.buzzer_mode  = mode;\n        Entry.hw.sendQueue.buzzer_value = value;\n        Entry.hw.sendQueue.buzzer_time  = time;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.buzzer_mode;\n        delete Entry.hw.sendQueue.buzzer_value;\n        delete Entry.hw.sendQueue.buzzer_time;\n    },\n\n\n    // -- Vibrator -----------------------------------------------------------------------------\n    transferVibrator(target, mode, timeOn, timeOff, timeRun)\n    {\n        Entry.hw.sendQueue.target         = target;\n        Entry.hw.sendQueue.vibrator_mode  = mode;\n        Entry.hw.sendQueue.vibrator_on    = timeOn;\n        Entry.hw.sendQueue.vibrator_off   = timeOff;\n        Entry.hw.sendQueue.vibrator_total = timeRun;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.vibrator_mode;\n        delete Entry.hw.sendQueue.vibrator_on;\n        delete Entry.hw.sendQueue.vibrator_off;\n        delete Entry.hw.sendQueue.vibrator_total;\n    },\n\n\n    // -- MotorSingle -----------------------------------------------------------------------------\n    transferMotorSingleRV(target, motorIndex, motorRotation, motorSpeed)\n    {\n        Entry.hw.sendQueue.target               = target;\n        Entry.hw.sendQueue.motorsingle_target   = motorIndex;\n        Entry.hw.sendQueue.motorsingle_rotation = motorRotation;\n        Entry.hw.sendQueue.motorsingle_value    = motorSpeed;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.motorsingle_target;\n        delete Entry.hw.sendQueue.motorsingle_rotation;\n        delete Entry.hw.sendQueue.motorsingle_value;\n    },\n\n\n    transferMotorSingleV(target, motorIndex, motorSpeed)\n    {\n        Entry.hw.sendQueue.target             = target;\n        Entry.hw.sendQueue.motorsingle_target = motorIndex;\n        Entry.hw.sendQueue.motorsingle_value  = motorSpeed;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.motorsingle_target;\n        delete Entry.hw.sendQueue.motorsingle_value;\n    },\n\n\n    // -- Command -----------------------------------------------------------------------------\n    transferCommand(target, command, option)\n    {\n        Entry.hw.sendQueue.target          = target;\n        Entry.hw.sendQueue.command_command = command;\n        Entry.hw.sendQueue.command_option  = option;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.command_command;\n        delete Entry.hw.sendQueue.command_option;\n    },\n\n\n    // -- Trim -----------------------------------------------------------------------------\n    transferTrim(target, roll, pitch, yaw, throttle)\n    {\n        Entry.hw.sendQueue.target        = target;\n        Entry.hw.sendQueue.trim_roll     = roll;\n        Entry.hw.sendQueue.trim_pitch    = pitch;\n        Entry.hw.sendQueue.trim_yaw      = yaw;\n        Entry.hw.sendQueue.trim_throttle = throttle;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.trim_roll;\n        delete Entry.hw.sendQueue.trim_pitch;\n        delete Entry.hw.sendQueue.trim_yaw;\n        delete Entry.hw.sendQueue.trim_throttle;\n    },\n\n\n    // -- Control -----------------------------------------------------------------------------\n    transferControlQuad(target, roll, pitch, yaw, throttle)\n    {\n        Entry.hw.sendQueue.target                 = target;\n        Entry.hw.sendQueue.control_quad8_roll     = roll;\n        Entry.hw.sendQueue.control_quad8_pitch    = pitch;\n        Entry.hw.sendQueue.control_quad8_yaw      = yaw;\n        Entry.hw.sendQueue.control_quad8_throttle = throttle;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.control_quad8_roll;\n        delete Entry.hw.sendQueue.control_quad8_pitch;\n        delete Entry.hw.sendQueue.control_quad8_yaw;\n        delete Entry.hw.sendQueue.control_quad8_throttle;\n    },\n\n\n    transferControlPosition(target, x, y, z, velocity, heading, rotationalVelocity)\n    {\n        Entry.hw.sendQueue.target                               = target;\n        Entry.hw.sendQueue.control_position_x                   = x;\n        Entry.hw.sendQueue.control_position_y                   = y;\n        Entry.hw.sendQueue.control_position_z                   = z;\n        Entry.hw.sendQueue.control_position_velocity            = velocity;\n        Entry.hw.sendQueue.control_position_heading             = heading;\n        Entry.hw.sendQueue.control_position_rotational_velocity = rotationalVelocity;\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue.target;\n        delete Entry.hw.sendQueue.control_position_x;\n        delete Entry.hw.sendQueue.control_position_y;\n        delete Entry.hw.sendQueue.control_position_z;\n        delete Entry.hw.sendQueue.control_position_velocity;\n        delete Entry.hw.sendQueue.control_position_heading;\n        delete Entry.hw.sendQueue.control_position_rotational_velocity;\n    },\n\n\n    /***************************************************************************************\n     *  기능\n     ***************************************************************************************/\n\n    // 데이터 읽기\n    getData(script, device)\n    {\n        return Entry.hw.portData[device];\n    },\n\n\n    getRgbFromString(stringColor)\n    {\n        let red   = 0;\n        let green = 0;\n        let blue  = 0;\n\n        switch (stringColor)\n        {\n            case 'red'           : { red = 255;  green = 0;    blue = 0;   }   break;\n            case 'green'         : { red = 0;    green = 255;  blue = 0;   }   break;\n            case 'blue'          : { red = 0;    green = 0;    blue = 255; }   break;\n            case 'cyan'          : { red = 0;    green = 255;  blue = 255; }   break;\n            case 'magenta'       : { red = 255;  green = 0;    blue = 255; }   break;\n            case 'yellow'        : { red = 255;  green = 255;  blue = 0;   }   break;\n            case 'white'         : { red = 255;  green = 255;  blue = 255; }   break;\n            case 'sunset'        : { red = 255;  green = 100;  blue = 0;   }   break;\n            case 'cottonCandy'   : { red = 20;   green = 250;  blue = 150; }   break;\n            case 'muscat'        : { red = 70;   green = 255;  blue = 0;   }   break;\n            case 'strawberryMilk': { red = 150;  green = 60;   blue = 20;  }   break;\n            case 'emerald'       : { red = 0;    green = 255;  blue = 30;  }   break;\n            case 'lavender'      : { red = 80;   green = 0;    blue = 200; }   break;\n        }\n\n        return { r:red, g:green, b:blue };\n    },\n\n\n\n    /***************************************************************************************\n     *  블럭 연동 함수\n     ***************************************************************************************/\n\n    // -- IR -----------------------------------------------------------------------------\n    // IR 데이터 송신\n    setIrMessage(script, target, irmessage)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferIrMessage(target, irmessage);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- Light -----------------------------------------------------------------------------\n    // LED 수동 설정\n    setLightManual(script, target, flags, brightness)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferLightManual(target, flags, brightness);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // LED 모드 설정\n    setLightMode(script, target, mode, interval)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferLightMode(target, mode, interval);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // LED 모드 설정, RGB\n    setLightModeColor(script, target, mode, interval, red, green, blue)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferLightModeColor(target, mode, interval, red, green, blue);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // LED 모드 설정, RGB\n    setLightModeColorString(script, target, mode, interval, stringColor)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    const color = this.getRgbFromString(stringColor);\n                    this.transferLightModeColor(target, mode, interval, color.r, color.g, color.b);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // LED 이벤트 설정\n    setLightEvent(script, target, mode, interval, repeat)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferLightEvent(target, mode, interval, repeat);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // LED 이벤트 설정, RGB\n    setLightEventColor(script, target, mode, interval, repeat, red, green, blue)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferLightEventColor(target, mode, interval, repeat, red, green, blue);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // LED 이벤트 설정, RGB\n    setLightEventColorString(script, target, mode, interval, repeat, stringColor)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    const color = this.getRgbFromString(stringColor);\n                    this.transferLightEventColor(target, mode, interval, repeat, color.r, color.g, color.b);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- Display -----------------------------------------------------------------------------\n    // 화면 전체 지우기, 선택 영역 지우기\n    setDisplayClearAll(script, target, pixel)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferDisplayClearAll(target, pixel);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 화면 전체 지우기, 선택 영역 지우기\n    setDisplayClear(script, target, pixel, x, y, width, height)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferDisplayClear(target, pixel, x, y, width, height);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 선택 영역 반전\n    setDisplayInvert(script, target, x, y, width, height)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferDisplayInvert(target, x, y, width, height);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 화면에 점 찍기\n    setDisplayDrawPoint(script, target, x, y, pixel)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferDisplayDrawPoint(target, x, y, pixel);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 화면에 선 그리기\n    setDisplayDrawLine(script, target, x1, y1, x2, y2, pixel, line)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferDisplayDrawLine(target, x1, y1, x2, y2, pixel, line);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 화면에 사각형 그리기\n    setDisplayDrawRect(script, target, x, y, width, height, pixel, flagFill, line)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferDisplayDrawRect(target, x, y, width, height, pixel, flagFill, line);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 화면에 원 그리기\n    setDisplayDrawCircle(script, target, x, y, radius, pixel, flagFill)\n    {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start': \n                {\n                    this.transferDisplayDrawCircle(target, x, y, radius, pixel, flagFill);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 화면에 문자열 쓰기\n    setDisplayDrawString(script, target, x, y, font, pixel, string)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferDisplayDrawString(target, x, y, font, pixel, string);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 화면에 문자열 정렬하여 그리기\n    setDisplayDrawStringAlign(script, target, xStart, xEnd, y, align, font, pixel, string)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferDisplayDrawStringAlign(target, xStart, xEnd, y, align, font, pixel, string);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- Buzzer -----------------------------------------------------------------------------\n    // 버저 설정(함수 호출 시 시간은 모두 ms 단위 사용)\n    /*\n        MuteInstantally = 1,   // 묵음 즉시 적용\n        MuteContinually = 2,   // 묵음 예약\n\n        ScaleInstantally = 3,   // 음계 즉시 적용\n        ScaleContinually = 4,   // 음계 예약\n\n        HzInstantally = 5,   // 주파수 즉시 적용\n        HzContinually = 6,   // 주파수 예약\n     */\n    // 정지\n    setBuzzerStop(script, target)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferBuzzer(target, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // 묵음\n    setBuzzerMute(script, target, time, flagDelay, flagInstantly)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    let mode = 2;  // 묵음 연속\n                    if (flagInstantly)\n                    {\n                        mode = 1;\n                    } // 묵음 즉시\n\n                    this.transferBuzzer(target, mode, 0xee, time);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    setBuzzerScale(script, target, octave, scale, time, flagDelay, flagInstantly)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    let mode = 4;  // Scale 연속\n                    if (flagInstantly)\n                    {\n                        mode = 3;\n                    } // Scale 즉시\n\n                    const scale_index = octave * 12 + scale;\n\n                    this.transferBuzzer(target, mode, scale_index, time);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    setBuzzerHz(script, target, hz, time, flagDelay, flagInstantly)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    let mode = 6;  // Hz 연속\n                    if (flagInstantly)\n                    {\n                        mode = 5;\n                    } // Hz 즉시\n                    this.transferBuzzer(target, mode, hz, time);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- Vibrator -----------------------------------------------------------------------------\n    // 진동 제어\n    /*\n        Stop        = 0,   // 정지\n        Instantally = 1,   // 즉시 적용\n        Continually = 2,   // 예약\n     */\n    setVibratorStop(script, target)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferVibrator(target, 0, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    setVibrator(script, target, timeOn, timeOff, timeRun, flagDelay, flagInstantly)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, timeRun);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    let mode = 2;  // 예약\n                    if (flagInstantly)\n                    {\n                        mode = 1;  // 즉시\n                    }\n\n                    this.transferVibrator(target, mode, timeOn, timeOff, timeRun);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- Command -----------------------------------------------------------------------------\n    sendStop(script, target)\n    {\n        return this.sendCommand(script, target, 0x01);\n    },\n\n\n    sendCommand(script, target, command, option = 0, timeDelay = 40)\n    {\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    this.transferCommand(target, command, option);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- MotorSingle -----------------------------------------------------------------------------\n    setMotorSingleRV(script, target, motorIndex, motorRotation, motorSpeed)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferMotorSingleRV(target, motorIndex, motorRotation, motorSpeed);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    setMotorSingleV(script, target, motorIndex, motorSpeed)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start': \n                {\n                    this.transferMotorSingleV(target, motorIndex, motorSpeed);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- EventFlight -----------------------------------------------------------------------------\n    setEventFlight(script, target, eventFlight, time)\n    {\n        switch (this.checkFinish(script, time))\n        {\n            case 'Start': \n                {\n                    this.transferControlQuad(0, 0, 0, 0); // 기존 입력되었던 조종기 방향 초기화 (수직으로 이륙, 착륙 하도록)\n                    this.transferCommand(target, 0x07, eventFlight); // 0x07 : CommandType::FlightEvent\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- Trim -----------------------------------------------------------------------------\n    sendTrim(script, target, roll, pitch, yaw, throttle)\n    {\n        let timeDelay = 40;\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    this.transferTrim(target, roll, pitch, yaw, throttle);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    // -- Control -----------------------------------------------------------------------------\n    sendControlQuadSingle(script, target, controlTarget, value, time = 40, flagDelay = false)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    Entry.hw.sendQueue.target           = target;\n                    Entry.hw.sendQueue[controlTarget]   = value;\n\n                    Entry.hw.update();\n\n                    delete Entry.hw.sendQueue.target;\n                    delete Entry.hw.sendQueue[controlTarget];\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                if (flagDelay)\n                {\n                    // 블럭을 빠져나갈 때 변경했던 값을 초기화\n                    Entry.hw.sendQueue.target           = target;\n                    Entry.hw.sendQueue[controlTarget]   = 0;\n\n                    Entry.hw.update();\n\n                    delete Entry.hw.sendQueue.target;\n                    delete Entry.hw.sendQueue[controlTarget];\n                }\n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    sendControlQuad(script, target, roll, pitch, yaw, throttle, time = 40, flagDelay = false)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    this.transferControlQuad(target, roll, pitch, yaw, throttle);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                if (flagDelay)\n                {\n                    this.transferControlQuad(target, 0, 0, 0, 0);\n                }\n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n\n\n    sendControlPosition(script, target, x, y, z, velocity, heading, rotationalVelocity, time = 40, flagDelay = false)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start': \n                {\n                    this.transferControlQuad(target, 0, 0, 0, 0);\n                    this.transferControlPosition(target, x, y, z, velocity, heading, rotationalVelocity);\n                }\n                return script;\n\n            case 'Running': \n                return script;\n\n            case 'Finish': \n                return script.callReturn();\n\n            default: \n                return script.callReturn();\n        }\n    },\n};\n\n\nmodule.exports = Entry.byrobot_base;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_controller_3_4.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_controller_3_4 =\n{\n    id       : 'F.C',\n    name     : 'byrobot_controller_3_4',\n    url      : 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_controller_3_4.png',\n    title    : {\n        en: 'BYROBOT Battle Drone Controller',\n        ko: '바이로봇 배틀 드론 조종기',\n    },\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero()\n    {\n        // 초기화\n        Entry.byrobot_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            Entry.byrobot_base.transferBuzzer(0x20, 0, 0, 0);\n            Entry.byrobot_base.transferVibrator(0x20, 0, 0, 0, 0);\n            Entry.byrobot_base.transferLightManual(0x20, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightModeColor(0x20, 0x22, 200, 255, 0, 0); // LED 초기화(조종기)\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.byrobot_controller_3_4.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                // 정보창\n                monitor_joystick_left_x              : '왼쪽 조이스틱 X',\n                monitor_joystick_left_y              : '왼쪽 조이스틱 Y',\n                monitor_joystick_left_direction      : '왼쪽 조이스틱 방향',\n                monitor_joystick_left_event          : '왼쪽 조이스틱 이벤트',\n                monitor_joystick_right_x             : '오른쪽 조이스틱 X',\n                monitor_joystick_right_y             : '오른쪽 조이스틱 Y',\n                monitor_joystick_right_direction     : '오른쪽 조이스틱 방향',\n                monitor_joystick_right_event         : '오른쪽 조이스틱 이벤트',\n                monitor_button_button                : '버튼',\n                monitor_button_event                 : '버튼 이벤트',\n                monitor_entryhw_countTransferReserved: '전송 예정 데이터',\n\n                common_light_color_red                  : '빨강',\n                common_light_color_yellow               : '노랑',\n                common_light_color_green                : '초록',\n                common_light_color_cyan                 : '하늘색',\n                common_light_color_blue                 : '파랑',\n                common_light_color_magenta              : '자홍',\n                common_light_color_white                : '흰색',\n                common_light_color_black                : '검정',\n                common_light_color_cottoncandy          : '구름솜사탕',\n                common_light_color_emerald              : '에메랄드',\n                common_light_color_lavender             : '라벤더',\n                common_light_color_muscat               : '청포도',\n                common_light_color_strawberrymilk       : '딸기우유',\n                common_light_color_sunset               : '저녁노을',\n                common_light_mode_hold                  : '켜짐',\n                common_light_mode_flicker               : '깜빡임',\n                common_light_mode_flicker_double        : '2번 연속 깜빡임',\n                common_light_mode_dimming               : '천천히 깜빡임',\n                common_light_mode_sunrise               : '점점 밝아짐',\n                common_light_mode_sunset                : '점점 어두워짐',\n                common_light_mode_rainbow               : '무지개',\n                common_light_mode_rainbow2              : '무지개2',\n                common_light_brightness_all             : '전체',\n                common_light_brightness_b100            : '밝기 100%',\n                common_light_brightness_b25             : '밝기 25%',\n                common_light_brightness_b50             : '밝기 50%',\n                common_light_brightness_b75             : '밝기 75%',\n                common_light_brightness_off             : '끄기',\n                common_light_brightness_on              : '켜기',\n                common_left                             : '왼쪽',\n                common_right                            : '오른쪽',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                controller_button                       : '버튼',\n                controller_button_event                 : '버튼 이벤트',\n                controller_button_front_left            : '전면 왼쪽 버튼',\n                controller_button_front_right           : '전면 오른쪽 버튼',\n                controller_button_top_left              : '상단 왼쪽 버튼',\n                controller_button_top_right             : '상단 오른쪽 버튼',\n                controller_button_center_up             : '중앙 위 버튼',\n                controller_button_center_left           : '중앙 왼쪽 버튼',\n                controller_button_center                : '중앙 버튼(전원)',\n                controller_button_center_right          : '중앙 오른쪽 버튼',\n                controller_button_center_down           : '중앙 아래쪽 버튼',\n                controller_button_bottom_left           : '하단 왼쪽 버튼',\n                controller_button_bottom_right          : '하단 오른쪽 버튼',\n                controller_buzzer                       : '버저',\n                controller_buzzer_a                     : '라',\n                controller_buzzer_as                    : '라#',\n                controller_buzzer_b                     : '시',\n                controller_buzzer_c                     : '도',\n                controller_buzzer_cs                    : '도#',\n                controller_buzzer_d                     : '레',\n                controller_buzzer_ds                    : '레#',\n                controller_buzzer_e                     : '미',\n                controller_buzzer_f                     : '파',\n                controller_buzzer_fs                    : '파#',\n                controller_buzzer_g                     : '솔',\n                controller_buzzer_gs                    : '솔#',\n                controller_buzzer_mute                  : '쉼',\n                controller_joystick_direction_left_up   : '왼쪽 위',\n                controller_joystick_direction_up        : '위',\n                controller_joystick_direction_right_up  : '오른쪽 위',\n                controller_joystick_direction_left      : '왼쪽',\n                controller_joystick_direction_center    : '중앙',\n                controller_joystick_direction_right     : '오른쪽',\n                controller_joystick_direction_left_down : '왼쪽 아래',\n                controller_joystick_direction_down      : '아래',\n                controller_joystick_direction_right_down: '오른쪽 아래',\n                controller_joystick_left_direction      : '왼쪽 조이스틱 방향',\n                controller_joystick_left_event          : '왼쪽 조이스틱 이벤트',\n                controller_joystick_left_x              : '왼쪽 조이스틱 가로축',\n                controller_joystick_left_y              : '왼쪽 조이스틱 세로축',\n                controller_joystick_right_direction     : '오른쪽 조이스틱 방향',\n                controller_joystick_right_event         : '오른쪽 조이스틱 이벤트',\n                controller_joystick_right_x             : '오른쪽 조이스틱 가로축',\n                controller_joystick_right_y             : '오른쪽 조이스틱 세로축',\n                entryhw_count_transfer_reserved         : '전송 예약된 데이터 수',\n            },\n\n            template: {\n                byrobot_controller_3_4_controller_buzzer_hz                : '%1 Hz 소리를 연주 %2',\n                byrobot_controller_3_4_controller_buzzer_hz_delay          : '%1 Hz 소리를 %2 초 연주 %3',\n                byrobot_controller_3_4_controller_buzzer_hz_reserve        : '%1 Hz 소리를 %2 초 예약 %3',\n                byrobot_controller_3_4_controller_buzzer_off               : '버저 끄기 %1',\n                byrobot_controller_3_4_controller_buzzer_scale             : '%1 옥타브 %2 을(를) 연주 %3',\n                byrobot_controller_3_4_controller_buzzer_scale_delay       : '%1 옥타브 %2 을(를) %3 초 연주 %4',\n                byrobot_controller_3_4_controller_buzzer_scale_reserve     : '%1 옥타브 %2 을(를) %3 초 예약 %4',\n                byrobot_controller_3_4_controller_if_button_press          : '조종기 %1을 눌렀을 때',\n                byrobot_controller_3_4_controller_if_joystick_direction    : '조종기 %1 조이스틱을 %2(으)로 움직였을 때',\n                byrobot_controller_3_4_controller_light_color_preset       : '조종기 LED %1 %2 %3',\n                byrobot_controller_3_4_controller_light_manual_single_input: '조종기 LED %1 밝기 %2 %3',\n                byrobot_controller_3_4_controller_light_manual_single_off  : '조종기 LED 끄기 %1',\n                byrobot_controller_3_4_controller_value_button             : '%1',\n                byrobot_controller_3_4_controller_value_joystick           : '%1',\n                byrobot_controller_3_4_controller_vibrator_delay           : '진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4',\n                byrobot_controller_3_4_controller_vibrator_off             : '진동 끄기 %1',\n                byrobot_controller_3_4_controller_vibrator_on_delay        : '진동 %1 초 켜기 %2',\n                byrobot_controller_3_4_controller_vibrator_on_reserve      : '진동 %1 초 예약 %2',\n                byrobot_controller_3_4_controller_vibrator_reserve         : '진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4',\n            },\n\n            Helper: {\n                byrobot_controller_3_4_controller_buzzer_hz                : \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                byrobot_controller_3_4_controller_buzzer_hz_delay          : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                byrobot_controller_3_4_controller_buzzer_hz_reserve        : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                byrobot_controller_3_4_controller_buzzer_off               : \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                byrobot_controller_3_4_controller_buzzer_scale             : \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                byrobot_controller_3_4_controller_buzzer_scale_delay       : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                byrobot_controller_3_4_controller_buzzer_scale_reserve     : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                byrobot_controller_3_4_controller_if_button_press          : \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                byrobot_controller_3_4_controller_if_joystick_direction    : \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                byrobot_controller_3_4_controller_light_color_preset       : \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_controller_3_4_controller_light_manual_single_input: \"<br>조종기 LED를 조작하는데 사용합니다.<br>LED를 선택하는데는 10진수(0 ~ 255) 또는 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_controller_3_4_controller_light_manual_single_off  : \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                byrobot_controller_3_4_controller_value_button             : \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                byrobot_controller_3_4_controller_value_joystick           : \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                byrobot_controller_3_4_controller_vibrator_delay           : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                byrobot_controller_3_4_controller_vibrator_off             : \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                byrobot_controller_3_4_controller_vibrator_on_delay        : \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                byrobot_controller_3_4_controller_vibrator_on_reserve      : \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                byrobot_controller_3_4_controller_vibrator_reserve         : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n            },\n        },\n\n        en: {\n            Blocks: {\n                // 정보창\n                monitor_joystick_left_x              : 'Left Joystick X',\n                monitor_joystick_left_y              : 'Left Joystick Y',\n                monitor_joystick_left_direction      : 'Left Joystick Direction',\n                monitor_joystick_left_event          : 'Left Joystick Event',\n                monitor_joystick_right_x             : 'Right Joystick X',\n                monitor_joystick_right_y             : 'Right Joystick Y',\n                monitor_joystick_right_direction     : 'Right Joystick Direction',\n                monitor_joystick_right_event         : 'Right Joystick Event',\n                monitor_button_button                : 'Button',\n                monitor_button_event                 : 'Button Event',\n                monitor_entryhw_countTransferReserved: 'Transfer Buffer',\n\n                // 일반 블럭\n                common_light_color_cottoncandy          : 'cotton candy',\n                common_light_color_emerald              : 'emerald',\n                common_light_color_lavender             : 'lavender',\n                common_light_color_muscat               : 'muscat',\n                common_light_color_strawberrymilk       : 'strawberry milk',\n                common_light_color_sunset               : 'sunset',\n                common_light_mode_hold                  : 'hold',\n                common_light_mode_dimming               : 'dimming',\n                common_light_mode_flicker               : 'flicker',\n                common_light_mode_flicker_double        : 'flicker double',\n                common_light_brightness_all             : 'all',\n                common_light_brightness_b100            : 'brightness 100%',\n                common_light_brightness_b25             : 'brightness 25%',\n                common_light_brightness_b50             : 'brightness 50%',\n                common_light_brightness_b75             : 'brightness 75%',\n                common_light_color_blue                 : 'blue',\n                common_light_color_cyan                 : 'cyan',\n                common_light_color_green                : 'green',\n                common_light_color_magenta              : 'magenta',\n                common_light_brightness_off             : 'off',\n                common_light_brightness_on              : 'on',\n                common_light_color_red                  : 'red',\n                common_light_color_white                : 'white',\n                common_light_color_yellow               : 'yellow',\n                common_left                             : 'left',\n                common_right                            : 'right',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                controller_button                       : 'button',\n                controller_button_event                 : 'button event',\n                controller_button_front_left            : 'Front left button',\n                controller_button_front_right           : 'Front right button',\n                controller_button_top_left              : 'Top left button',\n                controller_button_top_right             : 'Top right button',\n                controller_button_center_up             : 'Trim up button',\n                controller_button_center_left           : 'Trim left button',\n                controller_button_center                : 'Center button(Power)',\n                controller_button_center_right          : 'Trim right button',\n                controller_button_center_down           : 'Trim down button',\n                controller_button_bottom_left           : 'Bottom left button',\n                controller_button_bottom_right          : 'Bottom right button',\n                controller_buzzer                       : 'buzzer',\n                controller_buzzer_a                     : 'A',\n                controller_buzzer_as                    : 'A#',\n                controller_buzzer_b                     : 'B',\n                controller_buzzer_c                     : 'C',\n                controller_buzzer_cs                    : 'C#',\n                controller_buzzer_d                     : 'D',\n                controller_buzzer_ds                    : 'D#',\n                controller_buzzer_e                     : 'E',\n                controller_buzzer_f                     : 'F',\n                controller_buzzer_fs                    : 'F#',\n                controller_buzzer_g                     : 'G',\n                controller_buzzer_gs                    : 'G#',\n                controller_buzzer_mute                  : 'mute',\n                controller_joystick_direction_left_up   : 'Left top',\n                controller_joystick_direction_up        : 'Top',\n                controller_joystick_direction_right_up  : 'Right top',\n                controller_joystick_direction_left      : 'Left',\n                controller_joystick_direction_center    : 'Center',\n                controller_joystick_direction_right     : 'Right',\n                controller_joystick_direction_left_down : 'Left Bottom',\n                controller_joystick_direction_down      : 'Bottom',\n                controller_joystick_direction_right_down: 'Right Bottom',\n                controller_joystick_left_direction      : 'left joystick direction',\n                controller_joystick_left_event          : 'left joystick event',\n                controller_joystick_left_x              : 'left joystick X',\n                controller_joystick_left_y              : 'left joystick Y',\n                controller_joystick_right_direction     : 'right joystick direction',\n                controller_joystick_right_event         : 'right joystick event',\n                controller_joystick_right_x             : 'right joystick X',\n                controller_joystick_right_y             : 'right joystick Y',\n                entryhw_count_transfer_reserved         : 'Reserved data for transfer',\n            },\n\n            template: {\n                byrobot_controller_3_4_controller_buzzer_hz                : 'play Buzzer %1 Hz sound %2',\n                byrobot_controller_3_4_controller_buzzer_hz_delay          : 'play Buzzer %1 Hz sound for %2 second %3',\n                byrobot_controller_3_4_controller_buzzer_hz_reserve        : 'reserve to play Buzzer %1 Hz for %2 second %3',\n                byrobot_controller_3_4_controller_buzzer_off               : 'turn off the buzzer %1',\n                byrobot_controller_3_4_controller_buzzer_scale             : 'play %1 octave %2 %3',\n                byrobot_controller_3_4_controller_buzzer_scale_delay       : 'play %1 octave %2 for %3 second %4',\n                byrobot_controller_3_4_controller_buzzer_scale_reserve     : 'reserve to play %1 octave %2 for %3 second %4',\n                byrobot_controller_3_4_controller_if_button_press          : 'when press %1',\n                byrobot_controller_3_4_controller_if_joystick_direction    : 'when %1 stick move to %2',\n                byrobot_controller_3_4_controller_light_color_preset       : 'Controller LED %1 %2 %3',\n                byrobot_controller_3_4_controller_light_manual_single_input: 'Controller LED %1 Lightness %2 %3',\n                byrobot_controller_3_4_controller_light_manual_single_off  : 'Controller LED Off %1',\n                byrobot_controller_3_4_controller_value_button             : '%1',\n                byrobot_controller_3_4_controller_value_joystick           : '%1',\n                byrobot_controller_3_4_controller_vibrator_off             : 'Vibrator Off %1',\n                byrobot_controller_3_4_controller_vibrator_delay           : 'Vibrator %1 sec On, %2 sec Off for %3 sec run %4',\n                byrobot_controller_3_4_controller_vibrator_on_delay        : 'Vibrator %1 sec on %2',\n                byrobot_controller_3_4_controller_vibrator_on_reserve      : 'Vibrator %1 sec reserve %2',\n                byrobot_controller_3_4_controller_vibrator_reserve         : 'Vibrator %1 sec On, %2 sec Off for %3 sec reserve %4',\n            },\n\n            Helper: {\n                byrobot_controller_3_4_controller_buzzer_hz                : '',\n                byrobot_controller_3_4_controller_buzzer_hz_delay          : '',\n                byrobot_controller_3_4_controller_buzzer_hz_reserve        : '',\n                byrobot_controller_3_4_controller_buzzer_off               : '',\n                byrobot_controller_3_4_controller_buzzer_scale             : '',\n                byrobot_controller_3_4_controller_buzzer_scale_delay       : '',\n                byrobot_controller_3_4_controller_buzzer_scale_reserve     : '',\n                byrobot_controller_3_4_controller_if_button_press          : '',\n                byrobot_controller_3_4_controller_if_joystick_direction    : '',\n                byrobot_controller_3_4_controller_light_color_input        : '',\n                byrobot_controller_3_4_controller_light_color_preset       : '',\n                byrobot_controller_3_4_controller_light_manual_single_input: '',\n                byrobot_controller_3_4_controller_light_manual_single_off  : '',\n                byrobot_controller_3_4_controller_value_button             : '',\n                byrobot_controller_3_4_controller_value_joystick           : '',\n                byrobot_controller_3_4_controller_vibrator_delay           : '',\n                byrobot_controller_3_4_controller_vibrator_off             : '',\n                byrobot_controller_3_4_controller_vibrator_on_delay        : '',\n                byrobot_controller_3_4_controller_vibrator_on_reserve      : '',\n                byrobot_controller_3_4_controller_vibrator_reserve         : '',\n            },\n        },\n    };\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.byrobot_controller_3_4.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/byrobot_controller_3_4.png\",   // 배경 이미지\n        width  : 256,                               // 이미지의 폭\n        height : 256,                               // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            joystick_left_x              : { name: Lang.Blocks.monitor_joystick_left_x,                type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_y              : { name: Lang.Blocks.monitor_joystick_left_y,                type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_direction      : { name: Lang.Blocks.monitor_joystick_left_direction,        type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_event          : { name: Lang.Blocks.monitor_joystick_left_event,            type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_x             : { name: Lang.Blocks.monitor_joystick_right_x,               type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_y             : { name: Lang.Blocks.monitor_joystick_right_y,               type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_direction     : { name: Lang.Blocks.monitor_joystick_right_direction,       type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_event         : { name: Lang.Blocks.monitor_joystick_right_event,           type: 'input', pos: { x: 0, y: 0 } },\n            button_button                : { name: Lang.Blocks.monitor_button_button,                  type: 'input', pos: { x: 0, y: 0 } },\n            button_event                 : { name: Lang.Blocks.monitor_button_event,                   type: 'input', pos: { x: 0, y: 0 } },\n            entryhw_countTransferReserved: { name: Lang.Blocks.monitor_entryhw_countTransferReserved,  type: 'output', pos: { x: 0, y: 0 } },\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both',   // 표시 모드\n    };\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 블록명(다른 장치의 블록 이름과 달라야 함)\n ***************************************************************************************/\nEntry.byrobot_controller_3_4.blockMenuBlocks = [\n    'byrobot_controller_3_4_controller_value_button',\n    'byrobot_controller_3_4_controller_value_joystick',\n    'byrobot_controller_3_4_controller_if_button_press',\n    'byrobot_controller_3_4_controller_if_joystick_direction',\n    'byrobot_controller_3_4_controller_light_manual_single_off',\n    'byrobot_controller_3_4_controller_light_manual_single_input',\n    'byrobot_controller_3_4_controller_light_color_preset',\n    'byrobot_controller_3_4_controller_buzzer_off',\n    'byrobot_controller_3_4_controller_buzzer_scale',\n    'byrobot_controller_3_4_controller_buzzer_scale_delay',\n    'byrobot_controller_3_4_controller_buzzer_scale_reserve',\n    'byrobot_controller_3_4_controller_buzzer_hz',\n    'byrobot_controller_3_4_controller_buzzer_hz_delay',\n    'byrobot_controller_3_4_controller_buzzer_hz_reserve',\n    'byrobot_controller_3_4_controller_vibrator_off',\n    'byrobot_controller_3_4_controller_vibrator_on_delay',\n    'byrobot_controller_3_4_controller_vibrator_on_reserve',\n    'byrobot_controller_3_4_controller_vibrator_delay',\n    'byrobot_controller_3_4_controller_vibrator_reserve',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 정의\n ***************************************************************************************/\nEntry.byrobot_controller_3_4.getBlocks = function()\n{\n    return {\n        byrobot_controller_3_4_controller_value_button: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button,         'button_button'],\n                        [Lang.Blocks.controller_button_event,   'button_event'],\n                    ],\n                    value     : 'button_button',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_controller_3_4_controller_value_button',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                    // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_controller_3_4_controller_value_joystick: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_left_x,            'joystick_left_x'],\n                        [Lang.Blocks.controller_joystick_left_y,            'joystick_left_y'],\n                        [Lang.Blocks.controller_joystick_left_direction,    'joystick_left_direction'],\n                        [Lang.Blocks.controller_joystick_left_event,        'joystick_left_event'],\n                        [Lang.Blocks.controller_joystick_right_x,           'joystick_right_x'],\n                        [Lang.Blocks.controller_joystick_right_y,           'joystick_right_y'],\n                        [Lang.Blocks.controller_joystick_right_direction,   'joystick_right_direction'],\n                        [Lang.Blocks.controller_joystick_right_event,       'joystick_right_event'],\n                    ],\n                    value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_controller_3_4_controller_value_joystick',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                    // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_controller_3_4_controller_if_button_press: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button_front_left,   '1'],\n                        [Lang.Blocks.controller_button_front_right,  '2'],\n                        [Lang.Blocks.controller_button_top_left,     '4'],\n                        [Lang.Blocks.controller_button_top_right,    '8'],\n                        [Lang.Blocks.controller_button_center_up,    '16'],\n                        [Lang.Blocks.controller_button_center_left,  '32'],\n                        [Lang.Blocks.controller_button_center_right, '128'],\n                        [Lang.Blocks.controller_button_center_down,  '256'],\n                        [Lang.Blocks.controller_button_bottom_left,  '512'],\n                        [Lang.Blocks.controller_button_bottom_right, '1024'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_controller_3_4_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const read        = Entry.hw.portData;\n                const button      = 'button_button';    // paramsKeyMap에 정의된 이름 사용\n                const buttonevent = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        byrobot_controller_3_4_controller_if_joystick_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.common_right, 'joystick_right_direction'],\n                    ],\n                    value     : 'joystick_left_direction',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_direction_left_up,     '17'],\n                        [Lang.Blocks.controller_joystick_direction_up,          '18'],\n                        [Lang.Blocks.controller_joystick_direction_right_up,    '20'],\n                        [Lang.Blocks.controller_joystick_direction_left,        '33'],\n                        [Lang.Blocks.controller_joystick_direction_center,      '34'],\n                        [Lang.Blocks.controller_joystick_direction_right,       '36'],\n                        [Lang.Blocks.controller_joystick_direction_left_down,   '65'],\n                        [Lang.Blocks.controller_joystick_direction_down,        '66'],\n                        [Lang.Blocks.controller_joystick_direction_right_down,  '68'],\n                    ],\n                    value     : '34',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_controller_3_4_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE   : 0,\n                DIRECTION: 1,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const read   = Entry.hw.portData;\n                const device = script.getField('DEVICE');  // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION'))\n                {\n                    return true;\n                }\n                else\n                {\n                    return false;\n                }\n            },\n        },\n\n        byrobot_controller_3_4_controller_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_controller_3_4_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'controller_light',\n            isNotFor    : ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setLightManual(script, 0x20, 0xffff, 0);\n            },\n        },\n\n        byrobot_controller_3_4_controller_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_controller_3_4_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const mode        = 0x12;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n        },\n\n        byrobot_controller_3_4_controller_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0xFC'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'byrobot_controller_3_4_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x20, flags, brightness);\n            },\n        },\n\n\n        byrobot_controller_3_4_controller_buzzer_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_controller_3_4_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class       : 'buzzer',\n            isNotFor    : ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setBuzzerStop(script, 0x20);\n            },\n        },\n\n        byrobot_controller_3_4_controller_buzzer_scale: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_controller_3_4_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, 60000, false, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, 60000, false, true);\n                }\n            },\n        },\n\n        byrobot_controller_3_4_controller_buzzer_scale_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_3_4_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, true, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, true, true);\n                }\n            },\n        },\n\n        byrobot_controller_3_4_controller_buzzer_scale_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_3_4_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, false, false);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, false, false);\n                }\n            },\n        },\n\n        byrobot_controller_3_4_controller_buzzer_hz: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1000'] }, null],\n                type  : 'byrobot_controller_3_4_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const hz = script.getNumberValue('HZ');\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, 60000, false, true);\n            },\n        },\n\n        byrobot_controller_3_4_controller_buzzer_hz_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1000'] }, { type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_controller_3_4_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ  : 0,\n                TIME: 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, true, true);\n            },\n        },\n\n        byrobot_controller_3_4_controller_buzzer_hz_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['1000'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_3_4_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ  : 0,\n                TIME: 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, false, false);\n            },\n        },\n\n        byrobot_controller_3_4_controller_vibrator_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_controller_3_4_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class       : 'vibrator',\n            isNotFor    : ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setVibratorStop(script, 0x20);\n            },\n        },\n\n        byrobot_controller_3_4_controller_vibrator_on_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_controller_3_4_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, true, true);\n            },\n        },\n\n        byrobot_controller_3_4_controller_vibrator_on_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_controller_3_4_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, false, false);\n            },\n        },\n\n        byrobot_controller_3_4_controller_vibrator_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_3_4_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, true, true);\n            },\n        },\n\n        byrobot_controller_3_4_controller_vibrator_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_3_4_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_controller_3_4'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, false, false);\n            },\n        },\n\n    };\n};\n\n\nmodule.exports = Entry.byrobot_controller_3_4;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_controller_4.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_controller_4 = \n{\n    id       : 'F.9',\n    name     : 'byrobot_controller_4',\n    url      : 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_controller_4.png',\n    title    : {\n        en: 'BYROBOT E-DRONE Controller',\n        ko: '바이로봇 E-DRONE 조종기',\n    },\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero()\n    {\n        // 초기화\n        Entry.byrobot_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            Entry.byrobot_base.transferVibrator(0x20, 0, 0, 0, 0);\n            Entry.byrobot_base.transferBuzzer(0x20, 0, 0, 0);\n            Entry.byrobot_base.transferLightManual(0x20, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightModeColor(0x20, 0x22, 200, 255, 0, 0); // LED 초기화(조종기)\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.byrobot_controller_4.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                // 정보창\n                monitor_joystick_left_x              : '왼쪽 조이스틱 X',\n                monitor_joystick_left_y              : '왼쪽 조이스틱 Y',\n                monitor_joystick_left_direction      : '왼쪽 조이스틱 방향',\n                monitor_joystick_left_event          : '왼쪽 조이스틱 이벤트',\n                monitor_joystick_right_x             : '오른쪽 조이스틱 X',\n                monitor_joystick_right_y             : '오른쪽 조이스틱 Y',\n                monitor_joystick_right_direction     : '오른쪽 조이스틱 방향',\n                monitor_joystick_right_event         : '오른쪽 조이스틱 이벤트',\n                monitor_button_button                : '버튼',\n                monitor_button_event                 : '버튼 이벤트',\n                monitor_entryhw_countTransferReserved: '전송 예정 데이터',\n\n                // 일반 블럭\n                common_light_color_red                  : '빨강',\n                common_light_color_yellow               : '노랑',\n                common_light_color_green                : '초록',\n                common_light_color_cyan                 : '하늘색',\n                common_light_color_blue                 : '파랑',\n                common_light_color_magenta              : '자홍',\n                common_light_color_white                : '흰색',\n                common_light_color_black                : '검정',\n                common_light_color_cottoncandy          : '구름솜사탕',\n                common_light_color_emerald              : '에메랄드',\n                common_light_color_lavender             : '라벤더',\n                common_light_color_muscat               : '청포도',\n                common_light_color_strawberrymilk       : '딸기우유',\n                common_light_color_sunset               : '저녁노을',\n                common_light_mode_hold                  : '켜짐',\n                common_light_mode_flicker               : '깜빡임',\n                common_light_mode_flicker_double        : '2번 연속 깜빡임',\n                common_light_mode_dimming               : '천천히 깜빡임',\n                common_light_mode_sunrise               : '점점 밝아짐',\n                common_light_mode_sunset                : '점점 어두워짐',\n                common_light_mode_rainbow               : '무지개',\n                common_light_mode_rainbow2              : '무지개2',\n                common_light_brightness_all             : '전체',\n                common_light_brightness_b100            : '밝기 100%',\n                common_light_brightness_b25             : '밝기 25%',\n                common_light_brightness_b50             : '밝기 50%',\n                common_light_brightness_b75             : '밝기 75%',\n                common_light_brightness_off             : '끄기',\n                common_light_brightness_on              : '켜기',\n                common_left                             : '왼쪽',\n                common_right                            : '오른쪽',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                common_drone                            : '드론',\n                common_controller                       : '조종기',\n                controller_button                       : '버튼',\n                controller_button_event                 : '버튼 이벤트',\n                controller_button_front_left_top        : '전면 왼쪽 상단 버튼',\n                controller_button_front_left_bottom     : '전면 왼쪽 하단 버튼',\n                controller_button_front_right_top       : '전면 오른쪽 상단 버튼',\n                controller_button_front_right_bottom    : '전면 오른쪽 하단 버튼',\n                controller_button_top_left              : '상단 왼쪽 버튼',\n                controller_button_top_right             : '상단 오른쪽 버튼',\n                controller_button_center_up             : '중앙 위 버튼',\n                controller_button_center_left           : '중앙 왼쪽 버튼',\n                controller_button_center_right          : '중앙 오른쪽 버튼',\n                controller_button_center_down           : '중앙 아래쪽 버튼',\n                controller_button_bottom_left           : '하단 왼쪽 버튼',\n                controller_button_bottom_right          : '하단 오른쪽 버튼',\n                controller_buzzer                       : '버저',\n                controller_buzzer_a                     : '라',\n                controller_buzzer_as                    : '라#',\n                controller_buzzer_b                     : '시',\n                controller_buzzer_c                     : '도',\n                controller_buzzer_cs                    : '도#',\n                controller_buzzer_d                     : '레',\n                controller_buzzer_ds                    : '레#',\n                controller_buzzer_e                     : '미',\n                controller_buzzer_f                     : '파',\n                controller_buzzer_fs                    : '파#',\n                controller_buzzer_g                     : '솔',\n                controller_buzzer_gs                    : '솔#',\n                controller_buzzer_mute                  : '쉼',\n                controller_display_align_center         : '가운데',\n                controller_display_align_left           : '왼쪽',\n                controller_display_align_right          : '오른쪽',\n                controller_display_flagfill_off         : '채우지 않음',\n                controller_display_flagfill_on          : '채움',\n                controller_display_font_10x16           : '큼',\n                controller_display_font_5x8             : '작음',\n                controller_display_line_dashed          : '파선',\n                controller_display_line_dotted          : '점선',\n                controller_display_line_solid           : '실선',\n                controller_display_pixel_black          : '검은색',\n                controller_display_pixel_white          : '흰색',\n                controller_display_pixel_inverse        : '반전',\n                controller_joystick_direction_left_up   : '왼쪽 위',\n                controller_joystick_direction_up        : '위',\n                controller_joystick_direction_right_up  : '오른쪽 위',\n                controller_joystick_direction_left      : '왼쪽',\n                controller_joystick_direction_center    : '중앙',\n                controller_joystick_direction_right     : '오른쪽',\n                controller_joystick_direction_left_down : '왼쪽 아래',\n                controller_joystick_direction_down      : '아래',\n                controller_joystick_direction_right_down: '오른쪽 아래',\n                controller_joystick_left_direction      : '왼쪽 조이스틱 방향',\n                controller_joystick_left_event          : '왼쪽 조이스틱 이벤트',\n                controller_joystick_left_x              : '왼쪽 조이스틱 가로축',\n                controller_joystick_left_y              : '왼쪽 조이스틱 세로축',\n                controller_joystick_right_direction     : '오른쪽 조이스틱 방향',\n                controller_joystick_right_event         : '오른쪽 조이스틱 이벤트',\n                controller_joystick_right_x             : '오른쪽 조이스틱 가로축',\n                controller_joystick_right_y             : '오른쪽 조이스틱 세로축',\n                entryhw_count_transfer_reserved         : '전송 예약된 데이터 수',\n            },\n\n            template: {\n                \"byrobot_controller_4_buzzer_hz\"                           : \"%1 Hz 소리를 연주 %2\",\n                \"byrobot_controller_4_buzzer_hz_delay\"                     : \"%1 Hz 소리를 %2 초 연주 %3\",\n                \"byrobot_controller_4_buzzer_hz_reserve\"                   : \"%1 Hz 소리를 %2 초 예약 %3\",\n                \"byrobot_controller_4_buzzer_off\"                          : \"버저 끄기 %1\",\n                \"byrobot_controller_4_buzzer_scale\"                        : \"%1 옥타브 %2 을(를) 연주 %3\",\n                \"byrobot_controller_4_buzzer_scale_delay\"                  : \"%1 옥타브 %2 을(를) %3 초 연주 %4\",\n                \"byrobot_controller_4_buzzer_scale_reserve\"                : \"%1 옥타브 %2 을(를) %3 초 예약 %4\",\n                \"byrobot_controller_4_display_clear\"                       : \"지우기 x %1, y %2, 너비 %3, 높이 %4 %5 %6\",\n                \"byrobot_controller_4_display_clear_all\"                   : \"조종기 화면 전체 지우기%1 %2\",\n                \"byrobot_controller_4_display_draw_circle\"                 : \"원 x %1, y %2, 반지름 %3 %4 %5 %6\",\n                \"byrobot_controller_4_display_draw_line\"                   : \"선 x1 %1, y1 %2, x2 %3, y2 %4 %5 %6 %7\",\n                \"byrobot_controller_4_display_draw_point\"                  : \"점 그리기 x %1, y %2 %3 %4\",\n                \"byrobot_controller_4_display_draw_rect\"                   : \"사각형 x %1, y %2, 너비 %3, 높이 %4 %5 %6 %7 %8\",\n                \"byrobot_controller_4_display_draw_string\"                 : \"문자열 x %1, y %2 %3 %4 입력 %5 %6\",\n                \"byrobot_controller_4_display_draw_string_align\"           : \"문자열 정렬 x1 %1, x2 %2, y %3 %4 %5 %6 입력 %7 %8\",\n                \"byrobot_controller_4_if_button_press\"                     : \"조종기 %1 눌렀을 때\",\n                \"byrobot_controller_4_if_joystick_direction\"               : \"조종기 %1 조이스틱 %2 움직였을 때\",\n                \"byrobot_controller_4_controller_light_color_input\"        : \"조종기 LED R %1, G %2, B %3 %4 %5 %6\",\n                \"byrobot_controller_4_controller_light_color_select\"       : \"조종기 LED %1 %2 %3 %4\",\n                \"byrobot_controller_4_controller_light_color_preset\"       : \"조종기 LED %1 %2 %3\",\n                \"byrobot_controller_4_controller_light_manual_single_input\": \"조종기 LED %1 밝기 %2 %3\",\n                \"byrobot_controller_4_controller_light_manual_single_off\"  : \"조종기 LED 끄기 %1\",\n                \"byrobot_controller_4_value_button\"                        : \"%1\",\n                \"byrobot_controller_4_value_joystick\"                      : \"%1\",\n                \"byrobot_controller_4_vibrator_delay\"                      : \"진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4\",\n                \"byrobot_controller_4_vibrator_off\"                        : \"진동 끄기 %1\",\n                \"byrobot_controller_4_vibrator_on_delay\"                   : \"진동 %1 초 켜기 %2\",\n                \"byrobot_controller_4_vibrator_on_reserve\"                 : \"진동 %1 초 예약 %2\",\n                \"byrobot_controller_4_vibrator_reserve\"                    : \"진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4\",\n            },\n\n            Helper: {\n                \"byrobot_controller_4_buzzer_hz\"                           : \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_controller_4_buzzer_hz_delay\"                     : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_controller_4_buzzer_hz_reserve\"                   : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                \"byrobot_controller_4_buzzer_off\"                          : \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                \"byrobot_controller_4_buzzer_scale\"                        : \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_controller_4_buzzer_scale_delay\"                  : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_controller_4_buzzer_scale_reserve\"                : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                \"byrobot_controller_4_display_clear\"                       : \"<br>조종기 OLED 화면의 선택한 영역을 지웁니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_controller_4_display_clear_all\"                   : \"<br>조종기 OLED 화면 전체를 지웁니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_controller_4_display_draw_circle\"                 : \"<br>조종기 OLED 화면에서 지정한 위치에 원을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 반지름을 지정합니다. 원의 중심 = (x, y),<br>반지름은 원의 크기를 결정합니다.<br><br>★☆사용 가능한 값의 범위는 x값은 (-50~178), y값은 (-50~114), 반지름은 (1~200)입니다.☆★<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_controller_4_display_draw_line\"                   : \"<br>조종기 OLED 화면에서 지정한 위치에 선을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>시작점 = (x1, y1), 끝나는점 = (x2, y2)<br>선 그리기는 시작점과 끝나는점을 이어주는 기능입니다.<br>사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_controller_4_display_draw_point\"                  : \"<br>조종기 OLED 화면에서 지정한 위치에 점을 찍습니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다. x, y 좌표값으로 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_controller_4_display_draw_rect\"                   : \"<br>조종기 OLED 화면에서 지정한 위치에 사각형을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 너비, 높이를 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_controller_4_display_draw_string\"                 : \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 씁니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 글자 크기, 색을 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값은 (0~120), y값과 높이는 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_controller_4_display_draw_string_align\"           : \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 정렬하여 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 정렬 방향, 글자 크기, 색을 지정합니다. 시작점 = (x1, y), 끝나는점 = (x2, y), 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_controller_4_if_button_press\"                     : \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_controller_4_if_joystick_direction\"               : \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_controller_4_controller_light_color_input\"        : \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 조종기 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_controller_4_controller_light_color_select\"       : \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 조종기 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_controller_4_controller_light_color_preset\"       : \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_controller_4_controller_light_manual_single_input\": \"<br>조종기 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다. 각각의 비트는 LED를 선택하는 스위치 역할을 합니다.  밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다. 값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_controller_4_controller_light_manual_single_off\"  : \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_controller_4_value_button\"                        : \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_controller_4_value_joystick\"                      : \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_controller_4_vibrator_delay\"                      : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_controller_4_vibrator_off\"                        : \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                \"byrobot_controller_4_vibrator_on_delay\"                   : \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_controller_4_vibrator_on_reserve\"                 : \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_controller_4_vibrator_reserve\"                    : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n            }\n        },\n\n        en: {\n            Blocks: {\n                // 정보창\n                monitor_joystick_left_x              : 'Left Joystick X',\n                monitor_joystick_left_y              : 'Left Joystick Y',\n                monitor_joystick_left_direction      : 'Left Joystick Direction',\n                monitor_joystick_left_event          : 'Left Joystick Event',\n                monitor_joystick_right_x             : 'Right Joystick X',\n                monitor_joystick_right_y             : 'Right Joystick Y',\n                monitor_joystick_right_direction     : 'Right Joystick Direction',\n                monitor_joystick_right_event         : 'Right Joystick Event',\n                monitor_button_button                : 'Button',\n                monitor_button_event                 : 'Button Event',\n                monitor_entryhw_countTransferReserved: 'Transfer Buffer',\n\n                // 일반 블럭\n                common_light_color_cottoncandy          : 'cotton candy',\n                common_light_color_emerald              : 'emerald',\n                common_light_color_lavender             : 'lavender',\n                common_light_color_muscat               : 'muscat',\n                common_light_color_strawberrymilk       : 'strawberry milk',\n                common_light_color_sunset               : 'sunset',\n                common_light_mode_hold                  : 'hold',\n                common_light_mode_dimming               : 'dimming',\n                common_light_mode_flicker               : 'flicker',\n                common_light_mode_flicker_double        : 'flicker double',\n                common_light_brightness_all             : 'all',\n                common_light_brightness_b100            : 'brightness 100%',\n                common_light_brightness_b25             : 'brightness 25%',\n                common_light_brightness_b50             : 'brightness 50%',\n                common_light_brightness_b75             : 'brightness 75%',\n                common_light_color_blue                 : 'blue',\n                common_light_color_cyan                 : 'cyan',\n                common_light_color_green                : 'green',\n                common_light_color_magenta              : 'magenta',\n                common_light_brightness_off             : 'off',\n                common_light_brightness_on              : 'on',\n                common_light_color_red                  : 'red',\n                common_light_color_white                : 'white',\n                common_light_color_yellow               : 'yellow',\n                common_left                             : 'left',\n                common_right                            : 'right',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                controller_button                       : 'button',\n                controller_button_event                 : 'button event',\n                controller_button_front_left_up         : 'Fromt left top button',\n                controller_button_front_left_down       : 'Fromt left bottom button',\n                controller_button_front_right_up        : 'Fromt right top button',\n                controller_button_front_right_down      : 'Fromt right bottom button',\n                controller_button_top_left              : 'Top left button',\n                controller_button_top_right             : 'Top right button',\n                controller_button_center_up             : 'Trim up button',\n                controller_button_center_left           : 'Trim left button',\n                controller_button_center_right          : 'Trim right button',\n                controller_button_center_down           : 'Trim down button',\n                controller_button_bottom_left           : 'Bottom left button',\n                controller_button_bottom_right          : 'Bottom right button',\n                controller_buzzer                       : 'buzzer',\n                controller_buzzer_a                     : 'A',\n                controller_buzzer_as                    : 'A#',\n                controller_buzzer_b                     : 'B',\n                controller_buzzer_c                     : 'C',\n                controller_buzzer_cs                    : 'C#',\n                controller_buzzer_d                     : 'D',\n                controller_buzzer_ds                    : 'D#',\n                controller_buzzer_e                     : 'E',\n                controller_buzzer_f                     : 'F',\n                controller_buzzer_fs                    : 'F#',\n                controller_buzzer_g                     : 'G',\n                controller_buzzer_gs                    : 'G#',\n                controller_buzzer_mute                  : 'mute',\n                controller_display_align_center         : 'center',\n                controller_display_align_left           : 'left',\n                controller_display_align_right          : 'right',\n                controller_display_flagfill_off         : 'not fill',\n                controller_display_flagfill_on          : 'fill',\n                controller_display_font_10x16           : 'big',\n                controller_display_font_5x8             : 'small',\n                controller_display_line_dashed          : 'dashed',\n                controller_display_line_dotted          : 'dotted',\n                controller_display_line_solid           : 'solid',\n                controller_display_pixel_black          : 'black',\n                controller_display_pixel_white          : 'white',\n                controller_display_pixel_inverse        : 'inverse',\n                controller_joystick_direction_left_up   : 'Left top',\n                controller_joystick_direction_up        : 'Top',\n                controller_joystick_direction_right_up  : 'Right top',\n                controller_joystick_direction_left      : 'Left',\n                controller_joystick_direction_center    : 'Center',\n                controller_joystick_direction_right     : 'Right',\n                controller_joystick_direction_left_down : 'Left Bottom',\n                controller_joystick_direction_down      : 'Bottom',\n                controller_joystick_direction_right_down: 'Right Bottom',\n                controller_joystick_left_direction      : 'left joystick direction',\n                controller_joystick_left_event          : 'left joystick event',\n                controller_joystick_left_x              : 'left joystick X',\n                controller_joystick_left_y              : 'left joystick Y',\n                controller_joystick_right_direction     : 'right joystick direction',\n                controller_joystick_right_event         : 'right joystick event',\n                controller_joystick_right_x             : 'right joystick X',\n                controller_joystick_right_y             : 'right joystick Y',\n                entryhw_count_transfer_reserved         : 'Reserved data for transfer',\n            },\n\n            template: {\n                \"byrobot_controller_4_buzzer_hz\"                           : \"play %1 Hz sound %2\",\n                \"byrobot_controller_4_buzzer_hz_delay\"                     : \"play %1 Hz sound for %2 second %3\",\n                \"byrobot_controller_4_buzzer_hz_reserve\"                   : \"reserve to play %1 Hz sound for %2 second %3\",\n                \"byrobot_controller_4_buzzer_off\"                          : \"turn off the buzzer %1\",\n                \"byrobot_controller_4_buzzer_scale\"                        : \"play %1 octave %2 %3\",\n                \"byrobot_controller_4_buzzer_scale_delay\"                  : \"play %1 octave %2 for %3 second %4\",\n                \"byrobot_controller_4_buzzer_scale_reserve\"                : \"reserve to play %1 octave %2 for %3 second %4\",\n                \"byrobot_controller_4_display_clear\"                       : \"clear controller display x:%1, y:%2, width:%3, height:%4, color:%5 %6\",\n                \"byrobot_controller_4_display_clear_all\"                   : \"clear controller display with %1 color %2\",\n                \"byrobot_controller_4_display_draw_circle\"                 : \"draw a circle x:%1, y:%2, radius:%3, %4, %5, %6\",\n                \"byrobot_controller_4_display_draw_line\"                   : \"draw a line x1:%1, y1:%2, x2:%3, y2:%4, %5, %6 %7\",\n                \"byrobot_controller_4_display_draw_point\"                  : \"draw a point x:%1, y:%2, color:%3 %4\",\n                \"byrobot_controller_4_display_draw_rect\"                   : \"draw a rectangle x:%1, y:%2, width:%3, height:%4, %5, %6, %7 %8\",\n                \"byrobot_controller_4_display_draw_string\"                 : \"draw a string x:%1, y:%2, font size:%3, %4, input:%5, %6\",\n                \"byrobot_controller_4_display_draw_string_align\"           : \"draw aligned string x1:%1, x2:%2, y:%3, align:%4, font size:%5, %6, input:%7, %8\",\n                \"byrobot_controller_4_if_button_press\"                     : \"when press %1\",\n                \"byrobot_controller_4_if_joystick_direction\"               : \"when %1 stick move to %2\",\n                \"byrobot_controller_4_controller_light_color_input\"        : \"decide the color values of controller LED R %1, G %2, B %3 %4 %5\",\n                \"byrobot_controller_4_controller_light_color_select\"       : \"RGB combination examples of controller LED %1 %2 %3\",\n                \"byrobot_controller_4_controller_light_color_preset\"       : \"change the state of %1 controller LED to %2 %3\",\n                \"byrobot_controller_4_controller_light_manual_single_input\": \"change the brightness of %1 controller LED to %2 %3\",\n                \"byrobot_controller_4_controller_light_manual_single_off\"  : \"turn off all controller LEDs %1\",\n                \"byrobot_controller_4_value_button\"                        : \"%1\",\n                \"byrobot_controller_4_value_joystick\"                      : \"%1\",\n                \"byrobot_controller_4_vibrator_delay\"                      : \"vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_controller_4_vibrator_off\"                        : \"turn off the vibrator %1\",\n                \"byrobot_controller_4_vibrator_on_delay\"                   : \"turn on the vibrator for %1 second %2\",\n                \"byrobot_controller_4_vibrator_on_reserve\"                 : \"reserve turn on the vibrator for %1 second %2\",\n                \"byrobot_controller_4_vibrator_reserve\"                    : \"reserve vibration %1 second on, %2 second off for %3 seconds %4\",\n            },\n            \n            Helper: {\n\n            }\n        }\n    };\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.byrobot_controller_4.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/byrobot_controller_4.png\",   // 배경 이미지\n        width  : 256,                             // 이미지의 폭\n        height : 256,                             // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            joystick_left_x              : { name: Lang.Blocks.monitor_joystick_left_x,                type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_y              : { name: Lang.Blocks.monitor_joystick_left_y,                type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_direction      : { name: Lang.Blocks.monitor_joystick_left_direction,        type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_event          : { name: Lang.Blocks.monitor_joystick_left_event,            type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_x             : { name: Lang.Blocks.monitor_joystick_right_x,               type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_y             : { name: Lang.Blocks.monitor_joystick_right_y,               type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_direction     : { name: Lang.Blocks.monitor_joystick_right_direction,       type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_event         : { name: Lang.Blocks.monitor_joystick_right_event,           type: 'input', pos: { x: 0, y: 0 } },\n            button_button                : { name: Lang.Blocks.monitor_button_button,                  type: 'input', pos: { x: 0, y: 0 } },\n            button_event                 : { name: Lang.Blocks.monitor_button_event,                   type: 'input', pos: { x: 0, y: 0 } },\n            entryhw_countTransferReserved: { name: Lang.Blocks.monitor_entryhw_countTransferReserved,  type: 'output', pos: { x: 0, y: 0 } },\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both',   // 표시 모드\n    };\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 블록명(다른 장치의 블록 이름과 달라야 함)\n ***************************************************************************************/\nEntry.byrobot_controller_4.blockMenuBlocks = [\n    'byrobot_controller_4_value_button',\n    'byrobot_controller_4_value_joystick',\n    'byrobot_controller_4_if_button_press',\n    'byrobot_controller_4_if_joystick_direction',\n    'byrobot_controller_4_controller_light_manual_single_off',\n    'byrobot_controller_4_controller_light_manual_single_input',\n    'byrobot_controller_4_controller_light_color_preset',\n    'byrobot_controller_4_controller_light_color_input',\n    'byrobot_controller_4_controller_light_color_select',\n    'byrobot_controller_4_display_clear_all',\n    'byrobot_controller_4_display_clear',\n    'byrobot_controller_4_display_draw_point',\n    'byrobot_controller_4_display_draw_line',\n    'byrobot_controller_4_display_draw_rect',\n    'byrobot_controller_4_display_draw_circle',\n    'byrobot_controller_4_display_draw_string',\n    'byrobot_controller_4_display_draw_string_align',\n    'byrobot_controller_4_buzzer_off',\n    'byrobot_controller_4_buzzer_scale',\n    'byrobot_controller_4_buzzer_scale_delay',\n    'byrobot_controller_4_buzzer_scale_reserve',\n    'byrobot_controller_4_buzzer_hz',\n    'byrobot_controller_4_buzzer_hz_delay',\n    'byrobot_controller_4_buzzer_hz_reserve',\n    'byrobot_controller_4_vibrator_off',\n    'byrobot_controller_4_vibrator_on_delay',\n    'byrobot_controller_4_vibrator_on_reserve',\n    'byrobot_controller_4_vibrator_delay',\n    'byrobot_controller_4_vibrator_reserve',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 정의\n ***************************************************************************************/\nEntry.byrobot_controller_4.getBlocks = function()\n{\n    return {\n\n        byrobot_controller_4_value_button: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button,         'button_button'],\n                        [Lang.Blocks.controller_button_event,   'button_event'],\n                    ],\n                    value     : 'button_button',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_controller_4_value_button',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_controller_4_value_joystick: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_left_x,            'joystick_left_x'],\n                        [Lang.Blocks.controller_joystick_left_y,            'joystick_left_y'],\n                        [Lang.Blocks.controller_joystick_left_direction,    'joystick_left_direction'],\n                        [Lang.Blocks.controller_joystick_left_event,        'joystick_left_event'],\n                        [Lang.Blocks.controller_joystick_right_x,           'joystick_right_x'],\n                        [Lang.Blocks.controller_joystick_right_y,           'joystick_right_y'],\n                        [Lang.Blocks.controller_joystick_right_direction,   'joystick_right_direction'],\n                        [Lang.Blocks.controller_joystick_right_event,       'joystick_right_event'],\n                    ],\n                    value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_controller_4_value_joystick',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_controller_4_if_button_press: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button_front_left_top,      '1'],\n                        [Lang.Blocks.controller_button_front_left_bottom,   '2'],\n                        [Lang.Blocks.controller_button_front_right_top,     '4'],\n                        [Lang.Blocks.controller_button_front_right_bottom,  '8'],\n                        [Lang.Blocks.controller_button_top_left,            '16'],\n                        [Lang.Blocks.controller_button_top_right,           '32'],\n                        [Lang.Blocks.controller_button_center_up,           '64'],\n                        [Lang.Blocks.controller_button_center_left,         '128'],\n                        [Lang.Blocks.controller_button_center_right,        '256'],\n                        [Lang.Blocks.controller_button_center_down,         '512'],\n                        [Lang.Blocks.controller_button_bottom_left,         '1024'],\n                        [Lang.Blocks.controller_button_bottom_right,        '2048'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_controller_4_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const read        = Entry.hw.portData;\n                const button      = 'button_button';    // paramsKeyMap에 정의된 이름 사용\n                const buttonevent = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        byrobot_controller_4_if_joystick_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.common_right, 'joystick_right_direction'],\n                    ],\n                    value     : 'joystick_left_direction',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_direction_left_up,     '17'],\n                        [Lang.Blocks.controller_joystick_direction_up,          '18'],\n                        [Lang.Blocks.controller_joystick_direction_right_up,    '20'],\n                        [Lang.Blocks.controller_joystick_direction_left,        '33'],\n                        [Lang.Blocks.controller_joystick_direction_center,      '34'],\n                        [Lang.Blocks.controller_joystick_direction_right,       '36'],\n                        [Lang.Blocks.controller_joystick_direction_left_down,   '65'],\n                        [Lang.Blocks.controller_joystick_direction_down,        '66'],\n                        [Lang.Blocks.controller_joystick_direction_right_down,  '68'],\n                    ],\n                    value     : '34',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_controller_4_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE   : 0,\n                DIRECTION: 1,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const read   = Entry.hw.portData;\n                const device = script.getField('DEVICE');  // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION'))\n                {\n                    return true;\n                }\n                else\n                {\n                    return false;\n                }\n            },\n        },\n\n\n        byrobot_controller_4_controller_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_controller_4_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'controller_light',\n            isNotFor    : ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setLightManual(script, 0x20, 0xffff, 0);\n            },\n        },\n\n\n        byrobot_controller_4_controller_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_controller_4_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n        },\n\n\n        byrobot_controller_4_controller_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0xFF'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x20, flags, brightness);\n            },\n        },\n\n\n        byrobot_controller_4_controller_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_controller_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval = script.getNumberValue('INTERVAL');\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                return Entry.byrobot_base.setLightModeColor(script, 0x20, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_controller_4_controller_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'byrobot_controller_4_controller_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n        },\n\n\n        byrobot_controller_4_display_clear_all: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_controller_4_display_clear_all',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayClearAll(script, 0x20, pixel);\n            },\n        },\n\n\n        byrobot_controller_4_display_clear: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                ],\n                type: 'byrobot_controller_4_display_clear',\n            },\n            paramsKeyMap: {\n                X     : 0,\n                Y     : 1,\n                WIDTH : 2,\n                HEIGHT: 3,\n                PIXEL : 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const x      = script.getNumberValue('X');\n                const y      = script.getNumberValue('Y');\n                const width  = script.getNumberValue('WIDTH');\n                const height = script.getNumberValue('HEIGHT');\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayClear(script, 0x20, pixel, x, y, width, height);\n            },\n        },\n\n\n        byrobot_controller_4_display_draw_point: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    null,\n                    null,\n                ],\n                type: 'byrobot_controller_4_display_draw_point',\n            },\n            paramsKeyMap: {\n                X    : 0,\n                Y    : 1,\n                PIXEL: 2,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const x     = script.getNumberValue('X');\n                const y     = script.getNumberValue('Y');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayDrawPoint(script, 0x20, x, y, pixel);\n            },\n        },\n\n\n        byrobot_controller_4_display_draw_line: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    { type: 'text', params: ['96'] },\n                    { type: 'text', params: ['48'] },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_controller_4_display_draw_line',\n            },\n            paramsKeyMap: {\n                X1   : 0,\n                Y1   : 1,\n                X2   : 2,\n                Y2   : 3,\n                PIXEL: 4,\n                LINE : 5,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const x1    = script.getNumberValue('X1');\n                const y1    = script.getNumberValue('Y1');\n                const x2    = script.getNumberValue('X2');\n                const y2    = script.getNumberValue('Y2');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                const line  = parseInt(script.getField('LINE'), 10);\n                return Entry.byrobot_base.setDisplayDrawLine(script, 0x20, x1, y1, x2, y2, pixel, line);\n            },\n        },\n\n\n        byrobot_controller_4_display_draw_rect: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_controller_4_display_draw_rect',\n            },\n            paramsKeyMap: {\n                X       : 0,\n                Y       : 1,\n                WIDTH   : 2,\n                HEIGHT  : 3,\n                PIXEL   : 4,\n                FLAGFILL: 5,\n                LINE    : 6,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const x        = script.getNumberValue('X');\n                const y        = script.getNumberValue('Y');\n                const width    = script.getNumberValue('WIDTH');\n                const height   = script.getNumberValue('HEIGHT');\n                const pixel    = parseInt(script.getField('PIXEL'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n                const line     = parseInt(script.getField('LINE'), 10);\n                return Entry.byrobot_base.setDisplayDrawRect(script, 0x20, x, y, width, height, pixel, flagFill, line);\n            },\n        },\n\n\n        byrobot_controller_4_display_draw_circle: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['24'] },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_controller_4_display_draw_circle',\n            },\n            paramsKeyMap: {\n                X       : 0,\n                Y       : 1,\n                RADIUS  : 2,\n                PIXEL   : 3,\n                FLAGFILL: 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const x        = script.getNumberValue('X');\n                const y        = script.getNumberValue('Y');\n                const radius   = script.getNumberValue('RADIUS');\n                const pixel    = parseInt(script.getField('PIXEL'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n                return Entry.byrobot_base.setDisplayDrawCircle(script, 0x20, x, y, radius, pixel, flagFill);\n            },\n        },\n\n\n        byrobot_controller_4_display_draw_string: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_font_5x8, '0'],\n                        [Lang.Blocks.controller_display_font_10x16, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['39'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                    { type: 'text', params: ['HELLO'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_display_draw_string',\n            },\n            paramsKeyMap: {\n                X     : 0,\n                Y     : 1,\n                FONT  : 2,\n                PIXEL : 3,\n                STRING: 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const x      = script.getNumberValue('X');\n                const y      = script.getNumberValue('Y');\n                const font   = parseInt(script.getField('FONT'), 10);\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                const string = script.getStringValue('STRING');\n                return Entry.byrobot_base.setDisplayDrawString(script, 0x20, x, y, font, pixel, string);\n            },\n        },\n\n\n        byrobot_controller_4_display_draw_string_align: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_align_left, '0'],\n                        [Lang.Blocks.controller_display_align_center, '1'],\n                        [Lang.Blocks.controller_display_align_right, '2'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_font_5x8, '0'],\n                        [Lang.Blocks.controller_display_font_10x16, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0'] },\n                    { type: 'text', params: ['128'] },\n                    { type: 'text', params: ['42'] },\n                    null,\n                    null,\n                    null,\n                    { type: 'text', params: ['DRONE'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_display_draw_string_align',\n            },\n            paramsKeyMap: {\n                XSTART: 0,\n                XEND  : 1,\n                Y     : 2,\n                ALIGN : 3,\n                FONT  : 4,\n                PIXEL : 5,\n                STRING: 6,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const xStart = script.getNumberValue('XSTART');\n                const xEnd   = script.getNumberValue('XEND');\n                const y      = script.getNumberValue('Y');\n                const align  = parseInt(script.getField('ALIGN'), 10);\n                const font   = parseInt(script.getField('FONT'), 10);\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                const string = script.getStringValue('STRING');\n                return Entry.byrobot_base.setDisplayDrawStringAlign(script, 0x20, xStart, xEnd, y, align, font, pixel, string);\n            },\n        },\n\n\n        byrobot_controller_4_buzzer_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_controller_4_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class       : 'buzzer',\n            isNotFor    : ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setBuzzerStop(script, 0x20);\n            },\n        },\n\n\n        byrobot_controller_4_buzzer_scale: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_controller_4_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, 60000, false, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, 60000, false, true);\n                }\n            },\n        },\n\n\n        byrobot_controller_4_buzzer_scale_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, true, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, true, true);\n                }\n            },\n        },\n\n\n        byrobot_controller_4_buzzer_scale_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, false, false);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, false, false);\n                }\n            },\n        },\n\n\n        byrobot_controller_4_buzzer_hz: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1000'] }, null],\n                type  : 'byrobot_controller_4_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const hz = script.getNumberValue('HZ');\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, 60000, false, true);\n            },\n        },\n\n\n        byrobot_controller_4_buzzer_hz_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1000'] }, { type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_controller_4_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ  : 0,\n                TIME: 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, true, true);\n            },\n        },\n\n\n        byrobot_controller_4_buzzer_hz_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['1000'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ  : 0,\n                TIME: 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, false, false);\n            },\n        },\n\n\n        byrobot_controller_4_vibrator_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_controller_4_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class       : 'vibrator',\n            isNotFor    : ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setVibratorStop(script, 0x20);\n            },\n        },\n\n\n        byrobot_controller_4_vibrator_on_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_controller_4_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, true, true);\n            },\n        },\n\n\n        byrobot_controller_4_vibrator_on_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_controller_4_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, false, false);\n            },\n        },\n\n\n        byrobot_controller_4_vibrator_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, true, true);\n            },\n        },\n\n\n        byrobot_controller_4_vibrator_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_controller_4_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_controller_4'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, false, false);\n            },\n        },\n\n    };\n};\n\nmodule.exports = Entry.byrobot_controller_4;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_drone_3_10.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_drone_3_10 = \n{\n    id       : 'F.D',\n    name     : 'byrobot_drone_3_10',\n    url      : 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_drone_3_10.png',\n    title    : {\n        en: 'BYROBOT Battle Drone',\n        ko: '바이로봇 배틀 드론',\n    },\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero()\n    {\n        // 초기화\n        Entry.byrobot_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            if( Entry.hw.portData['state_modeFlight'] == 0x10 )\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x01, 0); // 드론, command = 0x01 (Stop)\n            }\n            else\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x07, 0x12); // 0x12 : FlightEvent::Landing\n            }\n            Entry.byrobot_base.transferBuzzer(0x20, 0, 0, 0);\n            Entry.byrobot_base.transferVibrator(0x20, 0, 0, 0, 0);\n            Entry.byrobot_base.transferLightManual(0x10, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightManual(0x20, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightModeColor(0x10, 0x22, 200, 255, 0, 0); // LED 초기화(드론)\n            Entry.byrobot_base.transferLightModeColor(0x20, 0x22, 200, 255, 0, 0); // LED 초기화(조종기)\n        }\n    },\n};\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.byrobot_drone_3_10.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                // 정보창\n                monitor_state_modeFlight                        : '비행 모드',\n                monitor_state_modeControlFlight                 : '비행 제어기 모드',\n                monitor_state_modeMovement                      : '이동 상태',\n                monitor_state_headless                          : '헤드리스',\n                monitor_state_controlSpeed                      : '제어 속도',\n                monitor_state_sensorOrientation                 : '센서 방향',\n                monitor_state_battery                           : '배터리',\n                monitor_motion_accelX                           : '가속도 X',\n                monitor_motion_accelY                           : '가속도 Y',\n                monitor_motion_accelZ                           : '가속도 Z',\n                monitor_motion_gyroRoll                         : '자이로 Roll',\n                monitor_motion_gyroPitch                        : '자이로 Pitch',\n                monitor_motion_gyroYaw                          : '자이로 Yaw',\n                monitor_motion_angleRoll                        : 'Roll',\n                monitor_motion_anglePitch                       : 'Pitch',\n                monitor_motion_angleYaw                         : 'Yaw',\n                monitor_battle_ir_message                       : 'IR Message',\n                monitor_informationAssembledForEntry_positionX  : '위치 X',\n                monitor_informationAssembledForEntry_positionY  : '위치 Y',\n                monitor_informationAssembledForEntry_positionZ  : '위치 Z',\n                monitor_informationAssembledForEntry_altitude   : '고도',\n                monitor_informationAssembledForEntry_rangeHeight: '거리 센서의 높이',\n                monitor_joystick_left_x                         : '왼쪽 조이스틱 X',\n                monitor_joystick_left_y                         : '왼쪽 조이스틱 Y',\n                monitor_joystick_left_direction                 : '왼쪽 조이스틱 방향',\n                monitor_joystick_left_event                     : '왼쪽 조이스틱 이벤트',\n                monitor_joystick_right_x                        : '오른쪽 조이스틱 X',\n                monitor_joystick_right_y                        : '오른쪽 조이스틱 Y',\n                monitor_joystick_right_direction                : '오른쪽 조이스틱 방향',\n                monitor_joystick_right_event                    : '오른쪽 조이스틱 이벤트',\n                monitor_button_button                           : '버튼',\n                monitor_button_event                            : '버튼 이벤트',\n                monitor_entryhw_countTransferReserved           : '전송 예정 데이터',\n\n                // 일반 블럭\n                common_light_color_red                  : '빨강',\n                common_light_color_yellow               : '노랑',\n                common_light_color_green                : '초록',\n                common_light_color_cyan                 : '하늘색',\n                common_light_color_blue                 : '파랑',\n                common_light_color_magenta              : '자홍',\n                common_light_color_white                : '흰색',\n                common_light_color_black                : '검정',\n                common_light_color_cottoncandy          : '구름솜사탕',\n                common_light_color_emerald              : '에메랄드',\n                common_light_color_lavender             : '라벤더',\n                common_light_color_muscat               : '청포도',\n                common_light_color_strawberrymilk       : '딸기우유',\n                common_light_color_sunset               : '저녁노을',\n                common_light_mode_hold                  : '켜짐',\n                common_light_mode_flicker               : '깜빡임',\n                common_light_mode_flicker_double        : '2번 연속 깜빡임',\n                common_light_mode_dimming               : '천천히 깜빡임',\n                common_light_mode_sunrise               : '점점 밝아짐',\n                common_light_mode_sunset                : '점점 어두워짐',\n                common_light_mode_rainbow               : '무지개',\n                common_light_mode_rainbow2              : '무지개2',\n                common_light_brightness_all             : '전체',\n                common_light_brightness_b100            : '밝기 100%',\n                common_light_brightness_b25             : '밝기 25%',\n                common_light_brightness_b50             : '밝기 50%',\n                common_light_brightness_b75             : '밝기 75%',\n                common_light_brightness_off             : '끄기',\n                common_light_brightness_on              : '켜기',\n                common_left                             : '왼쪽',\n                common_right                            : '오른쪽',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                common_drone                            : '드론',\n                common_controller                       : '조종기',\n                controller_button                       : '버튼',\n                controller_button_event                 : '버튼 이벤트',\n                controller_button_front_left            : '전면 왼쪽 버튼',\n                controller_button_front_right           : '전면 오른쪽 버튼',\n                controller_button_top_left              : '상단 왼쪽 버튼',\n                controller_button_top_right             : '상단 오른쪽 버튼',\n                controller_button_center_up             : '중앙 위 버튼',\n                controller_button_center_left           : '중앙 왼쪽 버튼',\n                controller_button_center                : '중앙 버튼(전원)',\n                controller_button_center_right          : '중앙 오른쪽 버튼',\n                controller_button_center_down           : '중앙 아래쪽 버튼',\n                controller_button_bottom_left           : '하단 왼쪽 버튼',\n                controller_button_bottom_right          : '하단 오른쪽 버튼',\n                controller_buzzer                       : '버저',\n                controller_buzzer_a                     : '라',\n                controller_buzzer_as                    : '라#',\n                controller_buzzer_b                     : '시',\n                controller_buzzer_c                     : '도',\n                controller_buzzer_cs                    : '도#',\n                controller_buzzer_d                     : '레',\n                controller_buzzer_ds                    : '레#',\n                controller_buzzer_e                     : '미',\n                controller_buzzer_f                     : '파',\n                controller_buzzer_fs                    : '파#',\n                controller_buzzer_g                     : '솔',\n                controller_buzzer_gs                    : '솔#',\n                controller_buzzer_mute                  : '쉼',\n                controller_joystick_direction_left_up   : '왼쪽 위',\n                controller_joystick_direction_up        : '위',\n                controller_joystick_direction_right_up  : '오른쪽 위',\n                controller_joystick_direction_left      : '왼쪽',\n                controller_joystick_direction_center    : '중앙',\n                controller_joystick_direction_right     : '오른쪽',\n                controller_joystick_direction_left_down : '왼쪽 아래',\n                controller_joystick_direction_down      : '아래',\n                controller_joystick_direction_right_down: '오른쪽 아래',\n                controller_joystick_left_direction      : '왼쪽 조이스틱 방향',\n                controller_joystick_left_event          : '왼쪽 조이스틱 이벤트',\n                controller_joystick_left_x              : '왼쪽 조이스틱 가로축',\n                controller_joystick_left_y              : '왼쪽 조이스틱 세로축',\n                controller_joystick_right_direction     : '오른쪽 조이스틱 방향',\n                controller_joystick_right_event         : '오른쪽 조이스틱 이벤트',\n                controller_joystick_right_x             : '오른쪽 조이스틱 가로축',\n                controller_joystick_right_y             : '오른쪽 조이스틱 세로축',\n                drone_accel_x                           : '가속도 x',\n                drone_accel_y                           : '가속도 y',\n                drone_accel_z                           : '가속도 z',\n                drone_gyro_pitch                        : '각속도 Pitch',\n                drone_gyro_roll                         : '각속도 Roll',\n                drone_gyro_yaw                          : '각속도 Yaw',\n                drone_attitude_pitch                    : '자세 Pitch',\n                drone_attitude_roll                     : '자세 Roll',\n                drone_attitude_yaw                      : '자세 Yaw',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_roll_left            : '왼쪽',\n                drone_control_quad_roll_right           : '오른쪽',\n                drone_control_quad_pitch_backward       : '뒤',\n                drone_control_quad_pitch_forward        : '앞',\n                drone_control_quad_throttle_down        : '아래',\n                drone_control_quad_throttle_up          : '위',\n                drone_control_quad_yaw_ccw              : '반시계 방향',\n                drone_control_quad_yaw_cw               : '시계 방향',\n                drone_headless_normal                   : 'off (숙련자용)',\n                drone_headless_headless                 : 'on (초보자용)',\n                drone_light_color_body                  : '몸체',\n                drone_light_manual_body_blue            : '파랑',\n                drone_light_manual_body_green           : '초록',\n                drone_light_manual_body_red             : '빨강',\n                drone_motor_rotation_clockwise          : '시계 방향',\n                drone_motor_rotation_counterclockwise   : '반시계 방향',\n                drone_altitude                          : '해발고도',\n                drone_range_height                      : '바닥과의 거리',\n                drone_battle_ir_message                 : '적외선 데이터',\n                drone_state_mode_system                 : '시스템 모드',\n                drone_state_mode_flight                 : '비행 동작 상태',\n                drone_state_mode_control_flight         : '비행 제어 모드',\n                drone_state_mode_movement               : '이동 상태',\n                drone_state_headless                    : 'Headless',\n                drone_state_control_speed               : '제어 속도',\n                drone_state_battery                     : '배터리',\n                entryhw_count_transfer_reserved         : '전송 예약된 데이터 수',\n            },\n\n            template: {\n                byrobot_drone_3_10_controller_buzzer_hz                : '%1 Hz 소리를 연주 %2',\n                byrobot_drone_3_10_controller_buzzer_hz_delay          : '%1 Hz 소리를 %2 초 연주 %3',\n                byrobot_drone_3_10_controller_buzzer_hz_reserve        : '%1 Hz 소리를 %2 초 예약 %3',\n                byrobot_drone_3_10_controller_buzzer_off               : '버저 끄기 %1',\n                byrobot_drone_3_10_controller_buzzer_scale             : '%1 옥타브 %2 을(를) 연주 %3',\n                byrobot_drone_3_10_controller_buzzer_scale_delay       : '%1 옥타브 %2 을(를) %3 초 연주 %4',\n                byrobot_drone_3_10_controller_buzzer_scale_reserve     : '%1 옥타브 %2 을(를) %3 초 예약 %4',\n                byrobot_drone_3_10_controller_if_button_press          : '조종기 %1을 눌렀을 때',\n                byrobot_drone_3_10_controller_if_joystick_direction    : '조종기 %1 조이스틱을 %2(으)로 움직였을 때',\n                byrobot_drone_3_10_controller_light_color_preset       : '조종기 LED %1 %2 %3',\n                byrobot_drone_3_10_controller_light_manual_single_input: '조종기 LED %1 밝기 %2 %3',\n                byrobot_drone_3_10_controller_light_manual_single_off  : '조종기 LED 끄기 %1',\n                byrobot_drone_3_10_controller_value_button             : '%1',\n                byrobot_drone_3_10_controller_value_joystick           : '%1',\n                byrobot_drone_3_10_controller_vibrator_delay           : '진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4',\n                byrobot_drone_3_10_controller_vibrator_off             : '진동 끄기 %1',\n                byrobot_drone_3_10_controller_vibrator_on_delay        : '진동 %1 초 켜기 %2',\n                byrobot_drone_3_10_controller_vibrator_on_reserve      : '진동 %1 초 예약 %2',\n                byrobot_drone_3_10_controller_vibrator_reserve         : '진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4',\n                byrobot_drone_3_10_drone_control_headless              : 'Headless mode %1 %2',\n                byrobot_drone_3_10_drone_control_drone_landing         : '드론 착륙 %1',\n                byrobot_drone_3_10_drone_control_drone_reset_heading   : '드론 방향 초기화 %1',\n                byrobot_drone_3_10_drone_control_drone_stop            : '드론 정지 %1',\n                byrobot_drone_3_10_drone_control_drone_takeoff         : '드론 이륙 %1',\n                byrobot_drone_3_10_drone_control_quad                  : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% 정하기 %5',\n                byrobot_drone_3_10_drone_control_quad_delay            : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5초 실행 %6',\n                byrobot_drone_3_10_drone_control_quad_one              : '드론 %1 %2% 정하기 %3',\n                byrobot_drone_3_10_drone_control_quad_one_delay        : '드론 %1 %2% %3 초 실행 %4',\n                byrobot_drone_3_10_drone_light_color_input             : '드론 LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_3_10_drone_light_color_select            : '드론 LED %1 %2 %3 %4',\n                byrobot_drone_3_10_drone_light_color_preset            : '드론 LED %1 %2 %3',\n                byrobot_drone_3_10_drone_light_manual_single_input     : '드론 LED %1 밝기 %2 %3',\n                byrobot_drone_3_10_drone_light_manual_single_off       : '드론 LED 끄기 %1',\n                byrobot_drone_3_10_drone_motor_stop                    : '드론 모터 정지 %1',\n                byrobot_drone_3_10_drone_motorsingle                   : '드론 %1번 모터를 %2(으)로 회전 %3',\n                byrobot_drone_3_10_drone_motorsingle_input             : '드론 %1번 모터를 %2(으)로 회전 %3',\n                byrobot_drone_3_10_drone_battle_ir_message             : '드론 적외선 데이터 %1 전송 %2',\n                byrobot_drone_3_10_drone_value_attitude                : '%1',\n                byrobot_drone_3_10_drone_value_motion                  : '%1',\n                byrobot_drone_3_10_drone_value_sensor                  : '%1',\n                byrobot_drone_3_10_drone_value_ir                      : '%1',\n                byrobot_drone_3_10_drone_value_etc                     : '%1',\n            },\n\n            Helper: {\n                byrobot_drone_3_10_controller_buzzer_hz                : \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                byrobot_drone_3_10_controller_buzzer_hz_delay          : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                byrobot_drone_3_10_controller_buzzer_hz_reserve        : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                byrobot_drone_3_10_controller_buzzer_off               : \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                byrobot_drone_3_10_controller_buzzer_scale             : \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                byrobot_drone_3_10_controller_buzzer_scale_delay       : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                byrobot_drone_3_10_controller_buzzer_scale_reserve     : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                byrobot_drone_3_10_controller_if_button_press          : \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                byrobot_drone_3_10_controller_if_joystick_direction    : \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                byrobot_drone_3_10_controller_light_color_preset       : \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_3_10_controller_light_manual_single_input: \"<br>조종기 LED를 조작하는데 사용합니다.<br>LED를 선택하는데는 10진수(0 ~ 255) 또는 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_3_10_controller_light_manual_single_off  : \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                byrobot_drone_3_10_controller_value_button             : \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                byrobot_drone_3_10_controller_value_joystick           : \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                byrobot_drone_3_10_controller_vibrator_delay           : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                byrobot_drone_3_10_controller_vibrator_off             : \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                byrobot_drone_3_10_controller_vibrator_on_delay        : \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                byrobot_drone_3_10_controller_vibrator_on_reserve      : \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                byrobot_drone_3_10_controller_vibrator_reserve         : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                byrobot_drone_3_10_drone_control_headless              : \"<br>드론 좌표 기준을 변경합니다. Headless mode 선택을 on으로 하면 이륙 시와 '방향초기화'를 했을 때 드론이 바라보는 방향을 기준으로 앞뒤좌우가 고정됩니다. 이 때에는 Yaw를 조작하여 드론이 다른 방향을 보게 하여도 처음 지정한 방향을 기준으로 앞뒤좌우로 움직입니다. 사용자가 바라보는 방향과 드론의 기준 방향이 같을 때 조작하기 편리한 장점이 있습니다.<br>Headless mode를 off로 선택하면 현재 드론이 바라보는 방향을 기준으로 앞뒤좌우가 결정됩니다. 드론의 움직임에 따라 앞뒤좌우가 계속 바뀌기 때문에 익숙해지기 전까지는 사용하기 어려울 수 있습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#좌표기준</font>\",\n                byrobot_drone_3_10_drone_control_drone_landing         : \"<br>드론을 착륙시킵니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#착륙</font>\",\n                byrobot_drone_3_10_drone_control_drone_reset_heading   : \"<br>드론의 방향을 초기화합니다. 앱솔루트 모드인 경우 현재 드론이 바라보는 방향을 0도로 변경합니다. 일반 모드에서는 아무런 영향이 없습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#방향초기화</font>\",\n                byrobot_drone_3_10_drone_control_drone_stop            : \"<br>드론 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#정지</font>\",\n                byrobot_drone_3_10_drone_control_drone_takeoff         : \"<br>드론을 이륙시킵니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이륙</font>\",\n                byrobot_drone_3_10_drone_control_quad                  : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                byrobot_drone_3_10_drone_control_quad_delay            : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_3_10_drone_control_quad_one              : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                byrobot_drone_3_10_drone_control_quad_one_delay        : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_3_10_drone_light_color_input             : \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 드론의 눈 또는 팔 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_3_10_drone_light_color_select            : \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 드론 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_3_10_drone_light_color_preset            : \"<br>드론의 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_3_10_drone_light_manual_single_input     : \"<br>드론 LED를 조작하는데 사용합니다.<br>LED를 선택하는데는 10진수(0 ~ 255) 또는 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_3_10_drone_light_manual_single_off       : \"<br>드론의 모든 LED를 끕니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED끄기</font>\",\n                byrobot_drone_3_10_drone_motor_stop                    : \"<br>모든 모터의 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터정지</font>\",\n                byrobot_drone_3_10_drone_motorsingle                   : \"<br>모터 제어 블럭입니다.<br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                byrobot_drone_3_10_drone_motorsingle_input             : \"<br>모터 제어 블럭입니다.<br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                byrobot_drone_3_10_drone_battle_ir_message             : \"<br>드론 적외선 데이터 송신 장치로 지정한 값을 전송합니다. 값의 범위는 0 ~ 0xFF 입니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#적외선_데이터_송신</font>\",\n                byrobot_drone_3_10_drone_value_attitude                : \"<br>드론의 현재 자세를 각도로 반환합니다. Roll은 좌우 기울기(-90 ~ 90), Pitch는 앞뒤 기울기(-90 ~ 90), Yaw는 회전 각도(-180 ~ 180) 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#자세</font>\",\n                byrobot_drone_3_10_drone_value_etc                     : \"<br>드론 설정과 관련된 값들과 적외선 통신으로 받은 값을 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#기타</font>\",\n                byrobot_drone_3_10_drone_value_motion                  : \"<br>드론 IMU센서와 관련된 값들을 반환합니다.<br>(병진운동) 가속도는 x, y, z축에 대한 중력가속도입니다. 1g = 9.8m/s^2<br>(회전운동) 각속도는 x, y, z축을 기준으로 회전하는 속력을 나타내는 벡터입니다.(pitch, roll, yaw) <br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#IMU센서</font> <font color='crimson'>#가속도</font> <font color='dodgerblue'>#병진운동</font> <font color='crimson'>#각속도</font> <font color='dodgerblue'>#회전운동</font>\",\n                byrobot_drone_3_10_drone_value_sensor                  : \"<br>드론 센서와 관련된 값들을 반환합니다.<br>온도 단위=섭씨 도, 해발고도 단위=m, image flow 단위=m, 바닥까지의 거리 단위=m<br>해발고도 값은 대기압의 영향을 받아서 오차범위가 큽니다. 바닥까지 거리의 유효 측정 거리는 2m입니다. image flow값은 일정한 속도와 높이에서 이동할 경우에 유효합니다. 이러한 센서값들을 이용하여 호버링(고도 유지) 기능을 수행합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#센서</font> <font color='crimson'>#온도</font> <font color='dodgerblue'>#해발고도</font> <font color='forestgreen'>#image flow</font> <font color='crimson'>#range</font> <font color='dodgerblue'>#대기압</font> <font color='forestgreen'>#호버링</font>\",\n                byrobot_drone_3_10_drone_value_ir                      : \"<br>드론 적외선 데이터 수신 장치에서 받은 데이터를 반환합니다<br><br><font color='dodgerblue'>#드론</font> <font color='forestgreen'>#적외선_데이터_수신</font>\",\n            },\n        },\n\n        en: {\n            Blocks: {\n                // 정보창\n                monitor_state_modeFlight                        : 'Flight Mode',\n                monitor_state_modeControlFlight                 : 'Control Flight Mode',\n                monitor_state_modeMovement                      : 'Movement Mode',\n                monitor_state_headless                          : 'Headless',\n                monitor_state_controlSpeed                      : 'Control Speed',\n                monitor_state_sensorOrientation                 : 'Sensor Orientation',\n                monitor_state_battery                           : 'Battery',\n                monitor_motion_accelX                           : 'Accel X',\n                monitor_motion_accelY                           : 'Accel Y',\n                monitor_motion_accelZ                           : 'Accel Z',\n                monitor_motion_gyroRoll                         : 'Gyro Roll',\n                monitor_motion_gyroPitch                        : 'Gyro Pitch',\n                monitor_motion_gyroYaw                          : 'Gyro Yaw',\n                monitor_motion_angleRoll                        : 'Roll',\n                monitor_motion_anglePitch                       : 'Pitch',\n                monitor_motion_angleYaw                         : 'Yaw',\n                monitor_battle_ir_message                       : 'IR Message',\n                monitor_informationAssembledForEntry_positionX  : 'Position X',\n                monitor_informationAssembledForEntry_positionY  : 'Position Y',\n                monitor_informationAssembledForEntry_positionZ  : 'Position Z',\n                monitor_informationAssembledForEntry_altitude   : 'Altitude',\n                monitor_informationAssembledForEntry_rangeHeight: 'Height',\n                monitor_joystick_left_x                         : 'Left Joystick X',\n                monitor_joystick_left_y                         : 'Left Joystick Y',\n                monitor_joystick_left_direction                 : 'Left Joystick Direction',\n                monitor_joystick_left_event                     : 'Left Joystick Event',\n                monitor_joystick_right_x                        : 'Right Joystick X',\n                monitor_joystick_right_y                        : 'Right Joystick Y',\n                monitor_joystick_right_direction                : 'Right Joystick Direction',\n                monitor_joystick_right_event                    : 'Right Joystick Event',\n                monitor_button_button                           : 'Button',\n                monitor_button_event                            : 'Button Event',\n                monitor_entryhw_countTransferReserved           : 'Transfer Buffer',\n\n                // 일반 블럭\n                common_light_color_cottoncandy          : 'cotton candy',\n                common_light_color_emerald              : 'emerald',\n                common_light_color_lavender             : 'lavender',\n                common_light_color_muscat               : 'muscat',\n                common_light_color_strawberrymilk       : 'strawberry milk',\n                common_light_color_sunset               : 'sunset',\n                common_light_mode_hold                  : 'hold',\n                common_light_mode_dimming               : 'dimming',\n                common_light_mode_flicker               : 'flicker',\n                common_light_mode_flicker_double        : 'flicker double',\n                common_light_brightness_all             : 'all',\n                common_light_brightness_b100            : 'brightness 100%',\n                common_light_brightness_b25             : 'brightness 25%',\n                common_light_brightness_b50             : 'brightness 50%',\n                common_light_brightness_b75             : 'brightness 75%',\n                common_light_color_blue                 : 'blue',\n                common_light_color_cyan                 : 'cyan',\n                common_light_color_green                : 'green',\n                common_light_color_magenta              : 'magenta',\n                common_light_brightness_off             : 'off',\n                common_light_brightness_on              : 'on',\n                common_light_color_red                  : 'red',\n                common_light_color_white                : 'white',\n                common_light_color_yellow               : 'yellow',\n                common_left                             : 'left',\n                common_right                            : 'right',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                controller_button                       : 'button',\n                controller_button_event                 : 'button event',\n                controller_button_front_left            : 'Front left button',\n                controller_button_front_right           : 'Front right button',\n                controller_button_top_left              : 'Top left button',\n                controller_button_top_right             : 'Top right button',\n                controller_button_center_up             : 'Trim up button',\n                controller_button_center_left           : 'Trim left button',\n                controller_button_center                : 'Center button(Power)',\n                controller_button_center_right          : 'Trim right button',\n                controller_button_center_down           : 'Trim down button',\n                controller_button_bottom_left           : 'Bottom left button',\n                controller_button_bottom_right          : 'Bottom right button',\n                controller_buzzer                       : 'buzzer',\n                controller_buzzer_a                     : 'A',\n                controller_buzzer_as                    : 'A#',\n                controller_buzzer_b                     : 'B',\n                controller_buzzer_c                     : 'C',\n                controller_buzzer_cs                    : 'C#',\n                controller_buzzer_d                     : 'D',\n                controller_buzzer_ds                    : 'D#',\n                controller_buzzer_e                     : 'E',\n                controller_buzzer_f                     : 'F',\n                controller_buzzer_fs                    : 'F#',\n                controller_buzzer_g                     : 'G',\n                controller_buzzer_gs                    : 'G#',\n                controller_buzzer_mute                  : 'mute',\n                controller_joystick_direction_left_up   : 'Left top',\n                controller_joystick_direction_up        : 'Top',\n                controller_joystick_direction_right_up  : 'Right top',\n                controller_joystick_direction_left      : 'Left',\n                controller_joystick_direction_center    : 'Center',\n                controller_joystick_direction_right     : 'Right',\n                controller_joystick_direction_left_down : 'Left Bottom',\n                controller_joystick_direction_down      : 'Bottom',\n                controller_joystick_direction_right_down: 'Right Bottom',\n                controller_joystick_left_direction      : 'left joystick direction',\n                controller_joystick_left_event          : 'left joystick event',\n                controller_joystick_left_x              : 'left joystick X',\n                controller_joystick_left_y              : 'left joystick Y',\n                controller_joystick_right_direction     : 'right joystick direction',\n                controller_joystick_right_event         : 'right joystick event',\n                controller_joystick_right_x             : 'right joystick X',\n                controller_joystick_right_y             : 'right joystick Y',\n                drone_accel_x                           : 'Accel x',\n                drone_accel_y                           : 'Accel y',\n                drone_accel_z                           : 'Accel z',\n                drone_gyro_pitch                        : 'Gyro Pitch',\n                drone_gyro_roll                         : 'Gyro Roll',\n                drone_gyro_yaw                          : 'Gyro Yaw',\n                drone_attitude_pitch                    : 'Attitude Pitch',\n                drone_attitude_roll                     : 'Attitude Roll',\n                drone_attitude_yaw                      : 'Attitude Yaw',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_pitch_backward       : 'Backward',\n                drone_control_quad_pitch_forward        : 'Forward',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_roll_left            : 'Left',\n                drone_control_quad_roll_right           : 'Right',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_throttle_down        : 'Down',\n                drone_control_quad_throttle_up          : 'Up',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_yaw_ccw              : 'Counterclockwise',\n                drone_control_quad_yaw_cw               : 'clockwise',\n                drone_headless_normal                   : 'Normal',\n                drone_headless_headless                 : 'Headless',\n                drone_light_color_body                  : 'Body',\n                drone_light_manual_body_blue            : 'Blue',\n                drone_light_manual_body_green           : 'Green',\n                drone_light_manual_body_red             : 'Red',\n                drone_motor_rotation_clockwise          : 'Clockwise',\n                drone_motor_rotation_counterclockwise   : 'Counterclockwise',\n                drone_altitude                          : 'Altitude',\n                drone_range_height                      : 'Height',\n                drone_battle_ir_message                 : 'IR Data',\n                drone_state_mode_system                 : 'System Mode',\n                drone_state_mode_flight                 : 'Flight Mode',\n                drone_state_mode_control_flight         : 'Flight Control Mode',\n                drone_state_mode_movement               : 'mode movement',\n                drone_state_headless                    : 'Headless',\n                drone_state_control_speed               : 'Speed',\n                drone_state_battery                     : 'Battery',\n                entryhw_count_transfer_reserved         : 'Reserved data for transfer',\n            },\n\n            template: {\n                byrobot_drone_3_10_controller_buzzer_hz                : 'play Buzzer %1 Hz sound %2',\n                byrobot_drone_3_10_controller_buzzer_hz_delay          : 'play Buzzer %1 Hz sound for %2 second %3',\n                byrobot_drone_3_10_controller_buzzer_hz_reserve        : 'reserve to play Buzzer %1 Hz for %2 second %3',\n                byrobot_drone_3_10_controller_buzzer_off               : 'turn off the buzzer %1',\n                byrobot_drone_3_10_controller_buzzer_scale             : 'play %1 octave %2 %3',\n                byrobot_drone_3_10_controller_buzzer_scale_delay       : 'play %1 octave %2 for %3 second %4',\n                byrobot_drone_3_10_controller_buzzer_scale_reserve     : 'reserve to play %1 octave %2 for %3 second %4',\n                byrobot_drone_3_10_controller_if_button_press          : 'when press %1',\n                byrobot_drone_3_10_controller_if_joystick_direction    : 'when %1 stick move to %2',\n                byrobot_drone_3_10_controller_light_color_preset       : 'Controller LED %1 %2 %3',\n                byrobot_drone_3_10_controller_light_manual_single_input: 'Controller LED %1 Lightness %2 %3',\n                byrobot_drone_3_10_controller_light_manual_single_off  : 'Controller LED Off %1',\n                byrobot_drone_3_10_controller_value_button             : '%1',\n                byrobot_drone_3_10_controller_value_joystick           : '%1',\n                byrobot_drone_3_10_controller_vibrator_off             : 'Vibrator Off %1',\n                byrobot_drone_3_10_controller_vibrator_delay           : 'Vibrator %1 sec On, %2 sec Off for %3 sec run %4',\n                byrobot_drone_3_10_controller_vibrator_on_delay        : 'Vibrator %1 sec on %2',\n                byrobot_drone_3_10_controller_vibrator_on_reserve      : 'Vibrator %1 sec reserve %2',\n                byrobot_drone_3_10_controller_vibrator_reserve         : 'Vibrator %1 sec On, %2 sec Off for %3 sec reserve %4',\n                byrobot_drone_3_10_drone_control_headless              : 'Headless mode %1 %2',\n                byrobot_drone_3_10_drone_control_drone_landing         : 'Landing %1',\n                byrobot_drone_3_10_drone_control_drone_reset_heading   : 'Reset heading %1',\n                byrobot_drone_3_10_drone_control_drone_stop            : 'Stop flight %1',\n                byrobot_drone_3_10_drone_control_drone_takeoff         : 'Takeoff %1',\n                byrobot_drone_3_10_drone_control_quad                  : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5',\n                byrobot_drone_3_10_drone_control_quad_delay            : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% for %5sec %6',\n                byrobot_drone_3_10_drone_control_quad_one              : 'Set %1 %2% %3',\n                byrobot_drone_3_10_drone_control_quad_one_delay        : 'Set %1 %2% %3 sec %4',\n                byrobot_drone_3_10_drone_light_manual_single_off       : 'Drone LED Off %1',\n                byrobot_drone_3_10_drone_light_manual_single_input     : 'Drone LED %1 lightness %2 %3',\n                byrobot_drone_3_10_drone_light_color_input             : 'Drone LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_3_10_drone_light_color_select            : 'Drone LED %1 %2 %3 %4',\n                byrobot_drone_3_10_drone_light_color_preset            : 'Drone LED %1 %2 %3',\n                byrobot_drone_3_10_drone_motor_stop                    : 'Motor stop %1',\n                byrobot_drone_3_10_drone_motorsingle                   : 'No. %1 Motor rotate for %2 %3',\n                byrobot_drone_3_10_drone_motorsingle_input             : 'No. %1 Motor rotate for %2 %3',\n                byrobot_drone_3_10_drone_battle_ir_message             : 'transfer %1 to IR transmitter %2',\n                byrobot_drone_3_10_drone_value_attitude                : '%1',\n                byrobot_drone_3_10_drone_value_motion                  : '%1',\n                byrobot_drone_3_10_drone_value_sensor                  : '%1',\n                byrobot_drone_3_10_drone_value_ir                      : '%1',\n                byrobot_drone_3_10_drone_value_etc                     : '%1',\n            },\n\n            Helper: {\n                byrobot_drone_3_10_controller_buzzer_hz                : '',\n                byrobot_drone_3_10_controller_buzzer_hz_delay          : '',\n                byrobot_drone_3_10_controller_buzzer_hz_reserve        : '',\n                byrobot_drone_3_10_controller_buzzer_off               : '',\n                byrobot_drone_3_10_controller_buzzer_scale             : '',\n                byrobot_drone_3_10_controller_buzzer_scale_delay       : '',\n                byrobot_drone_3_10_controller_buzzer_scale_reserve     : '',\n                byrobot_drone_3_10_controller_if_button_press          : '',\n                byrobot_drone_3_10_controller_if_joystick_direction    : '',\n                byrobot_drone_3_10_controller_light_color_preset       : '',\n                byrobot_drone_3_10_controller_light_manual_single_input: '',\n                byrobot_drone_3_10_controller_light_manual_single_off  : '',\n                byrobot_drone_3_10_controller_value_button             : '',\n                byrobot_drone_3_10_controller_value_joystick           : '',\n                byrobot_drone_3_10_controller_vibrator_delay           : '',\n                byrobot_drone_3_10_controller_vibrator_off             : '',\n                byrobot_drone_3_10_controller_vibrator_on_delay        : '',\n                byrobot_drone_3_10_controller_vibrator_on_reserve      : '',\n                byrobot_drone_3_10_controller_vibrator_reserve         : '',\n                byrobot_drone_3_10_drone_control_headless              : '',\n                byrobot_drone_3_10_drone_control_drone_landing         : '',\n                byrobot_drone_3_10_drone_control_drone_reset_heading   : '',\n                byrobot_drone_3_10_drone_control_drone_stop            : '',\n                byrobot_drone_3_10_drone_control_drone_takeoff         : '',\n                byrobot_drone_3_10_drone_control_quad                  : '',\n                byrobot_drone_3_10_drone_control_quad_delay            : '',\n                byrobot_drone_3_10_drone_control_quad_one              : '',\n                byrobot_drone_3_10_drone_control_quad_one_delay        : '',\n                byrobot_drone_3_10_drone_light_color_input             : '',\n                byrobot_drone_3_10_drone_light_color_select            : '',\n                byrobot_drone_3_10_drone_light_color_preset            : '',\n                byrobot_drone_3_10_drone_light_manual_single_input     : '',\n                byrobot_drone_3_10_drone_light_manual_single_off       : '',\n                byrobot_drone_3_10_drone_motor_stop                    : '',\n                byrobot_drone_3_10_drone_motorsingle                   : '',\n                byrobot_drone_3_10_drone_motorsingle_input             : '',\n                byrobot_drone_3_10_drone_battle_ir_message             : '',\n                byrobot_drone_3_10_drone_value_attitude                : '',\n                byrobot_drone_3_10_drone_value_etc                     : '',\n                byrobot_drone_3_10_drone_value_motion                  : '',\n                byrobot_drone_3_10_drone_value_ir                      : '',\n                byrobot_drone_3_10_drone_value_sensor                  : '',\n            },\n        },\n    };\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.byrobot_drone_3_10.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/byrobot_drone_3_10.png\",   // 배경 이미지\n        width  : 256,                           // 이미지의 폭\n        height : 256,                           // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeFlight                     : { name: Lang.Blocks.monitor_state_modeFlight,                           type: 'input', pos: { x: 0, y: 0 } },\n            state_modeControlFlight              : { name: Lang.Blocks.monitor_state_modeControlFlight,                    type: 'input', pos: { x: 0, y: 0 } },\n            state_modeMovement                   : { name: Lang.Blocks.monitor_state_modeMovement,                         type: 'input', pos: { x: 0, y: 0 } },\n            state_headless                       : { name: Lang.Blocks.monitor_state_headless,                             type: 'input', pos: { x: 0, y: 0 } },\n            state_controlSpeed                   : { name: Lang.Blocks.monitor_state_controlSpeed,                         type: 'input', pos: { x: 0, y: 0 } },\n            state_sensorOrientation              : { name: Lang.Blocks.monitor_state_sensorOrientation,                    type: 'input', pos: { x: 0, y: 0 } },\n            state_battery                        : { name: Lang.Blocks.monitor_state_battery,                              type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelX                        : { name: Lang.Blocks.monitor_motion_accelX,                              type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelY                        : { name: Lang.Blocks.monitor_motion_accelY,                              type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelZ                        : { name: Lang.Blocks.monitor_motion_accelZ,                              type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroRoll                      : { name: Lang.Blocks.monitor_motion_gyroRoll,                            type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroPitch                     : { name: Lang.Blocks.monitor_motion_gyroPitch,                           type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroYaw                       : { name: Lang.Blocks.monitor_motion_gyroYaw,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleRoll                     : { name: Lang.Blocks.monitor_motion_angleRoll,                           type: 'input', pos: { x: 0, y: 0 } },\n            motion_anglePitch                    : { name: Lang.Blocks.monitor_motion_anglePitch,                          type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleYaw                      : { name: Lang.Blocks.monitor_motion_angleYaw,                            type: 'input', pos: { x: 0, y: 0 } },\n            battle_ir_message                    : { name: Lang.Blocks.monitor_battle_ir_message,                          type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_altitude: { name: Lang.Blocks.monitor_informationAssembledForEntry_altitude,      type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_x                      : { name: Lang.Blocks.monitor_joystick_left_x,                            type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_y                      : { name: Lang.Blocks.monitor_joystick_left_y,                            type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_direction              : { name: Lang.Blocks.monitor_joystick_left_direction,                    type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_event                  : { name: Lang.Blocks.monitor_joystick_left_event,                        type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_x                     : { name: Lang.Blocks.monitor_joystick_right_x,                           type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_y                     : { name: Lang.Blocks.monitor_joystick_right_y,                           type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_direction             : { name: Lang.Blocks.monitor_joystick_right_direction,                   type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_event                 : { name: Lang.Blocks.monitor_joystick_right_event,                       type: 'input', pos: { x: 0, y: 0 } },\n            button_button                        : { name: Lang.Blocks.monitor_button_button,                              type: 'input', pos: { x: 0, y: 0 } },\n            button_event                         : { name: Lang.Blocks.monitor_button_event,                               type: 'input', pos: { x: 0, y: 0 } },\n            entryhw_countTransferReserved        : { name: Lang.Blocks.monitor_entryhw_countTransferReserved,              type: 'output', pos: { x: 0, y: 0 } },\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both',   // 표시 모드\n    };\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 블록명(다른 장치의 블록 이름과 달라야 함)\n ***************************************************************************************/\nEntry.byrobot_drone_3_10.blockMenuBlocks = [\n    'byrobot_drone_3_10_drone_value_attitude',\n    'byrobot_drone_3_10_drone_value_motion',\n    'byrobot_drone_3_10_drone_value_sensor',\n    'byrobot_drone_3_10_drone_value_ir',\n    'byrobot_drone_3_10_drone_value_etc',\n    'byrobot_drone_3_10_controller_value_button',\n    'byrobot_drone_3_10_controller_value_joystick',\n    'byrobot_drone_3_10_controller_if_button_press',\n    'byrobot_drone_3_10_controller_if_joystick_direction',\n    'byrobot_drone_3_10_drone_control_drone_takeoff',\n    'byrobot_drone_3_10_drone_control_drone_landing',\n    'byrobot_drone_3_10_drone_control_drone_stop',\n    'byrobot_drone_3_10_drone_control_headless',\n    'byrobot_drone_3_10_drone_control_drone_reset_heading',\n    'byrobot_drone_3_10_drone_control_quad_one',\n    'byrobot_drone_3_10_drone_control_quad_one_delay',\n    'byrobot_drone_3_10_drone_control_quad',\n    'byrobot_drone_3_10_drone_control_quad_delay',\n    'byrobot_drone_3_10_drone_motor_stop',\n    'byrobot_drone_3_10_drone_motorsingle',\n    'byrobot_drone_3_10_drone_motorsingle_input',\n    'byrobot_drone_3_10_drone_battle_ir_message',\n    'byrobot_drone_3_10_drone_light_manual_single_off',\n    'byrobot_drone_3_10_drone_light_manual_single_input',\n    'byrobot_drone_3_10_drone_light_color_preset',\n    'byrobot_drone_3_10_drone_light_color_input',\n    'byrobot_drone_3_10_drone_light_color_select',\n    'byrobot_drone_3_10_controller_light_manual_single_off',\n    'byrobot_drone_3_10_controller_light_manual_single_input',\n    'byrobot_drone_3_10_controller_light_color_preset',\n    'byrobot_drone_3_10_controller_buzzer_off',\n    'byrobot_drone_3_10_controller_buzzer_scale',\n    'byrobot_drone_3_10_controller_buzzer_scale_delay',\n    'byrobot_drone_3_10_controller_buzzer_scale_reserve',\n    'byrobot_drone_3_10_controller_buzzer_hz',\n    'byrobot_drone_3_10_controller_buzzer_hz_delay',\n    'byrobot_drone_3_10_controller_buzzer_hz_reserve',\n    'byrobot_drone_3_10_controller_vibrator_off',\n    'byrobot_drone_3_10_controller_vibrator_on_delay',\n    'byrobot_drone_3_10_controller_vibrator_on_reserve',\n    'byrobot_drone_3_10_controller_vibrator_delay',\n    'byrobot_drone_3_10_controller_vibrator_reserve',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 정의\n ***************************************************************************************/\nEntry.byrobot_drone_3_10.getBlocks = function()\n{\n    return {\n        byrobot_drone_3_10_drone_value_attitude: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_attitude_roll,   'motion_angleRoll'],\n                        [Lang.Blocks.drone_attitude_pitch,  'motion_anglePitch'],\n                        [Lang.Blocks.drone_attitude_yaw,    'motion_angleYaw'],\n                    ],\n                    value     : 'motion_angleRoll',                            // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_value_attitude',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_3_10_drone_value_motion: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_accel_x,     'motion_accelX'],\n                        [Lang.Blocks.drone_accel_y,     'motion_accelY'],\n                        [Lang.Blocks.drone_accel_z,     'motion_accelZ'],\n                        [Lang.Blocks.drone_gyro_roll,   'motion_gyroRoll'],\n                        [Lang.Blocks.drone_gyro_pitch,  'motion_gyroPitch'],\n                        [Lang.Blocks.drone_gyro_yaw,    'motion_gyroYaw'],\n                    ],\n                    value     : 'motion_accelX',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_value_motion',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_3_10_drone_value_sensor: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_altitude,        'informationAssembledForEntry_altitude'],\n                    ],\n                    value     : 'informationAssembledForEntry_altitude',       // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_value_sensor',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_3_10_drone_value_ir: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_battle_ir_message,       'battle_ir_message'],\n                    ],\n                    value     : 'battle_ir_message',                           // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_value_ir',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_3_10_drone_value_etc: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_state_mode_flight,           'state_modeFlight'],\n                        [Lang.Blocks.drone_state_mode_control_flight,   'state_modeControlFlight'],\n                        [Lang.Blocks.drone_state_mode_movement,         'state_modeMovement'],\n                        [Lang.Blocks.drone_state_headless,              'state_headless'],\n                        [Lang.Blocks.drone_state_control_speed,         'state_controlSpeed'],\n                        [Lang.Blocks.drone_state_battery,               'state_battery'],\n                    ],\n                    value     : 'state_battery',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_value_etc',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_3_10_controller_value_button: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button,         'button_button'],\n                        [Lang.Blocks.controller_button_event,   'button_event'],\n                    ],\n                    value     : 'button_button',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_controller_value_button',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_3_10_controller_value_joystick: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_left_x,            'joystick_left_x'],\n                        [Lang.Blocks.controller_joystick_left_y,            'joystick_left_y'],\n                        [Lang.Blocks.controller_joystick_left_direction,    'joystick_left_direction'],\n                        [Lang.Blocks.controller_joystick_left_event,        'joystick_left_event'],\n                        [Lang.Blocks.controller_joystick_right_x,           'joystick_right_x'],\n                        [Lang.Blocks.controller_joystick_right_y,           'joystick_right_y'],\n                        [Lang.Blocks.controller_joystick_right_direction,   'joystick_right_direction'],\n                        [Lang.Blocks.controller_joystick_right_event,       'joystick_right_event'],\n                    ],\n                    value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_controller_value_joystick',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_3_10_controller_if_button_press: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button_front_left,   '1'],\n                        [Lang.Blocks.controller_button_front_right,  '2'],\n                        [Lang.Blocks.controller_button_top_left,     '4'],\n                        [Lang.Blocks.controller_button_top_right,    '8'],\n                        [Lang.Blocks.controller_button_center_up,    '16'],\n                        [Lang.Blocks.controller_button_center_left,  '32'],\n                        [Lang.Blocks.controller_button_center_right, '128'],\n                        [Lang.Blocks.controller_button_center_down,  '256'],\n                        [Lang.Blocks.controller_button_bottom_left,  '512'],\n                        [Lang.Blocks.controller_button_bottom_right, '1024'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const read        = Entry.hw.portData;\n                const button      = 'button_button';    // paramsKeyMap에 정의된 이름 사용\n                const buttonevent = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        byrobot_drone_3_10_controller_if_joystick_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.common_right, 'joystick_right_direction'],\n                    ],\n                    value     : 'joystick_left_direction',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_direction_left_up,     '17'],\n                        [Lang.Blocks.controller_joystick_direction_up,          '18'],\n                        [Lang.Blocks.controller_joystick_direction_right_up,    '20'],\n                        [Lang.Blocks.controller_joystick_direction_left,        '33'],\n                        [Lang.Blocks.controller_joystick_direction_center,      '34'],\n                        [Lang.Blocks.controller_joystick_direction_right,       '36'],\n                        [Lang.Blocks.controller_joystick_direction_left_down,   '65'],\n                        [Lang.Blocks.controller_joystick_direction_down,        '66'],\n                        [Lang.Blocks.controller_joystick_direction_right_down,  '68'],\n                    ],\n                    value     : '34',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_3_10_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE   : 0,\n                DIRECTION: 1,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const read   = Entry.hw.portData;\n                const device = script.getField('DEVICE');  // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION'))\n                {\n                    return true;\n                }\n                else\n                {\n                    return false;\n                }\n            },\n        },\n\n        byrobot_drone_3_10_controller_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'controller_light',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setLightManual(script, 0x20, 0xffff, 0);\n            },\n        },\n\n        byrobot_drone_3_10_controller_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_drone_3_10_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const mode        = 0x12;\n                const interval    = parseInt(script.getField('BRIGHTNESS'));\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n        },\n\n        byrobot_drone_3_10_controller_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0xFC'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x20, flags, brightness);\n            },\n        },\n\n        byrobot_drone_3_10_drone_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'drone_light',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setLightManual(script, 0x10, 0xff, 0);\n            },\n        },\n\n        byrobot_drone_3_10_drone_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_drone_3_10_drone_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n        },\n\n        byrobot_drone_3_10_drone_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x03'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x10, flags, brightness);\n            },\n        },\n\n        byrobot_drone_3_10_drone_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_drone_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'));\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                const interval = script.getNumberValue('INTERVAL');\n                return Entry.byrobot_base.setLightModeColor(script, 0x10, mode, interval, red, green, blue);\n            },\n        },\n\n        byrobot_drone_3_10_drone_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'byrobot_drone_3_10_drone_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n        },\n\n        byrobot_drone_3_10_controller_buzzer_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class       : 'buzzer',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setBuzzerStop(script, 0x20);\n            },\n        },\n\n        byrobot_drone_3_10_controller_buzzer_scale: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_drone_3_10_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, 60000, false, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, 60000, false, true);\n                }\n            },\n        },\n\n        byrobot_drone_3_10_controller_buzzer_scale_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, true, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, true, true);\n                }\n            },\n        },\n\n        byrobot_drone_3_10_controller_buzzer_scale_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, false, false);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, false, false);\n                }\n            },\n        },\n\n        byrobot_drone_3_10_controller_buzzer_hz: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1000'] }, null],\n                type  : 'byrobot_drone_3_10_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const hz = script.getNumberValue('HZ');\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, 60000, false, true);\n            },\n        },\n\n        byrobot_drone_3_10_controller_buzzer_hz_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1000'] }, { type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_3_10_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ  : 0,\n                TIME: 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, true, true);\n            },\n        },\n\n        byrobot_drone_3_10_controller_buzzer_hz_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['1000'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ  : 0,\n                TIME: 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, false, false);\n            },\n        },\n\n        byrobot_drone_3_10_controller_vibrator_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class       : 'vibrator',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setVibratorStop(script, 0x20);\n            },\n        },\n\n        byrobot_drone_3_10_controller_vibrator_on_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_3_10_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, true, true);\n            },\n        },\n\n        byrobot_drone_3_10_controller_vibrator_on_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_3_10_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, false, false);\n            },\n        },\n\n        byrobot_drone_3_10_controller_vibrator_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, true, true);\n            },\n        },\n\n        byrobot_drone_3_10_controller_vibrator_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, false, false);\n            },\n        },\n\n\n        byrobot_drone_3_10_drone_motor_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'motor',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n        },\n\n        byrobot_drone_3_10_drone_motorsingle: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type      : 'Dropdown',\n                    options   : [['1(FR)', '0'], ['2(RR)', '1'], ['3(RL)', '2'], ['4(FL)', '3']],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'text', params: ['120'] }, null],\n                type  : 'byrobot_drone_3_10_drone_motorsingle',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const motorIndex = parseInt(script.getField('MOTORINDEX'), 10);\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.byrobot_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n        },\n\n        byrobot_drone_3_10_drone_motorsingle_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, { type: 'text', params: ['120'] }, null],\n                type  : 'byrobot_drone_3_10_drone_motorsingle_input',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const motorIndex = script.getNumberValue('MOTORINDEX') - 1;\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.byrobot_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n        },\n\n        byrobot_drone_3_10_drone_battle_ir_message: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['123'] }, null],\n                type  : 'byrobot_drone_3_10_drone_battle_ir_message',\n            },\n            paramsKeyMap: {\n                IRMESSAGE: 0,\n            },\n            class   : 'ir',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const irmessage = script.getNumberValue('IRMESSAGE');\n\n                return Entry.byrobot_base.setIrMessage(script, 0x10, irmessage);\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_drone_takeoff: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_control_drone_takeoff',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x11, 5000); // 0x11 : FlightEvent::TakeOff\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_drone_landing: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_control_drone_landing',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x12, 5000); // 0x12 : FlightEvent::Landing\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_drone_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_control_drone_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_headless: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_headless_headless, '1'],\n                        [Lang.Blocks.drone_headless_normal,   '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_3_10_drone_control_headless',\n            },\n            paramsKeyMap: {\n                HEADLESS: 0,\n            },\n            class   : 'control_flight',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const headless = script.getField('HEADLESS');\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x03, headless);\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_drone_reset_heading: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_3_10_drone_control_drone_reset_heading',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x07, 0xA0); // 0x22 : CommandType::FlightEvent  // 0xA0 : FlightEvent::ResetHeading\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_quad_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['0'] }, null],\n                type  : 'byrobot_drone_3_10_drone_control_quad_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, 0, false);\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_quad_one_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['100'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_drone_control_quad_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n                TIME         : 2,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n                const time          = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, time, true);\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_quad: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_drone_control_quad',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, 0, false);\n            },\n        },\n\n        byrobot_drone_3_10_drone_control_quad_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_3_10_drone_control_quad_delay',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n                TIME    : 4,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_3_10'],\n            func(sprite, script)\n            {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n                const time     = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, time, true);\n            },\n        },\n\n    };\n};\n\n\nmodule.exports = Entry.byrobot_drone_3_10;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_drone_4.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_drone_4 = \n{\n    id       : 'F.8',\n    name     : 'byrobot_drone_4',\n    url      : 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_drone_4.png',\n    title    : {\n        en: 'BYROBOT E-DRONE',\n        ko: '바이로봇 E-DRONE',\n    },\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero()\n    {\n        // 초기화\n        Entry.byrobot_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            if( Entry.hw.portData['state_modeFlight'] == 0x10 )\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x01, 0); // 드론, command = 0x01 (Stop)\n            }\n            else\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x07, 0x12); // 0x12 : FlightEvent::Landing\n            }\n            Entry.byrobot_base.transferBuzzer(0x20, 0, 0, 0);\n            Entry.byrobot_base.transferVibrator(0x20, 0, 0, 0, 0);\n            Entry.byrobot_base.transferLightManual(0x10, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightManual(0x20, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightModeColor(0x10, 0x22, 200, 255, 0, 0); // LED 초기화(드론)\n            Entry.byrobot_base.transferLightModeColor(0x20, 0x22, 200, 255, 0, 0); // LED 초기화(조종기)\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.byrobot_drone_4.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                // 정보창\n                monitor_state_modeFlight                        : '비행 모드',\n                monitor_state_modeControlFlight                 : '비행 제어기 모드',\n                monitor_state_modeMovement                      : '이동 상태',\n                monitor_state_headless                          : '헤드리스',\n                monitor_state_controlSpeed                      : '제어 속도',\n                monitor_state_sensorOrientation                 : '센서 방향',\n                monitor_state_battery                           : '배터리',\n                monitor_motion_accelX                           : '가속도 X',\n                monitor_motion_accelY                           : '가속도 Y',\n                monitor_motion_accelZ                           : '가속도 Z',\n                monitor_motion_gyroRoll                         : '자이로 Roll',\n                monitor_motion_gyroPitch                        : '자이로 Pitch',\n                monitor_motion_gyroYaw                          : '자이로 Yaw',\n                monitor_motion_angleRoll                        : '자세 Roll',\n                monitor_motion_anglePitch                       : '자세 Pitch',\n                monitor_motion_angleYaw                         : '자세 Yaw',\n                monitor_informationAssembledForEntry_positionX  : '위치 X',\n                monitor_informationAssembledForEntry_positionY  : '위치 Y',\n                monitor_informationAssembledForEntry_positionZ  : '위치 Z',\n                monitor_informationAssembledForEntry_altitude   : '고도',\n                monitor_informationAssembledForEntry_rangeHeight: '거리 센서의 높이',\n                monitor_joystick_left_x                         : '왼쪽 조이스틱 X',\n                monitor_joystick_left_y                         : '왼쪽 조이스틱 Y',\n                monitor_joystick_left_direction                 : '왼쪽 조이스틱 방향',\n                monitor_joystick_left_event                     : '왼쪽 조이스틱 이벤트',\n                monitor_joystick_right_x                        : '오른쪽 조이스틱 X',\n                monitor_joystick_right_y                        : '오른쪽 조이스틱 Y',\n                monitor_joystick_right_direction                : '오른쪽 조이스틱 방향',\n                monitor_joystick_right_event                    : '오른쪽 조이스틱 이벤트',\n                monitor_button_button                           : '버튼',\n                monitor_button_event                            : '버튼 이벤트',\n                monitor_entryhw_countTransferReserved           : '전송 예정 데이터',\n\n                // 일반 블럭\n                common_light_color_red                  : '빨강',\n                common_light_color_yellow               : '노랑',\n                common_light_color_green                : '초록',\n                common_light_color_cyan                 : '하늘색',\n                common_light_color_blue                 : '파랑',\n                common_light_color_magenta              : '자홍',\n                common_light_color_white                : '흰색',\n                common_light_color_black                : '검정',\n                common_light_color_cottoncandy          : '구름솜사탕',\n                common_light_color_emerald              : '에메랄드',\n                common_light_color_lavender             : '라벤더',\n                common_light_color_muscat               : '청포도',\n                common_light_color_strawberrymilk       : '딸기우유',\n                common_light_color_sunset               : '저녁노을',\n                common_light_mode_hold                  : '켜짐',\n                common_light_mode_flicker               : '깜빡임',\n                common_light_mode_flicker_double        : '2번 연속 깜빡임',\n                common_light_mode_dimming               : '천천히 깜빡임',\n                common_light_mode_sunrise               : '점점 밝아짐',\n                common_light_mode_sunset                : '점점 어두워짐',\n                common_light_mode_rainbow               : '무지개',\n                common_light_mode_rainbow2              : '무지개2',\n                common_light_brightness_all             : '전체',\n                common_light_brightness_b100            : '밝기 100%',\n                common_light_brightness_b25             : '밝기 25%',\n                common_light_brightness_b50             : '밝기 50%',\n                common_light_brightness_b75             : '밝기 75%',\n                common_light_brightness_off             : '끄기',\n                common_light_brightness_on              : '켜기',\n                common_left                             : '왼쪽',\n                common_right                            : '오른쪽',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                common_drone                            : '드론',\n                common_controller                       : '조종기',\n                controller_button                       : '버튼',\n                controller_button_event                 : '버튼 이벤트',\n                controller_button_front_left_top        : '전면 왼쪽 상단 버튼',\n                controller_button_front_left_bottom     : '전면 왼쪽 하단 버튼',\n                controller_button_front_right_top       : '전면 오른쪽 상단 버튼',\n                controller_button_front_right_bottom    : '전면 오른쪽 하단 버튼',\n                controller_button_top_left              : '상단 왼쪽 버튼',\n                controller_button_top_right             : '상단 오른쪽 버튼',\n                controller_button_center_up             : '중앙 위 버튼',\n                controller_button_center_left           : '중앙 왼쪽 버튼',\n                controller_button_center_right          : '중앙 오른쪽 버튼',\n                controller_button_center_down           : '중앙 아래쪽 버튼',\n                controller_button_bottom_left           : '하단 왼쪽 버튼',\n                controller_button_bottom_right          : '하단 오른쪽 버튼',\n                controller_buzzer                       : '버저',\n                controller_buzzer_a                     : '라',\n                controller_buzzer_as                    : '라#',\n                controller_buzzer_b                     : '시',\n                controller_buzzer_c                     : '도',\n                controller_buzzer_cs                    : '도#',\n                controller_buzzer_d                     : '레',\n                controller_buzzer_ds                    : '레#',\n                controller_buzzer_e                     : '미',\n                controller_buzzer_f                     : '파',\n                controller_buzzer_fs                    : '파#',\n                controller_buzzer_g                     : '솔',\n                controller_buzzer_gs                    : '솔#',\n                controller_buzzer_mute                  : '쉼',\n                controller_display_align_center         : '가운데',\n                controller_display_align_left           : '왼쪽',\n                controller_display_align_right          : '오른쪽',\n                controller_display_flagfill_off         : '채우지 않음',\n                controller_display_flagfill_on          : '채움',\n                controller_display_font_10x16           : '큼',\n                controller_display_font_5x8             : '작음',\n                controller_display_line_dashed          : '파선',\n                controller_display_line_dotted          : '점선',\n                controller_display_line_solid           : '실선',\n                controller_display_pixel_black          : '검은색',\n                controller_display_pixel_white          : '흰색',\n                controller_display_pixel_inverse        : '반전',\n                controller_joystick_direction_left_up   : '왼쪽 위',\n                controller_joystick_direction_up        : '위',\n                controller_joystick_direction_right_up  : '오른쪽 위',\n                controller_joystick_direction_left      : '왼쪽',\n                controller_joystick_direction_center    : '중앙',\n                controller_joystick_direction_right     : '오른쪽',\n                controller_joystick_direction_left_down : '왼쪽 아래',\n                controller_joystick_direction_down      : '아래',\n                controller_joystick_direction_right_down: '오른쪽 아래',\n                controller_joystick_left_direction      : '왼쪽 조이스틱 방향',\n                controller_joystick_left_event          : '왼쪽 조이스틱 이벤트',\n                controller_joystick_left_x              : '왼쪽 조이스틱 가로축',\n                controller_joystick_left_y              : '왼쪽 조이스틱 세로축',\n                controller_joystick_right_direction     : '오른쪽 조이스틱 방향',\n                controller_joystick_right_event         : '오른쪽 조이스틱 이벤트',\n                controller_joystick_right_x             : '오른쪽 조이스틱 가로축',\n                controller_joystick_right_y             : '오른쪽 조이스틱 세로축',\n                drone_accel_x                           : '가속도 x',\n                drone_accel_y                           : '가속도 y',\n                drone_accel_z                           : '가속도 z',\n                drone_gyro_pitch                        : '각속도 Pitch',\n                drone_gyro_roll                         : '각속도 Roll',\n                drone_gyro_yaw                          : '각속도 Yaw',\n                drone_attitude_pitch                    : '자세 Pitch',\n                drone_attitude_roll                     : '자세 Roll',\n                drone_attitude_yaw                      : '자세 Yaw',\n                drone_positionX                         : '위치 X',\n                drone_positionY                         : '위치 Y',\n                drone_positionZ                         : '위치 Z',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : '뒤',\n                drone_control_quad_pitch_forward        : '앞',\n                drone_control_quad_roll_left            : '왼쪽',\n                drone_control_quad_roll_right           : '오른쪽',\n                drone_control_quad_throttle_down        : '아래',\n                drone_control_quad_throttle_up          : '위',\n                drone_control_quad_yaw_ccw              : '반시계 방향',\n                drone_control_quad_yaw_cw               : '시계 방향',\n                drone_headless_normal                   : 'off (숙련자용)',\n                drone_headless_headless                 : 'on (초보자용)',\n                drone_light_color_body                  : '몸체',\n                drone_light_manual_body_blue            : '파랑',\n                drone_light_manual_body_green           : '초록',\n                drone_light_manual_body_red             : '빨강',\n                drone_motor_rotation_clockwise          : '시계 방향',\n                drone_motor_rotation_counterclockwise   : '반시계 방향',\n                drone_altitude                          : '해발고도',\n                drone_range_height                      : '바닥과의 거리',\n                drone_state_mode_system                 : '시스템 모드',\n                drone_state_mode_flight                 : '비행 동작 상태',\n                drone_state_mode_control_flight         : '비행 제어 모드',\n                drone_state_mode_movement               : '이동 상태',\n                drone_state_headless                    : 'Headless',\n                drone_state_control_speed               : '제어 속도',\n                drone_state_sensor_orientation          : '센서 방향',\n                drone_state_battery                     : '배터리',\n                entryhw_count_transfer_reserved         : '전송 예약된 데이터 수',\n            },\n\n            template: {\n                byrobot_drone_4_controller_buzzer_hz                : '%1Hz 소리를 연주 %2',\n                byrobot_drone_4_controller_buzzer_hz_delay          : '%1Hz 소리를 %2초 연주 %3',\n                byrobot_drone_4_controller_buzzer_hz_reserve        : '%1Hz 소리를 %2초 예약 %3',\n                byrobot_drone_4_controller_buzzer_off               : '버저 끄기 %1',\n                byrobot_drone_4_controller_buzzer_scale             : '%1 옥타브 %2을(를) 연주 %3',\n                byrobot_drone_4_controller_buzzer_scale_delay       : '%1 옥타브 %2을(를) %3초 연주 %4',\n                byrobot_drone_4_controller_buzzer_scale_reserve     : '%1 옥타브 %2을(를) %3초 예약 %4',\n                byrobot_drone_4_controller_display_clear            : '지우기 x %1, y %2, 너비 %3, 높이 %4 %5 %6',\n                byrobot_drone_4_controller_display_clear_all        : '화면 전체 지우기%1 %2',\n                byrobot_drone_4_controller_display_draw_circle      : '원 x %1, y %2, 반지름 %3 %4 %5 %6',\n                byrobot_drone_4_controller_display_draw_line        : '선 x1 %1, y1 %2, x2 %3, y2 %4 %5 %6 %7',\n                byrobot_drone_4_controller_display_draw_point       : '점 그리기 x %1, y %2 %3 %4',\n                byrobot_drone_4_controller_display_draw_rect        : '사각형 x %1, y %2, 너비 %3, 높이 %4 %5 %6 %7 %8',\n                byrobot_drone_4_controller_display_draw_string      : '문자열 x %1, y %2 %3 %4 입력 %5 %6',\n                byrobot_drone_4_controller_display_draw_string_align: '문자열 정렬 x1 %1, x2 %2, y %3 %4 %5 %6 입력 %7 %8',\n                byrobot_drone_4_controller_if_button_press          : '조종기 %1 눌렀을 때',\n                byrobot_drone_4_controller_if_joystick_direction    : '조종기 %1 조이스틱 %2 (으)로 움직였을 때',\n                byrobot_drone_4_controller_light_color_input        : '조종기 LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_4_controller_light_color_select       : '조종기 LED %1 %2 %3 %4',\n                byrobot_drone_4_controller_light_color_preset       : '조종기 LED %1 %2 %3',\n                byrobot_drone_4_controller_light_manual_single_input: '조종기 LED %1 밝기 %2 %3',\n                byrobot_drone_4_controller_light_manual_single_off  : '조종기 LED 끄기 %1',\n                byrobot_drone_4_controller_value_button             : '%1',\n                byrobot_drone_4_controller_value_joystick           : '%1',\n                byrobot_drone_4_controller_vibrator_delay           : '진동 %1초 켜기, %2초 끄기를 %3초 실행 %4',\n                byrobot_drone_4_controller_vibrator_off             : '진동 끄기 %1',\n                byrobot_drone_4_controller_vibrator_on_delay        : '진동 %1초 켜기 %2',\n                byrobot_drone_4_controller_vibrator_on_reserve      : '진동 %1초 예약 %2',\n                byrobot_drone_4_controller_vibrator_reserve         : '진동 %1초 켜기, %2초 끄기를 %3초 예약 %4',\n                byrobot_drone_4_drone_control_headless              : 'Headless mode %1 %2',\n                byrobot_drone_4_drone_control_drone_landing         : '드론 착륙 %1',\n                byrobot_drone_4_drone_control_drone_reset_heading   : '드론 방향 초기화 %1',\n                byrobot_drone_4_drone_control_drone_stop            : '드론 정지 %1',\n                byrobot_drone_4_drone_control_drone_takeoff         : '드론 이륙 %1',\n                byrobot_drone_4_drone_control_quad_one              : '드론 %1 %2% 정하기 %3',\n                byrobot_drone_4_drone_control_quad_one_delay        : '드론 %1 %2% %3 초 실행 %4',\n                byrobot_drone_4_drone_control_quad                  : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% 정하기 %5',\n                byrobot_drone_4_drone_control_quad_delay            : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5초 실행 %6',\n                byrobot_drone_4_drone_control_position_one          : '드론 %1(으)로 %2m를 %3m/s로 이동 %4',\n                byrobot_drone_4_drone_control_position_turn         : '드론 %1(으)로 %2도를 %3deg/s로 회전 %4',\n                byrobot_drone_4_drone_control_position_location     : '드론 %1 %2m, %3 %4m, %5 %6m를 %7m/s로 이동 %8',\n                byrobot_drone_4_drone_control_position_location_turn: '드론 %1 %2m, %3 %4m, %5 %6m를 %7m/s로 이동, %8 %9도를 %10deg/s로 회전 %11',\n                byrobot_drone_4_drone_light_color_input             : '드론 LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_4_drone_light_color_select            : '드론 LED %1 %2 %3 %4',\n                byrobot_drone_4_drone_light_color_preset            : '드론 LED %1 %2 %3',\n                byrobot_drone_4_drone_light_manual_single_input     : '드론 LED %1 밝기 %2 %3',\n                byrobot_drone_4_drone_light_manual_single_off       : '드론 LED 끄기 %1',\n                byrobot_drone_4_drone_motor_stop                    : '드론 모터 정지 %1',\n                byrobot_drone_4_drone_motorsingle                   : '드론 %1번 모터를 %2(으)로 회전 %3',\n                byrobot_drone_4_drone_motorsingle_input             : '드론 %1번 모터를 %2(으)로 회전 %3',\n                byrobot_drone_4_drone_value_attitude                : '%1',\n                byrobot_drone_4_drone_value_motion                  : '%1',\n                byrobot_drone_4_drone_value_position                : '%1',\n                byrobot_drone_4_drone_value_sensor                  : '%1',\n                byrobot_drone_4_drone_value_etc                     : '%1',\n            },\n\n            Helper: {\n                byrobot_drone_4_controller_buzzer_hz                : \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                byrobot_drone_4_controller_buzzer_hz_delay          : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                byrobot_drone_4_controller_buzzer_hz_reserve        : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                byrobot_drone_4_controller_buzzer_off               : \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                byrobot_drone_4_controller_buzzer_scale             : \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                byrobot_drone_4_controller_buzzer_scale_delay       : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                byrobot_drone_4_controller_buzzer_scale_reserve     : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                byrobot_drone_4_controller_display_clear            : \"<br>조종기 OLED 화면의 선택한 영역을 지웁니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_4_controller_display_clear_all        : \"<br>조종기 OLED 화면 전체를 지웁니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_4_controller_display_draw_circle      : \"<br>조종기 OLED 화면에서 지정한 위치에 원을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 반지름을 지정합니다. 원의 중심 = (x, y),<br>반지름은 원의 크기를 결정합니다.<br><br>★☆사용 가능한 값의 범위는 x값은 (-50~178), y값은 (-50~114), 반지름은 (1~200)입니다.☆★<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_4_controller_display_draw_line        : \"<br>조종기 OLED 화면에서 지정한 위치에 선을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>시작점 = (x1, y1), 끝나는점 = (x2, y2)<br>선 그리기는 시작점과 끝나는점을 이어주는 기능입니다.<br>사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_4_controller_display_draw_point       : \"<br>조종기 OLED 화면에서 지정한 위치에 점을 찍습니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다. x, y 좌표값으로 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_4_controller_display_draw_rect        : \"<br>조종기 OLED 화면에서 지정한 위치에 사각형을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 너비, 높이를 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_4_controller_display_draw_string      : \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 씁니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 글자 크기, 색을 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값은 (0~120), y값과 높이는 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_4_controller_display_draw_string_align: \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 정렬하여 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 정렬 방향, 글자 크기, 색을 지정합니다. 시작점 = (x1, y), 끝나는점 = (x2, y), 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_4_controller_if_button_press          : \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                byrobot_drone_4_controller_if_joystick_direction    : \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                byrobot_drone_4_controller_light_color_input        : \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 조종기 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_4_controller_light_color_select       : \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 조종기 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_4_controller_light_color_preset       : \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_4_controller_light_manual_single_input: \"<br>조종기 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255) 또는 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_4_controller_light_manual_single_off  : \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                byrobot_drone_4_controller_value_button             : \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                byrobot_drone_4_controller_value_joystick           : \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                byrobot_drone_4_controller_vibrator_delay           : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                byrobot_drone_4_controller_vibrator_off             : \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                byrobot_drone_4_controller_vibrator_on_delay        : \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                byrobot_drone_4_controller_vibrator_on_reserve      : \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                byrobot_drone_4_controller_vibrator_reserve         : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                byrobot_drone_4_drone_control_headless              : \"<br>드론 좌표 기준을 변경합니다. Headless mode 선택을 on으로 하면 이륙 시와 '방향초기화'를 했을 때 드론이 바라보는 방향을 기준으로 앞뒤좌우가 고정됩니다. 이 때에는 Yaw를 조작하여 드론이 다른 방향을 보게 하여도 처음 지정한 방향을 기준으로 앞뒤좌우로 움직입니다. 사용자가 바라보는 방향과 드론의 기준 방향이 같을 때 조작하기 편리한 장점이 있습니다.<br>Headless mode를 off로 선택하면 현재 드론이 바라보는 방향을 기준으로 앞뒤좌우가 결정됩니다. 드론의 움직임에 따라 앞뒤좌우가 계속 바뀌기 때문에 익숙해지기 전까지는 사용하기 어려울 수 있습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#좌표기준</font>\",\n                byrobot_drone_4_drone_control_drone_landing         : \"<br>드론을 착륙시킵니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#착륙</font>\",\n                byrobot_drone_4_drone_control_drone_reset_heading   : \"<br>드론의 방향을 초기화합니다. 앱솔루트 모드인 경우 현재 드론이 바라보는 방향을 0도로 변경합니다. 일반 모드에서는 아무런 영향이 없습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#방향초기화</font>\",\n                byrobot_drone_4_drone_control_drone_stop            : \"<br>드론 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#정지</font>\",\n                byrobot_drone_4_drone_control_drone_takeoff         : \"<br>드론을 이륙시킵니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이륙</font>\",\n                byrobot_drone_4_drone_control_quad                  : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                byrobot_drone_4_drone_control_quad_delay            : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_4_drone_control_quad_one              : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                byrobot_drone_4_drone_control_quad_one_delay        : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_4_drone_control_position_one          : \"<br>드론의 방향과 거리, 이동 속도를 지정하여 지정한 위치로 이동합니다. 거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_4_drone_control_position_turn         : \"<br>드론의 회전 방향과 각도, 회전 속도를 지정하여 지정한 각도로 회전합니다. 목표 각도를 회전 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#회전</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_4_drone_control_position_location     : \"<br>드론의 X, Y, Z 축의 방향과 거리, 이동 속도를 설정하여 지정한 위치로 이동합니다. 거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_4_drone_control_position_location_turn: \"<br>드론의 X, Y, Z 축의 방향과 거리, 이동 속도, 회전 방향과 목표 각도, 회전 속도를 설정하여 지정한 위치로의 이동과 회전을 실행합니다. 거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간 또는 목표 각도를 회전 속도로 나누어 얻은 시간에 1.2를 곱한 시간 중에 긴 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_4_drone_light_color_input             : \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 드론의 눈 또는 팔 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_4_drone_light_color_select            : \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 드론 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_4_drone_light_color_preset            : \"<br>드론의 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_4_drone_light_manual_single_input     : \"<br>드론 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255) 또는 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_4_drone_light_manual_single_off       : \"<br>드론의 모든 LED를 끕니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED끄기</font>\",\n                byrobot_drone_4_drone_motor_stop                    : \"<br>모든 모터의 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터정지</font>\",\n                byrobot_drone_4_drone_motorsingle                   : \"<br>모터 제어 블럭입니다.<br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                byrobot_drone_4_drone_motorsingle_input             : \"<br>모터 제어 블럭입니다.<br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                byrobot_drone_4_drone_value_attitude                : \"<br>드론의 현재 자세를 각도로 반환합니다. Roll은 좌우 기울기(-90 ~ 90), Pitch는 앞뒤 기울기(-90 ~ 90), Yaw는 회전 각도(-180 ~ 180) 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#자세</font>\",\n                byrobot_drone_4_drone_value_etc                     : \"<br>드론 설정과 관련된 값들과 적외선 통신으로 받은 값을 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#기타</font>\",\n                byrobot_drone_4_drone_value_motion                  : \"<br>드론 IMU센서와 관련된 값들을 반환합니다.<br>(병진운동) 가속도는 x, y, z축에 대한 중력가속도입니다. 1g = 9.8m/s^2<br>(회전운동) 각속도는 x, y, z축을 기준으로 회전하는 속력을 나타내는 벡터입니다.(pitch, roll, yaw) <br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#IMU센서</font> <font color='crimson'>#가속도</font> <font color='dodgerblue'>#병진운동</font> <font color='crimson'>#각속도</font> <font color='dodgerblue'>#회전운동</font>\",\n                byrobot_drone_4_drone_value_position                : \"<br>드론 위치와 관련된 값들을 반환합니다.(단위:m)<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#위치</font>\",\n                byrobot_drone_4_drone_value_sensor                  : \"<br>드론 거리 및 고도 센서와 관련된 값들을 반환합니다(단위:m)<br>거리 센서의 유효 측정 거리는 2m입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#센서</font> <font color='crimson'>#거리센서</font> <font color='dodgerblue'>#대기압</font>\",\n            },\n        },\n\n        en: {\n            Blocks: {\n                // 정보창\n                monitor_state_modeFlight                        : 'Flight Mode',\n                monitor_state_modeControlFlight                 : 'Control Flight Mode',\n                monitor_state_modeMovement                      : 'Movement Mode',\n                monitor_state_headless                          : 'Headless',\n                monitor_state_controlSpeed                      : 'Control Speed',\n                monitor_state_sensorOrientation                 : 'Sensor Orientation',\n                monitor_state_battery                           : 'Battery',\n                monitor_motion_accelX                           : 'Accel X',\n                monitor_motion_accelY                           : 'Accel Y',\n                monitor_motion_accelZ                           : 'Accel Z',\n                monitor_motion_gyroRoll                         : 'Gyro Roll',\n                monitor_motion_gyroPitch                        : 'Gyro Pitch',\n                monitor_motion_gyroYaw                          : 'Gyro Yaw',\n                monitor_motion_angleRoll                        : 'Roll',\n                monitor_motion_anglePitch                       : 'Pitch',\n                monitor_motion_angleYaw                         : 'Yaw',\n                monitor_informationAssembledForEntry_positionX  : 'Position X',\n                monitor_informationAssembledForEntry_positionY  : 'Position Y',\n                monitor_informationAssembledForEntry_positionZ  : 'Position Z',\n                monitor_informationAssembledForEntry_altitude   : 'Altitude',\n                monitor_informationAssembledForEntry_rangeHeight: 'Height',\n                monitor_joystick_left_x                         : 'Left Joystick X',\n                monitor_joystick_left_y                         : 'Left Joystick Y',\n                monitor_joystick_left_direction                 : 'Left Joystick Direction',\n                monitor_joystick_left_event                     : 'Left Joystick Event',\n                monitor_joystick_right_x                        : 'Right Joystick X',\n                monitor_joystick_right_y                        : 'Right Joystick Y',\n                monitor_joystick_right_direction                : 'Right Joystick Direction',\n                monitor_joystick_right_event                    : 'Right Joystick Event',\n                monitor_button_button                           : 'Button',\n                monitor_button_event                            : 'Button Event',\n                monitor_entryhw_countTransferReserved           : 'Transfer Buffer',\n\n                // 일반 블럭\n                common_light_color_red                  : 'red',\n                common_light_color_yellow               : 'yellow',\n                common_light_color_green                : 'green',\n                common_light_color_cyan                 : 'cyan',\n                common_light_color_blue                 : 'blue',\n                common_light_color_magenta              : 'magenta',\n                common_light_color_white                : 'white',\n                common_light_color_cottoncandy          : 'cotton candy',\n                common_light_color_emerald              : 'emerald',\n                common_light_color_lavender             : 'lavender',\n                common_light_color_muscat               : 'muscat',\n                common_light_color_strawberrymilk       : 'strawberry milk',\n                common_light_color_sunset               : 'sunset',\n                common_light_mode_hold                  : 'hold',\n                common_light_mode_flicker               : 'flicker',\n                common_light_mode_flicker_double        : 'flicker double',\n                common_light_mode_dimming               : 'dimming',\n                common_light_mode_sunrise               : 'sunrise',\n                common_light_mode_sunset                : 'sunset',\n                common_light_mode_rainbow               : 'rainbow',\n                common_light_mode_rainbow2              : 'rainbow2',\n                common_light_brightness_all             : 'all',\n                common_light_brightness_b100            : 'brightness 100%',\n                common_light_brightness_b25             : 'brightness 25%',\n                common_light_brightness_b50             : 'brightness 50%',\n                common_light_brightness_b75             : 'brightness 75%',\n                common_light_brightness_off             : 'off',\n                common_light_brightness_on              : 'on',\n                common_left                             : 'left',\n                common_right                            : 'right',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                common_drone                            : 'drone',\n                common_controller                       : 'controller',\n                controller_button                       : 'button',\n                controller_button_event                 : 'button event',\n                controller_button_front_left_top        : 'Front left top button',\n                controller_button_front_left_bottom     : 'Front left bottom button',\n                controller_button_front_right_top       : 'Front right top button',\n                controller_button_front_right_bottom    : 'Front right bottom button',\n                controller_button_top_left              : 'Top left button',\n                controller_button_top_right             : 'Top right button',\n                controller_button_center_up             : 'Trim up button',\n                controller_button_center_left           : 'Trim left button',\n                controller_button_center_right          : 'Trim right button',\n                controller_button_center_down           : 'Trim down button',\n                controller_button_bottom_left           : 'Bottom left button',\n                controller_button_bottom_right          : 'Bottom right button',\n                controller_buzzer                       : 'buzzer',\n                controller_buzzer_a                     : 'A',\n                controller_buzzer_as                    : 'A#',\n                controller_buzzer_b                     : 'B',\n                controller_buzzer_c                     : 'C',\n                controller_buzzer_cs                    : 'C#',\n                controller_buzzer_d                     : 'D',\n                controller_buzzer_ds                    : 'D#',\n                controller_buzzer_e                     : 'E',\n                controller_buzzer_f                     : 'F',\n                controller_buzzer_fs                    : 'F#',\n                controller_buzzer_g                     : 'G',\n                controller_buzzer_gs                    : 'G#',\n                controller_buzzer_mute                  : 'mute',\n                controller_display_align_center         : 'center',\n                controller_display_align_left           : 'left',\n                controller_display_align_right          : 'right',\n                controller_display_flagfill_off         : 'not fill',\n                controller_display_flagfill_on          : 'fill',\n                controller_display_font_10x16           : 'big',\n                controller_display_font_5x8             : 'small',\n                controller_display_line_dashed          : 'dashed',\n                controller_display_line_dotted          : 'dotted',\n                controller_display_line_solid           : 'solid',\n                controller_display_pixel_black          : 'black',\n                controller_display_pixel_white          : 'white',\n                controller_display_pixel_inverse        : 'inverse',\n                controller_joystick_direction_left_up   : 'Left top',\n                controller_joystick_direction_up        : 'Top',\n                controller_joystick_direction_right_up  : 'Right top',\n                controller_joystick_direction_left      : 'Left',\n                controller_joystick_direction_center    : 'Center',\n                controller_joystick_direction_right     : 'Right',\n                controller_joystick_direction_left_down : 'Left Bottom',\n                controller_joystick_direction_down      : 'Bottom',\n                controller_joystick_direction_right_down: 'Right Bottom',\n                controller_joystick_left_direction      : 'left joystick direction',\n                controller_joystick_left_event          : 'left joystick event',\n                controller_joystick_left_x              : 'left joystick X',\n                controller_joystick_left_y              : 'left joystick Y',\n                controller_joystick_right_direction     : 'right joystick direction',\n                controller_joystick_right_event         : 'right joystick event',\n                controller_joystick_right_x             : 'right joystick X',\n                controller_joystick_right_y             : 'right joystick Y',\n                drone_accel_x                           : 'Accel x',\n                drone_accel_y                           : 'Accel y',\n                drone_accel_z                           : 'Accel z',\n                drone_gyro_pitch                        : 'Gyro Pitch',\n                drone_gyro_roll                         : 'Gyro Roll',\n                drone_gyro_yaw                          : 'Gyro Yaw',\n                drone_attitude_pitch                    : 'Attitude Pitch',\n                drone_attitude_roll                     : 'Attitude Roll',\n                drone_attitude_yaw                      : 'Attitude Yaw',\n                drone_positionX                         : 'Position X',\n                drone_positionY                         : 'Position Y',\n                drone_positionZ                         : 'Position Z',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : 'Backward',\n                drone_control_quad_pitch_forward        : 'Forward',\n                drone_control_quad_roll_left            : 'Left',\n                drone_control_quad_roll_right           : 'Right',\n                drone_control_quad_throttle_down        : 'Down',\n                drone_control_quad_throttle_up          : 'Up',\n                drone_control_quad_yaw_ccw              : 'Counterclockwise',\n                drone_control_quad_yaw_cw               : 'clockwise',\n                drone_headless_normal                   : 'Normal',\n                drone_headless_headless                 : 'Headless',\n                drone_light_color_body                  : 'Body',\n                drone_light_manual_body_blue            : 'Blue',\n                drone_light_manual_body_green           : 'Green',\n                drone_light_manual_body_red             : 'Red',\n                drone_motor_rotation_clockwise          : 'Clockwise',\n                drone_motor_rotation_counterclockwise   : 'Counterclockwise',\n                drone_altitude                          : 'Altitude',\n                drone_range_height                      : 'Height',\n                drone_state_mode_system                 : 'System Mode',\n                drone_state_mode_flight                 : 'Flight Mode',\n                drone_state_mode_control_flight         : 'Flight Control Mode',\n                drone_state_mode_movement               : 'mode movement',\n                drone_state_headless                    : 'Headless',\n                drone_state_control_speed               : 'Speed',\n                drone_state_sensor_orientation          : 'Sensor direction',\n                drone_state_battery                     : 'Battery',\n                entryhw_count_transfer_reserved         : 'Reserved data for transfer',\n            },\n\n            template: {\n                byrobot_drone_4_controller_buzzer_hz                : 'play %1 Hz sound %2',\n                byrobot_drone_4_controller_buzzer_hz_delay          : 'play %1 Hz sound for %2 second %3',\n                byrobot_drone_4_controller_buzzer_hz_reserve        : 'reserve to play %1 Hz for %2 second %3',\n                byrobot_drone_4_controller_buzzer_off               : 'turn off the buzzer %1',\n                byrobot_drone_4_controller_buzzer_scale             : 'play %1 octave %2 %3',\n                byrobot_drone_4_controller_buzzer_scale_delay       : 'play %1 octave %2 for %3 second %4',\n                byrobot_drone_4_controller_buzzer_scale_reserve     : 'reserve to play %1 octave %2 for %3 second %4',\n                byrobot_drone_4_controller_display_clear            : 'clear controller display x:%1, y:%2, width:%3, height:%4, color:%5 %6',\n                byrobot_drone_4_controller_display_clear_all        : 'clear controller display with %1 color %2',\n                byrobot_drone_4_controller_display_draw_circle      : 'draw a circle x:%1, y:%2, radius:%3, %4, %5, %6',\n                byrobot_drone_4_controller_display_draw_line        : 'draw a line x1:%1, y1:%2, x2:%3, y2:%4, %5, %6 %7',\n                byrobot_drone_4_controller_display_draw_point       : 'draw a point x:%1, y:%2, color:%3 %4',\n                byrobot_drone_4_controller_display_draw_rect        : 'draw a rectangle x:%1, y:%2, width:%3, height:%4, %5, %6, %7 %8',\n                byrobot_drone_4_controller_display_draw_string      : 'draw a string x:%1, y:%2, font size:%3, %4, input:%5, %6',\n                byrobot_drone_4_controller_display_draw_string_align: 'draw aligned string x1:%1, x2:%2, y:%3, align:%4, font size:%5, %6, input:%7, %8',\n                byrobot_drone_4_controller_if_button_press          : 'when press %1',\n                byrobot_drone_4_controller_if_joystick_direction    : 'when %1 stick move to %2',\n                byrobot_drone_4_controller_light_color_input        : 'Controller LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_4_controller_light_color_select       : 'Controller LED Preset %1 %2 %3 %4',\n                byrobot_drone_4_controller_light_color_preset       : 'Controller LED %1 %2 %3',\n                byrobot_drone_4_controller_light_manual_single_input: 'Controller LED %1 Lightness %2 %3',\n                byrobot_drone_4_controller_light_manual_single_off  : 'Controller LED Off %1',\n                byrobot_drone_4_controller_value_button             : '%1',\n                byrobot_drone_4_controller_value_joystick           : '%1',\n                byrobot_drone_4_controller_vibrator_off             : 'Vibrator Off %1',\n                byrobot_drone_4_controller_vibrator_delay           : 'Vibrator %1 sec On, %2 sec Off for %3 sec run %4',\n                byrobot_drone_4_controller_vibrator_on_delay        : 'Vibrator %1 sec on %2',\n                byrobot_drone_4_controller_vibrator_on_reserve      : 'Vibrator %1 sec reserve %2',\n                byrobot_drone_4_controller_vibrator_reserve         : 'Vibrator %1 sec On, %2 sec Off for %3 sec reserve %4',\n                byrobot_drone_4_drone_control_headless              : 'Headless mode %1 %2',\n                byrobot_drone_4_drone_control_drone_landing         : 'Landing %1',\n                byrobot_drone_4_drone_control_drone_reset_heading   : 'Reset heading %1',\n                byrobot_drone_4_drone_control_drone_stop            : 'Stop flight %1',\n                byrobot_drone_4_drone_control_drone_takeoff         : 'Takeoff %1',\n                byrobot_drone_4_drone_control_quad                  : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5',\n                byrobot_drone_4_drone_control_quad_delay            : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% for %5sec %6',\n                byrobot_drone_4_drone_control_quad_one              : 'Set %1 %2% %3',\n                byrobot_drone_4_drone_control_quad_one_delay        : 'Set %1 %2% %3 sec %4',\n                byrobot_drone_4_drone_control_position_one          : 'Move %2 meter(s) %1 to %3 m/s %4',\n                byrobot_drone_4_drone_control_position_turn         : 'Rotate %2 degree(s) %1 to %3 deg/s %4',\n                byrobot_drone_4_drone_control_position_location     : 'Move %2 meter(s) %1, %4 meter(s) %3, %6 meter(s) %5 to %7 m/s %8',\n                byrobot_drone_4_drone_control_position_location_turn: 'Move %2 meter(s) %1, %4 meter(s) %3, %6 meter(s) %5 to %7 m/s, Rotate %9 degree(s) %8 to %10 deg/s %11',\n                byrobot_drone_4_drone_light_manual_single_off       : 'Drone LED Off %1',\n                byrobot_drone_4_drone_light_manual_single_input     : 'Drone LED %1 lightness %2 %3',\n                byrobot_drone_4_drone_light_color_input             : 'Drone LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_4_drone_light_color_select            : 'Drone LED %1 %2 %3 %4',\n                byrobot_drone_4_drone_light_color_preset            : 'Drone LED %1 %2 %3',\n                byrobot_drone_4_drone_motor_stop                    : 'Motor stop %1',\n                byrobot_drone_4_drone_motorsingle                   : 'No. %1 Motor rotate for %2 %3',\n                byrobot_drone_4_drone_motorsingle_input             : 'No. %1 Motor rotate for %2 %3',\n                byrobot_drone_4_drone_value_attitude                : '%1',\n                byrobot_drone_4_drone_value_motion                  : '%1',\n                byrobot_drone_4_drone_value_position                : '%1',\n                byrobot_drone_4_drone_value_sensor                  : '%1',\n                byrobot_drone_4_drone_value_etc                     : '%1',\n            },\n\n            Helper: {\n                byrobot_drone_4_controller_buzzer_hz                : '',\n                byrobot_drone_4_controller_buzzer_hz_delay          : '',\n                byrobot_drone_4_controller_buzzer_hz_reserve        : '',\n                byrobot_drone_4_controller_buzzer_off               : '',\n                byrobot_drone_4_controller_buzzer_scale             : '',\n                byrobot_drone_4_controller_buzzer_scale_delay       : '',\n                byrobot_drone_4_controller_buzzer_scale_reserve     : '',\n                byrobot_drone_4_controller_display_clear            : '',\n                byrobot_drone_4_controller_display_clear_all        : '',\n                byrobot_drone_4_controller_display_draw_circle      : '',\n                byrobot_drone_4_controller_display_draw_line        : '',\n                byrobot_drone_4_controller_display_draw_point       : '',\n                byrobot_drone_4_controller_display_draw_rect        : '',\n                byrobot_drone_4_controller_display_draw_string      : '',\n                byrobot_drone_4_controller_display_draw_string_align: '',\n                byrobot_drone_4_controller_if_button_press          : '',\n                byrobot_drone_4_controller_if_joystick_direction    : '',\n                byrobot_drone_4_controller_light_color_input        : '',\n                byrobot_drone_4_controller_light_color_select       : '',\n                byrobot_drone_4_controller_light_color_preset       : '',\n                byrobot_drone_4_controller_light_manual_single_input: '',\n                byrobot_drone_4_controller_light_manual_single_off  : '',\n                byrobot_drone_4_controller_value_button             : '',\n                byrobot_drone_4_controller_value_joystick           : '',\n                byrobot_drone_4_controller_vibrator_delay           : '',\n                byrobot_drone_4_controller_vibrator_off             : '',\n                byrobot_drone_4_controller_vibrator_on_delay        : '',\n                byrobot_drone_4_controller_vibrator_on_reserve      : '',\n                byrobot_drone_4_controller_vibrator_reserve         : '',\n                byrobot_drone_4_drone_control_headless              : '',\n                byrobot_drone_4_drone_control_drone_landing         : '',\n                byrobot_drone_4_drone_control_drone_reset_heading   : '',\n                byrobot_drone_4_drone_control_drone_stop            : '',\n                byrobot_drone_4_drone_control_drone_takeoff         : '',\n                byrobot_drone_4_drone_control_quad                  : '',\n                byrobot_drone_4_drone_control_quad_delay            : '',\n                byrobot_drone_4_drone_control_quad_one              : '',\n                byrobot_drone_4_drone_control_quad_one_delay        : '',\n                byrobot_drone_4_drone_control_position_one          : '',\n                byrobot_drone_4_drone_control_position_turn         : '',\n                byrobot_drone_4_drone_control_position_location     : '',\n                byrobot_drone_4_drone_control_position_location_turn: '',\n                byrobot_drone_4_drone_light_color_input             : '',\n                byrobot_drone_4_drone_light_color_select            : '',\n                byrobot_drone_4_drone_light_color_preset            : '',\n                byrobot_drone_4_drone_light_manual_single_input     : '',\n                byrobot_drone_4_drone_light_manual_single_off       : '',\n                byrobot_drone_4_drone_motor_stop                    : '',\n                byrobot_drone_4_drone_motorsingle                   : '',\n                byrobot_drone_4_drone_motorsingle_input             : '',\n                byrobot_drone_4_drone_value_attitude                : '',\n                byrobot_drone_4_drone_value_etc                     : '',\n                byrobot_drone_4_drone_value_motion                  : '',\n                byrobot_drone_4_drone_value_position                : '',\n                byrobot_drone_4_drone_value_sensor                  : '',\n            },\n        },\n    };\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.byrobot_drone_4.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/byrobot_drone_4.png\",   // 배경 이미지\n        width  : 256,                        // 이미지의 폭\n        height : 256,                        // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeFlight                        : { name: Lang.Blocks.monitor_state_modeFlight,                           type: 'input', pos: { x: 0, y: 0 } },\n            state_modeControlFlight                 : { name: Lang.Blocks.monitor_state_modeControlFlight,                    type: 'input', pos: { x: 0, y: 0 } },\n            state_modeMovement                      : { name: Lang.Blocks.monitor_state_modeMovement,                         type: 'input', pos: { x: 0, y: 0 } },\n            state_headless                          : { name: Lang.Blocks.monitor_state_headless,                             type: 'input', pos: { x: 0, y: 0 } },\n            state_controlSpeed                      : { name: Lang.Blocks.monitor_state_controlSpeed,                         type: 'input', pos: { x: 0, y: 0 } },\n            state_sensorOrientation                 : { name: Lang.Blocks.monitor_state_sensorOrientation,                    type: 'input', pos: { x: 0, y: 0 } },\n            state_battery                           : { name: Lang.Blocks.monitor_state_battery,                              type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelX                           : { name: Lang.Blocks.monitor_motion_accelX,                              type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelY                           : { name: Lang.Blocks.monitor_motion_accelY,                              type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelZ                           : { name: Lang.Blocks.monitor_motion_accelZ,                              type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroRoll                         : { name: Lang.Blocks.monitor_motion_gyroRoll,                            type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroPitch                        : { name: Lang.Blocks.monitor_motion_gyroPitch,                           type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroYaw                          : { name: Lang.Blocks.monitor_motion_gyroYaw,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleRoll                        : { name: Lang.Blocks.monitor_motion_angleRoll,                           type: 'input', pos: { x: 0, y: 0 } },\n            motion_anglePitch                       : { name: Lang.Blocks.monitor_motion_anglePitch,                          type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleYaw                         : { name: Lang.Blocks.monitor_motion_angleYaw,                            type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionX  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionX,     type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionY  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionY,     type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionZ  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionZ,     type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_altitude   : { name: Lang.Blocks.monitor_informationAssembledForEntry_altitude,      type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_rangeHeight: { name: Lang.Blocks.monitor_informationAssembledForEntry_rangeHeight,   type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_x                         : { name: Lang.Blocks.monitor_joystick_left_x,                            type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_y                         : { name: Lang.Blocks.monitor_joystick_left_y,                            type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_direction                 : { name: Lang.Blocks.monitor_joystick_left_direction,                    type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_event                     : { name: Lang.Blocks.monitor_joystick_left_event,                        type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_x                        : { name: Lang.Blocks.monitor_joystick_right_x,                           type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_y                        : { name: Lang.Blocks.monitor_joystick_right_y,                           type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_direction                : { name: Lang.Blocks.monitor_joystick_right_direction,                   type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_event                    : { name: Lang.Blocks.monitor_joystick_right_event,                       type: 'input', pos: { x: 0, y: 0 } },\n            button_button                           : { name: Lang.Blocks.monitor_button_button,                              type: 'input', pos: { x: 0, y: 0 } },\n            button_event                            : { name: Lang.Blocks.monitor_button_event,                               type: 'input', pos: { x: 0, y: 0 } },\n            entryhw_countTransferReserved           : { name: Lang.Blocks.monitor_entryhw_countTransferReserved,              type: 'output', pos: { x: 0, y: 0 } },\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both',   // 표시 모드\n    };\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 블록명(다른 장치의 블록 이름과 달라야 함)\n ***************************************************************************************/\nEntry.byrobot_drone_4.blockMenuBlocks = [\n    'byrobot_drone_4_drone_value_attitude',\n    'byrobot_drone_4_drone_value_motion',\n    'byrobot_drone_4_drone_value_position',\n    'byrobot_drone_4_drone_value_sensor',\n    'byrobot_drone_4_drone_value_etc',\n    'byrobot_drone_4_controller_value_button',\n    'byrobot_drone_4_controller_value_joystick',\n    'byrobot_drone_4_controller_if_button_press',\n    'byrobot_drone_4_controller_if_joystick_direction',\n    'byrobot_drone_4_drone_control_drone_takeoff',\n    'byrobot_drone_4_drone_control_drone_landing',\n    'byrobot_drone_4_drone_control_drone_stop',\n    'byrobot_drone_4_drone_control_headless',\n    'byrobot_drone_4_drone_control_drone_reset_heading',\n    'byrobot_drone_4_drone_control_quad_one',\n    'byrobot_drone_4_drone_control_quad_one_delay',\n    'byrobot_drone_4_drone_control_quad',\n    'byrobot_drone_4_drone_control_quad_delay',\n    'byrobot_drone_4_drone_control_position_one',\n    'byrobot_drone_4_drone_control_position_turn',\n    'byrobot_drone_4_drone_control_position_location',\n    'byrobot_drone_4_drone_control_position_location_turn',\n    'byrobot_drone_4_drone_motor_stop',\n    'byrobot_drone_4_drone_motorsingle',\n    'byrobot_drone_4_drone_motorsingle_input',\n    'byrobot_drone_4_drone_light_manual_single_off',\n    'byrobot_drone_4_drone_light_manual_single_input',\n    'byrobot_drone_4_drone_light_color_preset',\n    'byrobot_drone_4_drone_light_color_input',\n    'byrobot_drone_4_drone_light_color_select',\n    'byrobot_drone_4_controller_light_manual_single_off',\n    'byrobot_drone_4_controller_light_manual_single_input',\n    'byrobot_drone_4_controller_light_color_preset',\n    'byrobot_drone_4_controller_light_color_input',\n    'byrobot_drone_4_controller_light_color_select',\n    'byrobot_drone_4_controller_display_clear_all',\n    'byrobot_drone_4_controller_display_clear',\n    'byrobot_drone_4_controller_display_draw_point',\n    'byrobot_drone_4_controller_display_draw_line',\n    'byrobot_drone_4_controller_display_draw_rect',\n    'byrobot_drone_4_controller_display_draw_circle',\n    'byrobot_drone_4_controller_display_draw_string',\n    'byrobot_drone_4_controller_display_draw_string_align',\n    'byrobot_drone_4_controller_buzzer_off',\n    'byrobot_drone_4_controller_buzzer_scale',\n    'byrobot_drone_4_controller_buzzer_scale_delay',\n    'byrobot_drone_4_controller_buzzer_scale_reserve',\n    'byrobot_drone_4_controller_buzzer_hz',\n    'byrobot_drone_4_controller_buzzer_hz_delay',\n    'byrobot_drone_4_controller_buzzer_hz_reserve',\n    'byrobot_drone_4_controller_vibrator_off',\n    'byrobot_drone_4_controller_vibrator_on_delay',\n    'byrobot_drone_4_controller_vibrator_on_reserve',\n    'byrobot_drone_4_controller_vibrator_delay',\n    'byrobot_drone_4_controller_vibrator_reserve',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 정의\n ***************************************************************************************/\nEntry.byrobot_drone_4.getBlocks = function()\n{\n    return {\n        byrobot_drone_4_drone_value_attitude: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_attitude_roll,   'motion_angleRoll'],\n                        [Lang.Blocks.drone_attitude_pitch,  'motion_anglePitch'],\n                        [Lang.Blocks.drone_attitude_yaw,    'motion_angleYaw'],\n                    ],\n                    value     : 'motion_angleRoll',                            // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_value_attitude',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_4_drone_value_motion: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_accel_x,     'motion_accelX'],\n                        [Lang.Blocks.drone_accel_y,     'motion_accelY'],\n                        [Lang.Blocks.drone_accel_z,     'motion_accelZ'],\n                        [Lang.Blocks.drone_gyro_roll,   'motion_gyroRoll'],\n                        [Lang.Blocks.drone_gyro_pitch,  'motion_gyroPitch'],\n                        [Lang.Blocks.drone_gyro_yaw,    'motion_gyroYaw'],\n                    ],\n                    value     : 'motion_accelX',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_value_motion',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_4_drone_value_position: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_positionX,       'informationAssembledForEntry_positionX'],\n                        [Lang.Blocks.drone_positionY,       'informationAssembledForEntry_positionY'],\n                        [Lang.Blocks.drone_positionZ,       'informationAssembledForEntry_positionZ'],\n                    ],\n                    value     : 'informationAssembledForEntry_positionX',      // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_value_position',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_4_drone_value_sensor: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_range_height,    'informationAssembledForEntry_rangeHeight'],\n                        [Lang.Blocks.drone_altitude,        'informationAssembledForEntry_altitude'],\n                    ],\n                    value     : 'informationAssembledForEntry_rangeHeight',    // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_value_sensor',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_4_drone_value_etc: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_state_mode_flight,           'state_modeFlight'],\n                        [Lang.Blocks.drone_state_mode_control_flight,   'state_modeControlFlight'],\n                        [Lang.Blocks.drone_state_mode_movement,         'state_modeMovement'],\n                        [Lang.Blocks.drone_state_headless,              'state_headless'],\n                        [Lang.Blocks.drone_state_control_speed,         'state_controlSpeed'],\n                        [Lang.Blocks.drone_state_sensor_orientation,    'state_sensorOrientation'],\n                        [Lang.Blocks.drone_state_battery,               'state_battery'],\n                    ],\n                    value     : 'state_battery',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_value_etc',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_4_controller_value_button: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button,         'button_button'],\n                        [Lang.Blocks.controller_button_event,   'button_event'],\n                    ],\n                    value     : 'button_button',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_4_controller_value_button',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_4_controller_value_joystick: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_left_x,            'joystick_left_x'],\n                        [Lang.Blocks.controller_joystick_left_y,            'joystick_left_y'],\n                        [Lang.Blocks.controller_joystick_left_direction,    'joystick_left_direction'],\n                        [Lang.Blocks.controller_joystick_left_event,        'joystick_left_event'],\n                        [Lang.Blocks.controller_joystick_right_x,           'joystick_right_x'],\n                        [Lang.Blocks.controller_joystick_right_y,           'joystick_right_y'],\n                        [Lang.Blocks.controller_joystick_right_direction,   'joystick_right_direction'],\n                        [Lang.Blocks.controller_joystick_right_event,       'joystick_right_event'],\n                    ],\n                    value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_4_controller_value_joystick',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        byrobot_drone_4_controller_if_button_press: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button_front_left_top,      '1'],\n                        [Lang.Blocks.controller_button_front_left_bottom,   '2'],\n                        [Lang.Blocks.controller_button_front_right_top,     '4'],\n                        [Lang.Blocks.controller_button_front_right_bottom,  '8'],\n                        [Lang.Blocks.controller_button_top_left,            '16'],\n                        [Lang.Blocks.controller_button_top_right,           '32'],\n                        [Lang.Blocks.controller_button_center_up,           '64'],\n                        [Lang.Blocks.controller_button_center_left,         '128'],\n                        [Lang.Blocks.controller_button_center_right,        '256'],\n                        [Lang.Blocks.controller_button_center_down,         '512'],\n                        [Lang.Blocks.controller_button_bottom_left,         '1024'],\n                        [Lang.Blocks.controller_button_bottom_right,        '2048'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_4_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const read        = Entry.hw.portData;\n                const button      = 'button_button';    // paramsKeyMap에 정의된 이름 사용\n                const buttonevent = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        byrobot_drone_4_controller_if_joystick_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.common_right, 'joystick_right_direction'],\n                    ],\n                    value     : 'joystick_left_direction',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_direction_left_up,     '17'],\n                        [Lang.Blocks.controller_joystick_direction_up,          '18'],\n                        [Lang.Blocks.controller_joystick_direction_right_up,    '20'],\n                        [Lang.Blocks.controller_joystick_direction_left,        '33'],\n                        [Lang.Blocks.controller_joystick_direction_center,      '34'],\n                        [Lang.Blocks.controller_joystick_direction_right,       '36'],\n                        [Lang.Blocks.controller_joystick_direction_left_down,   '65'],\n                        [Lang.Blocks.controller_joystick_direction_down,        '66'],\n                        [Lang.Blocks.controller_joystick_direction_right_down,  '68'],\n                    ],\n                    value     : '34',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_4_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE   : 0,\n                DIRECTION: 1,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const read   = Entry.hw.portData;\n                const device = script.getField('DEVICE');  // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION'))\n                {\n                    return true;\n                }\n                else\n                {\n                    return false;\n                }\n            },\n        },\n\n        byrobot_drone_4_controller_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'controller_light',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setLightManual(script, 0x20, 0xffff, 0);\n            },\n        },\n\n        byrobot_drone_4_controller_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_drone_4_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n        },\n\n        byrobot_drone_4_controller_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x07'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x20, flags, brightness);\n            },\n        },\n\n        byrobot_drone_4_controller_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval = script.getNumberValue('INTERVAL');\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                return Entry.byrobot_base.setLightModeColor(script, 0x20, mode, interval, red, green, blue);\n            },\n        },\n\n        byrobot_drone_4_controller_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'byrobot_drone_4_controller_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n        },\n\n        byrobot_drone_4_drone_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'drone_light',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setLightManual(script, 0x10, 0xff, 0);\n            },\n        },\n\n        byrobot_drone_4_drone_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_drone_4_drone_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n        },\n\n        byrobot_drone_4_drone_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x3F'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x10, flags, brightness);\n            },\n        },\n\n        byrobot_drone_4_drone_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_drone_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                const interval = script.getNumberValue('INTERVAL');\n                return Entry.byrobot_base.setLightModeColor(script, 0x10, mode, interval, red, green, blue);\n            },\n        },\n\n        byrobot_drone_4_drone_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'byrobot_drone_4_drone_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n        },\n\n        byrobot_drone_4_controller_display_clear_all: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_4_controller_display_clear_all',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayClearAll(script, 0x20, pixel);\n            },\n        },\n\n        byrobot_drone_4_controller_display_clear: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_display_clear',\n            },\n            paramsKeyMap: {\n                X     : 0,\n                Y     : 1,\n                WIDTH : 2,\n                HEIGHT: 3,\n                PIXEL : 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const x      = script.getNumberValue('X');\n                const y      = script.getNumberValue('Y');\n                const width  = script.getNumberValue('WIDTH');\n                const height = script.getNumberValue('HEIGHT');\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayClear(script, 0x20, pixel, x, y, width, height);\n            },\n        },\n\n        byrobot_drone_4_controller_display_draw_point: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_display_draw_point',\n            },\n            paramsKeyMap: {\n                X    : 0,\n                Y    : 1,\n                PIXEL: 2,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const x     = script.getNumberValue('X');\n                const y     = script.getNumberValue('Y');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayDrawPoint(script, 0x20, x, y, pixel);\n            },\n        },\n\n        byrobot_drone_4_controller_display_draw_line: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    { type: 'text', params: ['96'] },\n                    { type: 'text', params: ['48'] },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_display_draw_line',\n            },\n            paramsKeyMap: {\n                X1   : 0,\n                Y1   : 1,\n                X2   : 2,\n                Y2   : 3,\n                PIXEL: 4,\n                LINE : 5,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const x1    = script.getNumberValue('X1');\n                const y1    = script.getNumberValue('Y1');\n                const x2    = script.getNumberValue('X2');\n                const y2    = script.getNumberValue('Y2');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                const line  = parseInt(script.getField('LINE'), 10);\n                return Entry.byrobot_base.setDisplayDrawLine(script, 0x20, x1, y1, x2, y2, pixel, line);\n            },\n        },\n\n        byrobot_drone_4_controller_display_draw_rect: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_display_draw_rect',\n            },\n            paramsKeyMap: {\n                X       : 0,\n                Y       : 1,\n                WIDTH   : 2,\n                HEIGHT  : 3,\n                PIXEL   : 4,\n                FLAGFILL: 5,\n                LINE    : 6,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const x        = script.getNumberValue('X');\n                const y        = script.getNumberValue('Y');\n                const width    = script.getNumberValue('WIDTH');\n                const height   = script.getNumberValue('HEIGHT');\n                const pixel    = parseInt(script.getField('PIXEL'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n                const line     = parseInt(script.getField('LINE'), 10);\n                return Entry.byrobot_base.setDisplayDrawRect(script, 0x20, x, y, width, height, pixel, flagFill, line);\n            },\n        },\n\n        byrobot_drone_4_controller_display_draw_circle: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['24'] },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_display_draw_circle',\n            },\n            paramsKeyMap: {\n                X       : 0,\n                Y       : 1,\n                RADIUS  : 2,\n                PIXEL   : 3,\n                FLAGFILL: 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const x        = script.getNumberValue('X');\n                const y        = script.getNumberValue('Y');\n                const radius   = script.getNumberValue('RADIUS');\n                const pixel    = parseInt(script.getField('PIXEL'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n                return Entry.byrobot_base.setDisplayDrawCircle(script, 0x20, x, y, radius, pixel, flagFill);\n            },\n        },\n\n        byrobot_drone_4_controller_display_draw_string: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_font_5x8, '0'],\n                        [Lang.Blocks.controller_display_font_10x16, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['39'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                    { type: 'text', params: ['HELLO'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_display_draw_string',\n            },\n            paramsKeyMap: {\n                X     : 0,\n                Y     : 1,\n                FONT  : 2,\n                PIXEL : 3,\n                STRING: 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const x      = script.getNumberValue('X');\n                const y      = script.getNumberValue('Y');\n                const font   = parseInt(script.getField('FONT'), 10);\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                const string = script.getStringValue('STRING');\n                return Entry.byrobot_base.setDisplayDrawString(script, 0x20, x, y, font, pixel, string);\n            },\n        },\n\n        byrobot_drone_4_controller_display_draw_string_align: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_align_left, '0'],\n                        [Lang.Blocks.controller_display_align_center, '1'],\n                        [Lang.Blocks.controller_display_align_right, '2'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_font_5x8, '0'],\n                        [Lang.Blocks.controller_display_font_10x16, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0'] },\n                    { type: 'text', params: ['128'] },\n                    { type: 'text', params: ['42'] },\n                    null,\n                    null,\n                    null,\n                    { type: 'text', params: ['DRONE'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_display_draw_string_align',\n            },\n            paramsKeyMap: {\n                XSTART: 0,\n                XEND  : 1,\n                Y     : 2,\n                ALIGN : 3,\n                FONT  : 4,\n                PIXEL : 5,\n                STRING: 6,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const xStart = script.getNumberValue('XSTART');\n                const xEnd   = script.getNumberValue('XEND');\n                const y      = script.getNumberValue('Y');\n                const align  = parseInt(script.getField('ALIGN'), 10);\n                const font   = parseInt(script.getField('FONT'), 10);\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                const string = script.getStringValue('STRING');\n                return Entry.byrobot_base.setDisplayDrawStringAlign(script, 0x20, xStart, xEnd, y, align, font, pixel, string);\n            },\n        },\n\n        byrobot_drone_4_controller_buzzer_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class       : 'buzzer',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setBuzzerStop(script, 0x20);\n            },\n        },\n\n        byrobot_drone_4_controller_buzzer_scale: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_drone_4_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, 60000, false, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, 60000, false, true);\n                }\n            },\n        },\n\n        byrobot_drone_4_controller_buzzer_scale_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, true, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, true, true);\n                }\n            },\n        },\n\n        byrobot_drone_4_controller_buzzer_scale_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, false, false);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, false, false);\n                }\n            },\n        },\n\n        byrobot_drone_4_controller_buzzer_hz: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1000'] }, null],\n                type  : 'byrobot_drone_4_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const hz = script.getNumberValue('HZ');\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, 60000, false, true);\n            },\n        },\n\n        byrobot_drone_4_controller_buzzer_hz_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1000'] }, { type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_4_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ  : 0,\n                TIME: 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, true, true);\n            },\n        },\n\n        byrobot_drone_4_controller_buzzer_hz_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['1000'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ  : 0,\n                TIME: 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, false, false);\n            },\n        },\n\n        byrobot_drone_4_controller_vibrator_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class       : 'vibrator',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setVibratorStop(script, 0x20);\n            },\n        },\n\n        byrobot_drone_4_controller_vibrator_on_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_4_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, true, true);\n            },\n        },\n\n        byrobot_drone_4_controller_vibrator_on_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_4_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, false, false);\n            },\n        },\n\n        byrobot_drone_4_controller_vibrator_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, true, true);\n            },\n        },\n\n        byrobot_drone_4_controller_vibrator_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, false, false);\n            },\n        },\n\n        byrobot_drone_4_drone_motor_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'motor',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n        },\n\n        byrobot_drone_4_drone_motorsingle: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type      : 'Dropdown',\n                    options   : [['1(FR)', '0'], ['2(RR)', '1'], ['3(RL)', '2'], ['4(FL)', '3']],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'text', params: ['120'] }, null],\n                type  : 'byrobot_drone_4_drone_motorsingle',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const motorIndex = parseInt(script.getField('MOTORINDEX'), 10);\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.byrobot_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n        },\n\n        byrobot_drone_4_drone_motorsingle_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, { type: 'text', params: ['120'] }, null],\n                type  : 'byrobot_drone_4_drone_motorsingle_input',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const motorIndex = script.getNumberValue('MOTORINDEX') - 1;\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.byrobot_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n        },\n\n        byrobot_drone_4_drone_control_drone_takeoff: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_control_drone_takeoff',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x11, 5000); // 0x11 : FlightEvent::TakeOff\n            },\n        },\n\n        byrobot_drone_4_drone_control_drone_landing: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_control_drone_landing',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x12, 5000); // 0x12 : FlightEvent::Landing\n            },\n        },\n\n        byrobot_drone_4_drone_control_drone_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_control_drone_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n        },\n\n        byrobot_drone_4_drone_control_headless: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_headless_headless, '1'],\n                        [Lang.Blocks.drone_headless_normal,   '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_4_drone_control_headless',\n            },\n            paramsKeyMap: {\n                HEADLESS: 0,\n            },\n            class   : 'control_flight',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const headless = script.getField('HEADLESS');\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x03, headless);\n            },\n        },\n\n        byrobot_drone_4_drone_control_drone_reset_heading: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_4_drone_control_drone_reset_heading',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x07, 0xA0); // 0x22 : CommandType::FlightEvent  // 0xA0 : FlightEvent::ResetHeading\n            },\n        },\n\n        byrobot_drone_4_drone_control_quad_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['0'] }, null],\n                type  : 'byrobot_drone_4_drone_control_quad_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, 0, false);\n            },\n        },\n\n        byrobot_drone_4_drone_control_quad_one_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['100'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_drone_control_quad_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n                TIME         : 2,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n                const time          = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, time, true);\n            },\n        },\n\n        byrobot_drone_4_drone_control_quad: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_drone_control_quad',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, 0, false);\n            },\n        },\n\n        byrobot_drone_4_drone_control_quad_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_4_drone_control_quad_delay',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n                TIME    : 4,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n                const time     = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, time, true);\n            },\n        },\n\n        byrobot_drone_4_drone_control_position_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  'pitch_forward'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, 'pitch_backward'],\n                        [Lang.Blocks.drone_control_quad_roll_left,      'roll_left'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     'roll_right'],\n                        [Lang.Blocks.drone_control_quad_throttle_up,    'throttle_up'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  'throttle_down'],\n                    ],\n                    value     : 'pitch_forward',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['1'] }, { type: 'number', params: ['1'] }, null],\n                type  : 'byrobot_drone_4_drone_control_position_one',\n            },\n            paramsKeyMap: {\n                CONTROLDIRECTION: 0,\n                DISTANCE        : 1,\n                SPEED           : 2,\n            },\n            class   : 'control_position',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const controlDirection = script.getField('CONTROLDIRECTION');\n                const distance         = script.getNumberValue('DISTANCE');\n                const speed            = script.getNumberValue('SPEED');\n                let   time             = 0;\n                \n                if( speed > 0 )\n                {\n                    time = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                let x = 0;\n                let y = 0;\n                let z = 0;\n\n                switch( controlDirection )\n                {\n                    case    'pitch_forward':   x = distance;   break;\n                    case    'pitch_backward':  x = -distance;  break;\n                    case    'roll_left':       y = distance;   break;\n                    case    'roll_right':      y = -distance;  break;\n                    case    'throttle_up':     z = distance;   break;\n                    default:                z    = -distance;  break;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, x, y, z, speed, 0, 0, time, true);\n            },\n        },\n\n        byrobot_drone_4_drone_control_position_turn: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                        [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['90'] },\n                    { type: 'number', params: ['45'] },\n                    null\n                ],\n                type: 'byrobot_drone_4_drone_control_position_turn',\n            },\n            paramsKeyMap: {\n                DIRECTION_YAW: 0,\n                DEGREE_YAW   : 1,\n                SPEED_YAW    : 2,\n            },\n            class   : 'control_position',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const directionYaw = script.getNumberValue('DIRECTION_YAW');\n                const degree       = script.getNumberValue('DEGREE_YAW');\n                const yaw          = directionYaw * degree;\n                const speedYaw     = script.getNumberValue('SPEED_YAW');\n\n                let time = 0;\n\n                if( speedYaw > 0 )\n                {\n                    time = Math.abs(degree / speedYaw) * 2 * 1000 + 3000;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, 0, 0, 0, 0, yaw, speedYaw, time, true);\n            },\n        },\n\n        byrobot_drone_4_drone_control_position_location: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null],\n                type: 'byrobot_drone_4_drone_control_position_location',\n            },\n            paramsKeyMap: {\n                DIRECTION_PITCH   : 0,\n                DISTANCE_PITCH    : 1,\n                DIRECTION_ROLL    : 2,\n                DISTANCE_ROLL     : 3,\n                DIRECTION_THROTTLE: 4,\n                DISTANCE_THROTTLE : 5,\n                SPEED             : 6\n            },\n            class   : 'control_position',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const directionPitch    = script.getNumberValue('DIRECTION_PITCH');\n                const directionRoll     = script.getNumberValue('DIRECTION_ROLL');\n                const directionThrottle = script.getNumberValue('DIRECTION_THROTTLE');\n                \n                const x = directionPitch     * script.getNumberValue('DISTANCE_PITCH');\n                const y = directionRoll      * script.getNumberValue('DISTANCE_ROLL');\n                const z = directionThrottle  * script.getNumberValue('DISTANCE_THROTTLE');\n\n                const distance = Math.sqrt((x * x) + (y * y) + (z * z));\n\n                const speed = script.getNumberValue('SPEED');\n\n                let time = 0;\n\n                if( speed > 0 )\n                {\n                    time = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, x, y, z, speed, 0, 0, time, true);\n            },\n        },\n\n        byrobot_drone_4_drone_control_position_location_turn: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                        [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['90'] },\n                    { type: 'number', params: ['45'] },\n                    null],\n                type: 'byrobot_drone_4_drone_control_position_location_turn',\n            },\n            paramsKeyMap: {\n                DIRECTION_PITCH   : 0,\n                DISTANCE_PITCH    : 1,\n                DIRECTION_ROLL    : 2,\n                DISTANCE_ROLL     : 3,\n                DIRECTION_THROTTLE: 4,\n                DISTANCE_THROTTLE : 5,\n                SPEED             : 6,\n                DIRECTION_YAW     : 7,\n                DEGREE_YAW        : 8,\n                SPEED_YAW         : 9,\n            },\n            class   : 'control_position',\n            isNotFor: ['byrobot_drone_4'],\n            func(sprite, script)\n            {\n                const directionPitch    = script.getNumberValue('DIRECTION_PITCH');\n                const directionRoll     = script.getNumberValue('DIRECTION_ROLL');\n                const directionThrottle = script.getNumberValue('DIRECTION_THROTTLE');\n                \n                const x = directionPitch     * script.getNumberValue('DISTANCE_PITCH');\n                const y = directionRoll      * script.getNumberValue('DISTANCE_ROLL');\n                const z = directionThrottle  * script.getNumberValue('DISTANCE_THROTTLE');\n\n                const distance = Math.sqrt((x * x) + (y * y) + (z * z));\n                const speed    = script.getNumberValue('SPEED');\n\n                const directionYaw = script.getNumberValue('DIRECTION_YAW');\n                const degree       = script.getNumberValue('DEGREE_YAW');\n                const yaw          = directionYaw * degree;\n                const speedYaw     = script.getNumberValue('SPEED_YAW');\n\n                let timePosition = 0;\n                let timeRotation = 0;\n\n                if( speed > 0 )\n                {\n                    timePosition = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                if( speedYaw > 0 )\n                {\n                    timeRotation = Math.abs(degree / speedYaw) * 2 * 1000 + 3000;\n                }\n\n                const time = Math.max(timePosition, timeRotation);\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, x, y, z, speed, yaw, speedYaw, time, true);\n            },\n        },\n    };\n};\n\n\nmodule.exports = Entry.byrobot_drone_4;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_drone_8.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_drone_8 = \n{\n    id       : 'F.7',\n    name     : 'byrobot_drone_8',\n    url      : 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_drone_8.png',\n    title    : {\n        en: 'BYROBOT Coding Drone',\n        ko: '바이로봇 코딩 드론',\n    },\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero()\n    {\n        // 초기화\n        Entry.byrobot_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            if( Entry.hw.portData['state_modeFlight'] == 0x10 )\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x01, 0); // 드론, command = 0x01 (Stop)\n            }\n            else\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x07, 0x12); // 0x12 : FlightEvent::Landing\n            }\n\n            Entry.byrobot_base.transferBuzzer(0x10, 0, 0, 0);\n            Entry.byrobot_base.transferBuzzer(0x20, 0, 0, 0);\n            Entry.byrobot_base.transferVibrator(0x20, 0, 0, 0, 0);\n            Entry.byrobot_base.transferLightManual(0x10, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightManual(0x20, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightModeColor(0x10, 0x22, 200, 255, 0, 0); // LED 초기화(드론)\n            Entry.byrobot_base.transferLightModeColor(0x20, 0x22, 200, 255, 0, 0); // LED 초기화(조종기)\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.byrobot_drone_8.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                // 정보창\n                monitor_state_modeFlight                        : '비행 모드',\n                monitor_state_modeControlFlight                 : '비행 제어기 모드',\n                monitor_state_modeMovement                      : '이동 상태',\n                monitor_state_headless                          : '헤드리스',\n                monitor_state_controlSpeed                      : '제어 속도',\n                monitor_state_sensorOrientation                 : '센서 방향',\n                monitor_state_battery                           : '배터리',\n                monitor_motion_accelX                           : '가속도 X',\n                monitor_motion_accelY                           : '가속도 Y',\n                monitor_motion_accelZ                           : '가속도 Z',\n                monitor_motion_gyroRoll                         : '자이로 Roll',\n                monitor_motion_gyroPitch                        : '자이로 Pitch',\n                monitor_motion_gyroYaw                          : '자이로 Yaw',\n                monitor_motion_angleRoll                        : '자세 Roll',\n                monitor_motion_anglePitch                       : '자세 Pitch',\n                monitor_motion_angleYaw                         : '자세 Yaw',\n                monitor_range_front                             : '정면 거리 센서',\n                monitor_range_bottom                            : '바닥 거리 센서',\n                monitor_cardColor_frontHue                      : '카드 위 색상',\n                monitor_cardColor_frontSaturation               : '카드 위 채도',\n                monitor_cardColor_frontValue                    : '카드 위 명도',\n                monitor_cardColor_frontLightness                : '카드 위 밝기',\n                monitor_cardColor_rearHue                       : '카드 아래 색상',\n                monitor_cardColor_rearSaturation                : '카드 아래 채도',\n                monitor_cardColor_rearValue                     : '카드 아래 명도',\n                monitor_cardColor_rearLightness                 : '카드 아래 밝기',\n                monitor_cardColor_frontColor                    : '카드 위 색',\n                monitor_cardColor_rearColor                     : '카드 아래 색',\n                monitor_cardColor_card                          : '카드',\n                monitor_informationAssembledForEntry_positionX  : '위치 X',\n                monitor_informationAssembledForEntry_positionY  : '위치 Y',\n                monitor_informationAssembledForEntry_positionZ  : '위치 Z',\n                monitor_informationAssembledForEntry_altitude   : '고도',\n                monitor_informationAssembledForEntry_rangeHeight: '거리 센서의 높이',\n                monitor_joystick_left_x                         : '왼쪽 조이스틱 X',\n                monitor_joystick_left_y                         : '왼쪽 조이스틱 Y',\n                monitor_joystick_left_direction                 : '왼쪽 조이스틱 방향',\n                monitor_joystick_left_event                     : '왼쪽 조이스틱 이벤트',\n                monitor_joystick_right_x                        : '오른쪽 조이스틱 X',\n                monitor_joystick_right_y                        : '오른쪽 조이스틱 Y',\n                monitor_joystick_right_direction                : '오른쪽 조이스틱 방향',\n                monitor_joystick_right_event                    : '오른쪽 조이스틱 이벤트',\n                monitor_button_button                           : '버튼',\n                monitor_button_event                            : '버튼 이벤트',\n                monitor_entryhw_countTransferReserved           : '전송 예정 데이터',\n\n                // 일반 블럭\n                common_light_color_red                  : '빨강',\n                common_light_color_yellow               : '노랑',\n                common_light_color_green                : '초록',\n                common_light_color_cyan                 : '하늘색',\n                common_light_color_blue                 : '파랑',\n                common_light_color_magenta              : '자홍',\n                common_light_color_white                : '흰색',\n                common_light_color_black                : '검정',\n                common_light_color_cottoncandy          : '구름솜사탕',\n                common_light_color_emerald              : '에메랄드',\n                common_light_color_lavender             : '라벤더',\n                common_light_color_muscat               : '청포도',\n                common_light_color_strawberrymilk       : '딸기우유',\n                common_light_color_sunset               : '저녁노을',\n                common_light_mode_hold                  : '켜짐',\n                common_light_mode_flicker               : '깜빡임',\n                common_light_mode_flicker_double        : '2번 연속 깜빡임',\n                common_light_mode_dimming               : '천천히 깜빡임',\n                common_light_mode_sunrise               : '점점 밝아짐',\n                common_light_mode_sunset                : '점점 어두워짐',\n                common_light_mode_rainbow               : '무지개',\n                common_light_mode_rainbow2              : '무지개2',\n                common_light_brightness_all             : '전체',\n                common_light_brightness_b100            : '밝기 100%',\n                common_light_brightness_b25             : '밝기 25%',\n                common_light_brightness_b50             : '밝기 50%',\n                common_light_brightness_b75             : '밝기 75%',\n                common_light_brightness_off             : '끄기',\n                common_light_brightness_on              : '켜기',\n                common_left                             : '왼쪽',\n                common_right                            : '오른쪽',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                common_drone                            : '드론',\n                common_controller                       : '조종기',\n                controller_button                       : '버튼',\n                controller_button_event                 : '버튼 이벤트',\n                controller_button_front_left_top        : '전면 왼쪽 상단 버튼',\n                controller_button_front_left_bottom     : '전면 왼쪽 하단 버튼',\n                controller_button_front_right_top       : '전면 오른쪽 상단 버튼',\n                controller_button_front_right_bottom    : '전면 오른쪽 하단 버튼',\n                controller_button_top_left              : '상단 왼쪽 버튼',\n                controller_button_top_right             : '상단 오른쪽 버튼',\n                controller_button_center_up             : '중앙 위 버튼',\n                controller_button_center_left           : '중앙 왼쪽 버튼',\n                controller_button_center_right          : '중앙 오른쪽 버튼',\n                controller_button_center_down           : '중앙 아래쪽 버튼',\n                controller_button_bottom_left           : '하단 왼쪽 버튼',\n                controller_button_bottom_right          : '하단 오른쪽 버튼',\n                controller_buzzer                       : '버저',\n                controller_buzzer_a                     : '라',\n                controller_buzzer_as                    : '라#',\n                controller_buzzer_b                     : '시',\n                controller_buzzer_c                     : '도',\n                controller_buzzer_cs                    : '도#',\n                controller_buzzer_d                     : '레',\n                controller_buzzer_ds                    : '레#',\n                controller_buzzer_e                     : '미',\n                controller_buzzer_f                     : '파',\n                controller_buzzer_fs                    : '파#',\n                controller_buzzer_g                     : '솔',\n                controller_buzzer_gs                    : '솔#',\n                controller_buzzer_mute                  : '쉼',\n                controller_display_align_center         : '가운데',\n                controller_display_align_left           : '왼쪽',\n                controller_display_align_right          : '오른쪽',\n                controller_display_flagfill_off         : '채우지 않음',\n                controller_display_flagfill_on          : '채움',\n                controller_display_font_10x16           : '큼',\n                controller_display_font_5x8             : '작음',\n                controller_display_line_dashed          : '파선',\n                controller_display_line_dotted          : '점선',\n                controller_display_line_solid           : '실선',\n                controller_display_pixel_black          : '검은색',\n                controller_display_pixel_white          : '흰색',\n                controller_display_pixel_inverse        : '반전',\n                controller_joystick_direction_left_up   : '왼쪽 위',\n                controller_joystick_direction_up        : '위',\n                controller_joystick_direction_right_up  : '오른쪽 위',\n                controller_joystick_direction_left      : '왼쪽',\n                controller_joystick_direction_center    : '중앙',\n                controller_joystick_direction_right     : '오른쪽',\n                controller_joystick_direction_left_down : '왼쪽 아래',\n                controller_joystick_direction_down      : '아래',\n                controller_joystick_direction_right_down: '오른쪽 아래',\n                controller_joystick_left_direction      : '왼쪽 조이스틱 방향',\n                controller_joystick_left_event          : '왼쪽 조이스틱 이벤트',\n                controller_joystick_left_x              : '왼쪽 조이스틱 가로축',\n                controller_joystick_left_y              : '왼쪽 조이스틱 세로축',\n                controller_joystick_right_direction     : '오른쪽 조이스틱 방향',\n                controller_joystick_right_event         : '오른쪽 조이스틱 이벤트',\n                controller_joystick_right_x             : '오른쪽 조이스틱 가로축',\n                controller_joystick_right_y             : '오른쪽 조이스틱 세로축',\n                drone_accel_x                           : '가속도 x',\n                drone_accel_y                           : '가속도 y',\n                drone_accel_z                           : '가속도 z',\n                drone_gyro_pitch                        : '각속도 Pitch',\n                drone_gyro_roll                         : '각속도 Roll',\n                drone_gyro_yaw                          : '각속도 Yaw',\n                drone_attitude_pitch                    : '자세 Pitch',\n                drone_attitude_roll                     : '자세 Roll',\n                drone_attitude_yaw                      : '자세 Yaw',\n                drone_positionX                         : '위치 X',\n                drone_positionY                         : '위치 Y',\n                drone_positionZ                         : '위치 Z',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : '뒤',\n                drone_control_quad_pitch_forward        : '앞',\n                drone_control_quad_roll_left            : '왼쪽',\n                drone_control_quad_roll_right           : '오른쪽',\n                drone_control_quad_throttle_down        : '아래',\n                drone_control_quad_throttle_up          : '위',\n                drone_control_quad_yaw_ccw              : '반시계 방향',\n                drone_control_quad_yaw_cw               : '시계 방향',\n                drone_headless_normal                   : 'off (숙련자용)',\n                drone_headless_headless                 : 'on (초보자용)',\n                drone_light_color_body                  : '몸체',\n                drone_light_manual_body_blue            : '파랑',\n                drone_light_manual_body_green           : '초록',\n                drone_light_manual_body_red             : '빨강',\n                drone_motor_rotation_clockwise          : '시계 방향',\n                drone_motor_rotation_counterclockwise   : '반시계 방향',\n                drone_altitude                          : '해발고도',\n                drone_range_height                      : '바닥과의 거리',\n                drone_range_front                       : '정면과의 거리',\n                drone_cardcolor_front_hue               : '앞 색상',\n                drone_cardcolor_front_saturation        : '앞 채도',\n                drone_cardcolor_front_value             : '앞 명도',\n                drone_cardcolor_front_lightness         : '앞 밝기',\n                drone_cardcolor_rear_hue                : '뒤 색상',\n                drone_cardcolor_rear_saturation         : '뒤 채도',\n                drone_cardcolor_rear_value              : '뒤 명도',\n                drone_cardcolor_rear_lightness          : '뒤 밝기',\n                drone_cardcolor_front_color             : '앞 카드 색',\n                drone_cardcolor_rear_color              : '뒤 카드 색',\n                drone_cardcolor_card                    : '카드',\n                drone_state_mode_system                 : '시스템 모드',\n                drone_state_mode_flight                 : '비행 동작 상태',\n                drone_state_mode_control_flight         : '비행 제어 모드',\n                drone_state_mode_movement               : '이동 상태',\n                drone_state_headless                    : 'Headless',\n                drone_state_control_speed               : '제어 속도',\n                drone_state_sensor_orientation          : '센서 방향',\n                drone_state_battery                     : '배터리',\n                entryhw_count_transfer_reserved         : '전송 예약된 데이터 수',\n            },\n\n            template: {\n                byrobot_drone_8_controller_buzzer_hz                : '%1 %2Hz 소리를 연주 %3',\n                byrobot_drone_8_controller_buzzer_hz_delay          : '%1 %2Hz 소리를 %3초 연주 %4',\n                byrobot_drone_8_controller_buzzer_hz_reserve        : '%1 %2Hz 소리를 %3초 예약 %4',\n                byrobot_drone_8_controller_buzzer_off               : '%1 버저 끄기 %2',\n                byrobot_drone_8_controller_buzzer_scale             : '%1 %2 옥타브 %3을(를) 연주 %4',\n                byrobot_drone_8_controller_buzzer_scale_delay       : '%1 %2 옥타브 %3을(를) %4초 연주 %5',\n                byrobot_drone_8_controller_buzzer_scale_reserve     : '%1 %2 옥타브 %3을(를) %4초 예약 %5',\n                byrobot_drone_8_controller_display_clear            : '지우기 x %1, y %2, 너비 %3, 높이 %4 %5 %6',\n                byrobot_drone_8_controller_display_clear_all        : '화면 전체 지우기%1 %2',\n                byrobot_drone_8_controller_display_draw_circle      : '원 x %1, y %2, 반지름 %3 %4 %5 %6',\n                byrobot_drone_8_controller_display_draw_line        : '선 x1 %1, y1 %2, x2 %3, y2 %4 %5 %6 %7',\n                byrobot_drone_8_controller_display_draw_point       : '점 그리기 x %1, y %2 %3 %4',\n                byrobot_drone_8_controller_display_draw_rect        : '사각형 x %1, y %2, 너비 %3, 높이 %4 %5 %6 %7 %8',\n                byrobot_drone_8_controller_display_draw_string      : '문자열 x %1, y %2 %3 %4 입력 %5 %6',\n                byrobot_drone_8_controller_display_draw_string_align: '문자열 정렬 x1 %1, x2 %2, y %3 %4 %5 %6 입력 %7 %8',\n                byrobot_drone_8_controller_if_button_press          : '조종기 %1 눌렀을 때',\n                byrobot_drone_8_controller_if_joystick_direction    : '조종기 %1 조이스틱 %2 (으)로 움직였을 때',\n                byrobot_drone_8_controller_light_color_input        : '조종기 LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_8_controller_light_color_select       : '조종기 LED %1 %2 %3 %4',\n                byrobot_drone_8_controller_light_color_preset       : '조종기 LED %1 %2 %3',\n                byrobot_drone_8_controller_light_manual_single_input: '조종기 LED %1 밝기 %2 %3',\n                byrobot_drone_8_controller_light_manual_single_off  : '조종기 LED 끄기 %1',\n                byrobot_drone_8_controller_value_button             : '%1',\n                byrobot_drone_8_controller_value_joystick           : '%1',\n                byrobot_drone_8_controller_vibrator_delay           : '진동 %1초 켜기, %2초 끄기를 %3초 실행 %4',\n                byrobot_drone_8_controller_vibrator_off             : '진동 끄기 %1',\n                byrobot_drone_8_controller_vibrator_on_delay        : '진동 %1초 켜기 %2',\n                byrobot_drone_8_controller_vibrator_on_reserve      : '진동 %1초 예약 %2',\n                byrobot_drone_8_controller_vibrator_reserve         : '진동 %1초 켜기, %2초 끄기를 %3초 예약 %4',\n                byrobot_drone_8_drone_control_headless              : 'Headless mode %1 %2',\n                byrobot_drone_8_drone_control_drone_landing         : '드론 착륙 %1',\n                byrobot_drone_8_drone_control_drone_reset_heading   : '드론 방향 초기화 %1',\n                byrobot_drone_8_drone_control_drone_stop            : '드론 정지 %1',\n                byrobot_drone_8_drone_control_drone_takeoff         : '드론 이륙 %1',\n                byrobot_drone_8_drone_control_quad_one              : '드론 %1 %2% 정하기 %3',\n                byrobot_drone_8_drone_control_quad_one_delay        : '드론 %1 %2% %3 초 실행 %4',\n                byrobot_drone_8_drone_control_quad                  : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% 정하기 %5',\n                byrobot_drone_8_drone_control_quad_delay            : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5초 실행 %6',\n                byrobot_drone_8_drone_control_position_one          : '드론 %1(으)로 %2m를 %3m/s로 이동 %4',\n                byrobot_drone_8_drone_control_position_turn         : '드론 %1(으)로 %2도를 %3deg/s로 회전 %4',\n                byrobot_drone_8_drone_control_position_location     : '드론 %1 %2m, %3 %4m, %5 %6m를 %7m/s로 이동 %8',\n                byrobot_drone_8_drone_control_position_location_turn: '드론 %1 %2m, %3 %4m, %5 %6m를 %7m/s로 이동, %8 %9도를 %10deg/s로 회전 %11',\n                byrobot_drone_8_drone_light_color_input             : '드론 LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_8_drone_light_color_select            : '드론 LED %1 %2 %3 %4',\n                byrobot_drone_8_drone_light_color_preset            : '드론 LED %1 %2 %3',\n                byrobot_drone_8_drone_light_manual_single_input     : '드론 LED %1 밝기 %2 %3',\n                byrobot_drone_8_drone_light_manual_single_off       : '드론 LED 끄기 %1',\n                byrobot_drone_8_drone_motor_stop                    : '드론 모터 정지 %1',\n                byrobot_drone_8_drone_motorsingle                   : '드론 %1번 모터를 %2(으)로 회전 %3',\n                byrobot_drone_8_drone_motorsingle_input             : '드론 %1번 모터를 %2(으)로 회전 %3',\n                byrobot_drone_8_drone_value_attitude                : '%1',\n                byrobot_drone_8_drone_value_motion                  : '%1',\n                byrobot_drone_8_drone_value_position                : '%1',\n                byrobot_drone_8_drone_value_sensor                  : '%1',\n                byrobot_drone_8_drone_value_card                    : '%1',\n                byrobot_drone_8_drone_value_etc                     : '%1',\n            },\n\n            Helper: {\n                byrobot_drone_8_controller_buzzer_hz                : \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                byrobot_drone_8_controller_buzzer_hz_delay          : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                byrobot_drone_8_controller_buzzer_hz_reserve        : \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                byrobot_drone_8_controller_buzzer_off               : \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                byrobot_drone_8_controller_buzzer_scale             : \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                byrobot_drone_8_controller_buzzer_scale_delay       : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                byrobot_drone_8_controller_buzzer_scale_reserve     : \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                byrobot_drone_8_controller_display_clear            : \"<br>조종기 OLED 화면의 선택한 영역을 지웁니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_8_controller_display_clear_all        : \"<br>조종기 OLED 화면 전체를 지웁니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_8_controller_display_draw_circle      : \"<br>조종기 OLED 화면에서 지정한 위치에 원을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 반지름을 지정합니다. 원의 중심 = (x, y),<br>반지름은 원의 크기를 결정합니다.<br><br>★☆사용 가능한 값의 범위는 x값은 (-50~178), y값은 (-50~114), 반지름은 (1~200)입니다.☆★<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_8_controller_display_draw_line        : \"<br>조종기 OLED 화면에서 지정한 위치에 선을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>시작점 = (x1, y1), 끝나는점 = (x2, y2)<br>선 그리기는 시작점과 끝나는점을 이어주는 기능입니다.<br>사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_8_controller_display_draw_point       : \"<br>조종기 OLED 화면에서 지정한 위치에 점을 찍습니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다. x, y 좌표값으로 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_8_controller_display_draw_rect        : \"<br>조종기 OLED 화면에서 지정한 위치에 사각형을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 너비, 높이를 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_8_controller_display_draw_string      : \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 씁니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 글자 크기, 색을 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값은 (0~120), y값과 높이는 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_8_controller_display_draw_string_align: \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 정렬하여 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 정렬 방향, 글자 크기, 색을 지정합니다. 시작점 = (x1, y), 끝나는점 = (x2, y), 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                byrobot_drone_8_controller_if_button_press          : \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                byrobot_drone_8_controller_if_joystick_direction    : \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                byrobot_drone_8_controller_light_color_input        : \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 조종기 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_8_controller_light_color_select       : \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 조종기 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_8_controller_light_color_preset       : \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_8_controller_light_manual_single_input: \"<br>조종기 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255) 또는 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 LED의 Red, Green, Blue 색을 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_8_controller_light_manual_single_off  : \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                byrobot_drone_8_controller_value_button             : \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                byrobot_drone_8_controller_value_joystick           : \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                byrobot_drone_8_controller_vibrator_delay           : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                byrobot_drone_8_controller_vibrator_off             : \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                byrobot_drone_8_controller_vibrator_on_delay        : \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                byrobot_drone_8_controller_vibrator_on_reserve      : \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                byrobot_drone_8_controller_vibrator_reserve         : \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                byrobot_drone_8_drone_control_headless              : \"<br>드론 좌표 기준을 변경합니다. Headless mode 선택을 on으로 하면 이륙 시와 '방향초기화'를 했을 때 드론이 바라보는 방향을 기준으로 앞뒤좌우가 고정됩니다. 이 때에는 Yaw를 조작하여 드론이 다른 방향을 보게 하여도 처음 지정한 방향을 기준으로 앞뒤좌우로 움직입니다. 사용자가 바라보는 방향과 드론의 기준 방향이 같을 때 조작하기 편리한 장점이 있습니다.<br>Headless mode를 off로 선택하면 현재 드론이 바라보는 방향을 기준으로 앞뒤좌우가 결정됩니다. 드론의 움직임에 따라 앞뒤좌우가 계속 바뀌기 때문에 익숙해지기 전까지는 사용하기 어려울 수 있습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#좌표기준</font>\",\n                byrobot_drone_8_drone_control_drone_landing         : \"<br>드론을 착륙시킵니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#착륙</font>\",\n                byrobot_drone_8_drone_control_drone_reset_heading   : \"<br>드론의 방향을 초기화합니다. 앱솔루트 모드인 경우 현재 드론이 바라보는 방향을 0도로 변경합니다. 일반 모드에서는 아무런 영향이 없습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#방향초기화</font>\",\n                byrobot_drone_8_drone_control_drone_stop            : \"<br>드론 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#정지</font>\",\n                byrobot_drone_8_drone_control_drone_takeoff         : \"<br>드론을 이륙시킵니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이륙</font>\",\n                byrobot_drone_8_drone_control_quad                  : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                byrobot_drone_8_drone_control_quad_delay            : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_8_drone_control_quad_one              : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                byrobot_drone_8_drone_control_quad_one_delay        : \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_8_drone_control_position_one          : \"<br>드론의 방향과 거리, 이동 속도를 지정하여 지정한 위치로 이동합니다. 거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_8_drone_control_position_turn         : \"<br>드론의 회전 방향과 각도, 회전 속도를 지정하여 지정한 각도로 회전합니다. 목표 각도를 회전 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#회전</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_8_drone_control_position_location     : \"<br>드론의 X, Y, Z 축의 방향과 거리, 이동 속도를 설정하여 지정한 위치로 이동합니다. 거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_8_drone_control_position_location_turn: \"<br>드론의 X, Y, Z 축의 방향과 거리, 이동 속도, 회전 방향과 목표 각도, 회전 속도를 설정하여 지정한 위치로의 이동과 회전을 실행합니다. 거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간 또는 목표 각도를 회전 속도로 나누어 얻은 시간에 1.2를 곱한 시간 중에 긴 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                byrobot_drone_8_drone_light_color_input             : \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 드론의 눈 또는 팔 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_8_drone_light_color_select            : \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 드론 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_8_drone_light_color_preset            : \"<br>드론의 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_8_drone_light_manual_single_input     : \"<br>드론 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                byrobot_drone_8_drone_light_manual_single_off       : \"<br>드론의 모든 LED를 끕니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED끄기</font>\",\n                byrobot_drone_8_drone_motor_stop                    : \"<br>모든 모터의 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터정지</font>\",\n                byrobot_drone_8_drone_motorsingle                   : \"<br>모터 제어 블럭입니다.<br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                byrobot_drone_8_drone_motorsingle_input             : \"<br>모터 제어 블럭입니다.<br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                byrobot_drone_8_drone_value_attitude                : \"<br>드론의 현재 자세를 각도로 반환합니다. Roll은 좌우 기울기(-90 ~ 90), Pitch는 앞뒤 기울기(-90 ~ 90), Yaw는 회전 각도(-180 ~ 180) 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#자세</font>\",\n                byrobot_drone_8_drone_value_etc                     : \"<br>드론 설정과 관련된 값들과 적외선 통신으로 받은 값을 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#기타</font>\",\n                byrobot_drone_8_drone_value_motion                  : \"<br>드론 IMU센서와 관련된 값들을 반환합니다.<br>(병진운동) 가속도는 x, y, z축에 대한 중력가속도입니다. 1g = 9.8m/s^2<br>(회전운동) 각속도는 x, y, z축을 기준으로 회전하는 속력을 나타내는 벡터입니다.(pitch, roll, yaw) <br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#IMU센서</font> <font color='crimson'>#가속도</font> <font color='dodgerblue'>#병진운동</font> <font color='crimson'>#각속도</font> <font color='dodgerblue'>#회전운동</font>\",\n                byrobot_drone_8_drone_value_position                : \"<br>드론 위치와 관련된 값들을 반환합니다.(단위:m)<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#위치</font>\",\n                byrobot_drone_8_drone_value_sensor                  : \"<br>드론 거리 및 고도 센서와 관련된 값들을 반환합니다(단위:m)<br>거리 센서의 유효 측정 거리는 2m입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#센서</font> <font color='crimson'>#거리센서</font> <font color='dodgerblue'>#대기압</font>\",\n                byrobot_drone_8_drone_value_card                    : \"<br>드론 카드 센서와 관련된 값들을 반환합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#카드</font>\",\n            },\n        },\n\n        en: {\n            Blocks: {\n                // 정보창\n                monitor_state_modeFlight                        : 'Flight Mode',\n                monitor_state_modeControlFlight                 : 'Control Flight Mode',\n                monitor_state_modeMovement                      : 'Movement Mode',\n                monitor_state_headless                          : 'Headless',\n                monitor_state_controlSpeed                      : 'Control Speed',\n                monitor_state_sensorOrientation                 : 'Sensor Orientation',\n                monitor_state_battery                           : 'Battery',\n                monitor_motion_accelX                           : 'Accel X',\n                monitor_motion_accelY                           : 'Accel Y',\n                monitor_motion_accelZ                           : 'Accel Z',\n                monitor_motion_gyroRoll                         : 'Gyro Roll',\n                monitor_motion_gyroPitch                        : 'Gyro Pitch',\n                monitor_motion_gyroYaw                          : 'Gyro Yaw',\n                monitor_motion_angleRoll                        : 'Roll',\n                monitor_motion_anglePitch                       : 'Pitch',\n                monitor_motion_angleYaw                         : 'Yaw',\n                monitor_range_front                             : 'Range Front',\n                monitor_range_bottom                            : 'Range Bottom',\n                monitor_cardColor_frontHue                      : 'Front Hue',\n                monitor_cardColor_frontSaturation               : 'Front Saturation',\n                monitor_cardColor_frontValue                    : 'Front Value',\n                monitor_cardColor_frontLightness                : 'Front Lightness',\n                monitor_cardColor_rearHue                       : 'Rear Hue',\n                monitor_cardColor_rearSaturation                : 'Rear Saturation',\n                monitor_cardColor_rearValue                     : 'Rear Value',\n                monitor_cardColor_rearLightness                 : 'Rear Lightness',\n                monitor_cardColor_frontColor                    : 'Front Color',\n                monitor_cardColor_rearColor                     : 'Rear Color',\n                monitor_cardColor_card                          : 'Card',\n                monitor_informationAssembledForEntry_positionX  : 'Position X',\n                monitor_informationAssembledForEntry_positionY  : 'Position Y',\n                monitor_informationAssembledForEntry_positionZ  : 'Position Z',\n                monitor_informationAssembledForEntry_altitude   : 'Altitude',\n                monitor_informationAssembledForEntry_rangeHeight: 'Height',\n                monitor_joystick_left_x                         : 'Left Joystick X',\n                monitor_joystick_left_y                         : 'Left Joystick Y',\n                monitor_joystick_left_direction                 : 'Left Joystick Direction',\n                monitor_joystick_left_event                     : 'Left Joystick Event',\n                monitor_joystick_right_x                        : 'Right Joystick X',\n                monitor_joystick_right_y                        : 'Right Joystick Y',\n                monitor_joystick_right_direction                : 'Right Joystick Direction',\n                monitor_joystick_right_event                    : 'Right Joystick Event',\n                monitor_button_button                           : 'Button',\n                monitor_button_event                            : 'Button Event',\n                monitor_entryhw_countTransferReserved           : 'Transfer Buffer',\n\n                // 일반 블럭\n                common_light_color_red                  : 'red',\n                common_light_color_yellow               : 'yellow',\n                common_light_color_green                : 'green',\n                common_light_color_cyan                 : 'cyan',\n                common_light_color_blue                 : 'blue',\n                common_light_color_magenta              : 'magenta',\n                common_light_color_white                : 'white',\n                common_light_color_cottoncandy          : 'cotton candy',\n                common_light_color_emerald              : 'emerald',\n                common_light_color_lavender             : 'lavender',\n                common_light_color_muscat               : 'muscat',\n                common_light_color_strawberrymilk       : 'strawberry milk',\n                common_light_color_sunset               : 'sunset',\n                common_light_mode_hold                  : 'hold',\n                common_light_mode_flicker               : 'flicker',\n                common_light_mode_flicker_double        : 'flicker double',\n                common_light_mode_dimming               : 'dimming',\n                common_light_mode_sunrise               : 'sunrise',\n                common_light_mode_sunset                : 'sunset',\n                common_light_mode_rainbow               : 'rainbow',\n                common_light_mode_rainbow2              : 'rainbow2',\n                common_light_brightness_all             : 'all',\n                common_light_brightness_b100            : 'brightness 100%',\n                common_light_brightness_b25             : 'brightness 25%',\n                common_light_brightness_b50             : 'brightness 50%',\n                common_light_brightness_b75             : 'brightness 75%',\n                common_light_brightness_off             : 'off',\n                common_light_brightness_on              : 'on',\n                common_left                             : 'left',\n                common_right                            : 'right',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                common_drone                            : 'drone',\n                common_controller                       : 'controller',\n                controller_button                       : 'button',\n                controller_button_event                 : 'button event',\n                controller_button_front_left_top        : 'Front left top button',\n                controller_button_front_left_bottom     : 'Front left bottom button',\n                controller_button_front_right_top       : 'Front right top button',\n                controller_button_front_right_bottom    : 'Front right bottom button',\n                controller_button_top_left              : 'Top left button',\n                controller_button_top_right             : 'Top right button',\n                controller_button_center_up             : 'Trim up button',\n                controller_button_center_left           : 'Trim left button',\n                controller_button_center_right          : 'Trim right button',\n                controller_button_center_down           : 'Trim down button',\n                controller_button_bottom_left           : 'Bottom left button',\n                controller_button_bottom_right          : 'Bottom right button',\n                controller_buzzer                       : 'buzzer',\n                controller_buzzer_a                     : 'A',\n                controller_buzzer_as                    : 'A#',\n                controller_buzzer_b                     : 'B',\n                controller_buzzer_c                     : 'C',\n                controller_buzzer_cs                    : 'C#',\n                controller_buzzer_d                     : 'D',\n                controller_buzzer_ds                    : 'D#',\n                controller_buzzer_e                     : 'E',\n                controller_buzzer_f                     : 'F',\n                controller_buzzer_fs                    : 'F#',\n                controller_buzzer_g                     : 'G',\n                controller_buzzer_gs                    : 'G#',\n                controller_buzzer_mute                  : 'mute',\n                controller_display_align_center         : 'center',\n                controller_display_align_left           : 'left',\n                controller_display_align_right          : 'right',\n                controller_display_flagfill_off         : 'not fill',\n                controller_display_flagfill_on          : 'fill',\n                controller_display_font_10x16           : 'big',\n                controller_display_font_5x8             : 'small',\n                controller_display_line_dashed          : 'dashed',\n                controller_display_line_dotted          : 'dotted',\n                controller_display_line_solid           : 'solid',\n                controller_display_pixel_black          : 'black',\n                controller_display_pixel_white          : 'white',\n                controller_display_pixel_inverse        : 'inverse',\n                controller_joystick_direction_left_up   : 'Left top',\n                controller_joystick_direction_up        : 'Top',\n                controller_joystick_direction_right_up  : 'Right top',\n                controller_joystick_direction_left      : 'Left',\n                controller_joystick_direction_center    : 'Center',\n                controller_joystick_direction_right     : 'Right',\n                controller_joystick_direction_left_down : 'Left Bottom',\n                controller_joystick_direction_down      : 'Bottom',\n                controller_joystick_direction_right_down: 'Right Bottom',\n                controller_joystick_left_direction      : 'left joystick direction',\n                controller_joystick_left_event          : 'left joystick event',\n                controller_joystick_left_x              : 'left joystick X',\n                controller_joystick_left_y              : 'left joystick Y',\n                controller_joystick_right_direction     : 'right joystick direction',\n                controller_joystick_right_event         : 'right joystick event',\n                controller_joystick_right_x             : 'right joystick X',\n                controller_joystick_right_y             : 'right joystick Y',\n                drone_accel_x                           : 'Accel x',\n                drone_accel_y                           : 'Accel y',\n                drone_accel_z                           : 'Accel z',\n                drone_gyro_pitch                        : 'Gyro Pitch',\n                drone_gyro_roll                         : 'Gyro Roll',\n                drone_gyro_yaw                          : 'Gyro Yaw',\n                drone_attitude_pitch                    : 'Attitude Pitch',\n                drone_attitude_roll                     : 'Attitude Roll',\n                drone_attitude_yaw                      : 'Attitude Yaw',\n                drone_positionX                         : 'Position X',\n                drone_positionY                         : 'Position Y',\n                drone_positionZ                         : 'Position Z',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : 'Backward',\n                drone_control_quad_pitch_forward        : 'Forward',\n                drone_control_quad_roll_left            : 'Left',\n                drone_control_quad_roll_right           : 'Right',\n                drone_control_quad_throttle_down        : 'Down',\n                drone_control_quad_throttle_up          : 'Up',\n                drone_control_quad_yaw_ccw              : 'Counterclockwise',\n                drone_control_quad_yaw_cw               : 'clockwise',\n                drone_headless_normal                   : 'Normal',\n                drone_headless_headless                 : 'Headless',\n                drone_light_color_body                  : 'Body',\n                drone_light_manual_body_blue            : 'Blue',\n                drone_light_manual_body_green           : 'Green',\n                drone_light_manual_body_red             : 'Red',\n                drone_motor_rotation_clockwise          : 'Clockwise',\n                drone_motor_rotation_counterclockwise   : 'Counterclockwise',\n                drone_altitude                          : 'Altitude',\n                drone_range_height                      : 'Height',\n                drone_range_front                       : 'Distance from front obstacle',\n                drone_cardcolor_front_hue               : 'Front Hue',\n                drone_cardcolor_front_saturation        : 'Front Saturation',\n                drone_cardcolor_front_value             : 'Front Value',\n                drone_cardcolor_front_lightness         : 'Front Lightness',\n                drone_cardcolor_rear_hue                : 'Rear Hue',\n                drone_cardcolor_rear_saturation         : 'Rear Saturation',\n                drone_cardcolor_rear_value              : 'Rear Value',\n                drone_cardcolor_rear_lightness          : 'Rear Lightness',\n                drone_cardcolor_front_color             : 'Front Card Color',\n                drone_cardcolor_rear_color              : 'Rear Card Color',\n                drone_cardcolor_card                    : 'Card',\n                drone_state_mode_system                 : 'System Mode',\n                drone_state_mode_flight                 : 'Flight Mode',\n                drone_state_mode_control_flight         : 'Flight Control Mode',\n                drone_state_mode_movement               : 'mode movement',\n                drone_state_headless                    : 'Headless',\n                drone_state_control_speed               : 'Speed',\n                drone_state_sensor_orientation          : 'Sensor direction',\n                drone_state_battery                     : 'Battery',\n                entryhw_count_transfer_reserved         : 'Reserved data for transfer',\n            },\n\n            template: {\n                byrobot_drone_8_controller_buzzer_hz                : '%1 play Buzzer %2 Hz sound %3',\n                byrobot_drone_8_controller_buzzer_hz_delay          : '%1 play Buzzer %2 Hz sound for %3 second %4',\n                byrobot_drone_8_controller_buzzer_hz_reserve        : '%1 reserve to play Buzzer %2 Hz for %3 second %4',\n                byrobot_drone_8_controller_buzzer_off               : '%1 turn off the buzzer %2',\n                byrobot_drone_8_controller_buzzer_scale             : '%1 play %2 octave %3 %4',\n                byrobot_drone_8_controller_buzzer_scale_delay       : '%1 play %2 octave %3 for %4 second %5',\n                byrobot_drone_8_controller_buzzer_scale_reserve     : '%1 reserve to play %2 octave %3 for %4 second %5',\n                byrobot_drone_8_controller_display_clear            : 'clear controller display x:%1, y:%2, width:%3, height:%4, color:%5 %6',\n                byrobot_drone_8_controller_display_clear_all        : 'clear controller display with %1 color %2',\n                byrobot_drone_8_controller_display_draw_circle      : 'draw a circle x:%1, y:%2, radius:%3, %4, %5, %6',\n                byrobot_drone_8_controller_display_draw_line        : 'draw a line x1:%1, y1:%2, x2:%3, y2:%4, %5, %6 %7',\n                byrobot_drone_8_controller_display_draw_point       : 'draw a point x:%1, y:%2, color:%3 %4',\n                byrobot_drone_8_controller_display_draw_rect        : 'draw a rectangle x:%1, y:%2, width:%3, height:%4, %5, %6, %7 %8',\n                byrobot_drone_8_controller_display_draw_string      : 'draw a string x:%1, y:%2, font size:%3, %4, input:%5, %6',\n                byrobot_drone_8_controller_display_draw_string_align: 'draw aligned string x1:%1, x2:%2, y:%3, align:%4, font size:%5, %6, input:%7, %8',\n                byrobot_drone_8_controller_if_button_press          : 'when press %1',\n                byrobot_drone_8_controller_if_joystick_direction    : 'when %1 stick move to %2',\n                byrobot_drone_8_controller_light_color_input        : 'Controller LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_8_controller_light_color_select       : 'Controller LED Preset %1 %2 %3 %4',\n                byrobot_drone_8_controller_light_color_preset       : 'Controller LED %1 %2 %3',\n                byrobot_drone_8_controller_light_manual_single_input: 'Controller LED %1 Lightness %2 %3',\n                byrobot_drone_8_controller_light_manual_single_off  : 'Controller LED Off %1',\n                byrobot_drone_8_controller_value_button             : '%1',\n                byrobot_drone_8_controller_value_joystick           : '%1',\n                byrobot_drone_8_controller_vibrator_delay           : 'Vibrator %1 sec On, %2 sec Off for %3 sec run %4',\n                byrobot_drone_8_controller_vibrator_off             : 'Vibrator Off %1',\n                byrobot_drone_8_controller_vibrator_on_delay        : 'Vibrator %1 sec on %2',\n                byrobot_drone_8_controller_vibrator_on_reserve      : 'Vibrator %1 sec reserve %2',\n                byrobot_drone_8_controller_vibrator_reserve         : 'Vibrator %1 sec On, %2 sec Off for %3 sec reserve %4',\n                byrobot_drone_8_drone_control_headless              : 'Headless mode %1 %2',\n                byrobot_drone_8_drone_control_drone_landing         : 'Landing %1',\n                byrobot_drone_8_drone_control_drone_reset_heading   : 'Reset heading %1',\n                byrobot_drone_8_drone_control_drone_stop            : 'Stop flight %1',\n                byrobot_drone_8_drone_control_drone_takeoff         : 'Takeoff %1',\n                byrobot_drone_8_drone_control_quad_one              : 'Set %1 %2% %3',\n                byrobot_drone_8_drone_control_quad_one_delay        : 'Set %1 %2% %3 sec %4',\n                byrobot_drone_8_drone_control_quad                  : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5',\n                byrobot_drone_8_drone_control_quad_delay            : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% for %5sec %6',\n                byrobot_drone_8_drone_control_position_one          : 'Move %2 meter(s) %1 to %3 m/s %4',\n                byrobot_drone_8_drone_control_position_turn         : 'Rotate %2 degree(s) %1 to %3 deg/s %4',\n                byrobot_drone_8_drone_control_position_location     : 'Move %2 meter(s) %1, %4 meter(s) %3, %6 meter(s) %5 to %7 m/s %8',\n                byrobot_drone_8_drone_control_position_location_turn: 'Move %2 meter(s) %1, %4 meter(s) %3, %6 meter(s) %5 to %7 m/s, Rotate %9 degree(s) %8 to %10 deg/s %11',\n                byrobot_drone_8_drone_light_color_input             : 'Drone LED R %1, G %2, B %3 %4 %5 %6',\n                byrobot_drone_8_drone_light_color_select            : 'Drone LED Preset %1 %2 %3 %4',\n                byrobot_drone_8_drone_light_color_preset            : 'Drone LED %1 %2 %3',\n                byrobot_drone_8_drone_light_manual_single_input     : 'Drone LED %1 lightness %2 %3',\n                byrobot_drone_8_drone_light_manual_single_off       : 'Drone LED Off %1',\n                byrobot_drone_8_drone_motor_stop                    : 'Motor stop %1',\n                byrobot_drone_8_drone_motorsingle                   : 'No. %1 Motor rotate for %2 %3',\n                byrobot_drone_8_drone_motorsingle_input             : 'No. %1 Motor rotate for %2 %3',\n                byrobot_drone_8_drone_value_attitude                : '%1',\n                byrobot_drone_8_drone_value_motion                  : '%1',\n                byrobot_drone_8_drone_value_position                : '%1',\n                byrobot_drone_8_drone_value_sensor                  : '%1',\n                byrobot_drone_8_drone_value_card                    : '%1',\n                byrobot_drone_8_drone_value_etc                     : '%1',\n            },\n\n            Helper: {\n                byrobot_drone_8_controller_buzzer_hz                : '',\n                byrobot_drone_8_controller_buzzer_hz_delay          : '',\n                byrobot_drone_8_controller_buzzer_hz_reserve        : '',\n                byrobot_drone_8_controller_buzzer_off               : '',\n                byrobot_drone_8_controller_buzzer_scale             : '',\n                byrobot_drone_8_controller_buzzer_scale_delay       : '',\n                byrobot_drone_8_controller_buzzer_scale_reserve     : '',\n                byrobot_drone_8_controller_display_clear            : '',\n                byrobot_drone_8_controller_display_clear_all        : '',\n                byrobot_drone_8_controller_display_draw_circle      : '',\n                byrobot_drone_8_controller_display_draw_line        : '',\n                byrobot_drone_8_controller_display_draw_point       : '',\n                byrobot_drone_8_controller_display_draw_rect        : '',\n                byrobot_drone_8_controller_display_draw_string      : '',\n                byrobot_drone_8_controller_display_draw_string_align: '',\n                byrobot_drone_8_controller_if_button_press          : '',\n                byrobot_drone_8_controller_if_joystick_direction    : '',\n                byrobot_drone_8_controller_light_color_input        : '',\n                byrobot_drone_8_controller_light_color_select       : '',\n                byrobot_drone_8_controller_light_color_preset       : '',\n                byrobot_drone_8_controller_light_manual_single_input: '',\n                byrobot_drone_8_controller_light_manual_single_off  : '',\n                byrobot_drone_8_controller_value_button             : '',\n                byrobot_drone_8_controller_value_joystick           : '',\n                byrobot_drone_8_controller_vibrator_delay           : '',\n                byrobot_drone_8_controller_vibrator_off             : '',\n                byrobot_drone_8_controller_vibrator_on_delay        : '',\n                byrobot_drone_8_controller_vibrator_on_reserve      : '',\n                byrobot_drone_8_controller_vibrator_reserve         : '',\n                byrobot_drone_8_drone_control_headless              : '',\n                byrobot_drone_8_drone_control_drone_landing         : '',\n                byrobot_drone_8_drone_control_drone_reset_heading   : '',\n                byrobot_drone_8_drone_control_drone_stop            : '',\n                byrobot_drone_8_drone_control_drone_takeoff         : '',\n                byrobot_drone_8_drone_control_quad                  : '',\n                byrobot_drone_8_drone_control_quad_delay            : '',\n                byrobot_drone_8_drone_control_quad_one              : '',\n                byrobot_drone_8_drone_control_quad_one_delay        : '',\n                byrobot_drone_8_drone_control_position_one          : '',\n                byrobot_drone_8_drone_control_position_turn         : '',\n                byrobot_drone_8_drone_control_position_location     : '',\n                byrobot_drone_8_drone_control_position_location_turn: '',\n                byrobot_drone_8_drone_light_color_input             : '',\n                byrobot_drone_8_drone_light_color_select            : '',\n                byrobot_drone_8_drone_light_color_preset            : '',\n                byrobot_drone_8_drone_light_manual_single_input     : '',\n                byrobot_drone_8_drone_light_manual_single_off       : '',\n                byrobot_drone_8_drone_motor_stop                    : '',\n                byrobot_drone_8_drone_motorsingle                   : '',\n                byrobot_drone_8_drone_motorsingle_input             : '',\n                byrobot_drone_8_drone_value_attitude                : '',\n                byrobot_drone_8_drone_value_etc                     : '',\n                byrobot_drone_8_drone_value_motion                  : '',\n                byrobot_drone_8_drone_value_position                : '',\n                byrobot_drone_8_drone_value_sensor                  : '',\n                byrobot_drone_8_drone_value_card                    : '',\n            },\n        },\n    };\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.byrobot_drone_8.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/byrobot_drone_8.png\",   // 배경 이미지\n        width  : 256,                        // 이미지의 폭\n        height : 256,                        // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeFlight                        : { name: Lang.Blocks.monitor_state_modeFlight,                          type: 'input', pos: { x: 0, y: 0 } },\n            state_modeControlFlight                 : { name: Lang.Blocks.monitor_state_modeControlFlight,                   type: 'input', pos: { x: 0, y: 0 } },\n            state_modeMovement                      : { name: Lang.Blocks.monitor_state_modeMovement,                        type: 'input', pos: { x: 0, y: 0 } },\n            state_headless                          : { name: Lang.Blocks.monitor_state_headless,                            type: 'input', pos: { x: 0, y: 0 } },\n            state_controlSpeed                      : { name: Lang.Blocks.monitor_state_controlSpeed,                        type: 'input', pos: { x: 0, y: 0 } },\n            state_sensorOrientation                 : { name: Lang.Blocks.monitor_state_sensorOrientation,                   type: 'input', pos: { x: 0, y: 0 } },\n            state_battery                           : { name: Lang.Blocks.monitor_state_battery,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelX                           : { name: Lang.Blocks.monitor_motion_accelX,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelY                           : { name: Lang.Blocks.monitor_motion_accelY,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelZ                           : { name: Lang.Blocks.monitor_motion_accelZ,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroRoll                         : { name: Lang.Blocks.monitor_motion_gyroRoll,                           type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroPitch                        : { name: Lang.Blocks.monitor_motion_gyroPitch,                          type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroYaw                          : { name: Lang.Blocks.monitor_motion_gyroYaw,                            type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleRoll                        : { name: Lang.Blocks.monitor_motion_angleRoll,                          type: 'input', pos: { x: 0, y: 0 } },\n            motion_anglePitch                       : { name: Lang.Blocks.monitor_motion_anglePitch,                         type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleYaw                         : { name: Lang.Blocks.monitor_motion_angleYaw,                           type: 'input', pos: { x: 0, y: 0 } },\n            range_front                             : { name: Lang.Blocks.monitor_range_front,                               type: 'input', pos: { x: 0, y: 0 } },\n            range_bottom                            : { name: Lang.Blocks.monitor_range_bottom,                              type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontHue                      : { name: Lang.Blocks.monitor_cardColor_frontHue,                        type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontSaturation               : { name: Lang.Blocks.monitor_cardColor_frontSaturation,                 type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontValue                    : { name: Lang.Blocks.monitor_cardColor_frontValue,                      type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontLightness                : { name: Lang.Blocks.monitor_cardColor_frontLightness,                  type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearHue                       : { name: Lang.Blocks.monitor_cardColor_rearHue,                         type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearSaturation                : { name: Lang.Blocks.monitor_cardColor_rearSaturation,                  type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearValue                     : { name: Lang.Blocks.monitor_cardColor_rearValue,                       type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearLightness                 : { name: Lang.Blocks.monitor_cardColor_rearLightness,                   type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontColor                    : { name: Lang.Blocks.monitor_cardColor_frontColor,                      type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearColor                     : { name: Lang.Blocks.monitor_cardColor_rearColor,                       type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_card                          : { name: Lang.Blocks.monitor_cardColor_card,                            type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionX  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionX,    type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionY  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionY,    type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionZ  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionZ,    type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_altitude   : { name: Lang.Blocks.monitor_informationAssembledForEntry_altitude,     type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_rangeHeight: { name: Lang.Blocks.monitor_informationAssembledForEntry_rangeHeight,  type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_x                         : { name: Lang.Blocks.monitor_joystick_left_x,                           type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_y                         : { name: Lang.Blocks.monitor_joystick_left_y,                           type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_direction                 : { name: Lang.Blocks.monitor_joystick_left_direction,                   type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_event                     : { name: Lang.Blocks.monitor_joystick_left_event,                       type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_x                        : { name: Lang.Blocks.monitor_joystick_right_x,                          type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_y                        : { name: Lang.Blocks.monitor_joystick_right_y,                          type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_direction                : { name: Lang.Blocks.monitor_joystick_right_direction,                  type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_event                    : { name: Lang.Blocks.monitor_joystick_right_event,                      type: 'input', pos: { x: 0, y: 0 } },\n            button_button                           : { name: Lang.Blocks.monitor_button_button,                             type: 'input', pos: { x: 0, y: 0 } },\n            button_event                            : { name: Lang.Blocks.monitor_button_event,                              type: 'input', pos: { x: 0, y: 0 } },\n            entryhw_countTransferReserved           : { name: Lang.Blocks.monitor_entryhw_countTransferReserved,             type: 'output', pos: { x: 0, y: 0 } },\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both',   // 표시 모드\n    };\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 블록명(다른 장치의 블록 이름과 달라야 함)\n ***************************************************************************************/\nEntry.byrobot_drone_8.blockMenuBlocks = [\n    'byrobot_drone_8_drone_value_attitude',\n    'byrobot_drone_8_drone_value_motion',\n    'byrobot_drone_8_drone_value_position',\n    'byrobot_drone_8_drone_value_sensor',\n    'byrobot_drone_8_drone_value_card',\n    'byrobot_drone_8_drone_value_etc',\n    'byrobot_drone_8_controller_value_button',\n    'byrobot_drone_8_controller_value_joystick',\n    'byrobot_drone_8_controller_if_button_press',\n    'byrobot_drone_8_controller_if_joystick_direction',\n    'byrobot_drone_8_drone_control_drone_takeoff',\n    'byrobot_drone_8_drone_control_drone_landing',\n    'byrobot_drone_8_drone_control_drone_stop',\n    'byrobot_drone_8_drone_control_headless',\n    'byrobot_drone_8_drone_control_drone_reset_heading',\n    'byrobot_drone_8_drone_control_quad_one',\n    'byrobot_drone_8_drone_control_quad_one_delay',\n    'byrobot_drone_8_drone_control_quad',\n    'byrobot_drone_8_drone_control_quad_delay',\n    'byrobot_drone_8_drone_control_position_one',\n    'byrobot_drone_8_drone_control_position_turn',\n    'byrobot_drone_8_drone_control_position_location',\n    'byrobot_drone_8_drone_control_position_location_turn',\n    'byrobot_drone_8_drone_motor_stop',\n    'byrobot_drone_8_drone_motorsingle',\n    'byrobot_drone_8_drone_motorsingle_input',\n    'byrobot_drone_8_drone_light_manual_single_off',\n    'byrobot_drone_8_drone_light_manual_single_input',\n    'byrobot_drone_8_drone_light_color_preset',\n    'byrobot_drone_8_drone_light_color_input',\n    'byrobot_drone_8_drone_light_color_select',\n    'byrobot_drone_8_controller_light_manual_single_off',\n    'byrobot_drone_8_controller_light_manual_single_input',\n    'byrobot_drone_8_controller_light_color_preset',\n    'byrobot_drone_8_controller_light_color_input',\n    'byrobot_drone_8_controller_light_color_select',\n    'byrobot_drone_8_controller_display_clear_all',\n    'byrobot_drone_8_controller_display_clear',\n    'byrobot_drone_8_controller_display_draw_point',\n    'byrobot_drone_8_controller_display_draw_line',\n    'byrobot_drone_8_controller_display_draw_rect',\n    'byrobot_drone_8_controller_display_draw_circle',\n    'byrobot_drone_8_controller_display_draw_string',\n    'byrobot_drone_8_controller_display_draw_string_align',\n    'byrobot_drone_8_controller_buzzer_off',\n    'byrobot_drone_8_controller_buzzer_scale',\n    'byrobot_drone_8_controller_buzzer_scale_delay',\n    'byrobot_drone_8_controller_buzzer_scale_reserve',\n    'byrobot_drone_8_controller_buzzer_hz',\n    'byrobot_drone_8_controller_buzzer_hz_delay',\n    'byrobot_drone_8_controller_buzzer_hz_reserve',\n    'byrobot_drone_8_controller_vibrator_off',\n    'byrobot_drone_8_controller_vibrator_on_delay',\n    'byrobot_drone_8_controller_vibrator_on_reserve',\n    'byrobot_drone_8_controller_vibrator_delay',\n    'byrobot_drone_8_controller_vibrator_reserve',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 정의\n ***************************************************************************************/\nEntry.byrobot_drone_8.getBlocks = function()\n{\n    return {\n        byrobot_drone_8_drone_value_attitude: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_attitude_roll,   'motion_angleRoll'],\n                        [Lang.Blocks.drone_attitude_pitch,  'motion_anglePitch'],\n                        [Lang.Blocks.drone_attitude_yaw,    'motion_angleYaw'],\n                    ],\n                    value     : 'motion_angleRoll',                            // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_value_attitude',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.attitude(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_attitude_roll,   'motion_angleRoll'],\n                                    [Lang.Blocks.drone_attitude_pitch,  'motion_anglePitch'],\n                                    [Lang.Blocks.drone_attitude_yaw,    'motion_angleYaw'],\n                                ],\n                                value     : 'motion_angleRoll',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_value_motion: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_accel_x,     'motion_accelX'],\n                        [Lang.Blocks.drone_accel_y,     'motion_accelY'],\n                        [Lang.Blocks.drone_accel_z,     'motion_accelZ'],\n                        [Lang.Blocks.drone_gyro_roll,   'motion_gyroRoll'],\n                        [Lang.Blocks.drone_gyro_pitch,  'motion_gyroPitch'],\n                        [Lang.Blocks.drone_gyro_yaw,    'motion_gyroYaw'],\n                    ],\n                    value     : 'motion_accelX',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_value_motion',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.motion(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_accel_x,     'motion_accelX'],\n                                    [Lang.Blocks.drone_accel_y,     'motion_accelY'],\n                                    [Lang.Blocks.drone_accel_z,     'motion_accelZ'],\n                                    [Lang.Blocks.drone_gyro_roll,   'motion_gyroRoll'],\n                                    [Lang.Blocks.drone_gyro_pitch,  'motion_gyroPitch'],\n                                    [Lang.Blocks.drone_gyro_yaw,    'motion_gyroYaw'],\n                                ],\n                                value     : 'motion_accelX',                               // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_value_position: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_positionX,       'informationAssembledForEntry_positionX'],\n                        [Lang.Blocks.drone_positionY,       'informationAssembledForEntry_positionY'],\n                        [Lang.Blocks.drone_positionZ,       'informationAssembledForEntry_positionZ'],\n                    ],\n                    value     : 'informationAssembledForEntry_positionX',      // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_value_position',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.position(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_positionX,       'informationAssembledForEntry_positionX'],\n                                    [Lang.Blocks.drone_positionY,       'informationAssembledForEntry_positionY'],\n                                    [Lang.Blocks.drone_positionZ,       'informationAssembledForEntry_positionZ'],\n                                ],\n                                value     : 'informationAssembledForEntry_positionX',      // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_value_sensor: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_range_front,     'range_front'],\n                        [Lang.Blocks.drone_range_height,    'informationAssembledForEntry_rangeHeight'],\n                        [Lang.Blocks.drone_altitude,        'informationAssembledForEntry_altitude'],\n                    ],\n                    value     : 'range_front',                                 // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_value_sensor',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.sensor(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_range_front,     'range_front'],\n                                    [Lang.Blocks.drone_range_height,    'informationAssembledForEntry_rangeHeight'],\n                                    [Lang.Blocks.drone_altitude,        'informationAssembledForEntry_altitude'],\n                                ],\n                                value     : 'range_front',                                 // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_value_card: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_cardcolor_front_color,            'cardColor_frontColor'],\n                        [Lang.Blocks.drone_cardcolor_rear_color,             'cardColor_rearColor'],\n                        [Lang.Blocks.drone_cardcolor_card,                   'cardColor_card'],\n                        [Lang.Blocks.drone_cardcolor_front_hue,              'cardColor_frontHue'],\n                        [Lang.Blocks.drone_cardcolor_front_saturation,       'cardColor_frontSaturation'],\n                        [Lang.Blocks.drone_cardcolor_front_value,            'cardColor_frontValue'],\n                        [Lang.Blocks.drone_cardcolor_front_lightness,        'cardColor_frontLightness'],\n                        [Lang.Blocks.drone_cardcolor_rear_hue,               'cardColor_rearHue'],\n                        [Lang.Blocks.drone_cardcolor_rear_saturation,        'cardColor_rearSaturation'],\n                        [Lang.Blocks.drone_cardcolor_rear_value,             'cardColor_rearValue'],\n                        [Lang.Blocks.drone_cardcolor_rear_lightness,         'cardColor_rearLightness'],\n                    ],\n                    value     : 'cardColor_frontColor',                        // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_value_card',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.card(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_cardcolor_front_color,            'cardColor_frontColor'],\n                                    [Lang.Blocks.drone_cardcolor_rear_color,             'cardColor_rearColor'],\n                                    [Lang.Blocks.drone_cardcolor_card,                   'cardColor_card'],\n                                    [Lang.Blocks.drone_cardcolor_front_hue,              'cardColor_frontHue'],\n                                    [Lang.Blocks.drone_cardcolor_front_saturation,       'cardColor_frontSaturation'],\n                                    [Lang.Blocks.drone_cardcolor_front_value,            'cardColor_frontValue'],\n                                    [Lang.Blocks.drone_cardcolor_front_lightness,        'cardColor_frontLightness'],\n                                    [Lang.Blocks.drone_cardcolor_rear_hue,               'cardColor_rearHue'],\n                                    [Lang.Blocks.drone_cardcolor_rear_saturation,        'cardColor_rearSaturation'],\n                                    [Lang.Blocks.drone_cardcolor_rear_value,             'cardColor_rearValue'],\n                                    [Lang.Blocks.drone_cardcolor_rear_lightness,         'cardColor_rearLightness'],\n                                ],\n                                value     : 'cardColor_frontColor',                        // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_value_etc: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_state_mode_flight,           'state_modeFlight'],\n                        [Lang.Blocks.drone_state_mode_control_flight,   'state_modeControlFlight'],\n                        [Lang.Blocks.drone_state_mode_movement,         'state_modeMovement'],\n                        [Lang.Blocks.drone_state_headless,              'state_headless'],\n                        [Lang.Blocks.drone_state_control_speed,         'state_controlSpeed'],\n                        [Lang.Blocks.drone_state_sensor_orientation,    'state_sensorOrientation'],\n                        [Lang.Blocks.drone_state_battery,               'state_battery'],\n                    ],\n                    value     : 'state_battery',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_value_etc',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.state(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_state_mode_flight,           'state_modeFlight'],\n                                    [Lang.Blocks.drone_state_mode_control_flight,   'state_modeControlFlight'],\n                                    [Lang.Blocks.drone_state_mode_movement,         'state_modeMovement'],\n                                    [Lang.Blocks.drone_state_headless,              'state_headless'],\n                                    [Lang.Blocks.drone_state_control_speed,         'state_controlSpeed'],\n                                    [Lang.Blocks.drone_state_sensor_orientation,    'state_sensorOrientation'],\n                                    [Lang.Blocks.drone_state_battery,               'state_battery'],\n                                ],\n                                value     : 'state_battery',                               // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_value_button: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button,         'button_button'],\n                        [Lang.Blocks.controller_button_event,   'button_event'],\n                    ],\n                    value     : 'button_button',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_controller_value_button',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.button(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_button,         'button_button'],\n                                    [Lang.Blocks.controller_button_event,   'button_event'],\n                                ],\n                                value     : 'button_button',                               // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_value_joystick: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_left_x,            'joystick_left_x'],\n                        [Lang.Blocks.controller_joystick_left_y,            'joystick_left_y'],\n                        [Lang.Blocks.controller_joystick_left_direction,    'joystick_left_direction'],\n                        [Lang.Blocks.controller_joystick_left_event,        'joystick_left_event'],\n                        [Lang.Blocks.controller_joystick_right_x,           'joystick_right_x'],\n                        [Lang.Blocks.controller_joystick_right_y,           'joystick_right_y'],\n                        [Lang.Blocks.controller_joystick_right_direction,   'joystick_right_direction'],\n                        [Lang.Blocks.controller_joystick_right_event,       'joystick_right_event'],\n                    ],\n                    value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_controller_value_joystick',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.joystick(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_joystick_left_x,            'joystick_left_x'],\n                                    [Lang.Blocks.controller_joystick_left_y,            'joystick_left_y'],\n                                    [Lang.Blocks.controller_joystick_left_direction,    'joystick_left_direction'],\n                                    [Lang.Blocks.controller_joystick_left_event,        'joystick_left_event'],\n                                    [Lang.Blocks.controller_joystick_right_x,           'joystick_right_x'],\n                                    [Lang.Blocks.controller_joystick_right_y,           'joystick_right_y'],\n                                    [Lang.Blocks.controller_joystick_right_direction,   'joystick_right_direction'],\n                                    [Lang.Blocks.controller_joystick_right_event,       'joystick_right_event'],\n                                ],\n                                value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_if_button_press: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button_front_left_top,      '1'],\n                        [Lang.Blocks.controller_button_front_left_bottom,   '2'],\n                        [Lang.Blocks.controller_button_front_right_top,     '4'],\n                        [Lang.Blocks.controller_button_front_right_bottom,  '8'],\n                        [Lang.Blocks.controller_button_top_left,            '16'],\n                        [Lang.Blocks.controller_button_top_right,           '32'],\n                        [Lang.Blocks.controller_button_center_up,           '64'],\n                        [Lang.Blocks.controller_button_center_left,         '128'],\n                        [Lang.Blocks.controller_button_center_right,        '256'],\n                        [Lang.Blocks.controller_button_center_down,         '512'],\n                        [Lang.Blocks.controller_button_bottom_left,         '1024'],\n                        [Lang.Blocks.controller_button_bottom_right,        '2048'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'byrobot_drone_8_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const read        = Entry.hw.portData;\n                const button      = 'button_button';    // paramsKeyMap에 정의된 이름 사용\n                const buttonevent = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.button_pressed(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_button_front_left_top,      '1'],\n                                    [Lang.Blocks.controller_button_front_left_bottom,   '2'],\n                                    [Lang.Blocks.controller_button_front_right_top,     '4'],\n                                    [Lang.Blocks.controller_button_front_right_bottom,  '8'],\n                                    [Lang.Blocks.controller_button_top_left,            '16'],\n                                    [Lang.Blocks.controller_button_top_right,           '32'],\n                                    [Lang.Blocks.controller_button_center_up,           '64'],\n                                    [Lang.Blocks.controller_button_center_left,         '128'],\n                                    [Lang.Blocks.controller_button_center_right,        '256'],\n                                    [Lang.Blocks.controller_button_center_down,         '512'],\n                                    [Lang.Blocks.controller_button_bottom_left,         '1024'],\n                                    [Lang.Blocks.controller_button_bottom_right,        '2048'],\n                                ],\n                                value     : '1',                                           // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_if_joystick_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.common_right, 'joystick_right_direction'],\n                    ],\n                    value     : 'joystick_left_direction',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_direction_left_up,     '17'],\n                        [Lang.Blocks.controller_joystick_direction_up,          '18'],\n                        [Lang.Blocks.controller_joystick_direction_right_up,    '20'],\n                        [Lang.Blocks.controller_joystick_direction_left,        '33'],\n                        [Lang.Blocks.controller_joystick_direction_center,      '34'],\n                        [Lang.Blocks.controller_joystick_direction_right,       '36'],\n                        [Lang.Blocks.controller_joystick_direction_left_down,   '65'],\n                        [Lang.Blocks.controller_joystick_direction_down,        '66'],\n                        [Lang.Blocks.controller_joystick_direction_right_down,  '68'],\n                    ],\n                    value     : '34',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_8_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE   : 0,\n                DIRECTION: 1,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const read   = Entry.hw.portData;\n                const device = script.getField('DEVICE');  // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION'))\n                {\n                    return true;\n                }\n                else\n                {\n                    return false;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.joystick_direction(%1, %2)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_left, 'joystick_left_direction'],\n                                    [Lang.Blocks.common_right, 'joystick_right_direction'],\n                                ],\n                                value     : 'joystick_left_direction',                     // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_joystick_direction_left_up,     '17'],\n                                    [Lang.Blocks.controller_joystick_direction_up,          '18'],\n                                    [Lang.Blocks.controller_joystick_direction_right_up,    '20'],\n                                    [Lang.Blocks.controller_joystick_direction_left,        '33'],\n                                    [Lang.Blocks.controller_joystick_direction_center,      '34'],\n                                    [Lang.Blocks.controller_joystick_direction_right,       '36'],\n                                    [Lang.Blocks.controller_joystick_direction_left_down,   '65'],\n                                    [Lang.Blocks.controller_joystick_direction_down,        '66'],\n                                    [Lang.Blocks.controller_joystick_direction_right_down,  '68'],\n                                ],\n                                value     : '34',                                          // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_8_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'controller_light',\n            isNotFor    : ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setLightManual(script, 0x20, 0xffff, 0);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Controller.light_off()',\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_drone_8_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.light_color_preset(%1, %2)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_brightness_on,    '220'],\n                                    [Lang.Blocks.common_light_brightness_off,   '0'],\n                                    [Lang.Blocks.common_light_brightness_b25,   '75'],\n                                    [Lang.Blocks.common_light_brightness_b50,   '125'],\n                                    [Lang.Blocks.common_light_brightness_b75,   '200'],\n                                    [Lang.Blocks.common_light_brightness_b100,  '255'],\n                                ],\n                                value     : '220',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x07'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x20, flags, brightness);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.light_color_manual(%1, %2)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval = script.getNumberValue('INTERVAL');\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                return Entry.byrobot_base.setLightModeColor(script, 0x20, mode, interval, red, green, blue);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.light_color_input(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'byrobot_drone_8_controller_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'controller_light',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.light_color_select(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'drone_light',\n            isNotFor    : ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setLightManual(script, 0x10, 0xff, 0);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.light_off()',\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'byrobot_drone_8_drone_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_preset(%1, %2)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_brightness_on,    '220'],\n                                    [Lang.Blocks.common_light_brightness_off,   '0'],\n                                    [Lang.Blocks.common_light_brightness_b25,   '75'],\n                                    [Lang.Blocks.common_light_brightness_b50,   '125'],\n                                    [Lang.Blocks.common_light_brightness_b75,   '200'],\n                                    [Lang.Blocks.common_light_brightness_b100,  '255'],\n                                ],\n                                value     : '200',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x3F'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x10, flags, brightness);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_manual(%1, %2)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_drone_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                const interval = script.getNumberValue('INTERVAL');\n                return Entry.byrobot_base.setLightModeColor(script, 0x10, mode, interval, red, green, blue);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_input(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'byrobot_drone_8_drone_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'drone_light',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_select(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_display_clear_all: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_8_controller_display_clear_all',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayClearAll(script, 0x20, pixel);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_clear_all(%1)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_display_clear: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_display_clear',\n            },\n            paramsKeyMap: {\n                X     : 0,\n                Y     : 1,\n                WIDTH : 2,\n                HEIGHT: 3,\n                PIXEL : 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const x      = script.getNumberValue('X');\n                const y      = script.getNumberValue('Y');\n                const width  = script.getNumberValue('WIDTH');\n                const height = script.getNumberValue('HEIGHT');\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayClear(script, 0x20, pixel, x, y, width, height);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_clear(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_display_draw_point: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_display_draw_point',\n            },\n            paramsKeyMap: {\n                X    : 0,\n                Y    : 1,\n                PIXEL: 2,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const x     = script.getNumberValue('X');\n                const y     = script.getNumberValue('Y');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                return Entry.byrobot_base.setDisplayDrawPoint(script, 0x20, x, y, pixel);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_point(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_display_draw_line: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    { type: 'text', params: ['96'] },\n                    { type: 'text', params: ['48'] },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_display_draw_line',\n            },\n            paramsKeyMap: {\n                X1   : 0,\n                Y1   : 1,\n                X2   : 2,\n                Y2   : 3,\n                PIXEL: 4,\n                LINE : 5,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const x1    = script.getNumberValue('X1');\n                const y1    = script.getNumberValue('Y1');\n                const x2    = script.getNumberValue('X2');\n                const y2    = script.getNumberValue('Y2');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                const line  = parseInt(script.getField('LINE'), 10);\n                return Entry.byrobot_base.setDisplayDrawLine(script, 0x20, x1, y1, x2, y2, pixel, line);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_line(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_line_solid, '0'],\n                                    [Lang.Blocks.controller_display_line_dotted, '1'],\n                                    [Lang.Blocks.controller_display_line_dashed, '2'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_display_draw_rect: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_display_draw_rect',\n            },\n            paramsKeyMap: {\n                X       : 0,\n                Y       : 1,\n                WIDTH   : 2,\n                HEIGHT  : 3,\n                PIXEL   : 4,\n                FLAGFILL: 5,\n                LINE    : 6,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const x        = script.getNumberValue('X');\n                const y        = script.getNumberValue('Y');\n                const width    = script.getNumberValue('WIDTH');\n                const height   = script.getNumberValue('HEIGHT');\n                const pixel    = parseInt(script.getField('PIXEL'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n                const line     = parseInt(script.getField('LINE'), 10);\n                return Entry.byrobot_base.setDisplayDrawRect(script, 0x20, x, y, width, height, pixel, flagFill, line);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_rect(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_flagfill_off, '0'],\n                                    [Lang.Blocks.controller_display_flagfill_on, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_line_solid, '0'],\n                                    [Lang.Blocks.controller_display_line_dotted, '1'],\n                                    [Lang.Blocks.controller_display_line_dashed, '2'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_display_draw_circle: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['24'] },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_display_draw_circle',\n            },\n            paramsKeyMap: {\n                X       : 0,\n                Y       : 1,\n                RADIUS  : 2,\n                PIXEL   : 3,\n                FLAGFILL: 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const x        = script.getNumberValue('X');\n                const y        = script.getNumberValue('Y');\n                const radius   = script.getNumberValue('RADIUS');\n                const pixel    = parseInt(script.getField('PIXEL'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n                return Entry.byrobot_base.setDisplayDrawCircle(script, 0x20, x, y, radius, pixel, flagFill);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_circle(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_flagfill_off, '0'],\n                                    [Lang.Blocks.controller_display_flagfill_on, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_display_draw_string: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_font_5x8, '0'],\n                        [Lang.Blocks.controller_display_font_10x16, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['39'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                    { type: 'text', params: ['HELLO'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_display_draw_string',\n            },\n            paramsKeyMap: {\n                X     : 0,\n                Y     : 1,\n                FONT  : 2,\n                PIXEL : 3,\n                STRING: 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const x      = script.getNumberValue('X');\n                const y      = script.getNumberValue('Y');\n                const font   = parseInt(script.getField('FONT'), 10);\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                const string = script.getStringValue('STRING');\n                return Entry.byrobot_base.setDisplayDrawString(script, 0x20, x, y, font, pixel, string);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_string(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_font_5x8, '0'],\n                                    [Lang.Blocks.controller_display_font_10x16, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_display_draw_string_align: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_align_left, '0'],\n                        [Lang.Blocks.controller_display_align_center, '1'],\n                        [Lang.Blocks.controller_display_align_right, '2'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_font_5x8, '0'],\n                        [Lang.Blocks.controller_display_font_10x16, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0'] },\n                    { type: 'text', params: ['128'] },\n                    { type: 'text', params: ['42'] },\n                    null,\n                    null,\n                    null,\n                    { type: 'text', params: ['DRONE'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_display_draw_string_align',\n            },\n            paramsKeyMap: {\n                XSTART: 0,\n                XEND  : 1,\n                Y     : 2,\n                ALIGN : 3,\n                FONT  : 4,\n                PIXEL : 5,\n                STRING: 6,\n            },\n            class   : 'controller_display',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const xStart = script.getNumberValue('XSTART');\n                const xEnd   = script.getNumberValue('XEND');\n                const y      = script.getNumberValue('Y');\n                const align  = parseInt(script.getField('ALIGN'), 10);\n                const font   = parseInt(script.getField('FONT'), 10);\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                const string = script.getStringValue('STRING');\n                return Entry.byrobot_base.setDisplayDrawStringAlign(script, 0x20, xStart, xEnd, y, align, font, pixel, string);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_string_align(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_align_left, '0'],\n                                    [Lang.Blocks.controller_display_align_center, '1'],\n                                    [Lang.Blocks.controller_display_align_right, '2'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_font_5x8, '0'],\n                                    [Lang.Blocks.controller_display_font_10x16, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_buzzer_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_8_controller_buzzer_off',\n            },\n            paramsKeyMap: {\n                TARGET: 0\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                return Entry.byrobot_base.setBuzzerStop(script, target);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_off(%1)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_buzzer_scale: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null, null],\n                type  : 'byrobot_drone_8_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                OCTAVE: 1,\n                SCALE : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, target, 60000, false, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, target, octave, scale, 60000, false, true);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_scale(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    ['1', '0'],\n                                    ['2', '1'],\n                                    ['3', '2'],\n                                    ['4', '3'],\n                                    ['5', '4'],\n                                    ['6', '5'],\n                                    ['7', '6'],\n                                    ['8', '7'],\n                                ],\n                                value     : '4',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_buzzer_mute, '-1'],\n                                    [Lang.Blocks.controller_buzzer_c,    '0'],\n                                    [Lang.Blocks.controller_buzzer_cs,   '1'],\n                                    [Lang.Blocks.controller_buzzer_d,    '2'],\n                                    [Lang.Blocks.controller_buzzer_ds,   '3'],\n                                    [Lang.Blocks.controller_buzzer_e,    '4'],\n                                    [Lang.Blocks.controller_buzzer_f,    '5'],\n                                    [Lang.Blocks.controller_buzzer_fs,   '6'],\n                                    [Lang.Blocks.controller_buzzer_g,    '7'],\n                                    [Lang.Blocks.controller_buzzer_gs,   '8'],\n                                    [Lang.Blocks.controller_buzzer_a,    '9'],\n                                    [Lang.Blocks.controller_buzzer_as,   '10'],\n                                    [Lang.Blocks.controller_buzzer_b,    '11'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_buzzer_scale_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                OCTAVE: 1,\n                SCALE : 2,\n                TIME  : 3,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, target, time, true, true);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, target, octave, scale, time, true, true);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_scale_delay(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    ['1', '0'],\n                                    ['2', '1'],\n                                    ['3', '2'],\n                                    ['4', '3'],\n                                    ['5', '4'],\n                                    ['6', '5'],\n                                    ['7', '6'],\n                                    ['8', '7'],\n                                ],\n                                value     : '4',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_buzzer_mute, '-1'],\n                                    [Lang.Blocks.controller_buzzer_c,    '0'],\n                                    [Lang.Blocks.controller_buzzer_cs,   '1'],\n                                    [Lang.Blocks.controller_buzzer_d,    '2'],\n                                    [Lang.Blocks.controller_buzzer_ds,   '3'],\n                                    [Lang.Blocks.controller_buzzer_e,    '4'],\n                                    [Lang.Blocks.controller_buzzer_f,    '5'],\n                                    [Lang.Blocks.controller_buzzer_fs,   '6'],\n                                    [Lang.Blocks.controller_buzzer_g,    '7'],\n                                    [Lang.Blocks.controller_buzzer_gs,   '8'],\n                                    [Lang.Blocks.controller_buzzer_a,    '9'],\n                                    [Lang.Blocks.controller_buzzer_as,   '10'],\n                                    [Lang.Blocks.controller_buzzer_b,    '11'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_buzzer_scale_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                OCTAVE: 1,\n                SCALE : 2,\n                TIME  : 3,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.byrobot_base.setBuzzerMute(script, target, time, false, false);\n                } else {\n                    return Entry.byrobot_base.setBuzzerScale(script, target, octave, scale, time, false, false);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_scale_reserve(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    ['1', '0'],\n                                    ['2', '1'],\n                                    ['3', '2'],\n                                    ['4', '3'],\n                                    ['5', '4'],\n                                    ['6', '5'],\n                                    ['7', '6'],\n                                    ['8', '7'],\n                                ],\n                                value     : '4',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_buzzer_mute, '-1'],\n                                    [Lang.Blocks.controller_buzzer_c,    '0'],\n                                    [Lang.Blocks.controller_buzzer_cs,   '1'],\n                                    [Lang.Blocks.controller_buzzer_d,    '2'],\n                                    [Lang.Blocks.controller_buzzer_ds,   '3'],\n                                    [Lang.Blocks.controller_buzzer_e,    '4'],\n                                    [Lang.Blocks.controller_buzzer_f,    '5'],\n                                    [Lang.Blocks.controller_buzzer_fs,   '6'],\n                                    [Lang.Blocks.controller_buzzer_g,    '7'],\n                                    [Lang.Blocks.controller_buzzer_gs,   '8'],\n                                    [Lang.Blocks.controller_buzzer_a,    '9'],\n                                    [Lang.Blocks.controller_buzzer_as,   '10'],\n                                    [Lang.Blocks.controller_buzzer_b,    '11'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_buzzer_hz: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'text', params: ['1000'] }, null],\n                type  : 'byrobot_drone_8_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                HZ    : 1,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const hz     = script.getNumberValue('HZ');\n                return Entry.byrobot_base.setBuzzerHz(script, target, hz, 60000, false, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_hz(%1, %2)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_buzzer_hz_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'text', params: ['1000'] }, { type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_8_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                HZ    : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const hz     = script.getNumberValue('HZ');\n                const time   = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, target, hz, time, true, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_hz_delay(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_buzzer_hz_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'text', params: ['1000'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                HZ    : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const hz     = script.getNumberValue('HZ');\n                const time   = script.getNumberValue('TIME') * 1000;\n                return Entry.byrobot_base.setBuzzerHz(script, target, hz, time, false, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_hz_reserve(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_vibrator_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_8_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class       : 'vibrator',\n            isNotFor    : ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setVibratorStop(script, 0x20);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Controller.vibrator_off()',\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_vibrator_on_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_8_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, true, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.vibrator_on_delay(%1)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_vibrator_on_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'byrobot_drone_8_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, 0, timeOn, false, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.vibrator_on_reserve(%1)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_vibrator_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, true, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.vibrator_delay(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_controller_vibrator_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.byrobot_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, false, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.vibrator_reserve(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_motor_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'motor',\n            isNotFor    : ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.motor_stop()',\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_motorsingle: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type      : 'Dropdown',\n                    options   : [['1(FR)', '0'], ['2(RR)', '1'], ['3(RL)', '2'], ['4(FL)', '3']],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'text', params: ['120'] }, null],\n                type  : 'byrobot_drone_8_drone_motorsingle',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const motorIndex = parseInt(script.getField('MOTORINDEX'), 10);\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.byrobot_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.motor_single(%1, %2)',\n                        textParams: [\n                            {\n                                type      : 'Dropdown',\n                                options   : [['1(FR)', '0'], ['2(RR)', '1'], ['3(RL)', '2'], ['4(FL)', '3']],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_motorsingle_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, { type: 'text', params: ['120'] }, null],\n                type  : 'byrobot_drone_8_drone_motorsingle_input',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const motorIndex = script.getNumberValue('MOTORINDEX') - 1;\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.byrobot_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.motor_single_input(%1, %2)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_drone_takeoff: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_control_drone_takeoff',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x11, 5000); // 0x11 : FlightEvent::TakeOff\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.takeoff()',\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_drone_landing: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_control_drone_landing',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x12, 5000); // 0x12 : FlightEvent::Landing\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.landing()',\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_drone_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_control_drone_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.stop()',\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_headless: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_headless_headless, '1'],\n                        [Lang.Blocks.drone_headless_normal,   '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'byrobot_drone_8_drone_control_headless',\n            },\n            paramsKeyMap: {\n                HEADLESS: 0,\n            },\n            class   : 'control_flight',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const headless = script.getField('HEADLESS');\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x03, headless);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.headless(%1)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_headless_headless, '1'],\n                                    [Lang.Blocks.drone_headless_normal,   '2'],\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_drone_reset_heading: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'byrobot_drone_8_drone_control_drone_reset_heading',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x07, 0xA0); // 0x22 : CommandType::FlightEvent  // 0xA0 : FlightEvent::ResetHeading\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.reset_heading()',\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_quad_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['0'] }, null],\n                type  : 'byrobot_drone_8_drone_control_quad_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, 0, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_quad_one(%1, %2)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                                    [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                                    [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                                    [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                                ],\n                                value     : 'control_quad8_pitch',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_quad_one_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['100'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_drone_control_quad_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n                TIME         : 2,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n                const time          = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_quad_one_delay(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                                    [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                                    [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                                    [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                                ],\n                                value     : 'control_quad8_pitch',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_quad: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_drone_control_quad',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, 0, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_quad(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_quad_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'byrobot_drone_8_drone_control_quad_delay',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n                TIME    : 4,\n            },\n            class   : 'control_quad',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n                const time     = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_quad_delay(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_position_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  'pitch_forward'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, 'pitch_backward'],\n                        [Lang.Blocks.drone_control_quad_roll_left,      'roll_left'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     'roll_right'],\n                        [Lang.Blocks.drone_control_quad_throttle_up,    'throttle_up'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  'throttle_down'],\n                    ],\n                    value     : 'pitch_forward',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['1'] }, { type: 'number', params: ['1'] }, null],\n                type  : 'byrobot_drone_8_drone_control_position_one',\n            },\n            paramsKeyMap: {\n                CONTROLDIRECTION: 0,\n                DISTANCE        : 1,\n                SPEED           : 2,\n            },\n            class   : 'control_position',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const controlDirection = script.getField('CONTROLDIRECTION');\n                const distance         = script.getNumberValue('DISTANCE');\n                const speed            = script.getNumberValue('SPEED');\n                let   time             = 0;\n                \n                if( speed > 0 )\n                {\n                    time = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                let x = 0;\n                let y = 0;\n                let z = 0;\n\n                switch( controlDirection )\n                {\n                    case    'pitch_forward':   x = distance;   break;\n                    case    'pitch_backward':  x = -distance;  break;\n                    case    'roll_left':       y = distance;   break;\n                    case    'roll_right':      y = -distance;  break;\n                    case    'throttle_up':     z = distance;   break;\n                    default:                z    = -distance;  break;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, x, y, z, speed, 0, 0, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_position_one(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_pitch_forward,  'pitch_forward'],\n                                    [Lang.Blocks.drone_control_quad_pitch_backward, 'pitch_backward'],\n                                    [Lang.Blocks.drone_control_quad_roll_left,      'roll_left'],\n                                    [Lang.Blocks.drone_control_quad_roll_right,     'roll_right'],\n                                    [Lang.Blocks.drone_control_quad_throttle_up,    'throttle_up'],\n                                    [Lang.Blocks.drone_control_quad_throttle_down,  'throttle_down'],\n                                ],\n                                value     : 'pitch_forward',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_position_turn: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                        [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['90'] },\n                    { type: 'number', params: ['45'] },\n                    null\n                ],\n                type: 'byrobot_drone_8_drone_control_position_turn',\n            },\n            paramsKeyMap: {\n                DIRECTION_YAW: 0,\n                DEGREE_YAW   : 1,\n                SPEED_YAW    : 2,\n            },\n            class   : 'control_position',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const directionYaw = script.getNumberValue('DIRECTION_YAW');\n                const degree       = script.getNumberValue('DEGREE_YAW');\n                const yaw          = directionYaw * degree;\n                const speedYaw     = script.getNumberValue('SPEED_YAW');\n\n                let time = 0;\n\n                if( speedYaw > 0 )\n                {\n                    time = Math.abs(degree / speedYaw) * 2 * 1000 + 3000;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, 0, 0, 0, 0, yaw, speedYaw, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_position_turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                                    [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_position_location: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null],\n                type: 'byrobot_drone_8_drone_control_position_location',\n            },\n            paramsKeyMap: {\n                DIRECTION_PITCH   : 0,\n                DISTANCE_PITCH    : 1,\n                DIRECTION_ROLL    : 2,\n                DISTANCE_ROLL     : 3,\n                DIRECTION_THROTTLE: 4,\n                DISTANCE_THROTTLE : 5,\n                SPEED             : 6\n            },\n            class   : 'control_position',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const directionPitch    = script.getNumberValue('DIRECTION_PITCH');\n                const directionRoll     = script.getNumberValue('DIRECTION_ROLL');\n                const directionThrottle = script.getNumberValue('DIRECTION_THROTTLE');\n                \n                const x = directionPitch     * script.getNumberValue('DISTANCE_PITCH');\n                const y = directionRoll      * script.getNumberValue('DISTANCE_ROLL');\n                const z = directionThrottle  * script.getNumberValue('DISTANCE_THROTTLE');\n\n                const distance = Math.sqrt((x * x) + (y * y) + (z * z));\n\n                const speed = script.getNumberValue('SPEED');\n\n                let time = 0;\n\n                if( speed > 0 )\n                {\n                    time = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, x, y, z, speed, 0, 0, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_position_location(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                                    [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                                    [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                                    [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        byrobot_drone_8_drone_control_position_location_turn: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                        [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['90'] },\n                    { type: 'number', params: ['45'] },\n                    null],\n                type: 'byrobot_drone_8_drone_control_position_location_turn',\n            },\n            paramsKeyMap: {\n                DIRECTION_PITCH   : 0,\n                DISTANCE_PITCH    : 1,\n                DIRECTION_ROLL    : 2,\n                DISTANCE_ROLL     : 3,\n                DIRECTION_THROTTLE: 4,\n                DISTANCE_THROTTLE : 5,\n                SPEED             : 6,\n                DIRECTION_YAW     : 7,\n                DEGREE_YAW        : 8,\n                SPEED_YAW         : 9,\n            },\n            class   : 'control_position',\n            isNotFor: ['byrobot_drone_8'],\n            func(sprite, script)\n            {\n                const directionPitch    = script.getNumberValue('DIRECTION_PITCH');\n                const directionRoll     = script.getNumberValue('DIRECTION_ROLL');\n                const directionThrottle = script.getNumberValue('DIRECTION_THROTTLE');\n                \n                const x = directionPitch     * script.getNumberValue('DISTANCE_PITCH');\n                const y = directionRoll      * script.getNumberValue('DISTANCE_ROLL');\n                const z = directionThrottle  * script.getNumberValue('DISTANCE_THROTTLE');\n\n                const distance = Math.sqrt((x * x) + (y * y) + (z * z));\n                const speed    = script.getNumberValue('SPEED');\n\n                const directionYaw = script.getNumberValue('DIRECTION_YAW');\n                const degree       = script.getNumberValue('DEGREE_YAW');\n                const yaw          = directionYaw * degree;\n                const speedYaw     = script.getNumberValue('SPEED_YAW');\n\n                let timePosition = 0;\n                let timeRotation = 0;\n\n                if( speed > 0 )\n                {\n                    timePosition = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                if( speedYaw > 0 )\n                {\n                    timeRotation = Math.abs(degree / speedYaw) * 2 * 1000 + 3000;\n                }\n\n                const time = Math.max(timePosition, timeRotation);\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, x, y, z, speed, yaw, speedYaw, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_position_location_turn(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                                    [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                                    [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                                    [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                                    [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                                ],\n                                value     : '-1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\n\nmodule.exports = Entry.byrobot_drone_8;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_dronefighter_controller.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n/***************************************************************************************\n *  장치와 연관된 변수 및 함수 정의\n ***************************************************************************************/\n\nEntry.byrobot_dronefighter_controller = {\n    id: 'F.1',\n    name: 'byrobot_dronefighter_controller',\n    url: 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_dronefighter_controller.png',\n    title: {\n        ko: '바이로봇 드론파이터 조종기',\n        en: 'BYROBOT Drone Fighter controller',\n    },\n\n    // 초기화\n    setZero: function() {\n        // 초기화\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (var i = 0; i < 1; i++) {\n            this.transferVibrator(0, 0, 0, 0);\n            this.transferBuzzer(0, 0, 0);\n            this.transferLightManual(0x11, 0xff, 0);\n            this.transferCommand(0x11, 0x81, 0);\n        }\n    },\n\n    // Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n    // listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\n    monitorTemplate: {\n        imgPath: 'hw/byrobot_dronefighter_controller.png', // 배경 이미지\n        width: 500, // 이미지의 폭\n        height: 500, // 이미지의 높이\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            /*\n            joystick_left_x:                {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_left_x,             type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_y:                {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_left_y,             type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_direction:        {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_left_direction,     type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_event:            {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_left_event,         type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_command:          {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_left_command,       type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_x:               {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_right_x,            type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_y:               {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_right_y,            type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_direction:       {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_right_direction,    type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_event:           {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_right_event,        type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_command:         {name: Lang.Blocks.byrobot_dronefighter_controller_joystick_right_command,      type: 'input',  pos: { x: 0, y: 0 }},\n            button_button:                  {name: Lang.Blocks.byrobot_dronefighter_controller_button_button,               type: 'input',  pos: { x: 0, y: 0 }},\n            button_event:                   {name: Lang.Blocks.byrobot_dronefighter_controller_button_event,                type: 'input',  pos: { x: 0, y: 0 }},\n            entryhw_countTransferReserved:  {name: Lang.Blocks.byrobot_dronefighter_entryhw_count_transfer_reserved,        type: 'output', pos: { x: 0, y: 0 }},\n            // */\n            joystick_left_x:                {name: 'Left Joystick X',           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_y:                {name: 'Left Joystick Y',           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_direction:        {name: 'Left Joystick Direction',   type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_event:            {name: 'Left Joystick Event',       type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_command:          {name: 'Left Joystick Command',     type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_x:               {name: 'Right Joystick X',          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_y:               {name: 'Right Joystick Y',          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_direction:       {name: 'Right Joystick Direction',  type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_event:           {name: 'Right Joystick Event',      type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_command:         {name: 'Right Joystick Command',    type: 'input',  pos: { x: 0, y: 0 }},\n            button_button:                  {name: 'Button',                    type: 'input',  pos: { x: 0, y: 0 }},\n            button_event:                   {name: 'Button Event',              type: 'input',  pos: { x: 0, y: 0 }},\n            entryhw_countTransferReserved:  {name: 'Transfer Buffer',           type: 'output', pos: { x: 0, y: 0 }},\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both', // 표시 모드\n    },\n\n    // functions\n\n    // 시간 지연\n    checkFinish: function(script, ms) {\n        if (!script.isStart) {\n            script.isStart = true;\n            script.timeFlag = 1;\n\n            var fps = Entry.FPS || 60;\n            var timeValue = 60 / fps * ms;\n\n            setTimeout(function() {\n                script.timeFlag = 0;\n            }, timeValue);\n\n            return 'Start';\n        } else if (script.timeFlag == 1) {\n            return 'Running';\n        } else {\n            delete script.timeFlag;\n            delete script.isStart;\n            Entry.engine.isContinue = false;\n            return 'Finish';\n        }\n    },\n\n    // 데이터 전송\n    transferLightManual: function(target, flags, brightness) {\n        // 범위 조정\n        target = Math.max(target, 0);\n        target = Math.min(target, 255);\n        flags = Math.max(flags, 0);\n        flags = Math.min(flags, 255);\n        brightness = Math.max(brightness, 0);\n        brightness = Math.min(brightness, 255);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('light_manual_flags', flags);\n        Entry.hw.setDigitalPortValue('light_manual_brightness', brightness);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['light_manual_flags'];\n        delete Entry.hw.sendQueue['light_manual_brightness'];\n    },\n\n    transferBuzzer: function(mode, value, time) {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x11);\n        Entry.hw.setDigitalPortValue('buzzer_mode', mode);\n        Entry.hw.setDigitalPortValue('buzzer_value', value);\n        Entry.hw.setDigitalPortValue('buzzer_time', time);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['buzzer_mode'];\n        delete Entry.hw.sendQueue['buzzer_value'];\n        delete Entry.hw.sendQueue['buzzer_time'];\n    },\n\n    transferVibrator: function(mode, timeOn, timeOff, timeRun) {\n        // 범위 조정\n        timeOn = Math.max(timeOn, 1);\n        timeOn = Math.min(timeOn, 60000);\n        timeOff = Math.max(timeOff, 1);\n        timeOff = Math.min(timeOff, 60000);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x11);\n        Entry.hw.setDigitalPortValue('vibrator_mode', mode);\n        Entry.hw.setDigitalPortValue('vibrator_on', timeOn);\n        Entry.hw.setDigitalPortValue('vibrator_off', timeOff);\n        Entry.hw.setDigitalPortValue('vibrator_total', timeRun);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['vibrator_mode'];\n        delete Entry.hw.sendQueue['vibrator_on'];\n        delete Entry.hw.sendQueue['vibrator_off'];\n        delete Entry.hw.sendQueue['vibrator_total'];\n    },\n\n    transferCommand: function(target, command, option) {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('command_command', command);\n        Entry.hw.setDigitalPortValue('command_option', option);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['command_command'];\n        delete Entry.hw.sendQueue['command_option'];\n    },\n\n    transferUserInterface: function(uicommand, uifunction) {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x11);\n        Entry.hw.setDigitalPortValue('userinterface_command', uicommand);\n        Entry.hw.setDigitalPortValue('userinterface_function', uifunction);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['userinterface_command'];\n        delete Entry.hw.sendQueue['userinterface_function'];\n    },\n\n    // functions for block\n\n    // 데이터 읽기\n    getData: function(script, device) {\n        return Entry.hw.portData[device];\n    },\n\n    // LED 수동 설정\n    setLightManual: function(script, target, flags, brightness) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferLightManual(target, flags, brightness);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 버저 설정(함수 호출 시 시간은 모두 ms 단위 사용)\n    /*\n        MuteInstantally     = 1,    // 묵음 즉시 적용\n        MuteContinually     = 2,    // 묵음 예약\n\n        ScaleInstantally    = 3,    // 음계 즉시 적용\n        ScaleContinually    = 4,    // 음계 예약\n\n        HzInstantally       = 5,    // 주파수 즉시 적용\n        HzContinually       = 6,    // 주파수 예약\n     */\n    // 정지\n    setBuzzerStop: function(script) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferBuzzer(0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 묵음\n    setBuzzerMute: function(script, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 2; // 묵음 연속\n                    if (flagInstantly) mode = 1; // 묵음 즉시\n\n                    this.transferBuzzer(mode, 0xee, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setBuzzerScale: function(script, octave, scale, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 4; // Scale 연속\n                    if (flagInstantly) mode = 3; // Scale 즉시\n\n                    var scalecalc = octave * 12 + scale;\n\n                    this.transferBuzzer(mode, scalecalc, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setBuzzerHz: function(script, hz, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 6; // Hz 연속\n                    if (flagInstantly) mode = 5; // Hz 즉시\n\n                    // 범위 조정\n                    hz = Math.max(hz, 1);\n                    hz = Math.min(hz, 63999);\n\n                    this.transferBuzzer(mode, hz, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 진동 제어\n    /*\n        Stop            = 0,    // 정지\n        Instantally     = 1,    // 즉시 적용\n        Continually     = 2,    // 예약\n     */\n    setVibratorStop: function(script) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferVibrator(0, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setVibrator: function(script, timeOn, timeOff, timeRun, flagDelay, flagInstantly) {\n        timeRun = Math.max(timeRun, 0);\n        timeRun = Math.min(timeRun, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = timeRun;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 2; // 예약\n                    if (flagInstantly) mode = 1; // 즉시\n\n                    this.transferVibrator(mode, timeOn, timeOff, timeRun);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendCommand: function(script, target, command, option) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferCommand(target, command, option);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setUserInterface: function(script, uicommand, uifunction) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferUserInterface(uicommand, uifunction);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\n// \nEntry.byrobot_dronefighter_controller.setLanguage = function ()\n{\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_dronefighter_drone_state_mode_system\": \"시스템 모드\",\n                \"byrobot_dronefighter_drone_state_mode_vehicle\": \"드론파이터 모드\",\n                \"byrobot_dronefighter_drone_state_mode_flight\": \"비행 모드\",\n                \"byrobot_dronefighter_drone_state_mode_drive\": \"자동차 모드\",\n                \"byrobot_dronefighter_drone_state_mode_coordinate\": \"기본 좌표계\",\n                \"byrobot_dronefighter_drone_state_battery\": \"배터리\",\n                \"byrobot_dronefighter_drone_attitude_roll\": \"자세 Roll\",\n                \"byrobot_dronefighter_drone_attitude_pitch\": \"자세 Pitch\",\n                \"byrobot_dronefighter_drone_attitude_yaw\": \"자세 Yaw\",\n                \"byrobot_dronefighter_drone_irmessage\": \"적외선 수신 값\",\n                \"byrobot_dronefighter_controller_joystick_left_x\": \"왼쪽 조이스틱 가로축\",\n                \"byrobot_dronefighter_controller_joystick_left_y\": \"왼쪽 조이스틱 세로축\",\n                \"byrobot_dronefighter_controller_joystick_left_direction\": \"왼쪽 조이스틱 방향\",\n                \"byrobot_dronefighter_controller_joystick_left_event\": \"왼쪽 조이스틱 이벤트\",\n                \"byrobot_dronefighter_controller_joystick_left_command\": \"왼쪽 조이스틱 명령\",\n                \"byrobot_dronefighter_controller_joystick_right_x\": \"오른쪽 조이스틱 가로축\",\n                \"byrobot_dronefighter_controller_joystick_right_y\": \"오른쪽 조이스틱 세로축\",\n                \"byrobot_dronefighter_controller_joystick_right_direction\": \"오른쪽 조이스틱 방향\",\n                \"byrobot_dronefighter_controller_joystick_right_event\": \"오른쪽 조이스틱 이벤트\",\n                \"byrobot_dronefighter_controller_joystick_right_command\": \"오른쪽 조이스틱 명령\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_up\": \"왼쪽 위\",\n                \"byrobot_dronefighter_controller_joystick_direction_up\": \"위\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_up\": \"오른쪽 위\",\n                \"byrobot_dronefighter_controller_joystick_direction_left\": \"왼쪽\",\n                \"byrobot_dronefighter_controller_joystick_direction_center\": \"중앙\",\n                \"byrobot_dronefighter_controller_joystick_direction_right\": \"오른쪽\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_down\": \"왼쪽 아래\",\n                \"byrobot_dronefighter_controller_joystick_direction_down\": \"아래\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_down\": \"오른쪽 아래\",\n                \"byrobot_dronefighter_controller_button_button\": \"버튼\",\n                \"byrobot_dronefighter_controller_button_event\": \"버튼 이벤트\",\n                \"byrobot_dronefighter_controller_button_front_left\": \"왼쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_front_right\": \"오른쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_front_left_right\": \"양쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up_left\": \"트림 좌회전 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up_right\": \"트림 우회전 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up\": \"트림 앞 버튼\",\n                \"byrobot_dronefighter_controller_button_center_left\": \"트림 왼쪽 버튼\",\n                \"byrobot_dronefighter_controller_button_center_right\": \"트림 오른쪽 버튼\",\n                \"byrobot_dronefighter_controller_button_center_down\": \"트림 뒤 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_left\": \"왼쪽 둥근 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_right\": \"오른쪽 둥근 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_left_right\": \"양쪽 둥근 버튼\",\n                \"byrobot_dronefighter_entryhw_count_transfer_reserved\": \"전송 예약된 데이터 수\",\n                \"byrobot_dronefighter_common_roll\": \"Roll\",\n                \"byrobot_dronefighter_common_pitch\": \"Pitch\",\n                \"byrobot_dronefighter_common_yaw\": \"Yaw\",\n                \"byrobot_dronefighter_common_throttle\": \"Throttle\",\n                \"byrobot_dronefighter_common_left\": \"왼쪽\",\n                \"byrobot_dronefighter_common_right\": \"오른쪽\",\n                \"byrobot_dronefighter_common_light_manual_on\": \"켜기\",\n                \"byrobot_dronefighter_common_light_manual_off\": \"끄기\",\n                \"byrobot_dronefighter_common_light_manual_b25\": \"밝기 25%\",\n                \"byrobot_dronefighter_common_light_manual_b50\": \"밝기 50%\",\n                \"byrobot_dronefighter_common_light_manual_b75\": \"밝기 75%\",\n                \"byrobot_dronefighter_common_light_manual_b100\": \"밝기 100%\",\n                \"byrobot_dronefighter_common_light_manual_all\": \"전체\",\n                \"byrobot_dronefighter_common_light_manual_red\": \"빨강\",\n                \"byrobot_dronefighter_common_light_manual_blue\": \"파랑\",\n                \"byrobot_dronefighter_common_light_manual_1\": \"1\",\n                \"byrobot_dronefighter_common_light_manual_2\": \"2\",\n                \"byrobot_dronefighter_common_light_manual_3\": \"3\",\n                \"byrobot_dronefighter_common_light_manual_4\": \"4\",\n                \"byrobot_dronefighter_common_light_manual_5\": \"5\",\n                \"byrobot_dronefighter_common_light_manual_6\": \"6\",\n                \"byrobot_dronefighter_controller_buzzer\": \"버저\",\n                \"byrobot_dronefighter_controller_buzzer_mute\": \"쉼\",\n                \"byrobot_dronefighter_controller_buzzer_c\": \"도\",\n                \"byrobot_dronefighter_controller_buzzer_cs\": \"도#\",\n                \"byrobot_dronefighter_controller_buzzer_d\": \"레\",\n                \"byrobot_dronefighter_controller_buzzer_ds\": \"레#\",\n                \"byrobot_dronefighter_controller_buzzer_e\": \"미\",\n                \"byrobot_dronefighter_controller_buzzer_f\": \"파\",\n                \"byrobot_dronefighter_controller_buzzer_fs\": \"파#\",\n                \"byrobot_dronefighter_controller_buzzer_g\": \"솔\",\n                \"byrobot_dronefighter_controller_buzzer_gs\": \"솔#\",\n                \"byrobot_dronefighter_controller_buzzer_a\": \"라\",\n                \"byrobot_dronefighter_controller_buzzer_as\": \"라#\",\n                \"byrobot_dronefighter_controller_buzzer_b\": \"시\",\n                \"byrobot_dronefighter_controller_userinterface_preset_clear\": \"모두 지우기\",\n                \"byrobot_dronefighter_controller_userinterface_preset_dronefighter2017\": \"기본\",\n                \"byrobot_dronefighter_controller_userinterface_preset_education\": \"교육용\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontleft_down\": \"왼쪽 빨간 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontright_down\": \"오른쪽 빨간 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnleft_down\": \"트림 좌회전 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnright_down\": \"트림 우회전 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midup_down\": \"트림 앞 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midleft_down\": \"트림 왼쪽 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midright_down\": \"트림 오른쪽 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_middown_down\": \"트림 뒤 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_up_in\": \"왼쪽 조이스틱을 위로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_left_in\": \"왼쪽 조이스틱을 왼쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_right_in\": \"왼쪽 조이스틱을 오른쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_down_in\": \"왼쪽 조이스틱을 아래로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_up_in\": \"오른쪽 조이스틱을 위로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_left_in\": \"오른쪽 조이스틱을 왼쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_right_in\": \"오른쪽 조이스틱을 오른쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_down_in\": \"오른쪽 조이스틱을 아래로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_function_joystickcalibration_reset\": \"조이스틱 보정 초기화\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_red\": \"팀 - 레드\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_blue\": \"팀 - 블루\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flight\": \"드론\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flightnoguard\": \"드론 - 가드 없음\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_drive\": \"자동차\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_local\": \"방위 - 일반\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_world\": \"방위 - 앱솔루트\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode1\": \"조종 - MODE 1\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode2\": \"조종 - MODE 2\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode3\": \"조종 - MODE 3\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode4\": \"조종 - MODE 4\",\n                \"byrobot_dronefighter_controller_userinterface_function_gyrobias_reset\": \"자이로 바이어스 리셋\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_cdc\": \"USB 시리얼 통신 장치\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_hid\": \"USB 게임 컨트롤러\",\n                \"byrobot_dronefighter_drone_team\": \"팀 \",\n                \"byrobot_dronefighter_drone_team_red\": \"레드\",\n                \"byrobot_dronefighter_drone_team_blue\": \"블루\",\n                \"byrobot_dronefighter_drone_coordinate_world\": \"앱솔루트\",\n                \"byrobot_dronefighter_drone_coordinate_local\": \"일반\",\n                \"byrobot_dronefighter_drone_mode_vehicle_flight\": \"드론\",\n                \"byrobot_dronefighter_drone_mode_vehicle_drive\": \"자동차\",\n                \"byrobot_dronefighter_drone_control_double_wheel\": \"방향\",\n                \"byrobot_dronefighter_drone_control_double_wheel_left\": \"왼쪽 회전\",\n                \"byrobot_dronefighter_drone_control_double_wheel_right\": \"오른쪽 회전\",\n                \"byrobot_dronefighter_drone_control_double_accel_forward\": \"전진\",\n                \"byrobot_dronefighter_drone_control_double_accel_backward\": \"후진\",\n                \"byrobot_dronefighter_drone_control_quad_roll\": \"Roll\",\n                \"byrobot_dronefighter_drone_control_quad_pitch\": \"Pitch\",\n                \"byrobot_dronefighter_drone_control_quad_yaw\": \"Yaw\",\n                \"byrobot_dronefighter_drone_control_quad_throttle\": \"Throttle\",\n                \"byrobot_dronefighter_drone_control_quad_roll_left\": \"왼쪽\",\n                \"byrobot_dronefighter_drone_control_quad_roll_right\": \"오른쪽\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_forward\": \"앞으로\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_backward\": \"뒤로\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_left\": \"왼쪽 회전\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_right\": \"오른쪽 회전\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_up\": \"위\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_down\": \"아래\",\n            },\n\n            // ko.js에 작성하던 내용\n            template: {\n                \"byrobot_dronefighter_controller_controller_value_button\": \"%1\",\n                \"byrobot_dronefighter_controller_controller_value_joystick\": \"%1\",\n                \"byrobot_dronefighter_controller_controller_if_button_press\": \"조종기 %1 눌렀을 때\",\n                \"byrobot_dronefighter_controller_controller_if_joystick_direction\": \"조종기 %1 조이스틱 %2 움직였을 때\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single_off\": \"조종기 LED 끄기 %1\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single\": \"조종기 LED %1 %2 %3\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single_input\": \"조종기 LED %1 밝기 %2 %3\",\n                \"byrobot_dronefighter_controller_controller_buzzer_off\": \"버저 끄기 %1\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale\": \"%1 옥타브 %2 을(를) 연주 %3\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale_delay\": \"%1 옥타브 %2 을(를) %3 초 연주 %4\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale_reserve\": \"%1 옥타브 %2 을(를) %3 초 예약 %4\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz\": \"%1 Hz 소리를 연주 %2\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz_delay\": \"%1 Hz 소리를 %2 초 연주 %3\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz_reserve\": \"%1 Hz 소리를 %2 초 예약 %3\",\n                \"byrobot_dronefighter_controller_controller_vibrator_off\": \"진동 끄기 %1\",\n                \"byrobot_dronefighter_controller_controller_vibrator_on_delay\": \"진동 %1 초 켜기 %2\",\n                \"byrobot_dronefighter_controller_controller_vibrator_on_reserve\": \"진동 %1 초 예약 %2\",\n                \"byrobot_dronefighter_controller_controller_vibrator_delay\": \"진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4\",\n                \"byrobot_dronefighter_controller_controller_vibrator_reserve\": \"진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4\",\n                \"byrobot_dronefighter_controller_controller_userinterface_preset\": \"조종기 설정 모드 사용자 인터페이스를 %1(으)로 변경%2\",\n                \"byrobot_dronefighter_controller_controller_userinterface\": \"조종기 설정 모드에서 %1 %2 실행 %3\",\n            },\n\n            Helper: {\n                \"byrobot_dronefighter_controller_controller_value_button\": \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_dronefighter_controller_controller_value_joystick\": \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_dronefighter_controller_controller_if_button_press\": \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_dronefighter_controller_controller_if_joystick_direction\": \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single_off\": \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single\": \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single_input\": \"<br>조종기 LED 여러 개의 밝기를 동시에 변경할 때 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 개별 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_controller_controller_buzzer_off\": \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale\": \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale_delay\": \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale_reserve\": \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz\": \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz_delay\": \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz_reserve\": \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                \"byrobot_dronefighter_controller_controller_vibrator_off\": \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                \"byrobot_dronefighter_controller_controller_vibrator_on_delay\": \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_dronefighter_controller_controller_vibrator_on_reserve\": \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_dronefighter_controller_controller_vibrator_delay\": \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_dronefighter_controller_controller_vibrator_reserve\": \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_dronefighter_controller_controller_userinterface_preset\": \"<br>조종기 설정 모드의 사용자 인터페이스를 미리 정해둔 설정으로 변경합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#설정모드</font> <font color='forestgreen'>#인터페이스</font>\",\n                \"byrobot_dronefighter_controller_controller_userinterface\": \"<br>조종기 설정 모드의 사용자 인터페이스를 직접 지정합니다. 각 버튼 및 조이스틱 조작 시 어떤 명령을 사용할 것인지를 지정할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#설정모드</font> <font color='forestgreen'>#인터페이스</font>\",\n            }\n        },\n\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_dronefighter_drone_state_mode_system\": \"system Mode\",\n                \"byrobot_dronefighter_drone_state_mode_vehicle\": \"vehicle Mode\",\n                \"byrobot_dronefighter_drone_state_mode_flight\": \"flight Mode\",\n                \"byrobot_dronefighter_drone_state_mode_drive\": \"drive Mode\",\n                \"byrobot_dronefighter_drone_state_mode_coordinate\": \"coordinate\",\n                \"byrobot_dronefighter_drone_state_battery\": \"battery\",\n                \"byrobot_dronefighter_drone_attitude_roll\": \"attitude - roll\",\n                \"byrobot_dronefighter_drone_attitude_pitch\": \"attitude - pitch\",\n                \"byrobot_dronefighter_drone_attitude_yaw\": \"attitude - yaw\",\n                \"byrobot_dronefighter_drone_irmessage\": \"IR data Received\",\n                \"byrobot_dronefighter_controller_joystick_left_x\": \"left joystick horizontal\",\n                \"byrobot_dronefighter_controller_joystick_left_y\": \"left joystick vertical\",\n                \"byrobot_dronefighter_controller_joystick_left_direction\": \"left joystick direction\",\n                \"byrobot_dronefighter_controller_joystick_left_event\": \"left joystick event\",\n                \"byrobot_dronefighter_controller_joystick_left_command\": \"left joystick command\",\n                \"byrobot_dronefighter_controller_joystick_right_x\": \"right joystick horizontal\",\n                \"byrobot_dronefighter_controller_joystick_right_y\": \"right joystick vertical\",\n                \"byrobot_dronefighter_controller_joystick_right_direction\": \"right joystick direction\",\n                \"byrobot_dronefighter_controller_joystick_right_event\": \"right joystick event\",\n                \"byrobot_dronefighter_controller_joystick_right_command\": \"right joystick command\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_up\": \"left up\",\n                \"byrobot_dronefighter_controller_joystick_direction_up\": \"up\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_up\": \"right up\",\n                \"byrobot_dronefighter_controller_joystick_direction_left\": \"left\",\n                \"byrobot_dronefighter_controller_joystick_direction_center\": \"center\",\n                \"byrobot_dronefighter_controller_joystick_direction_right\": \"right\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_down\": \"left down\",\n                \"byrobot_dronefighter_controller_joystick_direction_down\": \"down\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_down\": \"right down\",\n                \"byrobot_dronefighter_controller_button_button\": \"button\",\n                \"byrobot_dronefighter_controller_button_event\": \"button event\",\n                \"byrobot_dronefighter_controller_button_front_left\": \"left red button\",\n                \"byrobot_dronefighter_controller_button_front_right\": \"right red button\",\n                \"byrobot_dronefighter_controller_button_front_left_right\": \"both red button\",\n                \"byrobot_dronefighter_controller_button_center_up_left\": \"trim-turn-left button\",\n                \"byrobot_dronefighter_controller_button_center_up_right\": \"trim-turn-right button\",\n                \"byrobot_dronefighter_controller_button_center_up\": \"trim-forward button\",\n                \"byrobot_dronefighter_controller_button_center_left\": \"trim-left button\",\n                \"byrobot_dronefighter_controller_button_center_right\": \"trim-right button\",\n                \"byrobot_dronefighter_controller_button_center_down\": \"trim-backward button\",\n                \"byrobot_dronefighter_controller_button_bottom_left\": \"left round button\",\n                \"byrobot_dronefighter_controller_button_bottom_right\": \"right round button\",\n                \"byrobot_dronefighter_controller_button_bottom_left_right\": \"both round button\",\n                \"byrobot_dronefighter_entryhw_count_transfer_reserved\": \"reserved data blocks\",\n                \"byrobot_dronefighter_common_roll\": \"roll\",\n                \"byrobot_dronefighter_common_pitch\": \"pitch\",\n                \"byrobot_dronefighter_common_yaw\": \"yaw\",\n                \"byrobot_dronefighter_common_throttle\": \"throttle\",\n                \"byrobot_dronefighter_common_left\": \"left\",\n                \"byrobot_dronefighter_common_right\": \"right\",\n                \"byrobot_dronefighter_common_light_manual_on\": \"on\",\n                \"byrobot_dronefighter_common_light_manual_off\": \"off\",\n                \"byrobot_dronefighter_common_light_manual_b25\": \"brightness 25%\",\n                \"byrobot_dronefighter_common_light_manual_b50\": \"brightness 50%\",\n                \"byrobot_dronefighter_common_light_manual_b75\": \"brightness 75%\",\n                \"byrobot_dronefighter_common_light_manual_b100\": \"brightness 100%\",\n                \"byrobot_dronefighter_common_light_manual_all\": \"all\",\n                \"byrobot_dronefighter_common_light_manual_red\": \"red\",\n                \"byrobot_dronefighter_common_light_manual_blue\": \"blue\",\n                \"byrobot_dronefighter_common_light_manual_1\": \"1\",\n                \"byrobot_dronefighter_common_light_manual_2\": \"2\",\n                \"byrobot_dronefighter_common_light_manual_3\": \"3\",\n                \"byrobot_dronefighter_common_light_manual_4\": \"4\",\n                \"byrobot_dronefighter_common_light_manual_5\": \"5\",\n                \"byrobot_dronefighter_common_light_manual_6\": \"6\",\n                \"byrobot_dronefighter_controller_buzzer\": \"buzzer\",\n                \"byrobot_dronefighter_controller_buzzer_mute\": \"mute\",\n                \"byrobot_dronefighter_controller_buzzer_c\": \"C\",\n                \"byrobot_dronefighter_controller_buzzer_cs\": \"C#\",\n                \"byrobot_dronefighter_controller_buzzer_d\": \"D\",\n                \"byrobot_dronefighter_controller_buzzer_ds\": \"D#\",\n                \"byrobot_dronefighter_controller_buzzer_e\": \"E\",\n                \"byrobot_dronefighter_controller_buzzer_f\": \"F\",\n                \"byrobot_dronefighter_controller_buzzer_fs\": \"F#\",\n                \"byrobot_dronefighter_controller_buzzer_g\": \"G\",\n                \"byrobot_dronefighter_controller_buzzer_gs\": \"G#\",\n                \"byrobot_dronefighter_controller_buzzer_a\": \"A\",\n                \"byrobot_dronefighter_controller_buzzer_as\": \"A#\",\n                \"byrobot_dronefighter_controller_buzzer_b\": \"B\",\n                \"byrobot_dronefighter_controller_userinterface_preset_clear\": \"clear\",\n                \"byrobot_dronefighter_controller_userinterface_preset_dronefighter2017\": \"default\",\n                \"byrobot_dronefighter_controller_userinterface_preset_education\": \"education\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontleft_down\": \"press left red button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontright_down\": \"press right red button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnleft_down\": \"press trim-left-turn button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnright_down\": \"press trim-right-turn button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midup_down\": \"press trim-forward button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midleft_down\": \"press trim-left button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midright_down\": \"press trim-right button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_middown_down\": \"press trim-backward button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_up_in\": \"left joystick move up\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_left_in\": \"left joystick move left\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_right_in\": \"left joystick move right\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_down_in\": \"left joystick move down\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_up_in\": \"right joystick move up\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_left_in\": \"right joystick move left\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_right_in\": \"right joystick move right\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_down_in\": \"right joystick move down\",\n                \"byrobot_dronefighter_controller_userinterface_function_joystickcalibration_reset\": \"reset joystick calibration\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_red\": \"team - red\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_blue\": \"team - blue\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flight\": \"flight\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flightnoguard\": \"flight - no guard\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_drive\": \"drive\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_local\": \"coordinate - normal\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_world\": \"coordinate - absolute\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode1\": \"control - MODE 1\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode2\": \"control - MODE 2\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode3\": \"control - MODE 3\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode4\": \"control - MODE 4\",\n                \"byrobot_dronefighter_controller_userinterface_function_gyrobias_reset\": \"reset gyro bias\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_cdc\": \"USB serial device\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_hid\": \"USB game controller\",\n                \"byrobot_dronefighter_drone_team\": \"team\",\n                \"byrobot_dronefighter_drone_team_red\": \"red\",\n                \"byrobot_dronefighter_drone_team_blue\": \"blue\",\n                \"byrobot_dronefighter_drone_coordinate_world\": \"absolute\",\n                \"byrobot_dronefighter_drone_coordinate_local\": \"normal\",\n                \"byrobot_dronefighter_drone_mode_vehicle_flight\": \"flight\",\n                \"byrobot_dronefighter_drone_mode_vehicle_drive\": \"drive\",\n                \"byrobot_dronefighter_drone_control_double_wheel\": \"direction\",\n                \"byrobot_dronefighter_drone_control_double_wheel_left\": \"turn left\",\n                \"byrobot_dronefighter_drone_control_double_wheel_right\": \"turn right\",\n                \"byrobot_dronefighter_drone_control_double_accel_forward\": \"forward\",\n                \"byrobot_dronefighter_drone_control_double_accel_backward\": \"backward\",\n                \"byrobot_dronefighter_drone_control_quad_roll\": \"roll\",\n                \"byrobot_dronefighter_drone_control_quad_pitch\": \"pitch\",\n                \"byrobot_dronefighter_drone_control_quad_yaw\": \"yaw\",\n                \"byrobot_dronefighter_drone_control_quad_throttle\": \"throttle\",\n                \"byrobot_dronefighter_drone_control_quad_roll_left\": \"left\",\n                \"byrobot_dronefighter_drone_control_quad_roll_right\": \"right\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_forward\": \"foward\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_backward\": \"backward\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_left\": \"turn Left\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_right\": \"turn Right\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_up\": \"up\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_down\": \"down\",\n            },\n\n            // en.js에 작성하던 내용\n            template: {\n                \"byrobot_dronefighter_controller_controller_value_button\": \"%1\",\n                \"byrobot_dronefighter_controller_controller_value_joystick\": \"%1\",\n                \"byrobot_dronefighter_controller_controller_if_button_press\": \"when press %1\",\n                \"byrobot_dronefighter_controller_controller_if_joystick_direction\": \"when %1 stick move to %2\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single_off\": \"turn off all controller LEDs %1\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single\": \"change the state of %1 controller LED to %2 %3\",\n                \"byrobot_dronefighter_controller_controller_light_manual_single_input\": \"change the brightness of %1 controller LED to %2 %3\",\n                \"byrobot_dronefighter_controller_controller_buzzer_off\": \"turn off the buzzer %1\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale\": \"play %1 octave %2 %3\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale_delay\": \"play %1 octave %2 for %3 second %4\",\n                \"byrobot_dronefighter_controller_controller_buzzer_scale_reserve\": \"reserve to play %1 octave %2 for %3 second %4\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz\": \"play %1 Hz sound %2\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz_delay\": \"play %1 Hz sound for %2 second %3\",\n                \"byrobot_dronefighter_controller_controller_buzzer_hz_reserve\": \"reserve to play %1 Hz sound for %2 second %3\",\n                \"byrobot_dronefighter_controller_controller_vibrator_off\": \"turn off the vibrator %1\",\n                \"byrobot_dronefighter_controller_controller_vibrator_on_delay\": \"turn on the vibrator for %1 second %2\",\n                \"byrobot_dronefighter_controller_controller_vibrator_on_reserve\": \"reserve turn on the vibrator for %1 second %2\",\n                \"byrobot_dronefighter_controller_controller_vibrator_delay\": \"vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_dronefighter_controller_controller_vibrator_reserve\": \"reserve vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_dronefighter_controller_controller_userinterface_preset\": \"controller setup mode - select controller user interface preset %1 %2\",\n                \"byrobot_dronefighter_controller_controller_userinterface\": \"controller setup mode - when %1, run %2 %3\",\n            },\n            \n            Helper: {\n\n            }\n        }\n    }\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 이름\n ***************************************************************************************/\nEntry.byrobot_dronefighter_controller.blockMenuBlocks = [\n    'byrobot_dronefighter_controller_controller_value_button',\n    'byrobot_dronefighter_controller_controller_value_joystick',\n    'byrobot_dronefighter_controller_controller_if_button_press',\n    'byrobot_dronefighter_controller_controller_if_joystick_direction',\n    'byrobot_dronefighter_controller_controller_light_manual_single_off',\n    'byrobot_dronefighter_controller_controller_light_manual_single',\n    'byrobot_dronefighter_controller_controller_light_manual_single_input',\n    'byrobot_dronefighter_controller_controller_buzzer_off',\n    'byrobot_dronefighter_controller_controller_buzzer_scale',\n    'byrobot_dronefighter_controller_controller_buzzer_scale_delay',\n    'byrobot_dronefighter_controller_controller_buzzer_scale_reserve',\n    'byrobot_dronefighter_controller_controller_buzzer_hz',\n    'byrobot_dronefighter_controller_controller_buzzer_hz_delay',\n    'byrobot_dronefighter_controller_controller_buzzer_hz_reserve',\n    'byrobot_dronefighter_controller_controller_vibrator_off',\n    'byrobot_dronefighter_controller_controller_vibrator_on_delay',\n    'byrobot_dronefighter_controller_controller_vibrator_on_reserve',\n    'byrobot_dronefighter_controller_controller_vibrator_delay',\n    'byrobot_dronefighter_controller_controller_vibrator_reserve',\n    'byrobot_dronefighter_controller_controller_userinterface_preset',\n    'byrobot_dronefighter_controller_controller_userinterface',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 상세\n ***************************************************************************************/\nEntry.byrobot_dronefighter_controller.getBlocks = function() {\n    return {\n        //region byrobot 바이로봇\n        /* BYROBOT DroneFighter Controller Start */\n        byrobot_dronefighter_controller_controller_value_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_button_button,\n                            'button_button',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_event, 'button_event'],\n                    ],\n                    value: 'button_button', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_controller_controller_value_button', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_controller_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n                return read[device];\n            },\n        },\n        byrobot_dronefighter_controller_controller_value_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_x,\n                            'joystick_left_x',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_y,\n                            'joystick_left_y',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_direction,\n                            'joystick_left_direction',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_event,\n                            'joystick_left_event',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_command,\n                            'joystick_left_command',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_x,\n                            'joystick_right_x',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_y,\n                            'joystick_right_y',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_direction,\n                            'joystick_right_direction',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_event,\n                            'joystick_right_event',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_command,\n                            'joystick_right_command',\n                        ],\n                    ],\n                    value: 'joystick_left_x', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_controller_controller_value_joystick', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_controller_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n                return read[device];\n            },\n        },\n        byrobot_dronefighter_controller_controller_if_button_press: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_left, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_right, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_left_right, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up_left, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up_right, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up, '16'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_left, '32'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_right, '64'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_down, '128'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_bottom_left, '256'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_bottom_right, '512'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_button_bottom_left_right,\n                            '768',\n                        ],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_controller_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'byrobot_dronefighter_controller_boolean_input',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var button = 'button_button'; // paramsKeyMap에 정의된 이름 사용\n                var buttonevent = 'button_event'; // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2)\n                    return true;\n                else return false;\n            },\n        },\n        byrobot_dronefighter_controller_controller_if_joystick_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_dronefighter_common_right, 'joystick_right_direction'],\n                    ],\n                    value: 'joystick_left_direction',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_left_up,\n                            '17',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_up, '18'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_right_up,\n                            '20',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_left, '33'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_center,\n                            '34',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_right,\n                            '36',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_joystick_direction_left_down,\n                            '65',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_down, '66'],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_joystick_direction_right_down,\n                            '68',\n                        ],\n                    ],\n                    value: '34',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_dronefighter_controller_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                DIRECTION: 1,\n            },\n            class: 'byrobot_dronefighter_controller_boolean_input',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION')) return true;\n                else return false;\n            },\n        },\n        byrobot_dronefighter_controller_controller_light_manual_single_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_controller_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_controller_controller_light',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_controller.setLightManual(script, 0x11, 0xff, 0);\n            },\n        },\n        byrobot_dronefighter_controller_controller_light_manual_single: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_all, '255'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_1, '128'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_2, '64'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_3, '32'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_4, '16'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_5, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_6, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_blue, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_red, '1'],\n                    ],\n                    value: '128',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_on, '220'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_off, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b25, '75'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b50, '125'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b75, '200'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b100, '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_controller_controller_light_manual_single',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_controller_controller_light',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var flags = parseInt(script.getField('FLAGS'));\n                var brightness = parseInt(script.getField('BRIGHTNESS'));\n                return Entry.byrobot_dronefighter_controller.setLightManual(\n                    script,\n                    0x11,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_light_manual_single_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0xFF'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_controller_controller_light',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_dronefighter_controller.setLightManual(script, 0x11, flags, brightness);\n            },\n        },\n        byrobot_dronefighter_controller_controller_buzzer_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_controller_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_controller_buzzer',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_controller.setBuzzerStop(script);\n            },\n        },\n        byrobot_dronefighter_controller_controller_buzzer_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_controller_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n            },\n            class: 'byrobot_dronefighter_controller_buzzer',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_controller.setBuzzerMute(\n                        script,\n                        60000,\n                        false,\n                        true\n                    );\n                else\n                    return Entry.byrobot_dronefighter_controller.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        60000,\n                        false,\n                        true\n                    );\n            },\n        },\n        byrobot_dronefighter_controller_controller_buzzer_scale_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_dronefighter_controller_buzzer',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_controller.setBuzzerMute(\n                        script,\n                        time,\n                        true,\n                        true\n                    );\n                else\n                    return Entry.byrobot_dronefighter_controller.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        time,\n                        true,\n                        true\n                    );\n            },\n        },\n        byrobot_dronefighter_controller_controller_buzzer_scale_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_dronefighter_controller_buzzer',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_controller.setBuzzerMute(\n                        script,\n                        time,\n                        false,\n                        false\n                    );\n                else\n                    return Entry.byrobot_dronefighter_controller.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        time,\n                        false,\n                        false\n                    );\n            },\n        },\n        byrobot_dronefighter_controller_controller_buzzer_hz: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'byrobot_dronefighter_controller_buzzer',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                return Entry.byrobot_dronefighter_controller.setBuzzerHz(\n                    script,\n                    hz,\n                    60000,\n                    false,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_buzzer_hz_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_dronefighter_controller_buzzer',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_dronefighter_controller.setBuzzerHz(\n                    script,\n                    hz,\n                    time,\n                    true,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_buzzer_hz_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_dronefighter_controller_buzzer',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_dronefighter_controller.setBuzzerHz(\n                    script,\n                    hz,\n                    time,\n                    false,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_vibrator_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_controller_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_controller_vibrator',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_controller.setVibratorStop(script);\n            },\n        },\n        byrobot_dronefighter_controller_controller_vibrator_on_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_dronefighter_controller_vibrator',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_dronefighter_controller.setVibrator(\n                    script,\n                    timeOn,\n                    0,\n                    timeOn,\n                    true,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_vibrator_on_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_dronefighter_controller_vibrator',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_dronefighter_controller.setVibrator(\n                    script,\n                    timeOn,\n                    0,\n                    timeOn,\n                    false,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_vibrator_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.02'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_dronefighter_controller_vibrator',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_dronefighter_controller.setVibrator(\n                    script,\n                    timeOn,\n                    timeOff,\n                    timeRun,\n                    true,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_vibrator_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.02'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_controller_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_dronefighter_controller_vibrator',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_dronefighter_controller.setVibrator(\n                    script,\n                    timeOn,\n                    timeOff,\n                    timeRun,\n                    false,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_userinterface_preset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_userinterface_preset_clear,\n                            '1',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_preset_dronefighter2017,\n                            '3',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_preset_education,\n                            '4',\n                        ],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_dronefighter_controller_controller_userinterface_preset',\n            },\n            paramsKeyMap: {\n                PRESET: 0,\n            },\n            class: 'byrobot_dronefighter_controller_userinterface',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var preset = parseInt(script.getField('PRESET'));\n                return Entry.byrobot_dronefighter_controller.sendCommand(\n                    script,\n                    0x11,\n                    0x80,\n                    preset\n                );\n            },\n        },\n        byrobot_dronefighter_controller_controller_userinterface: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_button_frontleft_down,\n                            '1',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_button_frontright_down,\n                            '2',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_button_midturnleft_down,\n                            '3',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_button_midturnright_down,\n                            '4',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_button_midup_down,\n                            '5',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_button_midleft_down,\n                            '6',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_button_midright_down,\n                            '7',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_button_middown_down,\n                            '8',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_up_in,\n                            '9',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_left_in,\n                            '10',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_right_in,\n                            '11',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_down_in,\n                            '12',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_up_in,\n                            '13',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_left_in,\n                            '14',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_right_in,\n                            '15',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_down_in,\n                            '16',\n                        ],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_joystickcalibration_reset,\n                            '1',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_team_red,\n                            '2',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_team_blue,\n                            '3',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flight,\n                            '4',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flightnoguard,\n                            '5',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_drive,\n                            '6',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_coordinate_local,\n                            '7',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_coordinate_world,\n                            '8',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode1,\n                            '9',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode2,\n                            '10',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode3,\n                            '11',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode4,\n                            '12',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_gyrobias_reset,\n                            '13',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_usb_cdc,\n                            '14',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_userinterface_function_change_mode_usb_hid,\n                            '15',\n                        ],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_controller_controller_userinterface',\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n                FUNCTION: 1,\n            },\n            class: 'byrobot_dronefighter_controller_userinterface',\n            isNotFor: ['byrobot_dronefighter_controller'],\n            func: function(sprite, script) {\n                var uicommand = parseInt(script.getField('COMMAND'));\n                var uifunction = parseInt(script.getField('FUNCTION'));\n                return Entry.byrobot_dronefighter_controller.setUserInterface(\n                    script,\n                    uicommand,\n                    uifunction\n                );\n            },\n        },\n        /* BYROBOT DroneFighter Controller End */\n        //endregion byrobot 바이로봇\n    };\n};\n\nmodule.exports = Entry.byrobot_dronefighter_controller;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_dronefighter_drive.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n/***************************************************************************************\n *  장치와 연관된 변수 및 함수 정의\n ***************************************************************************************/\n\nEntry.byrobot_dronefighter_drive = {\n    id: 'F.2',\n    name: 'byrobot_dronefighter_drive',\n    url: 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_dronefighter_drive.png',\n    title: {\n        ko: '바이로봇 드론파이터 자동차',\n        en: 'BYROBOT Drone Fighter drive',\n    },\n\n    // 초기화\n    setZero: function() {\n        // 초기화\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (var i = 0; i < 1; i++) {\n            this.transferCommand(0x10, 0x24, 0);\n            this.transferVibrator(0, 0, 0, 0);\n            this.transferBuzzer(0, 0, 0);\n            this.transferLightManual(0x10, 0xff, 0);\n            this.transferLightManual(0x11, 0xff, 0);\n        }\n    },\n\n    // Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n    // listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\n    monitorTemplate: {\n        imgPath: 'hw/byrobot_dronefighter_drive.png', // 배경 이미지\n        width: 500, // 이미지의 폭\n        height: 500, // 이미지의 높이\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            /*\n            state_modeVehicle:              {name: Lang.Blocks.byrobot_dronefighter_drone_state_mode_vehicle,   type: 'input', pos: { x: 0, y: 0 }},\n            state_modeDrive:                {name: Lang.Blocks.byrobot_dronefighter_drone_state_mode_drive,     type: 'input', pos: { x: 0, y: 0 }},\n            state_battery:                  {name: Lang.Blocks.byrobot_dronefighter_drone_state_battery,        type: 'input', pos: { x: 0, y: 0 }},\n            attitude_roll:                  {name: Lang.Blocks.byrobot_dronefighter_drone_attitude_roll,        type: 'input', pos: { x: 0, y: 0 }},\n            attitude_pitch:                 {name: Lang.Blocks.byrobot_dronefighter_drone_attitude_pitch,       type: 'input', pos: { x: 0, y: 0 }},\n            attitude_yaw:                   {name: Lang.Blocks.byrobot_dronefighter_drone_attitude_yaw,         type: 'input', pos: { x: 0, y: 0 }},\n            irmessage_irdata:               {name: Lang.Blocks.byrobot_dronefighter_drone_irmessage,            type: 'input', pos: { x: 0, y: 0 }},\n            // */\n            \n            state_modeVehicle:              {name: 'Vehicle Mode',              type: 'input',  pos: { x: 0, y: 0 }},\n            state_modeDrive:                {name: 'Drive Mode',                type: 'input',  pos: { x: 0, y: 0 }},\n            state_battery:                  {name: 'Battery',                   type: 'input',  pos: { x: 0, y: 0 }},\n            attitude_roll:                  {name: 'Roll',                      type: 'input',  pos: { x: 0, y: 0 }},\n            attitude_pitch:                 {name: 'Pitch',                     type: 'input',  pos: { x: 0, y: 0 }},\n            attitude_yaw:                   {name: 'Yaw',                       type: 'input',  pos: { x: 0, y: 0 }},\n            irmessage_irdata:               {name: 'IR Data',                   type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_x:                {name: 'Left Joystick X',           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_y:                {name: 'Left Joystick Y',           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_direction:        {name: 'Left Joystick Direction',   type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_event:            {name: 'Left Joystick Event',       type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_command:          {name: 'Left Joystick Command',     type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_x:               {name: 'Right Joystick X',          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_y:               {name: 'Right Joystick Y',          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_direction:       {name: 'Right Joystick Direction',  type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_event:           {name: 'Right Joystick Event',      type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_command:         {name: 'Right Joystick Command',    type: 'input',  pos: { x: 0, y: 0 }},\n            button_button:                  {name: 'Button',                    type: 'input',  pos: { x: 0, y: 0 }},\n            button_event:                   {name: 'Button Event',              type: 'input',  pos: { x: 0, y: 0 }},\n            entryhw_countTransferReserved:  {name: 'Transfer Buffer',           type: 'output', pos: { x: 0, y: 0 }},\n            \n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both', // 표시 모드\n    },\n\n    // functions\n\n    // 시간 지연\n    checkFinish: function(script, ms) {\n        if (!script.isStart) {\n            script.isStart = true;\n            script.timeFlag = 1;\n\n            var fps = Entry.FPS || 60;\n            var timeValue = 60 / fps * ms;\n\n            setTimeout(function() {\n                script.timeFlag = 0;\n            }, timeValue);\n\n            return 'Start';\n        } else if (script.timeFlag == 1) {\n            return 'Running';\n        } else {\n            delete script.timeFlag;\n            delete script.isStart;\n            Entry.engine.isContinue = false;\n            return 'Finish';\n        }\n    },\n\n    // 데이터 전송\n    transferLightManual: function(target, flags, brightness) {\n        // 범위 조정\n        target = Math.max(target, 0);\n        target = Math.min(target, 255);\n        flags = Math.max(flags, 0);\n        flags = Math.min(flags, 255);\n        brightness = Math.max(brightness, 0);\n        brightness = Math.min(brightness, 255);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('light_manual_flags', flags);\n        Entry.hw.setDigitalPortValue('light_manual_brightness', brightness);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['light_manual_flags'];\n        delete Entry.hw.sendQueue['light_manual_brightness'];\n    },\n\n    transferBuzzer: function(mode, value, time) {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x11);\n        Entry.hw.setDigitalPortValue('buzzer_mode', mode);\n        Entry.hw.setDigitalPortValue('buzzer_value', value);\n        Entry.hw.setDigitalPortValue('buzzer_time', time);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['buzzer_mode'];\n        delete Entry.hw.sendQueue['buzzer_value'];\n        delete Entry.hw.sendQueue['buzzer_time'];\n    },\n\n    transferVibrator: function(mode, timeOn, timeOff, timeRun) {\n        // 범위 조정\n        timeOn = Math.max(timeOn, 1);\n        timeOn = Math.min(timeOn, 60000);\n        timeOff = Math.max(timeOff, 1);\n        timeOff = Math.min(timeOff, 60000);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x11);\n        Entry.hw.setDigitalPortValue('vibrator_mode', mode);\n        Entry.hw.setDigitalPortValue('vibrator_on', timeOn);\n        Entry.hw.setDigitalPortValue('vibrator_off', timeOff);\n        Entry.hw.setDigitalPortValue('vibrator_total', timeRun);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['vibrator_mode'];\n        delete Entry.hw.sendQueue['vibrator_on'];\n        delete Entry.hw.sendQueue['vibrator_off'];\n        delete Entry.hw.sendQueue['vibrator_total'];\n    },\n\n    transferIrMessage: function(irmessage) {\n        // 범위 조정\n        irmessage = Math.max(irmessage, 0);\n        irmessage = Math.min(irmessage, 127);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x10);\n        Entry.hw.setDigitalPortValue('irmessage_data', irmessage);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['irmessage_data'];\n    },\n\n    transferMotorSingle: function(motorIndex, motorDirection, motorSpeed) {\n        // 범위 조정\n        motorSpeed = Math.max(motorSpeed, 0);\n        motorSpeed = Math.min(motorSpeed, 4096);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x10);\n        Entry.hw.setDigitalPortValue('motorsingle_target', motorIndex);\n        Entry.hw.setDigitalPortValue('motorsingle_direction', motorDirection);\n        Entry.hw.setDigitalPortValue('motorsingle_value', motorSpeed);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['motorsingle_target'];\n        delete Entry.hw.sendQueue['motorsingle_direction'];\n        delete Entry.hw.sendQueue['motorsingle_value'];\n    },\n\n    transferCommand: function(target, command, option) {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('command_command', command);\n        Entry.hw.setDigitalPortValue('command_option', option);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['command_command'];\n        delete Entry.hw.sendQueue['command_option'];\n    },\n\n    transferControlDouble: function(wheel, accel) {\n        // 범위 조정\n        wheel = Math.max(wheel, -100);\n        wheel = Math.min(wheel, 100);\n        accel = Math.max(accel, 0);\n        accel = Math.min(accel, 100);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x10);\n        Entry.hw.setDigitalPortValue('control_wheel', wheel);\n        Entry.hw.setDigitalPortValue('control_accel', accel);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['control_wheel'];\n        delete Entry.hw.sendQueue['control_accel'];\n    },\n\n    transferControlQuad: function(roll, pitch, yaw, throttle) {\n        // 범위 조정\n        roll = Math.max(roll, -100);\n        roll = Math.min(roll, 100);\n        pitch = Math.max(pitch, -100);\n        pitch = Math.min(pitch, 100);\n        yaw = Math.max(yaw, -100);\n        yaw = Math.min(yaw, 100);\n        throttle = Math.max(throttle, -100);\n        throttle = Math.min(throttle, 100);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x10);\n        Entry.hw.setDigitalPortValue('control_roll', roll);\n        Entry.hw.setDigitalPortValue('control_pitch', pitch);\n        Entry.hw.setDigitalPortValue('control_yaw', yaw);\n        Entry.hw.setDigitalPortValue('control_throttle', throttle);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['control_roll'];\n        delete Entry.hw.sendQueue['control_pitch'];\n        delete Entry.hw.sendQueue['control_yaw'];\n        delete Entry.hw.sendQueue['control_throttle'];\n    },\n\n    // functions for block\n\n    // 데이터 읽기\n    getData: function(script, device) {\n        return Entry.hw.portData[device];\n    },\n\n    // LED 수동 설정\n    setLightManual: function(script, target, flags, brightness) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferLightManual(target, flags, brightness);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 버저 설정(함수 호출 시 시간은 모두 ms 단위 사용)\n    /*\n        MuteInstantally     = 1,    // 묵음 즉시 적용\n        MuteContinually     = 2,    // 묵음 예약\n\n        ScaleInstantally    = 3,    // 음계 즉시 적용\n        ScaleContinually    = 4,    // 음계 예약\n\n        HzInstantally       = 5,    // 주파수 즉시 적용\n        HzContinually       = 6,    // 주파수 예약\n     */\n    // 정지\n    setBuzzerStop: function(script) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferBuzzer(0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 묵음\n    setBuzzerMute: function(script, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 2; // 묵음 연속\n                    if (flagInstantly) mode = 1; // 묵음 즉시\n\n                    this.transferBuzzer(mode, 0xee, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setBuzzerScale: function(script, octave, scale, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 4; // Scale 연속\n                    if (flagInstantly) mode = 3; // Scale 즉시\n\n                    var scalecalc = octave * 12 + scale;\n\n                    this.transferBuzzer(mode, scalecalc, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setBuzzerHz: function(script, hz, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 6; // Hz 연속\n                    if (flagInstantly) mode = 5; // Hz 즉시\n\n                    // 범위 조정\n                    hz = Math.max(hz, 1);\n                    hz = Math.min(hz, 63999);\n\n                    this.transferBuzzer(mode, hz, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 진동 제어\n    /*\n        Stop            = 0,    // 정지\n        Instantally     = 1,    // 즉시 적용\n        Continually     = 2,    // 예약\n     */\n    setVibratorStop: function(script) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferVibrator(0, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setVibrator: function(script, timeOn, timeOff, timeRun, flagDelay, flagInstantly) {\n        timeRun = Math.max(timeRun, 0);\n        timeRun = Math.min(timeRun, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = timeRun;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 2; // 예약\n                    if (flagInstantly) mode = 1; // 즉시\n\n                    this.transferVibrator(mode, timeOn, timeOff, timeRun);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendIrMessage: function(script, irmessage) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferIrMessage(irmessage);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendStop: function(script) {\n        return this.sendCommand(script, 0x10, 0x24, 0);\n    },\n\n    sendCommand: function(script, target, command, option) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferCommand(target, command, option);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setMotorSingle: function(script, motorIndex, motorDirection, motorSpeed) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferMotorSingle(motorIndex, motorDirection, motorSpeed);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n    /*\n        None = 0,           ///< 없음\n\n        Flight = 0x10,      ///< 비행(가드 포함)\n        FlightNoGuard,      ///< 비행(가드 없음)\n        FlightFPV,          ///< 비행(FPV)\n\n        Drive = 0x20,       ///< 주행\n        DriveFPV,           ///< 주행(FPV)\n\n        Test = 0x30,        ///< 테스트\n     */\n    setModeVehicle: function(script, modeVehicle) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferCommand(0x10, 0x10, modeVehicle);\n\n                    this.transferControlDouble(0, 0);\n                    this.transferControlQuad(0, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendControlDoubleSingle: function(script, controlTarget, value, time, flagDelay) {\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    switch (controlTarget) {\n                        case 'control_wheel':\n                            {\n                                // 범위 조정\n                                value = Math.max(value, -100);\n                                value = Math.min(value, 100);\n                            }\n                            break;\n\n                        case 'control_accel':\n                            {\n                                // 범위 조정\n                                value = Math.max(value, 0);\n                                value = Math.min(value, 100);\n                            }\n                            break;\n                    }\n\n                    // 전송\n                    Entry.hw.setDigitalPortValue('target', 0x10);\n                    Entry.hw.setDigitalPortValue(controlTarget, value);\n\n                    Entry.hw.update();\n\n                    delete Entry.hw.sendQueue['target'];\n                    delete Entry.hw.sendQueue[controlTarget];\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                if (flagDelay) {\n                    // 블럭을 빠져나갈 때 변경했던 값을 초기화\n\n                    // 전송\n                    Entry.hw.setDigitalPortValue('target', 0x10);\n                    Entry.hw.setDigitalPortValue(controlTarget, 0);\n\n                    Entry.hw.update();\n\n                    delete Entry.hw.sendQueue['target'];\n                    delete Entry.hw.sendQueue[controlTarget];\n                }\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendControlDouble: function(script, wheel, accel, time, flagDelay) {\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    this.transferControlDouble(wheel, accel);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                if (flagDelay) {\n                    this.transferControlDouble(0, 0);\n                }\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\n// \nEntry.byrobot_dronefighter_drive.setLanguage = function ()\n{\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_dronefighter_drone_state_mode_system\": \"시스템 모드\",\n                \"byrobot_dronefighter_drone_state_mode_vehicle\": \"드론파이터 모드\",\n                \"byrobot_dronefighter_drone_state_mode_flight\": \"비행 모드\",\n                \"byrobot_dronefighter_drone_state_mode_drive\": \"자동차 모드\",\n                \"byrobot_dronefighter_drone_state_mode_coordinate\": \"기본 좌표계\",\n                \"byrobot_dronefighter_drone_state_battery\": \"배터리\",\n                \"byrobot_dronefighter_drone_attitude_roll\": \"자세 Roll\",\n                \"byrobot_dronefighter_drone_attitude_pitch\": \"자세 Pitch\",\n                \"byrobot_dronefighter_drone_attitude_yaw\": \"자세 Yaw\",\n                \"byrobot_dronefighter_drone_irmessage\": \"적외선 수신 값\",\n                \"byrobot_dronefighter_controller_joystick_left_x\": \"왼쪽 조이스틱 가로축\",\n                \"byrobot_dronefighter_controller_joystick_left_y\": \"왼쪽 조이스틱 세로축\",\n                \"byrobot_dronefighter_controller_joystick_left_direction\": \"왼쪽 조이스틱 방향\",\n                \"byrobot_dronefighter_controller_joystick_left_event\": \"왼쪽 조이스틱 이벤트\",\n                \"byrobot_dronefighter_controller_joystick_left_command\": \"왼쪽 조이스틱 명령\",\n                \"byrobot_dronefighter_controller_joystick_right_x\": \"오른쪽 조이스틱 가로축\",\n                \"byrobot_dronefighter_controller_joystick_right_y\": \"오른쪽 조이스틱 세로축\",\n                \"byrobot_dronefighter_controller_joystick_right_direction\": \"오른쪽 조이스틱 방향\",\n                \"byrobot_dronefighter_controller_joystick_right_event\": \"오른쪽 조이스틱 이벤트\",\n                \"byrobot_dronefighter_controller_joystick_right_command\": \"오른쪽 조이스틱 명령\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_up\": \"왼쪽 위\",\n                \"byrobot_dronefighter_controller_joystick_direction_up\": \"위\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_up\": \"오른쪽 위\",\n                \"byrobot_dronefighter_controller_joystick_direction_left\": \"왼쪽\",\n                \"byrobot_dronefighter_controller_joystick_direction_center\": \"중앙\",\n                \"byrobot_dronefighter_controller_joystick_direction_right\": \"오른쪽\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_down\": \"왼쪽 아래\",\n                \"byrobot_dronefighter_controller_joystick_direction_down\": \"아래\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_down\": \"오른쪽 아래\",\n                \"byrobot_dronefighter_controller_button_button\": \"버튼\",\n                \"byrobot_dronefighter_controller_button_event\": \"버튼 이벤트\",\n                \"byrobot_dronefighter_controller_button_front_left\": \"왼쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_front_right\": \"오른쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_front_left_right\": \"양쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up_left\": \"트림 좌회전 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up_right\": \"트림 우회전 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up\": \"트림 앞 버튼\",\n                \"byrobot_dronefighter_controller_button_center_left\": \"트림 왼쪽 버튼\",\n                \"byrobot_dronefighter_controller_button_center_right\": \"트림 오른쪽 버튼\",\n                \"byrobot_dronefighter_controller_button_center_down\": \"트림 뒤 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_left\": \"왼쪽 둥근 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_right\": \"오른쪽 둥근 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_left_right\": \"양쪽 둥근 버튼\",\n                \"byrobot_dronefighter_entryhw_count_transfer_reserved\": \"전송 예약된 데이터 수\",\n                \"byrobot_dronefighter_common_roll\": \"Roll\",\n                \"byrobot_dronefighter_common_pitch\": \"Pitch\",\n                \"byrobot_dronefighter_common_yaw\": \"Yaw\",\n                \"byrobot_dronefighter_common_throttle\": \"Throttle\",\n                \"byrobot_dronefighter_common_left\": \"왼쪽\",\n                \"byrobot_dronefighter_common_right\": \"오른쪽\",\n                \"byrobot_dronefighter_common_light_manual_on\": \"켜기\",\n                \"byrobot_dronefighter_common_light_manual_off\": \"끄기\",\n                \"byrobot_dronefighter_common_light_manual_b25\": \"밝기 25%\",\n                \"byrobot_dronefighter_common_light_manual_b50\": \"밝기 50%\",\n                \"byrobot_dronefighter_common_light_manual_b75\": \"밝기 75%\",\n                \"byrobot_dronefighter_common_light_manual_b100\": \"밝기 100%\",\n                \"byrobot_dronefighter_common_light_manual_all\": \"전체\",\n                \"byrobot_dronefighter_common_light_manual_red\": \"빨강\",\n                \"byrobot_dronefighter_common_light_manual_blue\": \"파랑\",\n                \"byrobot_dronefighter_common_light_manual_1\": \"1\",\n                \"byrobot_dronefighter_common_light_manual_2\": \"2\",\n                \"byrobot_dronefighter_common_light_manual_3\": \"3\",\n                \"byrobot_dronefighter_common_light_manual_4\": \"4\",\n                \"byrobot_dronefighter_common_light_manual_5\": \"5\",\n                \"byrobot_dronefighter_common_light_manual_6\": \"6\",\n                \"byrobot_dronefighter_controller_buzzer\": \"버저\",\n                \"byrobot_dronefighter_controller_buzzer_mute\": \"쉼\",\n                \"byrobot_dronefighter_controller_buzzer_c\": \"도\",\n                \"byrobot_dronefighter_controller_buzzer_cs\": \"도#\",\n                \"byrobot_dronefighter_controller_buzzer_d\": \"레\",\n                \"byrobot_dronefighter_controller_buzzer_ds\": \"레#\",\n                \"byrobot_dronefighter_controller_buzzer_e\": \"미\",\n                \"byrobot_dronefighter_controller_buzzer_f\": \"파\",\n                \"byrobot_dronefighter_controller_buzzer_fs\": \"파#\",\n                \"byrobot_dronefighter_controller_buzzer_g\": \"솔\",\n                \"byrobot_dronefighter_controller_buzzer_gs\": \"솔#\",\n                \"byrobot_dronefighter_controller_buzzer_a\": \"라\",\n                \"byrobot_dronefighter_controller_buzzer_as\": \"라#\",\n                \"byrobot_dronefighter_controller_buzzer_b\": \"시\",\n                \"byrobot_dronefighter_controller_userinterface_preset_clear\": \"모두 지우기\",\n                \"byrobot_dronefighter_controller_userinterface_preset_dronefighter2017\": \"기본\",\n                \"byrobot_dronefighter_controller_userinterface_preset_education\": \"교육용\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontleft_down\": \"왼쪽 빨간 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontright_down\": \"오른쪽 빨간 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnleft_down\": \"트림 좌회전 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnright_down\": \"트림 우회전 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midup_down\": \"트림 앞 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midleft_down\": \"트림 왼쪽 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midright_down\": \"트림 오른쪽 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_middown_down\": \"트림 뒤 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_up_in\": \"왼쪽 조이스틱을 위로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_left_in\": \"왼쪽 조이스틱을 왼쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_right_in\": \"왼쪽 조이스틱을 오른쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_down_in\": \"왼쪽 조이스틱을 아래로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_up_in\": \"오른쪽 조이스틱을 위로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_left_in\": \"오른쪽 조이스틱을 왼쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_right_in\": \"오른쪽 조이스틱을 오른쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_down_in\": \"오른쪽 조이스틱을 아래로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_function_joystickcalibration_reset\": \"조이스틱 보정 초기화\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_red\": \"팀 - 레드\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_blue\": \"팀 - 블루\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flight\": \"드론\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flightnoguard\": \"드론 - 가드 없음\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_drive\": \"자동차\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_local\": \"방위 - 일반\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_world\": \"방위 - 앱솔루트\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode1\": \"조종 - MODE 1\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode2\": \"조종 - MODE 2\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode3\": \"조종 - MODE 3\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode4\": \"조종 - MODE 4\",\n                \"byrobot_dronefighter_controller_userinterface_function_gyrobias_reset\": \"자이로 바이어스 리셋\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_cdc\": \"USB 시리얼 통신 장치\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_hid\": \"USB 게임 컨트롤러\",\n                \"byrobot_dronefighter_drone_team\": \"팀 \",\n                \"byrobot_dronefighter_drone_team_red\": \"레드\",\n                \"byrobot_dronefighter_drone_team_blue\": \"블루\",\n                \"byrobot_dronefighter_drone_coordinate_world\": \"앱솔루트\",\n                \"byrobot_dronefighter_drone_coordinate_local\": \"일반\",\n                \"byrobot_dronefighter_drone_mode_vehicle_flight\": \"드론\",\n                \"byrobot_dronefighter_drone_mode_vehicle_drive\": \"자동차\",\n                \"byrobot_dronefighter_drone_control_double_wheel\": \"방향\",\n                \"byrobot_dronefighter_drone_control_double_wheel_left\": \"왼쪽 회전\",\n                \"byrobot_dronefighter_drone_control_double_wheel_right\": \"오른쪽 회전\",\n                \"byrobot_dronefighter_drone_control_double_accel_forward\": \"전진\",\n                \"byrobot_dronefighter_drone_control_double_accel_backward\": \"후진\",\n                \"byrobot_dronefighter_drone_control_quad_roll\": \"Roll\",\n                \"byrobot_dronefighter_drone_control_quad_pitch\": \"Pitch\",\n                \"byrobot_dronefighter_drone_control_quad_yaw\": \"Yaw\",\n                \"byrobot_dronefighter_drone_control_quad_throttle\": \"Throttle\",\n                \"byrobot_dronefighter_drone_control_quad_roll_left\": \"왼쪽\",\n                \"byrobot_dronefighter_drone_control_quad_roll_right\": \"오른쪽\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_forward\": \"앞으로\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_backward\": \"뒤로\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_left\": \"왼쪽 회전\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_right\": \"오른쪽 회전\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_up\": \"위\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_down\": \"아래\",\n            },\n\n            // ko.js에 작성하던 내용\n            template: {\n                \"byrobot_dronefighter_drive_drone_value_attitude\": \"%1\",\n                \"byrobot_dronefighter_drive_drone_value_etc\": \"%1\",\n                \"byrobot_dronefighter_drive_controller_value_button\": \"%1\",\n                \"byrobot_dronefighter_drive_controller_value_joystick\": \"%1\",\n                \"byrobot_dronefighter_drive_controller_if_button_press\": \"조종기 %1 눌렀을 때\",\n                \"byrobot_dronefighter_drive_controller_if_joystick_direction\": \"조종기 %1 조이스틱 %2 움직였을 때\",\n                \"byrobot_dronefighter_drive_drone_control_car_stop\": \"자동차 정지 %1\",\n                \"byrobot_dronefighter_drive_drone_control_double_one\": \"자동차를 %1 %2% 정하기 %3\",\n                \"byrobot_dronefighter_drive_drone_control_double_one_delay\": \"자동차를 %1 %2% %3 초 실행 %4\",\n                \"byrobot_dronefighter_drive_drone_control_double\": \"자동차를 방향 %1%, 전진 %2% 정하기 %3\",\n                \"byrobot_dronefighter_drive_drone_motor_stop\": \"모터 정지 %1\",\n                \"byrobot_dronefighter_drive_drone_motorsingle\": \"%1 번 모터를 %2 (으)로 회전 %3\",\n                \"byrobot_dronefighter_drive_drone_motorsingle_input\": \"%1 번 모터를 %2 (으)로 회전 %3\",\n                \"byrobot_dronefighter_drive_drone_irmessage\": \"적외선으로 %1 값 보내기 %2\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single_off\": \"조종기 LED 끄기 %1\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single\": \"조종기 LED %1 %2 %3\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single_input\": \"조종기 LED %1 밝기 %2 %3\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single_off\": \"자동차 LED 끄기 %1\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single\": \"자동차 LED %1 %2 %3\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single_input\": \"자동차 LED %1 밝기 %2 %3\",\n                \"byrobot_dronefighter_drive_controller_buzzer_off\": \"버저 끄기 %1\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale\": \"%1 옥타브 %2 을(를) 연주 %3\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale_delay\": \"%1 옥타브 %2 을(를) %3 초 연주 %4\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale_reserve\": \"%1 옥타브 %2 을(를) %3 초 예약 %4\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz\": \"%1 Hz 소리를 연주 %2\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz_delay\": \"%1 Hz 소리를 %2 초 연주 %3\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz_reserve\": \"%1 Hz 소리를 %2 초 예약 %3\",\n                \"byrobot_dronefighter_drive_controller_vibrator_off\": \"진동 끄기 %1\",\n                \"byrobot_dronefighter_drive_controller_vibrator_on_delay\": \"진동 %1 초 켜기 %2\",\n                \"byrobot_dronefighter_drive_controller_vibrator_on_reserve\": \"진동 %1 초 예약 %2\",\n                \"byrobot_dronefighter_drive_controller_vibrator_delay\": \"진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4\",\n                \"byrobot_dronefighter_drive_controller_vibrator_reserve\": \"진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4\",\n            },\n\n            Helper: {\n                \"byrobot_dronefighter_drive_drone_value_attitude\": \"<br>자동차의 현재 자세를 각도로 반환합니다. Roll은 좌우 기울기(-90 ~ 90), Pitch는 앞뒤 기울기(-90 ~ 90), Yaw는 회전 각도(-180 ~ 180) 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#자동차</font> <font color='forestgreen'>#자세</font>\",\n                \"byrobot_dronefighter_drive_drone_value_etc\": \"<br>드론파이터 설정과 관련된 값들과 적외선 통신으로 받은 값을 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#자동차</font> <font color='forestgreen'>#기타</font>\",\n                \"byrobot_dronefighter_drive_controller_value_button\": \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_dronefighter_drive_controller_value_joystick\": \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_dronefighter_drive_controller_if_button_press\": \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_dronefighter_drive_controller_if_joystick_direction\": \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_dronefighter_drive_drone_control_car_stop\": \"<br>자동차 작동을 정지합니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#정지</font>\",\n                \"byrobot_dronefighter_drive_drone_control_double_one\": \"<br>자동차 조종 값을 지정합니다. 입력 가능한 값의 범위는 방향 -100 ~ 100, 전진 0 ~ 100입니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#조종</font>\",\n                \"byrobot_dronefighter_drive_drone_control_double_one_delay\": \"<br>자동차 조종 값을 지정합니다. 입력 가능한 값의 범위는 방향 -100 ~ 100, 전진 0 ~ 100입니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                \"byrobot_dronefighter_drive_drone_control_double\": \"<br>자동차 조종 값을 지정합니다. 입력 가능한 값의 범위는 방향 -100 ~ 100, 전진 0 ~ 100입니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#조종</font>\",\n                \"byrobot_dronefighter_drive_drone_motor_stop\": \"<br>모든 모터의 작동을 정지합니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#모터정지</font>\",\n                \"byrobot_dronefighter_drive_drone_motorsingle\": \"<br>지정한 모터를 원하는 빠르기로 회전할 때 사용합니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_dronefighter_drive_drone_motorsingle_input\": \"<br>지정한 모터(1, 2, 3, 4)를 원하는 빠르기로 회전할 때 사용합니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_dronefighter_drive_drone_irmessage\": \"<br>적외선으로 지정한 값을 보냅니다. 사용 가능한 값의 범위는 0 ~ 127입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#적외선통신</font>\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single_off\": \"<br>자동차의 모든 LED를 끕니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single\": \"<br>자동차의 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single_input\": \"<br>자동차 LED 여러 개의 밝기를 동시에 변경할 때 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>각각의 비트는 개별 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single_off\": \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single\": \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single_input\": \"<br>조종기 LED 여러 개의 밝기를 동시에 변경할 때 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>각각의 비트는 개별 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_drive_controller_buzzer_off\": \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale\": \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale_delay\": \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale_reserve\": \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz\": \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz_delay\": \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz_reserve\": \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                \"byrobot_dronefighter_drive_controller_vibrator_off\": \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                \"byrobot_dronefighter_drive_controller_vibrator_on_delay\": \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_dronefighter_drive_controller_vibrator_on_reserve\": \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_dronefighter_drive_controller_vibrator_delay\": \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_dronefighter_drive_controller_vibrator_reserve\": \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n            }\n        },\n\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_dronefighter_drone_state_mode_system\": \"system Mode\",\n                \"byrobot_dronefighter_drone_state_mode_vehicle\": \"vehicle Mode\",\n                \"byrobot_dronefighter_drone_state_mode_flight\": \"flight Mode\",\n                \"byrobot_dronefighter_drone_state_mode_drive\": \"drive Mode\",\n                \"byrobot_dronefighter_drone_state_mode_coordinate\": \"coordinate\",\n                \"byrobot_dronefighter_drone_state_battery\": \"battery\",\n                \"byrobot_dronefighter_drone_attitude_roll\": \"attitude - roll\",\n                \"byrobot_dronefighter_drone_attitude_pitch\": \"attitude - pitch\",\n                \"byrobot_dronefighter_drone_attitude_yaw\": \"attitude - yaw\",\n                \"byrobot_dronefighter_drone_irmessage\": \"IR data Received\",\n                \"byrobot_dronefighter_controller_joystick_left_x\": \"left joystick horizontal\",\n                \"byrobot_dronefighter_controller_joystick_left_y\": \"left joystick vertical\",\n                \"byrobot_dronefighter_controller_joystick_left_direction\": \"left joystick direction\",\n                \"byrobot_dronefighter_controller_joystick_left_event\": \"left joystick event\",\n                \"byrobot_dronefighter_controller_joystick_left_command\": \"left joystick command\",\n                \"byrobot_dronefighter_controller_joystick_right_x\": \"right joystick horizontal\",\n                \"byrobot_dronefighter_controller_joystick_right_y\": \"right joystick vertical\",\n                \"byrobot_dronefighter_controller_joystick_right_direction\": \"right joystick direction\",\n                \"byrobot_dronefighter_controller_joystick_right_event\": \"right joystick event\",\n                \"byrobot_dronefighter_controller_joystick_right_command\": \"right joystick command\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_up\": \"left up\",\n                \"byrobot_dronefighter_controller_joystick_direction_up\": \"up\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_up\": \"right up\",\n                \"byrobot_dronefighter_controller_joystick_direction_left\": \"left\",\n                \"byrobot_dronefighter_controller_joystick_direction_center\": \"center\",\n                \"byrobot_dronefighter_controller_joystick_direction_right\": \"right\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_down\": \"left down\",\n                \"byrobot_dronefighter_controller_joystick_direction_down\": \"down\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_down\": \"right down\",\n                \"byrobot_dronefighter_controller_button_button\": \"button\",\n                \"byrobot_dronefighter_controller_button_event\": \"button event\",\n                \"byrobot_dronefighter_controller_button_front_left\": \"left red button\",\n                \"byrobot_dronefighter_controller_button_front_right\": \"right red button\",\n                \"byrobot_dronefighter_controller_button_front_left_right\": \"both red button\",\n                \"byrobot_dronefighter_controller_button_center_up_left\": \"trim-turn-left button\",\n                \"byrobot_dronefighter_controller_button_center_up_right\": \"trim-turn-right button\",\n                \"byrobot_dronefighter_controller_button_center_up\": \"trim-forward button\",\n                \"byrobot_dronefighter_controller_button_center_left\": \"trim-left button\",\n                \"byrobot_dronefighter_controller_button_center_right\": \"trim-right button\",\n                \"byrobot_dronefighter_controller_button_center_down\": \"trim-backward button\",\n                \"byrobot_dronefighter_controller_button_bottom_left\": \"left round button\",\n                \"byrobot_dronefighter_controller_button_bottom_right\": \"right round button\",\n                \"byrobot_dronefighter_controller_button_bottom_left_right\": \"both round button\",\n                \"byrobot_dronefighter_entryhw_count_transfer_reserved\": \"reserved data blocks\",\n                \"byrobot_dronefighter_common_roll\": \"roll\",\n                \"byrobot_dronefighter_common_pitch\": \"pitch\",\n                \"byrobot_dronefighter_common_yaw\": \"yaw\",\n                \"byrobot_dronefighter_common_throttle\": \"throttle\",\n                \"byrobot_dronefighter_common_left\": \"left\",\n                \"byrobot_dronefighter_common_right\": \"right\",\n                \"byrobot_dronefighter_common_light_manual_on\": \"on\",\n                \"byrobot_dronefighter_common_light_manual_off\": \"off\",\n                \"byrobot_dronefighter_common_light_manual_b25\": \"brightness 25%\",\n                \"byrobot_dronefighter_common_light_manual_b50\": \"brightness 50%\",\n                \"byrobot_dronefighter_common_light_manual_b75\": \"brightness 75%\",\n                \"byrobot_dronefighter_common_light_manual_b100\": \"brightness 100%\",\n                \"byrobot_dronefighter_common_light_manual_all\": \"all\",\n                \"byrobot_dronefighter_common_light_manual_red\": \"red\",\n                \"byrobot_dronefighter_common_light_manual_blue\": \"blue\",\n                \"byrobot_dronefighter_common_light_manual_1\": \"1\",\n                \"byrobot_dronefighter_common_light_manual_2\": \"2\",\n                \"byrobot_dronefighter_common_light_manual_3\": \"3\",\n                \"byrobot_dronefighter_common_light_manual_4\": \"4\",\n                \"byrobot_dronefighter_common_light_manual_5\": \"5\",\n                \"byrobot_dronefighter_common_light_manual_6\": \"6\",\n                \"byrobot_dronefighter_controller_buzzer\": \"buzzer\",\n                \"byrobot_dronefighter_controller_buzzer_mute\": \"mute\",\n                \"byrobot_dronefighter_controller_buzzer_c\": \"C\",\n                \"byrobot_dronefighter_controller_buzzer_cs\": \"C#\",\n                \"byrobot_dronefighter_controller_buzzer_d\": \"D\",\n                \"byrobot_dronefighter_controller_buzzer_ds\": \"D#\",\n                \"byrobot_dronefighter_controller_buzzer_e\": \"E\",\n                \"byrobot_dronefighter_controller_buzzer_f\": \"F\",\n                \"byrobot_dronefighter_controller_buzzer_fs\": \"F#\",\n                \"byrobot_dronefighter_controller_buzzer_g\": \"G\",\n                \"byrobot_dronefighter_controller_buzzer_gs\": \"G#\",\n                \"byrobot_dronefighter_controller_buzzer_a\": \"A\",\n                \"byrobot_dronefighter_controller_buzzer_as\": \"A#\",\n                \"byrobot_dronefighter_controller_buzzer_b\": \"B\",\n                \"byrobot_dronefighter_controller_userinterface_preset_clear\": \"clear\",\n                \"byrobot_dronefighter_controller_userinterface_preset_dronefighter2017\": \"default\",\n                \"byrobot_dronefighter_controller_userinterface_preset_education\": \"education\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontleft_down\": \"press left red button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontright_down\": \"press right red button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnleft_down\": \"press trim-left-turn button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnright_down\": \"press trim-right-turn button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midup_down\": \"press trim-forward button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midleft_down\": \"press trim-left button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midright_down\": \"press trim-right button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_middown_down\": \"press trim-backward button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_up_in\": \"left joystick move up\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_left_in\": \"left joystick move left\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_right_in\": \"left joystick move right\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_down_in\": \"left joystick move down\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_up_in\": \"right joystick move up\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_left_in\": \"right joystick move left\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_right_in\": \"right joystick move right\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_down_in\": \"right joystick move down\",\n                \"byrobot_dronefighter_controller_userinterface_function_joystickcalibration_reset\": \"reset joystick calibration\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_red\": \"team - red\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_blue\": \"team - blue\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flight\": \"flight\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flightnoguard\": \"flight - no guard\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_drive\": \"drive\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_local\": \"coordinate - normal\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_world\": \"coordinate - absolute\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode1\": \"control - MODE 1\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode2\": \"control - MODE 2\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode3\": \"control - MODE 3\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode4\": \"control - MODE 4\",\n                \"byrobot_dronefighter_controller_userinterface_function_gyrobias_reset\": \"reset gyro bias\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_cdc\": \"USB serial device\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_hid\": \"USB game controller\",\n                \"byrobot_dronefighter_drone_team\": \"team\",\n                \"byrobot_dronefighter_drone_team_red\": \"red\",\n                \"byrobot_dronefighter_drone_team_blue\": \"blue\",\n                \"byrobot_dronefighter_drone_coordinate_world\": \"absolute\",\n                \"byrobot_dronefighter_drone_coordinate_local\": \"normal\",\n                \"byrobot_dronefighter_drone_mode_vehicle_flight\": \"flight\",\n                \"byrobot_dronefighter_drone_mode_vehicle_drive\": \"drive\",\n                \"byrobot_dronefighter_drone_control_double_wheel\": \"direction\",\n                \"byrobot_dronefighter_drone_control_double_wheel_left\": \"turn left\",\n                \"byrobot_dronefighter_drone_control_double_wheel_right\": \"turn right\",\n                \"byrobot_dronefighter_drone_control_double_accel_forward\": \"forward\",\n                \"byrobot_dronefighter_drone_control_double_accel_backward\": \"backward\",\n                \"byrobot_dronefighter_drone_control_quad_roll\": \"roll\",\n                \"byrobot_dronefighter_drone_control_quad_pitch\": \"pitch\",\n                \"byrobot_dronefighter_drone_control_quad_yaw\": \"yaw\",\n                \"byrobot_dronefighter_drone_control_quad_throttle\": \"throttle\",\n                \"byrobot_dronefighter_drone_control_quad_roll_left\": \"left\",\n                \"byrobot_dronefighter_drone_control_quad_roll_right\": \"right\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_forward\": \"foward\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_backward\": \"backward\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_left\": \"turn Left\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_right\": \"turn Right\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_up\": \"up\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_down\": \"down\",\n            },\n\n            // en.js에 작성하던 내용\n            template: {\n                \"byrobot_dronefighter_drive_drone_value_attitude\": \"%1\",\n                \"byrobot_dronefighter_drive_drone_value_etc\": \"%1\",\n                \"byrobot_dronefighter_drive_controller_value_button\": \"%1\",\n                \"byrobot_dronefighter_drive_controller_value_joystick\": \"%1\",\n                \"byrobot_dronefighter_drive_controller_if_button_press\": \"when press %1\",\n                \"byrobot_dronefighter_drive_controller_if_joystick_direction\": \"when %1 stick move to %2\",\n                \"byrobot_dronefighter_drive_drone_control_car_stop\": \"stop %1\",\n                \"byrobot_dronefighter_drive_drone_control_double_one\": \"set %1 to %2 %3\",\n                \"byrobot_dronefighter_drive_drone_control_double_one_delay\": \"set %1 to %2 and run for %3 second %4\",\n                \"byrobot_dronefighter_drive_drone_control_double\": \"set wheel to %1, forward to %2 %3\",\n                \"byrobot_dronefighter_drive_drone_motor_stop\": \"turn off all motors %1\",\n                \"byrobot_dronefighter_drive_drone_motorsingle\": \"set rotate for number %1 motor to %2 %3\",\n                \"byrobot_dronefighter_drive_drone_motorsingle_input\": \"set rotate for number %1 motor to %2 %3\",\n                \"byrobot_dronefighter_drive_drone_irmessage\": \"send %1 to the IR transmitter %2\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single_off\": \"turn off all controller LEDs %1\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single\": \"change the state of %1 controller LED to %2 %3\",\n                \"byrobot_dronefighter_drive_controller_light_manual_single_input\": \"change the brightness of %1 controller LED to %2 %3\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single_off\": \"turn off all drone LEDs %1\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single\": \"change the state of %1 drone LED to %2 %3\",\n                \"byrobot_dronefighter_drive_drone_light_manual_single_input\": \"change the brightness of %1 drone LED to %2 %3\",\n                \"byrobot_dronefighter_drive_controller_buzzer_off\": \"turn off the buzzer %1\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale\": \"play %1 octave %2 %3\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale_delay\": \"play %1 octave %2 for %3 second %4\",\n                \"byrobot_dronefighter_drive_controller_buzzer_scale_reserve\": \"reserve to play %1 octave %2 for %3 second %4\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz\": \"play %1 Hz sound %2\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz_delay\": \"play %1 Hz sound for %2 second %3\",\n                \"byrobot_dronefighter_drive_controller_buzzer_hz_reserve\": \"reserve to play %1 Hz sound for %2 second %3\",\n                \"byrobot_dronefighter_drive_controller_vibrator_off\": \"turn off the vibrator %1\",\n                \"byrobot_dronefighter_drive_controller_vibrator_on_delay\": \"turn on the vibrator for %1 second %2\",\n                \"byrobot_dronefighter_drive_controller_vibrator_on_reserve\": \"reserve turn on the vibrator for %1 second %2\",\n                \"byrobot_dronefighter_drive_controller_vibrator_delay\": \"vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_dronefighter_drive_controller_vibrator_reserve\": \"reserve vibration %1 second on, %2 second off for %3 seconds %4\",\n            },\n            \n            Helper: {\n\n            }\n        }\n    }\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 이름\n ***************************************************************************************/\nEntry.byrobot_dronefighter_drive.blockMenuBlocks = [\n    'byrobot_dronefighter_drive_drone_value_attitude',\n    'byrobot_dronefighter_drive_drone_value_etc',\n    'byrobot_dronefighter_drive_controller_value_button',\n    'byrobot_dronefighter_drive_controller_value_joystick',\n    'byrobot_dronefighter_drive_controller_if_button_press',\n    'byrobot_dronefighter_drive_controller_if_joystick_direction',\n    'byrobot_dronefighter_drive_drone_control_car_stop',\n    'byrobot_dronefighter_drive_drone_control_double_one',\n    'byrobot_dronefighter_drive_drone_control_double_one_delay',\n    'byrobot_dronefighter_drive_drone_control_double',\n    'byrobot_dronefighter_drive_drone_motor_stop',\n    'byrobot_dronefighter_drive_drone_motorsingle',\n    'byrobot_dronefighter_drive_drone_motorsingle_input',\n    'byrobot_dronefighter_drive_drone_irmessage',\n    'byrobot_dronefighter_drive_drone_light_manual_single_off',\n    'byrobot_dronefighter_drive_drone_light_manual_single',\n    'byrobot_dronefighter_drive_drone_light_manual_single_input',\n    'byrobot_dronefighter_drive_controller_light_manual_single_off',\n    'byrobot_dronefighter_drive_controller_light_manual_single',\n    'byrobot_dronefighter_drive_controller_light_manual_single_input',\n    'byrobot_dronefighter_drive_controller_buzzer_off',\n    'byrobot_dronefighter_drive_controller_buzzer_scale',\n    'byrobot_dronefighter_drive_controller_buzzer_scale_delay',\n    'byrobot_dronefighter_drive_controller_buzzer_scale_reserve',\n    'byrobot_dronefighter_drive_controller_buzzer_hz',\n    'byrobot_dronefighter_drive_controller_buzzer_hz_delay',\n    'byrobot_dronefighter_drive_controller_buzzer_hz_reserve',\n    'byrobot_dronefighter_drive_controller_vibrator_off',\n    'byrobot_dronefighter_drive_controller_vibrator_on_delay',\n    'byrobot_dronefighter_drive_controller_vibrator_on_reserve',\n    'byrobot_dronefighter_drive_controller_vibrator_delay',\n    'byrobot_dronefighter_drive_controller_vibrator_reserve',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 상세\n ***************************************************************************************/\nEntry.byrobot_dronefighter_drive.getBlocks = function() {\n    return {\n        //region byrobot 바이로봇\n        /* BYROBOT DroneFighter Drive Start */\n        byrobot_dronefighter_drive_drone_value_attitude: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_drone_attitude_roll, 'attitude_roll'],\n                        [Lang.Blocks.byrobot_dronefighter_drone_attitude_pitch, 'attitude_pitch'],\n                        [Lang.Blocks.byrobot_dronefighter_drone_attitude_yaw, 'attitude_yaw'],\n                    ],\n                    value: 'attitude_roll', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_drone_value_attitude', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n                return read[device];\n            },\n        },\n        byrobot_dronefighter_drive_drone_value_etc: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_state_mode_vehicle,\n                            'state_modeVehicle',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_state_mode_drive,\n                            'state_modeDrive',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_drone_state_battery, 'state_battery'],\n                        [Lang.Blocks.byrobot_dronefighter_drone_irmessage, 'irmessage_irdata'],\n                    ],\n                    value: 'irmessage_irdata', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_drone_value_etc', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n                return read[device];\n            },\n        },\n        byrobot_dronefighter_drive_controller_value_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_button_button,\n                            'button_button',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_event, 'button_event'],\n                    ],\n                    value: 'button_button', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_controller_value_button', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n                return read[device];\n            },\n        },\n        byrobot_dronefighter_drive_controller_value_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_x,\n                            'joystick_left_x',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_y,\n                            'joystick_left_y',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_direction,\n                            'joystick_left_direction',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_event,\n                            'joystick_left_event',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_command,\n                            'joystick_left_command',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_x,\n                            'joystick_right_x',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_y,\n                            'joystick_right_y',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_direction,\n                            'joystick_right_direction',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_event,\n                            'joystick_right_event',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_command,\n                            'joystick_right_command',\n                        ],\n                    ],\n                    value: 'joystick_left_x', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_controller_value_joystick', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n                return read[device];\n            },\n        },\n        byrobot_dronefighter_drive_controller_if_button_press: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_left, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_right, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_left_right, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up_left, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up_right, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up, '16'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_left, '32'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_right, '64'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_down, '128'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_bottom_left, '256'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_bottom_right, '512'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_button_bottom_left_right,\n                            '768',\n                        ],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'byrobot_dronefighter_drive_boolean_input',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var button = 'button_button'; // paramsKeyMap에 정의된 이름 사용\n                var buttonevent = 'button_event'; // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2)\n                    return true;\n                else return false;\n            },\n            syntax: { js: [], py: [] },\n        },\n        byrobot_dronefighter_drive_controller_if_joystick_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_dronefighter_common_right, 'joystick_right_direction'],\n                    ],\n                    value: 'joystick_left_direction',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_left_up,\n                            '17',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_up, '18'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_right_up,\n                            '20',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_left, '33'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_center,\n                            '34',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_right,\n                            '36',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_joystick_direction_left_down,\n                            '65',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_down, '66'],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_joystick_direction_right_down,\n                            '68',\n                        ],\n                    ],\n                    value: '34',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_dronefighter_drive_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                DIRECTION: 1,\n            },\n            class: 'byrobot_dronefighter_drive_boolean_input',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION')) return true;\n                else return false;\n            },\n        },\n        byrobot_dronefighter_drive_drone_control_car_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_drone_control_car_stop',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_drive_control_drive',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_drive.sendStop(script);\n            },\n        },\n        byrobot_dronefighter_drive_drone_control_double_one: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_control_double_wheel,\n                            'control_wheel',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_control_double_accel_forward,\n                            'control_accel',\n                        ],\n                    ],\n                    value: 'control_accel',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_drone_control_double_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE: 1,\n            },\n            class: 'byrobot_dronefighter_drive_control_drive',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var controlTarget = script.getField('CONTROLTARGET');\n                var value = parseInt(script.getNumberValue('VALUE', script));\n\n                return Entry.byrobot_dronefighter_drive.sendControlDoubleSingle(\n                    script,\n                    controlTarget,\n                    value,\n                    0,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_drive_drone_control_double_one_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_control_double_wheel,\n                            'control_wheel',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_control_double_accel_forward,\n                            'control_accel',\n                        ],\n                    ],\n                    value: 'control_accel',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_drone_control_double_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_dronefighter_drive_control_drive',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var controlTarget = script.getField('CONTROLTARGET');\n                var value = parseInt(script.getNumberValue('VALUE', script));\n                var time = parseInt(script.getNumberValue('TIME', script) * 1000);\n\n                return Entry.byrobot_dronefighter_drive.sendControlDoubleSingle(\n                    script,\n                    controlTarget,\n                    value,\n                    time,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_drive_drone_control_double: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_drone_control_double',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                ACCEL: 1,\n            },\n            class: 'byrobot_dronefighter_drive_control_drive',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var wheel = parseInt(script.getNumberValue('WHEEL', script));\n                var accel = parseInt(script.getNumberValue('ACCEL', script));\n                return Entry.byrobot_dronefighter_drive.sendControlDouble(\n                    script,\n                    wheel,\n                    accel,\n                    0,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_drive_drone_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_drive_motor',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_drive.sendStop(script);\n            },\n        },\n        byrobot_dronefighter_drive_drone_motorsingle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1'], ['3', '2'], ['4', '3']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_drone_motorsingle',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class: 'byrobot_dronefighter_drive_motor',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var motorIndex = parseInt(script.getField('MOTORINDEX'));\n                var motorDirection = 1;\n                var motorSpeed = parseInt(script.getNumberValue('MOTORSPEED', script));\n\n                return Entry.byrobot_dronefighter_drive.setMotorSingle(\n                    script,\n                    motorIndex,\n                    motorDirection,\n                    motorSpeed\n                );\n            },\n        },\n        byrobot_dronefighter_drive_drone_motorsingle_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_drone_motorsingle_input',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class: 'byrobot_dronefighter_drive_motor',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var motorIndex = parseInt(script.getNumberValue('MOTORINDEX', script)) - 1;\n                var motorDirection = 1;\n                var motorSpeed = parseInt(script.getNumberValue('MOTORSPEED', script));\n\n                return Entry.byrobot_dronefighter_drive.setMotorSingle(\n                    script,\n                    motorIndex,\n                    motorDirection,\n                    motorSpeed\n                );\n            },\n        },\n        byrobot_dronefighter_drive_drone_irmessage: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_drone_irmessage',\n            },\n            paramsKeyMap: {\n                IRMESSAGE: 0,\n            },\n            class: 'byrobot_dronefighter_drive_irmessage',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var irmessage = script.getNumberValue('IRMESSAGE', script);\n                return Entry.byrobot_dronefighter_drive.sendIrMessage(script, irmessage);\n            },\n        },\n        byrobot_dronefighter_drive_controller_light_manual_single_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_drive_controller_light',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_drive.setLightManual(script, 0x11, 0xff, 0);\n            },\n        },\n        byrobot_dronefighter_drive_controller_light_manual_single: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_all, '255'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_1, '128'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_2, '64'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_3, '32'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_4, '16'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_5, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_6, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_blue, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_red, '1'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_on, '220'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_off, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b25, '75'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b50, '125'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b75, '200'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b100, '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_drive_controller_light_manual_single',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_drive_controller_light',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var flags = parseInt(script.getField('FLAGS'));\n                var brightness = parseInt(script.getField('BRIGHTNESS'));\n                return Entry.byrobot_dronefighter_drive.setLightManual(\n                    script,\n                    0x11,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_drive_controller_light_manual_single_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0xFF'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_drive_controller_light',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_dronefighter_drive.setLightManual(\n                    script,\n                    0x11,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_drive_drone_light_manual_single_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_drive_drone_light',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_drive.setLightManual(script, 0x10, 0xff, 0);\n            },\n        },\n        byrobot_dronefighter_drive_drone_light_manual_single: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_all, '255'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_1, '128'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_2, '64'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_3, '32'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_4, '16'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_blue, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_red, '4'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_on, '220'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_off, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b25, '75'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b50, '125'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b75, '200'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b100, '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_drive_drone_light_manual_single',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_drive_drone_light',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var flags = parseInt(script.getField('FLAGS'));\n                var brightness = parseInt(script.getField('BRIGHTNESS'));\n                return Entry.byrobot_dronefighter_drive.setLightManual(\n                    script,\n                    0x10,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_drive_drone_light_manual_single_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0xFF'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_drive_drone_light',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_dronefighter_drive.setLightManual(\n                    script,\n                    0x10,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_drive_controller_buzzer_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_drive_buzzer',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_drive.setBuzzerStop(script);\n            },\n        },\n        byrobot_dronefighter_drive_controller_buzzer_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_drive_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n            },\n            class: 'byrobot_dronefighter_drive_buzzer',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_drive.setBuzzerMute(\n                        script,\n                        60000,\n                        false,\n                        true\n                    );\n                else\n                    return Entry.byrobot_dronefighter_drive.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        60000,\n                        false,\n                        true\n                    );\n            },\n        },\n        byrobot_dronefighter_drive_controller_buzzer_scale_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_dronefighter_drive_buzzer',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_drive.setBuzzerMute(script, time, true, true);\n                else\n                    return Entry.byrobot_dronefighter_drive.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        time,\n                        true,\n                        true\n                    );\n            },\n        },\n        byrobot_dronefighter_drive_controller_buzzer_scale_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_dronefighter_drive_buzzer',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_drive.setBuzzerMute(\n                        script,\n                        time,\n                        false,\n                        false\n                    );\n                else\n                    return Entry.byrobot_dronefighter_drive.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        time,\n                        false,\n                        false\n                    );\n            },\n        },\n        byrobot_dronefighter_drive_controller_buzzer_hz: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'byrobot_dronefighter_drive_buzzer',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                return Entry.byrobot_dronefighter_drive.setBuzzerHz(script, hz, 60000, false, true);\n            },\n        },\n        byrobot_dronefighter_drive_controller_buzzer_hz_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_dronefighter_drive_buzzer',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_dronefighter_drive.setBuzzerHz(script, hz, time, true, true);\n            },\n        },\n        byrobot_dronefighter_drive_controller_buzzer_hz_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_dronefighter_drive_buzzer',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_dronefighter_drive.setBuzzerHz(script, hz, time, false, false);\n            },\n        },\n        byrobot_dronefighter_drive_controller_vibrator_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_drive_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_drive_vibrator',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_drive.setVibratorStop(script);\n            },\n        },\n        byrobot_dronefighter_drive_controller_vibrator_on_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_dronefighter_drive_vibrator',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_dronefighter_drive.setVibrator(\n                    script,\n                    timeOn,\n                    0,\n                    timeOn,\n                    true,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_drive_controller_vibrator_on_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_dronefighter_drive_vibrator',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_dronefighter_drive.setVibrator(\n                    script,\n                    timeOn,\n                    0,\n                    timeOn,\n                    false,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_drive_controller_vibrator_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.02'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_dronefighter_drive_vibrator',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_dronefighter_drive.setVibrator(\n                    script,\n                    timeOn,\n                    timeOff,\n                    timeRun,\n                    true,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_drive_controller_vibrator_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.02'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_drive_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_dronefighter_drive_vibrator',\n            isNotFor: ['byrobot_dronefighter_drive'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_dronefighter_drive.setVibrator(\n                    script,\n                    timeOn,\n                    timeOff,\n                    timeRun,\n                    false,\n                    false\n                );\n            },\n        },\n        /* BYROBOT DroneFighter Drive End */\n        //endregion byrobot 바이로봇\n    };\n};\n\nmodule.exports = Entry.byrobot_dronefighter_drive;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_dronefighter_flight.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n/***************************************************************************************\n *  장치와 연관된 변수 및 함수 정의\n ***************************************************************************************/\n\nEntry.byrobot_dronefighter_flight = {\n    id: 'F.3',\n    name: 'byrobot_dronefighter_flight',\n    url: 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_dronefighter_flight.png',\n    title: {\n        ko: '바이로봇 드론파이터 드론',\n        en: 'BYROBOT Drone Fighter flight',\n    },\n\n    // 초기화\n    setZero: function() {\n        // 초기화\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (var i = 0; i < 1; i++) {\n            this.transferCommand(0x10, 0x24, 0);\n            this.transferVibrator(0, 0, 0, 0);\n            this.transferBuzzer(0, 0, 0);\n            this.transferLightManual(0x10, 0xff, 0);\n            this.transferLightManual(0x11, 0xff, 0);\n        }\n    },\n\n    // Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n    // listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\n    monitorTemplate: {\n        imgPath: 'hw/byrobot_dronefighter_flight.png', // 배경 이미지\n        width: 500, // 이미지의 폭\n        height: 500, // 이미지의 높이\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeVehicle:              {name: 'Vehicle Mode',              type: 'input',  pos: { x: 0, y: 0 }},\n            state_modeFlight:               {name: 'Flight Mode',               type: 'input',  pos: { x: 0, y: 0 },},\n            state_coordinate:               {name: 'Headless',                  type: 'input',  pos: { x: 0, y: 0 },},\n            state_modeDrive:                {name: 'Drive Mode',                type: 'input',  pos: { x: 0, y: 0 }},\n            state_battery:                  {name: 'Battery',                   type: 'input',  pos: { x: 0, y: 0 }},\n            attitude_roll:                  {name: 'Roll',                      type: 'input',  pos: { x: 0, y: 0 }},\n            attitude_pitch:                 {name: 'Pitch',                     type: 'input',  pos: { x: 0, y: 0 }},\n            attitude_yaw:                   {name: 'Yaw',                       type: 'input',  pos: { x: 0, y: 0 }},\n            irmessage_irdata:               {name: 'IR Data',                   type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_x:                {name: 'Left Joystick X',           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_y:                {name: 'Left Joystick Y',           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_direction:        {name: 'Left Joystick Direction',   type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_event:            {name: 'Left Joystick Event',       type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_command:          {name: 'Left Joystick Command',     type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_x:               {name: 'Right Joystick X',          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_y:               {name: 'Right Joystick Y',          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_direction:       {name: 'Right Joystick Direction',  type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_event:           {name: 'Right Joystick Event',      type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_command:         {name: 'Right Joystick Command',    type: 'input',  pos: { x: 0, y: 0 }},\n            button_button:                  {name: 'Button',                    type: 'input',  pos: { x: 0, y: 0 }},\n            button_event:                   {name: 'Button Event',              type: 'input',  pos: { x: 0, y: 0 }},\n            entryhw_countTransferReserved:  {name: 'Transfer Buffer',           type: 'output', pos: { x: 0, y: 0 }},\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both', // 표시 모드\n    },\n\n    // functions\n\n    // 시간 지연\n    checkFinish: function(script, ms) {\n        if (!script.isStart) {\n            script.isStart = true;\n            script.timeFlag = 1;\n\n            var fps = Entry.FPS || 60;\n            var timeValue = 60 / fps * ms;\n\n            setTimeout(function() {\n                script.timeFlag = 0;\n            }, timeValue);\n\n            return 'Start';\n        } else if (script.timeFlag == 1) {\n            return 'Running';\n        } else {\n            delete script.timeFlag;\n            delete script.isStart;\n            Entry.engine.isContinue = false;\n            return 'Finish';\n        }\n    },\n\n    // 데이터 전송\n    transferLightManual: function(target, flags, brightness) {\n        // 범위 조정\n        target = Math.max(target, 0);\n        target = Math.min(target, 255);\n        flags = Math.max(flags, 0);\n        flags = Math.min(flags, 255);\n        brightness = Math.max(brightness, 0);\n        brightness = Math.min(brightness, 255);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('light_manual_flags', flags);\n        Entry.hw.setDigitalPortValue('light_manual_brightness', brightness);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['light_manual_flags'];\n        delete Entry.hw.sendQueue['light_manual_brightness'];\n    },\n\n    transferBuzzer: function(mode, value, time) {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x11);\n        Entry.hw.setDigitalPortValue('buzzer_mode', mode);\n        Entry.hw.setDigitalPortValue('buzzer_value', value);\n        Entry.hw.setDigitalPortValue('buzzer_time', time);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['buzzer_mode'];\n        delete Entry.hw.sendQueue['buzzer_value'];\n        delete Entry.hw.sendQueue['buzzer_time'];\n    },\n\n    transferVibrator: function(mode, timeOn, timeOff, timeRun) {\n        // 범위 조정\n        timeOn = Math.max(timeOn, 1);\n        timeOn = Math.min(timeOn, 60000);\n        timeOff = Math.max(timeOff, 1);\n        timeOff = Math.min(timeOff, 60000);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x11);\n        Entry.hw.setDigitalPortValue('vibrator_mode', mode);\n        Entry.hw.setDigitalPortValue('vibrator_on', timeOn);\n        Entry.hw.setDigitalPortValue('vibrator_off', timeOff);\n        Entry.hw.setDigitalPortValue('vibrator_total', timeRun);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['vibrator_mode'];\n        delete Entry.hw.sendQueue['vibrator_on'];\n        delete Entry.hw.sendQueue['vibrator_off'];\n        delete Entry.hw.sendQueue['vibrator_total'];\n    },\n\n    transferIrMessage: function(irmessage) {\n        // 범위 조정\n        irmessage = Math.max(irmessage, 0);\n        irmessage = Math.min(irmessage, 127);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x10);\n        Entry.hw.setDigitalPortValue('irmessage_data', irmessage);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['irmessage_data'];\n    },\n\n    transferMotorSingle: function(motorIndex, motorDirection, motorSpeed) {\n        // 범위 조정\n        motorSpeed = Math.max(motorSpeed, 0);\n        motorSpeed = Math.min(motorSpeed, 4096);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x10);\n        Entry.hw.setDigitalPortValue('motorsingle_target', motorIndex);\n        Entry.hw.setDigitalPortValue('motorsingle_direction', motorDirection);\n        Entry.hw.setDigitalPortValue('motorsingle_value', motorSpeed);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['motorsingle_target'];\n        delete Entry.hw.sendQueue['motorsingle_direction'];\n        delete Entry.hw.sendQueue['motorsingle_value'];\n    },\n\n    transferCommand: function(target, command, option) {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('command_command', command);\n        Entry.hw.setDigitalPortValue('command_option', option);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['command_command'];\n        delete Entry.hw.sendQueue['command_option'];\n    },\n\n    transferControlDouble: function(wheel, accel) {\n        // 범위 조정\n        wheel = Math.max(wheel, -100);\n        wheel = Math.min(wheel, 100);\n        accel = Math.max(accel, 0);\n        accel = Math.min(accel, 100);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x10);\n        Entry.hw.setDigitalPortValue('control_wheel', wheel);\n        Entry.hw.setDigitalPortValue('control_accel', accel);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['control_wheel'];\n        delete Entry.hw.sendQueue['control_accel'];\n    },\n\n    transferControlQuad: function(roll, pitch, yaw, throttle) {\n        // 범위 조정\n        roll = Math.max(roll, -100);\n        roll = Math.min(roll, 100);\n        pitch = Math.max(pitch, -100);\n        pitch = Math.min(pitch, 100);\n        yaw = Math.max(yaw, -100);\n        yaw = Math.min(yaw, 100);\n        throttle = Math.max(throttle, -100);\n        throttle = Math.min(throttle, 100);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x10);\n        Entry.hw.setDigitalPortValue('control_roll', roll);\n        Entry.hw.setDigitalPortValue('control_pitch', pitch);\n        Entry.hw.setDigitalPortValue('control_yaw', yaw);\n        Entry.hw.setDigitalPortValue('control_throttle', throttle);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['control_roll'];\n        delete Entry.hw.sendQueue['control_pitch'];\n        delete Entry.hw.sendQueue['control_yaw'];\n        delete Entry.hw.sendQueue['control_throttle'];\n    },\n\n    // functions for block\n\n    // 데이터 읽기\n    getData: function(script, device) {\n        return Entry.hw.portData[device];\n    },\n\n    // LED 수동 설정\n    setLightManual: function(script, target, flags, brightness) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferLightManual(target, flags, brightness);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 버저 설정(함수 호출 시 시간은 모두 ms 단위 사용)\n    /*\n        MuteInstantally     = 1,    // 묵음 즉시 적용\n        MuteContinually     = 2,    // 묵음 예약\n\n        ScaleInstantally    = 3,    // 음계 즉시 적용\n        ScaleContinually    = 4,    // 음계 예약\n\n        HzInstantally       = 5,    // 주파수 즉시 적용\n        HzContinually       = 6,    // 주파수 예약\n     */\n    // 정지\n    setBuzzerStop: function(script) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferBuzzer(0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 묵음\n    setBuzzerMute: function(script, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 2; // 묵음 연속\n                    if (flagInstantly) mode = 1; // 묵음 즉시\n\n                    this.transferBuzzer(mode, 0xee, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setBuzzerScale: function(script, octave, scale, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 4; // Scale 연속\n                    if (flagInstantly) mode = 3; // Scale 즉시\n\n                    var scalecalc = octave * 12 + scale;\n\n                    this.transferBuzzer(mode, scalecalc, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setBuzzerHz: function(script, hz, time, flagDelay, flagInstantly) {\n        time = Math.max(time, 0);\n        time = Math.min(time, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 6; // Hz 연속\n                    if (flagInstantly) mode = 5; // Hz 즉시\n\n                    // 범위 조정\n                    hz = Math.max(hz, 1);\n                    hz = Math.min(hz, 63999);\n\n                    this.transferBuzzer(mode, hz, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    // 진동 제어\n    /*\n        Stop            = 0,    // 정지\n        Instantally     = 1,    // 즉시 적용\n        Continually     = 2,    // 예약\n     */\n    setVibratorStop: function(script) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferVibrator(0, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setVibrator: function(script, timeOn, timeOff, timeRun, flagDelay, flagInstantly) {\n        timeRun = Math.max(timeRun, 0);\n        timeRun = Math.min(timeRun, 60000);\n\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = timeRun;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    var mode = 2; // 예약\n                    if (flagInstantly) mode = 1; // 즉시\n\n                    this.transferVibrator(mode, timeOn, timeOff, timeRun);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendIrMessage: function(script, irmessage) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferIrMessage(irmessage);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendStop: function(script) {\n        return this.sendCommand(script, 0x10, 0x24, 0);\n    },\n\n    sendCommand: function(script, target, command, option) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferCommand(target, command, option);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setMotorSingle: function(script, motorIndex, motorDirection, motorSpeed) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferMotorSingle(motorIndex, motorDirection, motorSpeed);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n    /*\n        None = 0,           ///< 없음\n\n        Flight = 0x10,      ///< 비행(가드 포함)\n        FlightNoGuard,      ///< 비행(가드 없음)\n        FlightFPV,          ///< 비행(FPV)\n\n        Drive = 0x20,       ///< 주행\n        DriveFPV,           ///< 주행(FPV)\n\n        Test = 0x30,        ///< 테스트\n     */\n    setModeVehicle: function(script, modeVehicle) {\n        switch (this.checkFinish(script, 40)) {\n            case 'Start':\n                {\n                    this.transferCommand(0x10, 0x10, modeVehicle);\n\n                    this.transferControlQuad(0, 0, 0, 0);\n                    this.transferControlDouble(0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    setEventFlight: function(script, eventFlight, time) {\n        switch (this.checkFinish(script, time)) {\n            case 'Start':\n                {\n                    this.transferCommand(0x10, 0x22, eventFlight); // 0x22 : CommandType::FlightEvent\n                    this.transferControlQuad(0, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendControlQuadSingle: function(script, controlTarget, value, time, flagDelay) {\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    // 범위 조정\n                    value = Math.max(value, -100);\n                    value = Math.min(value, 100);\n\n                    // 전송\n                    Entry.hw.setDigitalPortValue('target', 0x10);\n                    Entry.hw.setDigitalPortValue(controlTarget, value);\n\n                    Entry.hw.update();\n\n                    delete Entry.hw.sendQueue['target'];\n                    delete Entry.hw.sendQueue[controlTarget];\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                if (flagDelay) {\n                    // 전송\n                    Entry.hw.setDigitalPortValue('target', 0x10);\n                    Entry.hw.setDigitalPortValue(controlTarget, 0);\n\n                    Entry.hw.update();\n\n                    delete Entry.hw.sendQueue['target'];\n                    delete Entry.hw.sendQueue[controlTarget];\n                }\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n    sendControlQuad: function(script, roll, pitch, yaw, throttle, time, flagDelay) {\n        var timeDelay = 40;\n        if (flagDelay) timeDelay = time;\n\n        switch (this.checkFinish(script, timeDelay)) {\n            case 'Start':\n                {\n                    this.transferControlQuad(roll, pitch, yaw, throttle);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                if (flagDelay) {\n                    this.transferControlQuad(0, 0, 0, 0);\n                }\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\n// \nEntry.byrobot_dronefighter_flight.setLanguage = function ()\n{\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_dronefighter_drone_state_mode_system\": \"시스템 모드\",\n                \"byrobot_dronefighter_drone_state_mode_vehicle\": \"드론파이터 모드\",\n                \"byrobot_dronefighter_drone_state_mode_flight\": \"비행 모드\",\n                \"byrobot_dronefighter_drone_state_mode_drive\": \"자동차 모드\",\n                \"byrobot_dronefighter_drone_state_mode_coordinate\": \"기본 좌표계\",\n                \"byrobot_dronefighter_drone_state_battery\": \"배터리\",\n                \"byrobot_dronefighter_drone_attitude_roll\": \"자세 Roll\",\n                \"byrobot_dronefighter_drone_attitude_pitch\": \"자세 Pitch\",\n                \"byrobot_dronefighter_drone_attitude_yaw\": \"자세 Yaw\",\n                \"byrobot_dronefighter_drone_irmessage\": \"적외선 수신 값\",\n                \"byrobot_dronefighter_controller_joystick_left_x\": \"왼쪽 조이스틱 가로축\",\n                \"byrobot_dronefighter_controller_joystick_left_y\": \"왼쪽 조이스틱 세로축\",\n                \"byrobot_dronefighter_controller_joystick_left_direction\": \"왼쪽 조이스틱 방향\",\n                \"byrobot_dronefighter_controller_joystick_left_event\": \"왼쪽 조이스틱 이벤트\",\n                \"byrobot_dronefighter_controller_joystick_left_command\": \"왼쪽 조이스틱 명령\",\n                \"byrobot_dronefighter_controller_joystick_right_x\": \"오른쪽 조이스틱 가로축\",\n                \"byrobot_dronefighter_controller_joystick_right_y\": \"오른쪽 조이스틱 세로축\",\n                \"byrobot_dronefighter_controller_joystick_right_direction\": \"오른쪽 조이스틱 방향\",\n                \"byrobot_dronefighter_controller_joystick_right_event\": \"오른쪽 조이스틱 이벤트\",\n                \"byrobot_dronefighter_controller_joystick_right_command\": \"오른쪽 조이스틱 명령\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_up\": \"왼쪽 위\",\n                \"byrobot_dronefighter_controller_joystick_direction_up\": \"위\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_up\": \"오른쪽 위\",\n                \"byrobot_dronefighter_controller_joystick_direction_left\": \"왼쪽\",\n                \"byrobot_dronefighter_controller_joystick_direction_center\": \"중앙\",\n                \"byrobot_dronefighter_controller_joystick_direction_right\": \"오른쪽\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_down\": \"왼쪽 아래\",\n                \"byrobot_dronefighter_controller_joystick_direction_down\": \"아래\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_down\": \"오른쪽 아래\",\n                \"byrobot_dronefighter_controller_button_button\": \"버튼\",\n                \"byrobot_dronefighter_controller_button_event\": \"버튼 이벤트\",\n                \"byrobot_dronefighter_controller_button_front_left\": \"왼쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_front_right\": \"오른쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_front_left_right\": \"양쪽 빨간 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up_left\": \"트림 좌회전 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up_right\": \"트림 우회전 버튼\",\n                \"byrobot_dronefighter_controller_button_center_up\": \"트림 앞 버튼\",\n                \"byrobot_dronefighter_controller_button_center_left\": \"트림 왼쪽 버튼\",\n                \"byrobot_dronefighter_controller_button_center_right\": \"트림 오른쪽 버튼\",\n                \"byrobot_dronefighter_controller_button_center_down\": \"트림 뒤 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_left\": \"왼쪽 둥근 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_right\": \"오른쪽 둥근 버튼\",\n                \"byrobot_dronefighter_controller_button_bottom_left_right\": \"양쪽 둥근 버튼\",\n                \"byrobot_dronefighter_entryhw_count_transfer_reserved\": \"전송 예약된 데이터 수\",\n                \"byrobot_dronefighter_common_roll\": \"Roll\",\n                \"byrobot_dronefighter_common_pitch\": \"Pitch\",\n                \"byrobot_dronefighter_common_yaw\": \"Yaw\",\n                \"byrobot_dronefighter_common_throttle\": \"Throttle\",\n                \"byrobot_dronefighter_common_left\": \"왼쪽\",\n                \"byrobot_dronefighter_common_right\": \"오른쪽\",\n                \"byrobot_dronefighter_common_light_manual_on\": \"켜기\",\n                \"byrobot_dronefighter_common_light_manual_off\": \"끄기\",\n                \"byrobot_dronefighter_common_light_manual_b25\": \"밝기 25%\",\n                \"byrobot_dronefighter_common_light_manual_b50\": \"밝기 50%\",\n                \"byrobot_dronefighter_common_light_manual_b75\": \"밝기 75%\",\n                \"byrobot_dronefighter_common_light_manual_b100\": \"밝기 100%\",\n                \"byrobot_dronefighter_common_light_manual_all\": \"전체\",\n                \"byrobot_dronefighter_common_light_manual_red\": \"빨강\",\n                \"byrobot_dronefighter_common_light_manual_blue\": \"파랑\",\n                \"byrobot_dronefighter_common_light_manual_1\": \"1\",\n                \"byrobot_dronefighter_common_light_manual_2\": \"2\",\n                \"byrobot_dronefighter_common_light_manual_3\": \"3\",\n                \"byrobot_dronefighter_common_light_manual_4\": \"4\",\n                \"byrobot_dronefighter_common_light_manual_5\": \"5\",\n                \"byrobot_dronefighter_common_light_manual_6\": \"6\",\n                \"byrobot_dronefighter_controller_buzzer\": \"버저\",\n                \"byrobot_dronefighter_controller_buzzer_mute\": \"쉼\",\n                \"byrobot_dronefighter_controller_buzzer_c\": \"도\",\n                \"byrobot_dronefighter_controller_buzzer_cs\": \"도#\",\n                \"byrobot_dronefighter_controller_buzzer_d\": \"레\",\n                \"byrobot_dronefighter_controller_buzzer_ds\": \"레#\",\n                \"byrobot_dronefighter_controller_buzzer_e\": \"미\",\n                \"byrobot_dronefighter_controller_buzzer_f\": \"파\",\n                \"byrobot_dronefighter_controller_buzzer_fs\": \"파#\",\n                \"byrobot_dronefighter_controller_buzzer_g\": \"솔\",\n                \"byrobot_dronefighter_controller_buzzer_gs\": \"솔#\",\n                \"byrobot_dronefighter_controller_buzzer_a\": \"라\",\n                \"byrobot_dronefighter_controller_buzzer_as\": \"라#\",\n                \"byrobot_dronefighter_controller_buzzer_b\": \"시\",\n                \"byrobot_dronefighter_controller_userinterface_preset_clear\": \"모두 지우기\",\n                \"byrobot_dronefighter_controller_userinterface_preset_dronefighter2017\": \"기본\",\n                \"byrobot_dronefighter_controller_userinterface_preset_education\": \"교육용\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontleft_down\": \"왼쪽 빨간 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontright_down\": \"오른쪽 빨간 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnleft_down\": \"트림 좌회전 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnright_down\": \"트림 우회전 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midup_down\": \"트림 앞 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midleft_down\": \"트림 왼쪽 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midright_down\": \"트림 오른쪽 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_middown_down\": \"트림 뒤 버튼을 눌렀을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_up_in\": \"왼쪽 조이스틱을 위로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_left_in\": \"왼쪽 조이스틱을 왼쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_right_in\": \"왼쪽 조이스틱을 오른쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_down_in\": \"왼쪽 조이스틱을 아래로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_up_in\": \"오른쪽 조이스틱을 위로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_left_in\": \"오른쪽 조이스틱을 왼쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_right_in\": \"오른쪽 조이스틱을 오른쪽으로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_down_in\": \"오른쪽 조이스틱을 아래로 움직였을 때\",\n                \"byrobot_dronefighter_controller_userinterface_function_joystickcalibration_reset\": \"조이스틱 보정 초기화\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_red\": \"팀 - 레드\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_blue\": \"팀 - 블루\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flight\": \"드론\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flightnoguard\": \"드론 - 가드 없음\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_drive\": \"자동차\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_local\": \"방위 - 일반\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_world\": \"방위 - 앱솔루트\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode1\": \"조종 - MODE 1\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode2\": \"조종 - MODE 2\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode3\": \"조종 - MODE 3\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode4\": \"조종 - MODE 4\",\n                \"byrobot_dronefighter_controller_userinterface_function_gyrobias_reset\": \"자이로 바이어스 리셋\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_cdc\": \"USB 시리얼 통신 장치\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_hid\": \"USB 게임 컨트롤러\",\n                \"byrobot_dronefighter_drone_team\": \"팀 \",\n                \"byrobot_dronefighter_drone_team_red\": \"레드\",\n                \"byrobot_dronefighter_drone_team_blue\": \"블루\",\n                \"byrobot_dronefighter_drone_coordinate_world\": \"앱솔루트\",\n                \"byrobot_dronefighter_drone_coordinate_local\": \"일반\",\n                \"byrobot_dronefighter_drone_mode_vehicle_flight\": \"드론\",\n                \"byrobot_dronefighter_drone_mode_vehicle_drive\": \"자동차\",\n                \"byrobot_dronefighter_drone_control_double_wheel\": \"방향\",\n                \"byrobot_dronefighter_drone_control_double_wheel_left\": \"왼쪽 회전\",\n                \"byrobot_dronefighter_drone_control_double_wheel_right\": \"오른쪽 회전\",\n                \"byrobot_dronefighter_drone_control_double_accel_forward\": \"전진\",\n                \"byrobot_dronefighter_drone_control_double_accel_backward\": \"후진\",\n                \"byrobot_dronefighter_drone_control_quad_roll\": \"Roll\",\n                \"byrobot_dronefighter_drone_control_quad_pitch\": \"Pitch\",\n                \"byrobot_dronefighter_drone_control_quad_yaw\": \"Yaw\",\n                \"byrobot_dronefighter_drone_control_quad_throttle\": \"Throttle\",\n                \"byrobot_dronefighter_drone_control_quad_roll_left\": \"왼쪽\",\n                \"byrobot_dronefighter_drone_control_quad_roll_right\": \"오른쪽\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_forward\": \"앞으로\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_backward\": \"뒤로\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_left\": \"왼쪽 회전\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_right\": \"오른쪽 회전\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_up\": \"위\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_down\": \"아래\",\n            },\n\n            // ko.js에 작성하던 내용\n            template: {\n                \"byrobot_dronefighter_flight_drone_value_attitude\": \"%1\",\n                \"byrobot_dronefighter_flight_drone_value_etc\": \"%1\",\n                \"byrobot_dronefighter_flight_controller_value_button\": \"%1\",\n                \"byrobot_dronefighter_flight_controller_value_joystick\": \"%1\",\n                \"byrobot_dronefighter_flight_controller_if_button_press\": \"조종기 %1 눌렀을 때\",\n                \"byrobot_dronefighter_flight_controller_if_joystick_direction\": \"조종기 %1 조이스틱 %2 움직였을 때\",\n                \"byrobot_dronefighter_flight_drone_control_drone_stop\": \"드론 정지 %1\",\n                \"byrobot_dronefighter_flight_drone_control_coordinate\": \"드론 좌표 기준을 %1로 정하기 %2\",\n                \"byrobot_dronefighter_flight_drone_control_drone_reset_heading\": \"드론 방향 초기화 %1\",\n                \"byrobot_dronefighter_flight_drone_control_quad_one\": \"드론 %1 %2% 정하기 %3\",\n                \"byrobot_dronefighter_flight_drone_control_quad_one_delay\": \"드론 %1 %2% %3 초 실행 %4\",\n                \"byrobot_dronefighter_flight_drone_control_quad\": \"드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% 정하기 %5\",\n                \"byrobot_dronefighter_flight_drone_motor_stop\": \"모터 정지 %1\",\n                \"byrobot_dronefighter_flight_drone_motorsingle\": \"%1 번 모터를 %2 (으)로 회전 %3\",\n                \"byrobot_dronefighter_flight_drone_motorsingle_input\": \"%1 번 모터를 %2 (으)로 회전 %3\",\n                \"byrobot_dronefighter_flight_drone_irmessage\": \"적외선으로 %1 값 보내기 %2\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single_off\": \"조종기 LED 끄기 %1\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single\": \"조종기 LED %1 %2 %3\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single_input\": \"조종기 LED %1 밝기 %2 %3\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single_off\": \"드론 LED 끄기 %1\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single\": \"드론 LED %1 %2 %3\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single_input\": \"드론 LED %1 밝기 %2 %3\",\n                \"byrobot_dronefighter_flight_controller_buzzer_off\": \"버저 끄기 %1\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale\": \"%1 옥타브 %2 을(를) 연주 %3\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale_delay\": \"%1 옥타브 %2 을(를) %3 초 연주 %4\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale_reserve\": \"%1 옥타브 %2 을(를) %3 초 예약 %4\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz\": \"%1 Hz 소리를 연주 %2\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz_delay\": \"%1 Hz 소리를 %2 초 연주 %3\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz_reserve\": \"%1 Hz 소리를 %2 초 예약 %3\",\n                \"byrobot_dronefighter_flight_controller_vibrator_off\": \"진동 끄기 %1\",\n                \"byrobot_dronefighter_flight_controller_vibrator_on_delay\": \"진동 %1 초 켜기 %2\",\n                \"byrobot_dronefighter_flight_controller_vibrator_on_reserve\": \"진동 %1 초 예약 %2\",\n                \"byrobot_dronefighter_flight_controller_vibrator_delay\": \"진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4\",\n                \"byrobot_dronefighter_flight_controller_vibrator_reserve\": \"진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4\",\n            },\n\n            Helper: {\n                \"byrobot_dronefighter_flight_drone_value_attitude\": \"<br>드론의 현재 자세를 각도로 반환합니다. Roll은 좌우 기울기(-90 ~ 90), Pitch는 앞뒤 기울기(-90 ~ 90), Yaw는 회전 각도(-180 ~ 180) 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#자세</font>\",\n                \"byrobot_dronefighter_flight_drone_value_etc\": \"<br>드론파이터 설정과 관련된 값들과 적외선 통신으로 받은 값을 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#기타</font>\",\n                \"byrobot_dronefighter_flight_controller_value_button\": \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_dronefighter_flight_controller_value_joystick\": \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_dronefighter_flight_controller_if_button_press\": \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_dronefighter_flight_controller_if_joystick_direction\": \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_dronefighter_flight_drone_control_drone_stop\": \"<br>드론 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#정지</font>\",\n                \"byrobot_dronefighter_flight_drone_control_coordinate\": \"<br>드론 좌표 기준을 변경합니다. 앱솔루트 모드는 이륙 시와 '방향초기화'를 했을 때 드론이 바라보는 방향을 기준으로 앞뒤좌우가 고정됩니다. 이 때에는 Yaw를 조작하여 드론이 다른 방향을 보게 하여도 처음 지정한 방향을 기준으로 앞뒤좌우로 움직입니다. 사용자가 바라보는 방향과 드론의 기준 방향이 같을 때 조작하기 편리한 장점이 있습니다. 일반 모드는 현재 드론이 바라보는 방향을 기준으로 앞뒤좌우가 결정됩니다. 드론의 움직임에 따라 앞뒤좌우가 계속 바뀌기 때문에 익숙해지기 전까지는 사용하기 어려울 수 있습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#좌표기준</font>\",\n                \"byrobot_dronefighter_flight_drone_control_drone_reset_heading\": \"<br>드론의 방향을 초기화합니다. 앱솔루트 모드인 경우 현재 드론이 바라보는 방향을 0도로 변경합니다. 일반 모드에서는 아무런 영향이 없습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#방향초기화</font>\",\n                \"byrobot_dronefighter_flight_drone_control_quad_one\": \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                \"byrobot_dronefighter_flight_drone_control_quad_one_delay\": \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                \"byrobot_dronefighter_flight_drone_control_quad\": \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                \"byrobot_dronefighter_flight_drone_motor_stop\": \"<br>모든 모터의 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터정지</font>\",\n                \"byrobot_dronefighter_flight_drone_motorsingle\": \"<br>지정한 모터를 원하는 빠르기로 회전할 때 사용합니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_dronefighter_flight_drone_motorsingle_input\": \"<br>지정한 모터(1, 2, 3, 4)를 원하는 빠르기로 회전할 때 사용합니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_dronefighter_flight_drone_irmessage\": \"<br>적외선으로 지정한 값을 보냅니다. 사용 가능한 값의 범위는 0 ~ 127입니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#적외선통신</font>\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single_off\": \"<br>드론의 모든 LED를 끕니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single\": \"<br>드론의 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single_input\": \"<br>드론 LED 여러 개의 밝기를 동시에 변경할 때 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 개별 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single_off\": \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single\": \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single_input\": \"<br>조종기 LED 여러 개의 밝기를 동시에 변경할 때 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 개별 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_dronefighter_flight_controller_buzzer_off\": \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale\": \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale_delay\": \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale_reserve\": \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz\": \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz_delay\": \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz_reserve\": \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                \"byrobot_dronefighter_flight_controller_vibrator_off\": \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                \"byrobot_dronefighter_flight_controller_vibrator_on_delay\": \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_dronefighter_flight_controller_vibrator_on_reserve\": \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_dronefighter_flight_controller_vibrator_delay\": \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_dronefighter_flight_controller_vibrator_reserve\": \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n            }\n        },\n\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_dronefighter_drone_state_mode_system\": \"system Mode\",\n                \"byrobot_dronefighter_drone_state_mode_vehicle\": \"vehicle Mode\",\n                \"byrobot_dronefighter_drone_state_mode_flight\": \"flight Mode\",\n                \"byrobot_dronefighter_drone_state_mode_drive\": \"drive Mode\",\n                \"byrobot_dronefighter_drone_state_mode_coordinate\": \"coordinate\",\n                \"byrobot_dronefighter_drone_state_battery\": \"battery\",\n                \"byrobot_dronefighter_drone_attitude_roll\": \"attitude - roll\",\n                \"byrobot_dronefighter_drone_attitude_pitch\": \"attitude - pitch\",\n                \"byrobot_dronefighter_drone_attitude_yaw\": \"attitude - yaw\",\n                \"byrobot_dronefighter_drone_irmessage\": \"IR data Received\",\n                \"byrobot_dronefighter_controller_joystick_left_x\": \"left joystick horizontal\",\n                \"byrobot_dronefighter_controller_joystick_left_y\": \"left joystick vertical\",\n                \"byrobot_dronefighter_controller_joystick_left_direction\": \"left joystick direction\",\n                \"byrobot_dronefighter_controller_joystick_left_event\": \"left joystick event\",\n                \"byrobot_dronefighter_controller_joystick_left_command\": \"left joystick command\",\n                \"byrobot_dronefighter_controller_joystick_right_x\": \"right joystick horizontal\",\n                \"byrobot_dronefighter_controller_joystick_right_y\": \"right joystick vertical\",\n                \"byrobot_dronefighter_controller_joystick_right_direction\": \"right joystick direction\",\n                \"byrobot_dronefighter_controller_joystick_right_event\": \"right joystick event\",\n                \"byrobot_dronefighter_controller_joystick_right_command\": \"right joystick command\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_up\": \"left up\",\n                \"byrobot_dronefighter_controller_joystick_direction_up\": \"up\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_up\": \"right up\",\n                \"byrobot_dronefighter_controller_joystick_direction_left\": \"left\",\n                \"byrobot_dronefighter_controller_joystick_direction_center\": \"center\",\n                \"byrobot_dronefighter_controller_joystick_direction_right\": \"right\",\n                \"byrobot_dronefighter_controller_joystick_direction_left_down\": \"left down\",\n                \"byrobot_dronefighter_controller_joystick_direction_down\": \"down\",\n                \"byrobot_dronefighter_controller_joystick_direction_right_down\": \"right down\",\n                \"byrobot_dronefighter_controller_button_button\": \"button\",\n                \"byrobot_dronefighter_controller_button_event\": \"button event\",\n                \"byrobot_dronefighter_controller_button_front_left\": \"left red button\",\n                \"byrobot_dronefighter_controller_button_front_right\": \"right red button\",\n                \"byrobot_dronefighter_controller_button_front_left_right\": \"both red button\",\n                \"byrobot_dronefighter_controller_button_center_up_left\": \"trim-turn-left button\",\n                \"byrobot_dronefighter_controller_button_center_up_right\": \"trim-turn-right button\",\n                \"byrobot_dronefighter_controller_button_center_up\": \"trim-forward button\",\n                \"byrobot_dronefighter_controller_button_center_left\": \"trim-left button\",\n                \"byrobot_dronefighter_controller_button_center_right\": \"trim-right button\",\n                \"byrobot_dronefighter_controller_button_center_down\": \"trim-backward button\",\n                \"byrobot_dronefighter_controller_button_bottom_left\": \"left round button\",\n                \"byrobot_dronefighter_controller_button_bottom_right\": \"right round button\",\n                \"byrobot_dronefighter_controller_button_bottom_left_right\": \"both round button\",\n                \"byrobot_dronefighter_entryhw_count_transfer_reserved\": \"reserved data blocks\",\n                \"byrobot_dronefighter_common_roll\": \"roll\",\n                \"byrobot_dronefighter_common_pitch\": \"pitch\",\n                \"byrobot_dronefighter_common_yaw\": \"yaw\",\n                \"byrobot_dronefighter_common_throttle\": \"throttle\",\n                \"byrobot_dronefighter_common_left\": \"left\",\n                \"byrobot_dronefighter_common_right\": \"right\",\n                \"byrobot_dronefighter_common_light_manual_on\": \"on\",\n                \"byrobot_dronefighter_common_light_manual_off\": \"off\",\n                \"byrobot_dronefighter_common_light_manual_b25\": \"brightness 25%\",\n                \"byrobot_dronefighter_common_light_manual_b50\": \"brightness 50%\",\n                \"byrobot_dronefighter_common_light_manual_b75\": \"brightness 75%\",\n                \"byrobot_dronefighter_common_light_manual_b100\": \"brightness 100%\",\n                \"byrobot_dronefighter_common_light_manual_all\": \"all\",\n                \"byrobot_dronefighter_common_light_manual_red\": \"red\",\n                \"byrobot_dronefighter_common_light_manual_blue\": \"blue\",\n                \"byrobot_dronefighter_common_light_manual_1\": \"1\",\n                \"byrobot_dronefighter_common_light_manual_2\": \"2\",\n                \"byrobot_dronefighter_common_light_manual_3\": \"3\",\n                \"byrobot_dronefighter_common_light_manual_4\": \"4\",\n                \"byrobot_dronefighter_common_light_manual_5\": \"5\",\n                \"byrobot_dronefighter_common_light_manual_6\": \"6\",\n                \"byrobot_dronefighter_controller_buzzer\": \"buzzer\",\n                \"byrobot_dronefighter_controller_buzzer_mute\": \"mute\",\n                \"byrobot_dronefighter_controller_buzzer_c\": \"C\",\n                \"byrobot_dronefighter_controller_buzzer_cs\": \"C#\",\n                \"byrobot_dronefighter_controller_buzzer_d\": \"D\",\n                \"byrobot_dronefighter_controller_buzzer_ds\": \"D#\",\n                \"byrobot_dronefighter_controller_buzzer_e\": \"E\",\n                \"byrobot_dronefighter_controller_buzzer_f\": \"F\",\n                \"byrobot_dronefighter_controller_buzzer_fs\": \"F#\",\n                \"byrobot_dronefighter_controller_buzzer_g\": \"G\",\n                \"byrobot_dronefighter_controller_buzzer_gs\": \"G#\",\n                \"byrobot_dronefighter_controller_buzzer_a\": \"A\",\n                \"byrobot_dronefighter_controller_buzzer_as\": \"A#\",\n                \"byrobot_dronefighter_controller_buzzer_b\": \"B\",\n                \"byrobot_dronefighter_controller_userinterface_preset_clear\": \"clear\",\n                \"byrobot_dronefighter_controller_userinterface_preset_dronefighter2017\": \"default\",\n                \"byrobot_dronefighter_controller_userinterface_preset_education\": \"education\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontleft_down\": \"press left red button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_frontright_down\": \"press right red button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnleft_down\": \"press trim-left-turn button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midturnright_down\": \"press trim-right-turn button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midup_down\": \"press trim-forward button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midleft_down\": \"press trim-left button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_midright_down\": \"press trim-right button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_button_middown_down\": \"press trim-backward button\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_up_in\": \"left joystick move up\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_left_in\": \"left joystick move left\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_right_in\": \"left joystick move right\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_left_down_in\": \"left joystick move down\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_up_in\": \"right joystick move up\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_left_in\": \"right joystick move left\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_right_in\": \"right joystick move right\",\n                \"byrobot_dronefighter_controller_userinterface_command_setup_joystick_right_down_in\": \"right joystick move down\",\n                \"byrobot_dronefighter_controller_userinterface_function_joystickcalibration_reset\": \"reset joystick calibration\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_red\": \"team - red\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_team_blue\": \"team - blue\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flight\": \"flight\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_flightnoguard\": \"flight - no guard\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_vehicle_drive\": \"drive\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_local\": \"coordinate - normal\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_coordinate_world\": \"coordinate - absolute\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode1\": \"control - MODE 1\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode2\": \"control - MODE 2\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode3\": \"control - MODE 3\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_control_mode4\": \"control - MODE 4\",\n                \"byrobot_dronefighter_controller_userinterface_function_gyrobias_reset\": \"reset gyro bias\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_cdc\": \"USB serial device\",\n                \"byrobot_dronefighter_controller_userinterface_function_change_mode_usb_hid\": \"USB game controller\",\n                \"byrobot_dronefighter_drone_team\": \"team\",\n                \"byrobot_dronefighter_drone_team_red\": \"red\",\n                \"byrobot_dronefighter_drone_team_blue\": \"blue\",\n                \"byrobot_dronefighter_drone_coordinate_world\": \"absolute\",\n                \"byrobot_dronefighter_drone_coordinate_local\": \"normal\",\n                \"byrobot_dronefighter_drone_mode_vehicle_flight\": \"flight\",\n                \"byrobot_dronefighter_drone_mode_vehicle_drive\": \"drive\",\n                \"byrobot_dronefighter_drone_control_double_wheel\": \"direction\",\n                \"byrobot_dronefighter_drone_control_double_wheel_left\": \"turn left\",\n                \"byrobot_dronefighter_drone_control_double_wheel_right\": \"turn right\",\n                \"byrobot_dronefighter_drone_control_double_accel_forward\": \"forward\",\n                \"byrobot_dronefighter_drone_control_double_accel_backward\": \"backward\",\n                \"byrobot_dronefighter_drone_control_quad_roll\": \"roll\",\n                \"byrobot_dronefighter_drone_control_quad_pitch\": \"pitch\",\n                \"byrobot_dronefighter_drone_control_quad_yaw\": \"yaw\",\n                \"byrobot_dronefighter_drone_control_quad_throttle\": \"throttle\",\n                \"byrobot_dronefighter_drone_control_quad_roll_left\": \"left\",\n                \"byrobot_dronefighter_drone_control_quad_roll_right\": \"right\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_forward\": \"foward\",\n                \"byrobot_dronefighter_drone_control_quad_pitch_backward\": \"backward\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_left\": \"turn Left\",\n                \"byrobot_dronefighter_drone_control_quad_yaw_right\": \"turn Right\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_up\": \"up\",\n                \"byrobot_dronefighter_drone_control_quad_throttle_down\": \"down\",\n            },\n\n            // en.js에 작성하던 내용\n            template: {\n                \"byrobot_dronefighter_flight_drone_value_attitude\": \"%1\",\n                \"byrobot_dronefighter_flight_drone_value_etc\": \"%1\",\n                \"byrobot_dronefighter_flight_controller_value_button\": \"%1\",\n                \"byrobot_dronefighter_flight_controller_value_joystick\": \"%1\",\n                \"byrobot_dronefighter_flight_controller_if_button_press\": \"when press %1\",\n                \"byrobot_dronefighter_flight_controller_if_joystick_direction\": \"when %1 stick move to %2\",\n                \"byrobot_dronefighter_flight_drone_control_drone_stop\": \"stop %1\",\n                \"byrobot_dronefighter_flight_drone_control_coordinate\": \"set coordinate reference to %1 %2\",\n                \"byrobot_dronefighter_flight_drone_control_drone_reset_heading\": \"reset heading reference %1\",\n                \"byrobot_dronefighter_flight_drone_control_quad_one\": \"set %1 to %2 %3\",\n                \"byrobot_dronefighter_flight_drone_control_quad_one_delay\": \"set %1 to %2 and run for %3 second %4\",\n                \"byrobot_dronefighter_flight_drone_control_quad\": \"set roll to %1, pitch to %2, yaw to %3, throttle to %4 %5\",\n                \"byrobot_dronefighter_flight_drone_motor_stop\": \"turn off all motors %1\",\n                \"byrobot_dronefighter_flight_drone_motorsingle\": \"set rotate for number %1 motor to %2 %3\",\n                \"byrobot_dronefighter_flight_drone_motorsingle_input\": \"set rotate for number %1 motor to %2 %3\",\n                \"byrobot_dronefighter_flight_drone_irmessage\": \"send %1 to the IR transmitter %2\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single_off\": \"turn off all controller LEDs %1\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single\": \"change the state of %1 controller LED to %2 %3\",\n                \"byrobot_dronefighter_flight_controller_light_manual_single_input\": \"change the brightness of %1 controller LED to %2 %3\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single_off\": \"turn off all drone LEDs %1\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single\": \"change the state of %1 drone LED to %2 %3\",\n                \"byrobot_dronefighter_flight_drone_light_manual_single_input\": \"change the brightness of %1 drone LED to %2 %3\",\n                \"byrobot_dronefighter_flight_controller_buzzer_off\": \"turn off the buzzer %1\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale\": \"play %1 octave %2 %3\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale_delay\": \"play %1 octave %2 for %3 second %4\",\n                \"byrobot_dronefighter_flight_controller_buzzer_scale_reserve\": \"reserve to play %1 octave %2 for %3 second %4\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz\": \"play %1 Hz sound %2\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz_delay\": \"play %1 Hz sound for %2 second %3\",\n                \"byrobot_dronefighter_flight_controller_buzzer_hz_reserve\": \"reserve to play %1 Hz sound for %2 second %3\",\n                \"byrobot_dronefighter_flight_controller_vibrator_off\": \"turn off the vibrator %1\",\n                \"byrobot_dronefighter_flight_controller_vibrator_on_delay\": \"turn on the vibrator for %1 second %2\",\n                \"byrobot_dronefighter_flight_controller_vibrator_on_reserve\": \"reserve turn on the vibrator for %1 second %2\",\n                \"byrobot_dronefighter_flight_controller_vibrator_delay\": \"vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_dronefighter_flight_controller_vibrator_reserve\": \"reserve vibration %1 second on, %2 second off for %3 seconds %4\",\n            },\n            \n            Helper: {\n\n            }\n        }\n    }\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 이름\n ***************************************************************************************/\nEntry.byrobot_dronefighter_flight.blockMenuBlocks = [\n    'byrobot_dronefighter_flight_drone_value_attitude',\n    'byrobot_dronefighter_flight_drone_value_etc',\n    'byrobot_dronefighter_flight_controller_value_button',\n    'byrobot_dronefighter_flight_controller_value_joystick',\n    'byrobot_dronefighter_flight_controller_if_button_press',\n    'byrobot_dronefighter_flight_controller_if_joystick_direction',\n    'byrobot_dronefighter_flight_drone_control_drone_stop',\n    'byrobot_dronefighter_flight_drone_control_coordinate',\n    'byrobot_dronefighter_flight_drone_control_drone_reset_heading',\n    'byrobot_dronefighter_flight_drone_control_quad_one',\n    'byrobot_dronefighter_flight_drone_control_quad_one_delay',\n    'byrobot_dronefighter_flight_drone_control_quad',\n    'byrobot_dronefighter_flight_drone_motor_stop',\n    'byrobot_dronefighter_flight_drone_motorsingle',\n    'byrobot_dronefighter_flight_drone_motorsingle_input',\n    'byrobot_dronefighter_flight_drone_irmessage',\n    'byrobot_dronefighter_flight_drone_light_manual_single_off',\n    'byrobot_dronefighter_flight_drone_light_manual_single',\n    'byrobot_dronefighter_flight_drone_light_manual_single_input',\n    'byrobot_dronefighter_flight_controller_light_manual_single_off',\n    'byrobot_dronefighter_flight_controller_light_manual_single',\n    'byrobot_dronefighter_flight_controller_light_manual_single_input',\n    'byrobot_dronefighter_flight_controller_buzzer_off',\n    'byrobot_dronefighter_flight_controller_buzzer_scale',\n    'byrobot_dronefighter_flight_controller_buzzer_scale_delay',\n    'byrobot_dronefighter_flight_controller_buzzer_scale_reserve',\n    'byrobot_dronefighter_flight_controller_buzzer_hz',\n    'byrobot_dronefighter_flight_controller_buzzer_hz_delay',\n    'byrobot_dronefighter_flight_controller_buzzer_hz_reserve',\n    'byrobot_dronefighter_flight_controller_vibrator_off',\n    'byrobot_dronefighter_flight_controller_vibrator_on_delay',\n    'byrobot_dronefighter_flight_controller_vibrator_on_reserve',\n    'byrobot_dronefighter_flight_controller_vibrator_delay',\n    'byrobot_dronefighter_flight_controller_vibrator_reserve',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 상세\n ***************************************************************************************/\nEntry.byrobot_dronefighter_flight.getBlocks = function() {\n    return {\n        //region byrobot 바이로봇\n        /* BYROBOT DroneFighter Flight Start */\n        byrobot_dronefighter_flight_drone_value_attitude: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_drone_attitude_roll, 'attitude_roll'],\n                        [Lang.Blocks.byrobot_dronefighter_drone_attitude_pitch, 'attitude_pitch'],\n                        [Lang.Blocks.byrobot_dronefighter_drone_attitude_yaw, 'attitude_yaw'],\n                    ],\n                    value: 'attitude_roll', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_value_attitude', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n        byrobot_dronefighter_flight_drone_value_etc: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_state_mode_vehicle,\n                            'state_modeVehicle',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_state_mode_flight,\n                            'state_modeFlight',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_state_mode_coordinate,\n                            'state_coordinate',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_drone_state_battery, 'state_battery'],\n                        [Lang.Blocks.byrobot_dronefighter_drone_irmessage, 'irmessage_irdata'],\n                    ],\n                    value: 'irmessage_irdata', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_value_etc', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n        byrobot_dronefighter_flight_controller_value_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_button_button,\n                            'button_button',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_event, 'button_event'],\n                    ],\n                    value: 'button_button', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_controller_value_button', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n        byrobot_dronefighter_flight_controller_value_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_x,\n                            'joystick_left_x',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_y,\n                            'joystick_left_y',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_direction,\n                            'joystick_left_direction',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_event,\n                            'joystick_left_event',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_left_command,\n                            'joystick_left_command',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_x,\n                            'joystick_right_x',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_y,\n                            'joystick_right_y',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_direction,\n                            'joystick_right_direction',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_event,\n                            'joystick_right_event',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_right_command,\n                            'joystick_right_command',\n                        ],\n                    ],\n                    value: 'joystick_left_x', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_controller_value_joystick', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_dronefighter_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n        byrobot_dronefighter_flight_controller_if_button_press: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_left, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_right, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_front_left_right, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up_left, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up_right, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_up, '16'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_left, '32'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_right, '64'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_center_down, '128'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_bottom_left, '256'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_button_bottom_right, '512'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_button_bottom_left_right,\n                            '768',\n                        ],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'byrobot_dronefighter_flight_boolean_input',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var button = 'button_button'; // paramsKeyMap에 정의된 이름 사용\n                var buttonevent = 'button_event'; // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2)\n                    return true;\n                else return false;\n            },\n            syntax: { js: [], py: [] },\n        },\n        byrobot_dronefighter_flight_controller_if_joystick_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_dronefighter_common_right, 'joystick_right_direction'],\n                    ],\n                    value: 'joystick_left_direction',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_left_up,\n                            '17',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_up, '18'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_right_up,\n                            '20',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_left, '33'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_center,\n                            '34',\n                        ],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_right,\n                            '36',\n                        ],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_joystick_direction_left_down,\n                            '65',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_controller_joystick_direction_down, '66'],\n                        [\n                            Lang.Blocks\n                                .byrobot_dronefighter_controller_joystick_direction_right_down,\n                            '68',\n                        ],\n                    ],\n                    value: '34',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_dronefighter_flight_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                DIRECTION: 1,\n            },\n            class: 'byrobot_dronefighter_flight_boolean_input',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION')) return true;\n                else return false;\n            },\n        },\n        byrobot_dronefighter_flight_controller_light_manual_single_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_controller_light',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.setLightManual(script, 0x11, 0xff, 0);\n            },\n        },\n        byrobot_dronefighter_flight_controller_light_manual_single: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_all, '255'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_1, '128'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_2, '64'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_3, '32'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_4, '16'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_5, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_6, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_blue, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_red, '1'],\n                    ],\n                    value: '128',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_on, '220'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_off, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b25, '75'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b50, '125'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b75, '200'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b100, '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_flight_controller_light_manual_single',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_flight_controller_light',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var flags = parseInt(script.getField('FLAGS'));\n                var brightness = parseInt(script.getField('BRIGHTNESS'));\n                return Entry.byrobot_dronefighter_flight.setLightManual(\n                    script,\n                    0x11,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_flight_controller_light_manual_single_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0xFF'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_flight_controller_light',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_dronefighter_flight.setLightManual(\n                    script,\n                    0x11,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_flight_drone_light_manual_single_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_drone_light',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.setLightManual(script, 0x10, 0xff, 0);\n            },\n        },\n        byrobot_dronefighter_flight_drone_light_manual_single: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_all, '255'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_1, '128'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_2, '64'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_3, '32'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_4, '16'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_blue, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_red, '4'],\n                    ],\n                    value: '128',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_on, '220'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_off, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b25, '75'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b50, '125'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b75, '200'],\n                        [Lang.Blocks.byrobot_dronefighter_common_light_manual_b100, '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_flight_drone_light_manual_single',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_flight_drone_light',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var flags = parseInt(script.getField('FLAGS'));\n                var brightness = parseInt(script.getField('BRIGHTNESS'));\n                return Entry.byrobot_dronefighter_flight.setLightManual(\n                    script,\n                    0x10,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_flight_drone_light_manual_single_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0xFF'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_dronefighter_flight_drone_light',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_dronefighter_flight.setLightManual(\n                    script,\n                    0x10,\n                    flags,\n                    brightness\n                );\n            },\n        },\n        byrobot_dronefighter_flight_controller_buzzer_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_buzzer',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.setBuzzerStop(script);\n            },\n        },\n        byrobot_dronefighter_flight_controller_buzzer_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_dronefighter_flight_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n            },\n            class: 'byrobot_dronefighter_flight_buzzer',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_flight.setBuzzerMute(\n                        script,\n                        60000,\n                        false,\n                        true\n                    );\n                else\n                    return Entry.byrobot_dronefighter_flight.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        60000,\n                        false,\n                        true\n                    );\n            },\n        },\n        byrobot_dronefighter_flight_controller_buzzer_scale_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_dronefighter_flight_buzzer',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_flight.setBuzzerMute(\n                        script,\n                        time,\n                        true,\n                        true\n                    );\n                else\n                    return Entry.byrobot_dronefighter_flight.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        time,\n                        true,\n                        true\n                    );\n            },\n        },\n        byrobot_dronefighter_flight_controller_buzzer_scale_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['4', '3'], ['5', '4'], ['6', '5'], ['7', '6'], ['8', '7']],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_c, '0'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_cs, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_d, '2'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_ds, '3'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_e, '4'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_f, '5'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_fs, '6'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_g, '7'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_gs, '8'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_a, '9'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_as, '10'],\n                        [Lang.Blocks.byrobot_dronefighter_controller_buzzer_b, '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_dronefighter_flight_buzzer',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_dronefighter_flight.setBuzzerMute(\n                        script,\n                        time,\n                        false,\n                        false\n                    );\n                else\n                    return Entry.byrobot_dronefighter_flight.setBuzzerScale(\n                        script,\n                        octave,\n                        scale,\n                        time,\n                        false,\n                        false\n                    );\n            },\n        },\n        byrobot_dronefighter_flight_controller_buzzer_hz: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'byrobot_dronefighter_flight_buzzer',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                return Entry.byrobot_dronefighter_flight.setBuzzerHz(\n                    script,\n                    hz,\n                    60000,\n                    false,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_flight_controller_buzzer_hz_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_dronefighter_flight_buzzer',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_dronefighter_flight.setBuzzerHz(script, hz, time, true, true);\n            },\n        },\n        byrobot_dronefighter_flight_controller_buzzer_hz_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_dronefighter_flight_buzzer',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_dronefighter_flight.setBuzzerHz(\n                    script,\n                    hz,\n                    time,\n                    false,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_flight_controller_vibrator_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_vibrator',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.setVibratorStop(script);\n            },\n        },\n        byrobot_dronefighter_flight_controller_vibrator_on_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_dronefighter_flight_vibrator',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_dronefighter_flight.setVibrator(\n                    script,\n                    timeOn,\n                    0,\n                    timeOn,\n                    true,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_flight_controller_vibrator_on_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_dronefighter_flight_vibrator',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_dronefighter_flight.setVibrator(\n                    script,\n                    timeOn,\n                    0,\n                    timeOn,\n                    false,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_flight_controller_vibrator_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.02'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_dronefighter_flight_vibrator',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_dronefighter_flight.setVibrator(\n                    script,\n                    timeOn,\n                    timeOff,\n                    timeRun,\n                    true,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_flight_controller_vibrator_reserve: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.02'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_dronefighter_flight_vibrator',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_dronefighter_flight.setVibrator(\n                    script,\n                    timeOn,\n                    timeOff,\n                    timeRun,\n                    false,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_flight_drone_irmessage: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_drone_irmessage',\n            },\n            paramsKeyMap: {\n                IRMESSAGE: 0,\n            },\n            class: 'byrobot_dronefighter_flight_irmessage',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var irmessage = script.getNumberValue('IRMESSAGE', script);\n                return Entry.byrobot_dronefighter_flight.sendIrMessage(script, irmessage);\n            },\n        },\n        byrobot_dronefighter_flight_drone_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_motor',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.sendStop(script);\n            },\n        },\n        byrobot_dronefighter_flight_drone_motorsingle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1'], ['3', '2'], ['4', '3']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_drone_motorsingle',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class: 'byrobot_dronefighter_flight_motor',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var motorIndex = parseInt(script.getField('MOTORINDEX'));\n                var motorDirection = 1;\n                var motorSpeed = parseInt(script.getNumberValue('MOTORSPEED', script));\n\n                return Entry.byrobot_dronefighter_flight.setMotorSingle(\n                    script,\n                    motorIndex,\n                    motorDirection,\n                    motorSpeed\n                );\n            },\n        },\n        byrobot_dronefighter_flight_drone_motorsingle_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_drone_motorsingle_input',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class: 'byrobot_dronefighter_flight_motor',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var motorIndex = parseInt(script.getNumberValue('MOTORINDEX', script)) - 1;\n                var motorDirection = 1;\n                var motorSpeed = parseInt(script.getNumberValue('MOTORSPEED', script));\n\n                return Entry.byrobot_dronefighter_flight.setMotorSingle(\n                    script,\n                    motorIndex,\n                    motorDirection,\n                    motorSpeed\n                );\n            },\n        },\n        byrobot_dronefighter_flight_drone_command_mode_vehicle_drone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_command_mode_vehicle_drone',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.setModeVehicle(script, 0x10); // 0x10 : Mode::Vehicle::Flight\n            },\n        },\n        byrobot_dronefighter_flight_drone_control_drone_takeoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_control_drone_takeoff',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.setEventFlight(script, 0x11, 200); // 0x11 : FlightEvent::TakeOff\n            },\n        },\n        byrobot_dronefighter_flight_drone_control_drone_landing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_control_drone_landing',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.setEventFlight(script, 0x12, 200); // 0x12 : FlightEvent::Landing\n            },\n        },\n        byrobot_dronefighter_flight_drone_control_drone_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_control_drone_stop',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.sendStop(script);\n            },\n        },\n        byrobot_dronefighter_flight_drone_control_coordinate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_drone_coordinate_world, '1'],\n                        [Lang.Blocks.byrobot_dronefighter_drone_coordinate_local, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_dronefighter_flight_drone_control_coordinate',\n            },\n            paramsKeyMap: {\n                COORDINATE: 0,\n            },\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var coordinate = script.getField('COORDINATE');\n                return Entry.byrobot_dronefighter_flight.sendCommand(\n                    script,\n                    0x10,\n                    0x20,\n                    coordinate\n                );\n            },\n        },\n        byrobot_dronefighter_flight_drone_control_drone_reset_heading: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_dronefighter_flight_drone_control_drone_reset_heading',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_dronefighter_flight.sendCommand(script, 0x10, 0x22, 0xa0); // 0x22 : CommandType::FlightEvent  // 0xA0 : FlightEvent::ResetHeading\n            },\n        },\n        byrobot_dronefighter_flight_drone_control_quad_one: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_drone_control_quad_roll, 'control_roll'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_control_quad_pitch,\n                            'control_pitch',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_drone_control_quad_yaw, 'control_yaw'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_control_quad_throttle,\n                            'control_throttle',\n                        ],\n                    ],\n                    value: 'control_throttle',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_drone_control_quad_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE: 1,\n            },\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var controlTarget = script.getField('CONTROLTARGET');\n                var value = parseInt(script.getNumberValue('VALUE', script));\n\n                return Entry.byrobot_dronefighter_flight.sendControlQuadSingle(\n                    script,\n                    controlTarget,\n                    value,\n                    0,\n                    false\n                );\n            },\n        },\n        byrobot_dronefighter_flight_drone_control_quad_one_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_dronefighter_drone_control_quad_roll, 'control_roll'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_control_quad_pitch,\n                            'control_pitch',\n                        ],\n                        [Lang.Blocks.byrobot_dronefighter_drone_control_quad_yaw, 'control_yaw'],\n                        [\n                            Lang.Blocks.byrobot_dronefighter_drone_control_quad_throttle,\n                            'control_throttle',\n                        ],\n                    ],\n                    value: 'control_throttle',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_drone_control_quad_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var controlTarget = script.getField('CONTROLTARGET');\n                var value = parseInt(script.getNumberValue('VALUE', script));\n                var time = parseInt(script.getNumberValue('TIME', script) * 1000);\n\n                return Entry.byrobot_dronefighter_flight.sendControlQuadSingle(\n                    script,\n                    controlTarget,\n                    value,\n                    time,\n                    true\n                );\n            },\n        },\n        byrobot_dronefighter_flight_drone_control_quad: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'byrobot_dronefighter_flight_drone_control_quad',\n            },\n            paramsKeyMap: {\n                ROLL: 0,\n                PITCH: 1,\n                YAW: 2,\n                THROTTLE: 3,\n            },\n            class: 'byrobot_dronefighter_flight_control_flight',\n            isNotFor: ['byrobot_dronefighter_flight'],\n            func: function(sprite, script) {\n                var roll = parseInt(script.getNumberValue('ROLL', script));\n                var pitch = parseInt(script.getNumberValue('PITCH', script));\n                var yaw = parseInt(script.getNumberValue('YAW', script));\n                var throttle = parseInt(script.getNumberValue('THROTTLE', script));\n\n                return Entry.byrobot_dronefighter_flight.sendControlQuad(\n                    script,\n                    roll,\n                    pitch,\n                    yaw,\n                    throttle,\n                    0,\n                    false\n                );\n            },\n        },\n        /* BYROBOT DroneFighter Flight End */\n        //endregion byrobot 바이로봇\n    };\n};\n\nmodule.exports = Entry.byrobot_dronefighter_flight;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_petrone_v2_base.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_petrone_v2_base =\n{\n    /***************************************************************************************\n     *  시간 지연 함수\n     ***************************************************************************************/\n\n    // 시간 지연\n    checkFinish(script, ms)\n    {\n        const _ms = this.fit(0, ms, 60000);\n\n        if (!script.isStart)\n        {\n            script.isStart = true;\n            script.timeFlag = 1;\n\n            const fps = Entry.FPS || 60;\n            const timeValue = (60 / fps) * _ms;\n\n            setTimeout(() => {\n                script.timeFlag = 0;\n            }, timeValue);\n\n            return 'Start';\n        }\n        else if (script.timeFlag == 1)\n        {\n            return 'Running';\n        }\n        else\n        {\n            delete script.timeFlag;\n            delete script.isStart;\n            Entry.engine.isContinue = false;\n            return 'Finish';\n        }\n    },\n\n\n    /***************************************************************************************\n     *  기능 함수\n     ***************************************************************************************/\n\n    transferBufferClear()\n    {\n        Entry.hw.setDigitalPortValue('buffer_clear', 0);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['buffer_clear'];\n    },\n\n\n    fit(min, value, max)\n    {\n        return Math.max(Math.min(value, max), min);\n    },\n\n\n    /***************************************************************************************\n     *  데이터 전송 함수 (Entry -> Hardware)\n     ***************************************************************************************/\n\n    // 데이터 전송\n    transferLightManual(target, flags, brightness)\n    {\n        // 범위 조정\n        target      = this.fit(0, target, 255);\n        flags       = this.fit(0, flags, 255);\n        brightness  = this.fit(0, brightness, 255);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('light_manual_flags', flags);\n        Entry.hw.setDigitalPortValue('light_manual_brightness', brightness);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['light_manual_flags'];\n        delete Entry.hw.sendQueue['light_manual_brightness'];\n    },\n\n\n    transferLightMode(target, mode, interval)\n    {\n        // 범위 조정\n        target = Math.max(target, 0);\n        target = Math.min(target, 255);\n        mode = Math.max(mode, 0);\n        mode = Math.min(mode, 255);\n        interval = Math.max(interval, 0);\n        interval = Math.min(interval, 65535);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('light_mode_mode', mode);\n        Entry.hw.setDigitalPortValue('light_mode_interval', interval);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['light_mode_mode'];\n        delete Entry.hw.sendQueue['light_mode_interval'];\n    },\n\n\n    transferLightModeColor(target, mode, interval, red, green, blue)\n    {\n        // 범위 조정\n        target      = this.fit(0, target,   255);\n        mode        = this.fit(0, mode,     255);\n        interval    = this.fit(0, interval, 65535);\n        red         = this.fit(0, red,      255);\n        green       = this.fit(0, green,    255);\n        blue        = this.fit(0, blue,     255);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target',              target);\n        Entry.hw.setDigitalPortValue('light_mode_mode',     mode);\n        Entry.hw.setDigitalPortValue('light_mode_interval', interval);\n        Entry.hw.setDigitalPortValue('light_color_r',       red);\n        Entry.hw.setDigitalPortValue('light_color_g',       green);\n        Entry.hw.setDigitalPortValue('light_color_b',       blue);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['light_mode_mode'];\n        delete Entry.hw.sendQueue['light_mode_interval'];\n        delete Entry.hw.sendQueue['light_color_r'];\n        delete Entry.hw.sendQueue['light_color_g'];\n        delete Entry.hw.sendQueue['light_color_b'];\n    },\n\n\n    transferDisplayClearAll(target, pixel)\n    {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_clearall_pixel', pixel);\n    \n        Entry.hw.update();\n    \n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_clearall_pixel'];\n    },\n\n\n\n    transferDisplayClear(target, pixel, x, y, width, height)\n    {\n        // 범위 조정\n        x      = this.fit(0, x, 128);\n        y      = this.fit(0, y, 64);\n        width  = this.fit(0, width, 128);\n        height = this.fit(0, height, 64);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_clear_x', x);\n        Entry.hw.setDigitalPortValue('display_clear_y', y);\n        Entry.hw.setDigitalPortValue('display_clear_width', width);\n        Entry.hw.setDigitalPortValue('display_clear_height', height);\n        Entry.hw.setDigitalPortValue('display_clear_pixel', pixel);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_clear_x'];\n        delete Entry.hw.sendQueue['display_clear_y'];\n        delete Entry.hw.sendQueue['display_clear_width'];\n        delete Entry.hw.sendQueue['display_clear_height'];\n        delete Entry.hw.sendQueue['display_clear_pixel'];\n    },\n\n\n    transferDisplayInvert(target, x, y, width, height)\n    {\n        // 범위 조정\n        x      = this.fit(0, x, 128);\n        y      = this.fit(0, y, 64);\n        width  = this.fit(0, width, 128);\n        height = this.fit(0, height, 64);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_invert_x', x);\n        Entry.hw.setDigitalPortValue('display_invert_y', y);\n        Entry.hw.setDigitalPortValue('display_invert_width', width);\n        Entry.hw.setDigitalPortValue('display_invert_height', height);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_invert_x'];\n        delete Entry.hw.sendQueue['display_invert_y'];\n        delete Entry.hw.sendQueue['display_invert_width'];\n        delete Entry.hw.sendQueue['display_invert_height'];\n    },\n\n\n    transferDisplayDrawPoint(target, x, y, pixel)\n    {\n        // 범위 조정\n        x = this.fit(0, x, 128);\n        y = this.fit(0, y, 64);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_draw_point_x', x);\n        Entry.hw.setDigitalPortValue('display_draw_point_y', y);\n        Entry.hw.setDigitalPortValue('display_draw_point_pixel', pixel);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_draw_point_x'];\n        delete Entry.hw.sendQueue['display_draw_point_y'];\n        delete Entry.hw.sendQueue['display_draw_point_pixel'];\n    },\n\n\n    transferDisplayDrawLine(target, x1, y1, x2, y2, pixel, line)\n    {\n        // 범위 조정\n        x1 = this.fit(0, x1, 128);\n        y1 = this.fit(0, y1, 64);\n        x2 = this.fit(0, x2, 128);\n        y2 = this.fit(0, y2, 64);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_draw_line_x1', x1);\n        Entry.hw.setDigitalPortValue('display_draw_line_y1', y1);\n        Entry.hw.setDigitalPortValue('display_draw_line_x2', x2);\n        Entry.hw.setDigitalPortValue('display_draw_line_y2', y2);\n        Entry.hw.setDigitalPortValue('display_draw_line_pixel', pixel);\n        Entry.hw.setDigitalPortValue('display_draw_line_line', line);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_draw_line_x1'];\n        delete Entry.hw.sendQueue['display_draw_line_y1'];\n        delete Entry.hw.sendQueue['display_draw_line_x2'];\n        delete Entry.hw.sendQueue['display_draw_line_y2'];\n        delete Entry.hw.sendQueue['display_draw_line_pixel'];\n        delete Entry.hw.sendQueue['display_draw_line_line'];\n    },\n\n\n    transferDisplayDrawRect(target, x, y, width, height, pixel, flagFill, line)\n    {\n        // 범위 조정\n        x      = this.fit(0, x, 128);\n        y      = this.fit(0, y, 64);\n        width  = this.fit(0, width, 128);\n        height = this.fit(0, height, 64);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_draw_rect_x', x);\n        Entry.hw.setDigitalPortValue('display_draw_rect_y', y);\n        Entry.hw.setDigitalPortValue('display_draw_rect_width', width);\n        Entry.hw.setDigitalPortValue('display_draw_rect_height', height);\n        Entry.hw.setDigitalPortValue('display_draw_rect_pixel', pixel);\n        Entry.hw.setDigitalPortValue('display_draw_rect_flagfill', flagFill);\n        Entry.hw.setDigitalPortValue('display_draw_rect_line', line);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_draw_rect_x'];\n        delete Entry.hw.sendQueue['display_draw_rect_y'];\n        delete Entry.hw.sendQueue['display_draw_rect_width'];\n        delete Entry.hw.sendQueue['display_draw_rect_height'];\n        delete Entry.hw.sendQueue['display_draw_rect_pixel'];\n        delete Entry.hw.sendQueue['display_draw_rect_flagfill'];\n        delete Entry.hw.sendQueue['display_draw_rect_line'];\n    },\n\n\n    transferDisplayDrawCircle(target, x, y, radius, pixel, flagFill)\n    {\n        // 범위 조정\n        x      = this.fit(-50, x, 178);\n        y      = this.fit(-50, y, 114);\n        radius = this.fit(1, radius, 200);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_draw_circle_x', x);\n        Entry.hw.setDigitalPortValue('display_draw_circle_y', y);\n        Entry.hw.setDigitalPortValue('display_draw_circle_radius', radius);\n        Entry.hw.setDigitalPortValue('display_draw_circle_pixel', pixel);\n        Entry.hw.setDigitalPortValue('display_draw_circle_flagfill', flagFill);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_draw_circle_x'];\n        delete Entry.hw.sendQueue['display_draw_circle_y'];\n        delete Entry.hw.sendQueue['display_draw_circle_radius'];\n        delete Entry.hw.sendQueue['display_draw_circle_pixel'];\n        delete Entry.hw.sendQueue['display_draw_circle_flagfill'];\n    },\n\n\n    transferDisplayDrawString(target, x, y, font, pixel, string)\n    {\n        // 범위 조정\n        x = this.fit(0, x, 120);\n        y = this.fit(0, y, 60);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_draw_string_x', x);\n        Entry.hw.setDigitalPortValue('display_draw_string_y', y);\n        Entry.hw.setDigitalPortValue('display_draw_string_font', font);\n        Entry.hw.setDigitalPortValue('display_draw_string_pixel', pixel);\n        Entry.hw.setDigitalPortValue('display_draw_string_string', string);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_draw_string_x'];\n        delete Entry.hw.sendQueue['display_draw_string_y'];\n        delete Entry.hw.sendQueue['display_draw_string_font'];\n        delete Entry.hw.sendQueue['display_draw_string_pixel'];\n        delete Entry.hw.sendQueue['display_draw_string_string'];\n    },\n\n\n    transferDisplayDrawStringAlign(target, xStart, xEnd, y, align, font, pixel, string)\n    {\n        // 범위 조정\n        xStart = this.fit(0, xStart, 124);\n        xEnd   = this.fit(0, xEnd, 128)\n        y      = this.fit(0, y, 60);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('display_draw_string_align_x_start', xStart);\n        Entry.hw.setDigitalPortValue('display_draw_string_align_x_end', xEnd);\n        Entry.hw.setDigitalPortValue('display_draw_string_align_y', y);\n        Entry.hw.setDigitalPortValue('display_draw_string_align_align', align);\n        Entry.hw.setDigitalPortValue('display_draw_string_align_font', font);\n        Entry.hw.setDigitalPortValue('display_draw_string_align_pixel', pixel);\n        Entry.hw.setDigitalPortValue('display_draw_string_align_string', string);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['display_draw_string_align_x_start'];\n        delete Entry.hw.sendQueue['display_draw_string_align_x_end'];\n        delete Entry.hw.sendQueue['display_draw_string_align_y'];\n        delete Entry.hw.sendQueue['display_draw_string_align_align'];\n        delete Entry.hw.sendQueue['display_draw_string_align_font'];\n        delete Entry.hw.sendQueue['display_draw_string_align_pixel'];\n        delete Entry.hw.sendQueue['display_draw_string_align_string'];\n    },\n\n\n    transferBuzzer(mode, value, time)\n    {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x31);\n        Entry.hw.setDigitalPortValue('buzzer_mode', mode);\n        Entry.hw.setDigitalPortValue('buzzer_value', value);\n        Entry.hw.setDigitalPortValue('buzzer_time', time);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['buzzer_mode'];\n        delete Entry.hw.sendQueue['buzzer_value'];\n        delete Entry.hw.sendQueue['buzzer_time'];\n    },\n\n\n    transferVibrator(mode, timeOn, timeOff, timeRun)\n    {\n        // 범위 조정\n        timeOn  = this.fit(1, timeOn, 60000);\n        timeOff = this.fit(1, timeOff, 60000);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x31);\n        Entry.hw.setDigitalPortValue('vibrator_mode', mode);\n        Entry.hw.setDigitalPortValue('vibrator_on', timeOn);\n        Entry.hw.setDigitalPortValue('vibrator_off', timeOff);\n        Entry.hw.setDigitalPortValue('vibrator_total', timeRun);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['vibrator_mode'];\n        delete Entry.hw.sendQueue['vibrator_on'];\n        delete Entry.hw.sendQueue['vibrator_off'];\n        delete Entry.hw.sendQueue['vibrator_total'];\n    },\n\n\n    transferIrMessage(irdirection, irmessage)\n    {\n        // 범위 조정\n        irmessage = this.fit(-2147483647, irmessage, 2147483647);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x30);\n        Entry.hw.setDigitalPortValue('irmessage_direction', irdirection);\n        Entry.hw.setDigitalPortValue('irmessage_irdata', irmessage);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['irmessage_direction'];\n        delete Entry.hw.sendQueue['irmessage_irdata'];\n    },\n\n\n    transferMotorSingle(motorIndex, motorRotation, motorSpeed)\n    {\n        // 범위 조정\n        motorSpeed = this.fit(0, motorSpeed, 4096);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x30);\n        Entry.hw.setDigitalPortValue('motorsingle_target', motorIndex);\n        Entry.hw.setDigitalPortValue('motorsingle_rotation', motorRotation);\n        Entry.hw.setDigitalPortValue('motorsingle_value', motorSpeed);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['motorsingle_target'];\n        delete Entry.hw.sendQueue['motorsingle_rotation'];\n        delete Entry.hw.sendQueue['motorsingle_value'];\n    },\n\n\n    transferCommand(target, command, option)\n    {\n        // 전송\n        Entry.hw.setDigitalPortValue('target', target);\n        Entry.hw.setDigitalPortValue('command_command', command);\n        Entry.hw.setDigitalPortValue('command_option', option);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['command_command'];\n        delete Entry.hw.sendQueue['command_option'];\n    },\n\n\n    transferControlDouble(wheel, accel)\n    {\n        // 범위 조정\n        wheel = this.fit(-100, wheel, 100);\n        accel = this.fit(-100, accel, 100);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x30);\n        Entry.hw.setDigitalPortValue('control_wheel', wheel);\n        Entry.hw.setDigitalPortValue('control_accel', accel);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['control_wheel'];\n        delete Entry.hw.sendQueue['control_accel'];\n    },\n\n\n    transferControlQuad(roll, pitch, yaw, throttle)\n    {\n        // 범위 조정\n        roll     = this.fit(-100, roll, 100);\n        pitch    = this.fit(-100, pitch, 100);\n        yaw      = this.fit(-100, yaw, 100);\n        throttle = this.fit(-100, throttle, 100);\n\n        // 전송\n        Entry.hw.setDigitalPortValue('target', 0x30);\n        Entry.hw.setDigitalPortValue('control_roll', roll);\n        Entry.hw.setDigitalPortValue('control_pitch', pitch);\n        Entry.hw.setDigitalPortValue('control_yaw', yaw);\n        Entry.hw.setDigitalPortValue('control_throttle', throttle);\n\n        Entry.hw.update();\n\n        delete Entry.hw.sendQueue['target'];\n        delete Entry.hw.sendQueue['control_roll'];\n        delete Entry.hw.sendQueue['control_pitch'];\n        delete Entry.hw.sendQueue['control_yaw'];\n        delete Entry.hw.sendQueue['control_throttle'];\n    },\n\n\n    /***************************************************************************************\n     *  블럭 연동 함수\n     ***************************************************************************************/\n\n    // 데이터 읽기\n    getData(script, device)\n    {\n        return Entry.hw.portData[device];\n    },\n\n\n    // LED 수동 설정\n    setLightManual(script, target, flags, brightness)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferLightManual(target, flags, brightness);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // LED 수동 설정 - RGB 값 직접 지정\n    setLightModeColor(script, target, mode, interval, red, green, blue)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferLightModeColor(target, mode, interval, red, green, blue);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // 화면 전체 지우기, 선택 영역 지우기\n    setDisplayClearAll(script, target, pixel)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayClearAll(target, pixel);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // OLED - 화면 전체 지우기, 선택 영역 지우기\n    setDisplayClear(script, target, pixel, x, y, width, height)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayClear(target, pixel, x, y, width, height);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // OLED - 선택 영역 반전\n    setDisplayInvert(script, target, x, y, width, height)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayInvert(target, x, y, width, height);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // OLED - 화면에 점 찍기\n    setDisplayDrawPoint(script, target, x, y, pixel)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayDrawPoint(target, x, y, pixel);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // OLED - 화면에 선 그리기\n    setDisplayDrawLine(script, target, x1, y1, x2, y2, pixel, line)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayDrawLine(target, x1, y1, x2, y2, pixel, line);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // OLED - 화면에 사각형 그리기\n    setDisplayDrawRect(script, target, x, y, width, height, pixel, flagFill, line)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayDrawRect(target, x, y, width, height, pixel, flagFill, line);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // OLED - 화면에 원 그리기\n    setDisplayDrawCircle(script, target, x, y, radius, pixel, flagFill)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayDrawCircle(target, x, y, radius, pixel, flagFill);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // OLED - 화면에 문자열 쓰기\n    setDisplayDrawString(script, target, x, y, font, pixel, string)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayDrawString(target, x, y, font, pixel, string);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // OLED - 화면에 문자열 정렬하여 그리기\n    setDisplayDrawStringAlign(script, target, xStart, xEnd, y, align, font, pixel, string)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferDisplayDrawStringAlign(target, xStart, xEnd, y, align, font, pixel, string);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // 버저 설정(함수 호출 시 시간은 모두 ms 단위 사용)\n    /*\n        MuteInstantally     = 1,    // 묵음 즉시 적용\n        MuteContinually     = 2,    // 묵음 예약\n\n        ScaleInstantally    = 3,    // 음계 즉시 적용\n        ScaleContinually    = 4,    // 음계 예약\n\n        HzInstantally       = 5,    // 주파수 즉시 적용\n        HzContinually       = 6,    // 주파수 예약\n     */\n    // 정지\n    setBuzzerStop(script)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferBuzzer(0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // 묵음\n    setBuzzerMute(script, time, flagDelay, flagInstantly)\n    {\n        time = this.fit(0, time, 60000);\n\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start':\n                {\n                    let mode = 2; // 묵음 연속\n                    if (flagInstantly)\n                    {\n                        mode = 1;\n                    } // 묵음 즉시\n\n                    this.transferBuzzer(mode, 0xee, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    setBuzzerScale(script, octave, scale, time, flagDelay, flagInstantly)\n    {\n        time = this.fit(0, time, 60000);\n\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start':\n                {\n                    let mode = 4; // Scale 연속\n                    if (flagInstantly)\n                    {\n                        mode = 3;\n                    } // Scale 즉시\n\n                    const scalecalc = octave * 12 + scale;\n\n                    this.transferBuzzer(mode, scalecalc, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    setBuzzerHz(script, hz, time, flagDelay, flagInstantly)\n    {\n        time = this.fit(0, time, 60000);\n\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start':\n                {\n                    let mode = 6; // Hz 연속\n                    if (flagInstantly)\n                    {\n                        mode = 5;\n                    } // Hz 즉시\n\n                    // 범위 조정\n                    hz = this.fit(1, hz, 63999);\n\n                    this.transferBuzzer(mode, hz, time);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    // 진동 제어\n    /*\n        Stop            = 0,    // 정지\n        Instantally     = 1,    // 즉시 적용\n        Continually     = 2,    // 예약\n     */\n    setVibratorStop(script)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferVibrator(0, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    setVibrator(script, timeOn, timeOff, timeRun, flagDelay, flagInstantly)\n    {\n        timeRun = this.fit(0, timeRun, 60000);\n\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, timeRun);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start':\n                {\n                    let mode = 2; // 예약\n                    if (flagInstantly)\n                    {\n                        mode = 1; // 즉시\n                    }\n\n                    this.transferVibrator(mode, timeOn, timeOff, timeRun);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    sendCommand(script, target, command, option)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferCommand(target, command, option);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    sendIrMessage(script, irdirection, irmessage)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferIrMessage(irdirection, irmessage);\n                    // Light Event (transferLightEvent 만들어야 할 듯)\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    sendStop(script)\n    {\n        return this.sendCommand(script, 0x30, 0x24, 0);\n    },\n\n\n    setMotorSingle(script, motorIndex, motorRotation, motorSpeed)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferMotorSingle(motorIndex, motorRotation, motorSpeed);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    /*\n        None = 0,           // 없음\n\n        Flight = 0x10,      // 비행(가드 포함)\n        FlightNoGuard,      // 비행(가드 없음)\n        FlightFPV,          // 비행(FPV)\n\n        Drive = 0x20,       // 주행\n        DriveFPV,           // 주행(FPV)\n\n        Test = 0x30,        // 테스트\n     */\n    setModeVehicle(script, modeVehicle)\n    {\n        switch (this.checkFinish(script, 40))\n        {\n            case 'Start':\n                {\n                    this.transferCommand(0x30, 0x10, modeVehicle);\n\n                    this.transferControlDouble(0, 0);\n                    this.transferControlQuad(0, 0, 0, 0);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    setEventFlight(script, eventFlight, time)\n    {\n        switch (this.checkFinish(script, time))\n        {\n            case 'Start':\n                {\n                    this.transferControlQuad(0, 0, 0, 0); // 기존 입력되었던 조종기 방향 초기화 (수직으로 이륙, 착륙 하도록)\n                    this.transferCommand(0x30, 0x22, eventFlight); // 0x22 : CommandType::FlightEvent\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    sendControlQuadSingle(script, controlTarget, value, time, flagDelay)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start':\n                {\n                    // 범위 조정\n                    value = this.fit(-100, value, 100);\n\n                    // 전송\n                    Entry.hw.setDigitalPortValue('target', 0x30);\n                    Entry.hw.setDigitalPortValue(controlTarget, value);\n\n                    Entry.hw.update();\n\n                    delete Entry.hw.sendQueue['target'];\n                    delete Entry.hw.sendQueue[controlTarget];\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                if (flagDelay)\n                {\n                    // 블럭을 빠져나갈 때 변경했던 값을 초기화\n\n                    // 전송\n                    Entry.hw.setDigitalPortValue('target', 0x30);\n                    Entry.hw.setDigitalPortValue(controlTarget, 0);\n\n                    Entry.hw.update();\n\n                    delete Entry.hw.sendQueue['target'];\n                    delete Entry.hw.sendQueue[controlTarget];\n                }\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n\n\n    sendControlQuad(script, roll, pitch, yaw, throttle, time, flagDelay)\n    {\n        let timeDelay = 40;\n        if (flagDelay)\n        {\n            timeDelay = Math.max(timeDelay, time);\n        }\n\n        switch (this.checkFinish(script, timeDelay))\n        {\n            case 'Start':\n                {\n                    this.transferControlQuad(roll, pitch, yaw, throttle);\n                }\n                return script;\n\n            case 'Running':\n                return script;\n\n            case 'Finish':\n                if (flagDelay)\n                {\n                    this.transferControlQuad(0, 0, 0, 0);\n                }\n                return script.callReturn();\n\n            default:\n                return script.callReturn();\n        }\n    },\n};\n\n\nmodule.exports = Entry.byrobot_petrone_v2_base;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_petrone_v2_controller.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_petrone_v2_controller =\n{\n    id: 'F.4',                                          // 엔트리에서 발급받은 하드웨어 번호를 기술합니다.\n    name: 'byrobot_petrone_v2_controller',              // isNotFor 속성과 대소문자까지 정확하게 매치되어야 합니다.\n    url: 'http://www.byrobot.co.kr/',                   // 생략 가능합니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    imageName: 'byrobot_petrone_v2_controller.png',     // images/hardware, images/hw 폴더 내에 존재하는 이미지입니다.\n    title: {\n        en: 'BYROBOT Petrone V2 controller',\n        ko: '바이로봇 페트론V2 조종기',\n    },\n\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero: function()\n    {\n        // 초기화\n        Entry.byrobot_petrone_v2_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            Entry.byrobot_petrone_v2_base.transferVibrator(0, 0, 0, 0);\n            Entry.byrobot_petrone_v2_base.transferBuzzer(0, 0, 0);\n            Entry.byrobot_petrone_v2_base.transferLightManual(0x31, 0xff, 0); // 조종기, flags = 0xFF (전체선택)\n            Entry.byrobot_petrone_v2_base.transferCommand(0x31, 0x80, 0);     // 조종기, command = 0x80 (DataStorageWrite)\n        }\n    },\n};\n\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.byrobot_petrone_v2_controller.setLanguage = function ()\n{\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_petrone_v2_common_left\":                       \"왼쪽\",\n                \"byrobot_petrone_v2_common_light_color_cottoncandy\":    \"구름솜사탕\",\n                \"byrobot_petrone_v2_common_light_color_emerald\":        \"에메랄드\",\n                \"byrobot_petrone_v2_common_light_color_lavender\":       \"라벤더\",\n                \"byrobot_petrone_v2_common_light_mode_dimming\":         \"천천히 깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_flicker\":         \"깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_flicker_double\":  \"2번 연속 깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_hold\":            \"켜짐\",\n                \"byrobot_petrone_v2_common_light_color_muscat\":         \"청포도\",\n                \"byrobot_petrone_v2_common_light_color_strawberrymilk\": \"딸기우유\",\n                \"byrobot_petrone_v2_common_light_color_sunset\":         \"저녁노을\",\n                \"byrobot_petrone_v2_common_light_manual_all\":           \"전체\",\n                \"byrobot_petrone_v2_common_light_manual_b100\":          \"밝기 100%\",\n                \"byrobot_petrone_v2_common_light_manual_b25\":           \"밝기 25%\",\n                \"byrobot_petrone_v2_common_light_manual_b50\":           \"밝기 50%\",\n                \"byrobot_petrone_v2_common_light_manual_b75\":           \"밝기 75%\",\n                \"byrobot_petrone_v2_common_light_manual_blue\":          \"파랑\",\n                \"byrobot_petrone_v2_common_light_manual_cyan\":          \"하늘색\",\n                \"byrobot_petrone_v2_common_light_manual_green\":         \"초록\",\n                \"byrobot_petrone_v2_common_light_manual_magenta\":       \"핑크\",\n                \"byrobot_petrone_v2_common_light_manual_off\":           \"끄기\",\n                \"byrobot_petrone_v2_common_light_manual_on\":            \"켜기\",\n                \"byrobot_petrone_v2_common_light_manual_red\":           \"빨강\",\n                \"byrobot_petrone_v2_common_light_manual_white\":         \"흰색\",\n                \"byrobot_petrone_v2_common_light_manual_yellow\":        \"노랑\",\n                \"byrobot_petrone_v2_common_pitch\":                      \"Pitch\",\n                \"byrobot_petrone_v2_common_right\":                      \"오른쪽\",\n                \"byrobot_petrone_v2_common_roll\":                       \"Roll\",\n                \"byrobot_petrone_v2_common_throttle\":                   \"Throttle\",\n                \"byrobot_petrone_v2_common_yaw\":                        \"Yaw\",\n                \"byrobot_petrone_v2_controller_button_bottom_left\":         \"왼쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_bottom_left_right\":   \"양쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_bottom_right\":        \"오른쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_button\":              \"버튼\",\n                \"byrobot_petrone_v2_controller_button_center_down\":         \"트림 뒤 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_left\":         \"트림 왼쪽 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_right\":        \"트림 오른쪽 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up\":           \"트림 앞 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up_left\":      \"트림 좌회전 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up_right\":     \"트림 우회전 버튼\",\n                \"byrobot_petrone_v2_controller_button_event\":               \"버튼 이벤트\",\n                \"byrobot_petrone_v2_controller_button_front_left\":          \"왼쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_button_front_left_right\":    \"양쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_button_front_right\":         \"오른쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_buzzer\":         \"버저\",\n                \"byrobot_petrone_v2_controller_buzzer_a\":       \"라\",\n                \"byrobot_petrone_v2_controller_buzzer_as\":      \"라#\",\n                \"byrobot_petrone_v2_controller_buzzer_b\":       \"시\",\n                \"byrobot_petrone_v2_controller_buzzer_c\":       \"도\",\n                \"byrobot_petrone_v2_controller_buzzer_cs\":      \"도#\",\n                \"byrobot_petrone_v2_controller_buzzer_d\":       \"레\",\n                \"byrobot_petrone_v2_controller_buzzer_ds\":      \"레#\",\n                \"byrobot_petrone_v2_controller_buzzer_e\":       \"미\",\n                \"byrobot_petrone_v2_controller_buzzer_f\":       \"파\",\n                \"byrobot_petrone_v2_controller_buzzer_fs\":      \"파#\",\n                \"byrobot_petrone_v2_controller_buzzer_g\":       \"솔\",\n                \"byrobot_petrone_v2_controller_buzzer_gs\":      \"솔#\",\n                \"byrobot_petrone_v2_controller_buzzer_mute\":    \"쉼\",\n                \"byrobot_petrone_v2_controller_display_align_center\":   \"가운데\",\n                \"byrobot_petrone_v2_controller_display_align_left\":     \"왼쪽\",\n                \"byrobot_petrone_v2_controller_display_align_right\":    \"오른쪽\",\n                \"byrobot_petrone_v2_controller_display_flagfill_off\":   \"채우지 않음\",\n                \"byrobot_petrone_v2_controller_display_flagfill_on\":    \"채움\",\n                \"byrobot_petrone_v2_controller_display_font_10x16\":     \"큼\",\n                \"byrobot_petrone_v2_controller_display_font_5x8\":       \"작음\",\n                \"byrobot_petrone_v2_controller_display_line_dashed\":    \"파선\",\n                \"byrobot_petrone_v2_controller_display_line_dotted\":    \"점선\",\n                \"byrobot_petrone_v2_controller_display_line_solid\":     \"실선\",\n                \"byrobot_petrone_v2_controller_display_pixel_black\":    \"검은색\",\n                \"byrobot_petrone_v2_controller_display_pixel_white\":    \"흰색\",\n                \"byrobot_petrone_v2_controller_joystick_direction_center\":      \"중앙\",\n                \"byrobot_petrone_v2_controller_joystick_direction_down\":        \"아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left\":        \"왼쪽\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_down\":   \"왼쪽 아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_up\":     \"왼쪽 위\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right\":       \"오른쪽\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_down\":  \"오른쪽 아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_up\":    \"오른쪽 위\",\n                \"byrobot_petrone_v2_controller_joystick_direction_up\":          \"위\",\n                \"byrobot_petrone_v2_controller_joystick_left_direction\":        \"왼쪽 조이스틱 방향\",\n                \"byrobot_petrone_v2_controller_joystick_left_event\":            \"왼쪽 조이스틱 이벤트\",\n                \"byrobot_petrone_v2_controller_joystick_left_x\":                \"왼쪽 조이스틱 가로축\",\n                \"byrobot_petrone_v2_controller_joystick_left_y\":                \"왼쪽 조이스틱 세로축\",\n                \"byrobot_petrone_v2_controller_joystick_right_direction\":       \"오른쪽 조이스틱 방향\",\n                \"byrobot_petrone_v2_controller_joystick_right_event\":           \"오른쪽 조이스틱 이벤트\",\n                \"byrobot_petrone_v2_controller_joystick_right_x\":               \"오른쪽 조이스틱 가로축\",\n                \"byrobot_petrone_v2_controller_joystick_right_y\":               \"오른쪽 조이스틱 세로축\",\n                \"byrobot_petrone_v2_entryhw_count_transfer_reserved\":           \"전송 예약된 데이터 수\",\n            },\n\n            // ko.js에 작성하던 내용\n            template: {\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz\":                   \"%1 Hz 소리를 연주 %2\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz_delay\":             \"%1 Hz 소리를 %2 초 연주 %3\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz_reserve\":           \"%1 Hz 소리를 %2 초 예약 %3\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_off\":                  \"버저 끄기 %1\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale\":                \"%1 옥타브 %2 을(를) 연주 %3\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale_delay\":          \"%1 옥타브 %2 을(를) %3 초 연주 %4\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale_reserve\":        \"%1 옥타브 %2 을(를) %3 초 예약 %4\",\n                \"byrobot_petrone_v2_controller_controller_display_clear\":               \"지우기 x %1, y %2, 너비 %3, 높이 %4 %5 %6\",\n                \"byrobot_petrone_v2_controller_controller_display_clear_all\":           \"조종기 화면 전체 지우기%1 %2\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_circle\":         \"원 x %1, y %2, 반지름 %3 %4 %5 %6\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_line\":           \"선 x1 %1, y1 %2, x2 %3, y2 %4 %5 %6 %7\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_point\":          \"점 그리기 x %1, y %2 %3 %4\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_rect\":           \"사각형 x %1, y %2, 너비 %3, 높이 %4 %5 %6 %7 %8\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_string\":         \"문자열 x %1, y %2 %3 %4 입력 %5 %6\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_string_align\":   \"문자열 정렬 x1 %1, x2 %2, y %3 %4 %5 %6 입력 %7 %8\",\n                \"byrobot_petrone_v2_controller_controller_display_invert\":              \"색반전 x %1, y %2, 너비 %3, 높이 %4 %5\",\n                \"byrobot_petrone_v2_controller_controller_if_button_press\":             \"조종기 %1 눌렀을 때\",\n                \"byrobot_petrone_v2_controller_controller_if_joystick_direction\":       \"조종기 %1 조이스틱 %2 움직였을 때\",\n                \"byrobot_petrone_v2_controller_controller_light_color_input\":           \"조종기 LED 색지정 R %1, G %2, B %3 %4 %5 %6\",\n                \"byrobot_petrone_v2_controller_controller_light_color_select\":          \"조종기 LED의 RGB 조합 예시 %1 %2 %3 %4\",\n                \"byrobot_petrone_v2_controller_controller_light_color_preset\":          \"조종기 LED %1 %2 %3\",\n                \"byrobot_petrone_v2_controller_controller_light_manual_single_input\":   \"조종기 LED %1 밝기 %2 %3\",\n                \"byrobot_petrone_v2_controller_controller_light_manual_single_off\":     \"조종기 LED 끄기 %1\",\n                \"byrobot_petrone_v2_controller_controller_value_button\":                \"%1\",\n                \"byrobot_petrone_v2_controller_controller_value_joystick\":              \"%1\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_delay\":              \"진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_off\":                \"진동 끄기 %1\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_on_delay\":           \"진동 %1 초 켜기 %2\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_on_reserve\":         \"진동 %1 초 예약 %2\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_reserve\":            \"진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4\",\n            },\n\n            Helper: {\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz\":                   \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz_delay\":             \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz_reserve\":           \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_off\":                  \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale\":                \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale_delay\":          \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale_reserve\":        \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_clear\":               \"<br>조종기 OLED 화면의 선택한 영역을 지웁니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_clear_all\":           \"<br>조종기 OLED 화면 전체를 지웁니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_circle\":         \"<br>조종기 OLED 화면에서 지정한 위치에 원을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 반지름을 지정합니다. 원의 중심 = (x, y),<br>반지름은 원의 크기를 결정합니다.<br><br>★☆사용 가능한 값의 범위는 x값은 (-50~178), y값은 (-50~114), 반지름은 (1~200)입니다.☆★<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_line\":           \"<br>조종기 OLED 화면에서 지정한 위치에 선을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>시작점 = (x1, y1), 끝나는점 = (x2, y2)<br>선 그리기는 시작점과 끝나는점을 이어주는 기능입니다.<br>사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_point\":          \"<br>조종기 OLED 화면에서 지정한 위치에 점을 찍습니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다. x, y 좌표값으로 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_rect\":           \"<br>조종기 OLED 화면에서 지정한 위치에 사각형을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 너비, 높이를 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_string\":         \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 씁니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 글자 크기, 색을 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값은 (0~120), y값은 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_string_align\":   \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 정렬하여 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 정렬 방향, 글자 크기, 색을 지정합니다. 시작점 = (x1, y), 끝나는점 = (x2, y), 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_display_invert\":              \"<br>조종기 OLED 화면에서 선택한 영역의 색을 반전시킵니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_controller_controller_if_button_press\":             \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_petrone_v2_controller_controller_if_joystick_direction\":       \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_petrone_v2_controller_controller_light_color_input\":           \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 조종기 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_controller_controller_light_color_select\":          \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 조종기 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_controller_controller_light_color_preset\":          \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_controller_controller_light_manual_single_input\":   \"<br>조종기 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다. 값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_controller_controller_light_manual_single_off\":     \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_petrone_v2_controller_controller_value_button\":                \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_petrone_v2_controller_controller_value_joystick\":              \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_delay\":              \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_off\":                \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_on_delay\":           \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_on_reserve\":         \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_reserve\":            \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n            }\n        },\n\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_petrone_v2_common_left\":                       \"left\",\n                \"byrobot_petrone_v2_common_light_color_cottoncandy\":    \"cotton candy\",\n                \"byrobot_petrone_v2_common_light_color_emerald\":        \"emerald\",\n                \"byrobot_petrone_v2_common_light_color_lavender\":       \"lavender\",\n                \"byrobot_petrone_v2_common_light_mode_dimming\":         \"dimming\",\n                \"byrobot_petrone_v2_common_light_mode_flicker\":         \"flicker\",\n                \"byrobot_petrone_v2_common_light_mode_flicker_double\":  \"flicker double\",\n                \"byrobot_petrone_v2_common_light_mode_hold\":            \"hold\",\n                \"byrobot_petrone_v2_common_light_color_muscat\":         \"muscat\",\n                \"byrobot_petrone_v2_common_light_color_strawberrymilk\": \"strawberry milk\",\n                \"byrobot_petrone_v2_common_light_color_sunset\":         \"sunset\",\n                \"byrobot_petrone_v2_common_light_manual_all\":           \"all\",\n                \"byrobot_petrone_v2_common_light_manual_b100\":          \"brightness 100%\",\n                \"byrobot_petrone_v2_common_light_manual_b25\":           \"brightness 25%\",\n                \"byrobot_petrone_v2_common_light_manual_b50\":           \"brightness 50%\",\n                \"byrobot_petrone_v2_common_light_manual_b75\":           \"brightness 75%\",\n                \"byrobot_petrone_v2_common_light_manual_blue\":          \"blue\",\n                \"byrobot_petrone_v2_common_light_manual_cyan\":          \"cyan\",\n                \"byrobot_petrone_v2_common_light_manual_green\":         \"green\",\n                \"byrobot_petrone_v2_common_light_manual_magenta\":       \"magenta\",\n                \"byrobot_petrone_v2_common_light_manual_off\":           \"off\",\n                \"byrobot_petrone_v2_common_light_manual_on\":            \"on\",\n                \"byrobot_petrone_v2_common_light_manual_red\":           \"red\",\n                \"byrobot_petrone_v2_common_light_manual_white\":         \"white\",\n                \"byrobot_petrone_v2_common_light_manual_yellow\":        \"yellow\",\n                \"byrobot_petrone_v2_common_pitch\":      \"pitch\",\n                \"byrobot_petrone_v2_common_right\":      \"right\",\n                \"byrobot_petrone_v2_common_roll\":       \"roll\",\n                \"byrobot_petrone_v2_common_throttle\":   \"throttle\",\n                \"byrobot_petrone_v2_common_yaw\":        \"yaw\",\n                \"byrobot_petrone_v2_controller_button_bottom_left\":         \"left round button\",\n                \"byrobot_petrone_v2_controller_button_bottom_left_right\":   \"both round button\",\n                \"byrobot_petrone_v2_controller_button_bottom_right\":        \"right round button\",\n                \"byrobot_petrone_v2_controller_button_button\":              \"button\",\n                \"byrobot_petrone_v2_controller_button_center_down\":         \"trim-backward button\",\n                \"byrobot_petrone_v2_controller_button_center_left\":         \"trim-left button\",\n                \"byrobot_petrone_v2_controller_button_center_right\":        \"trim-right button\",\n                \"byrobot_petrone_v2_controller_button_center_up\":           \"trim-forward button\",\n                \"byrobot_petrone_v2_controller_button_center_up_left\":      \"trim-turn-left button\",\n                \"byrobot_petrone_v2_controller_button_center_up_right\":     \"trim-turn-right button\",\n                \"byrobot_petrone_v2_controller_button_event\":               \"button event\",\n                \"byrobot_petrone_v2_controller_button_front_left\":          \"left red button\",\n                \"byrobot_petrone_v2_controller_button_front_left_right\":    \"both red button\",\n                \"byrobot_petrone_v2_controller_button_front_right\":         \"right red button\",\n                \"byrobot_petrone_v2_controller_buzzer\":         \"buzzer\",\n                \"byrobot_petrone_v2_controller_buzzer_a\":       \"A\",\n                \"byrobot_petrone_v2_controller_buzzer_as\":      \"A#\",\n                \"byrobot_petrone_v2_controller_buzzer_b\":       \"B\",\n                \"byrobot_petrone_v2_controller_buzzer_c\":       \"C\",\n                \"byrobot_petrone_v2_controller_buzzer_cs\":      \"C#\",\n                \"byrobot_petrone_v2_controller_buzzer_d\":       \"D\",\n                \"byrobot_petrone_v2_controller_buzzer_ds\":      \"D#\",\n                \"byrobot_petrone_v2_controller_buzzer_e\":       \"E\",\n                \"byrobot_petrone_v2_controller_buzzer_f\":       \"F\",\n                \"byrobot_petrone_v2_controller_buzzer_fs\":      \"F#\",\n                \"byrobot_petrone_v2_controller_buzzer_g\":       \"G\",\n                \"byrobot_petrone_v2_controller_buzzer_gs\":      \"G#\",\n                \"byrobot_petrone_v2_controller_buzzer_mute\":    \"mute\",\n                \"byrobot_petrone_v2_controller_display_align_center\":           \"center\",\n                \"byrobot_petrone_v2_controller_display_align_left\":             \"left\",\n                \"byrobot_petrone_v2_controller_display_align_right\":            \"right\",\n                \"byrobot_petrone_v2_controller_display_flagfill_off\":           \"not fill\",\n                \"byrobot_petrone_v2_controller_display_flagfill_on\":            \"fill\",\n                \"byrobot_petrone_v2_controller_display_font_10x16\":             \"big\",\n                \"byrobot_petrone_v2_controller_display_font_5x8\":               \"small\",\n                \"byrobot_petrone_v2_controller_display_line_dashed\":            \"dashed\",\n                \"byrobot_petrone_v2_controller_display_line_dotted\":            \"dotted\",\n                \"byrobot_petrone_v2_controller_display_line_solid\":             \"solid\",\n                \"byrobot_petrone_v2_controller_display_pixel_black\":            \"black\",\n                \"byrobot_petrone_v2_controller_display_pixel_white\":            \"white\",\n                \"byrobot_petrone_v2_controller_joystick_direction_center\":      \"center\",\n                \"byrobot_petrone_v2_controller_joystick_direction_down\":        \"down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left\":        \"left\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_down\":   \"left down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_up\":     \"left up\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right\":       \"right\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_down\":  \"right down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_up\":    \"right up\",\n                \"byrobot_petrone_v2_controller_joystick_direction_up\":          \"up\",\n                \"byrobot_petrone_v2_controller_joystick_left_direction\":        \"left joystick direction\",\n                \"byrobot_petrone_v2_controller_joystick_left_event\":            \"left joystick event\",\n                \"byrobot_petrone_v2_controller_joystick_left_x\":                \"left joystick horizontal\",\n                \"byrobot_petrone_v2_controller_joystick_left_y\":                \"left joystick vertical\",\n                \"byrobot_petrone_v2_controller_joystick_right_direction\":       \"right joystick direction\",\n                \"byrobot_petrone_v2_controller_joystick_right_event\":           \"right joystick event\",\n                \"byrobot_petrone_v2_controller_joystick_right_x\":               \"right joystick horizontal\",\n                \"byrobot_petrone_v2_controller_joystick_right_y\":               \"right joystick vertical\",\n                \"byrobot_petrone_v2_entryhw_count_transfer_reserved\":           \"reserved data blocks\",\n            },\n\n            // en.js에 작성하던 내용\n            template: {\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz\":                   \"play %1 Hz sound %2\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz_delay\":             \"play %1 Hz sound for %2 second %3\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_hz_reserve\":           \"reserve to play %1 Hz sound for %2 second %3\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_off\":                  \"turn off the buzzer %1\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale\":                \"play %1 octave %2 %3\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale_delay\":          \"play %1 octave %2 for %3 second %4\",\n                \"byrobot_petrone_v2_controller_controller_buzzer_scale_reserve\":        \"reserve to play %1 octave %2 for %3 second %4\",\n                \"byrobot_petrone_v2_controller_controller_display_clear\":               \"clear controller display x:%1, y:%2, width:%3, height:%4, color:%5 %6\",\n                \"byrobot_petrone_v2_controller_controller_display_clear_all\":           \"clear controller display with %1 color %2\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_circle\":         \"draw a circle in controller display x:%1, y:%2, radius:%3, %4, %5, %6\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_line\":           \"draw a line in controller display x1:%1, y1:%2, x2:%3, y2:%4, %5, %6 %7\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_point\":          \"draw a point in controller display  x:%1, y:%2, color:%3 %4\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_rect\":           \"draw a rectangle in controller display x:%1, y:%2, width:%3, height:%4, %5, %6, %7 %8\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_string\":         \"draw a string in controller display x:%1, y:%2, font size:%3, %4, input:%5, %6\",\n                \"byrobot_petrone_v2_controller_controller_display_draw_string_align\":   \"draw aligned string in controller display x1:%1, x2:%2, y:%3, align:%4, font size:%5, %6, input:%7, %8\",\n                \"byrobot_petrone_v2_controller_controller_display_invert\":              \"invert controller display x:%1, y:%2, width:%3, height:%4 %5\",\n                \"byrobot_petrone_v2_controller_controller_if_button_press\":             \"when press %1\",\n                \"byrobot_petrone_v2_controller_controller_if_joystick_direction\":       \"when %1 stick move to %2\",\n                \"byrobot_petrone_v2_controller_controller_light_color_input\":           \"decide the color values of controller LED R %1, G %2, B %3 %4 %5\",\n                \"byrobot_petrone_v2_controller_controller_light_color_select\":          \"RGB combination examples of controller LED %1 %2 %3\",\n                \"byrobot_petrone_v2_controller_controller_light_color_preset\":          \"change the state of %1 controller LED to %2 %3\",\n                \"byrobot_petrone_v2_controller_controller_light_manual_single_input\":   \"change the brightness of %1 controller LED to %2 %3\",\n                \"byrobot_petrone_v2_controller_controller_light_manual_single_off\":     \"turn off all controller LEDs %1\",\n                \"byrobot_petrone_v2_controller_controller_value_button\":                \"%1\",\n                \"byrobot_petrone_v2_controller_controller_value_joystick\":              \"%1\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_delay\":              \"vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_off\":                \"turn off the vibrator %1\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_on_delay\":           \"turn on the vibrator for %1 second %2\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_on_reserve\":         \"reserve turn on the vibrator for %1 second %2\",\n                \"byrobot_petrone_v2_controller_controller_vibrator_reserve\":            \"reserve vibration %1 second on, %2 second off for %3 seconds %4\",            \n            },\n            \n            Helper: {\n\n            }\n        }\n    }\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.byrobot_petrone_v2_controller.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/byrobot_petrone_v2_controller.png\",      // 배경 이미지\n        width: 256,     // 이미지의 폭\n        height: 256,    // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            joystick_left_x:                {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_x,           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_y:                {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_y,           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_direction:        {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_direction,   type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_event:            {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_event,       type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_x:               {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_x,          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_y:               {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_y,          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_direction:       {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_direction,  type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_event:           {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_event,      type: 'input',  pos: { x: 0, y: 0 }},\n            button_button:                  {name: Lang.Blocks.byrobot_petrone_v2_controller_button_button,             type: 'input',  pos: { x: 0, y: 0 }},\n            button_event:                   {name: Lang.Blocks.byrobot_petrone_v2_controller_button_event,              type: 'input',  pos: { x: 0, y: 0 }},\n            entryhw_countTransferReserved:  {name: Lang.Blocks.byrobot_petrone_v2_entryhw_count_transfer_reserved,      type: 'output', pos: { x: 0, y: 0 }},\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both', // 표시 모드\n    };\n};\n\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 이름\n ***************************************************************************************/\n\nEntry.byrobot_petrone_v2_controller.blockMenuBlocks = [\n    'byrobot_petrone_v2_controller_controller_value_button',\n    'byrobot_petrone_v2_controller_controller_value_joystick',\n    'byrobot_petrone_v2_controller_controller_if_button_press',\n    'byrobot_petrone_v2_controller_controller_if_joystick_direction',\n    'byrobot_petrone_v2_controller_controller_light_manual_single_off',\n    'byrobot_petrone_v2_controller_controller_light_manual_single_input',\n    'byrobot_petrone_v2_controller_controller_light_color_preset',\n    'byrobot_petrone_v2_controller_controller_light_color_input',\n    'byrobot_petrone_v2_controller_controller_light_color_select',\n    'byrobot_petrone_v2_controller_controller_display_clear_all',\n    'byrobot_petrone_v2_controller_controller_display_clear',\n    'byrobot_petrone_v2_controller_controller_display_invert',\n    'byrobot_petrone_v2_controller_controller_display_draw_point',\n    'byrobot_petrone_v2_controller_controller_display_draw_line',\n    'byrobot_petrone_v2_controller_controller_display_draw_rect',\n    'byrobot_petrone_v2_controller_controller_display_draw_circle',\n    'byrobot_petrone_v2_controller_controller_display_draw_string',\n    'byrobot_petrone_v2_controller_controller_display_draw_string_align',\n    'byrobot_petrone_v2_controller_controller_buzzer_off',\n    'byrobot_petrone_v2_controller_controller_buzzer_scale',\n    'byrobot_petrone_v2_controller_controller_buzzer_scale_delay',\n    'byrobot_petrone_v2_controller_controller_buzzer_scale_reserve',\n    'byrobot_petrone_v2_controller_controller_buzzer_hz',\n    'byrobot_petrone_v2_controller_controller_buzzer_hz_delay',\n    'byrobot_petrone_v2_controller_controller_buzzer_hz_reserve',\n    'byrobot_petrone_v2_controller_controller_vibrator_off',\n    'byrobot_petrone_v2_controller_controller_vibrator_on_delay',\n    'byrobot_petrone_v2_controller_controller_vibrator_on_reserve',\n    'byrobot_petrone_v2_controller_controller_vibrator_delay',\n    'byrobot_petrone_v2_controller_controller_vibrator_reserve',\n];\n\n\n\n/***************************************************************************************\n *  엔트리 블록 상세\n ***************************************************************************************/\nEntry.byrobot_petrone_v2_controller.getBlocks = function()\n{\n    return {\n        //region byrobot 바이로봇\n        /* BYROBOT PetroneV2 Controller Start */\n        byrobot_petrone_v2_controller_controller_value_button:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_button,   'button_button'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_event,    'button_event'],\n                    ],\n                    value: 'button_button', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_controller_controller_value_button', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_controller_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n                return read[device];\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_value_joystick:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_x,             'joystick_left_x'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_y,             'joystick_left_y'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_direction,     'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_event,         'joystick_left_event'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_x,            'joystick_right_x'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_y,            'joystick_right_y'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_direction,    'joystick_right_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_event,        'joystick_right_event'],\n                    ],\n                    value: 'joystick_left_x', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_controller_controller_value_joystick', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_controller_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n                return read[device];\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_if_button_press:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_left,        '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_right,       '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_left_right,  '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up_left,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up_right,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up,         '16'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_left,       '32'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_right,      '64'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_down,       '128'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_left,       '256'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_right,      '512'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_left_right, '768'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_controller_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'byrobot_petrone_v2_controller_boolean_input',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var button = 'button_button'; // paramsKeyMap에 정의된 이름 사용\n                var buttonevent = 'button_event'; // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2)\n                    return true;\n                else return false;\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_if_joystick_direction:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_right, 'joystick_right_direction'],\n                    ],\n                    value: 'joystick_left_direction',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left_up,      '17'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_up,           '18'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right_up,     '20'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left,         '33'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_center,       '34'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right,        '36'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left_down,    '65'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_down,         '66'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right_down,   '68'],\n                    ],\n                    value: '34',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_controller_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                DIRECTION: 1,\n            },\n            class: 'byrobot_petrone_v2_controller_boolean_input',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION')) return true;\n                else return false;\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_light_manual_single_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_controller_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_controller_controller_light',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x31, 0xff, 0);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_light_manual_single_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0xFF']},\n                    {type: 'text', params: ['255']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_light',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x31, flags, brightness);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_light_color_preset:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_red,        'red'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_green,      'green'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_blue,       'blue'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_yellow,     'yellow'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_magenta,    'magenta'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_cyan,       'cyan'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_white,      'white'],\n                    ],\n                    value: 'red',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_on,     '220'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b25,    '75'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b50,    '125'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b75,    '200'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b100,   '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_petrone_v2_controller_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_light',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var mode = 0x12;\n                var interval = parseInt(script.getField('BRIGHTNESS'));\n                var select = script.getField('FLAGS');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'red':     red = 255;  green = 0;    blue = 0;     break;\n                    case 'green':   red = 0;    green = 255;  blue = 0;     break;\n                    case 'blue':    red = 0;    green = 0;    blue = 255;   break;\n                    case 'cyan':    red = 0;    green = 255;  blue = 255;   break;\n                    case 'magenta': red = 255;  green = 0;    blue = 255;   break;\n                    case 'yellow':  red = 255;  green = 255;  blue = 0;     break;\n                    case 'white':   red = 255;  green = 255;  blue = 255;   break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_light_color_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'],   // TeamHold             = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'],   // TeamFlicker          = 0x13\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'],   // TeamFlickerDouble    = 0x14\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'],   // TeamDimming          = 0x15\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    null,\n                    {type: 'text', params: ['500']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_light_color_input',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n                MODE: 3,\n                INTERVAL: 4,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_light',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var mode = 0x12 + parseInt(script.getField('MODE'));\n                var interval = script.getNumberValue('INTERVAL');\n                var red = script.getNumberValue('RED');\n                var green = script.getNumberValue('GREEN');\n                var blue = script.getNumberValue('BLUE');\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_light_color_select:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_sunset,          'sunset'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_cottoncandy,     'cottonCandy'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_muscat,          'muscat'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_strawberrymilk,  'strawberryMilk'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_emerald,         'emerald'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_lavender,        'lavender'],\n                    ],\n                    value: 'sunset',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'], // TeamHold           = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'], // TeamFlicker        = 0x13\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'], // TeamFlickerDouble  = 0x14\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'], // TeamDimming        = 0x15\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['500']},\n                    null\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_light_color_select',\n            },\n            paramsKeyMap: {\n                SELECT: 0,\n                MODE: 1,\n                INTERVAL: 2,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_light',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var mode = 0x12 + parseInt(script.getField('MODE'));\n                var interval = script.getNumberValue('INTERVAL');\n                var select = script.getField('SELECT');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'sunset':          red = 255;  green = 100;    blue = 0;   break;\n                    case 'cottonCandy':     red = 20;   green = 250;    blue = 150; break;\n                    case 'muscat':          red = 70;   green = 255;    blue = 0;   break;\n                    case 'strawberryMilk':  red = 150;  green = 60;     blue = 20;  break;\n                    case 'emerald':         red = 0;    green = 255;    blue = 30;  break;\n                    case 'lavender':        red = 80;   green = 0;      blue = 200; break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_clear_all:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_controller_controller_display_clear_all',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayClearAll(script, 0x31, pixel);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_clear:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_display_clear',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n                PIXEL: 4,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayClear(script, 0x31, pixel, false, x, y, width, height);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_invert:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_display_invert',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                return Entry.byrobot_petrone_v2_base.setDisplayInvert(script, 0x31, x, y, width, height);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_draw_point:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_display_draw_point',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                PIXEL: 2,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawPoint(script, 0x31, x, y, pixel);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_draw_line:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_solid,  '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dotted, '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dashed, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    {type: 'text', params: ['96']},\n                    {type: 'text', params: ['48']},\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_display_draw_line',\n            },\n            paramsKeyMap: {\n                X1: 0,\n                Y1: 1,\n                X2: 2,\n                Y2: 3,\n                PIXEL: 4,\n                LINE: 5,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var x1 = script.getNumberValue('X1');\n                var y1 = script.getNumberValue('Y1');\n                var x2 = script.getNumberValue('X2');\n                var y2 = script.getNumberValue('Y2');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var line = parseInt(script.getField('LINE'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawLine(script, 0x31, x1, y1, x2, y2, pixel, line);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_draw_rect:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_on,     '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_solid,  '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dotted, '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dashed, '2'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_display_draw_rect',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n                PIXEL: 4,\n                FLAGFILL: 5,\n                LINE: 6,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var flagFill = parseInt(script.getField('FLAGFILL'));\n                var line = parseInt(script.getField('LINE'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawRect(script, 0x31, x, y, width, height, pixel, flagFill, line);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_draw_circle:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_on,     '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_display_draw_circle',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                RADIUS: 2,\n                PIXEL: 3,\n                FLAGFILL: 4,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var radius = script.getNumberValue('RADIUS');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var flagFill = parseInt(script.getField('FLAGFILL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawCircle(script, 0x31, x, y, radius, pixel, flagFill);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_draw_string:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_5x8,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_10x16,  '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['4']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    {type: 'text', params: ['{Petrone V2}']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_display_draw_string',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                FONT: 2,\n                PIXEL: 3,\n                STRING: 4,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var font = parseInt(script.getField('FONT'));\n                var pixel = parseInt(script.getField('PIXEL'));\n                var string = script.getStringValue('STRING');\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawString(script, 0x31, x, y, font, pixel, string);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_display_draw_string_align:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_left,      '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_center,    '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_right,     '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_5x8,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_10x16,  '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0']},\n                    {type: 'text', params: ['128']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    null,\n                    {type: 'text', params: ['BYROBOT & U']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_display_draw_string_align',\n            },\n            paramsKeyMap: {\n                XSTART: 0,\n                XEND: 1,\n                Y: 2,\n                ALIGN: 3,\n                FONT: 4,\n                PIXEL: 5,\n                STRING: 6,\n            },\n            class: 'byrobot_petrone_v2_controller_controller_display',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var xStart = script.getNumberValue('XSTART');\n                var xEnd = script.getNumberValue('XEND');\n                var y = script.getNumberValue('Y');\n                var align = parseInt(script.getField('ALIGN'));\n                var font = parseInt(script.getField('FONT'));\n                var pixel = parseInt(script.getField('PIXEL'));\n                var string = script.getStringValue('STRING');\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawStringAlign(script, 0x31, xStart, xEnd, y, align, font, pixel, string);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_buzzer_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_controller_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_controller_buzzer',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setBuzzerStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_buzzer_scale:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_petrone_v2_controller_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n            },\n            class: 'byrobot_petrone_v2_controller_buzzer',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, 60000, false, true);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, 60000, false, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_buzzer_scale_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_controller_buzzer',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, time, true, true);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, time, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_buzzer_scale_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_controller_buzzer',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, time, false, false);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, time, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_buzzer_hz:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'byrobot_petrone_v2_controller_buzzer',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, 60000, false, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_buzzer_hz_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_petrone_v2_controller_buzzer',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, time, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_buzzer_hz_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_petrone_v2_controller_buzzer',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, time, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_vibrator_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_controller_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_controller_vibrator',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setVibratorStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_vibrator_on_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_petrone_v2_controller_vibrator',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, 0, timeOn, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_vibrator_on_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_petrone_v2_controller_vibrator',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, 0, timeOn, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_controller_controller_vibrator_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0.02']},\n                    {type: 'text', params: ['0.2']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_petrone_v2_controller_vibrator',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, timeOff, timeRun, true, true);\n            },\n        },\n\n        \n        byrobot_petrone_v2_controller_controller_vibrator_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0.02']},\n                    {type: 'text', params: ['0.2']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_controller_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_petrone_v2_controller_vibrator',\n            isNotFor: ['byrobot_petrone_v2_controller'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, timeOff, timeRun, false, false);\n            },\n        },\n        /* BYROBOT PetroneV2 Controller End */\n        //endregion byrobot 바이로봇\n    };\n};\n\nmodule.exports = Entry.byrobot_petrone_v2_controller;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_petrone_v2_drive.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_petrone_v2_drive =\n{\n    id: 'F.5',\n    name: 'byrobot_petrone_v2_drive',\n    url: 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_petrone_v2_drive.png',\n    title: {\n        \"en\": \"BYROBOT Petrone V2 drive\",\n        \"ko\": \"바이로봇 페트론V2 자동차\"\n    },\n\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero: function()\n    {\n        // 초기화\n        Entry.byrobot_petrone_v2_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            Entry.byrobot_petrone_v2_base.transferCommand(0x30, 0x24, 0);       // 드론, command = 0x24 (Stop)\n            Entry.byrobot_petrone_v2_base.transferVibrator(0, 0, 0, 0);\n            Entry.byrobot_petrone_v2_base.transferBuzzer(0, 0, 0);\n            Entry.byrobot_petrone_v2_base.transferLightManual(0x30, 0xff, 0);   // LED 초기화(모두 꺼짐)\n            Entry.byrobot_petrone_v2_base.transferLightManual(0x31, 0xff, 0);   // LED 초기화(모두 꺼짐)\n            Entry.byrobot_petrone_v2_base.transferLightModeColor(0x30, 0x12, 200, 255, 0, 0); // LED 초기화(눈 빨강)\n            Entry.byrobot_petrone_v2_base.transferLightModeColor(0x30, 0x42, 200, 255, 0, 0); // LED 초기화(팔 빨강)\n            Entry.byrobot_petrone_v2_base.transferMotorSingle(0, 1, 0);         // 1번 모터방향 초기화(시계방향)\n            Entry.byrobot_petrone_v2_base.transferMotorSingle(1, 2, 0);         // 2번 모터방향 초기화(반시계방향)\n        }\n    },\n};\n\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.byrobot_petrone_v2_drive.setLanguage = function ()\n{\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_petrone_v2_common_left\":                       \"왼쪽\",\n                \"byrobot_petrone_v2_common_light_color_cottoncandy\":    \"구름솜사탕\",\n                \"byrobot_petrone_v2_common_light_color_emerald\":        \"에메랄드\",\n                \"byrobot_petrone_v2_common_light_color_lavender\":       \"라벤더\",\n                \"byrobot_petrone_v2_common_light_mode_dimming\":         \"천천히 깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_flicker\":         \"깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_flicker_double\":  \"2번 연속 깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_hold\":            \"켜짐\",\n                \"byrobot_petrone_v2_common_light_color_muscat\":         \"청포도\",\n                \"byrobot_petrone_v2_common_light_color_strawberrymilk\": \"딸기우유\",\n                \"byrobot_petrone_v2_common_light_color_sunset\":         \"저녁노을\",\n                \"byrobot_petrone_v2_common_light_manual_all\":           \"전체\",\n                \"byrobot_petrone_v2_common_light_manual_b100\":          \"밝기 100%\",\n                \"byrobot_petrone_v2_common_light_manual_b25\":           \"밝기 25%\",\n                \"byrobot_petrone_v2_common_light_manual_b50\":           \"밝기 50%\",\n                \"byrobot_petrone_v2_common_light_manual_b75\":           \"밝기 75%\",\n                \"byrobot_petrone_v2_common_light_manual_blue\":          \"파랑\",\n                \"byrobot_petrone_v2_common_light_manual_cyan\":          \"하늘색\",\n                \"byrobot_petrone_v2_common_light_manual_green\":         \"초록\",\n                \"byrobot_petrone_v2_common_light_manual_magenta\":       \"핑크\",\n                \"byrobot_petrone_v2_common_light_manual_off\":           \"끄기\",\n                \"byrobot_petrone_v2_common_light_manual_on\":            \"켜기\",\n                \"byrobot_petrone_v2_common_light_manual_red\":           \"빨강\",\n                \"byrobot_petrone_v2_common_light_manual_white\":         \"흰색\",\n                \"byrobot_petrone_v2_common_light_manual_yellow\":        \"노랑\",\n                \"byrobot_petrone_v2_common_pitch\":                      \"Pitch\",\n                \"byrobot_petrone_v2_common_right\":                      \"오른쪽\",\n                \"byrobot_petrone_v2_common_roll\":                       \"Roll\",\n                \"byrobot_petrone_v2_common_throttle\":                   \"Throttle\",\n                \"byrobot_petrone_v2_common_yaw\":                        \"Yaw\",\n                \"byrobot_petrone_v2_controller_button_bottom_left\":         \"왼쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_bottom_left_right\":   \"양쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_bottom_right\":        \"오른쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_button\":              \"버튼\",\n                \"byrobot_petrone_v2_controller_button_center_down\":         \"트림 뒤 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_left\":         \"트림 왼쪽 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_right\":        \"트림 오른쪽 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up\":           \"트림 앞 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up_left\":      \"트림 좌회전 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up_right\":     \"트림 우회전 버튼\",\n                \"byrobot_petrone_v2_controller_button_event\":               \"버튼 이벤트\",\n                \"byrobot_petrone_v2_controller_button_front_left\":          \"왼쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_button_front_left_right\":    \"양쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_button_front_right\":         \"오른쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_buzzer\":         \"버저\",\n                \"byrobot_petrone_v2_controller_buzzer_a\":       \"라\",\n                \"byrobot_petrone_v2_controller_buzzer_as\":      \"라#\",\n                \"byrobot_petrone_v2_controller_buzzer_b\":       \"시\",\n                \"byrobot_petrone_v2_controller_buzzer_c\":       \"도\",\n                \"byrobot_petrone_v2_controller_buzzer_cs\":      \"도#\",\n                \"byrobot_petrone_v2_controller_buzzer_d\":       \"레\",\n                \"byrobot_petrone_v2_controller_buzzer_ds\":      \"레#\",\n                \"byrobot_petrone_v2_controller_buzzer_e\":       \"미\",\n                \"byrobot_petrone_v2_controller_buzzer_f\":       \"파\",\n                \"byrobot_petrone_v2_controller_buzzer_fs\":      \"파#\",\n                \"byrobot_petrone_v2_controller_buzzer_g\":       \"솔\",\n                \"byrobot_petrone_v2_controller_buzzer_gs\":      \"솔#\",\n                \"byrobot_petrone_v2_controller_buzzer_mute\":    \"쉼\",\n                \"byrobot_petrone_v2_controller_display_align_center\":   \"가운데\",\n                \"byrobot_petrone_v2_controller_display_align_left\":     \"왼쪽\",\n                \"byrobot_petrone_v2_controller_display_align_right\":    \"오른쪽\",\n                \"byrobot_petrone_v2_controller_display_flagfill_off\":   \"채우지 않음\",\n                \"byrobot_petrone_v2_controller_display_flagfill_on\":    \"채움\",\n                \"byrobot_petrone_v2_controller_display_font_10x16\":     \"큼\",\n                \"byrobot_petrone_v2_controller_display_font_5x8\":       \"작음\",\n                \"byrobot_petrone_v2_controller_display_line_dashed\":    \"파선\",\n                \"byrobot_petrone_v2_controller_display_line_dotted\":    \"점선\",\n                \"byrobot_petrone_v2_controller_display_line_solid\":     \"실선\",\n                \"byrobot_petrone_v2_controller_display_pixel_black\":    \"검은색\",\n                \"byrobot_petrone_v2_controller_display_pixel_white\":    \"흰색\",\n                \"byrobot_petrone_v2_controller_joystick_direction_center\":      \"중앙\",\n                \"byrobot_petrone_v2_controller_joystick_direction_down\":        \"아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left\":        \"왼쪽\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_down\":   \"왼쪽 아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_up\":     \"왼쪽 위\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right\":       \"오른쪽\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_down\":  \"오른쪽 아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_up\":    \"오른쪽 위\",\n                \"byrobot_petrone_v2_controller_joystick_direction_up\":          \"위\",\n                \"byrobot_petrone_v2_controller_joystick_left_direction\":        \"왼쪽 조이스틱 방향\",\n                \"byrobot_petrone_v2_controller_joystick_left_event\":            \"왼쪽 조이스틱 이벤트\",\n                \"byrobot_petrone_v2_controller_joystick_left_x\":                \"왼쪽 조이스틱 가로축\",\n                \"byrobot_petrone_v2_controller_joystick_left_y\":                \"왼쪽 조이스틱 세로축\",\n                \"byrobot_petrone_v2_controller_joystick_right_direction\":       \"오른쪽 조이스틱 방향\",\n                \"byrobot_petrone_v2_controller_joystick_right_event\":           \"오른쪽 조이스틱 이벤트\",\n                \"byrobot_petrone_v2_controller_joystick_right_x\":               \"오른쪽 조이스틱 가로축\",\n                \"byrobot_petrone_v2_controller_joystick_right_y\":               \"오른쪽 조이스틱 세로축\",\n                \"byrobot_petrone_v2_drone_accel_x\":             \"가속도 x\",\n                \"byrobot_petrone_v2_drone_accel_y\":             \"가속도 y\",\n                \"byrobot_petrone_v2_drone_accel_z\":             \"가속도 z\",\n                \"byrobot_petrone_v2_drone_attitude_pitch\":      \"자세 Pitch\",\n                \"byrobot_petrone_v2_drone_attitude_roll\":       \"자세 Roll\",\n                \"byrobot_petrone_v2_drone_attitude_yaw\":        \"자세 Yaw\",\n                \"byrobot_petrone_v2_drone_control_double_accel_forward\":    \"전진/후진\",\n                \"byrobot_petrone_v2_drone_control_double_wheel\":            \"방향\",\n                \"byrobot_petrone_v2_drone_control_double_wheel_left\":       \"왼쪽 회전\",\n                \"byrobot_petrone_v2_drone_control_double_wheel_right\":      \"오른쪽 회전\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch\":              \"Pitch\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch_backward\":     \"뒤로\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch_forward\":      \"앞으로\",\n                \"byrobot_petrone_v2_drone_control_quad_roll\":               \"Roll\",\n                \"byrobot_petrone_v2_drone_control_quad_roll_left\":          \"왼쪽\",\n                \"byrobot_petrone_v2_drone_control_quad_roll_right\":         \"오른쪽\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle\":           \"Throttle\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle_down\":      \"아래\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle_up\":        \"위\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw\":                \"Yaw\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw_left\":           \"왼쪽 회전\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw_right\":          \"오른쪽 회전\",\n                \"byrobot_petrone_v2_drone_coordinate_local\":            \"off (숙련자용)\",\n                \"byrobot_petrone_v2_drone_coordinate_world\":            \"on (초보자용)\",\n                \"byrobot_petrone_v2_drone_gyro_pitch\":                  \"각속도 Pitch\",\n                \"byrobot_petrone_v2_drone_gyro_roll\":                   \"각속도 Roll\",\n                \"byrobot_petrone_v2_drone_gyro_yaw\":                    \"각속도 Yaw\",\n                \"byrobot_petrone_v2_drone_imageflow_positionX\":         \"image flow X\",\n                \"byrobot_petrone_v2_drone_imageflow_positionY\":         \"image flow Y\",\n                \"byrobot_petrone_v2_drone_irmessage\":                   \"적외선 수신 값\",\n                \"byrobot_petrone_v2_drone_irmessage_direction\":         \"적외선 수신 방향\",\n                \"byrobot_petrone_v2_drone_irmessage_direction_front\":   \"앞\",\n                \"byrobot_petrone_v2_drone_irmessage_direction_rear\":    \"뒤\",\n                \"byrobot_petrone_v2_drone_light_color_arm\":             \"팔\",\n                \"byrobot_petrone_v2_drone_light_color_eye\":             \"눈\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_blue\":       \"팔 파랑\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_green\":      \"팔 초록\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_red\":        \"팔 빨강\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_blue\":       \"눈 파랑\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_green\":      \"눈 초록\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_red\":        \"눈 빨강\",\n                \"byrobot_petrone_v2_drone_motor_rotation_clockwise\":        \"시계 방향\",\n                \"byrobot_petrone_v2_drone_motor_rotation_counterclockwise\": \"반시계 방향\",\n                \"byrobot_petrone_v2_drone_pressure_pressure\":           \"해발고도\",\n                \"byrobot_petrone_v2_drone_pressure_temperature\":        \"온도\",\n                \"byrobot_petrone_v2_drone_range_bottom\":                \"바닥까지 거리\",\n                \"byrobot_petrone_v2_drone_state_battery\":               \"배터리\",\n                \"byrobot_petrone_v2_drone_state_mode_coordinate\":       \"기본 좌표계\",\n                \"byrobot_petrone_v2_drone_state_mode_drive\":            \"자동차 동작 상태\",\n                \"byrobot_petrone_v2_drone_state_mode_flight\":           \"비행 동작 상태\",\n                \"byrobot_petrone_v2_drone_state_mode_system\":           \"시스템 모드\",\n                \"byrobot_petrone_v2_drone_state_mode_vehicle\":          \"Vehicle mode\",\n                \"byrobot_petrone_v2_drone_team\":                    \"팀 \",\n                \"byrobot_petrone_v2_drone_team_blue\":               \"블루\",\n                \"byrobot_petrone_v2_drone_team_red\":                \"레드\",\n                \"byrobot_petrone_v2_drone_vehicle_drive\":           \"자동차\",\n                \"byrobot_petrone_v2_drone_vehicle_drive_fpv\":       \"자동차(FPV)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight\":          \"드론(가드 포함)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight_fpv\":      \"드론(FPV)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight_noguard\":      \"드론(가드 없음)\",\n                \"byrobot_petrone_v2_entryhw_count_transfer_reserved\":   \"전송 예약된 데이터 수\",\n            },\n\n            // ko.js에 작성하던 내용\n            template: {\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz\":                    \"%1 Hz 소리를 연주 %2\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz_delay\":              \"%1 Hz 소리를 %2 초 연주 %3\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz_reserve\":            \"%1 Hz 소리를 %2 초 예약 %3\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_off\":                   \"버저 끄기 %1\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale\":                 \"%1 옥타브 %2 을(를) 연주 %3\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale_delay\":           \"%1 옥타브 %2 을(를) %3 초 연주 %4\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale_reserve\":         \"%1 옥타브 %2 을(를) %3 초 예약 %4\",\n                \"byrobot_petrone_v2_drive_controller_display_clear\":                \"지우기 x %1, y %2, 너비 %3, 높이 %4 %5 %6\",\n                \"byrobot_petrone_v2_drive_controller_display_clear_all\":            \"조종기 화면 전체 지우기%1 %2\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_circle\":          \"원 x %1, y %2, 반지름 %3 %4 %5 %6\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_line\":            \"선 x1 %1, y1 %2, x2 %3, y2 %4 %5 %6 %7\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_point\":           \"점 그리기 x %1, y %2 %3 %4\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_rect\":            \"사각형 x %1, y %2, 너비 %3, 높이 %4 %5 %6 %7 %8\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_string\":          \"문자열 x %1, y %2 %3 %4 입력 %5 %6\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_string_align\":    \"문자열 정렬 x1 %1, x2 %2, y %3 %4 %5 %6 입력 %7 %8\",\n                \"byrobot_petrone_v2_drive_controller_display_invert\":               \"색반전 x %1, y %2, 너비 %3, 높이 %4 %5\",\n                \"byrobot_petrone_v2_drive_controller_if_button_press\":              \"조종기 %1 눌렀을 때\",\n                \"byrobot_petrone_v2_drive_controller_if_joystick_direction\":        \"조종기 %1 조이스틱 %2 움직였을 때\",\n                \"byrobot_petrone_v2_drive_controller_light_color_input\":            \"조종기 LED 색지정 R %1, G %2, B %3 %4 %5 %6\",\n                \"byrobot_petrone_v2_drive_controller_light_color_select\":           \"조종기 LED의 RGB 조합 예시 %1 %2 %3 %4\",\n                \"byrobot_petrone_v2_drive_controller_light_color_preset\":           \"조종기 LED %1 %2 %3\",\n                \"byrobot_petrone_v2_drive_controller_light_manual_single_input\":    \"조종기 LED %1 밝기 %2 %3\",\n                \"byrobot_petrone_v2_drive_controller_light_manual_single_off\":      \"조종기 LED 끄기 %1\",\n                \"byrobot_petrone_v2_drive_controller_value_button\":                 \"%1\",\n                \"byrobot_petrone_v2_drive_controller_value_joystick\":               \"%1\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_delay\":               \"진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_off\":                 \"진동 끄기 %1\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_on_delay\":            \"진동 %1 초 켜기 %2\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_on_reserve\":          \"진동 %1 초 예약 %2\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_reserve\":             \"진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4\",\n                \"byrobot_petrone_v2_drive_drone_command_mode_vehicle_car\":          \"Vehicle mode %1 선택 %2\",\n                \"byrobot_petrone_v2_drive_drone_control_car_stop\":                  \"자동차 정지 %1\",\n                \"byrobot_petrone_v2_drive_drone_control_double\":                    \"자동차를 방향 %1%, 전진/후진 %2% 정하기 %3\",\n                \"byrobot_petrone_v2_drive_drone_control_double_delay\":              \"자동차를 방향 %1%, 전진/후진 %2% %3 초 실행 %4\",\n                \"byrobot_petrone_v2_drive_drone_control_double_one\":                \"자동차를 %1 %2% 정하기 %3\",\n                \"byrobot_petrone_v2_drive_drone_control_double_one_delay\":          \"자동차를 %1 %2% %3 초 실행 %4\",\n                \"byrobot_petrone_v2_drive_drone_irmessage\":                         \"적외선으로 %1 값 보내기 %2\",\n                \"byrobot_petrone_v2_drive_drone_light_color_input\":                 \"자동차 %1 LED 색지정 R %2, G %3, B %4 %5 %6 %7\",\n                \"byrobot_petrone_v2_drive_drone_light_color_select\":                \"자동차 %1 LED의 RGB 조합 예시 %2 %3 %4 %5\",\n                \"byrobot_petrone_v2_drive_drone_light_color_preset\":                \"자동차 LED %1 %2 %3\",\n                \"byrobot_petrone_v2_drive_drone_light_manual_single_input\":         \"자동차 LED %1 밝기 %2 %3\",\n                \"byrobot_petrone_v2_drive_drone_light_manual_single_off\":           \"자동차 LED 끄기 %1\",\n                \"byrobot_petrone_v2_drive_drone_motor_stop\":            \"모터 정지 %1\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle\":           \"%1번 모터를 %2(으)로 회전 %3\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle_input\":     \"%1번 모터를 %2(으)로 회전 %3\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle_rotation\":  \"%1번 모터를 %2으로 %3(으)로 회전 %4\",\n                \"byrobot_petrone_v2_drive_drone_value_attitude\":        \"%1\",\n                \"byrobot_petrone_v2_drive_drone_value_etc\":             \"%1\",\n                \"byrobot_petrone_v2_drive_drone_value_imu\":             \"%1\",\n                \"byrobot_petrone_v2_drive_drone_value_sensor\":          \"%1\",\n            },\n\n            Helper: {\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz\":                    \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz_delay\":              \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz_reserve\":            \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_off\":                   \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale\":                 \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale_delay\":           \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale_reserve\":         \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_clear\":                \"<br>조종기 OLED 화면의 선택한 영역을 지웁니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_clear_all\":            \"<br>조종기 OLED 화면 전체를 지웁니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_circle\":          \"<br>조종기 OLED 화면에서 지정한 위치에 원을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 반지름을 지정합니다. 원의 중심 = (x, y),<br>반지름은 원의 크기를 결정합니다.<br><br>★☆사용 가능한 값의 범위는 x값은 (-50~178), y값은 (-50~114), 반지름은 (1~200)입니다.☆★<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_line\":            \"<br>조종기 OLED 화면에서 지정한 위치에 선을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>시작점 = (x1, y1), 끝나는점 = (x2, y2)<br>선 그리기는 시작점과 끝나는점을 이어주는 기능입니다.<br>사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_point\":           \"<br>조종기 OLED 화면에서 지정한 위치에 점을 찍습니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다. x, y 좌표값으로 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_rect\":            \"<br>조종기 OLED 화면에서 지정한 위치에 사각형을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 너비, 높이를 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_string\":          \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 씁니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 글자 크기, 색을 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값은 (0~120), y값과 높이는 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_string_align\":    \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 정렬하여 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 정렬 방향, 글자 크기, 색을 지정합니다. 시작점 = (x1, y), 끝나는점 = (x2, y), 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_display_invert\":               \"<br>조종기 OLED 화면에서 선택한 영역의 색을 반전시킵니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_drive_controller_if_button_press\":              \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_petrone_v2_drive_controller_if_joystick_direction\":        \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_petrone_v2_drive_controller_light_color_input\":            \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 조종기 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_drive_controller_light_color_select\":           \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 조종기 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_drive_controller_light_color_preset\":           \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_drive_controller_light_manual_single_input\":    \"<br>조종기 LED 여러 개의 밝기를 동시에 변경할 때 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>각각의 비트는 개별 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_drive_controller_light_manual_single_off\":      \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_petrone_v2_drive_controller_value_button\":                 \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_petrone_v2_drive_controller_value_joystick\":               \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_delay\":               \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_off\":                 \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_on_delay\":            \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_on_reserve\":          \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_reserve\":             \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_petrone_v2_drive_drone_command_mode_vehicle_car\":          \"<br>자동차 Vehicle mode를 변경합니다.<br><br>자동차 = 32, 자동차(FPV) = 33 입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#Vehicle mode</font>\",\n                \"byrobot_petrone_v2_drive_drone_control_car_stop\":                  \"<br>자동차 작동을 정지합니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#정지</font>\",\n                \"byrobot_petrone_v2_drive_drone_control_double\":                    \"<br>자동차 조종 값을 지정합니다. 입력 가능한 값의 범위는 방향 -100 ~ 100, 전진/후진 -100 ~ 100입니다. (+)값은 전진, (-)값은 후진입니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#조종</font>\",\n                \"byrobot_petrone_v2_drive_drone_control_double_delay\":              \"<br>자동차 조종 값을 지정합니다. 입력 가능한 값의 범위는 방향 -100 ~ 100, 전진/후진 -100 ~ 100입니다. (+)값은 전진, (-)값은 후진입니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                \"byrobot_petrone_v2_drive_drone_control_double_one\":                \"<br>자동차 조종 값을 지정합니다. 입력 가능한 값의 범위는 방향 -100 ~ 100, 전진/후진 -100 ~ 100입니다. (+)값은 전진, (-)값은 후진입니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#조종</font>\",\n                \"byrobot_petrone_v2_drive_drone_control_double_one_delay\":          \"<br>자동차 조종 값을 지정합니다. 입력 가능한 값의 범위는 방향 -100 ~ 100, 전진/후진 -100 ~ 100입니다. (+)값은 전진, (-)값은 후진입니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                \"byrobot_petrone_v2_drive_drone_irmessage\":                         \"<br>적외선으로 지정한 값을 보냅니다. 사용 가능한 값의 범위는 0 ~ 127입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#적외선통신</font>\",\n                \"byrobot_petrone_v2_drive_drone_light_color_input\":                 \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 자동차의 눈 또는 팔 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_drive_drone_light_color_select\":                \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 자동차 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_drive_drone_light_color_preset\":                \"<br>자동차의 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_drive_drone_light_manual_single_input\":         \"<br>자동차 LED 여러 개의 밝기를 동시에 변경할 때 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 개별 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_drive_drone_light_manual_single_off\":           \"<br>자동차의 모든 LED를 끕니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_petrone_v2_drive_drone_motor_stop\":                        \"<br>모든 모터의 작동을 정지합니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#모터정지</font>\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle\":                       \"<br>지정한 모터를 원하는 빠르기로 회전할 때 사용합니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 자동차의 바퀴가 움직이기 위해서는 2700 이상을 입력해야 합니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle_input\":                 \"<br>지정한 모터(1, 2, 3, 4)를 원하는 빠르기로 회전할 때 사용합니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 자동차의 바퀴가 움직이기 위해서는 2700 이상을 입력해야 합니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle_rotation\":              \"<br>지정한 모터를 원하는 빠르기로 회전할 때 사용합니다. 1번 모터와 2번 모터는 역방향도 회전 가능하기 때문에 방향도 선택할 수 있습니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 자동차의 바퀴가 움직이기 위해서는 2700 이상을 입력해야 합니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_petrone_v2_drive_drone_value_attitude\":                    \"<br>자동차의 현재 자세를 각도로 반환합니다. Roll은 좌우 기울기(-90 ~ 90), Pitch는 앞뒤 기울기(-90 ~ 90), Yaw는 회전 각도(-180 ~ 180) 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#자동차</font> <font color='forestgreen'>#자세</font>\",\n                \"byrobot_petrone_v2_drive_drone_value_etc\":                         \"<br>페트론V2 설정과 관련된 값들과 적외선 통신으로 받은 값을 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#자동차</font> <font color='forestgreen'>#기타</font>\",\n                \"byrobot_petrone_v2_drive_drone_value_imu\":                         \"<br>페트론V2 IMU센서와 관련된 값들을 반환합니다.<br>(병진운동) 가속도는 x, y, z축에 대한 중력가속도입니다. 1g = 9.8m/s^2<br>(회전운동) 각속도는 x, y, z축을 기준으로 회전하는 속력을 나타내는 벡터입니다.(pitch, roll, yaw) <br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#IMU센서</font> <font color='crimson'>#가속도</font> <font color='dodgerblue'>#병진운동</font> <font color='crimson'>#각속도</font> <font color='dodgerblue'>#회전운동</font>\",\n                \"byrobot_petrone_v2_drive_drone_value_sensor\":                      \"<br>페트론V2 센서와 관련된 값들을 반환합니다.<br>온도 단위=섭씨 도, 해발고도 단위=m, image flow 단위=m, 바닥까지의 거리 단위=m<br>해발고도 값은 대기압의 영향을 받아서 오차범위가 큽니다. 바닥까지 거리의 유효 측정 거리는 2m입니다. image flow값은 일정한 속도와 높이에서 이동할 경우에 유효합니다. 이러한 센서값들을 이용하여 Petrone V2는 호버링(고도 유지) 기능을 수행합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#센서</font> <font color='crimson'>#온도</font> <font color='dodgerblue'>#해발고도</font> <font color='forestgreen'>#image flow</font> <font color='crimson'>#range</font> <font color='dodgerblue'>#대기압</font> <font color='forestgreen'>#호버링</font>\",\n            }\n        },\n\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_petrone_v2_common_left\":                       \"left\",\n                \"byrobot_petrone_v2_common_light_color_cottoncandy\":    \"cotton candy\",\n                \"byrobot_petrone_v2_common_light_color_emerald\":        \"emerald\",\n                \"byrobot_petrone_v2_common_light_color_lavender\":       \"lavender\",\n                \"byrobot_petrone_v2_common_light_mode_dimming\":         \"dimming\",\n                \"byrobot_petrone_v2_common_light_mode_flicker\":         \"flicker\",\n                \"byrobot_petrone_v2_common_light_mode_flicker_double\":  \"flicker double\",\n                \"byrobot_petrone_v2_common_light_mode_hold\":            \"hold\",\n                \"byrobot_petrone_v2_common_light_color_muscat\":         \"muscat\",\n                \"byrobot_petrone_v2_common_light_color_strawberrymilk\": \"strawberry milk\",\n                \"byrobot_petrone_v2_common_light_color_sunset\":         \"sunset\",\n                \"byrobot_petrone_v2_common_light_manual_all\":           \"all\",\n                \"byrobot_petrone_v2_common_light_manual_b100\":          \"brightness 100%\",\n                \"byrobot_petrone_v2_common_light_manual_b25\":           \"brightness 25%\",\n                \"byrobot_petrone_v2_common_light_manual_b50\":           \"brightness 50%\",\n                \"byrobot_petrone_v2_common_light_manual_b75\":           \"brightness 75%\",\n                \"byrobot_petrone_v2_common_light_manual_blue\":          \"blue\",\n                \"byrobot_petrone_v2_common_light_manual_cyan\":          \"cyan\",\n                \"byrobot_petrone_v2_common_light_manual_green\":         \"green\",\n                \"byrobot_petrone_v2_common_light_manual_magenta\":       \"magenta\",\n                \"byrobot_petrone_v2_common_light_manual_off\":           \"off\",\n                \"byrobot_petrone_v2_common_light_manual_on\":            \"on\",\n                \"byrobot_petrone_v2_common_light_manual_red\":           \"red\",\n                \"byrobot_petrone_v2_common_light_manual_white\":         \"white\",\n                \"byrobot_petrone_v2_common_light_manual_yellow\":        \"yellow\",\n                \"byrobot_petrone_v2_common_pitch\":      \"pitch\",\n                \"byrobot_petrone_v2_common_right\":      \"right\",\n                \"byrobot_petrone_v2_common_roll\":       \"roll\",\n                \"byrobot_petrone_v2_common_throttle\":   \"throttle\",\n                \"byrobot_petrone_v2_common_yaw\":        \"yaw\",\n                \"byrobot_petrone_v2_controller_button_bottom_left\":         \"left round button\",\n                \"byrobot_petrone_v2_controller_button_bottom_left_right\":   \"both round button\",\n                \"byrobot_petrone_v2_controller_button_bottom_right\":        \"right round button\",\n                \"byrobot_petrone_v2_controller_button_button\":              \"button\",\n                \"byrobot_petrone_v2_controller_button_center_down\":         \"trim-backward button\",\n                \"byrobot_petrone_v2_controller_button_center_left\":         \"trim-left button\",\n                \"byrobot_petrone_v2_controller_button_center_right\":        \"trim-right button\",\n                \"byrobot_petrone_v2_controller_button_center_up\":           \"trim-forward button\",\n                \"byrobot_petrone_v2_controller_button_center_up_left\":      \"trim-turn-left button\",\n                \"byrobot_petrone_v2_controller_button_center_up_right\":     \"trim-turn-right button\",\n                \"byrobot_petrone_v2_controller_button_event\":               \"button event\",\n                \"byrobot_petrone_v2_controller_button_front_left\":          \"left red button\",\n                \"byrobot_petrone_v2_controller_button_front_left_right\":    \"both red button\",\n                \"byrobot_petrone_v2_controller_button_front_right\":         \"right red button\",\n                \"byrobot_petrone_v2_controller_buzzer\":         \"buzzer\",\n                \"byrobot_petrone_v2_controller_buzzer_a\":       \"A\",\n                \"byrobot_petrone_v2_controller_buzzer_as\":      \"A#\",\n                \"byrobot_petrone_v2_controller_buzzer_b\":       \"B\",\n                \"byrobot_petrone_v2_controller_buzzer_c\":       \"C\",\n                \"byrobot_petrone_v2_controller_buzzer_cs\":      \"C#\",\n                \"byrobot_petrone_v2_controller_buzzer_d\":       \"D\",\n                \"byrobot_petrone_v2_controller_buzzer_ds\":      \"D#\",\n                \"byrobot_petrone_v2_controller_buzzer_e\":       \"E\",\n                \"byrobot_petrone_v2_controller_buzzer_f\":       \"F\",\n                \"byrobot_petrone_v2_controller_buzzer_fs\":      \"F#\",\n                \"byrobot_petrone_v2_controller_buzzer_g\":       \"G\",\n                \"byrobot_petrone_v2_controller_buzzer_gs\":      \"G#\",\n                \"byrobot_petrone_v2_controller_buzzer_mute\":    \"mute\",\n                \"byrobot_petrone_v2_controller_display_align_center\":           \"center\",\n                \"byrobot_petrone_v2_controller_display_align_left\":             \"left\",\n                \"byrobot_petrone_v2_controller_display_align_right\":            \"right\",\n                \"byrobot_petrone_v2_controller_display_flagfill_off\":           \"not fill\",\n                \"byrobot_petrone_v2_controller_display_flagfill_on\":            \"fill\",\n                \"byrobot_petrone_v2_controller_display_font_10x16\":             \"big\",\n                \"byrobot_petrone_v2_controller_display_font_5x8\":               \"small\",\n                \"byrobot_petrone_v2_controller_display_line_dashed\":            \"dashed\",\n                \"byrobot_petrone_v2_controller_display_line_dotted\":            \"dotted\",\n                \"byrobot_petrone_v2_controller_display_line_solid\":             \"solid\",\n                \"byrobot_petrone_v2_controller_display_pixel_black\":            \"black\",\n                \"byrobot_petrone_v2_controller_display_pixel_white\":            \"white\",\n                \"byrobot_petrone_v2_controller_joystick_direction_center\":      \"center\",\n                \"byrobot_petrone_v2_controller_joystick_direction_down\":        \"down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left\":        \"left\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_down\":   \"left down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_up\":     \"left up\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right\":       \"right\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_down\":  \"right down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_up\":    \"right up\",\n                \"byrobot_petrone_v2_controller_joystick_direction_up\":          \"up\",\n                \"byrobot_petrone_v2_controller_joystick_left_direction\":        \"left joystick direction\",\n                \"byrobot_petrone_v2_controller_joystick_left_event\":            \"left joystick event\",\n                \"byrobot_petrone_v2_controller_joystick_left_x\":                \"left joystick horizontal\",\n                \"byrobot_petrone_v2_controller_joystick_left_y\":                \"left joystick vertical\",\n                \"byrobot_petrone_v2_controller_joystick_right_direction\":       \"right joystick direction\",\n                \"byrobot_petrone_v2_controller_joystick_right_event\":           \"right joystick event\",\n                \"byrobot_petrone_v2_controller_joystick_right_x\":               \"right joystick horizontal\",\n                \"byrobot_petrone_v2_controller_joystick_right_y\":               \"right joystick vertical\",\n                \"byrobot_petrone_v2_entryhw_count_transfer_reserved\":           \"reserved data blocks\",\n            },\n\n            // en.js에 작성하던 내용\n            template: {\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz\": \"play %1 Hz sound %2\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz_delay\": \"play %1 Hz sound for %2 second %3\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_hz_reserve\": \"reserve to play %1 Hz sound for %2 second %3\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_off\": \"turn off the buzzer %1\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale\": \"play %1 octave %2 %3\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale_delay\": \"play %1 octave %2 for %3 second %4\",\n                \"byrobot_petrone_v2_drive_controller_buzzer_scale_reserve\": \"reserve to play %1 octave %2 for %3 second %4\",\n                \"byrobot_petrone_v2_drive_controller_display_clear\": \"clear controller display x:%1, y:%2, width:%3, height:%4, color:%5 %6\",\n                \"byrobot_petrone_v2_drive_controller_display_clear_all\": \"clear controller display with %1 color %2\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_circle\": \"draw a circle in controller display x:%1, y:%2, radius:%3, %4, %5, %6\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_line\": \"draw a line in controller display x1:%1, y1:%2, x2:%3, y2:%4, %5, %6 %7\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_point\": \"draw a point in controller display  x:%1, y:%2, color:%3 %4\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_rect\": \"draw a rectangle in controller display x:%1, y:%2, width:%3, height:%4, %5, %6, %7 %8\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_string\": \"draw a string in controller display x:%1, y:%2, font size:%3, %4, input:%5, %6\",\n                \"byrobot_petrone_v2_drive_controller_display_draw_string_align\": \"draw aligned string in controller display x1:%1, x2:%2, y:%3, align:%4, font size:%5, %6, input:%7, %8\",\n                \"byrobot_petrone_v2_drive_controller_display_invert\": \"invert controller display x:%1, y:%2, width:%3, height:%4 %5\",\n                \"byrobot_petrone_v2_drive_controller_if_button_press\": \"when press %1\",\n                \"byrobot_petrone_v2_drive_controller_if_joystick_direction\": \"when %1 stick move to %2\",\n                \"byrobot_petrone_v2_drive_controller_light_color_rgb_input\": \"decide the color values of controller LED R %1, G %2, B %3 %4 %5\",\n                \"byrobot_petrone_v2_drive_controller_light_color_rgb_select\": \"RGB combination examples of controller LED %1 %2 %3\",\n                \"byrobot_petrone_v2_drive_controller_light_color_preset\": \"change the state of %1 controller LED to %2 %3\",\n                \"byrobot_petrone_v2_drive_controller_light_manual_single_input\": \"change the brightness of %1 controller LED to %2 %3\",\n                \"byrobot_petrone_v2_drive_controller_light_manual_single_off\": \"turn off all controller LEDs %1\",\n                \"byrobot_petrone_v2_drive_controller_value_button\": \"%1\",\n                \"byrobot_petrone_v2_drive_controller_value_joystick\": \"%1\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_delay\": \"vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_off\": \"turn off the vibrator %1\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_on_delay\": \"turn on the vibrator for %1 second %2\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_on_reserve\": \"reserve turn on the vibrator for %1 second %2\",\n                \"byrobot_petrone_v2_drive_controller_vibrator_reserve\": \"reserve vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_petrone_v2_drive_drone_command_mode_vehicle_car\": \"Vehicle mode select %1 %2\",\n                \"byrobot_petrone_v2_drive_drone_control_car_stop\": \"stop %1\",\n                \"byrobot_petrone_v2_drive_drone_control_double\": \"set wheel to %1, forward/backward to %2 %3\",\n                \"byrobot_petrone_v2_drive_drone_control_double_delay\": \"set wheel to %1, forward/backward to %2 and run for %3 second %4\",\n                \"byrobot_petrone_v2_drive_drone_control_double_one\": \"set %1 to %2 %3\",\n                \"byrobot_petrone_v2_drive_drone_control_double_one_delay\": \"set %1 to %2 and run for %3 second %4\",\n                \"byrobot_petrone_v2_drive_drone_irmessage\": \"send %1 to the IR transmitter %2\",\n                \"byrobot_petrone_v2_drive_drone_light_color_rgb_input\": \"decide the color values of car %1 LED R %2, G %3, B %4 %5 %6\",\n                \"byrobot_petrone_v2_drive_drone_light_color_rgb_select\": \"RGB combination examples of car %1 LED %2 %3 %4\",\n                \"byrobot_petrone_v2_drive_drone_light_color_preset\": \"change the state of %1 car LED to %2 %3\",\n                \"byrobot_petrone_v2_drive_drone_light_manual_single_input\": \"change the brightness of %1 car LED to %2 %3\",\n                \"byrobot_petrone_v2_drive_drone_light_manual_single_off\": \"turn off all car LEDs %1\",\n                \"byrobot_petrone_v2_drive_drone_motor_stop\": \"turn off all motors %1\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle\": \"set rotate for number %1 motor to %2 %3\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle_input\": \"set rotate for number %1 motor to %2 %3\",\n                \"byrobot_petrone_v2_drive_drone_motorsingle_rotation\": \"set rotate for number %1 motor to %2 %3 %4\",\n                \"byrobot_petrone_v2_drive_drone_value_attitude\": \"%1\",\n                \"byrobot_petrone_v2_drive_drone_value_etc\": \"%1\",\n                \"byrobot_petrone_v2_drive_drone_value_imu\": \"%1\",\n                \"byrobot_petrone_v2_drive_drone_value_sensor\": \"%1\",\n            },\n            \n            Helper: {\n\n            }\n        }\n    }\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.byrobot_petrone_v2_drive.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/byrobot_petrone_v2_drive.png\",      // 배경 이미지\n        width: 256,     // 이미지의 폭\n        height: 256,    // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeVehicle:              {name: Lang.Blocks.byrobot_petrone_v2_drone_state_mode_vehicle,             type: 'input',  pos: { x: 0, y: 0 }},\n            state_modeDrive:                {name: Lang.Blocks.byrobot_petrone_v2_drone_state_mode_drive,               type: 'input',  pos: { x: 0, y: 0 }},\n            state_battery:                  {name: Lang.Blocks.byrobot_petrone_v2_drone_state_battery,                  type: 'input',  pos: { x: 0, y: 0 }},\n            imu_angleRoll:                  {name: Lang.Blocks.byrobot_petrone_v2_drone_attitude_roll,                  type: 'input',  pos: { x: 0, y: 0 }},\n            imu_anglePitch:                 {name: Lang.Blocks.byrobot_petrone_v2_drone_attitude_pitch,                 type: 'input',  pos: { x: 0, y: 0 }},\n            imu_angleYaw:                   {name: Lang.Blocks.byrobot_petrone_v2_drone_attitude_yaw,                   type: 'input',  pos: { x: 0, y: 0 }},\n            imu_accX:                       {name: Lang.Blocks.byrobot_petrone_v2_drone_accel_x,                        type: 'input',  pos: { x: 0, y: 0 }},\n            imu_accY:                       {name: Lang.Blocks.byrobot_petrone_v2_drone_accel_y,                        type: 'input',  pos: { x: 0, y: 0 }},\n            imu_accZ:                       {name: Lang.Blocks.byrobot_petrone_v2_drone_accel_z,                        type: 'input',  pos: { x: 0, y: 0 }},\n            imu_gyroRoll:                   {name: Lang.Blocks.byrobot_petrone_v2_drone_gyro_roll,                      type: 'input',  pos: { x: 0, y: 0 }},\n            imu_gyroPitch:                  {name: Lang.Blocks.byrobot_petrone_v2_drone_gyro_pitch,                     type: 'input',  pos: { x: 0, y: 0 }},\n            imu_gyroYaw:                    {name: Lang.Blocks.byrobot_petrone_v2_drone_gyro_yaw,                       type: 'input',  pos: { x: 0, y: 0 }},\n            pressure_temperature:           {name: Lang.Blocks.byrobot_petrone_v2_drone_pressure_temperature,           type: 'input',  pos: { x: 0, y: 0 }},\n            pressure_pressure:              {name: Lang.Blocks.byrobot_petrone_v2_drone_pressure_pressure,              type: 'input',  pos: { x: 0, y: 0 }},\n            imageflow_positionX:            {name: Lang.Blocks.byrobot_petrone_v2_drone_imageflow_positionX,            type: 'input',  pos: { x: 0, y: 0 }},\n            imageflow_positionY:            {name: Lang.Blocks.byrobot_petrone_v2_drone_imageflow_positionY,            type: 'input',  pos: { x: 0, y: 0 }},\n            range_bottom:                   {name: Lang.Blocks.byrobot_petrone_v2_drone_range_bottom,                   type: 'input',  pos: { x: 0, y: 0 }},\n            irmessage_direction:            {name: Lang.Blocks.byrobot_petrone_v2_drone_irmessage_direction,            type: 'input',  pos: { x: 0, y: 0 }},\n            irmessage_irdata:               {name: Lang.Blocks.byrobot_petrone_v2_drone_irmessage,                      type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_x:                {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_x,           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_y:                {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_y,           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_direction:        {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_direction,   type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_event:            {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_event,       type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_x:               {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_x,          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_y:               {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_y,          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_direction:       {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_direction,  type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_event:           {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_event,      type: 'input',  pos: { x: 0, y: 0 }},\n            button_button:                  {name: Lang.Blocks.byrobot_petrone_v2_controller_button_button,             type: 'input',  pos: { x: 0, y: 0 }},\n            button_event:                   {name: Lang.Blocks.byrobot_petrone_v2_controller_button_event,              type: 'input',  pos: { x: 0, y: 0 }},\n            entryhw_countTransferReserved:  {name: Lang.Blocks.byrobot_petrone_v2_entryhw_count_transfer_reserved,      type: 'output', pos: { x: 0, y: 0 }},\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both', // 표시 모드\n    };\n};\n\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 이름\n ***************************************************************************************/\nEntry.byrobot_petrone_v2_drive.blockMenuBlocks = [\n    'byrobot_petrone_v2_drive_drone_value_attitude',\n    'byrobot_petrone_v2_drive_drone_value_imu',\n    'byrobot_petrone_v2_drive_drone_value_sensor',\n    'byrobot_petrone_v2_drive_drone_value_etc',\n    'byrobot_petrone_v2_drive_controller_value_button',\n    'byrobot_petrone_v2_drive_controller_value_joystick',\n    'byrobot_petrone_v2_drive_controller_if_button_press',\n    'byrobot_petrone_v2_drive_controller_if_joystick_direction',\n    'byrobot_petrone_v2_drive_drone_command_mode_vehicle_car',\n    'byrobot_petrone_v2_drive_drone_control_car_stop',\n    'byrobot_petrone_v2_drive_drone_control_double_one',\n    'byrobot_petrone_v2_drive_drone_control_double_one_delay',\n    'byrobot_petrone_v2_drive_drone_control_double',\n    'byrobot_petrone_v2_drive_drone_control_double_delay',\n    'byrobot_petrone_v2_drive_drone_motor_stop',\n    'byrobot_petrone_v2_drive_drone_motorsingle',\n    'byrobot_petrone_v2_drive_drone_motorsingle_input',\n    'byrobot_petrone_v2_drive_drone_motorsingle_rotation',\n    'byrobot_petrone_v2_drive_drone_irmessage',\n    'byrobot_petrone_v2_drive_drone_light_manual_single_off',\n    'byrobot_petrone_v2_drive_drone_light_manual_single_input',\n    'byrobot_petrone_v2_drive_drone_light_color_preset',\n    'byrobot_petrone_v2_drive_drone_light_color_input',\n    'byrobot_petrone_v2_drive_drone_light_color_select',\n    'byrobot_petrone_v2_drive_controller_light_manual_single_off',\n    'byrobot_petrone_v2_drive_controller_light_manual_single_input',\n    'byrobot_petrone_v2_drive_controller_light_color_preset',\n    'byrobot_petrone_v2_drive_controller_light_color_input',\n    'byrobot_petrone_v2_drive_controller_light_color_select',\n    'byrobot_petrone_v2_drive_controller_display_clear_all',\n    'byrobot_petrone_v2_drive_controller_display_clear',\n    'byrobot_petrone_v2_drive_controller_display_invert',\n    'byrobot_petrone_v2_drive_controller_display_draw_point',\n    'byrobot_petrone_v2_drive_controller_display_draw_line',\n    'byrobot_petrone_v2_drive_controller_display_draw_rect',\n    'byrobot_petrone_v2_drive_controller_display_draw_circle',\n    'byrobot_petrone_v2_drive_controller_display_draw_string',\n    'byrobot_petrone_v2_drive_controller_display_draw_string_align',\n    'byrobot_petrone_v2_drive_controller_buzzer_off',\n    'byrobot_petrone_v2_drive_controller_buzzer_scale',\n    'byrobot_petrone_v2_drive_controller_buzzer_scale_delay',\n    'byrobot_petrone_v2_drive_controller_buzzer_scale_reserve',\n    'byrobot_petrone_v2_drive_controller_buzzer_hz',\n    'byrobot_petrone_v2_drive_controller_buzzer_hz_delay',\n    'byrobot_petrone_v2_drive_controller_buzzer_hz_reserve',\n    'byrobot_petrone_v2_drive_controller_vibrator_off',\n    'byrobot_petrone_v2_drive_controller_vibrator_on_delay',\n    'byrobot_petrone_v2_drive_controller_vibrator_on_reserve',\n    'byrobot_petrone_v2_drive_controller_vibrator_delay',\n    'byrobot_petrone_v2_drive_controller_vibrator_reserve',\n];\n\n\n\n/***************************************************************************************\n *  엔트리 블록 상세\n ***************************************************************************************/\nEntry.byrobot_petrone_v2_drive.getBlocks = function()\n{\n    return {\n        //region byrobot 바이로봇\n        /* BYROBOT PetroneV2 Drive Start */\n        byrobot_petrone_v2_drive_drone_value_attitude:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_attitude_roll,    'imu_angleRoll'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_attitude_pitch,   'imu_anglePitch'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_attitude_yaw,     'imu_angleYaw'],\n                    ],\n                    value: 'imu_angleRoll', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_drone_value_attitude', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_value_imu:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_accel_x,      'imu_accX'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_accel_y,      'imu_accY'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_accel_z,      'imu_accZ'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_gyro_roll,    'imu_gyroRoll'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_gyro_pitch,   'imu_gyroPitch'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_gyro_yaw,     'imu_gyroYaw'],\n                    ],\n                    value: 'imu_accX', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_drone_value_imu', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_value_sensor:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_pressure_temperature, 'pressure_temperature'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_pressure_pressure,    'pressure_pressure'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_imageflow_positionX,  'imageflow_positionX'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_imageflow_positionY,  'imageflow_positionY'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_range_bottom,         'range_bottom'],\n                    ],\n                    value: 'pressure_temperature', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_drone_value_sensor', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_value_etc:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_state_mode_vehicle,   'state_modeVehicle'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_state_mode_drive,     'state_modeDrive'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_state_battery,        'state_battery'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_irmessage,            'irmessage_irdata'],\n                    ],\n                    value: 'irmessage_irdata', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_drone_value_etc', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_value_button:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_button,   'button_button'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_event,    'button_event'],\n                    ],\n                    value: 'button_button', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_controller_value_button', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_value_joystick:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_x,             'joystick_left_x'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_y,             'joystick_left_y'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_direction,     'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_event,         'joystick_left_event'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_x,            'joystick_right_x'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_y,            'joystick_right_y'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_direction,    'joystick_right_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_event,        'joystick_right_event'],\n                    ],\n                    value: 'joystick_left_x', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_controller_value_joystick', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_if_button_press:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_left,        '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_right,       '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_left_right,  '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up_left,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up_right,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up,         '16'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_left,       '32'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_right,      '64'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_down,       '128'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_left,       '256'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_right,      '512'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_left_right, '768'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_boolean_input',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var button = 'button_button'; // paramsKeyMap에 정의된 이름 사용\n                var buttonevent = 'button_event'; // paramsKeyMap에 정의된 이름 사용\n\n                if (\n                    read[button] == script.getField('BUTTON') &&\n                    read[buttonevent] == 2\n                )\n                    return true;\n                else return false;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_if_joystick_direction:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_right, 'joystick_right_direction'],\n                    ],\n                    value: 'joystick_left_direction',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left_up,      '17'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_up,           '18'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right_up,     '20'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left,         '33'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_center,       '34'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right,        '36'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left_down,    '65'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_down,         '66'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right_down,   '68'],\n                    ],\n                    value: '34',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_drive_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                DIRECTION: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_boolean_input',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION')) return true;\n                else return false;\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_light_manual_single_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_drive_controller_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x31, 0xff, 0);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_light_color_preset:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_red,        'red'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_green,      'green'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_blue,       'blue'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_yellow,     'yellow'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_magenta,    'magenta'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_cyan,       'cyan'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_white,      'white'],\n                    ],\n                    value: 'red',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_on,     '220'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b25,    '75'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b50,    '125'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b75,    '200'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b100,   '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_petrone_v2_drive_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var mode = 0x12;\n                var interval = parseInt(script.getField('BRIGHTNESS'));\n                var select = script.getField('FLAGS');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'red':     red = 255;  green = 0;    blue = 0;     break;\n                    case 'green':   red = 0;    green = 255;  blue = 0;     break;\n                    case 'blue':    red = 0;    green = 0;    blue = 255;   break;\n                    case 'cyan':    red = 0;    green = 255;  blue = 255;   break;\n                    case 'magenta': red = 255;  green = 0;    blue = 255;   break;\n                    case 'yellow':  red = 255;  green = 255;  blue = 0;     break;\n                    case 'white':   red = 255;  green = 255;  blue = 255;   break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_light_manual_single_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0xFF']},\n                    {type: 'text', params: ['255']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x31, flags, brightness);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_light_color_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'],   // TeamHold             = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'],   // TeamFlicker          = 0x13\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'],   // TeamFlickerDouble    = 0x14\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'],   // TeamDimming          = 0x15\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    null,\n                    {type: 'text', params: ['500']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_light_color_input',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n                MODE: 3,\n                INTERVAL: 4,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var mode = 0x12 + parseInt(script.getField('MODE'));\n                var interval = script.getNumberValue('INTERVAL');\n                var red = script.getNumberValue('RED');\n                var green = script.getNumberValue('GREEN');\n                var blue = script.getNumberValue('BLUE');\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_light_color_select:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_sunset,          'sunset'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_cottoncandy,     'cottonCandy'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_muscat,          'muscat'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_strawberrymilk,  'strawberryMilk'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_emerald,         'emerald'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_lavender,        'lavender'],\n                    ],\n                    value: 'sunset',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'], // TeamHold           = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'], // TeamFlicker        = 0x13\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'], // TeamFlickerDouble  = 0x14\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'], // TeamDimming        = 0x15\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['500']},\n                    null\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_light_color_select',\n            },\n            paramsKeyMap: {\n                SELECT: 0,\n                MODE: 1,\n                INTERVAL: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var mode = 0x12 + parseInt(script.getField('MODE'));\n                var interval = script.getNumberValue('INTERVAL');\n                var select = script.getField('SELECT');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'sunset':          red = 255;  green = 100;    blue = 0;   break;\n                    case 'cottonCandy':     red = 20;   green = 250;    blue = 150; break;\n                    case 'muscat':          red = 70;   green = 255;    blue = 0;   break;\n                    case 'strawberryMilk':  red = 150;  green = 60;     blue = 20;  break;\n                    case 'emerald':         red = 0;    green = 255;    blue = 30;  break;\n                    case 'lavender':        red = 80;   green = 0;      blue = 200; break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_light_manual_single_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_drive_drone_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x30, 0xff, 0);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_light_color_preset:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_eye_red,     'eye_red'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_eye_green,   'eye_green'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_eye_blue,    'eye_blue'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_arm_red,     'arm_red'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_arm_green,   'arm_green'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_arm_blue,    'arm_blue'],\n                    ],\n                    value: 'eye_red',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_on,     '220'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b25,    '75'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b50,    '125'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b75,    '200'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b100,   '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_petrone_v2_drive_drone_light_color_preset',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_drone_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var mode = 0x12;\n                var interval = parseInt(script.getField('BRIGHTNESS'));\n                var select = script.getField('FLAGS');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'eye_red':     mode = 0x12;    red = 255;  green = 0;    blue = 0;     break;\n                    case 'eye_green':   mode = 0x12;    red = 0;    green = 255;  blue = 0;     break;\n                    case 'eye_blue':    mode = 0x12;    red = 0;    green = 0;    blue = 255;   break;\n                    case 'arm_red':     mode = 0x42;    red = 255;  green = 0;    blue = 0;     break;\n                    case 'arm_green':   mode = 0x42;    red = 0;    green = 255;  blue = 0;     break;\n                    case 'arm_blue':    mode = 0x42;    red = 0;    green = 0;    blue = 255;   break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x30, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_light_manual_single_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0xFF']},\n                    {type: 'text', params: ['255']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_drone_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x30, flags, brightness);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_light_color_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_color_eye, '18'], // EyeHold = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_color_arm, '66'], // ArmHold = 0x42\n                    ],\n                    value: '18',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'], // EyeHold = 0x12,          // ArmHold = 0x42\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'], // EyeFlicker = 0x13,       // ArmFlicker = 0x43\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'], // EyeFlickerDouble = 0x14, // ArmFlickerDouble = 0x44\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'], // EyeDimming = 0x15,       // ArmDimming = 0x45\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    null,\n                    {type: 'text', params: ['500']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_light_color_input',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n                MODESUB: 4,\n                INTERVAL: 5,\n            },\n            class: 'byrobot_petrone_v2_drive_drone_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var mode = parseInt(script.getField('MODE')) + parseInt(script.getField('MODESUB'));\n                var red = script.getNumberValue('RED');\n                var green = script.getNumberValue('GREEN');\n                var blue = script.getNumberValue('BLUE');\n                var interval = script.getNumberValue('INTERVAL');\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x30, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_light_color_select:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_color_eye, '18'], // EyeHold = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_color_arm, '66'], // ArmHold = 0x42\n                    ],\n                    value: '18',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_sunset,          'sunset'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_cottoncandy,     'cottonCandy'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_muscat,          'muscat'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_strawberrymilk,  'strawberryMilk'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_emerald,         'emerald'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_lavender,        'lavender'],\n                    ],\n                    value: 'sunset',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'], // EyeHold = 0x12,          // ArmHold = 0x42\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'], // EyeFlicker = 0x13,       // ArmFlicker = 0x43\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'], // EyeFlickerDouble = 0x14, // ArmFlickerDouble = 0x44\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'], // EyeDimming = 0x15,       // ArmDimming = 0x45\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {type: 'text', params: ['500']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_light_color_select',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n                SELECT: 1,\n                MODESUB: 2,\n                INTERVAL: 3,\n            },\n            class: 'byrobot_petrone_v2_drive_drone_light',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var mode = parseInt(script.getField('MODE')) + parseInt(script.getField('MODESUB'));\n                var interval = script.getNumberValue('INTERVAL');\n                var select = script.getField('SELECT');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'sunset':          red = 255;  green = 100;    blue = 0;   break;\n                    case 'cottonCandy':     red = 20;   green = 250;    blue = 150; break;\n                    case 'muscat':          red = 70;   green = 255;    blue = 0;   break;\n                    case 'strawberryMilk':  red = 150;  green = 60;     blue = 20;  break;\n                    case 'emerald':         red = 0;    green = 255;    blue = 30;  break;\n                    case 'lavender':        red = 80;   green = 0;      blue = 200; break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x30, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_clear_all:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_drive_controller_display_clear_all',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayClearAll(script, 0x31, pixel);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_clear:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_display_clear',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n                PIXEL: 4,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayClear(script, 0x31, pixel, false, x, y, width, height);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_invert:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_display_invert',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                return Entry.byrobot_petrone_v2_base.setDisplayInvert(script, 0x31, x, y, width, height);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_draw_point:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_display_draw_point',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                PIXEL: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawPoint(script, 0x31, x, y, pixel);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_draw_line:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_solid,  '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dotted, '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dashed, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    {type: 'text', params: ['96']},\n                    {type: 'text', params: ['48']},\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_display_draw_line',\n            },\n            paramsKeyMap: {\n                X1: 0,\n                Y1: 1,\n                X2: 2,\n                Y2: 3,\n                PIXEL: 4,\n                LINE: 5,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var x1 = script.getNumberValue('X1');\n                var y1 = script.getNumberValue('Y1');\n                var x2 = script.getNumberValue('X2');\n                var y2 = script.getNumberValue('Y2');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var line = parseInt(script.getField('LINE'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawLine(script, 0x31, x1, y1, x2, y2, pixel, line);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_draw_rect:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_on,     '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_solid,  '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dotted, '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dashed, '2'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_display_draw_rect',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n                PIXEL: 4,\n                FLAGFILL: 5,\n                LINE: 6,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var flagFill = parseInt(script.getField('FLAGFILL'));\n                var line = parseInt(script.getField('LINE'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawRect(script, 0x31, x, y, width, height, pixel, flagFill, line);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_draw_circle:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_on,     '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_display_draw_circle',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                RADIUS: 2,\n                PIXEL: 3,\n                FLAGFILL: 4,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var radius = script.getNumberValue('RADIUS');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var flagFill = parseInt(script.getField('FLAGFILL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawCircle(script, 0x31, x, y, radius, pixel, flagFill);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_draw_string:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_5x8,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_10x16,  '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['4']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    {type: 'text', params: ['{Petrone V2}']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_display_draw_string',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                FONT: 2,\n                PIXEL: 3,\n                STRING: 4,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var font = parseInt(script.getField('FONT'));\n                var pixel = parseInt(script.getField('PIXEL'));\n                var string = script.getStringValue('STRING');\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawString(script, 0x31, x, y, font, pixel, string);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_display_draw_string_align:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_left,      '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_center,    '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_right,     '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_5x8,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_10x16,  '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0']},\n                    {type: 'text', params: ['128']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    null,\n                    {type: 'text', params: ['BYROBOT & U']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_display_draw_string_align',\n            },\n            paramsKeyMap: {\n                XSTART: 0,\n                XEND: 1,\n                Y: 2,\n                ALIGN: 3,\n                FONT: 4,\n                PIXEL: 5,\n                STRING: 6,\n            },\n            class: 'byrobot_petrone_v2_drive_controller_display',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var xStart = script.getNumberValue('XSTART');\n                var xEnd = script.getNumberValue('XEND');\n                var y = script.getNumberValue('Y');\n                var align = parseInt(script.getField('ALIGN'));\n                var font = parseInt(script.getField('FONT'));\n                var pixel = parseInt(script.getField('PIXEL'));\n                var string = script.getStringValue('STRING');\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawStringAlign(script, 0x31, xStart, xEnd, y, align, font, pixel, string);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_buzzer_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_drive_buzzer',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setBuzzerStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_buzzer_scale:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_petrone_v2_drive_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_buzzer',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, 60000, false, true);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, 60000, false, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_buzzer_scale_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_buzzer',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, time, true, true);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, time, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_buzzer_scale_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_buzzer',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, time, false, false);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, time, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_buzzer_hz:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_buzzer',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, 60000, false, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_buzzer_hz_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_buzzer',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, time, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_buzzer_hz_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_buzzer',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, time, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_vibrator_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_drive_vibrator',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setVibratorStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_vibrator_on_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_vibrator',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, 0, timeOn, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_vibrator_on_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_vibrator',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, 0, timeOn, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_vibrator_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0.02']},\n                    {type: 'text', params: ['0.2']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_vibrator',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, timeOff, timeRun, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_controller_vibrator_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0.02']},\n                    {type: 'text', params: ['0.2']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_vibrator',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, timeOff, timeRun, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_irmessage:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_irmessage',\n            },\n            paramsKeyMap: {\n                IRMESSAGE: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_irmessage',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var irdirection = 0;\n                var irmessage = script.getNumberValue('IRMESSAGE', script);\n                return Entry.byrobot_petrone_v2_base.sendIrMessage(script, irdirection, irmessage);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_motor_stop:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_drive_motor',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.sendStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_motorsingle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1'], ['3', '2'], ['4', '3']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'text', params: ['3000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_motorsingle',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_motor',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var motorIndex = parseInt(script.getField('MOTORINDEX'));\n                var motorRotation = motorIndex % 2 + 1;\n                var motorSpeed = parseInt(\n                    script.getNumberValue('MOTORSPEED', script)\n                );\n\n                return Entry.byrobot_petrone_v2_base.setMotorSingle(script, motorIndex, motorRotation, motorSpeed);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_motorsingle_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1']},\n                    {type: 'text', params: ['3000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_motorsingle_input',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_motor',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var motorIndex =\n                    parseInt(script.getNumberValue('MOTORINDEX', script)) - 1;\n                var motorRotation = motorIndex % 2 + 1;\n                var motorSpeed = parseInt(\n                    script.getNumberValue('MOTORSPEED', script)\n                );\n\n                return Entry.byrobot_petrone_v2_base.setMotorSingle(script, motorIndex, motorRotation, motorSpeed);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_motorsingle_rotation:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_motor_rotation_clockwise,         '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_motor_rotation_counterclockwise,  '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['3000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_motorsingle_rotation',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORROTATION: 1,\n                MOTORSPEED: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_motor',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var motorIndex = parseInt(script.getField('MOTORINDEX'));\n                var motorRotation = parseInt(script.getField('MOTORROTATION'));\n                var motorSpeed = parseInt(\n                    script.getNumberValue('MOTORSPEED', script)\n                );\n\n                return Entry.byrobot_petrone_v2_base.setMotorSingle(script, motorIndex, motorRotation, motorSpeed);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_command_mode_vehicle_car:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_vehicle_drive,        '32'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_vehicle_drive_fpv,    '33'],\n                    ],\n                    value: '32',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_drive_drone_command_mode_vehicle_car',\n            },\n            paramsKeyMap: {\n                VEHICLE: 0,\n            },\n            class: 'byrobot_petrone_v2_drive_control_drive',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var vehicle = script.getField('VEHICLE');\n                return Entry.byrobot_petrone_v2_base.setModeVehicle(script, vehicle);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_control_car_stop:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_drive_drone_control_car_stop',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_drive_control_drive',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.sendStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_control_double_one:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_double_wheel,         'control_wheel'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_double_accel_forward, 'control_accel'],\n                    ],\n                    value: 'control_accel',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'number', params: ['0']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_control_double_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_control_drive',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var controlTarget = script.getField('CONTROLTARGET');\n                var value = parseInt(script.getNumberValue('VALUE', script));\n\n                return Entry.byrobot_petrone_v2_base.sendControlDoubleSingle(script, controlTarget, value, 0, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_control_double_one_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_double_wheel,         'control_wheel'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_double_accel_forward, 'control_accel'],\n                    ],\n                    value: 'control_accel',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'number', params: ['100']},\n                    {type: 'number', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_control_double_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_control_drive',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var controlTarget = script.getField('CONTROLTARGET');\n                var value = parseInt(script.getNumberValue('VALUE', script));\n                var time = parseInt(\n                    script.getNumberValue('TIME', script) * 1000\n                );\n\n                return Entry.byrobot_petrone_v2_base.sendControlDoubleSingle(script, controlTarget, value, time, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_control_double:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['0']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_control_double',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                ACCEL: 1,\n            },\n            class: 'byrobot_petrone_v2_drive_control_drive',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var wheel = parseInt(script.getNumberValue('WHEEL', script));\n                var accel = parseInt(script.getNumberValue('ACCEL', script));\n\n                return Entry.byrobot_petrone_v2_base.sendControlDouble(script, wheel, accel, 0, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_drive_drone_control_double_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_drive_drone_control_double_delay',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                ACCEL: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_drive_control_drive',\n            isNotFor: ['byrobot_petrone_v2_drive'],\n            func: function(sprite, script) {\n                var wheel = parseInt(script.getNumberValue('WHEEL', script));\n                var accel = parseInt(script.getNumberValue('ACCEL', script));\n                var time = parseInt(\n                    script.getNumberValue('TIME', script) * 1000\n                );\n\n                return Entry.byrobot_petrone_v2_base.sendControlDouble(script, wheel, accel, time, true);\n            },\n        },\n        /* BYROBOT PetroneV2 Drive End */\n        //endregion byrobot 바이로봇\n    };\n};\n\n\nmodule.exports = Entry.byrobot_petrone_v2_drive;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_byrobot_petrone_v2_flight.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n\n'use strict';\n\n/***************************************************************************************\n *\n *  이름 붙이기 규칙(2017.1.16)\n *\n *  1. 변수에 해당하는 이름들은 모두 소문자\n *  2. 이어지는 추가 이름은 '_'를 붙여서 연결\n *\n ***************************************************************************************/\n\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.byrobot_petrone_v2_flight =\n{\n    id: 'F.6',\n    name: 'byrobot_petrone_v2_flight',\n    url: 'http://www.byrobot.co.kr/',\n    imageName: 'byrobot_petrone_v2_flight.png',\n    title: {\n        \"en\": \"BYROBOT Petrone V2 flight\",\n        \"ko\": \"바이로봇 페트론V2 드론\"\n    },\n\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero: function()\n    {\n        // 초기화\n        Entry.byrobot_petrone_v2_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            Entry.byrobot_petrone_v2_base.transferCommand(0x30, 0x24, 0);       // 드론, command = 0x24 (Stop)\n            Entry.byrobot_petrone_v2_base.transferVibrator(0, 0, 0, 0);\n            Entry.byrobot_petrone_v2_base.transferBuzzer(0, 0, 0);\n            Entry.byrobot_petrone_v2_base.transferLightManual(0x30, 0xff, 0);   // LED 초기화(모두 꺼짐)\n            Entry.byrobot_petrone_v2_base.transferLightManual(0x31, 0xff, 0);   // LED 초기화(모두 꺼짐)\n            Entry.byrobot_petrone_v2_base.transferLightModeColor(0x30, 0x12, 200, 255, 0, 0); // LED 초기화(눈 빨강)\n            Entry.byrobot_petrone_v2_base.transferLightModeColor(0x30, 0x42, 200, 255, 0, 0); // LED 초기화(팔 빨강)\n            Entry.byrobot_petrone_v2_base.transferMotorSingle(0, 1, 0);         // 1번 모터방향 초기화(시계방향)\n            Entry.byrobot_petrone_v2_base.transferMotorSingle(1, 2, 0);         // 2번 모터방향 초기화(반시계방향)\n        }\n    },\n};\n\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.byrobot_petrone_v2_flight.setLanguage = function ()\n{\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_petrone_v2_common_left\":                       \"왼쪽\",\n                \"byrobot_petrone_v2_common_light_color_cottoncandy\":    \"구름솜사탕\",\n                \"byrobot_petrone_v2_common_light_color_emerald\":        \"에메랄드\",\n                \"byrobot_petrone_v2_common_light_color_lavender\":       \"라벤더\",\n                \"byrobot_petrone_v2_common_light_mode_dimming\":         \"천천히 깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_flicker\":         \"깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_flicker_double\":  \"2번 연속 깜빡임\",\n                \"byrobot_petrone_v2_common_light_mode_hold\":            \"켜짐\",\n                \"byrobot_petrone_v2_common_light_color_muscat\":         \"청포도\",\n                \"byrobot_petrone_v2_common_light_color_strawberrymilk\": \"딸기우유\",\n                \"byrobot_petrone_v2_common_light_color_sunset\":         \"저녁노을\",\n                \"byrobot_petrone_v2_common_light_manual_all\":           \"전체\",\n                \"byrobot_petrone_v2_common_light_manual_b100\":          \"밝기 100%\",\n                \"byrobot_petrone_v2_common_light_manual_b25\":           \"밝기 25%\",\n                \"byrobot_petrone_v2_common_light_manual_b50\":           \"밝기 50%\",\n                \"byrobot_petrone_v2_common_light_manual_b75\":           \"밝기 75%\",\n                \"byrobot_petrone_v2_common_light_manual_blue\":          \"파랑\",\n                \"byrobot_petrone_v2_common_light_manual_cyan\":          \"하늘색\",\n                \"byrobot_petrone_v2_common_light_manual_green\":         \"초록\",\n                \"byrobot_petrone_v2_common_light_manual_magenta\":       \"핑크\",\n                \"byrobot_petrone_v2_common_light_manual_off\":           \"끄기\",\n                \"byrobot_petrone_v2_common_light_manual_on\":            \"켜기\",\n                \"byrobot_petrone_v2_common_light_manual_red\":           \"빨강\",\n                \"byrobot_petrone_v2_common_light_manual_white\":         \"흰색\",\n                \"byrobot_petrone_v2_common_light_manual_yellow\":        \"노랑\",\n                \"byrobot_petrone_v2_common_pitch\":                      \"Pitch\",\n                \"byrobot_petrone_v2_common_right\":                      \"오른쪽\",\n                \"byrobot_petrone_v2_common_roll\":                       \"Roll\",\n                \"byrobot_petrone_v2_common_throttle\":                   \"Throttle\",\n                \"byrobot_petrone_v2_common_yaw\":                        \"Yaw\",\n                \"byrobot_petrone_v2_controller_button_bottom_left\":         \"왼쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_bottom_left_right\":   \"양쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_bottom_right\":        \"오른쪽 둥근 버튼\",\n                \"byrobot_petrone_v2_controller_button_button\":              \"버튼\",\n                \"byrobot_petrone_v2_controller_button_center_down\":         \"트림 뒤 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_left\":         \"트림 왼쪽 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_right\":        \"트림 오른쪽 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up\":           \"트림 앞 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up_left\":      \"트림 좌회전 버튼\",\n                \"byrobot_petrone_v2_controller_button_center_up_right\":     \"트림 우회전 버튼\",\n                \"byrobot_petrone_v2_controller_button_event\":               \"버튼 이벤트\",\n                \"byrobot_petrone_v2_controller_button_front_left\":          \"왼쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_button_front_left_right\":    \"양쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_button_front_right\":         \"오른쪽 빨간 버튼\",\n                \"byrobot_petrone_v2_controller_buzzer\":         \"버저\",\n                \"byrobot_petrone_v2_controller_buzzer_a\":       \"라\",\n                \"byrobot_petrone_v2_controller_buzzer_as\":      \"라#\",\n                \"byrobot_petrone_v2_controller_buzzer_b\":       \"시\",\n                \"byrobot_petrone_v2_controller_buzzer_c\":       \"도\",\n                \"byrobot_petrone_v2_controller_buzzer_cs\":      \"도#\",\n                \"byrobot_petrone_v2_controller_buzzer_d\":       \"레\",\n                \"byrobot_petrone_v2_controller_buzzer_ds\":      \"레#\",\n                \"byrobot_petrone_v2_controller_buzzer_e\":       \"미\",\n                \"byrobot_petrone_v2_controller_buzzer_f\":       \"파\",\n                \"byrobot_petrone_v2_controller_buzzer_fs\":      \"파#\",\n                \"byrobot_petrone_v2_controller_buzzer_g\":       \"솔\",\n                \"byrobot_petrone_v2_controller_buzzer_gs\":      \"솔#\",\n                \"byrobot_petrone_v2_controller_buzzer_mute\":    \"쉼\",\n                \"byrobot_petrone_v2_controller_display_align_center\":   \"가운데\",\n                \"byrobot_petrone_v2_controller_display_align_left\":     \"왼쪽\",\n                \"byrobot_petrone_v2_controller_display_align_right\":    \"오른쪽\",\n                \"byrobot_petrone_v2_controller_display_flagfill_off\":   \"채우지 않음\",\n                \"byrobot_petrone_v2_controller_display_flagfill_on\":    \"채움\",\n                \"byrobot_petrone_v2_controller_display_font_10x16\":     \"큼\",\n                \"byrobot_petrone_v2_controller_display_font_5x8\":       \"작음\",\n                \"byrobot_petrone_v2_controller_display_line_dashed\":    \"파선\",\n                \"byrobot_petrone_v2_controller_display_line_dotted\":    \"점선\",\n                \"byrobot_petrone_v2_controller_display_line_solid\":     \"실선\",\n                \"byrobot_petrone_v2_controller_display_pixel_black\":    \"검은색\",\n                \"byrobot_petrone_v2_controller_display_pixel_white\":    \"흰색\",\n                \"byrobot_petrone_v2_controller_joystick_direction_center\":      \"중앙\",\n                \"byrobot_petrone_v2_controller_joystick_direction_down\":        \"아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left\":        \"왼쪽\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_down\":   \"왼쪽 아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_up\":     \"왼쪽 위\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right\":       \"오른쪽\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_down\":  \"오른쪽 아래\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_up\":    \"오른쪽 위\",\n                \"byrobot_petrone_v2_controller_joystick_direction_up\":          \"위\",\n                \"byrobot_petrone_v2_controller_joystick_left_direction\":        \"왼쪽 조이스틱 방향\",\n                \"byrobot_petrone_v2_controller_joystick_left_event\":            \"왼쪽 조이스틱 이벤트\",\n                \"byrobot_petrone_v2_controller_joystick_left_x\":                \"왼쪽 조이스틱 가로축\",\n                \"byrobot_petrone_v2_controller_joystick_left_y\":                \"왼쪽 조이스틱 세로축\",\n                \"byrobot_petrone_v2_controller_joystick_right_direction\":       \"오른쪽 조이스틱 방향\",\n                \"byrobot_petrone_v2_controller_joystick_right_event\":           \"오른쪽 조이스틱 이벤트\",\n                \"byrobot_petrone_v2_controller_joystick_right_x\":               \"오른쪽 조이스틱 가로축\",\n                \"byrobot_petrone_v2_controller_joystick_right_y\":               \"오른쪽 조이스틱 세로축\",\n                \"byrobot_petrone_v2_drone_accel_x\":             \"가속도 x\",\n                \"byrobot_petrone_v2_drone_accel_y\":             \"가속도 y\",\n                \"byrobot_petrone_v2_drone_accel_z\":             \"가속도 z\",\n                \"byrobot_petrone_v2_drone_attitude_pitch\":      \"자세 Pitch\",\n                \"byrobot_petrone_v2_drone_attitude_roll\":       \"자세 Roll\",\n                \"byrobot_petrone_v2_drone_attitude_yaw\":        \"자세 Yaw\",\n                \"byrobot_petrone_v2_drone_control_double_accel_forward\":    \"전진/후진\",\n                \"byrobot_petrone_v2_drone_control_double_wheel\":            \"방향\",\n                \"byrobot_petrone_v2_drone_control_double_wheel_left\":       \"왼쪽 회전\",\n                \"byrobot_petrone_v2_drone_control_double_wheel_right\":      \"오른쪽 회전\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch\":              \"Pitch\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch_backward\":     \"뒤로\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch_forward\":      \"앞으로\",\n                \"byrobot_petrone_v2_drone_control_quad_roll\":               \"Roll\",\n                \"byrobot_petrone_v2_drone_control_quad_roll_left\":          \"왼쪽\",\n                \"byrobot_petrone_v2_drone_control_quad_roll_right\":         \"오른쪽\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle\":           \"Throttle\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle_down\":      \"아래\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle_up\":        \"위\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw\":                \"Yaw\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw_left\":           \"왼쪽 회전\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw_right\":          \"오른쪽 회전\",\n                \"byrobot_petrone_v2_drone_coordinate_local\":            \"off (숙련자용)\",\n                \"byrobot_petrone_v2_drone_coordinate_world\":            \"on (초보자용)\",\n                \"byrobot_petrone_v2_drone_gyro_pitch\":                  \"각속도 Pitch\",\n                \"byrobot_petrone_v2_drone_gyro_roll\":                   \"각속도 Roll\",\n                \"byrobot_petrone_v2_drone_gyro_yaw\":                    \"각속도 Yaw\",\n                \"byrobot_petrone_v2_drone_imageflow_positionX\":         \"image flow X\",\n                \"byrobot_petrone_v2_drone_imageflow_positionY\":         \"image flow Y\",\n                \"byrobot_petrone_v2_drone_irmessage\":                   \"적외선 수신 값\",\n                \"byrobot_petrone_v2_drone_irmessage_direction\":         \"적외선 수신 방향\",\n                \"byrobot_petrone_v2_drone_irmessage_direction_front\":   \"앞\",\n                \"byrobot_petrone_v2_drone_irmessage_direction_rear\":    \"뒤\",\n                \"byrobot_petrone_v2_drone_light_color_arm\":             \"팔\",\n                \"byrobot_petrone_v2_drone_light_color_eye\":             \"눈\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_blue\":       \"팔 파랑\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_green\":      \"팔 초록\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_red\":        \"팔 빨강\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_blue\":       \"눈 파랑\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_green\":      \"눈 초록\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_red\":        \"눈 빨강\",\n                \"byrobot_petrone_v2_drone_motor_rotation_clockwise\":        \"시계 방향\",\n                \"byrobot_petrone_v2_drone_motor_rotation_counterclockwise\": \"반시계 방향\",\n                \"byrobot_petrone_v2_drone_pressure_pressure\":           \"해발고도\",\n                \"byrobot_petrone_v2_drone_pressure_temperature\":        \"온도\",\n                \"byrobot_petrone_v2_drone_range_bottom\":                \"바닥까지 거리\",\n                \"byrobot_petrone_v2_drone_state_battery\":               \"배터리\",\n                \"byrobot_petrone_v2_drone_state_mode_coordinate\":       \"기본 좌표계\",\n                \"byrobot_petrone_v2_drone_state_mode_drive\":            \"자동차 동작 상태\",\n                \"byrobot_petrone_v2_drone_state_mode_flight\":           \"비행 동작 상태\",\n                \"byrobot_petrone_v2_drone_state_mode_system\":           \"시스템 모드\",\n                \"byrobot_petrone_v2_drone_state_mode_vehicle\":          \"Vehicle mode\",\n                \"byrobot_petrone_v2_drone_team\":                    \"팀 \",\n                \"byrobot_petrone_v2_drone_team_blue\":               \"블루\",\n                \"byrobot_petrone_v2_drone_team_red\":                \"레드\",\n                \"byrobot_petrone_v2_drone_vehicle_drive\":           \"자동차\",\n                \"byrobot_petrone_v2_drone_vehicle_drive_fpv\":       \"자동차(FPV)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight\":          \"드론(가드 포함)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight_fpv\":      \"드론(FPV)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight_noguard\":      \"드론(가드 없음)\",\n                \"byrobot_petrone_v2_entryhw_count_transfer_reserved\":   \"전송 예약된 데이터 수\",\n            },\n\n            // ko.js에 작성하던 내용\n            template: {\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz\":                   \"%1 Hz 소리를 연주 %2\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz_delay\":             \"%1 Hz 소리를 %2 초 연주 %3\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz_reserve\":           \"%1 Hz 소리를 %2 초 예약 %3\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_off\":                  \"버저 끄기 %1\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale\":                \"%1 옥타브 %2 을(를) 연주 %3\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale_delay\":          \"%1 옥타브 %2 을(를) %3 초 연주 %4\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale_reserve\":        \"%1 옥타브 %2 을(를) %3 초 예약 %4\",\n                \"byrobot_petrone_v2_flight_controller_display_clear\":               \"지우기 x %1, y %2, 너비 %3, 높이 %4 %5 %6\",\n                \"byrobot_petrone_v2_flight_controller_display_clear_all\":           \"조종기 화면 전체 지우기%1 %2\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_circle\":         \"원 x %1, y %2, 반지름 %3 %4 %5 %6\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_line\":           \"선 x1 %1, y1 %2, x2 %3, y2 %4 %5 %6 %7\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_point\":          \"점 그리기 x %1, y %2 %3 %4\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_rect\":           \"사각형 x %1, y %2, 너비 %3, 높이 %4 %5 %6 %7 %8\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_string\":         \"문자열 x %1, y %2 %3 %4 입력 %5 %6\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_string_align\":   \"문자열 정렬 x1 %1, x2 %2, y %3 %4 %5 %6 입력 %7 %8\",\n                \"byrobot_petrone_v2_flight_controller_display_invert\":              \"색반전 x %1, y %2, 너비 %3, 높이 %4 %5\",\n                \"byrobot_petrone_v2_flight_controller_if_button_press\":             \"조종기 %1 눌렀을 때\",\n                \"byrobot_petrone_v2_flight_controller_if_joystick_direction\":       \"조종기 %1 조이스틱 %2 움직였을 때\",\n                \"byrobot_petrone_v2_flight_controller_light_color_input\":           \"조종기 LED 색지정 R %1, G %2, B %3 %4 %5 %6\",\n                \"byrobot_petrone_v2_flight_controller_light_color_select\":          \"조종기 LED의 RGB 조합 예시 %1 %2 %3 %4\",\n                \"byrobot_petrone_v2_flight_controller_light_color_preset\":          \"조종기 LED %1 %2 %3\",\n                \"byrobot_petrone_v2_flight_controller_light_manual_single_input\":   \"조종기 LED %1 밝기 %2 %3\",\n                \"byrobot_petrone_v2_flight_controller_light_manual_single_off\":     \"조종기 LED 끄기 %1\",\n                \"byrobot_petrone_v2_flight_controller_value_button\":                \"%1\",\n                \"byrobot_petrone_v2_flight_controller_value_joystick\":              \"%1\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_delay\":              \"진동 %1 초 켜기, %2 초 끄기를 %3 초 실행 %4\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_off\":                \"진동 끄기 %1\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_on_delay\":           \"진동 %1 초 켜기 %2\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_on_reserve\":         \"진동 %1 초 예약 %2\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_reserve\":            \"진동 %1 초 켜기, %2 초 끄기를 %3 초 예약 %4\",\n                \"byrobot_petrone_v2_flight_drone_command_mode_vehicle_drone\":       \"Vehicle mode %1 선택 %2\",\n                \"byrobot_petrone_v2_flight_drone_control_coordinate\":               \"(드론 좌표 기준) Headless mode %1 %2\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_landing\":            \"드론 착륙 %1\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_reset_heading\":      \"드론 방향 초기화 %1\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_stop\":               \"드론 정지 %1\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_takeoff\":            \"드론 이륙 %1\",\n                \"byrobot_petrone_v2_flight_drone_control_quad\":                     \"드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% 정하기 %5\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_delay\":               \"드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5초 실행 %6\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_one\":                 \"드론 %1 %2% 정하기 %3\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_one_delay\":           \"드론 %1 %2% %3 초 실행 %4\",\n                \"byrobot_petrone_v2_flight_drone_irmessage\":                        \"적외선으로 %1 값 보내기 %2\",\n                \"byrobot_petrone_v2_flight_drone_light_color_input\":                \"드론 %1 LED 색지정 R %2, G %3, B %4 %5 %6 %7\",\n                \"byrobot_petrone_v2_flight_drone_light_color_select\":               \"드론 %1 LED의 RGB 조합 예시 %2 %3 %4 %5\",\n                \"byrobot_petrone_v2_flight_drone_light_color_preset\":               \"드론 LED %1 %2 %3\",\n                \"byrobot_petrone_v2_flight_drone_light_manual_single_input\":        \"드론 LED %1 밝기 %2 %3\",\n                \"byrobot_petrone_v2_flight_drone_light_manual_single_off\":          \"드론 LED 끄기 %1\",\n                \"byrobot_petrone_v2_flight_drone_motor_stop\":                       \"모터 정지 %1\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle\":                      \"%1번 모터를 %2(으)로 회전 %3\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle_input\":                \"%1번 모터를 %2(으)로 회전 %3\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle_rotation\":             \"%1번 모터를 %2으로 %3(으)로 회전 %4\",\n                \"byrobot_petrone_v2_flight_drone_value_attitude\":                   \"%1\",\n                \"byrobot_petrone_v2_flight_drone_value_etc\":                        \"%1\",\n                \"byrobot_petrone_v2_flight_drone_value_imu\":                        \"%1\",\n                \"byrobot_petrone_v2_flight_drone_value_sensor\":                     \"%1\",\n            },\n\n            Helper: {\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz\":                   \"<br>지정한 주파수의 소리를 계속해서 연주합니다(최대 60초). 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz_delay\":             \"<br>지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz_reserve\":           \"<br>지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_off\":                  \"<br>버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저끄기</font>\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale\":                \"<br>지정한 옥타브의 음을 계속해서 연주합니다(최대 60초). 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font>\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale_delay\":          \"<br>지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale_reserve\":        \"<br>지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_clear\":               \"<br>조종기 OLED 화면의 선택한 영역을 지웁니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_clear_all\":           \"<br>조종기 OLED 화면 전체를 지웁니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_circle\":         \"<br>조종기 OLED 화면에서 지정한 위치에 원을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 반지름을 지정합니다. 원의 중심 = (x, y),<br>반지름은 원의 크기를 결정합니다.<br><br>★☆사용 가능한 값의 범위는 x값은 (-50~178), y값은 (-50~114), 반지름은 (1~200)입니다.☆★<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_line\":           \"<br>조종기 OLED 화면에서 지정한 위치에 선을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>시작점 = (x1, y1), 끝나는점 = (x2, y2)<br>선 그리기는 시작점과 끝나는점을 이어주는 기능입니다.<br>사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_point\":          \"<br>조종기 OLED 화면에서 지정한 위치에 점을 찍습니다. 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다. x, y 좌표값으로 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_rect\":           \"<br>조종기 OLED 화면에서 지정한 위치에 사각형을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 너비, 높이를 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_string\":         \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 씁니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 글자 크기, 색을 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값은 (0~120), y값과 높이는 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_string_align\":   \"<br>조종기 OLED 화면에서 지정한 위치에 문자열을 정렬하여 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 정렬 방향, 글자 크기, 색을 지정합니다. 시작점 = (x1, y), 끝나는점 = (x2, y), 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_display_invert\":              \"<br>조종기 OLED 화면에서 선택한 영역의 색을 반전시킵니다. x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                \"byrobot_petrone_v2_flight_controller_if_button_press\":             \"<br>지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_petrone_v2_flight_controller_if_joystick_direction\":       \"<br>조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_petrone_v2_flight_controller_light_color_input\":           \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 조종기 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_flight_controller_light_color_select\":          \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 조종기 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_flight_controller_light_color_preset\":         \"<br>조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_flight_controller_light_manual_single_input\":   \"<br>조종기 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_flight_controller_light_manual_single_off\":     \"<br>조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_petrone_v2_flight_controller_value_button\":                \"<br>조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                \"byrobot_petrone_v2_flight_controller_value_joystick\":              \"<br>조종기의 조이스틱과 관련된 입력 값을 반환합니다. 각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_delay\":              \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_off\":                \"<br>진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_on_delay\":           \"<br>진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_on_reserve\":         \"<br>진동을 지정한 시간동안 켜는 것을 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_reserve\":            \"<br>진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                \"byrobot_petrone_v2_flight_drone_command_mode_vehicle_drone\":       \"<br>드론 Vehicle mode를 변경합니다.<br><br>드론(가드 포함) = 16, 드론(가드 없음) = 17, 드론(FPV) = 18 입니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#Vehicle mode</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_coordinate\":               \"<br>드론 좌표 기준을 변경합니다. Headless mode 선택을 on으로 하면 이륙 시와 '방향초기화'를 했을 때 드론이 바라보는 방향을 기준으로 앞뒤좌우가 고정됩니다. 이 때에는 Yaw를 조작하여 드론이 다른 방향을 보게 하여도 처음 지정한 방향을 기준으로 앞뒤좌우로 움직입니다. 사용자가 바라보는 방향과 드론의 기준 방향이 같을 때 조작하기 편리한 장점이 있습니다.<br>Headless mode를 off로 선택하면 현재 드론이 바라보는 방향을 기준으로 앞뒤좌우가 결정됩니다. 드론의 움직임에 따라 앞뒤좌우가 계속 바뀌기 때문에 익숙해지기 전까지는 사용하기 어려울 수 있습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#좌표기준</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_landing\":            \"<br>드론을 착륙시킵니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#착륙</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_reset_heading\":      \"<br>드론의 방향을 초기화합니다. 앱솔루트 모드인 경우 현재 드론이 바라보는 방향을 0도로 변경합니다. 일반 모드에서는 아무런 영향이 없습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#방향초기화</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_stop\":               \"<br>드론 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#정지</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_takeoff\":            \"<br>드론을 이륙시킵니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이륙</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_quad\":                     \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_delay\":               \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_one\":                 \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_one_delay\":           \"<br>드론 조종 값을 지정합니다. 입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                \"byrobot_petrone_v2_flight_drone_irmessage\":                        \"<br>적외선으로 지정한 값을 보냅니다. 사용 가능한 값의 범위는 -2147483647 ~ 2147483647입니다.수신 방향이 추가되었습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#적외선통신</font>\",\n                \"byrobot_petrone_v2_flight_drone_light_color_input\":                \"<br>빛의 삼원색인 Red, Green, Blue 값을 지정하여 드론의 눈 또는 팔 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_flight_drone_light_color_select\":               \"<br>RGB 색지정 블록을 이용해서 만들 수 있는<br> 드론 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_flight_drone_light_color_preset\":               \"<br>드론의 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_flight_drone_light_manual_single_input\":        \"<br>드론 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                \"byrobot_petrone_v2_flight_drone_light_manual_single_off\":          \"<br>드론의 모든 LED를 끕니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED끄기</font>\",\n                \"byrobot_petrone_v2_flight_drone_motor_stop\":                       \"<br>모든 모터의 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터정지</font>\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle\":                      \"<br>지정한 모터를 원하는 빠르기로 회전할 때 사용합니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle_input\":                \"<br>지정한 모터(1, 2, 3, 4)를 원하는 빠르기로 회전할 때 사용합니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle_rotation\":             \"<br>지정한 모터를 원하는 빠르기로 회전할 때 사용합니다. 1번 모터와 2번 모터는 역방향도 회전 가능하기 때문에 방향도 선택할 수 있습니다. 사용 가능한 값의 범위는 0 ~ 4000입니다. 모터의 순서는 '왼쪽 앞', '오른쪽 앞', '오른쪽 뒤', '왼쪽 뒤' 입니다.<br><br><font color='crimson'>#자동차</font> <font color='dodgerblue'>#모터제어</font>\",\n                \"byrobot_petrone_v2_flight_drone_value_attitude\":                   \"<br>드론의 현재 자세를 각도로 반환합니다. Roll은 좌우 기울기(-90 ~ 90), Pitch는 앞뒤 기울기(-90 ~ 90), Yaw는 회전 각도(-180 ~ 180) 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#자세</font>\",\n                \"byrobot_petrone_v2_flight_drone_value_etc\":                        \"<br>페트론V2 설정과 관련된 값들과 적외선 통신으로 받은 값을 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#기타</font>\",\n                \"byrobot_petrone_v2_flight_drone_value_imu\":                        \"<br>페트론V2 IMU센서와 관련된 값들을 반환합니다.<br>(병진운동) 가속도는 x, y, z축에 대한 중력가속도입니다. 1g = 9.8m/s^2<br>(회전운동) 각속도는 x, y, z축을 기준으로 회전하는 속력을 나타내는 벡터입니다.(pitch, roll, yaw) <br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#IMU센서</font> <font color='crimson'>#가속도</font> <font color='dodgerblue'>#병진운동</font> <font color='crimson'>#각속도</font> <font color='dodgerblue'>#회전운동</font>\",\n                \"byrobot_petrone_v2_flight_drone_value_sensor\":                     \"<br>페트론V2 센서와 관련된 값들을 반환합니다.<br>온도 단위=섭씨 도, 해발고도 단위=m, image flow 단위=m, 바닥까지의 거리 단위=m<br>해발고도 값은 대기압의 영향을 받아서 오차범위가 큽니다. 바닥까지 거리의 유효 측정 거리는 2m입니다. image flow값은 일정한 속도와 높이에서 이동할 경우에 유효합니다. 이러한 센서값들을 이용하여 Petrone V2는 호버링(고도 유지) 기능을 수행합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#센서</font> <font color='crimson'>#온도</font> <font color='dodgerblue'>#해발고도</font> <font color='forestgreen'>#image flow</font> <font color='crimson'>#range</font> <font color='dodgerblue'>#대기압</font> <font color='forestgreen'>#호버링</font>\",\n            }\n        },\n\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                \"byrobot_petrone_v2_common_left\":                       \"left\",\n                \"byrobot_petrone_v2_common_light_color_cottoncandy\":    \"cotton candy\",\n                \"byrobot_petrone_v2_common_light_color_emerald\":        \"emerald\",\n                \"byrobot_petrone_v2_common_light_color_lavender\":       \"lavender\",\n                \"byrobot_petrone_v2_common_light_mode_dimming\":         \"dimming\",\n                \"byrobot_petrone_v2_common_light_mode_flicker\":         \"flicker\",\n                \"byrobot_petrone_v2_common_light_mode_flicker_double\":  \"flicker double\",\n                \"byrobot_petrone_v2_common_light_mode_hold\":            \"hold\",\n                \"byrobot_petrone_v2_common_light_color_muscat\":         \"muscat\",\n                \"byrobot_petrone_v2_common_light_color_strawberrymilk\": \"strawberry milk\",\n                \"byrobot_petrone_v2_common_light_color_sunset\":         \"sunset\",\n                \"byrobot_petrone_v2_common_light_manual_all\":           \"all\",\n                \"byrobot_petrone_v2_common_light_manual_b100\":          \"brightness 100%\",\n                \"byrobot_petrone_v2_common_light_manual_b25\":           \"brightness 25%\",\n                \"byrobot_petrone_v2_common_light_manual_b50\":           \"brightness 50%\",\n                \"byrobot_petrone_v2_common_light_manual_b75\":           \"brightness 75%\",\n                \"byrobot_petrone_v2_common_light_manual_blue\":          \"blue\",\n                \"byrobot_petrone_v2_common_light_manual_cyan\":          \"cyan\",\n                \"byrobot_petrone_v2_common_light_manual_green\":         \"green\",\n                \"byrobot_petrone_v2_common_light_manual_magenta\":       \"magenta\",\n                \"byrobot_petrone_v2_common_light_manual_off\":           \"off\",\n                \"byrobot_petrone_v2_common_light_manual_on\":            \"on\",\n                \"byrobot_petrone_v2_common_light_manual_red\":           \"red\",\n                \"byrobot_petrone_v2_common_light_manual_white\":         \"white\",\n                \"byrobot_petrone_v2_common_light_manual_yellow\":        \"yellow\",\n                \"byrobot_petrone_v2_common_pitch\":      \"pitch\",\n                \"byrobot_petrone_v2_common_right\":      \"right\",\n                \"byrobot_petrone_v2_common_roll\":       \"roll\",\n                \"byrobot_petrone_v2_common_throttle\":   \"throttle\",\n                \"byrobot_petrone_v2_common_yaw\":        \"yaw\",\n                \"byrobot_petrone_v2_controller_button_bottom_left\":         \"left round button\",\n                \"byrobot_petrone_v2_controller_button_bottom_left_right\":   \"both round button\",\n                \"byrobot_petrone_v2_controller_button_bottom_right\":        \"right round button\",\n                \"byrobot_petrone_v2_controller_button_button\":              \"button\",\n                \"byrobot_petrone_v2_controller_button_center_down\":         \"trim-backward button\",\n                \"byrobot_petrone_v2_controller_button_center_left\":         \"trim-left button\",\n                \"byrobot_petrone_v2_controller_button_center_right\":        \"trim-right button\",\n                \"byrobot_petrone_v2_controller_button_center_up\":           \"trim-forward button\",\n                \"byrobot_petrone_v2_controller_button_center_up_left\":      \"trim-turn-left button\",\n                \"byrobot_petrone_v2_controller_button_center_up_right\":     \"trim-turn-right button\",\n                \"byrobot_petrone_v2_controller_button_event\":               \"button event\",\n                \"byrobot_petrone_v2_controller_button_front_left\":          \"left red button\",\n                \"byrobot_petrone_v2_controller_button_front_left_right\":    \"both red button\",\n                \"byrobot_petrone_v2_controller_button_front_right\":         \"right red button\",\n                \"byrobot_petrone_v2_controller_buzzer\":         \"buzzer\",\n                \"byrobot_petrone_v2_controller_buzzer_a\":       \"A\",\n                \"byrobot_petrone_v2_controller_buzzer_as\":      \"A#\",\n                \"byrobot_petrone_v2_controller_buzzer_b\":       \"B\",\n                \"byrobot_petrone_v2_controller_buzzer_c\":       \"C\",\n                \"byrobot_petrone_v2_controller_buzzer_cs\":      \"C#\",\n                \"byrobot_petrone_v2_controller_buzzer_d\":       \"D\",\n                \"byrobot_petrone_v2_controller_buzzer_ds\":      \"D#\",\n                \"byrobot_petrone_v2_controller_buzzer_e\":       \"E\",\n                \"byrobot_petrone_v2_controller_buzzer_f\":       \"F\",\n                \"byrobot_petrone_v2_controller_buzzer_fs\":      \"F#\",\n                \"byrobot_petrone_v2_controller_buzzer_g\":       \"G\",\n                \"byrobot_petrone_v2_controller_buzzer_gs\":      \"G#\",\n                \"byrobot_petrone_v2_controller_buzzer_mute\":    \"mute\",\n                \"byrobot_petrone_v2_controller_display_align_center\":           \"center\",\n                \"byrobot_petrone_v2_controller_display_align_left\":             \"left\",\n                \"byrobot_petrone_v2_controller_display_align_right\":            \"right\",\n                \"byrobot_petrone_v2_controller_display_flagfill_off\":           \"not fill\",\n                \"byrobot_petrone_v2_controller_display_flagfill_on\":            \"fill\",\n                \"byrobot_petrone_v2_controller_display_font_10x16\":             \"big\",\n                \"byrobot_petrone_v2_controller_display_font_5x8\":               \"small\",\n                \"byrobot_petrone_v2_controller_display_line_dashed\":            \"dashed\",\n                \"byrobot_petrone_v2_controller_display_line_dotted\":            \"dotted\",\n                \"byrobot_petrone_v2_controller_display_line_solid\":             \"solid\",\n                \"byrobot_petrone_v2_controller_display_pixel_black\":            \"black\",\n                \"byrobot_petrone_v2_controller_display_pixel_white\":            \"white\",\n                \"byrobot_petrone_v2_controller_joystick_direction_center\":      \"center\",\n                \"byrobot_petrone_v2_controller_joystick_direction_down\":        \"down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left\":        \"left\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_down\":   \"left down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_left_up\":     \"left up\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right\":       \"right\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_down\":  \"right down\",\n                \"byrobot_petrone_v2_controller_joystick_direction_right_up\":    \"right up\",\n                \"byrobot_petrone_v2_controller_joystick_direction_up\":          \"up\",\n                \"byrobot_petrone_v2_controller_joystick_left_direction\":        \"left joystick direction\",\n                \"byrobot_petrone_v2_controller_joystick_left_event\":            \"left joystick event\",\n                \"byrobot_petrone_v2_controller_joystick_left_x\":                \"left joystick horizontal\",\n                \"byrobot_petrone_v2_controller_joystick_left_y\":                \"left joystick vertical\",\n                \"byrobot_petrone_v2_controller_joystick_right_direction\":       \"right joystick direction\",\n                \"byrobot_petrone_v2_controller_joystick_right_event\":           \"right joystick event\",\n                \"byrobot_petrone_v2_controller_joystick_right_x\":               \"right joystick horizontal\",\n                \"byrobot_petrone_v2_controller_joystick_right_y\":               \"right joystick vertical\",\n                \"byrobot_petrone_v2_drone_accel_x\": \"accel x\",\n                \"byrobot_petrone_v2_drone_accel_y\": \"accel y\",\n                \"byrobot_petrone_v2_drone_accel_z\": \"accel z\",\n                \"byrobot_petrone_v2_drone_attitude_pitch\": \"attitude - pitch\",\n                \"byrobot_petrone_v2_drone_attitude_roll\": \"attitude - roll\",\n                \"byrobot_petrone_v2_drone_attitude_yaw\": \"attitude - yaw\",\n                \"byrobot_petrone_v2_drone_control_double_accel_forward\": \"forward/backward\",\n                \"byrobot_petrone_v2_drone_control_double_wheel\": \"direction\",\n                \"byrobot_petrone_v2_drone_control_double_wheel_left\": \"turn left\",\n                \"byrobot_petrone_v2_drone_control_double_wheel_right\": \"turn right\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch\": \"pitch\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch_backward\": \"backward\",\n                \"byrobot_petrone_v2_drone_control_quad_pitch_forward\": \"foward\",\n                \"byrobot_petrone_v2_drone_control_quad_roll\": \"roll\",\n                \"byrobot_petrone_v2_drone_control_quad_roll_left\": \"left\",\n                \"byrobot_petrone_v2_drone_control_quad_roll_right\": \"right\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle\": \"throttle\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle_down\": \"down\",\n                \"byrobot_petrone_v2_drone_control_quad_throttle_up\": \"up\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw\": \"yaw\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw_left\": \"turn Left\",\n                \"byrobot_petrone_v2_drone_control_quad_yaw_right\": \"turn Right\",\n                \"byrobot_petrone_v2_drone_coordinate_local\": \"off (hard)\",\n                \"byrobot_petrone_v2_drone_coordinate_world\": \"on (easy)\",\n                \"byrobot_petrone_v2_drone_gyro_pitch\": \"angular speed - pitch\",\n                \"byrobot_petrone_v2_drone_gyro_roll\": \"angular speed - roll\",\n                \"byrobot_petrone_v2_drone_gyro_yaw\": \"angular speed - yaw\",\n                \"byrobot_petrone_v2_drone_imageflow_positionX\": \"image flow X\",\n                \"byrobot_petrone_v2_drone_imageflow_positionY\": \"image flow Y\",\n                \"byrobot_petrone_v2_drone_irmessage\": \"IR data received\",\n                \"byrobot_petrone_v2_drone_irmessage_direction\": \"IR received direction\",\n                \"byrobot_petrone_v2_drone_irmessage_direction_front\": \"front\",\n                \"byrobot_petrone_v2_drone_irmessage_direction_rear\": \"rear\",\n                \"byrobot_petrone_v2_drone_light_color_arm\": \"arm\",\n                \"byrobot_petrone_v2_drone_light_color_eye\": \"eye\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_blue\": \"arm - blue\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_green\": \"arm - green\",\n                \"byrobot_petrone_v2_drone_light_manual_arm_red\": \"arm - red\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_blue\": \"eye - blue\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_green\": \"eye - green\",\n                \"byrobot_petrone_v2_drone_light_manual_eye_red\": \"eye - red\",\n                \"byrobot_petrone_v2_drone_motor_rotation_clockwise\": \"Clockwise\",\n                \"byrobot_petrone_v2_drone_motor_rotation_counterclockwise\": \"Counterclockwise\",\n                \"byrobot_petrone_v2_drone_pressure_pressure\": \"altitude above sea level\",\n                \"byrobot_petrone_v2_drone_pressure_temperature\": \"temperature\",\n                \"byrobot_petrone_v2_drone_range_bottom\": \"distance to bottom\",\n                \"byrobot_petrone_v2_drone_state_battery\": \"battery\",\n                \"byrobot_petrone_v2_drone_state_mode_coordinate\": \"coordinate\",\n                \"byrobot_petrone_v2_drone_state_mode_drive\": \"drive Mode\",\n                \"byrobot_petrone_v2_drone_state_mode_flight\": \"flight Mode\",\n                \"byrobot_petrone_v2_drone_state_mode_system\": \"system Mode\",\n                \"byrobot_petrone_v2_drone_state_mode_vehicle\": \"vehicle Mode\",\n                \"byrobot_petrone_v2_drone_team\": \"team\",\n                \"byrobot_petrone_v2_drone_team_blue\": \"blue\",\n                \"byrobot_petrone_v2_drone_team_red\": \"red\",\n                \"byrobot_petrone_v2_drone_vehicle_drive\": \"drive\",\n                \"byrobot_petrone_v2_drone_vehicle_drive_fpv\": \"drive(FPV)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight\": \"drone(with guard)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight_fpv\": \"drone(FPV)\",\n                \"byrobot_petrone_v2_drone_vehicle_flight_noguard\": \"drone(without guard)\",\n                \"byrobot_petrone_v2_entryhw_count_transfer_reserved\":           \"reserved data blocks\",\n            },\n\n            // en.js에 작성하던 내용\n            template: {\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz\": \"play %1 Hz sound %2\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz_delay\": \"play %1 Hz sound for %2 second %3\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_hz_reserve\": \"reserve to play %1 Hz sound for %2 second %3\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_off\": \"turn off the buzzer %1\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale\": \"play %1 octave %2 %3\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale_delay\": \"play %1 octave %2 for %3 second %4\",\n                \"byrobot_petrone_v2_flight_controller_buzzer_scale_reserve\": \"reserve to play %1 octave %2 for %3 second %4\",\n                \"byrobot_petrone_v2_flight_controller_display_clear\": \"clear controller display x:%1, y:%2, width:%3, height:%4, color:%5 %6\",\n                \"byrobot_petrone_v2_flight_controller_display_clear_all\": \"clear controller display with %1 color %2\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_circle\": \"draw a circle in controller display x:%1, y:%2, radius:%3, %4, %5, %6\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_line\": \"draw a line in controller display x1:%1, y1:%2, x2:%3, y2:%4, %5, %6 %7\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_point\": \"draw a point in controller display  x:%1, y:%2, color:%3 %4\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_rect\": \"draw a rectangle in controller display x:%1, y:%2, width:%3, height:%4, %5, %6, %7 %8\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_string\": \"draw a string in controller display x:%1, y:%2, font size:%3, %4, input:%5, %6\",\n                \"byrobot_petrone_v2_flight_controller_display_draw_string_align\": \"draw aligned string in controller display x1:%1, x2:%2, y:%3, align:%4, font size:%5, %6, input:%7, %8\",\n                \"byrobot_petrone_v2_flight_controller_display_invert\": \"invert controller display x:%1, y:%2, width:%3, height:%4 %5\",\n                \"byrobot_petrone_v2_flight_controller_if_button_press\": \"when press %1\",\n                \"byrobot_petrone_v2_flight_controller_if_joystick_direction\": \"when %1 stick move to %2\",\n                \"byrobot_petrone_v2_flight_controller_light_color_input\": \"decide the color values of controller LED R %1, G %2, B %3 %4 %5\",\n                \"byrobot_petrone_v2_flight_controller_light_color_select\": \"RGB combination examples of controller LED %1 %2 %3\",\n                \"byrobot_petrone_v2_flight_controller_light_color_preset\": \"change the state of %1 controller LED to %2 %3\",\n                \"byrobot_petrone_v2_flight_controller_light_manual_single_input\": \"change the brightness of %1 controller LED to %2 %3\",\n                \"byrobot_petrone_v2_flight_controller_light_manual_single_off\": \"turn off all controller LEDs %1\",\n                \"byrobot_petrone_v2_flight_controller_value_button\": \"%1\",\n                \"byrobot_petrone_v2_flight_controller_value_joystick\": \"%1\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_delay\": \"vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_off\": \"turn off the vibrator %1\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_on_delay\": \"turn on the vibrator for %1 second %2\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_on_reserve\": \"reserve turn on the vibrator for %1 second %2\",\n                \"byrobot_petrone_v2_flight_controller_vibrator_reserve\": \"reserve vibration %1 second on, %2 second off for %3 seconds %4\",\n                \"byrobot_petrone_v2_flight_drone_command_mode_vehicle_drone\": \"set vehicle mode to %1 %2\",\n                \"byrobot_petrone_v2_flight_drone_control_coordinate\": \"Headless mode (Absolute mode) %1 %2\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_landing\": \"landing %1\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_reset_heading\": \"reset heading reference %1\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_stop\": \"stop %1\",\n                \"byrobot_petrone_v2_flight_drone_control_drone_takeoff\": \"take off %1\",\n                \"byrobot_petrone_v2_flight_drone_control_quad\": \"set roll to %1, pitch to %2, yaw to %3, throttle to %4 %5\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_delay\": \"set roll to %1, pitch to %2, yaw to %3, throttle to %4 and run for %5 second %6\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_one\": \"set %1 to %2 %3\",\n                \"byrobot_petrone_v2_flight_drone_control_quad_one_delay\": \"set %1 to %2 and run for %3 second %4\",\n                \"byrobot_petrone_v2_flight_drone_irmessage\": \"send %1 to the IR transmitter %2\",\n                \"byrobot_petrone_v2_flight_drone_light_color_input\": \"decide the color values of drone %1 LED R %2, G %3, B %4 %5 %6\",\n                \"byrobot_petrone_v2_flight_drone_light_color_select\": \"RGB combination examples of drone %1 LED %2 %3 %4\",\n                \"byrobot_petrone_v2_flight_drone_light_color_preset\": \"change the state of %1 drone LED to %2 %3\",\n                \"byrobot_petrone_v2_flight_drone_light_manual_single_input\": \"change the brightness of %1 drone LED to %2 %3\",\n                \"byrobot_petrone_v2_flight_drone_light_manual_single_off\": \"turn off all drone LEDs %1\",\n                \"byrobot_petrone_v2_flight_drone_motor_stop\": \"turn off all motors %1\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle\": \"set rotate for number %1 motor to %2 %3\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle_input\": \"set rotate for number %1 motor to %2 %3\",\n                \"byrobot_petrone_v2_flight_drone_motorsingle_rotation\": \"set rotate for number %1 motor to %2 %3 %4\",\n                \"byrobot_petrone_v2_flight_drone_value_attitude\": \"%1\",\n                \"byrobot_petrone_v2_flight_drone_value_etc\": \"%1\",\n                \"byrobot_petrone_v2_flight_drone_value_imu\": \"%1\",\n                \"byrobot_petrone_v2_flight_drone_value_sensor\": \"%1\",\n            },\n            \n            Helper: {\n\n            }\n        }\n    }\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.byrobot_petrone_v2_flight.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/byrobot_petrone_v2_flight.png\",      // 배경 이미지\n        width: 256,     // 이미지의 폭\n        height: 256,    // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeVehicle:              {name: Lang.Blocks.byrobot_petrone_v2_drone_state_mode_vehicle,             type: 'input',  pos: { x: 0, y: 0 }},\n            state_modeFlight:               {name: Lang.Blocks.byrobot_petrone_v2_drone_state_mode_flight,              type: 'input',  pos: { x: 0, y: 0 }},\n            state_battery:                  {name: Lang.Blocks.byrobot_petrone_v2_drone_state_battery,                  type: 'input',  pos: { x: 0, y: 0 }},\n            imu_angleRoll:                  {name: Lang.Blocks.byrobot_petrone_v2_drone_attitude_roll,                  type: 'input',  pos: { x: 0, y: 0 }},\n            imu_anglePitch:                 {name: Lang.Blocks.byrobot_petrone_v2_drone_attitude_pitch,                 type: 'input',  pos: { x: 0, y: 0 }},\n            imu_angleYaw:                   {name: Lang.Blocks.byrobot_petrone_v2_drone_attitude_yaw,                   type: 'input',  pos: { x: 0, y: 0 }},\n            imu_accX:                       {name: Lang.Blocks.byrobot_petrone_v2_drone_accel_x,                        type: 'input',  pos: { x: 0, y: 0 }},\n            imu_accY:                       {name: Lang.Blocks.byrobot_petrone_v2_drone_accel_y,                        type: 'input',  pos: { x: 0, y: 0 }},\n            imu_accZ:                       {name: Lang.Blocks.byrobot_petrone_v2_drone_accel_z,                        type: 'input',  pos: { x: 0, y: 0 }},\n            imu_gyroRoll:                   {name: Lang.Blocks.byrobot_petrone_v2_drone_gyro_roll,                      type: 'input',  pos: { x: 0, y: 0 }},\n            imu_gyroPitch:                  {name: Lang.Blocks.byrobot_petrone_v2_drone_gyro_pitch,                     type: 'input',  pos: { x: 0, y: 0 }},\n            imu_gyroYaw:                    {name: Lang.Blocks.byrobot_petrone_v2_drone_gyro_yaw,                       type: 'input',  pos: { x: 0, y: 0 }},\n            pressure_temperature:           {name: Lang.Blocks.byrobot_petrone_v2_drone_pressure_temperature,           type: 'input',  pos: { x: 0, y: 0 }},\n            pressure_pressure:              {name: Lang.Blocks.byrobot_petrone_v2_drone_pressure_pressure,              type: 'input',  pos: { x: 0, y: 0 }},\n            imageflow_positionX:            {name: Lang.Blocks.byrobot_petrone_v2_drone_imageflow_positionX,            type: 'input',  pos: { x: 0, y: 0 }},\n            imageflow_positionY:            {name: Lang.Blocks.byrobot_petrone_v2_drone_imageflow_positionY,            type: 'input',  pos: { x: 0, y: 0 }},\n            range_bottom:                   {name: Lang.Blocks.byrobot_petrone_v2_drone_range_bottom,                   type: 'input',  pos: { x: 0, y: 0 }},\n            irmessage_direction:            {name: Lang.Blocks.byrobot_petrone_v2_drone_irmessage_direction,            type: 'input',  pos: { x: 0, y: 0 }},\n            irmessage_irdata:               {name: Lang.Blocks.byrobot_petrone_v2_drone_irmessage,                      type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_x:                {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_x,           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_y:                {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_y,           type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_direction:        {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_direction,   type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_left_event:            {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_event,       type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_x:               {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_x,          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_y:               {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_y,          type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_direction:       {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_direction,  type: 'input',  pos: { x: 0, y: 0 }},\n            joystick_right_event:           {name: Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_event,      type: 'input',  pos: { x: 0, y: 0 }},\n            button_button:                  {name: Lang.Blocks.byrobot_petrone_v2_controller_button_button,             type: 'input',  pos: { x: 0, y: 0 }},\n            button_event:                   {name: Lang.Blocks.byrobot_petrone_v2_controller_button_event,              type: 'input',  pos: { x: 0, y: 0 }},\n            entryhw_countTransferReserved:  {name: Lang.Blocks.byrobot_petrone_v2_entryhw_count_transfer_reserved,      type: 'output', pos: { x: 0, y: 0 }},\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both', // 표시 모드\n    };\n};\n\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 이름\n ***************************************************************************************/\nEntry.byrobot_petrone_v2_flight.blockMenuBlocks = [\n    'byrobot_petrone_v2_flight_drone_value_attitude',\n    'byrobot_petrone_v2_flight_drone_value_imu',\n    'byrobot_petrone_v2_flight_drone_value_sensor',\n    'byrobot_petrone_v2_flight_drone_value_etc',\n    'byrobot_petrone_v2_flight_controller_value_button',\n    'byrobot_petrone_v2_flight_controller_value_joystick',\n    'byrobot_petrone_v2_flight_controller_if_button_press',\n    'byrobot_petrone_v2_flight_controller_if_joystick_direction',\n    'byrobot_petrone_v2_flight_drone_command_mode_vehicle_drone',\n    'byrobot_petrone_v2_flight_drone_control_drone_takeoff',\n    'byrobot_petrone_v2_flight_drone_control_drone_landing',\n    'byrobot_petrone_v2_flight_drone_control_drone_stop',\n    'byrobot_petrone_v2_flight_drone_control_coordinate',\n    'byrobot_petrone_v2_flight_drone_control_drone_reset_heading',\n    'byrobot_petrone_v2_flight_drone_control_quad_one',\n    'byrobot_petrone_v2_flight_drone_control_quad_one_delay',\n    'byrobot_petrone_v2_flight_drone_control_quad',\n    'byrobot_petrone_v2_flight_drone_control_quad_delay',\n    'byrobot_petrone_v2_flight_drone_motor_stop',\n    'byrobot_petrone_v2_flight_drone_motorsingle',\n    'byrobot_petrone_v2_flight_drone_motorsingle_input',\n    'byrobot_petrone_v2_flight_drone_motorsingle_rotation',\n    'byrobot_petrone_v2_flight_drone_irmessage',\n    'byrobot_petrone_v2_flight_drone_light_manual_single_off',\n    'byrobot_petrone_v2_flight_drone_light_manual_single_input',\n    'byrobot_petrone_v2_flight_drone_light_color_preset',\n    'byrobot_petrone_v2_flight_drone_light_color_input',\n    'byrobot_petrone_v2_flight_drone_light_color_select',\n    'byrobot_petrone_v2_flight_controller_light_manual_single_off',\n    'byrobot_petrone_v2_flight_controller_light_manual_single_input',\n    'byrobot_petrone_v2_flight_controller_light_color_preset',\n    'byrobot_petrone_v2_flight_controller_light_color_input',\n    'byrobot_petrone_v2_flight_controller_light_color_select',\n    'byrobot_petrone_v2_flight_controller_display_clear_all',\n    'byrobot_petrone_v2_flight_controller_display_clear',\n    'byrobot_petrone_v2_flight_controller_display_invert',\n    'byrobot_petrone_v2_flight_controller_display_draw_point',\n    'byrobot_petrone_v2_flight_controller_display_draw_line',\n    'byrobot_petrone_v2_flight_controller_display_draw_rect',\n    'byrobot_petrone_v2_flight_controller_display_draw_circle',\n    'byrobot_petrone_v2_flight_controller_display_draw_string',\n    'byrobot_petrone_v2_flight_controller_display_draw_string_align',\n    'byrobot_petrone_v2_flight_controller_buzzer_off',\n    'byrobot_petrone_v2_flight_controller_buzzer_scale',\n    'byrobot_petrone_v2_flight_controller_buzzer_scale_delay',\n    'byrobot_petrone_v2_flight_controller_buzzer_scale_reserve',\n    'byrobot_petrone_v2_flight_controller_buzzer_hz',\n    'byrobot_petrone_v2_flight_controller_buzzer_hz_delay',\n    'byrobot_petrone_v2_flight_controller_buzzer_hz_reserve',\n    'byrobot_petrone_v2_flight_controller_vibrator_off',\n    'byrobot_petrone_v2_flight_controller_vibrator_on_delay',\n    'byrobot_petrone_v2_flight_controller_vibrator_on_reserve',\n    'byrobot_petrone_v2_flight_controller_vibrator_delay',\n    'byrobot_petrone_v2_flight_controller_vibrator_reserve',\n];\n\n\n\n/***************************************************************************************\n *  엔트리 블록 상세\n ***************************************************************************************/\nEntry.byrobot_petrone_v2_flight.getBlocks = function()\n{\n    return {\n        //region byrobot 바이로봇\n        /* BYROBOT PetroneV2 Flight Start */\n        byrobot_petrone_v2_flight_drone_value_attitude:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_attitude_roll,    'imu_angleRoll'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_attitude_pitch,   'imu_anglePitch'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_attitude_yaw,     'imu_angleYaw'],\n                    ],\n                    value: 'imu_angleRoll', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_value_attitude', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_value_imu:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_accel_x,      'imu_accX'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_accel_y,      'imu_accY'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_accel_z,      'imu_accZ'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_gyro_roll,    'imu_gyroRoll'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_gyro_pitch,   'imu_gyroPitch'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_gyro_yaw,     'imu_gyroYaw'],\n                    ],\n                    value: 'imu_accX', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_value_imu', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_value_sensor:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_pressure_temperature, 'pressure_temperature'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_pressure_pressure,    'pressure_pressure'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_imageflow_positionX,  'imageflow_positionX'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_imageflow_positionY,  'imageflow_positionY'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_range_bottom,         'range_bottom'],\n                    ],\n                    value: 'pressure_temperature', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_value_sensor', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_value_etc:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_state_mode_vehicle,   'state_modeVehicle'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_state_mode_flight,    'state_modeFlight'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_state_battery,        'state_battery'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_irmessage,            'irmessage_irdata'],\n                    ],\n                    value: 'irmessage_irdata', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_value_etc', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_value_button:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_button,   'button_button'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_event,    'button_event'],\n                    ],\n                    value: 'button_button', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_controller_value_button', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_value_joystick:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_x,             'joystick_left_x'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_y,             'joystick_left_y'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_direction,     'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_left_event,         'joystick_left_event'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_x,            'joystick_right_x'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_y,            'joystick_right_y'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_direction,    'joystick_right_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_right_event,        'joystick_right_event'],\n                    ],\n                    value: 'joystick_left_x', // 초기 선택항목 지정\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_controller_value_joystick', // 언어 파일에서 읽어들일 템플릿. 객체 이름과 동일하게\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_monitor', // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_if_button_press:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_left,        '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_right,       '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_front_left_right,  '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up_left,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up_right,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_up,         '16'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_left,       '32'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_right,      '64'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_center_down,       '128'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_left,       '256'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_right,      '512'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_button_bottom_left_right, '768'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_boolean_input',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n                var button = 'button_button'; // paramsKeyMap에 정의된 이름 사용\n                var buttonevent = 'button_event'; // paramsKeyMap에 정의된 이름 사용\n\n                if (\n                    read[button] == script.getField('BUTTON') &&\n                    read[buttonevent] == 2\n                )\n                    return true;\n                else return false;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_if_joystick_direction:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_right, 'joystick_right_direction'],\n                    ],\n                    value: 'joystick_left_direction',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left_up,      '17'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_up,           '18'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right_up,     '20'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left,         '33'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_center,       '34'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right,        '36'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_left_down,    '65'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_down,         '66'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_joystick_direction_right_down,   '68'],\n                    ],\n                    value: '34',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_flight_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                DIRECTION: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_boolean_input',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var read = Entry.hw.portData;\n\n                var device = script.getField('DEVICE'); // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION')) return true;\n                else return false;\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_light_manual_single_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_controller_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x31, 0xff, 0);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_light_color_preset:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_red,        'red'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_green,      'green'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_blue,       'blue'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_yellow,     'yellow'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_magenta,    'magenta'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_cyan,       'cyan'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_white,      'white'],\n                    ],\n                    value: 'red',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_on,     '220'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b25,    '75'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b50,    '125'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b75,    '200'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b100,   '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_petrone_v2_flight_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var mode = 0x12;\n                var interval = parseInt(script.getField('BRIGHTNESS'));\n                var select = script.getField('FLAGS');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'red':     red = 255;  green = 0;    blue = 0;     break;\n                    case 'green':   red = 0;    green = 255;  blue = 0;     break;\n                    case 'blue':    red = 0;    green = 0;    blue = 255;   break;\n                    case 'cyan':    red = 0;    green = 255;  blue = 255;   break;\n                    case 'magenta': red = 255;  green = 0;    blue = 255;   break;\n                    case 'yellow':  red = 255;  green = 255;  blue = 0;     break;\n                    case 'white':   red = 255;  green = 255;  blue = 255;   break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_light_manual_single_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0xFF']},\n                    {type: 'text', params: ['255']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x31, flags, brightness);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_light_color_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'],   // TeamHold             = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'],   // TeamFlicker          = 0x13\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'],   // TeamFlickerDouble    = 0x14\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'],   // TeamDimming          = 0x15\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    null,\n                    {type: 'text', params: ['500']},\n                    null,\n                ],\n                type:\n                    'byrobot_petrone_v2_flight_controller_light_color_input',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n                MODE: 3,\n                INTERVAL: 4,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var mode = 0x12 + parseInt(script.getField('MODE'));\n                var interval = script.getNumberValue('INTERVAL');\n                var red = script.getNumberValue('RED');\n                var green = script.getNumberValue('GREEN');\n                var blue = script.getNumberValue('BLUE');\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_light_color_select:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_sunset,          'sunset'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_cottoncandy,     'cottonCandy'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_muscat,          'muscat'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_strawberrymilk,  'strawberryMilk'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_emerald,         'emerald'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_lavender,        'lavender'],\n                    ],\n                    value: 'sunset',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'], // TeamHold           = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'], // TeamFlicker        = 0x13\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'], // TeamFlickerDouble  = 0x14\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'], // TeamDimming        = 0x15\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['500']},\n                    null\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_light_color_select',\n            },\n            paramsKeyMap: {\n                SELECT: 0,\n                MODE: 1,\n                INTERVAL: 2,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var mode = 0x12 + parseInt(script.getField('MODE'));\n                var interval = script.getNumberValue('INTERVAL');\n                var select = script.getField('SELECT');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'sunset':          red = 255;  green = 100;    blue = 0;   break;\n                    case 'cottonCandy':     red = 20;   green = 250;    blue = 150; break;\n                    case 'muscat':          red = 70;   green = 255;    blue = 0;   break;\n                    case 'strawberryMilk':  red = 150;  green = 60;     blue = 20;  break;\n                    case 'emerald':         red = 0;    green = 255;    blue = 30;  break;\n                    case 'lavender':        red = 80;   green = 0;      blue = 200; break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x31, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_light_manual_single_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_drone_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x30, 0xff, 0);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_light_color_preset:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_eye_red,     'eye_red'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_eye_green,   'eye_green'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_eye_blue,    'eye_blue'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_arm_red,     'arm_red'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_arm_green,   'arm_green'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_manual_arm_blue,    'arm_blue'],\n                    ],\n                    value: 'eye_red',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_on,     '220'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b25,    '75'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b50,    '125'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b75,    '200'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_manual_b100,   '255'],\n                    ],\n                    value: '220',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_petrone_v2_flight_drone_light_color_preset',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_drone_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var mode = 0x12;\n                var interval = parseInt(script.getField('BRIGHTNESS'));\n                var select = script.getField('FLAGS');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'eye_red':     mode = 0x12;    red = 255;  green = 0;    blue = 0;     break;\n                    case 'eye_green':   mode = 0x12;    red = 0;    green = 255;  blue = 0;     break;\n                    case 'eye_blue':    mode = 0x12;    red = 0;    green = 0;    blue = 255;   break;\n                    case 'arm_red':     mode = 0x42;    red = 255;  green = 0;    blue = 0;     break;\n                    case 'arm_green':   mode = 0x42;    red = 0;    green = 255;  blue = 0;     break;\n                    case 'arm_blue':    mode = 0x42;    red = 0;    green = 0;    blue = 255;   break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x30, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_light_manual_single_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0xFF']},\n                    {type: 'text', params: ['255']},\n                    null,\n                ],\n                type:\n                    'byrobot_petrone_v2_flight_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_drone_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_petrone_v2_base.setLightManual(script, 0x30, flags, brightness);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_light_color_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_color_eye, '18'], // EyeHold = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_color_arm, '66'], // ArmHold = 0x42\n                    ],\n                    value: '18',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'], // EyeHold = 0x12,          // ArmHold = 0x42\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'], // EyeFlicker = 0x13,       // ArmFlicker = 0x43\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'], // EyeFlickerDouble = 0x14, // ArmFlickerDouble = 0x44\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'], // EyeDimming = 0x15,       // ArmDimming = 0x45\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    {type: 'text', params: ['255']},\n                    null,\n                    {type: 'text', params: ['500']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_light_color_input',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n                MODESUB: 4,\n                INTERVAL: 5,\n            },\n            class: 'byrobot_petrone_v2_flight_drone_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var mode = parseInt(script.getField('MODE')) + parseInt(script.getField('MODESUB'));\n                var red = script.getNumberValue('RED');\n                var green = script.getNumberValue('GREEN');\n                var blue = script.getNumberValue('BLUE');\n                var interval = script.getNumberValue('INTERVAL');\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x30, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_light_color_select:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_color_eye, '18'], // EyeHold = 0x12\n                        [Lang.Blocks.byrobot_petrone_v2_drone_light_color_arm, '66'], // ArmHold = 0x42\n                    ],\n                    value: '18',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_sunset,          'sunset'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_cottoncandy,     'cottonCandy'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_muscat,          'muscat'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_strawberrymilk,  'strawberryMilk'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_emerald,         'emerald'],\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_color_lavender,        'lavender'],\n                    ],\n                    value: 'sunset',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_hold,             '0'], // EyeHold = 0x12,          // ArmHold = 0x42\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker,          '1'], // EyeFlicker = 0x13,       // ArmFlicker = 0x43\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_flicker_double,   '2'], // EyeFlickerDouble = 0x14, // ArmFlickerDouble = 0x44\n                        [Lang.Blocks.byrobot_petrone_v2_common_light_mode_dimming,          '3'], // EyeDimming = 0x15,       // ArmDimming = 0x45\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {type: 'text', params: ['500']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_light_color_select',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n                SELECT: 1,\n                MODESUB: 2,\n                INTERVAL: 3,\n            },\n            class: 'byrobot_petrone_v2_flight_drone_light',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var mode = parseInt(script.getField('MODE')) + parseInt(script.getField('MODESUB'));\n                var select = script.getField('SELECT');\n                var interval = script.getNumberValue('INTERVAL');\n                var red = 0;\n                var green = 0;\n                var blue = 0;\n\n                switch (select)\n                {\n                    case 'sunset':          red = 255;  green = 100;    blue = 0;   break;\n                    case 'cottonCandy':     red = 20;   green = 250;    blue = 150; break;\n                    case 'muscat':          red = 70;   green = 255;    blue = 0;   break;\n                    case 'strawberryMilk':  red = 150;  green = 60;     blue = 20;  break;\n                    case 'emerald':         red = 0;    green = 255;    blue = 30;  break;\n                    case 'lavender':        red = 80;   green = 0;      blue = 200; break;\n                }\n\n                return Entry.byrobot_petrone_v2_base.setLightModeColor(script, 0x30, mode, interval, red, green, blue);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_clear_all:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_flight_controller_display_clear_all',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayClearAll(script, 0x31, pixel);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_clear:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_display_clear',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n                PIXEL: 4,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayClear(script, 0x31, pixel, false, x, y, width, height);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_invert:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_display_invert',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                return Entry.byrobot_petrone_v2_base.setDisplayInvert(script, 0x31, x, y, width, height);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_draw_point:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_display_draw_point',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                PIXEL: 2,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var pixel = parseInt(script.getField('PIXEL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawPoint(script, 0x31, x, y, pixel);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_draw_line:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_solid,  '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dotted, '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dashed, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    {type: 'text', params: ['96']},\n                    {type: 'text', params: ['48']},\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_display_draw_line',\n            },\n            paramsKeyMap: {\n                X1: 0,\n                Y1: 1,\n                X2: 2,\n                Y2: 3,\n                PIXEL: 4,\n                LINE: 5,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var x1 = script.getNumberValue('X1');\n                var y1 = script.getNumberValue('Y1');\n                var x2 = script.getNumberValue('X2');\n                var y2 = script.getNumberValue('Y2');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var line = parseInt(script.getField('LINE'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawLine(script, 0x31, x1, y1, x2, y2, pixel, line);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_draw_rect:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_on,     '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_solid,  '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dotted, '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_line_dashed, '2'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['16']},\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_display_draw_rect',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n                PIXEL: 4,\n                FLAGFILL: 5,\n                LINE: 6,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var width = script.getNumberValue('WIDTH');\n                var height = script.getNumberValue('HEIGHT');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var flagFill = parseInt(script.getField('FLAGFILL'));\n                var line = parseInt(script.getField('LINE'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawRect(script, 0x31, x, y, width, height, pixel, flagFill, line);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_draw_circle:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_off,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_flagfill_on,     '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['64']},\n                    {type: 'text', params: ['32']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_display_draw_circle',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                RADIUS: 2,\n                PIXEL: 3,\n                FLAGFILL: 4,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var radius = script.getNumberValue('RADIUS');\n                var pixel = parseInt(script.getField('PIXEL'));\n                var flagFill = parseInt(script.getField('FLAGFILL'));\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawCircle(script, 0x31, x, y, radius, pixel, flagFill);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_draw_string:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_5x8,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_10x16,  '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['4']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    {type: 'text', params: ['{Petrone V2}']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_display_draw_string',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                FONT: 2,\n                PIXEL: 3,\n                STRING: 4,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('X');\n                var y = script.getNumberValue('Y');\n                var font = parseInt(script.getField('FONT'));\n                var pixel = parseInt(script.getField('PIXEL'));\n                var string = script.getStringValue('STRING');\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawString(script, 0x31, x, y, font, pixel, string);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_display_draw_string_align:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_left,      '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_center,    '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_align_right,     '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_5x8,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_font_10x16,  '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_black, '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_display_pixel_white, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0']},\n                    {type: 'text', params: ['128']},\n                    {type: 'text', params: ['24']},\n                    null,\n                    null,\n                    null,\n                    {type: 'text', params: ['BYROBOT & U']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_display_draw_string_align',\n            },\n            paramsKeyMap: {\n                XSTART: 0,\n                XEND: 1,\n                Y: 2,\n                ALIGN: 3,\n                FONT: 4,\n                PIXEL: 5,\n                STRING: 6,\n            },\n            class: 'byrobot_petrone_v2_flight_controller_display',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var xStart = script.getNumberValue('XSTART');\n                var xEnd = script.getNumberValue('XEND');\n                var y = script.getNumberValue('Y');\n                var align = parseInt(script.getField('ALIGN'));\n                var font = parseInt(script.getField('FONT'));\n                var pixel = parseInt(script.getField('PIXEL'));\n                var string = script.getStringValue('STRING');\n                return Entry.byrobot_petrone_v2_base.setDisplayDrawStringAlign(script, 0x31, xStart, xEnd, y, align, font, pixel, string);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_buzzer_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_buzzer',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setBuzzerStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_buzzer_scale:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'byrobot_petrone_v2_flight_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_buzzer',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, 60000, false, true);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, 60000, false, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_buzzer_scale_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_flight_buzzer',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, time, true, true);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, time, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_buzzer_scale_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_c,    '0'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_d,    '2'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_e,    '4'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_f,    '5'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_g,    '7'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_a,    '9'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_as,   '10'],\n                        [Lang.Blocks.byrobot_petrone_v2_controller_buzzer_b,    '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_flight_buzzer',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var octave = parseInt(script.getField('OCTAVE'));\n                var scale = parseInt(script.getField('SCALE'));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n\n                if (scale == -1)\n                    return Entry.byrobot_petrone_v2_base.setBuzzerMute(script, time, false, false);\n                else\n                    return Entry.byrobot_petrone_v2_base.setBuzzerScale(script, octave, scale, time, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_buzzer_hz:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_buzzer',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, 60000, false, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_buzzer_hz_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_buzzer',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, time, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_buzzer_hz_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1000']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_buzzer',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var hz = parseInt(script.getNumberValue('HZ', script));\n                var time = parseInt(script.getNumberValue('TIME') * 1000);\n                return Entry.byrobot_petrone_v2_base.setBuzzerHz(script, hz, time, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_vibrator_off:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_vibrator',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setVibratorStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_vibrator_on_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_vibrator',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, 0, timeOn, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_vibrator_on_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_vibrator',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, 0, timeOn, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_vibrator_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0.02']},\n                    {type: 'text', params: ['0.2']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_petrone_v2_flight_vibrator',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, timeOff, timeRun, true, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_controller_vibrator_reserve:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0.02']},\n                    {type: 'text', params: ['0.2']},\n                    {type: 'text', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class: 'byrobot_petrone_v2_flight_vibrator',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var timeOn = parseInt(script.getNumberValue('TIMEON') * 1000);\n                var timeOff = parseInt(script.getNumberValue('TIMEOFF') * 1000);\n                var timeRun = parseInt(script.getNumberValue('TIMERUN') * 1000);\n                return Entry.byrobot_petrone_v2_base.setVibrator(script, timeOn, timeOff, timeRun, false, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_irmessage:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['0']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_irmessage',\n            },\n            paramsKeyMap: {\n                IRMESSAGE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_irmessage',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var irdirection = 0;\n                var irmessage = script.getNumberValue('IRMESSAGE', script);\n                return Entry.byrobot_petrone_v2_base.sendIrMessage(script, irdirection, irmessage);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_motor_stop:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_motor',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.sendStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_motorsingle:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1'], ['3', '2'], ['4', '3']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'text', params: ['3000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_motorsingle',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_motor',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var motorIndex = parseInt(script.getField('MOTORINDEX'));\n                var motorRotation = motorIndex % 2 + 1;\n                var motorSpeed = parseInt(\n                    script.getNumberValue('MOTORSPEED', script)\n                );\n\n                return Entry.byrobot_petrone_v2_base.setMotorSingle(script, motorIndex, motorRotation, motorSpeed);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_motorsingle_input:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'text', params: ['1']},\n                    {type: 'text', params: ['3000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_motorsingle_input',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_motor',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var motorIndex =\n                    parseInt(script.getNumberValue('MOTORINDEX', script)) - 1;\n                var motorRotation = motorIndex % 2 + 1;\n                var motorSpeed = parseInt(\n                    script.getNumberValue('MOTORSPEED', script)\n                );\n\n                return Entry.byrobot_petrone_v2_base.setMotorSingle(script, motorIndex, motorRotation, motorSpeed);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_motorsingle_rotation:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_motor_rotation_clockwise,         '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_motor_rotation_counterclockwise,  '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'text', params: ['3000']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_motorsingle_rotation',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORROTATION: 1,\n                MOTORSPEED: 2,\n            },\n            class: 'byrobot_petrone_v2_flight_motor',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var motorIndex = parseInt(script.getField('MOTORINDEX'));\n                var motorRotation = parseInt(script.getField('MOTORROTATION'));\n                var motorSpeed = parseInt(\n                    script.getNumberValue('MOTORSPEED', script)\n                );\n\n                return Entry.byrobot_petrone_v2_base.setMotorSingle(script, motorIndex, motorRotation, motorSpeed);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_command_mode_vehicle_drone:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_vehicle_flight,           '16'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_vehicle_flight_noguard,   '17'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_vehicle_flight_fpv,       '18'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_flight_drone_command_mode_vehicle_drone',\n            },\n            paramsKeyMap: {\n                VEHICLE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var vehicle = script.getField('VEHICLE');\n                return Entry.byrobot_petrone_v2_base.setModeVehicle(script, vehicle);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_drone_takeoff:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_control_drone_takeoff',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setEventFlight(script, 0x11, 200); // 0x11 : FlightEvent::TakeOff\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_drone_landing:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_control_drone_landing',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.setEventFlight(script, 0x12, 200); // 0x12 : FlightEvent::Landing\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_drone_stop:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_control_drone_stop',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.sendStop(script);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_coordinate:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_coordinate_world, '1'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_coordinate_local, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'byrobot_petrone_v2_flight_drone_control_coordinate',\n            },\n            paramsKeyMap: {\n                COORDINATE: 0,\n            },\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var coordinate = script.getField('COORDINATE');\n                return Entry.byrobot_petrone_v2_base.sendCommand(script, 0x30, 0x20, coordinate);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_drone_reset_heading:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'byrobot_petrone_v2_flight_drone_control_drone_reset_heading',\n            },\n            paramsKeyMap: {},\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                return Entry.byrobot_petrone_v2_base.sendCommand(script, 0x30, 0x22, 0xa0); // 0x22 : CommandType::FlightEvent  // 0xA0 : FlightEvent::ResetHeading\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_quad_one:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_quad_roll,        'control_roll'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_quad_pitch,       'control_pitch'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_quad_yaw,         'control_yaw'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_quad_throttle,    'control_throttle'],\n                    ],\n                    value: 'control_throttle',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'number', params: ['0']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_control_quad_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE: 1,\n            },\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var controlTarget = script.getField('CONTROLTARGET');\n                var value = parseInt(script.getNumberValue('VALUE', script));\n\n                return Entry.byrobot_petrone_v2_base.sendControlQuadSingle(script, controlTarget, value, 0, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_quad_one_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_quad_roll,        'control_roll'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_quad_pitch,       'control_pitch'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_quad_yaw,         'control_yaw'],\n                        [Lang.Blocks.byrobot_petrone_v2_drone_control_quad_throttle,    'control_throttle'],\n                    ],\n                    value: 'control_throttle',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'number', params: ['100']},\n                    {type: 'number', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_control_quad_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE: 1,\n                TIME: 2,\n            },\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var controlTarget = script.getField('CONTROLTARGET');\n                var value = parseInt(script.getNumberValue('VALUE', script));\n                var time = parseInt(script.getNumberValue('TIME', script) * 1000);\n\n                return Entry.byrobot_petrone_v2_base.sendControlQuadSingle(script, controlTarget, value, time, true);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_quad:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['0']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_control_quad',\n            },\n            paramsKeyMap: {\n                ROLL: 0,\n                PITCH: 1,\n                YAW: 2,\n                THROTTLE: 3,\n            },\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var roll = parseInt(script.getNumberValue('ROLL', script));\n                var pitch = parseInt(script.getNumberValue('PITCH', script));\n                var yaw = parseInt(script.getNumberValue('YAW', script));\n                var throttle = parseInt(script.getNumberValue('THROTTLE', script));\n\n                return Entry.byrobot_petrone_v2_base.sendControlQuad(script, roll, pitch, yaw, throttle, 0, false);\n            },\n        },\n\n\n        byrobot_petrone_v2_flight_drone_control_quad_delay:\n        {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Block', accept: 'string'},\n                {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n            ],\n            events: {},\n            def: {\n                params: [\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['1']},\n                    null,\n                ],\n                type: 'byrobot_petrone_v2_flight_drone_control_quad_delay',\n            },\n            paramsKeyMap: {\n                ROLL: 0,\n                PITCH: 1,\n                YAW: 2,\n                THROTTLE: 3,\n                TIME: 4,\n            },\n            class: 'byrobot_petrone_v2_flight_control_flight',\n            isNotFor: ['byrobot_petrone_v2_flight'],\n            func: function(sprite, script) {\n                var roll = parseInt(script.getNumberValue('ROLL', script));\n                var pitch = parseInt(script.getNumberValue('PITCH', script));\n                var yaw = parseInt(script.getNumberValue('YAW', script));\n                var throttle = parseInt(script.getNumberValue('THROTTLE', script));\n                var time = parseInt(script.getNumberValue('TIME', script) * 1000);\n\n                return Entry.byrobot_petrone_v2_base.sendControlQuad(script, roll, pitch, yaw, throttle, time, true);\n            },\n        },\n        /* BYROBOT PetroneV2 Flight End */\n        //endregion byrobot 바이로봇\n    };\n};\n\nmodule.exports = Entry.byrobot_petrone_v2_flight;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_c3coding_arduino.js",
    "content": "'use strict';\n\nEntry.c3coding_arduino = {\n    id: '5C.1',\n    name: 'c3coding_arduino',\n    url: 'https://www.c3coding.com/',\n    imageName: 'c3coding_arduino.png',\n    title: {\n        ko: '씨큐브코딩 아두이노',\n        en: 'C3Coding Arduino',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.c3coding_arduino.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                c3coding_arduino_get_analog_value: '아날로그 %1 번 센서값',\n                c3coding_arduino_toggle_led: '디지털 %1 번 핀 %2 %3',\n                c3coding_arduino_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                c3coding_arduino_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                c3coding_arduino_get_digital: '디지털 %1 번 센서값',\n            },\n        },\n        en: {\n            template: {\n                c3coding_arduino_get_analog_value: 'Analog %1 Sensor value',\n                c3coding_arduino_toggle_led: 'Digital %1 Pin %2 %3',\n                c3coding_arduino_digital_pwm: 'Digital %1 Pin %2 %3',\n                c3coding_arduino_set_servo: 'Set servo pin %1 angle as %2 %3',\n                c3coding_arduino_get_digital: 'Digital %1 Sensor value',\n            },\n        },\n    };\n};\n\nEntry.c3coding_arduino.blockMenuBlocks = [\n    'c3coding_arduino_get_analog_value',\n    'c3coding_arduino_get_digital',\n    'c3coding_arduino_toggle_led',\n    'c3coding_arduino_digital_pwm',\n    'c3coding_arduino_set_servo',\n];\n\nEntry.c3coding_arduino.getBlocks = function () {\n    return {\n        c3coding_arduino_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.c3coding_arduino_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'c3coding_arduino_analog_list',\n                    },\n                ],\n            },\n        },\n        c3coding_arduino_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'c3coding_arduino_analog_list',\n                    },\n                ],\n                type: 'c3coding_arduino_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'c3coding_arduinoGet',\n            isNotFor: ['c3coding_arduino'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        c3coding_arduino_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'c3coding_arduino_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'c3coding_arduinoGet',\n            isNotFor: ['c3coding_arduino'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'c3coding_arduino') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.c3coding_arduino.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        c3coding_arduino_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'c3coding_arduino_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'c3coding_arduino',\n            isNotFor: ['c3coding_arduino'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.c3coding_arduino.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.c3coding_arduino.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.c3coding_arduino.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        c3coding_arduino_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'c3coding_arduino_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'c3coding_arduino',\n            isNotFor: ['c3coding_arduino'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.c3coding_arduino.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        c3coding_arduino_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'c3coding_arduino_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'c3coding_arduino',\n            isNotFor: ['c3coding_arduino'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.c3coding_arduino.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.c3coding_arduino;"
  },
  {
    "path": "src/playground/blocks/hardware/block_castarter_v2.js",
    "content": "'use strict';\r\n\r\nEntry.castarter_v2 = {\r\n    id: ['4D.1','4D.2','4D.3'],\r\n    name: 'castarter_v2',\r\n    url: 'http://codingarray.cc/',\r\n    imageName: 'castarter_v2.png',\r\n    title: {\r\n        ko: '2세대 코딩어레이 스타터',\r\n        en: '2nd Coding Array Starter',\r\n    },\r\n    setZero: function() {\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            let keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach(function(key) {\r\n                Entry.hw.sendQueue.SET[key].data = 0;\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    pins: {},\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO_PIN: 4,\r\n        TONE: 5,\r\n        PULSEIN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n        NEOPIXELINIT: 11,\r\n        NEOPIXELDIS: 12,\r\n        LCDINIT: 14,\r\n        LCD_DIS: 15,\r\n        LCDCLEAR: 16,\r\n        LCDOPTION: 17,\r\n        DHTTEMP: 26,\r\n        DHTHUMI: 27,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    highList: ['high', '1', 'on'],\r\n    lowList: ['low', '0', 'off'],\r\n    duration: {\r\n        TIME_1ms: 1,\r\n        TIME_5ms: 5,\r\n        TIME_10ms: 10,\r\n        TIME_20ms: 20,\r\n        TIME_50ms: 50,\r\n        TIME_100ms: 100,\r\n        TIME_200ms: 200,\r\n        TIME_500ms: 500,\r\n    },\r\n    waitMilliSec(milli) {\r\n        this.blockReq = true;\r\n        setTimeout(() => {\r\n            this.blockReq = false;\r\n        }, milli);\r\n    },\r\n    getOffsetX(str) {\r\n        return this.getByteLength(str) * 1.5 - 5;\r\n    },\r\n    getByteLength(s, b, i, c) {\r\n        for (b = i = 0; (c = s.charCodeAt(i++)); b += c >> 11 ? 3 : c >> 7 ? 2 : 1);\r\n        return b;\r\n    },\r\n    BlockState: {},\r\n};\r\nEntry.castarter_v2.setLanguage = function () {\r\n    return {\r\n        ko: {\r\n            Blocks: {\r\n                led_on: '켜기',\r\n                led_off: '끄기',\r\n                emoticonHeart:'하트',\r\n                emoticonSmile:'웃음',\r\n                emoticonSad:'슬픔',\r\n                emoticonTempsimbol:'온도 이미지',\r\n                emoticonTempsine:'온도 °C 기호',\r\n                emoticonHumisimbol:'습도 이미지',\r\n            },\r\n            template: {\r\n                castarterv2_get_Analog_title:'아날로그 입력',\r\n                castarterv2_get_analog_value: '아날로그 %1번 센서 값 ',\r\n                castarterv2_get_analog_value_map: '아날로그 %1번 센서 (%2~%3)값의 범위를 [%4~%5]으로 바꾼 값',\r\n                castarterv2_get_digital_title:'디지털 입력',\r\n                castarterv2_get_digital_dis: '디지털 %1 번 센서 값 ( LCD에 프린트 )',\r\n                castarterv2_get_digital: '디지털 %1 번 센서 값',\r\n                castarterv2_get_ultrasonic_title:'초음파 센서 값 입력',\r\n                castarterv2_get_ultrasonic_init: '초음파 센서 Trig%1번,  Echo%2번 센서 사용하기 %3 ',\r\n                castarterv2_get_ultrasonic_value: '초음파 센서 값 (Cm) ',\r\n                castarterv2_set_digital_title:'디지털 출력',\r\n                castarterv2_set_toggle_pin: '디지털 %1번을 %2  %3',\r\n                castarterv2_set_digital_pwm: '디지털 %1번을 아날로그 값 %2으로 정하기 %3',\r\n                castarterv2_set_tone_title:'피에조 부저 출력',\r\n                castarterv2_set_tone: '디지털 %1번 부저를 %2%3음으로%4초간 연주하기 %5',\r\n                castarterv2_set_servo_title:'서보 모터 출력',\r\n                castarterv2_set_servo: '디지털 %1번 서보모터를 %2도 각도로 정하기 %3',\r\n                castarterv2_set_analog_rgbled_title:'코딩어레이 RGB LED 아날로그(PWM) 출력',\r\n                castarterv2_set_analog_rgbled: 'RGB LED의 빨강:%1, 초록:%2, 파랑:%3으로 아날로그 값 정하기%4',\r\n                castarterv2_set_neopixel_title:'네오픽셀 RGB LED 출력',\r\n                castarterv2_set_neopixel_init:'디지털%1번에 네오픽셀%2개를 사용하기 %3',\r\n                castarterv2_set_neopixel_dis:'디지털%1번에 네오픽셀%2번째 빨강:%3,녹색:%4,파랑:%5으로 정하기 %6',\r\n                castarterv2_set_i2clcd_title:'I2C 1602 LCD 프린트',\r\n                castarterv2_set_i2clcd_init: 'I2C 1602 LCD 사용하기 %1',\r\n                castarterv2_set_i2clcd_print: 'LCD의%1번째 줄, %2번째 칸에%3 프린트하기 %4',\r\n                castarterv2_set_i2clcd_emotion: 'LCD의%1번째 줄, %2번째 칸에 %3 프린트하기 %4',\r\n                castarterv2_set_i2clcd_clear: 'LCD 화면 모두 지우기 %1',\r\n                castarterv2_set_dht_title:'DHT11 디지털 온도, 습도 센서 입력',\r\n                castarterv2_get_dht_temp_value: 'DHT11 온도 %1 센서의 온도 값',\r\n                castarterv2_get_dht_humi_value: 'DHT11 습도 %1 센서의 습도 값',\r\n                castarterv2_blank_title:' ',\r\n            },\r\n            Helper: { \r\n                castarterv2_get_analog_value: '아날로그 출력 값은 0~1023 까지입니다. LCD에 프린트 할 때는 4자리로 표시합니다.',\r\n                castarterv2_get_analog_value_map: ' ',\r\n                castarterv2_get_digital_dis: ' 디지털 핀 출력 값은 0 또는 1입니다. 이 블럭은 LCD에 디지털 값을 프린트 할 때 사용합니다. ',\r\n                castarterv2_get_digital: ' ',\r\n                castarterv2_get_ultrasonic_init: ' ',\r\n                castarterv2_get_ultrasonic_value: ' ',\r\n                castarterv2_set_toggle_pin: ' ',\r\n                castarterv2_set_digital_pwm: ' 서보모터와 아날로그 출력 블럭은 함께 사용할 수 없습니다.',\r\n                castarterv2_set_tone: ' ',\r\n                castarterv2_set_servo: ' 서보모터와 RGB LED 아날로그 출력 블럭은 함께 사용할 수 없습니다. ',\r\n                castarterv2_set_analog_rgbled: ' 서보모터와 RGB LED 아날로그 출력 블럭은 함께 사용할 수 없습니다.  ',\r\n                castarterv2_set_neopixel_init: ' ',\r\n                castarterv2_set_neopixel_dis: ' ',\r\n                castarterv2_set_i2clcd_init: ' LCD 사용을 위한 블럭입니다. 실행 초기에는 선언하지 않아도 LCD 프린트 블럭을 사용할 수 있습니다. 다만, 아날로그 4번 핀, 5번 핀을 사용 했었다면 이 블럭으로 LCD를 재설정 해줄 필요가 있을 수 있습니다.',\r\n                castarterv2_set_i2clcd_print: ' ',\r\n                castarterv2_set_i2clcd_emotion: ' ',\r\n                castarterv2_set_i2clcd_clear: ' ',\r\n                castarterv2_get_dht_temp_value: ' 온도는 2자리 숫자로 출력 및 표시됩니다.',\r\n                castarterv2_get_dht_humi_value: ' 습도는 2자리 숫자로 출력 및 표시됩니다.',\r\n            },\r\n            Device: {\r\n                castarter_v2: 'castarter_v2',\r\n            },\r\n            Menus: {\r\n                castarter_v2: 'castarter_v2',\r\n            },\r\n        },\r\n        en: {\r\n            Blocks: {\r\n                led_on: 'On',\r\n                led_off: 'Off',\r\n                emoticonHeart:'heart',\r\n                emoticonSmile:'Smile',\r\n                emoticonSad:'Sad',\r\n                emoticonTempsimbol:'Temp simbol',\r\n                emoticonTempsine:'Temp °C sine',\r\n                emoticonHumisimbol:'Humi simbol',\r\n            },\r\n            template: { \r\n                castarterv2_get_Analog_title:'Analog Sensor input',\r\n                castarterv2_get_analog_value: 'Analog %1 Sensor value',\r\n                castarterv2_get_analog_value_map: 'Map analog %1 pin sensor value %2 from %3 ~ %4 to %5 ~ %6',\r\n                castarterv2_get_digital_title:'Digital Sensor input',\r\n                castarterv2_get_digital_dis: 'Digital %1 Sensor value ( LCD Print )',\r\n                castarterv2_get_digital: 'Digital %1 Sensor value',\r\n                castarterv2_get_ultrasonic_title:'Ultrasonic sensor value input',\r\n                castarterv2_get_ultrasonic_init: 'Read ultrasonic sensor trig pin %1 echo pin %2',\r\n                castarterv2_get_ultrasonic_value: ' ultrasonic sensor value (Cm) ',\r\n                castarterv2_set_digital_title:'Digital Sensor output',\r\n                castarterv2_set_toggle_pin: 'Digital %1 Pin %2 %3',\r\n                castarterv2_set_digital_pwm: 'Digital %1 Pin %2 %3',\r\n                castarterv2_set_tone_title:'Piezo buzzer output',\r\n                castarterv2_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\r\n                castarterv2_set_servo_title:'Servo motor output',\r\n                castarterv2_set_servo: 'Set servo pin %1 angle as %2 %3',\r\n                castarterv2_set_analog_rgbled_title:'Coding array RGB LED analog (PWM) output',\r\n                castarterv2_set_analog_rgbled: 'Coding Array RGB LED Red %1 Green %2 Blue %3 %4', \r\n                castarterv2_set_neopixel_title:'NeoPixel RGB LED output',      \r\n                castarterv2_set_neopixel_init:'Digital %1 Pin NeoPixel %2 pixels setting %3',\r\n                castarterv2_set_neopixel_dis:'Digital %1 Pin NeoPixel %2 String red %3 , green %4 , blue %5 %6',\r\n                castarterv2_set_i2clcd_title:'I2C 1602 LCD Print',\r\n                castarterv2_set_i2clcd_init: 'Using LCD %1',\r\n                castarterv2_set_i2clcd_print: 'LCD %1 line, %2 column %3 Print %4',\r\n                castarterv2_set_i2clcd_emotion: 'LCD %1 line, %2 column %3 Print %4',\r\n                castarterv2_set_i2clcd_clear: 'LCD Erase all the screens %1',\r\n                castarterv2_set_dht_title:'Digital temperature, humidity sensor input',\r\n                castarterv2_get_dht_temp_value: 'DHT11 Temperature value',\r\n                castarterv2_get_dht_humi_value: 'DHT11 Humidity value',\r\n                castarterv2_blank_title:' ',\r\n            },\r\n            Helper: { \r\n                castarterv2_get_analog_value: ' ',\r\n                castarterv2_get_analog_value_map: ' ',\r\n                castarterv2_get_digital_dis: ' ',\r\n                castarterv2_get_digital: ' ',\r\n                castarterv2_get_ultrasonic_init: ' ',\r\n                castarterv2_get_ultrasonic_value: ' ',\r\n                castarterv2_set_toggle_pin: ' ',\r\n                castarterv2_set_digital_pwm: ' ',\r\n                castarterv2_set_tone: ' ',\r\n                castarterv2_set_servo: ' ',\r\n                castarterv2_set_analog_rgbled: ' ',\r\n                castarterv2_set_neopixel_init: ' ',\r\n                castarterv2_set_neopixel_dis: ' ',\r\n                castarterv2_set_i2clcd_init: ' ',\r\n                castarterv2_set_i2clcd_print: ' ',\r\n                castarterv2_set_i2clcd_emotion: ' ',\r\n                castarterv2_set_i2clcd_clear: ' ',\r\n                castarterv2_get_dht_temp_value: ' ',\r\n                castarterv2_get_dht_humi_value: ' ',\r\n            },\r\n            Device: {\r\n                castarter_v2: 'castarter_v2',\r\n            },\r\n            Menus: {\r\n                castarter_v2: 'castarter_v2',\r\n            },\r\n        },\r\n    };\r\n};\r\nEntry.castarter_v2.blockMenuBlocks = [\r\n    'castarterv2_get_Analog_title',\r\n    'castarterv2_analog_list',\r\n    'castarterv2_get_analog_value',\r\n    'castarterv2_get_analog_value_map',\r\n    'castarterv2_digital_list',\r\n    'castarterv2_get_digital_title',\r\n    'castarterv2_get_digital',\r\n    'castarterv2_get_digital_dis',\r\n    'castarterv2_get_ultrasonic_title',\r\n    'castarterv2_get_ultrasonic_init',\r\n    'castarterv2_get_ultrasonic_value',\r\n    'castarterv2_set_digital_title',\r\n    'castarterv2_set_toggle_pin',\r\n    'castarterv2_set_digital_pwm',\r\n    'castarterv2_set_tone_title',\r\n    'castarterv2_set_tone',\r\n    'castarterv2_set_servo_title',\r\n    'castarterv2_set_servo',\r\n    'castarterv2_set_analog_rgbled_title',\r\n    'castarterv2_set_analog_rgbled',\r\n    'castarterv2_set_neopixel_title',\r\n    'castarterv2_set_neopixel_init',\r\n    'castarterv2_set_neopixel_dis',\r\n    'castarterv2_set_i2clcd_title',\r\n    'castarter_v2_i2clcd_row',\r\n    'castarter_v2_i2clcd_col',\r\n    'castarterv2_set_i2clcd_init',\r\n    'castarterv2_set_i2clcd_print',\r\n    'castarterv2_set_i2clcd_emotion',\r\n    'castarterv2_set_i2clcd_clear',\r\n    'castarterv2_set_dht_title',\r\n    'castarterv2_get_dht_temp_value',\r\n    'castarterv2_get_dht_humi_value',\r\n    'castarterv2_blank_title',\r\n];\r\nEntry.castarter_v2.getBlocks = function () {\r\n    return {\r\n        castarterv2_get_Analog_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_get_Analog_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_get_Analog_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_get_Analog_title',\r\n            },\r\n            class: 'Analog_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_analog_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A0', '0'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                        ['A3', '3'],\r\n                        ['A4', '4'],\r\n                        ['A5', '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['A0', '0'],\r\n                                    ['A1', '1'],\r\n                                    ['A2', '2'],\r\n                                    ['A3', '3'],\r\n                                    ['A4', '4'],\r\n                                    ['A5', '5'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'castarterv2_analog_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        castarterv2_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_analog_list',\r\n                    },\r\n                ],\r\n                type: 'castarterv2_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'Analog_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {         \r\n                let port = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                if (port[0] === 'A') port = port.substring(1);\r\n                let velue =  ANALOG ? ANALOG[port] || 0 : 0;\r\n                velue = velue + '';\r\n                return velue.length >= 4 ? velue : new Array(4 - velue.length + 1).join(' ') + velue;\r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_get_analog_value(%1)'] },\r\n        },\r\n        castarterv2_get_analog_value_map: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1023',\r\n                    fontSize: 11,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '100',\r\n                    fontSize: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_analog_list',\r\n                    },\r\n                ],\r\n                type: 'castarterv2_get_analog_value_map',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'Analog_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                let port = script.getValue('PORT', script);\r\n                let result = 0;\r\n                let width = 0;\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                if (port[0] === 'A') {\r\n                    port = port.substring(1);\r\n                }\r\n                result = ANALOG ? ANALOG[port] || 0 : 0;\r\n                value2 = Math.min(1023, value2);\r\n                value2 = Math.max(0, value2);             \r\n                value3 = Math.min(1023, value3);\r\n                value3 = Math.max(0, value3);\r\n                let num = value4;\r\n                num = num.toString();\r\n                const value4Digit = num.length;\r\n                num = value5;\r\n                num = num.toString();\r\n                const value5Digit = num.length;\r\n                if(value4Digit > value5Digit) width = value4Digit;\r\n                else width = value5Digit;\r\n                if (value2 > value3) {\r\n                    const swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    const swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n                result = result.toFixed(0);\r\n                result = result + '';\r\n                return result.length >= width ? result : new Array(width - result.length + 1).join(' ') + result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarterv2_get_analog_value_map(%1, %2, %3, %4, %5)'],\r\n            },\r\n        },\r\n        castarterv2_digital_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                        ['12', '12'],\r\n                        ['13', '13'],\r\n                        ['A0', '14'],\r\n                        ['A1', '15'],\r\n                        ['A2', '16'],\r\n                        ['A3', '17'],\r\n                        ['A4', '18'],\r\n                        ['A5', '19'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['2', '2'],\r\n                                    ['3', '3'],\r\n                                    ['4', '4'],\r\n                                    ['5', '5'],\r\n                                    ['6', '6'],\r\n                                    ['7', '7'],\r\n                                    ['8', '8'],\r\n                                    ['9', '9'],\r\n                                    ['10', '10'],\r\n                                    ['11', '11'],\r\n                                    ['12', '12'],\r\n                                    ['13', '13'],\r\n                                    ['A0', '14'],\r\n                                    ['A1', '15'],\r\n                                    ['A2', '16'],\r\n                                    ['A3', '17'],\r\n                                    ['A4', '18'],\r\n                                    ['A5', '19'],\r\n                                ],\r\n                                value: '3',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'castarterv2_digital_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        castarterv2_get_digital_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_get_digital_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_get_digital_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_get_digital_title',\r\n            },\r\n            class: 'Digital_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_get_digital_dis: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['3'],\r\n                    },\r\n                ],\r\n                type: 'castarterv2_get_digital_dis',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'Digital_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const { hwModule = {} } = Entry.hw;\r\n                const { name } = hwModule;\r\n                if (name === 'castarter_v2') {\r\n                    const port = script.getNumberValue('PORT', script);\r\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                    if (!Entry.hw.sendQueue.GET) {\r\n                        Entry.hw.sendQueue.GET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.GET[Entry.castarter_v2.sensorTypes.DIGITAL] = {\r\n                        port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n                }; \r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_get_digital_dis(%1)'] },\r\n        },\r\n        castarterv2_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['3'],\r\n                    },\r\n                ],\r\n                type: 'castarterv2_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'Digital_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const { hwModule = {} } = Entry.hw;\r\n                const { name } = hwModule;\r\n                if (name === 'castarter_v2') {\r\n                    const port = script.getNumberValue('PORT', script);\r\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                    if (!Entry.hw.sendQueue.GET) {\r\n                        Entry.hw.sendQueue.GET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.GET[Entry.castarter_v2.sensorTypes.DIGITAL] = {\r\n                        port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n                }; \r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_get_digital(%1)'] },\r\n        },\r\n        castarterv2_get_ultrasonic_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_get_ultrasonic_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_get_ultrasonic_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_get_ultrasonic_title',\r\n            },\r\n            class: 'Ultrasonic_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_get_ultrasonic_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['4'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'castarterv2_get_ultrasonic_init',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'Ultrasonic_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT1', script);\r\n                const value = script.getNumberValue('PORT2', script);\r\n                if (!script.isStart) {\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n                    const duration = Entry.castarter_v2.duration.TIME_50ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    sq.SET[port] = {\r\n                        type: Entry.castarter_v2.sensorTypes.ULTRASONIC,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function () {\r\n                        script.timeFlag = 0;\r\n                    }, duration);\r\n                    return script;\r\n                }\r\n                else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_get_ultrasonic_init(%1, %2)'] },\r\n        },\r\n        castarterv2_get_ultrasonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'castarterv2_get_ultrasonic_value',\r\n            },\r\n            paramsKeyMap: {\r\n                DISTANCE: 0,\r\n            },\r\n            class: 'Ultrasonic_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const distance = script.getNumberValue('DISTANCE', script);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[distance];\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.castarter_v2.sensorTypes.ULTRASONIC] = {\r\n                    port: distance,\r\n                    time: new Date().getTime(),\r\n                };\r\n                let result = Entry.hw.portData.ULTRASONIC.toFixed(0) || 0;\r\n                let width = 3;\r\n                result = result + '';\r\n                return result.length >= width ? result : new Array(width - result.length + 1).join(' ') + result;\r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_get_ultrasonic_value()'] },\r\n        },\r\n        castarterv2_set_dht_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_set_dht_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_set_dht_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_set_dht_title',\r\n            },\r\n            class: 'Digital_DHT_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_get_dht_temp_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['12'],\r\n                    },\r\n                ],\r\n                type: 'castarterv2_get_dht_temp_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'Digital_DHT_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const port = script.getNumberValue('PORT', script);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[port];\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.castarter_v2.sensorTypes.DHTTEMP] = {\r\n                    port: port,\r\n                    time: new Date().getTime(),\r\n                };\r\n                let result = Entry.hw.portData.DHTTEMP.toFixed(0) || 0;\r\n                let width = 2;\r\n                result = result + '';\r\n                return result.length >= width ? result : new Array(width - result.length + 1).join(' ') + result;\r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_get_dht_temp_value(%1)'] },\r\n        },\r\n        castarterv2_get_dht_humi_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['12'],\r\n                    },\r\n                ],\r\n                type: 'castarterv2_get_dht_humi_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'Digital_DHT_Get',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const port = script.getNumberValue('PORT', script);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[port];\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.castarter_v2.sensorTypes.DHTHUMI] = {\r\n                    port: port,\r\n                    time: new Date().getTime(),\r\n                };\r\n                let result = Entry.hw.portData.DHTHUMI.toFixed(0) || 0;\r\n                let width = 2;\r\n                result = result + '';\r\n                return result.length >= width ? result : new Array(width - result.length + 1).join(' ') + result;\r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_get_dht_humi_value(%1)'] },\r\n        },\r\n        castarter_v2_highlow_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.led_on, 'on'], [Lang.Blocks.led_off, 'off']],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                VELUE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('VELUE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'castarter_v2_highlow_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        castarterv2_set_toggle_pin: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['13'],\r\n                    },\r\n                    {\r\n                        type: 'castarter_v2_highlow_list',\r\n                        params: ['on'],\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'castarterv2_set_toggle_pin',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'Digital_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getValue('VALUE');\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.castarter_v2.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.castarter_v2.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.castarter_v2.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_set_toggle_pin(%1,%2)'] },\r\n        },\r\n        castarterv2_pwm_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['3', '3'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                    ],\r\n                    value: '11',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['3', '3'],\r\n                                    ['5', '5'],\r\n                                    ['6', '6'],\r\n                                    ['9', '9'],\r\n                                    ['10', '10'],\r\n                                    ['11', '11'],\r\n                                ],\r\n                                value: '11',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'castarterv2_pwm_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        castarterv2_set_digital_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_set_digital_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_set_digital_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_set_digital_title',\r\n            },\r\n            class: 'Digital_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_set_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '255',\r\n                    fontSize: 11,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_pwm_list',\r\n                        params: ['11'],\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'castarterv2_set_digital_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'Digital_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n                if (!script.isStart) {\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n                    let duration = Entry.castarter_v2.duration.TIME_50ms;\r\n                        script.isStart = true;\r\n                        script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue.SET[port] = {\r\n                        type: Entry.castarter_v2.sensorTypes.PWM,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script; \r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarter_v2.castarterv2_set_digital_pwm(%1, %2)'],\r\n            },\r\n        },\r\n        castarter_v2_tone_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.silent, '0'],\r\n                                    [Lang.Blocks.do_name, 'C'],\r\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\r\n                                    [Lang.Blocks.re_name, 'D'],\r\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\r\n                                    [Lang.Blocks.mi_name, 'E'],\r\n                                    [Lang.Blocks.fa_name, 'F'],\r\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                                    [Lang.Blocks.sol_name, 'G'],\r\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                                    [Lang.Blocks.la_name, 'A'],\r\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\r\n                                    [Lang.Blocks.si_name, 'B'],\r\n                                ],\r\n                                value: 'C',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'castarter_v2_tone_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        castarter_v2_tone_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarter_v2_tone_value',\r\n                    },\r\n                ],\r\n                type: 'castarter_v2_tone_value',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getNumberValue('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'castarter_v2_tone_value',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        castarter_v2_octave_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'castarter_v2_octave_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        castarterv2_set_tone_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_set_tone_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_set_tone_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_set_tone_title',\r\n            },\r\n            class: 'TONE_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_set_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['6'],\r\n                    },\r\n                    {\r\n                        type: 'castarter_v2_tone_list',\r\n                    },\r\n                    {\r\n                        type: 'castarter_v2_octave_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'castarterv2_set_tone',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NOTE: 1,\r\n                OCTAVE: 2,\r\n                DURATION: 3,\r\n            },\r\n            class: 'TONE_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                if (!script.isStart) {\r\n                    let note = script.getValue('NOTE', script);\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.castarter_v2.toneTable[note];\r\n                    }\r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    } else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n                    let duration = script.getNumberValue('DURATION', script);\r\n                    if (duration < 0) {\r\n                        duration = 0;\r\n                    }\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n                    if (duration === 0) {\r\n                        sq.SET[port] = {\r\n                            type: Entry.castarter_v2.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    } else if (octave > 5) {\r\n                        octave = 5;\r\n                    }\r\n                    let value = 0;\r\n                    if (note != 0) {\r\n                        value = Entry.castarter_v2.toneMap[note][octave];\r\n                    }\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    sq.SET[port] = {\r\n                        type: Entry.castarter_v2.sensorTypes.TONE,\r\n                        data: {\r\n                            value,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    sq.SET[port] = {\r\n                        type: Entry.castarter_v2.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_set_tone(%1,%2,%3,%4)'] },\r\n        },\r\n        castarterv2_set_servo_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_set_servo_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_set_servo_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_set_servo_title',\r\n            },\r\n            class: 'SERVO_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_set_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '90',\r\n                    fontSize: 11,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['13'],\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'castarterv2_set_servo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'SERVO_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                let value = script.getNumberValue('VALUE', script);\r\n                value = Math.min(180, value);\r\n                value = Math.max(1, value);\r\n                if (!script.isStart) {\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n                    let duration = Entry.castarter_v2.duration.TIME_500ms;\r\n                            script.isStart = true;\r\n                            script.timeFlag = 1;\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n                    sq.SET[port] = {\r\n                        type: Entry.castarter_v2.sensorTypes.SERVO_PIN,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script; \r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: ['castarter_v2.castarterv2_set_servo(%1,%2)'] },\r\n        },\r\n        castarterv2_set_analog_rgbled_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_set_analog_rgbled_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_set_analog_rgbled_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_set_analog_rgbled_title',\r\n            },\r\n            class: 'RGBLED_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_set_analog_rgbled: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'castarterv2_set_analog_rgbled',\r\n            },\r\n            paramsKeyMap: {\r\n                R: 0,\r\n                G: 1,\r\n                B: 2,\r\n            },\r\n            class: 'RGBLED_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                let redPWM = script.getNumberValue('R');\r\n                let greenPWM = script.getNumberValue('G');\r\n                let bluePWM = script.getNumberValue('B');\r\n                redPWM = Math.round(redPWM);\r\n                redPWM = Math.max(redPWM, 0);\r\n                redPWM = Math.min(redPWM, 255);\r\n                greenPWM = Math.round(greenPWM);\r\n                greenPWM = Math.max(greenPWM, 0);\r\n                greenPWM = Math.min(greenPWM, 255);\r\n                bluePWM = Math.round(bluePWM);\r\n                bluePWM = Math.max(bluePWM, 0);\r\n                bluePWM = Math.min(bluePWM, 255);\r\n                if (!script.isStart) {\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n                    let duration = Entry.castarter_v2.duration.TIME_100ms;\r\n                        script.isStart = true;\r\n                        script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue.SET[9] = {\r\n                        type: Entry.castarter_v2.sensorTypes.PWM,\r\n                        data: redPWM,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.hw.sendQueue.SET[10] = {\r\n                        type: Entry.castarter_v2.sensorTypes.PWM,\r\n                        data: greenPWM,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.hw.sendQueue.SET[11] = {\r\n                        type: Entry.castarter_v2.sensorTypes.PWM,\r\n                        data: bluePWM,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script; \r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarter_v2.castarterv2_set_analog_rgbled(%1, %2, %3)'],\r\n            },\r\n        },\r\n        castarterv2_set_neopixel_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_set_neopixel_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_set_neopixel_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_set_neopixel_title',\r\n            },\r\n            class: 'NEOPIXEL_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n\t\tcastarterv2_set_neopixel_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    value: '2',\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['8'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['2'],\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'castarterv2_set_neopixel_init',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NUM: 1,\r\n            },\r\n            class: 'NEOPIXEL_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                let value = script.getNumberValue('NUM', script);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n\t\t\t\tif (!script.isStart) {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlet duration = Entry.castarter_v2.duration.TIME_50ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1; \r\n\t\t\t\t\tsq.SET[port] = {\r\n\t\t\t\t\t\t\ttype: Entry.castarter_v2.sensorTypes.NEOPIXELINIT,\r\n\t\t\t\t\t\t\tdata: value,\r\n\t\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script;\r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                } \r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarter_v2.castarterv2_set_neopixel_init(%1, %2)'],\r\n            },\r\n        },\r\n\t\tcastarterv2_set_neopixel_dis: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    value: '0',\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    value: '255',\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    value: '255',\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    value: '255',\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'castarterv2_digital_list',\r\n                        params: ['8'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    null, \r\n                    null, \r\n                    null, \r\n                    null\r\n                ],\r\n                type: 'castarterv2_set_neopixel_dis',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NUM: 1,\r\n\t\t\t\tRED: 2,\r\n\t\t\t\tGREEN: 3,\r\n\t\t\t\tBLUE: 4,\r\n            },\r\n            class: 'NEOPIXEL_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                let num = script.getNumberValue('NUM', script);\r\n\t\t\t\tlet r = script.getNumberValue('RED', script);\r\n\t\t\t\tlet g = script.getNumberValue('GREEN', script);\r\n\t\t\t\tlet b = script.getNumberValue('BLUE', script);\r\n                num = Math.max(num, 1);\r\n                num = Math.min(num, 255);\r\n                r = Math.max(r, 0);\r\n                r = Math.min(r, 255);\r\n                g = Math.max(g, 0);\r\n                g = Math.min(g, 255);\r\n                b = Math.max(b, 0);\r\n                b = Math.min(b, 255);\r\n\t\t\t\tif (!script.isStart) {\r\n\t\t\t\t\tif (!sq.SET) {\r\n\t\t\t\t\t\tsq.SET = {};\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlet duration = Entry.castarter_v2.duration.TIME_50ms;\r\n\t\t\t\t\t\tscript.isStart = true;\r\n\t\t\t\t\t\tscript.timeFlag = 1;\r\n\t\t\t\t\tsq.SET[port] = {\r\n\t\t\t\t\t\ttype: Entry.castarter_v2.sensorTypes.NEOPIXELDIS,\r\n\t\t\t\t\t\tdata: {\r\n\t\t\t\t\t\t\t\tnum: num,\r\n\t\t\t\t\t\t\t\tr: r,\r\n\t\t\t\t\t\t\t\tg: g,\r\n\t\t\t\t\t\t\t\tb: b,\r\n\t\t\t\t\t\t\t  },\r\n\t\t\t\t\t\ttime: new Date().getTime(),\r\n\t\t\t\t\t};\r\n\t\t\t\t\tsetTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration );\r\n                    return script; \r\n\t\t\t\t}\r\n\t\t\t\telse if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarter_v2.castarterv2_set_neopixel_dis(%1, %2, %3, %4, %5)'],\r\n            },\r\n        },\r\n\t\tcastarter_v2_i2clcd_row: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                ROW: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('ROW');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['0', '0'],\r\n                                    ['1', '1'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'castarter_v2_i2clcd_row',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\t\tcastarter_v2_i2clcd_col: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n\t\t\t\t\t\t['2', '2'],\r\n                        ['3', '3'],\r\n\t\t\t\t\t\t['4', '4'],\r\n                        ['5', '5'],\r\n\t\t\t\t\t\t['6', '6'],\r\n                        ['7', '7'],\r\n\t\t\t\t\t\t['8', '8'],\r\n                        ['9', '9'],\r\n\t\t\t\t\t\t['10', '10'],\r\n                        ['11', '11'],\r\n\t\t\t\t\t\t['12', '12'],\r\n                        ['13', '13'],\r\n\t\t\t\t\t\t['14', '14'],\r\n                        ['15', '15'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                COL: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('COL');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['0', '0'],\r\n\t\t\t\t\t\t\t\t\t['1', '1'],\r\n\t\t\t\t\t\t\t\t\t['2', '2'],\r\n\t\t\t\t\t\t\t\t\t['3', '3'],\r\n\t\t\t\t\t\t\t\t\t['4', '4'],\r\n\t\t\t\t\t\t\t\t\t['5', '5'],\r\n\t\t\t\t\t\t\t\t\t['6', '6'],\r\n\t\t\t\t\t\t\t\t\t['7', '7'],\r\n\t\t\t\t\t\t\t\t\t['8', '8'],\r\n\t\t\t\t\t\t\t\t\t['9', '9'],\r\n\t\t\t\t\t\t\t\t\t['10', '10'],\r\n\t\t\t\t\t\t\t\t\t['11', '11'],\r\n\t\t\t\t\t\t\t\t\t['12', '12'],\r\n\t\t\t\t\t\t\t\t\t['13', '13'],\r\n\t\t\t\t\t\t\t\t\t['14', '14'],\r\n\t\t\t\t\t\t\t\t\t['15', '15'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'castarter_v2_i2clcd_col',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        castarterv2_set_i2clcd_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_set_i2clcd_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_set_i2clcd_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_set_i2clcd_title',\r\n            },\r\n            class: 'CLCD_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n        castarterv2_set_i2clcd_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [                \r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'castarterv2_set_i2clcd_init',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'CLCD_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = 0;\r\n                const value = 255;\r\n                if (!script.isStart) {\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n                    const duration = Entry.castarter_v2.duration.TIME_200ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    sq.SET[port] = {\r\n                        type: Entry.castarter_v2.sensorTypes.LCDINIT,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function () {\r\n                        script.timeFlag = 0;\r\n                    }, duration);\r\n                    return script;\r\n                }\r\n                else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarter_v2.castarterv2_set_i2clcd_init()'],\r\n            },\r\n        },\r\n        castarterv2_set_i2clcd_print: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'text',\r\n                    value: 'Coding Array',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'castarter_v2_i2clcd_row',\r\n\t\t\t\t\t\tparams: ['0'],\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'castarter_v2_i2clcd_col',\r\n\t\t\t\t\t\tparams: ['0'],\r\n\t\t\t\t\t},\r\n                    null\r\n                ],\r\n                type: 'castarterv2_set_i2clcd_print',\r\n            },\r\n            paramsKeyMap: {\r\n                ROW: 0,\r\n                COL: 1,\r\n                TEXT: 2,\r\n            },\r\n            class: 'CLCD_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                    const sq = Entry.hw.sendQueue;\r\n                    const row = script.getNumberValue('ROW', script);\r\n                    const column = script.getNumberValue('COL', script);\r\n                    const text = script.getValue('TEXT', script);\r\n                    if (!script.isStart) {\r\n                        if (!sq.SET) {\r\n                            sq.SET = {};\r\n                        }\r\n                        const duration = Entry.castarter_v2.duration.TIME_100ms;\r\n                        script.isStart = true;\r\n                        script.timeFlag = 1;\r\n                        sq.SET[0] = {\r\n                            type: Entry.castarter_v2.sensorTypes.LCD_DIS,\r\n                            data: {\r\n                                row,\r\n                                column,\r\n                                text,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        setTimeout(function() {\r\n                            script.timeFlag = 0;\r\n                        }, duration );\r\n                        return script;\r\n                    }\r\n                    else if (script.timeFlag == 1) {\r\n                        return script;\r\n                    } else {\r\n                        delete script.timeFlag;\r\n                        delete script.isStart;\r\n                        Entry.engine.isContinue = false;\r\n                        return script.callReturn();\r\n                    }\r\n\r\n                },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarter_v2.castarterv2_set_i2clcd_print(%1,%2,%3)'],\r\n            },\r\n        },\r\n        castarterv2_set_i2clcd_emotion: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.emoticonHeart,         '1'],\r\n                        [Lang.Blocks.emoticonSmile,         '2'],\r\n                        [Lang.Blocks.emoticonSad,           '3'],\r\n                        [Lang.Blocks.emoticonTempsimbol,    '4'],\r\n                        [Lang.Blocks.emoticonTempsine,      '5'],\r\n                        [Lang.Blocks.emoticonHumisimbol,    '6'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'castarter_v2_i2clcd_row',\r\n\t\t\t\t\t\tparams: ['0'],\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'castarter_v2_i2clcd_col',\r\n\t\t\t\t\t\tparams: ['0'],\r\n\t\t\t\t\t},\r\n                    null\r\n                ],\r\n                type: 'castarterv2_set_i2clcd_emotion',\r\n            },\r\n            paramsKeyMap: {\r\n                ROW: 0,\r\n                COL: 1,\r\n                TEXT: 2,\r\n            },\r\n            class: 'CLCD_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                    const sq = Entry.hw.sendQueue;\r\n                    let row = script.getNumberValue('ROW', script);\r\n                    let column = script.getNumberValue('COL', script);\r\n                    const text = script.getValue('TEXT', script);\r\n                    if (!script.isStart) {\r\n                        if (!sq.SET) {\r\n                            sq.SET = {};\r\n                        }\r\n                        const duration = Entry.castarter_v2.duration.TIME_100ms;\r\n                        script.isStart = true;\r\n                        script.timeFlag = 1;\r\n                        sq.SET[0] = {\r\n                            type: Entry.castarter_v2.sensorTypes.LCDOPTION,\r\n                            data: {\r\n                                row,\r\n                                column,\r\n                                text,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        }; \r\n                        setTimeout(function() {\r\n                            script.timeFlag = 0;\r\n                        }, duration );\r\n                        return script;\r\n                    }\r\n                    else if (script.timeFlag == 1) {\r\n                        return script;\r\n                    } else {\r\n                        delete script.timeFlag;\r\n                        delete script.isStart;\r\n                        Entry.engine.isContinue = false;\r\n                        return script.callReturn();\r\n                    }\r\n                },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarter_v2.castarterv2_set_i2clcd_emotion(%1,%2,%3)'],\r\n            },\r\n        },        \r\n        castarterv2_set_i2clcd_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [                \r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 11,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'castarterv2_set_i2clcd_clear',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'CLCD_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = 0;\r\n                const value = 1;\r\n                if (!script.isStart) {\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n                    const duration = Entry.castarter_v2.duration.TIME_50ms;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    sq.SET[port] = {\r\n                        type: Entry.castarter_v2.sensorTypes.LCDCLEAR,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function () {\r\n                        script.timeFlag = 0;\r\n                    }, duration);\r\n                    return script;\r\n                }\r\n                else if (script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['castarter_v2.castarterv2_set_i2clcd_clear()'],\r\n            },\r\n        },\r\n        castarterv2_blank_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: this.getOffsetX(Lang.template.castarterv2_blank_title),\r\n                    offsetY: 3,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#d1702a',\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.castarterv2_blank_title,\r\n                    color: '#d1702a',\r\n                    align: 'left',\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'castarterv2_blank_title',\r\n            },\r\n            class: 'CLCD_Set',\r\n            isNotFor: ['castarter_v2'],\r\n            events: {},\r\n        },\r\n    };\r\n};\r\nmodule.exports = Entry.castarter_v2;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_cheese.js",
    "content": "'use strict';\n\nEntry.Cheese = {\n    setZero() {\n        Entry.Robomation.setZero();\n    },\n    afterReceive(pd) {\n        Entry.Robomation.afterReceive(pd, false);\n    },\n    afterSend(sq) {\n        Entry.Robomation.afterSend(sq);\n    },\n    getRobot() {\n        const robot = Entry.Robomation.getRobot('cheese', 0);\n        if (robot) {\n            robot.setMotoring(Entry.hw.sendQueue);\n        }\n        return robot;\n    },\n    id: '2.D',\n    name: 'cheese',\n    url: 'http://www.robomation.net',\n    imageName: 'cheese.png',\n    title: {\n        ko: '치즈 스틱',\n        en: 'Cheese Stick',\n        jp: 'チーズスティック',\n        vn: 'Cheese Stick',\n    },\n    monitorTemplate: () => ({\n        imgPath: 'hw/cheese.png',\n        width: 444,\n        height: 300,\n        listPorts: {\n            accelerationX: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            stepCount: {\n                name: Lang.Blocks.ROBOID_sensor_step_count,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Blocks.ROBOID_monitor_buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: {\n                name: Lang.Blocks.ROBOID_monitor_note,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            inputSa: {\n                name: Lang.Blocks.ROBOID_sensor_input_sa,\n                type: 'input',\n                pos: { x: 199, y: 219 },\n            },\n            inputSb: {\n                name: Lang.Blocks.ROBOID_sensor_input_sb,\n                type: 'input',\n                pos: { x: 305, y: 169 },\n            },\n            inputSc: {\n                name: Lang.Blocks.ROBOID_sensor_input_sc,\n                type: 'input',\n                pos: { x: 400, y: 123 },\n            },\n            inputLa: {\n                name: Lang.Blocks.ROBOID_sensor_input_la,\n                type: 'input',\n                pos: { x: 83, y: 102 },\n            },\n            inputLb: {\n                name: Lang.Blocks.ROBOID_sensor_input_lb,\n                type: 'input',\n                pos: { x: 100, y: 96 },\n            },\n            inputLc: {\n                name: Lang.Blocks.ROBOID_sensor_input_lc,\n                type: 'input',\n                pos: { x: 118, y: 89 },\n            },\n            outputSa: {\n                name: Lang.Blocks.ROBOID_monitor_output_sa,\n                type: 'output',\n                pos: { x: 199, y: 219 },\n            },\n            outputSb: {\n                name: Lang.Blocks.ROBOID_monitor_output_sb,\n                type: 'output',\n                pos: { x: 305, y: 169 },\n            },\n            outputSc: {\n                name: Lang.Blocks.ROBOID_monitor_output_sc,\n                type: 'output',\n                pos: { x: 400, y: 123 },\n            },\n            outputLa: {\n                name: Lang.Blocks.ROBOID_monitor_output_la,\n                type: 'output',\n                pos: { x: 83, y: 102 },\n            },\n            outputLb: {\n                name: Lang.Blocks.ROBOID_monitor_output_lb,\n                type: 'output',\n                pos: { x: 100, y: 96 },\n            },\n            outputLc: {\n                name: Lang.Blocks.ROBOID_monitor_output_lc,\n                type: 'output',\n                pos: { x: 118, y: 89 },\n            },\n            outputMab: {\n                name: Lang.Blocks.ROBOID_monitor_output_mab,\n                type: 'output',\n                pos: { x: 274, y: 26 },\n            },\n            outputMcd: {\n                name: Lang.Blocks.ROBOID_monitor_output_mcd,\n                type: 'output',\n                pos: { x: 305, y: 15 },\n            },\n        },\n        mode: 'both',\n    }),\n};\n\nEntry.Cheese.setLanguage = () => ({\n    ko: {\n        template: {\n            cheese_value: '%1',\n            cheese_boolean: '%1?',\n            cheese_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n            cheese_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n            cheese_change_buzzer_by: '버저 음을 %1 Hz만큼 바꾸기 %2',\n            cheese_set_buzzer_to: '버저 음을 %1 Hz로 정하기 %2',\n            cheese_clear_sound: '소리 끄기 %1',\n            cheese_play_note: '%1 %2 음을 연주하기 %3',\n            cheese_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n            cheese_rest_for: '%1 박자 쉬기 %2',\n            cheese_change_tempo_by: '연주 속도를 %1 BPM만큼 바꾸기 %2',\n            cheese_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n            cheese_set_sound_port_to: '소리 출력을 %1로 정하기 %2',\n            cheese_set_input_mode_to: '포트 %1를 %2 입력으로 정하기 %3',\n            cheese_set_input_range_to: '입력 %1의 범위 %2 ~ %3을(를) %4 ~ %5 소수점 %6으로 정하기 %7',\n            cheese_set_three_input_ranges_to: '입력 %1의 범위 %2 ~ %3 ~ %4을(를) %5 ~ %6 ~ %7 소수점 %8으로 정하기 %9',\n            cheese_analog_input: '입력 %1',\n            cheese_digital_input: '입력 %1 %2 ?',\n            cheese_button_state: '버튼 %1를 %2?',\n            cheese_set_pulse_mode_to: '포트 %1를 %2 입력으로 정하기 %3',\n            cheese_pulse_input: '포트 %1에서 펄스 감지?',\n            cheese_set_digital_output_to: '디지털 출력 %1를 %2(으)로 정하기 %3',\n            cheese_change_pwm_output_by: 'PWM 출력 %1를 %2%만큼 바꾸기 %3',\n            cheese_set_pwm_output_to: 'PWM 출력 %1를 %2%로 정하기 %3',\n            cheese_change_servo_motor_angle_by: '서보 모터 %1의 각도를 %2도만큼 바꾸기 %3',\n            cheese_set_servo_motor_angle_to: '서보 모터 %1의 각도를 %2도로 정하기 %3',\n            cheese_turn_off_servo_motor: '서보 모터 %1 전원 끄기 %2',\n            cheese_change_dc_motor_velocity_by: 'DC 모터 %1의 속도를 %2%만큼 바꾸기 %3',\n            cheese_set_dc_motor_velocity_to: 'DC 모터 %1의 속도를 %2%로 정하기 %3',\n            cheese_stop_dc_motor: 'DC 모터 %1 정지하기 %2',\n            cheese_rotate_step_motor: '스텝 모터 %1 스텝을 속도 %2 스텝/초로 회전하기 %3',\n            cheese_change_step_motor_velocity_by: '스텝 모터의 속도를 %1 스텝/초만큼 바꾸기 %2',\n            cheese_set_step_motor_velocity_to: '스텝 모터의 속도를 %1 스텝/초로 정하기 %2',\n            cheese_stop_off_step_motor: '스텝 모터 %1 %2',\n            cheese_set_step_motor_mode_to: '스텝 모터를 %1 모드로 정하기 %2',\n            cheese_step_count: '스텝 수',\n            cheese_set_led_to_color: 'RGB LED %1을(를) %2 %3으로 정하기 %4',\n            cheese_pick_led_to: 'RGB LED %1을(를) %2로 정하기 %3',\n            cheese_change_led_by_rgb: 'RGB LED %1을(를) R: %2 G: %3 B: %4만큼 바꾸기 %5',\n            cheese_setLed_to_rgb: 'RGB LED %1을(를) R: %2 G: %3 B: %4(으)로 정하기 %5',\n            cheese_clear_led: 'RGB LED %1 끄기 %2',\n            cheese_set_led_type_to: 'RGB LED %1을(를) %2형으로 정하기 %3',\n            cheese_neopixel_set_number_and_type_to: '네오픽셀 LED %1개, %2로 정하기 %3',\n            cheese_neopixel_set_all_leds_to_pattern: '네오픽셀 모든 LED를 %1 패턴으로 정하기 %2',\n            cheese_neopixel_set_all_leds_to_color: '네오픽셀 모든 LED를 %1으로 정하기 %2',\n            cheese_neopixel_pick_all_leds_to: '네오픽셀 모든 LED를 %1로 정하기 %2',\n            cheese_neopixel_change_all_leds_by_rgb: '네오픽셀 모든 LED를 R: %1 G: %2 B: %3만큼 바꾸기 %4',\n            cheese_neopixel_set_all_leds_to_rgb: '네오픽셀 모든 LED를 R: %1 G: %2 B: %3(으)로 정하기 %4',\n            cheese_neopixel_clear_all_leds: '네오픽셀 모든 LED 끄기 %1',\n            cheese_neopixel_set_led_to_color: '네오픽셀 %1번째 LED를 %2으로 정하기 %3',\n            cheese_neopixel_pick_led_to: '네오픽셀 %1번째 LED를 %2로 정하기 %3',\n            cheese_neopixel_change_led_by_rgb: '네오픽셀 %1번째 LED를 R: %2 G: %3 B: %4만큼 바꾸기 %5',\n            cheese_neopixel_set_led_to_rgb: '네오픽셀 %1번째 LED를 R: %2 G: %3 B: %4(으)로 정하기 %5',\n            cheese_neopixel_clear_led: '네오픽셀 %1번째 LED 끄기 %2',\n            cheese_neopixel_set_led_range_to_pattern: '네오픽셀 %1번째부터 %2번째까지의 LED를 %3 패턴으로 정하기 %4',\n            cheese_neopixel_set_led_range_to_color: '네오픽셀 %1번째부터 %2번째까지 %3칸 간격의 LED를 %4으로 정하기 %5',\n            cheese_neopixel_pick_led_range_to: '네오픽셀 %1번째부터 %2번째까지 %3칸 간격의 LED를 %4로 정하기 %5',\n            cheese_neopixel_change_led_range_by_rgb: '네오픽셀 %1번째부터 %2번째까지 %3칸 간격의 LED를 R: %4 G: %5 B: %6만큼 바꾸기 %7',\n            cheese_neopixel_set_led_range_to_rgb: '네오픽셀 %1번째부터 %2번째까지 %3칸 간격의 LED를 R: %4 G: %5 B: %6(으)로 정하기 %7',\n            cheese_neopixel_clear_led_range: '네오픽셀 %1번째부터 %2번째까지 %3칸 간격의 LED 끄기 %4',\n            cheese_neopixel_shift: '네오픽셀 %1칸 이동하기 %2',\n            cheese_neopixel_rotate: '네오픽셀 %1칸 회전하기 %2',\n            cheese_neopixel_change_brightness_by: '네오픽셀 밝기를 %1%만큼 바꾸기 %2',\n            cheese_neopixel_set_brightness_to: '네오픽셀 밝기를 %1%로 정하기 %2',\n            cheese_write_serial: '시리얼 %1 %2 쓰기 %3',\n            cheese_read_serial_until: '시리얼 %1 읽기 %2',\n            cheese_set_serial_port_to: '시리얼 포트를 %1로 정하기 %2',\n            cheese_set_serial_rate_to: '시리얼 속도를 %1Bd로 정하기 %2',\n            cheese_serial_input: '시리얼 입력',\n            cheese_pid_start: '%1 시작하기 %2',\n            cheese_pid_set_range_to: 'PID %1의 범위 %2 ~ %3을(를) %4 ~ %5 소수점 %6으로 정하기 %7',\n            cheese_pid_set_three_ranges_to: 'PID %1의 범위 %2 ~ %3 ~ %4을(를) %5 ~ %6 ~ %7 소수점 %8으로 정하기 %9',\n            cheese_pid_reset_encoder: 'PID 엔코더 값 초기화하기 %1',\n            cheese_pid_input: 'PID %1',\n            cheese_pid_button_state: 'PID 버튼 %1을(를) %2?',\n            cheese_hat010_start: 'HAT-010 5x5 매트릭스 시작하기 %1',\n            cheese_hat010_button: 'HAT-010 버튼 %1',\n            cheese_hat010_button_state: 'HAT-010 버튼 %1를 %2?',\n            cheese_hat010_background_turn_on_xy: 'HAT-010 배경 x: %1 y: %2 %3으로 켜기 %4',\n            cheese_hat010_background_turn_off_xy: 'HAT-010 배경 x: %1 y: %2 끄기 %3',\n            cheese_hat010_background_draw_shape_at_xy: 'HAT-010 배경 %1 %2을(를) x: %3 y: %4에 그리기 %5',\n            cheese_hat010_background_draw_string_at_xy: 'HAT-010 배경 %1 글자 %2을(를) x: %3 y: %4에 그리기 %5',\n            cheese_hat010_background_draw_pattern_at_xy: 'HAT-010 배경 %1 패턴 %2을(를) x: %3 y: %4에 그리기 %5',\n            cheese_hat010_clear: 'HAT-010 %1 지우기 %2',\n            cheese_hat010_scroll_by_xy: 'HAT-010 %1 x: %2 y: %3만큼 이동하기 %4',\n            cheese_hat010_sprite_set_to_shape: 'HAT-010 그림 %1을(를) %2 %3(으)로 정하기 %4',\n            cheese_hat010_sprite_set_to_string: 'HAT-010 그림 %1을(를) %2 글자 %3(으)로 정하기 %4',\n            cheese_hat010_sprite_set_to_pattern: 'HAT-010 그림 %1을(를) %2 패턴 %3(으)로 정하기 %4',\n            cheese_hat010_sprite_clear_show_hide: 'HAT-010 그림 %1 %2 %3',\n            cheese_hat010_sprite_change_positions_by_xy: 'HAT-010 그림 %1의 위치를 x: %2 y: %3만큼 바꾸기 %4',\n            cheese_hat010_sprite_set_positions_to_xy: 'HAT-010 그림 %1의 위치를 x: %2 y: %3(으)로 정하기 %4',\n            cheese_hat010_sprite_change_position_by_value: 'HAT-010 그림 %1의 %2 위치를 %3만큼 바꾸기 %4',\n            cheese_hat010_sprite_set_position_to_value: 'HAT-010 그림 %1의 %2 위치를 %3(으)로 정하기 %4',\n            cheese_hat010_sprite_rotate: 'HAT-010 그림 %1을(를) %2 방향으로 회전하기 %3',\n            cheese_hat010_sprite_flip_in_direction: 'HAT-010 그림 %1을(를) %2 방향으로 뒤집기 %3',\n            cheese_hat010_sprite_stamp_to_background: 'HAT-010 그림 %1을(를) 배경에 도장 찍기 %2',\n            cheese_hat010_sprite_position: 'HAT-010 그림 %1의 %2 위치',\n            cheese_hat010_sprite_touching_sprite: 'HAT-010 그림 %1이(가) 그림 %2에 닿았는가?',\n            cheese_hat010_sprite_touching: 'HAT-010 그림 %1이(가) %2에 닿았는가?',\n            cheese_hat010_change_brightness_by: 'HAT-010 밝기를 %1%만큼 바꾸기 %2',\n            cheese_hat010_set_brightness_to: 'HAT-010 밝기를 %1%로 정하기 %2',\n        },\n        Helper: {\n        },\n        Blocks: {\n            ROBOID_sensor_signal_strength: '신호 세기',\n            ROBOID_sensor_signal_strength_dbm: '신호 세기 (dBm)',\n            ROBOID_sensor_acceleration_x: 'x축 가속도',\n            ROBOID_sensor_acceleration_y: 'y축 가속도',\n            ROBOID_sensor_acceleration_z: 'z축 가속도',\n            ROBOID_sensor_input_sa: '입력 Sa',\n            ROBOID_sensor_input_sb: '입력 Sb',\n            ROBOID_sensor_input_sc: '입력 Sc',\n            ROBOID_sensor_input_la: '입력 La',\n            ROBOID_sensor_input_lb: '입력 Lb',\n            ROBOID_sensor_input_lc: '입력 Lc',\n            ROBOID_sensor_step_count: '스텝 수',\n            ROBOID_monitor_output_sa: '출력 Sa',\n            ROBOID_monitor_output_sb: '출력 Sb',\n            ROBOID_monitor_output_sc: '출력 Sc',\n            ROBOID_monitor_output_la: '출력 La',\n            ROBOID_monitor_output_lb: '출력 Lb',\n            ROBOID_monitor_output_lc: '출력 Lc',\n            ROBOID_monitor_output_mab: '출력 Mab',\n            ROBOID_monitor_output_mcd: '출력 Mcd',\n            ROBOID_monitor_buzzer: '버저',\n            ROBOID_monitor_note: '음표',\n            ROBOID_logo_sky_direction: '로고가 하늘 방향',\n            ROBOID_logo_earth_direction: '로고가 땅 방향',\n            ROBOID_power_switch_sky_direction: '전원 스위치가 하늘 방향',\n            ROBOID_power_switch_earth_direction: '전원 스위치가 땅 방향',\n            ROBOID_port_s_sky_direction: '포트 S가 하늘 방향',\n            ROBOID_port_s_earth_direction: '포트 S가 땅 방향',\n            ROBOID_tap: '두드림',\n            ROBOID_free_fall: '자유 낙하',\n            ROBOID_battery_normal: '배터리 정상',\n            ROBOID_battery_low: '배터리 부족',\n            ROBOID_battery_empty: '배터리 없음',\n            ROBOID_sound_beep: '삐',\n            ROBOID_sound_random_beep: '무작위 삐',\n            ROBOID_sound_noise: '지지직',\n            ROBOID_sound_siren: '사이렌',\n            ROBOID_sound_engine: '엔진',\n            ROBOID_sound_chop: '쩝',\n            ROBOID_sound_robot: '로봇',\n            ROBOID_sound_dibidibidip: '디비디비딥',\n            ROBOID_sound_good_job: '잘 했어요',\n            ROBOID_sound_happy: '행복',\n            ROBOID_sound_angry: '화남',\n            ROBOID_sound_sad: '슬픔',\n            ROBOID_sound_sleep: '졸림',\n            ROBOID_sound_march: '행진',\n            ROBOID_sound_birthday: '생일',\n            ROBOID_note_c: '도',\n            ROBOID_note_c_sharp: '도♯(레♭)',\n            ROBOID_note_d: '레',\n            ROBOID_note_d_sharp: '레♯(미♭)',\n            ROBOID_note_e: '미',\n            ROBOID_note_f: '파',\n            ROBOID_note_f_sharp: '파♯(솔♭)',\n            ROBOID_note_g: '솔',\n            ROBOID_note_g_sharp: '솔♯(라♭)',\n            ROBOID_note_a: '라',\n            ROBOID_note_a_sharp: '라♯(시♭)',\n            ROBOID_note_b: '시',\n            ROBOID_speaker_internal: '내부 스피커',\n            ROBOID_speaker_port_mab: '포트 Mab',\n            ROBOID_io_mode_makey: '메이키',\n            ROBOID_io_mode_button: '버튼',\n            ROBOID_io_mode_digital_pull_up: '디지털 (풀업)',\n            ROBOID_io_mode_digital_pull_down: '디지털 (풀다운)',\n            ROBOID_io_mode_analog: '아날로그',\n            ROBOID_io_mode_voltage: '전압',\n            ROBOID_io_mode_pulse: '펄스',\n            ROBOID_io_mode_pulse_pull_up: '펄스 (풀업)',\n            ROBOID_io_mode_pulse_pull_down: '펄스 (풀다운)',\n            ROBOID_io_mode_normal: '기본',\n            ROBOID_io_mode_power: '파워',\n            ROBOID_io_port_high_current_mab: '고전류 Ma(-)b',\n            ROBOID_io_port_high_current_mcd: '고전류 Mc(-)d',\n            ROBOID_io_action_stop: '정지하기',\n            ROBOID_io_action_turn_off: '전원 끄기',\n            ROBOID_range_integer: '없음',\n            ROBOID_range_real: '있음',\n            ROBOID_led_intensity_dark: '어두운',\n            ROBOID_led_intensity_normal: '기본',\n            ROBOID_led_intensity_bright: '밝은',\n            ROBOID_led_type_default: '기본',\n            ROBOID_led_type_crgb: '-RGB',\n            ROBOID_led_type_crbg: '-RBG',\n            ROBOID_led_type_cgrb: '-GRB',\n            ROBOID_led_type_cgbr: '-GBR',\n            ROBOID_led_type_cbrg: '-BRG',\n            ROBOID_led_type_cbgr: '-BGR',\n            ROBOID_led_type_argb: '+RGB',\n            ROBOID_led_type_arbg: '+RBG',\n            ROBOID_led_type_agrb: '+GRB',\n            ROBOID_led_type_agbr: '+GBR',\n            ROBOID_led_type_abrg: '+BRG',\n            ROBOID_led_type_abgr: '+BGR',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_orange: '주황색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_violet: '보라색',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_neopixel_3_colors: '3색',\n            ROBOID_neopixel_6_colors: '6색',\n            ROBOID_neopixel_12_colors: '12색',\n            ROBOID_neopixel_red_green: '빨간색부터 초록색까지',\n            ROBOID_neopixel_red_blue: '빨간색부터 파란색까지',\n            ROBOID_neopixel_red_white: '빨간색부터 하얀색까지',\n            ROBOID_neopixel_green_red: '초록색부터 빨간색까지',\n            ROBOID_neopixel_green_blue: '초록색부터 파란색까지',\n            ROBOID_neopixel_green_white: '초록색부터 하얀색까지',\n            ROBOID_neopixel_blue_red: '파란색부터 빨간색까지',\n            ROBOID_neopixel_blue_green: '파란색부터 초록색까지',\n            ROBOID_neopixel_blue_white: '파란색부터 하얀색까지',\n            ROBOID_neopixel_white_red: '하얀색부터 빨간색까지',\n            ROBOID_neopixel_white_green: '하얀색부터 초록색까지',\n            ROBOID_neopixel_white_blue: '하얀색부터 파란색까지',\n            ROBOID_neopixel_red_black: '빨간색 점점 어둡게',\n            ROBOID_neopixel_green_black: '초록색 점점 어둡게',\n            ROBOID_neopixel_blue_black: '파란색 점점 어둡게',\n            ROBOID_neopixel_white_black: '하얀색 점점 어둡게',\n            ROBOID_neopixel_black_red: '빨간색 점점 밝게',\n            ROBOID_neopixel_black_green: '초록색 점점 밝게',\n            ROBOID_neopixel_black_blue: '파란색 점점 밝게',\n            ROBOID_neopixel_black_white: '하얀색 점점 밝게',\n            ROBOID_serial_string: '글자',\n            ROBOID_serial_string_line: '글자 한 줄',\n            ROBOID_serial_all: '모두',\n            ROBOID_serial_until_comma: ',(쉼표)까지',\n            ROBOID_serial_until_colon: ':(쌍점)까지',\n            ROBOID_serial_until_dollar: '$까지',\n            ROBOID_serial_until_sharp: '#까지',\n            ROBOID_serial_until_new_line: '줄 바꿈까지',\n            ROBOID_serial_port_wa_rb: 'La(쓰기) Lb(읽기)',\n            ROBOID_serial_port_ra_wb: 'La(읽기) Lb(쓰기)',\n            ROBOID_serial_port_wa: 'La(쓰기)',\n            ROBOID_serial_port_ra: 'La(읽기)',\n            ROBOID_pid_10: 'PID-10 초음파 센서(HC-SR04+)',\n            ROBOID_pid_11_1: 'PID-11-1 온습도 센서(DHT11)',\n            ROBOID_pid_11_2: 'PID-11-2 온습도 센서(DHT21)',\n            ROBOID_pid_11_3: 'PID-11-3 온습도 센서(DHT22)',\n            ROBOID_pid_12: 'PID-12 온도 센서(DS18B20)',\n            ROBOID_pid_13: 'PID-13 조이스틱과 버튼',\n            ROBOID_pid_14: 'PID-14 듀얼 조이스틱',\n            ROBOID_pid_15: 'PID-15 IR 송수신기',\n            ROBOID_pid_16: 'PID-16 엔코더',\n            ROBOID_pid_distance: '거리 (cm)',\n            ROBOID_pid_temperature: '온도 (℃)',\n            ROBOID_pid_humidity: '습도 (%RH)',\n            ROBOID_pid_x1: 'x1',\n            ROBOID_pid_y1: 'y1',\n            ROBOID_pid_x2: 'x2',\n            ROBOID_pid_y2: 'y2',\n            ROBOID_pid_button1: '버튼1',\n            ROBOID_pid_button2: '버튼2',\n            ROBOID_pid_encoder: '엔코더',\n            ROBOID_clicked: '클릭했는가',\n            ROBOID_double_clicked: '더블클릭했는가',\n            ROBOID_long_pressed: '오래 눌렀는가',\n            ROBOID_shape_square: '사각형',\n            ROBOID_shape_triangle: '삼각형',\n            ROBOID_shape_diamond: '다이아몬드',\n            ROBOID_shape_circle: '원',\n            ROBOID_shape_x: 'X',\n            ROBOID_shape_like: '좋음',\n            ROBOID_shape_dislike: '싫음',\n            ROBOID_shape_angry: '화남',\n            ROBOID_shape_open_mouth: '입 열기',\n            ROBOID_shape_close_mouth: '입 닫기',\n            ROBOID_shape_walk1: '걷기 1',\n            ROBOID_shape_walk2: '걷기 2',\n            ROBOID_shape_heart: '하트',\n            ROBOID_shape_star: '별',\n            ROBOID_shape_airplane: '비행기',\n            ROBOID_shape_puppy: '강아지',\n            ROBOID_shape_butterfly: '나비',\n            ROBOID_shape_quarter_note: '4분 음표',\n            ROBOID_shape_eighth_note: '8분 음표',\n            ROBOID_shape_left_arrow: '왼쪽 화살표',\n            ROBOID_shape_right_arrow: '오른쪽 화살표',\n            ROBOID_shape_up_arrow: '위쪽 화살표',\n            ROBOID_shape_down_arrow: '아래쪽 화살표',\n            ROBOID_hat_background: '배경',\n            ROBOID_hat_all: '모두',\n            ROBOID_hat_clear: '지우기',\n            ROBOID_hat_show: '보이기',\n            ROBOID_hat_hide: '숨기기',\n            ROBOID_hat_clockwise: '시계',\n            ROBOID_hat_counterclockwise: '반시계',\n            ROBOID_hat_left_right: '왼쪽-오른쪽',\n            ROBOID_hat_up_down: '위-아래',\n            ROBOID_hat_auto: '자동',\n            ROBOID_hat_manual: '수동',\n            ROBOID_hat_other_sprite: '다른 그림',\n            ROBOID_hat_left_wall: '왼쪽 벽',\n            ROBOID_hat_right_wall: '오른쪽 벽',\n            ROBOID_hat_top_wall: '위쪽 벽',\n            ROBOID_hat_bottom_wall: '아래쪽 벽',\n            ROBOID_hat_any_wall: '아무 벽',\n        },\n    },\n    en: {\n        template: {\n            cheese_value: '%1',\n            cheese_boolean: '%1?',\n            cheese_play_sound_times: 'play sound %1 %2 times %3',\n            cheese_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            cheese_change_buzzer_by: 'change buzzer by %1 Hz %2',\n            cheese_set_buzzer_to: 'set buzzer to %1 Hz %2',\n            cheese_clear_sound: 'clear sound %1',\n            cheese_play_note: 'play note %1 %2 %3',\n            cheese_play_note_for: 'play note %1 %2 for %3 beats %4',\n            cheese_rest_for: 'rest for %1 beats %2',\n            cheese_change_tempo_by: 'change tempo by %1 BPM %2',\n            cheese_set_tempo_to: 'set tempo to %1 BPM %2',\n            cheese_set_sound_port_to: 'set sound output to %1 %2',\n            cheese_set_input_mode_to: 'set port %1 to %2 input %3',\n            cheese_set_input_range_to: 'set input %1 range %2 - %3 to %4 - %5 %6 decimal point %7',\n            cheese_set_three_input_ranges_to: 'set input %1 range %2 - %3 - %4 to %5 - %6 - %7 %8 decimal point %9',\n            cheese_analog_input: 'input %1',\n            cheese_digital_input: 'input %1 %2 ?',\n            cheese_button_state: 'button %1 %2 ?',\n            cheese_set_pulse_mode_to: 'set port %1 to %2 input %3',\n            cheese_pulse_input: 'pulse detected on port %1 ?',\n            cheese_set_digital_output_to: 'set digital output %1 to %2 %3',\n            cheese_change_pwm_output_by: 'change pwm output %1 by %2% %3',\n            cheese_set_pwm_output_to: 'set pwm output %1 to %2% %3',\n            cheese_change_servo_motor_angle_by: 'change servo motor %1 by %2 degrees %3',\n            cheese_set_servo_motor_angle_to: 'set servo motor %1 to %2 degrees %3',\n            cheese_turn_off_servo_motor: 'turn off servo motor %1 %2',\n            cheese_change_dc_motor_velocity_by: 'change dc motor %1 velocity by %2% %3',\n            cheese_set_dc_motor_velocity_to: 'set dc motor %1 velocity to %2% %3',\n            cheese_stop_dc_motor: 'stop dc motor %1 %2',\n            cheese_rotate_step_motor: 'rotate step motor %1 steps with velocity %2 step/sec %3',\n            cheese_change_step_motor_velocity_by: 'change step motor velocity by %1 step/sec %2',\n            cheese_set_step_motor_velocity_to: 'set step motor velocity to %1 step/sec %2',\n            cheese_stop_off_step_motor: '%1 step motor %2',\n            cheese_set_step_motor_mode_to: 'set step motor to %1 mode %2',\n            cheese_step_count: 'step count',\n            cheese_set_led_to_color: 'set rgb led %1 to %2 %3 %4',\n            cheese_pick_led_to: 'set rgb led %1 to %2 %3',\n            cheese_change_led_by_rgb: 'change rgb led %1 by r: %2 g: %3 b: %4 %5',\n            cheese_setLed_to_rgb: 'set rgb led %1 to r: %2 g: %3 b: %4 %5',\n            cheese_clear_led: 'clear rgb led %1 %2',\n            cheese_set_led_type_to: 'set rgb led %1 to %2 type %3',\n            cheese_neopixel_set_number_and_type_to: 'neopixel: set %1 leds as %2 %3',\n            cheese_neopixel_set_all_leds_to_color: 'neopixel: set all leds to %1 %2',\n            cheese_neopixel_pick_all_leds_to: 'neopixel: set all leds to %1 %2',\n            cheese_neopixel_change_all_leds_by_rgb: 'neopixel: change all leds by r: %1 g: %2 b: %3 %4',\n            cheese_neopixel_set_all_leds_to_rgb: 'neopixel: set all leds to r: %1 g: %2 b: %3 %4',\n            cheese_neopixel_set_all_leds_to_pattern: 'neopixel: set all leds to pattern %1 %2',\n            cheese_neopixel_clear_all_leds: 'neopixel: clear all leds %1',\n            cheese_neopixel_set_led_to_color: 'neopixel: set led %1 to %2 %3',\n            cheese_neopixel_pick_led_to: 'neopixel: set led %1 to %2 %3',\n            cheese_neopixel_change_led_by_rgb: 'neopixel: change led %1 by r: %2 g: %3 b: %4 %5',\n            cheese_neopixel_set_led_to_rgb: 'neopixel: set led %1 to r: %2 g: %3 b: %4 %5',\n            cheese_neopixel_clear_led: 'neopixel: clear led %1 %2',\n            cheese_neopixel_set_led_range_to_color: 'neopixel: set leds (from %1 to %2 with %3 increments) to %4 %5',\n            cheese_neopixel_pick_led_range_to: 'neopixel: set leds (from %1 to %2 with %3 increments) to %4 %5',\n            cheese_neopixel_change_led_range_by_rgb: 'neopixel: change leds (from %1 to %2 with %3 increments) by r: %4 g: %5 b: %6 %7',\n            cheese_neopixel_set_led_range_to_rgb: 'neopixel: set leds (from %1 to %2 with %3 increments) to r: %4 g: %5 b: %6 %7',\n            cheese_neopixel_set_led_range_to_pattern: 'neopixel: set leds (from %1 to %2) to pattern %3 %4',\n            cheese_neopixel_clear_led_range: 'neopixel: clear leds (from %1 to %2 with %3 increments) %4',\n            cheese_neopixel_shift: 'neopixel: shift %1 pixels %2',\n            cheese_neopixel_rotate: 'neopixel: rotate %1 pixels %2',\n            cheese_neopixel_change_brightness_by: 'neopixel: change brightness by %1% %2',\n            cheese_neopixel_set_brightness_to: 'neopixel: set brightness to %1% %2',\n            cheese_write_serial: 'write %1 %2 to serial %3',\n            cheese_read_serial_until: 'read serial %1 %2',\n            cheese_set_serial_port_to: 'set serial port to %1 %2',\n            cheese_set_serial_rate_to: 'set serial rate to %1Bd %2',\n            cheese_serial_input: 'serial input',\n            cheese_pid_start: 'start %1 %2',\n            cheese_pid_set_range_to: 'PID: set %1 range %2 - %3 to %4 - %5 %6 decimal point %7',\n            cheese_pid_set_three_ranges_to: 'PID: set %1 range %2 - %3 - %4 to %5 - %6 - %7 %8 decimal point %9',\n            cheese_pid_reset_encoder: 'PID: clear encoder %1',\n            cheese_pid_input: 'PID: %1',\n            cheese_pid_button_state: 'PID: button %1 %2?',\n            cheese_hat010_start: 'start HAT-010 5x5 matrix %1',\n            cheese_hat010_button: 'HAT-010: button %1',\n            cheese_hat010_button_state: 'HAT-010: button %1 %2?',\n            cheese_hat010_background_turn_on_xy: 'HAT-010 background: turn on x: %1 y: %2 in %3 %4',\n            cheese_hat010_background_turn_off_xy: 'HAT-010 background: turn off x: %1 y: %2 %3',\n            cheese_hat010_background_draw_shape_at_xy: 'HAT-010 background: draw %1 %2 at x: %3 y: %4 %5',\n            cheese_hat010_background_draw_string_at_xy: 'HAT-010 background: draw %1 string %2 at x: %3 y: %4 %5',\n            cheese_hat010_background_draw_pattern_at_xy: 'HAT-010 background: draw %1 pattern %2 at x: %3 y: %4 %5',\n            cheese_hat010_clear: 'HAT-010: clear %1 %2',\n            cheese_hat010_scroll_by_xy: 'HAT-010: scroll %1 by x: %2 y: %3 %4',\n            cheese_hat010_sprite_set_to_shape: 'HAT-010 sprite %1: set sprite to %2 %3 %4',\n            cheese_hat010_sprite_set_to_string: 'HAT-010 sprite %1: set sprite to %2 string %3 %4',\n            cheese_hat010_sprite_set_to_pattern: 'HAT-010 sprite %1: set sprite to %2 pattern %3 %4',\n            cheese_hat010_sprite_clear_show_hide: 'HAT-010 sprite %1: %2 sprite %3',\n            cheese_hat010_sprite_change_positions_by_xy: 'HAT-010 sprite %1: change position by x: %2 y: %3 %4',\n            cheese_hat010_sprite_set_positions_to_xy: 'HAT-010 sprite %1: set position to x: %2 y: %3 %4',\n            cheese_hat010_sprite_change_position_by_value: 'HAT-010 sprite %1: change %2 position by %3 %4',\n            cheese_hat010_sprite_set_position_to_value: 'HAT-010 sprite %1: set %2 position to %3 %4',\n            cheese_hat010_sprite_rotate: 'HAT-010 sprite %1: rotate %2 %3',\n            cheese_hat010_sprite_flip_in_direction: 'HAT-010 sprite %1: flip in %2 direction %3',\n            cheese_hat010_sprite_stamp_to_background: 'HAT-010 sprite %1: stamp to background %2',\n            cheese_hat010_sprite_position: 'HAT-010 sprite %1: %2 position',\n            cheese_hat010_sprite_touching_sprite: 'HAT-010 sprite %1: touching sprite %2?',\n            cheese_hat010_sprite_touching: 'HAT-010 sprite %1: touching %2?',\n            cheese_hat010_change_brightness_by: 'HAT-010: change brightness by %1% %2',\n            cheese_hat010_set_brightness_to: 'HAT-010: set brightness to %1% %2',\n        },\n        Helper: {\n        },\n        Blocks: {\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_signal_strength_dbm: 'signal strength (dBm)',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_input_sa: 'input Sa',\n            ROBOID_sensor_input_sb: 'input Sb',\n            ROBOID_sensor_input_sc: 'input Sc',\n            ROBOID_sensor_input_la: 'input La',\n            ROBOID_sensor_input_lb: 'input Lb',\n            ROBOID_sensor_input_lc: 'input Lc',\n            ROBOID_sensor_step_count: 'step count',\n            ROBOID_monitor_output_sa: 'output Sa',\n            ROBOID_monitor_output_sb: 'output Sb',\n            ROBOID_monitor_output_sc: 'output Sc',\n            ROBOID_monitor_output_la: 'output La',\n            ROBOID_monitor_output_lb: 'output Lb',\n            ROBOID_monitor_output_lc: 'output Lc',\n            ROBOID_monitor_output_mab: 'output Mab',\n            ROBOID_monitor_output_mcd: 'output Mcd',\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_logo_sky_direction: 'logo in sky direction',\n            ROBOID_logo_earth_direction: 'logo in earth direction',\n            ROBOID_power_switch_sky_direction: 'power switch in sky direction',\n            ROBOID_power_switch_earth_direction: 'power switch in earth direction',\n            ROBOID_port_s_sky_direction: 'port S in sky direction',\n            ROBOID_port_s_earth_direction: 'port S in earth direction',\n            ROBOID_tap: 'tap',\n            ROBOID_free_fall: 'free fall',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n            ROBOID_speaker_internal: 'internal speaker',\n            ROBOID_speaker_port_mab: 'port Mab',\n            ROBOID_io_mode_makey: 'makey',\n            ROBOID_io_mode_button: 'button',\n            ROBOID_io_mode_digital_pull_up: 'digital (pull up)',\n            ROBOID_io_mode_digital_pull_down: 'digital (pull down)',\n            ROBOID_io_mode_analog: 'analog',\n            ROBOID_io_mode_voltage: 'voltage',\n            ROBOID_io_mode_pulse: 'pulse',\n            ROBOID_io_mode_pulse_pull_up: 'pulse (pull up)',\n            ROBOID_io_mode_pulse_pull_down: 'pulse (pull down)',\n            ROBOID_io_mode_normal: 'normal',\n            ROBOID_io_mode_power: 'power',\n            ROBOID_io_port_high_current_mab: 'high current Ma(-)b',\n            ROBOID_io_port_high_current_mcd: 'high current Mc(-)d',\n            ROBOID_io_action_stop: 'stop',\n            ROBOID_io_action_turn_off: 'turn off',\n            ROBOID_range_integer: 'without',\n            ROBOID_range_real: 'with',\n            ROBOID_led_intensity_dark: 'dark',\n            ROBOID_led_intensity_normal: 'normal',\n            ROBOID_led_intensity_bright: 'bright',\n            ROBOID_led_type_default: 'default',\n            ROBOID_led_type_crgb: '-rgb',\n            ROBOID_led_type_crbg: '-rbg',\n            ROBOID_led_type_cgrb: '-grb',\n            ROBOID_led_type_cgbr: '-gbr',\n            ROBOID_led_type_cbrg: '-brg',\n            ROBOID_led_type_cbgr: '-bgr',\n            ROBOID_led_type_argb: '+rgb',\n            ROBOID_led_type_arbg: '+rbg',\n            ROBOID_led_type_agrb: '+grb',\n            ROBOID_led_type_agbr: '+gbr',\n            ROBOID_led_type_abrg: '+brg',\n            ROBOID_led_type_abgr: '+bgr',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_neopixel_3_colors: '3 colors',\n            ROBOID_neopixel_6_colors: '6 colors',\n            ROBOID_neopixel_12_colors: '12 colors',\n            ROBOID_neopixel_red_green: 'red to green',\n            ROBOID_neopixel_red_blue: 'red to blue',\n            ROBOID_neopixel_red_white: 'red to white',\n            ROBOID_neopixel_green_red: 'green to red',\n            ROBOID_neopixel_green_blue: 'green to blue',\n            ROBOID_neopixel_green_white: 'green to white',\n            ROBOID_neopixel_blue_red: 'blue to red',\n            ROBOID_neopixel_blue_green: 'blue to green',\n            ROBOID_neopixel_blue_white: 'blue to white',\n            ROBOID_neopixel_white_red: 'white to red',\n            ROBOID_neopixel_white_green: 'white to green',\n            ROBOID_neopixel_white_blue: 'white to blue',\n            ROBOID_neopixel_red_black: 'red getting darker',\n            ROBOID_neopixel_green_black: 'green getting darker',\n            ROBOID_neopixel_blue_black: 'blue getting darker',\n            ROBOID_neopixel_white_black: 'white getting darker',\n            ROBOID_neopixel_black_red: 'red getting brighter',\n            ROBOID_neopixel_black_green: 'green getting brighter',\n            ROBOID_neopixel_black_blue: 'blue getting brighter',\n            ROBOID_neopixel_black_white: 'white getting brighter',\n            ROBOID_serial_string: 'string',\n            ROBOID_serial_string_line: 'string line',\n            ROBOID_serial_all: 'all',\n            ROBOID_serial_until_comma: 'until ,(comma)',\n            ROBOID_serial_until_colon: 'until :(colon)',\n            ROBOID_serial_until_dollar: 'until $',\n            ROBOID_serial_until_sharp: 'until #',\n            ROBOID_serial_until_new_line: 'until new line',\n            ROBOID_serial_port_wa_rb: 'La(write) Lb(read)',\n            ROBOID_serial_port_ra_wb: 'La(read) Lb(write)',\n            ROBOID_serial_port_wa: 'La(write)',\n            ROBOID_serial_port_ra: 'La(read)',\n            ROBOID_pid_10: 'PID-10 ultrasonic sensor (HC-SR04+)',\n            ROBOID_pid_11_1: 'PID-11-1 humidity/temperature sensor (DHT11)',\n            ROBOID_pid_11_2: 'PID-11-2 humidity/temperature sensor (DHT21)',\n            ROBOID_pid_11_3: 'PID-11-3 humidity/temperature sensor (DHT22)',\n            ROBOID_pid_12: 'PID-12 temperature sensor (DS18B20)',\n            ROBOID_pid_13: 'PID-13 joystick and button',\n            ROBOID_pid_14: 'PID-14 dual joystick',\n            ROBOID_pid_15: 'PID-15 IR transceiver',\n            ROBOID_pid_16: 'PID-16 encoder',\n            ROBOID_pid_distance: 'distance (cm)',\n            ROBOID_pid_temperature: 'temperature (℃)',\n            ROBOID_pid_humidity: 'humidity (%RH)',\n            ROBOID_pid_x1: 'x1',\n            ROBOID_pid_y1: 'y1',\n            ROBOID_pid_x2: 'x2',\n            ROBOID_pid_y2: 'y2',\n            ROBOID_pid_button1: 'button1',\n            ROBOID_pid_button2: 'button2',\n            ROBOID_pid_encoder: 'encoder',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_shape_square: 'square',\n            ROBOID_shape_triangle: 'triangle',\n            ROBOID_shape_diamond: 'diamond',\n            ROBOID_shape_circle: 'circle',\n            ROBOID_shape_x: 'X',\n            ROBOID_shape_like: 'like',\n            ROBOID_shape_dislike: 'dislike',\n            ROBOID_shape_angry: 'angry',\n            ROBOID_shape_open_mouth: 'open mouth',\n            ROBOID_shape_close_mouth: 'close mouth',\n            ROBOID_shape_walk1: 'walk 1',\n            ROBOID_shape_walk2: 'walk 2',\n            ROBOID_shape_heart: 'heart',\n            ROBOID_shape_star: 'star',\n            ROBOID_shape_airplane: 'airplane',\n            ROBOID_shape_puppy: 'puppy',\n            ROBOID_shape_butterfly: 'butterfly',\n            ROBOID_shape_quarter_note: 'quarter note',\n            ROBOID_shape_eighth_note: 'eighth note',\n            ROBOID_shape_left_arrow: 'left arrow',\n            ROBOID_shape_right_arrow: 'right arrow',\n            ROBOID_shape_up_arrow: 'up arrow',\n            ROBOID_shape_down_arrow: 'down arrow',\n            ROBOID_hat_background: 'background',\n            ROBOID_hat_all: 'all',\n            ROBOID_hat_clear: 'clear',\n            ROBOID_hat_show: 'show',\n            ROBOID_hat_hide: 'hide',\n            ROBOID_hat_clockwise: 'clockwise',\n            ROBOID_hat_counterclockwise: 'counterclockwise',\n            ROBOID_hat_left_right: 'left-right',\n            ROBOID_hat_up_down: 'up-down',\n            ROBOID_hat_auto: 'auto',\n            ROBOID_hat_manual: 'manual',\n            ROBOID_hat_other_sprite: 'other sprite',\n            ROBOID_hat_left_wall: 'left wall',\n            ROBOID_hat_right_wall: 'right wall',\n            ROBOID_hat_top_wall: 'top wall',\n            ROBOID_hat_bottom_wall: 'bottom wall',\n            ROBOID_hat_any_wall: 'any wall',\n        },\n    },\n    jp: {\n        template: {\n            cheese_value: '%1',\n            cheese_boolean: '%1?',\n            cheese_play_sound_times: '%1 音を %2 回再生する %3',\n            cheese_play_sound_times_until_done: '%1 音を %2 回再生して待つ %3',\n            cheese_change_buzzer_by: 'ブザー音を %1 Hzずつ変える %2',\n            cheese_set_buzzer_to: 'ブザー音を %1 Hzにする %2',\n            cheese_clear_sound: '音をオフにする %1',\n            cheese_play_note: '%1 %2 音をならす %3',\n            cheese_play_note_for: '%1 %2 音を %3 拍子ならす %4',\n            cheese_rest_for: '%1 拍子休む %2',\n            cheese_change_tempo_by: '演奏のテンポを %1 BPMずつ変える %2',\n            cheese_set_tempo_to: '演奏のテンポを %1 BPMにする %2',\n            cheese_set_sound_port_to: '音出力を %1にする %2',\n            cheese_set_input_mode_to: 'ポート %1を %2 入力にする %3',\n            cheese_set_input_range_to: '入力 %1の範囲 %2 ~ %3を %4 ~ %5 小数点 %6にする %7',\n            cheese_set_three_input_ranges_to: '入力 %1の範囲 %2 ~ %3 ~ %4を %5 ~ %6 ~ %7 小数点 %8にする %9',\n            cheese_analog_input: '入力 %1',\n            cheese_digital_input: '入力 %1 %2 ?',\n            cheese_button_state: 'ボタン %1を %2?',\n            cheese_set_pulse_mode_to: 'ポート %1を %2 入力にする %3',\n            cheese_pulse_input: 'ポート %1でパルスが感知されたか?',\n            cheese_set_digital_output_to: 'デジタル出力 %1を %2にする %3',\n            cheese_change_pwm_output_by: 'PWM出力 %1を %2%ずつ変える %3',\n            cheese_set_pwm_output_to: 'PWM出力 %1を %2%にする %3',\n            cheese_change_servo_motor_angle_by: 'サーボモータ %1の角度を %2度ずつ変える %3',\n            cheese_set_servo_motor_angle_to: 'サーボモータ %1の角度を %2度にする %3',\n            cheese_turn_off_servo_motor: 'サーボモータ %1 の電源をオフにする %2',\n            cheese_change_dc_motor_velocity_by: 'DCモータ %1の速度を %2%ずつ変える %3',\n            cheese_set_dc_motor_velocity_to: 'DCモータ %1の速度を %2%にする %3',\n            cheese_stop_dc_motor: 'DCモータ %1 を停止する %2',\n            cheese_rotate_step_motor: 'ステップモータ %1 ステップを速度 %2 ステップ/秒に回る %3',\n            cheese_change_step_motor_velocity_by: 'ステップモータの速度を %1 ステップ/秒ずつ変える %2',\n            cheese_set_step_motor_velocity_to: 'ステップモータの速度を %1 ステップ/秒にする %2',\n            cheese_stop_off_step_motor: 'ステップモータを %1 %2',\n            cheese_set_step_motor_mode_to: 'ステップモータを %1 モードにする %2',\n            cheese_step_count: 'ステップ数',\n            cheese_set_led_to_color: 'RGBLED %1を %2 %3にする %4',\n            cheese_pick_led_to: 'RGBLED %1を %2にする %3',\n            cheese_change_led_by_rgb: 'RGBLED %1を R: %2 G: %3 B: %4ずつ変える %5',\n            cheese_setLed_to_rgb: 'RGBLED %1を R: %2 G: %3 B: %4にする %5',\n            cheese_clear_led: 'RGBLED %1 をオフにする %2',\n            cheese_set_led_type_to: 'RGBLED %1を %2形にする %3',\n            cheese_neopixel_set_number_and_type_to: 'ネオピクセル: LED %1個、%2にする %3',\n            cheese_neopixel_set_all_leds_to_color: 'ネオピクセル: すべてのLEDを %1にする %2',\n            cheese_neopixel_pick_all_leds_to: 'ネオピクセル: すべてのLEDを %1にする %2',\n            cheese_neopixel_change_all_leds_by_rgb: 'ネオピクセル: すべてのLEDを R: %1 G: %2 B: %3ずつ変える %4',\n            cheese_neopixel_set_all_leds_to_rgb: 'ネオピクセル: すべてのLEDを R: %1 G: %2 B: %3にする %4',\n            cheese_neopixel_set_all_leds_to_pattern: 'ネオピクセル: すべてのLEDを %1 パターンにする %2',\n            cheese_neopixel_clear_all_leds: 'ネオピクセル: すべてのLEDをオフにする %1',\n            cheese_neopixel_set_led_to_color: 'ネオピクセル: %1番目のLEDを %2にする %3',\n            cheese_neopixel_pick_led_to: 'ネオピクセル: %1番目のLEDを %2にする %3',\n            cheese_neopixel_change_led_by_rgb: 'ネオピクセル: %1番目のLEDを R: %2 G: %3 B: %4ずつ変える %5',\n            cheese_neopixel_set_led_to_rgb: 'ネオピクセル: %1番目のLEDを R: %2 G: %3 B: %4にする %5',\n            cheese_neopixel_clear_led: 'ネオピクセル: %1番目のLEDをオフにする %2',\n            cheese_neopixel_set_led_range_to_color: 'ネオピクセル: %1番目から %2番目まで %3間隔のLEDを %4にする %5',\n            cheese_neopixel_pick_led_range_to: 'ネオピクセル: %1番目から %2番目まで %3間隔のLEDを %4にする %5',\n            cheese_neopixel_change_led_range_by_rgb: 'ネオピクセル: %1番目から %2番目まで %3間隔のLEDを R: %4 G: %5 B: %6ずつ変える %7',\n            cheese_neopixel_set_led_range_to_rgb: 'ネオピクセル: %1番目から %2番目まで %3間隔のLEDを R: %4 G: %5 B: %6にする %7',\n            cheese_neopixel_set_led_range_to_pattern: 'ネオピクセル: %1番目から %2番目までのLEDを %3 パターンにする %4',\n            cheese_neopixel_clear_led_range: 'ネオピクセル: %1番目から %2番目まで %3間隔のLEDをオフにする %4',\n            cheese_neopixel_shift: 'ネオピクセル: %1ピクセル移動する %2',\n            cheese_neopixel_rotate: 'ネオピクセル: %1ピクセル回転する %2',\n            cheese_neopixel_change_brightness_by: 'ネオピクセル: 明るさを %1%ずつ変える %2',\n            cheese_neopixel_set_brightness_to: 'ネオピクセル: 明るさを %1%にする %2',\n            cheese_write_serial: 'シリアルに %1 %2 を書き出す %3',\n            cheese_read_serial_until: 'シリアルを %1 読み取る %2',\n            cheese_set_serial_port_to: 'シリアルポートを %1にする %2',\n            cheese_set_serial_rate_to: 'シリアル速度を %1Bdにする %2',\n            cheese_serial_input: 'シリアル入力',\n            cheese_pid_start: '%1 を開始する %2',\n            cheese_pid_set_range_to: 'PID %1の範囲 %2 ~ %3を %4 ~ %5 小数点 %6にする %7',\n            cheese_pid_set_three_ranges_to: 'PID %1の範囲 %2 ~ %3 ~ %4を %5 ~ %6 ~ %7 小数点 %8にする %9',\n            cheese_pid_reset_encoder: 'PID エンコーダ値を初期化する %1',\n            cheese_pid_input: 'PID %1',\n            cheese_pid_button_state: 'PID ボタン %1を %2?',\n            cheese_hat010_start: 'HAT-010 5x5マトリックスを開始する %1',\n            cheese_hat010_button: 'HAT-010 ボタン %1',\n            cheese_hat010_button_state: 'HAT-010 ボタン %1を %2?',\n            cheese_hat010_background_turn_on_xy: 'HAT-010 背景 x: %1 y: %2を %3に点灯する %4',\n            cheese_hat010_background_turn_off_xy: 'HAT-010 背景 x: %1 y: %2をオフにする %3',\n            cheese_hat010_background_draw_shape_at_xy: 'HAT-010 背景 %1 %2を x: %3 y: %4に描画する %5',\n            cheese_hat010_background_draw_string_at_xy: 'HAT-010 背景 %1 文字列 %2を x: %3 y: %4に描画する %5',\n            cheese_hat010_background_draw_pattern_at_xy: 'HAT-010 背景 %1 パターン %2を x: %3 y: %4に描画する %5',\n            cheese_hat010_clear: 'HAT-010 %1 を消す %2',\n            cheese_hat010_scroll_by_xy: 'HAT-010 %1 x: %2 y: %3だけ移動する %4',\n            cheese_hat010_sprite_set_to_shape: 'HAT-010 図 %1を %2 %3にする %4',\n            cheese_hat010_sprite_set_to_string: 'HAT-010 図 %1を %2 文字列 %3にする %4',\n            cheese_hat010_sprite_set_to_pattern: 'HAT-010 図 %1を %2 パターン %3にする %4',\n            cheese_hat010_sprite_clear_show_hide: 'HAT-010 図 %1を %2 %3',\n            cheese_hat010_sprite_change_positions_by_xy: 'HAT-010 図 %1の位置を x: %2 y: %3ずつ変える %4',\n            cheese_hat010_sprite_set_positions_to_xy: 'HAT-010 図 %1の位置を x: %2 y: %3にする %4',\n            cheese_hat010_sprite_change_position_by_value: 'HAT-010 図 %1の %2 位置を %3ずつ変える %4',\n            cheese_hat010_sprite_set_position_to_value: 'HAT-010 図 %1の %2 位置を %3にする %4',\n            cheese_hat010_sprite_rotate: 'HAT-010 図 %1を %2 方向に回転する %3',\n            cheese_hat010_sprite_flip_in_direction: 'HAT-010 図 %1を %2 方向に反転する %3',\n            cheese_hat010_sprite_stamp_to_background: 'HAT-010 図 %1を背景にスタンプする %2',\n            cheese_hat010_sprite_position: 'HAT-010 図 %1の %2 位置',\n            cheese_hat010_sprite_touching_sprite: 'HAT-010 図 %1が 図 %2に着いたか?',\n            cheese_hat010_sprite_touching: 'HAT-010 図 %1が %2に着いたか?',\n            cheese_hat010_change_brightness_by: 'HAT-010 明るさを %1%ずつ変える %2',\n            cheese_hat010_set_brightness_to: 'HAT-010 明るさを %1%にする %2',\n        },\n        Helper: {\n        },\n        Blocks: {\n            ROBOID_sensor_signal_strength: '信号の強さ',\n            ROBOID_sensor_signal_strength_dbm: '信号の強さ(dBm)',\n            ROBOID_sensor_acceleration_x: 'x軸の加速度',\n            ROBOID_sensor_acceleration_y: 'y軸の加速度',\n            ROBOID_sensor_acceleration_z: 'z軸の加速度',\n            ROBOID_sensor_input_sa: '入力Sa',\n            ROBOID_sensor_input_sb: '入力Sb',\n            ROBOID_sensor_input_sc: '入力Sc',\n            ROBOID_sensor_input_la: '入力La',\n            ROBOID_sensor_input_lb: '入力Lb',\n            ROBOID_sensor_input_lc: '入力Lc',\n            ROBOID_sensor_step_count: 'ステップ数',\n            ROBOID_monitor_output_sa: '出力Sa',\n            ROBOID_monitor_output_sb: '出力Sb',\n            ROBOID_monitor_output_sc: '出力Sc',\n            ROBOID_monitor_output_la: '出力La',\n            ROBOID_monitor_output_lb: '出力Lb',\n            ROBOID_monitor_output_lc: '出力Lc',\n            ROBOID_monitor_output_mab: '出力Mab',\n            ROBOID_monitor_output_mcd: '出力Mcd',\n            ROBOID_monitor_buzzer: 'ブザー',\n            ROBOID_monitor_note: '音符',\n            ROBOID_logo_sky_direction: 'ロゴが空の方向か',\n            ROBOID_logo_earth_direction: 'ロゴが地の方向か',\n            ROBOID_power_switch_sky_direction: '電源スイッチが空の方向か',\n            ROBOID_power_switch_earth_direction: '電源スイッチが地の方向か',\n            ROBOID_port_s_sky_direction: 'ポートSが空の方向か',\n            ROBOID_port_s_earth_direction: 'ポートSが地の方向か',\n            ROBOID_tap: '叩いたか',\n            ROBOID_free_fall: '落下したか',\n            ROBOID_battery_normal: '電池残量が充分か',\n            ROBOID_battery_low: '電池残量が足りないか',\n            ROBOID_battery_empty: '電池残量がなくなったか',\n            ROBOID_sound_beep: 'ビープ',\n            ROBOID_sound_random_beep: 'ランダムビープ',\n            ROBOID_sound_noise: 'ノイズ',\n            ROBOID_sound_siren: 'サイレン',\n            ROBOID_sound_engine: 'エンジン',\n            ROBOID_sound_chop: 'チョップ',\n            ROBOID_sound_robot: 'ロボット',\n            ROBOID_sound_dibidibidip: 'ディビディビディ',\n            ROBOID_sound_good_job: 'よくできました',\n            ROBOID_sound_happy: 'よろこび',\n            ROBOID_sound_angry: 'いかり',\n            ROBOID_sound_sad: 'かなしみ',\n            ROBOID_sound_sleep: 'ねむい',\n            ROBOID_sound_march: 'マーチ',\n            ROBOID_sound_birthday: 'たんじょうび',\n            ROBOID_note_c: 'ド',\n            ROBOID_note_c_sharp: 'ド♯(レ♭)',\n            ROBOID_note_d: 'レ',\n            ROBOID_note_d_sharp: 'レ♯(ミ♭)',\n            ROBOID_note_e: 'ミ',\n            ROBOID_note_f: 'ファ',\n            ROBOID_note_f_sharp: 'ファ♯(ソ♭)',\n            ROBOID_note_g: 'ソ',\n            ROBOID_note_g_sharp: 'ソ♯(ラ♭)',\n            ROBOID_note_a: 'ラ',\n            ROBOID_note_a_sharp: 'ラ♯(シ♭)',\n            ROBOID_note_b: 'シ',\n            ROBOID_speaker_internal: '内蔵スピーカー',\n            ROBOID_speaker_port_mab: 'ポートMab',\n            ROBOID_io_mode_makey: 'メイキー',\n            ROBOID_io_mode_button: 'ボタン',\n            ROBOID_io_mode_digital_pull_up: 'デジタル(プルアップ)',\n            ROBOID_io_mode_digital_pull_down: 'デジタル(プルダウン)',\n            ROBOID_io_mode_analog: 'アナログ',\n            ROBOID_io_mode_voltage: '電圧',\n            ROBOID_io_mode_pulse: 'パルス',\n            ROBOID_io_mode_pulse_pull_up: 'パルス(プルアップ)',\n            ROBOID_io_mode_pulse_pull_down: 'パルス(プルダウン)',\n            ROBOID_io_mode_normal: '基本',\n            ROBOID_io_mode_power: 'パワー',\n            ROBOID_io_port_high_current_mab: '大電流Ma(-)b',\n            ROBOID_io_port_high_current_mcd: '大電流Mc(-)d',\n            ROBOID_io_action_stop: '停止する',\n            ROBOID_io_action_turn_off: 'オフにする',\n            ROBOID_range_integer: 'なし',\n            ROBOID_range_real: 'あり',\n            ROBOID_led_intensity_dark: '暗い',\n            ROBOID_led_intensity_normal: '基本',\n            ROBOID_led_intensity_bright: '明るい',\n            ROBOID_led_type_default: '基本',\n            ROBOID_led_type_crgb: '-RGB',\n            ROBOID_led_type_crbg: '-RBG',\n            ROBOID_led_type_cgrb: '-GRB',\n            ROBOID_led_type_cgbr: '-GBR',\n            ROBOID_led_type_cbrg: '-BRG',\n            ROBOID_led_type_cbgr: '-BGR',\n            ROBOID_led_type_argb: '+RGB',\n            ROBOID_led_type_arbg: '+RBG',\n            ROBOID_led_type_agrb: '+GRB',\n            ROBOID_led_type_agbr: '+GBR',\n            ROBOID_led_type_abrg: '+BRG',\n            ROBOID_led_type_abgr: '+BGR',\n            ROBOID_color_red: '赤色',\n            ROBOID_color_orange: 'オレンジ色',\n            ROBOID_color_yellow: '黄色',\n            ROBOID_color_green: '緑色',\n            ROBOID_color_sky_blue: '水色',\n            ROBOID_color_blue: '青色',\n            ROBOID_color_violet: '青むらさき色',\n            ROBOID_color_purple: 'むらさき色',\n            ROBOID_color_white: '白色',\n            ROBOID_neopixel_3_colors: '3色',\n            ROBOID_neopixel_6_colors: '6色',\n            ROBOID_neopixel_12_colors: '12色',\n            ROBOID_neopixel_red_green: '赤色から緑色まで',\n            ROBOID_neopixel_red_blue: '赤色から青色まで',\n            ROBOID_neopixel_red_white: '赤色から白色まで',\n            ROBOID_neopixel_green_red: '緑色から赤色まで',\n            ROBOID_neopixel_green_blue: '緑色から青色まで',\n            ROBOID_neopixel_green_white: '緑色から白色まで',\n            ROBOID_neopixel_blue_red: '青色から赤色まで',\n            ROBOID_neopixel_blue_green: '青色から緑色まで',\n            ROBOID_neopixel_blue_white: '青色から白色まで',\n            ROBOID_neopixel_white_red: '白色から赤色まで',\n            ROBOID_neopixel_white_green: '白色から緑色まで',\n            ROBOID_neopixel_white_blue: '白色から青色まで',\n            ROBOID_neopixel_red_black: '赤色ますます暗く',\n            ROBOID_neopixel_green_black: '緑色ますます暗く',\n            ROBOID_neopixel_blue_black: '青色ますます暗く',\n            ROBOID_neopixel_white_black: '白色ますます暗く',\n            ROBOID_neopixel_black_red: '赤色ますます明るく',\n            ROBOID_neopixel_black_green: '緑色ますます明るく',\n            ROBOID_neopixel_black_blue: '青色ますます明るく',\n            ROBOID_neopixel_black_white: '白色ますます明るく',\n            ROBOID_serial_string: '文字列',\n            ROBOID_serial_string_line: '文字列1行',\n            ROBOID_serial_all: '全部',\n            ROBOID_serial_until_comma: '、(読点)まで',\n            ROBOID_serial_until_colon: '：(コロン)まで',\n            ROBOID_serial_until_dollar: '$まで',\n            ROBOID_serial_until_sharp: '#まで',\n            ROBOID_serial_until_new_line: '改行まで',\n            ROBOID_serial_port_wa_rb: 'La(書く)Lb(読む)',\n            ROBOID_serial_port_ra_wb: 'La(読む)Lb(書く)',\n            ROBOID_serial_port_wa: 'La(書く)',\n            ROBOID_serial_port_ra: 'La(読む)',\n            ROBOID_pid_10: 'PID-10 超音波センサー(HC-SR04+)',\n            ROBOID_pid_11_1: 'PID-11-1 温湿度センサー(DHT11)',\n            ROBOID_pid_11_2: 'PID-11-2 温湿度センサー(DHT21)',\n            ROBOID_pid_11_3: 'PID-11-3 温湿度センサー(DHT22)',\n            ROBOID_pid_12: 'PID-12 温度センサー(DS18B20)',\n            ROBOID_pid_13: 'PID-13 ジョイスティックとボタン',\n            ROBOID_pid_14: 'PID-14 デュアルジョイスティック',\n            ROBOID_pid_15: 'PID-15 IRトランシーバー',\n            ROBOID_pid_16: 'PID-16 エンコーダ',\n            ROBOID_pid_distance: '距離(cm)',\n            ROBOID_pid_temperature: '温度(℃)',\n            ROBOID_pid_humidity: '湿度(%RH)',\n            ROBOID_pid_x1: 'x1',\n            ROBOID_pid_y1: 'y1',\n            ROBOID_pid_x2: 'x2',\n            ROBOID_pid_y2: 'y2',\n            ROBOID_pid_button1: 'ボタン1',\n            ROBOID_pid_button2: 'ボタン2',\n            ROBOID_pid_encoder: 'エンコーダ',\n            ROBOID_clicked: 'クリックしたか',\n            ROBOID_double_clicked: 'ダブルクリックしたか',\n            ROBOID_long_pressed: '長く押したか',\n            ROBOID_shape_square: '四角形',\n            ROBOID_shape_triangle: '三角形',\n            ROBOID_shape_diamond: 'ダイヤモンド',\n            ROBOID_shape_circle: '円',\n            ROBOID_shape_x: 'X',\n            ROBOID_shape_like: 'すき',\n            ROBOID_shape_dislike: 'きらい',\n            ROBOID_shape_angry: 'いかり',\n            ROBOID_shape_open_mouth: '開けた口',\n            ROBOID_shape_close_mouth: '閉じた口',\n            ROBOID_shape_walk1: '歩く1',\n            ROBOID_shape_walk2: '歩く2',\n            ROBOID_shape_heart: 'ハート',\n            ROBOID_shape_star: '星',\n            ROBOID_shape_airplane: '飛行機',\n            ROBOID_shape_puppy: '子犬',\n            ROBOID_shape_butterfly: '蝶',\n            ROBOID_shape_quarter_note: '4分音符',\n            ROBOID_shape_eighth_note: '8分音符',\n            ROBOID_shape_left_arrow: '左矢印',\n            ROBOID_shape_right_arrow: '右矢印',\n            ROBOID_shape_up_arrow: '上矢印',\n            ROBOID_shape_down_arrow: '下矢印',\n            ROBOID_hat_background: '背景',\n            ROBOID_hat_all: '全部',\n            ROBOID_hat_clear: '消す',\n            ROBOID_hat_show: 'みせる',\n            ROBOID_hat_hide: 'かくす',\n            ROBOID_hat_clockwise: '時計',\n            ROBOID_hat_counterclockwise: '反時計',\n            ROBOID_hat_left_right: '左-右',\n            ROBOID_hat_up_down: '上-下',\n            ROBOID_hat_auto: '自動',\n            ROBOID_hat_manual: '手動',\n            ROBOID_hat_other_sprite: '他の図',\n            ROBOID_hat_left_wall: '左壁',\n            ROBOID_hat_right_wall: '右壁',\n            ROBOID_hat_top_wall: '上壁',\n            ROBOID_hat_bottom_wall: '下壁',\n            ROBOID_hat_any_wall: '全ての壁',\n        },\n    },\n    vn: {\n        template: {\n            cheese_value: '%1',\n            cheese_boolean: '%1?',\n            cheese_play_sound_times: 'play sound %1 %2 times %3',\n            cheese_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            cheese_change_buzzer_by: 'change buzzer by %1 Hz %2',\n            cheese_set_buzzer_to: 'set buzzer to %1 Hz %2',\n            cheese_clear_sound: 'clear sound %1',\n            cheese_play_note: 'play note %1 %2 %3',\n            cheese_play_note_for: 'play note %1 %2 for %3 beats %4',\n            cheese_rest_for: 'rest for %1 beats %2',\n            cheese_change_tempo_by: 'change tempo by %1 BPM %2',\n            cheese_set_tempo_to: 'set tempo to %1 BPM %2',\n            cheese_set_sound_port_to: 'set sound output to %1 %2',\n            cheese_set_input_mode_to: 'set port %1 to %2 input %3',\n            cheese_set_input_range_to: 'set input %1 range %2 - %3 to %4 - %5 %6 decimal point %7',\n            cheese_set_three_input_ranges_to: 'set input %1 range %2 - %3 - %4 to %5 - %6 - %7 %8 decimal point %9',\n            cheese_analog_input: 'input %1',\n            cheese_digital_input: 'input %1 %2 ?',\n            cheese_button_state: 'button %1 %2 ?',\n            cheese_set_pulse_mode_to: 'set port %1 to %2 input %3',\n            cheese_pulse_input: 'pulse detected on port %1 ?',\n            cheese_set_digital_output_to: 'set digital output %1 to %2 %3',\n            cheese_change_pwm_output_by: 'change pwm output %1 by %2% %3',\n            cheese_set_pwm_output_to: 'set pwm output %1 to %2% %3',\n            cheese_change_servo_motor_angle_by: 'change servo motor %1 by %2 degrees %3',\n            cheese_set_servo_motor_angle_to: 'set servo motor %1 to %2 degrees %3',\n            cheese_turn_off_servo_motor: 'turn off servo motor %1 %2',\n            cheese_change_dc_motor_velocity_by: 'change dc motor %1 velocity by %2% %3',\n            cheese_set_dc_motor_velocity_to: 'set dc motor %1 velocity to %2% %3',\n            cheese_stop_dc_motor: 'stop dc motor %1 %2',\n            cheese_rotate_step_motor: 'rotate step motor %1 steps with velocity %2 step/sec %3',\n            cheese_change_step_motor_velocity_by: 'change step motor velocity by %1 step/sec %2',\n            cheese_set_step_motor_velocity_to: 'set step motor velocity to %1 step/sec %2',\n            cheese_stop_off_step_motor: '%1 step motor %2',\n            cheese_set_step_motor_mode_to: 'set step motor to %1 mode %2',\n            cheese_step_count: 'step count',\n            cheese_set_led_to_color: 'set rgb led %1 to %2 %3 %4',\n            cheese_pick_led_to: 'set rgb led %1 to %2 %3',\n            cheese_change_led_by_rgb: 'change rgb led %1 by r: %2 g: %3 b: %4 %5',\n            cheese_setLed_to_rgb: 'set rgb led %1 to r: %2 g: %3 b: %4 %5',\n            cheese_clear_led: 'clear rgb led %1 %2',\n            cheese_set_led_type_to: 'set rgb led %1 to %2 type %3',\n            cheese_neopixel_set_number_and_type_to: 'neopixel: set %1 leds as %2 %3',\n            cheese_neopixel_set_all_leds_to_color: 'neopixel: set all leds to %1 %2',\n            cheese_neopixel_pick_all_leds_to: 'neopixel: set all leds to %1 %2',\n            cheese_neopixel_change_all_leds_by_rgb: 'neopixel: change all leds by r: %1 g: %2 b: %3 %4',\n            cheese_neopixel_set_all_leds_to_rgb: 'neopixel: set all leds to r: %1 g: %2 b: %3 %4',\n            cheese_neopixel_set_all_leds_to_pattern: 'neopixel: set all leds to pattern %1 %2',\n            cheese_neopixel_clear_all_leds: 'neopixel: clear all leds %1',\n            cheese_neopixel_set_led_to_color: 'neopixel: set led %1 to %2 %3',\n            cheese_neopixel_pick_led_to: 'neopixel: set led %1 to %2 %3',\n            cheese_neopixel_change_led_by_rgb: 'neopixel: change led %1 by r: %2 g: %3 b: %4 %5',\n            cheese_neopixel_set_led_to_rgb: 'neopixel: set led %1 to r: %2 g: %3 b: %4 %5',\n            cheese_neopixel_clear_led: 'neopixel: clear led %1 %2',\n            cheese_neopixel_set_led_range_to_color: 'neopixel: set leds (from %1 to %2 with %3 increments) to %4 %5',\n            cheese_neopixel_pick_led_range_to: 'neopixel: set leds (from %1 to %2 with %3 increments) to %4 %5',\n            cheese_neopixel_change_led_range_by_rgb: 'neopixel: change leds (from %1 to %2 with %3 increments) by r: %4 g: %5 b: %6 %7',\n            cheese_neopixel_set_led_range_to_rgb: 'neopixel: set leds (from %1 to %2 with %3 increments) to r: %4 g: %5 b: %6 %7',\n            cheese_neopixel_set_led_range_to_pattern: 'neopixel: set leds (from %1 to %2) to pattern %3 %4',\n            cheese_neopixel_clear_led_range: 'neopixel: clear leds (from %1 to %2 with %3 increments) %4',\n            cheese_neopixel_shift: 'neopixel: shift %1 pixels %2',\n            cheese_neopixel_rotate: 'neopixel: rotate %1 pixels %2',\n            cheese_neopixel_change_brightness_by: 'neopixel: change brightness by %1% %2',\n            cheese_neopixel_set_brightness_to: 'neopixel: set brightness to %1% %2',\n            cheese_write_serial: 'write %1 %2 to serial %3',\n            cheese_read_serial_until: 'read serial %1 %2',\n            cheese_set_serial_port_to: 'set serial port to %1 %2',\n            cheese_set_serial_rate_to: 'set serial rate to %1Bd %2',\n            cheese_serial_input: 'serial input',\n            cheese_pid_start: 'start %1 %2',\n            cheese_pid_set_range_to: 'PID: set %1 range %2 - %3 to %4 - %5 %6 decimal point %7',\n            cheese_pid_set_three_ranges_to: 'PID: set %1 range %2 - %3 - %4 to %5 - %6 - %7 %8 decimal point %9',\n            cheese_pid_reset_encoder: 'PID: clear encoder %1',\n            cheese_pid_input: 'PID: %1',\n            cheese_pid_button_state: 'PID: button %1 %2?',\n            cheese_hat010_start: 'start HAT-010 5x5 matrix %1',\n            cheese_hat010_button: 'HAT-010: button %1',\n            cheese_hat010_button_state: 'HAT-010: button %1 %2?',\n            cheese_hat010_background_turn_on_xy: 'HAT-010 background: turn on x: %1 y: %2 in %3 %4',\n            cheese_hat010_background_turn_off_xy: 'HAT-010 background: turn off x: %1 y: %2 %3',\n            cheese_hat010_background_draw_shape_at_xy: 'HAT-010 background: draw %1 %2 at x: %3 y: %4 %5',\n            cheese_hat010_background_draw_string_at_xy: 'HAT-010 background: draw %1 string %2 at x: %3 y: %4 %5',\n            cheese_hat010_background_draw_pattern_at_xy: 'HAT-010 background: draw %1 pattern %2 at x: %3 y: %4 %5',\n            cheese_hat010_clear: 'HAT-010: clear %1 %2',\n            cheese_hat010_scroll_by_xy: 'HAT-010: scroll %1 by x: %2 y: %3 %4',\n            cheese_hat010_sprite_set_to_shape: 'HAT-010 sprite %1: set sprite to %2 %3 %4',\n            cheese_hat010_sprite_set_to_string: 'HAT-010 sprite %1: set sprite to %2 string %3 %4',\n            cheese_hat010_sprite_set_to_pattern: 'HAT-010 sprite %1: set sprite to %2 pattern %3 %4',\n            cheese_hat010_sprite_clear_show_hide: 'HAT-010 sprite %1: %2 sprite %3',\n            cheese_hat010_sprite_change_positions_by_xy: 'HAT-010 sprite %1: change position by x: %2 y: %3 %4',\n            cheese_hat010_sprite_set_positions_to_xy: 'HAT-010 sprite %1: set position to x: %2 y: %3 %4',\n            cheese_hat010_sprite_change_position_by_value: 'HAT-010 sprite %1: change %2 position by %3 %4',\n            cheese_hat010_sprite_set_position_to_value: 'HAT-010 sprite %1: set %2 position to %3 %4',\n            cheese_hat010_sprite_rotate: 'HAT-010 sprite %1: rotate %2 %3',\n            cheese_hat010_sprite_flip_in_direction: 'HAT-010 sprite %1: flip in %2 direction %3',\n            cheese_hat010_sprite_stamp_to_background: 'HAT-010 sprite %1: stamp to background %2',\n            cheese_hat010_sprite_position: 'HAT-010 sprite %1: %2 position',\n            cheese_hat010_sprite_touching_sprite: 'HAT-010 sprite %1: touching sprite %2?',\n            cheese_hat010_sprite_touching: 'HAT-010 sprite %1: touching %2?',\n            cheese_hat010_change_brightness_by: 'HAT-010: change brightness by %1% %2',\n            cheese_hat010_set_brightness_to: 'HAT-010: set brightness to %1% %2',\n        },\n        Helper: {\n        },\n        Blocks: {\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_signal_strength_dbm: 'signal strength (dBm)',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_input_sa: 'input Sa',\n            ROBOID_sensor_input_sb: 'input Sb',\n            ROBOID_sensor_input_sc: 'input Sc',\n            ROBOID_sensor_input_la: 'input La',\n            ROBOID_sensor_input_lb: 'input Lb',\n            ROBOID_sensor_input_lc: 'input Lc',\n            ROBOID_sensor_step_count: 'step count',\n            ROBOID_monitor_output_sa: 'output Sa',\n            ROBOID_monitor_output_sb: 'output Sb',\n            ROBOID_monitor_output_sc: 'output Sc',\n            ROBOID_monitor_output_la: 'output La',\n            ROBOID_monitor_output_lb: 'output Lb',\n            ROBOID_monitor_output_lc: 'output Lc',\n            ROBOID_monitor_output_mab: 'output Mab',\n            ROBOID_monitor_output_mcd: 'output Mcd',\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_logo_sky_direction: 'logo in sky direction',\n            ROBOID_logo_earth_direction: 'logo in earth direction',\n            ROBOID_power_switch_sky_direction: 'power switch in sky direction',\n            ROBOID_power_switch_earth_direction: 'power switch in earth direction',\n            ROBOID_port_s_sky_direction: 'port S in sky direction',\n            ROBOID_port_s_earth_direction: 'port S in earth direction',\n            ROBOID_tap: 'tap',\n            ROBOID_free_fall: 'free fall',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n            ROBOID_speaker_internal: 'internal speaker',\n            ROBOID_speaker_port_mab: 'port Mab',\n            ROBOID_io_mode_makey: 'makey',\n            ROBOID_io_mode_button: 'button',\n            ROBOID_io_mode_digital_pull_up: 'digital (pull up)',\n            ROBOID_io_mode_digital_pull_down: 'digital (pull down)',\n            ROBOID_io_mode_analog: 'analog',\n            ROBOID_io_mode_voltage: 'voltage',\n            ROBOID_io_mode_pulse: 'pulse',\n            ROBOID_io_mode_pulse_pull_up: 'pulse (pull up)',\n            ROBOID_io_mode_pulse_pull_down: 'pulse (pull down)',\n            ROBOID_io_mode_normal: 'normal',\n            ROBOID_io_mode_power: 'power',\n            ROBOID_io_port_high_current_mab: 'high current Ma(-)b',\n            ROBOID_io_port_high_current_mcd: 'high current Mc(-)d',\n            ROBOID_io_action_stop: 'stop',\n            ROBOID_io_action_turn_off: 'turn off',\n            ROBOID_range_integer: 'without',\n            ROBOID_range_real: 'with',\n            ROBOID_led_intensity_dark: 'dark',\n            ROBOID_led_intensity_normal: 'normal',\n            ROBOID_led_intensity_bright: 'bright',\n            ROBOID_led_type_default: 'default',\n            ROBOID_led_type_crgb: '-rgb',\n            ROBOID_led_type_crbg: '-rbg',\n            ROBOID_led_type_cgrb: '-grb',\n            ROBOID_led_type_cgbr: '-gbr',\n            ROBOID_led_type_cbrg: '-brg',\n            ROBOID_led_type_cbgr: '-bgr',\n            ROBOID_led_type_argb: '+rgb',\n            ROBOID_led_type_arbg: '+rbg',\n            ROBOID_led_type_agrb: '+grb',\n            ROBOID_led_type_agbr: '+gbr',\n            ROBOID_led_type_abrg: '+brg',\n            ROBOID_led_type_abgr: '+bgr',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_neopixel_3_colors: '3 colors',\n            ROBOID_neopixel_6_colors: '6 colors',\n            ROBOID_neopixel_12_colors: '12 colors',\n            ROBOID_neopixel_red_green: 'red to green',\n            ROBOID_neopixel_red_blue: 'red to blue',\n            ROBOID_neopixel_red_white: 'red to white',\n            ROBOID_neopixel_green_red: 'green to red',\n            ROBOID_neopixel_green_blue: 'green to blue',\n            ROBOID_neopixel_green_white: 'green to white',\n            ROBOID_neopixel_blue_red: 'blue to red',\n            ROBOID_neopixel_blue_green: 'blue to green',\n            ROBOID_neopixel_blue_white: 'blue to white',\n            ROBOID_neopixel_white_red: 'white to red',\n            ROBOID_neopixel_white_green: 'white to green',\n            ROBOID_neopixel_white_blue: 'white to blue',\n            ROBOID_neopixel_red_black: 'red getting darker',\n            ROBOID_neopixel_green_black: 'green getting darker',\n            ROBOID_neopixel_blue_black: 'blue getting darker',\n            ROBOID_neopixel_white_black: 'white getting darker',\n            ROBOID_neopixel_black_red: 'red getting brighter',\n            ROBOID_neopixel_black_green: 'green getting brighter',\n            ROBOID_neopixel_black_blue: 'blue getting brighter',\n            ROBOID_neopixel_black_white: 'white getting brighter',\n            ROBOID_serial_string: 'string',\n            ROBOID_serial_string_line: 'string line',\n            ROBOID_serial_all: 'all',\n            ROBOID_serial_until_comma: 'until ,(comma)',\n            ROBOID_serial_until_colon: 'until :(colon)',\n            ROBOID_serial_until_dollar: 'until $',\n            ROBOID_serial_until_sharp: 'until #',\n            ROBOID_serial_until_new_line: 'until new line',\n            ROBOID_serial_port_wa_rb: 'La(write) Lb(read)',\n            ROBOID_serial_port_ra_wb: 'La(read) Lb(write)',\n            ROBOID_serial_port_wa: 'La(write)',\n            ROBOID_serial_port_ra: 'La(read)',\n            ROBOID_pid_10: 'PID-10 ultrasonic sensor (HC-SR04+)',\n            ROBOID_pid_11_1: 'PID-11-1 humidity/temperature sensor (DHT11)',\n            ROBOID_pid_11_2: 'PID-11-2 humidity/temperature sensor (DHT21)',\n            ROBOID_pid_11_3: 'PID-11-3 humidity/temperature sensor (DHT22)',\n            ROBOID_pid_12: 'PID-12 temperature sensor (DS18B20)',\n            ROBOID_pid_13: 'PID-13 joystick and button',\n            ROBOID_pid_14: 'PID-14 dual joystick',\n            ROBOID_pid_15: 'PID-15 IR transceiver',\n            ROBOID_pid_16: 'PID-16 encoder',\n            ROBOID_pid_distance: 'distance (cm)',\n            ROBOID_pid_temperature: 'temperature (℃)',\n            ROBOID_pid_humidity: 'humidity (%RH)',\n            ROBOID_pid_x1: 'x1',\n            ROBOID_pid_y1: 'y1',\n            ROBOID_pid_x2: 'x2',\n            ROBOID_pid_y2: 'y2',\n            ROBOID_pid_button1: 'button1',\n            ROBOID_pid_button2: 'button2',\n            ROBOID_pid_encoder: 'encoder',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_shape_square: 'square',\n            ROBOID_shape_triangle: 'triangle',\n            ROBOID_shape_diamond: 'diamond',\n            ROBOID_shape_circle: 'circle',\n            ROBOID_shape_x: 'X',\n            ROBOID_shape_like: 'like',\n            ROBOID_shape_dislike: 'dislike',\n            ROBOID_shape_angry: 'angry',\n            ROBOID_shape_open_mouth: 'open mouth',\n            ROBOID_shape_close_mouth: 'close mouth',\n            ROBOID_shape_walk1: 'walk 1',\n            ROBOID_shape_walk2: 'walk 2',\n            ROBOID_shape_heart: 'heart',\n            ROBOID_shape_star: 'star',\n            ROBOID_shape_airplane: 'airplane',\n            ROBOID_shape_puppy: 'puppy',\n            ROBOID_shape_butterfly: 'butterfly',\n            ROBOID_shape_quarter_note: 'quarter note',\n            ROBOID_shape_eighth_note: 'eighth note',\n            ROBOID_shape_left_arrow: 'left arrow',\n            ROBOID_shape_right_arrow: 'right arrow',\n            ROBOID_shape_up_arrow: 'up arrow',\n            ROBOID_shape_down_arrow: 'down arrow',\n            ROBOID_hat_background: 'background',\n            ROBOID_hat_all: 'all',\n            ROBOID_hat_clear: 'clear',\n            ROBOID_hat_show: 'show',\n            ROBOID_hat_hide: 'hide',\n            ROBOID_hat_clockwise: 'clockwise',\n            ROBOID_hat_counterclockwise: 'counterclockwise',\n            ROBOID_hat_left_right: 'left-right',\n            ROBOID_hat_up_down: 'up-down',\n            ROBOID_hat_auto: 'auto',\n            ROBOID_hat_manual: 'manual',\n            ROBOID_hat_other_sprite: 'other sprite',\n            ROBOID_hat_left_wall: 'left wall',\n            ROBOID_hat_right_wall: 'right wall',\n            ROBOID_hat_top_wall: 'top wall',\n            ROBOID_hat_bottom_wall: 'bottom wall',\n            ROBOID_hat_any_wall: 'any wall',\n        },\n    },\n});\n\nEntry.Cheese.blockMenuBlocks = [\n    'cheese_value',\n    'cheese_boolean',\n    'cheese_play_sound_times',\n    'cheese_play_sound_times_until_done',\n    'cheese_change_buzzer_by',\n    'cheese_set_buzzer_to',\n    'cheese_clear_sound',\n    'cheese_play_note',\n    'cheese_play_note_for',\n    'cheese_rest_for',\n    'cheese_change_tempo_by',\n    'cheese_set_tempo_to',\n    'cheese_set_sound_port_to',\n    'cheese_set_input_mode_to',\n    'cheese_set_input_range_to',\n    'cheese_set_three_input_ranges_to',\n    'cheese_analog_input',\n    'cheese_digital_input',\n    'cheese_button_state',\n    'cheese_set_pulse_mode_to',\n    'cheese_pulse_input',\n    'cheese_set_digital_output_to',\n    'cheese_change_pwm_output_by',\n    'cheese_set_pwm_output_to',\n    'cheese_change_servo_motor_angle_by',\n    'cheese_set_servo_motor_angle_to',\n    'cheese_turn_off_servo_motor',\n    'cheese_change_dc_motor_velocity_by',\n    'cheese_set_dc_motor_velocity_to',\n    'cheese_stop_dc_motor',\n    'cheese_rotate_step_motor',\n    'cheese_change_step_motor_velocity_by',\n    'cheese_set_step_motor_velocity_to',\n    'cheese_stop_off_step_motor',\n    'cheese_set_step_motor_mode_to',\n    'cheese_step_count',\n    'cheese_set_led_to_color',\n    'cheese_pick_led_to',\n    'cheese_change_led_by_rgb',\n    'cheese_setLed_to_rgb',\n    'cheese_clear_led',\n    'cheese_set_led_type_to',\n    'cheese_neopixel_set_number_and_type_to',\n    'cheese_neopixel_set_all_leds_to_pattern',\n    'cheese_neopixel_set_all_leds_to_color',\n    'cheese_neopixel_pick_all_leds_to',\n    'cheese_neopixel_change_all_leds_by_rgb',\n    'cheese_neopixel_set_all_leds_to_rgb',\n    'cheese_neopixel_clear_all_leds',\n    'cheese_neopixel_set_led_to_color',\n    'cheese_neopixel_pick_led_to',\n    'cheese_neopixel_change_led_by_rgb',\n    'cheese_neopixel_set_led_to_rgb',\n    'cheese_neopixel_clear_led',\n    'cheese_neopixel_set_led_range_to_pattern',\n    'cheese_neopixel_set_led_range_to_color',\n    'cheese_neopixel_pick_led_range_to',\n    'cheese_neopixel_change_led_range_by_rgb',\n    'cheese_neopixel_set_led_range_to_rgb',\n    'cheese_neopixel_clear_led_range',\n    'cheese_neopixel_shift',\n    'cheese_neopixel_rotate',\n    'cheese_neopixel_change_brightness_by',\n    'cheese_neopixel_set_brightness_to',\n    'cheese_write_serial',\n    'cheese_read_serial_until',\n    'cheese_set_serial_port_to',\n    'cheese_set_serial_rate_to',\n    'cheese_serial_input',\n    'cheese_pid_start',\n    'cheese_pid_set_range_to',\n    'cheese_pid_set_three_ranges_to',\n    'cheese_pid_reset_encoder',\n    'cheese_pid_input',\n    'cheese_pid_button_state',\n    'cheese_hat010_start',\n    'cheese_hat010_button',\n    'cheese_hat010_button_state',\n    'cheese_hat010_background_turn_on_xy',\n    'cheese_hat010_background_turn_off_xy',\n    'cheese_hat010_background_draw_shape_at_xy',\n    'cheese_hat010_background_draw_string_at_xy',\n    'cheese_hat010_background_draw_pattern_at_xy',\n    'cheese_hat010_clear',\n    'cheese_hat010_scroll_by_xy',\n    'cheese_hat010_sprite_set_to_shape',\n    'cheese_hat010_sprite_set_to_string',\n    'cheese_hat010_sprite_set_to_pattern',\n    'cheese_hat010_sprite_clear_show_hide',        \n    'cheese_hat010_sprite_change_positions_by_xy',\n    'cheese_hat010_sprite_set_positions_to_xy',\n    'cheese_hat010_sprite_change_position_by_value',\n    'cheese_hat010_sprite_set_position_to_value',\n    'cheese_hat010_sprite_rotate',\n    'cheese_hat010_sprite_flip_in_direction',\n    'cheese_hat010_sprite_stamp_to_background',\n    'cheese_hat010_sprite_position',\n    'cheese_hat010_sprite_touching_sprite',\n    'cheese_hat010_sprite_touching',\n    'cheese_hat010_change_brightness_by',\n    'cheese_hat010_set_brightness_to',\n];\n\nEntry.Cheese.getBlocks = function() {\n    return {\n        cheese_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                        [Lang.Blocks.ROBOID_sensor_signal_strength_dbm, 'SIGNAL_STRENGTH'],\n                    ],\n                    value: 'ACCELERATION_X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cheese_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'cheese_sensor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                                    [Lang.Blocks.ROBOID_sensor_signal_strength_dbm, 'SIGNAL_STRENGTH'],\n                                ],\n                                value: 'ACCELERATION_X',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_logo_sky_direction, 'TILT_NOT'],\n                        [Lang.Blocks.ROBOID_logo_earth_direction, 'TILT_FLIP'],\n                        [Lang.Blocks.ROBOID_power_switch_sky_direction, 'TILT_LEFT'],\n                        [Lang.Blocks.ROBOID_power_switch_earth_direction, 'TILT_RIGHT'],\n                        [Lang.Blocks.ROBOID_port_s_sky_direction, 'TILT_FORWARD'],\n                        [Lang.Blocks.ROBOID_port_s_earth_direction, 'TILT_BACKWARD'],\n                        [Lang.Blocks.ROBOID_tap, 'TAP'],\n                        [Lang.Blocks.ROBOID_free_fall, 'FREE_FALL'],\n                        [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_NOT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cheese_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'cheese_sensor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_logo_sky_direction, 'TILT_NOT'],\n                                    [Lang.Blocks.ROBOID_logo_earth_direction, 'TILT_FLIP'],\n                                    [Lang.Blocks.ROBOID_power_switch_sky_direction, 'TILT_LEFT'],\n                                    [Lang.Blocks.ROBOID_power_switch_earth_direction, 'TILT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_port_s_sky_direction, 'TILT_FORWARD'],\n                                    [Lang.Blocks.ROBOID_port_s_earth_direction, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.ROBOID_tap, 'TAP'],\n                                    [Lang.Blocks.ROBOID_free_fall, 'FREE_FALL'],\n                                    [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_NOT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_play_sound_times',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.play_sound(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.play_sound_until_done(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'cheese_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        cheese_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'cheese_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        cheese_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cheese_clear_sound',\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.clear_sound()',\n                    },\n                ],\n            },\n        },\n        cheese_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'cheese_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.play_pitch(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'cheese_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.play_note(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'cheese_rest_for',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.rest(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'cheese_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'cheese_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_sound_port_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_speaker_internal, 'INTERNAL'],\n                        [Lang.Blocks.ROBOID_speaker_port_mab, 'MAB'],\n                    ],\n                    value: 'INTERNAL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_sound_port_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setSoundPort(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_sound_port(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_speaker_internal, 'INTERNAL'],\n                                    [Lang.Blocks.ROBOID_speaker_port_mab, 'MAB'],\n                                ],\n                                value: 'INTERNAL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_input_mode_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_io_mode_makey, 'MAKEY'],\n                        [Lang.Blocks.ROBOID_io_mode_button, 'BUTTON'],\n                        [Lang.Blocks.ROBOID_io_mode_digital_pull_up, 'DIGITAL_PULL_UP'],\n                        [Lang.Blocks.ROBOID_io_mode_digital_pull_down, 'DIGITAL_PULL_DOWN'],\n                        [Lang.Blocks.ROBOID_io_mode_analog, 'ANALOG'],\n                        [Lang.Blocks.ROBOID_io_mode_voltage, 'VOLTAGE'],\n                    ],\n                    value: 'MAKEY',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_input_mode_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                MODE: 1,\n            },\n            class: 'cheese_input',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setInputModeTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_input_mode(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_io_mode_makey, 'MAKEY'],\n                                    [Lang.Blocks.ROBOID_io_mode_button, 'BUTTON'],\n                                    [Lang.Blocks.ROBOID_io_mode_digital_pull_up, 'DIGITAL_PULL_UP'],\n                                    [Lang.Blocks.ROBOID_io_mode_digital_pull_down, 'DIGITAL_PULL_DOWN'],\n                                    [Lang.Blocks.ROBOID_io_mode_analog, 'ANALOG'],\n                                    [Lang.Blocks.ROBOID_io_mode_voltage, 'VOLTAGE'],\n                                ],\n                                value: 'MAKEY',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_input_range_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                        [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                    ],\n                    value: 'INTEGER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_input_range_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                LOW1: 1,\n                HIGH1: 2,\n                LOW2: 3,\n                HIGH2: 4,\n                DECIMAL: 5,\n            },\n            class: 'cheese_input',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setInputRangeTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_input_range(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                                    [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                                ],\n                                value: 'INTEGER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_three_input_ranges_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                        [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                    ],\n                    value: 'INTEGER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['127'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['-100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_three_input_ranges_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                LOW1: 1,\n                MIDDLE1: 2,\n                HIGH1: 3,\n                LOW2: 4,\n                MIDDLE2: 5,\n                HIGH2: 6,\n                DECIMAL: 7,\n            },\n            class: 'cheese_input',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setThreeInputRangesTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_input_range_middle(%1, %2, %3, %4, %5, %6, %7, %8)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                                    [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                                ],\n                                value: 'INTEGER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_analog_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cheese_analog_input',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'cheese_input',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                if (robot) {\n                    return robot.getAnalogInput(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.analog_input(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_digital_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_digital_input',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_input',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.checkDigitalInput(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.digital_input(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_button_state',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                STATE: 1,\n            },\n            class: 'cheese_input',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.checkButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.button_state(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_pulse_mode_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sc', 'SC'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SC',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_io_mode_pulse, 'PULSE'],\n                        [Lang.Blocks.ROBOID_io_mode_pulse_pull_up, 'PULSE_PULL_UP'],\n                        [Lang.Blocks.ROBOID_io_mode_pulse_pull_down, 'PULSE_PULL_DOWN'],\n                    ],\n                    value: 'PULSE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_pulse_mode_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                MODE: 1,\n            },\n            class: 'cheese_input',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setInputModeTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_pulse_mode(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sc', 'SC'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SC',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_io_mode_pulse, 'PULSE'],\n                                    [Lang.Blocks.ROBOID_io_mode_pulse_pull_up, 'PULSE_PULL_UP'],\n                                    [Lang.Blocks.ROBOID_io_mode_pulse_pull_down, 'PULSE_PULL_DOWN'],\n                                ],\n                                value: 'PULSE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_pulse_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sc', 'SC'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SC',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cheese_pulse_input',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'cheese_input',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.checkPulseInput(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pulse_input(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sc', 'SC'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SC',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_digital_output_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                        [Lang.Blocks.ROBOID_io_port_high_current_mab, 'MAB'],\n                        [Lang.Blocks.ROBOID_io_port_high_current_mcd, 'MCD'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_digital_output_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_digital_output',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setDigitalOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_digital_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                    [Lang.Blocks.ROBOID_io_port_high_current_mab, 'MAB'],\n                                    [Lang.Blocks.ROBOID_io_port_high_current_mcd, 'MCD'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_change_pwm_output_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'cheese_change_pwm_output_by',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_pwm_output',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.changePwmOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_pwm_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_pwm_output_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'cheese_set_pwm_output_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_pwm_output',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setPwmOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_pwm_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_change_servo_motor_angle_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                        ['Ma(-)b(+)c', 'MABC'],\n                        ['Ma(-)b', 'MAB'],\n                        ['Mc(-)d', 'MCD'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'cheese_change_servo_motor_angle_by',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_servo_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.changeServoMotorAngle(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_servo_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                    ['Ma(-)b(+)c', 'MABC'],\n                                    ['Ma(-)b', 'MAB'],\n                                    ['Mc(-)d', 'MCD'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_servo_motor_angle_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                        ['Ma(-)b(+)c', 'MABC'],\n                        ['Ma(-)b', 'MAB'],\n                        ['Mc(-)d', 'MCD'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_set_servo_motor_angle_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_servo_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setServoMotorAngle(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_servo_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                    ['Ma(-)b(+)c', 'MABC'],\n                                    ['Ma(-)b', 'MAB'],\n                                    ['Mc(-)d', 'MCD'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_turn_off_servo_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                        ['Ma(-)b(+)c', 'MABC'],\n                        ['Ma(-)b', 'MAB'],\n                        ['Mc(-)d', 'MCD'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_turn_off_servo_motor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'cheese_servo_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.turnOffServoMotor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.release_servo(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                    ['Ma(-)b(+)c', 'MABC'],\n                                    ['Ma(-)b', 'MAB'],\n                                    ['Mc(-)d', 'MCD'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_change_dc_motor_velocity_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Mab', 'MAB'],\n                        ['Mcd', 'MCD'],\n                    ],\n                    value: 'MAB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'cheese_change_dc_motor_velocity_by',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_dc_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.changeDcMotorVelocity(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_dc_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Mab', 'MAB'],\n                                    ['Mcd', 'MCD'],\n                                ],\n                                value: 'MAB',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_dc_motor_velocity_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Mab', 'MAB'],\n                        ['Mcd', 'MCD'],\n                    ],\n                    value: 'MAB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'cheese_set_dc_motor_velocity_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_dc_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setDcMotorVelocity(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_dc_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Mab', 'MAB'],\n                                    ['Mcd', 'MCD'],\n                                ],\n                                value: 'MAB',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_stop_dc_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Mab', 'MAB'],\n                        ['Mcd', 'MCD'],\n                    ],\n                    value: 'MAB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_stop_dc_motor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'cheese_dc_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.stopDcMotor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.stop_dc(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Mab', 'MAB'],\n                                    ['Mcd', 'MCD'],\n                                ],\n                                value: 'MAB',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_rotate_step_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'cheese_rotate_step_motor',\n            },\n            paramsKeyMap: {\n                STEP: 0,\n                VELOCITY: 1,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.rotateStepMotor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.rotate_step(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_change_step_motor_velocity_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'cheese_change_step_motor_velocity_by',\n            },\n            paramsKeyMap: {\n                VELOCITY: 0,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.changeStepMotorVelocity(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_step_velocity(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_step_motor_velocity_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'cheese_set_step_motor_velocity_to',\n            },\n            paramsKeyMap: {\n                VELOCITY: 0,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setStepMotorVelocity(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_step_velocity(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_stop_off_step_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_io_action_stop, 'STOP'],\n                        [Lang.Blocks.ROBOID_io_action_turn_off, 'OFF'],\n                    ],\n                    value: 'STOP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_stop_off_step_motor',\n            },\n            paramsKeyMap: {\n                ACTION: 0,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.stopOffStepMotor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.step_motor(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_io_action_stop, 'STOP'],\n                                    [Lang.Blocks.ROBOID_io_action_turn_off, 'OFF'],\n                                ],\n                                value: 'STOP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_step_motor_mode_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_io_mode_normal, 'NORMAL'],\n                        [Lang.Blocks.ROBOID_io_mode_power, 'POWER'],\n                    ],\n                    value: 'NORMAL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_step_motor_mode_to',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setStepMotorMode(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_step_mode(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_io_mode_normal, 'NORMAL'],\n                                    [Lang.Blocks.ROBOID_io_mode_power, 'POWER'],\n                                ],\n                                value: 'NORMAL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_step_count: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cheese_step_count',\n            },\n            paramsKeyMap: {\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                if (robot) {\n                    return robot.getStepCount(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.step_count()',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        cheese_set_led_to_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_intensity_dark, 'DARK'],\n                        [Lang.Blocks.ROBOID_led_intensity_normal, 'NORMAL'],\n                        [Lang.Blocks.ROBOID_led_intensity_bright, 'BRIGHT'],\n                    ],\n                    value: 'NORMAL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_led_to_color',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                INTENSITY: 1,\n                COLOR: 2,\n            },\n            class: 'cheese_led',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setLedColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_led(%1, %2 %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_intensity_dark, 'DARK'],\n                                    [Lang.Blocks.ROBOID_led_intensity_normal, 'NORMAL'],\n                                    [Lang.Blocks.ROBOID_led_intensity_bright, 'BRIGHT'],\n                                ],\n                                value: 'NORMAL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_pick_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cheese_pick_led_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COLOR: 1,\n            },\n            class: 'cheese_led',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setLedRgbArray(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pick_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'cheese_led',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.changeLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_setLed_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_setLed_to_rgb',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'cheese_led',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_clear_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'cheese_led',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.clear_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_led_type_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_type_default, 'DEFAULT'],\n                        [Lang.Blocks.ROBOID_led_type_crgb, '-RGB'],\n                        [Lang.Blocks.ROBOID_led_type_crbg, '-RBG'],\n                        [Lang.Blocks.ROBOID_led_type_cgrb, '-GRB'],\n                        [Lang.Blocks.ROBOID_led_type_cgbr, '-GBR'],\n                        [Lang.Blocks.ROBOID_led_type_cbrg, '-BRG'],\n                        [Lang.Blocks.ROBOID_led_type_cbgr, '-BGR'],\n                        [Lang.Blocks.ROBOID_led_type_argb, '+RGB'],\n                        [Lang.Blocks.ROBOID_led_type_arbg, '+RBG'],\n                        [Lang.Blocks.ROBOID_led_type_agrb, '+GRB'],\n                        [Lang.Blocks.ROBOID_led_type_agbr, '+GBR'],\n                        [Lang.Blocks.ROBOID_led_type_abrg, '+BRG'],\n                        [Lang.Blocks.ROBOID_led_type_abgr, '+BGR'],\n                    ],\n                    value: 'DEFAULT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_led_type_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                TYPE: 1,\n            },\n            class: 'cheese_led',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setLedType(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_led_type(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_type_default, 'DEFAULT'],\n                                    [Lang.Blocks.ROBOID_led_type_crgb, '-RGB'],\n                                    [Lang.Blocks.ROBOID_led_type_crbg, '-RBG'],\n                                    [Lang.Blocks.ROBOID_led_type_cgrb, '-GRB'],\n                                    [Lang.Blocks.ROBOID_led_type_cgbr, '-GBR'],\n                                    [Lang.Blocks.ROBOID_led_type_cbrg, '-BRG'],\n                                    [Lang.Blocks.ROBOID_led_type_cbgr, '-BGR'],\n                                    [Lang.Blocks.ROBOID_led_type_argb, '+RGB'],\n                                    [Lang.Blocks.ROBOID_led_type_arbg, '+RBG'],\n                                    [Lang.Blocks.ROBOID_led_type_agrb, '+GRB'],\n                                    [Lang.Blocks.ROBOID_led_type_agbr, '+GBR'],\n                                    [Lang.Blocks.ROBOID_led_type_abrg, '+BRG'],\n                                    [Lang.Blocks.ROBOID_led_type_abgr, '+BGR'],\n                                ],\n                                value: 'DEFAULT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_number_and_type_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['GRB', 'GRB'],\n                        ['GRBW', 'GRBW'],\n                    ],\n                    value: 'GRB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_set_number_and_type_to',\n            },\n            paramsKeyMap: {\n                NUMBER: 0,\n                TYPE: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetNumberAndType(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_neopixel_number_type(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['GRB', 'GRB'],\n                                    ['GRBW', 'GRBW'],\n                                ],\n                                value: 'GRB',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_all_leds_to_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_neopixel_3_colors, 'FILL_3_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_6_colors, 'FILL_6_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_12_colors, 'FILL_12_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_red_green, 'GRADIENT_RED_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_red_blue, 'GRADIENT_RED_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_red_white, 'GRADIENT_RED_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_green_red, 'GRADIENT_GREEN_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_green_blue, 'GRADIENT_GREEN_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_green_white, 'GRADIENT_GREEN_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_red, 'GRADIENT_BLUE_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_green, 'GRADIENT_BLUE_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_white, 'GRADIENT_BLUE_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_white_red, 'GRADIENT_WHITE_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_white_green, 'GRADIENT_WHITE_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_white_blue, 'GRADIENT_WHITE_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_red_black, 'GRADIENT_RED_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_green_black, 'GRADIENT_GREEN_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_black, 'GRADIENT_BLUE_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_white_black, 'GRADIENT_WHITE_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_black_red, 'GRADIENT_BLACK_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_black_green, 'GRADIENT_BLACK_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_black_blue, 'GRADIENT_BLACK_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_black_white, 'GRADIENT_BLACK_WHITE'],\n                    ],\n                    value: 'FILL_3_COLORS',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_set_all_leds_to_pattern',\n            },\n            paramsKeyMap: {\n                PATTERN: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetAllPattern(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_all_neopixel_pattern(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_neopixel_3_colors, 'FILL_3_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_6_colors, 'FILL_6_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_12_colors, 'FILL_12_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_green, 'GRADIENT_RED_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_blue, 'GRADIENT_RED_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_white, 'GRADIENT_RED_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_red, 'GRADIENT_GREEN_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_blue, 'GRADIENT_GREEN_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_white, 'GRADIENT_GREEN_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_red, 'GRADIENT_BLUE_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_green, 'GRADIENT_BLUE_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_white, 'GRADIENT_BLUE_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_red, 'GRADIENT_WHITE_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_green, 'GRADIENT_WHITE_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_blue, 'GRADIENT_WHITE_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_black, 'GRADIENT_RED_BLACK'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_black, 'GRADIENT_GREEN_BLACK'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_black, 'GRADIENT_BLUE_BLACK'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_black, 'GRADIENT_WHITE_BLACK'],\n                                    [Lang.Blocks.ROBOID_neopixel_black_red, 'GRADIENT_BLACK_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_black_green, 'GRADIENT_BLACK_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_black_blue, 'GRADIENT_BLACK_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_black_white, 'GRADIENT_BLACK_WHITE'],\n                                ],\n                                value: 'FILL_3_COLORS',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_all_leds_to_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_set_all_leds_to_color',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetAllColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_all_neopixel(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_pick_all_leds_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_pick_all_leds_to',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetAllRgbArray(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pick_all_neopixel(%1)',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_change_all_leds_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_change_all_leds_by_rgb',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelChangeAllRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_all_neopixel_rgb(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_all_leds_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_set_all_leds_to_rgb',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetAllRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_all_neopixel_rgb(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_clear_all_leds: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cheese_neopixel_clear_all_leds',\n            },\n            paramsKeyMap: {\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelClearAll(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.clear_all_neopixel()',\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_led_to_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_set_led_to_color',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n                COLOR: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetLedColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_neopixel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_pick_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_pick_led_to',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n                COLOR: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetLedRgbArray(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pick_neopixel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelChangeLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_neopixel_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_set_led_to_rgb',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_neopixel_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_clear_led',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelClearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.clear_neopixel(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_led_range_to_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_neopixel_3_colors, 'FILL_3_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_6_colors, 'FILL_6_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_12_colors, 'FILL_12_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_red_green, 'GRADIENT_RED_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_red_blue, 'GRADIENT_RED_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_red_white, 'GRADIENT_RED_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_green_red, 'GRADIENT_GREEN_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_green_blue, 'GRADIENT_GREEN_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_green_white, 'GRADIENT_GREEN_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_red, 'GRADIENT_BLUE_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_green, 'GRADIENT_BLUE_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_white, 'GRADIENT_BLUE_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_white_red, 'GRADIENT_WHITE_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_white_green, 'GRADIENT_WHITE_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_white_blue, 'GRADIENT_WHITE_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_red_black, 'GRADIENT_RED_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_green_black, 'GRADIENT_GREEN_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_black, 'GRADIENT_BLUE_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_white_black, 'GRADIENT_WHITE_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_black_red, 'GRADIENT_BLACK_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_black_green, 'GRADIENT_BLACK_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_black_blue, 'GRADIENT_BLACK_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_black_white, 'GRADIENT_BLACK_WHITE'],\n                    ],\n                    value: 'FILL_3_COLORS',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_set_led_range_to_pattern',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                PATTERN: 2,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetRangePattern(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_neopixel_range_pattern(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_neopixel_3_colors, 'FILL_3_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_6_colors, 'FILL_6_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_12_colors, 'FILL_12_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_green, 'GRADIENT_RED_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_blue, 'GRADIENT_RED_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_white, 'GRADIENT_RED_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_red, 'GRADIENT_GREEN_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_blue, 'GRADIENT_GREEN_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_white, 'GRADIENT_GREEN_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_red, 'GRADIENT_BLUE_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_green, 'GRADIENT_BLUE_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_white, 'GRADIENT_BLUE_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_red, 'GRADIENT_WHITE_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_green, 'GRADIENT_WHITE_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_blue, 'GRADIENT_WHITE_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_black, 'GRADIENT_RED_BLACK'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_black, 'GRADIENT_GREEN_BLACK'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_black, 'GRADIENT_BLUE_BLACK'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_black, 'GRADIENT_WHITE_BLACK'],\n                                    [Lang.Blocks.ROBOID_neopixel_black_red, 'GRADIENT_BLACK_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_black_green, 'GRADIENT_BLACK_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_black_blue, 'GRADIENT_BLACK_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_black_white, 'GRADIENT_BLACK_WHITE'],\n                                ],\n                                value: 'FILL_3_COLORS',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_led_range_to_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_set_led_range_to_color',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                INCREMENT: 2,\n                COLOR: 3,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetRangeColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_neopixel_range(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_pick_led_range_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_neopixel_pick_led_range_to',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                INCREMENT: 2,\n                COLOR: 3,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetRangeRgbArray(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pick_neopixel_range(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_change_led_range_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_change_led_range_by_rgb',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                INCREMENT: 2,\n                RED: 3,\n                GREEN: 4,\n                BLUE: 5,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelChangeRangeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_neopixel_range_rgb(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_led_range_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_set_led_range_to_rgb',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                INCREMENT: 2,\n                RED: 3,\n                GREEN: 4,\n                BLUE: 5,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetRangeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_neopixel_range_rgb(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_clear_led_range: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_clear_led_range',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                INCREMENT: 2,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelClearRange(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.clear_neopixel_range(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_shift: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_shift',\n            },\n            paramsKeyMap: {\n                BIT: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelShift(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.shift_neopixel(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_rotate',\n            },\n            paramsKeyMap: {\n                BIT: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelRotate(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.rotate_neopixel(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_change_brightness_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_change_brightness_by',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelChangeBrightness(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.add_neopixel_brightness(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_neopixel_set_brightness_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'cheese_neopixel_set_brightness_to',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.neopixelSetBrightness(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_neopixel_brightness(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_write_serial: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_serial_string, 'STRING'],\n                        [Lang.Blocks.ROBOID_serial_string_line, 'STRING_LINE'],\n                    ],\n                    value: 'STRING',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['abc123'],\n                    },\n                    null,\n                ],\n                type: 'cheese_write_serial',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n                STRING: 1,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.writeSerial(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.write_serial(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_serial_string, 'STRING'],\n                                    [Lang.Blocks.ROBOID_serial_string_line, 'STRING_LINE'],\n                                ],\n                                value: 'STRING',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_read_serial_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_serial_all, 'ALL'],\n                        [Lang.Blocks.ROBOID_serial_until_comma, 'COMMA'],\n                        [Lang.Blocks.ROBOID_serial_until_colon, 'COLON'],\n                        [Lang.Blocks.ROBOID_serial_until_dollar, 'DOLLAR'],\n                        [Lang.Blocks.ROBOID_serial_until_sharp, 'SHARP'],\n                        [Lang.Blocks.ROBOID_serial_until_new_line, 'NEW_LINE'],\n                    ],\n                    value: 'ALL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_read_serial_until',\n            },\n            paramsKeyMap: {\n                DELIMITER: 0,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.readSerialUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.read_serial(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_serial_all, 'ALL'],\n                                    [Lang.Blocks.ROBOID_serial_until_comma, 'COMMA'],\n                                    [Lang.Blocks.ROBOID_serial_until_colon, 'COLON'],\n                                    [Lang.Blocks.ROBOID_serial_until_dollar, 'DOLLAR'],\n                                    [Lang.Blocks.ROBOID_serial_until_sharp, 'SHARP'],\n                                    [Lang.Blocks.ROBOID_serial_until_new_line, 'NEW_LINE'],\n                                ],\n                                value: 'ALL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_serial_port_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_serial_port_wa_rb, 'WRITE_READ'],\n                        [Lang.Blocks.ROBOID_serial_port_ra_wb, 'READ_WRITE'],\n                        [Lang.Blocks.ROBOID_serial_port_wa, 'WRITE'],\n                        [Lang.Blocks.ROBOID_serial_port_ra, 'READ'],\n                    ],\n                    value: 'WRITE_READ',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_serial_port_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setSerialPort(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_serial_port(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_serial_port_wa_rb, 'WRITE_READ'],\n                                    [Lang.Blocks.ROBOID_serial_port_ra_wb, 'READ_WRITE'],\n                                    [Lang.Blocks.ROBOID_serial_port_wa, 'WRITE'],\n                                    [Lang.Blocks.ROBOID_serial_port_ra, 'READ'],\n                                ],\n                                value: 'WRITE_READ',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_set_serial_rate_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['9600', '9600'],\n                        ['14400', '14400'],\n                        ['19200', '19200'],\n                        ['28800', '28800'],\n                        ['38400', '38400'],\n                        ['57600', '57600'],\n                        ['76800', '76800'],\n                        ['115200', '115200'],\n                    ],\n                    value: '9600',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_set_serial_rate_to',\n            },\n            paramsKeyMap: {\n                BAUD: 0,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.setSerialRate(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.set_serial_rate(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['9600', '9600'],\n                                    ['14400', '14400'],\n                                    ['19200', '19200'],\n                                    ['28800', '28800'],\n                                    ['38400', '38400'],\n                                    ['57600', '57600'],\n                                    ['76800', '76800'],\n                                    ['115200', '115200'],\n                                ],\n                                value: '9600',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_serial_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'cheese_serial_input',\n            },\n            paramsKeyMap: {\n            },\n            class: 'cheese_serial',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                if (robot) {\n                    return robot.getSerialInput(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.serial_input()',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        cheese_pid_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_pid_10, '10'],\n                        [Lang.Blocks.ROBOID_pid_11_1, '11-1'],\n                        [Lang.Blocks.ROBOID_pid_11_2, '11-2'],\n                        [Lang.Blocks.ROBOID_pid_11_3, '11-3'],\n                        [Lang.Blocks.ROBOID_pid_12, '12'],\n                        [Lang.Blocks.ROBOID_pid_13, '13'],\n                        [Lang.Blocks.ROBOID_pid_14, '14'],\n//                        [Lang.Blocks.ROBOID_pid_15, '15'],\n                        [Lang.Blocks.ROBOID_pid_16, '16'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_pid_start',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.pidStart(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pid_start(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_pid_10, '10'],\n                                    [Lang.Blocks.ROBOID_pid_11_1, '11-1'],\n                                    [Lang.Blocks.ROBOID_pid_11_2, '11-2'],\n                                    [Lang.Blocks.ROBOID_pid_11_3, '11-3'],\n                                    [Lang.Blocks.ROBOID_pid_12, '12'],\n                                    [Lang.Blocks.ROBOID_pid_13, '13'],\n                                    [Lang.Blocks.ROBOID_pid_14, '14'],\n//                                    [Lang.Blocks.ROBOID_pid_15, '15'],\n                                    [Lang.Blocks.ROBOID_pid_16, '16'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_pid_set_range_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                        [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                        [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                        [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                    ],\n                    value: 'X1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                        [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                    ],\n                    value: 'INTEGER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_pid_set_range_to',\n            },\n            paramsKeyMap: {\n                INPUT: 0,\n                LOW1: 1,\n                HIGH1: 2,\n                LOW2: 3,\n                HIGH2: 4,\n                DECIMAL: 5,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.pidSetRangeTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pid_set_input_range(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                                    [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                                    [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                                    [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                                ],\n                                value: 'X1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                                    [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                                ],\n                                value: 'INTEGER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_pid_set_three_ranges_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                        [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                        [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                        [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                    ],\n                    value: 'X1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                        [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                    ],\n                    value: 'INTEGER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['127'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['-100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_pid_set_three_ranges_to',\n            },\n            paramsKeyMap: {\n                INPUT: 0,\n                LOW1: 1,\n                MIDDLE1: 2,\n                HIGH1: 3,\n                LOW2: 4,\n                MIDDLE2: 5,\n                HIGH2: 6,\n                DECIMAL: 7,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.pidSetThreeRangesTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pid_set_input_range_middle(%1, %2, %3, %4, %5, %6, %7, %8)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                                    [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                                    [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                                    [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                                ],\n                                value: 'X1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                                    [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                                ],\n                                value: 'INTEGER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_pid_reset_encoder: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cheese_pid_reset_encoder',\n            },\n            paramsKeyMap: {\n            },\n            class: 'cheese_pid',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.pidResetEncoder(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pid_reset_encoder()',\n                    },\n                ],\n            },\n        },\n        cheese_pid_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_pid_distance, 'DISTANCE'],\n                        [Lang.Blocks.ROBOID_pid_temperature, 'TEMPERATURE'],\n                        [Lang.Blocks.ROBOID_pid_humidity, 'HUMIDITY'],\n                        [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                        [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                        [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                        [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                        [Lang.Blocks.ROBOID_pid_button1, 'BUTTON1'],\n                        [Lang.Blocks.ROBOID_pid_button2, 'BUTTON2'],\n                        [Lang.Blocks.ROBOID_pid_encoder, 'ENCODER'],\n                    ],\n                    value: 'DISTANCE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cheese_pid_input',\n            },\n            paramsKeyMap: {\n                INPUT: 0,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                if (robot) {\n                    return robot.pidGetInput(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pid_input(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_pid_distance, 'DISTANCE'],\n                                    [Lang.Blocks.ROBOID_pid_temperature, 'TEMPERATURE'],\n                                    [Lang.Blocks.ROBOID_pid_humidity, 'HUMIDITY'],\n                                    [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                                    [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                                    [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                                    [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                                    [Lang.Blocks.ROBOID_pid_button1, 'BUTTON1'],\n                                    [Lang.Blocks.ROBOID_pid_button2, 'BUTTON2'],\n                                    [Lang.Blocks.ROBOID_pid_encoder, 'ENCODER'],\n                                ],\n                                value: 'DISTANCE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_pid_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_pid_button_state',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n                STATE: 1,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.pidCheckButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.pid_button_state(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cheese_hat010_start',\n            },\n            paramsKeyMap: {\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010Start(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_start()',\n                    },\n                ],\n            },\n        },\n        cheese_hat010_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cheese_hat010_button',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                if (robot) {\n                    return robot.hat010GetButton(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_button(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A', 'A'],\n                                    ['B', 'B'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_hat010_button_state',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n                STATE: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010CheckButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_button_state(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A', 'A'],\n                                    ['B', 'B'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_double_clicked, 'DOUBLE_CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_background_turn_on_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_hat010_background_turn_on_xy',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                COLOR: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010BackgroundTurnOnXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_turn_on_background_pixel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_background_turn_off_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_background_turn_off_xy',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010BackgroundTurnOffXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_turn_off_background_pixel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_background_draw_shape_at_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_shape_square, 'SQUARE'],\n                        [Lang.Blocks.ROBOID_shape_triangle, 'TRIANGLE'],\n                        [Lang.Blocks.ROBOID_shape_diamond, 'DIAMOND'],\n                        [Lang.Blocks.ROBOID_shape_circle, 'CIRCLE'],\n                        [Lang.Blocks.ROBOID_shape_x, 'X'],\n                        [Lang.Blocks.ROBOID_shape_like, 'LIKE'],\n                        [Lang.Blocks.ROBOID_shape_dislike, 'DISLIKE'],\n                        [Lang.Blocks.ROBOID_shape_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_shape_open_mouth, 'OPEN_MOUTH'],\n                        [Lang.Blocks.ROBOID_shape_close_mouth, 'CLOSE_MOUTH'],\n                        [Lang.Blocks.ROBOID_shape_walk1, 'WALK1'],\n                        [Lang.Blocks.ROBOID_shape_walk2, 'WALK2'],\n                        [Lang.Blocks.ROBOID_shape_heart, 'HEART'],\n                        [Lang.Blocks.ROBOID_shape_star, 'STAR'],\n                        [Lang.Blocks.ROBOID_shape_airplane, 'AIRPLANE'],\n                        [Lang.Blocks.ROBOID_shape_puppy, 'PUPPY'],\n                        [Lang.Blocks.ROBOID_shape_butterfly, 'BUTTERFLY'],\n                        [Lang.Blocks.ROBOID_shape_quarter_note, 'QUARTER_NOTE'],\n                        [Lang.Blocks.ROBOID_shape_eighth_note, 'EIGHTH_NOTE'],\n                        [Lang.Blocks.ROBOID_shape_left_arrow, 'LEFT_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_right_arrow, 'RIGHT_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_up_arrow, 'UP_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_down_arrow, 'DOWN_ARRAY'],\n                    ],\n                    value: 'SQUARE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_background_draw_shape_at_xy',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                SHAPE: 1,\n                X: 2,\n                Y: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010BackgroundDrawShapeAtXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_draw_background_shape(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_shape_square, 'SQUARE'],\n                                    [Lang.Blocks.ROBOID_shape_triangle, 'TRIANGLE'],\n                                    [Lang.Blocks.ROBOID_shape_diamond, 'DIAMOND'],\n                                    [Lang.Blocks.ROBOID_shape_circle, 'CIRCLE'],\n                                    [Lang.Blocks.ROBOID_shape_x, 'X'],\n                                    [Lang.Blocks.ROBOID_shape_like, 'LIKE'],\n                                    [Lang.Blocks.ROBOID_shape_dislike, 'DISLIKE'],\n                                    [Lang.Blocks.ROBOID_shape_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_shape_open_mouth, 'OPEN_MOUTH'],\n                                    [Lang.Blocks.ROBOID_shape_close_mouth, 'CLOSE_MOUTH'],\n                                    [Lang.Blocks.ROBOID_shape_walk1, 'WALK1'],\n                                    [Lang.Blocks.ROBOID_shape_walk2, 'WALK2'],\n                                    [Lang.Blocks.ROBOID_shape_heart, 'HEART'],\n                                    [Lang.Blocks.ROBOID_shape_star, 'STAR'],\n                                    [Lang.Blocks.ROBOID_shape_airplane, 'AIRPLANE'],\n                                    [Lang.Blocks.ROBOID_shape_puppy, 'PUPPY'],\n                                    [Lang.Blocks.ROBOID_shape_butterfly, 'BUTTERFLY'],\n                                    [Lang.Blocks.ROBOID_shape_quarter_note, 'QUARTER_NOTE'],\n                                    [Lang.Blocks.ROBOID_shape_eighth_note, 'EIGHTH_NOTE'],\n                                    [Lang.Blocks.ROBOID_shape_left_arrow, 'LEFT_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_right_arrow, 'RIGHT_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_up_arrow, 'UP_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_down_arrow, 'DOWN_ARRAY'],\n                                ],\n                                value: 'SQUARE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_background_draw_string_at_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['abc123'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_background_draw_string_at_xy',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                TEXT: 1,\n                X: 2,\n                Y: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010BackgroundDrawStringAtXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_draw_background_string(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_background_draw_pattern_at_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10010'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_background_draw_pattern_at_xy',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                PATTERN: 1,\n                X: 2,\n                Y: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010BackgroundDrawPatternAtXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_draw_background_pattern(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                        [Lang.Blocks.ROBOID_hat_all, 'ALL'],\n                    ],\n                    value: 'BACKGROUND',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cheese_hat010_clear',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010Clear(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_clear(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                                    [Lang.Blocks.ROBOID_hat_all, 'ALL'],\n                                ],\n                                value: 'BACKGROUND',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_scroll_by_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                        [Lang.Blocks.ROBOID_hat_all, 'ALL'],\n                    ],\n                    value: 'BACKGROUND',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_scroll_by_xy',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                X: 1,\n                Y: 2,\n                \n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010ScrollByXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_scroll(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                                    [Lang.Blocks.ROBOID_hat_all, 'ALL'],\n                                ],\n                                value: 'BACKGROUND',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_set_to_shape: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_shape_square, 'SQUARE'],\n                        [Lang.Blocks.ROBOID_shape_triangle, 'TRIANGLE'],\n                        [Lang.Blocks.ROBOID_shape_diamond, 'DIAMOND'],\n                        [Lang.Blocks.ROBOID_shape_circle, 'CIRCLE'],\n                        [Lang.Blocks.ROBOID_shape_x, 'X'],\n                        [Lang.Blocks.ROBOID_shape_like, 'LIKE'],\n                        [Lang.Blocks.ROBOID_shape_dislike, 'DISLIKE'],\n                        [Lang.Blocks.ROBOID_shape_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_shape_open_mouth, 'OPEN_MOUTH'],\n                        [Lang.Blocks.ROBOID_shape_close_mouth, 'CLOSE_MOUTH'],\n                        [Lang.Blocks.ROBOID_shape_walk1, 'WALK1'],\n                        [Lang.Blocks.ROBOID_shape_walk2, 'WALK2'],\n                        [Lang.Blocks.ROBOID_shape_heart, 'HEART'],\n                        [Lang.Blocks.ROBOID_shape_star, 'STAR'],\n                        [Lang.Blocks.ROBOID_shape_airplane, 'AIRPLANE'],\n                        [Lang.Blocks.ROBOID_shape_puppy, 'PUPPY'],\n                        [Lang.Blocks.ROBOID_shape_butterfly, 'BUTTERFLY'],\n                        [Lang.Blocks.ROBOID_shape_quarter_note, 'QUARTER_NOTE'],\n                        [Lang.Blocks.ROBOID_shape_eighth_note, 'EIGHTH_NOTE'],\n                        [Lang.Blocks.ROBOID_shape_left_arrow, 'LEFT_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_right_arrow, 'RIGHT_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_up_arrow, 'UP_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_down_arrow, 'DOWN_ARRAY'],\n                    ],\n                    value: 'SQUARE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_set_to_shape',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                COLOR: 1,\n                SHAPE: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteSetToShape(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_set_sprite_shape(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_shape_square, 'SQUARE'],\n                                    [Lang.Blocks.ROBOID_shape_triangle, 'TRIANGLE'],\n                                    [Lang.Blocks.ROBOID_shape_diamond, 'DIAMOND'],\n                                    [Lang.Blocks.ROBOID_shape_circle, 'CIRCLE'],\n                                    [Lang.Blocks.ROBOID_shape_x, 'X'],\n                                    [Lang.Blocks.ROBOID_shape_like, 'LIKE'],\n                                    [Lang.Blocks.ROBOID_shape_dislike, 'DISLIKE'],\n                                    [Lang.Blocks.ROBOID_shape_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_shape_open_mouth, 'OPEN_MOUTH'],\n                                    [Lang.Blocks.ROBOID_shape_close_mouth, 'CLOSE_MOUTH'],\n                                    [Lang.Blocks.ROBOID_shape_walk1, 'WALK1'],\n                                    [Lang.Blocks.ROBOID_shape_walk2, 'WALK2'],\n                                    [Lang.Blocks.ROBOID_shape_heart, 'HEART'],\n                                    [Lang.Blocks.ROBOID_shape_star, 'STAR'],\n                                    [Lang.Blocks.ROBOID_shape_airplane, 'AIRPLANE'],\n                                    [Lang.Blocks.ROBOID_shape_puppy, 'PUPPY'],\n                                    [Lang.Blocks.ROBOID_shape_butterfly, 'BUTTERFLY'],\n                                    [Lang.Blocks.ROBOID_shape_quarter_note, 'QUARTER_NOTE'],\n                                    [Lang.Blocks.ROBOID_shape_eighth_note, 'EIGHTH_NOTE'],\n                                    [Lang.Blocks.ROBOID_shape_left_arrow, 'LEFT_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_right_arrow, 'RIGHT_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_up_arrow, 'UP_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_down_arrow, 'DOWN_ARRAY'],\n                                ],\n                                value: 'SQUARE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_set_to_string: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['abc123'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_set_to_string',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                COLOR: 1,\n                TEXT: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteSetToString(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_set_sprite_string(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_set_to_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10010'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_set_to_pattern',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                COLOR: 1,\n                PATTERN: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteSetToPattern(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_set_sprite_pattern(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_clear_show_hide: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_clear, 'CLEAR'],\n                        [Lang.Blocks.ROBOID_hat_show, 'SHOW'],\n                        [Lang.Blocks.ROBOID_hat_hide, 'HIDE'],\n                    ],\n                    value: 'CLEAR',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_clear_show_hide',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                ACTION: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteClearShowHide(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_sprite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_clear, 'CLEAR'],\n                                    [Lang.Blocks.ROBOID_hat_show, 'SHOW'],\n                                    [Lang.Blocks.ROBOID_hat_hide, 'HIDE'],\n                                ],\n                                value: 'CLEAR',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_change_positions_by_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_change_positions_by_xy',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                X: 1,\n                Y: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteChangePositionsByXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_add_sprite_positions(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_set_positions_to_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_set_positions_to_xy',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                X: 1,\n                Y: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteSetPositionsToXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_set_sprite_positions(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_change_position_by_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', 'X'],\n                        ['y', 'Y'],\n                    ],\n                    value: 'X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_change_position_by_value',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                POSITION: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteChangePositionByValue(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_add_sprite_position(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['x', 'X'],\n                                    ['y', 'Y'],\n                                ],\n                                value: 'X',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_set_position_to_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', 'X'],\n                        ['y', 'Y'],\n                    ],\n                    value: 'X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_set_position_to_value',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                POSITION: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteSetPositionToValue(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_set_sprite_position(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['x', 'X'],\n                                    ['y', 'Y'],\n                                ],\n                                value: 'X',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_clockwise, 'CLOCKWISE'],\n                        [Lang.Blocks.ROBOID_hat_counterclockwise, 'COUNTERCLOCKWISE'],\n                    ],\n                    value: 'CLOCKWISE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_rotate',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                DIRECTION: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteRotate(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_rotate_sprite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_clockwise, 'CLOCKWISE'],\n                                    [Lang.Blocks.ROBOID_hat_counterclockwise, 'COUNTERCLOCKWISE'],\n                                ],\n                                value: 'CLOCKWISE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_flip_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_left_right, 'LEFT_RIGHT'],\n                        [Lang.Blocks.ROBOID_hat_up_down, 'UP_DOWN'],\n                    ],\n                    value: 'LEFT_RIGHT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_flip_in_direction',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                DIRECTION: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteFlipInDirection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_flip_sprite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_left_right, 'LEFT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_hat_up_down, 'UP_DOWN'],\n                                ],\n                                value: 'LEFT_RIGHT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_stamp_to_background: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_stamp_to_background',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SpriteStampToBackground(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_stamp(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_position: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', 'X'],\n                        ['y', 'Y'],\n                    ],\n                    value: 'X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_position',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                POSITION: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                if (robot) {\n                    return robot.hat010GetSpritePosition(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_sprite_position(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['x', 'X'],\n                                    ['y', 'Y'],\n                                ],\n                                value: 'X',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_touching_sprite: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                ],\n                type: 'cheese_hat010_sprite_touching_sprite',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                TARGET: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010CheckCheckSpriteSpriteTouched(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_touching_sprite(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_sprite_touching: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                        [Lang.Blocks.ROBOID_hat_other_sprite, 'OTHER_SPRITE'],\n                        [Lang.Blocks.ROBOID_hat_left_wall, 'LEFT_WALL'],\n                        [Lang.Blocks.ROBOID_hat_right_wall, 'RIGHT_WALL'],\n                        [Lang.Blocks.ROBOID_hat_top_wall, 'TOP_WALL'],\n                        [Lang.Blocks.ROBOID_hat_bottom_wall, 'BOTTOM_WALL'],\n                        [Lang.Blocks.ROBOID_hat_any_wall, 'ANY_WALL'],\n                    ],\n                    value: 'BACKGROUND',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_sprite_touching',\n            },\n            paramsKeyMap: {\n                SPRITE: 0,\n                TARGET: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010CheckCheckSpriteTouched(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_touching(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                                    [Lang.Blocks.ROBOID_hat_other_sprite, 'OTHER_SPRITE'],\n                                    [Lang.Blocks.ROBOID_hat_left_wall, 'LEFT_WALL'],\n                                    [Lang.Blocks.ROBOID_hat_right_wall, 'RIGHT_WALL'],\n                                    [Lang.Blocks.ROBOID_hat_top_wall, 'TOP_WALL'],\n                                    [Lang.Blocks.ROBOID_hat_bottom_wall, 'BOTTOM_WALL'],\n                                    [Lang.Blocks.ROBOID_hat_any_wall, 'ANY_WALL'],\n                                ],\n                                value: 'BACKGROUND',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_change_brightness_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_change_brightness_by',\n            },\n            paramsKeyMap: {\n                BRIGHTNESS: 0,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010ChangeBrightnessBy(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_add_brightness(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cheese_hat010_set_brightness_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'cheese_hat010_set_brightness_to',\n            },\n            paramsKeyMap: {\n                BRIGHTNESS: 0,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['cheese'],\n            func(sprite, script) {\n                const robot = Entry.Cheese.getRobot();\n                return robot ? robot.hat010SetBrightnessTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Cheese.hat010_set_brightness(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Cheese;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_choco.js",
    "content": "'use strict';\r\n\r\nEntry.Choco = {\r\n    id: '45.1',\r\n    name: 'choco',\r\n    url: 'http://jjomulrak.com',\r\n    imageName: 'choco.png',\r\n    title: {\r\n        ko: '쪼코',\r\n        en: 'Choco',\r\n    },\r\n\r\n    getHashKey: function() {\r\n        let key = new Date().getSeconds().toString(16);\r\n        if (key.length === 1) {\r\n            key += ((Math.random() * 16) | 0).toString(16);\r\n        }\r\n        return Entry.generateHash() + key;\r\n    },\r\n\r\n    setZero: function() {\r\n        Entry.hw.update(); // 해당 데이터를 하드웨어에 전달한다.\r\n    },\r\n};\r\n\r\nEntry.Choco.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                choco_move_forward: '앞으로 %1 %2 이동 %3',\r\n                choco_move_backward: '뒤로 %1 %2 이동 %3',\r\n                choco_turn_left: '왼쪽으로 %1 %2 돌기 %3',\r\n                choco_turn_right: '오른쪽으로 %1 %2 돌기 %3',\r\n                choco_move_right_left: '오른쪽으로 %1 왼쪽으로 %2 %3 이동 %4',\r\n                choco_onoff_led_rear: '뒤쪽 LED %1 %2',\r\n                choco_set_led_color: '%1 LED %2 %3',\r\n                choco_play_sound: '%1 소리내기 %2',\r\n                choco_is_front_sensor: '전방센서',\r\n                choco_is_bottom_sensor: '바닥센서',\r\n                choco_is_light_sensor: '빛센서',\r\n                choco_get_front_sensor: '전방센서',\r\n                choco_get_bottom_sensor: '바닥센서',\r\n                choco_get_light_sensor: '빛센서',\r\n            },\r\n            Blocks: {\r\n                choco_move_step: '칸',\r\n                choco_move_cm: 'cm',\r\n                choco_trun_drgree: '도',\r\n                choco_trun_round: '바퀴',\r\n                choco_toggle_on: '켜기',\r\n                choco_toggle_off: '끄기',\r\n                choco_direction_right: '오른쪽',\r\n                choco_direction_left: '왼쪽',\r\n                choco_direction_dual: '양쪽(오른쪽,왼쪽)',\r\n\r\n                choco_color_off: '끄기',\r\n                choco_color_blue: '파란색',\r\n                choco_color_red: '빨간색',\r\n                choco_color_green: '초록색',\r\n                choco_color_yellow: '노랑색',\r\n                choco_color_pink: '분홍색',\r\n                choco_color_bluegreen: '청록색',\r\n                choco_color_white: '흰색',\r\n\r\n                choco_sound_car: '자동차',\r\n                choco_sound_robot: '로봇',\r\n                choco_sound_dog: '강아지',\r\n                choco_sound_cat: '고양이',\r\n                choco_sound_chicken: '닭',\r\n                choco_sound_tiger: '호랑이',\r\n                choco_sound_lion: '사자',\r\n                choco_sound_fart: '방귀소리',\r\n                choco_sound_helicopter: '헬리콥터',\r\n                choco_sound_train: '기차',\r\n                choco_sound_frog: '개구리',\r\n                choco_sound_jjajan: '짜잔(효과음)',\r\n                choco_sound_sheep: '양',\r\n                choco_sound_elephant: '코끼리',\r\n                choco_sound_camel: '낙타',\r\n                choco_sound_dolphin: '고래',\r\n                choco_sound_ttiyong: '띠용(효과음)',\r\n                choco_sound_hello_parrot: '헬로(앵무새)',\r\n                choco_sound_hello_manga: '헬로(만화)',\r\n                choco_sound_hello_man: '헬로(남자)',\r\n                choco_sound_ppong: '뽕(효과음)',\r\n                choco_sound_buzzer: '부저(효과음)',\r\n                choco_sound_ttalilalan: '따라리라란~(효과음)',\r\n                choco_sound_ttattattatta: '따따따따~(효과음)',\r\n                choco_sound_laughter: '웃음소리',\r\n                choco_sound_magic: '마술(효과음)',\r\n                choco_sound_woodpecker: '딱따구리',\r\n                choco_sound_bird: '새',\r\n                choco_sound_burp: '트림',\r\n                choco_sound_hiccup: '딸꾹질',\r\n                choco_sound_doridori: '도리도리',\r\n                choco_sound_firetruck: '소방차',\r\n                choco_sound_police_car: '경찰차',\r\n                choco_sound_applause: '박수환호',\r\n                choco_sound_kiss: '뽀뽀',\r\n                choco_sound_missile: '미사일',\r\n                choco_sound_angry_duck: '화난오리',\r\n                choco_sound_fly: '파리',\r\n                choco_sound_ufo: 'UFO',\r\n                choco_sound_fanfare: '팡파레',\r\n                choco_sound_sigh: '한숨소리',\r\n                choco_sound_alright: '올라잇~',\r\n                choco_sound_genius: '지니어스~',\r\n                choco_sound_no: '노우~',\r\n                choco_sound_wow: '오우~',\r\n                choco_sound_yahoo: '야호~',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                choco_move_forward: 'move forward %1 %2 block %3',\r\n                choco_move_backward: 'move backward %1 %2 block %3',\r\n                choco_turn_left: '%1 %2 to the left %3',\r\n                choco_turn_right: '%1 %2 to the right %3',\r\n                choco_move_right_left: 'move right %1 left %2 %3 %4',\r\n                choco_onoff_led_rear: 'Rear LED %1 %2',\r\n                choco_set_led_color: '%1 LED %2 %3',\r\n                choco_play_sound: 'play %1 %2',\r\n                choco_is_front_sensor: 'front sensor',\r\n                choco_is_bottom_sensor: 'bottom sensor',\r\n                choco_is_light_sensor: 'light sensor',\r\n                choco_get_front_sensor: 'front sensor',\r\n                choco_get_bottom_sensor: 'bottom sensor',\r\n                choco_get_light_sensor: 'light sensor',\r\n            },\r\n            Blocks: {\r\n                choco_move_step: 'step',\r\n                choco_move_cm: 'cm',\r\n                choco_trun_drgree: 'degree',\r\n                choco_trun_round: 'turns',\r\n                choco_toggle_on: 'on',\r\n                choco_toggle_off: 'off',\r\n                choco_direction_right: 'right',\r\n                choco_direction_left: 'left',\r\n                choco_direction_dual: 'all(right,left)',\r\n\r\n                choco_color_off: 'off',\r\n                choco_color_blue: 'blue',\r\n                choco_color_red: 'red',\r\n                choco_color_green: 'green',\r\n                choco_color_yellow: 'yellow',\r\n                choco_color_pink: 'pink',\r\n                choco_color_bluegreen: 'bluegreen',\r\n                choco_color_white: 'white',\r\n\r\n                choco_sound_car: 'car',\r\n                choco_sound_robot: 'robot',\r\n                choco_sound_dog: 'dog',\r\n                choco_sound_cat: 'cat',\r\n                choco_sound_chicken: 'chicken',\r\n                choco_sound_tiger: 'tiger',\r\n                choco_sound_lion: 'lion',\r\n                choco_sound_fart: 'fart',\r\n                choco_sound_helicopter: 'helicopter',\r\n                choco_sound_train: 'train',\r\n                choco_sound_frog: 'frog',\r\n                choco_sound_jjajan: 'jjajan(effect)',\r\n                choco_sound_sheep: 'sheep',\r\n                choco_sound_elephant: 'elephant',\r\n                choco_sound_camel: 'camel',\r\n                choco_sound_dolphin: 'dolphin',\r\n                choco_sound_ttiyong: 'ttiyong(effect)',\r\n                choco_sound_hello_parrot: 'hello(parrot)',\r\n                choco_sound_hello_manga: 'hello(manga)',\r\n                choco_sound_hello_man: 'hello(man)',\r\n                choco_sound_ppong: 'ppong(effect)',\r\n                choco_sound_buzzer: 'buzzer(effect)',\r\n                choco_sound_ttalilalan: 'ttalilalan(effect)',\r\n                choco_sound_ttattattatta: 'ttattattatta(effect)',\r\n                choco_sound_laughter: 'laughter',\r\n                choco_sound_magic: 'magic(effect)',\r\n                choco_sound_woodpecker: 'woodpecker',\r\n                choco_sound_bird: 'bird',\r\n                choco_sound_burp: 'burp',\r\n                choco_sound_hiccup: 'hiccup',\r\n                choco_sound_doridori: 'doridori',\r\n                choco_sound_firetruck: 'fire truck',\r\n                choco_sound_police_car: 'police car',\r\n                choco_sound_applause: 'applause',\r\n                choco_sound_kiss: 'kiss',\r\n                choco_sound_missile: 'missile',\r\n                choco_sound_angry_duck: 'angry duck',\r\n                choco_sound_fly: 'fly',\r\n                choco_sound_ufo: 'UFO',\r\n                choco_sound_fanfare: 'fanfare',\r\n                choco_sound_sigh: 'sigh',\r\n                choco_sound_alright: 'alright',\r\n                choco_sound_genius: 'genius',\r\n                choco_sound_no: 'no',\r\n                choco_sound_wow: 'wow',\r\n                choco_sound_yahoo: 'yahoo',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.Choco.blockMenuBlocks = [\r\n    //choco\r\n    'choco_move_forward',\r\n    'choco_move_backward',\r\n    'choco_turn_left',\r\n    'choco_turn_right',\r\n    'choco_move_right_left',\r\n    'choco_onoff_led_rear',\r\n    'choco_set_led_color',\r\n    'choco_play_sound',\r\n\r\n    'choco_is_front_sensor',\r\n    'choco_is_bottom_sensor',\r\n    'choco_is_light_sensor',\r\n    'choco_get_front_sensor',\r\n    'choco_get_bottom_sensor',\r\n    'choco_get_light_sensor',\r\n];\r\n\r\nEntry.Choco.getBlocks = function() {\r\n    return {\r\n        choco_move_forward: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_move_step, 'step'],\r\n                        [Lang.Blocks.choco_move_cm, 'cm'],\r\n                    ],\r\n                    value: 'step',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [1, 'step', null],\r\n                type: 'choco_move_forward',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_CNT: 0,\r\n                MOVE_UNIT: 1,\r\n            },\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const move_cnt = script.getValue('MOVE_CNT');\r\n                let move_unit = script.getValue('MOVE_UNIT');\r\n                if (move_cnt === 0) return script.callReturn();\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Choco.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: 'move_forward',\r\n                        data: {\r\n                            param1: move_cnt,\r\n                            param2: move_unit,\r\n                        },\r\n                        time: Date.now(),\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                }\r\n\r\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        choco_move_backward: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_move_step, 'step'],\r\n                        [Lang.Blocks.choco_move_cm, 'cm'],\r\n                    ],\r\n                    value: 'step',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [1, 'step', null],\r\n                type: 'choco_move_backward',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_CNT: 0,\r\n                MOVE_UNIT: 1,\r\n            },\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const move_cnt = script.getValue('MOVE_CNT');\r\n                let move_unit = script.getValue('MOVE_UNIT');\r\n                if (move_cnt === 0) return script.callReturn();\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Choco.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: 'move_backward',\r\n                        data: {\r\n                            param1: move_cnt,\r\n                            param2: move_unit,\r\n                        },\r\n                        time: Date.now(),\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                }\r\n\r\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        choco_turn_left: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_trun_drgree, 'degree'],\r\n                        [Lang.Blocks.choco_trun_round, 'turns'],\r\n                    ],\r\n                    value: 'degree',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [90, 'degree', null],\r\n                type: 'choco_turn_left',\r\n            },\r\n            paramsKeyMap: {\r\n                TURN_CNT: 0,\r\n                TURN_UNIT: 1,\r\n            },\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const turn_cnt = script.getValue('TURN_CNT');\r\n                let turn_unit = script.getValue('TURN_UNIT');\r\n                if (turn_cnt < 0) turn_cnt = 0;\r\n                if (turn_cnt === 0) return script.callReturn();\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Choco.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: 'turn_left',\r\n                        data: {\r\n                            param1: turn_cnt,\r\n                            param2: turn_unit,\r\n                        },\r\n                        time: Date.now(),\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                }\r\n\r\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        choco_turn_right: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_trun_drgree, 'degree'],\r\n                        [Lang.Blocks.choco_trun_round, 'turns'],\r\n                    ],\r\n                    value: 'degree',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [90, 'degree', null],\r\n                type: 'choco_turn_right',\r\n            },\r\n            paramsKeyMap: {\r\n                TURN_CNT: 0,\r\n                TURN_UNIT: 1,\r\n            },\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const turn_cnt = script.getValue('TURN_CNT');\r\n                let turn_unit = script.getValue('TURN_UNIT');\r\n                if (turn_cnt < 0) turn_cnt = 0;\r\n                if (turn_cnt === 0) return script.callReturn();\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Choco.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: 'turn_right',\r\n                        data: {\r\n                            param1: turn_cnt,\r\n                            param2: turn_unit,\r\n                        },\r\n                        time: Date.now(),\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                }\r\n\r\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        choco_move_right_left: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_move_step, 'step'],\r\n                        [Lang.Blocks.choco_move_cm, 'cm'],\r\n                    ],\r\n                    value: 'step',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [1, 1, 'step', null],\r\n                type: 'choco_move_right_left',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_RIGHT_CNT: 0,\r\n                MOVE_LEFT_CNT: 1,\r\n                MOVE_UNIT: 2,\r\n            },\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const move_right_cnt = script.getValue('MOVE_RIGHT_CNT');\r\n                const move_left_cnt = script.getValue('MOVE_LEFT_CNT');\r\n                let move_unit = script.getValue('MOVE_UNIT');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Choco.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: 'move_right_left',\r\n                        data: {\r\n                            param1: move_right_cnt,\r\n                            param2: move_left_cnt,\r\n                            param3: move_unit,\r\n                        },\r\n                        time: Date.now(),\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                }\r\n\r\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        choco_onoff_led_rear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_toggle_on, 'On'],\r\n                        [Lang.Blocks.choco_toggle_off, 'Off'],\r\n                    ],\r\n                    value: 'On',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['On', null],\r\n                type: 'choco_onoff_led_rear',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                const led_onoff = script.getValue('VALUE');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Choco.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: 'onoff_led_rear',\r\n                        data: {\r\n                            param1: led_onoff,\r\n                        },\r\n                        time: Date.now(),\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                }\r\n\r\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        choco_set_led_color: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_direction_right, 'right'],\r\n                        [Lang.Blocks.choco_direction_left, 'left'],\r\n                        [Lang.Blocks.choco_direction_dual, 'dual'],\r\n                    ],\r\n                    value: 'right',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_color_off, 0],\r\n                        [Lang.Blocks.choco_color_blue, 1],\r\n                        [Lang.Blocks.choco_color_red, 2],\r\n                        [Lang.Blocks.choco_color_green, 3],\r\n                        [Lang.Blocks.choco_color_yellow, 4],\r\n                        [Lang.Blocks.choco_color_pink, 5],\r\n                        [Lang.Blocks.choco_color_bluegreen, 6],\r\n                        [Lang.Blocks.choco_color_white, 7],\r\n                    ],\r\n                    value: 1,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['right', 1, null],\r\n                type: 'choco_set_led_color',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION: 0,\r\n                COLOR: 1,\r\n            },\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                const led_dir = script.getValue('DIRECTION');\r\n                const led_color = script.getValue('COLOR');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Choco.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: 'set_led_color',\r\n                        data: {\r\n                            param1: led_dir,\r\n                            param2: led_color,\r\n                        },\r\n                        time: Date.now(),\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                }\r\n\r\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        choco_play_sound: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.choco_sound_car, 1],\r\n                        [Lang.Blocks.choco_sound_robot, 2],\r\n                        [Lang.Blocks.choco_sound_dog, 3],\r\n                        [Lang.Blocks.choco_sound_cat, 4],\r\n                        [Lang.Blocks.choco_sound_chicken, 5],\r\n                        [Lang.Blocks.choco_sound_tiger, 6],\r\n                        [Lang.Blocks.choco_sound_lion, 7],\r\n                        [Lang.Blocks.choco_sound_fart, 8],\r\n                        [Lang.Blocks.choco_sound_helicopter, 9],\r\n                        [Lang.Blocks.choco_sound_train, 10],\r\n                        [Lang.Blocks.choco_sound_frog, 11],\r\n                        [Lang.Blocks.choco_sound_jjajan, 12],\r\n                        [Lang.Blocks.choco_sound_sheep, 13],\r\n                        [Lang.Blocks.choco_sound_elephant, 14],\r\n                        [Lang.Blocks.choco_sound_camel, 15],\r\n                        [Lang.Blocks.choco_sound_dolphin, 16],\r\n                        [Lang.Blocks.choco_sound_ttiyong, 17],\r\n                        [Lang.Blocks.choco_sound_hello_parrot, 18],\r\n                        [Lang.Blocks.choco_sound_hello_manga, 19],\r\n                        [Lang.Blocks.choco_sound_hello_man, 20],\r\n                        [Lang.Blocks.choco_sound_ppong, 21],\r\n                        [Lang.Blocks.choco_sound_buzzer, 22],\r\n                        [Lang.Blocks.choco_sound_ttalilalan, 23],\r\n                        [Lang.Blocks.choco_sound_ttattattatta, 24],\r\n                        [Lang.Blocks.choco_sound_laughter, 25],\r\n                        [Lang.Blocks.choco_sound_magic, 26],\r\n                        [Lang.Blocks.choco_sound_woodpecker, 27],\r\n                        [Lang.Blocks.choco_sound_bird, 28],\r\n                        [Lang.Blocks.choco_sound_burp, 29],\r\n                        [Lang.Blocks.choco_sound_hiccup, 30],\r\n                        [Lang.Blocks.choco_sound_doridori, 31],\r\n                        [Lang.Blocks.choco_sound_firetruck, 32],\r\n                        [Lang.Blocks.choco_sound_police_car, 33],\r\n                        [Lang.Blocks.choco_sound_applause, 34],\r\n                        [Lang.Blocks.choco_sound_kiss, 35],\r\n                        [Lang.Blocks.choco_sound_missile, 36],\r\n                        [Lang.Blocks.choco_sound_angry_duck, 37],\r\n                        [Lang.Blocks.choco_sound_fly, 38],\r\n                        [Lang.Blocks.choco_sound_ufo, 39],\r\n                        [Lang.Blocks.choco_sound_fanfare, 40],\r\n                        [Lang.Blocks.choco_sound_sigh, 41],\r\n                        [Lang.Blocks.choco_sound_alright, 42],\r\n                        [Lang.Blocks.choco_sound_genius, 43],\r\n                        [Lang.Blocks.choco_sound_no, 44],\r\n                        [Lang.Blocks.choco_sound_wow, 45],\r\n                        [Lang.Blocks.choco_sound_yahoo, 46],\r\n                    ],\r\n                    value: 1,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [1, null],\r\n                type: 'choco_play_sound',\r\n            },\r\n            paramsKeyMap: {\r\n                SOUND: 0,\r\n            },\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                const sound = script.getValue('SOUND');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Choco.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: 'play_sound',\r\n                        data: {\r\n                            param1: sound,\r\n                        },\r\n                        time: Date.now(),\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                }\r\n\r\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        choco_is_front_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'choco_is_front_sensor',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = false;\r\n                if (pd.sensorData) {\r\n                    retVal = pd.sensorData.is_front_sensor;\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n        choco_is_bottom_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'choco_is_bottom_sensor',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = false;\r\n                if (pd.sensorData) {\r\n                    retVal = pd.sensorData.is_bottom_sensor;\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n        choco_is_light_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'choco_is_light_sensor',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = false;\r\n                if (pd.sensorData) {\r\n                    retVal = pd.sensorData.is_light_sensor;\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n\r\n        choco_get_front_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'choco_get_front_sensor',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = 0;\r\n                if (pd.sensorData) {\r\n                    retVal = pd.sensorData.front_sensor;\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n        choco_get_bottom_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'choco_get_bottom_sensor',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = 0;\r\n                if (pd.sensorData) {\r\n                    retVal = pd.sensorData.bottom_sensor;\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n        choco_get_light_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'choco_get_light_sensor',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'choco_command',\r\n            isNotFor: ['choco'],\r\n            func: function(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = 0;\r\n                if (pd.sensorData) {\r\n                    retVal = pd.sensorData.light_sensor;\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n    };\r\n};\r\nmodule.exports = Entry.Choco;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_choco2.js",
    "content": "'use strict';\n\nEntry.Choco2 = {\n    id: '45.2',\n    name: 'choco2',\n    url: 'http://jjomulrak.com',\n    imageName: 'choco2.png',\n    title: {\n        ko: '쪼코2',\n        en: 'Choco2',\n    },\n\n    getHashKey: function() {\n        let key = new Date().getSeconds().toString(16);\n        if (key.length === 1) {\n            key += ((Math.random() * 16) | 0).toString(16);\n        }\n        return Entry.generateHash() + key;\n    },\n\n    setZero: function() {\n        Entry.hw.update(); // 해당 데이터를 하드웨어에 전달한다.\n    },\n};\n\nEntry.Choco2.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                choco2_move_forward: '앞으로 %1 %2 이동 %3',\n                choco2_move_backward: '뒤로 %1 %2 이동 %3',\n                choco2_turn_left: '왼쪽으로 %1 %2 돌기 %3',\n                choco2_turn_right: '오른쪽으로 %1 %2 돌기 %3',\n                choco2_move_right_left: '오른쪽으로 %1 왼쪽으로 %2 %3 이동 %4',\n                choco2_onoff_led_rear: '뒤쪽 LED %1 %2',\n                choco2_set_led_color: '%1 LED %2 %3',\n                choco2_play_sound: '%1 소리내기 %2',\n                choco2_is_front_sensor: '전방센서',\n                choco2_is_bottom_sensor: '바닥센서',\n                choco2_is_light_sensor: '빛센서',\n                choco2_get_front_sensor: '전방센서',\n                choco2_get_bottom_sensor: '바닥센서',\n                choco2_get_light_sensor: '빛센서',\n            },\n            Blocks: {\n                choco2_move_step: '칸',\n                choco2_move_cm: 'cm',\n                choco2_trun_drgree: '도',\n                choco2_trun_round: '바퀴',\n                choco2_toggle_on: '켜기',\n                choco2_toggle_off: '끄기',\n                choco2_direction_right: '오른쪽',\n                choco2_direction_left: '왼쪽',\n                choco2_direction_dual: '양쪽(오른쪽,왼쪽)',\n\n                choco2_color_off: '끄기',\n                choco2_color_blue: '파란색',\n                choco2_color_red: '빨간색',\n                choco2_color_green: '초록색',\n                choco2_color_yellow: '노랑색',\n                choco2_color_pink: '분홍색',\n                choco2_color_bluegreen: '청록색',\n                choco2_color_white: '흰색',\n\n                choco2_sound_car: '자동차',\n                choco2_sound_robot: '로봇',\n                choco2_sound_dog: '강아지',\n                choco2_sound_cat: '고양이',\n                choco2_sound_chicken: '닭',\n                choco2_sound_tiger: '호랑이',\n                choco2_sound_lion: '사자',\n                choco2_sound_fart: '방귀소리',\n                choco2_sound_helicopter: '헬리콥터',\n                choco2_sound_train: '기차',\n                choco2_sound_frog: '개구리',\n                choco2_sound_jjajan: '짜잔(효과음)',\n                choco2_sound_sheep: '양',\n                choco2_sound_elephant: '코끼리',\n                choco2_sound_camel: '낙타',\n                choco2_sound_dolphin: '고래',\n                choco2_sound_ttiyong: '띠용(효과음)',\n                choco2_sound_hello_parrot: '헬로(앵무새)',\n                choco2_sound_hello_manga: '헬로(만화)',\n                choco2_sound_hello_man: '헬로(남자)',\n                choco2_sound_ppong: '뽕(효과음)',\n                choco2_sound_buzzer: '부저(효과음)',\n                choco2_sound_ttalilalan: '따라리라란~(효과음)',\n                choco2_sound_ttattattatta: '따따따따~(효과음)',\n                choco2_sound_laughter: '웃음소리',\n                choco2_sound_magic: '마술(효과음)',\n                choco2_sound_woodpecker: '딱따구리',\n                choco2_sound_bird: '새',\n                choco2_sound_burp: '트림',\n                choco2_sound_hiccup: '딸꾹질',\n                choco2_sound_doridori: '도리도리',\n                choco2_sound_firetruck: '소방차',\n                choco2_sound_police_car: '경찰차',\n                choco2_sound_applause: '박수환호',\n                choco2_sound_kiss: '뽀뽀',\n                choco2_sound_missile: '미사일',\n                choco2_sound_angry_duck: '화난오리',\n                choco2_sound_fly: '파리',\n                choco2_sound_ufo: 'UFO',\n                choco2_sound_fanfare: '팡파레',\n                choco2_sound_sigh: '한숨소리',\n                choco2_sound_alright: '올라잇~',\n                choco2_sound_genius: '지니어스~',\n                choco2_sound_no: '노우~',\n                choco2_sound_wow: '오우~',\n                choco2_sound_yahoo: '야호~',\n\n                choco2_sound_low_do: '낮은 도',\n                choco2_sound_low_dosharp: '낮은 도#',\n                choco2_sound_low_re: '낮은 레',\n                choco2_sound_low_resharp: '낮은 레#',\n                choco2_sound_low_mi: '낮은 미',\n                choco2_sound_low_fa: '낮은 파',\n                choco2_sound_low_fasharp: '낮은 파#',\n                choco2_sound_low_sol: '낮은 솔',\n                choco2_sound_low_solsharp: '낮은 솔#',\n                choco2_sound_low_ra: '낮은 라',\n                choco2_sound_low_rasharp: '낮은 라#',\n                choco2_sound_low_si: '낮은 시',\n                choco2_sound_do: '도',\n                choco2_sound_dosharp: '도#',\n                choco2_sound_re: '레',\n                choco2_sound_resharp: '레#',\n                choco2_sound_mi: '미',\n                choco2_sound_fa: '파',\n                choco2_sound_fasharp: '파#',\n                choco2_sound_sol: '솔',\n                choco2_sound_solsharp: '솔#',\n                choco2_sound_ra: '라',\n                choco2_sound_rasharp: '라#',\n                choco2_sound_si: '시',\n                choco2_sound_high_do: '높은 도',\n                choco2_sound_high_dosharp: '높은 도#',\n                choco2_sound_high_re: '높은 레',\n                choco2_sound_high_resharp: '높은 레#',\n                choco2_sound_high_mi: '높은 미',\n                choco2_sound_high_fa: '높은 파',\n                choco2_sound_high_fasharp: '높은 파#',\n                choco2_sound_high_sol: '높은 솔',\n                choco2_sound_high_solsharp: '높은 솔#',\n                choco2_sound_high_ra: '높은 라',\n                choco2_sound_high_rasharp: '높은 라#',\n                choco2_sound_high_si: '높은 시',\n            },\n        },\n        en: {\n            template: {\n                choco2_move_forward: 'move forward %1 %2 block %3',\n                choco2_move_backward: 'move backward %1 %2 block %3',\n                choco2_turn_left: '%1 %2 to the left %3',\n                choco2_turn_right: '%1 %2 to the right %3',\n                choco2_move_right_left: 'move right %1 left %2 %3 %4',\n                choco2_onoff_led_rear: 'Rear LED %1 %2',\n                choco2_set_led_color: '%1 LED %2 %3',\n                choco2_play_sound: 'play %1 %2',\n                choco2_is_front_sensor: 'front sensor',\n                choco2_is_bottom_sensor: 'bottom sensor',\n                choco2_is_light_sensor: 'light sensor',\n                choco2_get_front_sensor: 'front sensor',\n                choco2_get_bottom_sensor: 'bottom sensor',\n                choco2_get_light_sensor: 'light sensor',\n            },\n            Blocks: {\n                choco2_move_step: 'step',\n                choco2_move_cm: 'cm',\n                choco2_trun_drgree: 'degree',\n                choco2_trun_round: 'turns',\n                choco2_toggle_on: 'on',\n                choco2_toggle_off: 'off',\n                choco2_direction_right: 'right',\n                choco2_direction_left: 'left',\n                choco2_direction_dual: 'all(right,left)',\n\n                choco2_color_off: 'off',\n                choco2_color_blue: 'blue',\n                choco2_color_red: 'red',\n                choco2_color_green: 'green',\n                choco2_color_yellow: 'yellow',\n                choco2_color_pink: 'pink',\n                choco2_color_bluegreen: 'bluegreen',\n                choco2_color_white: 'white',\n\n                choco2_sound_car: 'car',\n                choco2_sound_robot: 'robot',\n                choco2_sound_dog: 'dog',\n                choco2_sound_cat: 'cat',\n                choco2_sound_chicken: 'chicken',\n                choco2_sound_tiger: 'tiger',\n                choco2_sound_lion: 'lion',\n                choco2_sound_fart: 'fart',\n                choco2_sound_helicopter: 'helicopter',\n                choco2_sound_train: 'train',\n                choco2_sound_frog: 'frog',\n                choco2_sound_jjajan: 'jjajan(effect)',\n                choco2_sound_sheep: 'sheep',\n                choco2_sound_elephant: 'elephant',\n                choco2_sound_camel: 'camel',\n                choco2_sound_dolphin: 'dolphin',\n                choco2_sound_ttiyong: 'ttiyong(effect)',\n                choco2_sound_hello_parrot: 'hello(parrot)',\n                choco2_sound_hello_manga: 'hello(manga)',\n                choco2_sound_hello_man: 'hello(man)',\n                choco2_sound_ppong: 'ppong(effect)',\n                choco2_sound_buzzer: 'buzzer(effect)',\n                choco2_sound_ttalilalan: 'ttalilalan(effect)',\n                choco2_sound_ttattattatta: 'ttattattatta(effect)',\n                choco2_sound_laughter: 'laughter',\n                choco2_sound_magic: 'magic(effect)',\n                choco2_sound_woodpecker: 'woodpecker',\n                choco2_sound_bird: 'bird',\n                choco2_sound_burp: 'burp',\n                choco2_sound_hiccup: 'hiccup',\n                choco2_sound_doridori: 'doridori',\n                choco2_sound_firetruck: 'fire truck',\n                choco2_sound_police_car: 'police car',\n                choco2_sound_applause: 'applause',\n                choco2_sound_kiss: 'kiss',\n                choco2_sound_missile: 'missile',\n                choco2_sound_angry_duck: 'angry duck',\n                choco2_sound_fly: 'fly',\n                choco2_sound_ufo: 'UFO',\n                choco2_sound_fanfare: 'fanfare',\n                choco2_sound_sigh: 'sigh',\n                choco2_sound_alright: 'alright',\n                choco2_sound_genius: 'genius',\n                choco2_sound_no: 'no',\n                choco2_sound_wow: 'wow',\n                choco2_sound_yahoo: 'yahoo',\n\n                choco2_sound_low_do: 'low do',\n                choco2_sound_low_dosharp: 'low do#',\n                choco2_sound_low_re: 'low re',\n                choco2_sound_low_resharp: 'low re#',\n                choco2_sound_low_mi: 'low mi',\n                choco2_sound_low_fa: 'low fa',\n                choco2_sound_low_fasharp: 'low fa#',\n                choco2_sound_low_sol: 'low sol',\n                choco2_sound_low_solsharp: 'low sol#',\n                choco2_sound_low_ra: 'low ra',\n                choco2_sound_low_rasharp: 'low ra#',\n                choco2_sound_low_si: 'low si',\n                choco2_sound_do: 'do',\n                choco2_sound_dosharp: 'do#',\n                choco2_sound_re: 're',\n                choco2_sound_resharp: 're#',\n                choco2_sound_mi: 'mi',\n                choco2_sound_fa: 'fa',\n                choco2_sound_fasharp: 'fa#',\n                choco2_sound_sol: 'sol',\n                choco2_sound_solsharp: 'sol#',\n                choco2_sound_ra: 'ra',\n                choco2_sound_rasharp: 'ra#',\n                choco2_sound_si: 'si',\n                choco2_sound_high_do: 'high do',\n                choco2_sound_high_dosharp: 'high do#',\n                choco2_sound_high_re: 'high re',\n                choco2_sound_high_resharp: 'high re#',\n                choco2_sound_high_mi: 'high mi',\n                choco2_sound_high_fa: 'high fa',\n                choco2_sound_high_fasharp: 'high fa#',\n                choco2_sound_high_sol: 'high sol',\n                choco2_sound_high_solsharp: 'high sol#',\n                choco2_sound_high_ra: 'high ra',\n                choco2_sound_high_rasharp: 'high ra#',\n                choco2_sound_high_si: 'high si',\n            },\n        },\n    };\n};\n\nEntry.Choco2.blockMenuBlocks = [\n    //choco\n    'choco2_move_forward',\n    'choco2_move_backward',\n    'choco2_turn_left',\n    'choco2_turn_right',\n    'choco2_move_right_left',\n    'choco2_onoff_led_rear',\n    'choco2_set_led_color',\n    'choco2_play_sound',\n\n    'choco2_is_front_sensor',\n    'choco2_is_bottom_sensor',\n    'choco2_is_light_sensor',\n    'choco2_get_front_sensor',\n    'choco2_get_bottom_sensor',\n    'choco2_get_light_sensor',\n];\n\nEntry.Choco2.getBlocks = function() {\n    return {\n        choco2_move_forward: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_move_step, 'step'],\n                        [Lang.Blocks.choco2_move_cm, 'cm'],\n                    ],\n                    value: 'step',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, 'step', null],\n                type: 'choco2_move_forward',\n            },\n            paramsKeyMap: {\n                MOVE_CNT: 0,\n                MOVE_UNIT: 1,\n            },\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n\n                const move_cnt = script.getValue('MOVE_CNT');\n                let move_unit = script.getValue('MOVE_UNIT');\n                if (move_cnt === 0) return script.callReturn();\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    const msgId = Entry.Choco2.getHashKey();\n                    script.msg_id = msgId;\n                    sq.msg_id = script.msg_id;\n                    const msg = {\n                        id: msgId,\n                        type: 'move_forward',\n                        data: {\n                            param1: move_cnt,\n                            param2: move_unit,\n                        },\n                        time: Date.now(),\n                    };\n                    sq.msg = msg;\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    delete pd.msgId;\n\n                    return script.callReturn();\n                }\n                return script;\n            },\n        },\n        choco2_move_backward: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_move_step, 'step'],\n                        [Lang.Blocks.choco2_move_cm, 'cm'],\n                    ],\n                    value: 'step',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, 'step', null],\n                type: 'choco2_move_backward',\n            },\n            paramsKeyMap: {\n                MOVE_CNT: 0,\n                MOVE_UNIT: 1,\n            },\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n\n                const move_cnt = script.getValue('MOVE_CNT');\n                let move_unit = script.getValue('MOVE_UNIT');\n                if (move_cnt === 0) return script.callReturn();\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    const msgId = Entry.Choco2.getHashKey();\n                    script.msg_id = msgId;\n                    sq.msg_id = script.msg_id;\n                    const msg = {\n                        id: msgId,\n                        type: 'move_backward',\n                        data: {\n                            param1: move_cnt,\n                            param2: move_unit,\n                        },\n                        time: Date.now(),\n                    };\n                    sq.msg = msg;\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    delete pd.msgId;\n                    return script.callReturn();\n                }\n                return script;\n            },\n        },\n        choco2_turn_left: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_trun_drgree, 'degree'],\n                        [Lang.Blocks.choco2_trun_round, 'turns'],\n                    ],\n                    value: 'degree',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [90, 'degree', null],\n                type: 'choco2_turn_left',\n            },\n            paramsKeyMap: {\n                TURN_CNT: 0,\n                TURN_UNIT: 1,\n            },\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n\n                const turn_cnt = script.getValue('TURN_CNT');\n                let turn_unit = script.getValue('TURN_UNIT');\n                if (turn_cnt < 0) turn_cnt = 0;\n                if (turn_cnt === 0) return script.callReturn();\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    const msgId = Entry.Choco2.getHashKey();\n                    script.msg_id = msgId;\n                    sq.msg_id = script.msg_id;\n                    const msg = {\n                        id: msgId,\n                        type: 'turn_left',\n                        data: {\n                            param1: turn_cnt,\n                            param2: turn_unit,\n                        },\n                        time: Date.now(),\n                    };\n                    sq.msg = msg;\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    delete pd.msgId;\n                    return script.callReturn();\n                }\n                return script;\n            },\n        },\n        choco2_turn_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_trun_drgree, 'degree'],\n                        [Lang.Blocks.choco2_trun_round, 'turns'],\n                    ],\n                    value: 'degree',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [90, 'degree', null],\n                type: 'choco2_turn_right',\n            },\n            paramsKeyMap: {\n                TURN_CNT: 0,\n                TURN_UNIT: 1,\n            },\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n\n                const turn_cnt = script.getValue('TURN_CNT');\n                let turn_unit = script.getValue('TURN_UNIT');\n                if (turn_cnt < 0) turn_cnt = 0;\n                if (turn_cnt === 0) return script.callReturn();\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    const msgId = Entry.Choco2.getHashKey();\n                    script.msg_id = msgId;\n                    sq.msg_id = script.msg_id;\n                    const msg = {\n                        id: msgId,\n                        type: 'turn_right',\n                        data: {\n                            param1: turn_cnt,\n                            param2: turn_unit,\n                        },\n                        time: Date.now(),\n                    };\n                    sq.msg = msg;\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    delete pd.msgId;\n                    return script.callReturn();\n                }\n                return script;\n            },\n        },\n        choco2_move_right_left: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_move_step, 'step'],\n                        [Lang.Blocks.choco2_move_cm, 'cm'],\n                    ],\n                    value: 'step',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, 1, 'step', null],\n                type: 'choco2_move_right_left',\n            },\n            paramsKeyMap: {\n                MOVE_RIGHT_CNT: 0,\n                MOVE_LEFT_CNT: 1,\n                MOVE_UNIT: 2,\n            },\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n\n                const move_right_cnt = script.getValue('MOVE_RIGHT_CNT');\n                const move_left_cnt = script.getValue('MOVE_LEFT_CNT');\n                let move_unit = script.getValue('MOVE_UNIT');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    const msgId = Entry.Choco2.getHashKey();\n                    script.msg_id = msgId;\n                    sq.msg_id = script.msg_id;\n                    const msg = {\n                        id: msgId,\n                        type: 'move_right_left',\n                        data: {\n                            param1: move_right_cnt,\n                            param2: move_left_cnt,\n                            param3: move_unit,\n                        },\n                        time: Date.now(),\n                    };\n                    sq.msg = msg;\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    delete pd.msgId;\n                    return script.callReturn();\n                }\n                return script;\n            },\n        },\n        choco2_onoff_led_rear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_toggle_on, 'On'],\n                        [Lang.Blocks.choco2_toggle_off, 'Off'],\n                    ],\n                    value: 'On',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['On', null],\n                type: 'choco2_onoff_led_rear',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                const led_onoff = script.getValue('VALUE');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    const msgId = Entry.Choco2.getHashKey();\n                    script.msg_id = msgId;\n                    sq.msg_id = script.msg_id;\n                    const msg = {\n                        id: msgId,\n                        type: 'onoff_led_rear',\n                        data: {\n                            param1: led_onoff,\n                        },\n                        time: Date.now(),\n                    };\n                    sq.msg = msg;\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    delete pd.msgId;\n                    return script.callReturn();\n                }\n                return script;\n            },\n        },\n        choco2_set_led_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_direction_right, 'right'],\n                        [Lang.Blocks.choco2_direction_left, 'left'],\n                        [Lang.Blocks.choco2_direction_dual, 'dual'],\n                    ],\n                    value: 'right',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_color_off, 0],\n                        [Lang.Blocks.choco2_color_blue, 1],\n                        [Lang.Blocks.choco2_color_red, 2],\n                        [Lang.Blocks.choco2_color_green, 3],\n                        [Lang.Blocks.choco2_color_yellow, 4],\n                        [Lang.Blocks.choco2_color_pink, 5],\n                        [Lang.Blocks.choco2_color_bluegreen, 6],\n                        [Lang.Blocks.choco2_color_white, 7],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['right', 1, null],\n                type: 'choco2_set_led_color',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                COLOR: 1,\n            },\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                const led_dir = script.getValue('DIRECTION');\n                const led_color = script.getValue('COLOR');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    const msgId = Entry.Choco2.getHashKey();\n                    script.msg_id = msgId;\n                    sq.msg_id = script.msg_id;\n                    const msg = {\n                        id: msgId,\n                        type: 'set_led_color',\n                        data: {\n                            param1: led_dir,\n                            param2: led_color,\n                        },\n                        time: Date.now(),\n                    };\n                    sq.msg = msg;\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    delete pd.msgId;\n                    return script.callReturn();\n                }\n                return script;\n            },\n        },\n        choco2_play_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.choco2_sound_car, 1],\n                        [Lang.Blocks.choco2_sound_robot, 2],\n                        [Lang.Blocks.choco2_sound_dog, 3],\n                        [Lang.Blocks.choco2_sound_cat, 4],\n                        [Lang.Blocks.choco2_sound_chicken, 5],\n                        [Lang.Blocks.choco2_sound_tiger, 6],\n                        [Lang.Blocks.choco2_sound_lion, 7],\n                        [Lang.Blocks.choco2_sound_fart, 8],\n                        [Lang.Blocks.choco2_sound_helicopter, 9],\n                        [Lang.Blocks.choco2_sound_train, 10],\n                        [Lang.Blocks.choco2_sound_frog, 11],\n                        [Lang.Blocks.choco2_sound_jjajan, 12],\n                        [Lang.Blocks.choco2_sound_sheep, 13],\n                        [Lang.Blocks.choco2_sound_elephant, 14],\n                        [Lang.Blocks.choco2_sound_camel, 15],\n                        [Lang.Blocks.choco2_sound_dolphin, 16],\n                        [Lang.Blocks.choco2_sound_ttiyong, 17],\n                        [Lang.Blocks.choco2_sound_hello_parrot, 18],\n                        [Lang.Blocks.choco2_sound_hello_manga, 19],\n                        [Lang.Blocks.choco2_sound_hello_man, 20],\n                        [Lang.Blocks.choco2_sound_ppong, 21],\n                        [Lang.Blocks.choco2_sound_buzzer, 22],\n                        [Lang.Blocks.choco2_sound_ttalilalan, 23],\n                        [Lang.Blocks.choco2_sound_ttattattatta, 24],\n                        [Lang.Blocks.choco2_sound_laughter, 25],\n                        [Lang.Blocks.choco2_sound_magic, 26],\n                        [Lang.Blocks.choco2_sound_woodpecker, 27],\n                        [Lang.Blocks.choco2_sound_bird, 28],\n                        [Lang.Blocks.choco2_sound_burp, 29],\n                        [Lang.Blocks.choco2_sound_hiccup, 30],\n                        [Lang.Blocks.choco2_sound_doridori, 31],\n                        [Lang.Blocks.choco2_sound_firetruck, 32],\n                        [Lang.Blocks.choco2_sound_police_car, 33],\n                        [Lang.Blocks.choco2_sound_applause, 34],\n                        [Lang.Blocks.choco2_sound_kiss, 35],\n                        [Lang.Blocks.choco2_sound_missile, 36],\n                        [Lang.Blocks.choco2_sound_angry_duck, 37],\n                        [Lang.Blocks.choco2_sound_fly, 38],\n                        [Lang.Blocks.choco2_sound_ufo, 39],\n                        [Lang.Blocks.choco2_sound_fanfare, 40],\n                        [Lang.Blocks.choco2_sound_sigh, 41],\n                        [Lang.Blocks.choco2_sound_alright, 42],\n                        [Lang.Blocks.choco2_sound_genius, 43],\n                        [Lang.Blocks.choco2_sound_no, 44],\n                        [Lang.Blocks.choco2_sound_wow, 45],\n                        [Lang.Blocks.choco2_sound_yahoo, 46],\n\n                        [Lang.Blocks.choco2_sound_low_do, 47],\n                        [Lang.Blocks.choco2_sound_low_dosharp, 48],\n                        [Lang.Blocks.choco2_sound_low_re, 49],\n                        [Lang.Blocks.choco2_sound_low_resharp, 50],\n                        [Lang.Blocks.choco2_sound_low_mi, 51],\n                        [Lang.Blocks.choco2_sound_low_fa, 52],\n                        [Lang.Blocks.choco2_sound_low_fasharp, 53],\n                        [Lang.Blocks.choco2_sound_low_sol, 54],\n                        [Lang.Blocks.choco2_sound_low_solsharp, 55],\n                        [Lang.Blocks.choco2_sound_low_ra, 56],\n                        [Lang.Blocks.choco2_sound_low_rasharp, 57],\n                        [Lang.Blocks.choco2_sound_low_si, 58],\n                        [Lang.Blocks.choco2_sound_do, 59],\n                        [Lang.Blocks.choco2_sound_dosharp, 60],\n                        [Lang.Blocks.choco2_sound_re, 61],\n                        [Lang.Blocks.choco2_sound_resharp, 62],\n                        [Lang.Blocks.choco2_sound_mi, 63],\n                        [Lang.Blocks.choco2_sound_fa, 64],\n                        [Lang.Blocks.choco2_sound_fasharp, 65],\n                        [Lang.Blocks.choco2_sound_sol, 66],\n                        [Lang.Blocks.choco2_sound_solsharp, 67],\n                        [Lang.Blocks.choco2_sound_ra, 68],\n                        [Lang.Blocks.choco2_sound_rasharp, 69],\n                        [Lang.Blocks.choco2_sound_si, 70],\n                        [Lang.Blocks.choco2_sound_high_do, 71],\n                        [Lang.Blocks.choco2_sound_high_dosharp, 72],\n                        [Lang.Blocks.choco2_sound_high_re, 73],\n                        [Lang.Blocks.choco2_sound_high_resharp, 74],\n                        [Lang.Blocks.choco2_sound_high_mi, 75],\n                        [Lang.Blocks.choco2_sound_high_fa, 76],\n                        [Lang.Blocks.choco2_sound_high_fasharp, 77],\n                        [Lang.Blocks.choco2_sound_high_sol, 78],\n                        [Lang.Blocks.choco2_sound_high_solsharp, 79],\n                        [Lang.Blocks.choco2_sound_high_ra, 80],\n                        [Lang.Blocks.choco2_sound_high_rasharp, 81],\n                        [Lang.Blocks.choco2_sound_high_si, 82],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null],\n                type: 'choco2_play_sound',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                const sound = script.getValue('SOUND');\n\n                if (!script.is_started) {\n                    script.is_started = true;\n                    const msgId = Entry.Choco2.getHashKey();\n                    script.msg_id = msgId;\n                    sq.msg_id = script.msg_id;\n                    const msg = {\n                        id: msgId,\n                        type: 'play_sound',\n                        data: {\n                            param1: sound,\n                        },\n                        time: Date.now(),\n                    };\n                    sq.msg = msg;\n                    return script;\n                }\n\n                if (pd.msg_id && pd.msg_id.indexOf(script.msg_id) >= 0) {\n                    delete script.is_started;\n                    delete script.msg_id;\n                    delete pd.msgId;\n                    return script.callReturn();\n                }\n                return script;\n            },\n        },\n        choco2_is_front_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'choco2_is_front_sensor',\n            },\n            paramsKeyMap: {},\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                let retVal = false;\n                if (pd.sensorData) {\n                    retVal = pd.sensorData.is_front_sensor;\n                }\n                return retVal;\n            },\n        },\n        choco2_is_bottom_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'choco2_is_bottom_sensor',\n            },\n            paramsKeyMap: {},\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                let retVal = false;\n                if (pd.sensorData) {\n                    retVal = pd.sensorData.is_bottom_sensor;\n                }\n                return retVal;\n            },\n        },\n        choco2_is_light_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'choco2_is_light_sensor',\n            },\n            paramsKeyMap: {},\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                let retVal = false;\n                if (pd.sensorData) {\n                    retVal = pd.sensorData.is_light_sensor;\n                }\n                return retVal;\n            },\n        },\n\n        choco2_get_front_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'choco2_get_front_sensor',\n            },\n            paramsKeyMap: {},\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                let retVal = 0;\n                if (pd.sensorData) {\n                    retVal = pd.sensorData.front_sensor;\n                }\n                return retVal;\n            },\n        },\n        choco2_get_bottom_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'choco2_get_bottom_sensor',\n            },\n            paramsKeyMap: {},\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                let retVal = 0;\n                if (pd.sensorData) {\n                    retVal = pd.sensorData.bottom_sensor;\n                }\n                return retVal;\n            },\n        },\n        choco2_get_light_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'choco2_get_light_sensor',\n            },\n            paramsKeyMap: {},\n            class: 'choco2_command',\n            isNotFor: ['choco2'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const pd = Entry.hw.portData;\n                let retVal = 0;\n                if (pd.sensorData) {\n                    retVal = pd.sensorData.light_sensor;\n                }\n                return retVal;\n            },\n        },\n    };\n};\nmodule.exports = Entry.Choco2;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_chocopi.js",
    "content": "'use strict';\n\nEntry.Chocopi = {\n    id: '14.1',\n    name: 'chocopi',\n    url: 'http://chocopi.org/entry/',\n    imageName: 'chocopi.png',\n    title: {\n        ko: '초코파이보드',\n        en: 'ChocoPi',\n    },\n    p: {},\n    ev: {},\n    blocks: [],\n    setZero: function() {},\n    getport: function(id, port) {\n        if (!this.blocks) return -1;\n        if (this.blocks[port] && this.blocks[port].id == id) return port;\n        for (var p in this.blocks) if (this.blocks[port] && this.blocks[p].id == id) return p;\n        return -1;\n    },\n    connected: false,\n    portlist: [\n        [Lang.Blocks.chocopi_port + '1', 0],\n        [Lang.Blocks.chocopi_port + '2', 1],\n        [Lang.Blocks.chocopi_port + '3', 2],\n        [Lang.Blocks.chocopi_port + '4', 3],\n        [Lang.Blocks.chocopi_port + '5', 4],\n        [Lang.Blocks.chocopi_port + '6', 5],\n        [Lang.Blocks.chocopi_port + '7', 6],\n        [Lang.Blocks.chocopi_port + '8', 7],\n        ['BLE1', 8],\n        ['BLE2', 9],\n        ['BLE3', 10],\n        ['BLE4', 11],\n        ['BLE5', 12],\n        ['BLE6', 13],\n        ['BLE7', 14],\n        ['BLE8', 15],\n    ],\n    dataHandler: function(data) {\n        if (!Entry.hw.sendQueue.data) {\n            this.connected = true;\n            Entry.hw.sendQueue.init = true;\n            Entry.hw.update();\n            delete Entry.hw.sendQueue.init;\n            Entry.hw.sendQueue.data = {};\n        }\n        if (data['d']) {\n            for (var i in data['d']) {\n                this.p[i] = data['d'][i];\n            }\n        }\n        if (data['ev']) {\n            for (var i in data['ev']) {\n                this.ev[i] = data['ev'][i];\n                Entry.engine.fireEvent(this.blocks[i].name + '14');\n            }\n        }\n        if (data['bl']) {\n            this.blocks = data['bl'];\n        }\n    },\n};\nEntry.Chocopi.blockMenuBlocks = [\n    'chocopi_sensor',\n    'chocopi_touch_event',\n    'chocopi_touch_status',\n    'chocopi_touch_value',\n    'chocopi_control_event',\n    'chocopi_control_joystick',\n    'chocopi_control_button',\n    'chocopi_motion_photogate_event',\n    'chocopi_motion_photogate_time',\n    'chocopi_motion_photogate_status',\n    'chocopi_motion_value',\n    'chocopi_led',\n    'chocopi_dc_motor',\n    'chocopi_servo_motor',\n    'chocopi_map_range',\n];\nEntry.Chocopi.getBlocks = function() {\n    return {\n        //region chocopi 초코파이\n        chocopi_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Hw.temp, 'temp'],\n                        [Lang.Hw.humidity, 'humi'],\n                        [Lang.Hw.light, 'light'],\n                        [Lang.Hw.analog + '1', '0'],\n                        [Lang.Hw.analog + '2', '1'],\n                        [Lang.Hw.analog + '3', '2'],\n                    ],\n                    value: 'temp',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'chocopi_sensor' },\n            paramsKeyMap: { port: 0, sensor: 1 },\n            class: 'chocopi_sensor',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(8, script.getField('port'));\n                var name = script.getField('sensor');\n                if (port == -1) return 0;\n                return Entry.Chocopi.p[port][name];\n            },\n            syntax: { js: [], py: ['Chocopi.sensor(%1, %2)'] },\n        },\n        chocopi_touch_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 0],\n                        [2, 1],\n                        [3, 2],\n                        [4, 3],\n                        [5, 4],\n                        [6, 5],\n                        [7, 6],\n                        [8, 7],\n                        [9, 8],\n                        [10, 9],\n                        [11, 10],\n                        [12, 11],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_touch_event_touch, 1],\n                        [Lang.Blocks.chocopi_touch_event_untouch, 0],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'chocopi_touch_event' },\n            paramsKeyMap: { port: 1, id: 2, status: 3 },\n            class: 'chocopi_touch',\n            isNotFor: ['chocopi'],\n            event: 'touch14',\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(9, script.getField('port'));\n                if (port == -1) return this.die();\n                var id = script.getField('id');\n                var status = script.getField('status');\n                var ev = Entry.Chocopi.ev[port];\n                if (((ev.id >> id) & 1) != 1 || ((Entry.Chocopi.p[port].ts >> id) & 1) != status) {\n                    return this.die();\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['def on_chocopi_touch(%2, %3, %4 ):'] },\n        },\n        chocopi_touch_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 0],\n                        [2, 1],\n                        [3, 2],\n                        [4, 3],\n                        [5, 4],\n                        [6, 5],\n                        [7, 6],\n                        [8, 7],\n                        [9, 8],\n                        [10, 9],\n                        [11, 10],\n                        [12, 11],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'chocopi_touch_status' },\n            paramsKeyMap: { port: 0, sensor: 1 },\n            class: 'chocopi_touch',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(9, script.getField('port'));\n                var sensor = script.getField('sensor');\n                if (port == -1) return false;\n                if (!Entry.Chocopi.p[port]) Entry.Chocopi.p[port] = { ts: 0, tv: [] };\n                return (Entry.Chocopi.p[port].ts & (1 << sensor)) > 0;\n            },\n            syntax: { js: [], py: ['Chocopi.touchStatus(%1, %2)'] },\n        },\n        chocopi_touch_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 0],\n                        [2, 1],\n                        [3, 2],\n                        [4, 3],\n                        [5, 4],\n                        [6, 5],\n                        [7, 6],\n                        [8, 7],\n                        [9, 8],\n                        [10, 9],\n                        [11, 10],\n                        [12, 11],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'chocopi_touch_value' },\n            paramsKeyMap: { port: 0, sensor: 1 },\n            class: 'chocopi_touch',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(9, script.getField('port'));\n                if (port == -1) return false;\n                var sensor = script.getField('sensor');\n                if (!Entry.Chocopi.p[port]) Entry.Chocopi.p[port] = { ts: 0, tv: [] };\n                return Entry.Chocopi.p[port].tv[sensor];\n            },\n            syntax: { js: [], py: ['Chocopi.touchValue(%1, %2)'] },\n        },\n        chocopi_control_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Hw.button + '1', 0],\n                        [Lang.Hw.button + '2', 1],\n                        [Lang.Hw.button + '3', 2],\n                        [Lang.Hw.button + '4', 3],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_control_event_pressed, 1],\n                        [Lang.Blocks.chocopi_control_event_released, 0],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'chocopi_control_event' },\n            paramsKeyMap: { port: 1, id: 2, status: 3 },\n            class: 'chocopi_control',\n            isNotFor: ['chocopi'],\n            event: 'control14',\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(10, script.getField('port'));\n                if (port == -1) return this.die();\n                var id = script.getField('id');\n                var status = script.getField('status');\n                var ev = Entry.Chocopi.ev[port];\n                if (((ev.id >> (4 - id)) & 1) != 1 || ev.btn[id] != status) {\n                    return this.die();\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['def on_chocopi_control_button(%2, %3, %4 ):'],\n            },\n        },\n        chocopi_control_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_joystick_X, 0],\n                        [Lang.Blocks.chocopi_joystick_Y, 1],\n                        [Lang.Blocks.chocopi_pot, 2],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [null], type: 'chocopi_control_joystick' },\n            paramsKeyMap: { port: 0, sensor: 1 },\n            class: 'chocopi_control',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(10, script.getField('port'));\n                if (port == -1) return false;\n                var sensor = script.getField('sensor');\n                if (!Entry.Chocopi.p[port]) Entry.Chocopi.p[port] = { xyp: [] };\n                return Entry.Chocopi.p[port].xyp[sensor];\n            },\n            syntax: { js: [], py: ['Chocopi.joystick(%1, %2)'] },\n        },\n        chocopi_control_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Hw.button + '1', 0],\n                        [Lang.Hw.button + '2', 1],\n                        [Lang.Hw.button + '3', 2],\n                        [Lang.Hw.button + '4', 3],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [null], type: 'chocopi_control_button' },\n            paramsKeyMap: { port: 0, sensor: 1 },\n            class: 'chocopi_control',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(10, script.getField('port'));\n                if (port == -1) return false;\n                var sensor = script.getField('sensor');\n                if (!Entry.Chocopi.ev[port]) return 0;\n                return Entry.Chocopi.ev[port].btn[sensor];\n            },\n            syntax: { js: [], py: ['Chocopi.button(%1, %2)'] },\n        },\n        chocopi_motion_photogate_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 0],\n                        [2, 1],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_motion_photogate_time_unblocked, 0],\n                        [Lang.Blocks.chocopi_motion_photogate_time_blocked, 1],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [null], type: 'chocopi_motion_photogate_time' },\n            paramsKeyMap: { port: 0, sensor: 1, action: 2 },\n            class: 'chocopi_motion',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(11, script.getField('port'));\n                if (port == -1) return 0;\n                var sensor = script.getField('sensor');\n                var action = script.getField('action');\n                if (!Entry.Chocopi.ev[port]) return 0;\n                return Entry.Chocopi.ev[port].time[sensor][action];\n            },\n            syntax: { js: [], py: ['Chocopi.photogateTime(%1, %2, %3)'] },\n        },\n        chocopi_motion_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Hw.IR + ' 1', 0],\n                        [Lang.Hw.IR + ' 2', 1],\n                        [Lang.Hw.IR + ' 3', 2],\n                        [Lang.Blocks.chocopi_motion_angle_x, 9],\n                        [Lang.Blocks.chocopi_motion_angle_y, 10],\n                        [Lang.Blocks.chocopi_motion_angle_z, 11],\n                        [Lang.Hw.acceleration + 'X', 3],\n                        [Lang.Hw.acceleration + 'Y', 4],\n                        [Lang.Hw.acceleration + 'Z', 5],\n                        [Lang.Hw.angular_acceleration + 'U', 6],\n                        [Lang.Hw.angular_acceleration + 'V', 7],\n                        [Lang.Hw.angular_acceleration + 'W', 8],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [null], type: 'chocopi_motion_value' },\n            paramsKeyMap: { port: 0, sensor: 1 },\n            class: 'chocopi_motion',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(11, script.getField('port'));\n                if (port == -1) return 0;\n                var sensor = script.getField('sensor');\n                if (!Entry.Chocopi.p[port]) Entry.Chocopi.p[port] = { s: [] };\n                var v = Entry.Chocopi.p[port].s;\n                if (sensor < 9) return v[sensor];\n                switch (sensor) {\n                    case 9:\n                        return (Math.atan2(v[3], v[5]) * 180) / Math.PI;\n                    case 10:\n                        return (Math.atan2(v[4], v[5]) * 180) / Math.PI;\n                    case 11:\n                        return (Math.atan2(v[3], v[4]) * 180) / Math.PI;\n                }\n                return 0;\n            },\n            syntax: { js: [], py: ['Chocopi.motionValue(%1, %2)'] },\n        },\n\n        chocopi_motion_photogate_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [null], type: 'chocopi_motion_photogate_status' },\n            paramsKeyMap: { port: 0, sensor: 1 },\n            class: 'chocopi_motion',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(11, script.getField('port'));\n                if (port == -1) return 0;\n                var sensor = script.getField('sensor');\n                if (!Entry.Chocopi.ev[port]) return 0;\n                return Entry.Chocopi.ev[port].pg[sensor];\n            },\n            syntax: { js: [], py: ['Chocopi.motionPhotogateStatus(%1, %2)'] },\n        },\n        chocopi_motion_photogate_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 0],\n                        [2, 1],\n                        [3, 2],\n                        [4, 3],\n                        [5, 4],\n                        [6, 5],\n                        [7, 6],\n                        [8, 7],\n                        [9, 8],\n                        [10, 9],\n                        [11, 10],\n                        [12, 11],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_motion_photogate_event_unblocked, 0],\n                        [Lang.Blocks.chocopi_motion_photogate_event_blocked, 1],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: { params: [], type: 'chocopi_motion_photogate_event' },\n            paramsKeyMap: { port: 1, id: 2, status: 3 },\n            class: 'chocopi_motion',\n            isNotFor: ['chocopi'],\n            event: 'motion14',\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(11, script.getField('port'));\n                if (port == -1) return this.die();\n                var id = script.getField('id');\n                var status = script.getField('status');\n                if (Entry.Chocopi.ev[port].pg[id] != status) {\n                    return this.die();\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['def on_chocopi_photogate(%2, %3, %4 ):'] },\n        },\n        chocopi_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    { type: 'number', params: [1] },\n                    { type: 'number', params: [0] },\n                    { type: 'number', params: [0] },\n                    { type: 'number', params: [0] },\n                ],\n                type: 'chocopi_led',\n            },\n            paramsKeyMap: { port: 0, l: 1, r: 2, g: 3, b: 4 },\n            class: 'chocopi_output',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(12, script.getField('port'));\n                if (port == -1) return script.callReturn();\n                var l = script.getNumberValue('l');\n                var r = script.getNumberValue('r');\n                var g = script.getNumberValue('g');\n                var b = script.getNumberValue('b');\n                if (!Entry.hw.sendQueue.data) Entry.hw.sendQueue.data = {};\n                Entry.hw.sendQueue.data[port] = [l, r, g, b];\n                Entry.hw.update();\n                delete Entry.hw.sendQueue.data[port];\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Chocopi.LED(%1, %2, %3, %4, %5)'] },\n        },\n        chocopi_dc_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.General.clock, 0],\n                        [Lang.General.counter_clock, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null, null, { type: 'number', params: [0] }],\n                type: 'chocopi_dc_motor',\n            },\n            paramsKeyMap: { port: 0, id: 1, power: 2, direction: 3 },\n            class: 'chocopi_output',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(14, script.getField('port'));\n                if (port == -1) return script.callReturn();\n                var id = script.getField('id');\n                var s = script.getNumberValue('power');\n                var d = script.getField('direction');\n                if (!Entry.hw.sendQueue.data) Entry.hw.sendQueue.data = {};\n                Entry.hw.sendQueue.data[port] = [id, s, d];\n                Entry.hw.update();\n                delete Entry.hw.sendQueue.data[port];\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Chocopi.DCmotor(%1, %2, %3, %4)'] },\n        },\n        chocopi_servo_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.chocopi_port + '1', 0],\n                        [Lang.Blocks.chocopi_port + '2', 1],\n                        [Lang.Blocks.chocopi_port + '3', 2],\n                        [Lang.Blocks.chocopi_port + '4', 3],\n                        [Lang.Blocks.chocopi_port + '5', 4],\n                        [Lang.Blocks.chocopi_port + '6', 5],\n                        [Lang.Blocks.chocopi_port + '7', 6],\n                        [Lang.Blocks.chocopi_port + '8', 7],\n                        ['BLE1', 8],\n                        ['BLE2', 9],\n                        ['BLE3', 10],\n                        ['BLE4', 11],\n                        ['BLE5', 12],\n                        ['BLE6', 13],\n                        ['BLE7', 14],\n                        ['BLE8', 15],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                        ['3', 2],\n                        ['4', 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null, null, { type: 'number', params: [90] }],\n                type: 'chocopi_servo_motor',\n            },\n            paramsKeyMap: { port: 0, id: 1, angle: 2 },\n            class: 'chocopi_output',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var port = Entry.Chocopi.getport(15, script.getField('port'));\n                if (port == -1) return script.callReturn();\n                var id = script.getField('id');\n                var a = script.getNumberValue('angle');\n                if (!Entry.hw.sendQueue.data) Entry.hw.sendQueue.data = {};\n                Entry.hw.sendQueue.data[port] = [id, a];\n                Entry.hw.update();\n                delete Entry.hw.sendQueue.data[port];\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Chocopi.servo(%1, %2, %3)'] },\n        },\n        chocopi_map_range: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n            ],\n            def: {\n                params: [\n                    { type: 'number', params: [0] },\n                    { type: 'number', params: [0] },\n                    { type: 'number', params: [4096] },\n                    { type: 'number', params: [0] },\n                    { type: 'number', params: [255] },\n                ],\n                type: 'chocopi_map_range',\n            },\n            paramsKeyMap: { x: 0, x1: 1, x2: 2, y1: 3, y2: 4 },\n            class: 'chocopi',\n            isNotFor: ['chocopi'],\n            func: function(sprite, script) {\n                var x = script.getNumberValue('x');\n                var x1 = script.getNumberValue('x1');\n                var x2 = script.getNumberValue('x2');\n                var y1 = script.getNumberValue('y1');\n                var y2 = script.getNumberValue('y2');\n                if (x1 === x2) return y1;\n                return y1 + ((x - x1) * (y2 - y1)) / (x2 - x1);\n            },\n            syntax: { js: [], py: ['Chocopi.mapRange(%1, %2, %3, %4, %5)'] },\n        },\n    };\n};\n\nEntry.Chocopi.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                chocopi_control_event_pressed: '누를 때',\n                chocopi_control_event_released: '뗄 때',\n                chocopi_joystick_X: '조이스틱 좌우',\n                chocopi_joystick_Y: '조이스틱 상하',\n                chocopi_motion_photogate_event_blocked: '막았을 때',\n                chocopi_motion_photogate_event_unblocked: '열었을 때',\n                chocopi_motion_photogate_time_blocked: '막은 시간',\n                chocopi_motion_photogate_time_unblocked: '연 시간',\n                chocopi_motion_angle_x: '각도X',\n                chocopi_motion_angle_y: '각도Y',\n                chocopi_motion_angle_z: '각도Z',\n                chocopi_port: '포트',\n                chocopi_pot: '볼륨',\n                chocopi_touch_event_touch: '만질 때',\n                chocopi_touch_event_untouch: '뗄 때',\n            },\n            template: {\n                chocopi_control_button: '%1 컨트롤 %2번을 누름',\n                chocopi_control_event: '%1 %2 컨트롤 %3을 %4',\n                chocopi_control_joystick: '%1 컨트롤 %2의 값',\n                chocopi_dc_motor: '%1 DC모터 %2 %3% 세기 %4 방향 %5',\n                chocopi_led: '%1 LED %2 RGB(%3 %4 %5) %6',\n                chocopi_motion_photogate_event: '%1 %2 포토게이트 %3번을 %4',\n                chocopi_motion_photogate_status: '%1 포토게이트 %2번이 막힘',\n                chocopi_motion_photogate_time: '%1 포토게이트%2번을 %3',\n                chocopi_motion_value: '%1 모션 %2의 값',\n                chocopi_motion_angle: '%1 모션 %2',\n                chocopi_sensor: '%1 센서 %2',\n                chocopi_servo_motor: '%1 서보모터 %2번 %3도 %4',\n                chocopi_touch_event: '%1 %2 터치 %3번을 %4',\n                chocopi_touch_status: '%1 터치 %2번을 만짐',\n                chocopi_touch_value: '%1 터치 %2번의 값',\n                chocopi_map_range: '%1을 %2~%3에서 %4~%5로',\n            },\n            Device: {\n                chocopi: '초코파이보드',\n            },\n            Menus: {\n                chocopi: '초코파이보드',\n            },\n            Helper: {\n                chocopi_control_button:\n                    '버튼이 눌리면 참이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_control_event:\n                    '버튼을 누르거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_control_joystick:\n                    '조이스틱 좌우, 상하, 볼륨의 값은 0~4095까지 입니다.<br/>따라서 2047 근처가 중간이 됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_dc_motor:\n                    'DC모터 모듈에는 직류전동기 두개를 연결 할 수 있습니다.<br/> 직류 전동기는 최대 5V로 동작하게 됩니다.<br/>값은 100이 최대(100%)이고 음수를 넣으면 반대 방향으로 회전합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_led:\n                    'LED번호는 LED블록에 연결된 순서이고 1번부터 시작합니다.<br/>RGB값은 0~255사이의 값입니다.<br/>빨강(Red),녹색(Green), 파랑(Blue)순서로  입력합니다.<br/>밝은 LED를 직접보면 눈이 아프니까 값을 0~5정도로 씁니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_motion_photogate_event:\n                    '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br/>빛센서를 물체로 가리거나 치우면 시작되는 엔트리 블록을 연결합니다<br/>모션 모듈에는 포토게이트 2개를 연결할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_motion_photogate_status:\n                    '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>물체가 빛센서를 가리면 참</b>이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_motion_photogate_time:\n                    '포토게이트는 모션블록에 연결합니다.<br/>포토게이트는 한쪽에서 나온 빛을 맞은 편의 센서가 감지하는 장치입니다.<br>이 블록은 물체가 빛센서를 가리거나 벗어난 시간을 가집니다.<br/>1/10000초까지 측정할 수 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_motion_value:\n                    '모션 모듈에는 3개의 적외선 센서가 있습니다.<br/>0~4095사이의 값을 가질 수 있는데 물체가 빛을 많이 반사할 수록 작은 값을 가집니다. <br/>거리를 대략적으로 측정할 수 있습니다. <br/>가속도와 각가속도 값의 범위는 -32768~32767 까지입니다.<br/>가속도를 이용해서 센서의 기울기를 측정할 수도 있습니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_motion_angle:\n                    '모션 모듈의 가속도 센서를 이용하여 기울기를 측정합니다.<br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_sensor:\n                    '온도 값은 섭씨 온도입니다.<br/>습도 값은 백분율로 나타낸 상대습도 값입니다.<br/>빛은 로그스케일로 0~4095사이입니다.<br/>아날로그 값은 0~4095사이입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_servo_motor:\n                    '서보모터 모듈에는 4개의 서보모터를 연결 할 수 있습니다.<br/>서보모터는 5V로 동작하게 됩니다.<br/>각도는 0~200도까지 지정할 수 있습니다.<br/>연속회전식 서보모터를 연결하면 각도에 따라 속도가 변하게됩니다.<br/>90~100 사이가 중간값입니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_touch_event:\n                    '터치 모듈에는 1~12번의 연결 패드가 있습니다. <br/>만지거나 뗄 때 처리할 엔트리 블록들을 연결합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_touch_status:\n                    '터치 모듈의 패드를 만지면 참이됩니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_touch_value:\n                    '터치패드에 연결된 물체의 전기용량이 커지면 값이 작아집니다.<br/>여러 명이 손잡고 만지면 더 작은 값이 됩니다.<br/>전기용량이란 물체에 전기를 띈 입자를 얼마나 가지고 있을 수 있는 지를 말합니다.<br/><br/>포트번호는 맞추지 않아도 됩니다.<br/>단, 같은 종류의 모듈을 여러 개 연결하는 경우에만 포트를 지정하면 됩니다.',\n                chocopi_map_range:\n                    '예를 들어 설명하면, 컨트럴 블럭의 조이스틱X의 위치에 따라 인형의 위치를 -100에서 100사이로 정해주고 싶다면. 조이스틱X, 0, 4095, -100,100 순서대로 입력합니다.',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                chocopi_control_event_pressed: 'pressed',\n                chocopi_control_event_released: 'released',\n                chocopi_joystick_X: 'joystick X',\n                chocopi_joystick_Y: 'joystick Y',\n                chocopi_motion_photogate_event_blocked: 'blocked',\n                chocopi_motion_photogate_event_unblocked: 'unblocked',\n                chocopi_motion_photogate_time_blocked: 'blocked',\n                chocopi_motion_photogate_time_unblocked: 'unblocked',\n                chocopi_motion_angle_x: 'angle X',\n                chocopi_motion_angle_y: 'angle Y',\n                chocopi_motion_angle_z: 'angle Z',\n                chocopi_port: 'P',\n                chocopi_pot: 'potentiometer',\n                chocopi_touch_event_touch: 'touched',\n                chocopi_touch_event_untouch: 'untouched',\n            },\n            template: {\n                chocopi_control_button: '%1 controller %2 is pressed',\n                chocopi_control_event: '%1 When %2 controller %3 is %4',\n                chocopi_control_joystick: '%1 controller %2 value',\n                chocopi_dc_motor: '%1 DC motor #%2  %3 % direction %4 %5',\n                chocopi_led: '%1 LED #%2 RGB(%3 %4 %5) %6',\n                chocopi_motion_photogate_event: '%1 When %2 photogate %3 is %4',\n                chocopi_motion_photogate_status: '%1 photogate #%2 is blocked',\n                chocopi_motion_photogate_time: 'time when %1 photogate %2 was %3',\n                chocopi_motion_value: '%1 motion %2 value',\n                chocopi_sensor: '%1 sensor %2',\n                chocopi_servo_motor: '%1 set servo motor #%2 %3 degree %4',\n                chocopi_touch_event: '%1 When %2 touch pad%3 is %4',\n                chocopi_touch_status: '%1 touch pad%2 is touched',\n                chocopi_touch_value: '%1 touch pad%2 value',\n                chocopi_map_range: 'map %1 in %2~%3 to %4~%5',\n            },\n            Device: {\n                chocopi: 'ChocoPi',\n            },\n            Menus: {\n                chocopi: 'ChocoPi',\n            },\n            Helper: {\n                chocopi_control_button:\n                    'This block will be true if the button is pressed.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n                chocopi_control_event:\n                    'You can attach blocks to process when the button is pressed or released <br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n                chocopi_control_joystick:\n                    'Joystick X,Y and potentiometer has range of  0~4095.<br/>so, around 2047 will be center value.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n                chocopi_dc_motor:\n                    \"Two DC motors can be connected to 'DC motor' module<br/> The motor will be supplied with maximum 5V.<br/>Maximum value is 100 (100%), is negative value is used then it will rotate opposite direction.<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n                chocopi_led:\n                    'LED number start from 1 and is the connecting order from the LED module.<br/>You can assign RGB values from 0 to 255<br/>RGB(Red Green Blue) order<br/>To watch an LED with bright light can be painful,<br/>so, please use small number like 0 to 5.<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n                chocopi_motion_photogate_event:\n                    \"Two photogates can be connected to 'Motion' module<br/>A photogate is a device with light sensor facing light source in opposite side<br/>You can attach blocks when an object blocks or unblocks light sensor<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n                chocopi_motion_photogate_status:\n                    \"Two photogates can be connected to 'Motion' module<br/>A photogate is a device with light sensor facing light source in opposite side<br/>This block will be <b>true if an object blocks sensor</b><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n                chocopi_motion_photogate_time:\n                    \"Two photogates can be connected to 'Motion' module<br/>A photogate is a device with light sensor facing light source in opposite side<br/>This block will have the time when an object blocked or unblocked the sensor<br/>It can measure time with resolution of 1/10000 sec<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n                chocopi_motion_value:\n                    \"'Motion' module has three infrared sensors<br/>The value has range of 0~4095, the more reflection from object, the smaller the value is<br/>It can be used to measure approximate distance between the sensor and an object <br/>Acceleration and angular acceleration value ranges from -32768 to 32767.<br/>You can measure inclination of the sensor using these values.<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n                chocopi_sensor:\n                    'Temperature value is Celsius.<br/>Relative humidity value ranges from 0 to 100%.<br/>Light value ranges 0~4095 in log scale.<br/>Analog value ranges from 0 to 4095.<br/><br/>Port number(P1~P8) is automatically selected internally.<br>It is needed only when multiple modules with the same kind are used',\n                chocopi_servo_motor:\n                    \"'Servo' module can be connected to four servo motors<br/>Servo motors are provided with 5V<br/>You can assign 0~200 in degree unit.<br/>If a contineous rotational servo motor is connected, it's speed is determined by the degree value.<br/>Center value is from 90 to 100 varying by motor model.<br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n                chocopi_touch_event:\n                    'Touch module has #1~12 connecting pads.<br/>You can attach block to process when these pads are touched or untouched.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n                chocopi_touch_status:\n                    'It will be true if the pad is touched.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used',\n                chocopi_touch_value:\n                    \"The value will be smaller if the capacitance of the obeject is larger.<br/>If many people hold each other's hand and touch, the value will be smaller<br/>'Capacitance' means how many electric particles the object can hold.<br/><br/><br/>Port number(P1~P8) is automatically selected internally<br>It is needed only when multiple modules with the same kind are used\",\n                chocopi_map_range:\n                    'Usage example: If you want to set a sprite position x according to joystic x position between -100 and 100, you can put five values as Joystic X, 0, 4095, -100, 100.',\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Chocopi;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_coalaboard.js",
    "content": "'use strict';\n\nEntry.Coalaboard = {\n    SENSOR_MAP: {\n        1: 'light',\n        2: 'IR',\n        3: 'touch',\n        4: 'potentiometer',\n        5: 'MIC',\n        6: 'ultrasonicSensor',\n        7: 'temperature',\n        10: 'vibrationSensor',\n        21: 'UserSensor',\n        11: 'UserInput',\n        20: 'LED',\n        19: 'SERVO',\n        18: 'DC',\n    },\n    PORT_MAP: {\n        buzzer: 2,\n        '5': 4,\n        '6': 6,\n        '7': 8,\n        '8': 10,\n        LEDR: 12,\n        LEDG: 14,\n        LEDB: 16,\n    },\n    INEQ_SIGN: [\n        ['<', '<'],\n        ['>', '>'],\n        ['=', '='],\n    ],\n    sensorList: function() {\n        var list = [];\n        var portData = Entry.hw.portData;\n        for (var i = 1; i < 5; i++) {\n            var data = portData[i];\n            if (data && (data.value || data.value === 0)) {\n                list.push([i + ' - ' + Lang.Blocks['COALABOARD_' + data.type], i.toString()]);\n            }\n        }\n\n        if (list.length == 0) return [[Lang.Blocks.no_target, 'null']];\n        return list;\n    },\n    touchList: function() {\n        var list = [];\n        var portData = Entry.hw.portData;\n        for (var i = 1; i < 5; i++) {\n            var data = portData[i];\n            if (data && data.type === 'touch') list.push([i.toString(), i.toString()]);\n        }\n        if (list.length == 0) return [[Lang.Blocks.no_target, 'null']];\n        return list;\n    },\n    servoList: function() {\n        var list = [];\n        var portData = Entry.hw.portData;\n        for (var i = 5; i < 9; i++) {\n            var data = portData[i];\n            if (data && data.type === 'SERVO') list.push(['ABCD'[i - 5], i.toString()]);\n        }\n        if (list.length == 0) return [[Lang.Blocks.no_target, 'null']];\n        return list;\n    },\n    dcList: function() {\n        var list = [];\n        var portData = Entry.hw.portData;\n        for (var i = 5; i < 9; i++) {\n            var data = portData[i];\n            if (data && data.type === 'DC') list.push(['ABCD'[i - 5], i.toString()]);\n        }\n        if (list.length == 0) return [[Lang.Blocks.no_target, 'null']];\n        return list;\n    },\n    /**\n     * 엔트리가 중지 되면 호출된다.\n     */\n    setZero: function() {\n        let sq = Entry.hw.sendQueue;\n        for (let port in Entry.Coalaboard.PORT_MAP) {\n            let portData = Entry.hw.portData[port];\n            if (portData != null) {\n                if (portData.type == Entry.Coalaboard.SENSOR_MAP[18]) {\n                    // DC모터 인 경우, 129로 세팅하여 바로 멈추기\n                    sq[port] = 129;\n                } else {\n                    sq[port] = 0;\n                }\n            } else {\n                sq[port] = 0;\n            }\n        }\n        Entry.hw.update();\n    },\n    id: '3.3',\n    name: 'coalaboard',\n    url: 'http://www.bitbrick.cc/',\n    imageName: 'coalaboard.png',\n    title: {\n        ko: '코알라보드',\n        en: 'coalaboard',\n    },\n    servoMaxValue: 181,\n    servoMinValue: 1,\n    dcMaxValue: 100,\n    dcMinValue: -100,\n    /**\n     * 콜백 함수. 계속해서 센서 데이터를 받는다.\n     * @param {*} pd\n     */\n    afterReceive(pd) {\n        for (let i = 1; i < 5; i++) {\n            // 오직 센서만 받기\n            let obj = pd[i]; // ex) null or { type: \"touch\", value: 1023 }\n            if (obj != null) {\n                if (obj.type == 'touch' && obj.value == 0) {\n                    Entry.engine.fireEvent('coalaboardButtonEventReceive');\n                }\n                Entry.engine.fireEvent('coalaboardSensorGetValueEventReceive');\n            }\n        }\n    },\n    calculateDCMotorValue: function(value) {\n        let val = 0;\n        if (value > 0) {\n            val = Math.floor(value * 0.8 + 16);\n        } else if (value < 0) {\n            val = Math.ceil(value * 0.8 - 19);\n        } else {\n            val = 0;\n        }\n        // DC_MOTOR_ADJUSTMENT  128\n        val = 128 + val;\n        if (val == 128) {\n            val = 129;\n        }\n        return val;\n    },\n};\n\nEntry.Coalaboard.monitorTemplate = function() {\n    return {\n        keys: ['value'],\n        imgPath: 'hw/coalaboard.png',\n        width: 400,\n        height: 400,\n        listPorts: {\n            UserInput: {\n                name: Lang.Blocks.COALABOARD_UserInput,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            potentiometer: {\n                name: Lang.Blocks.COALABOARD_potentiometer,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            MIC: {\n                name: Lang.Blocks.COALABOARD_MIC,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            IR: {\n                name: Lang.Blocks.COALABOARD_IR,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            temperature: {\n                name: Lang.Blocks.COALABOARD_temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            light: {\n                name: Lang.Blocks.COALABOARD_light,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            touch: {\n                name: Lang.Blocks.COALABOARD_touch,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    };\n};\n\nEntry.Coalaboard.blockMenuBlocks = [\n    'coalaboard_when_button_pressed',\n    'coalaboard_when_sensor_get_value',\n    'coalaboard_is_touch_pressed',\n    'coalaboard_is_sensor_value_compare',\n    'coalaboard_sensor_value',\n    'coalaboard_convert_scale',\n    'coalaboard_turn_on_color_led_by_rgb',\n    'coalaboard_turn_on_color_led_by_picker',\n    'coalaboard_turn_on_color_led_by_value',\n    'coalaboard_turn_off_color_led',\n    'coalaboard_buzzer',\n    'coalaboard_servomotor_angle',\n    'coalaboard_dc_direction_speed',\n    'coalaboard_dc_speed',\n    'coalaboard_turn_off_all_motors',\n];\n\nEntry.Coalaboard.getBlocks = function() {\n    let options_COALABOARD_button2 = [\n        [Lang.Blocks.COALABOARD_button_pressed, 'pressed'],\n        [Lang.Blocks.COALABOARD_button_released, 'released'],\n    ];\n    return {\n        //region coalaboard 코알라보드\n        coalaboard_when_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                    position: {\n                        x: 0,\n                        y: 0,\n                    },\n                },\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    menuName: Entry.Coalaboard.touchList,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'coalaboard_when_button_pressed',\n            },\n            paramsKeyMap: {\n                DUMMY: 0,\n                PORT: 1,\n            },\n            class: 'event',\n            isNotFor: ['coalaboard'],\n            event: 'coalaboardButtonEventReceive',\n            func: function(sprite, script) {\n                let selectedSensor = script.values[1];\n                let port = script.getStringField('PORT');\n                let type = Entry.hw.portData[port].type;\n                let val = Entry.hw.portData[port].value; // 0이면 누름, 1023이면 누르지 않음\n                if (selectedSensor == port) {\n                    if (val == 0) {\n                        return script.callReturn();\n                    } else {\n                        return this.die();\n                    }\n                } else {\n                    return this.die();\n                }\n            },\n            syntax: { js: [], py: ['Coalaboard.when_button_pressed(%2, %3)'] },\n        },\n        coalaboard_when_sensor_get_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                    position: {\n                        x: 0,\n                        y: 0,\n                    },\n                },\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    menuName: Entry.Coalaboard.sensorList,\n                },\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: Entry.Coalaboard.INEQ_SIGN,\n                    value: '>',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                ],\n                type: 'coalaboard_when_sensor_get_value',\n            },\n            paramsKeyMap: {\n                DUMMY: 0,\n                PORT: 1,\n                INEQ_SIGN: 2,\n                VALUE: 3,\n            },\n            class: 'event',\n            isNotFor: ['coalaboard'],\n            event: 'coalaboardSensorGetValueEventReceive',\n            func: function(sprite, script) {\n                let selectedPort = script.values[1];\n                let ineqSign = script.values[2];\n                let value = script.values[3];\n                let port = script.getStringField('PORT');\n                let val = Entry.hw.portData[port].value;\n                if (selectedPort == port && ineqSign == '<' && val < value) {\n                    return script.callReturn();\n                } else if (selectedPort == port && ineqSign == '>' && val > value) {\n                    return script.callReturn();\n                } else if (selectedPort == port && ineqSign == '=' && val == value) {\n                    return script.callReturn();\n                } else {\n                    return this.die();\n                }\n            },\n            syntax: { js: [], py: ['Coalaboard.when_sensor_get_value(%2,%3,%4)'] },\n        },\n        coalaboard_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    menuName: Entry.Coalaboard.sensorList,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coalaboard_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'button',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port].value;\n            },\n            syntax: { js: [], py: ['Coalaboard.sensor_value(%1)'] },\n        },\n        coalaboard_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Coalaboard.sensorList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'coalaboard_convert_scale',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'button',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                var port = script.getNumberField('PORT');\n                var value1 = Entry.hw.portData[port].value;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var result = value1;\n\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n                return Math.round(result);\n            },\n            syntax: {\n                js: [],\n                py: ['Coalaboard.convert_scale(%1, %2, %3, %4, %5)'],\n            },\n        },\n        coalaboard_is_touch_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Coalaboard.touchList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_COALABOARD_button2,\n                    value: 'pressed',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'coalaboard_is_touch_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                PRESSED: 1,\n            },\n            class: 'button',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                let port = script.getStringField('PORT');\n                let val = Entry.hw.portData[port].value;\n                let pressed = script.getStringField('PRESSED');\n                if (pressed == 'pressed' && val == 0) {\n                    return true;\n                } else if (pressed == 'released' && val == 1023) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: ['Coalaboard.is_touch_pressed(%1, %2)'] },\n        },\n        coalaboard_is_sensor_value_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    menuName: Entry.Coalaboard.sensorList,\n                },\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: Entry.Coalaboard.INEQ_SIGN,\n                    value: '>',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                ],\n                type: 'coalaboard_is_sensor_value_compare',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                INEQ_SIGN: 1,\n                VALUE: 2,\n            },\n            class: 'button',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                let selectedPort = script.values[0];\n                let ineqSign = script.values[1];\n                let value = script.values[2];\n                let port = script.getStringField('PORT');\n                let val = Entry.hw.portData[port].value;\n                if (selectedPort == port && ineqSign == '<' && val < value) {\n                    return true;\n                } else if (selectedPort == port && ineqSign == '>' && val > value) {\n                    return true;\n                } else if (selectedPort == port && ineqSign == '=' && val == value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: ['Bitbrick.is_sensor_value_compare(%1,%2,%3)'] },\n        },\n        coalaboard_turn_off_color_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coalaboard_turn_off_color_led',\n                id: 'i3je',\n            },\n            class: 'led',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue['LEDR'] = 0;\n                Entry.hw.sendQueue['LEDG'] = 0;\n                Entry.hw.sendQueue['LEDB'] = 0;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Coalaboard.turn_off_color_led()'] },\n        },\n        coalaboard_turn_on_color_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'coalaboard_turn_on_color_led_by_rgb',\n            },\n            paramsKeyMap: {\n                rValue: 0,\n                gValue: 1,\n                bValue: 2,\n            },\n            class: 'led',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                var red = script.getNumberValue('rValue'),\n                    green = script.getNumberValue('gValue'),\n                    blue = script.getNumberValue('bValue'),\n                    min = 0,\n                    max = 255,\n                    adjustor = Entry.adjustValueWithMaxMin,\n                    sq = Entry.hw.sendQueue;\n\n                sq['LEDR'] = adjustor(red, min, max);\n                sq['LEDG'] = adjustor(green, min, max);\n                sq['LEDB'] = adjustor(blue, min, max);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Coalaboard.color_led_by_rgb(%1, %2, %3)'] },\n        },\n        coalaboard_turn_on_color_led_by_picker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coalaboard_turn_on_color_led_by_picker',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'led',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                var port = script.getStringField('VALUE');\n                Entry.hw.sendQueue['LEDR'] = parseInt(port.substr(1, 2), 16);\n                Entry.hw.sendQueue['LEDG'] = parseInt(port.substr(3, 2), 16);\n                Entry.hw.sendQueue['LEDB'] = parseInt(port.substr(5, 2), 16);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Coalaboard.color_led_by_picker(%1)'] },\n        },\n        coalaboard_turn_on_color_led_by_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'coalaboard_turn_on_color_led_by_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'led',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var red, green, blue;\n                value = value % 200;\n                if (value < 67) {\n                    red = 200 - value * 3;\n                    green = value * 3;\n                    blue = 0;\n                } else if (value < 134) {\n                    value = value - 67;\n                    red = 0;\n                    green = 200 - value * 3;\n                    blue = value * 3;\n                } else if (value < 201) {\n                    value = value - 134;\n                    red = value * 3;\n                    green = 0;\n                    blue = 200 - value * 3;\n                }\n                Entry.hw.sendQueue['LEDR'] = red;\n                Entry.hw.sendQueue['LEDG'] = green;\n                Entry.hw.sendQueue['LEDB'] = blue;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Coalaboard.color_led_by_value(%1)'] },\n        },\n        coalaboard_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'coalaboard_buzzer',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'buzzer',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var value = script.getNumberValue('VALUE');\n                    Entry.hw.sendQueue['buzzer'] = value;\n                    script.isStart = true;\n                    return script;\n                } else {\n                    Entry.hw.sendQueue['buzzer'] = 0;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Coalaboard.buzzer(%1)'] },\n        },\n        coalaboard_turn_off_all_motors: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coalaboard_turn_off_all_motors',\n            },\n            class: 'motor',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var coalaboard = Entry.Coalaboard;\n                coalaboard.servoList().map(function(servo) {\n                    sq[servo[1]] = 0;\n                });\n                coalaboard.dcList().map(function(dc) {\n                    sq[dc[1]] = 129;\n                });\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Coalaboard.turn_off_all_motors()'] },\n        },\n        coalaboard_dc_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Coalaboard.dcList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'coalaboard_dc_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, Entry.Coalaboard.dcMaxValue);\n                value = Math.max(value, Entry.Coalaboard.dcMinValue);\n                let val = Entry.Coalaboard.calculateDCMotorValue(value);\n                Entry.hw.sendQueue[script.getStringField('PORT')] = val;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Coalaboard.dc_speed(%1, %2)'] },\n        },\n        coalaboard_dc_direction_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Coalaboard.dcList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.COALABOARD_dc_direction_cw, 'CW'],\n                        [Lang.Blocks.COALABOARD_dc_direction_ccw, 'CCW'],\n                    ],\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'coalaboard_dc_direction_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n            },\n            class: 'motor',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                let isFront = script.getStringField('DIRECTION') === 'CW';\n                let value = script.getNumberValue('VALUE');\n                value = Math.min(value, Entry.Coalaboard.dcMaxValue);\n                value = Math.max(value, 0);\n                if (!isFront) {\n                    value = -1 * value;\n                }\n                let val = Entry.Coalaboard.calculateDCMotorValue(value);\n                Entry.hw.sendQueue[script.getStringField('PORT')] = val;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Coalaboard.dc_direction_speed(%1, %2, %3)'] },\n        },\n        coalaboard_servomotor_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.Coalaboard.servoList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'coalaboard_servomotor_angle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['coalaboard'],\n            func: function(sprite, script) {\n                var value = Entry.Coalaboard.servoMaxValue - (script.getNumberValue('VALUE') + 1);\n                value = Math.min(value, Entry.Coalaboard.servoMaxValue);\n                value = Math.max(value, Entry.Coalaboard.servoMinValue);\n                Entry.hw.sendQueue[script.getStringField('PORT')] = value;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Coalaboard.servomotor_angle(%1, %2)'] },\n        },\n        //endregion coalaboard 코알라보드\n    };\n};\n// 언어 적용\nEntry.Coalaboard.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            template: {\n                coalaboard_when_button_pressed: '%1 버튼 %2 눌러졌을 때',\n                coalaboard_when_sensor_get_value: '%1 %2 값 %3 %4 일 때',\n                coalaboard_is_touch_pressed: '버튼 %1 이(가) %2 인가?',\n                coalaboard_is_sensor_value_compare: '%1 값 %2 %3 인가?',\n                coalaboard_sensor_value: '%1 값',\n                coalaboard_convert_scale: '변환 %1 값 %2 ~ %3 에서 %4 ~ %5',\n                coalaboard_turn_on_color_led_by_rgb:\n                    '엘이디를 빨강 %1 초록 %2 파랑 %3 %4 (으)로 켜기',\n                coalaboard_turn_on_color_led_by_picker: '엘이디를 %1 (으)로 켜기 %2',\n                coalaboard_turn_on_color_led_by_value: '엘이디를 %1 (으)로 켜기 %2',\n                coalaboard_turn_off_color_led: '엘이디 끄기 %1',\n                coalaboard_buzzer: '버저음 %1 내기 %2',\n                coalaboard_servomotor_angle: '서보모터 %1 각도 %2 %3',\n                coalaboard_dc_direction_speed: '디씨모터 %1 방향 %2 속력 %3 %4',\n                coalaboard_dc_speed: '디씨모터 %1 속도 %2 %3',\n                coalaboard_turn_off_all_motors: '모든 모터 멈추기 %1',\n            },\n            Blocks: {\n                COALABOARD_button_pressed: '누름',\n                COALABOARD_button_released: '누르지 않음',\n                COALABOARD_light: '밝기 센서',\n                COALABOARD_IR: '적외선 센서',\n                COALABOARD_touch: '버튼',\n                COALABOARD_temperature: '온도 센서',\n                COALABOARD_ultrasonicSensor: '초음파 센서',\n                COALABOARD_vibrationSensor: '진동 센서',\n                COALABOARD_potentiometer: '가변저항',\n                COALABOARD_MIC: '소리 센서',\n                COALABOARD_UserSensor: '사용자 입력',\n                COALABOARD_UserInput: '사용자 입력',\n                COALABOARD_dc_direction_ccw: '반시계',\n                COALABOARD_dc_direction_cw: '시계',\n            },\n            Menus: {\n                coalaboard: '코알라보드',\n            },\n            Device: {\n                coalaboard: '코알라보드',\n            },\n            Helper: {\n                coalaboard_when_button_pressed:\n                    '비트브릭 버튼을 누르면 아래에 연결된 블록들을 실행합니다.',\n                coalaboard_when_sensor_get_value:\n                    '비트브릭 센서의 값과 오른쪽에 입력한 값을 비교합니다.\\n< : 센서 값이 오른쪽에 위치한 값보다 작은 경우 ‘참’으로 판단합니다.\\n> : 센서 값이 오른쪽에 위치한 값보다 큰 경우 ‘참으로 판단합니다.\\n= :  센서 값이 오른쪽에 위치한 값과 같은 경우 ‘참으로 판단합니다.',\n                coalaboard_sensor_value:\n                    '비트브릭 센서를 사용할 수 있는 블록입니다. 센서값의 범위는 0 ~1023입니다. 메인보드에 연결된 센서의 종류와 포트번호를 자동으로 인식합니다. 블록 안의 화살표를 눌러 사용하려고 하는 센서를 선택하세요.',\n                coalaboard_convert_scale: '비트브릭 센서의 값의 범위를 바꿀 수 있습니다.',\n                coalaboard_is_touch_pressed:\n                    '비트브릭 센서 중 버튼을 눌렀을 경우 ‘참’으로 판단합니다.',\n                coalaboard_turn_off_color_led: '비트브릭 엘이디를 끕니다.',\n                coalaboard_turn_on_color_led_by_rgb:\n                    '비트브릭 엘이디를 빛의 삼원색인 빨강,초록,파랑을 혼합하여 켭니다. 값의 범위는 0 ~ 255입니다.',\n                coalaboard_turn_on_color_led_by_picker:\n                    '비트브릭 엘이디를 색상 창을 사용해 켭니다.',\n                coalaboard_turn_on_color_led_by_value:\n                    '비트브릭 엘이디를 색상 값으로 켭니다. 값의 범위는 0 ~ 199입니다.',\n                coalaboard_buzzer:\n                    '비트브릭 버저를 사용하여 소리를 냅니다. 값의 범위는 0 ~ 96입니다. 값이 0일 때는 버저 소리를 끕니다.',\n                coalaboard_turn_off_all_motors: '비트브릭 모터를 모두 끕니다.',\n                coalaboard_dc_speed:\n                    '비트브릭 디씨모터의 속도를 제어합니다. 속도 값의 범위는 –100 ~ 100입니다. 음수(-)일 때는 반시계방향으로 회전합니다. 양수(+)일 때는 시계방향으로 회전합니다. 속도가 0일 때는 회전을 멈춥니다.',\n                coalaboard_dc_direction_speed:\n                    '비트브릭 디씨모터의 방향과 속력을 제어합니다. 방향은 시계방향과 반시계방향을 선택할 수 있습니다. 속력 값의 범위는 0 ~ 100입니다. 속력이 0일 때는 회전을 멈춥니다.',\n                coalaboard_servomotor_angle:\n                    '비트브릭 서보모터의 각도를 제어합니다. 각도 값의 범위는 0 ~ 180입니다.',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                coalaboard_when_button_pressed: '%1 when button %2',\n                coalaboard_when_sensor_get_value: '%1 when %2 value %3 %4',\n                coalaboard_is_touch_pressed: 'button %1 %2?',\n                coalaboard_is_sensor_value_compare: '%1 %2 %3? ',\n                coalaboard_sensor_value: '%1 value',\n                coalaboard_convert_scale: 'map %1 value from %2 ~ %3 to %4 ~ %5',\n                coalaboard_turn_on_color_led_by_rgb: 'set LED color to Red %1 Green %2 Blue %3 %4',\n                coalaboard_turn_on_color_led_by_picker: 'set LED color to %1 %2',\n                coalaboard_turn_on_color_led_by_value: 'set LED color %1 %2',\n                coalaboard_turn_off_color_led: 'turn off LED %1',\n                coalaboard_buzzer: 'buzz note %1 %2',\n                coalaboard_servomotor_angle: 'servo motor %1 degree %2 %3',\n                coalaboard_dc_direction_speed: 'dc motor %1 direction %2 speed %3 %4',\n                coalaboard_dc_speed: 'dc motor %1 velocity %2 %3',\n                coalaboard_turn_off_all_motors: 'stop all motors %1',\n            },\n            Blocks: {\n                COALABOARD_button_pressed: 'pressed',\n                COALABOARD_button_released: 'released',\n                COALABOARD_light: 'light',\n                COALABOARD_IR: 'IR',\n                COALABOARD_touch: 'touch',\n                COALABOARD_temperature: 'temperature',\n                COALABOARD_ultrasonicSensor: 'ultrasonicSenso',\n                COALABOARD_vibrationSensor: 'vibrationSensor',\n                COALABOARD_potentiometer: 'potentiometer',\n                COALABOARD_MIC: 'MIC',\n                COALABOARD_UserSensor: 'UserSensor',\n                COALABOARD_UserInput: 'UserInput',\n                COALABOARD_dc_direction_ccw: 'CCW',\n                COALABOARD_dc_direction_cw: 'CW',\n            },\n            Menus: {\n                coalaboard: 'coalaboard',\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Coalaboard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_cobl.js",
    "content": "'use strict';\n\nEntry.Cobl = {\n    id: '1.A',\n    name: 'cobl',\n    url: 'http://www.cobl.co.kr/',\n    imageName: 'cobl.png',\n    title: {\n        ko: '코블',\n        en: 'Cobl',\n    },\n    setZero: function() {\n        for (var port = 0; port < 14; port++) {\n            Entry.hw.sendQueue[port] = 0;\n        }\n        Entry.hw.update();\n    },\n};\nEntry.Cobl.blockMenuBlocks = [\n    'cobl_read_ultrason',\n    'cobl_read_potenmeter',\n    'cobl_read_irread1',\n    'cobl_read_irread2',\n    'cobl_read_joyx',\n    'cobl_read_joyy',\n    //\"cobl_read_sens1\",\n    //\"cobl_read_sens2\",\n    'cobl_read_tilt',\n    'cobl_read_temps',\n    'cobl_read_light',\n    'cobl_read_btn',\n    'cobl_led_control',\n    'cobl_rgb_boardled',\n    'cobl_servo_angle_control',\n    'cobl_melody',\n    'cobl_dcmotor',\n    'cobl_extention_port',\n    'cobl_external_RainBowled',\n    'cobl_external_led',\n    'cobl_7_segment',\n];\nEntry.Cobl.setLanguage = function() {\n    return {\n        ko: {\n            Menus: {\n                cobl: '코블',\n            },\n        },\n        en: {\n            Menus: {\n                cobl: 'Cobl',\n            },\n        },\n    };\n};\nEntry.Cobl.getBlocks = function() {\n    return {\n        //region cobl 코블\n        cobl_read_ultrason: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '1. 초음파거리(0~400)',\n            def: {\n                type: 'cobl_read_ultrason',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('ultrason');\n            },\n        },\n        cobl_read_potenmeter: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '2.가변저항(0~1023)',\n            def: {\n                type: 'cobl_read_potenmeter',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('potenmeter');\n            },\n        },\n        cobl_read_irread1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '3.적외선센서1(0~1023)',\n            def: {\n                type: 'cobl_read_irread1',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('irread1');\n            },\n        },\n        cobl_read_irread2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '4.적외선센서2(0~1023)',\n            def: {\n                type: 'cobl_read_irread2',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('irread2');\n            },\n        },\n        cobl_read_joyx: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '5.조이스틱X축(1, 0, -1)',\n            def: {\n                type: 'cobl_read_joyx',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('joyx');\n            },\n        },\n        cobl_read_joyy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '6.조이스틱Y축(1, 0, -1)',\n            def: {\n                type: 'cobl_read_joyy',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('joyy');\n            },\n        },\n        cobl_read_tilt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '7.기울기센서(0~4)',\n            def: {\n                type: 'cobl_read_tilt',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('tilt');\n            },\n        },\n        cobl_read_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '8.색상센서',\n            def: {\n                type: 'cobl_read_color',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var colorval = Entry.hw.getAnalogPortValue('color');\n\n                if (colorval == 1) return '빨강';\n                else if (colorval == 2) return '녹색';\n                else if (colorval == 3) return '파랑';\n                else return '알수없음';\n            },\n        },\n        cobl_read_humid: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '9.습도센서',\n            def: {\n                type: 'cobl_read_humid',\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('humid');\n            },\n        },\n        cobl_read_temps: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '10.온도센서@포트%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['1'],\n                type: 'cobl_read_temps',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                //    console.log(\"-----temptest------\")\n                var signal = script.getField('VALUE', script);\n                if (signal == 1) {\n                    //    console.log(\"-----temp1 selected \");\n                    return Entry.hw.getAnalogPortValue('temps1');\n                }\n\n                if (signal == 2) {\n                    //     console.log(\"-----temp2 selected \");\n                    return Entry.hw.getAnalogPortValue('temps2');\n                }\n            },\n        },\n        cobl_read_light: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '11.빛센서@포트%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['1'],\n                type: 'cobl_read_light',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var signal = script.getField('VALUE', script);\n                if (signal == 1) {\n                    return Entry.hw.getAnalogPortValue('light1');\n                }\n\n                if (signal == 2) {\n                    return Entry.hw.getAnalogPortValue('light2');\n                }\n            },\n        },\n        cobl_read_btn: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            template: '12.버튼스위치@포트%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['1'],\n                type: 'cobl_read_btn',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var signal = script.getField('VALUE', script);\n                if (signal == 1) {\n                    return Entry.hw.getDigitalPortValue('btn1');\n                }\n\n                if (signal == 2) {\n                    return Entry.hw.getDigitalPortValue('btn2');\n                }\n            },\n        },\n        cobl_led_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '13-1.무지개LED%1%2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OFF', 'OFF'],\n                        ['빨강', 'Red'],\n                        ['주황', 'Orange'],\n                        ['노랑', 'Yellow'],\n                        ['초록', 'Green'],\n                        ['파랑', 'Blue'],\n                        ['남색', 'Dark Blue'],\n                        ['보라', 'Purple'],\n                        ['흰색', 'White'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['1', 'OFF'],\n                type: 'cobl_led_control',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                var value = script.getStringField('OPERATOR');\n                Entry.hw.setDigitalPortValue('RainBowLED_' + port, value);\n                Entry.hw.update();\n                delete Entry.hw.sendQueue['RainBowLED_' + port];\n                return script.callReturn();\n            },\n        },\n        cobl_rgb_boardled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '13-2.무지개LED%1R%2G%3B%4 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['1', '1', '1', '1'],\n                type: 'cobl_rgb_boardled',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var led = script.getNumberField('LED');\n                var r = script.getStringField('RED');\n                var g = script.getStringField('GREEN');\n                var b = script.getStringField('BLUE');\n\n                Entry.hw.setDigitalPortValue('BLED_IDX', led);\n                Entry.hw.setDigitalPortValue('BLED_R', r);\n                Entry.hw.setDigitalPortValue('BLED_G', g);\n                Entry.hw.setDigitalPortValue('BLED_B', b);\n                Entry.hw.update();\n\n                delete Entry.hw.sendQueue['BLED_IDX'];\n                delete Entry.hw.sendQueue['BLED_R'];\n                delete Entry.hw.sendQueue['BLED_G'];\n                delete Entry.hw.sendQueue['BLED_B'];\n\n                return script.callReturn();\n            },\n        },\n        cobl_servo_angle_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '14.각도모터 각도%1(15~165) %2',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['90'],\n                type: 'cobl_servo_angle_control',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 15);\n                value = Math.min(value, 165);\n\n                Entry.hw.setDigitalPortValue('Servo1', value);\n                Entry.hw.update();\n                delete Entry.hw.sendQueue['Servo1'];\n\n                return script.callReturn();\n            },\n        },\n        cobl_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '15.멜로디%1 시간%2(초) %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['(낮은)솔', 'L_So'],\n                        ['(낮은)솔#', 'L_So#'],\n                        ['(낮은)라', 'L_La'],\n                        ['(낮은)라#', 'L_La#'],\n                        ['(낮은)시', 'L_Ti'],\n                        ['도', 'Do'],\n                        ['도#', 'Do#'],\n                        ['레', 'Re'],\n                        ['레#', 'Re#'],\n                        ['미', 'Mi'],\n                        ['파', 'Fa'],\n                        ['파#', 'Fa#'],\n                        ['솔', 'So'],\n                        ['솔#', 'So#'],\n                        ['라', 'La'],\n                        ['라#', 'La#'],\n                        ['시', 'Ti'],\n                        ['(높은)도', 'H_Do'],\n                        ['(높은)도#', 'H_Do#'],\n                        ['(높은)레', 'H_Re'],\n                        ['(높은)레#', 'H_Re#'],\n                        ['(높은)미', 'H_Mi'],\n                        ['(높은)파', 'H_Fa'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 1,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['Do', '1'],\n                type: 'cobl_melody',\n            },\n            paramsKeyMap: {\n                MELODY: 0,\n                DURATION: 1,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var melody = script.getStringField('MELODY');\n                var duration = script.getNumberValue('DURATION');\n\n                Entry.hw.setDigitalPortValue('Melody', melody);\n                Entry.hw.setDigitalPortValue('Melody_DUR', duration);\n\n                Entry.hw.update();\n                delete Entry.hw.sendQueue['Melody'];\n                delete Entry.hw.sendQueue['Melody_DUR'];\n\n                return script.callReturn();\n            },\n        },\n        cobl_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '16.회전모터%1%2속도%3 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1.시계방향', '1'],\n                        ['2.반시계방향', '2'],\n                        ['3.정지', '3'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['1', '1', '1'],\n                type: 'cobl_dcmotor',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var motor = script.getStringField('MOTOR');\n                var direction = script.getStringField('DIRECTION');\n                var speed = script.getStringField('SPEED');\n\n                if (motor == 1) {\n                    Entry.hw.setDigitalPortValue('DC1_DIR', direction);\n                    Entry.hw.setDigitalPortValue('DC1_SPEED', speed);\n                    Entry.hw.update();\n                    delete Entry.hw.sendQueue['DC1_DIR'];\n                    delete Entry.hw.sendQueue['DC1_SPEED'];\n                }\n\n                if (motor == 2) {\n                    Entry.hw.setDigitalPortValue('DC2_DIR', direction);\n                    Entry.hw.setDigitalPortValue('DC2_SPEED', speed);\n                    Entry.hw.update();\n                    delete Entry.hw.sendQueue['DC2_DIR'];\n                    delete Entry.hw.sendQueue['DC2_SPEED'];\n                }\n\n                return script.callReturn();\n            },\n        },\n        cobl_extention_port: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '17.USB포트%1단계%2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['1', '0'],\n                type: 'cobl_extention_port',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                LEVEL: 1,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                var level = script.getStringField('LEVEL');\n\n                if (port == 1) {\n                    Entry.hw.setDigitalPortValue('EXUSB1', level);\n                    Entry.hw.update();\n                    delete Entry.hw.sendQueue['EXUSB1'];\n                }\n\n                if (port == 2) {\n                    Entry.hw.setDigitalPortValue('EXUSB2', level);\n                    Entry.hw.update();\n                    delete Entry.hw.sendQueue['EXUSB2'];\n                }\n                return script.callReturn();\n            },\n        },\n        cobl_external_RainBowled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '18-1.외부LED%1 (1~64)%2 %3',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 0,\n                    fontSize: 11,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OFF', 'OFF'],\n                        ['빨강', 'Red'],\n                        ['주황', 'Orange'],\n                        ['노랑', 'Yellow'],\n                        ['초록', 'Green'],\n                        ['파랑', 'Blue'],\n                        ['남색', 'Dark Blue'],\n                        ['보라', 'Purple'],\n                        ['흰색', 'White'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['1', 'OFF'],\n                type: 'cobl_external_RainBowled',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var led = script.getNumberValue('PORT');\n                var value = script.getStringField('OPERATOR');\n\n                Entry.hw.setDigitalPortValue('ELED_IDX', led);\n\n                if (value == 'OFF') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 0);\n                    Entry.hw.setDigitalPortValue('ELED_G', 0);\n                    Entry.hw.setDigitalPortValue('ELED_B', 0);\n                } else if (value == 'Red') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 10);\n                    Entry.hw.setDigitalPortValue('ELED_G', 0);\n                    Entry.hw.setDigitalPortValue('ELED_B', 0);\n                } else if (value == 'Orange') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 10);\n                    Entry.hw.setDigitalPortValue('ELED_G', 3);\n                    Entry.hw.setDigitalPortValue('ELED_B', 0);\n                } else if (value == 'Yellow') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 10);\n                    Entry.hw.setDigitalPortValue('ELED_G', 10);\n                    Entry.hw.setDigitalPortValue('ELED_B', 0);\n                } else if (value == 'Green') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 0);\n                    Entry.hw.setDigitalPortValue('ELED_G', 10);\n                    Entry.hw.setDigitalPortValue('ELED_B', 0);\n                } else if (value == 'Blue') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 0);\n                    Entry.hw.setDigitalPortValue('ELED_G', 0);\n                    Entry.hw.setDigitalPortValue('ELED_B', 10);\n                } else if (value == 'Dark Blue') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 0);\n                    Entry.hw.setDigitalPortValue('ELED_G', 7);\n                    Entry.hw.setDigitalPortValue('ELED_B', 10);\n                } else if (value == 'Purple') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 10);\n                    Entry.hw.setDigitalPortValue('ELED_G', 0);\n                    Entry.hw.setDigitalPortValue('ELED_B', 10);\n                } else if (value == 'White') {\n                    Entry.hw.setDigitalPortValue('ELED_R', 10);\n                    Entry.hw.setDigitalPortValue('ELED_G', 10);\n                    Entry.hw.setDigitalPortValue('ELED_B', 10);\n                }\n                Entry.hw.update();\n\n                delete Entry.hw.sendQueue['ELED_IDX'];\n                delete Entry.hw.sendQueue['ELED_R'];\n                delete Entry.hw.sendQueue['ELED_G'];\n                delete Entry.hw.sendQueue['ELED_B'];\n            },\n        },\n        cobl_external_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '18-2.외부LED%1(1~64)R%2G%3B%4 %5',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 0,\n                    fontSize: 11,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['1', '1', '1', '1'],\n                type: 'cobl_external_led',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var led = script.getNumberValue('LED');\n                var r = script.getStringField('RED');\n                var g = script.getStringField('GREEN');\n                var b = script.getStringField('BLUE');\n\n                Entry.hw.setDigitalPortValue('ELED_IDX', led);\n                Entry.hw.setDigitalPortValue('ELED_R', r);\n                Entry.hw.setDigitalPortValue('ELED_G', g);\n                Entry.hw.setDigitalPortValue('ELED_B', b);\n                Entry.hw.update();\n\n                delete Entry.hw.sendQueue['ELED_IDX'];\n                delete Entry.hw.sendQueue['ELED_R'];\n                delete Entry.hw.sendQueue['ELED_G'];\n                delete Entry.hw.sendQueue['ELED_B'];\n\n                return script.callReturn();\n            },\n        },\n        cobl_7_segment: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '19.숫자전광판%1(0~9999) %2',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 0,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: ['0'],\n                type: 'cobl_7_segment',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cobl',\n            isNotFor: ['cobl'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var value_s = value.toString();\n                var value_c = value_s.substring(0, 4);\n                Entry.hw.setDigitalPortValue('7SEG', value_c);\n                Entry.hw.update();\n                delete Entry.hw.sendQueue['7SEG'];\n                return script.callReturn();\n            },\n        },\n        //endregion cobl 코블\n    };\n};\n\nmodule.exports = Entry.Cobl;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_coco.js",
    "content": "'use strict';\r\n\r\nEntry.coco = {\r\n    id: '5D.1',\r\n    name: 'coco',\r\n    url: 'http://www.coco.co.kr',\r\n    imageName: 'coco.png',\r\n    title: {\r\n        ko: '코코',\r\n        en: 'coco',\r\n    },\r\n    Static: {\r\n        BUTTON_PRESS_VALUE: 0,\r\n    },\r\n\r\n    //정지시 초기화 함수\r\n    setZero: function() {\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                if (Entry.hw.sendQueue.SET[key].type == Entry.coco.sensorTypes.SERVO) {\r\n                    Entry.hw.sendQueue.SET[key].data = 200;\r\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n                } \r\n                else if (Entry.hw.sendQueue.SET[key].type == Entry.coco.sensorTypes.SERVO2) {\r\n                    Entry.hw.sendQueue.SET[key].data.value1 = 200;\r\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n                } \r\n                else {\r\n                    Entry.hw.sendQueue.SET[key].data = 0;\r\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n                }\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO: 4,\r\n        TONE: 5,\r\n        PULSEIN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n        READ_BLUETOOTH: 9,\r\n        WRITE_BLUETOOTH: 10,\r\n        LCD: 11,\r\n        LCDCLEAR: 12,\r\n        RGBLED: 13,\r\n        DCMOTOR: 14,\r\n        OLED: 15,\r\n        PIR: 16,\r\n        LCDINIT: 17,\r\n        DHTHUMI: 18,\r\n        DHTTEMP: 19,\r\n        NEOPIXELINIT: 20,\r\n        NEOPIXELBRIGHT: 21,\r\n        NEOPIXEL: 22,\r\n        NEOPIXELALL: 23,\r\n        NEOPIXELCLEAR: 24,\r\n        DOTMATRIXINIT: 25,\r\n        DOTMATRIXBRIGHT: 26,\r\n        DOTMATRIX: 27,\r\n        DOTMATRIXEMOJI: 28,\r\n        DOTMATRIXCLEAR: 29,\r\n        MP3INIT: 30,\r\n        MP3PLAY1: 31,\r\n        MP3PLAY2: 32,\r\n        MP3VOL: 33,\r\n        RESET_: 34,\r\n        LOADINIT: 35,\r\n        LOADSCALE: 36,\r\n        LOADVALUE: 37,\r\n        DUST: 38,\r\n        JOYINIT: 39,\r\n        JOYX: 40,\r\n        JOYY: 41,\r\n        JOYZ: 42,\r\n        JOYMOVE: 43,\r\n        RFIDINIT: 44,\r\n        RFIDTAP: 45,\r\n        RFIDVALUE: 46,\r\n        STEPINIT: 47,\r\n        STEPSPEED: 48,\r\n        STEPROTATE: 49,\r\n        STEPROTATE2: 50,\r\n        STEPROTATE3: 51,\r\n        MLXOBJ: 52,\r\n        MLXAMB: 53,\r\n        SERVO2: 54,\r\n        GYROX: 55,\r\n        GYROY: 56,\r\n        GYROZ: 57,\r\n        PULLUP: 58,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    direction: {\r\n        CENTER: 0,\r\n        UP: 1,\r\n        LEFT: 2,\r\n        RIGHT: 3,\r\n        DOWN: 4,\r\n        LEFT_UP: 5,\r\n        LEFT_DOWN: 6,\r\n        RIGHT_UP: 7,\r\n        RIGHT_DOWN: 8,\r\n    },\r\n    highList: ['high', '1', 'on'],\r\n    lowList: ['low', '0', 'off'],\r\n    BlockState: {},\r\n};\r\nEntry.coco.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                coco_toggle_on: '켜기',\r\n                coco_toggle_off: '끄기',\r\n                coco_lcd_first_line: '첫 번째',\r\n                coco_lcd_seconds_line: '두 번째',\r\n                coco_get_analog_value: '아날로그 %1 핀 읽기',\r\n                coco_get_light_value: '조도센서(AO %1)값',\r\n                coco_get_moisture_value: '토양수분센서(AO %1)값',\r\n                coco_get_sound_value: '사운드센서(AO %1)값',\r\n                coco_get_infrared_value: '적외선센서(AO %1)값',\r\n                coco_get_pullup: '풀업 저항 사용 버튼 %1 핀 눌림 상태',\r\n                coco_get_button: '버튼 %1 핀 눌림 상태',\r\n                coco_get_analog_mapping:\r\n                    '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\r\n                coco_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\r\n                coco_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\r\n                coco_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\r\n                coco_get_digital: '디지털 %1 핀 읽기',\r\n                coco_get_digital_toggle: '디지털 %1 핀 센서 값',\r\n                coco_get_digital_pir: 'PIR %1 핀 센서 값',\r\n                coco_set_digital_toggle: '디지털 %1 핀 %2 %3',\r\n                coco_set_led_toggle: 'LED %1 핀 %2 %3',\r\n                coco_set_digital_pwm: 'LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3',\r\n                coco_set_digital_rgbled: 'RGB LED (R %1 핀, G %2 핀, B %3 핀) 색 (R: %4, G: %5, B: %6) 출력 %7',\r\n\r\n                coco_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\r\n                coco_set_digital_servo2: \"서보 모터 %1 핀 %2 ~ %3 각도로 %4 초 동안 회전 %5\",\r\n                coco_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\r\n                coco_set_digital_buzzer_volume: '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\r\n                coco_set_digital_buzzer: '피에조부저 %1 핀 %2 %3 음 %4 박자 연주 %5',\r\n\r\n                coco_set_digital_dcmotor: 'DC모터 %1핀 %2 %3',\r\n                coco_set_analog_dcmotor: 'DC모터(PWM %1 핀) 세기 %2 출력 (0 ~ 255) %3',\r\n                coco_set_neopixel_init:\r\n                    '네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\r\n                coco_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\r\n                coco_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\r\n                coco_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\r\n                coco_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\r\n                coco_set_dotmatrix_init:\r\n                    '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\r\n                coco_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\r\n                coco_set_dotmatrix: '도트매트릭스 LED %1 그리기 %2',\r\n                coco_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\r\n                coco_set_dotmatrix_clear: '도트매트릭스 LED 지우기 %1',\r\n\r\n                coco_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\r\n                coco_get_lcd_row: '%1',\r\n                coco_get_lcd_col: '%1',\r\n                coco_module_digital_lcd: 'LCD화면 %1 열 %2 행 부터 %3 출력 %4',\r\n                coco_lcd_clear: 'LCD 화면 지우기 %1',\r\n                coco_get_dht: 'DHT11 온습도센서(out %1)의 %2값',                \r\n\r\n                coco_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\r\n                coco_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\r\n                coco_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\r\n                coco_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\r\n                coco_get_analog_temp_value: 'DHT11 포트 %1의 %2 센서 값',\r\n\r\n                coco_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3',\r\n                coco_load_scale: 'HX711 로드셀 보정하기 %1 %2',\r\n                coco_load_value: 'HX711 로드셀 값',\r\n\r\n                coco_get_dust: '미세먼지센서 (LED %1, AO %2) 값',\r\n\r\n                coco_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5',\r\n                coco_get_joy_x: '%1 조이스틱 X값',\r\n                coco_get_joy_y: '%1 조이스틱 y값',\r\n                coco_get_joy_z: '%1 조이스틱 버튼 눌림 상태',\r\n                coco_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때',\r\n\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                coco_toggle_on: 'on',\r\n                coco_toggle_off: 'off',\r\n                coco_lcd_first_line: 'first',\r\n                coco_lcd_seconds_line: 'seconds',\r\n                coco_get_analog_value: 'Read analog %1 pin sensor value',\r\n                coco_get_analog_mapping: 'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\r\n                coco_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\r\n                coco_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\r\n                coco_get_digital_bluetooth: 'Bluetooth RX 2 value',\r\n                coco_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\r\n                coco_get_digital: 'Digital %1 pin sensor value',\r\n                coco_get_digital_toggle: 'Digital %1 pin sensor value',\r\n                coco_set_digital_toggle: 'Digital %1 pin %2 %3',\r\n                coco_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\r\n                coco_set_digital_rgbled: 'Digital %1 pin RGB LED Red %2 Green %3 Blue %4 %5',\r\n                coco_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\r\n                coco_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\r\n                coco_set_digital_buzzer_volume: '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\r\n                coco_set_digital_buzzer:\r\n                    '피에조부저 %1 번 핀의 버저를 %2 %3 음으로 %4 박자 연주 %5',\r\n                coco_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5',\r\n                coco_set_neopixel_init:\r\n                    '네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\r\n                coco_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\r\n                coco_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\r\n                coco_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\r\n                coco_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\r\n                coco_set_dotmatrix_init:\r\n                    '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\r\n                coco_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\r\n                coco_set_dotmatrix: '도트매트릭스 LED 그리기 %1 %2',\r\n                coco_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\r\n                coco_module_digital_lcd: 'LCD %1 열 %2 행 부터 %3 출력',\r\n                coco_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\r\n\r\n                coco_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\r\n                coco_module_digital_oled: 'OLED X codinate %1 Y coodinate %2 appear %3 %4',\r\n                coco_get_dht_temp_value: '온습도센서의 온도값',\r\n                coco_get_dht_humi_value: '온습도센서의 습도값',\r\n\r\n                coco_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\r\n                coco_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\r\n                coco_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\r\n                coco_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\r\n\r\n                coco_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3',\r\n                coco_load_scale: 'HX711 로드셀 보정하기 %1 %2',\r\n                coco_load_value: 'HX711 로드셀 값',\r\n\r\n                coco_get_dust: '미세먼지센서(LED %1, AO %2) 값(μg/m³)',\r\n\r\n                coco_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5',\r\n                coco_get_joy_x: '%1 조이스틱 X값',\r\n                coco_get_joy_y: '%1 조이스틱 y값',\r\n                coco_get_joy_z: '%1 조이스틱 버튼 눌림 상태',\r\n                coco_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때',\r\n\r\n            },\r\n        },\r\n    };\r\n};\r\nEntry.coco.blockMenuBlocks = [\r\n    'coco_set_digital_toggle',\r\n    'coco_get_analog_value',\r\n    'coco_get_digital',\r\n    'coco_get_analog_mapping',\r\n    'coco_mapping1',\r\n    'coco_mapping2',\r\n\r\n    'coco_set_led_toggle',\r\n    'coco_set_digital_pwm',\r\n    'coco_set_digital_rgbled',\r\n\r\n    'coco_get_digital_ultrasonic',\r\n    'coco_get_dust',\r\n    'coco_get_digital_toggle',\r\n    'coco_get_digital_pir',\r\n    'coco_get_light_value',\r\n    'coco_get_moisture_value',\r\n    'coco_get_sound_value',\r\n    'coco_get_infrared_value',\r\n    'coco_get_dht',\r\n\r\n    'coco_get_pullup',\r\n    'coco_get_button',\r\n\r\n    'coco_set_digital_dcmotor',\r\n    'coco_set_analog_dcmotor',\r\n    'coco_set_digital_servo',\r\n    'coco_set_digital_servo2',\r\n    'coco_set_digital_buzzer_toggle',\r\n    'coco_set_digital_buzzer_volume',\r\n    'coco_set_digital_buzzer',\r\n    'coco_set_neopixel_init',\r\n    'coco_set_neopixel_bright',\r\n    'coco_set_neopixel',\r\n    'coco_set_neopixel_all',\r\n    'coco_set_neopixel_clear',\r\n    'coco_set_dotmatrix_init',\r\n    'coco_set_dotmatrix_bright',\r\n    'coco_set_dotmatrix',\r\n    'coco_set_dotmatrix_emoji',\r\n    'coco_set_dotmatrix_clear',\r\n    'coco_lcd_init',\r\n    'coco_module_digital_lcd',\r\n    'coco_get_lcd_row',\r\n    'coco_get_lcd_col',\r\n    'coco_lcd_clear',\r\n    'coco_set_mp3_init',\r\n    'coco_set_mp3_vol',\r\n    'coco_set_mp3_play',\r\n    'coco_set_mp3_play2',\r\n    'coco_load_init',\r\n    'coco_load_scale',\r\n    'coco_load_value',\r\n\r\n    'coco_joy_init',\r\n    'coco_get_joy_x',\r\n    'coco_get_joy_y',\r\n    'coco_get_joy_z',\r\n    'coco_get_joy_move',\r\n];\r\nEntry.coco.getBlocks = function() {\r\n    var tx;\r\n    var din;\r\n    // var clk;\r\n    // var cs;\r\n    var dout;\r\n    var sck;\r\n    var joyx, joyy, joyz;\r\n    var joyx2, joyy2, joyz2;\r\n    var portpin1, portpin2, portpin3;\r\n    var ss;\r\n    var RGBport;\r\n    var mlxport;\r\n    var speed1 = 14;\r\n    var speed2 = 14;\r\n    var speed3 = 14;\r\n    var num = 0;\r\n\r\n    return {\r\n        coco_list_analog_basic: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n        coco_list_digital_basic: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                        ['12', '12'],\r\n                        ['13', '13'],\r\n                    ],\r\n                    value: '10',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n        coco_list_digital_octave: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n        },\r\n        coco_list_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['3', '3'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                    ],\r\n                    value: '11',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n        coco_list_digital_toggle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.coco_toggle_on, 'on'],\r\n                        [Lang.template.coco_toggle_off, 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OPERATOR: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('OPERATOR');\r\n            },\r\n        },\r\n        coco_list_digital_toggle_en: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['HIGH', 'on'],\r\n                        ['LOW', 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OPERATOR: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('OPERATOR');\r\n            },\r\n        },\r\n        coco_list_digital_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n        },\r\n        coco_set_neopixel_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['7'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['4'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_neopixel_init',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NUM: 1,\r\n            },\r\n            class: 'neo',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getNumberValue('NUM');\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.NEOPIXELINIT,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_set_neopixel_bright: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['7'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_neopixel_bright',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NUM: 1,\r\n            },\r\n            class: 'neo',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getNumberValue('NUM');\r\n\r\n                value = Math.round(value);\r\n                value = Math.min(value, 255);\r\n                value = Math.max(value, 0);\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.NEOPIXELBRIGHT,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_set_neopixel: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Color',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['7'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'coco_set_neopixel',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NUM: 1,\r\n                COLOR: 2,\r\n            },\r\n            class: 'neo',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                //var sq = Entry.hw.sendQueue;\r\n                var port = script.getNumberValue('PORT', script);\r\n                var num = script.getNumberValue('NUM', script);\r\n                var value = script.getStringField('COLOR', script);\r\n\r\n                let r = parseInt(value.substr(1, 2), 16);\r\n                let g = parseInt(value.substr(3, 2), 16);\r\n                let b = parseInt(value.substr(5, 2), 16);\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    r = Math.round(r);\r\n                    r = Math.min(r, 255);\r\n                    r = Math.max(r, 0);\r\n\r\n                    g = Math.round(g);\r\n                    g = Math.min(g, 255);\r\n                    g = Math.max(g, 0);\r\n\r\n                    b = Math.round(b);\r\n                    b = Math.min(b, 255);\r\n                    b = Math.max(b, 0);\r\n\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.NEOPIXEL,\r\n                        data: {\r\n                            num: num,\r\n                            r: r,\r\n                            g: g,\r\n                            b: b,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, 10);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_set_neopixel_all: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Color',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['7'],\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'coco_set_neopixel_all',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                COLOR: 1,\r\n            },\r\n            class: 'neo',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT', script);\r\n                var value = script.getStringField('COLOR', script);\r\n\r\n                let r = parseInt(value.substr(1, 2), 16);\r\n                let g = parseInt(value.substr(3, 2), 16);\r\n                let b = parseInt(value.substr(5, 2), 16);\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n                    r = Math.round(r);\r\n                    r = Math.min(r, 255);\r\n                    r = Math.max(r, 0);\r\n\r\n                    g = Math.round(g);\r\n                    g = Math.min(g, 255);\r\n                    g = Math.max(g, 0);\r\n\r\n                    b = Math.round(b);\r\n                    b = Math.min(b, 255);\r\n                    b = Math.max(b, 0);\r\n\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.NEOPIXELALL,\r\n                        data: {\r\n                            r: r,\r\n                            g: g,\r\n                            b: b,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, 10);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_set_neopixel_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['7'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_neopixel_clear',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'neo',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.NEOPIXELCLEAR,\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_lcd_list_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0x27', '0'],\r\n                        ['0x3F', '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                LINE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('LINE');\r\n            },\r\n        },\r\n        coco_set_dotmatrix_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['12'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['11'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['10'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_dotmatrix_init',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n                PORT3: 2,\r\n            },\r\n            class: 'dot',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port1 = script.getNumberValue('PORT1', script);\r\n                var port2 = script.getNumberValue('PORT2', script);\r\n                var port3 = script.getNumberValue('PORT3', script);\r\n\r\n                din = port1;\r\n                // clk = port2;\r\n                // cs = port3;\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][port1] = {\r\n                        type: Entry.coco.sensorTypes.DOTMATRIXINIT,\r\n                        data: {\r\n                            port1: port1,\r\n                            port2: port2,\r\n                            port3: port3,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_set_dotmatrix_bright: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['8'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_dotmatrix_bright',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n            },\r\n            class: 'dot',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var num = script.getNumberValue('NUM', script);\r\n\r\n                num = Math.round(num);\r\n                num = Math.min(num, 8);\r\n                num = Math.max(num, 0);\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][din] = {\r\n                        type: Entry.coco.sensorTypes.DOTMATRIXBRIGHT,\r\n                        data: num,\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_set_dotmatrix_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'coco_set_dotmatrix_clear',\r\n            },\r\n            class: 'dot',\r\n            isNotFor: ['coco'],\r\n            func(sprite, script) {\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (1 + 0.5) * 0.1; //0.15\r\n                    timeValue = (60 / fps) * timeValue * 100;\r\n\r\n                    Entry.hw.sendQueue['SET'][din] = {\r\n                        type: Entry.coco.sensorTypes.DOTMATRIXCLEAR,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_set_dotmatrix: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['003c420024242400'],\r\n                    },\r\n                ],\r\n                type: 'coco_set_dotmatrix',\r\n            },\r\n            paramsKeyMap: {\r\n                STRING: 0,\r\n            },\r\n            class: 'dot',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var text = script.getValue('STRING');\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][din] = {\r\n                        type: Entry.coco.sensorTypes.DOTMATRIX,\r\n                        data: {\r\n                            text: text,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_dotmatrix_emoji_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['🖤', '1'],\r\n                        ['🤍', '2'],\r\n                        ['👆', '3'],\r\n                        ['👇', '4'],\r\n                        ['👈', '5'],\r\n                        ['👉', '6'],\r\n                        ['😊', '7'],\r\n                        ['😥', '8'],\r\n                        ['😡', '9'],\r\n                        ['😆', '10'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                LINE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('LINE');\r\n            },\r\n        },\r\n        coco_set_dotmatrix_emoji: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_dotmatrix_emoji_list',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_dotmatrix_emoji',\r\n            },\r\n            paramsKeyMap: {\r\n                LIST: 0,\r\n            },\r\n            class: 'dot',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var value = script.getNumberValue('LIST');\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][din] = {\r\n                        type: Entry.coco.sensorTypes.DOTMATRIXEMOJI,\r\n                        data: value,\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_list_digital_lcd: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.coco_lcd_first_line, '0'],\r\n                        [Lang.template.coco_lcd_seconds_line, '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                LINE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('LINE');\r\n            },\r\n        },\r\n        coco_get_lcd_row: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                ROW: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('ROW');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['0', '0'],\r\n                                    ['1', '1'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'coco_get_lcd_row',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        coco_get_lcd_col: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                        ['12', '12'],\r\n                        ['13', '13'],\r\n                        ['14', '14'],\r\n                        ['15', '15'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                ROW: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('ROW');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['0', '0'],\r\n                                    ['1', '1'],\r\n                                    ['2', '2'],\r\n                                    ['3', '3'],\r\n                                    ['4', '4'],\r\n                                    ['5', '5'],\r\n                                    ['6', '6'],\r\n                                    ['7', '7'],\r\n                                    ['8', '8'],\r\n                                    ['9', '9'],\r\n                                    ['10', '10'],\r\n                                    ['11', '11'],\r\n                                    ['12', '12'],\r\n                                    ['13', '13'],\r\n                                    ['14', '14'],\r\n                                    ['15', '15'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'coco_get_lcd_col',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        coco_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.coco_get_analog_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoPin',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getValue('PORT', script);\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                if (port[0] === 'A') port = port.substring(1);\r\n\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: { js: [], py: ['coco.get_analog_value(%1)'] },\r\n        },\r\n        coco_get_light_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_light_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getValue('PORT', script);\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                if (port[0] === 'A') port = port.substring(1);\r\n\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: { js: [], py: ['coco.get_analog_value(%1)'] },\r\n        },\r\n        coco_get_moisture_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            //template: Lang.template.coco_get_analog_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                        params: ['1'],\r\n                    },\r\n                ],\r\n                type: 'coco_get_moisture_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getValue('PORT', script);\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                if (port[0] === 'A') port = port.substring(1);\r\n\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: { js: [], py: ['coco.get_analog_value(%1)'] },\r\n        },\r\n\r\n        coco_set_digital_dcmotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_set_digital_dcmotor,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_toggle',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_dcmotor',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'cocoSet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.coco.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.coco.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.coco.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: ['coco.set_digital_dcmotor(%1, %2, %3, %4)'] },\r\n        },\r\n        coco_set_analog_dcmotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_set_analog_dcmotor,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_pwm',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_analog_dcmotor',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'cocoSet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                value = Math.round(value);\r\n                value = Math.min(value, 255);\r\n                value = Math.max(value, 0);\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.coco.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: ['coco.set_digital_dcmotor(%1, %2, %3, %4)'] },\r\n        },\r\n        coco_get_sound_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_sound_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getValue('PORT', script);\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                if (port[0] === 'A') port = port.substring(1);\r\n\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: { js: [], py: ['coco.get_analog_value(%1)'] },\r\n        },\r\n        coco_get_infrared_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_infrared_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getValue('PORT', script);\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                if (port[0] === 'A') port = port.substring(1);\r\n\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: { js: [], py: ['coco.get_analog_value(%1)'] },\r\n        },\r\n        coco_get_pullup: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_pullup',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var pu = Entry.hw.portData.PULLUP;\r\n                \r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n\r\n                Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.PULLUP] = {\r\n                    port: port,\r\n                    data: 2,\r\n                    time: new Date().getTime(),\r\n                };\r\n                var pullupvalue = pu ? pu[port] || 0 : 0;\r\n                return !pullupvalue;\r\n                \r\n            },\r\n            \r\n            syntax: { js: [], py: [] },\r\n        },\r\n        coco_get_button: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_button',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT', script);\r\n                var DIGITAL = Entry.hw.portData.DIGITAL;\r\n\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n\r\n                Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.DIGITAL] = {\r\n                    port: port,\r\n                    data: 2,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                var value = DIGITAL ? DIGITAL[port] || 0 : 0;\r\n                return !value;\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        coco_get_analog_mapping: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.coco_get_analog_mapping,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'coco_get_analog_mapping',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'cocoPin',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getValue('PORT', script);\r\n                var result = 0;\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n                var value2 = script.getNumberValue('VALUE2', script);\r\n                var value3 = script.getNumberValue('VALUE3', script);\r\n                var value4 = script.getNumberValue('VALUE4', script);\r\n                var value5 = script.getNumberValue('VALUE5', script);\r\n\r\n                if (port[0] === 'A') {\r\n                    port = port.substring(1);\r\n                }\r\n                result = ANALOG ? ANALOG[port] || 0 : 0;\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['coco.get_analog_mapping(%1, %2, %3, %4, %5)'],\r\n            },\r\n        },\r\n        coco_mapping1: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['255'],\r\n                    },\r\n                ],\r\n                type: 'coco_mapping1',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n            },\r\n            class: 'cocoPin',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var num = script.getNumberValue('NUM', script);\r\n\r\n                var value2 = script.getNumberValue('VALUE2', script);\r\n                var value3 = script.getNumberValue('VALUE3', script);\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n\r\n                num = Math.min(value3, num);\r\n                num = Math.max(value2, num);\r\n\r\n                return parseInt(num);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [],\r\n            },\r\n        },\r\n        coco_mapping2: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1024'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'coco_mapping2',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'cocoPin',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var num = script.getNumberValue('NUM', script);\r\n                var flag = 0;\r\n\r\n                var value2 = script.getNumberValue('VALUE2', script);\r\n                var value3 = script.getNumberValue('VALUE3', script);\r\n                var value4 = script.getNumberValue('VALUE4', script);\r\n                var value5 = script.getNumberValue('VALUE5', script);\r\n\r\n                var value4_1 = value4;\r\n                var value5_1 = value5;\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n\r\n                if (value4 > value5) {\r\n                    flag = 1;\r\n                    var swap = value4;\r\n                    value4_1 = value5;\r\n                    value5_1 = swap;\r\n                }\r\n\r\n                num -= value2;\r\n                num = num * ((value5_1 - value4_1) / (value3 - value2));\r\n\r\n                if (flag == 1) {\r\n                    num = value4 - num;\r\n                    num = Math.min(value4, num);\r\n                    num = Math.max(value5, num);\r\n                } else {\r\n                    num = num + value4;\r\n                    num = Math.min(value5, num);\r\n                    num = Math.max(value4, num);\r\n                }\r\n\r\n                return parseInt(num);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [],\r\n            },\r\n        },\r\n        coco_get_digital_ultrasonic: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.coco_get_digital_ultrasonic,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                        params: ['13'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                        params: ['12'],\r\n                    },\r\n                ],\r\n                type: 'coco_get_digital_ultrasonic',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port1 = script.getNumberValue('PORT1');\r\n                var port2 = script.getNumberValue('PORT2');\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                delete Entry.hw.sendQueue['SET'][port1];\r\n                delete Entry.hw.sendQueue['SET'][port2];\r\n\r\n                Entry.Utils.sleep(700);\r\n\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.ULTRASONIC] = {\r\n                    port: [port1, port2],\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return Entry.hw.portData.ULTRASONIC[port2] || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['coco.get_digital_ultrasonic(%1, %2)'],\r\n            },\r\n        },\r\n        coco_get_dust: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                        params: ['7'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                        params: ['0'],\r\n                    },\r\n                ],\r\n                type: 'coco_get_dust',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port1 = script.getNumberValue('PORT1');\r\n                var port2 = script.getNumberValue('PORT2');\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                delete Entry.hw.sendQueue['SET'][port1];\r\n                delete Entry.hw.sendQueue['SET'][port2];\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.DUST] = {\r\n                    port: [port1, port2],\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return Entry.hw.portData.DUST || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['coco.get_digital_ultrasonic(%1, %2)'],\r\n            },\r\n        },\r\n        coco_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: Lang.template.coco_get_digital,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoPin',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var DIGITAL = Entry.hw.portData.DIGITAL;\r\n\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n                if (Entry.hw.sendQueue.SET[port]) {\r\n                    return Entry.hw.sendQueue.SET[port].data;\r\n                } else {\r\n                    Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.DIGITAL] = {\r\n                        port: port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                }\r\n\r\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n            },\r\n            syntax: { js: [], py: ['coco.get_digital(%1)'] },\r\n        },\r\n        coco_get_digital_toggle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: Lang.template.coco_get_digital_toggle,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_digital_toggle',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var DIGITAL = Entry.hw.portData.DIGITAL;\r\n\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.DIGITAL] = {\r\n                    port: port,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n            },\r\n            syntax: { js: [], py: ['coco.get_digital_toggle(%1)'] },\r\n        },\r\n        coco_get_digital_pir: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            template: Lang.template.coco_get_digital_pir,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                    },\r\n                ],\r\n                type: 'coco_get_digital_pir',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var DIGITAL = Entry.hw.portData.DIGITAL;\r\n\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.PIR] = {\r\n                    port: port,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n            },\r\n            syntax: { js: [], py: ['coco.get_digital_pir(%1)'] },\r\n        },\r\n        coco_set_digital_toggle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_set_digital_toggle,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_toggle_en',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_toggle',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'cocoPin',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.coco.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.coco.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.coco.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: ['coco.set_digital_toggle(%1, %2)'] },\r\n        },\r\n        coco_set_led_toggle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                        params: ['5'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_toggle',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_led_toggle',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'cocoLed',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.coco.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.coco.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.coco.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: ['coco.set_digital_toggle(%1, %2)'] },\r\n        },\r\n        coco_set_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_set_digital_pwm,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_pwm',\r\n                        params: ['5'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'cocoLed',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                value = Math.round(value);\r\n                value = Math.min(value, 255);\r\n                value = Math.max(value, 0);\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.coco.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: ['coco.set_digital_pwm(%1, %2)'] },\r\n        },\r\n        coco_set_digital_rgbled: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_set_digital_rgbled,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_pwm',\r\n                        params: ['9'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_pwm',\r\n                        params: ['10'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_pwm',\r\n                        params: ['11'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_rgbled',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n                PORT3: 2,\r\n                VALUE1: 3,\r\n                VALUE2: 4,\r\n                VALUE3: 5,\r\n            },\r\n            class: 'cocoLed',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port1 = script.getNumberValue('PORT1', script);\r\n                var port2 = script.getNumberValue('PORT2', script);\r\n                var port3 = script.getNumberValue('PORT3', script);\r\n                var value1 = script.getNumberValue('VALUE1', script);\r\n                var value2 = script.getNumberValue('VALUE2', script);\r\n                var value3 = script.getNumberValue('VALUE3', script);\r\n\r\n                RGBport = port1;                \r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port1] = {\r\n                    type: Entry.coco.sensorTypes.PWM,\r\n                    data: value1,\r\n                    time: new Date().getTime(),\r\n                };\r\n                Entry.hw.sendQueue['SET'][port2] = {\r\n                    type: Entry.coco.sensorTypes.PWM,\r\n                    data: value2,\r\n                    time: new Date().getTime(),\r\n                };\r\n                Entry.hw.sendQueue['SET'][port3] = {\r\n                    type: Entry.coco.sensorTypes.PWM,\r\n                    data: value3,\r\n                    time: new Date().getTime(),\r\n                };\r\n                 return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [{}] },\r\n        },\r\n        coco_set_digital_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_set_digital_servo,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                        params: ['8'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['90'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_servo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'cocoSet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getNumberValue('VALUE');\r\n                value = Math.min(value, 180);\r\n                value = Math.max(value, 0);\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.coco.sensorTypes.SERVO,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: ['coco.set_digital_servo(%1, %2)'] },\r\n        },\r\n        coco_set_digital_servo2: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_set_digital_servo2,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                        params: ['8'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['180'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_servo2',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE1: 1,\r\n                VALUE2: 2,\r\n                STIME: 3,\r\n            },\r\n            class: 'cocoSet',\r\n            isNotFor: ['coco'],\r\n            \r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value1 = script.getNumberValue('VALUE1', script);\r\n                var value2 = script.getNumberValue('VALUE2', script);\r\n                var stime = script.getNumberValue('STIME', script);\r\n\r\n                value1 = Math.min(value1, 180);\r\n                value1 = Math.max(value1, 0);\r\n                value2 = Math.min(value2, 180);\r\n                value2 = Math.max(value2, 0);\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.SERVO2,\r\n                        data: {\r\n                            value1: value1,\r\n                            value2: value2,\r\n                            stime: stime,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, 10);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [{}] },\r\n        },\r\n        coco_set_digital_buzzer_toggle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                        params: ['6'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_toggle',\r\n                    },\r\n\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_buzzer_toggle',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'cocoBuzzer',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.coco.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.coco.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.coco.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['coco.set_digital_toggle(%1, %2, %3, %4)'],\r\n            },\r\n        },\r\n        coco_set_digital_buzzer_volume: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_pwm',\r\n                        params: ['6'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_buzzer_volume',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'cocoBuzzer',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                value = Math.round(value);\r\n                value = Math.min(value, 255);\r\n                value = Math.max(value, 0);\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.coco.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['coco.set_digital_toggle(%1, %2, %3, %4)'],\r\n            },\r\n        },\r\n        coco_set_digital_buzzer: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_set_digital_buzzer,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_digital_basic',\r\n                        params: ['6'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_tone',\r\n                    },\r\n                    {\r\n                        type: 'coco_list_digital_octave',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_digital_buzzer',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NOTE: 1,\r\n                OCTAVE: 2,\r\n                DURATION: 3,\r\n            },\r\n            class: 'cocoBuzzer',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var duration = script.getNumberValue('DURATION');\r\n                var octave = script.getNumberValue('OCTAVE') - 1;\r\n                var value = 0;\r\n\r\n                if (!script.isStart) {\r\n                    var note = script.getValue('NOTE');\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.coco.toneTable[note];\r\n                    }\r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    } else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n                    if (duration < 0) {\r\n                        duration = 0;\r\n                    }\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    if (duration === 0) {\r\n                        Entry.hw.sendQueue['SET'][port] = {\r\n                            type: Entry.coco.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    } else if (octave > 8) {\r\n                        octave = 8;\r\n                    }\r\n                    if (note != 0) {\r\n                        value = Entry.coco.toneMap[note][octave];\r\n                    }\r\n\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.TONE,\r\n                        data: {\r\n                            value: value,\r\n                            duration: duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['coco.set_digital_toggle(%1, %2, %3, %4)'],\r\n            },\r\n        },\r\n        coco_lcd_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_lcd_list_init',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['16'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['2'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_lcd_init',\r\n            },\r\n            paramsKeyMap: {\r\n                LIST: 0,\r\n                COL: 1,\r\n                LINE: 2,\r\n            },\r\n            class: 'cocoModule',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var list = script.getNumberValue('LIST');\r\n                var col = script.getNumberValue('COL');\r\n                var line = script.getValue('LINE');\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 0.1 * 1000;\r\n\r\n                    Entry.hw.sendQueue['SET'][1] = {\r\n                        type: Entry.coco.sensorTypes.LCDINIT,\r\n                        data: {\r\n                            list: list,\r\n                            col: col,\r\n                            line: line,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: ['coco.module_digital_lcd(%1, %2)'] },\r\n        },\r\n        coco_module_digital_lcd: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_get_lcd_col',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'coco_get_lcd_row',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['Hello, coco'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_module_digital_lcd',\r\n            },\r\n            paramsKeyMap: {\r\n                COL: 0,\r\n                ROW: 1,\r\n                STRING: 2,\r\n            },\r\n            class: 'cocoModule',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var row = script.getNumberValue('ROW');\r\n                var col = script.getNumberValue('COL');\r\n                var text = script.getValue('STRING');\r\n                text += ' ';\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 100;\r\n\r\n                    Entry.hw.sendQueue['SET'][1] = {\r\n                        type: Entry.coco.sensorTypes.LCD,\r\n                        data: {\r\n                            line: row,\r\n                            column: col,\r\n                            text: text,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: ['coco.module_digital_lcd(%1, %2)'] },\r\n        },\r\n        coco_lcd_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'coco_lcd_clear',\r\n            },\r\n            class: 'cocoModule',\r\n            isNotFor: ['coco'],\r\n            func(sprite, script) {\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][1] = {\r\n                        type: Entry.coco.sensorTypes.LCDCLEAR,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_get_dht: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['온도(°C)', '0'],\r\n                        ['습도(%)', '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['4'],\r\n                    },\r\n\r\n                ],\r\n                type: 'coco_get_dht',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                DHT_SELECT: 1,\r\n            },\r\n            class: 'cocoGet',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = script.getNumberValue('PORT');\r\n                var type = script.getNumberValue('DHT_SELECT');\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                delete Entry.hw.sendQueue['SET'][port];\r\n\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n\r\n                if (type == 0) {\r\n                    Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.DHTTEMP] = {\r\n                        port: port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return Entry.hw.portData.DHTTEMP || 0;\r\n                } else if (type == 1) {\r\n                    Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.DHTHUMI] = {\r\n                        port: port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return Entry.hw.portData.DHTHUMI || 0;\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_set_mp3_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['10'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['11'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_mp3_init',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'mp3',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                tx = script.getNumberValue('PORT1');\r\n                var rx = script.getNumberValue('PORT2');\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][tx] = {\r\n                        type: Entry.coco.sensorTypes.MP3INIT,\r\n                        data: {\r\n                            tx: tx,\r\n                            rx: rx,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_set_mp3_play: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_mp3_play',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n            },\r\n            class: 'mp3',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var num = script.getNumberValue('NUM');\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                script.isStart = true;\r\n                script.timeFlag = 1;\r\n                var fps = Entry.FPS || 60;\r\n                var timeValue = (60 / fps) * 50;\r\n\r\n                Entry.hw.sendQueue['SET'][tx] = {\r\n                    type: Entry.coco.sensorTypes.MP3PLAY1,\r\n                    data: {\r\n                        tx: tx,\r\n                        num: num,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_set_mp3_play2: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_mp3_play2',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n                TIME: 1,\r\n            },\r\n            class: 'mp3',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var num = script.getNumberValue('NUM');\r\n                var time_value = script.getNumberValue('TIME');\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    time_value = (60 / fps) * time_value * 1000;\r\n\r\n                    Entry.hw.sendQueue['SET'][tx] = {\r\n                        type: Entry.coco.sensorTypes.MP3PLAY1,\r\n                        data: {\r\n                            tx: tx,\r\n                            num: num,\r\n                            //time_value: time_value,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, time_value);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n\r\n                    Entry.hw.sendQueue['SET'][tx] = {\r\n                        type: Entry.coco.sensorTypes.MP3PLAY1,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_set_mp3_vol: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['15'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_set_mp3_vol',\r\n            },\r\n            paramsKeyMap: {\r\n                VOL: 0,\r\n            },\r\n            class: 'mp3',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var vol = script.getNumberValue('VOL');\r\n\r\n                vol = Math.round(vol);\r\n                vol = Math.min(vol, 30);\r\n                vol = Math.max(vol, 0);\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][tx] = {\r\n                        type: Entry.coco.sensorTypes.MP3VOL,\r\n                        data: {\r\n                            tx: tx,\r\n                            vol: vol,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_load_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['6'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['7'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_load_init',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'load',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port1 = script.getNumberValue('PORT1', script);\r\n                var port2 = script.getNumberValue('PORT2', script);\r\n\r\n                dout = port1;\r\n                sck = port2;\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][sck] = {\r\n                        type: Entry.coco.sensorTypes.LOADINIT,\r\n                        data: {\r\n                            port1: port1,\r\n                            port2: port2,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_load_scale: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['-20000'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_load_scale',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n            },\r\n            class: 'load',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var num = script.getNumberValue('NUM', script);\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][sck] = {\r\n                        type: Entry.coco.sensorTypes.LOADSCALE,\r\n                        data: {\r\n                            num: num,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_load_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                type: 'coco_load_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'load',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                delete Entry.hw.sendQueue['SET'][sck];\r\n\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.LOADVALUE] = {\r\n                    port: sck,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return Entry.hw.portData.LOADVALUE || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        coco_list_joy: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['첫번째', '1'],\r\n                        ['두번째', '2'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('NUM');\r\n            },\r\n        },\r\n        coco_joy_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_joy',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_analog_basic',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['8'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_joy_init',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n                PORT1: 1,\r\n                PORT2: 2,\r\n                PORT3: 3,\r\n            },\r\n            class: 'joy',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var num = script.getNumberValue('NUM', script);\r\n                var port1 = script.getNumberValue('PORT1', script);\r\n                var port2 = script.getNumberValue('PORT2', script);\r\n                var port3 = script.getNumberValue('PORT3', script);\r\n\r\n                if (num == 1) {\r\n                    joyx = port1;\r\n                    joyy = port2;\r\n                    joyz = port3;\r\n                } else if (num == 2) {\r\n                    joyx2 = port1;\r\n                    joyy2 = port2;\r\n                    joyz2 = port3;\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    if (num == 1) {\r\n                        Entry.hw.sendQueue['SET'][joyx] = {\r\n                            type: Entry.coco.sensorTypes.JOYINIT,\r\n                            data: {\r\n                                num: num,\r\n                                port1: port1,\r\n                                port2: port2,\r\n                                port3: port3,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    } else if (num == 2) {\r\n                        Entry.hw.sendQueue['SET'][joyx2] = {\r\n                            type: Entry.coco.sensorTypes.JOYINIT,\r\n                            data: {\r\n                                num: num,\r\n                                port1: port1,\r\n                                port2: port2,\r\n                                port3: port3,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                    }\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_get_joy_x: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_joy',\r\n                        params: ['1'],\r\n                    },\r\n                ],\r\n                type: 'coco_get_joy_x',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n            },\r\n            class: 'joy',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n                var num = script.getNumberValue('NUM', script);\r\n                if (num == 1) {\r\n                    return ANALOG ? ANALOG[joyx] || 0 : 0;\r\n                } else if (num == 2) {\r\n                    return ANALOG ? ANALOG[joyx2] || 0 : 0;\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_get_joy_y: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_joy',\r\n                        params: ['1'],\r\n                    },\r\n                ],\r\n                type: 'coco_get_joy_y',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n            },\r\n            class: 'joy',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n                var num = script.getNumberValue('NUM', script);\r\n                if (num == 1) {\r\n                    return ANALOG ? ANALOG[joyy] || 0 : 0;\r\n                } else if (num == 2) {\r\n                    return ANALOG ? ANALOG[joyy2] || 0 : 0;\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n\r\n        coco_get_joy_z: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_joy',\r\n                        params: ['1'],\r\n                    },\r\n                ],\r\n                type: 'coco_get_joy_z',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n            },\r\n            class: 'joy',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var DIGITAL = Entry.hw.portData.DIGITAL;\r\n                var num = script.getNumberValue('NUM', script);\r\n\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n\r\n                if (num == 1) {\r\n                    Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.DIGITAL] = {\r\n                        port: joyz,\r\n                        data: 2,\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    var value = DIGITAL ? DIGITAL[joyz] || 0 : 0;\r\n                    return !value;\r\n                } else if (num == 2) {\r\n                    Entry.hw.sendQueue['GET'][Entry.coco.sensorTypes.DIGITAL] = {\r\n                        port: joyz2,\r\n                        data: 2,\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    var value = DIGITAL ? DIGITAL[joyz2] || 0 : 0;\r\n                    return !value;\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        coco_list_joy_direction: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['가운데', '0'],\r\n                        ['위', '1'],\r\n                        ['아래', '4'],\r\n                        ['왼쪽', '2'],\r\n                        ['오른쪽', '3'],\r\n                        ['왼쪽위', '5'],\r\n                        ['왼쪽아래', '6'],\r\n                        ['오른쪽위', '7'],\r\n                        ['오른쪽아래', '8'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                DIR: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('DIR');\r\n            },\r\n        },\r\n        coco_get_joy_move: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'coco_list_joy',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'coco_list_joy_direction',\r\n                        params: ['0'],\r\n                    },\r\n                ],\r\n                type: 'coco_get_joy_move',\r\n            },\r\n            paramsKeyMap: {\r\n                NUM: 0,\r\n                DIR: 1,\r\n            },\r\n            class: 'joy',\r\n            isNotFor: ['coco'],\r\n            func(sprite, script) {\r\n                var direction = script.getNumberValue('DIR');\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                num = script.getNumberValue('NUM', script);\r\n\r\n                const getValue = function(w) {\r\n                    return ANALOG[w] <= 100 ? 0 : ANALOG[w] >= 930 ? 2 : 1;\r\n                };\r\n\r\n                var xpin;\r\n                var ypin;\r\n                if (num == 1) {\r\n                    xpin = joyx;\r\n                    ypin = joyy;\r\n                } else if (num == 2) {\r\n                    xpin = joyx2;\r\n                    ypin = joyy2;\r\n                }\r\n                if (\r\n                    direction == Entry.coco.direction.CENTER &&\r\n                    getValue(xpin) == 1 &&\r\n                    getValue(ypin) == 1\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.coco.direction.DOWN &&\r\n                    getValue(xpin) == 1 &&\r\n                    getValue(ypin) == 2\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.coco.direction.LEFT &&\r\n                    getValue(xpin) == 0 &&\r\n                    getValue(ypin) == 1\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.coco.direction.LEFT_DOWN &&\r\n                    getValue(xpin) == 0 &&\r\n                    getValue(ypin) == 2\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.coco.direction.LEFT_UP &&\r\n                    getValue(xpin) == 0 &&\r\n                    getValue(ypin) == 0\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.coco.direction.RIGHT &&\r\n                    getValue(xpin) == 2 &&\r\n                    getValue(ypin) == 1\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.coco.direction.RIGHT_DOWN &&\r\n                    getValue(xpin) == 2 &&\r\n                    getValue(ypin) == 2\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.coco.direction.RIGHT_UP &&\r\n                    getValue(xpin) == 2 &&\r\n                    getValue(ypin) == 0\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.coco.direction.UP &&\r\n                    getValue(xpin) == 1 &&\r\n                    getValue(ypin) == 0\r\n                ) {\r\n                    return 1;\r\n                }\r\n\r\n                return 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [{}],\r\n            },\r\n        },\r\n        \r\n        coco_module_digital_oled: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.coco_module_digital_oled,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['20'],\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['My Entry!!'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'coco_module_digital_oled',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE0: 0,\r\n                VALUE1: 1,\r\n                STRING: 2,\r\n            },\r\n            class: 'cocoModule',\r\n            isNotFor: ['coco'],\r\n            func: function(sprite, script) {\r\n                var port = 0;\r\n                var coodinate_x = script.getNumberValue('VALUE0');\r\n                var coodinate_y = script.getNumberValue('VALUE1');\r\n                var string = script.getValue('STRING');\r\n                var text = [];\r\n\r\n                if (!script.isStart) {\r\n                    if (typeof string === 'string') {\r\n                        for (var i = 0; i < string.length; i++) {\r\n                            text[i] = string.charCodeAt(i);\r\n                        }\r\n                    } else if (typeof string === 'number') {\r\n                        text[0] = 1;\r\n                        text[1] = string / 1;\r\n                    } else {\r\n                        text[0] = string;\r\n                    }\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var fps = Entry.FPS || 60;\r\n                    var timeValue = (60 / fps) * 50;\r\n\r\n                    coodinate_x = Math.min(coodinate_x, 127);\r\n                    coodinate_x = Math.max(coodinate_x, 0);\r\n                    coodinate_y = Math.min(coodinate_y, 63);\r\n                    coodinate_y = Math.max(coodinate_y, 0);\r\n\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.coco.sensorTypes.OLED,\r\n                        data: {\r\n                            value0: coodinate_x,\r\n                            value1: coodinate_y,\r\n                            text0: text[0],\r\n                            text1: text[1],\r\n                            text2: text[2],\r\n                            text3: text[3],\r\n                            text4: text[4],\r\n                            text5: text[5],\r\n                            text6: text[6],\r\n                            text7: text[7],\r\n                            text8: text[8],\r\n                            text9: text[9],\r\n                            text10: text[10],\r\n                            text11: text[11],\r\n                            text12: text[12],\r\n                            text13: text[13],\r\n                            text14: text[14],\r\n                            text15: text[15],\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: ['coco.Module_digital_oled(%1, %2, %3)'] },\r\n        },\r\n               \r\n    };\r\n};\r\n\r\nmodule.exports = Entry.coco;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_coconut.js",
    "content": "'use strict';\n\nEntry.coconut = {\n    PORT_MAP: {\n        leftFloorValue: 0,\n        rightFloorValue: 0,\n        BothFloorDetection: 0,\n        leftProximityValue: 0,\n        rightProximityValue: 0,\n        BothProximityDetection: 0,\n        obstacleDetection: 0,\n        light: 0,\n        temp: 0,\n        extA2: 0,\n        extA3: 0,\n    },\n    setZero: function() {\n        var sq = Entry.hw.sendQueue;\n        sq.msgValue = [0xff, 0x55, 0x02, 0x00, 0x04];\n        Entry.hw.update();\n    },\n    lineTracerModeId: 0,\n    lineTracerStateId: -1,\n    tempo: 60,\n    timeouts: [],\n    removeTimeout: function(a) {\n        clearTimeout(a);\n        var b = this.timeouts;\n        a = b.indexOf(a);\n        0 <= a && b.splice(a, 1);\n    },\n    removeAllTimeouts: function() {\n        var a = this.timeouts,\n            b;\n        for (b in a) {\n            clearTimeout(a[b]);\n        }\n        this.timeouts = [];\n    },\n    setLineTracerMode: function(a, b) {\n        this.lineTracerModeId = (this.lineTracerModeId + 1) & 255;\n        a.lineTracerMode = b;\n        a.lineTracerModeId = this.lineTracerModeId;\n    },\n    //START : 2017.02.22 : LTW\n    msgValue: 0,\n    insertQueue: function(msg, sq) {\n        sq.msgValue = msg;\n    },\n    clearQueue: function(sq) {\n        sq.msgValue = '';\n    },\n\n    move: function(direction) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n        // seq, direction, speed, degree, time\n        return this.runPackage(this.devices['Motor'], 0, direction, this.speed);\n    },\n    /* Scratch coconut Extension import */\n    speed: 60,\n    directions: { Both: 0, Left: 1, Right: 2, Forward: 3, Backward: 4 },\n    devices: {\n        LightSensor: 14,\n        Accelerometer: 18,\n        Temperature: 21,\n        Buzzer: 3,\n        IRdistance: 5,\n        Linetracer: 7,\n        IR: 9,\n        RGBled: 25,\n        Motor: 26,\n        LedMatrix: 27,\n        Digital: 30,\n        Analog: 31,\n        PWM: 32,\n        External: 40,\n        Speaker: 41,\n        ExtIR: 42,\n        ServoMotor: 43,\n        ExLed: 44,\n        ExtCds: 45,\n    },\n    sharps: { '-': 0, '#': 1, b: 2 },\n    beats: {\n        Half: 500,\n        Quater: 250,\n        Eighth: 125,\n        Sixteenth: 63,\n        'Thirty-second': 32,\n        Whole: 1000,\n        'Dotted half': 750,\n        'Dotted quarter': 375,\n        'Dotted eighth': 188,\n        'Dotted sixteenth': 95,\n        'Dotted thirty-second': 48,\n        Double: 2000,\n        Zero: 0,\n    },\n    melodys: {\n        'Twinkle Twinkle little star': 1,\n        'Three bears': 2,\n        \"Mozart's Lullaby\": 3,\n        'Do-Re-Mi': 4,\n        Butterfly: 5,\n    },\n    colors: {\n        Black: 0,\n        White: 1,\n        Red: 2,\n        Green: 3,\n        Blue: 4,\n        Yellow: 5,\n        Cyan: 6,\n        Magenta: 7,\n    },\n    // IR distance 감지조건\n    detectConds: { Yes: 1, No: 0 },\n    /// 도트매트릭스 문자\n    // 소문자\n    sLetters: {\n        a: 0,\n        b: 1,\n        c: 2,\n        d: 3,\n        e: 4,\n        f: 5,\n        g: 6,\n        h: 7,\n        i: 8,\n        j: 9,\n        k: 10,\n        l: 11,\n        m: 12,\n        n: 13,\n        o: 14,\n        p: 15,\n        q: 16,\n        r: 17,\n        s: 18,\n        t: 19,\n        u: 20,\n        v: 21,\n        w: 22,\n        x: 23,\n        y: 24,\n        z: 25,\n    },\n    // 대문자\n    cLetters: {\n        A: 0,\n        B: 1,\n        C: 2,\n        D: 3,\n        E: 4,\n        F: 5,\n        G: 6,\n        H: 7,\n        I: 8,\n        J: 9,\n        K: 10,\n        L: 11,\n        M: 12,\n        N: 13,\n        O: 14,\n        P: 15,\n        Q: 16,\n        R: 17,\n        S: 18,\n        T: 19,\n        U: 20,\n        V: 21,\n        W: 22,\n        X: 23,\n        Y: 24,\n        Z: 25,\n    },\n    // 한글\n    kLetters: {\n        ga: 0,\n        na: 1,\n        da: 2,\n        la: 3,\n        ma: 4,\n        ba: 5,\n        sa: 6,\n        aa: 7,\n        ja: 8,\n        cha: 9,\n        ka: 10,\n        ta: 11,\n        pa: 12,\n        ha: 13,\n    },\n    onOffs: { On: 1, Off: 0 },\n    axiss: { 'X-Axis': 1, 'Y-Axis': 2, 'Z-Axis': 3 },\n    // external\n    pins: { D4: 4, D10: 10, D11: 11, D12: 12, A2: 16, A3: 17 },\n    outputValues: { HIGH: 1, LOW: 0 },\n\n    /**\n     * @brief   모터 움직이기 - 전진/후진/좌회전/우회전\n     * @details 기본 속도 적용, 시간제한 없음\n     * @date    2016.04.27\n     *\n     * @param   direction     방향 (1: Left, 2: Right, 3: Forward, 4: Backward), default: Go\n     */\n    moveMotor: function(direction) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n        // seq, direction, speed, degree, time\n        return this.runPackage(this.devices['Motor'], 0, direction, this.speed);\n    },\n\n    moveMotorSpeed: function(direction, speed) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n        // seq, direction, speed, degree, time\n        return this.runPackage(this.devices['Motor'], 0, direction, this.speed);\n    },\n\n    /**\n     * @brief   모터 움직이기 - 좌회전/우회전\n     * @details 기본 속도 적용, 시간제한 없음\n     *\n     * @param   direction     방향 (1: Left, 2: Right, 3: Forward, 4: Backward), default: Go\n     */\n    turnMotor: function(direction) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n        // seq, direction, speed, degree, time\n        return this.runPackage(this.devices['Motor'], 0, direction, this.speed);\n    },\n\n    /**\n     * @brief   모터 정지\n     * @date    2016.06.23\n     */\n    stopMotor: function() {\n        return this.runPackage(this.devices['Motor'], 1);\n    },\n\n    /**\n     * @brief   좌측/우측으로 각도 만큼 돌기\n     * @details 기본속도 적용, 정해진 각도만큼 회전후 정지\n     * @todo    degree<0 반대방향 적용 여부 결정\n     * @date    2016.04.27\n     * @param   direction   방향 (1: Left, 2: Right), default: Left\n     * @param   degree      회전각도 (0~360도), default: 90도\n     */\n    moveTurnAngle: function(direction, degree) {\n        var sec = 0; // 제한없음\n\n        if (typeof direction == 'string') direction = this.directions[direction];\n\n        // 각도가 360 이상일 경우 360으로 고정\n        if (degree > 360 || degree < -360) degree = 360;\n        // seq, direction, speed, degree, time\n        //motorControl(2, direction, speed, degree, sec);\n    },\n\n    /**\n     * @brief 움직이기 - 전/후진, 좌/우회전 - 시간\n     * @details 기본속도 적용\n     * @date2016.04.27\n     *\n     * @param direction 방향 (1: Left, 2: Right, 3: Forward, 4: Backward), default: Go\n     * @param sec 시간 (초), default: 1초\n     */\n    moveGoTime: function(direction, sec) {\n        // 시간이 0보다 작으면 양수로 변환\n        if (sec < 0) sec = -sec;\n        sec = 1000 * sec; // ms 변환\n\n        if (typeof direction == 'string') direction = this.directions[direction];\n\n        // seq, direction, speed, degree, time\n        return this.runPackage(\n            this.devices['Motor'],\n            3,\n            direction,\n            this.speed,\n            this.short2array(sec)\n        );\n    },\n\n    /**\n     * @brief 좌/우회전 - 시간\n     * @details 기본속도 적용\n     *\n     * @param direction 방향 (1: Left, 2: Right), default: Go\n     * @param sec 시간 (초), default: 1초\n     */\n    turnMotorTime: function(direction, sec) {\n        // 시간이 0보다 작으면 양수로 변환\n        if (sec < 0) sec = -sec;\n        sec = 1000 * sec; // ms 변환\n\n        if (typeof direction == 'string') direction = this.directions[direction];\n\n        return this.runPackage(\n            this.devices['Motor'],\n            3,\n            direction,\n            this.speed,\n            this.short2array(sec)\n        );\n    },\n\n    /**\n     * @brief 좌/우측 무한 회전하는 동안 RGB LED 켜기\n     *\n     * @paramdirection 방향 (1: Left, 2: Right), default: Left\n     * @paramcolor RGB LED 색상 (1: Red, 2: Green, 3: Blue), default: Red\n     */\n    moveMotorColor: function(direction, color) {\n        var deviceID = this.devices['Motor'];\n\n        if (typeof direction == 'string') direction = this.directions[direction];\n        if (typeof color == 'string') color = this.colors[color];\n\n        // deviceid, seq, direction, speed, color\n        return this.runPackage(deviceID, 5, direction, this.speed, color);\n    },\n\n    /**\n     * @brief 좌/우측 각도에 따라 회전하는 동안 RGB LED 켜기\n     * @todo각도 설정 불가, 추후 삭제\n     *\n     * @param direction 방향 (1: Left, 2: Right), default: Left\n     * @param angle 회전각도 (0~360도)\n     * @param color RGB LED 색상 (1: Red, 2: Green, 3: Blue), default: Red\n     */\n    moveMotorAngleColor: function(direction, angle, color) {\n        var deviceID = this.devices['Motor'];\n\n        if (typeof direction == 'string') direction = this.directions[direction];\n        if (typeof color == 'string') color = this.colors[color];\n        if (typeof angle != 'number') angle = 90;\n\n        // deviceid, seq, direction, speed, angle, time, color\n        return this.runPackage(\n            deviceID,\n            6,\n            direction,\n            this.short2array(0),\n            this.short2array(angle),\n            this.short2array(0),\n            color\n        );\n    },\n\n    /**\n     * @brief control external motor\n     *\n     * @param direction 방향 (1: Left, 2: Right, 3: Forward, 4: Backward), default: Go\n     * @param speed 속도 (0-255)\n     */\n    moveExtMotor: function(direction, speed) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n\n        // deviceid, seq, direction, speed\n        return this.runPackage(this.devices['Motor'], 7, direction, speed);\n    },\n\n    /**\n     * @brief RGB LED 켜기 - 방향, 색상 선택\n     * @details 시간제한 없음, seq=0\n     *\n     * @date2016.04.28\n     * @param direction 방향 (0: both, 1: Left, 2: Right), default: Left\n     * @param color 색상 (1: Red, 2: Green, 3: Blue), default: Red\n     */\n    rgbOn: function(direction, color) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n        if (typeof color == 'string') color = this.colors[color];\n\n        return this.runPackage(this.devices['RGBled'], 0, direction, color);\n    },\n\n    /**\n     * @brief RGB LED 끄기 - 방향\n     * @details 시간제한 없음, seq=1\n     *\n     * @param direction방향 (0: all, 1: Left, 2: Right), default: Left\n     */\n    rgbOff: function(direction) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n\n        return this.runPackage(this.devices['RGBled'], 1, direction, 0);\n    },\n\n    /**\n     * @brief RGB LED 끄기 - 방향, 색상\n     * @details seq=2\n     * @date2016.05.30\n     *\n     * @param direction 방향 (0: all, 1: Left, 2: Right), default: Left\n     * @param color 색상 (1: Red, 2: Green, 3: Blue), default: Red\n     */\n    rgbOffColor: function(direction, color) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n        if (typeof color == 'string') color = this.colors[color];\n\n        return this.runPackage(this.devices['RGBled'], 1, direction, color);\n    },\n\n    /**\n     * @brief RGB LED 켜기 - 방향, 색상, 시간\n     * @details seq=2\n     * @date2016.04.28\n     *\n     * @param direction 방향 (0: all, 1: Left, 2: Right), default: Left\n     * @param color 색상 (1: Red, 2: Green, 3: Blue), default: Red\n     * @param sec 시간, 초\n     */\n    ledOnTime: function(direction, color, sec) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n        if (typeof color == 'string') color = this.colors[color];\n\n        // 시간이 정수가 아니거나 0보다 작을 경우 0으로 변경\n        if (typeof sec != 'number') sec = 0;\n        else if (sec < 0) sec = 0;\n        else sec *= 1000; // ms 변환\n\n        return this.runPackage(this.devices['RGBled'], 3, direction, color, this.short2array(sec));\n    },\n\n    /// buzzer\n    /**\n     * @brief 스피커 켜기\n     * @details 버저음을 기본 주파수 c4 로 짧게 소리낸다.\n     */\n    beep: function() {\n        return this.buzzerControl(0, 262, 50);\n        //\n    },\n\n    /**\n     * @brief 버저음을 seconds 동안 소리내기 (기본주파수)\n     * @details 기본주파수 : c4 (도)\n     * @date2015.04.26\n     * @param sec 연주시간 (seconds, 초)\n     */\n    playBuzzerTime: function(sec) {\n        // 시간이 숫자가 아니거나 0보다 작을 경우 0.5초로 고정\n        if (typeof sec != 'number') sec = 0.5;\n        if (sec < 0) sec = 0.5;\n\n        sec = 1000 * sec; // milliseconds 변환\n\n        return this.buzzerControl(0, 262, sec);\n    },\n\n    /**\n     * @brief 버저음 freq hz를 seconds 초 동안 소리내기\n     * @date2016.04.26\n     * @param freq주파수 hz\n     * @param sec 연주시간 (seconds, 초)\n     */\n    playBuzzerFreq: function(freq, sec) {\n        // 시간이 숫자가 아니거나 0보다 작을 경우 0.5초로 고정\n        if (typeof sec != 'number') sec = 0.5;\n        if (sec < 0) sec = 0.5;\n\n        sec = 1000 * sec; // milliseconds 변환\n\n        // 주파수가 숫자가 아니거나 0보다 작을 경우 300hz로 고정\n        if (typeof freq != 'number') freq = 300;\n        if (freq < 0) freq = 300;\n\n        return this.buzzerControl(0, freq, sec);\n    },\n\n    /**\n     * @brief 버저 끄기\n     * @details tone = 0 일 경우 버저 끄기 실행\n     */\n    buzzerOff: function() {\n        // tone=0, beat=0\n        return this.buzzerControl(0, 0, 0);\n    },\n\n    /**\n     * @brief 버저 tone 음을 beat 박자로 실행\n     * @param note음계\n     * @param octave옥타브\n     * @param beat박자\n     */\n    playBuzzerNote: function(note, octave, beat) {\n        // note 에서 `NOTE_` 다음 문자열만 추출\n        //var arrNote = note.split(\"NOTE_\",2);\n        note = this.getNote(note);\n\n        if (typeof beat == 'string') beat = this.beats[beat];\n\n        // note ascii 코드로 변환하여 전송\n        return this.runPackage(\n            this.devices['Buzzer'],\n            2,\n            note.charCodeAt(0),\n            octave,\n            this.short2array(beat)\n        );\n    },\n\n    /**\n     * @brief 버저 tone 음을 beat 박자로 실행\n     * @param note음계\n     * @param octave옥타브\n     * @param sharp 올림표/내림표 (-:0, #:1, b:2)\n     * @param beat박자\n     */\n    playNote: function(note, octave, sharp, beat) {\n        // note 에서 `NOTE_` 다음 문자열만 추출\n        note = this.getNote(note);\n        if (typeof beat == 'string') beat = this.beats[beat];\n        return this.runPackage(\n            this.devices['Buzzer'],\n            4,\n            note.charCodeAt(0),\n            octave,\n            sharp.charCodeAt(0),\n            this.short2array(beat)\n        );\n    },\n\n    /**\n     * @brief 음계 문자 추출\n     * @param note음계 (eg. NOTE_C)\n     */\n    getNote: function(note) {\n        // note 에서 `NOTE_` 다음 문자열만 추출\n        var arrNote = note.split('_');\n\n        return arrNote[1];\n    },\n\n    /**\n     * @brief 박자 쉬기\n     * @param beat박자\n     */\n    restBeat: function(beat) {\n        if (typeof beat == 'string') {\n            // Half_rest 에서 `_` 앞 문자열만 추출하여 박자 설정\n            var arrBeat = beat.split('_', 1);\n            beat = this.beats[arrBeat];\n        }\n\n        return this.buzzerControl(1, 0, beat);\n    },\n\n    /**\n     * @brief 버저 tone+octave 음을 beat 박자로 실행시 LED 켜기\n     * @paramnote\n     * @paramoctave\n     * @parambeat\n     * @paramcolor 색상 (1: Red, 2: Green, 3: Blue), default: Red\n     */\n    playBuzzerColor: function(note, octave, beat, color) {\n        // note 에서 `NOTE_` 다음 문자열만 추출\n        //var arrNote = note.split(\"NOTE_\",2);\n        note = this.getNote(note);\n\n        if (typeof beat == 'string') beat = this.beats[beat];\n        if (typeof color == 'string') color = this.colors[color];\n\n        return this.runPackage(\n            this.devices['Buzzer'],\n            3,\n            note.charCodeAt(0),\n            octave,\n            this.short2array(beat),\n            color\n        );\n    },\n    /**\n     * @brief 버저 tone+octave 음을 beat 박자로 실행시 LED 켜기\n     * @param note\n     * @param octave\n     * @param sharp 올림표/내림표 (-:0, #:1, b:2)\n     * @param beat\n     * @param direction Left:1, Right:2, All: 0\n     * @param color 1: Red, 2: Green, 3: Blue, default: Red\n     */\n    playNoteColor: function(note, octave, sharp, beat, direction, color) {\n        // note 에서 `NOTE_` 다음 문자열만 추출\n        note = this.getNote(note);\n\n        if (typeof beat == 'string') beat = this.beats[beat];\n        if (typeof direction == 'string') direction = this.directions[direction];\n        if (typeof color == 'string') color = this.colors[color];\n\n        return this.runPackage(\n            this.devices['Buzzer'],\n            5,\n            note.charCodeAt(0),\n            octave,\n            sharp.charCodeAt(0),\n            this.short2array(beat),\n            direction,\n            color\n        );\n    },\n\n    /**\n     * @brief 멜로디 연주하기\n     * @param melody멜로디 (1:작은별, 2:곰세마리, 3:자장가, 4:도레미송, 5:나비야)\n     */\n    playMelody: function(melody) {\n        if (typeof melody == 'string') melody = this.melodys[melody];\n        return this.runPackage(this.devices['Buzzer'], 6, melody);\n    },\n\n    /**\n     * @brief 버저 제어\n     * @details\n     * @param seq 순번 (0: 연주, 1: 박자쉬기, 2: 음표 연주)\n     * @param tone주파수\n     * @param beat박자\n     * @param note음표\n     */\n    buzzerControl: function(seq, tone, beat) {\n        var deviceID = this.devices['Buzzer'];\n\n        if (typeof beat == 'string') beat = this.beats[beat];\n\n        return this.runPackage(deviceID, seq, this.short2array(tone), this.short2array(beat));\n    },\n\n    // led blink\n    runBlink: function() {\n        var pin = 13;\n        return this.runPackage(30, pin);\n    },\n\n    /**\n     * @brief 선 따라가기, level=5 (default)\n     */\n    followLine: function() {\n        return this.runPackage(this.devices['Linetracer'], 3, this.speed);\n    },\n\n    /**\n     * @brief 선 따라가기, 속도 설정\n     */\n    followLineLevel: function(level, speed) {\n        if (typeof speed != 'number') speed = 70;\n        return this.runPackage(this.devices['Linetracer'], 3, level, speed);\n    },\n\n    /**\n     * @brief 장애물 감지 기준 변경\n     * @date2016.05.24\n     *\n     * @param direction 방향, default Left (1: Left, 2: Right)\n     * @param standard감지 기준\n     */\n    setStandard: function(direction, standard) {\n        if (typeof direction == 'string') direction = this.directions[direction];\n        return this.runPackage(this.devices['IRdistance'], 0, direction, standard);\n    },\n\n    /**\n     * @brief 어보이드 모드\n     */\n    avoidMode: function() {\n        return this.runPackage(this.devices['IRdistance'], 3);\n    },\n\n    /// LED Matrix\n    /**\n     * @brief Led Matrix 행열 켜기\n     *\n     * @param row 행 번호, 0-8 (Both=0)\n     * @param col 열 번호, 0-8 (Both=0)\n     * @param onOff on=1, off=0\n     */\n    ledMatrixOn: function(onOff, row, col) {\n        if (typeof onOff == 'string') onOff = this.onOffs[onOff];\n        if (typeof row == 'string' && row == 'Both') row = 0;\n        if (typeof col == 'string' && col == 'Both') col = 0;\n\n        return this.runPackage(this.devices['LedMatrix'], 0, row, col, onOff);\n    },\n\n    /**\n     * @brief Led Matrix 행열 끄기\n     *\n     * @param row 행 번호\n     * @param col 열 번호\n     */\n    ledMatrixOff: function(row, col) {\n        return this.runPackage(this.devices['LedMatrix'], 0, row, col, 0);\n    },\n\n    /**\n     * @brief Led Matrix 모두 끄기\n     */\n    ledMatrixClear: function() {\n        return this.runPackage(this.devices['LedMatrix'], 5); // seq=5\n    },\n\n    /**\n     * @brief Led Matrix 모두 켜기\n     */\n    ledMatrixOnAll: function() {\n        return this.runPackage(this.devices['LedMatrix'], 6); // seq=6\n    },\n\n    /**\n     * @brief Led Matrix 숫자 표시\n     *\n     * @param code 숫자 (0-9)\n     */\n    showLedMatrix: function(code) {\n        return this.runPackage(this.devices['LedMatrix'], 1, code);\n    },\n\n    /**\n     * @brief Led Matrix 영문 소문자 표시\n     *\n     * @param code 소문자 (a-z)\n     */\n    showLedMatrixSmall: function(code) {\n        if (typeof code == 'string') code = this.sLetters[code];\n        return this.runPackage(this.devices['LedMatrix'], 2, code);\n    },\n\n    /**\n     * @brief Led Matrix 영문 대문자 표시\n     *\n     * @param code 대문자(A-Z)\n     */\n    showLedMatrixLarge: function(code) {\n        if (typeof code == 'string') code = this.cLetters[code];\n        return this.runPackage(this.devices['LedMatrix'], 3, code);\n    },\n\n    /**\n     * @brief Led Matrix 한글 표시\n     *\n     * @param code 한글 (가-하)\n     */\n    showLedMatrixKorean: function(code) {\n        if (typeof code == 'string') code = this.kLetters[code];\n        return this.runPackage(this.devices['LedMatrix'], 4, code);\n    },\n\n    /// IR\n    /**\n     * @brief IR 메시지 보내기\n     *\n     * @param message 전송할 문자열\n     */\n    // sendMessage: function(message) {\n    //     return this.runPackage(this.devices['IR'], this.string2array(message));\n    // },\n\n    /**\n     * @brief 외부 LED on/off\n     *\n     * @param pin 디지털 핀번호\n     * @param sec 시간 (ms)\n     */\n    extLedOn: function(pin, sec) {\n        if (typeof pin == 'string') pin = this.pins[pin];\n        sec *= 1000;\n        return this.runPackage(this.devices['ExLed'], pin, this.short2array(sec));\n    },\n\n    /**\n     * @brief 외부 speaker 소리내기\n     *\n     * @param pin pwm 핀번호\n     * @param freq주파수\n     * @param duration시간 (ms)\n     */\n    playSpeaker: function(pin, freq, duration) {\n        if (typeof pin == 'string') pin = this.pins[pin];\n        duration *= 1000;\n        return this.runPackage(\n            this.devices['Speaker'],\n            pin,\n            this.short2array(freq),\n            this.short2array(duration)\n        );\n    },\n\n    /**\n     * @brief 외부 speaker 끄기\n     *\n     * @param pin pwm 핀번호\n     */\n    stopSpeaker: function(pin) {\n        if (typeof pin == 'string') pin = this.pins[pin];\n        return this.runPackage(\n            this.devices['Speaker'],\n            pin,\n            this.short2array(0),\n            this.short2array(0)\n        );\n    },\n\n    /**\n     * @brief run servo motor\n     *\n     * @param pin pwm pins (D10, D11)\n     * @param angle 0~180\n     */\n    runExtServo: function(pin, angle) {\n        if (typeof pin == 'string') pin = this.pins[pin];\n        return this.runPackage(this.devices['ServoMotor'], pin, angle);\n    },\n\n    /**\n     * @brief 디지털 출력 설정\n     * @date2016.05.19\n     *\n     * @param pin 디지털 핀번호\n     * @param outputValue 출력값 (HIGH:1, LOW:0)\n     */\n    digitalWrite: function(pin, outputValue) {\n        if (typeof outputValue == 'string') outputValue = this.outputValues[outputValue];\n        return this.runPackage(this.devices['Digital'], pin, outputValue);\n    },\n\n    /**\n     * @brief 아날로그 출력 설정\n     * @date2016.05.19\n     *\n     * @param pin 아날로그 핀번호\n     * @param duty듀티사이클 (0~255)\n     */\n    analogWrite: function(pin, duty) {\n        if (typeof duty != 'number') {\n            duty = 0;\n        } else if (duty > 255) {\n            // 듀티사이클이 255를 넘길경우 255로 설정 (100%)\n            duty = 255;\n        } //if\n\n        return this.runPackage(this.devices['Analog'], pin, duty);\n    },\n\n    readFloat: function(arr, position) {\n        var f = [arr[position], arr[position + 1], arr[position + 2], arr[position + 3]];\n        return parseFloat(f);\n    }, //function\n\n    readShort: function(arr, position) {\n        var s = [arr[position], arr[position + 1]];\n        return parseFloat(s);\n    }, //furnction\n\n    readDouble: function(arr, position) {\n        return this.readFloat(arr, position);\n    }, //function\n\n    readString: function(arr, position, len) {\n        var value = '';\n        for (var ii = 0; ii < len; ii++) {\n            // value += String.fromCharCode(_rxBuf[ii + position]);\n        } //for\n\n        return value;\n    }, //function\n\n    short2array: function(value) {\n        var tempBytes = {};\n        for (var i = 0; i < 2; i++) {\n            var tempByte = value & 0xff;\n            tempBytes[i] = tempByte;\n            value = (value - tempByte) / 256;\n        }\n        return [tempBytes[0], tempBytes[1]];\n    },\n\n    runPackage: function() {\n        var bytes = [0xff, 0x55, 0, 0, 2];\n        for (var i = 0; i < arguments.length; i++) {\n            if (arguments[i].constructor == '[class Array]') {\n                bytes = bytes.concat(arguments[i]);\n            } else if (arguments[i].length == 2) {\n                //coconut 용 수\n                bytes = bytes.concat(arguments[i]);\n            } else {\n                bytes.push(arguments[i]);\n            }\n        } //for\n\n        bytes[2] = bytes.length - 3; // data length\n\n        // 장치에 ArrayBuffer data 전송\n        //device.send(bytes);\n        return bytes;\n    },\n    /* Scratch coconut Extension import */\n    id: '15.1',\n    name: 'coconut',\n    url: 'http://coco-nut.kr',\n    imageName: 'coconut.png',\n    title: {\n        ko: '코코넛',\n        en: 'coconut',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/coconut.png',\n        width: 256,\n        height: 256,\n        listPorts: {\n            temperature: {\n                name: Lang.Blocks.coconut_sensor_temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationX: {\n                name: Lang.Blocks.coconut_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.coconut_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.coconut_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            leftProximityValue: {\n                name: Lang.Blocks.coconut_sensor_left_proximity,\n                type: 'input',\n                pos: { x: 122, y: 156 },\n            },\n            rightProximityValue: {\n                name: Lang.Blocks.coconut_sensor_right_proximity,\n                type: 'input',\n                pos: { x: 10, y: 108 },\n            },\n            leftFloorValue: {\n                name: Lang.Blocks.coconut_sensor_left_floor,\n                type: 'input',\n                pos: { x: 100, y: 234 },\n            },\n            rightFloorValue: {\n                name: Lang.Blocks.coconut_sensor_right_floor,\n                type: 'input',\n                pos: { x: 13, y: 180 },\n            },\n            light: {\n                name: Lang.Blocks.coconut_sensor_light,\n                type: 'input',\n                pos: { x: 56, y: 189 },\n            },\n        },\n        mode: 'both',\n    },\n};\nEntry.coconut.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                coconut_stop_motor: '모터 정지 %1',\n                coconut_move_motor: '%1 움직이기 %2',\n                coconut_turn_motor: '%1 으로 돌기 %2',\n                coconut_move_for_secs: '%1 %2 초동안 움직이기 %3',\n                coconut_turn_for_secs: '%1 으로 %2 초동안 돌기 %3',\n                coconut_turn_to_led: '%1 으로 회전하는 동안 %2LED 켜기 %3',\n                coconut_move_outmotor: '외부모터 %1(으로) 움직이기 속도 %2 %3',\n                coconut_set_led_to: '%1 LED를 %2 으로 켜기 %3',\n                coconut_clear_led: '%1 LED 끄기 %2',\n                coconut_set_led_clear: '%1 LED %2 끄기 %3',\n                coconut_set_led_time: '%1 LED %2 으로 %3 초동안 켜기 %4',\n                coconut_beep: '버저 켜기 %1',\n                coconut_buzzer_time: '버저음을 %1 초 동안 소리내기 %2',\n                coconut_buzzer_set_hz: '버즈음 %1 Hz를 %2초 동안 소리내기 %3',\n                coconut_clear_buzzer: '버저 끄기 %1',\n                coconut_play_buzzer: '%1 %2 %3 음을 %4 박자로 연주하기 %5',\n                coconut_rest_buzzer: '%1 동안 쉬기 %2',\n                coconut_play_buzzer_led: '%1 %2 %3 음을 %4 박자로 연주하는 동안 %5 LED %6 켜기 %7',\n                coconut_play_midi: '%1 연주하기 %2',\n                coconut_floor_sensor: '%1 바닥센서',\n                coconut_floor_sensing: '%1 바닥센서 %2',\n                coconut_following_line: '선 따라가기 %1',\n                coconut_front_sensor: '%1 전방센서',\n                coconut_front_sensing: '%1 전방센서 %2',\n                coconut_obstruct_sensing: '장애물 감지',\n                coconut_avoid_mode: '어보이드 모드 %1',\n                coconut_dotmatrix_set: '도트매트릭스 %1 ( %2줄, %3칸 ) %4',\n                coconut_dotmatrix_on: '도트매트릭스 모두 켜기 %1',\n                coconut_dotmatrix_off: '도트매트릭스 모두 끄기 %1',\n                coconut_dotmatrix_num: '도트매트릭스 숫자 %1표시 %2',\n                coconut_dotmatrix_small_eng: '도트매트릭스 소문자 %1표시 %2',\n                coconut_dotmatrix_big_eng: '도트매트릭스 대문자 %1표시 %2',\n                coconut_dotmatrix_kor: '도트매트릭스 한글 %1표시 %2',\n                coconut_light_sensor: '밝기',\n                coconut_tem_sensor: '온도',\n                coconut_ac_sensor: '%1 가속도',\n                coconut_outled_sensor: '외부 LED 설정 %1 %2 초동안 켜기 %3',\n                coconut_outspk_sensor: '외부 스피커 설정 %1 %2Hz로 %3초 동안 소리내기 %4',\n                coconut_outspk_sensor_off: '외부 스피커 %1 끄기 %2',\n                coconut_outinfrared_sensor: '외부 적외선센서 %1',\n                coconut_outcds_sensor: '외부 빛센서(Cds) %1',\n                coconut_servomotor_angle: '서보모터 연결 %1 각도 %2 %3',\n            },\n            Blocks: {\n                coconut_stop_motor: '모터 정지',\n                coconut_move_motor: '움직이기',\n                coconut_turn_motor: '으로 돌기',\n                coconut_move_outmotor: '외부모터',\n                coconut_turn_left: '왼쪽',\n                coconut_turn_right: '오른쪽',\n                coconut_move_forward: '앞으로',\n                coconut_move_backward: '뒤로',\n                coconut_note_c: '도',\n                coconut_note_d: '레',\n                coconut_note_e: '미',\n                coconut_note_f: '파',\n                coconut_note_g: '솔',\n                coconut_note_a: '라',\n                coconut_note_b: '시',\n                coconut_move_speed_1: '0',\n                coconut_move_speed_2: '50',\n                coconut_move_speed_3: '100',\n                coconut_move_speed_4: '150',\n                coconut_move_speed_5: '255',\n                coconut_play_buzzer_hn: '2분음표',\n                coconut_play_buzzer_qn: '4분음표',\n                coconut_play_buzzer_en: '8분음표',\n                coconut_play_buzzer_sn: '16분음표',\n                coconut_play_buzzer_tn: '32분음표',\n                coconut_play_buzzer_wn: '온음표',\n                coconut_play_buzzer_dhn: '점2분음표',\n                coconut_play_buzzer_dqn: '점4분음표',\n                coconut_play_buzzer_den: '점8분음표',\n                coconut_play_buzzer_dsn: '점16분음표',\n                coconut_play_buzzer_dtn: '점32분음표',\n                coconut_rest_buzzer_hr: '2분쉼표',\n                coconut_rest_buzzer_qr: '4분쉼표',\n                coconut_rest_buzzer_er: '8분쉼표',\n                coconut_rest_buzzer_sr: '16분쉼표',\n                coconut_rest_buzzer_tr: '32분쉼표',\n                coconut_rest_buzzer_wr: '온쉼표',\n                coconut_play_midi_1: '반짝반짝 작은별',\n                coconut_play_midi_2: '곰세마리',\n                coconut_play_midi_3: '모차르트 자장가',\n                coconut_play_midi_4: '도레미송',\n                coconut_play_midi_5: '나비야',\n                coconut_floor_sensing_on: '감지',\n                coconut_floor_sensing_off: '미감지',\n                coconut_dotmatrix_set_on: '켜짐',\n                coconut_dotmatrix_set_off: '꺼짐',\n                coconut_dotmatrix_row_0: '모든',\n                coconut_dotmatrix_row_1: '1',\n                coconut_dotmatrix_row_2: '2',\n                coconut_dotmatrix_row_3: '3',\n                coconut_dotmatrix_row_4: '4',\n                coconut_dotmatrix_row_5: '5',\n                coconut_dotmatrix_row_6: '6',\n                coconut_dotmatrix_row_7: '7',\n                coconut_dotmatrix_row_8: '8',\n                coconut_dotmatrix_col_0: '모든',\n                coconut_dotmatrix_col_1: '1',\n                coconut_dotmatrix_col_2: '2',\n                coconut_dotmatrix_col_3: '3',\n                coconut_dotmatrix_col_4: '4',\n                coconut_dotmatrix_col_5: '5',\n                coconut_dotmatrix_col_6: '6',\n                coconut_dotmatrix_col_7: '7',\n                coconut_dotmatrix_col_8: '8',\n                coconut_sensor_left_proximity: '왼쪽 전방 센서',\n                coconut_sensor_right_proximity: '오른쪽 전방 센서',\n                coconut_sensor_both_proximity: '모든',\n                coconut_sensor_left_floor: '왼쪽 바닥센서',\n                coconut_sensor_right_floor: '오른쪽 바닥 센서',\n                coconut_sensor_both_floor: '모든',\n                coconut_sensor_acceleration_x: 'x축 가속도',\n                coconut_sensor_acceleration_y: 'y축 가속도',\n                coconut_sensor_acceleration_z: 'z축 가속도',\n                coconut_sensor_light: '밝기',\n                coconut_sensor_temperature: '온도',\n                coconut_left_led: '왼쪽',\n                coconut_right_led: '오른쪽',\n                coconut_both_leds: '모든',\n                coconut_color_cyan: '하늘색',\n                coconut_color_magenta: '보라색',\n                coconut_color_black: '검은색',\n                coconut_color_white: '흰색',\n                coconut_color_red: '빨간색',\n                coconut_color_yellow: '노란색',\n                coconut_color_green: '초록색',\n                coconut_color_blue: '파란색',\n                coconut_beep: '삐 소리내기',\n                coconut_clear_buzzer: '버저 끄기',\n                coconut_x_axis: 'X축',\n                coconut_y_axis: 'Y축',\n                coconut_z_axis: 'Z축',\n            },\n            Menus: {},\n        },\n        en: {\n            template: {\n                coconut_stop_motor: 'stop motor %1',\n                coconut_move_motor: 'move %1 %2',\n                coconut_turn_motor: 'turn %1 %2',\n                coconut_move_for_secs: 'move %1 for time %2 %3',\n                coconut_turn_for_secs: 'turn %1 for %2 secs %3',\n                coconut_turn_to_led: 'turn %1 RGB %2 %3',\n                coconut_move_outmotor: 'external Motor %1 speed %2 %3',\n                coconut_set_led_to: 'turn on RGB %1 %2 %3',\n                coconut_clear_led: 'turn off RGB %1 %2',\n                coconut_set_led_clear: 'turn off RGB %1 %2 %3',\n                coconut_set_led_time: 'turn on RGB %1 %2 for time %3 %4',\n                coconut_beep: 'buzzer on %1',\n                coconut_buzzer_time: 'play buzzer for time %1 %2',\n                coconut_buzzer_set_hz: 'play buzzer on frequency %1 Hz for time %2 %3',\n                coconut_clear_buzzer: 'buzzer off %1',\n                coconut_play_buzzer: 'play buzzer on note %1 octave %2 %3 beat %4 %5',\n                coconut_rest_buzzer: 'rest beat %1 %2',\n                coconut_play_buzzer_led: 'play buzzer on note %1 octave %2 %3 beat %4 RGB %5 %6 %7',\n                coconut_play_midi: 'play melody %1 %2',\n                coconut_floor_sensor: 'line tracer %1',\n                coconut_floor_sensing: 'line tracer detect %1 %2',\n                coconut_following_line: 'follow the line %1',\n                coconut_front_sensor: 'IR distance sensor %1',\n                coconut_front_sensing: 'detecting obstacle %1 %2',\n                coconut_obstruct_sensing: 'detecting obstacle',\n                coconut_avoid_mode: 'avoid mode %1',\n                coconut_dotmatrix_set: 'LED Matrix %1 ( ROW %2, COL %3 ) %4',\n                coconut_dotmatrix_on: 'turn on all LED Matrix %1',\n                coconut_dotmatrix_off: 'LED Matrix clear all %1',\n                coconut_dotmatrix_num: 'LED Matrix show %1 %2',\n                coconut_dotmatrix_small_eng: 'LED Matrix show small letter %1 %2',\n                coconut_dotmatrix_big_eng: 'LED Matrix show capital letters %1 %2',\n                coconut_dotmatrix_kor: 'LED Matrix show Korean %1 %2',\n                coconut_light_sensor: 'light sensor',\n                coconut_tem_sensor: 'temperature',\n                coconut_ac_sensor: '3-Axis Accelerometer %1 angle',\n                coconut_outled_sensor: 'set external LED pin %1 for time %2 %3',\n                coconut_outspk_sensor:\n                    'set Speaker pin %1 frequency %2 (Hz) duration %3 seconds %4',\n                coconut_outspk_sensor_off: 'stop Speaker pin %1 %2',\n                coconut_outinfrared_sensor: 'external IR sensor %1',\n                coconut_outcds_sensor: 'external Cds sensor %1',\n                coconut_servomotor_angle: 'set servo pin %1 angle as %2 %3',\n            },\n            Blocks: {\n                coconut_stop_motor: 'stop motor',\n                coconut_move_motor: 'move motor',\n                coconut_turn_motor: 'turn',\n                coconut_move_outmotor: 'external motor',\n                coconut_turn_left: 'left',\n                coconut_turn_right: 'right',\n                coconut_move_forward: 'forward',\n                coconut_move_backward: 'backward',\n                coconut_note_c: 'note_c',\n                coconut_note_d: 'note_d',\n                coconut_note_e: 'note_e',\n                coconut_note_f: 'note_f',\n                coconut_note_g: 'note_g',\n                coconut_note_a: 'note_a',\n                coconut_note_b: 'note_b',\n                coconut_move_speed_1: '0',\n                coconut_move_speed_2: '50',\n                coconut_move_speed_3: '100',\n                coconut_move_speed_4: '150',\n                coconut_move_speed_5: '255',\n                coconut_play_buzzer_hn: 'Half',\n                coconut_play_buzzer_qn: 'Quater',\n                coconut_play_buzzer_en: 'Eighth',\n                coconut_play_buzzer_sn: 'Sixteenth',\n                coconut_play_buzzer_tn: 'Thirty-second',\n                coconut_play_buzzer_wn: 'Whole',\n                coconut_play_buzzer_dhn: 'Dotted half',\n                coconut_play_buzzer_dqn: 'Dotted quarter',\n                coconut_play_buzzer_den: 'Dotted eighth',\n                coconut_play_buzzer_dsn: 'Dotted sixteenth',\n                coconut_play_buzzer_dtn: 'Dotted thirty-second',\n                coconut_rest_buzzer_hr: 'Half_rest',\n                coconut_rest_buzzer_qr: 'Quater_rest',\n                coconut_rest_buzzer_er: 'Eighth_rest',\n                coconut_rest_buzzer_sr: 'Sixteenth_rest',\n                coconut_rest_buzzer_tr: 'Thirty-second rest',\n                coconut_rest_buzzer_wr: 'Whole_rest',\n                coconut_play_midi_1: 'Twinkle Twinkle little star',\n                coconut_play_midi_2: 'Three bears',\n                coconut_play_midi_3: \"Mozart's Lullaby\",\n                coconut_play_midi_4: 'Do-Re-Mi',\n                coconut_play_midi_5: 'Butterfly',\n                coconut_floor_sensing_on: 'detect',\n                coconut_floor_sensing_off: 'not detect',\n                coconut_dotmatrix_set_on: 'on',\n                coconut_dotmatrix_set_off: 'off',\n                coconut_dotmatrix_row_0: 'all',\n                coconut_dotmatrix_row_1: '1',\n                coconut_dotmatrix_row_2: '2',\n                coconut_dotmatrix_row_3: '3',\n                coconut_dotmatrix_row_4: '4',\n                coconut_dotmatrix_row_5: '5',\n                coconut_dotmatrix_row_6: '6',\n                coconut_dotmatrix_row_7: '7',\n                coconut_dotmatrix_row_8: '8',\n                coconut_dotmatrix_col_0: 'all',\n                coconut_dotmatrix_col_1: '1',\n                coconut_dotmatrix_col_2: '2',\n                coconut_dotmatrix_col_3: '3',\n                coconut_dotmatrix_col_4: '4',\n                coconut_dotmatrix_col_5: '5',\n                coconut_dotmatrix_col_6: '6',\n                coconut_dotmatrix_col_7: '7',\n                coconut_dotmatrix_col_8: '8',\n                coconut_sensor_left_proximity: 'left IR distance',\n                coconut_sensor_right_proximity: 'right IR distance',\n                coconut_sensor_both_proximity: 'both IR distance',\n                coconut_sensor_left_floor: 'left line tracer',\n                coconut_sensor_right_floor: 'right line tracer',\n                coconut_sensor_both_floor: 'both line tracer',\n                coconut_sensor_acceleration_x: 'X-Axis Accelerometer',\n                coconut_sensor_acceleration_y: 'Y-Axis Accelerometer',\n                coconut_sensor_acceleration_z: 'Z-Axis Accelerometer',\n                coconut_sensor_light: 'light sensor',\n                coconut_sensor_temperature: 'temperature',\n                coconut_left_led: 'left led',\n                coconut_right_led: 'right led',\n                coconut_both_leds: 'both led',\n                coconut_color_cyan: 'Cyan',\n                coconut_color_magenta: 'Magenta',\n                coconut_color_black: 'Black',\n                coconut_color_white: 'White',\n                coconut_color_red: 'Red',\n                coconut_color_yellow: 'Yellow',\n                coconut_color_green: 'Green',\n                coconut_color_blue: 'Blue',\n                coconut_beep: 'buzzer on',\n                coconut_clear_buzzer: 'buzzer off',\n                coconut_x_axis: 'X-Axis',\n                coconut_y_axis: 'Y-Axis',\n                coconut_z_axis: 'Z-Axis',\n            },\n            Menus: {},\n        },\n    };\n};\nEntry.coconut.blockMenuBlocks = [\n    'coconut_move_motor',\n    'coconut_turn_motor',\n    'coconut_stop_motor',\n    'coconut_move_for_secs',\n    'coconut_turn_for_secs',\n    'coconut_turn_to_led',\n    'coconut_move_outmotor',\n    'coconut_set_led_to',\n    'coconut_clear_led',\n    'coconut_set_led_clear',\n    'coconut_set_led_time',\n    'coconut_beep',\n    'coconut_buzzer_time',\n    'coconut_buzzer_set_hz',\n    'coconut_clear_buzzer',\n    'coconut_play_buzzer',\n    'coconut_rest_buzzer',\n    'coconut_play_buzzer_led',\n    'coconut_play_midi',\n    'coconut_floor_sensor',\n    'coconut_floor_sensing',\n    'coconut_following_line',\n    'coconut_front_sensor',\n    'coconut_front_sensing',\n    'coconut_obstruct_sensing',\n    'coconut_avoid_mode',\n    'coconut_dotmatrix_set',\n    'coconut_dotmatrix_on',\n    'coconut_dotmatrix_off',\n    'coconut_dotmatrix_num',\n    'coconut_dotmatrix_small_eng',\n    'coconut_dotmatrix_big_eng',\n    'coconut_dotmatrix_kor',\n    'coconut_light_sensor',\n    'coconut_light_tmp',\n    'coconut_ac_sensor',\n    'coconut_outled_sensor',\n    'coconut_outspk_sensor',\n    'coconut_outspk_sensor_off',\n    'coconut_outinfrared_sensor',\n    'coconut_outcds_sensor',\n    'coconut_servomotor_angle',\n];\nEntry.coconut.getBlocks = function() {\n    return {\n        //region coconut 코코넛\n        coconut_move_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_move_forward, '3'],\n                        [Lang.Blocks.coconut_move_backward, '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_move_motor',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n            },\n            class: 'coconut_wheel',\n            isNotFor: ['coconut'],\n\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                //앞으로 가기\n                var dist = script.getField('DIST', script);\n                var move = parseInt(dist);\n                var arrMsg = Entry.coconut.moveMotor(move);\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x01\",\"0x07\",\"0x00\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        coconut_turn_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_turn_left, '1'],\n                        [Lang.Blocks.coconut_turn_right, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_turn_motor',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n            },\n            class: 'coconut_wheel',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist = script.getField('DIST');\n                var move = parseInt(dist);\n                var arrMsg = Entry.coconut.turnMotor(move); //왼쪽, 오른쪽으로 가기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x06\",\"0x00\",\"0x02\",\"0x1a\",\"0x00\",\"0x02\",\"0x3c\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        coconut_stop_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_stop_motor',\n            },\n            class: 'coconut_wheel',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var arrMsg = Entry.coconut.stopMotor(); //모터정지\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x04\",\"0x00\",\"0x02\",\"0x1a\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_move_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_move_forward, '3'],\n                        [Lang.Blocks.coconut_move_backward, '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'coconut_move_for_secs',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n                VALUE: 1,\n            },\n            class: 'coconut_wheel',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist = script.getField('DIST', script);\n                var move = parseInt(dist);\n                var time = script.getNumberValue('VALUE');\n                var arrMsg = Entry.coconut.moveGoTime(move, time); //앞으로 1초동안 움직이기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x1a\",\"0x03\",\"0x03\",\"0x3c\",\"0xe8\",\"0x03\"];\n\n                var now = Date();\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log(now + ' : rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log(now + ' : rev = continue' + pd.msg);\n                    } else {\n                        console.log(now + ' : rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log(now + ' : rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_turn_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_turn_left, '1'],\n                        [Lang.Blocks.coconut_turn_right, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'coconut_turn_for_secs',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n                VALUE: 1,\n            },\n            class: 'coconut_wheel',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist = script.getField('DIST', script);\n                var move = parseInt(dist);\n                var time = script.getNumberValue('VALUE');\n                var arrMsg = Entry.coconut.moveGoTime(move, time); //왼쪽으로 1초동안 돌기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x1a\",\"0x03\",\"0x01\",\"0x3c\",\"0xe8\",\"0x03\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        coconut_turn_to_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_turn_left, '1'],\n                        [Lang.Blocks.coconut_turn_right, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_color_red, '2'],\n                        [Lang.Blocks.coconut_color_yellow, '5'],\n                        [Lang.Blocks.coconut_color_green, '3'],\n                        [Lang.Blocks.coconut_color_cyan, '6'],\n                        [Lang.Blocks.coconut_color_blue, '4'],\n                        [Lang.Blocks.coconut_color_magenta, '7'],\n                        [Lang.Blocks.coconut_color_white, '1'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'coconut_turn_to_led',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n                COLOR: 1,\n            },\n            class: 'coconut_wheel',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist1 = script.getField('DIST', script);\n                var dist2 = script.getField('COLOR', script);\n                var move = parseInt(dist1);\n                var color = parseInt(dist2);\n                var arrMsg = Entry.coconut.moveMotorColor(move, color); //왼쪽으로 회전하는 동안 빨간색 LED켜기\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_move_outmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_move_forward, '3'],\n                        [Lang.Blocks.coconut_move_backward, '4'],\n                        [Lang.Blocks.coconut_turn_left, '1'],\n                        [Lang.Blocks.coconut_turn_right, '2'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                ],\n                type: 'coconut_move_outmotor',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n                VALUE: 1,\n            },\n            class: 'coconut_wheel',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist1 = script.getField('DIST', script);\n                var move = parseInt(dist1);\n                var speed = script.getNumberValue('VALUE');\n                var arrMsg = Entry.coconut.moveExtMotor(move, speed); //외부모터 앞으로 움직이기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x06\",\"0x00\",\"0x02\",\"0x1a\",\"0x07\",\"0x03\",\"0x3c\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_set_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_left_led, '1'],\n                        [Lang.Blocks.coconut_right_led, '2'],\n                        [Lang.Blocks.coconut_both_leds, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_color_red, '2'],\n                        [Lang.Blocks.coconut_color_yellow, '5'],\n                        [Lang.Blocks.coconut_color_green, '3'],\n                        [Lang.Blocks.coconut_color_cyan, '6'],\n                        [Lang.Blocks.coconut_color_blue, '4'],\n                        [Lang.Blocks.coconut_color_magenta, '7'],\n                        [Lang.Blocks.coconut_color_white, '1'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'coconut_set_led_to',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n                COLOR: 1,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var now = new Date();\n                var dist1 = script.getField('DIST', script);\n                var dist2 = script.getField('COLOR', script);\n                var dir = parseInt(dist1);\n                var color = parseInt(dist2);\n                var arrMsg = Entry.coconut.rgbOn(dir, color); //왼쪽 LED 빨간색으로 켜기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x06\",\"0x00\",\"0x02\",\"0x19\",\"0x00\",\"0x01\",\"0x02\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log(now + ' : rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log(now + ' : rev = continue' + pd.msg);\n                    } else {\n                        console.log(now + ' : rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_left_led, '1'],\n                        [Lang.Blocks.coconut_right_led, '2'],\n                        [Lang.Blocks.coconut_both_leds, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_clear_led',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist1 = script.getField('DIST', script);\n                var dir = parseInt(dist1);\n                var arrMsg = Entry.coconut.rgbOff(dir); //왼쪽LED 끄기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x06\",\"0x00\",\"0x02\",\"0x19\",\"0x01\",\"0x01\",\"0x00\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n        },\n        coconut_set_led_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_left_led, '1'],\n                        [Lang.Blocks.coconut_right_led, '2'],\n                        [Lang.Blocks.coconut_both_leds, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_color_red, '2'],\n                        [Lang.Blocks.coconut_color_yellow, '5'],\n                        [Lang.Blocks.coconut_color_green, '3'],\n                        [Lang.Blocks.coconut_color_cyan, '6'],\n                        [Lang.Blocks.coconut_color_blue, '4'],\n                        [Lang.Blocks.coconut_color_magenta, '7'],\n                        [Lang.Blocks.coconut_color_white, '1'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'coconut_set_led_clear',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n                COLOR: 1,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist1 = script.getField('DIST', script);\n                var dist2 = script.getField('COLOR', script);\n                var dir = parseInt(dist1);\n                var color = parseInt(dist2);\n                var arrMsg = Entry.coconut.rgbOffColor(dir, color); //왼쪽 LED 빨간색 끄기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x06\",\"0x00\",\"0x02\",\"0x19\",\"0x01\",\"0x01\",\"0x02\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_set_led_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_left_led, 'Left'],\n                        [Lang.Blocks.coconut_right_led, 'Right'],\n                        [Lang.Blocks.coconut_both_leds, 'Both'],\n                    ],\n                    value: 'Left',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_color_red, '2'],\n                        [Lang.Blocks.coconut_color_yellow, '5'],\n                        [Lang.Blocks.coconut_color_green, '3'],\n                        [Lang.Blocks.coconut_color_cyan, '6'],\n                        [Lang.Blocks.coconut_color_blue, '4'],\n                        [Lang.Blocks.coconut_color_magenta, '7'],\n                        [Lang.Blocks.coconut_color_white, '1'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0.6'],\n                    },\n                ],\n                type: 'coconut_set_led_time',\n            },\n            paramsKeyMap: {\n                DIST: 0,\n                COLOR: 1,\n                VALUE: 2,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist1 = script.getField('DIST', script);\n                var dist2 = script.getField('COLOR', script);\n                var time = script.getNumberValue('VALUE');\n                var color = parseInt(dist2);\n                var arrMsg = Entry.coconut.ledOnTime(dist1, color, time); //왼쪽 LED 빨간색으로 1초동안 켜기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x19\",\"0x03\",\"0x01\",\"0x02\",\"0xe8\",\"0x03\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_beep: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_beep',\n            },\n            class: 'coconut_buzzer',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var arrMsg = Entry.coconut.beep(); //버저 켜기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x03\",\"0x00\",\"0x06\",\"0x01\",\"0xf4\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_buzzer_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.6'],\n                    },\n                ],\n                type: 'coconut_buzzer_time',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'coconut_buzzer',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var time = script.getNumberValue('VALUE');\n                var arrMsg = Entry.coconut.playBuzzerTime(time); //버저음을 1초동안 소리내기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x03\",\"0x00\",\"0x06\",\"0x01\",\"0xe8\",\"0x03\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_buzzer_set_hz: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.6'],\n                    },\n                ],\n                type: 'coconut_buzzer_set_hz',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                TIME: 1,\n            },\n            class: 'coconut_buzzer',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var hz = script.getNumberValue('HZ');\n                var time = script.getNumberValue('TIME');\n                var arrMsg = Entry.coconut.playBuzzerFreq(hz, time); //버저음 1000hz를 1초동안 소리내기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x03\",\"0x00\",\"0x2c\",\"0x01\",\"0xe8\",\"0x03\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_clear_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_clear_buzzer',\n            },\n            class: 'coconut_buzzer',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var arrMsg = Entry.coconut.buzzerOff(); //버저 끄기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x03\",\"0x00\",\"0x00\",\"0x00\",\"0x00\",\"0x00\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_play_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_note_c, 'NOTE_C'],\n                        [Lang.Blocks.coconut_note_d, 'NOTE_D'],\n                        [Lang.Blocks.coconut_note_e, 'NOTE_E'],\n                        [Lang.Blocks.coconut_note_f, 'NOTE_F'],\n                        [Lang.Blocks.coconut_note_g, 'NOTE_G'],\n                        [Lang.Blocks.coconut_note_a, 'NOTE_A'],\n                        [Lang.Blocks.coconut_note_b, 'NOTE_B'],\n                    ],\n                    value: 'NOTE_C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['-', '-'],\n                        ['#', '#'],\n                        ['b', 'b'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_play_buzzer_hn, '500'],\n                        [Lang.Blocks.coconut_play_buzzer_qn, '250'],\n                        [Lang.Blocks.coconut_play_buzzer_en, '125'],\n                        [Lang.Blocks.coconut_play_buzzer_sn, '63'],\n                        [Lang.Blocks.coconut_play_buzzer_tn, '32'],\n                        [Lang.Blocks.coconut_play_buzzer_wn, '1000'],\n                        [Lang.Blocks.coconut_play_buzzer_dhn, '750'],\n                        [Lang.Blocks.coconut_play_buzzer_dqn, '375'],\n                        [Lang.Blocks.coconut_play_buzzer_den, '188'],\n                        [Lang.Blocks.coconut_play_buzzer_dsn, '95'],\n                        [Lang.Blocks.coconut_play_buzzer_dtn, '48'],\n                    ],\n                    value: '500',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', '-', null],\n                type: 'coconut_play_buzzer',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                SEMI: 2,\n                BEAT: 3,\n            },\n            class: 'coconut_buzzer',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist1 = script.getField('NOTE', script);\n                var dist2 = script.getField('OCTAVE', script);\n                var dist3 = script.getField('SEMI', script);\n                var dist4 = script.getField('BEAT', script);\n                var note = dist1;\n                var octave = parseInt(dist2);\n                var semi = dist3;\n                var beat = parseInt(dist4);\n                var arrMsg = Entry.coconut.playNote(note, octave, semi, beat); //(도)(3)(-)음을 2분음표 박자로 연주하기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x09\",\"0x00\",\"0x02\",\"0x03\",\"0x04\",\"0x43\",\"0x03\",\"0x2d\",\"0xf4\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_rest_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_rest_buzzer_hr, '500'],\n                        [Lang.Blocks.coconut_rest_buzzer_qr, '250'],\n                        [Lang.Blocks.coconut_rest_buzzer_er, '175'],\n                        [Lang.Blocks.coconut_rest_buzzer_sr, '63'],\n                        [Lang.Blocks.coconut_rest_buzzer_tr, '32'],\n                        [Lang.Blocks.coconut_rest_buzzer_wr, '1000'],\n                    ],\n                    value: '500',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_rest_buzzer',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'coconut_buzzer',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist = script.getField('BEAT', script);\n                var beat = parseInt(dist);\n                var arrMsg = Entry.coconut.restBeat(dist); //2분 쉼표 동안 쉬기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x03\",\"0x01\",\"0x00\",\"0x00\",\"0xf4\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_play_buzzer_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ALBERT_note_c, 'NOTE_C'],\n                        [Lang.Blocks.ALBERT_note_d, 'NOTE_D'],\n                        [Lang.Blocks.ALBERT_note_e, 'NOTE_E'],\n                        [Lang.Blocks.ALBERT_note_f, 'NOTE_F'],\n                        [Lang.Blocks.ALBERT_note_g, 'NOTE_G'],\n                        [Lang.Blocks.ALBERT_note_a, 'NOTE_A'],\n                        [Lang.Blocks.ALBERT_note_b, 'NOTE_B'],\n                    ],\n                    value: 'NOTE_C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['-', '-'],\n                        ['#', '#'],\n                        ['b', 'b'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_play_buzzer_hn, '500'],\n                        [Lang.Blocks.coconut_play_buzzer_qn, '250'],\n                        [Lang.Blocks.coconut_play_buzzer_en, '125'],\n                        [Lang.Blocks.coconut_play_buzzer_sn, '63'],\n                        [Lang.Blocks.coconut_play_buzzer_tn, '32'],\n                        [Lang.Blocks.coconut_play_buzzer_wn, '1000'],\n                        [Lang.Blocks.coconut_play_buzzer_dhn, '750'],\n                        [Lang.Blocks.coconut_play_buzzer_dqn, '375'],\n                        [Lang.Blocks.coconut_play_buzzer_den, '188'],\n                        [Lang.Blocks.coconut_play_buzzer_dsn, '95'],\n                        [Lang.Blocks.coconut_play_buzzer_dtn, '48'],\n                    ],\n                    value: '500',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_left_led, '1'],\n                        [Lang.Blocks.coconut_right_led, '2'],\n                        [Lang.Blocks.coconut_both_leds, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_color_red, '2'],\n                        [Lang.Blocks.coconut_color_yellow, '5'],\n                        [Lang.Blocks.coconut_color_green, '3'],\n                        [Lang.Blocks.coconut_color_cyan, '6'],\n                        [Lang.Blocks.coconut_color_blue, '4'],\n                        [Lang.Blocks.coconut_color_magenta, '7'],\n                        [Lang.Blocks.coconut_color_white, '1'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', '-', null, null, null],\n                type: 'coconut_play_buzzer_led',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                SEMI: 2,\n                BEAT: 3,\n                DIR: 4,\n                COLOR: 5,\n            },\n            class: 'coconut_buzzer',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var dist1 = script.getField('NOTE', script);\n                var dist2 = script.getField('OCTAVE', script);\n                var dist3 = script.getField('SEMI', script);\n                var dist4 = script.getField('BEAT', script);\n                var dist5 = script.getField('DIR', script);\n                var dist6 = script.getField('COLOR', script);\n                var note = dist1;\n                var octave = parseInt(dist2);\n                var semi = dist3;\n                var beat = parseInt(dist4);\n                var dir = parseInt(dist5);\n                var color = parseInt(dist6);\n                var arrMsg = Entry.coconut.playNoteColor(note, octave, semi, beat, dir, color);\n                //도 4 - 음을 2분음표 박자로 연주하는 동안 왼쪽 LED 빨간색 켜기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x0b\",\"0x00\",\"0x02\",\"0x03\",\"0x05\",\"0x43\",\"0x04\",\"0x2d\",\"0xf4\",\"0x01\",\"0x01\",\"0x02\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_play_midi: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_play_midi_1, '1'],\n                        [Lang.Blocks.coconut_play_midi_2, '2'],\n                        [Lang.Blocks.coconut_play_midi_3, '3'],\n                        [Lang.Blocks.coconut_play_midi_4, '4'],\n                        [Lang.Blocks.coconut_play_midi_5, '5'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_play_midi',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'coconut_buzzer',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                //반짝반짝 작은별 연주하기\n                var value = script.getField('VALUE');\n                var num = parseInt(value);\n                var arrMsg = Entry.coconut.playMelody(num);\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x01\",\"0x07\",\"0x00\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    sq.msgValue = '';\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_floor_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_sensor_left_floor, '1'],\n                        [Lang.Blocks.coconut_sensor_right_floor, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_floor_sensor',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            class: 'coconut_sensor',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var dir = script.getField('DIR');\n                if (dir == '1') {\n                    return pd.leftFloorValue;\n                } else {\n                    return pd.rightFloorValue;\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_floor_sensing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_sensor_left_floor, '1'],\n                        [Lang.Blocks.coconut_sensor_right_floor, '2'],\n                        [Lang.Blocks.coconut_sensor_both_floor, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_floor_sensing_on, '1'],\n                        [Lang.Blocks.coconut_floor_sensing_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'coconut_floor_sensing',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n                DET: 1,\n            },\n            class: 'coconut_sensor',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var dir = script.getField('DIR');\n                var det = script.getField('DET');\n                if (dir == '0') {\n                    if (det == '1') {\n                        if (pd.BothFloorDetection == 3)\n                            //모든 바닥센서가 감지됐나\n                            return true;\n                        else return false;\n                    } else {\n                        if (pd.BothFloorDetection == 0)\n                            //모든 바닥센서가 미감지됐나\n                            return true;\n                        else return false;\n                    }\n                } else if (dir == '1') {\n                    if (det == '1') {\n                        if (pd.BothFloorDetection == 2)\n                            // 왼쪽 바닥센서가 감지\n                            return true;\n                        else return false;\n                    } else {\n                        if (pd.BothFloorDetection == 0)\n                            // 왼쪽 바닥센서가 감지\n                            return true;\n                        else return false;\n                    }\n                } else if (dir == '2') {\n                    if (det == '1') {\n                        if (pd.BothFloorDetection == 1)\n                            // 오른쪽 바닥센서가 감지\n                            return true;\n                        else return false;\n                    } else {\n                        if (pd.BothFloorDetection == 0)\n                            // 오른쪽 바닥센서가 감지\n                            return true;\n                        else return false;\n                    }\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_following_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_following_line',\n            },\n            paramsKeyMap: {},\n            class: 'coconut_wheel',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                //선 따라가기\n\n                var arrMsg = Entry.coconut.followLine();\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x02\",\"0x07\",\"0x03\",\"0x3c\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_front_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_sensor_left_proximity, '1'],\n                        [Lang.Blocks.coconut_sensor_right_proximity, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_front_sensor',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            class: 'coconut_sensor',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var dir = script.getField('DIR');\n                if (dir == '1') {\n                    return pd.leftProximityValue;\n                } else {\n                    return pd.rightProximityValue;\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_front_sensing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_sensor_left_proximity, '1'],\n                        [Lang.Blocks.coconut_sensor_right_proximity, '2'],\n                        [Lang.Blocks.coconut_sensor_both_proximity, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_floor_sensing_on, '1'],\n                        [Lang.Blocks.coconut_floor_sensing_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'coconut_front_sensing',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n                DET: 1,\n            },\n            class: 'coconut_sensor',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var dir = script.getField('DIR');\n                var det = script.getField('DET');\n                if (dir == '0') {\n                    if (det == '1') {\n                        if (pd.BothProximityDetection == 3)\n                            //모든 바닥센서가 감지됐나\n                            return true;\n                        else return false;\n                    } else {\n                        if (pd.BothProximityDetection == 0)\n                            //모든 바닥센서가 미감지됐나\n                            return true;\n                        else return false;\n                    }\n                } else if (dir == '1') {\n                    if (det == '1') {\n                        if (pd.BothProximityDetection == 2 || pd.BothProximityDetection == 3)\n                            // 왼쪽 바닥센서가 감지\n                            return true;\n                        else return false;\n                    } else {\n                        if (pd.BothProximityDetection == 0 || pd.BothProximityDetection == 1)\n                            // 왼쪽 바닥센서가 감지\n                            return true;\n                        else return false;\n                    }\n                } else if (dir == '2') {\n                    if (det == '1') {\n                        if (pd.BothProximityDetection == 1 || pd.BothProximityDetection == 3)\n                            // 오른쪽 바닥센서가 감지\n                            return true;\n                        else return false;\n                    } else {\n                        if (pd.BothProximityDetection == 0 || pd.BothProximityDetection == 2)\n                            // 오른쪽 바닥센서가 감지\n                            return true;\n                        else return false;\n                    }\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_obstruct_sensing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_obstruct_sensing',\n            },\n            paramsKeyMap: {},\n            class: 'coconut_sensor',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (pd.BothProximityDetection > 0) {\n                    return true;\n                }\n                return false;\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_avoid_mode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_avoid_mode',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'coconut_sensor',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var arrMsg = Entry.coconut.avoidMode(); //어보이드 모드\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x04\",\"0x00\",\"0x02\",\"0x05\",\"0x03\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_dotmatrix_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_dotmatrix_set_on, '1'],\n                        [Lang.Blocks.coconut_dotmatrix_set_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_dotmatrix_row_0, '0'],\n                        [Lang.Blocks.coconut_dotmatrix_row_1, '1'],\n                        [Lang.Blocks.coconut_dotmatrix_row_2, '2'],\n                        [Lang.Blocks.coconut_dotmatrix_row_3, '3'],\n                        [Lang.Blocks.coconut_dotmatrix_row_4, '4'],\n                        [Lang.Blocks.coconut_dotmatrix_row_5, '5'],\n                        [Lang.Blocks.coconut_dotmatrix_row_6, '6'],\n                        [Lang.Blocks.coconut_dotmatrix_row_7, '7'],\n                        [Lang.Blocks.coconut_dotmatrix_row_8, '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_dotmatrix_col_0, '0'],\n                        [Lang.Blocks.coconut_dotmatrix_col_1, '1'],\n                        [Lang.Blocks.coconut_dotmatrix_col_2, '2'],\n                        [Lang.Blocks.coconut_dotmatrix_col_3, '3'],\n                        [Lang.Blocks.coconut_dotmatrix_col_4, '4'],\n                        [Lang.Blocks.coconut_dotmatrix_col_5, '5'],\n                        [Lang.Blocks.coconut_dotmatrix_col_6, '6'],\n                        [Lang.Blocks.coconut_dotmatrix_col_7, '7'],\n                        [Lang.Blocks.coconut_dotmatrix_col_8, '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'coconut_dotmatrix_set',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n                ROW: 1,\n                COL: 2,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var row = script.getField('ROW');\n                var col = script.getField('COL');\n                var button = script.getField('BUTTON');\n                var row = parseInt(row);\n                var col = parseInt(col);\n                var button = parseInt(button);\n                var arrMsg = Entry.coconut.ledMatrixOn(button, row, col); //도트매트릭스 켜짐 1줄 1칸\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x07\",\"0x00\",\"0x02\",\"0x1b\",\"0x00\",\"0x01\",\"0x01\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_dotmatrix_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_dotmatrix_on',\n            },\n            paramsKeyMap: {},\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var arrMsg = Entry.coconut.ledMatrixOnAll(); //도트매트릭스 모두 켜기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x01\",\"0x07\",\"0x00\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_dotmatrix_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_dotmatrix_off',\n            },\n            paramsKeyMap: {},\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var arrMsg = Entry.coconut.ledMatrixClear(); //도트매트릭스 모두 끄기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x04\",\"0x00\",\"0x02\",\"0x1b\",\"0x05\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_dotmatrix_num: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'coconut_dotmatrix_num',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getField('VALUE');\n                var num = parseInt(value);\n                var arrMsg = Entry.coconut.showLedMatrix(num); //도트매트릭스 숫자 1표시\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x02\",\"0x1b\",\"0x01\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_dotmatrix_small_eng: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['a', '0'],\n                        ['b', '1'],\n                        ['c', '2'],\n                        ['d', '3'],\n                        ['e', '4'],\n                        ['f', '5'],\n                        ['g', '6'],\n                        ['h', '7'],\n                        ['i', '8'],\n                        ['j', '9'],\n                        ['k', '10'],\n                        ['l', '11'],\n                        ['m', '12'],\n                        ['n', '13'],\n                        ['o', '14'],\n                        ['p', '15'],\n                        ['q', '16'],\n                        ['r', '17'],\n                        ['s', '18'],\n                        ['t', '19'],\n                        ['u', '20'],\n                        ['v', '21'],\n                        ['w', '22'],\n                        ['x', '23'],\n                        ['y', '24'],\n                        ['z', '25'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_dotmatrix_small_eng',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getField('VALUE');\n                var num = parseInt(value);\n                var arrMsg = Entry.coconut.showLedMatrixSmall(num); //도트매트릭스 소문자 a표시\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x02\",\"0x1b\",\"0x02\",\"0x00\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_dotmatrix_big_eng: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', '0'],\n                        ['B', '1'],\n                        ['C', '2'],\n                        ['D', '3'],\n                        ['E', '4'],\n                        ['F', '5'],\n                        ['G', '6'],\n                        ['H', '7'],\n                        ['I', '8'],\n                        ['J', '9'],\n                        ['K', '10'],\n                        ['L', '11'],\n                        ['M', '12'],\n                        ['N', '13'],\n                        ['O', '14'],\n                        ['P', '15'],\n                        ['Q', '16'],\n                        ['R', '17'],\n                        ['S', '18'],\n                        ['T', '19'],\n                        ['U', '20'],\n                        ['V', '21'],\n                        ['W', '22'],\n                        ['X', '23'],\n                        ['Y', '24'],\n                        ['Z', '25'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_dotmatrix_big_eng',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getField('VALUE');\n                var num = parseInt(value);\n                var arrMsg = Entry.coconut.showLedMatrixLarge(num); //도트매트릭스 대문자 A표시\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x02\",\"0x1b\",\"0x03\",\"0x00\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_dotmatrix_kor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가', '0'],\n                        ['나', '1'],\n                        ['다', '2'],\n                        ['라', '3'],\n                        ['마', '4'],\n                        ['바', '5'],\n                        ['사', '6'],\n                        ['아', '7'],\n                        ['자', '8'],\n                        ['차', '9'],\n                        ['카', '10'],\n                        ['타', '11'],\n                        ['파', '12'],\n                        ['하', '13'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_dotmatrix_kor',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var value = script.getField('VALUE');\n                var num = parseInt(value);\n                var arrMsg = Entry.coconut.showLedMatrixKorean(num); //도트매트릭스 한글 가 표시\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x02\",\"0x1b\",\"0x04\",\"0x00\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_light_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_light_sensor',\n            },\n            paramsKeyMap: {},\n            class: 'coconut_sensor',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                return pd.light;\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_tmp_senser: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'coconut_light_tmp',\n            },\n            paramsKeyMap: {},\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                return pd.temp;\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_ac_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.coconut_x_axis, '1'],\n                        [Lang.Blocks.coconut_y_axis, '2'],\n                        [Lang.Blocks.coconut_z_axis, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_ac_sensor',\n            },\n            paramsKeyMap: {\n                XYZ: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var xyz = script.getField('XYZ');\n\n                if (xyz == '1') {\n                    return pd.accelerationX;\n                } else if (xyz == '2') {\n                    return pd.accelerationY;\n                } else {\n                    return pd.accelerationZ;\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_outled_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['D4', 4],\n                        ['D10', 10],\n                        ['D11', 11],\n                        ['D12', 12],\n                        ['A2', 16],\n                        ['A3', 17],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                ],\n                type: 'coconut_outled_sensor',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                TIME: 1,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var pin = script.getNumberField('PIN');\n                var time = script.getNumberValue('TIME');\n                var arrMsg = Entry.coconut.extLedOn(pin, time); //외부 LED 설정 D4 0.5초동안 켜기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x06\",\"0x00\",\"0x02\",\"0x2c\",\"0x04\",\"0xf4\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_outspk_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['D10', '10'],\n                        ['D11', '11'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0.5'],\n                    },\n                ],\n                type: 'coconut_outspk_sensor',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                HZ: 1,\n                TIME: 2,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var pin = script.getNumberField('PIN');\n                var hz = script.getNumberValue('HZ');\n                var time = script.getNumberValue('TIME');\n                var arrMsg = Entry.coconut.playSpeaker(pin, hz, time); //외부 스피커 설정 D10 100hz로 0.5초 동안 소리내기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x29\",\"0x10\",\"0x64\",\"0x00\",\"0xf4\",\"0x01\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_outspk_sensor_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['D10', '10'],\n                        ['D11', '11'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_outspk_sensor_off',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var pin = script.getNumberField('PIN');\n                var arrMsg = Entry.coconut.stopSpeaker(pin); //외부스피커 D10 끄기\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x08\",\"0x00\",\"0x02\",\"0x29\",\"0x10\",\"0x00\",\"0x00\",\"0x00\",\"0x00\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_outinfrared_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A2', '16'],\n                        ['A3', '17'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_outinfrared_sensor',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var pin = script.getNumberField('PIN');\n\n                if (pin == '16') {\n                    return pd.extA2;\n                } else {\n                    return pd.extA3;\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_outcds_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A2', '16'],\n                        ['A3', '17'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'coconut_outcds_sensor',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var pin = script.getNumberField('PIN');\n                if (pin == '16') {\n                    return pd.extA2;\n                } else {\n                    return pd.extA3;\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        coconut_servomotor_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['D4', '4'],\n                        ['D10', '10'],\n                        ['D11', '11'],\n                        ['D12', '12'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'String',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'coconut_servomotor_angle',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                ANGLE: 1,\n            },\n            class: 'coconut_led',\n            isNotFor: ['coconut'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n\n                var pin = script.getNumberField('PIN');\n                var angle = script.getNumberValue('ANGLE');\n                var arrMsg = Entry.coconut.runExtServo(pin, angle); //서보모터 연결 D4 각도 90\n                //var arrMsg = [\"0xff\",\"0x55\",\"0x05\",\"0x00\",\"0x02\",\"0x43\",\"0x04\",\"0x5a\"];\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    pd.msgStatus = 'start';\n                    Entry.coconut.insertQueue(arrMsg, sq);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (pd.msgStatus == 'end') {\n                        console.log('rev = end');\n                        script.timeFlag = 0;\n                    } else if (pd.msgStatus == 'continue') {\n                        console.log('rev = continue' + pd.msg);\n                    } else {\n                        console.log('rev = waiting');\n                    }\n                    Entry.coconut.clearQueue(sq);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    console.log('rev = ok');\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['coconut.turn_for_secs(%1, %2)'] },\n        },\n        //endregion coconut 코코넛\n    };\n};\n\nmodule.exports = Entry.coconut;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_codeino.js",
    "content": "'use strict';\n\nEntry.CODEino = {\n    id: '1.3',\n    name: 'CODEino',\n    url: 'http://www.codable.co.kr/page/?pid=codeino',\n    imageName: 'codeino.png',\n    title: {\n        ko: '코드이노',\n        en: 'CODEino',\n    },\n    getSensorKey: function() {\n        return 'xxxxxxxx'\n            .replace(/[xy]/g, function(f) {\n                var e = (Math.random() * 16) | 0,\n                    d = f == 'x' ? e : (e & (0 * 3)) | (0 * 8);\n                return d.toString(16);\n            })\n            .toUpperCase();\n    },\n    getSensorTime: function(type) {\n        return new Date().getTime() + type;\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            let isFirst = true;\n            keySet.forEach(function(key) {\n                if (\n                    Entry.hw.sendQueue.SET[key].type === Entry.CODEino.sensorTypes.DEFAULT_NEOPIXEL\n                ) {\n                    Entry.hw.sendQueue.SET[key].data = {\n                        rValue: 0,\n                        gValue: 0,\n                        bValue: 0,\n                        brightness: 22,\n                    };\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else if (\n                    Entry.hw.sendQueue.SET[key].type ===\n                    Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_POWER\n                ) {\n                    Entry.CODEino.CUSTOM_NEOPIXEL_BRIGHTNESS_VALUE = 22;\n                    Entry.hw.sendQueue.SET[key].data = {\n                        isOn: 0,\n                        brightness: Entry.CODEino.CUSTOM_NEOPIXEL_BRIGHTNESS_VALUE,\n                    };\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else if (\n                    Entry.hw.sendQueue.SET[key].type ===\n                    Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_LED_HANDLE\n                ) {\n                    delete Entry.hw.sendQueue.SET[key];\n                } else if (\n                    Entry.hw.sendQueue.SET[key].type === Entry.CODEino.sensorTypes.RGBLED_PIN ||\n                    Entry.hw.sendQueue.SET[key].type === Entry.CODEino.sensorTypes.ULTRASONIC\n                ) {\n                    if (isFirst) {\n                        Entry.CODEino.LED_VALUES = [0, 0, 0];\n                        Entry.hw.sendQueue.SET[key].type = Entry.CODEino.sensorTypes.RESET;\n                        Entry.hw.sendQueue.SET[key].data = {\n                            r: Entry.CODEino.LED_VALUES[0],\n                            g: Entry.CODEino.LED_VALUES[1],\n                            b: Entry.CODEino.LED_VALUES[2],\n                        };\n                        Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                        isFirst = false;\n                    } else {\n                        delete Entry.hw.sendQueue.SET[key];\n                    }\n                } else {\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.CODEino.LAST_ORDER_PORT = 0;\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/codeino.png',\n        width: 431,\n        height: 354,\n        listPorts: {\n            '2': {\n                name: Lang.Hw.port_en + ' 2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '3': {\n                name: Lang.Hw.port_en + ' 3 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '4': {\n                name: Lang.Hw.port_en + ' 4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '5': {\n                name: Lang.Hw.port_en + ' 5 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '6': {\n                name: Lang.Hw.port_en + ' 6 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '7': {\n                name: Lang.Hw.port_en + ' 7 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '8': {\n                name: Lang.Hw.port_en + ' 8 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '9': {\n                name: Lang.Hw.port_en + ' 9 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '10': {\n                name: Lang.Hw.port_en + ' 10 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '11': {\n                name: Lang.Hw.port_en + ' 11 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '12': {\n                name: Lang.Hw.port_en + ' 12 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '13': {\n                name: Lang.Hw.port_en + ' 13 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: Lang.Hw.port_en + ' A0 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: Lang.Hw.port_en + ' A1 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a2: {\n                name: Lang.Hw.port_en + ' A2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a3: {\n                name: Lang.Hw.port_en + ' A3 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a4: {\n                name: Lang.Hw.port_en + ' A4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a5: {\n                name: Lang.Hw.port_en + ' A5 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a6: {\n                name: Lang.Hw.port_en + ' A6 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        RGBLED_PIN: 4,\n        ULTRASONIC: 7,\n        TIMER: 8,\n\n        SERVO_PIN: 10,\n        DEFAULT_NEOPIXEL: 11,\n        CUSTOM_NEOPIXEL_POWER: 12,\n        CUSTOM_NEOPIXEL_LED_HANDLE: 13,\n\n        DEFAULT_BUZZER: 5,\n        CUSTOM_BUZZER: 6,\n        RESET: 0xff,\n    },\n    BlockState: {},\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    customNeoPixelPin: 50,\n    customNeoPixelBrightness: 0,\n    LED_VALUES: [0, 0, 0],\n    LED_RED_VALUE: 0,\n    LED_GREEN_VALUE: 0,\n    LED_BLUE_VALUE: 0,\n\n    DEFAULT_NEOPIXEL_RED_VALUE: 0,\n    DEFAULT_NEOPIXEL_GREEN_VALUE: 0,\n    DEFAULT_NEOPIXEL_BLUE_VALUE: 0,\n    DEFAULT_NEOPIXEL_BRIGHTNESS_VALUE: 22,\n\n    CUSTOM_NEOPIXEL_BRIGHTNESS_VALUE: 22,\n\n    LAST_ORDER_PORT: 0,\n};\n\nEntry.CODEino.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                CODEino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                CODEino_get_digital_value: '디지털 %1 핀의 값  ',\n                CODEino_set_digital_value: '디지털 %1 핀의 %2 %3',\n                CODEino_set_pwm_value: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                CODEino_toggle_led: '디지털 %1 번 핀 %2 %3',\n                CODEino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                CODEino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                CODEino_set_rgb_value: '컬러 LED의 %1 색상을 %2 (으)로 정하기 %3',\n                CODEino_set_rgb_add_value: '컬러 LED의 %1 색상에 %2 만큼 더하기 %3',\n                CODEino_set_rgb_off: '컬러 LED 끄기 %1',\n                CODEino_set__led_by_rgb: '컬러 LED 색상을 빨강 %1 초록 %2 파랑 %3 (으)로 정하기 %4',\n                CODEino_rgb_set_color: '컬러 LED의 색상을 %1 (으)로 정하기 %2',\n                CODEino_led_by_value: '컬러 LED 켜기 %1',\n                CODEino_get_sensor_number: '%1  ',\n                CODEino_get_named_sensor_value: '  %1  센서값 ',\n                CODEino_get_sound_status: '소리센서  %1  ',\n                CODEino_get_light_status: '빛센서  %1  ',\n                CODEino_is_button_pressed: ' 보드의  %1  ',\n                CODEino_get_accelerometer_direction: ' 3축 가속도센서  %1  ',\n                CODEino_get_accelerometer_value: ' 3축 가속도센서  %1 축의 센서값 ',\n                CODEino_get_analog_value: '아날로그 %1 센서의 값',\n\n                CODEino_default_neopixel_on: '기본 네오픽셀을 %1(으)로 켜기 %2',\n                CODEino_default_neopixel_setBrightness: '기본 네오픽셀의 밝기를 %1(으)로 설정%2',\n                CODEino_default_neopixel_off: '기본 네오픽셀을 끄기 %1',\n                CODEino_default_buzzer: '기본 부저를 %1옥타브 %2음으로 %3초 연주하기%4',\n                CODEino_custom_buzzer: '%1번핀 부저를 %2옥타브 %3음으로 %4초 연주하기%5',\n\n                CODEino_custom_neopixel_on: '네오픽셀을 %1번 핀에 등록%2',\n                CODEino_custom_neopixel_setBrightness: '네오픽셀의 밝기를 %1(으)로 설정%2',\n                CODEino_custom_neopixel_off: '네오픽셀을 모두 끄기 %1',\n\n                CODEino_custom_neopixel_set_led_color: '네오픽셀 %1번째 LED를 %2로 설정%3',\n                CODEino_custom_neopixel_set_led_off: '네오픽셀 %1번째 LED를 끄기%2',\n\n                CODEino_set_servo: '%1번 핀의 서보모터를 %2의 각도로 정하기%3',\n                CODEino_get_ultrasonic: '초음파센서(Trig:%1, Echo:%2)의 값',\n            },\n            Blocks: {\n                CODEino_get_sensor_number_0: '0',\n                CODEino_get_sensor_number_1: '1',\n                CODEino_get_sensor_number_2: '2',\n                CODEino_get_sensor_number_3: '3',\n                CODEino_get_sensor_number_4: '4',\n                CODEino_get_sensor_number_5: '5',\n                CODEino_get_sensor_number_6: '6',\n                CODEino_sensor_name_0: '소리',\n                CODEino_sensor_name_1: '빛',\n                CODEino_sensor_name_2: '슬라이더',\n                CODEino_sensor_name_3: '저항-A',\n                CODEino_sensor_name_4: '저항-B',\n                CODEino_sensor_name_5: '저항-C',\n                CODEino_sensor_name_6: '저항-D',\n                CODEino_string_1: ' 센서값 ',\n                CODEino_string_2: ' 보드의 ',\n                CODEino_string_3: '버튼누름',\n                CODEino_string_4: 'A 연결됨',\n                CODEino_string_5: 'B 연결됨',\n                CODEino_string_6: 'C 연결됨',\n                CODEino_string_7: 'D 연결됨',\n                CODEino_string_8: ' 3축 가속도센서 ',\n                CODEino_string_9: '축의 센서값 ',\n                CODEino_string_10: '소리센서 ',\n                CODEino_string_11: '소리큼',\n                CODEino_string_12: '소리작음',\n                CODEino_string_13: '빛센서 ',\n                CODEino_string_14: '밝음',\n                CODEino_string_15: '어두움',\n                CODEino_string_16: '왼쪽 기울임',\n                CODEino_string_17: '오른쪽 기울임',\n                CODEino_string_18: '위쪽 기울임',\n                CODEino_string_19: '아래쪽 기울임',\n                CODEino_string_20: '뒤집힘',\n                CODEino_accelerometer_X: 'X',\n                CODEino_accelerometer_Y: 'Y',\n                CODEino_accelerometer_Z: 'Z',\n                CODEino_led_red: '빨강',\n                CODEino_led_green: '초록',\n                CODEino_led_blue: '파랑',\n            },\n            Device: {\n                CODEino: '코드이노',\n            },\n            Menus: {\n                codeino: '코드이노',\n            },\n        },\n        en: {\n            template: {\n                CODEino_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                CODEino_get_digital_value: 'Digital %1 Pin value  ',\n                CODEino_set_digital_value: 'Digital %1 Pin %2 %3',\n                CODEino_set_pwm_value: 'Digital %1 Pin %2 %3',\n                CODEino_toggle_led: 'Digital %1 Pin %2 %3',\n                CODEino_toggle_pwm: 'Digital %1 Pin %2 %3',\n                CODEino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n                CODEino_set_rgb_value: 'Set color LED %1 by %2 %3',\n                CODEino_set_rgb_add_value: 'Add color LED %1 by %2 %3',\n                CODEino_set_rgb_off: 'Turn off LED %1',\n                CODEino_set__led_by_rgb: 'Turn on color LED, Red %1 Green %2 Blue %3 %4',\n                CODEino_rgb_set_color: 'Select %1 for color LED %2',\n                CODEino_led_by_value: 'Turn on LED %1',\n                CODEino_get_sensor_number: '%1  ',\n                CODEino_get_named_sensor_value: '  %1  Sensor value ',\n                CODEino_get_sound_status: 'Sound is  %1  ',\n                CODEino_get_light_status: 'Light is  %1  ',\n                CODEino_is_button_pressed: ' Operation  %1  ',\n                CODEino_get_accelerometer_direction: ' 3-AXIS Accelerometer  %1  ',\n                CODEino_get_accelerometer_value: ' 3-AXIS Accelerometer  %1 -axis value ',\n                CODEino_get_analog_value: 'Analog %1 Sensor value',\n\n                CODEino_default_neopixel_on: 'Default Neopixel ON %1 %2',\n                CODEino_default_neopixel_setBrightness: 'Set Default Neopixel-brightness %1 %2',\n                CODEino_default_neopixel_off: 'Default Neopixel OFF %1',\n                CODEino_default_buzzer:\n                    'Play the default buzzer in a %1 octave %2 notes for %3 seconds %4',\n                CODEino_custom_buzzer:\n                    'Play the buzzer on %1pin in a %2 octave %3 notes for %4 seconds %5',\n\n                CODEino_custom_neopixel_on: 'Set Neopixel on %1pin%2',\n                CODEino_custom_neopixel_setBrightness: 'Set Neopixel-brightness %1 %2',\n                CODEino_custom_neopixel_off: 'Set Neopixel OFF %1',\n\n                CODEino_custom_neopixel_set_led_color: 'Set Neopixel %1LED to %2 %3',\n                CODEino_custom_neopixel_set_led_off: 'Set Neopixel %1LED OFF %2',\n\n                CODEino_set_servo: 'Set servo in %1 to degree %2 %3',\n                CODEino_get_ultrasonic: 'Get value of Ultrasonic(Trig:%1, Echo:%2)',\n            },\n            Blocks: {\n                CODEino_get_sensor_number_0: '0',\n                CODEino_get_sensor_number_1: '1',\n                CODEino_get_sensor_number_2: '2',\n                CODEino_get_sensor_number_3: '3',\n                CODEino_get_sensor_number_4: '4',\n                CODEino_get_sensor_number_5: '5',\n                CODEino_get_sensor_number_6: '6',\n                CODEino_sensor_name_0: 'Sound',\n                CODEino_sensor_name_1: 'Light',\n                CODEino_sensor_name_2: 'Slider',\n                CODEino_sensor_name_3: 'resistance-A',\n                CODEino_sensor_name_4: 'resistance-B',\n                CODEino_sensor_name_5: 'resistance-C',\n                CODEino_sensor_name_6: 'resistance-D',\n                CODEino_string_1: ' Sensor value ',\n                CODEino_string_2: ' Operation ',\n                CODEino_string_3: 'Push button',\n                CODEino_string_4: 'Connected A',\n                CODEino_string_5: 'Connected B',\n                CODEino_string_6: 'Connected C',\n                CODEino_string_7: 'Connected D',\n                CODEino_string_8: ' 3-AXIS Accelerometer ',\n                CODEino_string_9: '-axis value ',\n                CODEino_string_10: 'Sound is ',\n                CODEino_string_11: 'Great',\n                CODEino_string_12: 'Small',\n                CODEino_string_13: 'Light is ',\n                CODEino_string_14: 'Bright',\n                CODEino_string_15: 'Dark',\n                CODEino_string_16: 'Left tilt',\n                CODEino_string_17: 'Right tilt',\n                CODEino_string_18: 'Front tilt',\n                CODEino_string_19: 'Rear tilt',\n                CODEino_string_20: 'Reverse',\n                CODEino_accelerometer_X: 'X',\n                CODEino_accelerometer_Y: 'Y',\n                CODEino_accelerometer_Z: 'Z',\n                CODEino_led_red: 'Red',\n                CODEino_led_green: 'Green',\n                CODEino_led_blue: 'Blue',\n            },\n            Device: {\n                CODEino: 'CODEino',\n            },\n            Menus: {\n                codeino: 'CODEino',\n            },\n        },\n    };\n};\nEntry.CODEino.blockMenuBlocks = [\n    'CODEino_get_sensor_number',\n    'CODEino_get_named_sensor_value',\n    'CODEino_get_sound_status',\n    'CODEino_get_light_status',\n    'CODEino_is_button_pressed',\n    'CODEino_get_accelerometer_direction',\n    'CODEino_get_accelerometer_value',\n\n    'CODEino_get_digital_value',\n    'CODEino_set_digital_value',\n\n    'CODEino_set_pwm_value',\n    'CODEino_get_analog_value',\n    'CODEino_convert_scale',\n\n    'CODEino_default_neopixel_on',\n    'CODEino_default_neopixel_setBrightness',\n    'CODEino_default_neopixel_off',\n    'CODEino_default_buzzer',\n    'CODEino_custom_buzzer',\n\n    'CODEino_led_by_value',\n    'CODEino_set_rgb_off',\n    'CODEino_set__led_by_rgb',\n    'CODEino_rgb_set_color',\n    'CODEino_set_rgb_value',\n    'CODEino_set_rgb_add_value',\n\n    'CODEino_custom_neopixel_on',\n    'CODEino_custom_neopixel_off',\n    'CODEino_custom_neopixel_setBrightness',\n\n    'CODEino_custom_neopixel_set_led_color',\n    'CODEino_custom_neopixel_set_led_off',\n\n    'CODEino_get_ultrasonic',\n    'CODEino_set_servo',\n];\nEntry.CODEino.getBlocks = function() {\n    return {\n        CODEino_get_sensor_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', 'A0'],\n                        ['1', 'A1'],\n                        ['2', 'A2'],\n                        ['3', 'A3'],\n                        ['4', 'A4'],\n                        ['5', 'A5'],\n                        ['6', 'A6'],\n                    ],\n                    value: 'A0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        CODEino_get_named_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CODEino_sensor_name_0, '0'],\n                        [Lang.Blocks.CODEino_sensor_name_1, '1'],\n                        [Lang.Blocks.CODEino_sensor_name_2, '2'],\n                        [Lang.Blocks.CODEino_sensor_name_3, '3'],\n                        [Lang.Blocks.CODEino_sensor_name_4, '4'],\n                        [Lang.Blocks.CODEino_sensor_name_5, '5'],\n                        [Lang.Blocks.CODEino_sensor_name_6, '6'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_get_named_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CODEino_sensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG);\n                var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                var scope = script.executor.scope;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (!scope.isStart) {\n                    scope.isStart = true;\n                    scope.stamp = nowTime;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.ANALOG] = {\n                        port: port,\n                        time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG),\n                    };\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                } else if (hardwareTime && hardwareTime === scope.stamp) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    return ANALOG ? ANALOG[port] || 0 : 0;\n                } else if (nowTime - scope.stamp > 64) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    return ANALOG ? ANALOG[port] || 0 : 0;\n                } else {\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                }\n            },\n        },\n        CODEino_get_sound_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CODEino_string_11, 'GREAT'],\n                        [Lang.Blocks.CODEino_string_12, 'SMALL'],\n                    ],\n                    value: 'GREAT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_get_sound_status',\n            },\n            paramsKeyMap: {\n                STATUS: 0,\n            },\n            class: 'CODEino_sensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var value1 = script.getField('STATUS', script);\n                var value2 = 1;\n                var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG);\n                var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                var scope = script.executor.scope;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (!scope.isStart) {\n                    scope.isStart = true;\n                    scope.stamp = nowTime;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.ANALOG] = {\n                        port: 0,\n                        time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG),\n                    };\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                } else if (hardwareTime && hardwareTime === scope.stamp) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    if (value1 == 'GREAT') return ANALOG[0] > 600 ? 1 : 0;\n                    else return ANALOG[0] <= 600 ? 1 : 0;\n                } else if (nowTime - scope.stamp > 64) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    if (value1 == 'GREAT') return ANALOG[0] > 600 ? 1 : 0;\n                    else return ANALOG[0] <= 600 ? 1 : 0;\n                } else {\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                }\n            },\n        },\n        CODEino_get_light_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CODEino_string_14, 'BRIGHT'],\n                        [Lang.Blocks.CODEino_string_15, 'DARK'],\n                    ],\n                    value: 'BRIGHT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_get_light_status',\n            },\n            paramsKeyMap: {\n                STATUS: 0,\n            },\n            class: 'CODEino_sensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var value1 = script.getField('STATUS', script);\n                var value2 = 1;\n                var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG);\n                var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                var scope = script.executor.scope;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (!scope.isStart) {\n                    scope.isStart = true;\n                    scope.stamp = nowTime;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.ANALOG] = {\n                        port: 1,\n                        time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG),\n                    };\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                } else if (hardwareTime && hardwareTime === scope.stamp) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    if (value1 == 'GREAT') return ANALOG[value2] < 800 ? 1 : 0;\n                    else return ANALOG[value2] <= 800 ? 1 : 0;\n                } else if (nowTime - scope.stamp > 64) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    if (value1 == 'GREAT') return ANALOG[value2] < 800 ? 1 : 0;\n                    else return ANALOG[value2] <= 800 ? 1 : 0;\n                } else {\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                }\n            },\n        },\n        CODEino_is_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CODEino_string_3, '4'],\n                        [Lang.Blocks.CODEino_string_4, '17'],\n                        [Lang.Blocks.CODEino_string_5, '18'],\n                        [Lang.Blocks.CODEino_string_6, '19'],\n                        [Lang.Blocks.CODEino_string_7, '20'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_is_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CODEino_sensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getNumberField('PORT', script);\n                if (port < 10) {\n                    var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.DIGITAL);\n                    var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                    var scope = script.executor.scope;\n                    var DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!scope.isStart) {\n                        scope.isStart = true;\n                        scope.stamp = nowTime;\n                        if (!Entry.hw.sendQueue['GET']) {\n                            Entry.hw.sendQueue['GET'] = {};\n                        }\n                        Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.DIGITAL] = {\n                            port: 4,\n                            time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.DIGITAL),\n                        };\n                        throw new Entry.Utils.AsyncError();\n                        return;\n                    } else if (hardwareTime && hardwareTime === scope.stamp) {\n                        delete scope.isStart;\n                        delete scope.stamp;\n                        return DIGITAL ? !(DIGITAL[port] || 0) : 0;\n                    } else if (nowTime - scope.stamp > 64) {\n                        delete scope.isStart;\n                        delete scope.stamp;\n                        return DIGITAL ? !(DIGITAL[port] || 0) : 0;\n                    } else {\n                        throw new Entry.Utils.AsyncError();\n                        return;\n                    }\n                } else {\n                    var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG);\n                    var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                    var scope = script.executor.scope;\n                    var ANALOG = Entry.hw.portData.ANALOG;\n                    if (!scope.isStart) {\n                        scope.isStart = true;\n                        scope.stamp = nowTime;\n                        if (!Entry.hw.sendQueue['GET']) {\n                            Entry.hw.sendQueue['GET'] = {};\n                        }\n                        Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.ANALOG] = {\n                            port: port - 14,\n                            time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG),\n                        };\n                        throw new Entry.Utils.AsyncError();\n                        return;\n                    } else if (hardwareTime && hardwareTime === scope.stamp) {\n                        delete scope.isStart;\n                        delete scope.stamp;\n                        return ANALOG[port - 14] < 1000 ? 1 : 0;\n                    } else if (nowTime - scope.stamp > 64) {\n                        delete scope.isStart;\n                        delete scope.stamp;\n                        return ANALOG[port - 14] < 1000 ? 1 : 0;\n                    } else {\n                        throw new Entry.Utils.AsyncError();\n                        return;\n                    }\n                }\n            },\n        },\n        CODEino_get_accelerometer_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CODEino_string_16, 'LEFT'],\n                        [Lang.Blocks.CODEino_string_17, 'RIGHT'],\n                        [Lang.Blocks.CODEino_string_18, 'FRONT'],\n                        [Lang.Blocks.CODEino_string_19, 'REAR'],\n                        [Lang.Blocks.CODEino_string_20, 'REVERSE'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_get_accelerometer_direction',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'CODEino_sensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var value1 = script.getField('DIRECTION', script);\n                var port = 0;\n                var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG);\n                var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                var scope = script.executor.scope;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value4 = 265;\n                var value5 = 402;\n                var value6 = -90;\n                var value7 = 90;\n                var result;\n                if (value1 == 'LEFT' || value1 == 'RIGHT') port = 3;\n                else if (value1 == 'FRONT' || value1 == 'REAR') port = 4;\n                else if (value1 == 'REVERSE') port = 5;\n\n                if (!scope.isStart) {\n                    scope.isStart = true;\n                    scope.stamp = nowTime;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.ANALOG] = {\n                        port: port,\n                        time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG),\n                    };\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                } else if (hardwareTime && hardwareTime === scope.stamp) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    result = ANALOG[port];\n                    result -= value4;\n                    result = result * ((value7 - value6) / (value5 - value4));\n                    result += value6;\n                    result = Math.min(value7, result);\n                    result = Math.max(value6, result);\n                    result = Math.round(result);\n                    if (value1 == 'LEFT' || value1 == 'REAR') return result < -30 ? 1 : 0;\n                    else if (value1 == 'RIGHT' || value1 == 'FRONT') return result > 30 ? 1 : 0;\n                    else if (value1 == 'REVERSE') return result < -50 ? 1 : 0;\n                } else if (nowTime - scope.stamp > 64) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    result = ANALOG[port];\n                    result -= value4;\n                    result = result * ((value7 - value6) / (value5 - value4));\n                    result += value6;\n                    result = Math.min(value7, result);\n                    result = Math.max(value6, result);\n                    result = Math.round(result);\n                    if (value1 == 'LEFT' || value1 == 'REAR') return result < -30 ? 1 : 0;\n                    else if (value1 == 'RIGHT' || value1 == 'FRONT') return result > 30 ? 1 : 0;\n                    else if (value1 == 'REVERSE') return result < -50 ? 1 : 0;\n                } else {\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                }\n            },\n        },\n        CODEino_get_accelerometer_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X', '3'],\n                        ['Y', '4'],\n                        ['Z', '5'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_get_accelerometer_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CODEino_sensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getNumberField('PORT', script);\n                var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG);\n                var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                var scope = script.executor.scope;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var result = 0;\n                if (!scope.isStart) {\n                    scope.isStart = true;\n                    scope.stamp = nowTime;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.ANALOG] = {\n                        port: port,\n                        time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG),\n                    };\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                } else if (hardwareTime && hardwareTime === scope.stamp) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    result = ANALOG[port];\n                    result = (result - 333) * 1.46;\n                    result = Math.min(90, result);\n                    result = Math.max(-90, result);\n                    return Math.round(result);\n                } else if (nowTime - scope.stamp > 64) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    result = ANALOG[port];\n                    result = (result - 333) * 1.46;\n                    result = Math.min(90, result);\n                    result = Math.max(-90, result);\n                    return Math.round(result);\n                } else {\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                }\n            },\n        },\n        CODEino_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CODEino_analogSensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG);\n                var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                var scope = script.executor.scope;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (!scope.isStart) {\n                    scope.isStart = true;\n                    scope.stamp = nowTime;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.ANALOG] = {\n                        port: port,\n                        time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ANALOG),\n                    };\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                } else if (hardwareTime && hardwareTime === scope.stamp) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    return ANALOG ? ANALOG[port] || 0 : 0;\n                } else if (nowTime - scope.stamp > 64) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    return ANALOG ? ANALOG[port] || 0 : 0;\n                } else {\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                }\n            },\n        },\n        CODEino_get_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    accept: 'string',\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_get_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CODEino_digitalSensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var nowTime = Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.DIGITAL);\n                var hardwareTime = Entry.hw.portData['TIME'] || 0;\n                var scope = script.executor.scope;\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!scope.isStart) {\n                    scope.isStart = true;\n                    scope.stamp = nowTime;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.CODEino.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.DIGITAL),\n                    };\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                } else if (hardwareTime && hardwareTime === scope.stamp) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else if (nowTime - scope.stamp > 64) {\n                    delete scope.isStart;\n                    delete scope.stamp;\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    throw new Entry.Utils.AsyncError();\n                    return;\n                }\n            },\n        },\n        CODEino_set_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    accept: 'string',\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '13',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, '255'],\n                        [Lang.Blocks.ARDUINO_off, '0'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '255', null],\n                type: 'CODEino_set_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CODEino_digitalSensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberField('VALUE');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                if (Entry.CODEino.LAST_ORDER_PORT === port) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = port;\n                }\n\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.CODEino.sensorTypes.DIGITAL,\n                    data: value,\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.DIGITAL),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        CODEino_set_pwm_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                        params: ['3'],\n                    },\n                    {\n                        type: 'arduino_text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'CODEino_set_pwm_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CODEino_analogSensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                if (Entry.CODEino.LAST_ORDER_PORT === port) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = port;\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.CODEino.sensorTypes.PWM,\n                    data: value,\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.PWM),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        CODEino_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'CODEino_get_analog_value',\n                        value: '2',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'CODEino_convert_scale',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'CODEino_analogSensor',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n                return Math.round(result);\n            },\n        },\n        CODEino_set_rgb_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CODEino_led_red, '17'],\n                        [Lang.Blocks.CODEino_led_green, '18'],\n                        [Lang.Blocks.CODEino_led_blue, '19'],\n                    ],\n                    value: '17',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'CODEino_set_rgb_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CODEino_RGBLED_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getNumberField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n\n                value = Math.min(255, value);\n                value = Math.max(0, value);\n                Entry.CODEino.LED_VALUES[port - 17] = value;\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                if (Entry.CODEino.LAST_ORDER_PORT === 18) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = 18;\n                }\n                Entry.hw.sendQueue['SET'][18] = {\n                    type: Entry.CODEino.sensorTypes.RGBLED_PIN,\n                    data: {\n                        r: Entry.CODEino.LED_VALUES[0],\n                        g: Entry.CODEino.LED_VALUES[1],\n                        b: Entry.CODEino.LED_VALUES[2],\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.RGBLED_PIN),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        CODEino_set_rgb_add_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CODEino_led_red, '17'],\n                        [Lang.Blocks.CODEino_led_green, '18'],\n                        [Lang.Blocks.CODEino_led_blue, '19'],\n                    ],\n                    value: '17',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                type: 'CODEino_set_rgb_add_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CODEino_RGBLED_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var port = script.getNumberField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n\n                value += Entry.CODEino.LED_VALUES[port - 17];\n                value = Math.min(255, value);\n                value = Math.max(0, value);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                if (Entry.CODEino.LAST_ORDER_PORT === 18) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = 18;\n                }\n                Entry.hw.sendQueue['SET'][18] = {\n                    type: Entry.CODEino.sensorTypes.RGBLED_PIN,\n                    data: {\n                        r: Entry.CODEino.LED_VALUES[0],\n                        g: Entry.CODEino.LED_VALUES[1],\n                        b: Entry.CODEino.LED_VALUES[2],\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.RGBLED_PIN),\n                };\n                return script.callReturn();\n            },\n        },\n        CODEino_rgb_set_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_rgb_set_color',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'CODEino_RGBLED_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var value = script.getStringField('VALUE');\n                var sq = Entry.hw.sendQueue;\n\n                Entry.CODEino.LED_VALUES = [\n                    parseInt(value.substr(1, 2), 16),\n                    parseInt(value.substr(3, 2), 16),\n                    parseInt(value.substr(5, 2), 16),\n                ];\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                if (Entry.CODEino.LAST_ORDER_PORT === 18) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = 18;\n                }\n                sq['SET'][18] = {\n                    type: Entry.CODEino.sensorTypes.RGBLED_PIN,\n                    data: {\n                        r: Entry.CODEino.LED_VALUES[0],\n                        g: Entry.CODEino.LED_VALUES[1],\n                        b: Entry.CODEino.LED_VALUES[2],\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.RGBLED_PIN),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_set_rgb_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_set_rgb_off',\n            },\n            class: 'CODEino_RGBLED_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                Entry.CODEino.LED_VALUES = [0, 0, 0];\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                if (Entry.CODEino.LAST_ORDER_PORT === 18) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = 18;\n                }\n                sq['SET'][18] = {\n                    type: Entry.CODEino.sensorTypes.RGBLED_PIN,\n                    data: {\n                        r: Entry.CODEino.LED_VALUES[0],\n                        g: Entry.CODEino.LED_VALUES[1],\n                        b: Entry.CODEino.LED_VALUES[2],\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.RGBLED_PIN),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        CODEino_set__led_by_rgb: {\n            // r값 g값 b값 수동으로 주는 블록\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'CODEino_set__led_by_rgb',\n            },\n            paramsKeyMap: {\n                rValue: 0,\n                gValue: 1,\n                bValue: 2,\n            },\n            class: 'CODEino_RGBLED_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                let values = [\n                    script.getNumberValue('rValue'),\n                    script.getNumberValue('gValue'),\n                    script.getNumberValue('bValue'),\n                ];\n                for (let i = 0; i < values.length; ++i) {\n                    if (values[i] >= 0 && values[i] <= 255) {\n                        Entry.CODEino.LED_VALUES[i] = values[i];\n                    }\n                }\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                if (Entry.CODEino.LAST_ORDER_PORT === 18) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = 18;\n                }\n                sq['SET'][18] = {\n                    type: Entry.CODEino.sensorTypes.RGBLED_PIN,\n                    data: {\n                        r: Entry.CODEino.LED_VALUES[0],\n                        g: Entry.CODEino.LED_VALUES[1],\n                        b: Entry.CODEino.LED_VALUES[2],\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.RGBLED_PIN),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_led_by_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_led_by_value',\n            },\n            class: 'CODEino_RGBLED_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                Entry.CODEino.LED_VALUES = [100, 100, 100];\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                if (Entry.CODEino.LAST_ORDER_PORT === 18) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = 18;\n                }\n                sq['SET'][18] = {\n                    type: Entry.CODEino.sensorTypes.RGBLED_PIN,\n                    data: {\n                        r: Entry.CODEino.LED_VALUES[0],\n                        g: Entry.CODEino.LED_VALUES[1],\n                        b: Entry.CODEino.LED_VALUES[2],\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.RGBLED_PIN),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_get_number_sensor_value: {\n            parent: 'arduino_get_number_sensor_value',\n            isNotFor: ['CODEino'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'CODEino_get_number_sensor_value',\n            },\n            class: 'arduino_value',\n            syntax: { js: [], py: ['CODEino.get_number_sensor_value(%1)'] },\n        },\n        CODEino_toggle_led: {\n            parent: 'arduino_toggle_led',\n            isNotFor: ['CODEino'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'CODEino_toggle_led',\n            },\n            class: 'arduino_set',\n            syntax: { js: [], py: ['CODEino.toggle_led(%1)'] },\n        },\n        CODEino_toggle_pwm: {\n            parent: 'arduino_toggle_pwm',\n            isNotFor: ['CODEino'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'arduino_text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'CODEino_toggle_pwm',\n            },\n            class: 'arduino_set',\n            syntax: { js: [], py: ['CODEino.toggle_pwm(%1, %2)'] },\n        },\n\n        CODEino_default_neopixel_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_default_neopixel_on',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'CODEino_default_neopixel_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var value = script.getStringField('VALUE');\n                var sq = Entry.hw.sendQueue;\n                var port = 11;\n\n                let red = parseInt(value.substr(1, 2), 16);\n                let green = parseInt(value.substr(3, 2), 16);\n                let blue = parseInt(value.substr(5, 2), 16);\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                Entry.CODEino.DEFAULT_NEOPIXEL_RED_VALUE = red;\n                Entry.CODEino.DEFAULT_NEOPIXEL_GREEN_VALUE = green;\n                Entry.CODEino.DEFAULT_NEOPIXEL_BLUE_VALUE = blue;\n\n                if (Entry.CODEino.LAST_ORDER_PORT === port) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = port;\n                }\n\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.DEFAULT_NEOPIXEL,\n                    data: {\n                        rValue: Entry.CODEino.DEFAULT_NEOPIXEL_RED_VALUE,\n                        gValue: Entry.CODEino.DEFAULT_NEOPIXEL_GREEN_VALUE,\n                        bValue: Entry.CODEino.DEFAULT_NEOPIXEL_BLUE_VALUE,\n                        brightness: Entry.CODEino.DEFAULT_NEOPIXEL_BRIGHTNESS_VALUE,\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.DEFAULT_NEOPIXEL),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_default_neopixel_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_default_neopixel_off',\n            },\n            class: 'CODEino_default_neopixel_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var port = 11;\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                Entry.CODEino.DEFAULT_NEOPIXEL_RED_VALUE = 0;\n                Entry.CODEino.DEFAULT_NEOPIXEL_GREEN_VALUE = 0;\n                Entry.CODEino.DEFAULT_NEOPIXEL_BLUE_VALUE = 0;\n\n                if (Entry.CODEino.LAST_ORDER_PORT === port) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = port;\n                }\n\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.DEFAULT_NEOPIXEL,\n                    data: {\n                        rValue: Entry.CODEino.DEFAULT_NEOPIXEL_RED_VALUE,\n                        gValue: Entry.CODEino.DEFAULT_NEOPIXEL_GREEN_VALUE,\n                        bValue: Entry.CODEino.DEFAULT_NEOPIXEL_BLUE_VALUE,\n                        brightness: Entry.CODEino.DEFAULT_NEOPIXEL_BRIGHTNESS_VALUE,\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.DEFAULT_NEOPIXEL),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_default_neopixel_setBrightness: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['22'],\n                    },\n                    null,\n                ],\n                type: 'CODEino_default_neopixel_setBrightness',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'CODEino_default_neopixel_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE', script);\n                var sq = Entry.hw.sendQueue;\n\n                var port = 11;\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                Entry.CODEino.DEFAULT_NEOPIXEL_BRIGHTNESS_VALUE = value;\n\n                if (Entry.CODEino.LAST_ORDER_PORT === port) {\n                    Entry.hw.update();\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = port;\n                }\n\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.DEFAULT_NEOPIXEL,\n                    data: {\n                        rValue: Entry.CODEino.DEFAULT_NEOPIXEL_RED_VALUE,\n                        gValue: Entry.CODEino.DEFAULT_NEOPIXEL_GREEN_VALUE,\n                        bValue: Entry.CODEino.DEFAULT_NEOPIXEL_BLUE_VALUE,\n                        brightness: Entry.CODEino.DEFAULT_NEOPIXEL_BRIGHTNESS_VALUE,\n                    },\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.DEFAULT_NEOPIXEL),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_default_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'CODEino_octave_list',\n                    },\n                    {\n                        type: 'CODEino_tone_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'CODEino_default_buzzer',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                NOTE: 1,\n                DURATION: 2,\n            },\n            class: 'CODEino_default_buzzer_mode',\n            isNotFor: ['CODEino'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12;\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.CODEino.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (Entry.CODEino.LAST_ORDER_PORT === port) {\n                        Entry.hw.update();\n                    } else {\n                        Entry.CODEino.LAST_ORDER_PORT = port;\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.CODEino.sensorTypes.DEFAULT_BUZZER,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.CODEino.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.CODEino.sensorTypes.DEFAULT_BUZZER,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.CODEino.sensorTypes.DEFAULT_BUZZER,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        CODEino_custom_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    accept: 'string',\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                    ],\n                    value: '12',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'CODEino_octave_list',\n                    },\n                    {\n                        type: 'CODEino_tone_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'CODEino_custom_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OCTAVE: 1,\n                NOTE: 2,\n                DURATION: 3,\n            },\n            class: 'CODEino_custom_buzzer_mode',\n            isNotFor: ['CODEino'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT');\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.CODEino.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (Entry.CODEino.LAST_ORDER_PORT === port) {\n                        Entry.hw.update();\n                    } else {\n                        Entry.CODEino.LAST_ORDER_PORT = port;\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.CODEino.sensorTypes.CUSTOM_BUZZER,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.CODEino.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.CODEino.sensorTypes.CUSTOM_BUZZER,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.CODEino.sensorTypes.CUSTOM_BUZZER,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        CODEino_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        CODEino_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        CODEino_custom_neopixel_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    accept: 'string',\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_custom_neopixel_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CODEino_custom_neopixel_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT');\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_POWER,\n                    data: {\n                        isOn: 1,\n                        brightness: 22,\n                    },\n                    time: Entry.CODEino.getSensorTime(\n                        Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_POWER\n                    ),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_custom_neopixel_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_custom_neopixel_off',\n            },\n            class: 'CODEino_custom_neopixel_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                var port = Entry.CODEino.customNeoPixelPin + 9;\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_POWER,\n                    data: {\n                        isOn: 0,\n                        brightness: Entry.CODEino.CUSTOM_NEOPIXEL_BRIGHTNESS_VALUE,\n                    },\n                    time: Entry.CODEino.getSensorTime(\n                        Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_POWER\n                    ),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_custom_neopixel_setBrightness: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['22'],\n                    },\n                    null,\n                ],\n                type: 'CODEino_custom_neopixel_setBrightness',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'CODEino_custom_neopixel_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE', script);\n                var sq = Entry.hw.sendQueue;\n                var port = Entry.CODEino.customNeoPixelPin + 10;\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                Entry.CODEino.CUSTOM_NEOPIXEL_BRIGHTNESS_VALUE = value;\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_POWER,\n                    data: {\n                        isOn: 2,\n                        brightness: Entry.CODEino.CUSTOM_NEOPIXEL_BRIGHTNESS_VALUE,\n                    },\n                    time: Entry.CODEino.getSensorTime(\n                        Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_POWER\n                    ),\n                };\n\n                return script.callReturn();\n            },\n        },\n        CODEino_custom_neopixel_set_led_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    accept: 'string',\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                        ['9', '8'],\n                        ['10', '9'],\n                        ['11', '10'],\n                        ['12', '11'],\n                        ['13', '12'],\n                        ['14', '13'],\n                        ['15', '14'],\n                        ['16', '15'],\n                        ['17', '16'],\n                        ['18', '17'],\n                        ['19', '18'],\n                        ['20', '19'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_custom_neopixel_set_led_color',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },\n            class: 'CODEino_custom_neopixel_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                let led = script.getNumberValue('LED', script);\n\n                var value = script.getStringField('COLOR');\n                var sq = Entry.hw.sendQueue;\n                var port = Entry.CODEino.customNeoPixelPin + led;\n\n                let red = parseInt(value.substr(1, 2), 16);\n                let green = parseInt(value.substr(3, 2), 16);\n                let blue = parseInt(value.substr(5, 2), 16);\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_LED_HANDLE,\n                    data: {\n                        r: red,\n                        g: green,\n                        b: blue,\n                    },\n                    time: Entry.CODEino.getSensorTime(\n                        Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_LED_HANDLE\n                    ),\n                };\n                return script.callReturn();\n            },\n        },\n        CODEino_custom_neopixel_set_led_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                        ['9', '8'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_custom_neopixel_set_led_off',\n            },\n            paramsKeyMap: {\n                LED: 0,\n            },\n            class: 'CODEino_custom_neopixel_mode',\n            isNotFor: ['CODEino'],\n            func: function(sprite, script) {\n                let led = script.getNumberValue('LED', script);\n\n                var sq = Entry.hw.sendQueue;\n                var port = Entry.CODEino.customNeoPixelPin + led;\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_LED_HANDLE,\n                    data: {\n                        r: 0,\n                        g: 0,\n                        b: 0,\n                    },\n                    time: Entry.CODEino.getSensorTime(\n                        Entry.CODEino.sensorTypes.CUSTOM_NEOPIXEL_LED_HANDLE\n                    ),\n                };\n                return script.callReturn();\n            },\n        },\n        CODEino_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    accept: 'string',\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                    ],\n                    value: '7',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'CODEino_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CODEino_servo',\n            isNotFor: ['CODEino'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                if (Entry.CODEino.LAST_ORDER_PORT === port) {\n                    Entry.hw.update();\n                    delete Entry.hw.sendQueue['SET'][port];\n                } else {\n                    Entry.CODEino.LAST_ORDER_PORT = port;\n                }\n                sq.SET[port] = {\n                    type: Entry.CODEino.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.SERVO_PIN),\n                };\n                Entry.hw.update();\n                return script.callReturn();\n            },\n        },\n\n        CODEino_get_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    accept: 'string',\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                    ],\n                    value: '2',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    accept: 'string',\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                    ],\n                    value: '3',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CODEino_get_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'CODEino_ultrasonic',\n            isNotFor: ['CODEino'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.CODEino.sensorTypes.ULTRASONIC,\n                    data: port2,\n                    time: Entry.CODEino.getSensorTime(Entry.CODEino.sensorTypes.ULTRASONIC),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.CODEino;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_codestar.js",
    "content": "'use strict';\n\nEntry.Codestar = {\n    id: 'B.1',\n    name: 'codestar',\n    url: 'http://codestar.co.kr',\n    imageName: 'codestar.png',\n    title: {\n        ko: '코드스타',\n        en: 'Codestar',\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/codestar.png',\n        width: 333,\n        height: 409,\n        listPorts: {\n            '13': { name: '진동모터', type: 'output', pos: { x: 0, y: 0 } },\n            tilt: { name: '기울기센서', type: 'input', pos: { x: 0, y: 0 } },\n        },\n        ports: {\n            '7': { name: '빨간색', type: 'output', pos: { x: 238, y: 108 } },\n            '8': { name: '파란색', type: 'output', pos: { x: 265, y: 126 } },\n            '9': { name: '3색 빨간색', type: 'output', pos: { x: 292, y: 34 } },\n            '10': { name: '3색 녹색', type: 'output', pos: { x: 292, y: 34 } },\n            '11': {\n                name: '3색 파란색',\n                type: 'output',\n                pos: { x: 292, y: 34 },\n            },\n            '12': { name: '버튼', type: 'input', pos: { x: 248, y: 142 } },\n            a0: { name: '왼쪽 벽감지', type: 'input', pos: { x: 24, y: 231 } },\n            a2: { name: '마이크', type: 'input', pos: { x: 225, y: 67 } },\n            a3: { name: '부저', type: 'output', pos: { x: 283, y: 105 } },\n            a4: {\n                name: '왼쪽 라인감지',\n                type: 'input',\n                pos: { x: 37, y: 353 },\n            },\n            a5: {\n                name: '오른쪽 라인감지',\n                type: 'input',\n                pos: { x: 50, y: 368 },\n            },\n            a6: { name: '조도센서', type: 'input', pos: { x: 273, y: 22 } },\n            a7: {\n                name: '오른쪽 벽감지',\n                type: 'input',\n                pos: { x: 103, y: 381 },\n            },\n            temperature: {\n                name: '온도센서',\n                type: 'input',\n                pos: { x: 311, y: 238 },\n            },\n            sonar: { name: '초음파센서', type: 'input', pos: { x: 7, y: 277 } },\n            leftwheel: {\n                name: '왼쪽 바퀴',\n                type: 'output',\n                pos: { x: 177, y: 370 },\n            },\n            rightwheel: {\n                name: '오른쪽 바퀴',\n                type: 'output',\n                pos: { x: 83, y: 218 },\n            },\n        },\n        mode: 'both',\n    },\n};\nEntry.Codestar.blockMenuBlocks = [\n    'codestar_color_single',\n    'codestar_3color',\n    'codestar_vibration',\n    'codestar_buzzer',\n    'codestar_buzzer_stop',\n    'codestar_drive',\n    'codestar_wheel',\n    'codestar_light',\n    'codestar_button',\n    'codestar_ir',\n    'codestar_sonar',\n    'codestar_mic',\n    'codestar_temperature',\n    'codestar_tilt',\n];\nEntry.Codestar.setLanguage = function() {\n    return {\n        ko: {\n            Menus: {\n                codestar: '코드스타',\n            },\n        },\n        en: {\n            Menus: {\n                codestar: 'Codestar',\n            },\n        },\n    };\n};\nEntry.Codestar.getBlocks = function() {\n    return {\n        //region codestar 코드스타\n        codestar_color_single: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '%1 LED %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빨간색', 7],\n                        ['파란색', 8],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, 'on'],\n                        [Lang.Blocks.ARDUINO_off, 'off'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [7, 'on', null],\n                type: 'codestar_color_single',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                ONOFF: 1,\n            },\n            class: 'codestar_output_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var onoff = script.getField('ONOFF');\n                var value = onoff == 'on' ? 255 : 0;\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n        },\n        codestar_3color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '3색 LED %1 밝기 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빨간색', 9],\n                        ['초록색', 10],\n                        ['파란색', 11],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [9, { type: 'number', params: [120] }, null],\n                type: 'codestar_3color',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'codestar_output_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n        },\n        codestar_vibration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '진동모터 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, 'on'],\n                        [Lang.Blocks.ARDUINO_off, 'off'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['on', null],\n                type: 'codestar_vibration',\n            },\n            paramsKeyMap: {\n                ONOFF: 0,\n            },\n            class: 'codestar_output_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var port = 13;\n                var onoff = script.getField('ONOFF');\n                var value = onoff == 'on' ? 255 : 0;\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n        },\n        codestar_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '부저 톤%1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['G3', 1],\n                        ['A3', 2],\n                        ['B3', 3],\n                        ['C4', 4],\n                        ['D4', 5],\n                        ['E4', 6],\n                        ['F4', 7],\n                        ['G4', 8],\n                        ['A4', 9],\n                        ['B4', 10],\n                        ['C5', 11],\n                        ['D5', 12],\n                        ['E5', 13],\n                        ['F5', 14],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [4, null],\n                type: 'codestar_buzzer',\n            },\n            paramsKeyMap: {\n                TONE: 0,\n            },\n            class: 'codestar_output_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var tone = script.getField('TONE');\n                Entry.hw.setDigitalPortValue(15, tone);\n                return script.callReturn();\n            },\n        },\n        codestar_buzzer_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '부저 중지 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'codestar_buzzer_stop',\n            },\n            paramsKeyMap: {},\n            class: 'codestar_output_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                Entry.hw.setDigitalPortValue(15, 24);\n                return script.callReturn();\n            },\n        },\n        codestar_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '서보모터 %1 모터값 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['D3', 'D3'],\n                        ['D5', 'D5'],\n                        ['D6', 'D6'],\n                        ['D9', 'D9'],\n                        ['D10', 'D10'],\n                        ['D11', 'D11'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['D3', { type: 'number', params: [90] }, null],\n                type: 'codestar_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'codestar_motor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var sq = Entry.hw.sendQueue;\n                sq.outport = script.getField('PORT');\n                sq.value = 0;\n                if (!isNaN(value)) {\n                    var tmp = value;\n                    if (value < 0) tmp = 0;\n                    if (value > 255) tmp = 255;\n                    sq.value = tmp;\n                }\n                return script.callReturn();\n            },\n        },\n        codestar_drive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '방향 %1 속도 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '0'],\n                        ['뒤로', '1'],\n                        ['왼쪽', '2'],\n                        ['오른쪽', '3'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0', { type: 'number', params: [100] }, null],\n                type: 'codestar_drive',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n            },\n            class: 'codestar_motor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var dir = Number(script.getField('DIRECTION'));\n                var id = 0;\n                //if(value == 0) value = 1;\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n\n                value = Math.round(value / 30);\n                //if(value == 0) value = 1;\n                var query = (id << 7) + (dir << 5) + value;\n                Entry.hw.setDigitalPortValue(14, query);\n                return script.callReturn();\n            },\n        },\n        codestar_wheel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '방향 %1 바퀴속도 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '0'],\n                        ['오른쪽', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0', { type: 'number', params: [100] }, null],\n                type: 'codestar_wheel',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n            },\n            class: 'codestar_motor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var dir = Number(script.getField('DIRECTION'));\n                var id = 1;\n                //if(value == 0)value = 1;\n                value = Math.round(value);\n                value = Math.max(value, -255);\n                value = Math.min(value, 255);\n                if (value < 0) {\n                    dir = 2 + dir;\n                    value *= -1;\n                }\n                value = Math.round(value / 30);\n                //if(value == 0) value = 1;\n                var query = (id << 7) + (dir << 5) + value;\n                Entry.hw.setDigitalPortValue(14, query);\n                return script.callReturn();\n            },\n        },\n        codestar_light: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '조도센서',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'codestar_light',\n            },\n            paramsKeyMap: {},\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('6');\n            },\n        },\n        codestar_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '버튼',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'codestar_button',\n            },\n            paramsKeyMap: {},\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                return Entry.hw.getDigitalPortValue('12');\n            },\n        },\n        codestar_ir: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: 'IR %1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                        ['A7', '7'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0'],\n                type: 'codestar_ir',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                return Entry.hw.getAnalogPortValue(port);\n            },\n        },\n        codestar_sonar: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '초음파센서',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'codestar_sonar',\n            },\n            paramsKeyMap: {},\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                return Entry.hw.portData.sonar;\n            },\n        },\n        codestar_variable_R: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '가변저항 %1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'codestar_variable_R',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                return Entry.hw.getAnalogPortValue(port);\n            },\n        },\n        codestar_mic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '마이크',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'codestar_mic',\n            },\n            paramsKeyMap: {},\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue('2');\n            },\n        },\n        codestar_temperature: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '온도센서',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'codestar_temperature',\n            },\n            paramsKeyMap: {},\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                return Entry.hw.portData.temperature;\n            },\n        },\n        codestar_gyroscope: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '3축 자이로 %1 축 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', 'x'],\n                        ['y', 'y'],\n                        ['z', 'z'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['x', null],\n                type: 'codestar_gyroscope',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n            },\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var axis = script.getField('AXIS');\n                return Entry.hw.getAnalogPortValue('gyro_' + axis);\n            },\n        },\n        codestar_geomagnetic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '3축 지자기 %1 축 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', 'x'],\n                        ['y', 'y'],\n                        ['z', 'z'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['x', null],\n                type: 'codestar_geomagnetic',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n            },\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                var axis = script.getField('AXIS');\n                return Entry.hw.getAnalogPortValue('geo_' + axis);\n            },\n        },\n        codestar_irR: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: 'IR 리모콘',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'codestar_irR',\n            },\n            paramsKeyMap: {},\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                return Entry.hw.getDigitalPortValue('3');\n            },\n        },\n        codestar_tilt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '기울기센서',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'codestar_tilt',\n            },\n            paramsKeyMap: {},\n            class: 'codestar_input_sensor',\n            isNotFor: ['codestar'],\n            func: function(sprite, script) {\n                return Entry.hw.portData.tilt;\n            },\n        },\n        //endregion codestar 코드스타\n    };\n};\n\nmodule.exports = Entry.Codestar;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_codewiz.js",
    "content": "'use strict';\n\nEntry.CodeWiz = {\n    id: '1.12',\n    name: 'CodeWiz',\n    url: 'http://codable.co.kr/page/?pid=codewiz',\n    imageName: 'codewiz.png',\n    title: {\n        ko: '코드위즈',\n        en: 'CodeWiz',\n    },\n    setZero: function() {\n        Entry.hw.sendQueue = {\n            ORDER: {},\n            RESET: 1,\n        };\n        Entry.hw.update();\n        setTimeout(() => {\n            Entry.hw.sendQueue.RESET = 0;\n            Entry.hw.update();\n        }, 100);\n    },\n    getHashKey(opcode) {\n        // let key = new Date().getSeconds().toString(16);\n        // if (key.length === 1) {\n        //     key += ((Math.random() * 16) | 0).toString(16);\n        // }\n        // return Entry.generateHash(6)+opcode;\n        // Symbol을 쓰면 hw로 넘길수있나 -> 있으면 지금과 비교해서 속도는?\n        return (\n            Date.now()\n                .toString()\n                .substring(6) + opcode\n        );\n    },\n    sendOrder(order) {\n        const sq = Entry.hw.sendQueue;\n        Entry.CodeWiz.intervalId = true;\n        if (!sq.ORDER) {\n            sq.ORDER = {};\n        } //order.value.opcodescript.key\n        const id = this.getHashKey(order.value.opcode);\n        sq.ORDER[id] = order;\n        Entry.hw.update();\n        // return id;\n        this.deleteOrder(id);\n\n        return id;\n    },\n    HUSKY: {\n        CENT_X: 160,\n        CENT_Y: 120,\n        getDist: function(x, y) {\n            return Math.sqrt(Math.pow(this.CENT_X - x, 2) + Math.pow(this.CENT_Y - y, 2));\n        },\n    },\n    deleteOrder(id) {\n        // Entry.hw.portData.runOK = false;\n        /** */\n        // console.log('portData', Entry.hw.portData);\n        // console.log('deleteOrder:', id);\n\n        Entry.hw.portData[id] = { value: null };\n        /** */\n        delete Entry.hw.sendQueue.ORDER[id];\n        Entry.hw.update();\n    },\n    getOffsetX(str) {\n        return this.getByteLength(str) * 1.5 - 18;\n    },\n    getByteLength(s, b, i, c) {\n        if (!s) {\n            return;\n        }\n        for (b = i = 0; (c = s.charCodeAt(i++)); b += c >> 11 ? 3 : c >> 7 ? 2 : 1);\n        return b;\n    },\n    monitorTemplate: {\n        imgPath: 'hw/codeino.png',\n        width: 431,\n        height: 354,\n\n        mode: 'both',\n    },\n    sensorTypes: {\n        READ: 1,\n        WRITE: 0,\n    },\n\n    // preWaitList: [],\n    // preWaitResult: null,\n};\n\nEntry.CodeWiz.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                CodeWiz_sensor_title: '기본 센서',\n                CodeWiz_get_sensor: '%1센서 값',\n                CodeWiz_get_gyroSensor: '3축 센서 %1값',\n                CodeWiz_isPushedButton: '%1 스위치 버튼 값',\n                CodeWiz_touchPin: '터치핀 %1 값',\n\n                CodeWiz_buzzer_title: '스피커',\n                CodeWiz_default_buzzer: '스피커를 %1옥타브, %2음, %3분음표로 연주하기 %4',\n\n                CodeWiz_neopixel_title: '네오픽셀',\n                CodeWiz_neopixel_init: '네오픽셀 %1에 %2개로 시작설정%3',\n                CodeWiz_neopixel_brightness: '네오픽셀 밝기를 %1로 설정(0~255)%2',\n                CodeWiz_neopixel_setColor_one: '네오픽셀 %1번 LED를 %2(으)로 켜기%3',\n                CodeWiz_neopixel_setColor_one2:\n                    '네오픽셀 %1번 LED를 빨강%2초록%3파랑%4(으)로 켜기%5',\n                CodeWiz_neopixel_off_one: '네오픽셀 %1번 LED 끄기%2',\n                CodeWiz_neopixel_setColor_all: '네오픽셀 %1(으)로 모두 켜기%2',\n                CodeWiz_neopixel_setColor_all2: '네오픽셀 빨강%1초록%2파랑%3(으)로 모두 켜기%4',\n                CodeWiz_neopixel_off_all: '네오픽셀 모두 끄기%1',\n                CodeWiz_neopixel_OnPixelRandomColor: '네오픽셀 %1번 LED 무작위 색으로 켜기%2',\n                CodeWiz_neopixel_fillRandom: '네오픽셀 무작위 색으로 채우기%1',\n                CodeWiz_neopixel_rotate: '네오픽셀 LED %1으로 회전시키기%2',\n                CodeWiz_neopixel_shift: '네오픽셀 LED %1으로 밀기%2',\n                CodeWiz_neopixel_gradationRGB:\n                    '네오픽셀 %1번부터 %2번까지 RGB그라데이션(%3,%4)으로 켜기%5',\n                CodeWiz_neopixel_gradationHSL:\n                    '네오픽셀 %1번부터 %2번까지 HSL그라데이션(%3,%4)으로 켜기%5',\n                CodeWiz_neopixel_wheeeeeeel: '네오픽셀 휠%1',\n\n                CodeWiz_OLED_title: 'OLED',\n                CodeWiz_OLED_clear: 'OLED 지우기%1',\n                CodeWiz_OLED_mirror: 'OLED 반전 모드%1 %2',\n                CodeWiz_OLED_setSize: 'OLED 문자 크기를 %1(으)로 설정%2',\n                CodeWiz_OLED_setPosition: 'OLED 커서위치(%1,%2)(으)로 지정%3',\n                CodeWiz_OLED_println: 'OLED에 %1 출력%2',\n                CodeWiz_OLED_isCollision: 'OLED 자동 줄바꿈%1%2',\n                CodeWiz_OLED_specialChar: 'OLED에 기호%1 출력하기%2',\n                CodeWiz_OLED_setFont: 'OLED 폰트%1를 크기%2(으)로 설정%3',\n                CodeWiz_OLED_startScroll: 'OLED 스크롤 시키기%1 시작%2~종료%3(0~7)%4',\n                CodeWiz_OLED_stopScroll: 'OLED 스크롤 멈추기%1',\n                CodeWiz_OLED_drawPoint: 'OLED 점찍기 (%1,%2)%3%4',\n                CodeWiz_OLED_drawLine1: 'OLED 선 그리기 시작(%1,%2) 끝(%3,%4)%5%6',\n                CodeWiz_OLED_drawLine2: 'OLED 수직선 시작(%1,%2) 길이%3%4%5',\n                CodeWiz_OLED_drawLine3: 'OLED 수평선 시작(%1,%2) 길이%3%4%5',\n                CodeWiz_OLED_drawRect: 'OLED 직사각형 시작(%1,%2) 가로%3세로%4%5%6%7',\n                CodeWiz_OLED_drawCircle: 'OLED 원 중심(%1,%2) 반지름%3%4%5%6',\n                CodeWiz_OLED_drawPoligon: 'OLED 삼각형 점1(%1,%2)점2(%3,%4)점3(%5,%6)%7%8%9',\n                CodeWiz_OLED_printHG: 'OLED에 한글포함%1 출력, 줄바꿈%2%3',\n\n                CodeWiz_DIGITAL_OUTPUT_title: '기본 출력',\n                CodeWiz_DIGITAL_OUTPUT_digitalWrite: 'PIN%1(으)로 %2내보내기%3',\n                CodeWiz_DIGITAL_OUTPUT_pwmWrite: 'PIN%1(으)로 PWM %2내보내기(0~1023)%3',\n\n                CodeWiz_OzEye_title: '오즈아이',\n                CodeWiz_OzEye_initOzEye: '오즈아이 시작설정%1',\n                CodeWiz_OzEye_setModeOfOzEye: '오즈아이 %1알고리즘으로 설정%2',\n                CodeWiz_OzEye_readOzEye: '오즈아이 데이터 요청시작%1',\n                CodeWiz_OzEye_isLearnedOzEye: '오즈아이 ID가%1인 데이터를 학습했는가?%2',\n                CodeWiz_OzEye_getCountLearnedOzEye: '오즈아이가 감지한 학습데이터 수%1',\n                CodeWiz_OzEye_isContainOzEye: '오즈아이 ID:%1로 인식한 %2데이터가 있는가?%3',\n                CodeWiz_OzEye_hasTypeOzEye: '오즈아이가 읽은 데이터 타입이%1인가?%2',\n                CodeWiz_OzEye_getArrowInfoOzEye: '오즈아이가 읽은 ID%1인 화살표정보%2%3',\n                CodeWiz_OzEye_getBoxInfoOzEye2: '오즈아이가 읽은 ID%1인 사각형정보%2%3',\n                CodeWiz_OzEye_getBoxInfoOzEye:\n                    '오즈아이가 읽은 사각형정보%1(중심좌표가 중앙에 가장 가까운 것)%2',\n                // CodeWiz_OzEye_writeTextOzEye: '오즈아이 (%1,%2)에 %3출력%4',\n                // CodeWiz_OzEye_clearTextOzEye: '오즈아이 텍스트 지우기%1',\n                CodeWiz_OzEye_setLightLevel: '오즈아이 라이트 밝기를 %1 단계로 설정(1~7)%2',\n                CodeWiz_OzEye_LightOff: '오즈아이 라이트 끄기%1',\n\n                CodeWiz_HuskyLens_title: '허스키렌즈',\n                CodeWiz_HuskyLens_initHuskyLens: '허스키렌즈 시작설정%1',\n                CodeWiz_HuskyLens_setModeOfHuskyLens: '허스키렌즈 %1알고리즘으로 설정%2',\n                CodeWiz_HuskyLens_readHuskyLens: '허스키렌즈 데이터 요청시작%1',\n                CodeWiz_HuskyLens_isLearnedHuskyLens: '허스키렌즈 ID가%1인 데이터를 학습했는가?%2',\n                CodeWiz_HuskyLens_getCountLearnedHuskyLens: '허스키렌즈가 감지한 학습데이터 수%1',\n                CodeWiz_HuskyLens_isContainHuskyLens:\n                    '허스키렌즈 ID:%1로 인식한 %2데이터가 있는가?%3',\n                CodeWiz_HuskyLens_hasTypeHuskyLens: '허스키렌즈가 읽은 데이터 타입이%1인가?%2',\n                CodeWiz_HuskyLens_getArrowInfoHuskyLens: '허스키렌즈가 읽은 ID%1인 화살표정보%2%3',\n                CodeWiz_HuskyLens_getBoxInfoHuskyLens2: '허스키렌즈가 읽은 ID%1인 사각형정보%2%3',\n                CodeWiz_HuskyLens_getBoxInfoHuskyLens:\n                    '허스키렌즈가 읽은 사각형정보%1(중심좌표가 중앙에 가장 가까운 것)%2',\n                CodeWiz_HuskyLens_writeTextHuskyLens: '허스키렌즈 (%1,%2)에 %3출력%4',\n                CodeWiz_HuskyLens_clearTextHuskyLens: '허스키렌즈 텍스트 지우기%1',\n\n                CodeWiz_Servo_title: '서보모터',\n                CodeWiz_Servo_setAngle: '서보모터(%1) 각도를 %2(으)로 바꾸기%3',\n                CodeWiz_Servo_menuSpeed: '무한회전 서보모터(%1) %2속도로 정하기%3',\n                CodeWiz_Servo_customSpeed: '무한회전 서보모터(%1) %2속도로 정하기(-100~100)%3',\n\n                CodeWiz_Dc_title: 'DC 모터',\n                CodeWiz_Dc_setCarSpeed: 'WizCar모터에 왼쪽%1, 오른쪽%2 내보내기(-1000~1000)%3',\n                CodeWiz_Dc_setValue_Waterpump: '워터펌프(%1)에 %2내보내기(0~1023)%3',\n\n                CodeWiz_DotMatrix_title: '도트매트릭스',\n                CodeWiz_DotMatrix_init: '도트매트릭스 %1개 DIN%2, CS%3, CLK%4로 설정%5',\n                CodeWiz_DotMatrix_setBrightness: '도트매트릭스 %1번 밝기를 %2(으)로 설정%3',\n                CodeWiz_DotMatrix_printString: '도트매트릭스 %1번에 문자열%2 출력%3',\n                CodeWiz_DotMatrix_setLine: '도트매트릭스 %1번의 %2%3 %4(으)로 만들기%5',\n                CodeWiz_DotMatrix_setDot: '도트매트릭스 %1번의 %2행%3열 %4%5',\n                CodeWiz_DotMatrix_clear: '도트매트릭스 %1번 지우기%2',\n                CodeWiz_DotMatrix_clearAll: '도트매트릭스 모두 지우기%1',\n\n                CodeWiz_ColorSensor_title: '컬러센서',\n                CodeWiz_ColorSensor_isColor: 'MCON 컬러센서 감지된 색이 %1인가%2',\n                CodeWiz_ColorSensor_getColorValue: 'MCON 컬러센서 %1값%2',\n\n                CodeWiz_DHT_title: '디지털 온습도',\n                CodeWiz_DHT_init: '디지털 온습도 pin%1에 설정%2',\n                CodeWiz_DHT_getValue: '디지털 온습도 %1값%2',\n\n                CodeWiz_Joystick_title: '조이스틱',\n                CodeWiz_Joystick_setPin: '조이스틱 설정하기(X축%1, Y축%2, 버튼%3, 범위%4)%5',\n                CodeWiz_Joystick_readAxis: '조이스틱 %1의 값%2',\n                CodeWiz_Joystick_readButton: '조이스틱 버튼 값%1',\n\n                CodeWiz_etcReadSensor_title: '기타 입력센서',\n                CodeWiz_etcReadSensor_mconRead: 'MCON%1(pin%2)의 측정값%3',\n                CodeWiz_etcReadSensor_digitalRead: '%1(pin%2)의 측정값%3',\n                CodeWiz_etcReadSensor_InfraredThermometerRead: '비접촉온도센서 %1에 %2로 읽기%3',\n            },\n\n            Helper: {\n                CodeWiz_get_sensor: `주변의 소리값을 0~1023 사이 값으로 알려줍니다.\n\n                ▼을 클릭하여 빛, 거리, 홀, 온도를 선택하여\n                주변의 밝기, 거리, 자성, 보드의 온도를 확인할 수 있습니다.`,\n                CodeWiz_get_gyroSensor: `선택된 축의 기울기를 -90~90 사이 값으로 알려줍니다.\n                ▼을 눌러 X축, Y축, Z축을 선택할 수 있습니다.`,\n                CodeWiz_isPushedButton: `왼쪽/오른쪽 버튼을 누르면 “참” 으로 판단합니다.\n                ▼을 눌러 왼쪽, 오른쪽을 선택할 수 있습니다.`,\n                CodeWiz_touchPin: `🐻 모양의 터치센서를 손가락으로 터치하면 “참“으로 판단합니다.\n                ▼을 눌러 🔆,⭕, 🖐, 👊, ❌ 모양의 터치센서를 선택하면 해당 모양의 터치센서의 터치 여부도 확인할 수 있습니다.`,\n\n                CodeWiz_default_buzzer: `지정된 옥타브의 음을 지정된 음표로 스피커(부저)를 재생합니다.`,\n\n                CodeWiz_neopixel_init: `코드위즈의 네오 RGB LED 5개의 사용을 설정합니다.\n                ▼을 눌러 SCON에 연결된 네오픽셀의 개수와 사용을 설정할 수 있습니다.`,\n                CodeWiz_neopixel_brightness: `밝기를 0~255 사이 값으로 지정합니다.`,\n                CodeWiz_neopixel_setColor_one: `입력한 번호의 LED를 선택한 색으로 켭니다.`,\n                CodeWiz_neopixel_setColor_one2: `입력한 번호의 LED를 빨강, 초록, 파랑에 입력된 값의 색으로 켭니다.\n                    각 값을 0~255 사이 값으로 지정합니다.`,\n                CodeWiz_neopixel_off_one: `입력한 번호의 LED를 끕니다.`,\n                CodeWiz_neopixel_setColor_all: `모든 LED를 선택한 색으로 켭니다.`,\n                CodeWiz_neopixel_setColor_all2: `모든 LED를 빨강, 초록, 파랑에 입력된 값의 색으로 켭니다.\n                각 값을 0~255 사이 값으로 지정합니다.`,\n                CodeWiz_neopixel_off_all: `모든 LED를 끕니다.`,\n                CodeWiz_neopixel_OnPixelRandomColor: `입력한 번호의 LED를 무작위 색으로 켭니다.`,\n                CodeWiz_neopixel_fillRandom: `모든 LED를 무작위 색으로 채웁니다.`,\n                CodeWiz_neopixel_rotate: `모든 LED를 지정한 방향으로 회전시킵니다.\n                방향은 ▼을 눌러 설정합니다.`,\n                CodeWiz_neopixel_shift: `모든 LED를 지정한 방향으로 밀어냅니다.\n                빈자리는 기존 색으로 채워집니다.\n                방향은 ▼을 눌러 설정합니다.`,\n                CodeWiz_neopixel_gradationRGB: `지정범위의 LED를 선택한 색의 그라데이션으로 채웁니다.\n                왼쪽색부터 오른쪽색까지 RGB색표현의 그라데이션으로 채워집니다.\n                범위는 초기화한 LED범위를 벗어날 수 없으며 서로 다른 값이여야 합니다.\n                LED 번호가 작은 값은 왼쪽에 큰 값은 오른쪽에 위치해야합니다.`,\n                CodeWiz_neopixel_gradationHSL: `지정범위의 LED를 선택한 색의 그라데이션으로 채웁니다.\n                왼쪽색부터 오른쪽색까지 HSL색표현의 그라데이션으로 채워집니다.\n                범위는 초기화한 LED범위를 벗어날 수 없으며 서로 다른 값이여야 합니다.\n                LED 번호가 작은 값은 왼쪽에 큰 값은 오른쪽에 위치해야합니다.`,\n                CodeWiz_neopixel_wheeeeeeel: `녹색, 빨강, 파랑의 세 가지색을 기준으로 섞은 색을 순환시켜 켜주는 블록입니다.\n                이 블록을 사용해서 흐르는 듯한 네오픽셀을 표시할 수 있습니다.`,\n\n                CodeWiz_OLED_clear: `OLED에 표시된 내용을 지웁니다.`,\n                CodeWiz_OLED_mirror: `OLED에 표시할 내용의 출력 상태를 설정합니다.\n                OFF가 기본이며, ON을 선택하면 OLED 배경에 색이 채워지고 내용이 표시됩니다.`,\n                CodeWiz_OLED_setSize: `글자 크기를 지정합니다.\n                1~10 사이의 범위로 설정할 수 있습니다.`,\n                CodeWiz_OLED_setPosition: `글자가 출력될 위치(x좌표, y좌표)를 지정합니다.\n                X는 0~127, Y는 0~63 사이의 범위로 설정할 수 있습니다.`,\n                CodeWiz_OLED_println: `입력한 내용을 OLED에 출력합니다.`,\n                CodeWiz_OLED_isCollision: `OLED에 출력된 내용의 줄바꿈을 설정합니다.`,\n                CodeWiz_OLED_specialChar: `OLED에 기호를 출력합니다.`,\n                CodeWiz_OLED_setFont: `글꼴과 글자 크기를 ▼ 을 눌러 설정합니다.`,\n                CodeWiz_OLED_startScroll: `OLED에 입력된 내용을 지정한 화살표방향으로 이동시킵니다. 시작과 종료는 y좌표를 0~7 페이지로 나눈 것으로 각 페이지는 다음과 같은 y 좌표를 가집니다.\n                \n                0 : y좌표 0~7\n                1 : y좌표 8~15\n                2 : y좌표 16~23\n                3 : y좌표 24~31\n                4 : y좌표 32~39\n                5 : y좌표 40~47\n                6 : y좌표 48~55\n                7 : y좌표 56~63`,\n                CodeWiz_OLED_stopScroll: `이동을 멈춥니다.`,\n                CodeWiz_OLED_drawPoint: `지정된 위치 (x좌표, y좌표)에 점을 찍습니다.\n                X는 0~127, Y는 0~63 사이의 범위로 설정할 수 있습니다.`,\n                CodeWiz_OLED_drawLine1: `시작 위치 (x좌표, y좌표)에서 끝 위치 (x좌표, y좌표)까지 흰색 선을 그립니다.`,\n                CodeWiz_OLED_drawLine2: `시작 위치 (x좌표, y좌표)에서 지정된 길이의 흰색 수직선을 그립니다.`,\n                CodeWiz_OLED_drawLine3: `시작 위치 (x좌표, y좌표)에서 지정된 길이의 흰색 수평선을 그립니다.`,\n                CodeWiz_OLED_drawRect: `시작 위치 (x좌표, y좌표)에서 지정된 가로, 세로 길이의 흰색 선 직사각형을 그립니다.\n                ▼을 눌러 ‘비움’ 대신 ‘채움‘을 선택하면 직사각형 내부가 채워집니다.`,\n                CodeWiz_OLED_drawCircle: `중심(x좌표, y좌표)에서 지정된 반지름을 가지는 흰색 선 원을 그립니다.\n                ▼을 눌러 ‘비움’ 대신 ‘채움‘을 선택하면 원 내부가 채워집니다.`,\n                CodeWiz_OLED_drawPoligon: `점1(x좌표, y좌표), 점2 (x좌표, y좌표), 점3 (x좌표, y좌표)을 연결하여 흰색 선 삼각형을 그립니다.\n                ▼을 눌러 ‘비움’ 대신 ‘채움‘을 선택하면 원 내부가 채워집니다.`,\n                CodeWiz_OLED_printHG: `입력한 내용(한글포함)을 OLED에 출력합니다.\n                ▼을 눌러 ‘⭕’를 선택하면 아랫줄로 커서를 이동시키고 ‘❌‘를 선택하면 마지막 글자 오른쪽으로 커서를 이동시킵니다.`,\n\n                CodeWiz_DIGITAL_OUTPUT_digitalWrite: `지정된 핀(터치센서 또는 SCON)에 연결된 센서로 HIGH 또는 LOW 를 내보냅니다.\n                \n                <현재 활용 가능한 확장도구>\n                진동모터`,\n                CodeWiz_DIGITAL_OUTPUT_pwmWrite: `지정된 핀(터치센서 또는 SCON)에 연결된 센서로 입력된 값을 내보냅니다.\n                \n                <현재 활용 가능한 확장도구>\n                프로펠러`,\n\n                CodeWiz_OzEye_initOzEye: `오즈아이 시작을 설정합니다.`,\n                CodeWiz_OzEye_setModeOfOzEye: `오즈아이를 선택된 알고리즘으로 설정합니다.\n\n                1.선 인식\n                2.색 인식\n                3.태그 인식\n                4.이미지 인식\n                5.사물 인식\n                6.사물 추적\n                7.선 + 태그\n                8.얼굴 인식\n                9.숫자 인식`,\n                CodeWiz_OzEye_readOzEye: `오즈아이가 인식한 결과를 주기적으로 보내줍니다.`,\n                CodeWiz_OzEye_isLearnedOzEye: `입력한 ID 번호 데이터를 학습했다면 ‘참’으로 판단하여 알려줍니다.`,\n                CodeWiz_OzEye_isContainOzEye: `입력한 ID 번호의 사각형 데이터가 인식된다면 ‘참’으로 판단하여 알려줍니다.\n                    ▼을 눌러 화살표를 선택하면 화살표 데이터가 인식될 때 ‘참’으로 판단하여 알려줍니다.`,\n                CodeWiz_OzEye_getCountLearnedOzEye: `화면에 감지된 학습한 데이터 수를 알려줍니다.`,\n                CodeWiz_OzEye_hasTypeOzEye: `읽어온 데이터 타입이 선택한 타입(사각형/화살표)과 같다면 ‘참’으로 판단하여 알려줍니다.`,\n                CodeWiz_OzEye_getArrowInfoOzEye: `읽어온 화살표 데이터의 좌표 값을 알려줍니다. 좌표 값은 ‘시작 X좌표‘, ‘시작 Y좌표‘, ‘종료 X좌표‘, ‘종료 Y좌표‘ 중 하나를 선택합니다.\n                    대상이 없다면 -1을 반환합니다.`,\n                CodeWiz_OzEye_getBoxInfoOzEye2: `읽어온 사각형 데이터의 정보를 알려줍니다. 정보는 ‘중심 X좌표‘, ‘중심 Y좌표’, ‘너비‘, ‘높이’ 중 하나를 선택합니다.\n                    대상이 없다면 -1을 반환합니다.`,\n                CodeWiz_OzEye_getBoxInfoOzEye: `읽어온 사각형 데이터의 정보를 알려줍니다. 정보는 ‘ID’, ‘중심 X좌표‘, ‘중심 Y좌표’, ‘너비‘, ‘높이’ 중 하나를 선택합니다.\n                    대상이 없다면 -1을 반환합니다.`,\n                // CodeWiz_OzEye_writeTextOzEye: `오즈아이 화면의 지정된 좌표에 입력된 데이터를 출력합니다.`,\n                // CodeWiz_OzEye_clearTextOzEye: `오즈아이 화면에 출력되어 있는 데이터를 지웁니다.`,\n                CodeWiz_OzEye_setLightLevel: '오즈아이의 라이트 밝기를 1~7 단계로 설정합니다.',\n                CodeWiz_OzEye_LightOff: '오즈아이 라이트를 끕니다.',\n\n                CodeWiz_HuskyLens_initHuskyLens: `허스키렌즈 시작을 설정합니다.`,\n                CodeWiz_HuskyLens_setModeOfHuskyLens: `허스키렌즈를 선택된 알고리즘으로 설정합니다.\n\n                1.FACE_RECOGNITION\n                2.OBJECT_TRACKING\n                3.OBJECT_RECOGNITION\n                4.LINE_TRACKING\n                5.COLOR_RECOGNITION\n                6.TAG_RECOGNITION\n                7.OBJECT_CLASSIFICATION`,\n                CodeWiz_HuskyLens_readHuskyLens: `허스키렌즈가 인식한 결과를 주기적으로 보내줍니다.`,\n                CodeWiz_HuskyLens_isLearnedHuskyLens: `입력한 ID 번호 데이터를 학습했다면 ‘참’으로 판단하여 알려줍니다.`,\n                CodeWiz_HuskyLens_isContainHuskyLens: `입력한 ID 번호의 사각형 데이터가 인식된다면 ‘참’으로 판단하여 알려줍니다.\n                    ▼을 눌러 화살표를 선택하면 화살표 데이터가 인식될 때 ‘참’으로 판단하여 알려줍니다.`,\n                CodeWiz_HuskyLens_getCountLearnedHuskyLens: `화면에 감지된 학습한 데이터 수를 알려줍니다.`,\n                CodeWiz_HuskyLens_hasTypeHuskyLens: `읽어온 데이터 타입이 선택한 타입(사각형/화살표)과 같다면 ‘참’으로 판단하여 알려줍니다.`,\n                CodeWiz_HuskyLens_getArrowInfoHuskyLens: `읽어온 화살표 데이터의 좌표 값을 알려줍니다. 좌표 값은 ‘시작 X좌표‘, ‘시작 Y좌표‘, ‘종료 X좌표‘, ‘종료 Y좌표‘ 중 하나를 선택합니다.\n                    대상이 없다면 -1을 반환합니다.`,\n                CodeWiz_HuskyLens_getBoxInfoHuskyLens2: `읽어온 사각형 데이터의 정보를 알려줍니다. 정보는 ‘중심 X좌표‘, ‘중심 Y좌표’, ‘너비‘, ‘높이’ 중 하나를 선택합니다.\n                    대상이 없다면 -1을 반환합니다.`,\n                CodeWiz_HuskyLens_getBoxInfoHuskyLens: `읽어온 사각형 데이터의 정보를 알려줍니다. 정보는 ‘ID’, ‘중심 X좌표‘, ‘중심 Y좌표’, ‘너비‘, ‘높이’ 중 하나를 선택합니다.\n                    대상이 없다면 -1을 반환합니다.`,\n                CodeWiz_HuskyLens_writeTextHuskyLens: `허스키렌즈 화면의 지정된 좌표에 입력된 데이터를 출력합니다.`,\n                CodeWiz_HuskyLens_clearTextHuskyLens: `허스키렌즈 화면에 출력되어 있는 데이터를 지웁니다.`,\n\n                CodeWiz_Servo_setAngle: `선택된 커넥터(MCON/SCON)에 연결된 180도 서보모터의 각도를 입력된 각도로 회전시킵니다.(0~180)`,\n                CodeWiz_Servo_menuSpeed: `선택된 커넥터(MCON/SCON)에 무한회전 서보모터를 지정된 속도로 회전시킵니다.\n                ▼을 눌러 속도를 선택합니다.(빠른/보통/느림/멈춘)`,\n                CodeWiz_Servo_customSpeed: `선택된 커넥터(MCON/SCON)에 무한회전 서보모터를 지정된 속도로 회전시킵니다.\n\n                속도 = 0 : 모터의 회전이 멈춥니다.\n                속도 > 0 : 모터가 지정된 속도로 정방향 회전합니다.\n                속도 < 0 : 모터가 지정된 속도로 역방향 회전합니다.`,\n\n                CodeWiz_Dc_setCarSpeed: `WizCar 모터에 입력한 숫자값으로 회전시킵니다.\n                각 모터값은 -1000~-180(후진), 180~1000(전진) 사이값입니다. 바닥 상태에 따라 숫자값을 높여가면서 회전을 시켜보세요.`,\n                CodeWiz_Dc_setValue_Waterpump: `선택된 워터펌프를 입력한 속도로 회전시킵니다.\n                ▼을 눌러 회전시킬 모터(MOTOR_L, MOROT_R)를 선택하고 속도는 0~1023 사이 값으로 직접 입력합니다.`,\n\n                CodeWiz_DotMatrix_init: `도트매트릭스가 연결된 핀을 설정합니다.\n\n                18, 19번 : SCON                \n                15, 27번 : 터치센서`,\n                CodeWiz_DotMatrix_setBrightness: `입력된 값으로 도트매트릭스의 밝기를 설정합니다.(1~8)`,\n                CodeWiz_DotMatrix_printString: `입력된 문자열을 한 글자씩 출력합니다.`,\n                CodeWiz_DotMatrix_setLine: `지정된 행/열에 위치한 8개 LED의 ON/OFF를 각각 지정해서 제어합니다.\n\n                1 : ON                \n                0 : OFF`,\n                CodeWiz_DotMatrix_setDot: `입력된 행,열에 위치한 LED의 ON/OFF를 지정합니다.\n\n                켜기 : ON\n                끄기 : OFF`,\n                CodeWiz_DotMatrix_clear: `입력된 도트 매트릭스를 지웁니다.(끕니다.)`,\n                CodeWiz_DotMatrix_clearAll: `연결된 모든 도트 매트릭스를 지웁니다.(끕니다.)`,\n\n                CodeWiz_ColorSensor_isColor: `MCON에 연결된 컬러센서에 인식된 색 값이 지정된 색이라면 ‘참’으로 판단하여 알려줍니다.\n                ▼을 빨강, 초록, 파랑, 검정, 흰색을 선택할 수 있습니다.`,\n                CodeWiz_ColorSensor_getColorValue: `MCON에 연결된 컬러센서에 인식된 빨강의 색상 값을 0~255 사이값으로 알려줍니다.\n                ▼을 눌러 초록, 파랑을 선택할 수 있습니다.`,\n\n                CodeWiz_DHT_init: `지정한 핀으로 디지털 온습도를 설정합니다.`,\n                CodeWiz_DHT_getValue: `앞서 설정한 디지털 온습도에서 선택한 값을 가져옵니다.`,\n\n                CodeWiz_Joystick_setPin: '지정한 핀으로 조이스틱을 설정합니다.',\n                CodeWiz_Joystick_readAxis: '설정된 조이스틱의 지정한 축의 레버값을 읽어옵니다.',\n                CodeWiz_Joystick_readButton: '설정된 조이스틱의 버튼이 눌렸는지 값을 읽어옵니다.',\n\n                CodeWiz_etcReadSensor_mconRead: `가변저항/워터센서/토양수분센서의 측정값\n                선택한 센서에 따라서 값이 적절히 매핑되어 반환됩니다.`,\n                CodeWiz_etcReadSensor_digitalRead: `버튼/포토인터럽트의 측정값\n                해당핀의 digitalRead값을 가져옵니다.\n                버튼의 경우 눌렸을 때 참을 반환하기 위해서 인버스를 취하고,\n                포토인터럽트는 읽은 값 그대로 반환됩니다.\n                `,\n                CodeWiz_etcReadSensor_InfraredThermometerRead: `선택된 커넥터(MCON/SCON)에 연결된 비접촉 온도 센서에 인식된 온도를 알려줍니다.\n                ▼을 눌러 온도 단위를 선택합니다.`,\n            },\n        },\n    };\n};\nEntry.CodeWiz.blockMenuBlocks = [\n    'CodeWiz_sensor_title',\n    'CodeWiz_get_sensor',\n    'CodeWiz_get_gyroSensor',\n    'CodeWiz_isPushedButton',\n    'CodeWiz_touchPin',\n\n    'CodeWiz_buzzer_title',\n    'CodeWiz_default_buzzer',\n\n    'CodeWiz_neopixel_title',\n    'CodeWiz_neopixel_init',\n    'CodeWiz_neopixel_brightness',\n    'CodeWiz_neopixel_setColor_one',\n    'CodeWiz_neopixel_setColor_one2',\n    'CodeWiz_neopixel_off_one',\n    'CodeWiz_neopixel_setColor_all',\n    'CodeWiz_neopixel_setColor_all2',\n    'CodeWiz_neopixel_off_all',\n    'CodeWiz_neopixel_OnPixelRandomColor',\n    'CodeWiz_neopixel_fillRandom',\n    'CodeWiz_neopixel_rotate',\n    'CodeWiz_neopixel_shift',\n    'CodeWiz_neopixel_gradationRGB',\n    'CodeWiz_neopixel_gradationHSL',\n    'CodeWiz_neopixel_wheeeeeeel',\n\n    'CodeWiz_OLED_title',\n    'CodeWiz_OLED_clear',\n    'CodeWiz_OLED_mirror',\n    'CodeWiz_OLED_setSize',\n    'CodeWiz_OLED_setPosition',\n    'CodeWiz_OLED_println',\n    'CodeWiz_OLED_isCollision',\n    'CodeWiz_OLED_specialChar',\n    'CodeWiz_OLED_setFont',\n    'CodeWiz_OLED_startScroll',\n    'CodeWiz_OLED_stopScroll',\n    'CodeWiz_OLED_drawPoint',\n    'CodeWiz_OLED_drawLine1',\n    'CodeWiz_OLED_drawLine2',\n    'CodeWiz_OLED_drawLine3',\n    'CodeWiz_OLED_drawRect',\n    'CodeWiz_OLED_drawCircle',\n    'CodeWiz_OLED_drawPoligon',\n    'CodeWiz_OLED_printHG',\n\n    'CodeWiz_DIGITAL_OUTPUT_title',\n    'CodeWiz_DIGITAL_OUTPUT_digitalWrite',\n    'CodeWiz_DIGITAL_OUTPUT_pwmWrite',\n\n    'CodeWiz_OzEye_title',\n    'CodeWiz_OzEye_initOzEye',\n    'CodeWiz_OzEye_setModeOfOzEye',\n    'CodeWiz_OzEye_readOzEye',\n    'CodeWiz_OzEye_isLearnedOzEye',\n    'CodeWiz_OzEye_isContainOzEye',\n    'CodeWiz_OzEye_getCountLearnedOzEye',\n    'CodeWiz_OzEye_hasTypeOzEye',\n    'CodeWiz_OzEye_getArrowInfoOzEye',\n    'CodeWiz_OzEye_getBoxInfoOzEye2',\n    'CodeWiz_OzEye_getBoxInfoOzEye',\n    // 'CodeWiz_OzEye_writeTextOzEye',\n    // 'CodeWiz_OzEye_clearTextOzEye',\n    'CodeWiz_OzEye_setLightLevel',\n    'CodeWiz_OzEye_LightOff',\n\n    'CodeWiz_HuskyLens_title',\n    'CodeWiz_HuskyLens_initHuskyLens',\n    'CodeWiz_HuskyLens_setModeOfHuskyLens',\n    'CodeWiz_HuskyLens_readHuskyLens',\n    'CodeWiz_HuskyLens_isLearnedHuskyLens',\n    'CodeWiz_HuskyLens_isContainHuskyLens',\n    'CodeWiz_HuskyLens_getCountLearnedHuskyLens',\n    'CodeWiz_HuskyLens_hasTypeHuskyLens',\n    'CodeWiz_HuskyLens_getArrowInfoHuskyLens',\n    'CodeWiz_HuskyLens_getBoxInfoHuskyLens2',\n    'CodeWiz_HuskyLens_getBoxInfoHuskyLens',\n    'CodeWiz_HuskyLens_writeTextHuskyLens',\n    'CodeWiz_HuskyLens_clearTextHuskyLens',\n\n    'CodeWiz_Servo_title',\n    'CodeWiz_Servo_setAngle',\n    'CodeWiz_Servo_menuSpeed',\n    'CodeWiz_Servo_customSpeed',\n\n    'CodeWiz_Dc_title',\n    'CodeWiz_Dc_setCarSpeed',\n    'CodeWiz_Dc_setValue_Waterpump',\n\n    'CodeWiz_DotMatrix_title',\n    'CodeWiz_DotMatrix_init',\n    'CodeWiz_DotMatrix_setBrightness',\n    'CodeWiz_DotMatrix_printString',\n    'CodeWiz_DotMatrix_setLine',\n    'CodeWiz_DotMatrix_setDot',\n    'CodeWiz_DotMatrix_clear',\n    'CodeWiz_DotMatrix_clearAll',\n\n    'CodeWiz_ColorSensor_title',\n    'CodeWiz_ColorSensor_isColor',\n    'CodeWiz_ColorSensor_getColorValue',\n\n    'CodeWiz_DHT_title',\n    'CodeWiz_DHT_init',\n    'CodeWiz_DHT_getValue',\n\n    'CodeWiz_Joystick_title',\n    'CodeWiz_Joystick_setPin',\n    'CodeWiz_Joystick_readAxis',\n    'CodeWiz_Joystick_readButton',\n\n    'CodeWiz_etcReadSensor_title',\n    'CodeWiz_etcReadSensor_mconRead',\n    'CodeWiz_etcReadSensor_digitalRead',\n    'CodeWiz_etcReadSensor_InfraredThermometerRead',\n];\nEntry.CodeWiz.preWait = function() {\n    return new Promise((resolve) => {\n        let tmp = setInterval(() => {\n            // console.log('preWait:', Entry.CodeWiz.intervalId);\n            if (!Entry.CodeWiz.intervalId) {\n                clearInterval(tmp);\n                // Entry.CodeWiz.preWaitResult = Entry.CodeWiz.preWaitList.shift() || null;\n                resolve();\n            }\n        }, 11);\n    });\n};\nEntry.CodeWiz.checkComplete = function(timeout, id) {\n    let _promise = new Promise((resolve) => {\n        timeout = timeout ?? 1000;\n        Entry.CodeWiz.intervalId = setInterval(() => {\n            // console.log(Entry.CodeWiz.intervalId, 'runOK:', Entry.hw.portData[id]);\n            let ret = Entry.hw.portData[id]?.value;\n            if (ret !== undefined && ret !== null) {\n                clearInterval(Entry.CodeWiz.intervalId);\n                clearTimeout(Entry.CodeWiz.timeoutId);\n                Entry.CodeWiz.intervalId = null;\n                Entry.CodeWiz.timeoutId = null;\n                resolve();\n            }\n        }, 7);\n        Entry.CodeWiz.timeoutId = setTimeout(() => {\n            clearInterval(Entry.CodeWiz.intervalId);\n            // console.log(Entry.CodeWiz.intervalId, 'timeOut');\n            Entry.CodeWiz.intervalId = null;\n            Entry.CodeWiz.timeoutId = null;\n            // throw new Entry.Utils.AsyncError('TimeOutOccurred');\n            resolve();\n        }, timeout);\n    });\n    return _promise;\n};\n\nEntry.CodeWiz.getBlocks = function() {\n    return {\n        //region codeino 코드위즈\n        CodeWiz_sensor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_sensor_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_sensor_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_sensor_title',\n            },\n            class: 'CodeWiz_default_sensor',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_get_sensor: {\n            // Block UI : %1센서 값\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['소리', 'SOUND'],\n                        ['빛', 'LIGHT'],\n                        ['거리', 'DIST'],\n                        ['홀', 'HALL'],\n                        ['온도', 'tempSensor'],\n                    ],\n                    value: 'SOUND',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'CodeWiz_get_sensor',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n            },\n            isNotFor: ['CodeWiz'],\n            class: 'CodeWiz_default_sensor',\n            func: function(sprite, script) {\n                var sensor = script.getField('SENSOR', script);\n                var hw_sensorData = Entry.hw.portData;\n                return hw_sensorData[sensor] ?? 0;\n            },\n        },\n        CodeWiz_get_gyroSensor: {\n            // Block UI : 자이로 센서 %1값\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X', 'GYRO_X'],\n                        ['Y', 'GYRO_Y'],\n                        ['Z', 'GYRO_Z'],\n                    ],\n                    value: 'GYRO_X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'CodeWiz_get_gyroSensor',\n            },\n            paramsKeyMap: {\n                GYRO_TYPE: 0,\n            },\n            isNotFor: ['CodeWiz'],\n            class: 'CodeWiz_default_sensor',\n            func: function(sprite, script) {\n                var sensor = script.getField('GYRO_TYPE', script);\n                var hw_sensorData = Entry.hw.portData;\n                return hw_sensorData[sensor] ?? 0;\n            },\n        },\n        CodeWiz_isPushedButton: {\n            // Block UI : %1 스위치 버튼 값\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', 'switchButton_26'],\n                        ['오른쪽', 'switchButton_4'],\n                    ],\n                    value: 'switchButton_26',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_isPushedButton',\n            },\n            paramsKeyMap: {\n                SWITCH: 0,\n            },\n            isNotFor: ['CodeWiz'],\n            class: 'CodeWiz_default_sensor',\n            func: function(sprite, script) {\n                var sensor = script.getField('SWITCH', script);\n                var hw_sensorData = Entry.hw.portData;\n                return hw_sensorData[sensor] ?? false;\n            },\n        },\n        CodeWiz_touchPin: {\n            // Block UI : \"터치핀 %1 값\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['🔆(13)', 'touchPin_13'],\n                        ['⭕(14)', 'touchPin_14'],\n                        ['🖐(15)', 'touchPin_15'],\n                        ['👊(27)', 'touchPin_27'],\n                        ['🐻(32)', 'touchPin_32'],\n                        ['❌(33)', 'touchPin_33'],\n                    ],\n                    value: 'touchPin_32',\n                    fontSize: 14,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_touchPin',\n            },\n            paramsKeyMap: {\n                SWITCH: 0,\n            },\n            isNotFor: ['CodeWiz'],\n            class: 'CodeWiz_default_sensor',\n            func: function(sprite, script) {\n                var sensor = script.getField('SWITCH', script);\n                var hw_sensorData = Entry.hw.portData;\n                return hw_sensorData[sensor] ?? 0;\n            },\n        },\n        CodeWiz_buzzer_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_buzzer_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_buzzer_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_buzzer_title',\n            },\n            class: 'CodeWiz_buzzer',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_default_buzzer: {\n            // Block UI : \"스피커를 %1옥타브, %2음, %3분음표로 연주하기%4\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['도', '0'],\n                        ['도#', '1'],\n                        ['레', '2'],\n                        ['미♭', '3'],\n                        ['미', '4'],\n                        ['파', '5'],\n                        ['파#', '6'],\n                        ['솔', '7'],\n                        ['솔#', '8'],\n                        ['라', '9'],\n                        ['시♭', '10'],\n                        ['시', '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['4', '4'],\n                        ['8', '8'],\n                        ['16', '16'],\n                        ['32', '32'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'CodeWiz_default_buzzer',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                NOTE: 1,\n                BEAT: 2,\n            },\n            class: 'CodeWiz_buzzer',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let octave = Number.parseInt(script.getValue('OCTAVE', script));\n                let note = Number.parseInt(script.getValue('NOTE', script));\n                let beat = Number.parseInt(script.getValue('BEAT', script));\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 1,\n                        params: [octave, note, beat],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n\n                await Entry.CodeWiz.checkComplete(1234, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n\n        CodeWiz_neopixel_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_neopixel_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_neopixel_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_neopixel_title',\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_neopixel_init: {\n            // Block UI : \"네오픽셀 %1에 %2개로 시작설정%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['코드위즈', '23'],\n                        ['18', '18'],\n                        ['19', '19'],\n                    ],\n                    value: '23',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: 5,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_neopixel_init',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                COUNT: 1,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _pin = script.getNumberValue('PIN', script);\n                let _count = script.getNumberValue('COUNT', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 32,\n                        params: [_pin, _count],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_brightness: {\n            // Block UI : \"네오픽셀 밝기를 %1로 설정(0~255)%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: 22,\n                },\n\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'CodeWiz_neopixel_brightness',\n            },\n            paramsKeyMap: {\n                BRIGHTNESS: 0,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let value = script.getNumberValue('BRIGHTNESS', script);\n                value = Math.round(value);\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 2,\n                        params: [value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_setColor_one: {\n            // Block UI : \"네오픽셀 %1번 LED를 <색상표>%2(으)로 켜기%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', null, null],\n                type: 'CodeWiz_neopixel_setColor_one',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                COLOR: 1,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let num = script.getNumberValue('NUM', script) - 1;\n                let value = script.getStringField('COLOR', script);\n\n                let colorValue = [\n                    parseInt(value.substr(1, 2), 16),\n                    parseInt(value.substr(3, 2), 16),\n                    parseInt(value.substr(5, 2), 16),\n                ];\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 3,\n                        params: [num, ...colorValue],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_setColor_one2: {\n            // Block UI : \"네오픽셀 %1번 LED를 빨강%2초록%3파랑%4(으)로 켜기%5\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '255', '255', '255', null],\n                type: 'CodeWiz_neopixel_setColor_one2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                R: 1,\n                G: 2,\n                B: 3,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let num = script.getNumberValue('NUM', script) - 1;\n                let r = script.getNumberValue('R', script);\n                let g = script.getNumberValue('G', script);\n                let b = script.getNumberValue('B', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 3,\n                        params: [num, r, g, b],\n                    },\n                };\n\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_off_one: {\n            // Block UI : \"네오픽셀 %1번 LED 끄기%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', null],\n                type: 'CodeWiz_neopixel_off_one',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let num = script.getNumberValue('NUM', script) - 1;\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 4,\n                        params: [num],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_setColor_all: {\n            // Block UI : \"네오픽셀 %1(으)로 모두 켜기%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_neopixel_setColor_all',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let value = script.getStringField('COLOR', script);\n\n                let colorValue = [\n                    parseInt(value.substr(1, 2), 16),\n                    parseInt(value.substr(3, 2), 16),\n                    parseInt(value.substr(5, 2), 16),\n                ];\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 5,\n                        params: [...colorValue],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_setColor_all2: {\n            // Block UI : \"네오픽셀 빨강%1초록%2파랑%3(으)로 모두 켜기%4\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['255', '255', '255', null],\n                type: 'CodeWiz_neopixel_setColor_all2',\n            },\n            paramsKeyMap: {\n                R: 0,\n                G: 1,\n                B: 2,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let r = script.getNumberValue('R', script);\n                let g = script.getNumberValue('G', script);\n                let b = script.getNumberValue('B', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 5,\n                        params: [r, g, b],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_off_all: {\n            // Block UI : \"네오픽셀 모두 끄기%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_neopixel_off_all',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 6,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_OnPixelRandomColor: {\n            // 랜덤색상 켜기 - 단일\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', null],\n                type: 'CodeWiz_neopixel_OnPixelRandomColor',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let num = script.getNumberValue('NUM', script) - 1;\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 3,\n                        params: [\n                            num,\n                            Math.floor(Math.random() * 256),\n                            Math.floor(Math.random() * 256),\n                            Math.floor(Math.random() * 256),\n                        ],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_fillRandom: {\n            // 랜덤색상 켜기 - 전체\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_neopixel_fillRandom',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 43,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_rotate: {\n            // rotate 네오픽셀\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['역방향', '0'],\n                        ['정방향', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_neopixel_rotate',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _dir = script.getNumberValue('DIR', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 44,\n                        params: [_dir],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_shift: {\n            // shift 네오픽셀\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['역방향', '0'],\n                        ['정방향', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_neopixel_shift',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _dir = script.getNumberValue('DIR', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 45,\n                        params: [_dir],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_gradationRGB: {\n            // RGB그라데이션\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '8', '#ff0000', '#00ff00'],\n                type: 'CodeWiz_neopixel_gradationRGB',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                S_COLOR: 2,\n                E_COLOR: 3,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _start = script.getNumberValue('START', script) - 1;\n                let _end = script.getNumberValue('END', script) - 1;\n                let _sColor = script.getStringField('S_COLOR', script);\n                let _eColor = script.getStringField('E_COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 46,\n                        params: [_start, _end, _sColor, _eColor],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_gradationHSL: {\n            // HSL그라데이션\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '8', '#ff0000', '#611ca1'],\n                type: 'CodeWiz_neopixel_gradationHSL',\n            },\n            paramsKeyMap: {\n                START: 0,\n                END: 1,\n                S_COLOR: 2,\n                E_COLOR: 3,\n            },\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _start = script.getNumberValue('START', script) - 1;\n                let _end = script.getNumberValue('END', script) - 1;\n                let _sColor = script.getStringField('S_COLOR', script);\n                let _eColor = script.getStringField('E_COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 47,\n                        params: [_start, _end, _sColor, _eColor],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_neopixel_wheeeeeeel: {\n            // 휠 - 엔트리에선 느려서 활용도가 떨어질 것으로 예상해서 일단 주석\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_neopixel_wheeeeeeel',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_neopixel',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 49,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                // console.log(script.key);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n\n        CodeWiz_OLED_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_OLED_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_OLED_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_OLED_title',\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_OLED_clear: {\n            // Block UI : \"OLED 지우기%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_OLED_clear',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 7,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_mirror: {\n            // Block UI : \"OLED 반전모드%1 %2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OFF', '0'],\n                        ['ON', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OLED_mirror',\n            },\n            paramsKeyMap: {\n                SWITCH: 0,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _value = script.getNumberValue('SWITCH', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 8,\n                        params: [_value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_setSize: {\n            // Block UI : \"OLED 문자 크기를 %1(으)로 설정%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [3],\n                type: 'CodeWiz_OLED_setSize',\n            },\n            paramsKeyMap: {\n                SIZE: 0,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _value = script.getNumberValue('SIZE', script);\n                _value = Math.round(_value);\n                if (_value < 1) {\n                    _value = 1;\n                } else if (_value > 10) {\n                    _value = 10;\n                }\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 9,\n                        params: [_value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_setPosition: {\n            // Block UI : \"OLED 커서위치(%1,%2)(으)로 지정%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0', '0'],\n                type: 'CodeWiz_OLED_setPosition',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _x = script.getNumberValue('X', script);\n                _x = Math.round(_x);\n                if (_x < 0) {\n                    _x = 0;\n                } else if (_x > 255) {\n                    _x = 255;\n                }\n\n                let _y = script.getNumberValue('Y', script);\n                _y = Math.round(_y);\n                if (_y < 0) {\n                    _y = 0;\n                } else if (_y > 255) {\n                    _y = 255;\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 10,\n                        params: [_x, _y],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_println: {\n            // Block UI : \"OLED에 %1출력%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['Hello, World!!'],\n                type: 'CodeWiz_OLED_println',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _value = script.getStringValue('TEXT');\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 11,\n                        params: [_value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_isCollision: {\n            // Block UI : \"OLED 문자겹침 모드%1%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OFF', '0'],\n                        ['ON', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OLED_isCollision',\n            },\n            paramsKeyMap: {\n                SWITCH: 0,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _value = script.getNumberValue('SWITCH', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 12,\n                        params: [_value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_specialChar: {\n            // Block UI : \"OLED에 기호%1 출력하기%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['♥', '3'],\n                        ['◆', '4'],\n                        ['♣', '5'],\n                        ['♠', '6'],\n                        ['♬', '14'],\n                        ['▲', '30'],\n                        ['▼', '31'],\n\n                        ['😧', '1'],\n                        ['😀', '2'],\n                        ['♂', '11'],\n                        ['♀', '12'],\n                        ['↑', '24'],\n                        ['↓', '25'],\n                        ['→', '26'],\n                        ['←', '27'],\n                    ],\n                    value: '14',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OLED_specialChar',\n            },\n            paramsKeyMap: {\n                CHAR: 0,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _value = script.getNumberValue('CHAR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 13,\n                        params: [_value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_setFont: {\n            // Block UI : \"OLED 폰트%1를 크기%2(으)로 설정%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Serif', '0'],\n                        ['Sans', '1'],\n                        ['Mono', '2'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['9', '0'],\n                        ['12', '1'],\n                        ['18', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'CodeWiz_OLED_setFont',\n            },\n            paramsKeyMap: {\n                FONT: 0,\n                SIZE: 1,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _value = script.getNumberValue('FONT', script);\n                let _size = script.getNumberValue('SIZE', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 14,\n                        params: [_value, _size],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_startScroll: {\n            // Block UI : \"OLED 스크롤 시키기 옵션(%1, 범위%2~%3(0~7))%4\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['→', '0'],\n                        ['←', '1'],\n                        ['↗', '2'],\n                        ['↖', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 14,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '0', '0'],\n                type: 'CodeWiz_OLED_startScroll',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                START: 1,\n                END: 2,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _value = Number.parseInt(script.getNumberValue('DIRECTION', script));\n                let _st = Number.parseInt(script.getNumberValue('START', script));\n                _st = Math.round(_st);\n                if (_st < 0) {\n                    _x = 0;\n                } else if (_st > 7) {\n                    _st = 7;\n                }\n                let _ed = script.getNumberValue('END', script);\n                _ed = Math.round(_ed);\n                if (_ed < 0) {\n                    _ed = 0;\n                } else if (_ed > 7) {\n                    _ed = 7;\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 15,\n                        params: [_value, _st, _ed],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_stopScroll: {\n            // Block UI : \"OLED 스크롤 멈추기%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_OLED_stopScroll',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 16,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_drawPoint: {\n            // Block UI : \"OLED에 점찍기 옵션((%1,%2), %3)%4\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['검은색', '0'],\n                        ['흰색', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [63, 31, null],\n                type: 'CodeWiz_OLED_drawPoint',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                COLOR: 2,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _x = script.getNumberValue('X', script);\n                _x = Math.round(_x);\n                if (_x < 0) {\n                    _x = 0;\n                } else if (_x > 128) {\n                    _x = 128;\n                }\n\n                let _y = script.getNumberValue('Y', script);\n                _y = Math.round(_y);\n                if (_y < 0) {\n                    _y = 0;\n                } else if (_y > 64) {\n                    _y = 64;\n                }\n\n                let _color = script.getNumberValue('COLOR', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 17,\n                        params: [_x, _y, _color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_drawLine1: {\n            // Block UI : \"OLED에 선 그리기 옵션((%1,%2)~(%3,%4), %5)%6\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['검은색', '0'],\n                        ['흰색', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0', '0', '10', '0', null],\n                type: 'CodeWiz_OLED_drawLine1',\n            },\n            paramsKeyMap: {\n                SX: 0,\n                SY: 1,\n                EX: 2,\n                EY: 3,\n                COLOR: 4,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _sx = script.getNumberValue('SX', script);\n                _sx = Math.round(_sx);\n                if (_sx < 0) {\n                    _sx = 0;\n                } else if (_sx > 128) {\n                    _sx = 128;\n                }\n                let _sy = script.getNumberValue('SY', script);\n                _sy = Math.round(_sy);\n                if (_sy < 0) {\n                    _sy = 0;\n                } else if (_sy > 64) {\n                    _sy = 64;\n                }\n                let _ex = script.getNumberValue('EX', script);\n                _ex = Math.round(_ex);\n                if (_ex < 0) {\n                    _ex = 0;\n                } else if (_ex > 128) {\n                    _ex = 128;\n                }\n                let _ey = script.getNumberValue('EY', script);\n                _ey = Math.round(_ey);\n                if (_ey < 0) {\n                    _ey = 0;\n                } else if (_ey > 64) {\n                    _ey = 64;\n                }\n                let _color = script.getNumberValue('COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 18,\n                        params: [_sx, _sy, _ex, _ey, _color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_drawLine2: {\n            // Block UI : \"OLED에 수직 선 그리기 옵션((%1,%2), 길이%3, %4)%5\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['검은색', '0'],\n                        ['흰색', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0', '0', '10', null],\n                type: 'CodeWiz_OLED_drawLine2',\n            },\n            paramsKeyMap: {\n                SX: 0,\n                SY: 1,\n                LEN: 2,\n                COLOR: 3,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _sx = script.getNumberValue('SX', script);\n                _sx = Math.round(_sx);\n                if (_sx < 0) {\n                    _sx = 0;\n                } else if (_sx > 128) {\n                    _sx = 128;\n                }\n                let _sy = script.getNumberValue('SY', script);\n                _sy = Math.round(_sy);\n                if (_sy < 0) {\n                    _sy = 0;\n                } else if (_sy > 64) {\n                    _sy = 64;\n                }\n                let _len = script.getNumberValue('LEN', script);\n                _len = Math.round(_len);\n                if (_len < 0) {\n                    _len = 0;\n                } else if (_len > 64) {\n                    _len = 64;\n                }\n                let _color = script.getNumberValue('COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 19,\n                        params: [_sx, _sy, _len, _color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_drawLine3: {\n            // Block UI : \"OLED에 수평 선 그리기 옵션((%1,%2), 길이%3, %4)%5\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['검은색', '0'],\n                        ['흰색', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0', '0', '10', null],\n                type: 'CodeWiz_OLED_drawLine3',\n            },\n            paramsKeyMap: {\n                SX: 0,\n                SY: 1,\n                LEN: 2,\n                COLOR: 3,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _sx = script.getNumberValue('SX', script);\n                _sx = Math.round(_sx);\n                if (_sx < 0) {\n                    _sx = 0;\n                } else if (_sx > 128) {\n                    _sx = 128;\n                }\n                let _sy = script.getNumberValue('SY', script);\n                _sy = Math.round(_sy);\n                if (_sy < 0) {\n                    _sy = 0;\n                } else if (_sy > 64) {\n                    _sy = 64;\n                }\n                let _len = script.getNumberValue('LEN', script);\n                _len = Math.round(_len);\n                if (_len < 0) {\n                    _len = 0;\n                } else if (_len > 128) {\n                    _len = 128;\n                }\n                let _color = script.getNumberValue('COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 20,\n                        params: [_sx, _sy, _len, _color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_drawRect: {\n            // Block UI : \"OLED에 직사각형 그리기 옵션(좌상단점(%1,%2), 가로%3, 세로%4, %5, %6)%7\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['비움', '0'],\n                        ['채움', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['검은색', '0'],\n                        ['흰색', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0', '0', '10', '10', null, null],\n                type: 'CodeWiz_OLED_drawRect',\n            },\n            paramsKeyMap: {\n                SX: 0,\n                SY: 1,\n                WIDTH: 2,\n                HEIGHT: 3,\n                ISFILL: 4,\n                COLOR: 5,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _sx = script.getNumberValue('SX', script);\n                _sx = Math.round(_sx);\n                if (_sx < 0) {\n                    _sx = 0;\n                } else if (_sx > 128) {\n                    _sx = 128;\n                }\n                let _sy = script.getNumberValue('SY', script);\n                _sy = Math.round(_sy);\n                if (_sy < 0) {\n                    _sy = 0;\n                } else if (_sy > 64) {\n                    _sy = 64;\n                }\n                let _width = script.getNumberValue('WIDTH', script);\n                _width = Math.round(_width);\n                if (_width < 0) {\n                    _width = 0;\n                } else if (_width > 128) {\n                    _width = 128;\n                }\n                let _height = script.getNumberValue('HEIGHT', script);\n                _height = Math.round(_height);\n                if (_height < 0) {\n                    _height = 0;\n                } else if (_height > 64) {\n                    _height = 64;\n                }\n                let _isFill = script.getNumberValue('ISFILL', script);\n                let _color = script.getNumberValue('COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 21,\n                        x: _sx,\n                        y: _sy,\n                        params: [_sx, _sy, _width, _height, _isFill, _color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_drawCircle: {\n            // Block UI : \"OLED에 원 그리기 옵션(중심(%1,%2) 반지름%3, %4, %5)%6\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['비움', '0'],\n                        ['채움', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['검은색', '0'],\n                        ['흰색', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['30', '30', '10', null, null],\n                type: 'CodeWiz_OLED_drawCircle',\n            },\n            paramsKeyMap: {\n                RX: 0,\n                RY: 1,\n                RAD: 2,\n                ISFILL: 3,\n                COLOR: 4,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _rx = script.getNumberValue('RX', script);\n                _rx = Math.round(_rx);\n                if (_rx < 0) {\n                    _rx = 0;\n                } else if (_rx > 128) {\n                    _rx = 128;\n                }\n                let _ry = script.getNumberValue('RY', script);\n                _ry = Math.round(_ry);\n                if (_ry < 0) {\n                    _ry = 0;\n                } else if (_ry > 64) {\n                    _ry = 64;\n                }\n                let _rad = script.getNumberValue('RAD', script);\n                _rad = Math.round(_rad);\n                if (_rad < 0) {\n                    _rad = 0;\n                } else if (_rad > 255) {\n                    _rad = 255;\n                }\n                let _isFill = script.getNumberValue('ISFILL', script);\n                let _color = script.getNumberValue('COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 22,\n                        params: [_rx, _ry, _rad, _isFill, _color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_drawPoligon: {\n            // Block UI : \"OLED에 삼각형 그리기 옵션((%1,%2), (%3,%4), (%5,%6), %7, %8)%9\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['비움', '0'],\n                        ['채움', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['검은색', '0'],\n                        ['흰색', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0', '9', '6', '9', '3', '0', null, null],\n                type: 'CodeWiz_OLED_drawPoligon',\n            },\n            paramsKeyMap: {\n                X1: 0,\n                Y1: 1,\n                X2: 2,\n                Y2: 3,\n                X3: 4,\n                Y3: 5,\n                ISFILL: 6,\n                COLOR: 7,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _x1 = script.getNumberValue('X1', script);\n                _x1 = Math.round(_x1);\n                if (_x1 < 0) {\n                    _x1 = 0;\n                } else if (_x1 > 128) {\n                    _x1 = 128;\n                }\n                let _y1 = script.getNumberValue('Y1', script);\n                _y1 = Math.round(_y1);\n                if (_y1 < 0) {\n                    _y1 = 0;\n                } else if (_y1 > 64) {\n                    _y1 = 64;\n                }\n                let _x2 = script.getNumberValue('X2', script);\n                _x2 = Math.round(_x2);\n                if (_x2 < 0) {\n                    _x2 = 0;\n                } else if (_x2 > 128) {\n                    _x2 = 128;\n                }\n                let _y2 = script.getNumberValue('Y2', script);\n                _y2 = Math.round(_y2);\n                if (_y2 < 0) {\n                    _y2 = 0;\n                } else if (_y2 > 64) {\n                    _y2 = 64;\n                }\n                let _x3 = script.getNumberValue('X3', script);\n                _x3 = Math.round(_x3);\n                if (_x3 < 0) {\n                    _x3 = 0;\n                } else if (_x3 > 128) {\n                    _x3 = 128;\n                }\n                let _y3 = script.getNumberValue('Y3', script);\n                _y3 = Math.round(_y3);\n                if (_y3 < 0) {\n                    _y3 = 0;\n                } else if (_y3 > 64) {\n                    _y3 = 64;\n                }\n                let _isFill = script.getNumberValue('ISFILL', script);\n                let _color = script.getNumberValue('COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 23,\n                        params: [_x1, _y1, _x2, _y2, _x3, _y3, _isFill, _color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OLED_printHG: {\n            // OLED 한글 출력\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['❌', '0'],\n                        ['⭕', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['코드위즈 Magic!!', null],\n                type: 'CodeWiz_OLED_printHG',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                isLB: 1,\n            },\n            class: 'CodeWiz_OLED',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _value = script.getStringValue('TEXT');\n                let _isLB = script.getNumberValue('isLB', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 42,\n                        params: [_value, _isLB],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DIGITAL_OUTPUT_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_DIGITAL_OUTPUT_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_DIGITAL_OUTPUT_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_DIGITAL_OUTPUT_title',\n            },\n            class: 'CodeWiz_DIGITAL_OUTPUT',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_DIGITAL_OUTPUT_digitalWrite: {\n            // Block UI : \"터치센서 디지털 %1(으)로 %2내보내기%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['27', '27'],\n                        ['32', '32'],\n                        ['33', '33'],\n                        ['18', '18'],\n                        ['19', '19'],\n                    ],\n                    value: '13',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LOW', '0'],\n                        ['HIGH', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'CodeWiz_DIGITAL_OUTPUT_digitalWrite',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            class: 'CodeWiz_DIGITAL_OUTPUT',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _pin = script.getNumberValue('PIN', script);\n                let _val = script.getNumberValue('VALUE', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 25,\n                        params: [_pin, _val],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DIGITAL_OUTPUT_pwmWrite: {\n            // Block UI : \"터치센서 PWM %1(으)로 %2내보내기(0~1023)%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['27', '27'],\n                        ['32', '32'],\n                        ['33', '33'],\n                        ['18', '18'],\n                        ['19', '19'],\n                    ],\n                    value: '13',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '0'],\n                type: 'CodeWiz_DIGITAL_OUTPUT_pwmWrite',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            class: 'CodeWiz_DIGITAL_OUTPUT',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _pin = script.getNumberValue('PIN', script);\n                let _val = script.getNumberValue('VALUE', script);\n                _val = Math.round(_val);\n                if (_val < 0) {\n                    _val = 0;\n                } else if (_val > 1023) {\n                    _val = 1023;\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 26,\n                        params: [_pin, _val],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n\n        CodeWiz_HuskyLens_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_HuskyLens_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_HuskyLens_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_HuskyLens_title',\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n\n        /////////오즈아이 시작//////////////////////////////////////////////////////////////////////////////////////////////\n\n        CodeWiz_OzEye_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_OzEye_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_OzEye_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_OzEye_title',\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n\n        CodeWiz_OzEye_initOzEye: {\n            // Block UI : '오즈아이 시작설정%1',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OzEye_initOzEye',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 52,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                //delete Entry.hw.portData[id];\n            },\n        },\n\n        CodeWiz_OzEye_setModeOfOzEye: {\n            // Block UI : '오즈아이 %1알고리즘으로 설정%2'\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1.선 인식', '3'],\n                        ['2.색 인식', '4'],\n                        ['3.태그 인식', '5'],\n                        ['4.이미지 인식', '6'],\n                        ['5.사물 인식', '2'],\n                        ['6.사물 추적', '1'],\n                        ['7.선 + 태그', '7'],\n                        ['8.얼굴 인식', '0'],\n                        ['9.숫자 인식', '8'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OzEye_setModeOfOzEye',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let mode = script.getNumberValue('MODE', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 53,\n                        params: [mode],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                //delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OzEye_readOzEye: {\n            // Block UI : \"오즈아이 데이터 요청시작%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_OzEye_readOzEye',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 54,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                //delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OzEye_isLearnedOzEye: {\n            // Block UI : \"오즈아이 ID가%1인 데이터를 학습했는가?%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null],\n                type: 'CodeWiz_OzEye_isLearnedOzEye',\n            },\n            paramsKeyMap: {\n                ID: 0,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let learnId = script.getNumberValue('ID', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 15,\n                        params: [learnId],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                let retVal = Entry.hw.portData[id]?.value ?? false;\n                //delete Entry.hw.portData[id];\n\n                return retVal;\n            },\n        },\n        CodeWiz_OzEye_isContainOzEye: {\n            // Block UI : \"오즈아이 ID:%1로 인식한 %2데이터가 있는가?%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['사각형', '42'],\n                        ['화살표', '43'],\n                    ],\n                    value: '42',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null, null],\n                type: 'CodeWiz_OzEye_isContainOzEye',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _learnId = script.getNumberValue('ID', script);\n                let _type = script.getNumberValue('TYPE', script);\n                // console.log(this.sensorData);\n                // console.log(Entry.hw.portData.HUSKY_READ);\n                const huskyData = Entry.hw.portData.HUSKY_READ;\n                if (!huskyData._list || huskyData._list.length === 0) {\n                    return false;\n                }\n                if (huskyData?._type !== _type) {\n                    return false;\n                }\n                let _list = Entry.hw.portData.HUSKY_READ._list;\n                for (let i = 0; i < _list.length; ++i) {\n                    if (_list[i][0] === _learnId) {\n                        return true;\n                    }\n                }\n                return false;\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n            //     let _learnId = script.getNumberValue('ID', script);\n            //     let _type = script.getNumberValue('TYPE', script);\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 2,\n            //             params: [_learnId, _type],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n            //     let retVal= Entry.hw.portData[id]?.value ?? false;\n            //     //delete Entry.hw.portData[id];\n            //     return retVal;\n            // },\n        },\n        CodeWiz_OzEye_getCountLearnedOzEye: {\n            // Block UI : \"오즈아이가 감지한 학습데이터 수%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OzEye_getCountLearnedOzEye',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                return Entry.hw.portData.HUSKY_READ?._count ?? 0;\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 3,\n            //             params: [],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n\n            //     let retVal= Entry.hw.portData[id]?.value ?? 0;\n            //     //delete Entry.hw.portData[id];\n            //     return retVal;\n            // },\n        },\n        CodeWiz_OzEye_hasTypeOzEye: {\n            // Block UI : \"오즈아이가 읽은 데이터 타입이%1인가?%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['사각형', '42'],\n                        ['화살표', '43'],\n                    ],\n                    value: '42',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OzEye_hasTypeOzEye',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _type = script.getNumberValue('TYPE', script);\n                return Entry.hw.portData.HUSKY_READ?._type === _type;\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n            //     let _type = script.getNumberValue('TYPE', script);\n\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 4,\n            //             params: [_type],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n\n            //     let retVal= Entry.hw.portData[id]?.value ?? false;\n            //     //delete Entry.hw.portData[id];\n            //     return retVal\n            // },\n        },\n        CodeWiz_OzEye_getArrowInfoOzEye: {\n            // Block UI : \"오즈아이가 읽은 ID%1인 화살표정보%2%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시작 X좌표', '1'],\n                        ['시작 Y좌표', '2'],\n                        ['종료 X좌표', '3'],\n                        ['종료 Y좌표', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null],\n                type: 'CodeWiz_OzEye_getArrowInfoOzEye',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _id = script.getNumberValue('ID', script);\n                let _arrowType = script.getNumberValue('TYPE', script);\n                const huskyData = Entry.hw.portData.HUSKY_READ;\n                if (!huskyData._list || huskyData._list.length === 0) {\n                    return -1;\n                }\n                if (huskyData?._type !== 43) {\n                    return -1;\n                }\n                for (let i = 0; i < huskyData._list.length; ++i) {\n                    if (huskyData._list[i][0] === _id) {\n                        return huskyData._list[i][_arrowType];\n                    }\n                }\n                return -1;\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n            //     let _arrowType = script.getNumberValue('TYPE', script);\n\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 5,\n            //             params: [_arrowType],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n\n            //     let retVal= Entry.hw.portData[id]?.value ?? 0;\n            //     //delete Entry.hw.portData[id];\n            //     return retVal\n            // },\n        },\n        CodeWiz_OzEye_getBoxInfoOzEye2: {\n            // Block UI : \"오즈아이가 읽은 ID%1인 사각형정보%2%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['중심 X좌표', '1'],\n                        ['중심 Y좌표', '2'],\n                        ['너비', '3'],\n                        ['높이', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null],\n                type: 'CodeWiz_OzEye_getBoxInfoOzEye2',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _id = script.getNumberValue('ID', script);\n                let _boxType = script.getNumberValue('TYPE', script);\n                const huskyData = Entry.hw.portData.HUSKY_READ;\n                if (!huskyData._list || huskyData._list.length === 0) {\n                    return -1;\n                }\n                if (huskyData?._type !== 42) {\n                    return -1;\n                }\n                for (let i = 0; i < huskyData._list.length; ++i) {\n                    if (huskyData._list[i][0] === _id) {\n                        return huskyData._list[i][_boxType];\n                    }\n                }\n                return -1;\n            },\n        },\n        CodeWiz_OzEye_getBoxInfoOzEye: {\n            // Block UI : \"오즈아이가 읽은 사각형정보%1(중심좌표가 중앙에 가장 가까운 것)%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID', '0'],\n                        ['중심 X좌표', '1'],\n                        ['중심 Y좌표', '2'],\n                        ['너비', '3'],\n                        ['높이', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OzEye_getBoxInfoOzEye',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _boxType = script.getNumberValue('TYPE', script);\n                const huskyData = Entry.hw.portData.HUSKY_READ;\n                if (!huskyData._list || huskyData._list.length === 0) {\n                    return -1;\n                }\n                if (huskyData?._type !== 42 || huskyData?._count === 0) {\n                    return -1;\n                }\n                let curIdx = 0;\n                let dist = Entry.CodeWiz.HUSKY.getDist(\n                    huskyData._list[0][0],\n                    huskyData._list[0][1]\n                );\n                let curDist;\n                for (let i = 1; i < huskyData._count; ++i) {\n                    curDist = Entry.CodeWiz.HUSKY.getDist(\n                        huskyData._list[i][0],\n                        huskyData._list[i][1]\n                    );\n                    if (dist > curDist) {\n                        dist = curDist;\n                        curIdx = i;\n                    }\n                }\n                return huskyData._list[curIdx][_boxType];\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n            //     let _boxType = script.getNumberValue('TYPE', script);\n\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 6,\n            //             params: [_boxType],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n\n            //     let retVal= Entry.hw.portData[id]?.value ?? 0;\n            //     //delete Entry.hw.portData[id];\n            //     return retVal\n            // },\n        },\n\n        //오즈아이에 텍스트 출력하기 기능 이후 적용\n        /*\n        CodeWiz_OzEye_writeTextOzEye: {\n            // Block UI : \"오즈아이 x:%1 y:%2에 %3출력%4\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [0, 0, 'CodeWiz'],\n                type: 'CodeWiz_OzEye_writeTextOzEye',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                TEXT: 2,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _x = script.getNumberValue('X', script);\n                let _y = script.getNumberValue('Y', script);\n                let _text = script.getStringValue('TEXT');\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 55,\n                        params: [_x, _y, _text],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                //delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_OzEye_clearTextOzEye: {\n            // Block UI : \"오즈아이 텍스트 지우기%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_OzEye_clearTextOzEye',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 56,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                //delete Entry.hw.portData[id];\n            },\n        },\n        */\n\n        CodeWiz_OzEye_setLightLevel: {\n            // Block UI : '오즈아이 라이트 밝기를 %1 단계로 설정(1~7)%2',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OzEye_setLightLevel',\n            },\n            paramsKeyMap: {\n                Level: 0,\n            },\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let Level = script.getNumberValue('Level', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 57,\n                        params: [Level],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                //delete Entry.hw.portData[id];\n            },\n        },\n\n        CodeWiz_OzEye_LightOff: {\n            // Block UI : '오즈아이 라이트 끄기%1',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_OzEye_LightOff',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_OzEye',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 58,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                //delete Entry.hw.portData[id];\n            },\n        },\n\n        //////////오즈아이 끝/////////////////////////////////////////////////////////////////////////////////////////////\n\n        CodeWiz_HuskyLens_initHuskyLens: {\n            // Block UI : '허스키렌즈 시작설정%1',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_HuskyLens_initHuskyLens',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 27,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_HuskyLens_setModeOfHuskyLens: {\n            // Block UI : '허스키렌즈 %1알고리즘으로 설정%2'\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1.FACE_RECOGNITION', '0'],\n                        ['2.OBJECT_TRACKING', '1'],\n                        ['3.OBJECT_RECOGNITION', '2'],\n                        ['4.LINE_TRACKING', '3'],\n                        ['5.COLOR_RECOGNITION', '4'],\n                        ['6.TAG_RECOGNITION', '5'],\n                        ['7.OBJECT_CLASSIFICATION', '6'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_HuskyLens_setModeOfHuskyLens',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let mode = script.getNumberValue('MODE', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 28,\n                        params: [mode],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_HuskyLens_readHuskyLens: {\n            // Block UI : \"허스키렌즈 데이터 요청시작%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_HuskyLens_readHuskyLens',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 29,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_HuskyLens_isLearnedHuskyLens: {\n            // Block UI : \"허스키렌즈 ID가%1인 데이터를 학습했는가?%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null],\n                type: 'CodeWiz_HuskyLens_isLearnedHuskyLens',\n            },\n            paramsKeyMap: {\n                ID: 0,\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let learnId = script.getNumberValue('ID', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 1,\n                        params: [learnId],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                let retVal = Entry.hw.portData[id]?.value ?? false;\n                delete Entry.hw.portData[id];\n\n                return retVal;\n            },\n        },\n        CodeWiz_HuskyLens_isContainHuskyLens: {\n            // Block UI : \"허스키렌즈 ID:%1로 인식한 %2데이터가 있는가?%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['사각형', '42'],\n                        ['화살표', '43'],\n                    ],\n                    value: '42',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null, null],\n                type: 'CodeWiz_HuskyLens_isContainHuskyLens',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _learnId = script.getNumberValue('ID', script);\n                let _type = script.getNumberValue('TYPE', script);\n                // console.log(Entry.hw.portData);\n                // console.log(Entry.hw.portData.HUSKY_READ);\n                const huskyData = Entry.hw.portData.HUSKY_READ;\n                if (!huskyData._list || huskyData._list.length === 0) {\n                    return false;\n                }\n                if (huskyData?._type !== _type) {\n                    return false;\n                }\n                let _list = Entry.hw.portData.HUSKY_READ._list;\n                for (let i = 0; i < _list.length; ++i) {\n                    if (_list[i][0] === _learnId) {\n                        return true;\n                    }\n                }\n                return false;\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n            //     let _learnId = script.getNumberValue('ID', script);\n            //     let _type = script.getNumberValue('TYPE', script);\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 2,\n            //             params: [_learnId, _type],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n            //     let retVal= Entry.hw.portData[id]?.value ?? false;\n            //     delete Entry.hw.portData[id];\n            //     return retVal;\n            // },\n        },\n        CodeWiz_HuskyLens_getCountLearnedHuskyLens: {\n            // Block UI : \"허스키렌즈가 감지한 학습데이터 수%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_HuskyLens_getCountLearnedHuskyLens',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                return Entry.hw.portData.HUSKY_READ?._count ?? 0;\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 3,\n            //             params: [],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n\n            //     let retVal= Entry.hw.portData[id]?.value ?? 0;\n            //     delete Entry.hw.portData[id];\n            //     return retVal;\n            // },\n        },\n        CodeWiz_HuskyLens_hasTypeHuskyLens: {\n            // Block UI : \"허스키렌즈가 읽은 데이터 타입이%1인가?%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['사각형', '42'],\n                        ['화살표', '43'],\n                    ],\n                    value: '42',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_HuskyLens_hasTypeHuskyLens',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _type = script.getNumberValue('TYPE', script);\n                return Entry.hw.portData.HUSKY_READ?._type === _type;\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n            //     let _type = script.getNumberValue('TYPE', script);\n\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 4,\n            //             params: [_type],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n\n            //     let retVal= Entry.hw.portData[id]?.value ?? false;\n            //     delete Entry.hw.portData[id];\n            //     return retVal\n            // },\n        },\n        CodeWiz_HuskyLens_getArrowInfoHuskyLens: {\n            // Block UI : \"허스키렌즈가 읽은 ID%1인 화살표정보%2%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시작 X좌표', '1'],\n                        ['시작 Y좌표', '2'],\n                        ['종료 X좌표', '3'],\n                        ['종료 Y좌표', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null],\n                type: 'CodeWiz_HuskyLens_getArrowInfoHuskyLens',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _id = script.getNumberValue('ID', script);\n                let _arrowType = script.getNumberValue('TYPE', script);\n                const huskyData = Entry.hw.portData.HUSKY_READ;\n                if (!huskyData._list || huskyData._list.length === 0) {\n                    return -1;\n                }\n                if (huskyData?._type !== 43) {\n                    return -1;\n                }\n                for (let i = 0; i < huskyData._list.length; ++i) {\n                    if (huskyData._list[i][0] === _id) {\n                        return huskyData._list[i][_arrowType];\n                    }\n                }\n                return -1;\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n            //     let _arrowType = script.getNumberValue('TYPE', script);\n\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 5,\n            //             params: [_arrowType],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n\n            //     let retVal= Entry.hw.portData[id]?.value ?? 0;\n            //     delete Entry.hw.portData[id];\n            //     return retVal\n            // },\n        },\n        CodeWiz_HuskyLens_getBoxInfoHuskyLens2: {\n            // Block UI : \"허스키렌즈가 읽은 ID%1인 사각형정보%2%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['중심 X좌표', '1'],\n                        ['중심 Y좌표', '2'],\n                        ['너비', '3'],\n                        ['높이', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1, null],\n                type: 'CodeWiz_HuskyLens_getBoxInfoHuskyLens2',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _id = script.getNumberValue('ID', script);\n                let _boxType = script.getNumberValue('TYPE', script);\n                const huskyData = Entry.hw.portData.HUSKY_READ;\n                if (!huskyData._list || huskyData._list.length === 0) {\n                    return -1;\n                }\n                if (huskyData?._type !== 42) {\n                    return -1;\n                }\n                for (let i = 0; i < huskyData._list.length; ++i) {\n                    if (huskyData._list[i][0] === _id) {\n                        return huskyData._list[i][_boxType];\n                    }\n                }\n                return -1;\n            },\n        },\n        CodeWiz_HuskyLens_getBoxInfoHuskyLens: {\n            // Block UI : \"허스키렌즈가 읽은 사각형정보%1(중심좌표가 중앙에 가장 가까운 것)%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID', '0'],\n                        ['중심 X좌표', '1'],\n                        ['중심 Y좌표', '2'],\n                        ['너비', '3'],\n                        ['높이', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_HuskyLens_getBoxInfoHuskyLens',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            func(sprite, script) {\n                let _boxType = script.getNumberValue('TYPE', script);\n                const huskyData = Entry.hw.portData.HUSKY_READ;\n                if (!huskyData._list || huskyData._list.length === 0) {\n                    return -1;\n                }\n                if (huskyData?._type !== 42 || huskyData?._count === 0) {\n                    return -1;\n                }\n                let curIdx = 0;\n                let dist = Entry.CodeWiz.HUSKY.getDist(\n                    huskyData._list[0][0],\n                    huskyData._list[0][1]\n                );\n                let curDist;\n                for (let i = 1; i < huskyData._count; ++i) {\n                    curDist = Entry.CodeWiz.HUSKY.getDist(\n                        huskyData._list[i][0],\n                        huskyData._list[i][1]\n                    );\n                    if (dist > curDist) {\n                        dist = curDist;\n                        curIdx = i;\n                    }\n                }\n                return huskyData._list[curIdx][_boxType];\n            },\n            // async func(sprite, script) {\n            //     if (Entry.CodeWiz.intervalId) {\n            //         await Entry.CodeWiz.preWait();\n            //     }\n            //     let _boxType = script.getNumberValue('TYPE', script);\n\n            //     const order = {\n            //         type: Entry.CodeWiz.sensorTypes.READ,\n            //         value: {\n            //             opcode: 6,\n            //             params: [_boxType],\n            //         },\n            //     };\n            //     const id = Entry.CodeWiz.sendOrder(order);\n            //     await Entry.CodeWiz.checkComplete(1000, id);\n\n            //     let retVal= Entry.hw.portData[id]?.value ?? 0;\n            //     delete Entry.hw.portData[id];\n            //     return retVal\n            // },\n        },\n        CodeWiz_HuskyLens_writeTextHuskyLens: {\n            // Block UI : \"허스키렌즈 x:%1 y:%2에 %3출력%4\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [0, 0, 'CodeWiz'],\n                type: 'CodeWiz_HuskyLens_writeTextHuskyLens',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                TEXT: 2,\n            },\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _x = script.getNumberValue('X', script);\n                let _y = script.getNumberValue('Y', script);\n                let _text = script.getStringValue('TEXT');\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 30,\n                        params: [_x, _y, _text],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_HuskyLens_clearTextHuskyLens: {\n            // Block UI : \"허스키렌즈 텍스트 지우기%1\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_HuskyLens_clearTextHuskyLens',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_HuskyLens',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 31,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n\n        CodeWiz_Servo_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_Servo_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_Servo_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_Servo_title',\n            },\n            class: 'CodeWiz_Servo',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_Servo_setAngle: {\n            // Block UI : \"서보모터(%1) 각도를 %2로 바꾸기%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['SCON', '18.0'],\n                        ['MCON-18', '18.1'],\n                        ['MCON-19', '19'],\n                        ['MCON-15', '15'],\n                        ['MCON-27', '27'],\n                    ],\n                    value: '18.0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '0'],\n                type: 'CodeWiz_Servo_setAngle',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            class: 'CodeWiz_Servo',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _pin = Number.parseInt(script.getNumberValue('PIN', script));\n                let _value = Number.parseInt(script.getNumberValue('VALUE', script));\n                _value = Math.round(_value);\n                if (_value < 0) {\n                    _value = 0;\n                } else if (_value > 180) {\n                    _value = 180;\n                }\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 33,\n                        params: [_pin, _value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_Servo_menuSpeed: {\n            // Block UI : \"무한회전 서보모터(%1) %2속도로 정하기%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['SCON', '18.0'],\n                        ['MCON-18', '18.1'],\n                        ['MCON-19', '19'],\n                        ['MCON-15', '15'],\n                        ['MCON-27', '27'],\n                    ],\n                    value: '18.0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빠른', '21'],\n                        ['보통', '39'],\n                        ['느린', '58'],\n                        ['멈춘', '76'],\n                    ],\n                    value: '21',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'CodeWiz_Servo_menuSpeed',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            class: 'CodeWiz_Servo',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _pin = Number.parseInt(script.getNumberValue('PIN', script));\n                let _value = script.getNumberValue('VALUE', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 34,\n                        params: [_pin, _value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_Servo_customSpeed: {\n            // Block UI : \"무한회전 서보모터(%1) %2속도로 정하기(-100~100)%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['SCON', '18.0'],\n                        ['MCON-18', '18.1'],\n                        ['MCON-19', '19'],\n                        ['MCON-15', '15'],\n                        ['MCON-27', '27'],\n                    ],\n                    value: '18.0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '100'],\n                type: 'CodeWiz_Servo_customSpeed',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            class: 'CodeWiz_Servo',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _pin = Number.parseInt(script.getNumberValue('PIN', script));\n                let _value = Number.parseInt(script.getNumberValue('VALUE', script));\n                if (_value < -100) {\n                    _value = -100;\n                } else if (_value > 100) {\n                    _value = 100;\n                }\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 35,\n                        params: [_pin, _value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n\n        CodeWiz_Dc_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_Dc_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_Dc_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_Dc_title',\n            },\n            class: 'CodeWiz_Dc',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_Dc_setCarSpeed: {\n            // Block UI : 'WizCar 모터에 %1,%2내보내기(-1000~1000)%3',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['600', '600'],\n                type: 'CodeWiz_Dc_setCarSpeed',\n            },\n            paramsKeyMap: {\n                L_VALUE: 0,\n                R_VALUE: 1,\n            },\n            class: 'CodeWiz_Dc',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _lValue = Number.parseInt(script.getNumberValue('L_VALUE', script));\n                let _rValue = Number.parseInt(script.getNumberValue('R_VALUE', script));\n                _lValue = Math.min(Math.max(-1000, _lValue), 1000);\n                _rValue = Math.min(Math.max(-1000, _rValue), 1000);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 51,\n                        params: [_lValue, _rValue],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_Dc_setValue_Waterpump: {\n            // 워터펌프\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['MOTOR_L', '0'],\n                        ['MOTOR_R', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '1023'],\n                type: 'CodeWiz_Dc_setValue_Waterpump',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            class: 'CodeWiz_Dc',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _pin = script.getNumberValue('PIN', script);\n                let _value = Number.parseInt(script.getNumberValue('VALUE', script));\n                if (_value < 0) {\n                    _value = 0;\n                } else if (_value > 1023) {\n                    _value = 1023;\n                }\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 36,\n                        params: [_pin, 1, _value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DotMatrix_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_DotMatrix_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_DotMatrix_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_DotMatrix_title',\n            },\n            class: 'CodeWiz_DotMatrix',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_DotMatrix_init: {\n            // Block UI : '도트매트릭스 %1개 DIN%2, CS%3, CLK%4에 시작설정%5',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['18', '18'],\n                        ['19', '19'],\n                        ['15', '15'],\n                        ['27', '27'],\n                    ],\n                    value: '18',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['18', '18'],\n                        ['19', '19'],\n                        ['15', '15'],\n                        ['27', '27'],\n                    ],\n                    value: '19',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['18', '18'],\n                        ['19', '19'],\n                        ['15', '15'],\n                        ['27', '27'],\n                    ],\n                    value: '15',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', null, null, null],\n                type: 'CodeWiz_DotMatrix_init',\n            },\n            paramsKeyMap: {\n                COUNT: 0,\n                PIN1: 1,\n                PIN2: 2,\n                PIN3: 3,\n            },\n            class: 'CodeWiz_DotMatrix',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _count = Number.parseInt(script.getNumberValue('COUNT', script));\n                if (_count <= 0) {\n                    return;\n                } else if (_count > 8) {\n                    _count = 8;\n                }\n                let _pins = [\n                    script.getNumberValue('PIN1', script),\n                    script.getNumberValue('PIN2', script),\n                    script.getNumberValue('PIN3', script),\n                ];\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 24,\n                        params: [_count, ..._pins],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DotMatrix_setBrightness: {\n            // Block UI : '도트매트릭스 %1번 밝기를 %2로 설정%3',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '8'],\n                type: 'CodeWiz_DotMatrix_setBrightness',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'CodeWiz_DotMatrix',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                if (_num < 1) {\n                    num = 1;\n                } else if (_num > 8) {\n                    _num = 8;\n                }\n                let _brightness = Number.parseInt(script.getNumberValue('BRIGHTNESS', script));\n                if (_brightness < 1) {\n                    _brightness = 1;\n                } else if (_brightness > 15) {\n                    _brightness = 15;\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 37,\n                        params: [_num, _brightness],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DotMatrix_printString: {\n            // Block UI : '도트매트릭스 %1번에 문자열%2 출력%3',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', 'HELLO'],\n                type: 'CodeWiz_DotMatrix_printString',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                TEXT: 1,\n            },\n            class: 'CodeWiz_DotMatrix',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                if (_num < 1) {\n                    num = 1;\n                } else if (_num > 8) {\n                    _num = 8;\n                }\n                let _value = script.getStringValue('TEXT');\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 38,\n                        params: [_num, _value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DotMatrix_setLine: {\n            // Block UI : '도트매트릭스 %1번에 %2번%3 %4로 만들기%5',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['행', '1'],\n                        ['열', '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '2', null, '11111111'],\n                type: 'CodeWiz_DotMatrix_setLine',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                NUM_LINE: 1,\n                IS_ROW: 2,\n                VALUE: 3,\n            },\n            class: 'CodeWiz_DotMatrix',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                if (_num < 1) {\n                    num = 1;\n                } else if (_num > 8) {\n                    _num = 8;\n                }\n                let _numLine = Number.parseInt(script.getNumberValue('NUM_LINE', script));\n                if (_numLine < 1) {\n                    _numLine = 1;\n                } else if (_numLine > 8) {\n                    _numLine = 8;\n                }\n                let _isRow = script.getNumberValue('IS_ROW', script);\n                let _value = script.getStringValue('VALUE');\n                const _f = (str) => {\n                    str = str.substring(0, 8);\n                    let retVal = '';\n                    for (let i = 0; i < str.length; ++i) {\n                        if (str[i] === '0' || str[i] === ' ') {\n                            retVal += '0';\n                        } else {\n                            retVal += '1';\n                        }\n                    }\n                    return retVal.padStart(8, '0');\n                };\n                _value = _f(_value);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 39,\n                        params: [_num, _numLine, _isRow, _value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DotMatrix_setDot: {\n            // Block UI : '도트매트릭스 %1번에 %2행%3열 %4%5',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', '1'],\n                        ['끄기', '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '2', '2', null],\n                type: 'CodeWiz_DotMatrix_setDot',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                ROW: 1,\n                COL: 2,\n                VALUE: 3,\n            },\n            class: 'CodeWiz_DotMatrix',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                if (_num < 1) {\n                    num = 1;\n                } else if (_num > 8) {\n                    _num = 8;\n                }\n                let _numRow = Number.parseInt(script.getNumberValue('ROW', script));\n                if (_numRow < 1) {\n                    _numRow = 1;\n                } else if (_numRow > 8) {\n                    _numRow = 8;\n                }\n                let _numCol = Number.parseInt(script.getNumberValue('COL', script));\n                if (_numCol < 1) {\n                    _numCol = 1;\n                } else if (_numCol > 8) {\n                    _numCol = 8;\n                }\n                let _value = script.getNumberValue('VALUE', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 40,\n                        params: [_num, _numRow, _numCol, _value],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DotMatrix_clear: {\n            // Block UI : '도트매트릭스 %1번 지우기%2',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'CodeWiz_DotMatrix_clear',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'CodeWiz_DotMatrix',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                if (_num < 1) {\n                    num = 1;\n                } else if (_num > 8) {\n                    _num = 8;\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 41,\n                        params: [_num - 1],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n        CodeWiz_DotMatrix_clearAll: {\n            // Block UI : '도트매트릭스 모두 지우기%1',\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'CodeWiz_DotMatrix_clearAll',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_DotMatrix',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 41,\n                        params: [-1],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                delete Entry.hw.portData[id];\n            },\n        },\n\n        CodeWiz_ColorSensor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_ColorSensor_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_ColorSensor_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_ColorSensor_title',\n            },\n            class: 'CodeWiz_ColorSensor',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_ColorSensor_isColor: {\n            // Block UI : \"MCON 컬러센서 감지된 색이 %1인가%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빨강', '0'],\n                        ['초록', '1'],\n                        ['파랑', '2'],\n                        ['검정', '3'],\n                        ['흰색', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_ColorSensor_isColor',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'CodeWiz_ColorSensor',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _color = script.getNumberValue('COLOR', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 8,\n                        params: [_color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n\n                let retVal = Entry.hw.portData[id]?.value ?? false;\n                delete Entry.hw.portData[id];\n                return retVal;\n            },\n        },\n        CodeWiz_ColorSensor_getColorValue: {\n            // Block UI : \"MCON 컬러센서 %1값%2\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빨강', '0'],\n                        ['초록', '1'],\n                        ['파랑', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_ColorSensor_getColorValue',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'CodeWiz_ColorSensor',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _color = script.getNumberValue('COLOR', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 9,\n                        params: [_color],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n\n                let retVal = Entry.hw.portData[id]?.value ?? 0;\n                delete Entry.hw.portData[id];\n                return retVal;\n            },\n        },\n\n        CodeWiz_DHT_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_DHT_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_DHT_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_DHT_title',\n            },\n            class: 'CodeWiz_DHT',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_DHT_init: {\n            // 디지털온습도 설정\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['27', '27'],\n                        ['32', '32'],\n                        ['33', '33'],\n                        ['18', '18'],\n                        ['19', '19'],\n                    ],\n                    value: '18',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_DHT_init',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n            },\n            class: 'CodeWiz_DHT',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _pin = script.getNumberValue('PIN', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 48,\n                        params: [_pin],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n            },\n        },\n        CodeWiz_DHT_getValue: {\n            // 디지털 온습도 값\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['℃', '0'],\n                        ['℉', '1'],\n                        ['습도', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_DHT_getValue',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'CodeWiz_DHT',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _type = script.getNumberValue('TYPE', script);\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 12,\n                        params: [_type],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n\n                let retVal = Entry.hw.portData[id]?.value ?? 0.0;\n                delete Entry.hw.portData[id];\n                return retVal;\n            },\n        },\n        CodeWiz_Joystick_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.CodeWiz_Joystick_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_Joystick_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_Joystick_title',\n            },\n            class: 'CodeWiz_Joystick',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_Joystick_setPin: {\n            // 조이스틱 설정\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['32', '32'],\n                        ['33', '33'],\n                        ['36', '36'],\n                        ['39', '39'],\n                    ],\n                    value: '36',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['32', '32'],\n                        ['33', '33'],\n                        ['36', '36'],\n                        ['39', '39'],\n                    ],\n                    value: '39',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['27', '27'],\n                        ['18', '18'],\n                        ['19', '19'],\n                    ],\n                    value: '15',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, 12],\n                type: 'CodeWiz_Joystick_setPin',\n            },\n            paramsKeyMap: {\n                PIN_X: 0,\n                PIN_Y: 1,\n                PIN_B: 2,\n                RANGE: 3,\n            },\n            class: 'CodeWiz_Joystick',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                let _pinX = script.getNumberValue('PIN_X', script);\n                let _pinY = script.getNumberValue('PIN_Y', script);\n                let _pinB = script.getNumberValue('PIN_B', script);\n                let _range = script.getNumberValue('RANGE', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.WRITE,\n                    value: {\n                        opcode: 50,\n                        params: [_pinX, _pinY, _pinB, _range],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n            },\n        },\n        CodeWiz_Joystick_readAxis: {\n            // 조이스틱 XY레버값\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X축', '0'],\n                        ['Y축', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_Joystick_readAxis',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'CodeWiz_Joystick',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _type = script.getNumberValue('TYPE', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 13,\n                        params: [_type],\n                    },\n                };\n\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n\n                let retVal = Entry.hw.portData[id]?.value ?? 0;\n                delete Entry.hw.portData[id];\n                // console.log(_type===0?\"X:\":\"Y:\",retVal);\n                return retVal;\n            },\n        },\n        CodeWiz_Joystick_readButton: {\n            // 조이스틱 버튼값\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_Joystick_readButton',\n            },\n            paramsKeyMap: {},\n            class: 'CodeWiz_Joystick',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 14,\n                        params: [],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n                let retVal = Entry.hw.portData[id]?.value ?? false;\n                delete Entry.hw.portData[id];\n                // console.log(\"Button:\",retVal);\n                return retVal;\n            },\n        },\n\n        CodeWiz_etcReadSensor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: 5 + this.getOffsetX(Lang.template.CodeWiz_etcReadSensor_title),\n                    offsetY: 5,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#333333',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.CodeWiz_etcReadSensor_title,\n                    color: '#333333',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'CodeWiz_etcReadSensor_title',\n            },\n            class: 'CodeWiz_etcReadSensor',\n            isNotFor: ['CodeWiz'],\n            events: {},\n        },\n        CodeWiz_etcReadSensor_mconRead: {\n            // 가변저항, 워터센서, 토양수분센서\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가변저항', '0'],\n                        ['워터센서', '1'],\n                        ['토양수분센서', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['32', '32'],\n                        ['33', '33'],\n                        ['36', '36'],\n                        ['39', '39'],\n                    ],\n                    value: '36',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_etcReadSensor_mconRead',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n                PIN: 1,\n            },\n            class: 'CodeWiz_etcReadSensor',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _type = script.getNumberValue('TYPE', script);\n                let _pin = script.getNumberValue('PIN', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 10,\n                        params: [_type, _pin],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n\n                let retVal = Entry.hw.portData[id]?.value ?? 0;\n                delete Entry.hw.portData[id];\n                return retVal;\n            },\n        },\n        CodeWiz_etcReadSensor_digitalRead: {\n            // 버튼, 포토인터럽트\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['버튼', '0'],\n                        ['포토인터럽트', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['27', '27'],\n                        ['32', '32'],\n                        ['33', '33'],\n                        ['18', '18'],\n                        ['19', '19'],\n                    ],\n                    value: '18',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_etcReadSensor_digitalRead',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n                PIN: 1,\n            },\n            class: 'CodeWiz_etcReadSensor',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _type = script.getNumberValue('TYPE', script);\n                let _pin = script.getNumberValue('PIN', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 11,\n                        params: [_type, _pin],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n\n                let retVal = Entry.hw.portData[id]?.value ?? false;\n                delete Entry.hw.portData[id];\n                return retVal;\n            },\n        },\n        CodeWiz_etcReadSensor_InfraredThermometerRead: {\n            // Block UI : \"비접촉온도센서 %1에 %2로 읽기%3\",\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['SCON', '0'],\n                        ['MCON', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['℃', '0'],\n                        ['℉', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'CodeWiz_etcReadSensor_InfraredThermometerRead',\n            },\n            paramsKeyMap: {\n                IS_M: 0,\n                IS_F: 1,\n            },\n            class: 'CodeWiz_etcReadSensor',\n            isNotFor: ['CodeWiz'],\n            async func(sprite, script) {\n                if (Entry.CodeWiz.intervalId) {\n                    await Entry.CodeWiz.preWait();\n                }\n                let _isM = script.getNumberValue('IS_M', script);\n                let _isF = script.getNumberValue('IS_F', script);\n\n                const order = {\n                    type: Entry.CodeWiz.sensorTypes.READ,\n                    value: {\n                        opcode: 8,\n                        params: [_isM, _isF],\n                    },\n                };\n                const id = Entry.CodeWiz.sendOrder(order);\n                await Entry.CodeWiz.checkComplete(1000, id);\n\n                let retVal = Entry.hw.portData[id]?.value ?? 0;\n                delete Entry.hw.portData[id];\n                return retVal;\n            },\n        },\n        //endregion CodeWiz 코드위즈\n    };\n};\n\nmodule.exports = Entry.CodeWiz;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_coding_box.js",
    "content": "'use strict';\n\nEntry.CodingBox = {\n    id: '1.C',\n    name: 'CodingBox',\n    url: 'http://smartstore.naver.com/domekit',\n    imageName: 'codingbox.png',\n    title: {\n        ko: '코딩박스',\n        en: 'CodingBox',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n            Entry.hw.sendQueue['SET'][Entry.CodingBox.sensorTypes.LCD_INIT] = {\n                port: 0,\n                time: new Date().getTime(),\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    pins: {\n        POTENTIOMETER: 0,\n        MIC: 1,\n        SWITCH_1: 2,\n        SWITCH_2: 3,\n        BUZZER: 2,\n        LINE: 3,\n        ULTRASONIC_TRIG: 4,\n        ULTRASONIC_ECHO: 7,\n        SERVO: 5,\n        DCM_A: 6,\n        DCM_B: 9,\n        LED_1: 10,\n        LED_2: 11,\n        RGB_R: 8,\n        RGB_B: 12,\n        RGB_G: 13,\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        LCD_PRINT: 9,\n        LCD_CLEAR: 10,\n        LCD_INIT: 11,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.CodingBox.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n                CBX_LED_ON: '켜짐',\n                CBX_LED_OFF: '꺼짐',\n                CBX_DCM_FORWARD: '정회전',\n                CBX_DCM_BACKWARD: '역회전',\n                CBX_DCM_SPEED_MAX: '최대속도',\n                CBX_DCM_SPEED_STOP: '정지',\n            },\n            template: {\n                cbx_arduino_get_analog_value: '아날로그 %1 번 센서값',\n                cbx_arduino_get_analog_value_map:\n                    '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                cbx_arudino_read_ultrasonic_value:\n                    '울트라소닉 Trig %1 Echo %2 센서값',\n                cbx_arduino_toggle_led: '디지털 %1 번 핀 %2 %3',\n                cbx_arduino_digital_pwm:\n                    '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                cbx_arduino_write_tone:\n                    '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                cbx_arduino_write_servo:\n                    '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                cbx_arduino_read_digital: '디지털 %1 번 센서값',\n                cbx_write_servo: '서보모터 각도를 %1 도로 정하기 %2',\n                cbx_write_tone: '부저를 %1 %2 음으로 %3 초 연주하기 %4',\n                cbx_write_led: '%1 을 %2 로 정하기 %3',\n                cbx_write_dcm: 'DC모터를 %1 방향, 속도 %2 로 정하기 %3',\n                cbx_write_rgb_led:\n                    '빨강을 %1 으로, 초록을 %2 으로, 파랑 %3 으로 정하기 %4',\n                cbx_write_lcd: 'LCD %1 줄 %2 칸에 %3 을 쓰기 %4',\n                cbx_clear_lcd: 'LCD 화면 지우기 %1',\n                cbx_read_line: '라인센서 값',\n                cbx_read_switch: '%1 값',\n                cbx_read_mic: '마이크 값',\n                cbx_read_potentiometer: '가변저항 값',\n                cbx_read_ultrasonic: '초음파센서 값',\n            },\n        },\n        en: {\n            Blocks: {\n                CBX_LED_ON: 'On',\n                CBX_LED_OFF: 'Off',\n                CBX_DCM_FORWARD: 'Forward',\n                CBX_DCM_BACKWARD: 'Backward',\n                CBX_DCM_SPEED_MAX: 'MaxSpeed',\n                CBX_DCM_SPEED_STOP: 'Stop',\n            },\n            template: {\n                cbx_arduino_get_analog_value: 'Analog %1 Sensor value',\n                cbx_arduino_get_analog_value_map:\n                    'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                cbx_arudino_read_ultrasonic_value:\n                    'Read ultrasonic sensor trig pin %1 echo pin %2',\n                cbx_arduino_toggle_led: 'Digital %1 Pin %2 %3',\n                cbx_arduino_digital_pwm: 'Digital %1 Pin %2 %3',\n                cbx_arduino_write_tone:\n                    'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                cbx_arduino_write_servo: 'Set servo pin %1 angle as %2 %3',\n                cbx_arduino_read_digital: 'Digital %1 Sensor value',\n                cbx_write_led: '%1 set to %2 %3',\n                cbx_write_rgb_led: 'set red %1 , green %2 , blue %3 %4',\n                cbx_write_tone: 'note %1 octave %2 beat %3 %4',\n                cbx_write_servo: 'set servo angle %1 %2',\n                cbx_write_dcm: 'write DC motor direction %1 , speed %2 %3',\n                cbx_write_lcd: 'write on %1 line %2 column %3  %4',\n                cbx_clear_lcd: 'clear LCD screen %1',\n                cbx_read_line: 'line sensor value',\n                cbx_read_mic: 'mic value',\n                cbx_read_switch: '%1 value',\n                cbx_read_potentiometer: 'potentiometer value',\n                cbx_read_ultrasonic: ' Ultrasonic value',\n            },\n        },\n    };\n};\nEntry.CodingBox.blockMenuBlocks = [\n    'cbx_read_line',\n    'cbx_read_mic',\n    'cbx_read_switch',\n    'cbx_read_potentiometer',\n    'cbx_read_ultrasonic',\n    'cbx_write_led',\n    'cbx_write_rgb_led',\n    'cbx_write_tone',\n    'cbx_write_dcm',\n    'cbx_write_servo',\n    'cbx_write_lcd',\n    'cbx_clear_lcd',\n    'cbx_arduino_get_analog_value',\n    'cbx_arduino_get_analog_value_map',\n    'cbx_arudino_read_ultrasonic_value',\n    'cbx_arduino_read_digital',\n    'cbx_arduino_toggle_led',\n    'cbx_arduino_digital_pwm',\n    'cbx_arduino_write_servo',\n    'cbx_arduino_write_tone',\n];\n//region CodingBox 아두이노 확장모드\nEntry.CodingBox.getBlocks = function() {\n    return {\n        coding_box_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter:\n                                    Entry.block.converters.returnStringKey,\n                                codeMap:\n                                    'Entry.CodeMap.Arduino.arduino_ext_analog_list[0]',\n                                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'coding_box_analog_list',\n                    },\n                ],\n            },\n        },\n        cbx_arduino_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'coding_box_analog_list',\n                    },\n                ],\n                type: 'cbx_arduino_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CodingBoxArduinoRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_arduino_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cbx_arduino_get_analog_value',\n                        params: [\n                            {\n                                type: 'coding_box_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'cbx_arduino_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'CodingBoxArduinoRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var result = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var stringValue4 = script.getValue('VALUE4', script);\n                var stringValue5 = script.getValue('VALUE5', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) &&\n                        stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) &&\n                        stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_arudino_read_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'cbx_arudino_read_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'CodingBoxArduinoRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][\n                    Entry.CodingBox.sensorTypes.ULTRASONIC\n                ] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_arduino_read_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'cbx_arduino_read_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CodingBoxArduinoRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n\n                if (name === 'CodingBox') {\n                    var port = script.getNumberValue('PORT', script);\n                    var DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][\n                        Entry.CodingBox.sensorTypes.DIGITAL\n                    ] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(\n                        sprite,\n                        script\n                    );\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, 'on'],\n                        [Lang.Blocks.ARDUINO_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringValueUpperCase,\n                                codeMap:\n                                    'Entry.CodeMap.Arduino.arduino_get_digital_toggle[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_digital_toggle',\n                    },\n                ],\n            },\n        },\n        cbx_arduino_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'cbx_arduino_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CodingBoxArduinoWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.CodingBox.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.CodingBox.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.CodingBox.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_arduino_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'cbx_arduino_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CodingBoxArduinoWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.CodingBox.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        coding_box_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'coding_box_tone_list',\n                    },\n                ],\n            },\n        },\n        coding_box_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'coding_box_tone_list',\n                    },\n                ],\n                type: 'coding_box_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'coding_box_tone_value',\n                    },\n                ],\n            },\n        },\n        coding_box_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'coding_box_octave_list',\n                    },\n                ],\n            },\n        },\n        cbx_arduino_write_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'coding_box_tone_list',\n                    },\n                    {\n                        type: 'coding_box_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cbx_arduino_write_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'CodingBoxArduinoWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note))\n                        note = Entry.CodingBox.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.CodingBox.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var value = 0;\n\n                    if (note != 0) {\n                        value = Entry.CodingBox.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.CodingBox.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.CodingBox.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_arduino_write_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'cbx_arduino_write_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CodingBoxArduinoWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.CodingBox.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //////\n        //CodingBox Only\n        //////\n        cbx_read_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            events: {},\n            class: 'CodingBoxRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port1 = Entry.CodingBox.pins.ULTRASONIC_TRIG;\n                var port2 = Entry.CodingBox.pins.ULTRASONIC_ECHO;\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][\n                    Entry.CodingBox.sensorTypes.ULTRASONIC\n                ] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(4, 7)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_read_switch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cbx_switch_list',\n                    },\n                ],\n                type: 'cbx_read_switch',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CodingBoxRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value = ANALOG ? ANALOG[port] || 0 : 0;\n                var isPush = 0;\n\n                if (port[0] === 'A') port = port.substring(1);\n                if (value > 600) {\n                    isPush = 0;\n                } else {\n                    isPush = 1;\n                }\n\n                return isPush;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_read_potentiometer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //      statements: [],\n            //      params: [\n            //        {}\n            //      ],\n            //      events: {},\n            def: {\n                params: [],\n                type: 'cbx_read_potentiometer',\n            },\n            class: 'CodingBoxRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port = Entry.CodingBox.pins.POTENTIOMETER;\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_read_mic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'cbx_read_mic',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'CodingBoxRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port = Entry.CodingBox.pins.MIC;\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_read_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            paramsKeyMap: {},\n            class: 'CodingBoxRead',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                const port = 3;\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][\n                    Entry.CodingBox.sensorTypes.DIGITAL\n                ] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_write_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cbx_led_number_list',\n                    },\n                    {\n                        type: 'cbx_led_value_list',\n                    },\n                    null,\n                ],\n                type: 'cbx_write_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'CodingBoxWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.CodingBox.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        cbx_write_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cbx_lcd_row_list',\n                    },\n                    {\n                        type: 'cbx_lcd_column_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['Hello, CodingBox'],\n                    },\n                    null,\n                ],\n                type: 'cbx_write_lcd',\n            },\n            paramsKeyMap: {\n                ROW: 0,\n                COLUMN: 1,\n                TEXT: 2,\n            },\n            class: 'CodingBoxWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var row = script.getNumberValue('ROW');\n                var column = script.getNumberValue('COLUMN');\n                var text = script.getValue('TEXT');\n                let time = new Date().getTime();\n\n                //      아래코드에서 보조 변수들(script.isStart, script.timeFlag등)이 들어간 이유는 fps(초당프레임)를 위해서입니다.\n                //      해당 코드가 없을 경우 최소 딜레이가 없기때문에 흐리게 나오는 문제가 발생합니다.\n                if (!script.isStart) {\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = 60 / fps * 50;\n\n                    sq['SET'][15] = {\n                        type: Entry.CodingBox.sensorTypes.LCD_PRINT,\n                        data: {\n                            row,\n                            column,\n                            text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        cbx_clear_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cbx_clear_lcd',\n            },\n            paramsKeyMap: {},\n            class: 'CodingBoxWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                let sq = Entry.hw.sendQueue;\n                let time = new Date().getTime();\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][14] = {\n                    type: Entry.CodingBox.sensorTypes.LCD_CLEAR,\n                    data: 255,\n                    time: time,\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        cbx_write_rgb_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cbx_rgb_led_value_list',\n                    },\n                    {\n                        type: 'cbx_rgb_led_value_list',\n                    },\n                    {\n                        type: 'cbx_rgb_led_value_list',\n                    },\n                    null,\n                ],\n                type: 'cbx_write_rgb_led',\n            },\n            paramsKeyMap: {\n                R: 0,\n                G: 1,\n                B: 2,\n            },\n            class: 'CodingBoxWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var redPort = Entry.CodingBox.pins.RGB_R;\n                var greenPort = Entry.CodingBox.pins.RGB_G;\n                var bluePort = Entry.CodingBox.pins.RGB_B;\n                var redPWM = script.getNumberValue('R');\n                var greenPWM = script.getNumberValue('G');\n                var bluePWM = script.getNumberValue('B');\n\n                redPWM = Math.round(redPWM);\n                redPWM = Math.max(redPWM, 0);\n                redPWM = Math.min(redPWM, 1);\n                greenPWM = Math.round(greenPWM);\n                greenPWM = Math.max(greenPWM, 0);\n                greenPWM = Math.min(greenPWM, 1);\n                bluePWM = Math.round(bluePWM);\n                bluePWM = Math.max(bluePWM, 0);\n                bluePWM = Math.min(bluePWM, 1);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][redPort] = {\n                    type: Entry.CodingBox.sensorTypes.DIGITAL,\n                    data: redPWM,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][greenPort] = {\n                    type: Entry.CodingBox.sensorTypes.DIGITAL,\n                    data: greenPWM,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][bluePort] = {\n                    type: Entry.CodingBox.sensorTypes.DIGITAL,\n                    data: bluePWM,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_led_number_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['LED1', '10'], ['LED2', '11']],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [['LED1', '10'], ['LED2', '11']],\n                                value: '3',\n                                fontSize: 11,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cbx_led_number_list',\n                    },\n                ],\n            },\n        },\n        cbx_rgb_led_value_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CBX_LED_ON, '1'],\n                        [Lang.Blocks.CBX_LED_OFF, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.CBX_LED_ON, '1'],\n                                    [Lang.Blocks.CBX_LED_OFF, '0'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cbx_led_value_list',\n                    },\n                ],\n            },\n        },\n        cbx_led_value_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CBX_LED_ON, '255'],\n                        [Lang.Blocks.CBX_LED_OFF, '0'],\n                        ['50', '50'],\n                        ['100', '100'],\n                        ['150', '150'],\n                        ['200', '200'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['On', '255'],\n                                    ['Off', '0'],\n                                    ['0', '0'],\n                                    ['50', '50'],\n                                    ['100', '100'],\n                                    ['150', '150'],\n                                    ['200', '200'],\n                                    ['255', '255'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'cbx_led_value_list',\n                    },\n                ],\n            },\n        },\n        cbx_dcm_speed_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CBX_DCM_SPEED_MAX, '255'],\n                        [Lang.Blocks.CBX_DCM_SPEED_STOP, '0'],\n                        ['50', '50'],\n                        ['100', '100'],\n                        ['150', '150'],\n                        ['200', '200'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('SPEED');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Max', '255'],\n                                    ['Off', '0'],\n                                    ['50', '50'],\n                                    ['100', '100'],\n                                    ['150', '150'],\n                                    ['200', '200'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'cbx_dcm_speed_list',\n                    },\n                ],\n            },\n        },\n        cbx_servo_angle_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['30', '30'],\n                        ['60', '60'],\n                        ['90', '90'],\n                        ['120', '120'],\n                        ['150', '150'],\n                        ['180', '180'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ANGLE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('ANGLE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.CBX_SERVO_MAX, '255'],\n                                    [Lang.Blocks.CBX_SERVO_MIN, '0'],\n                                    ['50', '50'],\n                                    ['100', '100'],\n                                    ['150', '150'],\n                                    ['200', '200'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'cbx_dcm_speed_list',\n                    },\n                ],\n            },\n        },\n        cbx_lcd_column_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                        ['9', '8'],\n                        ['10', '9'],\n                        ['11', '10'],\n                        ['12', '11'],\n                        ['13', '12'],\n                        ['14', '13'],\n                        ['15', '14'],\n                        ['16', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLUMN: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('COLUMN');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '0'],\n                                    ['2', '1'],\n                                    ['3', '2'],\n                                    ['4', '3'],\n                                    ['5', '4'],\n                                    ['6', '5'],\n                                    ['7', '6'],\n                                    ['8', '7'],\n                                    ['9', '8'],\n                                    ['10', '9'],\n                                    ['11', '10'],\n                                    ['12', '11'],\n                                    ['13', '12'],\n                                    ['14', '13'],\n                                    ['15', '14'],\n                                    ['16', '15'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'cbx_dcm_speed_list',\n                    },\n                ],\n            },\n        },\n        cbx_lcd_row_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [['1', '0'], ['2', '1']],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'cbx_dcm_speed_list',\n                    },\n                ],\n            },\n        },\n        cbx_switch_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['switch1', Entry.CodingBox.pins.SWITCH_1],\n                        ['switch2', Entry.CodingBox.pins.SWITCH_2],\n                    ],\n                    value: Entry.CodingBox.pins.SWITCH_1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['switch1', Entry.CodingBox.pins.SWITCH_1],\n                                    ['switch2', Entry.CodingBox.pins.SWITCH_2],\n                                ],\n                                value: Entry.CodingBox.pins.SWITCH_1,\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'cbx_dcm_speed_list',\n                    },\n                ],\n            },\n        },\n        cbx_dcm_direction_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CBX_DCM_FORWARD, '1'],\n                        [Lang.Blocks.CBX_DCM_BACKWARD, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('DIRECTION');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [['forward', '1'], ['reverse', '0']],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter:\n                                    Entry.block.converters\n                                        .returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'cbx_dcm_value_list',\n                    },\n                ],\n            },\n        },\n        cbx_write_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cbx_servo_angle_list',\n                        params: [180],\n                    },\n                    null,\n                ],\n                type: 'cbx_write_servo',\n            },\n            paramsKeyMap: {\n                ANGLE: 0,\n            },\n            class: 'CodingBoxWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = Entry.CodingBox.pins.SERVO;\n                var angle = script.getNumberValue('ANGLE', script);\n\n                angle = Math.min(180, angle);\n                angle = Math.max(0, angle);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.CodingBox.sensorTypes.SERVO_PIN,\n                    data: angle,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_write_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'coding_box_tone_list',\n                    },\n                    {\n                        type: 'coding_box_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'cbx_write_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'CodingBoxWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = Entry.CodingBox.pins.BUZZER;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note))\n                        note = Entry.CodingBox.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.CodingBox.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var value = 0;\n\n                    if (note != 0) {\n                        value = Entry.CodingBox.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.CodingBox.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.CodingBox.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cbx_write_dcm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cbx_dcm_direction_list',\n                    },\n                    {\n                        type: 'cbx_dcm_speed_list',\n                    },\n                    null,\n                ],\n                type: 'cbx_write_dcm',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                SPEED: 1,\n            },\n            class: 'CodingBoxWrite',\n            isNotFor: ['CodingBox'],\n            func: function(sprite, script) {\n                var dcmAPin = Entry.CodingBox.pins.DCM_A;\n                var dcmBPin = Entry.CodingBox.pins.DCM_B;\n                var direction = script.getNumberValue('DIRECTION');\n                var speed = script.getNumberValue('SPEED', script);\n                var dcmASpeed = 0;\n                var dcmBSpeed = 0;\n\n                speed = Math.round(speed);\n                speed = Math.max(speed, 0);\n                speed = Math.min(speed, 255);\n\n                if (direction === 1) {\n                    dcmASpeed = speed;\n                    dcmBSpeed = 0;\n                } else {\n                    dcmASpeed = 0;\n                    dcmBSpeed = speed;\n                }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][dcmAPin] = {\n                    type: Entry.CodingBox.sensorTypes.PWM,\n                    data: dcmASpeed,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][dcmBPin] = {\n                    type: Entry.CodingBox.sensorTypes.PWM,\n                    data: dcmBSpeed,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //endregion CodingBox\n    };\n};\n//endregion CodingBox\n\nmodule.exports = Entry.CodingBox;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_codingmachine.js",
    "content": "'use strict';\nEntry.Codingmachine = {\n    id: '26.1',\n    name: 'Codingmachine',\n    url: 'http://wonn.co.kr/',\n    imageName: 'codingmachine.png', //thumbnail\n    title: {\n        ko: '코딩머신',\n        en: 'Codingmachine',\n    },\n    Cmd: {\n        LED: 1,\n        TUNE: 2,\n        TUNEDUR: 3,\n        ROLL: 4,\n        PITCH: 5,\n        YAW: 6,\n        THROTTLE: 7,\n        OPTION: 8,\n        MOTOR0: 9,\n        MOTOR1: 10,\n        MOTOR2: 11,\n        MOTOR3: 12,\n        DIGITAL_OUT1: 13,\n        DIGITAL_OUT2: 14,\n        DIGITAL_OUT3: 15,\n        DIGITAL_PWM: 16,\n        SERVOPORT: 17,\n        SERVODGREE: 18,\n    },\n    Sensor: {\n        JOYSTICK_LLR: 1,\n        JOYSTICK_LTB: 2,\n        JOYSTICK_RLR: 3,\n        JOYSTICK_RTB: 4,\n        BUTTON: 5,\n        DRONECONNECT: 6,\n        ULTRASONIC: 7,\n        GYRO_X: 8,\n        GYRO_Y: 9,\n        DRONEREADY: 10,\n        /*추가*/\n        DIGITAL_IN1: 11,\n        DIGITAL_IN2: 12,\n        ANALOG_A4: 13,\n        ANALOG_A5: 14,\n        /*추가*/\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.CMD = [\n            0xf0,\n            0x00,\n            0x00,\n            0x00,\n            0x64,\n            0x64,\n            0x64,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            /* -------- 추가 ------- */\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            /* -------- 추가 ------- */\n        ];\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/coconut.png',\n        width: 256,\n        height: 256,\n        listPorts: {\n            'CMD[1]': {\n                name: Lang.Blocks.coconut_sensor_temperature,\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            accelerationX: {\n                name: Lang.Blocks.coconut_sensor_acceleration_x,\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            accelerationY: {\n                name: Lang.Blocks.coconut_sensor_acceleration_y,\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.coconut_sensor_acceleration_z,\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n        },\n        ports: {\n            leftProximityValue: {\n                name: Lang.Blocks.coconut_sensor_left_proximity,\n                type: 'input',\n                pos: {\n                    x: 122,\n                    y: 156,\n                },\n            },\n            rightProximityValue: {\n                name: Lang.Blocks.coconut_sensor_right_proximity,\n                type: 'input',\n                pos: {\n                    x: 10,\n                    y: 108,\n                },\n            },\n            leftFloorValue: {\n                name: Lang.Blocks.coconut_sensor_left_floor,\n                type: 'input',\n                pos: {\n                    x: 100,\n                    y: 234,\n                },\n            },\n            rightFloorValue: {\n                name: Lang.Blocks.coconut_sensor_right_floor,\n                type: 'input',\n                pos: {\n                    x: 13,\n                    y: 180,\n                },\n            },\n            light: {\n                name: Lang.Blocks.coconut_sensor_light,\n                type: 'input',\n                pos: {\n                    x: 56,\n                    y: 189,\n                },\n            },\n        },\n        mode: 'both',\n    },\n};\nEntry.Codingmachine.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                codingmachine_altitude: '드론을 %1 높이만큼 날리기 %2',\n                codingmachine_button: '%1번 버튼 값 읽어오기',\n                codingmachine_connect: '드론 연결 상태 읽어오기',\n                codingmachine_emergency: '드론을 즉시 멈추기 %1',\n                codingmachine_gyro: '보드 %1 기울기 값 읽어오기',\n                codingmachine_joystick: '조이스틱 %1 읽기',\n                codingmachine_led: '%1 LED %2  %3',\n                codingmachine_motor: '%1 모터를 %2 세기로 돌리기 %3',\n                codingmachine_ready: '드론 비행 준비 상태 읽어오기',\n                codingmachine_rollpitch: '드론을 %1 방향 %2 세기로 움직이기 %3',\n                codingmachine_throttle: '드론 프로펠러를 %1 만큼 세기로 돌리기 %2',\n                codingmachine_tune: '%1 음을  %2 초동안 소리내기 %3',\n                codingmachine_ultrasonic: '거리(초음파)값 읽어오기',\n                codingmachine_yaw: '드론을 %1 만큼 회전하기 %2',\n                codingmachine_digital_out: '디지털 %1번 핀 %2 %3',\n                codingmachine_digital_in: '디지털 %1 번값 읽어오기',\n                codingmachine_analog_in: '아날로그 %1 번 센서값',\n                codingmachine_digital_pwm: '디지털 출력 %1 번 세기로 출력하기 %2 %3',\n                codingmachine_servo: '디지털  %1 핀의 서보모터를 %2 각도로 정하기 %3',\n            },\n        },\n        en: {\n            template: {\n                codingmachine_altitude: '드론을 %1 높이만큼 날리기 %2',\n                codingmachine_button: '%1번 버튼 값 읽어오기',\n                codingmachine_connect: '드론 연결 상태 읽어오기',\n                codingmachine_emergency: '드론을 즉시 멈추기 %1',\n                codingmachine_gyro: '보드 %1 기울기 값 읽어오기',\n                codingmachine_joystick: '조이스틱 %1 읽기',\n                codingmachine_led: '%1 LED %2  %3',\n                codingmachine_motor: '%1 모터를 %2 세기로 돌리기 %3',\n                codingmachine_ready: '드론 비행 준비 상태 읽어오기',\n                codingmachine_rollpitch: '드론을 %1 방향 %2 세기로 움직이기 %3',\n                codingmachine_throttle: '드론 프로펠러를 %1 만큼 세기로 돌리기 %2',\n                codingmachine_tune: '%1 음을  %2 초동안 소리내기 %3',\n                codingmachine_ultrasonic: '거리(초음파)값 읽어오기',\n                codingmachine_yaw: '드론을 %1 만큼 회전하기 %2',\n                codingmachine_digital_out: '디지털 %1번 핀 %2 %3',\n                codingmachine_digital_in: '디지털 %1 번값 읽어오기',\n                codingmachine_analog_in: 'analog %1 sensor',\n                codingmachine_digital_pwm: '디지털 출력 %1 번 세기로 출력하기 %2 %3',\n                codingmachine_servo: '디지털  %1 핀의 서보모터를 %2 각도로 정하기 %3',\n            }\n        }\n    };\n};\nEntry.Codingmachine.blockMenuBlocks = [\n    //Codingmachine Blocks\n    'codingmachine_led',\n    'codingmachine_tune',\n    'codingmachine_motor',\n    'codingmachine_joystick',\n    'codingmachine_button',\n    'codingmachine_gyro',\n    'codingmachine_ultrasonic',\n    'codingmachine_connect',\n    'codingmachine_ready',\n    'codingmachine_throttle',\n    'codingmachine_altitude',\n    'codingmachine_rollpitch',\n    'codingmachine_yaw',\n    'codingmachine_emergency',\n    'codingmachine_digital_out',\n    'codingmachine_digital_in',\n    'codingmachine_analog_in',\n    'codingmachine_digital_pwm',\n    'codingmachine_servo',\n    //Added 2018-09-24\n];\nEntry.Codingmachine.getBlocks = function() {\n    return {\n        //region JDKit\n        /* ----------- 추가 --------- */\n        codingmachine_analog_in: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['A4', 1], ['A5', 2]],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'codingmachine_analog_in',\n            },\n            paramsKeyMap: {\n                ANALOG_SENSOR: 0,\n            },\n            class: 'codingmachine_arduino',\n            isNotFor: ['Codingmachine'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var analog_sel = script.getField('ANALOG_SENSOR');\n                if (analog_sel == 1) return sensorData[Entry.Codingmachine.Sensor.ANALOG_A4];\n                else if (analog_sel == 2) return sensorData[Entry.Codingmachine.Sensor.ANALOG_A5];\n                else return sensorData[Entry.Codingmachine.Sensor.ANALOG_A4];\n            },\n            syntax: { js: [], py: [] },\n        },\n        /* ----------- 추가 --------- */\n        codingmachine_joystick: {\n            template: Lang.template.jdkit_joystick,\n            parent: 'jdkit_joystick',\n            def: {\n                params: [null],\n                type: 'codingmachine_joystick',\n            },\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        /* ----------- 추가 --------- */\n        codingmachine_digital_in: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        //3,4,5,6,7,11,12,13\n                        ['D3', 0] /*D3,D7*/,\n                        ['D4', 1] /*D4*/,\n                        ['D5', 2] /*D5*/,\n                        ['D6', 3] /*D6*/,\n                        ['D7', 4],\n                        ['D11', 5],\n                        ['D12', 6],\n                        ['D13', 7],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'codingmachine_digital_in',\n            },\n            paramsKeyMap: {\n                DIGITAL_PIN: 0,\n            },\n            class: 'codingmachine_arduino',\n            isNotFor: ['Codingmachine'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var digital_pin = script.getField('DIGITAL_PIN');\n                if (digital_pin <= 3) {\n                    return sensorData[Entry.Codingmachine.Sensor.DIGITAL_IN1] &\n                        (0x01 << digital_pin)\n                        ? 0\n                        : 1;\n                } else if (digital_pin == 4) {\n                    return sensorData[Entry.JDKit.Codingmachine.DIGITAL_IN2] & (0x01 << 0) ? 0 : 1;\n                } else {\n                    return sensorData[Entry.Codingmachine.Sensor.DIGITAL_IN2] &\n                        (0x01 << (digital_pin - 4))\n                        ? 0\n                        : 1;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        /* ----------- 추가 --------- */\n        codingmachine_button: {\n            template: Lang.template.jdkit_button,\n            parent: 'jdkit_button',\n            def: {\n                params: [null],\n                type: 'codingmachine_button',\n            },\n            isNotFor: ['Codingmachine'],\n\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_gyro: {\n            template: Lang.template.jdkit_gyro,\n            parent: 'jdkit_gyro',\n            def: {\n                params: [null],\n                type: 'codingmachine_gyro',\n            },\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_ultrasonic: {\n            template: Lang.template.jdkit_ultrasonic,\n            parent: 'jdkit_ultrasonic',\n            def: {\n                params: [null],\n                type: 'codingmachine_ultrasonic',\n            },\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_connect: {\n            template: Lang.template.jdkit_connect,\n            parent: 'jdkit_connect',\n            def: {\n                params: [null],\n                type: 'codingmachine_connect',\n            },\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_ready: {\n            template: Lang.template.jdkit_ready,\n            parent: 'jdkit_ready',\n            def: {\n                params: [null],\n                type: 'codingmachine_ready',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        /* -------- 추가 ------- */\n        codingmachine_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['D3', 3],\n                        ['D4', 4],\n                        ['D5', 5],\n                        ['D6', 6],\n                        ['D7', 7],\n                        ['D11', 11],\n                        ['D12', 12],\n                        ['D13', 13],\n                    ],\n                    value: 3,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '180',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'codingmachine_servo',\n            },\n            paramsKeyMap: {\n                DIGITAL_PIN: 0,\n                ACTION: 1,\n            },\n            class: 'codingmachine_arduino',\n            isNotFor: ['Codingmachine'],\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0,\n                        0,\n                        0,\n                        0,\n                        100,\n                        100,\n                        100,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        /* -------- 추가 ------- */\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        /* -------- 추가 ------- */\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var digital_pin = script.getField('DIGITAL_PIN', script);\n                var act_val = script.getNumberValue('ACTION', script);\n                cmd[Entry.Codingmachine.Cmd.SERVOPORT] |= digital_pin;\n                cmd[Entry.Codingmachine.Cmd.SERVODGREE] = act_val;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        /* -------- 추가 ------- */\n        /* -------- 추가 ------- */\n        codingmachine_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['D3', 1], ['D5', 2], ['D6', 3], ['D11', 4]],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '100',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'codingmachine_digital_pwm',\n            },\n            paramsKeyMap: {\n                DIGITAL_PIN: 0,\n                ACTION_VALUE: 1,\n            },\n            class: 'codingmachine_arduino',\n            isNotFor: ['Codingmachine'],\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0,\n                        0,\n                        0,\n                        0,\n                        100,\n                        100,\n                        100,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        /* -------- 추가 ------- */\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        /* -------- 추가 ------- */\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var digital_pin = script.getField('DIGITAL_PIN', script);\n                var act_value = script.getNumberValue('ACTION_VALUE', script);\n                cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT3] = (digital_pin << 4) & 0xf0;\n                cmd[Entry.Codingmachine.Cmd.DIGITAL_PWM] = act_value;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        /* -------- 추가 ------- */\n        /* -------- 추가 ------- */\n        codingmachine_digital_out: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        //3,4,5,6,7,11,12,13\n                        ['D3', 0] /*D3,D7*/,\n                        ['D4', 1] /*D4*/,\n                        ['D5', 2] /*D5*/,\n                        ['D6', 3] /*D6*/,\n                        ['D7', 4],\n                        ['D11', 5],\n                        ['D12', 6],\n                        ['D13', 7],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_led_turnon, 3],\n                        [Lang.Blocks.jdkit_led_turnoff, 4],\n                    ],\n                    value: 3,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'codingmachine_digital_out',\n            },\n            paramsKeyMap: {\n                DIGITAL_PIN: 0,\n                ACTION: 1,\n            },\n            class: 'codingmachine_arduino',\n            isNotFor: ['Codingmachine'],\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0,\n                        0,\n                        0,\n                        0,\n                        100,\n                        100,\n                        100,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        0,\n                        /* -------- 추가 ------- */\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        /* -------- 추가 ------- */\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var digital_pin = script.getField('DIGITAL_PIN', script);\n                var act = script.getField('ACTION', script);\n                if (act == 3) {\n                    if (digital_pin <= 2) {//D3, D4, D5\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT1] |= (0x01 << (digital_pin * 2 + 1));\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT1] |= (0x01 << digital_pin * 2);\n                    } else if (digital_pin <= 5) {//D6, D7, D11\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT2] |= (0x01 << ((digital_pin - 3) * 2 + 1));\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT2] |= (0x01 << (digital_pin - 3) * 2);\n                    } else {   //D12, D13\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT3] |= (0x01 << ((digital_pin - 6) * 2 + 1));\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT3] |= (0x01 << (digital_pin - 6) * 2);\n                    }\n                } else {\n                    if (digital_pin <= 2) {\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT1] |= (0x01 << (digital_pin * 2 + 1));\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT1] &= ~(0x01 << digital_pin * 2);\n                    } else if (digital_pin <= 5) {\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT2] |= (0x01 << ((digital_pin - 3) * 2 + 1));\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT2] &= ~(0x01 << (digital_pin - 3) * 2);\n                    } else {\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT3] |= (0x01 << ((digital_pin - 6) * 2 + 1));\n                        cmd[Entry.Codingmachine.Cmd.DIGITAL_OUT3] &= ~(0x01 << (digital_pin - 6) * 2);\n                    }\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        /* -------- 추가 ------- */\n        codingmachine_led: {\n            template: Lang.template.jdkit_led,\n            parent: 'jdkit_led',\n            def: {\n                params: [null],\n                type: 'codingmachine_led',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_tune: {\n            template: Lang.template.jdkit_tune,\n            parent: 'jdkit_tune',\n            def: {\n                params: [null],\n                type: 'codingmachine_tune',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_motor: {\n            template: Lang.template.jdkit_motor,\n            parent: 'jdkit_motor',\n            def: {\n                params: [null],\n                type: 'codingmachine_motor',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_throttle: {\n            template: Lang.template.jdkit_throttle,\n            parent: 'jdkit_throttle',\n            def: {\n                params: [null],\n                type: 'codingmachine_throttle',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_altitude: {\n            template: Lang.template.jdkit_altitude,\n            parent: 'jdkit_altitude',\n            def: {\n                params: [null],\n                type: 'codingmachine_altitude',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_rollpitch: {\n            template: Lang.template.jdkit_rollpitch,\n            parent: 'jdkit_rollpitch',\n            def: {\n                params: [null],\n                type: 'codingmachine_rollpitch',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_yaw: {\n            template: Lang.template.jdkit_yaw,\n            parent: 'jdkit_yaw',\n            def: {\n                params: [null],\n                type: 'codingmachine_yaw',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        codingmachine_emergency: {\n            template: Lang.template.jdkit_emergency,\n            parent: 'jdkit_emergency',\n            def: {\n                params: [null],\n                type: 'codingmachine_emergency',\n            },\n\n            isNotFor: ['Codingmachine'],\n            syntax: { js: [], py: [] },\n        },\n\n        //endregion JDKit\n    };\n};\n\nmodule.exports = Entry.Codingmachine;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_cp_moving.js",
    "content": "'use strict';\r\n\r\nEntry.cp_moving = {\r\n    id: '3E.1',\r\n    name: 'cp_moving',\r\n    url: 'https://cafe.naver.com/codingpl',\r\n    imageName: 'cp_moving.png',\r\n    title: {\r\n        en: 'CP Moving Car',\r\n        ko: 'CP 무빙카',\r\n    },\r\n    setZero() {\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[key].data = 0;\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO_PIN: 4,\r\n        TONE: 5,\r\n        PULSEIN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n        LED: 9,\r\n        TEMP: 10,\r\n        MOTOR: 11,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    direction: {\r\n        CENTER: 0,\r\n        UP: 1,\r\n        LEFT: 2,\r\n        RIGHT: 3,\r\n        DOWN: 4,\r\n        LEFT_UP: 5,\r\n        LEFT_DOWN: 6,\r\n        RIGHT_UP: 7,\r\n        RIGHT_DOWN: 8,\r\n    },\r\n    color: {\r\n        RED: [1.0, 0.0, 0.0],\r\n        GREEN: [0.0, 1.0, 0.0],\r\n        BLUE: [0.0, 0.0, 1.0],\r\n        TEAL: [0.0, 0.21, 0.26],\r\n        PINK: [1.0, 0.0, 0.56],\r\n        YELLOW: [1.0, 1.0, 0.0],\r\n        WHITE: [1.0, 1.0, 1.0],\r\n    },\r\n    move: {\r\n        FORWARD: [1.0, 1.0],\r\n        BACKWARD: [-1.0, -1.0],\r\n        LEFT: [0.5, 1.0],\r\n        RIGHT: [1.0, 0.5],\r\n    },\r\n};\r\nEntry.cp_moving.blockMenuBlocks = [\r\n    'cp_moving_get_ultrasonic',\r\n    'cp_moving_get_soil',\r\n    'cp_moving_get_analog_value',\r\n    'cp_moving_get_analog',\r\n    'cp_moving_get_digital',\r\n    'cp_moving_get_joystick',\r\n    'cp_moving_get_joystick_button',\r\n    'cp_moving_get_button',\r\n    'cp_moving_get_ir',\r\n    'cp_moving_set_vibrator',\r\n    'cp_moving_set_fan',\r\n    'cp_moving_set_led_color',\r\n    'cp_moving_set_led',\r\n    'cp_moving_stop_led',\r\n    'cp_moving_set_audio_octave',\r\n    'cp_moving_set_audio_freq',\r\n    'cp_moving_stop_audio',\r\n    'cp_moving_set_motor',\r\n    'cp_moving_stop_motor',\r\n    'cp_moving_set_move',\r\n    'cp_moving_stop_move'\r\n];\r\nEntry.cp_moving.getBlocks = function() {\r\n    return {\r\n        cp_moving_set_vibrator: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.cp_moving_set_on, 'on'], [Lang.Blocks.cp_moving_set_off, 'off']],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'cp_moving_set_vibrator',\r\n            },\r\n            paramsKeyMap: {\r\n                OPERATOR: 0,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const operator = script.getField('OPERATOR');\r\n                const value = operator == 'on' ? 255 : 0;\r\n                Entry.hw.setDigitalPortValue(2, value);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[2] = {\r\n                    type: Entry.cp_moving.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_set_fan: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[0, 0], [20, 50], [40, 100], [60, 150], [80, 200], [100, 250]],\r\n                    value: 150,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'cp_moving_set_fan',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                let value = script.getField('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[3] = {\r\n                    type: Entry.cp_moving.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_set_motor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_motor_left, 0],\r\n                        [Lang.Blocks.cp_moving_motor_right, 1],\r\n                    ],\r\n                    value: 0,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[0, 0], [20, 10], [40, 20], [60, 30], [80, 40], [100, 50]],\r\n                    value: 30,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_motor_forward, 0],\r\n                        [Lang.Blocks.cp_moving_motor_reverse, 1],\r\n                    ],\r\n                    value: 0,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'cp_moving_set_motor',\r\n            },\r\n            paramsKeyMap: {\r\n                WHICH: 0,\r\n                SPEED: 1,\r\n                DIRECTION: 2,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const which = script.getField('WHICH', script);\r\n                const speed = script.getField('SPEED', script);\r\n                const direction = script.getField('DIRECTION', script);\r\n                let s1 = 100;\r\n                let s2 = 100;\r\n\r\n                if (which == 0) {\r\n                    s1 = -speed;\r\n                    if (direction == 1) {\r\n                        s1 *= -1;\r\n                    }\r\n                } else {\r\n                    s2 = speed;\r\n                    if (direction == 1) {\r\n                        s2 *= -1;\r\n                    }\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[0] = {\r\n                    type: Entry.cp_moving.sensorTypes.MOTOR,\r\n                    data: { s1, s2 },\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_stop_motor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_motor_left, 0],\r\n                        [Lang.Blocks.cp_moving_motor_right, 1],\r\n                    ],\r\n                    value: 0,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'cp_moving_stop_motor',\r\n            },\r\n            paramsKeyMap: {\r\n                WHICH: 0,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const which = script.getField('WHICH', script);\r\n                let s1 = 100;\r\n                let s2 = 100;\r\n                if (which == 0) {\r\n                    s1 = 0;\r\n                } else {\r\n                    s2 = 0;\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[0] = {\r\n                    type: Entry.cp_moving.sensorTypes.MOTOR,\r\n                    data: { s1, s2 },\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_set_move: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[0, 0], [20, 10], [40, 20], [60, 30], [80, 40], [100, 50]],\r\n                    value: 30,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_move_forward, Entry.cp_moving.move.FORWARD],\r\n                        [Lang.Blocks.cp_moving_move_backward, Entry.cp_moving.move.BACKWARD],\r\n                        [Lang.Blocks.cp_moving_move_left, Entry.cp_moving.move.LEFT],\r\n                        [Lang.Blocks.cp_moving_move_right, Entry.cp_moving.move.RIGHT],\r\n                    ],\r\n                    value: Entry.cp_moving.move.FORWARD,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'cp_moving_set_move',\r\n            },\r\n            paramsKeyMap: {\r\n                SPEED: 0,\r\n                DIRECTION: 1,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const direction = script.getField('DIRECTION', script);\r\n                const speed = script.getField('SPEED', script);\r\n                let s1 = -speed;\r\n                let s2 = speed;\r\n                if (direction == Entry.cp_moving.move.BACKWARD) {\r\n                    s1 = speed;\r\n                    s2 = -speed;\r\n                } else if (direction == Entry.cp_moving.move.LEFT) {\r\n                    s1 = speed;\r\n                } else if (direction == Entry.cp_moving.move.RIGHT) {\r\n                    s2 = -speed;\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[0] = {\r\n                    type: Entry.cp_moving.sensorTypes.MOTOR,\r\n                    data: { s1, s2 },\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_stop_move: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'cp_moving_stop_move',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[0] = {\r\n                    type: Entry.cp_moving.sensorTypes.MOTOR,\r\n                    data: { s1: 0, s2: 0 },\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_set_servor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'cp_moving_set_servor',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                let value = script.getNumberValue('VALUE', script);\r\n                value = Math.min(180, value);\r\n                value = Math.max(0, value);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue = {\r\n                        GET: {},\r\n                        SET: {},\r\n                    };\r\n                }\r\n                Entry.hw.sendQueue.SET[11] = {\r\n                    type: Entry.cp_moving.sensorTypes.SERVO_PIN,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_set_audio_octave: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.do_name, 1],\r\n                        [Lang.Blocks.do_sharp_name, 2],\r\n                        [Lang.Blocks.re_name, 3],\r\n                        [Lang.Blocks.re_sharp_name, 4],\r\n                        [Lang.Blocks.mi_name, 5],\r\n                        [Lang.Blocks.fa_name, 6],\r\n                        [Lang.Blocks.fa_sharp_name, 7],\r\n                        [Lang.Blocks.sol_name, 8],\r\n                        [Lang.Blocks.sol_sharp_name, 9],\r\n                        [Lang.Blocks.la_name, 10],\r\n                        [Lang.Blocks.la_sharp_name, 11],\r\n                        [Lang.Blocks.si_name, 12],\r\n                    ],\r\n                    value: 1,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7]],\r\n                    value: 4,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_buzzer_wn, 1000],\r\n                        [Lang.Blocks.cp_moving_buzzer_hn, 500],\r\n                        [Lang.Blocks.cp_moving_buzzer_qn, 250],\r\n                        [Lang.Blocks.cp_moving_buzzer_en, 125],\r\n                        [Lang.Blocks.cp_moving_buzzer_sn, 63],\r\n                        [Lang.Blocks.cp_moving_buzzer_tn, 31],\r\n                    ],\r\n                    value: 250,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'cp_moving_set_audio_octave',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n                OCTAVE: 1,\r\n                DURATION: 2,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                if (!script.isStart) {\r\n                    const note = script.getField('NOTE', script);\r\n                    const octave = script.getField('OCTAVE', script) - 1;\r\n                    const duration = script.getField('DURATION', script);\r\n                    const value = Entry.cp_moving.toneMap[note][octave];\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue = {\r\n                            GET: {},\r\n                            SET: {},\r\n                        };\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue.SET[8] = {\r\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\r\n                        data: {\r\n                            value,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue.SET[8] = {\r\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        cp_moving_set_audio_freq: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: 3000,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: 1,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'cp_moving_set_audio_freq',\r\n            },\r\n            paramsKeyMap: {\r\n                HZ: 0,\r\n                SECOND: 1,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const value = script.getNumberValue('HZ', script);\r\n                const duration = script.getNumberValue('SECOND', script) * 1000;\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue = {\r\n                        GET: {},\r\n                        SET: {},\r\n                    };\r\n                }\r\n                Entry.hw.sendQueue.SET[8] = {\r\n                    type: Entry.ArduinoExt.sensorTypes.TONE,\r\n                    data: {\r\n                        value,\r\n                        duration,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_stop_audio: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_buzzer_wn, 1000],\r\n                        [Lang.Blocks.cp_moving_buzzer_hn, 500],\r\n                        [Lang.Blocks.cp_moving_buzzer_qn, 250],\r\n                        [Lang.Blocks.cp_moving_buzzer_en, 125],\r\n                        [Lang.Blocks.cp_moving_buzzer_sn, 63],\r\n                        [Lang.Blocks.cp_moving_buzzer_tn, 31],\r\n                    ],\r\n                    value: 250,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'cp_moving_stop_audio',\r\n            },\r\n            paramsKeyMap: {\r\n                DURATION: 0,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                if (!script.isStart) {\r\n                    const duration = script.getField('DURATION', script);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue = {\r\n                            GET: {},\r\n                            SET: {},\r\n                        };\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue.SET[8] = {\r\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\r\n                        data: {\r\n                            value: 0,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue.SET[8] = {\r\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        cp_moving_get_ultrasonic: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'cp_moving_get_ultrasonic',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[9];\r\n                delete Entry.hw.sendQueue.SET[10];\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.cp_moving.sensorTypes.ULTRASONIC] = {\r\n                    port: [10, 9],\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return Entry.hw.portData.ULTRASONIC || 0;\r\n            },\r\n        },\r\n        cp_moving_get_joystick: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_joystick_up, Entry.cp_moving.direction.UP],\r\n                        [Lang.Blocks.cp_moving_joystick_down, Entry.cp_moving.direction.DOWN],\r\n                        [Lang.Blocks.cp_moving_joystick_left, Entry.cp_moving.direction.LEFT],\r\n                        [Lang.Blocks.cp_moving_joystick_right, Entry.cp_moving.direction.RIGHT],\r\n                        [Lang.Blocks.cp_moving_joystick_left_up, Entry.cp_moving.direction.LEFT_UP],\r\n                        [Lang.Blocks.cp_moving_joystick_left_down, Entry.cp_moving.direction.LEFT_DOWN],\r\n                        [Lang.Blocks.cp_moving_joystick_right_up, Entry.cp_moving.direction.RIGHT_UP],\r\n                        [Lang.Blocks.cp_moving_joystick_right_down, Entry.cp_moving.direction.RIGHT_DOWN],\r\n                        [Lang.Blocks.cp_moving_joystick_center, Entry.cp_moving.direction.CENTER],\r\n                    ],\r\n                    value: Entry.cp_moving.direction.CENTER,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'cp_moving_get_joystick',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION: 0,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const direction = script.getField('DIRECTION', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                const getValue = function(w) {\r\n                    return ANALOG[w] == 0 ? 0 : ANALOG[w] == 1023 ? 2 : 1;\r\n                };\r\n\r\n                if (\r\n                    direction == Entry.cp_moving.direction.CENTER &&\r\n                    getValue(0) == 1 &&\r\n                    getValue(1) == 1\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.cp_moving.direction.DOWN &&\r\n                    getValue(0) == 1 &&\r\n                    getValue(1) == 2\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.cp_moving.direction.LEFT &&\r\n                    getValue(0) == 0 &&\r\n                    getValue(1) == 1\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.cp_moving.direction.LEFT_DOWN &&\r\n                    getValue(0) == 0 &&\r\n                    getValue(1) == 2\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.cp_moving.direction.LEFT_UP &&\r\n                    getValue(0) == 0 &&\r\n                    getValue(1) == 0\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.cp_moving.direction.RIGHT &&\r\n                    getValue(0) == 2 &&\r\n                    getValue(1) == 1\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.cp_moving.direction.RIGHT_DOWN &&\r\n                    getValue(0) == 2 &&\r\n                    getValue(1) == 2\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.cp_moving.direction.RIGHT_UP &&\r\n                    getValue(0) == 2 &&\r\n                    getValue(1) == 0\r\n                ) {\r\n                    return 1;\r\n                } else if (\r\n                    direction == Entry.cp_moving.direction.UP &&\r\n                    getValue(0) == 1 &&\r\n                    getValue(1) == 0\r\n                ) {\r\n                    return 1;\r\n                }\r\n\r\n                return 0;\r\n            },\r\n        },\r\n        cp_moving_get_joystick_button: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'cp_moving_get_joystick_button',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                return ANALOG ? ANALOG[1] && ANALOG[2] != 0 : 0;\r\n            },\r\n        },\r\n        cp_moving_get_button: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_button_blue, 6],\r\n                        [Lang.Blocks.cp_moving_button_red, 7],\r\n                    ],\r\n                    value: 6,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'cp_moving_get_button',\r\n            },\r\n            paramsKeyMap: {\r\n                WHICH: 0,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const which = script.getField('WHICH', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                return ANALOG ? ANALOG[which] != 0 : 0;\r\n            },\r\n        },\r\n        cp_moving_set_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: 100,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: 100,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: 100,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'cp_moving_set_led',\r\n            },\r\n            paramsKeyMap: {\r\n                R: 0,\r\n                G: 1,\r\n                B: 2,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                if (!script.isStart) {\r\n                    let r = script.getNumberValue('R', script);\r\n                    let g = script.getNumberValue('G', script);\r\n                    let b = script.getNumberValue('B', script);\r\n\r\n                    r = Math.max(Math.min(r, 255), 0);\r\n                    g = Math.max(Math.min(g, 255), 0);\r\n                    b = Math.max(Math.min(b, 255), 0);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue = {\r\n                            GET: {},\r\n                            SET: {},\r\n                        };\r\n                    }\r\n\r\n                    Entry.hw.sendQueue.SET[13] = {\r\n                        type: Entry.cp_moving.sensorTypes.LED,\r\n                        data: {\r\n                            r,\r\n                            g,\r\n                            b,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, 50);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        cp_moving_set_led_color: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.cp_moving_color_red, 'RED'],\r\n                        [Lang.Blocks.cp_moving_color_green, 'GREEN'],\r\n                        [Lang.Blocks.cp_moving_color_blue, 'BLUE'],\r\n                        [Lang.Blocks.cp_moving_color_teal, 'TEAL'],\r\n                        [Lang.Blocks.cp_moving_color_pink, 'PINK'],\r\n                        [Lang.Blocks.cp_moving_color_yellow, 'YELLOW'],\r\n                        [Lang.Blocks.cp_moving_color_white, 'WHITE'],\r\n                    ],\r\n                    value: 'RED',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: 100,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'cp_moving_set_led_color',\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0,\r\n                BRIGHTNESS: 1,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                if (!script.isStart) {\r\n                    const colorType = script.getField('COLOR', script);\r\n                    const color = Entry.cp_moving.color[colorType];\r\n                    let brightness = script.getNumberValue('BRIGHTNESS', script);\r\n\r\n                    brightness = Math.max(Math.min(brightness, 255), 0);\r\n\r\n                    let r = parseInt(color[0] * brightness);\r\n                    let g = parseInt(color[1] * brightness);\r\n                    let b = parseInt(color[2] * brightness);\r\n                    r = Math.max(Math.min(r, 255), 0);\r\n                    g = Math.max(Math.min(g, 255), 0);\r\n                    b = Math.max(Math.min(b, 255), 0);\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue = {\r\n                            GET: {},\r\n                            SET: {},\r\n                        };\r\n                    }\r\n\r\n                    Entry.hw.sendQueue.SET[13] = {\r\n                        type: Entry.cp_moving.sensorTypes.LED,\r\n                        data: {\r\n                            r,\r\n                            g,\r\n                            b,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, 50);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        cp_moving_stop_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'cp_moving_stop_led',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue = {\r\n                        GET: {},\r\n                        SET: {},\r\n                    };\r\n                }\r\n\r\n                Entry.hw.sendQueue.SET[13] = {\r\n                    type: Entry.cp_moving.sensorTypes.LED,\r\n                    data: {\r\n                        r: 0,\r\n                        g: 0,\r\n                        b: 0,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_get_soil: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'cp_moving_get_soil',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                return ANALOG ? ANALOG[3] || 0 : 0;\r\n            },\r\n        },\r\n        cp_moving_get_analog: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'cp_moving_get_analog',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                return ANALOG ? ANALOG[5] || 0 : 0;\r\n            },\r\n        },\r\n        cp_moving_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[1, 11], [2, 12]],\r\n                    value: 11,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'cp_moving_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const port = script.getField('PORT', script);\r\n                const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.cp_moving.sensorTypes.DIGITAL] = {\r\n                    port,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n            },\r\n        },\r\n        cp_moving_set_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[11, 11], [12, 12]],\r\n                    value: 11,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.cp_moving_set_on, 'on'], [Lang.Blocks.cp_moving_set_off, 'off']],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'cp_moving_set_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const port = script.getField('PORT', script);\r\n                const operator = script.getField('OPERATOR');\r\n                const value = operator == 'on' ? 255 : 0;\r\n                Entry.hw.setDigitalPortValue(port, value);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.cp_moving.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        cp_moving_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'cp_moving_get_analog_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                return ANALOG ? ANALOG[4] || 0 : 0;\r\n            },\r\n        },\r\n        cp_moving_get_ir: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.cp_moving_ir_left, 11], [Lang.Blocks.cp_moving_ir_right, 12]],\r\n                    value: 11,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'cp_moving_get_ir',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n            },\r\n            class: 'cp_moving',\r\n            isNotFor: ['cp_moving'],\r\n            func(sprite, script) {\r\n                const port = script.getField('PORT', script);\r\n                const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.cp_moving.sensorTypes.DIGITAL] = {\r\n                    port,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n            },\r\n        }\r\n    };\r\n};\r\nEntry.cp_moving.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            Blocks: {\r\n                cp_moving_set_on: '켜기',\r\n                cp_moving_set_off: '끄기',\r\n                cp_moving_color_red: '빨간',\r\n                cp_moving_color_green: '초록',\r\n                cp_moving_color_blue: '파란',\r\n                cp_moving_color_teal: '청록',\r\n                cp_moving_color_pink: '분홍',\r\n                cp_moving_color_yellow: '노란',\r\n                cp_moving_color_white: '하얀',\r\n                cp_moving_motor_left: '왼쪽',\r\n                cp_moving_motor_right: '오른쪽',\r\n                cp_moving_motor_forward: '정방향',\r\n                cp_moving_motor_reverse: '역방향',\r\n                cp_moving_move_forward: '전진',\r\n                cp_moving_move_backward: '후진',\r\n                cp_moving_move_left: '좌회전',\r\n                cp_moving_move_right: '우회전',\r\n                cp_moving_buzzer_hn: '2분음표',\r\n                cp_moving_buzzer_qn: '4분음표',\r\n                cp_moving_buzzer_en: '8분음표',\r\n                cp_moving_buzzer_sn: '16분음표',\r\n                cp_moving_buzzer_tn: '32분음표',\r\n                cp_moving_buzzer_wn: '온음표',\r\n                cp_moving_joystick_center: '가운데',\r\n                cp_moving_joystick_down: '아래',\r\n                cp_moving_joystick_left: '왼쪽',\r\n                cp_moving_joystick_left_down: '왼쪽 아래',\r\n                cp_moving_joystick_left_up: '왼쪽 위',\r\n                cp_moving_joystick_right: '오른쪽',\r\n                cp_moving_joystick_right_down: '오른쪽 아래',\r\n                cp_moving_joystick_right_up: '오른쪽 위',\r\n                cp_moving_joystick_up: '위',\r\n                cp_moving_button_red: '빨강',\r\n                cp_moving_button_blue: '파랑',\r\n                cp_moving_ir_left: '왼쪽',\r\n                cp_moving_ir_right: '오른쪽',\r\n            },\r\n            template: {\r\n                cp_moving_set_vibrator: '진동 알림 %1 %2',\r\n                cp_moving_set_fan: '팬을 속도 %1(으)로 회전 시키기 %2',\r\n                cp_moving_set_servor: '서보모터의 각도를 %1도로 정하기 %2',\r\n                cp_moving_set_motor: 'DC모터 %1을 %2의 속도로 %3으로 회전하기 %4',\r\n                cp_moving_stop_motor: 'DC모터 %1을 정지하기 %2',\r\n                cp_moving_set_move: '로봇을 %1의 속도로 %2 하기 %3',\r\n                cp_moving_stop_move: '로봇 정지하기 %1',\r\n                cp_moving_set_audio_octave: '계명 %1음을 %2옥타브 %3으로 연주하기 %4',\r\n                cp_moving_set_audio_freq: '펄스 %1Hz 음을 %2초 연주하기 %3',\r\n                cp_moving_stop_audio: '%1 만큼 연주쉬기 %2',\r\n                cp_moving_get_ultrasonic: '초음파센서 값 읽기',\r\n                cp_moving_get_joystick: '조이스틱 방향이 %1 인가?',\r\n                cp_moving_get_joystick_button: '조이스틱 버튼이 눌렸는가?',\r\n                cp_moving_get_button: '%1색 버튼이 눌렸는가?',\r\n                cp_moving_set_led: '컬러 LED 켜기- 빨강%1 초록%2 파랑%3 %4',\r\n                cp_moving_set_led_color: 'LED %1색을 밝기 %2으로 켜기 %3',\r\n                cp_moving_stop_led: 'LED 끄기 %1',\r\n                cp_moving_get_soil: '토양 센서 값 읽기',\r\n                cp_moving_get_analog: '아날로그 값 읽기',\r\n                cp_moving_get_digital: '디지털 %1번 포트가 참인가?',\r\n                cp_moving_set_digital: '디지털 %1 포트에 %2 출력하기 %3',\r\n                cp_moving_get_analog_value: '가변저항 값 읽기',\r\n                cp_moving_get_ir: '%1 적외선 센서 값 읽기',\r\n            },\r\n        },\r\n        en: {\r\n            Blocks: {\r\n                cp_moving_set_on: 'on',\r\n                cp_moving_set_off: 'off',\r\n                cp_moving_color_red: 'red',\r\n                cp_moving_color_green: 'green',\r\n                cp_moving_color_blue: 'blue',\r\n                cp_moving_color_teal: 'teal',\r\n                cp_moving_color_pink: 'pink',\r\n                cp_moving_color_yellow: 'yellow',\r\n                cp_moving_color_white: 'white',\r\n                cp_moving_motor_left: 'left',\r\n                cp_moving_motor_right: 'right',\r\n                cp_moving_motor_forward: 'forward',\r\n                cp_moving_motor_reverse: 'reverse',\r\n                cp_moving_move_forward: 'forward',\r\n                cp_moving_move_backward: 'backward',\r\n                cp_moving_move_left: 'left',\r\n                cp_moving_move_right: 'right',\r\n                cp_moving_buzzer_hn: 'half note',\r\n                cp_moving_buzzer_qn: 'quarter note',\r\n                cp_moving_buzzer_en: 'eighth note',\r\n                cp_moving_buzzer_sn: 'sixteenth note',\r\n                cp_moving_buzzer_tn: 'thirtysecond note',\r\n                cp_moving_buzzer_wn: 'whole note',\r\n                cp_moving_joystick_center: 'center',\r\n                cp_moving_joystick_down: 'bottom',\r\n                cp_moving_joystick_left: 'left',\r\n                cp_moving_joystick_left_down: 'left bottom',\r\n                cp_moving_joystick_left_up: 'left top',\r\n                cp_moving_joystick_right: 'right',\r\n                cp_moving_joystick_right_down: 'right bottom',\r\n                cp_moving_joystick_right_up: 'right top',\r\n                cp_moving_joystick_up: 'top',\r\n                cp_moving_button_red: 'red',\r\n                cp_moving_button_blue: 'blue',\r\n                cp_moving_ir_left: 'left',\r\n                cp_moving_ir_right: 'right',\r\n            },\r\n            template: {\r\n                cp_moving_set_vibrator: 'Set vibrator %1 %2',\r\n                cp_moving_set_fan: 'Rotating fan at %1 speed %2',\r\n                cp_moving_set_motor: 'Turn on motor %1 a %2 at speed of %3 %4',\r\n                cp_moving_stop_motor: 'Turn off motor %1 %2',\r\n                cp_moving_set_move: 'Moving robot %2 at %1 speed %3',\r\n                cp_moving_stop_move: 'Stop robot %1',\r\n                cp_moving_set_servor: 'Set servo motor angle to %1 degrees %2',\r\n                cp_moving_set_audio_octave: 'Play note %1 octave %2 beat %3 %4',\r\n                cp_moving_set_audio_freq: 'Play note %1Hz beat %3',\r\n                cp_moving_stop_audio: 'Rest audio as %1 %2',\r\n                cp_moving_get_ultrasonic: 'Get ultrasonic value',\r\n                cp_moving_get_joystick: 'Get joystick value',\r\n                cp_moving_get_joystick_button: 'Get joystick button pressed',\r\n                cp_moving_get_button: 'Get switch %1 preesed',\r\n                cp_moving_set_led: 'Turn on LED in red%1 green%2 blue%3 %4',\r\n                cp_moving_set_led_color: 'Turn on LED in %1 with %2 brightness %3',\r\n                cp_moving_stop_led: 'Turn off LED %1',\r\n                cp_moving_get_soil: 'Get soil sensor value',\r\n                cp_moving_get_analog: 'Read analog value',\r\n                cp_moving_get_digital: 'Read digital port %1',\r\n                cp_moving_set_digital: 'Write digital port %1 to value %2 %3',\r\n                cp_moving_get_analog_value: 'Read variable resistance',\r\n                cp_moving_get_ir: 'Read %1 infrared ray sensor value',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.cp_moving;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_creamo.js",
    "content": "'use strict';\n\nEntry.Creamo = {\n    id: '20.1',\n    name: 'creamo',\n    url: 'http://www.creamo.co.kr',\n    imageName: 'creamo.png',\n    title: {\n        en: 'creamo',\n        ko: '크리모',\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n    },\n    //수정\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        DC_MOTOR_LEFT: 9,\n        DC_MOTOR_RIGHT: 10,\n    },\n    monitorTemplate: {\n        imgPath: 'hw/arduino.png',\n        width: 200,\n        height: 200,\n        listPorts: {\n            '1': {\n                name: Lang.Hw.port_en + ' LED1 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '2': {\n                name: Lang.Hw.port_en + ' LED2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '3': {\n                name: Lang.Hw.port_en + ' 4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '4': {\n                name: Lang.Hw.port_en + ' 5 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '6': {\n                name: Lang.Hw.port_en + ' 6 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '7': {\n                name: Lang.Hw.port_en + ' 7 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '8': {\n                name: Lang.Hw.port_en + ' 8 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '9': {\n                name: Lang.Hw.port_en + ' 9 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '10': {\n                name: Lang.Hw.port_en + ' 10 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '11': {\n                name: Lang.Hw.port_en + ' 11 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '12': {\n                name: Lang.Hw.port_en + ' 12 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '13': {\n                name: Lang.Hw.port_en + ' 13 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: Lang.Hw.port_en + ' A0 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: Lang.Hw.port_en + ' A1 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a2: {\n                name: Lang.Hw.port_en + ' A2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a3: {\n                name: Lang.Hw.port_en + ' A3 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a4: {\n                name: Lang.Hw.port_en + ' A4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a5: {\n                name: Lang.Hw.port_en + ' A5 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n};\nEntry.Creamo.blockMenuBlocks = [\n    //creamo\n    'creamo_toggle_led',\n    'creamo_get_number_sensor_value',\n    'creamo_toggle_pwm',\n    'creamo_toggle_motor',\n];\nEntry.Creamo.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                creamo_get_number_sensor_value: '가변저항_블록 %1 번 센서값  ',\n                creamo_get_port_number: '%1',\n                creamo_get_pwm_port_number: '%1  ',\n                creamo_motor_port_number: '%1',\n                creamo_toggle_led: 'LED_블록 %1 번 핀 %2 %3',\n                creamo_toggle_motor: 'Motor_블록 %1 번 핀 %2 %3',\n                creamo_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n            },\n            Menus: {\n                creamo: '크리모',\n            },\n            Device: {\n                creamo: '크리모',\n            },\n        },\n        en: {\n            template: {\n                creamo_get_number_sensor_value: 'PWM_Block %1 Sensor value',\n                creamo_get_port_number: '%1',\n                creamo_get_pwm_port_number: '%1',\n                creamo_motor_port_number: '%1',\n                creamo_toggle_led: 'LED_Block %1 Pin %2 %3',\n                creamo_toggle_motor: 'Motor_Block %1 pin %2 %3',\n                creamo_toggle_pwm: 'Digital %1 Pin %2 %3',\n            },\n            Menus: {\n                creamo: 'creamo',\n            },\n            Device: {\n                creamo: 'creamo',\n            },\n        },\n    };\n};\n\nEntry.Creamo.getBlocks = function() {\n    return {\n        //region creamo\n        creamo_get_number_sensor_value: {\n            parent: 'arduino_get_number_sensor_value',\n            isNotFor: ['creamo'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'creamo_get_number_sensor_value',\n            },\n            class: 'arduino_value',\n            syntax: { js: [], py: ['creamo.get_number_sensor_value(%1)'] },\n        },\n        creamo_get_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['12', '12'],\n                    ],\n                    value: '7',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['12', '12'],\n                                ],\n                                value: '7',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_port_number',\n                    },\n                ],\n            },\n        },\n        //LED\n        creamo_toggle_led: {\n            parent: 'arduino_toggle_led',\n            isNotFor: ['creamo'],\n            def: {\n                params: [\n                    {\n                        type: 'creamo_get_port_number',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'creamo_toggle_led',\n            },\n            class: 'arduino_set',\n            syntax: { js: [], py: ['creamo.toggle_led(%1)'] },\n        },\n        //모터\n        creamo_toggle_motor: {\n            parent: 'arduino_toggle_led',\n            isNotFor: ['creamo'],\n            def: {\n                params: [\n                    {\n                        type: 'creamo_motor_port_number',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'creamo_toggle_motor',\n            },\n            class: 'arduino_set',\n            syntax: { js: [], py: ['creamo.toggle_led(%1)'] },\n        },\n        creamo_motor_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['6', '6'],\n                        ['9', '9'],\n                    ],\n                    value: '6',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['6', '6'],\n                                    ['9', '9'],\n                                ],\n                                value: '6',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_port_number',\n                    },\n                ],\n            },\n        },\n        creamo_toggle_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'creamo_get_pwm_port_number',\n                    },\n                    '255',\n                    null,\n                ],\n                type: 'creamo_toggle_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'arduino_set',\n            isNotFor: ['creamo'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'creamo.set_pin_digital(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        creamo_get_pwm_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['9', '9'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        keyOption: 'arduino_get_pwm_port_number',\n                    },\n                ],\n            },\n        },\n        //endregion creamo\n    };\n};\n\nmodule.exports = Entry.Creamo;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_cremaker_3Dpen.js",
    "content": "'use strict';\n\nEntry.cremaker_3Dpen = {\n    id       : '51.1',\n    name     : 'cremaker_3Dpen',\n    url      : 'http://www.cremaker.com/',\n    imageName: 'Testino.png',\n    title    : {\n        en: 'cremaker_3Dpen',\n        ko: '크리메이커 3D 펜',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        MOTOR_ENABLE: 5,\n        MOTOR_DIR: 6,\n        SCREEN: 8,\n        HEATER: 9,\n        MOTOR_SPEED: 10,\n        LED: 13,\n    },\n    temptype: {        \n        VALUE_TEMPTABLE: 0,\n        CELSIUS_TEMPTABLE: 1,\n    },\n    temperTable: {\n        '1': [1023, 0],\n        '2': [1008,10],\n        '3': [994,20],\n        '4': [990,30],\n        '5': [985,40],\n        '6': [983,50],\n        '7': [981,60],\n        '8': [978,70],\n        '9': [975,80],\n        '10': [965,90],\n        '11': [959,100],\n        '12': [952,110],\n        '13': [948,120],\n        '14': [941,130],\n        '15': [932,140],\n        '16': [920,150],\n        '17': [908,160],\n        '18': [890,170],\n        '19': [875,180],\n        '20': [845,190],\n        '21': [820,200],\n        '22': [790,210],\n        '23': [765,220],\n    },\n    BlockState: {},\n};\n\nEntry.cremaker_3Dpen.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n                cremaker3Dpen_btn_A: 'A',\n                cremaker3Dpen_btn_B: 'B',\n                cremaker3Dpen_btn_C: 'C',\n                cremaker3Dpen_btn_D: 'D',\n                cremaker3Dpen_temp_sensor:  '온도센서',\n                cremaker3Dpen_motor_ccw_dir: '반시계',\n                cremaker3Dpen_motor_cw_dir: '시계',\n                cremaker3Dpen_motor_enable_on: '활성화',\n                cremaker3Dpen_motor_enable_off: '비활성화',\n                cremaker3Dpen_motor_heater_on: '시작',\n                cremaker3Dpen_motor_heater_off: '종료',\n                cremaker3Dpen_screen_text_ok: 'ok',\n                cremaker3Dpen_screen_text_heating: 'heating',\n                cremaker3Dpen_screen_text_cooling: 'cooling',\n                cremaker3Dpen_led_on: '켜기',\n                cremaker3Dpen_led_off: '끄기',\n            },\n            template: {\n                cremaker3Dpen_get_analog_value: '%1 신호 값',\n                cremaker3Dpen_get_button_state: '%1 버튼이 눌렸는가?',\n                cremaker3Dpen_set_motor_enable: '모터 %1',\n                cremaker3Dpen_set_motor_direction: '모터를 %1 방향으로 설정',\n                cremaker3Dpen_set_motor_speed: '모터 속도를 %1 으로 설정',\n                cremaker3Dpen_set_heater: '노즐 예열 %1',\n                cremaker3Dpen_calculate_temperature: '%1 온도 계산',    \n                cremaker3Dpen_show_text_to_screen: '%1 를 화면에 표시',\n                cremaker3Dpen_set_led_toggle: 'LED를 %1',\n            },\n        },\n        en: {\n            Blocks: {\n                cremaker3Dpen_btn_A: 'A',\n                cremaker3Dpen_btn_B: 'B',\n                cremaker3Dpen_btn_C: 'C',\n                cremaker3Dpen_btn_D: 'D',\n                cremaker3Dpen_temp_sensor:  'Temp Sensor',\n                cremaker3Dpen_motor_ccw_dir: 'countclockwise',\n                cremaker3Dpen_motor_cw_dir: 'clockwise',\n                cremaker3Dpen_motor_enable_on: 'on',\n                cremaker3Dpen_motor_enable_off: 'off',                \n                cremaker3Dpen_motor_heater_on: 'turn on',\n                cremaker3Dpen_motor_heater_off: 'turn off',            \n                cremaker3Dpen_screen_text_ok: 'ok',\n                cremaker3Dpen_screen_text_heating: 'heating',\n                cremaker3Dpen_screen_text_cooling: 'cooling',\n                cremaker3Dpen_led_on: 'turn on',\n                cremaker3Dpen_led_off: 'turn off',\n            },\n            template: {\n                cremaker3Dpen_get_analog_value: '1% sensor value',\n                cremaker3Dpen_get_button_state: 'is pressed %1 button?',\n                cremaker3Dpen_set_motor_enable: 'motor %1',\n                cremaker3Dpen_set_motor_direction: 'set the direction of rotation of the motor to %1',\n                cremaker3Dpen_set_motor_speed: 'set motor speed to %1',\n                cremaker3Dpen_set_heater: '%1 nozzle heater',     \n                cremaker3Dpen_calculate_temperature: 'calculate temperature of %1',    \n                cremaker3Dpen_show_text_to_screen: 'show %1 to screen',\n                cremaker3Dpen_set_led_toggle: '%1 LED',\n            },\n        },\n    };\n};\n\nEntry.cremaker_3Dpen.blockMenuBlocks = [\n    'cremaker3Dpen_get_analog_value',\n    'cremaker3Dpen_calculate_temperature',\n    'cremaker3Dpen_get_button_state',\n    'cremaker3Dpen_set_motor_enable',\n    'cremaker3Dpen_set_motor_direction',\n    'cremaker3Dpen_set_motor_speed',\n    'cremaker3Dpen_set_heater',\n    'cremaker3Dpen_set_led_toggle',\n    'cremaker3Dpen_show_text_to_screen',\n];\n\nEntry.cremaker_3Dpen.getBlocks = function() {\n    return {\n        cremaker3Dpen_analog_list: {\n            parent: 'arduino_ext_analog_list',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.cremaker3Dpen_temp_sensor, '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                        ['A6', '6'],\n                        ['A7', '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],            \n            syntax: undefined,\n        },\n        cremaker3Dpen_get_analog_value: {\n            parent: 'arduino_ext_get_analog_value',\n            template: Lang.template.cremaker3Dpen_get_analog_value,\n            def: {\n                params: [\n                     {\n                         type: 'cremaker3Dpen_analog_list',\n                     },\n                ],\n                type: 'cremaker3Dpen_get_analog_value',\n            },\n            class: 'cremaker_3Dpen_value_set',\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: undefined,\n        },\n        cremaker3Dpen_calculate_temperature: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cremaker3Dpen_calculate_temperature',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cremaker_3Dpen_value_set',\n            func(sprite, script) {\n                let value = script.getNumberValue('VALUE');\n                let ratioTemp =0;\n                let cmt = Entry.cremaker_3Dpen.temptype;\n                let cmtt = Entry.cremaker_3Dpen.temperTable;\n                let value_temp = cmt.VALUE_TEMPTABLE;\n                let celsius_temp = cmt.CELSIUS_TEMPTABLE;\n                for(var i = 1; i < 23; i++)\n                {                    \n                    if(value > cmtt[i][value_temp])\n                    {\n                        ratioTemp = (value - cmtt[i][value_temp])/(cmtt[i-1][value_temp] - cmtt[i][value_temp])\n\n                        return cmtt[i][celsius_temp] - ratioTemp*(cmtt[i][celsius_temp] - cmtt[i-1][celsius_temp]);\n                    }\n                }\n                return 0;\n            },\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: undefined,\n        },\n        cremaker3Dpen_get_button_state: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.cremaker3Dpen_btn_A,  '8'],\n                        [Lang.Blocks.cremaker3Dpen_btn_B,  '7'],\n                        [Lang.Blocks.cremaker3Dpen_btn_C,  '11'],\n                        [Lang.Blocks.cremaker3Dpen_btn_D,  '12'],\n                    ],\n                    value     : '8',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'cremaker3Dpen_get_button_state',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'cremaker_3Dpen_set',\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT', script);\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.cremaker_3Dpen.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL[port] == 0 ? 1 : 0;\n            },\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'cremaker_3Dpen.digitalRead(%1)',\n                        blockType: 'param',\n                        //replaceBlockType: 'arduino_ext_get_digital',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cremaker3Dpen_set_motor_enable: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.cremaker3Dpen_motor_enable_on, 'on'],\n                        [Lang.Blocks.cremaker3Dpen_motor_enable_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cremaker3Dpen_set_motor_enable',\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            class: 'cremaker_3Dpen_set',\n            func(sprite, script) {                \n                const operator = script.getField('OPERATOR');\n                let value = 0;\n                if(operator == 'on')\n                {\n                    value = 255;\n                }\n                else\n                {\n                    value =  0;\n                }\n                const port = Entry.cremaker_3Dpen.sensorTypes.MOTOR_ENABLE;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.cremaker_3Dpen.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'cremaker_3Dpen.set_motor_enable(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.cremaker3Dpen_motor_enable_on, 'on'],\n                                    [Lang.Blocks.cremaker3Dpen_motor_enable_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cremaker3Dpen_set_motor_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.cremaker3Dpen_motor_ccw_dir, 'on'],\n                        [Lang.Blocks.cremaker3Dpen_motor_cw_dir, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cremaker3Dpen_set_motor_direction',\n            },\n            paramsKeyMap: {\n                OPERATOR: 1,\n            },\n            class: 'cremaker_3Dpen_set',\n            func(sprite, script) {                \n                const operator = script.getField('OPERATOR');\n                let value = 0;\n                if(operator == 'on')\n                {\n                    value = 255;\n                }\n                else\n                {\n                    value =  0;\n                }\n                const port = Entry.cremaker_3Dpen.sensorTypes.MOTOR_DIR;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.cremaker_3Dpen.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'cremaker_3Dpen.set_motor_dir(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.cremaker3Dpen_motor_ccw_dir, 'on'],\n                                    [Lang.Blocks.cremaker3Dpen_motor_cw_dir, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cremaker3Dpen_set_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'cremaker3Dpen_set_motor_speed',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'cremaker_3Dpen_set',\n            func(sprite, script) {\n                const port = Entry.cremaker_3Dpen.sensorTypes.MOTOR_SPEED;\n                let value = script.getNumberValue('VALUE');\n                console.log(value);\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.cremaker_3Dpen.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                console.log(value);\n                return script.callReturn();\n            },\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'cremaker_3Dpen.set_motor_speed(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        cremaker3Dpen_set_heater: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.cremaker3Dpen_motor_heater_on, 'on'],\n                        [Lang.Blocks.cremaker3Dpen_motor_heater_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cremaker3Dpen_set_heater',\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            class: 'cremaker_3Dpen_set',\n            func(sprite, script) {                \n                const operator = script.getField('OPERATOR');\n                let value = 0;\n                if(operator == 'on')\n                {\n                    value = 255;\n                }\n                else\n                {\n                    value =  0;\n                }\n                const port = Entry.cremaker_3Dpen.sensorTypes.HEATER;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.cremaker_3Dpen.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'cremaker_3Dpen.set_heater(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.cremaker3Dpen_motor_heater_on, 'on'],\n                                    [Lang.Blocks.cremaker3Dpen_motor_heater_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },       \n        cremaker3Dpen_set_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.cremaker3Dpen_led_on, 'on'],\n                        [Lang.Blocks.cremaker3Dpen_led_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cremaker3Dpen_set_led_toggle',\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            class: 'cremaker_3Dpen_set',\n            func(sprite, script) {                \n                const operator = script.getField('OPERATOR');\n                let value = 0;\n                if(operator == 'on')\n                {\n                    value = 255;\n                }\n                else\n                {\n                    value =  0;\n                }\n                const port = Entry.cremaker_3Dpen.sensorTypes.LED;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.cremaker_3Dpen.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'cremaker_3Dpen.set_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.cremaker3Dpen_led_on, 'on'],\n                                    [Lang.Blocks.cremaker3Dpen_led_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        }, \n        cremaker3Dpen_show_text_to_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.cremaker3Dpen_screen_text_ok, '0'],\n                        [Lang.Blocks.cremaker3Dpen_screen_text_heating, '1'],\n                        [Lang.Blocks.cremaker3Dpen_screen_text_cooling, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cremaker3Dpen_show_text_to_screen',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n            },\n            class: 'cremaker_3Dpen_screen_set',\n            func(sprite, script) {                \n                const value = script.getField('TEXT');\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[0] = {\n                    type: Entry.cremaker_3Dpen.sensorTypes.SCREEN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            isNotFor: ['cremaker_3Dpen'],\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'cremaker_3Dpen.set_text_screen(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.cremaker3Dpen_screen_text_ok, '1'],\n                                    [Lang.Blocks.cremaker3Dpen_screen_text_heating, '2'],\n                                    [Lang.Blocks.cremaker3Dpen_screen_text_cooling, '3'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },        \n    };\n};\n\nmodule.exports = Entry.cremaker_3Dpen;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_cuboai.js",
    "content": "'use strict';\n\nEntry.cuboai = {\n    id: '6E.1',\n    name: 'cuboai',\n    url: 'http://www.cuborobot.com/',\n    imageName: 'cuboai.png',\n    title: {\n        ko: '큐보 AI',\n        en: 'CUBO AI',\n    },\n    cmdIdx: 0,\n    packetStack: [],\n    flushStack: function() {\n        if (this.packetStack.length === 0) return;\n        if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n        this.packetStack.forEach(packet => {\n            const currentIdx = this.cmdIdx++;\n            const uniqueKey = `${packet.cmd}_${currentIdx}`;\n            Entry.hw.sendQueue.SET[uniqueKey] = packet.payload;\n        });\n        \n        this.updateAndClear();\n        this.packetStack = [];\n    },\n    updateAndClear: function(){\n        Entry.hw.update();\n        Entry.hw.sendQueue.SET = {};\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.SET = {};\n        Entry.hw.sendQueue.SET[Entry.cuboai.constants.CMD_DC_MOTOR_OFF] = {\n            data: true                       \n        };\n        this.updateAndClear();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/cuboai.png',\n        width: 1184,\n        height: 864,\n        listPorts: {\n            'p1': {\n                name: `핀 1`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            'p2': {\n                name: `핀 2`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            'p3': {\n                name: `핀 3`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            'p4': {\n                name: `핀 4`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            'p5': {\n                name: `핀 5`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            'p6': {\n                name: `핀 6`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            'rmc': {\n                name: `리모컨`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            }\n        },\n        mode: 'both',\n    },\n    constants: {\n        CMD_GPIO_OUT: 0x80,\n        CMD_SERVO_MOTOR: 0x81,\n        CMD_DC_MOTOR_ALL_ON: 0x82,\n        CMD_DC_MOTOR_OFF: 0x83,\n        CMD_IN_KEYBOARD: 0x84,\n        CMD_DC_MOTOR_1_ON: 0x85,\n        CMD_DC_MOTOR_2_ON: 0x86,\n\n        CMD_FLOW_COND_NUM: 0xB0,\n        CMD_FLOW_COND_IF: 0xB1,\n        CMD_FLOW_COND_IF_START: 0xB2,\n        CMD_FLOW_COND_ELSE_START: 0xB3,\n        CMD_FLOW_COND_IF_END: 0xB4,\n        CMD_FLOW_LOOP_COND_START: 0xB5,\n        CMD_FLOW_LOOP_COND_END: 0xB6,\n        CMD_FLOW_LOOP_START: 0xB7,\n        CMD_FLOW_LOOP_END: 0xB8,\n        CMD_FLOW_LOOP_CNT_START: 0xB9,\n        CMD_FLOW_LOOP_CNT_END: 0xBA,\n        CMD_FLOW_LOOP_DELAY_SEC: 0xBB,\n        CMD_FLOW_WRITE_VARIABLE: 0xBC,\n        CMD_FLOW_READ_VARIABLE: 0xBD,\n        CMD_FLOW_SET_VARIABLE: 0xBE,\n        CMD_IOT_SERVO_MOTOR_ANGLE_VALUE: 0xBF,\n        CMD_FLOW_LOOP_BREAK_CONTINUE: 0xC0,\n        CMD_FLOW_JGMT_SIGN: 0xC1,\n        CMD_FLOW_JGMT_BOOL: 0xC2,\n        CMD_FLOW_JGMT_LOGIC: 0xC3,\n        CMD_IOT_READ_REMOTE: 0xC4,\n        CMD_IOT_DC_MOTOR_OFF: 0xC5,\n        CMD_IOT_DC_MOTOR_SPEED: 0xC6,\n        CMD_IOT_SERVO_MOTOR_ANGLE: 0xC7,\n        CMD_IOT_DIGIT_OUTPUT: 0xC8,\n        CMD_IOT_ANALOG_INPUT: 0xC9,\n        CMD_IOT_DIGIT_INPUT: 0xCA,\n        CMD_IOT_DC_MOTOR_1_ON: 0xCB,\n        CMD_IOT_DC_MOTOR_2_ON: 0xCC,\n        CMD_IOT_DC_ALL_MOTOR_VALUE: 0xCD,\n        CMD_IOT_DC_MOTOR_1_VALUE: 0xCE,\n        CMD_IOT_DC_MOTOR_2_VALUE: 0xCF,\n        CMD_BLOCK_SAVE_START: 0xD0,\n        CMD_BLOCK_SAVE_END: 0xD1,\n    },\n    getOffsetX(str) {\n        return this.getByteLength(str) * 1.5 - 5;\n    },\n    getByteLength(s, b, i, c) {\n        for (b = i = 0; (c = s.charCodeAt(i++)); b += c >> 11 ? 3 : c >> 7 ? 2 : 1);\n        return b;\n    },\n    BlockState: {},\n};\nEntry.cuboai.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                cuboai_get_iot_title:'AI IoT 명령어',\n                cuboai_set_digital_value: '디지털%1번 핀%2(으)로 정하기%3%4',    \n                cuboai_get_digital_value: '디지털%1번 핀 읽기%2',\n                cuboai_get_analog_value: '아날로그%1번 핀 읽기%2',\n                cuboai_set_motor1_speed: '모터1 속도 L1:%1 R1:%2(으)로 정하기%3%4',\n                cuboai_set_motor2_speed: '모터2 속도 L2:%1 R2:%2(으)로 정하기%3%4',\n                cuboai_set_motor_speed: '모터 속도 L1:%1 L2:%2 R1:%3 R2:%4(으)로 정하기%5%6',\n                cuboai_set_servo_motor: '%1번 서보모터 각도:%2 속도:%3(으)로 정하기%4%5',\n                cuboai_stop_motor: '모든 DC 모터 끄기%1%2',\n                cuboai_set_keyboard_value: '%1키보드 값 전달%2%3',\n                cuboai_get_remote_value: '리모컨 값 읽기%1',     \n\n                cuboai_get_save_title:'AI LAMP 저장',\n                cuboai_block_save_start: '%1번으로 저장 시작%2',\n                cuboai_block_save_end: '저장 끝%1',\n\n                cuboai_get_cond_title:'AI LAMP 조건',\n                cuboai_block_flow_if_start: '만약 %1하기{%2',\n                cuboai_block_flow_else_start: '아니라면 하기{%1',\n                cuboai_block_flow_else_end: '}아니라면 끝%1',\n                cuboai_block_flow_if_end: '}만약 끝%1',\n\n                cuboai_get_loop_title:'AI LAMP 반복',\n                cuboai_block_flow_loop_start: '무한 반복 하기{%1',\n                cuboai_block_flow_loop_end: '}무한 반복 끝%1',\n                cuboai_block_flow_loop_cnt_start: '%1회 반복 하기{%2',\n                cuboai_block_flow_loop_cnt_end: '}횟 수 반복 끝%1',\n                cuboai_block_flow_loop_delay_sec: '멈추기 %1 %2 %3',\n                cuboai_block_flow_loop_break_continue: '%1 %2',\n\n                cuboai_get_jgmt_title:'AI LAMP 판단',\n                cuboai_block_flow_jgmt_logic: '%1 %2 %3',\n                cuboai_block_flow_jgmt_sign: '%1 %2 %3',\n\n                cuboai_get_value_title:'AI LAMP 값',\n                cuboai_block_flow_write_variable: '%1번%2(으)로 정하기%3',\n                cuboai_block_flow_set_variable: '%1번%2(으)로%3하고 적용%4',                \n                cuboai_block_flow_read_variable: '%1읽기',\n                cuboai_block_flow_remote_value: '리모컨 값%1',\n                                \n                cuboai_get_command_title:'AI LAMP 명령어',\n                cuboai_block_iotkit_digit_output: '디지털%1번 핀%2(으)로 정하기%3',\n                cuboai_block_iotkit_digit_input: '디지털%1번 핀 읽기',\n                cuboai_block_iotkit_analog_input: '아날로그%1번 핀 읽기',\n                cuboai_block_iotkit_read_remote: '리모컨 값 읽기',\n                cuboai_block_iotkit_dc_motor_1: '모터1 속도 L1:%1 R1:%2(으)로 정하기%3',\n                cuboai_block_iotkit_dc_motor_1_: '모터1 속도 L1:%1 R1:%2(으)로 정하기%3',\n                cuboai_block_iotkit_dc_motor_2: '모터2 속도 L2:%1 R2:%2(으)로 정하기%3',\n                cuboai_block_iotkit_dc_motor_2_: '모터2 속도 L2:%1 R2:%2(으)로 정하기%3',\n                cuboai_block_iotkit_dc_motor_speed: '모터 속도 L1:%1 L2:%2 R1:%3 R2:%4(으)로 정하기%5',\n                cuboai_block_iotkit_dc_motor_off: '모든 DC 모터 끄기%1',                \n                cuboai_block_iotkit_servo_motor: '%1번 서보모터 각도:%2 속도:%3(으)로 정하기%4',\n            },\n            Helper: { \n            },\n            Device: {\n                cuboai: 'cuboai',\n            },\n            Menus: {\n                cuboai: 'cuboai',\n            },\n        },\n    };\n};\nEntry.cuboai.blockMenuBlocks = [\n    'cuboai_get_iot_title',\n    'cuboai_set_digital_value',\n    'cuboai_get_digital_value',\n    'cuboai_get_analog_value',\n    'cuboai_set_motor1_speed',\n    'cuboai_set_motor2_speed',\n    'cuboai_set_motor_speed',\n    'cuboai_set_servo_motor',\n    'cuboai_stop_motor',\n    'cuboai_set_keyboard_value',\n    'cuboai_get_remote_value',\n\n    'cuboai_get_save_title',\n    'cuboai_block_save_start',\n    'cuboai_block_save_end',\n\n    'cuboai_get_cond_title',\n    'cuboai_block_flow_if_start',\n    'cuboai_block_flow_else_start',\n    'cuboai_block_flow_else_end',\n    'cuboai_block_flow_if_end',\n\n    'cuboai_get_loop_title',\n    'cuboai_block_flow_loop_start',\n    'cuboai_block_flow_loop_end',\n    'cuboai_block_flow_loop_cnt_start',\n    'cuboai_block_flow_loop_cnt_end',\n    'cuboai_block_flow_loop_delay_sec',\n    'cuboai_block_flow_loop_break_continue',\n\n    'cuboai_get_jgmt_title',\n    'cuboai_block_flow_jgmt_logic',\n    'cuboai_block_flow_jgmt_sign',\n\n    'cuboai_get_value_title',\n    \n    'cuboai_block_flow_write_variable',\n    'cuboai_block_flow_set_variable',                \n    'cuboai_block_flow_read_variable',\n    'cuboai_block_flow_remote_value',\n\n    'cuboai_get_command_title',\n    'cuboai_block_iotkit_digit_output',\n    'cuboai_block_iotkit_digit_input',\n    'cuboai_block_iotkit_analog_input',\n    'cuboai_block_iotkit_read_remote',\n    'cuboai_block_iotkit_dc_motor_1',\n    'cuboai_block_iotkit_dc_motor_1_',\n    'cuboai_block_iotkit_dc_motor_2',\n    'cuboai_block_iotkit_dc_motor_2_',\n    'cuboai_block_iotkit_dc_motor_speed',\n    'cuboai_block_iotkit_dc_motor_off',\n    'cuboai_block_iotkit_servo_motor',\n];\nEntry.cuboai.getBlocks = function () {\n    return {\n        // AI IoT 명령어 카테고리\n        cuboai_get_iot_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.cuboai_get_iot_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.cuboai_get_iot_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'cuboai_get_iot_title',\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            events: {},\n        },\n        //디지털 핀, 값 설정\n        cuboai_set_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_digital_out_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'cuboai_highlow_list',\n                        params: [1],\n                    },\n                    null,\n                    null\n                ],\n                type: 'cuboai_set_digital_value',\n            },\n            paramsKeyMap: {\n                port: 0,\n                value: 1,\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue) {\n                    Entry.hw.sendQueue = {};\n                }\n                let port = script.getNumberValue('port');\n                let value = script.getNumberValue('value');\n                Entry.hw.sendQueue.SET[Entry.cuboai.constants.CMD_GPIO_OUT] = {\n                    port: port,\n                    value: value,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_set_digital_value(%1,%2)'] },\n        },\n        //디지털 핀 값 읽기\n        cuboai_get_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_digital_in_list',\n                        params: [1],\n                    },\n                    null\n                ],\n                type: 'cuboai_get_digital_value',\n            },\n            paramsKeyMap: {\n                port: 0,\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                const port = script.getNumberValue('port', script);\n                const sensorKey = 'p' + port;\n                const value = Entry.hw.portData[sensorKey];\n                if(!Entry.hw.portData || Entry.hw.portData[sensorKey] === undefined){\n                    return 1;\n                }\n                const rawValue = Entry.hw.portData[sensorKey];\n                return rawValue > 100 ? 1 : 0;\n            },\n            syntax: { js: [], py: ['cuboai.cuboai_get_digital_value(%1)'] },\n        },\n        //아날로그 핀 값 읽기\n        cuboai_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_digital_in_list',\n                        params: [1],\n                    },\n                    null\n                ],\n                type: 'cuboai_get_analog_value',\n            },\n            paramsKeyMap: {\n                port: 0,\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                const port = script.getNumberValue('port', script);\n                const sensorKey = 'p' + port;\n                const value = Entry.hw.portData[sensorKey];\n                if(!Entry.hw.portData || Entry.hw.portData[sensorKey] === undefined){\n                    return 255;\n                }\n                const rawValue = Entry.hw.portData[sensorKey];\n                return rawValue;\n            },\n            syntax: { js: [], py: ['cuboai.cuboai_get_analog_value(%1)'] },\n        },\n        //모터1 속도 설정\n        cuboai_set_motor1_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_motor_speed_list',\n                        params: [100],\n                    },\n                    {\n                        type: 'cuboai_motor_speed_list',\n                        params: [100],\n                    },\n                    null,\n                    null\n                ],\n                type: 'cuboai_set_motor1_speed',\n            },\n            paramsKeyMap: {\n                l1: 0,\n                r1: 1,\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {                \n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let l1 = script.getNumberValue('l1');\n                let r1 = script.getNumberValue('r1');\n                l1 = Math.max(-100, Math.min(l1, 100));\n                r1 = Math.max(-100, Math.min(r1, 100));\n                Entry.hw.sendQueue.SET[Entry.cuboai.constants.CMD_DC_MOTOR_1_ON] = {\n                    l1: l1,\n                    r1: r1,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: {\n                js: [],\n                py: ['cuboai.cuboai_set_motor1_speed(%1, %2)'],\n            },\n        },\n        //모터2 속도 설정\n        cuboai_set_motor2_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_motor_speed_list',\n                        params: [100],\n                    },\n                    {\n                        type: 'cuboai_motor_speed_list',\n                        params: [100],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cuboai_set_motor2_speed',\n            },\n            paramsKeyMap: {\n                l2: 0,\n                r2: 1,\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let l2 = script.getNumberValue('l2');\n                let r2 = script.getNumberValue('r2');\n                l2 = Math.max(-100, Math.min(l2, 100));\n                r2 = Math.max(-100, Math.min(r2, 100));\n                Entry.hw.sendQueue.SET[Entry.cuboai.constants.CMD_DC_MOTOR_2_ON] = {\n                    l2: l2,\n                    r2: r2,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: {\n                js: [],\n                py: ['cuboai.cuboai_set_motor2_speed(%1, %2)'],\n            },\n        },\n        //모터1, 2 속도 설정\n        cuboai_set_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    100,\n                    100,\n                    100,\n                    100,\n                    null,\n                    null,\n                ],\n                type: 'cuboai_set_motor_speed',\n            },\n            paramsKeyMap: {\n                l1: 0,\n                l2: 1,\n                r1: 2,\n                r2: 3,\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let l1 = script.getNumberValue('l1');\n                let r1 = script.getNumberValue('r1');\n                let l2 = script.getNumberValue('l2');\n                let r2 = script.getNumberValue('r2');\n                l1 = Math.max(-100, Math.min(l1, 100));\n                r1 = Math.max(-100, Math.min(r1, 100));\n                l2 = Math.max(-100, Math.min(l2, 100));\n                r2 = Math.max(-100, Math.min(r2, 100));\n                Entry.hw.sendQueue.SET[Entry.cuboai.constants.CMD_DC_MOTOR_ALL_ON] = {\n                    l1: l1,\n                    r1: r1,                       \n                    l2: l2,\n                    r2: r2,\n                };    \n                Entry.cuboai.updateAndClear();          \n                return script.callReturn(); \n            },\n            syntax: {\n                js: [],\n                py: ['cuboai.cuboai_set_motor_speed(%1, %2, %3, %4)'],\n            },\n        },\n        //서보모터 각도, 속도 설정\n        cuboai_set_servo_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '20',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_servo_out_list',\n                        params: [3],\n                    },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cuboai_set_servo_motor',\n            },\n            paramsKeyMap: {\n                port: 0,\n                angle: 1,\n                speed: 2,\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let port = script.getNumberValue('port');\n                let angle = script.getNumberValue('angle');\n                let speed = script.getNumberValue('speed');\n                port = Math.max(3, Math.min(port, 6));\n                angle = Math.max(-90, Math.min(angle, 90));\n                if(angle < 0){\n                    angle = 255 + angle;\n                }\n                Entry.hw.sendQueue.SET[Entry.cuboai.constants.CMD_SERVO_MOTOR] = {\n                    port: port,\n                    angle: angle,\n                    speed: speed,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_set_servo_motor(%1,%2,%3)'] },\n        },\n        //모든 DC모터 끄기\n        cuboai_stop_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'cuboai_stop_motor',\n            },\n            paramsKeyMap: {},\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[Entry.cuboai.constants.CMD_DC_MOTOR_OFF] = {\n                    data: true,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_stop_motor()'] },\n        },\n        //키보드 값 전달\n        cuboai_set_keyboard_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },   \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },            \n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_keyboard_list',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cuboai_set_keyboard_value',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n             func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let value = script.getNumberValue('value');               \n                Entry.hw.sendQueue.SET[Entry.cuboai.constants.CMD_IN_KEYBOARD] = {\n                    value: value,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_set_keyboard_value(%1)'] },\n        },\n        //리모컨 값 읽기\n        cuboai_get_remote_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cuboai_get_remote_value',\n            },\n            class: 'AI_IoT_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {               \n                if(!Entry.hw.portData || Entry.hw.portData['rmc'] === undefined){\n                    return 0;\n                }\n                const rawValue = Entry.hw.portData['rmc'];\n                return rawValue;\n            },\n            syntax: { js: [], py: ['cuboai.cuboai_get_remote_value()'] },\n        },\n\n        // AI LAMP 저장 카테고리\n        cuboai_get_save_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.cuboai_get_save_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.cuboai_get_iot_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'cuboai_get_save_title',\n            },\n            class: 'AI_Save_Command',\n            isNotFor: ['cuboai'],\n            events: {},\n        },\n        // 저장 시작\n        cuboai_block_save_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    {\n                        type: 'cuboai_block_save_list',\n                        params: [0],\n                    },\n                    null,\n                ],\n                type: 'cuboai_block_save_start',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'AI_Save_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let value = script.getNumberValue('value');\n                value = Math.max(0, Math.min(value, 1));\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_BLOCK_SAVE_START}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    value: value,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_save_start(%1)'] },\n        },\n        // 저장 끝\n        cuboai_block_save_end: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_without_next',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'cuboai_block_save_end',\n            },\n            class: 'AI_Save_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_BLOCK_SAVE_END}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    data: true,\n                };\n                Entry.cuboai.updateAndClear();\n                if (Entry.engine && Entry.engine.toggleStop) {\n                    Entry.engine.toggleStop(); \n                } else if (Entry.engine && Entry.engine.stopProject) {\n                    Entry.engine.stopProject();\n                }\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_save_end()'] },\n        },\n        \n        // AI LAMP 조건\n        cuboai_get_cond_title:{\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.cuboai_get_cond_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.cuboai_get_cond_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'cuboai_get_cond_title',\n            },\n            class: 'AI_Cond_Command',\n            isNotFor: ['cuboai'],\n            events: {},\n        },\n\n        cuboai_block_flow_if_start: {  \n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, \n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    null,\n                    null,           \n                ],\n                type: 'cuboai_block_flow_if_start',\n            },\n            paramsKeyMap: {},\n            class: 'AI_Cond_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.cuboai.packetStack.unshift({\n                    cmd: Entry.cuboai.constants.CMD_FLOW_COND_IF,\n                    payload: { data: true }\n                });\n\n                Entry.cuboai.flushStack();\n                Entry.cuboai.packetStack.unshift({\n                    cmd: Entry.cuboai.constants.CMD_FLOW_COND_IF_START,\n                    payload: { data: true }\n                });\n\n                Entry.cuboai.flushStack();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_if_start(%1)'] },\n        },\n        cuboai_block_flow_else_start: {  \n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, \n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    null,           \n                ],\n                type: 'cuboai_block_flow_else_start',\n            },\n            class: 'AI_Cond_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_COND_ELSE_START}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    data: true,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_else_start()'] },\n        },\n        cuboai_block_flow_else_end: {  \n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, \n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    null,           \n                ],\n                type: 'cuboai_block_flow_else_end',\n            },\n            class: 'AI_Cond_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_else_end()'] },\n        },\n        cuboai_block_flow_if_end: {  \n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE, \n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    null,           \n                ],\n                type: 'cuboai_block_flow_if_end',\n            },\n            class: 'AI_Cond_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                \n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_COND_IF_END}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    data: true,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_if_end()'] },\n        },\n\n        //AI LAMP 반복\n        cuboai_get_loop_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.cuboai_get_loop_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.cuboai_get_loop_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'cuboai_get_loop_title',\n            },\n            class: 'AI_Loop_Command',\n            isNotFor: ['cuboai'],\n            events: {},\n        },\n        cuboai_block_flow_loop_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    null,\n                ],\n                type: 'cuboai_block_flow_loop_start',\n            },\n            paramsKeyMap: {},\n            class: 'AI_Loop_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_LOOP_START}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    data: true,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_loop_start()'] },\n        },\n        cuboai_block_flow_loop_end: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    null,                               \n                ],\n                type: 'cuboai_block_flow_loop_end',\n            },\n            paramsKeyMap: {},\n            class: 'AI_Loop_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_LOOP_END}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    data: true,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_loop_end()'] },\n        },\n        cuboai_block_flow_loop_cnt_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    0,\n                    null,\n                ],\n                type: 'cuboai_block_flow_loop_cnt_start',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'AI_Loop_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const value = script.getNumberValue('value', script);\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_LOOP_CNT_START}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    value: value\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_loop_cnt_start(%1)'] },\n        },\n        cuboai_block_flow_loop_cnt_end: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    null,\n                ],\n                type: 'cuboai_block_flow_loop_cnt_end',\n            },\n            paramsKeyMap: {},\n            class: 'AI_Loop_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_LOOP_CNT_END}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    data: true,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_loop_cnt_end()'] },\n        },\n        cuboai_block_flow_loop_delay_sec: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    0,\n                    {\n                        type: 'cuboai_block_delay_list',\n                        params: [1],\n                    },\n                    null,\n                ],\n                type: 'cuboai_block_flow_loop_delay_sec',\n            },\n            paramsKeyMap: {\n                value: 0,\n                type: 1,\n            },\n            class: 'AI_Loop_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const value = script.getNumberValue('value', script);\n                const type = script.getNumberValue('type', script);\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_LOOP_DELAY_SEC}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    value: value,\n                    type: type\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_loop_delay_sec(%1,%2)'] },\n        },\n        cuboai_block_flow_loop_break_continue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    {\n                        type: 'cuboai_block_loop_break_list',\n                        params: [0],\n                    },\n                    null,\n                ],\n                type: 'cuboai_block_flow_loop_break_continue',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'AI_Loop_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const value = script.getNumberValue('value', script);\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_LOOP_BREAK_CONTINUE}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    value: value,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_loop_break_continue(%1)'] },\n        },\n\n        //AI LAMP 판단\n        cuboai_get_jgmt_title: {    \n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.cuboai_get_jgmt_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.cuboai_get_jgmt_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'cuboai_get_jgmt_title',\n            },\n            class: 'AI_Jgmt_Command',\n            isNotFor: ['cuboai'],\n            events: {},\n        },\n        cuboai_block_flow_jgmt_logic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'boolean',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'cuboai_block_logic_list',\n                        params: [1],\n                    },,\n                    null,\n                ],\n                type: 'cuboai_block_flow_jgmt_logic',\n            },\n            paramsKeyMap: {\n                value: 1,\n            },\n            class: 'AI_Jgmt_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                let value = script.getNumberValue('value');\n                Entry.cuboai.packetStack.unshift({\n                    cmd: Entry.cuboai.constants.CMD_FLOW_JGMT_LOGIC,\n                    payload: { \n                        value: value,\n                    }\n                });\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_jgmt_logic(%2)'] },\n        },\n        cuboai_block_flow_jgmt_sign: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '0',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '0',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'cuboai_block_jgmt_list',\n                        params: [0],\n                    },,\n                    null,\n                ],\n                type: 'cuboai_block_flow_jgmt_sign',\n            },\n            paramsKeyMap: {\n                left: 0,\n                jgmt: 1,\n                right: 2,\n            },\n            class: 'AI_Jgmt_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                const left = script.getValue('left');\n                const jgmt = script.getNumberValue('jgmt');\n                const right = script.getValue('right');\n\n                if(right && right.cmd){\n                    Entry.cuboai.packetStack.unshift(right);\n                }\n                else if(right !== undefined && right !== null){\n                    const val = isNaN(Number(right)) ? right : Number(right);\n                    Entry.cuboai.packetStack.unshift({\n                        cmd: Entry.cuboai.constants.CMD_FLOW_COND_NUM,\n                        payload: { \n                            value: val,\n                        }\n                    });    \n                }\n\n                if(left && left.cmd){\n                    Entry.cuboai.packetStack.unshift(left);\n                }\n                else if(left !== undefined && left !== null){\n                    const val = isNaN(Number(left)) ? left : Number(left);\n                    Entry.cuboai.packetStack.unshift({\n                        cmd: Entry.cuboai.constants.CMD_FLOW_COND_NUM,\n                        payload: { \n                            value: val,\n                        }\n                    });\n                }\n                Entry.cuboai.packetStack.unshift({\n                    cmd: Entry.cuboai.constants.CMD_FLOW_JGMT_SIGN,\n                    payload: { \n                        jgmt: jgmt,\n                    }\n                });\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_jgmt_sign(%2)'] },\n        },\n        \n        \n        //AI LAMP 값\n        cuboai_get_value_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.cuboai_get_value_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.cuboai_get_value_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'cuboai_get_value_title',\n            },\n            class: 'AI_Value_Command',\n            isNotFor: ['cuboai'],\n            events: {},\n        },        \n        cuboai_block_flow_write_variable: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '0',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_block_variable_list',\n                        params: [0],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'cuboai_block_flow_write_variable',\n            },\n            paramsKeyMap: {\n                variable: 0,\n                value: 1,\n            },\n            class: 'AI_Value_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let variable = script.getNumberValue('variable');\n                let value = script.getNumberValue('value');\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_WRITE_VARIABLE}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    variable: variable,\n                    value: value,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_write_variable(%1,%2)'] },\n        },\n        cuboai_block_flow_set_variable: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_block_variable_list',\n                        params: [0],\n                    },\n                    null,\n                    {\n                        type: 'cuboai_block_calc_list',\n                        params: [0],\n                    },\n                    null,\n                ],\n                type: 'cuboai_block_flow_set_variable',\n            },\n            paramsKeyMap: {\n                variable: 0,\n                value: 1,\n                calc: 2,\n            },\n            class: 'AI_Value_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let variable = script.getNumberValue('variable');\n                let value = script.getNumberValue('value');\n                let calc = script.getNumberValue('calc');\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_FLOW_SET_VARIABLE}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    variable: variable,\n                    value: value,      \n                    calc: calc,                 \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_set_variable(%1,%2)'] },\n        },  \n        cuboai_block_flow_read_variable: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_block_variable_list',\n                        params: [0],\n                    },\n                ],\n                type: 'cuboai_block_flow_read_variable',\n            },\n            paramsKeyMap: {\n                variable: 0,\n            },\n            class: 'AI_Value_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                let variable = script.getNumberValue('variable');\n                return {\n                    cmd: Entry.cuboai.constants.CMD_FLOW_READ_VARIABLE,\n                    payload: { \n                        variable: variable,\n                    }                        \n                }\n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_read_variable(%1)'] },\n        },     \n        cuboai_block_flow_remote_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_block_remocon_list',\n                        params: [34],\n                    },\n                ],\n                type: 'cuboai_block_flow_remote_value',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'AI_Value_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                let value = script.getNumberValue('value');\n                return {\n                    cmd: Entry.cuboai.constants.CMD_FLOW_COND_NUM,\n                    payload: { \n                        value: value,\n                    }                        \n                } \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_flow_remote_value(%1)'] },\n        },\n        cuboai_get_command_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.cuboai_get_command_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.cuboai_get_value_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'cuboai_get_command_title',\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            events: {},\n        },\n        //디지털 핀, 값 설정\n        cuboai_block_iotkit_digit_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_digital_out_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'cuboai_highlow_list',\n                        params: [1],\n                    },\n                    null,\n                ],\n                type: 'cuboai_block_iotkit_digit_output',\n            },\n            paramsKeyMap: {\n                port: 0,\n                value: 1,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let port = script.getNumberValue('port');\n                let value = script.getNumberValue('value');\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_IOT_DIGIT_OUTPUT}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    port: port,\n                    value: value,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_iotkit_digit_output(%1,%2)'] },\n        },\n        //디지털 핀 값 읽기\n        cuboai_block_iotkit_digit_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_digital_in_list',\n                        params: [1],\n                    },\n                ],\n                type: 'cuboai_block_iotkit_digit_input',\n            },\n            paramsKeyMap: {\n                port: 0,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                let port = script.getNumberValue('port');\n                return {\n                    cmd: Entry.cuboai.constants.CMD_IOT_DIGIT_INPUT,\n                    payload: {\n                        port: port-1,\n                    }                            \n                };\n                // Entry.cuboai.packetStack.unshift({\n                //     cmd: Entry.cuboai.constants.CMD_IOT_DIGIT_INPUT,\n                //     payload: { \n                //         port: port,\n                //     }\n                // });\n                // return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_iotkit_digit_input(%1)'] },\n        },\n        //아날로그 핀 값 읽기\n        cuboai_block_iotkit_analog_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_digital_in_list',\n                        params: [1],\n                    },\n                ],\n                type: 'cuboai_block_iotkit_analog_input',\n            },\n            paramsKeyMap: {\n                port: 0,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                let port = script.getNumberValue('port');\n                return {\n                    cmd: Entry.cuboai.constants.CMD_IOT_ANALOG_INPUT,\n                    payload: { \n                        port: port-1,\n                    }                        \n                }\n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_iotkit_analog_input(%1)'] },\n        },\n        //모터1 속도 설정\n        cuboai_block_iotkit_dc_motor_1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_motor_speed_list',\n                        params: [100],\n                    },\n                    {\n                        type: 'cuboai_motor_speed_list',\n                        params: [100],\n                    },\n                    null,\n                ],\n                type: 'cuboai_block_iotkit_dc_motor_1',\n            },\n            paramsKeyMap: {\n                l1: 0,\n                r1: 1,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {                \n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let l1 = script.getNumberValue('l1');\n                let r1 = script.getNumberValue('r1');\n                l1 = Math.max(-100, Math.min(l1, 100));\n                r1 = Math.max(-100, Math.min(r1, 100));\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_IOT_DC_MOTOR_1_ON}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    l1: l1,\n                    r1: r1,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: {\n                js: [],\n                py: ['cuboai.cuboai_block_iotkit_dc_motor_1(%1, %2)'],\n            },\n        },\n        cuboai_block_iotkit_dc_motor_1_: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '100',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '100',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cuboai_block_iotkit_dc_motor_1_',\n            },\n            paramsKeyMap: {\n                l1: 0,\n                r1: 1,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {                \n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let l1 = script.getNumberValue('l1');\n                let r1 = script.getNumberValue('r1');\n                l1 = Math.max(-100, Math.min(l1, 100));\n                r1 = Math.max(-100, Math.min(r1, 100));\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_IOT_DC_MOTOR_1_ON}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    l1: l1,\n                    r1: r1,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: {\n                js: [],\n                py: ['cuboai.cuboai_block_iotkit_dc_motor_1_(%1, %2)'],\n            },\n        },\n        //모터2 속도 설정\n        cuboai_block_iotkit_dc_motor_2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_motor_speed_list',\n                        params: [100],\n                    },\n                    {\n                        type: 'cuboai_motor_speed_list',\n                        params: [100],\n                    },\n                    null,\n                ],\n                type: 'cuboai_block_iotkit_dc_motor_2',\n            },\n            paramsKeyMap: {\n                l2: 0,\n                r2: 1,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let l2 = script.getNumberValue('l2');\n                let r2 = script.getNumberValue('r2');\n                l2 = Math.max(-100, Math.min(l2, 100));\n                r2 = Math.max(-100, Math.min(r2, 100));\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_IOT_DC_MOTOR_2_ON}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    l2: l2,\n                    r2: r2,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: {\n                js: [],\n                py: ['cuboai.cuboai_block_iotkit_dc_motor_2(%1, %2)'],\n            },\n        },\n        cuboai_block_iotkit_dc_motor_2_: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '100',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '100',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cuboai_block_iotkit_dc_motor_2_',\n            },\n            paramsKeyMap: {\n                l2: 0,\n                r2: 1,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let l2 = script.getNumberValue('l2');\n                let r2 = script.getNumberValue('r2');\n                l2 = Math.max(-100, Math.min(l2, 100));\n                r2 = Math.max(-100, Math.min(r2, 100));\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_IOT_DC_MOTOR_2_ON}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    l2: l2,\n                    r2: r2,                       \n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: {\n                js: [],\n                py: ['cuboai.cuboai_block_iotkit_dc_motor_2_(%1, %2)'],\n            },\n        },\n        //모터1, 2 속도 설정\n        cuboai_block_iotkit_dc_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '100',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '100',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '100',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '100',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cuboai_block_iotkit_dc_motor_speed',\n            },\n            paramsKeyMap: {\n                l1: 0,\n                l2: 1,\n                r1: 2,\n                r2: 3,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let l1 = script.getNumberValue('l1');\n                let r1 = script.getNumberValue('r1');\n                let l2 = script.getNumberValue('l2');\n                let r2 = script.getNumberValue('r2');\n                l1 = Math.max(-100, Math.min(l1, 100));\n                r1 = Math.max(-100, Math.min(r1, 100));\n                l2 = Math.max(-100, Math.min(l2, 100));\n                r2 = Math.max(-100, Math.min(r2, 100));\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_IOT_DC_MOTOR_SPEED}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    l1: l1,\n                    r1: r1,                       \n                    l2: l2,\n                    r2: r2,\n                };    \n                Entry.cuboai.updateAndClear();           \n                return script.callReturn(); \n            },\n            syntax: {\n                js: [],\n                py: ['cuboai.cuboai_block_iotkit_dc_motor_speed(%1, %2, %3, %4)'],\n            },\n        },\n        //서보모터 각도, 속도 설정\n        cuboai_block_iotkit_servo_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: '20',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'cuboai_servo_out_list',\n                        params: [3],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'cuboai_block_iotkit_servo_motor',\n            },\n            paramsKeyMap: {\n                port: 0,\n                angle: 1,\n                speed: 2,\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                let port = script.getNumberValue('port');\n                let angle = script.getNumberValue('angle');\n                let speed = script.getNumberValue('speed');\n                port = Math.max(3, Math.min(port, 6));\n                angle = Math.max(-90, Math.min(angle, 90));\n                if(angle < 0){\n                    angle = 255 + angle;\n                }\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_IOT_SERVO_MOTOR_ANGLE}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    port: port,\n                    angle: angle,\n                    speed: speed,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_iotkit_servo_motor(%1,%2,%3)'] },\n        },\n        //모든 DC모터 끄기\n        cuboai_block_iotkit_dc_motor_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [   \n                    null,\n                ],\n                type: 'cuboai_block_iotkit_dc_motor_off',\n            },\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                const currentIdx = Entry.cuboai.cmdIdx++;\n                const uniqueKey = `${Entry.cuboai.constants.CMD_IOT_DC_MOTOR_OFF}_${currentIdx}`;\n                Entry.hw.sendQueue.SET[uniqueKey] = {\n                    data: true,\n                };\n                Entry.cuboai.updateAndClear();\n                return script.callReturn(); \n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_iotkit_dc_motor_off()'] },\n        },\n        //리모컨 값 읽기\n        cuboai_block_iotkit_read_remote: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            events: {},\n            class: 'AI_Command_Command',\n            isNotFor: ['cuboai'],\n            func: function(sprite, script) { \n                return { \n                    cmd: Entry.cuboai.constants.CMD_IOT_READ_REMOTE, \n                    payload: { data: true } \n                };\n            },\n            syntax: { js: [], py: ['cuboai.cuboai_block_iotkit_read_remote()'] },\n        },\n        \n        // ETC Block\n        cuboai_digital_out_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 1],\n                        ['OUT2', 2],\n                        ['OUT3', 3],\n                        ['OUT4', 4],\n                        ['OUT5', 5],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                port: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('port');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['OUT1', 1],\n                                    ['OUT2', 2],\n                                    ['OUT3', 3],\n                                    ['OUT4', 4],\n                                    ['OUT5', 5],\n                                ],\n                                value: 1,\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_digital_out_list',\n                    },\n                ],\n            },\n        },\n        cuboai_digital_in_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 1],\n                        ['IN2', 2],\n                        ['IN3', 3],\n                        ['IN4', 4],\n                        ['IN5', 5],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                port: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('port');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['IN1', 1],\n                                    ['IN2', 2],\n                                    ['IN3', 3],\n                                    ['IN4', 4],\n                                    ['IN5', 5],\n                                ],\n                                value: 1,\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_digital_in_list',\n                    },\n                ],\n            },\n        },\n        cuboai_highlow_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', 1], \n                        ['끄기', 0]\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('value');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'cuboai_highlow_list',\n                    },\n                ],\n            },\n        },\n        cuboai_servo_out_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT3', 3],\n                        ['OUT4', 4],\n                        ['OUT5', 5],\n                        ['OUT6', 6],\n                    ],\n                    value: 3,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                port: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('port');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['OUT3', 3],\n                                    ['OUT4', 4],\n                                    ['OUT5', 5],\n                                    ['OUT6', 6],\n                                ],\n                                value: 3,\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_servo_out_list',\n                    },\n                ],\n            },\n        },\n        cuboai_keyboard_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'DropdownExtra',\n                    options: [\n                        ['space', 32],\n                        ['enter', 13],\n                        ['↑', 9],\n                        ['↓', 10],\n                        ['←', 11],\n                        ['→', 12],\n                        ['a', 97],\n                        ['b', 98],\n                        ['c', 99],\n                        ['d', 100],\n                        ['e', 101],\n                        ['f', 102],\n                        ['g', 103],\n                        ['h', 104],\n                        ['i', 105],\n                        ['j', 106],\n                        ['k', 107],\n                        ['l', 108],\n                        ['m', 109],\n                        ['n', 110],\n                        ['o', 111],\n                        ['p', 112],\n                        ['q', 113],\n                        ['r', 114],\n                        ['s', 115],\n                        ['t', 116],\n                        ['u', 117],\n                        ['v', 118],\n                        ['w', 119],\n                        ['x', 120],\n                        ['y', 121],\n                        ['z', 122],\n                    ],\n                    value: 32,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('value');\n            }\n        },\n        cuboai_motor_speed_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100', '100'],\n                        ['90', '90'],\n                        ['80', '80'],\n                        ['70', '70'],\n                        ['60', '60'],\n                        ['50', '50'],\n                        ['40', '40'],\n                        ['30', '30'],\n                        ['20', '20'],\n                        ['10', '10'],\n                        ['0', '0'],\n                        ['-10', '-10'],\n                        ['-20', '-20'],\n                        ['-30', '-30'],\n                        ['-40', '-40'],\n                        ['-50', '-50'],\n                        ['-60', '-60'],\n                        ['-70', '-70'],\n                        ['-80', '-80'],\n                        ['-90', '-90'],\n                        ['-100', '-100'],                        \n                    ],\n                    value: '100',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['100', '100'],\n                                    ['90', '90'],\n                                    ['80', '80'],\n                                    ['70', '70'],\n                                    ['60', '60'],\n                                    ['50', '50'],\n                                    ['40', '40'],\n                                    ['30', '30'],\n                                    ['20', '20'],\n                                    ['10', '10'],\n                                    ['0', '0'],\n                                    ['-10', '-10'],\n                                    ['-20', '-20'],\n                                    ['-30', '-30'],\n                                    ['-40', '-40'],\n                                    ['-50', '-50'],\n                                    ['-60', '-60'],\n                                    ['-70', '-70'],\n                                    ['-80', '-80'],\n                                    ['-90', '-90'],\n                                    ['-100', '-100'],   \n                                ],\n                                value: '100',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_motor_speed_list',\n                    },\n                ],\n            },\n        },\n        cuboai_block_save_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['저장소1', 0],\n                        ['저장소2', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                     ['저장소1', '0'],\n                                     ['저장소2', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_block_save_list',\n                    },\n                ],\n            },\n        },\n        cuboai_block_variable_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['변수1', 0],\n                        ['변수2', 1],\n                        ['변수3', 2],\n                        ['변수4', 3],\n                        ['변수5', 4],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['변수1', 0],\n                                    ['변수2', 1],\n                                    ['변수3', 2],\n                                    ['변수4', 3],\n                                    ['변수5', 4],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_block_variable_list',\n                    },\n                ],\n            },\n        },\n        cuboai_block_calc_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['더하기', 0],\n                        ['빼기', 1],\n                        ['곱하기', 2],\n                        ['나누기', 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['더하기', 0],\n                                    ['빼기', 1],\n                                    ['곱하기', 2],\n                                    ['나누기', 3],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_block_calc_list',\n                    },\n                ],\n            },\n        },\n        cuboai_block_remocon_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'DropdownExtra',\n                    options: [\n                        ['↑', 34],\n                        ['↓', 42],\n                        ['←', 58],\n                        ['→', 50],\n                        ['↑+F1', 5],\n                        ['↑+F2', 41],\n                        ['↑+F3', 21],\n                        ['↑+F4', 57],\n                        ['↓+F1', 13],\n                        ['↓+F2', 61],\n                        ['↓+F3', 29],\n                        ['↓+F4', 45],\n                        ['KEY OFF', 0],\n                        ['R', 33],\n                        ['F1', 38],\n                        ['F2', 54],\n                        ['F3', 46],\n                        ['F4', 62],\n                        ['↑+R', 49],\n                        ['↓+R', 37],\n                        ['←+R', 25],\n                        ['→+R', 9],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['↑', 34],\n                                    ['↓', 42],\n                                    ['←', 58],\n                                    ['→', 50],\n                                    ['↑+F1', 5],\n                                    ['↑+F2', 41],\n                                    ['↑+F3', 21],\n                                    ['↑+F4', 57],\n                                    ['↓+F1', 13],\n                                    ['↓+F2', 61],\n                                    ['↓+F3', 29],\n                                    ['↓+F4', 45],\n                                    ['KEY OFF', 0],\n                                    ['R', 33],\n                                    ['F1', 38],\n                                    ['F2', 54],\n                                    ['F3', 46],\n                                    ['F4', 62],\n                                    ['↑+R', 49],\n                                    ['↓+R', 37],\n                                    ['←+R', 25],\n                                    ['→+R', 9],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_block_remocon_list',\n                    },\n                ],\n            },\n        },\n        cuboai_block_logic_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['그리고', 1],\n                        ['또는', 0],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['그리고', 1],\n                                    ['또는', 0],\n                                ],\n                                value: 1,\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_block_logic_list',\n                    },\n                ],\n            },\n        },\n        cuboai_block_jgmt_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 0],\n                        ['≠', 1],\n                        ['<', 2],\n                        ['≤', 3],\n                        ['>', 4],\n                        ['≥', 5],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['=', 0],\n                                    ['≠', 1],\n                                    ['<', 2],\n                                    ['≤', 3],\n                                    ['>', 4],\n                                    ['≥', 5],\n                                ],\n                                value: 1,\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_block_jgmt_list',\n                    },\n                ],\n            },\n        },\n        cuboai_block_delay_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['초', 1],\n                        ['밀리초', 0],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['초', 1],\n                                    ['밀리초', 0],\n                                ],\n                                value: 1,\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_block_delay_list',\n                    },\n                ],\n            },\n        },\n        cuboai_block_loop_break_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['반복 중단', 0],\n                        ['다음 반복', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['반복 중단', 0],\n                                    ['다음 반복', 1],\n                                ],\n                                value: 0,\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'cuboai_block_loop_break_list',\n                    },\n                ],\n            },\n        },\n    };\n};\nmodule.exports = Entry.cuboai;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_cue.js",
    "content": "'use strict';\n\nvar CueState = {\n    STATE_READY: 'ready',\n    STATE_WAIT: 'wait',\n    STATE_DONE: 'done',\n};\n\nEntry.Cue = {\n    PORT_MAP: {\n        seq: 0,\n        category: 0,\n        action: 0,\n        param_cnt: 0,\n        paramA: 0,\n        paramB: 0,\n        paramC: 0,\n        paramD: 0,\n        modeA: 0,\n        modeB: 0,\n    },\n    setZero: function () {\n        var portMap = Entry.Cue.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        Entry.Cue.sequance = 1;\n        Entry.Cue.isStarted = false;\n        Entry.Cue.state = CueState.STATE_DONE;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n    },\n    id: '24.3',\n    name: 'Cue',\n    url: 'https://clevermate.kr/',\n    imageName: 'cue.png',\n    title: {\n        ko: '큐',\n        en: 'Cue',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/cue.png',\n        width: 605,\n        height: 434,\n    },\n    sequance: 1,\n    isStarted: false,\n    state: CueState.STATE_DONE,\n};\nEntry.Cue.blockMenuBlocks = [\n    'cue_sensor1',\n    'cue_sensor2',\n    'cue_turn_drive',\n    'cue_turn_drive_360',\n    'cue_drive',\n    'cue_wheel_speed',\n    'cue_drive_stop',\n    'cue_v_head',\n    'cue_h_head',\n    'cue_forward_head',\n    'cue_light_color',\n    'cue_eye',\n    'cue_sound_emotion',\n    'cue_sound_moving',\n    'cue_sound_greeting',\n    'cue_sound_shape',\n    'cue_sound_color',\n    'cue_sound_number',\n    'cue_sound_direction',\n    'cue_my_sound',\n];\nEntry.Cue.getBlocks = function () {\n    return {\n\n        cue_sensor1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가운데 버튼', 0x05],\n                        ['버튼 ●', 0x06],\n                        ['버튼 ■', 0x07],\n                        ['버튼 ▲', 0x08],\n                        ['박수 소리', 0x09],\n                        ['소리', 0x0a],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['5'],\n                type: 'cue_sensor1',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            isNotFor: ['Cue'],\n            class: 'Cue_senor',\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('VALUE', script);\n                var pd = Entry.hw.portData;\n                switch (var1) {\n                    case 0x05:\n                        return pd.button0 ? true : false;\n                        break;\n                    case 0x06:\n                        return pd.button1 ? true : false;\n                        break;\n                    case 0x07:\n                        return pd.button2 ? true : false;\n                        break;\n                    case 0x08:\n                        return pd.button3 ? true : false;\n                        break;\n                    case 0x09:\n                        return pd.clap ? true : false;\n                        break;\n                    case 0x0a:\n                        return pd.sound ? true : false;\n                        break;\n                    default:\n                        break;\n                }\n                return -1;\n            },\n        },\n        cue_sensor2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞쪽 장애물', 0x00],\n                        ['뒤쪽 장애물', 0x01],\n                        ['오른쪽 장애물', 0x02],\n                        ['왼쪽 장애물', 0x03],\n                        // [ \"움직이지 못함\", 0x04 ],\t// not support.\n                        ['들림', 0x0a],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['0'],\n                type: 'cue_sensor2',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            isNotFor: ['Cue'],\n            class: 'Cue_senor',\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('VALUE', script);\n                var pd = Entry.hw.portData;\n                switch (var1) {\n                    case 0x00:\n                        return pd.barrier_front ? true : false;\n                        break;\n                    case 0x01:\n                        return pd.barrier_rear ? true : false;\n                        break;\n                    case 0x02:\n                        return pd.barrier_right ? true : false;\n                        break;\n                    case 0x03:\n                        return pd.barrier_left ? true : false;\n                        break;\n                    case 0x04:\n                        return pd.barrier_move ? true : false;\n                        break;\n                    case 0x0a:\n                        return pd.pickup ? true : false;\n                        break;\n                    default:\n                        break;\n                }\n                return -1;\n            },\n        },\n\n        cue_turn_drive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 으로 %2 만큼 회전하기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['시계 방향', 0x03], ['반 시계 방향', 0x04]],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'angle',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['3', 30],\n                type: 'cue_turn_drive',\n            },\n            paramsKeyMap: {\n                ROTATION: 0,\n                VALUE: 1,\n            },\n            class: 'Cue_drive',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('ROTATION', script);\n                var var2 = script.getNumberValue('VALUE', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 1;\n                    sq.action = var1;\n                    sq.param_cnt = 1;\n                    sq.paramA = var2;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isDriving) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isDriving) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_turn_drive_360: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 으로 한 바퀴 회전하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['시계 방향', 0x03], ['반 시계 방향', 0x04]],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['3'],\n                type: 'cue_turn_drive_360',\n            },\n            paramsKeyMap: {\n                ROTATION: 0,\n            },\n            class: 'Cue_drive',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('ROTATION', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 1;\n                    sq.action = var1;\n                    sq.param_cnt = 1;\n                    sq.paramA = 360;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isDriving) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isDriving) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_drive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 (으)로 %2 cm 만큼 %3이동하기 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['앞', 0x01], ['뒤', 0x02]],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['매우 느리게', 0x01],\n                        ['느리게', 0x02],\n                        ['보통 속도로', 0x03],\n                        ['빠르게', 0x04],\n                        ['매우 빠르게', 0x05],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', 30, '3'],\n                type: 'cue_drive',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DISTANCE: 1,\n                SPEED: 2,\n            },\n            class: 'Cue_drive',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('DIRECTION', script);\n                var var2 = script.getNumberValue('DISTANCE', script);\n                var var3 = script.getNumberField('SPEED', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 1;\n                    sq.action = var1;\n                    sq.param_cnt = 2;\n                    if (var2 > 1638) {\n                        var2 = 1638;\n                    }\n                    sq.paramA = var2;\n                    sq.paramB = var3;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isDriving) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isDriving) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_wheel_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '왼쪽 바퀴 %1(으)로 %2cm/s, 오른쪽 바퀴 %3(으)로 %4cm/s 속도로 움직이기 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['앞', 0x01], ['뒤', 0x02]],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['앞', 0x01], ['뒤', 0x02]],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '20', '1', '20'],\n                type: 'cue_wheel_speed',\n            },\n            paramsKeyMap: {\n                DIRECTION_L: 0,\n                SPEED_L: 1,\n                DIRECTION_R: 2,\n                SPEED_R: 3,\n            },\n            class: 'Cue_drive',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('DIRECTION_L', script);\n                var var2 = script.getNumberValue('SPEED_L', script);\n                var var3 = script.getNumberField('DIRECTION_R', script);\n                var var4 = script.getNumberValue('SPEED_R', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 0x01;\n                    sq.action = 0x05;\n                    sq.param_cnt = 0x04;\n                    sq.paramA = var1;\n                    sq.paramB = var2;\n                    sq.paramC = var3;\n                    sq.paramD = var4;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            var timer = setTimeout(function () {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }, 50);\n                            Entry.Cue.state = CueState.STATE_WAIT;\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_drive_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '정지 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cue_drive_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Cue_drive',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 0x01;\n                    sq.action = 0x06;\n                    sq.param_cnt = 0;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            var timer = setTimeout(function () {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }, 50);\n                            Entry.Cue.state = CueState.STATE_WAIT;\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_v_head: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 바라보기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['위쪽', 0x04], ['가운데', 0x05], ['아래쪽', 0x06]],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4'],\n                type: 'cue_v_head',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'Cue_head',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('DIRECTION', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 3;\n                    sq.action = var1;\n                    sq.param_cnt = 0;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            var timer = setTimeout(function () {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }, 500);\n                            Entry.Cue.state = CueState.STATE_WAIT;\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_h_head: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 을 %2 방향으로 바라보기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', 0x01],\n                        // [ \"가운데\", 0x02 ],\n                        ['오른쪽', 0x03],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['15˚', 15],\n                        ['30˚', 30],\n                        ['45˚', 45],\n                        ['60˚', 60],\n                        ['75˚', 75],\n                        ['90˚', 90],\n                        ['105˚', 105],\n                        ['120˚', 120],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', 30],\n                type: 'cue_h_head',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n            },\n            class: 'Cue_head',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('DIRECTION', script);\n                var var2 = script.getNumberField('VALUE', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 3;\n                    sq.action = var1;\n                    sq.param_cnt = 1;\n                    if (var2 > 120) {\n                        var2 = 120;\n                    }\n                    sq.paramA = var2;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            var timer = setTimeout(function () {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }, 1000);\n                            Entry.Cue.state = CueState.STATE_WAIT;\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_forward_head: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '앞을 바라보기 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cue_forward_head',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Cue_head',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 3;\n                    sq.action = 0x02;\n                    sq.param_cnt = 0;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            var timer = setTimeout(function () {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }, 500);\n                            Entry.Cue.state = CueState.STATE_WAIT;\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_voice_head: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '소리가 나는 쪽 바라보기 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'cue_voice_head',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Cue_head',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 3;\n                    sq.action = 7;\n                    sq.param_cnt = 0;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.soundDirection) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                                var timer = setTimeout(function () {\n                                    Entry.Cue.state = CueState.STATE_DONE;\n                                }, 100);\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_light_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 라이트 %2 색으로 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['모든', 0x01],\n                        ['왼쪽 귀', 0x02],\n                        ['오른쪽 귀', 0x03],\n                        ['전면', 0x04],\n                        ['버튼', 0x07],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'cue_light_color',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },\n            class: 'Cue_light',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('LED', script);\n                var var2 = script.getStringField('COLOR', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 4;\n                    sq.action = var1;\n                    sq.param_cnt = 1;\n                    sq.paramA = parseInt(parseInt(var2.substr(1, 2), 16));\n                    sq.paramB = parseInt(parseInt(var2.substr(3, 2), 16));\n                    sq.paramC = parseInt(parseInt(var2.substr(5, 2), 16));\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            var timer = setTimeout(function () {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }, 50);\n                            Entry.Cue.state = CueState.STATE_WAIT;\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_eye: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '눈 패턴 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['끄기', 0x00],\n                        ['웃는 얼굴', 0x01],\n                        ['익살스러운 얼굴', 0x02],\n                        ['화난 얼굴', 0x03],\n                        ['놀란 얼굴', 0x04],\n                        ['모두 켜기', 0x05],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0'],\n                type: 'cue_eye',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n            },\n            class: 'Cue_light',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var var1 = script.getNumberField('EYE', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 4;\n                    sq.action = 6;\n                    sq.param_cnt = 1;\n                    sq.paramA = var1;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            var timer = setTimeout(function () {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }, 50);\n                            Entry.Cue.state = CueState.STATE_WAIT;\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_sound_emotion: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '감정 %1 말하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['행복', 1],\n                        ['슬픔', 2],\n                        ['기쁨', 3],\n                        ['아픔', 4],\n                        ['무서움', 5],\n                        ['무작위', 0],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'cue_sound_emotion',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Cue_Sound',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 5;\n                    sq.action = 2;\n                    sq.param_cnt = 1;\n                    if (var1 == 0) {\n                        var1 = Math.floor(Math.random() * 5) + 1;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_sound_moving: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '동작 %1 말하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['간다!', 6],\n                        ['해 보자!', 7],\n                        ['미션 성공!', 8],\n                        ['새로운 계획', 15],\n                        ['박수', 9],\n                        ['센서 가동', 10],\n                        ['들어올리기', 11],\n                        ['내려놓기', 12],\n                        ['손 앞에', 13],\n                        ['손 뒤에', 14],\n                        ['무작위', 0],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['6'],\n                type: 'cue_sound_moving',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Cue_Sound',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 5;\n                    sq.action = 2;\n                    sq.param_cnt = 1;\n                    if (var1 == 0) {\n                        var1 = Math.floor(Math.random() * 10) + 6;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_sound_greeting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '인사 %1 말하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['안녕!', 16],\n                        ['다음에 만나!', 17],\n                        ['생일 축하해!', 18],\n                        ['휴일 잘 보내!', 19],\n                        ['무작위', 0],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['16'],\n                type: 'cue_sound_greeting',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Cue_Sound',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 5;\n                    sq.action = 2;\n                    sq.param_cnt = 1;\n                    if (var1 == 0) {\n                        var1 = Math.floor(Math.random() * 4) + 16;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_sound_shape: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '모양 %1 말하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['원', 20],\n                        ['삼각형', 21],\n                        ['사각형', 22],\n                        ['무작위', 0],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['20'],\n                type: 'cue_sound_shape',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Cue_Sound',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 5;\n                    sq.action = 2;\n                    sq.param_cnt = 1;\n                    if (var1 == 0) {\n                        var1 = Math.floor(Math.random() * 3) + 20;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_sound_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '색깔 %1 말하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빨간색', 23],\n                        ['주황색', 24],\n                        ['노란색', 25],\n                        ['초록색', 26],\n                        ['파란색', 27],\n                        ['무작위', 0],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['23'],\n                type: 'cue_sound_color',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Cue_Sound',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 5;\n                    sq.action = 2;\n                    sq.param_cnt = 1;\n                    if (var1 == 0) {\n                        var1 = Math.floor(Math.random() * 5) + 23;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_sound_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '숫자 %1 말하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 28],\n                        ['2', 29],\n                        ['3', 30],\n                        ['무작위', 0],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['28'],\n                type: 'cue_sound_number',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Cue_Sound',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 5;\n                    sq.action = 2;\n                    sq.param_cnt = 1;\n                    if (var1 == 0) {\n                        var1 = Math.floor(Math.random() * 3) + 28;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_sound_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '방향 %1 말하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞쪽', 31],\n                        ['뒤쪽', 32],\n                        ['오른쪽', 33],\n                        ['왼쪽', 34],\n                        ['무작위', 0],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['31'],\n                type: 'cue_sound_direction',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Cue_Sound',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 5;\n                    sq.action = 2;\n                    sq.param_cnt = 1;\n                    if (var1 == 0) {\n                        var1 = Math.floor(Math.random() * 4) + 31;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        cue_my_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '녹음된 %1 소리 내기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['#1', 0x00],\n                        ['#2', 0x01],\n                        ['#3', 0x02],\n                        ['#4', 0x03],\n                        ['#5', 0x04],\n                        ['#6', 0x05],\n                        ['#7', 0x06],\n                        ['#8', 0x07],\n                        ['#9', 0x08],\n                        ['#10', 0x09],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0'],\n                type: 'cue_my_sound',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Cue_Sound',\n            isNotFor: ['Cue'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Cue.isStarted) {\n                    sq.category = 5;\n                    sq.action = 1;\n                    sq.param_cnt = 1;\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Cue.sequance++;\n                    Entry.Cue.isStarted = true;\n                    Entry.Cue.state = CueState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Cue.state) {\n                        case CueState.STATE_READY:\n                            if (pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_WAIT:\n                            if (!pd.isPlaying) {\n                                Entry.Cue.state = CueState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case CueState.STATE_DONE:\n                            Entry.Cue.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Cue;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_dadublock.js",
    "content": "'use strict';\n\nEntry.DaduBlock = {\n    id: 'C.1',\n    name: 'dadublock',\n    url: 'http://www.dadublock.com/',\n    imageName: 'dadublock.png',\n    title: {\n        ko: '다두블럭',\n        en: 'DaduBlock',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    BlockState: {},\n};\n\nEntry.DaduBlock_Car = {\n    id: 'C.2',\n    name: 'dadublock_car',\n    url: 'http://www.dadublock.com/',\n    imageName: 'dadublock_car.png',\n    title: {\n        ko: '다두블럭 자동차',\n        en: 'DaduBlock Car',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    BlockState: {},\n};\nEntry.DaduBlock_Car.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                dadublock_car_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                dadublock_car_get_analog_value: '아날로그 %1 번 센서값',\n                dadublock_car_get_analog_value_map:\n                    '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                dadublock_car_get_digital: '디지털 %1 번 센서값',\n                dadublock_car_get_irsensor: '적외선 %1 번 센서값',\n                dadublock_car_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n                dadublock_car_motor: '모터 %1 번을 %2 (으)로 %3 %의 속도로 움직이기 %4',\n                dadublock_car_motor_stop: '모터 %1 번 멈추기 %2',\n                dadublock_car_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n                dadublock_car_set_tone:\n                    '디지털 %1 번 핀 을 %2 음으로 %3의 옥타브로 %4 만큼 연주하기 %5',\n                dadublock_car_toggle_led: '디지털 %1 번 핀 %2 %3',\n            },\n            Menus: {\n                dadublock_car: '다두블럭 자동차',\n            },\n        },\n        en: {\n            template: {\n                dadublock_car_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                dadublock_car_get_analog_value: '아날로그 %1 번 센서값',\n                dadublock_car_get_analog_value_map:\n                    '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                dadublock_car_get_digital: '디지털 %1 번 센서값',\n                dadublock_car_get_irsensor: '적외선 %1 번 센서값',\n                dadublock_car_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n                dadublock_car_motor: '모터 %1 번을 %2 (으)로 %3 %의 속도로 움직이기 %4',\n                dadublock_car_motor_stop: '모터 %1 번 멈추기 %2',\n                dadublock_car_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n                dadublock_car_set_tone:\n                    '디지털 %1 번 핀 을 %2 음으로 %3의 옥타브로 %4 만큼 연주하기 %5',\n                dadublock_car_toggle_led: '디지털 %1 번 핀 %2 %3',\n            },\n            Menus: {\n                dadublock_car: 'DaduBlock Car',\n            },\n        },\n    };\n};\nEntry.DaduBlock.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                dadublock_get_analog_value: '아날로그 %1 번 센서값',\n                dadublock_get_analog_value_map:\n                    '아날로그 %1번 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값',\n                dadublock_get_ultrasonic_value: '울트라소닉 Trig %1번핀 Echo %2번핀 센서값',\n                dadublock_toggle_led: '디지털 %1 번 핀 %2 %3',\n                dadublock_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                dadublock_set_tone: '디지털 %1 번 핀을 %2 음으로 %3 옥타브로 %4 만큼 연주하기 %5',\n                dadublock_set_servo: '서보모터 %1 번 핀을 %2 의 각도로 정하기 %3',\n                dadublock_get_digital: '디지털 %1 번 센서값',\n            },\n            Menus: { dadublock: '다두블럭' },\n        },\n        en: {\n            template: {\n                dadublock_get_analog_value: 'Analog %1 Sensor value',\n                dadublock_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n                dadublock_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                dadublock_toggle_led: 'Digital %1 Pin %2 %3',\n                dadublock_digital_pwm: 'Digital %1 Pin %2 %3',\n                dadublock_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                dadublock_set_servo: 'Set servo pin %1 angle as %2 %3',\n                dadublock_get_digital: '디지털 %1 번 센서값',\n            },\n            Menus: { dadublock: 'DaduBlock' },\n        },\n    };\n};\n\nEntry.DaduBlock.blockMenuBlocks = [\n    //dadublock 2016-12-19\n    'dadublock_get_analog_value',\n    'dadublock_get_analog_value_map',\n    'dadublock_get_ultrasonic_value',\n    'dadublock_get_digital',\n    'dadublock_toggle_led',\n    'dadublock_digital_pwm',\n    'dadublock_set_servo',\n    'dadublock_set_tone',\n];\nEntry.DaduBlock_Car.blockMenuBlocks = [\n    //dadublock_car\n    'dadublock_car_get_analog_value',\n    'dadublock_car_get_analog_value_map',\n    'dadublock_car_get_ultrasonic_value',\n    'dadublock_car_get_digital',\n    'dadublock_car_toggle_led',\n    'dadublock_car_digital_pwm',\n    'dadublock_car_set_servo',\n    'dadublock_car_set_tone',\n    'dadublock_car_motor_stop',\n    'dadublock_car_motor',\n    'dadublock_car_get_irsensor',\n];\nEntry.DaduBlock.getBlocks = function() {\n    return {\n        //region dadublock 다두블록\n        dadublock_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dadublock_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'dadublockget',\n            isNotFor: ['dadublock'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        dadublock_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'dadublock_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'dadublockget',\n            isNotFor: ['dadublock'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var result = ANALOG[port] || 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n        },\n        dadublock_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['2', '3'],\n                type: 'dadublock_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'dadublockget',\n            isNotFor: ['dadublock'],\n            func: function(sprite, script) {\n                var port1 = script.getField('PORT1', script);\n                var port2 = script.getField('PORT2', script);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.DaduBlock.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n        dadublock_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dadublock_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'dadublockget',\n            isNotFor: ['dadublock'],\n            func: function(sprite, script) {\n                //var port = script.getNumberValue(\"PORT\", script);\n                var port = script.getField('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.DaduBlock.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n        },\n        dadublock_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', 'on'],\n                        ['끄기', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'dadublock_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dadublockset',\n            isNotFor: ['dadublock'],\n            func: function(sprite, script) {\n                //var port = script.getNumberValue(\"PORT\");\n                var port = script.getField('PORT');\n                var value = script.getField('VALUE');\n                if (value == 'on') {\n                    value = 255;\n                } else {\n                    value = 0;\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.DaduBlock.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        dadublock_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dadublock_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dadublockset',\n            isNotFor: ['dadublock'],\n            func: function(sprite, script) {\n                //var port = script.getNumberValue(\"PORT\");\n                var port = script.getField('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.DaduBlock.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Arduino.analogWrite(%1, %2)'] },\n        },\n        dadublock_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'dadublock_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dadublockset',\n            isNotFor: ['dadublock'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                //var port = script.getNumberValue(\"PORT\", script);\n                var port = script.getField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.DaduBlock.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Arduino.servomotorWrite(%1, %2)'] },\n        },\n        dadublock_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['무음', '0'],\n                        ['도', '1'],\n                        ['도#(레♭)', '2'],\n                        ['레', '3'],\n                        ['레#(미♭)', '4'],\n                        ['미', '5'],\n                        ['파', '6'],\n                        ['파#(솔♭)', '7'],\n                        ['솔', '8'],\n                        ['솔#(라♭)', '9'],\n                        ['라', '10'],\n                        ['라#(시♭)', '11'],\n                        ['시', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dadublock_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'dadublockset',\n            isNotFor: ['dadublock'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                //var port = script.getNumberValue(\"PORT\", script);\n                var port = script.getField('PORT', script);\n\n                if (!script.isStart) {\n                    var note = script.getNumberField('NOTE', script);\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (note === 0 || duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.DaduBlock.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberField('OCTAVE', script);\n                    var value = Entry.DaduBlock.toneMap[note][octave];\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq['SET'][port] = {\n                        type: Entry.DaduBlock.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.DaduBlock.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        dadublock_car_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dadublock_car_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'dadublock_car_get',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        dadublock_car_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'dadublock_car_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'dadublock_car_get',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var result = ANALOG[port] || 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n        },\n        dadublock_car_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['2', '3'],\n                type: 'dadublock_car_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'dadublock_car_get',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                var port1 = script.getField('PORT1', script);\n                var port2 = script.getField('PORT2', script);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.DaduBlock.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n        dadublock_car_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dadublock_car_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'dadublock_car_get',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                //var port = script.getNumberValue(\"PORT\", script);\n                var port = script.getField('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.DaduBlock.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n        },\n        dadublock_car_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', 'on'],\n                        ['끄기', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'dadublock_car_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dadublock_car_set',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                //var port = script.getNumberValue(\"PORT\");\n                var port = script.getField('PORT');\n                var value = script.getField('VALUE');\n                if (value == 'on') {\n                    value = 255;\n                } else {\n                    value = 0;\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.DaduBlock.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        dadublock_car_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dadublock_car_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dadublock_car_set',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                //var port = script.getNumberValue(\"PORT\");\n                var port = script.getField('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.DaduBlock.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Arduino.analogWrite(%1, %2)'] },\n        },\n        dadublock_car_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'dadublock_car_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dadublock_car_set',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                //var port = script.getNumberValue(\"PORT\", script);\n                var port = script.getField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.DaduBlock.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Arduino.servomotorWrite(%1, %2)'] },\n        },\n        dadublock_car_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['무음', '0'],\n                        ['도', '1'],\n                        ['도#(레♭)', '2'],\n                        ['레', '3'],\n                        ['레#(미♭)', '4'],\n                        ['미', '5'],\n                        ['파', '6'],\n                        ['파#(솔♭)', '7'],\n                        ['솔', '8'],\n                        ['솔#(라♭)', '9'],\n                        ['라', '10'],\n                        ['라#(시♭)', '11'],\n                        ['시', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dadublock_car_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'dadublock_car_set',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                //var port = script.getNumberValue(\"PORT\", script);\n                var port = script.getField('PORT', script);\n\n                if (!script.isStart) {\n                    var note = script.getNumberField('NOTE', script);\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (note === 0 || duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.DaduBlock.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberField('OCTAVE', script);\n                    var value = Entry.DaduBlock.toneMap[note][octave];\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq['SET'][port] = {\n                        type: Entry.DaduBlock.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.DaduBlock.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        dadublock_car_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['~5,~6', '1'],\n                        ['~9,~10', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dadublock_car_motor_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'dadublock_car_motor',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                if (port == 1) {\n                    //~5,~6번을 선택했을때\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][5] = {\n                        type: Entry.DaduBlock.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][6] = {\n                        type: Entry.DaduBlock.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                } else if (port == 2) {\n                    //~9,~10번을 선택했을때\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][9] = {\n                        type: Entry.DaduBlock.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][10] = {\n                        type: Entry.DaduBlock.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n            },\n        },\n        dadublock_car_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['~5,~6', '1'],\n                        ['~9,~10', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['정방향', '1'],\n                        ['역방향', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'], // %로 바꿈 0~100% 모터 속도\n                    },\n                    null,\n                ],\n                type: 'dadublock_car_motor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n            },\n            class: 'dadublock_car_motor',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var direction = script.getField('DIRECTION');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n                value = value * 1.5; //최대값을 150으로 제한\n                if (port == 1) {\n                    //~5,~6번을 선택했을때\n                    if (direction == 1) {\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][5] = {\n                            type: Entry.DaduBlock.sensorTypes.PWM,\n                            data: value,\n                            time: new Date().getTime(),\n                        };\n\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][6] = {\n                            type: Entry.DaduBlock.sensorTypes.PWM,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    } else if (direction == 2) {\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][5] = {\n                            type: Entry.DaduBlock.sensorTypes.PWM,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][6] = {\n                            type: Entry.DaduBlock.sensorTypes.PWM,\n                            data: value,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                } else if (port == 2) {\n                    //~9,~10번을 선택했을때\n                    if (direction == 1) {\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][9] = {\n                            type: Entry.DaduBlock.sensorTypes.PWM,\n                            data: value,\n                            time: new Date().getTime(),\n                        };\n\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][10] = {\n                            type: Entry.DaduBlock.sensorTypes.PWM,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    } else if (direction == 2) {\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][9] = {\n                            type: Entry.DaduBlock.sensorTypes.PWM,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][10] = {\n                            type: Entry.DaduBlock.sensorTypes.PWM,\n                            data: value,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                }\n            },\n        },\n        dadublock_car_get_irsensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['14', '14'],\n                        ['15', '15'],\n                        ['16', '16'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dadublock_car_get_irsensor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'dadublock_car_motor',\n            isNotFor: ['dadublock_car'],\n            func: function(sprite, script) {\n                //var port = script.getNumberValue(\"PORT\", script);\n                var port = script.getField('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.DaduBlock.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n        },\n        //endregion dadublock 다두블록\n    };\n};\n\nmodule.exports = [Entry.DaduBlock, Entry.DaduBlock_Car];\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_dalgona.js",
    "content": "'use strict';\n\nEntry.Dalgona = {\n    id: '54.1',\n    name: 'Dalgona',\n    url: 'https://dalgonaedu.co.kr/',\n    imageName: 'dalgona.png',\n    title: {\n        ko: '달고나.에듀 Plus',\n        en: 'Dalgona.Edu Plus',\n    },\n    Static: {\n        BUTTON_PRESS_VALUE: 0,\n    },\n\n    //정지시 초기화 함수\n    setZero: function () {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                if (Entry.hw.sendQueue.SET[key].type == Entry.Dalgona.sensorTypes.SERVO) {\n                    Entry.hw.sendQueue.SET[key].data = 200;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else if (Entry.hw.sendQueue.SET[key].type == Entry.Dalgona.sensorTypes.SERVO2) {\n                    Entry.hw.sendQueue.SET[key].data.value1 = 200;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else {\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        READ_BLUETOOTH: 9,\n        WRITE_BLUETOOTH: 10,\n        LCD: 11,\n        LCDCLEAR: 12,\n        RGBLED: 13,\n        DCMOTOR: 14,\n        OLED: 15,\n        PIR: 16,\n        LCDINIT: 17,\n        DHTHUMI: 18,\n        DHTTEMP: 19,\n        NEOPIXELINIT: 20,\n        NEOPIXELBRIGHT: 21,\n        NEOPIXEL: 22,\n        NEOPIXELALL: 23,\n        NEOPIXELCLEAR: 24,\n        DOTMATRIXINIT: 25,\n        DOTMATRIXBRIGHT: 26,\n        DOTMATRIX: 27,\n        DOTMATRIXEMOJI: 28,\n        DOTMATRIXCLEAR: 29,\n        MP3INIT: 30,\n        MP3PLAY1: 31,\n        MP3PLAY2: 32,\n        MP3VOL: 33,\n        RESET_: 34,\n        LOADINIT: 35,\n        LOADSCALE: 36,\n        LOADVALUE: 37,\n        DUST: 38,\n        JOYINIT: 39,\n        JOYX: 40,\n        JOYY: 41,\n        JOYZ: 42,\n        JOYMOVE: 43,\n        RFIDINIT: 44,\n        RFIDTAP: 45,\n        RFIDVALUE: 46,\n        STEPINIT: 47,\n        STEPSPEED: 48,\n        STEPROTATE: 49,\n        STEPROTATE2: 50,\n        STEPROTATE3: 51,\n        MLXOBJ: 52,\n        MLXAMB: 53,\n        SERVO2: 54,\n        GYROX: 55,\n        GYROY: 56,\n        GYROZ: 57,\n        PULLUP: 58,\n        TONETOGGLE: 59,\n        TEST_ULTRASONIC_TRIG: 60,\n        TEST_ULTRASONIC_ECHO: 61,\n    },\n    toneTable: {\n        0: 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        4: [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        5: [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        6: [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    direction: {\n        CENTER: 0,\n        UP: 1,\n        LEFT: 2,\n        RIGHT: 3,\n        DOWN: 4,\n        LEFT_UP: 5,\n        LEFT_DOWN: 6,\n        RIGHT_UP: 7,\n        RIGHT_DOWN: 8,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    getOffsetX(str) {\n        return this.getByteLength(str) * 1.5 - 5;\n    },\n    getByteLength(s, b, i, c) {\n        for (b = i = 0; (c = s.charCodeAt(i++)); b += c >> 11 ? 3 : c >> 7 ? 2 : 1);\n        return b;\n    },\n    BlockState: {},\n};\nEntry.Dalgona.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                dalgona_digital_title: '달고나 디지털 블럭',\n                dalgona_analog_title: '달고나 아날로그 블럭',\n                dalgona_pwm_title: '달고나 PWM 블럭',\n                dalgona_library_title: '달고나 라이브러리 블럭',\n                dalgona_neopixel_title: '달고나 네오픽셀 블럭',\n                dalgona_ultrasonic_title: '달고나 초음파센서 블럭',\n                dalgona_buzzer_title: '달고나 피에조 부저 블럭',\n                dalgona_dotmatrix_title: '달고나 8X8 도트매트릭스 블럭',\n                dalgona_rfid_title: '달고나 RFID 블럭',\n                dalgona_motor_title: '달고나 모터 블럭',\n                dalgona_stepmotor_title: '달고나 스텝모터 블럭',\n                dalgona_joystick_title: '달고나 조이스틱 블럭',\n                dalgona_LCD_title: '달고나 LCD 블럭',\n                dalgona_mp3_title: '달고나 mp3 블럭',\n                dalgona_HX711_title: '달고나 HX711 로드셀 블럭',\n                dalgona_sensor_title: '달고나 센서 블럭',\n                dalgona_toggle_on: '켜기',\n                dalgona_toggle_off: '끄기',\n                dalgona_lcd_first_line: '첫 번째',\n                dalgona_lcd_seconds_line: '두 번째',\n                dalgona_get_analog_value: '아날로그 %1 핀 읽기',\n                dalgona_get_light_value: '조도센서(AO %1)값',\n                dalgona_get_moisture_value: '토양수분센서(AO %1)값',\n                dalgona_get_sound_value: '사운드센서(AO %1)값',\n                dalgona_get_infrared_value: '적외선센서(AO %1)값',\n                dalgona_get_pullup: '풀업 저항 사용 버튼 %1 핀 눌림 상태',\n                dalgona_get_button: '버튼 %1 핀 눌림 상태',\n                dalgona_get_analog_mapping:\n                    '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n                dalgona_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                dalgona_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                dalgona_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n                test_dalgona_set_ultrasonic_trig: '초음파 Trig %1 신호 보내기 %2',\n                test_dalgona_get_ultrasonic_echo: '초음파 Echo %1 신호 받기',\n                dalgona_get_digital: '디지털 %1 핀 읽기',\n                dalgona_get_digital_toggle: '디지털 %1 핀 센서 값',\n                dalgona_get_digital_pir: 'PIR %1 핀 센서 값',\n                dalgona_set_digital_toggle: '디지털 %1 핀 %2 %3',\n                dalgona_set_led_toggle: 'LED %1 핀 %2 %3',\n                dalgona_set_digital_pwm: 'LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3',\n                dalgona_set_digital_rgbled:\n                    'RGB LED (R %1 핀, G %2 핀, B %3 핀) 색 (R: %4, G: %5, B: %6) 출력 %7',\n                dalgona_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                dalgona_set_digital_servo2: '서보 모터 %1 핀 %2 ~ %3 각도로 %4 초 동안 회전 %5',\n                dalgona_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                dalgona_set_digital_buzzer_volume:\n                    '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                dalgona_set_digital_buzzer: '피에조부저 %1 핀 %2 %3 음 %4 박자 연주 %5',\n                dalgona_set_digital_dcmotor: 'DC모터 %1핀 %2 %3',\n                dalgona_set_analog_dcmotor: 'DC모터(PWM %1 핀) 세기 %2 출력 (0 ~ 255) %3',\n                dalgona_set_neopixel_init:\n                    '네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\n                dalgona_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\n                dalgona_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\n                dalgona_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\n                dalgona_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\n                dalgona_set_dotmatrix_init:\n                    '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                dalgona_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                dalgona_set_dotmatrix: '도트매트릭스 LED %1 그리기 %2',\n                dalgona_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                dalgona_set_dotmatrix_clear: '도트매트릭스 LED 지우기 %1',\n                dalgona_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n                dalgona_get_lcd_row: '%1',\n                dalgona_get_lcd_col: '%1',\n                dalgona_module_digital_lcd: 'LCD화면 %1 열 %2 행 부터 %3 출력 %4',\n                dalgona_lcd_clear: 'LCD 화면 지우기 %1',\n                dalgona_get_dht: 'DHT11 온습도센서(out %1)의 %2값',\n                dalgona_dht_temp: '온도(°C)',\n                dalgona_dht_humi: '습도(%)',\n\n                dalgona_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\n                dalgona_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\n                dalgona_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\n                dalgona_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\n                dalgona_get_analog_temp_value: 'DHT11 포트 %1의 %2 센서 값',\n\n                dalgona_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3',\n                dalgona_load_scale: 'HX711 로드셀 보정하기 %1 %2',\n                dalgona_load_value: 'HX711 로드셀 값',\n\n                dalgona_get_dust: '미세먼지센서 (LED %1, AO %2) 값',\n\n                dalgona_rfid_init: 'RFID 시작하기 설정 (SS %1, RST %2) %3',\n                dalgona_is_rfid_tapped: 'RFID 카드가 인식되었는가?',\n                dalgona_get_rfid_value: 'RFID 카드 값',\n                dalgona_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5',\n                dalgona_get_joy_x: '%1 조이스틱 X값',\n                dalgona_get_joy_y: '%1 조이스틱 y값',\n                dalgona_get_joy_z: '%1 조이스틱 버튼 눌림 상태',\n                dalgona_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때',\n\n                dalgona_joy_direction_centor: '가운데',\n                dalgona_joy_direction_up: '위',\n                dalgona_joy_direction_down: '아래',\n                dalgona_joy_direction_left: '왼쪽',\n                dalgona_joy_direction_right: '오른쪽',\n                dalgona_joy_direction_top_left: '왼쪽위',\n                dalgona_joy_direction_bottom_left: '왼쪽아래',\n                dalgona_joy_direction_top_right: '오른쪽위',\n                dalgona_joy_direction_bottom_right: '오른쪽아래',\n\n                dalgona_joy_first: '첫번째',\n                dalgona_joy_second: '두번째',\n\n                dalgona_get_mlx: 'mlx90614 비접촉 온도센서 %1값',\n\n                dalgona_step_motor_first: '첫번째',\n                dalgona_step_motor_second: '두번째',\n                dalgona_step_motor_third: '세번째',\n\n                dalgona_step_motor_forward_direction: '정방향',\n                dalgona_step_motor_reverse_direction: '역방향',\n\n                dalgona_step_init: '%1 스텝모터 시작하기 설정 (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6',\n                dalgona_step_speed: '%1 스텝모터 속도를 %2 로 설정하기 (0 ~ 20) %3',\n                dalgona_step_rotate: '%1 스텝모터 %2 으로 %3 바퀴 회전하기 %4',\n                dalgona_step_rotate2: '%1 스텝모터 %2 으로 %3 도 회전하기 %4',\n                dalgona_step_rotate3: '%1 스텝모터 %2 으로 %3 초 동안 회전하기 %4',\n            },\n        },\n        en: {\n            template: {\n                // set_neopixelinit: '디지털 %1 번 핀에 연결된 %2 개의 네오픽셀 LED 사용하기 %3',\n                // set_neopixel: '디지털 %1 번 핀에 연결된 %2 번째 네오픽셀 LED를 R: %3 , G: %4 , B: %5 색으로 켜기 %6',\n\n                // dalgona_digital_title:'달고나 디지털 블럭',\n                // dalgona_analog_title:'달고나 아날로그 블럭',\n                // dalgona_pwm_title:'달고나 PWM 블럭',\n                // dalgona_library_title:'달고나 라이브러리 블럭',\n                // dalgona_neopixel_title:'달고나 네오픽셀 블럭',\n                // dalgona_ultrasonic_title: '달고나 초음파센서 블럭',\n                // dalgona_buzzer_title: '달고나 피에조 부저 블럭',\n                // dalgona_dotmatrix_title:'달고나 8X8 도트매트릭스 블럭',\n                // dalgona_rfid_title:'달고나 RFID 블럭',\n                // dalgona_motor_title:'달고나 모터 블럭',\n                // dalgona_stepmotor_title:'달고나 스텝모터 블럭',\n                // dalgona_joystick_title:'달고나 조이스틱 블럭',\n                // dalgona_LCD_title:'달고나 LCD 블럭',\n                // dalgona_mp3_title:'달고나 mp3 블럭',\n                // dalgona_HX711_title:'달고나 HX711 로드셀 블럭',\n                // dalgona_sensor_title:'달고나 센서 블럭',\n\n                // dalgona_toggle_on: 'on',\n                // dalgona_toggle_off: 'off',\n                // dalgona_lcd_first_line: 'first',\n                // dalgona_lcd_seconds_line: 'seconds',\n                // dalgona_get_analog_value: 'Read analog %1 pin sensor value',\n                // dalgona_get_analog_mapping: 'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\n                // dalgona_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                // dalgona_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                // dalgona_get_digital_bluetooth: 'Bluetooth RX 2 value',\n                // dalgona_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n                // dalgona_get_digital: 'Digital %1 pin sensor value',\n                // dalgona_get_digital_toggle: 'Digital %1 pin sensor value',\n                // dalgona_set_digital_toggle: 'Digital %1 pin %2 %3',\n                // dalgona_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n                // dalgona_set_digital_rgbled: 'Digital %1 pin RGB LED Red %2 Green %3 Blue %4 %5',\n                // dalgona_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                // dalgona_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                // dalgona_set_digital_buzzer_volume: '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                // dalgona_set_digital_buzzer:'피에조부저 %1 번 핀의 버저를 %2 %3 음으로 %4 박자 연주 %5',\n                // dalgona_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5',\n                // dalgona_set_neopixel_init:'네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\n                // dalgona_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\n                // dalgona_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\n                // dalgona_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\n                // dalgona_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\n                // dalgona_set_dotmatrix_init: '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                // dalgona_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                // dalgona_set_dotmatrix: '도트매트릭스 LED 그리기 %1 %2',\n                // dalgona_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                // dalgona_module_digital_lcd: 'LCD %1 열 %2 행 부터 %3 출력',\n                // dalgona_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n\n                // dalgona_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\n                // dalgona_module_digital_oled: 'OLED X codinate %1 Y coodinate %2 appear %3 %4',\n                // dalgona_get_dht_temp_value: '온습도센서의 온도값',\n                // dalgona_get_dht_humi_value: '온습도센서의 습도값',\n\n                // dalgona_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\n                // dalgona_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\n                // dalgona_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\n                // dalgona_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\n\n                // dalgona_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3',\n                // dalgona_load_scale: 'HX711 로드셀 보정하기 %1 %2',\n                // dalgona_load_value: 'HX711 로드셀 값',\n\n                // dalgona_get_dust: '미세먼지센서(LED %1, AO %2) 값(μg/m³)',\n\n                // dalgona_rfid_init: 'RFID 시작하기 설정 (RST %1, SS %2) %3',\n                // dalgona_is_rfid_tapped: 'RFID 카드가 인식되었는가?',\n                // dalgona_get_rfid_value: 'RFID 카드 값',\n\n                // dalgona_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5',\n                // dalgona_get_joy_x: '%1 조이스틱 X값',\n                // dalgona_get_joy_y: '%1 조이스틱 y값',\n                // dalgona_get_joy_z: '%1 조이스틱 버튼 눌림 상태',\n                // dalgona_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때',\n\n                // dalgona_step_init: '%1 스텝모터 시작하기 설정 (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6',\n                // dalgona_step_speed: '%1 스텝모터 속도를 %2 로 설정하기 (0 ~ 20) %3',\n                // dalgona_step_rotate: '%1 스텝모터 %2 으로 %3 바퀴 회전하기 %4',\n                // dalgona_step_rotate2: '%1 스텝모터 %2 으로 %3 도 회전하기 %4',\n                // dalgona_step_rotate3: '%1 스텝모터 %2 으로 %3 초 동안 회전하기 %4',\n\n                // dalgona_mlx: 'mlx90614 값',\n\n                dalgona_digital_title: 'Dalgona Digital Block',\n                dalgona_analog_title: 'Dalgona Analog Block',\n                dalgona_pwm_title: 'Dalgona PWM block',\n                dalgona_library_title: 'Dalgona Library block',\n                dalgona_neopixel_title: 'Dalgona Neopixel block',\n                dalgona_ultrasonic_title: 'Dalgona Ultrasonic_Sensor block',\n                dalgona_buzzer_title: 'Dalgona Buzzer block',\n                dalgona_dotmatrix_title: 'Dalgona 8X8 Dotmatrix block',\n                dalgona_rfid_title: 'Dalgona RFID block',\n                dalgona_motor_title: 'Dalgona Motor block',\n                dalgona_stepmotor_title: 'Dalgona Step_Motor block',\n                dalgona_joystick_title: 'Dalgona Joystick block',\n                dalgona_LCD_title: 'Dalgona LCD block',\n                dalgona_mp3_title: 'Dalgona mp3 block',\n                dalgona_HX711_title: 'Dalgona HX711 Load_cell block',\n                dalgona_sensor_title: 'Dalgona Sensor block',\n                dalgona_toggle_on: 'on',\n                dalgona_toggle_off: 'off',\n                dalgona_lcd_first_line: 'first',\n                dalgona_lcd_seconds_line: 'seconds',\n                dalgona_get_analog_value: 'Read analog %1 pin sensor value',\n                dalgona_get_light_value: 'Photoresistor (AO %1) sensor value',\n                dalgona_get_moisture_value: 'Soil moisture (AO %1) sensor value',\n                dalgona_get_sound_value: 'Sound (AO %1) sensor value',\n                dalgona_get_infrared_value: 'Infrared (AO %1) sensor value',\n                dalgona_get_pullup: 'Pullup resistor Button %1 pin pressed state',\n                dalgona_get_button: 'Button %1 pin pressed state',\n                dalgona_get_analog_mapping:\n                    'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\n                dalgona_mapping1: 'Value %1 limited to between %2 and %3',\n                dalgona_mapping2: 'Convert value %1 from range %2 to %3 to range %4 to %5',\n                dalgona_get_digital_ultrasonic: 'Ultrasonic Trig pin %1 Echo pin %2 sensor value',\n                dalgona_get_digital: 'Read digital %1 pin value',\n                dalgona_get_digital_toggle: 'Read digital %1 pin sensor value',\n                dalgona_get_digital_pir: 'PIR %1 pin sensor value',\n                dalgona_set_digital_toggle: 'Digital %1 pin %2 %3',\n                dalgona_set_led_toggle: 'LED %1 pin %2 %3',\n                dalgona_set_digital_pwm: 'LED (PWM %1 pin) brightness %2 output (0 ~ 255) %3',\n                dalgona_set_digital_rgbled:\n                    'RGB LED (R %1 pin, G %2 pin, B %3 pin) color (R: %4, G: %5, B: %6) output %7',\n                dalgona_set_digital_servo: 'Servo motor pin %1 rotate by %2 degrees %3',\n                dalgona_set_digital_servo2:\n                    'Servo motor pin %1 rotates at angle %2 to %3 for %4 seconds %5',\n                dalgona_set_digital_buzzer_toggle: 'Piezo buzzer %1 pin %2 %3',\n                dalgona_set_digital_buzzer_volume:\n                    'Piezo buzzer (PWM %1 pin) volume %2 output (0 ~ 255) %3',\n                dalgona_set_digital_buzzer: 'Piezo buzzer %1 pin %2 %3 note %4 beat %5',\n                dalgona_set_digital_dcmotor: 'DC motor %1pin %2 %3',\n                dalgona_set_analog_dcmotor: 'DC motor(PWM %1 pin) intensity %2 output (0 ~ 255) %3',\n                dalgona_set_neopixel_init: 'Neopixel LED pin settings (%1 pin connects %2 LEDs) %3',\n                dalgona_set_neopixel_bright:\n                    'Neopixel LED (pin %1) brightness set to %2 (0 ~ 255) %3',\n                dalgona_set_neopixel: 'Neopixel LED (pin %1) %2th LED color %3 output %4',\n                dalgona_set_neopixel_all: 'Neopixel LED (pin %1) All LED colors %2 output %3',\n                dalgona_set_neopixel_clear: 'Neopixel LED (pin %1) Turn off all LEDs %2',\n                dalgona_set_dotmatrix_init:\n                    '8x8 Dot Matrix starting settings (DIN %1, CLK %2, CS %3) %4',\n                dalgona_set_dotmatrix_bright: 'Dot Matrix set bright to %1 (0 ~ 8) %2',\n                dalgona_set_dotmatrix: 'Dot Matrix LED %1 turn on %2',\n                dalgona_set_dotmatrix_emoji: 'Dot Matrix LED %1 turn on emoji %2',\n                dalgona_set_dotmatrix_clear: 'Dot Matrix LED cleat %1',\n                dalgona_lcd_init: 'I2C LCD starting settings (address %1, column %2, row %3) %4',\n                dalgona_get_lcd_row: '%1',\n                dalgona_get_lcd_col: '%1',\n                dalgona_module_digital_lcd: 'LCD screen %1 column %2 row %3 output %4',\n                dalgona_lcd_clear: 'LCD screen clear %1',\n                dalgona_get_dht: 'DHT11 temperature and humidity sensor (out pin %1) %2 value',\n                dalgona_dht_temp: 'temperature(°C)',\n                dalgona_dht_humi: 'humidity(%)',\n                dalgona_set_mp3_init: 'Mp3 init ( tx: %1, rx: %2 ) %3',\n                dalgona_set_mp3_play: 'Play MP3 file %1 %2',\n                dalgona_set_mp3_play2: 'mp3 file %1 played for %2 seconds %3',\n                dalgona_set_mp3_vol: 'Set mp3 volume %1 (0 ~ 30) %2',\n                dalgona_get_analog_temp_value: 'DHT11 포트 %1의 %2 센서 값',\n\n                dalgona_load_init: 'HX711 Load Cell Startup Settings (DOUT %1, SCK %2) %3',\n                dalgona_load_scale: 'Calibrating the HX711 Load Cell %1 %2',\n                dalgona_load_value: 'HX711 load cell value',\n\n                dalgona_get_dust: 'Fine dust sensor (LED %1, AO %2) value',\n\n                dalgona_rfid_init: 'RFID pin settings (SS %1, RST %2) %3',\n                dalgona_is_rfid_tapped: 'Was the RFID card recognized?',\n                dalgona_get_rfid_value: 'RFID card value',\n                dalgona_joy_init: '%1 Joystick startup settings (X AO %2, Y AO %3, Z %4) %5',\n                dalgona_get_joy_x: '%1 joystick x value',\n                dalgona_get_joy_y: '%1 joystick y value',\n                dalgona_get_joy_z: '%1 Joystick button pressed state',\n                dalgona_get_joy_move: 'When the %1 joystick moves in the %2 direction',\n\n                dalgona_joy_direction_centor: 'center',\n                dalgona_joy_direction_up: 'up',\n                dalgona_joy_direction_down: 'down',\n                dalgona_joy_direction_left: 'left',\n                dalgona_joy_direction_right: 'right',\n                dalgona_joy_direction_top_left: 'top left',\n                dalgona_joy_direction_bottom_left: 'bottom left',\n                dalgona_joy_direction_top_right: 'top right',\n                dalgona_joy_direction_bottom_right: 'bottom right',\n\n                dalgona_joy_first: 'First',\n                dalgona_joy_second: 'Second',\n\n                dalgona_get_mlx: 'mlx90614 비접촉 온도센서 %1값',\n\n                dalgona_step_motor_first: 'First',\n                dalgona_step_motor_second: 'Second',\n                dalgona_step_motor_third: 'Third',\n\n                dalgona_step_motor_forward_direction: 'forward direction',\n                dalgona_step_motor_reverse_direction: 'reverse direction',\n\n                dalgona_step_init:\n                    '%1 Stepper motor starting settings (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6',\n                dalgona_step_speed: '%1 Set step motor speed to %2 (0 ~ 20) %3',\n                dalgona_step_rotate: 'Rotate the %1 step motor %2 %3 turn %4',\n                dalgona_step_rotate2: 'Rotate %1 step motor %2 to rotate %3 degrees %4',\n                dalgona_step_rotate3: 'Rotate %1 step motor in %2 for %3 seconds %4',\n            },\n        },\n    };\n};\nEntry.Dalgona.blockMenuBlocks = [\n    // 'FND_event',\n    // 'FND_Control_diplay_brightness',\n    // 'FND_Control_display_onoff',\n    // 'FND_Control_diplay_char',\n\n    'dalgona_digital_title',\n    'dalgona_set_digital_toggle',\n    'dalgona_get_digital',\n    'dalgona_set_led_toggle',\n\n    'dalgona_analog_title',\n    'dalgona_get_analog_value',\n    'dalgona_get_analog_mapping',\n    'dalgona_mapping1',\n    'dalgona_mapping2',\n\n    'dalgona_pwm_title',\n    'dalgona_set_digital_pwm',\n    'dalgona_set_digital_rgbled',\n\n    'dalgona_library_title',\n\n    'dalgona_neopixel_title',\n    'dalgona_set_neopixel_init',\n    'dalgona_set_neopixel_bright',\n    'dalgona_set_neopixel',\n    'dalgona_set_neopixel_all',\n    'dalgona_set_neopixel_clear',\n\n    'dalgona_ultrasonic_title',\n    'dalgona_get_digital_ultrasonic',\n    // 'test_dalgona_set_ultrasonic_trig',\n    // 'test_dalgona_get_ultrasonic_echo',\n\n    'dalgona_buzzer_title',\n    'dalgona_set_digital_buzzer_toggle',\n    'dalgona_set_digital_buzzer_volume',\n    'dalgona_set_digital_buzzer',\n\n    'dalgona_dotmatrix_title',\n    'dalgona_set_dotmatrix_init',\n    'dalgona_set_dotmatrix_bright',\n    'dalgona_set_dotmatrix',\n    'dalgona_set_dotmatrix_emoji',\n    'dalgona_set_dotmatrix_clear',\n\n    'dalgona_rfid_title',\n    'dalgona_rfid_init',\n    'dalgona_is_rfid_tapped',\n    'dalgona_get_rfid_value',\n\n    'dalgona_motor_title',\n    'dalgona_set_digital_dcmotor',\n    'dalgona_set_analog_dcmotor',\n    'dalgona_set_digital_servo',\n    'dalgona_set_digital_servo2',\n\n    'dalgona_stepmotor_title',\n    'dalgona_step_init',\n    'dalgona_step_speed',\n    'dalgona_step_rotate',\n    'dalgona_step_rotate2',\n    'dalgona_step_rotate3',\n\n    'dalgona_joystick_title',\n    'dalgona_joy_init',\n    'dalgona_get_joy_x',\n    'dalgona_get_joy_y',\n    'dalgona_get_joy_z',\n    'dalgona_get_joy_move',\n\n    'dalgona_LCD_title',\n    'dalgona_lcd_init',\n    'dalgona_module_digital_lcd',\n    'dalgona_get_lcd_row',\n    'dalgona_get_lcd_col',\n    'dalgona_lcd_clear',\n\n    'dalgona_mp3_title',\n    'dalgona_set_mp3_init',\n    'dalgona_set_mp3_vol',\n    'dalgona_set_mp3_play',\n    'dalgona_set_mp3_play2',\n\n    'dalgona_HX711_title',\n    'dalgona_load_init',\n    'dalgona_load_scale',\n    'dalgona_load_value',\n\n    'dalgona_sensor_title',\n\n    'dalgona_get_dust',\n    'dalgona_get_digital_toggle',\n    'dalgona_get_digital_pir',\n    'dalgona_get_light_value',\n    'dalgona_get_moisture_value',\n    'dalgona_get_sound_value',\n    'dalgona_get_infrared_value',\n    'dalgona_get_dht',\n    //'dalgona_get_dht_temp_value',\n    //'dalgona_get_dht_humi_value',\n    'dalgona_get_pullup',\n    'dalgona_get_button',\n    'dalgona_get_mlx',\n    // 'dalgona_get_digital_bluetooth',\n    // 'dalgona_module_digital_bluetooth',\n];\nEntry.Dalgona.getBlocks = function () {\n    var tx;\n    var din;\n    // var clk;\n    // var cs;\n    var dout;\n    var sck;\n    var joyx, joyy, joyz;\n    var joyx2, joyy2, joyz2;\n    var portpin1, portpin2, portpin3;\n    var ss;\n    var RGBport;\n    var mlxport;\n    var speed1 = 14;\n    var speed2 = 14;\n    var speed3 = 14;\n    var num = 0;\n\n    return {\n        // FND_Control_init: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     fontColor: '#fff',\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['1', 1]],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['5', 5]],\n        //             value: 5,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['4', 4]],\n        //             value: 4,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //     ],\n        //     def: { params: [], type: 'FND_Control_init' },\n        //     paramsKeyMap: { fnd_device: 0, CLK: 1, DIO: 2 },\n        //     class: 'other',\n        //     isNotFor: ['Dalgona'],\n        //     func(sprite, script) {\n        //         const device = script.getNumberValue('fnd_device', script);\n        //         const clk_val = script.getNumberValue('CLK', script);\n        //         const dio_val = script.getNumberValue('DIO', script);\n\n        //         // index number patched by Remoted 2020-11-20\n        //         if (!Entry.hw.sendQueue.SET) {\n        //             Entry.hw.sendQueue.SET = {};\n        //         }\n        //         // FND_Init type data protocol defined\n        //         Entry.hw.sendQueue.SET[device] = {\n        //             type: Entry.Dalgona.sensorTypes.FNDINIT,\n        //             data: {\n        //                 clk_pin: clk_val,\n        //                 dio_pin: dio_val,\n        //             },\n        //             time: new Date().getTime(),\n        //         };\n\n        //         return script.callReturn();\n        //     },\n        //     syntax: { js: [], py: ['RichShield_FND_init(%1, %2)'] },\n        // },\n        // FND_Control_diplay_brightness: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     fontColor: '#fff',\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['1', 1]],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [\n        //                 ['1', 1],\n        //                 ['2', 2],\n        //                 ['3', 3],\n        //                 ['4', 4],\n        //                 ['5', 5],\n        //                 ['6', 6],\n        //                 ['7', 7],\n        //             ],\n        //             value: 3,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //     ],\n        //     def: { params: [], type: 'FND_Control_diplay_brightness' },\n        //     paramsKeyMap: { fnd_device: 0, level: 1 },\n        //     class: 'other',\n        //     isNotFor: ['Dalgona'],\n        //     func(sprite, script) {\n        //         const device = script.getNumberValue('fnd_device', script);\n        //         const level_val = script.getNumberValue('level', script);\n\n        //         if (!script.isStart) {\n        //             // index number patched by Remoted 2020-11-20\n        //             if (!Entry.hw.sendQueue.SET) {\n        //                 Entry.hw.sendQueue.SET = {};\n        //             }\n\n        //             script.isStart = true;\n        //             script.timeFlag = 1;\n        //             const fps = Entry.FPS || 60;\n        //             const timeValue = (60 / fps) * 50;\n\n        //             // FND_Init type data protocol defined\n        //             Entry.hw.sendQueue.SET[device] = {\n        //                 type: Entry.Dalgona.sensorTypes.FNDINIT,\n        //                 data: {\n        //                     level_val,\n        //                     block_index: 1,\n        //                 },\n        //                 time: new Date().getTime(),\n        //             };\n        //             setTimeout(() => {\n        //                 script.timeFlag = 0;\n        //             }, timeValue);\n        //             return script;\n        //         } else if (script.timeFlag == 1) {\n        //             return script;\n        //         } else {\n        //             delete script.timeFlag;\n        //             delete script.isStart;\n        //             Entry.engine.isContinue = false;\n        //             return script.callReturn();\n        //         }\n        //     },\n        //     syntax: { js: [], py: ['RichShield_FND_Control_diplay_brightness(%1, %2)'] },\n        // },\n        // FND_Control_display_onoff: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     fontColor: '#fff',\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['1', 1]],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [\n        //                 [Lang.Blocks.RichShield_toggle_off, 0],\n        //                 [Lang.Blocks.RichShield_toggle_on, 1],\n        //             ],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //     ],\n        //     def: { params: [], type: 'FND_Control_display_onoff' },\n        //     paramsKeyMap: { fnd_device: 0, onoff: 1 },\n        //     class: 'other',\n        //     isNotFor: ['Dalgona'],\n        //     func(sprite, script) {\n        //         const device = script.getNumberValue('fnd_device', script);\n        //         const onoff = script.getNumberValue('onoff', script);\n\n        //         if (!script.isStart) {\n        //             // index number patched by Remoted 2020-11-20\n        //             if (!Entry.hw.sendQueue.SET) {\n        //                 Entry.hw.sendQueue.SET = {};\n        //             }\n\n        //             script.isStart = true;\n        //             script.timeFlag = 1;\n        //             const fps = Entry.FPS || 60;\n        //             const timeValue = (60 / fps) * 50;\n\n        //             // FND_Init type data protocol defined\n        //             Entry.hw.sendQueue.SET[device] = {\n        //                 type: Entry.Dalgona.sensorTypes.FNDINIT,\n        //                 data: {\n        //                     onoff,\n        //                     block_index: 2,\n        //                 },\n        //                 time: new Date().getTime(),\n        //             };\n\n        //             setTimeout(() => {\n        //                 script.timeFlag = 0;\n        //             }, timeValue);\n        //             return script;\n        //         } else if (script.timeFlag == 1) {\n        //             return script;\n        //         } else {\n        //             delete script.timeFlag;\n        //             delete script.isStart;\n        //             Entry.engine.isContinue = false;\n        //             return script.callReturn();\n        //         }\n\n        //     },\n        //     syntax: { js: [], py: ['RichShield_FND_Control_display_onoff(%1, %2)'] },\n        // },\n        // FND_Control_diplay_char: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     fontColor: '#fff',\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['1', 1]],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Block',\n        //             accept: 'string',\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [\n        //                 [Lang.Blocks.RichShield_toggle_off, 0],\n        //                 [Lang.Blocks.RichShield_toggle_on, 1],\n        //             ],\n        //             value: 0,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Block',\n        //             accept: 'string',\n        //         },\n        //     ],\n        //     events: {},\n        //     def: {\n        //         params: [\n        //             '1',\n        //             {\n        //                 type: 'number',\n        //                 params: ['1234'],\n        //             },\n        //             '0',\n        //             {\n        //                 type: 'number',\n        //                 params: ['0.1'],\n        //             },\n        //         ],\n        //         type: 'FND_Control_diplay_char',\n        //     },\n        //     events: {},\n        //     paramsKeyMap: { fnd_device: 0, display_value: 1, onoff: 2, delay_ms: 3 },\n        //     class: 'other',\n        //     isNotFor: ['Dalgona'],\n        //     func(sprite, script) {\n        //         const device = script.getNumberValue('fnd_device', script);\n        //         const display_str = script.getNumberValue('display_value', script);\n        //         const onoff = script.getNumberValue('onoff', script);\n        //         const delay_ms_sec = script.getNumberValue('delay_ms', script);\n        //         const splited_array = [];\n        //         let display_str_converted = 0;\n\n        //         if (!script.isStart) {\n        //             if (!Entry.hw.sendQueue.SET) {\n        //                 Entry.hw.sendQueue.SET = {};\n        //             }\n\n        //             display_str_converted = display_str.toString();\n\n        //             script.isStart = true;\n        //             script.timeFlag = 1;\n        //             const fps = Entry.FPS || 60;\n        //             const timeValue = (60 / fps) * 100;\n\n        //             for (let i = 0; i < display_str_converted.length; i++) {\n        //                 splited_array.push(parseInt(display_str_converted.charAt(i)));\n        //             }\n\n        //             console.log(`splited_array :${splited_array}`);\n\n        //             // FND_Init type data protocol defined\n        //             Entry.hw.sendQueue.SET[device] = {\n        //                 type: Entry.Dalgona.sensorTypes.FNDINIT,\n        //                 data: {\n        //                     display_str,\n        //                     onoff,\n        //                     block_index: 3,\n        //                     str_length: display_str_converted.length,\n        //                     data_0: splited_array[0],\n        //                     data_1: splited_array[1],\n        //                     data_2: splited_array[2],\n        //                     data_3: splited_array[3],\n        //                     delay_ms: delay_ms_sec,\n        //                 },\n        //                 time: new Date().getTime(),\n        //             };\n\n        //             setTimeout(() => {\n        //                 script.timeFlag = 0;\n        //             }, timeValue);\n        //             return script;\n        //         } else if (script.timeFlag == 1) {\n        //             return script;\n        //         } else {\n        //             delete script.timeFlag;\n        //             delete script.isStart;\n        //             Entry.engine.isContinue = false;\n        //             return script.callReturn();\n        //         }\n        //     },\n        //     syntax: { js: [], py: ['RichShield_FND_Control_diplay_char(%1, %2, %3, %4)'] },\n        // },\n        dalgona_digital_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_digital_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_digital_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_digital_title',\n            },\n            class: 'digital',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_analog_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_analog_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_analog_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_analog_title',\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_pwm_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_pwm_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_pwm_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_pwm_title',\n            },\n            class: 'pwm',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_library_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_library_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_library_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_library_title',\n            },\n            class: 'library',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_neopixel_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_neopixel_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_neopixel_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_neopixel_title',\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_ultrasonic_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_ultrasonic_title),\n                    offsetY: 7,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_ultrasonic_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_ultrasonic_title',\n            },\n            class: 'ultrasonic',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_buzzer_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_buzzer_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_buzzer_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_buzzer_title',\n            },\n            class: 'buzzer',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_dotmatrix_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_dotmatrix_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_dotmatrix_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_dotmatrix_title',\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_rfid_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_rfid_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_rfid_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_rfid_title',\n            },\n            class: 'RFID',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_motor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_motor_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_motor_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_motor_title',\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_stepmotor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_stepmotor_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_stepmotor_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_stepmotor_title',\n            },\n            class: 'step',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_joystick_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_joystick_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_joystick_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_joystick_title',\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_LCD_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_LCD_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_LCD_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_LCD_title',\n            },\n            class: 'LCD',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_mp3_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_mp3_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_mp3_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_mp3_title',\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_HX711_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_HX711_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_HX711_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_HX711_title',\n            },\n            class: 'HX711',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n        dalgona_sensor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_sensor_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_sensor_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_sensor_title',\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            events: {},\n        },\n\n        dalgona_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        dalgona_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function (sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        dalgona_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        dalgona_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function (sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        dalgona_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_toggle_on, 'on'],\n                        [Lang.template.dalgona_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function (sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        dalgona_list_digital_toggle_en: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['HIGH', 'on'],\n                        ['LOW', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function (sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        dalgona_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        dalgona_set_neopixel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_neopixel_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('NUM');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.NEOPIXELINIT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_set_neopixel_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_neopixel_bright',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('NUM');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.NEOPIXELBRIGHT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_set_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'dalgona_set_neopixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n                COLOR: 2,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                //var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var num = script.getNumberValue('NUM', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.NEOPIXEL,\n                        data: {\n                            num: num,\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_set_neopixel_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'dalgona_set_neopixel_all',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COLOR: 1,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.NEOPIXELALL,\n                        data: {\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_set_neopixel_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_neopixel_clear',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.NEOPIXELCLEAR,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_lcd_list_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x27', '0'],\n                        ['0x3F', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        dalgona_set_dotmatrix_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['12'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_dotmatrix_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                din = port1;\n                // clk = port2;\n                // cs = port3;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port1] = {\n                        type: Entry.Dalgona.sensorTypes.DOTMATRIXINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                            port3: port3,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_set_dotmatrix_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_dotmatrix_bright',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                num = Math.round(num);\n                num = Math.min(num, 8);\n                num = Math.max(num, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.Dalgona.sensorTypes.DOTMATRIXBRIGHT,\n                        data: num,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_set_dotmatrix_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'dalgona_set_dotmatrix_clear',\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (1 + 0.5) * 0.1; //0.15\n                    timeValue = (60 / fps) * timeValue * 100;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.Dalgona.sensorTypes.DOTMATRIXCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_set_dotmatrix: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['003c420024242400'],\n                    },\n                ],\n                type: 'dalgona_set_dotmatrix',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var text = script.getValue('STRING');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.Dalgona.sensorTypes.DOTMATRIX,\n                        data: {\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_dotmatrix_emoji_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['🖤', '1'],\n                        ['🤍', '2'],\n                        ['👆', '3'],\n                        ['👇', '4'],\n                        ['👈', '5'],\n                        ['👉', '6'],\n                        ['😊', '7'],\n                        ['😥', '8'],\n                        ['😡', '9'],\n                        ['😆', '10'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        dalgona_set_dotmatrix_emoji: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_dotmatrix_emoji_list',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_dotmatrix_emoji',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var value = script.getNumberValue('LIST');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.Dalgona.sensorTypes.DOTMATRIXEMOJI,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_lcd_first_line, '0'],\n                        [Lang.template.dalgona_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        dalgona_get_lcd_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'dalgona_get_lcd_row',\n                    },\n                ],\n            },\n        },\n\n        dalgona_get_lcd_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'dalgona_get_lcd_col',\n                    },\n                ],\n            },\n        },\n        dalgona_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.dalgona_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_analog_basic',\n                    },\n                ],\n                type: 'dalgona_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['Dalgona.get_analog_value(%1)'] },\n        },\n        dalgona_get_light_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_analog_basic',\n                    },\n                ],\n                type: 'dalgona_get_light_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['dalgona.get_analog_value(%1)'] },\n        },\n        dalgona_get_moisture_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //template: Lang.template.dalgona_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_analog_basic',\n                        params: ['1'],\n                    },\n                ],\n                type: 'dalgona_get_moisture_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['dalgona.get_analog_value(%1)'] },\n        },\n\n        dalgona_set_digital_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_set_digital_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                    },\n                    {\n                        type: 'dalgona_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_digital_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Dalgona.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Dalgona.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['dalgona.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        dalgona_set_analog_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_set_analog_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_pwm',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_analog_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['dalgona.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        dalgona_get_sound_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_analog_basic',\n                    },\n                ],\n                type: 'dalgona_get_sound_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['dalgona.get_analog_value(%1)'] },\n        },\n        dalgona_get_infrared_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_analog_basic',\n                    },\n                ],\n                type: 'dalgona_get_infrared_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['dalgona.get_analog_value(%1)'] },\n        },\n        dalgona_get_pullup: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_get_pullup',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                // var pu = Entry.hw.portData.PULLUP;\n                var pu = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                // Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.PULLUP] = {\n                //     port: port,\n                //     data: 2,\n                //     time: new Date().getTime(),\n                // };\n\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                var pullupvalue = pu ? pu[port] || 0 : 0;\n                return !pullupvalue;\n            },\n\n            syntax: { js: [], py: [] },\n        },\n        dalgona_get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_get_button',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = {\n                    port: port,\n                    data: 2,\n                    time: new Date().getTime(),\n                };\n\n                var value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                return !value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.dalgona_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_analog_basic',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'dalgona_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                result = ANALOG ? ANALOG[port] || 0 : 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['dalgona.get_analog_mapping(%1, %2, %3, %4, %5)'],\n            },\n        },\n        dalgona_mapping1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                ],\n                type: 'dalgona_mapping1',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                num = Math.min(value3, num);\n                num = Math.max(value2, num);\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_mapping2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1024'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'dalgona_mapping2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var flag = 0;\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var value4_1 = value4;\n                var value5_1 = value5;\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                if (value4 > value5) {\n                    flag = 1;\n                    var swap = value4;\n                    value4_1 = value5;\n                    value5_1 = swap;\n                }\n\n                num -= value2;\n                num = num * ((value5_1 - value4_1) / (value3 - value2));\n\n                if (flag == 1) {\n                    num = value4 - num;\n                    num = Math.min(value4, num);\n                    num = Math.max(value5, num);\n                } else {\n                    num = num + value4;\n                    num = Math.min(value5, num);\n                    num = Math.max(value4, num);\n                }\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_get_digital_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.dalgona_get_digital_ultrasonic,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                        params: ['13'],\n                    },\n                    {\n                        type: 'dalgona_list_digital_basic',\n                        params: ['12'],\n                    },\n                ],\n                type: 'dalgona_get_digital_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'ultrasonic',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                Entry.Utils.sleep(700);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC[port2] || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['dalgona.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n        test_dalgona_set_ultrasonic_trig: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.test_dalgona_set_ultrasonic_trig,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'test_dalgona_set_ultrasonic_trig',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ultrasonic',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.TEST_ULTRASONIC_TRIG,\n                    time: new Date().getTime(),\n                };\n                Entry.Utils.sleep(10);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        test_dalgona_get_ultrasonic_echo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.test_dalgona_get_ultrasonic_echo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'test_dalgona_get_ultrasonic_echo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ultrasonic',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.TEST_ULTRASONIC_ECHO] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                Entry.Utils.sleep(30);\n                return Entry.hw.portData.ULTRASONIC[port] || 0;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n\n        dalgona_get_dust: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'dalgona_list_analog_basic',\n                        params: ['0'],\n                    },\n                ],\n                type: 'dalgona_get_dust',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DUST] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.DUST || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['dalgona.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n        dalgona_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.dalgona_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'digital',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['dalgona.get_digital(%1)'] },\n        },\n        dalgona_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.dalgona_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['dalgona.get_digital_toggle(%1)'] },\n        },\n        dalgona_get_digital_pir: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.dalgona_get_digital_pir,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_get_digital_pir',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.PIR] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['dalgona.get_digital_pir(%1)'] },\n        },\n\n        dalgona_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                    },\n                    {\n                        type: 'dalgona_list_digital_toggle_en',\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'digital',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Dalgona.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Dalgona.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['dalgona.set_digital_toggle(%1, %2)'] },\n        },\n        dalgona_set_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                        params: ['13'],\n                    },\n                    {\n                        type: 'dalgona_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_led_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'digital',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Dalgona.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Dalgona.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['dalgona.set_digital_toggle(%1, %2)'] },\n        },\n        dalgona_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_pwm',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'pwm',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['dalgona.set_digital_pwm(%1, %2)'] },\n        },\n        dalgona_set_digital_rgbled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_set_digital_rgbled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_pwm',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'dalgona_list_digital_pwm',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'dalgona_list_digital_pwm',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_digital_rgbled',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n                VALUE1: 3,\n                VALUE2: 4,\n                VALUE3: 5,\n            },\n            class: 'pwm',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                RGBport = port1;\n\n                // if (!Entry.hw.sendQueue['SET']) {\n                //     Entry.hw.sendQueue['SET'] = {};\n                // }\n                // Entry.hw.sendQueue['SET'][RGBport] = {\n                //     type: Entry.Dalgona.sensorTypes.RGBLED,\n                //     data: {\n                //         port1: port1,\n                //         port2: port2,\n                //         port3: port3,\n                //         value1: value1,\n                //         value2: value2,\n                //         value3: value3,\n                //     },\n                //     time: new Date().getTime(),\n                // };\n                // return script.callReturn();\n\n                // if (!script.isStart) {\n                //     script.isStart = true;\n                //     script.timeFlag = 1;\n                //     var fps = Entry.FPS || 60;\n                //     var timeValue = (60 / fps) * 50;\n\n                //     value1 = Math.round(value1);\n                //     value1 = Math.min(value1, 255);\n                //     value1 = Math.max(value1, 0);\n                //     value2 = Math.round(value2);\n                //     value2 = Math.min(value2, 255);\n                //     value2 = Math.max(value2, 0);\n                //     value3 = Math.round(value3);\n                //     value3 = Math.min(value3, 255);\n                //     value3 = Math.max(value3, 0);\n\n                //     if (!Entry.hw.sendQueue['SET']) {\n                //         Entry.hw.sendQueue['SET'] = {};\n                //     }\n                //     Entry.hw.sendQueue['SET'][RGBport] = {\n                //         type: Entry.Dalgona.sensorTypes.RGBLED,\n                //         data: {\n                //             port1: port1,\n                //             port2: port2,\n                //             port3: port3,\n                //             value1: value1,\n                //             value2: value2,\n                //             value3: value3,\n                //         },\n                //         time: new Date().getTime(),\n                //     };\n                //     setTimeout(function() {\n                //         script.timeFlag = 0;\n                //     }, 10);\n                //     return script;\n                // } else if (script.timeFlag == 1) {\n                //     return script;\n                // } else {\n                //     delete script.timeFlag;\n                //     delete script.isStart;\n                //     Entry.engine.isContinue = false;\n                //     return script.callReturn();\n                // }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type: Entry.Dalgona.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type: Entry.Dalgona.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port3] = {\n                    type: Entry.Dalgona.sensorTypes.PWM,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        dalgona_set_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_set_digital_servo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['dalgona.set_digital_servo(%1, %2)'] },\n        },\n        dalgona_set_digital_servo2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_set_digital_servo2,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['180'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_digital_servo2',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n                STIME: 3,\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona'],\n            // func: function(sprite, script) {\n            //     var port = script.getNumberValue('PORT');\n            //     var value1 = script.getNumber    Value('VALUE1', script);\n            //     var value2 = script.getNumberValue('VALUE2', script);\n            //     var stime = script.getNumberValue('STIME', script);\n\n            //     value1 = Math.min(value1, 180);\n            //     value1 = Math.max(value1, 0);\n            //     value2 = Math.min(value2, 180);\n            //     value2 = Math.max(value2, 0);\n\n            //     if (!Entry.hw.sendQueue['SET']) {\n            //         Entry.hw.sendQueue['SET'] = {};\n            //     }\n\n            //     Entry.hw.sendQueue['SET'][port] = {\n            //         type: Entry.Dalgona.sensorTypes.SERVO2,\n            //         data: {\n            //             value1: value1,\n            //             value2: value2,\n            //             stime: stime,\n            //         },\n            //         time: new Date().getTime(),\n            //     };\n            //     return script.callReturn();\n            // },\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var stime = script.getNumberValue('STIME', script);\n\n                value1 = Math.min(value1, 180);\n                value1 = Math.max(value1, 0);\n                value2 = Math.min(value2, 180);\n                value2 = Math.max(value2, 0);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.SERVO2,\n                        data: {\n                            value1: value1,\n                            value2: value2,\n                            stime: stime,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        dalgona_set_digital_buzzer_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'dalgona_list_digital_toggle',\n                    },\n\n                    null,\n                ],\n                type: 'dalgona_set_digital_buzzer_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'buzzer',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Dalgona.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Dalgona.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.TONETOGGLE,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_set_digital_buzzer_volume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_pwm',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_digital_buzzer_volume',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'buzzer',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['dalgona.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        dalgona_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_digital_basic',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'dalgona_list_digital_tone',\n                    },\n                    {\n                        type: 'dalgona_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'buzzer',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.Dalgona.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.Dalgona.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.Dalgona.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['dalgona.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        dalgona_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_lcd_list_init',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_lcd_init',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n                COL: 1,\n                LINE: 2,\n            },\n            class: 'LCD',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var list = script.getNumberValue('LIST');\n                var col = script.getNumberValue('COL');\n                var line = script.getValue('LINE');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 0.1 * 1000;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.Dalgona.sensorTypes.LCDINIT,\n                        data: {\n                            list: list,\n                            col: col,\n                            line: line,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['dalgona.module_digital_lcd(%1, %2)'] },\n        },\n        dalgona_module_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_get_lcd_col',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'dalgona_get_lcd_row',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Hello, dalgona'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_module_digital_lcd',\n            },\n            paramsKeyMap: {\n                COL: 0,\n                ROW: 1,\n                STRING: 2,\n            },\n            class: 'LCD',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var row = script.getNumberValue('ROW');\n                var col = script.getNumberValue('COL');\n                var text = script.getValue('STRING');\n                text += ' ';\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.Dalgona.sensorTypes.LCD,\n                        data: {\n                            line: row,\n                            column: col,\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['dalgona.module_digital_lcd(%1, %2)'] },\n        },\n        dalgona_lcd_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'dalgona_lcd_clear',\n            },\n            class: 'LCD',\n            isNotFor: ['Dalgona'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.Dalgona.sensorTypes.LCDCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_get_dht: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_dht_temp, '0'],\n                        [Lang.template.dalgona_dht_humi, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'dalgona_get_dht',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DHT_SELECT: 1,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var type = script.getNumberValue('DHT_SELECT');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (type == 0) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DHTTEMP] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTTEMP || 0;\n                } else if (type == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DHTHUMI] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTHUMI || 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_set_mp3_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_mp3_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                tx = script.getNumberValue('PORT1');\n                var rx = script.getNumberValue('PORT2');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.Dalgona.sensorTypes.MP3INIT,\n                        data: {\n                            tx: tx,\n                            rx: rx,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_set_mp3_play: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_mp3_play',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                script.isStart = true;\n                script.timeFlag = 1;\n                var fps = Entry.FPS || 60;\n                var timeValue = (60 / fps) * 50;\n\n                Entry.hw.sendQueue['SET'][tx] = {\n                    type: Entry.Dalgona.sensorTypes.MP3PLAY1,\n                    data: {\n                        tx: tx,\n                        num: num,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_set_mp3_play2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_mp3_play2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                TIME: 1,\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM');\n                var time_value = script.getNumberValue('TIME');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    time_value = (60 / fps) * time_value * 1000;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.Dalgona.sensorTypes.MP3PLAY1,\n                        data: {\n                            tx: tx,\n                            num: num,\n                            //time_value: time_value,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, time_value);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.Dalgona.sensorTypes.MP3PLAY1,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_set_mp3_vol: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['15'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_set_mp3_vol',\n            },\n            paramsKeyMap: {\n                VOL: 0,\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var vol = script.getNumberValue('VOL');\n\n                vol = Math.round(vol);\n                vol = Math.min(vol, 30);\n                vol = Math.max(vol, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.Dalgona.sensorTypes.MP3VOL,\n                        data: {\n                            tx: tx,\n                            vol: vol,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_load_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_load_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'HX711',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                dout = port1;\n                sck = port2;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][sck] = {\n                        type: Entry.Dalgona.sensorTypes.LOADINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_load_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['-20000'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_load_scale',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'HX711',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][sck] = {\n                        type: Entry.Dalgona.sensorTypes.LOADSCALE,\n                        data: {\n                            num: num,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_load_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'dalgona_load_value',\n            },\n            paramsKeyMap: {},\n            class: 'HX711',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][sck];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.LOADVALUE] = {\n                    port: sck,\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.LOADVALUE || 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_list_joy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_joy_first, '1'],\n                        [Lang.template.dalgona_joy_second, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('NUM');\n            },\n        },\n\n        dalgona_joy_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_joy',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_list_analog_basic',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'dalgona_list_analog_basic',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_joy_init',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                PORT1: 1,\n                PORT2: 2,\n                PORT3: 3,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                if (num == 1) {\n                    joyx = port1;\n                    joyy = port2;\n                    joyz = port3;\n                } else if (num == 2) {\n                    joyx2 = port1;\n                    joyy2 = port2;\n                    joyz2 = port3;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][joyx] = {\n                            type: Entry.Dalgona.sensorTypes.JOYINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][joyx2] = {\n                            type: Entry.Dalgona.sensorTypes.JOYINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_get_joy_x: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'dalgona_get_joy_x',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var num = script.getNumberValue('NUM', script);\n                if (num == 1) {\n                    return ANALOG ? ANALOG[joyx] || 0 : 0;\n                } else if (num == 2) {\n                    return ANALOG ? ANALOG[joyx2] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_get_joy_y: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'dalgona_get_joy_y',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var num = script.getNumberValue('NUM', script);\n                if (num == 1) {\n                    return ANALOG ? ANALOG[joyy] || 0 : 0;\n                } else if (num == 2) {\n                    return ANALOG ? ANALOG[joyy2] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_get_joy_z: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'dalgona_get_joy_z',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                var num = script.getNumberValue('NUM', script);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (num == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = {\n                        port: joyz,\n                        data: 2,\n                        time: new Date().getTime(),\n                    };\n\n                    var value = DIGITAL ? DIGITAL[joyz] || 0 : 0;\n                    return !value;\n                } else if (num == 2) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = {\n                        port: joyz2,\n                        data: 2,\n                        time: new Date().getTime(),\n                    };\n\n                    var value = DIGITAL ? DIGITAL[joyz2] || 0 : 0;\n                    return !value;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_list_joy_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_joy_direction_centor, '0'],\n                        [Lang.template.dalgona_joy_direction_up, '1'],\n                        [Lang.template.dalgona_joy_direction_down, '4'],\n                        [Lang.template.dalgona_joy_direction_left, '2'],\n                        [Lang.template.dalgona_joy_direction_right, '3'],\n                        [Lang.template.dalgona_joy_direction_top_left, '5'],\n                        [Lang.template.dalgona_joy_direction_bottom_left, '6'],\n                        [Lang.template.dalgona_joy_direction_top_right, '7'],\n                        [Lang.template.dalgona_joy_direction_bottom_right, '8'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('DIR');\n            },\n        },\n        dalgona_get_joy_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_joy',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_list_joy_direction',\n                        params: ['0'],\n                    },\n                ],\n                type: 'dalgona_get_joy_move',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona'],\n            func(sprite, script) {\n                var direction = script.getNumberValue('DIR');\n                const ANALOG = Entry.hw.portData.ANALOG;\n                num = script.getNumberValue('NUM', script);\n\n                const getValue = function (w) {\n                    return ANALOG[w] <= 100 ? 0 : ANALOG[w] >= 930 ? 2 : 1;\n                };\n\n                var xpin;\n                var ypin;\n                if (num == 1) {\n                    xpin = joyx;\n                    ypin = joyy;\n                } else if (num == 2) {\n                    xpin = joyx2;\n                    ypin = joyy2;\n                }\n                if (\n                    direction == Entry.Dalgona.direction.CENTER &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona.direction.DOWN &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona.direction.LEFT &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona.direction.LEFT_DOWN &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona.direction.LEFT_UP &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona.direction.RIGHT &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona.direction.RIGHT_DOWN &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona.direction.RIGHT_UP &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona.direction.UP &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                }\n\n                return 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_list_step: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_step_motor_first, '1'],\n                        [Lang.template.dalgona_step_motor_second, '2'],\n                        [Lang.template.dalgona_step_motor_third, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('NUM');\n            },\n        },\n        dalgona_step_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_step_init',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                PORT1: 1,\n                PORT2: 2,\n                PORT3: 3,\n                PORT4: 4,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n                var port4 = script.getNumberValue('PORT4', script);\n\n                if (num == 1) {\n                    portpin1 = port1;\n                } else if (num == 2) {\n                    portpin2 = port1;\n                } else if (num == 3) {\n                    portpin3 = port1;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        console.log('STEP INIT 1st');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        console.log('STEP INIT 2nd');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        console.log('STEP INIT 3rd');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_step_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['14'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_step_speed',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                SPEED: 1,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var sp = script.getNumberValue('SPEED', script);\n\n                sp = Math.round(sp);\n                sp = Math.min(sp, 20);\n                sp = Math.max(sp, 0);\n\n                if (num == 1) {\n                    speed1 = sp;\n                } else if (num == 2) {\n                    speed2 = sp;\n                } else if (num == 3) {\n                    speed3 = sp;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed1,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed2,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_list_step_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_step_motor_forward_direction, '1'],\n                        [Lang.template.dalgona_step_motor_reverse_direction, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            func: function (sprite, script) {\n                return script.getField('DIR');\n            },\n        },\n        dalgona_step_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_step_rotate',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                VALUE: 2,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var dir = script.getNumberValue('DIR', script);\n                num = script.getNumberValue('NUM', script);\n                var val = script.getNumberValue('VALUE', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue;\n\n                    if (num == 1) {\n                        timeValue = (60 / speed1) * val * 1000 + 32;\n                        console.log(timeValue);\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        timeValue = (60 / speed2) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        timeValue = (60 / speed3) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_step_rotate2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_step_rotate2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                VALUE: 2,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var dir = script.getNumberValue('DIR', script);\n                num = script.getNumberValue('NUM', script);\n                var val = script.getNumberValue('VALUE', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    var timeValue;\n\n                    if (num == 1) {\n                        timeValue = (60 / (speed1 * 360)) * val * 1000 + 32;\n                        console.log(timeValue);\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        timeValue = (60 / (speed2 * 360)) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        timeValue = (60 / (speed3 * 360)) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_step_rotate3: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_step_rotate3',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                SEC: 2,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                num = script.getNumberValue('NUM');\n                var dir = script.getNumberValue('DIR');\n                var sec = script.getNumberValue('SEC');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(\n                        function () {\n                            script.timeFlag = 0;\n                        },\n                        sec * 1000 + 32\n                    );\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_module_digital_oled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_module_digital_oled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_module_digital_oled',\n            },\n            paramsKeyMap: {\n                VALUE0: 0,\n                VALUE1: 1,\n                STRING: 2,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port = 0;\n                var coodinate_x = script.getNumberValue('VALUE0');\n                var coodinate_y = script.getNumberValue('VALUE1');\n                var string = script.getValue('STRING');\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    coodinate_x = Math.min(coodinate_x, 127);\n                    coodinate_x = Math.max(coodinate_x, 0);\n                    coodinate_y = Math.min(coodinate_y, 63);\n                    coodinate_y = Math.max(coodinate_y, 0);\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona.sensorTypes.OLED,\n                        data: {\n                            value0: coodinate_x,\n                            value1: coodinate_y,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['dalgona.Module_digital_oled(%1, %2, %3)'] },\n        },\n\n        dalgona_rfid_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_rfid_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'RFID',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                ss = port1;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][ss] = {\n                        type: Entry.Dalgona.sensorTypes.RFIDINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_is_rfid_tapped: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'dalgona_is_rfid_tapped',\n            },\n            paramsKeyMap: {},\n            class: 'RFID',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.RFIDTAP] = {\n                    port: ss,\n                    time: new Date().getTime(),\n                };\n\n                var value = Entry.hw.portData.RFIDTAP || 0;\n                return value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_get_rfid_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'dalgona_get_rfid_value',\n            },\n            paramsKeyMap: {},\n            class: 'RFID',\n            isNotFor: ['Dalgona'],\n            func: function (sprite, script) {\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][ss];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.RFIDVALUE] = {\n                    port: ss,\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.RFIDVALUE || 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_get_mlx: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['목표물', '0'],\n                        ['주변', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'dalgona_get_mlx',\n            },\n            paramsKeyMap: {\n                MLX_SELECT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona'],\n\n            func: function (sprite, script) {\n                var type = script.getNumberValue('MLX_SELECT');\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (type == 0) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.MLXOBJ] = {\n                        port: 0,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.MLXOBJ || 0;\n                } else if (type == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.MLXAMB] = {\n                        port: 0,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.MLXAMB || 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Dalgona;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_dalgona_basic.js",
    "content": "'use strict';\n\nEntry.Dalgona_basic = {\n    id: '54.2',\n    name: 'Dalgona_basic',\n    url: 'https://dalgonaedu.co.kr/',\n    imageName: 'dalgona.png',\n    title: {\n        ko: '달고나.에듀 Basic',\n        en: 'Dalgona.Edu Basic',\n    },\n    Static: {\n        BUTTON_PRESS_VALUE: 0,\n    },\n\n    //정지시 초기화 함수\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                if (Entry.hw.sendQueue.SET[key].type == Entry.Dalgona_basic.sensorTypes.SERVO) {\n                    Entry.hw.sendQueue.SET[key].data = 200;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } \n                else if (Entry.hw.sendQueue.SET[key].type == Entry.Dalgona_basic.sensorTypes.SERVO2) {\n                    Entry.hw.sendQueue.SET[key].data.value1 = 200;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } \n                else {\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        READ_BLUETOOTH: 9,\n        WRITE_BLUETOOTH: 10,\n        LCD: 11,\n        LCDCLEAR: 12,\n        RGBLED: 13,\n        DCMOTOR: 14,\n        OLED: 15,\n        PIR: 16,\n        LCDINIT: 17,\n        DHTHUMI: 18,\n        DHTTEMP: 19,\n        NEOPIXELINIT: 20,\n        NEOPIXELBRIGHT: 21,\n        NEOPIXEL: 22,\n        NEOPIXELALL: 23,\n        NEOPIXELCLEAR: 24,\n        DOTMATRIXINIT: 25,\n        DOTMATRIXBRIGHT: 26,\n        DOTMATRIX: 27,\n        DOTMATRIXEMOJI: 28,\n        DOTMATRIXCLEAR: 29,\n        MP3INIT: 30,\n        MP3PLAY1: 31,\n        MP3PLAY2: 32,\n        MP3VOL: 33,\n        RESET_: 34,\n        LOADINIT: 35,\n        LOADSCALE: 36,\n        LOADVALUE: 37,\n        DUST: 38,\n        JOYINIT: 39,\n        JOYX: 40,\n        JOYY: 41,\n        JOYZ: 42,\n        JOYMOVE: 43,\n        RFIDINIT: 44,\n        RFIDTAP: 45,\n        RFIDVALUE: 46,\n        STEPINIT: 47,\n        STEPSPEED: 48,\n        STEPROTATE: 49,\n        STEPROTATE2: 50,\n        STEPROTATE3: 51,\n        MLXOBJ: 52,\n        MLXAMB: 53,\n        SERVO2: 54,\n        GYROX: 55,\n        GYROY: 56,\n        GYROZ: 57,\n        PULLUP: 58,\n        TONETOGGLE: 59,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n          // 1옥  2옥  3옥  4옥  5옥  6옥   7옥   8옥\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],   // 도\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],   // 도#\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],   // 레\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],   // 미b\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],   // 미\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],   // 파\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],   // 파#\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],   // 솔\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],  // 솔#\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040], // 라\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459], // 시b\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902], // 시\n    },\n    direction: {\n        CENTER: 0,\n        UP: 1,\n        LEFT: 2,\n        RIGHT: 3,\n        DOWN: 4,\n        LEFT_UP: 5,\n        LEFT_DOWN: 6,\n        RIGHT_UP: 7,\n        RIGHT_DOWN: 8,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    getOffsetX(str) {\n        return this.getByteLength(str) * 1.5 - 5;\n    },\n    getByteLength(s, b, i, c) {\n        for (b = i = 0; (c = s.charCodeAt(i++)); b += c >> 11 ? 3 : c >> 7 ? 2 : 1);\n        return b;\n    },\n    BlockState: {},\n};\nEntry.Dalgona_basic.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                // set_neopixelinit: '디지털 %1 번 핀에 연결된 %2 개의 네오픽셀 LED 사용하기 %3',\n\t\t\t\t// set_neopixel: '디지털 %1 번 핀에 연결된 %2 번째 네오픽셀 LED를 R: %3 , G: %4 , B: %5 색으로 켜기 %6',\n\n                // FND_event: 'FND 4digit (TM1637)- CLK:D5, DIO:D4',\n                // FND_Control_init: 'FND %1 번 : 디지털 CLK %2, DIO %3 번 핀으로 설정',\n                // FND_Control_diplay_brightness: 'FND %1 번 : 밝기 %2 단계로 설정',\n                // FND_Control_display_onoff: 'FND %1 번 : 전원 %2',\n                // FND_Control_diplay_char:\n                //     'FND %1 번 : %2 출력하기:나머지0채우기 %3  %4 초 대기',\n\t\t\t\t\n\n\n\n\n                dalgona_basic_digital_title:'달고나 디지털 블럭',\n                dalgona_basic_analog_title:'달고나 아날로그 블럭',\n                dalgona_basic_pwm_title:'달고나 PWM 블럭',\n                dalgona_basic_library_title:'달고나 라이브러리 블럭',\n                dalgona_basic_neopixel_title:'달고나 네오픽셀 블럭',\n                dalgona_basic_ultrasonic_title: '달고나 초음파센서 블럭',\n                dalgona_basic_buzzer_title: '달고나 피에조 부저 블럭',\n                dalgona_basic_dotmatrix_title:'달고나 8X8 도트매트릭스 블럭',\n                dalgona_basic_rfid_title:'달고나 RFID 블럭',\n                dalgona_basic_motor_title:'달고나 모터 블럭',\n                dalgona_basic_stepmotor_title:'달고나 스텝모터 블럭',\n                dalgona_basic_joystick_title:'달고나 조이스틱 블럭',\n                dalgona_basic_LCD_title:'달고나 LCD 블럭',\n                dalgona_basic_mp3_title:'달고나 mp3 블럭',\n                dalgona_basic_HX711_title:'달고나 HX711 로드셀 블럭',\n                dalgona_basic_sensor_title:'달고나 센서 블럭',\n                dalgona_basic_toggle_on: '켜기',\n                dalgona_basic_toggle_off: '끄기',\n                dalgona_basic_lcd_first_line: '첫 번째',\n                dalgona_basic_lcd_seconds_line: '두 번째',\n                dalgona_basic_get_analog_value: '아날로그 %1 핀 읽기',\n                dalgona_basic_get_light_value: '조도센서(AO %1)값',\n                dalgona_basic_get_moisture_value: '토양수분센서(AO %1)값',\n                dalgona_basic_get_sound_value: '사운드센서(AO %1)값',\n                dalgona_basic_get_infrared_value: '적외선센서(AO %1)값',\n                dalgona_basic_get_pullup: '풀업 저항 사용 버튼 %1 핀 눌림 상태',\n                dalgona_basic_get_button: '버튼 %1 핀 눌림 상태',\n                dalgona_basic_get_analog_mapping: '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n                dalgona_basic_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                dalgona_basic_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                dalgona_basic_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n                dalgona_basic_get_digital: '디지털 %1 핀 읽기',\n                dalgona_basic_get_digital_toggle: '디지털 %1 핀 센서 값',\n                dalgona_basic_get_digital_pir: 'PIR %1 핀 센서 값',\n                dalgona_basic_set_digital_toggle: '디지털 %1 핀 %2 %3',\n                dalgona_basic_set_led_toggle: 'LED %1 핀 %2 %3',\n                dalgona_basic_set_digital_pwm: 'LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3',\n                dalgona_basic_set_digital_rgbled: 'RGB LED (R %1 핀, G %2 핀, B %3 핀) 색 (R: %4, G: %5, B: %6) 출력 %7',\n                dalgona_basic_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                dalgona_basic_set_digital_servo2: \"서보 모터 %1 핀 %2 ~ %3 각도로 %4 초 동안 회전 %5\",\n                dalgona_basic_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                dalgona_basic_set_digital_buzzer_volume: '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                dalgona_basic_set_digital_buzzer: '피에조부저 %1 핀 %2 %3 음 %4 박자 연주 %5',\n                dalgona_basic_set_digital_dcmotor: 'DC모터 %1핀 %2 %3',\n                dalgona_basic_set_analog_dcmotor: 'DC모터(PWM %1 핀) 세기 %2 출력 (0 ~ 255) %3',\n                dalgona_basic_set_neopixel_init: '네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\n                dalgona_basic_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\n                dalgona_basic_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\n                dalgona_basic_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\n                dalgona_basic_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\n                dalgona_basic_set_dotmatrix_init: '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                dalgona_basic_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                dalgona_basic_set_dotmatrix: '도트매트릭스 LED %1 그리기 %2',\n                dalgona_basic_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                dalgona_basic_set_dotmatrix_clear: '도트매트릭스 LED 지우기 %1',\n                dalgona_basic_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n                dalgona_basic_get_lcd_row: '%1',\n                dalgona_basic_get_lcd_col: '%1',\n                dalgona_basic_module_digital_lcd: 'LCD화면 %1 열 %2 행 부터 %3 출력 %4',\n                dalgona_basic_lcd_clear: 'LCD 화면 지우기 %1',\n                dalgona_basic_get_dht: 'DHT11 온습도센서(out %1)의 %2값',\n                //dalgona_basic_get_dht_temp_value: 'DHT11 온습도센서(out %1)의 온도(°C)값',\n                //dalgona_basic_get_dht_humi_value: 'DHT11 온습도센서(out %1)의 습도(%)값',\n\n                dalgona_basic_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\n                dalgona_basic_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\n                dalgona_basic_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\n                dalgona_basic_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\n                dalgona_basic_get_analog_temp_value: 'DHT11 포트 %1의 %2 센서 값',\n\n                dalgona_basic_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3',\n                dalgona_basic_load_scale: 'HX711 로드셀 보정하기 %1 %2',\n                dalgona_basic_load_value: 'HX711 로드셀 값',\n\n                dalgona_basic_get_dust: '미세먼지센서 (LED %1, AO %2) 값',\n\n                dalgona_basic_rfid_init: 'RFID 시작하기 설정 (SS %1, RST %2) %3',\n                dalgona_basic_is_rfid_tapped: 'RFID 카드가 인식되었는가?',\n                dalgona_basic_get_rfid_value: 'RFID 카드 값',\n                dalgona_basic_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5',\n                dalgona_basic_get_joy_x: '%1 조이스틱 X값',\n                dalgona_basic_get_joy_y: '%1 조이스틱 y값',\n                dalgona_basic_get_joy_z: '%1 조이스틱 버튼 눌림 상태',\n                dalgona_basic_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때',\n\n                dalgona_basic_get_mlx: 'mlx90614 비접촉 온도센서 %1값',\n\n                dalgona_basic_step_init: '%1 스텝모터 시작하기 설정 (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6',\n                dalgona_basic_step_speed: '%1 스텝모터 속도를 %2 로 설정하기 (0 ~ 20) %3',\n                dalgona_basic_step_rotate: '%1 스텝모터 %2 으로 %3 바퀴 회전하기 %4',\n                dalgona_basic_step_rotate2: '%1 스텝모터 %2 으로 %3 도 회전하기 %4',\n                dalgona_basic_step_rotate3: '%1 스텝모터 %2 으로 %3 초 동안 회전하기 %4',\n\n                // dalgona_basic_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\n                // dalgona_basic_module_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n\n            },\n        },\n        en: {\n            template: {\n                // FND_event: 'FND 4digit (TM1637)- CLK:D5, DIO:D4',\n                // FND_Control_init: 'FND %1 번 : 디지털 CLK %2, DIO %3 번 핀으로 설정',\n                // FND_Control_diplay_brightness: 'FND %1 번 : 밝기 %2 단계로 설정',\n                // FND_Control_display_onoff: 'FND %1 번 : 전원 %2',\n                // FND_Control_diplay_char:\n                //     'FND %1 번 : %2 출력하기:나머지0채우기 %3  %4 초 대기',\n\n\n\n                set_neopixelinit: '디지털 %1 번 핀에 연결된 %2 개의 네오픽셀 LED 사용하기 %3',\n\t\t\t\tset_neopixel: '디지털 %1 번 핀에 연결된 %2 번째 네오픽셀 LED를 R: %3 , G: %4 , B: %5 색으로 켜기 %6',\n\t\t\t\t\n                dalgona_basic_digital_title:'달고나 디지털 블럭',\n                dalgona_basic_analog_title:'달고나 아날로그 블럭',\n                dalgona_basic_pwm_title:'달고나 PWM 블럭',\n                dalgona_basic_library_title:'달고나 라이브러리 블럭',\n                dalgona_basic_neopixel_title:'달고나 네오픽셀 블럭',\n                dalgona_basic_ultrasonic_title: '달고나 초음파센서 블럭',\n                dalgona_basic_buzzer_title: '달고나 피에조 부저 블럭',\n                dalgona_basic_dotmatrix_title:'달고나 8X8 도트매트릭스 블럭',\n                dalgona_basic_rfid_title:'달고나 RFID 블럭',\n                dalgona_basic_motor_title:'달고나 모터 블럭',\n                dalgona_basic_stepmotor_title:'달고나 스텝모터 블럭',\n                dalgona_basic_joystick_title:'달고나 조이스틱 블럭',\n                dalgona_basic_LCD_title:'달고나 LCD 블럭',\n                dalgona_basic_mp3_title:'달고나 mp3 블럭',\n                dalgona_basic_HX711_title:'달고나 HX711 로드셀 블럭',\n                dalgona_basic_sensor_title:'달고나 센서 블럭',\n\n                dalgona_basic_toggle_on: 'on',\n                dalgona_basic_toggle_off: 'off',\n                dalgona_basic_lcd_first_line: 'first',\n                dalgona_basic_lcd_seconds_line: 'seconds',\n                dalgona_basic_get_analog_value: 'Read analog %1 pin sensor value',\n                dalgona_basic_get_analog_mapping: 'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\n                dalgona_basic_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                dalgona_basic_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                dalgona_basic_get_digital_bluetooth: 'Bluetooth RX 2 value',\n                dalgona_basic_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n                dalgona_basic_get_digital: 'Digital %1 pin sensor value',\n                dalgona_basic_get_digital_toggle: 'Digital %1 pin sensor value',\n                dalgona_basic_set_digital_toggle: 'Digital %1 pin %2 %3',\n                dalgona_basic_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n                dalgona_basic_set_digital_rgbled: 'Digital %1 pin RGB LED Red %2 Green %3 Blue %4 %5',\n                dalgona_basic_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                dalgona_basic_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                dalgona_basic_set_digital_buzzer_volume: '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                dalgona_basic_set_digital_buzzer:'피에조부저 %1 번 핀의 버저를 %2 %3 음으로 %4 박자 연주 %5',\n                dalgona_basic_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5',\n                dalgona_basic_set_neopixel_init:'네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\n                dalgona_basic_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\n                dalgona_basic_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\n                dalgona_basic_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\n                dalgona_basic_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\n                dalgona_basic_set_dotmatrix_init: '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                dalgona_basic_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                dalgona_basic_set_dotmatrix: '도트매트릭스 LED 그리기 %1 %2',\n                dalgona_basic_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                dalgona_basic_module_digital_lcd: 'LCD %1 열 %2 행 부터 %3 출력',\n                dalgona_basic_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n\n                dalgona_basic_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\n                dalgona_basic_module_digital_oled: 'OLED X codinate %1 Y coodinate %2 appear %3 %4',\n                dalgona_basic_get_dht_temp_value: '온습도센서의 온도값',\n                dalgona_basic_get_dht_humi_value: '온습도센서의 습도값',\n\n                dalgona_basic_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\n                dalgona_basic_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\n                dalgona_basic_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\n                dalgona_basic_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\n\n                dalgona_basic_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3',\n                dalgona_basic_load_scale: 'HX711 로드셀 보정하기 %1 %2',\n                dalgona_basic_load_value: 'HX711 로드셀 값',\n\n                dalgona_basic_get_dust: '미세먼지센서(LED %1, AO %2) 값(μg/m³)',\n\n                dalgona_basic_rfid_init: 'RFID 시작하기 설정 (RST %1, SS %2) %3',\n                dalgona_basic_is_rfid_tapped: 'RFID 카드가 인식되었는가?',\n                dalgona_basic_get_rfid_value: 'RFID 카드 값',\n\n                dalgona_basic_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5',\n                dalgona_basic_get_joy_x: '%1 조이스틱 X값',\n                dalgona_basic_get_joy_y: '%1 조이스틱 y값',\n                dalgona_basic_get_joy_z: '%1 조이스틱 버튼 눌림 상태',\n                dalgona_basic_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때',\n\n                dalgona_basic_step_init: '%1 스텝모터 시작하기 설정 (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6',\n                dalgona_basic_step_speed: '%1 스텝모터 속도를 %2 로 설정하기 (0 ~ 20) %3',\n                dalgona_basic_step_rotate: '%1 스텝모터 %2 으로 %3 바퀴 회전하기 %4',\n                dalgona_basic_step_rotate2: '%1 스텝모터 %2 으로 %3 도 회전하기 %4',\n                dalgona_basic_step_rotate3: '%1 스텝모터 %2 으로 %3 초 동안 회전하기 %4',\n\n                dalgona_basic_mlx: 'mlx90614 값',\n            },\n        },\n    };\n};\nEntry.Dalgona_basic.blockMenuBlocks = [\n\n    // 'FND_event',\n    // 'FND_Control_diplay_brightness',\n    // 'FND_Control_display_onoff',\n    // 'FND_Control_diplay_char',\n\n    'dalgona_basic_digital_title',\n    'dalgona_basic_set_digital_toggle',\n    'dalgona_basic_get_digital',\n    'dalgona_basic_set_led_toggle',\n\n    'dalgona_basic_analog_title',\n    'dalgona_basic_get_analog_value',\n    'dalgona_basic_get_analog_mapping',\n    'dalgona_basic_mapping1',\n    'dalgona_basic_mapping2',\n    \n    'dalgona_basic_pwm_title',\n    'dalgona_basic_set_digital_pwm',\n    'dalgona_basic_set_digital_rgbled',\n\n    'dalgona_basic_library_title',\n\n    'dalgona_basic_neopixel_title',\n    'dalgona_basic_set_neopixel_init',\n    'dalgona_basic_set_neopixel_bright',\n    'dalgona_basic_set_neopixel',\n    'dalgona_basic_set_neopixel_all',\n    'dalgona_basic_set_neopixel_clear',\n\n    'dalgona_basic_ultrasonic_title',\n    'dalgona_basic_get_digital_ultrasonic',\n\n    'dalgona_basic_buzzer_title',\n    'dalgona_basic_set_digital_buzzer_toggle',\n    'dalgona_basic_set_digital_buzzer_volume',\n    'dalgona_basic_set_digital_buzzer',\n\n    // 'dalgona_basic_dotmatrix_title',\n    // 'dalgona_basic_set_dotmatrix_init',\n    // 'dalgona_basic_set_dotmatrix_bright',\n    // 'dalgona_basic_set_dotmatrix',\n    // 'dalgona_basic_set_dotmatrix_emoji',\n    // 'dalgona_basic_set_dotmatrix_clear',\n\n    // 'dalgona_basic_rfid_title',\n    // 'dalgona_basic_rfid_init',\n    // 'dalgona_basic_is_rfid_tapped',\n    // 'dalgona_basic_get_rfid_value',\n\n    'dalgona_basic_motor_title',\n    'dalgona_basic_set_digital_dcmotor',\n    'dalgona_basic_set_analog_dcmotor',\n    // 'dalgona_basic_set_digital_servo',\n    // 'dalgona_basic_set_digital_servo2',\n\n    // 'dalgona_basic_stepmotor_title',\n    // 'dalgona_basic_step_init',\n    // 'dalgona_basic_step_speed',\n    // 'dalgona_basic_step_rotate',\n    // 'dalgona_basic_step_rotate2',\n    // 'dalgona_basic_step_rotate3',\n\n    // 'dalgona_basic_joystick_title',\n    // 'dalgona_basic_joy_init',\n    // 'dalgona_basic_get_joy_x',\n    // 'dalgona_basic_get_joy_y',\n    // 'dalgona_basic_get_joy_z',\n    // 'dalgona_basic_get_joy_move',\n\n    // 'dalgona_basic_LCD_title',\n    // 'dalgona_basic_lcd_init',\n    // 'dalgona_basic_module_digital_lcd',\n    // 'dalgona_basic_get_lcd_row',\n    // 'dalgona_basic_get_lcd_col',\n    // 'dalgona_basic_lcd_clear',\n\n    // 'dalgona_basic_mp3_title',\n    // 'dalgona_basic_set_mp3_init',\n    // 'dalgona_basic_set_mp3_vol',\n    // 'dalgona_basic_set_mp3_play',\n    // 'dalgona_basic_set_mp3_play2',\n\n    // 'dalgona_basic_HX711_title',\n    // 'dalgona_basic_load_init',\n    // 'dalgona_basic_load_scale',\n    // 'dalgona_basic_load_value',\n\n    'dalgona_basic_sensor_title',\n\n    // 'dalgona_basic_get_dust',\n    'dalgona_basic_get_digital_toggle',\n    'dalgona_basic_get_digital_pir',\n    'dalgona_basic_get_light_value',\n    // 'dalgona_basic_get_moisture_value',\n    'dalgona_basic_get_sound_value',\n    'dalgona_basic_get_infrared_value',\n    // 'dalgona_basic_get_dht',\n    //'dalgona_basic_get_dht_temp_value',\n    //'dalgona_basic_get_dht_humi_value',\n    'dalgona_basic_get_pullup',\n    'dalgona_basic_get_button',\n    // 'dalgona_basic_get_mlx',\n    // 'dalgona_basic_get_digital_bluetooth',\n    // 'dalgona_basic_module_digital_bluetooth',\n];\nEntry.Dalgona_basic.getBlocks = function() {\n    var tx;\n    var din;\n    // var clk;\n    // var cs; \n    var dout;\n    var sck;\n    var joyx, joyy, joyz;\n    var joyx2, joyy2, joyz2;\n    var portpin1, portpin2, portpin3;\n    var ss;\n    var RGBport;\n    var mlxport;\n    var speed1 = 14;\n    var speed2 = 14;\n    var speed3 = 14;\n    var num = 0;\n\n    return {\n\n        // FND_Control_init: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     fontColor: '#fff',\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['1', 1]],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['5', 5]],\n        //             value: 5,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['4', 4]],\n        //             value: 4,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //     ],\n        //     def: { params: [], type: 'FND_Control_init' },\n        //     paramsKeyMap: { fnd_device: 0, CLK: 1, DIO: 2 },\n        //     class: 'other',\n        //     isNotFor: ['Dalgona'],\n        //     func(sprite, script) {\n        //         const device = script.getNumberValue('fnd_device', script);\n        //         const clk_val = script.getNumberValue('CLK', script);\n        //         const dio_val = script.getNumberValue('DIO', script);\n\n        //         // index number patched by Remoted 2020-11-20\n        //         if (!Entry.hw.sendQueue.SET) {\n        //             Entry.hw.sendQueue.SET = {};\n        //         }\n        //         // FND_Init type data protocol defined\n        //         Entry.hw.sendQueue.SET[device] = {\n        //             type: Entry.Dalgona.sensorTypes.FNDINIT,\n        //             data: {\n        //                 clk_pin: clk_val,\n        //                 dio_pin: dio_val,\n        //             },\n        //             time: new Date().getTime(),\n        //         };\n\n        //         return script.callReturn();\n        //     },\n        //     syntax: { js: [], py: ['RichShield_FND_init(%1, %2)'] },\n        // },\n        // FND_Control_diplay_brightness: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     fontColor: '#fff',\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['1', 1]],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [\n        //                 ['1', 1],\n        //                 ['2', 2],\n        //                 ['3', 3],\n        //                 ['4', 4],\n        //                 ['5', 5],\n        //                 ['6', 6],\n        //                 ['7', 7],\n        //             ],\n        //             value: 3,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //     ],\n        //     def: { params: [], type: 'FND_Control_diplay_brightness' },\n        //     paramsKeyMap: { fnd_device: 0, level: 1 },\n        //     class: 'other',\n        //     isNotFor: ['Dalgona'],\n        //     func(sprite, script) {\n        //         const device = script.getNumberValue('fnd_device', script);\n        //         const level_val = script.getNumberValue('level', script);\n\n        //         if (!script.isStart) {\n        //             // index number patched by Remoted 2020-11-20\n        //             if (!Entry.hw.sendQueue.SET) {\n        //                 Entry.hw.sendQueue.SET = {};\n        //             }\n\n\n        //             script.isStart = true;\n        //             script.timeFlag = 1;\n        //             const fps = Entry.FPS || 60;\n        //             const timeValue = (60 / fps) * 50;\n\n        //             // FND_Init type data protocol defined\n        //             Entry.hw.sendQueue.SET[device] = {\n        //                 type: Entry.Dalgona.sensorTypes.FNDINIT,\n        //                 data: {\n        //                     level_val,\n        //                     block_index: 1,\n        //                 },\n        //                 time: new Date().getTime(),\n        //             };\n        //             setTimeout(() => {\n        //                 script.timeFlag = 0;\n        //             }, timeValue);\n        //             return script;\n        //         } else if (script.timeFlag == 1) {\n        //             return script;\n        //         } else {\n        //             delete script.timeFlag;\n        //             delete script.isStart;\n        //             Entry.engine.isContinue = false;\n        //             return script.callReturn();\n        //         }\n        //     },\n        //     syntax: { js: [], py: ['RichShield_FND_Control_diplay_brightness(%1, %2)'] },\n        // },\n        // FND_Control_display_onoff: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     fontColor: '#fff',\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['1', 1]],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [\n        //                 [Lang.Blocks.RichShield_toggle_off, 0],\n        //                 [Lang.Blocks.RichShield_toggle_on, 1],\n        //             ],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //     ],\n        //     def: { params: [], type: 'FND_Control_display_onoff' },\n        //     paramsKeyMap: { fnd_device: 0, onoff: 1 },\n        //     class: 'other',\n        //     isNotFor: ['Dalgona'],\n        //     func(sprite, script) {\n        //         const device = script.getNumberValue('fnd_device', script);\n        //         const onoff = script.getNumberValue('onoff', script);\n\n        //         if (!script.isStart) {\n        //             // index number patched by Remoted 2020-11-20\n        //             if (!Entry.hw.sendQueue.SET) {\n        //                 Entry.hw.sendQueue.SET = {};\n        //             }\n\n        //             script.isStart = true;\n        //             script.timeFlag = 1;\n        //             const fps = Entry.FPS || 60;\n        //             const timeValue = (60 / fps) * 50;\n\n        //             // FND_Init type data protocol defined\n        //             Entry.hw.sendQueue.SET[device] = {\n        //                 type: Entry.Dalgona.sensorTypes.FNDINIT,\n        //                 data: {\n        //                     onoff,\n        //                     block_index: 2,\n        //                 },\n        //                 time: new Date().getTime(),\n        //             };\n                    \n        //             setTimeout(() => {\n        //                 script.timeFlag = 0;\n        //             }, timeValue);\n        //             return script;\n        //         } else if (script.timeFlag == 1) {\n        //             return script;\n        //         } else {\n        //             delete script.timeFlag;\n        //             delete script.isStart;\n        //             Entry.engine.isContinue = false;\n        //             return script.callReturn();\n        //         }\n\n        //     },\n        //     syntax: { js: [], py: ['RichShield_FND_Control_display_onoff(%1, %2)'] },\n        // },\n        // FND_Control_diplay_char: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     fontColor: '#fff',\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['1', 1]],\n        //             value: 1,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Block',\n        //             accept: 'string',\n        //         },\n        //         {\n        //             type: 'Dropdown',\n        //             options: [\n        //                 [Lang.Blocks.RichShield_toggle_off, 0],\n        //                 [Lang.Blocks.RichShield_toggle_on, 1],\n        //             ],\n        //             value: 0,\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Block',\n        //             accept: 'string',\n        //         },\n        //     ],\n        //     events: {},\n        //     def: {\n        //         params: [\n        //             '1',\n        //             {\n        //                 type: 'number',\n        //                 params: ['1234'],\n        //             },\n        //             '0',\n        //             {\n        //                 type: 'number',\n        //                 params: ['0.1'],\n        //             },\n        //         ],\n        //         type: 'FND_Control_diplay_char',\n        //     },\n        //     events: {},\n        //     paramsKeyMap: { fnd_device: 0, display_value: 1, onoff: 2, delay_ms: 3 },\n        //     class: 'other',\n        //     isNotFor: ['Dalgona'],\n        //     func(sprite, script) {\n        //         const device = script.getNumberValue('fnd_device', script);\n        //         const display_str = script.getNumberValue('display_value', script);\n        //         const onoff = script.getNumberValue('onoff', script);\n        //         const delay_ms_sec = script.getNumberValue('delay_ms', script);\n        //         const splited_array = [];\n        //         let display_str_converted = 0;\n\n        //         if (!script.isStart) {\n        //             if (!Entry.hw.sendQueue.SET) {\n        //                 Entry.hw.sendQueue.SET = {};\n        //             }\n\n        //             display_str_converted = display_str.toString();\n\n        //             script.isStart = true;\n        //             script.timeFlag = 1;\n        //             const fps = Entry.FPS || 60;\n        //             const timeValue = (60 / fps) * 100;\n\n        //             for (let i = 0; i < display_str_converted.length; i++) {\n        //                 splited_array.push(parseInt(display_str_converted.charAt(i)));\n        //             }\n\n        //             console.log(`splited_array :${splited_array}`);\n\n        //             // FND_Init type data protocol defined\n        //             Entry.hw.sendQueue.SET[device] = {\n        //                 type: Entry.Dalgona.sensorTypes.FNDINIT,\n        //                 data: {\n        //                     display_str,\n        //                     onoff,\n        //                     block_index: 3,\n        //                     str_length: display_str_converted.length,\n        //                     data_0: splited_array[0],\n        //                     data_1: splited_array[1],\n        //                     data_2: splited_array[2],\n        //                     data_3: splited_array[3],\n        //                     delay_ms: delay_ms_sec,\n        //                 },\n        //                 time: new Date().getTime(),\n        //             };\n\n                        \n        //             setTimeout(() => {\n        //                 script.timeFlag = 0;\n        //             }, timeValue);\n        //             return script;\n        //         } else if (script.timeFlag == 1) {\n        //             return script;\n        //         } else {\n        //             delete script.timeFlag;\n        //             delete script.isStart;\n        //             Entry.engine.isContinue = false;\n        //             return script.callReturn();\n        //         }\n        //     },\n        //     syntax: { js: [], py: ['RichShield_FND_Control_diplay_char(%1, %2, %3, %4)'] },\n        // },\n        dalgona_basic_digital_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_digital_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_digital_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_digital_title',\n            },\n            class: 'digital',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_analog_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_analog_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_analog_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_analog_title',\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_pwm_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_pwm_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_pwm_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_pwm_title',\n            },\n            class: 'pwm',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_library_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_library_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_library_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_library_title',\n            },\n            class: 'library',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_neopixel_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_neopixel_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_neopixel_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_neopixel_title',\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_ultrasonic_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_ultrasonic_title),\n                    offsetY: 7,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_ultrasonic_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_ultrasonic_title',\n            },\n            class: 'ultrasonic',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_buzzer_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_buzzer_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_buzzer_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_buzzer_title',\n            },\n            class: 'buzzer',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_dotmatrix_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_dotmatrix_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_dotmatrix_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_dotmatrix_title',\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_rfid_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_rfid_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_rfid_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_rfid_title',\n            },\n            class: 'RFID',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_motor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_motor_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_motor_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_motor_title',\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_stepmotor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_stepmotor_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_stepmotor_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_stepmotor_title',\n            },\n            class: 'step',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_joystick_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_joystick_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_joystick_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_joystick_title',\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_LCD_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_LCD_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_LCD_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_LCD_title',\n            },\n            class: 'LCD',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_mp3_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_mp3_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_mp3_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_mp3_title',\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_HX711_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_HX711_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_HX711_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_HX711_title',\n            },\n            class: 'HX711',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n        dalgona_basic_sensor_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: this.getOffsetX(Lang.template.dalgona_basic_sensor_title),\n                    offsetY: 3,\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#d1702a',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.dalgona_basic_sensor_title,\n                    color: '#d1702a',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'dalgona_basic_sensor_title',\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            events: {},\n        },\n\n\n\n\n        dalgona_basic_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        dalgona_basic_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        dalgona_basic_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        dalgona_basic_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        dalgona_basic_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_basic_toggle_on, 'on'],\n                        [Lang.template.dalgona_basic_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        dalgona_basic_list_digital_toggle_en: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['HIGH', 'on'],\n                        ['LOW', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        dalgona_basic_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        dalgona_basic_set_neopixel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_neopixel_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('NUM');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.NEOPIXELINIT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_set_neopixel_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_neopixel_bright',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('NUM');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.NEOPIXELBRIGHT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_set_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'dalgona_basic_set_neopixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n                COLOR: 2,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                //var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var num = script.getNumberValue('NUM', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.NEOPIXEL,\n                        data: {\n                            num: num,\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_set_neopixel_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'dalgona_basic_set_neopixel_all',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COLOR: 1,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.NEOPIXELALL,\n                        data: {\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_set_neopixel_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_neopixel_clear',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neopixel',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.NEOPIXELCLEAR,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_lcd_list_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x27', '0'],\n                        ['0x3F', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        dalgona_basic_set_dotmatrix_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['12'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_dotmatrix_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                din = port1;\n                // clk = port2;\n                // cs = port3;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port1] = {\n                        type: Entry.Dalgona_basic.sensorTypes.DOTMATRIXINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                            port3: port3,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_set_dotmatrix_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_dotmatrix_bright',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                num = Math.round(num);\n                num = Math.min(num, 8);\n                num = Math.max(num, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.Dalgona_basic.sensorTypes.DOTMATRIXBRIGHT,\n                        data: num,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_set_dotmatrix_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'dalgona_basic_set_dotmatrix_clear',\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona_basic'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (1 + 0.5) * 0.1; //0.15\n                    timeValue = (60 / fps) * timeValue * 100;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.Dalgona_basic.sensorTypes.DOTMATRIXCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_set_dotmatrix: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['003c420024242400'],\n                    },\n                ],\n                type: 'dalgona_basic_set_dotmatrix',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var text = script.getValue('STRING');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.Dalgona_basic.sensorTypes.DOTMATRIX,\n                        data: {\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_dotmatrix_emoji_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['🖤', '1'],\n                        ['🤍', '2'],\n                        ['👆', '3'],\n                        ['👇', '4'],\n                        ['👈', '5'],\n                        ['👉', '6'],\n                        ['😊', '7'],\n                        ['😥', '8'],\n                        ['😡', '9'],\n                        ['😆', '10'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        dalgona_basic_set_dotmatrix_emoji: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_dotmatrix_emoji_list',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_dotmatrix_emoji',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n            },\n            class: 'dotmatrix',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('LIST');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.Dalgona_basic.sensorTypes.DOTMATRIXEMOJI,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.dalgona_basic_lcd_first_line, '0'],\n                        [Lang.template.dalgona_basic_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        dalgona_basic_get_lcd_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'dalgona_basic_get_lcd_row',\n                    },\n                ],\n            },\n        },\n\n        dalgona_basic_get_lcd_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'dalgona_basic_get_lcd_col',\n                    },\n                ],\n            },\n        },\n        dalgona_basic_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.dalgona_basic_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {},\n        },\n        dalgona_basic_get_light_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_light_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { },\n        },\n        dalgona_basic_get_moisture_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //template: Lang.template.dalgona_basic_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                        params: ['1'],\n                    },\n                ],\n                type: 'dalgona_basic_get_moisture_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {},\n        },\n\n        dalgona_basic_set_digital_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_set_digital_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Dalgona_basic.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Dalgona_basic.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona_basic.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {},\n        },\n        dalgona_basic_set_analog_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_set_analog_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_pwm',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_analog_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona_basic.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {},\n        },\n        dalgona_basic_get_sound_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_sound_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {},\n        },\n        dalgona_basic_get_infrared_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_infrared_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {},\n        },\n        dalgona_basic_get_pullup: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_pullup',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                // var pu = Entry.hw.portData.PULLUP;\n                var pu = Entry.hw.portData.DIGITAL;\n                \n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                // Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.PULLUP] = {\n                //     port: port,\n                //     data: 2,\n                //     time: new Date().getTime(),\n                // };\n\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                var pullupvalue = pu ? pu[port] || 0 : 0;\n                return !pullupvalue;\n\n                \n            },\n            \n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_button',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DIGITAL] = {\n                    port: port,\n                    data: 2,\n                    time: new Date().getTime(),\n                };\n\n                var value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                return !value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.dalgona_basic_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'dalgona_basic_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                result = ANALOG ? ANALOG[port] || 0 : 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_basic_mapping1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                ],\n                type: 'dalgona_basic_mapping1',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                num = Math.min(value3, num);\n                num = Math.max(value2, num);\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_basic_mapping2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1024'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'dalgona_basic_mapping2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'analog',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var flag = 0;\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var value4_1 = value4;\n                var value5_1 = value5;\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                if (value4 > value5) {\n                    flag = 1;\n                    var swap = value4;\n                    value4_1 = value5;\n                    value5_1 = swap;\n                }\n\n                num -= value2;\n                num = num * ((value5_1 - value4_1) / (value3 - value2));\n\n                if (flag == 1) {\n                    num = value4 - num;\n                    num = Math.min(value4, num);\n                    num = Math.max(value5, num);\n                } else {\n                    num = num + value4;\n                    num = Math.min(value5, num);\n                    num = Math.max(value4, num);\n                }\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_basic_get_digital_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.dalgona_basic_get_digital_ultrasonic,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                        params: ['13'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                        params: ['12'],\n                    },\n                ],\n                type: 'dalgona_basic_get_digital_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'ultrasonic',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                Entry.Utils.sleep(700);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC[port2] || 0;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_basic_get_dust: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                        params: ['0'],\n                    },\n                ],\n                type: 'dalgona_basic_get_dust',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DUST] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.DUST || 0;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_basic_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.dalgona_basic_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'digital',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.dalgona_basic_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_get_digital_pir: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.dalgona_basic_get_digital_pir,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                    },\n                ],\n                type: 'dalgona_basic_get_digital_pir',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.PIR] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['dalgona_basic.get_digital_pir(%1)'] },\n        },\n\n        dalgona_basic_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_toggle_en',\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'digital',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Dalgona_basic.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Dalgona_basic.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona_basic.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_set_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                        params: ['13'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_led_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'digital',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Dalgona_basic.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Dalgona_basic.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona_basic.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_pwm',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'pwm',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona_basic.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_set_digital_rgbled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_set_digital_rgbled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_pwm',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_pwm',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_pwm',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_rgbled',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n                VALUE1: 3,\n                VALUE2: 4,\n                VALUE3: 5,\n            },\n            class: 'pwm',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                RGBport = port1;\n\n                // if (!Entry.hw.sendQueue['SET']) {\n                //     Entry.hw.sendQueue['SET'] = {};\n                // }\n                // Entry.hw.sendQueue['SET'][RGBport] = {\n                //     type: Entry.Dalgona.sensorTypes.RGBLED,\n                //     data: {\n                //         port1: port1,\n                //         port2: port2,\n                //         port3: port3,\n                //         value1: value1,\n                //         value2: value2,\n                //         value3: value3,\n                //     },\n                //     time: new Date().getTime(),\n                // };\n                // return script.callReturn();\n                \n\n                // if (!script.isStart) {\n                //     script.isStart = true;\n                //     script.timeFlag = 1;\n                //     var fps = Entry.FPS || 60;\n                //     var timeValue = (60 / fps) * 50;\n\n                //     value1 = Math.round(value1);\n                //     value1 = Math.min(value1, 255);\n                //     value1 = Math.max(value1, 0);\n                //     value2 = Math.round(value2);\n                //     value2 = Math.min(value2, 255);\n                //     value2 = Math.max(value2, 0);\n                //     value3 = Math.round(value3);\n                //     value3 = Math.min(value3, 255);\n                //     value3 = Math.max(value3, 0);\n\n                //     if (!Entry.hw.sendQueue['SET']) {\n                //         Entry.hw.sendQueue['SET'] = {};\n                //     }\n                //     Entry.hw.sendQueue['SET'][RGBport] = {\n                //         type: Entry.Dalgona.sensorTypes.RGBLED,\n                //         data: {\n                //             port1: port1,\n                //             port2: port2,\n                //             port3: port3,\n                //             value1: value1,\n                //             value2: value2,\n                //             value3: value3,\n                //         },\n                //         time: new Date().getTime(),\n                //     };\n                //     setTimeout(function() {\n                //         script.timeFlag = 0;\n                //     }, 10);\n                //     return script;\n                // } else if (script.timeFlag == 1) {\n                //     return script;\n                // } else {\n                //     delete script.timeFlag;\n                //     delete script.isStart;\n                //     Entry.engine.isContinue = false;\n                //     return script.callReturn();\n                // }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type: Entry.Dalgona_basic.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type: Entry.Dalgona_basic.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port3] = {\n                    type: Entry.Dalgona_basic.sensorTypes.PWM,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n                 return script.callReturn();\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        dalgona_basic_set_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_set_digital_servo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona_basic.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_set_digital_servo2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_set_digital_servo2,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['180'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_servo2',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n                STIME: 3,\n            },\n            class: 'motor',\n            isNotFor: ['Dalgona_basic'],\n            // func: function(sprite, script) {\n            //     var port = script.getNumberValue('PORT');\n            //     var value1 = script.getNumber    Value('VALUE1', script);\n            //     var value2 = script.getNumberValue('VALUE2', script);\n            //     var stime = script.getNumberValue('STIME', script);\n\n            //     value1 = Math.min(value1, 180);\n            //     value1 = Math.max(value1, 0);\n            //     value2 = Math.min(value2, 180);\n            //     value2 = Math.max(value2, 0);\n\n            //     if (!Entry.hw.sendQueue['SET']) {\n            //         Entry.hw.sendQueue['SET'] = {};\n            //     }\n                \n            //     Entry.hw.sendQueue['SET'][port] = {\n            //         type: Entry.Dalgona.sensorTypes.SERVO2,\n            //         data: {\n            //             value1: value1,\n            //             value2: value2,\n            //             stime: stime,\n            //         },\n            //         time: new Date().getTime(),\n            //     };\n            //     return script.callReturn();\n            // },\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var stime = script.getNumberValue('STIME', script);\n\n                value1 = Math.min(value1, 180);\n                value1 = Math.max(value1, 0);\n                value2 = Math.min(value2, 180);\n                value2 = Math.max(value2, 0);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.SERVO2,\n                        data: {\n                            value1: value1,\n                            value2: value2,\n                            stime: stime,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        dalgona_basic_set_digital_buzzer_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_toggle',\n                    },\n\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_buzzer_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'buzzer',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Dalgona_basic.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Dalgona_basic.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona_basic.sensorTypes.TONETOGGLE,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_basic_set_digital_buzzer_volume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_pwm',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_buzzer_volume',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'buzzer',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Dalgona_basic.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_basic_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_digital_basic',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_tone',\n                    },\n                    {\n                        type: 'dalgona_basic_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'buzzer',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.Dalgona_basic.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.Dalgona_basic.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.Dalgona_basic.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        dalgona_basic_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_lcd_list_init',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_lcd_init',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n                COL: 1,\n                LINE: 2,\n            },\n            class: 'LCD',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var list = script.getNumberValue('LIST');\n                var col = script.getNumberValue('COL');\n                var line = script.getValue('LINE');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 0.1 * 1000;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.Dalgona_basic.sensorTypes.LCDINIT,\n                        data: {\n                            list: list,\n                            col: col,\n                            line: line,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_module_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_get_lcd_col',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'dalgona_basic_get_lcd_row',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Hello, dalgona_basic'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_module_digital_lcd',\n            },\n            paramsKeyMap: {\n                COL: 0,\n                ROW: 1,\n                STRING: 2,\n            },\n            class: 'LCD',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var row = script.getNumberValue('ROW');\n                var col = script.getNumberValue('COL');\n                var text = script.getValue('STRING');\n                text += ' ';\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.Dalgona_basic.sensorTypes.LCD,\n                        data: {\n                            line: row,\n                            column: col,\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_lcd_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'dalgona_basic_lcd_clear',\n            },\n            class: 'LCD',\n            isNotFor: ['Dalgona_basic'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.Dalgona_basic.sensorTypes.LCDCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_get_dht: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['온도(°C)', '0'],\n                        ['습도(%)', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n\n                ],\n                type: 'dalgona_basic_get_dht',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DHT_SELECT: 1,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var type = script.getNumberValue('DHT_SELECT');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (type == 0) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DHTTEMP] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTTEMP || 0;\n                } else if (type == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DHTHUMI] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTHUMI || 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_set_mp3_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_mp3_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                tx = script.getNumberValue('PORT1');\n                var rx = script.getNumberValue('PORT2');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.Dalgona_basic.sensorTypes.MP3INIT,\n                        data: {\n                            tx: tx,\n                            rx: rx,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_set_mp3_play: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_mp3_play',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                script.isStart = true;\n                script.timeFlag = 1;\n                var fps = Entry.FPS || 60;\n                var timeValue = (60 / fps) * 50;\n\n                Entry.hw.sendQueue['SET'][tx] = {\n                    type: Entry.Dalgona_basic.sensorTypes.MP3PLAY1,\n                    data: {\n                        tx: tx,\n                        num: num,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_set_mp3_play2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_mp3_play2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                TIME: 1,\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM');\n                var time_value = script.getNumberValue('TIME');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    time_value = (60 / fps) * time_value * 1000;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.Dalgona_basic.sensorTypes.MP3PLAY1,\n                        data: {\n                            tx: tx,\n                            num: num,\n                            //time_value: time_value,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, time_value);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.Dalgona_basic.sensorTypes.MP3PLAY1,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_set_mp3_vol: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['15'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_set_mp3_vol',\n            },\n            paramsKeyMap: {\n                VOL: 0,\n            },\n            class: 'mp3',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var vol = script.getNumberValue('VOL');\n\n                vol = Math.round(vol);\n                vol = Math.min(vol, 30);\n                vol = Math.max(vol, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.Dalgona_basic.sensorTypes.MP3VOL,\n                        data: {\n                            tx: tx,\n                            vol: vol,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_load_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_load_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'HX711',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                dout = port1;\n                sck = port2;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][sck] = {\n                        type: Entry.Dalgona_basic.sensorTypes.LOADINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_load_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['-20000'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_load_scale',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'HX711',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][sck] = {\n                        type: Entry.Dalgona_basic.sensorTypes.LOADSCALE,\n                        data: {\n                            num: num,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_load_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'dalgona_basic_load_value',\n            },\n            paramsKeyMap: {},\n            class: 'HX711',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][sck];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.LOADVALUE] = {\n                    port: sck,\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.LOADVALUE || 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_list_joy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['첫번째', '1'],\n                        ['두번째', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NUM');\n            },\n        },\n        dalgona_basic_joy_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_joy',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_analog_basic',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_joy_init',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                PORT1: 1,\n                PORT2: 2,\n                PORT3: 3,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                if (num == 1) {\n                    joyx = port1;\n                    joyy = port2;\n                    joyz = port3;\n                } else if (num == 2) {\n                    joyx2 = port1;\n                    joyy2 = port2;\n                    joyz2 = port3;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][joyx] = {\n                            type: Entry.Dalgona_basic.sensorTypes.JOYINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][joyx2] = {\n                            type: Entry.Dalgona_basic.sensorTypes.JOYINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_get_joy_x: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'dalgona_basic_get_joy_x',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var num = script.getNumberValue('NUM', script);\n                if (num == 1) {\n                    return ANALOG ? ANALOG[joyx] || 0 : 0;\n                } else if (num == 2) {\n                    return ANALOG ? ANALOG[joyx2] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_get_joy_y: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'dalgona_basic_get_joy_y',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var num = script.getNumberValue('NUM', script);\n                if (num == 1) {\n                    return ANALOG ? ANALOG[joyy] || 0 : 0;\n                } else if (num == 2) {\n                    return ANALOG ? ANALOG[joyy2] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        dalgona_basic_get_joy_z: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'dalgona_basic_get_joy_z',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                var num = script.getNumberValue('NUM', script);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (num == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DIGITAL] = {\n                        port: joyz,\n                        data: 2,\n                        time: new Date().getTime(),\n                    };\n\n                    var value = DIGITAL ? DIGITAL[joyz] || 0 : 0;\n                    return !value;\n                } else if (num == 2) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.DIGITAL] = {\n                        port: joyz2,\n                        data: 2,\n                        time: new Date().getTime(),\n                    };\n\n                    var value = DIGITAL ? DIGITAL[joyz2] || 0 : 0;\n                    return !value;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_list_joy_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가운데', '0'],\n                        ['위', '1'],\n                        ['아래', '4'],\n                        ['왼쪽', '2'],\n                        ['오른쪽', '3'],\n                        ['왼쪽위', '5'],\n                        ['왼쪽아래', '6'],\n                        ['오른쪽위', '7'],\n                        ['오른쪽아래', '8'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIR');\n            },\n        },\n        dalgona_basic_get_joy_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_joy',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_joy_direction',\n                        params: ['0'],\n                    },\n                ],\n                type: 'dalgona_basic_get_joy_move',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n            },\n            class: 'joystick',\n            isNotFor: ['Dalgona_basic'],\n            func(sprite, script) {\n                var direction = script.getNumberValue('DIR');\n                const ANALOG = Entry.hw.portData.ANALOG;\n                num = script.getNumberValue('NUM', script);\n\n                const getValue = function(w) {\n                    return ANALOG[w] <= 100 ? 0 : ANALOG[w] >= 930 ? 2 : 1;\n                };\n\n                var xpin;\n                var ypin;\n                if (num == 1) {\n                    xpin = joyx;\n                    ypin = joyy;\n                } else if (num == 2) {\n                    xpin = joyx2;\n                    ypin = joyy2;\n                }\n                if (\n                    direction == Entry.Dalgona_basic.direction.CENTER &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona_basic.direction.DOWN &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona_basic.direction.LEFT &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona_basic.direction.LEFT_DOWN &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona_basic.direction.LEFT_UP &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona_basic.direction.RIGHT &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona_basic.direction.RIGHT_DOWN &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona_basic.direction.RIGHT_UP &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.Dalgona_basic.direction.UP &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                }\n\n                return 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_list_step: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['첫번째', '1'],\n                        ['두번째', '2'],\n                        ['세번째', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NUM');\n            },\n        },\n        dalgona_basic_step_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_step_init',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                PORT1: 1,\n                PORT2: 2,\n                PORT3: 3,\n                PORT4: 4,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n                var port4 = script.getNumberValue('PORT4', script);\n\n                if (num == 1) {\n                    portpin1 = port1;\n                } else if (num == 2) {\n                    portpin2 = port1;\n                } else if (num == 3) {\n                    portpin3 = port1;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        console.log('STEP INIT 1st');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        console.log('STEP INIT 2nd');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        console.log('STEP INIT 3rd');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_step_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['14'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_step_speed',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                SPEED: 1,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var sp = script.getNumberValue('SPEED', script);\n\n                sp = Math.round(sp);\n                sp = Math.min(sp, 20);\n                sp = Math.max(sp, 0);\n\n                if (num == 1) {\n                    speed1 = sp;\n                } else if (num == 2) {\n                    speed2 = sp;\n                } else if (num == 3) {\n                    speed3 = sp;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed1,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed2,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_list_step_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['정방향', '1'],\n                        ['역방향', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIR');\n            },\n        },\n        dalgona_basic_step_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_step_rotate',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                VALUE: 2,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var dir = script.getNumberValue('DIR', script);\n                num = script.getNumberValue('NUM', script);\n                var val = script.getNumberValue('VALUE', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue;\n\n                    if (num == 1) {\n                        timeValue = (60 / speed1) * val * 1000 + 32;\n                        console.log(timeValue);\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        timeValue = (60 / speed2) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        timeValue = (60 / speed3) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona_basic.sensorTypes_basic.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };_basic\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_step_rotate2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_step_rotate2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                VALUE: 2,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var dir = script.getNumberValue('DIR', script);\n                num = script.getNumberValue('NUM', script);\n                var val = script.getNumberValue('VALUE', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    var timeValue;\n\n                    if (num == 1) {\n                        timeValue = (60 / (speed1 * 360)) * val * 1000 + 32;\n                        console.log(timeValue);\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        timeValue = (60 / (speed2 * 360)) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        timeValue = (60 / (speed3 * 360)) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_step_rotate3: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dalgona_basic_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'dalgona_basic_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic _step_rotate3',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                SEC: 2,\n            },\n            class: 'step',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                num = script.getNumberValue('NUM');\n                var dir = script.getNumberValue('DIR');\n                var sec = script.getNumberValue('SEC');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, sec * 1000 + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.Dalgona_basic.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_module_digital_oled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.dalgona_basic_module_digital_oled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_module_digital_oled',\n            },\n            paramsKeyMap: {\n                VALUE0: 0,\n                VALUE1: 1,\n                STRING: 2,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port = 0;\n                var coodinate_x = script.getNumberValue('VALUE0');\n                var coodinate_y = script.getNumberValue('VALUE1');\n                var string = script.getValue('STRING');\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    coodinate_x = Math.min(coodinate_x, 127);\n                    coodinate_x = Math.max(coodinate_x, 0);\n                    coodinate_y = Math.min(coodinate_y, 63);\n                    coodinate_y = Math.max(coodinate_y, 0);\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Dalgona_basic.sensorTypes.OLED,\n                        data: {\n                            value0: coodinate_x,\n                            value1: coodinate_y,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        dalgona_basic_rfid_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    null,\n                ],\n                type: 'dalgona_basic_rfid_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'RFID',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                ss = port1;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][ss] = {\n                        type: Entry.Dalgona_basic.sensorTypes.RFIDINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_is_rfid_tapped: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'dalgona_basic_is_rfid_tapped',\n            },\n            paramsKeyMap: {},\n            class: 'RFID',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.RFIDTAP] = {\n                    port: ss,\n                    time: new Date().getTime(),\n                };\n\n                var value = Entry.hw.portData.RFIDTAP || 0;\n                return value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        dalgona_basic_get_rfid_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'dalgona_basic_get_rfid_value',\n            },\n            paramsKeyMap: {},\n            class: 'RFID',\n            isNotFor: ['Dalgona_basic'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][ss];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.RFIDVALUE] = {\n                    port: ss,\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.RFIDVALUE || 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        dalgona_basic_get_mlx: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['목표물', '0'],\n                        ['주변', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'dalgona_basic_get_mlx',\n            },\n            paramsKeyMap: {\n                MLX_SELECT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['Dalgona_basic'],\n            \n            func: function(sprite, script) {\n                var type = script.getNumberValue('MLX_SELECT')\n\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (type == 0) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.MLXOBJ] = {\n                        port: 0,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.MLXOBJ || 0;\n                } else if (type == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.Dalgona_basic.sensorTypes.MLXAMB] = {\n                        port: 0,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.MLXAMB || 0;\n                }                    \n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Dalgona_basic;"
  },
  {
    "path": "src/playground/blocks/hardware/block_dash.js",
    "content": "'use strict';\n\nvar DashState = {\n    STATE_READY: 'ready',\n    STATE_WAIT: 'wait',\n    STATE_DONE: 'done',\n};\n\nEntry.Dash = {\n    PORT_MAP: {\n        seq: 0,\n        category: 0,\n        action: 0,\n        param_cnt: 0,\n        paramA: 0,\n        paramB: 0,\n        paramC: 0,\n        paramD: 0,\n        modeA: 0, //1:RO, 2:RW, 3:WO\n        modeB: 0,\n    },\n    setZero: function() {\n        var portMap = Entry.Dash.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        Entry.Dash.sequance = 1;\n        Entry.Dash.isStarted = false;\n        Entry.Dash.state = DashState.STATE_DONE;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n    },\n    id: '24.1',\n    name: 'Dash',\n    url: 'https://clevermate.kr',\n    imageName: 'dash.png',\n    title: {\n        ko: '대시',\n        en: 'Dash',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/dash.png',\n        width: 605,\n        height: 434,\n    },\n    sequance: 1,\n    isStarted: false,\n    state: DashState.STATE_DONE,\n};\nEntry.Dash.blockMenuBlocks = [\n    //region dash\n    'dash_sensor1',\n    'dash_sensor2',\n    'dash_turn_drive',\n    'dash_turn_drive_360',\n    'dash_drive',\n    'dash_wheel_speed',\n    'dash_drive_stop',\n    'dash_v_head',\n    'dash_h_head',\n    'dash_forward_head',\n    'dash_sound_say',\n    'dash_sound_animal',\n    'dash_sound_move',\n    'dash_sound_strange',\n    'dash_my_sound',\n    'dash_light_color',\n    'dash_tail_light_color',\n    'dash_eye',\n    'dash_animation',\n    //endregion dash\n];\n\nEntry.Dash.getBlocks = function() {\n    return {\n        // 소리\n        dash_sound_say: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '말하기 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['안녕', 0x00],\n                        ['응?', 0x01],\n                        ['어 어!', 0x02],\n                        ['좋아', 0x03],\n                        ['한숨..', 0x04],\n                        ['출발!', 0x1f],\n                        ['짜잔!', 0x05],\n                        ['위!', 0x06],\n                        ['잘 가', 0x07],\n                        ['무작위', 0x1e],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                // 기본 값\n                params: ['0'],\n                type: 'dash_sound_say',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Dash_Sound',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 5; // 소리\n                    sq.action = 2; // 말하기\n                    sq.param_cnt = 1; // param 갯수\n                    if (var1 == 0x1e) {\n                        var1 = Math.floor(Math.random() * 8);\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2; // WR\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            // 재생이 시작되었는지 확인\n                            if (pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            // 재생이 끝났는지 확인\n                            if (!pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            // 다음 블럭 진행\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_sound_animal: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '동물 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['말', 0x08],\n                        ['고양이', 0x09],\n                        ['개', 0x0a],\n                        ['공룡', 0x0b],\n                        ['사자', 0x0c],\n                        ['염소', 0x0d],\n                        ['악어', 0x0e],\n                        ['코끼리', 0x0f],\n                        ['무작위', 0x1e],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                // 기본 값\n                params: ['8'],\n                type: 'dash_sound_animal',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Dash_Sound',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Dash.isStarted) {\n                    console.log(var1);\n                    sq.category = 5; // 소리\n                    sq.action = 2; // 말하기\n                    sq.param_cnt = 1; // param 갯수\n                    if (var1 == 0x1e) {\n                        var1 = Math.floor(Math.random() * 8) + 0x08;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2; // WR\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            // 재생이 시작되었는지 확인\n                            if (pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            // 재생이 끝났는지 확인\n                            if (!pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            // 다음 블럭 진행\n                            Entry.Dash.isStarted = false;\n                            console.log('Goto Next Block');\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_sound_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '이동 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['화재 경보', 0x10],\n                        ['트럭 경적', 0x11],\n                        ['자동차 엔진', 0x12],\n                        ['자동차 타이어 끼익 소리', 0x13],\n                        ['헬리콥터', 0x14],\n                        ['제트기', 0x15],\n                        ['보트', 0x16],\n                        ['기차', 0x17],\n                        ['무작위', 0x1e],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                // 기본 값\n                params: ['16'],\n                type: 'dash_sound_move',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Dash_Sound',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Dash.isStarted) {\n                    console.log(var1);\n                    sq.category = 5; // 소리\n                    sq.action = 2; // 말하기\n                    sq.param_cnt = 1; // param 갯수\n                    if (var1 == 0x1e) {\n                        var1 = Math.floor(Math.random() * 8) + 0x10;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2; // WR\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            // 재생이 시작되었는지 확인\n                            if (pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            // 재생이 끝났는지 확인\n                            if (!pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            // 다음 블럭 진행\n                            Entry.Dash.isStarted = false;\n                            console.log('Goto Next Block');\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_sound_strange: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '이상한 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['경고음', 0x18],\n                        ['레이저', 0x19],\n                        ['고르륵 소리', 0x1a],\n                        ['윙윙 소리', 0x1b],\n                        ['어 어 어', 0x1c],\n                        ['찍 소리', 0x1d],\n                        ['무작위', 0x1e],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                // 기본 값\n                params: ['24'],\n                type: 'dash_sound_strange',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Dash_Sound',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Dash.isStarted) {\n                    console.log(var1);\n                    sq.category = 5; // 소리\n                    sq.action = 2; // 말하기\n                    sq.param_cnt = 1; // param 갯수\n                    if (var1 == 0x1e) {\n                        var1 = Math.floor(Math.random() * 6) + 0x18;\n                    }\n                    sq.paramA = var1;\n                    sq.modeA = 2; // WR\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            // 재생이 시작되었는지 확인\n                            if (pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            // 재생이 끝났는지 확인\n                            if (!pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            // 다음 블럭 진행\n                            Entry.Dash.isStarted = false;\n                            console.log('Goto Next Block');\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_my_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '녹음된 %1 소리 내기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['#1', 0x00],\n                        ['#2', 0x01],\n                        ['#3', 0x02],\n                        ['#4', 0x03],\n                        ['#5', 0x04],\n                        ['#6', 0x05],\n                        ['#7', 0x06],\n                        ['#8', 0x07],\n                        ['#9', 0x08],\n                        ['#10', 0x09],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                // 기본 값\n                params: ['0'],\n                type: 'dash_my_sound',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n            },\n            class: 'Dash_Sound',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('SOUND', script);\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 5;\n                    sq.action = 1;\n                    sq.param_cnt = 1;\n                    sq.paramA = var1;\n                    sq.modeA = 2;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            // 재생이 시작되었는지 확인\n                            if (pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            // 재생이 끝났는지 확인\n                            if (!pd.isPlaying) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            // 다음 블럭 진행\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        // LED\n        dash_light_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 라이트 %2 색으로 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['모든', 0x01],\n                        ['왼쪽 귀', 0x02],\n                        ['오른쪽 귀', 0x03],\n                        ['전면', 0x04],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'dash_light_color',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },\n            class: 'Dash_light',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('LED', script);\n                var var2 = script.getStringField('COLOR', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 4;\n                    sq.action = var1;\n                    sq.param_cnt = 1;\n                    sq.paramA = parseInt(parseInt(var2.substr(1, 2), 16));\n                    sq.paramB = parseInt(parseInt(var2.substr(3, 2), 16));\n                    sq.paramC = parseInt(parseInt(var2.substr(5, 2), 16));\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            var timer = setTimeout(function() {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }, 500);\n                            Entry.Dash.state = DashState.STATE_WAIT;\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_tail_light_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '꼬리 라이트 %1 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', 0x01],\n                        ['끄기', 0x00],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'dash_tail_light_color',\n            },\n            paramsKeyMap: {\n                LED: 0,\n            },\n            class: 'Dash_light',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('LED', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 4;\n                    sq.action = 0x05;\n                    sq.param_cnt = 1;\n                    sq.paramA = var1;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            var timer = setTimeout(function() {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }, 500);\n                            Entry.Dash.state = DashState.STATE_WAIT;\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_eye: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '눈 패턴 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['끄기', 0x00],\n                        ['웃는 얼굴', 0x01],\n                        ['익살스러운 얼굴', 0x02],\n                        ['화난 얼굴', 0x03],\n                        ['놀란 얼굴', 0x04],\n                        ['모두 켜기', 0x05],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['0'],\n                type: 'dash_eye',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n            },\n            class: 'Dash_light',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('EYE', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 4;\n                    sq.action = 6;\n                    sq.param_cnt = 1;\n                    sq.paramA = var1;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            var timer = setTimeout(function() {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }, 500);\n                            Entry.Dash.state = DashState.STATE_WAIT;\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        // 머리\n        dash_v_head: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 바라보기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['위쪽', 0x04],\n                        ['가운데', 0x05],\n                        ['아래쪽', 0x06],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4'],\n                type: 'dash_v_head',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'Dash_head',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('DIRECTION', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 3;\n                    sq.action = var1;\n                    sq.param_cnt = 0;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            var timer = setTimeout(function() {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }, 500);\n                            Entry.Dash.state = DashState.STATE_WAIT;\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_h_head: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 을 %2 방향으로 바라보기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', 0x01],\n                        // [ \"가운데\", 0x02 ],\n                        ['오른쪽', 0x03],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                // {\t// 드롭다운으로 변경\n                // \t\"type\": \"Angle\",\n                // \t\"accept\": \"string\"\n                // },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['15˚', 15],\n                        ['30˚', 30],\n                        ['45˚', 45],\n                        ['60˚', 60],\n                        ['75˚', 75],\n                        ['90˚', 90],\n                        ['105˚', 105],\n                        ['120˚', 120],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', 30],\n                type: 'dash_h_head',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n            },\n            class: 'Dash_head',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('DIRECTION', script);\n                var var2 = script.getNumberField('VALUE', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 3;\n                    sq.action = var1;\n                    sq.param_cnt = 1;\n                    if (var2 > 120) {\n                        var2 = 120; // 각도 값이 120이 넘지 않도록 한다.\n                    }\n                    sq.paramA = var2;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            var timer = setTimeout(function() {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }, 500);\n                            Entry.Dash.state = DashState.STATE_WAIT;\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_forward_head: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '앞을 바라보기 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dash_forward_head',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Dash_head',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 3;\n                    sq.action = 0x02;\n                    sq.param_cnt = 0;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            var timer = setTimeout(function() {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }, 500);\n                            Entry.Dash.state = DashState.STATE_WAIT;\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_voice_head: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '소리가 나는 쪽 바라보기 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dash_voice_head',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Dash_head',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 3;\n                    sq.action = 7;\n                    sq.param_cnt = 0;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            if (pd.soundDirection) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                                var timer = setTimeout(function() {\n                                    Entry.Dash.state = DashState.STATE_DONE;\n                                }, 500);\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        // 움직임\n        dash_turn_drive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 으로 %2 만큼 회전하기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계 방향', 0x03],\n                        ['반 시계 방향', 0x04],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'angle',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['3', 30],\n                type: 'dash_turn_drive',\n            },\n            paramsKeyMap: {\n                ROTATION: 0,\n                VALUE: 1,\n            },\n            class: 'Dash_drive',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('ROTATION', script);\n                var var2 = script.getNumberValue('VALUE', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 1;\n                    sq.action = var1;\n                    sq.param_cnt = 1;\n                    sq.paramA = var2;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            if (pd.isDriving) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            if (!pd.isDriving) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_turn_drive_360: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 으로 한 바퀴 회전하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계 방향', 0x03],\n                        ['반 시계 방향', 0x04],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['3'],\n                type: 'dash_turn_drive_360',\n            },\n            paramsKeyMap: {\n                ROTATION: 0,\n            },\n            class: 'Dash_drive',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('ROTATION', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 1;\n                    sq.action = var1;\n                    sq.param_cnt = 1;\n                    sq.paramA = 360;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            if (pd.isDriving) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            if (!pd.isDriving) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_drive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '%1 (으)로 %2 cm 만큼 %3이동하기 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞', 0x01],\n                        ['뒤', 0x02],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['매우 느리게', 0x01],\n                        ['느리게', 0x02],\n                        ['보통 속도로', 0x03],\n                        ['빠르게', 0x04],\n                        ['매우 빠르게', 0x05],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', 30, '3'],\n                type: 'dash_drive',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DISTANCE: 1,\n                SPEED: 2,\n            },\n            class: 'Dash_drive',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('DIRECTION', script);\n                var var2 = script.getNumberValue('DISTANCE', script);\n                var var3 = script.getNumberField('SPEED', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 1;\n                    sq.action = var1;\n                    sq.param_cnt = 2;\n                    if (var2 > 1638) {\n                        var2 = 1638;\n                    }\n                    sq.paramA = var2;\n                    sq.paramB = var3;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            if (pd.isDriving) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            if (!pd.isDriving) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_wheel_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '왼쪽 바퀴 %1 (으)로 %2, 오른쪽 바퀴 %3 (으)로 %4 움직이기 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞', 0x01],\n                        ['뒤', 0x02],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['매우 느리게', 0x01],\n                        ['느리게', 0x02],\n                        ['보통 속도로', 0x03],\n                        ['빠르게', 0x04],\n                        ['매우 빠르게', 0x05],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞', 0x01],\n                        ['뒤', 0x02],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['매우 느리게', 0x01],\n                        ['느리게', 0x02],\n                        ['보통 속도로', 0x03],\n                        ['빠르게', 0x04],\n                        ['매우 빠르게', 0x05],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '3', '1', '3'],\n                type: 'dash_wheel_speed',\n            },\n            paramsKeyMap: {\n                DIRECTION_L: 0,\n                SPEED_L: 1,\n                DIRECTION_R: 2,\n                SPEED_R: 3,\n            },\n            class: 'Dash_drive',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('DIRECTION_L', script);\n                var var2 = script.getNumberField('SPEED_L', script);\n                var var3 = script.getNumberField('DIRECTION_R', script);\n                var var4 = script.getNumberField('SPEED_R', script);\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 0x01;\n                    sq.action = 0x05;\n                    sq.param_cnt = 0x04;\n                    sq.paramA = var1;\n                    sq.paramB = var2;\n                    sq.paramC = var3;\n                    sq.paramD = var4;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            var timer = setTimeout(function() {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }, 500);\n                            Entry.Dash.state = DashState.STATE_WAIT;\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_drive_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '정지 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dash_drive_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Dash_drive',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 0x01;\n                    sq.action = 0x06;\n                    sq.param_cnt = 0;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            var timer = setTimeout(function() {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }, 500);\n                            Entry.Dash.state = DashState.STATE_WAIT;\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n        dash_sensor1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가운데 버튼', 0x05],\n                        ['1번 버튼', 0x06],\n                        ['2번 버튼', 0x07],\n                        ['3번 버튼', 0x08],\n                        ['박수 소리', 0x09],\n                        ['소리', 0x0a],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['5'],\n                type: 'dash_sensor1',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            isNotFor: ['Dash'],\n            class: 'Dash_senor',\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('VALUE', script);\n                var pd = Entry.hw.portData;\n                switch (var1) {\n                    case 0x05:\n                        return pd.button0 ? true : false;\n                        break;\n                    case 0x06:\n                        return pd.button1 ? true : false;\n                        break;\n                    case 0x07:\n                        return pd.button2 ? true : false;\n                        break;\n                    case 0x08:\n                        return pd.button3 ? true : false;\n                        break;\n                    case 0x09:\n                        return pd.clap ? true : false;\n                        break;\n                    case 0x0a:\n                        return pd.sound ? true : false;\n                        break;\n                    default:\n                        break;\n                }\n                return -1;\n            },\n        },\n        dash_sensor2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞쪽 장애물', 0x00],\n                        ['뒤쪽 장애물', 0x01],\n                        ['오른쪽 장애물', 0x02],\n                        ['왼쪽 장애물', 0x03],\n                        // [ \"움직이지 못함\", 0x04 ],\t// not support.\n                        ['들림', 0x0a],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['0'],\n                type: 'dash_sensor2',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            isNotFor: ['Dash'],\n            class: 'Dash_senor',\n            func: function(sprite, script) {\n                var var1 = script.getNumberField('VALUE', script);\n                var pd = Entry.hw.portData;\n                switch (var1) {\n                    case 0x00:\n                        return pd.barrier_front ? true : false;\n                        break;\n                    case 0x01:\n                        return pd.barrier_rear ? true : false;\n                        break;\n                    case 0x02:\n                        return pd.barrier_right ? true : false;\n                        break;\n                    case 0x03:\n                        return pd.barrier_left ? true : false;\n                        break;\n                    case 0x04:\n                        return pd.barrier_move ? true : false;\n                        break;\n                    case 0x0a:\n                        return pd.pickup ? true : false;\n                        break;\n                    default:\n                        break;\n                }\n                return -1;\n            },\n        },\n        dash_animation: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            template: '애니메이션 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['안녕', 0x00],\n                        ['안녕하세요', 0x01],\n                        ['걱정 마 (오른쪽)', 0x02],\n                        ['걱정 마 (왼쪽)', 0x07],\n                        ['잘가 #1', 0x03],\n                        ['잘가 #2', 0x04],\n                        ['자신감 있는', 0x05],\n                        ['그래그래', 0x06],\n                        ['아무도 없나요', 0x08],\n                        ['그윽', 0x09],\n                        ['하품', 0x0a],\n                        ['드르렁', 0x0b],\n                        ['휘파람', 0x0c],\n                        ['어지러워', 0x0d],\n                        ['출발', 0x0e],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [0],\n                type: 'dash_animation',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Dash_animation',\n            isNotFor: ['Dash'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var pd = Entry.hw.portData;\n                var var1 = script.getNumberField('PORT', script);\n                if (!Entry.Dash.isStarted) {\n                    sq.category = 0x06;\n                    sq.action = 0x01;\n                    sq.param_cnt = 1;\n                    sq.paramA = var1;\n                    sq.modeA = 3;\n                    sq.seq = Entry.Dash.sequance++;\n                    Entry.Dash.isStarted = true;\n                    Entry.Dash.state = DashState.STATE_READY;\n                    return script;\n                } else {\n                    switch (Entry.Dash.state) {\n                        case DashState.STATE_READY:\n                            if (pd.animation) {\n                                Entry.Dash.state = DashState.STATE_WAIT;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_WAIT:\n                            if (!pd.animation) {\n                                Entry.Dash.state = DashState.STATE_DONE;\n                            }\n                            return script;\n                            break;\n                        case DashState.STATE_DONE:\n                            // 다음 블럭 진행\n                            Entry.Dash.isStarted = false;\n                            return script.callReturn();\n                            break;\n                    }\n                }\n                return script;\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Dash;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_davinci.js",
    "content": "'use strict';\n\nconst _set = require('lodash/set');\nconst _get = require('lodash/get');\nconst _merge = require('lodash/merge');\n\nEntry.Davinci = new class Davinci {\n    constructor() {\n\t    this.id = '2D.1';\n        this.url = 'http://www.dasanbooks.com';\n        this.imageName = 'davinciai.png';\n        this.title = {\n            \"en\": \"Davinci\",\n            \"ko\": \"다빈치\"\n        };\n        this.name = 'davinci';\n        this.blockIds = {};\n        this.isExecBlock = false;\n        this.cacheValues = [];\n        this.cacheIndex = 0;\n        this.radioTime = 0;\n    }\n\n    getHashKey() {\n        let key = new Date().getSeconds().toString(16);\n        if (key.length === 1) {\n            key += ((Math.random() * 16) | 0).toString(16);\n        }\n        return Entry.generateHash() + key;\n    }\n\n    setZero() {\n        Entry.hw.sendQueue = {\n            [this.getHashKey()]: {\n                type: 'RST',\n            },\n        };\n        Entry.hw.update();\n        this.blockIds = {};\n        this.isExecBlock = false;\n        this.execTimeFlag = false;\n        this.radioTime = 0;\n    }\n\n    sendMessage({ socket, sendQueue = {} }) {\n        if (!_.isEmpty(sendQueue)) {\n            const keys = Object.keys(sendQueue);\n            const uniqueKey = this.getHashKey();\n            socket.emit(\n                'message',\n                {\n                    data: JSON.stringify(sendQueue),\n                    mode: socket.mode,\n                    type: 'utf8',\n                    key: uniqueKey,\n                },\n                (data) => {\n                    if (data === uniqueKey) {\n                        keys.forEach((key) => {\n                            delete sendQueue[key];\n                        });\n                    }\n                }\n            );\n        }\n    }\n\n    asyncFlowControl({ script, data }, scope) {\n        if (!this.isExecBlock && !scope.isStart) {\n            const blockId = this.getHashKey();\n            this.isExecBlock = true;\n            scope.isStart = true;\n            scope.timeFlag = 1;\n            this.nowBlockId = blockId;\n            this.blockIds[blockId] = false;\n            _merge(Entry.hw.sendQueue, {\n                [blockId]: data,\n            });\n            Entry.hw.update();\n            setTimeout(() => {\n                scope.timeFlag = 0;\n            });\n            return false;\n        } else if (this.blockIds[this.nowBlockId] && scope.timeFlag === 0) {\n            delete this.blockIds[this.nowBlockId];\n            delete scope.isStart;\n            this.execTimeFlag = 0;\n            this.execTimeFlag = undefined;\n            this.isExecBlock = false;\n            Entry.engine.isContinue = false;\n            return true;\n        }\n        return false;\n    }\n\n    postCallReturn(args) {\n        const { script } = args;\n        if (!this.asyncFlowControl(args, script)) {\n            return Entry.STATIC.BREAK;\n        }\n    }\n\n    checkValue(args) {\n        const { script, key } = args;\n        const { entity, executor } = script;\n        const { scope } = executor;\n        const { cacheValue = {} } = scope;\n        const value = _get(cacheValue, key);\n        if (value) {\n            return value;\n        } else if (!this.asyncFlowControl(args, scope)) {\n            throw new Entry.Utils.AsyncError();\n        }\n    }\n\n    afterSend(data) {\n        // Object.assign(data, {\n        //     OUTPUT: {},\n        // });\n    }\n\n    afterReceive({ blockId = '', RADIO }) {\n        if (blockId in this.blockIds) {\n            this.blockIds[blockId] = true;\n        } else if (RADIO && Entry.engine.isState('run') && RADIO.time > this.radioTime) {\n            this.radioTime = RADIO.time;\n            Entry.engine.fireEvent('DavinciRadioReceive');\n        }\n    }\n}();\n\nEntry.Davinci.blockMenuBlocks = [\n    'davinci_led_toggle',\n    'davinci_get_led',\n    'davinci_show_string',\n    'davinci_show_image',\n    'davinci_set_analog',\n    'davinci_set_digital',\n    'davinci_get_analog',\n    'davinci_get_analog_map',\n    'davinci_get_digital',\n    'davinci_get_button',\n    'davinci_get_sensor',\n    'davinci_get_accelerometer',\n    'davinci_get_gyro',\n    'davinci_get_magnet',\n    'davinci_play_note',\n    'davinci_play_melody',\n    'davinci_change_bpm',\n    'davinci_set_bpm',\n];\n\nEntry.Davinci.getBlocks = function() {\n    return {\n        davinci_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: 'LED의 X:%1 Y:%2 %3 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1'], ['3', '2'], ['4', '3'], ['5', '4']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', '0'],\n                        ['B', '1'],\n                        ['C', '2'],\n                        ['D', '3'],\n                        ['E', '4'],\n                        ['F', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['켜기', '0'], ['끄기', '1'], ['반전', '2']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciLed',\n            isNotFor: ['davinci'],\n            def: {\n                params: [],\n                type: 'davinci_led_toggle',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                VALUE: 2,\n            },\n            func: function(sprite, script) {\n                const value = script.getField('VALUE');\n                let x = script.getField('X');\n                let y = script.getField('Y');\n                \n                const data = {\n                    type: 'SET_LED',\n                    data: {\n                        x,\n                        y,\n                        value,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        davinci_get_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: 'LED의 X:%1 Y:%2 상태값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '0'], ['2', '1'], ['3', '2'], ['4', '3'], ['5', '4']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', '0'],\n                        ['B', '1'],\n                        ['C', '2'],\n                        ['D', '3'],\n                        ['E', '4'],\n                        ['F', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'DavinciLed',\n            isNotFor: ['davinci'],\n            def: {\n                params: [],\n                type: 'davinci_get_led',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n            },\n            func: function(sprite, script) {\n                let x = script.getNumberValue('X');\n                let y = script.getNumberValue('Y');\n\n                const data = {\n                    type: 'GET_LED',\n                    data: {\n                        x,\n                        y,\n                    },\n                };\n                let returnData = Entry.Davinci.checkValue({\n                    script,\n                    data,\n                    key: `LED.${x}.${y}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['LED']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `LED.${x}.${y}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        davinci_show_string: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '%1 출력하기 %2',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciLed',\n            isNotFor: ['davinci'],\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['Hello!'],\n                    },\n                ],\n                type: 'davinci_show_string',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                let value = script.getStringValue('VALUE');\n                value = value.replace(\n                    /[^A-Za-z0-9_\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\\\\\{\\}\\[\\]\\'\\\"\\;\\:\\<\\,\\>\\.\\?\\/\\s]/gim,\n                    ''\n                );\n                const data = {\n                    type: 'SET_STRING',\n                    data: {\n                        value,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        davinci_show_image: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '%1 이모티콘 출력하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['하트', 0],\n                        ['작은하트', 1],\n                        ['정답', 2],\n                        ['오답', 3],\n                        ['웃는얼굴', 5],\n                        ['화난얼굴', 6],\n                        ['슬픈얼굴', 7],\n                        ['소얼굴', 8],\n                        ['무표정한얼굴', 9],\n                        ['사슴', 12],\n                        ['물음표', 13],\n                        ['느낌표', 14],\n                        ['기린', 15],\n                        ['개', 16],\n                        ['위', 20],\n                        ['왼쪽', 21],\n                        ['아래', 22],\n                        ['오른쪽', 23],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciLed',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_show_image',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                const value = script.getField('VALUE');\n                const data = {\n                    type: 'SET_IMAGE',\n                    data: {\n                        value,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        davinci_set_analog: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '아날로그 핀 %1번을 %2으로 설정 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1번', 0], ['2번', 1], ['3번', 2], ['4번', 3]],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                    value: 0,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciDirect',\n            isNotFor: ['davinci'],\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: [0],\n                    },\n                ],\n                type: 'davinci_set_analog',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            func: function(_sprite, script) {\n                let pin = script.getField('PIN');\n                let value = script.getNumberValue('VALUE', script);\n\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n\n                const data = {\n                    type: 'SET_ANALOG',\n                    data: {\n                        pin,\n                        value,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        davinci_set_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '디지털 핀 %1번을 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1번', 0], ['2번', 1], ['3번', 2], ['4번', 3]],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['켜기', '0'], ['끄기', '1'], ['반전', '2']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciDirect',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_set_digital',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            func: function(_sprite, script) {\n                const value = script.getField('VALUE');\n                let pin = script.getField('PIN');\n\n                const data = {\n                    type: 'SET_DIGITAL',\n                    data: {\n                        pin,\n                        value,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        davinci_get_analog: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '아날로그 핀 %1번 입력 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1번', 0], ['2번', 1], ['3번', 2], ['4번', 3]],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'DavinciDirect',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_get_analog',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                const value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_ANALOG',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Davinci.checkValue({\n                    script,\n                    data,\n                    key: `GET_ANALOG.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_ANALOG']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_ANALOG.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        davinci_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '디지털 핀 %1번 입력 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1번', 0], ['2번', 1], ['3번', 2], ['4번', 3]],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'DavinciDirect',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_get_digital',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                let value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_DIGITAL',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Davinci.checkValue({\n                    script,\n                    data,\n                    key: `GET_DIGITAL.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_DIGITAL']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_DIGITAL.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        davinci_get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '%1버튼을 눌렀는가?',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['A', 10], ['B', 11], ['A + B', 12]],\n                    value: 10,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'DavinciSensor',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_get_button',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                let value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_BUTTON',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Davinci.checkValue({\n                    script,\n                    data,\n                    key: `GET_BUTTON.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_BUTTON']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    console.log(\"RETURN: \" + returnData);\n                    _set(scope.cacheValue, `GET_BUTTON.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        davinci_get_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1 센서값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빛', 'lightLevel'],\n                        ['온도', 'temperature'],\n                        ['소리', 'soundLevel'],\n                        ['자기', 'compassHeading'],\n                    ],\n                    value: 'temperature',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'DavinciSensor',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_get_sensor',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                let value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_SENSOR',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Davinci.checkValue({\n                    script,\n                    data,\n                    key: `GET_SENSOR.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_SENSOR']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_SENSOR.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        davinci_get_accelerometer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '가속도 센서 %1의 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x축', 0],\n                        ['y축', 1],\n                        ['z축', 2],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'DavinciSensor',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_get_accelerometer',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                let value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_ACCELEROMETER',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Davinci.checkValue({\n                    script,\n                    data,\n                    key: `GET_ACCELEROMETER.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_ACCELEROMETER']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(\n                        scope.cacheValue,\n                        `GET_ACCELEROMETER.${value}`,\n                        returnData\n                    );\n                }\n                return returnData;\n            },\n        },\n        davinci_get_gyro: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '자이로 센서 %1의 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x축', 0],\n                        ['y축', 1],\n                        ['z축', 2],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'DavinciSensor',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_get_gyro',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                let value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_GYRO',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Davinci.checkValue({\n                    script,\n                    data,\n                    key: `GET_GYRO.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_GYRO']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(\n                        scope.cacheValue,\n                        `GET_GYRO.${value}`,\n                        returnData\n                    );\n                }\n                return returnData;\n            },\n        },\n        davinci_get_magnet: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '지자기 센서 %1의 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x축', 0],\n                        ['y축', 1],\n                        ['z축', 2],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'DavinciSensor',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_get_magnet',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                let value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_MAGNET',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Davinci.checkValue({\n                    script,\n                    data,\n                    key: `GET_MAGNET.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_MAGNET']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(\n                        scope.cacheValue,\n                        `GET_MAGNET.${value}`,\n                        returnData\n                    );\n                }\n                return returnData;\n            },\n        },\n        davinci_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            statements: [],\n            template: '%1음을 %2박자 연주하기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['낮은 도', 1],\n                        ['낮은 도#', 22],\n                        ['낮은 레', 2],\n                        ['낮은 레#', 23],\n                        ['낮은 미', 3],\n                        ['낮은 파', 4],\n                        ['낮은 파#', 24],\n                        ['낮은 솔', 5],\n                        ['낮은 솔#', 25],\n                        ['낮은 라', 6],\n                        ['낮은 라#', 26],\n                        ['낮은 시', 7],\n                        ['가온 도', 8],\n                        ['가온 도#', 27],\n                        ['가온 레', 9],\n                        ['가온 레#', 28],\n                        ['가온 미', 10],\n                        ['가온 파', 11],\n                        ['가온 파#', 29],\n                        ['가온 솔', 12],\n                        ['가온 솔#', 30],\n                        ['가온 라', 13],\n                        ['가온 라#', 31],\n                        ['가온 시', 14],\n                        ['높은 도', 15],\n                        ['높은 도#', 32],\n                        ['높은 레', 16],\n                        ['높은 레#', 33],\n                        ['높은 미', 17],\n                        ['높은 파', 18],\n                        ['높은 파#', 34],\n                        ['높은 솔', 19],\n                        ['높은 솔#', 35],\n                        ['높은 라', 20],\n                        ['높은 라#', 36],\n                        ['높은 시', 21],\n                    ],\n                    value: 8,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['1/2', 4],\n                        ['1/4', 5],\n                        ['1/8', 6],\n                        ['1/16', 7],\n                        ['2', 1],\n                        ['4', 2],\n                        ['8', 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciMusic',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                BEAT: 1,\n            },\n            func: function(sprite, script) {\n                const note = script.getField('NOTE');\n                const beat = script.getField('BEAT');\n                const data = {\n                    type: 'PLAY_NOTE',\n                    data: {\n                        note,\n                        beat,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        davinci_play_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            statements: [],\n            template: '%1 노래 연주하기%2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['띠링', 0],\n                        ['와우와우와우', 1],\n                        ['올라가기', 2],\n                        ['내려가기', 3],\n                        ['파워업', 4],\n                        ['파워다운', 5],\n                        ['마법봉', 6],\n                        ['비상벨', 7],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciMusic',\n            isNotFor: ['davinci'],\n            def: {\n                type: 'davinci_play_melody',\n            },\n            paramsKeyMap: {\n                MELODY: 0,\n            },\n            func: function(sprite, script) {\n                const melody = script.getField('MELODY');\n                const data = {\n                    type: 'PLAY_MELODY',\n                    data: {\n                        melody,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        davinci_change_bpm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            statements: [],\n            template: '연주 속도를 %1BPM 만큼 바꾸기 %2',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciMusic',\n            isNotFor: ['davinci'],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [20],\n                    },\n                ],\n                type: 'davinci_change_bpm',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                const value = script.getNumberValue('VALUE');\n                const data = {\n                    type: 'CHANGE_BPM',\n                    data: {\n                        value,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        davinci_set_bpm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            statements: [],\n            template: '연주 속도를 %1BPM으로 정하기 %2',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'DavinciMusic',\n            isNotFor: ['davinci'],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [120],\n                    },\n                ],\n                type: 'davinci_set_bpm',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                const value = script.getNumberValue('VALUE');\n                const data = {\n                    type: 'SET_BPM',\n                    data: {\n                        value,\n                    },\n                };\n                return Entry.Davinci.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Davinci;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_diaboard.js",
    "content": "'use strict';\n\nconst PromiseManager = require('../../../core/promiseManager');\n\nEntry.Diaboard = {\n    // g:T:F:9:7:2:120:1:200\n    // g : L버튼상태 : R버튼상태 : 9컬러센서 : 색상 : 2 IR센서: IR값 : 1빛센서 : 조도값\n    // 프로토콜 인자값 : 표준 주파수\n    STANDARD_FREQ: {\t\n        0:\t32.7031875,\n        1:\t34.64784375,\n        2:\t36.70809375,\n        3:\t38.890875,\n        4:\t41.2034375,\n        5:\t43.6535,\n        6:\t46.2493125,\n        7:\t48.9994375,\n        8:\t51.9130625,\n        9:\t55,\n        10:\t58.2705,\n        11:\t61.7354375,\n        12:\t65.406375,\n        13:\t69.2956875,\n        14:\t73.4161875,\n        15:\t77.78175,\n        16:\t82.406875,\n        17:\t87.307,\n        18:\t92.498625,\n        19:\t97.998875,\n        20:\t103.826125,\n        21:\t110,\n        22:\t116.541,\n        23:\t123.470875,\n        24:\t130.81275,\n        25:\t138.591375,\n        26:\t146.832375,\n        27:\t155.5635,\n        28:\t164.81375,\n        29:\t174.614,\n        30:\t184.99725,\n        31:\t195.99775,\n        32:\t207.65225,\n        33:\t220,\n        34:\t233.082,\n        35:\t246.94175,\n        36:\t261.6255,\n        37:\t277.18275,\n        38:\t293.66475,\n        39:\t311.127,\n        40:\t329.6275,\n        41:\t349.228,\n        42:\t369.9945,\n        43:\t391.9955,\n        44:\t415.3045,\n        45:\t440,\n        46:\t466.164,\n        47:\t493.8835,\n        48:\t523.251,\n        49:\t554.3655,\n        50:\t587.3295,\n        51:\t622.254,\n        52:\t659.255,\n        53:\t698.456,\n        54:\t739.989,\n        55:\t783.991,\n        56:\t830.609,\n        57:\t880,\n        58:\t932.328,\n        59:\t987.767,\n        60:\t1046.502,\n        61:\t1108.731,\n        62:\t1174.659,\n        63:\t1244.508,\n        64:\t1318.51,\n        65:\t1397,\n        66:\t1479.978,\n        67:\t1567.982,\n        68:\t1661.218,\n        69:\t1760,\n        70:\t1864.656,\n        71:\t1975.534,\n        72:\t2093.004,\n        73:\t2217.462,\n        74:\t2349.318,\n        75:\t2489.016,\n        76:\t2637.02,\n        77:\t2794,\n        78:\t2959.956,\n        79:\t3135.964,\n        80:\t3322.436,\n        81:\t3520,\n        82:\t3729.312,\n        83:\t3951.068,\n        84:\t4186.008,\n        85:\t4434.924,\n        86:\t4698.636,\n        87:\t4978.032,\n        88:\t5274.04,\n        89:\t5588,\n        90:\t5919.912,\n        91:\t6271.928,\n        92:\t6644.872,\n        93:\t7040,\n        94:\t7458.624,\n        95:\t7902.136\n    },\n\n    COLOR_TYPE: {\n        0: 'no_color',\n        1: 'red',\n        2: 'yellow',\n        3: 'green',\n        4: 'cyan',\n        5: 'blue',\n        6: 'magenta',\n        7: 'white',\n    },\n\n    EFFECT_TYPE: {\n        0: 'f',     // effect_flame\n        1: 'd',     // effect_drop\n        2: 'g',     // effect_glitter\n        3: 'm',     // effect_dimming\n    },\n\n    INEQ_SIGN : [\n        [\"<\", \"<\"],\n        [\">\", \">\"],\n        [\"=\", \"=\"]\n    ],\n\n    OCTAVE_TYPE : [\n        [\"1\", 1],\n        [\"2\", 2],\n        [\"3\", 3],\n        [\"4\", 4],\n        [\"5\", 5],\n        [\"6\", 6],\n        [\"7\", 7]\n    ],\n\n    RHYTHM_TYPE : [\n        [\"0.125\", 0.125],\n        [\"0.25\",  0.25],\n        [\"0.5\",   0.5],\n        [\"1\",     1],\n        [\"2\",     2],\n        [\"4\",     4],\n        [\"8\",     8],\n        [\"16\",    16]\n    ],\n\n    MELODY_TYPE: {\n        //상승음\n        0: {\n            gap: 120,\n            commands : [ \"b:n:48:20\", \"b:n:50:20\", \"b:n:57:20\", \"b:n:55:20\", \"b:n:53:20\", \"b:n:52:20\", \"b:n:59:20\", \"b:n:60:20\" ]\n        },\n        // 하강음\n        1: {\n            gap : 120,\n            commands : [ \"b:n:60:10\", \"b:n:60:10\", \"b:n:55:10\", \"b:n:55:10\", \"b:n:52:10\", \"b:n:52:10\", \"b:n:48:10\", \"b:n:48:10\" ]\n        },\n        // 엘리제를 위하여 (이것만 총 9개의 음입니다.)\n        2: {\n            gap : 150,\n            commands : [ \"b:n:64:20\", \"b:n:63:20\", \"b:n:64:20\", \"b:n:63:20\", \"b:n:64:20\", \"b:n:59:20\", \"b:n:62:20\", \"b:n:60:20\", \"b:n:57:20\" ]\n        },\n        // 긴장감\n        3: { \n            gap : 150,\n            commands : [ \"b:n:69:20\", \"b:n:60:20\", \"b:n:69:20\", \"b:n:64:20\", \"b:n:69:20\", \"b:n:62:20\", \"b:n:69:20\", \"b:n:65:20\",\n                         \"b:n:69:20\", \"b:n:60:20\", \"b:n:69:20\", \"b:n:64:20\", \"b:n:69:20\", \"b:n:62:20\", \"b:n:69:20\", \"b:n:65:20\" ]\n        },\n        // 연결음\n        4: { \n            gap : 150,\n            commands : [ \"b:n:67:20\", \"b:n:65:20\", \"b:n:67:20\", \"b:x\", \"b:n:64:20\", \"b:n:65:20\", \"b:n:62:20\", \"b:x\" ]\n        },\n        // 뛰어 오르는\n        5: {\n            gap : 120,\n            commands : [ \"b:n:48:20\", \"b:n:50:20\", \"b:n:52:20\", \"b:n:48:20\", \"b:n:53:20\", \"b:x\", \"b:x\", \"b:x\" ] \n        },\n        // 뛰어 내리는\n        6: {\n            gap : 120,\n            commands : [ \"b:n:60:20\", \"b:n:53:20\", \"b:n:52:20\", \"b:n:50:20\", \"b:n:52:20\", \"b:n:48:20\", \"b:x\", \"b:x\" ]\n        }, \n        // 생일 축하\n        7: {\n            gap : 150,\n            commands : [ \"b:n:48:10\", \"b:n:48:10\", \"b:n:50:20\", \"b:x\", \"b:n:48:20\", \"b:n:53:10\", \"b:n:52:10\" ]\n        }\n    },\n\n    COLOR_RANDOM: '8',\n    EFFECT_RANDOM: 'r',\n    DEFAULT_SLEEP: 50,  // 전체 블록 마다 SLEEP\n    EFFECT_DEFAULT_SLEEP: 300,  // 효과음 내기 블록 기본 슬립\n\n    /**\n     * 명령어 시퀀스는 엔트리 하드웨어앱으로 한번 메세지를 보내게 되면,\n     * 엔트리 하드웨어앱에서는, 마지막 명령어를 계속 내부적으로 보낸다.\n     * 그렇기 때문에, 엔트리에서 같은 명령어의 블록을 두개를 연결시켜 보내면,\n     * 두번째 블록 명령어를 엔트리 하드웨어앱에서 무시하게 되어 있기 때문에\n     * ( 왜냐하면, 다이아보드 특성상, 시간이 들어간 명령어는 한번만 보내야하기 때문 )\n     * 그래서, 시퀀스를 보냄으로서, 같은 명령어지만, 다른 블록에 의해서, 호출됨을 만들어,\n     * 같은 블록을 연달아 하더라도, 동작하게끔 만들려는 목적으로 사용\n     */\n    _cmd_seq: 0,\n    _frequency: 60,     // default값은 60\n    _bpm: 120,          // default값은 120BPM 이라, 1분에 120비트 => 60초    \n\n    getBPM : function() {\n        return this._bpm;\n    },\n\n    setBPM : function( bpm ) {\n        // 출력을 위해, 세팅\n        Entry.hw.sendQueue['bpm']   = bpm;\n        Entry.hw.update();\n        // 글로벌 저장\n        this._bpm   = bpm;\n    },\n\n    /**\n     * 시간(초) = ( 60 / bpm ) * 박자 (rhythm)\n     * @param {*} rhythm \n     * @returns 시간(초)\n     */\n    convertTimeForBPM : function( rhythm ) {\n        return this.convertTimeByBPM( this.getBPM(), rhythm );\n    },\n\n    /**\n     * 시간(초) = ( 60 / bpm ) * 박자(rhythm)\n     * @param {*} rhythm \n     * @returns 시간(초)\n     */\n    convertTimeByBPM : function( bpm, rhythm ) {\n        return parseFloat( ( 60.0 / ( bpm * 1.0 ) * rhythm ).toFixed( 2 ) );\n    },\n\n    getFrequency : function() {\n        return this._frequency;\n    },\n\n    deferredReturn : function( blockReturn, sleep = Entry.Diaboard.DEFAULT_SLEEP ) {\n        if( sleep > 0 ) {\n            return new PromiseManager().Promise( ( resolve ) => {\n                setTimeout(() => {\n                    return resolve( blockReturn );\n                }, sleep );\n            });\n        } else {\n            return blockReturn();\n        }\n    },\n\n    setFrequency : function( frequency ) {\n        // 출력을 위해, 세팅\n        Entry.hw.sendQueue['frequency'] = frequency;\n        Entry.hw.update();\n        // 글로벌 저장\n        this._frequency = frequency\n    },\n\n    fireCommand : function( cmd ) {\n        Entry.hw.sendQueue['cmd'] = cmd;\n        Entry.hw.sendQueue['seq'] = ++this._cmd_seq;\n        Entry.hw.update();\n        // console.log( '>>> ' + cmd );\n    },\n    \n    setZero: function() {\n        this.fireCommand( \"stopNow\" );\n        // this.fireCommand( \"b:x\" );      // 부저 끄기\n        // this.fireCommand( \"m:x\" );      // 모터 끄기\n        // this.fireCommand( \"l:x:0\" );    // LED 끄기\n    },\n    id: '3.2',\n    name: 'diaboard',\n    url: 'http://www.bitbrick.cc/',\n    imageName: 'diaboard.png',\n    title: {\n        ko: '다이아보드',\n        en: 'diaboard',\n    },\n    servoMaxValue: 181,\n    servoMinValue: 1,\n    dcMaxValue: 100,\n    dcMinValue: -100,\n    monitorTemplate: {\n        keys: ['value'],\n        imgPath: 'hw/diaboard.png',\n        width: 400,\n        height: 400,\n        listPorts: {\n            'DISP_L_BUTTON':    { name: '왼쪽 버튼',        type: 'input',  pos: { x: 0, y: 0 }},\n            'DISP_R_BUTTON':    { name: '오른쪽 버튼',      type: 'input',  pos: { x: 0, y: 0 }},\n            'C1':               { name: '컬러센서 색상(hue)',   type: 'input',  pos: { x: 0, y: 0 }},\n            'DISP_COLOR':       { name: '컬러센서 색상',    type: 'input',  pos: { x: 0, y: 0 }},\n            'S6':   { name: '적외선 센서',          type: 'input',  pos: { x: 0, y: 0 }},\n            'S8':   { name: '밝기 센서',            type: 'input',  pos: { x: 0, y: 0 }},\n            // 'cmd':  { name: '커맨드',               type: 'output',  pos: { x: 0, y: 0 }},\n            'bpm':  { name: '연주속도(BPM)',                  type: 'output',  pos: { x: 0, y: 0 }},\n        },\n        mode: 'both',\n    },\n    /**\n     * 콜백 함수. 계속해서 센서 데이터를 받는다.\n     * @param {*} pd \n     */\n    afterReceive(pd) {\n        let items = pd[ 0 ];    // ['g', 'T', 'F', '9', '7', '2', '120', '1', '200']\n        let cmd   = items[ 0 ];\n        if( cmd == 'g' ) {      // sensor data\n            Entry.engine.fireEvent('diaboardSensorEventReceive');\n        }\n    },\n    calculateDCMotorValue: function( value ) {\n        let val = 0;\n        if ( value > 0 ) { \n            val  = Math.floor( ( value * 0.8 ) + 16 );\n        } else if ( value < 0 ) {\n            val  = Math.ceil( ( value * 0.8 ) - 19 );\n        } else { \n            val  = 0; \n        }\n        // DC_MOTOR_ADJUSTMENT  128\n        val = 128 + val;\n        if ( val == 128 ) {\n            val = 129;\n        }\n        return val;\n    }\n};\n\nEntry.Diaboard.blockMenuBlocks = [\n    // 이벤트\n    // 'diaboard_when_button_pressed',\n    // 'diaboard_when_color_is',\n    // 'diaboard_when_sensor_is',\n    \n    // 센서/버튼\n    'diaboard_button_pressed',\n    'diaboard_color_sensor_is',\n    'diaboard_sensor_condition',\n    'diaboard_color_sensor_seven_hue',\n    'diaboard_color_sensor_one_hue',\n    'diaboard_sensor_value',\n    'diaboard_convert_scale',\n\n    // 엘이디\n    'diaboard_led_rainbow',\n    'diaboard_led_rainbow_time',\n    'diaboard_led_effect',\n    'diaboard_led_effect_time',\n    'diaboard_led_six',\n    'diaboard_led_one',\n    'diaboard_led_one_time',\n    'diaboard_led_hue',\n    'diaboard_led_color',\n    'diaboard_led_rgb',\n    'diaboard_led_turn_off_all',\n    \n    // 모터\n    'diaboard_servomotor_angle',\n    'diaboard_servomotor_angle_time',\n    'diaboard_dc_direction_speed',\n    'diaboard_dc_direction_speed_time',\n    'diaboard_dc_speed',\n    'diaboard_dc_speed_time',\n    'diaboard_turn_off_all_motors',\n    \n    // 버저\n    'diaboard_buzzer_melody_type',\n    'diaboard_buzzer_effect_type',\n    'diaboard_buzzer_eight_melody_bpm',\n    'diaboard_buzzer_octave',\n    'diaboard_buzzer_octave_rhythm',\n    'diaboard_buzzer_hz',\n    'diaboard_buzzer_hz_change',\n    'diaboard_buzzer_speed_bpm',\n    'diaboard_buzzer_speed_bpm_change',\n    'diaboard_buzzer_sleep_rhythm',\n    'diaboard_buzzer_stop'\n];\n\nEntry.Diaboard.getBlocks = function() {\n\n    let options_DIABOARD_button1     = \n    [\n        [Lang.Blocks.DIABOARD_button_left,  'left'],\n        [Lang.Blocks.DIABOARD_button_right, 'right'],\n        [Lang.Blocks.DIABOARD_button_all,   'all'],\n    ];\n\n    let options_DIABOARD_button2    = \n    [\n        [Lang.Blocks.DIABOARD_button_pressed,  'pressed'],\n        [Lang.Blocks.DIABOARD_button_released, 'released'],\n    ];\n\n    let options_DIABOARD_color      = \n    [\n        [Lang.Blocks.DIABOARD_color_red,        1],\n        [Lang.Blocks.DIABOARD_color_yellow,     2],\n        [Lang.Blocks.DIABOARD_color_green,      3],\n        [Lang.Blocks.DIABOARD_color_cyan,       4],\n        [Lang.Blocks.DIABOARD_color_blue,       5],\n        [Lang.Blocks.DIABOARD_color_magenta,    6],\n        [Lang.Blocks.DIABOARD_color_white,      7],\n        [Lang.Blocks.DIABOARD_color_no_color,   0],\n    ];\n\n    let options_DIABOARD_color2     =\n    [\n        [Lang.Blocks.DIABOARD_color_red,        1],\n        [Lang.Blocks.DIABOARD_color_yellow,     2],\n        [Lang.Blocks.DIABOARD_color_green,      3],\n        [Lang.Blocks.DIABOARD_color_cyan,       4],\n        [Lang.Blocks.DIABOARD_color_blue,       5],\n        [Lang.Blocks.DIABOARD_color_magenta,    6],\n        [Lang.Blocks.DIABOARD_color_white,      7],\n        [Lang.Blocks.DIABOARD_color_random,     8],\n    ];\n\n    let options_DIABOARD_sensor     = \n    [\n        [Lang.Blocks.DIABOARD_sensor_ir,            'ir'],\n        [Lang.Blocks.DIABOARD_sensor_brightness,    'brightness'],\n    ];\n\n    let options_DIABOARD_effect     =\n    [\n        [Lang.Blocks.DIABOARD_effect_flame,     'f'],\n        [Lang.Blocks.DIABOARD_effect_drop,      'd'],\n        [Lang.Blocks.DIABOARD_effect_glitter,   'g'],\n        [Lang.Blocks.DIABOARD_effect_dimming,   'm'],\n        [Lang.Blocks.DIABOARD_effect_random,    'r'],\n    ];\n\n    let options_DIABOARD_led        =\n    [\n        [ Lang.Blocks.DIABOARD_led_all,      0 ],\n        [ Lang.Blocks.DIABOARD_led_1,        1 ],\n        [ Lang.Blocks.DIABOARD_led_2,        2 ],\n        [ Lang.Blocks.DIABOARD_led_3,        3 ],\n        [ Lang.Blocks.DIABOARD_led_4,        4 ],\n        [ Lang.Blocks.DIABOARD_led_5,        5 ],\n        [ Lang.Blocks.DIABOARD_led_6,        6 ],\n        [ Lang.Blocks.DIABOARD_led_random,   7 ],\n    ];\n\n    let options_DIABOARD_motor      =\n    [\n        [Lang.Blocks.DIABOARD_motor_a,   'A'],\n        [Lang.Blocks.DIABOARD_motor_b,   'B'],\n        [Lang.Blocks.DIABOARD_motor_all, 'X'],\n    ];\n\n    let options_DIABOARD_dc_direction   =\n    [\n        [Lang.Blocks.DIABOARD_dc_direction_cw,  'CW'],\n        [Lang.Blocks.DIABOARD_dc_direction_ccw, 'CCW'],\n    ];\n\n    let options_DIABOARD_melody     =\n    [\n        [ Lang.Blocks.DIABOARD_melody_rising,        0 ],\n        [ Lang.Blocks.DIABOARD_melody_falling,       1 ],\n        [ Lang.Blocks.DIABOARD_melody_forelise,      2 ],\n        [ Lang.Blocks.DIABOARD_melody_tension,       3 ],\n        [ Lang.Blocks.DIABOARD_melody_connecting,    4 ],\n        [ Lang.Blocks.DIABOARD_melody_jumpup,        5 ],\n        [ Lang.Blocks.DIABOARD_melody_jumpdown,      6 ],\n        [ Lang.Blocks.DIABOARD_melody_birthday,      7 ],\n    ];\n\n    let options_DIABOARD_effect_sound   =\n    [\n        [ Lang.Blocks.DIABOARD_effect_sound_happy,              0 ],\n        [ Lang.Blocks.DIABOARD_effect_sound_sullen,             1 ],\n        [ Lang.Blocks.DIABOARD_effect_sound_sad,                2 ],\n        [ Lang.Blocks.DIABOARD_effect_sound_engery_gathering,   3 ],\n        [ Lang.Blocks.DIABOARD_effect_sound_laser_beam,         4 ],\n    ];\n\n    let options_DIABOARD_tonicsolfa     =\n    [\n        [Lang.Blocks.DIABOARD_tonicsolfa_do,         0],\n        [Lang.Blocks.DIABOARD_tonicsolfa_do_sharp,   1],\n        [Lang.Blocks.DIABOARD_tonicsolfa_re,         2],\n        [Lang.Blocks.DIABOARD_tonicsolfa_re_sharp,   3],\n        [Lang.Blocks.DIABOARD_tonicsolfa_mi,         4],\n        [Lang.Blocks.DIABOARD_tonicsolfa_fa,         5],\n        [Lang.Blocks.DIABOARD_tonicsolfa_fa_sharp,   6],\n        [Lang.Blocks.DIABOARD_tonicsolfa_sol,        7],\n        [Lang.Blocks.DIABOARD_tonicsolfa_sol_sharp,  8],\n        [Lang.Blocks.DIABOARD_tonicsolfa_la,         9],\n        [Lang.Blocks.DIABOARD_tonicsolfa_la_sharp,  10],\n        [Lang.Blocks.DIABOARD_tonicsolfa_si,        11],\n        [Lang.Blocks.DIABOARD_tonicsolfa_high_do,   12],\n        [Lang.Blocks.DIABOARD_tonicsolfa_rest,     100],\n    ];\n\n    let options_DIABOARD_tonicsolfa2    =\n    [\n        [Lang.Blocks.DIABOARD_tonicsolfa_do,         0],\n        [Lang.Blocks.DIABOARD_tonicsolfa_do_sharp,   1],\n        [Lang.Blocks.DIABOARD_tonicsolfa_re,         2],\n        [Lang.Blocks.DIABOARD_tonicsolfa_re_sharp,   3],\n        [Lang.Blocks.DIABOARD_tonicsolfa_mi,         4],\n        [Lang.Blocks.DIABOARD_tonicsolfa_fa,         5],\n        [Lang.Blocks.DIABOARD_tonicsolfa_fa_sharp,   6],\n        [Lang.Blocks.DIABOARD_tonicsolfa_sol,        7],\n        [Lang.Blocks.DIABOARD_tonicsolfa_sol_sharp,  8],\n        [Lang.Blocks.DIABOARD_tonicsolfa_la,         9],\n        [Lang.Blocks.DIABOARD_tonicsolfa_la_sharp,  10],\n        [Lang.Blocks.DIABOARD_tonicsolfa_si,        11],\n    ];\n\n    return {\n        //region \n        /**\n        diaboard_when_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                    position: {\n                        x: 0,\n                        y: 0\n                    }\n                },      \n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_button1,\n                    value: 'left',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_button2,\n                    value: 'pressed',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'diaboard_when_button_pressed',\n            },\n            paramsKeyMap: {\n                DUMMY:  0,\n                PORT:   1,     // left/right/all\n                STATUS: 2,     // pressed\n            },\n            class: 'event',\n            isNotFor: ['diaboard'],\n            event: 'diaboardSensorEventReceive',\n            func: function(sprite, script) {\n                let port    = script.getStringField('PORT');\n                let status  = script.getStringField('STATUS');\n                let leftButton      = ( Entry.hw.portData[ 'S1' ] == 'T' ? true : false );\n                let rightButton     = ( Entry.hw.portData[ 'S2' ] == 'T' ? true : false );\n                let buttonStatus    = ( status == 'pressed' ? true : false );\n                if ( port == 'all' ) {    // all\n                    if ( leftButton == buttonStatus && rightButton == buttonStatus ) {\n                        return script.callReturn();\n                    }\n                } else if( port == 'left' ) {\n                    if ( leftButton == buttonStatus ) {\n                        return script.callReturn();\n                    }\n                } else if( port == 'right' ) {\n                    if ( rightButton == buttonStatus ) {\n                        return script.callReturn();\n                    }\n                }\n                return this.die();\n            },\n            syntax: { js: [], py: ['Diaboard.when_button_pressed(%2,%3)'] },\n        },\n        diaboard_when_color_is: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                    position: {\n                        x: 0,\n                        y: 0\n                    }\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_color,\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'diaboard_when_color_is',\n            },\n            paramsKeyMap: {\n                DUMMY: 0,\n                COLOR: 1,     // red/yellow/green/cyan/blue/purple/white\n            },\n            class: 'event',\n            isNotFor: ['diaboard'],\n            event: 'diaboardSensorEventReceive',\n            func: function(sprite, script) {\n                let color   = script.getNumberField('COLOR');\n                let sensorColor = Entry.hw.portData[ 'S4' ];               // 컬러센서 값 범위 0 ~ 7\n                if( color == sensorColor ) {\n                    return script.callReturn();\n                } else {\n                    return this.die();\n                }\n            },\n            syntax: { js: [], py: ['Diaboard.when_color_is(%2)'] },\n        },\n        diaboard_when_sensor_is: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                    position: {\n                        x: 0,\n                        y: 0\n                    }\n                },                \n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_sensor,\n                    value: 'ir',\n                },\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: Entry.Diaboard.INEQ_SIGN,\n                    value: '<',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    }\n                ],\n                type: 'diaboard_when_sensor_is',\n            },\n            paramsKeyMap: {\n                DUMMY: 0,\n                SENSOR: 1,\n                INEQ_SIGN: 2,\n                VALUE: 3\n            },\n            class: 'event',\n            isNotFor: ['diaboard'],\n            event: 'diaboardSensorEventReceive',\n            func: function(sprite, script) {\n                let sensor      = script.getStringField('SENSOR');\n                let ineqSign    = script.getStringField('INEQ_SIGN');\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 0 : value;\n                if( sensor == 'ir' ) {\n                    let irValue     = Entry.hw.portData[ 'S6' ];\n                    if( ineqSign == '<' && irValue < value ) {\n                        return script.callReturn();\n                    } else if( ineqSign == '>' && irValue > value ) {\n                        return script.callReturn();\n                    } else if( ineqSign == '=' && irValue == value ) {\n                        return script.callReturn();\n                    } else {\n                        return this.die();\n                    }\n                } else if( sensor == 'brightness' ) {\n                    let brightnessValue     = Entry.hw.portData[ 'S8' ];\n                    if( ineqSign == '<' && brightnessValue < value ) {\n                        return script.callReturn();\n                    } else if( ineqSign == '>' && brightnessValue > value ) {\n                        return script.callReturn();\n                    } else if( ineqSign == '=' && brightnessValue == value ) {\n                        return script.callReturn();\n                    } else {\n                        return this.die();\n                    }\n                } else {\n                    return this.die();\n                }\n            },\n            syntax: { js: [], py: ['Diaboard.when_sensor_is(%2,%3,%4)'] },\n        },\n         */\n        // ---\n        diaboard_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_button1,\n                    value: 'left',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_button2,\n                    value: 'pressed',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'diaboard_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                STATUS: 1,\n            },\n            class: 'condition',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let port    = script.getStringField('PORT');\n                let status  = script.getStringField('STATUS');\n                let leftButton      = ( Entry.hw.portData[ 'S1' ] == 'T' ? true : false );\n                let rightButton     = ( Entry.hw.portData[ 'S2' ] == 'T' ? true : false );\n                let buttonStatus    = ( status == 'pressed' ? true : false );\n                if ( port == 'all' ) {    // all\n                    return ( leftButton == buttonStatus && rightButton == buttonStatus );\n                } else if( port == 'left' ) {\n                    return ( leftButton == buttonStatus );\n                } else if( port == 'right' ) {\n                    return ( rightButton == buttonStatus );\n                }\n                return false;\n            },\n            syntax: { js: [], py: ['Diaboard.button_pressed(%1,%2)'] },\n        },\n        diaboard_color_sensor_is: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_color,\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'diaboard_color_sensor_is',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'condition',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let color   = script.getNumberField('COLOR');\n                let sensorColor = Entry.hw.portData[ 'S4' ];               // 컬러센서 값 범위 0 ~ 7\n                if( color == sensorColor ) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: ['Diaboard.color_sensor_is(%1)'] },\n        },\n        diaboard_sensor_condition: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_sensor,\n                    value: 'ir',\n                },\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: Entry.Diaboard.INEQ_SIGN,\n                    value: '<',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    }\n                ],\n                type: 'diaboard_sensor_condition',\n            },\n            paramsKeyMap: {\n                SENSOR:     0,\n                INEQ_SIGN:  1,\n                VALUE:      2,\n            },\n            class: 'condition',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let sensor      = script.getStringField('SENSOR');\n                let ineqSign    = script.getStringField('INEQ_SIGN');\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 0 : value;\n                if( sensor == 'ir' ) {\n                    let irValue     = Entry.hw.portData[ 'S6' ];\n                    if( ineqSign == '<' && irValue < value ) {\n                        return true;\n                    } else if( ineqSign == '>' && irValue > value ) {\n                        return true;\n                    } else if( ineqSign == '=' && irValue == value ) {\n                        return true;\n                    } else {\n                        return false;\n                    }\n                } else if( sensor == 'brightness' ) {\n                    let brightnessValue     = Entry.hw.portData[ 'S8' ];\n                    if( ineqSign == '<' && brightnessValue < value ) {\n                        return true;\n                    } else if( ineqSign == '>' && brightnessValue > value ) {\n                        return true;\n                    } else if( ineqSign == '=' && brightnessValue == value ) {\n                        return true;\n                    } else {\n                        return false;\n                    }\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: ['Diaboard.sensor_condition(%1,%2,%3)'] },\n        },\n        diaboard_color_sensor_seven_hue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'diaboard_color_sensor_seven_hue',\n            },\n            paramsKeyMap: {\n            },\n            class: 'condition',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let sensorValue     = Entry.hw.portData[ 'S4' ];            // sensorValue can be 0 ~ 7\n                let colorName       = Entry.Diaboard.COLOR_TYPE[ sensorValue ];     // colorName can be red, blue, white and so on\n                return Lang.Blocks['DIABOARD_color_' + colorName];\n            },\n            syntax: { js: [], py: ['Diaboard.color_sensor_seven_hue()'] },\n        },\n        diaboard_color_sensor_one_hue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'diaboard_color_sensor_one_hue',\n            },\n            paramsKeyMap: {\n            },\n            class: 'condition',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let hue         = Entry.hw.portData[ 'C1' ];\n                // let saturation  = Entry.hw.portData[ 'C2' ];\n                // let intensity   = Entry.hw.portData[ 'C3' ];\n                return hue;\n            },\n            syntax: { js: [], py: ['Diaboard.color_sensor_one_hue()'] },\n        },\n        diaboard_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_sensor,\n                    value: 'ir',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'diaboard_sensor_value',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,      // IR/brightness\n            },\n            class: 'condition',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let sensor  = script.getStringField('SENSOR');\n                if( sensor == 'ir' ) {\n                    let irSensor    = Entry.hw.portData[ 'S5' ];\n                    let irValue     = Entry.hw.portData[ 'S6' ];\n                    return irValue;\n                } else if( sensor == 'brightness' ) {\n                    let brightnessSensor    = Entry.hw.portData[ 'S7' ];\n                    let brightnessValue     = Entry.hw.portData[ 'S8' ];\n                    return brightnessValue;\n                } else {\n                    return \"\";\n                }                \n            },\n            syntax: { js: [], py: ['Diaboard.sensor_value(%1)'] },\n        },\n        diaboard_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_sensor,\n                    value: 'ir',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                ],\n                type: 'diaboard_convert_scale',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n                VALUE3: 3,\n                VALUE4: 4,\n            },\n            class: 'condition',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let sensor  = script.getStringField('SENSOR');\n                let in_min  = script.getNumberValue('VALUE1');\n                let in_max  = script.getNumberValue('VALUE2');\n                let out_min = script.getNumberValue('VALUE3');\n                let out_max = script.getNumberValue('VALUE4');\n\n                in_min   = isNaN( in_min ) ? 0 : in_min;\n                in_max   = isNaN( in_min ) ? 0 : in_max;\n                out_min  = isNaN( in_min ) ? 0 : out_min;\n                out_max  = isNaN( in_min ) ? 0 : out_max;\n\n                if( sensor == 'ir' ) {\n                    let irSensor            = Entry.hw.portData[ 'S5' ];\n                    let irValue             = Entry.hw.portData[ 'S6' ];\n                    let v                   = (irValue - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;\n                    return v.toString();\n                } else if ( sensor == 'brightness' ) {\n                    let brightnessSensor    = Entry.hw.portData[ 'S7' ];\n                    let brightnessValue     = Entry.hw.portData[ 'S8' ];\n                    let v                   = (brightnessValue - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;\n                    return v.toString();\n                } else {\n                    return \"0\";\n                }       \n            },\n            syntax: {\n                js: [],\n                py: ['Diaboard.convert_scale(%1, %2, %3, %4, %5)'],\n            },\n        },\n        // ---\n        diaboard_led_rainbow: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'diaboard_led_rainbow',\n                id: 'i3je',\n            },\n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let effect = \"r\";   // rainbow\n                let color  = 0;\n                let time   = 0;       \n                let cmd = `l:p:${effect}:${color}:${time}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.led_rainbow()'] },\n        },\n        diaboard_led_rainbow_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null\n                ],\n                type: 'diaboard_led_rainbow_time',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                TIME: 0\n            },            \n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let effect  = \"r\";   // rainbow\n                let color   = 0;\n                let second  = script.getNumberValue('TIME');\n                second      = ( isNaN( second ) || second < 0 ) ? 0 : second;\n                let time    = second * 10;   // 입력 시간이 1.5초 라면 15로 세팅 (곱하기 10 해야함)\n                let cmd     = `l:p:${effect}:${color}:${time}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn, second * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.led_rainbow_time(%1)'] },\n        },\n        diaboard_led_effect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_effect,\n                    value: 'f',\n                },\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_color2,\n                    value: 1,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null\n                ],\n                type: 'diaboard_led_effect',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                EFFECT: 0,\n                COLOR: 1,\n            },\n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let effect  = script.getStringValue('EFFECT');\n                if( effect == Entry.Diaboard.EFFECT_RANDOM ) {\n                    // returns a random integer from 0 to 3\n                    let v = Math.floor(Math.random() * 4);          // 0 ~ 3\n                    effect  = Entry.Diaboard.EFFECT_TYPE[ v ];      // v can be 'f' ~ 'm'\n                }\n                let color   = script.getStringValue('COLOR');       // '1' ~ '8'\n                if( color == Entry.Diaboard.COLOR_RANDOM ) {        // '8'\n                    // returns a random integer from 1 to 7\n                    color   = Math.floor(Math.random() * 7) + 1;    // red(1) ~ white(7)\n                }\n                let time    = 0;\n                let cmd     = `l:p:${effect}:${color}:${time}`;     // l:p:d:5:50\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.led_effect(%1,%2)'] },\n        },\n        diaboard_led_effect_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_effect,\n                    value: 'f',\n                },\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_color2,\n                    value: 1,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },                    \n                    null\n                ],\n                type: 'diaboard_led_effect_time',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                EFFECT: 0,\n                COLOR: 1,\n                TIME: 2,\n            },\n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let effect  = script.getStringValue('EFFECT');\n                if( effect == Entry.Diaboard.EFFECT_RANDOM ) {\n                    // returns a random integer from 0 to 3\n                    let v = Math.floor(Math.random() * 4);          // 0 ~ 3\n                    effect  = Entry.Diaboard.EFFECT_TYPE[ v ];      // v can be 'f' ~ 'm'\n                }                    \n                let color   = script.getNumberValue('COLOR');\n                if( color == Entry.Diaboard.COLOR_RANDOM ) {        // '8'\n                    // returns a random integer from 1 to 7\n                    color   = Math.floor(Math.random() * 7) + 1;    // red(1) ~ white(7)\n                }                    \n                let second  = script.getNumberValue('TIME');       \n                second      = ( isNaN( second ) || second < 0 ) ? 0 : second;\n                let time    = second * 10;   // 입력 시간이 1.5초 라면 15로 세팅 (곱하기 10 해야함)\n                let cmd     = `l:p:${effect}:${color}:${time}`;     // l:p:d:5:50\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn, second * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.led_effect_time(%1,%2,%3)'] },\n        },\n        diaboard_led_six: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'diaboard_led_six',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                COLOR1: 0,\n                COLOR2: 1,\n                COLOR3: 2,\n                COLOR4: 3,\n                COLOR5: 4,\n                COLOR6: 5\n            },            \n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let color1  = script.getStringValue('COLOR1');\n                let red1    = parseInt(color1.substr(1, 2), 16);\n                let green1  = parseInt(color1.substr(3, 2), 16);\n                let blue1   = parseInt(color1.substr(5, 2), 16);\n\n                let color2  = script.getStringValue('COLOR2');\n                let red2    = parseInt(color2.substr(1, 2), 16);\n                let green2  = parseInt(color2.substr(3, 2), 16);\n                let blue2   = parseInt(color2.substr(5, 2), 16);\n\n                let color3  = script.getStringValue('COLOR3');\n                let red3    = parseInt(color3.substr(1, 2), 16);\n                let green3  = parseInt(color3.substr(3, 2), 16);\n                let blue3   = parseInt(color3.substr(5, 2), 16);\n\n                let color4  = script.getStringValue('COLOR4');\n                let red4    = parseInt(color4.substr(1, 2), 16);\n                let green4  = parseInt(color4.substr(3, 2), 16);\n                let blue4   = parseInt(color4.substr(5, 2), 16);\n\n                let color5  = script.getStringValue('COLOR5');\n                let red5    = parseInt(color5.substr(1, 2), 16);\n                let green5  = parseInt(color5.substr(3, 2), 16);\n                let blue5   = parseInt(color5.substr(5, 2), 16);\n\n                let color6  = script.getStringValue('COLOR6');\n                let red6    = parseInt(color6.substr(1, 2), 16);\n                let green6  = parseInt(color6.substr(3, 2), 16);\n                let blue6   = parseInt(color6.substr(5, 2), 16);\n\n                let cmd     = `l:a:${red1}:${green1}:${blue1}:${red2}:${green2}:${blue2}:${red3}:${green3}:${blue3}:${red4}:${green4}:${blue4}:${red5}:${green5}:${blue5}:${red6}:${green6}:${blue6}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.led_six(%1,%2,%3,%4,%5,%6)'] },\n        },\n        diaboard_led_one: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_led,\n                    value: '0',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'diaboard_led_one',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },            \n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let led     = script.getNumberValue('LED');\n                if( led == 7 ) {        // 7은 랜덤\n                    led     = Math.floor(Math.random() * 6) + 1;    // 1 ~ 6\n                }\n                let color   = script.getStringValue('COLOR');\n                let red     = parseInt(color.substr(1, 2), 16);\n                let green   = parseInt(color.substr(3, 2), 16);\n                let blue    = parseInt(color.substr(5, 2), 16);\n                let time    = 0;\n                let cmd     = `l:c:${led}:${red}:${green}:${blue}:${time}`; // l:c:0:255:255:255:1\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.led_one(%1,%2)'] },\n        },\n        diaboard_led_one_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_led,\n                    value: 0,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },                    \n                ],\n                type: 'diaboard_led_one_time',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n                TIME: 2,\n            },            \n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let led     = script.getNumberValue('LED');\n                if( led == 7 ) {        // 7은 랜덤\n                    led     = Math.floor(Math.random() * 6) + 1;    // 1 ~ 6\n                }\n                let color   = script.getStringValue('COLOR');\n                let red     = parseInt(color.substr(1, 2), 16);\n                let green   = parseInt(color.substr(3, 2), 16);\n                let blue    = parseInt(color.substr(5, 2), 16);\n                let second  = script.getNumberValue('TIME');       \n                second      = ( isNaN( second ) || second < 0 ) ? 0 : second;\n                let time    = second * 10;   // 입력 시간이 1.5초 라면 15로 세팅 (곱하기 10 해야함)\n                let cmd     = `l:c:${led}:${red}:${green}:${blue}:${time}`; // l:c:0:255:255:255:1\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn, second * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.led_one_time(%1,%2,%3)'] },\n        },\n\n        diaboard_led_hue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_led,\n                    value: 0,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null\n                ],\n                type: 'diaboard_led_hue',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                HUE: 1,\n            },            \n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let led     = script.getNumberValue('LED');\n                if( led == 7 ) {        // 7은 랜덤\n                    led     = Math.floor(Math.random() * 6) + 1;    // 1 ~ 6\n                }\n\n                let hue     = script.getNumberValue('HUE');\n                hue         = ( isNaN( hue ) || hue < 0 ) ? 0 : hue;\n                hue         = Math.floor( hue % 360 );  // 0 ~ 359 범위로 조정하기\n                let r_value = 0;\n                let g_value = 0;\n                let b_value = 0;\n                if (hue <= 120) {\n                    r_value = 120 - hue;\n                    g_value = hue;\n                    b_value = 0;\n                }\n                else if (hue <= 240) {\n                    r_value = 0;\n                    g_value = 240 - hue;\n                    b_value = hue - 120;\n                } else {\n                    r_value = hue - 240;\n                    g_value = 0;\n                    b_value = 360 - hue;\n                }\n                let time    = 0;\n                let cmd     = `l:c:${led}:${r_value}:${g_value}:${b_value}:${time}`; // l:x:c:255:255:255:1\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.led_hue(%1,%2)'] },\n        },\n        diaboard_led_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_led,\n                    value: 0,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'diaboard_led_color',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                LED: 0\n            },            \n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let led = script.getNumberValue('LED');\n                if( led == 7 ) {        // 7은 랜덤\n                    led     = Math.floor(Math.random() * 6) + 1;    // 1 ~ 6\n                }\n                // ============================================================\n                let sensorValue = Entry.hw.portData[ 'S4' ];            // sensorValue can be 0 ~ 7\n                let COLOR_MAP   = {\n                    0: \"#000000\",        // 'no_color'\n                    1: \"#FF0000\",        // 'red'\n                    2: \"#FFFF00\",        // 'yellow'\n                    3: \"#008000\",        // 'green'\n                    4: \"#00FFFF\",        // 'cyan'\n                    5: \"#0000FF\",        // 'blue'\n                    6: \"#FF00FF\",        // 'magenta'\n                    7: \"#FFFFFF\"         // 'white'\n                };\n        \n                let color   = COLOR_MAP[ sensorValue ];\n                let red     = parseInt(color.substr(1, 2), 16);\n                let green   = parseInt(color.substr(3, 2), 16);\n                let blue    = parseInt(color.substr(5, 2), 16);\n                let time    = 0;\n                let cmd     = `l:c:${led}:${red}:${green}:${blue}:${time}`; // l:c:0:255:255:255:1\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.led_color(%1)'] },\n        },        \n        diaboard_led_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_led,\n                    value: 0,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },                    \n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },                    \n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },                    \n                ],\n                type: 'diaboard_led_rgb',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },            \n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let led     = script.getNumberValue('LED');\n                if( led == 7 ) {        // 7은 랜덤\n                    led     = Math.floor(Math.random() * 6) + 1;    // 1 ~ 6\n                }\n                let red     = script.getNumberValue('RED');\n                let green   = script.getNumberValue('GREEN');\n                let blue    = script.getNumberValue('BLUE');\n                red         = Math.max(Math.min(red,   255), 0);\n                green       = Math.max(Math.min(green, 255), 0);\n                blue        = Math.max(Math.min(blue,  255), 0);\n                let time    = 0;\n                let cmd     = `l:c:${led}:${red}:${green}:${blue}:${time}`; // l:x:c:255:255:255:1\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.led_rgb(%1,%2,%3,%4)'] },\n        },\n        diaboard_led_turn_off_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_led,\n                    value: 0,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'diaboard_led_turn_off_all',\n                id: 'i3je',\n            },\n            paramsKeyMap: {\n                LED: 0\n            },            \n            class: 'led',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let led = script.getNumberValue('LED');\n                if( led == 7 ) {        // 7은 랜덤\n                    led     = Math.floor(Math.random() * 6) + 1;    // 1 ~ 6\n                }\n                let cmd = `l:x:${led}`;        // l:x:0\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.led_turn_off_all(%1)'] },\n        },\n        // ---\n        diaboard_servomotor_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_motor,\n                    value: 'A'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_servomotor_angle',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let motor       = script.getStringValue('MOTOR');\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 0 : value;\n                let type        = \"S\";      // servo motor\n                let endAngle    = Math.max( Math.min(value, 180), 0 );      \n                let startAngle  = 0;\n                let time        = 0;\n                let cmd         = `m:${motor}:${type}:${endAngle}:${startAngle}:${time}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.servomotor_angle(%1, %2)'] },\n        },\n        diaboard_servomotor_angle_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_motor,\n                    value: 'A'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['180'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_servomotor_angle_time',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n                TIME: 3\n            },\n            class: 'motor',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let motor       = script.getStringValue('MOTOR');\n                let value1      = script.getNumberValue('VALUE1');\n                value1          = isNaN( value1 ) ? 0 : value1;\n                let value2      = script.getNumberValue('VALUE2');\n                value2          = isNaN( value2 ) ? 0 : value2;\n                let second      = script.getNumberValue('TIME');\n                second          = ( isNaN( second ) || second < 0 ) ? 0 : second;\n                let type        = \"S\";      // servo motor\n                let startAngle  = Math.max( Math.min(value1, 180), 0 );\n                let endAngle    = Math.max( Math.min(value2, 180), 0 );\n                let time        = second * 10;\n                let cmd         = `m:${motor}:${type}:${endAngle}:${startAngle}:${time}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn, second * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.servomotor_angle_time(%1,%2,%3,%4)'] },\n        },\n        diaboard_dc_direction_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_motor,\n                    value: 'A'\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_dc_direction,\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_dc_direction_speed',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n            },\n            class: 'motor',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let motor       = script.getStringValue('MOTOR');\n                let direction   = script.getStringValue('DIRECTION');\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 0 : value;\n                let time        = 0;\n                let type        = \"D\";      // db motor\n                let speed       = Math.max( Math.min(value, 100), 0 );\n                if( direction == 'CCW' ) {\n                    speed = -1 * speed;\n                }\n                let cmd         = `m:${motor}:${type}:${speed}:${time}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.dc_direction_speed(%1, %2, %3)'] },\n        },\n        diaboard_dc_direction_speed_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_motor,\n                    value: 'A'\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_dc_direction,\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_dc_direction_speed_time',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n                TIME: 3,\n            },\n            class: 'motor',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let motor       = script.getStringValue('MOTOR');\n                let direction   = script.getStringValue('DIRECTION');\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 0 : value;\n                let second      = script.getNumberValue('TIME');\n                second          = ( isNaN( second ) || second < 0 ) ? 0 : second;\n                let type        = \"D\";      // db motor\n                let speed       = Math.max( Math.min(value, 100), 0 );\n                if( direction == 'CCW' ) {\n                    speed = -1 * speed;\n                }\n                let time        = second * 10;\n                let cmd         = `m:${motor}:${type}:${speed}:${time}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn, second * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.dc_direction_speed_time(%1,%2,%3,%4)'] },\n        },\n        diaboard_dc_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_motor,\n                    value: 'A'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_dc_speed',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                VALUE: 1,\n            },\n            class: 'motor',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let motor       = script.getStringValue('MOTOR');\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 0 : value;\n                let time        = 0;\n                let type        = \"D\";      // db motor\n                let speed       = Math.max( Math.min(value, 100), -100 );\n                let cmd         = `m:${motor}:${type}:${speed}:${time}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.dc_speed(%1, %2)'] },\n        },\n        diaboard_dc_speed_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_motor,\n                    value: 'A'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_dc_speed_time',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                VALUE: 1,\n                TIME: 2\n            },\n            class: 'motor',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let motor       = script.getStringValue('MOTOR');\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 0 : value;\n                let second      = script.getNumberValue('TIME');\n                second          = ( isNaN( second ) || second < 0 ) ? 0 : second;\n                let type        = \"D\";      // db motor\n                let speed       = Math.max( Math.min(value, 100), -100 );\n                let time        = second * 10;\n                let cmd         = `m:${motor}:${type}:${speed}:${time}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn, second * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.dc_speed_time(%1,%2,%3)'] },\n        },\n        diaboard_turn_off_all_motors: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    options: options_DIABOARD_motor,\n                    value: 'A'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'diaboard_turn_off_all_motors',\n            },\n            paramsKeyMap: {\n                MOTOR: 0\n            },\n            class: 'motor',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let motor   = script.getStringValue('MOTOR');\n                motor       = motor.toLowerCase();\n                let cmd     = `m:${motor}`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.turn_off_all_motors(%1)'] },\n        },\n        // ---\n        diaboard_buzzer_melody_type: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_melody,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'diaboard_buzzer_melody_type',\n            },\n            paramsKeyMap: {\n                MELODY: 0\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let melodyIndex = script.getNumberValue('MELODY');\n                let melodyItem  = Entry.Diaboard.MELODY_TYPE[ melodyIndex ];\n                let gap         = melodyItem.gap;\n                let commands    = melodyItem.commands;\n                let totalMs     = commands.length * gap;        // gap은 ms\n                for( let index = 0; index < commands.length; index++ ) {\n                    let cmd = commands[ index ];\n                    if( index == 0 ) {\n                        Entry.Diaboard.fireCommand( cmd );\n                    } else {\n                        setTimeout( () => {\n                            Entry.Diaboard.fireCommand( cmd );\n                        }, index * gap );\n                    }\n                }\n                return Entry.Diaboard.deferredReturn( script.callReturn, totalMs );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_melody_type(%1)'] },\n        },\n        diaboard_buzzer_effect_type: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_effect_sound,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'diaboard_buzzer_effect_type',\n            },\n            paramsKeyMap: {\n                EFFECT: 0\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let effectIndex = script.getNumberValue('EFFECT');\n                if( effectIndex == 0 ) {\n                    // 1. 신바람\n                    let command     = \"n\";\n                    let inc         = 0;\n                    let delay       = 20;\n                    let time        = 5;    \n                    for( let i = 0; i <= 50; i++ ) {\n                        let setNote = 0;\n                        if ( parseInt( i / 5 ) == 0) setNote = i * 2;\n                        else if ( parseInt( i / 5 ) == 1 ) setNote = i * 3;\n                        else if ( parseInt( i / 5 ) == 2 ) setNote = i * 4;\n                        else if ( parseInt( i / 5 ) == 3 ) setNote = i * 2;\n                        else if ( parseInt( i / 5 ) == 4 ) setNote = i * 4;\n                        else if ( parseInt( i / 5 )  > 4 ) setNote = i * 2;\n\n                        setNote         = setNote + 20;\n                        let note        = setNote;\n                        let cmd         = `b:${command}:${note}:${time}`;               // buzzer : comman n(노트) : 노트번호 : 시간( 100 = 1초 = 1000ms )\n                        if( i == 0 ) {\n                            Entry.Diaboard.fireCommand( cmd );\n                        } else {\n                            setTimeout( () => {\n                                Entry.Diaboard.fireCommand( cmd );\n                            }, delay * inc );                // every 20ms\n                        }\n                        inc += 1;\n                    }\n                    let totalSecond = inc * delay + Entry.Diaboard.EFFECT_DEFAULT_SLEEP;  // delay 단위는 ms \n                    return Entry.Diaboard.deferredReturn( script.callReturn, totalSecond );\n                } else if( effectIndex == 1 ) {\n                    // 2. 시무룩\n                    let command     = \"f\";    \n                    let time        = 1;\n                    let inc         = 0;\n                    let delay       = 20;\n                    for( let i = 0; i < 10; i++ ) {\n                        let freq    = i * 4 + 240;\n                        let cmd     = `b:${command}:${freq}:${time}`;\n                        if( inc == 0 ) {\n                            Entry.Diaboard.fireCommand( cmd );\n                        } else {\n                            setTimeout( () => {\n                                Entry.Diaboard.fireCommand( cmd );\n                            }, delay * inc );        // every 20ms\n                        }\n                        inc += 1;\n                    }\n                    for( let i = 10 ; i >= 0; i-- ) {\n                        let freq    = i * 4 + 240;\n                        let cmd     = `b:${command}:${freq}:${time}`;\n                        setTimeout( () => {\n                            Entry.Diaboard.fireCommand( cmd );\n                        }, delay * inc );       // every 20ms\n                        inc += 1;\n                    }\n                    let totalSecond = inc * delay + Entry.Diaboard.EFFECT_DEFAULT_SLEEP;  // delay 단위는 ms \n                    return Entry.Diaboard.deferredReturn( script.callReturn, totalSecond );\n                } else if( effectIndex == 2 ) {\n                    // 3. 슬픔\n                    let command     = \"f\";    \n                    let time        = 1;\n                    let inc         = 0;\n                    let delay       = 20;\n                    for( let i = 0; i < 15; i++ ) {\n                        let freq    =   i * 7 + 900;\n                        let cmd     = `b:${command}:${freq}:${time}`;\n                        if( inc == 0 ) {\n                            Entry.Diaboard.fireCommand( cmd );\n                        } else {\n                            setTimeout( () => {\n                                Entry.Diaboard.fireCommand( cmd );\n                            }, delay * inc );              // every 20ms\n                        }\n                        inc += 1;\n                    }\n                    for( let i = 15; i >= 0; i-- ) {\n                        let freq    =   i * 7 + 900;\n                        let cmd     = `b:${command}:${freq}:${time}`;\n                        setTimeout( () => {\n                            Entry.Diaboard.fireCommand( cmd );\n                        }, delay * inc );        // every 20ms\n                        inc += 1;\n                    }\n                    let totalSecond = inc * delay + Entry.Diaboard.EFFECT_DEFAULT_SLEEP;  // delay 단위는 ms \n                    return Entry.Diaboard.deferredReturn( script.callReturn, totalSecond );\n                } else if( effectIndex == 3 ) {\n                    // 4. 에너지 모으는\n                    let command     = \"f\";\n                    let time        = 1;\n                    let inc         = 0;\n                    let delay       = 20;\n                    for( let i = 0; i <= 70; i++ ) {\n                        let freq    = 0;\n                        if ( i <= 51 ) {\n                            freq    = i * 45;   // 최대 2295 (=51 * 45)\n                        } else {\n                            freq    = 2380;     // 최대 2380 ( 52 ~ 70 )\n                        }\n                        let cmd     = `b:${command}:${freq}:${time}`;\n                        if( i == 0 ) {\n                            Entry.Diaboard.fireCommand( cmd );\n                        } else {\n                            setTimeout( () => {\n                                Entry.Diaboard.fireCommand( cmd );\n                            }, delay * inc );        // every 20ms\n                        }\n                        inc += 1;\n                    }\n                    let totalSecond = inc * delay + Entry.Diaboard.EFFECT_DEFAULT_SLEEP;  // delay 단위는 ms \n                    return Entry.Diaboard.deferredReturn( script.callReturn, totalSecond );\n                } else if( effectIndex == 4 ) {\n                    // 5. 레이저빔\n                    let command     = \"n\";\n                    let time        = 1;\n                    let inc         = 0;\n                    let delay       = 20;\n                    for( let i = 20; i >= 0; i-- ) {\n                        let freq    = i * 4 + 10;\n                        let cmd     = `b:${command}:${freq}:${time}`;\n                        if( i == 20 ) {\n                            Entry.Diaboard.fireCommand( cmd );\n                        } else {\n                            setTimeout( () => {\n                                Entry.Diaboard.fireCommand( cmd );\n                            }, delay * inc );                // every 20ms\n                        }\n                        inc += 1;\n                    }\n                    let totalSecond = inc * delay + Entry.Diaboard.EFFECT_DEFAULT_SLEEP;  // delay 단위는 ms \n                    return Entry.Diaboard.deferredReturn( script.callReturn, totalSecond );\n                } else {\n                    // invalid effectIndex\n                    return Entry.Diaboard.deferredReturn( script.callReturn );\n                }\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_effect_type(%1)'] },\n        },\n        diaboard_buzzer_eight_melody_bpm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    null,\n                    null,\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['120'],\n                    },\n                    null\n                ],\n                type: 'diaboard_buzzer_eight_melody_bpm',\n            },\n            paramsKeyMap: {\n                TONICSOLFA_1: 0,\n                TONICSOLFA_2: 1,\n                TONICSOLFA_3: 2,\n                TONICSOLFA_4: 3,\n                TONICSOLFA_5: 4,\n                TONICSOLFA_6: 5,\n                TONICSOLFA_7: 6,\n                TONICSOLFA_8: 7,\n                BPM: 8\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let tonicsolfaItems = [\n                    script.getNumberValue('TONICSOLFA_1'),\n                    script.getNumberValue('TONICSOLFA_2'),\n                    script.getNumberValue('TONICSOLFA_3'),\n                    script.getNumberValue('TONICSOLFA_4'),\n                    script.getNumberValue('TONICSOLFA_5'),\n                    script.getNumberValue('TONICSOLFA_6'),\n                    script.getNumberValue('TONICSOLFA_7'),\n                    script.getNumberValue('TONICSOLFA_8')\n                ];\n                let bpm         = script.getNumberValue('BPM');\n                bpm             = isNaN( bpm ) ? 120 : bpm;                         // 유효하지 않은 값은 120bpm으로 설정\n                bpm             = Math.max( Math.min( bpm, 300 ), 30);             // bpm은 30 ~ 300\n                let second      = Entry.Diaboard.convertTimeByBPM( bpm, 0.5 );      // 리턴 단위 초, ( bpm, 박자 )\n                let totalSecond = second * 8;\n                let octave      = 4;                                                // 기본값 4 옥타브\n                let command     = \"n\";    \n                for( let index = 0; index < tonicsolfaItems.length; index++ ) {\n                    let tonicsolfa  = tonicsolfaItems[ index ];\n                    let note        = ( tonicsolfa == 100 ) ? 96 : ( ( octave - 1 ) * 12 + tonicsolfa );        // 100은 무음 (note 번호 96은 무음 (박자 쉬기 블록일 때))\n                    let time        = second * 100;                                 // 메세지 시간 세팅 시 ( 초 * 100 )\n                    let cmd         = `b:${command}:${note}:${time}`;               // buzzer : comman n(노트) : 노트번호 : 시간\n                    if( index == 0 ) {\n                        Entry.Diaboard.fireCommand( cmd );\n                    } else {\n                        setTimeout( () => {\n                            Entry.Diaboard.fireCommand( cmd );\n                        }, ( second * 1000 ) * index );\n                    }\n                }\n                return Entry.Diaboard.deferredReturn( script.callReturn, totalSecond * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_eight_melody_bpm(%1,%2,%3,%4,%5,%6,%7,%8,%9,%10)'] },\n        },\n        diaboard_buzzer_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: Entry.Diaboard.OCTAVE_TYPE,\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa2,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'diaboard_buzzer_octave',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                TONICSOLFA: 1\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let octave      = script.getNumberValue('OCTAVE');\n                let tonicsolfa  = script.getNumberValue('TONICSOLFA');\n                let command     = \"n\";    \n                let note        = ( octave - 1 ) * 12 + tonicsolfa;     // 프로토콜 인자값 ( 0 ~ 11 )\n                let stdFreq     = Entry.Diaboard.STANDARD_FREQ[ note ]; // 프로토콜 인자값으로 표준주파수값을 가져온다\n                Entry.Diaboard.setFrequency( Math.ceil( stdFreq ) );    // 표준주파수값을 저장한다. \n                let time        = 0;\n                let cmd         = `b:${command}:${note}:${time}`;       // buzzer : comman n(노트) : 노트번호 : 시간\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_octave(%1,%2)'] },\n        },\n        diaboard_buzzer_octave_rhythm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: Entry.Diaboard.OCTAVE_TYPE,\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: options_DIABOARD_tonicsolfa2,\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: Entry.Diaboard.RHYTHM_TYPE,\n                    value: 0.5,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,                    \n                    null,\n                ],\n                type: 'diaboard_buzzer_octave_rhythm',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                TONICSOLFA: 1,\n                RHYTHM: 2,\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let octave      = script.getNumberValue('OCTAVE');\n                let tonicsolfa  = script.getNumberValue('TONICSOLFA');\n                let rhythm      = script.getNumberValue('RHYTHM');\n                let command     = \"n\";    \n                let note        = ( octave - 1 ) * 12 + tonicsolfa;\n                let stdFreq     = Entry.Diaboard.STANDARD_FREQ[ note ];         // 프로토콜 인자값으로 표준주파수값을 가져온다\n                Entry.Diaboard.setFrequency( Math.ceil( stdFreq ) );            // 표준주파수값을 저장한다. \n                let second      = Entry.Diaboard.convertTimeForBPM( rhythm );   // 초\n                let time        = second * 100;                                 // 메세지 시간 세팅 시 ( 초 * 100 )\n                let cmd         = `b:${command}:${note}:${time}`;               // buzzer : comman n(노트) : 노트번호 : 시간\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn, second * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_octave_rhythm(%1,%2,%3)'] },\n        },\n        diaboard_buzzer_hz: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_buzzer_hz',\n            },\n            paramsKeyMap: {\n                VALUE: 0\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 60 : Math.round( value );    // 유효하지 않은 값은, 60로 처리\n                let command     = \"f\";    \n                let freq        = Math.max( Math.min( value, 8000 ), 32);   // 주파수는 32~8000hz 범위로 보내기 \n                Entry.Diaboard.setFrequency( freq );\n                let time        = 0;\n                let cmd         = `b:${command}:${freq}:${time}`;   // buzzer : comman n(노트) : 노트번호 : 시간\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_hz(%1)'] },\n        },\n        diaboard_buzzer_hz_change: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_buzzer_hz_change',\n            },\n            paramsKeyMap: {\n                VALUE: 0\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let value       = script.getNumberValue('VALUE');\n                value           = isNaN( value ) ? 0 : Math.round( value );                     // 유효하지 않은 값은, 0으로 설정\n                let command     = \"f\";    \n                let diffFreq    = Math.max( Math.min( value, 8000 - 32 ), ( -8000 + 32 ) );     // 주파수 변화 값 -7968 ~ 7968\n                let freq        = Entry.Diaboard.getFrequency() + diffFreq;\n                Entry.Diaboard.setFrequency( freq );\n                let time        = 0;\n                let cmd         = `b:${command}:${freq}:${time}`;   // buzzer : comman n(노트) : 노트번호 : 시간\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_hz_change(%1)'] },\n        },\n        diaboard_buzzer_speed_bpm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['120'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_buzzer_speed_bpm',\n            },\n            paramsKeyMap: {\n                VALUE: 0\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let value   = script.getNumberValue('VALUE');\n                value       = isNaN( value ) ? 120 : Math.round( value );       // 유효하지 않은 값은 120\n                let bpm     = Math.max(Math.min( value, 300 ), 30 );            // BPM 범위는 30 ~ 300\n                Entry.Diaboard.setBPM( bpm );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_speed_bpm(%1)'] },\n        },\n        diaboard_buzzer_speed_bpm_change: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'diaboard_buzzer_speed_bpm_change',\n            },\n            paramsKeyMap: {\n                VALUE: 0\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let value   = script.getNumberValue('VALUE');\n                value       = isNaN( value ) ? 120 : Math.round( value );       // 유효하지 않은 값은 120\n                let newVal  = Entry.Diaboard.getBPM() + value;\n                let bpm     = Math.max( Math.min( newVal, 300 ), 30 );          // BPM 범위는 30 ~ 300\n                Entry.Diaboard.setBPM( bpm );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_speed_bpm_change(%1)'] },\n        },\n        diaboard_buzzer_sleep_rhythm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: Entry.Diaboard.RHYTHM_TYPE,\n                    value: 0.25,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'diaboard_buzzer_sleep_rhythm',\n            },\n            paramsKeyMap: {\n                RHYTHM: 0\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let rhythm      = script.getNumberValue('RHYTHM');\n                let second      = Entry.Diaboard.convertTimeForBPM( rhythm );   // 초\n                let time        = second * 100;                                 // 메세지 시간 세팅 시 ( 초 * 100 )\n                let cmd         = `b:n:96:${time}`;                             // 96은 무음 (박자 쉬기 블록일 때)\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn, second * 1000 );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_sleep_rhythm(%1)'] },\n        },\n        diaboard_buzzer_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'diaboard_buzzer_stop',\n            },\n            paramsKeyMap: {\n                VALUE: 0\n            },\n            class: 'buzzer',\n            isNotFor: ['diaboard'],\n            func: function(sprite, script) {\n                let cmd         = `b:x`;\n                Entry.Diaboard.fireCommand( cmd );\n                return Entry.Diaboard.deferredReturn( script.callReturn );\n            },\n            syntax: { js: [], py: ['Diaboard.buzzer_stop(%1)'] },\n        },\n        //endregion Diaboard 비트브릭\n    };\n};\n// 언어 적용\nEntry.Diaboard.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            template: {\n                // 이벤트\n                diaboard_when_button_pressed:\t\t'%1 %2 버튼이 %3 일 때',\n                diaboard_when_color_is:\t\t\t\t'%1 컬러센서 색상이 %2 일 때',\n                diaboard_when_sensor_is:\t\t\t'%1 %2 값 %3 %4 일 때',\n                // 센서/버튼 2\n                diaboard_button_pressed:\t\t\t'%1 버튼이 %2 인가?',\n                diaboard_color_sensor_is:\t\t    '컬러센서의 색상이 %1 인가?',\n                diaboard_sensor_condition:\t\t\t'%1 값 %2 %3 인가?',\n                diaboard_color_sensor_seven_hue:    '컬러센서 색상(7가지)',\n                diaboard_color_sensor_one_hue:\t\t'컬러센서 색상(hue)',\n                diaboard_sensor_value:\t\t\t\t'%1 값',\n                diaboard_convert_scale:\t\t\t\t'변환 %1 값 %2 ~ %3 에서 %4 ~ %5',\n                // 엘이디\n                diaboard_led_rainbow:\t\t\t\t'엘이디 무지개 효과를 켜기',\n                diaboard_led_rainbow_time:\t\t\t'엘이디 무지개 효과를 %1초 동안 켜기 %2',\n                diaboard_led_effect:\t\t\t\t'엘이디 %1 효과를 %2 (으)로 켜기 %3',\n                diaboard_led_effect_time:\t\t\t'엘이디 %1 효과를 %2 (으)로 %3 초 동안 켜기 %4',\n                diaboard_led_six:\t\t\t\t    '엘이디 %1 %2 %3 %4 %5 %6 (으)로 켜기 %7',\n                diaboard_led_one:\t\t\t\t    '엘이디 %1 (을)를 %2 (으)로 켜기 %3',\n                diaboard_led_one_time:\t\t\t\t'엘이디 %1 (을)를 %2 (으)로 %3 초 동안 켜기 %4',\n                diaboard_led_hue:\t\t\t\t    '엘이디 %1 (을)를 색상(hue) %2 (으)로 켜기 %3',\n                diaboard_led_color:\t\t\t\t    '엘이디 %1 (을)를 컬러센서 색상(7가지)로 켜기 %2',\n                diaboard_led_rgb:\t\t\t\t    '엘이디 %1 (을)를 빨강 %2 녹색 %3 파랑 %4 (으)로 켜기 %5',\n                diaboard_led_turn_off_all:\t\t\t'엘이디 %1 끄기 %2',\n                // 모터\n                diaboard_servomotor_angle:\t\t\t'서보모터 %1 각도 %2 %3',\n                diaboard_servomotor_angle_time:\t\t'서보모터 %1 각도 %2 ~ %3 범위를 %4 초 동안 동작 %5',\n                diaboard_dc_direction_speed:\t\t'디씨모터 %1 %2 방향 속력 %3 %4',\n                diaboard_dc_direction_speed_time:\t'디씨모터 %1 %2 방향 속력 %3 (으)로 %4 초 동안 동작 %5',\n                diaboard_dc_speed:\t\t\t\t    '디씨모터 %1 속도 %2 %3',\n                diaboard_dc_speed_time:\t\t\t\t'디씨모터 %1 속도 %2 (으)로 %3 초 동안 동작 %4',\n                diaboard_turn_off_all_motors:\t\t'모터 %1 멈추기 %2',\n                // 버저\n                diaboard_buzzer_melody_type:\t\t'%1 멜로디 연주하기 %2',\n                diaboard_buzzer_effect_type:\t\t'%1 효과음 내기 %2',\n                diaboard_buzzer_eight_melody_bpm:\t'%1 %2 %3 %4 %5 %6 %7 %8 멜로디를 %9 BPM으로 연주하기 %10',\n                diaboard_buzzer_octave:\t\t\t\t'%1 옥타브 %2 음을 연주하기 %3',\n                diaboard_buzzer_octave_rhythm:\t\t'%1 옥타브 %2 음을 %3 박자 연주하기 %4',\n                diaboard_buzzer_hz:\t\t\t\t    '버저 음을 %1 Hz로 연주하기 %2',\n                diaboard_buzzer_hz_change:\t\t\t'버저 음을 %1 Hz 만큼 바꾸기 %2',\n                diaboard_buzzer_speed_bpm:\t\t\t'연주 속도를 %1 BPM으로 정하기 %2',\n                diaboard_buzzer_speed_bpm_change:\t'연주 속도를 %1 BPM만큼 바꾸기 %2',\n                diaboard_buzzer_sleep_rhythm:\t\t'%1 박자 쉬기',\n                diaboard_buzzer_stop:\t\t\t\t'버저음 멈추기',\n            },\n            Helper: {\n                diaboard_when_button_pressed:       \"선택한 버튼을 누르거나 누르지 않으면 아래에 연결된 블록들을 실행합니다.\",\n                diaboard_when_color_is:\t\t\t\t\"선택한 색상을 컬러센서가 감지하면 아래에 연결된 블록들을 실행합니다.\",\n                diaboard_when_sensor_is:\t\t\t\"선택한 센서의 값과 오른쪽의 값을 비교하여 아래에 연결된 블록들을 실행합니다.\\n< : 센서값이 오른쪽 값보다 작은 경우 '참'으로 판단합니다.\\n> : 센서값이 오른쪽 값보다 큰 경우 '참'으로 판단합니다.\\n= : 센서값이 오른쪽 값과 같은 경우 '참'으로 판단합니다.\",\n                diaboard_button_pressed:\t\t\t\"선택한 버튼을 누르거나 누르지 않은 경우 '참'으로 판단합니다.\",\n                diaboard_color_sensor_is:\t\t\t\"선택한 색상을 컬러센서가 감지한 경우 '참'으로 판단합니다.\",\n                diaboard_sensor_condition:\t\t\t\"선택한 센서의 값과 오른쪽의 값을 비교합니다.\\n< : 센서값이 오른쪽 값보다 작은 경우 '참'으로 판단합니다.\\n> : 센서값이 오른쪽 값보다 큰 경우 '참'으로 판단합니다.\\n= : 센서값이 오른쪽 값과 같은 경우 '참'으로 판단합니다.\",\n                diaboard_color_sensor_seven_hue:\t\"컬러센서가 감지하는 색상을 7가지로 분류한 값입니다.\\n7가지 색상 : 빨강, 노랑, 녹색, 청록, 파랑, 보라, 하양\",\n                diaboard_color_sensor_one_hue:\t\t\"컬러센서가 감지한 색상값입니다.\\n색상(hue) : 0 ~ 359 사이 범위로 설정할 수 있습니다.\\n(총 360가지의 색상을 감지하며 360과 0은 같은 색으로 표현됩니다.)\",\n                diaboard_sensor_value:\t\t\t\t\"선택한 센서가 감지한 값입니다. 값의 범위는 0 ~ 1023입니다. \\n적외선 센서 : 물체에 반사된 적외선을 양을 측정하여 물체와의 거리를 감지합니다.\\n밝기 센서 : 주변 환경이 얼마나 밝고 어두운지를 감지합니다.\",\n                diaboard_convert_scale:\t\t\t\t\"선택한 센서가 감지한 값의 범위를 사용자가 임의로 바꿔서 사용합니다.\\n적외선 센서 : 물체에 반사된 적외선을 양을 측정하여 물체와의 거리를 감지합니다.\\n밝기 센서 : 주변 환경이 얼마나 밝고 어두운지를 감지합니다.\",\n                diaboard_led_rainbow:\t\t\t\t\"엘이디를 무지개 효과로 켭니다.\",\n                diaboard_led_rainbow_time:\t\t\t\"엘이디를 입력한 시간만큼 무지개 효과로 켭니다.\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.\",\n                diaboard_led_effect:\t\t\t\t\"엘이디를 선택한 효과와 선택한 색상으로 켭니다.\",\n                diaboard_led_effect_time:\t\t\t\"엘이디를 입력한 시간만큼 선택한 효과와 선택한 색상으로 켭니다.\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.\",\n                diaboard_led_six:\t\t\t\t\t\"엘이디 1번 ~ 6번을 선택한 색상으로 각자 켭니다.\",\n                diaboard_led_one:\t\t\t\t\t\"선택한 번호의 엘이디를 선택한 색상으로 켭니다.\",\n                diaboard_led_one_time:\t\t\t\t\"선택한 번호의 엘이디를 입력한 시간만큼 선택한 색상으로 켭니다.\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.\",\n                diaboard_led_hue:\t\t\t\t\t\"선택한 번호의 엘이디를 색상(hue)값으로 켭니다.\\n색상( hue) : 0 ~ 359 사이 범위로 설정할 수 있습니다.\\n(총 360가지의 색상을 감지하며 360과 0은 같은 색으로 표현됩니다.)\",\n                diaboard_led_color:\t\t\t\t\t\"선택한 번호의 엘이디를 현재 컬러센서가 감지한 색상(7가지)으로 켭니다. 컬러센서 색상이 \\\"없음\\\"일 때는 코드를 실행해도 엘이디를 켜지 않습니다.\\n7가지 색상 : 빨강, 노랑, 녹색, 청록, 파랑, 보라, 하양\",\n                diaboard_led_rgb:\t\t\t\t\t\"선택한 번호의 엘이디를 빨강, 녹색, 파랑값으로 켭니다.\\n빨강, 녹색, 파랑 : 0 ~ 255의 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 255이상은 255로 처리됩니다. )\",\n                diaboard_led_turn_off_all:\t\t\t\"선택한 번호의 엘이디를 끕니다.\",\n                diaboard_servomotor_angle:\t\t\t\"선택한 포트의 서보모터의 각도를 입력한 값으로 정합니다.\\n각도 : 0 ~ 180 사이 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 180이상은 180으로 처리됩니다.)\",\n                diaboard_servomotor_angle_time:\t\t\"선택한 포트의 서보모터의 초기각도와 목표각도를 설정해 입력한 시간만큼 각도를 바꿉니다.\\n각도 : 0 ~ 180 사이 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 180이상은 180으로 처리됩니다.)\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.\",\n                diaboard_dc_direction_speed:\t\t\"선택한 포트의 디씨모터의 방향과 속력을 정합니다.\\n방향 : 시계방향과 반시계 방향을 설정할 수 있습니다.\\n속력 : 0 ~ 100까지 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 100이상은 100으로 처리됩니다.)\",\n                diaboard_dc_direction_speed_time:\t\"선택한 포트의 디씨모터의 방향과 속력을 정하고, 입력한 시간만큼 동작합니다.\\n방향 : 시계방향과 반시계 방향을 설정할 수 있습니다.\\n속력 : 0 ~ 100까지 범위로 설정할 수 있습니다.\\n(0이하는 0으로, 100이상은 100으로 처리됩니다.)\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.\",\n                diaboard_dc_speed:\t\t\t\t\t\"선택한 포트의 디씨모터의 속도를 정합니다.\\n속도 : -100 ~ 100 사이의 범위로 설정할 수 있습니다.\\n(-100이하는 -100으로, 100이상은 100으로 처리됩니다.)\",\n                diaboard_dc_speed_time:\t\t\t\t\"선택한 포트의 디씨모터의 속도를 정하고, 입력한 시간만큼 동작합니다.\\n속도 : -100 ~ 100 사이의 범위로 설정할 수 있습니다.\\n(-100이하는 -100으로, 100이상은 100으로 처리됩니다.)\\n시간 : 0 ~ 100 범위에서 0.1초 단위로 설정할 수 있습니다.\",\n                diaboard_turn_off_all_motors:\t\t\"선택한 포트의 모터를 멈춥니다.\",\n                diaboard_buzzer_melody_type:        \"선택한 멜로디를 연주합니다.\",\n                diaboard_buzzer_effect_type:        \"선택한 효과음을 냅니다.\",\n                diaboard_buzzer_eight_melody_bpm:\t\"선택한 음들을 입력한 BPM으로 연주합니다.\\n연주속도(BPM) : 30 ~ 300 사이의 범위로 설정할 수 있습니다.\\n(30이하는 30으로, 300이상은 300으로 처리됩니다.)\",\n                diaboard_buzzer_octave:             \"선택한 옥타브와 음으로 연주합니다.\",\n                diaboard_buzzer_octave_rhythm:      \"선택한 옥타브와 음을 입력한 박자로 연주합니다.\",\n                diaboard_buzzer_hz:                 \"입력한 주파수로 연주합니다.\\n주파수 : 33 ~ 7,900 사이의 범위로 설정할 수 있습니다.\\n(33이하는 33으로 7,900이상은 7,900으로 처리됩니다.)\",\n                diaboard_buzzer_hz_change:          \"입력한 주파수만큼 바꿔서 연주합니다.\",\n                diaboard_buzzer_speed_bpm:          \"입력한 BPM으로 연주 속도를 정합니다.\\n연주속도(BPM) : 30 ~ 300 사이의 범위로 설정할 수 있습니다.\\n(30이하는 30으로, 300이상은 300으로 처리됩니다.)\",\n                diaboard_buzzer_speed_bpm_change:   \"입력한 BPM만큼 연주 속도를 바꿉니다.\",\n                diaboard_buzzer_sleep_rhythm:       \"선택한 박자만큼 쉽니다.\",\n                diaboard_buzzer_stop:\t\t\t\t\"버저음을 멈춥니다.\"\n            },\n            Blocks: {\n                DIABOARD_button_left:   '왼쪽',\n                DIABOARD_button_right:  '오른쪽',\n                DIABOARD_button_all:    '모든',\n                DIABOARD_button_pressed:    '누름',\n                DIABOARD_button_released:   '누르지 않음',\n                DIABOARD_color_no_color:    '없음',\n                DIABOARD_color_black:   '검정',\n                DIABOARD_color_red:     '빨강',\n                DIABOARD_color_yellow:  '노랑',\n                DIABOARD_color_green:   '녹색',\n                DIABOARD_color_cyan:    '청록',\n                DIABOARD_color_blue:    '파랑',\n                DIABOARD_color_magenta: '보라',\n                DIABOARD_color_white:   '하양',\n                DIABOARD_color_random:  '아무 색',\n                DIABOARD_sensor_ir:            '적외선 센서',\n                DIABOARD_sensor_brightness:    '밝기 센서',\n                DIABOARD_effect_flame:     '불꽃',\n                DIABOARD_effect_drop:      '별똥별',\n                DIABOARD_effect_glitter:   '반짝임',\n                DIABOARD_effect_dimming:   '숨쉬기',\n                DIABOARD_effect_random:    '아무',\n                DIABOARD_led_all:    '모두',\n                DIABOARD_led_1:      '1',\n                DIABOARD_led_2:      '2',\n                DIABOARD_led_3:      '3',\n                DIABOARD_led_4:      '4',\n                DIABOARD_led_5:      '5',\n                DIABOARD_led_6:      '6',\n                DIABOARD_led_random: '아무 곳',\n                DIABOARD_motor_a:   'A',\n                DIABOARD_motor_b:   'B',\n                DIABOARD_motor_all: '모두',\n                DIABOARD_dc_direction_cw: '시계',\n                DIABOARD_dc_direction_ccw: '반시계',\n                DIABOARD_melody_rising:        '상승음',\n                DIABOARD_melody_falling:       '하강음',\n                DIABOARD_melody_forelise:      '엘리제를 위하여',\n                DIABOARD_melody_tension:       '긴장감',\n                DIABOARD_melody_connecting:    '연결음',\n                DIABOARD_melody_jumpup:        '뛰어 오르는',\n                DIABOARD_melody_jumpdown:      '뛰어 내리는',\n                DIABOARD_melody_birthday:      '생일 축하',\n                DIABOARD_effect_sound_happy:              \"신바람\",\n                DIABOARD_effect_sound_sullen:             \"시무룩\",\n                DIABOARD_effect_sound_sad:                \"슬픔\",\n                DIABOARD_effect_sound_engery_gathering:   \"에너지 모으는\",\n                DIABOARD_effect_sound_laser_beam:         \"레이저빔\",\n                DIABOARD_tonicsolfa_do:         '도',\n                DIABOARD_tonicsolfa_do_sharp:   '도#(레b)',\n                DIABOARD_tonicsolfa_re:         '레',\n                DIABOARD_tonicsolfa_re_sharp:   '레#(미b)',\n                DIABOARD_tonicsolfa_mi:         '미',\n                DIABOARD_tonicsolfa_fa:         '파',\n                DIABOARD_tonicsolfa_fa_sharp:   '파#(솔b)',\n                DIABOARD_tonicsolfa_sol:        '솔',\n                DIABOARD_tonicsolfa_sol_sharp:  '솔#(라b)',\n                DIABOARD_tonicsolfa_la:         '라',\n                DIABOARD_tonicsolfa_la_sharp:   '라#(시b)',\n                DIABOARD_tonicsolfa_si:         '시',\n                DIABOARD_tonicsolfa_high_do:    '(높은)도',\n                DIABOARD_tonicsolfa_rest:       '쉬기',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                // 이벤트\n                diaboard_when_button_pressed:\t\t'%1 when %2 button %3',\n                diaboard_when_color_is:\t\t\t\t'%1 when color is %2',\n                diaboard_when_sensor_is:\t\t\t'%1 when %2 %3 %4',\n                // 센서/버튼 2\n                diaboard_button_pressed:\t\t\t'%1 button %2 ?',\n                diaboard_color_sensor_is:\t\t    'color is %1 ?',\n                diaboard_sensor_condition:\t\t\t'%1 %2 %3 ?',\n                diaboard_color_sensor_seven_hue:    '7 colors',\n                diaboard_color_sensor_one_hue:\t\t'color hues',\n                diaboard_sensor_value:\t\t\t\t'%1 value',\n                diaboard_convert_scale:\t\t\t\t'map %1 value from %2 ~ %3 to %4 ~ %5',\n                // 엘이디\n                diaboard_led_rainbow:\t\t\t\t'show effect rainbow %1',\n                diaboard_led_rainbow_time:\t\t\t'show effect rainbow for %1 seconds %2',\n                diaboard_led_effect:\t\t\t\t'show effect %1 to %2 %3',\n                diaboard_led_effect_time:\t\t\t'show effect %1 to %2 for %3 seconds %4',\n                diaboard_led_six:\t\t\t\t    'turn on %1 %2 %3 %4 %5 %6 %7',\n                diaboard_led_one:\t\t\t\t    'turn on %1 to %2 %3',\n                diaboard_led_one_time:\t\t\t\t'turn on %1 to %2 for %3 seconds %4',\n                diaboard_led_hue:\t\t\t\t    'turn on %1 to %2 %3',\n                diaboard_led_color:\t\t\t\t    'turn on %1 to seven colors %2',\n                diaboard_led_rgb:\t\t\t\t    'turn on %1 to red %2 green %3 blue %4 %5',\n                diaboard_led_turn_off_all:\t\t\t'turn off %1 %2',\n                // 모터\n                diaboard_servomotor_angle:\t\t\t'servo motor %1 degree %2 %3',\n                diaboard_servomotor_angle_time:\t\t'servo motor %1 degree %2 ~ %3 for %4 seconds %5',\n                diaboard_dc_direction_speed:\t\t'DC motor %1 direction %2 speed %3 %4',\n                diaboard_dc_direction_speed_time:\t'DC motor %1 direction %2 speed %3 for %4 seconds %5',\n                diaboard_dc_speed:\t\t\t\t    'DC motor %1 velocity %2 %3',\n                diaboard_dc_speed_time:\t\t\t\t'DC motor %1 velocity %2 for %3 second %4',\n                diaboard_turn_off_all_motors:\t\t'stop %1 motor %2',\n                // 버저\n                diaboard_buzzer_melody_type:\t\t'play melody %1 %2',\n                diaboard_buzzer_effect_type:\t\t'play sound %1 %2',\n                diaboard_buzzer_eight_melody_bpm:\t'play melody %1 %2 %3 %4 %5 %6 %7 %8 at tempo %9 bpm %10',\n                diaboard_buzzer_octave:\t\t\t\t'play octave %1 tone %2 %3',\n                diaboard_buzzer_octave_rhythm:\t\t'play octave %1 tone %2 for %3 beat %4',\n                diaboard_buzzer_hz:\t\t\t\t    'play tone %1 Hz %2',\n                diaboard_buzzer_hz_change:\t\t\t'change tone %1 Hz %2',\n                diaboard_buzzer_speed_bpm:\t\t\t'set tempo to %1 bpm %2',\n                diaboard_buzzer_speed_bpm_change:\t'change tempo by %1 bpm %2',\n                diaboard_buzzer_sleep_rhythm:\t\t'rest sound for %1 beat',\n                diaboard_buzzer_stop:\t\t\t\t'stop all sound',\n            },\n            Helper: {\n                diaboard_when_button_pressed:       \"\",\n                diaboard_when_color_is:\t\t\t\t\"\",\n                diaboard_when_sensor_is:\t\t\t\"\",\n                diaboard_button_pressed:\t\t\t\"\",\n                diaboard_color_sensor_is:\t\t\t\"\",\n                diaboard_sensor_condition:\t\t\t\"\",\n                diaboard_color_sensor_seven_hue:\t\"\",\n                diaboard_color_sensor_one_hue:\t\t\"\",\n                diaboard_sensor_value:\t\t\t\t\"\",\n                diaboard_convert_scale:\t\t\t\t\"\",\n                diaboard_led_rainbow:\t\t\t\t\"\",\n                diaboard_led_rainbow_time:\t\t\t\"\",\n                diaboard_led_effect:\t\t\t\t\"\",\n                diaboard_led_effect_time:\t\t\t\"\",\n                diaboard_led_six:\t\t\t\t\t\"\",\n                diaboard_led_one:\t\t\t\t\t\"\",\n                diaboard_led_one_time:\t\t\t\t\"\",\n                diaboard_led_hue:\t\t\t\t\t\"\",\n                diaboard_led_color:\t\t\t\t\t\"\",\n                diaboard_led_rgb:\t\t\t\t\t\"\",\n                diaboard_led_turn_off_all:\t\t\t\"\",\n                diaboard_servomotor_angle:\t\t\t\"\",\n                diaboard_servomotor_angle_time:\t\t\"\",\n                diaboard_dc_direction_speed:\t\t\"\",\n                diaboard_dc_direction_speed_time:\t\"\",\n                diaboard_dc_speed:\t\t\t\t\t\"\",\n                diaboard_dc_speed_time:\t\t\t\t\"\",\n                diaboard_turn_off_all_motors:\t\t\"\",\n                diaboard_buzzer_melody_type:        \"\",\n                diaboard_buzzer_effect_type:        \"\",\n                diaboard_buzzer_eight_melody_bpm:\t\"\",\n                diaboard_buzzer_octave:             \"\",\n                diaboard_buzzer_octave_rhythm:      \"\",\n                diaboard_buzzer_hz:                 \"\",\n                diaboard_buzzer_hz_change:          \"\",\n                diaboard_buzzer_speed_bpm:          \"\",\n                diaboard_buzzer_speed_bpm_change:   \"\",\n                diaboard_buzzer_sleep_rhythm:       \"\",\n                diaboard_buzzer_stop:\t\t\t\t\"\"\n            },\n            Blocks: {\n                DIABOARD_button_left:   'left',\n                DIABOARD_button_right:  'right',\n                DIABOARD_button_all:    'all',\n                DIABOARD_button_pressed:    'pressed',\n                DIABOARD_button_released:   'release',\n                DIABOARD_color_no_color:    'no color',\n                DIABOARD_color_black:   'black',\n                DIABOARD_color_red:     'red',\n                DIABOARD_color_yellow:  'yellow',\n                DIABOARD_color_green:   'green',\n                DIABOARD_color_cyan:    'cyan',\n                DIABOARD_color_blue:    'blue',\n                DIABOARD_color_magenta: 'magenta',\n                DIABOARD_color_white:   'white',\n                DIABOARD_color_random:  'random',\n                DIABOARD_sensor_ir:            'IR',\n                DIABOARD_sensor_brightness:    'Brightness',\n                DIABOARD_effect_flame:     'flame',\n                DIABOARD_effect_drop:      'drop',\n                DIABOARD_effect_glitter:   'glitter',\n                DIABOARD_effect_dimming:   'dimming',\n                DIABOARD_effect_random:    'random',\n                DIABOARD_led_all:    'all',\n                DIABOARD_led_1:      '1',\n                DIABOARD_led_2:      '2',\n                DIABOARD_led_3:      '3',\n                DIABOARD_led_4:      '4',\n                DIABOARD_led_5:      '5',\n                DIABOARD_led_6:      '6',                \n                DIABOARD_led_random: 'random',                \n                DIABOARD_motor_a:   'A',\n                DIABOARD_motor_b:   'B',\n                DIABOARD_motor_all: 'all',                \n                DIABOARD_dc_direction_cw: 'CW',\n                DIABOARD_dc_direction_ccw: 'CCW',\n                DIABOARD_melody_rising:        'rising',\n                DIABOARD_melody_falling:       'falling',\n                DIABOARD_melody_forelise:      'For Elise',\n                DIABOARD_melody_tension:       'tension',\n                DIABOARD_melody_connecting:    'connecting',\n                DIABOARD_melody_jumpup:        'jump up',\n                DIABOARD_melody_jumpdown:      'jump down',\n                DIABOARD_melody_birthday:      'birthday',\n                DIABOARD_effect_sound_happy:              \"happy\",\n                DIABOARD_effect_sound_sullen:             \"sullen\",\n                DIABOARD_effect_sound_sad:                \"sad\",\n                DIABOARD_effect_sound_engery_gathering:   \"energy gathering\",\n                DIABOARD_effect_sound_laser_beam:         \"laser beam\",\n                DIABOARD_tonicsolfa_do:         'do',\n                DIABOARD_tonicsolfa_do_sharp:   'do#(reb)',\n                DIABOARD_tonicsolfa_re:         're',\n                DIABOARD_tonicsolfa_re_sharp:   're#(mib)',\n                DIABOARD_tonicsolfa_mi:         'mi',\n                DIABOARD_tonicsolfa_fa:         'fa',\n                DIABOARD_tonicsolfa_fa_sharp:   'fa#(solb)',\n                DIABOARD_tonicsolfa_sol:        'sol',\n                DIABOARD_tonicsolfa_sol_sharp:  'sol#(lab)',\n                DIABOARD_tonicsolfa_la:         'la',\n                DIABOARD_tonicsolfa_la_sharp:   'la#(sib)',\n                DIABOARD_tonicsolfa_si:         'si',\n                DIABOARD_tonicsolfa_high_do:    '(C5)do',\n                DIABOARD_tonicsolfa_rest:       'rest',\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Diaboard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_dodaland.js",
    "content": "'use strict';\n\nEntry.Dodaland = {\n    id: '4F.1',\n    name: 'dodaland',\n    url: 'http://www.dodaland.com/',\n    imageName: 'dodaland.png',\n    title: {\n        ko: '도다랜드',\n        en: 'Dodaland',\n    },\n    setZero: () => {\n        Entry.hw.sendQueue[\n            'command'\n        ] = `{\"doda-control\":{\"def-normal-inst\":2,\"led-app-control\":false,\"fix-volume\":false,\"fix-tempo\":false}}`;\n        Entry.hw.update();\n    },\n};\n\nEntry.Dodaland.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                dodaland_start_button_pressed: '재생 버튼이 눌렸을 때',\n                dodaland_play_note_with_length: '계이름 %1 를 %2 길이만큼 연주',\n                dodaland_onoff_channel_led: '채널 %1 번의 LED %2',\n                dodaland_onoff_location_led: '좌표 %1, %2 위치의 채널 LED %3',\n                dodaland_select_instrument: '%1 악기 사용하기',\n                dodaland_press_start_button: '재생 버튼 누르기',\n                dodaland_press_stop_button: '정지 버튼 누르기',\n                dodaland_play_channel: '채널 %1 번 연주하기',\n                dodaland_play_location: '좌표 %1, %2 위치의 채널 연주하기',\n                dodaland_control_led: 'LED 제어 모드 %1',\n                dodaland_control_volume: '볼륨 제어 모드 %1',\n                dodaland_control_tempo: '템포 제어 모드 %1',\n                dodaland_set_volume: '볼륨값 %1 으로 설정하기',\n                dodaland_set_tempo: '템포값 %1 으로 설정하기',\n            },\n        },\n        en: {\n            template: {\n                dodaland_start_button_pressed: '재생 버튼이 눌렸을 때',\n                dodaland_play_note_with_length: '계이름 %1 를 %2 길이만큼 연주',\n                dodaland_onoff_channel_led: '채널 %1 번의 LED %2',\n                dodaland_onoff_location_led: '좌표 %1, %2 위치의 채널 LED %3',\n                dodaland_select_instrument: '%1 악기 사용하기',\n                dodaland_press_start_button: '재생 버튼 누르기',\n                dodaland_press_stop_button: '정지 버튼 누르기',\n                dodaland_play_channel: '채널 %1 번 연주하기',\n                dodaland_play_location: '좌표 %1, %2 위치의 채널 연주하기',\n                dodaland_control_led: 'LED 제어 모드 %1',\n                dodaland_control_volume: '볼륨 제어 모드 %1',\n                dodaland_control_tempo: '템포 제어 모드 %1',\n                dodaland_set_volume: '볼륨값 %1 으로 설정하기',\n                dodaland_set_tempo: '템포값 %1 으로 설정하기',\n            },\n        },\n    };\n};\n\nEntry.Dodaland.blockMenuBlocks = [\n    'dodaland_press_start_button',\n    'dodaland_press_stop_button',\n    'dodaland_onoff_channel_led',\n    'dodaland_onoff_location_led',\n    'dodaland_select_instrument',\n    'dodaland_play_channel',\n    'dodaland_play_location',\n    'dodaland_control_led',\n    'dodaland_control_volume',\n    'dodaland_control_tempo',\n    'dodaland_set_volume',\n    'dodaland_set_tempo',\n];\n\nEntry.Dodaland.getBlocks = function() {\n    return {\n        dodaland_start_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_play.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                type: 'dodaland_start_button_pressed',\n            },\n            class: 'buttons',\n            func: (sprite, script) => {},\n        },\n        dodaland_play_note_with_length: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['도', '도'],\n                        ['레', '레'],\n                        ['미', '미'],\n                        ['파', '파'],\n                        ['솔', '솔'],\n                        ['라', '라'],\n                        ['시', '시'],\n                        ['도', '도'],\n                    ],\n                    fontSize: 11,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['온음표', '온음표'],\n                        ['2분음표', '2분음표'],\n                        ['4분음표', '4분음표'],\n                        ['8분음표', '8분음표'],\n                        ['16분음표', '16분음표'],\n                    ],\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: ['도', '4분음표'],\n                type: 'dodaland_play_note_with_length',\n            },\n            paramsKeyMap: {\n                PITCH_NAME: 0,\n                NOTE_NAME: 1,\n            },\n            class: 'blocks',\n            func: (sprite, script) => {\n                const pitchName = script.getValue('PITCH_NAME', script);\n                const noteName = script.getValue('NOTE_NAME', script);\n                console.log(pitchName, noteName);\n            },\n        },\n        dodaland_press_start_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_play.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                type: 'dodaland_press_start_button',\n            },\n            class: 'buttons',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                Entry.hw.sendQueue['command'] = '{\"doda-button\":{\"play\":true}}';\n                Entry.hw.update();\n            },\n        },\n        dodaland_press_stop_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_play.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                type: 'dodaland_press_stop_button',\n            },\n            class: 'buttons',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                Entry.hw.sendQueue['command'] = '{\"doda-button\":{\"stop\":true}}';\n                Entry.hw.update();\n            },\n        },\n        dodaland_onoff_channel_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 0],\n                        [2, 1],\n                        [3, 2],\n                        [4, 3],\n                        [5, 4],\n                        [6, 5],\n                        [7, 6],\n                        [8, 7],\n                        [9, 8],\n                        [10, 9],\n                        [11, 10],\n                        [12, 11],\n                        [13, 12],\n                        [14, 13],\n                        [15, 14],\n                        [16, 15],\n                        [17, 16],\n                        [18, 17],\n                        [19, 18],\n                        [20, 19],\n                        [21, 20],\n                        [22, 21],\n                        [23, 22],\n                        [24, 23],\n                        [25, 24],\n                        [26, 25],\n                        [27, 26],\n                        [28, 27],\n                        [29, 28],\n                        [30, 29],\n                        [31, 30],\n                        [32, 31],\n                        [33, 32],\n                        [34, 33],\n                        [35, 34],\n                        [36, 35],\n                        [37, 36],\n                        [38, 37],\n                        [39, 38],\n                        [40, 39],\n                    ],\n                    fontSize: 11,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['끄기', 0],\n                        ['켜기', 1],\n                    ],\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: ['0', '1'],\n                type: 'dodaland_onoff_channel_led',\n            },\n            paramsKeyMap: {\n                CHANNEL_NUMBER: 0,\n                ONOFF: 1,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                const channelNumber = script.getValue('CHANNEL_NUMBER', script);\n                const onOrOff = script.getValue('ONOFF', script);\n                console.log(channelNumber, onOrOff);\n                Entry.hw.sendQueue['command'] = `{\"doda-led\":{\"${\n                    onOrOff ? 'ledon' : 'ledoff'\n                }\":[${channelNumber}]}}`;\n                Entry.hw.update();\n            },\n        },\n        dodaland_onoff_location_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['끄기', 0],\n                        ['켜기', 1],\n                    ],\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    1,\n                ],\n                type: 'dodaland_onoff_location_led',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                ON_OR_OFF: 2,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                const xLocation = script.getNumberValue('X', script);\n                const yLocation = script.getNumberValue('Y', script);\n                const onOrOff = script.getValue('ON_OR_OFF', script);\n                console.log(xLocation, yLocation, onOrOff);\n                if (xLocation > 10 || yLocation > 4) {\n                    // do nothing\n                } else {\n                    const channelNumber = (yLocation - 1) * 10 + (xLocation - 1);\n                    console.log(xLocation, yLocation, onOrOff, channelNumber);\n                    Entry.hw.sendQueue['command'] = `{\"doda-led\":{\"${\n                        onOrOff ? 'ledon' : 'ledoff'\n                    }\":[${channelNumber}]}}`;\n                    Entry.hw.update();\n                }\n            },\n        },\n        dodaland_select_instrument: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['피아노', '2'],\n                        ['전자피아노', '6'],\n                        ['글로켄슈필', '10'],\n                        ['오르골', '11'],\n                        ['종', '15'],\n                        ['오르간', '20'],\n                        ['어쿠스틱 기타', '25'],\n                        ['전자기타', '31'],\n                        ['베이스', '34'],\n                        ['바이올린', '41'],\n                        ['비올라', '42'],\n                        ['첼로', '43'],\n                        ['더블 베이스', '44'],\n                        ['하프', '47'],\n                        ['목소리', '53'],\n                        ['트럼펫', '58'],\n                        ['튜바', '62'],\n                        ['색소폰', '65'],\n                        ['오보에', '69'],\n                        ['호른', '70'],\n                        ['클라리넷', '72'],\n                        ['플루트', '74'],\n                        ['팬플루트', '76'],\n                        ['오카리나', '80'],\n                        ['단소', '83'],\n                        ['비', '97'],\n                        ['보석', '99'],\n                        ['밴조', '106'],\n                        ['칼림바', '109'],\n                        ['핸드벨', '113'],\n                        ['우드블럭', '116'],\n                        ['오리', '121'],\n                        ['파도', '123'],\n                        ['전화벨', '125'],\n                    ],\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: ['2'],\n                type: 'dodaland_select_instrument',\n            },\n            paramsKeyMap: {\n                INSTRUMENT_NAME: 0,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                const instrumentName = script.getValue('INSTRUMENT_NAME', script);\n                console.log(instrumentName);\n                Entry.hw.sendQueue[\n                    'command'\n                ] = `{\"doda-control\":{\"def-normal-inst\":${instrumentName}}}`;\n                Entry.hw.update();\n            },\n        },\n        dodaland_play_channel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [1, 0],\n                        [2, 1],\n                        [3, 2],\n                        [4, 3],\n                        [5, 4],\n                        [6, 5],\n                        [7, 6],\n                        [8, 7],\n                        [9, 8],\n                        [10, 9],\n                        [11, 10],\n                        [12, 11],\n                        [13, 12],\n                        [14, 13],\n                        [15, 14],\n                        [16, 15],\n                        [17, 16],\n                        [18, 17],\n                        [19, 18],\n                        [20, 19],\n                        [21, 20],\n                        [22, 21],\n                        [23, 22],\n                        [24, 23],\n                        [25, 24],\n                        [26, 25],\n                        [27, 26],\n                        [28, 27],\n                        [29, 28],\n                        [30, 29],\n                        [31, 30],\n                        [32, 31],\n                        [33, 32],\n                        [34, 33],\n                        [35, 34],\n                        [36, 35],\n                        [37, 36],\n                        [38, 37],\n                        [39, 38],\n                        [40, 39],\n                    ],\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: ['0'],\n                type: 'dodaland_play_channel',\n            },\n            paramsKeyMap: {\n                CHANNEL_NUMBER: 0,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                const channelNumber = script.getValue('CHANNEL_NUMBER', script);\n                console.log(channelNumber);\n                Entry.hw.sendQueue[\n                    'command'\n                ] = `{\"doda-entry\":{\"single-channel-play\": ${channelNumber}}}`;\n                Entry.hw.update();\n            },\n        },\n        dodaland_play_location: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    1,\n                ],\n                type: 'dodaland_play_location',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                const xLocation = script.getNumberValue('X', script);\n                const yLocation = script.getNumberValue('Y', script);\n                if (xLocation > 10 || yLocation > 4) {\n                    // do nothing\n                } else {\n                    const channelNumber = (yLocation - 1) * 10 + (xLocation - 1);\n                    console.log(xLocation, yLocation, channelNumber);\n                    Entry.hw.sendQueue[\n                        'command'\n                    ] = `{\"doda-entry\":{\"single-channel-play\": ${channelNumber}}}`;\n                    Entry.hw.update();\n                }\n            },\n        },\n        dodaland_control_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['끄기', 0],\n                        ['켜기', 1],\n                    ],\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: [1],\n                type: 'dodaland_control_led',\n            },\n            paramsKeyMap: {\n                ENABLE: 0,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                const controlEnable = script.getValue('ENABLE', script);\n                console.log(controlEnable);\n                Entry.hw.sendQueue['command'] = `{\"doda-control\":{\"led-app-control\":${\n                    controlEnable ? true : false\n                }}}`;\n                Entry.hw.update();\n            },\n        },\n        dodaland_control_volume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['끄기', 0],\n                        ['켜기', 1],\n                    ],\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: [1],\n                type: 'dodaland_control_volume',\n            },\n            paramsKeyMap: {\n                ENABLE: 0,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                const controlEnable = script.getValue('ENABLE', script);\n                console.log(controlEnable);\n                Entry.hw.sendQueue['command'] = `{\"doda-control\":{\"fix-volume\":${\n                    controlEnable ? true : false\n                }}}`;\n                Entry.hw.update();\n            },\n        },\n        dodaland_control_tempo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['끄기', 0],\n                        ['켜기', 1],\n                    ],\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: [1],\n                type: 'dodaland_control_tempo',\n            },\n            paramsKeyMap: {\n                ENABLE: 0,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                const controlEnable = script.getValue('ENABLE', script);\n                console.log(controlEnable);\n                Entry.hw.sendQueue['command'] = `{\"doda-control\":{\"fix-tempo\":${\n                    controlEnable ? true : false\n                }}}`;\n                Entry.hw.update();\n            },\n        },\n        dodaland_set_volume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'dodaland_set_volume',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                let controlValue = script.getNumberValue('VALUE', script);\n                if (controlValue > 100) {\n                    controlValue = 100;\n                }\n                console.log(controlValue);\n                Entry.hw.sendQueue['command'] = `{\"doda-control\":{\"set-volume\":${controlValue}}}`;\n                Entry.hw.update();\n            },\n        },\n        dodaland_set_tempo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'dodaland_set_tempo',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'blocks',\n            isNotFor: ['dodaland'],\n            func: (sprite, script) => {\n                let controlValue = script.getNumberValue('VALUE', script);\n                if (controlValue > 100) {\n                    controlValue = 100;\n                }\n                console.log(controlValue);\n                Entry.hw.sendQueue['command'] = `{\"doda-control\":{\"set-tempo\":${controlValue}}}`;\n                Entry.hw.update();\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Dodaland;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_dplay.js",
    "content": "'use strict';\n\nEntry.dplay = {\n    id: '1.5',\n    name: 'dplay',\n    url: 'http://dplay.cc',\n    imageName: 'dplay.png',\n    title: {\n        ko: '디플레이',\n        en: 'DPLAY',\n    },\n    vel_value: 255,\n    Left_value: 255,\n    Right_value: 255,\n    setZero: Entry.Arduino.setZero,\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    monitorTemplate: {\n        imgPath: 'hw/dplay.png',\n        width: 500,\n        height: 600,\n        listPorts: {\n            '2': {\n                name: Lang.Hw.port_en + ' 2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '3': {\n                name: Lang.Hw.port_en + ' 3 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '4': {\n                name: Lang.Hw.port_en + ' 4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '5': {\n                name: Lang.Hw.port_en + ' 5 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '6': {\n                name: Lang.Hw.port_en + ' 6 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '7': {\n                name: Lang.Hw.port_en + ' 7 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '8': {\n                name: Lang.Hw.port_en + ' 8 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '9': {\n                name: Lang.Hw.port_en + ' 9 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '10': {\n                name: Lang.Hw.port_en + ' 10 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '11': {\n                name: Lang.Hw.port_en + ' 11 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '12': {\n                name: Lang.Hw.port_en + ' 12 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '13': {\n                name: Lang.Hw.port_en + ' 13 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: Lang.Hw.port_en + ' A0 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: Lang.Hw.port_en + ' A1 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a2: {\n                name: Lang.Hw.port_en + ' A2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a3: {\n                name: Lang.Hw.port_en + ' A3 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a4: {\n                name: Lang.Hw.port_en + ' A4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a5: {\n                name: Lang.Hw.port_en + ' A5 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n};\nEntry.dplay.blockMenuBlocks = [\n    //dplay\n    'dplay_get_number_sensor_value',\n    'dplay_get_value',\n    'dplay_get_gas_sensor_value',\n    'dplay_get_dust_sensor_value',\n    'dplay_get_CO2_sensor_value',\n    'dplay_convert_scale',\n    'dplay_get_digital_value',\n    'dplay_get_switch_status',\n    'dplay_get_tilt',\n    'dplay_toggle_led',\n    'dplay_toggle_pwm',\n    'dplay_select_led',\n    'dplay_DCmotor',\n    'dplay_DCmotor_speed',\n    'dplay_buzzer',\n    'dplay_servo',\n    'dplay_Robot_run',\n    'dplay_Robot_run_sec',\n    'dplay_robot_speed_sel',\n    'dplay_robot_speed_set',\n    'dplay_robot_stop',\n];\n\nEntry.dplay.setLangauge = function() {\n    return {\n        ko: {\n            template: {\n                dplay_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                dplay_get_digital_value: '디지털 %1 번 센서값  ',\n                dplay_toggle_led: '디지털 %1 번 핀 %2 %3',\n                dplay_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                dplay_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n            },\n            Blocks: {\n                dplay_switch: '스위치 ',\n                dplay_light: '빛센서가 ',\n                dplay_tilt: '기울기센서 상태가',\n                dplay_string_1: '켜짐',\n                dplay_string_2: '꺼짐',\n                dplay_string_3: '밝음',\n                dplay_string_4: '어두움',\n                dplay_string_5: '눌림',\n                dplay_string_6: '열림',\n                dplay_num_pin_1: 'LED 상태를',\n                dplay_num_pin_2: '번 스위치가',\n                dplay_num_pin_3: '아날로그',\n                dplay_num_pin_4: '번 ',\n                dplay_num_pin_5: '센서값',\n                dplay_analog_number_0: 'A0',\n                dplay_analog_number_1: 'A1',\n                dplay_analog_number_2: 'A2',\n                dplay_analog_number_3: 'A3',\n                dplay_analog_number_4: 'A4',\n                dplay_analog_number_5: 'A5',\n            },\n            Menus: {\n                dplay: '디플레이',\n            },\n        },\n        en: {\n            template: {\n                dplay_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                dplay_get_digital_value: 'Digital %1 Sensor value  ',\n                dplay_toggle_led: 'Digital %1 Pin %2 %3',\n                dplay_toggle_pwm: 'Digital %1 Pin %2 %3',\n                dplay_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n            },\n            Blocks: {\n                dplay_switch: '스위치 ',\n                dplay_light: 'Light sensor is ',\n                dplay_tilt: 'Slope sensor status is',\n                dplay_string_1: '켜짐',\n                dplay_string_2: '꺼짐',\n                dplay_string_3: 'bright',\n                dplay_string_4: 'dark',\n                dplay_string_5: 'pressed',\n                dplay_string_6: 'opened',\n                dplay_num_pin_1: 'LED status',\n                dplay_num_pin_2: 'switch',\n                dplay_num_pin_3: 'analogue',\n                dplay_num_pin_4: '번 ',\n                dplay_num_pin_5: 'sensor value',\n                dplay_analog_number_0: 'A0',\n                dplay_analog_number_1: 'A1',\n                dplay_analog_number_2: 'A2',\n                dplay_analog_number_3: 'A3',\n                dplay_analog_number_4: 'A4',\n                dplay_analog_number_5: 'A5',\n            },\n            Menus: {\n                dplay: 'DPLAY',\n            },\n        },\n    };\n};\nEntry.dplay.getBlocks = function() {\n    return {\n        //region dplay 디플레이\n        dplay_get_number_sensor_value: {\n            parent: 'arduino_get_number_sensor_value',\n            isNotFor: ['dplay'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'dplay_get_number_sensor_value',\n            },\n            class: 'dplay_get',\n            syntax: { js: [], py: ['Dplay.sensor_value(%1)'] },\n        },\n        dplay_get_dust_sensor_value: {\n            parent: 'arduino_get_number_sensor_value',\n            template: '아날로그 %1 번  먼지 센서값',\n            isNotFor: ['dplay'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'dplay_get_dust_sensor_value',\n            },\n            class: 'dplay_get',\n            syntax: { js: [], py: ['Dplay.dust_sensor_value(%1)'] },\n        },\n        dplay_get_CO2_sensor_value: {\n            parent: 'arduino_get_number_sensor_value',\n            template: '아날로그 %1 번  이산화탄소 센서값',\n            isNotFor: ['dplay'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'dplay_get_CO2_sensor_value',\n            },\n            class: 'dplay_get',\n            syntax: { js: [], py: ['Dplay.co2_sensor_value(%1)'] },\n        },\n        dplay_get_gas_sensor_value: {\n            parent: 'arduino_get_number_sensor_value',\n            isNotFor: ['dplay'],\n            template: '아날로그 %1 번 가스 센서값',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'dplay_get_gas_sensor_value',\n                id: 'hh5b',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'dplay_get',\n            func: function(sprite, script) {\n                var signal = script.getValue('VALUE', script);\n                return Entry.hw.getAnalogPortValue(signal[1]);\n            },\n            syntax: { js: [], py: ['Dplay.gas_sensor_value(%1)'] },\n        },\n        dplay_convert_scale: {\n            parent: 'arduino_convert_scale',\n            isNotFor: ['dplay'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_number_sensor_value',\n                        params: [\n                            {\n                                type: 'arduino_get_sensor_number',\n                                id: 'bl5e',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'dplay_convert_scale',\n            },\n            class: 'dplay_get',\n            syntax: { js: [], py: ['Dplay.convert_scale(%1, %2, %3, %4, %5)'] },\n        },\n        dplay_get_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '아날로그 %1 번  %2 센서값',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['적외선', 'INFR'],\n                        ['가변저항', 'ADJU'],\n                        ['빛센서', 'LIGHT'],\n                        ['온도센서', 'TEMP'],\n                        ['조이스틱 X', 'JOYSX'],\n                        ['조이스틱 Y', 'JOYSY'],\n                    ],\n                    value: 'INFR',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                    null,\n                ],\n                type: 'dplay_get_value',\n                id: 'hh5b',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                OPERATOR: 1,\n            },\n            class: 'dplay_get',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var signal = script.getValue('VALUE', script);\n                return Entry.hw.getAnalogPortValue(signal[1]);\n            },\n            syntax: { js: [], py: ['Dplay.value(%1, %2)'] },\n        },\n        dplay_get_digital_value: {\n            parent: 'arduino_get_digital_value',\n            isNotFor: ['dplay'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'dplay_get_digital_value',\n            },\n            class: 'dplay_get',\n            syntax: { js: [], py: ['Dplay.digital_value(%1)'] },\n        },\n        dplay_get_switch_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '디지털 %1 번 스위치가 %2  ',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['4', '4'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['눌림', 'ON'],\n                        ['열림', 'OFF'],\n                    ],\n                    value: 'ON',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'dplay_get_switch_status',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                STATUS: 1,\n            },\n            class: 'dplay_get',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port1 = script.getField('PORT');\n                var port = 2;\n                if (port1 == '2') port = 2;\n                else if (port1 == '4') port = 4;\n                var value1 = script.getField('STATUS');\n                if (value1 == 'ON') return Entry.hw.getDigitalPortValue(port) == 1 ? 1 : 0;\n                else return Entry.hw.getDigitalPortValue(port) == 0 ? 1 : 0;\n            },\n            syntax: { js: [], py: ['Dplay.switch_status(%1, %2)'] },\n        },\n        dplay_get_tilt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '디지털  %1 번 기울기센서가 %2  ',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['4', '4'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', 'LEFT'],\n                        ['오른쪽', 'LIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'dplay_get_tilt',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                STATUS: 1,\n            },\n            class: 'dplay_get',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port1 = script.getField('PORT');\n                var port = 2;\n                if (port1 == '2') port = 2;\n                else if (port1 == '4') port = 4;\n                var value1 = script.getField('STATUS');\n                if (value1 == 'LIGHT') return Entry.hw.getDigitalPortValue(port) == 1 ? 1 : 0;\n                else return Entry.hw.getDigitalPortValue(port) == 0 ? 1 : 0;\n            },\n            syntax: { js: [], py: ['Dplay.tilt(%1, %2)'] },\n        },\n        dplay_toggle_led: {\n            parent: 'arduino_toggle_led',\n            isNotFor: ['dplay'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'dplay_toggle_led',\n            },\n            class: 'dplay_set',\n            syntax: { js: [], py: ['Dplay.toggle_led(%1)'] },\n        },\n        dplay_toggle_pwm: {\n            parent: 'arduino_toggle_pwm',\n            isNotFor: ['dplay'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'arduino_text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'dplay_toggle_pwm',\n            },\n            class: 'dplay_set',\n            syntax: { js: [], py: ['Dplay.toggle_pwm(%1, %2)'] },\n        },\n        dplay_select_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '디지털 %1 LED 상태를 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '7',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', 'ON'],\n                        ['끄기', 'OFF'],\n                    ],\n                    value: 'ON',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'dplay_select_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'dplay_set',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port1 = script.getField('PORT');\n                var port = 7;\n                if (port1 == '7') port = 7;\n                else if (port1 == '8') port = 8;\n                else if (port1 == '12') port = 12;\n                else if (port1 == '13') port = 13;\n                var operator = script.getField('OPERATOR');\n                var value = operator == 'ON' ? 255 : 0;\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Dplay.select_led(%1, %2)'] },\n        },\n        dplay_DCmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '%1  DC모터 상태를 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['양쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['정방향', 'FRONT'],\n                        ['역방향', 'REAR'],\n                        ['정지', 'OFF'],\n                    ],\n                    value: 'FRONT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'dplay_DCmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'dplay_set',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var port1 = 0;\n                var port2 = 0;\n                var port3 = 0;\n                var port4 = 0;\n                if (port == '1') {\n                    port1 = 3;\n                    port2 = 5;\n                } else if (port == '2') {\n                    port1 = 6;\n                    port2 = 11;\n                } else if (port == '3') {\n                    port1 = 3;\n                    port2 = 5;\n                    port3 = 11;\n                    port4 = 6;\n                }\n                var temp = Entry.dplay.vel_value;\n                var operator = script.getField('OPERATOR');\n                var value1 = 0;\n                var value2 = 0;\n                var value3 = 0;\n                var value4 = 0;\n                if (operator == 'FRONT') {\n                    value1 = temp;\n                    value2 = 0;\n                } else if (operator == 'REAR') {\n                    value1 = 0;\n                    value2 = temp;\n                } else if (operator == 'OFF') {\n                    value1 = 0;\n                    value2 = 0;\n                }\n                Entry.hw.setDigitalPortValue(port1, value2);\n                Entry.hw.setDigitalPortValue(port2, value1);\n                Entry.hw.setDigitalPortValue(port3, value2);\n                Entry.hw.setDigitalPortValue(port4, value1);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Dplay.dc_motor(%1, %2)'] },\n        },\n        dplay_DCmotor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '%1 DC모터 속도를 %2(으)로 정하기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['양쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'dplay_DCmotor_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dplay_set',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port1 = 0;\n                var port2 = 0;\n                var port3 = 0;\n                var port4 = 0;\n                var value1 = 0;\n                var value2 = 0;\n                var result = 0;\n                var port = script.getField('PORT');\n                if (port == '1') {\n                    port1 = 3;\n                    port2 = 5;\n                } else if (port == '2') {\n                    port1 = 11;\n                    port2 = 6;\n                } else if (port == '3') {\n                    port1 = 3;\n                    port2 = 5;\n                    port3 = 11;\n                    port4 = 6;\n                }\n                var operator = script.getNumberValue('VALUE', script);\n                operator = Math.max(operator, -100);\n                operator = Math.min(operator, 100);\n                if (operator == 0) {\n                    value1 = 0;\n                    value2 = 0;\n                    Entry.dplay.vel_value = value2;\n                } else if (operator > 0) {\n                    result = operator + 155;\n                    result = Math.round(result);\n                    value1 = 0;\n                    value2 = result;\n                    Entry.dplay.vel_value = value2;\n                } else if (operator < 0) {\n                    result = operator - 155;\n                    result = Math.round(result);\n                    value1 = -result;\n                    value2 = 0;\n                    Entry.dplay.vel_value = value1;\n                }\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue = 50;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 2;\n                        Entry.dplay.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.dplay.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    Entry.hw.setDigitalPortValue(3, 0);\n                    Entry.hw.setDigitalPortValue(5, 0);\n                    Entry.hw.setDigitalPortValue(6, 0);\n                    Entry.hw.setDigitalPortValue(11, 0);\n                    return script;\n                } else if (script.timeFlag == 2) {\n                    Entry.hw.setDigitalPortValue(port1, value1);\n                    Entry.hw.setDigitalPortValue(port2, value2);\n                    Entry.hw.setDigitalPortValue(port3, value1);\n                    Entry.hw.setDigitalPortValue(port4, value2);\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Dplay.dc_motor_speed(%1, %2)'] },\n        },\n        dplay_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '디지털 10번 부저를 %1 %2 %3 박자로 연주하기',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['도', '1'],\n                        ['도#', '2'],\n                        ['레', '3'],\n                        ['미b', '4'],\n                        ['미', '5'],\n                        ['파', '6'],\n                        ['파#', '7'],\n                        ['솔', '8'],\n                        ['솔#', '9'],\n                        ['라', '10'],\n                        ['시b', '11'],\n                        ['시', '12'],\n                        ['무음', '100'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '1',\n                    '1',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'dplay_buzzer',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                VALUE: 2,\n            },\n            class: 'dplay_set',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var note = script.getNumberField('NOTE', script);\n                    var octave = script.getNumberField('OCTAVE', script);\n                    var beat = script.getNumberValue('VALUE');\n                    var tempo = 60;\n                    var note_go = note + (octave - 1) * 12;\n                    var timeValue = (beat * 60 * 1000) / tempo;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    if (note == 100) Entry.hw.setDigitalPortValue(10, 100);\n                    else Entry.hw.setDigitalPortValue(10, note_go);\n                    if (timeValue > 100) {\n                        var timer1 = setTimeout(function() {\n                            Entry.hw.setDigitalPortValue(10, 100);\n                            Entry.dplay.removeTimeout(timer1);\n                        }, timeValue - 100);\n                        Entry.dplay.timeouts.push(timer1);\n                    }\n                    var timer2 = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.dplay.removeTimeout(timer2);\n                    }, timeValue);\n                    Entry.dplay.timeouts.push(timer2);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.setDigitalPortValue(10, 100);\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Dplay.buzzer(%1, %2, %3)'] },\n        },\n        dplay_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '디지털 9번 서보모터 각도를 %1 (도)로 이동',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['180'],\n                    },\n                    null,\n                ],\n                type: 'dplay_servo',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'dplay_set',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port = 9;\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 1);\n                value = Math.min(value, 179);\n                Entry.hw.setDigitalPortValue(9, value);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Dplay.servo(%1)'] },\n        },\n        dplay_Robot_run: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '로봇을 %1 하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['전진', '1'],\n                        ['후진', '2'],\n                        ['우회전', '3'],\n                        ['좌회전', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'dplay_Robot_run',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'dplay_robot',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var port1 = 3;\n                var port2 = 5;\n                var port3 = 6;\n                var port4 = 11;\n                var value1 = 0;\n                var value2 = 0;\n                var value3 = 0;\n                var value4 = 0;\n                var temp_Left = Entry.dplay.Left_value;\n                var temp_Right = Entry.dplay.Right_value;\n                if (port == '1') {\n                    value1 = 0;\n                    value2 = temp_Left;\n                    value3 = temp_Right;\n                    value4 = 0;\n                } else if (port == '2') {\n                    value1 = temp_Left;\n                    value2 = 0;\n                    value3 = 0;\n                    value4 = temp_Right;\n                } else if (port == '3') {\n                    value1 = 0;\n                    value2 = temp_Left;\n                    value3 = 0;\n                    value4 = 0;\n                } else if (port == '4') {\n                    value1 = 0;\n                    value2 = 0;\n                    value3 = temp_Right;\n                    value4 = 0;\n                }\n                Entry.hw.setDigitalPortValue(port1, value1);\n                Entry.hw.setDigitalPortValue(port2, value2);\n                Entry.hw.setDigitalPortValue(port3, value3);\n                Entry.hw.setDigitalPortValue(port4, value4);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Dplay.robot_run(%1)'] },\n        },\n        dplay_Robot_run_sec: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '로봇을 %1 초 동안 %2 하기 %3',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['전진', '1'],\n                        ['후진', '2'],\n                        ['우회전', '3'],\n                        ['좌회전', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'dplay_Robot_run_sec',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                PORT: 1,\n            },\n            class: 'dplay_robot',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port1 = 3;\n                var port2 = 5;\n                var port3 = 6;\n                var port4 = 11;\n                var value1 = 0;\n                var value2 = 0;\n                var value3 = 0;\n                var value4 = 0;\n                var temp_Left = Entry.dplay.Left_value;\n                var temp_Right = Entry.dplay.Right_value;\n                var port = script.getField('PORT');\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue = script.getNumberValue('VALUE') * 1000;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.dplay.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.dplay.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    if (port == '1') {\n                        value1 = 0;\n                        value2 = temp_Left;\n                        value3 = temp_Right;\n                        value4 = 0;\n                    } else if (port == '2') {\n                        value1 = temp_Left;\n                        value2 = 0;\n                        value3 = 0;\n                        value4 = temp_Right;\n                    } else if (port == '3') {\n                        value1 = 0;\n                        value2 = temp_Left;\n                        value3 = 0;\n                        value4 = 0;\n                    } else if (port == '4') {\n                        value1 = 0;\n                        value2 = 0;\n                        value3 = temp_Right;\n                        value4 = 0;\n                    }\n                    Entry.hw.setDigitalPortValue(port1, value1);\n                    Entry.hw.setDigitalPortValue(port2, value2);\n                    Entry.hw.setDigitalPortValue(port3, value3);\n                    Entry.hw.setDigitalPortValue(port4, value4);\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    value1 = 0;\n                    value2 = 0;\n                    value3 = 0;\n                    value4 = 0;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Dplay.robot_run_sec(%1, %2)'] },\n        },\n        dplay_robot_speed_sel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '%1 바퀴 속도를 %2(으)로 정하기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['양쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'dplay_robot_speed_sel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dplay_robot',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port1 = 0;\n                var port2 = 0;\n                var port3 = 0;\n                var port4 = 0;\n                var value1 = 0;\n                var value2 = 0;\n                var value3 = 0;\n                var value4 = 0;\n                var result = 0;\n                var port = script.getField('PORT');\n                var operator = script.getNumberValue('VALUE', script);\n                operator = Math.max(operator, -100);\n                operator = Math.min(operator, 100);\n                if (port == '1') {\n                    port1 = 3;\n                    port2 = 5;\n                    if (operator > 0) {\n                        result = operator + 155;\n                        result = Math.round(result);\n                        value1 = 0;\n                        value2 = result;\n                        Entry.dplay.Left_value = value2;\n                    } else if (operator < 0) {\n                        result = operator - 155;\n                        result = Math.round(result);\n                        value1 = -result;\n                        value2 = 0;\n                        Entry.dplay.Left_value = value1;\n                    } else if (operator == 0) {\n                        value1 = 0;\n                        value2 = 0;\n                        Entry.dplay.Left_value = 0;\n                    }\n                }\n                if (port == '2') {\n                    port3 = 6;\n                    port4 = 11;\n                    if (operator > 0) {\n                        result = operator + 155;\n                        result = Math.round(result);\n                        value3 = 0;\n                        value4 = result;\n                        Entry.dplay.Right_value = value4;\n                    } else if (operator < 0) {\n                        result = operator - 155;\n                        result = Math.round(result);\n                        value3 = -result;\n                        value4 = 0;\n                        Entry.dplay.Right_value = value3;\n                    } else if (operator == 0) {\n                        value3 = 0;\n                        value4 = 0;\n                        Entry.dplay.Right_value = value3;\n                    }\n                }\n                if (port == '3') {\n                    port1 = 3;\n                    port2 = 5;\n                    port3 = 6;\n                    port4 = 11;\n                    if (operator > 0) {\n                        result = operator + 155;\n                        result = Math.round(result);\n                        value1 = 0;\n                        value2 = result;\n                        value3 = 0;\n                        value4 = result;\n                        Entry.dplay.Left_value = value2;\n                        Entry.dplay.Right_value = value4;\n                    } else if (operator < 0) {\n                        result = operator - 155;\n                        result = Math.round(result);\n                        value1 = -result;\n                        value2 = 0;\n                        value3 = -result;\n                        value4 = 0;\n                        Entry.dplay.Left_value = value1;\n                        Entry.dplay.Right_value = value3;\n                    } else if (operator == 0) {\n                        value1 = 0;\n                        value2 = 0;\n                        value3 = 0;\n                        value4 = 0;\n                        Entry.dplay.Left_value = 0;\n                        Entry.dplay.Right_value = 0;\n                    }\n                }\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue = 50;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 2;\n                        Entry.dplay.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.dplay.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    Entry.hw.setDigitalPortValue(3, 0);\n                    Entry.hw.setDigitalPortValue(5, 0);\n                    Entry.hw.setDigitalPortValue(6, 0);\n                    Entry.hw.setDigitalPortValue(11, 0);\n                    return script;\n                } else if (script.timeFlag == 2) {\n                    Entry.hw.setDigitalPortValue(port1, value1);\n                    Entry.hw.setDigitalPortValue(port2, value2);\n                    Entry.hw.setDigitalPortValue(port3, value4);\n                    Entry.hw.setDigitalPortValue(port4, value3);\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        dplay_robot_speed_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '오른쪽 바퀴 %1 왼쪽 바퀴 %2(으)로 정하기 %3',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'dplay_robot_speed_set',\n            },\n            paramsKeyMap: {\n                R_VALUE: 0,\n                L_VALUE: 1,\n            },\n            class: 'dplay_robot',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port1 = 3;\n                var port2 = 5;\n                var port3 = 6;\n                var port4 = 11;\n                var value1 = 0;\n                var value2 = 0;\n                var value3 = 0;\n                var value4 = 0;\n                var result_R = 0;\n                var result_L = 0;\n                var value_L = script.getNumberValue('L_VALUE', script);\n                value_L = Math.max(value_L, -100);\n                value_L = Math.min(value_L, 100);\n                if (value_L > 0) {\n                    result_L = value_L + 155;\n                    result_L = Math.round(result_L);\n                    value1 = 0;\n                    value2 = result_L;\n                    Entry.dplay.Left_value = value2;\n                } else if (value_L < 0) {\n                    result_L = value_L - 155;\n                    result_L = Math.round(result_L);\n                    value1 = -result_L;\n                    value2 = 0;\n                    Entry.dplay.Left_value = value1;\n                } else if (value_L == 0) {\n                    value1 = 0;\n                    value2 = 0;\n                    Entry.dplay.Left_value = 0;\n                }\n                var value_R = script.getNumberValue('R_VALUE', script);\n                value_R = Math.max(value_R, -100);\n                value_R = Math.min(value_R, 100);\n                if (value_R > 0) {\n                    result_R = value_R + 155;\n                    result_R = Math.round(result_R);\n                    value3 = 0;\n                    value4 = result_R;\n                    Entry.dplay.Right_value = value4;\n                } else if (value_R < 0) {\n                    result_R = value_R - 155;\n                    result_R = Math.round(result_R);\n                    value3 = -result_R;\n                    value4 = 0;\n                    Entry.dplay.Right_value = value3;\n                } else if (value_R == 0) {\n                    value3 = 0;\n                    value4 = 0;\n                    Entry.dplay.Right_value = 0;\n                }\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue = 50;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 2;\n                        Entry.dplay.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.dplay.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    Entry.hw.setDigitalPortValue(3, 0);\n                    Entry.hw.setDigitalPortValue(5, 0);\n                    Entry.hw.setDigitalPortValue(6, 0);\n                    Entry.hw.setDigitalPortValue(11, 0);\n                    return script;\n                } else if (script.timeFlag == 2) {\n                    Entry.hw.setDigitalPortValue(port1, value1);\n                    Entry.hw.setDigitalPortValue(port2, value2);\n                    Entry.hw.setDigitalPortValue(port3, value4);\n                    Entry.hw.setDigitalPortValue(port4, value3);\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Dplay.robot_speed_sel(%1, %2)'] },\n        },\n        dplay_robot_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFF',\n            skeleton: 'basic',\n            statements: [],\n            template: '로봇을 정지하기 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'dplay_robot_stop',\n            },\n            paramsKeyMap: {},\n            class: 'dplay_robot',\n            isNotFor: ['dplay'],\n            func: function(sprite, script) {\n                var port1 = 3;\n                var port2 = 5;\n                var port3 = 6;\n                var port4 = 11;\n                var value1 = 0;\n                var value2 = 0;\n                Entry.hw.setDigitalPortValue(port1, value1);\n                Entry.hw.setDigitalPortValue(port2, value2);\n                Entry.hw.setDigitalPortValue(port4, value1);\n                Entry.hw.setDigitalPortValue(port3, value2);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Dplay.robot_stop()'] },\n        },\n        //endregion dplay 디플레이\n    };\n};\n\nmodule.exports = Entry.dplay;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_eduino.js",
    "content": "'use strict';\n\nEntry.eduino = {\n    id: '3B.1',\n    name: 'eduino',\n    url: 'http://www.eduino.kr/',\n    imageName: 'eduino.png',\n    title: {\n        ko: '에듀이노 보드',\n        en: 'Eduino board',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.eduino.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                eduino_get_analog_value: '아날로그 %1 번 센서값',\n                eduino_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                eduino_get_ultrasonic_value: '초음파센서 Trig핀 %1 Echo핀 %2 ',\n                eduino_toggle_led: '디지털 %1 번 핀 %2 %3',\n                eduino_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                eduino_set_tone: '디지털 %1 번 핀의 부저를 %2 %3 음으로 %4 초 연주하기 %5',\n                eduino_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                eduino_get_digital: '디지털 %1 번 센서값',\n            },\n        },\n        en: {\n            template: {\n                eduino_get_analog_value: 'Analog %1 Sensor value',\n                eduino_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                eduino_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                eduino_toggle_led: 'Digital %1 Pin %2 %3',\n                eduino_digital_pwm: 'Digital %1 Pin %2 %3',\n                eduino_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                eduino_set_servo: 'Set servo pin %1 angle as %2 %3',\n                eduino_get_digital: 'Digital %1 Sensor value',\n            },\n        },\n    };\n};\n\nEntry.eduino.blockMenuBlocks = [\n    'eduino_get_analog_value',\n    'eduino_get_analog_value_map',\n    'eduino_get_ultrasonic_value',\n    'eduino_get_digital',\n    'eduino_toggle_led',\n    'eduino_digital_pwm',\n    'eduino_set_servo',\n    'eduino_set_tone',\n];\n\n//region eduino 아두이노 확장모드\nEntry.eduino.getBlocks = function() {\n    return {\n        eduino_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.eduino_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'eduino_analog_list',\n                    },\n                ],\n            },\n        },\n        eduino_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'eduino_analog_list',\n                    },\n                ],\n                type: 'eduino_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'eduinoGet',\n            isNotFor: ['eduino'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        eduino_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'eduino_get_analog_value',\n                        params: [\n                            {\n                                type: 'eduino_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'eduino_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'eduinoGet',\n            isNotFor: ['eduino'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        eduino_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'eduino_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'eduinoGet',\n            isNotFor: ['eduino'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.eduino.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        eduino_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'eduino_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'eduinoGet',\n            isNotFor: ['eduino'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'eduino' || name === 'ArduinoNano') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.eduino.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_get_digital_toggle[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_digital_toggle',\n                    },\n                ],\n            },\n        },\n        eduino_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'eduino_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'eduino',\n            isNotFor: ['eduino'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.eduino.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.eduino.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.eduino.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        eduino_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'eduino_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'eduino',\n            isNotFor: ['eduino'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.eduino.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        eduino_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'eduino_tone_list',\n                    },\n                ],\n            },\n        },\n        eduino_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'eduino_tone_list',\n                    },\n                ],\n                type: 'eduino_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'eduino_tone_value',\n                    },\n                ],\n            },\n        },\n        eduino_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'eduino_octave_list',\n                    },\n                ],\n            },\n        },\n        eduino_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'eduino_tone_list',\n                    },\n                    {\n                        type: 'eduino_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'eduino_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'eduino',\n            isNotFor: ['eduino'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.eduino.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.eduino.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.eduino.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.eduino.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.eduino.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        eduino_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'eduino_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'eduino',\n            isNotFor: ['eduino'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.eduino.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n//endregion eduino 아두이노 확장모드\n\nmodule.exports = Entry.eduino;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_edumaker.js",
    "content": "'use strict';\n\nEntry.EduMaker = {\n    id: '1B.1',\n    name: 'EduMaker',\n    imageName: 'edumaker.png',\n    title: {\n        ko: '에듀메이커 보드',\n        en: 'EduMaker Board',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\nEntry.EduMaker.blockMenuBlocks = [\n    // EduMaker Added 2017-11-30\n    'edumaker_get_analog_value',\n    'edumaker_get_analog_value_map',\n    'edumaker_get_ultrasonic_value',\n    'edumaker_get_digital',\n    'edumaker_toggle_led',\n    'edumaker_digital_pwm',\n    'edumaker_set_tone',\n    'edumaker_set_servo',\n    // EduMaker Added 2017-11-30\n];\n\nEntry.EduMaker.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                edumaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                edumaker_get_analog_value: '아날로그 %1 번 센서값',\n                edumaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                edumaker_get_digital: '디지털 %1 번 센서값',\n                edumaker_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                edumaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                edumaker_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                edumaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n            },\n            Menus: { edumaker: '에듀메이커 보드' },\n        },\n        en: {\n            template: {\n                edumaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                edumaker_get_analog_value: '아날로그 %1 번 센서값',\n                edumaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                edumaker_get_digital: '디지털 %1 번 센서값',\n                edumaker_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                edumaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                edumaker_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                edumaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n            },\n            Menus: { edumaker: 'EduMaker Board' },\n        },\n    };\n};\n\nEntry.EduMaker.getBlocks = function() {\n    return {\n        //region edumaker 에듀메이커\n        edumaker_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'edumaker_analog_list',\n                    },\n                ],\n                type: 'edumaker_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'EduMakerGet',\n            isNotFor: ['EduMaker'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'edumaker_get_analog_value',\n                        params: [\n                            {\n                                type: 'edumaker_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'edumaker_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'EduMakerGet',\n            isNotFor: ['EduMaker'],\n            func: function(sprite, script) {\n                var result = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var stringValue4 = script.getValue('VALUE4', script);\n                var stringValue5 = script.getValue('VALUE5', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'edumaker_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'EduMakerGet',\n            isNotFor: ['EduMaker'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.ArduinoExt.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'edumaker_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'EduMakerGet',\n            isNotFor: ['EduMaker'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.ArduinoExt.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ARDUINO_on, 'on'],\n                        [Lang.Blocks.ARDUINO_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'edumaker_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'EduMaker',\n            isNotFor: ['EduMaker'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.ArduinoExt.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.ArduinoExt.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ArduinoExt.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'edumaker_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'EduMaker',\n            isNotFor: ['EduMaker'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ArduinoExt.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'edumaker_tone_list',\n                    },\n                ],\n                type: 'edumkaer_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_ext_tone_list',\n                    },\n                    {\n                        type: 'arduino_ext_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'edumaker_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'EduMaker',\n            isNotFor: ['EduMaker'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) note = Entry.ArduinoExt.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.ArduinoExt.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var value = 0;\n\n                    if (note != 0) {\n                        value = Entry.ArduinoExt.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        edumaker_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'edumaker_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'EduMaker',\n            isNotFor: ['EduMaker'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.ArduinoExt.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        //endregion edumaker 에듀메이커\n    };\n};\n\nmodule.exports = Entry.EduMaker;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_elio.js",
    "content": "'use strict';\n\nEntry.elio = {\n    id: '28.1', // 엔트리에서 발급받은 하드웨어 번호를 기술합니다.\n    name: 'elio', // isNotFor 속성과 대소문자까지 정확하게 매치되어야 합니다.\n    url: 'https://mobilian.biz/#/app/product/elio', // 생략 가능합니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    imageName: 'elio.png', // images/hardware 폴더 내에 존재하는 이미지입니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    title: {\n        'ko': '엘리오',\n        'en': 'ELIO',\n    },\n    setZero: function() {\n        var sq = Entry.hw.sendQueue;\n        for (var port in  Entry.Power) {\n            sq[port] = 0;\n        }\n        Entry.hw.update();\n    },\n\n};\n\nEntry.Power = {\n    DC1: 0,\n    DC2: 0,\n    SV1: 0,\n    SV2: 0,\n\n    V3: 0,\n    V5: 0,\n    IO1: 0,\n    IO2: 0,\n    IO3: 0,\n    IO4: 0,\n};\n\nEntry.elio.getIO = function(data) {\n    if (data == '0') {\n        return 'V3';\n    } else if (data == '1') {\n        return 'V5';\n    } else if (data == '2') {\n        return 'IO1';\n    } else if (data == '3') {\n        return 'IO2';\n    } else if (data == '4') {\n        return 'IO3';\n    } else if (data == '5') {\n        return 'IO4';\n    }\n};\n\nEntry.elio.getDC = function(data) {\n    if (data == '0') {\n        return 'DC1';\n    } else if (data == '1') {\n        return 'DC2';\n    }\n};\n\nEntry.elio.getSV = function(data) {\n    if (data == '0') {\n        return 'SV1';\n    } else if (data == '1') {\n        return 'SV2';\n    }\n};\n\n// 언어 적용\nEntry.elio.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                'elio_config_block': '초음파 %1,  라인센서1 %2, 라인센서2 %3 으로 정하기 %4',\n                'elio_io_block': '%1 %2 으로 정하기 %3',\n                'elio_io_all_block': '%1 %2, %3 %4, %5 %6, %7 %8, %9 %10, %11 %12 으로 정하기 %13',\n\n                'elio_dc_block': '%1 %2 으로 정하기 %3',\n                'elio_dc_all_block': '%1 %2, %3 %4 으로 정하기 %5',\n\n                'elio_servo_block': '%1 %2 으로 정하기 %3',\n                'elio_servo_all_block': '%1 %2, %3 %4 으로 정하기 %5',\n\n                'elio_all_block': '%1 %2, %3 %4, %5 %6, %7 %8, %9 %10, %11 %12, %13 %14, %15 %16, %17 %18, %19 %20 으로 정하기 %21',\n\n                'elio_dc_value': '%1 속도값 읽기',\n                'elio_servo_value': '%1 각도 읽기',\n                'elio_io_value': '%1 값 읽기',\n\n                'elio_distance_value': '거리',\n                'elio_line1_value': '라인1',\n                'elio_line2_value': '라인2',\n\t\t\t\t\n\t\t\t\t'elio_temperature_value'\t\t: '온도',\n\t\t\t\t'elio_humidity_value'\t\t\t: '습도',\n\t\t\t\t'elio_water_value'\t\t\t: '수분'\n\n\t\t\t\t\n\t\t\t\t\n            },\n        },\n        en: {\n            template: {\n                'elio_config_block': '초음파 %1,  라인센서1 %2, 라인센서2 %3 으로 정하기 %4',\n                'elio_io_block': '%1 %2 으로 정하기 %3',\n                'elio_io_all_block': '%1 %2, %3 %4, %5 %6, %7 %8, %9 %10, %11 %12 으로 정하기 %13',\n\n                'elio_dc_block': '%1 %2 으로 정하기 %3',\n                'elio_dc_all_block': '%1 %2, %3 %4 으로 정하기 %5',\n\n                'elio_servo_block': '%1 %2 으로 정하기 %3',\n                'elio_servo_all_block': '%1 %2, %3 %4 으로 정하기 %5',\n\n                'elio_all_block': '%1 %2, %3 %4, %5 %6, %7 %8, %9 %10, %11 %12, %13 %14, %15 %16, %17 %18, %19 %20 으로 정하기 %21',\n\n                'elio_dc_value': '%1 속도값 읽기',\n                'elio_servo_value': '%1 각도 읽기',\n                'elio_io_value': '%1 값 읽기',\n\n                'elio_distance_value': '거리',\n                'elio_line1_value': '라인1',\n                'elio_line2_value': '라인2',\n\t\t\t\t\n\t\t\t\t'elio_temperature_value'\t\t: '온도',\n\t\t\t\t'elio_humidity_value'\t\t\t: '습도',\n\t\t\t\t'elio_water_value'\t\t\t: '수분'\n\n            },\n        },\n    };\n};\n\n// 엔트리에 등록할 블록들의 블록명 작성\nEntry.elio.blockMenuBlocks = [\n    'elio_config_block',\n\n    'elio_io_block',\n    'elio_io_all_block',\n    'elio_dc_block',\n    'elio_dc_all_block',\n    'elio_servo_block',\n    'elio_servo_all_block',\n\n    'elio_all_block',\n\n    'elio_dc_value',\n    'elio_servo_value',\n    'elio_io_value',\n\n    'elio_distance_value',\n    'elio_line1_value',\n    'elio_line2_value',\n\t\t\t\n\t'elio_temperature_value',\n\t'elio_humidity_value',\n\t'elio_water_value'\n\n\n];\n\n// 블록 생성\nEntry.elio.getBlocks = function() {\n    return {\n        elio_config_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['OFF', '0'],\n                        ['ON', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['OFF', '0'],\n                        ['ON', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['OFF', '0'],\n                        ['ON', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', '1', '0'],\n                type: 'elio_config_block',\n            },\n\n            paramsKeyMap: {\n                SONIC: 0,\n                LINE1: 1,\n                LINE2: 2,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n\n                var sonic = script.getStringField('SONIC', script);\n                var line1 = script.getStringField('LINE1', script);\n                var line2 = script.getStringField('LINE2', script);\n\n                var sq = Entry.hw.sendQueue;\n\n                Entry.hw.sendQueue['SONIC'] = sonic;\n                Entry.hw.sendQueue['LINE1'] = line1;\n                Entry.hw.sendQueue['LINE2'] = line2;\n\n                return script.callReturn();\n            },\n        },\n\n\n        elio_io_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', null],\n                type: 'elio_io_block',\n            },\n\n            paramsKeyMap: {\n                IO: 0,\n                VALUE: 1,\n            },\n\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var io = Entry.elio.getIO(script.getStringField('IO', script));\n                var value = script.getValue('VALUE', script);\n                var sq = Entry.hw.sendQueue;\n                Entry.hw.sendQueue[io] = value;\n                return script.callReturn();\n            },\n        },\n\n        elio_io_all_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', '100', '1', '100', '2', '100', '3', '100', '4', '100', '5', '100', '6', '100'],\n                type: 'elio_io_all_block',\n            },\n\n            paramsKeyMap: {\n                IO1: 0,\n                V1: 1,\n\n                IO2: 2,\n                V2: 3,\n\n\n                IO3: 4,\n                V3: 5,\n\n                IO4: 6,\n                V4: 7,\n\n                IO5: 8,\n                V5: 9,\n\n                IO6: 10,\n                V6: 11,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var io1 = Entry.elio.getIO(script.getStringField('IO1', script));\n                var v1 = script.getValue('V1', script);\n\n                var io2 = Entry.elio.getIO(script.getStringField('IO2', script));\n                var v2 = script.getValue('V2', script);\n\n                var io3 = Entry.elio.getIO(script.getStringField('IO3', script));\n                var v3 = script.getValue('V3', script);\n\n                var io4 = Entry.elio.getIO(script.getStringField('IO4', script));\n                var v4 = script.getValue('V4', script);\n\n                var io5 = Entry.elio.getIO(script.getStringField('IO5', script));\n                var v5 = script.getValue('V5', script);\n\n                var io6 = Entry.elio.getIO(script.getStringField('IO6', script));\n                var v6 = script.getValue('V6', script);\n\n                var sq = Entry.hw.sendQueue;\n\n                Entry.hw.sendQueue[io1] = v1;\n                Entry.hw.sendQueue[io2] = v2;\n                Entry.hw.sendQueue[io3] = v3;\n                Entry.hw.sendQueue[io4] = v4;\n                Entry.hw.sendQueue[io5] = v5;\n                Entry.hw.sendQueue[io6] = v6;\n                //왜 소스가 반영이 안되지...\n                return script.callReturn();\n            },\n        },\n\n\n        elio_dc_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['DC1', '0'],\n                        ['DC2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', 50],\n                type: 'elio_dc_block',\n            },\n            paramsKeyMap: {\n                DC1: 0,\n                V1: 1,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var dc1 = Entry.elio.getDC(script.getStringField('DC1', script));\n                var v1 = script.getValue('V1', script);\n\n                var sq = Entry.hw.sendQueue;\n                Entry.hw.sendQueue[dc1] = v1;\n\n                return script.callReturn();\n            },\n        },\n\n        elio_dc_all_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['DC1', '0'],\n                        ['DC2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['DC1', '0'],\n                        ['DC2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', '30', '1', '30'],\n                type: 'elio_dc_all_block',\n            },\n            paramsKeyMap: {\n                DC1: 0,\n                V1: 1,\n                DC2: 2,\n                V2: 3,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n\n                var dc1 = Entry.elio.getDC(script.getStringField('DC1', script));\n                var v1 = script.getValue('V1', script);\n\n                var dc2 = Entry.elio.getDC(script.getStringField('DC2', script));\n                var v2 = script.getValue('V2', script);\n\n                var sq = Entry.hw.sendQueue;\n\n                Entry.hw.sendQueue[dc1] = v1;\n                Entry.hw.sendQueue[dc2] = v2;\n\n                return script.callReturn();\n            },\n        },\n\n        elio_servo_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['방향1', '0'],\n                        ['방향2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', null],\n                type: 'elio_servo_block',\n            },\n            paramsKeyMap: {\n                SV1: 0,\n                V1: 1,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n\n                var sv1 = Entry.elio.getSV(script.getStringField('SV1', script));\n                var v1 = script.getValue('V1', script);\n\n                var sq = Entry.hw.sendQueue;\n\n                Entry.hw.sendQueue[sv1] = v1;\n\n                return script.callReturn();\n            },\n        },\n\n        elio_servo_all_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['방향1', '0'],\n                        ['방향2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['방향1', '0'],\n                        ['방향2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', '10', '1', '10'],\n                type: 'elio_servo_all_block',\n            },\n            paramsKeyMap: {\n                SV1: 0,\n                V1: 1,\n                SV2: 2,\n                V2: 3,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var sv1 = Entry.elio.getSV(script.getStringField('SV1', script));\n                var v1 = script.getValue('V1', script);\n                var sv2 = Entry.elio.getSV(script.getStringField('SV2', script));\n                var v2 = script.getValue('V2', script);\n\n\n                var sq = Entry.hw.sendQueue;\n\n                Entry.hw.sendQueue[sv1] = v1;\n                Entry.hw.sendQueue[sv2] = v2;\n\n                return script.callReturn();\n            },\n        },\n\n        elio_all_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['모터1', '0'],\n                        ['모터2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['모터1', '0'],\n                        ['모터2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['방향1', '0'],\n                        ['방향2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['방향1', '0'],\n                        ['방향2', '1'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', '30',\n                    '1', '30',\n\n                    '0', '30',\n                    '1', '30',\n\n                    '0', '100',\n                    '1', '100',\n                    '2', '100',\n                    '3', '100',\n                    '4', '100',\n                    '5', '100',\n                ],\n                type: 'elio_all_block',\n            },\n            paramsKeyMap: {\n                DC1: 0,\n                DC1_V: 1,\n\n                DC2: 2,\n                DC2_V: 3,\n\n                SV1: 4,\n                SV1_V: 5,\n\n                SV2: 6,\n                SV2_V: 7,\n\n\n                V3: 8,\n                V3_V: 9,\n\n                V5: 10,\n                V5_V: 11,\n\n                IO1: 12,\n                IO1_V: 13,\n\n                IO2: 14,\n                IO2_V: 15,\n\n                IO3: 16,\n                IO3_V: 17,\n\n                IO4: 18,\n                IO4_V: 19,\n\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var dc1 = Entry.elio.getSV(script.getStringField('DC1', script));\n                var dc1_v = script.getValue('DC1_V', script);\n\n                var dc2 = Entry.elio.getSV(script.getStringField('DC2', script));\n                var dc2_v = script.getValue('DC2_V', script);\n\n                var sv1 = Entry.elio.getSV(script.getStringField('SV1', script));\n                var sv1_v = script.getValue('SV1_V', script);\n\n                var sv2 = Entry.elio.getSV(script.getStringField('SV2', script));\n                var sv2_v = script.getValue('SV2_V', script);\n\n                var v3 = Entry.elio.getSV(script.getStringField('V3', script));\n                var v3_v = script.getValue('V3_V', script);\n\n                var v5 = Entry.elio.getSV(script.getStringField('V5', script));\n                var v5_v = script.getValue('V5_V', script);\n\n\n                var io1 = Entry.elio.getSV(script.getStringField('IO1', script));\n                var io1_v = script.getValue('IO1_V', script);\n\n                var io2 = Entry.elio.getSV(script.getStringField('IO2', script));\n                var io2_v = script.getValue('IO2_V', script);\n\n                var io3 = Entry.elio.getSV(script.getStringField('IO3', script));\n                var io3_v = script.getValue('IO3_V', script);\n\n                var io4 = Entry.elio.getSV(script.getStringField('IO4', script));\n                var io4_v = script.getValue('IO4_V', script);\n\n\n                var sq = Entry.hw.sendQueue;\n\n                Entry.hw.sendQueue[dc1] = dc1_v;\n                Entry.hw.sendQueue[dc2] = dc2_v;\n\n                Entry.hw.sendQueue[sv1] = sv1_v;\n                Entry.hw.sendQueue[sv2] = sv2_v;\n\n                Entry.hw.sendQueue[io1] = io1_v;\n                Entry.hw.sendQueue[io2] = io2_v;\n                Entry.hw.sendQueue[io3] = io3_v;\n                Entry.hw.sendQueue[io4] = io4_v;\n\n\n                return script.callReturn();\n            },\n        },\n\n        elio_dc_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['DC1', '0'],\n                        ['DC2', '1'],\n\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['1', null],\n                type: 'elio_dc_value',\n            },\n\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var port = Entry.elio.getDC(script.getStringField('VALUE', script));\n                var pd = Entry.hw.portData;\n                return pd[port];\n            },\n        },\n\n        elio_servo_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['방향1', '0'],\n                        ['방향2', '1'],\n\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', null],\n                type: 'elio_servo_value',\n            },\n\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var port = Entry.elio.getSV(script.getStringField('VALUE', script));\n                var pd = Entry.hw.portData;\n                return pd[port];\n            },\n        },\n\n        elio_io_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n\n                    options: [\n                        ['3V', '0'],\n                        ['5V', '1'],\n                        ['IO1', '2'],\n                        ['IO2', '3'],\n                        ['IO3', '4'],\n                        ['IO4', '5'],\n\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n\n            def: {\n                params: ['0', null],\n                type: 'elio_io_value',\n            },\n\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var port = Entry.elio.getIO(script.getStringField('VALUE', script));\n                var pd = Entry.hw.portData;\n                return pd[port];\n            },\n        },\n\n        elio_distance_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'TextInput',\n                    value: 0,\n                },\n            ],\n            def: {\n                type: 'elio_distance_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                return pd['SONIC'];\n            },\n        },\n\n        elio_line1_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'TextInput',\n                    value: 0,\n                },\n            ],\n            def: {\n                type: 'elio_line1_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                //var port = Entry.elio.getDC(script.getStringField('VALUE', script));\n                var pd = Entry.hw.portData;\n                return pd['LINE1'];\n            },\n        },\n\n        elio_line2_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'TextInput',\n                    value: 0,\n                },\n            ],\n            def: {\n                type: 'elio_line2_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'elio',\n            isNotFor: ['elio'],\n            func: function(sprite, script) {\n                //var port = Entry.elio.getDC(script.getStringField('VALUE', script));\n                var pd = Entry.hw.portData;\n                return pd['LINE2'];\n            },\n        },\n\t\t\n\t\telio_temperature_value: {\n\t\t\tcolor: '#00CFCA',\n\t\t\touterLine: '#04B5B0',\n\t\t\tskeleton: 'basic_string_field',\n\t\t\tfontColor: '#fff',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'TextInput',\n\t\t\t\t\tvalue: 0\n\t\t\t\t}\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\ttype: 'elio_temperature_value'\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0\n\t\t\t},\n\t\t\tclass: 'elio',\n\t\t\tisNotFor: ['elio'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\t\t//var port = Entry.elio.getDC(script.getStringField('VALUE', script));\n\t\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\t\treturn pd[\"TEMPERATURE\"];\n\t\t\t}\n\t\t},\n\t\t\n\t\telio_humidity_value: {\n\t\t\tcolor: '#00CFCA',\n\t\t\touterLine: '#04B5B0',\n\t\t\tskeleton: 'basic_string_field',\n\t\t\tfontColor: '#fff',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'TextInput',\n\t\t\t\t\tvalue: 0\n\t\t\t\t}\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\ttype: 'elio_humidity_value'\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0\n\t\t\t},\n\t\t\tclass: 'elio',\n\t\t\tisNotFor: ['elio'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\t\t//var port = Entry.elio.getDC(script.getStringField('VALUE', script));\n\t\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\t\treturn pd[\"HUMIDITY\"];\n\t\t\t}\n\t\t},\n\t\t\n\t\telio_water_value: {\n\t\t\tcolor: '#00CFCA',\n\t\t\touterLine: '#04B5B0',\n\t\t\tskeleton: 'basic_string_field',\n\t\t\tfontColor: '#fff',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'TextInput',\n\t\t\t\t\tvalue: 0\n\t\t\t\t}\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\ttype: 'elio_water_value'\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0\n\t\t\t},\n\t\t\tclass: 'elio',\n\t\t\tisNotFor: ['elio'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\t\t//var port = Entry.elio.getDC(script.getStringField('VALUE', script));\n\t\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\t\treturn pd[\"WATER\"];\n\t\t\t}\n\t\t},\t\t\n    };\n};\n\n// 엔트리에서 하드웨어 블록 클래스를 인식할 수 있도록 내보내기\nmodule.exports = Entry.elio;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_etboard.js",
    "content": "'use strict';\n\nEntry.etboard = {\n    id: ['2F.1'],\n    name: 'etboard',\n    url: 'http://et.ketri.re.kr',\n    imageName: 'etboard.png',\n    title: {\n        ko: 'ET-BOARD(USB)',\n        en: 'ET-BOARD(USB)',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                // 서보모터(SERVO_PIN, type: 4)인 경우 제외하고 나머지만 0으로 설정\n                if (Entry.hw.sendQueue.SET[key].type !== 4) {\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n      ALIVE: 0,\n      DIGITAL: 1,\n      ANALOG: 2,\n      PWM: 3,\n      SERVO_PIN: 4,\n      TONE: 5,\n      PULSEIN: 6,\n      ULTRASONIC: 7,\n      TIMER: 8,\n      OLED: 241,\n      COM: 242,\n    \tNEOPIXELCOLOR: 243,\n\n    },\n    duration: {\n          TIME_1ms: 1,\n          TIME_5ms: 5,\n          TIME_10ms: 10,\n          TIME_20ms: 20,\n          TIME_50ms: 50,\n          TIME_100ms: 100,\n          TIME_200ms: 200,\n          TIME_500ms: 500,\n          TIME_600ms: 600,\n      },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.etboard.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n              GreenColor: '초록색',\n              BlueColor: '파랑색',\n              YellowColor: '노랑색',\n              RedColor: '빨강색',\n              GreenButton: '초록 버튼',\n              BlueButton: '파랑 버튼',\n              YellowButton: '노랑 버튼',\n              RedButton: '빨강 버튼',\n            },\n            template: {\n                etboard_serial_set: '시리얼 통신으로 설정하고 %1 속도로 전송하기',\n                etboard_ble_set: '블루투스 통신으로 설정하고 %1 속도로 전송하기',\n                etboard_get_analog_value: '아날로그 %1 센서값',\n                etboard_toggle_pin: '디지털 %1 번핀 %2',\n                etboard_port_number: '%1',\n                etboard_ultrasonic_get_value:'초음파 송신 %1 핀 수신 %2 핀',\n                etboard_get_digital_button: '%1 누름',\n                etboard_get_digital: '디지털 %1번 센서값',\n                etboard_toggle_led: 'LED %1 을 %2',\n                etboard_get_port_number1: '%1',\n                etboard_get_port_number: '%1',\n                etboard_get_ultrasonic_port_number: '%1',\n                etboard_set_servo: '서보모터 %1번 핀을 %2 도로 정하기',\n                etboard_oled_set: 'OLED %1 번째 줄의 %2 표시하기',\n                etboard_pw_get_port_number: '%1',\n                etboard_neopixel_set: '디지털 %1 번 핀에 연결된 %2 번째 네오픽셀 %3 개 사용하기',\n                etboard_neopixel_led: '네오픽셀 %1 번에 %2 번째 LED R: %3 , G: %4 , B: %5 색을 밝기 %6 으로 켜기',\n                etboard_neopixel_all_led: '네오픽셀 %1 번에 LED R: %2 , G: %3 , B: %4 색을 밝기 %5 으로 켜기',\n            },\n        },\n        en: {\n            Blocks: {\n              GreenColor: 'Green Color',\n              BlueColor: 'Blue Color',\n              YellowColor: 'Yellow Color',\n              RedColor: 'Red Color',\n              GreenButton: 'Green Button',\n              BlueButton: 'Blue Button',\n              YellowButton: 'Yellow Button',\n              RedButton: 'Red Button',\n            },\n            template: {\n              etboard_serial_set: 'Set Serial COMM %1 boardrates',\n              etboard_ble_set: 'Set Bluetooth COMM %1 boardrates',\n              etboard_get_analog_value: 'Analog %1 Value',\n              etboard_toggle_pin: 'Digital %1 PIN %2',\n              etboard_port_number: '%1',\n              etboard_ultrasonic_get_value:'Ultrasonic Trigger %1 PIN echo %2 PIN Value',\n              etboard_get_digital_button: '%1 Push',\n              etboard_get_digital: 'Digital %1 PIN Value',\n              etboard_toggle_led: '%1 LED %2',\n              etboard_get_port_number1: '%1',\n              etboard_get_port_number: '%1',\n              etboard_get_ultrasonic_port_number: '%1',\n              etboard_set_servo: 'Servo %1 PIN %2 degree set',\n              etboard_oled_set: 'OLE %1 line %2 Display',\n              etboard_pw_get_port_number: '%1',\n              etboard_neopixel_set: '디지털 %1 번핀에 연결된 %2 개의 네오픽셀 LED 사용하기',\n              etboard_neopixel_led: '디지털 %1 번핀에 연결된 %2  번째 네오픽셀 LED R: %3 , G: %4 , B: %5 색으로 켜기',\n              etboard_neopixel_all_led: '디지털 %1 번 핀에 연결된 %2  번째 네오픽셀 LED R: %3 , G: %4 , B: %5 색으로 켜기',\n            },\n        },\n    };\n};\n\nEntry.etboard.blockMenuBlocks = [\n    'etboard_serial_set',\n    'etboard_ble_set',\n    'etboard_get_analog_value',\n    'etboard_ultrasonic_get_value',\n    'etboard_get_digital_button',\n    'etboard_get_digital',\n    'etboard_toggle_pin',\n    'etboard_toggle_led',\n    'etboard_set_servo',\n    'etboard_oled_set',\n    'etboard_neopixel_set',\n    'etboard_neopixel_led',\n    'etboard_neopixel_all_led',\n\n];\n\nEntry.etboard.getBlocks = function() {\n    return {\n        etboard_serial_set: {\n          color: EntryStatic.colorSet.block.default.HARDWARE,\n          outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n          skeleton: 'basic',\n          statements: [],\n          params : [\n            {\n                  type: 'Dropdown',\n                  options: [\n                   ['1','1'],\n                   ['2','2'],\n                   ['3','3'],\n                   ['4','4'],\n                   ['5','5'],\n                   ['6','6'],\n                   ['7','7'],\n                   ['8','8'],\n                   ['9','9'],\n                   ['10','10'],\n                  ],\n                  value:'10',\n                  fontSize:11,\n                  bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                  arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n              },\n          ],\n          events: {},\n          def: {\n              params: [null],\n              type: 'etboard_serial_set',\n          },\n          isNotFor: [ 'etboard' ],\n          syntax: undefined,\n          paramsKeyMap: {\n              NOTE: 0,\n          },\n          class: 'COM',\n          func: function (sprite, script) {\n              var data = script.getField('NOTE');\n\n              if(!Entry.hw.sendQueue['SET']) {\n                  Entry.hw.sendQueue['SET'] = {};\n              }\n              Entry.hw.sendQueue['SET'][0] = {\n                  type: 242,\n                  data: data,\n                  time: new Date().getTime()\n              };\n              return script.callReturn();\n          },\n        },\n        etboard_ble_set: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic',\n              statements: [],\n              params: [\n          \t\t{\n                      \"type\": \"Dropdown\",\n                      \"options\": [\n                       [\"1\",\"1\"],\n                       [\"2\",\"2\"],\n                       [\"3\",\"3\"],\n                      ],\n                      \"value\":\"3\",\n                      \"fontSize\":11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n              ],\n              events: {},\n              def: {\n                  \"params\": [\n                      null,\n                  ],\n                  \"type\": \"etboard_ble_set\"\n              },\n              isNotFor: [ \"etboard\" ],\n              paramsKeyMap: {\n                  \"VALUE1\": 0,\n              },\n              class: \"COM\",\n              func: function (sprite, script) {\n                  var data = script.getField(\"VALUE1\");\n\n                  if(!Entry.hw.sendQueue['SET']) {\n                      Entry.hw.sendQueue['SET'] = {};\n                  }\n                  Entry.hw.sendQueue['SET'][1] = {\n                      type: 242,\n                      data: data,\n                      time: new Date().getTime()\n                  };\n                  return script.callReturn();\n\n              },\n          },\n          etboard_get_analog_value: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic_string_field',\n              statements: [],\n              events: {},\n              params: [\n                    {\n                        \"type\": \"Dropdown\",\n                        \"options\": [\n                            [ \"A0\", \"0\" ],\n                            [ \"A1\", \"1\" ],\n                            [ \"A2\", \"2\" ],\n                            [ \"A3\", \"3\" ],\n                            [ \"A4\", \"4\" ],\n                            [ \"A5\", \"5\" ],\n                        ],\n                        \"value\": \"0\",\n                        \"fontSize\": 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n              def: {\n                params: [ null ],\n                \"type\": \"etboard_get_analog_value\"\n              },\n              isNotFor: [ \"etboard\" ],\n              class: \"SENSOR\",\n              paramsKeyMap: {\n                  \"PORT\": 0,\n              },\n              func: function (sprite, script) {\n                var port = script.getValue(\"PORT\", script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === \"A\")\n                    port = port.substring(1)\n                return ANALOG ? ANALOG[port] || 0 : 0;\n              },\n          },\n          etboard_get_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: \"basic_string_field\",\n              statements: [],\n              params: [\n                  {\n                      \"type\": \"Dropdown\",\n                      \"options\": [\n                          [ \"2\", \"2\" ],\n                          [ \"3\", \"3\" ],\n                          [ \"4\", \"4\" ],\n                          [ \"5\", \"5\" ],\n                          [ \"6\", \"6\" ],\n                          [ \"7\", \"7\" ],\n                          [ \"8\", \"8\" ],\n                          [ \"9\", \"9\" ],\n                      ],\n                      \"value\": \"2\",\n                      \"fontSize\": 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  }\n              ],\n              events: {},\n              def: {\n                  \"params\": [ null ]\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0\n              },\n              func: function (sprite, script) {\n                  return script.getStringField(\"PORT\");\n              },\n          },\n          etboard_get_ultrasonic_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: \"basic_string_field\",\n              statements: [],\n              params: [\n                  {\n                      \"type\": \"Dropdown\",\n                      \"options\": [\n                          [ \"6\", \"6\" ],\n                          [ \"7\", \"7\" ],\n                          [ \"8\", \"8\" ],\n                          [ \"9\", \"9\" ],\n                      ],\n                      \"value\": \"2\",\n                      \"fontSize\": 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  }\n              ],\n              events: {},\n              def: {\n                  \"params\": [ null ]\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0\n              },\n              func: function (sprite, script) {\n                  return script.getStringField(\"PORT\");\n              },\n          },\n          etboard_port_number: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: \"basic_string_field\",\n              statements: [],\n              params: [\n                  {\n                    \"type\": \"Dropdown\",\n                    \"options\": [\n                      [ Lang.Blocks.RedButton, \"6\" ],\n                      [ Lang.Blocks.BlueButton, \"7\" ],\n                      [ Lang.Blocks.GreenButton, \"8\" ],\n                      [ Lang.Blocks.YellowButton, \"9\" ],\n                    ],\n                      value: \"6\",\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  }\n              ],\n              events: {},\n              def: {\n                  \"params\": [ null ]\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0\n              },\n              func: function (sprite, script) {\n                  return script.getStringField(\"PORT\");\n              },\n          },\n          etboard_toggle_pin: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                }\n            ],\n             events: {},\n              def: {\n                  \"params\": [\n                      {\n                          \"type\": \"etboard_get_port_number\"\n                      },\n                      {\n                          \"type\": \"arduino_get_digital_toggle\",\n                          \"params\": [ \"on\" ],\n                      },\n                      null\n                  ],\n                  \"type\": \"etboard_toggle_pin\"\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0,\n                  \"VALUE\": 1,\n              },\n              isNotFor: [ \"etboard\" ],\n              class: \"run\",\n              func: function (sprite, script) {\n                  var port = script.getNumberValue(\"PORT\");\n                  var value = script.getValue(\"VALUE\");\n\n                  if(typeof value === 'string') {\n                      value = value.toLowerCase();\n                  }\n                  if(Entry.ArduinoExt.highList.indexOf(value) > -1) {\n                      value = 255;\n                  } else if(Entry.ArduinoExt.lowList.indexOf(value) > -1) {\n                      value = 0;\n                  } else {\n                      throw new Error();\n                  }\n                  if(!Entry.hw.sendQueue['SET']) {\n                      Entry.hw.sendQueue['SET'] = {};\n                  }\n                  Entry.hw.sendQueue['SET'][port] = {\n                      type: Entry.etboard.sensorTypes.DIGITAL,\n                      data: value,\n                      time: new Date().getTime()\n                  };\n                  return script.callReturn();\n              },\n          },\n          etboard_ultrasonic_get_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic_string_field\",\n            params: [\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                }\n            ],\n            def: {\n                params: [{\n                    type: 'etboard_get_ultrasonic_port_number',\n                    params: [ '6' ],\n                }, {\n                    type: 'etboard_get_ultrasonic_port_number',\n                    params: [ '8' ],\n                }],\n                type: \"etboard_ultrasonic_get_value\"\n            },\n            paramsKeyMap: {\n                \"PORT1\": 0,\n                \"PORT2\": 1,\n            },\n            func: function (sprite, script) {\n                var port1 = script.getNumberValue(\"PORT1\", script);\n                var port2 = script.getNumberValue(\"PORT2\", script);\n\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if(!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.etboard.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime()\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            isNotFor: [ \"etboard\" ],\n            class: \"SENSOR\",\n        },\n        etboard_get_digital_button: {\n          color: EntryStatic.colorSet.block.default.HARDWARE,\n          outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic_boolean_field\",\n            params: [{\n                \"type\": \"Block\",\n                \"accept\": \"string\"\n            }],\n            def: {\n                \"params\": [\n                    {\n                        \"type\": \"etboard_port_number\",\n                        \"params\": [6]\n                    }\n                ],\n                \"type\": \"etboard_get_digital_button\"\n            },\n            paramsKeyMap: {\n                \"PORT\": 0\n            },\n            class: \"digital\",\n            isNotFor: [ \"etboard\" ],\n            func: function (sprite, script) {\n                var port = script.getNumberValue(\"PORT\", script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if(!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.etboard.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime()\n                };\n                return (DIGITAL) ? DIGITAL[port] || 0 : 0;\n            },\n        },\n        etboard_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic_boolean_field\",\n            params: [{\n                \"type\": \"Block\",\n                \"accept\": \"string\"\n            }],\n            def: {\n                \"params\": [\n                    {\n                        \"type\": \"etboard_get_port_number\"\n                    }\n                ],\n                \"type\": \"etboard_get_digital\"\n            },\n            paramsKeyMap: {\n                 \"PORT\": 0\n             },\n            isNotFor: [ \"etboard\" ],\n            class: \"digital\",\n            func: function (sprite, script) {\n                var port = script.getNumberValue(\"PORT\", script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if(!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.etboard.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime()\n                };\n                return (DIGITAL) ? DIGITAL[port] || 0 : 0;\n            },\n        },\n        etboard_get_port_number1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic_string_field\",\n            statements: [],\n            params: [\n                {\n                    \"type\": \"Dropdown\",\n                    \"options\": [\n                        [ Lang.Blocks.RedColor, \"2\" ],\n                        [ Lang.Blocks.BlueColor, \"3\" ],\n                        [ Lang.Blocks.GreenColor, \"4\" ],\n                        [ Lang.Blocks.YellowColor, \"5\" ],\n                    ],\n                    \"value\": \"2\",\n                    \"fontSize\": 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            \"events\": {},\n            \"def\": {\n                \"params\": [ null ]\n            },\n            \"paramsKeyMap\": {\n                \"PORT\": 0\n            },\n            \"func\": function (sprite, script) {\n                return script.getStringField(\"PORT\");\n            },\n            \"class\": \"ArduinoExt\"\n        },\n        etboard_toggle_led: {\n          color: EntryStatic.colorSet.block.default.HARDWARE,\n          outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n          skeleton: 'basic',\n          params: [\n              {\n                  \"type\": \"Block\",\n                  \"accept\": \"string\"\n              },\n              {\n                  \"type\": \"Block\",\n                  \"accept\": \"string\"\n              }\n          ],\n          def: {\n              \"params\": [\n                  {\n                      \"type\": \"etboard_get_port_number1\"\n                  },\n                  {\n                      \"type\": \"arduino_get_digital_toggle\",\n                      \"params\": [ \"on\" ],\n                  },\n              ],\n              \"type\": \"etboard_toggle_led\"\n            },\n            \"paramsKeyMap\": {\n                \"PORT\": 0,\n                \"VALUE\": 1\n            },\n            \"isNotFor\": [ \"etboard\" ],\n            \"class\": \"run\",\n            \"func\": function (sprite, script) {\n                var port = script.getNumberValue(\"PORT\");\n                var value = script.getValue(\"VALUE\");\n\n                if(typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if(Entry.ArduinoExt.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if(Entry.ArduinoExt.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.etboard.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime()\n                };\n                return script.callReturn();\n            },\n        },\n        etboard_pw_get_port_number: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: \"basic_string_field\",\n              statements: [],\n              params: [\n                  {\n                      \"type\": \"Dropdown\",\n                      \"options\": [\n                          [ \"5\", \"5\" ]\n                      ],\n                      \"value\": \"5\",\n                      \"fontSize\": 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  }\n              ],\n              events: {},\n              def: {\n                  \"params\": [ null ]\n              },\n              paramsKeyMap: {\n                  \"PORT\": 0\n              },\n              func: function (sprite, script) {\n                  return script.getStringField(\"PORT\");\n              },\n          },\n        etboard_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: \"basic\",\n            statements: [],\n            params: [\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                    type: \"etboard_pw_get_port_number\"\n                    },\n                    {\n                        \"type\": \"text\",\n                        \"params\": [ \"0\" ]\n                    },\n                    null\n                ],\n                type: \"etboard_set_servo\"\n            },\n            paramsKeyMap: {\n                \"PORT\": 0,\n                \"VALUE\": 1\n            },\n            class: \"ext\",\n            isNotFor: [ \"etboard\" ],\n            func: function (sprite, script) {\n                var port = script.getNumberValue(\"PORT\");\n                var value = script.getNumberValue(\"VALUE\");\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 180);\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: 4,\n                    data: value,\n                    time: new Date().getTime()\n                };\n                return script.callReturn();\n            },\n            \"syntax\": {}\n        },\n        etboard_oled_set: {\n          color: EntryStatic.colorSet.block.default.HARDWARE,\n          outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n          skeleton: \"basic\",\n          statements: [],\n          params: [\n              {\n                  \"type\": \"Dropdown\",\n                  \"options\": [\n                   [\"1\",\"1\"],\n                   [\"2\",\"2\"],\n                   [\"3\",\"3\"]\n                  ],\n                  \"value\":\"1\",\n                  \"fontSize\":11,\n                  bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                  arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n              },\n      \t\t    {\n                  \"type\": \"Block\",\n                  \"accept\": \"string\"\n              }\n          ],\n          events: {},\n          def: {\n              \"params\": [\n                  null,\n                  {\n                      \"type\":\"text\",\n                      \"params\": [ \"1\" ],\n                  },\n              ],\n              \"type\": \"etboard_oled_set\"\n          },\n          isNotFor: [ \"etboard\" ],\n          paramsKeyMap: {\n              \"VALUE1\": 0,\n              \"VALUE2\": 1\n          },\n          class: \"ext\",\n          func: function (sprite, script) {\n              var line = script.getField(\"VALUE1\");\n              var text = script.getValue(\"VALUE2\");\n\n              if(!Entry.hw.sendQueue['SET']) {\n                  Entry.hw.sendQueue['SET'] = {};\n              }\n              Entry.hw.sendQueue['SET'][line] = {\n                  type: 241,\n                  data: text,\n                  time: new Date().getTime()\n              };\n              return script.callReturn();\n\n          },\n          \"syntax\": {}\n          },\n          etboard_neopixel_set: {\n                  color: EntryStatic.colorSet.block.default.HARDWARE,\n                  outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                  skeleton: 'basic',\n                  statements: [],\n                  params: [\n                      {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n                      {\n                              \"type\": \"Dropdown\",\n                              \"options\": [\n                               [\"1\",\"1\"],\n                               [\"2\",\"2\"],\n                              ],\n                              \"value\":\"1\",\n                              \"fontSize\":11,\n                              bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                              arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                      },\n                      {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n                      {\n                          type: 'Indicator',\n                          img: 'block_icon/hardware_icon.svg',\n                          size: 12,\n                      },\n                  ],\n                  events: {},\n      \t\t\tdef: {\n                      params: [\n                          {\n                              type: 'arduino_get_port_number',\n                              params: ['9'],\n                          },\n                          null,\n      \t\t\t\t\t          {\n                              type: 'number',\n                              params: ['12'],\n                          },\n                          null,\n                      ],\n                      type: 'etboard_neopixel_set',\n                  },\n                  paramsKeyMap: {\n                      PORT: 0,\n                      INDEX: 1,\n                      VALUE: 2,\n                  },\n                  class: 'neopixel',\n                  isNotFor: ['etboard'],\n                  func(sprite, script) {\n                    var port = script.getNumberValue(\"PORT\");\n                    var mode = 1;\n                    var index = script.getNumberValue(\"INDEX\");\n                    var value = script.getNumberValue(\"VALUE\");\n\n                    if (!script.isStart)\n                    {\n\n                    if(!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.Orange.duration.TIME_10ms;\n          \t\t\t\t\t\tscript.isStart = true;\n          \t\t\t\t\t\tscript.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.etboard.sensorTypes.NEOPIXELCOLOR,\n                        data:\n                        {\n                          value : value,\n                          mode: mode,\n                          index: index,\n                        },\n                        time: new Date().getTime()\n                    };\n                    setTimeout(function() {\n                                  script.timeFlag = 0;\n                              }, duration );\n                              return script;\n          \t\t\t\t}\n          \t\t\t\telse if (script.timeFlag == 1)\n                          {\n                              return script;\n                          }\n                          else\n                          {\n                              delete script.timeFlag;\n                              delete script.isStart;\n\n                              Entry.engine.isContinue = false;\n                              return script.callReturn();\n                          }\n                  },\n                  syntax: {\n                  },\n              },\n      \t\tetboard_neopixel_led: {\n                  color: EntryStatic.colorSet.block.default.HARDWARE,\n                  outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                  skeleton: 'basic',\n                  statements: [],\n                  params: [\n                      {\n                              \"type\": \"Dropdown\",\n                              \"options\": [\n                               [\"1\",\"1\"],\n                               [\"2\",\"2\"],\n                              ],\n                              \"value\":\"1\",\n                              \"fontSize\":11,\n                              bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                              arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                      },\n                      {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n      \t\t\t\t{\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n      \t\t\t\t{\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n      \t\t\t\t        {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n                      {\n                          type: 'Block',\n                          accept: 'string',\n                          defaultType: 'number',\n                      },\n                      {\n                          type: 'Indicator',\n                          img: 'block_icon/hardware_icon.svg',\n                          size: 12,\n                      },\n                  ],\n                  events: {},\n      \t\t\tdef: {\n                      params: [\n                          null,\n      \t\t\t\t\t          {\n                              type: 'number',\n                              params: ['1'],\n                          },\n      \t\t\t\t\t          {\n                              type: 'number',\n                              params: ['255'],\n                          },\n      \t\t\t\t\t{\n                              type: 'number',\n                              params: ['255'],\n                          },\n      \t\t\t\t\t{\n                              type: 'number',\n                              params: ['255'],\n                          },\n                          {\n                              type: 'number',\n                              params: ['100'],\n                          },\n                          null,\n                      ],\n                      type: 'etboard_neopixel_led',\n                  },\n                  paramsKeyMap: {\n                      INDEX : 0,\n                      POS: 1,\n              \t\t\t\tRED: 2,\n              \t\t\t\tGREEN: 3,\n              \t\t\t\tBLUE: 4,\n                      BRIG: 5,\n                  },\n                  class: 'neopixel',\n                  isNotFor: ['etboard'],\n                  func(sprite, script) {\n                    var port = script.getNumberValue(\"INDEX\");\n                    var pos = script.getNumberValue(\"POS\");\n                    var red = script.getNumberValue(\"RED\");\n                    var green = script.getNumberValue(\"GREEN\");\n                    var blue = script.getNumberValue(\"BLUE\");\n                    var brig = script.getNumberValue(\"BRIG\");\n                    var mode = 2;\n\n\n                    if (!script.isStart)\n                    {\n\n                    if(!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    var duration = Entry.Orange.duration.TIME_10ms;\n                      script.isStart = true;\n                      script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.etboard.sensorTypes.NEOPIXELCOLOR,\n                        data:\n                        {\n                          index : port,\n                          pos : pos,\n                          mode: mode,\n                          red: red,\n                          green: green,\n                          blue: blue,\n                          brig: brig,\n                        },\n                        time: new Date().getTime()\n                    };\n                    setTimeout(function() {\n                                  script.timeFlag = 0;\n                              }, duration );\n                              return script;\n          \t\t\t\t}\n          \t\t\t\telse if (script.timeFlag == 1)\n                          {\n                              return script;\n                          }\n                          else\n                          {\n                              delete script.timeFlag;\n                              delete script.isStart;\n\n                              Entry.engine.isContinue = false;\n                              return script.callReturn();\n                          }\n                  },\n                  syntax: {\n                  },\n              },\n              etboard_neopixel_all_led: {\n                      color: EntryStatic.colorSet.block.default.HARDWARE,\n                      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                      skeleton: 'basic',\n                      statements: [],\n                      params: [\n                          {\n                                  \"type\": \"Dropdown\",\n                                  \"options\": [\n                                   [\"1\",\"1\"],\n                                   [\"2\",\"2\"],\n                                  ],\n                                  \"value\":\"1\",\n                                  \"fontSize\":11,\n                                  bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                  arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                          },\n                          {\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n          \t\t\t\t{\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n          \t\t\t\t{\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n          \t\t\t\t        {\n                              type: 'Block',\n                              accept: 'string',\n                              defaultType: 'number',\n                          },\n                          {\n                              type: 'Indicator',\n                              img: 'block_icon/hardware_icon.svg',\n                              size: 12,\n                          },\n                      ],\n                      events: {},\n          \t\t\tdef: {\n                          params: [\n                              null,\n          \t\t\t\t\t          {\n                                  type: 'number',\n                                  params: ['255'],\n                              },\n          \t\t\t\t\t{\n                                  type: 'number',\n                                  params: ['255'],\n                              },\n          \t\t\t\t\t{\n                                  type: 'number',\n                                  params: ['255'],\n                              },\n                              {\n                                  type: 'number',\n                                  params: ['100'],\n                              },\n                              null,\n                          ],\n                          type: 'etboard_neopixel_all_led',\n                      },\n                      paramsKeyMap: {\n                          INDEX : 0,\n                  \t\t\t\tRED: 1,\n                  \t\t\t\tGREEN: 2,\n                  \t\t\t\tBLUE: 3,\n                          BRIG: 4,\n                      },\n                      class: 'neopixel',\n                      isNotFor: ['etboard'],\n                      func(sprite, script) {\n                        var port = script.getNumberValue(\"INDEX\");\n                        var red = script.getNumberValue(\"RED\");\n                        var green = script.getNumberValue(\"GREEN\");\n                        var blue = script.getNumberValue(\"BLUE\");\n                        var brig = script.getNumberValue(\"BRIG\");\n                        var mode = 3;\n\n                        if (!script.isStart)\n                        {\n\n                        if(!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        var duration = Entry.Orange.duration.TIME_10ms;\n                          script.isStart = true;\n                          script.timeFlag = 1;\n\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.etboard.sensorTypes.NEOPIXELCOLOR,\n                            data:\n                            {\n                              index : port,\n                              mode: mode,\n                              red: red,\n                              green: green,\n                              blue: blue,\n                              brig: brig,\n                            },\n                            time: new Date().getTime()\n                        };\n                        setTimeout(function() {\n                                      script.timeFlag = 0;\n                                  }, duration );\n                                  return script;\n                      }\n                      else if (script.timeFlag == 1)\n                              {\n                                  return script;\n                              }\n                              else\n                              {\n                                  delete script.timeFlag;\n                                  delete script.isStart;\n\n                                  Entry.engine.isContinue = false;\n                                  return script.callReturn();\n                              }\n                      },\n                      syntax: {\n                      },\n                  },\n    }   //return\n};  //function\n\nmodule.exports = Entry.etboard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_etkit.js",
    "content": "'use strict';\r\n\r\nEntry.ETkit = {\r\n  id: '58.1',\r\n  name: 'ETkit',\r\n  url: 'https://2tc.co.kr/',\r\n  imageName: 'etkit.png',\r\n  title: {\r\n    ko: '이티키트',\r\n    en: 'ETkit',\r\n  },\r\n\r\n  setZero: function() {\r\n    if (!Entry.hw.sendQueue.SET) {\r\n      Entry.hw.sendQueue = {\r\n        GET: {},\r\n        SET: {},\r\n      };\r\n    } else {\r\n      var keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n      keySet.forEach(function(key) {\r\n        Entry.hw.sendQueue.SET[key].data = 0;\r\n        Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n      });\r\n    }\r\n    Entry.hw.sendQueue.GET = {};\r\n    Entry.hw.update();\r\n  },\r\n  sensorTypes: {\r\n    ALIVE:    0,\r\n    DIGITAL:  1,\r\n    ANALOG:   2,\r\n    DHT_PIN:  3,\r\n    LCD:      4,\r\n    PWM:      5,\r\n    SERVO:       6,\r\n    PULSEIN:         7,\r\n    ULTRASONIC:      8,\r\n    TIMER:              9,\r\n    WRITE_SEG:                10,\r\n    READ_SEG: 13,\r\n    READ_BLUETOOTH:     11,\r\n    WRITE_BLUETOOTH:    12,\r\n    GAS:                14\r\n  },\r\n\r\n  highList: ['high', '1', 'on'],\r\n  lowList: ['low', '0', 'off'],\r\n  BlockState: {},\r\n};\r\n\r\n\r\nEntry.ETkit.setLanguage = function () {\r\n  return {\r\n    ko: {\r\n      template: {\r\n        etkit_get_digital_pin:'디지털 %1 번 핀 센서 값',\r\n        etkit_get_digital_pin_bool:'디지털 %1 번 핀 센서 값',\r\n        etkit_get_analog_pin: '아날로그 %1 번 핀 센서 값',\r\n        etkit_get_dht: '%1 번 핀의 온도 센서 값 ',\r\n        etkit_set_digital_pin: '디지털 %1 번 핀 %2 %3',\r\n        etkit_set_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\r\n        etkit_set_digital_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\r\n        etkit_module_digital_lcd: 'LCD화면 %1 줄에 %2 나타내기 %3',\r\n        etkit_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\r\n        etkit_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\r\n        etkit_module_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\r\n        etkit_module_digital_seg: 'SEGMENT 화면에 %1 나타내기 %2',\r\n        etkit_get_digital_segment: '세그먼트 데이터 값',\r\n      },\r\n      Blocks: {\r\n        etkit_toggle_on: '켜기',\r\n        etkit_toggle_off: '끄기',\r\n        etkit_lcd_first_line: '첫 번째',\r\n        etkit_lcd_seconds_line: '두 번째',\r\n      },\r\n      Menus: {\r\n        etkit: '이티키트',\r\n      },\r\n      \r\n    },\r\n    en: {\r\n      template: {\r\n        etkit_get_digital_pin: 'Digital %1 pin sensor value',\r\n        etkit_get_digital_pin_bool: 'Digital %1 pin sensor value',\r\n        etkit_get_analog_pin: 'Read analog %1 pin sensor value',\r\n        etkit_set_digital_pin: 'Digital %1 Pin %2 %3',\r\n        etkit_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\r\n        etkit_set_digital_servo: 'Set servo pin %1 angle as %2 %3',\r\n        etkit_get_dht: 'pin %1 DHT sensor value',\r\n        etkit_module_digital_lcd: 'LCD %1 line %2 appear %3',\r\n        etkit_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\r\n        etkit_get_digital_bluetooth: 'Bluetooth RX 2 value',\r\n        etkit_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\r\n        etkit_module_digital_seg: 'SEGMENT %1 display %2',  \r\n        etkit_get_digital_segment: 'Segment data value',\r\n      },\r\n      Blocks: {\r\n        etkit_toggle_on: 'on',\r\n        etkit_toggle_off: 'off',\r\n        etkit_lcd_first_line: 'first',\r\n        etkit_lcd_seconds_line: 'seconds',\r\n      },\r\n      Menus: {\r\n        etkit: 'ETkit',\r\n      },\r\n      \r\n    },\r\n  };\r\n};\r\nEntry.ETkit.blockMenuBlocks = [ // 여기서 순서를 정함.\r\n  'etkit_get_analog_pin',\r\n  'etkit_get_digital_pin',\r\n  'etkit_get_digital_ultrasonic',\r\n  'etkit_get_dht',\r\n  'etkit_get_digital_pin_bool',\r\n  'etkit_get_digital_bluetooth',\r\n  'etkit_get_digital_segment',\r\n  'etkit_set_digital_pin',\r\n  'etkit_set_digital_pwm',\r\n  'etkit_set_digital_servo',\r\n  'etkit_module_digital_lcd',\r\n  'etkit_module_digital_bluetooth',\r\n  'etkit_module_digital_seg',\r\n];\r\n\r\nEntry.ETkit.getBlocks = function () {\r\n  return {\r\n    etkit_list_analog_basic: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic_string_field',\r\n      statements: [],\r\n      template: '%1',\r\n      params: [\r\n        {\r\n          type: 'Dropdown',\r\n          options: [\r\n            ['A0', '0'],\r\n            ['A1', '1'],\r\n            ['A2', '2'],\r\n            ['A3', '3'],\r\n            ['A4', '4'],\r\n            ['A5', '5'],\r\n          ],\r\n          value: '0',\r\n          fontSize: 11,\r\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [null],\r\n      },\r\n      paramsKeyMap: {\r\n        PORT: 0,\r\n      },\r\n      func: function (sprite, script) {\r\n        return script.getField('PORT');\r\n      },\r\n    },\r\n    etkit_get_analog_pin: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      fontColor: '#fff',\r\n      skeleton: 'basic_string_field',\r\n      template: Lang.template.etkit_get_analog_pin,\r\n      statements: [],\r\n      params: [\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [\r\n          {\r\n            type: 'etkit_list_analog_basic',\r\n          },\r\n        ],\r\n        type: 'etkit_get_analog_pin',\r\n      },\r\n      paramsKeyMap: {\r\n        PORT: 0,\r\n      },\r\n      class: 'ETkitGet',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var port = script.getValue('PORT', script);\r\n        var ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n        if (port[0] === 'A') port = port.substring(1);\r\n\r\n        return ANALOG ? ANALOG[port] || 0 : 0;\r\n      },\r\n      syntax: { js: [], py: ['etkit.get_analog_pin(%1)'] },\r\n    },\r\n    etkit_get_digital_ultrasonic: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      fontColor: '#fff',\r\n      skeleton: 'basic_string_field',\r\n      template: Lang.template.etkit_get_digital_ultrasonic,\r\n      statements: [],\r\n      params: [\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n        },\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [\r\n          {\r\n            type: 'text',\r\n            params: ['4'],\r\n          },\r\n          {\r\n            type: 'text',\r\n            params: ['5'],\r\n          },\r\n        ],\r\n        type: 'etkit_get_digital_ultrasonic',\r\n      },\r\n      paramsKeyMap: {\r\n        PORT1: 0,\r\n        PORT2: 1,\r\n      },\r\n      class: 'ETkitGet',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var port1 = script.getNumberValue('PORT1');\r\n        var port2 = script.getNumberValue('PORT2');\r\n\r\n        if (!Entry.hw.sendQueue['SET']) {\r\n          Entry.hw.sendQueue['SET'] = {};\r\n        }\r\n        delete Entry.hw.sendQueue['SET'][port1];\r\n        delete Entry.hw.sendQueue['SET'][port2];\r\n        if (!Entry.hw.sendQueue['GET']) {\r\n          Entry.hw.sendQueue['GET'] = {};\r\n        }\r\n        Entry.hw.sendQueue['GET'][Entry.ETkit.sensorTypes.ULTRASONIC] = {\r\n          port: [port1, port2],\r\n          time: new Date().getTime(),\r\n        };\r\n\r\n        return Entry.hw.portData.ULTRASONIC || 0;\r\n      },\r\n      syntax: {\r\n        js: [],\r\n        py: ['etkit.get_digital_ultrasonic(%1, %2)'],\r\n      },\r\n    },\r\n    etkit_set_digital_pwm: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      fontColor: '#fff',\r\n      skeleton: 'basic',\r\n      statements: [],\r\n      template: Lang.template.etkit_set_digital_pwm,\r\n      params: [\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n          defaultType: 'number',\r\n        },\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n          defaultType: 'number',\r\n        },\r\n        {\r\n          type: 'Indicator',\r\n          img: 'block_icon/hardware_icon.svg',\r\n          size: 12,\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [\r\n          {\r\n            type: 'etkit_list_digital_pwm',\r\n          },\r\n          {\r\n            type: 'text',\r\n            params: ['254'],\r\n          },\r\n          null,\r\n        ],\r\n        type: 'etkit_set_digital_pwm',\r\n      },\r\n      paramsKeyMap: {\r\n        PORT: 0,\r\n        VALUE: 1,\r\n      },\r\n      class: 'ETkitSet',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var port = script.getNumberValue('PORT');\r\n        var value = script.getNumberValue('VALUE');\r\n\r\n        value = Math.round(value);\r\n        value = Math.min(value, 254);\r\n        value = Math.max(value, 0);\r\n        if (!Entry.hw.sendQueue['SET']) {\r\n          Entry.hw.sendQueue['SET'] = {};\r\n        }\r\n        Entry.hw.sendQueue['SET'][port] = {\r\n          type: Entry.ETkit.sensorTypes.PWM,\r\n          data: value,\r\n          time: new Date().getTime(),\r\n        };\r\n\r\n        return script.callReturn();\r\n      },\r\n      syntax: { js: [], py: ['etkit.set_digital_pwm(%1, %2)'] },\r\n    },\r\n    etkit_list_digital_pwm: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic_string_field',\r\n      statements: [],\r\n      template: '%1',\r\n      params: [\r\n        {\r\n          type: 'Dropdown',\r\n          options: [\r\n            ['~3', '3'],\r\n            ['~5', '5'],\r\n            ['~6', '6'],\r\n            ['~9', '9'],\r\n            ['~10', '10'],\r\n            ['~11', '11'],\r\n          ],\r\n          value: '11',\r\n          fontSize: 11,\r\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [null],\r\n      },\r\n      paramsKeyMap: {\r\n        PORT: 0,\r\n      },\r\n      func: function (sprite, script) {\r\n        return script.getStringField('PORT');\r\n      },\r\n    },\r\n    etkit_list_digital_lcd: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic_string_field',\r\n      statements: [],\r\n      template: '%1',\r\n      params: [\r\n        {\r\n          type: 'Dropdown',\r\n          options: [\r\n            [Lang.Blocks.etkit_lcd_first_line, '0'],\r\n            [Lang.Blocks.etkit_lcd_seconds_line, '1'],\r\n          ],\r\n          value: '0',\r\n          fontSize: 11,\r\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [null],\r\n      },\r\n      paramsKeyMap: {\r\n        LINE: 0,\r\n      },\r\n      func: function (sprite, script) {\r\n        return script.getField('LINE');\r\n      },\r\n    },\r\n    etkit_module_digital_lcd: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic',\r\n      template: Lang.template.etkit_module_digital_lcd,\r\n      statements: [],\r\n      params: [\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n          defaultType: 'number',\r\n        },\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n        },\r\n        {\r\n          type: 'Indicator',\r\n          img: 'block_icon/hardware_icon.svg',\r\n          size: 12,\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [\r\n          {\r\n            type: 'etkit_list_digital_lcd',\r\n          },\r\n          {\r\n            type: 'text',\r\n            params: ['My Entry!!'],\r\n          },\r\n          null,\r\n        ],\r\n        type: 'etkit_module_digital_lcd',\r\n      },\r\n      paramsKeyMap: {\r\n        LINE: 0,\r\n        STRING: 1,\r\n      },\r\n      class: 'ETkitLCD',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var line = script.getNumberValue('LINE');\r\n        var string = script.getValue('STRING');\r\n        var text = [];\r\n\r\n        if (!script.isStart) {\r\n          if (typeof string === 'string' || typeof string === 'number') {\r\n            string = string.toString();\r\n            for (var i = 0; i < string.length; i++) {\r\n              text[i] = string.charCodeAt(i);\r\n            }\r\n          } else {\r\n            text[0] = string;\r\n          }\r\n\r\n          if (!Entry.hw.sendQueue['SET']) {\r\n            Entry.hw.sendQueue['SET'] = {};\r\n          }\r\n\r\n          script.isStart = true;\r\n          script.timeFlag = 1;\r\n          var fps = Entry.FPS || 60;\r\n          var timeValue = (60 / fps) * 50;\r\n\r\n          Entry.hw.sendQueue['SET'][line] = {\r\n            type: Entry.ETkit.sensorTypes.LCD,\r\n            data: {\r\n              text0: text[0],\r\n              text1: text[1],\r\n              text2: text[2],\r\n              text3: text[3],\r\n              text4: text[4],\r\n              text5: text[5],\r\n              text6: text[6],\r\n              text7: text[7],\r\n              text8: text[8],\r\n              text9: text[9],\r\n              text10: text[10],\r\n              text11: text[11],\r\n              text12: text[12],\r\n              text13: text[13],\r\n              text14: text[14],\r\n              text15: text[15],\r\n            },\r\n            time: new Date().getTime(),\r\n          };\r\n\r\n          setTimeout(function () {\r\n            script.timeFlag = 0;\r\n          }, timeValue);\r\n          return script;\r\n        } else if (script.timeFlag == 1) {\r\n          return script;\r\n        } else {\r\n          delete script.timeFlag;\r\n          delete script.isStart;\r\n          Entry.engine.isContinue = false;\r\n          return script.callReturn();\r\n        }\r\n      },\r\n      syntax: { js: [], py: ['etkit.module_digital_lcd(%1, %2)'] },\r\n    },\r\n\r\n    etkit_get_dht: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic_string_field',\r\n      params: [\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n          defaultType: 'number',\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [\r\n          {\r\n            type: 'arduino_get_port_number',\r\n            params: ['7'],\r\n          },\r\n          null,\r\n        ],\r\n        type: 'etkit_get_dht',\r\n      },\r\n      paramsKeyMap: {\r\n        PORT: 0,\r\n      },\r\n      class: 'ETkitGet',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var port = script.getNumberValue('PORT');\r\n\r\n        if (!Entry.hw.sendQueue['SET']) {\r\n          Entry.hw.sendQueue['SET'] = {};\r\n        }\r\n        delete Entry.hw.sendQueue['SET'][port];\r\n\r\n        if (!Entry.hw.sendQueue['GET']) {\r\n          Entry.hw.sendQueue['GET'] = {};\r\n        }\r\n        Entry.hw.sendQueue['GET'][Entry.ETkit.sensorTypes.DHT_PIN] = {\r\n          port: port,\r\n          time: new Date().getTime(),\r\n        };\r\n\r\n        var temp;\r\n        temp = Entry.hw.portData.DHT_PIN;\r\n        return temp || 0;\r\n\r\n      },\r\n      syntax: { js: [], py: [] },\r\n    },\r\n    etkit_get_digital_pin: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      fontColor: '#fff',\r\n      skeleton: 'basic_string_field',\r\n      statements: [],\r\n      template: Lang.template.etkit_get_digital_pin,\r\n      params: [\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n          defaultType: 'number',\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [\r\n          {\r\n            type: 'etkit_list_digital_basic',\r\n          },\r\n        ],\r\n        type: 'etkit_get_digital_pin',\r\n      },\r\n      paramsKeyMap: {\r\n        PORT: 0,\r\n      },\r\n      class: 'ETkitGet',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var port = script.getNumberValue('PORT');\r\n        var DIGITAL = Entry.hw.portData.DIGITAL;\r\n        if (!Entry.hw.sendQueue['GET']) {\r\n          Entry.hw.sendQueue['GET'] = {};\r\n        }\r\n        if (Entry.hw.sendQueue.SET[port]) {\r\n          return Entry.hw.sendQueue.SET[port].data;\r\n        } else {\r\n          Entry.hw.sendQueue['GET'][Entry.ETkit.sensorTypes.DIGITAL] = {\r\n            port: port,\r\n            time: new Date().getTime(),\r\n          };\r\n        }\r\n        return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n      },\r\n      syntax: { js: [], py: ['etkit.get_digital_pin(%1)'] },\r\n    },\r\n    etkit_get_digital_pin_bool: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      fontColor: '#fff',\r\n      skeleton: 'basic_boolean_field',\r\n      template: Lang.template.etkit_get_digital_pin_bool,\r\n      params: [\r\n          {\r\n              type: 'Block',\r\n              accept: 'string',\r\n              defaultType: 'number',\r\n          },\r\n      ],\r\n      events: {},\r\n      def: {\r\n          params: [\r\n              {\r\n                  type: 'arduino_get_port_number',\r\n                  params: [4],\r\n              },\r\n          ],\r\n          type: 'etkit_get_digital_pin_bool',\r\n      },\r\n      paramsKeyMap: {\r\n          PORT: 0,\r\n      },\r\n      class: 'ETkitGet',\r\n      isNotFor: ['ETkit'],\r\n      func(sprite, script) {\r\n          const { hwModule = {} } = Entry.hw;\r\n          const { name } = hwModule;\r\n          if (name === 'ETkit') {\r\n              //var port = script.getValue('PORT');\r\n              const port = script.getNumberValue('PORT', script);\r\n              const DIGITAL = Entry.hw.portData.DIGITAL;\r\n              if (!Entry.hw.sendQueue.GET) {\r\n                  Entry.hw.sendQueue.GET = {};\r\n              }\r\n              Entry.hw.sendQueue.GET[Entry.ETkit.sensorTypes.DIGITAL] = {\r\n                  port,\r\n                  time: new Date().getTime(),\r\n              };\r\n              return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n          } else {\r\n              return Entry.block.etkit_get_digital_pin_bool.func(sprite, script);\r\n          }\r\n      },\r\n      syntax: {\r\n          js: [],\r\n          py: [\r\n              {\r\n                  syntax: 'Arduino.etkit_get_digital_pin_bool(%1)',\r\n                  blockType: 'param',\r\n                  textParams: [\r\n                      {\r\n                          type: 'Block',\r\n                          accept: 'string',\r\n                      },\r\n                  ],\r\n              },\r\n          ],\r\n      },\r\n    },\r\n    etkit_set_digital_pin: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic',\r\n      statements: [],\r\n      template: Lang.template.etkit_set_digital_pin,\r\n      params: [\r\n          {\r\n              type: 'Block',\r\n              accept: 'string',\r\n              defaultType: 'number',\r\n          },\r\n          \r\n          {\r\n              type: 'Dropdown',\r\n              options: [\r\n                  [Lang.Blocks.ARDUINO_on, 'on'],\r\n                  [Lang.Blocks.ARDUINO_off, 'off'],\r\n              ],\r\n              value: 'on',\r\n              fontSize: 11,\r\n              bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n              arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n          },\r\n          \r\n          /*{\r\n              type: 'Block',\r\n              accept: 'string',\r\n          },*/\r\n          {\r\n              type: 'Indicator',\r\n              img: 'block_icon/hardware_icon.svg',\r\n              size: 12,\r\n          },\r\n      ],\r\n      events: {},\r\n      def: {\r\n          params: [\r\n              {\r\n                  type: 'arduino_get_port_number',\r\n                  //type: 'etkit_list_digital_basic',\r\n                  params: [5],\r\n              },\r\n              //{\r\n              //    type: 'etkit_toggle_digital_basic',\r\n              //    params: ['on'],\r\n              //},\r\n              null,\r\n              null,\r\n          ],\r\n          type: 'etkit_set_digital_pin',\r\n      },\r\n      paramsKeyMap: {\r\n          PORT: 0,\r\n          VALUE: 1,\r\n      },\r\n      class: 'ETkitSet',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n          const port = script.getNumberValue('PORT');\r\n          let value = script.getValue('VALUE');\r\n\r\n          if (typeof value === 'string') {\r\n              value = value.toLowerCase();\r\n          }\r\n          if (Entry.ETkit.highList.indexOf(value) > -1) {\r\n              value = 255;\r\n          } else if (Entry.ETkit.lowList.indexOf(value) > -1) {\r\n              value = 0;\r\n          } else {\r\n              throw new Error();\r\n          }\r\n          if (!Entry.hw.sendQueue.SET) {\r\n              Entry.hw.sendQueue.SET = {};\r\n          }\r\n          Entry.hw.sendQueue.SET[port] = {\r\n              type: Entry.ETkit.sensorTypes.DIGITAL,\r\n              data: value,\r\n              time: new Date().getTime(),\r\n          };\r\n          return script.callReturn();\r\n      },\r\n      syntax: {\r\n          js: [],\r\n          py: [\r\n              {\r\n                  syntax: 'Arduino.digitalWrite(%1, %2)',\r\n                  textParams: [\r\n                      {\r\n                          type: 'Block',\r\n                          accept: 'string',\r\n                      },\r\n                      {\r\n                          type: 'Block',\r\n                          accept: 'string',\r\n                      },\r\n                  ],\r\n              },\r\n          ],\r\n      },\r\n    },\r\n    etkit_list_digital_basic: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic_string_field',\r\n      statements: [],\r\n      template: '%1',\r\n      params: [\r\n        {\r\n          type: 'Dropdown',\r\n          options: [\r\n            ['0', '0'],\r\n            ['1', '1'],\r\n            ['2', '2'],\r\n            ['3', '3'],\r\n            ['4', '4'],\r\n            ['5', '5'],\r\n            ['6', '6'],\r\n            ['7', '7'],\r\n            ['8', '8'],\r\n            ['9', '9'],\r\n            ['10', '10'],\r\n            ['11', '11'],\r\n            ['12', '12'],\r\n            ['13', '13'],\r\n          ],\r\n          value: '10',\r\n          fontSize: 11,\r\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [null],\r\n      },\r\n      paramsKeyMap: {\r\n        PORT: 0,\r\n      },\r\n      func: function (sprite, script) {\r\n        return script.getStringField('PORT');\r\n      },\r\n    },\r\n    etkit_set_digital_servo: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      fontColor: '#fff',\r\n      skeleton: 'basic',\r\n      template: Lang.template.etkit_set_digital_servo,\r\n      statements: [],\r\n      params: [\r\n          {\r\n              type: 'Block',\r\n              accept: 'string',\r\n              defaultType: 'number',\r\n          },\r\n          {\r\n              type: 'Block',\r\n              accept: 'string',\r\n              defaultType: 'number',\r\n          },\r\n          {\r\n              type: 'Indicator',\r\n              img: 'block_icon/hardware_icon.svg',\r\n              size: 12,\r\n          },\r\n      ],\r\n      events: {},\r\n      def: {\r\n          params: [\r\n            {\r\n              type: 'arduino_get_port_number',\r\n              params: ['3'],\r\n            },\r\n            null,\r\n          ],\r\n          type: 'etkit_set_digital_servo',\r\n      },\r\n      paramsKeyMap: {\r\n          PORT: 0,\r\n          VALUE: 1,\r\n      },\r\n      class: 'ETkitSet',\r\n      isNotFor: ['ETkit'],\r\n      func: function(sprite, script) {\r\n        const sq = Entry.hw.sendQueue;\r\n        const port = script.getNumberValue('PORT', script);\r\n        let value = script.getNumberValue('VALUE', script);\r\n        value = Math.min(180, value);\r\n        value = Math.max(0, value);\r\n\r\n        if (!sq.SET) {\r\n            sq.SET = {};\r\n        }\r\n        sq.SET[port] = {\r\n            type: Entry.ETkit.sensorTypes.SERVO,\r\n            data: value,\r\n            time: new Date().getTime(),\r\n        };\r\n\r\n        return script.callReturn();\r\n      },\r\n      syntax: { js: [], py: ['etkit.set_digital_servo(%1, %2)'] },\r\n    },\r\n    etkit_get_digital_bluetooth: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic_string_field',\r\n      template: Lang.template.etkit_get_digital_bluetooth,\r\n      statements: [],\r\n      params: [],\r\n      events: {},\r\n      def: {\r\n        params: [],\r\n        type: 'etkit_get_digital_bluetooth',\r\n      },\r\n      paramsKeyMap: {},\r\n      class: 'ETkitBT',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var port = 2;\r\n        var getString = Entry.hw.portData.READ_BLUETOOTH;\r\n        if (!Entry.hw.sendQueue['SET']) {\r\n          Entry.hw.sendQueue['SET'] = {};\r\n        }\r\n        delete Entry.hw.sendQueue['SET'][port];\r\n        if (!Entry.hw.sendQueue['GET']) {\r\n          Entry.hw.sendQueue['GET'] = {};\r\n        }\r\n        Entry.hw.sendQueue['GET'][Entry.ETkit.sensorTypes.READ_BLUETOOTH] = {\r\n          port: port,\r\n          time: new Date().getTime(),\r\n        };\r\n\r\n        return getString ? getString.slice(0, getString.length - 1) : ' ';\r\n      },\r\n      syntax: { js: [], py: ['etkit.get_digital_bluetooth()'] },\r\n    },\r\n    etkit_module_digital_bluetooth: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic',\r\n      template: Lang.template.etkit_module_digital_bluetooth,\r\n      statements: [],\r\n      params: [\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n        },\r\n        {\r\n          type: 'Indicator',\r\n          img: 'block_icon/hardware_icon.svg',\r\n          size: 12,\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [\r\n          {\r\n            type: 'text',\r\n            params: ['My Entry!!'],\r\n          },\r\n          null,\r\n        ],\r\n        type: 'etkit_module_digital_bluetooth',\r\n      },\r\n      paramsKeyMap: {\r\n        STRING: 0,\r\n      },\r\n      class: 'ETkitBT',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var string = script.getValue('STRING');\r\n        var port = 3;\r\n        var text = [];\r\n\r\n        if (!script.isStart) {\r\n          if (typeof string === 'string') {\r\n            for (var i = 0; i < string.length; i++) {\r\n              text[i] = string.charCodeAt(i);\r\n            }\r\n          } else {\r\n            text[0] = string;\r\n          }\r\n          if (!Entry.hw.sendQueue['SET']) {\r\n            Entry.hw.sendQueue['SET'] = {};\r\n          }\r\n\r\n          script.isStart = true;\r\n          script.timeFlag = 1;\r\n          var fps = Entry.FPS || 60;\r\n          var timeValue = (60 / fps) * 50;\r\n\r\n          Entry.hw.sendQueue['SET'][port] = {\r\n            type: Entry.ETkit.sensorTypes.WRITE_BLUETOOTH,\r\n            data: {\r\n              text0: text[0],\r\n              text1: text[1],\r\n              text2: text[2],\r\n              text3: text[3],\r\n              text4: text[4],\r\n              text5: text[5],\r\n              text6: text[6],\r\n              text7: text[7],\r\n              text8: text[8],\r\n              text9: text[9],\r\n              text10: text[10],\r\n              text11: text[11],\r\n              text12: text[12],\r\n              text13: text[13],\r\n              text14: text[14],\r\n              text15: text[15],\r\n            },\r\n            time: new Date().getTime(),\r\n          };\r\n\r\n          setTimeout(function () {\r\n            script.timeFlag = 0;\r\n          }, timeValue);\r\n          return script;\r\n        } else if (script.timeFlag == 1) {\r\n          return script;\r\n        } else {\r\n          delete script.timeFlag;\r\n          delete script.isStart;\r\n          Entry.engine.isContinue = false;\r\n          return script.callReturn();\r\n        }\r\n      },\r\n      syntax: { js: [], py: ['etkit.module_digital_bluetooth(%1)'] },\r\n    },\r\n    etkit_module_digital_seg: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic',\r\n      statements: [],\r\n      template: Lang.template.etkit_module_digital_seg,\r\n      params: [\r\n        {\r\n          type: 'Block',\r\n          accept: 'string',\r\n        },\r\n        {\r\n          type: 'Indicator',\r\n          img: 'block_icon/hardware_icon.svg',\r\n          size: 12,\r\n        },\r\n      ],\r\n      events: {},\r\n      def: {\r\n        params: [\r\n          {\r\n            type: 'text',\r\n            params: ['1234'],\r\n          },\r\n          null,\r\n        ],\r\n        type: 'etkit_module_digital_seg',\r\n      },\r\n      paramsKeyMap: {\r\n        STRING : 0,\r\n      },\r\n      class: 'ETkitSEG',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var port = 0;\r\n        var string = script.getValue('STRING');\r\n        var string2 = script.getValue('STRING2');\r\n        var text = [];\r\n        if(!script.isStart) {\r\n          if(typeof string === 'string') {\r\n            for(var i=0; i<string.length; i++) {\r\n              text[i] = string.charCodeAt(i);\r\n            }\r\n          }\r\n          else if(typeof string === 'number') {\r\n            text[0] = 1;\r\n            text[1] = string / 1;\r\n          } else {\r\n            text[0] = string;\r\n          }\r\n          if (!Entry.hw.sendQueue['SET']) {\r\n            Entry.hw.sendQueue['SET'] = {};\r\n          }\r\n          script.isStart = true;\r\n          script.timeFlag = 1;\r\n          var fps = Entry.FPS || 60;\r\n          var timeValue = (60 / fps) * 50;\r\n\r\n          Entry.hw.sendQueue['SET'][port] = {\r\n            type: Entry.ETkit.sensorTypes.WRITE_SEG,\r\n            data: {\r\n              text0: text[0],\r\n              text1: text[1],\r\n              text2: text[2],\r\n              text3: text[3],\r\n              text4: text[4],\r\n              text5: text[5],\r\n              text6: text[6],\r\n              text7: text[7],\r\n              text8: text[8],\r\n              text9: text[9],\r\n              text10: text[10],\r\n              text11: text[11],\r\n              text12: text[12],\r\n              text13: text[13],\r\n              text14: text[14],\r\n              text15: text[15],\r\n            },\r\n            time: new Date().getTime(),\r\n          };\r\n          setTimeout(function () {\r\n            script.timeFlag = 0;\r\n          }, timeValue);\r\n          return script;\r\n        } else if (script.timeFlag == 1) {\r\n          return script;\r\n        } else {\r\n          delete script.timeFlag;\r\n          delete script.isStart;\r\n          Entry.engine.isContinue = false;\r\n\r\n          return script.callReturn();\r\n        }\r\n      },\r\n      syntax: { js: [], py: [] },\r\n    },\r\n    etkit_get_digital_segment: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic_string_field',\r\n      template: Lang.template.etkit_get_digital_segment,\r\n      statements: [],\r\n      params: [],\r\n      events: {},\r\n      def: {\r\n        params: [],\r\n        type: 'etkit_get_digital_segment',\r\n      },\r\n      paramsKeyMap: {},\r\n      class: 'ETkitSEG',\r\n      isNotFor: ['ETkit'],\r\n      func: function (sprite, script) {\r\n        var port = 4;\r\n        var getString = Entry.hw.portData.READ_SEG;\r\n        if (!Entry.hw.sendQueue['SET']) {\r\n          Entry.hw.sendQueue['SET'] = {};\r\n        }\r\n        delete Entry.hw.sendQueue['SET'][port];\r\n        if (!Entry.hw.sendQueue['GET']) {\r\n          Entry.hw.sendQueue['GET'] = {};\r\n        }\r\n        Entry.hw.sendQueue['GET'][Entry.ETkit.sensorTypes.READ_SEG] = {\r\n          port: port,\r\n          time: new Date().getTime(),\r\n        };\r\n        var temp = getString.slice(0, getString.length - 1);\r\n        \r\n        return getString ? getString.slice(0, getString.length - 1) : ' ';\r\n      },\r\n      syntax: { js: [], py: ['etkit.get_digital_segment()'] },\r\n    },\r\n    arduino_get_port_number: {\r\n      color: EntryStatic.colorSet.block.default.HARDWARE,\r\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n      skeleton: 'basic_string_field',\r\n      statements: [],\r\n      //template: Lang.template.arduino_get_port_number,\r\n      template: '%1',\r\n      params: [\r\n          {\r\n              type: 'Dropdown',\r\n              options: [\r\n                  ['0', '0'],\r\n                  ['1', '1'],\r\n                  ['2', '2'],\r\n                  ['3', '3'],\r\n                  ['4', '4'],\r\n                  ['5', '5'],\r\n                  ['6', '6'],\r\n                  ['7', '7'],\r\n                  ['8', '8'],\r\n                  ['9', '9'],\r\n                  ['10', '10'],\r\n                  ['11', '11'],\r\n                  ['12', '12'],\r\n                  ['13', '13'],\r\n              ],\r\n              value: '5',\r\n              fontSize: 11,\r\n              bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n              arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n          },\r\n      ],\r\n      events: {},\r\n      def: {\r\n          params: [null],\r\n      },\r\n      paramsKeyMap: {\r\n          PORT: 0,\r\n      },\r\n      func(sprite, script) {\r\n          return script.getStringField('PORT');\r\n      },\r\n      syntax: {\r\n          js: [],\r\n          py: [\r\n              {\r\n                  syntax: '%1',\r\n                  textParams: [\r\n                      {\r\n                          type: 'Dropdown',\r\n                          options: [\r\n                              ['0', '0'],\r\n                              ['1', '1'],\r\n                              ['2', '2'],\r\n                              ['3', '3'],\r\n                              ['4', '4'],\r\n                              ['5', '5'],\r\n                              ['6', '6'],\r\n                              ['7', '7'],\r\n                              ['8', '8'],\r\n                              ['9', '9'],\r\n                              ['10', '10'],\r\n                              ['11', '11'],\r\n                              ['12', '12'],\r\n                              ['13', '13'],\r\n                          ],\r\n                          value: '0',\r\n                          fontSize: 11,\r\n                          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                      },\r\n                  ],\r\n                  keyOption: 'arduino_get_port_number',\r\n              },\r\n          ],\r\n      },\r\n  },\r\n  \r\n  };\r\n}\r\n\r\nmodule.exports = Entry.ETkit;"
  },
  {
    "path": "src/playground/blocks/hardware/block_ev3.js",
    "content": "'use strict';\n\nEntry.EV3 = {\n    PORT_MAP: {\n        A: 0,\n        B: 0,\n        C: 0,\n        D: 0,\n        '1': undefined,\n        '2': undefined,\n        '3': undefined,\n        '4': undefined,\n    },\n    motorMovementTypes: {\n        Degrees: 0,\n        Power: 1,\n    },\n    deviceTypes: {\n        NxtTouch: 1,\n        NxtLight: 2,\n        NxtSound: 3,\n        NxtColor: 4,\n        NxtUltrasonic: 5,\n        NxtTemperature: 6,\n        LMotor: 7,\n        MMotor: 8,\n        Touch: 16,\n        Color: 29,\n        Ultrasonic: 30,\n        Gyroscope: 32,\n        Infrared: 33,\n        Initializing: 0x7d,\n        Empty: 0x7e,\n        WrongPort: 0x7f,\n        Unknown: 0xff,\n    },\n    colorSensorValue: ['', '000000', '0000FF', '00FF00', 'FFFF00', 'FF0000', 'FFFFFF', 'A52A2A'],\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    setZero: function() {\n        var portMap = this.PORT_MAP;\n        Object.keys(portMap).forEach(function(port) {\n            var regex = /[A-D]/i;\n            if (regex.test(port)) {\n                Entry.hw.sendQueue[port] = {\n                    type: Entry.EV3.motorMovementTypes.Power,\n                    power: 0,\n                };\n            } else {\n                Entry.hw.sendQueue[port] = portMap[port];\n            }\n        });\n        Entry.hw.sendQueue.STATUS_COLOR = 'GREEN';\n        Entry.hw.update();\n    },\n    id: '12.1',\n    name: 'EV3',\n    url: 'http://www.lego.com/ko-kr/mindstorms/about-ev3',\n    imageName: 'ev3.png',\n    title: {\n        ko: 'EV3',\n        en: 'EV3',\n    },\n};\n\nEntry.EV3.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                ev3_get_sensor_value: '%1 의 값',\n                ev3_touch_sensor: '%1 의 터치센서가 작동되었는가?',\n                ev3_button_pressed: '%1 버튼이 눌려져있는가?',\n                ev3_color_sensor: '%1 의 %2 값',\n                ev3_motor_power: '%1 의 값을 %2 으로 출력 %3',\n                ev3_motor_power_on_time: '%1 의 값을 %2 초 동안 %3 으로 출력 %4',\n                ev3_motor_degrees: '%1 의 값을 %2 으로  %3 도 만큼 회전 %4',\n                ev3_status_led: 'LED 색깔을 %1 (으)로 정하기 %2',\n            },\n            Blocks: {\n                ev3_ccw: '반시계',\n                ev3_cw: '시계',\n            },\n            Menus: {\n                ev3: 'EV3',\n            },\n            Device: {\n                ev3: 'EV3',\n            },\n        },\n        en: {\n            template: {\n                ev3_get_sensor_value: \"%1's value\",\n                ev3_touch_sensor: \"%1's touch sensor activated?\",\n                ev3_button_pressed: \"%1's button pressed?\",\n                ev3_color_sensor: \"%1's %2 value\",\n                ev3_motor_power: \"%1's value print as %2 %3\",\n                ev3_motor_power_on_time: \"%1's value for %2seconds %3 printed %4\",\n                ev3_motor_degrees: \"%1's value in %2 direction turn %3 degrees %4\",\n                ev3_status_led: 'Set status light to %1 %2',\n            },\n            Blocks: {\n                ev3_ccw: 'CCW',\n                ev3_cw: 'CW',\n            },\n            Menus: {\n                ev3: 'EV3',\n            },\n            Device: {\n                ev3: 'EV3',\n            },\n        },\n    };\n};\nEntry.EV3.blockMenuBlocks = [\n    'ev3_get_sensor_value',\n    'ev3_touch_sensor',\n    'ev3_button_pressed',\n    'ev3_color_sensor',\n    'ev3_motor_power',\n    'ev3_motor_power_on_time',\n    'ev3_motor_degrees',\n    'ev3_status_led',\n];\nEntry.EV3.getBlocks = function() {\n    return {\n        //region ev3 이브이3\n        ev3_color_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['RGB', 'RGB'],\n                        ['R', 'R'],\n                        ['G', 'G'],\n                        ['B', 'B'],\n                    ],\n                    value: 'RGB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'ev3_color_sensor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                RGB: 1,\n            },\n            class: 'ev3_sensor',\n            isNotFor: ['EV3'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var rgb = script.getStringField('RGB', script);\n                var portData = Entry.hw.getDigitalPortValue(script.getNumberField('PORT', script));\n                var result = '';\n                if (portData.type == Entry.EV3.deviceTypes.Color) {\n                    if (portData.siValue == 0) {\n                        result = '';\n                    } else {\n                        switch (rgb) {\n                            case 'RGB':\n                                result = Entry.EV3.colorSensorValue[portData.siValue];\n                                break;\n                            case 'R':\n                                result = Entry.EV3.colorSensorValue[portData.siValue].substring(\n                                    0,\n                                    2\n                                );\n                                break;\n                            case 'G':\n                                result = Entry.EV3.colorSensorValue[portData.siValue].substring(\n                                    2,\n                                    4\n                                );\n                                break;\n                            case 'B':\n                                result = Entry.EV3.colorSensorValue[portData.siValue].substring(\n                                    4,\n                                    6\n                                );\n                                break;\n                        }\n                    }\n                } else {\n                    result = '컬러 센서 아님';\n                }\n                return result;\n            },\n        },\n        ev3_get_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ev3_get_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ev3_sensor',\n            isNotFor: ['EV3'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var portData = Entry.hw.getDigitalPortValue(script.getNumberField('PORT', script));\n                var result;\n                if ($.isPlainObject(portData)) {\n                    result = portData.siValue || 0;\n                }\n                return result;\n            },\n        },\n        ev3_motor_degrees: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                        ['C', 'C'],\n                        ['D', 'D'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ev3_cw, 'CW'],\n                        [Lang.Blocks.ev3_ccw, 'CCW'],\n                    ],\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'angle',\n                    },\n                ],\n                type: 'ev3_motor_degrees',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                DEGREE: 2,\n            },\n            class: 'ev3_output',\n            isNotFor: ['EV3'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var degree = script.getValue('DEGREE', script);\n                if (degree <= 0) {\n                    degree = 0;\n                } else if (degree >= 720) {\n                    degree = 720;\n                }\n                var direction = script.getStringField('DIRECTION', script);\n                Entry.hw.sendQueue[port] = {\n                    id: Math.floor(Math.random() * 100000, 0),\n                    type: Entry.EV3.motorMovementTypes.Degrees,\n                    degree: degree,\n                    power: direction == 'CW' ? 50 : -50,\n                };\n                return script.callReturn();\n            },\n        },\n        ev3_motor_power: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                        ['C', 'C'],\n                        ['D', 'D'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                ],\n                type: 'ev3_motor_power',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'ev3_output',\n            isNotFor: ['EV3'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var value = script.getValue('VALUE', script);\n                Entry.hw.sendQueue[port] = {\n                    id: Math.floor(Math.random() * 100000, 0),\n                    type: Entry.EV3.motorMovementTypes.Power,\n                    power: value,\n                };\n                return script.callReturn();\n            },\n        },\n        ev3_motor_power_on_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                        ['C', 'C'],\n                        ['D', 'D'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                ],\n                type: 'ev3_motor_power_on_time',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                TIME: 1,\n                VALUE: 2,\n            },\n            class: 'ev3_output',\n            isNotFor: ['EV3'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getStringField('PORT', script);\n                if (!script.isStart) {\n                    var time = script.getValue('TIME', script);\n                    var value = script.getValue('VALUE', script);\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue[port] = {\n                        id: Math.floor(Math.random() * 100000, 0),\n                        type: Entry.EV3.motorMovementTypes.Power,\n                        power: value,\n                    };\n                    var timeValue = time * 1000;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.EV3.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.EV3.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    Entry.hw.sendQueue[port] = {\n                        id: Math.floor(Math.random() * 100000, 0),\n                        type: Entry.EV3.motorMovementTypes.Power,\n                        power: 0,\n                    };\n                    return script.callReturn();\n                }\n            },\n        },\n        ev3_touch_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ev3_touch_sensor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ev3_sensor',\n            isNotFor: ['EV3'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var portData = Entry.hw.getDigitalPortValue(script.getNumberField('PORT', script));\n                var result = false;\n                if (portData.type == Entry.EV3.deviceTypes.Touch) {\n                    if (Number(portData.siValue) >= 1) {\n                        result = true;\n                    }\n                }\n\n                return result;\n            },\n        },\n        ev3_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['위', 'UP'],\n                        ['아래', 'DOWN'],\n                        ['왼쪽', 'LEFT'],\n                        ['오른쪽', 'RIGHT'],\n                        ['가운데', 'ENTER'],\n                        ['뒤로', 'BACK'],\n                    ],\n                    value: 'UP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ev3_button_pressed',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'ev3_sensor',\n            isNotFor: ['EV3'],\n            func: function(sprite, script) {\n                const buttonValue = script.getStringField('BUTTON', script);\n                var buttonData = Entry.hw.getDigitalPortValue(buttonValue);\n                var result = false;\n                if (buttonData.pressed) {\n                    return true;\n                }\n\n                return result;\n            },\n        },\n        ev3_status_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['주황', 'ORANGE'],\n                        ['끄기', 'OFF'],\n                        ['초록', 'GREEN'],\n                        ['빨강', 'RED'],\n                        ['초록 깜박임', 'GREEN_FLASH'],\n                        ['빨강 깜박임', 'RED_FLASH'],\n                        ['주황 깜박임', 'ORANGE_FLASH'],\n                        ['초록 진동', 'GREEN_PULSE'],\n                        ['빨강 진동', 'RED_PULSE'],\n                        ['주황 진동', 'ORANGE_PULSE'],\n                    ],\n                    value: 'ORANGE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'ev3_status_led',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'ev3_output',\n            isNotFor: ['EV3'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue.STATUS_COLOR = script.getStringField('COLOR', script);\n            },\n        },\n        //endregion ev3 이브이3\n    };\n};\n\nmodule.exports = Entry.EV3;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_exmars_cube.js",
    "content": "'use strict';\r\n\r\nEntry.exMars_Cube = {\r\n    id: '43.1',\r\n    name: 'exMars_Cube',\r\n    url: 'http://www.exmarscube.com',\r\n    imageName: 'exmars_cube.png',\r\n    title: {\r\n        ko: 'eX-Mars Cube',\r\n        en: 'eX-Mars Cube',\r\n    },\r\n    setZero: function() {\r\n        // 엔트리 정지시 하드웨어 초기화 로직\r\n    },\r\n    delayTime: 20,\r\n    timeouts: [],\r\n    index: 0,\r\n    removeTimeout: function(id) {\r\n        clearTimeout(id);\r\n        var timeouts = this.timeouts;\r\n        var index = timeouts.indexOf(id);\r\n        if (index >= 0) {\r\n            timeouts.splice(index, 1);\r\n        }\r\n    },\r\n    removeAllTimeouts: function() {\r\n        var timeouts = this.timeouts;\r\n        for (var i in timeouts) {\r\n            clearTimeout(timeouts[i]);\r\n        }\r\n        this.timeouts = [];\r\n    },\r\n    getIndex: function() {\r\n        Entry.exMars_Cube.index = Entry.exMars_Cube.index + 1;\r\n        if (Entry.exMars_Cube.index > 2000) {\r\n            Entry.exMars_Cube.index = 1;\r\n        }\r\n    }\r\n};\r\n\r\nEntry.exMars_Cube.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                ColorRed: '빨강',\r\n                ColorGreen: '초록',\r\n                ColorBlue: '파랑',\r\n                ColorYellow: '노랑',\r\n                ColorPurple: '보라',\r\n                ColorWhite: '하양',\r\n                ColorSkip: '무시하기',\r\n                ColorOff: '끄기',\r\n                BrakeOff: '끄기',\r\n                BrakeOn: '켜기',\r\n                NoteC: '도',\r\n                NoteCS: '도#',\r\n                NoteD: '레',\r\n                NoteDS: '레#',\r\n                NoteE: '미',\r\n                NoteF: '파',\r\n                NoteFS: '파#',\r\n                NoteG: '솔',\r\n                NoteGS: '솔#',\r\n                NoteA: '라',\r\n                NoteAS: '라#',\r\n                NoteB: '시',\r\n                NoteRest: '쉼표',\r\n                Scale6: '6 음계',\r\n                Scale12: '12 음계',\r\n                User2: '유저 2',\r\n                User3: '유저 3',\r\n                DirectionBrake: '멈춤',\r\n                DirectionCW: '정방향',\r\n                DirectionCCW: '역방향',\r\n                DirectionPassive: '풀림',\r\n                RecordIndex0: '노멀',\r\n                RecordIndex1: '5 릴레이',\r\n                RecordIndex2: '하프 블라인드',\r\n                RecordIndex3: '풀 불라인드',\r\n                RecordIndex4: '시간 패널티',\r\n                RecordIndex5: '20~28 모드',\r\n                RecordIndex6: '최소회전',\r\n                RecordIndex7: '02 모드',\r\n                RecordTime1: '최신',\r\n                RecordTime2: '최신-1',\r\n                RecordTime3: '최신-2',\r\n                RecordTime4: '최신-3',\r\n                RecordTime5: '최신-4',\r\n                RecordTimeBest: '최고',\r\n                RecordDiceNumber: '주사위 숫자',\r\n                ModeMain: '메인',\r\n                ModeSub: '서브',\r\n                CellLedColor: '%1 면 %2 번 셀의 색상값',\r\n                FaceLedColor: '%1 면의 셀 색상값',\r\n                FaceDir: '%1 면의 회전값',\r\n                Record: '%1 의 %2 기록',\r\n                RecodeDice: '%1 기록',\r\n                ModeState: '모드 상태',\r\n                MenuInit: '모드 빠져나오기  %1',\r\n                NonBrake: '브레이크 기능을 %1 %2',\r\n                ResetAllFace: '모든 색상을 초기화하기 %1',\r\n                ModeSetting: '모드를 %1 %2 로 설정하기 %3',\r\n                CenterColorChange: '%1 면의 가운데 셀 LED 색상을 %2 으로 바꾸기 %3',\r\n                CellColorChange: ' %1 면의 셀 색상을 %2 %3 %4 %5 %6 %7 %8 %9 으로 바꾸기 %10',\r\n                PosDirTorChange: '%1 면을 %2 포지션, %3 방향, %4 토크로 바꾸기 %5',\r\n                FaceRotationOnlyColor: '%1 면의 LED 색상을 %2 방향으로 %3º 만큼 회전하기 %4',\r\n                FaceRotation: '%1 면을 %2 방향으로 %3º 만큼 회전하기 %4',\r\n                FacesRotation: '%1 면을 %2 방향으로 %3º 만큼,  %4 면을 %5 방향으로 %6º 만큼 회전하기 %7',\r\n                SolveCube: '%1 을 앞면으로 %2 를 %3 초 동안 풀기 %4',\r\n                PlayMode: '%1 연주 모드로 바꾸기 %2',\r\n                UserMode: '%1 펌웨어로 바꾸기 %2',\r\n                PlayNote: '%1 를 %2 초 연주하기 %3',\r\n                GetRecord: '%1 기록 가져오기 %2',\r\n                GetRecordDice: '주사위 숫자 기록 가져오기 %1',\r\n                AutoSolve: '자동솔빙 시작 %1',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                ColorRed: 'Red',\r\n                ColorGreen: 'Green',\r\n                ColorBlue: 'Blue',\r\n                ColorYellow: 'Yellow',\r\n                ColorPurple: 'Purple',\r\n                ColorWhite: 'White',\r\n                ColorSkip: 'Skip',\r\n                ColorOff: 'Off',\r\n                BrakeOff: 'Turn off',\r\n                BrakeOn: 'Turn on',\r\n                NoteC: 'C',\r\n                NoteCS: 'C#',\r\n                NoteD: 'D',\r\n                NoteDS: 'D#',\r\n                NoteE: 'E',\r\n                NoteF: 'F',\r\n                NoteFS: 'F#',\r\n                NoteG: 'G',\r\n                NoteGS: 'G#',\r\n                NoteA: 'A',\r\n                NoteAS: 'A#',\r\n                NoteB: 'B',\r\n                NoteRest: 'Rest',\r\n                Scale6: '6 Scale',\r\n                Scale12: '12 Scale',\r\n                User2: 'User 2',\r\n                User3: 'USer 3',\r\n                DirectionBrake: 'Brake',\r\n                DirectionCW: 'CW',\r\n                DirectionCCW: 'CCW',\r\n                DirectionPassive: 'Passive',\r\n                RecordIndex0: 'Normal',\r\n                RecordIndex1: '5 relay',\r\n                RecordIndex2: 'Half blind',\r\n                RecordIndex3: 'Full blind',\r\n                RecordIndex4: 'Time penalty',\r\n                RecordIndex5: '20~28 mode',\r\n                RecordIndex6: 'Fewest move',\r\n                RecordIndex7: '02 mode',\r\n                RecordTime1: 'Latest',\r\n                RecordTime2: 'Latest-1',\r\n                RecordTime3: 'Latest-2',\r\n                RecordTime4: 'Latest-3',\r\n                RecordTime5: 'Latest-4',\r\n                RecordTimeBest: 'Best',\r\n                RecordDiceNumber: 'Dice number',\r\n                ModeMain: 'Main',\r\n                ModeSub: 'Sub',\r\n                CellLedColor: 'LED color of %1 face %2 cell',\r\n                FaceLedColor: 'LED color of %1 face',\r\n                FaceDir: 'rotation value of %1 face',\r\n                Record: '%2 record of %1',\r\n                RecodeDice: '%1 record',                \r\n                ModeState: 'mode state',\r\n                MenuInit: 'Exit mode %1',\r\n                NonBrake: '%1 the brake function %2',\r\n                ResetAllFace: 'Initialize all colors %1',\r\n                ModeSetting: 'Set mode to %1 %2 %3',\r\n                CenterColorChange: 'Change the center cell LED color of %1 face to %2 %3',\r\n                CellColorChange: 'Change the cell color of %1 face to %2  %3 %4 %5 %6 %7 %8 %9 %10',\r\n                PosDirTorChange: 'Change %1 face to %2 position, %3 direction %4 torque %5',\r\n                FaceRotationOnlyColor: 'Rotate the LED color of %1 face to %3º in %2 direction %4',\r\n                FaceRotation: 'Rotate %1 face to %3º in %2 direction %4',\r\n                FacesRotation: 'Rotate %1 face to %3º in %2 direction, %4 face to %6º in %5 direction %7',\r\n                SolveCube: 'Solve %1 for %3 seconds with %2 as front face %4',\r\n                PlayMode: 'Change to %1 play mode %2',\r\n                UserMode: 'Change to %1 firmware %2',\r\n                PlayNote: 'Play %1 for %2 seconds %3',\r\n                GetRecord: 'Get %1 record %2',\r\n                GetRecordDice: 'Get dice number record %1',\r\n                AutoSolve: 'Auto solving start %1'\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.exMars_Cube.blockMenuBlocks = [\r\n    'GetBlock_CellLedColor',\r\n    'GetBlock_FaceLedColor',\r\n    'GetBlock_FaceDir',\r\n    'GetBlock_Record',\r\n    'GetBlock_RecordDice',\r\n    'GetBlock_ModeState',\r\n    'SetBlock_MenuInit',\r\n    'SetBlock_ModeSetting',\r\n    'SetBlock_PlayMode',\r\n    'SetBlock_UserMode',\r\n    'SetBlock_NonBrake',\r\n    'SetBlock_ResetAllFace',    \r\n    'SetBlock_CenterColorChange',\r\n    'SetBlock_CellColorChange',\r\n    'SetBlock_PosDirTorChange',\r\n    'SetBlock_FaceRotationOnlyColor',\r\n    'SetBlock_FaceRotation',\r\n    'SetBlock_FacesRotation',\r\n    'SetBlock_SolveCube',\r\n    'SetBlock_PlayNote',\r\n    'SetBlock_GetRecord',\r\n    'SetBlock_GetRecordDice',\r\n    'SetBlock_AutoSolve'\r\n];\r\n\r\nEntry.exMars_Cube.getBlocks = function() {\r\n    return {\r\n        //region exMars cube\r\n        // ===================================================================================== //\r\n        // DropDown Blocks\r\n        // ===================================================================================== //\r\n        DropDownBlock_FaceName_W: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.ColorWhite, '0'],\r\n                        [Lang.template.ColorYellow, '1'],\r\n                        [Lang.template.ColorGreen, '2'],\r\n                        [Lang.template.ColorBlue, '3'],\r\n                        [Lang.template.ColorRed, '4'],\r\n                        [Lang.template.ColorPurple, '5']\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('FACE');\r\n            }\r\n        },\r\n        DropDownBlock_FaceName_Y: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.ColorWhite, '0'],\r\n                        [Lang.template.ColorYellow, '1'],\r\n                        [Lang.template.ColorGreen, '2'],\r\n                        [Lang.template.ColorBlue, '3'],\r\n                        [Lang.template.ColorRed, '4'],\r\n                        [Lang.template.ColorPurple, '5']\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('FACE');\r\n            }\r\n        },\r\n        DropDownBlock_FaceName_G: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.ColorWhite, '0'],\r\n                        [Lang.template.ColorYellow, '1'],\r\n                        [Lang.template.ColorGreen, '2'],\r\n                        [Lang.template.ColorBlue, '3'],\r\n                        [Lang.template.ColorRed, '4'],\r\n                        [Lang.template.ColorPurple, '5']\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('FACE');\r\n            }\r\n        },        \r\n        DropDownBlock_FaceName_B: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.ColorWhite, '0'],\r\n                        [Lang.template.ColorYellow, '1'],\r\n                        [Lang.template.ColorGreen, '2'],\r\n                        [Lang.template.ColorBlue, '3'],\r\n                        [Lang.template.ColorRed, '4'],\r\n                        [Lang.template.ColorPurple, '5']\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('FACE');\r\n            }\r\n        },        \r\n        DropDownBlock_CellName: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8']\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                CELL: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('CELL');\r\n            }\r\n        },\r\n        DropDownBlock_Brake: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.BrakeOff, '0'],\r\n                        [Lang.template.BrakeOn, '1']\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                BRAKE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('BRAKE');\r\n            }\r\n        },\r\n        DropDownBlock_ModeMainNumber: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                        ['12', '12'],\r\n                        ['13', '13'],\r\n                        ['14', '14'],\r\n                        ['15', '15']\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                MAIN: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('MAIN');\r\n            }\r\n        },\r\n        DropDownBlock_ModeSubNumber: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                        ['9', '9'],\r\n                        ['10', '10']\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                SUB: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('SUB');\r\n            }\r\n        },\r\n        DropDownBlock_ColorName: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.ColorRed, '1'],\r\n                        [Lang.template.ColorGreen, '2'],\r\n                        [Lang.template.ColorBlue, '3'],\r\n                        [Lang.template.ColorYellow, '4'],\r\n                        [Lang.template.ColorPurple, '6'],\r\n                        [Lang.template.ColorWhite, '7'],\r\n                        [Lang.template.ColorSkip, '8'],\r\n                        [Lang.template.ColorOff, '0']\r\n                    ],\r\n                    value: '7',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('COLOR');\r\n            }\r\n        },\r\n        DropDownBlock_ColorNameMini: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.ColorGreen, '2'],\r\n                        [Lang.template.ColorPurple, '5'],\r\n                        [Lang.template.ColorBlue, '3'],\r\n                        [Lang.template.ColorRed, '4'],\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                ANGLE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('ANGLE');\r\n            }\r\n        },\r\n        DropDownBlock_Direction: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.DirectionBrake, '0'],\r\n                        [Lang.template.DirectionCW, '1'],\r\n                        [Lang.template.DirectionCCW, '2'],\r\n                        [Lang.template.DirectionPassive, '3']\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('DIRECTION');\r\n            }\r\n        },        \r\n        DropDownBlock_DirectionMini: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.DirectionCW, '1'],\r\n                        [Lang.template.DirectionCCW, '2']\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('DIRECTION');\r\n            }\r\n        },\r\n        DropDownBlock_Torque: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8']\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                TORQUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('TORQUE');\r\n            }\r\n        },\r\n        DropDownBlock_Angle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['30', '1'],\r\n                        ['60', '2'],\r\n                        ['90', '3'],\r\n                        ['120', '4'],\r\n                        ['150', '5'],\r\n                        ['180', '6']\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                ANGLE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('ANGLE');\r\n            }\r\n        },\r\n        DropDownBlock_MovingFace: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['F', '0'],\r\n                        ['F\\'', '1'],\r\n                        ['R', '2'],\r\n                        ['R\\'', '3'],\r\n                        ['L', '4'],\r\n                        ['L\\'', '5'],\r\n                        ['U', '6'],\r\n                        ['U\\'', '7'],\r\n                        ['D', '8'],\r\n                        ['D\\'', '9'],\r\n                        ['B', '10'],\r\n                        ['B\\'', '11']\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                ANGLE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('ANGLE');\r\n            }\r\n        },\r\n        DropDownBlock_PlayMode: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [                        \r\n                        [Lang.template.Scale6, '0'],\r\n                        [Lang.template.Scale12, '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                ANGLE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('ANGLE');\r\n            }\r\n        },\r\n        DropDownBlock_UserMode: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [                        \r\n                        [Lang.template.User2, '2'],\r\n                        [Lang.template.User3, '3'],\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                ANGLE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('ANGLE');\r\n            }\r\n        },\r\n        DropDownBlock_Note: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [                        \r\n                        [Lang.template.NoteC, '0'],\r\n                        [Lang.template.NoteCS, '1'],\r\n                        [Lang.template.NoteD, '2'],\r\n                        [Lang.template.NoteDS, '3'],\r\n                        [Lang.template.NoteE, '4'],\r\n                        [Lang.template.NoteF, '5'],\r\n                        [Lang.template.NoteFS, '6'],\r\n                        [Lang.template.NoteG, '7'],\r\n                        [Lang.template.NoteGS, '8'],\r\n                        [Lang.template.NoteA, '9'],\r\n                        [Lang.template.NoteAS, '10'],\r\n                        [Lang.template.NoteB, '11'],\r\n                        [Lang.template.NoteRest, '12']\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('NOTE');\r\n            }\r\n        },\r\n        DropDownBlock_RecordIndex: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.RecordIndex0, '0'],\r\n                        [Lang.template.RecordIndex1, '1'],\r\n                        [Lang.template.RecordIndex2, '2'],\r\n                        [Lang.template.RecordIndex3, '3'],\r\n                        [Lang.template.RecordIndex4, '4'],\r\n                        [Lang.template.RecordIndex5, '5'],\r\n                        [Lang.template.RecordIndex6, '6'],\r\n                        [Lang.template.RecordIndex7, '7']\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                INDEX: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('INDEX');\r\n            }\r\n        },\r\n        DropDownBlock_RecordTime: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [                        \r\n                        [Lang.template.RecordTime1, '0'],\r\n                        [Lang.template.RecordTime2, '1'],\r\n                        [Lang.template.RecordTime3, '2'],\r\n                        [Lang.template.RecordTime4, '3'],\r\n                        [Lang.template.RecordTime5, '4'],\r\n                        [Lang.template.RecordTimeBest, '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                TIME: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('TIME');\r\n            }\r\n        },\r\n        DropDownBlock_RecordDice: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.RecordDiceNumber, '5']\r\n                    ],\r\n                    value: '5',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                TIME: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('TIME');\r\n            }\r\n        },\r\n        DropDownBlock_Mode: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.ModeMain, '0'],\r\n                        [Lang.template.ModeSub, '1']\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\r\n                }\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                TIME: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('TIME');\r\n            }\r\n        },\r\n        // ===================================================================================== //\r\n        // Get Value Blocks\r\n        // ===================================================================================== //\r\n        GetBlock_CellLedColor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            template: Lang.template.CellLedColor,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                }\r\n            ],\r\n            def: {\r\n                params: [ \r\n                    {\r\n                        type: 'DropDownBlock_FaceName_W'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_CellName'\r\n                    }\r\n                ],\r\n                type: 'GetBlock_CellLedColor'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0,\r\n                CELL: 1\r\n            },\r\n            events: {},\r\n            class: 'GetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face = script.getNumberValue('FACE');\r\n                var cell = script.getNumberValue('CELL');\r\n                var hwData = Entry.hw.portData;\r\n\r\n                return hwData[face][cell];\r\n            }\r\n        },\r\n        GetBlock_FaceLedColor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            template: Lang.template.FaceLedColor,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                }\r\n            ],\r\n            def: {\r\n                params: [ \r\n                    {\r\n                        type: 'DropDownBlock_FaceName_W'\r\n                    }\r\n                ],\r\n                type: 'GetBlock_FaceLedColor'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0\r\n            },\r\n            events: {},\r\n            class: 'GetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face = script.getNumberValue('FACE');\r\n                var hwData = Entry.hw.portData;\r\n\r\n                return hwData[face];\r\n            }\r\n        },        \r\n        GetBlock_FaceDir: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            template: Lang.template.FaceDir,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                }\r\n            ],\r\n            def: {\r\n                params: [ \r\n                    {\r\n                        type: 'DropDownBlock_FaceName_W'\r\n                    }\r\n                ],\r\n                type: 'GetBlock_FaceDir'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0\r\n            },\r\n            events: {},\r\n            class: 'GetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face = script.getNumberValue('FACE');\r\n                var dir = '';\r\n                var hwData = Entry.hw.portData;\r\n\r\n                if (hwData[6][face] == 3) {\r\n                    dir = 'CW';\r\n                }\r\n                else if (hwData[6][face] == 11) {\r\n                    dir = 'CCW'\r\n                }\r\n                else {\r\n                    dir = '0'\r\n                }\r\n                return dir;\r\n            }\r\n        },\r\n        GetBlock_Record: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            template: Lang.template.Record,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                }\r\n            ],\r\n            def: {\r\n                params: [ \r\n                    {\r\n                        type: 'DropDownBlock_RecordIndex'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_RecordTime'\r\n                    }\r\n                ],\r\n                type: 'GetBlock_Record'\r\n            },\r\n            paramsKeyMap: {\r\n                INDEX: 0,\r\n                TIME: 1\r\n            },\r\n            events: {},\r\n            class: 'GetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var index = script.getNumberValue('INDEX');\r\n                var time = script.getNumberValue('TIME');\r\n                var hwData = Entry.hw.portData;\r\n                var s = Math.floor(hwData[index + 7][time] / 10) / 100;\r\n\r\n                return s;\r\n            }\r\n        },\r\n        GetBlock_RecordDice: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            template: Lang.template.RecodeDice,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_RecordDice'\r\n                    }\r\n                ],\r\n                type: 'GetBlock_RecordDice'\r\n            },\r\n            paramsKeyMap: {\r\n                TIME: 0\r\n            },\r\n            events: {},\r\n            class: 'GetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var index = 7;\r\n                var time = script.getNumberValue('TIME');\r\n                var hwData = Entry.hw.portData;\r\n                var s = Math.floor(hwData[index + 7][time] / 10) / 100;\r\n\r\n                return s;\r\n            }\r\n        },\r\n        \r\n        GetBlock_ModeState: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            template: Lang.template.ModeState,\r\n            params: [\r\n                {\r\n                    //type: 'Block',\r\n                    //accept: 'string',\r\n                    //defaultType: 'number'\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        //type: 'DropDownBlock_Mode'\r\n                    }\r\n                ],\r\n                type: 'GetBlock_ModeState'\r\n            },\r\n            paramsKeyMap: {\r\n                MODE: 0\r\n            },\r\n            events: {},\r\n            class: 'GetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var hwData = Entry.hw.portData;\r\n                var s = String(hwData[16]) + String(hwData[17]);\r\n                \r\n                return s;\r\n            }\r\n        },\r\n        // ===================================================================================== //\r\n        // Set Value Blocks\r\n        // ===================================================================================== //\r\n        SetBlock_MenuInit: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.MenuInit,\r\n             params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null\r\n                ],\r\n                type: 'SetBlock_MenuInit'\r\n            },\r\n            paramsKeyMap:{},\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'MenuInit',\r\n                        index: Entry.exMars_Cube.index\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_NonBrake: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.NonBrake,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_Brake'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_NonBrake'\r\n            },\r\n            paramsKeyMap:{\r\n                BRAKE: 0\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var brake = script.getNumberValue('BRAKE');\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'NonBrake',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: brake\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_ModeSetting: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.ModeSetting,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_ModeMainNumber'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ModeSubNumber'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_ModeSetting'\r\n            },\r\n            paramsKeyMap: {\r\n                MAIN: 0,\r\n                SUB: 1\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var main = script.getNumberValue('MAIN');\r\n                var sub = script.getNumberValue('SUB');\r\n\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'ModeSetting',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: main,\r\n                        data1: sub\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_CenterColorChange: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.CenterColorChange,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_FaceName_W'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },                    \r\n                    null\r\n                ],\r\n                type: 'SetBlock_CenterColorChange'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0,\r\n                CELL: 1\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face = script.getNumberValue('FACE');\r\n                var cell = script.getNumberValue('CELL');\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'CenterColorChange',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: face,\r\n                        data1: cell\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_CellColorChange: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.CellColorChange,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_FaceName_W'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_ColorName'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_CellColorChange'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0,\r\n                CELL1: 1,\r\n                CELL2: 2,\r\n                CELL3: 3,\r\n                CELL4: 4,\r\n                CELL5: 5,\r\n                CELL6: 6,\r\n                CELL7: 7,\r\n                CELL8: 8\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face = script.getNumberValue('FACE');\r\n                var cell1 = script.getNumberValue('CELL1');\r\n                var cell2 = script.getNumberValue('CELL2');\r\n                var cell3 = script.getNumberValue('CELL3');\r\n                var cell4 = script.getNumberValue('CELL4');\r\n                var cell5 = script.getNumberValue('CELL5');\r\n                var cell6 = script.getNumberValue('CELL6');\r\n                var cell7 = script.getNumberValue('CELL7');\r\n                var cell8 = script.getNumberValue('CELL8');\r\n\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'CellColorChange',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: face,\r\n                        data1: cell1,\r\n                        data2: cell2,\r\n                        data3: cell3,\r\n                        data4: cell4,\r\n                        data5: cell5,\r\n                        data6: cell6,\r\n                        data7: cell7,\r\n                        data8: cell8\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_PosDirTorChange: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.PosDirTorChange,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_FaceName_W'\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['12']\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_Direction'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_Torque'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_PosDirTorChange'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0,\r\n                POSITION: 1,\r\n                DIRECTION: 2,\r\n                TORQUE: 3,\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face = script.getNumberValue('FACE');\r\n                var position = script.getNumberValue('POSITION');\r\n                var direction = script.getNumberValue('DIRECTION');\r\n                var torque = script.getNumberValue('TORQUE');\r\n\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'PosDirTorChange',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: face,\r\n                        data1: position,\r\n                        data2: direction,\r\n                        data3: torque\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_FaceRotationOnlyColor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.FaceRotationOnlyColor,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_FaceName_Y'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_DirectionMini'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_Angle'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_FaceRotationOnlyColor'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0,\r\n                DIRECTION: 1,\r\n                ANGLE: 2\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face = script.getNumberValue('FACE');\r\n                var direction = script.getNumberValue('DIRECTION');\r\n                var angle = script.getNumberValue('ANGLE');\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'FaceRotationOnlyColor',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: face,\r\n                        data1: direction,\r\n                        data2: angle\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_FaceRotation: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.FaceRotation,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_FaceName_Y'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_DirectionMini'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_Angle'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_FaceRotation'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE: 0,\r\n                DIRECTION: 1,\r\n                ANGLE: 2\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face = script.getNumberValue('FACE');\r\n                var direction = script.getNumberValue('DIRECTION');\r\n                var angle = script.getNumberValue('ANGLE');\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'FaceRotation',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: face,\r\n                        data1: direction,\r\n                        data2: angle\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_FacesRotation: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.FacesRotation,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_FaceName_G'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_DirectionMini'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_Angle'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_FaceName_B'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_DirectionMini'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_Angle'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_FacesRotation'\r\n            },\r\n            paramsKeyMap: {\r\n                FACE1: 0,\r\n                DIRECTION1: 1,\r\n                ANGLE1: 2,\r\n                FACE2: 3,\r\n                DIRECTION2: 4,\r\n                ANGLE2: 5\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var face1 = script.getNumberValue('FACE1');\r\n                var direction1 = script.getNumberValue('DIRECTION1');\r\n                var angle1 = script.getNumberValue('ANGLE1');\r\n                var face2 = script.getNumberValue('FACE2');\r\n                var direction2 = script.getNumberValue('DIRECTION2');\r\n                var angle2 = script.getNumberValue('ANGLE2');\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'FacesRotation',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: face1,\r\n                        data1: direction1,\r\n                        data2: angle1,\r\n                        data3: face2,\r\n                        data4: direction2,\r\n                        data5: angle2\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_SolveCube: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.SolveCube,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_ColorNameMini'\r\n                    },\r\n                    {\r\n                        type: 'DropDownBlock_MovingFace'\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0.8']\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_SolveCube'\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0,\r\n                MOVINGFACE: 1,\r\n                TIME: 2,\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var color = script.getNumberValue('COLOR');\r\n                var movingFace = script.getNumberValue('MOVINGFACE');\r\n                var time = script.getNumberValue('TIME');\r\n                if(!script.isStart) {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'SolveCube',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: color,\r\n                        data1: movingFace\r\n                    };\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    const fps = Entry.FPS || 60;\r\n                    time = 60 / fps * time * 1000;\r\n\r\n                    const blockId = script.block.id;\r\n                    Entry.TimeWaitManager.add(\r\n                        blockId,\r\n                        function() {\r\n                            script.timeFlag = 0;\r\n                        },\r\n                        time\r\n                    );\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },        \r\n        SetBlock_ResetAllFace: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.ResetAllFace,\r\n             params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null\r\n                ],\r\n                type: 'SetBlock_ResetAllFace'\r\n            },\r\n            paramsKeyMap: {},\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'ResetAllFace',\r\n                        index: Entry.exMars_Cube.index\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_PlayMode: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.PlayMode,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_PlayMode'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_PlayMode'\r\n            },\r\n            paramsKeyMap: {\r\n                MODE: 0\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var mode = script.getNumberValue('MODE');\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'PlayMode',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: mode\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_UserMode: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.UserMode,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_UserMode'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_UserMode'\r\n            },\r\n            paramsKeyMap: {\r\n                MODE: 0\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var mode = script.getNumberValue('MODE');\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'UserMode',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: mode\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_PlayNote: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.PlayNote,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_Note'\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1']\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_PlayNote'\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n                TIME: 1\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var note = script.getNumberValue('NOTE');\r\n                var time = script.getNumberValue('TIME');                \r\n                \r\n                if(!script.isStart) {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'PlayNote',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: note\r\n                    };\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    const fps = Entry.FPS || 60;\r\n                    time = 60 / fps * time * 1000;\r\n\r\n                    const blockId = script.block.id;\r\n                    Entry.TimeWaitManager.add(\r\n                        blockId,\r\n                        function() {\r\n                            script.timeFlag = 0;\r\n                        },\r\n                        time\r\n                    );\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_GetRecord: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.GetRecord,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    value: '1',\r\n                    defaultType: 'number'\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'DropDownBlock_RecordIndex'\r\n                    },\r\n                    null\r\n                ],\r\n                type: 'SetBlock_GetRecord'\r\n            },\r\n            paramsKeyMap: {\r\n                INDEX: 0\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var index = script.getNumberValue('INDEX');\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'GetRecord',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: index\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_GetRecordDice: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.GetRecordDice,\r\n             params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null\r\n                ],\r\n                type: 'SetBlock_GetRecordDice'\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var index = 7;\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'GetRecord',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: index\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        SetBlock_AutoSolve: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.AutoSolve,\r\n             params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12\r\n                }\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null\r\n                ],\r\n                type: 'SetBlock_AutoSolve'\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            events: {},\r\n            class: 'WriteBlock',\r\n            isNotFor: ['exMars_Cube'],\r\n            func: function(sprite, script) {\r\n                var index = 7;\r\n                if(!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.exMars_Cube.removeTimeout(timer);\r\n                    }, Entry.exMars_Cube.delayTime);\r\n                    Entry.exMars_Cube.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    Entry.exMars_Cube.getIndex();\r\n                    Entry.hw.sendQueue['SetBlock'] = {\r\n                        name: 'GetRecord',\r\n                        index: Entry.exMars_Cube.index,\r\n                        data0: index\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            }\r\n        },\r\n        //endregion exMars cube\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.exMars_Cube;"
  },
  {
    "path": "src/playground/blocks/hardware/block_firmtech2.js",
    "content": "'use strict';\n\nEntry.Firmtech2 = {\n    Cmd: {\n        CMD_LED: 1,\n        CMD_TUNE: 2,\n        CMD_TUNEDUR: 3,\n        CMD_ROLL_LOW: 4,\n        CMD_ROLL_HIGH: 5,\n        CMD_PITCH_LOW: 6,\n        CMD_PITCH_HIGH: 7,\n        CMD_OPTION_LOW: 8,\n        CMD_MOTOR0: 9,\n        CMD_MOTOR1: 10,\n        CMD_MOTOR2: 11,\n        CMD_MOTOR3: 12,\n        CMD_EXTPIN1: 13,\n        CMD_EXTPIN2: 14,\n        CMD_EXTPIN3: 15,\n        CMD_PWM: 16,\n        CMD_SERVOPORT: 17,\n        CMD_SERVODGREE: 18,\n        CMD_OPTION_HIGH: 19,\n        CMD_YAW_LOW: 20,\n        CMD_YAW_HIGH: 21,\n        CMD_THROTTLE_LOW: 22,\n        CMD_THROTTLE_HIGH: 23,\n        CMD_POSVEL_LOW: 24,\n        CMD_POSVEL_HIGH: 25,\n        CMD_YAWVEL_LOW: 26,\n        CMD_YAWVEL_HIGH: 27,\n        CMD_ULTRASONIC: 28,\n    },\n    Sensor: {\n        SENSOR_JOYSTICK_LLR: 1,\n        SENSOR_JOYSTICK_LTB: 2,\n        SENSOR_JOYSTICK_RLR: 3,\n        SENSOR_JOYSTICK_RTB: 4,\n        SENSOR_BUTTON: 5,\n        SENSOR_DRONECONNECT: 6,\n        SENSOR_DRONEALT: 7,\n        SENSOR_GYRO_X: 8,\n        SENSOR_GYRO_Y: 9,\n        SENSOR_DRONEREADY: 10,\n        SENSOR_EXTPIN1: 11,\n        SENSOR_EXTPIN2: 12,\n        SENSOR_ANALOG4: 13,\n        SENSOR_ANALOG5: 14,\n        SENSOR_JDKITMAX: 15,\n        SENSOR_BATTERY: 15,\n        SENSOR_POSX_L: 16,\n        SENSOR_POSX_H: 17,\n        SENSOR_POSY_L: 18,\n        SENSOR_POSY_H: 19,\n        SENSOR_ULTRASONIC: 20,\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.CMD = [\n            0xf0, 0, 0, 0, 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,\n        ];\n        Entry.hw.update();\n    },\n    id: '4E.1',\n    name: 'Firmtech2',\n    url: 'http://www.firmtech2.co.kr',\n    imageName: 'firmtech2.png',\n    title: {\n        'en': 'Firmtech2',\n        'ko': '펌테크 드론 2호',\n    },\n    monitorTemplate: {\n    },\n};\n\n\nEntry.Firmtech2.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                'firmtech2_takeoff': '드론 이륙하기 %1',\n                'firmtech2_landing': '드론 착륙하기 %1',\n                'firmtech2_altitude': '%1cm 높이로 비행%2',\n                'firmtech2_throttle': '프로펠러를 %1 % 세기로 돌리기 %2',\n                'firmtech2_velocity': '%1(으)로 %2속도(cm/s)로 비행%3',\n                'firmtech2_distance': '%1(으)로 %2cm 거리를 %3속도(cm/s)로 비행%4',\n                'firmtech2_degree': '%1으로 %2도를 %3각속도(deg/s)로 회전 %4',\n                'firmtech2_motor': '%1 모터를 %2 세기로 돌리기 %3',\n                'firmtech2_emergency': '드론 즉시멈추기 %1',\n                'firmtech2_connect': '드론 연결상태',\n                'firmtech2_ready': '드론 준비상태',\n                'firmtech2_battery': '배터리(%)',\n                'firmtech2_dronealt': '드론 높이',\n                'firmtech2_gyrox': '드론 좌우 기울기',\n                'firmtech2_gyroy': '드론 앞뒤 기울기',\n                'firmtech2_posx': '드론 좌우 이동',\n                'firmtech2_posy': '드론 앞뒤 이동',\n                'firmtech2_dir_front': '앞',\n                'firmtech2_dir_back': '뒤',\n                'firmtech2_dir_right': '오른쪽',\n                'firmtech2_dir_left': '왼쪽',\n                'firmtech2_alt': '드론 높이',\n                'firmtech2_tiltx': '드론좌우기울기',\n                'firmtech2_tilty': '드론앞뒤기울기',\n                'firmtech2_battery': '배터리',\n            },\n        },\n        en: {\n            template: {\n                'firmtech2_takeoff': '드론 이륙하기 %1',\n                'firmtech2_landing': '드론 착륙하기 %1',\n                'firmtech2_altitude': '%1cm 높이로 비행%2',\n                'firmtech2_throttle': '프로펠러를 %1 % 세기로 돌리기 %2',\n                'firmtech2_velocity': '%1(으)로 %2속도(cm/s)로 비행%3',\n                'firmtech2_distance': '%1(으)로 %2cm 거리를 %3속도(cm/s)로 비행%4',\n                'firmtech2_degree': '%1으로 %2도를 %3각속도(deg/s)로 회전 %4',\n                'firmtech2_motor': '%1 모터를 %2 세기로 돌리기 %3',\n                'firmtech2_emergency': '드론 즉시멈추기 %1',\n                'firmtech2_connect': '드론 연결상태',\n                'firmtech2_ready': '드론 준비상태',\n                'firmtech2_battery': '배터리(%)',\n                'firmtech2_dronealt': '드론 높이',\n                'firmtech2_gyrox': '드론 좌우 기울기',\n                'firmtech2_gyroy': '드론 앞뒤 기울기',\n                'firmtech2_posx': '드론 좌우 이동',\n                'firmtech2_posy': '드론 앞뒤 이동',\n                'firmtech2_dir_front': '앞',\n                'firmtech2_dir_back': '뒤',\n                'firmtech2_dir_right': '오른쪽',\n                'firmtech2_dir_left': '왼쪽',\n                'firmtech2_alt': '드론 높이',\n                'firmtech2_tiltx': '드론좌우기울기',\n                'firmtech2_tilty': '드론앞뒤기울기',\n                'firmtech2_battery': '배터리',\n            },\n        },\n    };\n};\n\n\nEntry.Firmtech2.blockMenuBlocks = [\n    'firmtech2_takeoff',\n    'firmtech2_landing',\n    'firmtech2_altitude',\n    'firmtech2_throttle',\n    'firmtech2_velocity',\n    'firmtech2_distance',\n    'firmtech2_degree',\n    'firmtech2_emergency',\n    'firmtech2_connect',\n    'firmtech2_ready',\n    'firmtech2_battery',\n    'firmtech2_dronealt',\n    'firmtech2_gyrox',\n    'firmtech2_gyroy',\n    'firmtech2_posx',\n    'firmtech2_posy',\n];\n\n\nEntry.Firmtech2.getBlocks = function() {\n    return {\n        //region Firmtech2\n        firmtech2_takeoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_takeoff',\n            },\n            paramsKeyMap: {},\n            class: 'Firmtech2_Command',\n            isNotFor: ['Firmtech2'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                }\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.Firmtech2.Cmd.CMD_THROTTLE_LOW] = 70;\n                cmd[Entry.Firmtech2.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.Firmtech2.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_LOW] = 0x2F;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_HIGH] = 0;\n\n                Entry.hw.sendQueue.rollCnt = 0;\n                Entry.hw.sendQueue.pitchCnt = 0;\n                Entry.hw.sendQueue.yawCnt = 0;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_landing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_landing',\n            },\n            paramsKeyMap: {},\n            class: 'Firmtech2_Command',\n            isNotFor: ['Firmtech2'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.Firmtech2.Cmd.CMD_THROTTLE_LOW] = 0;\n                cmd[Entry.Firmtech2.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.Firmtech2.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_LOW] = 0x2F;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_HIGH] = 0;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_altitude: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '100',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_altitude',\n            },\n            paramsKeyMap: {\n                THROTTLE: 0,\n            },\n            class: 'Firmtech2_Command',\n            isNotFor: ['Firmtech2'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var throttle = script.getNumberValue('THROTTLE', script);\n                cmd[Entry.Firmtech2.Cmd.CMD_THROTTLE_LOW] = throttle & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_THROTTLE_HIGH] = (throttle >> 8) & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_LOW] = 0x2F;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_throttle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_throttle',\n            },\n            paramsKeyMap: {\n                THROTTLE: 0,\n            },\n            class: 'Firmtech2_Command',\n            isNotFor: ['Firmtech2'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var throttle = script.getNumberValue('THROTTLE', script);\n                throttle = (throttle < 0) ? 0 : (throttle > 100) ? 1000 : throttle * 10;\n                cmd[Entry.Firmtech2.Cmd.CMD_THROTTLE_LOW] = throttle & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_THROTTLE_HIGH] = (throttle >> 8) & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_LOW] = 0x09;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        firmtech2_velocity: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.firmtech2_dir_front, 0],\n                        [Lang.template.firmtech2_dir_back, 1],\n                        [Lang.template.firmtech2_dir_right, 2],\n                        [Lang.template.firmtech2_dir_left, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_velocity',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VELOCITY: 1,\n            },\n            class: 'Firmtech2_Command',\n            isNotFor: ['Firmtech2'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if ((direction == 1) || (direction == 3))\n                    velocity = velocity * -1;\n                if (direction < 2) {\n                    cmd[Entry.Firmtech2.Cmd.CMD_PITCH_LOW] = velocity & 0xFF;\n                    cmd[Entry.Firmtech2.Cmd.CMD_PITCH_HIGH] = (velocity >> 8) & 0xFF;\n                } else {\n                    cmd[Entry.Firmtech2.Cmd.CMD_ROLL_LOW] = velocity & 0xFF;\n                    cmd[Entry.Firmtech2.Cmd.CMD_ROLL_HIGH] = (velocity >> 8) & 0xFF;\n                }\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_LOW] = cmd[Entry.Firmtech2.Cmd.CMD_OPTION_LOW] & 0xDF;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_distance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.firmtech2_dir_front, 0],\n                        [Lang.template.firmtech2_dir_back, 1],\n                        [Lang.template.firmtech2_dir_right, 2],\n                        [Lang.template.firmtech2_dir_left, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '100',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_distance',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DISTANCE: 1,\n                VELOCITY: 2,\n            },\n            class: 'Firmtech2_Command',\n            isNotFor: ['Firmtech2'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var distance = script.getNumberValue('DISTANCE', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if ((direction == 1) || (direction == 3))\n                    distance = distance * -1;\n                if (direction < 2) {\n                    cmd[Entry.Firmtech2.Cmd.CMD_PITCH_LOW] = distance & 0xFF;\n                    cmd[Entry.Firmtech2.Cmd.CMD_PITCH_HIGH] = (distance >> 8) & 0xFF;\n                    var pitchCnt = Entry.hw.sendQueue.pitchCnt;\n                    Entry.hw.sendQueue.pitchCnt = typeof pitchCnt == 'undefined' ? 1 : pitchCnt + 1;\n\n                } else {\n                    cmd[Entry.Firmtech2.Cmd.CMD_ROLL_LOW] = distance & 0xFF;\n                    cmd[Entry.Firmtech2.Cmd.CMD_ROLL_HIGH] = (distance >> 8) & 0xFF;\n                    var rollCnt = Entry.hw.sendQueue.rollCnt;\n                    Entry.hw.sendQueue.rollCnt = typeof rollCnt == 'undefined' ? 1 : rollCnt + 1;\n                }\n                cmd[Entry.Firmtech2.Cmd.CMD_POSVEL_LOW] = velocity & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_POSVEL_HIGH] = (velocity >> 8) & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_LOW] = 0x2F;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_clockwise, 0],\n                        [Lang.Blocks.jdkit_counterclockwise, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '90',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_degree',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DEGREE: 1,\n                VELOCITY: 2,\n            },\n            class: 'Firmtech2_Command',\n            isNotFor: ['Firmtech2'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var degree = script.getNumberValue('DEGREE', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if (direction == 1)\n                    degree = degree * -1;\n                cmd[Entry.Firmtech2.Cmd.CMD_YAW_LOW] = degree & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_YAW_HIGH] = (degree >> 8) & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_YAWVEL_LOW] = velocity & 0xFF;\n                cmd[Entry.Firmtech2.Cmd.CMD_YAWVEL_HIGH] = (velocity >> 8) & 0xFF;\n                var yawCnt = Entry.hw.sendQueue.yawCnt;\n                Entry.hw.sendQueue.yawCnt = typeof yawCnt == 'undefined' ? 1 : yawCnt + 1;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_emergency: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_emergency',\n            },\n            paramsKeyMap: {},\n            class: 'Firmtech2_Command',\n            isNotFor: ['Firmtech2'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.Firmtech2.Cmd.CMD_THROTTLE_LOW] = 0;\n                cmd[Entry.Firmtech2.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.Firmtech2.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_LOW] = 0x00;\n                cmd[Entry.Firmtech2.Cmd.CMD_OPTION_HIGH] = 0;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_connect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_connect',\n            },\n            class: 'Firmtech2_Sensor',\n            isNotFor: ['Firmtech2'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.Firmtech2.Sensor.SENSOR_DRONECONNECT];\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_ready: {\n            parent: 'jdkit_ready',\n            def: {\n                params: [null],\n                type: 'firmtech2_ready',\n            },\n            class: 'Firmtech2_Sensor',\n            isNotFor: ['Firmtech2'],\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_battery: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_battery',\n            },\n            class: 'Firmtech2_Sensor',\n            isNotFor: ['Firmtech2'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.Firmtech2.Sensor.SENSOR_BATTERY];\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_dronealt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_dronealt',\n            },\n            class: 'Firmtech2_Sensor',\n            isNotFor: ['Firmtech2'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.Firmtech2.Sensor.SENSOR_DRONEALT];\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_gyrox: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_gyrox',\n            },\n            class: 'Firmtech2_Sensor',\n            isNotFor: ['Firmtech2'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var x = sensorData[Entry.Firmtech2.Sensor.SENSOR_GYRO_X];\n                if (x > 127)\n                    x = -1 * (256 - x);\n                return x;\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_gyroy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_gyroy',\n            },\n            class: 'Firmtech2_Sensor',\n            isNotFor: ['Firmtech2'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var y = sensorData[Entry.Firmtech2.Sensor.SENSOR_GYRO_Y];\n                if (y > 127)\n                    y = -1 * (256 - y);\n                return y;\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_posx: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_posx',\n            },\n            class: 'Firmtech2_Sensor',\n            isNotFor: ['Firmtech2'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var posx = sensorData[Entry.Firmtech2.Sensor.SENSOR_POSX_L] + sensorData[Entry.Firmtech2.Sensor.SENSOR_POSX_H] * 256;\n                if (posx > 32767)\n                    posx = -1 * (65536 - posx);\n                return posx;\n            },\n            syntax: { js: [], py: [] },\n        },\n        firmtech2_posy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'firmtech2_posy',\n            },\n            class: 'Firmtech2_Sensor',\n            isNotFor: ['Firmtech2'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var posy = sensorData[Entry.Firmtech2.Sensor.SENSOR_POSY_L] + sensorData[Entry.Firmtech2.Sensor.SENSOR_POSY_H] * 256;\n                if (posy > 32767)\n                    posy = -1 * (65536 - posy);\n                return posy;\n\n            },\n            syntax: { js: [], py: [] },\n        },\n        //endregion Firmtech2\n    };\n};\n\nmodule.exports = Entry.Firmtech2;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_freearduino.js",
    "content": "'use strict';\n\nEntry.freearduino = {\n    id: '2B.1',\n    name: 'freearduino',\n    url: 'https://cafe.naver.com/robotclubmokdong',\n    imageName: 'freearduino.png',\n    title: {\n        \"ko\": \"프리 아두이노\",\n        \"en\": \"freearduino\"\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 20; port++) {\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        for (var port = 2; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 199;\n        }\n        for (var port = 20; port < 25; port++) {\n            Entry.hw.sendQueue[port] = 0;\n        }\n        Entry.hw.sendQueue[0] = 0;\n        Entry.hw.update();\n    },\n};\n\nEntry.freearduino.blockMenuBlocks = [\n    \"freearduino_set_digital_value\",\n    \"freearduino_get_digital_value\",\n    \"freearduino_get_digital_value_pullup\",\n    \"freearduino_set_pwm_value\",\n    \"freearduino_get_analog_value\",\n    \"freearduino_get_analog_value_pullup\",\n    \"freearduino_get_analog_mapped_value\",\n    \"freearduino_get_humidity_value\",\n    \"freearduino_get_temperature_value\",\n    \"freearduino_get_distance_value\",\n    \"freearduino_set_servo_angle\",\n    \"freearduino_set_motor_run\",\n    \"freearduino_set_motor_speed\",\n];\n\nEntry.freearduino.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                \"freearduino_get_analog_value\": \"%1 핀 아날로그 입력값\",\n                \"freearduino_get_analog_value_pullup\": \"%1 핀 아날로그 입력값 (PULL UP)\",\n                \"freearduino_get_analog_mapped_value\": \"%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값\",\n                \"freearduino_get_humidity_value\" : \"온습도센서 %1 핀 습도값(%)\",\n                \"freearduino_get_temperature_value\" : \"온습도센서 %1 핀 온도값(C)\",\n                \"freearduino_get_distance_value\" : \"초음파센서 trig %1 echo %2 핀 거리값(mm)\",\n                \"freearduino_set_digital_value\": \"%1 핀에 디지털 %2 출력 %3\",\n                \"freearduino_get_digital_value\": \"%1 핀 디지털 입력값\",\n                \"freearduino_get_digital_value_pullup\": \"%1 핀의 디지털 입력값 (PULL UP)\",\n                \"freearduino_set_pwm_value\" : \"%1 핀에 아날로그 %2 값 출력 %3\",\n                \"freearduino_set_servo_angle\": \"%1 핀 서보모터 각도를 %2 도로 정하기 %3\",\n                \"freearduino_set_motor_run\": \"모터실드 %1 번 DC모터 %2 %3\",\n                \"freearduino_set_motor_speed\": \"모터실드 %1 번 DC모터 속도를 %2 (으)로 정하기 %3\",\n            }\n        },\n        en: {\n            template: {\n                \"freearduino_get_analog_value\": \"analogRead %1\",\n                \"freearduino_get_analog_value_pullup\": \"analogRead %1 (PULL UP)\",\n                \"freearduino_get_analog_mapped_value\": \"map %1 from %2 ~ %3 to %4 ~ %5\",\n                \"freearduino_get_humidity_value\" : \"humidity value from DHT11 pin %1 (%)\",\n                \"freearduino_get_temperature_value\" : \"temperature value from DHT11 pin %1 (C)\",\n                \"freearduino_get_distance_value\" : \"fistance value from HC-SR04 trig %1 echo %2 (mm)\",\n                \"freearduino_set_digital_value\": \"digitalWrite %1 to %2 %3\",\n                \"freearduino_get_digital_value\": \"digitalRead %1 \",\n                \"freearduino_get_digital_value_pullup\": \"digitalRead %1 (PULL UP)\",\n                \"freearduino_set_pwm_value\" : \"analogWrite %1 to %2 %3\",\n                \"freearduino_set_servo_angle\": \"write servo attached %1 angle as %2 %3\",\n                \"freearduino_set_motor_run\": \"set L293D motor %1 rotate %2 %3\",\n                \"freearduino_set_motor_speed\": \"set L293D motor %1 speed to %2 %3\",\n            }\n        }\n    }\n};\n\nEntry.freearduino.getBlocks = function() {\n    return {\n        freearduino_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'freearduino_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'freearduino_basic',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT',script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG[port];\n            },\n            syntax: { js: [], py: ['freearduino.get_analog_value(%1)'] },\n        },\n\n        freearduino_get_analog_value_pullup: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'freearduino_get_analog_value_pullup',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'freearduino_basic',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT',script);\n                var ANALOG = Entry.hw.portData.ANALOG_PULLUP;\n                return ANALOG[port];\n            },\n            syntax: { js: [], py: ['freearduino.get_analog_value_pullup(%1)'] },\n        },\n\n        freearduino_get_analog_mapped_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '1023',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '255',\n                    fontSize: 11,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'freearduino_get_analog_value',\n                        params: [ '0'],\n                    }, \n                    null, null, null, null],\n                type: 'freearduino_get_analog_mapped_value',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'freearduino_basic',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var stringValue4 = script.getValue('VALUE4', script);\n                var stringValue5 = script.getValue('VALUE5', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) &&\n                        stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) &&\n                        stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                var result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['freearduino_get_analog_mapped_value(%1, %2, %3, %4, %5)'],\n            },\n        },\n\n        freearduino_get_humidity_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['A0', '14'],\n                        ['A1', '15'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                        ['A4', '18'],\n                        ['A5', '19'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'freearduino_get_humidity_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'freearduino_sensor',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                Entry.hw.setDigitalPortValue(port, 201);\n                script.callReturn();\n                return Entry.hw.portData.DHT_HUMI;\n            },\n            syntax: { js: [], py: ['freearduino.get_humidity_value(%1)'] },\n        },\n\n        freearduino_get_temperature_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['A0', '14'],\n                        ['A1', '15'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                        ['A4', '18'],\n                        ['A5', '19'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'freearduino_get_temperature_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'freearduino_sensor',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                Entry.hw.setDigitalPortValue(port, 201);\n                script.callReturn();\n                return Entry.hw.portData.DHT_TEMP;\n            },\n            syntax: { js: [], py: ['freearduino.get_temperature_value(%1)'] },\n        },\n\n        freearduino_get_distance_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['A0', '14'],\n                        ['A1', '15'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                        ['A4', '18'],\n                        ['A5', '19'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['A0', '14'],\n                        ['A1', '15'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                        ['A4', '18'],\n                        ['A5', '19'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null,null],\n                type: 'freearduino_get_distance_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'freearduino_sensor',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var trig = script.getField('PORT1');\n                var echo = script.getField('PORT2');\n                Entry.hw.setDigitalPortValue(trig, 202);\n                Entry.hw.setDigitalPortValue(echo, 203);\n                script.callReturn();\n                return Entry.hw.portData.US_DISTANCE;\n            },\n            syntax: { js: [], py: ['freearduino.get_distance_value(%1, %2)'] },\n        },\n\n        freearduino_set_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['A0', '14'],\n                        ['A1', '15'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                        ['A4', '18'],\n                        ['A5', '19'],\n                    ],\n                    value: '13',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['HIGH', '255'], ['LOW', '0']],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null, null, null],\n                type: 'freearduino_set_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'freearduino_basic',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var value = script.getNumberField('OPERATOR');\n                Entry.hw.setDigitalPortValue(port,value === 255 ? 200 : 199);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['freearduino.set_digital_value(%1, %2)'] },\n        },\n\n        freearduino_get_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['A0', '14'],\n                        ['A1', '15'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                        ['A4', '18'],\n                        ['A5', '19'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'freearduino_get_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'freearduino_basic',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT',script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                return DIGITAL[port];\n            },\n            syntax: { js: [], py: ['freearduino.get_digital_value(%1)'] },\n        },\n\n        freearduino_get_digital_value_pullup: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['A0', '14'],\n                        ['A1', '15'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                        ['A4', '18'],\n                        ['A5', '19'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'freearduino_get_digital_value_pullup',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'freearduino_basic',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT',script);\n                var DIGITAL = Entry.hw.portData.DIGITAL_PULLUP;\n                return DIGITAL[port];\n            },\n            syntax: { js: [], py: ['freearduino.get_digital_value_pullup(%1)'] },\n        },\n\n        freearduino_set_pwm_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '255',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null, null, null],\n                type: 'freearduino_set_pwm_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'freearduino_basic',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                var port2;\n                if(port == 3) port2 = 20;\n                if(port == 5) port2 = 21;\n                if(port == 6) port2 = 22;\n                if(port == 9) port2 = 23;\n                if(port == 10) port2 = 24;\n                if(port == 11) port2 = 25;\n                Entry.hw.setDigitalPortValue(port2, value);\n                Entry.hw.removePortReadable(port);\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['freearduino.set_pwm_value(%1, %2)'],\n            },\n        },\n\n\n        freearduino_set_servo_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['A0', '14'],\n                        ['A1', '15'],\n                        ['A2', '16'],\n                        ['A3', '17'],\n                        ['A4', '18'],\n                        ['A5', '19'],\n                    ],\n                    value: '9',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '90',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null, null, null],\n                type: 'freearduino_set_servo_angle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'freearduino_servo',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 180);\n                Entry.hw.setDigitalPortValue(port, value+1);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['freearduino.set_servo_angle(%1, %2)'] },\n        },\n\n        freearduino_set_motor_run: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.roborobo_motor_stop, '4'],\n                        [Lang.Blocks.roborobo_motor_CW, '1'],\n                        [Lang.Blocks.roborobo_motor_CCW, '2'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null, null, null],\n                type: 'freearduino_set_motor_run',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'freearduino_motor',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var value1 = Number(script.getField('VALUE1'));\n                var value2 = Number(script.getField('VALUE2'));\n                var port;\n                if (value1 === 1) port = 11;\n                if (value1 === 2) port = 3;\n                if (value1 === 3) port = 5;\n                if (value1 === 4) port = 6;\n                Entry.hw.sendQueue[0] = 1;\n                Entry.hw.setDigitalPortValue(26,value1*10+value2);\n                Entry.hw.removePortReadable(port);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['freearduino.set_motor_run(%1, %2)'] },\n        },\n\n        freearduino_set_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,  \n            skeleton: 'basic',\n            fontColor: '#fff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '200',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null, null, null],\n                type: 'freearduino_set_motor_speed',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'freearduino_motor',\n            isNotFor: ['freearduino'],\n            func: function(sprite, script) {\n                var value1 = Number(script.getField('VALUE1'));\n                var value2 = script.getNumberValue('VALUE2');\n                value2 = Math.round(value2);\n                value2 = Math.max(value2, 0);\n                value2 = Math.min(value2, 255);\n                var port;\n                if (value1 === 1) port = 11;\n                if (value1 === 2) port = 3;\n                if (value1 === 3) port = 5;\n                if (value1 === 4) port = 6;\n                Entry.hw.sendQueue[0] = 1;\n                Entry.hw.setDigitalPortValue(value1+26,value2);\n                Entry.hw.removePortReadable(port);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['freearduino.set_motor_speed(%1, %2)'] },\n        },\n    };\n};\n\nmodule.exports = Entry.freearduino;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_freelinker2.js",
    "content": "'use strict';\n\nEntry.freelinker = {\n    id: '25.2',\n    name: 'freelinker2',\n    url: 'http://www.koreadigital.com/kr/main.asp',\n    imageName: 'FreeLinker2.png',\n    title: {\n        'ko': '프리링커2',\n        'en': 'freelinker2',\n    },\n    /*setZero: function() {\n\n        Entry.hw.sendQueue['data'] = 0;\n\n        Entry.hw.update();\n\n\n    },*/\n};\nEntry.freelinker.setLanguage = () => {\n    return {\n        ko: {\n            template: {\n                A_channel: 'A_channel',\n                B_channel: 'B_channel',\n                C_channel: 'C_channel',\n                D_channel: 'D_channel',\n            },\n        },\n        en: {\n            template: {\n                A_channel: 'A_channel',\n                B_channel: 'B_channel',\n                C_channel: 'C_channel',\n                D_channel: 'D_channel',\n            },\n        },\n    };\n};\n\nEntry.freelinker.blockMenuBlocks = [\n    //sciencecube start\n    'A_channel',\n    'B_channel',\n    'C_channel',\n    'D_channel',\n    //sciencecube end\n];\n\nEntry.freelinker.getBlocks = () => {\n    return {\n        A_channel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'A_channel',\n                text: 'A채널',\n            }, ],\n            def: {\n                type: 'A_channel',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'FreeLinker2',\n            isNotFor: ['freelinker2'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                Entry.hw.sendQueue['data'] = 'A';\n                var result = Entry.hw.portData['A'];\n\n                result /= 10000;\n\n                if (result < 0) {\n                    result = 0;\n                }\n\n                return result;\n            },\n        },\n        B_channel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'B_channel',\n                text: 'B채널',\n            }, ],\n            def: {\n                type: 'B_channel',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'FreeLinker2',\n            isNotFor: ['freelinker2'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                Entry.hw.sendQueue['data'] = 'B';\n                var result = Entry.hw.portData['B'];\n\n                result /= 10000;\n\n                if (result < 0) {\n                    result = 0;\n                }\n\n                return result;\n            },\n        },\n        C_channel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'C_channel',\n                text: 'C채널',\n            }, ],\n            def: {\n                type: 'C_channel',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'FreeLinker2',\n            isNotFor: ['freelinker2'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                Entry.hw.sendQueue['data'] = 'C';\n                var result = Entry.hw.portData['C'];\n\n                result /= 10000;\n\n                if (result < 0) {\n                    result = 0;\n                }\n\n                return result;\n            },\n        },\n        D_channel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'D_channel',\n                text: 'D채널',\n            }, ],\n            def: {\n                type: 'D_channel',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'FreeLinker2',\n            isNotFor: ['freelinker2'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                Entry.hw.sendQueue['data'] = 'D';\n                var result = Entry.hw.portData['D'];\n\n                result /= 10000;\n\n                if (result < 0) {\n                    result = 0;\n                }\n\n                return result;\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.freelinker;"
  },
  {
    "path": "src/playground/blocks/hardware/block_funboard.js",
    "content": "'use strict';\n\nEntry.FunBoard = {\n    // isNotFor\": [ \"funboard\" ] 값\n    id: '21.1',\n    name: 'funboard',\n    url: 'http://www.thinkfunedu.com',\n    imageName: 'funboard.png',\n    title: {\n        en: 'funboard',\n        ko: '펀보드',\n    },\n    Static: {\n        FUNBOARD_BLOCK_color: EntryStatic.colorSet.block.default.HARDWARE, // gray(#848484)\n        FUNBOARD_ARROW_COLOR_HW: EntryStatic.colorSet.block.default.HARDWARE,\n        FUNBOARD_FONT_COLOR: '#000f0f', // cyan(#000f0f), lightgray(#000113), reddish-brown(#982600)\n        FUNBOARD_LED_ON: 255,\n        BUTTON_PRESS_VALUE: 0, // 버튼 눌림 값\n        FUNBOARD_MATRIX_STRING_MAX: 5, //문자열 입력 허용 최대 문자수//실제 적용갯수는 (이 값 - 1)\n        DELAY_SECOND: 0.1, //0.3//0.2\n        ANALOG_STATE_PERCENT: 0.5, //30%(306.9) , 50%(511.5)\n        MATRIX_REGISTED_SYMBOL_TOTAL: 10, //펌웨어에 등록되어 있는 symbol 갯수\n    },\n\n    //entry [중지]-버튼을 누르면 실행되므로...\n    setZero: function() {\n        //-------------------------------------------------\n        {\n            if (!Entry.hw.sendQueue['SET']) {\n                Entry.hw.sendQueue['SET'] = {};\n            }\n            //reset - [중지] 시\n            var port = 13;\n            Entry.hw.sendQueue['SET'][port] = {\n                type: Entry.FunBoard.sensorTypes.ETC,\n                data: Entry.FunBoard.EventTypes.RESET,\n                time: new Date().getTime(),\n            };\n            for (var i = 0; i < 50000; i++) {}\n            Entry.hw.update();\n            delete Entry.hw.sendQueue[port];\n            for (var i = 0; i < 500000; i++) {}\n        }\n        //-------------------------------------------------\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].type = Entry.FunBoard.sensorTypes.ETC;\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    toByte: function(data) {\n        var c = data;\n        data = Entry.FunBoard._str2bin(c);\n        return data;\n    },\n    EventTypes: {\n        //ETC\n        BUZZER_ON: 1,\n        BUZZER_OFF: 2,\n        MATRIX_OFF_ALL: 3,\n        MATRIX_ON_ALL: 4,\n        MATRIX_INTENSITY: 5,\n        MATRIX_SCROLL_DIR: 6,\n        MATRIX_SCROLL_RAPID: 7,\n        MATRIX_SYMBOL_OUT: 8,\n        RESET: 13,\n        //MATRIX, MATRIX64\n        SET_ROW_COL: 3,\n        SET_ROW1: 4,\n        SET_COL1: 5,\n        STR_OUT_NO_SCROLL: 6,\n        STR_OUT_LEFT: 7,\n        STR_OUT_UP: 8,\n        STR_OUT_RIGHT: 9,\n        STR_OUT_DOWN: 10,\n        STR_OUT_DEFAULT: 11,\n        CHAR_OUT: 12,\n        SET_64: 13,\n        //14 이상 안된다. (digital port memory 14개)\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        ETC: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        rxBLUETOOTH: 9,\n        MATRIX: 10,\n        txBLUETOOTH: 11,\n        MATRIX64: 12,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n\n    PORT_MAP: {\n        rx: 0, //D0\n        tx: 1, //D1\n        matrix_cs: 2, //D2\n        matrix_data: 3, //D3(PWM)\n        matrix_clk: 4, //D4\n        up_bt: 5, //D5(PWM)\n        down_bt: 6, //D6(PWM)\n        left_bt: 7, //D7\n        right_bt: 8, //D8\n        buzzer: 9, //D9(PWM)\n        led_red: 10, //D10(PWM)\n        led_yellow: 11, //D11(PWM)\n        led_green: 12, //D12\n        led_blue: 13, //D13\n\n        slide: 0, //A0\n        cds: 1, //A1\n        mic: 2, //A2\n        space_touchbt: 3, //A3\n        enter_touchbt: 4, //A4\n        escape_touchbt: 5, //A5\n    },\n\n    //-------------------------------------------------------------//\n    // (value2 ~ value3) 범위의 값을 (value4 ~ value5) 범위로 변환 //\n    //-------------------------------------------------------------//\n    get_analog_value_map: function(a, what, value2, value3, value4, value5) {\n        var result = a;\n        var value2 = value2;\n        var value3 = value3;\n        var value4 = value4;\n        var value5 = value5;\n\n        var stringValue4 = String(value4);\n        var stringValue5 = String(value5);\n        var isFloat = false;\n\n        if (\n            (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n            (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n        ) {\n            isFloat = true;\n        }\n\n        if (value2 > value3) {\n            var swap = value2;\n            value2 = value3;\n            value3 = swap;\n        }\n        if (value4 > value5) {\n            var swap = value4;\n            value4 = value5;\n            value5 = swap;\n        }\n        result -= value2;\n        result = result * ((value5 - value4) / (value3 - value2));\n        result += value4;\n        result = Math.min(value5, result);\n        result = Math.max(value4, result);\n\n        if (isFloat) {\n            result = Math.round(result * 100) / 100;\n        } else {\n            result = Math.round(result);\n        }\n        return result;\n    },\n\n    bt_pressed: function(bt_index, value) {\n        var bt_pressed = 0;\n        //Analog\n        if (bt_index >= 5) {\n            bt_pressed = value > 100 ? 0 : 1;\n            //bt_pressed = value < 3 ? 1 : 0;\n            //bt_pressed = value < 1 ? 1 : 0;\n        } else {\n            //Digital\n            //bt_pressed = value > 0 ? 0 : 1;\n            bt_pressed = value > 0 ? 1 : 0;\n        }\n        return bt_pressed;\n    },\n    sleep: function(num) {\n        var now = new Date();\n        var stop = now.getTime() + num;\n        while (true) {\n            now = new Date();\n            if (now.getTime() > stop) return;\n        }\n    },\n    MinMax: function(v, vmin, vmax) {\n        var value = v;\n        value = Math.max(value, vmin);\n        value = Math.min(value, vmax);\n        return value;\n    },\n    get_char_index: function(k, str) {\n        //LedControl.h 의 displayCharSet[] 에서 symbol 제외한 문자들만 복사 사용 !!!\n        //즉, 비교할 수 있는 문자들만(기호는 문자비교를 할 수 없으니...)...\n        // \\ 는 앞에 \\ 를 붙인다.\n        var displayCharSet =\n            \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !?#$%&*+-/~^_@<>=()[]{},.:;'`\\\\|\";\n        var not_found = 62; //62 == space 문자 위치\n        if (k < 0 || k >= str.length) return not_found;\n        var pos = displayCharSet.indexOf(str[k]);\n        if (pos >= 0) {\n            return pos;\n        }\n        return not_found;\n    },\n    strwith01: function(len, str) {\n        var charset = '1#*';\n        var pos = -1;\n        var str3 = '';\n        for (var i = 0; i < len; i++) {\n            pos = -1;\n            if (i < len) pos = charset.indexOf(str[i]);\n            if (pos < 0) str3 = str3.concat('0');\n            else str3 = str3.concat('1');\n        }\n        return str3;\n    },\n    str2byte: function(str) {\n        var value = 0;\n        for (var i = str.length - 1; i >= 0; i--) {\n            value = value + str[i] * Math.pow(2, 8 - (i + 1));\n        }\n        return value;\n    },\n    // Convert a string to an array of little-endian words\n    // If chrsz is ASCII, characters >255 have their hi-byte silently ignored.\n    _str2bin: function(str) {\n        var chrsz = 8;\n        var bin = Array();\n        //var mask = 0xFF;\n        var mask = (1 << chrsz) - 1;\n        for (var i = 0; i < str.length * chrsz; i += chrsz)\n            bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << i % 32;\n        return bin;\n    },\n};\nEntry.FunBoard.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                funboard_buzzer_onoff: '버저 %1 %2',\n                funboard_buzzer_second: '버저%1%2초 동안%3',\n                funboard_buzzer_tone_simple: '%1%2음을%3초 연주하기%4',\n                funboard_color_led_on_pwm: '%1색  LED %2 % %3',\n                funboard_color_led_onoff: '%1색  LED %2 %3',\n                funboard_convert_scale: '%1값 %2~%3 에서 %4~%5 으로 변환값',\n                funboard_dotmatrix_1column: '%1칸 %2표시하기 %3',\n                funboard_dotmatrix_1row: '%1줄 %2표시하기 %3',\n                funboard_dotmatrix_1row_1column: '%1%2 %3표시하기 %4',\n                funboard_dotmatrix_64_display: '%1 (8x8)표시하기%2',\n                funboard_dotmatrix_big_eng: '대문자 %1표시하기 %2',\n                funboard_dotmatrix_char_display: '문자%1표시하기%2',\n                funboard_dotmatrix_extra_char: '문자 %1표시하기 %2',\n                funboard_dotmatrix_intensity: '밝기 %1% %2',\n                funboard_dotmatrix_kor: '▦  한글 %1표시하기 %2',\n                funboard_dotmatrix_num: '숫자 %1표시하기 %2',\n                funboard_dotmatrix_onoff: '모두 %1 %2',\n                funboard_dotmatrix_scroll_option: '스크롤 방향%1%2',\n                funboard_dotmatrix_scroll_rapid: '스크롤 속도 %1% %2',\n                funboard_dotmatrix_set: '%1줄 %2칸  %3 %4',\n                funboard_dotmatrix_small_eng: '소문자 %1표시하기 %2',\n                funboard_dotmatrix_string_display: '문자열%1표시하기%2',\n                funboard_dotmatrix_string_display_scroll: '문자열%1표시하기%2스크롤%3',\n                funboard_dotmatrix_symbol: '기호 %1표시하기 %2',\n                funboard_get_analog_sensor_2state: '%1값 %2',\n                funboard_get_digital_button_value: '%1 버튼  값',\n                funboard_get_number_sensor_value: '%1 값',\n                funboard_get_touch_button_value: '%1 터치  값',\n                funboard_set_digital_buzzer: '버저를 %1옥타브 %2음 %3초  연주%4',\n                funboard_what_button_pressed: '%1 버튼  눌림',\n                funboard_what_touch_button_pressed: '%1 터치됨',\n            },\n            Blocks: {\n                //for dropdown\n                FUNBOARD_bt_down: '노랑(B)',\n                FUNBOARD_bt_left: '초록(C)',\n                FUNBOARD_bt_right: '파랑(D)',\n                FUNBOARD_bt_up: '빨강(A)',\n                FUNBOARD_column_tag: '칸',\n                FUNBOARD_do_off: '끄기',\n                FUNBOARD_do_on: '켜기',\n                FUNBOARD_led_color_all: '모두',\n                FUNBOARD_led_color_blue: '파랑',\n                FUNBOARD_led_color_green: '초록',\n                FUNBOARD_led_color_red: '빨강',\n                FUNBOARD_led_color_str: '색',\n                FUNBOARD_led_color_yellow: '노랑',\n                FUNBOARD_led_off_str: 'LED 끄기',\n                FUNBOARD_led_on_str: 'LED 켜기',\n                FUNBOARD_row_tag: '줄',\n                FUNBOARD_scroll_down: '아래쪽으로',\n                FUNBOARD_scroll_left: '왼쪽으로',\n                FUNBOARD_scroll_no: '없음',\n                FUNBOARD_scroll_right: '오른쪽으로',\n                FUNBOARD_scroll_up: '위쪽으로',\n                FUNBOARD_sensor_cds: 'Cds (밝기 감지)',\n                FUNBOARD_sensor_mic: '마이크 (소리 감지)',\n                FUNBOARD_sensor_slide: '슬라이드 (막대 조정)',\n                FUNBOARD_sensor_state_1: '작다',\n                FUNBOARD_sensor_state_2: '크다',\n                FUNBOARD_touchbt_down: 'B(노랑)',\n                FUNBOARD_touchbt_enter: 'F',\n                FUNBOARD_touchbt_escape: 'G',\n                FUNBOARD_touchbt_left: 'C(초록)',\n                FUNBOARD_touchbt_right: 'D(파랑)',\n                FUNBOARD_touchbt_space: 'E',\n                FUNBOARD_touchbt_up: 'A(빨강)',\n                funboard_dotmatrix_set_off: '끄기',\n                funboard_dotmatrix_set_on: '켜기',\n            },\n            Menus: {\n                funboard: '펀보드',\n            },\n            Device: {\n                funboard: '펀보드',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                funboard_buzzer_onoff: 'buzzer %1 %2',\n                funboard_buzzer_second: 'buzzer%1%2seconds%3',\n                funboard_buzzer_tone_simple: 'play note%1%2,%3sec of Melody Playing%4',\n                funboard_color_led_on_pwm: '%1COLOR  LED %2 % %3',\n                funboard_color_led_onoff: '%1COLOR  LED %2 %3',\n                funboard_convert_scale: 'Convert %1 value from %2~%3 to %4~%5',\n                funboard_dotmatrix_1column: '%1column %2set %3',\n                funboard_dotmatrix_1row: '%1row %2set %3',\n                funboard_dotmatrix_1row_1column: '%1%2 %3set %4',\n                funboard_dotmatrix_64_display: '%1 (8x8)display%2',\n                funboard_dotmatrix_big_eng: 'capital letters %1 %2',\n                funboard_dotmatrix_char_display: 'char%1display%2',\n                funboard_dotmatrix_extra_char: 'char %1 %2',\n                funboard_dotmatrix_intensity: 'Intensity %1% %2',\n                funboard_dotmatrix_kor: '∷∷  korean %1 %2',\n                funboard_dotmatrix_num: 'number %1 %2',\n                funboard_dotmatrix_onoff: 'turn all %1 %2',\n                funboard_dotmatrix_scroll_option: 'scroll direction%1%2',\n                funboard_dotmatrix_scroll_rapid: 'scroll rapid %1% %2',\n                funboard_dotmatrix_set: '%1row %2column  %3 %4',\n                funboard_dotmatrix_small_eng: 'small letter %1 %2',\n                funboard_dotmatrix_string_display: 'string%1display%2',\n                funboard_dotmatrix_string_display_scroll: 'string%1display%2scroll%3',\n                funboard_dotmatrix_symbol: 'symbol %1 %2',\n                funboard_get_analog_sensor_2state: '%1 value %2',\n                funboard_get_digital_button_value: '%1 button value',\n                funboard_get_number_sensor_value: '%1 value',\n                funboard_get_touch_button_value: '%1 touch button value',\n                funboard_set_digital_buzzer: 'Play tone octave %1 note %2 beat %3 %4',\n                funboard_what_button_pressed: '%1 button pressed.',\n                funboard_what_touch_button_pressed: '%1 touch button pressed.',\n            },\n            Blocks: {\n                //for dropdown\n                FUNBOARD_bt_down: 'yellow(B)',\n                FUNBOARD_bt_left: 'green(C)',\n                FUNBOARD_bt_right: 'blue(D)',\n                FUNBOARD_bt_up: 'red(A)',\n                FUNBOARD_column_tag: 'column',\n                FUNBOARD_do_off: 'off',\n                FUNBOARD_do_on: 'on',\n                FUNBOARD_led_color_all: 'all',\n                FUNBOARD_led_color_blue: 'blue',\n                FUNBOARD_led_color_green: 'green',\n                FUNBOARD_led_color_red: 'red',\n                FUNBOARD_led_color_str: 'color  ',\n                FUNBOARD_led_color_yellow: 'yellow',\n                FUNBOARD_led_off_str: 'Turn off the LED',\n                FUNBOARD_led_on_str: 'Turn on the LED',\n                FUNBOARD_row_tag: 'row',\n                FUNBOARD_scroll_down: 'downward',\n                FUNBOARD_scroll_left: 'leftward',\n                FUNBOARD_scroll_no: 'no',\n                FUNBOARD_scroll_right: 'rightward',\n                FUNBOARD_scroll_up: 'upwards',\n                FUNBOARD_sensor_cds: 'light sensor',\n                FUNBOARD_sensor_mic: 'microphone sensor',\n                FUNBOARD_sensor_slide: 'potentiometer',\n                FUNBOARD_sensor_state_1: 'low',\n                FUNBOARD_sensor_state_2: 'high',\n                FUNBOARD_touchbt_down: 'B(yellow)',\n                FUNBOARD_touchbt_enter: 'F',\n                FUNBOARD_touchbt_escape: 'G',\n                FUNBOARD_touchbt_left: 'C(green)',\n                FUNBOARD_touchbt_right: 'D(blue)',\n                FUNBOARD_touchbt_space: 'E',\n                FUNBOARD_touchbt_up: 'A(red)',\n                funboard_dotmatrix_set_off: 'off',\n                funboard_dotmatrix_set_on: 'on',\n            },\n            Menus: {\n                funboard: 'funboard',\n            },\n            Device: {\n                funboard: 'funboard',\n            },\n        }, //\n    };\n};\nEntry.FunBoard.blockMenuBlocks = [\n    'funboard_list_pushbutton_basic',\n    'funboard_list_touchbutton_basic',\n    'funboard_list_analogsensor_basic',\n    'funboard_list_2_state_basic',\n    'funboard_list_ledcolor_basic',\n    'funboard_list_onoff_basic',\n    'funboard_what_button_pressed',\n    'funboard_what_touch_button_pressed',\n    'funboard_get_analog_sensor_2state',\n    'funboard_get_digital_button_value',\n    'funboard_get_touch_button_value',\n    'funboard_get_number_sensor_value',\n    'funboard_convert_scale',\n    'funboard_set_digital_buzzer',\n    'funboard_buzzer_onoff',\n    'funboard_color_led_onoff',\n    'funboard_color_led_on_pwm',\n    'funboard_dotmatrix_intensity',\n    'funboard_dotmatrix_onoff',\n    'funboard_dotmatrix_symbol',\n    'funboard_dotmatrix_char_display',\n    'funboard_dotmatrix_string_display_scroll',\n    'funboard_dotmatrix_set',\n    'funboard_dotmatrix_1row',\n    'funboard_dotmatrix_1column',\n];\nEntry.FunBoard.getBlocks = function() {\n    return {\n        //region FunBoard\n        funboard_list_pushbutton_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_bt_up, '1'],\n                        [Lang.Blocks.FUNBOARD_bt_down, '2'],\n                        [Lang.Blocks.FUNBOARD_bt_left, '3'],\n                        [Lang.Blocks.FUNBOARD_bt_right, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        funboard_list_touchbutton_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_touchbt_up, '1'],\n                        [Lang.Blocks.FUNBOARD_touchbt_down, '2'],\n                        [Lang.Blocks.FUNBOARD_touchbt_left, '3'],\n                        [Lang.Blocks.FUNBOARD_touchbt_right, '4'],\n                        [Lang.Blocks.FUNBOARD_touchbt_space, '5'],\n                        [Lang.Blocks.FUNBOARD_touchbt_enter, '6'],\n                        [Lang.Blocks.FUNBOARD_touchbt_escape, '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        funboard_list_analogsensor_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_sensor_slide, '1'],\n                        [Lang.Blocks.FUNBOARD_sensor_cds, '2'],\n                        [Lang.Blocks.FUNBOARD_sensor_mic, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        funboard_list_2_state_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_sensor_state_1, '1'],\n                        [Lang.Blocks.FUNBOARD_sensor_state_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        funboard_list_ledcolor_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_led_color_red, '1'],\n                        [Lang.Blocks.FUNBOARD_led_color_yellow, '2'],\n                        [Lang.Blocks.FUNBOARD_led_color_green, '3'],\n                        [Lang.Blocks.FUNBOARD_led_color_blue, '4'],\n                        [Lang.Blocks.FUNBOARD_led_color_all, '5'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        funboard_list_ledcolor_pwm_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_led_color_red, '1'],\n                        [Lang.Blocks.FUNBOARD_led_color_yellow, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        funboard_list_onoff_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_do_on, '1'],\n                        [Lang.Blocks.FUNBOARD_do_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        funboard_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        funboard_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        funboard_list_matrix_rows: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('ROW');\n            },\n        },\n        funboard_list_matrix_row_or_column: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_row_tag, '1'],\n                        [Lang.Blocks.FUNBOARD_column_tag, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                WHAT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('WHAT');\n            },\n        },\n        funboard_list_matrix_scroll_option: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FUNBOARD_scroll_no, '1'],\n                        [Lang.Blocks.FUNBOARD_scroll_left, '2'],\n                        [Lang.Blocks.FUNBOARD_scroll_right, '4'],\n                        [Lang.Blocks.FUNBOARD_scroll_up, '3'],\n                        [Lang.Blocks.FUNBOARD_scroll_down, '5'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                RET: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('RET');\n            },\n        },\n        funboard_list_matrix_char: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['A', 'A'],\n                        ['B', 'B'],\n                        ['C', 'C'],\n                        ['D', 'D'],\n                        ['E', 'E'],\n                        ['F', 'F'],\n                        ['G', 'G'],\n                        ['H', 'H'],\n                        ['I', 'I'],\n                        ['J', 'J'],\n                        ['K', 'K'],\n                        ['L', 'L'],\n                        ['M', 'M'],\n                        ['N', 'N'],\n                        ['O', 'O'],\n                        ['P', 'P'],\n                        ['Q', 'Q'],\n                        ['R', 'R'],\n                        ['S', 'S'],\n                        ['T', 'T'],\n                        ['U', 'U'],\n                        ['V', 'V'],\n                        ['W', 'W'],\n                        ['X', 'X'],\n                        ['Y', 'Y'],\n                        ['Z', 'Z'],\n                        ['a', 'a'],\n                        ['b', 'b'],\n                        ['c', 'c'],\n                        ['d', 'd'],\n                        ['e', 'e'],\n                        ['f', 'f'],\n                        ['g', 'g'],\n                        ['h', 'h'],\n                        ['i', 'i'],\n                        ['j', 'j'],\n                        ['k', 'k'],\n                        ['l', 'l'],\n                        ['m', 'm'],\n                        ['n', 'n'],\n                        ['o', 'o'],\n                        ['p', 'p'],\n                        ['q', 'q'],\n                        ['r', 'r'],\n                        ['s', 's'],\n                        ['t', 't'],\n                        ['u', 'u'],\n                        ['v', 'v'],\n                        ['w', 'w'],\n                        ['x', 'x'],\n                        ['y', 'y'],\n                        ['z', 'z'],\n                        [' ', ' '],\n                        ['!', '!'],\n                        ['?', '?'],\n                        ['#', '#'],\n                        ['$', '$'],\n                        ['%', '%'],\n                        ['&', '&'],\n                        ['*', '*'],\n                        ['+', '+'],\n                        ['-', '-'],\n                        ['/', '/'],\n                        ['~', '~'],\n                        ['^', '^'],\n                        ['_', '_'],\n                        ['@', '@'],\n                        ['<', '<'],\n                        ['>', '>'],\n                        ['=', '='],\n                        ['(', '('],\n                        [')', ')'],\n                        ['[', '['],\n                        [']', ']'],\n                        ['{', '{'],\n                        ['}', '}'],\n                        [',', ','],\n                        ['.', '.'],\n                        [':', ':'],\n                        [';', ';'],\n                        [\"'\", \"'\"],\n                        ['`', '`'],\n                        ['\\\\', '\\\\'],\n                        ['|', '|'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                RET: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('RET');\n            },\n        },\n        funboard_what_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_pushbutton_basic',\n                    },\n                ],\n                type: 'funboard_what_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'funboardget',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var port = 0;\n                var bt_index = script.getNumberValue('PORT');\n                if (bt_index == 1) port = Entry.FunBoard.PORT_MAP['up_bt'];\n                else if (bt_index == 2) port = Entry.FunBoard.PORT_MAP['down_bt'];\n                else if (bt_index == 3) port = Entry.FunBoard.PORT_MAP['left_bt'];\n                else if (bt_index == 4) port = Entry.FunBoard.PORT_MAP['right_bt'];\n\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                var value = 0;\n                var bt_pressed = 0;\n                value = DIGITAL ? DIGITAL[port] || 0 : 0;\n\n                if (Entry.FunBoard.Static.BUTTON_PRESS_VALUE == 0) {\n                    bt_pressed = value > 0 ? 0 : 1;\n                } else {\n                    bt_pressed = value > 0 ? 1 : 0;\n                }\n                /*\n            if(!Entry.hw.sendQueue['GET']) {\n                Entry.hw.sendQueue['GET'] = {};\n            }\n            Entry.hw.sendQueue['GET'][Entry.FunBoard.sensorTypes.DIGITAL] = {\n                port: port,\n                time: new Date().getTime()\n            };\n            */\n\n                return bt_pressed;\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_what_touch_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_touchbutton_basic',\n                    },\n                ],\n                type: 'funboard_what_touch_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'funboardget',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var port = 0;\n                var bt_index = script.getNumberValue('PORT');\n                if (bt_index == 1) port = Entry.FunBoard.PORT_MAP['up_bt'];\n                else if (bt_index == 2) port = Entry.FunBoard.PORT_MAP['down_bt'];\n                else if (bt_index == 3) port = Entry.FunBoard.PORT_MAP['left_bt'];\n                else if (bt_index == 4) port = Entry.FunBoard.PORT_MAP['right_bt'];\n                else if (bt_index == 5) port = Entry.FunBoard.PORT_MAP['space_touchbt'];\n                else if (bt_index == 6) port = Entry.FunBoard.PORT_MAP['enter_touchbt'];\n                else if (bt_index == 7) port = Entry.FunBoard.PORT_MAP['escape_touchbt'];\n\n                var value = 0;\n                var bt_pressed = 0;\n\n                if (bt_index >= 5) {\n                    var ANALOG = Entry.hw.portData.ANALOG;\n                    value = ANALOG ? ANALOG[port] || 0 : 0;\n                } else {\n                    var DIGITAL = Entry.hw.portData.DIGITAL;\n                    value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                    /*\n                if(!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.FunBoard.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime()\n                };\n                */\n                }\n                if (Entry.FunBoard.Static.BUTTON_PRESS_VALUE == 0) {\n                    bt_pressed = value > 0 ? 0 : 1;\n                } else {\n                    bt_pressed = value > 0 ? 1 : 0;\n                }\n                return bt_pressed;\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_get_digital_button_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_pushbutton_basic',\n                    },\n                ],\n                type: 'funboard_get_digital_button_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'funboardget',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var port = 0;\n                var bt_index = script.getNumberValue('PORT');\n                if (bt_index == 1) port = Entry.FunBoard.PORT_MAP['up_bt'];\n                else if (bt_index == 2) port = Entry.FunBoard.PORT_MAP['down_bt'];\n                else if (bt_index == 3) port = Entry.FunBoard.PORT_MAP['left_bt'];\n                else if (bt_index == 4) port = Entry.FunBoard.PORT_MAP['right_bt'];\n\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                var value = 0;\n                /*\n            if(!Entry.hw.sendQueue['GET']) {\n                Entry.hw.sendQueue['GET'] = {};\n            }\n            Entry.hw.sendQueue['GET'][Entry.FunBoard.sensorTypes.DIGITAL] = {\n                port: port,\n                time: new Date().getTime()\n            };\n            */\n\n                // 버튼 눌림 값 그대로...\n                value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                //누른 경우 1, 아니면 0 으로 알려 준다.\n                if (Entry.FunBoard.Static.BUTTON_PRESS_VALUE == 0) {\n                    value = value ? 0 : 1;\n                }\n                return value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_get_touch_button_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_touchbutton_basic',\n                    },\n                ],\n                type: 'funboard_get_touch_button_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'funboardget',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var port = 0;\n                var bt_index = script.getNumberValue('PORT');\n                if (bt_index == 1) port = Entry.FunBoard.PORT_MAP['up_bt'];\n                else if (bt_index == 2) port = Entry.FunBoard.PORT_MAP['down_bt'];\n                else if (bt_index == 3) port = Entry.FunBoard.PORT_MAP['left_bt'];\n                else if (bt_index == 4) port = Entry.FunBoard.PORT_MAP['right_bt'];\n                else if (bt_index == 5) port = Entry.FunBoard.PORT_MAP['space_touchbt'];\n                else if (bt_index == 6) port = Entry.FunBoard.PORT_MAP['enter_touchbt'];\n                else if (bt_index == 7) port = Entry.FunBoard.PORT_MAP['escape_touchbt'];\n\n                var value = 0;\n                if (bt_index >= 5) {\n                    var ANALOG = Entry.hw.portData.ANALOG;\n                    value = ANALOG ? ANALOG[port] || 0 : 0;\n\n                    // 버튼 눌림 값 그대로...\n                    value = ANALOG ? ANALOG[port] || 0 : 0;\n                    //누른 경우 1, 아니면 0 으로 알려 준다.\n                    if (Entry.FunBoard.Static.BUTTON_PRESS_VALUE == 0) {\n                        value = value ? 0 : 1;\n                    }\n                } else {\n                    var DIGITAL = Entry.hw.portData.DIGITAL;\n                    /*\n                if(!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.FunBoard.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime()\n                };\n                */\n\n                    // 버튼 눌림 값 그대로...\n                    value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                    //누른 경우 1, 아니면 0 으로 알려 준다.\n                    if (Entry.FunBoard.Static.BUTTON_PRESS_VALUE == 0) {\n                        value = value ? 0 : 1;\n                    }\n                }\n                return value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_get_number_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_analogsensor_basic',\n                    },\n                ],\n                type: 'funboard_get_number_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'funboardget',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var port = 0;\n                var index = script.getValue('PORT', script);\n                if (index == 1) port = Entry.FunBoard.PORT_MAP['slide'];\n                else if (index == 2) port = Entry.FunBoard.PORT_MAP['cds'];\n                else if (index == 3) port = Entry.FunBoard.PORT_MAP['mic'];\n\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value = ANALOG ? ANALOG[port] || 0 : 0;\n                return value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_get_analog_sensor_2state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_analogsensor_basic',\n                    },\n                    {\n                        type: 'funboard_list_2_state_basic',\n                    },\n                ],\n                type: 'funboard_get_analog_sensor_2state',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                STATE: 1,\n            },\n            class: 'funboardget',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var index = script.getValue('PORT', script);\n                var state = script.getValue('STATE', script);\n                var vmin = 0,\n                    vmax = 1023,\n                    vlimit;\n                var port = 0;\n                var mode = 1;\n                if (index == 1) port = Entry.FunBoard.PORT_MAP['slide'];\n                else if (index == 2) port = Entry.FunBoard.PORT_MAP['cds'];\n                else if (index == 3) port = Entry.FunBoard.PORT_MAP['mic'];\n\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value = ANALOG ? ANALOG[port] || 0 : 0;\n\n                vlimit =\n                    vmin +\n                    Math.max(0, Math.abs(vmax - vmin) * Entry.FunBoard.Static.ANALOG_STATE_PERCENT);\n\n                var ret = 0;\n                //작다\n                if (state == 1) {\n                    if (value < vlimit) ret = 1;\n                } else {\n                    //크다\n                    //if(state == 2)\n                    if (value > vlimit) ret = 1;\n                }\n                return ret;\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_analogsensor_basic',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'funboard_convert_scale',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'funboardget',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var index = script.getValue('PORT', script);\n                var port = 0;\n                if (index == 1) port = Entry.FunBoard.PORT_MAP['slide'];\n                else if (index == 2) port = Entry.FunBoard.PORT_MAP['cds'];\n                else if (index == 3) port = Entry.FunBoard.PORT_MAP['mic'];\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var stringValue4 = script.getValue('VALUE4', script);\n                var stringValue5 = script.getValue('VALUE5', script);\n                var isFloat = false;\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value1 = ANALOG ? ANALOG[port] || 0 : 0;\n                var result = value1;\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n                //return Math.round(result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n                return result;\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_digital_octave',\n                    },\n                    {\n                        type: 'funboard_list_digital_tone',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'funboard_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                NOTE: 1,\n                DURATION: 2,\n            },\n            class: 'funboardset',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var port = Entry.FunBoard.PORT_MAP['buzzer'];\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.FunBoard.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.FunBoard.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.FunBoard.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_buzzer_second: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_onoff_basic',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'funboard_buzzer_second',\n            },\n            paramsKeyMap: {\n                ONOFF: 0,\n                DURATION: 1,\n            },\n            class: 'funboardset',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var onoff = script.getNumberValue('ONOFF');\n                var duration = script.getNumberValue('DURATION');\n                var li_duration = Math.ceil(duration);\n                if (li_duration < 1) return script.callReturn();\n\n                if (!script.isStart) {\n                    {\n                        var port = 0;\n                        if (onoff == '1') port = Entry.FunBoard.EventTypes.BUZZER_ON;\n                        else port = Entry.FunBoard.EventTypes.BUZZER_OFF;\n\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.FunBoard.sensorTypes.ETC,\n                            data: li_duration,\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue = li_duration; // * Entry.FunBoard.Static.DELAY_SECOND;\n                    var fps = Entry.FPS || 60;\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_buzzer_tone_simple: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_c, 'C'],\n                        [Lang.Blocks.XBOT_d, 'D'],\n                        [Lang.Blocks.XBOT_e, 'E'],\n                        [Lang.Blocks.XBOT_f, 'F'],\n                        [Lang.Blocks.XBOT_g, 'G'],\n                        [Lang.Blocks.XBOT_a, 'A'],\n                        [Lang.Blocks.XBOT_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'funboard_buzzer_tone_simple',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                VALUE: 2,\n            },\n            class: 'funboardset',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var note = script.getStringField('NOTE', script);\n                var octave = script.getStringField('OCTAVE', script);\n                var duration = script.getNumberValue('VALUE', script);\n\n                var value = 255;\n                if (note == 'C') value = 39;\n                else if (note == 'D') value = 75;\n                else if (note == 'E') value = 111;\n                else if (note == 'F') value = 147;\n                else if (note == 'G') value = 183;\n                else if (note == 'A') value = 219;\n                else if (note == 'B') value = 255;\n                var port = Entry.FunBoard.PORT_MAP['buzzer'];\n                Entry.hw.sendQueue[port] = value;\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_buzzer_onoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_onoff_basic',\n                    },\n                    null,\n                ],\n                type: 'funboard_buzzer_onoff',\n            },\n            paramsKeyMap: {\n                ONOFF: 0,\n            },\n            class: 'funboardset',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var onoff = script.getNumberValue('ONOFF');\n\n                if (!script.isStart) {\n                    {\n                        //1 based value\n                        var eff_value = Math.floor(Math.random() * (123 - 1)) + 1;\n\n                        var port = 0;\n                        if (onoff == '1') port = Entry.FunBoard.EventTypes.BUZZER_ON;\n                        else port = Entry.FunBoard.EventTypes.BUZZER_OFF;\n\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.FunBoard.sensorTypes.ETC,\n                            data: eff_value,\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Math.max(1, 3 * Entry.FunBoard.Static.DELAY_SECOND);\n                    timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_color_led_onoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_ledcolor_basic',\n                    },\n                    {\n                        type: 'funboard_list_onoff_basic',\n                    },\n                    null,\n                ],\n                type: 'funboard_color_led_onoff',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                ONOFF: 1,\n            },\n            class: 'funboardset',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var color_index = script.getNumberValue('VALUE');\n                var onoff = script.getValue('ONOFF');\n\n                if (!script.isStart) {\n                    {\n                        var portR = 0;\n                        var portY = 0;\n                        var portG = 0;\n                        var portB = 0;\n\n                        //on\n                        if (onoff == '1') {\n                            portR = 0;\n                            portY = 0;\n                            portG = 0;\n                            portB = 0;\n                            if (color_index === 1) portR = 255;\n                            else if (color_index === 2) portY = 255;\n                            else if (color_index === 3) portG = 255;\n                            else if (color_index === 4) portB = 255;\n                            else if (color_index === 5) {\n                                portR = 255;\n                                portY = 255;\n                                portG = 255;\n                                portB = 255;\n                            }\n\n                            if (portR > 0) {\n                                if (!Entry.hw.sendQueue['SET']) {\n                                    Entry.hw.sendQueue['SET'] = {};\n                                }\n                                Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_red']] = {\n                                    type: Entry.FunBoard.sensorTypes.DIGITAL,\n                                    data: portR,\n                                    time: new Date().getTime(),\n                                };\n                            }\n                            if (portY > 0) {\n                                if (!Entry.hw.sendQueue['SET']) {\n                                    Entry.hw.sendQueue['SET'] = {};\n                                }\n                                Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_yellow']] = {\n                                    type: Entry.FunBoard.sensorTypes.DIGITAL,\n                                    data: portY,\n                                    time: new Date().getTime(),\n                                };\n                            }\n                            if (portG > 0) {\n                                if (!Entry.hw.sendQueue['SET']) {\n                                    Entry.hw.sendQueue['SET'] = {};\n                                }\n                                Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_green']] = {\n                                    type: Entry.FunBoard.sensorTypes.DIGITAL,\n                                    data: portG,\n                                    time: new Date().getTime(),\n                                };\n                            }\n                            if (portB > 0) {\n                                if (!Entry.hw.sendQueue['SET']) {\n                                    Entry.hw.sendQueue['SET'] = {};\n                                }\n                                Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_blue']] = {\n                                    type: Entry.FunBoard.sensorTypes.DIGITAL,\n                                    data: portB,\n                                    time: new Date().getTime(),\n                                };\n                            }\n                        } else {\n                            //off\n                            portR = 255;\n                            portY = 255;\n                            portG = 255;\n                            portB = 255;\n\n                            if (color_index === 1) portR = 0;\n                            else if (color_index === 2) portY = 0;\n                            else if (color_index === 3) portG = 0;\n                            else if (color_index === 4) portB = 0;\n                            else if (color_index === 5) {\n                                portR = 0;\n                                portY = 0;\n                                portG = 0;\n                                portB = 0;\n                            }\n\n                            if (portR < 1) {\n                                if (!Entry.hw.sendQueue['SET']) {\n                                    Entry.hw.sendQueue['SET'] = {};\n                                }\n                                Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_red']] = {\n                                    type: Entry.FunBoard.sensorTypes.DIGITAL,\n                                    data: portR,\n                                    time: new Date().getTime(),\n                                };\n                            }\n                            if (portY < 1) {\n                                if (!Entry.hw.sendQueue['SET']) {\n                                    Entry.hw.sendQueue['SET'] = {};\n                                }\n                                Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_yellow']] = {\n                                    type: Entry.FunBoard.sensorTypes.DIGITAL,\n                                    data: portY,\n                                    time: new Date().getTime(),\n                                };\n                            }\n                            if (portG < 1) {\n                                if (!Entry.hw.sendQueue['SET']) {\n                                    Entry.hw.sendQueue['SET'] = {};\n                                }\n                                Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_green']] = {\n                                    type: Entry.FunBoard.sensorTypes.DIGITAL,\n                                    data: portG,\n                                    time: new Date().getTime(),\n                                };\n                            }\n                            if (portB < 1) {\n                                if (!Entry.hw.sendQueue['SET']) {\n                                    Entry.hw.sendQueue['SET'] = {};\n                                }\n                                Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_blue']] = {\n                                    type: Entry.FunBoard.sensorTypes.DIGITAL,\n                                    data: portB,\n                                    time: new Date().getTime(),\n                                };\n                            }\n                        }\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_color_led_on_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_ledcolor_pwm_basic',\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'funboard_color_led_on_pwm',\n            },\n            pyHelpDef: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['A&value'],\n                    },\n                    null,\n                ],\n                type: 'funboard_color_led_on_pwm',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                PERCENT: 1,\n            },\n            class: 'funboardset',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var color_index = script.getNumberValue('VALUE');\n                var li_percent = script.getNumberValue('PERCENT');\n                li_percent = Entry.FunBoard.MinMax(li_percent, 0, 100);\n                var pwm_value = Math.round(\n                    Entry.FunBoard.Static.FUNBOARD_LED_ON * (li_percent / 100)\n                );\n\n                if (!script.isStart) {\n                    {\n                        var portR = 0;\n                        var portY = 0;\n                        if (color_index === 1) portR = pwm_value;\n                        else if (color_index === 2) portY = pwm_value;\n\n                        if (portR > 0) {\n                            if (!Entry.hw.sendQueue['SET']) {\n                                Entry.hw.sendQueue['SET'] = {};\n                            }\n                            Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_red']] = {\n                                type: Entry.FunBoard.sensorTypes.PWM,\n                                data: portR,\n                                time: new Date().getTime(),\n                            };\n                        }\n                        if (portY > 0) {\n                            if (!Entry.hw.sendQueue['SET']) {\n                                Entry.hw.sendQueue['SET'] = {};\n                            }\n                            Entry.hw.sendQueue['SET'][Entry.FunBoard.PORT_MAP['led_yellow']] = {\n                                type: Entry.FunBoard.sensorTypes.PWM,\n                                data: portY,\n                                time: new Date().getTime(),\n                            };\n                        }\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_intensity: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_intensity',\n            },\n            pyHelpDef: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['A&value'],\n                    },\n                    null,\n                ],\n                type: 'funboard_color_led_on_pwm',\n            },\n            paramsKeyMap: {\n                PERCENT: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var li_percent = script.getNumberValue('PERCENT');\n                //1-based value (setZero와 구별)\n                li_percent = Entry.FunBoard.MinMax(li_percent, 0, 100);\n                li_percent = li_percent + 1;\n\n                if (!script.isStart) {\n                    {\n                        var port = Entry.FunBoard.EventTypes.MATRIX_INTENSITY;\n\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.FunBoard.sensorTypes.ETC,\n                            data: li_percent,\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = 1 * Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_scroll_option: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_matrix_scroll_option',\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_scroll_option',\n            },\n            paramsKeyMap: {\n                OPTION: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var value = script.getValue('OPTION', script);\n                if (value.length < 1) return script.callReturn();\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.MATRIX_SCROLL_DIR;\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.ETC,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_scroll_rapid: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_scroll_rapid',\n            },\n            pyHelpDef: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['A&value'],\n                    },\n                    null,\n                ],\n                type: 'funboard_color_led_on_pwm',\n            },\n            paramsKeyMap: {\n                PERCENT: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var li_percent = script.getNumberValue('PERCENT');\n                //1-based value로 (setZero와 구별)\n                li_percent = Entry.FunBoard.MinMax(li_percent, 0, 100);\n                li_percent = li_percent + 1;\n\n                if (!script.isStart) {\n                    {\n                        var port = Entry.FunBoard.EventTypes.MATRIX_SCROLL_RAPID;\n                        if (!Entry.hw.sendQueue['SET']) {\n                            Entry.hw.sendQueue['SET'] = {};\n                        }\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.FunBoard.sensorTypes.ETC,\n                            data: li_percent,\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_onoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_onoff_basic',\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_onoff',\n            },\n            paramsKeyMap: {\n                ONOFF: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var onoff = script.getValue('ONOFF', script);\n                var eff_value = Math.floor(Math.random() * (123 - 1)) + 1;\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.MATRIX_OFF_ALL;\n                    if (onoff == '1') port = Entry.FunBoard.EventTypes.MATRIX_ON_ALL;\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = 1 * Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.ETC,\n                        data: eff_value,\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_char_display: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_matrix_char',\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_char_display',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var string = script.getValue('VALUE', script);\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n\n                //1개 문자만 허용\n                var char_tot = 1;\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.CHAR_OUT;\n\n                    var text = [];\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < char_tot; i++) {\n                            text[i] = Entry.FunBoard.toByte(string[i]);\n                        }\n                    } else {\n                        text[0] = string[0];\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (char_tot + 0.5) * Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_string_display: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['A'],\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_string_display',\n            },\n            pyHelpDef: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['A&value'],\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_string_display',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var string = script.getValue('VALUE', script);\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                var char_tot = Math.min(\n                    string.length,\n                    Entry.FunBoard.Static.FUNBOARD_MATRIX_STRING_MAX\n                );\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.STR_OUT_DEFAULT;\n\n                    var text = [];\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < char_tot; i++) {\n                            text[i] = Entry.FunBoard.toByte(string[i]);\n                        }\n                    } else {\n                        text[0] = string[0];\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = char_tot * Entry.FunBoard.Static.DELAY_SECOND;\n                    //scroll//var timeValue = (char_tot*3)*Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_string_display_scroll: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['A'],\n                    },\n                    {\n                        type: 'funboard_list_matrix_scroll_option',\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_string_display_scroll',\n            },\n            pyHelpDef: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['A&value'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['A&value'],\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_string_display_scroll',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                SCROLL: 1,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var string = script.getValue('VALUE', script);\n                var scroll_opt = script.getValue('SCROLL', script);\n                if (string.length < 1) return script.callReturn();\n\n                var char_tot = Math.min(\n                    string.length,\n                    Entry.FunBoard.Static.FUNBOARD_MATRIX_STRING_MAX\n                );\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.STR_OUT_NO_SCROLL;\n                    if (scroll_opt == '1') port = Entry.FunBoard.EventTypes.STR_OUT_NO_SCROLL;\n                    else if (scroll_opt == '2') port = Entry.FunBoard.EventTypes.STR_OUT_LEFT;\n                    else if (scroll_opt == '3') port = Entry.FunBoard.EventTypes.STR_OUT_UP;\n                    else if (scroll_opt == '4') port = Entry.FunBoard.EventTypes.STR_OUT_RIGHT;\n                    else if (scroll_opt == '5') port = Entry.FunBoard.EventTypes.STR_OUT_DOWN;\n\n                    var text = [];\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < char_tot; i++) {\n                            text[i] = Entry.FunBoard.toByte(string[i]);\n                        }\n                    } else {\n                        text[0] = string[0];\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    //var timeValue = char_tot*Entry.FunBoard.Static.DELAY_SECOND;\n                    var timeValue = char_tot;\n                    //var timeValue = Math.ceil(char_tot*0.6);\n                    //var timeValue = (char_tot*0.8);\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        funboard_dotmatrix_symbol: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['♥', '1'],\n                        ['♡', '2'],\n                        ['↑', '3'],\n                        ['↓', '4'],\n                        ['←', '5'],\n                        ['→', '6'],\n                        ['■', '7'],\n                        ['◆', '8'],\n                        ['●', '9'],\n                        ['※', '10'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'funboard_dotmatrix_symbol',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var string = script.getField('VALUE');\n                //1 based value (setZero 구별)\n                var value = parseInt(string);\n                if (value < 1 || value > Entry.FunBoard.Static.MATRIX_REGISTED_SYMBOL_TOTAL) {\n                    return script.callReturn();\n                }\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.MATRIX_SYMBOL_OUT;\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.ETC,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = 1 * Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_num: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'funboard_dotmatrix_num',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var string = script.getField('VALUE');\n                var char_index = parseInt(string);\n                if (char_index < 0 || string.length < 1) {\n                    return script.callReturn();\n                }\n                var char_tot = Math.min(\n                    string.length,\n                    Entry.FunBoard.Static.FUNBOARD_MATRIX_STRING_MAX\n                );\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.STR_OUT_NO_SCROLL;\n\n                    var text = [];\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < char_tot; i++) {\n                            text[i] = Entry.FunBoard.toByte(string[i]);\n                        }\n                    } else {\n                        text[0] = string[0];\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = char_tot * Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_big_eng: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                        ['C', 'C'],\n                        ['D', 'D'],\n                        ['E', 'E'],\n                        ['F', 'F'],\n                        ['G', 'G'],\n                        ['H', 'H'],\n                        ['I', 'I'],\n                        ['J', 'J'],\n                        ['K', 'K'],\n                        ['L', 'L'],\n                        ['M', 'M'],\n                        ['N', 'N'],\n                        ['O', 'O'],\n                        ['P', 'P'],\n                        ['Q', 'Q'],\n                        ['R', 'R'],\n                        ['S', 'S'],\n                        ['T', 'T'],\n                        ['U', 'U'],\n                        ['V', 'V'],\n                        ['W', 'W'],\n                        ['X', 'X'],\n                        ['Y', 'Y'],\n                        ['Z', 'Z'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'funboard_dotmatrix_big_eng',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var string = script.getField('VALUE');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                var char_tot = Math.min(\n                    string.length,\n                    Entry.FunBoard.Static.FUNBOARD_MATRIX_STRING_MAX\n                );\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.STR_OUT_NO_SCROLL;\n\n                    var text = [];\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < char_tot; i++) {\n                            text[i] = Entry.FunBoard.toByte(string[i]);\n                        }\n                    } else {\n                        text[0] = string;\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = char_tot * Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_small_eng: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['a', 'a'],\n                        ['b', 'b'],\n                        ['c', 'c'],\n                        ['d', 'd'],\n                        ['e', 'e'],\n                        ['f', 'f'],\n                        ['g', 'g'],\n                        ['h', 'h'],\n                        ['i', 'i'],\n                        ['j', 'j'],\n                        ['k', 'k'],\n                        ['l', 'l'],\n                        ['m', 'm'],\n                        ['n', 'n'],\n                        ['o', 'o'],\n                        ['p', 'p'],\n                        ['q', 'q'],\n                        ['r', 'r'],\n                        ['s', 's'],\n                        ['t', 't'],\n                        ['u', 'u'],\n                        ['v', 'v'],\n                        ['w', 'w'],\n                        ['x', 'x'],\n                        ['y', 'y'],\n                        ['z', 'z'],\n                    ],\n                    value: 'a',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'funboard_dotmatrix_small_eng',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var string = script.getField('VALUE');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                var char_tot = Math.min(\n                    string.length,\n                    Entry.FunBoard.Static.FUNBOARD_MATRIX_STRING_MAX\n                );\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.STR_OUT_NO_SCROLL;\n\n                    var text = [];\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < char_tot; i++) {\n                            text[i] = Entry.FunBoard.toByte(string[i]);\n                        }\n                    } else {\n                        text[0] = string[0];\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = char_tot * Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_extra_char: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['!', '!'],\n                        ['?', '?'],\n                        ['#', '#'],\n                        ['$', '$'],\n                        ['%', '%'],\n                        ['&', '&'],\n                        ['*', '*'],\n                        ['+', '+'],\n                        ['-', '-'],\n                        ['/', '/'],\n                        ['~', '~'],\n                        ['^', '^'],\n                        ['_', '_'],\n                        ['@', '@'],\n                        ['<', '<'],\n                        ['>', '>'],\n                        [\n                            '=',\n                            '=',\n                        ] /*,\n                    [\"(\",\"(\"],\n                    [\")\",\")\"],\n                    [\"[\",\"[\"],\n                    [\"]\",\"]\"],\n                    [\"{\",\"{\"],\n                    [\"}\",\"}\"],\n                    [\",\",\",\"],\n                    [\".\",\".\"],\n                    [\":\",\":\"],\n                    [\";\",\";\"],\n                    [\"'\",\"'\"],\n                    [\"`\",\"`\"],\n                    [\"\\\\\",\"\\\\\"],\n                    [\"|\",\"|\"]\n                    */,\n                    ],\n                    value: '!',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'funboard_dotmatrix_extra_char',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var string = script.getField('VALUE');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                var char_tot = Math.min(\n                    string.length,\n                    Entry.FunBoard.Static.FUNBOARD_MATRIX_STRING_MAX\n                );\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.STR_OUT_NO_SCROLL;\n\n                    var text = [];\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < char_tot; i++) {\n                            text[i] = Entry.FunBoard.toByte(string[i]);\n                        }\n                    } else {\n                        text[0] = string[0];\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = char_tot * Entry.FunBoard.Static.DELAY_SECOND;\n                    timeValue = (60 / fps) * timeValue * 1000;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_1row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_matrix_rows',\n                    },\n                    {\n                        type: 'text',\n                        params: ['00000000'],\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_1row',\n            },\n            paramsKeyMap: {\n                WHAT: 0,\n                BIT8: 1,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var str = script.getNumberValue('WHAT');\n                var str_bit8 = script.getStringValue('BIT8', script);\n\n                var charset = '1#*';\n                var pos = -1;\n                var str3 = '';\n                //8개 column 값\n                for (var i = 0; i < 8; i++) {\n                    pos = -1;\n                    if (i < str_bit8.length) pos = charset.indexOf(str_bit8[i]);\n                    if (pos < 0) str3 = str3.concat('0');\n                    else str3 = str3.concat('1');\n                }\n\n                if (!script.isStart) {\n                    var port = Entry.FunBoard.EventTypes.SET_ROW1;\n                    var text = [];\n                    text[0] = str;\n                    text[1] = Entry.FunBoard.toByte(str3[0]);\n                    text[2] = Entry.FunBoard.toByte(str3[1]);\n                    text[3] = Entry.FunBoard.toByte(str3[2]);\n                    text[4] = Entry.FunBoard.toByte(str3[3]);\n                    text[5] = Entry.FunBoard.toByte(str3[4]);\n                    text[6] = Entry.FunBoard.toByte(str3[5]);\n                    text[7] = Entry.FunBoard.toByte(str3[6]);\n                    text[8] = Entry.FunBoard.toByte(str3[7]);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    //timeValue = 60/fps*timeValue*1000;\n                    timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        value: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_1column: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_matrix_rows',\n                    },\n                    {\n                        type: 'text',\n                        params: ['00000000'],\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_1column',\n            },\n            paramsKeyMap: {\n                WHAT: 0,\n                BIT8: 1,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var str = script.getNumberValue('WHAT');\n                var str_bit8 = script.getStringValue('BIT8', script);\n\n                var charset = '1#*';\n                var pos = -1;\n                var str3 = '';\n                //8개 row 값\n                for (var i = 0; i < 8; i++) {\n                    pos = -1;\n                    if (i < str_bit8.length) pos = charset.indexOf(str_bit8[i]);\n                    if (pos < 0) str3 = str3.concat('0');\n                    else str3 = str3.concat('1');\n                }\n\n                var port = Entry.FunBoard.EventTypes.SET_COL1;\n\n                if (!script.isStart) {\n                    var text = [];\n                    text[0] = str;\n                    text[1] = Entry.FunBoard.toByte(str3[0]);\n                    text[2] = Entry.FunBoard.toByte(str3[1]);\n                    text[3] = Entry.FunBoard.toByte(str3[2]);\n                    text[4] = Entry.FunBoard.toByte(str3[3]);\n                    text[5] = Entry.FunBoard.toByte(str3[4]);\n                    text[6] = Entry.FunBoard.toByte(str3[5]);\n                    text[7] = Entry.FunBoard.toByte(str3[6]);\n                    text[8] = Entry.FunBoard.toByte(str3[7]);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    //timeValue = 60/fps*timeValue*1000;\n                    timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        value: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        funboard_dotmatrix_1row_1column: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_matrix_rows',\n                    },\n                    {\n                        type: 'funboard_list_matrix_row_or_column',\n                    },\n                    {\n                        type: 'text',\n                        params: ['00000000'],\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_1row_1column',\n            },\n            paramsKeyMap: {\n                WHAT: 0,\n                HOW: 1,\n                BIT8: 2,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var str = script.getNumberValue('WHAT');\n                var how = script.getNumberValue('HOW');\n                var str_bit8 = script.getStringValue('BIT8', script);\n\n                var charset = '1#*';\n                var pos = -1;\n                var str3 = '';\n                //8개 값\n                for (var i = 0; i < 8; i++) {\n                    pos = -1;\n                    if (i < str_bit8.length) pos = charset.indexOf(str_bit8[i]);\n                    if (pos < 0) str3 = str3.concat('0');\n                    else str3 = str3.concat('1');\n                }\n\n                var port = Entry.FunBoard.EventTypes.SET_ROW1;\n                if (how == '2') port = Entry.FunBoard.EventTypes.SET_COL1;\n\n                if (!script.isStart) {\n                    var text = [];\n                    text[0] = str;\n                    text[1] = Entry.FunBoard.toByte(str3[0]);\n                    text[2] = Entry.FunBoard.toByte(str3[1]);\n                    text[3] = Entry.FunBoard.toByte(str3[2]);\n                    text[4] = Entry.FunBoard.toByte(str3[3]);\n                    text[5] = Entry.FunBoard.toByte(str3[4]);\n                    text[6] = Entry.FunBoard.toByte(str3[5]);\n                    text[7] = Entry.FunBoard.toByte(str3[6]);\n                    text[8] = Entry.FunBoard.toByte(str3[7]);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    //timeValue = 60/fps*timeValue*1000;\n                    timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        value: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        funboard_dotmatrix_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_ledx.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'funboard_list_matrix_rows',\n                    },\n                    {\n                        type: 'funboard_list_matrix_rows',\n                    },\n                    {\n                        type: 'funboard_list_onoff_basic',\n                    },\n                    null,\n                ],\n                type: 'funboard_dotmatrix_set',\n            },\n            paramsKeyMap: {\n                ROW: 0,\n                COL: 1,\n                ONOFF: 2,\n            },\n            class: 'funboardsetmatrix',\n            isNotFor: ['funboard'],\n            func: function(sprite, script) {\n                var str_row = script.getNumberValue('ROW');\n                var str_col = script.getNumberValue('COL');\n                var str_onoff = script.getValue('ONOFF');\n\n                var port = Entry.FunBoard.EventTypes.SET_ROW_COL;\n\n                if (!script.isStart) {\n                    var text = [];\n                    text[0] = str_row;\n                    text[1] = str_col;\n                    text[2] = str_onoff;\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = Entry.FunBoard.Static.DELAY_SECOND;\n                    //timeValue = 60/fps*timeValue*1000;\n                    timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.FunBoard.sensorTypes.MATRIX,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        value: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        //endregion FunBoard\n    };\n};\n\nmodule.exports = Entry.FunBoard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_gbot.js",
    "content": "'use strict';\n\nEntry.GBot = {\n    id: '49.1',\n    name: 'GBot',\n    url: 'https://www.gbot123.com/',\n    imageName: 'Gbot.png',\n    title: {\n        ko: 'G.Bot',\n        en: 'G.Bot',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n\t\tLED_INIT: 9,\n        LED_BRIGHT: 10,\n        LED_ONOFF: 11,\n        LED_OUTPUT: 12,\n        LED_OFF: 13,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    duration: {\n        TIME_1ms: 1,\n        TIME_5ms: 5,\n        TIME_10ms: 10,\n        TIME_20ms: 20,\n        TIME_50ms: 50,\n\t\tTIME_70ms: 70,\n        TIME_100ms: 100,\n        TIME_200ms: 200, \n        TIME_500ms: 500,    \n        TIME_600ms: 600,   \n    },\n    toByte: function(data) {\n        if (data == '0') {\n            data = 48;\n        } else if (data == '1') {\n            data = 49;\n        }\n        return data;\n    },\n\n    BlockState: {},\n};\n\nEntry.GBot.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                g_bot_get_analog_value: '아날로그 %1 번 센서값',\n                g_bot_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                g_bot_get_ultrasonic_value: '초음파 센서 Trig %1 Echo %2 센서값',\n                g_bot_toggle_led: '디지털 %1 번 핀 %2 %3',\n                g_bot_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                g_bot_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                g_bot_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                g_bot_get_digital: '디지털 %1 번 센서값',\n\t\t\t\tg_bot_set_led_init: '디지털 DIN 10, CS 11, CLK 12 핀으로 설정하기',\n\t\t\t\tg_bot_set_brightness: '밝기를 %1 (으)로 정하기',\n                g_bot_get_brightness: '%1',\n                g_bot_get_led_row: '%1',\n                g_bot_get_led_col: '%1',\n\t\t\t\tg_bot_led_onoff: '%1 행 - %2 열의 LED %3',\n\t\t\t\tg_bot_led_output: '%1 %2 에 %3 출력하기',\n\t\t\t\tg_bot_led_off_all: 'LED 모두 끄기',\n            },\n        },\n        en: {\n            template: {\n                g_bot_get_analog_value: 'Analog %1 Sensor value',\n                g_bot_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                g_bot_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                g_bot_toggle_led: 'Digital %1 Pin %2 %3',\n                g_bot_digital_pwm: 'Digital %1 Pin %2 %3',\n                g_bot_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                g_bot_set_servo: 'Set servo pin %1 angle as %2 %3',\n                g_bot_get_digital: 'Digital %1 Sensor value',\n\t\t\t\tg_bot_set_led_init: 'Set Digital DIN 10, CS 11, CLK 12 pin',\n\t\t\t\tg_bot_set_brightness: 'Set brightness as %1',\n                g_bot_get_brightness: '%1',\n                g_bot_get_led_row: '%1',\n                g_bot_get_led_col: '%1',\n\t\t\t\tg_bot_led_onoff: 'Turn on LED in row %1 - col %2',\n\t\t\t\tg_bot_led_output: 'Output %1 %2 %3',\n\t\t\t\tg_bot_led_off_all: 'Turn off all LEDs',\n            },\n        },\n    };\n};\n\nEntry.GBot.blockMenuBlocks = [\n    'g_bot_get_analog_value',\n    'g_bot_get_analog_value_map',\n    'g_bot_get_ultrasonic_value',\n    'g_bot_get_digital',\n    'g_bot_toggle_led',\n    'g_bot_digital_pwm',\n    'g_bot_set_servo',\n    'g_bot_set_tone',\n\t'g_bot_set_led_init',\n\t'g_bot_set_brightness',\n    'g_bot_get_brightness',\n    'g_bot_get_led_row',\n    'g_bot_get_led_col',\n\t'g_bot_led_onoff',\n\t'g_bot_led_output',\n\t'g_bot_led_off_all',\n];\n\nEntry.GBot.getBlocks = function() {\n    return {\n        //region GBot\n        g_bot_analog_list: {\n            parent: 'arduino_ext_analog_list',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                        ['A6', '6'],\n                        ['A7', '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            syntax: undefined,\n        },\n        g_bot_ext_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n            },\n            func(sprite, script) {\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_ext_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_ext_analog_list',\n                    },\n                ],\n            },\n        },\n        g_bot_get_analog_value: {\n            parent: 'arduino_ext_get_analog_value',\n            template: Lang.template.arduino_ext_get_analog_value,\n            def: {\n                params: [\n                    {\n                        type: 'g_bot_analog_list',\n                    },\n                ],\n                type: 'g_bot_get_analog_value',\n            },\n            isNotFor: ['GBot'],\n            syntax: undefined,\n        },\n        g_bot_get_analog_value_map: {\n            parent: 'arduino_ext_get_analog_value_map',\n            template: Lang.template.arduino_ext_get_analog_value_map,\n            def: {\n                params: [\n                    {\n                        type: 'g_bot_get_analog_value',\n                        params: [\n                            {\n                                type: 'g_bot_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'g_bot_get_analog_value_map',\n            },\n            isNotFor: ['GBot'],\n            syntax: undefined,\n        },\n        g_bot_get_ultrasonic_value: {\n            template: Lang.template.arduino_ext_get_ultrasonic_value,\n            parent: 'arduino_ext_get_ultrasonic_value',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'g_bot_get_ultrasonic_value',\n            },\n            isNotFor: ['GBot'],\n            syntax: undefined,\n        },\n        g_bot_get_digital: {\n            template: Lang.template.arduino_ext_get_digital,\n            parent: 'arduino_ext_get_digital',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'g_bot_get_digital',\n            },\n            isNotFor: ['GBot'],\n            syntax: undefined,\n        },\n        g_bot_toggle_led: {\n            template: Lang.template.arduino_ext_toggle_led,\n            parent: 'arduino_ext_toggle_led',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'g_bot_toggle_led',\n            },\n            isNotFor: ['GBot'],\n            syntax: undefined,\n        },\n        g_bot_digital_pwm: {\n            template: Lang.template.arduino_ext_digital_pwm,\n            parent: 'arduino_ext_digital_pwm',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'g_bot_digital_pwm',\n            },\n            isNotFor: ['GBot'],\n            syntax: undefined,\n        },\n        g_bot_set_tone: {\n            template: Lang.template.arduino_ext_set_tone,\n            parent: 'arduino_ext_set_tone',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        value: 4,\n                    },\n                    {\n                        type: 'arduino_ext_tone_list',\n                    },\n                    {\n                        type: 'arduino_ext_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'g_bot_set_tone',\n            },\n            isNotFor: ['GBot'],\n            syntax: undefined,\n        },\n        g_bot_set_servo: {\n            template: Lang.template.arduino_ext_set_servo,\n            parent: 'arduino_ext_set_servo',\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    null,\n                ],\n                type: 'g_bot_set_servo',\n            },\n            isNotFor: ['GBot'],\n            syntax: undefined,\n        },\n        // GBot\n        g_bot_set_led_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['12'],\n                    },\n                    null,\n                ],\n                type: 'g_bot_set_led_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n            },\n            class: 'GBotLED',\n            isNotFor: ['GBot'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port1 = script.getNumberValue('PORT1', script)\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                if (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.GBot.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET['14'] = {\n\t\t\t\t\t\t\ttype: Entry.GBot.sensorTypes.LED_INIT,\n\t\t\t\t\t\t\tdata: {\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                            },\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        \n                    },\n                ],\n            },\n        },\n        g_bot_get_brightness: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n\t\t\t\t\t\t['2', '2'],\n                        ['3', '3'],\n\t\t\t\t\t\t['4', '4'],\n                        ['5', '5'],\n\t\t\t\t\t\t['6', '6'],\n                        ['7', '7'],\n\t\t\t\t\t\t['8', '8'],\n                        ['9', '9'],\n\t\t\t\t\t\t['10', '10'],\n                        ['11', '11'],\n\t\t\t\t\t\t['12', '12'],\n                        ['13', '13'],\n\t\t\t\t\t\t['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                BRIGHT: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('BRIGHT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n\t\t\t\t\t\t\t\t\t['1', '1'],\n\t\t\t\t\t\t\t\t\t['2', '2'],\n\t\t\t\t\t\t\t\t\t['3', '3'],\n\t\t\t\t\t\t\t\t\t['4', '4'],\n\t\t\t\t\t\t\t\t\t['5', '5'],\n\t\t\t\t\t\t\t\t\t['6', '6'],\n\t\t\t\t\t\t\t\t\t['7', '7'],\n\t\t\t\t\t\t\t\t\t['8', '8'],\n\t\t\t\t\t\t\t\t\t['9', '9'],\n\t\t\t\t\t\t\t\t\t['10', '10'],\n\t\t\t\t\t\t\t\t\t['11', '11'],\n\t\t\t\t\t\t\t\t\t['12', '12'],\n\t\t\t\t\t\t\t\t\t['13', '13'],\n\t\t\t\t\t\t\t\t\t['14', '14'],\n\t\t\t\t\t\t\t\t\t['15', '15'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'g_bot_get_brightness',\n                    },\n                ],\n            },\n        },\n        g_bot_get_led_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n\t\t\t\t\t\t['2', '2'],\n                        ['3', '3'],\n\t\t\t\t\t\t['4', '4'],\n                        ['5', '5'],\n\t\t\t\t\t\t['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n\t\t\t\t\t\t            ['2', '2'],\n                                    ['3', '3'],\n\t\t\t\t\t\t            ['4', '4'],\n                                    ['5', '5'],\n\t\t\t\t\t\t            ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'g_bot_get_led_row',\n                    },\n                ],\n            },\n        },\n        g_bot_get_led_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n\t\t\t\t\t\t['2', '2'],\n                        ['3', '3'],\n\t\t\t\t\t\t['4', '4'],\n                        ['5', '5'],\n\t\t\t\t\t\t['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COL: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('COL');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n\t\t\t\t\t\t\t\t\t['1', '1'],\n\t\t\t\t\t\t\t\t\t['2', '2'],\n\t\t\t\t\t\t\t\t\t['3', '3'],\n\t\t\t\t\t\t\t\t\t['4', '4'],\n\t\t\t\t\t\t\t\t\t['5', '5'],\n\t\t\t\t\t\t\t\t\t['6', '6'],\n\t\t\t\t\t\t\t\t\t['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'g_bot_get_led_col',\n                    },\n                ],\n            },\n        },\n        g_bot_set_brightness: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'g_bot_get_brightness',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'g_bot_set_brightness',\n            },\n            paramsKeyMap: {\n                LEVEL: 0,\n            },\n            class: 'GBotLED',\n            isNotFor: ['GBot'],\n            func(sprite, script) {\n                var level = script.getNumberValue('LEVEL', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET['15'] = {\n                    type: Entry.GBot.sensorTypes.LED_BRIGHT,\n                    data: level,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        \n                    },\n                ],\n            },\n        },\n        g_bot_get_row_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.table_row, 'row'], [Lang.Blocks.table_col, 'column']],\n                    value: 'row',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.table_row, 'row'],\n                                    [Lang.Blocks.table_row, 'column'],\n                                ],\n                                value: 'row',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Arduino.g_bot_get_row_col[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'g_bot_get_row_col',\n                    },\n                ],\n            },\n        },\n        g_bot_led_onoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'g_bot_get_led_row',\n                        params: [0],\n                    },\n                    {\n                        type: 'g_bot_get_led_col',\n                        params: [0],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'g_bot_led_onoff',\n            },\n            paramsKeyMap: {\n                ROW: 0,\n                COL: 1,\n                OPERATOR: 2,\n            },\n            class: 'GBotLED',\n            isNotFor: ['GBot'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var row = script.getNumberValue('ROW');\n                var col = script.getNumberValue('COL');\n                var operator = script.getField('OPERATOR');\n                let onoff = operator == 'on' ? 255 : 0;\n\n                if (!script.isStart) \n                {\t\t\t\t\t\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.GBot.duration.TIME_70ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET['16'] = {\n\t\t\t\t\t\t\ttype: Entry.GBot.sensorTypes.LED_ONOFF,\n\t\t\t\t\t\t\tdata: {\n                                row: row,\n\t\t\t\t\t\t\t\tcol: col,\n\t\t\t\t\t\t\t\tonoff: onoff,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        \n                    },\n                ],\n            },\n        },\n        g_bot_led_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.table_row, 'row'], [Lang.Blocks.table_col, 'column']],\n                    value: 'row',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'g_bot_get_led_row',\n                        params: [0],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['11111111'],\n                    },\n                    null,\n                ],\n                type: 'g_bot_led_output',\n            },\n            paramsKeyMap: {\n                ROW: 0,\n                OPERATOR: 1,\n                STRING: 2,\n            },\n            class: 'GBotLED',\n            isNotFor: ['GBot'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var row = script.getNumberValue('ROW', script);\n                var operator = script.getField('OPERATOR', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n\n                if (!script.isStart) \n                {\n\t\t\t\t\tif (typeof string === 'string') \n                    {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = Entry.GBot.toByte(string[i]);\n                        }\n                    }\n                    else if (typeof string === 'number') \n                    {\n                        var num_to_string = string.toString();\n                        for (var i = 0; i < num_to_string.length; i++) {\n                            text[i] = Entry.GBot.toByte(num_to_string[i]);\n                        }\n                    } \n                    else \n                    {\n                        text[0] = string;\n                    }\n\n                    if (operator === 'row')\n                    {\n                        operator = 0;\n                    }\n                    else if (operator === 'column')\n                    {\n                        operator = 1;\n                    }\n\t\t\t\t\t\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.GBot.duration.TIME_70ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET['17'] = {\n\t\t\t\t\t\t\ttype: Entry.GBot.sensorTypes.LED_OUTPUT,\n\t\t\t\t\t\t\tdata: {\n                                row_col: row,\n\t\t\t\t\t\t\t\tsel: operator,\n\t\t\t\t\t\t\t\ttext0: text[0],\n\t\t\t\t\t\t\t\ttext1: text[1],\n\t\t\t\t\t\t\t\ttext2: text[2],\n\t\t\t\t\t\t\t\ttext3: text[3],\n\t\t\t\t\t\t\t\ttext4: text[4],\n\t\t\t\t\t\t\t\ttext5: text[5],\n\t\t\t\t\t\t\t\ttext6: text[6],\n\t\t\t\t\t\t\t\ttext7: text[7],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        \n                    },\n                ],\n            },\n        },\n        g_bot_led_off_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tparams: ['18'],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tparams: ['1'],\n\t\t\t\t\t},\n\t\t\t\t\tnull,\n                ],\n                type: 'g_bot_led_off_all',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tPORT1: 1,\n            },\n            class: 'GBotLED',\n            isNotFor: ['GBot'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\t\t\t\tvar port1 = script.getNumberValue('PORT1', script);\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.GBot.duration.TIME_70ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET[port] = {\n\t\t\t\t\t\t\ttype: Entry.GBot.sensorTypes.LED_OFF,\n\t\t\t\t\t\t\tdata: port1,\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n        //endregion GBot\n    };\n};\n\nmodule.exports = Entry.GBot;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_genirobot.js",
    "content": "'use strict';\nlet ack = 1 ;\nlet count =0;\nlet lastData = [];\nlet first = false;\nlet music ={\n    tempo: 100,\n}\n\nconst distanceError = (2 * 1000 * 0.81) / (3.141592 * 3.2 * 1.25);\n// this.runtime = runtime;\nconst STEPPER_RATE = {\n    SLOW: 900,\n    NORMAL: 950,\n    FAST: 1000,\n};\n\nconst motion = {\n    stepRate: STEPPER_RATE.NORMAL,\n    distanceMultiplier: distanceError,\n    angleMultiplier: (distanceError * 3.141592 * 5.0 * 1.01 / 360),\n};\n\nfunction countNoteLength(noteId) {\n    const noteBPM = [240, 120, 180, 60, 90, 30, 45, 15]; // Beat per miniutes\n    return noteBPM[noteId] ? (noteBPM[noteId] / music.tempo) : 2.4; // Duration in seconds\n}\n\nfunction arraysEqual(a, b) {\n    if (a === b) return true;\n    if (a == null || b == null) return false;\n    if (a.length !== b.length) return false;\n\n    // If you don't care about the order of the elements inside\n    // the array, you should sort both arrays here.\n    // Please note that calling sort on an array will modify that array.\n    // you might want to clone your array first.\n\n    for (var i = 0; i < a.length; ++i) {\n        if (a[i] !== b[i]) return false;\n    }\n    return true;\n}\n\nfunction getDistanceStepTime(distance){\n    let step = (distance * motion.distanceMultiplier / (Math.abs(motion.stepRate) / (Math.abs(motion.stepRate) * -0.01 + 11)))  * 1000;\n    return step;\n}\n\nfunction getAngleStepTime(angle){\n    let stepTime = (angle * motion.angleMultiplier / (Math.abs(motion.stepRate) / (Math.abs(motion.stepRate) * -0.01 + 11)))  * 1000;\n    return stepTime;\n}\n\nEntry.GENIBOT = {\n    id: '44.1',\n    name: 'genibot',\n    url: 'https://genirobot.com',\n    imageName: 'genibot.png',\n    title: {\n        ko: '지니봇',\n        en: 'Genibot',\n    },\n    eventState: {\n        'BUTTON': false,\n    },\n    postDelayBlockHandler(script, myfunc) {\n        if (myfunc == undefined) {\n            return script.callReturn();\n        }\n        \n        if (script.is_start == undefined) {\n            script.is_start = true;\n            const waitTime = myfunc();\n            let today = new Date(); \n            let hours = today.getHours(); // 시\n            let minutes = today.getMinutes();  // 분\n            let seconds = today.getSeconds();  // 초\n            let milliseconds = today.getMilliseconds();\n\n            setTimeout(() => {\n                script.is_start = false;\n                let today = new Date();   \n    \n                let hours = today.getHours(); // 시\n                let minutes = today.getMinutes();  // 분\n                let seconds = today.getSeconds();  // 초\n                let milliseconds = today.getMilliseconds();\n            }, waitTime);\n    \n            return script;\n        } else if (script.is_start == true) {\n            return script;\n        } else {\n            delete script.is_start;\n    \n            return script.callReturn();\n        }\n    },setZero() {\n\n    },\n    afterReceive: async function(pd) {\n        if(pd['log']){\n            const a = pd['log'];\n            if(!arraysEqual(a.data,lastData)){\n                lastData = a.data;\n            }\n\n        }\n        if (pd['BUTTON']) {\n            Entry.engine.fireEvent('buttonPressed');\n        }\n        if(pd['LOGGER'] && pd['LOGGER'].list.length > 0){\n            console.log(\"pd['LOGGER']\",pd['LOGGER']);\n        }\n    },\n};\nconst ko = {\n    'genibot.speed': '속력을 %1 (으)로 정하기',\n    'genibot.moveDistance': '%1 (으)로 %2cm 가기 %3', // \"[DIRECTION] (으)로 [DISTANCE]cm 가기\"\n    'genibot.turnAngle': '%1 으로 %2도 돌기 %3', // \"[DIRECTION] 으로 [ANGLE]도 돌기\",\n    'genibot.motionGoDistance': '%1 속도로 %2cm 가기 %3', //\"[VELOCITY] 속도로 [DISTANCE]cm 가기\",\n    'genibot.motionRotateAngle': '%1 속도로 %2도 돌기 %3', // \"[VELOCITY] 속도로 [ANGLE]도 돌기\",\n    'genibot.startMoving': '왼쪽: %1 오른쪽: %2 속도로 움직이기 %3',//\"왼쪽: [VELOCITY1] 오른쪽: [VELOCITY2] 속도로 움직이기\"\n    'genibot.stopMoving': '멈추기 %1',\n    'genibot.move.forward': '앞',\n    'genibot.move.backward': '뒤',\n    'genibot.rotate.left': '왼쪽',\n    'genibot.rotate.right': '오른쪽',\n    'genibot.ledColor': '%1 LED 색을 %2 로 나타내기',\n    'genibot.ledColorName': '%1 LED 색을 색상: %2 밝기: %3 (으)로 나타내기 %4', //\"[LED] LED 색을 색상: [COLOR_NAME] 밝기: [COLOR_BRIGHTNESS] (으)로 나타내기\",\n    'genibot.ledColor.left': '왼쪽',\n    'genibot.ledColor.right': '오른쪽',\n    'genibot.ledColor.front': '앞쪽',\n    'genibot.ledColor.back': '뒤쪽',\n    'genibot.ledColor.all': '모든',\n    'genibot.ledColorName.white': '하양',\n    'genibot.ledColorName.red': '빨강',\n    'genibot.ledColorName.green': '초록',\n    'genibot.ledColorName.blue': '파랑',\n    'genibot.ledColorName.cyan': '연파랑',\n    'genibot.ledColorName.magenta': '분홍',\n    'genibot.ledColorName.yellow': '노랑',\n    'genibot.ledColorName.violet': '보라',\n    'genibot.ledColorName.orange': '오렌지',\n    'genibot.ledColorName.springgreen': '연두',\n    'genibot.ledColorName.lightpink': '연분홍',\n    'genibot.lineFollower': '라인트레이싱 %1 %2', //[ACTION]\n    'genibot.lineFollower.start': '시작하기',\n    'genibot.lineFollower.stop': '멈추기',\n    'genibot.setInstrument': '악기를 %1 (으)로 정하기',\n    'genibot.setTempo': '빠르기를 %1 (으)로 정하기',\n    'genibot.playNote': '%1 %2 소리내기',\n    'genibot.playNoteKey': '%1 %2 소리내기',\n    'genibot.setSpeakerVolume': '소리 세기를 %1 (으)로 정하기 %2', // [VOLUME]\n    'genibot.acceleration': '가속도 %1 축',\n    'genibot.tiltAngle': '기울기',\n    'genibot.oidCode': 'OID 코드',\n    'genibot.getButtonPressed': '%1 버튼을 눌렀을 때',\n    'genibot.steppersSpeed.slow': '느리게',\n    'genibot.steppersSpeed.normal': '보통',\n    'genibot.steppersSpeed.fast': '빠르게',\n    'genibot.instrument.piano': '피아노',\n    'genibot.instrument.flute': '플룻',\n    'genibot.instrument.string': '기타',\n    'genibot.instrument.note.lowTi': '시 (B3)',\n    'genibot.instrument.note.do': '도 (C4)',\n    'genibot.instrument.note.doSharp': '도#',\n    'genibot.instrument.note.re': '레',\n    'genibot.instrument.note.reSharp': '레#',\n    'genibot.instrument.note.mi': '미',\n    'genibot.instrument.note.fa': '파',\n    'genibot.instrument.note.faSharp': '파#',\n    'genibot.instrument.note.sol': '솔',\n    'genibot.instrument.note.solSharp': '솔#',\n    'genibot.instrument.note.la': '라',\n    'genibot.instrument.note.laSharp': '라#',\n    'genibot.instrument.note.ti': '시',\n    'genibot.instrument.note.highDo': '도 (C5)',\n    'genibot.instrument.note.highDoSharp': '도# (C#5)',\n    'genibot.instrument.note.highRe': '레 (D5)',\n    'genibot.instrument.note.highReSharp': '레# (D#5)',\n    'genibot.instrument.note.highMi': '미 (E5)',\n    'genibot.instrument.note.highFa': '파 (F5)',\n    'genibot.instrument.beat.whole': '온음표',\n    'genibot.instrument.beat.half': '2분음표',\n    'genibot.instrument.beat.dottedHalf': '점2분음표',\n    'genibot.instrument.beat.quarter': '4분음표',\n    'genibot.instrument.beat.dottedQuarter': '점4분음표',\n    'genibot.instrument.beat.eight': '8분음표',\n    'genibot.instrument.beat.dottedEight': '점8분음표',\n    'genibot.instrument.beat.sixteenth': '16분음표',\n};\nconst en = {\n    'genibot.speed': 'set speed %1',\n    'genibot.moveDistance': 'move [DIRECTION] [DISTANCE]cm',\n    'genibot.turnAngle': 'turn [DIRECTION] [ANGLE]degrees',\n    'genibot.motionGoDistance': 'go [DISTANCE]cm at velocity of [VELOCITY]',\n    'genibot.motionRotateAngle': 'rotate [ANGLE]degrees at velocity of [VELOCITY]',\n    'genibot.startMoving': 'start moving at velocity of left: [VELOCITY1] right: [VELOCITY2]',\n    'genibot.stopMoving': 'stop moving',\n    'genibot.move.forward': 'front',\n    'genibot.move.backward': 'back',\n    'genibot.rotate.left': 'left',\n    'genibot.rotate.right': 'right',\n    'genibot.ledColor': 'set %1 led color to %2',\n    'genibot.ledColorName': 'set [LED] led color to hue: [COLOR_NAME] brightness: [COLOR_BRIGHTNESS]',\n    'genibot.ledColor.left': 'left',\n    'genibot.ledColor.right': 'right',\n    'genibot.ledColor.front': 'front',\n    'genibot.ledColor.back': 'back',\n    'genibot.ledColor.all': 'all',\n    'genibot.ledColorName.white': 'white',\n    'genibot.ledColorName.red': 'red',\n    'genibot.ledColorName.green': 'green',\n    'genibot.ledColorName.blue': 'blue',\n    'genibot.ledColorName.cyan': 'cyan',\n    'genibot.ledColorName.magenta': 'magenta',\n    'genibot.ledColorName.yellow': 'yellow',\n    'genibot.ledColorName.violet': 'violet',\n    'genibot.ledColorName.orange': 'orange',\n    'genibot.ledColorName.springgreen': 'spring green',\n    'genibot.ledColorName.lightpink': 'light pink',\n    'genibot.lineFollower': '[ACTION] line follower',\n    'genibot.lineFollower.start': 'start',\n    'genibot.lineFollower.stop': 'stop',\n    'genibot.setInstrument': 'set instrument to [INSTRUMENT]',\n    'genibot.setTempo': 'set tempo to [TEMPO]',\n    'genibot.playNote': 'play %1 note %2',//'play [BEATS] note [NOTE]',\n    'genibot.playNoteKey': 'play %1 note %2', // \"play [BEATS] note [NOTE]\"\n    'genibot.setSpeakerVolume': 'set speaker volume to [VOLUME]',\n    'genibot.acceleration': 'acceleration of %1 axis',\n    'genibot.tiltAngle': 'tilt angle',\n    'genibot.oidCode': 'oid code',\n    'genibot.getButtonPressed': 'when button pressed',\n    'genibot.steppersSpeed.slow': 'slow',\n    'genibot.steppersSpeed.normal': 'normal',\n    'genibot.steppersSpeed.fast': 'fast',\n    'genibot.instrument.piano': 'piano',\n    'genibot.instrument.flute': 'flute',\n    'genibot.instrument.string': 'string',\n    'genibot.instrument.note.lowTi': 'Ti (B3)',\n    'genibot.instrument.note.do': 'Do (C4)',\n    'genibot.instrument.note.doSharp': 'DO#',\n    'genibot.instrument.note.re': 'Re',\n    'genibot.instrument.note.reSharp': 'Re#',\n    'genibot.instrument.note.mi': 'Mi',\n    'genibot.instrument.note.fa': 'Fa',\n    'genibot.instrument.note.faSharp': 'Fa#',\n    'genibot.instrument.note.sol': 'Sol',\n    'genibot.instrument.note.solSharp': 'Sol#',\n    'genibot.instrument.note.la': 'La',\n    'genibot.instrument.note.laSharp': 'La#',\n    'genibot.instrument.note.ti': 'Ti',\n    'genibot.instrument.note.highDo': 'Do (C5)',\n    'genibot.instrument.note.highDoSharp': 'DO# (C#5)',\n    'genibot.instrument.note.highRe': 'Re (D5)',\n    'genibot.instrument.note.highReSharp': 'Re# (D#5)',\n    'genibot.instrument.note.highMi': 'Mi (E5)',\n    'genibot.instrument.note.highFa': 'Fa (F5)',\n\n    'genibot.instrument.note.code.lowTi': 'lowTi',\n    'genibot.instrument.note.code.do': 'do',\n    'genibot.instrument.note.code.doSharp': 'doSharp',\n    'genibot.instrument.note.code.re': 're',\n    'genibot.instrument.note.code.reSharp': 'reSharp',\n    'genibot.instrument.note.code.mi': 'mi',\n    'genibot.instrument.note.code.fa': 'fa',\n    'genibot.instrument.note.code.faSharp': 'faSharp',\n    'genibot.instrument.note.code.sol': 'sol',\n    'genibot.instrument.note.code.solSharp': 'solSharp',\n    'genibot.instrument.note.code.la': 'la',\n    'genibot.instrument.note.code.laSharp': 'laSharp',\n    'genibot.instrument.note.code.ti': 'ti',\n    'genibot.instrument.note.code.highDo': 'highDo',\n    'genibot.instrument.note.code.highDoSharp': 'highDoSharp',\n    'genibot.instrument.note.code.highRe': 'highRe',\n    'genibot.instrument.note.code.highReSharp': 'highReSharp',\n    'genibot.instrument.note.code.highMi': 'highMi',\n    'genibot.instrument.note.code.highFa': 'highFa',\n    'genibot.instrument.beat.whole': 'whole',\n    'genibot.instrument.beat.half': 'half',\n    'genibot.instrument.beat.dottedHalf': 'dottedHalf',\n    'genibot.instrument.beat.quarter': 'quarter',\n    'genibot.instrument.beat.dottedQuarter': 'dottedQuarter',\n    'genibot.instrument.beat.eight': 'eight',\n    'genibot.instrument.beat.dottedEight': 'dottedEight',\n    'genibot.instrument.beat.sixteenth': 'sixteenth',\n};\nEntry.GENIBOT.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                getButtonPressed: ko['genibot.getButtonPressed'],\n                setRobotSpeedItem: ko['genibot.speed'],\n                moveDistance: ko['genibot.moveDistance'],\n                turnAngle: ko['genibot.turnAngle'],\n                startMoving: ko['genibot.startMoving'],\n                stopMoving: ko['genibot.stopMoving'],\n                motionGoDistance: ko['genibot.motionGoDistance'],\n                motionRotateAngle: ko['genibot.motionRotateAngle'],\n                startLineFollower: ko['genibot.lineFollower'],\n                setLedColor: ko['genibot.ledColor'],\n                setLedColorName: ko['genibot.ledColorName'],\n                setSpeakerVolume: ko['genibot.setSpeakerVolume'],\n                setTempo: ko['genibot.setTempo'],\n                setInstrument: ko['genibot.setInstrument'],\n                playNote: ko['genibot.playNote'],\n                playNoteKey: ko['genibot.playNoteKey'],\n                getAcceleration: ko['genibot.acceleration'],\n                getTilt: ko['genibot.tiltAngle'],\n                getOidCode: ko['genibot.oidCode'],\n            },\n        },\n        en: {\n            template: {\n                getButtonPressed: en['genibot.getButtonPressed'],\n                setRobotSpeedItem: en['genibot.speed'],\n                moveDistance: en['genibot.moveDistance'],\n                turnAngle: en['genibot.turnAngle'],\n                startMoving: en['genibot.startMoving'],\n                stopMoving: en['genibot.stopMoving'],\n                motionGoDistance: en['genibot.motionGoDistance'],\n                motionRotateAngle: en['genibot.motionRotateAngle'],\n                startLineFollower: en['genibot.lineFollower'],\n                setLedColor: en['genibot.ledColor'],\n                setLedColorName: en['genibot.ledColorName'],\n                setSpeakerVolume: en['genibot.setSpeakerVolume'],\n                setTempo: en['genibot.setTempo'],\n                setInstrument: en['genibot.setInstrument'],\n                playNote: en['genibot.playNote'],\n                playNoteKey: en['genibot.playNoteKey'],\n                getAcceleration: en['genibot.acceleration'],\n                getTilt: en['genibot.tiltAngle'],\n                getOidCode: en['genibot.oidCode'],\n            },\n        },\n    };\n};\n\nEntry.GENIBOT.blockMenuBlocks = [\n    'getButtonPressed',\n    'setRobotSpeedItem',\n    'moveDistance',\n    'turnAngle',\n    'startMoving',\n    'stopMoving',\n    'motionGoDistance',\n    'motionRotateAngle',\n    'startLineFollower',\n    'setLedColor',\n    'setLedColorName',\n    'setSpeakerVolume',\n    'setTempo',\n    'setInstrument',\n    'playNote',\n    'playNoteKey',\n    'getAcceleration',\n    'getTilt',\n    'getOidCode',\n];\n\n\n\nEntry.GENIBOT.getBlocks = function() {\n    return {\n        //region arduino 아두이노\n        getButtonPressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            // skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/genibot_icon.png',\n                    size: 14,\n                    position: {\n                        x: 0,\n                        y: -2,\n                    },\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'getButtonPressed',\n            },\n            paramsKeyMap: {},\n            class: 'geni_input',\n            isNotFor: ['genibot'],\n            func(sprite, script) {\n                var portData = Entry.hw.portData['BUTTON'];\n                if (portData) {\n                    portData = '0';\n                    return script.callReturn();\n                } else {\n                    return false;\n                }\n            },\n            event: 'buttonPressed',\n        },\n        setRobotSpeedItem: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.steppersSpeed.slow'], en['genibot.steppersSpeed.slow']],\n                        [ko['genibot.steppersSpeed.normal'], en['genibot.steppersSpeed.normal']],\n                        [ko['genibot.steppersSpeed.fast'], en['genibot.steppersSpeed.fast']],\n                    ],\n                    value: en['genibot.steppersSpeed.normal'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'setRobotSpeedItem',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const speed = script.getStringField('SPEED', script);\n                    if (speed) {\n                        Entry.hw.sendQueue.SET_ROBOT_SPEED_ITEM = {\n                            'SPEED': speed,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    let speedInt = STEPPER_RATE.NORMAL;\n                    switch (speed) {\n                        case 'slow':\n                            speedInt = STEPPER_RATE.SLOW;\n                            break;\n                        case 'normal':\n                            speedInt = STEPPER_RATE.NORMAL;\n                            break;\n                        case 'fast':\n                            speedInt = STEPPER_RATE.FAST;\n                            break;\n                    }\n                    motion.stepRate = speedInt;\n                    return 100;\n                });\n            }\n        },\n        moveDistance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.move.forward'], en['genibot.move.forward']],\n                        [ko['genibot.move.backward'], en['genibot.move.backward']],\n                    ],\n                    value: en['genibot.move.forward'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '6',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'moveDistance',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DISTANCE: 1,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script){\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const direction = script.getStringField('DIRECTION', script);\n                    const distance = script.getStringField('DISTANCE', script);\n                  \n                    if (direction && distance) {\n                        Entry.hw.sendQueue.MOVE_DISTANCE = {\n                            'DIRECTION': direction,\n                            'DISTANCE': distance,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n    \n                    let stepRate =  motion.stepRate;\n                    if (direction == 'front') {\n                        stepRate *= 1;\n                    } else {\n                        stepRate *= -1;\n                    }\n                    const waitTime = getDistanceStepTime(distance);\n                    return waitTime;\n                });\n            }\n        },\n        turnAngle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.rotate.left'], en['genibot.rotate.left']],\n                        [ko['genibot.rotate.right'], en['genibot.rotate.right']],\n                    ],\n                    value: en['genibot.rotate.right'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['180', '180'],\n                        ['120', '120'],\n                        ['90', '90'],\n                        ['60', '60'],\n                        ['45', '45'],\n                        ['30', '30'],\n                        ['15', '15'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'turnAngle',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                ANGLE: 1,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const direction = script.getStringField('DIRECTION', script);\n                    const angle = script.getStringField('ANGLE', script);\n                \n                    if (direction && angle) {\n                        Entry.hw.sendQueue.TURN_ANGLE = {\n                            'DIRECTION': direction,\n                            'ANGLE': angle,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    return getAngleStepTime(angle);\n                });\n            }\n        },\n        startMoving: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['-5', '-5'],\n                        ['-4', '-4'],\n                        ['-3', '-3'],\n                        ['-2', '-2'],\n                        ['-1', '-1'],\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['-5', '-5'],\n                        ['-4', '-4'],\n                        ['-3', '-3'],\n                        ['-2', '-2'],\n                        ['-1', '-1'],\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'startMoving',\n            },\n            paramsKeyMap: {\n                VELOCITY1: 0,\n                VELOCITY2: 1,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const VELOCITY1 = script.getStringField('VELOCITY1', script);\n                    const VELOCITY2 = script.getStringField('VELOCITY2', script);\n                    if (VELOCITY1 && VELOCITY2) {\n                        Entry.hw.sendQueue.START_MOVING = {\n                            'VELOCITY1': VELOCITY1,\n                            'VELOCITY2': VELOCITY2,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    return 100;\n                });\n            }\n        },\n        stopMoving: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'stopMoving',\n            },\n            paramsKeyMap: {},\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    Entry.hw.sendQueue.STOP_MOVING = {\n                        'ACK': ack++,\n                    };\n                    Entry.hw.update();\n                    return 100;\n                });\n            }\n        },\n        motionGoDistance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['-5', '-5'],\n                        ['-4', '-4'],\n                        ['-3', '-3'],\n                        ['-2', '-2'],\n                        ['-1', '-1'],\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null,\n                    {\n                        type: 'number',\n                        params: ['0~30'],\n                    },\n                ],\n                type: 'motionGoDistance',\n            },\n            paramsKeyMap: {\n                VELOCITY: 0,\n                DISTANCE: 1,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n     \n                    const VELOCITY = script.getStringField('VELOCITY', script);\n                    const DISTANCE_ANY = script.getValue('DISTANCE')\n                    const DISTANCE = script.getNumberValue('DISTANCE')//Field('DISTANCE', script);\n\n                    if(isNaN(String(DISTANCE_ANY)) || Number(DISTANCE) < 0 || Number(DISTANCE)>30) {\n                        alert(\"0~30 사이에 값만 입력할수 있습니다.\")\n                        throw \"error\"\n                    }\n                    if (VELOCITY && DISTANCE) {\n                        Entry.hw.sendQueue.MOTION_GO_DISTANCE = {\n                            'VELOCITY': VELOCITY,\n                            'DISTANCE': DISTANCE,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    return getDistanceStepTime(DISTANCE);\n                });\n            },\n        },\n        motionRotateAngle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['-5', '-5'],\n                        ['-4', '-4'],\n                        ['-3', '-3'],\n                        ['-2', '-2'],\n                        ['-1', '-1'],\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null,\n                    {\n                        type: 'number',\n                        params: ['0~360'],\n                    },\n                ],\n                type: 'motionRotateAngle',\n            },\n            paramsKeyMap: {\n                VELOCITY: 0,\n                ANGLE: 1,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n         \n                    const VELOCITY = script.getStringField('VELOCITY', script);\n                    const ANGLE_ANY = script.getValue('ANGLE')\n                    const ANGLE = script.getNumberValue('ANGLE', script);\n\n                    if(isNaN(ANGLE_ANY) || Number(ANGLE) < 0 || Number(ANGLE) > 360){\n                        alert(\"0~360 사이에 값만 입력할수 있습니다.\");\n                        throw 'error'\n                    }\n                    if (VELOCITY && ANGLE) {\n                        Entry.hw.sendQueue.MOTION_ROTATE_ANGLE = {\n                            'VELOCITY': VELOCITY,\n                            'ANGLE': ANGLE,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    return getAngleStepTime(ANGLE);\n                });\n            },\n        },\n        startLineFollower: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.lineFollower.start'], en['genibot.lineFollower.start']],\n                        [ko['genibot.lineFollower.stop'], en['genibot.lineFollower.stop']],\n                    ],\n                    value: en['genibot.lineFollower.start'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'startLineFollower',\n            },\n            paramsKeyMap: {\n                ACTION: 0,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script){\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const ACTION = script.getStringField('ACTION', script);\n                    // const speed = script.getStringField('SPEED',script);\n                    if (ACTION) {\n                        Entry.hw.sendQueue.START_LINE_FOLLOWER = {\n                            'ACTION': ACTION,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    return 100;\n                });\n            },\n        },\n        setLedColor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.ledColor.left'], en['genibot.ledColor.left']],\n                        [ko['genibot.ledColor.right'], en['genibot.ledColor.right']],\n                        [ko['genibot.ledColor.front'], en['genibot.ledColor.front']],\n                        [ko['genibot.ledColor.back'], en['genibot.ledColor.back']],\n                        [ko['genibot.ledColor.all'], en['genibot.ledColor.all']],\n                    ],\n                    value: en['genibot.ledColor.all'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'setLedColor',\n            },\n            paramsKeyMap: {\n                SIDE: 0,\n                COLOR: 1,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const side = script.getStringField('SIDE', script);\n                    let ledId = 0xff;\n                    switch (side) {\n                        case en['genibot.ledColor.left']:\n                            ledId = 0x02;\n                            break;\n                        case en['genibot.ledColor.right']:\n                            ledId = 0x00;\n                            break;\n                        case en['genibot.ledColor.front']:\n                            ledId = 0x03;\n                            break;\n                        case en['genibot.ledColor.back']:\n                            ledId = 0x01;\n                            break;\n                        default:\n                            ledId = 0xff;\n                    }\n                    const color = script.getStringField('COLOR', script);\n                    const rgb = Entry.hex2rgb(color);\n\n                    Entry.hw.sendQueue.SET_LED_COLOR = {\n                        'SIDE': ledId,\n                        'COLOR': [rgb.r, rgb.g, rgb.b],\n                        'ACK': ack++,\n                    };\n                    Entry.hw.update();\n                    return 100;\n                });\n            },\n\n        },\n        setLedColorName: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.ledColor.left'], en['genibot.ledColor.left']],\n                        [ko['genibot.ledColor.right'], en['genibot.ledColor.right']],\n                        [ko['genibot.ledColor.front'], en['genibot.ledColor.front']],\n                        [ko['genibot.ledColor.back'], en['genibot.ledColor.back']],\n                        [ko['genibot.ledColor.all'], en['genibot.ledColor.all']],\n                    ],\n                    value: en['genibot.ledColor.all'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.ledColorName.white'], en['genibot.ledColorName.white']],\n                        [ko['genibot.ledColorName.red'], en['genibot.ledColorName.red']],\n                        [ko['genibot.ledColorName.green'], en['genibot.ledColorName.green']],\n                        [ko['genibot.ledColorName.blue'], en['genibot.ledColorName.blue']],\n                        [ko['genibot.ledColorName.cyan'], en['genibot.ledColorName.cyan']],\n                        [ko['genibot.ledColorName.magenta'], en['genibot.ledColorName.magenta']],\n                        [ko['genibot.ledColorName.yellow'], en['genibot.ledColorName.yellow']],\n                        [ko['genibot.ledColorName.violet'], en['genibot.ledColorName.violet']],\n                        [ko['genibot.ledColorName.orange'], en['genibot.ledColorName.orange']],\n                        [ko['genibot.ledColorName.springgreen'], en['genibot.ledColorName.springgreen']],\n                        [ko['genibot.ledColorName.lightpink'], en['genibot.ledColorName.lightpink']],\n                    ],\n                    value: en['genibot.ledColorName.white'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [['1','1'],\n                        ['2','2'],\n                        ['3','3'],\n                        ['4','4'],\n                        ['5','5'],\n                        ['6','6'],\n                        ['7','7'],\n                        ['8','8'],\n                        ['9','9'],\n                        ['10','10'],\n                        ['11','11'],\n                        ['12','12'],\n                        ['13','13'],\n                        ['14','14'],\n                        ['15','15'],\n                        ['16','16'],\n                        ['17','17'],\n                        ['18','18'],\n                        ['19','19'],\n                        ['20','20'],\n                        ['21','21'],\n                        ['22','22'],\n                        ['23','23'],\n                        ['24','24'],\n                        ['25','25'],\n                        ['26','26'],\n                        ['27','27'],\n                        ['28','28'],\n                        ['29','29'],\n                        ['30','30'],\n                        ['31','31'],\n                        ['32','32'],\n                        ['33','33'],\n                        ['34','34'],\n                        ['35','35'],\n                        ['36','36'],\n                        ['37','37'],\n                        ['38','38'],\n                        ['39','39'],\n                        ['40','40'],\n                        ['41','41'],\n                        ['42','42'],\n                        ['43','43'],\n                        ['44','44'],\n                        ['45','45'],\n                        ['46','46'],\n                        ['47','47'],\n                        ['48','48'],\n                        ['49','49'],\n                        ['50','50'],\n                        ['51','51'],\n                        ['52','52'],\n                        ['53','53'],\n                        ['54','54'],\n                        ['55','55'],\n                        ['56','56'],\n                        ['57','57'],\n                        ['58','58'],\n                        ['59','59'],\n                        ['60','60'],\n                        ['61','61'],\n                        ['62','62'],\n                        ['63','63'],\n                        ['64','64'],\n                        ['65','65'],\n                        ['66','66'],\n                        ['67','67'],\n                        ['68','68'],\n                        ['69','69'],\n                        ['70','70'],\n                        ['71','71'],\n                        ['72','72'],\n                        ['73','73'],\n                        ['74','74'],\n                        ['75','75'],\n                        ['76','76'],\n                        ['77','77'],\n                        ['78','78'],\n                        ['79','79'],\n                        ['80','80'],\n                        ['81','81'],\n                        ['82','82'],\n                        ['83','83'],\n                        ['84','84'],\n                        ['85','85'],\n                        ['86','86'],\n                        ['87','87'],\n                        ['88','88'],\n                        ['89','89'],\n                        ['90','90'],\n                        ['91','91'],\n                        ['92','92'],\n                        ['93','93'],\n                        ['94','94'],\n                        ['95','95'],\n                        ['96','96'],\n                        ['97','97'],\n                        ['98','98'],\n                        ['99','99'],\n                        ['100','100'],\n                    ],\n                    value: '100',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'setLedColorName',\n            },\n            paramsKeyMap: {\n                SIDE: 0,\n                COLOR: 1,\n                COLOR_BRIGHTNESS: 2,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const SIDE = script.getStringField('SIDE', script);\n                    const COLOR = script.getStringField('COLOR', script);\n                    const COLOR_BRIGHTNESS = script.getStringField('COLOR_BRIGHTNESS', script);\n                    \n                    if (SIDE && COLOR && COLOR_BRIGHTNESS) {\n                        \n\n                        Entry.hw.sendQueue.SET_LED_COLOR_NAME = {\n                            'LED': SIDE,\n                            'COLOR_NAME': COLOR,\n                            'COLOR_BRIGHTNESS': Number(COLOR_BRIGHTNESS),\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    return 100;\n                });\n            }\n        },\n        setSpeakerVolume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'setSpeakerVolume',\n            },\n            paramsKeyMap: {\n                VOLUME: 0,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const VOLUME = script.getStringField('VOLUME', script);\n                    if (VOLUME) {\n                        Entry.hw.sendQueue.SET_SPEAKER_VOLUME = {\n                            'VOLUME': VOLUME,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    return 100;\n                });\n            }\n        },\n        setTempo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'setTempo',\n            },\n            paramsKeyMap: {\n                TEMPO: 0,\n            },\n\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const TEMPO = script.getNumberValue('TEMPO', script);\n                    if (TEMPO) {\n                        Entry.hw.sendQueue.SET_TEMPO = {\n                            'TEMPO': TEMPO,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    music.tempo = TEMPO;\n                    return 100;\n                });\n            }\n        },\n        setInstrument: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.instrument.piano'], en['genibot.instrument.piano']],\n                        [ko['genibot.instrument.flute'], en['genibot.instrument.flute']],\n                        [ko['genibot.instrument.string'], en['genibot.instrument.string']],\n                    ],\n                    value: en['genibot.instrument.piano'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'setInstrument',\n            },\n            paramsKeyMap: {\n                INSTRUMENT: 0,\n            },\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const INSTRUMENT = script.getStringField('INSTRUMENT', script);\n                    if (INSTRUMENT) {          \n                        Entry.hw.sendQueue.SET_INSTRUMENT = {\n                            'INSTRUMENT': INSTRUMENT,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n\n                    }\n                    return 100;\n                });\n            }\n\n        },\n        playNote: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.instrument.beat.whole'], en['genibot.instrument.beat.whole']],\n                        [ko['genibot.instrument.beat.half'], en['genibot.instrument.beat.half']],\n                        [ko['genibot.instrument.beat.dottedHalf'], en['genibot.instrument.beat.dottedHalf']],\n                        [ko['genibot.instrument.beat.quarter'], en['genibot.instrument.beat.quarter']],\n                        [ko['genibot.instrument.beat.dottedQuarter'], en['genibot.instrument.beat.dottedQuarter']],\n                        [ko['genibot.instrument.beat.eight'], en['genibot.instrument.beat.eight']],\n                        [ko['genibot.instrument.beat.dottedEight'], en['genibot.instrument.beat.dottedEight']],\n                        [ko['genibot.instrument.beat.sixteenth'], en['genibot.instrument.beat.sixteenth']],\n                    ],\n                    value: en['genibot.instrument.beat.whole'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }, {\n                    type: 'Dropdown',\n                    options: [\n                        [ko['genibot.instrument.note.lowTi'], en['genibot.instrument.note.code.lowTi']],\n                        [ko['genibot.instrument.note.do'], en['genibot.instrument.note.code.do']],\n                        [ko['genibot.instrument.note.doSharp'], en['genibot.instrument.note.code.doSharp']],\n                        [ko['genibot.instrument.note.re'], en['genibot.instrument.note.code.re']],\n                        [ko['genibot.instrument.note.reSharp'], en['genibot.instrument.note.code.reSharp']],\n                        [ko['genibot.instrument.note.mi'], en['genibot.instrument.note.code.mi']],\n                        [ko['genibot.instrument.note.fa'], en['genibot.instrument.note.code.fa']],\n                        [ko['genibot.instrument.note.faSharp'], en['genibot.instrument.note.code.faSharp']],\n                        [ko['genibot.instrument.note.sol'], en['genibot.instrument.note.code.sol']],\n                        [ko['genibot.instrument.note.solSharp'], en['genibot.instrument.note.code.solSharp']],\n                        [ko['genibot.instrument.note.la'], en['genibot.instrument.note.code.la']],\n                        [ko['genibot.instrument.note.laSharp'], en['genibot.instrument.note.code.laSharp']],\n                        [ko['genibot.instrument.note.ti'], en['genibot.instrument.note.code.ti']],\n                        [ko['genibot.instrument.note.highDo'], en['genibot.instrument.note.code.highDo']],\n                        [ko['genibot.instrument.note.highDoSharp'], en['genibot.instrument.note.code.highDoSharp']],\n                        [ko['genibot.instrument.note.highRe'], en['genibot.instrument.note.code.highRe']],\n                        [ko['genibot.instrument.note.highReSharp'], en['genibot.instrument.note.code.highReSharp']],\n                        [ko['genibot.instrument.note.highMi'], en['genibot.instrument.note.code.highMi']],\n                        [ko['genibot.instrument.note.highFa'], en['genibot.instrument.note.code.highFa']],\n                    ],\n                    value: en['genibot.instrument.note.code.lowTi'],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null, null,\n                ],\n                type: 'playNote',\n            },\n            paramsKeyMap: {\n                BEATS: 0,\n                NOTE: 1,\n            },\n            class: 'geni_output',\n            isNotFor:['genibot'],\n            func(sprite, script) {\n                return Entry.GENIBOT.postDelayBlockHandler(script, () => {\n                    const BEATS = script.getStringField('BEATS', script);\n                    const NOTE = script.getStringField('NOTE', script);\n                    const noteLabel = ['whole', 'half', 'dottedHalf', 'quarter', 'dottedQuarter', 'eight', 'dottedEight', 'sixteenth'];\n                    const noteId = noteLabel.findIndex(element => element === BEATS);\n\n                    if (BEATS && NOTE) {\n                        Entry.hw.sendQueue.PLAY_NOTE = {\n                            'BEATS': BEATS,\n                            'NOTE': NOTE,\n                            'ACK': ack++,\n                        };\n                        Entry.hw.update();\n                    }\n                    return (countNoteLength(noteId) * 1000)+100;\n                });\n            }\n        },\n        getAcceleration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['x', 'x'], ['y', 'y'], ['z', 'z']],\n                    value: 'x',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'getAcceleration',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'geni_input',\n            isNotFor: ['genibot'],\n            func(sprite, script){\n                let port = script.getStringField('PORT');\n                const ACC_TILT = Entry.hw.getDigitalPortValue('ACC_TILT');\n                const value = ACC_TILT['a' + port.toUpperCase()];\n\n                return value || 0;\n            },\n        },\n        getTilt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'getTilt',\n            },\n            paramsKeyMap: {},\n            class: 'geni_input',\n            isNotFor: ['genibot'],\n            func: function(sprite, script) {\n                const ACC_TILT = Entry.hw.getDigitalPortValue('ACC_TILT');\n                const tilt = ACC_TILT['tilt'];\n                const tiltStatusKo = {'3':'위', '-3':'아래', '1':'오른쪽', '-1':'왼쪽', '2':'앞', '-2':'뒤'};\n                \n                return tiltStatusKo[tilt] || \"0\";\n            },\n        },\n        getOidCode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {},\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'getOidCode',\n            },\n            paramsKeyMap: {},\n            class: 'geni_input',\n            isNotFor: ['genibot'],\n            func: function(sprite, script) {\n                var OIDCODE = Entry.hw.getDigitalPortValue('OIDCODE');\n                const ROBOT_VERSION = Entry.hw.getDigitalPortValue('ROBOT_VERSION');\n                if(OIDCODE == 65535){\n                    OIDCODE = -1;\n                    if(ROBOT_VERSION < 8){\n                        OIDCODE = -8;\n                    }\n                }\n                return OIDCODE;\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.GENIBOT;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_hamster.js",
    "content": "'use strict';\n\nEntry.Hamster = {\n    setZero() {\n        Entry.Robomation.setZero();\n    },\n    afterReceive(pd) {\n        Entry.Robomation.afterReceive(pd, false);\n    },\n    getRobot() {\n        const robot = Entry.Robomation.getRobot('hamster', 0);\n        if (robot) {\n            robot.setMotoring(Entry.hw.sendQueue);\n        }\n        return robot;\n    },\n    id: '2.4',\n    name: 'hamster',\n    url: 'http://www.robomation.net',\n    imageName: 'hamster.png',\n    title: {\n        ko: '햄스터',\n        en: 'Hamster',\n        jp: 'ハムスター',\n        vn: 'Hamster',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/hamster.png',\n        width: 256,\n        height: 256,\n        listPorts: {\n            temperature: {\n                name: Lang.Blocks.HAMSTER_sensor_temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            inputA: {\n                name: Lang.Blocks.HAMSTER_sensor_input_a,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            inputB: {\n                name: Lang.Blocks.HAMSTER_sensor_input_b,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationX: {\n                name: Lang.Blocks.HAMSTER_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.HAMSTER_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.HAMSTER_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Hw.buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: { name: Lang.Hw.note, type: 'output', pos: { x: 0, y: 0 } },\n            outputA: {\n                name: `${Lang.Hw.output}A`,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            outputB: {\n                name: `${Lang.Hw.output}B`,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            leftProximity: {\n                name: Lang.Blocks.HAMSTER_sensor_left_proximity,\n                type: 'input',\n                pos: { x: 122, y: 156 },\n            },\n            rightProximity: {\n                name: Lang.Blocks.HAMSTER_sensor_right_proximity,\n                type: 'input',\n                pos: { x: 10, y: 108 },\n            },\n            leftFloor: {\n                name: Lang.Blocks.HAMSTER_sensor_left_floor,\n                type: 'input',\n                pos: { x: 100, y: 234 },\n            },\n            rightFloor: {\n                name: Lang.Blocks.HAMSTER_sensor_right_floor,\n                type: 'input',\n                pos: { x: 13, y: 180 },\n            },\n            light: {\n                name: Lang.Blocks.HAMSTER_sensor_light,\n                type: 'input',\n                pos: { x: 56, y: 189 },\n            },\n            leftWheel: {\n                name: Lang.Hw.leftWheel,\n                type: 'output',\n                pos: { x: 209, y: 115 },\n            },\n            rightWheel: {\n                name: Lang.Hw.rightWheel,\n                type: 'output',\n                pos: { x: 98, y: 30 },\n            },\n            leftLed: {\n                name: `${Lang.Hw.left} ${Lang.Hw.led_en}`,\n                type: 'output',\n                pos: { x: 87, y: 210 },\n            },\n            rightLed: {\n                name: `${Lang.Hw.right} ${Lang.Hw.led_en}`,\n                type: 'output',\n                pos: { x: 24, y: 168 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.Hamster.setLanguage = () => ({\n    ko: {\n        template: {\n            hamster_gripper: '집게 %1 %2',\n            hamster_release_gripper: '집게 끄기 %1',\n            hamster_boolean: '%1?',\n            hamster_play_note: '%1 %2 음을 연주하기 %3',\n            hamster_hand_found: '손 찾음?',\n            hamster_value: '%1',\n            hamster_move_forward_once: '말판 앞으로 한 칸 이동하기 %1',\n            hamster_turn_once: '말판 %1 으로 한 번 돌기 %2',\n            hamster_move_forward_for_secs: '앞으로 %1 초 이동하기 %2',\n            hamster_move_backward_for_secs: '뒤로 %1 초 이동하기 %2',\n            hamster_turn_for_secs: '%1 으로 %2 초 돌기 %3',\n            hamster_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            hamster_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            hamster_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            hamster_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            hamster_follow_line_using: '%1 선을 %2 바닥 센서로 따라가기 %3',\n            hamster_follow_line_until: '%1 선을 따라 %2 교차로까지 이동하기 %3',\n            hamster_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n            hamster_stop: '정지하기 %1',\n            hamster_set_led_to: '%1 LED를 %2 으로 정하기 %3',\n            hamster_clear_led: '%1 LED 끄기 %2',\n            hamster_beep: '삐 소리내기 %1',\n            hamster_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            hamster_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            hamster_clear_buzzer: '버저 끄기 %1',\n            hamster_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n            hamster_rest_for: '%1 박자 쉬기 %2',\n            hamster_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            hamster_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n            hamster_set_port_to: '포트 %1 를 %2 으로 정하기 %3',\n            hamster_change_output_by: '출력 %1 를 %2 만큼 바꾸기 %3',\n            hamster_set_output_to: '출력 %1 를 %2 (으)로 정하기 %3',\n        },\n        Helper: {\n            hamster_gripper: '집게를 열거나 닫습니다.',\n            hamster_release_gripper: '집게의 전원을 끄고 자유롭게 움직일 수 있도록 합니다.',\n            hamster_boolean:\n                \"앞으로 기울임: 앞으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            hamster_play_note: '선택한 계이름과 옥타브의 음을 소리 냅니다.',\n            hamster_beep: '버저 소리를 짧게 냅니다.',\n            hamster_change_both_wheels_by:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            hamster_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            hamster_change_output_by:\n                '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n            hamster_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            hamster_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            hamster_clear_buzzer: '버저 소리를 끕니다.',\n            hamster_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n            hamster_follow_line_until:\n                '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n            hamster_follow_line_using:\n                '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n            hamster_hand_found:\n                \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            hamster_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n            hamster_move_forward_for_secs: '입력한 시간(초) 동안 앞으로 이동합니다.',\n            hamster_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n            hamster_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            hamster_rest_for: '입력한 박자만큼 쉽니다.',\n            hamster_set_both_wheels_to:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            hamster_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n            hamster_set_following_speed_to:\n                '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            hamster_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n            hamster_set_output_to:\n                '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n            hamster_set_port_to: '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n            hamster_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n            hamster_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            hamster_stop: '양쪽 바퀴를 정지합니다.',\n            hamster_turn_for_secs:\n                '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            hamster_turn_once: '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n            hamster_value:\n                '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n        },\n        Blocks: {\n            HAMSTER_hand_found: '손 찾음?',\n            HAMSTER_sensor_left_proximity: '왼쪽 근접 센서',\n            HAMSTER_sensor_right_proximity: '오른쪽 근접 센서',\n            HAMSTER_sensor_left_floor: '왼쪽 바닥 센서',\n            HAMSTER_sensor_right_floor: '오른쪽 바닥 센서',\n            HAMSTER_sensor_acceleration_x: 'x축 가속도',\n            HAMSTER_sensor_acceleration_y: 'y축 가속도',\n            HAMSTER_sensor_acceleration_z: 'z축 가속도',\n            HAMSTER_sensor_light: '밝기',\n            HAMSTER_sensor_temperature: '온도',\n            HAMSTER_sensor_signal_strength: '신호 세기',\n            HAMSTER_sensor_input_a: '입력 A',\n            HAMSTER_sensor_input_b: '입력 B',\n            HAMSTER_move_forward_once: '말판 앞으로 한 칸 이동하기',\n            HAMSTER_turn_once_1: '말판',\n            HAMSTER_turn_once_2: '으로 한 번 돌기',\n            HAMSTER_turn_once_left: '왼쪽',\n            HAMSTER_turn_right: '오른쪽',\n            HAMSTER_move_forward: '앞으로 이동하기',\n            HAMSTER_move_backward: '뒤로 이동하기',\n            HAMSTER_turn_around_1: '',\n            HAMSTER_turn_around_2: '으로 돌기',\n            HAMSTER_move_forward_for_secs_1: '앞으로',\n            HAMSTER_move_forward_for_secs_2: '초 이동하기',\n            HAMSTER_move_backward_for_secs_1: '뒤로',\n            HAMSTER_move_backward_for_secs_2: '초 이동하기',\n            HAMSTER_turn_for_secs_1: '',\n            HAMSTER_turn_for_secs_2: '으로',\n            HAMSTER_turn_for_secs_3: '초 돌기',\n            HAMSTER_change_both_wheels_by_1: '왼쪽 바퀴',\n            HAMSTER_change_both_wheels_by_2: '오른쪽 바퀴',\n            HAMSTER_change_both_wheels_by_3: '만큼 바꾸기',\n            HAMSTER_set_both_wheels_to_1: '왼쪽 바퀴',\n            HAMSTER_set_both_wheels_to_2: '오른쪽 바퀴',\n            HAMSTER_set_both_wheels_to_3: '(으)로 정하기',\n            HAMSTER_change_wheel_by_1: '',\n            HAMSTER_change_wheel_by_2: '바퀴',\n            HAMSTER_change_wheel_by_3: '만큼 바꾸기',\n            HAMSTER_left_wheel: '왼쪽',\n            HAMSTER_right_wheel: '오른쪽',\n            HAMSTER_both_wheels: '양쪽',\n            HAMSTER_set_wheel_to_1: '',\n            HAMSTER_set_wheel_to_2: '바퀴',\n            HAMSTER_set_wheel_to_3: '(으)로 정하기',\n            HAMSTER_follow_line_using_1: '',\n            HAMSTER_follow_line_using_2: '선을',\n            HAMSTER_follow_line_using_3: '바닥 센서로 따라가기',\n            HAMSTER_left_floor_sensor: '왼쪽',\n            HAMSTER_right_floor_sensor: '오른쪽',\n            HAMSTER_both_floor_sensors: '양쪽',\n            HAMSTER_follow_line_until_1: '',\n            HAMSTER_follow_line_until_2: '선을 따라',\n            HAMSTER_follow_line_until_3: '교차로까지 이동하기',\n            HAMSTER_left_intersection: '왼쪽',\n            HAMSTER_right_intersection: '오른쪽',\n            HAMSTER_front_intersection: '앞쪽',\n            HAMSTER_rear_intersection: '뒤쪽',\n            HAMSTER_set_following_speed_to_1: '선 따라가기 속도를',\n            HAMSTER_set_following_speed_to_2: '(으)로 정하기',\n            HAMSTER_front: '앞쪽',\n            HAMSTER_rear: '뒤쪽',\n            HAMSTER_stop: '정지하기',\n            HAMSTER_set_led_to_1: '',\n            HAMSTER_set_led_to_2: 'LED를',\n            HAMSTER_set_led_to_3: '으로 정하기',\n            HAMSTER_left_led: '왼쪽',\n            HAMSTER_right_led: '오른쪽',\n            HAMSTER_both_leds: '양쪽',\n            HAMSTER_clear_led_1: '',\n            HAMSTER_clear_led_2: 'LED 끄기',\n            HAMSTER_color_cyan: '하늘색',\n            HAMSTER_color_magenta: '자주색',\n            HAMSTER_color_black: '검은색',\n            HAMSTER_color_white: '하얀색',\n            HAMSTER_color_red: '빨간색',\n            HAMSTER_color_yellow: '노란색',\n            HAMSTER_color_green: '초록색',\n            HAMSTER_color_blue: '파란색',\n            HAMSTER_beep: '삐 소리내기',\n            HAMSTER_change_buzzer_by_1: '버저 음을',\n            HAMSTER_change_buzzer_by_2: '만큼 바꾸기',\n            HAMSTER_set_buzzer_to_1: '버저 음을',\n            HAMSTER_set_buzzer_to_2: '(으)로 정하기',\n            HAMSTER_clear_buzzer: '버저 끄기',\n            HAMSTER_play_note_for_1: '',\n            HAMSTER_play_note_for_2: '',\n            HAMSTER_play_note_for_3: '음을',\n            HAMSTER_play_note_for_4: '박자 연주하기',\n            HAMSTER_rest_for_1: '',\n            HAMSTER_rest_for_2: '박자 쉬기',\n            HAMSTER_change_tempo_by_1: '연주 속도를',\n            HAMSTER_change_tempo_by_2: '만큼 바꾸기',\n            HAMSTER_set_tempo_to_1: '연주 속도를 분당',\n            HAMSTER_set_tempo_to_2: '박자로 정하기',\n            HAMSTER_set_port_to_1: '포트',\n            HAMSTER_set_port_to_2: '를',\n            HAMSTER_set_port_to_3: '으로 정하기',\n            HAMSTER_change_output_by_1: '출력',\n            HAMSTER_change_output_by_2: '를',\n            HAMSTER_change_output_by_3: '만큼 바꾸기',\n            HAMSTER_set_output_to_1: '출력',\n            HAMSTER_set_output_to_2: '를',\n            HAMSTER_set_output_to_3: '(으)로 정하기',\n            HAMSTER_port_a: 'A',\n            HAMSTER_port_b: 'B',\n            HAMSTER_port_ab: 'A와 B',\n            HAMSTER_analog_input: '아날로그 입력',\n            HAMSTER_digital_input: '디지털 입력',\n            HAMSTER_servo_output: '서보 출력',\n            HAMSTER_pwm_output: 'PWM 출력',\n            HAMSTER_digital_output: '디지털 출력',\n            hamster_note_c: '도',\n            hamster_note_c_sharp: '도♯(레♭)',\n            hamster_note_d: '레',\n            hamster_note_d_sharp: '레♯(미♭)',\n            hamster_note_e: '미',\n            hamster_note_f: '파',\n            hamster_note_f_sharp: '파♯(솔♭)',\n            hamster_note_g: '솔',\n            hamster_note_g_sharp: '솔♯(라♭)',\n            hamster_note_a: '라',\n            hamster_note_a_sharp: '라♯(시♭)',\n            hamster_note_b: '시',\n            hamster_tilt_forward: '앞으로 기울임',\n            hamster_tilt_backward: '뒤로 기울임',\n            hamster_tilt_left: '왼쪽으로 기울임',\n            hamster_tilt_right: '오른쪽으로 기울임',\n            hamster_tilt_flip: '거꾸로 뒤집음',\n            hamster_tilt_not: '기울이지 않음',\n            hamster_battery_normal: '배터리 정상',\n            hamster_battery_low: '배터리 부족',\n            hamster_battery_empty: '배터리 없음',\n            hamster_open_gripper: '열기',\n            hamster_close_gripper: '닫기',\n        },\n    },\n    en: {\n        template: {\n            hamster_gripper: '%1 gripper %2',\n            hamster_release_gripper: 'release gripper %1',\n            hamster_boolean: '%1?',\n            hamster_play_note: 'play note %1 %2 %3',\n            hamster_hand_found: 'hand found?',\n            hamster_value: '%1',\n            hamster_move_forward_once: 'move forward once on board %1',\n            hamster_turn_once: 'turn %1 once on board %2',\n            hamster_move_forward_for_secs: 'move forward for %1 secs %2',\n            hamster_move_backward_for_secs: 'move backward for %1 secs %2',\n            hamster_turn_for_secs: 'turn %1 for %2 secs %3',\n            hamster_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            hamster_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            hamster_change_wheel_by: 'change %1 wheel by %2 %3',\n            hamster_set_wheel_to: 'set %1 wheel to %2 %3',\n            hamster_follow_line_using: 'follow %1 line using %2 floor sensor %3',\n            hamster_follow_line_until: 'follow %1 line until %2 intersection %3',\n            hamster_set_following_speed_to: 'set following speed to %1 %2',\n            hamster_stop: 'stop %1',\n            hamster_set_led_to: 'set %1 led to %2 %3',\n            hamster_clear_led: 'clear %1 led %2',\n            hamster_beep: 'beep %1',\n            hamster_change_buzzer_by: 'change buzzer by %1 %2',\n            hamster_set_buzzer_to: 'set buzzer to %1 %2',\n            hamster_clear_buzzer: 'clear buzzer %1',\n            hamster_play_note_for: 'play note %1 %2 for %3 beats %4',\n            hamster_rest_for: 'rest for %1 beats %2',\n            hamster_change_tempo_by: 'change tempo by %1 %2',\n            hamster_set_tempo_to: 'set tempo to %1 bpm %2',\n            hamster_set_port_to: 'set port %1 to %2 %3',\n            hamster_change_output_by: 'change output %1 by %2 %3',\n            hamster_set_output_to: 'set output %1 to %2 %3',\n        },\n        Helper: {\n            hamster_gripper: 'Opens or closes the gripper.',\n            hamster_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            hamster_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            hamster_play_note: 'It sounds the selected tone and octave.',\n            hamster_beep: 'Plays beep sound.',\n            hamster_change_both_wheels_by:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            hamster_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            hamster_change_output_by:\n                'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            hamster_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            hamster_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            hamster_clear_buzzer: 'Turns off buzzer sound.',\n            hamster_clear_led: 'Turns off the left/right/both LEDs.',\n            hamster_follow_line_until:\n                'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n            hamster_follow_line_using:\n                'Moves along the black/white line by using the left/right/both floor sensors.',\n            hamster_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            hamster_move_backward_for_secs: 'Moves backward for the number of seconds entered.',\n            hamster_move_forward_for_secs: 'Moves forward for the number of seconds entered.',\n            hamster_move_forward_once: 'Moves one space forward on the board.',\n            hamster_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            hamster_rest_for: 'Rests as much as the beat you entered.',\n            hamster_set_both_wheels_to:\n                'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            hamster_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            hamster_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            hamster_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n            hamster_set_output_to:\n                'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            hamster_set_port_to:\n                'Sets the io mode of the selected external port to the selected mode.',\n            hamster_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            hamster_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            hamster_stop: 'Stops both wheels.',\n            hamster_turn_for_secs: 'Turns left/right for the number of seconds entered.',\n            hamster_turn_once: 'Turns left/right 90 degrees on the board.',\n            hamster_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n        },\n        Blocks: {\n            HAMSTER_hand_found: 'hand found?',\n            HAMSTER_sensor_left_proximity: 'left proximity',\n            HAMSTER_sensor_right_proximity: 'right proximity',\n            HAMSTER_sensor_left_floor: 'left floor',\n            HAMSTER_sensor_right_floor: 'right floor',\n            HAMSTER_sensor_acceleration_x: 'x acceleration',\n            HAMSTER_sensor_acceleration_y: 'y acceleration',\n            HAMSTER_sensor_acceleration_z: 'z acceleration',\n            HAMSTER_sensor_light: 'light',\n            HAMSTER_sensor_temperature: 'temperature',\n            HAMSTER_sensor_signal_strength: 'signal strength',\n            HAMSTER_sensor_input_a: 'input A',\n            HAMSTER_sensor_input_b: 'input B',\n            HAMSTER_move_forward_once: 'move forward once on board',\n            HAMSTER_turn_once_1: 'turn',\n            HAMSTER_turn_once_2: 'once on board',\n            HAMSTER_turn_once_left: 'left',\n            HAMSTER_turn_right: 'right',\n            HAMSTER_move_forward: 'move forward',\n            HAMSTER_move_backward: 'move backward',\n            HAMSTER_turn_around_1: 'turn',\n            HAMSTER_turn_around_2: '',\n            HAMSTER_move_forward_for_secs_1: 'move forward for',\n            HAMSTER_move_forward_for_secs_2: 'secs',\n            HAMSTER_move_backward_for_secs_1: 'move backward',\n            HAMSTER_move_backward_for_secs_2: 'secs',\n            HAMSTER_turn_for_secs_1: 'turn',\n            HAMSTER_turn_for_secs_2: 'for',\n            HAMSTER_turn_for_secs_3: 'secs',\n            HAMSTER_change_both_wheels_by_1: 'change wheel by left:',\n            HAMSTER_change_both_wheels_by_2: 'right:',\n            HAMSTER_change_both_wheels_by_3: '',\n            HAMSTER_set_both_wheels_to_1: 'set wheel to left:',\n            HAMSTER_set_both_wheels_to_2: 'right:',\n            HAMSTER_set_both_wheels_to_3: '',\n            HAMSTER_change_wheel_by_1: 'change',\n            HAMSTER_change_wheel_by_2: 'wheel by',\n            HAMSTER_change_wheel_by_3: '',\n            HAMSTER_left_wheel: 'left',\n            HAMSTER_right_wheel: 'right',\n            HAMSTER_both_wheels: 'both',\n            HAMSTER_set_wheel_to_1: 'set',\n            HAMSTER_set_wheel_to_2: 'wheel to',\n            HAMSTER_set_wheel_to_3: '',\n            HAMSTER_follow_line_using_1: 'follow',\n            HAMSTER_follow_line_using_2: 'line using',\n            HAMSTER_follow_line_using_3: 'floor sensor',\n            HAMSTER_left_floor_sensor: 'left',\n            HAMSTER_right_floor_sensor: 'right',\n            HAMSTER_both_floor_sensors: 'both',\n            HAMSTER_follow_line_until_1: 'follow',\n            HAMSTER_follow_line_until_2: 'line until',\n            HAMSTER_follow_line_until_3: 'intersection',\n            HAMSTER_left_intersection: 'left',\n            HAMSTER_right_intersection: 'right',\n            HAMSTER_front_intersection: 'front',\n            HAMSTER_rear_intersection: 'rear',\n            HAMSTER_set_following_speed_to_1: 'set following speed to',\n            HAMSTER_set_following_speed_to_2: '',\n            HAMSTER_front: 'front',\n            HAMSTER_rear: 'rear',\n            HAMSTER_stop: 'stop',\n            HAMSTER_set_led_to_1: 'set',\n            HAMSTER_set_led_to_2: 'led to',\n            HAMSTER_set_led_to_3: '',\n            HAMSTER_left_led: 'left',\n            HAMSTER_right_led: 'right',\n            HAMSTER_both_leds: 'both',\n            HAMSTER_clear_led_1: 'clear',\n            HAMSTER_clear_led_2: 'led',\n            HAMSTER_color_cyan: 'sky blue',\n            HAMSTER_color_magenta: 'purple',\n            HAMSTER_color_black: 'black',\n            HAMSTER_color_white: 'white',\n            HAMSTER_color_red: 'red',\n            HAMSTER_color_yellow: 'yellow',\n            HAMSTER_color_green: 'green',\n            HAMSTER_color_blue: 'blue',\n            HAMSTER_beep: 'beep',\n            HAMSTER_change_buzzer_by_1: 'change buzzer by',\n            HAMSTER_change_buzzer_by_2: '',\n            HAMSTER_set_buzzer_to_1: 'set buzzer to',\n            HAMSTER_set_buzzer_to_2: '',\n            HAMSTER_clear_buzzer: 'clear buzzer',\n            HAMSTER_play_note_for_1: 'play note',\n            HAMSTER_play_note_for_2: '',\n            HAMSTER_play_note_for_3: 'for',\n            HAMSTER_play_note_for_4: 'beats',\n            HAMSTER_rest_for_1: 'rest for',\n            HAMSTER_rest_for_2: 'beats',\n            HAMSTER_change_tempo_by_1: 'change tempo by',\n            HAMSTER_change_tempo_by_2: '',\n            HAMSTER_set_tempo_to_1: 'set tempo to',\n            HAMSTER_set_tempo_to_2: 'bpm',\n            HAMSTER_set_port_to_1: 'set port',\n            HAMSTER_set_port_to_2: 'to',\n            HAMSTER_set_port_to_3: '',\n            HAMSTER_change_output_by_1: 'change output',\n            HAMSTER_change_output_by_2: 'by',\n            HAMSTER_change_output_by_3: '',\n            HAMSTER_set_output_to_1: 'set output',\n            HAMSTER_set_output_to_2: 'to',\n            HAMSTER_set_output_to_3: '',\n            HAMSTER_port_a: 'A',\n            HAMSTER_port_b: 'B',\n            HAMSTER_port_ab: 'A and B',\n            HAMSTER_analog_input: 'analog input',\n            HAMSTER_digital_input: 'digital input',\n            HAMSTER_servo_output: 'servo output',\n            HAMSTER_pwm_output: 'pwm output',\n            HAMSTER_digital_output: 'digital output',\n            hamster_note_c: 'C',\n            hamster_note_c_sharp: 'C♯(D♭)',\n            hamster_note_d: 'D',\n            hamster_note_d_sharp: 'D♯(E♭)',\n            hamster_note_e: 'E',\n            hamster_note_f: 'F',\n            hamster_note_f_sharp: 'F♯(G♭)',\n            hamster_note_g: 'G',\n            hamster_note_g_sharp: 'G♯(A♭)',\n            hamster_note_a: 'A',\n            hamster_note_a_sharp: 'A♯(B♭)',\n            hamster_note_b: 'B',\n            hamster_tilt_forward: 'tilt forward',\n            hamster_tilt_backward: 'tilt backward',\n            hamster_tilt_left: 'tilt left',\n            hamster_tilt_right: 'tilt right',\n            hamster_tilt_flip: 'tilt flip',\n            hamster_tilt_not: 'not tilt',\n            hamster_battery_normal: 'battery normal',\n            hamster_battery_low: 'battery low',\n            hamster_battery_empty: 'battery empty',\n            hamster_open_gripper: 'open',\n            hamster_close_gripper: 'close',\n        },\n    },\n    jp: {\n        template: {\n            hamster_gripper: 'グリッパを %1 %2',\n            hamster_release_gripper: 'グリッパをオフ %1',\n            hamster_boolean: '%1?',\n            hamster_play_note: '%1 %2 を演奏する %3',\n        },\n        Helper: {\n            hamster_gripper: 'Opens or closes the gripper.',\n            hamster_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            hamster_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            hamster_play_note: '選択された音階（音名、オクターブ）が鳴ります。',\n        },\n        Blocks: {\n            hamster_note_c: 'ド',\n            hamster_note_c_sharp: 'ド♯(レ♭)',\n            hamster_note_d: 'レ',\n            hamster_note_d_sharp: 'レ♯(ミ♭)',\n            hamster_note_e: 'ミ',\n            hamster_note_f: 'ファ',\n            hamster_note_f_sharp: 'ファ♯(ソ♭)',\n            hamster_note_g: 'ソ',\n            hamster_note_g_sharp: 'ソ♯(ラ♭)',\n            hamster_note_a: 'ラ',\n            hamster_note_a_sharp: 'ラ♯(シ♭)',\n            hamster_note_b: 'シ',\n            hamster_tilt_forward: '前に傾けたか',\n            hamster_tilt_backward: '後に傾けたか',\n            hamster_tilt_left: '左に傾けたか',\n            hamster_tilt_right: '右に傾けたか',\n            hamster_tilt_flip: '上下裏返したか',\n            hamster_tilt_not: '傾けなかったか',\n            hamster_battery_normal: '電池が正常か',\n            hamster_battery_low: '電池が足りないか',\n            hamster_battery_empty: '電池がないか',\n            hamster_open_gripper: '開く',\n            hamster_close_gripper: '閉める',\n        },\n    },\n    vn: {\n        template: {\n            hamster_gripper: '%1 gripper %2',\n            hamster_release_gripper: 'release gripper %1',\n            hamster_boolean: '%1?',\n            hamster_play_note: 'play note %1 %2 %3',\n        },\n        Helper: {\n            hamster_gripper: 'Opens or closes the gripper.',\n            hamster_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            hamster_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            hamster_play_note: 'It sounds the selected tone and octave.',\n        },\n        Blocks: {\n            hamster_note_c: 'C',\n            hamster_note_c_sharp: 'C♯(D♭)',\n            hamster_note_d: 'D',\n            hamster_note_d_sharp: 'D♯(E♭)',\n            hamster_note_e: 'E',\n            hamster_note_f: 'F',\n            hamster_note_f_sharp: 'F♯(G♭)',\n            hamster_note_g: 'G',\n            hamster_note_g_sharp: 'G♯(A♭)',\n            hamster_note_a: 'A',\n            hamster_note_a_sharp: 'A♯(B♭)',\n            hamster_note_b: 'B',\n            hamster_tilt_forward: 'tilt forward',\n            hamster_tilt_backward: 'tilt backward',\n            hamster_tilt_left: 'tilt left',\n            hamster_tilt_right: 'tilt right',\n            hamster_tilt_flip: 'tilt flip',\n            hamster_tilt_not: 'not tilt',\n            hamster_battery_normal: 'battery normal',\n            hamster_battery_low: 'battery low',\n            hamster_battery_empty: 'battery empty',\n            hamster_open_gripper: 'open',\n            hamster_close_gripper: 'close',\n        },\n    },\n});\n\nEntry.Hamster.blockMenuBlocks = [\n    'hamster_hand_found',\n    'hamster_boolean',\n    'hamster_value',\n    'hamster_move_forward_once',\n    'hamster_turn_once',\n    'hamster_move_forward_for_secs',\n    'hamster_move_backward_for_secs',\n    'hamster_turn_for_secs',\n    'hamster_change_both_wheels_by',\n    'hamster_set_both_wheels_to',\n    'hamster_change_wheel_by',\n    'hamster_set_wheel_to',\n    'hamster_follow_line_using',\n    'hamster_follow_line_until',\n    'hamster_set_following_speed_to',\n    'hamster_stop',\n    'hamster_set_led_to',\n    'hamster_clear_led',\n    'hamster_beep',\n    'hamster_change_buzzer_by',\n    'hamster_set_buzzer_to',\n    'hamster_clear_buzzer',\n    'hamster_play_note',\n    'hamster_play_note_for',\n    'hamster_rest_for',\n    'hamster_change_tempo_by',\n    'hamster_set_tempo_to',\n    'hamster_set_port_to',\n    'hamster_change_output_by',\n    'hamster_set_output_to',\n    'hamster_gripper',\n    'hamster_release_gripper',\n];\n\nEntry.Hamster.getBlocks = function() {\n    return {\n        hamster_hand_found: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'hamster_hand_found',\n            },\n            class: 'hamster_sensor',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.checkHandFound(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.hand_found()',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        hamster_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.hamster_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.hamster_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.hamster_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.hamster_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.hamster_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.hamster_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.hamster_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.hamster_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hamster_sensor',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.hamster_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.hamster_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.hamster_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.hamster_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.hamster_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.hamster_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.hamster_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.hamster_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_sensor_left_proximity, 'leftProximity'],\n                        [Lang.Blocks.HAMSTER_sensor_right_proximity, 'rightProximity'],\n                        [Lang.Blocks.HAMSTER_sensor_left_floor, 'leftFloor'],\n                        [Lang.Blocks.HAMSTER_sensor_right_floor, 'rightFloor'],\n                        [Lang.Blocks.HAMSTER_sensor_acceleration_x, 'accelerationX'],\n                        [Lang.Blocks.HAMSTER_sensor_acceleration_y, 'accelerationY'],\n                        [Lang.Blocks.HAMSTER_sensor_acceleration_z, 'accelerationZ'],\n                        [Lang.Blocks.HAMSTER_sensor_light, 'light'],\n                        [Lang.Blocks.HAMSTER_sensor_temperature, 'temperature'],\n                        [Lang.Blocks.HAMSTER_sensor_signal_strength, 'signalStrength'],\n                        [Lang.Blocks.HAMSTER_sensor_input_a, 'inputA'],\n                        [Lang.Blocks.HAMSTER_sensor_input_b, 'inputB'],\n                    ],\n                    value: 'leftProximity',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hamster_sensor',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_sensor_left_proximity, 'leftProximity'],\n                                    [Lang.Blocks.HAMSTER_sensor_right_proximity, 'rightProximity'],\n                                    [Lang.Blocks.HAMSTER_sensor_left_floor, 'leftFloor'],\n                                    [Lang.Blocks.HAMSTER_sensor_right_floor, 'rightFloor'],\n                                    [Lang.Blocks.HAMSTER_sensor_acceleration_x, 'accelerationX'],\n                                    [Lang.Blocks.HAMSTER_sensor_acceleration_y, 'accelerationY'],\n                                    [Lang.Blocks.HAMSTER_sensor_acceleration_z, 'accelerationZ'],\n                                    [Lang.Blocks.HAMSTER_sensor_light, 'light'],\n                                    [Lang.Blocks.HAMSTER_sensor_temperature, 'temperature'],\n                                    [Lang.Blocks.HAMSTER_sensor_signal_strength, 'signalStrength'],\n                                    [Lang.Blocks.HAMSTER_sensor_input_a, 'inputA'],\n                                    [Lang.Blocks.HAMSTER_sensor_input_b, 'inputB'],\n                                ],\n                                value: 'leftProximity',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_move_forward_once: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_move_forward_once',\n            },\n            class: 'hamster_board',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.boardForward(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.board_forward()',\n                    },\n                ],\n            },\n        },\n        hamster_turn_once: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_turn_once_left, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_turn_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_turn_once',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'hamster_board',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.boardTurn(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.board_turn(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_turn_once_left, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_turn_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_move_forward_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'hamster_move_forward_for_secs',\n            },\n            paramsKeyMap: {\n                SECS: 0,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.moveForwardSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.move_forward(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_move_backward_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'hamster_move_backward_for_secs',\n            },\n            paramsKeyMap: {\n                SECS: 0,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.moveBackwardSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.move_backward(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_turn_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_turn_once_left, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_turn_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'hamster_turn_for_secs',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                SECS: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.turnSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.turn(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_turn_once_left, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_turn_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_change_both_wheels_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'hamster_change_both_wheels_by',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_set_both_wheels_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'hamster_set_both_wheels_to',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_wheel, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_wheel, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_wheels, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'hamster_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_wheel, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_wheel, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_wheels, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_wheel, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_wheel, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_wheels, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'hamster_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_wheel, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_wheel, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_wheels, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_follow_line_using: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_color_black, 'BLACK'],\n                        [Lang.Blocks.HAMSTER_color_white, 'WHITE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_floor_sensor, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_floor_sensor, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_floor_sensors, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_follow_line_using',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                SENSOR: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.follow_line(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_black, 'BLACK'],\n                                    [Lang.Blocks.HAMSTER_color_white, 'WHITE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_floor_sensor, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_floor_sensor, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_floor_sensors, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_color_black, 'BLACK'],\n                        [Lang.Blocks.HAMSTER_color_white, 'WHITE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_floor_sensor, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_floor_sensor, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_front, 'FRONT'],\n                        [Lang.Blocks.HAMSTER_rear, 'REAR'],\n                    ],\n                    value: 'FRONT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_follow_line_until',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                DIRECTION: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.follow_line_until(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_black, 'BLACK'],\n                                    [Lang.Blocks.HAMSTER_color_white, 'WHITE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_floor_sensor, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_floor_sensor, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_front, 'FRONT'],\n                                    [Lang.Blocks.HAMSTER_rear, 'REAR'],\n                                ],\n                                value: 'FRONT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['5', null],\n                type: 'hamster_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_line_speed(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_stop',\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.stop()',\n                    },\n                ],\n            },\n        },\n        hamster_set_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_color_red, '4'],\n                        [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                        [Lang.Blocks.HAMSTER_color_green, '2'],\n                        [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                        [Lang.Blocks.HAMSTER_color_blue, '1'],\n                        [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                        [Lang.Blocks.HAMSTER_color_white, '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_set_led_to',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },\n            class: 'hamster_led',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.setLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_led_red(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '4'],\n                    },\n                    {\n                        syntax: 'Hamster.set_led_yellow(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '6'],\n                    },\n                    {\n                        syntax: 'Hamster.set_led_green(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '2'],\n                    },\n                    {\n                        syntax: 'Hamster.set_led_sky_blue(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '3'],\n                    },\n                    {\n                        syntax: 'Hamster.set_led_blue(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1'],\n                    },\n                    {\n                        syntax: 'Hamster.set_led_purple(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '5'],\n                    },\n                    {\n                        syntax: 'Hamster.set_led_white(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '7'],\n                    },\n                ],\n            },\n        },\n        hamster_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_clear_led',\n            },\n            paramsKeyMap: {\n                LED: 0,\n            },\n            class: 'hamster_led',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.clear_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_beep: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_beep',\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.beep(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.beep()',\n                    },\n                ],\n            },\n        },\n        hamster_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'hamster_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.add_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        hamster_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'hamster_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        hamster_clear_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_clear_buzzer',\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.clearBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.clear_buzzer()',\n                    },\n                ],\n            },\n        },\n        hamster_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_note_c, '4'],\n                        [Lang.Blocks.hamster_note_c_sharp, '5'],\n                        [Lang.Blocks.hamster_note_d, '6'],\n                        [Lang.Blocks.hamster_note_d_sharp, '7'],\n                        [Lang.Blocks.hamster_note_e, '8'],\n                        [Lang.Blocks.hamster_note_f, '9'],\n                        [Lang.Blocks.hamster_note_f_sharp, '10'],\n                        [Lang.Blocks.hamster_note_g, '11'],\n                        [Lang.Blocks.hamster_note_g_sharp, '12'],\n                        [Lang.Blocks.hamster_note_a, '13'],\n                        [Lang.Blocks.hamster_note_a_sharp, '14'],\n                        [Lang.Blocks.hamster_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'hamster_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.play_pitch_c(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['4'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_c_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['5'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_d(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['6'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_d_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['7'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_e(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['8'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_f(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['9'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_f_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['10'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_g(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['11'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_g_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['12'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_a(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['13'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_a_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['14'],\n                    },\n                    {\n                        syntax: 'Hamster.play_pitch_b(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['15'],\n                    },\n                ],\n            },\n        },\n        hamster_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_note_c, '4'],\n                        [Lang.Blocks.hamster_note_c_sharp, '5'],\n                        [Lang.Blocks.hamster_note_d, '6'],\n                        [Lang.Blocks.hamster_note_d_sharp, '7'],\n                        [Lang.Blocks.hamster_note_e, '8'],\n                        [Lang.Blocks.hamster_note_f, '9'],\n                        [Lang.Blocks.hamster_note_f_sharp, '10'],\n                        [Lang.Blocks.hamster_note_g, '11'],\n                        [Lang.Blocks.hamster_note_g_sharp, '12'],\n                        [Lang.Blocks.hamster_note_a, '13'],\n                        [Lang.Blocks.hamster_note_a_sharp, '14'],\n                        [Lang.Blocks.hamster_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'hamster_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.play_note_c(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['4'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_c_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['5'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_d(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['6'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_d_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['7'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_e(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['8'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_f(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['9'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_f_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['10'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_g(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['11'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_g_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['12'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_a(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['13'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_a_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['14'],\n                    },\n                    {\n                        syntax: 'Hamster.play_note_b(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['15'],\n                    },\n                ],\n            },\n        },\n        hamster_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'hamster_rest_for',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.rest(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'hamster_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'hamster_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_set_port_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_port_a, 'A'],\n                        [Lang.Blocks.HAMSTER_port_b, 'B'],\n                        [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_analog_input, '0'],\n                        [Lang.Blocks.HAMSTER_digital_input, '1'],\n                        [Lang.Blocks.HAMSTER_servo_output, '8'],\n                        [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                        [Lang.Blocks.HAMSTER_digital_output, '10'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_set_port_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                MODE: 1,\n            },\n            class: 'hamster_port',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.setIoMode(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_io_mode_analog_input(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '0'],\n                    },\n                    {\n                        syntax: 'Hamster.set_io_mode_digital_input(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1'],\n                    },\n                    {\n                        syntax: 'Hamster.set_io_mode_servo_output(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '8'],\n                    },\n                    {\n                        syntax: 'Hamster.set_io_mode_pwm_output(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '9'],\n                    },\n                    {\n                        syntax: 'Hamster.set_io_mode_digital_output(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '10'],\n                    },\n                ],\n            },\n        },\n        hamster_change_output_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_port_a, 'A'],\n                        [Lang.Blocks.HAMSTER_port_b, 'B'],\n                        [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'hamster_change_output_by',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'hamster_port',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.changeOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.add_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_set_output_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_port_a, 'A'],\n                        [Lang.Blocks.HAMSTER_port_b, 'B'],\n                        [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'hamster_set_output_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'hamster_port',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.setOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_gripper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_open_gripper, 'OPEN'],\n                        [Lang.Blocks.hamster_close_gripper, 'CLOSE'],\n                    ],\n                    value: 'OPEN',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_gripper',\n            },\n            paramsKeyMap: {\n                ACTION: 0,\n            },\n            class: 'hamster_port',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.gripper(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.set_gripper(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_open_gripper, 'OPEN'],\n                                    [Lang.Blocks.hamster_close_gripper, 'CLOSE'],\n                                ],\n                                value: 'OPEN',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_release_gripper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_release_gripper',\n            },\n            class: 'hamster_port',\n            isNotFor: ['hamster'],\n            func(sprite, script) {\n                const robot = Entry.Hamster.getRobot();\n                return robot ? robot.releaseGripper(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Hamster.release_gripper()',\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Hamster;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_hamster_s.js",
    "content": "'use strict';\n\nEntry.HamsterS = {\n    setZero() {\n        Entry.Robomation.setZero();\n    },\n    afterReceive(pd) {\n        Entry.Robomation.afterReceive(pd, false);\n    },\n    afterSend(sq) {\n        Entry.Robomation.afterSend(sq);\n    },\n    getRobot() {\n        const robot = Entry.Robomation.getRobot('hamster', 0);\n        if (robot) {\n            robot.setMotoring(Entry.hw.sendQueue);\n        }\n        return robot;\n    },\n    id: '2.E',\n    name: 'hamsterS',\n    url: 'http://www.robomation.net',\n    imageName: 'hamster_s.png',\n    title: {\n        ko: '햄스터S',\n        en: 'HamsterS',\n        jp: 'ハムスターS',\n        vn: 'HamsterS',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/hamster_s.png',\n        width: 256,\n        height: 256,\n        listPorts: {\n            temperature: {\n                name: Lang.Blocks.HAMSTER_sensor_temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            inputA: {\n                name: Lang.Blocks.HAMSTER_sensor_input_a,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            inputB: {\n                name: Lang.Blocks.HAMSTER_sensor_input_b,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationX: {\n                name: Lang.Blocks.HAMSTER_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.HAMSTER_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.HAMSTER_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Hw.buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: { name: Lang.Hw.note, type: 'output', pos: { x: 0, y: 0 } },\n            outputA: {\n                name: `${Lang.Hw.output}A`,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            outputB: {\n                name: `${Lang.Hw.output}B`,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            leftProximity: {\n                name: Lang.Blocks.HAMSTER_sensor_left_proximity,\n                type: 'input',\n                pos: { x: 246, y: 110 },\n            },\n            rightProximity: {\n                name: Lang.Blocks.HAMSTER_sensor_right_proximity,\n                type: 'input',\n                pos: { x: 128, y: 156 },\n            },\n            leftFloor: {\n                name: Lang.Blocks.HAMSTER_sensor_left_floor,\n                type: 'input',\n                pos: { x: 243, y: 186 },\n            },\n            rightFloor: {\n                name: Lang.Blocks.HAMSTER_sensor_right_floor,\n                type: 'input',\n                pos: { x: 150, y: 236 },\n            },\n            light: {\n                name: Lang.Blocks.HAMSTER_sensor_light,\n                type: 'input',\n                pos: { x: 195, y: 190 },\n            },\n            leftWheel: {\n                name: Lang.Hw.leftWheel,\n                type: 'output',\n                pos: { x: 190, y: 30 },\n            },\n            rightWheel: {\n                name: Lang.Hw.rightWheel,\n                type: 'output',\n                pos: { x: 40, y: 115 },\n            },\n            leftRgb: {\n                name: `${Lang.Hw.left} ${Lang.Hw.led_en}`,\n                type: 'output',\n                pos: { x: 235, y: 183 },\n            },\n            rightRgb: {\n                name: `${Lang.Hw.right} ${Lang.Hw.led_en}`,\n                type: 'output',\n                pos: { x: 154, y: 228 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.HamsterS.setLanguage = () => ({\n    ko: {\n        template: {\n            hamster_s_hand_found: '손 찾음?',\n            hamster_s_boolean: '%1?',\n            hamster_s_value: '%1',\n            hamster_s_move_forward_once: '말판 앞으로 한 칸 이동하기 %1',\n            hamster_s_turn_once: '말판 %1 으로 한 번 돌기 %2',\n            hamster_s_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n            hamster_s_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n            hamster_s_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n            hamster_s_pivot_around_unit_in_direction: '%1 중심으로 %2 %3 %4 방향으로 돌기 %5',\n            hamster_s_turn_unit_with_radius_in_direction:\n                '%1 %2 으로 %3 %4 반지름 %5 cm를 %6 방향으로 돌기 %7',\n            hamster_s_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            hamster_s_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            hamster_s_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            hamster_s_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            hamster_s_follow_line_using: '%1 선을 %2 바닥 센서로 따라가기 %3',\n            hamster_s_follow_line_until: '%1 선을 따라 %2 교차로까지 이동하기 %3',\n            hamster_s_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n            hamster_s_set_following_gain_to: '선 따라가기 방향 변화량을 %1 (으)로 정하기 %2',\n            hamster_s_stop: '정지하기 %1',\n            hamster_s_set_led_to: '%1 LED를 %2 으로 정하기 %3',\n            hamster_s_pick_led: '%1 LED를 %2로 정하기 %3',\n            hamster_s_change_led_by_rgb: '%1 LED를 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n            hamster_s_set_led_to_rgb: '%1 LED를 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n            hamster_s_clear_led: '%1 LED 끄기 %2',\n            hamster_s_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n            hamster_s_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n            hamster_s_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            hamster_s_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            hamster_s_clear_sound: '소리 끄기 %1',\n            hamster_s_play_note: '%1 %2 음을 연주하기 %3',\n            hamster_s_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n            hamster_s_rest_for: '%1 박자 쉬기 %2',\n            hamster_s_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            hamster_s_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n            hamster_s_set_port_to: '포트 %1 를 %2 으로 정하기 %3',\n            hamster_s_change_output_by: '출력 %1 를 %2 만큼 바꾸기 %3',\n            hamster_s_set_output_to: '출력 %1 를 %2 (으)로 정하기 %3',\n            hamster_s_gripper: '집게 %1 %2',\n            hamster_s_release_gripper: '집게 끄기 %1',\n            hamster_s_write_serial: '시리얼 %1 %2 쓰기 %3',\n            hamster_s_read_serial_until: '시리얼 %1 읽기 %2',\n            hamster_s_set_serial_rate_to: '시리얼 속도를 %1 Bd로 정하기 %2',\n        },\n        Helper: {\n            hamster_s_hand_found:\n                \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            hamster_s_boolean:\n                \"앞으로 기울임: 앞으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            hamster_s_value:\n                '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n            hamster_s_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n            hamster_s_turn_once: '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n            hamster_s_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            hamster_s_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            hamster_s_turn_unit_in_place:\n                '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            hamster_s_pivot_around_unit_in_direction:\n                '왼쪽/오른쪽 펜/바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 앞쪽/뒤쪽 방향으로 회전합니다.',\n            hamster_s_turn_unit_with_radius_in_direction:\n                '왼쪽/오른쪽 펜이 입력한 반지름의 원을 왼쪽/오른쪽에 그리면서 입력한 각도(도)/시간(초)/펄스만큼 앞쪽/뒤쪽 방향으로 회전합니다.',\n            hamster_s_change_both_wheels_by:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            hamster_s_set_both_wheels_to:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            hamster_s_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            hamster_s_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            hamster_s_follow_line_using:\n                '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n            hamster_s_follow_line_until:\n                '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n            hamster_s_set_following_speed_to:\n                '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            hamster_s_set_following_gain_to:\n                '선을 따라 이동하는 방향 변화량(1 ~ 8)을 설정합니다. 숫자가 클수록 급커브를 잘 따라가지만 직선에서 좌우로 더 흔들립니다.',\n            hamster_s_stop: '양쪽 바퀴를 정지합니다.',\n            hamster_s_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n            hamster_s_pick_led: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n            hamster_s_change_led_by_rgb:\n                '왼쪽/오른쪽/양쪽 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            hamster_s_set_led_to_rgb:\n                '왼쪽/오른쪽/양쪽 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            hamster_s_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n            hamster_s_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            hamster_s_play_sound_times_until_done:\n                '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            hamster_s_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            hamster_s_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n            hamster_s_clear_sound: '소리를 끕니다.',\n            hamster_s_play_note: '선택한 계이름과 옥타브의 음을 소리 냅니다.',\n            hamster_s_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            hamster_s_rest_for: '입력한 박자만큼 쉽니다.',\n            hamster_s_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            hamster_s_set_tempo_to:\n                '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n            hamster_s_set_port_to:\n                '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n            hamster_s_change_output_by:\n                '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n            hamster_s_set_output_to:\n                '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n            hamster_s_gripper: '집게를 열거나 닫습니다.',\n            hamster_s_release_gripper: '집게의 전원을 끄고 자유롭게 움직일 수 있도록 합니다.',\n            hamster_s_write_serial: '시리얼 통신으로 글자를 전송합니다.',\n            hamster_s_read_serial_until: '시리얼 통신으로 받은 글자를 읽습니다.',\n            hamster_s_set_serial_rate_to: '시리얼 통신의 속도를 설정합니다.',\n        },\n        Blocks: {\n            hamster_s_color_black: '검은색',\n            hamster_s_color_blue: '파란색',\n            hamster_s_color_green: '초록색',\n            hamster_s_color_orange: '주황색',\n            hamster_s_color_purple: '자주색',\n            hamster_s_color_red: '빨간색',\n            hamster_s_color_sky_blue: '하늘색',\n            hamster_s_color_violet: '보라색',\n            hamster_s_color_white: '하얀색',\n            hamster_s_color_yellow: '노란색',\n            hamster_s_left: '왼쪽',\n            hamster_s_right: '오른쪽',\n            hamster_s_both: '양쪽',\n            hamster_s_note_c: '도',\n            hamster_s_note_c_sharp: '도♯(레♭)',\n            hamster_s_note_d: '레',\n            hamster_s_note_d_sharp: '레♯(미♭)',\n            hamster_s_note_e: '미',\n            hamster_s_note_f: '파',\n            hamster_s_note_f_sharp: '파♯(솔♭)',\n            hamster_s_note_g: '솔',\n            hamster_s_note_g_sharp: '솔♯(라♭)',\n            hamster_s_note_a: '라',\n            hamster_s_note_a_sharp: '라♯(시♭)',\n            hamster_s_note_b: '시',\n            hamster_s_port_a: 'A',\n            hamster_s_port_b: 'B',\n            hamster_s_port_ab: 'A와 B',\n            hamster_s_tilt_forward: '앞으로 기울임',\n            hamster_s_tilt_backward: '뒤로 기울임',\n            hamster_s_tilt_left: '왼쪽으로 기울임',\n            hamster_s_tilt_right: '오른쪽으로 기울임',\n            hamster_s_tilt_flip: '거꾸로 뒤집음',\n            hamster_s_tilt_not: '기울이지 않음',\n            hamster_s_tap: '두드림',\n            hamster_s_free_fall: '자유 낙하',\n            hamster_s_battery_normal: '배터리 정상',\n            hamster_s_battery_low: '배터리 부족',\n            hamster_s_battery_empty: '배터리 없음',\n            hamster_s_forward: '앞쪽',\n            hamster_s_backward: '뒤쪽',\n            hamster_s_front: '앞쪽',\n            hamster_s_rear: '뒤쪽',\n            hamster_s_left_pen: '왼쪽 펜',\n            hamster_s_right_pen: '오른쪽 펜',\n            hamster_s_left_wheel: '왼쪽 바퀴',\n            hamster_s_right_wheel: '오른쪽 바퀴',\n            hamster_s_robot: '로봇',\n            hamster_s_gain_default: '기본 값',\n            hamster_s_sensor_acceleration_x: 'x축 가속도',\n            hamster_s_sensor_acceleration_y: 'y축 가속도',\n            hamster_s_sensor_acceleration_z: 'z축 가속도',\n            hamster_s_sensor_input_a: '입력 A',\n            hamster_s_sensor_input_b: '입력 B',\n            hamster_s_sensor_left_floor: '왼쪽 바닥 센서',\n            hamster_s_sensor_left_proximity: '왼쪽 근접 센서',\n            hamster_s_sensor_light: '밝기',\n            hamster_s_sensor_right_floor: '오른쪽 바닥 센서',\n            hamster_s_sensor_right_proximity: '오른쪽 근접 센서',\n            hamster_s_sensor_signal_strength: '신호 세기',\n            hamster_s_sensor_temperature: '온도',\n            hamster_s_buzzer: '버저',\n            hamster_s_left_led: '왼쪽 LED',\n            hamster_s_left_wheel: '왼쪽 바퀴',\n            hamster_s_note: '음표',\n            hamster_s_output_a: '출력 A',\n            hamster_s_output_b: '출력 B',\n            hamster_s_right_led: '오른쪽 LED',\n            hamster_s_right_wheel: '오른쪽 바퀴',\n            hamster_s_sound_angry: '화남',\n            hamster_s_sound_beep: '삐',\n            hamster_s_sound_birthday: '생일',\n            hamster_s_sound_chop: '쩝',\n            hamster_s_sound_dibidibidip: '디비디비딥',\n            hamster_s_sound_engine: '엔진',\n            hamster_s_sound_good_job: '잘 했어요',\n            hamster_s_sound_happy: '행복',\n            hamster_s_sound_march: '행진',\n            hamster_s_sound_noise: '지지직',\n            hamster_s_sound_random_beep: '무작위 삐',\n            hamster_s_sound_robot: '로봇',\n            hamster_s_sound_sad: '슬픔',\n            hamster_s_sound_siren: '사이렌',\n            hamster_s_sound_sleep: '졸림',\n            hamster_s_unit_cm: 'cm',\n            hamster_s_unit_deg: '도',\n            hamster_s_unit_pulse: '펄스',\n            hamster_s_unit_sec: '초',\n            hamster_s_analog_input: '아날로그 입력',\n            hamster_s_digital_input: '디지털 입력',\n            hamster_s_digital_input_pull_down: '디지털 입력 (풀다운)',\n            hamster_s_digital_input_pull_up: '디지털 입력 (풀업)',\n            hamster_s_digital_output: '디지털 출력',\n            hamster_s_pwm_output: 'PWM 출력',\n            hamster_s_servo_output: '서보 출력',\n            hamster_s_voltage_input: '전압 입력',\n            hamster_s_open_gripper: '열기',\n            hamster_s_close_gripper: '닫기',\n            hamster_s_serial_string: '글자',\n            hamster_s_serial_string_line: '글자 한 줄',\n            hamster_s_serial_all: '모두',\n            hamster_s_serial_until_new_line: '줄 바꿈까지',\n            hamster_s_serial_until_comma: ',(쉼표)까지',\n            hamster_s_serial_until_colon: ':(쌍점)까지',\n            hamster_s_serial_until_dollar: '$까지',\n            hamster_s_serial_until_sharp: '#까지',\n            hamster_s_serial_input: '시리얼 입력',\n        },\n    },\n    en: {\n        template: {\n            hamster_s_hand_found: 'hand found?',\n            hamster_s_boolean: '%1?',\n            hamster_s_value: '%1',\n            hamster_s_move_forward_once: 'move forward once on board %1',\n            hamster_s_turn_once: 'turn %1 once on board %2',\n            hamster_s_move_forward_unit: 'move forward %1 %2 %3',\n            hamster_s_move_backward_unit: 'move backward %1 %2 %3',\n            hamster_s_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            hamster_s_pivot_around_unit_in_direction: 'pivot around %1 %2 %3 in %4 direction %5',\n            hamster_s_turn_unit_with_radius_in_direction:\n                '%1 turn %2 %3 %4 with radius %5 cm in %6 direction %7',\n            hamster_s_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            hamster_s_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            hamster_s_change_wheel_by: 'change %1 wheel by %2 %3',\n            hamster_s_set_wheel_to: 'set %1 wheel to %2 %3',\n            hamster_s_follow_line_using: 'follow %1 line using %2 floor sensor %3',\n            hamster_s_follow_line_until: 'follow %1 line until %2 intersection %3',\n            hamster_s_set_following_speed_to: 'set following speed to %1 %2',\n            hamster_s_set_following_gain_to: 'set following directional variation to %1 %2',\n            hamster_s_stop: 'stop %1',\n            hamster_s_set_led_to: 'set %1 led to %2 %3',\n            hamster_s_pick_led: 'set %1 led to %2 %3',\n            hamster_s_change_led_by_rgb: 'change %1 led by r: %2 g: %3 b: %4 %5',\n            hamster_s_set_led_to_rgb: 'set %1 led to r: %2 g: %3 b: %4 %5',\n            hamster_s_clear_led: 'clear %1 led %2',\n            hamster_s_play_sound_times: 'play sound %1 %2 times %3',\n            hamster_s_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            hamster_s_change_buzzer_by: 'change buzzer by %1 %2',\n            hamster_s_set_buzzer_to: 'set buzzer to %1 %2',\n            hamster_s_clear_sound: 'clear sound %1',\n            hamster_s_play_note: 'play note %1 %2 %3',\n            hamster_s_play_note_for: 'play note %1 %2 for %3 beats %4',\n            hamster_s_rest_for: 'rest for %1 beats %2',\n            hamster_s_change_tempo_by: 'change tempo by %1 %2',\n            hamster_s_set_tempo_to: 'set tempo to %1 bpm %2',\n            hamster_s_set_port_to: 'set port %1 to %2 %3',\n            hamster_s_change_output_by: 'change output %1 by %2 %3',\n            hamster_s_set_output_to: 'set output %1 to %2 %3',\n            hamster_s_gripper: '%1 gripper %2',\n            hamster_s_release_gripper: 'release gripper %1',\n            hamster_s_write_serial: 'write %1 %2 to serial %3',\n            hamster_s_read_serial_until: 'read serial %1 %2',\n            hamster_s_set_serial_rate_to: 'set serial rate to %1 Bd %2',\n        },\n        Helper: {\n            hamster_s_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            hamster_s_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            hamster_s_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n            hamster_s_move_forward_once: 'Moves one space forward on the board.',\n            hamster_s_turn_once: 'Turns left/right 90 degrees on the board.',\n            hamster_s_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            hamster_s_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            hamster_s_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            hamster_s_pivot_around_unit_in_direction:\n                'Pivots around the left/right pen/wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            hamster_s_turn_unit_with_radius_in_direction:\n                'Turns left/right so that the left/right pen draws the circle of the entered radius in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            hamster_s_change_both_wheels_by:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            hamster_s_set_both_wheels_to:\n                'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            hamster_s_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            hamster_s_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            hamster_s_follow_line_using:\n                'Moves along the black/white line by using the left/right/both floor sensors.',\n            hamster_s_follow_line_until:\n                'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n            hamster_s_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            hamster_s_set_following_gain_to:\n                'Sets the directional variation (1 to 8) 선을 따라 이동하는 방향 변화량(1 ~ 8)을 설정합니다. 숫자가 클수록 급커브를 잘 따라가지만 직선에서 좌우로 더 흔들립니다.',\n            hamster_s_stop: 'Stops both wheels.',\n            hamster_s_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n            hamster_s_pick_led: 'Turns left/right/both LEDs to the selected color.',\n            hamster_s_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of left/right/both LEDs, respectively.',\n            hamster_s_set_led_to_rgb:\n                'Sets the R, G, B values of left/right/both LEDs to the entered values.',\n            hamster_s_clear_led: 'Turns off the left/right/both LEDs.',\n            hamster_s_play_sound_times: 'Plays the selected sound as many times as entered.',\n            hamster_s_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            hamster_s_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            hamster_s_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            hamster_s_clear_sound: 'Turns off sound.',\n            hamster_s_play_note: 'It sounds the selected tone and octave.',\n            hamster_s_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            hamster_s_rest_for: 'Rests as much as the beat you entered.',\n            hamster_s_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            hamster_s_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            hamster_s_set_port_to:\n                'Sets the io mode of the selected external port to the selected mode.',\n            hamster_s_change_output_by:\n                'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            hamster_s_set_output_to:\n                'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            hamster_s_gripper: 'Opens or closes the gripper.',\n            hamster_s_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            hamster_s_write_serial: 'Sends strings via serial communication.',\n            hamster_s_read_serial_until: 'Read the strings received by serial communication.',\n            hamster_s_set_serial_rate_to: 'Sets the speed of serial communication.',\n        },\n        Blocks: {\n            hamster_s_color_black: 'black',\n            hamster_s_color_blue: 'blue',\n            hamster_s_color_green: 'green',\n            hamster_s_color_orange: 'orange',\n            hamster_s_color_purple: 'purple',\n            hamster_s_color_red: 'red',\n            hamster_s_color_sky_blue: 'sky blue',\n            hamster_s_color_violet: 'violet',\n            hamster_s_color_white: 'white',\n            hamster_s_color_yellow: 'yellow',\n            hamster_s_left: 'left',\n            hamster_s_right: 'right',\n            hamster_s_both: 'both',\n            hamster_s_note_c: 'C',\n            hamster_s_note_c_sharp: 'C♯(D♭)',\n            hamster_s_note_d: 'D',\n            hamster_s_note_d_sharp: 'D♯(E♭)',\n            hamster_s_note_e: 'E',\n            hamster_s_note_f: 'F',\n            hamster_s_note_f_sharp: 'F♯(G♭)',\n            hamster_s_note_g: 'G',\n            hamster_s_note_g_sharp: 'G♯(A♭)',\n            hamster_s_note_a: 'A',\n            hamster_s_note_a_sharp: 'A♯(B♭)',\n            hamster_s_note_b: 'B',\n            hamster_s_port_a: 'A',\n            hamster_s_port_b: 'B',\n            hamster_s_port_ab: 'A and B',\n            hamster_s_tilt_forward: 'tilt forward',\n            hamster_s_tilt_backward: 'tilt backward',\n            hamster_s_tilt_left: 'tilt left',\n            hamster_s_tilt_right: 'tilt right',\n            hamster_s_tilt_flip: 'tilt flip',\n            hamster_s_tilt_not: 'not tilt',\n            hamster_s_tap: 'tap',\n            hamster_s_free_fall: 'free fall',\n            hamster_s_battery_normal: 'battery normal',\n            hamster_s_battery_low: 'battery low',\n            hamster_s_battery_empty: 'battery empty',\n            hamster_s_forward: 'forward',\n            hamster_s_backward: 'backward',\n            hamster_s_front: 'front',\n            hamster_s_rear: 'rear',\n            hamster_s_left_pen: 'left pen',\n            hamster_s_right_pen: 'right pen',\n            hamster_s_left_wheel: 'left wheel',\n            hamster_s_right_wheel: 'right wheel',\n            hamster_s_robot: 'robot',\n            hamster_s_gain_default: 'default',\n            hamster_s_sensor_acceleration_x: 'x acceleration',\n            hamster_s_sensor_acceleration_y: 'y acceleration',\n            hamster_s_sensor_acceleration_z: 'z acceleration',\n            hamster_s_sensor_input_a: 'input A',\n            hamster_s_sensor_input_b: 'input B',\n            hamster_s_sensor_left_floor: 'left floor',\n            hamster_s_sensor_left_proximity: 'left proximity',\n            hamster_s_sensor_light: 'light',\n            hamster_s_sensor_right_floor: 'right floor',\n            hamster_s_sensor_right_proximity: 'right proximity',\n            hamster_s_sensor_signal_strength: 'signal strength',\n            hamster_s_sensor_temperature: 'temperature',\n            hamster_s_buzzer: 'buzzer',\n            hamster_s_left_led: 'left LED',\n            hamster_s_left_wheel: 'left wheel',\n            hamster_s_note: 'note',\n            hamster_s_output_a: 'output A',\n            hamster_s_output_b: 'output B',\n            hamster_s_right_led: 'right LED',\n            hamster_s_right_wheel: 'right wheel',\n            hamster_s_sound_angry: 'angry',\n            hamster_s_sound_beep: 'beep',\n            hamster_s_sound_birthday: 'birthday',\n            hamster_s_sound_chop: 'chop',\n            hamster_s_sound_dibidibidip: 'dibidibidip',\n            hamster_s_sound_engine: 'engine',\n            hamster_s_sound_good_job: 'good job',\n            hamster_s_sound_happy: 'happy',\n            hamster_s_sound_march: 'march',\n            hamster_s_sound_noise: 'noise',\n            hamster_s_sound_random_beep: 'random beep',\n            hamster_s_sound_robot: 'robot',\n            hamster_s_sound_sad: 'sad',\n            hamster_s_sound_siren: 'siren',\n            hamster_s_sound_sleep: 'sleep',\n            hamster_s_unit_cm: 'cm',\n            hamster_s_unit_deg: 'degrees',\n            hamster_s_unit_pulse: 'pulses',\n            hamster_s_unit_sec: 'seconds',\n            hamster_s_analog_input: 'analog input',\n            hamster_s_digital_input: 'digital input',\n            hamster_s_digital_input_pull_down: 'digital input (pull down)',\n            hamster_s_digital_input_pull_up: 'digital input (pull up)',\n            hamster_s_digital_output: 'digital output',\n            hamster_s_pwm_output: 'pwm output',\n            hamster_s_servo_output: 'servo output',\n            hamster_s_voltage_input: 'voltage input',\n            hamster_s_open_gripper: 'open',\n            hamster_s_close_gripper: 'close',\n            hamster_s_serial_string: 'string',\n            hamster_s_serial_string_line: 'string line',\n            hamster_s_serial_all: 'all',\n            hamster_s_serial_until_new_line: 'until new line',\n            hamster_s_serial_until_comma: 'until ,(comma)',\n            hamster_s_serial_until_colon: 'until :(colon)',\n            hamster_s_serial_until_dollar: 'until $',\n            hamster_s_serial_until_sharp: 'until #',\n            hamster_s_serial_input: 'serial input',\n        },\n    },\n    jp: {\n        template: {\n            hamster_s_hand_found: '手を見つけたか?',\n            hamster_s_boolean: '%1?',\n            hamster_s_value: '%1',\n            hamster_s_move_forward_once: 'ボード板上で前へ動かす %1',\n            hamster_s_turn_once: 'ボード板上で%1に回す %2',\n            hamster_s_move_forward_unit: '前へ%1%2動かす %3',\n            hamster_s_move_backward_unit: '後ろへ%1%2動かす %3',\n            hamster_s_turn_unit_in_place: '所定位置で%1に%2%3回す %4',\n            hamster_s_pivot_around_unit_in_direction: '%1を中心に%2%3%4方向に回す %5',\n            hamster_s_turn_unit_with_radius_in_direction: '%1%2に%3%4半径%5cmを%6方向に回す %7',\n            hamster_s_change_both_wheels_by: '左車輪を%1右車輪を%2ずつ変える %3',\n            hamster_s_set_both_wheels_to: '左車輪を%1右車輪を%2にする %3',\n            hamster_s_change_wheel_by: '%1車輪を%2ずつ変える %3',\n            hamster_s_set_wheel_to: '%1車輪を%2にする %3',\n            hamster_s_follow_line_using: '%1線を%2フロアセンサーで追従する %3',\n            hamster_s_follow_line_until: '%1線を追従して%2交差点まで動かす %3',\n            hamster_s_set_following_speed_to: '線を追従する速度を%1にする %2',\n            hamster_s_set_following_gain_to: '線を追従する方向変化量を%1にする %2',\n            hamster_s_stop: '停止する %1',\n            hamster_s_set_led_to: '%1LEDを%2にする %3',\n            hamster_s_pick_led: '%1LEDを%2にする %3',\n            hamster_s_change_led_by_rgb: '%1LEDをR:%2G:%3B:%4ずつ変える %5',\n            hamster_s_set_led_to_rgb: '%1LEDをR:%2G:%3B:%4にする %5',\n            hamster_s_clear_led: '%1LEDをオフ %2',\n            hamster_s_play_sound_times: '%1音を%2回鳴らす %3',\n            hamster_s_play_sound_times_until_done: '終わるまで%1音を%2回鳴らす %3',\n            hamster_s_change_buzzer_by: 'ブザー音を%1ずつ変える %2',\n            hamster_s_set_buzzer_to: 'ブザー音を%1にする %2',\n            hamster_s_clear_sound: '音を止める %1',\n            hamster_s_play_note: '%1%2音を鳴らす %3',\n            hamster_s_play_note_for: '%1%2音を%3拍鳴らす %4',\n            hamster_s_rest_for: '%1拍休む %2',\n            hamster_s_change_tempo_by: 'テンポを%1ずつ変える %2',\n            hamster_s_set_tempo_to: 'テンポを%1BPMにする %2',\n            hamster_s_set_port_to: 'ポート%1を%2にする %3',\n            hamster_s_change_output_by: '出力%1を%2ずつ変える %3',\n            hamster_s_set_output_to: '出力%1を%2にする %3',\n            hamster_s_gripper: 'グリッパを%1 %2',\n            hamster_s_release_gripper: 'グリッパをオフ %1',\n            hamster_s_write_serial: 'シリアルに%1%2を書き出す %3',\n            hamster_s_read_serial_until: 'シリアルを%1読み取る %2',\n            hamster_s_set_serial_rate_to: 'シリアル速度を%1Bdにする %2',\n        },\n        Helper: {\n            hamster_s_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            hamster_s_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            hamster_s_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n            hamster_s_move_forward_once: 'Moves one space forward on the board.',\n            hamster_s_turn_once: 'Turns left/right 90 degrees on the board.',\n            hamster_s_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            hamster_s_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            hamster_s_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            hamster_s_pivot_around_unit_in_direction:\n                'Pivots around the left/right pen/wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            hamster_s_turn_unit_with_radius_in_direction:\n                'Turns left/right so that the left/right pen draws the circle of the entered radius in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            hamster_s_change_both_wheels_by:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            hamster_s_set_both_wheels_to:\n                'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            hamster_s_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            hamster_s_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            hamster_s_follow_line_using:\n                'Moves along the black/white line by using the left/right/both floor sensors.',\n            hamster_s_follow_line_until:\n                'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n            hamster_s_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            hamster_s_set_following_gain_to:\n                'Sets the directional variation (1 to 8) 선을 따라 이동하는 방향 변화량(1 ~ 8)을 설정합니다. 숫자가 클수록 급커브를 잘 따라가지만 직선에서 좌우로 더 흔들립니다.',\n            hamster_s_stop: 'Stops both wheels.',\n            hamster_s_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n            hamster_s_pick_led: 'Turns left/right/both LEDs to the selected color.',\n            hamster_s_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of left/right/both LEDs, respectively.',\n            hamster_s_set_led_to_rgb:\n                'Sets the R, G, B values of left/right/both LEDs to the entered values.',\n            hamster_s_clear_led: 'Turns off the left/right/both LEDs.',\n            hamster_s_play_sound_times: 'Plays the selected sound as many times as entered.',\n            hamster_s_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            hamster_s_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            hamster_s_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            hamster_s_clear_sound: 'Turns off sound.',\n            hamster_s_play_note: 'It sounds the selected tone and octave.',\n            hamster_s_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            hamster_s_rest_for: 'Rests as much as the beat you entered.',\n            hamster_s_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            hamster_s_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            hamster_s_set_port_to:\n                'Sets the io mode of the selected external port to the selected mode.',\n            hamster_s_change_output_by:\n                'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            hamster_s_set_output_to:\n                'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            hamster_s_gripper: 'Opens or closes the gripper.',\n            hamster_s_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            hamster_s_write_serial: 'Sends strings via serial communication.',\n            hamster_s_read_serial_until: 'Read the strings received by serial communication.',\n            hamster_s_set_serial_rate_to: 'Sets the speed of serial communication.',\n        },\n        Blocks: {\n            hamster_s_color_black: '黒',\n            hamster_s_color_blue: '青',\n            hamster_s_color_green: '緑',\n            hamster_s_color_orange: 'オレンジ',\n            hamster_s_color_purple: '紫',\n            hamster_s_color_red: '赤',\n            hamster_s_color_sky_blue: '水色',\n            hamster_s_color_violet: '赤紫',\n            hamster_s_color_white: '白',\n            hamster_s_color_yellow: '黄色',\n            hamster_s_left: '左',\n            hamster_s_right: '右',\n            hamster_s_both: '両方',\n            hamster_s_note_c: 'ド',\n            hamster_s_note_c_sharp: 'ド♯(レ♭)',\n            hamster_s_note_d: 'レ',\n            hamster_s_note_d_sharp: 'レ♯(ミ♭)',\n            hamster_s_note_e: 'ミ',\n            hamster_s_note_f: 'ファ',\n            hamster_s_note_f_sharp: 'ファ♯(ソ♭)',\n            hamster_s_note_g: 'ソ',\n            hamster_s_note_g_sharp: 'ソ♯(ラ♭)',\n            hamster_s_note_a: 'ラ',\n            hamster_s_note_a_sharp: 'ラ♯(シ♭)',\n            hamster_s_note_b: 'シ',\n            hamster_s_port_a: 'A',\n            hamster_s_port_b: 'B',\n            hamster_s_port_ab: 'AとB',\n            hamster_s_tilt_forward: '前に傾けたか',\n            hamster_s_tilt_backward: '後に傾けたか',\n            hamster_s_tilt_left: '左に傾けたか',\n            hamster_s_tilt_right: '右に傾けたか',\n            hamster_s_tilt_flip: '上下裏返したか',\n            hamster_s_tilt_not: '傾けなかったか',\n            hamster_s_tap: '叩いたか',\n            hamster_s_free_fall: '自由落下したか',\n            hamster_s_battery_normal: '電池が正常か',\n            hamster_s_battery_low: '電池が足りないか',\n            hamster_s_battery_empty: '電池がないか',\n            hamster_s_forward: '前',\n            hamster_s_backward: '後',\n            hamster_s_front: '前',\n            hamster_s_rear: '後',\n            hamster_s_left_pen: '左ペン',\n            hamster_s_right_pen: '右ペン',\n            hamster_s_left_wheel: '左車輪',\n            hamster_s_right_wheel: '右車輪',\n            hamster_s_robot: 'ロボット',\n            hamster_s_gain_default: '基本値',\n            hamster_s_sensor_acceleration_x: '前後の速さ',\n            hamster_s_sensor_acceleration_y: '左右の速さ',\n            hamster_s_sensor_acceleration_z: '上下の速さ',\n            hamster_s_sensor_input_a: '入力A',\n            hamster_s_sensor_input_b: '入力B',\n            hamster_s_sensor_left_floor: '左床センサー',\n            hamster_s_sensor_left_proximity: '左近接センサー',\n            hamster_s_sensor_light: '照度',\n            hamster_s_sensor_right_floor: '右床センサー',\n            hamster_s_sensor_right_proximity: '右近接センサー',\n            hamster_s_sensor_signal_strength: '信号強度',\n            hamster_s_sensor_temperature: '温度',\n            hamster_s_buzzer: 'ブーザー',\n            hamster_s_left_led: '左LED',\n            hamster_s_left_wheel: '左車輪',\n            hamster_s_note: '音符',\n            hamster_s_output_a: '出力A',\n            hamster_s_output_b: '出力B',\n            hamster_s_right_led: '右LED',\n            hamster_s_right_wheel: '右車輪',\n            hamster_s_sound_angry: '怒った',\n            hamster_s_sound_beep: 'ビープ音',\n            hamster_s_sound_birthday: '誕生日',\n            hamster_s_sound_chop: 'チョップ',\n            hamster_s_sound_dibidibidip: 'ディビディビディップ',\n            hamster_s_sound_engine: 'エンジン',\n            hamster_s_sound_good_job: 'よくできました',\n            hamster_s_sound_happy: '幸福',\n            hamster_s_sound_march: '行進',\n            hamster_s_sound_noise: 'ノイズ',\n            hamster_s_sound_random_beep: 'ビープ音のどれか',\n            hamster_s_sound_robot: 'ロボット',\n            hamster_s_sound_sad: '悲しみ',\n            hamster_s_sound_siren: 'サイレン',\n            hamster_s_sound_sleep: '睡眠',\n            hamster_s_unit_cm: 'cm',\n            hamster_s_unit_deg: '°',\n            hamster_s_unit_pulse: 'パルス',\n            hamster_s_unit_sec: '秒',\n            hamster_s_analog_input: 'アナログ入力',\n            hamster_s_digital_input: 'デジタル入力',\n            hamster_s_digital_input_pull_down: 'デジタル入力 (プルダウン)',\n            hamster_s_digital_input_pull_up: 'デジタル入力 (プルアップ)',\n            hamster_s_digital_output: 'デジタル出力',\n            hamster_s_pwm_output: 'PWM出力',\n            hamster_s_servo_output: 'サーボ出力',\n            hamster_s_voltage_input: '電圧入力',\n            hamster_s_open_gripper: '開く',\n            hamster_s_close_gripper: '閉める',\n            hamster_s_serial_string: '文字列',\n            hamster_s_serial_string_line: '文字列1行',\n            hamster_s_serial_all: '全部',\n            hamster_s_serial_until_new_line: '改行まで',\n            hamster_s_serial_until_comma: '、(読点)まで',\n            hamster_s_serial_until_colon: '：(コロン)まで',\n            hamster_s_serial_until_dollar: '$まで',\n            hamster_s_serial_until_sharp: '#まで',\n            hamster_s_serial_input: 'シリアル入力',\n        },\n    },\n    vn: {\n        template: {\n            hamster_s_hand_found: 'hand found?',\n            hamster_s_boolean: '%1?',\n            hamster_s_value: '%1',\n            hamster_s_move_forward_once: 'move forward once on board %1',\n            hamster_s_turn_once: 'turn %1 once on board %2',\n            hamster_s_move_forward_unit: 'move forward %1 %2 %3',\n            hamster_s_move_backward_unit: 'move backward %1 %2 %3',\n            hamster_s_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            hamster_s_pivot_around_unit_in_direction: 'pivot around %1 %2 %3 in %4 direction %5',\n            hamster_s_turn_unit_with_radius_in_direction:\n                '%1 turn %2 %3 %4 with radius %5 cm in %6 direction %7',\n            hamster_s_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            hamster_s_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            hamster_s_change_wheel_by: 'change %1 wheel by %2 %3',\n            hamster_s_set_wheel_to: 'set %1 wheel to %2 %3',\n            hamster_s_follow_line_using: 'follow %1 line using %2 floor sensor %3',\n            hamster_s_follow_line_until: 'follow %1 line until %2 intersection %3',\n            hamster_s_set_following_speed_to: 'set following speed to %1 %2',\n            hamster_s_set_following_gain_to: 'set following directional variation to %1 %2',\n            hamster_s_stop: 'stop %1',\n            hamster_s_set_led_to: 'set %1 led to %2 %3',\n            hamster_s_pick_led: 'set %1 led to %2 %3',\n            hamster_s_change_led_by_rgb: 'change %1 led by r: %2 g: %3 b: %4 %5',\n            hamster_s_set_led_to_rgb: 'set %1 led to r: %2 g: %3 b: %4 %5',\n            hamster_s_clear_led: 'clear %1 led %2',\n            hamster_s_play_sound_times: 'play sound %1 %2 times %3',\n            hamster_s_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            hamster_s_change_buzzer_by: 'change buzzer by %1 %2',\n            hamster_s_set_buzzer_to: 'set buzzer to %1 %2',\n            hamster_s_clear_sound: 'clear sound %1',\n            hamster_s_play_note: 'play note %1 %2 %3',\n            hamster_s_play_note_for: 'play note %1 %2 for %3 beats %4',\n            hamster_s_rest_for: 'rest for %1 beats %2',\n            hamster_s_change_tempo_by: 'change tempo by %1 %2',\n            hamster_s_set_tempo_to: 'set tempo to %1 bpm %2',\n            hamster_s_set_port_to: 'set port %1 to %2 %3',\n            hamster_s_change_output_by: 'change output %1 by %2 %3',\n            hamster_s_set_output_to: 'set output %1 to %2 %3',\n            hamster_s_gripper: '%1 gripper %2',\n            hamster_s_release_gripper: 'release gripper %1',\n            hamster_s_write_serial: 'write %1 %2 to serial %3',\n            hamster_s_read_serial_until: 'read serial %1 %2',\n            hamster_s_set_serial_rate_to: 'set serial rate to %1 Bd %2',\n        },\n        Helper: {\n            hamster_s_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            hamster_s_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            hamster_s_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n            hamster_s_move_forward_once: 'Moves one space forward on the board.',\n            hamster_s_turn_once: 'Turns left/right 90 degrees on the board.',\n            hamster_s_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            hamster_s_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            hamster_s_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            hamster_s_pivot_around_unit_in_direction:\n                'Pivots around the left/right pen/wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            hamster_s_turn_unit_with_radius_in_direction:\n                'Turns left/right so that the left/right pen draws the circle of the entered radius in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            hamster_s_change_both_wheels_by:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            hamster_s_set_both_wheels_to:\n                'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            hamster_s_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            hamster_s_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            hamster_s_follow_line_using:\n                'Moves along the black/white line by using the left/right/both floor sensors.',\n            hamster_s_follow_line_until:\n                'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n            hamster_s_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            hamster_s_set_following_gain_to:\n                'Sets the directional variation (1 to 8) 선을 따라 이동하는 방향 변화량(1 ~ 8)을 설정합니다. 숫자가 클수록 급커브를 잘 따라가지만 직선에서 좌우로 더 흔들립니다.',\n            hamster_s_stop: 'Stops both wheels.',\n            hamster_s_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n            hamster_s_pick_led: 'Turns left/right/both LEDs to the selected color.',\n            hamster_s_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of left/right/both LEDs, respectively.',\n            hamster_s_set_led_to_rgb:\n                'Sets the R, G, B values of left/right/both LEDs to the entered values.',\n            hamster_s_clear_led: 'Turns off the left/right/both LEDs.',\n            hamster_s_play_sound_times: 'Plays the selected sound as many times as entered.',\n            hamster_s_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            hamster_s_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            hamster_s_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            hamster_s_clear_sound: 'Turns off sound.',\n            hamster_s_play_note: 'It sounds the selected tone and octave.',\n            hamster_s_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            hamster_s_rest_for: 'Rests as much as the beat you entered.',\n            hamster_s_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            hamster_s_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            hamster_s_set_port_to:\n                'Sets the io mode of the selected external port to the selected mode.',\n            hamster_s_change_output_by:\n                'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            hamster_s_set_output_to:\n                'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            hamster_s_gripper: 'Opens or closes the gripper.',\n            hamster_s_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            hamster_s_write_serial: 'Sends strings via serial communication.',\n            hamster_s_read_serial_until: 'Read the strings received by serial communication.',\n            hamster_s_set_serial_rate_to: 'Sets the speed of serial communication.',\n        },\n        Blocks: {\n            hamster_s_color_black: 'black',\n            hamster_s_color_blue: 'blue',\n            hamster_s_color_green: 'green',\n            hamster_s_color_orange: 'orange',\n            hamster_s_color_purple: 'purple',\n            hamster_s_color_red: 'red',\n            hamster_s_color_sky_blue: 'sky blue',\n            hamster_s_color_violet: 'violet',\n            hamster_s_color_white: 'white',\n            hamster_s_color_yellow: 'yellow',\n            hamster_s_left: 'left',\n            hamster_s_right: 'right',\n            hamster_s_both: 'both',\n            hamster_s_note_c: 'C',\n            hamster_s_note_c_sharp: 'C♯(D♭)',\n            hamster_s_note_d: 'D',\n            hamster_s_note_d_sharp: 'D♯(E♭)',\n            hamster_s_note_e: 'E',\n            hamster_s_note_f: 'F',\n            hamster_s_note_f_sharp: 'F♯(G♭)',\n            hamster_s_note_g: 'G',\n            hamster_s_note_g_sharp: 'G♯(A♭)',\n            hamster_s_note_a: 'A',\n            hamster_s_note_a_sharp: 'A♯(B♭)',\n            hamster_s_note_b: 'B',\n            hamster_s_port_a: 'A',\n            hamster_s_port_b: 'B',\n            hamster_s_port_ab: 'A and B',\n            hamster_s_tilt_forward: 'tilt forward',\n            hamster_s_tilt_backward: 'tilt backward',\n            hamster_s_tilt_left: 'tilt left',\n            hamster_s_tilt_right: 'tilt right',\n            hamster_s_tilt_flip: 'tilt flip',\n            hamster_s_tilt_not: 'not tilt',\n            hamster_s_tap: 'tap',\n            hamster_s_free_fall: 'free fall',\n            hamster_s_battery_normal: 'battery normal',\n            hamster_s_battery_low: 'battery low',\n            hamster_s_battery_empty: 'battery empty',\n            hamster_s_forward: 'forward',\n            hamster_s_backward: 'backward',\n            hamster_s_front: 'front',\n            hamster_s_rear: 'rear',\n            hamster_s_left_pen: 'left pen',\n            hamster_s_right_pen: 'right pen',\n            hamster_s_left_wheel: 'left wheel',\n            hamster_s_right_wheel: 'right wheel',\n            hamster_s_robot: 'robot',\n            hamster_s_gain_default: 'default',\n            hamster_s_sensor_acceleration_x: 'x acceleration',\n            hamster_s_sensor_acceleration_y: 'y acceleration',\n            hamster_s_sensor_acceleration_z: 'z acceleration',\n            hamster_s_sensor_input_a: 'input A',\n            hamster_s_sensor_input_b: 'input B',\n            hamster_s_sensor_left_floor: 'left floor',\n            hamster_s_sensor_left_proximity: 'left proximity',\n            hamster_s_sensor_light: 'light',\n            hamster_s_sensor_right_floor: 'right floor',\n            hamster_s_sensor_right_proximity: 'right proximity',\n            hamster_s_sensor_signal_strength: 'signal strength',\n            hamster_s_sensor_temperature: 'temperature',\n            hamster_s_buzzer: 'buzzer',\n            hamster_s_left_led: 'left LED',\n            hamster_s_left_wheel: 'left wheel',\n            hamster_s_note: 'note',\n            hamster_s_output_a: 'output A',\n            hamster_s_output_b: 'output B',\n            hamster_s_right_led: 'right LED',\n            hamster_s_right_wheel: 'right wheel',\n            hamster_s_sound_angry: 'angry',\n            hamster_s_sound_beep: 'beep',\n            hamster_s_sound_birthday: 'birthday',\n            hamster_s_sound_chop: 'chop',\n            hamster_s_sound_dibidibidip: 'dibidibidip',\n            hamster_s_sound_engine: 'engine',\n            hamster_s_sound_good_job: 'good job',\n            hamster_s_sound_happy: 'happy',\n            hamster_s_sound_march: 'march',\n            hamster_s_sound_noise: 'noise',\n            hamster_s_sound_random_beep: 'random beep',\n            hamster_s_sound_robot: 'robot',\n            hamster_s_sound_sad: 'sad',\n            hamster_s_sound_siren: 'siren',\n            hamster_s_sound_sleep: 'sleep',\n            hamster_s_unit_cm: 'cm',\n            hamster_s_unit_deg: 'degrees',\n            hamster_s_unit_pulse: 'pulses',\n            hamster_s_unit_sec: 'seconds',\n            hamster_s_analog_input: 'analog input',\n            hamster_s_digital_input: 'digital input',\n            hamster_s_digital_input_pull_down: 'digital input (pull down)',\n            hamster_s_digital_input_pull_up: 'digital input (pull up)',\n            hamster_s_digital_output: 'digital output',\n            hamster_s_pwm_output: 'pwm output',\n            hamster_s_servo_output: 'servo output',\n            hamster_s_voltage_input: 'voltage input',\n            hamster_s_open_gripper: 'open',\n            hamster_s_close_gripper: 'close',\n            hamster_s_serial_string: 'string',\n            hamster_s_serial_string_line: 'string line',\n            hamster_s_serial_all: 'all',\n            hamster_s_serial_until_new_line: 'until new line',\n            hamster_s_serial_until_comma: 'until ,(comma)',\n            hamster_s_serial_until_colon: 'until :(colon)',\n            hamster_s_serial_until_dollar: 'until $',\n            hamster_s_serial_until_sharp: 'until #',\n            hamster_s_serial_input: 'serial input',\n        },\n    },\n});\n\nEntry.HamsterS.blockMenuBlocks = [\n    'hamster_s_hand_found',\n    'hamster_s_boolean',\n    'hamster_s_value',\n    'hamster_s_move_forward_once',\n    'hamster_s_turn_once',\n    'hamster_s_move_forward_unit',\n    'hamster_s_move_backward_unit',\n    'hamster_s_turn_unit_in_place',\n    'hamster_s_pivot_around_unit_in_direction',\n    'hamster_s_turn_unit_with_radius_in_direction',\n    'hamster_s_change_both_wheels_by',\n    'hamster_s_set_both_wheels_to',\n    'hamster_s_change_wheel_by',\n    'hamster_s_set_wheel_to',\n    'hamster_s_follow_line_using',\n    'hamster_s_follow_line_until',\n    'hamster_s_set_following_speed_to',\n    'hamster_s_set_following_gain_to',\n    'hamster_s_stop',\n    'hamster_s_set_led_to',\n    'hamster_s_pick_led',\n    'hamster_s_change_led_by_rgb',\n    'hamster_s_set_led_to_rgb',\n    'hamster_s_clear_led',\n    'hamster_s_play_sound_times',\n    'hamster_s_play_sound_times_until_done',\n    'hamster_s_change_buzzer_by',\n    'hamster_s_set_buzzer_to',\n    'hamster_s_clear_sound',\n    'hamster_s_play_note',\n    'hamster_s_play_note_for',\n    'hamster_s_rest_for',\n    'hamster_s_change_tempo_by',\n    'hamster_s_set_tempo_to',\n    'hamster_s_set_port_to',\n    'hamster_s_change_output_by',\n    'hamster_s_set_output_to',\n    'hamster_s_gripper',\n    'hamster_s_release_gripper',\n    'hamster_s_write_serial',\n    'hamster_s_read_serial_until',\n    'hamster_s_set_serial_rate_to',\n];\n\nEntry.HamsterS.getBlocks = function() {\n    return {\n        hamster_s_hand_found: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'hamster_s_hand_found',\n            },\n            class: 'hamster_s_sensor',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.checkHandFound(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.hand_found()',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        hamster_s_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.hamster_s_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.hamster_s_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.hamster_s_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.hamster_s_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.hamster_s_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.hamster_s_tap, 'TAP'],\n                        [Lang.Blocks.hamster_s_free_fall, 'FREE_FALL'],\n                        [Lang.Blocks.hamster_s_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.hamster_s_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.hamster_s_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_s_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hamster_s_sensor',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.hamster_s_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.hamster_s_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.hamster_s_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.hamster_s_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.hamster_s_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.hamster_s_tap, 'TAP'],\n                                    [Lang.Blocks.hamster_s_free_fall, 'FREE_FALL'],\n                                    [Lang.Blocks.hamster_s_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.hamster_s_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.hamster_s_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                        [Lang.Blocks.hamster_s_sensor_right_proximity, 'RIGHT_PROXIMITY'],\n                        [Lang.Blocks.hamster_s_sensor_left_floor, 'LEFT_FLOOR'],\n                        [Lang.Blocks.hamster_s_sensor_right_floor, 'RIGHT_FLOOR'],\n                        [Lang.Blocks.hamster_s_sensor_acceleration_x, 'ACCELERATION_X'],\n                        [Lang.Blocks.hamster_s_sensor_acceleration_y, 'ACCELERATION_Y'],\n                        [Lang.Blocks.hamster_s_sensor_acceleration_z, 'ACCELERATION_Z'],\n                        [Lang.Blocks.hamster_s_sensor_light, 'LIGHT'],\n                        [Lang.Blocks.hamster_s_sensor_temperature, 'TEMPERATURE'],\n                        [Lang.Blocks.hamster_s_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                        [Lang.Blocks.hamster_s_sensor_input_a, 'INPUT_A'],\n                        [Lang.Blocks.hamster_s_sensor_input_b, 'INPUT_B'],\n                        [Lang.Blocks.hamster_s_serial_input, 'SERIAL_INPUT'],\n                    ],\n                    value: 'LEFT_PROXIMITY',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_s_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hamster_s_sensor',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                                    [\n                                        Lang.Blocks.hamster_s_sensor_right_proximity,\n                                        'RIGHT_PROXIMITY',\n                                    ],\n                                    [Lang.Blocks.hamster_s_sensor_left_floor, 'LEFT_FLOOR'],\n                                    [Lang.Blocks.hamster_s_sensor_right_floor, 'RIGHT_FLOOR'],\n                                    [Lang.Blocks.hamster_s_sensor_acceleration_x, 'ACCELERATION_X'],\n                                    [Lang.Blocks.hamster_s_sensor_acceleration_y, 'ACCELERATION_Y'],\n                                    [Lang.Blocks.hamster_s_sensor_acceleration_z, 'ACCELERATION_Z'],\n                                    [Lang.Blocks.hamster_s_sensor_light, 'LIGHT'],\n                                    [Lang.Blocks.hamster_s_sensor_temperature, 'TEMPERATURE'],\n                                    [\n                                        Lang.Blocks.hamster_s_sensor_signal_strength,\n                                        'SIGNAL_STRENGTH',\n                                    ],\n                                    [Lang.Blocks.hamster_s_sensor_input_a, 'INPUT_A'],\n                                    [Lang.Blocks.hamster_s_sensor_input_b, 'INPUT_B'],\n                                    [Lang.Blocks.hamster_s_serial_input, 'SERIAL_INPUT'],\n                                ],\n                                value: 'LEFT_PROXIMITY',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_move_forward_once: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_s_move_forward_once',\n            },\n            class: 'hamster_s_board',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.boardForward(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.board_forward()',\n                    },\n                ],\n            },\n        },\n        hamster_s_turn_once: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_s_turn_once',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'hamster_s_board',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.boardTurn(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.board_turn(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_cm, 'CM'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'hamster_s_move_forward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.move_forward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_cm, 'CM'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_cm, 'CM'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'hamster_s_move_backward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.move_backward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_cm, 'CM'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'hamster_s_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_pivot_around_unit_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left_pen, 'LEFT_PEN'],\n                        [Lang.Blocks.hamster_s_right_pen, 'RIGHT_PEN'],\n                        [Lang.Blocks.hamster_s_left_wheel, 'LEFT_WHEEL'],\n                        [Lang.Blocks.hamster_s_right_wheel, 'RIGHT_WHEEL'],\n                    ],\n                    value: 'LEFT_PEN',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_forward, 'FORWARD'],\n                        [Lang.Blocks.hamster_s_backward, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'hamster_s_pivot_around_unit_in_direction',\n            },\n            paramsKeyMap: {\n                PART: 0,\n                VALUE: 1,\n                UNIT: 2,\n                TOWARD: 3,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.pivotUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.pivot(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left_pen, 'LEFT_PEN'],\n                                    [Lang.Blocks.hamster_s_right_pen, 'RIGHT_PEN'],\n                                    [Lang.Blocks.hamster_s_left_wheel, 'LEFT_WHEEL'],\n                                    [Lang.Blocks.hamster_s_right_wheel, 'RIGHT_WHEEL'],\n                                ],\n                                value: 'LEFT_PEN',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_forward, 'FORWARD'],\n                                    [Lang.Blocks.hamster_s_backward, 'BACKWARD'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_turn_unit_with_radius_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left_pen, 'LEFT_PEN'],\n                        [Lang.Blocks.hamster_s_right_pen, 'RIGHT_PEN'],\n                        [Lang.Blocks.hamster_s_robot, 'ROBOT'],\n                    ],\n                    value: 'LEFT_PEN',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_forward, 'FORWARD'],\n                        [Lang.Blocks.hamster_s_backward, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'hamster_s_turn_unit_with_radius_in_direction',\n            },\n            paramsKeyMap: {\n                PART: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n                UNIT: 3,\n                RADIUS: 4,\n                TOWARD: 5,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.swingUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.circle(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left_pen, 'LEFT_PEN'],\n                                    [Lang.Blocks.hamster_s_right_pen, 'RIGHT_PEN'],\n                                    [Lang.Blocks.hamster_s_robot, 'ROBOT'],\n                                ],\n                                value: 'LEFT_PEN',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_forward, 'FORWARD'],\n                                    [Lang.Blocks.hamster_s_backward, 'BACKWARD'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_change_both_wheels_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_change_both_wheels_by',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_both_wheels_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_set_both_wheels_to',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_follow_line_using: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_color_black, 'BLACK'],\n                        [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_s_follow_line_using',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                SENSOR: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.follow_line(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_color_black, 'BLACK'],\n                                    [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_color_black, 'BLACK'],\n                        [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_front, 'FRONT'],\n                        [Lang.Blocks.hamster_s_rear, 'REAR'],\n                    ],\n                    value: 'FRONT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_s_follow_line_until',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                DIRECTION: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.follow_line_until(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_color_black, 'BLACK'],\n                                    [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_front, 'FRONT'],\n                                    [Lang.Blocks.hamster_s_rear, 'REAR'],\n                                ],\n                                value: 'FRONT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['5', null],\n                type: 'hamster_s_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_line_speed(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_following_gain_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_gain_default, 'DEFAULT'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: 'DEFAULT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_s_set_following_gain_to',\n            },\n            paramsKeyMap: {\n                GAIN: 0,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setLineTracerGain(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_line_gain(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_gain_default, 'DEFAULT'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: 'DEFAULT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_s_stop',\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.stop()',\n                    },\n                ],\n            },\n        },\n        hamster_s_set_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_color_red, 'RED'],\n                        [Lang.Blocks.hamster_s_color_orange, 'ORANGE'],\n                        [Lang.Blocks.hamster_s_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.hamster_s_color_green, 'GREEN'],\n                        [Lang.Blocks.hamster_s_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.hamster_s_color_blue, 'BLUE'],\n                        [Lang.Blocks.hamster_s_color_violet, 'VIOLET'],\n                        [Lang.Blocks.hamster_s_color_purple, 'PURPLE'],\n                        [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_s_set_led_to',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_color_red, 'RED'],\n                                    [Lang.Blocks.hamster_s_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.hamster_s_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.hamster_s_color_green, 'GREEN'],\n                                    [Lang.Blocks.hamster_s_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.hamster_s_color_blue, 'BLUE'],\n                                    [Lang.Blocks.hamster_s_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.hamster_s_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_pick_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_s_pick_led',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.pickLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.pick_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.changeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.add_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_set_led_to_rgb',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_s_clear_led',\n            },\n            paramsKeyMap: {\n                LED: 0,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.clear_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_sound_beep, 'BEEP'],\n                        [Lang.Blocks.hamster_s_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.hamster_s_sound_noise, 'NOISE'],\n                        [Lang.Blocks.hamster_s_sound_siren, 'SIREN'],\n                        [Lang.Blocks.hamster_s_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.hamster_s_sound_chop, 'CHOP'],\n                        [Lang.Blocks.hamster_s_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.hamster_s_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.hamster_s_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.hamster_s_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.hamster_s_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.hamster_s_sound_sad, 'SAD'],\n                        [Lang.Blocks.hamster_s_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.hamster_s_sound_march, 'MARCH'],\n                        [Lang.Blocks.hamster_s_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_play_sound_times',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.play_sound(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.hamster_s_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.hamster_s_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.hamster_s_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.hamster_s_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.hamster_s_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.hamster_s_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.hamster_s_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.hamster_s_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.hamster_s_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.hamster_s_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.hamster_s_sound_sad, 'SAD'],\n                                    [Lang.Blocks.hamster_s_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.hamster_s_sound_march, 'MARCH'],\n                                    [Lang.Blocks.hamster_s_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_sound_beep, 'BEEP'],\n                        [Lang.Blocks.hamster_s_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.hamster_s_sound_noise, 'NOISE'],\n                        [Lang.Blocks.hamster_s_sound_siren, 'SIREN'],\n                        [Lang.Blocks.hamster_s_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.hamster_s_sound_chop, 'CHOP'],\n                        [Lang.Blocks.hamster_s_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.hamster_s_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.hamster_s_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.hamster_s_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.hamster_s_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.hamster_s_sound_sad, 'SAD'],\n                        [Lang.Blocks.hamster_s_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.hamster_s_sound_march, 'MARCH'],\n                        [Lang.Blocks.hamster_s_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.play_sound_until_done(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.hamster_s_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.hamster_s_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.hamster_s_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.hamster_s_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.hamster_s_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.hamster_s_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.hamster_s_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.hamster_s_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.hamster_s_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.hamster_s_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.hamster_s_sound_sad, 'SAD'],\n                                    [Lang.Blocks.hamster_s_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.hamster_s_sound_march, 'MARCH'],\n                                    [Lang.Blocks.hamster_s_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.add_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        hamster_s_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        hamster_s_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_s_clear_sound',\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.clear_sound()',\n                        params: [null],\n                    },\n                ],\n            },\n        },\n        hamster_s_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_note_c, 'C'],\n                        [Lang.Blocks.hamster_s_note_c_sharp, 'C#'],\n                        [Lang.Blocks.hamster_s_note_d, 'D'],\n                        [Lang.Blocks.hamster_s_note_d_sharp, 'D#'],\n                        [Lang.Blocks.hamster_s_note_e, 'E'],\n                        [Lang.Blocks.hamster_s_note_f, 'F'],\n                        [Lang.Blocks.hamster_s_note_f_sharp, 'F#'],\n                        [Lang.Blocks.hamster_s_note_g, 'G'],\n                        [Lang.Blocks.hamster_s_note_g_sharp, 'G#'],\n                        [Lang.Blocks.hamster_s_note_a, 'A'],\n                        [Lang.Blocks.hamster_s_note_a_sharp, 'A#'],\n                        [Lang.Blocks.hamster_s_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'hamster_s_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.play_pitch(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_note_c, 'C'],\n                                    [Lang.Blocks.hamster_s_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.hamster_s_note_d, 'D'],\n                                    [Lang.Blocks.hamster_s_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.hamster_s_note_e, 'E'],\n                                    [Lang.Blocks.hamster_s_note_f, 'F'],\n                                    [Lang.Blocks.hamster_s_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.hamster_s_note_g, 'G'],\n                                    [Lang.Blocks.hamster_s_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.hamster_s_note_a, 'A'],\n                                    [Lang.Blocks.hamster_s_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.hamster_s_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_note_c, 'C'],\n                        [Lang.Blocks.hamster_s_note_c_sharp, 'C#'],\n                        [Lang.Blocks.hamster_s_note_d, 'D'],\n                        [Lang.Blocks.hamster_s_note_d_sharp, 'D#'],\n                        [Lang.Blocks.hamster_s_note_e, 'E'],\n                        [Lang.Blocks.hamster_s_note_f, 'F'],\n                        [Lang.Blocks.hamster_s_note_f_sharp, 'F#'],\n                        [Lang.Blocks.hamster_s_note_g, 'G'],\n                        [Lang.Blocks.hamster_s_note_g_sharp, 'G#'],\n                        [Lang.Blocks.hamster_s_note_a, 'A'],\n                        [Lang.Blocks.hamster_s_note_a_sharp, 'A#'],\n                        [Lang.Blocks.hamster_s_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.play_note(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_note_c, 'C'],\n                                    [Lang.Blocks.hamster_s_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.hamster_s_note_d, 'D'],\n                                    [Lang.Blocks.hamster_s_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.hamster_s_note_e, 'E'],\n                                    [Lang.Blocks.hamster_s_note_f, 'F'],\n                                    [Lang.Blocks.hamster_s_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.hamster_s_note_g, 'G'],\n                                    [Lang.Blocks.hamster_s_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.hamster_s_note_a, 'A'],\n                                    [Lang.Blocks.hamster_s_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.hamster_s_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_rest_for',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.rest(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_port_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_port_a, 'A'],\n                        [Lang.Blocks.hamster_s_port_b, 'B'],\n                        [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_analog_input, 'ANALOG_INPUT'],\n                        [Lang.Blocks.hamster_s_digital_input, 'DIGITAL_INPUT'],\n                        [Lang.Blocks.hamster_s_digital_input_pull_up, 'DIGITAL_INPUT_PULL_UP'],\n                        [Lang.Blocks.hamster_s_digital_input_pull_down, 'DIGITAL_INPUT_PULL_DOWN'],\n                        [Lang.Blocks.hamster_s_voltage_input, 'VOLTAGE_INPUT'],\n                        [Lang.Blocks.hamster_s_servo_output, 'SERVO_OUTPUT'],\n                        [Lang.Blocks.hamster_s_pwm_output, 'PWM_OUTPUT'],\n                        [Lang.Blocks.hamster_s_digital_output, 'DIGITAL_OUTPUT'],\n                    ],\n                    value: 'ANALOG_INPUT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'hamster_s_set_port_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                MODE: 1,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setIoMode(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_io_mode(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_port_a, 'A'],\n                                    [Lang.Blocks.hamster_s_port_b, 'B'],\n                                    [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_analog_input, 'ANALOG_INPUT'],\n                                    [Lang.Blocks.hamster_s_digital_input, 'DIGITAL_INPUT'],\n                                    [\n                                        Lang.Blocks.hamster_s_digital_input_pull_up,\n                                        'DIGITAL_INPUT_PULL_UP',\n                                    ],\n                                    [\n                                        Lang.Blocks.hamster_s_digital_input_pull_down,\n                                        'DIGITAL_INPUT_PULL_DOWN',\n                                    ],\n                                    [Lang.Blocks.hamster_s_voltage_input, 'VOLTAGE_INPUT'],\n                                    [Lang.Blocks.hamster_s_servo_output, 'SERVO_OUTPUT'],\n                                    [Lang.Blocks.hamster_s_pwm_output, 'PWM_OUTPUT'],\n                                    [Lang.Blocks.hamster_s_digital_output, 'DIGITAL_OUTPUT'],\n                                ],\n                                value: 'ANALOG_INPUT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_change_output_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_port_a, 'A'],\n                        [Lang.Blocks.hamster_s_port_b, 'B'],\n                        [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_change_output_by',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.changeOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.add_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_port_a, 'A'],\n                                    [Lang.Blocks.hamster_s_port_b, 'B'],\n                                    [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_output_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_port_a, 'A'],\n                        [Lang.Blocks.hamster_s_port_b, 'B'],\n                        [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_set_output_to',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_output(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_port_a, 'A'],\n                                    [Lang.Blocks.hamster_s_port_b, 'B'],\n                                    [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_gripper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_open_gripper, 'OPEN'],\n                        [Lang.Blocks.hamster_s_close_gripper, 'CLOSE'],\n                    ],\n                    value: 'OPEN',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_s_gripper',\n            },\n            paramsKeyMap: {\n                ACTION: 0,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.gripper(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_gripper(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_open_gripper, 'OPEN'],\n                                    [Lang.Blocks.hamster_s_close_gripper, 'CLOSE'],\n                                ],\n                                value: 'OPEN',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_release_gripper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hamster_s_release_gripper',\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.releaseGripper(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.release_gripper()',\n                    },\n                ],\n            },\n        },\n        hamster_s_write_serial: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_serial_string, 'STRING'],\n                        [Lang.Blocks.hamster_s_serial_string_line, 'STRING_LINE'],\n                    ],\n                    value: 'STRING',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['abc123'],\n                    },\n                    null,\n                ],\n                type: 'hamster_s_write_serial',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n                STRING: 1,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.writeSerial(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.write_serial(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_serial_string, 'STRING'],\n                                    [Lang.Blocks.hamster_s_serial_string_line, 'STRING_LINE'],\n                                ],\n                                value: 'STRING',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_read_serial_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_serial_all, 'ALL'],\n                        [Lang.Blocks.hamster_s_serial_until_comma, 'COMMA'],\n                        [Lang.Blocks.hamster_s_serial_until_colon, 'COLON'],\n                        [Lang.Blocks.hamster_s_serial_until_dollar, 'DOLLAR'],\n                        [Lang.Blocks.hamster_s_serial_until_sharp, 'SHARP'],\n                        [Lang.Blocks.hamster_s_serial_until_new_line, 'NEW_LINE'],\n                    ],\n                    value: 'ALL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_s_read_serial_until',\n            },\n            paramsKeyMap: {\n                DELIMITER: 0,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.readSerialUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.read_serial(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_serial_all, 'ALL'],\n                                    [Lang.Blocks.hamster_s_serial_until_comma, 'COMMA'],\n                                    [Lang.Blocks.hamster_s_serial_until_colon, 'COLON'],\n                                    [Lang.Blocks.hamster_s_serial_until_dollar, 'DOLLAR'],\n                                    [Lang.Blocks.hamster_s_serial_until_sharp, 'SHARP'],\n                                    [Lang.Blocks.hamster_s_serial_until_new_line, 'NEW_LINE'],\n                                ],\n                                value: 'ALL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        hamster_s_set_serial_rate_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['9600', '9600'],\n                        ['14400', '14400'],\n                        ['19200', '19200'],\n                        ['28800', '28800'],\n                        ['38400', '38400'],\n                        ['57600', '57600'],\n                        ['76800', '76800'],\n                        ['115200', '115200'],\n                    ],\n                    value: '9600',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'hamster_s_set_serial_rate_to',\n            },\n            paramsKeyMap: {\n                BAUD: 0,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['hamsterS'],\n            func(sprite, script) {\n                const robot = Entry.HamsterS.getRobot();\n                return robot ? robot.setSerialRate(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'HamsterS.set_serial_rate(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['9600', '9600'],\n                                    ['14400', '14400'],\n                                    ['19200', '19200'],\n                                    ['28800', '28800'],\n                                    ['38400', '38400'],\n                                    ['57600', '57600'],\n                                    ['76800', '76800'],\n                                    ['115200', '115200'],\n                                ],\n                                value: '9600',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.HamsterS;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_handino.js",
    "content": "'use strict';\nconst SERVO_PIN_NUMBERS = [12, 10, 9, 6, 2];\nconst HAND_MAX_ANGLE = 165;\nconst HAND_HALF_ANGLE = 60;\nconst HAND_MIN_ANGLE = 0;\nconst HAND_DELAY = 1000;\nconst HAND_TYPE = {\n    ROCK: 0,\n    PAPER: 1,\n    SCISSORS: 2,\n    GESTURE_THUMBSUP: 3,\n    GESTURE_PEACE: 4,\n    GESTURE_PROMISE: 5,\n    GESTURE_V: 6,\n    LANGUAGE_ㄱ:7,\n    LANGUAGE_ㄴ:8,\n    LANGUAGE_ㄷ:9,\n    LANGUAGE_ㄹ:10,\n    LANGUAGE_ㅁ:11,\n    LANGUAGE_ㅂ:12,\n    LANGUAGE_ㅅ:13,\n    LANGUAGE_ㅇ:14,\n    LANGUAGE_ㅈ:15,\n    LANGUAGE_ㅊ:16,\n    LANGUAGE_ㅋ:17,\n    LANGUAGE_ㅌ:18,\n    LANGUAGE_ㅍ:19,\n    LANGUAGE_ㅎ:20,\n};\n\nfunction Lerp(a, b, t) {\n    return (1 - t) * a + b * t;\n}\n\nfunction sleep(ms) {\n    return new Promise((r) => setTimeout(r, ms));\n  }\n\nfunction setFinger(idx, angle)\n{\n    Entry.hw.sendQueue.SET[SERVO_PIN_NUMBERS[idx]] = {\n        type: Entry.ArduinoZin.sensorTypes.SERVO_PIN,\n        data: angle,\n        time: new Date().getTime(),\n    };\n}\n\nfunction setFingerDuration(idx, startAngle, targetAngle, duration)\n{\n    var delayTime = duration*1000;\n    let func = (i, maxIdx) => {\n        sleep(i).then(() => {\n            setFinger(idx, Lerp(startAngle, targetAngle, i/maxIdx));                                \n        });\n    };\n       \n    for (var i = 0; i <= delayTime; i+=delayTime/100)\n    {\n        func(i, delayTime);\n    }\n}\n\nfunction setHandType(type)\n{\n    switch (type)\n    {\n        case HAND_TYPE.ROCK:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MIN_ANGLE);\n                setFinger(2, HAND_MIN_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.PAPER:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MAX_ANGLE);\n                setFinger(4, HAND_MAX_ANGLE);\n                \n            }break;\n        case HAND_TYPE.SCISSORS:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.GESTURE_THUMBSUP:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MIN_ANGLE);\n                setFinger(2, HAND_MIN_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.GESTURE_PEACE:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MIN_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MAX_ANGLE);\n            }break;\n        case HAND_TYPE.GESTURE_PROMISE:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MIN_ANGLE);\n                setFinger(2, HAND_MIN_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MAX_ANGLE);\n            }break;\n        case HAND_TYPE.GESTURE_V:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㄱ:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MIN_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㄴ:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MIN_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㄷ:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㄹ:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MAX_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅁ:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_HALF_ANGLE);\n                setFinger(2, HAND_HALF_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅂ:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MAX_ANGLE);\n                setFinger(4, HAND_MAX_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅅ:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅇ:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MIN_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MAX_ANGLE);\n                setFinger(4, HAND_MAX_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅈ:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅊ:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MAX_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅋ:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MIN_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅌ:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MAX_ANGLE);\n                setFinger(2, HAND_MAX_ANGLE);\n                setFinger(3, HAND_MAX_ANGLE);\n                setFinger(4, HAND_HALF_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅍ:\n            {\n                setFinger(0, HAND_MIN_ANGLE);\n                setFinger(1, HAND_MIN_ANGLE);\n                setFinger(2, HAND_MIN_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n        case HAND_TYPE.LANGUAGE_ㅎ:\n            {\n                setFinger(0, HAND_MAX_ANGLE);\n                setFinger(1, HAND_MIN_ANGLE);\n                setFinger(2, HAND_MIN_ANGLE);\n                setFinger(3, HAND_MIN_ANGLE);\n                setFinger(4, HAND_MIN_ANGLE);\n            }break;\n    }\n}\n\nfunction setFingerNumber(n, duration) \n{\n    if (n <= 5)\n    {\n        for (var i = 0; i < 5; i++)\n        {\n            let angle = HAND_MIN_ANGLE;\n            if (i < n)\n                angle = HAND_MAX_ANGLE;\n\n            setFingerDuration(i, HAND_HALF_ANGLE, angle, duration);\n        }\n    }\n    else\n    {\n        for (var i = 0; i < 5; i++)\n        {\n            let angle = HAND_MIN_ANGLE;\n            if (10 - n <= i)\n                angle = HAND_MAX_ANGLE;\n            \n            setFingerDuration(i, HAND_HALF_ANGLE, angle, duration);\n        }\n    }    \n}\n\nfunction getRandomArbitraryInt(min, max) {\n    return parseInt(Math.random() * (max - min) + min);\n}\n\nfunction delayScriptCallReturn(script, delay, onStart){\n    if (!script.isStart) {\n\n        onStart();\n\n        setTimeout(()=>{\n            clearInterval(Entry.ArduinoZin.handTimerId);\n            script.isLoop = 0;\n        }, delay);\n\n        script.isStart = true;\n        script.isLoop = true;                    \n        return script;\n    } else if (script.isLoop == true) {\n        return script;\n    }\n\n    delete script.isLoop;\n    delete script.isStart;\n    return script.callReturn();\n}\nEntry.ArduinoZin = {\n    id: '59.1',\n    name: 'ArduinoZin',\n    url: 'http://www.arduino.cc/',\n    imageName: 'arduinoZin.png',\n    title: {\n        ko: '아두이노 Uno Zin',\n        en: 'Arduino Uno Zin',\n    },\n    handTimerId:-1,\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            clearInterval(Entry.ArduinoZin.handTimerId);\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = HAND_MAX_ANGLE;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n};\n\nEntry.ArduinoZin.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                arduino_ext_set_servo_hand_scissors: '가위바위보 %1 %2',\n                arduino_ext_set_servo_hand_count: '숫자 세기 %1 %2',\n                arduino_ext_set_servo_hand_gesture: '손 제스처 %1 %2',\n                arduino_ext_set_servo_hand_finger_updown: '%1번째 손가락 %2 %3',\n                arduino_ext_set_servo_hand_play_scissors: '랜덤 가위보기하기 %1 %2',\n                arduino_ext_set_servo_hand_finger_updown_same_time: '%1번째 %2번째 %3번째 %4번째 %5번째 손가락 %6 %7 %8',\n                arduino_ext_set_servo_hand_language: '수어 %1 %2',\n                arduino_ext_set_servo_hand_arithmetic: '산수 %1 %2 %3',\n            },\n        },\n        en: {\n            template: {\n                arduino_ext_set_servo_hand_scissors: 'Rock Paper Scissors %1 %2',\n                arduino_ext_set_servo_hand_count: 'number count %1 %2',\n                arduino_ext_set_servo_hand_gesture: 'hand gesture %1 %2',\n                arduino_ext_set_servo_hand_finger_updown: '%1 finger %2 %3',\n                arduino_ext_set_servo_hand_play_scissors: 'play rock paper scissors %1 %2',\n                arduino_ext_set_servo_hand_finger_updown_same_time: '%1st %2ed %3rd %4rd %5rd finger %6 %7 %8',\n                arduino_ext_set_servo_hand_language: 'hand language %1 %2',\n                arduino_ext_set_servo_hand_arithmetic: 'arithmetic %1 %2 %3',\n            },\n        },\n    };\n};\n\nEntry.ArduinoZin.blockMenuBlocks = [\n    'arduino_ext_set_servo_hand_scissors',\n    'arduino_ext_set_servo_hand_count',\n    'arduino_ext_set_servo_hand_gesture',\n    'arduino_ext_set_servo_hand_finger_updown',\n    'arduino_ext_set_servo_hand_play_scissors',\n    'arduino_ext_set_servo_hand_finger_updown_same_time',\n    'arduino_ext_set_servo_hand_language',\n    'arduino_ext_set_servo_hand_arithmetic',\n];\n\n//region ArduinoZin 아두이노 확장모드\nEntry.ArduinoZin.getBlocks = function() {\n    return {        \n        arduino_ext_set_servo_hand_scissors: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"바위\", 0 ],\n                        [ \"보\", 1 ],\n                        [ \"가위\", 2 ]\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    0,\n                    null,\n                ],\n                type: 'arduino_ext_set_servo_hand_scissors',\n            },\n            paramsKeyMap: {\n                HAND_TYPE: 0\n            },\n            class: 'ArduinoZin',\n            isNotFor: ['ArduinoZin'],\n            func(sprite, script) {                \n                \n                const sq = Entry.hw.sendQueue;\n                return delayScriptCallReturn(script, HAND_DELAY,\n                    ()=>{\n                        const handType = script.getNumberValue('HAND_TYPE', script);\n\n                        if (!sq.SET) {\n                            sq.SET = {};\n                        }\n                        \n                        switch(handType) {\n                            case 0:\n                                {           \n                                    setHandType(HAND_TYPE.ROCK);\n                                }\n                                break;\n                            case 1:\n                                {\n                                    setHandType(HAND_TYPE.PAPER);\n                                }\n                                break;\n                            case 2:\n                                {\n                                    setHandType(HAND_TYPE.SCISSORS);\n                                }\n                                break;\n                        }     \n                    }\n                );\n            },\n        },\n        arduino_ext_set_servo_hand_count: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_ext_set_servo_hand_count',\n            },\n            paramsKeyMap: {\n                VALUE: 0\n            },\n            class: 'ArduinoZin',\n            isNotFor: ['ArduinoZin'],\n            func(sprite, script) {                \n                const sq = Entry.hw.sendQueue;\n                if (!script.isStart) {\n                    \n                    let value = script.getNumberValue('VALUE', script);\n                    value = Math.min(180, value);\n                    value = Math.max(0, value);\n    \n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    setHandType(HAND_TYPE.PAPER);\n                    \n                    if (value == 0)\n                        return script.callReturn();\n                    \n                    script.handCount = 0;\n\n                    Entry.ArduinoZin.handTimerId = setInterval(() => { \n\n                        if (script.handCount%(SERVO_PIN_NUMBERS.length*2) < SERVO_PIN_NUMBERS.length)\n                            setFinger(script.handCount%SERVO_PIN_NUMBERS.length, HAND_MIN_ANGLE);\n                        else\n                            setFinger(script.handCount%SERVO_PIN_NUMBERS.length, HAND_MAX_ANGLE);\n\n                        script.handCount++;\n\n                        if(script.handCount == value) {\n                            clearInterval(Entry.ArduinoZin.handTimerId);\n                            setTimeout(()=>{                                \n                                script.isLoop = 0;\n                            }, HAND_DELAY);                            \n                        }\n                    }, HAND_DELAY);\n\n                    script.isStart = true;\n                    script.isLoop = true;\n                    return script;\n                } else if (script.isLoop == true) {\n                    return script;\n                } \n                \n                delete script.isLoop;\n                delete script.isStart;\n                delete script.handCount;\n                return script.callReturn();\n            },\n        },\n        arduino_ext_set_servo_hand_gesture: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [       \n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"따봉\", HAND_TYPE.GESTURE_THUMBSUP ],\n                        [ \"피스\", HAND_TYPE.GESTURE_PEACE ],\n                        [ \"약속\", HAND_TYPE.GESTURE_PROMISE ],\n                        [ \"브이\", HAND_TYPE.GESTURE_V ],\n                    ],\n                    fontSize: 11\n                },        \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {       \n                params: [\n                    HAND_TYPE.GESTURE_THUMBSUP,\n                    null,\n                ],        \n                type: 'arduino_ext_set_servo_hand_gesture',\n            },\n            paramsKeyMap: {\n                HAND_TYPE: 0\n            },\n            class: 'ArduinoZin',\n            isNotFor: ['ArduinoZin'],\n            func(sprite, script) {                \n                \n                const sq = Entry.hw.sendQueue;\n                return delayScriptCallReturn(script, HAND_DELAY, \n                    ()=>{\n                        if (!sq.SET) {\n                            sq.SET = {};\n                        }\n    \n                        const handType = script.getNumberValue('HAND_TYPE', script);\n                        setHandType(handType);\n                    }\n                );\n            },\n        },\n        arduino_ext_set_servo_hand_finger_updown: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"1\", 0 ],\n                        [ \"2\", 1 ],\n                        [ \"3\", 2 ],\n                        [ \"4\", 3 ],\n                        [ \"5\", 4 ]\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"매우 천천히 접기\", 0 ],\n                        [ \"매우 천천히 펴기\", 1 ],\n                        [ \"천천히 접기\", 2 ],\n                        [ \"천천히 펴기\", 3 ],\n                        [ \"보통 접기\", 4 ],\n                        [ \"보통 펴기\", 5 ],\n                        [ \"빠르게 접기\", 6 ],\n                        [ \"빠르게 펴기\", 7 ]\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {     \n                params: [\n                    0,\n                    0,\n                    null,\n                ],           \n                type: 'arduino_ext_set_servo_hand_finger_updown',\n            },\n            paramsKeyMap: {\n                FINGER_TYPE: 0,\n                FINGER_UPDOWN: 1\n            },\n            class: 'ArduinoZin',\n            isNotFor: ['ArduinoZin'],\n            func(sprite, script) {                \n                const fingerType = script.getNumberValue('FINGER_TYPE', script);\n                const fingerUpDown = script.getNumberValue('FINGER_UPDOWN', script);\n                let delayTimes = [10, 2.5, 0.5, 0.1];\n                let startAngle = HAND_MIN_ANGLE;\n                let targetAngle = HAND_MAX_ANGLE;\n                if (fingerUpDown % 2 == 0)\n                {\n                    startAngle = HAND_MAX_ANGLE;\n                    targetAngle = HAND_MIN_ANGLE;\n                }\n                else if (fingerUpDown % 2 == 1)\n                {\n                    startAngle = HAND_MIN_ANGLE;\n                    targetAngle = HAND_MAX_ANGLE;                    \n                }\n                let delayTime = delayTimes[parseInt(fingerUpDown/2)];\n                const sq = Entry.hw.sendQueue;\n                return delayScriptCallReturn(script, HAND_DELAY+delayTime*1000, \n                    ()=>{                        \n        \n                        if (!sq.SET) {\n                            sq.SET = {};\n                        }\n\n                        setFingerDuration(fingerType, startAngle, targetAngle, delayTime);\n                    }\n                );\n\n            },\n        },\n        arduino_ext_set_servo_hand_play_scissors: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"바위\", \"0\" ],\n                        [ \"보\", \"1\" ],\n                        [ \"가위\", \"2\" ]\n                    ],\n                    fontSize: 11\n                },                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {     \n                params: [\n                \"0\",\n                null,\n                ],           \n                type: 'arduino_ext_set_servo_hand_play_scissors',\n            },\n            paramsKeyMap: {\n                HAND_TYPE: 0,\n            },\n            class: 'ArduinoZin',\n            isNotFor: ['ArduinoZin'],\n            func(sprite, script) {                \n                \n                const sq = Entry.hw.sendQueue;\n                return delayScriptCallReturn(script, HAND_DELAY, \n                    ()=>{\n                        const handType = script.getNumberValue('HAND_TYPE', script);\n                        const handList = [HAND_TYPE.ROCK, HAND_TYPE.PAPER, HAND_TYPE.SCISSORS];\n                        if (!sq.SET) {\n                            sq.SET = {};\n                        }\n        \n                        let h = getRandomArbitraryInt(0, handList.length);\n                        setHandType(handList[h]);\n                    }\n                );\n\n            },\n        },\n        arduino_ext_set_servo_hand_finger_updown_same_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"1\", 1 ],\n                        [ \"-\", 0 ],\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"2\", 1 ],\n                        [ \"-\", 0 ],\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"3\", 1 ],\n                        [ \"-\", 0 ],\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"4\", 1 ],\n                        [ \"-\", 0 ],\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"5\", 1 ],\n                        [ \"-\", 0 ],\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"동시에\", 0 ],\n                        [ \"하나씩\", 1 ]\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"접기\", 0 ],\n                        [ \"펴기\", 1 ]\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {     \n                params: [\n                    1,\n                    1,\n                    1,\n                    1,\n                    1,\n                    0,\n                    0,\n                    null,\n                ],           \n                type: 'arduino_ext_set_servo_hand_finger_updown_same_time',\n            },\n            paramsKeyMap: {\n                FINGER_NUMBER1:0,\n                FINGER_NUMBER2:1,\n                FINGER_NUMBER3:2,\n                FINGER_NUMBER4:3,\n                FINGER_NUMBER5:4,\n                TIME_TYPE: 5,\n                FINGER_UPDOWN: 6\n            },\n            class: 'ArduinoZin',\n            isNotFor: ['ArduinoZin'],\n            func(sprite, script) {                \n                const fingerNumbers = [\n                    script.getNumberValue('FINGER_NUMBER1', script),\n                    script.getNumberValue('FINGER_NUMBER2', script),\n                    script.getNumberValue('FINGER_NUMBER3', script),\n                    script.getNumberValue('FINGER_NUMBER4', script),\n                    script.getNumberValue('FINGER_NUMBER5', script)\n                ];\n                \n                const fingerUpDown = script.getNumberValue('FINGER_UPDOWN', script);\n                let targetAngle = fingerUpDown == 0 ? HAND_MIN_ANGLE :HAND_MAX_ANGLE;\n                let delayTime = 0;\n                const timeType = script.getNumberValue('TIME_TYPE', script);\n                if (timeType == 1)\n                {\n                    for (var i = 0; i < fingerNumbers.length; i++)\n                    {\n                        if (fingerNumbers[i] == 1)\n                            delayTime += HAND_DELAY;\n                    }\n                }\n                \n                const sq = Entry.hw.sendQueue;\n                return delayScriptCallReturn(script, HAND_DELAY+delayTime, \n                    ()=>{                        \n        \n                        if (!sq.SET) {\n                            sq.SET = {};\n                        }\n\n                        if (timeType == 0)\n                        {\n                            for (var i = 0; i < fingerNumbers.length; i++)\n                            {\n                                if (fingerNumbers[i] == 1)\n                                    setFinger(i, targetAngle);  \n                            }\n                        }\n                        else\n                        {\n                            let func = (idx, t) => {\n                                sleep(t).then(() => {\n                                    setFinger(idx, targetAngle);                                \n                                });\n                            };\n                            \n                            var c = 0;\n                            for (var i = 0; i < fingerNumbers.length; i++)\n                            {\n                                if (fingerNumbers[i] == 1)\n                                {\n                                    func(i, c*HAND_DELAY);\n                                    c++;\n                                }\n                            }\n                        }\n                        \n                    }\n                );\n\n            },\n        },\n        arduino_ext_set_servo_hand_language: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [       \n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"ㄱ\", HAND_TYPE.LANGUAGE_ㄱ ],\n                        [ \"ㄴ\", HAND_TYPE.LANGUAGE_ㄴ ],\n                        [ \"ㄷ\", HAND_TYPE.LANGUAGE_ㄷ ],\n                        [ \"ㄹ\", HAND_TYPE.LANGUAGE_ㄹ ],\n                        [ \"ㅁ\", HAND_TYPE.LANGUAGE_ㅁ ],\n                        [ \"ㅂ\", HAND_TYPE.LANGUAGE_ㅂ ],\n                        [ \"ㅅ\", HAND_TYPE.LANGUAGE_ㅅ ],\n                        [ \"ㅇ\", HAND_TYPE.LANGUAGE_ㅇ ],\n                        [ \"ㅈ\", HAND_TYPE.LANGUAGE_ㅈ ],\n                        [ \"ㅊ\", HAND_TYPE.LANGUAGE_ㅊ ],\n                        [ \"ㅋ\", HAND_TYPE.LANGUAGE_ㅋ ],\n                        [ \"ㅌ\", HAND_TYPE.LANGUAGE_ㅌ ],\n                        [ \"ㅍ\", HAND_TYPE.LANGUAGE_ㅍ ],\n                        [ \"ㅎ\", HAND_TYPE.LANGUAGE_ㅎ ],\n                    ],\n                    fontSize: 11\n                },        \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {       \n                params: [\n                    HAND_TYPE.LANGUAGE_ㄱ,\n                    null,\n                ],        \n                type: 'arduino_ext_set_servo_hand_language',\n            },\n            paramsKeyMap: {\n                HAND_TYPE: 0\n            },\n            class: 'ArduinoZin',\n            isNotFor: ['ArduinoZin'],\n            func(sprite, script) {                \n                \n                const sq = Entry.hw.sendQueue;\n                return delayScriptCallReturn(script, HAND_DELAY, \n                    ()=>{\n                        if (!sq.SET) {\n                            sq.SET = {};\n                        }\n    \n                        const handType = script.getNumberValue('HAND_TYPE', script);\n                        setHandType(handType);\n                    }\n                );\n            },\n        },\n        arduino_ext_set_servo_hand_arithmetic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [      \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: \"Dropdown\",\n                    options: [\n                        [ \"+\", 0 ],\n                        [ \"-\", 1 ],\n                        [ \"x\", 2 ],\n                        [ \"/\", 3 ],\n                    ],\n                    fontSize: 11\n                },        \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {       \n                params: [\n                    0,\n                    0,\n                    0,\n                    null,\n                ],        \n                type: 'arduino_ext_set_servo_hand_arithmetic',\n            },\n            paramsKeyMap: {\n                OPRND1: 0,\n                OPTOR: 1,\n                OPRND2: 2\n            },\n            class: 'ArduinoZin',\n            isNotFor: ['ArduinoZin'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    const oprnd1 = script.getNumberValue('OPRND1', script);\n                    const optor = script.getNumberValue('OPTOR', script);\n                    const oprnd2 = script.getNumberValue('OPRND2', script);\n                    let result = 0;\n                    \n                    switch (optor)\n                    {\n                        case 0:\n                            result = oprnd1 + oprnd2;\n                            break;\n                        case 1:\n                            result = oprnd1 - oprnd2;\n                            break;\n                        case 2:\n                            result = oprnd1 * oprnd2;\n                            break;\n                        case 3:\n                            result = oprnd1 / oprnd2;\n                            break;\n                    }\n                    \n                    // 음수 무시\n                    result = Math.abs(result.toFixed());\n                    let strResult = result.toString();\n                    \n                    script.handCount = 0;\n\n                    setFinger(0, HAND_HALF_ANGLE);\n                    setFinger(1, HAND_HALF_ANGLE);\n                    setFinger(2, HAND_HALF_ANGLE);\n                    setFinger(3, HAND_HALF_ANGLE);\n                    setFinger(4, HAND_HALF_ANGLE);\n\n                    Entry.ArduinoZin.handTimerId = setInterval(() => { \n\n                        let number = parseInt(strResult[script.handCount]);\n                                                \n                        setFingerNumber(number, 0.5);\n                        script.handCount++;\n\n                        if(script.handCount == strResult.length) {\n                            clearInterval(Entry.ArduinoZin.handTimerId);\n                            setTimeout(()=>{                                \n                                script.isLoop = 0;\n                            }, HAND_DELAY);\n                        }\n                    }, HAND_DELAY+HAND_DELAY*2);\n\n                    script.isStart = true;\n                    script.isLoop = true;\n                    return script;\n                } else if (script.isLoop == true) {\n                    return script;\n                } \n                \n                delete script.isLoop;\n                delete script.isStart;\n                delete script.handCount;\n                return script.callReturn();\n            },\n        },\n    };\n};\n//endregion ArduinoZin 아두이노 확장모드\n\nmodule.exports = Entry.ArduinoZin;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_hasseam.js",
    "content": "'use strict';\n\nEntry.Hasseam = {\n    id: '1.11',\n    name: 'hasseam',\n    url: 'http://www.hanibot.com',\n    imageName: 'hasseam.png',\n    title: {\n        ko: '하쌤 보드',\n        en: 'Hasseam Board',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                if(Entry.hw.sendQueue.SET[key].type==Entry.Hasseam.sensorTypes.DCMOTOR){\n                    Entry.hw.sendQueue.SET[key].data.value1=0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }else{\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.hw.sendQueue.GET={};\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        READ_BLUETOOTH: 9,\n        WRITE_BLUETOOTH: 10,\n        LCD: 11,\n        RGBLED: 12,\n        DCMOTOR: 13,\n        OLED: 14,\n        PIR : 15,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\nEntry.Hasseam.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                hasseam_pulldown:'기본',\n                hasseam_pullup:'풀업',\n                hasseam_toggle_on: '켜기',\n                hasseam_toggle_off: '끄기',\n                hasseam_lcd_first_line: '첫 번째',\n                hasseam_lcd_seconds_line: '두 번째',\n                hasseam_dcmotor_direction_forward: '정방향',\n                hasseam_dcmotor_direction_reverse: '역방향',\n                hasseam_btData_select_number: '숫자',\n                hasseam_btData_select_character: '문자',\n                hasseam_get_analog_value: '아날로그 %1 번 핀 센서 %2 값',\n                hasseam_get_analog_mapping:\n                    '아날로그 %1 번 핀 센서 %2 값의 범위를 %3 ~ %4 에서 %5 ~ %6 로 바꾼 값',\n                hasseam_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\n                hasseam_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n                hasseam_get_digital: '디지털 %1 번 핀 센서 %2 값',\n                hasseam_get_digital_toggle: '디지털 %1 번 핀 센서 %2 값',\n                hasseam_get_digital_pir: 'PIR %1 번 핀 센서 값',\n                hasseam_set_digital_toggle: '디지털 %1 번 핀 %2 %3',\n                hasseam_set_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                hasseam_set_digital_rgbled:\n                    '디지털 %1 번 핀의 RGB LED를 빨강 %2 초록 %3 파랑 %4 로 정하기 %5',\n                hasseam_set_digital_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                hasseam_set_digital_buzzer:\n                    '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                hasseam_set_digital_dcmotor:\n                    'DC모터 %1 번 핀을 %2 %3 번 핀의 속도를 %4 로 정하기 %5',\n                hasseam_module_digital_lcd: 'LCD화면 %1 줄에 %2 나타내기 %3',\n                hasseam_module_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n                hasseam_module_digital_oled: 'OLED화면 X 좌표 %1  Y 좌표 %2 에 %3 나타내기 %4',\n            },\n        },\n        en: {\n            template: {\n                hasseam_pulldown:'pulldown',\n                hasseam_pullup:'pullup',\n                hasseam_toggle_on: 'on',\n                hasseam_toggle_off: 'off',\n                hasseam_lcd_first_line: 'first',\n                hasseam_lcd_seconds_line: 'seconds',\n                hasseam_dcmotor_direction_forward: 'forward',\n                hasseam_dcmotor_direction_reverse: 'reverse',\n                hasseam_btData_select_number: 'number',\n                hasseam_btData_select_character: 'character',\n                hasseam_get_analog_value: 'Read analog %1 pin sensor value %2',\n                hasseam_get_analog_mapping:\n                    'Map analog %1 pin sensor value %2 from %3 ~ %4 to %5 ~ %6',\n                hasseam_get_digital_bluetooth: 'Bluetooth RX 2 value',\n                hasseam_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n                hasseam_get_digital: 'Digital %1 pin sensor value %2',\n                hasseam_get_digital_toggle: 'Digital %1 pin sensor value %2',\n                hasseam_set_digital_toggle: 'Digital %1 pin %2 %3',\n                hasseam_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n                hasseam_set_digital_rgbled: 'Digital %1 pin RGB LED Red %2 Green %3 Blue %4 %5',\n                hasseam_set_digital_servo: 'Set servo pin %1 angle as %2 %3',\n                hasseam_set_digital_buzzer: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                hasseam_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5',\n                hasseam_module_digital_lcd: 'LCD %1 line %2 appear %3',\n                hasseam_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\n                hasseam_module_digital_oled: 'OLED X codinate %1 Y coodinate %2 appear %3 %4',\n            },\n        },\n    };\n};\nEntry.Hasseam.blockMenuBlocks = [\n    'hasseam_get_analog_value',\n    'hasseam_get_analog_mapping',\n    'hasseam_get_digital_bluetooth',\n    'hasseam_get_digital_ultrasonic',\n    'hasseam_get_digital',\n    'hasseam_get_digital_toggle',\n    'hasseam_get_digital_pir',\n    'hasseam_set_digital_toggle',\n    'hasseam_set_digital_pwm',\n    'hasseam_set_digital_rgbled',\n    'hasseam_set_digital_servo',\n    'hasseam_set_digital_buzzer',\n    'hasseam_set_digital_dcmotor',\n    'hasseam_module_digital_lcd',\n    'hasseam_module_digital_bluetooth',\n    'hasseam_module_digital_oled',\n];\nEntry.Hasseam.getBlocks = function() {\n    return {\n        //region hasseam 한쌤보드\n        hasseam_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        hasseam_list_pullup_setting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.hasseam_pulldown, '0'],\n                        [Lang.template.hasseam_pullup, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        hasseam_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        hasseam_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        hasseam_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['~3', '3'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                        ['~11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        hasseam_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.hasseam_toggle_on, 'on'],\n                        [Lang.template.hasseam_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        hasseam_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        hasseam_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.hasseam_lcd_first_line, '0'],\n                        [Lang.template.hasseam_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        hasseam_list_digital_dcmotor_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.hasseam_dcmotor_direction_reverse, '0'],\n                        [Lang.template.hasseam_dcmotor_direction_forward, '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIRECTION');\n            },\n        },\n        hasseam_list_digital_btData_select: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.hasseam_btData_select_number, '0'],\n                        [Lang.template.hasseam_btData_select_character, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIRECTION');\n            },\n        },\n        hasseam_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.hasseam_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_analog_basic',\n                    },\n                    {\n                        type: 'hasseam_list_pullup_setting',\n                    },\n                ],\n                type: 'hasseam_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'hasseamGet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var opr = script.getNumberValue('OPERATOR');\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Hasseam.sensorTypes.ANALOG] = {\n                    port: port,\n                    data: opr,\n                    time: new Date().getTime(),\n                };\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['hasseam.get_analog_value(%1 %2)'] },\n        },\n        hasseam_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.hasseam_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_analog_basic',\n                    },\n                    {\n                        type: 'hasseam_list_pullup_setting',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'hasseam_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                VALUE2: 2,\n                VALUE3: 3,\n                VALUE4: 4,\n                VALUE5: 5,\n            },\n            class: 'hasseamGet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var opr = script.getNumberValue('OPERATOR');\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                result = ANALOG ? ANALOG[port] || 0 : 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if(Entry.hw.sendQueue.SET[port]){\n                    return Entry.hw.sendQueue.SET[port].data;\n                }else{\n                    Entry.hw.sendQueue['GET'][Entry.Hasseam.sensorTypes.DIGITAL] = {\n                        port: port,\n                        data: opr,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['hasseam.get_analog_mapping(%1, %2, %3, %4, %5, %6)'],\n            },\n        },\n        hasseam_get_digital_bluetooth: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.hasseam_get_digital_bluetooth,\n            statements: [],\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'hasseam_get_digital_bluetooth',\n            },\n            paramsKeyMap: {\n            },\n            class: 'hasseamGet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = 2;\n                var getString = Entry.hw.portData.READ_BLUETOOTH;\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Hasseam.sensorTypes.READ_BLUETOOTH] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return getString ? getString.slice(0,getString.length-1) : ' ';\n            },\n            syntax: { js: [], py: ['hasseam.get_digital_bluetooth()'] },\n        },\n        hasseam_get_digital_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.hasseam_get_digital_ultrasonic,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['17'],\n                    },\n                ],\n                type: 'hasseam_get_digital_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'hasseamGet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Hasseam.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['hasseam.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n        hasseam_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.hasseam_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_basic',\n                    },\n                    {\n                        type: 'hasseam_list_pullup_setting',\n                    },\n                ],\n                type: 'hasseam_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'hasseamGet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var opr = script.getNumberValue('OPERATOR');\n                //\"down = 0\" or \"up = 2\"\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if(Entry.hw.sendQueue.SET[port]){\n                    return Entry.hw.sendQueue.SET[port].data;\n                }else{\n                    Entry.hw.sendQueue['GET'][Entry.Hasseam.sensorTypes.DIGITAL] = {\n                        port: port,\n                        data: opr,\n                        time: new Date().getTime(),\n                    };\n                }\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['hasseam.get_digital(%1,%2)'] },\n        },\n        hasseam_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.hasseam_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_basic',\n                    },\n                    {\n                        type: 'hasseam_list_pullup_setting',\n                    },\n                ],\n                type: 'hasseam_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'hasseamGet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var opr = script.getNumberValue('OPERATOR');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if(Entry.hw.sendQueue.SET[port]){\n                    return Entry.hw.sendQueue.SET[port].data;\n                }else{\n                    Entry.hw.sendQueue['GET'][Entry.Hasseam.sensorTypes.DIGITAL] = {\n                        port: port,\n                        data: opr,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['hasseam.get_digital_toggle(%1 %2)'] },\n        },\n        hasseam_get_digital_pir: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.hasseam_get_digital_pir,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_basic',\n                    },\n                ],\n                type: 'hasseam_get_digital_pir',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'hasseamGet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Hasseam.sensorTypes.PIR] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['hasseam.get_digital_pir(%1)'] },\n        },\n        hasseam_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.hasseam_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_basic',\n                    },\n                    {\n                        type: 'hasseam_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'hasseam_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'hasseamSet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Hasseam.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Hasseam.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Hasseam.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['hasseam.set_digital_toggle(%1, %2)'] },\n        },\n        hasseam_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.hasseam_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_pwm',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'hasseam_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'hasseamSet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Hasseam.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['hasseam.set_digital_pwm(%1, %2)'] },\n        },\n        hasseam_set_digital_rgbled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.hasseam_set_digital_rgbled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_basic',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'hasseam_set_digital_rgbled',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE0: 1,\n                VALUE1: 2,\n                VALUE2: 3,\n            },\n            class: 'hasseamSet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = [3];\n                value[0] = script.getNumberValue('VALUE0');\n                value[1] = script.getNumberValue('VALUE1');\n                value[2] = script.getNumberValue('VALUE2');\n\n                for (var i = 0; i < 3; i++) {\n                    value[i] = Math.round(value[i]);\n                    value[i] = Math.min(value[i], 200);\n                    value[i] = Math.max(value[i], 0);\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Hasseam.sensorTypes.RGBLED,\n                    data: {\n                        redValue: value[0],\n                        greenValue: value[1],\n                        blueValue: value[2],\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['hasseam.set_digital_pwm(%1, %2)'] },\n        },\n        hasseam_set_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.hasseam_set_digital_servo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_basic',\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'hasseam_set_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'hasseamSet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Hasseam.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['hasseam.set_digital_servo(%1, %2)'] },\n        },\n        hasseam_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.hasseam_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_basic',\n                    },\n                    {\n                        type: 'hasseam_list_digital_tone',\n                    },\n                    {\n                        type: 'hasseam_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'hasseam_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'hasseamSet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.Hasseam.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.Hasseam.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.Hasseam.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Hasseam.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Hasseam.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['hasseam.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        hasseam_set_digital_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.hasseam_set_digital_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_basic',\n                    },\n                    {\n                        type: 'hasseam_list_digital_dcmotor_direction',\n                    },\n                    {\n                        type: 'hasseam_list_digital_pwm',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'hasseam_set_digital_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT0: 0,\n                VALUE0: 1,\n                PORT1: 2,\n                VALUE1: 3,\n            },\n            class: 'hasseamSet',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = 0; // port value is dummy;\n                var directionPort = script.getNumberValue('PORT0');\n                var speedPort = script.getNumberValue('PORT1');\n                var directionValue = script.getNumberValue('VALUE0');\n                var speedValue = script.getNumberValue('VALUE1');\n\n                speedValue = Math.round(speedValue);\n                speedValue = Math.min(speedValue, 255);\n                speedValue = Math.max(speedValue, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Hasseam.sensorTypes.DCMOTOR,\n                    data: {\n                        port0: directionPort,\n                        port1: speedPort,\n                        value0: directionValue,\n                        value1: speedValue,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['hasseam.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        hasseam_module_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: Lang.template.hasseam_module_digital_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'hasseam_list_digital_lcd',\n                    },\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'hasseam_module_digital_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                STRING: 1,\n            },\n            class: 'hasseamModule',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var line = script.getNumberValue('LINE');\n                var string = script.getValue('STRING');\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = 60 / fps * 50;\n\n                    Entry.hw.sendQueue['SET'][line] = {\n                        type: Entry.Hasseam.sensorTypes.LCD,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['hasseam.module_digital_lcd(%1, %2)'] },\n        },\n        hasseam_module_digital_oled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.hasseam_module_digital_oled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'hasseam_module_digital_oled',\n            },\n            paramsKeyMap: {\n                VALUE0: 0,\n                VALUE1: 1,\n                STRING: 2,\n            },\n            class: 'hasseamModule',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var port = 0; // port value is dummy;\n                var coodinate_x = script.getNumberValue('VALUE0');\n                var coodinate_y = script.getNumberValue('VALUE1');\n                var string = script.getValue('STRING');\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = 60 / fps * 50;\n\n                    coodinate_x = Math.min(coodinate_x, 127);\n                    coodinate_x = Math.max(coodinate_x, 0);\n                    coodinate_y = Math.min(coodinate_y, 63);\n                    coodinate_y = Math.max(coodinate_y, 0);\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Hasseam.sensorTypes.OLED,\n                        data: {\n                            value0: coodinate_x,\n                            value1: coodinate_y,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['hasseam.Module_digital_oled(%1, %2, %3)'] },\n        },\n        hasseam_module_digital_bluetooth: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: Lang.template.hasseam_module_digital_bluetooth,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'hasseam_module_digital_bluetooth',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'hasseamModule',\n            isNotFor: ['hasseam'],\n            func: function(sprite, script) {\n                var string = script.getValue('STRING');\n                var port = 3;\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else {\n                        text[0] = string;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = 60 / fps * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.Hasseam.sensorTypes.WRITE_BLUETOOTH,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['hasseam.module_digital_bluetooth(%1)'] },\n        },\n        //endregion hasseam 하쌤보드\n    };\n};\n\nmodule.exports = Entry.Hasseam;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_hexaboard.js",
    "content": "'use strict';\n\nEntry.HEXABOARD = new (class HEXABOARD {\n  constructor() {\n    this.id = '5A.1'; // 엔트리에서 발급받은 하드웨어 번호를 기술합니다.\n    this.name = 'HEXABOARD'; // isNotFor 속성과 대소문자까지 정확하게 매치되어야 합니다.\n    this.url = 'http://makeitnow.kr/'; // 생략 가능합니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    this.imageName = 'HEXABOARD.png'; // images/hardware, images/hw 폴더 내에 존재하는 이미지입니다.\n    this.title = {\n      'ko': '헥사보드',\n      'en': 'HEXABOARD'\n    };\n\n    this.sensorTypes = {\n    DIGITAL_WRITE: 0x01, // 디지털 출력 변경\n    ANALOG_WRITE: 0x02, // PWM을 이용한 아날로그 출력 변경\n    DIGITAL_READ: 0x03, // 디지털 입력 상태 요청\n    ANALOG_READ: 0x04, // 아날로그 입력 값 요청\n    PLAY_TONE: 0x05, // 부저에 음 재생\n    READ_COLOR_SENSOR: 0x06, // 색상 센서 값 요청 (R,G,B,W)\n    READ_GYRO_SENSOR: 0x07, // 자이로 센서 값 요청\n    UPDATE_NEOPIXEL: 0x08, // 네오픽셀 LED 상태 변경\n    SLIDE_NEOPIXEL: 0x09, //네오픽셀 텍스트 출력\n    DISPLAY_OLED: 0x10, // OLED 값 정의\n    UPDATE_ALL_NEOPIXEL: 0x11, //모든 네오픽셀 켜기\n    // DISPLAY_INIT_OLED: 0x12, // OLED 값 정의\n    READ_DHT_SENSOR : 0x13, //DHT11 센서 값\n    READ_GYRO_ANGLE_SENSOR: 0x17, // 자이로 센서 값 요청\n    READ_ULTRASONIC_SENSOR: 0x18, //초음파 센서 값 요청\n    READ_WEATHER_SENSOR: 0x19, //날씨 센서 값 요청\n    READ_LINE_SENSOR: 0x20, // 근접센서 값 요청\n    // CONNECT_WIFI: 0x21, //WIFI 연결\n    // CONNECT_BLYNK: 0x21, //BLYNK서버 연결\n    // BLYNK_VIRTUAL_WRITE: 0x22, //BLYNK 가상의 핀 데이터 전송\n    // BLYNK_WRITE: 0x23, //BLYNK 상태값 바뀌었을때\n    // CONNECTED_BLYNK: 0x24, //BLYNK서버 연결\n    CLEAR_DISPLAY_OLED: 0x25, // OLED값 리셋\n    READ_WEIGHT_SENSOR: 0x26, //무게센서 값 요청\n    READ_WATERTEMPERATURE_SENSOR: 0x27, //수온센서 값 요청\n    READ_DUST_SENSOR: 0x28, //먼지센서 값 요청\n    READ_WATERQUALITY_SENSOR: 0x29, //수질센서 값요청\n    HEXA_INIT: 0x30,\n    READ_SOUND_SENSOR: 0x31, //소리센서 값요청\n    READ_PRESSURE_SENSOR: 0x32, //압력센서 값요청\n    READ_CO2_SENSOR: 0x33, //CO2센서 값요청\n    READ_TOUCH_SENSOR: 0x34, //터치센서 값요청\n    WRITE_MOTOR_SENSOR: 0x35, //모터 값 요청\n    WRITE_SERVOMOTOR_SENSOR: 0x36, //서보모터 값 요청\n    OLED_HEXA: 0x37, //Hexa 앞의 oled 값 요청\n    WRITE_VEHICLE_LED: 0x38, //차량LED 값 요청\n    OLED_PRINT: 0x39, //OLED 출력\n    READ_GYRO_INTENSITY: 0x40, //자이로센서 세기 값 요청\n    CUSTOM_NEOPIXEL_LED: 0x41, //네오픽셀 매트릭스 LED 상태 변경\n    };\n    // 자이로 센서에 대한 추가적인 세부 명령 정의\n    this.gyro_command = {\n    LEFT: 0x11,\n    RIGHT: 0x12,\n    FRONT: 0x13,\n    BACK: 0x14,\n    UP: 0x15,\n    DOWN: 0x16,\n    ANGLE_X: 0x17,\n    ANGLE_Y: 0x18,\n    ANGLE_Z: 0x19,\n    };\n    this.command = {\n      READ: 1,\n      WRITE: 0,\n    };\n    // 센서 초기화 플래그들\n    this.sensorInitialized = {\n      digitalRead: false,\n      analogRead: false,\n      weather: false,\n      line: false,\n      dust: false,\n      weight: false,\n      button: false,\n      waterTemperature: false,\n      waterQuality: false,\n      sound: false,\n      pressure: false,\n      dht: false,\n      co2: false,\n      gyro: false,\n      gyroAngle: false,\n      gyroIntensity: false,\n      ultrasonic: false,\n      color: false,\n      rgbColor: false,\n      touch: false,\n    };\n    this.blockMenuBlocks = [\n      'makeitnow_input_title',\n      'makeitnow_input_subtitle',\n      'makeitnow_digitalRead_hexa',\n      'makeitnow_analogRead_hexa',\n      'makeitnow_weather_title',\n      'makeitnow_sensor_weather',\n      'makeitnow_line_title',\n      'makeitnow_sensor_line',\n      'makeitnow_dust_title',\n      'makeitnow_sensor_dust',\n      'makeitnow_weight_title',\n      'makeitnow_sensor_weight',\n      'makeitnow_button_title',\n      'makeitnow_buttonRead_hexa',\n      'makeitnow_watertemperature_title',\n      'makeitnow_sensor_watertemperature',\n      'makeitnow_waterquality_title',\n      'makeitnow_sensor_waterquality',\n      'makeitnow_sound_title',\n      'makeitnow_sensor_sound',\n      'makeitnow_pressure_title',\n      'makeitnow_sensor_pressure',\n      'makeitnow_dht11_title',\n      'makeitnow_sensor_dht11',\n      'makeitnow_co2_title',\n      'makeitnow_sensor_co2',\n      'makeitnow_gyro_title',\n      'makeitnow_gyro_hexa',\n      'makeitnow_gyro_direction_hexa',\n      'makeitnow_gyro_intensity_hexa',\n      'makeitnow_ultrasonic_title',\n      'makeitnow_sensor_ultrasonic',\n      'makeitnow_color_title',\n      'makeitnow_getColor_hexa',\n      'makeitnow_get_RGBColor_hexa',\n      'makeitnow_touch_title',\n      'makeitnow_sensor_touch',\n      'makeitnow_output_title',\n      'makeitnow_output_subtitle',\n      'makeitnow_digitalwrite_hexa',\n      'makeitnow_pwm_hexa',\n      'makeitnow_buzzer_title',\n      'makeitnow_buzzer_hexa',\n      'makeitnow_buzzer_off_hexa',\n      'makeitnow_motor_title',\n      'makeitnow_motor_hexa',\n      'makeitnow_servomotor_hexa',\n      'makeitnow_vehicle_led_title',\n      'makeitnow_vehicle_led',\n      'makeitnow_neo_title',\n      'makeitnow_neo_messageslide_hexa',\n      'neopixel_set_led',\n      'hexaboard_show_custom_image',\n      'makeitnow_neoled_onecolorset_hexa',\n      'makeitnow_neoled_allColorSet_hexa',\n      'makeitnow_neoled_oneColorSelect_hexa',\n      'makeitnow_neoled_AllColorSelect_hexa',\n      'makeitnow_neoled_AllOff_hexa',\n      'makeitnow_oled_title',\n      'makeitnow_display_oled_hexa',\n      'makeitnow_oled_print_hexa',\n      'makeitnow_oled_clear_hexa',\n      'makeitnow_percentage_conversion_title',\n      'makeitnow_percentage_conversion',\n      'makeitnow_wireless_title',\n    ];\n  }\n\n  rgbToHex(r, g, b) {\n    const toHex = c => c.toString(16).padStart(2, '0');\n    return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();\n  }\n\n  reduceColorHex(hex, percent) {\n    // 16진수 색상 코드를 R, G, B로 분리\n    const r = parseInt(hex.substring(1, 3), 16);\n    const g = parseInt(hex.substring(3, 5), 16);\n    const b = parseInt(hex.substring(5, 7), 16);\n\n    // 각 색상 구성 요소에 백분율 적용\n    const newR = Math.round(r * percent / 100);\n    const newG = Math.round(g * percent / 100);\n    const newB = Math.round(b * percent / 100);\n\n    // 새로운 색상 코드 생성\n    return \"#\" + ((1 << 24) + (newR << 16) + (newG << 8) + newB).toString(16).slice(1).toUpperCase();\n  }\n\n  setZero() {\n    // 엔트리 정지시 하드웨어 초기화 로직\n    // for(let i = 2 ; i <= 13 ; i++) {\n    //   Entry.hw.sendQueue.PORT[i] = 0;\n    // }\n    // 모든 센서 초기화 플래그 리셋\n    Object.keys(this.sensorInitialized).forEach(key => {\n      this.sensorInitialized[key] = false;\n    });\n    console.log('setZero: 모든 센서 초기화 플래그 리셋');\n    if (!Entry.hw.sendQueue.SET) {\n      Entry.hw.sendQueue.SET = {};\n    }\n    Entry.hw.sendQueue.SET = {\n      type: Entry.HEXABOARD.command.WRITE,\n      data: {\n        command : Entry.HEXABOARD.sensorTypes.HEXA_INIT,\n      },\n    };\n    // console.log(\"Reset\");\n    Entry.hw.update(); // 하드웨어에 명시적으로 정보를 보냄.\n    delete Entry.hw.sendQueue.SET;\n  }\n\n  // 언어 적용\n  setLanguage() {\n    return {\n    ko: {\n      // ko.js에 작성하던 내용\n      template: {\n        hexaboard_show_custom_image: 'LED 출력하기 %1 색상 %2 ',\n        neopixel_set_led: 'LED의 X: %1 Y: %2 를 밝기 %3 (으)로 밝히기 %4',\n        makeitnow_input_title : '입력',\n        makeitnow_input_subtitle : '입력',\n        makeitnow_weather_title : '날씨 센서',\n        makeitnow_sensor_weather: '날씨센서 %1값 읽기',\n        makeitnow_line_title : '라인 센서',\n        makeitnow_sensor_line: '라인감지 : %1값 읽기',\n        makeitnow_dust_title : '먼지 센서',\n        makeitnow_sensor_dust : '미세먼지센서 %1 에서 %2 값 읽기',\n        makeitnow_weight_title : '무게 센서',\n        makeitnow_sensor_weight: '무게센서 값 읽기 DATA : %1 SCK : %2',\n        makeitnow_button_title : '버튼 센서',\n        makeitnow_buttonRead_hexa : '버튼 %1 값 읽기',\n        makeitnow_watertemperature_title : '수온 센서',\n        makeitnow_sensor_watertemperature: '수중 온도 센서 %1핀에서 온도값 읽기',\n        makeitnow_waterquality_title : '수질 센서',\n        makeitnow_sensor_waterquality : '수질센서: %1 에서 값 읽기',\n        makeitnow_sound_title : '소리 센서',\n        makeitnow_sensor_sound : '소리 센서 %1값 읽기',\n        makeitnow_pressure_title : '압력 센서',\n        makeitnow_sensor_pressure : '압력 센서에서 %1 값 읽기',\n        makeitnow_digitalRead_hexa : '디지털 %1 읽기',\n        makeitnow_analogRead_hexa : '아날로그 %1 읽기',\n        makeitnow_dht11_title : '온습도 센서',\n        makeitnow_sensor_dht11: '온습도센서 %1 에서 %2값 가져오기',\n        makeitnow_co2_title : 'CO2 센서',\n        makeitnow_sensor_co2 : 'CO2센서에서 %1 값 읽기',\n        makeitnow_gyro_title : '자이로 센서',\n        makeitnow_gyro_hexa : '보드가 %1로 기울어진진 각도',\n        makeitnow_gyro_direction_hexa : '보드가 %1방향으로 기울었을 때',\n        makeitnow_gyro_intensity_hexa : '움직임 세기 값 읽기',\n        makeitnow_ultrasonic_title : '초음파 센서',\n        makeitnow_sensor_ultrasonic: '초음파센서에서 %1값 읽기',\n        makeitnow_color_title : '컬러 센서',\n        makeitnow_getColor_hexa : '컬러센서 %1 값 읽기',\n        makeitnow_get_RGBColor_hexa : '컬러센서 %1 과 같은 색상 탐지',\n        makeitnow_touch_title : '터치 센서',\n        makeitnow_sensor_touch : '터치센서 %1 값 읽기',\n        \n        \n        makeitnow_output_title : '출력',\n        makeitnow_output_subtitle : '출력',\n        makeitnow_digitalwrite_hexa : '디지털 출력 %1 핀에 %2 값 출력',\n        makeitnow_pwm_hexa : '아날로그 출력 %1핀에 %2 값 출력',\n        makeitnow_buzzer_title : '소리',\n        makeitnow_buzzer_hexa: '소리내기 옥타브 %1, 음이름 %2, 지속시간 %3',\n        makeitnow_buzzer_off_hexa : '소리 끄기',\n        makeitnow_motor_title : '모터',\n        makeitnow_motor_hexa : '%1 속도 : %2',\n        makeitnow_servomotor_hexa : '%1 각도 : %2',\n        makeitnow_vehicle_led_title : 'LED',\n        makeitnow_vehicle_led : '차량LED : %1에 %2 값 출력',\n\n        makeitnow_neo_messageslide_hexa : '문자출력 %1 빠르기 %2 색상 %3',\n        makeitnow_neo_bitmap_hexa : 'LED 출력하기 ' +\n          '%1%2%3%4%5'+\n          '%6%7%8%9%10' +\n          '%11%12%13%14%15' +\n          '%16%17%18%19%20' +\n          '%21%22%23%24%25',\n        makeitnow_neoled_onecolorset_hexa : '%1 %2개중 %3번째 빨강%4 초록%5 파랑%6',\n        makeitnow_neoled_allColorSet_hexa : '%1 %2개 모두 빨강%3 초록%4 파랑%5',\n        makeitnow_neoled_oneColorSelect_hexa : '%1 %2개중 %3번째 %4 밝기 %5%',\n        makeitnow_neoled_AllColorSelect_hexa : '%1 %2개 모두 %3 밝기 %4%',\n        makeitnow_neoled_AllOff_hexa : '%1 %2개 모두 끄기',\n        makeitnow_neo_title : '네오픽셀',\n        makeitnow_oled_title : 'OLED 디스플레이',\n        makeitnow_oled_print_hexa : 'OLED 출력 %1',\n        // makeitnow_oled_setting_hexa : 'OLED 사용하기 주소%1 %2',\n        makeitnow_oled_clear_hexa: 'OLED 모두 지우기 %1',\n        makeitnow_display_oled_hexa : 'X:%1 Y:%2에 %3출력 크기%4 %5',\n        // makeitnow_wireless_title : '무선통신',\n        // makeitnow_wireless_wifiConnect_hexa : 'WIFI연결 이름%1 비밀번호%2 인증번호%3 %4',\n        // makeitnow_wireless_serverConnect_hexa: '서버 인증번호:%1 %2',\n        // makeitnow_wireless_serverSend_hexa : '가상핀 %1에 %2값 전송 %3',\n        // makeitnow_wireless_serverReceived_hexa: '가상핀 ( V%1 )값을 가져오기',\n        makeitnow_wireless_blynk_title : '',\n        makeitnow_percentage_conversion_title: '값 변환',\n        makeitnow_percentage_conversion: '값 %1의 범위 %2 ~ %3 을 %4 ~ %5 로 변환',\n      }\n    },\n    en: {\n      // en.js에 작성하던 내용\n      template: {\n        hexaboard_show_custom_image: 'LED %1 %2 color brightness %3',\n        neopixel_set_led: 'LED %1 %2 color brightness %3',\n        makeitnow_input_title : 'input',\n        makeitnow_input_subtitle : 'input',\n        makeitnow_weather_title : 'Weather Sensor',\n        makeitnow_sensor_weather: 'Read weather sensor %1 value',\n        makeitnow_line_title : 'Line Sensor',\n        makeitnow_sensor_line: 'Read line sensor %1 value',\n        makeitnow_dust_title : 'Dust Sensor',\n        makeitnow_sensor_dust : 'Read %2 value from %1 dust sensor',\n        makeitnow_weight_title : 'Weight Sensor',\n        makeitnow_sensor_weight: 'Read weight sensor value DATA %1 SCK %2',\n        makeitnow_button_title : 'Button Sensor',\n        makeitnow_buttonRead_hexa: 'Read %1 button value',\n        makeitnow_watertemperature_title : 'Watertemperature Sensor',\n        makeitnow_sensor_watertemperature: 'water temperature sensor %1 temperature value',\n        makeitnow_waterquality_title : 'Waterquality Sensor',\n        makeitnow_sensor_waterquality : 'Read value from water quality sensor %1 (reference temperature: %2)',\n        makeitnow_sound_title : 'Sound Sensor',\n        makeitnow_sensor_sound : 'Read sound sensor %1 value',\n        makeitnow_pressure_title : 'Pressure Sensor',\n        makeitnow_sensor_pressure : 'Read pressure sensor value %1',\n        makeitnow_digitalRead_hexa: 'Read %1 digital signal',\n        makeitnow_analogRead_hexa: 'Read %1 analog signal',\n        makeitnow_dht11_title : 'Humidity Sensor',\n        makeitnow_sensor_dht11: 'Humidity sensor %1, get %2 value',\n        makeitnow_co2_title : 'CO2 Sensor',\n        makeitnow_sensor_co2: 'Read %1 value from the CO2 sensor',\n        makeitnow_gyro_title : 'Gyro Sensor',\n        makeitnow_gyro_hexa: 'Board tilt angle %1',\n        makeitnow_gyro_direction_hexa: 'Direction of board tilt %1',\n        makeitnow_gyro_intensity_hexa: 'Read movement intensity value',\n        makeitnow_ultrasonic_title : 'Ultrasonic Sensor',\n        makeitnow_sensor_ultrasonic: 'ultrasonic sensor %1 value',\n        makeitnow_color_title : 'Color Sensor',\n        makeitnow_getColor_hexa: 'Read color value %1',\n        makeitnow_get_RGBColor_hexa: 'Detect color %1',\n        makeitnow_touch_title : 'Touch Sensor',\n        makeitnow_sensor_touch: 'Read value from touch sensor %1',\n\n\n        makeitnow_output_title : 'output',\n        makeitnow_output_subtitle : 'output',\n        makeitnow_digitalwrite_hexa: 'Digital output to pin %1 value %2',\n        makeitnow_pwm_hexa: 'Analog output to pin %1 value %2',\n        makeitnow_buzzer_title : 'buzzer',\n        makeitnow_buzzer_hexa: 'Sound octave %1, note %2, duration %3',\n        makeitnow_buzzer_off_hexa: 'Turn off sound',\n        makeitnow_motor_title : 'motor',\n        makeitnow_motor_hexa : '%1 Speed : %2',\n        makeitnow_servomotor_hexa : '%1 Angle : %2',\n        makeitnow_vehicle_led_title : 'LED',\n        makeitnow_vehicle_led : 'Vehicle LED : Display %2 on %1',\n\n        makeitnow_neo_messageslide_hexa: 'Display text %1 speed %2 color %3',\n        makeitnow_neo_bitmap_hexa: 'LED output ' +\n          '%1%2%3%4%5'+\n          '%6%7%8%9%10' +\n          '%11%12%13%14%15' +\n          '%16%17%18%19%20' +\n          '%21%22%23%24%25',\n        makeitnow_neoled_onecolorset_hexa: '%1 Set LED %2 at position %3 red%4 green%5 blue%6',\n        makeitnow_neoled_allColorSet_hexa: '%1 Set all %2 LEDs red%3 green%4 blue%5',\n        makeitnow_neoled_oneColorSelect_hexa: '%1 Set LED %2 at position %3 brightness %4%',\n        makeitnow_neoled_AllColorSelect_hexa: '%1 Set all %2 LEDs brightness %3%',\n        makeitnow_neoled_AllOff_hexa: '%1 Turn off all %2 LEDs',\n        makeitnow_neo_title: 'NeoPixel',\n        makeitnow_oled_title: 'OLED Display',\n        makeitnow_oled_print_hexa: 'OLED Display %1',\n        // makeitnow_oled_setting_hexa: 'Setup OLED address %1 %2',\n        makeitnow_display_oled_hexa: 'Print at X:%1 Y:%2 %3 size%4 %5',\n        makeitnow_oled_clear_hexa: 'Clear OLED %1',\n        // makeitnow_wireless_title: 'Wireless Communication',\n        // makeitnow_wireless_wifiConnect_hexa: 'Connect to WiFi name %1 password %2 auth %3 %4',\n        // makeitnow_wireless_serverReceived_hexa: 'Retrieve value from virtual pin ( V%1 )',\n        makeitnow_wireless_blynk_title: 'Blynk Wireless',\n        makeitnow_percentage_conversion_title: 'Value Conversion',\n        makeitnow_percentage_conversion: 'Convert value %1 range %2 ~ %3 to %4 ~ %5',\n\n      }\n    }\n    };\n  }\n\n  // 블록 생성\n  getBlocks() {\n    const HEXABOARD = Entry.HEXABOARD;\n\n    return {\n    /*\n    * 입력력 관련 블록\n    */\n    makeitnow_input_title :{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 10,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_input_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_input_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_input_subtitle:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_input_title, color: '#333333', align: 'left'        \n        }\n      ],\n      def: {\n        type: 'makeitnow_input_subtitle',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_digitalRead_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [\"PIN1\", \"32\"],\n            [\"PIN2\", \"33\"],\n            [\"PIN3\", \"4\"],\n          ],\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class: 'input',\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"32\"],\n        type: \"makeitnow_digitalRead_hexa\",\n      },\n      paramsKeyMap: {\n        PIN: 0,\n      },\n      func: function(sprite, script) {\n        const pin_num = script.getField('PIN', script);\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.digitalRead) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.DIGITAL_READ,\n              pin : pin_num,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.digitalRead = true;\n        }\n\n        let hwVal = Entry.hw.portData[pin_num];\n        if (hwVal !== undefined) {\n          return hwVal;\n        } else {\n          return script.callReturn();\n        }\n      }\n    },\n\n    makeitnow_analogRead_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"32\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"32\"],\n        type: \"makeitnow_analogRead_hexa\",\n      },\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      func: function(sprite, script) {\n        const pin = script.getField('PIN', script);\n        const pinName = `A${pin}`\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.analogRead) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.ANALOG_READ,\n              pin :  pin,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.analogRead = true;\n        }\n\n        let hwVal = Entry.hw.portData[pinName];\n        console.log('[ANALOG READ]', pinName, hwVal);\n        if (hwVal !== undefined ){\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      }\n    },\n\n    makeitnow_weather_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        {\n          type: 'Text', text: Lang.template.makeitnow_input_title, color: '#333333', align: 'left'\n        },\n      ],\n      def: {\n        type: 'makeitnow_weather_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    //날씨 센서\n    makeitnow_sensor_weather :{\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"온도\", \"1\" ],\n            [ \"습도\", \"0\" ],\n            [ \"기압\", \"2\" ],\n            [ \"고도\", \"3\"],\n          ],\n          \"value\": \"1\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        \n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"1\"],\n        type: \"makeitnow_sensor_weather\",\n      },\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      class : 'input',\n      func: function (sprite, script) {\n        const pin = script.getField('PIN', script);\n        \n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.weather) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_WEATHER_SENSOR,\n              pin : pin,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.weather = true;\n        }\n\n        let hwVal = Entry.hw.portData[`W${pin}`];\n        if (hwVal !== undefined ){\n          // 온도(\"1\")와 습도(\"0\")는 1000단위를 10.00 형식으로 변환 (100으로 나눔)\n          if (pin === \"0\" || pin === \"1\") {\n            return hwVal / 100;\n          }\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_line_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_line_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_line_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    \n    makeitnow_sensor_line : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor:'#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"1\", \"0\" ],\n            [ \"2\", \"1\" ],\n            [ \"3\", \"2\" ],\n            [ \"4\", \"3\" ],\n          ],\n          \"value\": \"0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할 수 있습니다.\n        params: [\"0\"],\n        type: \"makeitnow_sensor_line\",\n      },\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      class: 'input',\n      func: function (sprite, script) {\n        const pin = Number(script.getField('PIN', script));\n        const pinnumber = `L${pin}`;\n        \n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.line) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_LINE_SENSOR,\n              pin : pin,\n            },\n          };\n          console.log('[PROX REQUEST]', Entry.hw.sendQueue.SET);\n          Entry.hw.update();\n          console.log('[PORTDATA AFTER]', pinnumber, Entry.hw.portData[pinnumber]);\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.line = true;\n        }\n\n        let hwVal = Entry.hw.portData[pinnumber];\n        console.log('[PROX READ]', pinnumber, hwVal);\n        if (hwVal !== undefined ){\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_dust_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_dust_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_dust_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_dust : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"32\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PM1.0\", \"0\" ],\n            [ \"PM2.5\", \"1\" ],\n            [ \"PM10\", \"2\" ],\n          ],\n          \"value\": \"0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"32\",\"0\"],\n        type: \"makeitnow_sensor_dust\",\n      },\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n        PM : 1,\n      },\n      func: function(sprite, script) {\n        const pin = script.getField('PIN', script);\n        const pm = script.getField('PM', script);\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.dust) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_DUST_SENSOR,\n              pin : pin,\n              pm : pm,\n            },\n          };\n\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.dust = true;\n        }\n\n        const dustKey = `DU${pm}`;\n        let hwVal = Entry.hw.portData[dustKey];\n        console.log('[DUST READ]', dustKey, hwVal);\n        if (hwVal !== undefined ){\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      }\n    },\n\n    makeitnow_weight_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_weight_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_weight_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_weight : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"32\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"32\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n        SCK : 1,\n      },\n      func: function (sprite, script) {\n        const pin = script.getField('PIN', script);\n        const sck = script.getField('SCK', script);\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.weight) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_WEIGHT_SENSOR,\n              pin : pin,\n              sck : sck,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.weight = true;\n        }\n\n        let hwVal = Entry.hw.portData[`WD${pin}`];\n        if (hwVal !== undefined ){\n          return hwVal / 10;\n        }else{\n          return script.callReturn();\n        }\n      },\n    },  \n\n    makeitnow_button_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_button_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_button_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_buttonRead_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"A\", \"35\" ],\n            [ \"B\", \"34\" ],\n          ],\n          \"value\": \"35\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"35\"],\n        type: \"makeitnow_buttonRead_hexa\",\n      },\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      func: function (sprite, script) {\n        const pin_num = script.getField('PIN', script);\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.button) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.DIGITAL_READ,\n              pin : pin_num,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.button = true;\n        }\n\n        let hwVal = Entry.hw.portData[pin_num];\n        if ( hwVal !== undefined ){\n          return hwVal; // 하드웨어에서 읽은 값 반환\n        }else{\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_watertemperature_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_watertemperature_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_watertemperature_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_watertemperature : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor:'#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"0\" ],\n            [ \"PIN2\", \"1\" ],\n            [ \"PIN3\", \"2\" ],\n          ],\n          \"value\": \"0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        {type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12},\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할 수 있습니다.\n        params: [\"0\"],\n        type: \"makeitnow_sensor_watertemperature\",\n      },\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      class: 'input',\n      func: function (sprite, script) {\n        const pin = script.getField('PIN', script);\n        \n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.waterTemperature) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_WATERTEMPERATURE_SENSOR,\n              pin : pin,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.waterTemperature = true;\n        }\n\n        let hwVal = Entry.hw.portData[`WA${pin}`];\n        if (hwVal !== undefined ){\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_waterquality_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_waterquality_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_waterquality_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_waterquality : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"0\" ],\n            [ \"PIN2\", \"1\" ],\n            [ \"PIN3\", \"2\" ],\n          ],\n          \"value\": \"0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"0\"],\n        type: \"makeitnow_sensor_waterquality\",\n      },\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      func: function(sprite, script) {\n        const pin = script.getField('PIN', script);  //pin번호로 key받아오기 \n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.waterQuality) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_WATERQUALITY_SENSOR,\n              pin : pin,\n            },\n          };\n          console.log('[PROX REQUEST]', Entry.hw.sendQueue.SET);\n          Entry.hw.update();\n          console.log('[PORTDATA AFTER]', pin, Entry.hw.portData[`WQ${pin}`]);\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.waterQuality = true;\n        }\n\n        let hwVal = Entry.hw.portData[`WQ${pin}`];\n        if (hwVal !== undefined ){\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      }\n    },\n\n    makeitnow_sound_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_sound_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_sound_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_sound : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"32\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"32\"],\n        type: \"makeitnow_sensor_sound\",\n      },\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      func: function(sprite, script) {\n        const pin = script.getField('PIN', script);  //pin번호로 key받아오기 \n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.sound) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_SOUND_SENSOR,\n              pin :  pin,\n            },\n          };\n          Entry.hw.update();  \n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.sound = true;\n        }\n\n        let hwVal = Entry.hw.portData[`S${pin}`];\n        if (hwVal !== undefined ){\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      }\n    },\n\n    makeitnow_pressure_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_pressure_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_pressure_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_pressure : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"압력\", \"0\" ],\n            [ \"온도\", \"1\" ],\n          ],\n          \"value\": \"0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"0\"],\n        type: \"makeitnow_sensor_pressure\",\n      },\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      func: function(sprite, script) {\n        const pin = script.getField('PIN', script);  //pin번호로 key받아오기 \n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.pressure) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_PRESSURE_SENSOR,\n              pin : pin,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.pressure = true;\n        }\n\n        let hwVal = Entry.hw.portData[`P${pin}`];\n        if (hwVal !== undefined ){\n          if (pin === \"1\") {\n            return hwVal / 100;\n          }\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      }\n    },\n\n    makeitnow_dht11_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_dht11_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_dht11_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_dht11 : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"32\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"온도\", \"D1\" ],\n            [ \"습도\", \"D0\" ],\n          ],\n          \"value\": \"D0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"32\", \"D1\"],\n        type: \"makeitnow_sensor_dht11\",\n      },\n      paramsKeyMap: {\n        PIN : 0,\n        VALUE : 1,\n      },\n      class : 'input',\n      func: function (sprite, script) {\n        const pin = script.getField('PIN', script);\n        const dht11 = script.getField('VALUE', script);\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.dht) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_DHT_SENSOR,\n              pin : pin,\n              value : dht11,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.dht = true;\n        }\n\n        let hwVal = Entry.hw.portData[dht11];\n        if (hwVal !== undefined ){\n          hwVal = hwVal / 100;\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_co2_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_co2_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_co2_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_co2 : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"이산화탄소\", \"0\" ],\n            [ \"온도\", \"1\" ],\n            [ \"습도\", \"2\" ],\n          ],\n          \"value\": \"0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"0\"],\n        type: \"makeitnow_sensor_co2\",\n      },\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      func: function(sprite, script) {\n        const pin = script.getField('PIN', script);  //pin번호로 key받아오기 \n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.co2) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_CO2_SENSOR,\n              pin :  pin,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.co2 = true;\n        }\n\n        let hwVal = Entry.hw.portData[`CO2${pin}`];\n        if (hwVal !== undefined ){\n          if (pin === \"1\" || pin === \"2\") {\n            return hwVal / 100;\n          }\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      }\n    },\n\n    makeitnow_gyro_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_gyro_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_gyro_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_gyro_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"좌우\", 0 ],\n            [ \"상하\", 1 ],\n            [ \"앞뒤\", 2 ],\n          ],\n          \"value\": 0,\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        // { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [0],\n        type: \"makeitnow_gyro_hexa\",\n      },\n      class : 'input',\n      paramsKeyMap: {\n        GYRO : 0,\n      },\n      func: function (sprite, script) {\n        const gyro = script.getField('GYRO', script); // 핀 번호를 가져옵니다.\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.gyro) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_GYRO_SENSOR,\n              pin :  gyro,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.gyro = true;\n        }\n\n        // 하드웨어 모듈에서 'A${port}' 형식으로 저장하므로 동일한 형식으로 접근\n        const portKey = `A${gyro}`;\n        let hwVal = Entry.hw.portData[portKey] ?? 0;\n        if (hwVal !== undefined){\n          return hwVal;\n        }else {\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_gyro_direction_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"왼쪽\", HEXABOARD.gyro_command.LEFT ],\n            [ \"오른쪽\", HEXABOARD.gyro_command.RIGHT ],\n            [ \"앞쪽\", HEXABOARD.gyro_command.FRONT ],\n            [ \"뒤쪽\", HEXABOARD.gyro_command.BACK ],\n            [ \"앞면\", HEXABOARD.gyro_command.UP ],\n            [ \"뒷면\", HEXABOARD.gyro_command.DOWN ],\n          ],\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        // { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [HEXABOARD.gyro_command.LEFT],\n        type: \"makeitnow_gyro_direction_hexa\",\n      },\n      class : 'input',\n      // isNotFor: ['HEXABOARD'],\n      paramsKeyMap: {\n        GYRO : 0,\n      },\n      func: function (sprite, script) {\n        const gyro = script.getField('GYRO', script); // 핀 번호를 가져옵니다.\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.gyroAngle) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_GYRO_ANGLE_SENSOR,\n              pin :  gyro,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.gyroAngle = true;\n        }\n\n        // 하드웨어 큐에 데이터 추가\n        let hwVal = Entry.hw.portData[gyro];\n        if ( hwVal !== undefined ){\n          return hwVal;\n        }else {\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_gyro_intensity_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [],\n      def: {\n        type: 'makeitnow_gyro_intensity_hexa',\n      },\n      class : 'input',\n      // isNotFor: ['HEXABOARD'],\n\n      params: [\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n\n      isNotFor: ['HEXABOARD'],\n      class: 'input',\n\n      paramsKeyMap: {\n        GYRO : 0,\n      },\n\n      func: function (sprite, script) {\n        const gi = script.getField('GYRO', script);\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.gyroIntensity) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_GYRO_INTENSITY,\n              pin :  gi,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.gyroIntensity = true;\n        }\n\n        // 하드웨어 큐에 데이터 추가\n        let hwVal = Entry.hw.portData['GI'];\n        if ( hwVal !== undefined ){\n          return hwVal;\n        }else {\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_ultrasonic_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_ultrasonic_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_ultrasonic_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    //초음파 센서\n    makeitnow_sensor_ultrasonic: {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field',      // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n    \n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          type: \"Dropdown\",\n          options: [\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          value: \"32\",\n          fontSize: 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"32\"],\n        type: \"makeitnow_sensor_ultrasonic\",\n      },\n    \n      paramsKeyMap: {\n        PIN: 0,\n      },\n    \n      class: 'input',\n    \n      func: function (sprite, script) {\n        const pin = script.getField('PIN', script);\n        const pinnumber = `U${pin}`;\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.ultrasonic) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_ULTRASONIC_SENSOR,\n              pin : pin,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.ultrasonic = true;\n        }\n\n        let hwVal = Entry.hw.portData[pinnumber];\n        if (hwVal !== undefined ){\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_color_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_color_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_color_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_getColor_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"빨강\", \"0\" ],\n            [ \"초록\", \"1\" ],\n            [ \"파랑\", \"2\" ],\n            [ \"밝기(lux)\", \"3\" ],\n          ],\n          \"value\": \"0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        // { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"3\"],\n        type: \"makeitnow_getColor_hexa\",\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      func: function (sprite, script) {\n        //TODO : 이 곳에 통신 코드 작성하기\n        const pin_num = script.getField('PIN', script);\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.color) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_COLOR_SENSOR,\n              pin : pin_num,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.color = true;\n        }\n        \n        let hwVal = Entry.hw.portData[`C${pin_num}`];\n        // console.log(`pin_num : ${pin_num} , hwVal : ${hwVal}`);\n        if ( hwVal !== undefined ){\n          return hwVal; // 하드웨어에서 읽은 값 반환\n        }else{\n          return script.callReturn();\n        }\n      },\n    },\n\n    makeitnow_get_RGBColor_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"빨강\", \"0\" ],\n            [ \"초록\", \"1\" ],\n            [ \"파랑\", \"2\" ],\n          ],\n          \"value\": \"0\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        // { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"0\"],\n        type: \"makeitnow_get_RGBColor_hexa\",\n      },\n      paramsKeyMap: {\n        VALUE : 0,\n      },\n      func: function (sprite, script) {\n        //TODO : 이 곳에 통신 코드 작성하기\n        const colorChoice = script.getField('VALUE', script);\n        const redValue = Entry.hw.portData[`C${0}`];\n        const greenValue = Entry.hw.portData[`C${1}`];\n        const blueValue = Entry.hw.portData[`C${2}`];\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.rgbColor) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_COLOR_SENSOR,\n              pin : colorChoice,  \n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.rgbColor = true;\n        }\n\n        // let hwVal = Entry.hw.portData[`C${colorChoice}`];\n        // // console.log(`pin_num : ${pin_num} , hwVal : ${hwVal}`);\n        // if ( hwVal !== undefined ){\n        //   return hwVal; // 하드웨어에서 읽은 값 반환\n        // }else{\n        //   return script.callReturn();\n        // }\n\n        if (colorChoice === \"0\") { // 빨강 선택\n          return (redValue > greenValue && redValue > blueValue) ? 1 : 0;\n        } else if (colorChoice === \"1\") { // 초록 선택\n          return (greenValue > redValue && greenValue > blueValue) ? 1 : 0;\n        } else if (colorChoice === \"2\") { // 파랑 선택\n          return (blueValue > redValue && blueValue > greenValue) ? 1 : 0;\n        }\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_touch_title:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', \n          text: Lang.template.makeitnow_touch_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_touch_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'input',\n      fontSize:22,\n    },\n\n    makeitnow_sensor_touch : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"32\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"32\"],\n        type: \"makeitnow_sensor_touch\",\n      },\n      class : 'input',\n      paramsKeyMap: {\n        PIN : 0,\n      },\n      func: function(sprite, script) {\n        const pin = script.getField('PIN', script);\n\n        // 최초 한번만 하드웨어 업데이트 실행\n        if (!Entry.HEXABOARD.sensorInitialized.touch) {\n          if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue.SET = {};\n          }\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.READ,\n            data: {\n              command : Entry.HEXABOARD.sensorTypes.READ_TOUCH_SENSOR,\n              pin :  pin,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          Entry.HEXABOARD.sensorInitialized.touch = true;\n        }\n\n        let hwVal = Entry.hw.portData[`T${pin}`];\n        // console.log('[TOUCH READ]', pinName, hwVal);\n        if (hwVal !== undefined ){\n          return hwVal;\n        }else{\n          return script.callReturn();\n        }\n      }\n    },\n\n     \n\n\n    /*\n    * 출력 블록 섹션\n    * */\n\n    makeitnow_output_title :{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_output_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_output_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n    },\n\n    makeitnow_output_subtitle:{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_output_subtitle, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_output_subtitle',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n      fontSize:22,\n    },\n\n    makeitnow_digitalwrite_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"보드LED\", \"2\" ],\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"2\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"낮은\", \"0\" ],\n            [ \"높은\", \"1\" ],\n          ],\n          \"value\": \"1\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n      paramsKeyMap: {\n        PIN: 0,\n        VALUE : 1,\n      },\n      func: function (sprite, script) {\n        var pin = script.getField('PIN', script); // 핀 번호를 가져옵니다.\n        var value = script.getField('VALUE', script); // 설정할 값을 가져옵니다.\n\n        // 하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.DIGITAL_WRITE,\n            pin : pin,\n            value: value\n          },\n        };\n        console.log(Entry.hw.sendQueue.SET);\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_pwm_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"보드LED\", \"2\" ],\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"value\": \"2\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type: \"Block\",\n          accept: \"string\",\n          \"value\": \"1023\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n      paramsKeyMap: {\n        PIN: 0,\n        VALUE : 1,\n      },\n      func: function (sprite, script) {\n        const pin = script.getField('PIN', script); // 핀 번호를 가져옵니다.\n        const value = script.getNumberValue('VALUE', script); // 설정할 값을 가져옵니다.\n        console.log(value);\n        // 하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.ANALOG_WRITE,\n            pin : pin,\n            value: value\n          },\n        };\n        // console.log(Entry.hw.sendQueue.SET);\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },  \n\n    makeitnow_buzzer_title :{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_buzzer_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_buzzer_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n    },\n\n    makeitnow_buzzer_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          type: \"Dropdown\",\n          options: [\n            [ \"1\", \"1\" ],\n            [ \"2\", \"2\" ],\n            [ \"3\", \"3\" ],\n            [ \"4\", \"4\" ],\n            [ \"5\", \"5\" ],\n            [ \"6\", \"6\" ],\n          ],\n          \"value\": \"3\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type: \"Dropdown\",\n          options: [\n            [ \"도\", \"32.7032\" ],\n            [ \"도#\", \"34.6478\" ],\n            [ \"레\", \"36.7081\" ],\n            [ \"레#\", \"38.8909\" ],\n            [ \"미\", \"41.2034\" ],\n            [ \"파\", \"43.6535\" ],\n            [ \"파#\", \"46.2493\" ],\n            [ \"솔\", \"48.9994\" ],\n            [ \"솔#\", \"51.9130\" ],\n            [ \"라\", \"55.0000\" ],\n            [ \"라#\", \"58.2705\" ],\n            [ \"시\", \"61.7354\" ],\n          ],\n          \"value\": \"32.7032\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type: \"Block\",\n          accept: \"string\",\n          value : \"0.3\",\n          fontSize: 11,\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n      paramsKeyMap: {\n        OCTAVE : 0,\n        SCALE : 1,\n        DURATION : 2,\n      },\n      func: function (sprite, script) {\n        const octave = script.getField('OCTAVE', script); // 핀 번호를 가져옵니다.\n        const scale = script.getField('SCALE', script); // 핀 번호를 가져옵니다.\n        const duration = Math.round(script.getNumberValue('DURATION', script) * 10) / 10; // 소수점 첫째 자리까지 반올림\n\n        console.log(`duration: ${duration}`);\n        let multiplier = Math.pow(2, octave - 1);\n        let note_value = Math.round(scale * multiplier);\n\n        /***\n         * TODO : 부저 빠르게 출력하면 출력이 되지 않는 이슈\n         */\n        // 하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.PLAY_TONE,\n            pin : 27,\n            value : note_value,\n            duration : duration,\n          },\n          time: new Date().getTime()\n        };\n        // console.log(Entry.hw.sendQueue.SET);\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_buzzer_off_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n      func: function (sprite, script) {\n        // 하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.PLAY_TONE,\n            pin : 27,\n            value: 0,\n            duration : 0,\n          },\n          time: new Date().getTime()\n        };\n        console.log(Entry.hw.sendQueue.SET);\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_motor_title :{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_motor_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_motor_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n    },\n\n    makeitnow_motor_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic',\n      statements: [],\n      params: [\n        {\n          type: \"Dropdown\",\n          options: [\n            [ \"Motor_A\", \"A\" ],\n            [ \"Motor_B\", \"B\" ],\n          ],\n          value: \"A\",\n          fontSize: 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type: \"Block\",\n          accept: \"string\",\n          value: \"0\",\n          fontSize: 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],  \n      class : 'output',\n      def: {\n        params: [\"A\", \"0\"],\n        type: \"makeitnow_motor_hexa\",\n      },\n      paramsKeyMap: {\n        MOTOR : 0,\n        SPEED : 1,\n      },\n      func: function (sprite, script) {\n        const motor = script.getField('MOTOR', script);\n        let value = script.getStringValue('SPEED', script);\n    \n        if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.WRITE_MOTOR_SENSOR,\n            pin : motor,\n            speed : value,\n          },\n        };\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n    makeitnow_servomotor_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic',\n      statements: [],\n      params: [\n        {\n          type: \"Dropdown\",\n          options: [\n            [ \"Servo_A\", \"A\" ],\n            [ \"Servo_B\", \"B\" ],\n          ],\n          value: \"A\",\n          fontSize: 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type: \"Block\",\n          accept: \"string\",\n          value: \"0\",\n          fontSize: 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n      def: {\n        params: [\"A\", \"0\"],\n        type: \"makeitnow_servomotor_hexa\",\n      },\n      paramsKeyMap: {\n        MOTOR : 0,\n        ANGLE : 1,\n      },\n      func: function (sprite, script) {\n        const motor = script.getField('MOTOR', script);\n        let value = script.getStringValue('ANGLE', script);\n        if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.WRITE_SERVOMOTOR_SENSOR,\n            pin : motor,\n            angle : value,\n          },\n        };\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_vehicle_led_title :{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        { \n          type: 'Text', text: Lang.template.makeitnow_vehicle_led_title, color: '#333333', align: 'left' \n        }\n      ],\n      def: {\n        type: 'makeitnow_vehicle_led_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n    },\n\n    makeitnow_vehicle_led : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic',\n      statements: [],\n      params: [\n        {\n          type: \"Dropdown\",\n          options: [\n            [ \"왼쪽 LED\", \"19\" ],\n            [ \"오른쪽 LED\", \"18\" ],\n          ],\n          value: \"0\",\n          fontSize: 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"낮은\", \"0\" ],\n            [ \"높은\", \"1\" ],\n          ],\n          \"value\": \"1\",\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'output',\n      def: {\n        params: [\"19\", \"1\"],\n        type: \"makeitnow_vehicle_led\",\n      },\n      paramsKeyMap: {\n        PIN : 0,\n        VALUE : 1,\n      },\n      func: function (sprite, script) {\n        var pin = script.getField('PIN', script); // 핀 번호를 가져옵니다.\n        var value = script.getField('VALUE', script); // 설정할 값을 가져옵니다.\n\n        // 하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.WRITE_VEHICLE_LED,\n            pin : pin,\n            value: value\n          },\n        };\n        console.log(Entry.hw.sendQueue.SET);\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n\n    /*\n    * 네오픽셀 섹션\n    * */\n    makeitnow_neo_title :{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      def: {\n        type: 'makeitnow_neo_title',\n      },\n      isNotFor: ['HEXABOARD'],\n      class : 'neopixel_hexa',\n    },\n\n    makeitnow_neo_messageslide_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          type : \"Block\",\n          accept : \"string\"\n        },\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"1\", \"1\" ],\n            [ \"2\", \"2\" ],\n            [ \"3\", \"3\" ],\n            [ \"4\", \"4\" ],\n            [ \"5\", \"5\" ],\n            [ \"6\", \"6\" ],\n            [ \"7\", \"7\" ],\n            [ \"8\", \"8\" ],\n            [ \"9\", \"9\" ],\n            [ \"10\", \"10\" ],\n          ],\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type: \"Color\",\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      events: {},\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"HEXABOARD\", '1', null],\n        type: \"makeitnow_neo_messageslide_hexa\",\n      },\n      isNotFor: ['HEXABOARD'],\n      class: 'neopixel_hexa',\n      paramsKeyMap: {\n        TEXT: 0,\n        SPEED: 1,\n        COLOR: 2,\n      },\n      isNotFor: ['HEXABOARD'],\n      func: function (sprite, script) {\n        const text = script.getStringValue('TEXT', script);\n        const slide_speed = script.getNumberValue('SPEED', script);\n        const color_value = script.getStringField('COLOR', script);\n\n        //하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.SLIDE_NEOPIXEL,\n            message : text,\n            speed : slide_speed,\n            color : color_value,\n          },\n        };\n        // console.log(Entry.hw.sendQueue.SET);\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    hexaboard_show_custom_image: {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      skeleton: 'basic',\n      statements: [],\n      params: [\n          {\n              type: 'Led2',\n          },\n          {\n            type : \"Color\",\n          },\n          {\n              type: 'Indicator',\n              img: 'block_icon/hardware_icon.svg',\n              size: 12,\n          },\n      ],\n      events: {},\n      isNotFor: ['HEXABOARD'],\n\n      class: 'neopixel_hexa',\n      // isNotFor: ['microbit2'],\n      def: {\n          params: [HEXABOARD.defaultLed, null],\n          type: 'hexaboard_show_custom_image',\n      },\n      \n      paramsKeyMap: {\n          VALUE: 0,\n          COLOR: 1,\n        },\n        func: function(sprite, script) {\n          const value = script.getField('VALUE');      // Led2 매트릭스\n          const color_value = script.getField('COLOR'); // \"#RRGGBB\"\n          console.log(value);\n          console.log(color_value);\n        \n          const processedValue = [];\n          for (const i in value) processedValue[i] = value[i].join();\n          const parsedPayload = `${processedValue.join(':').replace(/,/gi, '')}`;\n          console.log(parsedPayload);\n\n          Entry.hw.sendQueue.SET = {\n            type: Entry.HEXABOARD.command.WRITE,\n            data: {\n              command: Entry.HEXABOARD.sensorTypes.CUSTOM_NEOPIXEL_LED,\n              payload: parsedPayload,\n              color: color_value,\n            },\n          };\n          Entry.hw.update();\n          delete Entry.hw.sendQueue.SET;\n          return script.callReturn();\n        },\n  },\n\n    makeitnow_neoled_onecolorset_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"HEXABOARD\", \"23\" ],\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"23\", \"25\", \"1\", \"0\", \"0\", \"0\"],\n        type: \"makeitnow_neoled_onecolorset_hexa\",\n      },\n      \n      class: 'neopixel_hexa',\n      paramsKeyMap: {\n        PIN: 0,\n        NUM: 1,\n        INDEX: 2,\n        RED: 3,\n        GREEN: 4,\n        BLUE: 5,\n      },\n      isNotFor: ['HEXABOARD'],\n      func: function (sprite, script) {\n        const pin_num = script.getField('PIN', script);\n        const led_num = script.getNumberValue('NUM', script);\n        const led_index = script.getNumberValue('INDEX', script);\n        const redColor = script.getNumberValue('RED', script);\n        const greenColor = script.getNumberValue('GREEN', script);\n        const blueColor = script.getNumberValue('BLUE', script);\n\n        let color_value = Entry.HEXABOARD.rgbToHex(redColor, greenColor, blueColor);\n\n        //하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.UPDATE_NEOPIXEL,\n            pin : pin_num,\n            ledNum : led_num,\n            ledIndex : led_index,\n            color : color_value,\n          },\n        };\n        // console.log(Entry.hw.sendQueue.SET);\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_neoled_allColorSet_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"HEXABOARD\", \"23\" ],\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"23\", \"25\", \"0\", \"0\", \"0\"],\n        type: \"makeitnow_neoled_allColorSet_hexa\",\n      },\n      class: 'neopixel_hexa',\n      paramsKeyMap: {\n        PIN: 0,\n        LEDNUM: 1,\n        RED: 2,\n        GREEN: 3,\n        BLUE: 4,\n      },\n      isNotFor: ['HEXABOARD'],\n      func: function (sprite, script) {\n        const pin_num = script.getField('PIN', script);\n        const led_num = script.getNumberValue('LEDNUM', script);\n        const redColor = script.getNumberValue('RED', script);\n        const greenColor = script.getNumberValue('GREEN', script);\n        const blueColor = script.getNumberValue('BLUE', script);\n        let color_value = Entry.HEXABOARD.rgbToHex(redColor, greenColor, blueColor);\n\n        //하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.UPDATE_ALL_NEOPIXEL,\n            pin : pin_num,\n            ledNum : led_num,\n            color : color_value,\n          },\n        };\n        // console.log(Entry.hw.sendQueue.SET);\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_neoled_oneColorSelect_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"HEXABOARD\", \"23\" ],\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Color\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        params: [\"23\", \"25\",\"1\" , null, \"20\"],\n        type: \"makeitnow_neoled_oneColorSelect_hexa\",\n      },\n      class: 'neopixel_hexa',\n      paramsKeyMap: {\n        PIN: 0,\n        NUM: 1,\n        INDEX: 2,\n        COLOR : 3,\n        BRIGHTNESS : 4,\n      },\n      isNotFor: ['HEXABOARD'],\n      func: function (sprite, script) {\n        const pin_num = script.getField('PIN', script);\n        const led_num = script.getNumberValue('NUM', script);\n        const led_index = script.getNumberValue('INDEX', script);\n        const color_value = script.getStringField('COLOR', script);\n        const brightness_value = script.getNumberValue('BRIGHTNESS', script);\n        let cal_color_value = Entry.HEXABOARD.reduceColorHex(color_value, brightness_value);\n\n        //하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.UPDATE_NEOPIXEL,\n            pin : pin_num,\n            ledNum : led_num,\n            ledIndex : led_index,\n            color : cal_color_value,\n          },\n        };\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_neoled_AllColorSelect_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"HEXABOARD\", \"23\" ],\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Color\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        params: [\"23\", \"25\", null, \"20\"],\n        type: \"makeitnow_neoled_AllColorSelect_hexa\",\n      },\n      class: 'neopixel_hexa',\n      paramsKeyMap: {\n        PIN: 0,\n        NUM: 1,\n        COLOR : 2,\n        BRIGHTNESS : 3,\n      },\n      isNotFor: ['HEXABOARD'],\n      func: function (sprite, script) {\n        const pin_num = script.getField('PIN', script);\n        const led_num = script.getNumberValue('NUM', script);\n        const color_value = script.getStringField('COLOR', script);\n        const brightness_value = script.getNumberValue('BRIGHTNESS', script);\n        let cal_color_value = Entry.HEXABOARD.reduceColorHex(color_value, brightness_value);\n\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.UPDATE_ALL_NEOPIXEL,\n            pin : pin_num,\n            ledNum : led_num,\n            color : cal_color_value,\n          },\n        };\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_neoled_AllOff_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      statements: [],\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          \"type\": \"Dropdown\",\n          \"options\": [\n            [ \"HEXABOARD\", \"23\" ],\n            [ \"PIN1\", \"32\" ],\n            [ \"PIN2\", \"33\" ],\n            [ \"PIN3\", \"4\" ],\n          ],\n          \"fontSize\": 11,\n          bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n          arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        params: [\"23\", \"25\"],\n        type: \"makeitnow_neoled_AllOff_hexa\",\n      },\n      class: 'neopixel_hexa',\n      paramsKeyMap: {\n        PIN: 0,\n        NUM: 1,\n      },\n      isNotFor: ['HEXABOARD'],\n      func: function (sprite, script) {\n        const pin_num = script.getField('PIN', script);\n        const led_num = script.getNumberValue('NUM', script); // 핀 번호를 가져옵니다.\n        //하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.UPDATE_ALL_NEOPIXEL,\n            pin : pin_num,\n            ledNum : led_num,\n            color : '#000000',\n          },\n          time: new Date().getTime()\n        };\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    /*\n     * 디스플레이 : OLED\n     * */\n    makeitnow_oled_title :{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        {\n          type: 'Text',\n          text: Lang.template.makeitnow_oled_title,\n          color: '#333333',\n          align: 'left',\n        },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'oled_hexa',\n    },\n\n    // *************** OLED 주소 설정 ***************\n    // makeitnow_oled_setting_hexa : {\n    //   color: EntryStatic.colorSet.block.default.HARDWARE,\n    //   outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n    //   fontColor: '#ffffff',\n    //   skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n    //   statements: [\n    //     {\n    //       accept: 'basic',\n    //     },\n    //   ],\n    //   params: [\n    //     //입력될 파라미터들의 속성을 정의\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n    //     { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n    //   ],\n    //   def: {\n    //     // def의 params의 경우는 초기값을 지정할수 있습니다.\n    //     params: [\"60\"],\n    //     type: \"makeitnow_oled_setting_hexa\",\n    //   },\n    //   class: 'oled_hexa',\n    //   paramsKeyMap: {\n    //     I2C_ADDRESS: 0,\n    //   },\n    //   isNotFor: ['HEXABOARD'],\n    //   func: function (sprite, script) {\n    //     const i2c_addr = script.getNumberValue('I2C_ADDRESS', script); // 핀 번호를 가져옵니다.\n    //     //하드웨어 큐에 데이터 추가\n    //     if (!Entry.hw.sendQueue.SET) {\n    //       Entry.hw.sendQueue.SET = {};\n    //     }\n\n    //     Entry.hw.sendQueue.SET = {\n    //       type: Entry.HEXABOARD.command.WRITE,\n    //       data: {\n    //         command : Entry.HEXABOARD.sensorTypes.DISPLAY_INIT_OLED,\n    //         address : i2c_addr,\n    //       },\n    //       time: new Date().getTime()\n    //     };\n    //     // console.log(Entry.hw.sendQueue.SET);\n    //     Entry.hw.update();\n    //     delete Entry.hw.sendQueue.SET;\n    //     return script.callReturn();\n    //   },\n    // },\n\n    makeitnow_display_oled_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      params: [\n        //입력될 파라미터들의 속성을 정의\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        {\n          type : \"Block\",\n          accept : \"string\",\n        },\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        params: [\"0\", \"0\", \"HEXABOARD\", \"1\"],\n        type: \"makeitnow_display_oled_hexa\",\n      },\n      isNotFor: ['HEXABOARD'],\n      class: 'oled_hexa',\n      paramsKeyMap: {\n        POSITION_X: 0,\n        POSITION_Y: 1,\n        TEXT : 2,\n        FONTSIZE : 3,\n      },\n      func: function (sprite, script) {\n        const position_x = script.getNumberValue('POSITION_X', script);\n        const position_y = script.getNumberValue('POSITION_Y', script);\n        const text = script.getStringValue('TEXT', script);\n        const font_size = script.getNumberValue('FONTSIZE', script);\n\n        //하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.DISPLAY_OLED,\n            x : position_x,\n            y : position_y,\n            message : text,\n            fontsize : font_size,\n          },\n          time: new Date().getTime()\n        };\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_oled_print_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      params: [\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        type: \"makeitnow_oled_print_hexa\",\n      },\n      isNotFor: ['HEXABOARD'],\n      class: 'oled_hexa',\n      func: function (sprite, script) {\n\n        //하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.OLED_PRINT,\n          },\n        };\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n\n    makeitnow_oled_clear_hexa : {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n      params: [\n        // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n      ],\n      def: {\n        // def의 params의 경우는 초기값을 지정할수 있습니다.\n        type: \"makeitnow_oled_clear_hexa\",\n      },\n      isNotFor: ['HEXABOARD'],\n      class: 'oled_hexa',\n      func: function (sprite, script) {\n        //TODO : 이 곳에 통신 코드 작성하기\n\n        //하드웨어 큐에 데이터 추가\n        if (!Entry.hw.sendQueue.SET) {\n          Entry.hw.sendQueue.SET = {};\n        }\n\n        Entry.hw.sendQueue.SET = {\n          type: Entry.HEXABOARD.command.WRITE,\n          data: {\n            command : Entry.HEXABOARD.sensorTypes.CLEAR_DISPLAY_OLED,\n          },\n        };\n        Entry.hw.update();\n        delete Entry.hw.sendQueue.SET;\n        return script.callReturn();\n      },\n    },\n    \n    makeitnow_percentage_conversion_title: {\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      params: [\n        {\n          type: 'Text',\n          text: Lang.template.makeitnow_percentage_conversion_title,\n          color: '#333333',\n          align: 'left',\n        },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class: 'function',\n    },\n\n    makeitnow_percentage_conversion: {\n      color: EntryStatic.colorSet.block.default.HARDWARE,\n      outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n      fontColor: '#ffffff',\n      skeleton: 'basic_string_field',\n      params: [\n        { type: \"Block\", accept: \"string\" }, // VALUE\n        { type: \"Block\", accept: \"number\" }, // MIN\n        { type: \"Block\", accept: \"number\" }, // MAX\n        { type: \"Block\", accept: \"number\" }, // NEW_MIN\n        { type: \"Block\", accept: \"number\" }, // NEW_MAX\n        { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 14 },\n      ],\n      def: {\n        type: \"makeitnow_percentage_conversion\",\n        params: [0, 0, 4095, 0, 100], // 기본값 꼭 주기\n      },\n      paramsKeyMap: {\n        VALUE: 0,\n        MIN: 1,\n        MAX: 2,\n        NEW_MIN: 3,\n        NEW_MAX: 4,\n      },\n      isNotFor: ['HEXABOARD'],\n      class: 'function',\n      func: function (sprite, script) {\n        const value  = script.getNumberValue('VALUE', script);\n        const min    = script.getNumberValue('MIN', script);\n        const max    = script.getNumberValue('MAX', script);\n        const newMin = script.getNumberValue('NEW_MIN', script);\n        const newMax = script.getNumberValue('NEW_MAX', script);\n    \n        // 0으로 나누기 방지\n        if (max === min) return newMin;\n    \n        const result = (value - min) * (newMax - newMin) / (max - min) + newMin;\n    \n        // 범위 클램핑 (결과값이 newMin~newMax 범위를 벗어나지 않도록)\n        const clampedResult = Math.max(newMin, Math.min(newMax, result));\n        return Math.round(clampedResult);\n      },\n    },\n\n    /*\n * 디스플레이 : 무선통신\n * */\n    makeitnow_wireless_title :{\n      skeleton: 'basic_text',\n      color: EntryStatic.colorSet.common.TRANSPARENT,\n      fontColor: '#333333',\n      skeletonOptions: {\n        contentPos: {\n          x: 20,\n          y: 10,\n        },\n      },\n      \n      params: [\n        {\n          type: 'Text',\n          text: Lang.template.makeitnow_oled_title,\n          color: '#333333',\n          align: 'left',\n        },\n      ],\n      isNotFor: ['HEXABOARD'],\n      class : 'wireless_hexa',\n    },\n    \n\n    // makeitnow_percentage_conversion : {\n    //   color: EntryStatic.colorSet.block.default.HARDWARE,\n    //   outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n    //   fontColor: '#ffffff',\n    //   skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n    //   params: [\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     {\n    //       type : \"Block\",\n    //       accept : \"number\",\n    //     },\n    //     {\n    //       type : \"Block\",\n    //       accept : \"number\",\n    //     },\n    //     {\n    //       type : \"Block\",\n    //       accept : \"number\",\n    //     },\n    //     {\n    //       type : \"Block\",\n    //       accept : \"number\",\n    //     },\n    //     { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 14 },\n    //   ],\n    //   def: {\n    //     type: \"makeitnow_percentage_conversion\",\n    //   },\n    //   isNotFor: ['HEXABOARD'],\n    //   class: 'input',\n    //   func: function (sprite, script) {\n    //     const value = script.getField('VALUE', script);\n    //     const min = script.getNumberValue('MIN', script);\n    //     const max = script.getNumberValue('MAX', script);\n    //     const newMin = script.getNumberValue('NEW_MIN', script);\n    //     const newMax = script.getNumberValue('NEW_MAX', script);\n    //     const result = Math.round((value - min) * (newMax - newMin) / (max - min) + newMin);\n    //     return script.callReturn(result);\n    //   },\n    // },\n\n    // ***************WIFI 연결 ***************\n    // makeitnow_wireless_wifiConnect_hexa : {\n    //   color: EntryStatic.colorSet.block.default.HARDWARE,\n    //   outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n    //   fontColor: '#ffffff',\n    //   skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n    //   params: [\n    //     //입력될 파라미터들의 속성을 정의\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n    //     { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n    //   ],\n    //   def: {\n    //     // def의 params의 경우는 초기값을 지정할수 있습니다.\n    //     // params: [\"SSID\", \"PASSWORD\", \"AUTH_TOKEN\"],\n    //     params: [\"WIFI이름\", \"비밀번호\", \"AUTH_TOKEN\"],\n    //     type: \"makeitnow_wireless_wifiConnect_hexa\",\n    //   },\n    //   isNotFor: ['HEXABOARD'],\n    //   class: 'wireless_hexa',\n    //   paramsKeyMap: {\n    //     SSID: 0,\n    //     PW: 1,\n    //     AUTH_TOKEN: 2,\n    //   },\n    //   func: function (sprite, script) {\n    //     const ssid = script.getStringValue('SSID', script);\n    //     const password = script.getStringValue('PW', script);\n    //     const authToken = script.getStringValue('AUTH_TOKEN', script);\n\n    //     //하드웨어 큐에 데이터 추가\n    //     if (!Entry.hw.sendQueue.SET) {\n    //       Entry.hw.sendQueue.SET = {};\n    //     }\n\n    //     Entry.hw.sendQueue.SET = {\n    //       type: Entry.HEXABOARD.command.WRITE,\n    //       data: {\n    //         command : Entry.HEXABOARD.sensorTypes.CONNECT_WIFI,\n    //         ssid : ssid,\n    //         password : password,\n    //         authToken : authToken,\n    //       },\n    //       time: new Date().getTime()\n    //     };\n    //     // console.log(Entry.hw.sendQueue.SET);\n    //     Entry.hw.update();\n    //     delete Entry.hw.sendQueue.SET;\n    //     return script.callReturn();\n    //   },\n    // },\n\n\n    // makeitnow_wireless_serverConnect_hexa : {\n    //   color: EntryStatic.colorSet.block.default.HARDWARE,\n    //   outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n    //   fontColor: '#ffffff',\n    //   skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n    //   params: [\n    //     //입력될 파라미터들의 속성을 정의\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n    //     { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n    //   ],\n    //   def: {\n    //     // def의 params의 경우는 초기값을 지정할수 있습니다.\n    //     params: [\"AUTH_TOKEN\"],\n    //     type: \"makeitnow_wireless_serverConnect_hexa\",\n    //   },\n    //   isNotFor: ['HEXABOARD'],\n    //   class: 'wireless_hexa',\n    //   func: function (sprite, script) {\n    //     //TODO : 이 곳에 통신 코드 작성하기\n    //   },\n    // },\n\n    // *************** Blynk 연결 ***************\n    // makeitnow_wireless_serverSend_hexa : {\n    //   color: EntryStatic.colorSet.block.default.HARDWARE,\n    //   outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n    //   fontColor: '#ffffff',\n    //   skeleton: 'basic', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n    //   params: [\n    //     //입력될 파라미터들의 속성을 정의\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n    //     { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n    //   ],\n    //   def: {\n    //     // def의 params의 경우는 초기값을 지정할수 있습니다.\n    //     params: [\"0\", \"숫자\"],\n    //     type: \"makeitnow_wireless_serverSend_hexa\",\n    //   },\n    //   isNotFor: ['HEXABOARD'],\n    //   class: 'wireless_hexa',\n    //   paramsKeyMap: {\n    //     VIRTUAL_PIN: 0,\n    //     DATA: 1,\n    //   },\n    //   func: function (sprite, script) {\n    //     const virtual_pin = script.getNumberValue('VIRTUAL_PIN', script);\n    //     const send_data = script.getStringValue('DATA', script);\n\n    //     //하드웨어 큐에 데이터 추가\n    //     if (!Entry.hw.sendQueue.SET) {\n    //       Entry.hw.sendQueue.SET = {};\n    //     }\n\n    //     Entry.hw.sendQueue.SET = {\n    //       type: Entry.HEXABOARD.command.WRITE,\n    //       data: {\n    //         command : Entry.HEXABOARD.sensorTypes.BLYNK_VIRTUAL_WRITE,\n    //         virtualPin : virtual_pin,\n    //         value : send_data,\n    //       },\n    //     };\n    //     // console.log(Entry.hw.sendQueue.SET);\n    //     Entry.hw.update();\n    //     delete Entry.hw.sendQueue.SET;\n    //     return script.callReturn();\n    //   },\n    // },\n\n    // *************** Blynk 가상핀 값 읽기 ***************\n    // makeitnow_wireless_serverReceived_hexa : {\n    //   color: EntryStatic.colorSet.block.default.HARDWARE,\n    //   outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n    //   fontColor: '#ffffff',\n    //   // fontSize: 13,\n    //   skeleton: 'basic_string_field', // 블록 모양 템플릿. 자세한 목록은 docs 를 참고해주세요\n    //   statements: [\n    //     {\n    //       accept: 'basic',\n    //     },\n    //   ],\n    //   params: [\n    //     //입력될 파라미터들의 속성을 정의\n    //     {\n    //       type : \"Block\",\n    //       accept : \"string\",\n    //     },\n    //     // basic skeleton 의 마지막엔 인디케이터를 추가해주셔야 합니다.\n    //     // { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n    //   ],\n    //   def: {\n    //     // def의 params의 경우는 초기값을 지정할수 있습니다.\n    //     params: [\"0\"],\n    //     type: \"makeitnow_wireless_serverReceived_hexa\",\n    //   },\n    //   isNotFor: ['HEXABOARD'],\n    //   class: 'wireless_hexa',\n    //   paramsKeyMap: {\n    //     VIRTUAL_PIN: 0,\n    //   },\n    //   func: function (sprite, script) {\n    //     const virtual_pin = script.getNumberValue('VIRTUAL_PIN', script);\n    //     const dataStream = `V${virtual_pin}`;\n    //     //하드웨어 큐에 데이터 추가\n    //     let hwVal = Entry.hw.portData[dataStream];\n    //     // console.log(`DataStream ${dataStream}  value : ${hwVal}`);\n    //     if ( hwVal !== undefined ){\n    //       return hwVal; // 하드웨어에서 읽은 값 반환\n    //     }else{\n    //       return script.callReturn();\n    //     }\n    //   },\n    // },\n\n    // *************** Blynk 타이틀 ***************\n    // makeitnow_wireless_blynk_title :{\n    //   skeleton: 'basic_text',\n    //   color: EntryStatic.colorSet.common.TRANSPARENT,\n    //   fontColor: '#333333',\n    //   skeletonOptions: {\n    //     box: {\n    //       offsetX: 20,\n    //     },\n    //   },\n    //   params: [\n    //     {\n    //       type: 'Text',\n    //       text: Lang.template.makeitnow_oled_title,\n    //       color: '#333333',\n    //       align: 'left',\n    //     },\n    //   ],\n    //   isNotFor: ['HEXABOARD'],\n    //   class : 'wireless_hexa',\n    // },\n    };\n  }\n})();\n\n// 엔트리에서 하드웨어 블록 클래스를 인식할 수 있도록 내보내기\nmodule.exports = Entry.HEXABOARD;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_hummingbird.js",
    "content": "'use strict';\n\nEntry.hummingbird = {\n    PORT_MAP: {\n        triLEDR1: 256, //D7\n        triLEDG1: 256, //D4\n        triLEDB1: 256, //D12\n        triLEDR2: 256, //D11\n        triLEDG2: 256, //D6\n        triLEDB2: 256, //D5\n        led1: 256, //D3\n        led2: 256, //D2\n        led3: 256, //HWB\n        led4: 256, //A0\n        vibrat1: 256, //D9\n        vibrat2: 256, //D10\n        dcMotor1: 256, //spi\n        dcMotor2: 256, //spi\n        //servo1: 256,  //spi\n        //servo2: 256,  //spi\n        //servo3: 256, //spi\n        //servo4: 256  //spi\n    },\n    setZero: function() {\n        var portMap = Entry.hummingbird.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        var hummingbird = Entry.hummingbird;\n        hummingbird.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n\n    //장치이름, 부사장님과 상의가 필요 일단 허밍버드로\n    id: '1C.1',\n    name: 'hummingbird',\n    url: 'http://www.creartbot.com/hummingbird',\n    imageName: 'hummingbirdduo.png',\n    title: {\n        en: 'Hummingbird Duo',\n        ko: '허밍버드 듀오',\n    },\n};\nEntry.hummingbird.blockMenuBlocks = [\n    //hummingbirdduo\n    'hummingbird_sensorValue',\n    'hummingbird_temperatureValue',\n    'hummingbird_lightValue',\n    'hummingbird_distanceValue',\n    'hummingbird_rotaryValue',\n    'hummingbird_soundValue',\n    'hummingbird_vibeMotor',\n    'hummingbird_servo',\n    'hummingbird_dcMotor',\n    'hummingbird_triLED',\n    'hummingbird_led',\n];\nEntry.hummingbird.getBlocks = function() {\n    return {\n        //region hummingbird 허밍버드\n        //Hummingbird parts\n        //범용 센서\n        hummingbird_sensorValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '아날로그센서 %1번 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'adc1'], ['2', 'adc2'], ['3', 'adc3'], ['4', 'adc4']],\n                    value: 'adc1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hummingbird_sensorValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hummingbird_sensor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        //온도센서\n        hummingbird_temperatureValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: 'HB 온도센서 %1번 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'adc1'], ['2', 'adc2'], ['3', 'adc3'], ['4', 'adc4']],\n                    value: 'adc1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hummingbird_temperatureValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hummingbird_sensor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                var rawData = (pd[dev] >> 2) & 0xff;\n                var temperature_value = Math.floor(((rawData - 127) / 2.4 + 25) * 100 / 100);\n                return temperature_value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        // 빛 블럭\n        hummingbird_lightValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: 'HB 빛센서 %1번 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'adc1'], ['2', 'adc2'], ['3', 'adc3'], ['4', 'adc4']],\n                    value: 'adc1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hummingbird_lightValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hummingbird_sensor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                var light_value = Math.round(pd[dev] * 100 / 1024);\n                return light_value;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        // 거리센서 블럭\n        hummingbird_distanceValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: 'HB 거리센서 %1번 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'adc1'], ['2', 'adc2'], ['3', 'adc3'], ['4', 'adc4']],\n                    value: 'adc1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hummingbird_distanceValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hummingbird_sensor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n\n                var distance = 0;\n                var reading = ((pd[dev] >> 2) & 0xff) * 4;\n                if (reading < 130) {\n                    distance = 100.0;\n                } else {\n                    reading = reading - 120;\n                    if (reading > 680) {\n                        distance = 5.0;\n                    } else {\n                        var sensor_val_square = reading * reading;\n                        distance =\n                            sensor_val_square * sensor_val_square * reading * -0.000000000004789 +\n                            sensor_val_square * sensor_val_square * 0.000000010057143 -\n                            sensor_val_square * reading * 0.000008279033021 +\n                            sensor_val_square * 0.003416264518201 -\n                            reading * 0.756893112198934 +\n                            90.707167605683;\n                    }\n                }\n                return Math.floor(distance);\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        // 소음 센서 블럭\n        hummingbird_soundValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: 'HB 소리센서 %1번 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'adc1'], ['2', 'adc2'], ['3', 'adc3'], ['4', 'adc4']],\n                    value: 'adc1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hummingbird_soundValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hummingbird_sensor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                var sound_value = (pd[dev] >> 2) & 0xff;\n\n                if (sound_value > 14) {\n                    return Math.round((sound_value - 15) * 3 / 2);\n                } else {\n                    return 0;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        // 회전센서\n        hummingbird_rotaryValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: 'HB 로터리센서 %1번 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'adc1'], ['2', 'adc2'], ['3', 'adc3'], ['4', 'adc4']],\n                    value: 'adc1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'hummingbird_rotaryValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'hummingbird_sensor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                var rotary_value = Math.round(pd[dev] * 100 / 1024);\n                //if (rotary_value == 0) rotary_value = 1;\n                return rotary_value;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        //진동모터\n        hummingbird_vibeMotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: 'HB 진동모터 %1번 세기: %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'vibeMotor1'], ['2', 'vibeMotor2']],\n                    value: 'vibeMotor1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'hummingbird_vibeMotor',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'hummingbird_motor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getNumberValue('VALUE', script);\n\n                if (value > 100) value = 127;\n                else if (value < 0) value = 0;\n                else value = Math.floor(value * 1.27); // 0 ~ 127\n\n                if (dev == 'vibeMotor1') sq.vibrat1 = value;\n                else if (dev == 'vibeMotor2') sq.vibrat2 = value;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        //서보모터\n        hummingbird_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: 'HB 서보모터 %1번 각도: %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'servo1'], ['2', 'servo2'], ['3', 'servo3'], ['4', 'servo4']],\n                    value: 'servo1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'hummingbird_servo',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'hummingbird_motor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var mtype = script.getStringField('DEVICE', script);\n                var angle = script.getNumberValue('VALUE', script);\n\n                if (angle < 0) angle = 0;\n                else if (angle > 180) angle = 180;\n\n                if (mtype == 'servo1') sq.servo1 = angle;\n                else if (mtype == 'servo2') sq.servo2 = angle;\n                else if (mtype == 'servo3') sq.servo3 = angle;\n                else if (mtype == 'servo4') sq.servo4 = angle;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        //기어모터\n        hummingbird_dcMotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: 'HB 기어모터 %1번 속도: %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'dcMotor1'], ['2', 'dcMotor2']],\n                    value: 'dcMotor1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'hummingbird_dcMotor',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'hummingbird_motor',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dir = script.getStringField('DEVICE', script);\n                var speed = script.getNumberValue('VALUE', script);\n\n                if (speed == 0) speed = 256;\n                else if (speed > 100) speed = 127;\n                else if (speed < -100) speed = -127;\n                else speed = Math.floor(speed * 1.27); // range : -127~127\n\n                if (dir == 'dcMotor1') sq.dcMotor1 = speed;\n                else if (dir == 'dcMotor2') sq.dcMotor2 = speed;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        // 단색LED\n        hummingbird_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: 'HB 단색LED %1번 밝기: %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'led1'], ['2', 'led2'], ['3', 'led3'], ['4', 'led4']],\n                    value: 'led1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'hummingbird_led',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'hummingbird_led',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var ledtype = script.getStringField('DEVICE', script);\n                var value = script.getNumberValue('VALUE', script);\n                if (value > 100) value = 100;\n                if (value < 0) value = 0;\n                value = Math.floor(value * 2.55);\n\n                if (ledtype == 'led1') sq.led1 = value;\n                else if (ledtype == 'led2') sq.led2 = value;\n                else if (ledtype == 'led3') sq.led3 = value;\n                else if (ledtype == 'led4') sq.led4 = value;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        // 삼색LED\n        hummingbird_triLED: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: 'HB 삼색LED %1번 빨강%2 초록%3 파랑%4 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', 'triLED1'], ['2', 'triLED2']],\n                    value: 'triLED1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'hummingbird_triLED',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                cRED: 1,\n                cGREEN: 2,\n                cBLUE: 3,\n            },\n            class: 'hummingbird_led',\n            isNotFor: ['hummingbird'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var ledtype = script.getStringField('DEVICE', script);\n                var colorRed = script.getNumberValue('cRED', script);\n                var colorGreen = script.getNumberValue('cGREEN', script);\n                var colorBlue = script.getNumberValue('cBLUE', script);\n\n                if (colorRed > 100) colorRed = 100;\n                if (colorGreen > 100) colorGreen = 100;\n                if (colorBlue > 100) colorBlue = 100;\n                if (colorRed < 0) colorRed = 0;\n                if (colorGreen < 0) colorGreen = 0;\n                if (colorBlue < 0) colorBlue = 0;\n\n                colorRed = Math.floor(colorRed * 2.55);\n                colorGreen = Math.floor(colorGreen * 2.55);\n                colorBlue = Math.floor(colorBlue * 2.55);\n\n                if (ledtype == 'triLED1') {\n                    sq.triLEDR1 = colorRed;\n                    sq.triLEDG1 = colorGreen;\n                    sq.triLEDB1 = colorBlue;\n                } else if (ledtype == 'triLED2') {\n                    sq.triLEDR2 = colorRed;\n                    sq.triLEDG2 = colorGreen;\n                    sq.triLEDB2 = colorBlue;\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        //endregion hummingbird 허밍버드\n    };\n};\n\nmodule.exports = Entry.hummingbird;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_hyact.js",
    "content": "'use strict';\r\n\r\nEntry.HyACT_Xylobot = {\r\n    id: '33.1',\r\n    name: 'hyact_xylobot',\r\n    url: 'http://www.naver.com/',\r\n    imageName: 'hyact_xylobot.png',\r\n    title: {\r\n        ko: '하이엑트 실로봇',\r\n        en: 'HyACT Xylobot',\r\n    },\r\n\r\n    delayTime: 20,\r\n    timeouts: [],\r\n    array: {\r\n        SET_ZERO: 0,\r\n        GET_NOW_AIXS: 1,\r\n        GET_NOTE_AIXS: 2,\r\n        SET_LED_MOVEMENT: 3,\r\n        SET_LED_COLOR: 4,\r\n        SET_LED_RGB: 5,\r\n        SET_TORQUE_TOGGLE: 6,\r\n        SET_POSITION_SINGLE: 7,\r\n        SET_POSITION_MANY: 8,\r\n        SET_SPEED: 9,\r\n        SET_TORQUE: 10,\r\n        SET_PLAY_NOTE: 11,\r\n        SET_MOVE_NOTE: 12,\r\n        SET_MOVE_DEFAULT: 13,\r\n    },\r\n    note: {\r\n        C: 1,\r\n        D: 2,\r\n        E: 3,\r\n        F: 4,\r\n        G: 5,\r\n        A: 6,\r\n        B: 7,\r\n        HIGH_C: 8,\r\n    },\r\n    removeTimeout: function(id) {\r\n        clearTimeout(id);\r\n        var timeouts = this.timeouts;\r\n        var index = timeouts.indexOf(id);\r\n        if (index >= 0) {\r\n            timeouts.splice(index, 1);\r\n        }\r\n    },\r\n    removeAllTimeouts: function() {\r\n        var timeouts = this.timeouts;\r\n        for (var i in timeouts) {\r\n            clearTimeout(timeouts[i]);\r\n        }\r\n        this.timeouts = [];\r\n    },\r\n    setZero: function() {    \r\n        Entry.hw.sendQueue['SEND'] = {};\r\n        Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_ZERO] = {\r\n            Time: new Date().getTime(),\r\n        };\r\n        Entry.hw.update();\r\n    },\r\n};\r\nEntry.HyACT_Xylobot.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                hyact_xylobot_list_aixs_1: '1 축',\r\n                hyact_xylobot_list_aixs_2: '2 축',\r\n                hyact_xylobot_list_aixs_3: '3 축',\r\n                hyact_xylobot_list_aixs_all: '모든 축',\r\n                hyact_xylobot_list_octave_4_do: '도',\r\n                hyact_xylobot_list_octave_4_re: '레',\r\n                hyact_xylobot_list_octave_4_mi: '미',\r\n                hyact_xylobot_list_octave_4_fa: '파',\r\n                hyact_xylobot_list_octave_4_sol: '솔',\r\n                hyact_xylobot_list_octave_4_la: '라',\r\n                hyact_xylobot_list_octave_4_si: '시',\r\n                hyact_xylobot_list_octave_5_do: '높은 도',\r\n                hyact_xylobot_list_movement_on: '켜기',\r\n                hyact_xylobot_list_movement_twinkle: '반짝',\r\n                hyact_xylobot_list_movement_standby: '대기',\r\n                hyact_xylobot_list_toggle_on: '켜기',\r\n                hyact_xylobot_list_toggle_off: '끄기',\r\n                hyact_xylobot_list_color_off: '끄기',\r\n                hyact_xylobot_list_color_red: '빨간색',\r\n                hyact_xylobot_list_color_orange: '주황색',\r\n                hyact_xylobot_list_color_yellow: '노란색',\r\n                hyact_xylobot_list_color_green: '초록색',\r\n                hyact_xylobot_list_color_blue: '파란색',\r\n                hyact_xylobot_list_color_navy: '남색',\r\n                hyact_xylobot_list_color_purple: '보라색',\r\n                hyact_xylobot_list_color_white: '흰색',\r\n                hyact_xylobot_list_position_ready: '준비위치',\r\n                hyact_xylobot_list_position_target: '목표위치',\r\n                hyact_xylobot_get_now_aixs_block: '지금 %1 위치값',\r\n                hyact_xylobot_get_note_aixs_block: '%1 음의 %2 위치값',\r\n                hyact_xylobot_set_led_movement_block: 'LED 모드를 %1 모드로 정하기 %2',\r\n                hyact_xylobot_set_led_color_block: 'LED 색을 %1 으로 정하기 %2',\r\n                hyact_xylobot_set_led_rgb_block: 'LED 색을 R : %1% G : %2% B : %3% 으로 정하기 %4',\r\n                hyact_xylobot_set_torque_toggle_block: '%1 토크를 %2 %3',\r\n                hyact_xylobot_set_position_single_block: '%1 의 목표 위치값을 %2º(도) 로 정하기 %3',\r\n                hyact_xylobot_set_position_many_block: '목표 위치값을 1축 : %1º(도)  2축 : %2º(도)  3축 : %3º(도) 으로 정하기 %4',\r\n                hyact_xylobot_set_speed_block: '%1 의 속도를 %2% 으로 정하기 %3',\r\n                hyact_xylobot_set_torque_block: '%1 의 토크값을 %2% 으로 정하기 %3',\r\n                hyact_xylobot_set_play_note_block: '%1 음을 치기 %2',\r\n                hyact_xylobot_set_move_note_block: '%1 음의 %2 로 가기 %3',\r\n                hyact_xylobot_set_move_default_block: '모든 축이 기본 위치로 가기 %1',\r\n\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                hyact_xylobot_list_aixs_1: 'First axis',\r\n                hyact_xylobot_list_aixs_2: 'Second axis',\r\n                hyact_xylobot_list_aixs_3: 'Third axis',\r\n                hyact_xylobot_list_aixs_all: 'All axis',\r\n                hyact_xylobot_list_octave_4_do: 'C',\r\n                hyact_xylobot_list_octave_4_re: 'D',\r\n                hyact_xylobot_list_octave_4_mi: 'E',\r\n                hyact_xylobot_list_octave_4_fa: 'F',\r\n                hyact_xylobot_list_octave_4_sol: 'G',\r\n                hyact_xylobot_list_octave_4_la: 'A',\r\n                hyact_xylobot_list_octave_4_si: 'B',\r\n                hyact_xylobot_list_octave_5_do: 'High C',\r\n                hyact_xylobot_list_movement_on: 'On',\r\n                hyact_xylobot_list_movement_twinkle: 'Twinkle',\r\n                hyact_xylobot_list_movement_standby: 'Stand by',\r\n                hyact_xylobot_list_toggle_on: 'On',\r\n                hyact_xylobot_list_toggle_off: 'Off',\r\n                hyact_xylobot_list_color_off: 'Off',\r\n                hyact_xylobot_list_color_red: 'Red',\r\n                hyact_xylobot_list_color_orange: 'Orange',\r\n                hyact_xylobot_list_color_yellow: 'Yellow',\r\n                hyact_xylobot_list_color_green: 'Green',\r\n                hyact_xylobot_list_color_blue: 'Blue',\r\n                hyact_xylobot_list_color_navy: 'Navy',\r\n                hyact_xylobot_list_color_purple: 'Purple',\r\n                hyact_xylobot_list_color_white: 'White',\r\n                hyact_xylobot_list_position_ready: 'Ready position',\r\n                hyact_xylobot_list_position_target: 'Target position',\r\n                hyact_xylobot_get_now_aixs_block: 'Current %1 position value',\r\n                hyact_xylobot_get_note_aixs_block: '%1 note\\'s %2 position value',\r\n                hyact_xylobot_set_led_movement_block: 'LED mode setting to %1 %2',\r\n                hyact_xylobot_set_led_color_block: 'LED color setting to %1 %2',\r\n                hyact_xylobot_set_led_rgb_block: 'LED color setting to R : %1% G : %2% B : %3% %4',\r\n                hyact_xylobot_set_torque_toggle_block: '%1 torque %2 %3',\r\n                hyact_xylobot_set_position_single_block: '%1 \\'s target position setting to %2º(degree) %3',\r\n                hyact_xylobot_set_position_many_block: 'Target position setting to first axis : %1º(degree)  second axis : %2º(degree)  third axis : %3º(degree) %4',\r\n                hyact_xylobot_set_speed_block: '%1 \\'s speed setting to %2% %3',\r\n                hyact_xylobot_set_torque_block: '%1 \\'s torque value setting to %2% %3',\r\n                hyact_xylobot_set_play_note_block: 'Play %1 %2',\r\n                hyact_xylobot_set_move_note_block: 'Go to %1 \\'s %2 %3',\r\n                hyact_xylobot_set_move_default_block: 'Go to all axis default position %1',\r\n            },\r\n        },\r\n        jp: {\r\n            template: {\r\n                hyact_xylobot_list_aixs_1: '第1関節',\r\n                hyact_xylobot_list_aixs_2: '第２関節',\r\n                hyact_xylobot_list_aixs_3: '第３関節',\r\n                hyact_xylobot_list_aixs_all: '全ての関節',\r\n                hyact_xylobot_list_octave_4_do: 'ド',\r\n                hyact_xylobot_list_octave_4_re: 'レ',\r\n                hyact_xylobot_list_octave_4_mi: 'ミ',\r\n                hyact_xylobot_list_octave_4_fa: 'ファ',\r\n                hyact_xylobot_list_octave_4_sol: 'ソ',\r\n                hyact_xylobot_list_octave_4_la: 'ラ',\r\n                hyact_xylobot_list_octave_4_si: 'シ',\r\n                hyact_xylobot_list_octave_5_do: '上のド',\r\n                hyact_xylobot_list_movement_on: '点灯',\r\n                hyact_xylobot_list_movement_twinkle: '点滅',\r\n                hyact_xylobot_list_movement_standby: '待機',\r\n                hyact_xylobot_list_toggle_on: '点灯',\r\n                hyact_xylobot_list_toggle_off: 'オフ',\r\n                hyact_xylobot_list_color_off: 'オフ',\r\n                hyact_xylobot_list_color_red: '赤',\r\n                hyact_xylobot_list_color_orange: '黄緑',\r\n                hyact_xylobot_list_color_yellow: '黄色',\r\n                hyact_xylobot_list_color_green: '緑',\r\n                hyact_xylobot_list_color_blue: '青',\r\n                hyact_xylobot_list_color_navy: '藍色',\r\n                hyact_xylobot_list_color_purple: '紫',\r\n                hyact_xylobot_list_color_white: '白',\r\n                hyact_xylobot_list_position_ready: '準備位置',\r\n                hyact_xylobot_list_position_target: '目標位置',\r\n                hyact_xylobot_get_now_aixs_block: '現在の %1 角度',\r\n                hyact_xylobot_get_note_aixs_block: '%1 音の %2 角度',\r\n                hyact_xylobot_set_led_movement_block: 'LEDモードを %1 モードにする %2',\r\n                hyact_xylobot_set_led_color_block: 'LED色を %1 にする。 %2',\r\n                hyact_xylobot_set_led_rgb_block: 'LED色を R : %1% G : %2% B : %3% に設定 %4',\r\n                hyact_xylobot_set_torque_toggle_block: '%1 トルク %2 %3',\r\n                hyact_xylobot_set_position_single_block: '%1 の角度を %2º(度) にする。 %3',\r\n                hyact_xylobot_set_position_many_block: '姿勢を第1関節: %1º(度)  第２関節: %2º(度)  第３関節: %3º(度) にする。 %4',\r\n                hyact_xylobot_set_speed_block: '%1 の速度を %2% にする。 %3',\r\n                hyact_xylobot_set_torque_block: '%1 のトルクを %2% にする。 %3',\r\n                hyact_xylobot_set_play_note_block: '%1 を叩く。 %2',\r\n                hyact_xylobot_set_move_note_block: '%1 音の %2 に動く。 %3',\r\n                hyact_xylobot_set_move_default_block: '初期姿勢に戻る。 %1',\r\n            },\r\n        },\r\n    };\r\n};\r\nEntry.HyACT_Xylobot.blockMenuBlocks = [\r\n    'hyact_xylobot_get_now_aixs_block',\r\n    'hyact_xylobot_get_note_aixs_block',\r\n    'hyact_xylobot_set_led_movement_block',\r\n    'hyact_xylobot_set_led_color_block',\r\n    'hyact_xylobot_set_led_rgb_block',\r\n    'hyact_xylobot_set_torque_toggle_block',\r\n    'hyact_xylobot_set_position_single_block',\r\n    'hyact_xylobot_set_position_many_block',\r\n    'hyact_xylobot_set_speed_block',\r\n    'hyact_xylobot_set_torque_block',\r\n    'hyact_xylobot_set_play_note_block',\r\n    'hyact_xylobot_set_move_note_block',\r\n    'hyact_xylobot_set_move_default_block',\r\n];\r\nEntry.HyACT_Xylobot.getBlocks = function() {\r\n    return {\r\n        //region HyACT 하이액트 Xylobot\r\n        hyact_xylobot_list_aixs_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.hyact_xylobot_list_aixs_1, '0'],\r\n                        [Lang.template.hyact_xylobot_list_aixs_2, '1'],\r\n                        [Lang.template.hyact_xylobot_list_aixs_3, '2'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                AXIS: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('AXIS');\r\n            },\r\n        },\r\n        hyact_xylobot_list_aixs_ex_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.hyact_xylobot_list_aixs_1, '0'],\r\n                        [Lang.template.hyact_xylobot_list_aixs_2, '1'],\r\n                        [Lang.template.hyact_xylobot_list_aixs_3, '2'],\r\n                        [Lang.template.hyact_xylobot_list_aixs_all, '3'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                AXIS: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('AXIS');\r\n            },\r\n        },\r\n        hyact_xylobot_list_note_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.hyact_xylobot_list_octave_4_do, '1'],\r\n                        [Lang.template.hyact_xylobot_list_octave_4_re, '2'],\r\n                        [Lang.template.hyact_xylobot_list_octave_4_mi, '3'],\r\n                        [Lang.template.hyact_xylobot_list_octave_4_fa, '4'],\r\n                        [Lang.template.hyact_xylobot_list_octave_4_sol, '5'],\r\n                        [Lang.template.hyact_xylobot_list_octave_4_la, '6'],\r\n                        [Lang.template.hyact_xylobot_list_octave_4_si, '7'],\r\n                        [Lang.template.hyact_xylobot_list_octave_5_do, '8'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n        },\r\n        hyact_xylobot_list_movement_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.hyact_xylobot_list_movement_on, '0'],\r\n                        [Lang.template.hyact_xylobot_list_movement_twinkle, '1'],\r\n                        [Lang.template.hyact_xylobot_list_movement_standby, '2'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                MOVEMENT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('MOVEMENT');\r\n            },\r\n        },\r\n        hyact_xylobot_list_toggle_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.hyact_xylobot_list_toggle_off, '0'],\r\n                        [Lang.template.hyact_xylobot_list_toggle_on, '1'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                MOVEMENT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('MOVEMENT');\r\n            },\r\n        },\r\n        hyact_xylobot_list_color_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.hyact_xylobot_list_color_off, '0'],\r\n                        [Lang.template.hyact_xylobot_list_color_red, '1'],\r\n                        [Lang.template.hyact_xylobot_list_color_orange, '2'],\r\n                        [Lang.template.hyact_xylobot_list_color_yellow, '3'],\r\n                        [Lang.template.hyact_xylobot_list_color_green, '4'],\r\n                        [Lang.template.hyact_xylobot_list_color_blue, '5'],\r\n                        [Lang.template.hyact_xylobot_list_color_navy, '6'],\r\n                        [Lang.template.hyact_xylobot_list_color_purple, '7'],\r\n                        [Lang.template.hyact_xylobot_list_color_white, '9'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('COLOR');\r\n            },\r\n        },\r\n        hyact_xylobot_list_position_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.hyact_xylobot_list_position_ready, '0'],\r\n                        [Lang.template.hyact_xylobot_list_position_target, '1'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                POSITION: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('POSITION');\r\n            },\r\n        },\r\n        hyact_xylobot_get_now_aixs_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_get_now_aixs_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_aixs_block',\r\n                    },\r\n                ],\r\n                type: 'hyact_xylobot_get_now_aixs_block',\r\n            },\r\n            paramsKeyMap: {\r\n                AXIS: 0,\r\n            },\r\n            events: {},\r\n            class: 'GetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var axisData = script.getNumberValue('AXIS');\r\n                var xylobotDatas = new Object();\r\n                var axis = 0;\r\n\r\n                xylobotDatas = Entry.hw.portData;\r\n\r\n                if (axisData == 0) axis = xylobotDatas.positionNow.aixs1;\r\n                else if (axisData == 1) axis = xylobotDatas.positionNow.aixs2;\r\n                else if (axisData == 2) axis = xylobotDatas.positionNow.aixs3;\r\n                axis = Math.floor((axis / 1023) * 300);\r\n                axis = (axis - 150) * -1;\r\n\r\n                return axis;\r\n            },\r\n        },\r\n        hyact_xylobot_get_note_aixs_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_get_note_aixs_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_note_block',\r\n                    },\r\n                    {\r\n                        type: 'hyact_xylobot_list_aixs_block',\r\n                    },\r\n                ],\r\n                type: 'hyact_xylobot_get_note_aixs_block',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n                AXIS: 1,\r\n            },\r\n            events: {},\r\n            class: 'GetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var noteData = script.getNumberValue('NOTE');\r\n                var axisData = script.getNumberValue('AXIS');\r\n                var xylobotDatas = 0;\r\n                var axis = 0;\r\n\r\n                xylobotDatas = Entry.hw.portData;\r\n\r\n                switch(noteData)\r\n                {\r\n                    case Entry.HyACT_Xylobot.note.C:\r\n                        if(axisData == 0) axis = xylobotDatas.positionC.aixs1;\r\n                        else if(axisData == 1) axis = xylobotDatas.positionC.aixs2;\r\n                        else if(axisData == 2) axis = xylobotDatas.positionC.aixs3;\r\n                        break;\r\n                    case Entry.HyACT_Xylobot.note.D:                        \r\n                        if(axisData == 0) axis = xylobotDatas.positionD.aixs1;\r\n                        else if(axisData == 1) axis = xylobotDatas.positionD.aixs2;\r\n                        else if(axisData == 2) axis = xylobotDatas.positionD.aixs3;\r\n                        break; \r\n                    case Entry.HyACT_Xylobot.note.E:\r\n                        if(axisData == 0) axis = xylobotDatas.positionE.aixs1;\r\n                        else if(axisData == 1) axis = xylobotDatas.positionE.aixs2;\r\n                        else if(axisData == 2) axis = xylobotDatas.positionE.aixs3;\r\n                        break; \r\n                    case Entry.HyACT_Xylobot.note.F:\r\n                        if(axisData == 0) axis = xylobotDatas.positionF.aixs1;\r\n                        else if(axisData == 1) axis = xylobotDatas.positionF.aixs2;\r\n                        else if(axisData == 2) axis = xylobotDatas.positionF.aixs3;\r\n                        break; \r\n                    case Entry.HyACT_Xylobot.note.G:\r\n                        if(axisData == 0) axis = xylobotDatas.positionG.aixs1;\r\n                        else if(axisData == 1) axis = xylobotDatas.positionG.aixs2;\r\n                        else if(axisData == 2) axis = xylobotDatas.positionG.aixs3;\r\n                        break; \r\n                    case Entry.HyACT_Xylobot.note.A:\r\n                        if(axisData == 0) axis = xylobotDatas.positionA.aixs1;\r\n                        else if(axisData == 1) axis = xylobotDatas.positionA.aixs2;\r\n                        else if(axisData == 2) axis = xylobotDatas.positionA.aixs3;\r\n                        break; \r\n                    case Entry.HyACT_Xylobot.note.B:\r\n                        if(axisData == 0) axis = xylobotDatas.positionB.aixs1;\r\n                        else if(axisData == 1) axis = xylobotDatas.positionB.aixs2;\r\n                        else if(axisData == 2) axis = xylobotDatas.positionB.aixs3;\r\n                        break; \r\n                    case Entry.HyACT_Xylobot.note.HIGH_C:\r\n                        if(axisData == 0) axis = xylobotDatas.positionHighC.aixs1;\r\n                        else if(axisData == 1) axis = xylobotDatas.positionHighC.aixs2;\r\n                        else if(axisData == 2) axis = xylobotDatas.positionHighC.aixs3;\r\n                        break; \r\n                }\r\n                axis = Math.floor((axis / 1023) * 300);\r\n                axis = (axis - 150) * -1;\r\n\r\n                return axis;\r\n            },\r\n        },\r\n        hyact_xylobot_set_led_movement_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_led_movement_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_movement_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_led_movement_block',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVEMENT: 0,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var movementData = script.getNumberValue('MOVEMENT');\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_LED_MOVEMENT] = {\r\n                        Movement: movementData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_led_color_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_led_color_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',                    \r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_color_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_led_color_block',\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var colorData = script.getNumberValue('COLOR');\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_LED_COLOR] = {\r\n                        Color: colorData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_led_rgb_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_led_rgb_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_led_rgb_block',\r\n            },\r\n            paramsKeyMap: {\r\n                RED: 0,\r\n                GREEN: 1,\r\n                BLUE: 2,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var red = script.getNumberValue('RED');\r\n                var green = script.getNumberValue('GREEN');\r\n                var blue = script.getNumberValue('BLUE');\r\n                var redData = 0;\r\n                var greenData = 0;\r\n                var blueData =  0;\r\n\r\n                if(red > 100) red = 100;\r\n                else if(red < 0) red = 0;\r\n                if(green > 100) green = 100;\r\n                else if(green < 0) green = 0;\r\n                if(blue > 100) blue = 100;\r\n                else if(blue < 0) blue = 0;\r\n                redData = Math.floor((255 * red) / 100);\r\n                greenData = Math.floor((255 * green) / 100);\r\n                blueData = Math.floor((255 * blue) / 100);\r\n\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_LED_RGB] = {\r\n                        Red: redData,\r\n                        Green: greenData,\r\n                        Blue: blueData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_torque_toggle_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_torque_toggle_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_aixs_ex_block',\r\n                    },\r\n                    {\r\n                        type: 'hyact_xylobot_list_toggle_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_torque_toggle_block',\r\n            },\r\n            paramsKeyMap: {\r\n                AIXS: 0,\r\n                TOGGLE: 1,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var axisData = script.getNumberValue('AIXS');\r\n                var toggleData = script.getNumberValue(\"TOGGLE\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_TORQUE_TOGGLE] = {\r\n                        Axis: axisData,\r\n                        Toggle: toggleData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_position_single_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_position_single_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_aixs_block',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_position_single_block',\r\n            },\r\n            paramsKeyMap: {\r\n                AIXS: 0,\r\n                POSITION: 1,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var axisData = script.getNumberValue('AIXS');\r\n                var position = script.getNumberValue(\"POSITION\");\r\n                var positionData = 0;\r\n\r\n                if(position > 150) position = 150;\r\n                else if(position < -150) position = -150;\r\n                position = (position * -1) + 150;\r\n                positionData = Math.floor((1023 * position) / 300);\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_POSITION_SINGLE] = {\r\n                        Axis: axisData,\r\n                        Position: positionData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_position_many_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_position_many_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_position_many_block',\r\n            },\r\n            paramsKeyMap: {\r\n\r\n                POSITION1: 0,\r\n                POSITION2: 1,\r\n                POSITION3: 2,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var position1 = script.getNumberValue(\"POSITION1\");\r\n                var position2 = script.getNumberValue(\"POSITION2\");\r\n                var position3 = script.getNumberValue(\"POSITION3\");\r\n                var position1Data = 0;\r\n                var position2Data = 0;\r\n                var position3Data = 0;\r\n\r\n                if(position1 > 150) position1 = 150;\r\n                else if(position1 < -150) position1 = -150;\r\n                if(position2 > 150) position2 = 150;\r\n                else if(position2 < -150) position2 = -150;\r\n                if(position3 > 150) position3 = 150;\r\n                else if(position3 < -150) position3 = -150;\r\n                position1 = (position1 * -1) + 150;\r\n                position1Data = Math.floor((1023 * position1) / 300);\r\n                position2 = (position2 * -1) + 150;\r\n                position2Data = Math.floor((1023 * position2) / 300);\r\n                position3 = (position3 * -1) + 150;\r\n                position3Data = Math.floor((1023 * position3) / 300);\r\n\r\n                 if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_POSITION_MANY] = {\r\n                        Position1: position1Data,\r\n                        Position2: position2Data,\r\n                        Position3: position3Data,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_speed_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_speed_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_aixs_ex_block',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_speed_block',\r\n            },\r\n            paramsKeyMap: {\r\n                AIXS: 0,\r\n                SPEED: 1,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var axisData = script.getNumberValue(\"AIXS\");\r\n                var speed = script.getNumberValue(\"SPEED\");\r\n                var speedData = 0;\r\n                \r\n                if(speed >= 100) speed = 0;    // 0 값이 최대 속력\r\n                else if(speed < 0) speed = 1;\r\n                speedData = Math.floor((1023 * speed) / 100);\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_SPEED] = {\r\n                        Axis: axisData,\r\n                        Speed: speedData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_torque_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_torque_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_aixs_ex_block',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_torque_block',\r\n            },\r\n            paramsKeyMap: {\r\n                AIXS: 0,\r\n                TORQUE: 1,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var axisData = script.getNumberValue(\"AIXS\");\r\n                var torque = script.getNumberValue(\"TORQUE\");\r\n                var torqueData = 0;\r\n\r\n                if(torque > 100) torque = 100;\r\n                else if(torque < 0) torque = 0;\r\n                torqueData = Math.floor((1023 * torque) / 100);\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_TORQUE] = {\r\n                        Axis: axisData,\r\n                        Torque: torqueData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_play_note_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_play_note_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_note_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_play_note_block',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var noteData = script.getNumberValue(\"NOTE\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_PLAY_NOTE] = {\r\n                        Note: noteData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_move_note_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_move_note_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'hyact_xylobot_list_note_block',\r\n                    },\r\n                    {\r\n                        type: 'hyact_xylobot_list_position_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_move_note_block',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n                LOCATION: 1,\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                var noteData = script.getNumberValue(\"NOTE\");\r\n                var locationData = script.getNumberValue(\"LOCATION\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_MOVE_NOTE] = {\r\n                        Note: noteData,\r\n                        Location: locationData,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        hyact_xylobot_set_move_default_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.hyact_xylobot_set_move_default_block,\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'hyact_xylobot_set_move_default_block',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            events: {},\r\n            class: 'SetBlock',\r\n            isNotFor: ['hyact_xylobot'],\r\n            func: function(sprite, script) {\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.HyACT_Xylobot.removeTimeout(timer);\r\n                    }, Entry.HyACT_Xylobot.delayTime);\r\n                    Entry.HyACT_Xylobot.timeouts.push(timer);\r\n                    return script;\r\n\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['SEND'] = {};\r\n                    Entry.hw.sendQueue['SEND'][Entry.HyACT_Xylobot.array.SET_MOVE_DEFAULT] = {\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        //endregion HyACT 하이액트 Xylobot\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.HyACT_Xylobot;"
  },
  {
    "path": "src/playground/blocks/hardware/block_iCOBOT.js",
    "content": "'use strict';\n\nEntry.iCOBOT = {\n    PORT_MAP: {\n        left_up_red: 0,\n        left_up_green: 0,\n        left_up_blue: 0,\n        right_up_red: 0,\n        right_up_green: 0,\n        right_up_blue: 0,\n        left_down_red: 0,\n        left_down_green: 0,\n        left_down_blue: 0,\n        right_down_red: 0,\n        right_down_green: 0,\n        right_down_blue: 0,\n        tone: 0,\n        leftmotor_speed: 0,\n        leftmotor_dir: 0,\n        rightmotor_speed: 0,\n        rightmotor_dir: 0,\n        motor_mode: 0,\n        motor_value: 0,\n        motor_dir: 0\n    },\n    setZero: function() {\n        var portMap = Entry.iCOBOT.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        motor_type = 0x00;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        var iCOBOT = Entry.iCOBOT;\n        iCOBOT.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    id: '50.2',\n    name: 'iCOBOT',\n    url: 'https://aicontrol.ai/',\n    imageName: 'iCOBOT.png',\n    title:\n    {\n        ko: '아이코봇',\n        en: 'iCOBOT',\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n};\nvar motor_type = 0;\n\nEntry.iCOBOT.blockMenuBlocks = [\n    'icobot_sensor_input_title',\n    'icobot_get_cds_value',\n    'icobot_get_sound_value',\n    'icobot_get_distsensor_value',\n    'icobot_get_analog_temp_value',\n    'icobot_get_discomfort_index_value',\n    'icobot_buzzer_title',\n    'icobot_buzzer_onoff',\t\t\n    'icobot_set_digital_buzzer_notime',\t\t\n    'icobot_set_digital_buzzer',\n    'icobot_led_title',\n    'icobot_digital_rgbled_off',    \n    'icobot_digital_rgbled_onoff',      \n    'icobot_digital_set_rgbled_value',\n    'icobot_motor_title',\n    'icobot_digital_motor_stop',\t\n    'icobot_digital_set_motor_speed',\n    'icobot_digital_set_motor_direction',\n    'icobot_digital_set_motor_angle',\n    'icobot_digital_set_motor_straight',\n    'icobot_digital_wait_motor_movement',\n];\n\nEntry.iCOBOT.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n\t\t\t\ticobot_sensor_input_title: \"▶ 아이코봇 센서 입력 값\",\n\t\t\t\ticobot_get_cds_value: \"조도(밝기) 센서 값\",\n\t\t\t\ticobot_get_sound_value: \"사운드(소리)감지 센서 값\",\n\t\t\t\ticobot_get_distsensor_value: \"거리(IR) %1 센서 값\",\n\t\t\t\ticobot_get_analog_temp_value: \"%1 센서 값\",\n\t\t\t\ticobot_get_discomfort_index_value: \"불쾌 지수 값\",\n\t\t\t\ticobot_buzzer_title: \"▶ 아이코봇 부저 출력\",\n\t\t\t\ticobot_buzzer_onoff: \"부저 %1 %2\",\n                icobot_set_digital_buzzer: \"부저를 %1 옥타브 %2 음 %3 초 연주 %4\",\n                icobot_set_digital_buzzer_notime: \"부저를 %1 옥타브 %2 음 연주 %3\",\n\t\t\t\ticobot_led_title: \"▶ 아이코봇 RGB LED 출력\",\n                icobot_digital_rgbled_onoff: \"%1 RGB LED %2 색 켜기 %3\",\n\t\t\t\ticobot_digital_rgbled_off: \"%1 RGB LED 끄기 %2\",\n                icobot_digital_set_rgbled_value: \"%1 RGB LED 빨강 %2 초록 %3 파랑 %4 으로 켜기 %5\",\n\t\t\t\ticobot_motor_title: \"▶ 아이코봇 모터 출력\",\n\t\t\t\ticobot_digital_motor_stop: \"%1 모터 정지하기 %2\",\n\t\t\t\ticobot_digital_set_motor_speed: \"%1 모터의 속도를 %2 로 정하기 %3\",\n\t\t\t\ticobot_digital_set_motor_direction: \"%1 모터 방향을 %2 방향으로 정하기 %3\",\n\t\t\t\ticobot_digital_set_motor_angle: \"%1 방향으로 %2° 회전하기 %3\",\n\t\t\t\ticobot_digital_set_motor_straight: \"%1cm %2 하기 %3\",\n                icobot_digital_wait_motor_movement: \"모터 구동이 끝날때까지 기다리기 %1\"\n            },\n            Helper: {\n\t\t\t\ticobot_get_cds_value: \"현재 조도(밝기) 값을 읽어 옵니다.\",\n\t\t\t\ticobot_get_sound_value: \"현재 주변의 사운드(소리)감지하여 읽어 옵니다.\\n 값이 순간적으로 변화합니다.\",\n\t\t\t\ticobot_get_distsensor_value: \"선택한 거리(IR)센서의 값을 읽어 옵니다.\\n 값이 클 수록 물체와의 거리가 가까움을 나타내거나, 흰색을 감지하고 있음을 나타냅니다.\",\n\t\t\t\ticobot_get_analog_temp_value: \"현재 온도/습도 값을 읽어 옵니다.\",\n\t\t\t\ticobot_get_discomfort_index_value: \"현재의 온도와 상대습도 값을 이용하여 불쾌 지수 값을 계산합니다.\\n\\n 불쾌지수 = ((9/5)T)-(0.55(1-RH)((9/5)T-26))+32 \\n\\n T : 온도,  RH : 상대습도\",\n\t\t\t\ticobot_buzzer_onoff: \"부저를 울리거나, 끌수있습니다.\",\n                icobot_set_digital_buzzer: \"선택한 계이름과 옥타브의 음을 입력한 시간만큼 소리 냅니다.\",\n                icobot_set_digital_buzzer_notime: \"선택한 계이름과 옥타브의 음을 계속 소리 냅니다.\",\n                icobot_digital_rgbled_onoff: \"LED를 선택한 색깔로 켭니다.\",\n\t\t\t\ticobot_digital_rgbled_off: \"LED를 끕니다.\",\n                icobot_digital_set_rgbled_value: \"LED의 R, G, B 값을 입력한 값으로 각각 설정하여 켭니다.\",\n\t\t\t\ticobot_digital_set_motor_direction: \"선택한 모터의 구동 방향을 정하고, 그 방향으로 이동합니다.\",\n\t\t\t\ticobot_digital_set_motor_angle: \"원하는 각도만큼 i-COBOT이 움직입니다.\",\n\t\t\t\ticobot_digital_set_motor_straight: \"원하는 거리만큼 i-COBOT이 움직입니다.\",\n\t\t\t\ticobot_digital_set_motor_speed: \"선택한 모터의 속도를 정하고, 그 속도로 구동됩니다.\",\n\t\t\t\ticobot_digital_motor_stop: \"선택한 모터가 정지합니다.\",\n                icobot_digital_wait_motor_movement: \"모터 구동이 끝날때까지 실행을 멈추고 기다립니다.\"\n            },\n            Blocks: {\n                icobot_Sound: \"소리감지\",\n                icobot_Brightness: \"밝기(조도)\",\n                monitor_ir_front: \"정면 거리\",\n                monitor_ir_left: \"왼쪽 거리\",\n                monitor_ir_right: \"오른쪽 거리\",\n                monitor_ir_bottom_mid: \"아래중앙 거리\",\n                monitor_ir_bottom_left: \"아래왼쪽 거리\",\n                monitor_ir_bottom_right: \"아래오른쪽 거리\",\n                icobot_Temperature: \"온도(°C)\",\n                icobot_Humidity: \"습도(%)\",\n                icobot_ir_front: \"정면\",\n                icobot_ir_left: \"왼쪽\",\n                icobot_ir_right: \"오른쪽\",\n                icobot_ir_bottom_mid: \"아래중앙\",\n                icobot_ir_bottom_left: \"아래왼쪽\",\n                icobot_ir_bottom_right: \"아래오른쪽\",\n                icobot_buzzer_on: \"켜기\",\n                icobot_buzzer_off: \"끄기\",\n                icobot_buzzer_silent: \"무음\",\n                icobot_buzzer_do: \"도\",\n                icobot_buzzer_do_sharp: \"도＃(레♭)\",\n                icobot_buzzer_re: \"레\",\n                icobot_buzzer_re_sharp: \"레＃(미♭)\",\n                icobot_buzzer_mi: \"미\",\n                icobot_buzzer_fa: \"파\",\n                icobot_buzzer_fa_sharp: \"파＃(솔♭)\",\n                icobot_buzzer_sol: \"솔\",\n                icobot_buzzer_sol_sharp: \"솔＃(라♭)\",\n                icobot_buzzer_la: \"라\",\n                icobot_buzzer_la_sharp: \"라＃(시♭)\",\n                icobot_buzzer_si: \"시\",\n                icobot_led_total: \"모든\",\n                icobot_led_left_up: \"왼쪽 위\",\n                icobot_led_left_down: \"왼쪽 아래\",\n                icobot_led_right_up: \"오른쪽 위\",\n                icobot_led_right_down: \"오른쪽 아래\",\n                icobot_color_white: \"흰\",\n                icobot_color_red: \"빨간\",\n                icobot_color_orange: \"주황\",\n                icobot_color_yellow: \"노란\",\n                icobot_color_green: \"초록\",\n                icobot_color_blue: \"파란\",\n                icobot_color_sky_blue: \"하늘\",\n                icobot_color_purple: \"보라\",\n                icobot_motor_both_wheels: \"양쪽\",\n                icobot_motor_left_wheels: \"왼쪽\",\n                icobot_motor_right_wheels: \"오른쪽\",\n                icobot_motor_front_move: \"전진\",\n                icobot_motor_back_move: \"후진\",\n                icobot_motor_left_turn: \"왼쪽\",\n                icobot_motor_right_turn: \"오른쪽\",\n                icobot_motor_straight: \"모터구동\",\n                icobot_motor_rotation: \"회전\",\n                icobot_motor_30_degrees: \"30°\",\n                icobot_motor_45_degrees: \"45°\",\n                icobot_motor_60_degrees: \"60°\",\n                icobot_motor_90_degrees: \"90°\",\n                icobot_motor_120_degrees: \"120°\",\n                icobot_motor_135_degrees: \"135°\",\n                icobot_motor_150_degrees: \"150°\",\n                icobot_motor_180_degrees: \"180°\",\n                icobot_motor_210_degrees: \"210°\",\n                icobot_motor_225_degrees: \"225°\",\n                icobot_motor_240_degrees: \"240°\",\n                icobot_motor_270_degrees: \"270°\",\n                icobot_motor_300_degrees: \"300°\",\n                icobot_motor_315_degrees: \"315°\",\n                icobot_motor_330_degrees: \"330°\",\n                icobot_motor_360_degrees: \"360°\",\n            }\n        },\n        en: {\n            template: {\n\t\t\t\ticobot_sensor_input_title: \"▶ i-COBOT Input Sensor Value\",\n\t\t\t\ticobot_get_cds_value: \"CDS(Brightness) Sensor Value\",\n\t\t\t\ticobot_get_sound_value: \"Sound Sensor Value\",\n\t\t\t\ticobot_get_distsensor_value: \"Distance(IR) %1 Sensor Value\",\n\t\t\t\ticobot_get_analog_temp_value: \"%1 Sensor Value\",\n\t\t\t\ticobot_get_discomfort_index_value: \"Discomfort Index Value\",\n\t\t\t\ticobot_buzzer_title: \"▶ i-COBOT Buzzer Output\",\n\t\t\t\ticobot_buzzer_onoff: \"Buzzer %1 %2\",\n                icobot_set_digital_buzzer: \"Play %1 Octave %2 for %3 Sec with Buzzer %4\",\n                icobot_set_digital_buzzer_notime: \"Play %1 Octave %2 with Buzzer %3\",\n\t\t\t\ticobot_led_title: \"▶ i-COBOT RGB LED Output\",\n                icobot_digital_rgbled_onoff: \"Turn On %1 RGB LED as %2 Color %3\",\n\t\t\t\ticobot_digital_rgbled_off: \"Turn Off %1 RGB LED %2\",\n                icobot_digital_set_rgbled_value: \"Set the %1 RGB LED value to RED %2 GREEN %3 BLUE %4 %5\",\n\t\t\t\ticobot_motor_title: \"▶ i-COBOT Motor Output\",\n\t\t\t\ticobot_digital_motor_stop: \"Stop %1 Motor %2\",\n\t\t\t\ticobot_digital_set_motor_speed: \"Set %1 Motor Speed to %2 %3\",\n\t\t\t\ticobot_digital_set_motor_direction: \"Set %1 Motor Direction to %2 %3\",\n\t\t\t\ticobot_digital_set_motor_angle: \"Rotate %1 by %2 ° degrees %3\",\n\t\t\t\ticobot_digital_set_motor_straight: \"Move %1 cm %2 %3\",\n                // icobot_digital_wait_motor_movement: \"Wait until the motor %1 stops %2\"\n                icobot_digital_wait_motor_movement: \"Wait until the motor stops operating %1\"\n            },\n            Helper: {\n\t\t\t\ticobot_get_cds_value: \"i-COBOT reads the current value of CDS photocell.\\n\\n A CDS photocell(or Light Dependant Resistor / LDR) is a resistor that changes the resistance based on the amount of light.\",\n\t\t\t\ticobot_get_sound_value: \"Senses the surrounding sound.\\n The value changes minute by minute.\",\n\t\t\t\ticobot_get_distsensor_value: \"Reads the value of selected IR sensor.\\n A larger value indicates that the distance from the object is close, or that it is detecting a white color.\",\n\t\t\t\ticobot_get_analog_temp_value: \"Reads the value of current temperature or humidity.\",\n\t\t\t\ticobot_get_discomfort_index_value: \"Calculate the Temperature-Humidity Index(THI) using the current temperature and relative humidity values.\\n\\n THI = ((9/5)T)-(0.55(1-RH)((9/5)T-26))+32 \\n\\n T : Temperature,  RH : Relative Humidity\",\n\t\t\t\ticobot_buzzer_onoff: \"You can turn on/off the buzzer.\",\n                icobot_set_digital_buzzer: \"Let i-COBOT play the pitch you entered for the seconds you entered.\",\n                icobot_set_digital_buzzer_notime: \"Let i-COBOT keep playing the pitch you entered.\",\n                icobot_digital_rgbled_onoff: \"Turn the LED on as the selected color.\",\n\t\t\t\ticobot_digital_rgbled_off: \"Turns off the LED.\",\n                icobot_digital_set_rgbled_value: \"Set the R, G, and B values of the LED to the entered values and turn them on.\",\n\t\t\t\ticobot_digital_set_motor_direction: \"Determine the driving path of the motor.\",\n\t\t\t\ticobot_digital_set_motor_angle: \"Let i-COBOT rotate as much as you want.\",\n\t\t\t\ticobot_digital_set_motor_straight: \"Let i-COBOT move as much as you want.\",\n\t\t\t\ticobot_digital_set_motor_speed: \"Determine the speed of the motor.\",\n\t\t\t\ticobot_digital_motor_stop: \"The selected motor stops.\",\n                icobot_digital_wait_motor_movement: \"Stop all command delibery until motor operation is complete\"\n            },\n            Blocks: {\n                icobot_Sound: \"Noise\",\n                icobot_Brightness: \"Brightness(CDS)\",\n                monitor_ir_front: \"Front Dist.\",\n                monitor_ir_left: \"Left Dist.\",\n                monitor_ir_right: \"Right Dist.\",\n                monitor_ir_bottom_mid: \"Bottom_Mid Dist.\",\n                monitor_ir_bottom_left: \"Bottom_Left Dist.\",\n                monitor_ir_bottom_right: \"Bottom_Right Dist.\",\n                icobot_Temperature: \"Temperature(°C)\",\n                icobot_Humidity: \"Humidity(%)\",\n                icobot_ir_front: \"Front\",\n                icobot_ir_left: \"Left\",\n                icobot_ir_right: \"Right\",\n                icobot_ir_bottom_mid: \"Bottom_Mid\",\n                icobot_ir_bottom_left: \"Bottom_Left\",\n                icobot_ir_bottom_right: \"Bottom_Right\",\n                icobot_buzzer_on: \"On\",\n                icobot_buzzer_off: \"Off\",\n                icobot_buzzer_silent: \"NoTone\",\n                icobot_buzzer_do: \"C\",\n                icobot_buzzer_do_sharp: \"C＃(D♭)\",\n                icobot_buzzer_re: \"D\",\n                icobot_buzzer_re_sharp: \"D＃(E♭)\",\n                icobot_buzzer_mi: \"E\",\n                icobot_buzzer_fa: \"F\",\n                icobot_buzzer_fa_sharp: \"F＃(G♭)\",\n                icobot_buzzer_sol: \"G\",\n                icobot_buzzer_sol_sharp: \"G＃(A♭)\",\n                icobot_buzzer_la: \"A\",\n                icobot_buzzer_la_sharp: \"A＃(B♭)\",\n                icobot_buzzer_si: \"B\",\n                icobot_led_total: \"All\",\n                icobot_led_left_up: \"Left Top\",\n                icobot_led_left_down: \"Left Bottom\",\n                icobot_led_right_up: \"Right Top\",\n                icobot_led_right_down: \"Right Bottom\",\n                icobot_color_white: \"White\",\n                icobot_color_red: \"Red\",\n                icobot_color_orange: \"Orange\",\n                icobot_color_yellow: \"Yellow\",\n                icobot_color_green: \"Green\",\n                icobot_color_blue: \"Blue\",\n                icobot_color_sky_blue: \"Sky Blue\",\n                icobot_color_purple: \"Purple\",\n                icobot_motor_both_wheels: \"Both\",\n                icobot_motor_left_wheels: \"Left\",\n                icobot_motor_right_wheels: \"Right\",\n                icobot_motor_front_move: \"Front\",\n                icobot_motor_back_move: \"Back\",\n                icobot_motor_left_turn: \"Left\",\n                icobot_motor_right_turn: \"Right\",\n                icobot_motor_straight: \"Straight Operation\",\n                icobot_motor_rotation: \"Rotation\",\n                icobot_motor_30_degrees: \"30°\",\n                icobot_motor_45_degrees: \"45°\",\n                icobot_motor_60_degrees: \"60°\",\n                icobot_motor_90_degrees: \"90°\",\n                icobot_motor_120_degrees: \"120°\",\n                icobot_motor_135_degrees: \"135°\",\n                icobot_motor_150_degrees: \"150°\",\n                icobot_motor_180_degrees: \"180°\",\n                icobot_motor_210_degrees: \"210°\",\n                icobot_motor_225_degrees: \"225°\",\n                icobot_motor_240_degrees: \"240°\",\n                icobot_motor_270_degrees: \"270°\",\n                icobot_motor_300_degrees: \"300°\",\n                icobot_motor_315_degrees: \"315°\",\n                icobot_motor_330_degrees: \"330°\",\n                icobot_motor_360_degrees: \"360°\",\n            }\n        }\n    }\n};\n\nEntry.iCOBOT.monitorTemplate = function() {\n\n    return {\n        imgPath: 'hw/iCOBOT_Front.png',\n        width: 550,\n        height: 600,\n        listPorts: {\n            BLeft_IR: {\n                name: Lang.Blocks.monitor_ir_bottom_left,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            BMid_IR: {\n                name: Lang.Blocks.monitor_ir_bottom_mid,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            BRight_IR: {\n                name: Lang.Blocks.monitor_ir_bottom_right,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            Real_T: {\n                name: Lang.Blocks.icobot_Temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            Real_H: {\n                name: Lang.Blocks.icobot_Humidity,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            Sound: {\n                name: Lang.Blocks.icobot_Sound,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            Brightness: {\n                name: Lang.Blocks.icobot_Brightness,\n                type: 'input',\n                pos: { x: 295, y: 350 },\n            },\n            Front_IR: {\n                name: Lang.Blocks.monitor_ir_front,\n                type: 'input',\n                pos: { x: 250, y: 300 },\n            },\n            Left_IR: {\n                name: Lang.Blocks.monitor_ir_left,\n                type: 'input',\n                pos: { x: 20, y: 450 },\n            },\n            Right_IR: {\n                name: Lang.Blocks.monitor_ir_right,\n                type: 'input',\n                pos: { x: 525, y: 450 },\n            },\n        },\n        mode: 'both',\n    };\n};\n\nEntry.iCOBOT.getBlocks = function() {\n    return {\n        //1. 센서 입력\t\t\t\n        icobot_sensor_input_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.icobot_sensor_input_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'icobot_sensor_input_title',\n            },\n            class: 'iCOBOT_ANA',\n            isNotFor: ['iCOBOT'],\n            events: {},\n        },\n\t\t\n\t\t// 조도(밝기) - 센서 값 \t\t\t\t\n        icobot_get_cds_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.icobot_get_cds_value,\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'icobot_get_cds_value',\n            },\n            paramsKeyMap: {},\n            class: 'iCOBOT_ANA',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script)\n\t\t\t{\n                var pd = Entry.hw.portData;\n\n                return pd['Brightness'];\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 소리(소음) - 센서 값 \t\t\t\t\n        icobot_get_sound_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.icobot_get_sound_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n            ],\n            events: {},\n            def: {\n                type: 'icobot_get_sound_value',\n            },\n            paramsKeyMap: {},\n            class: 'iCOBOT_ANA',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script)\n\t\t\t{\n                var pd = Entry.hw.portData;\n\n                return pd['Sound'];\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\t\t\n        icobot_get_analog_temp_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n            fontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_Temperature, 'Real_T'],\n                        [Lang.Blocks.icobot_Humidity, 'Real_H'],\n                    ],\n                    value: 'Real_T',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'icobot_get_analog_temp_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'iCOBOT_ANA',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n            {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n\n                return pd[dev];\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 불쾌지수\t\t\t\t\n        icobot_get_discomfort_index_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.icobot_get_discomfort_index_value,\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'icobot_get_discomfort_index_value',\n            },\n            paramsKeyMap: {},\n            class: 'iCOBOT_ANA',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script)\n\t\t\t{\n                var pd = Entry.hw.portData;\n                var Temperature = pd['Real_T'];\n                var Humidity = (pd['Real_H'])/100;\n                var Discomfort_index = (((9/5)*Temperature) - (0.55*(1-Humidity)*(((9/5)*Temperature)-26)) + 32);\n                return Discomfort_index;\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n        icobot_get_distsensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_ir_front, 'Front_IR'],\n                        [Lang.Blocks.icobot_ir_left, 'Left_IR'],\n                        [Lang.Blocks.icobot_ir_right, 'Right_IR'],\n                        [Lang.Blocks.icobot_ir_bottom_left, 'BLeft_IR'],\n                        [Lang.Blocks.icobot_ir_bottom_mid, 'BMid_IR'],\n                        [Lang.Blocks.icobot_ir_bottom_right, 'BRight_IR'],\n                    ],\n                    value: 'Front_IR',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'icobot_get_distsensor_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'iCOBOT_ANA',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script)\n\t\t\t{\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n\n                return pd[dev];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        //2. 부저 관련\t\n        icobot_buzzer_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.icobot_buzzer_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'icobot_buzzer_title',\n            },\n            class: 'iCOBOT_BUZ',\n            isNotFor: ['iCOBOT'],\n            events: {},\n        },\n\n        icobot_buzzer_onoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_buzzer_on, '1'],\n                        [Lang.Blocks.icobot_buzzer_off, '0'],\n                    ],\t\t\t\t\t\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr2.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'icobot_buzzer_onoff',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'iCOBOT_BUZ',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\n                var sq = Entry.hw.sendQueue;\n                var value = script.getNumberValue('VALUE');\n                if(value == 1){\n                    sq.tone = 262;\n                }\n                else{\n                    sq.tone = 0;\n                }\n\n                return script.callReturn();\t\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 부저 - 부저 옥타브/음/초 동안 연주\n        icobot_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.icobot_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_buzzer_silent, '0'],\n                        [Lang.Blocks.icobot_buzzer_do, 'C'],\n                        [Lang.Blocks.icobot_buzzer_do_sharp, 'CS'],\n                        [Lang.Blocks.icobot_buzzer_re, 'D'],\n                        [Lang.Blocks.icobot_buzzer_re_sharp, 'DS'],\n                        [Lang.Blocks.icobot_buzzer_mi, 'E'],\n                        [Lang.Blocks.icobot_buzzer_fa, 'F'],\n                        [Lang.Blocks.icobot_buzzer_fa_sharp, 'FS'],\n                        [Lang.Blocks.icobot_buzzer_sol, 'G'],\n                        [Lang.Blocks.icobot_buzzer_sol_sharp, 'GS'],\n                        [Lang.Blocks.icobot_buzzer_la, 'A'],\n                        [Lang.Blocks.icobot_buzzer_la_sharp, 'AS'],\n                        [Lang.Blocks.icobot_buzzer_si, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr2.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"1\"],\n                    },\n                    null,\n                ],\n                type: 'icobot_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\t\t\t\t\n                NOTE: 1,\n                DURATION: 2,\n            },\n            class: 'iCOBOT_BUZ',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) {\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var duration = script.getNumberValue('DURATION', script);\n                var sq = Entry.hw.sendQueue;\n                var value = 0;\n\n                if (!script.isStart) \n\t\t\t\t{\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) \n\t\t\t\t\t{\n                        note = Entry.iCOBOT.toneTable[note];\n                    }\n                    if (note < 0) note = 0;\n                    else if (note > 12) note = 12;\n\n                    if (duration < 0) duration = 0;\n\t\t\t\t\t\n                    if (duration == 0) \n\t\t\t\t\t{\n                        sq.tone = 0;\n                        return script.callReturn();\n                    }\n\t\t\t\t\t\n                    if (octave < 0) octave = 0;\n                    else if (octave > 8) octave = 8;\n                    if (note != 0) value = Entry.iCOBOT.toneMap[note][octave];\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    sq.tone = value;\n\n                    setTimeout(function() \n\t\t\t\t\t{\n                        sq.tone = 0;\n                        script.timeFlag = 2;\n                    }, duration);\n                    return script;\n                } \n\t\t\t\telse if (script.timeFlag == 1) \n\t\t\t\t{\n                    return script;\n                } \n\t\t\t\telse if (script.timeFlag == 2) \n\t\t\t\t{\n\n                    setTimeout(function() \n\t\t\t\t\t{\n                        script.timeFlag = 0;\n                    }, 10); // 부저 끊어 소리내기 위해 0.01초 기다림.\n                    return script;\n                } \n\t\t\t\telse \n\t\t\t\t{\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 부저 - 부저 옥타브/음/초 동안 연주\n        icobot_set_digital_buzzer_notime: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.icobot_set_digital_buzzer_notime,\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_buzzer_silent, '0'],\n                        [Lang.Blocks.icobot_buzzer_do, 'C'],\n                        [Lang.Blocks.icobot_buzzer_do_sharp, 'CS'],\n                        [Lang.Blocks.icobot_buzzer_re, 'D'],\n                        [Lang.Blocks.icobot_buzzer_re_sharp, 'DS'],\n                        [Lang.Blocks.icobot_buzzer_mi, 'E'],\n                        [Lang.Blocks.icobot_buzzer_fa, 'F'],\n                        [Lang.Blocks.icobot_buzzer_fa_sharp, 'FS'],\n                        [Lang.Blocks.icobot_buzzer_sol, 'G'],\n                        [Lang.Blocks.icobot_buzzer_sol_sharp, 'GS'],\n                        [Lang.Blocks.icobot_buzzer_la, 'A'],\n                        [Lang.Blocks.icobot_buzzer_la_sharp, 'AS'],\n                        [Lang.Blocks.icobot_buzzer_si, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr2.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'icobot_set_digital_buzzer_notime',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\t\t\t\t\n                NOTE: 1,\n            },\n            class: 'iCOBOT_BUZ',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                var note = script.getValue('NOTE');\n                if (!Entry.Utils.isNumber(note)) \n                {\n                    note = Entry.iCOBOT.toneTable[note];\n                }\n                if (note < 0) note = 0;\n                else if (note > 12) note = 12;\n                \n                if (octave < 0) octave = 0;\n                else if (octave > 8) octave = 8;\n                if (note != 0) value = Entry.iCOBOT.toneMap[note][octave];\n                sq.tone = value;\n                return script.callReturn();\t\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        //3. LED 관련\n        icobot_led_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.icobot_led_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'icobot_led_title',\n            },\n            class: 'iCOBOT_RGB',\n            isNotFor: ['iCOBOT'],\n            events: {},\n        },\n        \n        icobot_rgb_list: {\n             color: EntryStatic.colorSet.block.default.HARDWARE,\n             outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n             fontColor: '#fff',\t\t\t\n             skeleton: 'basic_string_field',\n             statements: [],\n             template: '%1',\n             params: [\n                 {\n                     type: 'Dropdown',\n                     options: [\n                         [Lang.Blocks.icobot_led_total, '0'],\n                         [Lang.Blocks.icobot_led_left_up, '1'],\n                         [Lang.Blocks.icobot_led_right_up, '2'],\n                         [Lang.Blocks.icobot_led_left_down, '3'],\n                         [Lang.Blocks.icobot_led_right_down, '4'],\t\t\t\t\n                     ],\n                     value: '0',\n                     fontSize: 11,\n                     bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                     arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                 },\n             ],\n             events: {},\n             def: {\n                 params: [null],\n             },\n             paramsKeyMap: {\n                 PORT: 0,\n             },\n             func: function(sprite, script) {\n                 return script.getField('PORT');\n             },\n         },\n\t\t\n\t\t// RGBLED - 종류 선택 및 On/Off\n\t\ticobot_digital_rgbled_onoff: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    // type: 'Dropdown',\n                    // options: [\n                    //     [Lang.Blocks.icobot_led_total, '0'],\n                    //     [Lang.Blocks.icobot_led_left_up, '1'],\n                    //     [Lang.Blocks.icobot_led_right_up, '2'],\n                    //     [Lang.Blocks.icobot_led_left_down, '3'],\n                    //     [Lang.Blocks.icobot_led_right_down, '4'],\n                    // ],\n                    // value: '0',\n                    // fontSize: 11,\n                    // bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    // arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_color_white, '1'],\n                        [Lang.Blocks.icobot_color_red, '2'],\n                        [Lang.Blocks.icobot_color_orange, '3'],\n                        [Lang.Blocks.icobot_color_yellow, '4'],\n                        [Lang.Blocks.icobot_color_green, '5'],\n                        [Lang.Blocks.icobot_color_blue, '6'],\n                        [Lang.Blocks.icobot_color_sky_blue, '7'],\n                        [Lang.Blocks.icobot_color_purple, '8'],\t\t\t\t\t\t\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'icobot_rgb_list',\n                    },\n                    null\n                ],\n                type: 'icobot_digital_rgbled_onoff',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                COLOR: 1,\n            },\n            class: 'iCOBOT_RGB',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\t\n                var sq = Entry.hw.sendQueue;\n                var num = script.getNumberValue('NUM', script);\n                var color = script.getNumberValue('COLOR', script);\n\n\t\t\t\tvar rLED, gLED, bLED;\n\n\t\t\t\tswitch(color)\n\t\t\t\t{\n\t\t\t\t\tcase 0:\trLED = gLED = bLED = 0;\t\t\t        // Black\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\trLED = gLED = bLED = 255;\t\t        // white\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\trLED = 255; gLED = bLED = 0;\t        // Red\n\t\t\t\t\t\t\t\tbreak;\n                    case 3:\trLED = 255; gLED = 50; bLED = 0;         // orange\n                                break;\n                    case 4:\trLED = gLED = 255; bLED = 0;            // Yellow\n                                break;\n\t\t\t\t\tcase 5:\trLED = bLED = 0; gLED = 255;\t        // green\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 6:\trLED = gLED = 0; bLED = 255;\t        // Blue\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 7:\trLED = 0; gLED = bLED = 255;            // sky_blue\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 8:\trLED = bLED = 255; gLED = 0;\t\t    // purple\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t}\n                \n\n\t\t\t\tswitch(num)\n\t\t\t\t{\n\t\t\t\t\tcase 0:\n                        sq.left_up_red = sq.right_up_red = sq.left_down_red = sq.right_down_red = rLED;\n                        sq.left_up_green = sq.right_up_green = sq.left_down_green = sq.right_down_green = gLED;\n                        sq.left_up_blue = sq.right_up_blue = sq.left_down_blue = sq.right_down_blue = bLED;\n                        break;\n\t\t\t\t\tcase 1:\n                        sq.left_up_red = rLED;\n                        sq.left_up_green = gLED;\n                        sq.left_up_blue = bLED;\n                        break;\n\t\t\t\t\tcase 2:\n                        sq.right_up_red = rLED;\n                        sq.right_up_green = gLED;\n                        sq.right_up_blue = bLED;\n                        break;\n                    case 3:\n                        sq.left_down_red = rLED;\n                        sq.left_down_green = gLED;\n                        sq.left_down_blue = bLED;\n                        break;\n                    case 4:\n                        sq.right_down_red = rLED;\n                        sq.right_down_green = gLED;\n                        sq.right_down_blue = bLED;\n                        break;\n\t\t\t\t}\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n\t\t// RGBLED - Off\n\t\ticobot_digital_rgbled_off: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [    \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    // type: 'Dropdown',\n                    // options: [\n                    //     [Lang.Blocks.icobot_led_total, '0'],\n                    //     [Lang.Blocks.icobot_led_left_up, '1'],\n                    //     [Lang.Blocks.icobot_led_right_up, '2'],\n                    //     [Lang.Blocks.icobot_led_left_down, '3'],\n                    //     [Lang.Blocks.icobot_led_right_down, '4'],\n                    // ],\n                    // value: '0',\n                    // fontSize: 11,\n                    // bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    // arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'icobot_rgb_list',\n                    },\n                    null\n                ],\n                type: 'icobot_digital_rgbled_off',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'iCOBOT_RGB',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\n                var sq = Entry.hw.sendQueue;\n                var num = script.getNumberValue('NUM', script);\n                \n\t\t\t\tswitch(num)\n\t\t\t\t{\n\t\t\t\t\tcase 0:\n                        sq.left_up_red = sq.right_up_red = sq.left_down_red = sq.right_down_red = 0;\n                        sq.left_up_green = sq.right_up_green = sq.left_down_green = sq.right_down_green = 0;\n                        sq.left_up_blue = sq.right_up_blue = sq.left_down_blue = sq.right_down_blue = 0;\n                        break;\n\t\t\t\t\tcase 1:\n                        sq.left_up_red = 0;\n                        sq.left_up_green = 0;\n                        sq.left_up_blue = 0;\n                        break;\n\t\t\t\t\tcase 2:\n                        sq.right_up_red = 0;\n                        sq.right_up_green = 0;\n                        sq.right_up_blue = 0;\n                        break;\n                    case 3:\n                        sq.left_down_red = 0;\n                        sq.left_down_green = 0;\n                        sq.left_down_blue = 0;\n                        break;\n                    case 4:\n                        sq.right_down_red = 0;\n                        sq.right_down_green = 0;\n                        sq.right_down_blue = 0;\n                        break;\n\t\t\t\t}\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\t\t// RGBLED - RGB 값으로 켜기\n\t\ticobot_digital_set_rgbled_value: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    // type: 'Dropdown',\n                    // options: [\n                    //     [Lang.Blocks.icobot_led_total, '0'],\n                    //     [Lang.Blocks.icobot_led_left_up, '1'],\n                    //     [Lang.Blocks.icobot_led_right_up, '2'],\n                    //     [Lang.Blocks.icobot_led_left_down, '3'],\n                    //     [Lang.Blocks.icobot_led_right_down, '4'],\n                    // ],\n                    // value: '0',\n                    // fontSize: 11,\n                    // bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    // arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'icobot_rgb_list',\n                    },\t\t\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\t\t\t\t\n\t\t\t\t\t{\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\t\n                    null,\n                ],\n                type: 'icobot_digital_set_rgbled_value',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE0:1,\n                VALUE1:2,\n\t\t\t\tVALUE2:3,\n            },\n            class: 'iCOBOT_RGB',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\n                var sq = Entry.hw.sendQueue;  \n                var num = script.getNumberValue('NUM', script);\n                var rLED = script.getNumberValue('VALUE0', script);\n                var gLED = script.getNumberValue('VALUE1', script);\n                var bLED = script.getNumberValue('VALUE2', script);\n                switch(num)\n\t\t\t\t{\n\t\t\t\t\tcase 0:\n                        sq.left_up_red = sq.right_up_red = sq.left_down_red = sq.right_down_red = rLED;\n                        sq.left_up_green = sq.right_up_green = sq.left_down_green = sq.right_down_green = gLED;\n                        sq.left_up_blue = sq.right_up_blue = sq.left_down_blue = sq.right_down_blue = bLED;\n                        break;\n\t\t\t\t\tcase 1:\n                        sq.left_up_red = rLED;\n                        sq.left_up_green = gLED;\n                        sq.left_up_blue = bLED;\n                        break;\n\t\t\t\t\tcase 2:\n                        sq.right_up_red = rLED;\n                        sq.right_up_green = gLED;\n                        sq.right_up_blue = bLED;\n                        break;\n                    case 3:\n                        sq.left_down_red = rLED;\n                        sq.left_down_green = gLED;\n                        sq.left_down_blue = bLED;\n                        break;\n                    case 4:\n                        sq.right_down_red = rLED;\n                        sq.right_down_green = gLED;\n                        sq.right_down_blue = bLED;\n                        break;\n\t\t\t\t}\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },      \n\n        //4. 모터 관련\n        icobot_motor_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.icobot_motor_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'icobot_motor_title',\n            },\n            class: 'iCOBOT_DC',\n            isNotFor: ['iCOBOT'],\n            events: {},\n        },\n\n\t\t// 모터 - 방향 바꾸기\t\t\n\t\ticobot_digital_set_motor_direction: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_motor_both_wheels, '2'],\t\n                        [Lang.Blocks.icobot_motor_left_wheels, '1'],\n                        [Lang.Blocks.icobot_motor_right_wheels, '3'],\t\t\t\t\t\t\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_motor_front_move, '0'],\n                        [Lang.Blocks.icobot_motor_back_move, '1'],\t\t\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\t\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'icobot_digital_set_motor_direction',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tDIR: 1,\n\t\t\t},\n            class: 'iCOBOT_DC',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\n                var sq = Entry.hw.sendQueue;  \n                var port = script.getNumberValue('PORT', script);\n                var dir = script.getNumberValue('DIR', script);\n                var pd = Entry.hw.portData;\n\n                switch(port)\n\t\t\t\t{\n\t\t\t\t\tcase 1:\n                        sq.leftmotor_dir = dir;\n                        if(!(sq.leftmotor_speed > 0))\n                        {\n                            sq.leftmotor_speed = 500;\n                        }else{}\n                        break;\n\t\t\t\t\tcase 2:\n                        sq.rightmotor_dir = dir;\n                        sq.leftmotor_dir = dir;\n                        if(!(sq.leftmotor_speed > 0))\n                        {\n                            sq.leftmotor_speed = 500;\n                        }else{}\n                        if(!(sq.rightmotor_speed > 0))\n                        {\n                            sq.rightmotor_speed = 500;\n                        }else{}\n                        break;\n                    case 3:\n                        sq.rightmotor_dir = dir;\n                        if(!(sq.rightmotor_speed > 0))\n                        {\n                            sq.rightmotor_speed = 500;\n                        }else{}\n                        break;\n                }\n                sq.motor_mode = 0;\n                motor_type = 0x00;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 모터 - 모터 속도 정하기\t\t\n\t\ticobot_digital_set_motor_speed: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_motor_both_wheels, '2'],\t\n                        [Lang.Blocks.icobot_motor_left_wheels, '1'],\n                        [Lang.Blocks.icobot_motor_right_wheels, '3'],\t\t\t\t\t\t\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\t\t\t\t\n                    null,\n                ],\n                type: 'icobot_digital_set_motor_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tSPEED: 1,\n            },\n            class: 'iCOBOT_DC',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var speed = script.getNumberValue('SPEED', script);\n\t\t\t\t\t\t\n                speed = Math.min(1000, speed);\n                speed = Math.max(0, speed);\n\n                switch(port)\n\t\t\t\t{\n\t\t\t\t\tcase 1:\n                        sq.leftmotor_speed = speed;\n                        break;\n\t\t\t\t\tcase 2:\n                        sq.rightmotor_speed = speed;\n                        sq.leftmotor_speed = speed;\n                        break;\n                    case 3:\n                        sq.rightmotor_speed = speed;\n                        break;\n                }\n                sq.motor_mode = 0;\n                motor_type = 0x00;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 모터 - 모터 정지하기\t\t\n\t\ticobot_digital_motor_stop: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_motor_both_wheels, '2'],\t\n                        [Lang.Blocks.icobot_motor_left_wheels, '1'],\n                        [Lang.Blocks.icobot_motor_right_wheels, '3'],\t\t\t\t\t\t\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'icobot_digital_motor_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'iCOBOT_DC',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\n                switch(port)\n\t\t\t\t{\n\t\t\t\t\tcase 1:\n                        sq.leftmotor_speed = 0;\n                        break;\n\t\t\t\t\tcase 2:\n                        sq.rightmotor_speed = 0;\n                        sq.leftmotor_speed = 0;\n                        break;\n                    case 3:\n                        sq.rightmotor_speed = 0;\n                        break;\n                }\n                sq.motor_mode = 0;\n                motor_type = 0x00;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\t\t// 모터 - 회전하기\t\t\n\t\ticobot_digital_set_motor_angle: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_motor_left_turn, '0'],\n                        [Lang.Blocks.icobot_motor_right_turn, '1'],\t\t\t\t\t\t\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                // {\n                //     type: 'Dropdown',\n                //     options: [\n                //         [Lang.Blocks.icobot_motor_30_degrees, '0'],\n                //         [Lang.Blocks.icobot_motor_45_degrees, '1'],\n                //         [Lang.Blocks.icobot_motor_60_degrees, '2'],\n                //         [Lang.Blocks.icobot_motor_90_degrees, '3'],\n                //         [Lang.Blocks.icobot_motor_120_degrees, '4'],\n                //         [Lang.Blocks.icobot_motor_135_degrees, '5'],\n                //         [Lang.Blocks.icobot_motor_150_degrees, '6'],\n                //         [Lang.Blocks.icobot_motor_180_degrees, '7'],\n                //         [Lang.Blocks.icobot_motor_210_degrees, '8'],\n                //         [Lang.Blocks.icobot_motor_225_degrees, '9'],\n                //         [Lang.Blocks.icobot_motor_240_degrees, '10'],\n                //         [Lang.Blocks.icobot_motor_270_degrees, '11'],\n                //         [Lang.Blocks.icobot_motor_300_degrees, '12'],\n                //         [Lang.Blocks.icobot_motor_315_degrees, '13'],\n                //         [Lang.Blocks.icobot_motor_330_degrees, '14'],\n                //         [Lang.Blocks.icobot_motor_360_degrees, '15'],\n                //     ],\n                //     value: '0',\n                //     fontSize: 11,\n                //     bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                //     arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                //     arrowColor: EntryStatic.ARROW_COLOR_HW,\n                // },\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null,\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"90\"],\n                    },\n                    null,\n                ],\n                type: 'icobot_digital_set_motor_angle',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n\t\t\t\tANGLE: 1,\n\t\t\t},\n            class: 'iCOBOT_DC',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\n                var sq = Entry.hw.sendQueue;\n                sq.motor_dir = script.getNumberValue('DIR', script);\n                sq.motor_value = script.getNumberValue('ANGLE', script);\n\n                var pd = Entry.hw.portData;\n                var Bool_Motor = pd['Motor_F'];\n\n                if(sq.motor_value == 0){\n                    return script.callReturn();\n                }\n                else{\n                    if (Bool_Motor == 0x03) {\n                        sq.motor_mode = 0x03;\n                        sq.leftmotor_speed = 0;\n                        sq.rightmotor_speed = 0;\n                        motor_type = 0x01;\n                        return script.callReturn();\n                    } else {\n                        sq.motor_mode = 0x01;\n                        if((!(sq.leftmotor_speed > 0)) && (!(sq.rightmotor_speed > 0)))\n                        {\n                            sq.leftmotor_speed = 500;\n                            sq.rightmotor_speed = 500;\n                        }else{}\n                        return script;\n                    }\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\t\t// 모터 - 거리 움직이기\t\t\n\t\ticobot_digital_set_motor_straight: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.icobot_motor_front_move, '0'],\n                        [Lang.Blocks.icobot_motor_back_move, '1'],\t\t\t\t\t\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"1\"],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'icobot_digital_set_motor_straight',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n\t\t\t\tDIR: 1,\n\t\t\t},\n            class: 'iCOBOT_DC',\n            isNotFor: ['iCOBOT'],\n            func: function(sprite, script) \n\t\t\t{\n                var sq = Entry.hw.sendQueue;\n                sq.motor_dir = script.getNumberValue('DIR', script);\n                sq.motor_value = script.getNumberValue('VALUE', script);\n\n                var pd = Entry.hw.portData;\n                var Bool_Motor = pd['Motor_F'];\n\n                if(sq.motor_value == 0){\n                    return script.callReturn();\n                }\n                else{\n                    if (Bool_Motor == 0x03) {\n                        sq.motor_mode = 0x03;\n                        sq.leftmotor_speed = 0;\n                        sq.rightmotor_speed = 0;\n                        motor_type = 0x02;\n                        return script.callReturn();\n                    } else {\n                        sq.motor_mode = 0x02;\n                        if((!(sq.leftmotor_speed > 0)) && (!(sq.rightmotor_speed > 0)))\n                        {\n                            sq.leftmotor_speed = 500;\n                            sq.rightmotor_speed = 500;\n                        }else{}\n                        return script;\n                    }\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        icobot_digital_wait_motor_movement: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'icobot_digital_wait_motor_movement',\n            },\n            paramsKeyMap: {},\n            class: 'iCOBOT_DC',\n            isNotFor: ['iCOBOT'],\n            func(sprite, script) {\n                var pd = Entry.hw.portData;\n\n                var Bool_Motor = pd['Motor_F'];\n\n                if (motor_type == Bool_Motor) {\n                    motor_type = 0x00;\n                    return script.callReturn();\n                } else {\n                    return script;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n    };\n};\n\nmodule.exports = Entry.iCOBOT;"
  },
  {
    "path": "src/playground/blocks/hardware/block_iboard.js",
    "content": "'use strict';\n\nEntry.iboard = {\n    id: '9.1',\n    name: 'iboard',\n    url: 'http://www.io-tech.co.kr',\n    imageName: 'iboard.png',\n    title: {\n        en: 'iboard',\n        ko: '아이보드',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.iboard.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                iboard_get_analog_value: '아날로그 %1 번 센서값',\n                iboard_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                iboard_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                iboard_toggle_led: '디지털 %1 번 핀 %2 %3',\n                iboard_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                iboard_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                iboard_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                iboard_get_digital: '디지털 %1 번 센서값',\n                iboard_button: '%1 버튼을 눌렀는가?',\n                iboard_motor: '모터를 %2 (으)로 동작하기',\n                iboard_LED_pwm: 'LED %1 번의 밝기를 %2 (으)로 정하기',\n                iboard_led: 'LED %1 번을 %2',\n                iboard_buzzer: '버저를 %2 %3 음으로 %4 초 연주하기',\n                iboard_rgb_pwm: 'RGB LED의 %1 LED의 밝기를 %2 (으)로 정하기',\n\t\t\t\tiboard_toggle_rgb: 'RGB LED의 %1 LED %2',\n                iboard_get_cds: '현재 밝기',\n                iboard_get_res: '가변저항 값',\n                iboard_get_mic: '소리센서 값',\n                iboard_get_tmp: '현재 섭씨온도',\n            },\n\t\t\tDevice: {\n                iboard: 'iboard',\n            },\n            Menus: {\n                iboard: 'iboard',\n            },\n        },\n        en: {\n            template: {\n                iboard_get_analog_value: 'Analog %1 Sensor value',\n                iboard_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                iboard_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                iboard_toggle_led: 'Digital %1 Pin %2 %3',\n                iboard_digital_pwm: 'Digital %1 Pin %2 %3',\n                iboard_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                iboard_set_servo: 'Set servo pin %1 angle as %2 %3',\n                iboard_get_digital: 'Digital %1 Sensor value',\n                iboard_button: 'Did you press button %1 ?',\n                iboard_motor: 'Turn on the fan %2',\n                iboard_LED_pwm: 'LED %1 Pin %2',\n                iboard_led: 'LED %1 pin %2',\n                iboard_buzzer: 'Play tone on note %2 octave %3 beat %4 %5',\n                iboard_rgb_pwm: 'RGB LED %1 Pin %2',\n\t\t\t\tiboard_toggle_rgb: 'RGB LED %1 LED %2',\n                iboard_get_cds: 'Light Sensor Value',\n                iboard_get_res: 'Potentiometer Value',\n                iboard_get_mic: 'Mic Value',\n                iboard_get_tmp: 'Now Temp(C)',\n            },\n\t\t\tDevice: {\n                iboard: 'iboard',\n            },\n            Menus: {\n                iboard: 'iboard',\n            },\n        },\n    };\n};\n\nEntry.iboard.blockMenuBlocks = [\n    'iboard_get_tmp',\n    'iboard_get_res',\n    'iboard_get_cds',\n    'iboard_get_mic',\n\t\n    'iboard_button',\n\t\n    'iboard_led',\n    'iboard_LED_pwm',\n    'iboard_rgb_pwm',\n\t'iboard_toggle_rgb',\n    'iboard_buzzer',\n    'iboard_motor',\n\t\n    'iboard_get_analog_value',\n    'iboard_get_analog_value_map',\n\t\n    'iboard_get_digital',\n\t\n    'iboard_toggle_led',\n    'iboard_digital_pwm',\n    'iboard_set_tone',\n\t'iboard_get_ultrasonic_value',\n];\n\nEntry.iboard.getBlocks = function() {\n    return {\n        iboard_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.iboard_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'iboard_analog_list',\n                    },\n                ],\n            },\n        },\n\t\t\n\t\t\n/////////////////////////////////////////////////////////////////////////////////////////////\t\t\n\t\tiboard_button_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['D2', '2'], ['D3', '3'], ['D4', '4']],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n\t\tiboard_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'iboard_button_list',\n                    },\n                ],\n                type: 'iboard_button',\n            },\n\t\t\tparamsKeyMap: {\n                PORT: 0,\n            },\n\t\t\tclass: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'iboard' || name === 'ArduinoNano') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.iboard.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_motor_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['정지', '0'], ['미풍', '100'], ['약풍', '170'], ['강풍', '255']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('VALUE', script);\n            },\n        },\n\t\t\n\t\tiboard_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'iboard_motor_list'\n                    },\n                    null,\n                ],\n                type: 'iboard_motor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.iboard.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t/////////////////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_pwm_rgb_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['빨강', '5'], ['초록', '6'], ['파랑', '9']],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n\t\t\n\t\tiboard_rgb_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'iboard_pwm_rgb_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'iboard_rgb_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t//////////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_led_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['D10', '10'], ['D11', '11']],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n\t\tiboard_led_list2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['켜기', '1'], ['끄기', '0'],],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('VALUE', script);\n            },\n        },\n\t\tiboard_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'iboard_led_list',\n                    },\n                    {\n                        type: 'iboard_led_list2',\n                    },\n                    null,\n                ],\n                type: 'iboard_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.iboard.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.iboard.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.iboard.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t//////////////////////////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_toggle_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'iboard_pwm_rgb_list',\n                    },\n                    {\n                        type: 'iboard_led_list2',\n                    },\n                    null,\n                ],\n                type: 'iboard_toggle_rgb',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.iboard.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.iboard.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.iboard.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t//////////////////////////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_pwm_led_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['D5', '5'], ['D6', '6']],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n\t\t\n\t\tiboard_LED_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'iboard_pwm_led_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'iboard_LED_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t\n\t\t/////////////////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'iboard_tone_list',\n                    },\n                    {\n                        type: 'iboard_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'iboard_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.iboard.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.iboard.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.iboard.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.iboard.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.iboard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t//////////////////////////////////////////////////////////////////////////////\n        iboard_get_cds: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                ],\n                type: 'iboard_get_cds',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t//////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_get_res: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'iboard_get_res',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t////////////////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_get_mic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['3'],\n                    },\n                ],\n                type: 'iboard_get_mic',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t////////////////////////////////////////////////////////////////////////////////\n\t\tiboard_get_tmp: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'iboard_get_tmp',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                var value1 =  ANALOG ? ANALOG[port] || 0 : 0;\n\t\t\t\tvar value2 = 5;\n                var value3 = 1023;\n                var value4 = 100;\n                var value5 = 50;\n                var result = value1 * value2 / value3 * value4 - value5;\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t\n\t\t\n/////////////////////////////////////////////////////////////////////////////////////////\t\t\n        iboard_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'iboard_analog_list',\n                    },\n                ],\n                type: 'iboard_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t///////////////////////////////////////////////////////////////////////\n        iboard_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'iboard_get_analog_value',\n                        params: [\n                            {\n                                type: 'iboard_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                ],\n                type: 'iboard_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t///////////////////////////////////////////////////////////////////////////////\n        iboard_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                ],\n                type: 'iboard_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.iboard.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////////\n        iboard_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'iboard_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'iboardGet',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'iboard' || name === 'ArduinoNano') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.iboard.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t////////////////////////////////////////////////////////////////////////////////////////////////\n        iboard_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_get_digital_toggle[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_digital_toggle',\n                    },\n                ],\n            },\n        },\n\t\t///////////////////////////////////////////////////////////////////////////////////////////////////////////\n        iboard_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'iboard_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.iboard.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.iboard.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.iboard.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t///////////////////////////////////////////////////////////////////////////////////////\n        iboard_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'iboard_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.iboard.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t//////////////////////////////////////////////////////////////////////////////////////\n        iboard_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'iboard_tone_list',\n                    },\n                ],\n            },\n        },\n        iboard_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'iboard_tone_list',\n                    },\n                ],\n                type: 'iboard_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'iboard_tone_value',\n                    },\n                ],\n            },\n        },\n        iboard_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'iboard_octave_list',\n                    },\n                ],\n            },\n        },\n        iboard_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'iboard_tone_list',\n                    },\n                    {\n                        type: 'iboard_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'iboard_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.iboard.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.iboard.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.iboard.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.iboard.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.iboard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t/////////////////////////////////////////////////////////////////////////\n        iboard_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'iboard_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'iboard',\n            isNotFor: ['iboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.iboard.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.iboard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_iotsmartfarm.js",
    "content": "'use strict';\n\nEntry.IotSmartFarm = {\n    PORT_MAP: {\n        control: 0,\n        led1: 0,\n        led2: 0,\n        led3: 0,\n        led4: 0,\n        led5: 0,\n        led6: 0,\n        display1: 0,\n        display2: 0,\n        display3: 0,\n        display4: 0,\n        display5: 0,\n        display6: 0,\n        display7: 0,\n        display8: 0,\n        display9: 0,\n        switch: 0\n    },\n    setZero: function() {\n        var portMap = Entry.IotSmartFarm.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        var IotSmartFarm = Entry.IotSmartFarm;\n        IotSmartFarm.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    id: '18.3',\n    name: 'iotsmartfarm',\n    url: 'http://saeon.co.kr/',\n    imageName: 'iotsmartfarm.png',\n    title: {\n        en: 'IOT SmartFarm',\n        ko: 'IOT 스마트팜',\n    },\n};\n\nEntry.IotSmartFarm.blockMenuBlocks = [\n    'iotsmartfarm_analogValue',\n    'iotsmartfarm_stopAll',\n    'iotsmartfarm_window',\n    'iotsmartfarm_fan',\n    'iotsmartfarm_pump',\n    'iotsmartfarm_heater',\n    'iotsmartfarm_camera',\n    'iotsmartfarm_led',\n    'iotsmartfarm_led_num',\n    'iotsmartfarm_display',\n    'iotsmartfarm_switch',\n];\n\nEntry.IotSmartFarm.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                iotsmartfarm_HUM: '습도',\n                iotsmartfarm_HEAT_TEMP: '난방온도',\n                iotsmartfarm_TEMP: '온도',\n                iotsmartfarm_SOIL: '토양',\n                iotsmartfarm_CDS: '조도',\n                iotsmartfarm_stopAll: '모두',\n                iotsmartfarm_stopWindow: '창문',\n                iotsmartfarm_stopFan: '환기',\n                iotsmartfarm_stopPump: '펌프',\n                iotsmartfarm_stopHeater: '히터',\n                iotsmartfarm_stopCamera: '카메라',\n                iotsmartfarm_stopLed: '조명',\n                iotsmartfarm_stopDisplay: '표시하기',\n                iotsmartfarm_open: '열기',\n                iotsmartfarm_close: '닫기',\n                iotsmartfarm_on: '켜기',\n                iotsmartfarm_off: '끄기',\n                iotsmartfarm_led_idx1: '1',\n                iotsmartfarm_led_idx2: '2',\n                iotsmartfarm_led_idx3: '3',\n                iotsmartfarm_led_idx4: '4',\n                iotsmartfarm_led_val0: '0',\n                iotsmartfarm_led_val1: '1',\n                iotsmartfarm_led_val2: '2',\n                iotsmartfarm_led_val3: '3',\n                iotsmartfarm_led_val4: '4',\n                iotsmartfarm_led_val5: '5',\n                iotsmartfarm_led_val6: '6',\n                iotsmartfarm_led_val7: '7',\n                iotsmartfarm_led_val8: '8',\n                iotsmartfarm_led_val9: '9',\n                iotsmartfarm_led_val10: '10',\n                iotsmartfarm_led_val11: '11',\n                iotsmartfarm_led_val12: '12',\n                iotsmartfarm_led_val13: '13',\n                iotsmartfarm_led_val14: '14',\n                iotsmartfarm_led_val15: '15',\n                iotsmartfarm_switch_idx1: '1',\n                iotsmartfarm_switch_idx2: '2',\n                iotsmartfarm_switch_idx3: '3',\n            },\n            template: {\n                iotsmartfarm_analogValue: 'IOT 스마트팜 %1 센서값',\n                iotsmartfarm_stopAll: '정지 %1%2',\n                iotsmartfarm_window: '창문 %1 %2',\n                iotsmartfarm_fan: '환기 %1 %2',\n                iotsmartfarm_pump: '펌프 %1 %2',\n                iotsmartfarm_heater: '히터 %1 %2',\n                iotsmartfarm_camera: '카메라 %1 %2',\n                iotsmartfarm_led: '조명 %1 R:%2 G:%3 B:%4 %5',\n                iotsmartfarm_led_num: '조명 %1 R:%2 G:%3 B:%4 %5',\n                iotsmartfarm_display: '표시하기 %1 %2',\n                iotsmartfarm_switch: '%1 번 스위치를 눌렸는가? %2',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            Blocks: {\n                iotsmartfarm_HUM: 'HUM',\n                iotsmartfarm_HEAT_TEMP: 'HEATER',\n                iotsmartfarm_TEMP: 'TEMP',\n                iotsmartfarm_SOIL: 'SOIL',\n                iotsmartfarm_CDS: 'CDS',\n                iotsmartfarm_stopAll: 'All',\n                iotsmartfarm_stopWindow: 'Window',\n                iotsmartfarm_stopFan: 'Fan',\n                iotsmartfarm_stopPump: 'Pump',\n                iotsmartfarm_stopHeater: 'Heater',\n                iotsmartfarm_stopCamera: 'Cam',\n                iotsmartfarm_stopLed: 'Led',\n                iotsmartfarm_stopDisplay: 'Display',\n                iotsmartfarm_open: 'Open',\n                iotsmartfarm_close: 'Close',\n                iotsmartfarm_on: 'On',\n                iotsmartfarm_off: 'Off',\n                iotsmartfarm_led_idx1: '1',\n                iotsmartfarm_led_idx2: '2',\n                iotsmartfarm_led_idx3: '3',\n                iotsmartfarm_led_idx4: '4',\n                iotsmartfarm_led_val0: '0',\n                iotsmartfarm_led_val1: '1',\n                iotsmartfarm_led_val2: '2',\n                iotsmartfarm_led_val3: '3',\n                iotsmartfarm_led_val4: '4',\n                iotsmartfarm_led_val5: '5',\n                iotsmartfarm_led_val6: '6',\n                iotsmartfarm_led_val7: '7',\n                iotsmartfarm_led_val8: '8',\n                iotsmartfarm_led_val9: '9',\n                iotsmartfarm_led_val10: '10',\n                iotsmartfarm_led_val11: '11',\n                iotsmartfarm_led_val12: '12',\n                iotsmartfarm_led_val13: '13',\n                iotsmartfarm_led_val14: '14',\n                iotsmartfarm_led_val15: '15',\n                iotsmartfarm_switch_idx1: '1',\n                iotsmartfarm_switch_idx2: '2',\n                iotsmartfarm_switch_idx3: '3',\n            },\n            template: {\n                iotsmartfarm_analogValue: 'IOT SmartFarm %1 sensor value',\n                iotsmartfarm_stopAll: 'Stop %1%2',\n                iotsmartfarm_window: 'Window %1 %2',\n                iotsmartfarm_fan: 'Fan %1 %2',\n                iotsmartfarm_pump: 'Pump %1 %2',\n                iotsmartfarm_heater: 'Heater %1 %2',\n                iotsmartfarm_camera: 'Cam %1 %2',\n                iotsmartfarm_led: 'Led %1 R:%2 G:%3 B:%4 %5',\n                iotsmartfarm_led_num: 'Led %1 R:%2 G:%3 B:%4 %5',\n                iotsmartfarm_display: 'Display %1 %2',\n                iotsmartfarm_switch: 'Switch %1 pressed? %2',\n            },\n        },\n    };\n};\n\nEntry.IotSmartFarm.getBlocks = function() {\n    return {\n        //region IotSmartFarm IOT스마트팜\n        iotsmartfarm_analogValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_HUM, 'hum'],\n                        [Lang.Blocks.iotsmartfarm_HEAT_TEMP, 'heatertemp'],\n                        [Lang.Blocks.iotsmartfarm_TEMP, 'temp'],\n                        [Lang.Blocks.iotsmartfarm_SOIL, 'soil'],\n                        [Lang.Blocks.iotsmartfarm_CDS, 'cds'],\n                    ],\n                    value: 'hum',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'iotsmartfarm_analogValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'iotsmartfarm_sensor',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['IotSmartFarm.analog_value(%1)'] },\n        },\n        iotsmartfarm_stopAll: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_stopAll, 'All'],\n                        [Lang.Blocks.iotsmartfarm_stopWindow, 'Window'],\n                        [Lang.Blocks.iotsmartfarm_stopFan, 'Fan'],\n                        [Lang.Blocks.iotsmartfarm_stopPump, 'Pump'],\n                        [Lang.Blocks.iotsmartfarm_stopHeater, 'Heater'],\n                        [Lang.Blocks.iotsmartfarm_stopCamera, 'Cam'],\n                        [Lang.Blocks.iotsmartfarm_stopLed, 'Led'],\n                        [Lang.Blocks.iotsmartfarm_stopDisplay, 'Display'],\n                    ],\n                    value: 'All',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'iotsmartfarm_stopAll',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'All') {\n                    sq.control = 0;\n                    sq.led1 = 0;\n                    sq.led2 = 0;\n                    sq.led3 = 0;\n                    sq.led4 = 0;\n                    sq.led5 = 0;\n                    sq.led6 = 0;\n                    sq.display1 = 0;\n                    sq.display2 = 0;\n                    sq.display3 = 0;\n                    sq.display4 = 0;\n                    sq.display5 = 0;\n                    sq.display6 = 0;\n                    sq.display7= 0;\n                    sq.display8 = 0;\n                    sq.display9 = 0;\n                } else if (direction == 'Window') {\n                    sq.control &= 0xfe;\n                } else if (direction == 'Fan') {\n                    sq.control &= 0xfd;\n                } else if (direction == 'Pump') {\n                    sq.control &= 0xfb;\n                } else if (direction == 'Heater') {\n                    sq.control &= 0xf7;\n                } else if (direction == 'Cam') {\n                    sq.control &= 0x0f;\n                } else if (direction == 'Led') {\n                    sq.led1 = 0;\n                    sq.led2 = 0;\n                    sq.led3 = 0;\n                    sq.led4 = 0;\n                    sq.led5 = 0;\n                    sq.led6 = 0;\n                } else if (direction == 'Display') {\n                    sq.display1 = 0;\n                    sq.display2 = 0;\n                    sq.display3 = 0;\n                    sq.display4 = 0;\n                    sq.display5 = 0;\n                    sq.display6 = 0;\n                    sq.display7 = 0;\n                    sq.display8 = 0;\n                    sq.display9 = 0;\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.stop(%1)'] },\n        },\n        iotsmartfarm_window: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_open, 'Open'],\n                        [Lang.Blocks.iotsmartfarm_close, 'Close'],\n                    ],\n                    value: 'Close',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'iotsmartfarm_window',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'Open') {\n                    sq.control |= 0x01;\n                } else if (direction == 'Close') {\n                    sq.control &= 0xfe;\n                } \n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.window(%1)'] },\n        },\n        iotsmartfarm_fan: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_on, 'On'],\n                        [Lang.Blocks.iotsmartfarm_off, 'Off'],\n                    ],\n                    value: 'Off',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'iotsmartfarm_fan',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'On') {\n                    sq.control |= 0x02;\n                } else if (direction == 'Off') {\n                    sq.control &= 0xfd;\n                } \n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.fan(%1)'] },\n        },\n        iotsmartfarm_pump: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_on, 'On'],\n                        [Lang.Blocks.iotsmartfarm_off, 'Off'],\n                    ],\n                    value: 'Off',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'iotsmartfarm_pump',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'On') {\n                    sq.control |= 0x04;\n                } else if (direction == 'Off') {\n                    sq.control &= 0xfb;\n                } \n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.pump(%1)'] },\n        },\n        iotsmartfarm_heater: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_on, 'On'],\n                        [Lang.Blocks.iotsmartfarm_off, 'Off'],\n                    ],\n                    value: 'Off',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'iotsmartfarm_heater',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getField('DIRECTION', script);\n\n                if (direction == 'On') {\n                    sq.control |= 0x08;\n                } else if (direction == 'Off') {\n                    sq.control &= 0xf7;\n                } \n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.heater(%1)'] },\n        },\n        iotsmartfarm_camera: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'iotsmartfarm_camera',\n            },\n            paramsKeyMap: {\n                camVal: 0,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var val = 0;\n\n                val = parseInt(Number(script.getStringValue('camVal')), 10);\n\n                if(val < 0) val = 0;\n                if(val > 15) val = 15;\n\n                sq.control &= 0x0f;\n                sq.control |= (val << 4) & 0xf0;\n                \n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.cam(%1)'] },\n        },\n        iotsmartfarm_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {                    \n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_led_idx1, '1'],\n                        [Lang.Blocks.iotsmartfarm_led_idx2, '2'],\n                        [Lang.Blocks.iotsmartfarm_led_idx3, '3'],\n                        [Lang.Blocks.iotsmartfarm_led_idx4, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_led_val0, '0'],\n                        [Lang.Blocks.iotsmartfarm_led_val1, '1'],\n                        [Lang.Blocks.iotsmartfarm_led_val2, '2'],\n                        [Lang.Blocks.iotsmartfarm_led_val3, '3'],\n                        [Lang.Blocks.iotsmartfarm_led_val4, '4'],\n                        [Lang.Blocks.iotsmartfarm_led_val5, '5'],\n                        [Lang.Blocks.iotsmartfarm_led_val6, '6'],\n                        [Lang.Blocks.iotsmartfarm_led_val7, '7'],\n                        [Lang.Blocks.iotsmartfarm_led_val8, '8'],\n                        [Lang.Blocks.iotsmartfarm_led_val9, '9'],\n                        [Lang.Blocks.iotsmartfarm_led_val10, '10'],\n                        [Lang.Blocks.iotsmartfarm_led_val11, '11'],\n                        [Lang.Blocks.iotsmartfarm_led_val12, '12'],\n                        [Lang.Blocks.iotsmartfarm_led_val13, '13'],\n                        [Lang.Blocks.iotsmartfarm_led_val14, '14'],\n                        [Lang.Blocks.iotsmartfarm_led_val15, '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_led_val0, '0'],\n                        [Lang.Blocks.iotsmartfarm_led_val1, '1'],\n                        [Lang.Blocks.iotsmartfarm_led_val2, '2'],\n                        [Lang.Blocks.iotsmartfarm_led_val3, '3'],\n                        [Lang.Blocks.iotsmartfarm_led_val4, '4'],\n                        [Lang.Blocks.iotsmartfarm_led_val5, '5'],\n                        [Lang.Blocks.iotsmartfarm_led_val6, '6'],\n                        [Lang.Blocks.iotsmartfarm_led_val7, '7'],\n                        [Lang.Blocks.iotsmartfarm_led_val8, '8'],\n                        [Lang.Blocks.iotsmartfarm_led_val9, '9'],\n                        [Lang.Blocks.iotsmartfarm_led_val10, '10'],\n                        [Lang.Blocks.iotsmartfarm_led_val11, '11'],\n                        [Lang.Blocks.iotsmartfarm_led_val12, '12'],\n                        [Lang.Blocks.iotsmartfarm_led_val13, '13'],\n                        [Lang.Blocks.iotsmartfarm_led_val14, '14'],\n                        [Lang.Blocks.iotsmartfarm_led_val15, '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_led_val0, '0'],\n                        [Lang.Blocks.iotsmartfarm_led_val1, '1'],\n                        [Lang.Blocks.iotsmartfarm_led_val2, '2'],\n                        [Lang.Blocks.iotsmartfarm_led_val3, '3'],\n                        [Lang.Blocks.iotsmartfarm_led_val4, '4'],\n                        [Lang.Blocks.iotsmartfarm_led_val5, '5'],\n                        [Lang.Blocks.iotsmartfarm_led_val6, '6'],\n                        [Lang.Blocks.iotsmartfarm_led_val7, '7'],\n                        [Lang.Blocks.iotsmartfarm_led_val8, '8'],\n                        [Lang.Blocks.iotsmartfarm_led_val9, '9'],\n                        [Lang.Blocks.iotsmartfarm_led_val10, '10'],\n                        [Lang.Blocks.iotsmartfarm_led_val11, '11'],\n                        [Lang.Blocks.iotsmartfarm_led_val12, '12'],\n                        [Lang.Blocks.iotsmartfarm_led_val13, '13'],\n                        [Lang.Blocks.iotsmartfarm_led_val14, '14'],\n                        [Lang.Blocks.iotsmartfarm_led_val15, '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'iotsmartfarm_led',\n            },\n            paramsKeyMap: {\n                IDX: 0,\n                LED_R: 1,\n                LED_G: 2,\n                LED_B: 3,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var led_idx = parseInt(Number(script.getStringField('IDX', script)), 10);\n                var led_r = parseInt(Number(script.getStringField('LED_R', script)), 10);\n                var led_g = parseInt(Number(script.getStringField('LED_G', script)), 10);\n                var led_b = parseInt(Number(script.getStringField('LED_B', script)), 10);\n                \n                var dst = 0;\n                var msk = 0xfff;\n                var org = 0;\n\n                dst |= led_b;\n                dst = (dst << 4) | led_g;\n                dst = (dst << 4) | led_r;\n                \n                dst = dst << ((led_idx - 1) % 2) * 12;\n                msk = msk << ((led_idx - 1) % 2) * 12;\n\n                \n                if ((led_idx == 1) || (led_idx == 2)) {\n                    org = sq.led3;\n                    org = (org << 8) | sq.led2;\n                    org = (org << 8) | sq.led1;\n\n                    org &= ~msk;\n                    org |= dst;\n\n                    sq.led1 = org & 0xff;\n                    sq.led2 = (org >> 8) & 0xff;\n                    sq.led3 = (org >> 16) & 0xff;\n                }\n                else if ((led_idx == 3) || (led_idx == 4)) {\n                    org = sq.led6;\n                    org = (org << 8) | sq.led5;\n                    org = (org << 8) | sq.led4;\n\n                    org &= ~msk;\n                    org |= dst;\n\n                    sq.led4 = org & 0xff;\n                    sq.led5 = (org >> 8) & 0xff;\n                    sq.led6 = (org >> 16) & 0xff;\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.led(%1, %2, %3, %4)'] },\n        },\n        iotsmartfarm_led_num: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'iotsmartfarm_led_num',\n            },\n            paramsKeyMap: {\n                LED_IDX: 0,\n                LED_R: 1,\n                LED_G: 2,\n                LED_B: 3,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var led_idx = script.getNumberValue('LED_IDX');\n                var led_r = script.getNumberValue('LED_R');\n                var led_g = script.getNumberValue('LED_G');\n                var led_b = script.getNumberValue('LED_B');\n                \n                if(led_idx < 1) led_idx = 1;\n                if(led_idx > 4) led_idx = 4;\n\n                if(led_r < 0) led_r = 0;\n                if(led_r > 15) led_r = 15;\n\n                if(led_g < 0) led_g = 0;\n                if(led_g > 15) led_g = 15;\n\n                if(led_b < 0) led_b = 0;\n                if(led_b > 15) led_b = 15;\n\n                var dst = 0;\n                var msk = 0xfff;\n                var org = 0;\n\n                dst |= led_b;\n                dst = (dst << 4) | led_g;\n                dst = (dst << 4) | led_r;\n                \n                dst = dst << ((led_idx - 1) % 2) * 12;\n                msk = msk << ((led_idx - 1) % 2) * 12;\n\n                \n                if ((led_idx == 1) || (led_idx == 2)) {\n                    org = sq.led3;\n                    org = (org << 8) | sq.led2;\n                    org = (org << 8) | sq.led1;\n\n                    org &= ~msk;\n                    org |= dst;\n\n                    sq.led1 = org & 0xff;\n                    sq.led2 = (org >> 8) & 0xff;\n                    sq.led3 = (org >> 16) & 0xff;\n                }\n                else if ((led_idx == 3) || (led_idx == 4)) {\n                    org = sq.led6;\n                    org = (org << 8) | sq.led5;\n                    org = (org << 8) | sq.led4;\n\n                    org &= ~msk;\n                    org |= dst;\n\n                    sq.led4 = org & 0xff;\n                    sq.led5 = (org >> 8) & 0xff;\n                    sq.led6 = (org >> 16) & 0xff;\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.led_num(%1, %2, %3, %4)'] },\n        },\n        iotsmartfarm_display: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['SmartFarm'],\n                    },\n                    null,\n                ],\n                type: 'iotsmartfarm_display',\n            },\n            paramsKeyMap: {\n                MSG: 0,\n            },\n            class: 'iotsmartfarm_output',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var msg = script.getStringValue('MSG', script);\n                var msgbuf;\n\n                for (var i = 0; i < 9; i++) {\n                    sq[`display${i + 1}`] = 0;\n                }\n\n                if(msg.length > 9) {\n                    msg = msg.substr(0, 9);\n                }\n                if(msg.length < 1) {\n                    msg = \" \";\n                }\n\n                for (var i = 0; i < msg.length; i++) {\n                    sq[`display${i + 1}`] = msg.charCodeAt(i);\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['IotSmartFarm.display(%1)'] },\n        },\n        iotsmartfarm_switch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.iotsmartfarm_switch_idx1, \"switch1\"],\n                        [Lang.Blocks.iotsmartfarm_switch_idx2, \"switch2\"],\n                        [Lang.Blocks.iotsmartfarm_switch_idx3, \"switch3\"],\n                    ],\n                    fontSize: 11\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \"switch1\"\n                ],\n                type: 'iotsmartfarm_switch',\n            },\n            paramsKeyMap: {\n                IDX: 0,\n            },\n            class: 'iotsmartfarm_expert',\n            isNotFor: ['iotsmartfarm'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('IDX');\n                console.log(dev + ' : ' +pd[dev]);\n                \n                if(pd[dev] == 1) {\n                    result = true;\n                }\n                else {\n                    result = false;\n                }\n\n                var result;\n\n                return result;\n            },\n            syntax: { js: [], py: ['IotSmartFarm.switch(%1)'] },\n        },\n    };\n};\n\nmodule.exports = Entry.IotSmartFarm;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_jcboard.js",
    "content": "'use strict';\n\nEntry.JCBoard = {\n    Cmd: {\n        CMD_GOLDENKEY0: 0,\n        CMD_GOLDENKEY1: 1,\n        CMD_GOLDENKEY2: 2,\n        CMD_GOLDENKEY3: 3,\n        CMD_LENGTH: 4,\n        CMD_CHECKSUM: 5,\n        CMD_LED: 6,\n        CMD_PIN: 7,\n        CMD_BUZZER: 8,\n        CMD_BUZZER_DUR: 9,\n        CMD_DC0: 10,\n        CMD_DC1: 11,\n        CMD_SERVO0: 12,\n        CMD_SERVO1: 13,\n        CMD_SERVO2: 14,\n        CMD_SERVO3: 15,\n        CMD_ULTRASONIC: 16,\n    },\n    Sensor: {\n        SENSOR_GOLDENKEY0: 0,\n        SENSOR_GOLDENKEY1: 1,\n        SENSOR_GOLDENKEY2: 2,\n        SENSOR_GOLDENKEY3: 3,\n        SENSOR_LENGTH: 4,\n        SENSOR_CHECKSUM: 5,\n        SENSOR_BUTTON: 6,\n        SENSOR_AIN0: 7,\n        SENSOR_AIN1: 8,\n        SENSOR_AIN2: 9,\n        SENSOR_AIN3: 10,\n        SENSOR_AIN4: 11,\n    },\n    setZero() {\n        Entry.hw.sendQueue.CMD = [\n            0x26,\n            0xa8,\n            0x14,\n            0xc1,\n            0x14,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n        ];\n        Entry.hw.update();\n    },\n    id: '1D.4',\n    name: 'JCBoard',\n    url: 'http://www.junilab.co.kr',\n    imageName: 'jcboard.png',\n    title: {\n        en: 'JCBoard',\n        ko: '제이씨보드',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/jcboard.png',\n        width: 600,\n        height: 535,\n        ports: {\n            A0: {\n                name: 'BUTTON1',\n                type: 'input',\n                pos: {\n                    x: 207,\n                    y: 385,\n                },\n            },\n            A1: {\n                name: 'BUTTON2',\n                type: 'input',\n                pos: {\n                    x: 280,\n                    y: 385,\n                },\n            },\n            A2: {\n                name: 'AIN1',\n                type: 'input',\n                pos: {\n                    x: 338,\n                    y: 385,\n                },\n            },\n            A3: {\n                name: 'AIN2',\n                type: 'input',\n                pos: {\n                    x: 380,\n                    y: 385,\n                },\n            },\n            A4: {\n                name: 'AIN3',\n                type: 'input',\n                pos: {\n                    x: 416,\n                    y: 385,\n                },\n            },\n            A5: {\n                name: 'AIN4',\n                type: 'input',\n                pos: {\n                    x: 453,\n                    y: 385,\n                },\n            },\n            A6: {\n                name: 'AIN5',\n                type: 'input',\n                pos: {\n                    x: 490,\n                    y: 385,\n                },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.JCBoard.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                jcboard_sonarport: '%1 번 포트를 초음파센서로 사용 %2',\n                jcboard_led: '%1 번 LED %2 %3',\n                jcboard_buzzer: '%1 음을 %2 초동안 소리내기 %3',\n                jcboard_dcmotor: '%1 번 DC모터를 %2 세기로 돌리기 %3',\n                jcboard_servomotor: '%1 번 서보모터를 %2도 회전 %3',\n                jcboard_pin: '%1 번 디지털핀을 %2 로 설정 %3',\n                jcboard_button: '%1 번 버튼 값',\n                jcboard_analog: '%1 번 아날로그 값',\n\n                jcboard_on: '켜기',\n                jcboard_off: '끄기',\n                jcboard_do: '도',\n                jcboard_re: '레',\n                jcboard_mi: '미',\n                jcboard_fa: '파',\n                jcboard_sol: '솔',\n                jcboard_ra: '라',\n                jcboard_si: '시',\n            },\n        },\n        en: {\n            template: {\n                jcboard_sonarport: '%1 번 포트를 초음파센서로 사용 %2',\n                jcboard_led: '%1 번 LED %2 %3',\n                jcboard_buzzer: '%1 음을 %2 초동안 소리내기모 %3',\n                jcboard_dcmotor: '%1 번 DC모터를 %2 세기로 돌리기 %3',\n                jcboard_servomotor: '%1 번 서보모터를 %2도 회전 %3',\n                jcboard_pin: '%1 번 디지털핀을 %2 로 설정 %3',\n                jcboard_button: '%1 번 버튼 값',\n                jcboard_analog: '%1 번 아날로그 값',\n\n                jcboard_on: '켜기',\n                jcboard_off: '끄기',\n                jcboard_do: '도',\n                jcboard_re: '레',\n                jcboard_mi: '미',\n                jcboard_fa: '파',\n                jcboard_sol: '솔',\n                jcboard_ra: '라',\n                jcboard_si: '시',\n            },\n        },\n    };\n};\n\nEntry.JCBoard.blockMenuBlocks = [\n    'jcboard_sonarport',\n    'jcboard_led',\n    'jcboard_buzzer',\n    'jcboard_dcmotor',\n    'jcboard_servomotor',\n    'jcboard_pin',\n    'jcboard_button',\n    'jcboard_analog',\n];\n\nEntry.JCBoard.getBlocks = function() {\n    let noteID = 1;\n    const moveID = 1;\n    const rotID = 1;\n    let oldSensorData = [0x26, 0xa8, 0x14, 0xc1, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n    return {\n        //region JCBoard\n        jcboard_sonarport: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                        ['3', 2],\n                        ['4', 3],\n                        ['5', 4],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jcboard_sonarport',\n            },\n            paramsKeyMap: {\n                SONARPORT: 0,\n            },\n            class: 'JCBoard_Command',\n            isNotFor: ['JCBoard'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xc1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const port = script.getNumberValue('SONARPORT', script);\n                cmd[Entry.JCBoard.Cmd.CMD_ULTRASONIC] |= 0x01 << port;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jcboard_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jcboard_on, 0],\n                        [Lang.template.jcboard_off, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jcboard_led',\n            },\n            paramsKeyMap: {\n                LED_PORT: 0,\n                LED_ACTION: 1,\n            },\n            class: 'JCBoard_Command',\n            isNotFor: ['JCBoard'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xc1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const what = script.getNumberValue('LED_PORT', script);\n                const act = script.getNumberValue('LED_ACTION', script);\n                if (act == 0) {\n                    cmd[Entry.JCBoard.Cmd.CMD_LED] |= 0x01 << what;\n                } else {\n                    cmd[Entry.JCBoard.Cmd.CMD_LED] &= ~(0x01 << what);\n                }\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jcboard_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jcboard_do, 1],\n                        [Lang.template.jcboard_re, 2],\n                        [Lang.template.jcboard_mi, 3],\n                        [Lang.template.jcboard_fa, 4],\n                        [Lang.template.jcboard_sol, 5],\n                        [Lang.template.jcboard_ra, 6],\n                        [Lang.template.jcboard_si, 7],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.5', 5],\n                        ['0.8', 8],\n                        ['1', 10],\n                        ['2', 20],\n                        ['3', 30],\n                        ['4', 40],\n                        ['5', 50],\n                    ],\n                    value: 10,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jcboard_buzzer',\n            },\n            paramsKeyMap: {\n                BUZZER_NOTE: 0,\n                BUZZER_DUR: 1,\n            },\n            class: 'JCBoard_Command',\n            isNotFor: ['JCBoard'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xc1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const note = script.getNumberValue('BUZZER_NOTE', script);\n                const delay = script.getNumberValue('BUZZER_DUR', script);\n\n                cmd[Entry.JCBoard.Cmd.CMD_BUZZER] = note | (noteID << 4);\n                cmd[Entry.JCBoard.Cmd.CMD_BUZZER_DUR] = delay;\n                noteID = (noteID + 1) & 0x0f;\n                console.log(\n                    '%d %d %d',\n                    cmd[Entry.JCBoard.Cmd.CMD_BUZZER],\n                    cmd[Entry.JCBoard.Cmd.CMD_BUZZER_DUR],\n                    noteID\n                );\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jcboard_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jcboard_dcmotor',\n            },\n            paramsKeyMap: {\n                MOTOR_WHAT: 0,\n                MOTOR_SPEED: 1,\n            },\n            class: 'JCBoard_Command',\n            isNotFor: ['JCBoard'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xc1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const what = script.getNumberValue('MOTOR_WHAT', script);\n                let speed = script.getNumberValue('MOTOR_SPEED', script);\n                if (speed > 100) {\n                    speed = 100;\n                } else if (speed < -100) {\n                    speed = -100;\n                }\n                cmd[Entry.JCBoard.Cmd.CMD_DC0 + what] = speed;\n                //console.log(\"%d %d\", \twhat, speed);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jcboard_servomotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                        ['3', 2],\n                        ['4', 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jcboard_servomotor',\n            },\n            paramsKeyMap: {\n                SERVO_WHAT: 0,\n                SERVO_DEGREE: 1,\n            },\n            class: 'JCBoard_Command',\n            isNotFor: ['JCBoard'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const what = script.getNumberValue('SERVO_WHAT', script);\n                let degree = script.getNumberValue('SERVO_DEGREE', script);\n                if (degree < -90) {\n                    degree = -90;\n                } else if (degree > 90) {\n                    degree = 90;\n                }\n                cmd[Entry.JCBoard.Cmd.CMD_SERVO0 + what] = degree;\n                console.log('servo what:%d degree:%d', what, degree);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jcboard_pin: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                        ['3', 2],\n                        ['4', 3],\n                        ['5', 4],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['HIGH', 0],\n                        ['LOW', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jcboard_pin',\n            },\n            paramsKeyMap: {\n                PIN_WHAT: 0,\n                PIN_STATE: 1,\n            },\n            class: 'JCBoard_Command',\n            isNotFor: ['JCBoard'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const what = script.getNumberValue('PIN_WHAT', script);\n                const state = script.getNumberValue('PIN_STATE', script);\n                if (state == 0) {\n                    cmd[Entry.JCBoard.Cmd.CMD_PIN] |= 0x01 << what;\n                } else {\n                    cmd[Entry.JCBoard.Cmd.CMD_PIN] &= ~(0x01 << what);\n                }\n                //console.log(\"servo what:%d degree:%d\", \twhat, degree);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jcboard_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jcboard_button',\n            },\n            paramsKeyMap: {\n                BUTTON_WHAT: 0,\n            },\n            class: 'JCBoard_Sensor',\n            isNotFor: ['JCBoard'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                const what = script.getNumberValue('BUTTON_WHAT', script);\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                return (sensorData[Entry.JCBoard.Sensor.SENSOR_BUTTON] & (0x01 << what))!=0? 1 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jcboard_analog: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                        ['3', 2],\n                        ['4', 3],\n                        ['5', 4],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jcboard_analog',\n            },\n            paramsKeyMap: {\n                ANALOG_WHAT: 0,\n            },\n            class: 'JCBoard_Sensor',\n            isNotFor: ['JCBoard'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                const what = script.getNumberValue('ANALOG_WHAT', script);\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                return sensorData[Entry.JCBoard.Sensor.SENSOR_AIN0 + what];\n            },\n            syntax: { js: [], py: [] },\n        },\n    };\n};\n\nmodule.exports = Entry.JCBoard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_jdcode.js",
    "content": "'use strict';\n\nEntry.JDCode = {\n    Cmd: {\n        CMD_LED: 1,\n        CMD_TUNE: 2,\n        CMD_TUNEDUR: 3,\n        CMD_ROLL_LOW: 4,\n        CMD_ROLL_HIGH: 5,\n        CMD_PITCH_LOW: 6,\n        CMD_PITCH_HIGH: 7,\n        CMD_OPTION_LOW: 8,\n        CMD_MOTOR0: 9,\n        CMD_MOTOR1: 10,\n        CMD_MOTOR2: 11,\n        CMD_MOTOR3: 12,\n        CMD_EXTPIN1: 13,\n        CMD_EXTPIN2: 14,\n        CMD_EXTPIN3: 15,\n        CMD_PWM: 16,\n        CMD_SERVOPORT: 17,\n        CMD_SERVODGREE: 18,\n        CMD_OPTION_HIGH: 19,\n        CMD_YAW_LOW: 20,\n        CMD_YAW_HIGH: 21,\n        CMD_THROTTLE_LOW: 22,\n        CMD_THROTTLE_HIGH: 23,\n        CMD_POSVEL_LOW: 24,\n        CMD_POSVEL_HIGH: 25,\n        CMD_YAWVEL_LOW: 26,\n        CMD_YAWVEL_HIGH: 27,\n        CMD_ULTRASONIC: 28,\n    },\n    Sensor: {\n        SENSOR_JOYSTICK_LLR: 1,\n        SENSOR_JOYSTICK_LTB: 2,\n        SENSOR_JOYSTICK_RLR: 3,\n        SENSOR_JOYSTICK_RTB: 4,\n        SENSOR_BUTTON: 5,\n        SENSOR_DRONECONNECT: 6,\n        SENSOR_DRONEALT: 7,\n        SENSOR_GYRO_X: 8,\n        SENSOR_GYRO_Y: 9,\n        SENSOR_DRONEREADY: 10,\n        SENSOR_EXTPIN1: 11,\n        SENSOR_EXTPIN2: 12,\n        SENSOR_ANALOG4: 13,\n        SENSOR_ANALOG5: 14,\n        SENSOR_JDKITMAX: 15,\n        SENSOR_BATTERY: 15,\n        SENSOR_POSX_L: 16,\n        SENSOR_POSX_H: 17,\n        SENSOR_POSY_L: 18,\n        SENSOR_POSY_H: 19,\n        SENSOR_ULTRASONIC: 20,\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.CMD = [\n            0xf0, 0, 0, 0, 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,\n        ];\n        Entry.hw.update();\n    },\n    id: '1D.2',\n    name: 'JDCode',\n    url: 'http://www.junilab.co.kr',\n    imageName: 'jdcode.png',\n    title: {\n        'en': 'JDCode',\n        'ko': '제이디코드',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/jdrc.png',\n        width: 600,\n        height: 355,\n        listPorts: {\n            'A6': {\n                name: '드론연결상태',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A10': {\n                name: '드론준비상태',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A15': {\n                name: '배터리(%)',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A8': {\n                name: '드론좌우기울기',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A9': {\n                name: '드론앞뒤기울기',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A7': {\n                name: '드론높이',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A16': {\n                name: '드론좌우이동',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'A18': {\n                name: '드론앞뒤이동',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n        },\n        ports: {\n            'A1': {\n                name: Lang.Blocks.jdkit_joystick_leftleftright,\n                type: 'input',\n                pos: {\n                    x: 140,\n                    y: 140,\n                },\n            },\n\n            'A2': {\n                name: Lang.Blocks.jdkit_joystick_lefttopbottom,\n                type: 'input',\n                pos: {\n                    x: 140,\n                    y: 140,\n                },\n            },\n            'A3': {\n                name: Lang.Blocks.jdkit_joystick_rightleftright,\n                type: 'input',\n                pos: {\n                    x: 450,\n                    y: 140,\n                },\n            },\n\n            'A4': {\n                name: Lang.Blocks.jdkit_joystick_righttopbottom,\n                type: 'input',\n                pos: {\n                    x: 450,\n                    y: 140,\n                },\n            },\n            'A5': {\n                name: '버튼',\n                type: 'input',\n                pos: {\n                    x: 430,\n                    y: 250,\n                },\n            },\n\n\n        },\n        mode: 'both',\n    },\n};\n\n\nEntry.JDCode.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                'jdcode_takeoff': '드론 이륙하기 %1',\n                'jdcode_landing': '드론 착륙하기 %1',\n                'jdcode_altitude': '%1cm 높이로 비행%2',\n                'jdcode_throttle': '프로펠러를 %1 % 세기로 돌리기 %2',\n                'jdcode_velocity': '%1(으)로 %2속도(cm/s)로 비행%3',\n                'jdcode_distance': '%1(으)로 %2cm 거리를 %3속도(cm/s)로 비행%4',\n                'jdcode_degree': '%1으로 %2도를 %3각속도(deg/s)로 회전 %4',\n                'jdcode_motor': '%1 모터를 %2 세기로 돌리기 %3',\n                'jdcode_emergency': '드론 즉시멈추기 %1',\n                'jdcode_connect': '드론 연결상태',\n                'jdcode_ready': '드론 준비상태',\n                'jdcode_battery': '배터리(%)',\n                'jdcode_dronealt': '드론 높이',\n                'jdcode_gyrox': '드론 좌우 기울기',\n                'jdcode_gyroy': '드론 앞뒤 기울기',\n                'jdcode_posx': '드론 좌우 이동',\n                'jdcode_posy': '드론 앞뒤 이동',\n                'jdcode_led': '%1 LED %2 %3',\n                'jdcode_tune': '%1 음을  %2 초동안 소리내기 %3',\n                'jdcode_joystick': '조이스틱 %1 읽기',\n                'jdcode_button': '%1번 버튼 값 읽어오기',\n                'jdcode_dir_front': '앞',\n                'jdcode_dir_back': '뒤',\n                'jdcode_dir_right': '오른쪽',\n                'jdcode_dir_left': '왼쪽',\n                'jdcode_alt': '드론 높이',\n                'jdcode_tiltx': '드론좌우기울기',\n                'jdcode_tilty': '드론앞뒤기울기',\n                'jdcode_battery': '배터리',\n            },\n        },\n        en: {\n            template: {\n                'jdcode_takeoff': '드론 이륙하기 %1',\n                'jdcode_landing': '드론 착륙하기 %1',\n                'jdcode_altitude': '%1cm 높이로 비행%2',\n                'jdcode_throttle': '프로펠러를 %1 % 세기로 돌리기 %2',\n                'jdcode_velocity': '%1(으)로 %2속도(cm/s)로 비행%3',\n                'jdcode_distance': '%1(으)로 %2cm 거리를 %3속도(cm/s)로 비행%4',\n                'jdcode_degree': '%1으로 %2도를 %3각속도(deg/s)로 회전 %4',\n                'jdcode_motor': '%1 모터를 %2 세기로 돌리기 %3',\n                'jdcode_emergency': '드론 즉시멈추기 %1',\n                'jdcode_connect': '드론 연결상태',\n                'jdcode_ready': '드론 준비상태',\n                'jdcode_battery': '배터리(%)',\n                'jdcode_dronealt': '드론 높이',\n                'jdcode_gyrox': '드론 좌우 기울기',\n                'jdcode_gyroy': '드론 앞뒤 기울기',\n                'jdcode_posx': '드론 좌우 이동',\n                'jdcode_posy': '드론 앞뒤 이동',\n                'jdcode_led': '%1 LED %2 %3',\n                'jdcode_tune': '%1 음을  %2 초동안 소리내기 %3',\n                'jdcode_joystick': '조이스틱 %1 읽기',\n                'jdcode_button': '%1번 버튼 값 읽어오기',\n                'jdcode_dir_front': '앞',\n                'jdcode_dir_back': '뒤',\n                'jdcode_dir_right': '오른쪽',\n                'jdcode_dir_left': '왼쪽',\n                'jdcode_alt': '드론 높이',\n                'jdcode_tiltx': '드론좌우기울기',\n                'jdcode_tilty': '드론앞뒤기울기',\n                'jdcode_battery': '배터리',\n            },\n        },\n    };\n};\n\n\nEntry.JDCode.blockMenuBlocks = [\n    'jdcode_takeoff',\n    'jdcode_landing',\n    'jdcode_altitude',\n    'jdcode_throttle',\n    'jdcode_velocity',\n    'jdcode_distance',\n    'jdcode_degree',\n    'jdcode_emergency',\n    'jdcode_connect',\n    'jdcode_ready',\n    'jdcode_battery',\n    'jdcode_dronealt',\n    'jdcode_gyrox',\n    'jdcode_gyroy',\n    'jdcode_posx',\n    'jdcode_posy',\n    'jdcode_led',\n    'jdcode_tune',\n    'jdcode_motor',\n    'jdcode_joystick',\n    'jdcode_button',\n];\n\n\nEntry.JDCode.getBlocks = function() {\n    return {\n        //region JDCode\n        jdcode_takeoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_takeoff',\n            },\n            paramsKeyMap: {},\n            class: 'JDCode_Command',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                }\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.JDCode.Cmd.CMD_THROTTLE_LOW] = 70;\n                cmd[Entry.JDCode.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.JDCode.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_LOW] = 0x2F;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_HIGH] = 0;\n\n                Entry.hw.sendQueue.rollCnt = 0;\n                Entry.hw.sendQueue.pitchCnt = 0;\n                Entry.hw.sendQueue.yawCnt = 0;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_landing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_landing',\n            },\n            paramsKeyMap: {},\n            class: 'JDCode_Command',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.JDCode.Cmd.CMD_THROTTLE_LOW] = 0;\n                cmd[Entry.JDCode.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.JDCode.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_LOW] = 0x2F;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_HIGH] = 0;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_altitude: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '100',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_altitude',\n            },\n            paramsKeyMap: {\n                THROTTLE: 0,\n            },\n            class: 'JDCode_Command',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var throttle = script.getNumberValue('THROTTLE', script);\n                cmd[Entry.JDCode.Cmd.CMD_THROTTLE_LOW] = throttle & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_THROTTLE_HIGH] = (throttle >> 8) & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_LOW] = 0x2F;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_throttle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_throttle',\n            },\n            paramsKeyMap: {\n                THROTTLE: 0,\n            },\n            class: 'JDCode_Command',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var throttle = script.getNumberValue('THROTTLE', script);\n                throttle = (throttle < 0) ? 0 : (throttle > 100) ? 1000 : throttle * 10;\n                cmd[Entry.JDCode.Cmd.CMD_THROTTLE_LOW] = throttle & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_THROTTLE_HIGH] = (throttle >> 8) & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_LOW] = 0x09;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jdcode_velocity: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jdcode_dir_front, 0],\n                        [Lang.template.jdcode_dir_back, 1],\n                        [Lang.template.jdcode_dir_right, 2],\n                        [Lang.template.jdcode_dir_left, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_velocity',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VELOCITY: 1,\n            },\n            class: 'JDCode_Command',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if ((direction == 1) || (direction == 3))\n                    velocity = velocity * -1;\n                if (direction < 2) {\n                    cmd[Entry.JDCode.Cmd.CMD_PITCH_LOW] = velocity & 0xFF;\n                    cmd[Entry.JDCode.Cmd.CMD_PITCH_HIGH] = (velocity >> 8) & 0xFF;\n                } else {\n                    cmd[Entry.JDCode.Cmd.CMD_ROLL_LOW] = velocity & 0xFF;\n                    cmd[Entry.JDCode.Cmd.CMD_ROLL_HIGH] = (velocity >> 8) & 0xFF;\n                }\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_LOW] = cmd[Entry.JDCode.Cmd.CMD_OPTION_LOW] & 0xDF;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_distance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jdcode_dir_front, 0],\n                        [Lang.template.jdcode_dir_back, 1],\n                        [Lang.template.jdcode_dir_right, 2],\n                        [Lang.template.jdcode_dir_left, 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '100',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_distance',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DISTANCE: 1,\n                VELOCITY: 2,\n            },\n            class: 'JDCode_Command',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var distance = script.getNumberValue('DISTANCE', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if ((direction == 1) || (direction == 3))\n                    distance = distance * -1;\n                if (direction < 2) {\n                    cmd[Entry.JDCode.Cmd.CMD_PITCH_LOW] = distance & 0xFF;\n                    cmd[Entry.JDCode.Cmd.CMD_PITCH_HIGH] = (distance >> 8) & 0xFF;\n                    var pitchCnt = Entry.hw.sendQueue.pitchCnt;\n                    Entry.hw.sendQueue.pitchCnt = typeof pitchCnt == 'undefined' ? 1 : pitchCnt + 1;\n\n                } else {\n                    cmd[Entry.JDCode.Cmd.CMD_ROLL_LOW] = distance & 0xFF;\n                    cmd[Entry.JDCode.Cmd.CMD_ROLL_HIGH] = (distance >> 8) & 0xFF;\n                    var rollCnt = Entry.hw.sendQueue.rollCnt;\n                    Entry.hw.sendQueue.rollCnt = typeof rollCnt == 'undefined' ? 1 : rollCnt + 1;\n                }\n                cmd[Entry.JDCode.Cmd.CMD_POSVEL_LOW] = velocity & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_POSVEL_HIGH] = (velocity >> 8) & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_LOW] = 0x2F;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_clockwise, 0],\n                        [Lang.Blocks.jdkit_counterclockwise, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '90',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '70',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_degree',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                DEGREE: 1,\n                VELOCITY: 2,\n            },\n            class: 'JDCode_Command',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n\n                var cmd = Entry.hw.sendQueue.CMD;\n                var direction = script.getField('DIRECTION', script);\n                var degree = script.getNumberValue('DEGREE', script);\n                var velocity = script.getNumberValue('VELOCITY', script);\n                if (direction == 1)\n                    degree = degree * -1;\n                cmd[Entry.JDCode.Cmd.CMD_YAW_LOW] = degree & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_YAW_HIGH] = (degree >> 8) & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_YAWVEL_LOW] = velocity & 0xFF;\n                cmd[Entry.JDCode.Cmd.CMD_YAWVEL_HIGH] = (velocity >> 8) & 0xFF;\n                var yawCnt = Entry.hw.sendQueue.yawCnt;\n                Entry.hw.sendQueue.yawCnt = typeof yawCnt == 'undefined' ? 1 : yawCnt + 1;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_emergency: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_emergency',\n            },\n            paramsKeyMap: {},\n            class: 'JDCode_Command',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                cmd[Entry.JDCode.Cmd.CMD_THROTTLE_LOW] = 0;\n                cmd[Entry.JDCode.Cmd.CMD_ROLL_LOW] = 0;\n                cmd[Entry.JDCode.Cmd.CMD_PITCH_LOW] = 0;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_LOW] = 0x00;\n                cmd[Entry.JDCode.Cmd.CMD_OPTION_HIGH] = 0;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_connect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_connect',\n            },\n            class: 'JDCode_Sensor',\n            isNotFor: ['JDCode'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.JDCode.Sensor.SENSOR_DRONECONNECT];\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_ready: {\n            parent: 'jdkit_ready',\n            def: {\n                params: [null],\n                type: 'jdcode_ready',\n            },\n            class: 'JDCode_Sensor',\n            isNotFor: ['JDCode'],\n            syntax: { js: [], py: [] },\n        },\n        jdcode_battery: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_battery',\n            },\n            class: 'JDCode_Sensor',\n            isNotFor: ['JDCode'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.JDCode.Sensor.SENSOR_BATTERY];\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_dronealt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_dronealt',\n            },\n            class: 'JDCode_Sensor',\n            isNotFor: ['JDCode'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.JDCode.Sensor.SENSOR_DRONEALT];\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_gyrox: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_gyrox',\n            },\n            class: 'JDCode_Sensor',\n            isNotFor: ['JDCode'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var x = sensorData[Entry.JDCode.Sensor.SENSOR_GYRO_X];\n                if (x > 127)\n                    x = -1 * (256 - x);\n                return x;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_gyroy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_gyroy',\n            },\n            class: 'JDCode_Sensor',\n            isNotFor: ['JDCode'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var y = sensorData[Entry.JDCode.Sensor.SENSOR_GYRO_Y];\n                if (y > 127)\n                    y = -1 * (256 - y);\n                return y;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_posx: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_posx',\n            },\n            class: 'JDCode_Sensor',\n            isNotFor: ['JDCode'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var posx = sensorData[Entry.JDCode.Sensor.SENSOR_POSX_L] + sensorData[Entry.JDCode.Sensor.SENSOR_POSX_H] * 256;\n                if (posx > 32767)\n                    posx = -1 * (65536 - posx);\n                return posx;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdcode_posy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_posy',\n            },\n            class: 'JDCode_Sensor',\n            isNotFor: ['JDCode'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var posy = sensorData[Entry.JDCode.Sensor.SENSOR_POSY_L] + sensorData[Entry.JDCode.Sensor.SENSOR_POSY_H] * 256;\n                if (posy > 32767)\n                    posy = -1 * (65536 - posy);\n                return posy;\n\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jdcode_led: {\n            parent: 'jdkit_led',\n            def: {\n                params: [null],\n                type: 'jdcode_led',\n            },\n            class: 'JDCode_CodeRC',\n            isNotFor: ['JDCode'],\n            syntax: { js: [], py: [] },\n        },\n        jdcode_tune: {\n            parent: 'jdkit_tune',\n            def: {\n                params: [null],\n                type: 'jdcode_tune',\n            },\n            class: 'JDCode_CodeRC',\n            isNotFor: ['JDCode'],\n            syntax: { js: [], py: [] },\n        },\n        jdcode_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_motor_lefttop, 1],\n                        [Lang.Blocks.jdkit_motor_leftbottom, 2],\n                        [Lang.Blocks.jdkit_motor_righttop, 0],\n                        [Lang.Blocks.jdkit_motor_rightbottom, 3],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '15',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdcode_motor',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                POWER: 1,\n            },\n            class: 'JDCode_CodeRC',\n            isNotFor: ['JDCode'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [\n                        0xf0, 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,\n                    ];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var motor = script.getField('MOTOR', script);\n                var power = script.getNumberValue('POWER', script);\n\n                cmd[Entry.JDKit.Cmd.MOTOR0 + motor] =\n                    power > 100 ? 100 : power < 0 ? 0 : power;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jdcode_joystick: {\n            parent: 'jdkit_joystick',\n            def: {\n                params: [null],\n                type: 'jdcode_joystick',\n            },\n            class: 'JDCode_CodeRC',\n            isNotFor: ['JDCode'],\n            syntax: { js: [], py: [] },\n        },\n        jdcode_button: {\n            parent: 'jdkit_button',\n            def: {\n                params: [null],\n                type: 'jdcode_button',\n            },\n            class: 'JDCode_CodeRC',\n            isNotFor: ['JDCode'],\n            syntax: { js: [], py: [] },\n        },\n\n        //endregion JDCode\n    };\n};\n\nmodule.exports = Entry.JDCode;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_jdkit.js",
    "content": "'use strict';\n\nEntry.JDKit = {\n    Cmd: {\n        LED: 1,\n        TUNE: 2,\n        TUNEDUR: 3,\n        ROLL: 4,\n        PITCH: 5,\n        YAW: 6,\n        THROTTLE: 7,\n        OPTION: 8,\n        MOTOR0: 9,\n        MOTOR1: 10,\n        MOTOR2: 11,\n        MOTOR3: 12,\n    },\n    Sensor: {\n        JOYSTICK_LLR: 1,\n        JOYSTICK_LTB: 2,\n        JOYSTICK_RLR: 3,\n        JOYSTICK_RTB: 4,\n        BUTTON: 5,\n        DRONECONNECT: 6,\n        ULTRASONIC: 7,\n        GYRO_X: 8,\n        GYRO_Y: 9,\n        DRONEREADY: 10,\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.CMD = [\n            0xf0,\n            0x00,\n            0x00,\n            0x00,\n            0x64,\n            0x64,\n            0x64,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n        ];\n        Entry.hw.update();\n    },\n    id: '1D.1',\n    name: 'JDKit',\n    url: 'http://www.junilab.co.kr',\n    imageName: 'jdkit.png',\n    title: {\n        en: 'JDKit',\n        ko: '제이디키트',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/jdrc.png',\n        width: 600,\n        height: 355,\n        listPorts: {\n            A6: {\n                name: '드론연결상태',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A10: {\n                name: '드론준비상태',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A8: {\n                name: '드론좌우기울기',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A9: {\n                name: '드론앞뒤기울기',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A7: {\n                name: '드론높이',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n        },\n        ports: {\n            A1: {\n                name: Lang.Blocks.jdkit_joystick_leftleftright,\n                type: 'input',\n                pos: {\n                    x: 140,\n                    y: 140,\n                },\n            },\n\n            A2: {\n                name: Lang.Blocks.jdkit_joystick_lefttopbottom,\n                type: 'input',\n                pos: {\n                    x: 140,\n                    y: 140,\n                },\n            },\n            A3: {\n                name: Lang.Blocks.jdkit_joystick_rightleftright,\n                type: 'input',\n                pos: {\n                    x: 450,\n                    y: 140,\n                },\n            },\n\n            A4: {\n                name: Lang.Blocks.jdkit_joystick_righttopbottom,\n                type: 'input',\n                pos: {\n                    x: 450,\n                    y: 140,\n                },\n            },\n            A5: {\n                name: '버튼',\n                type: 'input',\n                pos: {\n                    x: 430,\n                    y: 250,\n                },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.JDKit.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                jdkit_altitude: '드론을 %1 높이만큼 날리기 %2',\n                jdkit_button: '%1번 버튼 값 읽어오기',\n                jdkit_connect: '드론 연결 상태 읽어오기',\n                jdkit_emergency: '드론을 즉시 멈추기 %1',\n                jdkit_gyro: '보드 %1 기울기 값 읽어오기',\n                jdkit_joystick: '조이스틱 %1 읽기',\n                jdkit_led: '%1 LED %2  %3',\n                jdkit_motor: '%1 모터를 %2 세기로 돌리기 %3',\n                jdkit_ready: '드론 비행 준비 상태 읽어오기',\n                jdkit_rollpitch: '드론을 %1 방향 %2 세기로 움직이기 %3',\n                jdkit_throttle: '드론 프로펠러를 %1 만큼 세기로 돌리기 %2',\n                jdkit_tune: '%1 음을  %2 초동안 소리내기 %3',\n                jdkit_ultrasonic: '거리(초음파)값 읽어오기',\n                jdkit_yaw: '드론을 %1 만큼 회전하기 %2',\n            },\n            Blocks: {\n                jdkit_clockwise: '시계방향',\n                jdkit_counterclockwise: '반시계방향',\n                jdkit_gyro_frontrear: '앞뒤',\n                jdkit_gyro_leftright: '좌우',\n                jdkit_joystick_leftleftright: '왼쪽 좌우',\n                jdkit_joystick_lefttopbottom: '왼쪽 상하',\n                jdkit_joystick_rightleftright: '오른쪽 좌우',\n                jdkit_joystick_righttopbottom: '오른쪽 상하',\n                jdkit_led: 'LED',\n                jdkit_led_color_green: '초록색',\n                jdkit_led_color_orange: '오랜지색',\n                jdkit_led_turnoff: '끄기',\n                jdkit_led_turnon: '켜기',\n                jdkit_motor_leftbottom: '왼쪽아래',\n                jdkit_motor_lefttop: '왼쪽위',\n                jdkit_motor_rightbottom: '오른쪽아래',\n                jdkit_motor_righttop: '오른쪽위',\n                jdkit_tune_do: '도',\n                jdkit_tune_fa: '파',\n                jdkit_tune_la: '라',\n                jdkit_tune_mi: '미',\n                jdkit_tune_re: '레',\n                jdkit_tune_si: '시',\n                jdkit_tune_sol: '솔',\n            },\n            Menus: {\n                jdkit: '제이디키트',\n            },\n        },\n        en: {\n            template: {\n                jdkit_altitude: '드론을 %1 높이만큼 날리기 %2',\n                jdkit_button: '%1번 버튼 값 읽어오기',\n                jdkit_connect: '드론 연결 상태 읽어오기',\n                jdkit_emergency: '드론을 즉시 멈추기 %1',\n                jdkit_gyro: '보드 %1 기울기 값 읽어오기',\n                jdkit_joystick: '조이스틱 %1 읽기',\n                jdkit_led: '%1 LED %2  %3',\n                jdkit_motor: '%1 모터를 %2 세기로 돌리기 %3',\n                jdkit_ready: '드론 비행 준비 상태 읽어오기',\n                jdkit_rollpitch: '드론을 %1 방향 %2 세기로 움직이기 %3',\n                jdkit_throttle: '드론 프로펠러를 %1 만큼 세기로 돌리기 %2',\n                jdkit_tune: '%1 음을  %2 초동안 소리내기 %3',\n                jdkit_ultrasonic: '거리(초음파)값 읽어오기',\n                jdkit_yaw: '드론을 %1 만큼 회전하기 %2',\n            },\n            Blocks: {\n                jdkit_clockwise: '시계방향',\n                jdkit_counterclockwise: '반시계방향',\n                jdkit_gyro_frontrear: '앞뒤',\n                jdkit_gyro_leftright: '좌우',\n                jdkit_joystick_leftleftright: '왼쪽 좌우',\n                jdkit_joystick_lefttopbottom: '왼쪽 상하',\n                jdkit_joystick_rightleftright: '오른쪽 좌우',\n                jdkit_joystick_righttopbottom: '오른쪽 상하',\n                jdkit_led: 'LED',\n                jdkit_led_color_green: '초록색',\n                jdkit_led_color_orange: '오랜지색',\n                jdkit_led_turnoff: '끄기',\n                jdkit_led_turnon: '켜기',\n                jdkit_motor_leftbottom: '왼쪽아래',\n                jdkit_motor_lefttop: '왼쪽위',\n                jdkit_motor_rightbottom: '오른쪽아래',\n                jdkit_motor_righttop: '오른쪽위',\n                jdkit_tune_do: '도',\n                jdkit_tune_fa: '파',\n                jdkit_tune_la: '라',\n                jdkit_tune_mi: '미',\n                jdkit_tune_re: '레',\n                jdkit_tune_si: '시',\n                jdkit_tune_sol: '솔',\n            },\n            Menus: {\n                jdkit: 'JDKit',\n            },\n        },\n    };\n};\n\nEntry.JDKit.blockMenuBlocks = [\n    'jdkit_led',\n    'jdkit_tune',\n    'jdkit_motor',\n    'jdkit_joystick',\n    'jdkit_button',\n    'jdkit_gyro',\n    'jdkit_ultrasonic',\n    'jdkit_connect',\n    'jdkit_ready',\n    'jdkit_throttle',\n    'jdkit_altitude',\n    'jdkit_rollpitch',\n    'jdkit_yaw',\n    'jdkit_emergency',\n];\nEntry.JDKit.getBlocks = function() {\n    return {\n        //region JDKit\n        jdkit_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_joystick_lefttopbottom, 1],\n                        [Lang.Blocks.jdkit_joystick_leftleftright, 2],\n                        [Lang.Blocks.jdkit_joystick_righttopbottom, 3],\n                        [Lang.Blocks.jdkit_joystick_rightleftright, 4],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_joystick',\n            },\n            paramsKeyMap: {\n                JOYSTICK: 0,\n            },\n            class: 'JDKit_Sensor',\n            isNotFor: ['JDKit'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var joystick = script.getField('JOYSTICK');\n\n                if (joystick == 1) return sensorData[Entry.JDKit.Sensor.JOYSTICK_LTB];\n                else if (joystick == 2) return 100 - sensorData[Entry.JDKit.Sensor.JOYSTICK_LLR];\n                else if (joystick == 3) return sensorData[Entry.JDKit.Sensor.JOYSTICK_RTB] - 100;\n                else return 100 - sensorData[Entry.JDKit.Sensor.JOYSTICK_RLR];\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                        ['3', 2],\n                        ['4', 3],\n                        ['5', 4],\n                        ['6', 5],\n                        ['7', 6],\n                        ['8', 7],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_button',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'JDKit_Sensor',\n            isNotFor: ['JDKit'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var button = script.getField('BUTTON');\n                return sensorData[Entry.JDKit.Sensor.BUTTON] & (0x01 << button) ? 0 : 1;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_gyro: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_gyro_frontrear, 1],\n                        [Lang.Blocks.jdkit_gyro_leftright, 2],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_gyro',\n            },\n            paramsKeyMap: {\n                GYRO: 0,\n            },\n            class: 'JDKit_Sensor',\n            isNotFor: ['JDKit'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                var gyro = script.getField('GYRO');\n                var gyro_x = sensorData[Entry.JDKit.Sensor.GYRO_X];\n                var gyro_y = sensorData[Entry.JDKit.Sensor.GYRO_Y];\n                if (gyro == 1) return gyro_y > 127 ? (gyro_y ^ 0xff) + 1 : -1 * gyro_y;\n                else return gyro_x > 127 ? (gyro_x ^ 0xff) + 1 : -1 * gyro_x;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_ultrasonic',\n            },\n            class: 'JDKit_Sensor',\n            isNotFor: ['JDKit'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.JDKit.Sensor.ULTRASONIC];\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_connect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_connect',\n            },\n            class: 'JDKit_Sensor',\n            isNotFor: ['JDKit'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.JDKit.Sensor.DRONECONNECT];\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_ready: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_ready',\n            },\n            class: 'JDKit_Sensor',\n            isNotFor: ['JDKit'],\n            func: function(sprite, script) {\n                var sensorData = Entry.hw.portData.CMD;\n                return sensorData[Entry.JDKit.Sensor.DRONEREADY];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jdkit_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_led_color_green, 1],\n                        [Lang.Blocks.jdkit_led_color_orange, 2],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_led_turnon, 3],\n                        [Lang.Blocks.jdkit_led_turnoff, 4],\n                    ],\n                    value: 3,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_led',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                ACTION: 1,\n            },\n            class: 'JDKit_Command',\n            isNotFor: ['JDKit'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [0xf0, 0, 0, 0, 100, 100, 100, 0, 0, 0, 0, 0, 0];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var color = script.getField('COLOR', script);\n                var act = script.getField('ACTION', script);\n                if (color == 1) cmd[Entry.JDKit.Cmd.LED] = act == 3 ? cmd[1] | 0x01 : cmd[1] & 0x02;\n                else cmd[Entry.JDKit.Cmd.LED] = act == 3 ? cmd[1] | 0x02 : cmd[1] & 0x01;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_tune: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_tune_do, 1],\n                        [Lang.Blocks.jdkit_tune_re, 2],\n                        [Lang.Blocks.jdkit_tune_mi, 3],\n                        [Lang.Blocks.jdkit_tune_fa, 4],\n                        [Lang.Blocks.jdkit_tune_sol, 5],\n                        [Lang.Blocks.jdkit_tune_la, 6],\n                        [Lang.Blocks.jdkit_tune_si, 7],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.2', 2],\n                        ['0.4', 4],\n                        ['0.6', 6],\n                        ['0.8', 8],\n                        ['1', 10],\n                        ['2', 20],\n                        ['3', 30],\n                        ['4', 40],\n                        ['5', 50],\n                    ],\n                    value: 10,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_tune',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                DURATION: 1,\n            },\n            class: 'JDKit_Command',\n            isNotFor: ['JDKit'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [0xf0, 0, 0, 0, 100, 100, 100, 0, 0, 0, 0, 0, 0];\n                var cmd = Entry.hw.sendQueue.CMD;\n\n                var note = script.getField('NOTE', script);\n                var duration = script.getField('DURATION', script);\n                var noteCount = Entry.hw.sendQueue.noteCount;\n                Entry.hw.sendQueue.noteCount = typeof noteCount == 'undefined' ? 1 : noteCount + 1;\n                cmd[Entry.JDKit.Cmd.TUNE] = note;\n                cmd[Entry.JDKit.Cmd.TUNEDUR] = duration;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jdkit_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_motor_lefttop, 1],\n                        [Lang.Blocks.jdkit_motor_leftbottom, 0],\n                        [Lang.Blocks.jdkit_motor_righttop, 2],\n                        [Lang.Blocks.jdkit_motor_rightbottom, 3],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '15',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_motor',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                POWER: 1,\n            },\n            class: 'JDKit_Command',\n            isNotFor: ['JDKit'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [0xf0, 0, 0, 0, 100, 100, 100, 0, 0, 0, 0, 0, 0];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var motor = script.getField('MOTOR', script);\n                var power = script.getNumberValue('POWER', script);\n\n                cmd[Entry.JDKit.Cmd.MOTOR0 + motor] = power > 100 ? 100 : power < 0 ? 0 : power;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        jdkit_throttle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_throttle',\n            },\n            paramsKeyMap: {\n                THROTTLE: 0,\n            },\n            class: 'JDKit_Command',\n            isNotFor: ['JDKit'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [0xf0, 0, 0, 0, 100, 100, 100, 0, 0, 0, 0, 0, 0];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var throttle = script.getNumberValue('THROTTLE', script);\n\n                cmd[Entry.JDKit.Cmd.THROTTLE] = throttle > 200 ? 200 : throttle < 0 ? 0 : throttle;\n                cmd[Entry.JDKit.Cmd.OPTION] = 0x01;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_altitude: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_altitude',\n            },\n            paramsKeyMap: {\n                ALTITUDE: 0,\n            },\n            class: 'JDKit_Command',\n            isNotFor: ['JDKit'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [0xf0, 0, 0, 0, 100, 100, 100, 0, 0, 0, 0, 0, 0];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var alt = script.getNumberValue('ALTITUDE', script);\n\n                cmd[Entry.JDKit.Cmd.THROTTLE] = alt > 200 ? 200 : alt < 0 ? 0 : alt;\n                cmd[Entry.JDKit.Cmd.OPTION] = 0x05;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_rollpitch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.jdkit_gyro_frontrear, 1],\n                        [Lang.Blocks.jdkit_gyro_leftright, 2],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_rollpitch',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n                POWER: 1,\n            },\n            class: 'JDKit_Command',\n            isNotFor: ['JDKit'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [0xf0, 0, 0, 0, 100, 100, 100, 0, 0, 0, 0, 0, 0];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var dir = script.getField('DIR', script);\n                var power = script.getNumberValue('POWER', script);\n                if (dir == 1)\n                    cmd[Entry.JDKit.Cmd.PITCH] = power > 100 ? 200 : power < -100 ? 0 : power + 100;\n                else cmd[Entry.JDKit.Cmd.ROLL] = power > 100 ? 200 : power < -100 ? 0 : power + 100;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_yaw: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_yaw',\n            },\n            paramsKeyMap: {\n                YAW: 0,\n            },\n            class: 'JDKit_Command',\n            isNotFor: ['JDKit'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [0xf0, 0, 0, 0, 100, 100, 100, 0, 0, 0, 0, 0, 0];\n                var cmd = Entry.hw.sendQueue.CMD;\n                var yaw = script.getNumberValue('YAW', script);\n\n                cmd[Entry.JDKit.Cmd.YAW] = yaw > 25 ? 101 : yaw < -25 ? 99 : 100;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        jdkit_emergency: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jdkit_emergency',\n            },\n            paramsKeyMap: {},\n            class: 'JDKit_Command',\n            isNotFor: ['JDKit'],\n\n            func: function(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined')\n                    Entry.hw.sendQueue.CMD = [0xf0, 0, 0, 0, 100, 100, 100, 0, 0, 0, 0, 0, 0];\n                var cmd = Entry.hw.sendQueue.CMD;\n\n                cmd[Entry.JDKit.Cmd.OPTION] = 0x81;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        //endregion JDKit\n    };\n};\n\nmodule.exports = Entry.JDKit;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_jikko.js",
    "content": "'use strict';\n\nEntry.jikko = {\n    id: '47.1',\n    name: 'jikko',\n    url: 'http://www.makeitall.co.kr',\n    imageName: 'jikko.png',\n    title: {\n        ko: '직코',\n        en: 'jikko',\n    },\n    Static: {\n        BUTTON_PRESS_VALUE: 0,\n    },\n\n    //정지시 초기화 함수\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                if (Entry.hw.sendQueue.SET[key].type == Entry.jikko.sensorTypes.SERVO) {\n                    Entry.hw.sendQueue.SET[key].data = 200;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } \n                else if (Entry.hw.sendQueue.SET[key].type == Entry.jikko.sensorTypes.SERVO2) {\n                    Entry.hw.sendQueue.SET[key].data.value1 = 200;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } \n                else {\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        READ_BLUETOOTH: 9,\n        WRITE_BLUETOOTH: 10,\n        LCD: 11,\n        LCDCLEAR: 12,\n        RGBLED: 13,\n        DCMOTOR: 14,\n        OLED: 15,\n        PIR: 16,\n        LCDINIT: 17,\n        DHTHUMI: 18,\n        DHTTEMP: 19,\n        NEOPIXELINIT: 20,\n        NEOPIXELBRIGHT: 21,\n        NEOPIXEL: 22,\n        NEOPIXELALL: 23,\n        NEOPIXELCLEAR: 24,\n        DOTMATRIXINIT: 25,\n        DOTMATRIXBRIGHT: 26,\n        DOTMATRIX: 27,\n        DOTMATRIXEMOJI: 28,\n        DOTMATRIXCLEAR: 29,\n        MP3INIT: 30,\n        MP3PLAY1: 31,\n        MP3PLAY2: 32,\n        MP3VOL: 33,\n        RESET_: 34,\n        LOADINIT: 35,\n        LOADSCALE: 36,\n        LOADVALUE: 37,\n        DUST: 38,\n        JOYINIT: 39,\n        JOYX: 40,\n        JOYY: 41,\n        JOYZ: 42,\n        JOYMOVE: 43,\n        RFIDINIT: 44,\n        RFIDTAP: 45,\n        RFIDVALUE: 46,\n        STEPINIT: 47,\n        STEPSPEED: 48,\n        STEPROTATE: 49,\n        STEPROTATE2: 50,\n        STEPROTATE3: 51,\n        MLXOBJ: 52,\n        MLXAMB: 53,\n        SERVO2: 54,\n        GYROX: 55,\n        GYROY: 56,\n        GYROZ: 57,\n        PULLUP: 58,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    direction: {\n        CENTER: 0,\n        UP: 1,\n        LEFT: 2,\n        RIGHT: 3,\n        DOWN: 4,\n        LEFT_UP: 5,\n        LEFT_DOWN: 6,\n        RIGHT_UP: 7,\n        RIGHT_DOWN: 8,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\nEntry.jikko.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                jikko_toggle_on: '켜기',\n                jikko_toggle_off: '끄기',\n                jikko_lcd_first_line: '첫 번째',\n                jikko_lcd_seconds_line: '두 번째',\n                jikko_get_analog_value: '아날로그 %1 핀 읽기',\n                jikko_get_light_value: '조도센서(AO %1)값',\n                jikko_get_moisture_value: '토양수분센서(AO %1)값',\n                jikko_get_sound_value: '사운드센서(AO %1)값',\n                jikko_get_infrared_value: '적외선센서(AO %1)값',\n                jikko_get_pullup: '풀업 저항 사용 버튼 %1 핀 눌림 상태',\n                jikko_get_button: '버튼 %1 핀 눌림 상태',\n                jikko_get_analog_mapping:\n                    '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n                jikko_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                jikko_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                jikko_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n                jikko_get_digital: '디지털 %1 핀 읽기',\n                jikko_get_digital_toggle: '디지털 %1 핀 센서 값',\n                jikko_get_digital_pir: 'PIR %1 핀 센서 값',\n                jikko_set_digital_toggle: '디지털 %1 핀 %2 %3',\n                jikko_set_led_toggle: 'LED %1 핀 %2 %3',\n                jikko_set_digital_pwm: 'LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3',\n                jikko_set_digital_rgbled: 'RGB LED (R %1 핀, G %2 핀, B %3 핀) 색 (R: %4, G: %5, B: %6) 출력 %7',\n\n                jikko_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                jikko_set_digital_servo2: \"서보 모터 %1 핀 %2 ~ %3 각도로 %4 초 동안 회전 %5\",\n                jikko_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                jikko_set_digital_buzzer_volume: '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                jikko_set_digital_buzzer: '피에조부저 %1 핀 %2 %3 음 %4 박자 연주 %5',\n\n                jikko_set_digital_dcmotor: 'DC모터 %1핀 %2 %3',\n                jikko_set_analog_dcmotor: 'DC모터(PWM %1 핀) 세기 %2 출력 (0 ~ 255) %3',\n                jikko_set_neopixel_init:\n                    '네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\n                jikko_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\n                jikko_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\n                jikko_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\n                jikko_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\n                jikko_set_dotmatrix_init:\n                    '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                jikko_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                jikko_set_dotmatrix: '도트매트릭스 LED %1 그리기 %2',\n                jikko_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                jikko_set_dotmatrix_clear: '도트매트릭스 LED 지우기 %1',\n\n                jikko_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n                jikko_get_lcd_row: '%1',\n                jikko_get_lcd_col: '%1',\n                jikko_module_digital_lcd: 'LCD화면 %1 열 %2 행 부터 %3 출력 %4',\n                jikko_lcd_clear: 'LCD 화면 지우기 %1',\n                jikko_get_dht: 'DHT11 온습도센서(out %1)의 %2값',\n                //jikko_get_dht_temp_value: 'DHT11 온습도센서(out %1)의 온도(°C)값',\n                //jikko_get_dht_humi_value: 'DHT11 온습도센서(out %1)의 습도(%)값',\n\n                jikko_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\n                jikko_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\n                jikko_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\n                jikko_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\n                jikko_get_analog_temp_value: 'DHT11 포트 %1의 %2 센서 값',\n\n                jikko_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3',\n                jikko_load_scale: 'HX711 로드셀 보정하기 %1 %2',\n                jikko_load_value: 'HX711 로드셀 값',\n\n                jikko_get_dust: '미세먼지센서 (LED %1, AO %2) 값',\n\n                jikko_rfid_init: 'RFID 시작하기 설정 (SS %1, RST %2) %3',\n                jikko_is_rfid_tapped: 'RFID 카드가 인식되었는가?',\n                jikko_get_rfid_value: 'RFID 카드 값',\n                jikko_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5',\n                jikko_get_joy_x: '%1 조이스틱 X값',\n                jikko_get_joy_y: '%1 조이스틱 y값',\n                jikko_get_joy_z: '%1 조이스틱 버튼 눌림 상태',\n                jikko_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때',\n\n                jikko_get_mlx: 'mlx90614 비접촉 온도센서 %1값',\n\n                jikko_step_init: '%1 스텝모터 시작하기 설정 (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6',\n                jikko_step_speed: '%1 스텝모터 속도를 %2 로 설정하기 (0 ~ 20) %3',\n                jikko_step_rotate: '%1 스텝모터 %2 으로 %3 바퀴 회전하기 %4',\n                jikko_step_rotate2: '%1 스텝모터 %2 으로 %3 도 회전하기 %4',\n                jikko_step_rotate3: '%1 스텝모터 %2 으로 %3 초 동안 회전하기 %4',\n\n                // jikko_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\n                // jikko_module_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n\n            },\n        },\n        en: {\n            template: {\n                jikko_toggle_on: 'on',\n                jikko_toggle_off: 'off',\n                jikko_lcd_first_line: 'first',\n                jikko_lcd_seconds_line: 'seconds',\n                jikko_get_analog_value: 'Read analog %1 pin sensor value',\n                jikko_get_analog_mapping: 'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\n                jikko_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                jikko_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                jikko_get_digital_bluetooth: 'Bluetooth RX 2 value',\n                jikko_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n                jikko_get_digital: 'Digital %1 pin sensor value',\n                jikko_get_digital_toggle: 'Digital %1 pin sensor value',\n                jikko_set_digital_toggle: 'Digital %1 pin %2 %3',\n                jikko_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n                jikko_set_digital_rgbled: 'Digital %1 pin RGB LED Red %2 Green %3 Blue %4 %5',\n                jikko_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                jikko_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                jikko_set_digital_buzzer_volume: '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                jikko_set_digital_buzzer:\n                    '피에조부저 %1 번 핀의 버저를 %2 %3 음으로 %4 박자 연주 %5',\n                jikko_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5',\n                jikko_set_neopixel_init:\n                    '네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\n                jikko_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\n                jikko_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\n                jikko_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\n                jikko_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\n                jikko_set_dotmatrix_init:\n                    '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                jikko_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                jikko_set_dotmatrix: '도트매트릭스 LED 그리기 %1 %2',\n                jikko_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                jikko_module_digital_lcd: 'LCD %1 열 %2 행 부터 %3 출력',\n                jikko_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n\n                jikko_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\n                jikko_module_digital_oled: 'OLED X codinate %1 Y coodinate %2 appear %3 %4',\n                jikko_get_dht_temp_value: '온습도센서의 온도값',\n                jikko_get_dht_humi_value: '온습도센서의 습도값',\n\n                jikko_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\n                jikko_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\n                jikko_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\n                jikko_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\n\n                jikko_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3',\n                jikko_load_scale: 'HX711 로드셀 보정하기 %1 %2',\n                jikko_load_value: 'HX711 로드셀 값',\n\n                jikko_get_dust: '미세먼지센서(LED %1, AO %2) 값(μg/m³)',\n\n                jikko_rfid_init: 'RFID 시작하기 설정 (RST %1, SS %2) %3',\n                jikko_is_rfid_tapped: 'RFID 카드가 인식되었는가?',\n                jikko_get_rfid_value: 'RFID 카드 값',\n\n                jikko_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5',\n                jikko_get_joy_x: '%1 조이스틱 X값',\n                jikko_get_joy_y: '%1 조이스틱 y값',\n                jikko_get_joy_z: '%1 조이스틱 버튼 눌림 상태',\n                jikko_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때',\n\n                jikko_step_init: '%1 스텝모터 시작하기 설정 (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6',\n                jikko_step_speed: '%1 스텝모터 속도를 %2 로 설정하기 (0 ~ 20) %3',\n                jikko_step_rotate: '%1 스텝모터 %2 으로 %3 바퀴 회전하기 %4',\n                jikko_step_rotate2: '%1 스텝모터 %2 으로 %3 도 회전하기 %4',\n                jikko_step_rotate3: '%1 스텝모터 %2 으로 %3 초 동안 회전하기 %4',\n\n                jikko_mlx: 'mlx90614 값',\n            },\n        },\n    };\n};\nEntry.jikko.blockMenuBlocks = [\n    'jikko_set_digital_toggle',\n    'jikko_get_analog_value',\n    'jikko_get_digital',\n    'jikko_get_analog_mapping',\n    'jikko_mapping1',\n    'jikko_mapping2',\n\n    'jikko_set_led_toggle',\n    'jikko_set_digital_pwm',\n    'jikko_set_digital_rgbled',\n\n    'jikko_get_digital_ultrasonic',\n    'jikko_get_dust',\n    'jikko_get_digital_toggle',\n    'jikko_get_digital_pir',\n    'jikko_get_light_value',\n    'jikko_get_moisture_value',\n    'jikko_get_sound_value',\n    'jikko_get_infrared_value',\n    'jikko_get_dht',\n    //'jikko_get_dht_temp_value',\n    //'jikko_get_dht_humi_value',\n    'jikko_get_pullup',\n    'jikko_get_button',\n\n    'jikko_set_digital_dcmotor',\n    'jikko_set_analog_dcmotor',\n    'jikko_set_digital_servo',\n    'jikko_set_digital_servo2',\n    'jikko_set_digital_buzzer_toggle',\n    'jikko_set_digital_buzzer_volume',\n    'jikko_set_digital_buzzer',\n    'jikko_set_neopixel_init',\n    'jikko_set_neopixel_bright',\n    'jikko_set_neopixel',\n    'jikko_set_neopixel_all',\n    'jikko_set_neopixel_clear',\n    'jikko_set_dotmatrix_init',\n    'jikko_set_dotmatrix_bright',\n    'jikko_set_dotmatrix',\n    'jikko_set_dotmatrix_emoji',\n    'jikko_set_dotmatrix_clear',\n    'jikko_lcd_init',\n    'jikko_module_digital_lcd',\n    'jikko_get_lcd_row',\n    'jikko_get_lcd_col',\n    'jikko_lcd_clear',\n    'jikko_set_mp3_init',\n    'jikko_set_mp3_vol',\n    'jikko_set_mp3_play',\n    'jikko_set_mp3_play2',\n    'jikko_load_init',\n    'jikko_load_scale',\n    'jikko_load_value',\n    'jikko_rfid_init',\n    'jikko_is_rfid_tapped',\n    'jikko_get_rfid_value',\n    'jikko_joy_init',\n    'jikko_get_joy_x',\n    'jikko_get_joy_y',\n    'jikko_get_joy_z',\n    'jikko_get_joy_move',\n\n    'jikko_get_mlx',\n\n    'jikko_step_init',\n    'jikko_step_speed',\n    'jikko_step_rotate',\n    'jikko_step_rotate2',\n    'jikko_step_rotate3',\n\n\n    // 'jikko_get_digital_bluetooth',\n    // 'jikko_module_digital_bluetooth',\n];\nEntry.jikko.getBlocks = function() {\n    var tx;\n    var din;\n    // var clk;\n    // var cs;\n    var dout;\n    var sck;\n    var joyx, joyy, joyz;\n    var joyx2, joyy2, joyz2;\n    var portpin1, portpin2, portpin3;\n    var ss;\n    var RGBport;\n    var mlxport;\n    var speed1 = 14;\n    var speed2 = 14;\n    var speed3 = 14;\n    var num = 0;\n\n    return {\n        jikko_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        jikko_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        jikko_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jikko_toggle_on, 'on'],\n                        [Lang.template.jikko_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        jikko_list_digital_toggle_en: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['HIGH', 'on'],\n                        ['LOW', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        jikko_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        jikko_set_neopixel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_neopixel_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'neo',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('NUM');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.NEOPIXELINIT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_set_neopixel_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_neopixel_bright',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'neo',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('NUM');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.NEOPIXELBRIGHT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_set_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'jikko_set_neopixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n                COLOR: 2,\n            },\n            class: 'neo',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                //var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var num = script.getNumberValue('NUM', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.NEOPIXEL,\n                        data: {\n                            num: num,\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_set_neopixel_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'jikko_set_neopixel_all',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COLOR: 1,\n            },\n            class: 'neo',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.NEOPIXELALL,\n                        data: {\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_set_neopixel_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_neopixel_clear',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neo',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.NEOPIXELCLEAR,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_lcd_list_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x27', '0'],\n                        ['0x3F', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_set_dotmatrix_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['12'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_dotmatrix_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n            },\n            class: 'dot',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                din = port1;\n                // clk = port2;\n                // cs = port3;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port1] = {\n                        type: Entry.jikko.sensorTypes.DOTMATRIXINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                            port3: port3,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_set_dotmatrix_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_dotmatrix_bright',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                num = Math.round(num);\n                num = Math.min(num, 8);\n                num = Math.max(num, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko.sensorTypes.DOTMATRIXBRIGHT,\n                        data: num,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_set_dotmatrix_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_set_dotmatrix_clear',\n            },\n            class: 'dot',\n            isNotFor: ['jikko'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (1 + 0.5) * 0.1; //0.15\n                    timeValue = (60 / fps) * timeValue * 100;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko.sensorTypes.DOTMATRIXCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_set_dotmatrix: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['003c420024242400'],\n                    },\n                ],\n                type: 'jikko_set_dotmatrix',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var text = script.getValue('STRING');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko.sensorTypes.DOTMATRIX,\n                        data: {\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_dotmatrix_emoji_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['🖤', '1'],\n                        ['🤍', '2'],\n                        ['👆', '3'],\n                        ['👇', '4'],\n                        ['👈', '5'],\n                        ['👉', '6'],\n                        ['😊', '7'],\n                        ['😥', '8'],\n                        ['😡', '9'],\n                        ['😆', '10'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_set_dotmatrix_emoji: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_dotmatrix_emoji_list',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_dotmatrix_emoji',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('LIST');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko.sensorTypes.DOTMATRIXEMOJI,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jikko_lcd_first_line, '0'],\n                        [Lang.template.jikko_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_get_lcd_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'jikko_get_lcd_row',\n                    },\n                ],\n            },\n        },\n\n        jikko_get_lcd_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'jikko_get_lcd_col',\n                    },\n                ],\n            },\n        },\n        jikko_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_analog_basic',\n                    },\n                ],\n                type: 'jikko_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoPin',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko.get_analog_value(%1)'] },\n        },\n        jikko_get_light_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_analog_basic',\n                    },\n                ],\n                type: 'jikko_get_light_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko.get_analog_value(%1)'] },\n        },\n        jikko_get_moisture_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //template: Lang.template.jikko_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_analog_basic',\n                        params: ['1'],\n                    },\n                ],\n                type: 'jikko_get_moisture_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko.get_analog_value(%1)'] },\n        },\n\n        jikko_set_digital_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_set_digital_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                    },\n                    {\n                        type: 'jikko_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'jikko_set_digital_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikkoSet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        jikko_set_analog_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_set_analog_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_pwm',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_analog_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikkoSet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        jikko_get_sound_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_analog_basic',\n                    },\n                ],\n                type: 'jikko_get_sound_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko.get_analog_value(%1)'] },\n        },\n        jikko_get_infrared_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_analog_basic',\n                    },\n                ],\n                type: 'jikko_get_infrared_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko.get_analog_value(%1)'] },\n        },\n        jikko_get_pullup: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_get_pullup',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var pu = Entry.hw.portData.PULLUP;\n                \n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.PULLUP] = {\n                    port: port,\n                    data: 2,\n                    time: new Date().getTime(),\n                };\n                var pullupvalue = pu ? pu[port] || 0 : 0;\n                return !pullupvalue;\n                \n            },\n            \n            syntax: { js: [], py: [] },\n        },\n        jikko_get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_get_button',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.DIGITAL] = {\n                    port: port,\n                    data: 2,\n                    time: new Date().getTime(),\n                };\n\n                var value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                return !value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jikko_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_analog_basic',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'jikko_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'jikkoPin',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                result = ANALOG ? ANALOG[port] || 0 : 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['jikko.get_analog_mapping(%1, %2, %3, %4, %5)'],\n            },\n        },\n        jikko_mapping1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                ],\n                type: 'jikko_mapping1',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'jikkoPin',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                num = Math.min(value3, num);\n                num = Math.max(value2, num);\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        jikko_mapping2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1024'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'jikko_mapping2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'jikkoPin',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var flag = 0;\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var value4_1 = value4;\n                var value5_1 = value5;\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                if (value4 > value5) {\n                    flag = 1;\n                    var swap = value4;\n                    value4_1 = value5;\n                    value5_1 = swap;\n                }\n\n                num -= value2;\n                num = num * ((value5_1 - value4_1) / (value3 - value2));\n\n                if (flag == 1) {\n                    num = value4 - num;\n                    num = Math.min(value4, num);\n                    num = Math.max(value5, num);\n                } else {\n                    num = num + value4;\n                    num = Math.min(value5, num);\n                    num = Math.max(value4, num);\n                }\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        jikko_get_digital_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_get_digital_ultrasonic,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                        params: ['13'],\n                    },\n                    {\n                        type: 'jikko_list_digital_basic',\n                        params: ['12'],\n                    },\n                ],\n                type: 'jikko_get_digital_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                Entry.Utils.sleep(700);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC[port2] || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['jikko.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n        jikko_get_dust: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'jikko_list_analog_basic',\n                        params: ['0'],\n                    },\n                ],\n                type: 'jikko_get_dust',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.DUST] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.DUST || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['jikko.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n        jikko_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.jikko_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoPin',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko.get_digital(%1)'] },\n        },\n        jikko_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.jikko_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko.get_digital_toggle(%1)'] },\n        },\n        jikko_get_digital_pir: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: Lang.template.jikko_get_digital_pir,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_get_digital_pir',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.PIR] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko.get_digital_pir(%1)'] },\n        },\n        jikko_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                    },\n                    {\n                        type: 'jikko_list_digital_toggle_en',\n                    },\n                    null,\n                ],\n                type: 'jikko_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikkoPin',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko.set_digital_toggle(%1, %2)'] },\n        },\n        jikko_set_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'jikko_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'jikko_set_led_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikkoLed',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko.set_digital_toggle(%1, %2)'] },\n        },\n        jikko_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_pwm',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikkoLed',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko.set_digital_pwm(%1, %2)'] },\n        },\n        jikko_set_digital_rgbled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_set_digital_rgbled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_pwm',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'jikko_list_digital_pwm',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'jikko_list_digital_pwm',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_digital_rgbled',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n                VALUE1: 3,\n                VALUE2: 4,\n                VALUE3: 5,\n            },\n            class: 'jikkoLed',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                RGBport = port1;\n\n                // if (!Entry.hw.sendQueue['SET']) {\n                //     Entry.hw.sendQueue['SET'] = {};\n                // }\n                // Entry.hw.sendQueue['SET'][RGBport] = {\n                //     type: Entry.jikko.sensorTypes.RGBLED,\n                //     data: {\n                //         port1: port1,\n                //         port2: port2,\n                //         port3: port3,\n                //         value1: value1,\n                //         value2: value2,\n                //         value3: value3,\n                //     },\n                //     time: new Date().getTime(),\n                // };\n                // return script.callReturn();\n                \n\n                // if (!script.isStart) {\n                //     script.isStart = true;\n                //     script.timeFlag = 1;\n                //     var fps = Entry.FPS || 60;\n                //     var timeValue = (60 / fps) * 50;\n\n                //     value1 = Math.round(value1);\n                //     value1 = Math.min(value1, 255);\n                //     value1 = Math.max(value1, 0);\n                //     value2 = Math.round(value2);\n                //     value2 = Math.min(value2, 255);\n                //     value2 = Math.max(value2, 0);\n                //     value3 = Math.round(value3);\n                //     value3 = Math.min(value3, 255);\n                //     value3 = Math.max(value3, 0);\n\n                //     if (!Entry.hw.sendQueue['SET']) {\n                //         Entry.hw.sendQueue['SET'] = {};\n                //     }\n                //     Entry.hw.sendQueue['SET'][RGBport] = {\n                //         type: Entry.jikko.sensorTypes.RGBLED,\n                //         data: {\n                //             port1: port1,\n                //             port2: port2,\n                //             port3: port3,\n                //             value1: value1,\n                //             value2: value2,\n                //             value3: value3,\n                //         },\n                //         time: new Date().getTime(),\n                //     };\n                //     setTimeout(function() {\n                //         script.timeFlag = 0;\n                //     }, 10);\n                //     return script;\n                // } else if (script.timeFlag == 1) {\n                //     return script;\n                // } else {\n                //     delete script.timeFlag;\n                //     delete script.isStart;\n                //     Entry.engine.isContinue = false;\n                //     return script.callReturn();\n                // }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type: Entry.jikko.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type: Entry.jikko.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port3] = {\n                    type: Entry.jikko.sensorTypes.PWM,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n                 return script.callReturn();\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        jikko_set_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_set_digital_servo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikkoSet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko.set_digital_servo(%1, %2)'] },\n        },\n        jikko_set_digital_servo2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_set_digital_servo2,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['180'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_digital_servo2',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n                STIME: 3,\n            },\n            class: 'jikkoSet',\n            isNotFor: ['jikko'],\n            // func: function(sprite, script) {\n            //     var port = script.getNumberValue('PORT');\n            //     var value1 = script.getNumber    Value('VALUE1', script);\n            //     var value2 = script.getNumberValue('VALUE2', script);\n            //     var stime = script.getNumberValue('STIME', script);\n\n            //     value1 = Math.min(value1, 180);\n            //     value1 = Math.max(value1, 0);\n            //     value2 = Math.min(value2, 180);\n            //     value2 = Math.max(value2, 0);\n\n            //     if (!Entry.hw.sendQueue['SET']) {\n            //         Entry.hw.sendQueue['SET'] = {};\n            //     }\n                \n            //     Entry.hw.sendQueue['SET'][port] = {\n            //         type: Entry.jikko.sensorTypes.SERVO2,\n            //         data: {\n            //             value1: value1,\n            //             value2: value2,\n            //             stime: stime,\n            //         },\n            //         time: new Date().getTime(),\n            //     };\n            //     return script.callReturn();\n            // },\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var stime = script.getNumberValue('STIME', script);\n\n                value1 = Math.min(value1, 180);\n                value1 = Math.max(value1, 0);\n                value2 = Math.min(value2, 180);\n                value2 = Math.max(value2, 0);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.SERVO2,\n                        data: {\n                            value1: value1,\n                            value2: value2,\n                            stime: stime,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        jikko_set_digital_buzzer_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'jikko_list_digital_toggle',\n                    },\n\n                    null,\n                ],\n                type: 'jikko_set_digital_buzzer_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikkoBuzzer',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['jikko.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_set_digital_buzzer_volume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_pwm',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_digital_buzzer_volume',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikkoBuzzer',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['jikko.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_digital_basic',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'jikko_list_digital_tone',\n                    },\n                    {\n                        type: 'jikko_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'jikkoBuzzer',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.jikko.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.jikko.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.jikko.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['jikko.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lcd_list_init',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lcd_init',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n                COL: 1,\n                LINE: 2,\n            },\n            class: 'jikkoModule',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var list = script.getNumberValue('LIST');\n                var col = script.getNumberValue('COL');\n                var line = script.getValue('LINE');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 0.1 * 1000;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko.sensorTypes.LCDINIT,\n                        data: {\n                            list: list,\n                            col: col,\n                            line: line,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko.module_digital_lcd(%1, %2)'] },\n        },\n        jikko_module_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_get_lcd_col',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'jikko_get_lcd_row',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Hello, Jikko'],\n                    },\n                    null,\n                ],\n                type: 'jikko_module_digital_lcd',\n            },\n            paramsKeyMap: {\n                COL: 0,\n                ROW: 1,\n                STRING: 2,\n            },\n            class: 'jikkoModule',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var row = script.getNumberValue('ROW');\n                var col = script.getNumberValue('COL');\n                var text = script.getValue('STRING');\n                text += ' ';\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko.sensorTypes.LCD,\n                        data: {\n                            line: row,\n                            column: col,\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko.module_digital_lcd(%1, %2)'] },\n        },\n        jikko_lcd_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_lcd_clear',\n            },\n            class: 'jikkoModule',\n            isNotFor: ['jikko'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko.sensorTypes.LCDCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_get_dht: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['온도(°C)', '0'],\n                        ['습도(%)', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n\n                ],\n                type: 'jikko_get_dht',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DHT_SELECT: 1,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var type = script.getNumberValue('DHT_SELECT');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (type == 0) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.DHTTEMP] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTTEMP || 0;\n                } else if (type == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.DHTHUMI] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTHUMI || 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_set_mp3_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_mp3_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'mp3',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                tx = script.getNumberValue('PORT1');\n                var rx = script.getNumberValue('PORT2');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.jikko.sensorTypes.MP3INIT,\n                        data: {\n                            tx: tx,\n                            rx: rx,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_set_mp3_play: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_mp3_play',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'mp3',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                script.isStart = true;\n                script.timeFlag = 1;\n                var fps = Entry.FPS || 60;\n                var timeValue = (60 / fps) * 50;\n\n                Entry.hw.sendQueue['SET'][tx] = {\n                    type: Entry.jikko.sensorTypes.MP3PLAY1,\n                    data: {\n                        tx: tx,\n                        num: num,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_set_mp3_play2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_mp3_play2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                TIME: 1,\n            },\n            class: 'mp3',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM');\n                var time_value = script.getNumberValue('TIME');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    time_value = (60 / fps) * time_value * 1000;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.jikko.sensorTypes.MP3PLAY1,\n                        data: {\n                            tx: tx,\n                            num: num,\n                            //time_value: time_value,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, time_value);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.jikko.sensorTypes.MP3PLAY1,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_set_mp3_vol: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['15'],\n                    },\n                    null,\n                ],\n                type: 'jikko_set_mp3_vol',\n            },\n            paramsKeyMap: {\n                VOL: 0,\n            },\n            class: 'mp3',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var vol = script.getNumberValue('VOL');\n\n                vol = Math.round(vol);\n                vol = Math.min(vol, 30);\n                vol = Math.max(vol, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.jikko.sensorTypes.MP3VOL,\n                        data: {\n                            tx: tx,\n                            vol: vol,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_load_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'jikko_load_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'load',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                dout = port1;\n                sck = port2;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][sck] = {\n                        type: Entry.jikko.sensorTypes.LOADINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_load_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['-20000'],\n                    },\n                    null,\n                ],\n                type: 'jikko_load_scale',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'load',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][sck] = {\n                        type: Entry.jikko.sensorTypes.LOADSCALE,\n                        data: {\n                            num: num,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_load_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'jikko_load_value',\n            },\n            paramsKeyMap: {},\n            class: 'load',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][sck];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.LOADVALUE] = {\n                    port: sck,\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.LOADVALUE || 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_list_joy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['첫번째', '1'],\n                        ['두번째', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NUM');\n            },\n        },\n        jikko_joy_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_joy',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'jikko_list_analog_basic',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'jikko_list_analog_basic',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'jikko_joy_init',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                PORT1: 1,\n                PORT2: 2,\n                PORT3: 3,\n            },\n            class: 'joy',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                if (num == 1) {\n                    joyx = port1;\n                    joyy = port2;\n                    joyz = port3;\n                } else if (num == 2) {\n                    joyx2 = port1;\n                    joyy2 = port2;\n                    joyz2 = port3;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][joyx] = {\n                            type: Entry.jikko.sensorTypes.JOYINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][joyx2] = {\n                            type: Entry.jikko.sensorTypes.JOYINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_get_joy_x: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'jikko_get_joy_x',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joy',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var num = script.getNumberValue('NUM', script);\n                if (num == 1) {\n                    return ANALOG ? ANALOG[joyx] || 0 : 0;\n                } else if (num == 2) {\n                    return ANALOG ? ANALOG[joyx2] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_get_joy_y: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'jikko_get_joy_y',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joy',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var num = script.getNumberValue('NUM', script);\n                if (num == 1) {\n                    return ANALOG ? ANALOG[joyy] || 0 : 0;\n                } else if (num == 2) {\n                    return ANALOG ? ANALOG[joyy2] || 0 : 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_get_joy_z: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_joy',\n                        params: ['1'],\n                    },\n                ],\n                type: 'jikko_get_joy_z',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'joy',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                var num = script.getNumberValue('NUM', script);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (num == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.DIGITAL] = {\n                        port: joyz,\n                        data: 2,\n                        time: new Date().getTime(),\n                    };\n\n                    var value = DIGITAL ? DIGITAL[joyz] || 0 : 0;\n                    return !value;\n                } else if (num == 2) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.DIGITAL] = {\n                        port: joyz2,\n                        data: 2,\n                        time: new Date().getTime(),\n                    };\n\n                    var value = DIGITAL ? DIGITAL[joyz2] || 0 : 0;\n                    return !value;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        jikko_list_joy_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가운데', '0'],\n                        ['위', '1'],\n                        ['아래', '4'],\n                        ['왼쪽', '2'],\n                        ['오른쪽', '3'],\n                        ['왼쪽위', '5'],\n                        ['왼쪽아래', '6'],\n                        ['오른쪽위', '7'],\n                        ['오른쪽아래', '8'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIR');\n            },\n        },\n        jikko_get_joy_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_joy',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'jikko_list_joy_direction',\n                        params: ['0'],\n                    },\n                ],\n                type: 'jikko_get_joy_move',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n            },\n            class: 'joy',\n            isNotFor: ['jikko'],\n            func(sprite, script) {\n                var direction = script.getNumberValue('DIR');\n                const ANALOG = Entry.hw.portData.ANALOG;\n                num = script.getNumberValue('NUM', script);\n\n                const getValue = function(w) {\n                    return ANALOG[w] <= 100 ? 0 : ANALOG[w] >= 930 ? 2 : 1;\n                };\n\n                var xpin;\n                var ypin;\n                if (num == 1) {\n                    xpin = joyx;\n                    ypin = joyy;\n                } else if (num == 2) {\n                    xpin = joyx2;\n                    ypin = joyy2;\n                }\n                if (\n                    direction == Entry.jikko.direction.CENTER &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.jikko.direction.DOWN &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.jikko.direction.LEFT &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.jikko.direction.LEFT_DOWN &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.jikko.direction.LEFT_UP &&\n                    getValue(xpin) == 0 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.jikko.direction.RIGHT &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.jikko.direction.RIGHT_DOWN &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.jikko.direction.RIGHT_UP &&\n                    getValue(xpin) == 2 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.jikko.direction.UP &&\n                    getValue(xpin) == 1 &&\n                    getValue(ypin) == 0\n                ) {\n                    return 1;\n                }\n\n                return 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_list_step: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['첫번째', '1'],\n                        ['두번째', '2'],\n                        ['세번째', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NUM');\n            },\n        },\n        jikko_step_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'jikko_step_init',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                PORT1: 1,\n                PORT2: 2,\n                PORT3: 3,\n                PORT4: 4,\n            },\n            class: 'step',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n                var port4 = script.getNumberValue('PORT4', script);\n\n                if (num == 1) {\n                    portpin1 = port1;\n                } else if (num == 2) {\n                    portpin2 = port1;\n                } else if (num == 3) {\n                    portpin3 = port1;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        console.log('STEP INIT 1st');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.jikko.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        console.log('STEP INIT 2nd');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.jikko.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        console.log('STEP INIT 3rd');\n                        console.log(num);\n                        console.log(port1);\n                        console.log(port2);\n                        console.log(port3);\n                        console.log(port4);\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.jikko.sensorTypes.STEPINIT,\n                            data: {\n                                num: num,\n                                port1: port1,\n                                port2: port2,\n                                port3: port3,\n                                port4: port4,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_step_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['14'],\n                    },\n                    null,\n                ],\n                type: 'jikko_step_speed',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                SPEED: 1,\n            },\n            class: 'step',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var sp = script.getNumberValue('SPEED', script);\n\n                sp = Math.round(sp);\n                sp = Math.min(sp, 20);\n                sp = Math.max(sp, 0);\n\n                if (num == 1) {\n                    speed1 = sp;\n                } else if (num == 2) {\n                    speed2 = sp;\n                } else if (num == 3) {\n                    speed3 = sp;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.jikko.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed1,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.jikko.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed2,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.jikko.sensorTypes.STEPSPEED,\n                            data: {\n                                num: num,\n                                speed: speed3,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_list_step_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['정방향', '1'],\n                        ['역방향', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIR');\n            },\n        },\n        jikko_step_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'jikko_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_step_rotate',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                VALUE: 2,\n            },\n            class: 'step',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var dir = script.getNumberValue('DIR', script);\n                num = script.getNumberValue('NUM', script);\n                var val = script.getNumberValue('VALUE', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timeValue;\n\n                    if (num == 1) {\n                        timeValue = (60 / speed1) * val * 1000 + 32;\n                        console.log(timeValue);\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        timeValue = (60 / speed2) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        timeValue = (60 / speed3) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: val * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_step_rotate2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'jikko_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'jikko_step_rotate2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                VALUE: 2,\n            },\n            class: 'step',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var dir = script.getNumberValue('DIR', script);\n                num = script.getNumberValue('NUM', script);\n                var val = script.getNumberValue('VALUE', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    var timeValue;\n\n                    if (num == 1) {\n                        timeValue = (60 / (speed1 * 360)) * val * 1000 + 32;\n                        console.log(timeValue);\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        timeValue = (60 / (speed2 * 360)) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        timeValue = (60 / (speed3 * 360)) * val * 1000 + 32;\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE2,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                val: (val / 360) * 2048,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE2,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_step_rotate3: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_list_step',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'jikko_list_step_direction',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'jikko_step_rotate3',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                SEC: 2,\n            },\n            class: 'step',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                num = script.getNumberValue('NUM');\n                var dir = script.getNumberValue('DIR');\n                var sec = script.getNumberValue('SEC');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE3,\n                            data: {\n                                num: num,\n                                dir: dir,\n                                sec: sec,\n                            },\n                            time: new Date().getTime(),\n                        };\n                    }\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, sec * 1000 + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    if (num == 1) {\n                        Entry.hw.sendQueue['SET'][portpin1] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 2) {\n                        Entry.hw.sendQueue['SET'][portpin2] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    } else if (num == 3) {\n                        Entry.hw.sendQueue['SET'][portpin3] = {\n                            type: Entry.jikko.sensorTypes.STEPROTATE3,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                    }\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_module_digital_oled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_module_digital_oled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['My Entry!!'],\n                    },\n                    null,\n                ],\n                type: 'jikko_module_digital_oled',\n            },\n            paramsKeyMap: {\n                VALUE0: 0,\n                VALUE1: 1,\n                STRING: 2,\n            },\n            class: 'jikkoModule',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port = 0;\n                var coodinate_x = script.getNumberValue('VALUE0');\n                var coodinate_y = script.getNumberValue('VALUE1');\n                var string = script.getValue('STRING');\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = string.charCodeAt(i);\n                        }\n                    } else if (typeof string === 'number') {\n                        text[0] = 1;\n                        text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    coodinate_x = Math.min(coodinate_x, 127);\n                    coodinate_x = Math.max(coodinate_x, 0);\n                    coodinate_y = Math.min(coodinate_y, 63);\n                    coodinate_y = Math.max(coodinate_y, 0);\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko.sensorTypes.OLED,\n                        data: {\n                            value0: coodinate_x,\n                            value1: coodinate_y,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko.Module_digital_oled(%1, %2, %3)'] },\n        },\n\n        jikko_rfid_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    null,\n                ],\n                type: 'jikko_rfid_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'rfid',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                ss = port1;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][ss] = {\n                        type: Entry.jikko.sensorTypes.RFIDINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_is_rfid_tapped: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_is_rfid_tapped',\n            },\n            paramsKeyMap: {},\n            class: 'rfid',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.RFIDTAP] = {\n                    port: ss,\n                    time: new Date().getTime(),\n                };\n\n                var value = Entry.hw.portData.RFIDTAP || 0;\n                return value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jikko_get_rfid_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'jikko_get_rfid_value',\n            },\n            paramsKeyMap: {},\n            class: 'rfid',\n            isNotFor: ['jikko'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][ss];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.RFIDVALUE] = {\n                    port: ss,\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.RFIDVALUE || 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_get_mlx: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['목표물', '0'],\n                        ['주변', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_get_mlx',\n            },\n            paramsKeyMap: {\n                MLX_SELECT: 0,\n            },\n            class: 'jikkoGet',\n            isNotFor: ['jikko'],\n            \n            func: function(sprite, script) {\n                var type = script.getNumberValue('MLX_SELECT')\n\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (type == 0) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.MLXOBJ] = {\n                        port: 0,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.MLXOBJ || 0;\n                } else if (type == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko.sensorTypes.MLXAMB] = {\n                        port: 0,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.MLXAMB || 0;\n                }                    \n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.jikko;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_jikko_basic.js",
    "content": "'use strict';\n\nEntry.jikko_basic = {\n    id: '47.4',\n    name: 'jikko_basic',\n    url: 'http://www.makeitall.co.kr',\n    imageName: 'jikko_basic.png',\n    title: {\n        ko: '직코베이직',\n        en: 'jikko_basic',\n    },\n    Static: {\n        BUTTON_PRESS_VALUE: 0,\n    },\n\n    //정지시 초기화 함수\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                if (Entry.hw.sendQueue.SET[key].type == Entry.jikko_basic.sensorTypes.SERVO) {\n                    Entry.hw.sendQueue.SET[key].data = 200;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else if (\n                    Entry.hw.sendQueue.SET[key].type == Entry.jikko_basic.sensorTypes.SERVO2\n                ) {\n                    Entry.hw.sendQueue.SET[key].data.value1 = 200;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else {\n                    Entry.hw.sendQueue.SET[key].data = 0;\n                    Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                }\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        PULLUP: 4,\n        SERVO: 5,\n        SERVO2: 6,\n        TONE: 7,\n        ULTRASONIC: 8,\n        READ_BLUETOOTH: 9,\n        WRITE_BLUETOOTH: 10,\n        LCDINIT: 11,\n        LCD: 12,\n        LCDCLEAR: 13,\n        DCMOTOR: 14,\n        DHTHUMI: 15,\n        DHTTEMP: 16,\n        NEOPIXELINIT: 17,\n        NEOPIXELBRIGHT: 18,\n        NEOPIXEL: 19,\n        NEOPIXELALL: 20,\n        NEOPIXELCLEAR: 21,\n        DOTMATRIXINIT: 22,\n        DOTMATRIXBRIGHT: 23,\n        DOTMATRIX: 24,\n        DOTMATRIXEMOJI: 25,\n        DOTMATRIXCLEAR: 26,\n        MP3INIT: 27,\n        MP3PLAY1: 28,\n        MP3PLAY2: 29,\n        MP3VOL: 30,\n        TIMER: 31,\n        RESET_: 32,\n        PULSEIN: 33,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\nEntry.jikko_basic.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                jikko_basic_toggle_on: '켜기',\n                jikko_basic_toggle_off: '끄기',\n                jikko_basic_lcd_first_line: '첫 번째',\n                jikko_basic_lcd_seconds_line: '두 번째',\n                jikko_basic_get_analog_value: '아날로그 %1 핀 읽기',\n                jikko_basic_get_light_value: '조도센서(AO %1)값',\n                jikko_basic_get_moisture_value: '토양수분센서(AO %1)값',\n                jikko_basic_get_pullup: '풀업 저항 사용 버튼 %1 핀 눌림 상태',\n                jikko_basic_get_button: '버튼 %1 핀 눌림 상태',\n                jikko_basic_get_analog_mapping:\n                    '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n                jikko_basic_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                jikko_basic_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                jikko_basic_get_digital_ultrasonic: '초음파 Trig %1 핀 Echo %2 핀 센서 값',\n                jikko_basic_get_digital: '디지털 %1 핀 읽기',\n                jikko_basic_get_digital_toggle: '디지털 %1 핀 센서 값',\n                jikko_basic_set_digital_toggle: '디지털 %1 핀 %2 %3',\n                jikko_basic_set_led_toggle: 'LED %1 핀 %2 %3',\n                jikko_basic_set_digital_pwm: 'LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3',\n\n                jikko_basic_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                jikko_basic_set_digital_servo2: '서보 모터 %1 핀 %2 ~ %3 각도로 %4 초 동안 회전 %5',\n                jikko_basic_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                jikko_basic_set_digital_buzzer_volume:\n                    '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                jikko_basic_set_digital_buzzer: '피에조부저 %1 핀 %2 %3 음 %4 박자 연주 %5',\n\n                jikko_basic_set_digital_dcmotor: 'DC모터 %1핀 %2 %3',\n                jikko_basic_set_analog_dcmotor: 'DC모터(PWM %1 핀) 세기 %2 출력 (0 ~ 255) %3',\n                jikko_basic_set_neopixel_init:\n                    '네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\n                jikko_basic_set_neopixel_bright:\n                    '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\n                jikko_basic_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\n                jikko_basic_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\n                jikko_basic_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\n                jikko_basic_set_dotmatrix_init:\n                    '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                jikko_basic_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                jikko_basic_set_dotmatrix: '도트매트릭스 LED %1 그리기 %2',\n                jikko_basic_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                jikko_basic_set_dotmatrix_clear: '도트매트릭스 LED 지우기 %1',\n\n                jikko_basic_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n                jikko_basic_get_lcd_row: '%1',\n                jikko_basic_get_lcd_col: '%1',\n                jikko_basic_module_digital_lcd: 'LCD화면 %1 열 %2 행 부터 %3 출력 %4',\n                jikko_basic_lcd_clear: 'LCD 화면 지우기 %1',\n                jikko_basic_get_dht: 'DHT11 온습도센서(out %1)의 %2값',\n\n                jikko_basic_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\n                jikko_basic_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\n                jikko_basic_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\n                jikko_basic_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\n                // jikko_basic_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값',\n                // jikko_basic_module_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2',\n            },\n        },\n        en: {\n            template: {\n                jikko_basic_toggle_on: 'on',\n                jikko_basic_toggle_off: 'off',\n                jikko_basic_lcd_first_line: 'first',\n                jikko_basic_lcd_seconds_line: 'seconds',\n                jikko_basic_get_analog_value: 'Read analog %1 pin sensor value',\n                jikko_basic_get_analog_mapping:\n                    'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\n                jikko_basic_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                jikko_basic_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                jikko_basic_get_digital_bluetooth: 'Bluetooth RX 2 value',\n                jikko_basic_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n                jikko_basic_get_digital: 'Digital %1 pin sensor value',\n                jikko_basic_get_digital_toggle: 'Digital %1 pin sensor value',\n                jikko_basic_set_digital_toggle: 'Digital %1 pin %2 %3',\n                jikko_basic_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n                jikko_basic_set_digital_rgbled: 'Digital %1 pin RGB LED Red %2 Green %3 Blue %4 %5',\n                jikko_basic_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                jikko_basic_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                jikko_basic_set_digital_buzzer_volume:\n                    '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                jikko_basic_set_digital_buzzer:\n                    '피에조부저 %1 번 핀의 버저를 %2 %3 음으로 %4 박자 연주 %5',\n                jikko_basic_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5',\n                jikko_basic_set_neopixel_init:\n                    '네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3',\n                jikko_basic_set_neopixel_bright:\n                    '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3',\n                jikko_basic_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4',\n                jikko_basic_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3',\n                jikko_basic_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2',\n                jikko_basic_set_dotmatrix_init:\n                    '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                jikko_basic_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                jikko_basic_set_dotmatrix: '도트매트릭스 LED 그리기 %1 %2',\n                jikko_basic_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                jikko_basic_module_digital_lcd: 'LCD %1 열 %2 행 부터 %3 출력',\n                jikko_basic_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n\n                jikko_basic_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2',\n                jikko_basic_module_digital_oled: 'OLED X codinate %1 Y coodinate %2 appear %3 %4',\n                jikko_basic_get_dht_temp_value: '온습도센서의 온도값',\n                jikko_basic_get_dht_humi_value: '온습도센서의 습도값',\n\n                jikko_basic_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3',\n                jikko_basic_set_mp3_play: 'mp3 %1 번 파일 재생 %2',\n                jikko_basic_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3',\n                jikko_basic_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2',\n            },\n        },\n    };\n};\nEntry.jikko_basic.blockMenuBlocks = [\n    'jikko_basic_set_digital_toggle',\n    'jikko_basic_get_analog_value',\n    'jikko_basic_get_digital',\n    'jikko_basic_get_analog_mapping',\n    'jikko_basic_mapping1',\n    'jikko_basic_mapping2',\n\n    'jikko_basic_set_led_toggle',\n    'jikko_basic_set_digital_pwm',\n\n    'jikko_basic_get_digital_ultrasonic',\n    'jikko_basic_get_digital_toggle',\n    'jikko_basic_get_light_value',\n    'jikko_basic_get_moisture_value',\n    'jikko_basic_get_dht',\n    'jikko_basic_get_pullup',\n    'jikko_basic_get_button',\n\n    'jikko_basic_set_digital_dcmotor',\n    'jikko_basic_set_analog_dcmotor',\n    'jikko_basic_set_digital_servo',\n    'jikko_basic_set_digital_servo2',\n    'jikko_basic_set_digital_buzzer_toggle',\n    'jikko_basic_set_digital_buzzer_volume',\n    'jikko_basic_set_digital_buzzer',\n    'jikko_basic_set_neopixel_init',\n    'jikko_basic_set_neopixel_bright',\n    'jikko_basic_set_neopixel',\n    'jikko_basic_set_neopixel_all',\n    'jikko_basic_set_neopixel_clear',\n    'jikko_basic_set_dotmatrix_init',\n    'jikko_basic_set_dotmatrix_bright',\n    'jikko_basic_set_dotmatrix',\n    'jikko_basic_set_dotmatrix_emoji',\n    'jikko_basic_set_dotmatrix_clear',\n    'jikko_basic_lcd_init',\n    'jikko_basic_module_digital_lcd',\n    'jikko_basic_get_lcd_row',\n    'jikko_basic_get_lcd_col',\n    'jikko_basic_lcd_clear',\n    'jikko_basic_set_mp3_init',\n    'jikko_basic_set_mp3_vol',\n    'jikko_basic_set_mp3_play',\n    'jikko_basic_set_mp3_play2',\n\n    // 'jikko_basic_get_digital_bluetooth',\n    // 'jikko_basic_module_digital_bluetooth',\n];\nEntry.jikko_basic.getBlocks = function() {\n    var tx;\n    var din;\n\n    return {\n        jikko_basic_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        jikko_basic_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_basic_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        jikko_basic_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_basic_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jikko_basic_toggle_on, 'on'],\n                        [Lang.template.jikko_basic_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        jikko_basic_list_digital_toggle_en: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['HIGH', 'on'],\n                        ['LOW', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        jikko_basic_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n\n        jikko_basic_set_neopixel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_neopixel_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('NUM');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_basic.sensorTypes.NEOPIXELINIT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_set_neopixel_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_neopixel_bright',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('NUM');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_basic.sensorTypes.NEOPIXELBRIGHT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_set_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'jikko_basic_set_neopixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n                COLOR: 2,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                //var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var num = script.getNumberValue('NUM', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_basic.sensorTypes.NEOPIXEL,\n                        data: {\n                            num: num,\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_set_neopixel_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'jikko_basic_set_neopixel_all',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COLOR: 1,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_basic.sensorTypes.NEOPIXELALL,\n                        data: {\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_set_neopixel_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_neopixel_clear',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_basic.sensorTypes.NEOPIXELCLEAR,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_basic_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_lcd_list_init',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_lcd_init',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n                COL: 1,\n                LINE: 2,\n            },\n            class: 'jikko_basicModule',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var list = script.getNumberValue('LIST');\n                var col = script.getNumberValue('COL');\n                var line = script.getValue('LINE');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 0.1 * 1000;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_basic.sensorTypes.LCDINIT,\n                        data: {\n                            list: list,\n                            col: col,\n                            line: line,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko_basic.module_digital_lcd(%1, %2)'] },\n        },\n        jikko_basic_module_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_get_lcd_col',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'jikko_basic_get_lcd_row',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Hello, jikko'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_module_digital_lcd',\n            },\n            paramsKeyMap: {\n                COL: 0,\n                ROW: 1,\n                STRING: 2,\n            },\n            class: 'jikko_basicModule',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var row = script.getNumberValue('ROW');\n                var col = script.getNumberValue('COL');\n                var text = script.getValue('STRING');\n                text += ' ';\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_basic.sensorTypes.LCD,\n                        data: {\n                            line: row,\n                            column: col,\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko_basic.module_digital_lcd(%1, %2)'] },\n        },\n        jikko_basic_lcd_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_basic_lcd_clear',\n            },\n            class: 'jikko_basicModule',\n            isNotFor: ['jikko_basic'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_basic.sensorTypes.LCDCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jikko_basic_lcd_first_line, '0'],\n                        [Lang.template.jikko_basic_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_basic_lcd_list_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x27', '0'],\n                        ['0x3F', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_basic_get_lcd_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'jikko_basic_get_lcd_row',\n                    },\n                ],\n            },\n        },\n        jikko_basic_get_lcd_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'jikko_basic_get_lcd_col',\n                    },\n                ],\n            },\n        },\n\n        jikko_basic_set_dotmatrix_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['12'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_dotmatrix_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n            },\n            class: 'dot',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                din = port1;\n                // clk = port2;\n                // cs = port3;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port1] = {\n                        type: Entry.jikko_basic.sensorTypes.DOTMATRIXINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                            port3: port3,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_set_dotmatrix_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_dotmatrix_bright',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                num = Math.round(num);\n                num = Math.min(num, 8);\n                num = Math.max(num, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko_basic.sensorTypes.DOTMATRIXBRIGHT,\n                        data: num,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_set_dotmatrix_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_basic_set_dotmatrix_clear',\n            },\n            class: 'dot',\n            isNotFor: ['jikko_basic'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (1 + 0.5) * 0.1; //0.15\n                    timeValue = (60 / fps) * timeValue * 100;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko_basic.sensorTypes.DOTMATRIXCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_set_dotmatrix: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['003c420024242400'],\n                    },\n                ],\n                type: 'jikko_basic_set_dotmatrix',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var text = script.getValue('STRING');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko_basic.sensorTypes.DOTMATRIX,\n                        data: {\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_basic_dotmatrix_emoji_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['🖤', '1'],\n                        ['🤍', '2'],\n                        ['👆', '3'],\n                        ['👇', '4'],\n                        ['👈', '5'],\n                        ['👉', '6'],\n                        ['😊', '7'],\n                        ['😥', '8'],\n                        ['😡', '9'],\n                        ['😆', '10'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_basic_set_dotmatrix_emoji: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_dotmatrix_emoji_list',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_dotmatrix_emoji',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('LIST');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko_basic.sensorTypes.DOTMATRIXEMOJI,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_basic_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_basic_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_analog_basic',\n                    },\n                ],\n                type: 'jikko_basic_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_basicPin',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_basic.get_analog_value(%1)'] },\n        },\n        jikko_basic_get_light_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_analog_basic',\n                    },\n                ],\n                type: 'jikko_basic_get_light_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_basicGet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_basic.get_analog_value(%1)'] },\n        },\n        jikko_basic_get_moisture_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //template: Lang.template.jikko_basic_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_analog_basic',\n                        params: ['1'],\n                    },\n                ],\n                type: 'jikko_basic_get_moisture_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_basicGet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_basic.get_analog_value(%1)'] },\n        },\n\n        jikko_basic_set_digital_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_basic_set_digital_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_basicSet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_basic.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_basic.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_basic.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_basic.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        jikko_basic_set_analog_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_basic_set_analog_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_pwm',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_analog_dcmotor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_basicSet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_basic.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_basic.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        jikko_basic_get_pullup: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_basic_get_pullup',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_basicGet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var pu = Entry.hw.portData.PULLUP;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.jikko_basic.sensorTypes.PULLUP] = {\n                    port: port,\n                    data: 2,\n                    time: new Date().getTime(),\n                };\n                var pullupvalue = pu ? pu[port] || 0 : 0;\n                return !pullupvalue;\n            },\n\n            syntax: { js: [], py: [] },\n        },\n        jikko_basic_get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_basic_get_button',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_basicGet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.jikko_basic.sensorTypes.DIGITAL] = {\n                    port: port,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n\n                var value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                return !value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jikko_basic_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_basic_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_analog_basic',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'jikko_basic_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'jikko_basicPin',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                result = ANALOG ? ANALOG[port] || 0 : 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_basic.get_analog_mapping(%1, %2, %3, %4, %5)'],\n            },\n        },\n        jikko_basic_mapping1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                ],\n                type: 'jikko_basic_mapping1',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'jikko_basicPin',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                num = Math.min(value3, num);\n                num = Math.max(value2, num);\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        jikko_basic_mapping2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1024'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'jikko_basic_mapping2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'jikko_basicPin',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var flag = 0;\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var value4_1 = value4;\n                var value5_1 = value5;\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                if (value4 > value5) {\n                    flag = 1;\n                    var swap = value4;\n                    value4_1 = value5;\n                    value5_1 = swap;\n                }\n\n                num -= value2;\n                num = num * ((value5_1 - value4_1) / (value3 - value2));\n\n                if (flag == 1) {\n                    num = value4 - num;\n                    num = Math.min(value4, num);\n                    num = Math.max(value5, num);\n                } else {\n                    num = num + value4;\n                    num = Math.min(value5, num);\n                    num = Math.max(value4, num);\n                }\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        jikko_basic_get_digital_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_basic_get_digital_ultrasonic,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                        params: ['4'],\n                    },\n                ],\n                type: 'jikko_basic_get_digital_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'jikko_basicGet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1');\n                var port2 = script.getNumberValue('PORT2');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                Entry.Utils.sleep(700);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko_basic.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC[port2] || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_basic.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n        jikko_basic_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.jikko_basic_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_basic_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_basicPin',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.jikko_basic.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_basic.get_digital(%1)'] },\n        },\n        jikko_basic_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.jikko_basic_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_basic_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_basicGet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko_basic.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_basic.get_digital_toggle(%1)'] },\n        },\n        jikko_basic_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_basic_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_toggle_en',\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_basicPin',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_basic.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_basic.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_basic.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_basic.set_digital_toggle(%1, %2)'] },\n        },\n        jikko_basic_set_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_led_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_basicLed',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_basic.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_basic.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_basic.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_basic.set_digital_toggle(%1, %2)'] },\n        },\n        jikko_basic_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_basic_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_pwm',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_basicLed',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_basic.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_basic.set_digital_pwm(%1, %2)'] },\n        },\n        jikko_basic_set_digital_rgbled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_basic_set_digital_rgbled,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_pwm',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_pwm',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_pwm',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_rgbled',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n                VALUE1: 3,\n                VALUE2: 4,\n                VALUE3: 5,\n            },\n            class: 'jikko_basicLed',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                RGBport = port1;\n\n                // if (!script.isStart) {\n                //     script.isStart = true;\n                //     script.timeFlag = 1;\n                //     var fps = Entry.FPS || 60;\n                //     var timeValue = (60 / fps) * 50;\n\n                //     value1 = Math.round(value1);\n                //     value1 = Math.min(value1, 255);\n                //     value1 = Math.max(value1, 0);\n                //     value2 = Math.round(value2);\n                //     value2 = Math.min(value2, 255);\n                //     value2 = Math.max(value2, 0);\n                //     value3 = Math.round(value3);\n                //     value3 = Math.min(value3, 255);\n                //     value3 = Math.max(value3, 0);\n\n                //     if (!Entry.hw.sendQueue['SET']) {\n                //         Entry.hw.sendQueue['SET'] = {};\n                //     }\n                //     Entry.hw.sendQueue['SET'][RGBport] = {\n                //         type: Entry.jikko_basic.sensorTypes.RGBLED,\n                //         data: {\n                //             port1: port1,\n                //             port2: port2,\n                //             port3: port3,\n                //             value1: value1,\n                //             value2: value2,\n                //             value3: value3,\n                //         },\n                //         time: new Date().getTime(),\n                //     };\n                //     setTimeout(function() {\n                //         script.timeFlag = 0;\n                //     }, 10);\n                //     return script;\n                // } else if (script.timeFlag == 1) {\n                //     return script;\n                // } else {\n                //     delete script.timeFlag;\n                //     delete script.isStart;\n                //     Entry.engine.isContinue = false;\n                //     return script.callReturn();\n                // }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type: Entry.jikko_basic.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type: Entry.jikko_basic.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port3] = {\n                    type: Entry.jikko_basic.sensorTypes.PWM,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        jikko_basic_set_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_basic_set_digital_servo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_basicSet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_basic.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_basic.set_digital_servo(%1, %2)'] },\n        },\n        jikko_basic_set_digital_servo2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_basic_set_digital_servo2,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['180'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_servo2',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n                STIME: 3,\n            },\n            class: 'jikko_basicSet',\n            isNotFor: ['jikko_basic'],\n            // func: function(sprite, script) {\n            //     var port = script.getNumberValue('PORT');\n            //     var value1 = script.getNumber    Value('VALUE1', script);\n            //     var value2 = script.getNumberValue('VALUE2', script);\n            //     var stime = script.getNumberValue('STIME', script);\n\n            //     value1 = Math.min(value1, 180);\n            //     value1 = Math.max(value1, 0);\n            //     value2 = Math.min(value2, 180);\n            //     value2 = Math.max(value2, 0);\n\n            //     if (!Entry.hw.sendQueue['SET']) {\n            //         Entry.hw.sendQueue['SET'] = {};\n            //     }\n\n            //     Entry.hw.sendQueue['SET'][port] = {\n            //         type: Entry.jikko_basic.sensorTypes.SERVO2,\n            //         data: {\n            //             value1: value1,\n            //             value2: value2,\n            //             stime: stime,\n            //         },\n            //         time: new Date().getTime(),\n            //     };\n            //     return script.callReturn();\n            // },\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var stime = script.getNumberValue('STIME', script);\n\n                value1 = Math.min(value1, 180);\n                value1 = Math.max(value1, 0);\n                value2 = Math.min(value2, 180);\n                value2 = Math.max(value2, 0);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_basic.sensorTypes.SERVO2,\n                        data: {\n                            value1: value1,\n                            value2: value2,\n                            stime: stime,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        jikko_basic_set_digital_buzzer_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_toggle',\n                    },\n\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_buzzer_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_basicBuzzer',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_basic.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_basic.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_basic.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_basic.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_basic_set_digital_buzzer_volume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_pwm',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_buzzer_volume',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_basicBuzzer',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_basic.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_basic.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_basic_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_basic_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_basic_list_digital_basic',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_tone',\n                    },\n                    {\n                        type: 'jikko_basic_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'jikko_basicBuzzer',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.jikko_basic.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.jikko_basic.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.jikko_basic.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_basic.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_basic.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_basic.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_basic_get_dht: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['온도(°C)', '0'],\n                        ['습도(%)', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'jikko_basic_get_dht',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DHT_SELECT: 1,\n            },\n            class: 'jikko_basicGet',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var type = script.getNumberValue('DHT_SELECT');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (type == 0) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko_basic.sensorTypes.DHTTEMP] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTTEMP || 0;\n                } else if (type == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko_basic.sensorTypes.DHTHUMI] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTHUMI || 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_basic_set_mp3_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_mp3_init',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'mp3',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                tx = script.getNumberValue('PORT1');\n                var rx = script.getNumberValue('PORT2');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.jikko_basic.sensorTypes.MP3INIT,\n                        data: {\n                            tx: tx,\n                            rx: rx,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_basic_set_mp3_play: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_mp3_play',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'mp3',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                script.isStart = true;\n                script.timeFlag = 1;\n                var fps = Entry.FPS || 60;\n                var timeValue = (60 / fps) * 50;\n\n                Entry.hw.sendQueue['SET'][tx] = {\n                    type: Entry.jikko_basic.sensorTypes.MP3PLAY1,\n                    data: {\n                        tx: tx,\n                        num: num,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_basic_set_mp3_play2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_mp3_play2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                TIME: 1,\n            },\n            class: 'mp3',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM');\n                var time_value = script.getNumberValue('TIME');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    time_value = (60 / fps) * time_value * 1000;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.jikko_basic.sensorTypes.MP3PLAY1,\n                        data: {\n                            tx: tx,\n                            num: num,\n                            //time_value: time_value,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, time_value);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.jikko_basic.sensorTypes.MP3PLAY1,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_basic_set_mp3_vol: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['15'],\n                    },\n                    null,\n                ],\n                type: 'jikko_basic_set_mp3_vol',\n            },\n            paramsKeyMap: {\n                VOL: 0,\n            },\n            class: 'mp3',\n            isNotFor: ['jikko_basic'],\n            func: function(sprite, script) {\n                var vol = script.getNumberValue('VOL');\n\n                vol = Math.round(vol);\n                vol = Math.min(vol, 30);\n                vol = Math.max(vol, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][tx] = {\n                        type: Entry.jikko_basic.sensorTypes.MP3VOL,\n                        data: {\n                            tx: tx,\n                            vol: vol,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.jikko_basic;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_jikko_lidoc.js",
    "content": "'use strict';\n\nEntry.jikko_lidoc = {\n    id: '47.2',\n    name: 'jikko_lidoc',\n    url: 'http://www.makeitall.co.kr',\n    imageName: 'jikko_lidoc.png',\n    title: {\n        ko: '직코&리닥 CPR',\n        en: 'jikko_lidoc',\n    },\n    Static: {\n        BUTTON_PRESS_VALUE: 0,\n    },\n\n    //정지시 초기화 함수\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        TONE: 5,\n        LCD: 11,\n        LCDCLEAR: 12,\n        LCDINIT: 17,\n        NEOPIXELINIT: 20,\n        NEOPIXELBRIGHT: 21,\n        NEOPIXEL: 22,\n        NEOPIXELALL: 23,\n        NEOPIXELCLEAR: 24,\n        LOADINIT: 35,\n        LOADSCALE: 36,\n        LOADVALUE: 37,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    direction: {\n        CENTER: 0,\n        UP: 1,\n        LEFT: 2,\n        RIGHT: 3,\n        DOWN: 4,\n        LEFT_UP: 5,\n        LEFT_DOWN: 6,\n        RIGHT_UP: 7,\n        RIGHT_DOWN: 8,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\nEntry.jikko_lidoc.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                jikko_lidoc_toggle_on: '켜기',\n                jikko_lidoc_toggle_off: '끄기',\n                jikko_lidoc_lcd_first_line: '첫 번째',\n                jikko_lidoc_lcd_seconds_line: '두 번째',\n                jikko_lidoc_get_analog_value: '아날로그 %1 핀 읽기',\n                jikko_lidoc_get_pullup: '풀업 저항 사용 버튼 %1 핀 눌림 상태',\n                jikko_lidoc_get_button: '버튼 %1 핀 눌림 상태',\n                jikko_lidoc_get_analog_mapping:\n                    '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n                jikko_lidoc_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                jikko_lidoc_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                jikko_lidoc_get_digital: '디지털 %1 핀 읽기',\n                jikko_lidoc_get_digital_toggle: '디지털 %1 핀 센서 값',\n                jikko_lidoc_set_digital_toggle: '디지털 %1 핀 %2 %3',\n                jikko_lidoc_set_led_toggle: 'LED 13 핀 %1 %2',\n                jikko_lidoc_set_digital_pwm: 'LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3',\n\n                jikko_lidoc_set_digital_buzzer_toggle: '피에조부저 12핀 %1 %2',\n                jikko_lidoc_set_digital_buzzer_volume:\n                    '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                jikko_lidoc_set_digital_buzzer: '피에조부저 12핀 %1 %2 음 %3 박자 연주 %4',\n\n                jikko_lidoc_set_neopixel_init:\n                    '네오픽셀 LED 시작하기 설정 (10 핀에 %1 개의 LED 연결) %2',\n                jikko_lidoc_set_neopixel_bright: '네오픽셀 LED 밝기 %1 으로 설정 (0 ~ 255) %2',\n                jikko_lidoc_set_neopixel: '네오픽셀 LED %1 번째 LED 색 %2 출력 %3',\n                jikko_lidoc_set_neopixel_all: '네오픽셀 LED 모든 LED 색 %1 출력 %2',\n                jikko_lidoc_set_neopixel_clear: '네오픽셀 LED 모든 LED 끄기 %1',\n\n                jikko_lidoc_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n                jikko_lidoc_get_lcd_row: '%1',\n                jikko_lidoc_get_lcd_col: '%1',\n                jikko_lidoc_module_digital_lcd: 'LCD화면 %1 열 %2 행 부터 %3 출력 %4',\n                jikko_lidoc_lcd_clear: 'LCD 화면 지우기 %1',\n\n                jikko_lidoc_load_init: 'HX711 로드셀 시작하기 설정 (DOUT 6핀, SCK 7핀) %1',\n                jikko_lidoc_load_scale: 'HX711 로드셀 보정하기 %1 %2',\n                jikko_lidoc_load_value: 'HX711 로드셀 값',\n            },\n        },\n        en: {\n            template: {\n                jikko_lidoc_toggle_on: '켜기',\n                jikko_lidoc_toggle_off: '끄기',\n                jikko_lidoc_lcd_first_line: '첫 번째',\n                jikko_lidoc_lcd_seconds_line: '두 번째',\n                jikko_lidoc_get_analog_value: '아날로그 %1 핀 읽기',\n                jikko_lidoc_get_pullup: '풀업 저항 사용 버튼 %1 핀 눌림 상태',\n                jikko_lidoc_get_button: '버튼 %1 핀 눌림 상태',\n                jikko_lidoc_get_analog_mapping:\n                    '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n                jikko_lidoc_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                jikko_lidoc_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                jikko_lidoc_get_digital: '디지털 %1 핀 읽기',\n                jikko_lidoc_get_digital_toggle: '디지털 %1 핀 센서 값',\n                jikko_lidoc_set_digital_toggle: '디지털 %1 핀 %2 %3',\n                jikko_lidoc_set_led_toggle: 'LED 13 핀 %1 %2',\n                jikko_lidoc_set_digital_pwm: 'LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3',\n\n                jikko_lidoc_set_digital_buzzer_toggle: '피에조부저 12핀 %1 %2',\n                jikko_lidoc_set_digital_buzzer_volume:\n                    '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                jikko_lidoc_set_digital_buzzer: '피에조부저 12핀 %1 %2 음 %3 박자 연주 %4',\n\n                jikko_lidoc_set_neopixel_init:\n                    '네오픽셀 LED 시작하기 설정 (10 핀에 %1 개의 LED 연결) %2',\n                jikko_lidoc_set_neopixel_bright: '네오픽셀 LED 밝기 %1 으로 설정 (0 ~ 255) %2',\n                jikko_lidoc_set_neopixel: '네오픽셀 LED %1 번째 LED 색 %2 출력 %3',\n                jikko_lidoc_set_neopixel_all: '네오픽셀 LED 모든 LED 색 %1 출력 %2',\n                jikko_lidoc_set_neopixel_clear: '네오픽셀 LED 모든 LED 끄기 %1',\n\n                jikko_lidoc_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n                jikko_lidoc_get_lcd_row: '%1',\n                jikko_lidoc_get_lcd_col: '%1',\n                jikko_lidoc_module_digital_lcd: 'LCD화면 %1 열 %2 행 부터 %3 출력 %4',\n                jikko_lidoc_lcd_clear: 'LCD 화면 지우기 %1',\n\n                jikko_lidoc_load_init: 'HX711 로드셀 시작하기 설정 (DOUT 6핀, SCK 7핀) %1',\n                jikko_lidoc_load_scale: 'HX711 로드셀 보정하기 %1 %2',\n                jikko_lidoc_load_value: 'HX711 로드셀 값',\n            },\n        },\n    };\n};\nEntry.jikko_lidoc.blockMenuBlocks = [\n    'jikko_lidoc_set_digital_toggle',\n    'jikko_lidoc_set_led_toggle',\n    //  'jikko_lidoc_set_digital_pwm',\n\n    'jikko_lidoc_set_digital_buzzer_toggle',\n    'jikko_lidoc_set_digital_buzzer',\n    'jikko_lidoc_set_neopixel_init',\n    'jikko_lidoc_set_neopixel_bright',\n    'jikko_lidoc_set_neopixel',\n    'jikko_lidoc_set_neopixel_all',\n    'jikko_lidoc_set_neopixel_clear',\n\n    'jikko_lidoc_lcd_init',\n    'jikko_lidoc_module_digital_lcd',\n    'jikko_lidoc_get_lcd_row',\n    'jikko_lidoc_get_lcd_col',\n    'jikko_lidoc_lcd_clear',\n\n    'jikko_lidoc_load_init',\n    'jikko_lidoc_load_scale',\n    'jikko_lidoc_load_value',\n\n    // 'jikko_lidoc_get_digital_bluetooth',\n    // 'jikko_lidoc_module_digital_bluetooth',\n];\nEntry.jikko_lidoc.getBlocks = function() {\n    var tx;\n    var din;\n    // var clk;\n    // var cs;\n    var dout;\n    var sck;\n    var joyx, joyy, joyz;\n    var joyx2, joyy2, joyz2;\n    var portpin1, portpin2, portpin3;\n    var ss;\n    var speed1 = 14;\n    var speed2 = 14;\n    var speed3 = 14;\n    var num = 0;\n\n    return {\n        jikko_lidoc_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        jikko_lidoc_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_lidoc_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        jikko_lidoc_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_lidoc_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jikko_lidoc_toggle_on, 'on'],\n                        [Lang.template.jikko_lidoc_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        jikko_lidoc_list_digital_toggle_en: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['HIGH', 'on'],\n                        ['LOW', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        jikko_lidoc_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        jikko_lidoc_set_neopixel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_set_neopixel_init',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = 10;\n                var value = script.getNumberValue('NUM');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_lidoc.sensorTypes.NEOPIXELINIT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_lidoc_set_neopixel_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_set_neopixel_bright',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = 10;\n                var value = script.getNumberValue('NUM');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_lidoc.sensorTypes.NEOPIXELBRIGHT,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_lidoc_set_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'jikko_lidoc_set_neopixel',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                COLOR: 1,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                //var sq = Entry.hw.sendQueue;\n                var port = 10;\n                var num = script.getNumberValue('NUM', script);\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_lidoc.sensorTypes.NEOPIXEL,\n                        data: {\n                            num: num,\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_lidoc_set_neopixel_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'jikko_lidoc_set_neopixel_all',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'neo',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = 10;\n                var value = script.getStringField('COLOR', script);\n\n                let r = parseInt(value.substr(1, 2), 16);\n                let g = parseInt(value.substr(3, 2), 16);\n                let b = parseInt(value.substr(5, 2), 16);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n                    r = Math.round(r);\n                    r = Math.min(r, 255);\n                    r = Math.max(r, 0);\n\n                    g = Math.round(g);\n                    g = Math.min(g, 255);\n                    g = Math.max(g, 0);\n\n                    b = Math.round(b);\n                    b = Math.min(b, 255);\n                    b = Math.max(b, 0);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_lidoc.sensorTypes.NEOPIXELALL,\n                        data: {\n                            r: r,\n                            g: g,\n                            b: b,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 10);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_lidoc_set_neopixel_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jikko_lidoc_set_neopixel_clear',\n            },\n            paramsKeyMap: {},\n            class: 'neo',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = 10;\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_lidoc.sensorTypes.NEOPIXELCLEAR,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_lidoc_lcd_list_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x27', '0'],\n                        ['0x3F', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_lidoc_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jikko_lidoc_lcd_first_line, '0'],\n                        [Lang.template.jikko_lidoc_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_lidoc_get_lcd_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'jikko_lidoc_get_lcd_row',\n                    },\n                ],\n            },\n        },\n\n        jikko_lidoc_get_lcd_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'jikko_lidoc_get_lcd_col',\n                    },\n                ],\n            },\n        },\n        jikko_lidoc_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_lidoc_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_analog_basic',\n                    },\n                ],\n                type: 'jikko_lidoc_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_lidocPin',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_lidoc.get_analog_value(%1)'] },\n        },\n\n        jikko_lidoc_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_lidoc_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_analog_basic',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'jikko_lidoc_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'jikko_lidocPin',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                result = ANALOG ? ANALOG[port] || 0 : 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_lidoc.get_analog_mapping(%1, %2, %3, %4, %5)'],\n            },\n        },\n\n        jikko_lidoc_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.jikko_lidoc_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_lidoc_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_lidocPin',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.jikko_lidoc.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_lidoc.get_digital(%1)'] },\n        },\n        jikko_lidoc_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.jikko_lidoc_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_lidoc_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_lidocGet',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko_lidoc.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_lidoc.get_digital_toggle(%1)'] },\n        },\n\n        jikko_lidoc_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_lidoc_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_digital_basic',\n                    },\n                    {\n                        type: 'jikko_lidoc_list_digital_toggle_en',\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_lidocPin',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_lidoc.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_lidoc.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_lidoc.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_lidoc.set_digital_toggle(%1, %2)'] },\n        },\n        jikko_lidoc_set_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_set_led_toggle',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'jikko_lidocLed',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = 13;\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_lidoc.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_lidoc.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_lidoc.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_lidoc.set_digital_toggle(%1, %2)'] },\n        },\n        jikko_lidoc_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_lidoc_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_digital_pwm',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_lidocLed',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_lidoc.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_lidoc.set_digital_pwm(%1, %2)'] },\n        },\n\n        jikko_lidoc_set_digital_buzzer_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_digital_toggle',\n                    },\n\n                    null,\n                ],\n                type: 'jikko_lidoc_set_digital_buzzer_toggle',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'jikko_lidocBuzzer',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = 12;\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_lidoc.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_lidoc.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_lidoc.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_lidoc.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_lidoc_set_digital_buzzer_volume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_digital_pwm',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_set_digital_buzzer_volume',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_lidocBuzzer',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_lidoc.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_lidoc.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_lidoc_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_lidoc_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_list_digital_tone',\n                    },\n                    {\n                        type: 'jikko_lidoc_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'jikko_lidocBuzzer',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port = 12;\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.jikko_lidoc.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.jikko_lidoc.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.jikko_lidoc.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_lidoc.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_lidoc.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_lidoc.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_lidoc_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_lcd_list_init',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_lcd_init',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n                COL: 1,\n                LINE: 2,\n            },\n            class: 'jikko_lidocModule',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var list = script.getNumberValue('LIST');\n                var col = script.getNumberValue('COL');\n                var line = script.getValue('LINE');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 0.1 * 1000;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_lidoc.sensorTypes.LCDINIT,\n                        data: {\n                            list: list,\n                            col: col,\n                            line: line,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko_lidoc.module_digital_lcd(%1, %2)'] },\n        },\n        jikko_lidoc_module_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_lidoc_get_lcd_col',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'jikko_lidoc_get_lcd_row',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Hello, jikko_lidoc'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_module_digital_lcd',\n            },\n            paramsKeyMap: {\n                COL: 0,\n                ROW: 1,\n                STRING: 2,\n            },\n            class: 'jikko_lidocModule',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var row = script.getNumberValue('ROW');\n                var col = script.getNumberValue('COL');\n                var text = script.getValue('STRING');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_lidoc.sensorTypes.LCD,\n                        data: {\n                            line: row,\n                            column: col,\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko_lidoc.module_digital_lcd(%1, %2)'] },\n        },\n        jikko_lidoc_lcd_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_lidoc_lcd_clear',\n            },\n            class: 'jikko_lidocModule',\n            isNotFor: ['jikko_lidoc'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_lidoc.sensorTypes.LCDCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_lidoc_load_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jikko_lidoc_load_init',\n            },\n            paramsKeyMap: {},\n            class: 'load',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var port1 = 6;\n                var port2 = 7;\n\n                dout = port1;\n                sck = port2;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][sck] = {\n                        type: Entry.jikko_lidoc.sensorTypes.LOADINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_lidoc_load_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['-20000'],\n                    },\n                    null,\n                ],\n                type: 'jikko_lidoc_load_scale',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'load',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][sck] = {\n                        type: Entry.jikko_lidoc.sensorTypes.LOADSCALE,\n                        data: {\n                            num: num,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n\n        jikko_lidoc_load_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'jikko_lidoc_load_value',\n            },\n            paramsKeyMap: {},\n            class: 'load',\n            isNotFor: ['jikko_lidoc'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][sck];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko_lidoc.sensorTypes.LOADVALUE] = {\n                    port: sck,\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.LOADVALUE || 0;\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.jikko_lidoc;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_jikko_make.js",
    "content": "'use strict';\n\nEntry.jikko_make = {\n    id: '47.3',\n    name: 'jikko_make',\n    url: 'http://www.makeitall.co.kr',\n    imageName: 'jikko_make.png',\n    title: {\n        ko: '직코_만들다',\n        en: 'jikko_make',\n    },\n    Static: {\n        BUTTON_PRESS_VALUE: 0,\n    },\n\n    //정지시 초기화 함수\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO: 4,\n        TONE: 5,\n        ULTRASONIC: 7,\n        TIMER: 7,\n        LCD: 11,\n        LCDCLEAR: 12,\n        DCMOTOR: 14,\n        LCDINIT: 17,\n        DHTHUMI: 18,\n        DHTTEMP: 19,\n        DOTMATRIXINIT: 25,\n        DOTMATRIXBRIGHT: 26,\n        DOTMATRIX: 27,\n        DOTMATRIXEMOJI: 28,\n        DOTMATRIXCLEAR: 29,\n        PULLUP: 58,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\nEntry.jikko_make.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                jikko_make_toggle_on: '켜기',\n                jikko_make_toggle_off: '끄기',\n                jikko_make_lcd_first_line: '첫 번째',\n                jikko_make_lcd_seconds_line: '두 번째',\n                jikko_make_get_analog_value: '아날로그 %1 핀 읽기',\n                jikko_make_get_light_value: '조도센서(AO 1핀)값',\n                jikko_make_get_moisture_value: '토양수분센서(AO %1)값',\n                jikko_make_get_pullup: '풀업 저항 사용 버튼 %1 핀 눌림 상태',\n                jikko_make_get_button: '버튼 %1 핀 눌림 상태',\n                jikko_make_get_analog_mapping:\n                    '아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\n                jikko_make_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                jikko_make_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                jikko_make_get_digital_ultrasonic: '초음파(Trig 5핀 Echo 4핀) 센서 값',\n                jikko_make_get_digital: '디지털 %1 핀 읽기',\n                jikko_make_get_digital_toggle: '디지털 %1 핀 센서 값',\n                jikko_make_set_digital_toggle: '디지털 %1 핀 %2 %3',\n                jikko_make_set_led_toggle: 'LED %1 핀 %2 %3',\n\n                jikko_make_set_digital_dcmotor: 'DC모터 6핀 %1 %2',\n                jikko_make_set_analog_dcmotor: 'DC모터(PWM 6핀) 세기 %1 출력 (0 ~ 255) %2',\n\n                jikko_make_set_digital_pwm: 'LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3',\n                jikko_make_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                jikko_make_set_digital_buzzer_toggle: '피에조부저 7핀 %1 %2',\n                jikko_make_set_digital_buzzer_volume:\n                    '피에조부저 (PWM 7핀) 음량 %1 출력 (0 ~ 255) %2',\n                jikko_make_set_digital_buzzer: '피에조부저 7핀 %1 %2 음 %3 박자 연주 %4',\n                jikko_make_set_dotmatrix_init:\n                    '8x8 도트매트릭스 시작하기 설정 (DIN 12, CLK 10, CS 11) %1',\n                jikko_make_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                jikko_make_set_dotmatrix: '도트매트릭스 LED %1 그리기 %2',\n                jikko_make_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                jikko_make_set_dotmatrix_clear: '도트매트릭스 LED 지우기 %1',\n\n                jikko_make_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n                jikko_make_get_lcd_row: '%1',\n                jikko_make_get_lcd_col: '%1',\n                jikko_make_module_digital_lcd: 'LCD화면 %1 열 %2 행 부터 %3 출력 %4',\n                jikko_make_lcd_clear: 'LCD 화면 지우기 %1',\n                // jikko_make_get_dht_temp_value: 'DHT11 온습도센서(out 3핀)의 온도(°C)값',\n                // jikko_make_get_dht_humi_value: 'DHT11 온습도센서(out 3핀)의 습도(%)값',\n                jikko_make_get_dht: 'DHT11 온습도센서 3핀의 %1값',\n            },\n        },\n        en: {\n            template: {\n                jikko_make_toggle_on: 'on',\n                jikko_make_toggle_off: 'off',\n                jikko_make_lcd_first_line: 'first',\n                jikko_make_lcd_seconds_line: 'seconds',\n                jikko_make_get_analog_value: 'Read analog %1 pin sensor value',\n                jikko_make_get_analog_mapping:\n                    'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5',\n                jikko_make_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값',\n                jikko_make_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                jikko_make_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value',\n                jikko_make_get_digital: 'Digital %1 pin sensor value',\n                jikko_make_get_digital_toggle: 'Digital %1 pin sensor value',\n                jikko_make_set_digital_toggle: 'Digital %1 pin %2 %3',\n                jikko_make_set_digital_pwm: 'Digital pwm %1 Pin %2 %3',\n                jikko_make_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3',\n                jikko_make_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3',\n                jikko_make_set_digital_buzzer_volume:\n                    '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3',\n                jikko_make_set_digital_buzzer:\n                    '피에조부저 %1 번 핀의 버저를 %2 %3 음으로 %4 박자 연주 %5',\n                jikko_make_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5',\n                jikko_make_set_dotmatrix_init:\n                    '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4',\n                jikko_make_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2',\n                jikko_make_set_dotmatrix: '도트매트릭스 LED 그리기 %1 %2',\n                jikko_make_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2',\n                jikko_make_module_digital_lcd: 'LCD %1 열 %2 행 부터 %3 출력',\n                jikko_make_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4',\n            },\n        },\n    };\n};\nEntry.jikko_make.blockMenuBlocks = [\n    'jikko_make_set_digital_toggle',\n    'jikko_make_get_analog_value',\n    'jikko_make_get_digital',\n    'jikko_make_get_analog_mapping',\n    'jikko_make_mapping1',\n    'jikko_make_mapping2',\n\n    'jikko_make_set_led_toggle',\n    'jikko_make_set_digital_pwm',\n\n    'jikko_make_set_digital_dcmotor',\n    'jikko_make_set_analog_dcmotor',\n\n    'jikko_make_get_digital_ultrasonic',\n    'jikko_make_get_digital_toggle',\n    'jikko_make_get_light_value',\n\n    'jikko_make_get_dht',\n    'jikko_make_get_pullup',\n    'jikko_make_get_button',\n\n    'jikko_make_set_digital_servo',\n    'jikko_make_set_digital_buzzer_toggle',\n    'jikko_make_set_digital_buzzer_volume',\n    'jikko_make_set_digital_buzzer',\n    'jikko_make_set_dotmatrix_init',\n    'jikko_make_set_dotmatrix_bright',\n    'jikko_make_set_dotmatrix',\n    'jikko_make_set_dotmatrix_emoji',\n    'jikko_make_set_dotmatrix_clear',\n    'jikko_make_lcd_init',\n    'jikko_make_module_digital_lcd',\n    'jikko_make_get_lcd_row',\n    'jikko_make_get_lcd_col',\n    'jikko_make_lcd_clear',\n];\nEntry.jikko_make.getBlocks = function() {\n    var tx;\n    var din;\n    // var clk;\n    // var cs;\n    var dout;\n    var sck;\n    var ss;\n\n    var num = 0;\n\n    return {\n        jikko_make_list_analog_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        jikko_make_list_digital_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_make_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        jikko_make_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_make_list_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jikko_make_toggle_on, 'on'],\n                        [Lang.template.jikko_make_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        jikko_make_list_digital_toggle_en: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['HIGH', 'on'],\n                        ['LOW', 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n        jikko_make_set_digital_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_make_set_digital_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_digital_dcmotor',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'jikko_makeSet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = 6;\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_make.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_make.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_make.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_make.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        jikko_make_set_analog_dcmotor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_make_set_analog_dcmotor,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_analog_dcmotor',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'jikko_makeSet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = 6;\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_make.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_make.set_digital_dcmotor(%1, %2, %3, %4)'] },\n        },\n        jikko_make_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n\n        jikko_make_lcd_list_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x27', '0'],\n                        ['0x3F', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_make_set_dotmatrix_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jikko_make_set_dotmatrix_init',\n            },\n            paramsKeyMap: {},\n            class: 'dot',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                // var port1 = script.getNumberValue('PORT1', script);\n                // var port2 = script.getNumberValue('PORT2', script);\n                // var port3 = script.getNumberValue('PORT3', script);\n\n                var port1 = 12;\n                var port2 = 10;\n                var port3 = 11;\n\n                din = port1;\n                // clk = port2;\n                // cs = port3;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][port1] = {\n                        type: Entry.jikko_make.sensorTypes.DOTMATRIXINIT,\n                        data: {\n                            port1: port1,\n                            port2: port2,\n                            port3: port3,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_make_set_dotmatrix_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_dotmatrix_bright',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                num = Math.round(num);\n                num = Math.min(num, 8);\n                num = Math.max(num, 0);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko_make.sensorTypes.DOTMATRIXBRIGHT,\n                        data: num,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_make_set_dotmatrix_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_make_set_dotmatrix_clear',\n            },\n            class: 'dot',\n            isNotFor: ['jikko_make'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (1 + 0.5) * 0.1; //0.15\n                    timeValue = (60 / fps) * timeValue * 100;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko_make.sensorTypes.DOTMATRIXCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_make_set_dotmatrix: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['003c420024242400'],\n                    },\n                ],\n                type: 'jikko_make_set_dotmatrix',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var text = script.getValue('STRING');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko_make.sensorTypes.DOTMATRIX,\n                        data: {\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_make_dotmatrix_emoji_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['🖤', '1'],\n                        ['🤍', '2'],\n                        ['👆', '3'],\n                        ['👇', '4'],\n                        ['👈', '5'],\n                        ['👉', '6'],\n                        ['😊', '7'],\n                        ['😥', '8'],\n                        ['😡', '9'],\n                        ['😆', '10'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_make_set_dotmatrix_emoji: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_dotmatrix_emoji_list',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_dotmatrix_emoji',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n            },\n            class: 'dot',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('LIST');\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][din] = {\n                        type: Entry.jikko_make.sensorTypes.DOTMATRIXEMOJI,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_make_list_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.jikko_make_lcd_first_line, '0'],\n                        [Lang.template.jikko_make_lcd_seconds_line, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        jikko_make_get_lcd_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'jikko_make_get_lcd_row',\n                    },\n                ],\n            },\n        },\n\n        jikko_make_get_lcd_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                    ['10', '10'],\n                                    ['11', '11'],\n                                    ['12', '12'],\n                                    ['13', '13'],\n                                    ['14', '14'],\n                                    ['15', '15'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'jikko_make_get_lcd_col',\n                    },\n                ],\n            },\n        },\n        jikko_make_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_make_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_analog_basic',\n                    },\n                ],\n                type: 'jikko_make_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_makePin',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_make.get_analog_value(%1)'] },\n        },\n        jikko_make_get_light_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_make_get_light_value',\n            },\n            paramsKeyMap: {},\n            class: 'jikko_makeGet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = 1;\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_make.get_analog_value(%1)'] },\n        },\n        jikko_make_get_moisture_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //template: Lang.template.jikko_make_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_analog_basic',\n                        params: ['1'],\n                    },\n                ],\n                type: 'jikko_make_get_moisture_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_makeGet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_make.get_analog_value(%1)'] },\n        },\n        jikko_make_list_digital_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_make_get_pullup: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_button',\n                    },\n                ],\n                type: 'jikko_make_get_pullup',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_makeGet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var pu = Entry.hw.portData.PULLUP;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.jikko_make.sensorTypes.PULLUP] = {\n                    port: port,\n                    data: 2,\n                    time: new Date().getTime(),\n                };\n\n                //var value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                var value = pu ? pu[port] || 0 : 0;\n                return !value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jikko_make_get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_button',\n                    },\n                ],\n                type: 'jikko_make_get_button',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_makeGet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.jikko_make.sensorTypes.DIGITAL] = {\n                    port: port,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n\n                var value = DIGITAL ? DIGITAL[port] || 0 : 0;\n                return !value;\n            },\n            syntax: { js: [], py: [] },\n        },\n        jikko_make_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_make_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_analog_basic',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'jikko_make_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'jikko_makePin',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                result = ANALOG ? ANALOG[port] || 0 : 0;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_make.get_analog_mapping(%1, %2, %3, %4, %5)'],\n            },\n        },\n        jikko_make_mapping1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                ],\n                type: 'jikko_make_mapping1',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'jikko_makePin',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                num = Math.min(value3, num);\n                num = Math.max(value2, num);\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        jikko_make_mapping2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1024'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'jikko_make_mapping2',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'jikko_makePin',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var flag = 0;\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var value4_1 = value4;\n                var value5_1 = value5;\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                if (value4 > value5) {\n                    flag = 1;\n                    var swap = value4;\n                    value4_1 = value5;\n                    value5_1 = swap;\n                }\n\n                num -= value2;\n                num = num * ((value5_1 - value4_1) / (value3 - value2));\n\n                if (flag == 1) {\n                    num = value4 - num;\n                    num = Math.min(value4, num);\n                    num = Math.max(value5, num);\n                } else {\n                    num = num + value4;\n                    num = Math.min(value5, num);\n                    num = Math.max(value4, num);\n                }\n\n                return parseInt(num);\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        jikko_make_get_digital_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.jikko_make_get_digital_ultrasonic,\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_make_get_digital_ultrasonic',\n            },\n            paramsKeyMap: {},\n            class: 'jikko_makeGet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                // var port1 = script.getNumberValue('PORT1');\n                // var port2 = script.getNumberValue('PORT2');\n\n                var port1 = 5;\n                var port2 = 4;\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                Entry.Utils.sleep(700);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko_make.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC[port2] || 0;\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_make.get_digital_ultrasonic(%1, %2)'],\n            },\n        },\n\n        jikko_make_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.jikko_make_get_digital,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_make_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_makePin',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                if (Entry.hw.sendQueue.SET[port]) {\n                    return Entry.hw.sendQueue.SET[port].data;\n                } else {\n                    Entry.hw.sendQueue['GET'][Entry.jikko_make.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                }\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_make.get_digital(%1)'] },\n        },\n        jikko_make_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.jikko_make_get_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_basic',\n                    },\n                ],\n                type: 'jikko_make_get_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'jikko_makeGet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.jikko_make.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: ['jikko_make.get_digital_toggle(%1)'] },\n        },\n\n        jikko_make_set_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_make_set_digital_toggle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_basic',\n                    },\n                    {\n                        type: 'jikko_make_list_digital_toggle_en',\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_digital_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_makePin',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_make.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_make.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_make.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_make.set_digital_toggle(%1, %2)'] },\n        },\n        jikko_make_list_digital_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '8',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_make_set_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_led',\n                        params: ['8'],\n                    },\n                    {\n                        type: 'jikko_make_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_led_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_makeLed',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_make.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_make.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_make.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_make.set_digital_toggle(%1, %2)'] },\n        },\n        jikko_make_list_digital_ledpwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_make_set_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_make_set_digital_pwm,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_ledpwm',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_makeLed',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_make.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_make.set_digital_pwm(%1, %2)'] },\n        },\n        jikko_make_list_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        jikko_make_set_digital_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_make_set_digital_servo,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_servo',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_digital_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'jikko_makeSet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_make.sensorTypes.SERVO,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['jikko_make.set_digital_servo(%1, %2)'] },\n        },\n        jikko_make_set_digital_buzzer_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_toggle',\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_digital_buzzer_toggle',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'jikko_makeBuzzer',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = 7;\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.jikko_make.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.jikko_make.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_make.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_make.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_make_set_digital_buzzer_volume: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_digital_buzzer_volume',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'jikko_makeBuzzer',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = 7;\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.jikko_make.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_make.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_make_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.jikko_make_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_list_digital_tone',\n                    },\n                    {\n                        type: 'jikko_make_list_digital_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'jikko_makeBuzzer',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = 7;\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.jikko_make.toneTable[note];\n                    }\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        Entry.hw.sendQueue['SET'][port] = {\n                            type: Entry.jikko_make.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n                    if (note != 0) {\n                        value = Entry.jikko_make.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_make.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = {\n                        type: Entry.jikko_make.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['jikko_make.set_digital_toggle(%1, %2, %3, %4)'],\n            },\n        },\n        jikko_make_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_lcd_list_init',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_lcd_init',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n                COL: 1,\n                LINE: 2,\n            },\n            class: 'jikko_makeModule',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var list = script.getNumberValue('LIST');\n                var col = script.getNumberValue('COL');\n                var line = script.getValue('LINE');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 0.1 * 1000;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_make.sensorTypes.LCDINIT,\n                        data: {\n                            list: list,\n                            col: col,\n                            line: line,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko_make.module_digital_lcd(%1, %2)'] },\n        },\n        jikko_make_module_digital_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'jikko_make_get_lcd_col',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'jikko_make_get_lcd_row',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Hello, jikko_make'],\n                    },\n                    null,\n                ],\n                type: 'jikko_make_module_digital_lcd',\n            },\n            paramsKeyMap: {\n                COL: 0,\n                ROW: 1,\n                STRING: 2,\n            },\n            class: 'jikko_makeModule',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var row = script.getNumberValue('ROW');\n                var col = script.getNumberValue('COL');\n                var text = script.getValue('STRING');\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_make.sensorTypes.LCD,\n                        data: {\n                            line: row,\n                            column: col,\n                            text: text,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['jikko_make.module_digital_lcd(%1, %2)'] },\n        },\n        jikko_make_lcd_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'jikko_make_lcd_clear',\n            },\n            class: 'jikko_makeModule',\n            isNotFor: ['jikko_make'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.jikko_make.sensorTypes.LCDCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n        jikko_make_get_dht: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['온도(°C)', '0'],\n                        ['습도(%)', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'jikko_make_get_dht',\n            },\n            paramsKeyMap: {\n                DHT_SELECT: 0,\n            },\n            class: 'jikko_makeGet',\n            isNotFor: ['jikko_make'],\n            func: function(sprite, script) {\n                var port = 3;\n                var type = script.getNumberValue('DHT_SELECT');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                if (type == 0) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko_make.sensorTypes.DHTTEMP] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTTEMP || 0;\n                } else if (type == 1) {\n                    Entry.hw.sendQueue['GET'][Entry.jikko_make.sensorTypes.DHTHUMI] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return Entry.hw.portData.DHTHUMI || 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [{}],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.jikko_make;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_jinirobot_aibot.js",
    "content": "'use strict';\n\nEntry.aibot = {\n    id: ['4C.1'],\n    name: 'aibot',\n    url: 'http://www.jinirobot.com',\n    imageName: 'jinirobot_aibot.png',\n    title: {\n        ko: 'AIBOT',\n        en: 'AIBOT',\n    },\n    array: {        \n\t\tSERVO_CONTROL: 0,\n\t\tHOME_CONTROL: 1,\n\t\tPORT_CONTROL: 2,\n\t\tPORT_OUT_CONTROL: 3,\n\t\tBUZZ_CONTROL: 4,\n        SERVO_SPEED: 5,\n        SET_SERVO_OFFSET_ZERO:6 ,\n        SET_SERVO_HOME_POS: 7,\n        AIDESK_CONTROL: 8,\n        REMOTE_DEVICE: 9,\n        CONNECT_DEVICE: 10,\n    },\n\n    delayTime: 50,\n    timeouts: [],\n\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    \n    setZero() {\n        \n    },\n    BlockState: {},\n    monitorTemplate: {\n        width: 400,\n        height: 600,\n        listPorts: {\n            A0: {\n                name: 'D1',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A1: {\n                name: 'D2',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A2: {\n                name: 'D3',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A3: {\n                name: 'D4',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A4: {\n                name: 'A1',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A5: {\n                name: 'A2',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A6: {\n                name: 'A3',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A7: {\n                name: 'A4',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A8: {\n                name: 'RD1',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A9: {\n                name: 'RD2',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A10: {\n                name: 'RD3',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A11: {\n                name: 'RD4',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A12: {\n                name: 'RA1',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A13: {\n                name: 'RA2',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A14: {\n                name: 'RA3',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            A15: {\n                name: 'RA4',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            \n            AD0: {\n                name: 'AID1',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            AD1: {\n                name: 'AID2',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            AD2: {\n                name: 'AID3',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            AD3: {\n                name: 'AID4',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            AD4: {\n                name: 'AID5',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            AD5: {\n                name: 'AID6',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n\n        },\n        mode: 'both',\n    },\n};\n\nEntry.aibot.setLanguage = function() {\n    return {\n        ko: {\n            template: {                \n                aibot_analog_read: '아날로그 %1번 입력값',\n                aibot_digital_read: '디지털 %1번 입력값',\n                aibot_set_port: '입출력 %1번을 %2(으)로 설정%3',\n                aibot_set_port_out: '디지털출력 %1번 %2 %3',\n                aibot_buzzer_play: '%1 효과음 재생하기 %2',\n                aibot_set_servo_speed: '제어속도를 %1로 정하기 %2',\n                aibot_set_servo_angle_single_numtype: '모듈 %1을 %2각도로 제어%3',\n                aibot_set_servo_angle_single: '모듈 %1을 %2각도로 제어%3',                \n                aibot_set_servo_angle_123: '모듈 1%1, 2%2, 3%3 각도로 제어%4',\n                aibot_set_servo_angle_1234: '모듈 1%1, 2%2, 3%3, 4%4 각도로 제어%5',\n                aibot_set_servo_angle_56: '모듈 5%1, 6%2 각도로 제어%3',                \n                aibot_set_servo_angle_123456: '모듈 1%1, 2%2, 3%3, 4%4, 5%5, 6%6 각도로 제어%7',\n                aibot_set_servo_go_home: '모든 모듈을 기본위치로 제어하기(원점복귀) %1',\n                aibot_set_set_offset_zero: '모든 설정값 공장초기화 %1',\n                //aibot_set_servo_home_pos_angle: '%1번 모듈의 기본위치 각도를 %2도로 설정하기%3',\n                aibot_set_servo_home_pos_current: '%1번 모듈의 90도 위치를 현재의 위치로 정하기%2',\n                aibot_set_remote_servo_speed: '원격의 제어속도를 %1로 정하기 %2',\n                aibot_set_remote_servo_angle_single: '원격모듈 %1을 %2각도로 제어%3',    \n                aibot_set_remote_servo_angle_single_numtype: '원격모듈 %1을 %2각도로 제어%3',              \n                aibot_set_remote_servo_angle_123: '원격모듈 1%1, 2%2, 3%3 각도로 제어%4',\n                aibot_set_remote_servo_angle_1234: '원격모듈 1%1, 2%2, 3%3, 4%4 각도로 제어%5',\n                aibot_set_remote_servo_angle_56: '원격모듈 5%1, 6%2 각도로 제어%3',\n                aibot_set_remote_servo_angle_123456: '원격모듈 1%1, 2%2, 3%3, 4%4, 5%5, 6%6 각도로 제어%7',\n                aibot_set_remote_servo_go_home: '원격의 모든 모듈을 기본위치로 제어하기(원점복귀) %1',\n                //aibot_aidesk_read_string: 'AI Desk의 %1번 문자열 반환값 가져오기 %2',  \n                aibot_aidesk_read_number: 'AI Desk의 %1번 값%2', \n                aibot_aidesk_control_basic: 'AI Desk의 %1번 기능 시작하기(변수1:%2, 변수2:%3, 변수3:%4, 변수4:%5)%6',\n                aibot_aidesk_func_stop: 'AI Desk의 %1번 기능 정지하기%2',\n                aibot_set_remote_device: '원격 디바이스 설정%1',\n\n                remote1: '원격1',\n                remote2: '원격2',\n                remote3: '원격3',\n                remote4: '원격4',\n                digitalInput: '디지털입력',\n                digitalOutput: '디지털출력',\n                analogInput: '아날로그입력', \n                on: '켜기',\n                off: '끄기',   \n            },\n        },\n        en: {\n            template: {\n                aibot_analog_read: '%1 read analog',\n                aibot_digital_read: '%1 read digital',\n                aibot_set_port: 'PORT %1 SET TO %2 %3',\n                aibot_set_port_out: 'PORT %1 OUT %2 %3',\n                aibot_buzzer_play: '%1 play melody %2',\n                aibot_set_servo_speed: 'Control Speed %1 %2',\n                aibot_set_servo_angle_single_numtype: '%1 SERVO %2 DEGREE %3',\n                aibot_set_servo_angle_single: '%1 SERVO %2 DEGREE %3',\n                aibot_set_servo_angle_123: 'Module control degree 1%1, 2%2 3%3 %4', \n                aibot_set_servo_angle_1234: 'Module control degree 1%1, 2%2, 3%3, 4%4 %5',    \n                aibot_set_servo_angle_56: 'Module control degree 5%1, 6%2 %3',      \n                aibot_set_servo_angle_123456: 'Module control degree 1%1, 2%2, 3%3, 4%4, 5%5, 6%6 %7',        \n                aibot_set_servo_go_home: 'Module Home Position %1',\n                aibot_set_set_offset_zero: 'Factory reset %1',\n                //aibot_set_servo_home_pos_angle: 'Servo %1 Set Home Position to %2degree %3',\n                aibot_set_servo_home_pos_current: 'Servo %1 Set Home Position to current %2',\n                aibot_set_remote_servo_speed: 'Remote Control Speed %1 %2',\n                aibot_set_remote_servo_angle_single_numtype: 'Remote %1 Module %2 DEGREE %3',\n                aibot_set_remote_servo_angle_single: 'Remote %1 Module %2 DEGREE %3',\n                aibot_set_remote_servo_angle_123: 'Remote Module control degree 1%1, 2%2 3%3 %4',\n                aibot_set_remote_servo_angle_1234: 'Remote Module control degree 1%1, 2%2, 3%3, 4%4 %5',      \n                aibot_set_remote_servo_angle_56: 'Remote Module control degree 5%1, 6%2 %3', \n                aibot_set_remote_servo_angle_123456: 'Remote Module control degree 1%1, 2%2, 3%3, 4%4, 5%5, 6%6 %7', \n                aibot_set_remote_servo_go_home: 'Remote Module Home Position %1',\n                //aibot_aidesk_read_string: 'Read String %1 of AIDesk %2',  \n                aibot_aidesk_read_number: 'Read Number %1 of AIDesk %2',  \n                aibot_aidesk_control_basic: 'Start Function%1 of AI Desk(Var1:%2, Var2:%3, Var3:%4, Var4:%5)%6',\n                aibot_aidesk_func_stop: 'Stop Function%1 of AI Desk%2',\n                aibot_set_remote_device: 'Set Remote Device%1',\n            \n                remote1: 'REMOTE1',\n                remote2: 'REMOTE2',\n                remote3: 'REMOTE3',\n                remote4: 'REMOTE4',                \n                digitalInput: 'DIGITAL INPUT',\n                digitalOutput: 'DIGITAL OUTPUT',\n                analogInput: 'ANALOG INPUT',                      \n                on: 'ON',\n                off: 'OFF', \n            }\n        },\n    };\n};\n\nEntry.aibot.blockMenuBlocks = [  \n    'aibot_analog_read',    \n    'aibot_digital_read',\n    'aibot_set_port',\n    'aibot_set_port_out',\n    'aibot_buzzer_play',\n    'aibot_set_servo_speed',\n    'aibot_set_servo_angle_single_numtype',\n    'aibot_set_servo_angle_single',    \n    'aibot_set_servo_angle_123',\n    'aibot_set_servo_angle_1234',\n    'aibot_set_servo_angle_56',\n    'aibot_set_servo_angle_123456',\n    'aibot_set_servo_go_home',\n    //'aibot_set_servo_home_pos_angle',\n    'aibot_set_servo_home_pos_current',    \n    'aibot_set_set_offset_zero',\n    'aibot_set_remote_servo_speed',\n    'aibot_set_remote_servo_angle_single_numtype',\n    'aibot_set_remote_servo_angle_single',\n    'aibot_set_remote_servo_angle_123',\n    'aibot_set_remote_servo_angle_1234',\n    'aibot_set_remote_servo_angle_56',\n    'aibot_set_remote_servo_angle_123456',\n    'aibot_set_remote_servo_go_home',\n    'aibot_set_remote_device',\n    //'aibot_aidesk_read_string',\n    'aibot_aidesk_read_number',\n    'aibot_aidesk_control_basic',\n    'aibot_aidesk_func_stop',\n];\n\nEntry.aibot.getBlocks = function() {\n    return {   \n        ///======================================================================================================================\n        ///======================================================================================================================\n        ///======================================================================================================================\n        aibot_analog_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        [Lang.template.remote1, '4'],\n                        [Lang.template.remote2, '5'],\n                        [Lang.template.remote3, '6'],\n                        [Lang.template.remote4, '7'],\n                    ],\n                    value: '0',   \n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_analog_read',\n            },\n            paramsKeyMap: {                    \n                VALUE: 0,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) { \n                var value = script.getNumberValue('VALUE',script);  \n                if(value<4){\n                    value = value + 4;\n                    var result = Entry.hw.portData.SENSOR[value];\n                }    \n                else if(value>=4){\n                    value = value + 8;\n                    var result = Entry.hw.portData.SENSOR[value];\n                }              \n                return result;\n            },\n        },\n        aibot_digital_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        [Lang.template.remote1, '4'],\n                        [Lang.template.remote2, '5'],\n                        [Lang.template.remote3, '6'],\n                        [Lang.template.remote4, '7'],\n                    ],\n                    value: '0',   \n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_digital_read',\n            },\n            paramsKeyMap: {                    \n                VALUE: 0,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) { \n                var value = script.getNumberValue('VALUE',script); \n                if(value<4){\n                    value = value;\n                    var result = Entry.hw.portData.SENSOR[value];\n                }  \n                else if(value>=4){\n                    value = value + 4;\n                    var result = Entry.hw.portData.SENSOR[value];\n                }  \n                return result;\n            },\n        },\n        aibot_set_port: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        [Lang.template.remote1, '4'],\n                        [Lang.template.remote2, '5'],\n                        [Lang.template.remote3, '6'],\n                        [Lang.template.remote4, '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        [Lang.template.digitalInput, '0'],\n                        [Lang.template.digitalOutput, '1'],\n                        [Lang.template.analogInput, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_set_port',    \n            },\n            paramsKeyMap: {                    \n                PORT: 0,\n                MODE: 1,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var portVal = script.getNumberValue('PORT', script);\n                    var modeVal = script.getNumberValue('MODE', script);\n                    var remote = 1;\n                    if(portVal>=4){\n                        remote = 2;\n                        portVal=portVal-4;\n                    }\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.PORT_CONTROL] = {\n                        remote: remote,\n                        port: portVal,\n                        mode: modeVal,\n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_port_out: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        [Lang.template.remote1, '4'],\n                        [Lang.template.remote2, '5'],\n                        [Lang.template.remote3, '6'],\n                        [Lang.template.remote4, '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        [Lang.template.on, '1'],\n                        [Lang.template.off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_set_port_out',    \n            },\n            paramsKeyMap: {                    \n                PORT: 0,\n                VAL: 1,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var portVal = script.getNumberValue('PORT', script);\n                    var Val = script.getNumberValue('VAL', script);\n                    var remote = 1;\n                    if(portVal>=4){\n                        remote = 2;\n                        portVal=portVal-4;\n                    }\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.PORT_OUT_CONTROL] = {\n                        remote: remote,\n                        port: portVal,\n                        val: Val,\n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_buzzer_play: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_buzzer_play',    \n            },\n            paramsKeyMap: {                    \n                MELODY: 0,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Melody = script.getNumberValue('MELODY', script);\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.BUZZ_CONTROL] = {\n                        remote: Remote,\n                        melody: Melody,\n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '1',\n                    fontSize: 12,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_set_servo_speed',    \n            },\n            paramsKeyMap: {                    \n                SPEED: 0,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Speed = script.getNumberValue('SPEED', script);\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_SPEED] = {\n                        remote: Remote,\n                        speed: Speed,\n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_angle_single_numtype: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },   \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1,90],\n                type: 'aibot_set_servo_angle_single_numtype',    \n            },\n            paramsKeyMap: {                    \n                SERVO: 0,\n                ANGLE: 1,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;  \n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=0;var Servo2=0;var Servo3=0;\n                    var Servo4=0;var Servo5=0;var Servo6=0;\n                    var Servo = script.getNumberValue('SERVO', script);\n                    var Angle = script.getNumberValue('ANGLE', script);\n                                        \n                    if(Angle<0)Angle = 0;if(Angle>180)Angle = 180;Angle = Angle*10 + 700;                    \n\n                    if(Servo==1)Servo1 = Angle;\n                    else if(Servo==2)Servo2 = Angle;\n                    else if(Servo==3)Servo3 = Angle;\n                    else if(Servo==4)Servo4 = Angle;\n                    else if(Servo==5)Servo5 = Angle;\n                    else if(Servo==6)Servo6 = Angle;                   \n\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_angle_single: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '1',\n                    fontSize: 12,\n                },   \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1,90],\n                type: 'aibot_set_servo_angle_single',    \n            },\n            paramsKeyMap: {                    \n                SERVO: 0,\n                ANGLE: 1,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=0;var Servo2=0;var Servo3=0;\n                    var Servo4=0;var Servo5=0;var Servo6=0;\n                    var Servo = script.getNumberValue('SERVO', script);\n                    var Angle = script.getNumberValue('ANGLE', script);\n                                        \n                    if(Angle<0)Angle = 0;if(Angle>180)Angle = 180;Angle = Angle*10 + 700;                    \n\n                    if(Servo==1)Servo1 = Angle;\n                    else if(Servo==2)Servo2 = Angle;\n                    else if(Servo==3)Servo3 = Angle;\n                    else if(Servo==4)Servo4 = Angle;\n                    else if(Servo==5)Servo5 = Angle;\n                    else if(Servo==6)Servo6 = Angle;                   \n\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_servo_angle_1234: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['90','90','90','90'],\n                type: 'aibot_set_remote_servo_angle_1234',    \n            },\n            paramsKeyMap: {                    \n                SERVO1: 0,\n                SERVO2: 1,\n                SERVO3: 2,\n                SERVO4: 3,\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=script.getNumberValue('SERVO1', script);\n                    var Servo2=script.getNumberValue('SERVO2', script);\n                    var Servo3=script.getNumberValue('SERVO3', script);\n                    var Servo4=script.getNumberValue('SERVO4', script);\n                    if(Servo1<0)Servo1 = 0;if(Servo1>180)Servo1 = 180;Servo1 = Servo1*10 + 700;  \n                    if(Servo2<0)Servo2 = 0;if(Servo2>180)Servo2 = 180;Servo2 = Servo2*10 + 700;  \n                    if(Servo3<0)Servo3 = 0;if(Servo3>180)Servo3 = 180;Servo3 = Servo3*10 + 700;  \n                    if(Servo4<0)Servo4 = 0;if(Servo4>180)Servo4 = 180;Servo4 = Servo4*10 + 700;  \n\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: 0,\n                        servo6: 0,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_servo_angle_123456: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['90','90','90','90','90','90'],\n                type: 'aibot_set_remote_servo_angle_123456',    \n            },\n            paramsKeyMap: {                    \n                SERVO1: 0,\n                SERVO2: 1,\n                SERVO3: 2,\n                SERVO4: 3,\n                SERVO5: 4,\n                SERVO6: 5,\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=script.getNumberValue('SERVO1', script);\n                    var Servo2=script.getNumberValue('SERVO2', script);\n                    var Servo3=script.getNumberValue('SERVO3', script);\n                    var Servo4=script.getNumberValue('SERVO4', script);\n                    var Servo5=script.getNumberValue('SERVO5', script);\n                    var Servo6=script.getNumberValue('SERVO6', script);\n                    if(Servo1<0)Servo1 = 0;if(Servo1>180)Servo1 = 180;Servo1 = Servo1*10 + 700;  \n                    if(Servo2<0)Servo2 = 0;if(Servo2>180)Servo2 = 180;Servo2 = Servo2*10 + 700;  \n                    if(Servo3<0)Servo3 = 0;if(Servo3>180)Servo3 = 180;Servo3 = Servo3*10 + 700;  \n                    if(Servo4<0)Servo4 = 0;if(Servo4>180)Servo4 = 180;Servo4 = Servo4*10 + 700;  \n                    if(Servo5<0)Servo5 = 0;if(Servo5>180)Servo5 = 180;Servo5 = Servo5*10 + 700;  \n                    if(Servo6<0)Servo6 = 0;if(Servo6>180)Servo6 = 180;Servo6 = Servo6*10 + 700;  \n\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_angle_123456: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['90','90','90','90','90','90'],\n                type: 'aibot_set_servo_angle_123456',    \n            },\n            paramsKeyMap: {                    \n                SERVO1: 0,\n                SERVO2: 1,\n                SERVO3: 2,\n                SERVO4: 3,\n                SERVO5: 4,\n                SERVO6: 5,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=script.getNumberValue('SERVO1', script);\n                    var Servo2=script.getNumberValue('SERVO2', script);\n                    var Servo3=script.getNumberValue('SERVO3', script);\n                    var Servo4=script.getNumberValue('SERVO4', script);\n                    var Servo5=script.getNumberValue('SERVO5', script);\n                    var Servo6=script.getNumberValue('SERVO6', script);\n                    if(Servo1<0)Servo1 = 0;if(Servo1>180)Servo1 = 180;Servo1 = Servo1*10 + 700;  \n                    if(Servo2<0)Servo2 = 0;if(Servo2>180)Servo2 = 180;Servo2 = Servo2*10 + 700;  \n                    if(Servo3<0)Servo3 = 0;if(Servo3>180)Servo3 = 180;Servo3 = Servo3*10 + 700;  \n                    if(Servo4<0)Servo4 = 0;if(Servo4>180)Servo4 = 180;Servo4 = Servo4*10 + 700;  \n                    if(Servo5<0)Servo5 = 0;if(Servo5>180)Servo5 = 180;Servo5 = Servo5*10 + 700;  \n                    if(Servo6<0)Servo6 = 0;if(Servo6>180)Servo6 = 180;Servo6 = Servo6*10 + 700;  \n\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_angle_1234: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['90','90','90','90'],\n                type: 'aibot_set_servo_angle_1234',    \n            },\n            paramsKeyMap: {                    \n                SERVO1: 0,\n                SERVO2: 1,\n                SERVO3: 2,\n                SERVO4: 3,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=script.getNumberValue('SERVO1', script);\n                    var Servo2=script.getNumberValue('SERVO2', script);\n                    var Servo3=script.getNumberValue('SERVO3', script);\n                    var Servo4=script.getNumberValue('SERVO4', script);\n                    if(Servo1<0)Servo1 = 0;if(Servo1>180)Servo1 = 180;Servo1 = Servo1*10 + 700;  \n                    if(Servo2<0)Servo2 = 0;if(Servo2>180)Servo2 = 180;Servo2 = Servo2*10 + 700;  \n                    if(Servo3<0)Servo3 = 0;if(Servo3>180)Servo3 = 180;Servo3 = Servo3*10 + 700;  \n                    if(Servo4<0)Servo4 = 0;if(Servo4>180)Servo4 = 180;Servo4 = Servo4*10 + 700;                     \n\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: 0,\n                        servo6: 0,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_angle_123: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['90','90','90'],\n                type: 'aibot_set_servo_angle_123',    \n            },\n            paramsKeyMap: {                    \n                SERVO1: 0,\n                SERVO2: 1,\n                SERVO3: 2,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=script.getNumberValue('SERVO1', script);\n                    var Servo2=script.getNumberValue('SERVO2', script);\n                    var Servo3=script.getNumberValue('SERVO3', script);\n                    var Servo4=0;var Servo5=0;var Servo6=0;\n                    if(Servo1<0)Servo1 = 0;if(Servo1>180)Servo1 = 180;Servo1 = Servo1*10 + 700;  \n                    if(Servo2<0)Servo2 = 0;if(Servo2>180)Servo2 = 180;Servo2 = Servo2*10 + 700;  \n                    if(Servo3<0)Servo3 = 0;if(Servo3>180)Servo3 = 180;Servo3 = Servo3*10 + 700;  \n\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_angle_56: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [     \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['90','90'],\n                type: 'aibot_set_servo_angle_56',    \n            },\n            paramsKeyMap: {                    \n                SERVO5: 0,\n                SERVO6: 1,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=0;var Servo2=0;var Servo3=0;\n                    var Servo4=0;\n                    var Servo5=script.getNumberValue('SERVO5', script);\n                    var Servo6=script.getNumberValue('SERVO6', script);\n                    if(Servo5<0)Servo5 = 0;if(Servo5>180)Servo5 = 180;Servo5 = Servo5*10 + 700;  \n                    if(Servo6<0)Servo6 = 0;if(Servo6>180)Servo6 = 180;Servo6 = Servo6*10 + 700;  \n                    \n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_servo_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '1',\n                    fontSize: 12,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_set_remote_servo_speed',    \n            },\n            paramsKeyMap: {                    \n                SPEED: 0,\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Speed = script.getNumberValue('SPEED', script);\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_SPEED] = {\n                        remote: Remote,\n                        speed: Speed,\n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_servo_angle_single_numtype: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1,90],\n                type: 'aibot_set_remote_servo_angle_single_numtype',    \n            },\n            paramsKeyMap: {                    \n                SERVO: 0,\n                ANGLE: 1,\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=0,Servo2=0,Servo3=0;\n                    var Servo4=0,Servo5=0,Servo6=0;\n                    var Servo = script.getNumberValue('SERVO', script);\n                    var Angle = script.getNumberValue('ANGLE', script);\n                                        \n                    if(Angle<0)Angle = 0;if(Angle>180)Angle = 180;Angle = Angle*10 + 700;                    \n\n                    if(Servo==1)Servo1 = Angle;\n                    else if(Servo==2)Servo2 = Angle;\n                    else if(Servo==3)Servo3 = Angle;\n                    else if(Servo==4)Servo4 = Angle;\n                    else if(Servo==5)Servo5 = Angle;\n                    else if(Servo==6)Servo6 = Angle;                   \n\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_servo_angle_single: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '1',\n                    fontSize: 12,\n                },   \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1,90],\n                type: 'aibot_set_remote_servo_angle_single',    \n            },\n            paramsKeyMap: {                    \n                SERVO: 0,\n                ANGLE: 1,\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=0,Servo2=0,Servo3=0;\n                    var Servo4=0,Servo5=0,Servo6=0;\n                    var Servo = script.getNumberValue('SERVO', script);\n                    var Angle = script.getNumberValue('ANGLE', script);\n                                        \n                    if(Angle<0)Angle = 0;if(Angle>180)Angle = 180;Angle = Angle*10 + 700;                    \n\n                    if(Servo==1)Servo1 = Angle;\n                    else if(Servo==2)Servo2 = Angle;\n                    else if(Servo==3)Servo3 = Angle;\n                    else if(Servo==4)Servo4 = Angle;\n                    else if(Servo==5)Servo5 = Angle;\n                    else if(Servo==6)Servo6 = Angle;                   \n\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_servo_angle_123: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['90','90','90'],\n                type: 'aibot_set_remote_servo_angle_123',    \n            },\n            paramsKeyMap: {                    \n                SERVO1: 0,\n                SERVO2: 1,\n                SERVO3: 2,\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=script.getNumberValue('SERVO1', script);\n                    var Servo2=script.getNumberValue('SERVO2', script);\n                    var Servo3=script.getNumberValue('SERVO3', script);\n                    var Servo4=0;var Servo5=0;var Servo6=0;\n                    if(Servo1<0)Servo1 = 0;if(Servo1>180)Servo1 = 180;Servo1 = Servo1*10 + 700;  \n                    if(Servo2<0)Servo2 = 0;if(Servo2>180)Servo2 = 180;Servo2 = Servo2*10 + 700;  \n                    if(Servo3<0)Servo3 = 0;if(Servo3>180)Servo3 = 180;Servo3 = Servo3*10 + 700;  \n\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_servo_angle_56: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [     \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['90','90'],\n                type: 'aibot_set_remote_servo_angle_56',    \n            },\n            paramsKeyMap: {                    \n                SERVO5: 0,\n                SERVO6: 1,\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=0;var Servo2=0;var Servo3=0;\n                    var Servo4=0;\n                    var Servo5=script.getNumberValue('SERVO5', script);\n                    var Servo6=script.getNumberValue('SERVO6', script);\n                    if(Servo5<0)Servo5 = 0;if(Servo5>180)Servo5 = 180;Servo5 = Servo5*10 + 700;  \n                    if(Servo6<0)Servo6 = 0;if(Servo6>180)Servo6 = 180;Servo6 = Servo6*10 + 700;  \n                    \n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SERVO_CONTROL] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_go_home: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_set_servo_go_home',    \n            },\n            paramsKeyMap: {\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {      \n                    var sq = Entry.hw.sendQueue;\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.HOME_CONTROL] = {\n                        remote: Remote,                      \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_servo_go_home: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_set_remote_servo_go_home',    \n            },\n            paramsKeyMap: {\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {      \n                    var sq = Entry.hw.sendQueue;\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.HOME_CONTROL] = {\n                        remote: Remote,                      \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_home_pos_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '1',\n                    fontSize: 12,\n                },   \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1,90],\n                type: 'aibot_set_servo_home_pos_angle',    \n            },\n            paramsKeyMap: {                    \n                SERVO: 0,\n                ANGLE: 1,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=0;var Servo2=0;var Servo3=0;\n                    var Servo4=0;var Servo5=0;var Servo6=0;\n                    var Servo = script.getNumberValue('SERVO', script);\n                    var Angle = script.getNumberValue('ANGLE', script);\n                                        \n                    if(Angle<0)Angle = 0;if(Angle>180)Angle = 180;\n                    if(Servo==1 || Servo==5 )Angle = 90+Angle;\n                    \n                    Angle = Angle*10 + 700;                    \n\n                    if(Servo==1)Servo1 = Angle;\n                    else if(Servo==2)Servo2 = Angle;\n                    else if(Servo==3)Servo3 = Angle;\n                    else if(Servo==4)Servo4 = Angle;\n                    else if(Servo==5)Servo5 = Angle;\n                    else if(Servo==6)Servo6 = Angle;                   \n\n                    var Remote = 3;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SET_SERVO_HOME_POS] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_servo_home_pos_current: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '1',\n                    fontSize: 12,\n                },   \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'aibot_set_servo_home_pos_current',    \n            },\n            paramsKeyMap: {                    \n                SERVO: 0,\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Servo1=0;var Servo2=0;var Servo3=0;\n                    var Servo4=0;var Servo5=0;var Servo6=0;\n                    var Servo = script.getNumberValue('SERVO', script);               \n\n                    if(Servo==1)Servo1 = 1;\n                    else if(Servo==2)Servo2 = 1;\n                    else if(Servo==3)Servo3 = 1;\n                    else if(Servo==4)Servo4 = 1;\n                    else if(Servo==5)Servo5 = 1;\n                    else if(Servo==6)Servo6 = 1;                   \n\n                    var Remote = 4;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SET_SERVO_HOME_POS] = {\n                        remote: Remote,\n                        servo1: Servo1,\n                        servo2: Servo2,\n                        servo3: Servo3,\n                        servo4: Servo4,\n                        servo5: Servo5,\n                        servo6: Servo6,                        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_set_offset_zero: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_set_set_offset_zero',    \n            },\n            paramsKeyMap: {\n            },\n            class: 'aibot',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {      \n                    var sq = Entry.hw.sendQueue;\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.SET_SERVO_OFFSET_ZERO] = {\n                        remote: Remote,                      \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_aidesk_read_string: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'aibot_aidesk_read_string',\n            },\n            paramsKeyMap: {                    \n                VALUE: 0,\n            },\n            class: 'aibot_aidesk',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) { \n                var value = script.getNumberValue('VALUE',script);  \n                result = Entry.hw.portData.SENSOR[19];\n                return result;\n            },\n        },\n        aibot_aidesk_read_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'aibot_aidesk_read_number',\n            },\n            paramsKeyMap: {                    \n                VALUE: 0,\n            },\n            class: 'aibot_aidesk',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) { \n                var value = script.getNumberValue('VALUE',script); \n                if(value>6)value=6; \n                if(value<1)value=1; \n                var result = Entry.hw.portData.AIDESK[value-1];\n                return result;\n            },\n        },\n        aibot_aidesk_control_basic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1','0','0','0','0'],\n                type: 'aibot_aidesk_control_basic',    \n            },\n            paramsKeyMap: {                    \n                FUNC: 0,\n                VAR1: 1,\n                VAR2: 2,\n                VAR3: 3,\n                VAR4: 4,\n            },\n            class: 'aibot_aidesk',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Func=script.getNumberValue('FUNC', script);\n                    var Var1=script.getNumberValue('VAR1', script);\n                    var Var2=script.getNumberValue('VAR2', script); \n                    var Var3=script.getNumberValue('VAR3', script); \n                    var Var4=script.getNumberValue('VAR4', script); \n\n                    if(Var1>2000)Var1=2000;\n                    if(Var1<-2000)Var1=-2000;\n                    if(Var2>2000)Var2=2000;\n                    if(Var2<-2000)Var2=-2000;\n                    if(Var3>2000)Var3=2000;\n                    if(Var3<-2000)Var3=-2000;\n                    if(Var4>2000)Var4=2000;\n                    if(Var4<-2000)Var4=-2000;\n\n                    var Remote = 1;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.AIDESK_CONTROL] = {\n                        remote: Remote,\n                        func: Func,\n                        var1: Var1, \n                        var2: Var2,\n                        var3: Var3,    \n                        var4: Var4,                    \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_aidesk_func_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1'],\n                type: 'aibot_aidesk_func_stop',    \n            },\n            paramsKeyMap: {                    \n                FUNC: 0,\n            },\n            class: 'aibot_aidesk',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Func=script.getNumberValue('FUNC', script);\n                    var Var1 = 0;\n                    var Var2 = 0;\n                    var Var3 = 0;\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.AIDESK_CONTROL] = {\n                        remote: Remote,      \n                        func: Func,    \n                        var1: Var1,\n                        var2: Var2, \n                        var3: Var3,        \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n        aibot_set_remote_device: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [  \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'aibot_set_remote_device',    \n            },\n            paramsKeyMap: {                    \n                FUNC: 0,\n            },\n            class: 'aibot_remote',\n            isNotFor: ['aibot'],\n            func: function(sprite, script) {\n                if(!script.isStart)\n                {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.aibot.removeTimeout(timer);\n                    }, Entry.aibot.delayTime);\n                    Entry.aibot.timeouts.push(timer);\n                    return script;\n                }\n                else if(script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else\n                {\n                    var sq = Entry.hw.sendQueue;\n                    var Var1 = 1;\n                    var Var2 = 1;\n                    var Var3 = 1;\n                    var Remote = 2;\n                    sq['SEND'] = {};\n                    sq['SEND'][Entry.aibot.array.REMOTE_DEVICE] = {\n                        remote: Remote,      \n                        var1: Var1,    \n                        var2: Var2,\n                        var3: Var3,         \n                        Time: new Date().getTime(),\n                    };\n                    return script.callReturn(); \n                }\n            },\n        },\n\n\n\n    };\n};\n\nmodule.exports = Entry.aibot;"
  },
  {
    "path": "src/playground/blocks/hardware/block_jinirobot_toybot.js",
    "content": "'use strict';\n\nEntry.toybot = {\n    id: ['4C.2'],\n    name: 'toybot',\n    url: 'http://www.jinirobot.com',\n    imageName: 'jinirobot_toybot.png',\n    title: {\n        ko: 'ToyBot',\n        en: 'ToyBot',\n    },\n    delayTime: 0.01,\n    timeouts: [],\n    scoreFlag: false,\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },    \n    setZero: function() {\n        Entry.hw.sendQueue['setblock'] = {\n            id: Math.random(),\n            setZero: 1\n        };\n        Entry.hw.update();\n        this.setCount = 0;\n    },\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    convert: function(value) {\n        const temp = Number(value);\n        return isNaN(temp) ? value : temp;\n    },\n    checkRangeInteger: function(value, min, max) {\n        if (isNaN(value)) {\n            return 0;\n        } else {\n            let temp = parseInt(Math.round(value));\n            if (temp < min)\n                temp = min;\n            else if (temp > max)\n                temp = max;\n            return temp;\n        }\n    },\n    setProcessor: function(script, delayTime, code) {\n        if (!script.isStart) {\n            script.isStart = true;\n            script.timeFlag = 1;\n            const fps = Entry.FPS || 60;\n            const timeValue = (60 / fps) * delayTime * 1000;\n            Entry.TimeWaitManager.add(\n                Math.random(),\n                () => {\n                    script.timeFlag = 0;\n                },\n                timeValue\n            );\n            Entry.toybot.scoreFlag = code();\n            return script;\n        } else if (script.timeFlag == 1) {\n            return script;\n        } else {\n            if (Entry.toybot.scoreFlag === true) {\n                Entry.hw.sendQueue['setblock'] = {\n                    id: Math.random(),\n                    playScore: {\n                        beat: 0x0B,\n                        pitch: 0,\n                    }\n                };\n                Entry.hw.update();\n            }\n\n            delete script.timeFlag;\n            delete script.isStart;\n            Entry.engine.isContinue = false;\n            return script.callReturn();\n        }\n    },\n};\n\nEntry.toybot.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                list_all: '모두',\n                list_button_a: 'A',\n                list_button_b: 'B',\n                list_color_white: '흰색',\n                list_color_red: '빨간색',\n                list_color_orange: '주황색',\n                list_color_yellow: '노란색',\n                list_color_green: '초록색',\n                list_color_blue: '파란색',\n                list_color_navy: '남색',\n                list_color_violet: '보라색',\n                list_color_off: '끄기',\n                list_accidental_natural: '기본음',\n                list_accidental_sharp: '반올림',\n                list_accidental_flat: '반내림',\n                list_beat_oneeight: '1/8박',\n                list_beat_onefour: '1/4박',\n                list_beat_onetwo: '1/2박',\n                list_beat_one: '1박',\n                list_beat_onehalf: '1.5박',\n                list_beat_two: '2박',\n                list_beat_three: '3박',\n                list_beat_four: '4박',\n                list_octave_low: '낮은',\n                list_octave_middle: '보통',\n                list_octave_high: '높은',\n                list_pitch_c: '도',\n                list_pitch_d: '레',\n                list_pitch_e: '미',\n                list_pitch_f: '파',\n                list_pitch_g: '솔',\n                list_pitch_a: '라',\n                list_pitch_b: '시',\n                list_pitch_r: '쉼표',\n                list_rotation_forward: '정회전',\n                list_rotation_reverse: '역회전',\n                list_rotation_stop: '정지',\n                get_ultrasonic_distance: '초음파센서 거리값',\n                get_button_state: '%1 버튼 값',\n                get_analog_input: '아날로그 입력 값',\n                get_servo_angle: '%1번 서보모터 각도 값',\n                set_led_color_name: 'LED의 색깔을 %1(으)로 정하기 %2',\n                set_led_rgb: 'LED의 색깔을 빨강 %1, 초록 %2, 파랑 %3(으)로 바꾸기 %4',                \n                set_play_score: '음표를 %1 %2 %3 %4으로 연주하기 %5',\n                set_play_sound_effect: '%1번 효과음 연주하기 %2',\n                set_play_melody: '%1번 멜로디 연주하기 %2',\n                set_servo_each: '서보모터 %1을(를) 속도 %2, 각도 %3으로 회전하기 %4',\n                set_servo_all: '모든 서보모터를 속도 %1, 각도 %2, %3, %4, %5, %6(으)로 회전하기 %7',\n                set_servo_home: '모든 서보모터를 속도 %1, 기본위치로 제어하기 %2',\n                set_analog_output: '아날로그 출력값을 %1(으)로 정하기 %2',\n                set_dc_run: 'DC 모터 %1을(를) 속도 %2(으)로 %3 하기 %4 ',                \n                set_servo_offset: '서보모터 %1 의 각도 90°를 현재 위치로 정하기%2',\n                set_servo_reset: '모든 설정값을 공장초기화 하기 %1',\n\n\n\n                warning_index: '항목 없음',\n                warning_over_range: '측정 범위 초과',\n            },\n        },\n        en: {\n            template: {\n                list_all: 'All',\n                list_button_a: 'A',\n                list_button_b: 'B',\n                list_color_white: 'White',\n                list_color_red: 'Red',\n                list_color_orange: 'Orange',\n                list_color_yellow: 'Yellow',\n                list_color_green: 'Green',\n                list_color_blue: 'Blue',\n                list_color_navy: 'Navy',\n                list_color_violet: 'Violet',\n                list_color_off: 'Off',\n                list_accidental_natural: 'Natural',\n                list_accidental_sharp: 'Sharp',\n                list_accidental_flat: 'Flat',\n                list_beat_oneeight: '1/8 of a beats',\n                list_beat_onefour: '1/4 of a beats',\n                list_beat_onetwo: '1/2 of a beats',\n                list_beat_one: '1 beat',\n                list_beat_onehalf: '1.5 beats',\n                list_beat_two: '2 beats',\n                list_beat_three: '3 beats',\n                list_beat_four: '4 beats',\n                list_octave_low: 'Low',\n                list_octave_middle: 'Middle',\n                list_octave_high: 'High',\n                list_pitch_c: 'C',\n                list_pitch_d: 'D',\n                list_pitch_e: 'E',\n                list_pitch_f: 'F',\n                list_pitch_g: 'G',\n                list_pitch_a: 'A',\n                list_pitch_b: 'B',\n                list_pitch_r: 'Rest',\n                list_rotation_forward: 'Forward rotation',\n                list_rotation_reverse: 'Reverse rotation',\n                list_rotation_stop: 'Stop',\n                get_ultrasonic_distance: 'Ultrasonic wave sensor distance value',\n                get_button_state: '%1 button value',\n                get_analog_input: 'Analog input value',\n                get_servo_angle: 'No.%1 servo motor angle value',\n                set_led_color_name: 'Set LED color to %1 %2',                \n                set_led_rgb: 'Set LED color to red %1, green %2, blue %3 %4',\n                set_play_score: 'Play note to %1 %2 %3 %4 %5',\n                set_play_sound_effect: 'Play No.%1 sound effect %2',\n                set_play_melody: 'Play No.%1 melody %2',\n                set_servo_each: 'Rotate %1 servo motor to speed %2, angle %3 %4',\n                set_servo_all: 'Rotate all servo motor to speed %1, angle %2, %3, %4, %5, %6 %7',\n                set_servo_home: 'Control all servo motor to speed %1, home position %2',\n                set_analog_output: 'Set analog output to %1 %2',\n                set_dc_run: '%3 DC motor %1 to speed %2 %4',\n                set_servo_offset: 'Set angle 90° of servo motor %1 to current position %2',\n                set_servo_reset: 'Factory reset all settings %1',\n\n                \n                warning_index: 'No item',\n                warning_over_range: 'Measurement over range',\n            }\n        },\n    };\n};\n\nEntry.toybot.blockMenuBlocks = [\n    'dropdown_button',\n    'dropdown_color',\n    'dropdown_accidental',\n    'dropdown_beat',\n    'dropdown_octave',\n    'dropdown_pitch',\n    'dropdown_effect',\n    'dropdown_melody',\n    'dropdown_servo',\n    'dropdown_servo_all',\n    'dropdown_speed',\n    'dropdown_dc',\n    'dropdown_rotation',\n    'get_ultrasonic_distance',\n    'get_button_state',\n    'get_analog_input',\n    'get_servo_angle',\n    'set_led_color_name',\n    'set_led_rgb',\n    'set_play_score',\n    'set_play_sound_effect',\n    'set_play_melody',\n    'set_servo_each',\n    'set_servo_all',\n    'set_servo_home',\n    'set_analog_output',\n    'set_dc_run',\n    'set_servo_offset',\n    'set_servo_reset'\n];\n\nEntry.toybot.getBlocks = function() {\n    return {\n        ///========================================================================================\n        /// dropdown\n        ///========================================================================================\n        dropdown_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_button_a, 0],\n                        [Lang.template.list_button_b, 1]\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_color_white, 1],\n                        [Lang.template.list_color_red, 2],\n                        [Lang.template.list_color_orange, 3],\n                        [Lang.template.list_color_yellow, 4],\n                        [Lang.template.list_color_green, 5],\n                        [Lang.template.list_color_blue, 6],\n                        [Lang.template.list_color_navy, 7],\n                        [Lang.template.list_color_violet, 8],\n                        [Lang.template.list_color_off, 0]\n                    ],\n                    value: 5,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_accidental: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_accidental_natural, 0],\n                        [Lang.template.list_accidental_sharp, 1],\n                        [Lang.template.list_accidental_flat, -1]\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_beat: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_beat_oneeight, 1],\n                        [Lang.template.list_beat_onefour, 2],\n                        [Lang.template.list_beat_onetwo, 3],\n                        [Lang.template.list_beat_one, 4],\n                        [Lang.template.list_beat_onehalf, 5],\n                        [Lang.template.list_beat_two, 6],\n                        [Lang.template.list_beat_three, 7],\n                        [Lang.template.list_beat_four, 8]\n                    ],\n                    value: 4,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_octave_low, 4],\n                        [Lang.template.list_octave_middle, 5],\n                        [Lang.template.list_octave_high, 6]\n                    ],\n                    value: 5,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_pitch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_pitch_c, 1],\n                        [Lang.template.list_pitch_d, 2],\n                        [Lang.template.list_pitch_e, 3],\n                        [Lang.template.list_pitch_f, 4],\n                        [Lang.template.list_pitch_g, 5],\n                        [Lang.template.list_pitch_a, 6],\n                        [Lang.template.list_pitch_b, 7],\n                        [Lang.template.list_pitch_r, 0]\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_effect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        ['5', 5]\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4]\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', 0],\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4]\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },        \n        dropdown_servo_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', 0],\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        [Lang.template.list_all, 5]\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [                        \n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        ['5', 5]\n                    ],\n                    value: 3,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        dropdown_dc: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        [Lang.template.list_all, 3]\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },        \n        dropdown_rotation: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.list_rotation_forward, 1],\n                        [Lang.template.list_rotation_reverse, -1],\n                        [Lang.template.list_rotation_stop, 0]\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE\n                }\n            ],\n            def: {\n                params: [null]\n            },\n            paramsKeyMap: {\n                INDEX: 0\n            },\n            events: {},\n            func: function(sprite, script) {\n                return script.getField('INDEX');\n            }\n        },\n        ///========================================================================================\n        /// getblock\n        ///========================================================================================\n        get_ultrasonic_distance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.get_ultrasonic_distance,\n            params: [],\n            events: {},\n            def: {\n                type: 'get_ultrasonic_distance'\n            },\n            paramsKeyMap: {},\n            class: 'getblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) { \n                const datas = Entry.hw.portData['getblock'];\n                return datas['distance'] === 65535\n                    ? Lang.template.warning_over_range\n                    : datas['distance'] / 10;\n            }\n        },\n        get_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.get_button_state,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_button'\n                    }\n                ],\n                type: 'get_button_state'\n            },\n            paramsKeyMap: {\n                BUTTON: 0\n            },\n            class: 'getblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                const button = Entry.toybot.convert(script.getValue('BUTTON', script));\n                const datas = Entry.hw.portData['getblock'];\n                switch (button) {\n                    case 0:\n                    case Lang.template.list_button_a:\n                        return datas['button'][0] > 0 ? 1 : 0;\n                    case 1:\n                    case Lang.template.list_button_b:\n                        return datas['button'][1] > 0 ? 1 : 0;\n                    default: \n                        return Lang.template.warning_index;\n                }\n            }\n        },\n        get_analog_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.get_analog_input,\n            params: [],\n            events: {},\n            def: {\n                type: 'get_analog_input'\n            },\n            paramsKeyMap: {},\n            class: 'getblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                const datas = Entry.hw.portData['getblock'];\n                return Math.round((datas['analog'] / 1023) * 100);\n            }\n        },\n        get_servo_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.get_servo_angle,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_servo'\n                    }\n                ],\n                type: 'get_servo_angle'\n            },\n            paramsKeyMap: {\n                SERVO: 0\n            },\n            class: 'getblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                const servo = Entry.toybot.convert(script.getValue('SERVO', script));\n                const datas = Entry.hw.portData['getblock'];\n                this.servoPosition = datas['servo'];\n                switch (servo) {\n                    case 0:\n                        return Math.round(datas['servo'][0] / 10);\n                    case 1:\n                        return Math.round(datas['servo'][1] / 10);\n                    case 2:\n                        return Math.round(datas['servo'][2] / 10);\n                    case 3:\n                        return Math.round(datas['servo'][3] / 10);\n                    case 4:\n                        return Math.round(datas['servo'][4] / 10);\n                    default:\n                        return Lang.template.warning_index;\n                }\n            }\n        },\n        ///========================================================================================\n        /// setblock\n        ///========================================================================================        \n        set_led_color_name: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_led_color_name,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_color'\n                    },\n                    null\n                ],\n                type: 'set_led_color_name'\n            },\n            paramsKeyMap: {\n                COLOR: 0\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const colorName = Entry.toybot.convert(script.getValue('COLOR', script));\n                    const color = {\n                        r: 0x00,\n                        g: 0x00,\n                        b: 0x00\n                    };\n                    switch (colorName) {\n                        case 0:\n                        case Lang.template.list_color_off:\n                            color.r = 0x00;\n                            color.g = 0x00;\n                            color.b = 0x00;\n                            break;\n                        case 1:\n                        case Lang.template.list_color_white:\n                            color.r = 0xFF;\n                            color.g = 0xFF;\n                            color.b = 0xFF;\n                            break;\n                        case 2:\n                        case Lang.template.list_color_red:\n                            color.r = 0xFF;\n                            color.g = 0x00;\n                            color.b = 0x00;\n                            break;\n                        case 3:\n                        case Lang.template.list_color_orange:\n                            color.r = 0xFF;\n                            color.g = 0x80;\n                            color.b = 0x00;\n                            break;\n                        case 4:\n                        case Lang.template.list_color_yellow:\n                            color.r = 0xFF;\n                            color.g = 0xFF;\n                            color.b = 0x00;\n                            break;\n                        case 5:\n                        case Lang.template.list_color_green:\n                            color.r = 0x00;\n                            color.g = 0x80;\n                            color.b = 0x00;\n                            break;\n                        case 6:\n                        case Lang.template.list_color_blue:\n                            color.r = 0x00;\n                            color.g = 0x00;\n                            color.b = 0xFF;\n                            break;\n                        case 7:\n                        case Lang.template.list_color_navy:\n                            color.r = 0x00;\n                            color.g = 0x00;\n                            color.b = 0x80;\n                            break;\n                        case 8:\n                        case Lang.template.list_color_violet:\n                            color.r = 0x7F;\n                            color.g = 0x00;\n                            color.b = 0xFF;\n                            break;\n                    }\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        ledControl: color\n                    };\n\n                    return false;\n                });\n            }\n        },\n        set_led_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_led_rgb,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 100 ]\n                    },\n                    {\n                        type: 'number',\n                        params: [ 100 ]\n                    },\n                    {\n                        type: 'number',\n                        params: [ 100 ]\n                    },\n                    null\n                ],\n                type: 'set_led_rgb'\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const red = Entry.toybot.convert(script.getValue('RED', script));\n                    const green = Entry.toybot.convert(script.getValue('GREEN', script));\n                    const blue = Entry.toybot.convert(script.getValue('BLUE', script));\n                    const color = {\n                        r: Entry.toybot.checkRangeInteger(red * 2.55, 0, 255),\n                        g: Entry.toybot.checkRangeInteger(green * 2.55, 0, 255),\n                        b: Entry.toybot.checkRangeInteger(blue * 2.55, 0, 255)\n                    };\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        ledControl: color\n                    };\n\n                    return false;\n                });\n            }\n        },\n        set_play_score: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_play_score,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_octave'\n                    },\n                    {\n                        type: 'dropdown_pitch'\n                    },\n                    {\n                        type: 'dropdown_accidental'\n                    },\n                    {\n                        type: 'dropdown_beat'\n                    },\n                    null\n                ],\n                type: 'set_play_score'\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                PITCH: 1,\n                ACCIDENTAL: 2,\n                BEAT: 3\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                let beat = Entry.toybot.convert(script.getValue('BEAT', script));\n                let octave = Entry.toybot.convert(script.getValue('OCTAVE', script));\n                let accidental = Entry.toybot.convert(script.getValue('ACCIDENTAL', script));\n                let pitch = Entry.toybot.convert(script.getValue('PITCH', script));\n                let delayTime = 0;\n                const note = {\n                    beat: 0,\n                    pitch: 0\n                };\n                switch (beat) {\n                    case 1:\n                    case Lang.template.list_beat_oneeight:\n                        beat = 11;\n                        delayTime = 0.0625;\n                        break;                            \n                    case 2:\n                    case Lang.template.list_beat_onefour:\n                        beat = 9;\n                        delayTime = 0.125;\n                        break;\n                    case 3:\n                    case Lang.template.list_beat_onetwo:\n                        beat = 7;\n                        delayTime = 0.25;\n                        break;\n                    case 4:\n                    case Lang.template.list_beat_one:\n                        beat = 5;\n                        delayTime = 0.5;\n                        break;\n                    case 5:\n                    case Lang.template.list_beat_onehalf:\n                        beat = 4;\n                        delayTime = 0.75;\n                        break;\n                    case 6:\n                    case Lang.template.list_beat_two:\n                        beat = 3;\n                        delayTime = 1;\n                        break;\n                    case 7:\n                    case Lang.template.list_beat_three:\n                        beat = 2;\n                        delayTime = 1.5;\n                        break;\n                    case 8:\n                    case Lang.template.list_beat_four:\n                        beat = 1;\n                        delayTime = 2;\n                        break;\n                }\n                return Entry.toybot.setProcessor(script, delayTime, function() {                    \n                    switch (octave) {\n                        case 4:\n                        case Lang.template.list_octave_low:\n                            octave = 0x40;\n                            break;\n                        case 5:\n                        case Lang.template.list_octave_middle:\n                            octave = 0x50;\n                            break;\n                        case 6:\n                        case Lang.template.list_octave_high:\n                            octave = 0x60;\n                            break;\n                    }\n                    switch (accidental) {\n                        case 0:\n                        case Lang.template.list_accidental_natural:\n                            accidental = 0;\n                            break;\n                        case 1:\n                        case Lang.template.list_accidental_sharp:\n                            accidental = 1;\n                            break;\n                        case -1:\n                        case Lang.template.list_accidental_flat:\n                            accidental = -1;\n                            break;\n                    }\n                    switch (pitch) {\n                        case 0:\n                        case Lang.template.list_pitch_r:\n                            pitch = -1;\n                            break;\n                        case 1:\n                        case Lang.template.list_pitch_c:\n                            pitch = 1;\n                            break;\n                        case 2:\n                        case Lang.template.list_pitch_d:\n                            pitch = 3;\n                            break;\n                        case 3:\n                        case Lang.template.list_pitch_e:\n                            pitch = 5;\n                            break;\n                        case 4:\n                        case Lang.template.list_pitch_f:\n                            pitch = 6;\n                            break;\n                        case 5:\n                        case Lang.template.list_pitch_g:\n                            pitch = 8;\n                            break;\n                        case 6:\n                        case Lang.template.list_pitch_a:\n                            pitch = 10;\n                            break;\n                        case 7:\n                        case Lang.template.list_pitch_b:\n                            pitch = 12;\n                            break;\n                    }\n                    if (pitch > -1) {\n                        pitch = pitch + accidental;\n                        switch (pitch) {\n                            case 0:\n                                octave = octave - 0x10;\n                                pitch = 12;\n                                break;\n                            case 13:\n                                octave = octave + 0x10;\n                                pitch = 1;\n                                break;\n                        }\n                    } else {\n                        pitch = 0;\n                    }\n                    note.pitch = Entry.toybot.checkRangeInteger(octave | pitch, 0x00, 0x7C);\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        playScore: note\n                    };\n\n                    return true;\n                });\n            }\n        },\n        set_play_sound_effect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_play_sound_effect,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_effect'\n                    },\n                    null\n                ],\n                type: 'set_play_sound_effect'\n            },\n            paramsKeyMap: {\n                LIST: 0\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const list = Entry.toybot.convert(script.getValue('LIST', script));\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        playList: {\n                            name: Entry.toybot.checkRangeInteger(list, 1, 12),\n                            play: 1\n                        }\n                    };\n\n                    return false;\n                });\n            }\n        },\n        set_play_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_play_melody,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_melody'\n                    },\n                    null\n                ],\n                type: 'set_play_melody'\n            },\n            paramsKeyMap: {\n                LIST: 0\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const list = Entry.toybot.convert(script.getValue('LIST', script)) + 12;\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        playList: {\n                            name: Entry.toybot.checkRangeInteger(list, 13, 16),\n                            play: 1\n                        }\n                    };\n\n                    return false;\n                });\n            }\n        },\n        set_servo_each: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_servo_each,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_servo'\n                    },\n                    {\n                        type: 'dropdown_speed'\n                    },\n                    {\n                        type: 'number',\n                        params: [ 90 ]\n                    },\n                    null\n                ],\n                type: 'set_servo_each'\n            },\n            paramsKeyMap: {\n                SERVO: 0,\n                SPEED: 1,\n                POSITION: 2\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const id = Entry.toybot.convert(script.getValue('SERVO', script));\n                    const speed = Entry.toybot.convert(script.getValue('SPEED', script));\n                    const position =  Entry.toybot.convert(script.getValue('POSITION', script)) * 10;\n                    const servo = [\n                        {\n                            id: Entry.toybot.checkRangeInteger(id, 0, 4),\n                            speed: Entry.toybot.checkRangeInteger(speed, 1, 5),\n                            position: Entry.toybot.checkRangeInteger(position, 0, 1800)\n                        }\n                    ]\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        servoControl: servo\n                    };\n\n                    return false;\n                });\n            }\n        },\n        set_servo_all: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_servo_all,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_speed'\n                    },\n                    {\n                        type: 'number',\n                        params: [ 90 ]\n                    },\n                    {\n                        type: 'number',\n                        params: [ 90 ]\n                    },\n                    {\n                        type: 'number',\n                        params: [ 90 ]\n                    },\n                    {\n                        type: 'number',\n                        params: [ 90 ]\n                    },\n                    {\n                        type: 'number',\n                        params: [ 90 ]\n                    },\n                    null\n                ],\n                type: 'set_servo_all'\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n                POSITION0: 1,\n                POSITION1: 2,\n                POSITION2: 3,\n                POSITION3: 4,\n                POSITION4: 5,\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const nSpeed =  Entry.toybot.convert(script.getValue('SPEED', script));\n                    const nPosition = [\n                        Entry.toybot.convert(script.getValue('POSITION0', script)),\n                        Entry.toybot.convert(script.getValue('POSITION1', script)),\n                        Entry.toybot.convert(script.getValue('POSITION2', script)),\n                        Entry.toybot.convert(script.getValue('POSITION3', script)),\n                        Entry.toybot.convert(script.getValue('POSITION4', script)),\n                    ];\n                    const speed = Entry.toybot.checkRangeInteger(nSpeed, 1, 5);\n                    const position = [\n                        Entry.toybot.checkRangeInteger(nPosition[0] * 10, 0, 1800),\n                        Entry.toybot.checkRangeInteger(nPosition[1] * 10, 0, 1800),\n                        Entry.toybot.checkRangeInteger(nPosition[2] * 10, 0, 1800),\n                        Entry.toybot.checkRangeInteger(nPosition[3] * 10, 0, 1800),\n                        Entry.toybot.checkRangeInteger(nPosition[4] * 10, 0, 1800)\n                    ];\n                    const servo = [\n                        {\n                            id: 0,\n                            speed: speed,\n                            position: position[0]\n                        },\n                        {\n                            id: 1,\n                            speed: speed,\n                            position: position[1]\n                        },\n                        {\n                            id: 2,\n                            speed: speed,\n                            position: position[2]\n                        },\n                        {\n                            id: 3,\n                            speed: speed,\n                            position: position[3]\n                        },\n                        {\n                            id: 4,\n                            speed: speed,\n                            position: position[4]\n                        },\n                    ]\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        servoControl: servo\n                    };\n\n                    return false;\n                });\n            }\n        },\n        set_servo_home: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_servo_home,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_speed'\n                    },\n                    null\n                ],\n                type: 'set_servo_home'\n            },\n            paramsKeyMap: {\n                SPEED: 0\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const nSpeed =  Entry.toybot.convert(script.getValue('SPEED', script));\n                    const speed = Entry.toybot.checkRangeInteger(nSpeed, 1, 5);                    \n                    const servo = [\n                        {\n                            id: 0,\n                            speed: speed,\n                            position: 900\n                        },\n                        {\n                            id: 1,\n                            speed: speed,\n                            position: 900\n                        },\n                        {\n                            id: 2,\n                            speed: speed,\n                            position: 900\n                        },\n                        {\n                            id: 3,\n                            speed: speed,\n                            position: 900\n                        },\n                        {\n                            id: 4,\n                            speed: speed,\n                            position: 900\n                        },\n                    ]\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        servoControl: servo\n                    };\n\n                    return false;\n                });\n            }\n        },\n        set_analog_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_analog_output,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [ 70 ]\n                    },\n                    null\n                ],\n                type: 'set_analog_output'\n            },\n            paramsKeyMap: {\n                PWM: 0\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const pwm = script.getValue('PWM', script);\n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        pwmControl: Entry.toybot.checkRangeInteger(pwm * 10.23, 0, 1023)\n                    };\n\n                    return false;\n                });\n            }\n        },\n        set_dc_run: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_dc_run,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_dc'\n                    },\n                    {\n                        type: 'dropdown_speed'\n                    },\n                    {\n                        type: 'dropdown_rotation'\n                    },\n                    null\n                ],\n                type: 'set_dc_run'\n            },\n            paramsKeyMap: {\n                DC:0,\n                SPEED: 1,\n                DIRECTION: 2\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const id = Entry.toybot.convert(script.getValue('DC', script));\n                    const pwm = Entry.toybot.convert(script.getValue('SPEED', script));\n                    let direction = Entry.toybot.convert(script.getValue('DIRECTION', script));\n                    switch (direction) {\n                        case Lang.template.list_rotation_forward:\n                            direction = 1;\n                            break;\n                        case Lang.template.list_rotation_reverse:\n                            direction = -1;\n                            break;\n                        case Lang.template.list_rotation_stop:\n                            direction = 0;\n                            break;\n                    }\n                    const speed = Entry.toybot.checkRangeInteger((pwm * 51) * direction, -255, 255);\n                    const dc = [\n                        {\n                            id: 0,\n                            speed: speed\n                        },\n                        {\n                            id: 1,\n                            speed: speed\n                        }\n                    ];\n                    switch (id) {\n                        case 1:\n                        case 2:\n                            Entry.hw.sendQueue['setblock'] = {\n                                id: Math.random(),\n                                dcControl: [dc[id-1]]\n                            };\n                            break;\n                        case 3:\n                        case Lang.template.list_all:                            \n                            Entry.hw.sendQueue['setblock'] = {\n                                id: Math.random(),\n                                dcControl: dc\n                            };\n                            break;\n                    }\n\n                    return false;\n                });\n            }\n        },\n        set_servo_offset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_servo_offset,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'dropdown_servo_all'\n                    },\n                    null\n                ],\n                type: 'set_servo_offset'\n            },\n            paramsKeyMap: {\n                SERVO: 0\n            },\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    let id = Entry.toybot.convert(script.getValue('SERVO', script));\n                    const datas = Entry.hw.portData['getblock'];\n                    const servoOffset = [\n                        {\n                            id:0,\n                            offset: 0\n                        },\n                        {\n                            id:1,\n                            offset: 0\n                        },\n                        {\n                            id:2,\n                            offset: 0\n                        },\n                        {\n                            id:3,\n                            offset: 0\n                        },\n                        {\n                            id:4,\n                            offset: 0\n                        }\n                    ];\n                    for (let i = 0; i < 5; i++) {\n                        const offset = datas['offset'][i];\n                        const calibration = datas['servo'][i] - 900 + offset;\n                        servoOffset[i].offset = Entry.toybot.checkRangeInteger(calibration, -900, 900);\n                    }\n                    switch (id) {\n                        case 0:\n                        case 1:\n                        case 2:\n                        case 3:\n                        case 4:\n                            Entry.hw.sendQueue['setblock'] = {\n                                id: Math.random(),\n                                servoOffset: [servoOffset[id]]\n                            };\n                            break;\n                        case 5:\n                            Entry.hw.sendQueue['setblock'] = {\n                                id: Math.random(),\n                                servoOffset: servoOffset\n                            };\n                            break;\n                    }\n\n                    return false;\n                });\n            }\n        },\n        set_servo_reset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.set_servo_reset,\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12\n                }\n            ],\n            events: {},\n            def: {\n                type: 'set_servo_reset'\n            },\n            paramsKeyMap: {},\n            class: 'setblock',\n            isNotFor: ['toybot'],\n            func: function(sprite, script) {\n                return Entry.toybot.setProcessor(script, Entry.toybot.delayTime, function() {\n                    const servoOffset = [\n                        {\n                            id:0,\n                            offset: 0\n                        },\n                        {\n                            id:1,\n                            offset: 0\n                        },\n                        {\n                            id:2,\n                            offset: 0\n                        },\n                        {\n                            id:3,\n                            offset: 0\n                        },\n                        {\n                            id:4,\n                            offset: 0\n                        }\n                    ];  \n                    Entry.hw.sendQueue['setblock'] = {\n                        id: Math.random(),\n                        servoOffset: servoOffset\n                    };\n\n                    return false;\n                });\n            }\n        },\n    };\n};\n\nmodule.exports = Entry.toybot;"
  },
  {
    "path": "src/playground/blocks/hardware/block_joystick.js",
    "content": "'use strict';\n\nEntry.joystick = {\n    id: '1.4',\n    name: 'joystick',\n    url: 'http://www.kocoafab.cc/',\n    imageName: 'joystick.png',\n    title: {\n        ko: '조이스틱 센서 쉴드',\n        en: 'Joystick Sensor Shield',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.joystick.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                joystick_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                joystick_get_digital_value: '디지털 %1 번 센서값  ',\n                joystick_toggle_led: '디지털 %1 번 핀 %2 %3',\n                joystick_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                joystick_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                joystick_get_analog_value: '아날로그 %1 번 센서값',\n                joystick_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                joystick_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                joystick_toggle_led: '디지털 %1 번 핀 %2 %3',\n                joystick_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                joystick_set_tone: '피에조부저를 %1 %2 음으로 %3 초 연주하기 %4',\n                joystick_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                joystick_get_digital: '디지털 %1 번 센서값',\n                joystick_is_button_pressed: '%1 버튼이 눌렸는가?',\n                joystick_get_joystick_value: '조이스틱을 %1 으로 움직였는가?',\n                joystick_get_sensor_value: '%1 의 측정값',\n                joystick_toggle_motor: '진동모터 %1 %2',\n                joystick_toggle_shield_led: '%1 번째 LED를 %2 %3',\n                joystick_get_led_number: '%1',\n            },\n        },\n        en: {\n            template: {\n                joystick_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                joystick_get_digital_value: 'Digital %1 Sensor value  ',\n                joystick_toggle_led: 'Digital %1 Pin %2 %3',\n                joystick_toggle_pwm: 'Digital %1 Pin %2 %3',\n                joystick_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n                joystick_get_analog_value: 'Analog %1 Sensor value',\n                joystick_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                joystick_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                joystick_toggle_led: 'Digital %1 Pin %2 %3',\n                joystick_digital_pwm: 'Digital %1 Pin %2 %3',\n                joystick_set_tone: 'Play tone on note %1 octave %2 beat %3 %4',\n                joystick_set_servo: 'Set servo pin %1 angle as %2 %3',\n                joystick_get_digital: 'Digital %1 Sensor value',\n                joystick_is_button_pressed: 'button pressed %1',\n                joystick_get_joystick_value: 'when the joystick move to %1',\n                joystick_get_sensor_value: '%1 value',\n                joystick_toggle_motor: 'vibrator motor %1 %2',\n                joystick_toggle_shield_led: '%2 the sensorshield %1 LED %3',\n                joystick_get_led_number: '%1',\n            },\n        },\n    };\n};\n\nEntry.joystick.blockMenuBlocks = [\n    'joystick_get_analog_value',\n    'joystick_get_analog_value_map',\n    'joystick_get_ultrasonic_value',\n    'joystick_get_digital',\n    'joystick_toggle_led',\n    'joystick_digital_pwm',\n    'joystick_set_servo',\n    'joystick_toggle_shield_led',\n    'joystick_set_tone',\n    'joystick_toggle_motor',\n    'joystick_is_button_pressed',\n    'joystick_get_joystick_value',\n    'joystick_get_sensor_value',\n];\n\nEntry.joystick.getBlocks = function() {\n    return {\n        joystick_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.joystick_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'joystick_analog_list',\n                    },\n                ],\n            },\n        },\n        joystick_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'joystick_analog_list',\n                    },\n                ],\n                type: 'joystick_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'joystickGet',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'joystick_get_analog_value',\n                        params: [\n                            {\n                                type: 'joystick_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'joystick_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'joystickGet',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var result = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var stringValue4 = script.getValue('VALUE4', script);\n                var stringValue5 = script.getValue('VALUE5', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'joystick_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'joystickGet',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.joystick.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'joystick_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'joystickGet',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'joystick') {\n                    var port = script.getNumberValue('PORT', script);\n                    var DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.joystick.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'joystick_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'joystick',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.joystick.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.joystick.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.joystick.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'joystick_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'joystick',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.joystick.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                            },\n                        ],\n                        keyOption: 'joystick_tone_list',\n                    },\n                ],\n            },\n        },\n        joystick_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'joystick_tone_list',\n                    },\n                ],\n                type: 'joystick_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'joystick_tone_value',\n                    },\n                ],\n            },\n        },\n        joystick_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'joystick_octave_list',\n                    },\n                ],\n            },\n        },\n        joystick_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'joystick_tone_list',\n                    },\n                    {\n                        type: 'joystick_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'joystick_set_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'joysticksensor',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = 6;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) note = Entry.joystick.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.joystick.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var value = 0;\n\n                    if (note != 0) {\n                        value = Entry.joystick.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.joystick.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.joystick.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'joystick_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'joystick',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.joystick.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_is_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['흰색', '16'],\n                        ['노랑', '9'],\n                        ['빨강', '8'],\n                        ['파랑', '17'],\n                        ['왼쪽 위', '4'],\n                        ['오른쪽 위', '5'],\n                        ['조이스틱', '10'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'joystick_is_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'joysticksensor',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'joystick') {\n                    var port = script.getNumberField('PORT', script);\n                    var DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.joystick.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? !DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_get_joystick_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['오른쪽', '1'],\n                        ['왼쪽', '2'],\n                        ['위', '3'],\n                        ['아래', '4'],\n                        ['오른쪽 위', '5'],\n                        ['오른쪽 아래', '6'],\n                        ['왼쪽 위', '7'],\n                        ['왼쪽 아래', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'joystick_get_joystick_value',\n            },\n            paramsKeyMap: {\n                STICK: 0,\n            },\n            class: 'joysticksensor',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var stick = script.getNumberField('STICK', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (stick === 1 && ANALOG[0] > 800) {\n                    return 1;\n                } else if (stick === 2 && ANALOG[0] < 100) {\n                    return 1;\n                } else if (stick === 3 && ANALOG[1] > 800) {\n                    return 1;\n                } else if (stick === 4 && ANALOG[1] < 100) {\n                    return 1;\n                } else if (stick === 5 && ANALOG[0] > 700 && ANALOG[1] > 700) {\n                    return 1;\n                } else if (stick === 6 && ANALOG[0] > 700 && ANALOG[1] < 300) {\n                    return 1;\n                } else if (stick === 7 && ANALOG[0] < 300 && ANALOG[1] > 700) {\n                    return 1;\n                } else if (stick === 8 && ANALOG[0] < 300 && ANALOG[1] < 300) {\n                    return 1;\n                } else {\n                    return 0;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_get_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가변저항', '1'],\n                        ['빛감지센서', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'joystick_get_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'joysticksensor',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var port = script.getNumberField('PORT', script);\n                if (port === 1) {\n                    port = 'A4';\n                } else if (port === 2) {\n                    port = 'A5';\n                } else {\n                    port = '0';\n                }\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_toggle_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'joystick_toggle_motor',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'joysticksensor',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var port = 7;\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.joystick.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.joystick.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.joystick.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(7, %1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        joystick_get_led_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        joystick_toggle_shield_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'joystick_get_led_number',\n                        params: [null],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'joystick_toggle_shield_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'joysticksensor',\n            isNotFor: ['joystick'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT');\n                if (port === '1') {\n                    port = 2;\n                } else if (port === '2') {\n                    port = 3;\n                } else if (port === '3') {\n                    port = 11;\n                } else if (port === '4') {\n                    port = 12;\n                } else if (port === '5') {\n                    port = 13;\n                } else {\n                    port = null;\n                }\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.joystick.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.joystick.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.joystick.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //endregion joystick 조이스틱\n    };\n};\n\nmodule.exports = Entry.joystick;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_kaboino.js",
    "content": "'use strict';\r\n\r\nlet last_wheel_left_speed = 0;\r\nlet last_wheel_right_speed = 0;\r\nlet last_line1_string = '                     ';\r\nlet last_line2_string = '                     ';\r\nlet last_line3_string = '                     ';\r\nlet last_line4_string = '                     ';\r\nlet last_line5_string = '                     ';\r\nlet last_line6_string = '                     ';\r\nlet lcd_clear = 'cleared';\r\n\r\nEntry.Kaboino = {\r\n    id: '56.1',\r\n    name: 'Kaboino',\r\n    url: 'http://www.kabotel.com/',\r\n    imageName: 'kaboino.png',\r\n    title: {\r\n        ko: '카보이노',\r\n        en: 'Kaboino',\r\n    },\r\n    setZero() {\r\n        last_line1_string = '                     ';\r\n        last_line2_string = '                     ';\r\n        last_line3_string = '                     ';\r\n        last_line4_string = '                     ';\r\n        last_line5_string = '                     ';\r\n        last_line6_string = '                     ';\r\n        last_wheel_left_speed = 0;\r\n        last_wheel_right_speed = 0;\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        }\r\n        else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                if ((key == Entry.Kaboino.PORT_MAP.SET_BODY_SPEED_TURN_PORT) ||\r\n                    (key == Entry.Kaboino.PORT_MAP.SET_BODY_WHEEL_SPIN_PORT) ||\r\n                    (key == Entry.Kaboino.PORT_MAP.SET_WHEEL_SPEED_PORT)) {\r\n                    Entry.hw.sendQueue.SET[key].data = [0, 0];\r\n                }\r\n                else if((key == Entry.Kaboino.PORT_MAP.SET_ULTRASONIC_ANGLE_PORT) ||\r\n                        (key == Entry.Kaboino.PORT_MAP.SET_ROBOT_ARM_ROTATOR_PORT) ||\r\n                        (key == Entry.Kaboino.PORT_MAP.SET_ROBOT_ARM_RAISER_PORT)) {\r\n                    Entry.hw.sendQueue.SET[key].data = 90;\r\n                }\r\n                else if(key == Entry.Kaboino.PORT_MAP.SET_ROBOT_ARM_PUSHER_PORT) {\r\n                    Entry.hw.sendQueue.SET[key].data = 110;\r\n                }\r\n                else {\r\n                    Entry.hw.sendQueue.SET[key].data = 0;\r\n                }\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO_PIN: 4,\r\n        TONE: 5,\r\n        PULSEIN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n        SET_LGT: 9,\r\n        SET_TONE: 10,\r\n        SET_BODY_SPEED_TURN: 11,\r\n        SET_BODY_WHEEL_SPIN: 12,\r\n        SET_WHEEL_BALANCE: 13,\r\n        SET_WHEEL_SPEED: 14,\r\n        SET_DISPLAY_STRING: 15,\r\n        SET_DISPLAY_CLEAR: 16,\r\n        SET_SEARCH_LIGHT:17,\r\n        GET_DUST_SENSOR: 22,\r\n        GET_ULTRASONIC_SENSOR: 23,\r\n        GET_COLOR_SENSOR: 24,\r\n        GET_SND_SENSOR: 25,\r\n        SET_BALL_HOLDER: 26,\r\n        SET_ROBOT_ARM: 28,\r\n        SET_ULTRASONIC_ANGLE: 29,\r\n        SET_COLOR_SEN_LED: 30,\r\n    },\r\n    PORT_MAP: {\r\n        GET_IR_BOT_CENTER_PORT: 0,\r\n        GET_IR_BOT_LEFT_PORT: 1,\r\n        GET_IR_BOT_RIGHT_PORT: 2,\r\n        GET_IR_FOR_CENTER_PORT: 3,      //0\r\n        GET_IR_FOR_LEFT_PORT: 4,        //1\r\n        GET_IR_FOR_RIGHT_PORT: 5,       //2\r\n        GET_LIGHT_SENSOR_PORT: 6,       //3\r\n        GET_MID_SENSOR_PORT: 7,         //4\r\n        GET_COLOR_SENSOR_PORT: 8,       //5\r\n        GET_TEMP_SND_SENSOR_PORT: 9,    //6\r\n        GET_HUMIDITY_SENSOR_PORT: 10,   //7\r\n        GET_DUST_ULTRA_SENSOR_PORT: 11, //8\r\n\r\n        SET_TONE_PORT: 12,\r\n        SET_ANY_PORT: 13,\r\n        SET_CENTER_LGT_PORT: 14,\r\n        SET_LEFT_LGT_PORT: 15,\r\n        SET_RIGHT_LGT_PORT: 16,\r\n        SET_BODY_SPEED_TURN_PORT: 17,\r\n        SET_BODY_WHEEL_SPIN_PORT: 18,\r\n        SET_WHEEL_SPEED_PORT: 19,\r\n        SET_DISPLAY_LINE_PORT: 20,\r\n        SET_DISPLAY_CLEAR_PORT: 21,\r\n        SET_SEARCH_LIGHT_PORT: 22,\r\n        SET_BALL_HOLDER_PORT: 27,\r\n        SET_ULTRASONIC_ANGLE_PORT: 29,\r\n        SET_ROBOT_ARM_GRIPPER_PORT: 30,\r\n        SET_ROBOT_ARM_PUSHER_PORT: 31,\r\n        SET_ROBOT_ARM_RAISER_PORT: 32,\r\n        SET_ROBOT_ARM_ROTATOR_PORT: 33,\r\n        SET_COLOR_LED_PORT: 34,\r\n    },\r\n    CONST_VAL: {\r\n        MAX_SPEED: 126,\r\n    },\r\n    MID_VALUE: {\r\n        BASIC_MODEL: 1,\r\n        BT_RC_CAR: 2,\r\n        BALL_HOLDER_CAR: 3,\r\n        TEMP_HUM_DUST_CAR: 4,\r\n        ULTRASONIC_CAR: 5,\r\n        SHOOTING_CAR: 6,\r\n        ROBOT_ARM_CAR: 8,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    highList: ['high', '1', 'on', 'up'],\r\n    lowList: ['low', '0', 'off', 'down'],\r\n    BlockState: {},\r\n};\r\n\r\nEntry.Kaboino.setLanguage = function() {\r\n    globalThis.isFirstAlertStatement = false;\r\n    return {\r\n        ko: {\r\n            Blocks: {\r\n                KABOINO_on: '켜기',\r\n                KABOINO_off: '끄기',\r\n                KABOINO_front_LED: '전방전조등',\r\n                KABOINO_left_LED: '왼쪽회전등',\r\n                KABOINO_right_LED: '오른쪽회전등',\r\n                KABOINO_front_center_ir_sensor: '중앙 적외선 센서',\r\n                KABOINO_front_left_ir_sensor: '왼쪽 적외선 센서',\r\n                KABOINO_front_right_ir_sensor: '오른쪽 적외선 센서',\r\n                KABOINO_bottom_center_ir_sensor: '중앙 적외선 센서',\r\n                KABOINO_bottom_left_ir_sensor: '왼쪽 적외선 센서',\r\n                KABOINO_bottom_right_ir_sensor: '오른쪽 적외선 센서',\r\n                KABOINO_forward_wheel: '직진',\r\n                KABOINO_backward_wheel: '후진',\r\n                KABOINO_turn_right: '우회전',\r\n                KABOINO_turn_left: '좌회전',\r\n                KABOINO_spin_right: '우측돌기',\r\n                KABOINO_spin_left: '좌측돌기',\r\n                KABOINO_color_white: '흰색',\r\n                KABOINO_color_red: '빨강',\r\n                KABOINO_color_green: '녹색',\r\n                KABOINO_color_blue: '파랑',\r\n                KABOINO_color_black: '검정',\r\n                KABOINO_environment_temp_sensor: '온도 센서',\r\n                KABOINO_environment_humidity_sensor: '습도 센서',\r\n                KABOINO_up: '올리기',\r\n                KABOINO_down: '내리기',\r\n                KABOINO_ultrasonic_angle_center: '정면',\r\n                KABOINO_ultrasonic_angle_left: '왼쪽',\r\n                KABOINO_ultrasonic_angle_right: '오른쪽',\r\n                KABOINO_robot_arm_gripper: '집게',\r\n                KABOINO_robot_arm_pusher: '내밀기',\r\n                KABOINO_robot_arm_raiser: '들어올리기',\r\n                KABOINO_robot_arm_rotator: '회전하기',\r\n            },\r\n            template: {\r\n                kaboino_get_obstacle_sensor_value: '카보이노 장애물 감지 %1 값',\r\n                kaboino_get_light_sensor_value: '카보이노 빛 감지 센서 값',\r\n                kaboino_get_color_sensor_value: '카보이노 색상 감지 센서 값',\r\n                kaboino_get_line_trace_sensor_value: '카보이노 라인 트레이서 감지 %1 값',\r\n                kaboino_get_analog_value_map: '카보이노 값 범위 조정 %1 를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값',\r\n                kaboino_set_light: '카보이노 라이트 %1 을(를) %2 %3',\r\n                kaboino_set_tone: '카보이노 음소리 %1 옥타브 %2 음으로 %3 초 연주하기 %4',\r\n                kaboino_set_body_speed_straight: '카보이노 차체 %1 속도 %2 , 회전 %3 속도 %4 로 이동 %5',\r\n                kaboino_set_wheel_spin: '카보이노 제자리 %1 속도 %2 로 돌기 %3',\r\n                kaboino_set_wheel_balance: '카보이노 바퀴 균형 방향 %1 속도 %2 로 맞추기 %3',\r\n                kaboino_set_wheel_speed: '카보이노 좌 바퀴 %1 %2 , 우 바퀴 %3 %4 로 이동 %5',\r\n                kaboino_set_display: '카보이노 OLED 라인 %1 위치에 %2 표시하기 %3',\r\n                kaboino_set_display_clear: '카보이노 OLED 화면 지우기 %1',\r\n                kaboino_get_color_sensor_value: '카보이노 색깔 감지 %1',\r\n                kaboino_set_color_sensor_led: '카보이노 색깔 감지 LED %1 %2',\r\n                kaboino_set_search_light: '카보이노 확장 1 서치라이트 %1 %2',\r\n                kaboino_set_ball_holder: '카보이노 확장 2 볼 홀더 %1 %2',\r\n                kaboino_get_environmnet_sensor_value: '카보이노 확장 3 환경 감지 %1 값',\r\n                kaboino_get_dust_sensor_value: '카보이노 확장 3 미세먼지 감지 센서 값',\r\n                kaboino_get_ultrasonic_value: '카보이노 확장 4 원거리 장애물 감지 센서값',\r\n                kaboino_set_ultrasonic_angle: '카보이노 확장 4 원거리 장애물 감지 센서 방향 %1 각도 %2 %3',\r\n                kaboino_get_sound_sensor_value: '카보이노 확장 5 타겟 감지 센서 값',\r\n                kaboino_set_robot_arm: '카보이노 확장 7 로봇 팔 %1 조정 %2 %3',\r\n            },\r\n        },\r\n        en: {\r\n            Blocks: {\r\n                KABOINO_on: 'on',\r\n                KABOINO_off: 'off',\r\n                KABOINO_front_LED: 'center LED',\r\n                KABOINO_left_LED: 'left LED',\r\n                KABOINO_right_LED: 'right LED',\r\n                KABOINO_front_center_ir_sensor: 'center ir sensor',\r\n                KABOINO_front_left_ir_sensor: 'left ir sensor',\r\n                KABOINO_front_right_ir_sensor: 'right ir sensor',\r\n                KABOINO_bottom_center_ir_sensor: 'center ir sensor',\r\n                KABOINO_bottom_left_ir_sensor: 'left ir sensor',\r\n                KABOINO_bottom_right_ir_sensor: 'right ir sensor',\r\n                KABOINO_spin_right: 'spin right',\r\n                KABOINO_spin_left: 'spin left',\r\n                KABOINO_forward_wheel: 'straight wheel',\r\n                KABOINO_backward_wheel: 'reverse wheel',\r\n                KABOINO_turn_right: 'turn right',\r\n                KABOINO_turn_left: 'turn left',\r\n                KABOINO_spin_right: 'spin right',\r\n                KABOINO_spin_left: 'spin left',\r\n                KABOINO_color_white: 'white',\r\n                KABOINO_color_red: 'red',\r\n                KABOINO_color_green: 'green',\r\n                KABOINO_color_blue: 'blue',\r\n                KABOINO_color_black: 'black',\r\n                KABOINO_environment_temp_sensor: 'temperature sensor',\r\n                KABOINO_environment_humidity_sensor: 'humidity sensor',\r\n                KABOINO_up: 'up',\r\n                KABOINO_down: 'down',\r\n                KABOINO_ultrasonic_angle_center: 'center',\r\n                KABOINO_ultrasonic_angle_left: 'left',\r\n                KABOINO_ultrasonic_angle_right: 'right',\r\n                KABOINO_robot_arm_gripper: 'gripper',\r\n                KABOINO_robot_arm_pusher: 'pusher',\r\n                KABOINO_robot_arm_raiser: 'raiser',\r\n                KABOINO_robot_arm_rotator: 'rotator',\r\n            },\r\n            template: {\r\n                kaboino_get_obstacle_sensor_value: 'Obstacle sensor %1 value',\r\n                kaboino_get_light_sensor_value: 'Light sensor value',\r\n                kaboino_get_color_sensor_value: 'Color sensor value',\r\n                kaboino_get_line_trace_sensor_value: 'Line Trace sensor %1 value',\r\n                kaboino_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\r\n                kaboino_set_light: 'Set light %1 as %2 %3',\r\n                kaboino_set_tone: 'Play tone on note %1 octave %2 beat %3 %4',\r\n                kaboino_set_body_speed_straight: 'Move Whell straight %1 Speed %2 Turn %3 Speed %4 %5',\r\n                kaboino_set_wheel_spin: 'Wheel spin direction %1 speed %2 %3',\r\n                kaboino_set_wheel_balance:'Wheel balance direction %1 speed %2 %3',\r\n                kaboino_set_wheel_speed: 'Move Left wheel direction %1 Speed %2 Right wheel direction %3 Speed %4 %5',\r\n                kaboino_set_display: 'Display height %1 string %2 %3',\r\n                kaboino_set_display_clear: 'Clear display %1',\r\n                kaboino_get_color_sensor_value: 'Color sensor value %1',\r\n                kaboino_set_color_sensor_led: 'Set color led light %1 %2',\r\n                kaboino_set_search_light: 'Extension 1 Set search light %1 %2',\r\n                kaboino_set_ball_holder: 'Extension 2 Set ball holder %1 %2',\r\n                kaboino_get_environmnet_sensor_value: 'Extension 3 Environment sensor %1 value',\r\n                kaboino_get_dust_sensor_value: 'Extension 3 Dust Sensor value',\r\n                kaboino_get_ultrasonic_value: 'Extension 4 Read ULTRASONIC sensor value',\r\n                kaboino_set_ultrasonic_angle: 'Extension 4 set ULTRASONIC sensor direction %1 , angle %2 %3',\r\n                kaboino_get_sound_sensor_value: 'Extension 5 Target sensor value',\r\n                kaboino_set_robot_arm: 'Extension 7 Robot arm %1 control %2 %3',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.Kaboino.blockMenuBlocks = [\r\n    'kaboino_get_obstacle_sensor_value',\r\n    'kaboino_get_light_sensor_value',\r\n    'kaboino_get_line_trace_sensor_value',\r\n    'kaboino_get_analog_value_map',\r\n    'kaboino_get_color_sensor_value',\r\n    'kaboino_set_light',\r\n    'kaboino_set_tone',\r\n    'kaboino_set_spin_speed',\r\n    'kaboino_set_body_speed_straight',\r\n    'kaboino_set_wheel_spin',\r\n    'kaboino_set_wheel_balance',\r\n    'kaboino_set_wheel_speed',\r\n    'kaboino_set_display',\r\n    'kaboino_set_display_clear',\r\n    'kaboino_get_color_sensor_value',\r\n    'kaboino_set_color_sensor_led',\r\n    'kaboino_set_search_light',\r\n    'kaboino_set_ball_holder',\r\n    'kaboino_get_environmnet_sensor_value',\r\n    'kaboino_get_dust_sensor_value',\r\n    'kaboino_get_ultrasonic_value',\r\n    'kaboino_set_ultrasonic_angle',\r\n    'kaboino_get_sound_sensor_value',\r\n    'kaboino_set_robot_arm',\r\n];\r\n\r\nEntry.Kaboino.getBlocks = function() {\r\n    return {\r\n        kaboino_obstacle_sensor_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_front_center_ir_sensor, \"frontCenterIR\"],\r\n                        [Lang.Blocks.KABOINO_front_left_ir_sensor, \"frontLeftIR\"],\r\n                        [Lang.Blocks.KABOINO_front_right_ir_sensor, \"frontRightIR\"],\r\n                    ],\r\n                    value: \"frontCenterIR\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                var port = script.getStringField('PORT', script);\r\n                return port;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_front_center_ir_sensor, \"frontCenterIR\"],\r\n                                    [Lang.Blocks.KABOINO_front_left_ir_sensor, \"frontLeftIR\"],\r\n                                    [Lang.Blocks.KABOINO_front_right_ir_sensor, \"frontRightIR\"],\r\n                                ],\r\n                                value: \"frontCenterIR\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_obstacle_sensor_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_obstacle_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_obstacle_sensor_list',\r\n                    },\r\n                ],\r\n                type: 'kaboino_get_obstacle_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'KaboinoGet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let receivedStringKey = script.getValue('PORT', script);\r\n                let port = 0;\r\n                if (receivedStringKey == \"frontCenterIR\") {\r\n                    port = Entry.Kaboino.PORT_MAP.GET_IR_FOR_CENTER_PORT - 3;\r\n                }\r\n                else if (receivedStringKey == \"frontLeftIR\") {\r\n                    port = Entry.Kaboino.PORT_MAP.GET_IR_FOR_LEFT_PORT - 3;\r\n                }\r\n                else if (receivedStringKey == \"frontRightIR\") {\r\n                    port = Entry.Kaboino.PORT_MAP.GET_IR_FOR_RIGHT_PORT -3;\r\n                }\r\n                \r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                \r\n                return String(ANALOG[port]);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.readObstacleSensor(%1)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_light_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'kaboino_get_light_sensor_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'KaboinoGet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let port = Entry.Kaboino.PORT_MAP.GET_LIGHT_SENSOR_PORT - 3;\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                return String(ANALOG[port]);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.readLightSensor()',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_line_trace_sensor_value_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_bottom_center_ir_sensor, \"lineCenterIR\"],\r\n                        [Lang.Blocks.KABOINO_bottom_left_ir_sensor, \"lineLeftIR\"],\r\n                        [Lang.Blocks.KABOINO_bottom_right_ir_sensor, \"lineRightIR\"],\r\n                    ],\r\n                    value: \"lineCenterIR\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                var port = script.getStringField('PORT', script);\r\n                return port;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_bottom_center_ir_sensor, \"lineCenterIR\"],\r\n                                    [Lang.Blocks.KABOINO_bottom_left_ir_sensor, \"lineLeftIR\"],\r\n                                    [Lang.Blocks.KABOINO_bottom_right_ir_sensor, \"lineRightIR\"],\r\n                                ],\r\n                                value: \"lineCenterIR\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_get_line_trace_sensor_value_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_line_trace_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_get_line_trace_sensor_value_list',\r\n                    },\r\n                ],\r\n                type: 'kaboino_get_line_trace_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'KaboinoGet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let receivedStringKey = script.getValue('PORT', script);\r\n                let port = 0;\r\n\r\n                if (receivedStringKey == \"lineCenterIR\") {\r\n                    port = 0;\r\n                }\r\n                else if (receivedStringKey == \"lineLeftIR\") {\r\n                    port = 1;\r\n                }\r\n                else if (receivedStringKey == \"lineRightIR\") {\r\n                    port = 2;\r\n                }\r\n\r\n                const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.Kaboino.sensorTypes.DIGITAL] = {\r\n                    port,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.readLineTraceSensor(%1)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        \r\n        kaboino_get_analog_value_map: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_get_analog_value',\r\n                        params: [\r\n                            {\r\n                                type: 'kaboino_analog_list',\r\n                            },\r\n                        ],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'kaboino_get_analog_value_map',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'KaboinoGet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let result = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                const stringValue4 = script.getValue('VALUE4', script);\r\n                const stringValue5 = script.getValue('VALUE5', script);\r\n                let isFloat = false;\r\n\r\n                if ((Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\r\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)) {\r\n                    isFloat = true;\r\n                }\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                if (isFloat) {\r\n                    result = Math.round(result * 100) / 100;\r\n                } else {\r\n                    result = Math.round(result);\r\n                }\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.map(%1, %2, %3, %4, %5)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_light_port_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_front_LED, \"centerLED\"],\r\n                        [Lang.Blocks.KABOINO_left_LED, \"leftLED\"],\r\n                        [Lang.Blocks.KABOINO_right_LED, \"rightLED\"],\r\n                    ],\r\n                    value: \"centerLED\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                var port = script.getStringField('PORT', script);\r\n                return port;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_front_LED, \"centerLED\"],\r\n                                    [Lang.Blocks.KABOINO_left_LED, \"leftLED\"],\r\n                                    [Lang.Blocks.KABOINO_right_LED, \"rightLED\"],\r\n                                ],\r\n                                value: \"centerLED\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_light_port_list',\r\n                    },\r\n                ]\r\n            },\r\n        },\r\n        kaboino_on_off_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_on, 'on'],\r\n                        [Lang.Blocks.KABOINO_off, 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                var value = script.getStringField('VALUE', script);\r\n                return value;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_on, 'on'],\r\n                                    [Lang.Blocks.KABOINO_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_on_off_list',\r\n                    },\r\n                ]\r\n            },\r\n        },\r\n        kaboino_set_light: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_light_port_list',\r\n                    },\r\n                    {\r\n                        type: 'kaboino_on_off_list',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_light',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'KaboinoSet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let receivedPortStringKey = script.getValue('PORT', script);\r\n                let port = 0;\r\n                if (receivedPortStringKey == \"centerLED\") {\r\n                    port = Entry.Kaboino.PORT_MAP.SET_CENTER_LGT_PORT;\r\n                }\r\n                else if (receivedPortStringKey == \"leftLED\") {\r\n                    port = Entry.Kaboino.PORT_MAP.SET_LEFT_LGT_PORT;\r\n                }\r\n                else if (receivedPortStringKey == \"rightLED\") {\r\n                    port = Entry.Kaboino.PORT_MAP.SET_RIGHT_LGT_PORT;\r\n                }\r\n\r\n                let receivedValueStringKey = script.getValue('VALUE', script);\r\n                let value = 0;\r\n                \r\n                if (receivedValueStringKey == 'on') {\r\n                    value = 0xf;\r\n                }\r\n                else if (receivedValueStringKey == 'off') {\r\n                    value = 0;\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.Kaboino.sensorTypes.SET_LGT,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                \r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.setLight(%1, %2)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_tone_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.silent, '0'],\r\n                                    [Lang.Blocks.do_name, 'C'],\r\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\r\n                                    [Lang.Blocks.re_name, 'D'],\r\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\r\n                                    [Lang.Blocks.mi_name, 'E'],\r\n                                    [Lang.Blocks.fa_name, 'F'],\r\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                                    [Lang.Blocks.sol_name, 'G'],\r\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                                    [Lang.Blocks.la_name, 'A'],\r\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\r\n                                    [Lang.Blocks.si_name, 'B'],\r\n                                ],\r\n                                value: 'C',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_tone_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_tone_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_tone_list',\r\n                    },\r\n                ],\r\n                type: 'kaboino_tone_value',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getNumberValue('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'kaboino_tone_value',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_octave_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'kaboino_octave_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_tone_list',\r\n                    },\r\n                    {\r\n                        type: 'kaboino_octave_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_tone',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n                OCTAVE: 1,\r\n                DURATION: 2,\r\n            },\r\n            class: 'KaboinoSet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = Entry.Kaboino.PORT_MAP.SET_TONE_PORT;\r\n\r\n                if (!script.isStart) {\r\n                    let note = script.getValue('NOTE', script);\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.Kaboino.toneTable[note];\r\n                    }\r\n                    \r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    }\r\n                    else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n\r\n                    let duration = script.getNumberValue('DURATION', script);\r\n\r\n                    if (duration < 0) {\r\n                        duration = 0;\r\n                    }\r\n\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n\r\n                    if (duration === 0) {\r\n                        sq.SET[port] = {\r\n                            type: Entry.Kaboino.sensorTypes.SET_TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n\r\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    }\r\n                    else if (octave > 7) {\r\n                        octave = 7;\r\n                    }\r\n\r\n                    let value = 0;\r\n\r\n                    if (note != 0) {\r\n                        value = Entry.Kaboino.toneMap[note][octave];\r\n                    }\r\n\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    sq.SET[port] = {\r\n                        type: Entry.Kaboino.sensorTypes.SET_TONE,\r\n                        data: {\r\n                            value,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                }\r\n                else if (script.timeFlag == 1) {\r\n                    return script;\r\n                }\r\n                else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    sq.SET[port] = {\r\n                        type: Entry.Kaboino.sensorTypes.SET_TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.setTone(%1, %2, %3)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_wheel_straight_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_forward_wheel, \"forward\"],\r\n                        [Lang.Blocks.KABOINO_backward_wheel, \"reverse\"],\r\n                    ],\r\n                    value: \"forward\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_forward_wheel, \"forward\"],\r\n                                    [Lang.Blocks.KABOINO_backward_wheel, \"reverse\"],\r\n                                ],\r\n                                value: \"forward\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_set_wheel_straight_list',\r\n                    },\r\n                ]\r\n            },\r\n        },\r\n        kaboino_set_wheel_turn_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_turn_left, \"leftTurn\"],\r\n                        [Lang.Blocks.KABOINO_turn_right, \"rightTurn\"],\r\n                    ],\r\n                    value: \"leftTurn\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_turn_left, \"leftTurn\"],\r\n                                    [Lang.Blocks.KABOINO_turn_right, \"rightTurn\"],\r\n                                ],\r\n                                value: \"leftTurn\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_set_wheel_turn_list',\r\n                    },\r\n                ]\r\n            },\r\n        },\r\n        kaboino_set_body_speed_straight: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_set_wheel_straight_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['10'],\r\n                    },\r\n                    {\r\n                        type: 'kaboino_set_wheel_turn_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_body_speed_straight',\r\n            },\r\n            paramsKeyMap: {\r\n                CAR_BODY_STRAIGHT: 0,\r\n                CAR_BODY_SPEED: 1,\r\n                CAR_BODY_TURN: 2,\r\n                CAR_BODY_TURN_SPEED: 3,\r\n            },\r\n            class: 'KaboinoSet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let car_body_straight = script.getValue('CAR_BODY_STRAIGHT', script);\r\n                let car_body_speed = script.getValue('CAR_BODY_SPEED', script);\r\n                let car_body_turn = script.getValue('CAR_BODY_TURN', script);\r\n                let car_body_turn_speed = script.getValue('CAR_BODY_TURN_SPEED', script);\r\n                const port = Entry.Kaboino.PORT_MAP.SET_BODY_SPEED_TURN_PORT;\r\n\r\n                car_body_speed = Math.round(car_body_speed);\r\n                car_body_speed = Math.max(car_body_speed, 0);\r\n                car_body_speed = Math.min(car_body_speed, 125);\r\n\r\n                car_body_turn_speed = Math.round(car_body_turn_speed);\r\n                car_body_turn_speed = Math.max(car_body_turn_speed, 0);\r\n                car_body_turn_speed = Math.min(car_body_turn_speed, 25);\r\n\r\n                let wheel_left_speed;\r\n                let wheel_right_speed;\r\n\r\n                if (car_body_straight == \"forward\") {\r\n                    if (car_body_turn == \"leftTurn\") {\r\n                        wheel_left_speed = car_body_speed - car_body_speed * Math.round(car_body_turn_speed/25);\r\n                        wheel_right_speed = car_body_speed;\r\n                    }\r\n                    else if (car_body_turn == \"rightTurn\") {\r\n                        wheel_left_speed = car_body_speed;\r\n                        wheel_right_speed = car_body_speed - car_body_speed * Math.round(car_body_turn_speed/25);\r\n                    }\r\n                }\r\n                else if (car_body_straight == \"reverse\") {\r\n                    if (car_body_turn == \"leftTurn\") {\r\n                        wheel_left_speed = car_body_speed - car_body_speed * Math.round(car_body_turn_speed/25);\r\n                        wheel_right_speed = car_body_speed;\r\n                    }\r\n                    else if (car_body_turn == \"rightTurn\") {\r\n                        wheel_left_speed = car_body_speed;\r\n                        wheel_right_speed = car_body_speed - car_body_speed * Math.round(car_body_turn_speed/25);\r\n                    }\r\n                    if (wheel_left_speed == 0) wheel_left_speed = 0;\r\n                    else wheel_left_speed = wheel_left_speed + Entry.Kaboino.CONST_VAL.MAX_SPEED;\r\n                    if (wheel_right_speed == 0) wheel_right_speed = 0;\r\n                    else wheel_right_speed = wheel_right_speed + Entry.Kaboino.CONST_VAL.MAX_SPEED;\r\n                }\r\n\r\n                if (!(last_wheel_left_speed == wheel_left_speed) || !(last_wheel_right_speed == wheel_right_speed)) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[port] = {\r\n                        type: Entry.Kaboino.sensorTypes.SET_BODY_SPEED_TURN,\r\n                        data: [wheel_left_speed, wheel_right_speed],\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    last_wheel_left_speed = wheel_left_speed;\r\n                    last_wheel_right_speed = wheel_right_speed;\r\n                    return script;\r\n                }\r\n                else return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.writeBodySpeedStraight(%1, %2, %3, %4)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_wheel_spin_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_spin_left, \"leftSpin\"],\r\n                        [Lang.Blocks.KABOINO_spin_right, \"rightSpin\"],\r\n                    ],\r\n                    value: \"leftSpin\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_spin_left, \"leftSpin\"],\r\n                                    [Lang.Blocks.KABOINO_spin_right, \"rightSpin\"],\r\n                                ],\r\n                                value: \"leftSpin\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_set_wheel_spin_list',\r\n                    },\r\n                ]\r\n            },\r\n        },\r\n        kaboino_set_wheel_spin: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_set_wheel_spin_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['10'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_wheel_spin',\r\n            },\r\n            paramsKeyMap: {\r\n                SPIN_DIR: 0,\r\n                SPIN_SPEED: 1,\r\n            },\r\n            class: 'KaboinoSet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let spin_dir = script.getValue('SPIN_DIR', script);\r\n                let spin_speed = script.getValue('SPIN_SPEED', script);\r\n                const port = Entry.Kaboino.PORT_MAP.SET_BODY_WHEEL_SPIN_PORT;\r\n\r\n                spin_speed = Math.round(spin_speed);\r\n                spin_speed = Math.max(spin_speed, 0);\r\n                spin_speed = Math.min(spin_speed, 125);\r\n                \r\n                let wheel_left_speed;\r\n                let wheel_right_speed;\r\n\r\n                if (spin_dir == \"leftSpin\") {\r\n                    wheel_left_speed = spin_speed + Entry.Kaboino.CONST_VAL.MAX_SPEED;\r\n                    wheel_right_speed = spin_speed;\r\n                }\r\n                else if (spin_dir == \"rightSpin\") {\r\n                    wheel_left_speed = spin_speed;\r\n                    wheel_right_speed = spin_speed + Entry.Kaboino.CONST_VAL.MAX_SPEED;\r\n                }\r\n\r\n                if (!(last_wheel_left_speed == wheel_left_speed) || !(last_wheel_right_speed == wheel_right_speed)) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[port] = {\r\n                        type: Entry.Kaboino.sensorTypes.SET_BODY_WHEEL_SPIN,\r\n                        data: [wheel_left_speed, wheel_right_speed],\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    last_wheel_left_speed = wheel_left_speed;\r\n                    last_wheel_right_speed = wheel_right_speed;\r\n                    return script;\r\n                }\r\n                else return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.writeSpinPWM(%1, %2)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        kaboino_set_wheel_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_set_wheel_straight_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['10'],\r\n                    },\r\n                    {\r\n                        type: 'kaboino_set_wheel_straight_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['10'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_wheel_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                WHEEL_LEFT_STRAIGHT: 0,\r\n                WHEEL_LEFT_SPEED: 1,\r\n                WHEEL_RIGHT_STRAIGHT: 2,\r\n                WHEEL_RIGHT_SPEED: 3,\r\n            },\r\n            class: 'KaboinoSet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let wheel_left_straight = script.getValue('WHEEL_LEFT_STRAIGHT', script);\r\n                let wheel_left_speed = script.getValue('WHEEL_LEFT_SPEED', script);\r\n                let wheel_right_straight = script.getValue('WHEEL_RIGHT_STRAIGHT', script);\r\n                let wheel_right_speed = script.getValue('WHEEL_RIGHT_SPEED', script);\r\n                let port = Entry.Kaboino.PORT_MAP.SET_WHEEL_SPEED_PORT;\r\n                \r\n                wheel_left_speed = Math.round(wheel_left_speed);\r\n                wheel_left_speed = Math.max(wheel_left_speed, 0);\r\n                wheel_left_speed = Math.min(wheel_left_speed, (Entry.Kaboino.CONST_VAL.MAX_SPEED - 1));\r\n\r\n                wheel_right_speed = Math.round(wheel_right_speed);\r\n                wheel_right_speed = Math.max(wheel_right_speed, 0);\r\n                wheel_right_speed = Math.min(wheel_right_speed, (Entry.Kaboino.CONST_VAL.MAX_SPEED - 1));\r\n\r\n                if(wheel_left_straight == \"forward\")\r\n                {\r\n                    wheel_left_speed = wheel_left_speed;\r\n                }\r\n                else if (wheel_left_straight == \"reverse\")\r\n                {\r\n                    wheel_left_speed = wheel_left_speed + Entry.Kaboino.CONST_VAL.MAX_SPEED;\r\n                }\r\n\r\n                if(wheel_right_straight == \"forward\")\r\n                {\r\n                    wheel_right_speed = wheel_right_speed;\r\n                }\r\n                else if (wheel_right_straight == \"reverse\")\r\n                {\r\n                    wheel_right_speed = wheel_right_speed + Entry.Kaboino.CONST_VAL.MAX_SPEED;\r\n                }\r\n\r\n                if (!(last_wheel_left_speed == wheel_left_speed) || !(last_wheel_right_speed == wheel_right_speed)) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[port] = {\r\n                        type: Entry.Kaboino.sensorTypes.SET_WHEEL_SPEED,\r\n                        data: [wheel_left_speed, wheel_right_speed],\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    last_wheel_left_speed = wheel_left_speed;\r\n                    last_wheel_right_speed = wheel_right_speed;\r\n                    return script;\r\n                }\r\n                else return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.writeMotorSpeed(%1, %2, %3, %4)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_display: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'text', \r\n                        params: ['Welcome to Kaboino!'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_display',\r\n            },\r\n            paramsKeyMap: {\r\n                HEIGHT: 0,\r\n                STRING: 1,\r\n            },\r\n            class: 'KaboinoSet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let port = Entry.Kaboino.PORT_MAP.SET_DISPLAY_LINE_PORT;\r\n                let width = 0;\r\n                let line = script.getValue('HEIGHT', script);\r\n                let height = line;\r\n                let current_string = script.getValue('STRING', script);\r\n                let character = [];\r\n                let buf;\r\n                line = Math.round(line);\r\n                line = Math.max(line, 1);\r\n                line = Math.min(line, 6);\r\n                let line1_string = '';\r\n                let line2_string = '';\r\n                let line3_string = '';\r\n                let line4_string = '';\r\n                let line5_string = '';\r\n                let line6_string = '';\r\n                lcd_clear = 'not_cleared';\r\n                height = (line - 1) * 10;\r\n\r\n                if (line == 1) {\r\n                    line1_string = current_string;\r\n                }\r\n                else if (line == 2) {\r\n                    line2_string = current_string;\r\n                }\r\n                else if (line == 3) {\r\n                    line3_string = current_string;\r\n                }\r\n                else if (line == 4) {\r\n                    line4_string = current_string;\r\n                }\r\n                else if (line == 5) {\r\n                    line5_string = current_string;\r\n                }\r\n                else if (line == 6) {\r\n                    line6_string = current_string;\r\n                }\r\n                \r\n                if (typeof current_string === 'string') {\r\n                    for (var i = 0; i < current_string.length; i++) {\r\n                        buf = Entry.memaker.toByte(current_string[parseInt(i, 10)]);\r\n                        character[parseInt(i, 10)] = buf;\r\n                    }\r\n                } else {\r\n                    character[0] = current_string;\r\n                }\r\n                \r\n                if ((!(last_line1_string == line1_string) && (line == 1)) ||\r\n                    (!(last_line2_string == line2_string) && (line == 2)) ||\r\n                    (!(last_line3_string == line3_string) && (line == 3)) ||\r\n                    (!(last_line4_string == line4_string) && (line == 4)) ||\r\n                    (!(last_line5_string == line5_string) && (line == 5)) ||\r\n                    (!(last_line6_string == line6_string) && (line == 6))) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[port] = {\r\n                        type: Entry.Kaboino.sensorTypes.SET_DISPLAY_STRING,\r\n                        data: [\r\n                            width,\r\n                            height,\r\n                            character[0],\r\n                            character[1],\r\n                            character[2],\r\n                            character[3],\r\n                            character[4],\r\n                            character[5],\r\n                            character[6],\r\n                            character[7],\r\n                            character[8],\r\n                            character[9],\r\n                            character[10],\r\n                            character[11],\r\n                            character[12],\r\n                            character[13],\r\n                            character[14],\r\n                            character[15],\r\n                            character[16],\r\n                            character[17],\r\n                            character[18],\r\n                            character[19],\r\n                            character[20]\r\n                        ],\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    \r\n                    if (line == 1) {\r\n                        last_line1_string = current_string;\r\n                    }\r\n                    else if (line == 2) {\r\n                        last_line2_string = current_string;\r\n                    }\r\n                    else if (line == 3) {\r\n                        last_line3_string = current_string;\r\n                    }\r\n                    else if (line == 4) {\r\n                        last_line4_string = current_string;\r\n                    }\r\n                    else if (line == 5) {\r\n                        last_line5_string = current_string;\r\n                    }\r\n                    else if (line == 6) {\r\n                        last_line6_string = current_string;\r\n                    }\r\n\r\n                    return script;\r\n                }\r\n                else return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.displayLineString(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_display_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_display_clear',\r\n            },\r\n            paramsKeyMap: {\r\n                \r\n            },\r\n            class: 'KaboinoSet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                const port = Entry.Kaboino.PORT_MAP.SET_DISPLAY_CLEAR_PORT;\r\n                if (!(lcd_clear == 'cleared')) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[port] = {\r\n                        type: Entry.Kaboino.sensorTypes.SET_DISPLAY_CLEAR,\r\n                        data: {\r\n                            data: 0,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    lcd_clear = 'cleared';\r\n                    last_line1_string = '                     ';\r\n                    last_line2_string = '                     ';\r\n                    last_line3_string = '                     ';\r\n                    last_line4_string = '                     ';\r\n                    last_line5_string = '                     ';\r\n                    last_line6_string = '                     ';\r\n                    return script;\r\n                }\r\n                else return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.displayClearLine()',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_color_sensor_value_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_color_white, \"white\"],\r\n                        [Lang.Blocks.KABOINO_color_red, \"red\"],\r\n                        [Lang.Blocks.KABOINO_color_green, \"green\"],\r\n                        [Lang.Blocks.KABOINO_color_blue, \"blue\"],\r\n                        [Lang.Blocks.KABOINO_color_black, \"black\"],\r\n                    ],\r\n                    value: \"white\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                var port = script.getStringField('PORT', script);\r\n                \r\n                return port;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_color_white, \"white\"],\r\n                                    [Lang.Blocks.KABOINO_color_red, \"red\"],\r\n                                    [Lang.Blocks.KABOINO_color_green, \"green\"],\r\n                                    [Lang.Blocks.KABOINO_color_blue, \"blue\"],\r\n                                    [Lang.Blocks.KABOINO_color_black, \"black\"],\r\n                                ],\r\n                                value: \"white\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_get_color_sensor_value_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_color_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_get_color_sensor_value_list',\r\n                    },\r\n                ],\r\n                type: 'kaboino_get_color_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR_NUMBER: 0,\r\n            },\r\n            class: 'KaboinoGet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let receivedPortStringValue = script.getValue('COLOR_NUMBER', script);\r\n                let color_number;\r\n\r\n                if (receivedPortStringValue == \"white\")\r\n                    color_number = 4;\r\n                else if (receivedPortStringValue == \"red\")\r\n                    color_number = 1;\r\n                else if (receivedPortStringValue == \"green\")\r\n                    color_number = 2;\r\n                else if (receivedPortStringValue == \"blue\")\r\n                    color_number = 3;\r\n                else if (receivedPortStringValue == \"black\")\r\n                    color_number = 5;\r\n\r\n                const ColorPort = Entry.Kaboino.PORT_MAP.GET_COLOR_SENSOR_PORT - 3;\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.Kaboino.sensorTypes.GET_COLOR_SENSOR] = {\r\n                    port: ColorPort,\r\n                    time: new Date().getTime(),\r\n                };\r\n                const COLOR_VALUE = Entry.hw.portData.COLOR;\r\n\r\n                if (color_number == COLOR_VALUE) {\r\n                    \r\n                }\r\n                else {\r\n\r\n                }\r\n\r\n                return (color_number == COLOR_VALUE) || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.readColorSensor(%1)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_color_sensor_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_on, 'on'],\r\n                        [Lang.Blocks.KABOINO_off, 'off'],\r\n                    ],\r\n                    value: 'off',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_color_sensor_led',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'KaboinoSet',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let port = Entry.Kaboino.PORT_MAP.SET_COLOR_LED_PORT;\r\n                let value = script.getValue('VALUE', script);\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (value == 'on') {\r\n                    value = 0xf;\r\n                } else if (value == 'off') {\r\n                    value = 0;\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.Kaboino.sensorTypes.SET_COLOR_SEN_LED,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.setColorSenLED(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_on, 'on'],\r\n                                    [Lang.Blocks.KABOINO_off, 'off'],\r\n                                ],\r\n                                value: 'off',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_search_light: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_on, 'on'],\r\n                        [Lang.Blocks.KABOINO_off, 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_search_light',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'KaboinoSet_2',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let port = Entry.Kaboino.PORT_MAP.SET_SEARCH_LIGHT_PORT;\r\n                let value = script.getValue('VALUE', script);\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n\r\n                if (value == 'on') {\r\n                    value = 0xf;\r\n                } else if (value == 'off') {\r\n                    value = 0;\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.Kaboino.sensorTypes.SET_SEARCH_LIGHT,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.turnSearchLight(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_on, 'on'],\r\n                                    [Lang.Blocks.KABOINO_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_ball_holder: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_up, \"up\"],\r\n                        [Lang.Blocks.KABOINO_down, \"down\"],\r\n                    ],\r\n                    value: \"up\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_ball_holder',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'KaboinoSet_3',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let port = '0';\r\n                let value = script.getValue('VALUE', script);\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n\r\n                if (value == \"up\") value = 180;\r\n                else if (value == \"down\") value = 0;\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.Kaboino.sensorTypes.SET_BALL_HOLDER,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.liftBallHolder(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_up, \"up\"],\r\n                                    [Lang.Blocks.KABOINO_down, \"down\"],\r\n                                ],\r\n                                value: \"up\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_environmnet_sensor_value_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_environment_temp_sensor, \"tempSensor\"],\r\n                        [Lang.Blocks.KABOINO_environment_humidity_sensor, \"humSensor\"],\r\n                    ],\r\n                    value: \"tempSensor\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                var port = script.getStringField('PORT', script);\r\n                return port;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_environment_temp_sensor, \"tempSensor\"],\r\n                                    [Lang.Blocks.KABOINO_environment_humidity_sensor, \"humSensor\"],\r\n                                ],\r\n                                value: \"tempSensor\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_get_environmnet_sensor_value_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_environmnet_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_get_environmnet_sensor_value_list',\r\n                    },\r\n                ],\r\n                type: 'kaboino_get_environmnet_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'KaboinoGet_4',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let port = script.getValue('PORT', script);\r\n\r\n                if (port == \"tempSensor\") {\r\n                    port = Entry.Kaboino.PORT_MAP.GET_TEMP_SND_SENSOR_PORT - 3;\r\n                } else if (port == \"humSensor\" ){\r\n                    port = Entry.Kaboino.PORT_MAP.GET_HUMIDITY_SENSOR_PORT - 3;\r\n                }\r\n                \r\n                if (port[0] === 'A') {\r\n                    port = port.substring(1);\r\n                }\r\n\r\n                return String(ANALOG[port]/100);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.readEnvironmentSensor(%1)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_dust_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'kaboino_get_dust_sensor_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'KaboinoGet_4',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                const DustPort = Entry.Kaboino.PORT_MAP.GET_DUST_ULTRA_SENSOR_PORT - 3;\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.Kaboino.sensorTypes.GET_DUST_SENSOR] = {\r\n                    port: DustPort,\r\n                    time: new Date().getTime(),\r\n                };\r\n                const DUST_VALUE = Entry.hw.portData.DUST;\r\n\r\n                return String(DUST_VALUE || 0);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.readDustSensor()',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_ultrasonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'kaboino_get_ultrasonic_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'KaboinoGet_5',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                \r\n                const UltrasonicPort = Entry.Kaboino.PORT_MAP.GET_DUST_ULTRA_SENSOR_PORT - 3;\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.Kaboino.sensorTypes.GET_ULTRASONIC_SENSOR] = {\r\n                    port: UltrasonicPort,\r\n                    time: new Date().getTime(),\r\n                };\r\n                const ULTRASONIC_VALUE = Entry.hw.portData.ULTRASONIC;\r\n\r\n                return String(ULTRASONIC_VALUE || 0);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.readUltrasonicSensor()',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_ultrasonic_angle_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_ultrasonic_angle_center, \"ultraCenterAng\"],\r\n                        [Lang.Blocks.KABOINO_ultrasonic_angle_left, \"ultraLeftAng\"],\r\n                        [Lang.Blocks.KABOINO_ultrasonic_angle_right, \"ultraRightAng\"],\r\n                    ],\r\n                    value: \"ultraCenterAng\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                var port = script.getStringField('PORT', script);\r\n\r\n                return port;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_ultrasonic_angle_center, \"ultraCenterAng\"],\r\n                                    [Lang.Blocks.KABOINO_ultrasonic_angle_left, \"ultraLeftAng\"],\r\n                                    [Lang.Blocks.KABOINO_ultrasonic_angle_right, \"ultraRightAng\"],\r\n                                ],\r\n                                value: \"ultraCenterAng\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_set_ultrasonic_angle_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_ultrasonic_angle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_set_ultrasonic_angle_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_ultrasonic_angle',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'KaboinoSet_5',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let port = Entry.Kaboino.PORT_MAP.SET_ULTRASONIC_ANGLE_PORT;\r\n                let direction = script.getValue('DIRECTION', script);\r\n                let value = script.getValue('VALUE', script);\r\n                let ultrasonic_angle = 90;\r\n\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 90);\r\n                \r\n                if (direction == \"ultraCenterAng\") {\r\n                    ultrasonic_angle = 90;\r\n                }\r\n                else if (direction == \"ultraLeftAng\") {\r\n                    ultrasonic_angle = 90 + value;\r\n                }\r\n                else if (direction == \"ultraRightAng\") {\r\n                    ultrasonic_angle = 90 - value;\r\n                }\r\n                \r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.Kaboino.sensorTypes.SET_ULTRASONIC_ANGLE,\r\n                    data: ultrasonic_angle,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.setUltrasonicAngle(%1)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_get_sound_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'kaboino_get_sound_sensor_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'KaboinoGet_6',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                const SNDPort = Entry.Kaboino.PORT_MAP.GET_TEMP_SND_SENSOR_PORT - 3;\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.Kaboino.sensorTypes.GET_SND_SENSOR] = {\r\n                    port: SNDPort,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                const SND_VALUE = Entry.hw.portData.SND;\r\n\r\n                return String(SND_VALUE || 0);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.readShootingValue()',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        kaboino_set_robot_arm_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.KABOINO_robot_arm_gripper, \"armGripper\"],\r\n                        [Lang.Blocks.KABOINO_robot_arm_pusher, \"armPusher\"],\r\n                        [Lang.Blocks.KABOINO_robot_arm_raiser, \"armRaiser\"],\r\n                        [Lang.Blocks.KABOINO_robot_arm_rotator, \"armRotator\"],\r\n                    ],\r\n                    value: \"armGripper\",\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT', script);\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.KABOINO_robot_arm_gripper, \"armGripper\"],\r\n                                    [Lang.Blocks.KABOINO_robot_arm_pusher, \"armPusher\"],\r\n                                    [Lang.Blocks.KABOINO_robot_arm_raiser, \"armRaiser\"],\r\n                                    [Lang.Blocks.KABOINO_robot_arm_rotator, \"armRotator\"],\r\n                                ],\r\n                                value: \"armGripper\",\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'kaboino_set_robot_arm_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        kaboino_set_robot_arm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaboino_set_robot_arm_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaboino_set_robot_arm',\r\n            },\r\n            paramsKeyMap: {\r\n                ACTOR: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'KaboinoSet_8',\r\n            isNotFor: ['Kaboino'],\r\n            func(sprite, script) {\r\n                let port;\r\n                let actorPort = script.getValue('ACTOR', script);\r\n                let value = script.getValue('VALUE', script);\r\n\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 180);\r\n                \r\n                if (actorPort == \"armGripper\") {\r\n                    port = Entry.Kaboino.PORT_MAP.SET_ROBOT_ARM_GRIPPER_PORT;\r\n                }\r\n                else if (actorPort == \"armPusher\") {\r\n                    port = Entry.Kaboino.PORT_MAP.SET_ROBOT_ARM_PUSHER_PORT;\r\n                }\r\n                else if (actorPort == \"armRaiser\") {\r\n                    port = Entry.Kaboino.PORT_MAP.SET_ROBOT_ARM_RAISER_PORT;\r\n                }\r\n                else if (actorPort == \"armRotator\") {\r\n                    port = Entry.Kaboino.PORT_MAP.SET_ROBOT_ARM_ROTATOR_PORT;\r\n                }\r\n                \r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.Kaboino.sensorTypes.SET_ROBOT_ARM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Kaboino.controlRobotArm(%1, %2)',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.Kaboino;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_kaduino.js",
    "content": "'use strict';\r\n\r\nEntry.kaduino = \r\n{\r\n\tid: '3A.1',\t\r\n    name: 'kaduino',\r\n    url: 'http://www.kairobot.co.kr/',\r\n    imageName: 'kaduino.png',\r\n    title: \r\n\t{\r\n        \"ko\": \"카두이노\", \r\n        \"en\": \"kaduino\"\r\n    },\r\n\r\n    setZero: function() {    ///  하드웨어 초기화 로직\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } \r\n\t\telse \r\n\t\t{\r\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach(function(key) {\r\n                Entry.hw.sendQueue.SET[key].data = 0;\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });   \r\n        }\r\n        Entry.hw.update();\r\n        lmotor_speed = 0;\r\n        rmotor_speed = 0;\r\n        var rgbled_0 = [];\r\n        rgbled_r = rgbled_0;\r\n        rgbled_g = rgbled_0;\r\n        rgbled_b = rgbled_0;\r\n    },\r\n\t\r\n    Static: {\r\n//        kaduino_BLOCK_COLOR: '#00979D', // gray(#848484)\r\n//        kaduino_ARROW_COLOR_HW: '#00979D',\r\n\r\n    },\r\n\t\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        BUZZER: 3,\r\n        SERVO: 4,\r\n        TONE: 5,\r\n        TEMP: 6,\r\n        USONIC: 7,\r\n        RGBLED: 11,\r\n        MOTOR: 12,\r\n        RGBLEDSHOW: 13,\r\n        PWM: 32,\r\n        USONIC_SET: 33,\r\n        I2C_SET: 34,\r\n        LCD_SET: 40,\r\n       },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    BlockState: {},\t\r\n};\r\n\r\nEntry.kaduino.blockMenuBlocks = [    /// 하드웨어 블록 등록 , 여기에 등록된 블록이 순서대로 나열되며 설정한 이름으로 화면에 보임\r\n        'kaduino_buzzer_onoff',\t\t\t            // 스피커 삐 소리\r\n        'kaduino_set_digital_buzzer',               // 스피커 멜로디\r\n        'kaduino_set_motor_speed',                  // DC모터 속도제어\r\n        'kaduino_motor_stop',            // DC모터 정지하기\t\r\n        'kaduino_set_servo',                        // 서보모터 제어\r\n\r\n        'kaduino_set_rgbled_onoff',                // rgb led로 지정색 제어\r\n        'kaduino_rgbled_seting',                // rgb led 핀번호 설정\r\n        'kaduino_set_rgbled_value',                //rgb led 개별색 제어\r\n        'kaduino_rgbled_all_onoff',                // rgb led all show, all off\r\n\r\n        'kaduino_digital_onoff',                   /// 디지털 포트 제어\r\n        'kaduino_get_digital_value',\t            //디지탈 입력\r\n        'kaduino_get_analog_value',                 // 아날로그 입력\r\n        'kaduino_set_pwm',                          //PWM제어\r\n\r\n        'kaduino_set_ultrasonic',                   //초음파센서 포트설정\r\n        'kaduino_get_usonic_value',              //초음파센서 읽기\r\n        'kaduino_set_temp',                  //온도센서 연결포트 설정\r\n        'kaduino_get_temp_value',                   // 온도센서 입력\r\n        'kaduino_set_i2c',                   //I2C포트 센서연결설정\r\n        'kaduino_get_color_value',                  // 컬러센서 입력\r\n        'kaduino_get_gyro_value',                   // 자이로센서 입력\r\n       \r\n        'kaduino_set_lcd_string',\r\n        'kaduino_set_lcd_init',\r\n        'kaduino_set_lcd_clear',\r\n\r\n\t\t'kaduino_get_analog_mapping',\r\n\r\n\t\t\r\n];\r\n\r\nEntry.kaduino.setLanguage = function() {    // 블록 이름  번역\r\n    return {\r\n        ko: {\r\n            template: {\r\n                \"kaduino_buzzer_onoff\": \"스피커 삐 소리 %1 초 연주하기 %2\",\t\t\t\t\r\n                \"kaduino_set_digital_buzzer\": \"스피커음계 %1 옥타브 %2 음 %3 초 연주하기 %4\",\t\r\n                \"kaduino_set_motor_speed\": \"DC모터 왼쪽 속도%1 오른쪽 속도%2 으로 정하기 %3\", \r\n                \"kaduino_motor_stop\": \"DC모터 정지하기 %1\",\t\r\n                \"kaduino_set_servo\": \"서보모터 %1핀 각도 %2 이동 %3\",\t\t\r\n\r\n                \"kaduino_set_rgbled_onoff\": \"RGB LED %1 번째 색깔 %2 하기 %3\",\t\r\n                \"kaduino_rgbled_seting\": \"RGB LED %1핀에 %2개  밝기%3 설정하기 %4\",   \r\n                \"kaduino_set_rgbled_value\": \"RGB LED %1번째  빨강%2 초록%3 파랑%4 으로 하기 %5\",\r\n                \"kaduino_rgbled_all_onoff\": \"RGB LED  %1 %2\",\r\n\r\n                \"kaduino_digital_onoff\": \"디지털 %1 핀 %2 설정하기 %3\",         \r\n                \"kaduino_get_digital_value\": \"디지털 %1 핀 읽기\",\t\t\t\t\r\n                \"kaduino_get_analog_value\": \"아날로그 %1 핀 읽기\",\r\n                \"kaduino_set_pwm\": \"PWM %1 핀에 %2 보내기 %3\",\t\r\n\r\n                \"kaduino_set_ultrasonic\": \"초음파센서 설정 트리거 %1 핀, 에코 %2 핀 으로 연결하기 %3\",\t\r\n                \"kaduino_get_usonic_value\": \"초음파센서 값 읽기\",\t\r\n                \"kaduino_set_temp\": \"온도센서 %1 핀에 연결하기 %2\",\t\r\n                \"kaduino_get_temp_value\": \"온도센서 값 읽기\",\t\r\n                \"kaduino_set_i2c\": \"I2C포트  %1 연결하기 %2\",\t\r\n                \"kaduino_get_color_value\": \"컬러센서 %1 값 읽기\",\r\n                \"kaduino_get_gyro_value\": \"자이로센서 %1 값 읽기\",\r\n\r\n                \"kaduino_set_lcd_string\": \"lcd 세로%1줄,  가로%2줄 에  %3 표시하기 %4\",\r\n                \"kaduino_set_lcd_init\": \"lcd 설정 : I2C 주소 0x%1 , 가로줄 수 %2 , 세로줄 수 %3 으로 정하기%4\",\r\n                \"kaduino_set_lcd_clear\": \"lcd 지우기 %1\",\r\n\r\n\r\n\t\t\t\t\"kaduino_get_analog_mapping\": \" %1 값 %2 ~ %3 에서 %4 ~ %5 으로 변환값\", \r\n\t\t\t\t\r\n            },\r\n            Blocks: {\r\n                On_block: \"켜짐(HIGH, 5V)\",\r\n                Off_block: \"꺼짐(LOW, 0V)\",\r\n                AllOn_block: \"모두 켜짐\",\r\n                AllOff_block: \"모두 꺼짐\",\r\n                RGB_red: \"빨강색\",\r\n                RGB_blue: \"파란색\",\r\n                RGB_green: \"초록색\",\r\n                RGB_white: \"하얀색\",\r\n                RGB_skyblue: \"하늘색\",\r\n                RGB_yellow: \"노란색\",\r\n                RGB_purple: \"보라색\",\r\n                RGB_off: \"끄기\",\r\n            }\r\n        },\r\n        en: {\r\n            template: {\r\n                \"kaduino_buzzer_onoff\": \"Speakers Beep %1 Playing Second %2\",\t\t\t\t\r\n                \"kaduino_set_digital_buzzer\": \"Speakers  %1 Octave %2 Play %3 seconds %4\",\t\r\n                \"kaduino_set_motor_speed\": \"Set DC motor left speed %1  right speed %2 %3\", \t\r\n                \"kaduino_motor_stop\": \"Stop DC Motor %1\",\t\r\n                \"kaduino_set_servo\": \"Servo motor %1 pin angle %2 movement %3\",\t\t\r\n\r\n                \"kaduino_set_rgbled_onoff\": \"RGB LED %1 First Color %2 %3\",\t\t\r\n                \"kaduino_rgbled_seting\": \"Setting %2 brightness %3 on RGB LED %1 pin %4\",\r\n                \"kaduino_set_rgbled_value\": \"RGB LED %1 st Red %2 Green %3 Blue %4\",\r\n                \"kaduino_rgbled_all_onoff\": \"RGB LED %1 %2\",\t\t\r\n\r\n                \"kaduino_digital_onoff\": \"Setting up digital %1 pin %2 %3\",\t\r\n                \"kaduino_get_digital_value\": \"Read digital %1 pins\",\t\t\t\t\r\n                \"kaduino_get_analog_value\": \"Analog %1 pin read\",\r\n                \"kaduino_set_pwm\": \"Send %2 to pin %1 %3\",\t\t\r\n\r\n                \"kaduino_set_ultrasonic\": \"Connecting to the ultrasonic sensor setting trigger %1 pin, echo %2 pin %3\",\t\t\r\n                \"kaduino_get_usonic_value\": \"Reading ultrasonic sensor values\",\t\t\r\n                \"kaduino_set_temp\": \"Connecting to the temperature sensor %1 pin %2\",\t\t\r\n                \"kaduino_get_temp_value\": \"Reading temperature sensor values\",\t\t\r\n                \"kaduino_set_i2c\": \"Connect I2Cport %1 %2\",\t\t\r\n                \"kaduino_get_color_value\": \"Reading the color sensor %1 value\",\r\n\t\t\t\t\"kaduino_get_gyro_value\": \"Read gyro sensor %1 value\",\r\n                \r\n                \"kaduino_set_lcd_string\": \"lcd Display %3 on line %1 and line %2 %4\",\t\t\r\n                \"kaduino_set_lcd_init\": \"setting lcd : I2C address 0x%1 , horizontal line number %2 , vertical line number %3 %4\",\t\r\n                \"kaduino_set_lcd_clear\": \"Clear lcd %1\",\t\t\r\n\r\n\t\t\t\t\r\n                \"kaduino_get_analog_mapping\": \"%1 value %2 to %3 ; to %4 to %5 conversion value \",\t\r\n\t\t\t\t\t\t\t\t\r\n            },\r\n            Blocks: {\r\n                On_block: \"On(HIGH, 5V)\",\r\n                Off_block: \"Off(LOW, 0V)\",\r\n                AllOn_block: \"ALL ON\",\r\n                AllOff_block: \"ALL OFF\",\r\n                RGB_red: \"Red\",\r\n                RGB_blue: \"Blue\",\r\n                RGB_green: \"Green\",\r\n                RGB_white: \"White\",\r\n                RGB_skyblue: \"Sky blue\",\r\n                RGB_yellow: \"Yellow\",\r\n                RGB_purple: \"Purple\",\r\n                RGB_off: \"Off\",\r\n            }\r\n        }\r\n    }\r\n};\r\nvar delay_time = 0;\r\nvar lmotor_speed = 0;\r\nvar rmotor_speed = 0;\r\nvar rgbled_r = [];\r\nvar rgbled_g = [];\r\nvar rgbled_b = [];\r\n\r\nEntry.kaduino.getBlocks = function() {\r\n    return {\r\n        kaduino_digital_port_onoff_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.On_block, '1'],\r\n                        [Lang.Blocks.Off_block, '0'],\r\n                    ],\t\t\t\t\t\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\t\r\n        \r\n        kaduino_list_digital_octave: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n        },\r\n\t\t\r\n        kaduino_list_digital_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n        },\r\n        kaduino_digital_port_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['D2', '2'],\r\n                        ['D8', '8'],\r\n                        ['D9', '9'],\r\n                        ['D10', '10'],\r\n                        ['D11', '11'],\r\n                        ['D12', '12'],\r\n                        ['D13', '13'],\r\n                        ['A0', '14'],\r\n                        ['A1', '15'],\r\n                        ['A2', '16'],\r\n                        ['A3', '17'],\r\n                        ['A4', '18'],\r\n                        ['A5', '19'],\r\n                    ],\r\n                    value: '8',       // 기본 표시값\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n\r\n\t\tkaduino_pwn_port_list: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                    ],\r\n                    value: '9',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PWMPORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('PWMPORT');\r\n            },\r\n        },\r\n        kaduino_lcd_add_list: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['27', '39'],\r\n                        ['3f', '63'],\r\n                    ],\r\n                    value: '39',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                LCDADD: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('LCDADD');\r\n            },\r\n        },\r\n        kaduino_i2c_sen_list: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['Color Sensor', '1'],\r\n                        ['Gyro Sensor', '2'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                SENSOR: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getStringField('SENSOR');\r\n            },\r\n        },\r\n\r\n        kaduino_all_onoff_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.AllOff_block, '2'],\r\n                        [Lang.Blocks.AllOn_block, '3'],\r\n                    ],\t\t\t\t\t\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            },\r\n        },\r\n        kaduino_analog_port_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A0', '0'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                        ['A3', '3'],\r\n                        ['A4', '4'],\r\n                        ['A5', '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n        \r\n\t\tkaduino_ultrasonic_port_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                        ['12', '12'],\r\n                        ['13', '13'],\r\n                    ],\r\n                    value: '10',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n        kaduino_analog_rgb_color_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.RGB_red, '0'],\r\n                        [Lang.Blocks.RGB_blue, '1'],\r\n                        [Lang.Blocks.RGB_green, '2'],\r\n                        [Lang.Blocks.RGB_white, '3'],\r\n                        [Lang.Blocks.RGB_skyblue, '4'],\r\n                        [Lang.Blocks.RGB_yellow, '5'],\r\n                        [Lang.Blocks.RGB_purple, '6'],\r\n                        [Lang.Blocks.RGB_off, '7'],\t\t\t\t\t\t\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: function(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\t\t// 1. 삐소리\r\n\t\tkaduino_buzzer_onoff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaduino_buzzer_onoff',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'kaduino_LV1',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var port = 10;\r\n                var duration = script.getNumberValue('VALUE');\t// 길이\t\r\n                var octave = 5;    // 옥타브\r\n                var value = 2400;//698;   // 음 주파수\r\n                var mode = 1;\r\n                \r\n                if (!script.isStart) \r\n\t\t\t\t{\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    if (duration == 0) // 음 길이가 0 이면\r\n\t\t\t\t\t{\r\n                        Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t\t\t{\r\n                            type: Entry.kaduino.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n                    if(duration > 300)\r\n                        duration = 300;\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;  // 출력 시작 플래그 셋\r\n                    script.timeFlag = 1;    // 시간플래그 셋\r\n\r\n                    Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t\t{\r\n                        type: Entry.kaduino.sensorTypes.TONE,\r\n                        data: \r\n\t\t\t\t\t\t{\r\n                            value: value,\r\n                            duration: duration/10,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() \r\n\t\t\t\t\t{\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n\r\n                }\r\n                else if (script.timeFlag == 1) \r\n\t\t\t\t{\r\n                    return script;\r\n                } \r\n\t\t\t\telse    // 설정 시간이 지나면 출력 리셋\r\n\t\t\t\t{\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t\t{\r\n                        type: Entry.kaduino.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            \t\t\t\t\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\t\t\r\n\t\t// 2) 옥타브/음/초 동안 연주\r\n        kaduino_set_digital_buzzer: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.kaduino_set_digital_buzzer,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_list_digital_octave',\t\t\t\t\t\t\r\n                    },\r\n                    {\r\n                        type: 'kaduino_list_digital_tone',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_digital_buzzer',\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\t\t\t\t\r\n                NOTE: 1,\r\n                DURATION: 2,\r\n            },\r\n            class: 'kaduino_LV1',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) {\r\n                var port = 10; //script.getNumberValue('PORT');\r\n                var duration = script.getNumberValue('DURATION');\r\n                var octave = script.getNumberValue('OCTAVE') - 1;\r\n                var value = 0;\r\n\r\n                if (!script.isStart) \r\n\t\t\t\t{\r\n                    var note = script.getValue('NOTE');\r\n                    if (!Entry.Utils.isNumber(note)) \r\n\t\t\t\t\t{\r\n                        note = Entry.kaduino.toneTable[note];\r\n                    }\r\n                    if (note < 0) note = 0;\r\n                    else if (note > 12) note = 12;\r\n\r\n                    if (duration < 0) duration = 0;\r\n\t\t\t\t\t\r\n                    if (!Entry.hw.sendQueue['SET']) \r\n\t\t\t\t\t{\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n\t\t\t\t\t\r\n                    if (duration == 0) \r\n\t\t\t\t\t{\r\n                        Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t\t\t{\r\n                            type: Entry.kaduino.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n\t\t\t\t\t\r\n                    if (octave < 0) octave = 0;\r\n                    else if (octave > 8) octave = 8;\r\n                    if (note != 0) value = Entry.kaduino.toneMap[note][octave];\r\n                    if(duration > 300)\r\n                        duration = 300;\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t\t{\r\n                        type: Entry.kaduino.sensorTypes.TONE,\r\n                        data: \r\n\t\t\t\t\t\t{\r\n                            value: value,\r\n                            duration: duration/10,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() \r\n\t\t\t\t\t{\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } \r\n\t\t\t\telse if (script.timeFlag == 1) \r\n\t\t\t\t{\r\n                    return script;\r\n                } \r\n\t\t\t\telse \r\n\t\t\t\t{\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t\t{\r\n                        type: Entry.kaduino.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        \r\n        // 3. DC 모터 속도 정하기\t\t\r\n\t\tkaduino_set_motor_speed: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_motor_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n\t\t\t\tRSPEED: 1,\r\n            },\r\n            class: 'kaduino_LV1',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var lspeed = script.getNumberValue('LSPEED', script);\r\n                var rspeed = script.getNumberValue('RSPEED', script);\r\n                var port = 3;\r\n                \t\t\r\n                lspeed = Math.min(100, lspeed);\r\n                lspeed = Math.max(-100, lspeed);\t\t\r\n                rspeed = Math.min(100, rspeed);\r\n                rspeed = Math.max(-100, rspeed);\t\t\r\n                \r\n                if(!(lmotor_speed == lspeed) || !(rmotor_speed == rspeed))\r\n                {\r\n                    if (!script.isStart) \r\n                    {\r\n                        if (!Entry.hw.sendQueue['SET']) {\r\n                            Entry.hw.sendQueue['SET'] = {};\r\n                        }\r\n                        Entry.hw.sendQueue['SET'][port] = \r\n                        {\r\n                            type: Entry.kaduino.sensorTypes.MOTOR,\r\n                            data: [lspeed, rspeed],\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        lmotor_speed = lspeed;\r\n                        rmotor_speed = rspeed;\r\n                        script.isStart = true;  // 출력 시작 플래그 셋\r\n                        script.timeFlag = 1;    // 시간플래그 셋\r\n                        setTimeout(function() \r\n                        {\r\n                            script.timeFlag = 0;\r\n                        }, delay_time );\r\n                        return script;\r\n                    }\r\n                    else if (script.timeFlag == 1) \r\n                    {\r\n                        return script;\r\n                    } \r\n                    else    // 설정 시간이 지나면 출력 리셋\r\n                    {\r\n                        delete script.timeFlag;\r\n                        delete script.isStart;\r\n                        Entry.engine.isContinue = false;\r\n                        return script.callReturn();\r\n                    }\r\n                }\r\n                else\r\n                    return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\t\t\r\n\t\t// 4. DC 모터 정지하기\t\t\r\n\t\tkaduino_motor_stop: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kaduino_motor_stop',\r\n            },\r\n            paramsKeyMap: {\r\n                //PORT: 0,\r\n            },\r\n            class: 'kaduino_LV1',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var port = 19;//script.getNumberValue('PORT', script);\r\n\t\t\t\t//port += 2;\r\n\t\t\t\tvar lspeed = 0;\r\n                var rspeed = 0;\r\n                \r\n                if(!(lmotor_speed == 0) || !(rmotor_speed == 0))\r\n                {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    Entry.hw.sendQueue['SET'][port] = \r\n                    {\r\n                        type: Entry.kaduino.sensorTypes.MOTOR,\r\n                        data: [lspeed, rspeed],\r\n                        time: new Date().getTime(),\r\n                    };\r\n                }\r\n\r\n                lmotor_speed = 0;\r\n                rmotor_speed = 0;\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 5.  서보 모터 각도 설정하기\t\t\r\n\t\tkaduino_set_servo: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_digital_port_list',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_servo',\r\n            },\r\n            paramsKeyMap: \r\n\t\t\t{\r\n\t\t\t\tPORT: 0,\r\n                ANGLE: 1,\r\n            },\r\n            class: 'kaduino_LV1',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var port = script.getNumberValue('PORT', script);\r\n                var angle = script.getNumberValue('ANGLE', script);\r\n//\t\t\t\tport += 2;\r\n//\t\t\t\tvar mode = 1;\r\n\t\t\t\t\r\n                angle = Math.min(180, angle);\r\n                angle = Math.max(0, angle);\r\n                angle += 1;\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t{\r\n                    type: Entry.kaduino.sensorTypes.SERVO,\r\n                    data: angle,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n\r\n        // 6. RGBLED  색상 설정 및 show\r\n\t\tkaduino_set_rgbled_onoff: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'kaduino_analog_rgb_color_list',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_rgbled_onoff',\r\n            },\r\n            paramsKeyMap: {\r\n                LEDNUM: 0,\r\n                COLOR: 1,\r\n            },\r\n            class: 'kaduino_LV2',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\t\r\n\t\t\t\tvar port = script.getNumberValue('LEDNUM');\r\n                var color = script.getNumberValue('COLOR', script);\r\n                var ledmode = 1;\r\n\t\t\t\tvar rLED, gLED, bLED;\r\n\r\n\t\t\t\tswitch(color)\r\n\t\t\t\t{\r\n\t\t\t\t\t\tcase 0: \trLED = 255; gLED = 0; bLED = 0;\t\t// Red\r\n\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\r\n                        case 1: \trLED = 0; gLED = 0; bLED = 255;\t\t// Blue\r\n\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\r\n                        case 2: \trLED = 0; gLED = 255;\tbLED = 0;\t// Lime\r\n\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\r\n                        case 3: \trLED = 255; gLED = 255; bLED = 255;\t// white\r\n\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\r\n                        case 4: \trLED = 0; gLED = 255; bLED = 255;\t// Cyan\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n                        case 5: \trLED = 255; gLED = 255; bLED = 0;\t// Yellow\r\n\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\r\n\t\t\t\t\t\tcase 6: \trLED = 255; gLED = 0;\tbLED = 255;\t// Magenta\r\n                                    break;\r\n                        case 6: \trLED = 0; gLED = 0;\tbLED = 0;\t    // 끄기\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n                \r\n                \r\n                if(!(rgbled_r[port] == rLED) || !(rgbled_g[port] == gLED) || !(rgbled_b[port] == bLED))\r\n                {\r\n                    if (!script.isStart) \r\n                    {\r\n                        if (!Entry.hw.sendQueue['SET']) \r\n                        {\r\n                            Entry.hw.sendQueue['SET'] = {};\r\n                        }\r\n                        Entry.hw.sendQueue['SET'][port] = {  // port 를 \r\n                            type: Entry.kaduino.sensorTypes.RGBLED,\r\n                            data: {\t\t\t\r\n                                r: rLED,\r\n                                g: gLED,\r\n                                b: bLED,\r\n                                mode: ledmode,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        rgbled_r[port] = rLED;\r\n                        rgbled_g[port] = gLED;\r\n                        rgbled_b[port] = bLED;\r\n                        script.isStart = true;  // 출력 시작 플래그 셋\r\n                        script.timeFlag = 1;    // 시간플래그 셋\r\n                        setTimeout(function() \r\n                        {\r\n                            script.timeFlag = 0;\r\n                        }, delay_time );\r\n                        return script;\r\n                    }\r\n                    else if (script.timeFlag == 1) \r\n                    {\r\n                        return script;\r\n                    } \r\n                    else    // 설정 시간이 지나면 출력 리셋\r\n                    {\r\n                        delete script.timeFlag;\r\n                        delete script.isStart;\r\n                        Entry.engine.isContinue = false;\r\n                        return script.callReturn();\r\n                    }\r\n                }\r\n                else\r\n                    return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 7. rgb led 연결 설정\r\n        kaduino_rgbled_seting:     \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_digital_port_list', \r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"2\"],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"255\"],\r\n                    },\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_rgbled_seting',\r\n            },\r\n            paramsKeyMap: {\r\n                RGBPIN:0,\r\n                VALUE0:1,\r\n                VALUE1:2,\r\n            },\r\n            class: 'kaduino_LV2',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var port = 0;\r\n                var rLED = script.getNumberValue('RGBPIN', script);  // 핀번호\r\n                var gLED = script.getNumberValue('VALUE0', script);  // 수량\r\n                var bLED = script.getNumberValue('VALUE1', script);  // 밝기\r\n                var ledmode = 4;  // 핀번호설정\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.kaduino.sensorTypes.RGBLED,\r\n                    data: {\r\n                        r: rLED,\r\n                        g: gLED,\r\n                        b: bLED,\r\n                        mode: ledmode,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\t\t\r\n\t\t// 8. RGBLED 색상설정\r\n\t\tkaduino_set_rgbled_value: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"1\"],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\t\t\t\t\r\n\t\t\t\t\t{\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_rgbled_value',\r\n            },\r\n            paramsKeyMap: {\r\n                RGBNUM:0,\r\n                VALUE0:1,\r\n                VALUE1:2,\r\n\t\t\t\tVALUE2:3,\r\n            },\r\n            class: 'kaduino_LV2',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var port = script.getNumberValue('RGBNUM', script);\r\n                var rLED = script.getNumberValue('VALUE0', script);\r\n                var gLED = script.getNumberValue('VALUE1', script);\r\n                var bLED = script.getNumberValue('VALUE2', script);\r\n                var ledmode = 7;\r\n\r\n                if(!(rgbled_r[port] == rLED) || !(rgbled_g[port] == gLED) || !(rgbled_b[port] == bLED))\r\n                {\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    Entry.hw.sendQueue['SET'][port] = {\r\n                        type: Entry.kaduino.sensorTypes.RGBLED,\r\n                        data: {\r\n                            r: rLED,\r\n                            g: gLED,\r\n                            b: bLED,\r\n                            mode: ledmode,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    rgbled_r[port] = rLED;\r\n                    rgbled_g[port] = gLED;\r\n                    rgbled_b[port] = bLED;\r\n                    return script.callReturn();\r\n                }\r\n                else\r\n                    return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        \r\n\t\t// 9. RGBLED 끄기, SHOW\r\n\t\tkaduino_rgbled_all_onoff: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_all_onoff_list',\r\n                    },\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_rgbled_all_onoff',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'kaduino_LV2',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var port = 4;//script.getNumberValue('PORT');\r\n                var ledmode = script.getNumberValue('VALUE', script);\r\n\r\n\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.kaduino.sensorTypes.RGBLEDSHOW,\r\n                    data: {\r\n                        mode: ledmode,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 10. 디지털  출력\r\n\t\tkaduino_digital_onoff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_digital_port_list',      \r\n                    },\r\n                    {\r\n                        type: 'kaduino_digital_port_onoff_list',\r\n                    },\t\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_digital_onoff',\r\n            },\r\n            paramsKeyMap: {   // 실제 블록의 로직인 func에서 key값으로 사용할 파라미터의 인덱스 번호\r\n                PORT: 0,\r\n\t\t\t\tVALUE: 1,\r\n            },\r\n            class: 'kaduino_LV3',    // 블록을 묶는 그룹 이름. 이 값이 다르면 사이에 가로줄이 생깁니다\r\n            isNotFor: ['kaduino'],\r\n           func: function(sprite, script) \r\n\t\t   {\r\n                var port = script.getNumberValue('PORT');\r\n                var value = script.getNumberValue('VALUE');\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = {\r\n                    type: Entry.kaduino.sensorTypes.DIGITAL,    /// 출력 디바이스\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\t\t\t\t\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n\t\t\r\n\t\t// 11. 디지털입력\t\t\r\n        kaduino_get_digital_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            template: Lang.template.kaduino_get_digital_value,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_digital_port_list',\r\n                    },\r\n                ],\r\n                type: 'kaduino_get_digital_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'kaduino_LV3',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\t\t\r\n                var port = script.getNumberValue('PORT');\r\n                var DIGITAL = Entry.hw.portData.DIGITAL;\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['GET'][ \r\n                    Entry.kaduino.sensorTypes.DIGITAL\r\n                ] = {\r\n                    port: port,\r\n                    time: new Date().getTime(),\r\n                };\r\n\t\t\r\n\t\t\t\treturn DIGITAL[port];\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\t\r\n        \r\n        // 12. 아날로그 읽기\r\n        kaduino_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.kaduino_get_analog_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_analog_port_list',\r\n                    },\t\t\t\t\r\n                ],\r\n                type: 'kaduino_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n\t\t\t\tTYPE: 1,\r\n            },\r\n            class: 'kaduino_LV3',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var btn_index = script.getNumberValue('PORT');\t\t\t\t\r\n                var ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                return ANALOG[btn_index];\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 13.  PWM 제어 \t\r\n\t\tkaduino_set_pwm: \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_pwn_port_list',\r\n                    },\t\t\t\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tPORT: 0,\r\n                ANGLE: 1,\r\n            },\r\n            class: 'kaduino_LV3',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var port = script.getNumberValue('PORT', script);\r\n                var angle = script.getNumberValue('ANGLE', script);\r\n\t\t\t\t//var mode = 2;\r\n                //port += 2;\r\n                \r\n                angle = Math.min(180, angle);\r\n                angle = Math.max(0, angle);\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t{\r\n                    type: Entry.kaduino.sensorTypes.PWM,\r\n                    data: angle,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 14. 초음파센서 설정\r\n        kaduino_set_ultrasonic:   \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_ultrasonic_port_list',\r\n                        params: ['11'],\r\n                    },\t\t\t\r\n                    {\r\n                        type: 'kaduino_ultrasonic_port_list',\r\n                        params: ['10'],\r\n                    },\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_ultrasonic',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tTRIG: 0,\r\n                ECHO: 1,\r\n            },\r\n            class: 'kaduino_LV4',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var trig = script.getNumberValue('TRIG', script);\r\n                var echo = script.getNumberValue('ECHO', script);\r\n\t\t\t\t//var mode = 2;\r\n                var port = trig;\r\n\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t{\r\n                    type: Entry.kaduino.sensorTypes.USONIC,\r\n                    data: echo,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 15. 초음파 센서 값\t\t\r\n        kaduino_get_usonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.kaduino_get_usonic_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kaduino_get_usonic_value',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kaduino_LV4',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) {\r\n //               var us = Entry.hw.portData.USONIC ;\r\n\r\n//                if (!Entry.hw.sendQueue['SET']) {\r\n//                    Entry.hw.sendQueue['SET'] = {};\r\n//                }\r\n//                delete Entry.hw.sendQueue['SET'][port1];\r\n//                delete Entry.hw.sendQueue['SET'][port2];\r\n\t\t\t\t\r\n/*                if (!Entry.hw.sendQueue['GET']) {\r\n                    Entry.hw.sendQueue['GET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['GET'][\r\n                    Entry.kaduino.sensorTypes.USONIC\t\t\r\n                ] = {\r\n                    port: [port1, port2],\r\n                    time: new Date().getTime(),\r\n                };*/\r\n//                Entry.hw.update();\r\n\r\n//                var time2 = new Date().getTime();\r\n//                while(time2 + 1000 > new Date().getTime());\r\n  \r\n                return Entry.hw.portData.USONIC;// || 0;\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        //16. 온도센서 연결핀 설정\r\n        kaduino_set_temp:   \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_digital_port_list',\r\n                        params: ['14'],\r\n                    },\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_temp',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tSENSOR: 0,\r\n            },\r\n            class: 'kaduino_LV4',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var sensor = script.getNumberValue('SENSOR', script);\r\n                var port = sensor;\r\n\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t{\r\n                    type: Entry.kaduino.sensorTypes.TEMP,\r\n                    data: sensor,\r\n                    time: new Date().getTime(),\r\n                };\r\n               // return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 17. 온도센서값 읽기\r\n        kaduino_get_temp_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.kaduino_get_temp_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kaduino_get_temp_value',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kaduino_LV4',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) {\r\n \r\n                return Entry.hw.portData.TEMP;// || 0;\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 18. i2c포트 센서연결 설정\r\n        kaduino_set_i2c:   \r\n\t\t{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_i2c_sen_list',\r\n                        params: ['1'],\r\n                    },\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_i2c',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tSENSOR: 0,\r\n            },\r\n            class: 'kaduino_LV4',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var sensor = script.getNumberValue('SENSOR', script);\r\n                var port = sensor;\r\n\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][port] = \r\n\t\t\t\t{\r\n                    type: Entry.kaduino.sensorTypes.I2C_SET,\r\n                    data: sensor,\r\n                    time: new Date().getTime(),\r\n                };\r\n               // return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 19. 컬러센서값\r\n        kaduino_get_color_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.kaduino_get_color_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['R', '1'],\r\n                        ['G', '2'],\r\n                        ['B', '3']\r\n                    ],\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                }\r\n\t\t\t\t\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['1'],\r\n                type: 'kaduino_get_color_value',\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0,\r\n            },\r\n            class: 'kaduino_LV4',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var btn_index = script.getField('COLOR');\t\t\t\t\r\n\r\n                return Entry.hw.portData.COLOR_SEN[btn_index-1];\r\n            },\r\n           \r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 20. 자이로센서값\r\n        kaduino_get_gyro_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.kaduino_get_gyro_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['angle X', '1'],\r\n                        ['angle Y', '2'],\r\n                        ['angle Z', '3'],\r\n                        ['acc X', '4'],\r\n                        ['acc Y', '5'],\r\n                        ['acc Z', '6']\r\n                    ],\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                }\r\n\t\t\t\t\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['1'],\r\n                type: 'kaduino_get_gyro_value',\r\n            },\r\n            paramsKeyMap: {\r\n                GYRO: 0,\r\n            },\r\n            class: 'kaduino_LV4',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var btn_index = script.getField('GYRO');\t\t\t\t\r\n\r\n                return Entry.hw.portData.GYRO_SEN[btn_index-1];\r\n            },\r\n           \r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 21. LCD글자출력\r\n        kaduino_set_lcd_string:\r\n        {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"0\"],\r\n                    },\r\n                    {\r\n                        type: 'text', \r\n                        params: ['Hello, Kaduino'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_lcd_string',\r\n            },\r\n            paramsKeyMap: {\r\n                COLUMN: 0,\r\n                LINE: 1,\r\n                STRING: 2,\r\n            },\r\n            class: 'kaduino_LV5',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                \r\n         //       var sq = Entry.hw.sendQueue;\r\n                var line = script.getValue('LINE', script);\r\n                var column = script.getValue('COLUMN', script);\r\n                var string = script.getValue('STRING', script);\r\n                var text = [];\r\n\r\n                if (!script.isStart) {\r\n                    if (typeof string === 'string') {\r\n                        for (var i = 0; i < string.length; i++) {\r\n                            text[i] = Entry.memaker.toByte(string[i]);\r\n                        }\r\n                    } else if (typeof string === 'number') {\r\n                        var num_to_string = string.toString();\r\n                        for (var i = 0; i < num_to_string.length; i++) {\r\n                            text[i] = Entry.memaker.toByte(num_to_string[i]);\r\n                        }\r\n                    } else {\r\n                        text[0] = string;\r\n                    }\r\n\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    //var fps = Entry.FPS || 60;\r\n                   // var timeValue = 60 / fps * 50;\r\n\r\n                    Entry.hw.sendQueue['SET'][3] = {\r\n                        type: Entry.kaduino.sensorTypes.LCD_SET,\r\n                        data: {\r\n                            line: line,\r\n                            column: column,\r\n                            text0: text[0],\r\n                            text1: text[1],\r\n                            text2: text[2],\r\n                            text3: text[3],\r\n                            text4: text[4],\r\n                            text5: text[5],\r\n                            text6: text[6],\r\n                            text7: text[7],\r\n                            text8: text[8],\r\n                            text9: text[9],\r\n                            text10: text[10],\r\n                            text11: text[11],\r\n                            text12: text[12],\r\n                            text13: text[13],\r\n                            text14: text[14],\r\n                            text15: text[15],\r\n                            text15: text[16],\r\n                            text15: text[17],\r\n                            text15: text[18],\r\n                            text15: text[19],\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, delay_time);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = true;\r\n                    return script.callReturn();\r\n                }\r\n                 \r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 22. LCD 연결설정\r\n\t\tkaduino_set_lcd_init: \r\n        {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'kaduino_lcd_add_list', \r\n                        params: [\"39\"],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"16\"],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: [\"2\"],\r\n                    },\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_lcd_init',\r\n            },\r\n            paramsKeyMap: {\r\n                LCD_ADD:0,\r\n                Y_LINE:1,\r\n                X_LINE:2,\r\n            },\r\n            class: 'kaduino_LV5',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                //var port = 0;\r\n                var lcd_add = script.getNumberValue('LCD_ADD', script);  // 주소\r\n                var y_line = script.getNumberValue('Y_LINE', script);  // 세로 줄수\r\n                var x_line = script.getNumberValue('X_LINE', script);  // 가로 줄수\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][1] = {\r\n                    type: Entry.kaduino.sensorTypes.LCD_SET,\r\n                    data: [\r\n                        lcd_add,\r\n                        y_line,\r\n                        x_line,\r\n                    ],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\t\r\n        // 23. LCD 지우기\r\n\t\tkaduino_set_lcd_clear: \r\n        {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\t\t\t\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kaduino_set_lcd_clear',\r\n            },\r\n            paramsKeyMap: {\r\n\r\n            },\r\n            class: 'kaduino_LV5',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                //var port = 0;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n                Entry.hw.sendQueue['SET'][4] = {\r\n                    type: Entry.kaduino.sensorTypes.LCD_SET,\r\n                    data: [\r\n                        4,\r\n                        4,\r\n                        4,\r\n                    ],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n\r\n   \r\n\t\t\r\n\t\t// 3. 소리/빛/가변저항 - 2) mapping 값\t\t\t\r\n        kaduino_get_analog_mapping: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.kaduino_get_analog_mapping,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\t\t\t\t\t\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'kaduino_get_analog_mapping',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tIDATA: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'kaduino_ANA',\r\n            isNotFor: ['kaduino'],\r\n            func: function(sprite, script) \r\n\t\t\t{\r\n                var result = script.getNumberValue('IDATA', script);\t\t\t\t\r\n                var value2 = script.getNumberValue('VALUE2', script);\r\n                var value3 = script.getNumberValue('VALUE3', script);\r\n                var value4 = script.getNumberValue('VALUE4', script);\r\n                var value5 = script.getNumberValue('VALUE5', script);\r\n\t\t\t\r\n\t\t\t\t\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                return Math.round(result);\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\t\t\t\r\n\t\t\r\n\r\n\t\t\r\n   \r\n       \r\n\r\n\t\t\r\n\t\r\n\t\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.kaduino;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_kamibot.js",
    "content": "'use strict';\r\n\r\nconst COMMAND_TYPE = {\r\n    MOVE_FORWARD: 0x01,\r\n    TURN_LEFT: 0x02,\r\n    TURN_RIGHT: 0x03,\r\n    TURN_BACK: 0x04,\r\n    TOGGLE_LINERRACER: 0x05,\r\n    MOVE_FORWARD_SPEED: 0x06,\r\n    MOVE_LEFT_SPEED: 0x07,\r\n    MOVE_RIGHT_SPEED: 0x08,\r\n    MOVE_BACKWARD_SPEED: 0x09,\r\n    MOVE_FORWARD_LRSPEED: 0x0A,\r\n    MOVE_BACKWARD_LRSPEED: 0x0B,\r\n    STOP_KAMIBOT: 0x0C,\r\n    RESET_KAMIBOT: 0x0D,\r\n    SET_LED_COLOR: 0x0E,\r\n    SET_SERVER_MOTOR: 0x10,\r\n    GET_ULTRASONIC: 0x11,\r\n    GET_IR: 0x12,\r\n    KAMIBOT_CLEAR: 0x17,\r\n    RESET:0xFF\r\n};\r\n\r\nEntry.Kamibot = {\r\n    id: '42.1',\r\n    name: 'kamibot',\r\n    url: 'http://www.kamibot.com/',\r\n    imageName: 'kamibot.png',\r\n    title: {\r\n        ko: '카미봇',\r\n        en: 'Kamibot',\r\n    },\r\n\r\n    getHashKey: function() {\r\n        let key = new Date().getSeconds().toString(16);\r\n        if (key.length === 1) {\r\n            key += ((Math.random() * 16) | 0).toString(16);\r\n        }\r\n        return Entry.generateHash() + key;\r\n    },\r\n\r\n    /**\r\n     * 정지버튼을 누르면 실행\r\n     */\r\n    setZero: function() {\r\n        Entry.hw.update(); // 해당 데이터를 하드웨어에 전달한다.\r\n    },\r\n};\r\n\r\nEntry.Kamibot.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                kamibot_move_forward: \"{ 블록 }: 앞으로 %1 칸 가기 %2\",\r\n                kamibot_turn_left: \"{ 블록 }: 왼쪽으로 돌기 %1\",\r\n                kamibot_turn_right: \"{ 블록 }: 오른쪽으로 돌기 %1\",\r\n                kamibot_turn_back: \"{ 블록 }: 뒤로 돌기 %1\",\r\n                kamibot_linetracer_speed: \"선따라 이동 속도 %1 로 정하기 %2\",\r\n                kamibot_linetracer: \"선따라 이동하기 %1 %2\",\r\n                kamibot_forward_speed: \"앞으로 %1 속도로 가기 %2\",\r\n                kamibot_left_speed: \"왼쪽으로 %1 속도로 돌기 %2\",\r\n                kamibot_right_speed: \"오른쪽으로 %1 속도로 돌기 %2\",\r\n                kamibot_backward_speed: \"뒤로 %1 속도로 가기 %2\",\r\n                kamibot_forward_lr_speed: \"앞으로 속도 왼쪽: %1 오른쪽: %2 %3\",\r\n                kamibot_backward_lr_speed: \"뒤로 속도 왼쪽: %1 오른쪽: %2 %3\",\r\n                kamibot_stop: \"멈추기 %1\",\r\n                kamibot_color: \"LED %1 으로 바꾸기 %2\",\r\n                kamibot_servor: \"서보모터 %1 도 위치로 설정 %2\",\r\n                kamibot_ultrasonic: \"초음파센서 %1\",\r\n                kamibot_infrared: \"적외선 센서 %1 번 %2\"\r\n            },\r\n            Blocks: {\r\n                kamibot_toggle_on: '켜기',\r\n                kamibot_toggle_off: '끄기',\r\n                kamibot_color_red: '빨강',\r\n                kamibot_color_pink: '분홍',\r\n                kamibot_color_blue: '파랑',\r\n                kamibot_color_sky: '하늘',\r\n                kamibot_color_green: '초록',\r\n                kamibot_color_yellow: '노랑',\r\n                kamibot_color_white: '하양',\r\n            }\r\n        },\r\n        en: {\r\n            template: {\r\n                kamibot_move_forward: \"{block}: move forward %1 block %2\",\r\n                kamibot_turn_left: \"{block}: turn left %1\",\r\n                kamibot_turn_right: \"{block}: turn right %1\",\r\n                kamibot_turn_back: \"{block}: turn back %1\",\r\n                kamibot_linetracer_speed: \"set linetracer speed %1 %2\",\r\n                kamibot_linetracer: \"turn linetracer %1 %2\",\r\n                kamibot_forward_speed: \"move forward speed: %1 %2\",\r\n                kamibot_left_speed: \"move left speed: %1 %2\",\r\n                kamibot_right_speed: \"move right speed: %1 %2\",\r\n                kamibot_backward_speed: \"move backward speed: %1 %2\",\r\n                kamibot_forward_lr_speed: \"move forward speed Left: %1 Right: %2 %3\",\r\n                kamibot_backward_lr_speed: \"move backward speed Left: %1 Right: %2 %3\",\r\n                kamibot_stop: \"stop %1\",\r\n                kamibot_color: \"set LED color to %1 %2\",\r\n                kamibot_servor: \"set servor motor to %1 %2\",\r\n                kamibot_ultrasonic: \"ultrasonic sensor %1\",\r\n                kamibot_infrared: \"%1 infrared sensor %2\"\r\n            },\r\n            Blocks: {\r\n                kamibot_toggle_on: 'on',\r\n                kamibot_toggle_off: 'off',\r\n                kamibot_color_red: 'red',\r\n                kamibot_color_pink: 'pink',\r\n                kamibot_color_blue: 'blue',\r\n                kamibot_color_sky: 'sky',\r\n                kamibot_color_green: 'green',\r\n                kamibot_color_yellow: 'yellow',\r\n                kamibot_color_white: 'white',\r\n            }\r\n        },\r\n    };\r\n};\r\n\r\nEntry.Kamibot.blockMenuBlocks = [\r\n    \r\n    'kamibot_move_forward',\r\n    'kamibot_turn_left',\r\n    'kamibot_turn_right',\r\n    'kamibot_turn_back',\r\n    'kamibot_forward_speed',\r\n    'kamibot_left_speed',\r\n    'kamibot_right_speed',\r\n    'kamibot_backward_speed',\r\n    'kamibot_forward_lr_speed',\r\n    'kamibot_backward_lr_speed',\r\n    'kamibot_stop',\r\n    'kamibot_color',\r\n    'kamibot_servor',\r\n    'kamibot_ultrasonic',\r\n    'kamibot_infrared',\r\n];\r\n\r\nEntry.Kamibot.getBlocks = function() {\r\n    return {\r\n        kamibot_move_forward: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [1],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_move_forward',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'kamibot_mapboard',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                const value = parseInt( script.getValue('VALUE'));\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MOVE_FORWARD,\r\n                        data: {\r\n                            param1:value,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_turn_left: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_turn_left',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kamibot_mapboard',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.TURN_LEFT,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_turn_right: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_turn_right',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kamibot_mapboard',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.TURN_RIGHT,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_turn_back: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_turn_back',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kamibot_mapboard',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.TURN_BACK,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_forward_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_forward_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                SPEED: 0,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const speed = script.getValue('SPEED');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MOVE_FORWARD_SPEED,\r\n                        data: {\r\n                            param1:speed,\r\n                            param2:speed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_left_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_left_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                SPEED: 0,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const speed = script.getValue('SPEED');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MOVE_LEFT_SPEED,\r\n                        data: {\r\n                            param1:speed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_right_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_right_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                SPEED: 0,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                const speed = script.getValue('SPEED');\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MOVE_RIGHT_SPEED,\r\n                        data: {\r\n                            param1:speed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_backward_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_backward_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                SPEED: 0,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const speed = script.getValue('SPEED');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MOVE_BACKWARD_SPEED,\r\n                        data: {\r\n                            param1:speed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        // '----------------------------------------------------------------------------'\r\n        kamibot_forward_lr_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_forward_lr_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                RSPEED: 1,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const lspeed = script.getValue('LSPEED');\r\n                const rspeed = script.getValue('RSPEED');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MOVE_FORWARD_LRSPEED,\r\n                        data: {\r\n                            param1:lspeed,\r\n                            param2:rspeed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_backward_lr_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_backward_lr_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED:0,\r\n                RSPEED:1,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const lspeed = script.getValue('LSPEED');\r\n                const rspeed = script.getValue('RSPEED');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MOVE_BACKWARD_LRSPEED,\r\n                        data: {\r\n                            param1:lspeed,\r\n                            param2:rspeed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_stop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_stop',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.STOP_KAMIBOT,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_color: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_color_red, 'red'],\r\n                        [Lang.Blocks.kamibot_color_pink, 'pink'],\r\n                        [Lang.Blocks.kamibot_color_blue, 'blue'],\r\n                        [Lang.Blocks.kamibot_color_sky, 'sky'],\r\n                        [Lang.Blocks.kamibot_color_green, 'green'],\r\n                        [Lang.Blocks.kamibot_color_yellow, 'yellow'],\r\n                        [Lang.Blocks.kamibot_color_white, 'white'],\r\n                    ],\r\n                    value: 'green',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_color',\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const color = script.getField('COLOR');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.SET_LED_COLOR,\r\n                        data: {\r\n                            param1:color,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n            syntax: undefined,\r\n        },\r\n        kamibot_servor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['15', '15'],\r\n                        ['30', '30'],\r\n                        ['45', '45'],\r\n                        ['60', '60'],\r\n                        ['75', '75'],\r\n                        ['90', '90'],\r\n                        ['105', '105'],\r\n                        ['120', '120'],\r\n                        ['135', '135'],\r\n                        ['150', '150'],\r\n                        ['165', '165'],\r\n                        ['180', '180'],\r\n                    ],\r\n                    value: '90',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_servor',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const angle = parseInt(script.getField('VALUE'), 10);\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.Kamibot.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.SET_SERVER_MOTOR,\r\n                        data: {\r\n                            param1:angle,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        // '-------------------------------------------------------------------------------------'\r\n        kamibot_ultrasonic: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_ultrasonic',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = 0;\r\n                if (pd.sensorData) {\r\n                    retVal = pd.sensorData.ultra;\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n        kamibot_infrared: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_infrared',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibot'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                const no = parseInt(script.getField('VALUE'), 10);\r\n                \r\n                let retVal = 0;\r\n                if (pd.sensorData) {\r\n                    if (no === 1) {\r\n                        retVal = pd.sensorData.lir1;\r\n                    } else if (no === 2) {\r\n                        retVal = pd.sensorData.lir2;\r\n                    } else if (no === 3) {\r\n                        retVal = pd.sensorData.cir;\r\n                    } else if (no === 4) {\r\n                        retVal = pd.sensorData.rir1;\r\n                    } else if (no === 5) {\r\n                        retVal = pd.sensorData.rir2;\r\n                    }\r\n                }\r\n                return retVal.toString(10);\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.Kamibot;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_kamibotPi.js",
    "content": "'use strict';\r\n\r\nconst COMMAND_TYPE = {\r\n    BLOCK_MOVE_FORWARD: 0x01,\r\n    BLOCK_MOVE_BACKWARD: 0x21,\r\n    BLOCK_TURN_LEFT: 0x02,\r\n    BLOCK_TURN_RIGHT: 0x03,\r\n    BLOCK_TURN_BACK: 0x04,\r\n    /** */\r\n    MOVE_FORWARD_LINE: 0x22,\r\n    TURN_LEFT_LINE: 0x23,\r\n    TURN_RIGHT_LINE: 0x24,\r\n    TURN_BACK_LINE: 0x25,\r\n    /** */\r\n    TOGGLE_LINERRACER: 0x05,\r\n    MOVE_FORWARD_SPEED: 0x06,\r\n    MOVE_LEFT_SPEED: 0x07,\r\n    MOVE_RIGHT_SPEED: 0x08,\r\n    MOVE_BACKWARD_SPEED: 0x09,\r\n    MOVE_FORWARD_LRSPEED: 0x0A,\r\n    MOVE_BACKWARD_LRSPEED: 0x0B,\r\n    MOVE_LRSPEED: 0x26,\r\n\r\n    MOVE_UNIT:0x27,\r\n    SPIN_DEGREE:0x28,\r\n\r\n    TOPMOTOR_TURN:0x29,\r\n    TOPMOTOR_MOVE_ABSOLUTE: 0x2A,\r\n    TOPMOTOR_MOVE_RELATIVE: 0x2B,\r\n    TOPMOTOR_STOP: 0x2C,\r\n\r\n    STOP_KAMIBOT: 0x0C,\r\n    RESET_KAMIBOT: 0x0D,\r\n    SET_LED_COLOR: 0x0E,\r\n    LED_TURN:0x2D,\r\n\r\n    DRAW_SHAPE: 0x31,\r\n    DRAW_CIRCLE:  0x32,\r\n    MELODY_BEEP: 0x33,\r\n    MELODY_MUTE: 0x34,\r\n\r\n    EMERGENCY_STOP: 0x35,\r\n    RESET_INITIALIZE: 0x36,\r\n\r\n    KAMIBOT_CLEAR: 0x17,\r\n    PING: 0x18,\r\n    RESET:0xFF\r\n};\r\n\r\n\r\nEntry.KamibotPi = {\r\n    id: '42.2',\r\n    name: 'kamibotPi',\r\n    url: 'http://www.kamibot.com/',\r\n    imageName: 'kamibotPi.png',\r\n    title: {\r\n        ko: '카미봇Pi',\r\n        en: 'KamibotPi',\r\n    },\r\n    moveSpeed: 100,\r\n\r\n    getHashKey: function() {\r\n        let key = new Date().getSeconds().toString(16);\r\n        if (key.length === 1) {\r\n            key += ((Math.random() * 16) | 0).toString(16);\r\n        }\r\n        return Entry.generateHash() + key;\r\n    },\r\n\r\n    /**\r\n     * 정지버튼을 누르면 실행\r\n     */\r\n    setZero: function() {\r\n        const sq = Entry.hw.sendQueue;\r\n        const pd = Entry.hw.portData;\r\n\r\n        const msgId = Entry.KamibotPi.getHashKey();\r\n        sq.msg_id = msgId;\r\n        const msg = {\r\n            id: msgId,\r\n            type: COMMAND_TYPE.EMERGENCY_STOP,\r\n            data: {\r\n            },\r\n            time: Date.now()\r\n        };\r\n        sq.msg = msg;\r\n\r\n        Entry.hw.update(); // 해당 데이터를 하드웨어에 전달한다.\r\n    },\r\n\r\n    clamp: function(n, min, max) {\r\n        return Math.min(Math.max(n, min), max);\r\n    }\r\n};\r\n\r\nEntry.KamibotPi.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                kamibot_move_forward: \"{ 블록 }: %1 %2 칸 가기 %3\",\r\n                kamibot_turn_left: \"{ 블록 }: %1으로 돌기 %2\",\r\n                kamibot_turn_right: \"{ 블록 }: 오른쪽으로 돌기 %1\",\r\n                kamibot_turn_back: \"{ 블록 }: 뒤로 돌기 %1\",\r\n                /** */\r\n                kamibot_move_forward_line: \"{ 라인 }: 앞으로 %1칸 가기 %2\",\r\n                kamibot_turn_left_line: \"{ 라인 }: %1으로 돌기 %2\",\r\n                /** */\r\n                kamibot_linetracer_speed: \"선따라 이동 속도 %1 로 정하기 %2\",\r\n                kamibot_linetracer: \"선따라 이동하기 %1 %2\",\r\n\r\n                kamibot_forward_speed: \"%1 %2 속도로 가기 %3\",\r\n                kamibot_left_speed: \"%1으로 %2 속도로 돌기 %3\",\r\n\r\n                kamibot_lspeed_rspeed: \"왼쪽바퀴:속도 %1 %2, 오른쪽바퀴:속도 %3 %4 %5\",\r\n                kamibot_move_unit: \"%1 속도: %2으로 %3 cm 이동 %4\",\r\n                kamibot_spin_unit: \"%1 도 %2으로 제자리 돌기 %3\",\r\n\r\n                kamibot_topmotor_turn:\"머리 %1으로 돌리기 %2\",\r\n                kamibot_topmotor_move_abs:\"머리 %1도 위치로 이동 %2\",\r\n                kamibot_topmotor_move_relative:\"머리 %1도 만큼 회전 %2\",\r\n                kamibot_topmotor_stop:\"머리 멈추기 %1\",\r\n                kamibot_stop: \"이동 멈추기 %1\",\r\n\r\n                kamibot_draw_shape:\"한 변(지름) %1cm인 %2 그리기 %3\",\r\n\r\n                kamibot_color_rgb:'LED R:%1 G:%2 B:%3 으로 바꾸기 %4',\r\n                kamibot_color: \"LED %1 으로 바꾸기 %2\",\r\n                \r\n                kamibot_melody_beep: \"%1번 음계 %2초동안 연주하기 %3\",\r\n\r\n                kamibot_distance_sensor:\"%1 근접센서 %2\",\r\n                kamibot_line_sensor:\"%1 바닥센서 %2\",\r\n                kamibot_color_sensor:\"컬러센서 %1값 %2\",\r\n\r\n                kamibot_all_stop:\"모두 멈추기 %1\",\r\n                kamibot_initialize:\"상태 초기화 %1\"\r\n\r\n            },\r\n            Blocks: {\r\n                kamibot_dir_forward: '앞으로',\r\n                kamibot_dir_backward: '뒤로',\r\n                kamibot_dir_left: '왼쪽',\r\n                kamibot_dir_right: '오른쪽',\r\n                kamibot_dir_center: '중앙',\r\n                kamibot_toggle_on: '켜기',\r\n                kamibot_toggle_off: '끄기',\r\n                kamibot_color_red: '빨강',\r\n                kamibot_color_pink: '분홍',\r\n                kamibot_color_blue: '파랑',\r\n                kamibot_color_sky: '하늘',\r\n                kamibot_color_green: '초록',\r\n                kamibot_color_yellow: '노랑',\r\n                kamibot_color_white: '하양',\r\n                kamibot_color_tri: '삼각형',\r\n                kamibot_color_rec: '사각형',\r\n                kamibot_color_penta: '오각형',\r\n                kamibot_color_hexa: '육각형',\r\n                kamibot_color_star: '별',\r\n                kamibot_color_circle: '원',\r\n                kamibot_color_r:'R',\r\n                kamibot_color_g:'G',\r\n                kamibot_color_b:'B',\r\n            }\r\n        },\r\n        en: {\r\n            template: {\r\n                kamibot_move_forward: \"{block}: move %1 %2 block %3\",\r\n                kamibot_turn_left: \"{block}: turn %1 %2\",\r\n                kamibot_turn_right: \"{block}: turn right %1\",\r\n                kamibot_turn_back: \"{block}: turn back %1\",\r\n                /** */\r\n                kamibot_move_forward_line: \"{ line }: move forward %1 %2\",\r\n                kamibot_turn_left_line: \"{ line }: turn %1 %2\",\r\n                /** */\r\n                kamibot_linetracer_speed: \"set linetracer speed %1 %2\",\r\n                kamibot_linetracer: \"turn linetracer %1 %2\",\r\n\r\n                kamibot_forward_speed: \"move %1 speed: %2 %3\",\r\n                kamibot_left_speed: \"move %1 speed: %2 %3\",\r\n\r\n                kamibot_lspeed_rspeed: \"left wheel:speed %1 %2, right wheel:speed %3 %4 %5\",\r\n                kamibot_move_unit: \"move %1 speed:%2 %3 cm %4\",\r\n                kamibot_spin_unit: \"%1 degree, turn %2 %3\",\r\n\r\n                kamibot_topmotor_turn:\"top-motor turn %1 %2\",\r\n                kamibot_topmotor_move_abs:\"turn top-motor abs position %1 %2\",\r\n                kamibot_topmotor_move_relative:\"turn top-motor relative position %1 %2\",\r\n                kamibot_topmotor_stop:\"stop top-motor %1\",\r\n                kamibot_stop: \"stop %1\",\r\n\r\n                kamibot_draw_shape:\"length %1 cm draw %2 %3\",\r\n\r\n                kamibot_color: \"set LED color to %1 %2\",\r\n                kamibot_color_rgb: \"set LED color to R:%1, G:%2, B:%3 %4\",\r\n\r\n                kamibot_melody_beep: \"make sound number %1, %2sec %3\",\r\n\r\n                kamibot_distance_sensor:\"%1 distance sensor %2\",\r\n                kamibot_line_sensor:\"%1 line seonsor %2\",\r\n                kamibot_color_sensor:\"color sensor %1 %2\",\r\n\r\n                kamibot_all_stop:\"all stop %1\",\r\n                kamibot_initialize:\"state reset %1\"\r\n            },\r\n            Blocks: {\r\n                kamibot_dir_forward: 'forward',\r\n                kamibot_dir_backward: 'backward',\r\n                kamibot_dir_left: 'left',\r\n                kamibot_dir_right: 'right',\r\n                kamibot_dir_center: 'center',\r\n                kamibot_toggle_on: 'on',\r\n                kamibot_toggle_off: 'off',\r\n                kamibot_color_red: 'red',\r\n                kamibot_color_pink: 'pink',\r\n                kamibot_color_blue: 'blue',\r\n                kamibot_color_sky: 'sky',\r\n                kamibot_color_green: 'green',\r\n                kamibot_color_yellow: 'yellow',\r\n                kamibot_color_white: 'white',\r\n                kamibot_color_tri: 'triangle',\r\n                kamibot_color_rec: 'rectangle',\r\n                kamibot_color_penta: 'pentagon',\r\n                kamibot_color_hexa: 'hexagon',\r\n                kamibot_color_star: 'star',\r\n                kamibot_color_circle: 'circle',\r\n                kamibot_color_r:'R',\r\n                kamibot_color_g:'G',\r\n                kamibot_color_b:'B',\r\n            }\r\n        },\r\n    };\r\n};\r\n\r\nEntry.KamibotPi.blockMenuBlocks = [\r\n    \r\n    'kamibot_move_forward',\r\n    'kamibot_turn_left',\r\n\r\n    'kamibot_move_forward_line',\r\n    'kamibot_turn_left_line',\r\n    // '-----------------------------' \r\n    'kamibot_color',\r\n    'kamibot_color_rgb',\r\n\r\n    'kamibot_draw_shape',\r\n    'kamibot_melody_beep',\r\n\r\n    'kamibot_distance_sensor',\r\n    'kamibot_line_sensor',\r\n    'kamibot_color_sensor',\r\n    // '-----------------------------' \r\n    'kamibot_forward_speed',\r\n    'kamibot_left_speed',\r\n    'kamibot_lspeed_rspeed',\r\n    'kamibot_move_unit',\r\n    'kamibot_spin_unit',\r\n    'kamibot_stop',\r\n\r\n    'kamibot_topmotor_turn',\r\n    'kamibot_topmotor_move_abs',\r\n    'kamibot_topmotor_move_relative',\r\n    'kamibot_topmotor_stop',\r\n\r\n    'kamibot_all_stop',\r\n    'kamibot_initialize',\r\n\r\n];\r\n\r\nEntry.KamibotPi.getBlocks = function() {\r\n    return {\r\n        kamibot_move_forward: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_forward, 'forward'],\r\n                        [Lang.Blocks.kamibot_dir_backward, 'backward'],\r\n                    ],\r\n                    value: 'forward',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: [1],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_move_forward',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_DIR:0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'kamibot_mapboard',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const moveDir = script.getField('MOVE_DIR');\r\n                const value = parseInt( script.getValue('VALUE'));\r\n                let type = COMMAND_TYPE.BLOCK_MOVE_FORWARD;\r\n                if(moveDir == 'backward') {\r\n                    type = COMMAND_TYPE.BLOCK_MOVE_BACKWARD;\r\n                }\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:value,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_turn_left: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_left, 'left'],\r\n                        [Lang.Blocks.kamibot_dir_right, 'right'],\r\n                        [Lang.Blocks.kamibot_dir_backward, 'backward'],\r\n                    ],\r\n                    value: 'left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_turn_left',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_DIR:0,\r\n            },\r\n            class: 'kamibot_mapboard',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const moveDir = script.getField('MOVE_DIR');\r\n                let type = COMMAND_TYPE.BLOCK_TURN_LEFT;\r\n                if(moveDir == 'right') {\r\n                    type = COMMAND_TYPE.BLOCK_TURN_RIGHT;\r\n                } else if(moveDir == 'backward') {\r\n                    type = COMMAND_TYPE.BLOCK_TURN_BACK;\r\n                }\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        // '----------------------------------------------------------------------------'\r\n        kamibot_move_forward_line: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [1],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_move_forward_line',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'kamibot_mapboard',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const value = parseInt( script.getValue('VALUE'));\r\n                let type = COMMAND_TYPE.MOVE_FORWARD_LINE;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:value,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_turn_left_line: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_left, 'left'],\r\n                        [Lang.Blocks.kamibot_dir_right, 'right'],\r\n                        [Lang.Blocks.kamibot_dir_backward, 'backward'],\r\n                    ],\r\n                    value: 'left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_turn_left_line',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_DIR:0,\r\n            },\r\n            class: 'kamibot_mapboard',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const moveDir = script.getField('MOVE_DIR');\r\n                console.log('moveDir', moveDir)\r\n                let type = COMMAND_TYPE.TURN_LEFT_LINE;\r\n                if(moveDir == 'right') {\r\n                    type = COMMAND_TYPE.TURN_RIGHT_LINE;\r\n                } else if(moveDir == 'backward') {\r\n                    type = COMMAND_TYPE.TURN_BACK_LINE;\r\n                }\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        // '----------------------------------------------------------------------------'\r\n        kamibot_set_speed:{\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [100],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_set_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                SPEED:0,\r\n            },\r\n            class: 'kamibotpi_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const speed = parseInt( script.getValue('SPEED'));\r\n                Entry.KamibotPi.moveSpeed = speed;\r\n                return null;\r\n            },\r\n        },\r\n        // '----------------------------------------------------------------------------'\r\n        kamibot_forward_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_forward, 'forward'],\r\n                        [Lang.Blocks.kamibot_dir_backward, 'backward'],\r\n                    ],\r\n                    value: 'forward',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_forward_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_DIR:0,\r\n                SPEED: 1,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const moveDir = script.getField('MOVE_DIR');\r\n                const speed = script.getValue('SPEED');\r\n                let type = COMMAND_TYPE.MOVE_FORWARD_SPEED;\r\n                if(moveDir == 'backward') {\r\n                    type = COMMAND_TYPE.MOVE_BACKWARD_SPEED;\r\n                }\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:speed,\r\n                            param2:speed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_left_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_left, 'left'],\r\n                        [Lang.Blocks.kamibot_dir_right, 'right'],\r\n                    ],\r\n                    value: 'left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_left_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_DIR:0,\r\n                SPEED: 1,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const speed = script.getValue('SPEED');\r\n                const moveDir = script.getField('MOVE_DIR');\r\n                console.log('moveDir', moveDir)\r\n                let type = COMMAND_TYPE.MOVE_LEFT_SPEED;\r\n                if(moveDir == 'right') {\r\n                    type = COMMAND_TYPE.MOVE_RIGHT_SPEED;\r\n                } \r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:speed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_lspeed_rspeed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_forward, 'forward'],\r\n                        [Lang.Blocks.kamibot_dir_backward, 'backward'],\r\n                    ],\r\n                    value: 'forward',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_forward, 'forward'],\r\n                        [Lang.Blocks.kamibot_dir_backward, 'backward'],\r\n                    ],\r\n                    value: 'forward',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_lspeed_rspeed',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                L_DIR:1,\r\n                RSPEED: 2,\r\n                R_DIR:3,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const lspeed = script.getValue('LSPEED');\r\n                const rspeed = script.getValue('RSPEED');\r\n                let leftDir = script.getField('L_DIR');\r\n                let rightDir = script.getField('R_DIR');\r\n                \r\n                if(leftDir == 'backward') {\r\n                    leftDir = 0x01\r\n                } else {\r\n                    leftDir = 0x00\r\n                }\r\n                if(rightDir == 'backward') {\r\n                    rightDir = 0x01\r\n                }else {\r\n                    rightDir = 0x00\r\n                }\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MOVE_LRSPEED,\r\n                        data: {\r\n                            param1:lspeed,\r\n                            param2:leftDir,\r\n                            param3:rspeed,\r\n                            param4:rightDir,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_move_unit: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_forward, 'forward'],\r\n                        [Lang.Blocks.kamibot_dir_backward, 'backward'],\r\n                    ],\r\n                    value: 'forward',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: [30],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: [5],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_move_unit',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_DIR:0,\r\n                SPEED:1,\r\n                VALUE: 2,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                let moveDir = script.getField('MOVE_DIR');\r\n                const value = parseInt( script.getValue('VALUE'));\r\n                const speed = parseInt( script.getValue('SPEED'));\r\n\r\n                let type = COMMAND_TYPE.MOVE_UNIT;\r\n\r\n                if(moveDir == 'backward') {\r\n                    moveDir = 0x04;    // 뒤로\r\n                } else {\r\n                    moveDir = 0x01;    // 앞으로\r\n                }\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:moveDir,\r\n                            param2:value,\r\n                            param3:speed,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_spin_unit: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_left, 'left'],\r\n                        [Lang.Blocks.kamibot_dir_right, 'right'],\r\n                    ],\r\n                    value: 'left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [90],\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_spin_unit',\r\n            },\r\n            paramsKeyMap: {\r\n                DEGREE:0,\r\n                SPIN_DIR:1,\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                let spinDir = script.getField('SPIN_DIR');\r\n                const degree = parseInt( script.getValue('DEGREE'));\r\n\r\n                let type = COMMAND_TYPE.SPIN_DEGREE;\r\n\r\n                let ldir=0x01;\r\n                let rdir=0x01;\r\n                if(spinDir == 'left') {\r\n                    ldir=0x02;\r\n                    rdir=0x01;\r\n                } else {\r\n                    ldir=0x01;\r\n                    rdir=0x02;\r\n                }\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:ldir,\r\n                            param2:rdir,\r\n                            param3:degree,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_stop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_stop',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kamibot_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.STOP_KAMIBOT,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        // '-------------------------------------------------------------------------------------'\r\n        kamibot_topmotor_turn: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_left, 'left'],\r\n                        [Lang.Blocks.kamibot_dir_right, 'right'],\r\n                    ],\r\n                    value: 'left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_topmotor_turn',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_DIR:0,\r\n            },\r\n            class: 'kamibot_topmotor_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                let moveDir = script.getField('MOVE_DIR');\r\n                let type = COMMAND_TYPE.TOPMOTOR_TURN;\r\n\r\n                if(moveDir == 'left') {\r\n                    moveDir = 0x02;    // 왼쪽\r\n                } else {\r\n                    moveDir = 0x01;    // 오른쪽\r\n                }\r\n                const speed = 9;   // 1 ~ 10\r\n                const torque = 3;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:moveDir,\r\n                            param2:speed,\r\n                            param3:torque,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_topmotor_move_abs: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [90],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_topmotor_move_abs',\r\n            },\r\n            paramsKeyMap: {\r\n                DEGREE:0,\r\n            },\r\n            class: 'kamibot_topmotor_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const degree = script.getValue('DEGREE');\r\n                let type = COMMAND_TYPE.TOPMOTOR_MOVE_ABSOLUTE;\r\n\r\n                const speed = 9;   // 1 ~ 10\r\n                \r\n                const torque = 3;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:speed,\r\n                            param2:degree,\r\n                            param3:torque,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_topmotor_move_relative: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [90],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_topmotor_move_relative',\r\n            },\r\n            paramsKeyMap: {\r\n                DEGREE:0,\r\n            },\r\n            class: 'kamibot_topmotor_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const degree = script.getValue('DEGREE');\r\n                let type = COMMAND_TYPE.TOPMOTOR_MOVE_RELATIVE;\r\n\r\n                const speed = 9;   // 1 ~ 10\r\n                const torque = 3;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                            param1:speed,\r\n                            param2:degree,\r\n                            param3:torque,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_topmotor_stop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_topmotor_stop',\r\n            },\r\n            paramsKeyMap: {\r\n                MOVE_DIR:0,\r\n            },\r\n            class: 'kamibot_topmotor_control',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                let type = COMMAND_TYPE.TOPMOTOR_STOP;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: type,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        // '-------------------------------------------------------------------------------------'\r\n        kamibot_color: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_color_red, 'red'],\r\n                        [Lang.Blocks.kamibot_color_pink, 'pink'],\r\n                        [Lang.Blocks.kamibot_color_blue, 'blue'],\r\n                        [Lang.Blocks.kamibot_color_sky, 'sky'],\r\n                        [Lang.Blocks.kamibot_color_green, 'green'],\r\n                        [Lang.Blocks.kamibot_color_yellow, 'yellow'],\r\n                        [Lang.Blocks.kamibot_color_white, 'white'],\r\n                    ],\r\n                    value: 'green',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_color',\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                const color = script.getField('COLOR');\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.SET_LED_COLOR,\r\n                        data: {\r\n                            param1:color,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n            syntax: undefined,\r\n        },\r\n        kamibot_color_rgb: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [0],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: [250],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: [0],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_color_rgb',\r\n            },\r\n            paramsKeyMap: {\r\n                R_VALUE: 0,\r\n                G_VALUE: 1,\r\n                B_VALUE: 2,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                let rvalue = parseInt(script.getValue('R_VALUE'));\r\n                let gvalue = parseInt(script.getValue('G_VALUE'));\r\n                let bvalue = parseInt(script.getValue('B_VALUE'));\r\n                \r\n                rvalue = Entry.KamibotPi.clamp(rvalue, 0, 255)\r\n                gvalue = Entry.KamibotPi.clamp(gvalue, 0, 255)\r\n                bvalue = Entry.KamibotPi.clamp(bvalue, 0, 255)\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.LED_TURN,\r\n                        data: {\r\n                            param1:rvalue,\r\n                            param2:gvalue,\r\n                            param3:bvalue,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n            syntax: undefined,\r\n        },\r\n        kamibot_draw_shape: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_color_tri, 'tri'],\r\n                        [Lang.Blocks.kamibot_color_rec, 'rect'],\r\n                        [Lang.Blocks.kamibot_color_penta, 'penta'],\r\n                        [Lang.Blocks.kamibot_color_hexa, 'hexa'],\r\n                        [Lang.Blocks.kamibot_color_star, 'star'],\r\n                        [Lang.Blocks.kamibot_color_circle, 'circle'],\r\n                    ],\r\n                    value: 'tri',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [5],\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_draw_shape',\r\n            },\r\n            paramsKeyMap: {\r\n                LENGTH: 0,\r\n                SHAPE: 1,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                let value = parseInt(script.getValue('LENGTH'));\r\n                let shape = script.getField('SHAPE');\r\n\r\n                console.log(shape);\r\n\r\n                if (shape === 'tri') {\r\n                    shape = 0x01;\r\n                } else if (shape === 'rect') {\r\n                    shape = 0x02;\r\n                } else if (shape === 'penta') {\r\n                    shape = 0x03;\r\n                } else if (shape === 'hexa') {\r\n                    shape = 0x04;\r\n                } else if (shape === 'star') {\r\n                    shape = 0x06;\r\n                } else if (shape == 'circle') {\r\n                    shape = 0x07;\r\n                }\r\n                value = Entry.KamibotPi.clamp(value, 0, 100)\r\n                console.log(value);\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.DRAW_SHAPE,\r\n                        data: {\r\n                            param1:shape,\r\n                            param2:value,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n            syntax: undefined,\r\n        },\r\n        kamibot_melody_beep: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: [45],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: [1],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'kamibot_melody_beep',\r\n            },\r\n            paramsKeyMap: {\r\n                FREQUENCY:0,\r\n                DURATION:1,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                let frequency = parseInt(script.getValue('FREQUENCY'));\r\n                let duration = parseInt(script.getValue('DURATION'));\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.MELODY_BEEP,\r\n                        data: {\r\n                            param1:frequency,\r\n                            param2:duration,\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n            syntax: undefined,\r\n        },\r\n        // '-------------------------------------------------------------------------------------'\r\n        kamibot_distance_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_left, 'left'],\r\n                        [Lang.Blocks.kamibot_dir_right, 'right'],\r\n                    ],\r\n                    value: 'left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_distance_sensor',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION:0,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = 0;\r\n\r\n                const dir = script.getField('DIRECTION');\r\n                if (pd.sensorData) {\r\n                    if (dir == 'left') {\r\n                        retVal = pd.sensorData.leftObject;\r\n                        console.log('left>>>', retVal)\r\n                    } else {\r\n                        retVal = pd.sensorData.rigthObject;\r\n                        console.log('right>>>', retVal)\r\n                    }\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n        kamibot_line_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_dir_left, 'left'],\r\n                        [Lang.Blocks.kamibot_dir_center, 'center'],\r\n                        [Lang.Blocks.kamibot_dir_right, 'right'],\r\n                    ],\r\n                    value: 'left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_line_sensor',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION:0,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = 0;\r\n\r\n                const dir = script.getField('DIRECTION');\r\n                if (pd.sensorData) {\r\n                    if (dir == 'left') {\r\n                        retVal = pd.sensorData.leftLine;\r\n                    } else if (dir == 'center'){\r\n                        retVal = pd.sensorData.centerLine;\r\n                    } else {\r\n                        retVal = pd.sensorData.rightLine;\r\n                    }\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n        kamibot_color_sensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.kamibot_color_r, 'color_r'],\r\n                        [Lang.Blocks.kamibot_color_g, 'color_g'],\r\n                        [Lang.Blocks.kamibot_color_b, 'color_b'],\r\n                    ],\r\n                    value: 'color_r',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'kamibot_color_sensor',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION:0,\r\n            },\r\n            class: 'kamibot_sensor',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n                let retVal = 0;\r\n\r\n                const dir = script.getField('DIRECTION');\r\n                if (pd.sensorData) {\r\n                    if (dir == 'color_r') {\r\n                        retVal = pd.sensorData.r;\r\n                    } else if (dir == 'color_g'){\r\n                        retVal = pd.sensorData.g;\r\n                    } else {\r\n                        retVal = pd.sensorData.b;\r\n                    }\r\n                }\r\n                return retVal;\r\n            },\r\n        },\r\n        // '--------------------------------------------------------------------------------------'\r\n        kamibot_all_stop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_all_stop',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kamibot_control_stop',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.EMERGENCY_STOP,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n        kamibot_initialize: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'kamibot_initialize',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'kamibot_control_stop',\r\n            isNotFor: ['kamibotPi'],\r\n            func: function (sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const pd = Entry.hw.portData;\r\n\r\n                if (!script.is_started) {\r\n                    script.is_started = true;\r\n                    const msgId = Entry.KamibotPi.getHashKey();\r\n                    script.msg_id = msgId;\r\n                    sq.msg_id = script.msg_id;\r\n                    const msg = {\r\n                        id: msgId,\r\n                        type: COMMAND_TYPE.RESET_INITIALIZE,\r\n                        data: {\r\n                        },\r\n                        time: Date.now()\r\n                    };\r\n                    sq.msg = msg;\r\n                    return script;\r\n                } \r\n                \r\n                if ((pd.msg_id) && (pd.msg_id.indexOf(script.msg_id) >= 0)) {\r\n                    delete script.is_started;\r\n                    delete script.msg_id;\r\n                    delete pd.msgId;\r\n                    return script.callReturn();\r\n                }\r\n                return script;\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.KamibotPi;\r\n\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_kingcoding.js",
    "content": "'use strict';\n\nEntry.Kingcoding = {\n    id: '34.1',\n    name: 'Kingcoding',\n    url: 'http://www.kingkongedu.co.kr/',\n    imageName: 'kingcoderLine.png',\n    title: {\n        ko: '킹코딩',\n        en: 'Kingcoding',\n    },\n    setZero() {\n        //정지시 초기화 부분\n\n        //200210 setDigitalPortValue 추후 지원 않을 예정임으로 변경\n        Entry.hw.sendQueue.MOTOR1 = 0;\n        Entry.hw.sendQueue.MOTOR2 = 0;\n        Entry.hw.sendQueue.LED = 0;\n        Entry.hw.sendQueue.BUZZER = 0;\n\n        Entry.hw.sendQueue.ANAL1 = 0; //a1값 요청 명령 변수\n        Entry.hw.sendQueue.ANAL2 = 0;\n        Entry.hw.sendQueue.DIGI1 = 0; //d1값 요청 명령 변수\n        Entry.hw.sendQueue.DIGI2 = 0;\n\n        Entry.hw.sendQueue.SET_DIGI1 = 0; //d1 출력 명령\n        Entry.hw.sendQueue.SET_DIGI2 = 0;\n        Entry.hw.sendQueue.USE_SET_DIGITAL = 0; //digital 입력을 받을 것인지 출력을 줄것인지 결정하는 flag\n\n        Entry.hw.update();\n    },\n};\n\nEntry.Kingcoding.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                kingcoding_set_motor: '킹코딩 모터 제어 %1 %2',\n                kingcoding_set_led: '킹코딩 LED 제어 %1 %2',\n                kingcoding_set_buzzer: '킹코딩 버저 제어 %1 %2',\n                kingcoding_set_digital1: '디지털 1번 제어  %1 %2',\n                kingcoding_set_digital2: '디지털 2번 제어  %1 %2',\n                kingcoding_get_number_sensor_1_value: '아날로그 1번 센서값(0~100)',\n                kingcoding_get_number_sensor_2_value: '아날로그 2번 센서값(0~100)',\n                kingcoding_get_digital_1_value: '디지털 1번 센서 참 ',\n                kingcoding_get_digital_2_value: '디지털 2번 센서 참',\n            },\n        },\n        en: {\n            template: {\n                kingcoding_set_motor: 'Motor Control',\n                kingcoding_set_led: 'LED Control',\n                kingcoding_set_buzzer: 'Buzzer Control',\n                kingcoding_set_digital1: 'Digital no.1 Control %1 %2',\n                kingcoding_set_digital2: 'Digital no.2 Control  %1 %2',\n                kingcoding_get_number_sensor_1_value: 'Analog Port 1 Value',\n                kingcoding_get_number_sensor_2_value: 'Analog Port 2 Value',\n                kingcoding_get_digital_1_value: 'Digital Port 1 Value',\n                kingcoding_get_digital_2_value: 'Digital Port 2 Value',\n            },\n        },\n    };\n};\n\nEntry.Kingcoding.blockMenuBlocks = [\n    'kingcoding_set_motor',\n    'kingcoding_set_led',\n    'kingcoding_set_buzzer',\n    'kingcoding_set_digital1',\n    'kingcoding_set_digital2',\n    'kingcoding_get_number_sensor_1_value',\n    'kingcoding_get_number_sensor_2_value',\n    'kingcoding_get_digital_1_value',\n    'kingcoding_get_digital_2_value',\n];\n\nEntry.Kingcoding.getBlocks = function() {\n    return {\n        kingcoding_set_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1번 정회전', '1'],\n                        ['1번 역회전', '2'],\n                        ['1번 정지', '3'],\n                        ['2번 정회전', '4'],\n                        ['2번 역회전', '5'],\n                        ['2번 정지', '6'],\n                        ['1,2번 정회전', '7'],\n                        ['1,2번 역회전', '8'],\n                        ['1번 정회전, 2번 역회전', '9'],\n                        ['1번 역회전, 2번 정회전', '10'],\n                        ['모든 모터 정지', '11'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'kingcoding_set_motor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Kingcoding',\n            isNotFor: ['Kingcoding'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const timeValue = 50; //지연 시간 ms\n                    const blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        () => {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    const value = script.getNumberField('PORT', script);\n                    console.log(`motor :${value}`);\n                    switch (value) {\n                        case 1:\n                            Entry.hw.sendQueue.MOTOR1 = 1; //정\n                            break;\n                        case 2:\n                            Entry.hw.sendQueue.MOTOR1 = 2; //역\n                            break;\n                        case 3:\n                            Entry.hw.sendQueue.MOTOR1 = 0; //STOP\n                            break;\n                        case 4:\n                            Entry.hw.sendQueue.MOTOR2 = 1; //정\n                            break;\n                        case 5:\n                            Entry.hw.sendQueue.MOTOR2 = 2; //역\n                            break;\n                        case 6:\n                            Entry.hw.sendQueue.MOTOR2 = 0; //STOP\n                            break;\n                        case 7:\n                            Entry.hw.sendQueue.MOTOR1 = 1; //정\n                            Entry.hw.sendQueue.MOTOR2 = 1; //정\n                            break;\n                        case 8:\n                            Entry.hw.sendQueue.MOTOR1 = 2; //역\n                            Entry.hw.sendQueue.MOTOR2 = 2; //역\n                            break;\n                        case 9:\n                            Entry.hw.sendQueue.MOTOR1 = 1; //정\n                            Entry.hw.sendQueue.MOTOR2 = 2; //역\n                            break;\n                        case 10:\n                            Entry.hw.sendQueue.MOTOR1 = 2; //역\n                            Entry.hw.sendQueue.MOTOR2 = 1; //정\n                            break;\n                        case 11:\n                            Entry.hw.sendQueue.MOTOR1 = 0; //STOP\n                            Entry.hw.sendQueue.MOTOR2 = 0; //STOP\n                            break;\n                    }\n\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Kingcoding.set_motor(%1)'] },\n        },\n\n        kingcoding_set_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['적색 LED 켜기', '1'],\n                        ['청색 LED 켜기', '2'],\n                        ['녹색 LED 켜기', '3'],\n                        ['주황색 LED 켜기', '4'],\n                        ['보라색 LED 켜기', '5'],\n                        ['하늘색 LED 켜기', '6'],\n                        ['백색 LED 켜기', '7'],\n                        ['LED 끄기', '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator', \n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'kingcoding_set_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Kingcoding',\n            isNotFor: ['Kingcoding'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const timeValue = 25; //시간지연\n                    const blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        () => {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    Entry.hw.sendQueue.LED = script.getNumberField('PORT', script);\n                    console.log(`led :${Entry.hw.sendQueue.LED}`);\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Kingcoding.set_led(%1)'] },\n        },\n        kingcoding_set_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['낮은음', '1'],\n                        ['중간음', '2'],\n                        ['높은음', '3'],\n                        ['버저 끄기', '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator', \n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'kingcoding_set_buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Kingcoding',\n            isNotFor: ['Kingcoding'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    const timeValue = 25; //시간지연\n                    const blockId = script.block.id;\n                    Entry.TimeWaitManager.add(\n                        blockId,\n                        () => {\n                            script.timeFlag = 0;\n                        },\n                        timeValue\n                    );\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    Entry.hw.sendQueue.BUZZER = script.getNumberField('PORT', script);\n                    console.log(`buzzer :${Entry.hw.sendQueue.BUZZER}`);\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Kingcoding.set_buzzer(%1)'] },\n        },\n        // kingcoding_set_digital1: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['켜기', '1'], ['끄기', '0']],\n        //             value: '1',\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Indicator',\n        //             img: 'block_icon/hardware_icon.svg',\n        //             size: 12,\n        //         },\n        //     ],\n        //     events: {},\n        //     def: {\n        //         params: [null, null],\n        //         type: 'kingcoding_set_digital1',\n        //     },\n        //     paramsKeyMap: {\n        //         PORT: 0,\n        //     },\n        //     class: 'Kingcoding2',\n        //     isNotFor: ['Kingcoding'],\n        //     func: function(sprite, script) {\n        //         if (!script.isStart) {\n        //             script.isStart = true;\n        //             script.timeFlag = 1;\n        //             var timeValue = 25;//시간지연\n        //             const blockId = script.block.id;\n        //             Entry.TimeWaitManager.add(\n        //                 blockId,\n        //                 function() {\n        //                     script.timeFlag = 0;\n        //                 },\n        //                 timeValue\n        //             );\n        //             return script;\n        //         } else if (script.timeFlag == 1) {\n        //             return script;\n        //         } else {\n        //             delete script.timeFlag;\n        //             delete script.isStart;\n        //             Entry.engine.isContinue = false;\n        //             var value = script.getNumberField('PORT', script);\n        //             console.log(\"digital1 :\"+value);\n        //             Entry.hw.setDigitalPortValue(`11`, value); \n        //             Entry.hw.setDigitalPortValue(`13`, 1); //출력을 사용한다는 플래그 세움\n        //             return script.callReturn();\n        //         }\n        //       },\n        //     syntax: { js: [], py: ['Kingcoding.set_digital1(%1)'] },\n        // },\n\n        // kingcoding_set_digital2: {\n        //     color: EntryStatic.colorSet.block.default.HARDWARE,\n        //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n        //     skeleton: 'basic',\n        //     statements: [],\n        //     params: [\n        //         {\n        //             type: 'Dropdown',\n        //             options: [['켜기', '1'], ['끄기', '0']],\n        //             value: '1',\n        //             fontSize: 11,\n        //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n        //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n        //         },\n        //         {\n        //             type: 'Indicator',\n        //             img: 'block_icon/hardware_icon.svg',\n        //             size: 12,\n        //         },\n        //     ],\n        //     events: {},\n        //     def: {\n        //         params: [null, null],\n        //         type: 'kingcoding_set_digital2',\n        //     },\n        //     paramsKeyMap: {\n        //         PORT: 0,\n        //     },\n        //     class: 'Kingcoding2',\n        //     isNotFor: ['Kingcoding'],\n        //     func: function(sprite, script) {\n        //         if (!script.isStart) {\n        //             script.isStart = true;\n        //             script.timeFlag = 1;\n        //             var timeValue = 25;//시간지연\n        //             const blockId = script.block.id;\n        //             Entry.TimeWaitManager.add(\n        //                 blockId,\n        //                 function() {\n        //                     script.timeFlag = 0;\n        //                 },\n        //                 timeValue\n        //             );\n        //             return script;\n        //         } else if (script.timeFlag == 1) {\n        //             return script;\n        //         } else {\n        //             delete script.timeFlag;\n        //             delete script.isStart;\n        //             Entry.engine.isContinue = false;\n        //             var value = script.getNumberField('PORT', script);\n        //             console.log(\"digital1 :\"+value);\n        //             Entry.hw.setDigitalPortValue(`12`, value); \n        //             Entry.hw.setDigitalPortValue(`13`, 1); //출력을 사용한다는 플래그 세움\n        //             return script.callReturn();\n        //         }\n        //       },\n        //     syntax: { js: [], py: ['Kingcoding.set_digital2(%1)'] },\n        // },\n\n        kingcoding_get_number_sensor_1_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'kingcoding_get_number_sensor_1_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Kingcoding3',\n            isNotFor: ['Kingcoding'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.ANAL1 = 1;\n                let ret = Entry.hw.portData.ANAL1; //값을 받기\n                ret = ret & 63; // mask: 00111111\n                ret = (ret * 100) / 63; //(0~100 으로 변환)\n                console.log(`anal 1 :${ret}`);\n                return ret;\n            },\n            syntax: { js: [], py: ['Kingcoding.sensor_1_value()'] },\n        },\n        kingcoding_get_number_sensor_2_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'kingcoding_get_number_sensor_2_value',\n            },\n\n            class: 'Kingcoding3',\n            isNotFor: ['Kingcoding'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.ANAL2 = 1;\n                let ret = Entry.hw.portData.ANAL2; //값을 받기\n                ret = ret & 63; // mask: 00111111\n                ret = (ret * 100) / 63; //(0~100 으로 변환)\n                console.log(`anal 2 :${ret}`);\n                return ret;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Kingcoding.sensor_2_value()',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        kingcoding_get_digital_1_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'kingcoding_get_digital_1_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Kingcoding3',\n            isNotFor: ['Kingcoding'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.DIGI1 = 1;\n                let ret = Entry.hw.portData.DIGI_1_2; //값을 받기\n                ret = ret & 1; // mask: 0000 0001\n                console.log(`digi 1 :${ret}`);\n                return ret;\n            },\n            syntax: { js: [], py: ['Kingcoding.is_button_1_pressed()'] },\n        },\n        kingcoding_get_digital_2_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Text',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'kingcoding_get_digital_2_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Kingcoding3',\n            isNotFor: ['Kingcoding'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.DIGI2 = 1;\n                let ret = Entry.hw.portData.DIGI_1_2; //값을 받기\n                ret = ret & 2; // mask: 0000 0010\n                console.log(`digi 2 :${ret}`);\n                return ret;\n            },\n            syntax: { js: [], py: ['Kingcoding.is_button_2_pressed()'] },\n        },\n    };\n};\n\nmodule.exports = Entry.Kingcoding;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_lecoboard.js",
    "content": "'use strict';\n\nEntry.lecoboard = {\n    id: '3C.1',\n    name: 'lecoboard',\n    url: 'http://www.fnj.or.kr/',\n    imageName: 'lecoboard.png',\n    title: {\n        ko: '레코보드',\n        en: 'LECOBOARD',\n    },\n    setZero() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 34; port++) {\n            if (port == 13 || port == 14 || port == 15 || port == 16 || port == 33) {\n                Entry.hw.sendQueue[port] = 1;\n            } else if (port == 17) {\n                Entry.hw.sendQueue[port] = 0;\n            } else {\n                Entry.hw.sendQueue[port] = 0;\n                Entry.hw.sendQueue.readablePorts.push(port);\n            }\n        }\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        LCD: 9,\n        LCD_COMMAND: 10,\n        BLE_WRITE: 11,\n        BLE_READ: 12,        \n        ARM_XYZ: 13,\n        ARM_WG: 14,\n    },\n    toneTable: {\n        0: 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n        C2: 13,\n    },\n    toneMap: {\n        1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        4: [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        5: [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        6: [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n        13: [65, 131, 262, 523, 1046, 2093, 4186, 8372],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n    monitorTemplate: {\n        //imgPath: 'hw/lecoboard.png',\n        //keys: ['value'],\n        width: 800,\n        height: 600,\n        listPorts: {\n            BLE_READ: {\n                name: '블루투스',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            ULTRASONIC: {\n                name: '초음파센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            4: {\n                name: '버튼입력',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: '조도센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: '가변저항',\n                type: 'input',\n                pos: { x: 200, y: 0 },\n            },\n            a2: {\n                name: '습도센서',\n                type: 'input',\n                pos: { x: 400, y: 0 },\n            },\n            a7: {\n                name: '온도센서',\n                type: 'input',\n                pos: { x: 600, y: 0 },\n            },\n            a3: {\n                name: '아날로그1',\n                type: 'input',\n                pos: { x: 0, y: 500 },\n            },\n            a4: {\n                name: '아날로그2',\n                type: 'input',\n                pos: { x: 200, y: 500 },\n            },\n            a5: {\n                name: '아날로그3',\n                type: 'input',\n                pos: { x: 400, y: 500 },\n            },\n            a6: {\n                name: '아날로그4',\n                type: 'input',\n                pos: { x: 600, y: 500 },\n            },\n            28: {\n                name: '입력1',\n                type: 'input',\n                pos: { x: 0, y: 400 },\n            },\n            29: {\n                name: '입력2',\n                type: 'input',\n                pos: { x: 200, y: 400 },\n            },\n            1: {\n                name: '입력3',\n                type: 'input',\n                pos: { x: 400, y: 400 },\n            },\n            0: {\n                name: '입력4',\n                type: 'input',\n                pos: { x: 600, y: 400 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.lecoboard.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                lecoboard_button_read: '버튼 읽어오기',\n                lecoboard_button_read_bool: '버튼 읽어오기',\n                lecoboard_ultrasonic_read: '초음파센서 읽어오기',\n                lecoboard_cds_read: '조도센서 읽어오기',\n                lecoboard_var_read: '가변저항 읽어오기',\n                lecoboard_ir_read: '습도센서 읽어오기',\n                lecoboard_temp_read: '온도센서 읽어오기',\n                lecoboard_analog_read: '아날로그입력 %1 읽어오기',\n                lecoboard_digital_read: '디지털 %1 읽어오기',\n                lecoboard_dual_led_color_toggle: 'LED %1 색으로 정하기 %2',\n                lecoboard_dual_led_toggle: 'LED 녹색 %1 빨강 %2 으로 정하기 %3',\n                lecoboard_led_rgb_toggle: 'RGB LED R%1 G%2 B%3 %4',\n                //lecoboard_led_strip_toggle: 'LED 스트립 빨강%1 녹색%2 파랑%3 노랑%4 %5',\n                lecoboard_set_tone: '부저를 %1 음으로 %2 박자로 연주하기 %3',\n                lecoboard_set_tone_long: '부저를 %1 음으로 연주하기 %2',\n                lecoboard_set_freq_tone: '신호음 %1번핀에서 %2 주파수로 %3 동안 연주하기 %4',\n                lecoboard_set_tone_off: '부저 끄기 %1',\n                lecobaord_set_servo: '%1번 서보모터 %2°로 정하기 %3',\n                lecoboard_dc_motor: '%1번 DC모터 %2방향으로 속력%3 으로 정하기 %4',\n                lecoboard_dc_motor_stop: 'DC 모터 정지하기',\n                lecoboard_digital_write: '디지털 %1번핀에 %2 보내기 %3',\n                lecoboard_digital_pwm: 'PWM %1 번핀에 %2 보내기 %3',\n                lecoboard_convert_value: '%1의 값을 %2부터 %3까지의 값으로 변환하기 %4',\n                lecoboard_lcd_command: 'LCD 설정 %1 %2',\n                lecoboard_set_lcd: 'LCD %1번째줄 %2번째칸에 %3을 출력하기 %4',\n                lecoboard_send_ble: '블루투스로 %1을 보내기 %2',\n                lecoboard_get_bluetooth: '블루투스에서 읽어오기',     \n                /*\n                lecoboard_dc_motor_for_sec: '%1번 DC모터 %2방향으로 속력%3 으로 %4초 동안 동작하기 %5',*/\n            },\n        },\n        en: {\n            template: {\n                lecoboard_button_read: 'Button value',\n                lecoboard_button_read_bool: 'Button value',\n                lecoboard_ultrasonic_read: 'Read ultrasonic sensor',\n                lecoboard_cds_read: 'Read cds sensor',\n                lecoboard_var_read: 'Read var sensor',\n                lecoboard_ir_read: 'Read  Humidity sensor',\n                lecoboard_temp_read: 'Read temperature sensor',\n                lecoboard_analog_read: 'Read Analog Input %1',\n                lecoboard_digital_read: 'Read Digital %1 Pin',\n                lecoboard_dual_led_color_toggle: 'LED %1 color %2',\n                lecoboard_dual_led_toggle: 'LED green %1 red %2 value %3',\n                lecoboard_set_tone: 'buzzer %1 tone %2 sec play %3',\n                lecoboard_led_rgb_toggle: 'RGB LED R%1 G%2 B%3 %4',\n                //lecoboard_led_strip_toggle: 'LED strip red%1 green%2 blue%3 yellow%4 %5',\n                lecoboard_set_tone_long: 'buzzer %1 tone play %2',\n                lecoboard_set_freq_tone: 'buzzer %1 pin %2 Hz %3 ms %4',\n                lecoboard_set_tone_off: 'buzzer off',\n                lecobaord_set_servo: '%1 Sevomotor angle as %2 %3',\n                lecoboard_dc_motor: '%1 DC motor direction %2 speed %3 %4',\n                /*\n                lecoboard_dc_motor_for_sec: '%1 DC motor direction %2 speed %3 sec %4 %5', */\n                lecoboard_dc_motor_stop: 'DC motor stop',\n                lecoboard_digital_write: 'Digital %1 port as %2 %3',\n                lecoboard_digital_pwm: 'PWM %1 pin %2 out %3',\n                lecoboard_convert_value: 'Convert value %1 from %2 to %3 %4',\n                lecoboard_lcd_command: 'Set LCD cmd %1 %2',\n                lecoboard_set_lcd: 'Set LCD data %1 %2 %3 %4',\n                lecoboard_send_ble: 'BLE print %1 %2',\n                lecoboard_get_bluetooth: 'Read from BLE',\n            },\n        },\n    };\n};\n\nEntry.lecoboard.blockMenuBlocks = [\n    'lecoboard_led_rgb_toggle',\n    'lecoboard_dual_led_color_toggle',\n    'lecoboard_dual_led_toggle',\n    //'lecoboard_led_strip_toggle',\n    'lecoboard_button_read_bool',\n    'lecoboard_button_read',\n    'lecoboard_ultrasonic_read',\n    'lecoboard_cds_read',\n    'lecoboard_var_read',\n    'lecoboard_ir_read',\n    'lecoboard_temp_read',\n    'lecoboard_analog_read',\n    'lecoboard_digital_read',\n    'lecoboard_convert_value',\n    'lecoboard_set_tone',\n    'lecoboard_set_tone_long',\n    'lecoboard_set_freq_tone',\n    'lecoboard_set_tone_off',\n    'lecobaord_set_servo',\n    'lecoboard_dc_motor',\n    //'lecoboard_dc_motor_for_sec',\n    'lecoboard_dc_motor_stop',\n    'lecoboard_digital_write',\n    'lecoboard_digital_pwm',\n    'lecoboard_lcd_command',\n    'lecoboard_set_lcd',\n    'lecoboard_send_ble',\n    'lecoboard_get_bluetooth',    \n];\n\nEntry.lecoboard.getBlocks = function() {\n    return {\n        lecoboard_arm_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [0],\n                    },\n                    {\n                        type: 'number',\n                        params: [98],\n                    },\n                    {\n                        type: 'number',\n                        params: [160],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_arm_control',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'lecoboardRobotArm',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {                \n                let value_x = script.getNumberValue('VALUE1',script);\n                let value_y = script.getNumberValue('VALUE2',script);\n                let value_z = script.getNumberValue('VALUE3',script);\n                let port = 0;\n\n                value_x = value_x*10;\n                value_y = value_y*10;\n                value_z = value_z*10;\n\n                port=31;\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.lecoboard.sensorTypes.ARM_XYZ,\n                    data: {\n                        value_x,\n                        value_y,\n                        value_z,\n                    },\n                    time: new Date().getTime(),\n                };  \n                return script.callReturn();\n            },\n        },\n        lecoboard_arm_gripper_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [0],\n                    },\n                    {\n                        type: 'number',\n                        params: [45],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_arm_gripper_control',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardRobotArm',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {                \n                let value_w = script.getNumberValue('VALUE1',script);\n                let value_g = script.getNumberValue('VALUE2',script);\n                let port = 0;\n\n                value_w = value_w*10;\n                value_g = value_g*10;\n                \n\n                port=32;\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.lecoboard.sensorTypes.ARM_WG,\n                    data: {\n                        value_w,\n                        value_g,\n                    },\n                    time: new Date().getTime(),\n                };    \n                return script.callReturn();\n            },\n        },\n        lecoboard_port_highlow_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORTVALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORTVALUE');\n            },\n        },\n        lecoboard_digital_write: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    //accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_digital_write',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboardTest',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                let port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n\n                /*\n                if (value == 1) value = 255;\n                else value = 0;\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                */\n\n                if (typeof value === 'string') value = value.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value) > -1) value = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value) > -1) value = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n             \n        },\n        lecoboard_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    //accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboardTest',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                let port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n\n                value = 255 * (value / 100);\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        lecoboard_analog_input_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '3'],\n                        ['2', '4'],\n                        ['3', '5'],\n                        ['4', '6'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [3],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecoboard_button_read_bool: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4'],\n                type: 'lecoboard_button_read_bool',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const port = 4;\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboard.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n            },\n        },\n        lecoboard_button_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4'],\n                type: 'lecoboard_button_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const port = 4;\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboard.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n                //return DIGITAL ? DIGITAL[port] || 0 : 1;\n            },\n        },\n        lecoboard_ultrasonic_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['5'],\n                    },\n                ],\n                type: 'lecoboard_ultrasonic_read',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.ArduinoExt.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n        lecoboard_analog_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_analog_input_list',\n                        params: ['3'],\n                    },\n                ],\n                type: 'lecoboard_analog_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboard_cds_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboard_cds_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                let port = 0;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboard_var_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboard_var_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                let port = 1;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboard_ir_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboard_ir_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[7] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: 1,\n                    time: new Date().getTime(),\n                };\n\n                let port = 2;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboard_temp_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboard_temp_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                let port = 7;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboard_digital_port_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '28'],\n                        ['2', '29'],\n                        ['3', '1'],\n                        ['4', '0'],\n                    ],\n                    value: '28',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecoboard_digital_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_digital_port_list',\n                        params: [28],\n                    },\n                ],\n                type: 'lecoboard_digital_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n\n                const port = script.getNumberValue('PORT', script);\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboard.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n            },\n        },\n        lecoboard_convert_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['180'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_convert_value',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboard'],\n            func: function(sprite, script) {\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                var stringValue2 = script.getValue('VALUE2', script);\n                var stringValue3 = script.getValue('VALUE3', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue2) && stringValue2.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue3) && stringValue3.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                var result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                result = result * ((value3 - value2) / (1023 - 0));\n                result += value2;\n                result = Math.min(value3, result);\n                result = Math.max(value2, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n        },\n        lecoboard_dual_color_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['녹색', '1'],\n                        ['빨강', '2'],\n                        ['오렌지', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            func(sprite, script) {\n                return script.getField('COLOR');\n            },\n        },\n\n        lecoboard_dual_led_color_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_dual_color_list',\n                        params: [1],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_dual_led_color_toggle',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: '0lecoboard_led',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const port1 = 17;\n                const port2 = 33;\n                let value1 = 0; //script.getValue('VALUE1');\n                let value2 = 0; //script.getValue('VALUE2');\n                let color = script.getValue('COLOR');\n\n                if (color == 1) {\n                    value1 = 255;\n                    value2 = 0;\n                } else if (color == 2) {\n                    value1 = 0;\n                    value2 = 255;\n                } else if (color == 3) {\n                    value1 = 255;\n                    value2 = 255;\n                }\n\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_dual_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_dual_led_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: '0lecoboard_led',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const port1 = 17;\n                const port2 = 33;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_led_rgb_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_led_rgb_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: '0lecoboard_led',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const port1 = 16;\n                const port2 = 15;\n                const port3 = 14;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n                let value3 = script.getValue('VALUE3');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                if (typeof value3 === 'string') value3 = value3.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value3) > -1) value3 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value3) > -1) value3 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_led_strip_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_led_strip_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n            },\n            class: '0lecoboard_led',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const port1 = 13;\n                const port2 = 14;\n                const port3 = 15;\n                const port4 = 16;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n                let value3 = script.getValue('VALUE3');\n                let value4 = script.getValue('VALUE4');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                if (typeof value3 === 'string') value3 = value3.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value3) > -1) value3 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value3) > -1) value3 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n                if (typeof value4 === 'string') value4 = value4.toLowerCase();\n                if (Entry.lecoboard.highList.indexOf(value4) > -1) value4 = 255;\n                else if (Entry.lecoboard.lowList.indexOf(value4) > -1) value4 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port4] = {\n                    type: Entry.lecoboard.sensorTypes.DIGITAL,\n                    data: value4,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                        [Lang.Blocks.do_name, 'C2'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        arduino_ext_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_tone_list',\n                    },\n                ],\n                type: 'arduino_ext_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n        },\n        arduino_ext_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        lecoboard_buzzer_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboard_buzzer_number',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n        },\n        lecoboard_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_tone_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_set_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                DURATION: 1,\n            },\n            class: 'lecoboard_buzzer',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                let note = script.getValue('NOTE', script);\n                if (!Entry.Utils.isNumber(note)) {\n                    note = Entry.lecoboard.toneTable[note];\n                }\n\n                if (note < 0) {\n                    note = 0;\n                } else if (note > 13) {\n                    note = 13;\n                }\n\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration < 0) {\n                    duration = 0;\n                }\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                if (duration === 0) {\n                    sq.SET[port] = {\n                        type: Entry.lecoboard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n                let octave = 4;\n                let value = 0;\n\n                if (note != 0) {\n                    value = Entry.lecoboard.toneMap[note][octave];\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboard.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_set_freq_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['12'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['HZ'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_set_freq_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                DURATION: 2,\n            },\n            class: 'lecoboard_buzzer',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                let freq = script.getNumberValue('NOTE', script);\n\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration < 0) {\n                    duration = 0;\n                }\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                if (duration === 0) {\n                    sq.SET[port] = {\n                        type: Entry.lecoboard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n                let value = freq;\n\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboard.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_set_tone_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_buzzer_number',\n                        params: [1],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_set_tone_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'lecoboard_buzzer',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = 0;\n                    let duration = 0;\n                    sq.SET[port] = {\n                        type: Entry.lecoboard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboard_set_tone_long: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_tone_list',\n                    },\n                ],\n                type: 'lecoboard_set_tone_long',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            class: 'lecoboard_buzzer',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                let note = script.getValue('NOTE', script);\n                if (!Entry.Utils.isNumber(note)) {\n                    note = Entry.lecoboard.toneTable[note];\n                }\n\n                if (note < 0) {\n                    note = 0;\n                } else if (note > 13) {\n                    note = 13;\n                }\n\n                let duration = 20;\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                let octave = 4;\n                let value = 0;\n\n                if (note != 0) {\n                    value = Entry.lecoboard.toneMap[note][octave];\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboard.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_set_tone_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'lecoboard_set_tone_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'lecoboard_buzzer',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = 0;\n                    let duration = 0;\n                    sq.SET[port] = {\n                        type: Entry.lecoboard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboard_servomotor_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecobaord_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                ],\n                type: 'lecobaord_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboard_servo',\n            isNotFor: ['lecoboard'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let port = script.getNumberValue('PORT', script);\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n                else script.callReturn();\n\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(1, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.lecoboard.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_dc_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '1'],\n                        ['오른쪽', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', '0'],\n                        ['반시계방향', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_dc_motor',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIR: 1,\n                SPEED: 2,\n            },\n            class: 'lecoboard_motor',\n            isNotFor: ['lecoboard'],\n            func: function(sprite, script) {\n                var idx = script.getField('INDEX');\n                var dir = script.getField('DIR');\n                var speed = script.getNumberValue('SPEED');\n                var value = 0;\n                var value1 = 0;\n                var value2 = 0;\n\n                var port1 = 0;\n                var port2 = 0;\n\n                if (idx == 1) {\n                    port1 = 28;\n                    port2 = 29;\n                } else if (idx == 2) {\n                    port1 = 1;\n                    port2 = 0;\n                }\n\n                var value = speed;\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n\n                value = value * (255 / 100);\n                value = Math.round(value);\n\n                if (dir == 0) {\n                    value1 = value;\n                    value2 = 0;\n                } else {\n                    value1 = 0;\n                    value2 = value;\n                }\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboard.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboard.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_dc_motor_for_sec: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', '0'],\n                        ['반시계방향', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_dc_motor_for_sec',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIR: 1,\n                SPEED: 2,\n                SEC: 3,\n            },\n            class: 'lecoboard_motor',\n            isNotFor: ['lecoboard'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var idx = script.getField('INDEX');\n                    var dir = script.getField('DIR');\n                    var speed = script.getNumberValue('SPEED');\n                    var sec = script.getNumberValue('SEC');\n                    var value = 0;\n                    var value1 = 0;\n                    var value2 = 0;\n\n                    var port1 = 0;\n                    var port2 = 0;\n\n                    if (idx == 1) {\n                        port1 = 28;\n                        port2 = 29;\n                    } else if (idx == 2) {\n                        port1 = 0;\n                        port2 = 1;\n                    }\n\n                    var value = speed;\n                    value = Math.round(value);\n                    value = Math.max(value, 0);\n                    value = Math.min(value, 100);\n\n                    value = value * (255 / 100);\n                    value = Math.round(value);\n\n                    if (dir == 0) {\n                        value1 = value;\n                        value2 = 0;\n                    } else {\n                        value1 = 0;\n                        value2 = value;\n                    }\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n                    Entry.hw.sendQueue.SET[port1] = {\n                        type: Entry.lecoboard.sensorTypes.PWM,\n                        data: value1,\n                        time: new Date().getTime(),\n                    };\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n                    Entry.hw.sendQueue.SET[port2] = {\n                        type: Entry.lecoboard.sensorTypes.PWM,\n                        data: value2,\n                        time: new Date().getTime(),\n                    };\n\n                    sec = sec * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, sec);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue.SET[port1] = {\n                        type: Entry.lecoboard.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.hw.sendQueue.SET[port2] = {\n                        type: Entry.lecoboard.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboard_dc_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'lecoboard_dc_motor_stop',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'lecoboard_motor',\n            isNotFor: ['lecoboard'],\n            func: function(sprite, script) {\n                var port1 = 28;\n                var port2 = 29;\n                var port3 = 1;\n                var port4 = 0;\n\n                var value = 0;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboard.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboard.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboard.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port4] = {\n                    type: Entry.lecoboard.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n\n        lecoboard_list_digital_lcd_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        lecoboard_list_digital_lcd_column: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                        ['9', '8'],\n                        ['10', '9'],\n                        ['11', '10'],\n                        ['12', '11'],\n                        ['13', '12'],\n                        ['14', '13'],\n                        ['15', '14'],\n                        ['16', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLUMN: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COLUMN');\n            },\n        },\n        lecoboard_set_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            //template: Lang.template.lecoboard_set_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_list_digital_lcd_line',\n                    },\n                    {\n                        type: 'lecoboard_list_digital_lcd_column',\n                    },\n                    {\n                        type: 'text',\n                        params: ['HELLO'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_set_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                COLUMN: 1,\n                STRING: 2,\n            },\n            class: 'lecoboardLcd',\n            isNotFor: ['lecoboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var line = script.getValue('LINE', script);\n                var column = script.getValue('COLUMN', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n                var str;\n                let temp = [];\n                //var string = script.getField('STRING');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                str = string;\n                if (!script.isStart) {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = string.charCodeAt(i);\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq.SET[1] = {\n                        type: Entry.lecoboard.sensorTypes.LCD,\n                        data: {\n                            line: line,\n                            column: column,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboard_list_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['지움', '2'],\n\n                        ['백라이트켜기', '3'],\n                        ['백라이트끄기', '4'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COMMAND');\n            },\n        },\n        lecoboard_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            //template: Lang.template.lecoboard_lcd_command,\n            //\"template\": \"%1 %2\",\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboard_list_lcd_command',\n                    },\n                    null,\n                ],\n                type: 'lecoboard_lcd_command',\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n            },\n            class: 'lecoboardLcd',\n            isNotFor: ['lecoboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var value = script.getNumberValue('COMMAND', script);\n                var command = script.getNumberValue('COMMAND', script);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n\n                sq.SET[0] = {\n                    type: Entry.lecoboard.sensorTypes.LCD_COMMAND,\n                    data: {\n                        value: value,\n                        command: command,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboard_send_ble: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            //template: Lang.template.lecoboard_set_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['HELLO'],\n                    },\n                    null,\n                ],\n                type: 'lecoboard_send_ble',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'lecoboardble',\n            isNotFor: ['lecoboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var string = script.getValue('STRING', script);\n                var text = [];\n                var str;\n                let temp = [];\n                //var string = script.getField('STRING');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                str = string;\n                if (!script.isStart) {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = string.charCodeAt(i);\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq.SET[1] = {\n                        type: Entry.lecoboard.sensorTypes.BLE_WRITE,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboard_get_bluetooth: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //template: Lang.template.lecoboard_get_digital_bluetooth,\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboard_get_bluetooth',\n            },\n            paramsKeyMap: {},\n            class: 'lecoboardble',\n            isNotFor: ['lecoboard'],\n            func: function(sprite, script) {\n                var port = 2;\n                var getString = Entry.hw.portData.BLE_READ;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboard.sensorTypes.BLE_READ] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n\n                return getString ? getString.slice(0, getString.length - 1) : ' ';\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.lecoboard;"
  },
  {
    "path": "src/playground/blocks/hardware/block_lecoboardAvr.js",
    "content": "'use strict';\n\nEntry.lecoboardAvr = {\n    id: '3C.3',\n    name: 'lecoboardAvr',\n    url: 'http://www.fnj.or.kr/',\n    imageName: 'lecoboardAvr.png',\n    title: {\n        ko: '레코보드2.0',\n        en: 'LECOBOARD2.0',\n    },\n    setZero() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 34; port++) {\n            if (port == 13 || port == 14 || port == 15 || port == 16 || port == 33) {\n                Entry.hw.sendQueue[port] = 1;\n            } else if (port == 17) {\n                Entry.hw.sendQueue[port] = 0;\n            } else {\n                Entry.hw.sendQueue[port] = 0;\n                Entry.hw.sendQueue.readablePorts.push(port);\n            }\n        }\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        LCD: 9,\n        LCD_COMMAND: 10,\n        BLE_WRITE: 11,\n        BLE_READ: 12,        \n        ARM_XYZ: 13,\n        ARM_WG: 14,\n        HUSKY: 15,\n        HUSKY_GET: 16,\n        HUSKY_GET_LEARNED_ID_CNT: 17,\n        HUSKY_GET_BLOCK_CNT: 18,\n        HUSKY_GET_ARROW_CNT: 19,\n        HUSKY_GET_ID: 20,\n        HUSKY_GET_XD: 21,\n        HUSKY_GET_YD: 22,\n        HUSKY_GET_WD: 23,\n        HUSKY_GET_HT: 24, \n        HUSKY_GET_ID_BL_EXIST: 25,\n        HUSKY_GET_ID_AR_EXIST: 26,\n        HUSKY_GET_BLOCK_INFO: 27,\n        HUSKY_GET_ARROW_INFO: 28, \n        HUSKY_GET_ID_LEARNED: 29,\n    },\n\n\n\n    toneTable: {\n        0: 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n        C2: 13,\n    },\n    toneMap: {\n        1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        4: [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        5: [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        6: [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n        13: [65, 131, 262, 523, 1046, 2093, 4186, 8372],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n    monitorTemplate: {\n        //imgPath: 'hw/lecoboard.png',\n        //keys: ['value'],\n        width: 800,\n        height: 600,\n        listPorts: {\n            BLE_READ: {\n                name: '블루투스',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            ULTRASONIC: {\n                name: '초음파센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            4: {\n                name: '버튼입력',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: '조도센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: '가변저항',\n                type: 'input',\n                pos: { x: 200, y: 0 },\n            },\n            a2: {\n                name: '습도센서',\n                type: 'input',\n                pos: { x: 400, y: 0 },\n            },\n            a7: {\n                name: '온도센서',\n                type: 'input',\n                pos: { x: 600, y: 0 },\n            },\n            a3: {\n                name: '아날로그1',\n                type: 'input',\n                pos: { x: 0, y: 500 },\n            },\n            a4: {\n                name: '아날로그2',\n                type: 'input',\n                pos: { x: 200, y: 500 },\n            },\n            a5: {\n                name: '아날로그3',\n                type: 'input',\n                pos: { x: 400, y: 500 },\n            },\n            a6: {\n                name: '아날로그4',\n                type: 'input',\n                pos: { x: 600, y: 500 },\n            },\n            28: {\n                name: '입력1',\n                type: 'input',\n                pos: { x: 0, y: 400 },\n            },\n            29: {\n                name: '입력2',\n                type: 'input',\n                pos: { x: 200, y: 400 },\n            },\n            1: {\n                name: '입력3',\n                type: 'input',\n                pos: { x: 400, y: 400 },\n            },\n            0: {\n                name: '입력4',\n                type: 'input',\n                pos: { x: 600, y: 400 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.lecoboardAvr.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                lecoboardAvr_button_read: '버튼 읽어오기',\n                lecoboardAvr_button_read_bool: '버튼 읽어오기',\n                lecoboardAvr_ultrasonic_read: '초음파센서 읽어오기',\n                lecoboardAvr_cds_read: '조도센서 읽어오기',\n                lecoboardAvr_var_read: '가변저항 읽어오기',\n                lecoboardAvr_ir_read: '습도센서 읽어오기',\n                lecoboardAvr_temp_read: '온도센서 읽어오기',\n                lecoboardAvr_analog_read: '아날로그입력 %1 읽어오기',\n                lecoboardAvr_digital_read: '디지털 %1 읽어오기',\n                lecoboardAvr_dual_led_color_toggle: 'LED %1 색으로 정하기 %2',\n                lecoboardAvr_dual_led_toggle: 'LED 녹색 %1 빨강 %2 으로 정하기 %3',\n                lecoboardAvr_led_rgb_toggle: 'RGB LED R%1 G%2 B%3 %4',\n                //lecoboardAvr_led_strip_toggle: 'LED 스트립 빨강%1 녹색%2 파랑%3 노랑%4 %5',\n                lecoboardAvr_set_tone: '부저를 %1 음으로 %2 박자로 연주하기 %3',\n                lecoboardAvr_set_tone_long: '부저를 %1 음으로 연주하기 %2',\n                lecoboardAvr_set_freq_tone: '신호음 %1번핀에서 %2 주파수로 %3 동안 연주하기 %4',\n                lecoboardAvr_set_tone_off: '부저 끄기 %1',\n                lecoboardAvr_set_servo: '%1번 서보모터 %2°로 정하기 %3',\n                lecoboardAvr_dc_motor: '%1번 DC모터 %2방향으로 속력%3 으로 정하기 %4',\n                lecoboardAvr_dc_motor_stop: 'DC 모터 정지하기',\n                lecoboardAvr_digital_write: '디지털 %1번핀에 %2 보내기 %3',\n                lecoboardAvr_digital_pwm: 'PWM %1 번핀에 %2 보내기 %3',\n                lecoboardAvr_convert_value: '%1의 값을 %2부터 %3까지의 값으로 변환하기 %4',\n                lecoboardAvr_lcd_command: 'LCD 설정 %1 %2',\n                lecoboardAvr_set_lcd: 'LCD %1번째줄 %2번째칸에 %3을 출력하기 %4',\n                lecoboardAvr_send_ble: '블루투스로 %1을 보내기 %2',\n                lecoboardAvr_get_bluetooth: '블루투스에서 읽어오기',                \n                lecoboardAvr_arm_control: '로봇팔 X%1 Y%2 Z%3 %4',\n                lecoboardAvr_arm_gripper_control: '로봇팔 그리퍼 A%1 G%2 %3',\n                lecoboardAvr_husky_al_set: '허스키렌즈 알고리즘 %1(으)로 설정하기 %2',\n                lecoboardAvr_husky_get_learn: '허스키렌즈 학습한 ID수 읽어오기',\n                lecoboardAvr_husky_get_item: '허스키렌즈 화면에 인식된 %1 읽어오기',\n                lecoboardAvr_husky_get_ID: '허스키렌즈 화면에 인식된 ID %1 %2 읽어오기',\n                lecoboardAvr_husky_get_closest_block: '허스키렌즈 화면 중심에서 가까운 %1 프레임 읽어오기',\n                lecoboardAvr_husky_get_closest_arrow: '허스키렌즈 화면 중심에서 가까운 %1 화살표 읽어오기',\n                lecoboardAvr_husky_get_id_block: '허스키렌즈 ID %1의 프레임에서 %2 읽어오기',\n                lecoboardAvr_husky_get_id_arrow: '허스키렌즈 ID %1의 화살표에서 %2 읽어오기',\n                lecoboardAvr_husky_get_id_learned: '허스키렌즈 학습한 ID %1이 있는지 읽어오기',\n                \n\n\n                /*\n                lecoboardAvr_dc_motor_for_sec: '%1번 DC모터 %2방향으로 속력%3 으로 %4초 동안 동작하기 %5',*/\n            },\n        },\n        en: {\n            template: {\n                lecoboardAvr_button_read: 'Button value',\n                lecoboardAvr_button_read_bool: 'Button value',\n                lecoboardAvr_ultrasonic_read: 'Read ultrasonic sensor',\n                lecoboardAvr_cds_read: 'Read cds sensor',\n                lecoboardAvr_var_read: 'Read var sensor',\n                lecoboardAvr_ir_read: 'Read  Humidity sensor',\n                lecoboardAvr_temp_read: 'Read temperature sensor',\n                lecoboardAvr_analog_read: 'Read Analog Input %1',\n                lecoboardAvr_digital_read: 'Read Digital %1 Pin',\n                lecoboardAvr_dual_led_color_toggle: 'LED %1 color %2',\n                lecoboardAvr_dual_led_toggle: 'LED green %1 red %2 value %3',\n                lecoboardAvr_set_tone: 'buzzer %1 tone %2 sec play %3',\n                lecoboardAvr_led_rgb_toggle: 'RGB LED R%1 G%2 B%3 %4',\n                //lecoboardAvr_led_strip_toggle: 'LED strip red%1 green%2 blue%3 yellow%4 %5',\n                lecoboardAvr_set_tone_long: 'buzzer %1 tone play %2',\n                lecoboardAvr_set_freq_tone: 'buzzer %1 pin %2 Hz %3 ms %4',\n                lecoboardAvr_set_tone_off: 'buzzer off',\n                lecoboardAvr_set_servo: '%1 Sevomotor angle as %2 %3',\n                lecoboardAvr_dc_motor: '%1 DC motor direction %2 speed %3 %4',\n                /*\n                lecoboardAvr_dc_motor_for_sec: '%1 DC motor direction %2 speed %3 sec %4 %5', */\n                lecoboardAvr_dc_motor_stop: 'DC motor stop',\n                lecoboardAvr_digital_write: 'Digital %1 port as %2 %3',\n                lecoboardAvr_digital_pwm: 'PWM %1 pin %2 out %3',\n                lecoboardAvr_convert_value: 'Convert value %1 from %2 to %3 %4',\n                lecoboardAvr_lcd_command: 'Set LCD cmd %1 %2',\n                lecoboardAvr_set_lcd: 'Set LCD data %1 %2 %3 %4',\n                lecoboardAvr_send_ble: 'BLE print %1 %2',\n                lecoboardAvr_get_bluetooth: 'Read from BLE',\n                lecoboardAvr_arm_control: 'Arm X%1 Y%2 Z%3 %4',\n                lecoboardAvr_arm_gripper_control: 'Arm gripper A%1 G%2 %3',\n                lecoboardAvr_husky_al_set: 'Huskylens Algorithm set as %1 %2',\n                lecoboardAvr_husky_get_learn: 'Read number of learned IDs',\n                lecoboardAvr_husky_get_item: 'Read check if %1 on screen',\n                lecoboardAvr_husky_get_ID: 'Read check if ID %1 of %2 on screen',\n                lecoboardAvr_husky_get_closest_block: 'Read %1 of frames closest to the center of screen',\n                lecoboardAvr_husky_get_closest_arrow: 'Read %1 of arrows closest to the center of screen',\n                lecoboardAvr_husky_get_id_block: 'Read frame ID %1  %2',\n                lecoboardAvr_husky_get_id_arrow: 'Read arrow ID %1  %2',\n                lecoboardAvr_husky_get_id_learned: 'Read Learned ID %1',\n            },\n        },\n    };\n};\n\nEntry.lecoboardAvr.blockMenuBlocks = [\n    'lecoboardAvr_led_rgb_toggle',\n    'lecoboardAvr_dual_led_color_toggle',\n    'lecoboardAvr_dual_led_toggle',\n    //'lecoboardAvr_led_strip_toggle',\n    'lecoboardAvr_button_read_bool',\n    'lecoboardAvr_button_read',\n    'lecoboardAvr_ultrasonic_read',\n    'lecoboardAvr_cds_read',\n    'lecoboardAvr_var_read',\n    'lecoboardAvr_ir_read',\n    'lecoboardAvr_temp_read',\n    'lecoboardAvr_analog_read',\n    'lecoboardAvr_digital_read',\n    'lecoboardAvr_convert_value',\n    'lecoboardAvr_set_tone',\n    'lecoboardAvr_set_tone_long',\n    'lecoboardAvr_set_freq_tone',\n    'lecoboardAvr_set_tone_off',\n    'lecoboardAvr_set_servo',\n    'lecoboardAvr_dc_motor',\n    //'lecoboardAvr_dc_motor_for_sec',\n    'lecoboardAvr_dc_motor_stop',\n    'lecoboardAvr_digital_write',\n    'lecoboardAvr_digital_pwm',\n    'lecoboardAvr_lcd_command',\n    'lecoboardAvr_set_lcd',\n    'lecoboardAvr_send_ble',\n    'lecoboardAvr_get_bluetooth',    \n    'lecoboardAvr_arm_control',\n    'lecoboardAvr_arm_gripper_control',\n    'lecoboardAvr_husky_al_set',\n    'lecoboardAvr_husky_get_learn',\n    'lecoboardAvr_husky_get_id_learned',\n    'lecoboardAvr_husky_get_item',\n    'lecoboardAvr_husky_get_ID',\n    'lecoboardAvr_husky_get_closest_block',\n    'lecoboardAvr_husky_get_closest_arrow',\n    'lecoboardAvr_husky_get_id_block',\n    'lecoboardAvr_husky_get_id_arrow',\n    \n];\n\nEntry.lecoboardAvr.getBlocks = function() {\n    return {\n        \n        lecoboardAvr_husky_al_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['얼굴 인식하기', '1'],\n                        ['사물 따라가기', '2'],\n                        ['사물 인식하기', '3'],\n                        ['선 따라가기', '4'],\n                        ['색깔 인식하기', '5'],\n                        ['태그 인식하기', '6'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1,null],\n                type: 'lecoboardAvr_husky_al_set',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {                  \n                let huskyitem = 1;      \n                let huskyset = script.getNumberValue('VALUE1',script);\n                \n                let port = 0;\n\n                port=1;\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port] = {\n                    type: 15, \n                    data: {\n                        huskyitem,\n                        huskyset,\n                    },\n                    time: new Date().getTime(),\n                };    \n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_husky_get_learn: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},     \n            def: {\n                params: [],\n                type: 'lecoboardAvr_husky_get_learn',\n            },\n            paramsKeyMap: {},\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const item = 1;\n                const id = 0;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvr.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.HUSKYLENS_LEARNED_CNT;\n            },\n        },\n        lecoboardAvr_husky_get_item: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['프레임', '2'],\n                        ['화살표', '3'],\n                    ],\n                    value: '2',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [2],\n                type: 'lecoboardAvr_husky_get_item',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const id = 0;\n                let result = 0;\n                const item = script.getNumberValue('VALUE1',script);\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvr.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(item==2)\n                    if(Entry.hw.portData.HUSKYLENS_BL_EXIST>0)result = true;\n                    else result = false;\n                else if(item==3)\n                    if(Entry.hw.portData.HUSKYLENS_AR_EXIST>0)result = true;\n                    else result = false;\n                else result = false;\n                return result;\n            },\n        },\n        lecoboardAvr_husky_get_ID: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['프레임', '4'],\n                        ['화살표', '5'],\n                    ],\n                    value: '4',\n                    size: 12,\n                },  \n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [1,4],\n                    },\n                ],\n                type: 'lecoboardAvr_husky_get_ID',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                let id = script.getNumberValue('VALUE1',script);;\n                let result = 0;\n                let item = script.getNumberValue('VALUE2',script);\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvr.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(item==4)\n                    if(Entry.hw.portData.HUSKYLENS_BLID_EXIST>0)result = true;\n                    else result = false;\n                else if(item==5)\n                    if(Entry.hw.portData.HUSKYLENS_ARID_EXIST>0)result = true;\n                    else result = false;\n                else result = false;\n               \n                return result;\n            },\n        },\n        lecoboardAvr_husky_get_closest_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID', '1'],\n                        ['X 중심점', '2'],\n                        ['Y 중심점', '3'],\n                        ['좌우 크기', '4'],\n                        ['상하 크기', '5'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboardAvr_husky_get_closest_block',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const id = 0;\n                let result = script.getNumberValue('VALUE1',script);\n                let item = 6;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvr.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                \n                if(result>=1)\n                    return Entry.hw.portData.HUSKYLENS_RESULT[result-1];\n                else return 0;\n            },\n        },\n        lecoboardAvr_husky_get_closest_arrow: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID', '1'],\n                        ['X 시작점', '2'],\n                        ['Y 시작점', '3'],\n                        ['X 끝점', '4'],\n                        ['Y 끝점', '5'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboardAvr_husky_get_closest_arrow',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const id = 0;\n                let result = script.getNumberValue('VALUE1',script);\n                let item = 7;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvr.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(result>=1)\n                    return Entry.hw.portData.HUSKYLENS_RESULT[result-1];\n                else return 0;\n            },\n        },\n        lecoboardAvr_husky_get_id_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X 중심점', '1'],\n                        ['Y 중심점', '2'],\n                        ['좌우 크기', '3'],\n                        ['상하 크기', '4'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [1,1],\n                type: 'lecoboardAvr_husky_get_id_block',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const id = script.getNumberValue('VALUE1',script);\n                let result = script.getNumberValue('VALUE2',script);\n                let item = 8;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvr.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(result>=1)\n                    return Entry.hw.portData.HUSKYLENS_RESULT[result];\n                else return 0;\n            },\n        },\n        lecoboardAvr_husky_get_id_arrow: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X 시작점', '1'],\n                        ['Y 시작점', '2'],\n                        ['X 끝점', '3'],\n                        ['Y 끝점', '4'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [1,1],\n                type: 'lecoboardAvr_husky_get_id_arrow',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const id = script.getNumberValue('VALUE1',script);\n                let result = script.getNumberValue('VALUE2',script);;\n                let item = 9;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvr.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(result>=1)\n                    return Entry.hw.portData.HUSKYLENS_RESULT[result];\n                else return 0;\n            },\n        },\n        lecoboardAvr_husky_get_id_learned: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            fontSize: 14,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',                    \n                    size: 12,\n                },       \n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboardAvr_husky_get_id_learned',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const id = script.getNumberValue('VALUE1',script);\n                const item = 10;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvr.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.HUSKYLENS_ID_LEARNED;\n            },\n        },\n        lecoboardAvr_arm_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [0],\n                    },\n                    {\n                        type: 'number',\n                        params: [95],\n                    },\n                    {\n                        type: 'number',\n                        params: [185],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_arm_control',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'lecoboardRobotArm',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {                \n                let value_x = script.getNumberValue('VALUE1',script);\n                let value_y = script.getNumberValue('VALUE2',script);\n                let value_z = script.getNumberValue('VALUE3',script);\n                let port = 0;\n\n                value_x = value_x*10;\n                value_y = value_y*10;\n                value_z = value_z*10;\n\n                port=31;\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.lecoboardAvr.sensorTypes.ARM_XYZ,\n                    data: {\n                        value_x,\n                        value_y,\n                        value_z,\n                    },\n                    time: new Date().getTime(),\n                };  \n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_arm_gripper_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [0],\n                    },\n                    {\n                        type: 'number',\n                        params: [45],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_arm_gripper_control',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardRobotArm',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {                \n                let value_w = script.getNumberValue('VALUE1',script);\n                let value_g = script.getNumberValue('VALUE2',script);\n                let port = 0;\n\n                value_w = value_w*10;\n                value_g = value_g*10;\n                \n\n                port=32;\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.lecoboardAvr.sensorTypes.ARM_WG,\n                    data: {\n                        value_w,\n                        value_g,\n                    },\n                    time: new Date().getTime(),\n                };    \n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_port_highlow_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORTVALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORTVALUE');\n            },\n        },\n        lecoboardAvr_digital_write: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    //accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_digital_write',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboardTest',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                let port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n\n                /*\n                if (value == 1) value = 255;\n                else value = 0;\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                */\n\n                if (typeof value === 'string') value = value.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value) > -1) value = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value) > -1) value = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    //accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboardTest',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                let port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n\n                value = 255 * (value / 100);\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_analog_input_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '3'],\n                        ['2', '4'],\n                        ['3', '5'],\n                        ['4', '6'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [3],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecoboardAvr_button_read_bool: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4'],\n                type: 'lecoboardAvr_button_read_bool',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const port = 4;\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboardAvr.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n            },\n        },\n        lecoboardAvr_button_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4'],\n                type: 'lecoboardAvr_button_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const port = 4;\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboardAvr.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n                //return DIGITAL ? DIGITAL[port] || 0 : 1;\n            },\n        },\n        lecoboardAvr_ultrasonic_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['5'],\n                    },\n                ],\n                type: 'lecoboardAvr_ultrasonic_read',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.ArduinoExt.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n        lecoboardAvr_analog_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_analog_input_list',\n                        params: ['3'],\n                    },\n                ],\n                type: 'lecoboardAvr_analog_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvr_cds_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvr_cds_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                let port = 0;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvr_var_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvr_var_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                let port = 1;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvr_ir_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvr_ir_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[7] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: 1,\n                    time: new Date().getTime(),\n                };\n\n                let port = 2;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvr_temp_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvr_temp_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                let port = 7;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvr_digital_port_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '28'],\n                        ['2', '29'],\n                        ['3', '1'],\n                        ['4', '0'],\n                    ],\n                    value: '28',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecoboardAvr_digital_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_digital_port_list',\n                        params: [28],\n                    },\n                ],\n                type: 'lecoboardAvr_digital_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n\n                const port = script.getNumberValue('PORT', script);\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboardAvr.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n            },\n        },\n        lecoboardAvr_convert_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['180'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_convert_value',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvr'],\n            func: function(sprite, script) {\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                var stringValue2 = script.getValue('VALUE2', script);\n                var stringValue3 = script.getValue('VALUE3', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue2) && stringValue2.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue3) && stringValue3.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                var result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                result = result * ((value3 - value2) / (1023 - 0));\n                result += value2;\n                result = Math.min(value3, result);\n                result = Math.max(value2, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n        },\n        lecoboardAvr_dual_color_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['녹색', '1'],\n                        ['빨강', '2'],\n                        ['오렌지', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            func(sprite, script) {\n                return script.getField('COLOR');\n            },\n        },\n\n        lecoboardAvr_dual_led_color_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_dual_color_list',\n                        params: [1],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_dual_led_color_toggle',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: '0lecoboardAvr_led',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const port1 = 17;\n                const port2 = 33;\n                let value1 = 0; //script.getValue('VALUE1');\n                let value2 = 0; //script.getValue('VALUE2');\n                let color = script.getValue('COLOR');\n\n                if (color == 1) {\n                    value1 = 255;\n                    value2 = 0;\n                } else if (color == 2) {\n                    value1 = 0;\n                    value2 = 255;\n                } else if (color == 3) {\n                    value1 = 255;\n                    value2 = 255;\n                }\n\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_dual_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_dual_led_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: '0lecoboardAvr_led',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const port1 = 17;\n                const port2 = 33;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_led_rgb_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_led_rgb_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: '0lecoboardAvr_led',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const port1 = 16;\n                const port2 = 15;\n                const port3 = 14;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n                let value3 = script.getValue('VALUE3');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                if (typeof value3 === 'string') value3 = value3.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value3) > -1) value3 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value3) > -1) value3 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_led_strip_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_led_strip_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n            },\n            class: '0lecoboardAvr_led',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const port1 = 13;\n                const port2 = 14;\n                const port3 = 15;\n                const port4 = 16;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n                let value3 = script.getValue('VALUE3');\n                let value4 = script.getValue('VALUE4');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                if (typeof value3 === 'string') value3 = value3.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value3) > -1) value3 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value3) > -1) value3 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n                if (typeof value4 === 'string') value4 = value4.toLowerCase();\n                if (Entry.lecoboardAvr.highList.indexOf(value4) > -1) value4 = 255;\n                else if (Entry.lecoboardAvr.lowList.indexOf(value4) > -1) value4 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port4] = {\n                    type: Entry.lecoboardAvr.sensorTypes.DIGITAL,\n                    data: value4,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                        [Lang.Blocks.do_name, 'C2'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        arduino_ext_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_tone_list',\n                    },\n                ],\n                type: 'arduino_ext_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n        },\n        arduino_ext_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        lecoboardAvr_buzzer_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboardAvr_buzzer_number',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n        },\n        lecoboardAvr_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_tone_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_set_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                DURATION: 1,\n            },\n            class: 'lecoboardAvr_buzzer',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                let note = script.getValue('NOTE', script);\n                if (!Entry.Utils.isNumber(note)) {\n                    note = Entry.lecoboardAvr.toneTable[note];\n                }\n\n                if (note < 0) {\n                    note = 0;\n                } else if (note > 13) {\n                    note = 13;\n                }\n\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration < 0) {\n                    duration = 0;\n                }\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                if (duration === 0) {\n                    sq.SET[port] = {\n                        type: Entry.lecoboardAvr.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n                let octave = 4;\n                let value = 0;\n\n                if (note != 0) {\n                    value = Entry.lecoboardAvr.toneMap[note][octave];\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboardAvr.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_set_freq_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['12'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['HZ'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_set_freq_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                DURATION: 2,\n            },\n            class: 'lecoboardAvr_buzzer',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                let freq = script.getNumberValue('NOTE', script);\n\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration < 0) {\n                    duration = 0;\n                }\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                if (duration === 0) {\n                    sq.SET[port] = {\n                        type: Entry.lecoboardAvr.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n                let value = freq;\n\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboardAvr.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_set_tone_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_buzzer_number',\n                        params: [1],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_set_tone_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'lecoboardAvr_buzzer',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = 0;\n                    let duration = 0;\n                    sq.SET[port] = {\n                        type: Entry.lecoboardAvr.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvr_set_tone_long: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_tone_list',\n                    },\n                ],\n                type: 'lecoboardAvr_set_tone_long',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            class: 'lecoboardAvr_buzzer',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                let note = script.getValue('NOTE', script);\n                if (!Entry.Utils.isNumber(note)) {\n                    note = Entry.lecoboardAvr.toneTable[note];\n                }\n\n                if (note < 0) {\n                    note = 0;\n                } else if (note > 13) {\n                    note = 13;\n                }\n\n                let duration = 20;\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                let octave = 4;\n                let value = 0;\n\n                if (note != 0) {\n                    value = Entry.lecoboardAvr.toneMap[note][octave];\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboardAvr.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_set_tone_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'lecoboardAvr_set_tone_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'lecoboardAvr_buzzer',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = 0;\n                    let duration = 0;\n                    sq.SET[port] = {\n                        type: Entry.lecoboardAvr.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvr_servomotor_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecoboardAvr_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                ],\n                type: 'lecoboardAvr_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboardAvr_servo',\n            isNotFor: ['lecoboardAvr'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let port = script.getNumberValue('PORT', script);\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n                else script.callReturn();\n\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(1, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.lecoboardAvr.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_dc_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '1'],\n                        ['오른쪽', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', '0'],\n                        ['반시계방향', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_dc_motor',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIR: 1,\n                SPEED: 2,\n            },\n            class: 'lecoboardAvr_motor',\n            isNotFor: ['lecoboardAvr'],\n            func: function(sprite, script) {\n                var idx = script.getField('INDEX');\n                var dir = script.getField('DIR');\n                var speed = script.getNumberValue('SPEED');\n                var value = 0;\n                var value1 = 0;\n                var value2 = 0;\n\n                var port1 = 0;\n                var port2 = 0;\n\n                if (idx == 1) {\n                    port1 = 28;\n                    port2 = 29;\n                } else if (idx == 2) {\n                    port1 = 1;\n                    port2 = 0;\n                }\n\n                var value = speed;\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n\n                value = value * (255 / 100);\n                value = Math.round(value);\n\n                if (dir == 0) {\n                    value1 = value;\n                    value2 = 0;\n                } else {\n                    value1 = 0;\n                    value2 = value;\n                }\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvr.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvr.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_dc_motor_for_sec: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', '0'],\n                        ['반시계방향', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_dc_motor_for_sec',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIR: 1,\n                SPEED: 2,\n                SEC: 3,\n            },\n            class: 'lecoboardAvr_motor',\n            isNotFor: ['lecoboardAvr'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var idx = script.getField('INDEX');\n                    var dir = script.getField('DIR');\n                    var speed = script.getNumberValue('SPEED');\n                    var sec = script.getNumberValue('SEC');\n                    var value = 0;\n                    var value1 = 0;\n                    var value2 = 0;\n\n                    var port1 = 0;\n                    var port2 = 0;\n\n                    if (idx == 1) {\n                        port1 = 28;\n                        port2 = 29;\n                    } else if (idx == 2) {\n                        port1 = 0;\n                        port2 = 1;\n                    }\n\n                    var value = speed;\n                    value = Math.round(value);\n                    value = Math.max(value, 0);\n                    value = Math.min(value, 100);\n\n                    value = value * (255 / 100);\n                    value = Math.round(value);\n\n                    if (dir == 0) {\n                        value1 = value;\n                        value2 = 0;\n                    } else {\n                        value1 = 0;\n                        value2 = value;\n                    }\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n                    Entry.hw.sendQueue.SET[port1] = {\n                        type: Entry.lecoboardAvr.sensorTypes.PWM,\n                        data: value1,\n                        time: new Date().getTime(),\n                    };\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n                    Entry.hw.sendQueue.SET[port2] = {\n                        type: Entry.lecoboardAvr.sensorTypes.PWM,\n                        data: value2,\n                        time: new Date().getTime(),\n                    };\n\n                    sec = sec * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, sec);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue.SET[port1] = {\n                        type: Entry.lecoboardAvr.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.hw.sendQueue.SET[port2] = {\n                        type: Entry.lecoboardAvr.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvr_dc_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'lecoboardAvr_dc_motor_stop',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'lecoboardAvr_motor',\n            isNotFor: ['lecoboardAvr'],\n            func: function(sprite, script) {\n                var port1 = 28;\n                var port2 = 29;\n                var port3 = 1;\n                var port4 = 0;\n\n                var value = 0;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvr.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvr.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboardAvr.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port4] = {\n                    type: Entry.lecoboardAvr.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n\n        lecoboardAvr_list_digital_lcd_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        lecoboardAvr_list_digital_lcd_column: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                        ['9', '8'],\n                        ['10', '9'],\n                        ['11', '10'],\n                        ['12', '11'],\n                        ['13', '12'],\n                        ['14', '13'],\n                        ['15', '14'],\n                        ['16', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLUMN: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COLUMN');\n            },\n        },\n        lecoboardAvr_set_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            //template: Lang.template.lecoboardAvr_set_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_list_digital_lcd_line',\n                    },\n                    {\n                        type: 'lecoboardAvr_list_digital_lcd_column',\n                    },\n                    {\n                        type: 'text',\n                        params: ['HELLO'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_set_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                COLUMN: 1,\n                STRING: 2,\n            },\n            class: 'lecoboardLcd',\n            isNotFor: ['lecoboardAvr'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var line = script.getValue('LINE', script);\n                var column = script.getValue('COLUMN', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n                var str;\n                let temp = [];\n                //var string = script.getField('STRING');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                str = string;\n                if (!script.isStart) {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = string.charCodeAt(i);\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq.SET[1] = {\n                        type: Entry.lecoboardAvr.sensorTypes.LCD,\n                        data: {\n                            line: line,\n                            column: column,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvr_list_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['지움', '2'],\n\n                        ['백라이트켜기', '3'],\n                        ['백라이트끄기', '4'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COMMAND');\n            },\n        },\n        lecoboardAvr_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            //template: Lang.template.lecoboardAvr_lcd_command,\n            //\"template\": \"%1 %2\",\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvr_list_lcd_command',\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_lcd_command',\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n            },\n            class: 'lecoboardLcd',\n            isNotFor: ['lecoboardAvr'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var value = script.getNumberValue('COMMAND', script);\n                var command = script.getNumberValue('COMMAND', script);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n\n                sq.SET[0] = {\n                    type: Entry.lecoboardAvr.sensorTypes.LCD_COMMAND,\n                    data: {\n                        value: value,\n                        command: command,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvr_send_ble: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            //template: Lang.template.lecoboardAvr_set_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['HELLO'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvr_send_ble',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'lecoboardble',\n            isNotFor: ['lecoboardAvr'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var string = script.getValue('STRING', script);\n                var text = [];\n                var str;\n                let temp = [];\n                //var string = script.getField('STRING');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                str = string;\n                if (!script.isStart) {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = string.charCodeAt(i);\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq.SET[1] = {\n                        type: Entry.lecoboardAvr.sensorTypes.BLE_WRITE,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvr_get_bluetooth: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //template: Lang.template.lecoboardAvr_get_digital_bluetooth,\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvr_get_bluetooth',\n            },\n            paramsKeyMap: {},\n            class: 'lecoboardble',\n            isNotFor: ['lecoboardAvr'],\n            func: function(sprite, script) {\n                var port = 2;\n                var getString = Entry.hw.portData.BLE_READ;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboardAvr.sensorTypes.BLE_READ] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n\n                return getString ? getString.slice(0, getString.length - 1) : ' ';\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.lecoboardAvr;"
  },
  {
    "path": "src/playground/blocks/hardware/block_lecoboardAvrBT.js",
    "content": "'use strict';\n\nEntry.lecoboardAvrBT = {\n    id: '3C.4',\n    name: 'lecoboardAvrBT',\n    url: 'http://www.fnj.or.kr/',\n    imageName: 'lecoboardAvrBT.png',\n    title: {\n        ko: '레코보드2.0 BT',\n        en: 'LECOBOARD2.0 BT',\n    },\n    setZero() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 34; port++) {\n            if (port == 13 || port == 14 || port == 15 || port == 16 || port == 33) {\n                Entry.hw.sendQueue[port] = 1;\n            } else if (port == 17) {\n                Entry.hw.sendQueue[port] = 0;\n            } else {\n                Entry.hw.sendQueue[port] = 0;\n                Entry.hw.sendQueue.readablePorts.push(port);\n            }\n        }\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        LCD: 9,\n        LCD_COMMAND: 10,\n        BLE_WRITE: 11,\n        BLE_READ: 12,        \n        ARM_XYZ: 13,\n        ARM_WG: 14,\n        HUSKY: 15,\n        HUSKY_GET: 16,\n        HUSKY_GET_LEARNED_ID_CNT: 17,\n        HUSKY_GET_BLOCK_CNT: 18,\n        HUSKY_GET_ARROW_CNT: 19,\n        HUSKY_GET_ID: 20,\n        HUSKY_GET_XD: 21,\n        HUSKY_GET_YD: 22,\n        HUSKY_GET_WD: 23,\n        HUSKY_GET_HT: 24, \n        HUSKY_GET_ID_BL_EXIST: 25,\n        HUSKY_GET_ID_AR_EXIST: 26,\n        HUSKY_GET_BLOCK_INFO: 27,\n        HUSKY_GET_ARROW_INFO: 28, \n        HUSKY_GET_ID_LEARNED: 29,\n    },\n\n\n\n    toneTable: {\n        0: 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n        C2: 13,\n    },\n    toneMap: {\n        1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        4: [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        5: [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        6: [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n        13: [65, 131, 262, 523, 1046, 2093, 4186, 8372],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n    monitorTemplate: {\n        //imgPath: 'hw/lecoboard.png',\n        //keys: ['value'],\n        width: 800,\n        height: 600,\n        listPorts: {\n            BLE_READ: {\n                name: '블루투스',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            ULTRASONIC: {\n                name: '초음파센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            4: {\n                name: '버튼입력',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: '조도센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: '가변저항',\n                type: 'input',\n                pos: { x: 200, y: 0 },\n            },\n            a2: {\n                name: '습도센서',\n                type: 'input',\n                pos: { x: 400, y: 0 },\n            },\n            a7: {\n                name: '온도센서',\n                type: 'input',\n                pos: { x: 600, y: 0 },\n            },\n            a3: {\n                name: '아날로그1',\n                type: 'input',\n                pos: { x: 0, y: 500 },\n            },\n            a4: {\n                name: '아날로그2',\n                type: 'input',\n                pos: { x: 200, y: 500 },\n            },\n            a5: {\n                name: '아날로그3',\n                type: 'input',\n                pos: { x: 400, y: 500 },\n            },\n            a6: {\n                name: '아날로그4',\n                type: 'input',\n                pos: { x: 600, y: 500 },\n            },\n            28: {\n                name: '입력1',\n                type: 'input',\n                pos: { x: 0, y: 400 },\n            },\n            29: {\n                name: '입력2',\n                type: 'input',\n                pos: { x: 200, y: 400 },\n            },\n            1: {\n                name: '입력3',\n                type: 'input',\n                pos: { x: 400, y: 400 },\n            },\n            0: {\n                name: '입력4',\n                type: 'input',\n                pos: { x: 600, y: 400 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.lecoboardAvrBT.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                lecoboardAvrBT_button_read: '버튼 읽어오기',\n                lecoboardAvrBT_button_read_bool: '버튼 읽어오기',\n                lecoboardAvrBT_ultrasonic_read: '초음파센서 읽어오기',\n                lecoboardAvrBT_cds_read: '조도센서 읽어오기',\n                lecoboardAvrBT_var_read: '가변저항 읽어오기',\n                lecoboardAvrBT_ir_read: '습도센서 읽어오기',\n                lecoboardAvrBT_temp_read: '온도센서 읽어오기',\n                lecoboardAvrBT_analog_read: '아날로그입력 %1 읽어오기',\n                lecoboardAvrBT_digital_read: '디지털 %1 읽어오기',\n                lecoboardAvrBT_dual_led_color_toggle: 'LED %1 색으로 정하기 %2',\n                lecoboardAvrBT_dual_led_toggle: 'LED 녹색 %1 빨강 %2 으로 정하기 %3',\n                lecoboardAvrBT_led_rgb_toggle: 'RGB LED R%1 G%2 B%3 %4',\n                //lecoboardAvrBT_led_strip_toggle: 'LED 스트립 빨강%1 녹색%2 파랑%3 노랑%4 %5',\n                lecoboardAvrBT_set_tone: '부저를 %1 음으로 %2 박자로 연주하기 %3',\n                lecoboardAvrBT_set_tone_long: '부저를 %1 음으로 연주하기 %2',\n                lecoboardAvrBT_set_freq_tone: '신호음 %1번핀에서 %2 주파수로 %3 동안 연주하기 %4',\n                lecoboardAvrBT_set_tone_off: '부저 끄기 %1',\n                lecoboardAvrBT_set_servo: '%1번 서보모터 %2°로 정하기 %3',\n                lecoboardAvrBT_dc_motor: '%1번 DC모터 %2방향으로 속력%3 으로 정하기 %4',\n                lecoboardAvrBT_dc_motor_stop: 'DC 모터 정지하기',\n                lecoboardAvrBT_digital_write: '디지털 %1번핀에 %2 보내기 %3',\n                lecoboardAvrBT_digital_pwm: 'PWM %1 번핀에 %2 보내기 %3',\n                lecoboardAvrBT_convert_value: '%1의 값을 %2부터 %3까지의 값으로 변환하기 %4',\n                lecoboardAvrBT_lcd_command: 'LCD 설정 %1 %2',\n                lecoboardAvrBT_set_lcd: 'LCD %1번째줄 %2번째칸에 %3을 출력하기 %4',\n                lecoboardAvrBT_send_ble: '블루투스로 %1을 보내기 %2',\n                lecoboardAvrBT_get_bluetooth: '블루투스에서 읽어오기',                \n                lecoboardAvrBT_arm_control: '로봇팔 X%1 Y%2 Z%3 %4',\n                lecoboardAvrBT_arm_gripper_control: '로봇팔 그리퍼 A%1 G%2 %3',\n                lecoboardAvrBT_husky_al_set: '허스키렌즈 알고리즘 %1(으)로 설정하기 %2',\n                lecoboardAvrBT_husky_get_learn: '허스키렌즈 학습한 ID수 읽어오기',\n                lecoboardAvrBT_husky_get_item: '허스키렌즈 화면에 인식된 %1 읽어오기',\n                lecoboardAvrBT_husky_get_ID: '허스키렌즈 화면에 인식된 ID %1 %2 읽어오기',\n                lecoboardAvrBT_husky_get_closest_block: '허스키렌즈 화면 중심에서 가까운 %1 프레임 읽어오기',\n                lecoboardAvrBT_husky_get_closest_arrow: '허스키렌즈 화면 중심에서 가까운 %1 화살표 읽어오기',\n                lecoboardAvrBT_husky_get_id_block: '허스키렌즈 ID %1의 프레임에서 %2 읽어오기',\n                lecoboardAvrBT_husky_get_id_arrow: '허스키렌즈 ID %1의 화살표에서 %2 읽어오기',\n                lecoboardAvrBT_husky_get_id_learned: '허스키렌즈 학습한 ID %1이 있는지 읽어오기',\n                \n\n\n                /*\n                lecoboardAvrBT_dc_motor_for_sec: '%1번 DC모터 %2방향으로 속력%3 으로 %4초 동안 동작하기 %5',*/\n            },\n        },\n        en: {\n            template: {\n                lecoboardAvrBT_button_read: 'Button value',\n                lecoboardAvrBT_button_read_bool: 'Button value',\n                lecoboardAvrBT_ultrasonic_read: 'Read ultrasonic sensor',\n                lecoboardAvrBT_cds_read: 'Read cds sensor',\n                lecoboardAvrBT_var_read: 'Read var sensor',\n                lecoboardAvrBT_ir_read: 'Read  Humidity sensor',\n                lecoboardAvrBT_temp_read: 'Read temperature sensor',\n                lecoboardAvrBT_analog_read: 'Read Analog Input %1',\n                lecoboardAvrBT_digital_read: 'Read Digital %1 Pin',\n                lecoboardAvrBT_dual_led_color_toggle: 'LED %1 color %2',\n                lecoboardAvrBT_dual_led_toggle: 'LED green %1 red %2 value %3',\n                lecoboardAvrBT_set_tone: 'buzzer %1 tone %2 sec play %3',\n                lecoboardAvrBT_led_rgb_toggle: 'RGB LED R%1 G%2 B%3 %4',\n                //lecoboardAvrBT_led_strip_toggle: 'LED strip red%1 green%2 blue%3 yellow%4 %5',\n                lecoboardAvrBT_set_tone_long: 'buzzer %1 tone play %2',\n                lecoboardAvrBT_set_freq_tone: 'buzzer %1 pin %2 Hz %3 ms %4',\n                lecoboardAvrBT_set_tone_off: 'buzzer off',\n                lecoboardAvrBT_set_servo: '%1 Sevomotor angle as %2 %3',\n                lecoboardAvrBT_dc_motor: '%1 DC motor direction %2 speed %3 %4',\n                /*\n                lecoboardAvrBT_dc_motor_for_sec: '%1 DC motor direction %2 speed %3 sec %4 %5', */\n                lecoboardAvrBT_dc_motor_stop: 'DC motor stop',\n                lecoboardAvrBT_digital_write: 'Digital %1 port as %2 %3',\n                lecoboardAvrBT_digital_pwm: 'PWM %1 pin %2 out %3',\n                lecoboardAvrBT_convert_value: 'Convert value %1 from %2 to %3 %4',\n                lecoboardAvrBT_lcd_command: 'Set LCD cmd %1 %2',\n                lecoboardAvrBT_set_lcd: 'Set LCD data %1 %2 %3 %4',\n                lecoboardAvrBT_send_ble: 'BLE print %1 %2',\n                lecoboardAvrBT_get_bluetooth: 'Read from BLE',\n                lecoboardAvrBT_arm_control: 'Arm X%1 Y%2 Z%3 %4',\n                lecoboardAvrBT_arm_gripper_control: 'Arm gripper A%1 G%2 %3',\n                lecoboardAvrBT_husky_al_set: 'Huskylens Algorithm set as %1 %2',\n                lecoboardAvrBT_husky_get_learn: 'Read number of learned IDs',\n                lecoboardAvrBT_husky_get_item: 'Read check if %1 on screen',\n                lecoboardAvrBT_husky_get_ID: 'Read check if ID %1 of %2 on screen',\n                lecoboardAvrBT_husky_get_closest_block: 'Read %1 of frames closest to the center of screen',\n                lecoboardAvrBT_husky_get_closest_arrow: 'Read %1 of arrows closest to the center of screen',\n                lecoboardAvrBT_husky_get_id_block: 'Read frame ID %1  %2',\n                lecoboardAvrBT_husky_get_id_arrow: 'Read arrow ID %1  %2',\n                lecoboardAvrBT_husky_get_id_learned: 'Read Learned ID %1',\n            },\n        },\n    };\n};\n\nEntry.lecoboardAvrBT.blockMenuBlocks = [\n    'lecoboardAvrBT_led_rgb_toggle',\n    'lecoboardAvrBT_dual_led_color_toggle',\n    'lecoboardAvrBT_dual_led_toggle',\n    //'lecoboardAvrBT_led_strip_toggle',\n    'lecoboardAvrBT_button_read_bool',\n    'lecoboardAvrBT_button_read',\n    'lecoboardAvrBT_ultrasonic_read',\n    'lecoboardAvrBT_cds_read',\n    'lecoboardAvrBT_var_read',\n    'lecoboardAvrBT_ir_read',\n    'lecoboardAvrBT_temp_read',\n    'lecoboardAvrBT_analog_read',\n    'lecoboardAvrBT_digital_read',\n    'lecoboardAvrBT_convert_value',\n    'lecoboardAvrBT_set_tone',\n    'lecoboardAvrBT_set_tone_long',\n    'lecoboardAvrBT_set_freq_tone',\n    'lecoboardAvrBT_set_tone_off',\n    'lecoboardAvrBT_set_servo',\n    'lecoboardAvrBT_dc_motor',\n    //'lecoboardAvrBT_dc_motor_for_sec',\n    'lecoboardAvrBT_dc_motor_stop',\n    'lecoboardAvrBT_digital_write',\n    'lecoboardAvrBT_digital_pwm',\n    'lecoboardAvrBT_lcd_command',\n    'lecoboardAvrBT_set_lcd',\n    'lecoboardAvrBT_send_ble',\n    'lecoboardAvrBT_get_bluetooth',    \n    'lecoboardAvrBT_arm_control',\n    'lecoboardAvrBT_arm_gripper_control',\n    'lecoboardAvrBT_husky_al_set',\n    'lecoboardAvrBT_husky_get_learn',\n    'lecoboardAvrBT_husky_get_id_learned',\n    'lecoboardAvrBT_husky_get_item',\n    'lecoboardAvrBT_husky_get_ID',\n    'lecoboardAvrBT_husky_get_closest_block',\n    'lecoboardAvrBT_husky_get_closest_arrow',\n    'lecoboardAvrBT_husky_get_id_block',\n    'lecoboardAvrBT_husky_get_id_arrow',\n    \n];\n\nEntry.lecoboardAvrBT.getBlocks = function() {\n    return {\n        \n        lecoboardAvrBT_husky_al_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['얼굴 인식하기', '1'],\n                        ['사물 따라가기', '2'],\n                        ['사물 인식하기', '3'],\n                        ['선 따라가기', '4'],\n                        ['색깔 인식하기', '5'],\n                        ['태그 인식하기', '6'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [1,null],\n                type: 'lecoboardAvrBT_husky_al_set',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {                  \n                let huskyitem = 1;      \n                let huskyset = script.getNumberValue('VALUE1',script);\n                \n                let port = 0;\n\n                port=1;\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port] = {\n                    type: 15, \n                    data: {\n                        huskyitem,\n                        huskyset,\n                    },\n                    time: new Date().getTime(),\n                };    \n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_husky_get_learn: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},     \n            def: {\n                params: [],\n                type: 'lecoboardAvrBT_husky_get_learn',\n            },\n            paramsKeyMap: {},\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const item = 1;\n                const id = 0;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvrBT.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.HUSKYLENS_LEARNED_CNT;\n            },\n        },\n        lecoboardAvrBT_husky_get_item: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['프레임', '2'],\n                        ['화살표', '3'],\n                    ],\n                    value: '2',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [2],\n                type: 'lecoboardAvrBT_husky_get_item',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const id = 0;\n                let result = 0;\n                const item = script.getNumberValue('VALUE1',script);\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvrBT.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(item==2)\n                    if(Entry.hw.portData.HUSKYLENS_BL_EXIST>0)result = true;\n                    else result = false;\n                else if(item==3)\n                    if(Entry.hw.portData.HUSKYLENS_AR_EXIST>0)result = true;\n                    else result = false;\n                else result = false;\n                return result;\n            },\n        },\n        lecoboardAvrBT_husky_get_ID: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['프레임', '4'],\n                        ['화살표', '5'],\n                    ],\n                    value: '4',\n                    size: 12,\n                },  \n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [1,4],\n                    },\n                ],\n                type: 'lecoboardAvrBT_husky_get_ID',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                let id = script.getNumberValue('VALUE1',script);;\n                let result = 0;\n                let item = script.getNumberValue('VALUE2',script);\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvrBT.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(item==4)\n                    if(Entry.hw.portData.HUSKYLENS_BLID_EXIST>0)result = true;\n                    else result = false;\n                else if(item==5)\n                    if(Entry.hw.portData.HUSKYLENS_ARID_EXIST>0)result = true;\n                    else result = false;\n                else result = false;\n               \n                return result;\n            },\n        },\n        lecoboardAvrBT_husky_get_closest_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID', '1'],\n                        ['X 중심점', '2'],\n                        ['Y 중심점', '3'],\n                        ['좌우 크기', '4'],\n                        ['상하 크기', '5'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboardAvrBT_husky_get_closest_block',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const id = 0;\n                let result = script.getNumberValue('VALUE1',script);\n                let item = 6;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvrBT.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                \n                if(result>=1)\n                    return Entry.hw.portData.HUSKYLENS_RESULT[result-1];\n                else return 0;\n            },\n        },\n        lecoboardAvrBT_husky_get_closest_arrow: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID', '1'],\n                        ['X 시작점', '2'],\n                        ['Y 시작점', '3'],\n                        ['X 끝점', '4'],\n                        ['Y 끝점', '5'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboardAvrBT_husky_get_closest_arrow',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const id = 0;\n                let result = script.getNumberValue('VALUE1',script);\n                let item = 7;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvrBT.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(result>=1)\n                    return Entry.hw.portData.HUSKYLENS_RESULT[result-1];\n                else return 0;\n            },\n        },\n        lecoboardAvrBT_husky_get_id_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X 중심점', '1'],\n                        ['Y 중심점', '2'],\n                        ['좌우 크기', '3'],\n                        ['상하 크기', '4'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [1,1],\n                type: 'lecoboardAvrBT_husky_get_id_block',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const id = script.getNumberValue('VALUE1',script);\n                let result = script.getNumberValue('VALUE2',script);\n                let item = 8;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvrBT.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(result>=1)\n                    return Entry.hw.portData.HUSKYLENS_RESULT[result];\n                else return 0;\n            },\n        },\n        lecoboardAvrBT_husky_get_id_arrow: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X 시작점', '1'],\n                        ['Y 시작점', '2'],\n                        ['X 끝점', '3'],\n                        ['Y 끝점', '4'],\n                    ],\n                    value: '1',\n                    size: 12,\n                },                \n            ],\n            events: {},\n            def: {\n                params: [1,1],\n                type: 'lecoboardAvrBT_husky_get_id_arrow',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const id = script.getNumberValue('VALUE1',script);\n                let result = script.getNumberValue('VALUE2',script);;\n                let item = 9;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvrBT.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                if(result>=1)\n                    return Entry.hw.portData.HUSKYLENS_RESULT[result];\n                else return 0;\n            },\n        },\n        lecoboardAvrBT_husky_get_id_learned: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            fontSize: 14,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',                    \n                    size: 12,\n                },       \n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboardAvrBT_husky_get_id_learned',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n            },\n            class: 'lecoboardHuskylens',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const id = script.getNumberValue('VALUE1',script);\n                const item = 10;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[16/*Entry.lecoboardAvrBT.sensorTypes.HUSKY*/] = {\n                    port: item,\n                    data: id,\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.HUSKYLENS_ID_LEARNED;\n            },\n        },\n        lecoboardAvrBT_arm_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [0],\n                    },\n                    {\n                        type: 'number',\n                        params: [95],\n                    },\n                    {\n                        type: 'number',\n                        params: [185],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_arm_control',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'lecoboardRobotArm',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {                \n                let value_x = script.getNumberValue('VALUE1',script);\n                let value_y = script.getNumberValue('VALUE2',script);\n                let value_z = script.getNumberValue('VALUE3',script);\n                let port = 0;\n\n                value_x = value_x*10;\n                value_y = value_y*10;\n                value_z = value_z*10;\n\n                port=31;\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[1] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.ARM_XYZ,\n                    data: {\n                        value_x,\n                        value_y,\n                        value_z,\n                    },\n                    time: new Date().getTime(),\n                };  \n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_arm_gripper_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [0],\n                    },\n                    {\n                        type: 'number',\n                        params: [45],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_arm_gripper_control',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'lecoboardRobotArm',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {                \n                let value_w = script.getNumberValue('VALUE1',script);\n                let value_g = script.getNumberValue('VALUE2',script);\n                let port = 0;\n\n                value_w = value_w*10;\n                value_g = value_g*10;\n                \n\n                port=32;\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.ARM_WG,\n                    data: {\n                        value_w,\n                        value_g,\n                    },\n                    time: new Date().getTime(),\n                };    \n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_port_highlow_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORTVALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORTVALUE');\n            },\n        },\n        lecoboardAvrBT_digital_write: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    //accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_digital_write',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboardTest',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                let port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n\n                /*\n                if (value == 1) value = 255;\n                else value = 0;\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                */\n\n                if (typeof value === 'string') value = value.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value) > -1) value = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value) > -1) value = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    //accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboardTest',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                let port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n\n                value = 255 * (value / 100);\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.ArduinoExt.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_analog_input_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '3'],\n                        ['2', '4'],\n                        ['3', '5'],\n                        ['4', '6'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [3],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecoboardAvrBT_button_read_bool: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4'],\n                type: 'lecoboardAvrBT_button_read_bool',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const port = 4;\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboardAvrBT.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n            },\n        },\n        lecoboardAvrBT_button_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4'],\n                type: 'lecoboardAvrBT_button_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const port = 4;\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboardAvrBT.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n                //return DIGITAL ? DIGITAL[port] || 0 : 1;\n            },\n        },\n        lecoboardAvrBT_ultrasonic_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['5'],\n                    },\n                ],\n                type: 'lecoboardAvrBT_ultrasonic_read',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.ArduinoExt.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n        lecoboardAvrBT_analog_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_analog_input_list',\n                        params: ['3'],\n                    },\n                ],\n                type: 'lecoboardAvrBT_analog_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvrBT_cds_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvrBT_cds_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                let port = 0;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvrBT_var_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvrBT_var_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                let port = 1;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvrBT_ir_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvrBT_ir_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[7] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: 1,\n                    time: new Date().getTime(),\n                };\n\n                let port = 2;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvrBT_temp_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvrBT_temp_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                let port = 7;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        lecoboardAvrBT_digital_port_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '28'],\n                        ['2', '29'],\n                        ['3', '1'],\n                        ['4', '0'],\n                    ],\n                    value: '28',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecoboardAvrBT_digital_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_digital_port_list',\n                        params: [28],\n                    },\n                ],\n                type: 'lecoboardAvrBT_digital_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n\n                const port = script.getNumberValue('PORT', script);\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboardAvrBT.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                let value = DIGITAL[port];\n                if (value == 0) value = 1;\n                else value = 0;\n                return value;\n            },\n        },\n        lecoboardAvrBT_convert_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['180'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_convert_value',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: 'LecoboardAnalogRead',\n            isNotFor: ['lecoboardAvrBT'],\n            func: function(sprite, script) {\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                var stringValue2 = script.getValue('VALUE2', script);\n                var stringValue3 = script.getValue('VALUE3', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue2) && stringValue2.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue3) && stringValue3.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                var result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                result = result * ((value3 - value2) / (1023 - 0));\n                result += value2;\n                result = Math.min(value3, result);\n                result = Math.max(value2, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n        },\n        lecoboardAvrBT_dual_color_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['녹색', '1'],\n                        ['빨강', '2'],\n                        ['오렌지', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            func(sprite, script) {\n                return script.getField('COLOR');\n            },\n        },\n\n        lecoboardAvrBT_dual_led_color_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_dual_color_list',\n                        params: [1],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_dual_led_color_toggle',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: '0lecoboardAvrBT_led',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const port1 = 17;\n                const port2 = 33;\n                let value1 = 0; //script.getValue('VALUE1');\n                let value2 = 0; //script.getValue('VALUE2');\n                let color = script.getValue('COLOR');\n\n                if (color == 1) {\n                    value1 = 255;\n                    value2 = 0;\n                } else if (color == 2) {\n                    value1 = 0;\n                    value2 = 255;\n                } else if (color == 3) {\n                    value1 = 255;\n                    value2 = 255;\n                }\n\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_dual_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_dual_led_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: '0lecoboardAvrBT_led',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const port1 = 17;\n                const port2 = 33;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_led_rgb_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_led_rgb_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n            },\n            class: '0lecoboardAvrBT_led',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const port1 = 16;\n                const port2 = 15;\n                const port3 = 14;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n                let value3 = script.getValue('VALUE3');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                if (typeof value3 === 'string') value3 = value3.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value3) > -1) value3 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value3) > -1) value3 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_led_strip_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_led_strip_toggle',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n            },\n            class: '0lecoboardAvrBT_led',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const port1 = 13;\n                const port2 = 14;\n                const port3 = 15;\n                const port4 = 16;\n                let value1 = script.getValue('VALUE1');\n                let value2 = script.getValue('VALUE2');\n                let value3 = script.getValue('VALUE3');\n                let value4 = script.getValue('VALUE4');\n\n                if (typeof value1 === 'string') value1 = value1.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value1) > -1) value1 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value1) > -1) value1 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (typeof value2 === 'string') value2 = value2.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value2) > -1) value2 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value2) > -1) value2 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                if (typeof value3 === 'string') value3 = value3.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value3) > -1) value3 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value3) > -1) value3 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n                if (typeof value4 === 'string') value4 = value4.toLowerCase();\n                if (Entry.lecoboardAvrBT.highList.indexOf(value4) > -1) value4 = 255;\n                else if (Entry.lecoboardAvrBT.lowList.indexOf(value4) > -1) value4 = 0;\n                else throw new Error();\n                if (!Entry.hw.sendQueue.SET) Entry.hw.sendQueue.SET = {};\n                Entry.hw.sendQueue.SET[port4] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.DIGITAL,\n                    data: value4,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                        [Lang.Blocks.do_name, 'C2'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n        arduino_ext_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_tone_list',\n                    },\n                ],\n                type: 'arduino_ext_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n        },\n        arduino_ext_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n        lecoboardAvrBT_buzzer_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [1],\n                type: 'lecoboardAvrBT_buzzer_number',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n        },\n        lecoboardAvrBT_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_tone_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_set_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                DURATION: 1,\n            },\n            class: 'lecoboardAvrBT_buzzer',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                let note = script.getValue('NOTE', script);\n                if (!Entry.Utils.isNumber(note)) {\n                    note = Entry.lecoboardAvrBT.toneTable[note];\n                }\n\n                if (note < 0) {\n                    note = 0;\n                } else if (note > 13) {\n                    note = 13;\n                }\n\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration < 0) {\n                    duration = 0;\n                }\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                if (duration === 0) {\n                    sq.SET[port] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n                let octave = 4;\n                let value = 0;\n\n                if (note != 0) {\n                    value = Entry.lecoboardAvrBT.toneMap[note][octave];\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_set_freq_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['12'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['HZ'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_set_freq_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                DURATION: 2,\n            },\n            class: 'lecoboardAvrBT_buzzer',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                let freq = script.getNumberValue('NOTE', script);\n\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration < 0) {\n                    duration = 0;\n                }\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                if (duration === 0) {\n                    sq.SET[port] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n                let value = freq;\n\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_set_tone_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_buzzer_number',\n                        params: [1],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_set_tone_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'lecoboardAvrBT_buzzer',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = 0;\n                    let duration = 0;\n                    sq.SET[port] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvrBT_set_tone_long: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_tone_list',\n                    },\n                ],\n                type: 'lecoboardAvrBT_set_tone_long',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            class: 'lecoboardAvrBT_buzzer',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                let note = script.getValue('NOTE', script);\n                if (!Entry.Utils.isNumber(note)) {\n                    note = Entry.lecoboardAvrBT.toneTable[note];\n                }\n\n                if (note < 0) {\n                    note = 0;\n                } else if (note > 13) {\n                    note = 13;\n                }\n\n                let duration = 20;\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                let octave = 4;\n                let value = 0;\n\n                if (note != 0) {\n                    value = Entry.lecoboardAvrBT.toneMap[note][octave];\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_set_tone_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'lecoboardAvrBT_set_tone_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'lecoboardAvrBT_buzzer',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12; //script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = 0;\n                    let duration = 0;\n                    sq.SET[port] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvrBT_servomotor_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        lecoboardAvrBT_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_servomotor_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                ],\n                type: 'lecoboardAvrBT_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'lecoboardAvrBT_servo',\n            isNotFor: ['lecoboardAvrBT'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let port = script.getNumberValue('PORT', script);\n\n                if (port == 1) port = 28;\n                else if (port == 2) port = 29;\n                else if (port == 3) port = 1;\n                else if (port == 4) port = 0;\n                else script.callReturn();\n\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(1, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_dc_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', '1'],\n                        ['오른쪽', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', '0'],\n                        ['반시계방향', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_dc_motor',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIR: 1,\n                SPEED: 2,\n            },\n            class: 'lecoboardAvrBT_motor',\n            isNotFor: ['lecoboardAvrBT'],\n            func: function(sprite, script) {\n                var idx = script.getField('INDEX');\n                var dir = script.getField('DIR');\n                var speed = script.getNumberValue('SPEED');\n                var value = 0;\n                var value1 = 0;\n                var value2 = 0;\n\n                var port1 = 0;\n                var port2 = 0;\n\n                if (idx == 1) {\n                    port1 = 28;\n                    port2 = 29;\n                } else if (idx == 2) {\n                    port1 = 1;\n                    port2 = 0;\n                }\n\n                var value = speed;\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n\n                value = value * (255 / 100);\n                value = Math.round(value);\n\n                if (dir == 0) {\n                    value1 = value;\n                    value2 = 0;\n                } else {\n                    value1 = 0;\n                    value2 = value;\n                }\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_dc_motor_for_sec: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', '0'],\n                        ['반시계방향', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_dc_motor_for_sec',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIR: 1,\n                SPEED: 2,\n                SEC: 3,\n            },\n            class: 'lecoboardAvrBT_motor',\n            isNotFor: ['lecoboardAvrBT'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var idx = script.getField('INDEX');\n                    var dir = script.getField('DIR');\n                    var speed = script.getNumberValue('SPEED');\n                    var sec = script.getNumberValue('SEC');\n                    var value = 0;\n                    var value1 = 0;\n                    var value2 = 0;\n\n                    var port1 = 0;\n                    var port2 = 0;\n\n                    if (idx == 1) {\n                        port1 = 28;\n                        port2 = 29;\n                    } else if (idx == 2) {\n                        port1 = 0;\n                        port2 = 1;\n                    }\n\n                    var value = speed;\n                    value = Math.round(value);\n                    value = Math.max(value, 0);\n                    value = Math.min(value, 100);\n\n                    value = value * (255 / 100);\n                    value = Math.round(value);\n\n                    if (dir == 0) {\n                        value1 = value;\n                        value2 = 0;\n                    } else {\n                        value1 = 0;\n                        value2 = value;\n                    }\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n                    Entry.hw.sendQueue.SET[port1] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                        data: value1,\n                        time: new Date().getTime(),\n                    };\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue.SET = {};\n                    }\n                    Entry.hw.sendQueue.SET[port2] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                        data: value2,\n                        time: new Date().getTime(),\n                    };\n\n                    sec = sec * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, sec);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue.SET[port1] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.hw.sendQueue.SET[port2] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvrBT_dc_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'lecoboardAvrBT_dc_motor_stop',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'lecoboardAvrBT_motor',\n            isNotFor: ['lecoboardAvrBT'],\n            func: function(sprite, script) {\n                var port1 = 28;\n                var port2 = 29;\n                var port3 = 1;\n                var port4 = 0;\n\n                var value = 0;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port4] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n\n        lecoboardAvrBT_list_digital_lcd_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        lecoboardAvrBT_list_digital_lcd_column: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                        ['9', '8'],\n                        ['10', '9'],\n                        ['11', '10'],\n                        ['12', '11'],\n                        ['13', '12'],\n                        ['14', '13'],\n                        ['15', '14'],\n                        ['16', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLUMN: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COLUMN');\n            },\n        },\n        lecoboardAvrBT_set_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            //template: Lang.template.lecoboardAvrBT_set_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_list_digital_lcd_line',\n                    },\n                    {\n                        type: 'lecoboardAvrBT_list_digital_lcd_column',\n                    },\n                    {\n                        type: 'text',\n                        params: ['HELLO'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_set_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                COLUMN: 1,\n                STRING: 2,\n            },\n            class: 'lecoboardLcd',\n            isNotFor: ['lecoboardAvrBT'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var line = script.getValue('LINE', script);\n                var column = script.getValue('COLUMN', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n                var str;\n                let temp = [];\n                //var string = script.getField('STRING');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                str = string;\n                if (!script.isStart) {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = string.charCodeAt(i);\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq.SET[1] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.LCD,\n                        data: {\n                            line: line,\n                            column: column,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvrBT_list_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['지움', '2'],\n\n                        ['백라이트켜기', '3'],\n                        ['백라이트끄기', '4'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COMMAND');\n            },\n        },\n        lecoboardAvrBT_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            //template: Lang.template.lecoboardAvrBT_lcd_command,\n            //\"template\": \"%1 %2\",\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'lecoboardAvrBT_list_lcd_command',\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_lcd_command',\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n            },\n            class: 'lecoboardLcd',\n            isNotFor: ['lecoboardAvrBT'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var value = script.getNumberValue('COMMAND', script);\n                var command = script.getNumberValue('COMMAND', script);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n\n                sq.SET[0] = {\n                    type: Entry.lecoboardAvrBT.sensorTypes.LCD_COMMAND,\n                    data: {\n                        value: value,\n                        command: command,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        lecoboardAvrBT_send_ble: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            //template: Lang.template.lecoboardAvrBT_set_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['HELLO'],\n                    },\n                    null,\n                ],\n                type: 'lecoboardAvrBT_send_ble',\n            },\n            paramsKeyMap: {\n                STRING: 0,\n            },\n            class: 'lecoboardble',\n            isNotFor: ['lecoboardAvrBT'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var string = script.getValue('STRING', script);\n                var text = [];\n                var str;\n                let temp = [];\n                //var string = script.getField('STRING');\n                if (string.length < 1) {\n                    return script.callReturn();\n                }\n                str = string;\n                if (!script.isStart) {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = string.charCodeAt(i);\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    sq.SET[1] = {\n                        type: Entry.lecoboardAvrBT.sensorTypes.BLE_WRITE,\n                        data: {\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n            },\n        },\n        lecoboardAvrBT_get_bluetooth: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            //template: Lang.template.lecoboardAvrBT_get_digital_bluetooth,\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'lecoboardAvrBT_get_bluetooth',\n            },\n            paramsKeyMap: {},\n            class: 'lecoboardble',\n            isNotFor: ['lecoboardAvrBT'],\n            func: function(sprite, script) {\n                var port = 2;\n                var getString = Entry.hw.portData.BLE_READ;\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.lecoboardAvrBT.sensorTypes.BLE_READ] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n\n                return getString ? getString.slice(0, getString.length - 1) : ' ';\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.lecoboardAvrBT;"
  },
  {
    "path": "src/playground/blocks/hardware/block_littlebits.js",
    "content": "'use strict';\n\nclass LittleBits {\n    id = '1.F';\n    name = 'littlebits';\n    url = 'https://playentry.org';\n    imageName = 'littlebits.png';\n    title = {\n        ko: '리틀비츠',\n        en: 'littleBits',\n    };\n\n    blockMenuBlocks = [\n        'littlebits_get_number_sensor_value',\n        'littlebits_get_digital_value',\n        'littlebits_toggle_led',\n        'littlebits_toggle_pwm',\n        'littlebits_convert_scale',\n    ];\n\n    setZero() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (let port = 0; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n    }\n\n    setLanguage() {\n        return {\n            ko: {\n                template: {\n                    littlebits_text: '%1',\n                    littlebits_get_sensor_number: '%1  ',\n                    littlebits_get_port_number: '%1  ',\n                    littlebits_get_pwm_port_number: '%1  ',\n                    littlebits_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                    littlebits_get_digital_value: '디지털 %1 번 센서값  ',\n                    littlebits_toggle_led: '디지털 %1 번 핀 %2 %3',\n                    littlebits_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                    littlebits_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                },\n                Menus: {\n                    littlebits: '리틀비츠',\n                },\n            },\n            en: {\n                template: {\n                    littlebits_text: '%1',\n                    littlebits_get_sensor_number: '%1  ',\n                    littlebits_get_port_number: '%1  ',\n                    littlebits_get_pwm_port_number: '%1  ',\n                    littlebits_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                    littlebits_get_digital_value: '디지털 %1 번 센서값  ',\n                    littlebits_toggle_led: '디지털 %1 번 핀 %2 %3',\n                    littlebits_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                    littlebits_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                },\n                Menus: {\n                    littlebits: 'Littlebits',\n                },\n            },\n        };\n    }\n\n    getBlocks() {\n        return {\n            littlebits_text: {\n                color: '#FFD974',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'TextInput',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: ['10'],\n                },\n                paramsKeyMap: {\n                    NAME: 0,\n                },\n\n                func(sprite, script) {\n                    return script.getStringField('NAME');\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1',\n                            textParams: [\n                                {\n                                    type: 'TextInput',\n                                    value: 10,\n                                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                                },\n                            ],\n                            keyOption: 'littlebits_text',\n                        },\n                    ],\n                },\n            },\n            littlebits_get_sensor_number: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['0', 'A0'],\n                            ['1', 'A1'],\n                            ['2', 'A2'],\n                            ['3', 'A3'],\n                            ['4', 'A4'],\n                            ['5', 'A5'],\n                        ],\n                        value: 'A0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                },\n                func(sprite, script) {\n                    return script.getStringField('PORT');\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        ['0', 'A0'],\n                                        ['1', 'A1'],\n                                        ['2', 'A2'],\n                                        ['3', 'A3'],\n                                        ['4', 'A4'],\n                                        ['5', 'A5'],\n                                    ],\n                                    value: 'A0',\n                                    fontSize: 11,\n                                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    converter: Entry.block.converters.returnStringValue,\n                                },\n                            ],\n                            keyOption: 'littlebits_get_sensor_number',\n                        },\n                    ],\n                },\n            },\n            littlebits_get_port_number: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['0', '0'],\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                            ['9', '9'],\n                            ['10', '10'],\n                            ['11', '11'],\n                            ['12', '12'],\n                            ['13', '13'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                },\n                func(sprite, script) {\n                    return script.getStringField('PORT');\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        ['0', '0'],\n                                        ['1', '1'],\n                                        ['2', '2'],\n                                        ['3', '3'],\n                                        ['4', '4'],\n                                        ['5', '5'],\n                                        ['6', '6'],\n                                        ['7', '7'],\n                                        ['8', '8'],\n                                        ['9', '9'],\n                                        ['10', '10'],\n                                        ['11', '11'],\n                                        ['12', '12'],\n                                        ['13', '13'],\n                                    ],\n                                    value: '0',\n                                    fontSize: 11,\n                                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                },\n                            ],\n                            keyOption: 'littlebits_get_port_number',\n                        },\n                    ],\n                },\n            },\n            littlebits_get_pwm_port_number: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['3', '3'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['9', '9'],\n                            ['10', '10'],\n                            ['11', '11'],\n                        ],\n                        value: '3',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                },\n                func(sprite, script) {\n                    return script.getStringField('PORT');\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: '%1',\n                            textParams: [\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        ['3', '3'],\n                                        ['5', '5'],\n                                        ['6', '6'],\n                                        ['9', '9'],\n                                        ['10', '10'],\n                                        ['11', '11'],\n                                    ],\n                                    value: '3',\n                                    fontSize: 11,\n                                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    converter: Entry.block.converters.returnStringOrNumberByValue,\n                                },\n                            ],\n                            keyOption: 'littlebits_get_pwm_port_number',\n                        },\n                    ],\n                },\n            },\n            littlebits_get_number_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'littlebits_get_sensor_number',\n                        },\n                    ],\n                    type: 'littlebits_get_number_sensor_value',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'littlebits_value',\n                isNotFor: ['littlebits'],\n                func(sprite, script) {\n                    const signal = script.getValue('VALUE', script);\n                    return Entry.hw.getAnalogPortValue(signal[1]);\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Arduino.sensor_value(%1)',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            littlebits_get_digital_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'littlebits_get_port_number',\n                        },\n                    ],\n                    type: 'littlebits_get_digital_value',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                },\n                class: 'littlebits_value',\n                isNotFor: ['littlebits'],\n                func(sprite, script) {\n                    const { hwModule = {} } = Entry.hw;\n                    const { name } = hwModule;\n                    if (name === 'ArduinoExt') {\n                        return Entry.block.littlebits_ext_get_digital.func(sprite, script);\n                    } else {\n                        const signal = script.getNumberValue('PORT', script);\n                        return Entry.hw.getDigitalPortValue(signal);\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Arduino.digitalRead(%1)',\n                            blockType: 'param',\n                            replaceBlockType: 'littlebits_ext_get_digital',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            littlebits_toggle_led: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.ARDUINO_on, 'on'],\n                            [Lang.Blocks.ARDUINO_off, 'off'],\n                        ],\n                        value: 'on',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'littlebits_get_port_number',\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'littlebits_toggle_led',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                    OPERATOR: 1,\n                },\n                class: 'littlebits_set',\n                isNotFor: ['littlebits'],\n                func(sprite, script) {\n                    const port = script.getNumberValue('VALUE');\n                    const operator = script.getField('OPERATOR');\n                    const value = operator == 'on' ? 255 : 0;\n                    Entry.hw.setDigitalPortValue(port, value);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Arduino.pin_digital(%1, %2)',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Dropdown',\n                                    options: [\n                                        [Lang.Blocks.ARDUINO_on, 'on'],\n                                        [Lang.Blocks.ARDUINO_off, 'off'],\n                                    ],\n                                    value: 'on',\n                                    fontSize: 11,\n                                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    converter: Entry.block.converters.returnStringValue,\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            littlebits_toggle_pwm: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'littlebits_get_pwm_port_number',\n                        },\n                        {\n                            type: 'littlebits_text',\n                            params: ['255'],\n                        },\n                        null,\n                    ],\n                    type: 'littlebits_toggle_pwm',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    VALUE: 1,\n                },\n                class: 'littlebits_set',\n                isNotFor: ['littlebits'],\n                func(sprite, script) {\n                    const port = script.getNumberValue('PORT');\n                    let value = script.getNumberValue('VALUE');\n                    value = Math.round(value);\n                    value = Math.max(value, 0);\n                    value = Math.min(value, 255);\n                    Entry.hw.setDigitalPortValue(port, value);\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Arduino.set_pin_digital(%1, %2)',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            littlebits_convert_scale: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'littlebits_get_number_sensor_value',\n                            params: [\n                                {\n                                    type: 'littlebits_get_sensor_number',\n                                    id: 'bl5e',\n                                },\n                            ],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['1023'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                    ],\n                    type: 'littlebits_convert_scale',\n                },\n                paramsKeyMap: {\n                    VALUE1: 0,\n                    VALUE2: 1,\n                    VALUE3: 2,\n                    VALUE4: 3,\n                    VALUE5: 4,\n                },\n                class: 'littlebits',\n                isNotFor: ['littlebits'],\n                func(sprite, script) {\n                    const value1 = script.getNumberValue('VALUE1', script);\n                    let value2 = script.getNumberValue('VALUE2', script);\n                    let value3 = script.getNumberValue('VALUE3', script);\n                    let value4 = script.getNumberValue('VALUE4', script);\n                    let value5 = script.getNumberValue('VALUE5', script);\n\n                    const stringValue4 = script.getValue('VALUE4', script);\n                    const stringValue5 = script.getValue('VALUE5', script);\n                    let isFloat = false;\n\n                    if (\n                        (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                        (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                    ) {\n                        isFloat = true;\n                    }\n\n                    let result = value1;\n                    if (value2 > value3) {\n                        var swap = value2;\n                        value2 = value3;\n                        value3 = swap;\n                    }\n                    if (value4 > value5) {\n                        var swap = value4;\n                        value4 = value5;\n                        value5 = swap;\n                    }\n                    result -= value2;\n                    result = result * ((value5 - value4) / (value3 - value2));\n                    result += value4;\n                    result = Math.min(value5, result);\n                    result = Math.max(value4, result);\n\n                    if (isFloat) {\n                        result = Math.round(result * 100) / 100;\n                    } else {\n                        result = Math.round(result);\n                    }\n\n                    return result;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'Arduino.convert_scale(%1, %2, %3, %4, %5)',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n        };\n    }\n}\n\nmodule.exports = new LittleBits();\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_magkinder.js",
    "content": "'use strict';\r\n\r\nEntry.MagKinder = {\r\n    id: '37.1',\r\n    name: 'magkinder',\r\n    url: 'https://www.magkinder.com',\r\n    imageName: 'magkinder.png',\r\n    title: {\r\n        ko: '맥킨더',\r\n        en: 'MagKinder'\r\n    },\r\n    timeouts: [],\r\n    array: {\r\n        AutoSensing: 0,\r\n        Stop: 1,\r\n        Move: 2,\r\n        Turn: 3,\r\n        WheelSpeed: 4,\r\n        LED: 5,\r\n        Volume: 6,\r\n        Speak: 7,\r\n        Scale: 8,\r\n        Mode: 9,\r\n    },\r\n\r\n    removeTimeout: function(id) {\r\n        clearTimeout(id);\r\n        var timeouts = this.timeouts;\r\n        var index = timeouts.indexOf(id);\r\n        if (index >= 0) {\r\n            timeouts.splice(index, 1);\r\n        }\r\n    },\r\n    removeAllTimeouts: function() {\r\n        var timeouts = this.timeouts;\r\n        for (var i in timeouts) {\r\n            clearTimeout(timeouts[i]);\r\n        }\r\n        this.timeouts = [];\r\n    },\r\n    setZero: function() {\r\n\r\n    }\r\n};\r\n\r\nEntry.MagKinder.setLanguage = function() {\r\n    return{\r\n        ko: {\r\n            template: {\r\n                magkinder_list_leftSide: '바깥 왼쪽',\r\n                magkinder_list_left: '왼쪽',\r\n                magkinder_list_right: '오른쪽',\r\n                magkinder_list_rightSide: '바깥 오른쪽',\r\n                magkinder_list_front: '앞쪽',\r\n                magkinder_list_both: '양쪽',\r\n                magkinder_list_forward: '앞으로',\r\n                magkinder_list_backwards: '뒤로',\r\n                magkinder_list_on: '켜기',\r\n                magkinder_list_off: '끄기',\r\n                magkinder_list_red: '빨간색',\r\n                magkinder_list_blue: '파란색',\r\n                magkinder_list_green: '초록색',\r\n                magkinder_list_yellow: '노란색',\r\n                magkinder_list_purple: '보라색',\r\n                magkinder_list_white: '하얀색',\r\n                magkinder_list_4_octave_C: '4 옥타브 도',\r\n                magkinder_list_4_octave_D: '4 옥타브 레',\r\n                magkinder_list_4_octave_E: '4 옥타브 미',\r\n                magkinder_list_4_octave_F: '4 옥타브 파',\r\n                magkinder_list_4_octave_G: '4 옥타브 솔',\r\n                magkinder_list_4_octave_A: '4 옥타브 라',\r\n                magkinder_list_4_octave_B: '4 옥타브 시',\r\n                magkinder_list_5_octave_C: '5 옥타브 도',\r\n                magkinder_list_5_octave_D: '5 옥타브 레',\r\n                magkinder_list_5_octave_E: '5 옥타브 미',\r\n                magkinder_list_5_octave_F: '5 옥타브 파',\r\n                magkinder_list_5_octave_G: '5 옥타브 솔',\r\n                magkinder_list_5_octave_A: '5 옥타브 라',\r\n                magkinder_list_5_octave_B: '5 옥타브 시',\r\n                magkinder_list_6_octave_C: '6 옥타브 도',\r\n                magkinder_list_codingMode: '코딩',\r\n                magkinder_list_lineMode: '라인',\r\n                magkinder_list_gestureFollowMode: '몸짓 따라가기',\r\n                magkinder_list_handFollowMode: '손 따라가기',\r\n                magkinder_list_AvoidMode: '피하기',\r\n                magkinder_list_gestureCodingMode: '몸짓 코딩',\r\n                magkinder_list_cardCodingMode: '카드 코딩',\r\n                magkinder_received_bottomSensor_block: '바닥 %1 센서 값',\r\n                magkinder_received_cardSensor_block: '카드 %1 센서 값',\r\n                magkinder_received_frontSensor_block: '전방 %1 센서 값',\r\n                magkinder_transmit_autoSensor_block: '센서값 자동 업데이트 %1 %2',\r\n                magkinder_transmit_moveStop_block: '정지하기 %1',\r\n                magkinder_transmit_move_block: '%1 으로 %2 cm 움직이기 %3',\r\n                magkinder_transmit_turn_block: '%1 으로 %2 ° 회전하기 %3',\r\n                magkinder_transmit_wheelSpeed_block: '%1 바퀴의 빠르기를 %2로 정하기 %3',\r\n                magkinder_transmit_eyeLED_block: '눈 LED 색상을 %1 으로 정하기 %2',\r\n                magkinder_transmit_volumm_block: '소리 크기를 %1 로 정하기 %2',\r\n                magkinder_transmit_speak_block: '%1 번 소리를 내기 %2',\r\n                magkinder_transmit_scale_block: '%1 음을 내기 %2',\r\n                magkinder_transmit_modeSetting_block: '%1 모드로 정하기 %2',\r\n            }\r\n        },\r\n        en: {\r\n            template: {\r\n                magkinder_list_leftSide: 'left side',\r\n                magkinder_list_left: 'left',\r\n                magkinder_list_right: 'right',\r\n                magkinder_list_rightSide: 'right side',\r\n                magkinder_list_front: 'front',\r\n                magkinder_list_forward: 'forward',\r\n                magkinder_list_backwards: 'backwards',\r\n                magkinder_list_both: 'both',\r\n                magkinder_list_on: 'on',\r\n                magkinder_list_off: 'off',\r\n                magkinder_list_red: 'red',\r\n                magkinder_list_blue: 'blue',\r\n                magkinder_list_green: 'green',\r\n                magkinder_list_yellow: 'yellow',\r\n                magkinder_list_purple: 'purple',\r\n                magkinder_list_white: 'white',                \r\n                magkinder_list_4_octave_C: '4 octave C',\r\n                magkinder_list_4_octave_D: '4 octave D',\r\n                magkinder_list_4_octave_E: '4 octave E',\r\n                magkinder_list_4_octave_F: '4 octave F',\r\n                magkinder_list_4_octave_G: '4 octave G',\r\n                magkinder_list_4_octave_A: '4 octave A',\r\n                magkinder_list_4_octave_B: '4 octave B',\r\n                magkinder_list_5_octave_C: '5 octave C',\r\n                magkinder_list_5_octave_D: '5 octave D',\r\n                magkinder_list_5_octave_E: '5 octave E',\r\n                magkinder_list_5_octave_F: '5 octave F',\r\n                magkinder_list_5_octave_G: '5 octave G',\r\n                magkinder_list_5_octave_A: '5 octave A',\r\n                magkinder_list_5_octave_B: '5 octave B',\r\n                magkinder_list_6_octave_C: '6 octave C',\r\n                magkinder_list_codingMode: 'Coding',\r\n                magkinder_list_lineMode: 'Line',\r\n                magkinder_list_gestureFollowMode: 'Gesture follow',\r\n                magkinder_list_handFollowMode: 'Hand follow',\r\n                magkinder_list_AvoidMode: 'Avoid',\r\n                magkinder_list_gestureCodingMode: 'Gesture coding',\r\n                magkinder_list_cardCodingMode: 'Card coding',\r\n                magkinder_received_bottomSensor_block: 'Bottom %1 sensor value',\r\n                magkinder_received_cardSensor_block: 'Card %1 sensor value',\r\n                magkinder_received_frontSensor_block: 'Front %1 sensor value',\r\n                magkinder_transmit_autoSensor_block: 'Automatically update sensor values %1 %2',\r\n                magkinder_transmit_moveStop_block: 'Stop %1',\r\n                magkinder_transmit_move_block: 'Move to %1 %2 cm %3',\r\n                magkinder_transmit_turn_block: 'Rotate to %1 %2 ° %3',\r\n                magkinder_transmit_wheelSpeed_block: 'Set %1 wheel(s) speed %2 %3',\r\n                magkinder_transmit_eyeLED_block: 'Set eye LED color to %1 %2',\r\n                magkinder_transmit_volumm_block: 'Set sound volume to %1 %2',\r\n                magkinder_transmit_speak_block: 'Speaking No. %1 %2',\r\n                magkinder_transmit_scale_block: 'Speaking %1 %2',\r\n                magkinder_transmit_modeSetting_block: 'Set %1 mode %2',\r\n            }\r\n        }\r\n    };\r\n};\r\n\r\nEntry.MagKinder.blockMenuBlocks = [\r\n    'magkinder_received_bottomSensor_block',\r\n    'magkinder_received_cardSensor_block',\r\n    'magkinder_received_frontSensor_block',\r\n    //'magkinder_transmit_autoSensor_block',\r\n    'magkinder_transmit_moveStop_block',\r\n    'magkinder_transmit_move_block',\r\n    'magkinder_transmit_turn_block',\r\n    'magkinder_transmit_wheelSpeed_block',\r\n    'magkinder_transmit_eyeLED_block',\r\n    'magkinder_transmit_volumm_block',\r\n    'magkinder_transmit_speak_block',\r\n    'magkinder_transmit_scale_block',\r\n    //'magkinder_transmit_modeSetting_block',\r\n];\r\n\r\nEntry.MagKinder.getBlocks = function() {\r\n    return {\r\n        // region MagKinder 맥킨더        \r\n        magkinder_list_bottomSensor_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_leftSide, '0'],\r\n                        [Lang.template.magkinder_list_left, '1'],\r\n                        [Lang.template.magkinder_list_right, '2'],\r\n                        [Lang.template.magkinder_list_rightSide, '3'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_cardSensor_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_front, '0'],\r\n                        [Lang.template.magkinder_list_left, '1'],\r\n                        [Lang.template.magkinder_list_right, '2'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_frontSensor_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_left, '0'],\r\n                        [Lang.template.magkinder_list_right, '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_toggle_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_off, '0'],\r\n                        [Lang.template.magkinder_list_on, '1'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_motionMove_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_forward, '0'],\r\n                        [Lang.template.magkinder_list_backwards, '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_motionTurn_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_left, '2'],\r\n                        [Lang.template.magkinder_list_right, '3'],\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_wheelSpeed_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_left, '0'],\r\n                        [Lang.template.magkinder_list_right, '1'],\r\n                        [Lang.template.magkinder_list_both, '2'],\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_color_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_off, '0'],\r\n                        [Lang.template.magkinder_list_red, '1'],\r\n                        [Lang.template.magkinder_list_blue, '2'],\r\n                        [Lang.template.magkinder_list_green, '3'],\r\n                        [Lang.template.magkinder_list_yellow, '4'],\r\n                        [Lang.template.magkinder_list_purple, '5'],                        \r\n                        [Lang.template.magkinder_list_white, '6'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_soundVolume_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [\"0\", '0'],\r\n                        [\"1\", '1'],\r\n                        [\"2\", '2'],\r\n                        [\"3\", '3'],\r\n                        [\"4\", '4'],\r\n                        [\"5\", '5'],\r\n                        [\"6\", '6'],\r\n                        [\"7\", '7'],\r\n                    ],\r\n                    value: '7',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_speak_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [\"1\", '1'],\r\n                        [\"2\", '2'],\r\n                        [\"3\", '3'],\r\n                        [\"4\", '4'],\r\n                        [\"5\", '5'],\r\n                        [\"6\", '6'],\r\n                        [\"7\", '7'],\r\n                        [\"8\", '8'],\r\n                        [\"9\", '9'],\r\n                        [\"10\", '10'],\r\n                        [\"11\", '11'],\r\n                        [\"12\", '12'],\r\n                        [\"13\", '13'],\r\n                        [\"14\", '14'],\r\n                        [\"15\", '15'],\r\n                        [\"16\", '16'],\r\n                        [\"17\", '17'],\r\n                        [\"18\", '18'],\r\n                        [\"19\", '19'],\r\n                        [\"20\", '20'],\r\n                        [\"21\", '21'],\r\n                        [\"22\", '22'],\r\n                        [\"23\", '23'],\r\n                        [\"24\", '24'],\r\n                        [\"25\", '25'],\r\n                        [\"26\", '26'],\r\n                        [\"27\", '27'],\r\n                        [\"28\", '28'],\r\n                        [\"29\", '29'],\r\n                        [\"30\", '30'],\r\n                        [\"31\", '31'],\r\n                        [\"32\", '32'],\r\n                        [\"33\", '33'],\r\n                        [\"34\", '34'],\r\n                        [\"35\", '35'],\r\n                        [\"36\", '36'],\r\n                        [\"37\", '37'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_scale_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_4_octave_C, '22'],\r\n                        [Lang.template.magkinder_list_4_octave_D, '23'],\r\n                        [Lang.template.magkinder_list_4_octave_E, '24'],\r\n                        [Lang.template.magkinder_list_4_octave_F, '25'],\r\n                        [Lang.template.magkinder_list_4_octave_G, '26'],\r\n                        [Lang.template.magkinder_list_4_octave_A, '27'],\r\n                        [Lang.template.magkinder_list_4_octave_B, '28'],\r\n                        [Lang.template.magkinder_list_5_octave_C, '29'],\r\n                        [Lang.template.magkinder_list_5_octave_D, '30'],\r\n                        [Lang.template.magkinder_list_5_octave_E, '31'],\r\n                        [Lang.template.magkinder_list_5_octave_F, '32'],\r\n                        [Lang.template.magkinder_list_5_octave_G, '33'],\r\n                        [Lang.template.magkinder_list_5_octave_A, '34'],\r\n                        [Lang.template.magkinder_list_5_octave_B, '35'],\r\n                        [Lang.template.magkinder_list_6_octave_C, '36'],\r\n                    ],\r\n                    value: '22',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_list_modeSetting_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.template.magkinder_list_codingMode, '0'],\r\n                        [Lang.template.magkinder_list_lineMode, '1'],\r\n                        [Lang.template.magkinder_list_gestureFollowMode, '2'],\r\n                        [Lang.template.magkinder_list_handFollowMode, '3'],\r\n                        [Lang.template.magkinder_list_AvoidMode, '4'],\r\n                        [Lang.template.magkinder_list_gestureCodingMode, '5'],\r\n                        [Lang.template.magkinder_list_cardCodingMode, '6'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null]\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0\r\n            },\r\n            events: {},\r\n            func: function(sprite, script) {\r\n                return script.getField('VALUE');\r\n            }\r\n        },\r\n        magkinder_received_bottomSensor_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_received_bottomSensor_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_bottomSensor_block',\r\n                    },\r\n                ],\r\n                type: 'magkinder_received_bottomSensor_block',\r\n            },\r\n            paramsKeyMap: {\r\n                BOTTOM_SENSOR: 0\r\n            },\r\n            events: {},\r\n            class: 'SensorClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n                var select = script.getNumberValue('BOTTOM_SENSOR');\r\n                var received = Entry.hw.portData;\r\n                var data = 0;\r\n\r\n                switch(select)\r\n                {\r\n                    case 0: data = received.bottom.leftSide; break;\r\n                    case 1: data = received.bottom.left; break;\r\n                    case 2: data = received.bottom.right; break;\r\n                    case 3: data = received.bottom.rightSide; break;\r\n                }\r\n\r\n                return data; \r\n            },\r\n        },\r\n        magkinder_received_cardSensor_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_received_cardSensor_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_cardSensor_block',\r\n                    },\r\n                ],\r\n                type: 'magkinder_received_cardSensor_block',\r\n            },\r\n            paramsKeyMap: {\r\n                CARD_SENSOR: 0\r\n            },\r\n            events: {},\r\n            class: 'SensorClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n                var select = script.getNumberValue('CARD_SENSOR');\r\n                var received = Entry.hw.portData;\r\n                var data = 0;\r\n\r\n                switch(select)\r\n                {\r\n                    case 0: data = received.card.front; break;\r\n                    case 1: data = received.card.left; break;\r\n                    case 2: data = received.card.right; break;\r\n                }\r\n\r\n                return data; \r\n            },\r\n        },\r\n        magkinder_received_frontSensor_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_received_frontSensor_block,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_frontSensor_block',\r\n                    },\r\n                ],\r\n                type: 'magkinder_received_frontSensor_block',\r\n            },\r\n            paramsKeyMap: {\r\n                CARD_SENSOR: 0\r\n            },\r\n            events: {},\r\n            class: 'SensorClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n                var select = script.getNumberValue('CARD_SENSOR');\r\n                var received = Entry.hw.portData;\r\n                var data = 0;\r\n\r\n                switch(select)\r\n                {\r\n                    case 0: data = received.front.left; break;\r\n                    case 1: data = received.front.right; break;\r\n                }\r\n\r\n                return data; \r\n            },\r\n        },\r\n        magkinder_transmit_autoSensor_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_autoSensor_block,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_toggle_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_autoSensor_block',\r\n            },\r\n            paramsKeyMap: {\r\n                TOGGLE: 1,\r\n            },\r\n            events: {},\r\n            class: 'SensorClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n                var data = script.getNumberValue(\"TOGGLE\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.AutoSensing] = {\r\n                        Toggle: data,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_moveStop_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_moveStop_block,\r\n             params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_moveStop_block',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            events: {},\r\n            class: 'MoveClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.Stop] = {\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_move_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_move_block,\r\n             params: [\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_motionMove_block',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['10'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_move_block',\r\n            },\r\n            paramsKeyMap: {\r\n            \tDIRECTION: 0,\r\n            \tDISTANCE: 1,\r\n            },\r\n            events: {},\r\n            class: 'MoveClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n            \tvar direction = script.getNumberValue(\"DIRECTION\");\r\n            \tvar distance = script.getNumberValue(\"DISTANCE\") * 10;\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.Move] = {\r\n                    \tDirection: direction,\r\n                    \tDistance: distance,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_turn_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_turn_block,\r\n             params: [\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_motionTurn_block',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['90'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_turn_block',\r\n            },\r\n            paramsKeyMap: {\r\n            \tDIRECTION: 0,\r\n            \tANGLE: 1,\r\n            },\r\n            events: {},\r\n            class: 'MoveClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n            \tvar direction = script.getNumberValue(\"DIRECTION\");\r\n            \tvar angle = script.getNumberValue(\"ANGLE\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.Turn] = {\r\n                    \tDirection: direction,\r\n                    \tAngle: angle,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_wheelSpeed_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_wheelSpeed_block,\r\n             params: [\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_wheelSpeed_block',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['999'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_wheelSpeed_block',\r\n            },\r\n            paramsKeyMap: {\r\n            \tWHEEL: 0,\r\n            \tSPEED: 1,\r\n            },\r\n            events: {},\r\n            class: 'MoveClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n            \tvar wheel = script.getNumberValue(\"WHEEL\");\r\n            \tvar speed = script.getNumberValue(\"SPEED\");\r\n\r\n            \tif(speed < -999) speed = -999;\r\n            \telse if(speed > 999) speed = 999;\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.WheelSpeed] = {\r\n                    \tWheel: wheel,\r\n                    \tSpeed: speed,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_eyeLED_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_eyeLED_block,\r\n             params: [\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_color_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_eyeLED_block',\r\n            },\r\n            paramsKeyMap: {\r\n            \tCOLOR: 0,\r\n            \tSPEED: 1,\r\n            },\r\n            events: {},\r\n            class: 'LedClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n            \tvar color = script.getNumberValue(\"COLOR\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.LED] = {\r\n                    \tColor: color,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_volumm_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_volumm_block,\r\n             params: [\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_soundVolume_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_volumm_block',\r\n            },\r\n            paramsKeyMap: {\r\n            \tVOLUME: 0\r\n            },\r\n            events: {},\r\n            class: 'SoundClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n            \tvar volume = script.getNumberValue(\"VOLUME\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.Volume] = {\r\n                    \tVolume: volume,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_speak_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_speak_block,\r\n             params: [\r\n                {\r\n                \ttype: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_speak_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_speak_block',\r\n            },\r\n            paramsKeyMap: {\r\n            \tSPEAK: 0\r\n            },\r\n            events: {},\r\n            class: 'SoundClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n            \tvar speak = script.getNumberValue(\"SPEAK\") - 1;\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.Speak] = {\r\n                    \tSpeak: speak,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_scale_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_scale_block,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_scale_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_scale_block',\r\n            },\r\n            paramsKeyMap: {\r\n                SCALE: 0\r\n            },\r\n            events: {},\r\n            class: 'SoundClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n                var scale = script.getNumberValue(\"SCALE\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.Scale] = {\r\n                        Scale: scale,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        magkinder_transmit_modeSetting_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            template: Lang.template.magkinder_transmit_modeSetting_block,\r\n             params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'magkinder_list_modeSetting_block',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'magkinder_transmit_modeSetting_block',\r\n            },\r\n            paramsKeyMap: {\r\n                MODE: 0\r\n            },\r\n            events: {},\r\n            class: 'ModeSettingClass',\r\n            isNotFor: ['magkinder'],\r\n            func: function(sprite, script) {\r\n                var mode = script.getNumberValue(\"MODE\");\r\n\r\n                if(!script.isStart)\r\n                {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    var timer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                        Entry.MagKinder.removeTimeout(timer);\r\n                    }, Entry.MagKinder.delayTime);\r\n                    Entry.MagKinder.timeouts.push(timer);\r\n                    return script;\r\n                }\r\n                else if(script.timeFlag == 1)\r\n                {\r\n                    return script;\r\n                }\r\n                else\r\n                {\r\n                    Entry.hw.sendQueue['TRANSMIT'] = {};\r\n                    Entry.hw.sendQueue['TRANSMIT'][Entry.MagKinder.array.Mode] = {\r\n                        Mode: mode,\r\n                        Time: new Date().getTime(),\r\n                    };\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n        },\r\n        // endregion MagKinder 맥킨더\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.MagKinder"
  },
  {
    "path": "src/playground/blocks/hardware/block_makermate.js",
    "content": "'use strict';\n\nEntry.makermate = {\n    id: '5B.1',\n    name: 'makermate',\n    url: 'https://makermate.kr/store',\n    imageName: 'makermate.png',\n    title: {\n        ko: '휴몬랩 메이커메이트',\n        en: 'makermate',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.makermate.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                makermate_toggle_on: '켜기',\n                makermate_toggle_off: '끄기',\n\n                // values\n                makermate_get_digital_bool: '디지털 %1 번 센서값',\n                makermate_get_digital_string: '디지털 %1 번 센서 값',\n                makermate_get_analog: '아날로그 %1 번 센서 값',\n                makermate_sonar_read: '초음파 Trig %1 Echo %2 센서 값', // sonar sensor\n                makermate_light_read: '빛감지센서 %1 값',\n                makermate_map_value: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환',\n                makermate_touch_read: '터치센서 %1 를 터치했는가?',\n\n                // default blocks\n                makermate_set_digital: '디지털 %1 핀 %2 %3',\n\n                // rgb led\n                makermate_rgbled_set_color:\n                    'R %4 + G %5 + B %6 색으로 RGB LED 켜기 (R %1 핀, G %2 핀, B %3 핀) %7',\n\n                makermate_rgbled_off: 'RGB LED 끄기 (R %1 핀, G %2 핀, B %3 핀) %4',\n\n                // buzzer\n                makermate_buzzer_on: '%1 핀 부저를 %3 옥타브 %2 음으로 %4 초 연주 %5',\n\n                // servo\n                makermate_servo_set: '%1 핀 서보모터를 %2 각도로 움직이기 %3',\n            },\n        },\n        en: {\n            template: {\n                makermate_toggle_on: 'on',\n                makermate_toggle_off: 'off',\n\n                // values\n                makermate_get_digital_bool: 'Digital %1 Sensor value',\n                makermate_get_digital_string: 'Digital %1 Sensor value',\n                makermate_get_analog: 'Analog %1 Sensor value',\n                makermate_touch_read: 'Touch Sensor %1 value',\n                makermate_sonar_read: 'Ultrasonic Trig %1 Echo %2 pin Sensor value',\n                makermate_light_read: 'Light Sensor %1 value',\n\n                makermate_map_value: 'Map %1 value from %2 ~ %3 range to %4 ~ %5 range',\n\n                // default blocks\n                makermate_set_digital: 'Digital %1 Pin %2 %3',\n\n                // rgbled\n                makermate_rgbled_set_color:\n                    'Turn on RGB LED (R Pin: %1 , G Pin: %2 , B Pin: %3 ) with values R %4, G %5, B %6 %7',\n                makermate_rgbled_off: 'Turn off RGB LED (R %1 핀, G %2 핀, B %3 핀) %4',\n\n                // buzzer\n                makermate_buzzer_on: 'Play buzzer pin %1 on note %2 octave %3 beat %4 %5',\n\n                // servo\n                makermate_servo_set: 'Set servo pin %1 angle as %2 %3',\n            },\n        },\n    };\n};\n\nEntry.makermate.blockMenuBlocks = [\n    // get values\n    'makermate_get_digital_bool', // 디지털 0번 센서값 읽기 (boolean)\n    'makermate_get_digital_string', // 디지털 0번 센서 값 읽기 (string)\n    'makermate_get_analog', // 아날로그 0번 센서 값 읽기 (string)\n    'makermate_sonar_read', // 초음파센서 값 읽기\n    'makermate_touch_read', // 터치센서 값 읽기\n    'makermate_light_read', // 빛감지센서 값 읽기\n    'makermate_map_value', // 값 매핑\n\n    // default\n    'makermate_set_digital', // 디지털 0번 핀 켜기/끄기\n\n    // rgb led\n    'makermate_rgbled_set_color', // rgb led 켜기/끄기\n    'makermate_rgbled_off',\n\n    // buzzer\n    'makermate_buzzer_on', // 부저를 0음 0옥타브로 0초 연주\n\n    // servo\n    'makermate_servo_set', // 서보모터 각도 지정\n];\n\nEntry.makermate.getBlocks = function() {\n    return {\n        makermate_list_digital_pin: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '13',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n\n        makermate_list_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '9',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n\n        makermate_list_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.makermate_toggle_on, 'on'],\n                        [Lang.template.makermate_toggle_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n        },\n\n        makermate_list_analog_pin: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n\n        makermate_list_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n\n        makermate_list_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n\n        /** GET VALUES */\n        makermate_get_digital_bool: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            template: Lang.template.makermate_get_digital_bool,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pin',\n                        params: [5],\n                    },\n                ],\n                type: 'makermate_get_digital_bool',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'makermateValues',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                const port = script.getNumberValue('PORT', script);\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.makermate.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n        },\n\n        makermate_get_digital_string: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.makermate_get_digital_bool,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pin',\n                        params: [5],\n                    },\n                ],\n                type: 'makermate_get_digital_string',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'makermateValues',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                const port = script.getNumberValue('PORT', script);\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.makermate.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n        },\n\n        makermate_get_analog: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_analog_pin',\n                    },\n                ],\n                type: 'makermate_get_analog',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'makermateValues',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n\n        makermate_touch_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pin',\n                        params: [5],\n                    },\n                ],\n                type: 'makermate_touch_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'makermateValues',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                const port = script.getNumberValue('PORT', script);\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.makermate.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n        },\n\n        makermate_light_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_analog_pin',\n                    },\n                ],\n                type: 'makermate_light_read',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'makermateValues',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n\n        makermate_sonar_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.makermate_sonar_read,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pin',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'makermate_list_digital_pin',\n                        params: ['6'],\n                    },\n                ],\n                type: 'makermate_sonar_read',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'makermateValues',\n            isNotFor: ['makermate'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.makermate.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n\n        makermate_map_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['180'],\n                    },\n                ],\n                type: 'makermate_map_value',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'makermateValues',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                var num = script.getNumberValue('NUM', script);\n                var flag = 0;\n\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                var value4_1 = value4;\n                var value5_1 = value5;\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n\n                if (value4 > value5) {\n                    flag = 1;\n                    var swap = value4;\n                    value4_1 = value5;\n                    value5_1 = swap;\n                }\n\n                num -= value2;\n                num = num * ((value5_1 - value4_1) / (value3 - value2));\n\n                if (flag == 1) {\n                    num = value4 - num;\n                    num = Math.min(value4, num);\n                    num = Math.max(value5, num);\n                } else {\n                    num = num + value4;\n                    num = Math.min(value5, num);\n                    num = Math.max(value4, num);\n                }\n\n                return parseInt(num);\n            },\n        },\n\n        /** SET VALUES */\n        // Default Blocks\n        makermate_set_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pin',\n                        params: [13],\n                    },\n                    {\n                        type: 'makermate_list_digital_value',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'makermate_set_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'makermateValues',\n            isNotFor: ['makermate'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.makermate.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.makermate.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.makermate.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n\n        // RGB LED\n        makermate_rgbled_set_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pwm',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'makermate_list_digital_pwm',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'makermate_list_digital_pwm',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'makermate_rgbled_set_color',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n                VALUE1: 3,\n                VALUE2: 4,\n                VALUE3: 5,\n            },\n            class: 'makermateRgbled',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type: Entry.makermate.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type: Entry.makermate.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port3] = {\n                    type: Entry.makermate.sensorTypes.PWM,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n\n        makermate_rgbled_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pwm',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'makermate_list_digital_pwm',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'makermate_list_digital_pwm',\n                        params: ['11'],\n                    },\n                    null,\n                ],\n                type: 'makermate_rgbled_off',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n            },\n            class: 'makermateRgbled',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type: Entry.makermate.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type: Entry.makermate.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][port3] = {\n                    type: Entry.makermate.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n\n        // Buzzer\n        makermate_buzzer_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.makermate_buzzer_on,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pin',\n                        params: [13],\n                    },\n                    {\n                        type: 'makermate_list_tone',\n                    },\n                    {\n                        type: 'makermate_list_octave',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'makermate_buzzer_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'makermateBuzzer',\n            isNotFor: ['makermate'],\n            func: function(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.makermate.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.makermate.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 8) {\n                        octave = 8;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.makermate.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.makermate.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.makermate.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        // Servo\n        makermate_servo_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: Lang.template.makermate_servo_set,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'makermate_list_digital_pin',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['180'],\n                    },\n                    null,\n                ],\n                type: 'makermate_servo_set',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'makermateServo',\n            isNotFor: ['makermate'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n\n                sq.SET[port] = {\n                    type: Entry.makermate.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.makermate;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_mechanicblock_controller.js",
    "content": "'use strict';\r\n\r\nEntry.MechanicblockController = {\r\n    id: '39.1',\r\n    name: 'MechanicblockController',\r\n    url: 'http://www.mechanicblock.co.kr/',\r\n    imageName: 'mechanicblock_controller.png',\r\n    title: {\r\n        ko: '메카닉블럭 조종기',\r\n        en: 'Mechanicblock Controller',\r\n    },\r\n    setZero() {\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[key].data = 0;\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO_PIN: 4,\r\n        TONE: 5,\r\n        PULSEIN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    highList: ['high', '1', 'on'],\r\n    lowList: ['low', '0', 'off'],\r\n    BlockState: {},\r\n};\r\n\r\nEntry.MechanicblockController.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                mechanicblock_controller_get_analog_value: '아날로그 %1 번 센서값',\r\n                mechanicblock_controller_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\r\n                mechanicblock_controller_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\r\n                mechanicblock_controller_toggle_led: '디지털 %1 번 핀 %2 %3',\r\n                mechanicblock_controller_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\r\n                mechanicblock_controller_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\r\n                mechanicblock_controller_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\r\n                mechanicblock_controller_get_digital: '디지털 %1 번 센서값',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                mechanicblock_controller_get_analog_value: 'Analog %1 Sensor value',\r\n                mechanicblock_controller_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\r\n                mechanicblock_controller_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\r\n                mechanicblock_controller_toggle_led: 'Digital %1 Pin %2 %3',\r\n                mechanicblock_controller_digital_pwm: 'Digital %1 Pin %2 %3',\r\n                mechanicblock_controller_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\r\n                mechanicblock_controller_set_servo: 'Set servo pin %1 angle as %2 %3',\r\n                mechanicblock_controller_get_digital: 'Digital %1 Sensor value',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.MechanicblockController.blockMenuBlocks = [\r\n    'mechanicblock_controller_get_analog_value',\r\n    'mechanicblock_controller_get_analog_value_map',\r\n    'mechanicblock_controller_get_ultrasonic_value',\r\n    'mechanicblock_controller_get_digital',\r\n    'mechanicblock_controller_toggle_led',\r\n    'mechanicblock_controller_digital_pwm',\r\n    'mechanicblock_controller_set_servo',\r\n    'mechanicblock_controller_set_tone',\r\n];\r\n\r\n//region MechanicblockController 아두이노 확장모드\r\nEntry.MechanicblockController.getBlocks = function() {\r\n    return {\r\n        mechanicblock_controller_analog_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A0', '0'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                        ['A3', '3'],\r\n                        ['A4', '4'],\r\n                        ['A5', '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['A0', '0'],\r\n                                    ['A1', '1'],\r\n                                    ['A2', '2'],\r\n                                    ['A3', '3'],\r\n                                    ['A4', '4'],\r\n                                    ['A5', '5'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                codeMap: 'Entry.CodeMap.Arduino.mechanicblock_controller_analog_list[0]',\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'mechanicblock_controller_analog_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_controller_analog_list',\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_controller_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'MechanicblockControllerGet',\r\n            isNotFor: ['MechanicblockController'],\r\n            func(sprite, script) {\r\n                let port = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                if (port[0] === 'A') {\r\n                    port = port.substring(1);\r\n                }\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_get_analog_value_map: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_controller_get_analog_value',\r\n                        params: [\r\n                            {\r\n                                type: 'mechanicblock_controller_analog_list',\r\n                            },\r\n                        ],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_controller_get_analog_value_map',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'MechanicblockControllerGet',\r\n            isNotFor: ['MechanicblockController'],\r\n            func(sprite, script) {\r\n                let result = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                const stringValue4 = script.getValue('VALUE4', script);\r\n                const stringValue5 = script.getValue('VALUE5', script);\r\n                let isFloat = false;\r\n\r\n                if (\r\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\r\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\r\n                ) {\r\n                    isFloat = true;\r\n                }\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                if (isFloat) {\r\n                    result = Math.round(result * 100) / 100;\r\n                } else {\r\n                    result = Math.round(result);\r\n                }\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_get_ultrasonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['4'],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_controller_get_ultrasonic_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'MechanicblockControllerGet',\r\n            isNotFor: ['MechanicblockController'],\r\n            func(sprite, script) {\r\n                const port1 = script.getNumberValue('PORT1', script);\r\n                const port2 = script.getNumberValue('PORT2', script);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[port1];\r\n                delete Entry.hw.sendQueue.SET[port2];\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.MechanicblockController.sensorTypes.ULTRASONIC] = {\r\n                    port: [port1, port2],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.ULTRASONIC || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [2],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_controller_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'MechanicblockControllerGet',\r\n            isNotFor: ['MechanicblockController'],\r\n            func(sprite, script) {\r\n                const { hwModule = {} } = Entry.hw;\r\n                const { name } = hwModule;\r\n                if (name === 'MechanicblockController') {\r\n                    const port = script.getNumberValue('PORT', script);\r\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                    if (!Entry.hw.sendQueue.GET) {\r\n                        Entry.hw.sendQueue.GET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.GET[Entry.MechanicblockController.sensorTypes.DIGITAL] = {\r\n                        port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n                } else {\r\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_toggle_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_digital_toggle',\r\n                        params: ['on'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_controller_toggle_led',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockController',\r\n            isNotFor: ['MechanicblockController'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.MechanicblockController.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.MechanicblockController.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.MechanicblockController.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_pwm_port_number',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_controller_digital_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockController',\r\n            isNotFor: ['MechanicblockController'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.MechanicblockController.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_tone_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.silent, '0'],\r\n                                    [Lang.Blocks.do_name, 'C'],\r\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\r\n                                    [Lang.Blocks.re_name, 'D'],\r\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\r\n                                    [Lang.Blocks.mi_name, 'E'],\r\n                                    [Lang.Blocks.fa_name, 'F'],\r\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                                    [Lang.Blocks.sol_name, 'G'],\r\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                                    [Lang.Blocks.la_name, 'A'],\r\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\r\n                                    [Lang.Blocks.si_name, 'B'],\r\n                                ],\r\n                                value: 'C',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'mechanicblock_controller_tone_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_tone_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_controller_tone_list',\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_controller_tone_value',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getNumberValue('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'mechanicblock_controller_tone_value',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_octave_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'mechanicblock_controller_octave_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_set_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'mechanicblock_controller_tone_list',\r\n                    },\r\n                    {\r\n                        type: 'mechanicblock_controller_octave_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_controller_set_tone',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NOTE: 1,\r\n                OCTAVE: 2,\r\n                DURATION: 3,\r\n            },\r\n            class: 'MechanicblockController',\r\n            isNotFor: ['MechanicblockController'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n\r\n                if (!script.isStart) {\r\n                    let note = script.getValue('NOTE', script);\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.MechanicblockController.toneTable[note];\r\n                    }\r\n\r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    } else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n\r\n                    let duration = script.getNumberValue('DURATION', script);\r\n\r\n                    if (duration < 0) {\r\n                        duration = 0;\r\n                    }\r\n\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n\r\n                    if (duration === 0) {\r\n                        sq.SET[port] = {\r\n                            type: Entry.MechanicblockController.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n\r\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    } else if (octave > 5) {\r\n                        octave = 5;\r\n                    }\r\n\r\n                    let value = 0;\r\n\r\n                    if (note != 0) {\r\n                        value = Entry.MechanicblockController.toneMap[note][octave];\r\n                    }\r\n\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    sq.SET[port] = {\r\n                        type: Entry.MechanicblockController.sensorTypes.TONE,\r\n                        data: {\r\n                            value,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    sq.SET[port] = {\r\n                        type: Entry.MechanicblockController.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_controller_set_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_controller_set_servo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'ArduMechanicblockControllerinoExt',\r\n            isNotFor: ['MechanicblockController'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                let value = script.getNumberValue('VALUE', script);\r\n                value = Math.min(180, value);\r\n                value = Math.max(0, value);\r\n\r\n                if (!sq.SET) {\r\n                    sq.SET = {};\r\n                }\r\n                sq.SET[port] = {\r\n                    type: Entry.MechanicblockController.sensorTypes.SERVO_PIN,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n    };\r\n};\r\n//endregion MechanicblockController 아두이노 확장모드\r\n\r\nmodule.exports = Entry.MechanicblockController;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_mechanicblock_uno.js",
    "content": "'use strict';\r\n\r\nEntry.MechanicblockUno = {\r\n    id: '39.3',\r\n    name: 'MechanicblockUno',\r\n    url: 'http://www.mechanicblock.co.kr/',\r\n    imageName: 'mechanicblock_uno.png',\r\n    title: {\r\n        ko: '메카닉블럭 Uno',\r\n        en: 'Mechanicblock Uno',\r\n    },\r\n    setZero() {\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[key].data = 0;\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO_PIN: 4,\r\n        TONE: 5,\r\n        PULSEIN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    highList: ['high', '1', 'on'],\r\n    lowList: ['low', '0', 'off'],\r\n    BlockState: {},\r\n};\r\n\r\nEntry.MechanicblockUno.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                mechanicblock_uno_get_analog_value: '아날로그 %1 번 센서값',\r\n                mechanicblock_uno_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\r\n                mechanicblock_uno_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\r\n                mechanicblock_uno_toggle_led: '디지털 %1 번 핀 %2 %3',\r\n                mechanicblock_uno_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\r\n                mechanicblock_uno_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\r\n                mechanicblock_uno_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\r\n                mechanicblock_uno_get_digital: '디지털 %1 번 센서값',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                mechanicblock_uno_get_analog_value: 'Analog %1 Sensor value',\r\n                mechanicblock_uno_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\r\n                mechanicblock_uno_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\r\n                mechanicblock_uno_toggle_led: 'Digital %1 Pin %2 %3',\r\n                mechanicblock_uno_digital_pwm: 'Digital %1 Pin %2 %3',\r\n                mechanicblock_uno_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\r\n                mechanicblock_uno_set_servo: 'Set servo pin %1 angle as %2 %3',\r\n                mechanicblock_uno_get_digital: 'Digital %1 Sensor value',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.MechanicblockUno.blockMenuBlocks = [\r\n    'mechanicblock_uno_get_analog_value',\r\n    'mechanicblock_uno_get_analog_value_map',\r\n    'mechanicblock_uno_get_ultrasonic_value',\r\n    'mechanicblock_uno_get_digital',\r\n    'mechanicblock_uno_toggle_led',\r\n    'mechanicblock_uno_digital_pwm',\r\n    'mechanicblock_uno_set_servo',\r\n    'mechanicblock_uno_set_tone',\r\n];\r\n\r\n//region MechanicblockUno 아두이노 확장모드\r\nEntry.MechanicblockUno.getBlocks = function() {\r\n    return {\r\n        mechanicblock_uno_analog_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A0', '0'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                        ['A3', '3'],\r\n                        ['A4', '4'],\r\n                        ['A5', '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['A0', '0'],\r\n                                    ['A1', '1'],\r\n                                    ['A2', '2'],\r\n                                    ['A3', '3'],\r\n                                    ['A4', '4'],\r\n                                    ['A5', '5'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                codeMap: 'Entry.CodeMap.Arduino.mechanicblock_uno_analog_list[0]',\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'mechanicblock_uno_analog_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_analog_list',\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'MechanicblockUnoGet',\r\n            isNotFor: ['MechanicblockUno'],\r\n            func(sprite, script) {\r\n                let port = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                if (port[0] === 'A') {\r\n                    port = port.substring(1);\r\n                }\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_get_analog_value_map: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_get_analog_value',\r\n                        params: [\r\n                            {\r\n                                type: 'mechanicblock_uno_analog_list',\r\n                            },\r\n                        ],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_get_analog_value_map',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'MechanicblockUnoGet',\r\n            isNotFor: ['MechanicblockUno'],\r\n            func(sprite, script) {\r\n                let result = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                const stringValue4 = script.getValue('VALUE4', script);\r\n                const stringValue5 = script.getValue('VALUE5', script);\r\n                let isFloat = false;\r\n\r\n                if (\r\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\r\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\r\n                ) {\r\n                    isFloat = true;\r\n                }\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                if (isFloat) {\r\n                    result = Math.round(result * 100) / 100;\r\n                } else {\r\n                    result = Math.round(result);\r\n                }\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_get_ultrasonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['4'],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_get_ultrasonic_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'MechanicblockUnoGet',\r\n            isNotFor: ['MechanicblockUno'],\r\n            func(sprite, script) {\r\n                const port1 = script.getNumberValue('PORT1', script);\r\n                const port2 = script.getNumberValue('PORT2', script);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[port1];\r\n                delete Entry.hw.sendQueue.SET[port2];\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.MechanicblockUno.sensorTypes.ULTRASONIC] = {\r\n                    port: [port1, port2],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.ULTRASONIC || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [2],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'MechanicblockUnoGet',\r\n            isNotFor: ['MechanicblockUno'],\r\n            func(sprite, script) {\r\n                const { hwModule = {} } = Entry.hw;\r\n                const { name } = hwModule;\r\n                if (name === 'MechanicblockUno') {\r\n                    const port = script.getNumberValue('PORT', script);\r\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                    if (!Entry.hw.sendQueue.GET) {\r\n                        Entry.hw.sendQueue.GET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.GET[Entry.MechanicblockUno.sensorTypes.DIGITAL] = {\r\n                        port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n                } else {\r\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_toggle_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_digital_toggle',\r\n                        params: ['on'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_toggle_led',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockUno',\r\n            isNotFor: ['MechanicblockUno'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.MechanicblockUno.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.MechanicblockUno.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.MechanicblockUno.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_pwm_port_number',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_digital_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockUno',\r\n            isNotFor: ['MechanicblockUno'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.MechanicblockUno.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_tone_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.silent, '0'],\r\n                                    [Lang.Blocks.do_name, 'C'],\r\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\r\n                                    [Lang.Blocks.re_name, 'D'],\r\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\r\n                                    [Lang.Blocks.mi_name, 'E'],\r\n                                    [Lang.Blocks.fa_name, 'F'],\r\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                                    [Lang.Blocks.sol_name, 'G'],\r\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                                    [Lang.Blocks.la_name, 'A'],\r\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\r\n                                    [Lang.Blocks.si_name, 'B'],\r\n                                ],\r\n                                value: 'C',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'mechanicblock_uno_tone_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_tone_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_tone_list',\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_tone_value',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getNumberValue('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'mechanicblock_uno_tone_value',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_octave_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'mechanicblock_uno_octave_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_set_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'mechanicblock_uno_tone_list',\r\n                    },\r\n                    {\r\n                        type: 'mechanicblock_uno_octave_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_set_tone',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NOTE: 1,\r\n                OCTAVE: 2,\r\n                DURATION: 3,\r\n            },\r\n            class: 'MechanicblockUno',\r\n            isNotFor: ['MechanicblockUno'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n\r\n                if (!script.isStart) {\r\n                    let note = script.getValue('NOTE', script);\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.MechanicblockUno.toneTable[note];\r\n                    }\r\n\r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    } else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n\r\n                    let duration = script.getNumberValue('DURATION', script);\r\n\r\n                    if (duration < 0) {\r\n                        duration = 0;\r\n                    }\r\n\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n\r\n                    if (duration === 0) {\r\n                        sq.SET[port] = {\r\n                            type: Entry.MechanicblockUno.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n\r\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    } else if (octave > 5) {\r\n                        octave = 5;\r\n                    }\r\n\r\n                    let value = 0;\r\n\r\n                    if (note != 0) {\r\n                        value = Entry.MechanicblockUno.toneMap[note][octave];\r\n                    }\r\n\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    sq.SET[port] = {\r\n                        type: Entry.MechanicblockUno.sensorTypes.TONE,\r\n                        data: {\r\n                            value,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    sq.SET[port] = {\r\n                        type: Entry.MechanicblockUno.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_set_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_set_servo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'ArduMechanicblockUnoinoExt',\r\n            isNotFor: ['MechanicblockUno'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                let value = script.getNumberValue('VALUE', script);\r\n                value = Math.min(180, value);\r\n                value = Math.max(0, value);\r\n\r\n                if (!sq.SET) {\r\n                    sq.SET = {};\r\n                }\r\n                sq.SET[port] = {\r\n                    type: Entry.MechanicblockUno.sensorTypes.SERVO_PIN,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n    };\r\n};\r\n//endregion MechanicblockUno 아두이노 확장모드\r\n\r\nmodule.exports = Entry.MechanicblockUno;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_mechanicblock_uno_mini.js",
    "content": "'use strict';\r\n\r\nEntry.MechanicblockUnoMini = {\r\n    id: '39.4',\r\n    name: 'MechanicblockUnoMini',\r\n    url: 'http://www.mechanicblock.co.kr/',\r\n    imageName: 'mechanicblock_uno_mini.png',\r\n    title: {\r\n        ko: '메카닉블럭 Uno Mini',\r\n        en: 'Mechanicblock Uno Mini',\r\n    },\r\n    setZero() {\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[key].data = 0;\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO_PIN: 4,\r\n        TONE: 5,\r\n        PULSEIN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    highList: ['high', '1', 'on'],\r\n    lowList: ['low', '0', 'off'],\r\n    BlockState: {},\r\n};\r\n\r\nEntry.MechanicblockUnoMini.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                mechanicblock_uno_mini_get_analog_value: '아날로그 %1 번 센서값',\r\n                mechanicblock_uno_mini_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\r\n                mechanicblock_uno_mini_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\r\n                mechanicblock_uno_mini_toggle_led: '디지털 %1 번 핀 %2 %3',\r\n                mechanicblock_uno_mini_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\r\n                mechanicblock_uno_mini_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\r\n                mechanicblock_uno_mini_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\r\n                mechanicblock_uno_mini_get_digital: '디지털 %1 번 센서값',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                mechanicblock_uno_mini_get_analog_value: 'Analog %1 Sensor value',\r\n                mechanicblock_uno_mini_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\r\n                mechanicblock_uno_mini_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\r\n                mechanicblock_uno_mini_toggle_led: 'Digital %1 Pin %2 %3',\r\n                mechanicblock_uno_mini_digital_pwm: 'Digital %1 Pin %2 %3',\r\n                mechanicblock_uno_mini_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\r\n                mechanicblock_uno_mini_set_servo: 'Set servo pin %1 angle as %2 %3',\r\n                mechanicblock_uno_mini_get_digital: 'Digital %1 Sensor value',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.MechanicblockUnoMini.blockMenuBlocks = [\r\n    'mechanicblock_uno_mini_get_analog_value',\r\n    'mechanicblock_uno_mini_get_analog_value_map',\r\n    'mechanicblock_uno_mini_get_ultrasonic_value',\r\n    'mechanicblock_uno_mini_get_digital',\r\n    'mechanicblock_uno_mini_toggle_led',\r\n    'mechanicblock_uno_mini_digital_pwm',\r\n    'mechanicblock_uno_mini_set_servo',\r\n    'mechanicblock_uno_mini_set_tone',\r\n];\r\n\r\n//region MechanicblockUnoMini 아두이노 확장모드\r\nEntry.MechanicblockUnoMini.getBlocks = function() {\r\n    return {\r\n        mechanicblock_uno_mini_analog_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A0', '0'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                        ['A3', '3'],\r\n                        ['A4', '4'],\r\n                        ['A5', '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['A0', '0'],\r\n                                    ['A1', '1'],\r\n                                    ['A2', '2'],\r\n                                    ['A3', '3'],\r\n                                    ['A4', '4'],\r\n                                    ['A5', '5'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                codeMap: 'Entry.CodeMap.Arduino.mechanicblock_uno_mini_analog_list[0]',\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'mechanicblock_uno_mini_analog_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_mini_analog_list',\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_mini_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'MechanicblockUnoMiniGet',\r\n            isNotFor: ['MechanicblockUnoMini'],\r\n            func(sprite, script) {\r\n                let port = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                if (port[0] === 'A') {\r\n                    port = port.substring(1);\r\n                }\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_get_analog_value_map: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_mini_get_analog_value',\r\n                        params: [\r\n                            {\r\n                                type: 'mechanicblock_uno_mini_analog_list',\r\n                            },\r\n                        ],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_mini_get_analog_value_map',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'MechanicblockUnoMiniGet',\r\n            isNotFor: ['MechanicblockUnoMini'],\r\n            func(sprite, script) {\r\n                let result = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                const stringValue4 = script.getValue('VALUE4', script);\r\n                const stringValue5 = script.getValue('VALUE5', script);\r\n                let isFloat = false;\r\n\r\n                if (\r\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\r\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\r\n                ) {\r\n                    isFloat = true;\r\n                }\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                if (isFloat) {\r\n                    result = Math.round(result * 100) / 100;\r\n                } else {\r\n                    result = Math.round(result);\r\n                }\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_get_ultrasonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['4'],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_mini_get_ultrasonic_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'MechanicblockUnoMiniGet',\r\n            isNotFor: ['MechanicblockUnoMini'],\r\n            func(sprite, script) {\r\n                const port1 = script.getNumberValue('PORT1', script);\r\n                const port2 = script.getNumberValue('PORT2', script);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[port1];\r\n                delete Entry.hw.sendQueue.SET[port2];\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.MechanicblockUnoMini.sensorTypes.ULTRASONIC] = {\r\n                    port: [port1, port2],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.ULTRASONIC || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [2],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_mini_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'MechanicblockUnoMiniGet',\r\n            isNotFor: ['MechanicblockUnoMini'],\r\n            func(sprite, script) {\r\n                const { hwModule = {} } = Entry.hw;\r\n                const { name } = hwModule;\r\n                if (name === 'MechanicblockUnoMini' || name === 'ArduinoNano') {\r\n                    const port = script.getNumberValue('PORT', script);\r\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                    if (!Entry.hw.sendQueue.GET) {\r\n                        Entry.hw.sendQueue.GET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.GET[Entry.MechanicblockUnoMini.sensorTypes.DIGITAL] = {\r\n                        port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n                } else {\r\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_toggle_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_digital_toggle',\r\n                        params: ['on'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_mini_toggle_led',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockUnoMini',\r\n            isNotFor: ['MechanicblockUnoMini'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.MechanicblockUnoMini.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.MechanicblockUnoMini.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.MechanicblockUnoMini.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_pwm_port_number',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_mini_digital_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockUnoMini',\r\n            isNotFor: ['MechanicblockUnoMini'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.MechanicblockUnoMini.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_tone_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.silent, '0'],\r\n                                    [Lang.Blocks.do_name, 'C'],\r\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\r\n                                    [Lang.Blocks.re_name, 'D'],\r\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\r\n                                    [Lang.Blocks.mi_name, 'E'],\r\n                                    [Lang.Blocks.fa_name, 'F'],\r\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                                    [Lang.Blocks.sol_name, 'G'],\r\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                                    [Lang.Blocks.la_name, 'A'],\r\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\r\n                                    [Lang.Blocks.si_name, 'B'],\r\n                                ],\r\n                                value: 'C',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'mechanicblock_uno_mini_tone_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_tone_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_mini_tone_list',\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_mini_tone_value',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getNumberValue('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'mechanicblock_uno_mini_tone_value',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_octave_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'mechanicblock_uno_mini_octave_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_set_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'mechanicblock_uno_mini_tone_list',\r\n                    },\r\n                    {\r\n                        type: 'mechanicblock_uno_mini_octave_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_mini_set_tone',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NOTE: 1,\r\n                OCTAVE: 2,\r\n                DURATION: 3,\r\n            },\r\n            class: 'MechanicblockUnoMini',\r\n            isNotFor: ['MechanicblockUnoMini'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n\r\n                if (!script.isStart) {\r\n                    let note = script.getValue('NOTE', script);\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.MechanicblockUnoMini.toneTable[note];\r\n                    }\r\n\r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    } else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n\r\n                    let duration = script.getNumberValue('DURATION', script);\r\n\r\n                    if (duration < 0) {\r\n                        duration = 0;\r\n                    }\r\n\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n\r\n                    if (duration === 0) {\r\n                        sq.SET[port] = {\r\n                            type: Entry.MechanicblockUnoMini.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n\r\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    } else if (octave > 5) {\r\n                        octave = 5;\r\n                    }\r\n\r\n                    let value = 0;\r\n\r\n                    if (note != 0) {\r\n                        value = Entry.MechanicblockUnoMini.toneMap[note][octave];\r\n                    }\r\n\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    sq.SET[port] = {\r\n                        type: Entry.MechanicblockUnoMini.sensorTypes.TONE,\r\n                        data: {\r\n                            value,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    sq.SET[port] = {\r\n                        type: Entry.MechanicblockUnoMini.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_mini_set_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_mini_set_servo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockUnoMini',\r\n            isNotFor: ['MechanicblockUnoMini'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                let value = script.getNumberValue('VALUE', script);\r\n                value = Math.min(180, value);\r\n                value = Math.max(0, value);\r\n\r\n                if (!sq.SET) {\r\n                    sq.SET = {};\r\n                }\r\n                sq.SET[port] = {\r\n                    type: Entry.MechanicblockUnoMini.sensorTypes.SERVO_PIN,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n    };\r\n};\r\n//endregion MechanicblockUnoMini 아두이노 확장모드\r\n\r\nmodule.exports = Entry.MechanicblockUnoMini;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_mechanicblock_uno_s.js",
    "content": "'use strict';\r\n\r\nEntry.MechanicblockUnoS = {\r\n    id: '39.2',\r\n    name: 'MechanicblockUnoS',\r\n    url: 'http://www.mechanicblock.co.kr/',\r\n    imageName: 'mechanicblock_uno_s.png',\r\n    title: {\r\n        ko: '메카닉블럭 Uno S',\r\n        en: 'Mechanicblock Uno S',\r\n    },\r\n    setZero() {\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[key].data = 0;\r\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        PWM: 3,\r\n        SERVO_PIN: 4,\r\n        TONE: 5,\r\n        PULSEIN: 6,\r\n        ULTRASONIC: 7,\r\n        TIMER: 8,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    highList: ['high', '1', 'on'],\r\n    lowList: ['low', '0', 'off'],\r\n    BlockState: {},\r\n};\r\n\r\nEntry.MechanicblockUnoS.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                mechanicblock_uno_s_get_analog_value: '아날로그 %1 번 센서값',\r\n                mechanicblock_uno_s_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\r\n                mechanicblock_uno_s_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\r\n                mechanicblock_uno_s_toggle_led: '디지털 %1 번 핀 %2 %3',\r\n                mechanicblock_uno_s_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\r\n                mechanicblock_uno_s_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\r\n                mechanicblock_uno_s_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\r\n                mechanicblock_uno_s_get_digital: '디지털 %1 번 센서값',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                mechanicblock_uno_s_get_analog_value: 'Analog %1 Sensor value',\r\n                mechanicblock_uno_s_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\r\n                mechanicblock_uno_s_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\r\n                mechanicblock_uno_s_toggle_led: 'Digital %1 Pin %2 %3',\r\n                mechanicblock_uno_s_digital_pwm: 'Digital %1 Pin %2 %3',\r\n                mechanicblock_uno_s_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\r\n                mechanicblock_uno_s_set_servo: 'Set servo pin %1 angle as %2 %3',\r\n                mechanicblock_uno_s_get_digital: 'Digital %1 Sensor value',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.MechanicblockUnoS.blockMenuBlocks = [\r\n    'mechanicblock_uno_s_get_analog_value',\r\n    'mechanicblock_uno_s_get_analog_value_map',\r\n    'mechanicblock_uno_s_get_ultrasonic_value',\r\n    'mechanicblock_uno_s_get_digital',\r\n    'mechanicblock_uno_s_toggle_led',\r\n    'mechanicblock_uno_s_digital_pwm',\r\n    'mechanicblock_uno_s_set_servo',\r\n    'mechanicblock_uno_s_set_tone',\r\n];\r\n\r\n//region MechanicblockUnoS 아두이노 확장모드\r\nEntry.MechanicblockUnoS.getBlocks = function() {\r\n    return {\r\n        mechanicblock_uno_s_analog_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A0', '0'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                        ['A3', '3'],\r\n                        ['A4', '4'],\r\n                        ['A5', '5'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['A0', '0'],\r\n                                    ['A1', '1'],\r\n                                    ['A2', '2'],\r\n                                    ['A3', '3'],\r\n                                    ['A4', '4'],\r\n                                    ['A5', '5'],\r\n                                ],\r\n                                value: '0',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                codeMap: 'Entry.CodeMap.Arduino.mechanicblock_uno_s_analog_list[0]',\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'mechanicblock_uno_s_analog_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_s_analog_list',\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_s_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'MechanicblockUnoSGet',\r\n            isNotFor: ['MechanicblockUnoS'],\r\n            func(sprite, script) {\r\n                let port = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                if (port[0] === 'A') {\r\n                    port = port.substring(1);\r\n                }\r\n                return ANALOG ? ANALOG[port] || 0 : 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_get_analog_value_map: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_s_get_analog_value',\r\n                        params: [\r\n                            {\r\n                                type: 'mechanicblock_uno_s_analog_list',\r\n                            },\r\n                        ],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_s_get_analog_value_map',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'MechanicblockUnoSGet',\r\n            isNotFor: ['MechanicblockUnoS'],\r\n            func(sprite, script) {\r\n                let result = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                const stringValue4 = script.getValue('VALUE4', script);\r\n                const stringValue5 = script.getValue('VALUE5', script);\r\n                let isFloat = false;\r\n\r\n                if (\r\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\r\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\r\n                ) {\r\n                    isFloat = true;\r\n                }\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                if (isFloat) {\r\n                    result = Math.round(result * 100) / 100;\r\n                } else {\r\n                    result = Math.round(result);\r\n                }\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_get_ultrasonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['4'],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_s_get_ultrasonic_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT1: 0,\r\n                PORT2: 1,\r\n            },\r\n            class: 'MechanicblockUnoSGet',\r\n            isNotFor: ['MechanicblockUnoS'],\r\n            func(sprite, script) {\r\n                const port1 = script.getNumberValue('PORT1', script);\r\n                const port2 = script.getNumberValue('PORT2', script);\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                delete Entry.hw.sendQueue.SET[port1];\r\n                delete Entry.hw.sendQueue.SET[port2];\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.MechanicblockUnoS.sensorTypes.ULTRASONIC] = {\r\n                    port: [port1, port2],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return Entry.hw.portData.ULTRASONIC || 0;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [2],\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_s_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'MechanicblockUnoSGet',\r\n            isNotFor: ['MechanicblockUnoS'],\r\n            func(sprite, script) {\r\n                const { hwModule = {} } = Entry.hw;\r\n                const { name } = hwModule;\r\n                if (name === 'MechanicblockUnoS' || name === 'ArduinoNano') {\r\n                    const port = script.getNumberValue('PORT', script);\r\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\r\n                    if (!Entry.hw.sendQueue.GET) {\r\n                        Entry.hw.sendQueue.GET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.GET[Entry.MechanicblockUnoS.sensorTypes.DIGITAL] = {\r\n                        port,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\r\n                } else {\r\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_toggle_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'arduino_get_digital_toggle',\r\n                        params: ['on'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_s_toggle_led',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockUnoS',\r\n            isNotFor: ['MechanicblockUnoS'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getValue('VALUE');\r\n\r\n                if (typeof value === 'string') {\r\n                    value = value.toLowerCase();\r\n                }\r\n                if (Entry.MechanicblockUnoS.highList.indexOf(value) > -1) {\r\n                    value = 255;\r\n                } else if (Entry.MechanicblockUnoS.lowList.indexOf(value) > -1) {\r\n                    value = 0;\r\n                } else {\r\n                    throw new Error();\r\n                }\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.MechanicblockUnoS.sensorTypes.DIGITAL,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_pwm_port_number',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_s_digital_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockUnoS',\r\n            isNotFor: ['MechanicblockUnoS'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.MechanicblockUnoS.sensorTypes.PWM,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.analogWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_tone_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.silent, '0'],\r\n                                    [Lang.Blocks.do_name, 'C'],\r\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\r\n                                    [Lang.Blocks.re_name, 'D'],\r\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\r\n                                    [Lang.Blocks.mi_name, 'E'],\r\n                                    [Lang.Blocks.fa_name, 'F'],\r\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                                    [Lang.Blocks.sol_name, 'G'],\r\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                                    [Lang.Blocks.la_name, 'A'],\r\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\r\n                                    [Lang.Blocks.si_name, 'B'],\r\n                                ],\r\n                                value: 'C',\r\n                                fontSize: 11,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'mechanicblock_uno_s_tone_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_tone_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'mechanicblock_uno_s_tone_list',\r\n                    },\r\n                ],\r\n                type: 'mechanicblock_uno_s_tone_value',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getNumberValue('NOTE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'mechanicblock_uno_s_tone_value',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_octave_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('OCTAVE');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        keyOption: 'mechanicblock_uno_s_octave_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_set_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: [3],\r\n                    },\r\n                    {\r\n                        type: 'mechanicblock_uno_s_tone_list',\r\n                    },\r\n                    {\r\n                        type: 'mechanicblock_uno_s_octave_list',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_s_set_tone',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                NOTE: 1,\r\n                OCTAVE: 2,\r\n                DURATION: 3,\r\n            },\r\n            class: 'MechanicblockUnoS',\r\n            isNotFor: ['MechanicblockUnoS'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n\r\n                if (!script.isStart) {\r\n                    let note = script.getValue('NOTE', script);\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.MechanicblockUnoS.toneTable[note];\r\n                    }\r\n\r\n                    if (note < 0) {\r\n                        note = 0;\r\n                    } else if (note > 12) {\r\n                        note = 12;\r\n                    }\r\n\r\n                    let duration = script.getNumberValue('DURATION', script);\r\n\r\n                    if (duration < 0) {\r\n                        duration = 0;\r\n                    }\r\n\r\n                    if (!sq.SET) {\r\n                        sq.SET = {};\r\n                    }\r\n\r\n                    if (duration === 0) {\r\n                        sq.SET[port] = {\r\n                            type: Entry.MechanicblockUnoS.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n\r\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\r\n                    if (octave < 0) {\r\n                        octave = 0;\r\n                    } else if (octave > 5) {\r\n                        octave = 5;\r\n                    }\r\n\r\n                    let value = 0;\r\n\r\n                    if (note != 0) {\r\n                        value = Entry.MechanicblockUnoS.toneMap[note][octave];\r\n                    }\r\n\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    sq.SET[port] = {\r\n                        type: Entry.MechanicblockUnoS.sensorTypes.TONE,\r\n                        data: {\r\n                            value,\r\n                            duration,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    sq.SET[port] = {\r\n                        type: Entry.MechanicblockUnoS.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        mechanicblock_uno_s_set_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'arduino_get_port_number',\r\n                        params: ['3'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'mechanicblock_uno_s_set_servo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'MechanicblockUnoS',\r\n            isNotFor: ['MechanicblockUnoS'],\r\n            func(sprite, script) {\r\n                const sq = Entry.hw.sendQueue;\r\n                const port = script.getNumberValue('PORT', script);\r\n                let value = script.getNumberValue('VALUE', script);\r\n                value = Math.min(180, value);\r\n                value = Math.max(0, value);\r\n\r\n                if (!sq.SET) {\r\n                    sq.SET = {};\r\n                }\r\n                sq.SET[port] = {\r\n                    type: Entry.MechanicblockUnoS.sensorTypes.SERVO_PIN,\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n    };\r\n};\r\n//endregion MechanicblockUnoS 아두이노 확장모드\r\n\r\nmodule.exports = Entry.MechanicblockUnoS;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_mechatro.js",
    "content": "'use strict';\n\n/*******************************************************\n * 명명 규칙\n *\n * 함수명, 변수명 : 첫 글자 소문자, 다음 단어 첫 글자 대문자, 두단어 이상 조합     예) nameRull\n * 키  값 : 모두 대문자, 단어사이 '_' 사용함                                    예) NAME_RULL\n *\n *********************************************************/\n\nclass mechatro {\n    constructor() {\n        this.id = '1F.1';\n        this.url = 'http://cafe.naver.com/easybread';\n        this.name = 'mechatro';\n        this.imageName = 'mechatro_nano.png';\n        this.title = {\n            ko: '메카트로',\n            en: 'mechatro',\n        };\n\n        this.monitorTemplate = {\n            imgPath: 'hw/transparent.png',\n            width: 500,\n            height: 434,\n            listPorts: {\n                '2': {\n                    name: ` D2 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '4': {\n                    name: ` D4 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '5': {\n                    name: ` D5 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '6': {\n                    name: ` D6 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '7': {\n                    name: ` D7 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '10': {\n                    name: ` D10 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '14': {\n                    name: `MA current`,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '15': {\n                    name: ` MB current `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '16': {\n                    name: ` A2 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '17': {\n                    name: ` A3 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '18': {\n                    name: ` A4 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '19': {\n                    name: ` A5 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '20': {\n                    name: ` A6 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                '21': {\n                    name: ` A7 `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n                com: {\n                    name: ` inform `,\n                    type: 'input',\n                    pos: { x: 0, y: 0 },\n                },\n            },\n            mode: 'both',\n        };\n\n        this.portMode = {\n            SET_GROUP_1: 0x80,\n            SET_INIT_DEVICE: 0x80,\n            SET_DIGITAL_OUT: 0x81,\n            SET_NO_TONE: 0x82,\n            SET_PORT_DISABLE: 0x86,\n            SET_BLUE_PW: 0x87,\n\n            SET_ALL_SERVO_RUNTIME: 0x88,\n            SET_MOTOR_CURRENT: 0x8A,\n            SET_MOTOR_CURRENT_A: 0x8A,\n            SET_MOTOR_CURRENT_B: 0X8B,\n\n            SET_MOTOR_SPEED_Free: 0x90,\n            SET_MOTOR_SPEED_Fast: 0x94,\n\n            SET_TONE: 0x98,\n            SET_PWM: 0x9C,\n\n            SET_GROUP_2: 0xA0,\n            SET_SERVO_POSITION: 0xA0,\n\n            SET_GROUP_3: 0xC0,\n            SET_SERVO_SPEED: 0xC0,\n            SET_SERVO_RUNTIME: 0xD0,\n\n            SET_GROUP_INPUT: 0xE0,\n            SET_ANALOG_IN: 0xE0,\n            SET_ULTRASONIC: 0xE8,\n            SET_DIGITAL_IN: 0xF0,\n        };\n\n        this.prev_sensor_data = { '2': 0, '4': 0, '5': 0, '6': 0, '7': 0, '10': 0 };\n        this.tonePin = 0;\n\n        this.eventState = {\n            FALLING: {\n                '2': false,\n                '4': false,\n                '5': false,\n                '6': false,\n                '7': false,\n                '10': false,\n                TRIGGER: false,\n            },\n            RISING: {\n                '2': false,\n                '4': false,\n                '5': false,\n                '6': false,\n                '7': false,\n                '10': false,\n                TRIGGER: false,\n            },\n            ENABLE: { '2': true, '4': true, '5': true, '6': true, '7': true, '10': true },\n        };\n\n        // 순서에 따라 화면에 보임\n        this.blockMenuBlocks = [\n            'mechatro_event_rising_falling',  // Add 2020-07-04\n            'mechatro_get_digital',\n            'mechatro_get_analog_judgement',  // Add 2022-05-22\n            'mechatro_get_sensor_value',\n            'mechatro_get_dc_motor_current',\n            'mechatro_get_ultrasonic_value',\n            'mechatro_get_temperature',\n            'mechatro_set_get_sensor_value_map',\n            'mechatro_set_digital',\n            'mechatro_set_pwm',\n            'mechatro_set_tone',\n            'mechatro_set_tone_time',\n            'mechatro_set_dc_motor',\n            'mechatro_set_servo_position',\n            'mechatro_set_servo_positions',\n            //'mechatro_set_servo_speed',\n            'mechatro_set_blue_pw',\n        ];\n    }\n    setLanguage() {\n        return {\n            ko: {\n                // ko.js에 작성하던 내용\n                template: {\n                    mechatro_event_rising_falling: \"%1 %2 이 %3이 될 때\",\n                    mechatro_get_dc_motor_current: \"%1모터 전류값[mA]\",\n                    mechatro_get_digital: \"%1 디지털 값\",\n                    mechatro_get_analog_judgement: \"%1 %2 %3\",\n                    mechatro_get_sensor_value: \"%1 센서값\",\n                    mechatro_set_get_sensor_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                    mechatro_get_ultrasonic_value: \"초음파센서 Trig %1 Echo %2 의 거리값 [cm]\",\n                    mechatro_get_temperature: \"%1 온도 센서 값 (TMP36)\",\n                    mechatro_set_blue_pw: \"블루투스 비밀번호 : %1%2%3%4로 정하기%5\",\n                    mechatro_set_dc_motor: \"%1모터 속도 %2로 정하기%3\",\n                    mechatro_set_digital: \"%1번 %2 %3\",\n                    mechatro_set_pwm: \"%1PWM을 %2%로 정하기 %3\",\n                    mechatro_set_servo_position: \"%1서보모터 %2˚ 까지 1초당 %3˚씩 이동하기 %4\",\n                    mechatro_set_servo_positions: \"서보각도 D2%1 D5%2 D6%3 D10%4 작동시간: %5초\",\n                    //mechatro_set_servo_speed: \"%1서보모터 속도 : 1초당 %2도로 정하기 %3\",\n                    mechatro_set_threshold: \"%1 센서 감도 : %2로 정하기%3\",\n                    mechatro_set_tone: \"%1버저 %2 %3 음으로 연주 %4\",\n                    mechatro_set_tone_time: \"%1버저 %2 %3 음으로 %4 초 연주 %5\",\n                },\n            },\n            en: {\n                // en.js에 작성하던 내용\n                template: {\n                    mechatro_event_rising_falling: \"%1 When %2 is turned %3\",\n                    mechatro_get_dc_motor_current: 'Get 1%motor current',\n                    mechatro_get_digital: '%1',\n                    mechatro_get_analog_judgement: \"%1 %2 %3\",\n                    mechatro_get_sensor_value: 'Analog %1 Sensor value',\n                    mechatro_set_get_sensor_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                    mechatro_get_ultrasonic_value: \"Read ultrasonic sensor trig pin %1 echo pin %2\",\n                    mechatro_get_temperature: \"temperature %1 Sensor (TMP36)\",\n                    mechatro_set_blue_pw: \"Change PW of Bluetooth to %1%2%3%4 %5\",\n                    mechatro_set_dc_motor: \"Set %1 motor speed to %2 %3\",\n                    mechatro_set_digital: \"Digital %1 Pin %2 %3\",\n                    mechatro_set_pwm: \"Digital %1 Pin %2 %3\",\n                    mechatro_set_servo_position: \"Set servo pin %1 angle %2, speed %3[˚/1s] %4\",\n                    mechatro_set_servo_positions: \"%Servo D2%1 D5%2 D6%3 D10%4 time %5\",\n                    //mechatro_set_servo_speed: \"Set servo pin %1 speed %2 degree per second %3\",\n                    mechatro_set_threshold: \"Set %1 threshold : %2%3\",\n                    mechatro_set_tone: \"Play tone pin %1 on note %2 octave %3 %4\",\n                    mechatro_set_tone_time: \"Play tone pin %1 on note %2 octave %3 beat %4 %5\",\n                },\n            },\n        };\n    }\n\n    setZero() {                  // 엔트리 정지 시 하드웨어 초기화 로직\n        Entry.hw.sendQueue = {\n            SEND_DATA: {}, // key 값이 없으면 entry-HW에서 entryJS 정지로 인식\n        };\n        Entry.hw.update(); // 반드시 업데이트 해야 전송됨\n        this.eventState = {\n            FALLING: {\n                '2': false,\n                '4': false,\n                '5': false,\n                '6': false,\n                '7': false,\n                '10': false,\n                TRIGGER: false,\n            },\n            RISING: {\n                '2': false,\n                '4': false,\n                '5': false,\n                '6': false,\n                '7': false,\n                '10': false,\n                TRIGGER: false,\n            },\n            ENABLE: { '2': true, '4': true, '5': true, '6': true, '7': true, '10': true },\n        };\n    }\n\n    afterReceive(pd) {\n        /*\n        if (!Entry.engine.isState('run')) {\n            // 정지시에도 이전값 저장으로 실행하는 순간 발생할 수 있는 이벤트 발생을 금지\n            // ??????????????????????????????????????????????????????????????????????????????????????????\n            // 값이 상시 없데이트 되므로 불필요할 것으로 생각됨, 필요한지 확인필요\n            Object.keys(this.prev_sensor_data).forEach((key) => {\n                this.prev_sensor_data[key] = pd[key];\n            });\n            //console.log(\"afterReceive \", \"run\");\n            return;\n        }\n        else {\n            //console.log(\"afterReceive \", \"stop\");\n        }\n*/\n        Object.keys(this.prev_sensor_data).forEach((key) => {\n            // 이벤트 사용 가능 조사 (초음파, PWM, TONE 아웃풋 포트 이벤트 사용 불가)\n            if (this.eventState.ENABLE[key]) {\n                const new_data = pd[key];\n                if (this.prev_sensor_data[key] ^ new_data) {\n                    if (new_data) {\n                        this.eventState.RISING[key] = true;\n                        this.eventState.RISING.TRIGGER = true;\n                    } else {\n                        this.eventState.FALLING[key] = true;\n                        this.eventState.FALLING.TRIGGER = true;\n                    }\n                }\n                this.prev_sensor_data[key] = new_data;\n            }\n        });\n\n        if (this.eventState.RISING.TRIGGER) {\n            this.eventState.RISING.TRIGGER = false;\n            Entry.engine.fireEvent('event_digital_input');\n        }\n\n        if (this.eventState.FALLING.TRIGGER) {\n            this.eventState.FALLING.TRIGGER = false;\n            Entry.engine.fireEvent('event_digital_input');\n        }\n    }\n\n    //this.SEND_DATA = {\n    //    portNo:{\n    //        mode : 0,\n    //        value: 0,\n    //    },\n    //};\n\n    transferModeValue(portNo, mode, value) {\n        if (Entry.hw.sendQueue.SEND_DATA == undefined) {\n            Entry.hw.sendQueue = {\n                SEND_DATA: {},\n            };\n        }\n        Entry.hw.sendQueue.SEND_DATA[portNo] = {\n            MODE: mode,\n            VALUE: value,\n        };\n    }\n\n    transferMode(portNo, mode) {\n        if (Entry.hw.sendQueue.SEND_DATA == undefined) {\n            Entry.hw.sendQueue = {\n                SEND_DATA: {},\n            };\n        }\n        Entry.hw.sendQueue.SEND_DATA[portNo] = {\n            MODE: mode,\n        };\n    }\n\n    getBlocks() {\n        return {\n            mechatro_event_rising_falling: {  // Digital Low Hit Only, \n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_event',\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D2', '2'],\n                            ['D4', '4'],\n                            ['D5', '5'],\n                            ['D6', '6'],\n                            ['D7', '7'],\n                            ['D10', '10'],\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['참', '1'],\n                            ['거짓', '0'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, '2', '1'],\n                    type: 'mechatro_event_rising_falling',\n                },\n                paramsKeyMap: {\n                    PORT: 1,\n                    EDGE: 2,\n                },\n                class: 'MechatroStart',\n                isNotFor: ['mechatro'],\n                event: 'event_digital_input',\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    const toggle = script.getNumberField('EDGE', script);\n                    if (toggle) {\n                        if (Entry.mechatro.eventState.RISING[portNo]) {\n                            Entry.mechatro.eventState.RISING[portNo] = false;\n                            return script.callReturn();\n                        }\n                    } else {\n                        if (Entry.mechatro.eventState.FALLING[portNo]) {\n                            Entry.mechatro.eventState.FALLING[portNo] = false;\n                            return script.callReturn();\n                        }\n                    }\n                    return this.die();\n                },\n                syntax: { js: [], py: [] },\n            },\n            mechatro_get_digital: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_boolean_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D2', '2'],\n                            ['D4', '4'],\n                            ['D5', '5'],\n                            ['D6', '6'],\n                            ['D7', '7'],\n                            ['D10', '10'],\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'mechatro_get_digital',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                },\n                class: 'MechatroJudgement',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    var portNo = script.getNumberField('PORT', script);\n                    var mode;\n                    var value;\n                    mode = Entry.mechatro.portMode.SET_DIGITAL_IN;\n\n                    Entry.mechatro.transferMode(portNo, mode);\n\n                    if (Entry.hw.portData[portNo] !== undefined) {\n                        value = Entry.hw.portData[portNo];\n                        return value;\n                    } else {\n                        return 0;\n                    }\n                },\n                syntax: { js: [], py: [] },\n            },\n\n            mechatro_get_analog_judgement: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_boolean_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                            ['A6', '20'],\n                            ['A7', '21'],\n                        ],\n                        value: '16',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['=', 'EQUAL'],\n                            ['!=', 'NOT_EQUAL'],\n                            ['>', 'GREATER'],\n                            ['<', 'LESS'],\n                            ['≥', 'GREATER_OR_EQUAL'],\n                            ['≤', 'LESS_OR_EQUAL'],\n                        ],\n                        value: 'LESS',\n                        fontSize: 10,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        noArrow: true,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        'LESS',\n                        {\n                            type: 'text',\n                            params: ['512'],\n                        }],\n                    type: 'mechatro_get_analog_judgement',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    OPERATOR: 1,\n                    RIGHTHAND: 2,\n                },\n                class: 'MechatroJudgement',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const operator = script.getField('OPERATOR', script);\n                    let [portNo, rightValue] = script.getValues(\n                        ['PORT', 'RIGHTHAND'],\n                        script\n                    );\n                    let mode;\n                    let leftValue;\n\n                    mode = Entry.mechatro.portMode.SET_ANALOG_IN;\n                    Entry.mechatro.transferMode(portNo, mode);\n\n                    if (typeof rightValue === 'string' && rightValue.length) {\n                        const rightNumber = Number(rightValue);\n                        if (!isNaN(rightNumber)) {\n                            rightValue = rightNumber;\n                        }\n                    }\n\n                    if (Entry.hw.portData[portNo] !== undefined) {\n                        leftValue = Entry.hw.portData[portNo];\n                        switch (operator) {\n                            case 'EQUAL':\n                                return leftValue === rightValue;\n                            case 'NOT_EQUAL':\n                                return leftValue != rightValue;\n                            case 'GREATER':\n                                return leftValue > rightValue;\n                            case 'LESS':\n                                return leftValue < rightValue;\n                            case 'GREATER_OR_EQUAL':\n                                return leftValue >= rightValue;\n                            case 'LESS_OR_EQUAL':\n                                return leftValue <= rightValue;\n                        }\n                    } else {\n                        return 0;\n                    }\n                },\n                syntax: { js: [], py: [] },\n            },\n\n            mechatro_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                            ['A6', '20'],\n                            ['A7', '21'],\n                        ],\n                        value: '16',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'mechatro_get_sensor_value',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                },\n                class: 'MechatroGet',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    //const mPortNo = `m${portNo}`;\n                    const mode = Entry.mechatro.portMode.SET_ANALOG_IN;\n\n                    Entry.mechatro.transferMode(portNo, mode);\n\n                    if (Entry.hw.portData[portNo] !== undefined) {\n                        return Entry.hw.portData[portNo];\n                    } else {\n                        return 0;\n                    }\n                },\n                syntax: { js: [], py: ['mechatro.sensor_value(%1)'] },\n            },\n            mechatro_get_temperature: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                            ['A6', '20'],\n                            ['A7', '21'],\n                        ],\n                        value: '16',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'mechatro_get_temperature',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                },\n                class: 'MechatroGet',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    //const mPortNo = `m${portNo}`;\n                    const mode = Entry.mechatro.portMode.SET_ANALOG_IN;\n                    Entry.mechatro.transferMode(portNo, mode);\n                    if (Entry.hw.portData[portNo] !== undefined) {\n                        return Math.round((Entry.hw.portData[portNo] * 0.4883 - 50));\n                    } else {\n                        return 0;\n                    }\n                },\n                syntax: { js: [], py: ['mechatro.sensor_temp(%1)'] },\n            },\n            mechatro_set_get_sensor_value_map: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'mechatro_get_sensor_value',\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['1023'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                    ],\n                    type: 'mechatro_set_get_sensor_value_map',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    VALUE2: 1,\n                    VALUE3: 2,\n                    VALUE4: 3,\n                    VALUE5: 4,\n                },\n                class: 'MechatroGet',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    let result = script.getValue('PORT', script);\n                    let value2 = script.getNumberValue('VALUE2', script);\n                    let value3 = script.getNumberValue('VALUE3', script);\n                    let value4 = script.getNumberValue('VALUE4', script);\n                    let value5 = script.getNumberValue('VALUE5', script);\n                    const stringValue4 = script.getValue('VALUE4', script);\n                    const stringValue5 = script.getValue('VALUE5', script);\n                    let isFloat = false;\n\n                    if (\n                        (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                        (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                    ) {\n                        isFloat = true;\n                    }\n\n                    result -= value2;\n                    result = result * ((value5 - value4) / (value3 - value2));\n                    result += value4;\n                    //result = Math.min(value5, result);\n                    //result = Math.max(value4, result);\n\n                    if (isFloat) {\n                        result = Math.round(result * 100) / 100;\n                    } else {\n                        result = Math.round(result);\n                    }\n\n                    return result;\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'mechatro.map(%1, %2, %3, %4, %5)',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            mechatro_get_ultrasonic_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D2', '2'],\n                            ['D4', '4'],\n                            ['D5', '5'],\n                            ['D6', '6'],\n                            ['D7', '7'],\n                            ['D10', '10'],\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D2', '2'],\n                            ['D4', '4'],\n                            ['D5', '5'],\n                            ['D6', '6'],\n                            ['D7', '7'],\n                            ['D10', '10'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'mechatro_get_ultrasonic_value',\n                },\n                paramsKeyMap: {\n                    TIRG: 0,\n                    ECHO: 1,\n                },\n                class: 'MechatroGet',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const trig = script.getNumberField('TIRG', script);\n                    const echo = script.getNumberField('ECHO', script);\n                    const mode = Entry.mechatro.portMode.SET_ULTRASONIC;\n                    Entry.mechatro.transferModeValue(trig, mode, echo);\n                    // 받는 값 업데이트 포트를 Disable 함. 디지털, 아날로그핀 설정으로 업데이트가 되지 안도록 함.\n                    // Echo 포트의 업데이트는 triger 포트에서 업데이트를 시켜줌\n                    Entry.mechatro.transferModeValue(echo, Entry.mechatro.portMode.SET_PORT_DISABLE);\n                    Entry.mechatro.eventState.ENABLE[trig] = false;\n                    Entry.mechatro.eventState.ENABLE[echo] = false;\n                    if (Entry.hw.portData.hasOwnProperty(echo)) {\n                        return Entry.hw.portData[echo];\n                    } else {\n                        return 0;\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'mechatro.ultrasonicRead(%1, %2)',\n                            blockType: 'param',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            mechatro_set_digital: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D2', '2'],\n                            ['D4', '4'],\n                            ['D5', '5'],\n                            ['D6', '6'],\n                            ['D7', '7'],\n                            ['D10', '10'],\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['켜기', '1'],\n                            ['끄기', '0'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'mechatro_set_digital',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    OPERATOR: 1,\n                },\n                class: 'Mechatro_d_out',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    let mode;\n                    mode = Entry.mechatro.portMode.SET_DIGITAL_OUT;\n                    const value = script.getNumberField('OPERATOR');\n\n                    Entry.mechatro.transferModeValue(portNo, mode, value);\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['mechatro.set_digital(%1, %2)'] },\n            },\n            mechatro_set_pwm: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D5', '5'],\n                            ['D6', '6'],\n                        ],\n                        value: '5',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0~100'],\n                        },\n                        null,\n                    ],\n                    type: 'mechatro_set_pwm',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    VALUE: 1,\n                },\n                class: 'Mechatro_d_out',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    const mode = Entry.mechatro.portMode.SET_PWM;\n                    let value = script.getValue('VALUE');\n\n                    if (!Entry.Utils.isNumber(value)) {\n                        value = 0;\n                    }\n                    value = Math.max(value, 0);\n                    value = Math.min(value, 100);\n\n                    Entry.mechatro.transferModeValue(portNo, mode, value);\n                    Entry.mechatro.eventState.ENABLE[portNo] = false;\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['mechatro.set_pwm(%1, %2)'] },\n            },\n            mechatro_set_tone_time: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D5', '5'],\n                            ['D6', '6'],\n                            ['D7', '7'],\n                            ['D10', '10'],\n                        ],\n                        value: '5',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['무음', '0'],\n                            ['도', '1'],\n                            ['도#(레♭)', '2'],\n                            ['레', '3'],\n                            ['레#(미♭)', '4'],\n                            ['미', '5'],\n                            ['파', '6'],\n                            ['파#(솔♭)', '7'],\n                            ['솔', '8'],\n                            ['솔#(라♭)', '9'],\n                            ['라', '10'],\n                            ['라#(시♭)', '11'],\n                            ['시', '12'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '0'],\n                            ['2', '1'],\n                            ['3', '2'],\n                            ['4', '3'],\n                            ['5', '4'],\n                            ['6', '5'],\n                        ],\n                        value: '3',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        null,\n                        {\n                            type: 'text',\n                            params: ['1'],\n                        },\n                        null,\n                    ],\n                    type: 'mechatro_set_tone_time',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    NOTE: 1,\n                    OCTAVE: 2,\n                    DURATION: 3,\n                },\n                class: 'Mechatro_d_out',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    Entry.mechatro.tonePin = portNo;\n                    let mode;\n                    if (!script.isStart) {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n\n                        let note = script.getNumberField('NOTE', script);\n                        let octave = script.getNumberField('OCTAVE', script);\n                        let value = (octave << 4) | (note - 1);\n                        let duration = script.getNumberValue('DURATION', script);\n\n                        duration = duration * 1000;\n                        if (duration < 100) {   //  100ms 이상만 연주, 통신 속도 및 음 후반부 50ms 무음처리 위함\n                            duration = 50;\n                        }\n\n                        if (duration === 50 || note === 0) {   // 음 후반 50ms 무음 처리, 동일음 연속사용시 음간 구분\n                            mode = Entry.mechatro.portMode.SET_NO_TONE;\n                            Entry.mechatro.transferMode(portNo, mode);\n                            Entry.mechatro.eventState.ENABLE[portNo] = true;\n                            Entry.mechatro.tonePin = 0;\n                        } else {\n                            mode = Entry.mechatro.portMode.SET_TONE;\n                            Entry.mechatro.transferModeValue(3, Entry.mechatro.portMode.SET_MOTOR_SPEED_Free, 100);    // 모터 사용 중지\n                            Entry.mechatro.transferModeValue(11, Entry.mechatro.portMode.SET_MOTOR_SPEED_Free, 100);   // 모터 사용 중지\n                            Entry.mechatro.transferModeValue(portNo, mode, value);\n                            Entry.mechatro.eventState.ENABLE[portNo] = false;\n                        }\n\n                        setTimeout(() => {\n                            script.timeFlag = 2;\n                        }, duration - 50);\n\n                        setTimeout(() => {\n                            script.timeFlag = 0;\n                        }, duration);\n\n                        return script;\n                    } else if (script.timeFlag == 1) {\n                        return script;\n                    } else if (script.timeFlag == 2) {\n                        mode = Entry.mechatro.portMode.SET_NO_TONE;\n                        Entry.mechatro.transferMode(portNo, mode);\n                        Entry.mechatro.eventState.ENABLE[portNo] = true;\n                        Entry.mechatro.tonePin = 0;\n                        return script;\n                    } else {\n                        delete script.timeFlag;\n                        delete script.isStart;\n                        Entry.engine.isContinue = false;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'mechatro.tone_time(%1, %2, %3, %4)',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            mechatro_set_tone: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D5', '5'],\n                            ['D6', '6'],\n                            ['D7', '7'],\n                            ['D10', '10'],\n                        ],\n                        value: '5',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['무음', '0'],\n                            ['도', '1'],\n                            ['도#(레♭)', '2'],\n                            ['레', '3'],\n                            ['레#(미♭)', '4'],\n                            ['미', '5'],\n                            ['파', '6'],\n                            ['파#(솔♭)', '7'],\n                            ['솔', '8'],\n                            ['솔#(라♭)', '9'],\n                            ['라', '10'],\n                            ['라#(시♭)', '11'],\n                            ['시', '12'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '0'],\n                            ['2', '1'],\n                            ['3', '2'],\n                            ['4', '3'],\n                            ['5', '4'],\n                            ['6', '5'],\n                        ],\n                        value: '3',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null, null],\n                    type: 'mechatro_set_tone',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    NOTE: 1,\n                    OCTAVE: 2,\n                },\n                class: 'Mechatro_d_out',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    let portNo = script.getNumberField('PORT', script);\n                    Entry.mechatro.tonePin = portNo;\n                    let note = script.getNumberField('NOTE', script);\n                    let octave = script.getNumberField('OCTAVE', script);\n                    let mode;\n                    let value = (octave << 4) | (note - 1);\n\n                    if (note === 0) {\n                        mode = Entry.mechatro.portMode.SET_NO_TONE;\n                        Entry.mechatro.transferMode(portNo, mode);\n                        Entry.mechatro.eventState.ENABLE[portNo] = true;\n                        Entry.mechatro.tonePin = 0;\n                    } else {\n                        mode = Entry.mechatro.portMode.SET_TONE;\n                        Entry.mechatro.transferModeValue(3, Entry.mechatro.portMode.SET_MOTOR_SPEED_Free, 100);\n                        Entry.mechatro.transferModeValue(11, Entry.mechatro.portMode.SET_MOTOR_SPEED_Free, 100);\n                        Entry.mechatro.transferModeValue(portNo, mode, value);\n                        Entry.mechatro.eventState.ENABLE[portNo] = false;\n                    }\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: [\n                        {\n                            syntax: 'mechatro.tone(%1, %2, %3)',\n                            textParams: [\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                                {\n                                    type: 'Block',\n                                    accept: 'string',\n                                },\n                            ],\n                        },\n                    ],\n                },\n            },\n            mechatro_set_dc_motor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['MA', '3'],\n                            ['MB', '11'],\n                        ],\n                        value: '3',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['-100 ~ 100 사이값'],\n                        },\n                        null,\n                    ],\n                    type: 'mechatro_set_dc_motor',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    SPEED: 1,\n                },\n                class: 'set_motor',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getField('PORT', script);\n                    let value = script.getValue('SPEED');\n\n                    if (!Entry.Utils.isNumber(value)) {\n                        value = 0;\n                    }\n\n                    const mode = Entry.mechatro.portMode.SET_MOTOR_SPEED_Free;\n                    value = Math.round(value);\n                    value = value + 100;\n                    value = Math.max(value, 0);\n                    value = Math.min(value, 200);\n\n                    if (Entry.mechatro.tonePin) {   // 22.6.5 톤 중복 사용 금지처리\n                        Entry.mechatro.transferMode(Entry.mechatro.tonePin, Entry.mechatro.portMode.SET_NO_TONE);\n                        Entry.mechatro.tonePin = 0;\n                    }\n                    Entry.mechatro.transferModeValue(portNo, mode, value);\n                    return script.callReturn();\n                },\n            },\n            mechatro_get_dc_motor_current: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['MA', '14'],\n                            ['MB', '15'],\n                        ],\n                        value: '14',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'mechatro_get_dc_motor_current',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                },\n                class: 'MechatroGet',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    const mode = Entry.mechatro.portMode.SET_MOTOR_CURRENT;\n\n                    Entry.mechatro.transferMode(portNo, mode);\n\n                    if (Entry.hw.portData[portNo] !== undefined) {\n                        return Entry.hw.portData[portNo] * 10.0; // [cA] → [mA]\n                    } else {\n                        return 0;\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: ['mechatro.get_dc_motor_current(%1)'],\n                },\n            },\n            mechatro_set_servo_position: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D2', '2'],\n                            ['D5', '5'],\n                            ['D6', '6'],\n                            ['D10', '10'],\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0~180'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['1~255'],\n                        },\n                        null,\n                    ],\n                    type: 'mechatro_set_servo_position',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    DEGREE: 1,\n                    SPEED: 2,\n                },\n                class: 'set_motor',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    const mode = Entry.mechatro.portMode.SET_SERVO_SPEED;\n\n                    let degree = script.getValue('DEGREE');\n                    if (!Entry.Utils.isNumber(degree)) {\n                        degree = 90;\n                    };\n                    degree = Math.max(degree, 0);\n                    degree = Math.min(degree, 180);\n\n                    let speed = script.getValue('SPEED');\n                    if (!Entry.Utils.isNumber(speed)) {   // 입력값 검사\n                        speed = 60;  //초당 60도\n                    };\n                    speed = Math.max(speed, 1);\n                    speed = Math.min(speed, 255);\n\n                    if (Entry.hw.sendQueue.SEND_DATA == undefined) {\n                        Entry.hw.sendQueue = {\n                            SEND_DATA: {},\n                        };\n                    }\n                    Entry.hw.sendQueue.SEND_DATA[portNo] = {\n                        MODE: mode,\n                        POSITION: degree,\n                        VALUE: speed,\n                    };\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: ['mechatro.set_servo_position(%1, %2)'],\n                },\n            },\n            mechatro_set_servo_positions: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['0~180'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0~180'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0~180'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0~180'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0.5~12.0'],\n                        },\n                        null,\n                    ],\n                    type: 'mechatro_set_servo_positions',\n                },\n                paramsKeyMap: {\n                    P0: 0,\n                    P1: 1,\n                    P2: 2,\n                    P3: 3,\n                    RUNTIME: 4,\n                },\n                class: 'set_motor',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    if (!script.isStart) {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n\n                        const mode = Entry.mechatro.portMode.SET_ALL_SERVO_RUNTIME;\n                        let runTime = script.getValue('RUNTIME');\n                        let servoP = {\n                            '0': script.getValue('P0'),\n                            '1': script.getValue('P1'),\n                            '2': script.getValue('P2'),\n                            '3': script.getValue('P3'),\n                        };\n                        Object.keys(servoP).forEach((key) => {    // 입력값 검사\n                            if (!Entry.Utils.isNumber(servoP[key])) {\n                                servoP[key] = 90;\n                            };\n                            servoP[key] = Math.max(servoP[key], 0);\n                            servoP[key] = Math.min(servoP[key], 180);\n                        });\n\n                        if (!Entry.Utils.isNumber(runTime)) {   // 입력값 검사\n                            runTime = 30;  //3초\n                        } else {\n                            runTime *= 10;\n                        };\n                        runTime = Math.max(runTime, 5);\n                        runTime = Math.min(runTime, 128);\n\n                        if (Entry.hw.sendQueue.SEND_DATA == undefined) {\n                            Entry.hw.sendQueue = {\n                                SEND_DATA: {},\n                            };\n                        }\n                        Entry.hw.sendQueue.SEND_DATA[\"allServoPort\"] = {\n                            MODE: mode,\n                            POSITION: servoP,\n                            VALUE: runTime,\n                        };\n                        setTimeout(() => {\n                            script.timeFlag = 0;\n                        }, runTime * 100);\n                        return script;\n                    } else if (script.timeFlag == 1) {\n                        return script;\n                    } else {\n                        delete script.timeFlag;\n                        delete script.isStart;\n                        Entry.engine.isContinue = false;\n                        return script.callReturn();\n                    }\n                },\n                syntax: {\n                    js: [],\n                    py: ['mechatro.set_servo_positions(%1, %2, %3, %4, %5)'],\n                },\n            },\n            mechatro_set_servo_speed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['D2', '22'],\n                            ['D5', '24'],\n                            ['D6', '25'],\n                            ['D10', '27'],\n                        ],\n                        value: '22',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['1~255'],\n                        },\n                        null,\n                    ],\n                    type: 'mechatro_set_servo_speed',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    SPEED: 1,\n                },\n                class: 'set_motor',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const portNo = script.getNumberField('PORT', script);\n                    const mode = Entry.mechatro.portMode.SET_SERVO_SPEED;\n                    let value = script.getValue('SPEED');\n\n                    if (!Entry.Utils.isNumber(value)) {\n                        value = 255;\n                    }\n                    value = Math.max(value, 0);\n                    value = Math.min(value, 255);\n\n                    Entry.mechatro.transferModeValue(portNo, mode, value);\n\n                    return script.callReturn();\n                },\n                syntax: {\n                    js: [],\n                    py: ['mechatro.set_servo_speed(%1, %2)'],\n                },\n            },\n            mechatro_set_blue_pw: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['1'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['2'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['3'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['4'],\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    type: 'mechatro_set_blue_pw',\n                },\n                paramsKeyMap: {\n                    PW1: 0,\n                    PW2: 1,\n                    PW3: 2,\n                    PW4: 3,\n                },\n                class: 'Mechatro_blue',\n                isNotFor: ['mechatro'],\n                func(sprite, script) {\n                    const mode = Entry.mechatro.portMode.SET_BLUE_PW;\n\n                    const value =\n                        script.getNumberValue('PW1') * 1000 +\n                        script.getNumberValue('PW2') * 100 +\n                        script.getNumberValue('PW3') * 10 +\n                        script.getNumberValue('PW4');\n\n                    Entry.mechatro.transferModeValue(2, mode, value);\n\n                    return script.callReturn();\n                },\n                syntax: { js: [], py: ['mechatro.set_pwm(%1, %2)'] },\n            },\n        };\n    }\n}\n\nEntry.mechatro = new mechatro();\nmodule.exports = Entry.mechatro;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_mechatronics_4d.js",
    "content": "'use strict';\n\nEntry.Mechatronics_4D = {\n    id: '1A.1',\n    name: 'Mechatronics_4D',\n    url: 'http://4dblock.com/',\n    imageName: 'mechatronics_4d.png',\n    title: {\n        'ko': '4D 메카트로닉스',\n        'en': '4D Mechatronics'\n    },\n    \n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on', 'left', 'clock', 'front'],\n    lowList: ['low', '0', 'off', 'right', 'counter_clock', 'rear'],\n    BlockState: {},\n};\n\nEntry.Mechatronics_4D.blockMenuBlocks = [ //작성할 블록의 이름을 이곳에 추가합니다.\n    'Mechatronics_4D_get_analog_value',\n    'Mechatronics_4D_get_analog_value_map',\n    'Mechatronics_4D_get_ultrasonic_value',\n    'Mechatronics_4D_get_digital',\n    \"Mechatronics_4D_toggle_led\",\n    \"Mechatronics_4D_digital_pwm\",\n    \"Mechatronics_4D_set_tone\",\n    \"Mechatronics_4D_get_digital\",\n    \"Mechatronics_4D_on_motor\",\n    \"Mechatronics_4D_controll_motor_speed1\",\n    \"Mechatronics_4D_controll_motor_speed2\",\n    \"Mechatronics_4D_off_motor\",\n    \"Mechatronics_4D_set_servo\",\n];\n\nEntry.Mechatronics_4D.setLanguage = () => { //블록 언어 템플릿\n    return {\n        ko: {\n            template: {\n                Mechatronics_4D_get_analog_value: '아날로그 %1 번 센서값',\n                Mechatronics_4D_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                Mechatronics_4D_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                Mechatronics_4D_get_digital: '디지털 %1 번 센서값',\n                Mechatronics_4D_toggle_led: '디지털 %1번 핀 %2 %3',\n                Mechatronics_4D_digital_pwm: '디지털 %1번 핀을 %2(으)로 정하기 %3',\n                Mechatronics_4D_set_tone: '디지털 %1번 핀의 버저를 %2 %3 음으로 %4초 연주하기 %5',\n                Mechatronics_4D_get_digital: '디지털 %1번 센서값',\n                Mechatronics_4D_on_motor: '%1 %2 %3 DC모터를 %4으로 움직이기 %5',\n                Mechatronics_4D_controll_motor_speed1: '%1 %2 뒤 DC모터를 %3 %4 속도로 움직이기 %5',\n                Mechatronics_4D_controll_motor_speed2: '%1 %2 뒤 DC모터를 %3 %4 속도로 움직이기 %5',\n                Mechatronics_4D_off_motor: '%1 %2 %3 DC모터를 멈추기 %4',   \n                Mechatronics_4D_set_servo: '%1 %2 서보 모터의 각도를 %3(으)로 정하기 %4',\n            }\n        },\n        en: {\n            template: {\n                Mechatronics_4D_get_analog_value: 'Analog %1 Sensor value',\n                Mechatronics_4D_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                Mechatronics_4D_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                Mechatronics_4D_get_digital: 'Digital %1 Sensor value',\n                Mechatronics_4D_toggle_led: 'Digital %1 Pin %2 %3',\n                Mechatronics_4D_digital_pwm: 'Digital %1 Pin %2 %3',\n                Mechatronics_4D_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                Mechatronics_4D_get_digital: 'Digital %1 Sensor value',\n                Mechatronics_4D_on_motor: 'Turn on %1 %2 DC motor %3wise %4',\n                Mechatronics_4D_controll_motor_speed1: 'Turn on %1 rear DC motor %2 at the speed of %3 %4',\n                Mechatronics_4D_controll_motor_speed2: 'Turn on %1 rear DC motor %2 at the speed of %3 %4',\n                Mechatronics_4D_off_motor: 'Turn off %1 $2 DC motor %3',\n                Mechatronics_4D_set_servo: 'Set %1 servo motor angle as %2 %3',\n            }\n        }\n    }\n}\n\nEntry.Mechatronics_4D.getBlocks = () => {\n    return {\n        //region Mechatronics_4D 메카트로닉스4D\n        Mechatronics_4D_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n\n        Mechatronics_4D_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Mechatronics_4D_analog_list',\n                    },\n                ],\n                type: 'Mechatronics_4D_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Mechatronics_4D_Get',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n\n        Mechatronics_4D_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Mechatronics_4D_get_analog_value',\n                        params: [\n                            {\n                                type: 'Mechatronics_4D_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'Mechatronics_4D_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'Mechatronics_4D_Get',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                var result = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var stringValue4 = script.getValue('VALUE4', script);\n                var stringValue5 = script.getValue('VALUE5', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n        },\n\n        Mechatronics_4D_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'Mechatronics_4D_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'Mechatronics_4D_Get',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.Mechatronics_4D.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n\n        Mechatronics_4D_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'Mechatronics_4D_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Mechatronics_4D_Get',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Mechatronics_4D') {\n                    var port = script.getNumberValue('PORT', script);\n                    var DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.Mechatronics_4D.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n        },\n\n        Mechatronics_4D_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'Mechatronics_4D_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Mechatronics_4D',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Mechatronics_4D.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Mechatronics_4D.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Mechatronics_4D.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n\n        Mechatronics_4D_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'Mechatronics_4D_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Mechatronics_4D',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Mechatronics_4D.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n\n        Mechatronics_4D_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n\n        Mechatronics_4D_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Mechatronics_4D_tone_list',\n                    },\n                ],\n                type: 'Mechatronics_4D_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n        },\n\n        Mechatronics_4D_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'Mechatronics_4D_tone_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_tone_value',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'Mechatronics_4D_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'Mechatronics_4D',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) note = Entry.Mechatronics_4D.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.Mechatronics_4D.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var value = 0;\n\n                    if (note != 0) {\n                        value = Entry.Mechatronics_4D.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.Mechatronics_4D.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.Mechatronics_4D.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        Mechatronics_4D_board_version_list: { //보드 버전 리스트\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statement: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['V3', '3'],\n                        ['V4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VERSION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('VERSION');\n            },\n        },\n\n        Mechatronics_4D_motor_list: {//왼쪽 모터, 오른쪽 모터 드랍다운 블록\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statement: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.General.left, 'left'],\n                        [Lang.General.right, 'right'],\n                    ],\n                    value: 'left',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('MOTOR');\n            },\n        },\n\n        Mechatronics_4D_motor_side_list: { // 앞쪽 모터, 오른쪽 모터 드랍다운 블록\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statement: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞', 'front'],\n                        ['뒤', 'rear'],\n                    ],\n                    value: 'front',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                SIDE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('SIDE');\n            },\n        },\n        \n        Mechatronics_4D_rotation_list: { //시계방향, 반시계방향 드랍다운 블록\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statement: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['정방향', 'clock'],\n                        ['역방향', 'counter_clock'],\n                    ],\n                    value: 'clock',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROTATION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('ROTATION');\n            },\n        },\n\n        Mechatronics_4D_on_motor: { //모터 작동 블록(속도 조절 불가능)\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'Mechatronics_4D_board_version_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_motor_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_motor_side_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_rotation_list',\n                    },\n                ],\n                type: 'Mechatronics_4D_on_motor'\n            },\n            paramsKeyMap: {\n                VERSION: 0,\n                MOTOR: 1,\n                SIDE: 2,\n                ROTATION: 3,\n            },\n            class: 'Mechatronics_4D',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                //보드의 버전\n                var version = script.getNumberValue('VERSION');\n                //제어할 DC모터의 방향\n                var motor = script.getValue('MOTOR');\n                //제어할 DC모터의 위치\n                var side = script.getValue('SIDE');\n                //DC모터의 회전 방향\n                var rotation = script.getValue('ROTATION');\n                \n                //제어할 DC모터의 핀 번호\n                var port1, port2;\n\n                //회전 방향을 제어할 변수\n                var value1, value2;\n\n\n                if(typeof motor === 'string') {\n                    motor = motor.toLowerCase();\n                }\n                \n                if(typeof rotation === 'string') {\n                    rotation = rotation.toLowerCase();\n                }\n\n                switch(version){  //보드의 버전을 구분\n                    case 3: //v3\n                        if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                            if(Entry.Mechatronics_4D.highList.indexOf(side) > -1) {\n                                //왼쪽 앞단 DC모터를 제어하는 14번핀과 15번핀(A0, A1)\n                                port1 = '14';\n                                port2 = '15';\n                            }\n                            else if(Entry.Mechatronics_4D.lowList.indexOf(side) > -1) {\n                                //왼쪽 뒷단 DC모터를 제어하는 5번핀과 6번핀\n                                port1 = '5';\n                                port2 = '6';\n                            }\n                        }\n                        else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                            if(Entry.Mechatronics_4D.highList.indexOf(side) > -1) {\n                                //오른쪽 앞단 DC모터를 제어하는 16번 핀과 17번핀(A3, A4)\n                                port1 = '17';\n                                port2 = '16';\n                            }\n                                else if(Entry.Mechatronics_4D.lowList.indexOf(side) > -1) {\n                                //오른쪽 뒷단 DC모터를 제어하는 9번핀과 10번핀\n                                port1 = '10';\n                                port2 = '9';\n                            }\n                        }\n                        else {\n                            throw new Error();\n                        }\n                        break;\n\n                    case 4: //v4\n                        if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                            if(Entry.Mechatronics_4D.highList.indexOf(side) > -1) {\n                                //왼쪽 앞단 DC모터를 제어하는 16번핀과 17번핀\n                                port1 = '16';\n                                port2 = '17';\n                            }\n                            else if(Entry.Mechatronics_4D.lowList.indexOf(side) > -1) {\n                                //왼쪽 뒷단 DC모터를 제어하는 9번핀과 10번핀\n                                port1 = '9';\n                                port2 = '10';                                \n                            }\n                        }\n                        else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                            if(Entry.Mechatronics_4D.highList.indexOf(side) > -1) {\n                                //오른쪽 앞단 DC모터를 제어하는 14번핀과 15번핀(A3, A4)\n                                port1 = '14';\n                                port2 = '15';\n                            }\n                            else if(Entry.Mechatronics_4D.lowList.indexOf(side) > -1) {\n                                //오른쪽 뒷단 DC모터를 제어하는 5번핀과 6번핀\n                                port1 = '5';\n                                port2 = '6';\n                            }\n                        }\n                        else {\n                            throw new Error();\n                        }\n                        break;\n                }\n            \n                if(Entry.Mechatronics_4D.highList.indexOf(rotation) > -1) {\n                    //정방향 회전\n                    value1 = 0;\n                    value2 = 1;\n                }\n                else if(Entry.Mechatronics_4D.lowList.indexOf(rotation) > -1) {\n                    //역방향 회전\n                    value1 = 1;\n                    value2 = 0;\n                }\n                else {\n                    throw new Error();\n                }\n               \n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                //각 핀에 데이터 보냄\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.DIGITAL,\n                    data : value1,\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.DIGITAL,\n                    data : value2,\n                    time: new Date().getTime(),\n                };\n            }\n        },\n\n        // 14~17(A0~A3)번 핀은 속도 조절이 불가능함 \n        Mechatronics_4D_controll_motor_speed1: { //모터 작동 블록(속도 조절 가능)\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'Mechatronics_4D_board_version_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_motor_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_rotation_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                ],\n                type: 'Mechatronics_4D_controll_motor_speed1'\n            },\n            paramsKeyMap: {\n                VERSION: 0,\n                MOTOR: 1,\n                ROTATION: 2,\n                VALUE: 3,\n            },\n            class: 'Mechatronics_4D',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                //보드의 버전\n                var version = script.getNumberValue('VERSION');\n                //제어할 DC모터의 위치\n                var motor = script.getValue('MOTOR');\n                //DC모터의 회전 방향\n                var rotation = script.getValue('ROTATION');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                \n                //제어할 DC모터의 핀 번호\n                var port1, port2;\n\n                //회전 방향을 제어할 변수\n                var value1, value2;\n\n                if(typeof motor === 'string') {\n                    motor = motor.toLowerCase();\n                }\n                switch(version){ //보드의 버전을 구분\n                    case 3: //v3\n                        if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                            //왼쪽 DC모터를 제어하는 5번핀과 6번핀\n                            port1 = '5';\n                            port2 = '6';\n                        }\n                        else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                            //오른쪽 DC모터를 제어하는 9번핀과 10번핀\n                            port1 = '10';\n                            port2 = '9';\n                        }\n                        else {\n                            throw new Error();\n                        }\n                        break;\n\n                    case 4: //v4\n                        if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                            //왼쪽 DC모터를 제어하는 9번핀과 10번핀\n                            port1 = '9';\n                            port2 = '10';\n                        }\n                        else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                            //오른쪽 DC모터를 제어하는 5번핀과 6번핀\n                            port1 = '5';\n                            port2 = '6';\n                        }\n                        else {\n                            throw new Error();\n                        }\n                        break;\n                }\n               \n\n                if(typeof rotation === 'string') {\n                    rotation = rotation.toLowerCase();\n                }\n\n                if(Entry.Mechatronics_4D.highList.indexOf(rotation) > -1) {\n                    //정방향 회전\n                    value1 = 0;\n                    value2 = value;\n                }\n                else if(Entry.Mechatronics_4D.lowList.indexOf(rotation) > -1) {\n                    //역방향 회전\n                    value1 = value;\n                    value2 = 0;\n                }\n                else {\n                    throw new Error();\n                }\n\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                //각 핀에 데이터 보냄\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.PWM,\n                    data : value1,\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.PWM,\n                    data : value2,\n                    time: new Date().getTime(),\n                };\n            }\n        },\n        \n        Mechatronics_4D_motor_speed_list: { //시계방향, 반시계방향 드랍다운 블록\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statement: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['아주 느린', '60'],\n                        ['느린', '100'],\n                        ['보통', '140'],\n                        ['빠른', '180'],\n                        ['아주 빠른', '255'],\n                    ],\n                    value: '140',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('SPEED');\n            },\n        },\n\n        Mechatronics_4D_controll_motor_speed2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'Mechatronics_4D_board_version_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_motor_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_rotation_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_motor_speed_list',\n                    },\n                ],\n                type: 'Mechatronics_4D_controll_motor_speed2'\n            },\n            paramsKeyMap: {\n                VERSION: 0,\n                MOTOR: 1,\n                ROTATION: 2,\n                SPEED: 3,\n            },\n            class: 'Mechatronics_4D',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                //보드의 버전\n                var version = script.getNumberValue('VERSION');\n                //제어할 DC모터의 위치\n                var motor = script.getValue('MOTOR');\n                //DC모터의 회전 방향\n                var rotation = script.getValue('ROTATION');\n                var speed = script.getNumberValue('SPEED');\n                \n                //제어할 DC모터의 핀 번호\n                var port1, port2;\n\n                //회전 방향을 제어할 변수\n                var value1, value2;\n\n                if(typeof motor === 'string') {\n                    motor = motor.toLowerCase();\n                }\n                \n                switch(version){\n                    case 3: //v3\n                        if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                            //왼쪽 DC모터를 제어하는 5번핀과 6번핀\n                            port1 = '5';\n                            port2 = '6';\n                        }\n                        else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                            //오른쪽 DC모터를 제어하는 9번핀과 10번핀\n                            port1 = '10';\n                            port2 = '9';\n                        }\n                        else {\n                            throw new Error();\n                        }\n                        break;\n\n                    case 4: //v4\n                        if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                            //왼쪽 DC모터를 제어하는 9번핀과 10번핀\n                            port1 = '9';\n                            port2 = '10';\n                        }\n                        else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                            //오른쪽 DC모터를 제어하는 5번핀과 6번핀\n                            port1 = '5';\n                            port2 = '6';\n                        }\n                        else {\n                            throw new Error();\n                        }\n                        break;\n                }\n\n                if(typeof rotation === 'string') {\n                    rotation = rotation.toLowerCase();\n                }\n\n                if(Entry.Mechatronics_4D.highList.indexOf(rotation) > -1) {\n                    //정방향 회전\n                    value1 = 0;\n                    value2 = speed;\n                }\n                else if(Entry.Mechatronics_4D.lowList.indexOf(rotation) > -1) {\n                    //역방향 회전\n                    value1 = speed;\n                    value2 = 0;\n                }\n                else {\n                    throw new Error();\n                }\n\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                //각 핀에 데이터 보냄\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.PWM,\n                    data : value1,\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.PWM,\n                    data : value2,\n                    time: new Date().getTime(),\n                };\n            }\n        },\n\n        Mechatronics_4D_off_motor: { //모터 작동 중지 블록\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'Mechatronics_4D_board_version_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_motor_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_motor_side_list',\n                    },\n                ],\n                type: 'Mechatronics_4D_off_motor'\n            },\n            paramsKeyMap: {\n                VERSION: 0,\n                MOTOR: 1,\n                SIDE: 2,\n            },\n            class: 'Mechatronics_4D',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                //보드의 버전\n                var version = script.getNumberValue('VERSION');\n                //제어할 DC모터의 방향\n                var motor = script.getValue('MOTOR');\n                //제어할 DC모터의 위치\n                var side = script.getValue('SIDE');\n                //제어할 DC모터의 핀 번호\n                var port1, port2;\n                //핀 번호에 보내줄 값, 정지할 것이므로 0으로 설정\n                var value = 0;\n\n                if(typeof motor === 'string') {\n                    motor = motor.toLowerCase();\n                }\n                \n                switch(version){  //보드의 버전을 구분\n                    case 3: //v3\n                        if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                            if(Entry.Mechatronics_4D.highList.indexOf(side) > -1) {\n                                //왼쪽 앞단 DC모터를 제어하는 14번핀과 15번핀(A0, A1)\n                                port1 = '14';\n                                port2 = '15';\n                            }\n                            else if(Entry.Mechatronics_4D.lowList.indexOf(side) > -1) {\n                                //왼쪽 뒷단 DC모터를 제어하는 5번핀과 6번핀\n                                port1 = '5';\n                                port2 = '6';\n                            }\n                        }\n                        else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                            if(Entry.Mechatronics_4D.highList.indexOf(side) > -1) {\n                                //오른쪽 앞단 DC모터를 제어하는 16번 핀과 17번핀(A3, A4)\n                                port1 = '17';\n                                port2 = '16';\n                            }\n                                else if(Entry.Mechatronics_4D.lowList.indexOf(side) > -1) {\n                                //오른쪽 뒷단 DC모터를 제어하는 9번핀과 10번핀\n                                port1 = '10';\n                                port2 = '9';\n                            }\n                        }\n                        else {\n                            throw new Error();\n                        }\n                        break;\n\n                    case 4: //v4\n                        if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                            if(Entry.Mechatronics_4D.highList.indexOf(side) > -1) {\n                                //왼쪽 앞단 DC모터를 제어하는 16번핀과 17번핀\n                                port1 = '16';\n                                port2 = '17';\n                            }\n                            else if(Entry.Mechatronics_4D.lowList.indexOf(side) > -1) {\n                                //왼쪽 뒷단 DC모터를 제어하는 9번핀과 10번핀\n                                port1 = '9';\n                                port2 = '10';                                \n                            }\n                        }\n                        else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                            if(Entry.Mechatronics_4D.highList.indexOf(side) > -1) {\n                                //오른쪽 앞단 DC모터를 제어하는 14번핀과 15번핀(A3, A4)\n                                port1 = '14';\n                                port2 = '15';\n                            }\n                            else if(Entry.Mechatronics_4D.lowList.indexOf(side) > -1) {\n                                //오른쪽 뒷단 DC모터를 제어하는 5번핀과 6번핀\n                                port1 = '5';\n                                port2 = '6';\n                            }\n                        }\n                        else {\n                            throw new Error();\n                        }\n                        break;\n                }\n                \n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                //각 핀에 데이터 보냄\n                Entry.hw.sendQueue['SET'][port1] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.DIGITAL,\n                    data : value,\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.sendQueue['SET'][port2] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.DIGITAL,\n                    data : value,\n                    time: new Date().getTime(),\n                };\n            }\n        },\n\n        Mechatronics_4D_set_servo: { //서보모터 작동 블록\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    {\n                        type: 'Mechatronics_4D_board_version_list',\n                    },\n                    {\n                        type: 'Mechatronics_4D_motor_list',\n                    },\n                    null,\n                ],\n                type: 'Mechatronics_4D_set_servo',\n            },\n            paramsKeyMap: {\n                VERSION: 0,\n                MOTOR: 1,\n                ANGLE: 2,\n            },\n            class: 'Mechatronics_4D',\n            isNotFor: ['Mechatronics_4D'],\n            func: function(sprite, script) {\n                //보드의 버전\n                var version = script.getNumberValue('VERSION');\n                //제어할 서보모터의 위치\n                var motor = script.getValue('MOTOR');\n                //제어할 서보모터의 핀 번호\n                var port;\n                //서보모터를 설정할 각도\n                var angle = script.getValue('ANGLE');\n\n                if(typeof motor === 'string') {\n                    motor = motor.toLowerCase();\n                }\n\n                if(Entry.Mechatronics_4D.highList.indexOf(motor) > -1) {\n                    //왼쪽 서보모터를 제어하는 11번핀\n                    port = '11';\n                }\n                else if(Entry.Mechatronics_4D.lowList.indexOf(motor) > -1) {\n                    //오른쪽 서보모터를 제어하는 3번핀\n                    port = '3';\n                }\n                else {\n                    throw new Error();\n                }\n\n                if(!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                //핀에 데이터 보냄\n                Entry.hw.sendQueue['SET'][port] = {\n                    type : Entry.Mechatronics_4D.sensorTypes.SERVO_PIN,\n                    data : angle,\n                    time: new Date().getTime(),\n                };\n            }\n        },\n\n    }\n     //endregion Mechatronics_4D 메카트로닉스4D\n}\n\nmodule.exports = Entry.Mechatronics_4D;"
  },
  {
    "path": "src/playground/blocks/hardware/block_memaker.js",
    "content": "'use strict';\n\nEntry.memaker = {\n    id: '6.2',\n    name: 'memaker',\n    url: 'http://www.jkelec.co.kr/',\n    imageName: 'memaker.png',\n    title: {\n        ko: '미메이커',\n        en: 'memaker',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    toByte: function(data) {\n        switch (data) {\n            case ' ':\n                data = 32;\n                break;\n            case '!':\n                data = 33;\n                break;\n            case '\"':\n                data = 34;\n                break;\n            case '#':\n                data = 35;\n                break;\n            case '$':\n                data = 36;\n                break;\n            case '%':\n                data = 37;\n                break;\n            case '&':\n                data = 38;\n                break;\n            case \"'\":\n                data = 39;\n                break;\n            case '(':\n                data = 40;\n                break;\n            case ')':\n                data = 41;\n                break;\n            case '*':\n                data = 42;\n                break;\n            case '+':\n                data = 43;\n                break;\n            case ',':\n                data = 44;\n                break;\n            case '-':\n                data = 45;\n                break;\n            case '.':\n                data = 46;\n                break;\n            case '/':\n                data = 47;\n                break;\n            case '0':\n                data = 48;\n                break;\n            case '1':\n                data = 49;\n                break;\n            case '2':\n                data = 50;\n                break;\n            case '3':\n                data = 51;\n                break;\n            case '4':\n                data = 52;\n                break;\n            case '5':\n                data = 53;\n                break;\n            case '6':\n                data = 54;\n                break;\n            case '7':\n                data = 55;\n                break;\n            case '8':\n                data = 56;\n                break;\n            case '9':\n                data = 57;\n                break;\n            case ':':\n                data = 58;\n                break;\n            case ';':\n                data = 59;\n                break;\n            case '<':\n                data = 60;\n                break;\n            case '=':\n                data = 61;\n                break;\n            case '>':\n                data = 62;\n                break;\n            case '?':\n                data = 63;\n                break;\n            case '@':\n                data = 64;\n                break;\n            case 'A':\n                data = 65;\n                break;\n            case 'B':\n                data = 66;\n                break;\n            case 'C':\n                data = 67;\n                break;\n            case 'D':\n                data = 68;\n                break;\n            case 'E':\n                data = 69;\n                break;\n            case 'F':\n                data = 70;\n                break;\n            case 'G':\n                data = 71;\n                break;\n            case 'H':\n                data = 72;\n                break;\n            case 'I':\n                data = 73;\n                break;\n            case 'J':\n                data = 74;\n                break;\n            case 'K':\n                data = 75;\n                break;\n            case 'L':\n                data = 76;\n                break;\n            case 'M':\n                data = 77;\n                break;\n            case 'N':\n                data = 78;\n                break;\n            case 'O':\n                data = 79;\n                break;\n            case 'P':\n                data = 80;\n                break;\n            case 'Q':\n                data = 81;\n                break;\n            case 'R':\n                data = 82;\n                break;\n            case 'S':\n                data = 83;\n                break;\n            case 'T':\n                data = 84;\n                break;\n            case 'U':\n                data = 85;\n                break;\n            case 'V':\n                data = 86;\n                break;\n            case 'W':\n                data = 87;\n                break;\n            case 'X':\n                data = 88;\n                break;\n            case 'Y':\n                data = 89;\n                break;\n            case 'Z':\n                data = 90;\n                break;\n            case '[':\n                data = 91;\n                break;\n            case '\\\\':\n                data = 92;\n                break;\n            case ']':\n                data = 93;\n                break;\n            case '^':\n                data = 94;\n                break;\n            case '_':\n                data = 95;\n                break;\n            case '`':\n                data = 96;\n                break;\n            case 'a':\n                data = 97;\n                break;\n            case 'b':\n                data = 98;\n                break;\n            case 'c':\n                data = 99;\n                break;\n            case 'd':\n                data = 100;\n                break;\n            case 'e':\n                data = 101;\n                break;\n            case 'f':\n                data = 102;\n                break;\n            case 'g':\n                data = 103;\n                break;\n            case 'h':\n                data = 104;\n                break;\n            case 'i':\n                data = 105;\n                break;\n            case 'j':\n                data = 106;\n                break;\n            case 'k':\n                data = 107;\n                break;\n            case 'l':\n                data = 108;\n                break;\n            case 'm':\n                data = 109;\n                break;\n            case 'n':\n                data = 110;\n                break;\n            case 'o':\n                data = 111;\n                break;\n            case 'p':\n                data = 112;\n                break;\n            case 'q':\n                data = 113;\n                break;\n            case 'r':\n                data = 114;\n                break;\n            case 's':\n                data = 115;\n                break;\n            case 't':\n                data = 116;\n                break;\n            case 'u':\n                data = 117;\n                break;\n            case 'v':\n                data = 118;\n                break;\n            case 'w':\n                data = 119;\n                break;\n            case 'x':\n                data = 120;\n                break;\n            case 'y':\n                data = 121;\n                break;\n            case 'z':\n                data = 122;\n                break;\n            case '{':\n                data = 123;\n                break;\n            case '|':\n                data = 124;\n                break;\n            case '}':\n                data = 125;\n                break;\n            case '~':\n                data = 126;\n                break;\n        }\n\n        return data;\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        LCD: 9,\n        LCD_COMMAND: 10,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    directionTable: {\n        Forward: 0,\n        Backward: 1,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\nEntry.memaker.blockMenuBlocks = [\n    // memaker Added 2017-10-01\n    'memaker_get_analog_value',\n    'memaker_get_analog_value_map',\n    'memaker_get_ultrasonic_value',\n    'memaker_get_digital',\n    'memaker_toggle_led',\n    'memaker_digital_pwm',\n    'memaker_set_servo',\n    'memaker_set_lcd',\n    'memaker_lcd_command',\n    // memaker Added 2017-10-01\n];\n\nEntry.memaker.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                memaker_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                memaker_get_analog_value: '아날로그 %1 번 센서값',\n                memaker_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                memaker_get_digital: '디지털 %1 번 센서값',\n                memaker_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n                memaker_set_lcd: '1602 문자 LCD %1 행 , %2열에 %3 출력하기 %4',\n                memaker_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                memaker_toggle_led: '디지털 %1 번 핀 %2 %3',\n                memaker_lcd_command: '1602 문자 LCD %1 명령실행하기 %2',\n            },\n        },\n        en: {\n            template: {\n                memaker_digital_pwm: 'Digital %1 Pin %2 %3',\n                memaker_get_analog_value: 'Analog %1 Sensor value',\n                memaker_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                memaker_get_digital: 'Digital %1 Sensor value',\n                memaker_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                memaker_set_lcd: '1602 LCD Row %1, Column %2 Value %3 %4',\n                memaker_set_servo: 'Set servo pin %1 angle as %3',\n                memaker_toggle_led: 'Digital %1 Pin %2 %3',\n                memaker_lcd_command: '1602 LCD Command %1 execute %2',\n            },\n        },\n    };\n};\nEntry.memaker.getBlocks = function() {\n    return {\n        //region memaker 미메이커\n        memaker_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                        ['A6', '6'],\n                        ['A7', '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: { js: [], py: [] },\n        },\n        memaker_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'memaker_analog_list',\n                    },\n                ],\n                type: 'memaker_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'memakerGet',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        memaker_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'memaker_get_analog_value',\n                        params: [\n                            {\n                                type: 'memaker_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'memaker_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'memakerGet',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var result = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: { js: [], py: [] },\n        },\n        memaker_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                ],\n                type: 'memaker_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'memakerGet',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port1];\n                delete Entry.hw.sendQueue['SET'][port2];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.memaker.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        memaker_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'memaker_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'memakerGet',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.memaker.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        memaker_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'memaker_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'memaker',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.memaker.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.memaker.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.memaker.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        memaker_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'memaker_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'memaker',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.memaker.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        memaker_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'memaker_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'memaker',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.memaker.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        memaker_list_digital_lcd_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LINE1', '0'],\n                        ['LINE2', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        memaker_list_digital_lcd_column: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['COL1', '0'],\n                        ['COL2', '1'],\n                        ['COL3', '2'],\n                        ['COL4', '3'],\n                        ['COL5', '4'],\n                        ['COL6', '5'],\n                        ['COL7', '6'],\n                        ['COL8', '7'],\n                        ['COL9', '8'],\n                        ['COL10', '9'],\n                        ['COL11', '10'],\n                        ['COL12', '11'],\n                        ['COL13', '12'],\n                        ['COL14', '13'],\n                        ['COL15', '14'],\n                        ['COL16', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLUMN: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COLUMN');\n            },\n        },\n        memaker_set_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: Lang.template.memaker_set_lcd,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'memaker_list_digital_lcd_line',\n                    },\n                    {\n                        type: 'memaker_list_digital_lcd_column',\n                    },\n                    {\n                        type: 'text',\n                        params: ['Type text !!'],\n                    },\n                    null,\n                ],\n                type: 'memaker_set_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                COLUMN: 1,\n                STRING: 2,\n            },\n            class: 'memakerLcd',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var line = script.getValue('LINE', script);\n                var column = script.getValue('COLUMN', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = Entry.memaker.toByte(string[i]);\n                        }\n                    } else if (typeof string === 'number') {\n                        var num_to_string = string.toString();\n                        for (var i = 0; i < num_to_string.length; i++) {\n                            text[i] = Entry.memaker.toByte(num_to_string[i]);\n                        }\n                    } else {\n                        text[0] = string;\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    Entry.hw.sendQueue['SET'][line] = {\n                        type: Entry.memaker.sensorTypes.LCD,\n                        data: {\n                            line: line,\n                            column: column,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = true;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['memaker.memaker_set_lcd(%1, %2, %3)'] },\n        },\n        memaker_list_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LCD_BLUE', '0'],\n                        ['LCD_GREEN', '1'],\n                        ['LCD_CLEAR', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COMMAND');\n            },\n        },\n\n        memaker_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: Lang.template.memaker_lcd_command,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'memaker_list_lcd_command',\n                    },\n                    null,\n                ],\n                type: 'memaker_lcd_command',\n            },\n            paramsKeyMap: {\n                COMMAND: 0,\n            },\n            class: 'memakerLcd',\n            isNotFor: ['memaker'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var value = script.getNumberValue('COMMAND', script);\n                var command = script.getNumberValue('COMMAND', script);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][0] = {\n                    type: Entry.memaker.sensorTypes.LCD_COMMAND,\n                    data: {\n                        value: value,\n                        command: command,\n                    },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        //endregion memaker 미메이커\n    };\n};\n\nmodule.exports = Entry.memaker;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_microbit.js",
    "content": "'use strict';\n\nconst _set = require('lodash/set');\nconst _get = require('lodash/get');\nconst _merge = require('lodash/merge');\n\nEntry.Microbit = new (class Microbit {\n    constructor() {\n        this.id = '22.1';\n        this.url = 'http://microbit.org/ko/';\n        this.imageName = 'microbit.png';\n        this.title = {\n            en: 'Microbit V1',\n            ko: '마이크로비트 V1',\n        };\n        this.name = 'microbit';\n        this.blockIds = {};\n        this.isExecBlock = false;\n        this.cacheValues = [];\n        this.cacheIndex = 0;\n        this.radioTime = 0;\n    }\n\n    getHashKey() {\n        let key = new Date().getSeconds().toString(16);\n        if (key.length === 1) {\n            key += ((Math.random() * 16) | 0).toString(16);\n        }\n        return Entry.generateHash() + key;\n    }\n\n    setZero() {\n        Entry.hw.sendQueue = {\n            [this.getHashKey()]: {\n                type: 'RST',\n            },\n        };\n        Entry.hw.update();\n        this.blockIds = {};\n        this.isExecBlock = false;\n        this.execTimeFlag = false;\n        this.radioTime = 0;\n    }\n\n    sendMessage({ socket, sendQueue = {} }) {\n        if (!_.isEmpty(sendQueue)) {\n            const keys = Object.keys(sendQueue);\n            const uniqueKey = this.getHashKey();\n            socket.emit(\n                'message',\n                {\n                    data: JSON.stringify(sendQueue),\n                    mode: socket.mode,\n                    type: 'utf8',\n                    key: uniqueKey,\n                },\n                (data) => {\n                    if (data === uniqueKey) {\n                        keys.forEach((key) => {\n                            delete sendQueue[key];\n                        });\n                    }\n                }\n            );\n        }\n    }\n\n    asyncFlowControl({ script, data }, scope) {\n        if (!this.isExecBlock && !scope.isStart) {\n            const blockId = this.getHashKey();\n            this.isExecBlock = true;\n            scope.isStart = true;\n            scope.timeFlag = 1;\n            this.nowBlockId = blockId;\n            this.blockIds[blockId] = false;\n            _merge(Entry.hw.sendQueue, {\n                [blockId]: data,\n            });\n            Entry.hw.update();\n            setTimeout(() => {\n                scope.timeFlag = 0;\n            });\n            return false;\n        } else if (this.blockIds[this.nowBlockId] && scope.timeFlag === 0) {\n            delete this.blockIds[this.nowBlockId];\n            delete scope.isStart;\n            this.execTimeFlag = 0;\n            this.execTimeFlag = undefined;\n            this.isExecBlock = false;\n            Entry.engine.isContinue = false;\n            return true;\n        }\n        return false;\n    }\n\n    postCallReturn(args) {\n        const { script } = args;\n        if (!this.asyncFlowControl(args, script)) {\n            return Entry.STATIC.BREAK;\n        }\n    }\n\n    checkValue(args) {\n        const { script, key } = args;\n        const { entity, executor } = script;\n        const { scope } = executor;\n        const { cacheValue = {} } = scope;\n        const value = _get(cacheValue, key);\n        if (value) {\n            return value;\n        } else if (!this.asyncFlowControl(args, scope)) {\n            throw new Entry.Utils.AsyncError();\n        }\n    }\n\n    afterSend(data) {\n        // Object.assign(data, {\n        //     OUTPUT: {},\n        // });\n    }\n\n    afterReceive({ blockId = '', RADIO }) {\n        if (blockId in this.blockIds) {\n            this.blockIds[blockId] = true;\n        } else if (RADIO && Entry.engine.isState('run') && RADIO.time > this.radioTime) {\n            this.radioTime = RADIO.time;\n            Entry.engine.fireEvent('MicrobitRadioReceive');\n        }\n    }\n})();\nEntry.Microbit.blockMenuBlocks = [\n    //region microbit\n    'microbit_led_toggle',\n    'microbit_get_led',\n    'microbit_show_string',\n    'microbit_show_image',\n    'microbit_get_analog',\n    'microbit_get_analog_map',\n    'microbit_get_digital',\n    'microbit_get_button',\n    'microbit_get_sensor',\n    'microbit_get_accelerometer',\n    'microbit_play_note',\n    'microbit_change_bpm',\n    'microbit_set_bpm',\n    // \"microbit_radio_receive_event\",\n    //endregion microbit\n];\nEntry.Microbit.getBlocks = function () {\n    return {\n        microbit_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: 'LED의 X:%1 Y:%2 %3 %4',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', 'on'],\n                        ['끄기', 'off'],\n                        ['반전', 'toggle'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'MicrobitLed',\n            isNotFor: ['microbit'],\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'microbit_led_toggle',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                VALUE: 2,\n            },\n            func(sprite, script) {\n                const value = script.getField('VALUE');\n                let x = script.getNumberValue('X');\n                let y = script.getNumberValue('Y');\n                x = Math.max(0, x);\n                x = Math.min(4, x);\n                y = Math.max(0, y);\n                y = Math.min(4, y);\n                const data = {\n                    type: 'SET_LED',\n                    data: {\n                        x,\n                        y,\n                        value,\n                    },\n                };\n                return Entry.Microbit.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        microbit_get_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: 'LED의 X:%1 Y:%2 상태값',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            class: 'MicrobitLed',\n            isNotFor: ['microbit'],\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'microbit_get_led',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n            },\n            func(sprite, script) {\n                let x = script.getNumberValue('X');\n                let y = script.getNumberValue('Y');\n                x = Math.max(0, x);\n                x = Math.min(4, x);\n                y = Math.max(0, y);\n                y = Math.min(4, y);\n                const data = {\n                    type: 'GET_LED',\n                    data: {\n                        x,\n                        y,\n                    },\n                };\n                let returnData = Entry.Microbit.checkValue({\n                    script,\n                    data,\n                    key: `LED.${x}.${y}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['LED']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `LED.${x}.${y}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        microbit_show_string: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '%1 출력하기 %2',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'MicrobitLed',\n            isNotFor: ['microbit'],\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['Hello!'],\n                    },\n                ],\n                type: 'microbit_show_string',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                let value = script.getStringValue('VALUE');\n                value = value.replace(\n                    /[^A-Za-z0-9_\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\\\\\{\\}\\[\\]\\'\\\"\\;\\:\\<\\,\\>\\.\\?\\/\\s]/gim,\n                    ''\n                );\n                const data = {\n                    type: 'SET_STRING',\n                    data: {\n                        value,\n                    },\n                };\n                return Entry.Microbit.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        microbit_show_image: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            template: '%1 아이콘 출력하기 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['하트', 0],\n                        ['행복함', 4],\n                        ['삼각형', 32],\n                        ['사각형', 37],\n                        ['다이아몬드', 35],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'MicrobitLed',\n            isNotFor: ['microbit'],\n            def: {\n                type: 'microbit_show_image',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.getField('VALUE');\n                const data = {\n                    type: 'SET_IMAGE',\n                    data: {\n                        value,\n                    },\n                };\n                return Entry.Microbit.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        microbit_get_analog: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '아날로그 핀 %1번 센서값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P0', 7],\n                        ['P1', 8],\n                        ['P2', 9],\n                    ],\n                    value: 7,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'MicrobitAnalog',\n            isNotFor: ['microbit'],\n            def: {\n                type: 'microbit_get_analog',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_ANALOG',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Microbit.checkValue({\n                    script,\n                    data,\n                    key: `GET_ANALOG.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_ANALOG']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_ANALOG.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        microbit_get_analog_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '아날로그 핀 %1번 센서값의 범위를 %2~%3 에서 %4~%5 (으)로 바꾼값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P0', 7],\n                        ['P1', 8],\n                        ['P2', 9],\n                    ],\n                    value: 7,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            class: 'MicrobitAnalog',\n            isNotFor: ['microbit'],\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'microbit_get_analog_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            func(sprite, script) {\n                const value = script.getField('PORT');\n                const data = {\n                    type: 'GET_ANALOG',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Microbit.checkValue({\n                    script,\n                    data,\n                    key: `GET_ANALOG.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_ANALOG']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_ANALOG.${value}`, returnData);\n                }\n\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                returnData -= value2;\n                returnData = returnData * ((value5 - value4) / (value3 - value2));\n                returnData += value4;\n                returnData = Math.min(value5, returnData);\n                returnData = Math.max(value4, returnData);\n\n                if (isFloat) {\n                    returnData = Math.round(returnData * 100) / 100;\n                } else {\n                    returnData = Math.round(returnData);\n                }\n                return returnData;\n            },\n        },\n        microbit_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '디지털 핀 %1번 센서값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P0', 7],\n                        ['P1', 8],\n                        ['P2', 9],\n                    ],\n                    value: 7,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'MicrobitDigital',\n            isNotFor: ['microbit'],\n            def: {\n                type: 'microbit_get_digital',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_DIGITAL',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Microbit.checkValue({\n                    script,\n                    data,\n                    key: `GET_DIGITAL.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_DIGITAL']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_DIGITAL.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        microbit_get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '%1버튼을 눌렀는가?',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 1],\n                        ['B', 2],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'MicrobitButton',\n            isNotFor: ['microbit'],\n            def: {\n                type: 'microbit_get_button',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_BUTTON',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Microbit.checkValue({\n                    script,\n                    data,\n                    key: `GET_BUTTON.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_BUTTON']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_BUTTON.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        microbit_get_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1 센서값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빛', 'lightLevel'],\n                        ['온도', 'temperature'],\n                        ['자기', 'compassHeading'],\n                    ],\n                    value: 'temperature',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'MicrobitSensor',\n            isNotFor: ['microbit'],\n            def: {\n                type: 'microbit_get_sensor',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_SENSOR',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Microbit.checkValue({\n                    script,\n                    data,\n                    key: `GET_SENSOR.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_SENSOR']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_SENSOR.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        microbit_get_accelerometer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '가속도 센서 %1의 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x축', 0],\n                        ['y축', 1],\n                        ['z축', 2],\n                        ['크기', 3],\n                    ],\n                    value: 'x',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            class: 'MicrobitAccelerometer',\n            isNotFor: ['microbit'],\n            def: {\n                type: 'microbit_get_accelerometer',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.getField('VALUE');\n                const data = {\n                    type: 'GET_ACCELEROMETER',\n                    data: {\n                        value,\n                    },\n                };\n                let returnData = Entry.Microbit.checkValue({\n                    script,\n                    data,\n                    key: `GET_ACCELEROMETER.${value}`,\n                });\n                if (!returnData) {\n                    returnData = _get(Entry.hw.portData, ['GET_ACCELEROMETER']);\n                    const { executor } = script;\n                    const { scope } = executor;\n                    if (!scope.cacheValue) {\n                        scope.cacheValue = {};\n                    }\n                    _set(scope.cacheValue, `GET_ACCELEROMETER.${value}`, returnData);\n                }\n                return returnData;\n            },\n        },\n        microbit_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            statements: [],\n            template: '%1음을 %2박자 연주하기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Low C', 131],\n                        ['Low C#', 139],\n                        ['Low D', 147],\n                        ['Low Eb', 156],\n                        ['Low E', 165],\n                        ['Low F', 175],\n                        ['Low F#', 185],\n                        ['Low G', 196],\n                        ['Low G#', 208],\n                        ['Low A', 220],\n                        ['Low Bb', 233],\n                        ['Low B', 247],\n                        ['Middle C', 262],\n                        ['Middle C#', 277],\n                        ['Middle D', 294],\n                        ['Middle Eb', 311],\n                        ['Middle E', 330],\n                        ['Middle F', 349],\n                        ['Middle F#', 370],\n                        ['Middle G', 392],\n                        ['Middle G#', 415],\n                        ['Middle A', 440],\n                        ['Middle Bb', 466],\n                        ['Middle B', 494],\n                        ['High C', 523],\n                        ['High C#', 555],\n                        ['High D', 587],\n                        ['High Eb', 622],\n                        ['High E', 659],\n                        ['High F', 698],\n                        ['High F#', 740],\n                        ['High G', 784],\n                        ['High G#', 831],\n                        ['High A', 880],\n                        ['High Bb', 932],\n                        ['High B', 988],\n                    ],\n                    value: 262,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['1/2', 2],\n                        ['1/4', 4],\n                        ['1/8', 8],\n                        ['1/16', 16],\n                        ['2', 32],\n                        ['4', 64],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'MicrobitNote',\n            isNotFor: ['microbit'],\n            def: {\n                type: 'microbit_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                BEAT: 1,\n            },\n            func(sprite, script) {\n                const note = script.getField('NOTE');\n                const beat = script.getField('BEAT');\n                const data = {\n                    type: 'PLAY_NOTE',\n                    data: {\n                        note,\n                        beat,\n                    },\n                };\n                return Entry.Microbit.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        microbit_change_bpm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            statements: [],\n            template: '연주 속도를 %1BPM 만큼 바꾸기 %2',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'MicrobitNote',\n            isNotFor: ['microbit'],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [20],\n                    },\n                ],\n                type: 'microbit_change_bpm',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.getNumberValue('VALUE');\n                const data = {\n                    type: 'CHANGE_BPM',\n                    data: {\n                        value,\n                    },\n                };\n                return Entry.Microbit.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        microbit_set_bpm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            statements: [],\n            template: '연주 속도를 %1BPM으로 정하기 %2',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            class: 'MicrobitNote',\n            isNotFor: ['microbit'],\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [120],\n                    },\n                ],\n                type: 'microbit_set_bpm',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                const value = script.getNumberValue('VALUE');\n                const data = {\n                    type: 'SET_BPM',\n                    data: {\n                        value,\n                    },\n                };\n                return Entry.Microbit.postCallReturn({\n                    script,\n                    data,\n                });\n            },\n        },\n        microbit_radio_receive_event: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_event',\n            statements: [],\n            template: '%1라디오를 수신했을 때',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/start_icon_hardware.svg',\n                    size: 14,\n                    position: { x: 0, y: -2 },\n                },\n            ],\n            def: { params: [], type: 'microbit_radio_receive_event' },\n            paramsKeyMap: {},\n            class: 'MicrobitRadio',\n            isNotFor: ['microbit'],\n            event: 'MicrobitRadioReceive',\n            func(sprite, script) {\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n    };\n};\n\nmodule.exports = Entry.Microbit;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_microbit2.js",
    "content": "'use strict';\n\nconst _clamp = require('lodash/clamp');\nconst _throttle = require('lodash/throttle');\n\nconst EVENT_INTERVAL = 150;\n\nEntry.Microbit2 = new (class Microbit2 {\n    constructor() {\n        this.functionKeys = {\n            GET_ANALOG: 'get-analog',\n            GET_DIGITAL: 'get-digital',\n            SET_ANALOG: 'set-analog',\n            SET_DIGITAL: 'set-digital',\n            SET_LED: 'set-pixel',\n            GET_LED: 'get-pixel',\n            RESET: 'reset',\n            PRESET_IMAGE: 'pre-image',\n            SET_CUSTOM_IMAGE: 'custom-image',\n            SET_STRING: 'print',\n            RESET_SCREEN: 'display-clear',\n            DISPLAY_ON: 'display-on',\n            DISPLAY_OFF: 'display-off',\n            SPEAKER_ON: 'speaker-on',\n            SPEAKER_OFF: 'speaker-off',\n            PLAY_TONE: 'play-tone',\n            PLAY_SOUND: 'pre-sound',\n            PLAY_MELODY: 'pre-melody',\n            GET_BTN: 'get-btn',\n            CHANGE_TEMPO: 'change-tempo',\n            GET_LOGO: 'get-touch',\n            GET_ACC: 'get-acc',\n            GET_GESTURE: 'get-gesture',\n            GET_DIRECTION: 'direction',\n            GET_FIELD_STRENGTH: 'field-strength',\n            GET_FIELD_STRENGTH_AXIS: 'field-axis-strength',\n            GET_LIGHT_LEVEL: 'light-level',\n            GET_TEMPERATURE: 'temperature',\n            GET_SOUND_LEVEL: 'sound-level',\n            SET_RADIO: 'radio-send',\n            GET_RADIO: 'radio-receive',\n            RADIO_ON: 'radio-on',\n            RADIO_OFF: 'radio-off',\n            SETTING_RADIO: 'radio-setting',\n            SET_SERVO_MILLI: 'write-period',\n            SET_SERVO_MICRO: 'write-micro-period',\n            SET_SERVO_ANGLE: 'servo-write',\n        };\n\n        this.presetImage = [\n            // Image.HEART\n            '09090:99999:99999:09990:00900',\n            // Image.HEART_SMALL,\n            '00000:09090:09990:00900:00000',\n            // Image.HAPPY,\n            '00000:09090:00000:90009:09990',\n            // Image.SMILE,\n            '00000:00000:00000:90009:09990',\n            // Image.SAD,\n            '00000:09090:00000:09990:90009',\n            // Image.CONFUSED,\n            '00000:09090:00000:09090:90909',\n            // Image.ANGRY,\n            '90009:09090:00000:99999:90909',\n            // Image.ASLEEP,\n            '00000:99099:00000:09990:00000',\n            // Image.SURPRISED,\n            '09090:00000:00900:09090:00900',\n            // Image.SILLY,\n            '90009:00000:99999:00909:00999',\n            // Image.FABULOUS,\n            '99999:99099:00000:09090:09990',\n            // Image.MEH,\n            '09090:00000:00090:00900:09000',\n            // Image.YES,\n            '00000:00009:00090:90900:09000',\n            // Image.NO,\n            '90009:09090:00900:09090:90009',\n            // Image.CLOCK1,\n            '00090:00090:00900:00000:00000',\n            // Image.CLOCK2,\n            '00000:00990:00900:00000:00000',\n            // Image.CLOCK3,\n            '00000:00000:00999:00000:00000',\n            // Image.CLOCK4,\n            '00000:00000:00900:00990:00000',\n            // Image.CLOCK5,\n            '00000:00000:00900:00090:00090',\n            // Image.CLOCK6,\n            '00000:00000:00900:00900:00900',\n            // Image.CLOCK7,\n            '00000:00000:00900:09000:09000',\n            // Image.CLOCK8,\n            '00000:00000:00900:99000:00000',\n            // Image.CLOCK9,\n            '00000:00000:99900:00000:00000',\n            // Image.CLOCK10,\n            '00000:09900:00900:00000:00000',\n            // Image.CLOCK11,\n            '09000:09000:00900:00000:00000',\n            // Image.CLOCK12,\n            '00900:00900:00900:00000:00000',\n            // Image.ARROW_N,\n            '00900:09990:90909:00900:00900',\n            // Image.ARROW_NE,\n            '00999:00099:00909:09000:90000',\n            // Image.ARROW_E,\n            '00900:00090:99999:00090:00900',\n            // Image.ARROW_SE,\n            '90000:09000:00909:00099:00999',\n            // Image.ARROW_S,\n            '00900:00900:90909:09990:00900',\n            // Image.ARROW_SW,\n            '00009:00090:90900:99000:99900',\n            // Image.ARROW_W,\n            '00900:09000:99999:09000:00900',\n            // Image.ARROW_NW,\n            '99900:99000:90900:00090:00009',\n            // Image.TRIANGLE,\n            '00000:00900:09090:99999:00000',\n            // Image.TRIANGLE_LEFT,\n            '90000:99000:90900:90090:99999',\n            // Image.CHESSBOARD,\n            '09090:90909:09090:90909:09090',\n            // Image.DIAMOND,\n            '00900:09090:90009:09090:00900',\n            // Image.DIAMOND_SMALL,\n            '00000:00900:09090:00900:00000',\n            // Image.SQUARE,\n            '99999:90009:90009:90009:99999',\n            // Image.SQUARE_SMALL,\n            '00000:09990:09090:09990:00000',\n            // Image.RABBIT,\n            '90900:90900:99990:99090:99990',\n            // Image.COW,\n            '90009:90009:99999:09990:00900',\n            // Image.MUSIC_CROTCHET,\n            '00900:00900:00900:99900:99900',\n            // Image.MUSIC_QUAVER,\n            '00900:00990:00909:99900:99900',\n            // Image.MUSIC_QUAVERS,\n            '09999:09009:09009:99099:99099',\n            // Image.PITCHFORK,\n            '90909:90909:99999:00900:00900',\n            // Image.XMAS,\n            '00900:09990:00900:09990:99999',\n            // Image.PACMAN,\n            '099999:99090:99900:99990:09999',\n            // Image.TARGET,\n            '00900:09990:99099:09990:00900',\n            // Image.TSHIRT,\n            '99099:99999:09990:09990:09990',\n            // Image.ROLLERSKATE,\n            '00099:00099:99999:99999:09090',\n            // Image.DUCK,\n            '00990:99900:09999:09990:00000',\n            // Image.HOUSE,\n            '00900:09990:99999:09990:09090',\n            // Image.TORTOISE,\n            '00000:09990:99999:09090:00000',\n            // Image.BUTTERFLY,\n            '99099:99999:00900:99999:99099',\n            // Image.STICKFIGURE,\n            '00900:99999:00900:09090:90009',\n            // Image.GHOST,\n            '99999:90909:99999:99999:90909',\n            // Image.SWORD,\n            '00900:00900:00900:09990:00900',\n            // Image.GIRAFFE,\n            '99000:09000:09000:09990:09090',\n            // Image.SKULL,\n            '09990:90909:99999:09990:09990',\n            // Image.UMBRELLA,\n            '09990:99999:00900:90900:09900',\n            // Image.SNAKE,\n            '99000:99099:09090:09990:00000',\n        ];\n        this.id = '22.3';\n        this.url = 'http://microbit.org/ko/';\n        this.imageName = 'microbit2.png';\n        this.title = {\n            en: 'Microbit V2',\n            ko: '마이크로비트 V2',\n        };\n        this.name = 'microbit2';\n        this.communicationType = 'manual';\n        this.commandStatus = {};\n        this.commandValue = {};\n        this.digitalPins = [\n            ['P8', 8],\n            ['P9', 9],\n            ['P12', 12],\n            ['P13', 13],\n            ['P14', 14],\n            ['P15', 15],\n            ['P16', 16],\n        ];\n        this.analogPins = [\n            ['P0', 0],\n            ['P1', 1],\n            ['P2', 2],\n            ['P3', 3],\n            ['P4', 4],\n            ['P10', 10],\n        ];\n        this.majorPins = [\n            ['P0', 0],\n            ['P1', 1],\n            ['P2', 2],\n        ];\n        this.ledRows = [\n            [0, 0],\n            [1, 1],\n            [2, 2],\n            [3, 3],\n            [4, 4],\n        ];\n        this.defaultLed = [\n            [0, 0, 0, 0, 0],\n            [0, 9, 0, 9, 0],\n            [0, 0, 0, 0, 0],\n            [9, 0, 0, 0, 9],\n            [0, 9, 9, 9, 0],\n        ];\n        this.blockMenuBlocks = [\n            'microbit2_common_title',\n            'microbit2_get_analog',\n            'microbit2_set_analog',\n            'microbit2_get_digital',\n            'microbit2_set_digital',\n            'microbit2_screen_toggle',\n            'microbit2_set_led',\n            'microbit2_get_led',\n            'microbit2_show_custom_image',\n            'microbit2_show_string',\n            'microbit2_show_preset_image',\n            'microbit2_reset_screen',\n            'microbit2_radio_toggle',\n            'microbit2_radio_setting',\n            'microbit2_radio_send',\n            'microbit2_radio_received',\n            'microbit2_change_tempo',\n            'microbit2_set_tone',\n            'microbit2_play_preset_music',\n            'microbit2_get_btn',\n            'microbit2_get_acc',\n            'microbit2_get_gesture',\n            'microbit2_get_direction',\n            'microbit2_get_field_strength_axis',\n            'microbit2_get_light_level',\n            'microbit2_get_temperature',\n            'microbit2_set_servo',\n            'microbit2_set_pwm',\n            'microbit2_v2_title',\n            'microbit2_btn_event',\n            'microbit2_get_logo',\n            'microbit2_speaker_toggle',\n            'microbit2_play_sound_effect',\n            'microbit2_get_sound_level',\n        ];\n        this.version = '2';\n        this.firePressedBtnEventWithThrottle = _throttle(\n            (pressedBtn) => {\n                Entry.engine.fireEventWithValue('microbit_btn_pressed', pressedBtn);\n            },\n            EVENT_INTERVAL,\n            { leading: true, trailing: false }\n        );\n    }\n\n    setZero() {\n        // 엔트리 정지시 하드웨어 초기화 로직\n        this.requestCommand(this.functionKeys.RESET);\n        this.commandStatus = {};\n        this.commandValue = {};\n    }\n\n    // will not use in this module\n    requestCommand(type, payload) {\n        Entry.hw.sendQueue = {\n            type,\n            payload,\n        };\n        Entry.hw.update();\n    }\n    waitMilliSec(milli) {\n        this.blockReq = true;\n        setTimeout(() => {\n            this.blockReq = false;\n        }, milli);\n    }\n\n    /**\n     * command 요청 후 데이터 송수신이 끝날 때까지 대기한다.\n     * @param type\n     * @param payload\n     */\n    requestCommandWithResponse({ id, command: type, payload }) {\n        if (this.blockReq) {\n            throw new Entry.Utils.AsyncError();\n        }\n        const codeId = this.generateCodeId(id, type, payload);\n        if (!this.commandStatus[codeId]) {\n            // 첫 진입시 무조건 AsyncError\n            Entry.hw.sendQueue = {\n                type,\n                payload,\n            };\n\n            this.commandStatus[codeId] = 'pending';\n            Entry.hw.sendQueue.codeId = codeId;\n            Entry.hw.update();\n            throw new Entry.Utils.AsyncError();\n        } else if (this.commandStatus[codeId] === 'pending') {\n            // 두 번째 이상의 진입시도이며 작업이 아직 끝나지 않은 경우\n            throw new Entry.Utils.AsyncError();\n        } else if (this.commandStatus[codeId] === 'completed') {\n            // 두 번째 이상의 진입시도이며 pending 도 아닌 경우\n            // 블록 func 로직에서 다음 데이터를 처리한다.\n            delete this.commandStatus[codeId];\n        }\n    }\n\n    generateCodeId(entityId, type, payload) {\n        return `${entityId}-${type}${payload ? '-' + payload : ''}`;\n    }\n\n    afterReceive(portData) {\n        if (portData) {\n            let codeId = portData.recentlyWaitDone;\n            let value = portData.result;\n            if (value && value.indexOf('localdata') > -1) {\n                const version = value.split(';')[1];\n                if (!version) {\n                    return;\n                }\n                const major = version[0];\n                if (this.version !== major) {\n                    this.version = major;\n                }\n\n                // INFO: A,B 버튼이벤트 관련 로직\n                const pressedBtn = value.split(':btn:')[1];\n                if (pressedBtn) {\n                    // INFO: 이벤트 중복발생 방지를 위한 쓰로틀링\n                    this.firePressedBtnEventWithThrottle(pressedBtn);\n                }\n            } else if (codeId) {\n                if (codeId.indexOf('reset') > -1) {\n                    this.commandStatus = {};\n                    this.commandValue = {};\n                    return;\n                }\n                this.commandStatus[codeId] = 'completed';\n                this.commandValue[codeId] = value || 'DONE';\n            }\n        }\n\n        if (!Entry.engine.isState('run')) {\n            this.commandStatus = {};\n        }\n    }\n\n    // 언어 적용\n    setLanguage() {\n        return {\n            ko: {\n                template: {\n                    microbit2_get_analog: '핀 %1 번 아날로그 값',\n                    microbit2_set_analog: '핀 %1 에 아날로그 값 %2 를 출력하기 %3',\n                    microbit2_get_digital: '핀 %1 번 디지털 값',\n                    microbit2_set_digital: '핀 %1 에 디지털 값 %2 를 출력하기 %3',\n                    microbit2_screen_toggle: 'LED 기능 %1 %2',\n                    microbit2_set_led: 'LED의 X: %1 Y: %2 를 밝기 %3 (으)로 밝히기 %4',\n                    microbit2_get_led: 'LED의 X: %1 Y: %2 밝기 값',\n                    microbit2_show_preset_image: 'LED에 %1 모양 나타내기 %2',\n                    microbit2_show_custom_image: 'LED %1 밝히기 %2',\n                    microbit2_show_string: 'LED에 %1 을(를) 나타내기 %2',\n                    microbit2_reset_screen: 'LED 모두 %1 %2',\n                    microbit2_radio_toggle: '라디오 기능 %1 %2',\n                    microbit2_radio_setting: '라디오 채널을 %1 (으)로 바꾸기 %2',\n                    microbit2_radio_send: '라디오로 %1 송신하기 %2',\n                    microbit2_radio_received: '라디오 수신 값',\n                    microbit2_speaker_toggle: '스피커 기능 %1 %2',\n                    microbit2_change_tempo: '연주 속도를 %1 박에 %2 BPM으로 정하기 %3',\n                    microbit2_set_tone: '%1 음을 %2 박만큼 연주하기 %3',\n                    microbit2_play_preset_music: '%1 음악을 연주하기 %2',\n                    microbit2_play_sound_effect: '%1 효과음을 연주하기 %2',\n                    microbit2_btn_event: '%1 %2 버튼을 눌렀을 때',\n                    microbit2_get_btn: '%1 버튼이 눌렸는가?',\n                    microbit2_get_logo: '로고를 터치했는가?',\n                    microbit2_get_gesture: '움직임이 %1 인가?',\n                    microbit2_get_acc: '%1 의 가속도',\n                    microbit2_get_direction: '나침반 방향',\n                    microbit2_get_field_strength_axis: '%1 의 자기장 세기 값',\n                    microbit2_get_light_level: '빛 센서 값',\n                    microbit2_get_temperature: '온도',\n                    microbit2_get_sound_level: '마이크 소리 크기',\n                    microbit2_set_servo: '핀 %1 에 서보 모터 각도를 %2 로 정하기 %3',\n                    microbit2_set_pwm: '핀 %1 에 서보 펄스 폭을 %2 %3초로 정하기 %4',\n                    microbit2_common_title: '마이크로비트 공통',\n                    microbit2_v2_title: '마이크로비트 V2 전용',\n                },\n                Blocks: {\n                    octave: '옥타브',\n                    scalar: '스칼라',\n                    xAxis: 'X축',\n                    yAxis: 'Y축',\n                    zAxis: 'Z축',\n                    up: '위',\n                    down: '아래',\n                    left: '왼쪽',\n                    right: '오른쪽',\n                    face_up: '앞면',\n                    face_down: '뒷면',\n                    freefall: '자유 낙하',\n                    '3g': '3G',\n                    '6g': '6G',\n                    '8g': '8G',\n                    shake: '흔들림',\n                    DADADADUM: '운명 교향곡',\n                    ENTERTAINER: '엔터테이너',\n                    PRELUDE: '바흐 프렐류드 1번',\n                    ODE: '합창 교향곡',\n                    NYAN: '냥캣',\n                    RINGTONE: '벨소리',\n                    FUNK: '펑크',\n                    BLUES: '블루스',\n                    BIRTHDAY: '생일 축하합니다',\n                    WEDDING: '결혼 행진곡',\n                    FUNERAL: '장례식 노래',\n                    PUNCHLINE: '펀치라인',\n                    PYTHON: '서커스',\n                    BADDY: '악당',\n                    CHASE: '추격전',\n                    BA_DING: '동전 GET',\n                    WAWAWAWAA: '실망',\n                    JUMP_UP: '위로 점프',\n                    JUMP_DOWN: '아래로 점프',\n                    POWER_UP: '켜기',\n                    POWER_DOWN: '끄기',\n                    GIGGLE: '웃음',\n                    HAPPY: '행복',\n                    HELLO: '인사',\n                    MYSTERIOUS: '신비로움',\n                    SAD: '슬픔',\n                    SLIDE: '슬라이드',\n                    SOARING: '상승',\n                    SPRING: '봄',\n                    TWINKLE: '반짝반짝',\n                    YAWN: '하품',\n                    plot: '켜기',\n                    unplot: '끄기',\n                    on: '켜기',\n                    off: '끄기',\n                    remove: '지우기',\n                    light: '밝히기',\n                    microbit_2_HEART: '하트',\n                    microbit_2_HEART_SMALL: '작은 하트',\n                    microbit_2_HAPPY: '행복',\n                    microbit_2_SMILE: '웃음',\n                    microbit_2_SAD: '슬픔',\n                    microbit_2_CONFUSED: '혼란',\n                    microbit_2_ANGRY: '화남',\n                    microbit_2_ASLEEP: '졸림',\n                    microbit_2_SURPRISED: '놀람',\n                    microbit_2_SILLY: '메롱',\n                    microbit_2_FABULOUS: '환상적인',\n                    microbit_2_MEH: '별로',\n                    microbit_2_YES: '예스',\n                    microbit_2_NO: '노',\n                    microbit_2_TRIANGLE: '삼각형',\n                    microbit_2_TRIANGLE_LEFT: '왼쪽 삼각형',\n                    microbit_2_CHESSBOARD: '체스판',\n                    microbit_2_DIAMOND: '다이아몬드',\n                    microbit_2_DIAMOND_SMALL: '작은 다이아몬드',\n                    microbit_2_SQUARE: '사각형',\n                    microbit_2_SQUARE_SMALL: '작은 사각형',\n                    microbit_2_RABBIT: '토끼',\n                    microbit_2_COW: '소',\n                    microbit_2_MUSIC_CROTCHET: '4분음표',\n                    microbit_2_MUSIC_QUAVER: '8분음표',\n                    microbit_2_MUSIC_QUAVERS: '8분음표 2개',\n                    microbit_2_PITCHFORK: '쇠스랑',\n                    microbit_2_XMAS: '크리스마스 트리',\n                    microbit_2_PACMAN: '팩맨',\n                    microbit_2_TARGET: '표적',\n                    microbit_2_TSHIRT: '티셔츠',\n                    microbit_2_ROLLERSKATE: '롤러스케이트',\n                    microbit_2_DUCK: '오리',\n                    microbit_2_HOUSE: '집',\n                    microbit_2_TORTOISE: '거북이',\n                    microbit_2_BUTTERFLY: '나비',\n                    microbit_2_STICKFIGURE: '스틱맨',\n                    microbit_2_GHOST: '유령',\n                    microbit_2_SWORD: '칼',\n                    microbit_2_GIRAFFE: '기린',\n                    microbit_2_SKULL: '해골',\n                    microbit_2_UMBRELLA: '우산',\n                    microbit_2_SNAKE: '뱀',\n                    microbit_2_CLOCK1: '1시',\n                    microbit_2_CLOCK2: '2시',\n                    microbit_2_CLOCK3: '3시',\n                    microbit_2_CLOCK4: '4시',\n                    microbit_2_CLOCK5: '5시',\n                    microbit_2_CLOCK6: '6시',\n                    microbit_2_CLOCK7: '7시',\n                    microbit_2_CLOCK8: '8시',\n                    microbit_2_CLOCK9: '9시',\n                    microbit_2_CLOCK10: '10시',\n                    microbit_2_CLOCK11: '11시',\n                    microbit_2_CLOCK12: '12시',\n                    microbit_2_ARROW_N: '북쪽',\n                    microbit_2_ARROW_NE: '북동쪽',\n                    microbit_2_ARROW_E: '동쪽',\n                    microbit_2_ARROW_SE: '남동쪽',\n                    microbit_2_ARROW_S: '남쪽',\n                    microbit_2_ARROW_SW: '남서쪽',\n                    microbit_2_ARROW_W: '서쪽',\n                    microbit_2_ARROW_NW: '북서쪽',\n                },\n                Helper: {\n                    microbit2_get_analog: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)',\n                    microbit2_set_analog: '선택한 핀에 입력한 아날로그 값을 출력합니다. (0 ~ 1023)',\n                    microbit2_get_digital: '선택한 핀의 디지털 값입니다. (0, 1)',\n                    microbit2_set_digital: '선택한 핀에 입력한 디지털 값을 출력합니다. (0, 1)',\n                    microbit2_screen_toggle: 'LED 기능을 켜거나 끕니다.',\n                    microbit2_set_led: 'X, Y 좌표로 선택한 LED를 선택한 밝기로 켭니다.',\n                    microbit2_get_led: 'X, Y 좌표로 선택한 LED의 밝기 값입니다.',\n                    microbit2_show_preset_image: 'LED에 미리 설정되어 있는 모양을 나타냅니다.',\n                    microbit2_show_custom_image:\n                        '블록에서 선택한 LED를 선택한 밝기로 밝힙니다. 한 번에 모든 LED를 조작할 수 있습니다.',\n                    microbit2_show_string: '입력한 문자열을 LED에 차례대로 밝힙니다.',\n                    microbit2_reset_screen: 'LED를 모두 지우거나 밝힙니다.',\n                    microbit2_radio_toggle: '라디오 기능을 켜거나 끕니다.',\n                    microbit2_radio_setting: '라디오 채널을 입력한 숫자로 바꿉니다.',\n                    microbit2_radio_send: '라디오로 입력한 영문과 숫자를 송신합니다.',\n                    microbit2_radio_received: '라디오로 수신된 값입니다.',\n                    microbit2_speaker_toggle: '스피커 기능을 켜거나 끕니다.',\n                    microbit2_change_tempo: '연주 속도를 선택한 박자와 BPM으로 정합니다.',\n                    microbit2_set_tone:\n                        '선택한 음을 선택한 박만큼 연주합니다. 1~5옥타브 사이의 음계를 선택할 수 있습니다.',\n                    microbit2_play_preset_music: '미리 설정되어 있는 음악을 연주합니다.',\n                    microbit2_play_sound_effect: '미리 설정되어 있는 효과음을 연주합니다.',\n                    microbit2_btn_event: '선택한 버튼이 눌리면 아래에 연결된 블록들을 실행합니다.',\n                    microbit2_get_btn: \"선택한 버튼이 눌렸다면 '참'으로 판단합니다.\",\n                    microbit2_get_logo: \"로고를 터치했다면 '참'으로 판단합니다.\",\n                    microbit2_get_gesture: \"선택한 움직임이 감지되면 '참'으로 판단합니다.\",\n                    microbit2_get_acc: '선택한 축의 가속도 값입니다.',\n                    microbit2_get_direction: '나침반 방향 값입니다. (0~360) ',\n                    microbit2_get_field_strength_axis: '선택한 축의 자기장 세기 값입니다.',\n                    microbit2_get_light_level: '빛 센서의 값입니다.',\n                    microbit2_get_temperature: '현재 온도 값입니다. (℃)',\n                    microbit2_get_sound_level: '마이크 소리 크기 값입니다.',\n                    microbit2_set_servo: '선택한 핀에 서보 모터 각도를 입력한 값으로 정합니다.',\n                    microbit2_set_pwm: '선택한 핀의 서보 펄스폭을 선택한 시간으로 정합니다.',\n                },\n                Msgs: {\n                    microbit2_compatible_error: '마이크로비트 V2에서만 사용할 수 있는 블록입니다.',\n                    microbit2_octave: '옥타브',\n                },\n            },\n            en: {\n                template: {\n                    microbit2_get_analog: 'analog read pin %1',\n                    microbit2_set_analog: 'Set analog pin %1 to %2 %3',\n                    microbit2_get_digital: 'digital read pin %1',\n                    microbit2_set_digital: 'Set digital pin %1 to %2 %3',\n                    microbit2_screen_toggle: '%1 LED screen %2',\n                    microbit2_set_led: 'Light X: %1 Y:%2 LED to brightness %3 %4',\n                    microbit2_get_led: 'brightness of X: %1 Y: %2 LED %3',\n                    microbit2_show_preset_image: 'Light %1 icon on LED %2',\n                    microbit2_show_custom_image: 'Light %1 on LED %2',\n                    microbit2_show_string: 'Light string %1 on LED %2',\n                    microbit2_reset_screen: '%1 all on LED %2',\n                    microbit2_radio_toggle: '%1 radio %2',\n                    microbit2_radio_setting: 'Change radio channel to %1 %2',\n                    microbit2_radio_send: 'Send %1 to radio %2',\n                    microbit2_radio_received: 'radio received value',\n                    microbit2_speaker_toggle: '%1 speaker %2',\n                    microbit2_change_tempo: 'Set tempo to %2 BPM per %1 beat %3',\n                    microbit2_set_tone: 'Play melody %1 for %2 beat %3',\n                    microbit2_play_preset_music: 'Play music %1 %2',\n                    microbit2_play_sound_effect: 'Play sound %1 %2',\n                    microbit2_btn_event: '%1 When %2 button pressed',\n                    microbit2_get_btn: '%1 button pressed?',\n                    microbit2_get_logo: 'logo touched?',\n                    microbit2_get_gesture: 'Is the movement %1?',\n                    microbit2_get_acc: 'acceleration value of %1',\n                    microbit2_get_direction: 'compass direction',\n                    microbit2_get_field_strength_axis: 'magnetic field strength value of %1 ',\n                    microbit2_get_light_level: 'light sensor value',\n                    microbit2_get_temperature: 'temperature',\n                    microbit2_get_sound_level: 'microphone volume',\n                    microbit2_set_servo: 'Set servo pin %1 angle to %2 %3',\n                    microbit2_set_pwm: 'set servo pin %1 pulse to %2 %3 %4',\n                    microbit2_common_title: 'Common Blocks',\n                    microbit2_v2_title: 'v2 Only',\n                },\n                Blocks: {\n                    octave: 'octave',\n                    scalar: 'scalar',\n                    xAxis: 'X-axis',\n                    yAxis: 'Y-axis',\n                    zAxis: 'Z-axis',\n                    up: 'up',\n                    down: 'down',\n                    left: 'left',\n                    right: 'right',\n                    face_up: 'face up',\n                    face_down: 'face down',\n                    freefall: 'freefall',\n                    '3g': '3G',\n                    '6g': '6G',\n                    '8g': '8G',\n                    shake: 'shake',\n                    DADADADUM: 'Dadadadum',\n                    ENTERTAINER: 'Entertainer',\n                    PRELUDE: 'Prelude',\n                    ODE: 'Ode',\n                    NYAN: 'Nyan',\n                    RINGTONE: 'Ringtone',\n                    FUNK: 'Funk',\n                    BLUES: 'Blues',\n                    BIRTHDAY: 'Birthday',\n                    WEDDING: 'Wedding',\n                    FUNERAL: 'Funeral',\n                    PUNCHLINE: 'Punchline',\n                    PYTHON: 'Python',\n                    BADDY: 'Baddy',\n                    CHASE: 'Chase',\n                    BA_DING: 'Coin',\n                    WAWAWAWAA: 'Wawawawaa',\n                    JUMP_UP: 'Jump up',\n                    JUMP_DOWN: 'Jump down',\n                    POWER_UP: 'Power up',\n                    POWER_DOWN: 'Power down',\n                    GIGGLE: 'giggle',\n                    HAPPY: 'happy',\n                    HELLO: 'hello',\n                    MYSTERIOUS: 'mysterious',\n                    SAD: 'sad',\n                    SLIDE: 'slide',\n                    SOARING: 'soaring',\n                    SPRING: 'spring',\n                    TWINKLE: 'twinkle',\n                    YAWN: 'yawn',\n                    plot: 'plot',\n                    unplot: 'unplot',\n                    on: 'Turn on',\n                    off: 'Turn off',\n                    remove: 'Clear',\n                    light: 'Light',\n                    microbit_2_HEART: 'heart',\n                    microbit_2_HEART_SMALL: 'small heart',\n                    microbit_2_HAPPY: 'happy',\n                    microbit_2_SMILE: 'smile',\n                    microbit_2_SAD: 'sad',\n                    microbit_2_CONFUSED: 'confused',\n                    microbit_2_ANGRY: 'angry',\n                    microbit_2_ASLEEP: 'asleep',\n                    microbit_2_SURPRISED: 'surprised',\n                    microbit_2_SILLY: 'silly',\n                    microbit_2_FABULOUS: 'fabulous',\n                    microbit_2_MEH: 'meh',\n                    microbit_2_YES: 'yes',\n                    microbit_2_NO: 'no',\n                    microbit_2_TRIANGLE: 'triangle',\n                    microbit_2_TRIANGLE_LEFT: 'left triangle',\n                    microbit_2_CHESSBOARD: 'chessboard',\n                    microbit_2_DIAMOND: 'diamond',\n                    microbit_2_DIAMOND_SMALL: 'small diamond',\n                    microbit_2_SQUARE: 'square',\n                    microbit_2_SQUARE_SMALL: 'small square',\n                    microbit_2_RABBIT: 'rabbit',\n                    microbit_2_COW: 'cow',\n                    microbit_2_MUSIC_CROTCHET: 'crotchet',\n                    microbit_2_MUSIC_QUAVER: 'quaver',\n                    microbit_2_MUSIC_QUAVERS: 'quavers',\n                    microbit_2_PITCHFORK: 'pitchfork',\n                    microbit_2_XMAS: 'xmas',\n                    microbit_2_PACMAN: 'pacman',\n                    microbit_2_TARGET: 'target',\n                    microbit_2_TSHIRT: 'tshirt',\n                    microbit_2_ROLLERSKATE: 'rollerskate',\n                    microbit_2_DUCK: 'duck',\n                    microbit_2_HOUSE: 'house',\n                    microbit_2_TORTOISE: 'tortoise',\n                    microbit_2_BUTTERFLY: 'butterfly',\n                    microbit_2_STICKFIGURE: 'stickfigure',\n                    microbit_2_GHOST: 'ghost',\n                    microbit_2_SWORD: 'sword',\n                    microbit_2_GIRAFFE: 'giraffe',\n                    microbit_2_SKULL: 'skull',\n                    microbit_2_UMBRELLA: 'umbrella',\n                    microbit_2_SNAKE: 'snake',\n                    microbit_2_CLOCK1: \"1 o'clock\",\n                    microbit_2_CLOCK2: \"2 o'clock\",\n                    microbit_2_CLOCK3: \"3 o'clock\",\n                    microbit_2_CLOCK4: \"4 o'clock\",\n                    microbit_2_CLOCK5: \"5 o'clock\",\n                    microbit_2_CLOCK6: \"6 o'clock\",\n                    microbit_2_CLOCK7: \"7 o'clock\",\n                    microbit_2_CLOCK8: \"8 o'clock\",\n                    microbit_2_CLOCK9: \"9 o'clock\",\n                    microbit_2_CLOCK10: \"10 o'clock\",\n                    microbit_2_CLOCK11: \"11 o'clock\",\n                    microbit_2_CLOCK12: \"12 o'clock\",\n                    microbit_2_ARROW_N: 'north',\n                    microbit_2_ARROW_NE: 'northeast',\n                    microbit_2_ARROW_E: 'east',\n                    microbit_2_ARROW_SE: 'southeast',\n                    microbit_2_ARROW_S: 'south',\n                    microbit_2_ARROW_SW: 'southwest',\n                    microbit_2_ARROW_W: 'west',\n                    microbit_2_ARROW_NW: 'northwest',\n                },\n                Helper: {\n                    microbit2_get_analog:\n                        'Reads an analog signal from the pin you choose. (0 ~ 1023)',\n                    microbit2_set_analog:\n                        'Writes an analog signal to the pin you choose. (0 ~ 1023)',\n                    microbit2_get_digital:\n                        'Reads a digital signal from the pin you choose. (0 ~ 1023)',\n                    microbit2_set_digital: 'Writes a digital signal to the pin you choose. (0 ~ 1)',\n                    microbit2_screen_toggle: 'Turns on or turns off the LED screen.',\n                    microbit2_set_led:\n                        'Lights the selected LED with X and Y coordinates to the selected brightness.',\n                    microbit2_get_led: 'Brightness of the selected LED with X and Y coordinates',\n                    microbit2_show_preset_image: 'Lights the selected icon on the LED screen.',\n                    microbit2_show_custom_image:\n                        'Lights the selected LED and brightness. You can set all the LEDs at once.',\n                    microbit2_show_string: 'Lights the entered string in order on the LED screen.',\n                    microbit2_reset_screen: 'Clears or lights all LED screen.',\n                    microbit2_radio_toggle: 'Turns on or turns off the radio.',\n                    microbit2_radio_setting: 'Changes the radio channel to the number entered.',\n                    microbit2_radio_send: 'Sends the number or the string entered to the radio.',\n                    microbit2_radio_received: 'Value received by the radio.',\n                    microbit2_speaker_toggle: 'Turns on or turns off the speaker.',\n                    microbit2_change_tempo: 'Sets the tempo to the entered beat and BPM.',\n                    microbit2_set_tone:\n                        'Plays the entered melody for the entered beat. You can choose a scale between 1 and 5 octaves.',\n                    microbit2_play_preset_music: 'Plays preset music.',\n                    microbit2_play_sound_effect: 'Plays preset sound.',\n                    microbit2_btn_event:\n                        'When the selected button is pressed, the connected blocks below will run',\n                    microbit2_get_btn: \"If the selected button is pressed, it is judged as 'True'.\",\n                    microbit2_get_logo: \"If the logo is touched, it is judged as 'True'.\",\n                    microbit2_get_gesture:\n                        \"When the selected movement is detected, it is judged as 'True'.\",\n                    microbit2_get_acc: 'The acceleration value of the selected axis.',\n                    microbit2_get_direction: 'The compass direction value. (0~360)',\n                    microbit2_get_field_strength_axis:\n                        'The magnetic field strength value of the selected axis.',\n                    microbit2_get_light_level: 'The value of the light sensor.',\n                    microbit2_get_temperature: 'The current temperature value. (℃)',\n                    microbit2_get_sound_level: 'The microphone volume value.',\n                    microbit2_set_servo:\n                        'Sets the servo motor angle to the entered value on the selected pin.',\n                    microbit2_set_pwm:\n                        'Sets the servo pulse to the entered time on the selected pin.',\n                },\n                Msgs: {\n                    microbit2_compatible_error:\n                        'The corresponding block is not compatible to Microbit V1',\n                    microbit2_octave: 'Octave',\n                },\n            },\n            jp: {\n                template: {\n                    microbit2_get_analog: 'たんし %1 のアナログ値',\n                    microbit2_set_analog: 'たんし %1 のアナログ値 %2 を出力する %3',\n                    microbit2_get_digital: 'たんし %1 のデジタル値',\n                    microbit2_set_digital: 'たんし %1 にデジタル値 %2 を出力する %3',\n                    microbit2_screen_toggle: 'LED機能を %1 %2',\n                    microbit2_set_led: 'LEDの X: %1 Y: %2 を明るさ %3 にする %4',\n                    microbit2_get_led: 'LEDの X: %1 Y: %2 の明るさ',\n                    microbit2_show_preset_image: 'LEDに %1 アイコンを表示する %2',\n                    microbit2_show_custom_image: 'LEDに %1 を表示する %2',\n                    microbit2_show_string: 'LEDに %1 を表示する %2',\n                    microbit2_reset_screen: 'LEDを全部消す %1',\n                    microbit2_radio_toggle: 'むせん機能を %1 %2',\n                    microbit2_radio_setting: 'むせんのチャンネルを %1 に変える %2',\n                    microbit2_radio_send: 'むせんで %1 を送信する %2',\n                    microbit2_radio_received: '受信した値',\n                    microbit2_speaker_toggle: 'スピーカー機能を %1 %2',\n                    microbit2_change_tempo: '長さ %1 拍、テンポ %2 (bpm)にする %3',\n                    microbit2_set_tone: '%1 音を長さ %2 拍鳴らす %3',\n                    microbit2_play_preset_music: 'メロディ %1 を鳴らす %2',\n                    microbit2_play_sound_effect: '効果音 %1 を鳴らす %2',\n                    microbit2_get_btn: '%1 ボタンを押しているか？',\n                    microbit2_get_logo: 'ロゴをタッチしているか？',\n                    microbit2_get_gesture: '%1 か？',\n                    microbit2_get_acc: '%1 の加速度',\n                    microbit2_get_direction: '方角(°)',\n                    microbit2_get_field_strength_axis: '%1 の磁力',\n                    microbit2_get_light_level: '明るさ',\n                    microbit2_get_temperature: '温度(℃)',\n                    microbit2_get_sound_level: 'まわりの音の大きさ',\n                    microbit2_set_servo: 'たんし %1 にサーボモーターの角度 %2 を出力する %3',\n                    microbit2_set_pwm: 'たんし %1 にサーボパルス幅 %2 %3 を出力する %4',\n                    microbit2_common_title: 'Common Blocks',\n                    microbit2_v2_title: 'v2 Only',\n                },\n                Blocks: {\n                    octave: 'オクターブ',\n                    scalar: 'スカラー',\n                    xAxis: 'X軸',\n                    yAxis: 'Y軸',\n                    zAxis: 'Z軸',\n                    up: '上をむいている',\n                    down: '下をむいている',\n                    left: '右をむいている',\n                    right: '左をむいている',\n                    face_up: '表をむいている',\n                    face_down: '裏をむいている',\n                    freefall: '落ちている',\n                    '3g': 'しょうとつ（3G）',\n                    '6g': 'しょうとつ（6G）',\n                    '8g': 'しょうとつ（8G）',\n                    shake: '振った',\n                    DADADADUM: '運命交響曲',\n                    ENTERTAINER: 'エンターネーター',\n                    PRELUDE: 'バッハ·プレリュード第1番',\n                    ODE: '合唱交響曲',\n                    NYAN: 'ニャンキャット',\n                    RINGTONE: '着信メロディ',\n                    FUNK: 'ファンク',\n                    BLUES: 'ブルース',\n                    BIRTHDAY: 'お誕生日おめでとう',\n                    WEDDING: '結婚行進曲',\n                    FUNERAL: '葬式の歌',\n                    PUNCHLINE: 'パンチライン',\n                    PYTHON: 'サーカス',\n                    BADDY: '悪党',\n                    CHASE: '追撃戦',\n                    BA_DING: 'コインGET',\n                    WAWAWAWAA: 'ガッカリ',\n                    JUMP_UP: '上にジャンプ',\n                    JUMP_DOWN: '下にジャンプ',\n                    POWER_UP: '点ける',\n                    POWER_DOWN: '消す',\n                    GIGGLE: '笑い',\n                    HAPPY: '幸せ',\n                    HELLO: '挨拶',\n                    MYSTERIOUS: '神秘的',\n                    SAD: '悲しみ',\n                    SLIDE: 'スライド',\n                    SOARING: '上昇',\n                    SPRING: '春',\n                    TWINKLE: 'キラキラ',\n                    YAWN: 'あくび',\n                    plot: 'オンにする',\n                    unplot: 'オフにする',\n                    on: 'オンにする',\n                    off: 'オフにする',\n                    microbit_2_HEART: 'ハート',\n                    microbit_2_HEART_SMALL: '小さなハート',\n                    microbit_2_HAPPY: '幸せ',\n                    microbit_2_SMILE: '笑い',\n                    microbit_2_SAD: '悲しみ',\n                    microbit_2_CONFUSED: '混乱',\n                    microbit_2_ANGRY: '怒り',\n                    microbit_2_ASLEEP: '眠気',\n                    microbit_2_SURPRISED: '驚き',\n                    microbit_2_SILLY: '間抜け',\n                    microbit_2_FABULOUS: '幻想的な',\n                    microbit_2_MEH: '別に',\n                    microbit_2_YES: 'イエス',\n                    microbit_2_NO: 'ノー',\n                    microbit_2_TRIANGLE: '三角形',\n                    microbit_2_TRIANGLE_LEFT: '左三角形',\n                    microbit_2_CHESSBOARD: 'チェスパン',\n                    microbit_2_DIAMOND: 'ダイヤモンド',\n                    microbit_2_DIAMOND_SMALL: '小さなダイヤモンド',\n                    microbit_2_SQUARE: '四角形',\n                    microbit_2_SQUARE_SMALL: '小さな四角形',\n                    microbit_2_RABBIT: 'ウサギ',\n                    microbit_2_COW: '牛',\n                    microbit_2_MUSIC_CROTCHET: '4分音符',\n                    microbit_2_MUSIC_QUAVER: '8分音符',\n                    microbit_2_MUSIC_QUAVERS: '8分音符2個',\n                    microbit_2_PITCHFORK: 'フォーク',\n                    microbit_2_XMAS: 'クリスマスツリー',\n                    microbit_2_PACMAN: 'パックマン',\n                    microbit_2_TARGET: '標的',\n                    microbit_2_TSHIRT: 'Tシャツ',\n                    microbit_2_ROLLERSKATE: 'ローラースケート',\n                    microbit_2_DUCK: 'アヒル',\n                    microbit_2_HOUSE: '家',\n                    microbit_2_TORTOISE: '亀',\n                    microbit_2_BUTTERFLY: '蝶',\n                    microbit_2_STICKFIGURE: 'スティックマン',\n                    microbit_2_GHOST: '幽霊',\n                    microbit_2_SWORD: 'ナイフ',\n                    microbit_2_GIRAFFE: 'キリン',\n                    microbit_2_SKULL: '骸骨',\n                    microbit_2_UMBRELLA: '傘',\n                    microbit_2_SNAKE: '蛇',\n                    microbit_2_CLOCK1: '1時',\n                    microbit_2_CLOCK2: '2時',\n                    microbit_2_CLOCK3: '3時',\n                    microbit_2_CLOCK4: '4時',\n                    microbit_2_CLOCK5: '5時',\n                    microbit_2_CLOCK6: '6時',\n                    microbit_2_CLOCK7: '7時',\n                    microbit_2_CLOCK8: '8時',\n                    microbit_2_CLOCK9: '9時',\n                    microbit_2_CLOCK10: '10時',\n                    microbit_2_CLOCK11: '11時',\n                    microbit_2_CLOCK12: '12時',\n                    microbit_2_ARROW_N: '北',\n                    microbit_2_ARROW_NE: '北東',\n                    microbit_2_ARROW_E: '東',\n                    microbit_2_ARROW_SE: '南東',\n                    microbit_2_ARROW_S: '南',\n                    microbit_2_ARROW_SW: '南西',\n                    microbit_2_ARROW_W: '西',\n                    microbit_2_ARROW_NW: '北西',\n                },\n                Helper: {\n                    microbit2_get_analog: '選択したたんしのアナログ値です。(0 ~ 1023)',\n                    microbit2_set_analog:\n                        '選択したたんしに入力したアナログ値を出力します。(0 ~ 1023)',\n                    microbit2_get_digital: '選択したたんしのデジタル値です。(0, 1)',\n                    microbit2_set_digital: '選択したたんしに入力したデジタル値を出力します。(0, 1)',\n                    microbit2_screen_toggle: 'LED機能をオンまたはオフにします。',\n                    microbit2_set_led: 'X、Y座標で選択したLEDを選択した明るさで点けます。',\n                    microbit2_get_led: 'X、Y座標で選択したLEDの明るさです。',\n                    microbit2_show_preset_image: 'LEDに先に設定されていた形で点けます。',\n                    microbit2_show_custom_image:\n                        'ブロックで選択したLEDを選択した明るさで点けます。 一度にすべてのLEDを操作できます。',\n                    microbit2_show_string: '入力した文字列をLEDに順番に表示します。',\n                    microbit2_reset_screen: 'LEDに表示したものをすべて消します。',\n                    microbit2_radio_toggle: 'むせん機能をオンまたはオフにします。',\n                    microbit2_radio_setting: 'むせんチャンネルを入力した数字に変えます。',\n                    microbit2_radio_send: 'むせんで入力した英数字を送信します。',\n                    microbit2_radio_received: 'むせんで受信した値です。',\n                    microbit2_speaker_toggle: 'スピーカー機能をオンまたはオフにします。',\n                    microbit2_change_tempo: '長さを選択した拍子とBPMで設定します。',\n                    microbit2_set_tone:\n                        '選択した音を選択した拍子で演奏します。 1~5オクターブ間の音階を選べます。',\n                    microbit2_play_preset_music: '先に設定されていたメロディを演奏します。',\n                    microbit2_play_sound_effect: '先に設定されていた効果音を演奏します。',\n                    microbit2_get_btn: '選択したボタンが押されたら、「True」と判断します。',\n                    microbit2_get_logo: 'ロゴをタッチすると、「True」と判断します。',\n                    microbit2_get_gesture: '選択した動きを感知したら、「True」と判断します。',\n                    microbit2_get_acc: '選択した軸の加速度値です。',\n                    microbit2_get_direction: '方角(°)の値です。 (0~360)',\n                    microbit2_get_field_strength_axis: '選択した軸の磁力の値です。',\n                    microbit2_get_light_level: '明るさの値です。',\n                    microbit2_get_temperature: '現在の温度です。 (℃)',\n                    microbit2_get_sound_level: 'まわりの音の大きさの値です。',\n                    microbit2_set_servo:\n                        '選択したたんしにサーボモーターの角度を入力した値で設定します。',\n                    microbit2_set_pwm: '選択したたんしのサーボパルス幅を選択した値にします。',\n                },\n                Msgs: {\n                    microbit2_compatible_error: '対応するブロックはMicrobitV1と互換性がありません',\n                    microbit2_octave: 'Octave',\n                },\n            },\n        };\n    }\n\n    getResponse({ id, command, payload }) {\n        const codeId = this.generateCodeId(id, command, payload);\n        const parsedResponse = this.commandValue[codeId].split(';');\n        return parsedResponse;\n    }\n\n    getBlocks = function () {\n        return {\n            microbit2_common_title: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#333333',\n                template: '%1',\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.microbit2_common_title,\n                        color: '#333333',\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'microbit2_common_title',\n                },\n                class: 'microbit2Pin',\n                isNotFor: ['microbit2'],\n                events: {},\n            },\n            microbit2_v2_title: {\n                skeleton: 'basic_text',\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#333333',\n                template: '%1',\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.microbit2_v2_title,\n                        color: '#333333',\n                        align: 'center',\n                    },\n                ],\n                def: {\n                    type: 'microbit2_v2_title',\n                },\n                class: 'microbit2v2',\n                isNotFor: ['microbit2'],\n                events: {},\n            },\n            microbit2_get_analog: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: this.analogPins,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Pin',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_analog',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getValue('VALUE');\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_ANALOG,\n                        payload: value,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_get_digital: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: this.digitalPins,\n                        value: 8,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Pin',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_digital',\n                },\n                paramsKeyMap: { VALUE: 0 },\n                func: (sprite, script) => {\n                    const value = script.getValue('VALUE');\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_DIGITAL,\n                        payload: value,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_set_analog: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: this.analogPins,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Pin',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_set_analog',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                func: (sprite, script) => {\n                    const pin = script.getValue('PIN');\n                    const value = Math.round(_clamp(script.getNumberValue('VALUE'), 0, 1023));\n\n                    const parsedPayload = `${pin};${value}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_ANALOG,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return;\n                },\n            },\n            microbit2_set_digital: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: this.digitalPins,\n                        value: 8,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [0, 0],\n                            [1, 1],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Pin',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_set_digital',\n                },\n                paramsKeyMap: { PIN: 0, VALUE: 1 },\n                func: (sprite, script) => {\n                    const pin = script.getValue('PIN');\n                    const value = script.getValue('VALUE');\n                    const parsedPayload = `${pin};${value}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_DIGITAL,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return;\n                },\n            },\n            microbit2_set_led: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 0,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 0,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 9,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Led',\n                isNotFor: ['microbit2'],\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['9'],\n                        },\n                    ],\n                    type: 'microbit2_set_led',\n                },\n                paramsKeyMap: {\n                    X: 0,\n                    Y: 1,\n                    VALUE: 2,\n                },\n                func: (sprite, script) => {\n                    const value = script.getNumberValue('VALUE');\n                    const x = script.getNumberValue('X');\n                    const y = script.getNumberValue('Y');\n                    if (x < 0 || y < 0 || x > 4 || y > 4 || value < 0 || value > 9) {\n                        return;\n                    }\n                    const data = {\n                        type: this.functionKeys.SET_LED,\n                        data: {\n                            x,\n                            y,\n                            value,\n                        },\n                    };\n\n                    const parsedPayload = `${x};${y};${value}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_LED,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_get_led: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 0,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 0,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Led',\n                isNotFor: ['microbit2'],\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['0'],\n                        },\n                    ],\n                    type: 'microbit2_get_led',\n                },\n                paramsKeyMap: {\n                    X: 0,\n                    Y: 1,\n                },\n                func: (sprite, script) => {\n                    const x = script.getNumberValue('X');\n                    const y = script.getNumberValue('Y');\n                    if (x < 0 || y < 0 || x > 4 || y > 4) {\n                        return -1;\n                    }\n                    const parsedPayload = `${x};${y}`;\n\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_LED,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n\n                    if (parsedResponse[1] == 0) {\n                        return 0;\n                    } else if (parsedResponse[1] == 1) {\n                        return 1;\n                    }\n\n                    return Math.round(Math.log2(parsedResponse[1] * 2));\n                },\n            },\n            microbit2_show_preset_image: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.microbit_2_HEART, 0],\n                            [Lang.Blocks.microbit_2_HEART_SMALL, 1],\n                            [Lang.Blocks.microbit_2_HAPPY, 2],\n                            [Lang.Blocks.microbit_2_SMILE, 3],\n                            [Lang.Blocks.microbit_2_SAD, 4],\n                            [Lang.Blocks.microbit_2_CONFUSED, 5],\n                            [Lang.Blocks.microbit_2_ANGRY, 6],\n                            [Lang.Blocks.microbit_2_ASLEEP, 7],\n                            [Lang.Blocks.microbit_2_SURPRISED, 8],\n                            [Lang.Blocks.microbit_2_SILLY, 9],\n                            [Lang.Blocks.microbit_2_FABULOUS, 10],\n                            [Lang.Blocks.microbit_2_MEH, 11],\n                            [Lang.Blocks.microbit_2_YES, 12],\n                            [Lang.Blocks.microbit_2_NO, 13],\n                            [Lang.Blocks.microbit_2_TRIANGLE, 34],\n                            [Lang.Blocks.microbit_2_TRIANGLE_LEFT, 35],\n                            [Lang.Blocks.microbit_2_CHESSBOARD, 36],\n                            [Lang.Blocks.microbit_2_DIAMOND, 37],\n                            [Lang.Blocks.microbit_2_DIAMOND_SMALL, 38],\n                            [Lang.Blocks.microbit_2_SQUARE, 39],\n                            [Lang.Blocks.microbit_2_SQUARE_SMALL, 40],\n                            [Lang.Blocks.microbit_2_RABBIT, 41],\n                            [Lang.Blocks.microbit_2_COW, 42],\n                            [Lang.Blocks.microbit_2_MUSIC_CROTCHET, 43],\n                            [Lang.Blocks.microbit_2_MUSIC_QUAVER, 44],\n                            [Lang.Blocks.microbit_2_MUSIC_QUAVERS, 45],\n                            [Lang.Blocks.microbit_2_PITCHFORK, 46],\n                            [Lang.Blocks.microbit_2_XMAS, 47],\n                            [Lang.Blocks.microbit_2_PACMAN, 48],\n                            [Lang.Blocks.microbit_2_TARGET, 49],\n                            [Lang.Blocks.microbit_2_TSHIRT, 50],\n                            [Lang.Blocks.microbit_2_ROLLERSKATE, 51],\n                            [Lang.Blocks.microbit_2_DUCK, 52],\n                            [Lang.Blocks.microbit_2_HOUSE, 53],\n                            [Lang.Blocks.microbit_2_TORTOISE, 54],\n                            [Lang.Blocks.microbit_2_BUTTERFLY, 55],\n                            [Lang.Blocks.microbit_2_STICKFIGURE, 56],\n                            [Lang.Blocks.microbit_2_GHOST, 57],\n                            [Lang.Blocks.microbit_2_SWORD, 58],\n                            [Lang.Blocks.microbit_2_GIRAFFE, 59],\n                            [Lang.Blocks.microbit_2_SKULL, 60],\n                            [Lang.Blocks.microbit_2_UMBRELLA, 61],\n                            [Lang.Blocks.microbit_2_SNAKE, 62],\n                            [Lang.Blocks.microbit_2_CLOCK1, 14],\n                            [Lang.Blocks.microbit_2_CLOCK2, 15],\n                            [Lang.Blocks.microbit_2_CLOCK3, 16],\n                            [Lang.Blocks.microbit_2_CLOCK4, 17],\n                            [Lang.Blocks.microbit_2_CLOCK5, 18],\n                            [Lang.Blocks.microbit_2_CLOCK6, 19],\n                            [Lang.Blocks.microbit_2_CLOCK7, 20],\n                            [Lang.Blocks.microbit_2_CLOCK8, 21],\n                            [Lang.Blocks.microbit_2_CLOCK9, 22],\n                            [Lang.Blocks.microbit_2_CLOCK10, 23],\n                            [Lang.Blocks.microbit_2_CLOCK11, 24],\n                            [Lang.Blocks.microbit_2_CLOCK12, 25],\n                            [Lang.Blocks.microbit_2_ARROW_N, 26],\n                            [Lang.Blocks.microbit_2_ARROW_NE, 27],\n                            [Lang.Blocks.microbit_2_ARROW_E, 28],\n                            [Lang.Blocks.microbit_2_ARROW_SE, 29],\n                            [Lang.Blocks.microbit_2_ARROW_S, 30],\n                            [Lang.Blocks.microbit_2_ARROW_SW, 31],\n                            [Lang.Blocks.microbit_2_ARROW_W, 32],\n                            [Lang.Blocks.microbit_2_ARROW_NW, 33],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Led',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_show_preset_image',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = _clamp(script.getNumberValue('VALUE'), 0, 62);\n                    const parsedPayload = `${this.presetImage[value]}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_CUSTOM_IMAGE,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_show_custom_image: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Led2',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Led',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_show_custom_image',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    const processedValue = [];\n                    for (const i in value) {\n                        processedValue[i] = value[i].join();\n                    }\n                    const parsedPayload = `${processedValue.join(':').replace(/,/gi, '')}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_CUSTOM_IMAGE,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_show_string: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Led',\n                isNotFor: ['microbit2'],\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['Hello!'],\n                            accept: 'string',\n                        },\n                    ],\n                    type: 'microbit2_show_string',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    let payload = script.getStringValue('VALUE');\n                    payload = payload.replace(\n                        /[^A-Za-z0-9_\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\\\\\{\\}\\[\\]\\'\\\"\\;\\:\\<\\,\\>\\.\\?\\/\\s]/gim,\n                        ''\n                    );\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_STRING,\n                        payload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_reset_screen: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.remove, 'remove'],\n                            [Lang.Blocks.light, 'light'],\n                        ],\n                        value: 'remove',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Led',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_reset_screen',\n                },\n                paramsKeyMap: { LED_STATUS: 0 },\n                func: (sprite, script) => {\n                    const ledStatus = script.getField('LED_STATUS');\n                    let reqOptions;\n                    if (ledStatus === 'light') {\n                        const defaultLed = '99999:99999:99999:99999:99999';\n                        reqOptions = {\n                            id: script.entity.id,\n                            command: this.functionKeys.SET_CUSTOM_IMAGE,\n                            payload: defaultLed,\n                        };\n                    } else {\n                        reqOptions = {\n                            id: script.entity.id,\n                            command: this.functionKeys.RESET_SCREEN,\n                        };\n                    }\n\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_screen_toggle: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.on, this.functionKeys.DISPLAY_ON],\n                            [Lang.Blocks.off, this.functionKeys.DISPLAY_OFF],\n                        ],\n                        value: this.functionKeys.DISPLAY_ON,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Led',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_screen_toggle',\n                },\n                paramsKeyMap: { VALUE: 0 },\n                func: (sprite, script) => {\n                    const command = script.getField('VALUE');\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n\n            microbit2_change_tempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Sound',\n                isNotFor: ['microbit2'],\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['4'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['120'],\n                        },\n                    ],\n                    type: 'microbit2_change_tempo',\n                },\n                paramsKeyMap: {\n                    BEAT: 0,\n                    BPM: 1,\n                },\n                func: (sprite, script) => {\n                    const beat = Math.round(_clamp(script.getNumberValue('BEAT'), 0, 4));\n                    const bpm = Math.round(_clamp(script.getNumberValue('BPM'), 1, 230));\n\n                    const parsedPayload = `${beat};${bpm}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.CHANGE_TEMPO,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_set_tone: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'MusicScale',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['4', 16],\n                            ['2', 8],\n                            ['1', 4],\n                            ['1/2', 2],\n                            ['1/4', 1],\n                        ],\n                        value: 4,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Sound',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_set_tone',\n                },\n                paramsKeyMap: {\n                    SCALE: 0,\n                    NOTE: 1,\n                },\n                func: (sprite, script) => {\n                    const scale = script.getField('SCALE');\n                    const note = script.getField('NOTE');\n                    const parsedPayload = `${scale}:${note}`;\n\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.PLAY_TONE,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_play_preset_music: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.DADADADUM, 0],\n                            [Lang.Blocks.ENTERTAINER, 1],\n                            [Lang.Blocks.PRELUDE, 2],\n                            [Lang.Blocks.ODE, 3],\n                            [Lang.Blocks.NYAN, 4],\n                            [Lang.Blocks.RINGTONE, 5],\n                            [Lang.Blocks.FUNK, 6],\n                            [Lang.Blocks.BLUES, 7],\n                            [Lang.Blocks.BIRTHDAY, 8],\n                            [Lang.Blocks.WEDDING, 9],\n                            [Lang.Blocks.FUNERAL, 10],\n                            [Lang.Blocks.PUNCHLINE, 11],\n                            [Lang.Blocks.PYTHON, 12],\n                            [Lang.Blocks.BADDY, 13],\n                            [Lang.Blocks.CHASE, 14],\n                            [Lang.Blocks.BA_DING, 15],\n                            [Lang.Blocks.WAWAWAWAA, 16],\n                            [Lang.Blocks.JUMP_UP, 17],\n                            [Lang.Blocks.JUMP_DOWN, 18],\n                            [Lang.Blocks.POWER_UP, 19],\n                            [Lang.Blocks.POWER_DOWN, 20],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Sound',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_play_preset_music',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = _clamp(script.getNumberValue('VALUE'), 0, 20);\n                    const parsedPayload = `${value}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.PLAY_MELODY,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    this.waitMilliSec(500);\n                },\n            },\n            microbit2_radio_toggle: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.on, this.functionKeys.RADIO_ON],\n                            [Lang.Blocks.off, this.functionKeys.RADIO_OFF],\n                        ],\n                        value: this.functionKeys.RADIO_ON,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Radio',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_radio_toggle',\n                },\n                paramsKeyMap: { VALUE: 0 },\n                func: (sprite, script) => {\n                    const command = script.getField('VALUE');\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_radio_setting: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 7,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Radio',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_radio_setting',\n                },\n                paramsKeyMap: { RATE: 0, CHANNEL: 1 },\n                func: (sprite, script) => {\n                    if (!Entry.Utils.isNumber(script.getNumberValue('CHANNEL'))) {\n                        return;\n                    }\n                    const channel = Math.round(_clamp(script.getNumberValue('CHANNEL'), 0, 83));\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SETTING_RADIO,\n                        payload: channel,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_radio_send: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Radio',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_radio_send',\n                },\n                paramsKeyMap: { VALUE: 0 },\n                func: (sprite, script) => {\n                    const value = script.getStringValue('VALUE');\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_RADIO,\n                        payload: value,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_radio_received: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                class: 'microbit2Radio',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_radio_received',\n                },\n                paramsKeyMap: {},\n                func: (sprite, script) => {\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_RADIO,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_get_btn: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A', 'a'],\n                            ['B', 'b'],\n                            ['A+B', 'ab'],\n                        ],\n                        value: 'a',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Sensor',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_btn',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_BTN,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n\n                    if (parsedResponse[1] == '1' && value == 'a') {\n                        return 1;\n                    } else if (parsedResponse[1] == '2' && value == 'b') {\n                        return 1;\n                    } else if (parsedResponse[1] == '3' && value == 'ab') {\n                        return 1;\n                    } else return 0;\n                },\n            },\n            microbit2_btn_event: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#fff',\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A', '1'],\n                            ['B', '2'],\n                            ['A+B', '3'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                def: {\n                    type: 'microbit2_btn_event',\n                },\n                paramsKeyMap: {\n                    VALUE: 1,\n                },\n                class: 'microbit2v2',\n                isNotFor: ['microbit2'],\n                event: 'microbit_btn_pressed',\n                func: (sprite, script) => {\n                    return script.callReturn();\n                },\n            },\n            microbit2_get_acc: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.xAxis, 'x'],\n                            [Lang.Blocks.yAxis, 'y'],\n                            [Lang.Blocks.zAxis, 'z'],\n                            [Lang.Blocks.scalar, 'mag'],\n                        ],\n                        value: 'x',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Sensor',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_acc',\n                },\n                paramsKeyMap: {\n                    AXIS: 0,\n                },\n                func: (sprite, script) => {\n                    const axis = script.getField('AXIS');\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_ACC,\n                        payload: axis,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_get_gesture: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.up, 'up'],\n                            [Lang.Blocks.down, 'down'],\n                            [Lang.Blocks.left, 'left'],\n                            [Lang.Blocks.right, 'right'],\n                            [Lang.Blocks.face_up, 'face up'],\n                            [Lang.Blocks.face_down, 'face down'],\n                            [Lang.Blocks.freefall, 'freefall'],\n                            [Lang.Blocks['3g'], '3g'],\n                            [Lang.Blocks['6g'], '6g'],\n                            [Lang.Blocks['8g'], '8g'],\n                            [Lang.Blocks['shake'], 'shake'],\n                        ],\n                        value: 'up',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Sensor',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_gesture',\n                },\n                paramsKeyMap: { GESTURE: 0 },\n                func: (sprite, script) => {\n                    const gesture = script.getField('GESTURE');\n\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_GESTURE,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    if (gesture === parsedResponse[1]) {\n                        return true;\n                    }\n                    return false;\n                },\n            },\n            microbit2_get_direction: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                class: 'microbit2Sensor',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_direction',\n                },\n                paramsKeyMap: {},\n                func: (sprite, script) => {\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_DIRECTION,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_get_field_strength_axis: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.xAxis, 'x'],\n                            [Lang.Blocks.yAxis, 'y'],\n                            [Lang.Blocks.zAxis, 'z'],\n                            [Lang.Blocks.scalar, 'mag'],\n                        ],\n                        value: 'x',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Sensor',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_field_strength_axis',\n                },\n                paramsKeyMap: {\n                    AXIS: 0,\n                },\n                func: (sprite, script) => {\n                    const axis = script.getField('AXIS');\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_FIELD_STRENGTH,\n                        payload: axis,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_get_light_level: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                class: 'microbit2Sensor',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_light_level',\n                },\n                paramsKeyMap: {},\n                func: (sprite, script) => {\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_LIGHT_LEVEL,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_get_temperature: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                class: 'microbit2Sensor',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_temperature',\n                },\n                paramsKeyMap: {},\n                func: (sprite, script) => {\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_TEMPERATURE,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_get_sound_level: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [],\n                events: {},\n                class: 'microbit2v2',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_sound_level',\n                },\n                paramsKeyMap: {},\n                func: (sprite, script) => {\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_SOUND_LEVEL,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return parsedResponse[1];\n                },\n            },\n            microbit2_set_pwm: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: this.analogPins,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['ms', 'milli'],\n                            ['µs', 'micro'],\n                        ],\n                        value: 'milli',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Servo',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_set_pwm',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                    UNIT: 2,\n                },\n                func: (sprite, script) => {\n                    const pin = script.getValue('PIN');\n                    const unit = script.getValue('UNIT');\n                    const value = Math.round(_clamp(script.getNumberValue('VALUE'), 0, 1023));\n                    const command =\n                        unit === 'milli'\n                            ? this.functionKeys.SET_SERVO_MILLI\n                            : this.functionKeys.SET_SERVO_MICRO;\n\n                    const parsedPayload = `${pin};${value}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_SERVO_MILLI,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return;\n                },\n            },\n            microbit2_set_servo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: this.majorPins,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2Servo',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_set_servo',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                func: (sprite, script) => {\n                    const pin = script.getValue('PIN');\n                    const value = Math.round(_clamp(script.getNumberValue('VALUE'), 0, 180));\n\n                    const parsedPayload = `${pin};${value}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.SET_SERVO_ANGLE,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                    return;\n                },\n            },\n            microbit2_get_logo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [],\n                events: {},\n                class: 'microbit2v2',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_get_logo',\n                },\n                paramsKeyMap: {},\n                func: (sprite, script) => {\n                    if (this.version === '1') {\n                        throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                            Lang.Msgs.microbit2_compatible_error,\n                        ]);\n                    }\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.GET_LOGO,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n\n                    if (parsedResponse[1] == '1') {\n                        return 1;\n                    } else return 0;\n                },\n            },\n            microbit2_speaker_toggle: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.on, this.functionKeys.SPEAKER_ON],\n                            [Lang.Blocks.off, this.functionKeys.SPEAKER_OFF],\n                        ],\n                        value: this.functionKeys.SPEAKER_ON,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2v2',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_speaker_toggle',\n                },\n                paramsKeyMap: { VALUE: 0 },\n                func: (sprite, script) => {\n                    if (this.version === '1') {\n                        throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                            Lang.Msgs.microbit2_compatible_error,\n                        ]);\n                    }\n                    const command = script.getField('VALUE');\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n            microbit2_play_sound_effect: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.GIGGLE, 21],\n                            [Lang.Blocks.HAPPY, 22],\n                            [Lang.Blocks.HELLO, 23],\n                            [Lang.Blocks.MYSTERIOUS, 24],\n                            [Lang.Blocks.SAD, 25],\n                            [Lang.Blocks.SLIDE, 26],\n                            [Lang.Blocks.SOARING, 27],\n                            [Lang.Blocks.SPRING, 28],\n                            [Lang.Blocks.TWINKLE, 29],\n                            [Lang.Blocks.YAWN, 30],\n                        ],\n                        value: 21,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbit2v2',\n                isNotFor: ['microbit2'],\n                def: {\n                    type: 'microbit2_play_sound_effect',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    if (this.version === '1') {\n                        throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                            Lang.Msgs.microbit2_compatible_error,\n                        ]);\n                    }\n                    const value = _clamp(script.getNumberValue('VALUE'), 21, 30);\n                    const parsedPayload = `${value}`;\n                    const reqOptions = {\n                        id: script.entity.id,\n                        command: this.functionKeys.PLAY_SOUND,\n                        payload: parsedPayload,\n                    };\n                    this.requestCommandWithResponse(reqOptions);\n                    const parsedResponse = this.getResponse(reqOptions);\n                },\n            },\n        };\n    };\n})();\n\nmodule.exports = Entry.Microbit2;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_microbit_ext.js",
    "content": "'use strict';\n\nconst _clamp = require('lodash/clamp');\nconst _get = require('lodash/get');\n\nconst functionKeys = {\n    TEST_MESSAGE: 0xfa,\n    RESET: 0xfe,\n    CHECK_READY: 0xff,\n    SET_LED: 0x01,\n    SET_STRING: 0x02,\n    SET_IMAGE: 0x03,\n    SET_TONE: 0x04,\n    SET_TEMPO: 0x05,\n    SET_RELATIVE_TEMPO: 0x06,\n    SET_DIGITAL: 0x07,\n    SET_ANALOG: 0x08,\n    RESET_SCREEN: 0x09,\n    SET_ANALOG_PERIOD: 0x10,\n    SET_SERVO: 0x11,\n    SET_SERVO_PERIOD: 0x12,\n    SET_CUSTOM_IMAGE: 0x13,\n\n    GET_LED: 0x31,\n    GET_ANALOG: 0x32,\n    GET_DIGITAL: 0x33,\n    GET_BUTTON: 0x34,\n    GET_LIGHT_LEVEL: 0x35,\n    GET_TEMPERATURE: 0x36,\n    GET_COMPASS_HEADING: 0x37,\n    GET_ACCELEROMETER: 0x38,\n    GET_PITCH: 0x39,\n    GET_ROLL: 0x40,\n    GET_GESTURE: 0x41,\n};\n\nconst microbitGestures = {\n    TILT_UP: 1,\n    TILT_DOWN: 2,\n    TILT_LEFT: 3,\n    TILT_RIGHT: 4,\n    FACE_UP: 5,\n    FACE_DOWN: 6,\n    FREEFALL: 7,\n    THREE_G: 8,\n    SIX_G: 9,\n    EIGHT_G: 10,\n    SHAKE: 11,\n};\n\nEntry.MicrobitExt = new (class MicrobitExt {\n    constructor() {\n        this.id = '22.2';\n        this.url = 'http://microbit.org/ko/';\n        this.imageName = 'microbit_ext.png';\n        this.title = {\n            en: 'MicrobitExt',\n            ko: '마이크로비트 확장',\n        };\n        this.name = 'microbitExt';\n        this.communicationType = 'manual';\n        this.lastGesture = -1;\n        this.blockMenuBlocks = [\n            'microbit_ext_led_toggle',\n            'microbit_ext_get_led',\n            'microbit_ext_show_string',\n            'microbit_ext_show_image',\n            'microbit_ext_set_led_image',\n            'microbit_ext_reset_screen',\n            'microbit_ext_set_analog',\n            'microbit_ext_set_analog_period',\n            'microbit_ext_get_analog',\n            'microbit_ext_get_analog_map',\n            'microbit_ext_set_digital',\n            'microbit_ext_get_digital',\n            'microbit_ext_set_tone',\n            'microbit_ext_set_tempo',\n            'microbit_ext_set_relative_tempo',\n            'microbit_ext_get_button',\n            'microbit_ext_is_tilt',\n            'microbit_ext_get_tilt',\n            'microbit_ext_get_gesture',\n            'microbit_ext_get_sensor',\n            'microbit_ext_get_accelerometer',\n            'microbit_ext_set_servo',\n            'microbit_ext_set_servo_period',\n        ];\n        this.commandStatus = {};\n    }\n\n    setZero() {\n        this.requestCommand(functionKeys.RESET);\n        this.lastGesture = -1;\n        this.commandStatus = {};\n        this.isEngineStop = true;\n        delete Entry.hw.portData.sensorData;\n    }\n\n    requestCommand(type, payload) {\n        this.isEngineStop = false;\n        Entry.hw.sendQueue = {\n            type,\n            payload,\n        };\n        Entry.hw.update();\n    }\n\n    /**\n     * command 요청 후 데이터 송수신이 끝날 때까지 대기한다.\n     * @param type\n     * @param payload\n     */\n    requestCommandWithResponse(entityId, type, payload) {\n        this.isEngineStop = false;\n        const codeId = `${entityId}-${type}`;\n        if (!this.commandStatus[codeId]) {\n            // 첫 진입시 무조건 AsyncError\n            Entry.hw.sendQueue = {\n                type,\n                payload,\n            };\n            this.commandStatus[codeId] = 'pending';\n            Entry.hw.sendQueue.codeId = codeId;\n            Entry.hw.update();\n            throw new Entry.Utils.AsyncError();\n        } else if (this.commandStatus[codeId] === 'pending') {\n            // 두 번째 이상의 진입시도이며 작업이 아직 끝나지 않은 경우\n            throw new Entry.Utils.AsyncError();\n        } else if (this.commandStatus[codeId] === 'completed') {\n            // 두 번째 이상의 진입시도이며 pending 도 아닌 경우\n            // 블록 func 로직에서 다음 데이터를 처리한다.\n            this.commandStatus[codeId] = null;\n        }\n    }\n\n    afterReceive(portData) {\n        if (this.isEngineStop) {\n            return;\n        }\n        if (!portData.payload) {\n            return;\n        }\n        if (portData.payload.isSensorMap) {\n            return;\n        }\n        if (portData.payload.codeId) {\n            this.commandStatus[portData.payload.codeId] = 'completed';\n        }\n        if (portData.payload.codeIdMiss) {\n            this.commandStatus[portData.payload.codeIdMiss] = 'completed';\n        }\n    }\n    setLanguage() {\n        return {\n            ko: {\n                template: {\n                    microbit_ext_led_toggle: 'LED의 X:%1 Y:%2 %3 %4',\n                    microbit_ext_get_led: 'LED의 X:%1 Y:%2 상태값',\n                    microbit_ext_show_string: '%1 출력하기 %2',\n                    microbit_ext_show_image: '%1 아이콘 출력하기 %2',\n                    microbit_ext_set_led_image: 'LED %1 으로 출력하기 %2',\n                    microbit_ext_reset_screen: '화면 지우기 %1',\n                    microbit_ext_set_tone: '%1 음을 %2 박자 연주하기 %3',\n                    microbit_ext_set_tempo: '연주 속도를 %1 BPM 으로 정하기 %2',\n                    microbit_ext_set_relative_tempo: '연주 속도를 %1 BPM 만큼 바꾸기 %2',\n                    microbit_ext_set_analog: '%1 에 아날로그 값 %2 출력 %3',\n                    microbit_ext_set_analog_period:\n                        '%1 에 아날로그 PWM 출력 주기를 %2 마이크로초 로 설정 %3',\n                    microbit_ext_get_analog: '아날로그 핀 %1번 센서값',\n                    microbit_ext_get_analog_map:\n                        '아날로그 핀 %1번 센서값의 범위를 %2~%3 에서 %4~%5 (으)로 바꾼값',\n                    microbit_ext_set_digital: '%1 에 디지털 값 %2 출력 %3',\n                    microbit_ext_get_digital: '디지털 핀 %1번 센서값',\n                    microbit_ext_get_button: '%1 버튼을 눌렀는가?',\n                    microbit_ext_get_sensor: '%1 센서값',\n                    microbit_ext_is_tilt: '%1 방향으로 기울었는가?',\n                    microbit_ext_get_tilt: '%1 방향으로 기울어진 각도값',\n                    microbit_ext_get_accelerometer: '가속도 센서 %1의 값',\n                    microbit_ext_set_servo: '%1 에 서보 값 %2 출력 %3',\n                    microbit_ext_set_servo_period: '%1 에 서보 펄스 폭을 %2 마이크로초로 설정 %3',\n                    microbit_ext_get_gesture: '%1 이 감지되는가?',\n                },\n                Blocks: {\n                    microbit_ext_acc_xaxis: 'x축',\n                    microbit_ext_acc_yaxis: 'y축',\n                    microbit_ext_acc_zaxis: 'z축',\n                    microbit_ext_acc_strength: '크기',\n                    microbit_ext_tilt_right: '오른쪽',\n                    microbit_ext_tilt_left: '왼쪽',\n                    microbit_ext_tilt_rear: '뒤쪽',\n                    microbit_ext_tilt_front: '앞쪽',\n                    microbit_ext_sensor_temperature: '온도',\n                    microbit_ext_sensor_compass: '자기',\n                    microbit_ext_sensor_light: '빛',\n                    microbit_ext_tone_b: '시',\n                    microbit_ext_tone_a_sharp: '라#',\n                    microbit_ext_tone_a: '라',\n                    microbit_ext_tone_g_sharp: '솔#',\n                    microbit_ext_tone_g: '솔',\n                    microbit_ext_tone_f_sharp: '파#',\n                    microbit_ext_tone_f: '파',\n                    microbit_ext_tone_e: '미',\n                    microbit_ext_tone_d_sharp: '레#',\n                    microbit_ext_tone_d: '레',\n                    microbit_ext_tone_c_sharp: '도#',\n                    microbit_ext_tone_c: '도',\n                    microbit_ext_tone_high: '높은',\n                    microbit_ext_tone_middle: '',\n                    microbit_ext_tone_low: '낮은',\n                    microbit_ext_image_target: '표적',\n                    microbit_ext_image_rake: '갈퀴',\n                    microbit_ext_image_eighth_note: '8분 음표',\n                    microbit_ext_image_quarter_note: '4분 음표',\n                    microbit_ext_image_ox: '소',\n                    microbit_ext_image_rabbit: '토끼',\n                    microbit_ext_image_snake: '뱀',\n                    microbit_ext_image_umbrella: '우산',\n                    microbit_ext_image_skull: '해골',\n                    microbit_ext_image_giraffe: '기린',\n                    microbit_ext_image_sword: '칼',\n                    microbit_ext_image_ghost: '유령',\n                    microbit_ext_image_stickman: '스틱맨',\n                    microbit_ext_image_butterfly: '나비',\n                    microbit_ext_image_turtle: '거북이',\n                    microbit_ext_image_house: '집',\n                    microbit_ext_image_duck: '오리',\n                    microbit_ext_image_rollerskate: '롤러스케이트',\n                    microbit_ext_image_tshirt: '티셔츠',\n                    microbit_ext_image_scissors: '가위',\n                    microbit_ext_image_small_square: '작은 사각형',\n                    microbit_ext_image_square: '사각형',\n                    microbit_ext_image_small_diamond: '작은 다이아몬드',\n                    microbit_ext_image_diamond: '다이아몬드',\n                    microbit_ext_image_chessboard: '체스판',\n                    microbit_ext_image_left_triangle: '왼쪽 삼각형',\n                    microbit_ext_image_triangle: '삼각형',\n                    microbit_ext_image_no: '노놉',\n                    microbit_ext_image_yes: '예스',\n                    microbit_ext_image_not_good: '별로',\n                    microbit_ext_image_fantastic: '환상적인',\n                    microbit_ext_image_fool: '바보',\n                    microbit_ext_image_surprised: '놀람',\n                    microbit_ext_image_sleepy: '졸림',\n                    microbit_ext_image_angry: '화남',\n                    microbit_ext_image_confused: '혼란',\n                    microbit_ext_image_sadness: '슬픔',\n                    microbit_ext_image_happiness: '행복함',\n                    microbit_ext_image_small_heart: '작은 하트',\n                    microbit_ext_image_heart: '하트',\n                    microbit_ext_led_toggle_on: '켜기',\n                    microbit_ext_led_toggle_off: '끄기',\n                    microbit_ext_led_toggle_toggle: '반전',\n                    microbit_ext_gesture_shake: '흔들림',\n                    microbit_ext_gesture_portrait_top: '세워서 위쪽 방향',\n                    microbit_ext_gesture_portrait_bottom: '세워서 아래쪽 방향',\n                    microbit_ext_gesture_portrait_right: '세워서 오른쪽 방향',\n                    microbit_ext_gesture_portrait_left: '세워서 왼쪽 방향',\n                    microbit_ext_gesture_horizontal_top: '눕혀서 위쪽 방향',\n                    microbit_ext_gesture_horizontal_bottom: '눕혀서 아래쪽 방향',\n                    microbit_ext_gesture_horizontal_right: '눕혀서 오른쪽 방향',\n                    microbit_ext_gesture_horizontal_left: '눕혀서 왼쪽 방향',\n                },\n                Msgs: {\n                    microbit_led_erase_all: '모두 지우기',\n                },\n            },\n            en: {\n                template: {\n                    microbit_ext_led_toggle: 'LED X:%1 Y:%2 %3 %4',\n                    microbit_ext_get_led: 'LED X:%1 Y:%2 Value',\n                    microbit_ext_show_string: '%1 appear %2',\n                    microbit_ext_show_image: '%1 icon appear %2',\n                    microbit_ext_set_led_image: 'Show %1 leds %2',\n                    microbit_ext_reset_screen: 'Clear screen %1',\n                    microbit_ext_set_tone: 'Play %1 for %2 beat %3',\n                    microbit_ext_set_tempo: 'Set tempo to %1 BPM %2',\n                    microbit_ext_set_relative_tempo: 'Change tempo by %1 BPM %2',\n                    microbit_ext_set_analog: 'Analog writen pin %1 to %2 %3',\n                    microbit_ext_set_analog_period: 'Analog set period pin %1 to microsecond %2 %3',\n                    microbit_ext_get_analog: 'Analog %1 Sensor Value',\n                    microbit_ext_get_analog_map:\n                        'Change analog %1 Sensor Value from %2 ~ %3 to %4 ~ %5',\n                    microbit_ext_set_digital: 'Analog writen pin %1 to %2 %3',\n                    microbit_ext_get_digital: 'Digital %1 Sensor Value',\n                    microbit_ext_get_button: 'Button %1 is pressed?',\n                    microbit_ext_get_sensor: 'value of %1 sensor',\n                    microbit_ext_is_tilt: 'Tilted to the %1?',\n                    microbit_ext_get_tilt: 'Angle value tilted to the %1',\n                    microbit_ext_get_accelerometer: 'Acceleration %1',\n                    microbit_ext_set_servo: 'Servo write pin %1 to %2 %3',\n                    microbit_ext_set_servo_period: 'Set servo %1 pulse to %2 microsecond %3',\n                    microbit_ext_get_gesture: '%1 Sensor Value?',\n                },\n                Blocks: {\n                    microbit_ext_acc_xaxis: 'x',\n                    microbit_ext_acc_yaxis: 'y',\n                    microbit_ext_acc_zaxis: 'z',\n                    microbit_ext_acc_strength: 'Strength',\n                    microbit_ext_tilt_right: 'Right',\n                    microbit_ext_tilt_left: 'Left',\n                    microbit_ext_tilt_rear: 'Rear',\n                    microbit_ext_tilt_front: 'Front',\n                    microbit_ext_sensor_temperature: 'Temperature',\n                    microbit_ext_sensor_compass: 'Compass',\n                    microbit_ext_sensor_light: 'Light',\n                    microbit_ext_tone_high: 'HIGH',\n                    microbit_ext_tone_middle: 'MIDDLE',\n                    microbit_ext_tone_low: 'Low',\n                    microbit_ext_tone_b: 'B',\n                    microbit_ext_tone_a_sharp: 'A#',\n                    microbit_ext_tone_a: 'A',\n                    microbit_ext_tone_g_sharp: 'G#',\n                    microbit_ext_tone_g: 'G',\n                    microbit_ext_tone_f_sharp: 'F#',\n                    microbit_ext_tone_f: 'F',\n                    microbit_ext_tone_e: 'E',\n                    microbit_ext_tone_d_sharp: 'D#',\n                    microbit_ext_tone_d: 'D',\n                    microbit_ext_tone_c_sharp: 'C#',\n                    microbit_ext_tone_c: 'C',\n                    microbit_ext_image_target: 'Target',\n                    microbit_ext_image_rake: 'Rake',\n                    microbit_ext_image_eighth_note: 'Eighth note',\n                    microbit_ext_image_quarter_note: 'Quarter note',\n                    microbit_ext_image_ox: 'Ox',\n                    microbit_ext_image_rabbit: 'Rabbit',\n                    microbit_ext_image_snake: 'Snake',\n                    microbit_ext_image_umbrella: 'Umbrella',\n                    microbit_ext_image_skull: 'Skull',\n                    microbit_ext_image_giraffe: 'Giraffe',\n                    microbit_ext_image_sword: 'Sword',\n                    microbit_ext_image_ghost: 'Ghost',\n                    microbit_ext_image_stickman: 'Stickfigure',\n                    microbit_ext_image_butterfly: 'Butterfly',\n                    microbit_ext_image_turtle: 'Turtle',\n                    microbit_ext_image_house: 'House',\n                    microbit_ext_image_duck: 'Duck',\n                    microbit_ext_image_rollerskate: 'Rollerskate',\n                    microbit_ext_image_tshirt: 'T-shirt',\n                    microbit_ext_image_scissors: 'Scissors',\n                    microbit_ext_image_small_square: 'Small Square',\n                    microbit_ext_image_square: 'Square',\n                    microbit_ext_image_small_diamond: 'Small Diamond',\n                    microbit_ext_image_diamond: 'Diamond',\n                    microbit_ext_image_chessboard: 'Chessboard',\n                    microbit_ext_image_left_triangle: 'Left Triangle',\n                    microbit_ext_image_triangle: 'Triangle',\n                    microbit_ext_image_no: 'Nope',\n                    microbit_ext_image_yes: 'Yes',\n                    microbit_ext_image_not_good: 'Not Good',\n                    microbit_ext_image_fantastic: 'fantastic',\n                    microbit_ext_image_fool: 'Fool',\n                    microbit_ext_image_surprised: 'Surpriesd',\n                    microbit_ext_image_sleepy: 'Sleepy',\n                    microbit_ext_image_angry: 'Angry',\n                    microbit_ext_image_confused: 'Confused',\n                    microbit_ext_image_sadness: 'Sadness',\n                    microbit_ext_image_happiness: 'Happiness',\n                    microbit_ext_image_small_heart: 'Small Heart',\n                    microbit_ext_image_heart: 'Heart',\n                    microbit_ext_led_toggle_on: 'On',\n                    microbit_ext_led_toggle_off: 'Off',\n                    microbit_ext_led_toggle_toggle: 'Reverse',\n                    microbit_ext_gesture_shake: 'Shake',\n                    microbit_ext_gesture_portrait_top: 'Portrait Top',\n                    microbit_ext_gesture_portrait_bottom: 'Portrait Bottom',\n                    microbit_ext_gesture_portrait_right: 'Portrait Right',\n                    microbit_ext_gesture_portrait_left: 'Portrait Left',\n                    microbit_ext_gesture_horizontal_top: 'Horizontal Top',\n                    microbit_ext_gesture_horizontal_bottom: 'Horizontal Bottom',\n                    microbit_ext_gesture_horizontal_right: 'Horizontal Right',\n                    microbit_ext_gesture_horizontal_left: 'Horizontal Left',\n                },\n                Msgs: {\n                    microbit_led_erase_all: 'Reset',\n                },\n            },\n            jp: {\n                template: {\n                    microbit_ext_led_toggle: 'LED X:%1 Y:%2 %3 %4',\n                    microbit_ext_get_led: 'LED X:%1 Y:%2 が点灯している',\n                    microbit_ext_show_string: '%1 文字列を表示 %2',\n                    microbit_ext_show_image: '%1 アイコンを表示 %2',\n                    microbit_ext_set_led_image: '%1 LED画面に表示 %2',\n                    microbit_ext_reset_screen: '表示のクリア %1',\n                    microbit_ext_set_tone: '%1 音を %2 拍子演奏する %3',\n                    microbit_ext_set_tempo: '演奏スピードを %1 BPM に決める %2',\n                    microbit_ext_set_relative_tempo: '演奏スピードを %1 BPM変更する %2',\n                    microbit_ext_set_analog: 'アナログで出力する 端子 %1 値 %2 %3',\n                    microbit_ext_set_analog_period:\n                        'アナログ出力 パルス周期を設定する 端子 %1 周期（マイクロ秒）%2 %3',\n                    microbit_ext_get_analog: 'アナログピン %1 番のセンサー値',\n                    microbit_ext_get_analog_map:\n                        'アナログピン %1 番のセンサー値の範囲を %2 ～ %3 から %4 ～ %5 に変更した値',\n                    microbit_ext_set_digital: 'アナログで出力する 端子 %1 値 %2 %3',\n                    microbit_ext_get_digital: 'デジタルピン %1 番のセンサー値',\n                    microbit_ext_get_button: '%1 ボタンを押したか？',\n                    microbit_ext_get_sensor: '%1 センサー値',\n                    microbit_ext_is_tilt: '%1 に傾いているか？',\n                    microbit_ext_get_tilt: '%1 に傾いた角度',\n                    microbit_ext_get_accelerometer: '加速度センサー %1 の値',\n                    microbit_ext_set_servo: 'サーボ 出力する 端子 %1 角度 %2 %3',\n                    microbit_ext_set_servo_period: 'Servo %1 パルス幅の設定（マイクロ秒） %2 %3',\n                    microbit_ext_get_gesture: '%1 があるか？',\n                },\n                Blocks: {\n                    microbit_ext_acc_xaxis: 'x軸',\n                    microbit_ext_acc_yaxis: 'y軸',\n                    microbit_ext_acc_zaxis: 'z軸',\n                    microbit_ext_acc_strength: '大きさ',\n                    microbit_ext_tilt_right: '右',\n                    microbit_ext_tilt_left: '左',\n                    microbit_ext_tilt_rear: '後ろ',\n                    microbit_ext_tilt_front: '前方',\n                    microbit_ext_sensor_temperature: '温度',\n                    microbit_ext_sensor_compass: '磁気',\n                    microbit_ext_sensor_light: '光',\n                    microbit_ext_tone_high: '高い',\n                    microbit_ext_tone_middle: '',\n                    microbit_ext_tone_low: '低い',\n\n                    microbit_ext_tone_b: 'シ',\n                    microbit_ext_tone_a_sharp: 'ラ#',\n                    microbit_ext_tone_a: 'ラ',\n                    microbit_ext_tone_g_sharp: 'ソ#',\n                    microbit_ext_tone_g: 'ソ',\n                    microbit_ext_tone_f_sharp: 'ファ#',\n                    microbit_ext_tone_f: 'ファ',\n                    microbit_ext_tone_e: 'ミ',\n                    microbit_ext_tone_d_sharp: 'レ#',\n                    microbit_ext_tone_d: 'レ',\n                    microbit_ext_tone_c_sharp: 'ド#',\n                    microbit_ext_tone_c: 'ド',\n                    microbit_ext_image_target: '目標',\n                    microbit_ext_image_rake: 'レーキ',\n                    microbit_ext_image_eighth_note: '8分音符',\n                    microbit_ext_image_quarter_note: '4分音符',\n                    microbit_ext_image_ox: '牛',\n                    microbit_ext_image_rabbit: 'ウサギ',\n                    microbit_ext_image_snake: 'ヘビ',\n                    microbit_ext_image_umbrella: '傘',\n                    microbit_ext_image_skull: '頭蓋骨',\n                    microbit_ext_image_giraffe: 'キリン',\n                    microbit_ext_image_sword: '剣',\n                    microbit_ext_image_ghost: '幽霊',\n                    microbit_ext_image_stickman: '棒人間',\n                    microbit_ext_image_butterfly: 'バタフライ',\n                    microbit_ext_image_turtle: 'カメ',\n                    microbit_ext_image_house: '家',\n                    microbit_ext_image_duck: 'アヒル',\n                    microbit_ext_image_rollerskate: 'ローラースケート',\n                    microbit_ext_image_tshirt: 'Tシャツ',\n                    microbit_ext_image_scissors: 'はさみ',\n                    microbit_ext_image_small_square: '小さな四角形',\n                    microbit_ext_image_square: '四角形',\n                    microbit_ext_image_small_diamond: '小さなダイヤモンド',\n                    microbit_ext_image_diamond: 'ダイヤモンド',\n                    microbit_ext_image_chessboard: 'チェス盤',\n                    microbit_ext_image_left_triangle: '左の三角形',\n                    microbit_ext_image_triangle: '三角形',\n                    microbit_ext_image_no: 'いや',\n                    microbit_ext_image_yes: '良かった',\n                    microbit_ext_image_not_good: '良くない',\n                    microbit_ext_image_fantastic: '素晴らしい',\n                    microbit_ext_image_fool: 'バカ',\n                    microbit_ext_image_surprised: 'びっくり',\n                    microbit_ext_image_sleepy: '眠いです',\n                    microbit_ext_image_angry: '怒り',\n                    microbit_ext_image_confused: '混乱した',\n                    microbit_ext_image_sadness: '悲しみ',\n                    microbit_ext_image_happiness: '幸せ',\n                    microbit_ext_image_small_heart: '小さな心',\n                    microbit_ext_image_heart: 'ハート',\n                    microbit_ext_led_toggle_on: '点灯',\n                    microbit_ext_led_toggle_off: '消灯',\n                    microbit_ext_led_toggle_toggle: '反転',\n                    microbit_ext_gesture_shake: '揺れ',\n                    microbit_ext_gesture_portrait_top: '立て上方向',\n                    microbit_ext_gesture_portrait_bottom: '立て下向き',\n                    microbit_ext_gesture_portrait_right: '立て右方向',\n                    microbit_ext_gesture_portrait_left: '立て左方向',\n                    microbit_ext_gesture_horizontal_top: '寝かせ上方向',\n                    microbit_ext_gesture_horizontal_bottom: '寝かせ、下方向',\n                    microbit_ext_gesture_horizontal_right: '寝かせ右方向',\n                    microbit_ext_gesture_horizontal_left: '寝かせ左方向',\n                },\n            },\n        };\n    }\n\n    getBlocks() {\n        return {\n            microbit_ext_led_toggle: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.microbit_ext_led_toggle_on, 'on'],\n                            [Lang.Blocks.microbit_ext_led_toggle_off, 'off'],\n                            [Lang.Blocks.microbit_ext_led_toggle_toggle, 'toggle'],\n                        ],\n                        value: 'on',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtLed',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['0'],\n                        },\n                    ],\n                    type: 'microbit_ext_led_toggle',\n                },\n                paramsKeyMap: {\n                    X: 0,\n                    Y: 1,\n                    VALUE: 2,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    const x = _clamp(script.getNumberValue('X'), 0, 4);\n                    const y = _clamp(script.getNumberValue('Y'), 0, 4);\n                    this.requestCommandWithResponse(script.entity.id, functionKeys.SET_LED, {\n                        x,\n                        y,\n                        value,\n                    });\n                },\n            },\n            microbit_ext_get_led: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                class: 'microbitExtLed',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'text',\n                            params: ['0'],\n                        },\n                    ],\n                    type: 'microbit_ext_get_led',\n                },\n                paramsKeyMap: {\n                    X: 0,\n                    Y: 1,\n                },\n                func: (sprite, script) => {\n                    const x = _clamp(script.getNumberValue('X'), 0, 4);\n                    const y = _clamp(script.getNumberValue('Y'), 0, 4);\n                    this.requestCommandWithResponse(script.entity.id, functionKeys.GET_LED, {\n                        x,\n                        y,\n                    });\n                    return _get(Entry.hw.portData, ['payload', 'sensorData', 'led', x, y]);\n                },\n            },\n            microbit_ext_show_string: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtLed',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        {\n                            type: 'text',\n                            params: ['Hello!'],\n                        },\n                    ],\n                    type: 'microbit_ext_show_string',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    let value = script.getStringValue('VALUE');\n                    value = value.replace(\n                        /[^A-Za-z0-9_\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\\\\\{\\}\\[\\]\\'\\\"\\;\\:\\<\\,\\>\\.\\?\\/\\s]/gim,\n                        ''\n                    );\n                    this.requestCommandWithResponse(\n                        script.entity.id,\n                        functionKeys.SET_STRING,\n                        value\n                    );\n                },\n            },\n            microbit_ext_show_image: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.microbit_ext_image_heart, 0],\n                            [Lang.Blocks.microbit_ext_image_small_heart, 1],\n                            [Lang.Blocks.microbit_ext_image_happiness, 2],\n                            [Lang.Blocks.microbit_ext_image_sadness, 3],\n                            [Lang.Blocks.microbit_ext_image_confused, 4],\n                            [Lang.Blocks.microbit_ext_image_angry, 5],\n                            [Lang.Blocks.microbit_ext_image_sleepy, 6],\n                            [Lang.Blocks.microbit_ext_image_surprised, 7],\n                            [Lang.Blocks.microbit_ext_image_fool, 8],\n                            [Lang.Blocks.microbit_ext_image_fantastic, 9],\n                            [Lang.Blocks.microbit_ext_image_not_good, 10],\n                            [Lang.Blocks.microbit_ext_image_yes, 11],\n                            [Lang.Blocks.microbit_ext_image_no, 12],\n                            [Lang.Blocks.microbit_ext_image_triangle, 13],\n                            [Lang.Blocks.microbit_ext_image_left_triangle, 14],\n                            [Lang.Blocks.microbit_ext_image_chessboard, 15],\n                            [Lang.Blocks.microbit_ext_image_diamond, 17],\n                            [Lang.Blocks.microbit_ext_image_small_diamond, 18],\n                            [Lang.Blocks.microbit_ext_image_square, 19],\n                            [Lang.Blocks.microbit_ext_image_small_square, 20],\n                            [Lang.Blocks.microbit_ext_image_scissors, 21],\n                            [Lang.Blocks.microbit_ext_image_tshirt, 22],\n                            [Lang.Blocks.microbit_ext_image_rollerskate, 23],\n                            [Lang.Blocks.microbit_ext_image_duck, 24],\n                            [Lang.Blocks.microbit_ext_image_house, 25],\n                            [Lang.Blocks.microbit_ext_image_turtle, 26],\n                            [Lang.Blocks.microbit_ext_image_butterfly, 27],\n                            [Lang.Blocks.microbit_ext_image_stickman, 28],\n                            [Lang.Blocks.microbit_ext_image_ghost, 29],\n                            [Lang.Blocks.microbit_ext_image_sword, 30],\n                            [Lang.Blocks.microbit_ext_image_giraffe, 31],\n                            [Lang.Blocks.microbit_ext_image_skull, 32],\n                            [Lang.Blocks.microbit_ext_image_umbrella, 33],\n                            [Lang.Blocks.microbit_ext_image_snake, 34],\n                            [Lang.Blocks.microbit_ext_image_rabbit, 35],\n                            [Lang.Blocks.microbit_ext_image_ox, 36],\n                            [Lang.Blocks.microbit_ext_image_quarter_note, 37],\n                            [Lang.Blocks.microbit_ext_image_eighth_note, 38],\n                            [Lang.Blocks.microbit_ext_image_rake, 39],\n                            [Lang.Blocks.microbit_ext_image_target, 40],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtLed',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_show_image',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    this.requestCommandWithResponse(script.entity.id, functionKeys.SET_IMAGE, {\n                        value,\n                    });\n                },\n            },\n            microbit_ext_set_led_image: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Led',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtLed',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_set_led_image',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    this.requestCommand(functionKeys.SET_CUSTOM_IMAGE, { value });\n                },\n            },\n            microbit_ext_reset_screen: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtLed',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_reset_screen',\n                },\n                paramsKeyMap: {},\n                func: (sprite, script) => {\n                    this.requestCommand(functionKeys.RESET_SCREEN);\n                },\n            },\n            microbit_ext_set_tone: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [\n                                Lang.Blocks.microbit_ext_tone_low + Lang.Blocks.microbit_ext_tone_c,\n                                131,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low +\n                                    Lang.Blocks.microbit_ext_tone_c_sharp,\n                                139,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low + Lang.Blocks.microbit_ext_tone_d,\n                                147,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low +\n                                    Lang.Blocks.microbit_ext_tone_d_sharp,\n                                156,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low + Lang.Blocks.microbit_ext_tone_e,\n                                165,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low + Lang.Blocks.microbit_ext_tone_f,\n                                175,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low +\n                                    Lang.Blocks.microbit_ext_tone_f_sharp,\n                                185,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low + Lang.Blocks.microbit_ext_tone_g,\n                                196,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low +\n                                    Lang.Blocks.microbit_ext_tone_g_sharp,\n                                208,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low + Lang.Blocks.microbit_ext_tone_a,\n                                220,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low +\n                                    Lang.Blocks.microbit_ext_tone_a_sharp,\n                                233,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_low + Lang.Blocks.microbit_ext_tone_b,\n                                247,\n                            ],\n                            [Lang.Blocks.microbit_ext_tone_c, 262],\n                            [Lang.Blocks.microbit_ext_tone_c_sharp, 277],\n                            [Lang.Blocks.microbit_ext_tone_d, 294],\n                            [Lang.Blocks.microbit_ext_tone_d_sharp, 311],\n                            [Lang.Blocks.microbit_ext_tone_e, 330],\n                            [Lang.Blocks.microbit_ext_tone_f, 349],\n                            [Lang.Blocks.microbit_ext_tone_f_sharp, 370],\n                            [Lang.Blocks.microbit_ext_tone_g, 392],\n                            [Lang.Blocks.microbit_ext_tone_g_sharp, 415],\n                            [Lang.Blocks.microbit_ext_tone_a, 440],\n                            [Lang.Blocks.microbit_ext_tone_a_sharp, 466],\n                            [Lang.Blocks.microbit_ext_tone_b, 494],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_c,\n                                523,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_c_sharp,\n                                554,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_d,\n                                587,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_d_sharp,\n                                622,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_e,\n                                659,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_f,\n                                698,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_f_sharp,\n                                740,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_g,\n                                784,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_g_sharp,\n                                831,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_a,\n                                880,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_a_sharp,\n                                932,\n                            ],\n                            [\n                                Lang.Blocks.microbit_ext_tone_high +\n                                    Lang.Blocks.microbit_ext_tone_b,\n                                988,\n                            ],\n                        ],\n                        value: 131,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['4', 1],\n                            ['2', 2],\n                            ['1', 4],\n                            ['1/2', 8],\n                            ['1/4', 16],\n                            ['1/8', 32],\n                        ],\n                        value: 4,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtSound',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_set_tone',\n                },\n                paramsKeyMap: {\n                    NOTE_VALUE: 0,\n                    BEAT_VALUE: 1,\n                },\n                func: (sprite, script) => {\n                    const noteValue = script.getField('NOTE_VALUE');\n                    const beatValue = script.getField('BEAT_VALUE');\n                    this.requestCommandWithResponse(script.entity.id, functionKeys.SET_TONE, {\n                        noteValue,\n                        beatValue,\n                    });\n                },\n            },\n            microbit_ext_set_tempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtSound',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['120'],\n                        },\n                    ],\n                    type: 'microbit_ext_set_tempo',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const pinNumber = script.getField('PIN');\n                    const value = _clamp(script.getNumberValue('VALUE'), 0, 255);\n                    this.requestCommand(functionKeys.SET_TEMPO, { value });\n                },\n            },\n            microbit_ext_set_relative_tempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtSound',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['20'],\n                        },\n                    ],\n                    type: 'microbit_ext_set_relative_tempo',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const pinNumber = script.getField('PIN');\n                    const value = _clamp(script.getNumberValue('VALUE'), -127, 127) + 128; // offset for uint8_t payload\n                    this.requestCommand(functionKeys.SET_RELATIVE_TEMPO, { value });\n                },\n            },\n\n            microbit_ext_set_analog: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['P0', 0],\n                            ['P1', 1],\n                            ['P2', 2],\n                            ['P3', 3],\n                            ['P4', 4],\n                            ['P10', 10],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtAnalog',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['1023'],\n                        },\n                    ],\n                    type: 'microbit_ext_set_analog',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                func: (sprite, script) => {\n                    const pinNumber = script.getField('PIN');\n                    const value = _clamp(script.getNumberValue('VALUE'), 0, 1023);\n                    this.requestCommand(functionKeys.SET_ANALOG, { pinNumber, value });\n                },\n            },\n            microbit_ext_set_analog_period: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['P0', 0],\n                            ['P1', 1],\n                            ['P2', 2],\n                            ['P3', 3],\n                            ['P4', 4],\n                            ['P10', 10],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtAnalog',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['20000'],\n                        },\n                    ],\n                    type: 'microbit_ext_set_analog_period',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                func: (sprite, script) => {\n                    const pinNumber = script.getField('PIN');\n                    const value = script.getNumberValue('VALUE');\n                    this.requestCommand(functionKeys.SET_ANALOG_PERIOD, { pinNumber, value });\n                },\n            },\n            microbit_ext_get_analog: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['P0', 0],\n                            ['P1', 1],\n                            ['P2', 2],\n                            ['P3', 3],\n                            ['P4', 4],\n                            ['P10', 10],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtAnalog',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_get_analog',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    this.requestCommandWithResponse(script.entity.id, functionKeys.GET_ANALOG, [\n                        value,\n                    ]);\n                    return _get(Entry.hw.portData, ['payload', 'sensorData', 'analog', value], 0);\n                },\n            },\n            microbit_ext_get_analog_map: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['P0', 0],\n                            ['P1', 1],\n                            ['P2', 2],\n                            ['P3', 3],\n                            ['P4', 4],\n                            ['P10', 10],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                ],\n                events: {},\n                class: 'microbitExtAnalog',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['1023'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                    ],\n                    type: 'microbit_ext_get_analog_map',\n                },\n                paramsKeyMap: {\n                    PORT: 0,\n                    VALUE2: 1,\n                    VALUE3: 2,\n                    VALUE4: 3,\n                    VALUE5: 4,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    this.requestCommandWithResponse(script.entity.id, functionKeys.GET_ANALOG, [\n                        value,\n                    ]);\n                    let returnData = _get(\n                        Entry.hw.portData,\n                        ['payload', 'sensorData', 'analog', value],\n                        0\n                    );\n\n                    let value2 = script.getNumberValue('VALUE2', script);\n                    let value3 = script.getNumberValue('VALUE3', script);\n                    let value4 = script.getNumberValue('VALUE4', script);\n                    let value5 = script.getNumberValue('VALUE5', script);\n                    const stringValue4 = script.getValue('VALUE4', script);\n                    const stringValue5 = script.getValue('VALUE5', script);\n                    let isFloat = false;\n\n                    if (\n                        (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                        (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                    ) {\n                        isFloat = true;\n                    }\n                    let swap;\n                    if (value2 > value3) {\n                        swap = value2;\n                        value2 = value3;\n                        value3 = swap;\n                    }\n                    if (value4 > value5) {\n                        swap = value4;\n                        value4 = value5;\n                        value5 = swap;\n                    }\n                    returnData -= value2;\n                    returnData = returnData * ((value5 - value4) / (value3 - value2));\n                    returnData += value4;\n                    returnData = Math.min(value5, returnData);\n                    returnData = Math.max(value4, returnData);\n\n                    if (isFloat) {\n                        returnData = Math.round(returnData * 100) / 100;\n                    } else {\n                        returnData = Math.round(returnData);\n                    }\n                    return returnData;\n                },\n            },\n            microbit_ext_set_digital: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['P0', 0],\n                            ['P1', 1],\n                            ['P2', 2],\n                            ['P3', 3],\n                            ['P4', 4],\n                            ['P5', 5],\n                            ['P6', 6],\n                            ['P7', 7],\n                            ['P8', 8],\n                            ['P9', 9],\n                            ['P10', 10],\n                            ['P11', 11],\n                            ['P12', 12],\n                            ['P13', 13],\n                            ['P14', 14],\n                            ['P15', 15],\n                            ['P16', 16],\n                            ['P19', 19],\n                            ['P20', 20],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['0', 0],\n                            ['1', 1],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtDigital',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [],\n                    type: 'microbit_ext_set_digital',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                func: (sprite, script) => {\n                    const pinNumber = script.getField('PIN');\n                    const value = script.getNumberField('VALUE');\n                    this.requestCommandWithResponse(script.entity.id, functionKeys.SET_DIGITAL, {\n                        pinNumber,\n                        value,\n                    });\n                },\n            },\n            microbit_ext_get_digital: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['P0', 0],\n                            ['P1', 1],\n                            ['P2', 2],\n                            ['P3', 3],\n                            ['P4', 4],\n                            ['P5', 5],\n                            ['P6', 6],\n                            ['P7', 7],\n                            ['P8', 8],\n                            ['P9', 9],\n                            ['P10', 10],\n                            ['P11', 11],\n                            ['P12', 12],\n                            ['P13', 13],\n                            ['P14', 14],\n                            ['P15', 15],\n                            ['P16', 16],\n                            ['P19', 19],\n                            ['P20', 20],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtDigital',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_get_digital',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    this.requestCommandWithResponse(script.entity.id, functionKeys.GET_DIGITAL, [\n                        value,\n                    ]);\n                    return _get(Entry.hw.portData, ['payload', 'sensorData', 'digital', value], 0);\n                },\n            },\n            microbit_ext_get_button: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A', 1],\n                            ['B', 2],\n                            ['A+B', 3],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtButton',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_get_button',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    const buttonState = _get(\n                        Entry.hw.portData,\n                        ['payload', 'sensorData', 'button'],\n                        -1\n                    );\n\n                    // double equal 은 의도한 것임.\n                    // noinspection EqualityComparisonWithCoercionJS\n                    return buttonState == value;\n                },\n            },\n            microbit_ext_get_sensor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.microbit_ext_sensor_light, 'lightLevel'],\n                            [Lang.Blocks.microbit_ext_sensor_temperature, 'temperature'],\n                            [Lang.Blocks.microbit_ext_sensor_compass, 'compassHeading'],\n                        ],\n                        value: 'temperature',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtSensor',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_get_sensor',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    if (value === 'lightLevel') {\n                        let commandType = functionKeys.GET_LIGHT_LEVEL;\n                        this.requestCommandWithResponse(script.entity.id, commandType);\n                    } else if (value === 'compassHeading') {\n                        let commandType = functionKeys.GET_COMPASS_HEADING;\n                        this.requestCommandWithResponse(script.entity.id, commandType);\n                    }\n                    return _get(Entry.hw.portData, ['payload', 'sensorData', value], -1);\n                },\n            },\n            microbit_ext_is_tilt: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.microbit_ext_tilt_left, 0],\n                            [Lang.Blocks.microbit_ext_tilt_right, 1],\n                            [Lang.Blocks.microbit_ext_tilt_front, 2],\n                            [Lang.Blocks.microbit_ext_tilt_rear, 3],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtMove',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_is_tilt',\n                },\n                paramsKeyMap: {\n                    DIRECTION: 0,\n                },\n                func: (sprite, script) => {\n                    const direction = script.getField('DIRECTION');\n\n                    let command;\n                    const sensorDataMap = ['payload', 'sensorData', 'tilt'];\n                    switch (direction) {\n                        case 0:\n                        case 1: {\n                            command = functionKeys.GET_ROLL;\n                            sensorDataMap.push('roll');\n                            break;\n                        }\n                        case 2:\n                        case 3:\n                        default: {\n                            command = functionKeys.GET_PITCH;\n                            sensorDataMap.push('pitch');\n                            break;\n                        }\n                    }\n\n                    const value = _get(Entry.hw.portData, sensorDataMap, -1);\n                    // 기획팀 의도에 따라 30도 이내는 기울지 않았다고 판단\n\n                    /*\n                    좌우 = 우측으로 기울일수록 +\n                    앞뒤 = 뒤로 기울일수록 +\n                     */\n                    switch (direction) {\n                        case 0: // 왼쪽\n                        case 2: // 앞쪽\n                            return value <= -30 && value >= -180;\n                        case 1: // 오른쪽\n                        case 3: // 뒤쪽\n                            return value >= 30 && value <= 180;\n                        default:\n                            return false;\n                    }\n                },\n            },\n            microbit_ext_get_tilt: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.microbit_ext_tilt_left, 0],\n                            [Lang.Blocks.microbit_ext_tilt_right, 1],\n                            [Lang.Blocks.microbit_ext_tilt_front, 2],\n                            [Lang.Blocks.microbit_ext_tilt_rear, 3],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtMove',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_get_tilt',\n                },\n                paramsKeyMap: {\n                    DIRECTION: 0,\n                },\n                func: (sprite, script) => {\n                    const direction = script.getField('DIRECTION');\n\n                    let command;\n                    const sensorDataMap = ['payload', 'sensorData', 'tilt'];\n                    switch (direction) {\n                        case 0:\n                        case 1: {\n                            command = functionKeys.GET_ROLL;\n                            sensorDataMap.push('roll');\n                            break;\n                        }\n                        case 2:\n                        case 3:\n                        default: {\n                            command = functionKeys.GET_PITCH;\n                            sensorDataMap.push('pitch');\n                            break;\n                        }\n                    }\n\n                    const value = _get(Entry.hw.portData, sensorDataMap, -1);\n                    /*\n                    좌우 = 우측으로 기울일수록 +\n                    앞뒤 = 뒤로 기울일수록 +\n                     */\n                    switch (direction) {\n                        case 1: // 오른쪽\n                        case 3: // 뒤쪽\n                            return value;\n                        case 0: // 왼쪽\n                        case 2: // 앞쪽\n                        default:\n                            return -value;\n                    }\n                },\n            },\n            microbit_ext_get_accelerometer: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.microbit_ext_acc_xaxis, 0],\n                            [Lang.Blocks.microbit_ext_acc_yaxis, 1],\n                            [Lang.Blocks.microbit_ext_acc_zaxis, 2],\n                            [Lang.Blocks.microbit_ext_acc_strength, 3],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtSensor',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_get_accelerometer',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    const value = script.getField('VALUE');\n                    let whole = _get(Entry.hw.portData, 'payload.sensorData.accelerometer', -1);\n                    if (whole instanceof Object) {\n                        switch (value) {\n                            case 0:\n                                whole = whole.x;\n                                break;\n                            case 1:\n                                whole = whole.y;\n                                break;\n                            case 2:\n                                whole = whole.z;\n                                break;\n                            case 3:\n                                whole = whole.strength;\n                                break;\n                            default:\n                                whole = whole;\n                                break;\n                        }\n                    }\n                    return whole;\n                },\n            },\n            microbit_ext_get_gesture: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.microbit_ext_gesture_shake, 11],\n                            [Lang.Blocks.microbit_ext_gesture_portrait_top, 1],\n                            [Lang.Blocks.microbit_ext_gesture_portrait_bottom, 2],\n                            [Lang.Blocks.microbit_ext_gesture_portrait_right, 4],\n                            [Lang.Blocks.microbit_ext_gesture_portrait_left, 3],\n                            [Lang.Blocks.microbit_ext_gesture_horizontal_top, 5],\n                            [Lang.Blocks.microbit_ext_gesture_horizontal_bottom, 6],\n                            [Lang.Blocks.microbit_ext_gesture_horizontal_right, 14],\n                            [Lang.Blocks.microbit_ext_gesture_horizontal_left, 13],\n                        ],\n                        value: 11,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtMove',\n                isNotFor: ['microbitExt'],\n                def: {\n                    type: 'microbit_ext_get_gesture',\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    let value = script.getField('VALUE');\n                    const gesture = _get(Entry.hw.portData, 'payload.sensorData.gesture', -1);\n                    // 밸류 중복으로 인해서 생기는 문제로 인해 +10을 오프셋으로 사용\n                    if (value > 11) {\n                        value = value - 10;\n                    }\n                    /**\n                     * 제스쳐는 단 한번만 검사하기 위해 제스쳐가 이전과 다르게 변경된 경우만 검사한다.\n                     * 달라진 경우,\n                     * '흔들림' 이 있는가? = SHAKE event 인지만 검사\n                     * '움직임' 이 있는가? = 제스쳐의 변경 -> 움직임이기 때문에 무조건 true\n                     */\n                    if (this.lastGesture === gesture) {\n                        return false;\n                    } else {\n                        this.lastGesture = gesture;\n                        if (value === 0) {\n                            return this.lastGesture === microbitGestures.SHAKE;\n                        } else if (value == gesture) {\n                            return true;\n                        }\n                        //\n\n                        // } else if (value === 1) {\n                        //     return true;\n                        // }\n                    }\n                },\n            },\n            microbit_ext_set_servo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['P0', 0],\n                            ['P1', 1],\n                            ['P2', 2],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtServo',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['180'],\n                        },\n                    ],\n                    type: 'microbit_ext_set_servo',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                func: (sprite, script) => {\n                    const pinNumber = script.getField('PIN');\n                    const value = _clamp(script.getNumberValue('VALUE'), 0, 180);\n                    this.requestCommand(functionKeys.SET_SERVO, { pinNumber, value });\n                },\n            },\n            microbit_ext_set_servo_period: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['P0', 0],\n                            ['P1', 1],\n                            ['P2', 2],\n                        ],\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                class: 'microbitExtServo',\n                isNotFor: ['microbitExt'],\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['1500'],\n                        },\n                    ],\n                    type: 'microbit_ext_set_servo_period',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                func: (sprite, script) => {\n                    const pinNumber = script.getField('PIN');\n                    const value = script.getNumberValue('VALUE');\n                    this.requestCommand(functionKeys.SET_SERVO_PERIOD, { pinNumber, value });\n                },\n            },\n        };\n    }\n})();\n\nmodule.exports = Entry.MicrobitExt;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_mindpiggy.js",
    "content": "'use strict';\n\nEntry.Mindpiggy = {\n    id: '29.1',\n    name: 'Mindpiggy',\n    url: 'http://inuscoop.com',\n    imageName: 'mindpiggy.png',\n    title: {\n        \"en\": 'mindpiggy',\n        \"ko\": '마인드피기'\n    },\n    setZero: function () {\n        Entry.hw.sendQueue = {\n            GET: {},\n            SET: {},\n        };\n        // var keySet = Object.keys(Entry.hw.sendQueue.SET);\n        // keySet.forEach(function(key) {\n        //     Entry.hw.sendQueue.SET[key].data = 0;\n        // });\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        DIGITAL:0,\n        ANALOG:1,\n        NEOPIXEL:2,\n        SPEAKER:3,\n        DCMOTOR:4,\n        REMOTE:5,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n};\n\n// 언어 적용\nEntry.Mindpiggy.setLanguage = function () {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            template: {\n                mindpiggy_get_analog_value: '아날로그 %1 번 센서값 ',\n                mindpiggy_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                mindpiggy_toggle_led: '디지털 %1 번 핀 %2 %3',\n                mindpiggy_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                mindpiggy_get_digital: '디지털 %1 번 센서값',\n                mindpiggy_get_bool_digital: '디지털 %1 번 센서값 ',\n                mindpiggy_neopixel_on_value: '네오픽셀 %1 번핀  %2 로 설정하기 %3',\n                mindpiggy_neopixel_pixel_on_value: '네오픽셀 %1 번핀 %2번째 픽셀 %3 로 설정하기 %4',\n                mindpiggy_neopixel_off_value: '네오픽셀 %1 번핀 끄기 %2',\n                mindpiggy_set_tone: '스피커 %1 핀 %2 %3의 음으로 %4초 연주하기 %5',\n                mindpiggy_dcmotor_direction_forward: '정방향',\n                mindpiggy_dcmotor_direction_reverse: '역방향',\n                mindpiggy_set_dcmotor:\n                    'DC모터 %1 번 핀을 %2 , %3 번 핀의 속도를 %4 로 정하기 %5',\n                mindpiggy_get_vibration:' 진동센서 %1 번핀 값 ',\n                mindpiggy_module_digital_remote: '리모컨 아날로그 %1 핀 수신값',\n            }\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                mindpiggy_get_analog_value: 'Analog %1 Sensor value',\n                mindpiggy_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                mindpiggy_toggle_led: 'Digital %1 Pin %2 %3',\n                mindpiggy_digital_pwm: 'Digital %1 Pin %2 %3',\n                mindpiggy_get_digital: 'Digital %1 Sensor value',\n                mindpiggy_get_bool_digital: 'Digital %1 Pin Sensor value',\n                mindpiggy_neopixel_on_value: 'Neopixel %1 Pin on %2 %3',\n                mindpiggy_neopixel_pixel_on_value: 'Neopixel %1 Pin %2 pixel on %3 %4',\n                mindpiggy_neopixel_off_value: 'Neopixel %1 Pin off %2',\n                mindpiggy_set_tone: 'play %1 Pin tone on node %2 octave %3 beat %4 %5',\n                mindpiggy_dcmotor_direction_forward: 'forward',\n                mindpiggy_dcmotor_direction_reverse: 'reverse',\n                mindpiggy_set_dcmotor: 'DC Motor %1 pin direction %2 , %3 pin speed %4 %5',\n                mindpiggy_get_vibration:' Vibration %1 pin value ',\n                mindpiggy_module_digital_remote: 'RemoteController Analog %1 Pin value',\n            }\n        }\n    }\n};\n\n// 엔트리에 등록할 블록들의 블록명 작성\nEntry.Mindpiggy.blockMenuBlocks = [\n    \"mindpiggy_get_analog_value\",\n    \"mindpiggy_get_analog_value_map\",\n    \"mindpiggy_toggle_led\",\n    \"mindpiggy_digital_pwm\",\n    \"mindpiggy_get_bool_digital\",\n    \"mindpiggy_get_digital\",\n    \"mindpiggy_get_vibration\",\n    \"mindpiggy_neopixel_on_value\",\n    \"mindpiggy_neopixel_pixel_on_value\",\n    \"mindpiggy_neopixel_off_value\",\n    \"mindpiggy_module_digital_remote\",\n    \"mindpiggy_set_dcmotor\",\n];\n/* 보류\n    \"mindpiggy_set_tone\",\n    \"mindpiggy_get_soundsensor\",\n    \"mindpiggy_get_photo\",\n*/\n// 블록 생성\nEntry.Mindpiggy.getBlocks = function () {\n    return {\n        mindpiggy_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {js: [],py: []},\n        },\n        mindpiggy_get_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: { js: [],py: []},\n        },\n        mindpiggy_digital_pwm_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['~3', '3'],\n                        ['~5', '5'],\n                        ['~6', '6'],\n                        ['~9', '9'],\n                        ['~10', '10'],\n                        ['~11', '11'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n        mindpiggy_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mindpiggy_analog_list',\n                    },\n                ],\n                type: 'mindpiggy_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'MindpiggyNomalBlock',\n            isNotFor: ['Mindpiggy'],\n            func: function(sprite, script) {\n                var port = script.getStringValue('PORT', script);\n                port = String(Number(port)+14);\n                var ANALOG = Entry.hw.portData[port];\n                return ANALOG ? ANALOG['data'] || 0 : 0;\n            },\n            syntax: {js: [], py: ['mindpiggy.analogRead(%1)']},\n        },\n        mindpiggy_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mindpiggy_get_analog_value',\n                        params: [\n                            {\n                                type: 'mindpiggy_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'mindpiggy_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'MindpiggyNomalBlock',\n            isNotFor: ['Mindpiggy'],\n            func: function(sprite, script) {\n                var result = script.getValue('PORT', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var stringValue4 = script.getValue('VALUE4', script);\n                var stringValue5 = script.getValue('VALUE5', script);\n                var isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {js:[], py:['mindpiggy.map(%1, %2, %3, %4, %5)']},\n        },\n        mindpiggy_get_bool_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mindpiggy_get_port_number',\n                    },\n                ],\n                type: 'mindpiggy_get_bool_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'MindpiggyNomalBlock',\n            isNotFor: ['Mindpiggy'],\n            func: function(sprite, script) {\n                var port = script.getStringValue('PORT', script);\n                var val = Entry.hw.portData[port];\n                if (!Entry.hw.sendQueue['GET'])Entry.hw.sendQueue['GET'] = {};\n                Entry.hw.sendQueue['GET'][port]={\n                    type: Entry.Mindpiggy.sensorTypes.DIGITAL,\n                    time: new Date().getTime(),\n                };\n                return val? val['data'] : 0;\n\n            },\n            syntax: {js: [], py: ['mindpiggy.digitalRead(%1)'] },\n        },\n        mindpiggy_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mindpiggy_get_port_number',\n                    },\n                ],\n                type: 'mindpiggy_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'MindpiggyBlock',\n            isNotFor: ['Mindpiggy'],\n            func: function(sprite, script) {\n                var port = script.getStringValue('PORT', script);\n                var val = Entry.hw.portData[port];\n                if (!Entry.hw.sendQueue['GET'])Entry.hw.sendQueue['GET'] = {};\n                Entry.hw.sendQueue['GET'][port]={\n                    type: Entry.Mindpiggy.sensorTypes.DIGITAL,\n                    time: new Date().getTime(),\n                };\n                return val? val['data'] : 0;\n\n            },\n            syntax: {js: [], py: ['mindpiggy.digitalRead(%1)'] },\n        },\n        mindpiggy_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template:'%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OPERATOR');\n            },\n            syntax: { js: [],  py: []},\n        },\n        mindpiggy_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mindpiggy_get_port_number',\n                        params: ['3'],\n                    },\n                    {\n                        type: 'mindpiggy_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'mindpiggy_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'MindpiggyNomalBlock',\n            isNotFor: ['Mindpiggy'],\n            func: function(sprite, script) {\n                var port = script.getStringValue('PORT');\n                var value = script.getValue('VALUE');\n                value = value.toLowerCase();\n                if(value=='on')value=255;\n                else if(value=='off')value=0;\n                if (!Entry.hw.sendQueue['SET'])Entry.hw.sendQueue['SET'] = {};\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Mindpiggy.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n            },\n            syntax: { js: [],  py: ['mindpiggy.digitalWrite(%1, %2)'] },\n        },\n        mindpiggy_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mindpiggy_digital_pwm_list',\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'mindpiggy_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'MindpiggyNomalBlock',\n            isNotFor: ['Mindpiggy'],\n            func: function(sprite, script) {\n                var port = script.getStringValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET'])Entry.hw.sendQueue['SET'] = {};\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.Mindpiggy.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n            },\n            syntax: { js: [], py: ['mindpiggy.analogWrite(%1, %2)' ] },\n        },\n        mindpiggy_rgb:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template:'R %1 G %2 B %3',\n            params:[\n                {\n                    type:'Block',\n                    accept:'string',\n                    defaultType: 'number',\n                },\n                {\n                    type:'Block',\n                    accept:'string',\n                    defaultType: 'number',\n                },\n                {\n                    type:'Block',\n                    accept:'string',\n                    defaultType: 'number',\n                },\n            ],\n            def:{\n                params:[\n                    {\n                        type:'number',\n                    },\n                    {\n                        type:'number',\n                    },\n                    {\n                        type:'number',\n                    },\n                ],\n                type:'mindpiggy_rgb',\n            },\n            paramsKeyMap:{\n                RED:0,\n                GREEN:1,\n                BLUE:2\n            },\n            events:{},\n            class:'MindpiggyBlock',\n            isNotFor:['Mindpiggy'],\n            func:function(sprite,script){\n                var Red = script.getNumberValue('RED');\n                var Green = script.getNumberValue('GREEN');\n                var Blue = script.getNumberValue('BLUE');\n                var rgb = [Red,Green,Blue];\n                rgb.forEach(function(val){\n                    val = Math.round(val);\n                    val = Math.max(val, 0);\n                    val = Math.min(val, 255);\n                });\n                return rgb;\n            },\n            syntax: { js: [], py: []},\n        },\n        mindpiggy_neopixel_on_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type:'Block',\n                    accept:'string'\n                },\n                {\n                    type:'Block',\n                    accept:'string'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def:{\n                params: [\n                    {\n                        type: 'mindpiggy_get_port_number',\n                        params:[11],\n                    },\n                    {\n                        type:'mindpiggy_rgb',\n                        params:[255,110,0],\n                    },\n                    null,\n                ],\n                type:'mindpiggy_neopixel_on_value'\n            },\n            paramsKeyMap:{\n                PORT:0,\n                RGB:1,\n            },\n            events:{},\n            class:'MindpiggyBlock',\n            isNotFor:['Mindpiggy'],\n            func:function(sprite,script){\n                if (!script.isStart){\n                    var Port = script.getStringValue('PORT');\n                    var rgbValue = script.getValue('RGB');\n                    if(!Entry.hw.sendQueue.SET)Entry.hw.sendQueue.SET={};\n                    Entry.hw.sendQueue['SET'][Port]={\n                        type : Entry.Mindpiggy.sensorTypes.NEOPIXEL,\n                        data : [0,255,rgbValue[0],rgbValue[1],rgbValue[2]],\n                        time: new Date().getTime(),\n                    };\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        script.timeFlag = 0;},20);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mindpiggy.neopixel_mood_on_value(%1, %2, %3)'] },\n        },\n        mindpiggy_neopixel_pixel_on_value :{\n            color : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton : 'basic',\n            statements : [],\n            params : [\n                {\n                    type:'Block',\n                    accept:'string'\n                },\n                {\n                    type:'Block',\n                    accept:'string'\n                },\n                {\n                    type:'Block',\n                    accept:'string'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def : {\n                params : [\n                    {\n                        type: 'mindpiggy_get_port_number',\n                        params:[11]\n                    },\n                    {\n                        type:'number',\n                        params:['0']\n                    },\n                    {\n                        type:'mindpiggy_rgb',\n                        params:[255,110,0],\n                    },\n                    null,\n                ],\n                type : 'mindpiggy_neopixel_pixel_on_value'\n            },\n            paramsKeyMap : {\n                PORT: 0,\n                PIXEL: 1,\n                RGB: 2,\n            },\n            events : {},\n            class : 'MindpiggyBlock',\n            isNotFor : ['Mindpiggy'],\n            func:function(sprite,script){\n                if (!script.isStart){\n                    var Port = script.getStringValue('PORT');\n                    var Pixel = script.getNumberValue('PIXEL');\n                    var rgb = script.getValue('RGB');\n                    if(!Entry.hw.sendQueue.SET)Entry.hw.sendQueue.SET={};\n                    Entry.hw.sendQueue['SET'][Port]={\n                        type : Entry.Mindpiggy.sensorTypes.NEOPIXEL,\n                        data : [Pixel,Pixel,rgb[0],rgb[1],rgb[2]],\n                        time: new Date().getTime(),\n                    };\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        script.timeFlag = 0;},20);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mindpiggy.neopixel_mood_pixel_on_value(1%, 2%, 3%, 4%)'] },\n        },\n        mindpiggy_neopixel_off_value : {\n            color : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton : 'basic',\n            statements : [],\n            params : [\n                {\n                    type: 'Block',\n                    accept:'String',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def : {\n                params: [\n                    {\n                        type: 'mindpiggy_get_port_number',\n                        params:[11],\n                    },\n                    null\n                ],\n                type : 'mindpiggy_neopixel_off_value'\n            },\n            paramsKeyMap : {\n                PORT : 0,\n            },\n            events : {},\n            class : 'MindpiggyBlock',\n            isNotFor : ['Mindpiggy'],\n            func:function(sprite,script){\n                if (!script.isStart){\n                    var Port = script.getStringValue('PORT');\n                    if(!Entry.hw.sendQueue.SET)Entry.hw.sendQueue.SET={};\n                    Entry.hw.sendQueue['SET'][Port]={\n                    type : Entry.Mindpiggy.sensorTypes.NEOPIXEL,\n                    data : [0,255,0,0,0],\n                    time: new Date().getTime(),\n                };\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        script.timeFlag = 0;},20);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    return script.callReturn();\n                }\n\n\n            },\n            syntax: { js: [], py: ['mindpiggy.neopixel_mood_off_value()'] },\n        },\n        mindpiggy_get_vibration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '0'],\n                    ],\n                    value : '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'mindpiggy_get_vibration',\n            },\n            paramsKeyMap: {\n                EVENT : 0,\n            },\n            class: 'MindpiggyBlock',\n            isNotFor: ['Mindpiggy'],\n            func:function(sprite,script){\n                var getdata = Entry.hw.portData['3'];\n                if(!Entry.hw.sendQueue.GET)Entry.hw.sendQueue.GET={};\n                Entry.hw.sendQueue.GET['3']={\n                    type : Entry.Mindpiggy.sensorTypes.DIGITAL,\n                    time: new Date().getTime(),\n                };\n                return getdata ? getdata.data : 0;\n            },\n            syntax: { js: [], py: ['mindpiggy.get_vibration(1%)'] },\n        },\n\n        mindpiggy_get_soundsensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'mindpiggy_get_soundsensor',\n            },\n            paramsKeyMap: {},\n            class: 'MindpiggyBlock',\n            isNotFor: ['Mindpiggy'],\n            func:function(sprite,script){\n                var getdata = Entry.hw.portData['15'];\n                if(!Entry.hw.sendQueue.GET)Entry.hw.sendQueue.GET={};\n                Entry.hw.sendQueue.GET['15']={\n                    type : Entry.Mindpiggy.sensorTypes.ANALOG,\n                    time: new Date().getTime(),\n                };\n                return getdata ? getdata.data : 0;\n            },\n            syntax: { js: [], py: ['mindpiggy.get_soundsensor()'] },\n        },\n        mindpiggy_get_photo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['5', '0'],\n                        ['6', '1'],\n                    ],\n                    value : '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mindpiggy_get_photo',\n            },\n            paramsKeyMap: {\n                PINNUM: 0,\n            },\n            class: 'MindpiggyBlock',\n            isNotFor: ['Mindpiggy'],\n            func:function(sprite,script){\n                var pinNum = script.getField('PINNUM');\n                var isSense;\n                if(pinNum === '0'){\n                    isSense = Entry.hw.portData.isPhotoInterrupt&2;\n                }else if(pinNum === '1'){\n                    isSense = Entry.hw.portData.isPhotoInterrupt&1;\n                }\n                if(isSense == 0)return false;\n                else return true;\n            },\n            syntax: { js: [], py: ['mindpiggy.get_photo(%1)'] },\n        },\n        mindpiggy_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        mindpiggy_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        mindpiggy_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mindpiggy_analog_list',\n                    },\n                    {\n                        type: 'mindpiggy_tone_list',\n                    },\n                    {\n                        type: 'mindpiggy_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'mindpiggy_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'MindpiggyExtBlock',\n            isNotFor: ['Mindpiggy'],\n            func: function(sprite, script) {\n                var Port = script.getStringValue('PORT');\n                Port = String(Number(Port)+14);\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note))\n                        note = Entry.Mindpiggy.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (duration === 0) {\n                        // sned\n                        if(!Entry.hw.sendQueue.SET)Entry.hw.sendQueue.SET={};\n                        Entry.hw.sendQueue['SET'][Port]={\n                            type:Entry.Mindpiggy.sensorTypes.SPEAKER,\n                            data:[0,0],\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var frequency = 0;\n\n                    if (note != 0) {\n                        frequency = Entry.Mindpiggy.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    //send\n\n                    if(!Entry.hw.sendQueue.SET)Entry.hw.sendQueue.SET={};\n                    Entry.hw.sendQueue['SET'][Port]={\n                        type:Entry.Mindpiggy.sensorTypes.SPEAKER,\n                        data:[frequency,duration],\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    // send\n                    if(!Entry.hw.sendQueue.SET)Entry.hw.sendQueue.SET={};\n                    Entry.hw.sendQueue['SET'][Port]={\n                        type:Entry.Mindpiggy.sensorTypes.SPEAKER,\n                        data:[0,0],\n                        time: new Date().getTime(),\n                    };\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mindpiggy.set_tone(%1, %2, %3)'] },\n        },\n        mindpiggy_dcmotor_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.mindpiggy_dcmotor_direction_reverse, 'reverse'],\n                        [Lang.template.mindpiggy_dcmotor_direction_forward, 'forward'],\n                    ],\n                    value: 'forward',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('DIRECTION');\n            },\n        },\n        mindpiggy_set_dcmotor:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params:[\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def:{\n                params: [\n                    {\n                        type: 'mindpiggy_get_port_number',\n                        params: [12],\n                    },\n                    {\n                        type: 'mindpiggy_dcmotor_direction'\n                    },\n                    {\n                        type: 'mindpiggy_digital_pwm_list',\n                        params: [10],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type:'mindpiggy_set_dcmotor',\n            },\n            paramsKeyMap:{\n                PORT0: 0,\n                VALUE0: 1,\n                PORT1: 2,\n                VALUE1: 3,\n            },\n            events : {},\n            class : 'MindpiggyExtBlock',\n            isNotFor : ['Mindpiggy'],\n            func:function(sprite,script){\n                var directionPort = script.getStringValue('PORT0');\n                var directionValue = script.getStringValue('VALUE0');\n                var speedPort = script.getStringValue('PORT1');\n                var speedValue = script.getNumberValue('VALUE1');\n                if(directionValue=='reverse') directionValue=0;\n                else if(directionValue=='forward')directionValue=1;\n                speedValue = Math.round(speedValue);\n                speedValue = Math.max(speedValue, 0);\n                speedValue = Math.min(speedValue, 255);\n                if(!Entry.hw.sendQueue.SET)Entry.hw.sendQueue.SET={};\n                Entry.hw.sendQueue['SET'][directionPort]={\n                    type:Entry.Mindpiggy.sensorTypes.DCMOTOR,\n                    data:[directionValue,1],\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][speedPort]={\n                    type:Entry.Mindpiggy.sensorTypes.DCMOTOR,\n                    data:[speedValue,0],\n                    time: new Date().getTime(),\n                };\n            },\n            syntax: { js: [], py: [] },\n        },\n        mindpiggy_module_digital_remote:{\n            color:EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine:EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor:'#fff',\n            skeleton:'basic_string_field',\n            statements:[],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'mindpiggy_module_digital_remote',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'MindpiggyExtBlock',\n            isNotFor: ['Mindpiggy'],\n            func: function(sprite, script) {\n                // var port = script.getStringValue('PORT', script);\n                // port = String(Number(port)+14);\n                var REMOTE = Entry.hw.portData['A0'];\n                if (!Entry.hw.sendQueue['GET'])Entry.hw.sendQueue['GET'] = {};\n                Entry.hw.sendQueue['GET']['14']={\n                    type: Entry.Mindpiggy.sensorTypes.REMOTE,\n                    time: new Date().getTime(),\n                };\n                if(REMOTE && (REMOTE['data']!=255))return REMOTE['data'];\n                else return String('x');\n            },\n            syntax: { js: [], py: ['mindpiggy.module_digital_remote(%1)'] },\n        },\n    }\n};\n\n// 엔트리에서 하드웨어 블록 클래스를 인식할 수 있도록 내보내기\nmodule.exports = Entry.Mindpiggy;"
  },
  {
    "path": "src/playground/blocks/hardware/block_mkboard.js",
    "content": "'use strict';\n\nEntry.mkboard = {\n    id: '6.1',\n    name: 'mkboard',\n    url: 'http://www.jkelec.co.kr',\n    imageName: 'mkboard.png',\n    title: {\n        en: 'MakeBrick',\n        ko: '메이크브릭',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    toByte: function(data) {\n        switch (data) {\n            case ' ':\n                data = 32;\n                break;\n            case '!':\n                data = 33;\n                break;\n            case '\"':\n                data = 34;\n                break;\n            case '#':\n                data = 35;\n                break;\n            case '$':\n                data = 36;\n                break;\n            case '%':\n                data = 37;\n                break;\n            case '&':\n                data = 38;\n                break;\n            case \"'\":\n                data = 39;\n                break;\n            case '(':\n                data = 40;\n                break;\n            case ')':\n                data = 41;\n                break;\n            case '*':\n                data = 42;\n                break;\n            case '+':\n                data = 43;\n                break;\n            case ',':\n                data = 44;\n                break;\n            case '-':\n                data = 45;\n                break;\n            case '.':\n                data = 46;\n                break;\n            case '/':\n                data = 47;\n                break;\n            case '0':\n                data = 48;\n                break;\n            case '1':\n                data = 49;\n                break;\n            case '2':\n                data = 50;\n                break;\n            case '3':\n                data = 51;\n                break;\n            case '4':\n                data = 52;\n                break;\n            case '5':\n                data = 53;\n                break;\n            case '6':\n                data = 54;\n                break;\n            case '7':\n                data = 55;\n                break;\n            case '8':\n                data = 56;\n                break;\n            case '9':\n                data = 57;\n                break;\n            case ':':\n                data = 58;\n                break;\n            case ';':\n                data = 59;\n                break;\n            case '<':\n                data = 60;\n                break;\n            case '=':\n                data = 61;\n                break;\n            case '>':\n                data = 62;\n                break;\n            case '?':\n                data = 63;\n                break;\n            case '@':\n                data = 64;\n                break;\n            case 'A':\n                data = 65;\n                break;\n            case 'B':\n                data = 66;\n                break;\n            case 'C':\n                data = 67;\n                break;\n            case 'D':\n                data = 68;\n                break;\n            case 'E':\n                data = 69;\n                break;\n            case 'F':\n                data = 70;\n                break;\n            case 'G':\n                data = 71;\n                break;\n            case 'H':\n                data = 72;\n                break;\n            case 'I':\n                data = 73;\n                break;\n            case 'J':\n                data = 74;\n                break;\n            case 'K':\n                data = 75;\n                break;\n            case 'L':\n                data = 76;\n                break;\n            case 'M':\n                data = 77;\n                break;\n            case 'N':\n                data = 78;\n                break;\n            case 'O':\n                data = 79;\n                break;\n            case 'P':\n                data = 80;\n                break;\n            case 'Q':\n                data = 81;\n                break;\n            case 'R':\n                data = 82;\n                break;\n            case 'S':\n                data = 83;\n                break;\n            case 'T':\n                data = 84;\n                break;\n            case 'U':\n                data = 85;\n                break;\n            case 'V':\n                data = 86;\n                break;\n            case 'W':\n                data = 87;\n                break;\n            case 'X':\n                data = 88;\n                break;\n            case 'Y':\n                data = 89;\n                break;\n            case 'Z':\n                data = 90;\n                break;\n            case '[':\n                data = 91;\n                break;\n            case '\\\\':\n                data = 92;\n                break;\n            case ']':\n                data = 93;\n                break;\n            case '^':\n                data = 94;\n                break;\n            case '_':\n                data = 95;\n                break;\n            case '`':\n                data = 96;\n                break;\n            case 'a':\n                data = 97;\n                break;\n            case 'b':\n                data = 98;\n                break;\n            case 'c':\n                data = 99;\n                break;\n            case 'd':\n                data = 100;\n                break;\n            case 'e':\n                data = 101;\n                break;\n            case 'f':\n                data = 102;\n                break;\n            case 'g':\n                data = 103;\n                break;\n            case 'h':\n                data = 104;\n                break;\n            case 'i':\n                data = 105;\n                break;\n            case 'j':\n                data = 106;\n                break;\n            case 'k':\n                data = 107;\n                break;\n            case 'l':\n                data = 108;\n                break;\n            case 'm':\n                data = 109;\n                break;\n            case 'n':\n                data = 110;\n                break;\n            case 'o':\n                data = 111;\n                break;\n            case 'p':\n                data = 112;\n                break;\n            case 'q':\n                data = 113;\n                break;\n            case 'r':\n                data = 114;\n                break;\n            case 's':\n                data = 115;\n                break;\n            case 't':\n                data = 116;\n                break;\n            case 'u':\n                data = 117;\n                break;\n            case 'v':\n                data = 118;\n                break;\n            case 'w':\n                data = 119;\n                break;\n            case 'x':\n                data = 120;\n                break;\n            case 'y':\n                data = 121;\n                break;\n            case 'z':\n                data = 122;\n                break;\n            case '{':\n                data = 123;\n                break;\n            case '|':\n                data = 124;\n                break;\n            case '}':\n                data = 125;\n                break;\n            case '~':\n                data = 126;\n                break;\n        }\n\n        return data;\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC_1: 7,\n        ULTRASONIC_2: 8,\n        TIMER: 9,\n        LCD: 10,\n        SEGMENT: 11,\n        OLED: 12,\n        MATRIX: 13,\n        NEOPIXEL: 14,\n        PMS5003: 15,\n        PMS5003_PM10: 16,\n        PMS5003_PM25: 17,\n        PMS5003_PM100: 18,\n        LSM303_ACCEL: 19,\n        LSM303_ACCEL_X: 20,\n        LSM303_ACCEL_Y: 21,\n        LSM303_ACCEL_Z: 22,\n        LSM303_COMPASS: 23,\n        ULTRASONIC_1_USE: 24,\n        ULTRASONIC_2_USE: 25,\n        UNKNOWN_SENSOR: 99,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    directionTable: {\n        Forward: 0,\n        Backward: 1,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    duration: {\n        TIME_1ms: 1,\n        TIME_5ms: 5,\n        TIME_10ms: 10,\n        TIME_20ms: 20,\n        TIME_50ms: 50,\n        TIME_100ms: 100,\n        TIME_200ms: 200,\n        TIME_500ms: 500,\n        TIME_600ms: 600,\n    },\n    BlockState: {},\n};\n\nEntry.mkboard.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                mkboard_get_ultrasonic_value: '초음파센서 Trig %1 Echo %2 센서값',\n                mkboard_set_lcd: '1602 문자 LCD %1 행 , %2열에 %3 출력하기 %4',\n                mkboard_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                mkboard_get_analog_value: '아날로그 %1 번 센서값',\n                mkboard_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                mkboard_get_digital: '디지털 %1 번 센서값',\n                mkboard_get_ultrasonic_1_use: '초음파센서 1번 Trig %1 Echo %2 시작 %3',\n                mkboard_get_ultrasonic_1_value: '초음파센서 1번 센서값',\n                mkboard_get_ultrasonic_2_use: '초음파센서 2번 Trig %1 Echo %2 시작 %3',\n                mkboard_get_ultrasonic_2_value: '초음파센서 2번 센서값',\n                mkboard_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                mkboard_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                mkboard_toggle_led: '디지털 %1 번 핀 %2 %3',\n                mkboard_lcd_print: '1602 LCD : 문자를 %1 행 %2 열에 %3 출력 %4',\n                mkboard_lcd_init: '1602 LCD : LCD를 %1 로 초기화 %2',\n                mkboard_lcd_command: '1602 LCD : LCD에 %1 명령어 수행 %2',\n                mkboard_segment_init: 'FND : 디지털 CLK을 %1 DIO를 %2 로 설정 %3',\n                mkboard_segment_bright: 'FND : 밝기를 %1 로 설정 하기 %2',\n                mkboard_segment_clear: 'FND : 세그먼트 내용 지우기 %1',\n                mkboard_segment_value: 'FND : 숫자 %1 를 소숫점 이하 %2로 출력 0 채움 %3 %4',\n                mkboard_oled_init: 'OLED : OLED를 %1 로 초기화 %2',\n                mkboard_oled_clear: 'OLED : OLED 내용 지우기 %1',\n                mkboard_oled_print: 'OLED : %1 행, %2 열에 문자열 %3 출력 %4',\n                mkboard_oled_print_number:\n                    'OLED : %1 행 %2 열에 숫자 %3 를 소수점 이하 %4로 출력 %5',\n                mkboard_matrix_init:\n                    '매트릭스 : 총 개수 %1 매트릭스 Data %2 Clk %3 CS %4로 설정 %5',\n                mkboard_matrix_bright: '매트릭스 : %1 매트릭스 밝기를 %2 로 설정 하기 %3',\n                mkboard_matrix_clear: '매트릭스 : %1 매트릭스 내용 지우기 %2',\n                mkboard_matrix_set: '매트릭스 : %1 매트릭스 %2행 %3열 위치 %4 %5',\n                mkboard_matrix_set_row: '매트릭스 : %1 매트릭스 %2행에 2진수 %3 출력 %4',\n                mkboard_matrix_set_col: '매트릭스 : %1 매트릭스 %2열에 2진수 %3 출력 %4',\n                mkboard_matrix_char: '매트릭스 : %1 문자 %2 출력 %3',\n                mkboard_neopixel_init:\n                    '네오픽셀(%1) : 디지털 %2 번 핀으로 설정(LED 개수 %3개) %4 로 설정',\n                mkboard_neopixel_set_rgb: '네오픽셀(RGB) : %1 번째 LED를 색상 (R:%2 G:%3 B:%4) %5',\n                mkboard_neopixel_set_rgbw:\n                    '네오픽셀(RGBW) : %1 번째 LED를 색상 (R:%2 G:%3 B:%4 W:%5) %6',\n                mkboard_neopixel_on: '네오픽셀 : 설정한 값으로 네오픽셀 %1 %2',\n                mkboard_pms5003_init: '먼지센서 : RX핀 %1 TX핀 %2로 설정 %3',\n                mkboard_pms5003_measure: '먼지센서 : 먼지 값 측정 시작하기 %1',\n                mkboard_pms5003_read: '먼지센서 : %1 먼지 값 읽오 오기 %2',\n                mkboard_lsm303_accel_init: '가속도센서 : 초기화 %1',\n                mkboard_lsm303_accel_measure: '가속도센서 : 가속도 값 측정 시작하기 %1',\n                mkboard_lsm303_accel_read: '가속도센서 : %1 축 가속도 값 읽기 %2',\n                mkboard_lsm303_compass_init: '나침반센서 : 초기화 %1',\n                mkboard_lsm303_compass_measure: '나침반센서 : 방위각 측정 시작하기 %1',\n                mkboard_lsm303_compass_read: '나침반센서 : 방위각 읽기 %1',\n            },\n        },\n        en: {\n            template: {\n                mkboard_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                mkboard_set_lcd: '1602 LCD Row %1, Column %2 Value %3 %4',\n                mkboard_digital_pwm: 'Digital %1 Pin %2 %3',\n                mkboard_get_analog_value: 'Analog %1 Sensor value',\n                mkboard_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                mkboard_get_digital: 'Digital %1 Sensor value',\n                mkboard_get_ultrasonic_1_use: 'Start ultrasonic 1 sensor trig pin %1 echo pin %2',\n                mkboard_get_ultrasonic_1_value: 'Read ultrasonic 1 sensor value',\n                mkboard_get_ultrasonic_2_use: 'Start ultrasonic 2 sensor trig pin %1 echo pin %2',\n                mkboard_get_ultrasonic_2_value: 'Read ultrasonic 2 sensor value',\n                mkboard_set_servo: 'Set servo pin %1 angle as %2 %3',\n                mkboard_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                mkboard_toggle_led: 'Digital %1 Pin %2 %3',\n                mkboard_lcd_print: '1602 LCD : Print Row %1, Column %2, Value %3 %4',\n                mkboard_lcd_init: '1602 LCD : LCD initialize %1 %2',\n                mkboard_lcd_command: '1602 LCD : Execute %1 command %2',\n                mkboard_segment_init: 'FND : Set digital CLK %1 DIO %2 %3',\n                mkboard_segment_bright: 'FND : Set bright %1 %2',\n                mkboard_segment_clear: 'FND : Clear all segment value %1',\n                mkboard_segment_value: 'FND : Print number %1 point %2 fill zero %3 %4',\n                mkboard_oled_init: 'OLED : Initialize OLED %1 %2',\n                mkboard_oled_clear: 'OLED : Clear OLED %1',\n                mkboard_oled_print: 'OLED : Row %1, Col %2 print string %3 %4',\n                mkboard_oled_print_number: 'OLED : Row %1, Col %2 print number %3 point %4 %5',\n                mkboard_maxtrix_init:\n                    'Matrix : Count %1, Matrix initialize Data %2 Clk %3 CS %4 %5',\n                mkboard_maxtrix_set: 'Matrix : No %1, Matrix set Row %2 Col %3 %4 %5',\n                mkboard_matrix_bright: 'Matrix : No %1, Matrix Set bright %2 %3',\n                mkboard_matrix_clear: 'Matrix : No %1, Matrix All clear %2',\n                mkboard_matrix_set_row: 'Matrix : No %1, Matrix Row %2, Binary number %3 print %4',\n                mkboard_matrix_set_col:\n                    'Matrix : No %1, Matrix Column %2, Binary number %3 print %4',\n                mkboard_matrix_char: 'Matrix : No %1, Matrix Char %2 print %3',\n                mkboard_neopixel_init: 'Nexpixel(%1) : Set Digital pin %2(LED count %3) %4',\n                mkboard_neopixel_set_rgb: 'Nexpixel(RGB) : LED %1 Set color (R:%2 G:%3 B:%4) %5',\n                mkboard_neopixel_set_rgbw:\n                    'Nexpixel(RGBW) : LED %1 Set color (R:%2 G:%3 B:%4 W:%5) %6',\n                mkboard_neopixel_on: 'Nexpixel : Nexpixel LED %1 %2',\n                mkboard_pms5003_init: 'Dust Sensor : Set pin RX %1, TX %2 %3',\n                mkboard_pms5003_measure: 'Dust Sensor : Sensor measure %1',\n                mkboard_pms5003_read: 'Dust Sensor : Read %1 value %2',\n                mkboard_lsm303_accel_init: 'Accelerometer : Initialize %1',\n                mkboard_lsm303_accel_measure: 'Accelerometer : Sensor measure %1',\n                mkboard_lsm303_accel_read: 'Accelerometer : Read %1 Axis %2',\n                mkboard_lsm303_compass_init: 'Compass : Initialize %1',\n                mkboard_lsm303_compass_measure: 'Compass : Sensor measure %1',\n                mkboard_lsm303_compass_read: 'Compass : Read compass value %1',\n            },\n        },\n    };\n};\n\nEntry.mkboard.blockMenuBlocks = [\n    // mkboard Added 2017-07-04\n    'mkboard_get_analog_value',\n    'mkboard_get_analog_value_map',\n    'mkboard_get_digital',\n\n    'mkboard_get_ultrasonic_1_use',\n    'mkboard_get_ultrasonic_1_value',\n    'mkboard_get_ultrasonic_2_use',\n    'mkboard_get_ultrasonic_2_value',\n\n    'mkboard_toggle_led',\n    'mkboard_digital_pwm',\n    'mkboard_set_servo',\n    'mkboard_set_tone',\n\n    'mkboard_lcd_init',\n    'mkboard_lcd_command',\n    'mkboard_lcd_print',\n\n    'mkboard_segment_init',\n    'mkboard_segment_bright',\n    'mkboard_segment_clear',\n    'mkboard_segment_value',\n\n    'mkboard_oled_init',\n    'mkboard_oled_clear',\n    'mkboard_oled_print',\n    'mkboard_oled_print_number',\n\n    'mkboard_matrix_init',\n    'mkboard_matrix_bright',\n    'mkboard_matrix_clear',\n    'mkboard_matrix_set',\n    'mkboard_matrix_set_row',\n    'mkboard_matrix_set_col',\n    'mkboard_matrix_char',\n\n    'mkboard_neopixel_init',\n    'mkboard_neopixel_set_rgb',\n    'mkboard_neopixel_set_rgbw',\n    'mkboard_neopixel_on',\n\n    'mkboard_pms5003_init',\n    'mkboard_pms5003_measure',\n    'mkboard_pms5003_read',\n\n    'mkboard_lsm303_accel_init',\n    'mkboard_lsm303_accel_measure',\n    'mkboard_lsm303_accel_read',\n\n    'mkboard_lsm303_compass_init',\n    'mkboard_lsm303_compass_measure',\n    'mkboard_lsm303_compass_read',\n\n    // mkboard Added 2017-07-04\n];\nEntry.mkboard.getBlocks = function() {\n    return {\n        //region mkboard 몽키보드\n        mkboard_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                        ['A6', '6'],\n                        ['A7', '7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_analog_list',\n                    },\n                ],\n                type: 'mkboard_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'mkboardGet',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_get_analog_value',\n                        params: [\n                            {\n                                type: 'mkboard_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'mkboard_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'mkboardGet',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var result = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return result;\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_get_ultrasonic_1_use: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_get_ultrasonic_1_use,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                ],\n                type: 'mkboard_get_ultrasonic_1_use',\n            },\n            paramsKeyMap: {\n                TRIG: 0,\n                ECHO: 1,\n            },\n            class: 'mkboardUltrasound',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var trig = script.getNumberValue('TRIG', script);\n                var echo = script.getNumberValue('ECHO', script);\n                //console.log(\"ULTRASONIC_1_USE\");\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_500ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.ULTRASONIC_1_USE,\n                        data: {\n                            trig: trig,\n                            echo: echo,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_get_ultrasonic_1_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            // template: Lang.template.mkboard_get_ultrasonic_1_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_get_ultrasonic_1_value',\n            },\n            //paramsKeyMap: {\n            //    PORT1: 0,\n            //    PORT2: 1,\n            //},\n            class: 'mkboardUltrasound',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                //var port1 = script.getNumberValue('PORT1', script);\n                //var port2 = script.getNumberValue('PORT2', script);\n\n                /*\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][0];\n                delete Entry.hw.sendQueue['SET'][0];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.mkboard.sensorTypes.ULTRASONIC_1] = {\n                    port: [0, 0],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC_1 || 0;\n                */\n                return Entry.hw.portData.ULTRASONIC_1 || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_get_ultrasonic_2_use: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_get_ultrasonic_2_use,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['5'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'mkboard_get_ultrasonic_2_use',\n            },\n            paramsKeyMap: {\n                TRIG: 0,\n                ECHO: 1,\n            },\n            class: 'mkboardUltrasound',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var trig = script.getNumberValue('TRIG', script);\n                var echo = script.getNumberValue('ECHO', script);\n                //console.log(\"ULTRASONIC_2_USE\");\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_500ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.ULTRASONIC_2_USE,\n                        data: {\n                            trig: trig,\n                            echo: echo,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_get_ultrasonic_2_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            // template: Lang.template.mkboard_get_ultrasonic_2_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_get_ultrasonic_2_value',\n            },\n            //paramsKeyMap: {\n            //    PORT1: 0,\n            //    PORT2: 1,\n            //},\n            class: 'mkboardUltrasound',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                //var port1 = script.getNumberValue('PORT1', script);\n                //var port2 = script.getNumberValue('PORT2', script);\n\n                /*\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][0];\n                delete Entry.hw.sendQueue['SET'][0];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.mkboard.sensorTypes.ULTRASONIC_2] = {\n                    port: [0, 0],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC_2 || 0;\n                */\n                return Entry.hw.portData.ULTRASONIC_2 || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'mkboard_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'mkboardGet',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.mkboard.sensorTypes.DIGITAL] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'mkboard',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.mkboard.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.mkboard.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.mkboard.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'mkboard',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.mkboard.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_tone_list',\n                    },\n                ],\n                type: 'mkboard_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        value: 4,\n                        params: ['11'],\n                    },\n                    {\n                        type: 'mkboard_tone_list',\n                    },\n                    {\n                        type: 'mkboard_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'mkboard',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) note = Entry.mkboard.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    var duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.mkboard.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    var value = 0;\n\n                    if (note != 0) {\n                        value = Entry.mkboard.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.mkboard.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.mkboard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'mkboard',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                value = Math.min(360, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.mkboard.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        mkboard_list_digital_lcd_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LINE1', '0'],\n                        ['LINE2', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        mkboard_list_digital_lcd_column: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['COL1', '0'],\n                        ['COL2', '1'],\n                        ['COL3', '2'],\n                        ['COL4', '3'],\n                        ['COL5', '4'],\n                        ['COL6', '5'],\n                        ['COL7', '6'],\n                        ['COL8', '7'],\n                        ['COL9', '8'],\n                        ['COL10', '9'],\n                        ['COL11', '10'],\n                        ['COL12', '11'],\n                        ['COL13', '12'],\n                        ['COL14', '13'],\n                        ['COL15', '14'],\n                        ['COL16', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLUMN: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('COLUMN');\n            },\n        },\n\n        mkboard_list_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x20', '0x20'],\n                        ['0x27', '0x27'],\n                        ['0x3f', '0x3f'],\n                    ],\n                    value: '0x27',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LCD_INIT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LCD_INIT');\n            },\n        },\n\n        mkboard_list_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LCD_CLEAR', '0'],\n                        /*,\n                        [ \"BACKLIGHT_ON\", \"3\" ],\n                        [ \"BACKLIGHT_OFF\", \"4\" ]\n                        */\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LCD_COMMAND: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LCD_COMMAND');\n            },\n        },\n\n        mkboard_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_lcd_init,\n            //\"template\": \"%1 %2\",\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_list_lcd_init',\n                        params: ['0x27'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_lcd_init',\n            },\n            paramsKeyMap: {\n                LCD_INIT: 0,\n            },\n            class: 'mkboardLcd',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var value = script.getNumberValue('LCD_INIT', script);\n                //var value = script.getValue('LCD_INIT', script);\n\n                //console.log(\"LCD_INIT=\");\n                //console.log(value);\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_500ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.LCD,\n                        data: {\n                            cmd: 0,\n                            value: value,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lcd_init(%1)'] },\n        },\n\n        mkboard_lcd_command: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_lcd_command,\n            //\"template\": \"%1 %2\",\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_list_lcd_command',\n                    },\n                    null,\n                ],\n                type: 'mkboard_lcd_command',\n            },\n            paramsKeyMap: {\n                LCD_COMMAND: 0,\n            },\n            class: 'mkboardLcd',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var value = script.getNumberValue('LCD_COMMAND', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_100ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.LCD,\n                        data: {\n                            cmd: 1,\n                            value: value,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lcd_command(%1)'] },\n        },\n\n        mkboard_lcd_print: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_lcd_print,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_list_digital_lcd_line',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'mkboard_list_digital_lcd_column',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Type text !!'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_lcd_print',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                COLUMN: 1,\n                STRING: 2,\n            },\n            class: 'mkboardLcd',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var line = script.getValue('LINE', script);\n                var column = script.getValue('COLUMN', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n\n                if (!script.isStart) {\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = Entry.mkboard.toByte(string[i]);\n                        }\n                    } else if (typeof string === 'number') {\n                        //console.log(\"string\");\n                        //console.log(string);\n                        var num_to_string = string.toString();\n                        for (var i = 0; i < num_to_string.length; i++) {\n                            text[i] = Entry.mkboard.toByte(num_to_string[i]);\n                        }\n                        //console.log(\"num_to_string\");\n                        //console.log(num_to_string);\n                        //text[0] = 1;\n                        //text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    //var fps = Entry.FPS || 60;\n                    //var timeValue = 60 / fps * 50;\n                    var duration = Entry.mkboard.duration.TIME_100ms;\n\n                    Entry.hw.sendQueue['SET'][1] = {\n                        type: Entry.mkboard.sensorTypes.LCD,\n                        data: {\n                            cmd: 2,\n                            line: line,\n                            column: column,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lcd_print(%1, %2, %3)'] },\n        },\n\n        mkboard_list_segment_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                BRIGHT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('BRIGHT');\n            },\n        },\n\n        mkboard_list_segment_comma: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                SEGMENT_COMMA: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('SEGMENT_COMMA');\n            },\n        },\n\n        mkboard_segment_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_segment_init,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_segment_init',\n            },\n            paramsKeyMap: {\n                PORT_CLK: 0,\n                PORT_DIO: 1,\n            },\n            class: 'mkboardSegment',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var port_clk = script.getNumberValue('PORT_CLK', script);\n                var port_dio = script.getNumberValue('PORT_DIO', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_500ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.SEGMENT,\n                        data: {\n                            cmd: 0, // 포트설정\n                            port_clk: port_clk,\n                            port_dio: port_dio,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_segment_init(%1, %2)'] },\n        },\n\n        mkboard_segment_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_segment_bright,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_list_segment_bright',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_segment_bright',\n            },\n            paramsKeyMap: {\n                BRIGHT: 0,\n            },\n            class: 'mkboardSegment',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var bright = script.getNumberValue('BRIGHT', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.SEGMENT,\n                        data: {\n                            cmd: 1, // 밝기설정\n                            bright: bright,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_segment_bright(%1)'] },\n        },\n\n        mkboard_segment_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_segment_clear,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_segment_clear',\n            },\n            //paramsKeyMap: {\n            //    PORT_RX: 0,\n            //    PORT_TX: 1,\n            //},\n            class: 'mkboardSegment',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.SEGMENT,\n                        data: {\n                            cmd: 3, // Segment Clear\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_segment_clear()'] },\n        },\n\n        mkboard_segment_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_segment_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['888'],\n                    },\n                    {\n                        type: 'mkboard_list_segment_comma',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['off'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_segment_value',\n            },\n            paramsKeyMap: {\n                NUMBER: 0,\n                SEGMENT_COMMA: 1,\n                ON_OFF: 2,\n            },\n            class: 'mkboardSegment',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var number = script.getNumberValue('NUMBER');\n                var segment_comma = script.getNumberValue('SEGMENT_COMMA');\n                var on_off = script.getValue('ON_OFF');\n\n                number = Math.round(number);\n                number = Math.max(number, 0);\n                number = Math.min(number, 999);\n\n                if (typeof on_off === 'string') {\n                    on_off = on_off.toLowerCase();\n                }\n                if (Entry.mkboard.highList.indexOf(on_off) > -1) {\n                    on_off = 1;\n                } else if (Entry.mkboard.lowList.indexOf(on_off) > -1) {\n                    on_off = 0;\n                } else {\n                    throw new Error();\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_100ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.SEGMENT,\n                        data: {\n                            cmd: 2, // 데이터출력\n                            number: number,\n                            segment_comma: segment_comma,\n                            on_off: on_off,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_segment_value(%1, %2, %3)'] },\n        },\n\n        mkboard_list_oled_comma: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OLED_COMMA: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OLED_COMMA');\n            },\n        },\n\n        mkboard_oled_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_oled_init,\n            //\"template\": \"%1 %2\",\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0x3C'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_oled_init',\n            },\n            paramsKeyMap: {\n                OLED_INIT: 0,\n            },\n            class: 'mkboardOled',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var oled_init = script.getNumberValue('OLED_INIT', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_500ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.OLED,\n                        data: {\n                            cmd: 0, // OLED Initialize\n                            oled_init: oled_init,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_oled_init(%)'] },\n        },\n\n        mkboard_oled_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_oled_clear,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_oled_clear',\n            },\n            //paramsKeyMap: {\n            //    PORT_RX: 0,\n            //    PORT_TX: 1,\n            //},\n            class: 'mkboardOled',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.OLED,\n                        data: {\n                            cmd: 3, // OLED Clear\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_oled_clear()'] },\n        },\n\n        mkboard_oled_print: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_oled_print,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['Type text !!'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_oled_print',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                COLUMN: 1,\n                STRING: 2,\n            },\n            class: 'mkboardOled',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var line = script.getNumberValue('LINE', script);\n                var column = script.getNumberValue('COLUMN', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n\n                if (!script.isStart) {\n                    line = Math.min(5, line);\n                    line = Math.max(0, line);\n\n                    column = Math.min(20, column);\n                    column = Math.max(0, column);\n\n                    if (typeof string === 'string') {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = Entry.mkboard.toByte(string[i]);\n                        }\n                    } else if (typeof string === 'number') {\n                        //console.log(\"string\");\n                        //console.log(string);\n                        var num_to_string = string.toString();\n                        for (var i = 0; i < num_to_string.length; i++) {\n                            text[i] = Entry.mkboard.toByte(num_to_string[i]);\n                        }\n                        //console.log(\"num_to_string\");\n                        //console.log(num_to_string);\n                        //text[0] = 1;\n                        //text[1] = string / 1;\n                    } else {\n                        text[0] = string;\n                    }\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.OLED,\n                        data: {\n                            cmd: 1,\n                            line: line,\n                            column: column,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                            text8: text[8],\n                            text9: text[9],\n                            text10: text[10],\n                            text11: text[11],\n                            text12: text[12],\n                            text13: text[13],\n                            text14: text[14],\n                            text15: text[15],\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_oled_print(%1, %2, %3)'] },\n        },\n\n        mkboard_oled_print_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_oled_print_number,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['999'],\n                    },\n                    {\n                        type: 'mkboard_list_oled_comma',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_oled_print_number',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                COLUMN: 1,\n                NUMBER: 2,\n                OLED_COMMA: 3,\n            },\n            class: 'mkboardOled',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var line = script.getNumberValue('LINE', script);\n                var column = script.getNumberValue('COLUMN', script);\n                var number = script.getNumberValue('NUMBER', script);\n                var oled_comma = script.getNumberValue('OLED_COMMA', script);\n\n                if (!script.isStart) {\n                    line = Math.min(5, line);\n                    line = Math.max(0, line);\n\n                    column = Math.min(20, column);\n                    column = Math.max(0, column);\n\n                    number = Math.round(number);\n                    number = Math.max(number, 0);\n                    number = Math.min(number, 65535);\n\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.OLED,\n                        data: {\n                            cmd: 2, // 데이터출력\n                            line: line,\n                            column: column,\n                            number: number,\n                            oled_comma: oled_comma,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_oled_print_number(%1, %2, %3, %4)'] },\n        },\n\n        mkboard_matrix_count_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                MATRIX_NUM: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('MATRIX_NUM');\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        mkboard_list_matrix_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '7',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                BRIGHT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('BRIGHT');\n            },\n        },\n\n        mkboard_matrix_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_matrix_init,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['11'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_matrix_init',\n            },\n            paramsKeyMap: {\n                MATRIX_NUM: 0,\n                PORT_DATA: 1,\n                PORT_CLK: 2,\n                PORT_CS: 3,\n            },\n            class: 'mkboardMatrix',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var matrix_num = script.getValue('MATRIX_NUM', script);\n                var port_data = script.getValue('PORT_DATA', script);\n                var port_clk = script.getValue('PORT_CLK', script);\n                var port_cs = script.getValue('PORT_CS', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.MATRIX,\n                        data: {\n                            cmd: 0, // 포트설정\n                            matrix_num: matrix_num,\n                            port_data: port_data,\n                            port_clk: port_clk,\n                            port_cs: port_cs,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_matrix_init(%1, %2, %3, %4)'] },\n        },\n\n        mkboard_matrix_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_matrix_bright,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'mkboard_list_matrix_bright',\n                        params: ['7'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_matrix_bright',\n            },\n            paramsKeyMap: {\n                MATRIX_NUM: 0,\n                BRIGHT: 0,\n            },\n            class: 'mkboardMatrix',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var matrix_num = script.getValue('MATRIX_NUM', script);\n                var bright = script.getValue('BRIGHT', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.MATRIX,\n                        data: {\n                            cmd: 1, // 밝기설정\n                            matrix_num: matrix_num,\n                            bright: bright,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_matrix_bright(%1, %2)'] },\n        },\n\n        mkboard_matrix_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_matrix_clear,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_matrix_clear',\n            },\n            paramsKeyMap: {\n                MATRIX_NUM: 0,\n            },\n            class: 'mkboardMatrix',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var matrix_num = script.getValue('MATRIX_NUM', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.MATRIX,\n                        data: {\n                            cmd: 2, // Matrix Clear\n                            matrix_num: matrix_num,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_matrix_clear(%1)'] },\n        },\n\n        mkboard_matrix_set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_matrix_set,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_matrix_set',\n            },\n            paramsKeyMap: {\n                MATRIX_NUM: 0,\n                MATRIX_ROW: 1,\n                MATRIX_COL: 2,\n                MATRIX_ON_OFF: 3,\n            },\n            class: 'mkboardMatrix',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var matrix_num = script.getValue('MATRIX_NUM', script);\n                var matrix_row = script.getValue('MATRIX_ROW', script);\n                var matrix_col = script.getValue('MATRIX_COL', script);\n                var matrix_on_off = script.getValue('MATRIX_ON_OFF', script);\n\n                // var matrix_num_row = script.getNumberValue('MATRIX_ROW', script);\n\n                // console.log(\"mkboard_matrix_set\");\n                // console.log(\"matrix_row=\");\n                // console.log(matrix_row);\n\n                // console.log(\"matrix_num_row=\");\n                // console.log(matrix_num_row);\n\n                if (typeof matrix_on_off === 'string') {\n                    matrix_on_off = matrix_on_off.toLowerCase();\n                }\n                if (Entry.mkboard.highList.indexOf(matrix_on_off) > -1) {\n                    matrix_on_off = 1;\n                } else if (Entry.mkboard.lowList.indexOf(matrix_on_off) > -1) {\n                    matrix_on_off = 0;\n                } else {\n                    throw new Error();\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.MATRIX,\n                        data: {\n                            cmd: 3, // 포트설정\n                            matrix_num: matrix_num,\n                            matrix_row: matrix_row,\n                            matrix_col: matrix_col,\n                            matrix_on_off: matrix_on_off,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_matrix_set(%1, %2, %3, %4)'] },\n        },\n\n        mkboard_matrix_set_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_matrix_set_row,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['01010101'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_matrix_set_row',\n            },\n            paramsKeyMap: {\n                MATRIX_NUM: 0,\n                MATRIX_ROW: 1,\n                STRING: 2,\n            },\n            class: 'mkboardMatrix',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var matrix_num = script.getValue('MATRIX_NUM', script);\n                var matrix_row = script.getValue('MATRIX_ROW', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n\n                for (var i = 0; i < 8; i++) {\n                    text[i] = '0';\n                }\n\n                if (typeof string === 'string') {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = Entry.mkboard.toByte(string[i]);\n                    }\n                } else if (typeof string === 'number') {\n                    var num_to_string = string.toString();\n                    for (var i = 0; i < num_to_string.length; i++) {\n                        text[i] = Entry.mkboard.toByte(num_to_string[i]);\n                    }\n                } else {\n                    text[0] = string;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.MATRIX,\n                        data: {\n                            cmd: 4, // Row\n                            matrix_num: matrix_num,\n                            matrix_row: matrix_row,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_matrix_set_row(%1, %2, %3)'] },\n        },\n\n        mkboard_matrix_set_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_matrix_set_col,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['01010101'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_matrix_set_col',\n            },\n            paramsKeyMap: {\n                MATRIX_NUM: 0,\n                MATRIX_COL: 1,\n                STRING: 2,\n            },\n            class: 'mkboardMatrix',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var matrix_num = script.getValue('MATRIX_NUM', script);\n                var matrix_col = script.getValue('MATRIX_COL', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n\n                for (var i = 0; i < 8; i++) {\n                    text[i] = '0';\n                }\n\n                if (typeof string === 'string') {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = Entry.mkboard.toByte(string[i]);\n                    }\n                } else if (typeof string === 'number') {\n                    var num_to_string = string.toString();\n                    for (var i = 0; i < num_to_string.length; i++) {\n                        text[i] = Entry.mkboard.toByte(num_to_string[i]);\n                    }\n                } else {\n                    text[0] = string;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.MATRIX,\n                        data: {\n                            cmd: 5, // Col\n                            matrix_num: matrix_num,\n                            matrix_col: matrix_col,\n                            text0: text[0],\n                            text1: text[1],\n                            text2: text[2],\n                            text3: text[3],\n                            text4: text[4],\n                            text5: text[5],\n                            text6: text[6],\n                            text7: text[7],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_matrix_set_col(%1, %2, %3)'] },\n        },\n\n        mkboard_matrix_char: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_matrix_char,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_matrix_count_list',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['A'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_matrix_char',\n            },\n            paramsKeyMap: {\n                MATRIX_NUM: 0,\n                STRING: 1,\n            },\n            class: 'mkboardMatrix',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var matrix_num = script.getValue('MATRIX_NUM', script);\n                var string = script.getValue('STRING', script);\n                var text = [];\n\n                for (var i = 0; i < 1; i++) {\n                    text[i] = '0';\n                }\n\n                if (typeof string === 'string') {\n                    for (var i = 0; i < string.length; i++) {\n                        text[i] = Entry.mkboard.toByte(string[i]);\n                    }\n                } else if (typeof string === 'number') {\n                    var num_to_string = string.toString();\n                    for (var i = 0; i < num_to_string.length; i++) {\n                        text[i] = Entry.mkboard.toByte(num_to_string[i]);\n                    }\n                } else {\n                    text[0] = string;\n                }\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.MATRIX,\n                        data: {\n                            cmd: 6, // Char\n                            matrix_num: matrix_num,\n                            text0: text[0],\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_matrix_char(%1, %2)'] },\n        },\n\n        mkboard_neopixel_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['RGB', '0'],\n                        ['RGBW', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                RGB: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('RGB');\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        mkboard_neopixel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_neopixel_init,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_neopixel_list',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_neopixel_init',\n            },\n            paramsKeyMap: {\n                RGB: 0,\n                PORT_NO: 1,\n                LED_COUNT: 2,\n            },\n            class: 'mkboardNeopixel',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var port_no = script.getNumberValue('PORT_NO', script);\n                var led_count = script.getNumberValue('LED_COUNT', script);\n                var rgb = script.getNumberValue('RGB', script);\n\n                led_count = Math.round(led_count);\n                led_count = Math.max(led_count, 1);\n                led_count = Math.min(led_count, 30);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.NEOPIXEL,\n                        data: {\n                            cmd: 0, // 포트설정\n                            port_no: port_no,\n                            led_count: led_count,\n                            rgb: rgb,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_neopixel_init(%1, %2, %3)'] },\n        },\n\n        mkboard_neopixel_set_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_neopixel_set_rgb,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_neopixel_set_rgb',\n            },\n            paramsKeyMap: {\n                LED_NO: 0,\n                R_VAL: 1,\n                G_VAL: 2,\n                B_VAL: 3,\n            },\n            class: 'mkboardNeopixel',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var led_no = script.getNumberValue('LED_NO', script);\n                var r_val = script.getNumberValue('R_VAL', script);\n                var g_val = script.getNumberValue('G_VAL', script);\n                var b_val = script.getNumberValue('B_VAL', script);\n\n                led_no = Math.round(led_no);\n                led_no = Math.max(led_no, 1);\n                led_no = Math.min(led_no, 30);\n\n                r_val = Math.round(r_val);\n                r_val = Math.max(r_val, 0);\n                r_val = Math.min(r_val, 255);\n\n                g_val = Math.round(g_val);\n                g_val = Math.max(g_val, 0);\n                g_val = Math.min(g_val, 255);\n\n                b_val = Math.round(b_val);\n                b_val = Math.max(b_val, 0);\n                b_val = Math.min(b_val, 255);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.NEOPIXEL,\n                        data: {\n                            cmd: 1, // 포트설정\n                            led_no: led_no,\n                            r_val: r_val,\n                            g_val: g_val,\n                            b_val: b_val,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_neopixel_set_rgb(%1, %2, %3, %4)'] },\n        },\n\n        mkboard_neopixel_set_rgbw: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_neopixel_set_rgbw,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_neopixel_set_rgbw',\n            },\n            paramsKeyMap: {\n                LED_NO: 0,\n                R_VAL: 1,\n                G_VAL: 2,\n                B_VAL: 3,\n                W_VAL: 4,\n            },\n            class: 'mkboardNeopixel',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var led_no = script.getNumberValue('LED_NO', script);\n                var r_val = script.getNumberValue('R_VAL', script);\n                var g_val = script.getNumberValue('G_VAL', script);\n                var b_val = script.getNumberValue('B_VAL', script);\n                var w_val = script.getNumberValue('W_VAL', script);\n\n                led_no = Math.round(led_no);\n                led_no = Math.max(led_no, 1);\n                led_no = Math.min(led_no, 30);\n\n                r_val = Math.round(r_val);\n                r_val = Math.max(r_val, 0);\n                r_val = Math.min(r_val, 255);\n\n                g_val = Math.round(g_val);\n                g_val = Math.max(g_val, 0);\n                g_val = Math.min(g_val, 255);\n\n                b_val = Math.round(b_val);\n                b_val = Math.max(b_val, 0);\n                b_val = Math.min(b_val, 255);\n\n                w_val = Math.round(w_val);\n                w_val = Math.max(w_val, 0);\n                w_val = Math.min(w_val, 255);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.NEOPIXEL,\n                        data: {\n                            cmd: 2, // 포트설정\n                            led_no: led_no,\n                            r_val: r_val,\n                            g_val: g_val,\n                            b_val: b_val,\n                            w_val: w_val,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_neopixel_set_rgbw(%1, %2, %3, %4, %5)'] },\n        },\n\n        mkboard_neopixel_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_neopixel_on,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_neopixel_on',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'mkboardNeopixel',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var value = script.getValue('VALUE', script);\n\n                //console.log(\"value=\");\n                //console.log(value);\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.mkboard.highList.indexOf(value) > -1) {\n                    value = 1;\n                } else if (Entry.mkboard.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n\n                //console.log(\"value=\");\n                //console.log(value);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_50ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.NEOPIXEL,\n                        data: {\n                            cmd: 3, // 켜기\n                            value: value,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_neopixel_on(%1)'] },\n        },\n\n        mkboard_pm5003_pm_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PM1.0', '0'],\n                        ['PM2.5', '1'],\n                        ['PM10', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PM_KIND: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PM_KIND');\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        mkboard_pms5003_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_pms5003_init,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['9'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['8'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_pms5003_init',\n            },\n            paramsKeyMap: {\n                PORT_RX: 0,\n                PORT_TX: 1,\n            },\n            class: 'mkboardPms5003',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var port_rx = script.getNumberValue('PORT_RX', script);\n                var port_tx = script.getNumberValue('PORT_TX', script);\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.PMS5003,\n                        data: {\n                            cmd: 0, // 포트설정\n                            port_rx: port_rx,\n                            port_tx: port_tx,\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_pms5003_init(%1, %2)'] },\n        },\n\n        mkboard_pms5003_measure: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_pms5003_measure,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_pms5003_measure',\n            },\n            //paramsKeyMap: {\n            //    PORT_RX: 0,\n            //    PORT_TX: 1,\n            //},\n            class: 'mkboardPms5003',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_10ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.PMS5003,\n                        data: {\n                            cmd: 1, // 먼지센서 측정\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_pms5003_measure()'] },\n        },\n\n        mkboard_pms5003_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            // template: Lang.template.mkboard_pms5003_read,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_pm5003_pm_list',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_pms5003_read',\n            },\n            paramsKeyMap: {\n                PM_KIND: 0,\n            },\n            class: 'mkboardPms5003',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var pm_kind = script.getNumberValue('PM_KIND', script);\n\n                if (pm_kind === 0) {\n                    return Entry.hw.portData.PMS5003_PM10 || 0;\n                } else if (pm_kind === 1) {\n                    return Entry.hw.portData.PMS5003_PM25 || 0;\n                } else {\n                    return Entry.hw.portData.PMS5003_PM100 || 0;\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_pms5003_read(%1)'] },\n        },\n\n        mkboard_lsm303_axis_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X', '0'],\n                        ['Y', '1'],\n                        ['Z', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('AXIS');\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        mkboard_lsm303_accel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_lsm303_accel_init,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_lsm303_accel_init',\n            },\n            //paramsKeyMap: {\n            //    PORT_RX: 0,\n            //    PORT_TX: 1,\n            //},\n            class: 'mkboardLsm303Accel',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_100ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.LSM303_ACCEL,\n                        data: {\n                            cmd: 0, // 초기화\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lsm303_accel_init()'] },\n        },\n\n        mkboard_lsm303_accel_measure: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_lsm303_accel_measure,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_lsm303_accel_measure',\n            },\n            //paramsKeyMap: {\n            //    PORT_RX: 0,\n            //    PORT_TX: 1,\n            //},\n            class: 'mkboardLsm303Accel',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_100ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.LSM303_ACCEL,\n                        data: {\n                            cmd: 1, // 먼지센서 측정\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lsm303_accel_measure()'] },\n        },\n\n        mkboard_lsm303_accel_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            // template: Lang.template.mkboard_lsm303_accel_read,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'mkboard_lsm303_axis_list',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'mkboard_lsm303_accel_read',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n            },\n            class: 'mkboardLsm303Accel',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var axis = script.getNumberValue('AXIS', script);\n\n                if (axis === 0) return Entry.hw.portData.LSM303_ACCEL_X || 0;\n                else if (axis === 1) return Entry.hw.portData.LSM303_ACCEL_Y || 0;\n                else return Entry.hw.portData.LSM303_ACCEL_Z || 0;\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lsm303_accel_read(%1)'] },\n        },\n\n        mkboard_lsm303_compass_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_lsm303_compass_init,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_lsm303_compass_init',\n            },\n            //paramsKeyMap: {\n            //    PORT_RX: 0,\n            //    PORT_TX: 1,\n            //},\n            class: 'mkboardLsm303Compass',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.LSM303_COMPASS,\n                        data: {\n                            cmd: 0, // 초기화\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lsm303_compass_init()'] },\n        },\n\n        mkboard_lsm303_compass_measure: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            // template: Lang.template.mkboard_lsm303_compass_measure,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_lsm303_compass_measure',\n            },\n            //paramsKeyMap: {\n            //    PORT_RX: 0,\n            //    PORT_TX: 1,\n            //},\n            class: 'mkboardLsm303Compass',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    if (!Entry.hw.sendQueue['SET']) {\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\n                    var duration = Entry.mkboard.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][0] = {\n                        type: Entry.mkboard.sensorTypes.LSM303_COMPASS,\n                        data: {\n                            cmd: 1, // 지자기 센서 측정\n                        },\n                        time: new Date().getTime(),\n                    };\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lsm303_compass_measure()'] },\n        },\n\n        mkboard_lsm303_compass_read: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            // template: Lang.template.mkboard_lsm303_compass_read,\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mkboard_lsm303_compass_read',\n            },\n            //paramsKeyMap: {\n            //    AXIS: 0,\n            //},\n            class: 'mkboardLsm303Compass',\n            isNotFor: ['mkboard'],\n            func: function(sprite, script) {\n                return Entry.hw.portData.LSM303_COMPASS || 0;\n            },\n            syntax: { js: [], py: ['mkboard.mkboard_lsm303_compass_read()'] },\n        },\n\n        //endregion mkboard 몽키보드\n    };\n};\n\nmodule.exports = Entry.mkboard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_modi.js",
    "content": "'use strict';\nEntry.MODI = {\n    id: '16.1',\n    name: 'modi',\n    url: 'http://www.luxrobo.com/',\n    imageName: 'modi.png',\n    title: {\n        ko: '모디',\n        en: 'MODI',\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.moduleValue = {\n            led: [],\n            motor: [],\n            speaker: [],\n            display: [],\n        };\n        Entry.hw.sendQueue['getProperty'] = {};\n        Entry.hw.getModule = {\n            id: 0,\n            property: 0,\n        };\n        Entry.hw.update();\n    },\n    initSend: function() {\n        Entry.hw.sendQueue.moduleValue = {\n            led: [],\n            motor: [],\n            speaker: [],\n            display: [],\n        };\n        Entry.hw.sendQueue['getProperty'] = {};\n        Entry.hw.getModule = {\n            id: 0,\n            property: 0,\n        };\n        Entry.hw.update();\n    },\n    getModule: {\n        id: 0,\n        property: 0,\n    },\n    microphoneList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['mic'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['mic'].length; i++) {\n            if (moduleData['mic'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    environmentList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['environment'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['environment'].length; i++) {\n            if (moduleData['environment'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    dialList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['dial'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['dial'].length; i++) {\n            if (moduleData['dial'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    gyroscopeList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['gyro'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['gyro'].length; i++) {\n            if (moduleData['gyro'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    buttonList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['button'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['button'].length; i++) {\n            if (moduleData['button'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    infraredList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['ir'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['ir'].length; i++) {\n            if (moduleData['ir'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    ultrasonicList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['ultrasonic'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['ultrasonic'].length; i++) {\n            if (moduleData['ultrasonic'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    motorList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['motor'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n        list = [];\n        for (var i = 0; i < moduleData['motor'].length; i++) {\n            if (moduleData['motor'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    ledList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['led'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['led'].length; i++) {\n            if (moduleData['led'][i]) list.push([i, i]);\n        }\n        return list;\n    },\n    speakerList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['speaker'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['speaker'].length; i++) {\n            if (moduleData['speaker'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n    displayList: function() {\n        var list;\n        var moduleData = Entry.hw.portData['module'] || {};\n\n        if (moduleData['display'] === undefined) {\n            return [[Lang.Blocks.no_target, 'null']];\n        }\n\n        list = [];\n        for (var i = 0; i < moduleData['display'].length; i++) {\n            if (moduleData['display'][i]) list.push([i.toString(), i.toString()]);\n        }\n        return list;\n    },\n};\nEntry.MODI.blockMenuBlocks = [\n    //MODI\n    'modi_microphone_value',\n    'modi_environment_value',\n    'modi_dial_value',\n    'modi_gyroscope_value',\n    'modi_button_value',\n    'modi_button_true',\n    'modi_button_false',\n    'modi_infrared_value',\n    'modi_ultrasonic_value',\n    'modi_set_motor_value',\n    'modi_change_motor_upper_value',\n    'modi_change_motor_bottom_value',\n    'modi_clear_led',\n    'modi_set_led_rgb',\n    'modi_set_led_color',\n    'modi_set_basic_speaker',\n    'modi_set_custom_speaker',\n    'modi_print_display_by_value',\n];\nEntry.MODI.setLanguage = function() {\n    return {\n        ko: {\n            template: {},\n            Blocks: {\n                modi_enviroment_bule: '파랑',\n                modi_enviroment_green: '초록',\n                modi_enviroment_humidity: '습도',\n                modi_enviroment_illuminance: '조도',\n                modi_enviroment_red: '빨강',\n                modi_enviroment_temperature: '온도',\n                modi_gyroscope_xAcceleratior: 'X축 가속',\n                modi_gyroscope_yAcceleratior: 'Y축 가속',\n                modi_gyroscope_zAcceleratior: 'Z축 가속',\n                modi_motor_angle: '각도',\n                modi_motor_speed: '속도',\n                modi_motor_torque: '회전',\n                modi_speaker_F_DO_5: '도5',\n                modi_speaker_F_DO_6: '도6',\n                modi_speaker_F_DO_7: '도7',\n                modi_speaker_F_DO_S_5: '도#5',\n                modi_speaker_F_DO_S_6: '도#6',\n                modi_speaker_F_DO_S_7: '도#7',\n                modi_speaker_F_MI_5: '미5',\n                modi_speaker_F_MI_6: '미6',\n                modi_speaker_F_MI_7: '미7',\n                modi_speaker_F_PA_5: '파5',\n                modi_speaker_F_PA_6: '파6',\n                modi_speaker_F_PA_7: '파7',\n                modi_speaker_F_PA_S_5: '파#5',\n                modi_speaker_F_PA_S_6: '파#6',\n                modi_speaker_F_PA_S_7: '파#7',\n                modi_speaker_F_RA_5: '라5',\n                modi_speaker_F_RA_6: '라6',\n                modi_speaker_F_RA_7: '라7',\n                modi_speaker_F_RA_S_5: '라#5',\n                modi_speaker_F_RA_S_6: '라#6',\n                modi_speaker_F_RA_S_7: '라#7',\n                modi_speaker_F_RE_5: '레5',\n                modi_speaker_F_RE_6: '레6',\n                modi_speaker_F_RE_7: '레7',\n                modi_speaker_F_RE_S_5: '라#5',\n                modi_speaker_F_RE_S_6: '레#6',\n                modi_speaker_F_RE_S_7: '레#7',\n                modi_speaker_F_SOL_5: '솔5',\n                modi_speaker_F_SOL_6: '솔6',\n                modi_speaker_F_SOL_7: '솔7',\n                modi_speaker_F_SOL_S_5: '솔#5',\n                modi_speaker_F_SOL_S_6: '솔#6',\n                modi_speaker_F_SOL_S_7: '솔#7',\n                modi_speaker_F_SO_5: '시5',\n                modi_speaker_F_SO_6: '시6',\n                modi_speaker_F_SO_7: '시7',\n            },\n        },\n        en: {\n            template: {},\n            Blocks: {\n                modi_enviroment_bule: 'Blue',\n                modi_enviroment_green: 'Green',\n                modi_enviroment_humidity: 'Humidity',\n                modi_enviroment_illuminance: 'Illuminance',\n                modi_enviroment_red: 'Red',\n                modi_enviroment_temperature: 'Temparature',\n                modi_gyroscope_xAcceleratior: 'X-axis acceleration',\n                modi_gyroscope_yAcceleratior: 'Y-axis acceleration',\n                modi_gyroscope_zAcceleratior: 'Z-axis acceleration',\n                modi_motor_angle: 'Angle',\n                modi_motor_speed: 'Speed',\n                modi_motor_torque: 'Torque',\n                modi_speaker_F_DO_5: 'DO 5',\n                modi_speaker_F_DO_6: 'DO 6',\n                modi_speaker_F_DO_7: 'DO 7',\n                modi_speaker_F_DO_S_5: 'DO #5',\n                modi_speaker_F_DO_S_6: 'DO #6',\n                modi_speaker_F_DO_S_7: 'DO #7',\n                modi_speaker_F_MI_5: 'MI 5',\n                modi_speaker_F_MI_6: 'MI 6',\n                modi_speaker_F_MI_7: 'MI 7',\n                modi_speaker_F_PA_5: 'FA 5',\n                modi_speaker_F_PA_6: 'FA 6',\n                modi_speaker_F_PA_7: 'FA 7',\n                modi_speaker_F_PA_S_5: 'FA #5',\n                modi_speaker_F_PA_S_6: 'FA #6',\n                modi_speaker_F_PA_S_7: 'FA #7',\n                modi_speaker_F_RA_5: 'LA 5',\n                modi_speaker_F_RA_6: 'LA 6',\n                modi_speaker_F_RA_7: 'LA 7',\n                modi_speaker_F_RA_S_5: 'LA #5',\n                modi_speaker_F_RA_S_6: 'LA #6',\n                modi_speaker_F_RA_S_7: 'LA #7',\n                modi_speaker_F_RE_5: 'RE 5',\n                modi_speaker_F_RE_6: 'RE 6',\n                modi_speaker_F_RE_7: 'RE 7',\n                modi_speaker_F_RE_S_5: 'LA #5',\n                modi_speaker_F_RE_S_6: 'RE #6',\n                modi_speaker_F_RE_S_7: 'RE #7',\n                modi_speaker_F_SOL_5: 'SOL 5',\n                modi_speaker_F_SOL_6: 'SOL 6',\n                modi_speaker_F_SOL_7: 'SOL 7',\n                modi_speaker_F_SOL_S_5: 'SOL #5',\n                modi_speaker_F_SOL_S_6: 'SOL #6',\n                modi_speaker_F_SOL_S_7: 'SOL #7',\n                modi_speaker_F_SO_5: 'TI 5',\n                modi_speaker_F_SO_6: 'TI 6',\n                modi_speaker_F_SO_7: 'TI 7',\n            },\n        },\n    };\n};\n\n//region modi 모디\nEntry.MODI.getBlocks = function() {\n    return {\n        modi_microphone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '마이크 %1번의 볼륨',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.microphoneList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'modi_microphone_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n            },\n            class: 'microphone',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                var key = script.getStringField('name');\n\n                var pd = JSON.parse(Entry.hw.portData.module['mic'][key]);\n                var moduleID = pd.id;\n\n                if (!Entry.hw.sendQueue['getProperty']) {\n                    Entry.MODI.initSend();\n                }\n\n                if (!pd.value[2]) {\n                    pd.value[2] = 0;\n\n                    // send GETPROPERTY\n                    /*if(Entry.MODI.getModule.id != moduleID || Object.keys(Entry.hw.sendQueue[\"getProperty\"]).length == 0){\n                Entry.hw.sendQueue[\"getProperty\"][moduleID] = JSON.stringify({module: 2, id: moduleID});\n                Entry.MODI.getModule.id = moduleID;\n            }*/\n                }\n\n                return pd.value[2];\n            },\n        },\n        modi_environment_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '환경센서 %1번의 %2',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.environmentList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.modi_enviroment_temperature, 6],\n                        [Lang.Blocks.modi_enviroment_humidity, 7],\n                        [Lang.Blocks.modi_enviroment_illuminance, 2],\n                        [Lang.Blocks.modi_enviroment_red, 3],\n                        [Lang.Blocks.modi_enviroment_bule, 5],\n                        [Lang.Blocks.modi_enviroment_green, 4],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null, 6],\n                type: 'modi_environment_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n                property: 1,\n            },\n            class: 'environment',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                var key = script.getStringField('name');\n                var property = script.getNumberField('property');\n\n                var pd = JSON.parse(Entry.hw.portData.module['environment'][key]);\n                var moduleID = pd.id;\n\n                if (!Entry.hw.sendQueue['getProperty']) {\n                    Entry.MODI.initSend();\n                }\n\n                if (!pd.value[property]) {\n                    pd.value[property] = 0;\n\n                    // send GETPROPERTY\n                    /*if(Entry.MODI.getModule.id != moduleID || Entry.MODI.getModule.property != property || Object.keys(Entry.hw.sendQueue[\"getProperty\"]).length == 0){\n                Entry.hw.sendQueue[\"getProperty\"][moduleID] = JSON.stringify({module: property, id: moduleID});\n                Entry.MODI.getModule.id = moduleID;\n                Entry.MODI.getModule.property = property;\n            }*/\n                }\n\n                return pd.value[property];\n            },\n        },\n        modi_dial_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '다이얼 %1번의 각도',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.dialList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'modi_dial_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n            },\n            class: 'dial',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                var key = script.getStringField('name');\n\n                var pd = JSON.parse(Entry.hw.portData.module['dial'][key]);\n                var moduleID = pd.id;\n\n                if (!Entry.hw.sendQueue['getProperty']) {\n                    Entry.MODI.initSend();\n                }\n\n                if (!pd.value[2]) {\n                    pd.value[2] = 0;\n\n                    // send GETPROPERTY\n                    /*if(Entry.MODI.getModule.id != moduleID || Object.keys(Entry.hw.sendQueue[\"getProperty\"]).length == 0){\n                Entry.hw.sendQueue[\"getProperty\"][moduleID] = JSON.stringify({module: 2, id: moduleID});\n                Entry.MODI.getModule.id = moduleID;\n            }*/\n                }\n\n                var moduleID = JSON.parse(Entry.hw.portData.module['dial'][key]).id;\n\n                return pd.value[2];\n            },\n        },\n        modi_gyroscope_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '자이로센서 %1번의 %2',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.gyroscopeList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Roll', 2],\n                        ['Pitch', 3],\n                        ['Yaw', 4],\n                        [Lang.Blocks.modi_gyroscope_xAcceleratior, 8],\n                        [Lang.Blocks.modi_gyroscope_yAcceleratior, 9],\n                        [Lang.Blocks.modi_gyroscope_zAcceleratior, 10],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null, 2],\n                type: 'modi_gyroscope_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n                property: 1,\n            },\n            class: 'gyroscope',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                var key = script.getStringField('name');\n                var property = script.getNumberField('property');\n\n                var pd = JSON.parse(Entry.hw.portData.module['gyro'][key]);\n                var moduleID = pd.id;\n\n                if (!Entry.hw.sendQueue['getProperty']) {\n                    Entry.MODI.initSend();\n                }\n                if (!pd.value[property]) {\n                    pd.value[property] = 0;\n\n                    // send GETPROPERTY\n                    /*if(Entry.MODI.getModule.id != moduleID || Entry.MODI.getModule.property != property || Object.keys(Entry.hw.sendQueue[\"getProperty\"]).length == 0){\n                Entry.hw.sendQueue[\"getProperty\"][moduleID] = JSON.stringify({module: property, id: moduleID});\n                Entry.MODI.getModule.id = moduleID;\n                Entry.MODI.getModule.property = property;\n            }*/\n                }\n\n                return pd.value[property];\n            },\n        },\n        modi_button_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '버튼 %1번의 %2',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.buttonList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Click', 2],\n                        ['Double Click', 3],\n                        ['Toggle', 5],\n                        ['Press', 4],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null, 2],\n                type: 'modi_button_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n                property: 1,\n            },\n            class: 'button',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue || !Entry.hw.sendQueue['getProperty']) {\n                    Entry.MODI.initSend();\n                }\n\n                var key = script.getStringField('name');\n                var property = script.getNumberField('property');\n                var moduleID = JSON.parse(Entry.hw.portData.module['button'][key]).id;\n                var pd = JSON.parse(Entry.hw.portData.module['button'][key]);\n\n                if (!Entry.hw.sendQueue['getProperty']) {\n                    Entry.MODI.initSend();\n                }\n\n                if (!pd.value[property]) {\n                    pd.value[property] = 0;\n\n                    // send GETPROPERTY\n                    /*if(Entry.MODI.getModule.id != moduleID || Entry.MODI.getModule.property != property || Object.keys(Entry.hw.sendQueue[\"getProperty\"]).length == 0){\n                Entry.hw.sendQueue[\"getProperty\"][moduleID] = JSON.stringify({module: property, id: moduleID});\n                Entry.MODI.getModule.id = moduleID;\n                Entry.MODI.getModule.property = property;\n            }*/\n                    return 0;\n                }\n\n                return pd.value[property];\n            },\n        },\n        modi_button_true: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '눌림',\n            def: {\n                params: [null],\n                type: 'modi_button_true',\n            },\n            class: 'button',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                return 100;\n            },\n        },\n        modi_button_false: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '안눌림',\n            def: {\n                params: [null],\n                type: 'modi_button_false',\n            },\n            class: 'button',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                return 0;\n            },\n        },\n        modi_infrared_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '적외선 %1번 센서의 거리(%)',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.infraredList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'modi_infrared_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n            },\n            class: 'infrared',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                var key = script.getStringField('name');\n\n                var pd = JSON.parse(Entry.hw.portData.module['ir'][key]);\n                var moduleID = pd.id;\n\n                if (!Entry.hw.sendQueue['getProperty']) {\n                    Entry.MODI.initSend();\n                }\n\n                if (!pd.value[2]) {\n                    pd.value[2] = 0;\n\n                    // send GETPROPERTY\n                    /*if(Entry.MODI.getModule.id != moduleID || Object.keys(Entry.hw.sendQueue[\"getProperty\"]).length == 0){\n                Entry.hw.sendQueue[\"getProperty\"][moduleID] = JSON.stringify({module: 2, id: moduleID});\n                Entry.MODI.getModule.id = moduleID;\n            }*/\n                }\n\n                return pd.value[2];\n            },\n        },\n        modi_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '초음파 %1번 센서의 거리(%)',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.ultrasonicList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'modi_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n            },\n            class: 'ultrasonic',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                var key = script.getStringField('name');\n\n                var pd = JSON.parse(Entry.hw.portData.module['ultrasonic'][key]);\n                var moduleID = pd.id;\n\n                if (!Entry.hw.sendQueue['getProperty']) {\n                    Entry.MODI.initSend();\n                }\n\n                if (!pd.value[2]) {\n                    pd.value[2] = 0;\n\n                    // send GETPROPERTY\n                    /*if(Entry.MODI.getModule.id != moduleID || Object.keys(Entry.hw.sendQueue[\"getProperty\"]).length == 0){\n                Entry.hw.sendQueue[\"getProperty\"][moduleID] = JSON.stringify({module: 2, id: moduleID});\n                Entry.MODI.getModule.id = moduleID;\n            }*/\n                }\n\n                return pd.value[2];\n            },\n        },\n        modi_set_motor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: '모터 %1번 %2의 상단값은 %3 하단값은 %4 (으)로 정하기 %5',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.motorList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.modi_motor_angle, 'MOTOR_ANGLE'],\n                        [Lang.Blocks.modi_motor_speed, 'MOTOR_SPEED'],\n                        [Lang.Blocks.modi_motor_torque, 'MOTOR_TORQUE'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    'MOTOR_ANGLE',\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'modi_set_motor_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n                property: 1,\n                upper: 2,\n                bottom: 3,\n            },\n            class: 'motor',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n                var key = script.getStringField('name'),\n                    property = script.getStringField('property'),\n                    upper = script.getNumberValue('upper'),\n                    bottom = script.getNumberValue('bottom');\n                var moduleID = JSON.parse(Entry.hw.portData.module['motor'][key]).id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                sq['motor'][key] = JSON.stringify({\n                    module: property,\n                    id: moduleID,\n                    value1: upper,\n                    value2: bottom,\n                });\n\n                return script.callReturn();\n            },\n        },\n        modi_change_motor_upper_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: '모터 %1번 %2의 상단값을 %3만큼 바꾸기 %4',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.motorList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.modi_motor_angle, 'MOTOR_ANGLE'],\n                        [Lang.Blocks.modi_motor_speed, 'MOTOR_SPEED'],\n                        [Lang.Blocks.modi_motor_torque, 'MOTOR_TORQUE'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    'MOTOR_ANGLE',\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'modi_change_motor_upper_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n                property: 1,\n                value: 2,\n            },\n            class: 'motor',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n\n                var key = script.getStringField('name'),\n                    value = script.getNumberValue('value'),\n                    property = script.getStringField('property');\n\n                var pd = JSON.parse(Entry.hw.portData.module['motor'][key]);\n                var moduleID = pd.id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                var upper = value,\n                    bottom = 0;\n\n                if (upper > 100) upper = 100;\n                else if (upper < 0 && property == 'MOTOR_ANGLE') upper = 0;\n                else if (upper < -100 && property != 'MOTOR_ANGLE') upper = -100;\n\n                sq['motor'][key] = JSON.stringify({\n                    module: property,\n                    id: moduleID,\n                    value1: upper,\n                    value2: bottom,\n                });\n\n                return script.callReturn();\n            },\n        },\n        modi_change_motor_bottom_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: '모터 %1번 %2의 하단값을 %3만큼 바꾸기 %4',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.motorList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.modi_motor_angle, 'MOTOR_ANGLE'],\n                        [Lang.Blocks.modi_motor_speed, 'MOTOR_SPEED'],\n                        [Lang.Blocks.modi_motor_torque, 'MOTOR_TORQUE'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    'MOTOR_ANGLE',\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                ],\n                type: 'modi_change_motor_bottom_value',\n            },\n            class: 'motor',\n            isNotFor: ['modi'],\n            paramsKeyMap: {\n                name: 0,\n                property: 1,\n                value: 2,\n            },\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n\n                var key = script.getStringField('name'),\n                    value = script.getNumberValue('value'),\n                    property = script.getStringField('property');\n\n                var pd = JSON.parse(Entry.hw.portData.module['motor'][key]);\n                var moduleID = pd.id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                var upper = 0,\n                    bottom = value;\n\n                if (bottom > 100) bottom = 100;\n                else if (bottom < 0 && property == 'MOTOR_ANGLE') bottom = 0;\n                else if (bottom < -100 && property != 'MOTOR_ANGLE') bottom = -100;\n\n                sq['motor'][key] = JSON.stringify({\n                    module: property,\n                    id: moduleID,\n                    value1: upper,\n                    value2: bottom,\n                });\n\n                return script.callReturn();\n            },\n        },\n        modi_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: 'LED %1번의 색 끄기 %2',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.ledList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'modi_clear_led',\n            },\n            paramsKeyMap: {\n                name: 0,\n            },\n            class: 'led',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n\n                var key = script.getStringField('name');\n                var moduleID = JSON.parse(Entry.hw.portData.module['led'][key]).id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                sq['led'][key] = JSON.stringify({\n                    module: 'LED_RGB',\n                    id: moduleID,\n                    value1: 0,\n                    value2: 0,\n                    value3: 0,\n                });\n\n                return script.callReturn();\n            },\n        },\n        modi_set_led_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: 'LED %1번 R %2 G %3 B %4  %5',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.ledList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'modi_set_led_rgb',\n            },\n            paramsKeyMap: {\n                name: 0,\n                rValue: 1,\n                gValue: 2,\n                bValue: 3,\n            },\n            class: 'led',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n                var key = script.getStringField('name');\n                var red = script.getNumberValue('rValue');\n                var green = script.getNumberValue('gValue');\n                var blue = script.getNumberValue('bValue');\n\n                var moduleID = JSON.parse(Entry.hw.portData.module['led'][key]).id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                sq['led'][key] = JSON.stringify({\n                    module: 'LED_RGB',\n                    id: moduleID,\n                    value1: red,\n                    value2: green,\n                    value3: blue,\n                });\n\n                return script.callReturn();\n            },\n        },\n        modi_set_led_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: 'LED %1번 색 %2로 정하기 %3',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.ledList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'modi_set_led_color',\n            },\n            paramsKeyMap: {\n                name: 0,\n                color: 1,\n            },\n            class: 'led',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n                var key = script.getStringField('name');\n                var color = script.getStringField('color');\n\n                color = color.substring(1, 7);\n                var bigint = parseInt(color, 16);\n                var red = Math.round((((bigint >> 16) & 255) / 255) * 100);\n                var green = Math.round((((bigint >> 8) & 255) / 255) * 100);\n                var blue = Math.round(((bigint & 255) / 255) * 100);\n                var moduleID = JSON.parse(Entry.hw.portData.module['led'][key]).id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                sq['led'][key] = JSON.stringify({\n                    module: 'LED_RGB',\n                    id: moduleID,\n                    value1: red,\n                    value2: green,\n                    value3: blue,\n                });\n\n                return script.callReturn();\n            },\n        },\n        modi_set_basic_speaker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: '스피커 %1번을 %2음으로 크기는 %3(으)로 정하기 %4',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.speakerList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.modi_speaker_F_PA_5, 'F_PA_5'],\n                        [Lang.Blocks.modi_speaker_F_SOL_5, 'F_SOL_5'],\n                        [Lang.Blocks.modi_speaker_F_RA_5, 'F_RA_5'],\n                        [Lang.Blocks.modi_speaker_F_SO_5, 'F_SO_5'],\n                        [Lang.Blocks.modi_speaker_F_PA_S_5, 'F_PA_S_5'],\n                        [Lang.Blocks.modi_speaker_F_SOL_S_5, 'F_SOL_S_5'],\n                        [Lang.Blocks.modi_speaker_F_RA_S_5, 'F_RA_S_5'],\n                        [Lang.Blocks.modi_speaker_F_DO_6, 'F_DO_6'],\n                        [Lang.Blocks.modi_speaker_F_RE_6, 'F_RE_6'],\n                        [Lang.Blocks.modi_speaker_F_MI_6, 'F_MI_6'],\n                        [Lang.Blocks.modi_speaker_F_PA_6, 'F_PA_6'],\n                        [Lang.Blocks.modi_speaker_F_SOL_6, 'F_SOL_6'],\n                        [Lang.Blocks.modi_speaker_F_RA_6, 'F_RA_6'],\n                        [Lang.Blocks.modi_speaker_F_SO_6, 'F_SO_6'],\n                        [Lang.Blocks.modi_speaker_F_DO_S_6, 'F_DO_S_6'],\n                        [Lang.Blocks.modi_speaker_F_RE_S_6, 'F_RE_S_6'],\n                        [Lang.Blocks.modi_speaker_F_PA_S_6, 'F_PA_S_6'],\n                        [Lang.Blocks.modi_speaker_F_SOL_S_6, 'F_SOL_S_6'],\n                        [Lang.Blocks.modi_speaker_F_RA_S_6, 'F_RA_S_6'],\n                        [Lang.Blocks.modi_speaker_F_DO_7, 'F_DO_7'],\n                        [Lang.Blocks.modi_speaker_F_RE_7, 'F_RE_7'],\n                        [Lang.Blocks.modi_speaker_F_MI_7, 'F_MI_7'],\n                        [Lang.Blocks.modi_speaker_F_DO_S_7, 'F_DO_S_7'],\n                        [Lang.Blocks.modi_speaker_F_RE_S_7, 'F_RE_S_7'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    'F_DO_6',\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'modi_set_basic_speaker',\n            },\n            paramsKeyMap: {\n                name: 0,\n                frequence: 1,\n                volume: 2,\n            },\n            class: 'speaker',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n                var key = script.getStringField('name'),\n                    frequence = script.getStringField('frequence'),\n                    volume = script.getNumberValue('volume', script);\n                var moduleID = JSON.parse(Entry.hw.portData.module['speaker'][key]).id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                sq['speaker'][key] = JSON.stringify({\n                    module: 'SPEAKER_BUZZER',\n                    id: moduleID,\n                    value1: frequence,\n                    value2: volume,\n                });\n\n                return script.callReturn();\n            },\n        },\n        modi_set_custom_speaker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: '스피커 %1번의 진동수는 %2 크기는 %3(으)로 정하기 %4',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.speakerList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'modi_set_custom_speaker',\n            },\n            paramsKeyMap: {\n                name: 0,\n                frequence: 1,\n                volume: 2,\n            },\n            class: 'speaker',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n                var key = script.getStringField('name'),\n                    frequence = script.getNumberValue('frequence'),\n                    volume = script.getNumberValue('volume', script);\n                var moduleID = JSON.parse(Entry.hw.portData.module['speaker'][key]).id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                sq['speaker'][key] = JSON.stringify({\n                    module: 'SPEAKER_BUZZER',\n                    id: moduleID,\n                    value1: frequence,\n                    value2: volume,\n                });\n\n                return script.callReturn();\n            },\n        },\n        modi_print_display_by_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: '디스플레이 %1번의 화면에 %2 보이기 %3',\n            params: [\n                {\n                    type: 'DropdownDynamic',\n                    value: null,\n                    fontSize: 11,\n                    menuName: Entry.MODI.displayList,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['text'],\n                    },\n                ],\n                type: 'modi_print_display_by_value',\n            },\n            paramsKeyMap: {\n                name: 0,\n                text: 1,\n            },\n            class: 'display',\n            isNotFor: ['modi'],\n            func: function(sprite, script) {\n                if (!Entry.hw.sendQueue.moduleValue) {\n                    Entry.MODI.initSend();\n                }\n\n                var key = script.getStringField('name'),\n                    text = script.getStringValue('text');\n\n                if (text.length > 27) {\n                    return script.callReturn();\n                }\n\n                var moduleID = JSON.parse(Entry.hw.portData.module['display'][key]).id;\n\n                var sq = Entry.hw.sendQueue.moduleValue;\n                sq['display'][key] = JSON.stringify({\n                    module: 'DISPLAY_TEXT',\n                    id: moduleID,\n                    value1: text,\n                });\n                return script.callReturn();\n            },\n        },\n    };\n};\n//endregion modi 모디\n\nmodule.exports = Entry.MODI;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_mrt.js",
    "content": "'use strict';\n\nEntry.MRT = {\n    id: '23.1',\n    name: 'MRT-X',\n    url: 'http://www.myrobottime.com/',\n    imageName: 'mrt.png',\n    title: {\n        ko: 'MRT-X',\n        en: 'MRT-X',\n    },\n    PORT_MAP: {\n        RIGHT_WHEEL1: 0,\n        LEFT_WHEEL1: 0,\n        RIGHT_WHEEL2: 0,\n        LEFT_WHEEL2: 0,\n        OUT1: 90,\n        OUT2: 90,\n        OUT3: 90,\n        analogD5: 127, //D4\n        analogD6: 127, //D5\n        OUT4: 0,\n        OUT5: 0,\n        LED: 0,\n        BUZZER: 0,\n        lcdNum: 0,\n        lcdTxt: '                ',\n        note: 262,\n        duration: 0,\n    },\n    setZero: function() {\n        var portMap = Entry.MRT.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        var MRT = Entry.MRT;\n        MRT.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n};\n\nEntry.MRT.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                mrt_digitalInput: '%1',\n                mrt_analogValue: '%1',\n                mrt_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n                mrt_servo: '서보 모터 %1 , 각도 %2 %3',\n                mrt_oneWheel: '바퀴(DC) 모터 %1 , 속도 %2 %3',\n                mrt_buzzer: '%1   %2 음을 %3 초 연주하기 %4',\n                mrt_lcd: 'LCD %1 번째 줄 ,  출력 값 %2 %3',\n                mrt_ultra: '초음파 센서',\n                mrt_gyro: '자이로 센서 %1',\n                mrt_color: '컬러 센서',\n                mrt_remotecontrol: '리모콘',\n                mrt_keyvalue: '키 값',\n            },\n        },\n        en: {\n            template: {\n                mrt_digitalInput: '%1',\n                mrt_analogValue: '%1',\n                mrt_digitalOutput: 'digital write pin %1 , value %2 %3',\n                mrt_servo: 'servo write pin %1 , degrees %2 %3',\n                mrt_oneWheel: 'set DC-motor %1 , speed %2 %3',\n                mrt_buzzer: 'play Tone on note %1   %2  %3 duration %4',\n                mrt_lcd: 'LCD %1 번째 줄 ,  출력 값 %2 %3',\n                mrt_ultra: 'ultrasonic sensor',\n                mrt_gyro: 'gyro sensor %1',\n                mrt_color: 'color sensor',\n                mrt_remotecontrol: 'remocon',\n                mrt_keyvalue: 'key value',\n            },\n        },\n    };\n};\n\nEntry.MRT.blockMenuBlocks = [\n    //region MRT-X Blocks added\n    'mrt_digitalInput',\n    'mrt_digitalOutput',\n    'mrt_analogValue',\n    'mrt_ultra',\n    'mrt_color',\n    'mrt_gyro',\n    'mrt_remotecontrol',\n    'mrt_keyvalue',\n    'mrt_buzzer',\n    'mrt_servo',\n    'mrt_oneWheel',\n    'mrt_lcd',\n    //endregion end of MRT-X Blocks added\n];\n\nEntry.MRT.getBlocks = function() {\n    return {\n        //region xbot 엑스봇\n        mrt_analogValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'adc0'],\n                        ['IN2', 'adc1'],\n                        ['IN3', 'adc2'],\n                        ['IN4', 'adc3'],\n                        ['IN5', 'adc4'],\n                    ],\n                    value: 'adc0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mrt_analogValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'mrt_sensor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['MRT.analog_value(%1)'] },\n        },\n        mrt_ultra: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            fontColor: '#ffffff',\n            params: [\n                {\n                    type: 'default_value',\n                    options: [['ultra', 'ultra']],\n                    value: 'ultra',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mrt_ultra',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'mrt_sensor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['MRT.analog_value(%1)'] },\n        },\n\n        mrt_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            fontColor: '#ffffff',\n            params: [\n                {\n                    type: 'default_value',\n                    options: [['color', 'color']],\n                    value: 'color',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mrt_color',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'mrt_sensor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['MRT.analog_value(%1)'] },\n        },\n\n        mrt_remotecontrol: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            fontColor: '#ffffff',\n            params: [\n                {\n                    type: 'default_value',\n                    options: [['remocon', 'remocon']],\n                    value: 'remocon',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mrt_remotecontrol',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'mrt_sensor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['MRT.analog_value(%1)'] },\n        },\n\n        mrt_keyvalue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            fontColor: '#ffffff',\n            params: [\n                {\n                    type: 'default_value',\n                    options: [['key', 'key']],\n                    value: 'key',\n                    fontSize: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mrt_keyvalue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'mrt_sensor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['MRT.analog_value(%1)'] },\n        },\n\n        mrt_gyro: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            fontColor: '#ffffff',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['X', 'gyroX'], ['Y', 'gyroY'], ['Z', 'gyroZ']],\n                    value: 'gyroX',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'mrt_gyro',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'mrt_sensor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['MRT.analog_value(%1)'] },\n        },\n\n        mrt_digitalOutput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT4', 'OUT4'],\n                        ['OUT5', 'OUT5'],\n                        ['LED', 'LED'],\n                        ['BUZZER ', 'BUZZER'],\n                    ],\n                    value: 'LED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.XBOT_High, 'HIGH'], [Lang.Blocks.XBOT_Low, 'LOW']],\n                    value: 'HIGH',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'mrt_digitalOutput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'mrt_sensor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getStringField('VALUE', script);\n\n                if (dev == 'BUZZER' && value == 'HIGH') {\n                    sq.BUZZER = 1;\n                } else {\n                    sq.BUZZER = 0;\n                }\n\n                if (dev == 'OUT4' && value == 'HIGH') {\n                    sq.OUT4 = 1;\n                } else {\n                    sq.OUT4 = 0;\n                }\n\n                if (dev == 'OUT5' && value == 'HIGH') {\n                    sq.OUT5 = 1;\n                } else {\n                    sq.OUT5 = 0;\n                }\n\n                if (dev == 'LED' && value == 'HIGH') {\n                    sq.LED = 1;\n                } else {\n                    sq.LED = 0;\n                }\n                //sq.D13 = 1;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['MRT.digital_output(%1, %2)'] },\n        },\n\n        mrt_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['OUT1', 'OUT1'], ['OUT2', 'OUT2'], ['OUT3', 'OUT3']],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'mrt_servo',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'mrt_motor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var mtype = script.getStringField('DEVICE', script);\n                var angle = script.getNumberValue('VALUE', script);\n\n                if (mtype == 'OUT1') {\n                    sq.OUT1 = angle;\n                } else if (mtype == 'OUT2') {\n                    sq.OUT2 = angle;\n                } else if (mtype == 'OUT3') {\n                    sq.OUT3 = angle;\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['MRT.servo(%1, %2)'] },\n        },\n        mrt_oneWheel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['RIGHT_WHEEL1', 'RIGHT_WHEEL1'],\n                        ['LEFT_WHEEL1', 'LEFT_WHEEL1'],\n                        ['RIGHT_WHEEL2', 'RIGHT_WHEEL2'],\n                        ['LEFT_WHEEL2', 'LEFT_WHEEL2'],\n                    ],\n                    value: 'RIGHT_WHEEL1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'mrt_oneWheel',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'mrt_motor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                //console.log('xbot_move_forward_for_secs');\n                var sq = Entry.hw.sendQueue;\n                var dir = script.getStringField('DEVICE', script);\n                var speed = script.getNumberValue('VALUE', script);\n\n                if (dir == 'RIGHT_WHEEL1') sq.RIGHT_WHEEL1 = speed;\n                if (dir == 'LEFT_WHEEL1') sq.LEFT_WHEEL1 = speed;\n                if (dir == 'RIGHT_WHEEL2') sq.RIGHT_WHEEL2 = speed;\n                if (dir == 'LEFT_WHEEL2') sq.LEFT_WHEEL2 = speed;\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['MRT.one_wheel(%1, %2)'] },\n        },\n\n        mrt_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['0', '0'], ['1', '1']],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['Hello'],\n                    },\n                    null,\n                ],\n                type: 'mrt_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                VALUE: 1,\n            },\n            class: 'mrt_sensor',\n            isNotFor: ['MRT-X'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var line = script.getNumberField('LINE', script);\n                var str = script.getStringValue('VALUE', script);\n\n                if (line == 0) {\n                    sq.lcdNum = 0;\n                    sq.lcdTxt = str;\n                } else if (line == 1) {\n                    sq.lcdNum = 1;\n                    sq.lcdTxt = str;\n                }\n                //console.log('ledR' + sq.ledR + ' ledG ' + sq.ledG +' ledB ' + sq.ledB);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['MRT.lcd(%1, %2)'] },\n        },\n        //endregion xbot 엑스봇\n    };\n};\n\nmodule.exports = Entry.MRT;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_nemoino.js",
    "content": "'use strict';\n\nEntry.nemoino = {\n    id: '1.6',\n    name: 'nemoino',\n    imageName: 'nemoino.png',\n    title: {\n        ko: '네모이노',\n        en: 'NEMOino',\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n    },\n};\n\nEntry.nemoino.blockMenuBlocks = [\n    //nemoino\n    'nemoino_get_named_sensor_value',\n    'nemoino_get_sound_status',\n    'nemoino_is_button_pressed',\n    'nemoino_get_accelerometer_direction',\n    'nemoino_get_accelerometer_value',\n    'nemoino_get_number_sensor_value',\n    'nemoino_get_digital_value',\n    'nemoino_toggle_led',\n    'nemoino_toggle_pwm',\n    'nemoino_convert_scale',\n];\n\nEntry.nemoino.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                nemoino_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                nemoino_get_digital_value: '디지털 %1 번 센서값  ',\n                nemoino_toggle_led: '디지털 %1 번 핀 %2 %3',\n                nemoino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                nemoino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n            },\n        },\n        en: {\n            template: {\n                nemoino_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                nemoino_get_digital_value: 'Digital %1 Sensor value  ',\n                nemoino_toggle_led: 'Digital %1 Pin %2 %3',\n                nemoino_toggle_pwm: 'Digital %1 Pin %2 %3',\n                nemoino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n            },\n        },\n    };\n};\n\nEntry.nemoino.getBlocks = function() {\n    return {\n        //region nemoino 네모이노\n        nemoino_get_named_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1 센서값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['소리', '0'],\n                        ['빛', '1'],\n                        ['슬라이더', '2'],\n                        ['저항-A', '3'],\n                        ['저항-B', '4'],\n                        ['저항-C', '5'],\n                        ['저항-D', '6'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'nemoino_get_named_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'nemoino',\n            isNotFor: ['nemoino'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue(script.getField('PORT', script));\n            },\n        },\n        nemoino_get_sound_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '소리센서 %1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['소리큼', 'GREAT'],\n                        ['소리작음', 'SMALL'],\n                    ],\n                    value: 'GREAT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'nemoino_get_sound_status',\n            },\n            paramsKeyMap: {\n                STATUS: 0,\n            },\n            class: 'nemoino',\n            isNotFor: ['nemoino'],\n            func: function(sprite, script) {\n                var value1 = script.getField('STATUS', script);\n                var value2 = 0;\n                if (value1 == 'GREAT') return Entry.hw.getAnalogPortValue(value2) > 600 ? 1 : 0;\n                else return Entry.hw.getAnalogPortValue(value2) < 600 ? 1 : 0;\n            },\n        },\n        nemoino_is_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '보드의 %1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['버튼누름', '4'],\n                        ['A연결됨', '17'],\n                        ['B연결됨', '18'],\n                        ['C연결됨', '19'],\n                        ['D연결됨', '20'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'nemoino_is_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'nemoino',\n            isNotFor: ['nemoino'],\n            func: function(sprite, script) {\n                var value = script.getNumberField('PORT', script);\n                if (value > 14) {\n                    value = value - 14;\n                    return !Entry.hw.getAnalogPortValue(value);\n                } else return !Entry.hw.getDigitalPortValue(value);\n            },\n        },\n        nemoino_get_accelerometer_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '3축 가속도센서 %1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽 기울임', 'LEFT'],\n                        ['오른쪽 기울임', 'RIGHT'],\n                        ['위쪽 기울임', 'FRONT'],\n                        ['아래쪽 기울임', 'REAR'],\n                        ['뒤집힘', 'REVERSE'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'nemoino_get_accelerometer_direction',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'nemoino',\n            isNotFor: ['nemoino'],\n            func: function(sprite, script) {\n                var value1 = script.getField('DIRECTION', script);\n                var value2 = 0;\n                if (value1 == 'LEFT' || value1 == 'RIGHT') value2 = 3;\n                else if (value1 == 'FRONT' || value1 == 'REAR') value2 = 4;\n                else if (value1 == 'REVERSE') value2 = 5;\n                var value3 = Entry.hw.getAnalogPortValue(value2);\n                var value4 = 265;\n                var value5 = 402;\n                var value6 = -90;\n                var value7 = 90;\n                var result = value3;\n                result -= value4;\n                result = result * ((value7 - value6) / (value5 - value4));\n                result += value6;\n                result = Math.min(value7, result);\n                result = Math.max(value6, result);\n                result = Math.round(result);\n                if (value1 == 'LEFT' || value1 == 'REAR') return result < -30 ? 1 : 0;\n                else if (value1 == 'RIGHT' || value1 == 'FRONT') return result > 30 ? 1 : 0;\n                else if (value1 == 'REVERSE') return result < -50 ? 1 : 0;\n            },\n        },\n        nemoino_get_accelerometer_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '3축 가속도센서 %1 축의 센서값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X', '3'],\n                        ['Y', '4'],\n                        ['Z', '5'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'nemoino_get_accelerometer_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'nemoino',\n            isNotFor: ['nemoino'],\n            func: function(sprite, script) {\n                var value1 = Entry.hw.getAnalogPortValue(script.getField('PORT', script));\n                var value2 = 265;\n                var value3 = 402;\n                var value4 = -90;\n                var value5 = 90;\n                var result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n                return Math.round(result);\n            },\n        },\n        //endregion nemoino 네모이노\n        //region nemoino 네모이노\n        nemoino_get_number_sensor_value: {\n            parent: 'arduino_get_number_sensor_value',\n            isNotFor: ['nemoino'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'nemoino_get_number_sensor_value',\n            },\n            class: 'arduino_value',\n            syntax: { js: [], py: ['Nemoino.sensor_value(%1)'] },\n        },\n        nemoino_get_digital_value: {\n            parent: 'arduino_get_digital_value',\n            isNotFor: ['nemoino'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'nemoino_get_digital_value',\n            },\n            class: 'arduino_value',\n            syntax: { js: [], py: ['Nemoino.digital_value(%1)'] },\n        },\n        nemoino_toggle_led: {\n            parent: 'arduino_toggle_led',\n            isNotFor: ['nemoino'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'nemoino_toggle_led',\n            },\n            class: 'arduino_set',\n            syntax: { js: [], py: ['Nemoino.toggle_led(%1)'] },\n        },\n        nemoino_toggle_pwm: {\n            parent: 'arduino_toggle_pwm',\n            isNotFor: ['nemoino'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'arduino_text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'nemoino_toggle_pwm',\n            },\n            class: 'arduino_set',\n            syntax: { js: [], py: ['Nemoino.toggle_pwm(%1, %2)'] },\n        },\n        nemoino_convert_scale: {\n            parent: 'arduino_convert_scale',\n            isNotFor: ['nemoino'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_number_sensor_value',\n                        params: [\n                            {\n                                type: 'arduino_get_sensor_number',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'nemoino_convert_scale',\n            },\n            class: 'arduino',\n            syntax: {\n                js: [],\n                py: ['Nemoino.convert_scale(%1, %2, %3, %4, %5)'],\n            },\n        },\n        //endregion nemoino 네모이노\n    };\n};\n\nmodule.exports = Entry.nemoino;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neo.js",
    "content": "'use strict';\n\n/*\n 엔트리에 정의된 블럭 명령어\n 엔트리에서 받을 때는 BlockTypes 로 통신하고,\n 하드웨어로 전송할 때는 Command 로 변환 후 Pdu 로 Wrapping 하여 전송한다.\n */\nconst NeoBlockType = {\n    // MOTOR 명령어 0x1X\n    MOTOR_MOVE: 0x11,\n    MOTOR_MOVE_BOTH: 0x12,\n    MOTOR_STOP: 0x13,\n    ROBOT_MOVE: 0x14,\n    ROBOT_STOP: 0x15,\n    // SERVO 명령어 0x2X\n    SERVO_RESET: 0x21,\n    SERVO_ANGLE: 0x22,\n    SERVO_ANGLE_WAIT: 0x23,\n    SERVO_ROTATE: 0x24,\n    SERVO_STOP: 0x25,\n    // LINE_TRACER 명령어 0x3X\n    LINE_TRACER_START: 0x31,\n    LINE_CROSS_MOVE: 0x32,\n    LINE_CROSS_TURN: 0x33,\n    LINE_CHANGE_START: 0x34,\n    LINE_CHANGE_TURN: 0x35,\n    // AUTO_DRIVING 명령어 0x4X\n    AUTO_DRIVING_START: 0x41,\n    AUTO_DRIVING_SENSOR_START: 0x42,\n    AUTO_DRIVING_STOP: 0x43,\n    AUTO_PARKING_START: 0x44,\n    AUTO_DETECT_WALL_START: 0x45,\n    AUTO_DETECT_WALL_TURN: 0x46,\n    // LED 명령어 0x5X\n    LED_ON: 0x51,\n    LED_BLINK: 0x52,\n    LED_OFF: 0x53,\n    COLOR_LED_ON: 0x54,\n    COLOR_LED_OFF: 0x55,\n    COLOR_LED_ON_SENSOR: 0x56,\n    // SET_OUTPUT 명령어 0x6X\n    SET_OUTPUT: 0x61,\n    // BUZZER 명령어 0x7X\n    BUZZER_START: 0x71,\n    BUZZER_WITH_SENSOR: 0x72,\n    BUZZER_STOP: 0x73,\n    // LCD 명령어 0x8X\n    LCD_IMAGE: 0x81,\n    LCD_TEXT: 0x82,\n};\n\n/*\n PDU 정의\n */\nconst HEADER = [0xaa, 0xaa, 0xcc];\n\nconst FrameCode = {\n    BASIC: 0x01,\n};\n\nconst PduCode = {\n    SENSOR_DATA: 0x01,\n    CONTROLLER_COMMAND: 0x02,\n    ACTION_COMMAND: 0x03,\n    BASIC: 0x10,\n    EXTEND_1: 0x11,\n    EXTEND_2: 0x12,\n    EXTEND_3: 0x13,\n};\n\nconst ActorKind = {\n    CONTROLLER: 0x00,\n    LED: 0x80,\n    SERVO: 0x81,\n    COLOR_LED: 0x82,\n    LCD: 0x83,\n};\n\nconst ControllerCommand = {\n    CONTROLLER_LED: 0x01,\n    BUZZER: 0x02,\n    MOTOR: 0x03,\n    MOTOR_BOTH: 0x04,\n    ROBOT: 0x05,\n    LINE_TRACER: 0x06,\n    AUTO_DRIVING: 0x07,\n    AUTO_PARKING: 0x08,\n    AUTO_DETECT_WALL: 0x09,\n};\n\nconst ServoCommand = {\n    STOP: 0x01,\n    RESET: 0x02,\n    ANGLE: 0x03,\n    ANGLE_WAIT: 0x04,\n    ROTATE: 0x05,\n};\n\nconst LedCommand = {\n    OFF: 0x00,\n    ON: 0x01,\n};\n\nconst LcdCommand = {\n    IMAGE: 0x01,\n    TEXT: 0x02,\n};\n\nconst UnitId = {\n    CONTROLLER: 0x00,\n    CONTROLLER_IN1: 0x01,\n    CONTROLLER_IN2: 0x02,\n    CONTROLLER_IN3: 0x03,\n    SENSOR_STICK: 0x10,\n    SENSOR_STICK_IN1: 0x11,\n    IOT: 0x80,\n    CONTROLLER_OUT1: 0x81,\n    CONTROLLER_OUT2: 0x82,\n    CONTROLLER_OUT12: 0x83,\n    CONTROLLER_OUT3: 0x84,\n    CONTROLLER_OUT13: 0x85,\n    CONTROLLER_OUT23: 0x86,\n    CONTROLLER_OUT123: 0x87,\n    CONTROLLER_OUT_ALL: 0x8f,\n};\n\n/*\n 블럭 실행 단계\n execute: 최초 실행\n pending_response: 최초 실행의 response 대기중인 상태\n set_timeout: 블럭에서 duration 필드에 의거하여 타임아웃을 설정\n wait_timeout: timeout 대기중인 상태\n stop: 파라미터를 0으로 바꿔서 실행\n pending_stop: 파라미터를 0으로 바꾼 실행의 response 대기중인 상태\n end: 실행 종료 단계\n */\nconst ExecPhase = {\n    EXECUTE: 'execute',\n    PENDING_RESPONSE: 'pending_response',\n    SET_TIMEOUT: 'set_timeout',\n    WAIT_TIMEOUT: 'wait_timeout',\n    STOP: 'stop',\n    PENDING_STOP: 'pending_stop',\n    END: 'end',\n};\n\n/*\n dropdown params\n 양이 많아서 분리함.\n */\nEntry.Neo = new (class Neo {\n    constructor() {\n        this.id = '5.8';\n        this.url = 'http://www.neobot.co.kr';\n        this.name = 'neo';\n        this.imageName = 'neo.png';\n        this.title = {\n            ko: '네오(NEO)',\n            en: 'NEO',\n        };\n        this.blockMenuBlocks = [\n            // robot\n            'neo_robot_title',\n            'neo_robot_move',\n            'neo_robot_stop',\n\n            // auto driving\n            'neo_auto_driving_title',\n            'neo_auto_driving_start',\n            'neo_auto_driving_sensor_start',\n            'neo_auto_driving_stop',\n            // auto parking\n            // 'neo_auto_parking_title',\n            // 'neo_auto_parking_start',\n\n            // line tracer\n            // 'neo_line_tracer_title',\n            'neo_line_tracer_start',\n            'neo_line_cross_move',\n            'neo_line_cross_turn',\n            'neo_line_cross_reached',\n\n            // motor\n            'neo_motor_title',\n            'neo_motor_move',\n            'neo_motor_move_both',\n            'neo_motor_stop',\n\n            // servo\n            'neo_servo_title',\n            'neo_servo_reset',\n            'neo_servo_angle',\n            'neo_servo_angle_var',\n            'neo_servo_angle_wait',\n            'neo_servo_rotate',\n            'neo_servo_stop',\n\n            // led\n            'neo_led_title',\n            'neo_led_on',\n            'neo_led_blink',\n            'neo_led_off',\n\n            // set output\n            'neo_set_output_title',\n            'neo_set_output',\n\n            // color led\n            'neo_color_led_title',\n            'neo_color_led_on',\n            'neo_color_led_off',\n            'neo_color_led_on_with_sensor',\n\n            // sensor\n            'neo_sensor_title',\n            'neo_sensor_in',\n            'neo_sensor_digital_in',\n            'neo_sensor_convert',\n            'neo_sensor_compare',\n            'neo_sensor_between',\n            'neo_sensor_digital_compare',\n            'neo_sensor_color_compare',\n            'neo_sensor_color_sequence_compare',\n            'neo_sensor_button_pressed',\n            // buzzer\n            'neo_buzzer_title',\n            'neo_buzzer_start',\n            'neo_buzzer_with_sensor',\n            'neo_buzzer_stop',\n            // lcd\n            'neo_lcd_title',\n            'neo_lcd_image',\n            'neo_lcd_text',\n        ];\n        this.seqBlockId = 0;\n        this.executeList = {};\n        this.pendingResponseList = {};\n        this.monitorTemplate = {\n            imgPath: 'hw/neo.png',\n            width: 500,\n            height: 500,\n            listPorts: {\n                IN11: { name: 'IN1 1', type: 'input', pos: { x: 0, y: 0 } },\n                IN12: { name: 'IN1 2', type: 'input', pos: { x: 0, y: 0 } },\n                IN13: { name: 'IN1 3', type: 'input', pos: { x: 0, y: 0 } },\n                IN14: { name: 'IN1 4', type: 'input', pos: { x: 0, y: 0 } },\n                IN21: { name: 'IN2 1', type: 'input', pos: { x: 0, y: 0 } },\n                IN22: { name: 'IN2 2', type: 'input', pos: { x: 0, y: 0 } },\n                IN23: { name: 'IN2 3', type: 'input', pos: { x: 0, y: 0 } },\n                IN24: { name: 'IN2 4', type: 'input', pos: { x: 0, y: 0 } },\n                IN31: { name: 'IN3 1', type: 'input', pos: { x: 0, y: 0 } },\n                IN32: { name: 'IN3 2', type: 'input', pos: { x: 0, y: 0 } },\n                IN33: { name: 'IN3 3', type: 'input', pos: { x: 0, y: 0 } },\n                IN34: { name: 'IN3 4', type: 'input', pos: { x: 0, y: 0 } },\n                IR: { name: 'IR', type: 'input', pos: { x: 0, y: 0 } },\n                BAT: { name: 'BAT', type: 'input', pos: { x: 0, y: 0 } },\n            },\n            mode: 'both',\n        };\n    }\n\n    setZero() {\n        const blockId = this.generateBlockId();\n        const pdu = this.makePdu([FrameCode.BASIC, PduCode.CONTROLLER_COMMAND, blockId, 0x04]);\n        Entry.hw.sendQueue.executeList = {\n            blockId: {\n                blockId,\n                pdu,\n            },\n        };\n        Entry.hw.update();\n\n        this.pendingResponseList = {};\n        this.executeList = {};\n    }\n\n    afterReceive(portData) {\n        for (let i = 0; i <= 255; i++) {\n            if (this.pendingResponseList[i]) {\n                if (portData.pendingList[i] && portData.pendingList[i].state === 'completed') {\n                    delete this.pendingResponseList[i];\n                    delete this.executeList[i];\n                }\n            }\n        }\n    }\n\n    generateBlockId() {\n        this.seqBlockId += 1;\n        if (this.seqBlockId > 255) {\n            this.seqBlockId = 1;\n        }\n        return this.seqBlockId;\n    }\n\n    setLanguage() {\n        return {\n            ko: {\n                template: {\n                    // robot\n                    neo_robot_title: '로봇',\n                    neo_robot_move: '로봇 제어하기 %1 %2 %3 %4',\n                    neo_robot_stop: '로봇 멈추기 %1',\n\n                    // auto driving\n                    neo_auto_driving_title: '자율주행',\n                    neo_auto_driving_start: '자율주행 시작하기 %1 %2 %3',\n                    neo_auto_driving_sensor_start: '%1 를 감지하여 자율주행 %2 %3',\n                    neo_auto_driving_stop: '자율주행 멈추기 %1',\n\n                    // auto parking\n                    neo_auto_parking_title: '자율주차 | 아이블(AiBle) 전용',\n                    neo_auto_parking_start: '주차하기 %1 %2 %3',\n\n                    // line tracer\n                    neo_line_tracer_title: '라인트레이서 | 아이온(AION) 전용',\n                    neo_line_tracer_start: '검은색 길 따라가기 %1 %2 %3',\n                    neo_line_cross_move: '%1 교차로까지 직진하기 %2',\n                    neo_line_cross_turn: '방향바꾸기 %1 %2',\n                    neo_line_cross_reached: '교차로에 도착하였는가?',\n\n                    // motor\n                    neo_motor_title: '회전모터',\n                    neo_motor_move: '회전모터 제어하기 %1 %2 %3 %4',\n                    neo_motor_move_both: '회전모터 동시에 제어하기 L %1 R %2 %3',\n                    neo_motor_stop: '회전모터 멈추기 %1 %2',\n\n                    // servo\n                    neo_servo_title: '서보모터',\n                    neo_servo_reset: '%1 서보모터 현위치를 0도로 설정하기 %2',\n                    neo_servo_angle: '서보모터 각도 바꾸기 %1 %2 %3 %4',\n                    neo_servo_angle_var: '서보모터 각도 바꾸기 %1 %2 %3 %4',\n                    neo_servo_angle_wait: '각도 바뀔때까지 기다리기 %1 %2 %3 %4',\n                    neo_servo_rotate: '서보모터 회전하기 %1 %2 %3 %4',\n                    neo_servo_stop: '서보모터 멈추기 %1 %2',\n\n                    // led\n                    neo_led_title: 'LED',\n                    neo_led_on: 'LED 켜기 %1 %2 %3 %4',\n                    neo_led_blink: 'LED 깜빡이기 %1 %2 %3 %4',\n                    neo_led_off: 'LED 끄기 %1 %2',\n\n                    // set output\n                    neo_set_output_title: '출력',\n                    neo_set_output: '값 출력하기 %1 %2 %3 %4',\n\n                    // color led\n                    neo_color_led_title: '컬러 LED',\n                    neo_color_led_on: '컬러LED 켜기 %1 %2 %3 %4',\n                    neo_color_led_off: '컬러LED 끄기 %1 %2',\n                    neo_color_led_on_with_sensor: '컬러센서 %1 로 컬러LED %2 제어 %3',\n\n                    // sensor\n                    neo_sensor_title: '센서',\n                    neo_sensor_in: '%1',\n                    neo_sensor_in_2: '%1',\n                    neo_sensor_digital_in: '%1 의 %2',\n                    neo_sensor_convert: '%1 : %2 %3 → %4 %5',\n                    neo_sensor_compare: '%1 %2 %3',\n                    neo_sensor_between: '%1 %2 %3 %4 %5',\n                    neo_sensor_digital_compare: '%1 의 %2 %3 %4',\n                    neo_sensor_color_compare: '%1 = %2',\n                    neo_sensor_color_sequence_compare: '%1 = %2 %3 %4',\n                    neo_sensor_button_pressed: '%1 %2',\n\n                    // buzzer\n                    neo_buzzer_title: '버저',\n                    neo_buzzer_start: '버저 울리기 %1 %2 %3 %4',\n                    neo_buzzer_with_sensor: '센서로 버저 울리기 %1 %2',\n                    neo_buzzer_stop: '버저 멈추기 %1',\n\n                    // lcd\n                    neo_lcd_title: 'LCD',\n                    neo_lcd_image: 'LCD에 이미지 보여주기 %1 %2 %3',\n                    neo_lcd_text: 'LCD에 텍스트 보여주기 %1 %2 %3',\n\n                    // args\n                    neo_arg_duration: '%1',\n                    neo_arg_both_motor_speed: '%1',\n                    neo_arg_servo_angle: '%1',\n                },\n                Blocks: {\n                    neo_input_1: 'IN1',\n                    neo_input_2: 'IN2',\n                    neo_input_3: 'IN3',\n                    neo_input_12: 'IN1&2',\n                    neo_input_123: 'IN1&2&3',\n                    neo_input_1_2: 'IN1&IN2',\n                    neo_input_11_12: 'IN1-1&IN1-2',\n                    neo_input_13_14: 'IN1-3&IN1-4',\n                    neo_input_21_22: 'IN2-1&IN2-2',\n                    neo_input_23_24: 'IN2-3&IN2-4',\n                    neo_input_31_32: 'IN3-1&IN3-2',\n                    neo_input_33_34: 'IN3-3&IN3-4',\n\n                    neo_output_1: 'OUT1',\n                    neo_output_2: 'OUT2',\n                    neo_output_3: 'OUT3',\n                    neo_output_12: 'OUT1&2',\n                    neo_output_123: 'OUT1&2&3',\n\n                    neo_speed_0: '0%',\n                    neo_speed_5: '5%',\n                    neo_speed_10: '10%',\n                    neo_speed_15: '15%',\n                    neo_speed_20: '20%',\n                    neo_speed_25: '25%',\n                    neo_speed_30: '30%',\n                    neo_speed_35: '35%',\n                    neo_speed_40: '40%',\n                    neo_speed_45: '45%',\n                    neo_speed_50: '50%',\n                    neo_speed_55: '55%',\n                    neo_speed_60: '60%',\n                    neo_speed_65: '65%',\n                    neo_speed_70: '70%',\n                    neo_speed_75: '75%',\n                    neo_speed_80: '80%',\n                    neo_speed_85: '85%',\n                    neo_speed_90: '90%',\n                    neo_speed_95: '95%',\n                    neo_speed_100: '100%',\n\n                    neo_duration_c: '계속',\n                    neo_duration_0: '0초',\n                    neo_duration_1: '1초',\n                    neo_duration_2: '2초',\n                    neo_duration_3: '3초',\n                    neo_duration_4: '4초',\n                    neo_duration_5: '5초',\n                    neo_duration_6: '6초',\n                    neo_duration_7: '7초',\n                    neo_duration_8: '8초',\n                    neo_duration_9: '9초',\n\n                    neo_compare_gt: '≥',\n                    neo_compare_g: '>',\n                    neo_compare_e: '=',\n                    neo_compare_l: '<',\n                    neo_compare_lt: '≤',\n\n                    neo_turn_direction_l: '좌회전',\n                    neo_turn_direction_r: '우회전',\n                    neo_turn_direction_u: 'U턴',\n\n                    neo_motor_out_l: 'L모터',\n                    neo_motor_out_r: 'R모터',\n                    neo_motor_out_lr: 'L/R모터',\n\n                    neo_motor_speed_n100: '-100%',\n                    neo_motor_speed_n95: '-95%',\n                    neo_motor_speed_n90: '-90%',\n                    neo_motor_speed_n85: '-85%',\n                    neo_motor_speed_n80: '-80%',\n                    neo_motor_speed_n75: '-75%',\n                    neo_motor_speed_n70: '-70%',\n                    neo_motor_speed_n65: '-65%',\n                    neo_motor_speed_n60: '-60%',\n                    neo_motor_speed_n55: '-55%',\n                    neo_motor_speed_n50: '-50%',\n                    neo_motor_speed_n45: '-45%',\n                    neo_motor_speed_n40: '-40%',\n                    neo_motor_speed_n35: '-35%',\n                    neo_motor_speed_n30: '-30%',\n                    neo_motor_speed_n25: '-25%',\n                    neo_motor_speed_n20: '-20%',\n                    neo_motor_speed_n15: '-15%',\n                    neo_motor_speed_n10: '-10%',\n                    neo_motor_speed_n5: '-5%',\n                    neo_motor_speed_0: '0%',\n                    neo_motor_speed_5: '5%',\n                    neo_motor_speed_10: '10%',\n                    neo_motor_speed_15: '15%',\n                    neo_motor_speed_20: '20%',\n                    neo_motor_speed_25: '25%',\n                    neo_motor_speed_30: '30%',\n                    neo_motor_speed_35: '35%',\n                    neo_motor_speed_40: '40%',\n                    neo_motor_speed_45: '45%',\n                    neo_motor_speed_50: '50%',\n                    neo_motor_speed_55: '55%',\n                    neo_motor_speed_60: '60%',\n                    neo_motor_speed_65: '65%',\n                    neo_motor_speed_70: '70%',\n                    neo_motor_speed_75: '75%',\n                    neo_motor_speed_80: '80%',\n                    neo_motor_speed_85: '85%',\n                    neo_motor_speed_90: '90%',\n                    neo_motor_speed_95: '95%',\n                    neo_motor_speed_100: '100%',\n\n                    neo_robot_direction_f: '앞으로',\n                    neo_robot_direction_b: '뒤로',\n                    neo_robot_direction_l: '왼쪽으로',\n                    neo_robot_direction_r: '오른쪽으로',\n                    neo_robot_direction_tl: '제자리왼쪽',\n                    neo_robot_direction_tr: '제자리오른쪽',\n\n                    neo_servo_angle_n360: '-360도',\n                    neo_servo_angle_n350: '-350도',\n                    neo_servo_angle_n340: '-340도',\n                    neo_servo_angle_n330: '-330도',\n                    neo_servo_angle_n320: '-320도',\n                    neo_servo_angle_n310: '-310도',\n                    neo_servo_angle_n300: '-300도',\n                    neo_servo_angle_n290: '-290도',\n                    neo_servo_angle_n280: '-280도',\n                    neo_servo_angle_n270: '-270도',\n                    neo_servo_angle_n260: '-260도',\n                    neo_servo_angle_n250: '-250도',\n                    neo_servo_angle_n240: '-240도',\n                    neo_servo_angle_n230: '-230도',\n                    neo_servo_angle_n220: '-220도',\n                    neo_servo_angle_n210: '-210도',\n                    neo_servo_angle_n200: '-200도',\n                    neo_servo_angle_n190: '-190도',\n                    neo_servo_angle_n180: '-180도',\n                    neo_servo_angle_n170: '-170도',\n                    neo_servo_angle_n160: '-160도',\n                    neo_servo_angle_n150: '-150도',\n                    neo_servo_angle_n140: '-140도',\n                    neo_servo_angle_n130: '-130도',\n                    neo_servo_angle_n120: '-120도',\n                    neo_servo_angle_n110: '-110도',\n                    neo_servo_angle_n100: '-100도',\n                    neo_servo_angle_n90: '-90도',\n                    neo_servo_angle_n80: '-80도',\n                    neo_servo_angle_n70: '-70도',\n                    neo_servo_angle_n60: '-60도',\n                    neo_servo_angle_n50: '-50도',\n                    neo_servo_angle_n40: '-40도',\n                    neo_servo_angle_n30: '-30도',\n                    neo_servo_angle_n20: '-20도',\n                    neo_servo_angle_n10: '-10도',\n                    neo_servo_angle_0: '0도',\n                    neo_servo_angle_10: '10도',\n                    neo_servo_angle_20: '20도',\n                    neo_servo_angle_30: '30도',\n                    neo_servo_angle_40: '40도',\n                    neo_servo_angle_50: '50도',\n                    neo_servo_angle_60: '60도',\n                    neo_servo_angle_70: '70도',\n                    neo_servo_angle_80: '80도',\n                    neo_servo_angle_90: '90도',\n                    neo_servo_angle_100: '100도',\n                    neo_servo_angle_110: '110도',\n                    neo_servo_angle_120: '120도',\n                    neo_servo_angle_130: '130도',\n                    neo_servo_angle_140: '140도',\n                    neo_servo_angle_150: '150도',\n                    neo_servo_angle_160: '160도',\n                    neo_servo_angle_170: '170도',\n                    neo_servo_angle_180: '180도',\n                    neo_servo_angle_190: '190도',\n                    neo_servo_angle_200: '200도',\n                    neo_servo_angle_210: '210도',\n                    neo_servo_angle_220: '220도',\n                    neo_servo_angle_230: '230도',\n                    neo_servo_angle_240: '240도',\n                    neo_servo_angle_250: '250도',\n                    neo_servo_angle_260: '260도',\n                    neo_servo_angle_270: '270도',\n                    neo_servo_angle_280: '280도',\n                    neo_servo_angle_290: '290도',\n                    neo_servo_angle_300: '300도',\n                    neo_servo_angle_310: '310도',\n                    neo_servo_angle_320: '320도',\n                    neo_servo_angle_330: '330도',\n                    neo_servo_angle_340: '340도',\n                    neo_servo_angle_350: '350도',\n                    neo_servo_angle_360: '360도',\n\n                    neo_servo_direction_f: '앞으로',\n                    neo_servo_direction_b: '뒤로',\n\n                    neo_line_cross_move_1: '첫번째',\n                    neo_line_cross_move_2: '두번째',\n                    neo_line_cross_move_3: '세번째',\n                    neo_line_cross_move_4: '네번째',\n                    neo_line_cross_move_5: '다섯번째',\n                    neo_line_cross_move_6: '여섯번째',\n                    neo_line_cross_move_7: '일곱번째',\n                    neo_line_cross_move_8: '여덟번째',\n                    neo_line_cross_move_9: '아홉번째',\n                    neo_line_cross_move_10: '열번째',\n\n                    neo_line_cross_turn_direction_l: '좌회전',\n                    neo_line_cross_turn_direction_r: '우회전',\n                    neo_line_cross_turn_direction_u: 'U턴',\n\n                    neo_line_cross_turn_which_next: '다음',\n                    neo_line_cross_turn_which_current: '현재',\n\n                    neo_auto_driving_speed_in3: 'IN3',\n\n                    neo_auto_parking_which_l: '왼쪽에',\n                    neo_auto_parking_which_r: '오른쪽에',\n\n                    neo_auto_parking_direction_b: '후면주차',\n                    neo_auto_parking_direction_s: '평행주차',\n\n                    neo_led_brightness_0: '0%',\n                    neo_led_brightness_5: '5%',\n                    neo_led_brightness_10: '10%',\n                    neo_led_brightness_15: '15%',\n                    neo_led_brightness_20: '20%',\n                    neo_led_brightness_25: '25%',\n                    neo_led_brightness_30: '30%',\n                    neo_led_brightness_35: '35%',\n                    neo_led_brightness_40: '40%',\n                    neo_led_brightness_45: '45%',\n                    neo_led_brightness_50: '50%',\n                    neo_led_brightness_55: '55%',\n                    neo_led_brightness_60: '60%',\n                    neo_led_brightness_65: '65%',\n                    neo_led_brightness_70: '70%',\n                    neo_led_brightness_75: '75%',\n                    neo_led_brightness_80: '80%',\n                    neo_led_brightness_85: '85%',\n                    neo_led_brightness_90: '90%',\n                    neo_led_brightness_95: '95%',\n                    neo_led_brightness_100: '100%',\n\n                    neo_led_blink_speed_1: '1단계',\n                    neo_led_blink_speed_2: '2단계',\n                    neo_led_blink_speed_3: '3단계',\n                    neo_led_blink_speed_4: '4단계',\n                    neo_led_blink_speed_5: '5단계',\n\n                    neo_set_output_value_0: '0',\n                    neo_set_output_value_5: '5',\n                    neo_set_output_value_10: '10',\n                    neo_set_output_value_15: '15',\n                    neo_set_output_value_20: '20',\n                    neo_set_output_value_25: '25',\n                    neo_set_output_value_30: '30',\n                    neo_set_output_value_35: '35',\n                    neo_set_output_value_40: '40',\n                    neo_set_output_value_45: '45',\n                    neo_set_output_value_50: '50',\n                    neo_set_output_value_55: '55',\n                    neo_set_output_value_60: '60',\n                    neo_set_output_value_65: '65',\n                    neo_set_output_value_70: '70',\n                    neo_set_output_value_75: '75',\n                    neo_set_output_value_80: '80',\n                    neo_set_output_value_85: '85',\n                    neo_set_output_value_90: '90',\n                    neo_set_output_value_95: '95',\n                    neo_set_output_value_100: '100',\n                    neo_set_output_value_105: '105',\n                    neo_set_output_value_110: '110',\n                    neo_set_output_value_115: '115',\n                    neo_set_output_value_120: '120',\n                    neo_set_output_value_125: '125',\n                    neo_set_output_value_130: '130',\n                    neo_set_output_value_135: '135',\n                    neo_set_output_value_140: '140',\n                    neo_set_output_value_145: '145',\n                    neo_set_output_value_150: '150',\n                    neo_set_output_value_155: '155',\n                    neo_set_output_value_160: '160',\n                    neo_set_output_value_165: '165',\n                    neo_set_output_value_170: '170',\n                    neo_set_output_value_175: '175',\n                    neo_set_output_value_180: '180',\n                    neo_set_output_value_185: '185',\n                    neo_set_output_value_190: '190',\n                    neo_set_output_value_195: '195',\n                    neo_set_output_value_200: '200',\n                    neo_set_output_value_205: '205',\n                    neo_set_output_value_210: '210',\n                    neo_set_output_value_215: '215',\n                    neo_set_output_value_220: '220',\n                    neo_set_output_value_225: '225',\n                    neo_set_output_value_230: '230',\n                    neo_set_output_value_235: '235',\n                    neo_set_output_value_240: '240',\n                    neo_set_output_value_245: '245',\n                    neo_set_output_value_250: '250',\n                    neo_set_output_value_255: '255',\n\n                    neo_sensor_in_digital_1: '1번',\n                    neo_sensor_in_digital_2: '2번',\n                    neo_sensor_in_digital_3: '3번',\n                    neo_sensor_in_digital_4: '4번',\n\n                    neo_color_black: '검정',\n                    neo_color_white: '흰색',\n                    neo_color_red: '빨강',\n                    neo_color_yellow: '노랑',\n                    neo_color_green: '초록',\n                    neo_color_blue: '파랑',\n\n                    neo_button_1: '버튼1',\n                    neo_button_2: '버튼2',\n                    neo_button_3: '버튼3',\n                    neo_button_4: '버튼4',\n\n                    neo_button_on: 'ON',\n                    neo_button_off: 'OFF',\n\n                    neo_buzzer_octave_1: '1옥타브',\n                    neo_buzzer_octave_2: '2옥타브',\n                    neo_buzzer_octave_3: '3옥타브',\n                    neo_buzzer_octave_4: '4옥타브',\n                    neo_buzzer_octave_5: '5옥타브',\n                    neo_buzzer_octave_6: '6옥타브',\n\n                    neo_buzzer_do: '도',\n                    neo_buzzer_do_sharp: '도#',\n                    neo_buzzer_re: '레',\n                    neo_buzzer_re_sharp: '레#',\n                    neo_buzzer_mi: '미',\n                    neo_buzzer_fa: '파',\n                    neo_buzzer_fa_sharp: '파#',\n                    neo_buzzer_sol: '솔',\n                    neo_buzzer_sol_sharp: '솔#',\n                    neo_buzzer_la: '라',\n                    neo_buzzer_la_sharp: '라#',\n                    neo_buzzer_ti: '시',\n\n                    neo_buzzer_whole_note: '온음표',\n                    neo_buzzer_half_note: '2분 음표',\n                    neo_buzzer_quarter_note: '4분 음표',\n                    neo_buzzer_8th_note: '8분 음표',\n\n                    neo_lcd_image_1: '화남',\n                    neo_lcd_image_2: '어지러움',\n                    neo_lcd_image_3: '똑똑함',\n                    neo_lcd_image_4: '활기참',\n                    neo_lcd_image_5: '뽀뽀',\n                    neo_lcd_image_6: '사랑해',\n                    neo_lcd_image_7: '윙크',\n                    neo_lcd_image_8: '폭풍눈물',\n                    neo_lcd_image_9: '졸림',\n                    neo_lcd_image_10: '미소',\n                    neo_lcd_image_11: '깜찍함',\n                    neo_lcd_image_12: '의심',\n                    neo_lcd_image_13: '못마땅',\n                },\n            },\n            en: {\n                // en.js에 작성하던 내용\n                template: {\n                    // robot\n                    neo_robot_title: 'Robot',\n                    neo_robot_move: 'Move robot %1 %2 %3 %4',\n                    neo_robot_stop: 'Stop robot %1',\n\n                    // auto driving\n                    neo_auto_driving_title: 'Self-driving',\n                    neo_auto_driving_start: 'Start self-driving %1 %2 %3',\n                    neo_auto_driving_sensor_start: 'Start self-driving with %1 %2 %3',\n                    neo_auto_driving_stop: 'Stop self-driving %1',\n\n                    // auto parking\n                    neo_auto_parking_title: 'Auto parking | AiBle-only',\n                    neo_auto_parking_start: 'Start auto parking %1 %2 %3',\n\n                    // line tracer\n                    neo_line_tracer_title: 'Line tracer | AION-only',\n                    neo_line_tracer_start: 'Start line tracer with black line %1 %2 %3',\n                    neo_line_cross_move: 'Keep moving to the %1 intersection %2',\n                    neo_line_cross_turn: 'Turn %1 %2',\n                    neo_line_cross_reached: 'Reached an intersection?',\n\n                    // motor\n                    neo_motor_title: 'Motor',\n                    neo_motor_move: 'Move motor %1 %2 %3 %4',\n                    neo_motor_move_both: 'Move both motor L %1 R %2 %3',\n                    neo_motor_stop: 'Stop motor %1 %2',\n\n                    // servo\n                    neo_servo_title: 'Servo motor',\n                    neo_servo_reset: 'Reset the current position of %1 servo motor to 0 degree %2',\n                    neo_servo_angle: 'Change servo angle %1 %2 %3 %4',\n                    neo_servo_angle_var: 'Change servo angle %1 %2 %3 %4',\n                    neo_servo_angle_wait: 'Wait to change servo angle %1 %2 %3 %4',\n                    neo_servo_rotate: 'Rotate servo motor %1 %2 %3 %4',\n                    neo_servo_stop: 'Stop servo motor %1 %2',\n\n                    // led\n                    neo_led_title: 'LED',\n                    neo_led_on: 'Turn on the LED %1 %2 %3 %4',\n                    neo_led_blink: 'Blink the LED %1 %2 %3 %4',\n                    neo_led_off: 'Turn off the LED %1 %2',\n\n                    // set output\n                    neo_set_output_title: 'Set output',\n                    neo_set_output: 'Set output %1 %2 %3 %4',\n\n                    // color led\n                    neo_color_led_title: 'Color LED',\n                    neo_color_led_on: 'Turn on the color LED %1 %2 %3 %4',\n                    neo_color_led_off: 'Turn off the color LED %1 %2',\n                    neo_color_led_on_with_sensor:\n                      'Turn on the color LED %2 with color sensor %1 %3',\n\n                    // sensor\n                    neo_sensor_title: 'Sensor',\n                    neo_sensor_in: '%1',\n                    neo_sensor_in_2: '%1',\n                    neo_sensor_digital_in: '%1 %2',\n                    neo_sensor_convert: '%1 : %2 %3 → %4 %5',\n                    neo_sensor_compare: '%1 %2 %3',\n                    neo_sensor_between: '%1 %2 %3 %4 %5',\n                    neo_sensor_digital_compare: '%1 %2 %3 %4',\n                    neo_sensor_color_compare: '%1 = %2',\n                    neo_sensor_color_sequence_compare: '%1 = %2 %3 %4',\n                    neo_sensor_button_pressed: '%1 %2',\n\n                    // buzzer\n                    neo_buzzer_title: 'Buzzer',\n                    neo_buzzer_start: 'Buzzer %1 %2 %3 %4',\n                    neo_buzzer_with_sensor: 'Buzzer by sensor value %1 %2',\n                    neo_buzzer_stop: 'Stop the buzzer %1',\n\n                    // lcd\n                    neo_lcd_title: 'LCD',\n                    neo_lcd_image: 'Show image on LCD %1 %2 %3',\n                    neo_lcd_text: 'Show text on LCD %1 %2 %3',\n\n                    // args\n                    neo_arg_duration: '%1',\n                    neo_arg_both_motor_speed: '%1',\n                    neo_arg_servo_angle: '%1',\n                },\n                Blocks: {\n                    neo_input_1: 'IN1',\n                    neo_input_2: 'IN2',\n                    neo_input_3: 'IN3',\n                    neo_input_12: 'IN1&2',\n                    neo_input_123: 'IN1&2&3',\n                    neo_input_1_2: 'IN1&IN2',\n                    neo_input_11_12: 'IN1-1&IN1-2',\n                    neo_input_13_14: 'IN1-3&IN1-4',\n                    neo_input_21_22: 'IN2-1&IN2-2',\n                    neo_input_23_24: 'IN2-3&IN2-4',\n                    neo_input_31_32: 'IN3-1&IN3-2',\n                    neo_input_33_34: 'IN3-3&IN3-4',\n\n                    neo_output_1: 'OUT1',\n                    neo_output_2: 'OUT2',\n                    neo_output_3: 'OUT3',\n                    neo_output_12: 'OUT1&2',\n                    neo_output_123: 'OUT1&2&3',\n\n                    neo_speed_0: '0%',\n                    neo_speed_5: '5%',\n                    neo_speed_10: '10%',\n                    neo_speed_15: '15%',\n                    neo_speed_20: '20%',\n                    neo_speed_25: '25%',\n                    neo_speed_30: '30%',\n                    neo_speed_35: '35%',\n                    neo_speed_40: '40%',\n                    neo_speed_45: '45%',\n                    neo_speed_50: '50%',\n                    neo_speed_55: '55%',\n                    neo_speed_60: '60%',\n                    neo_speed_65: '65%',\n                    neo_speed_70: '70%',\n                    neo_speed_75: '75%',\n                    neo_speed_80: '80%',\n                    neo_speed_85: '85%',\n                    neo_speed_90: '90%',\n                    neo_speed_95: '95%',\n                    neo_speed_100: '100%',\n\n                    neo_duration_c: 'constantly',\n                    neo_duration_0: '0 second',\n                    neo_duration_1: '1 second',\n                    neo_duration_2: '2 seconds',\n                    neo_duration_3: '3 seconds',\n                    neo_duration_4: '4 seconds',\n                    neo_duration_5: '5 seconds',\n                    neo_duration_6: '6 seconds',\n                    neo_duration_7: '7 seconds',\n                    neo_duration_8: '8 seconds',\n                    neo_duration_9: '9 seconds',\n\n                    neo_compare_gt: '≥',\n                    neo_compare_g: '>',\n                    neo_compare_e: '=',\n                    neo_compare_l: '<',\n                    neo_compare_lt: '≤',\n\n                    neo_turn_direction_l: 'left',\n                    neo_turn_direction_r: 'right',\n                    neo_turn_direction_u: 'U-turn',\n\n                    neo_motor_out_l: 'left',\n                    neo_motor_out_r: 'right',\n                    neo_motor_out_lr: 'both',\n\n                    neo_motor_speed_n100: '-100%',\n                    neo_motor_speed_n95: '-95%',\n                    neo_motor_speed_n90: '-90%',\n                    neo_motor_speed_n85: '-85%',\n                    neo_motor_speed_n80: '-80%',\n                    neo_motor_speed_n75: '-75%',\n                    neo_motor_speed_n70: '-70%',\n                    neo_motor_speed_n65: '-65%',\n                    neo_motor_speed_n60: '-60%',\n                    neo_motor_speed_n55: '-55%',\n                    neo_motor_speed_n50: '-50%',\n                    neo_motor_speed_n45: '-45%',\n                    neo_motor_speed_n40: '-40%',\n                    neo_motor_speed_n35: '-35%',\n                    neo_motor_speed_n30: '-30%',\n                    neo_motor_speed_n25: '-25%',\n                    neo_motor_speed_n20: '-20%',\n                    neo_motor_speed_n15: '-15%',\n                    neo_motor_speed_n10: '-10%',\n                    neo_motor_speed_n5: '-5%',\n                    neo_motor_speed_0: '0%',\n                    neo_motor_speed_5: '5%',\n                    neo_motor_speed_10: '10%',\n                    neo_motor_speed_15: '15%',\n                    neo_motor_speed_20: '20%',\n                    neo_motor_speed_25: '25%',\n                    neo_motor_speed_30: '30%',\n                    neo_motor_speed_35: '35%',\n                    neo_motor_speed_40: '40%',\n                    neo_motor_speed_45: '45%',\n                    neo_motor_speed_50: '50%',\n                    neo_motor_speed_55: '55%',\n                    neo_motor_speed_60: '60%',\n                    neo_motor_speed_65: '65%',\n                    neo_motor_speed_70: '70%',\n                    neo_motor_speed_75: '75%',\n                    neo_motor_speed_80: '80%',\n                    neo_motor_speed_85: '85%',\n                    neo_motor_speed_90: '90%',\n                    neo_motor_speed_95: '95%',\n                    neo_motor_speed_100: '100%',\n\n                    neo_robot_direction_f: 'forward',\n                    neo_robot_direction_b: 'backward',\n                    neo_robot_direction_l: 'left',\n                    neo_robot_direction_r: 'right',\n                    neo_robot_direction_tl: 'left in place',\n                    neo_robot_direction_tr: 'right in place',\n\n                    neo_servo_angle_n360: '-360 degree',\n                    neo_servo_angle_n350: '-350 degree',\n                    neo_servo_angle_n340: '-340 degree',\n                    neo_servo_angle_n330: '-330 degree',\n                    neo_servo_angle_n320: '-320 degree',\n                    neo_servo_angle_n310: '-310 degree',\n                    neo_servo_angle_n300: '-300 degree',\n                    neo_servo_angle_n290: '-290 degree',\n                    neo_servo_angle_n280: '-280 degree',\n                    neo_servo_angle_n270: '-270 degree',\n                    neo_servo_angle_n260: '-260 degree',\n                    neo_servo_angle_n250: '-250 degree',\n                    neo_servo_angle_n240: '-240 degree',\n                    neo_servo_angle_n230: '-230 degree',\n                    neo_servo_angle_n220: '-220 degree',\n                    neo_servo_angle_n210: '-210 degree',\n                    neo_servo_angle_n200: '-200 degree',\n                    neo_servo_angle_n190: '-190 degree',\n                    neo_servo_angle_n180: '-180 degree',\n                    neo_servo_angle_n170: '-170 degree',\n                    neo_servo_angle_n160: '-160 degree',\n                    neo_servo_angle_n150: '-150 degree',\n                    neo_servo_angle_n140: '-140 degree',\n                    neo_servo_angle_n130: '-130 degree',\n                    neo_servo_angle_n120: '-120 degree',\n                    neo_servo_angle_n110: '-110 degree',\n                    neo_servo_angle_n100: '-100 degree',\n                    neo_servo_angle_n90: '-90 degree',\n                    neo_servo_angle_n80: '-80 degree',\n                    neo_servo_angle_n70: '-70 degree',\n                    neo_servo_angle_n60: '-60 degree',\n                    neo_servo_angle_n50: '-50 degree',\n                    neo_servo_angle_n40: '-40 degree',\n                    neo_servo_angle_n30: '-30 degree',\n                    neo_servo_angle_n20: '-20 degree',\n                    neo_servo_angle_n10: '-10 degree',\n                    neo_servo_angle_0: '0 degree',\n                    neo_servo_angle_10: '10 degree',\n                    neo_servo_angle_20: '20 degree',\n                    neo_servo_angle_30: '30 degree',\n                    neo_servo_angle_40: '40 degree',\n                    neo_servo_angle_50: '50 degree',\n                    neo_servo_angle_60: '60 degree',\n                    neo_servo_angle_70: '70 degree',\n                    neo_servo_angle_80: '80 degree',\n                    neo_servo_angle_90: '90 degree',\n                    neo_servo_angle_100: '100 degree',\n                    neo_servo_angle_110: '110 degree',\n                    neo_servo_angle_120: '120 degree',\n                    neo_servo_angle_130: '130 degree',\n                    neo_servo_angle_140: '140 degree',\n                    neo_servo_angle_150: '150 degree',\n                    neo_servo_angle_160: '160 degree',\n                    neo_servo_angle_170: '170 degree',\n                    neo_servo_angle_180: '180 degree',\n                    neo_servo_angle_190: '190 degree',\n                    neo_servo_angle_200: '200 degree',\n                    neo_servo_angle_210: '210 degree',\n                    neo_servo_angle_220: '220 degree',\n                    neo_servo_angle_230: '230 degree',\n                    neo_servo_angle_240: '240 degree',\n                    neo_servo_angle_250: '250 degree',\n                    neo_servo_angle_260: '260 degree',\n                    neo_servo_angle_270: '270 degree',\n                    neo_servo_angle_280: '280 degree',\n                    neo_servo_angle_290: '290 degree',\n                    neo_servo_angle_300: '300 degree',\n                    neo_servo_angle_310: '310 degree',\n                    neo_servo_angle_320: '320 degree',\n                    neo_servo_angle_330: '330 degree',\n                    neo_servo_angle_340: '340 degree',\n                    neo_servo_angle_350: '350 degree',\n                    neo_servo_angle_360: '360 degree',\n\n                    neo_servo_direction_f: 'forward',\n                    neo_servo_direction_b: 'backward',\n\n                    neo_line_cross_move_1: '1st',\n                    neo_line_cross_move_2: '2nd',\n                    neo_line_cross_move_3: '3rd',\n                    neo_line_cross_move_4: '4th',\n                    neo_line_cross_move_5: '5th',\n                    neo_line_cross_move_6: '6th',\n                    neo_line_cross_move_7: '7th',\n                    neo_line_cross_move_8: '8th',\n                    neo_line_cross_move_9: '9th',\n                    neo_line_cross_move_10: '10th',\n\n                    neo_line_cross_turn_direction_l: 'to left',\n                    neo_line_cross_turn_direction_r: 'to right',\n                    neo_line_cross_turn_direction_u: 'U-turn',\n\n                    neo_line_cross_turn_which_next: 'next',\n                    neo_line_cross_turn_which_current: 'current',\n\n                    neo_auto_driving_speed_in3: 'IN3',\n\n                    neo_auto_parking_which_l: 'to left',\n                    neo_auto_parking_which_r: 'to right',\n\n                    neo_auto_parking_direction_b: 'rear parking',\n                    neo_auto_parking_direction_s: 'parallel parking',\n\n                    neo_led_brightness_0: '0%',\n                    neo_led_brightness_5: '5%',\n                    neo_led_brightness_10: '10%',\n                    neo_led_brightness_15: '15%',\n                    neo_led_brightness_20: '20%',\n                    neo_led_brightness_25: '25%',\n                    neo_led_brightness_30: '30%',\n                    neo_led_brightness_35: '35%',\n                    neo_led_brightness_40: '40%',\n                    neo_led_brightness_45: '45%',\n                    neo_led_brightness_50: '50%',\n                    neo_led_brightness_55: '55%',\n                    neo_led_brightness_60: '60%',\n                    neo_led_brightness_65: '65%',\n                    neo_led_brightness_70: '70%',\n                    neo_led_brightness_75: '75%',\n                    neo_led_brightness_80: '80%',\n                    neo_led_brightness_85: '85%',\n                    neo_led_brightness_90: '90%',\n                    neo_led_brightness_95: '95%',\n                    neo_led_brightness_100: '100%',\n\n                    neo_led_blink_speed_1: 'stage 1',\n                    neo_led_blink_speed_2: 'stage 2',\n                    neo_led_blink_speed_3: 'stage 3',\n                    neo_led_blink_speed_4: 'stage 4',\n                    neo_led_blink_speed_5: 'stage 5',\n\n                    neo_set_output_value_0: '0',\n                    neo_set_output_value_5: '5',\n                    neo_set_output_value_10: '10',\n                    neo_set_output_value_15: '15',\n                    neo_set_output_value_20: '20',\n                    neo_set_output_value_25: '25',\n                    neo_set_output_value_30: '30',\n                    neo_set_output_value_35: '35',\n                    neo_set_output_value_40: '40',\n                    neo_set_output_value_45: '45',\n                    neo_set_output_value_50: '50',\n                    neo_set_output_value_55: '55',\n                    neo_set_output_value_60: '60',\n                    neo_set_output_value_65: '65',\n                    neo_set_output_value_70: '70',\n                    neo_set_output_value_75: '75',\n                    neo_set_output_value_80: '80',\n                    neo_set_output_value_85: '85',\n                    neo_set_output_value_90: '90',\n                    neo_set_output_value_95: '95',\n                    neo_set_output_value_100: '100',\n                    neo_set_output_value_105: '105',\n                    neo_set_output_value_110: '110',\n                    neo_set_output_value_115: '115',\n                    neo_set_output_value_120: '120',\n                    neo_set_output_value_125: '125',\n                    neo_set_output_value_130: '130',\n                    neo_set_output_value_135: '135',\n                    neo_set_output_value_140: '140',\n                    neo_set_output_value_145: '145',\n                    neo_set_output_value_150: '150',\n                    neo_set_output_value_155: '155',\n                    neo_set_output_value_160: '160',\n                    neo_set_output_value_165: '165',\n                    neo_set_output_value_170: '170',\n                    neo_set_output_value_175: '175',\n                    neo_set_output_value_180: '180',\n                    neo_set_output_value_185: '185',\n                    neo_set_output_value_190: '190',\n                    neo_set_output_value_195: '195',\n                    neo_set_output_value_200: '200',\n                    neo_set_output_value_205: '205',\n                    neo_set_output_value_210: '210',\n                    neo_set_output_value_215: '215',\n                    neo_set_output_value_220: '220',\n                    neo_set_output_value_225: '225',\n                    neo_set_output_value_230: '230',\n                    neo_set_output_value_235: '235',\n                    neo_set_output_value_240: '240',\n                    neo_set_output_value_245: '245',\n                    neo_set_output_value_250: '250',\n                    neo_set_output_value_255: '255',\n\n                    neo_sensor_in_digital_1: '1st',\n                    neo_sensor_in_digital_2: '2nd',\n                    neo_sensor_in_digital_3: '3rd',\n                    neo_sensor_in_digital_4: '4th',\n\n                    neo_color_black: 'black',\n                    neo_color_white: 'white',\n                    neo_color_red: 'red',\n                    neo_color_yellow: 'yellow',\n                    neo_color_green: 'green',\n                    neo_color_blue: 'blue',\n\n                    neo_button_1: 'button 1',\n                    neo_button_2: 'button 2',\n                    neo_button_3: 'button 3',\n                    neo_button_4: 'button 4',\n\n                    neo_button_on: 'ON',\n                    neo_button_off: 'OFF',\n\n                    neo_buzzer_octave_1: '1 octave',\n                    neo_buzzer_octave_2: '2 octave',\n                    neo_buzzer_octave_3: '3 octave',\n                    neo_buzzer_octave_4: '4 octave',\n                    neo_buzzer_octave_5: '5 octave',\n                    neo_buzzer_octave_6: '6 octave',\n\n                    neo_buzzer_do: 'Do',\n                    neo_buzzer_do_sharp: 'Do#',\n                    neo_buzzer_re: 'Re',\n                    neo_buzzer_re_sharp: 'Re#',\n                    neo_buzzer_mi: 'Mi',\n                    neo_buzzer_fa: 'Fa',\n                    neo_buzzer_fa_sharp: 'Fa#',\n                    neo_buzzer_sol: 'So',\n                    neo_buzzer_sol_sharp: 'So#',\n                    neo_buzzer_la: 'La',\n                    neo_buzzer_la_sharp: 'La#',\n                    neo_buzzer_ti: 'Si',\n\n                    neo_buzzer_whole_note: 'whole note',\n                    neo_buzzer_half_note: 'a half note',\n                    neo_buzzer_quarter_note: 'a quarter note',\n                    neo_buzzer_8th_note: 'a eighth note',\n\n                    neo_lcd_image_1: 'angry',\n                    neo_lcd_image_2: 'dizzy',\n                    neo_lcd_image_3: 'smart',\n                    neo_lcd_image_4: 'lively',\n                    neo_lcd_image_5: 'kiss',\n                    neo_lcd_image_6: 'lovely',\n                    neo_lcd_image_7: 'wink',\n                    neo_lcd_image_8: 'cry',\n                    neo_lcd_image_9: 'sleepy',\n                    neo_lcd_image_10: 'smiley',\n                    neo_lcd_image_11: 'cute',\n                    neo_lcd_image_12: 'doubt',\n                    neo_lcd_image_13: 'bad',\n                },\n            }, //\n        };\n    }\n\n    getBlocks() {\n        return {\n            /**\n             * 로봇\n             */\n            neo_robot_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_robot_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_robot_title',\n                },\n                class: 'neo_robot',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_robot_move: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_robot_direction_f, 1],\n                            [Lang.Blocks.neo_robot_direction_b, 2],\n                            [Lang.Blocks.neo_robot_direction_l, 3],\n                            [Lang.Blocks.neo_robot_direction_r, 4],\n                            [Lang.Blocks.neo_robot_direction_tl, 5],\n                            [Lang.Blocks.neo_robot_direction_tr, 6],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_95, '95'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_85, '85'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_75, '75'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_65, '65'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_55, '55'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_45, '45'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_35, '35'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_25, '25'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_15, '15'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_5, '5'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '100',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'neo_arg_duration',\n                        },\n                        null,\n                    ],\n                    type: 'neo_robot_move',\n                },\n                paramsKeyMap: {\n                    DIRECTION: 0,\n                    SPEED: 1,\n                    DURATION: 2,\n                },\n                class: 'neo_robot',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const direction = script.getNumberField('DIRECTION');\n                        const speed = script.getStringField('SPEED');\n                        const duration = script.getStringValue('DURATION', script);\n                        const blockId = this.generateBlockId();\n                        if (speed.indexOf('IN') >= 0) {\n                            this.requestExtCommand(blockId, NeoBlockType.ROBOT_MOVE, [\n                                direction,\n                                speed,\n                            ]);\n                        } else {\n                            this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [\n                                direction,\n                                speed,\n                            ]);\n                        }\n                        if (duration === 'c' || !Entry.parseNumber(duration)) {\n                            script.block_id = blockId;\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                        } else {\n                            script.exec_phase = ExecPhase.SET_TIMEOUT;\n                        }\n                    } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                        const duration = script.getStringValue('DURATION', script);\n                        const durationValue = Entry.parseNumber(duration);\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, durationValue * 1000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const direction = script.getNumberField('DIRECTION', script);\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [direction, 0]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_robot_stop: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'neo_robot_stop',\n                },\n                paramsKeyMap: {\n                    //\n                },\n                class: 'neo_robot',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        this.requestCommand(blockId, NeoBlockType.ROBOT_STOP, []);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            /**\n             * 자율주행\n             */\n            neo_auto_driving_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_auto_driving_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_auto_driving_title',\n                },\n                class: 'neo_auto_driving',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_auto_driving_start: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_95, '95'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_85, '85'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_75, '75'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_65, '65'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_55, '55'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_45, '45'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_35, '35'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_25, '25'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_15, '15'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_5, '5'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '60',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'neo_arg_duration',\n                        },\n                        null,\n                    ],\n                    type: 'neo_auto_driving_start',\n                },\n                paramsKeyMap: {\n                    SPEED: 0,\n                    DURATION: 1,\n                },\n                class: 'neo_auto_driving',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const speed = script.getStringField('SPEED');\n                        const duration = script.getStringValue('DURATION', script);\n                        const blockId = this.generateBlockId();\n                        if (speed.indexOf('IN') >= 0) {\n                            this.requestExtCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [\n                                speed,\n                            ]);\n                        } else {\n                            this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [speed]);\n                        }\n                        if (duration === 'c' || !Entry.parseNumber(duration)) {\n                            script.block_id = blockId;\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                        } else {\n                            script.exec_phase = ExecPhase.SET_TIMEOUT;\n                        }\n                    } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                        const duration = script.getStringValue('DURATION', script);\n                        const durationValue = Entry.parseNumber(duration);\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, durationValue * 1000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [0]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_auto_driving_sensor_start: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_input_1_2, 0x10],\n                            [Lang.Blocks.neo_input_11_12, 0x11],\n                            [Lang.Blocks.neo_input_13_14, 0x12],\n                            [Lang.Blocks.neo_input_21_22, 0x13],\n                            [Lang.Blocks.neo_input_23_24, 0x14],\n                            [Lang.Blocks.neo_input_31_32, 0x15],\n                            [Lang.Blocks.neo_input_33_34, 0x16],\n                        ],\n                        value: 0x10,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_95, '95'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_85, '85'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_75, '75'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_65, '65'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_55, '55'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_45, '45'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_35, '35'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_25, '25'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_15, '15'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_5, '5'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '60',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'neo_auto_driving_sensor_start',\n                },\n                paramsKeyMap: {\n                    SENSOR: 0,\n                    SPEED: 1,\n                },\n                class: 'neo_auto_driving',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const sensor = script.getNumberField('SENSOR');\n                        const speed = script.getStringField('SPEED');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        if (speed.indexOf('IN') >= 0) {\n                            this.requestExtCommand(\n                              blockId,\n                              NeoBlockType.AUTO_DRIVING_SENSOR_START,\n                              [sensor, speed]\n                            );\n                        } else {\n                            this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_SENSOR_START, [\n                                sensor,\n                                speed,\n                            ]);\n                        }\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_auto_driving_stop: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'neo_auto_driving_stop',\n                },\n                paramsKeyMap: {\n                    DIRECTION: 0,\n                },\n                class: 'neo_auto_driving',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_STOP, []);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            /**\n             * 자율주차\n             */\n            neo_auto_parking_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_auto_parking_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_auto_parking_title',\n                },\n                class: 'neo_auto_parking',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_auto_parking_start: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_auto_parking_which_l, 1],\n                            [Lang.Blocks.neo_auto_parking_which_r, 2],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_auto_parking_direction_b, 1],\n                            [Lang.Blocks.neo_auto_parking_direction_s, 2],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'neo_auto_parking_start',\n                },\n                paramsKeyMap: {\n                    WHICH: 0,\n                    DIRECTION: 1,\n                },\n                class: 'neo_auto_parking',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    return this.runAutoParking(script);\n                },\n            },\n            /**\n             * 라인트레이서\n             */\n            neo_line_tracer_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_line_tracer_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_line_tracer_title',\n                },\n                class: 'neo_line_tracer',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_line_tracer_start: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_95, '95'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_85, '85'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_75, '75'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_65, '65'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_55, '55'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_45, '45'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_35, '35'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_25, '25'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_15, '15'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_5, '5'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '60',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'neo_arg_duration',\n                        },\n                        null,\n                    ],\n                    type: 'neo_line_tracer_start',\n                },\n                paramsKeyMap: {\n                    SPEED: 0,\n                    DURATION: 1,\n                },\n                class: 'neo_auto_driving',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const speed = script.getStringField('SPEED');\n                        const blockId = this.generateBlockId();\n                        const duration = script.getStringValue('DURATION', script);\n                        if (speed.indexOf('IN') >= 0) {\n                            this.requestExtCommand(blockId, NeoBlockType.LINE_TRACER_START, [\n                                speed,\n                            ]);\n                        } else {\n                            this.requestCommand(blockId, NeoBlockType.LINE_TRACER_START, [speed]);\n                        }\n                        if (duration === 'c' || !Entry.parseNumber(duration)) {\n                            script.block_id = blockId;\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                        } else {\n                            script.exec_phase = ExecPhase.SET_TIMEOUT;\n                        }\n                    } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                        const duration = script.getStringValue('DURATION', script);\n                        const durationValue = Entry.parseNumber(duration);\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, durationValue * 1000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.LINE_TRACER_START, [0]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_line_cross_move: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_line_cross_move_1, 1],\n                            [Lang.Blocks.neo_line_cross_move_2, 2],\n                            [Lang.Blocks.neo_line_cross_move_3, 3],\n                            [Lang.Blocks.neo_line_cross_move_4, 4],\n                            [Lang.Blocks.neo_line_cross_move_5, 5],\n                            [Lang.Blocks.neo_line_cross_move_6, 6],\n                            [Lang.Blocks.neo_line_cross_move_7, 7],\n                            [Lang.Blocks.neo_line_cross_move_8, 8],\n                            [Lang.Blocks.neo_line_cross_move_9, 9],\n                            [Lang.Blocks.neo_line_cross_move_10, 10],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_line_cross_move',\n                },\n                paramsKeyMap: {\n                    COUNT: 0,\n                },\n                class: 'neo_auto_driving',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const count = script.getStringField('COUNT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.LINE_CROSS_MOVE, [count]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_line_cross_turn: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_turn_direction_l, 30],\n                            [Lang.Blocks.neo_turn_direction_r, 31],\n                        ],\n                        value: 30,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_line_cross_turn',\n                },\n                paramsKeyMap: {\n                    DIRECTION: 0,\n                },\n                class: 'neo_auto_driving',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const direction = script.getStringField('DIRECTION');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.LINE_CROSS_TURN, [direction]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_line_cross_reached: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                fontColor: '#fff',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'neo_line_cross_reached',\n                },\n                paramsKeyMap: {},\n                class: 'neo_auto_driving',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const sensorData = Entry.hw.portData['sensor'];\n                    const leftValue = sensorData['in1Values'][0];\n                    const rightValue = sensorData['in1Values'][1];\n                    return 0 <= leftValue && leftValue <= 50 && 0 <= rightValue && rightValue <= 50;\n                },\n            },\n\n            /**\n             * 회전모터\n             */\n            neo_motor_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_motor_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_motor_title',\n                },\n                class: 'neo_motor',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_motor_move: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_out_l, 1],\n                            [Lang.Blocks.neo_motor_out_r, 2],\n                            [Lang.Blocks.neo_motor_out_lr, 0],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_95, '95'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_85, '85'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_75, '75'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_65, '65'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_55, '55'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_45, '45'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_35, '35'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_25, '25'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_15, '15'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_5, '5'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_motor_speed_n5, '-5'],\n                            [Lang.Blocks.neo_motor_speed_n10, '-10'],\n                            [Lang.Blocks.neo_motor_speed_n15, '-15'],\n                            [Lang.Blocks.neo_motor_speed_n20, '-20'],\n                            [Lang.Blocks.neo_motor_speed_n25, '-25'],\n                            [Lang.Blocks.neo_motor_speed_n30, '-30'],\n                            [Lang.Blocks.neo_motor_speed_n35, '-35'],\n                            [Lang.Blocks.neo_motor_speed_n40, '-40'],\n                            [Lang.Blocks.neo_motor_speed_n45, '-45'],\n                            [Lang.Blocks.neo_motor_speed_n50, '-50'],\n                            [Lang.Blocks.neo_motor_speed_n55, '-55'],\n                            [Lang.Blocks.neo_motor_speed_n60, '-60'],\n                            [Lang.Blocks.neo_motor_speed_n65, '-65'],\n                            [Lang.Blocks.neo_motor_speed_n70, '-70'],\n                            [Lang.Blocks.neo_motor_speed_n75, '-75'],\n                            [Lang.Blocks.neo_motor_speed_n80, '-80'],\n                            [Lang.Blocks.neo_motor_speed_n85, '-85'],\n                            [Lang.Blocks.neo_motor_speed_n90, '-90'],\n                            [Lang.Blocks.neo_motor_speed_n95, '-95'],\n                            [Lang.Blocks.neo_motor_speed_n100, '-100'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '100',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'neo_arg_duration',\n                        },\n                        null,\n                    ],\n                    type: 'neo_motor_move',\n                },\n                paramsKeyMap: {\n                    DC: 0,\n                    SPEED: 1,\n                    DURATION: 2,\n                },\n                class: 'neo_motor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const dc = script.getNumberField('DC');\n                        const speed = script.getStringField('SPEED');\n                        const duration = script.getStringValue('DURATION', script);\n                        const blockId = this.generateBlockId();\n                        if (speed.indexOf('IN') >= 0) {\n                            this.requestExtCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, speed]);\n                        } else {\n                            this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, speed]);\n                        }\n                        if (duration === 'c' || !Entry.parseNumber(duration)) {\n                            script.block_id = blockId;\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                        } else {\n                            script.exec_phase = ExecPhase.SET_TIMEOUT;\n                        }\n                    } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        const duration = script.getStringValue('DURATION', script);\n                        const durationValue = Entry.parseNumber(duration);\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, durationValue * 1000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const dc = script.getNumberField('DC', script);\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, 0]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_motor_move_both: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'neo_arg_both_motor_speed',\n                        },\n                        {\n                            type: 'neo_arg_both_motor_speed',\n                        },\n                        null,\n                    ],\n                    type: 'neo_motor_move_both',\n                },\n                paramsKeyMap: {\n                    SPEED_L: 0,\n                    SPEED_R: 1,\n                },\n                class: 'neo_motor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const speedL = script.getNumberValue('SPEED_L', script);\n                        const speedR = script.getNumberValue('SPEED_R', script);\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE_BOTH, [\n                            speedL,\n                            speedR,\n                        ]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_motor_stop: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_out_l, 1],\n                            [Lang.Blocks.neo_motor_out_r, 2],\n                            [Lang.Blocks.neo_motor_out_lr, 0],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_motor_stop',\n                },\n                paramsKeyMap: {\n                    DC: 0,\n                },\n                class: 'neo_motor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const dc = script.getStringField('DC');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        this.requestCommand(blockId, NeoBlockType.MOTOR_STOP, [dc]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n\n            /**\n             * 서보모터\n             */\n            neo_servo_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_servo_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_servo_title',\n                },\n                class: 'neo_servo',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_servo_reset: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_servo_reset',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                },\n                class: 'neo_servo',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.SERVO_RESET, [output]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_servo_angle: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_servo_angle_360, '360'],\n                            [Lang.Blocks.neo_servo_angle_350, '350'],\n                            [Lang.Blocks.neo_servo_angle_340, '340'],\n                            [Lang.Blocks.neo_servo_angle_330, '330'],\n                            [Lang.Blocks.neo_servo_angle_320, '320'],\n                            [Lang.Blocks.neo_servo_angle_310, '310'],\n                            [Lang.Blocks.neo_servo_angle_300, '300'],\n                            [Lang.Blocks.neo_servo_angle_290, '290'],\n                            [Lang.Blocks.neo_servo_angle_280, '280'],\n                            [Lang.Blocks.neo_servo_angle_270, '270'],\n                            [Lang.Blocks.neo_servo_angle_260, '260'],\n                            [Lang.Blocks.neo_servo_angle_250, '250'],\n                            [Lang.Blocks.neo_servo_angle_240, '240'],\n                            [Lang.Blocks.neo_servo_angle_230, '230'],\n                            [Lang.Blocks.neo_servo_angle_220, '220'],\n                            [Lang.Blocks.neo_servo_angle_210, '210'],\n                            [Lang.Blocks.neo_servo_angle_200, '200'],\n                            [Lang.Blocks.neo_servo_angle_190, '190'],\n                            [Lang.Blocks.neo_servo_angle_180, '180'],\n                            [Lang.Blocks.neo_servo_angle_170, '170'],\n                            [Lang.Blocks.neo_servo_angle_160, '160'],\n                            [Lang.Blocks.neo_servo_angle_150, '150'],\n                            [Lang.Blocks.neo_servo_angle_140, '140'],\n                            [Lang.Blocks.neo_servo_angle_130, '130'],\n                            [Lang.Blocks.neo_servo_angle_120, '120'],\n                            [Lang.Blocks.neo_servo_angle_110, '110'],\n                            [Lang.Blocks.neo_servo_angle_100, '100'],\n                            [Lang.Blocks.neo_servo_angle_90, '90'],\n                            [Lang.Blocks.neo_servo_angle_80, '80'],\n                            [Lang.Blocks.neo_servo_angle_70, '70'],\n                            [Lang.Blocks.neo_servo_angle_60, '60'],\n                            [Lang.Blocks.neo_servo_angle_50, '50'],\n                            [Lang.Blocks.neo_servo_angle_40, '40'],\n                            [Lang.Blocks.neo_servo_angle_30, '30'],\n                            [Lang.Blocks.neo_servo_angle_20, '20'],\n                            [Lang.Blocks.neo_servo_angle_10, '10'],\n                            [Lang.Blocks.neo_servo_angle_0, '0'],\n                            [Lang.Blocks.neo_servo_angle_n10, '-10'],\n                            [Lang.Blocks.neo_servo_angle_n20, '-20'],\n                            [Lang.Blocks.neo_servo_angle_n30, '-30'],\n                            [Lang.Blocks.neo_servo_angle_n40, '-40'],\n                            [Lang.Blocks.neo_servo_angle_n50, '-50'],\n                            [Lang.Blocks.neo_servo_angle_n60, '-60'],\n                            [Lang.Blocks.neo_servo_angle_n70, '-70'],\n                            [Lang.Blocks.neo_servo_angle_n80, '-80'],\n                            [Lang.Blocks.neo_servo_angle_n90, '-90'],\n                            [Lang.Blocks.neo_servo_angle_n100, '-100'],\n                            [Lang.Blocks.neo_servo_angle_n110, '-110'],\n                            [Lang.Blocks.neo_servo_angle_n120, '-120'],\n                            [Lang.Blocks.neo_servo_angle_n130, '-130'],\n                            [Lang.Blocks.neo_servo_angle_n140, '-140'],\n                            [Lang.Blocks.neo_servo_angle_n150, '-150'],\n                            [Lang.Blocks.neo_servo_angle_n160, '-160'],\n                            [Lang.Blocks.neo_servo_angle_n170, '-170'],\n                            [Lang.Blocks.neo_servo_angle_n180, '-180'],\n                            [Lang.Blocks.neo_servo_angle_n190, '-190'],\n                            [Lang.Blocks.neo_servo_angle_n200, '-200'],\n                            [Lang.Blocks.neo_servo_angle_n210, '-210'],\n                            [Lang.Blocks.neo_servo_angle_n220, '-220'],\n                            [Lang.Blocks.neo_servo_angle_n230, '-230'],\n                            [Lang.Blocks.neo_servo_angle_n240, '-240'],\n                            [Lang.Blocks.neo_servo_angle_n250, '-250'],\n                            [Lang.Blocks.neo_servo_angle_n260, '-260'],\n                            [Lang.Blocks.neo_servo_angle_n270, '-270'],\n                            [Lang.Blocks.neo_servo_angle_n280, '-280'],\n                            [Lang.Blocks.neo_servo_angle_n290, '-290'],\n                            [Lang.Blocks.neo_servo_angle_n300, '-300'],\n                            [Lang.Blocks.neo_servo_angle_n310, '-310'],\n                            [Lang.Blocks.neo_servo_angle_n320, '-320'],\n                            [Lang.Blocks.neo_servo_angle_n330, '-330'],\n                            [Lang.Blocks.neo_servo_angle_n340, '-340'],\n                            [Lang.Blocks.neo_servo_angle_n350, '-350'],\n                            [Lang.Blocks.neo_servo_angle_n360, '-360'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '90',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '50',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null, null],\n                    type: 'neo_servo_angle',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    ANGLE: 1,\n                    SPEED: 2,\n                },\n                class: 'neo_servo',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const angle = script.getStringField('ANGLE');\n                        const speed = script.getStringField('SPEED');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        const isExt2 = angle.indexOf('IN') >= 0 && speed.indexOf('IN') >= 0;\n                        if (isExt2) {\n                            this.requestExt2Command(blockId, NeoBlockType.SERVO_ANGLE, [\n                                output,\n                                angle,\n                                speed,\n                            ]);\n                        } else {\n                            const isExt1 = angle.indexOf('IN') >= 0 || speed.indexOf('IN') >= 0;\n                            if (isExt1) {\n                                this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE, [\n                                    output,\n                                    angle,\n                                    speed,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [\n                                    output,\n                                    angle,\n                                    speed,\n                                ]);\n                            }\n                        }\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_servo_angle_var: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '50',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'neo_arg_servo_angle',\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'neo_servo_angle_var',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    ANGLE: 1,\n                    SPEED: 2,\n                },\n                class: 'neo_servo',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const angle = script.getNumberValue('ANGLE', script);\n                        const speed = script.getStringField('SPEED');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [\n                            output,\n                            angle,\n                            speed,\n                        ]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_servo_angle_wait: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_servo_angle_360, '360'],\n                            [Lang.Blocks.neo_servo_angle_350, '350'],\n                            [Lang.Blocks.neo_servo_angle_340, '340'],\n                            [Lang.Blocks.neo_servo_angle_330, '330'],\n                            [Lang.Blocks.neo_servo_angle_320, '320'],\n                            [Lang.Blocks.neo_servo_angle_310, '310'],\n                            [Lang.Blocks.neo_servo_angle_300, '300'],\n                            [Lang.Blocks.neo_servo_angle_290, '290'],\n                            [Lang.Blocks.neo_servo_angle_280, '280'],\n                            [Lang.Blocks.neo_servo_angle_270, '270'],\n                            [Lang.Blocks.neo_servo_angle_260, '260'],\n                            [Lang.Blocks.neo_servo_angle_250, '250'],\n                            [Lang.Blocks.neo_servo_angle_240, '240'],\n                            [Lang.Blocks.neo_servo_angle_230, '230'],\n                            [Lang.Blocks.neo_servo_angle_220, '220'],\n                            [Lang.Blocks.neo_servo_angle_210, '210'],\n                            [Lang.Blocks.neo_servo_angle_200, '200'],\n                            [Lang.Blocks.neo_servo_angle_190, '190'],\n                            [Lang.Blocks.neo_servo_angle_180, '180'],\n                            [Lang.Blocks.neo_servo_angle_170, '170'],\n                            [Lang.Blocks.neo_servo_angle_160, '160'],\n                            [Lang.Blocks.neo_servo_angle_150, '150'],\n                            [Lang.Blocks.neo_servo_angle_140, '140'],\n                            [Lang.Blocks.neo_servo_angle_130, '130'],\n                            [Lang.Blocks.neo_servo_angle_120, '120'],\n                            [Lang.Blocks.neo_servo_angle_110, '110'],\n                            [Lang.Blocks.neo_servo_angle_100, '100'],\n                            [Lang.Blocks.neo_servo_angle_90, '90'],\n                            [Lang.Blocks.neo_servo_angle_80, '80'],\n                            [Lang.Blocks.neo_servo_angle_70, '70'],\n                            [Lang.Blocks.neo_servo_angle_60, '60'],\n                            [Lang.Blocks.neo_servo_angle_50, '50'],\n                            [Lang.Blocks.neo_servo_angle_40, '40'],\n                            [Lang.Blocks.neo_servo_angle_30, '30'],\n                            [Lang.Blocks.neo_servo_angle_20, '20'],\n                            [Lang.Blocks.neo_servo_angle_10, '10'],\n                            [Lang.Blocks.neo_servo_angle_0, '0'],\n                            [Lang.Blocks.neo_servo_angle_n10, '-10'],\n                            [Lang.Blocks.neo_servo_angle_n20, '-20'],\n                            [Lang.Blocks.neo_servo_angle_n30, '-30'],\n                            [Lang.Blocks.neo_servo_angle_n40, '-40'],\n                            [Lang.Blocks.neo_servo_angle_n50, '-50'],\n                            [Lang.Blocks.neo_servo_angle_n60, '-60'],\n                            [Lang.Blocks.neo_servo_angle_n70, '-70'],\n                            [Lang.Blocks.neo_servo_angle_n80, '-80'],\n                            [Lang.Blocks.neo_servo_angle_n90, '-90'],\n                            [Lang.Blocks.neo_servo_angle_n100, '-100'],\n                            [Lang.Blocks.neo_servo_angle_n110, '-110'],\n                            [Lang.Blocks.neo_servo_angle_n120, '-120'],\n                            [Lang.Blocks.neo_servo_angle_n130, '-130'],\n                            [Lang.Blocks.neo_servo_angle_n140, '-140'],\n                            [Lang.Blocks.neo_servo_angle_n150, '-150'],\n                            [Lang.Blocks.neo_servo_angle_n160, '-160'],\n                            [Lang.Blocks.neo_servo_angle_n170, '-170'],\n                            [Lang.Blocks.neo_servo_angle_n180, '-180'],\n                            [Lang.Blocks.neo_servo_angle_n190, '-190'],\n                            [Lang.Blocks.neo_servo_angle_n200, '-200'],\n                            [Lang.Blocks.neo_servo_angle_n210, '-210'],\n                            [Lang.Blocks.neo_servo_angle_n220, '-220'],\n                            [Lang.Blocks.neo_servo_angle_n230, '-230'],\n                            [Lang.Blocks.neo_servo_angle_n240, '-240'],\n                            [Lang.Blocks.neo_servo_angle_n250, '-250'],\n                            [Lang.Blocks.neo_servo_angle_n260, '-260'],\n                            [Lang.Blocks.neo_servo_angle_n270, '-270'],\n                            [Lang.Blocks.neo_servo_angle_n280, '-280'],\n                            [Lang.Blocks.neo_servo_angle_n290, '-290'],\n                            [Lang.Blocks.neo_servo_angle_n300, '-300'],\n                            [Lang.Blocks.neo_servo_angle_n310, '-310'],\n                            [Lang.Blocks.neo_servo_angle_n320, '-320'],\n                            [Lang.Blocks.neo_servo_angle_n330, '-330'],\n                            [Lang.Blocks.neo_servo_angle_n340, '-340'],\n                            [Lang.Blocks.neo_servo_angle_n350, '-350'],\n                            [Lang.Blocks.neo_servo_angle_n360, '-360'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '90',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                        ],\n                        value: '50',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null, null],\n                    type: 'neo_servo_angle_wait',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    ANGLE: 1,\n                    SPEED: 2,\n                },\n                class: 'neo_servo',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const angle = script.getStringField('ANGLE');\n                        const speed = script.getStringField('SPEED');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        const isExt2 = angle.indexOf('IN') >= 0 && speed.indexOf('IN') >= 0;\n                        if (isExt2) {\n                            this.requestExt2Command(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [\n                                output,\n                                angle,\n                                speed,\n                            ]);\n                        } else {\n                            const isExt1 = angle.indexOf('IN') >= 0 || speed.indexOf('IN') >= 0;\n                            if (isExt1) {\n                                this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [\n                                    output,\n                                    angle,\n                                    speed,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [\n                                    output,\n                                    angle,\n                                    speed,\n                                ]);\n                            }\n                        }\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_servo_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_servo_direction_f, 1],\n                            [Lang.Blocks.neo_servo_direction_b, 2],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '50',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null, null],\n                    type: 'neo_servo_rotate',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    DIRECTION: 1,\n                    SPEED: 2,\n                },\n                class: 'neo_servo',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const direction = script.getStringField('DIRECTION');\n                        const speed = script.getStringField('SPEED');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        if (speed.indexOf('IN') >= 0) {\n                            this.requestExtCommand(blockId, NeoBlockType.SERVO_ROTATE, [\n                                output,\n                                direction,\n                                speed,\n                            ]);\n                        } else {\n                            this.requestCommand(blockId, NeoBlockType.SERVO_ROTATE, [\n                                output,\n                                direction,\n                                speed,\n                            ]);\n                        }\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_servo_stop: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_servo_stop',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                },\n                class: 'neo_servo',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.SERVO_STOP, [output]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n\n            /**\n             * LED\n             */\n            neo_led_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_led_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_led_title',\n                },\n                class: 'neo_led',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_led_on: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_led_brightness_100, '100'],\n                            [Lang.Blocks.neo_led_brightness_90, '90'],\n                            [Lang.Blocks.neo_led_brightness_80, '80'],\n                            [Lang.Blocks.neo_led_brightness_70, '70'],\n                            [Lang.Blocks.neo_led_brightness_60, '60'],\n                            [Lang.Blocks.neo_led_brightness_50, '50'],\n                            [Lang.Blocks.neo_led_brightness_40, '40'],\n                            [Lang.Blocks.neo_led_brightness_30, '30'],\n                            [Lang.Blocks.neo_led_brightness_20, '20'],\n                            [Lang.Blocks.neo_led_brightness_10, '10'],\n                            [Lang.Blocks.neo_led_brightness_0, '0'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '100',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'neo_arg_duration',\n                        },\n                        null,\n                    ],\n                    type: 'neo_led_on',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    BRIGHTNESS: 1,\n                    DURATION: 2,\n                },\n                class: 'neo_led',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const output = script.getStringField('OUTPUT');\n                        const brightness = script.getStringField('BRIGHTNESS');\n                        const duration = script.getStringValue('DURATION', script);\n                        const blockId = this.generateBlockId();\n                        if (brightness.indexOf('IN') >= 0) {\n                            this.requestExtCommand(blockId, NeoBlockType.LED_ON, [\n                                output,\n                                brightness,\n                            ]);\n                        } else {\n                            this.requestCommand(blockId, NeoBlockType.LED_ON, [output, brightness]);\n                        }\n                        if (duration === 'c' || !Entry.parseNumber(duration)) {\n                            script.block_id = blockId;\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                        } else {\n                            script.exec_phase = ExecPhase.SET_TIMEOUT;\n                        }\n                    } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                        const duration = script.getStringValue('DURATION', script);\n                        const durationValue = Entry.parseNumber(duration);\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, durationValue * 1000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const output = script.getStringField('OUTPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.LED_ON, [output, 0]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_led_blink: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_led_blink_speed_1, 500],\n                            [Lang.Blocks.neo_led_blink_speed_2, 400],\n                            [Lang.Blocks.neo_led_blink_speed_3, 300],\n                            [Lang.Blocks.neo_led_blink_speed_4, 200],\n                            [Lang.Blocks.neo_led_blink_speed_5, 100],\n                        ],\n                        value: 100,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'neo_arg_duration',\n                        },\n                        null,\n                    ],\n                    type: 'neo_led_blink',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    SPEED: 1,\n                    DURATION: 2,\n                },\n                class: 'neo_led',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const output = script.getStringField('OUTPUT');\n                        const speed = script.getStringField('SPEED');\n                        const duration = script.getStringValue('DURATION', script);\n                        const blockId = this.generateBlockId();\n                        this.requestCommand(blockId, NeoBlockType.LED_BLINK, [output, speed, 100]);\n                        if (duration === 'c' || !Entry.parseNumber(duration)) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            script.block_id = blockId;\n                        } else {\n                            script.exec_phase = ExecPhase.SET_TIMEOUT;\n                        }\n                    } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                        const duration = script.getStringValue('DURATION', script);\n                        const durationValue = Entry.parseNumber(duration);\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, durationValue * 1000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const output = script.getStringField('OUTPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.LED_BLINK, [output, 0, 0]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_led_off: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_led_off',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                },\n                class: 'neo_led',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.LED_OFF, [output]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            /**\n             * 컬러 LED\n             */\n            neo_color_led_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_color_led_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_color_led_title',\n                },\n                class: 'neo_color_led',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_color_led_on: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Color',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        '#0000FF',\n                        {\n                            type: 'neo_arg_duration',\n                        },\n                        null,\n                    ],\n                    type: 'neo_color_led_on',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    COLOR: 1,\n                    DURATION: 2,\n                },\n                class: 'neo_color_led',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const output = script.getStringField('OUTPUT');\n                        const color = script.getStringValue('COLOR', script);\n                        const duration = script.getStringValue('DURATION', script);\n                        const blockId = this.generateBlockId();\n                        this.requestCommand(blockId, NeoBlockType.COLOR_LED_ON, [output, color]);\n                        if (duration === 'c' || !Entry.parseNumber(duration)) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            script.block_id = blockId;\n                        } else {\n                            script.exec_phase = ExecPhase.SET_TIMEOUT;\n                        }\n                    } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                        const duration = script.getStringValue('DURATION', script);\n                        const durationValue = Entry.parseNumber(duration);\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, durationValue * 1000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const output = script.getStringField('OUTPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.COLOR_LED_ON, [output, 0]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_color_led_off: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_color_led_off',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                },\n                class: 'neo_color_led',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.COLOR_LED_OFF, [output]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            neo_color_led_on_with_sensor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: 'IN1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'neo_color_led_on_with_sensor',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                    OUTPUT: 1,\n                },\n                class: 'neo_color_led',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const input = script.getStringField('INPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestExtCommand(blockId, NeoBlockType.COLOR_LED_ON_SENSOR, [\n                            output,\n                            input,\n                        ]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            /**\n             * 출력\n             */\n            neo_set_output_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_set_output_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_set_output_title',\n                },\n                class: 'neo_set_output',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_set_output: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                            [Lang.Blocks.neo_output_12, 'OUT12'],\n                            [Lang.Blocks.neo_output_123, 'OUT123'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_set_output_value_255, '255'],\n                            [Lang.Blocks.neo_set_output_value_250, '250'],\n                            [Lang.Blocks.neo_set_output_value_245, '245'],\n                            [Lang.Blocks.neo_set_output_value_240, '240'],\n                            [Lang.Blocks.neo_set_output_value_235, '235'],\n                            [Lang.Blocks.neo_set_output_value_230, '230'],\n                            [Lang.Blocks.neo_set_output_value_225, '225'],\n                            [Lang.Blocks.neo_set_output_value_220, '220'],\n                            [Lang.Blocks.neo_set_output_value_215, '215'],\n                            [Lang.Blocks.neo_set_output_value_210, '210'],\n                            [Lang.Blocks.neo_set_output_value_205, '205'],\n                            [Lang.Blocks.neo_set_output_value_200, '200'],\n                            [Lang.Blocks.neo_set_output_value_195, '195'],\n                            [Lang.Blocks.neo_set_output_value_190, '190'],\n                            [Lang.Blocks.neo_set_output_value_185, '185'],\n                            [Lang.Blocks.neo_set_output_value_180, '180'],\n                            [Lang.Blocks.neo_set_output_value_175, '175'],\n                            [Lang.Blocks.neo_set_output_value_170, '170'],\n                            [Lang.Blocks.neo_set_output_value_165, '165'],\n                            [Lang.Blocks.neo_set_output_value_160, '160'],\n                            [Lang.Blocks.neo_set_output_value_155, '155'],\n                            [Lang.Blocks.neo_set_output_value_150, '150'],\n                            [Lang.Blocks.neo_set_output_value_145, '145'],\n                            [Lang.Blocks.neo_set_output_value_140, '140'],\n                            [Lang.Blocks.neo_set_output_value_135, '135'],\n                            [Lang.Blocks.neo_set_output_value_130, '130'],\n                            [Lang.Blocks.neo_set_output_value_125, '125'],\n                            [Lang.Blocks.neo_set_output_value_120, '120'],\n                            [Lang.Blocks.neo_set_output_value_115, '115'],\n                            [Lang.Blocks.neo_set_output_value_110, '110'],\n                            [Lang.Blocks.neo_set_output_value_105, '105'],\n                            [Lang.Blocks.neo_set_output_value_100, '100'],\n                            [Lang.Blocks.neo_set_output_value_95, '95'],\n                            [Lang.Blocks.neo_set_output_value_90, '90'],\n                            [Lang.Blocks.neo_set_output_value_85, '85'],\n                            [Lang.Blocks.neo_set_output_value_80, '80'],\n                            [Lang.Blocks.neo_set_output_value_75, '75'],\n                            [Lang.Blocks.neo_set_output_value_70, '70'],\n                            [Lang.Blocks.neo_set_output_value_65, '65'],\n                            [Lang.Blocks.neo_set_output_value_60, '60'],\n                            [Lang.Blocks.neo_set_output_value_55, '55'],\n                            [Lang.Blocks.neo_set_output_value_50, '50'],\n                            [Lang.Blocks.neo_set_output_value_45, '45'],\n                            [Lang.Blocks.neo_set_output_value_40, '40'],\n                            [Lang.Blocks.neo_set_output_value_35, '35'],\n                            [Lang.Blocks.neo_set_output_value_30, '30'],\n                            [Lang.Blocks.neo_set_output_value_25, '25'],\n                            [Lang.Blocks.neo_set_output_value_20, '20'],\n                            [Lang.Blocks.neo_set_output_value_15, '15'],\n                            [Lang.Blocks.neo_set_output_value_10, '10'],\n                            [Lang.Blocks.neo_set_output_value_5, '5'],\n                            [Lang.Blocks.neo_set_output_value_0, '0'],\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: '100',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'neo_arg_duration',\n                        },\n                        null,\n                    ],\n                    type: 'neo_set_output',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    VALUE: 1,\n                    DURATION: 2,\n                },\n                class: 'neo_set_output',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const output = script.getStringField('OUTPUT');\n                        const value = script.getStringField('VALUE');\n                        const duration = script.getStringValue('DURATION', script);\n                        const blockId = this.generateBlockId();\n                        if (value.indexOf('IN') >= 0) {\n                            this.requestExtCommand(blockId, NeoBlockType.SET_OUTPUT, [\n                                output,\n                                value,\n                            ]);\n                        } else {\n                            this.requestCommand(blockId, NeoBlockType.SET_OUTPUT, [output, value]);\n                        }\n                        if (duration === 'c' || !Entry.parseNumber(duration)) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            script.block_id = blockId;\n                        } else {\n                            script.exec_phase = ExecPhase.SET_TIMEOUT;\n                        }\n                    } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                        const duration = script.getStringValue('DURATION', script);\n                        const durationValue = Entry.parseNumber(duration);\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, durationValue * 1000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const output = script.getStringField('OUTPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.SET_OUTPUT, [output, 0]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            /**\n             * 센서\n             */\n            neo_sensor_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_sensor_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_sensor_title',\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_sensor_in: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                fontColor: '#fff',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['IN1', 'IN1'],\n                            ['IN2', 'IN2'],\n                            ['IN3', 'IN3'],\n                        ],\n                        value: 'IN1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'neo_sensor_in',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const input = script.getStringField('INPUT');\n                    const sensorData = Entry.hw.portData['sensor'];\n                    switch (input) {\n                        case 'IN1':\n                            return sensorData['in1Values'][0];\n                        case 'IN2':\n                            return sensorData['in2Values'][0];\n                        case 'IN3':\n                            return sensorData['in3Values'][0];\n                    }\n                    return 0;\n                },\n            },\n            neo_sensor_in_2: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                fontColor: '#fff',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['IN1', 'IN1'],\n                            ['IN2', 'IN2'],\n                            ['IN3', 'IN3'],\n                        ],\n                        value: 'IN2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'neo_sensor_in_2',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const input = script.getStringField('INPUT');\n                    const sensorData = Entry.hw.portData['sensor'];\n                    switch (input) {\n                        case 'IN1':\n                            return sensorData['in1Values'][0];\n                        case 'IN2':\n                            return sensorData['in2Values'][0];\n                        case 'IN3':\n                            return sensorData['in3Values'][0];\n                    }\n                    return 0;\n                },\n            },\n            neo_sensor_digital_in: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                fontColor: '#fff',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['IN1', 'IN1'],\n                            ['IN2', 'IN2'],\n                            ['IN3', 'IN3'],\n                        ],\n                        value: 'IN1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_sensor_in_digital_1, 0],\n                            [Lang.Blocks.neo_sensor_in_digital_2, 1],\n                            [Lang.Blocks.neo_sensor_in_digital_3, 2],\n                            [Lang.Blocks.neo_sensor_in_digital_4, 3],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'neo_sensor_digital_in',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                    INDEX: 1,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const input = script.getStringField('INPUT');\n                    const index = script.getNumberField('INDEX');\n                    const sensorData = Entry.hw.portData['sensor'];\n                    switch (input) {\n                        case 'IN1':\n                            return sensorData['in1Values'][index];\n                        case 'IN2':\n                            return sensorData['in2Values'][index];\n                        case 'IN3':\n                            return sensorData['in3Values'][index];\n                    }\n                    return 0;\n                },\n            },\n            neo_sensor_convert: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                fontColor: '#fff',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'neo_sensor_in',\n                        },\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['255'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                    ],\n                    type: 'neo_sensor_convert',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                    FROM_MIN: 1,\n                    FROM_MAX: 2,\n                    TO_MIN: 3,\n                    TO_MAX: 4,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    let value = script.getNumberValue('INPUT', script);\n                    let fromMin = script.getNumberValue('FROM_MIN', script);\n                    let fromMax = script.getNumberValue('FROM_MAX', script);\n                    let toMin = script.getNumberValue('TO_MIN', script);\n                    let toMax = script.getNumberValue('TO_MAX', script);\n\n                    if (fromMin > fromMax) {\n                        const temp = fromMin;\n                        fromMin = fromMax;\n                        fromMax = temp;\n                    }\n\n                    if (toMin > toMax) {\n                        const temp = toMin;\n                        toMin = toMax;\n                        toMax = temp;\n                    }\n\n                    value -= fromMin;\n                    value = value * ((toMax - toMin) / (fromMax - fromMin));\n                    value += toMin;\n                    value = Math.min(toMax, value);\n                    value = Math.max(toMin, value);\n\n                    return Math.round(value);\n                },\n            },\n            neo_sensor_compare: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_compare_gt, '>='],\n                            [Lang.Blocks.neo_compare_g, '>'],\n                            [Lang.Blocks.neo_compare_e, '='],\n                            [Lang.Blocks.neo_compare_l, '<'],\n                            [Lang.Blocks.neo_compare_lt, '<='],\n                        ],\n                        value: '>',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'neo_sensor_in',\n                        },\n                        null,\n                        10,\n                    ],\n                    type: 'neo_sensor_compare',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                    SYMBOL: 1,\n                    VALUE: 2,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const input = script.getNumberValue('INPUT', script);\n                    const symbol = script.getStringField('SYMBOL');\n                    const value = script.getNumberValue('VALUE', script);\n\n                    let sensorValue = input;\n                    if (symbol === '=') {\n                        return sensorValue === value;\n                    } else if (symbol === '>') {\n                        return sensorValue > value;\n                    } else if (symbol === '<') {\n                        return sensorValue < value;\n                    } else if (symbol === '>=') {\n                        return sensorValue >= value;\n                    } else if (symbol === '<=') {\n                        return sensorValue <= value;\n                    }\n\n                    return false;\n                },\n            },\n            neo_sensor_between: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_compare_gt, '>='],\n                            [Lang.Blocks.neo_compare_g, '>'],\n                            [Lang.Blocks.neo_compare_e, '='],\n                            [Lang.Blocks.neo_compare_l, '<'],\n                            [Lang.Blocks.neo_compare_lt, '<='],\n                        ],\n                        value: '<',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_compare_gt, '>='],\n                            [Lang.Blocks.neo_compare_g, '>'],\n                            [Lang.Blocks.neo_compare_e, '='],\n                            [Lang.Blocks.neo_compare_l, '<'],\n                            [Lang.Blocks.neo_compare_lt, '<='],\n                        ],\n                        value: '<',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        10,\n                        null,\n                        {\n                            type: 'neo_sensor_in',\n                        },\n                        null,\n                        30,\n                    ],\n                    type: 'neo_sensor_between',\n                },\n                paramsKeyMap: {\n                    L_VALUE: 0,\n                    L_SYMBOL: 1,\n                    INPUT: 2,\n                    R_SYMBOL: 3,\n                    R_VALUE: 4,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const input = script.getNumberValue('INPUT', script);\n                    const lSymbol = script.getStringField('L_SYMBOL');\n                    const lValue = script.getNumberValue('L_VALUE', script);\n                    const rSymbol = script.getStringField('R_SYMBOL');\n                    const rValue = script.getNumberValue('R_VALUE', script);\n\n                    let sensorValue = input;\n                    let lResult = false;\n                    if (lSymbol === '=') {\n                        lResult = lValue === sensorValue;\n                    } else if (lSymbol === '>') {\n                        lResult = lValue > sensorValue;\n                    } else if (lSymbol === '<') {\n                        lResult = lValue < sensorValue;\n                    } else if (lSymbol === '>=') {\n                        lResult = lValue >= sensorValue;\n                    } else if (lSymbol === '<=') {\n                        lResult = lValue <= sensorValue;\n                    }\n                    let rResult = false;\n                    if (rSymbol === '=') {\n                        rResult = sensorValue === rValue;\n                    } else if (rSymbol === '>') {\n                        rResult = sensorValue > rValue;\n                    } else if (rSymbol === '<') {\n                        rResult = sensorValue < rValue;\n                    } else if (rSymbol === '>=') {\n                        rResult = sensorValue >= rValue;\n                    } else if (rSymbol === '<=') {\n                        rResult = sensorValue <= rValue;\n                    }\n                    return lResult && rResult;\n                },\n            },\n            neo_sensor_digital_compare: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['IN1', 'IN1'],\n                            ['IN2', 'IN2'],\n                            ['IN3', 'IN3'],\n                        ],\n                        value: 'IN1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_sensor_in_digital_1, 0],\n                            [Lang.Blocks.neo_sensor_in_digital_2, 1],\n                            [Lang.Blocks.neo_sensor_in_digital_3, 2],\n                            [Lang.Blocks.neo_sensor_in_digital_4, 3],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_compare_gt, '>='],\n                            [Lang.Blocks.neo_compare_g, '>'],\n                            [Lang.Blocks.neo_compare_e, '='],\n                            [Lang.Blocks.neo_compare_l, '<'],\n                            [Lang.Blocks.neo_compare_lt, '<='],\n                        ],\n                        value: '>',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        null,\n                        10,\n                    ],\n                    type: 'neo_sensor_digital_compare',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                    INDEX: 1,\n                    SYMBOL: 2,\n                    VALUE: 3,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const input = script.getStringField('INPUT');\n                    const index = script.getNumberField('INDEX');\n                    const sensorData = Entry.hw.portData['sensor'];\n                    const symbol = script.getStringField('SYMBOL');\n                    const value = script.getNumberValue('VALUE', script);\n\n                    let sensorValue = 0;\n                    switch (input) {\n                        case 'IN1':\n                            sensorValue = sensorData['in1Values'][index];\n                            break;\n                        case 'IN2':\n                            sensorValue = sensorData['in2Values'][index];\n                            break;\n                        case 'IN3':\n                            sensorValue = sensorData['in3Values'][index];\n                            break;\n                    }\n\n                    if (symbol === '=') {\n                        return sensorValue === value;\n                    } else if (symbol === '>') {\n                        return sensorValue > value;\n                    } else if (symbol === '<') {\n                        return sensorValue < value;\n                    } else if (symbol === '>=') {\n                        return sensorValue >= value;\n                    } else if (symbol === '<=') {\n                        return sensorValue <= value;\n                    }\n\n                    return false;\n                },\n            },\n            neo_sensor_color_compare: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_color_black, 1],\n                            [Lang.Blocks.neo_color_white, 2],\n                            [Lang.Blocks.neo_color_red, 3],\n                            [Lang.Blocks.neo_color_yellow, 4],\n                            [Lang.Blocks.neo_color_green, 5],\n                            [Lang.Blocks.neo_color_blue, 6],\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'neo_sensor_in_2',\n                        },\n                        null,\n                    ],\n                    type: 'neo_sensor_color_compare',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                    COLOR: 1,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const input = script.getNumberValue('INPUT', script);\n                    const color = script.getNumberField('COLOR');\n                    let sensorValue = input;\n                    if (color === 1) {\n                        return 0 <= sensorValue && sensorValue <= 10;\n                    } else if (color === 2) {\n                        return 11 <= sensorValue && sensorValue <= 59;\n                    } else if (color === 3) {\n                        return 61 <= sensorValue && sensorValue <= 99;\n                    } else if (color === 4) {\n                        return 101 <= sensorValue && sensorValue <= 139;\n                    } else if (color === 5) {\n                        return 141 <= sensorValue && sensorValue <= 179;\n                    } else if (color === 6) {\n                        return 181 <= sensorValue && sensorValue <= 219;\n                    }\n\n                    return false;\n                },\n            },\n            neo_sensor_color_sequence_compare: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['IN1', 'IN1'],\n                            ['IN2', 'IN2'],\n                            ['IN3', 'IN3'],\n                        ],\n                        value: 'IN2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_color_red, 3],\n                            [Lang.Blocks.neo_color_yellow, 4],\n                            [Lang.Blocks.neo_color_green, 5],\n                            [Lang.Blocks.neo_color_blue, 6],\n                        ],\n                        value: '3',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_color_red, 3],\n                            [Lang.Blocks.neo_color_yellow, 4],\n                            [Lang.Blocks.neo_color_green, 5],\n                            [Lang.Blocks.neo_color_blue, 6],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_color_black, 1],\n                            [Lang.Blocks.neo_color_red, 3],\n                            [Lang.Blocks.neo_color_yellow, 4],\n                            [Lang.Blocks.neo_color_green, 5],\n                            [Lang.Blocks.neo_color_blue, 6],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null, null],\n                    type: 'neo_sensor_color_sequence_compare',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                    COLOR1: 1,\n                    COLOR2: 2,\n                    COLOR3: 3,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const input = script.getStringField('INPUT');\n                    const color1 = script.getNumberField('COLOR1');\n                    const color2 = script.getNumberField('COLOR2');\n                    const color3 = script.getNumberField('COLOR3');\n                    const sensorData = Entry.hw.portData['sensor'];\n                    let seq1 = 0;\n                    let seq2 = 0;\n                    let seq3 = 0;\n                    switch (input) {\n                        case 'IN1':\n                            seq1 = sensorData['in1Values'][1];\n                            seq2 = sensorData['in1Values'][2];\n                            seq3 = sensorData['in1Values'][3];\n                            break;\n                        case 'IN2':\n                            seq1 = sensorData['in2Values'][1];\n                            seq2 = sensorData['in2Values'][2];\n                            seq3 = sensorData['in2Values'][3];\n                            break;\n                        case 'IN3':\n                            seq1 = sensorData['in3Values'][1];\n                            seq2 = sensorData['in3Values'][2];\n                            seq3 = sensorData['in3Values'][3];\n                            break;\n                    }\n                    let compare1 = false;\n                    let compare2 = false;\n                    let compare3 = false;\n\n                    if (color1 === 3) compare1 = 61 <= seq1 && seq1 <= 99;\n                    else if (color1 === 4) compare1 = 101 <= seq1 && seq1 <= 139;\n                    else if (color1 === 5) compare1 = 141 <= seq1 && seq1 <= 179;\n                    else if (color1 === 6) compare1 = 181 <= seq1 && seq1 <= 219;\n\n                    if (color2 === 3) compare2 = 61 <= seq2 && seq2 <= 99;\n                    else if (color2 === 4) compare2 = 101 <= seq2 && seq2 <= 139;\n                    else if (color2 === 5) compare2 = 141 <= seq2 && seq2 <= 179;\n                    else if (color2 === 6) compare2 = 181 <= seq2 && seq2 <= 219;\n\n                    if (color3 === 1) compare3 = 0 <= seq3 && seq3 <= 10;\n                    else if (color3 === 3) compare3 = 61 <= seq3 && seq3 <= 99;\n                    else if (color3 === 4) compare3 = 101 <= seq3 && seq3 <= 139;\n                    else if (color3 === 5) compare3 = 141 <= seq3 && seq3 <= 179;\n                    else if (color3 === 6) compare3 = 181 <= seq3 && seq3 <= 219;\n\n                    return compare1 && compare2 && compare3;\n                },\n            },\n            neo_sensor_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#FFFFFF',\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_button_1, '1'],\n                            [Lang.Blocks.neo_button_2, '2'],\n                            [Lang.Blocks.neo_button_3, '3'],\n                            [Lang.Blocks.neo_button_4, '4'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_button_on, 'ON'],\n                            [Lang.Blocks.neo_button_off, 'OFF'],\n                        ],\n                        value: 'ON',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_sensor_button_pressed',\n                },\n                paramsKeyMap: {\n                    BUTTON: 0,\n                    PRESSED: 1,\n                },\n                class: 'neo_sensor',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    const button = script.getNumberField('BUTTON');\n                    const pressed = script.getStringField('PRESSED');\n                    const sensorData = Entry.hw.portData['sensor'];\n                    const value = sensorData['IR'];\n                    if (button === 1) {\n                        if (pressed === 'ON') return value === 10;\n                        else return value !== 10;\n                    } else if (button === 2) {\n                        if (pressed === 'ON') return value === 11;\n                        else return value !== 11;\n                    } else if (button === 3) {\n                        if (pressed === 'ON') return value === 12;\n                        else return value !== 12;\n                    } else if (button === 4) {\n                        if (pressed === 'ON') return value === 13;\n                        else return value !== 13;\n                    }\n                },\n            },\n            /**\n             * 버저\n             */\n            neo_buzzer_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_buzzer_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_buzzer_title',\n                },\n                class: 'neo_buzzer',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_buzzer_start: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_buzzer_octave_1, '0'],\n                            [Lang.Blocks.neo_buzzer_octave_2, '1'],\n                            [Lang.Blocks.neo_buzzer_octave_3, '2'],\n                            [Lang.Blocks.neo_buzzer_octave_4, '3'],\n                            [Lang.Blocks.neo_buzzer_octave_5, '4'],\n                            [Lang.Blocks.neo_buzzer_octave_6, '5'],\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_buzzer_do, '1'],\n                            [Lang.Blocks.neo_buzzer_do_sharp, '2'],\n                            [Lang.Blocks.neo_buzzer_re, '3'],\n                            [Lang.Blocks.neo_buzzer_re_sharp, '4'],\n                            [Lang.Blocks.neo_buzzer_mi, '5'],\n                            [Lang.Blocks.neo_buzzer_fa, '6'],\n                            [Lang.Blocks.neo_buzzer_fa_sharp, '7'],\n                            [Lang.Blocks.neo_buzzer_sol, '8'],\n                            [Lang.Blocks.neo_buzzer_sol_sharp, '9'],\n                            [Lang.Blocks.neo_buzzer_la, '10'],\n                            [Lang.Blocks.neo_buzzer_la_sharp, '11'],\n                            [Lang.Blocks.neo_buzzer_ti, '12'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_buzzer_whole_note, '1'],\n                            [Lang.Blocks.neo_buzzer_half_note, '2'],\n                            [Lang.Blocks.neo_buzzer_quarter_note, '4'],\n                            [Lang.Blocks.neo_buzzer_8th_note, '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null, null],\n                    type: 'neo_buzzer_start',\n                },\n                paramsKeyMap: {\n                    OCTAVE: 0,\n                    NOTE: 1,\n                    DURATION: 2,\n                },\n                class: 'neo_buzzer',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        const octave = script.getNumberField('OCTAVE');\n                        const note = script.getNumberField('NOTE');\n                        const value = Math.min(note + 12 * octave, 72);\n                        const duration = script.getStringValue('DURATION', script);\n                        const blockId = this.generateBlockId();\n                        this.requestCommand(blockId, NeoBlockType.BUZZER_START, [value]);\n                        script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                        setTimeout(function() {\n                            script.exec_phase = ExecPhase.STOP;\n                        }, (1 / duration) * 2000);\n                    } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                        return script;\n                    } else if (script.exec_phase === ExecPhase.STOP) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.BUZZER_STOP, []);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n\n            neo_buzzer_with_sensor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_input_1, 'IN1'],\n                            [Lang.Blocks.neo_input_2, 'IN2'],\n                            [Lang.Blocks.neo_input_3, 'IN3'],\n                        ],\n                        value: 'IN1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'neo_buzzer_with_sensor',\n                },\n                paramsKeyMap: {\n                    INPUT: 0,\n                },\n                class: 'neo_buzzer',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const input = script.getStringField('INPUT');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestExtCommand(blockId, NeoBlockType.BUZZER_WITH_SENSOR, [input]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n\n            neo_buzzer_stop: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'neo_buzzer_stop',\n                },\n                paramsKeyMap: {},\n                class: 'neo_buzzer',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_STOP;\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.BUZZER_STOP, []);\n                    } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            /**\n             * LCD\n             */\n            neo_lcd_title: {\n                color: EntryStatic.colorSet.common.TRANSPARENT,\n                fontColor: '#191970',\n                skeleton: 'basic_text',\n                skeletonOptions: {\n                    contentPos: {\n                        x: 5,\n                    },\n                },\n                params: [\n                    {\n                        type: 'Text',\n                        text: Lang.template.neo_lcd_title,\n                        color: '#191970',\n                        align: 'left',\n                    },\n                ],\n                def: {\n                    type: 'neo_lcd_title',\n                },\n                class: 'neo_lcd',\n                isNotFor: ['neo'],\n                events: {},\n            },\n            neo_lcd_image: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_lcd_image_1, '1'],\n                            [Lang.Blocks.neo_lcd_image_2, '2'],\n                            [Lang.Blocks.neo_lcd_image_3, '3'],\n                            [Lang.Blocks.neo_lcd_image_4, '4'],\n                            [Lang.Blocks.neo_lcd_image_5, '5'],\n                            [Lang.Blocks.neo_lcd_image_6, '6'],\n                            [Lang.Blocks.neo_lcd_image_7, '7'],\n                            [Lang.Blocks.neo_lcd_image_8, '8'],\n                            [Lang.Blocks.neo_lcd_image_9, '9'],\n                            [Lang.Blocks.neo_lcd_image_10, '10'],\n                            [Lang.Blocks.neo_lcd_image_11, '11'],\n                            [Lang.Blocks.neo_lcd_image_12, '12'],\n                            [Lang.Blocks.neo_lcd_image_13, '13'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'neo_lcd_image',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    IMAGE: 1,\n                },\n                class: 'neo_lcd',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const image = script.getStringField('IMAGE');\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.LCD_IMAGE, [output, image]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n\n            neo_lcd_text: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_output_1, 'OUT1'],\n                            [Lang.Blocks.neo_output_2, 'OUT2'],\n                            [Lang.Blocks.neo_output_3, 'OUT3'],\n                        ],\n                        value: 'OUT1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, '안녕', null],\n                    type: 'neo_lcd_text',\n                },\n                paramsKeyMap: {\n                    OUTPUT: 0,\n                    TEXT: 1,\n                },\n                class: 'neo_lcd',\n                isNotFor: ['neo'],\n                func: (sprite, script) => {\n                    if (!script.exec_phase) {\n                        script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                        const output = script.getStringField('OUTPUT');\n                        const text = script.getStringValue('TEXT', script);\n                        const blockId = this.generateBlockId();\n                        script.block_id = blockId;\n                        this.requestCommand(blockId, NeoBlockType.LCD_TEXT, [output, text]);\n                    } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                        if (!this.pendingResponseList[script.block_id]) {\n                            delete script.block_id;\n                            delete script.exec_phase;\n                            return script.callReturn();\n                        }\n                    }\n                    return script;\n                },\n            },\n            /**\n             * ARG Blocks\n             */\n            neo_arg_duration: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_duration_c, 'c'],\n                            [Lang.Blocks.neo_duration_0, '0'],\n                            [Lang.Blocks.neo_duration_1, '1'],\n                            [Lang.Blocks.neo_duration_2, '2'],\n                            [Lang.Blocks.neo_duration_3, '3'],\n                            [Lang.Blocks.neo_duration_4, '4'],\n                            [Lang.Blocks.neo_duration_5, '5'],\n                            [Lang.Blocks.neo_duration_6, '6'],\n                            [Lang.Blocks.neo_duration_7, '7'],\n                            [Lang.Blocks.neo_duration_8, '8'],\n                            [Lang.Blocks.neo_duration_9, '9'],\n                        ],\n                        value: 'c',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'neo_arg',\n                isNotFor: ['neo'],\n                func: function(sprite, script) {\n                    return script.getStringField('VALUE');\n                },\n            },\n            neo_arg_both_motor_speed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_motor_speed_100, '100'],\n                            [Lang.Blocks.neo_motor_speed_95, '95'],\n                            [Lang.Blocks.neo_motor_speed_90, '90'],\n                            [Lang.Blocks.neo_motor_speed_85, '85'],\n                            [Lang.Blocks.neo_motor_speed_80, '80'],\n                            [Lang.Blocks.neo_motor_speed_75, '75'],\n                            [Lang.Blocks.neo_motor_speed_70, '70'],\n                            [Lang.Blocks.neo_motor_speed_65, '65'],\n                            [Lang.Blocks.neo_motor_speed_60, '60'],\n                            [Lang.Blocks.neo_motor_speed_55, '55'],\n                            [Lang.Blocks.neo_motor_speed_50, '50'],\n                            [Lang.Blocks.neo_motor_speed_45, '45'],\n                            [Lang.Blocks.neo_motor_speed_40, '40'],\n                            [Lang.Blocks.neo_motor_speed_35, '35'],\n                            [Lang.Blocks.neo_motor_speed_30, '30'],\n                            [Lang.Blocks.neo_motor_speed_25, '25'],\n                            [Lang.Blocks.neo_motor_speed_20, '20'],\n                            [Lang.Blocks.neo_motor_speed_15, '15'],\n                            [Lang.Blocks.neo_motor_speed_10, '10'],\n                            [Lang.Blocks.neo_motor_speed_5, '5'],\n                            [Lang.Blocks.neo_motor_speed_0, '0'],\n                            [Lang.Blocks.neo_motor_speed_n5, '-5'],\n                            [Lang.Blocks.neo_motor_speed_n10, '-10'],\n                            [Lang.Blocks.neo_motor_speed_n15, '-15'],\n                            [Lang.Blocks.neo_motor_speed_n20, '-20'],\n                            [Lang.Blocks.neo_motor_speed_n25, '-25'],\n                            [Lang.Blocks.neo_motor_speed_n30, '-30'],\n                            [Lang.Blocks.neo_motor_speed_n35, '-35'],\n                            [Lang.Blocks.neo_motor_speed_n40, '-40'],\n                            [Lang.Blocks.neo_motor_speed_n45, '-45'],\n                            [Lang.Blocks.neo_motor_speed_n50, '-50'],\n                            [Lang.Blocks.neo_motor_speed_n55, '-55'],\n                            [Lang.Blocks.neo_motor_speed_n60, '-60'],\n                            [Lang.Blocks.neo_motor_speed_n65, '-65'],\n                            [Lang.Blocks.neo_motor_speed_n70, '-70'],\n                            [Lang.Blocks.neo_motor_speed_n75, '-75'],\n                            [Lang.Blocks.neo_motor_speed_n80, '-80'],\n                            [Lang.Blocks.neo_motor_speed_n85, '-85'],\n                            [Lang.Blocks.neo_motor_speed_n90, '-90'],\n                            [Lang.Blocks.neo_motor_speed_n95, '-95'],\n                            [Lang.Blocks.neo_motor_speed_n100, '-100'],\n                        ],\n                        value: '100',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'neo_arg',\n                isNotFor: ['neo'],\n                func: function(sprite, script) {\n                    return script.getStringField('VALUE');\n                },\n            },\n            neo_arg_servo_angle: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.neo_servo_angle_360, '360'],\n                            [Lang.Blocks.neo_servo_angle_350, '350'],\n                            [Lang.Blocks.neo_servo_angle_340, '340'],\n                            [Lang.Blocks.neo_servo_angle_330, '330'],\n                            [Lang.Blocks.neo_servo_angle_320, '320'],\n                            [Lang.Blocks.neo_servo_angle_310, '310'],\n                            [Lang.Blocks.neo_servo_angle_300, '300'],\n                            [Lang.Blocks.neo_servo_angle_290, '290'],\n                            [Lang.Blocks.neo_servo_angle_280, '280'],\n                            [Lang.Blocks.neo_servo_angle_270, '270'],\n                            [Lang.Blocks.neo_servo_angle_260, '260'],\n                            [Lang.Blocks.neo_servo_angle_250, '250'],\n                            [Lang.Blocks.neo_servo_angle_240, '240'],\n                            [Lang.Blocks.neo_servo_angle_230, '230'],\n                            [Lang.Blocks.neo_servo_angle_220, '220'],\n                            [Lang.Blocks.neo_servo_angle_210, '210'],\n                            [Lang.Blocks.neo_servo_angle_200, '200'],\n                            [Lang.Blocks.neo_servo_angle_190, '190'],\n                            [Lang.Blocks.neo_servo_angle_180, '180'],\n                            [Lang.Blocks.neo_servo_angle_170, '170'],\n                            [Lang.Blocks.neo_servo_angle_160, '160'],\n                            [Lang.Blocks.neo_servo_angle_150, '150'],\n                            [Lang.Blocks.neo_servo_angle_140, '140'],\n                            [Lang.Blocks.neo_servo_angle_130, '130'],\n                            [Lang.Blocks.neo_servo_angle_120, '120'],\n                            [Lang.Blocks.neo_servo_angle_110, '110'],\n                            [Lang.Blocks.neo_servo_angle_100, '100'],\n                            [Lang.Blocks.neo_servo_angle_90, '90'],\n                            [Lang.Blocks.neo_servo_angle_80, '80'],\n                            [Lang.Blocks.neo_servo_angle_70, '70'],\n                            [Lang.Blocks.neo_servo_angle_60, '60'],\n                            [Lang.Blocks.neo_servo_angle_50, '50'],\n                            [Lang.Blocks.neo_servo_angle_40, '40'],\n                            [Lang.Blocks.neo_servo_angle_30, '30'],\n                            [Lang.Blocks.neo_servo_angle_20, '20'],\n                            [Lang.Blocks.neo_servo_angle_10, '10'],\n                            [Lang.Blocks.neo_servo_angle_0, '0'],\n                            [Lang.Blocks.neo_servo_angle_n10, '-10'],\n                            [Lang.Blocks.neo_servo_angle_n20, '-20'],\n                            [Lang.Blocks.neo_servo_angle_n30, '-30'],\n                            [Lang.Blocks.neo_servo_angle_n40, '-40'],\n                            [Lang.Blocks.neo_servo_angle_n50, '-50'],\n                            [Lang.Blocks.neo_servo_angle_n60, '-60'],\n                            [Lang.Blocks.neo_servo_angle_n70, '-70'],\n                            [Lang.Blocks.neo_servo_angle_n80, '-80'],\n                            [Lang.Blocks.neo_servo_angle_n90, '-90'],\n                            [Lang.Blocks.neo_servo_angle_n100, '-100'],\n                            [Lang.Blocks.neo_servo_angle_n110, '-110'],\n                            [Lang.Blocks.neo_servo_angle_n120, '-120'],\n                            [Lang.Blocks.neo_servo_angle_n130, '-130'],\n                            [Lang.Blocks.neo_servo_angle_n140, '-140'],\n                            [Lang.Blocks.neo_servo_angle_n150, '-150'],\n                            [Lang.Blocks.neo_servo_angle_n160, '-160'],\n                            [Lang.Blocks.neo_servo_angle_n170, '-170'],\n                            [Lang.Blocks.neo_servo_angle_n180, '-180'],\n                            [Lang.Blocks.neo_servo_angle_n190, '-190'],\n                            [Lang.Blocks.neo_servo_angle_n200, '-200'],\n                            [Lang.Blocks.neo_servo_angle_n210, '-210'],\n                            [Lang.Blocks.neo_servo_angle_n220, '-220'],\n                            [Lang.Blocks.neo_servo_angle_n230, '-230'],\n                            [Lang.Blocks.neo_servo_angle_n240, '-240'],\n                            [Lang.Blocks.neo_servo_angle_n250, '-250'],\n                            [Lang.Blocks.neo_servo_angle_n260, '-260'],\n                            [Lang.Blocks.neo_servo_angle_n270, '-270'],\n                            [Lang.Blocks.neo_servo_angle_n280, '-280'],\n                            [Lang.Blocks.neo_servo_angle_n290, '-290'],\n                            [Lang.Blocks.neo_servo_angle_n300, '-300'],\n                            [Lang.Blocks.neo_servo_angle_n310, '-310'],\n                            [Lang.Blocks.neo_servo_angle_n320, '-320'],\n                            [Lang.Blocks.neo_servo_angle_n330, '-330'],\n                            [Lang.Blocks.neo_servo_angle_n340, '-340'],\n                            [Lang.Blocks.neo_servo_angle_n350, '-350'],\n                            [Lang.Blocks.neo_servo_angle_n360, '-360'],\n                        ],\n                        value: '100',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                class: 'neo_arg',\n                isNotFor: ['neo'],\n                func: function(sprite, script) {\n                    return script.getStringField('VALUE');\n                },\n            },\n        };\n    }\n\n    getCheckSum(command) {\n        let checkSum = 0;\n        for (let i = 0; i < command.length; i++) {\n            checkSum += command[i];\n        }\n        return checkSum & 255;\n    }\n\n    getUnitId(port) {\n        switch (port) {\n            case 'OUT1':\n                return UnitId.CONTROLLER_OUT1;\n            case 'OUT2':\n                return UnitId.CONTROLLER_OUT2;\n            case 'OUT3':\n                return UnitId.CONTROLLER_OUT3;\n            case 'OUT12':\n                return UnitId.CONTROLLER_OUT12;\n            case 'OUT123':\n                return UnitId.CONTROLLER_OUT_ALL;\n            case 'IN1':\n                return UnitId.CONTROLLER_IN1;\n            case 'IN2':\n                return UnitId.CONTROLLER_IN2;\n            case 'IN3':\n                return UnitId.CONTROLLER_IN3;\n        }\n        return UnitId.CONTROLLER;\n    }\n\n    makePdu(command) {\n        const pdu = [];\n        pdu.push(...HEADER);\n        pdu.push(command.length);\n        pdu.push(...command);\n        pdu.push(this.getCheckSum(command));\n        return pdu;\n    }\n\n    requestCommand(blockId, type, params) {\n        // console.log(blockId + ' requested');\n        if (this.pendingResponseList[blockId]) {\n            delete this.pendingResponseList[blockId];\n        }\n        this.pendingResponseList[blockId] = 'executed';\n        const command = this.makeCommand(blockId, type, params);\n        if (!command) return;\n        const pdu = this.makePdu(command);\n        this.executeList[blockId] = {\n            blockId,\n            pdu,\n        };\n        Entry.hw.sendQueue.executeList = { ...this.executeList };\n        Entry.hw.update();\n    }\n\n    requestExt2Command(blockId, type, params) {\n        // console.log(blockId + ' requested');\n        if (this.pendingResponseList[blockId]) {\n            delete this.pendingResponseList[blockId];\n        }\n        this.pendingResponseList[blockId] = 'executed';\n        const command = this.makeCommandExt2(blockId, type, params);\n        if (!command) return;\n        const pdu = this.makePdu(command);\n        this.executeList[blockId] = {\n            blockId,\n            pdu,\n        };\n        Entry.hw.sendQueue.executeList = { ...this.executeList };\n        Entry.hw.update();\n    }\n\n    requestExtCommand(blockId, type, params) {\n        // console.log(blockId + ' requested');\n        if (this.pendingResponseList[blockId]) {\n            delete this.pendingResponseList[blockId];\n        }\n        this.pendingResponseList[blockId] = 'executed';\n        const command = this.makeCommandExt(blockId, type, params);\n        if (!command) return;\n        const pdu = this.makePdu(command);\n        this.executeList[blockId] = {\n            blockId,\n            pdu,\n        };\n        Entry.hw.sendQueue.executeList = { ...this.executeList };\n        Entry.hw.update();\n    }\n\n    makeCommand(blockId, type, params) {\n        //const body = [FrameCode.BASIC, PduCode.ACTION_COMMAND, PduType.REQUEST];\n        const body = [FrameCode.BASIC, PduCode.BASIC, blockId];\n        if (type === NeoBlockType.MOTOR_MOVE) {\n            const which = params[0];\n            const speed = Math.abs(params[1]);\n            const direction = params[1] < 0 ? 1 : 0;\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR);\n            const data = Buffer.from([0, 0, 0, 0, 0, 0]);\n            data.writeInt16LE(speed, 0);\n            data.writeInt16LE(which, 2);\n            data.writeInt16LE(direction, 4);\n            body.push(...data);\n        } else if (type === NeoBlockType.MOTOR_MOVE_BOTH) {\n            const speedL = params[0];\n            const speedR = params[1];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR_BOTH);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(speedL, 0);\n            data.writeInt16LE(speedR, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.ROBOT_MOVE) {\n            const robotCommand = params[0];\n            const speed = params[1];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(speed, 0);\n            data.writeInt16LE(robotCommand, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.MOTOR_STOP || type === NeoBlockType.AUTO_DRIVING_STOP) {\n            const which = params[0];\n            const direction = 1;\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR);\n            const data = Buffer.from([0, 0, 0, 0, 0, 0]);\n            data.writeInt16LE(which, 2);\n            data.writeInt16LE(direction, 4);\n            body.push(...data);\n        } else if (type === NeoBlockType.ROBOT_STOP) {\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT);\n            const data = Buffer.from([0, 0, 0, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.SERVO_RESET) {\n            const output = params[0];\n            body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.RESET);\n            const data = Buffer.from([0, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.SERVO_ANGLE) {\n            const output = params[0];\n            const angle = params[1];\n            const speed = params[2];\n            body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.ANGLE);\n            const data = Buffer.from([0, 0, 0, 0, 1, 0]);\n            data.writeInt16LE(angle, 0);\n            data.writeInt16LE(speed, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.SERVO_ANGLE_WAIT) {\n            const output = params[0];\n            const angle = params[1];\n            const speed = params[2];\n\n            body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.ANGLE_WAIT);\n            const data = Buffer.from([0, 0, 0, 0, 1, 0]);\n            data.writeInt16LE(angle, 0);\n            data.writeInt16LE(speed, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.SERVO_ROTATE) {\n            const output = params[0];\n            const direction = params[1];\n            const speed = params[2];\n            body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.ROTATE);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(speed, 0);\n            data.writeInt16LE(direction, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.SERVO_STOP) {\n            const output = params[0];\n            body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.STOP);\n        } else if (\n          type === NeoBlockType.LINE_TRACER_START ||\n          type === NeoBlockType.AUTO_DRIVING_START ||\n          type === NeoBlockType.AUTO_DETECT_WALL_START\n        ) {\n            const speed = params[0];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT);\n            const data = Buffer.from([0, 0, 0x10, 0]);\n            data.writeInt16LE(speed, 0);\n            body.push(...data);\n        } else if (type === NeoBlockType.AUTO_DRIVING_SENSOR_START) {\n            const sensor = params[0];\n            const speed = params[1];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(speed, 0);\n            data.writeInt16LE(sensor, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.LINE_CROSS_MOVE) {\n            const count = params[0];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.LINE_TRACER);\n            const data = Buffer.from([0, 0]);\n            data.writeInt16LE(count, 0);\n            body.push(...data);\n        } else if (type === NeoBlockType.LINE_CROSS_TURN) {\n            const direction = params[0];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.LINE_TRACER);\n            const data = Buffer.from([0, 0]);\n            data.writeInt16LE(direction, 0);\n            body.push(...data);\n        } else if (type === NeoBlockType.AUTO_PARKING_START) {\n            // TODO : which 누락\n            const which = params[0];\n            const direction = params[1];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.AUTO_PARKING);\n            const data = Buffer.from([0, 0]);\n            data.writeInt16LE(direction, 0);\n            body.push(...data);\n        } else if (type === NeoBlockType.LINE_CHANGE_START) {\n            const direction = params[0];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.AUTO_DRIVING);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(60, 0);\n            data.writeInt16LE(direction, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.LINE_CHANGE_TURN) {\n            const direction = params[0];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.AUTO_DRIVING);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(60, 0);\n            data.writeInt16LE(direction, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.AUTO_DETECT_WALL_TURN) {\n            const direction = params[0];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.AUTO_DETECT_WALL);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(60, 0);\n            data.writeInt16LE(direction, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.LED_ON) {\n            const output = params[0];\n            const brightness = params[1];\n            body.push(this.getUnitId(output), ActorKind.LED, 0);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(brightness, 0);\n            body.push(...data);\n        } else if (type === NeoBlockType.LED_BLINK) {\n            const output = params[0];\n            const speed = params[1];\n            const brightness = params[2];\n            body.push(this.getUnitId(output), ActorKind.LED, 0);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(brightness, 0);\n            data.writeInt16LE(speed, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.LED_OFF) {\n            const output = params[0];\n            body.push(this.getUnitId(output), ActorKind.LED, 0);\n            const data = Buffer.from([0, 0, 0, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.COLOR_LED_ON) {\n            const output = params[0];\n            body.push(this.getUnitId(output), ActorKind.COLOR_LED, LedCommand.ON);\n            const data = Buffer.from([0, 0, 0, 0, 0, 0]);\n            const color = params[1];\n            if (color.length === 7 && color[0] === '#') {\n                const r = color.substr(1, 2);\n                const g = color.substr(3, 2);\n                const b = color.substr(5, 2);\n                data.writeInt16LE(parseInt(r, 16), 0);\n                data.writeInt16LE(parseInt(g, 16), 2);\n                data.writeInt16LE(parseInt(b, 16), 4);\n            }\n            body.push(...data);\n        } else if (type === NeoBlockType.COLOR_LED_OFF) {\n            const output = params[0];\n            body.push(this.getUnitId(output), ActorKind.COLOR_LED, LedCommand.OFF);\n        } else if (type === NeoBlockType.SET_OUTPUT) {\n            const output = params[0];\n            const value = params[1];\n            body.push(this.getUnitId(output), ActorKind.LED, 0);\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(value, 0);\n            body.push(...data);\n        } else if (type === NeoBlockType.BUZZER_START) {\n            const value = params[0];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.BUZZER);\n            const data = Buffer.from([0, 0]);\n            data.writeInt16LE(value, 0);\n            body.push(...data);\n        } else if (type === NeoBlockType.BUZZER_STOP) {\n            const value = params[0];\n            body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.BUZZER);\n            const data = Buffer.from([0, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.LCD_IMAGE) {\n            const output = this.getUnitId(params[0]);\n            const value = params[1];\n            body.push(output, ActorKind.LCD, LcdCommand.IMAGE);\n            const data = Buffer.from([value, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.LCD_TEXT) {\n            const output = this.getUnitId(params[0]);\n            const value = params[1];\n            body.push(output, ActorKind.LCD, LcdCommand.TEXT);\n            body.push(0); // 글씨크기 : 지금 안됨.\n            if (value.length > 0) {\n                for (let idx = 0; idx < value.length; idx++) {\n                    body.push(value.charCodeAt(idx));\n                }\n            }\n        }\n        return body;\n    }\n\n    makeCommandExt(blockId, type, params) {\n        const body = [FrameCode.BASIC];\n        if (type === NeoBlockType.MOTOR_MOVE) {\n            const which = params[0];\n            const unitId = this.getUnitId(params[1]);\n            body.push(\n              PduCode.EXTEND_1,\n              blockId,\n              UnitId.CONTROLLER,\n              ActorKind.CONTROLLER,\n              ControllerCommand.MOTOR\n            );\n            const data = Buffer.from([unitId, 0, which, 0, 0, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.ROBOT_MOVE) {\n            const robotCommand = params[0];\n            const unitId = this.getUnitId(params[1]);\n            body.push(\n              PduCode.EXTEND_1,\n              blockId,\n              UnitId.CONTROLLER,\n              ActorKind.CONTROLLER,\n              ControllerCommand.ROBOT\n            );\n            const data = Buffer.from([unitId, 0, 0, 0]);\n            data.writeInt16LE(robotCommand, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.SERVO_ANGLE || type === NeoBlockType.SERVO_ANGLE_WAIT) {\n            const unitId = this.getUnitId(params[0]);\n            let angle = params[1];\n            let speed = params[2];\n            if (angle.indexOf('IN') >= 0) angle = this.getUnitId(angle);\n            body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.SERVO, ServoCommand.ANGLE);\n            const data = Buffer.from([angle, 0, 0, 0, 1, 0]);\n            data.writeInt16LE(speed, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.SERVO_ROTATE) {\n            const unitId = this.getUnitId(params[0]);\n            const direction = params[1];\n            const inUnitId = this.getUnitId(params[2]);\n            body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.SERVO, ServoCommand.ROTATE);\n            const data = Buffer.from([inUnitId, 0, 0, 0]);\n            data.writeInt16LE(direction, 2);\n            body.push(...data);\n        } else if (\n          type === NeoBlockType.LINE_TRACER_START ||\n          type === NeoBlockType.AUTO_DRIVING_START ||\n          type === NeoBlockType.AUTO_DETECT_WALL_START\n        ) {\n            const unitId = this.getUnitId(params[0]);\n            body.push(\n              PduCode.EXTEND_1,\n              blockId,\n              UnitId.CONTROLLER,\n              ActorKind.CONTROLLER,\n              ControllerCommand.ROBOT\n            );\n            const data = Buffer.from([unitId, 0, 0x10, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.AUTO_DRIVING_SENSOR_START) {\n            const sensor = params[0];\n            const unitId = this.getUnitId(params[1]);\n            body.push(\n              PduCode.EXTEND_1,\n              blockId,\n              UnitId.CONTROLLER,\n              ActorKind.CONTROLLER,\n              ControllerCommand.ROBOT\n            );\n            const data = Buffer.from([0, 0, 0, 0]);\n            data.writeInt16LE(unitId, 0);\n            data.writeInt16LE(sensor, 2);\n            body.push(...data);\n        } else if (type === NeoBlockType.LED_ON) {\n            const unitId = this.getUnitId(params[0]);\n            const inUnitId = this.getUnitId(params[1]);\n            body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.LED, 0);\n            const data = Buffer.from([inUnitId, 0, 0, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.SET_OUTPUT) {\n            const unitId = this.getUnitId(params[0]);\n            const inUnitId = this.getUnitId(params[1]);\n            body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.LED, 0);\n            const data = Buffer.from([inUnitId, 0, 0, 0]);\n            body.push(...data);\n        } else if (type === NeoBlockType.BUZZER_WITH_SENSOR) {\n            const sensorUnitId = this.getUnitId(params[0]);\n            body.push(\n              PduCode.EXTEND_1,\n              blockId,\n              UnitId.CONTROLLER,\n              ActorKind.CONTROLLER,\n              ControllerCommand.BUZZER\n            );\n            const data = Buffer.from([0, 0]);\n            data.writeInt16LE(sensorUnitId, 0);\n            body.push(...data);\n        } else if (type === NeoBlockType.COLOR_LED_ON_SENSOR) {\n            const outUnitId = this.getUnitId(params[0]);\n            const inUnitId = this.getUnitId(params[1]);\n            body.push(PduCode.EXTEND_3, blockId, outUnitId, ActorKind.COLOR_LED, LedCommand.ON);\n            const data = Buffer.from([inUnitId, 1, inUnitId, 2, inUnitId, 3]);\n            body.push(...data);\n        }\n        return body;\n    }\n\n    makeCommandExt2(blockId, type, params) {\n        const body = [FrameCode.BASIC];\n        if (type === NeoBlockType.SERVO_ANGLE || type === NeoBlockType.SERVO_ANGLE_WAIT) {\n            const unitId = this.getUnitId(params[0]);\n            const angleInUnitId = this.getUnitId(params[1]);\n            const speedInUnitId = this.getUnitId(params[2]);\n            body.push(PduCode.EXTEND_2, blockId, unitId, ActorKind.SERVO, ServoCommand.ANGLE);\n            const data = Buffer.from([angleInUnitId, 0, speedInUnitId, 0, 1, 0]);\n            body.push(...data);\n        }\n        return body;\n    }\n    /*\n      후면주차 실행 (pending response 하지 않고 바로 다음 단계로 넘어감 : phase 가 너무 많아서 간소화)\n      주석은 왼쪽 기준으로 오른쪽에서는 좌우만 바꿔준다.\n     */\n    async runAutoParking(script) {\n        const type = script.getNumberValue('DIRECTION', script);\n        const side = script.getNumberValue('WHICH', script);\n        let which = 0;\n        if (type === 1) {\n            // 후면주차\n            this.requestCommand(this.generateBlockId(), NeoBlockType.LINE_TRACER_START, [40]);\n            await Entry.Utils.sleep(2400);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            which = side === 1 ? 1 : 2;\n            this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, 30]);\n            await Entry.Utils.sleep(2000);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_MOVE, [2, 25]);\n            await Entry.Utils.sleep(2500);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            which = side === 1 ? 2 : 1;\n            this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, -30]);\n            await Entry.Utils.sleep(1300);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_MOVE, [2, 25]);\n            await Entry.Utils.sleep(1700);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n        } else {\n            // 평행주차\n            this.requestCommand(this.generateBlockId(), NeoBlockType.LINE_TRACER_START, [40]);\n            await Entry.Utils.sleep(3000);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            which = side === 1 ? 1 : 2;\n            this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, 30]);\n            await Entry.Utils.sleep(2000);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_MOVE, [2, 30]);\n            await Entry.Utils.sleep(3000);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            which = side === 1 ? 1 : 2;\n            this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, -30]);\n            await Entry.Utils.sleep(1000);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            which = side === 1 ? 2 : 1;\n            this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, 25]);\n            await Entry.Utils.sleep(1000);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_MOVE, [2, 20]);\n            await Entry.Utils.sleep(1000);\n            this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n        }\n        return script.callReturn();\n    }\n})();\n\nmodule.exports = Entry.Neo;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neo_cannon.js",
    "content": "'use strict';\n\nEntry.NeoCannon = {\n    id: '41.2',\n    name: 'NeoCannon',\n    url: 'https://blog.naver.com/PostView.naver?blogId=neo3ds&logNo=223071491275',\n    imageName: 'neo_cannon.png',\n    title: {\n        ko: '네오캐논',\n        en: 'NeoCannon',\n    },\n    PORT_MAP: {\n        mode: 1,\n        life: 0,\n        tone: 0,\n        motorState: 0,\n        led: 0,\n        shootState: 0,\n        d9: 0,\n        d10: 0,\n        angleState: 0,\n        neopixel: 0,\n    },\n    setZero() {\n        let portMap = Entry.NeoCannon.PORT_MAP;\n        let sq = Entry.hw.sendQueue;\n        for (let port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n    },\n    toneTable: {\n        0: 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        4: [39, 78, 156, 310, 622, 1245, 2637, 4978],\n        5: [41, 82, 165, 330, 659, 1319, 2794, 5274],\n        6: [44, 87, 175, 349, 698, 1397, 2849, 5588],\n        7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neo_cannon.png',\n        width: 400,\n        height: 400,\n        listPorts: {\n            vibe: {\n                name: '진동센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n    BlockState: {},\n};\n\nEntry.NeoCannon.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                neo_cannon_get_vibe_value: '진동 센서 감지됨',\n                neo_cannon_set_tone: '부저를 %1 %2 음으로 %3 초 연주하기 %4',\n                neo_cannon_motor_state: '%1 이동하기 %2',\n                neo_cannon_motor_state_secs: '%1 %2 초 이동하기 %3',\n                neo_cannon_motor_stop: '정지하기 %1',\n                neo_cannon_shoot_reload: '%1 초 장전하기 %2',\n                neo_cannon_shoot_catch: '장전 풀림 방지 %1',\n                neo_cannon_shoot_shooting: '발사하기 %1',\n                neo_cannon_angle_state: '각도 %1 %2 초 이동하기 %3',\n                neo_cannon_rgb_led_select_state: '%1 %2 %3',\n                neo_cannon_rgb_led_select_pwm: '%1 %2 세기로 켜기 %3',\n                neo_cannon_rgb_led_color_picker: 'RGB LED %1 %2',\n                neo_cannon_rgb_led_pwm: 'RGB LED 빨강 %1 초록 %2 파랑 %3 %4',\n                neo_cannon_rgb_led_off: 'RGB LED 끄기 %1',\n                neo_cannon_neopixel_color_picker: 'Neopixel %1번  %2 (으)로 켜기 %3',\n                neo_cannon_neopixel: 'Neopixel %1번  빨 %2 녹 %3 파 %4 (으)로 켜기 %5',\n                neo_cannon_neopixel_color_picker_all_on: 'Neopixel 전체 %1 (으)로 켜기 %2',\n                neo_cannon_neopixel_all_on: 'Neopixel 전체  빨 %1 녹 %2 파 %3 (으)로 켜기 %4',\n                neo_cannon_neopixel_all_off: 'Neopixel 전체 끄기 %1',\n            },\n\n            Helper: {\n                neo_cannon_get_vibe_value:\n                    '진동 감지 여부를 가져옵니다.<br/><font color=\"crimson\">센서값 0: `감지 못함`, 1: `감지됨`</font>',\n                neo_cannon_set_tone:\n                    '부저를 통해 선택한 옥타브 음계를 통해 해당 시간만큼 소리를 냅니다.<br/><font color=\"crimson\">(참고, 다음 블럭이 있을경우에 부저 연주시간이 끝난 후에 다음 블럭을 실행합니다.)</font>',\n                neo_cannon_motor_state: '네오캐논을 앞, 왼쪽, 오른쪽, 뒤로 이동시킬 수 있습니다.',\n                neo_cannon_motor_state_secs:\n                    '네오캐논을 앞, 왼쪽, 오른쪽, 뒤로 정해진 시간(초)만큼 이동시킬 수 있습니다.',\n                neo_cannon_motor_stop: '네오캐논 이동을 정지합니다.',\n                neo_cannon_shoot_reload: '장전 모터를 정해진 시간(초)만큼 장전합니다.',\n                neo_cannon_shoot_catch:\n                    '장전 모터가 풀리는 것을 방지해주기 위해 일정 세기로 잡아줍니다.',\n                neo_cannon_shoot_shooting: '장전 모터를 풀어서 발사합니다.',\n                neo_cannon_angle_state:\n                    '각도 모터를 제어하여 위, 아래로 정해진 시간(초)만큼 이동합니다.',\n                neo_cannon_rgb_led_select_state:\n                    'RGB LED 중 빨강, 초록, 파랑을 선택하여 ON/OFF를 제어합니다.<br/><font color=\"crimson\">(주의, LED모드로 진행해주세요.)</font>',\n                neo_cannon_rgb_led_select_pwm:\n                    'RGB LED 중 빨강, 초록, 파랑을 선택하여 세기값(0~255)을 주어 원하는 색상을 나타낼 수 있습니다.<br/><font color=\"crimson\">(주의, LED모드로 진행해주세요.)</font>',\n                neo_cannon_rgb_led_color_picker:\n                    'RGB LED를 색을 선택하여 원하는 색상을 나타낼 수 있습니다.<br/><font color=\"crimson\">(주의, LED모드로 진행해주세요.)</font>',\n                neo_cannon_rgb_led_pwm:\n                    'RGB LED에 세기값(0~255)을 주어 원하는 색상을 나타낼 수 있습니다.<br/><font color=\"crimson\">(주의, LED모드로 진행해주세요.)</font>',\n                neo_cannon_rgb_led_off: 'RGB LED를 끌 수 있습니다.',\n                neo_cannon_neopixel_color_picker:\n                    '색을 보고 RGB색상을 정하여 정해진 네오픽셀를 켤 수 있습니다.<br/><font color=\"crimson\">(참고, 네오픽셀번호는 0번부터 17번까지 입니다.)</font>',\n                neo_cannon_neopixel:\n                    '정해준 네오픽셀 번호에 빨강, 파랑, 초록의 색을 넣고 조합하여 네오픽셀를 켤 수 있습니다.<br/><font color=\"crimson\">(참고, 네오픽셀번호는 0번부터 17번까지 입니다.)</font>',\n                neo_cannon_neopixel_color_picker_all_on:\n                    '색을 보고 RGB색상을 정하여 모든 네오픽셀를 켤 수 있습니다.',\n                neo_cannon_neopixel_all_on:\n                    '빨강, 파랑, 초록의 색을 넣고 조합하여 모든 네오픽셀를 켤 수 있습니다.',\n                neo_cannon_neopixel_all_off: '모든 네오픽셀를 끌 수 있습니다.',\n            },\n        },\n        en: {\n            template: {\n                neo_cannon_get_vibe_value: 'Detected Vibe Sensor',\n                neo_cannon_set_tone: 'Play tone note %1 octave %2 beat %3 %4',\n                neo_cannon_motor_state: 'Move %1 %2',\n                neo_cannon_motor_state_secs: 'Move %1 %2 secs %3',\n                neo_cannon_motor_stop: 'Move Stop %1',\n                neo_cannon_shoot_reload: 'Reload %1 secs %2',\n                neo_cannon_shoot_catch: 'Anti-shoot %1',\n                neo_cannon_shoot_shooting: 'Shoot %1',\n                neo_cannon_angle_state: 'Move Angle %1 %2 secs %3',\n                neo_cannon_rgb_led_select_state: '%1 color %2 %3',\n                neo_cannon_rgb_led_select_pwm: '%1 color %2 turn on pwm %3',\n                neo_cannon_rgb_led_color_picker: 'RGB LED %1 %2',\n                neo_cannon_rgb_led_pwm: 'RGB LED R %1 G %2 B %3 %4',\n                neo_cannon_rgb_led_off: 'RGB LED OFF',\n                neo_cannon_neopixel_color_picker: 'Neopixel number %1 turn on %2 %3',\n                neo_cannon_neopixel: 'Neopixel number %1 turn on R %2 G %3 B %4 %5',\n                neo_cannon_neopixel_color_picker_all_on: 'All Neopixel turn on %1 %2',\n                neo_cannon_neopixel_all_on: 'All Neopixel turn on R %1 G %2 B %3 %4',\n                neo_cannon_neopixel_all_off: 'All Neopixel turn off %1',\n            },\n        },\n    };\n};\n\nEntry.NeoCannon.blockMenuBlocks = [\n    'neo_cannon_get_vibe_value',\n    'neo_cannon_set_tone',\n    'neo_cannon_motor_state',\n    'neo_cannon_motor_state_secs',\n    'neo_cannon_motor_stop',\n    'neo_cannon_shoot_reload',\n    'neo_cannon_shoot_catch',\n    'neo_cannon_shoot_shooting',\n    'neo_cannon_angle_state',\n    'neo_cannon_rgb_led_select_state',\n    'neo_cannon_rgb_led_select_pwm',\n    'neo_cannon_rgb_led_color_picker',\n    'neo_cannon_rgb_led_pwm',\n    'neo_cannon_rgb_led_off',\n    'neo_cannon_neopixel_color_picker',\n    'neo_cannon_neopixel',\n    'neo_cannon_neopixel_color_picker_all_on',\n    'neo_cannon_neopixel_all_on',\n    'neo_cannon_neopixel_all_off',\n];\n\nEntry.NeoCannon.getBlocks = function () {\n    return {\n        neo_cannon_get_vibe_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'neo_cannon_get_vibe_value',\n            },\n            paramsKeyMap: {},\n            class: 'NeoCannonGet',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                let port = 'vibe';\n\n                return Entry.hw.portData[port] || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.getVibe()',\n                        blockType: 'param',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_cannon_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'neo_cannon_tone_list',\n                    },\n                ],\n            },\n        },\n        neo_cannon_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neo_cannon_tone_list',\n                    },\n                ],\n                type: 'neo_cannon_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'neo_cannon_tone_value',\n                    },\n                ],\n            },\n        },\n        neo_cannon_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'neo_cannon_octave_list',\n                    },\n                ],\n            },\n        },\n        neo_cannon_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neo_cannon_tone_list',\n                    },\n                    {\n                        type: 'neo_cannon_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'neo_cannon_set_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'NeoCannon',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.NeoCannon.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.tone) {\n                        sq.tone = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.tone = {\n                            type: Entry.NeoCannon.PORT_MAP.tone,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.NeoCannon.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.tone = {\n                        type: Entry.NeoCannon.PORT_MAP.tone,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.tone = {\n                        type: Entry.NeoCannon.PORT_MAP.tone,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.tone(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_motor_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', 1],\n                        ['왼쪽으로', 2],\n                        ['오른쪽으로', 3],\n                        ['뒤로', 4],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neo_cannon_motor_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'NeoCannon',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let state = script.getNumberValue('STATE', script);\n\n                if (!sq.motorState) {\n                    sq.motorState = {};\n                }\n\n                sq.motorState = state;\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.motorState(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['앞으로', '1'],\n                                    ['왼쪽으로', '2'],\n                                    ['오른쪽으로', '3'],\n                                    ['뒤로', '4'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_motor_state_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', 1],\n                        ['왼쪽으로', 2],\n                        ['오른쪽으로', 3],\n                        ['뒤로', 4],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'neo_cannon_motor_state_secs',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n                DURATION: 1,\n            },\n            class: 'NeoCannon',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    let state = script.getNumberValue('STATE', script);\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration <= 0) {\n                        duration = 0;\n                        state = 0;\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (!sq.motorState) {\n                        sq.motorState = {};\n                    }\n\n                    sq.motorState = state;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.motorState = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.motorStateSecs(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['앞으로', '1'],\n                                    ['왼쪽으로', '2'],\n                                    ['오른쪽으로', '3'],\n                                    ['뒤로', '4'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neo_cannon_motor_stop',\n            },\n            paramsKeyMap: {},\n            class: 'NeoCannon',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                if (!sq.motorState) {\n                    sq.motorState = {};\n                }\n                sq.motorState = 0;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.motorStop()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_cannon_shoot_reload: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'neo_cannon_shoot_reload',\n            },\n            paramsKeyMap: {\n                DURATION: 0,\n            },\n            class: 'NeoCannon',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration <= 0) {\n                        duration = 0;\n                        state = 0;\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (!sq.shootState) {\n                        sq.shootState = {};\n                    }\n                    if (!sq.d9) {\n                        sq.d9 = {};\n                    }\n                    if (!sq.d10) {\n                        sq.d10 = {};\n                    }\n\n                    sq.shootState = 1;\n                    sq.d9 = 200;\n                    sq.d10 = 0;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.shootState = 0;\n                    sq.d9 = 0;\n                    sq.d10 = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.reload(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_shoot_catch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neo_cannon_shoot_catch',\n            },\n            paramsKeyMap: {},\n            class: 'NeoCannon',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                if (!sq.shootState) {\n                    sq.shootState = {};\n                }\n                if (!sq.d9) {\n                    sq.d9 = {};\n                }\n                if (!sq.d10) {\n                    sq.d10 = {};\n                }\n                sq.shootState = 3;\n                sq.d9 = 80;\n                sq.d10 = 0;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.shootCatch()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_cannon_shoot_shooting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neo_cannon_shoot_shooting',\n            },\n            paramsKeyMap: {},\n            class: 'NeoCannon',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    let duration = 40;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (!sq.shootState) {\n                        sq.shootState = {};\n                    }\n                    if (!sq.d9) {\n                        sq.d9 = {};\n                    }\n                    if (!sq.d10) {\n                        sq.d10 = {};\n                    }\n\n                    sq.shootState = 2;\n                    sq.d9 = 0;\n                    sq.d10 = 200;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    sq.shootState = 0;\n                    sq.d9 = 0;\n                    sq.d10 = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.shooting()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_cannon_angle_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['UP', '1'],\n                        ['DOWN', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0.1'],\n                    },\n                ],\n                type: 'neo_cannon_angle_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n                DURATION: 1,\n            },\n            class: 'NeoCannon',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                if (!script.isStart) {\n                    let state = script.getNumberValue('STATE', script);\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration <= 0) {\n                        duration = 0;\n                        state = 0;\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (!sq.angleState) {\n                        sq.angleState = {};\n                    }\n\n                    sq.angleState = state;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.angleState = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.angleState(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['UP', '1'],\n                                    ['DOWN', '2'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueLowerCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_rgb_led_select_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['BLUE', '0'],\n                        ['RED', '1'],\n                        ['GREEN', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OFF', '0'],\n                        ['ON', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neo_cannon_rgb_led_select_state',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                STATE: 1,\n            },\n            class: 'NeoCannonRGB',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let color = script.getNumberValue('COLOR', script);\n                let state = script.getNumberValue('STATE', script);\n\n                let power = state == 1 ? 255 : 0;\n\n                if (color == 0) {\n                    if (!sq.led) {\n                        sq.led = {};\n                    }\n                    sq.led = power;\n                } else if (color == 1) {\n                    if (!sq.shootState) {\n                        sq.shootState = {};\n                    }\n                    if (!sq.d9) {\n                        sq.d9 = {};\n                    }\n                    sq.shootState = 4;\n                    sq.d9 = power;\n                } else if (color == 2) {\n                    if (!sq.shootState) {\n                        sq.shootState = {};\n                    }\n                    if (!sq.d10) {\n                        sq.d10 = {};\n                    }\n                    sq.shootState = 4;\n                    sq.d10 = power;\n                }\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.rgbLedSelectState(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['BLUE', '0'],\n                                    ['RED', '1'],\n                                    ['GREEN', '2'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['ON', '1'],\n                                    ['OFF', '0'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_rgb_led_select_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['BLUE', '0'],\n                        ['RED', '1'],\n                        ['GREEN', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neo_cannon_rgb_led_select_pwm',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                POWER: 1,\n            },\n            class: 'NeoCannonRGB',\n            isNotFor: ['NeoCannon'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let color = script.getNumberValue('COLOR', script);\n                let power = script.getNumberValue('POWER', script);\n\n                if (color == 0) {\n                    if (!sq.led) {\n                        sq.led = {};\n                    }\n                    sq.led = power;\n                } else if (color == 1) {\n                    if (!sq.shootState) {\n                        sq.shootState = {};\n                    }\n                    if (!sq.d9) {\n                        sq.d9 = {};\n                    }\n                    sq.shootState = 4;\n                    sq.d9 = power;\n                } else if (color == 2) {\n                    if (!sq.shootState) {\n                        sq.shootState = {};\n                    }\n                    if (!sq.d10) {\n                        sq.d10 = {};\n                    }\n                    sq.shootState = 4;\n                    sq.d10 = power;\n                }\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.rgbLedSelectPwm(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['BLUE', '0'],\n                                    ['RED', '1'],\n                                    ['GREEN', '2'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_rgb_led_color_picker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['#0000FF', null],\n                type: 'neo_cannon_rgb_led_color_picker',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'NeoCannonRGB',\n            isNotFor: ['NeoCannon'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                let value = script.getStringField('COLOR');\n\n                if (!sq.shootState) {\n                    sq.shootState = {};\n                }\n\n                if (!sq.led) {\n                    sq.led = {};\n                }\n                if (!sq.d9) {\n                    sq.d9 = {};\n                }\n                if (!sq.d10) {\n                    sq.d10 = {};\n                }\n\n                let red = parseInt(value.substr(1, 2), 16);\n                let green = parseInt(value.substr(3, 2), 16);\n                let blue = parseInt(value.substr(5, 2), 16);\n\n                sq.shootState = 4;\n                sq.led = blue;\n                sq.d9 = red;\n                sq.d10 = green;\n\n                Entry.hw.update();\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.rgbLedColorPicker(%1)',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_rgb_led_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'neo_cannon_rgb_led_pwm',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'NeoCannonRGB',\n            isNotFor: ['NeoCannon'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                let red = script.getNumberValue('RED', script);\n                let green = script.getNumberValue('GREEN', script);\n                let blue = script.getNumberValue('BLUE', script);\n\n                if (!sq.shootState) {\n                    sq.shootState = {};\n                }\n\n                if (!sq.led) {\n                    sq.led = {};\n                }\n                if (!sq.d9) {\n                    sq.d9 = {};\n                }\n                if (!sq.d10) {\n                    sq.d10 = {};\n                }\n\n                sq.shootState = 4;\n                sq.led = blue & 255;\n                sq.d9 = red & 255;\n                sq.d10 = green & 255;\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.rgbLedPwm(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_rgb_led_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neo_cannon_rgb_led_off',\n            },\n            paramsKeyMap: {},\n            class: 'NeoCannonRGB',\n            isNotFor: ['NeoCannon'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!sq.shootState) {\n                    sq.shootState = {};\n                }\n\n                if (!sq.led) {\n                    sq.led = {};\n                }\n                if (!sq.d9) {\n                    sq.d9 = {};\n                }\n                if (!sq.d10) {\n                    sq.d10 = {};\n                }\n\n                sq.shootState = 4;\n                sq.led = 0;\n                sq.d9 = 0;\n                sq.d10 = 0;\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.rgbLedOff()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_cannon_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'neo_cannon_neopixel',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'NeoCannonNeopixel',\n            isNotFor: ['NeoCannon'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let num = script.getNumberValue('NUM', script) || 0;\n                num = num % 18;\n\n                let red = script.getNumberValue('RED', script);\n                let green = script.getNumberValue('GREEN', script);\n                let blue = script.getNumberValue('BLUE', script);\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                sq.neopixel = {\n                    type: Entry.NeoCannon.PORT_MAP.neopixel,\n                    data: {\n                        num,\n                        red,\n                        green,\n                        blue,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.update();\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.neopixel(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_neopixel_color_picker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'neo_cannon_neopixel_color_picker',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                COLOR: 1,\n            },\n            class: 'NeoCannonNeopixel',\n            isNotFor: ['NeoCannon'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let num = script.getNumberValue('NUM', script) || 0;\n                num = num % 18;\n\n                let value = script.getStringField('COLOR');\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                let red = parseInt(value.substr(1, 2), 16);\n                let green = parseInt(value.substr(3, 2), 16);\n                let blue = parseInt(value.substr(5, 2), 16);\n\n                sq.neopixel = {\n                    type: Entry.NeoCannon.PORT_MAP.neopixel,\n                    data: {\n                        num,\n                        red,\n                        green,\n                        blue,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.update();\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.neopixelColorPicker(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_neopixel_color_picker_all_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neo_cannon_neopixel_color_picker_all_on',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'NeoCannonNeopixel',\n            isNotFor: ['NeoCannon'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let value = script.getStringField('COLOR');\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                let red = parseInt(value.substr(1, 2), 16);\n                let green = parseInt(value.substr(3, 2), 16);\n                let blue = parseInt(value.substr(5, 2), 16);\n\n                sq.neopixel = {\n                    type: Entry.NeoCannon.PORT_MAP.neopixel,\n                    data: {\n                        red,\n                        green,\n                        blue,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.neopixelColorPickerAllOn(%1)',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_neopixel_all_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'neo_cannon_neopixel_all_on',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'NeoCannonNeopixel',\n            isNotFor: ['NeoCannon'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                let red = script.getNumberValue('RED', script);\n                let green = script.getNumberValue('GREEN', script);\n                let blue = script.getNumberValue('BLUE', script);\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                sq.neopixel = {\n                    type: Entry.NeoCannon.PORT_MAP.neopixel,\n                    data: {\n                        red,\n                        green,\n                        blue,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.neopixelAllON(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_cannon_neopixel_all_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neo_cannon_neopixel_all_off',\n            },\n            paramsKeyMap: {},\n            class: 'NeoCannonNeopixel',\n            isNotFor: ['NeoCannon'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                sq.neopixel = 0;\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoCannon.neopixelAllOFF()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.NeoCannon;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neo_spider.js",
    "content": "'use strict';\n\nEntry.NeoSpider = {\n    id: '41.1',\n    name: 'NeoSpider',\n    url: 'http://www.neo3ds.com/',\n    imageName: 'neo_spider.png',\n    title: {\n        ko: '네오스파이더',\n        en: 'NeoSpider',\n    },\n    PORT_MAP: {\n        tone: 0,\n        motorState: 0,\n        servoAngle: 0,\n        ultrasonic: 0,\n        motion: 0,\n        neopixel: 0,\n        outerLeftMotor: 0,\n        outerRightMotor: 0,\n    },\n    setZero() {\n        let portMap = Entry.NeoSpider.PORT_MAP;\n        let sq = Entry.hw.sendQueue;\n        for (let port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 310, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neo_spider.png',\n        width: 256,\n        height: 256,\n        listPorts: {\n            gas: {\n                name: '가스/외부센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cds: {\n                name: '조도센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            tmp: {\n                name: '온도센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            vibe: {\n                name: '진동센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            left_infared: {\n                name: '적외선(좌)',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            right_infared: {\n                name: '적외선(우)',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            ultrasonic: {\n                name: '초음파센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            motion: {\n                name: '모션센서',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n    BlockState: {},\n};\n\nEntry.NeoSpider.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                neo_spider_get_analog_value: '아날로그 %1 센서값',\n                neo_spider_get_analog_value_map: '아날로그 %1 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                neo_spider_get_ultrasonic_value: '초음파 센서값',\n                neo_spider_get_motion_value: '모션 센서 감지됨',\n                neo_spider_get_infared_value: '적외선센서 %1 감지됨',\n                neo_spider_set_tone: '부저를 %1 %2 음으로 %3 초 연주하기 %4',\n                neo_spider_set_servo: '머리방향 %1 의 각도로 정하기 (최소:50, 최대:130) %2',\n                neo_spider_set_servo_direction: '머리방향 %1 바라보기 %2',\n                neo_spider_motor_state: '네오스파이더 %1 이동하기 %2',\n                neo_spider_motor_state_secs: '네오스파이더 %1(으)로 %2초 이동하기 %3',\n                neo_spider_motor_stop: '네오스파이더 정지하기 %1',\n                neo_spider_neopixel_color_picker: 'RGB LED %1번  %2 (으)로 켜기 %3',\n                neo_spider_neopixel: 'RGB LED %1번  빨 %2 녹 %3 파 %4 (으)로 켜기 %5',\n                neo_spider_neopixel_color_picker_all_on: 'RGB LED 전체 %1 (으)로 켜기 %2',\n                neo_spider_neopixel_all_on: 'RGB LED 전체  빨 %1 녹 %2 파 %3 (으)로 켜기 %4',\n                neo_spider_neopixel_all_off: 'RGB LED 전체 끄기 %1',\n                neo_spider_outer_motor: '디지털 %1핀 %2 %3',\n                neo_spider_outer_motor_pwm: '디지털 %1핀 %2 (으)로 정하기 %3',\n            },\n\n            Helper: {\n                neo_spider_get_analog_value: '아날로그 센서값을 읽어오는 블럭입니다.<br/>가스, 조도, 진동, 외부 센서는 `0~1023`의 값 가지며, 온도센서는 온도값을 읽어옵니다.<br/><font color=\"crimson\">(단, 가스센서와 외부센서는 동시에 사용할 수 없습니다.)</font>',\n                neo_spider_get_analog_value_map: '아날로그 센서값의 범위를 다른 범위로 변환합니다.',\n                neo_spider_get_ultrasonic_value: '초음파를 통해 거리를 측정합니다.<br/><font color=\"crimson\">(참고, HC-SR04의 경우 약 0~2cm정도 측정을 못하고 너무 가까우면 이상한 값을 나타냅니다.)</font>',\n                neo_spider_get_motion_value: '모션 센서의 값을 가져옵니다.<br/>해당 센서값은 0: `감지 못함`, 1: `감지됨`입니다.<br/><font color=\"crimson\">(참고, 해당 센서의 경우 길게는 약 7초 정도 감지된 값을 유지합니다.)</font>',\n                neo_spider_get_infared_value: '적외선 센서의 값을 가져옵니다.<br/>왼쪽과 오른쪽 2가지로 나뉘어 있으며, 센서값은 0: `감지 못함`, 1: `감지됨`입니다.',\n                neo_spider_set_tone: '부저를 통해 선택한 옥타브 음계를 통해 해당 시간만큼 소리를 냅니다.<br/><font color=\"crimson\">(참고, 다음 블럭이 있을경우에 부저 연주시간이 끝난 후에 다음 블럭을 실행합니다.)</font>',\n                neo_spider_set_servo: '머리각도를 최소 50 ~ 최대 130도 사이의 값으로 움직입니다.',\n                neo_spider_set_servo_direction: '머리각도를 왼쪽(50), 정면(90), 오른쪽(130)으로 이동할 수 있습니다.',\n                neo_spider_motor_state: '네오스파이더를 전진, 좌회전, 우회전, 후진을 실행합니다.',\n                neo_spider_motor_state_secs: '네오스파이더를 전진, 좌회전, 우회전, 후진을 정해진 시간만큼 실행합니다.',\n                neo_spider_motor_stop: '네오스파이더 이동을 정지',\n                neo_spider_neopixel_color_picker: '색을 보고 RGB색상을 정하여 정해진 LED를 켤 수 있습니다.<br/><font color=\"crimson\">(참고, LED번호는 0번부터 7번까지 입니다.)</font>',\n                neo_spider_neopixel: '정해준 LED 번호에 빨강, 파랑, 초록의 색을 넣고 조합하여 LED를 켤 수 있습니다.<br/><font color=\"crimson\">(참고, LED번호는 0번부터 7번까지 입니다.)</font>',\n                neo_spider_neopixel_color_picker_all_on: '색을 보고 RGB색상을 정하여 모든 LED를 켤 수 있습니다.',\n                neo_spider_neopixel_all_on: '빨강, 파랑, 초록의 색을 넣고 조합하여 모든 LED를 켤 수 있습니다.',\n                neo_spider_neopixel_all_off: '모든 LED를 끌 수 있습니다.',\n                neo_spider_outer_motor: '외부 모듈을 통하여 D5, D6번을 제어할 수 있습니다.<font color=\"crimson\">(단, 동시에 HIGH를 주어 작동 시킬 수 없습니다.)</font>',\n                neo_spider_outer_motor_pwm: '외부 모듈을 통하여 D5, D6번을 제어할 수 있습니다.<font color=\"crimson\">(단, 동시에 0 이상의 값을 주어 작동 시킬 수 없습니다.)</font>',\n            },\n        },\n        en: {\n            template: {\n                neo_spider_get_analog_value: 'Analog %1 pin Sensor value',\n                neo_spider_get_analog_value_map: 'Analog %1 value Map range %2 ~ %3 to %4 ~ %5',\n                neo_spider_get_ultrasonic_value: 'Ultrasonic Sensor value',\n                neo_spider_get_motion_value: 'Motion Sensor value',\n                neo_spider_get_infared_value: 'Infared ray %1 Sensor value',\n                neo_spider_set_tone: 'Play tone note %1 octave %2 beat %3 %4',\n                neo_spider_set_servo: 'Set head direction as %1 (min:50, max:130) %2',\n                neo_spider_set_servo_direction: 'Set head direction as %1 %2',\n                neo_spider_motor_state: 'Move neospider %1 %2',\n                neo_spider_motor_state_secs: 'Move neospider %1 %2 secs %3',\n                neo_spider_motor_stop: 'Neospider stop %1',\n                neo_spider_neopixel_color_picker: 'RGB LED number %1 turn on %2 %3',\n                neo_spider_neopixel: 'RGB LED number %1 turn on R %2 G %3 B %4 %5',\n                neo_spider_neopixel_color_picker_all_on: 'All RGB LED turn on %1 %2',\n                neo_spider_neopixel_all_on: 'All RGB LED turn on R %1 G %2 B %3 %4',\n                neo_spider_neopixel_all_off: 'All RGB LED turn off %1',\n                neo_spider_outer_motor: 'Digital %1 pin %2 %3',\n                neo_spider_outer_motor_pwm: 'Digital %1 pin %2 %3',\n            },\n        },\n    };\n};\n\n\nEntry.NeoSpider.blockMenuBlocks = [\n    'neo_spider_get_analog_value',\n    'neo_spider_get_analog_value_map',\n    'neo_spider_get_ultrasonic_value',\n    'neo_spider_get_motion_value',\n    'neo_spider_get_infared_value',\n    'neo_spider_set_servo',\n    'neo_spider_set_servo_direction',\n    'neo_spider_set_tone',\n    'neo_spider_motor_state',\n    'neo_spider_motor_state_secs',\n    'neo_spider_motor_stop',\n    'neo_spider_neopixel_color_picker',\n    'neo_spider_neopixel_color_picker_all_on',\n    'neo_spider_neopixel',\n    'neo_spider_neopixel_all_on',\n    'neo_spider_neopixel_all_off',\n    'neo_spider_outer_motor',\n    'neo_spider_outer_motor_pwm',\n];\n\nEntry.NeoSpider.getBlocks = function () {\n    return {\n        neo_spider_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가스', 'gas'],\n                        ['조도', 'cds'],\n                        ['온도', 'tmp'],\n                        ['진동', 'vibe'],\n                        ['외부', 'outer'],\n                    ],\n                    value: 'gas',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null,],\n                type: 'neo_spider_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'NeoSpiderGet',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const pd = Entry.hw.portData;\n                let port = script.getValue('PORT', script);\n                port = port == 'outer' ? 'gas' : port;\n                return pd[port];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['가스', 'gas'],\n                                    ['조도', 'cds'],\n                                    ['온도', 'tmp'],\n                                    ['진동', 'vibe'],\n                                    ['외부', 'outer'],\n                                ],\n                                value: 'gas',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueLowerCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['가스', 'gas'],\n                        ['조도', 'cds'],\n                        ['온도', 'tmp'],\n                        ['진동', 'vibe'],\n                        ['외부', 'outer'],\n                    ],\n                    value: 'gas',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'neo_spider_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'NeoSpiderGet',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const pd = Entry.hw.portData;\n                let port = script.getValue('PORT', script);\n                port = port == 'outer' ? 'gas' : port;\n                let result = pd[port];\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n\n                result = ((result - value2) * (value5 - value4) / value3 - value2) + value4;\n\n                if ((result % 1) == 0) {\n                    result = Math.round(result);\n                } else {\n                    result = Math.round(result * 100 / 100);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.mapAnalog(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['가스', 'gas'],\n                                    ['조도', 'cds'],\n                                    ['온도', 'tmp'],\n                                    ['진동', 'vibe'],\n                                    ['외부', 'outer'],\n                                ],\n                                value: 'gas',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueLowerCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'neo_spider_get_ultrasonic_value',\n            },\n            paramsKeyMap: {},\n            class: 'NeoSpiderGet',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!sq.ultrasonic) {\n                    sq.ultrasonic = {};\n                }\n\n                sq.ultrasonic = 1;\n\n                return Entry.hw.portData.ultrasonic || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.getUltrasonic()',\n                        blockType: 'param',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_spider_get_motion_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'neo_spider_get_motion_value',\n            },\n            paramsKeyMap: {},\n            class: 'NeoSpiderGet',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!sq.motion) {\n                    sq.motion = {};\n                }\n\n                sq.motion = 1;\n\n                return Entry.hw.portData.motion || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.getMotionValue()',\n                        blockType: 'param',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_spider_get_infared_value : {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['왼쪽', 'left_infared'],\n                        ['오른쪽', 'right_infared'],\n                    ],\n                    value: 'left_infared',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null,],\n                type: 'neo_spider_get_infared_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'NeoSpiderGet',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n\n                return Entry.hw.portData[port] || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.getInfaredValue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['왼쪽', 'left_infared'],\n                                    ['오른쪽', 'right_infared'],\n                                ],\n                                value: 'left_infared',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueLowerCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'neo_spider_tone_list',\n                    },\n                ],\n            },\n        },\n        neo_spider_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neo_spider_tone_list',\n                    },\n                ],\n                type: 'neo_spider_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'neo_spider_tone_value',\n                    },\n                ],\n            },\n        },\n        neo_spider_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'neo_spider_octave_list',\n                    },\n                ],\n            },\n        },\n        neo_spider_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neo_spider_tone_list',\n                    },\n                    {\n                        type: 'neo_spider_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'neo_spider_set_tone',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.NeoSpider.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.tone) {\n                        sq.tone = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.tone = {\n                            type: Entry.NeoSpider.PORT_MAP.tone,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.NeoSpider.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.tone = {\n                        type: Entry.NeoSpider.PORT_MAP.tone,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.tone = {\n                        type: Entry.NeoSpider.PORT_MAP.tone,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.tone(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    90,\n                ],\n                type: 'neo_spider_set_servo',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(130, value);\n                value = Math.max(50, value);\n\n                sq.servoAngle = value;\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.servomotorWrite(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_set_servo_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞', '90'],\n                        ['왼쪽', '50'],\n                        ['오른쪽', '130'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neo_spider_set_servo_direction',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(130, value);\n                value = Math.max(50, value);\n\n                sq.servoAngle = value;\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.servomotorWrite(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_motor_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', 1],\n                        ['왼쪽으로', 2],\n                        ['오른쪽으로', 3],\n                        ['뒤로', 4],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'neo_spider_motor_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let state = script.getNumberValue('STATE', script);\n\n                if (!sq.motorState) {\n                    sq.motorState = {};\n                }\n\n                sq.motorState = state;\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.motorState(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['앞으로', '1'],\n                                    ['왼쪽으로', '2'],\n                                    ['오른쪽으로', '3'],\n                                    ['뒤로', '4'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_motor_state_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', 1],\n                        ['왼쪽으로', 2],\n                        ['오른쪽으로', 3],\n                        ['뒤로', 4],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n                type: 'neo_spider_motor_state_secs',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n                DURATION: 1,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    let state = script.getNumberValue('STATE', script);\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration <= 0) {\n                        duration = 0;\n                        state = 0;\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (!sq.motorState) {\n                        sq.motorState = {};\n                    }\n\n                    sq.motorState = state;\n\n                    setTimeout(() =>  {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.motorState = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.motorStateSecs(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['앞으로', '1'],\n                                    ['왼쪽으로', '2'],\n                                    ['오른쪽으로', '3'],\n                                    ['뒤로', '4'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neo_spider_motor_stop',\n            },\n            paramsKeyMap: {},\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                if (!sq.motorState) {\n                    sq.motorState = {};\n                }\n                sq.motorState = 0;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.motorStop()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_spider_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'neo_spider_neopixel',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let num = script.getNumberValue('NUM', script);\n                let numStr = '';\n                switch (num) {\n                    case 0: {\n                        numStr = 'first';\n                        break;\n                    }\n                    case 1: {\n                        numStr = 'second';\n                        break;\n                    }\n                    case 2: {\n                        numStr = 'third';\n                        break;\n                    }\n                    case 3: {\n                        numStr = 'fourth';\n                        break;\n                    }\n                    case 4: {\n                        numStr = 'fifth';\n                        break;\n                    }\n                    case 5: {\n                        numStr = 'sixth';\n                        break;\n                    }\n                    case 6: {\n                        numStr = 'seventh';\n                        break;\n                    }\n                    case 7: {\n                        numStr = 'eighth';\n                        break;\n                    }\n                }\n\n                let red = script.getNumberValue('RED', script);\n                let green = script.getNumberValue('GREEN', script);\n                let blue = script.getNumberValue('BLUE', script);\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                if (numStr) {\n                    sq.neopixel = {\n                        type: Entry.NeoSpider.PORT_MAP.neopixel,\n                        data: {\n                            numStr,\n                            red,\n                            green,\n                            blue\n                        },\n                        time: new Date().getTime(),\n                    };\n    \n                    Entry.hw.update();\n                }\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.neopixel(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_neopixel_color_picker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'neo_spider_neopixel_color_picker',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                COLOR: 1,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let num = script.getNumberValue('NUM', script);\n                let numStr = '';\n                switch (num) {\n                    case 0: {\n                        numStr = 'first';\n                        break;\n                    }\n                    case 1: {\n                        numStr = 'second';\n                        break;\n                    }\n                    case 2: {\n                        numStr = 'third';\n                        break;\n                    }\n                    case 3: {\n                        numStr = 'fourth';\n                        break;\n                    }\n                    case 4: {\n                        numStr = 'fifth';\n                        break;\n                    }\n                    case 5: {\n                        numStr = 'sixth';\n                        break;\n                    }\n                    case 6: {\n                        numStr = 'seventh';\n                        break;\n                    }\n                    case 7: {\n                        numStr = 'eighth';\n                        break;\n                    }\n                }\n\n                let value = script.getStringField('COLOR');\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                if (numStr) {\n                    let red = parseInt(value.substr(1, 2), 16);\n                    let green = parseInt(value.substr(3, 2), 16);\n                    let blue = parseInt(value.substr(5, 2), 16);\n\n                    sq.neopixel = {\n                        type: Entry.NeoSpider.PORT_MAP.neopixel,\n                        data: {\n                            numStr,\n                            red,\n                            green,\n                            blue\n                        },\n                        time: new Date().getTime(),\n                    };\n    \n                    Entry.hw.update();\n                }\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.neopixelColorPicker(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_neopixel_color_picker_all_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'neo_spider_neopixel_color_picker_all_on',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let value = script.getStringField('COLOR');\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                let red = parseInt(value.substr(1, 2), 16);\n                let green = parseInt(value.substr(3, 2), 16);\n                let blue = parseInt(value.substr(5, 2), 16);\n\n                sq.neopixel = {\n                    type: Entry.NeoSpider.PORT_MAP.neopixel,\n                    data: {\n                        red,\n                        green,\n                        blue\n                    },\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.neopixelColorPickerAllOn(%1)',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_neopixel_all_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'neo_spider_neopixel_all_on',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                let red = script.getNumberValue('RED', script);\n                let green = script.getNumberValue('GREEN', script);\n                let blue = script.getNumberValue('BLUE', script);\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                sq.neopixel = {\n                    type: Entry.NeoSpider.PORT_MAP.neopixel,\n                    data: {\n                        red,\n                        green,\n                        blue\n                    },\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.neopixelAllON(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_neopixel_all_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null,],\n                type: 'neo_spider_neopixel_all_off',\n            },\n            paramsKeyMap: {},\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func: function (sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!sq.neopixel) {\n                    sq.neopixel = {};\n                }\n\n                sq.neopixel = 0;\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.neopixelAllOFF()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        neo_spider_outer_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LOW', '0'],\n                        ['HIGH', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    5,\n                    null,\n                ],\n                type: 'neo_spider_outer_motor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                STATE: 1,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let port = script.getNumberValue('PORT', script);\n                let state = script.getNumberValue('STATE', script);\n                state = state ? 255 : 0;\n                if (port == 5) {\n                    if (!sq.outerLeftMotor) {\n                        sq.outerLeftMotor = {};\n                    }\n                    sq.outerLeftMotor = state;\n                } else if (port == 6) {\n                    if (!sq.outerRightMotor) {\n                        sq.outerRightMotor = {};\n                    }\n                    sq.outerRightMotor = state;\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.outerDigitalPin(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                ],\n                                value: '5',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['LOW', '0'],\n                                    ['HIGH', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        neo_spider_outer_motor_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    5,\n                    null,\n                ],\n                type: 'neo_spider_outer_motor_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'NeoSpider',\n            isNotFor: ['NeoSpider'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                \n                if (port == 5) {\n                    if (!sq.outerLeftMotor) {\n                        sq.outerLeftMotor = {};\n                    }\n                    sq.outerLeftMotor = value;\n                } else if (port == 6) {\n                    if (!sq.outerRightMotor) {\n                        sq.outerRightMotor = {};\n                    }\n                    sq.outerRightMotor = value;\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'NeoSpider.outerDigitalPinPWM(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                ],\n                                value: '5',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.NeoSpider;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neobot.js",
    "content": "'use strict';\n\nEntry.Neobot = {\n    hasPracticalCourse: true,\n    id: '5.1',\n    name: 'neobot',\n    url: 'http://www.neobot.co.kr',\n    imageName: 'neobot.png',\n    title: {\n        ko: '네오봇',\n        en: 'NeoBot',\n    },\n    LOCAL_MAP: ['IN1', 'IN2', 'IN3', 'IR', 'BAT'],\n    REMOTE_MAP: ['OUT1', 'OUT2', 'OUT3', 'DCR', 'DCL', 'SND', 'FND', 'OPT'],\n    setZero: function () {\n        for (var port in Entry.Neobot.REMOTE_MAP) {\n            Entry.hw.sendQueue[Entry.Neobot.REMOTE_MAP[port]] = 0;\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neobot.png',\n        width: 700,\n        height: 700,\n        listPorts: {\n            IR: { name: 'IR', type: 'input', pos: { x: 0, y: 0 } },\n            BAT: { name: 'BAT', type: 'input', pos: { x: 0, y: 0 } },\n            SND: { name: 'SND', type: 'output', pos: { x: 0, y: 0 } },\n            FND: { name: 'FND', type: 'output', pos: { x: 0, y: 0 } },\n        },\n        ports: {\n            IN1: { name: 'IN1', type: 'input', pos: { x: 270, y: 170 } },\n            IN2: { name: 'IN2', type: 'input', pos: { x: 325, y: 170 } },\n            IN3: { name: 'IN3', type: 'input', pos: { x: 325, y: 530 } },\n            DCL: { name: 'L-Motor', type: 'output', pos: { x: 270, y: 530 } },\n            DCR: { name: 'R-Motor', type: 'output', pos: { x: 435, y: 530 } },\n            OUT1: { name: 'OUT1', type: 'output', pos: { x: 380, y: 170 } },\n            OUT2: { name: 'OUT2', type: 'output', pos: { x: 435, y: 170 } },\n            OUT3: { name: 'OUT3', type: 'output', pos: { x: 380, y: 530 } },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.Neobot.getPracticalBlocks = function () {\n    return {\n        practical_course_motor_speed: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic_string_field',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '15',\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n        practical_course_set_servo2: {\n            color: '#D128BD',\n            outerLine: '#a2049e',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1 포트의 서보모터를 %2 도 이동 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', '1'],\n                        ['OUT2', '2'],\n                        ['OUT3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/servo.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'practical_course_set_servo2',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DEGREE: 1,\n            },\n            class: 'practical_course_servo',\n            func(sprite, script) {\n                const port = script.getNumberField('PORT');\n                let degree = script.getNumberValue('DEGREE');\n                if (degree < 0) {\n                    degree = 0;\n                } else if (degree > 180) {\n                    degree = 180;\n                }\n                Entry.hw.sendQueue[`OUT${port}`] = degree;\n                let option = port;\n                if (option === 3) {\n                    option = 4;\n                }\n                Entry.hw.sendQueue.OPT = Entry.hw.sendQueue.OPT | option;\n                return script.callReturn();\n            },\n        },\n        practical_course_move_for_secs: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1모터를 %2 %3의 속도로 %4초 동안 회전 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['양쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['왼쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '16'],\n                        ['뒤로', '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'practical_course_motor_speed',\n                    },\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'practical_course_move_for_secs',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n                DURATION: 3,\n            },\n            class: 'practical_course_motor',\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const wheel = script.getNumberField('WHEEL');\n                    const speed = script.getNumberValue('SPEED');\n                    const direction = script.getNumberField('DIRECTION');\n                    const duration = script.getNumberValue('DURATION');\n                    const value = speed + direction;\n                    switch (wheel) {\n                        case 1: {\n                            Entry.hw.sendQueue.DCL = value;\n                            Entry.hw.sendQueue.DCR = value;\n                            break;\n                        }\n\n                        case 2: {\n                            Entry.hw.sendQueue.DCR = value;\n                            break;\n                        }\n\n                        case 3: {\n                            Entry.hw.sendQueue.DCL = value;\n                            break;\n                        }\n                    }\n\n                    script.wheelMode = wheel;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    switch (script.wheelMode) {\n                        case 1: {\n                            Entry.hw.sendQueue.DCL = 0;\n                            Entry.hw.sendQueue.DCR = 0;\n                            break;\n                        }\n\n                        case 2: {\n                            Entry.hw.sendQueue.DCR = 0;\n                            break;\n                        }\n\n                        case 3: {\n                            Entry.hw.sendQueue.DCL = 0;\n                            break;\n                        }\n                    }\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    delete script.wheelMode;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        practical_course_move_for_secs2: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '왼쪽 모터를 %1 %2의 속도로, 오른쪽 모터를 %3 %4의 속도로 %5초 동안 회전 %6',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '16'],\n                        ['뒤로', '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '16'],\n                        ['뒤로', '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'practical_course_motor_speed',\n                    },\n                    null,\n                    {\n                        type: 'practical_course_motor_speed',\n                    },\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'practical_course_move_for_secs2',\n            },\n            paramsKeyMap: {\n                DIRECTION1: 0,\n                SPEED1: 1,\n                DIRECTION2: 2,\n                SPEED2: 3,\n                DURATION: 4,\n            },\n            class: 'practical_course_motor',\n            func(sprite, script) {\n                if (!script.isStart) {\n                    // var wheel = script.getNumberField('WHEEL');\n                    const speed1 = script.getNumberValue('SPEED1');\n                    const speed2 = script.getNumberValue('SPEED2');\n                    const direction1 = script.getNumberField('DIRECTION1');\n                    const direction2 = script.getNumberField('DIRECTION2');\n                    const duration = script.getNumberValue('DURATION');\n                    const value1 = speed1 + direction1;\n                    const value2 = speed2 + direction2;\n\n                    Entry.hw.sendQueue.DCL = value1;\n                    Entry.hw.sendQueue.DCR = value2;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue.DCL = 0;\n                    Entry.hw.sendQueue.DCR = 0;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    delete script.wheelMode;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        practical_course_move_for: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1모터를 %2 %3의 속도로 계속 회전 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['양쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['왼쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '16'],\n                        ['뒤로', '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'practical_course_motor_speed',\n                    },\n                    null,\n                ],\n                type: 'practical_course_move_for',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'practical_course_motor',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                const wheel = script.getNumberField('WHEEL');\n                const speed = script.getNumberValue('SPEED');\n                const direction = script.getNumberField('DIRECTION');\n                const value = speed + direction;\n\n                switch (wheel) {\n                    case 1: {\n                        Entry.hw.sendQueue.DCL = value;\n                        Entry.hw.sendQueue.DCR = value;\n                        break;\n                    }\n\n                    case 2: {\n                        Entry.hw.sendQueue.DCR = value;\n                        break;\n                    }\n\n                    case 3: {\n                        Entry.hw.sendQueue.DCL = value;\n                        break;\n                    }\n                }\n\n                return script.callReturn();\n            },\n        },\n        practical_course_move_for2: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '왼쪽 모터를 %1 %2의 속도로, 오른쪽 모터를 %3 %4의 속도로 계속 회전 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '16'],\n                        ['뒤로', '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '16'],\n                        ['뒤로', '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'practical_course_motor_speed',\n                    },\n                    null,\n                    {\n                        type: 'practical_course_motor_speed',\n                    },\n                    null,\n                ],\n                type: 'practical_course_move_for2',\n            },\n            paramsKeyMap: {\n                DIRECTION1: 0,\n                SPEED1: 1,\n                DIRECTION2: 2,\n                SPEED2: 3,\n            },\n            class: 'practical_course_motor',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                const speed1 = script.getNumberValue('SPEED1');\n                const direction1 = script.getNumberField('DIRECTION1');\n                const speed2 = script.getNumberValue('SPEED2');\n                const direction2 = script.getNumberField('DIRECTION2');\n                const value1 = speed1 + direction1;\n                const value2 = speed2 + direction2;\n\n                Entry.hw.sendQueue.DCL = value1;\n                Entry.hw.sendQueue.DCR = value2;\n\n                return script.callReturn();\n            },\n        },\n        practical_course_stop_for: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1모터를 정지 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['양쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['왼쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'practical_course_stop_for',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n            },\n            class: 'practical_course_motor',\n            func(sprite, script) {\n                const wheel = script.getNumberField('WHEEL');\n                if (wheel == 2) {\n                    Entry.hw.sendQueue.DCR = 0;\n                } else if (wheel == 3) {\n                    Entry.hw.sendQueue.DCL = 0;\n                } else {\n                    Entry.hw.sendQueue.DCR = 0;\n                    Entry.hw.sendQueue.DCL = 0;\n                }\n                return script.callReturn();\n            },\n        },\n        practical_course_touch_value: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 접촉 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'practical_course_touch_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'practical_course_touch',\n            func(sprite, script) {\n                const port = script.getStringField('PORT');\n                const value = Entry.hw.portData[`IN${port}`] > 125 ? 1 : 0;\n                return value;\n            },\n        },\n        practical_course_touch_value_boolean: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 접촉 센서가 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['접촉 되면', '1'],\n                        ['접촉 안되면', '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            def: {\n                params: [null, null, null],\n                type: 'practical_course_touch_value_boolean',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                TOUCH: 1,\n            },\n            class: 'practical_course_touch',\n            func(sprite, script) {\n                const port = script.getStringField('PORT');\n                const touch = script.getNumberField('TOUCH', script);\n                const value = Entry.hw.portData[`IN${port}`];\n                const isTouch = !((value > 125) ^ touch);\n\n                return isTouch;\n            },\n        },\n        practical_course_light_value: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 빛 감지 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'practical_course_light_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'practical_course_light',\n            func(sprite, script) {\n                const port = script.getStringField('PORT');\n                return Entry.hw.portData[`IN${port}`];\n            },\n        },\n        practical_course_light_value_boolean: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 빛 감지 센서 값 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'practical_course_light_value_boolean',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                RIGHTVALUE: 2,\n            },\n            class: 'practical_course_light',\n            func(sprite, script) {\n                const port = script.getNumberField('PORT', script);\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\n                const leftValue = Entry.hw.portData[`IN${port}`];\n                let isCheck = false;\n\n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n\n                return isCheck;\n            },\n        },\n        practical_course_sound_value: {\n            color: '#01d67f',\n            outerLine: '#00b36a',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 소리 센서에 감지되는 소리 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#00b36a',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'practical_course_sound_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'practical_course_sound',\n            func(sprite, script) {\n                const port = script.getStringField('PORT');\n                return Entry.hw.portData[`IN${port}`];\n            },\n        },\n        practical_course_sound_value_boolean: {\n            color: '#01d67f',\n            outerLine: '#00b36a',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 소리 센서에 감지되는 소리 값 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#00b36a',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#00b36a',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'practical_course_sound_value_boolean',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                RIGHTVALUE: 2,\n            },\n            class: 'practical_course_sound',\n            func(sprite, script) {\n                const port = script.getNumberField('PORT', script);\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\n                const leftValue = Entry.hw.portData[`IN${port}`];\n                let isCheck = false;\n\n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n\n                return isCheck;\n            },\n        },\n        practical_course_irs_value: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 적외선 센서에 감지되는 크기 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'practical_course_irs_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'practical_course_irs',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                const port = script.getStringField('PORT');\n                return Entry.hw.portData[`IN${port}`];\n            },\n        },\n        practical_course_irs_value_boolean: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 적외선 센서에 감지되는 크기 값이 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'practical_course_irs_value_boolean',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                RIGHTVALUE: 2,\n            },\n            class: 'practical_course_irs',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                const port = script.getNumberField('PORT', script);\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\n                const leftValue = Entry.hw.portData[`IN${port}`];\n                let isCheck = false;\n\n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n\n                return isCheck;\n            },\n        },\n        practical_course_diode_secs_toggle: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 발광다이오드를 %2초 동안 %3 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT 1', '1'],\n                        ['OUT 2', '2'],\n                        ['OUT 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', '255'],\n                        ['끄기', '0'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/diode.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'practical_course_diode_secs_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DURATION: 1,\n                VALUE: 2,\n            },\n            class: 'practical_course_diode',\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getNumberField('PORT');\n                    const duration = script.getNumberValue('DURATION');\n                    let value = script.getNumberField('VALUE');\n\n                    let option = port;\n                    if (value < 0) {\n                        value = 0;\n                    } else if (value > 255) {\n                        value = 255;\n                    }\n                    if (option === 3) {\n                        option = 4;\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    script.outPort = port;\n                    script.outOption = option;\n                    Entry.hw.sendQueue[`OUT${port}`] = value;\n                    Entry.hw.sendQueue.OPT = Entry.hw.sendQueue.OPT & ~option;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue[`OUT${script.outPort}`] = 0;\n                    Entry.hw.sendQueue.OPT = Entry.hw.sendQueue.OPT & ~script.outOption;\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    delete script.outPort;\n                    delete script.outOption;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        practical_course_diode_toggle: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 발광다이오드를 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT 1', '1'],\n                        ['OUT 2', '2'],\n                        ['OUT 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', '255'],\n                        ['끄기', '0'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/diode.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'practical_course_diode_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'practical_course_diode',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                const port = script.getNumberField('PORT');\n                let value = script.getNumberField('VALUE');\n                let option = port;\n\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n\n                if (option === 3) {\n                    option = 4;\n                }\n\n                Entry.hw.sendQueue[`OUT${port}`] = value;\n                Entry.hw.sendQueue.OPT = Entry.hw.sendQueue.OPT & ~option;\n\n                return script.callReturn();\n            },\n        },\n        practical_course_diode_inout_toggle: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 발광다이오드를 %2번 포트의 %3~%4의 범위로 켜기%5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT 1', '1'],\n                        ['OUT 2', '2'],\n                        ['OUT 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/diode.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['255'] },\n                    null,\n                ],\n                type: 'practical_course_diode_inout_toggle',\n            },\n            paramsKeyMap: {\n                OUTPUT: 0,\n                INPUT: 1,\n                MIN: 2,\n                MAX: 3,\n            },\n            class: 'practical_course_diode',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                const outputPort = script.getNumberField('OUTPUT');\n                const inputPort = script.getNumberField('INPUT');\n                let option = inputPort;\n                if (option === 3) {\n                    option = 4;\n                }\n                const oMin = script.getNumberValue('MIN');\n                const oMax = script.getNumberValue('MAX');\n                const nMin = 0;\n                const nMax = 255;\n                const x = Entry.hw.portData[`IN${inputPort}`];\n                const percent = (x - oMin) / (oMax - oMin);\n                let result = percent * (nMax - nMin) + nMin;\n                if (result > nMax) {\n                    result = nMax;\n                }\n                if (result < nMin) {\n                    result = nMin;\n                }\n\n                Entry.hw.sendQueue[`OUT${outputPort}`] = result;\n                Entry.hw.sendQueue.OPT = Entry.hw.sendQueue.OPT & ~option;\n\n                return script.callReturn();\n            },\n        },\n        practical_course_diode_set_output: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 발광다이오드를 %2의 밝기로 정하기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT 1', '1'],\n                        ['OUT 2', '2'],\n                        ['OUT 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/diode.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'practical_course_diode_set_output',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'practical_course_diode',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                const port = script.getStringField('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                let option = port;\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n                if (option === 3) {\n                    option = 4;\n                }\n                Entry.hw.sendQueue[`OUT${port}`] = value;\n                Entry.hw.sendQueue.OPT = Entry.hw.sendQueue.OPT & ~option;\n                return script.callReturn();\n            },\n        },\n        practical_course_diode_input_value: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '%1번 포트의 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN 1', '1'],\n                        ['IN 2', '2'],\n                        ['IN 3', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'practical_course_diode_input_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'practical_course_diode',\n            func(sprite, script) {\n                const port = script.getStringField('PORT');\n                return Entry.hw.portData[`IN${port}`];\n            },\n        },\n        practical_course_melody_note_for: {\n            color: '#FC327F',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['neobot'],\n            template: '멜로디 %1 을(를) %2 옥타브로 %3 길이만큼 소리내기 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['무음', '0'],\n                        ['도', '1'],\n                        ['도#(레♭)', '2'],\n                        ['레', '3'],\n                        ['레#(미♭)', '4'],\n                        ['미', '5'],\n                        ['파', '6'],\n                        ['파#(솔♭)', '7'],\n                        ['솔', '8'],\n                        ['솔#(라♭)', '9'],\n                        ['라', '10'],\n                        ['라#(시♭)', '11'],\n                        ['시', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#ce105e',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: '#ce105e',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['온음표', '1'],\n                        ['2분음표', '2'],\n                        ['4분음표', '4'],\n                        ['8분음표', '8'],\n                        ['16분음표', '16'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: '#ce105e',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/melody.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'practical_course_melody_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'practical_course_melody',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    const note = script.getNumberField('NOTE', script);\n                    const octave = script.getNumberField('OCTAVE', script);\n                    const duration = script.getNumberField('DURATION', script);\n                    let value = note > 0 ? note + 12 * octave : 0;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    script.soundFlag = 1;\n                    if (value > 65) {\n                        value = 65;\n                    }\n                    sq.SND = value;\n                    setTimeout(() => {\n                        setTimeout(() => {\n                            script.timeFlag = 0;\n                        }, 50);\n                    }, (1 / duration) * 2000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else if (script.soundFlag == 1) {\n                    Entry.hw.sendQueue.SND = 0;\n                    script.soundFlag = 0;\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n    }\n}\n\nEntry.Neobot.practicalBlockMenuBlocks = {\n    hw_motor: [\n        // 'practical_course_motor_speed',\n        'practical_course_move_for_secs',\n        'practical_course_move_for_secs2',\n        'practical_course_move_for',\n        'practical_course_move_for2',\n        'practical_course_stop_for',\n        'practical_course_set_servo2',\n    ],\n    hw_melody: [\n        'practical_course_melody_note_for',\n    ],\n    hw_sensor: [\n        'practical_course_touch_value',\n        'practical_course_touch_value_boolean',\n        'practical_course_light_value',\n        'practical_course_light_value_boolean',\n        'practical_course_sound_value',\n        'practical_course_sound_value_boolean',\n        'practical_course_irs_value',\n        'practical_course_irs_value_boolean',\n    ],\n    hw_led: [\n        'practical_course_diode_secs_toggle',\n        'practical_course_diode_toggle',\n        'practical_course_diode_inout_toggle',\n        'practical_course_diode_set_output',\n        'practical_course_diode_input_value',\n    ],\n}\n\nEntry.Neobot.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                neobot_turn_left: '왼쪽모터를 %1 %2 회전 %3',\n                neobot_stop_left: '왼쪽모터 정지 %1',\n                neobot_turn_right: '오른쪽모터를 %1 %2 회전 %3',\n                neobot_stop_right: '오른쪽모터 정지 %1',\n                neobot_run_motor: '%1 모터를  %2 초간 %3 %4 %5',\n                neobot_servo_1: 'SERVO1에 연결된 서보모터를 %1 속도로 %2 로 이동 %3',\n                neobot_servo_2: 'SERVO2에 연결된 서보모터를 %1 속도로 %2 로 이동 %3',\n                neobot_set_sensor_value: '%1 번 포트의 값을 %2 %3',\n\n                neobot_sensor_value: '%1 값',\n                neobot_sensor_connect_external: '%1 에 연결한 %2 값',\n                neobot_sensor_convert_scale: '%1 센서값 %2 ~ %3 를 %4 ~ %5 (으)로 바꾼 값',\n\n                neobot_compare_symbol: '%1',\n                neobot_decision_sensor_is_over: '%1 의 센서값이 %2 %3',\n                neobot_decision_equal_with_sensor: '%1 에 연결한 컬러센서가 %2 을 감지함',\n                neobot_remote_button: '리모컨의 %1 버튼을 누름',\n\n                get_motor_speed: '%1',\n                neobot_left_motor: '왼쪽 모터를 %1 %2 의 속도로 회전 %3',\n                neobot_stop_left_motor: '왼쪽 모터를 정지 %1',\n                neobot_right_motor: '오른쪽 모터를 %1 %2 의 속도로 회전 %3',\n                neobot_stop_right_motor: '오른쪽 모터를 정지 %1',\n                neobot_both_motor: '왼쪽 모터를 %1 %2 & 오른쪽 모터를 %3 %4 의 속도로 회전 %5',\n                neobot_all_motor: '양쪽 모터를 %1 %2의 속도로 %3 회전 %4',\n                neobot_stop_all_motor: '양쪽 모터를 정지 %1',\n                neobot_robot: '로봇 %1 %2',\n\n                neobot_output_led_type1: '%1 에 연결한 LED를 %2 밝기로 %3 켜기 %4',\n                neobot_output_led_on: '%1 에 연결한 LED 켜기 %2',\n                neobot_output_led_off: '%1 에 연결한 LED 끄기 %2',\n                neobot_set_output: '%1 에 %2값만큼 출력 %3',\n\n                get_servo_degree: '%1',\n                neobot_servo_init: '%1 Servo모터 리셋 %2',\n                neobot_servo_change_degree: 'Servo모터 각도 바꾸기 : %1 %2 %3 %4 %5',\n                neobot_servo_rotate: 'Servo모터 회전하기 : %1 %2 %3 %4',\n                neobot_servo_stop: '%1 Servo모터 멈추기 %2',\n\n                neobot_play_note_for: '멜로디 %1 을(를) %2 옥타브로 %3 길이만큼 소리내기 %4',\n                neobot_play_note_with_sensor:\n                    '컨트롤러에서 %1 센서의 %2 ~ %3 값으로 멜로디 연주하기 %4',\n            },\n            Helper: {\n                neobot_sensor_value:\n                    'IN1 ~ IN3 포트 및 리모컨에서 입력되는 값 그리고 배터리 정보를 0부터 255의 숫자로 표시합니다.',\n                neobot_sensor_convert_scale:\n                    '선택한 포트 입력값의 변화를 특정범위의 값으로 표현범위를 조절할 수 있습니다.',\n                neobot_left_motor: 'L모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.',\n                neobot_stop_left_motor: 'L모터 포트에 연결한 모터를 정지합니다.',\n                neobot_right_motor: 'R모터 포트에 연결한 모터의 회전방향 및 속도를 설정합니다.',\n                neobot_stop_right_motor: 'R모터 포트에 연결한 모터를 정지합니다.',\n                neobot_all_motor:\n                    'L모터 및 R모터 포트에 2개 모터를 연결하여 바퀴로 활용할 때 전, 후, 좌, 우 이동 방향 및 속도, 시간을 설정할 수 있습니다.',\n                neobot_stop_all_motor: 'L모터 및 R모터에 연결한 모터를 모두 정지합니다.',\n                neobot_set_servo:\n                    'OUT1 ~ OUT3에 서보모터를 연결했을 때 0도 ~ 180도 범위 내에서 각도를 조절할 수 있습니다.',\n                neobot_set_output:\n                    'OUT1 ~ OUT3에 라이팅블록 및 전자회로를 연결했을 때 출력 전압을 설정할 수 있습니다.</br>0은 0V, 1 ~ 255는 2.4 ~ 4.96V의 전압을 나타냅니다.',\n                neobot_set_fnd: 'FND로 0~99 까지의 숫자를 표시할 수 있습니다.',\n                neobot_set_fnd_off: 'FND에 표시한 숫자를 끌 수 있습니다.',\n                neobot_play_note_for:\n                    '주파수 발진 방법을 이용해 멜로디에 반음 단위의 멜로디 음을 발생시킬 수 있습니다.',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_port_1: 'IN1',\n                neobot_port_2: 'IN2',\n                neobot_port_3: 'IN3',\n                neobot_port_4: 'IN4',\n                neobot_port_bat: '배터리',\n                neobot_port_remot: '리모컨',\n                neobot_color_white: '흰색',\n                neobot_color_red: '빨간색',\n                neobot_color_yellow: '노란색',\n                neobot_color_green: '초록색(연두색)',\n                neobot_color_blue: '파란색',\n                neobot_direction_forward: '앞으로',\n                neobot_direction_backward: '뒤로',\n                neobot_sound_silent: '무음',\n                neobot_sound_do: '도',\n                neobot_sound_do_shop: '도#',\n                neobot_sound_re: '레',\n                neobot_sound_re_shop: '레#',\n                neobot_sound_mi: '미',\n                neobot_sound_fa: '파',\n                neobot_sound_fa_shop: '파#',\n                neobot_sound_so: '솔',\n                neobot_sound_so_shop: '솔#',\n                neobot_sound_la: '라',\n                neobot_sound_la_shop: '라#',\n                neobot_sound_ti: '시',\n                neobot_sound_half_note: '2분 음표',\n                neobot_sound_quarter_note: '4분 음표',\n                neobot_sound_eighth_note: '8븐 음표',\n                neobot_sound_sixteenth_note: '16분 음표',\n                neobot_sensor_infrared: '적외선센서',\n                neobot_sensor_light: '빛센서',\n                neobot_sensor_sound: '소리센서',\n                neobot_compare_symbol1: '＝',\n                neobot_compare_symbol2: '＞',\n                neobot_compare_symbol3: '＜',\n                neobot_compare_symbol4: '≥',\n                neobot_compare_symbol5: '≤',\n                neobot_remote_btn_a: 'A',\n                neobot_remote_btn_b: 'B',\n                neobot_remote_btn_c: 'C',\n                neobot_remote_btn_d: 'D',\n                neobot_remote_btn_1: '1',\n                neobot_remote_btn_2: '2',\n                neobot_remote_btn_3: '3',\n                neobot_remote_btn_4: '4',\n                neobot_remote_btn_up: '▲',\n                neobot_remote_btn_down: '▼',\n                neobot_remote_btn_left: '◀',\n                neobot_remote_btn_right: '▶',\n                neobot_duration_cont: '계속',\n                neobot_duration_1s: '1초',\n                neobot_duration_2s: '2초',\n                neobot_duration_3s: '3초',\n                neobot_duration_4s: '4초',\n                neobot_duration_5s: '5초',\n                neobot_duration_6s: '6초',\n                neobot_duration_7s: '7초',\n                neobot_duration_8s: '8초',\n                neobot_duration_9s: '9초',\n                neobot_motor_both: '양쪽',\n                neobot_motor_left: '왼쪽',\n                neobot_motor_right: '오른쪽',\n                neobot_motor_move_forward: '전진',\n                neobot_motor_move_backward: '후진',\n                neobot_motor_move_left: '좌회전',\n                neobot_motor_move_right: '우회전',\n                neobot_motor_move_stop: '정지',\n                // modified string by cky 191205\n                neobot_servo_dir_1: '정방향',\n                neobot_servo_dir_2: '역방향',\n                // added by cky 191205\n                neobot_percent_10: '10%속도',\n                neobot_percent_20: '20%속도',\n                neobot_percent_30: '30%속도',\n                neobot_percent_40: '40%속도',\n                neobot_percent_50: '50%속도',\n                neobot_percent_60: '60%속도',\n                neobot_percent_70: '70%속도',\n                neobot_percent_80: '80%속도',\n                neobot_percent_90: '90%속도',\n                neobot_percent_100: '100%속도',\n\n                neobot_degree_0: '0도',\n                neobot_degree_5: '5도',\n                neobot_degree_10: '10도',\n                neobot_degree_15: '15도',\n                neobot_degree_20: '20도',\n                neobot_degree_25: '25도',\n                neobot_degree_30: '30도',\n                neobot_degree_35: '35도',\n                neobot_degree_40: '40도',\n                neobot_degree_45: '45도',\n                neobot_degree_50: '50도',\n                neobot_degree_55: '55도',\n                neobot_degree_60: '60도',\n                neobot_degree_65: '65도',\n                neobot_degree_70: '70도',\n                neobot_degree_75: '75도',\n                neobot_degree_80: '80도',\n                neobot_degree_85: '85도',\n                neobot_degree_90: '90도',\n                neobot_degree_95: '95도',\n                neobot_degree_100: '100도',\n                neobot_degree_105: '105도',\n                neobot_degree_110: '110도',\n                neobot_degree_115: '115도',\n                neobot_degree_120: '120도',\n                neobot_degree_125: '125도',\n                neobot_degree_130: '130도',\n                neobot_degree_135: '135도',\n                neobot_degree_140: '140도',\n                neobot_degree_145: '145도',\n                neobot_degree_150: '150도',\n                neobot_degree_155: '155도',\n                neobot_degree_160: '160도',\n                neobot_degree_165: '165도',\n                neobot_degree_170: '170도',\n                neobot_degree_175: '175도',\n                neobot_degree_180: '180도',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                neobot_turn_left: 'Rotate left motor %1 %2 %3',\n                neobot_stop_left: 'Stop left motor %1',\n                neobot_turn_right: 'Rotate right motor %1 %2 %3',\n                neobot_stop_right: 'Stop right motor %1',\n                neobot_run_motor: 'Run %1 motor for %2 secs',\n                neobot_servo_1:\n                    'Move the servo motor connected to SERVO1 to %2 with the speed of %1 %3',\n                neobot_servo_2:\n                    'Move the servo motor connected to SERVO2 to %2 with the speed of %1 %3',\n                neobot_set_sensor_value: '%1 value of the port to %2 %3',\n\n                neobot_sensor_value: '%1 value',\n                neobot_sensor_connect_external: 'the %2 value connected %1',\n\n                neobot_sensor_convert_scale:\n                    'the value that is changed %1 sensor value %2 ~%3 to %4 ~ %5',\n\n                neobot_compare_symbol: '%1',\n                neobot_decision_sensor_is_over: '%1 sensor value %2 %3',\n                neobot_decision_equal_with_sensor: 'being detected %2 by %1 color sensor',\n                neobot_remote_button: 'pressing button %1 of remote controller',\n\n                get_motor_speed: '%1',\n                neobot_left_motor: 'Rotate the left motor in %2 for speed %1 %3',\n                neobot_stop_left_motor: 'Stop the left motor %1',\n                neobot_right_motor: 'Rotate the right motor in %2 for speed %1 %3',\n                neobot_stop_right_motor: 'Stop right motor %1',\n                neobot_both_motor:\n                    'Rotate the left motor in %2 speed %1 & the right motor in %4 for speed %3 %5',\n                neobot_all_motor: 'Rotate both motors %2 speed %1 for %3 second(s) %4',\n                neobot_stop_all_motor: 'Stop both motors %1',\n                neobot_robot: 'Go %1 the robot %2',\n\n                neobot_output_led_type1: 'Turn on the LED connected %1 in %2 brightness for %3 %4',\n                neobot_output_led_on: 'Turn on the LED connected %1 %2',\n                neobot_output_led_off: 'Turn off the LED connected %1 %2',\n                neobot_set_output: 'Output %1 port value to %2 %3',\n\n                get_servo_degree: '%1',\n                neobot_servo_init: 'Reset the %1 servo motor %2',\n                neobot_servo_change_degree: 'Change servo angle : %1 %2 %3 %4 %5',\n                neobot_servo_rotate: 'Rotate the servo motor : %1 %2 %3 %4',\n                neobot_servo_stop: 'Stop the %1 servo motor %2',\n\n                neobot_play_note_for: 'Make a sound the melody %1 to %2 octave(s) as %3 %4',\n                neobot_play_note_with_sensor:\n                    'Play the melody as %2 ~ %3 value of %1 sensor in the controller %4',\n            },\n            Helper: {\n                neobot_sensor_value:\n                    'Indicates the input value from ports IN1 - IN3 and the battery information as number from 0 to 255.',\n                neobot_sensor_convert_scale:\n                    \"The expressed scale of the selected port's change of input value as the value of a particular scale can be adjusted.\",\n                neobot_left_motor:\n                    'Sets the wheel direction and speed of the motor connected to L motor port.',\n                neobot_stop_left_motor: 'Stops the motor connected to L motor port.',\n                neobot_right_motor:\n                    'Sets the wheel direction and speed of the motor connected to R motor port.',\n                neobot_stop_right_motor: 'Stops the motor connected to R motor port.',\n                neobot_all_motor:\n                    'The speed, time, and direction towards front, back, left and right, when connecting 2 motors to L and R motor ports can be set and used as wheels. ',\n                neobot_stop_all_motor: 'Stops the motor connected to both L and R motor ports.',\n                neobot_set_servo:\n                    'The angle within 0 - 180 degrees when connecting servo motor to OUT1 - OUT3 can be adjusted',\n                neobot_set_output:\n                    'The output voltage when connecting lighting block and electronic circuit to OUT1 - OUT3 can be set.</br>0 indicates 0V, and 1 ~ 255 indicates 2.4 ~ 4.96V.',\n                neobot_set_fnd: 'Numbers from 0 to 99 with FND can be indicated.',\n                neobot_set_fnd_off: 'Number indicated on FND can be turned off.',\n                neobot_play_note_for:\n                    'Notes in semitone units of the melody can be played by utilizing frequency oscillation. ',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_port_1: 'port1',\n                neobot_port_2: 'port2',\n                neobot_port_3: 'port3',\n                neobot_port_4: 'port4',\n                neobot_port_bat: 'battery',\n                neobot_port_remot: 'remote',\n                neobot_color_white: 'white',\n                neobot_color_red: 'red',\n                neobot_color_yellow: 'yellow',\n                neobot_color_green: 'green',\n                neobot_color_blue: 'blue',\n                neobot_direction_forward: 'forward',\n                neobot_direction_backward: 'backward',\n                neobot_sound_silent: 'silent',\n                neobot_sound_do: 'Do',\n                neobot_sound_do_shop: 'Do#',\n                neobot_sound_re: 'Re',\n                neobot_sound_re_shop: 'Re#',\n                neobot_sound_mi: 'Mi',\n                neobot_sound_fa: 'Fa',\n                neobot_sound_fa_shop: 'Fa#',\n                neobot_sound_so: 'So',\n                neobot_sound_so_shop: 'So#',\n                neobot_sound_la: 'La',\n                neobot_sound_la_shop: 'La#',\n                neobot_sound_ti: 'Ti',\n                neobot_sound_half_note: 'a half note',\n                neobot_sound_quarter_note: 'a quarter note',\n                neobot_sound_eighth_note: 'a eighth note',\n                neobot_sound_sixteenth_note: 'a sixteenth note',\n                neobot_sensor_infrared: 'IR sensor',\n                neobot_sensor_light: 'light sensor',\n                neobot_sensor_sound: 'sound sensor',\n                neobot_compare_symbol1: '＝',\n                neobot_compare_symbol2: '＞',\n                neobot_compare_symbol3: '＜',\n                neobot_compare_symbol4: '≥',\n                neobot_compare_symbol5: '≤',\n                neobot_remote_btn_a: 'A',\n                neobot_remote_btn_b: 'B',\n                neobot_remote_btn_c: 'C',\n                neobot_remote_btn_d: 'D',\n                neobot_remote_btn_1: '1',\n                neobot_remote_btn_2: '2',\n                neobot_remote_btn_3: '3',\n                neobot_remote_btn_4: '4',\n                neobot_remote_btn_up: '▲',\n                neobot_remote_btn_down: '▼',\n                neobot_remote_btn_left: '◀',\n                neobot_remote_btn_right: '▶',\n                neobot_duration_cont: 'constantly',\n                neobot_duration_1s: '1 second',\n                neobot_duration_2s: '2 seconds',\n                neobot_duration_3s: '3 seconds',\n                neobot_duration_4s: '4 seconds',\n                neobot_duration_5s: '5 seconds',\n                neobot_duration_6s: '6 seconds',\n                neobot_duration_7s: '7 seconds',\n                neobot_duration_8s: '8 seconds',\n                neobot_duration_9s: '9 seconds',\n                neobot_motor_both: 'both',\n                neobot_motor_left: 'left',\n                neobot_motor_right: 'right',\n                neobot_motor_move_forward: 'go forward',\n                neobot_motor_move_backward: 'go backward',\n                neobot_motor_move_left: 'turn Left',\n                neobot_motor_move_right: 'turn Right',\n                neobot_motor_move_stop: 'stop',\n                // modified string by cky 191205\n                neobot_servo_dir_1: 'forward',\n                neobot_servo_dir_2: 'backward',\n                // added by cky 191205\n                neobot_percent_10: '10% speed',\n                neobot_percent_20: '20% speed',\n                neobot_percent_30: '30% speed',\n                neobot_percent_40: '40% speed',\n                neobot_percent_50: '50% speed',\n                neobot_percent_60: '60% speed',\n                neobot_percent_70: '70% speed',\n                neobot_percent_80: '80% speed',\n                neobot_percent_90: '90% speed',\n                neobot_percent_100: '100% speed',\n\n                neobot_degree_0: '0 degree',\n                neobot_degree_5: '5 degrees',\n                neobot_degree_10: '10 degrees',\n                neobot_degree_15: '15 degrees',\n                neobot_degree_20: '20 degrees',\n                neobot_degree_25: '25 degrees',\n                neobot_degree_30: '30 degrees',\n                neobot_degree_35: '35 degrees',\n                neobot_degree_40: '40 degrees',\n                neobot_degree_45: '45 degrees',\n                neobot_degree_50: '50 degrees',\n                neobot_degree_55: '55 degrees',\n                neobot_degree_60: '60 degrees',\n                neobot_degree_65: '65 degrees',\n                neobot_degree_70: '70 degrees',\n                neobot_degree_75: '75 degrees',\n                neobot_degree_80: '80 degrees',\n                neobot_degree_85: '85 degrees',\n                neobot_degree_90: '90 degrees',\n                neobot_degree_95: '95 degrees',\n                neobot_degree_100: '100 degrees',\n                neobot_degree_105: '105 degrees',\n                neobot_degree_110: '110 degrees',\n                neobot_degree_115: '115 degrees',\n                neobot_degree_120: '120 degrees',\n                neobot_degree_125: '125 degrees',\n                neobot_degree_130: '130 degrees',\n                neobot_degree_135: '135 degrees',\n                neobot_degree_140: '140 degrees',\n                neobot_degree_145: '145 degrees',\n                neobot_degree_150: '150 degrees',\n                neobot_degree_155: '155 degrees',\n                neobot_degree_160: '160 degrees',\n                neobot_degree_165: '165 degrees',\n                neobot_degree_170: '170 degrees',\n                neobot_degree_175: '175 degrees',\n                neobot_degree_180: '180degrees',\n            },\n        }, //\n    };\n};\n\nEntry.Neobot.blockMenuBlocks = [\n    // class sensor\n    'neobot_sensor_value',\n    'neobot_sensor_connect_external',\n    'neobot_sensor_convert_scale',\n    // class decision\n    'neobot_decision_sensor_is_over',\n    'neobot_decision_equal_with_sensor',\n    // class remote\n    'neobot_remote_button',\n    // class motor\n    'neobot_left_motor',\n    'neobot_stop_left_motor',\n    'neobot_right_motor',\n    'neobot_stop_right_motor',\n    'neobot_both_motor',\n    'neobot_all_motor',\n    // removed by cky 190423\n    //'neobot_motor_with_sensor',\n    'neobot_stop_all_motor',\n    'neobot_robot',\n    // class output\n    'neobot_output_led_type1',\n    'neobot_output_led_on',\n    'neobot_output_led_off',\n    'neobot_set_output',\n    // class servo\n    'neobot_servo_init',\n    'neobot_servo_change_degree',\n    'neobot_servo_rotate',\n    'neobot_servo_stop',\n    // class note\n    'neobot_play_note_for',\n    'neobot_play_note_with_sensor',\n];\n\nEntry.Neobot.getBlocks = function () {\n    return {\n        //region neobot 네오봇\n        neobot_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_port_4, 'BAT'],\n                        [Lang.Blocks.neobot_port_remot, 'IR'],\n                        [Lang.Blocks.neobot_port_bat, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_value',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port];\n            },\n            syntax: { js: [], py: ['Neobot.sensor_value(%1)'] },\n        },\n\n        // un-used. use if required pluggable block.\n        neobot_compare_symbol: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_compare_symbol',\n            },\n            paramsKeyMap: {\n                SYMBOL: 0,\n            },\n            class: 'neobot_value',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                return script.getStringField('SYMBOL');\n            },\n        },\n\n        neobot_sensor_connect_external: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_sensor_infrared, '1'],\n                        [Lang.Blocks.neobot_sensor_light, '2'],\n                        [Lang.Blocks.neobot_sensor_sound, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_sensor_connect_external',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_value',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port];\n            },\n        },\n\n        neobot_sensor_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'neobot_sensor_convert_scale',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OMIN: 1,\n                OMAX: 2,\n                MIN: 3,\n                MAX: 4,\n            },\n            class: 'neobot_value',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var port = script.getStringField('PORT');\n                var value = Entry.hw.portData[port];\n                var omin = script.getNumberValue('OMIN', script);\n                var omax = script.getNumberValue('OMAX', script);\n                var min = script.getNumberValue('MIN', script);\n                var max = script.getNumberValue('MAX', script);\n\n                if (omin > omax) {\n                    var temp = omin;\n                    omin = omax;\n                    omax = temp;\n                }\n\n                if (min > max) {\n                    var temp = min;\n                    min = max;\n                    max = temp;\n                }\n\n                value -= omin;\n                value = value * ((max - min) / (omax - omin));\n                value += min;\n                value = Math.min(max, value);\n                value = Math.max(min, value);\n\n                return Math.round(value);\n            },\n        },\n\n        neobot_decision_sensor_is_over: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, 10],\n                type: 'neobot_decision_sensor_is_over',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                SYMBOL: 1,\n                VALUE: 2,\n            },\n            class: 'decision',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var symbol = script.getStringField('SYMBOL');\n                var value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                if (symbol == '=') {\n                    if (sensor == value) return true;\n                    else return false;\n                } else if (symbol == '>') {\n                    if (sensor > value) return true;\n                    else return false;\n                } else if (symbol == '<') {\n                    if (sensor < value) return true;\n                    else return false;\n                } else if (symbol == '>=') {\n                    if (sensor >= value) return true;\n                    else return false;\n                } else if (symbol == '<=') {\n                    if (sensor <= value) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        neobot_decision_equal_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_port_4, 'BAT'],\n                        [Lang.Blocks.neobot_port_remot, 'IR'],\n                        [Lang.Blocks.neobot_port_bat, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_color_white, 0],\n                        [Lang.Blocks.neobot_color_red, 1],\n                        [Lang.Blocks.neobot_color_yellow, 2],\n                        [Lang.Blocks.neobot_color_green, 3],\n                        [Lang.Blocks.neobot_color_blue, 4],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_decision_equal_with_sensor',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                COLOR: 1,\n            },\n            class: 'decision',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var color = script.getNumberField('COLOR');\n\n                if (sensor >= 10 && sensor <= 50) {\n                    if (color == 0) return true;\n                    else return false;\n                } else if (sensor >= 51 && sensor <= 90) {\n                    if (color == 1) return true;\n                    else return false;\n                } else if (sensor >= 91 && sensor <= 130) {\n                    if (color == 2) return true;\n                    else return false;\n                } else if (sensor >= 131 && sensor <= 170) {\n                    if (color == 3) return true;\n                    else return false;\n                } else if (sensor >= 171 && sensor <= 210) {\n                    if (color == 4) return true;\n                    else return false;\n                }\n                return false;\n            },\n            syntax: { js: [], py: ['Entry.neobot_equal_check()'] },\n        },\n        neobot_remote_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_remote_btn_a, '1'],\n                        [Lang.Blocks.neobot_remote_btn_b, '2'],\n                        [Lang.Blocks.neobot_remote_btn_c, '3'],\n                        [Lang.Blocks.neobot_remote_btn_d, '4'],\n                        [Lang.Blocks.neobot_remote_btn_1, '5'],\n                        [Lang.Blocks.neobot_remote_btn_2, '6'],\n                        [Lang.Blocks.neobot_remote_btn_3, '7'],\n                        [Lang.Blocks.neobot_remote_btn_4, '8'],\n                        [Lang.Blocks.neobot_remote_btn_up, '11'],\n                        [Lang.Blocks.neobot_remote_btn_down, '12'],\n                        [Lang.Blocks.neobot_remote_btn_left, '14'],\n                        [Lang.Blocks.neobot_remote_btn_right, '13'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_remote_button',\n            },\n            paramsKeyMap: {\n                KEY: 0,\n            },\n            class: 'remote',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var key = script.getNumberField('KEY');\n                var value = Entry.hw.portData['IR'];\n                if (key >= 5 && key <= 8) key -= 4;\n                if (key == value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        get_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function (sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: { js: [], py: ['%1get_motor_speed#'] },\n        },\n        neobot_left_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_direction_forward, '16'],\n                        [Lang.Blocks.neobot_direction_backward, '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'get_motor_speed',\n                        id: 'm111',\n                    },\n                    null,\n                ],\n                type: 'neobot_left_motor',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                SPEED: 1,\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var speed = Entry.parseNumber(script.getStringValue('SPEED'));\n                var direction = script.getNumberField('DIRECTION');\n\n                // added 210324\n                if (speed === '0') speed = 0;\n                speed = Math.max(speed, 0);\n                speed = Math.min(speed, 15);\n\n                Entry.hw.sendQueue['DCL'] = direction + speed;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Neobot.turn_left(%1, %2)'] },\n        },\n        neobot_stop_left_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_stop_left_motor',\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                Entry.hw.sendQueue['DCL'] = 0;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Neobot.stop_left()'] },\n        },\n        neobot_right_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_direction_forward, '16'],\n                        [Lang.Blocks.neobot_direction_backward, '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'get_motor_speed',\n                        id: 'm112',\n                    },\n                    null,\n                ],\n                type: 'neobot_right_motor',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                SPEED: 1,\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var speed = Entry.parseNumber(script.getStringValue('SPEED'));\n                var direction = script.getNumberField('DIRECTION');\n\n                // added 210324\n                if (speed === '0') speed = 0;\n                speed = Math.max(speed, 0);\n                speed = Math.min(speed, 15);\n\n                Entry.hw.sendQueue['DCR'] = speed + direction;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Neobot.turn_right(%1, %2)'] },\n        },\n        neobot_stop_right_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_stop_right_motor',\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                Entry.hw.sendQueue['DCR'] = 0;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Neobot.stop_right()'] },\n        },\n        neobot_both_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_direction_forward, '16'],\n                        [Lang.Blocks.neobot_direction_backward, '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_direction_forward, '16'],\n                        [Lang.Blocks.neobot_direction_backward, '32'],\n                    ],\n                    value: '16',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '16',\n                    {\n                        type: 'get_motor_speed',\n                        id: 'm113',\n                    },\n                    '16',\n                    {\n                        type: 'get_motor_speed',\n                        id: 'm114',\n                    },\n                    null,\n                ],\n                type: 'neobot_both_motor',\n            },\n            paramsKeyMap: {\n                DIRECTION_LEFT: 0,\n                SPEED_LEFT: 1,\n                DIRECTION_RIGHT: 2,\n                SPEED_RIGHT: 3,\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var speed_left = Entry.parseNumber(script.getStringValue('SPEED_LEFT'));\n                var direction_left = script.getNumberField('DIRECTION_LEFT');\n                var speed_right = Entry.parseNumber(script.getStringValue('SPEED_RIGHT'));\n                var direction_right = script.getNumberField('DIRECTION_RIGHT');\n\n                // added 210324\n                if (speed_left === '0') speed_left = 0;\n                speed_left = Math.max(speed_left, 0);\n                speed_left = Math.min(speed_left, 15);\n\n                if (speed_right === '0') speed_right = 0;\n                speed_right = Math.max(speed_right, 0);\n                speed_right = Math.min(speed_right, 15);\n\n                Entry.hw.sendQueue['DCL'] = speed_left + direction_left;\n                Entry.hw.sendQueue['DCR'] = speed_right + direction_right;\n                return script.callReturn();\n            },\n        },\n        neobot_all_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_direction_forward, '1'],\n                        [Lang.Blocks.neobot_direction_backward, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_duration_cont, '0'],\n                        [Lang.Blocks.neobot_duration_1s, '1'],\n                        [Lang.Blocks.neobot_duration_2s, '2'],\n                        [Lang.Blocks.neobot_duration_3s, '3'],\n                        [Lang.Blocks.neobot_duration_4s, '4'],\n                        [Lang.Blocks.neobot_duration_5s, '5'],\n                        [Lang.Blocks.neobot_duration_6s, '6'],\n                        [Lang.Blocks.neobot_duration_7s, '7'],\n                        [Lang.Blocks.neobot_duration_8s, '8'],\n                        [Lang.Blocks.neobot_duration_9s, '9'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '1',\n                    {\n                        type: 'get_motor_speed',\n                        id: 'm115',\n                    },\n                    '0',\n                    null,\n                ],\n                type: 'neobot_all_motor',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                SPEED: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    var speed = Entry.parseNumber(script.getStringValue('SPEED'));\n                    var direction = script.getNumberField('DIRECTION');\n                    var duration = script.getNumberField('DURATION');\n\n                    // added 210324\n                    if (speed === '0') speed = 0;\n                    speed = Math.max(speed, 0);\n                    speed = Math.min(speed, 15);\n\n                    switch (direction) {\n                        case 1:\n                            Entry.hw.sendQueue['DCL'] = 0x10 + speed;\n                            Entry.hw.sendQueue['DCR'] = 0x10 + speed;\n                            break;\n                        case 2:\n                            Entry.hw.sendQueue['DCL'] = 0x20 + speed;\n                            Entry.hw.sendQueue['DCR'] = 0x20 + speed;\n                            break;\n                    }\n\n                    if (duration == 0) return script.callReturn();\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, duration * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['DCL'] = 0;\n                    Entry.hw.sendQueue['DCR'] = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // removed by cky 190423\n        /*neobot_motor_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_motor_both, '1'],\n                        [Lang.Blocks.neobot_motor_left, '2'],\n                        [Lang.Blocks.neobot_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'neobot_motor_with_sensor',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                MIN_VALUE: 1,\n                MAX_VALUE: 2,\n                MOTOR: 3,\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var min = script.getNumberValue('MIN_VALUE', script);\n                var max = script.getNumberValue('MAX_VALUE', script);\n                var motor = script.getNumberField('MOTOR', script);\n                var sensorValue =  Entry.hw.portData[port];\n                var sectionUnit = (max - min) / 15;\n                var value = 0;\n\n                if(min > max\n                    || sensorValue > max\n                    || sensorValue < min) {\n                    return script.callReturn();\n                }\n\n                sensorValue = sensorValue - min;\n                value = Math.round(sensorValue / sectionUnit);\n\n                if(value > 15)\n                    value = 15;\n                else (value < 0)\n                    value = 0;\n\n                switch (motor) {\n                    case 1:\n                    Entry.hw.sendQueue['DCL'] = 0x10 + value;\n                    Entry.hw.sendQueue['DCR'] = 0x10 + value;\n                    break;\n                    case 2:\n                    Entry.hw.sendQueue['DCL'] = 0x10 + value;\n                    break;\n                    case 3:\n                    Entry.hw.sendQueue['DCR'] = 0x10 + value;\n                    break;\n                }\n            },\n        },*/\n        neobot_stop_all_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_stop_all_motor',\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                Entry.hw.sendQueue['DCL'] = 0;\n                Entry.hw.sendQueue['DCR'] = 0;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Neobot.run_motor(%1, %2, %3, %4)'] },\n        },\n        neobot_robot: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_motor_move_forward, '1'],\n                        [Lang.Blocks.neobot_motor_move_backward, '2'],\n                        [Lang.Blocks.neobot_motor_move_left, '3'],\n                        [Lang.Blocks.neobot_motor_move_right, '4'],\n                        [Lang.Blocks.neobot_motor_move_stop, '5'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_robot',\n            },\n            paramsKeyMap: {\n                MOVE: 0,\n            },\n            class: 'neobot_motor',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var move = script.getNumberField('MOVE');\n                switch (move) {\n                    case 1:\n                        Entry.hw.sendQueue['DCL'] = 0x10 + 10;\n                        Entry.hw.sendQueue['DCR'] = 0x10 + 10;\n                        break;\n                    case 2:\n                        Entry.hw.sendQueue['DCL'] = 0x20 + 10;\n                        Entry.hw.sendQueue['DCR'] = 0x20 + 10;\n                        break;\n                    case 3:\n                        Entry.hw.sendQueue['DCL'] = 0x20 + 5;\n                        Entry.hw.sendQueue['DCR'] = 0x10 + 5;\n                        break;\n                    case 4:\n                        Entry.hw.sendQueue['DCL'] = 0x10 + 5;\n                        Entry.hw.sendQueue['DCR'] = 0x20 + 5;\n                        break;\n                    case 5:\n                        Entry.hw.sendQueue['DCL'] = 0;\n                        Entry.hw.sendQueue['DCR'] = 0;\n                        break;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_output_led_type1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100%', '255'],\n                        ['90%', '230'],\n                        ['80%', '204'],\n                        ['70%', '179'],\n                        ['60%', '153'],\n                        ['50%', '128'],\n                        ['40%', '102'],\n                        ['30%', '77'],\n                        ['20%', '51'],\n                        ['10%', '26'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_duration_cont, '0'],\n                        [Lang.Blocks.neobot_duration_1s, '1'],\n                        [Lang.Blocks.neobot_duration_2s, '2'],\n                        [Lang.Blocks.neobot_duration_3s, '3'],\n                        [Lang.Blocks.neobot_duration_4s, '4'],\n                        [Lang.Blocks.neobot_duration_5s, '5'],\n                        [Lang.Blocks.neobot_duration_6s, '6'],\n                        [Lang.Blocks.neobot_duration_7s, '7'],\n                        [Lang.Blocks.neobot_duration_8s, '8'],\n                        [Lang.Blocks.neobot_duration_9s, '9'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'neobot_output_led_type1',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_output',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                if (!script.isStart) {\n                    var port = script.getStringField('PORT', script);\n                    var value = script.getNumberField('VALUE', script);\n                    var duration = script.getNumberField('DURATION', script);\n\n                    Entry.hw.sendQueue[port] = value;\n                    if (duration == 0) {\n                        return script.callReturn();\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function () {\n                        Entry.hw.sendQueue[port] = 0;\n                        script.timeFlag = 0;\n                    }, duration * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        neobot_output_led_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_output_led_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_output',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var port = script.getStringField('PORT', script);\n                Entry.hw.sendQueue[port] = 255;\n                return script.callReturn();\n            },\n        },\n        neobot_output_led_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_output_led_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_output',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var option = port;\n                Entry.hw.sendQueue[port] = 0;\n                return script.callReturn();\n            },\n        },\n        neobot_set_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_set_output',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'neobot_output',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                var option = port;\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n                Entry.hw.sendQueue[port] = value;\n                return script.callReturn();\n            },\n        },\n\n        // class note\n        neobot_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_sound_silent, '0'],\n                        [Lang.Blocks.neobot_sound_do, '1'],\n                        [Lang.Blocks.neobot_sound_do_shop, '2'],\n                        [Lang.Blocks.neobot_sound_re, '3'],\n                        [Lang.Blocks.neobot_sound_re_shop, '4'],\n                        [Lang.Blocks.neobot_sound_mi, '5'],\n                        [Lang.Blocks.neobot_sound_fa, '6'],\n                        [Lang.Blocks.neobot_sound_fa_shop, '7'],\n                        [Lang.Blocks.neobot_sound_so, '8'],\n                        [Lang.Blocks.neobot_sound_so_shop, '9'],\n                        [Lang.Blocks.neobot_sound_la, '10'],\n                        [Lang.Blocks.neobot_sound_la_shop, '11'],\n                        [Lang.Blocks.neobot_sound_ti, '12'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_sound_half_note, '2'],\n                        [Lang.Blocks.neobot_sound_quarter_note, '4'],\n                        [Lang.Blocks.neobot_sound_eighth_note, '8'],\n                        [Lang.Blocks.neobot_sound_sixteenth_note, '16'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '2', '4', null],\n                type: 'neobot_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_note',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    var note = script.getNumberField('NOTE', script);\n                    var octave = script.getNumberField('OCTAVE', script);\n                    var duration = script.getNumberField('DURATION', script);\n                    var value = note > 0 ? note + 12 * octave : 0;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    if (value > 65) {\n                        value = 65;\n                    }\n                    sq.SND = value;\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, (1 / duration) * 2000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SND'] = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Neobot.play_note(%1, %2, %3)'] },\n        },\n        neobot_play_note_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_port_remot, 'IR'],\n                        [Lang.Blocks.neobot_port_bat, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_play_note_with_sensor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                MIN_VALUE: 1,\n                MAX_VALUE: 2,\n                VALUE: 3,\n            },\n            class: 'neobot_note',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                var port = script.getStringField('PORT', script);\n                var value = Entry.hw.portData[port];\n                var omin = script.getNumberValue('MIN_VALUE', script);\n                var omax = script.getNumberValue('MAX_VALUE', script);\n                var min = 0;\n                var max = 72;\n\n                if (omin > omax) {\n                    var temp = omin;\n                    omin = omax;\n                    omax = temp;\n                }\n\n                if (min > max) {\n                    var temp = min;\n                    min = max;\n                    max = temp;\n                }\n\n                value -= omin;\n                value = value * ((max - min) / (omax - omin));\n                value += min;\n                value = Math.min(max, value);\n                value = Math.max(min, value);\n\n                value = Math.round(value);\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    if (value > 72) {\n                        value = 72;\n                    }\n                    sq.SND = value;\n                    setTimeout(function () {\n                        script.timeFlag = 0;\n                    }, (1 / 4) * 2000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SND'] = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['Neobot.play_note_with_sensor(%1, %2, %3)'],\n            },\n        },\n\n        // class servo\n        get_servo_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_degree_0, '0'],\n                        [Lang.Blocks.neobot_degree_5, '5'],\n                        [Lang.Blocks.neobot_degree_10, '10'],\n                        [Lang.Blocks.neobot_degree_15, '15'],\n                        [Lang.Blocks.neobot_degree_20, '20'],\n                        [Lang.Blocks.neobot_degree_25, '25'],\n                        [Lang.Blocks.neobot_degree_30, '30'],\n                        [Lang.Blocks.neobot_degree_35, '35'],\n                        [Lang.Blocks.neobot_degree_40, '40'],\n                        [Lang.Blocks.neobot_degree_45, '45'],\n                        [Lang.Blocks.neobot_degree_50, '50'],\n                        [Lang.Blocks.neobot_degree_55, '55'],\n                        [Lang.Blocks.neobot_degree_60, '60'],\n                        [Lang.Blocks.neobot_degree_65, '65'],\n                        [Lang.Blocks.neobot_degree_70, '70'],\n                        [Lang.Blocks.neobot_degree_75, '75'],\n                        [Lang.Blocks.neobot_degree_80, '80'],\n                        [Lang.Blocks.neobot_degree_85, '85'],\n                        [Lang.Blocks.neobot_degree_90, '90'],\n                        [Lang.Blocks.neobot_degree_95, '95'],\n                        [Lang.Blocks.neobot_degree_100, '100'],\n                        [Lang.Blocks.neobot_degree_105, '105'],\n                        [Lang.Blocks.neobot_degree_110, '110'],\n                        [Lang.Blocks.neobot_degree_115, '115'],\n                        [Lang.Blocks.neobot_degree_120, '120'],\n                        [Lang.Blocks.neobot_degree_125, '125'],\n                        [Lang.Blocks.neobot_degree_130, '130'],\n                        [Lang.Blocks.neobot_degree_135, '135'],\n                        [Lang.Blocks.neobot_degree_140, '140'],\n                        [Lang.Blocks.neobot_degree_145, '145'],\n                        [Lang.Blocks.neobot_degree_150, '150'],\n                        [Lang.Blocks.neobot_degree_155, '155'],\n                        [Lang.Blocks.neobot_degree_160, '160'],\n                        [Lang.Blocks.neobot_degree_165, '165'],\n                        [Lang.Blocks.neobot_degree_170, '170'],\n                        [Lang.Blocks.neobot_degree_175, '175'],\n                        [Lang.Blocks.neobot_degree_180, '180'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function (sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: { js: [], py: ['%1get_servo_degree#'] },\n        },\n        neobot_servo_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT1&2', 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_servo_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_servo',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                if (!script.isStart) {\n                    var port = script.getStringField('PORT', script);\n                    if (port == 'ALL') {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n\n                        Entry.hw.sendQueue['OUT1'] = 0xBA;\n                        Entry.hw.sendQueue['OUT2'] = 0xBA;\n\n                        setTimeout(function () {\n                            Entry.hw.sendQueue['OUT1'] = 0x01;\n                            Entry.hw.sendQueue['OUT2'] = 0x01;\n                            setTimeout(function () {\n                                script.timeFlag = 0;\n                            }, 100);\n                        }, 200);\n\n                    } else {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n\n                        Entry.hw.sendQueue[port] = 0xBA;\n                        setTimeout(function () {\n                            Entry.hw.sendQueue[port] = 0x01;\n                            setTimeout(function () {\n                                script.timeFlag = 0;\n                            }, 100);\n                        }, 200);\n                    }\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        // integrated by cky 191205 from neobot_servo_turn_typeX\n        neobot_servo_change_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT1&2', 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_percent_10, '9'],\n                        [Lang.Blocks.neobot_percent_20, '8'],\n                        [Lang.Blocks.neobot_percent_30, '7'],\n                        [Lang.Blocks.neobot_percent_40, '6'],\n                        [Lang.Blocks.neobot_percent_50, '5'],\n                        [Lang.Blocks.neobot_percent_60, '4'],\n                        [Lang.Blocks.neobot_percent_70, '3'],\n                        [Lang.Blocks.neobot_percent_80, '2'],\n                        [Lang.Blocks.neobot_percent_90, '1'],\n                        [Lang.Blocks.neobot_percent_100, '0'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_servo_degree',\n                        id: 'm211',\n                    },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'neobot_servo_change_degree',\n            },\n            paramsKeyMap: {\n                DEGREE: 0,\n                PORT: 1,\n                DIRECTION: 2,\n                SPEED: 3,\n            },\n            class: 'neobot_servo',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                if (!script.isStart) {\n                    var degree = Entry.parseNumber(script.getStringValue('DEGREE'));\n                    var port = script.getStringField('PORT', script);\n                    var direction = script.getNumberField('DIRECTION');\n                    var speed = script.getNumberField('SPEED');\n\n                    if (port == 'ALL') {\n                        switch (direction) {\n                            case 1:\n                                Entry.hw.sendQueue['OUT1'] = 0xBC;\n                                Entry.hw.sendQueue['OUT2'] = 0xBC;\n                                break;\n                            case 2:\n                                Entry.hw.sendQueue['OUT1'] = 0xBD;\n                                Entry.hw.sendQueue['OUT2'] = 0xBD;\n                                break;\n                        }\n\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(function () {\n                            // for speed\n                            Entry.hw.sendQueue['OUT1'] = 0xfa - speed;\n                            Entry.hw.sendQueue['OUT2'] = 0xfa - speed;\n                            setTimeout(function () {\n                                // for degree\n                                if (degree > 180) {\n                                    degree = 180;\n                                }\n                                if (degree < 0) {\n                                    degree = 0;\n                                }\n                                degree = degree + 0x01;\n                                degree *= 1;\n                                Entry.hw.sendQueue['OUT1'] = degree;\n                                Entry.hw.sendQueue['OUT2'] = degree;\n                                script.timeFlag = 0;\n                            }, 200);\n                        }, 200);\n                    } else {\n                        switch (direction) {\n                            case 1:\n                                Entry.hw.sendQueue[port] = 0xBC;\n                                break;\n                            case 2:\n                                Entry.hw.sendQueue[port] = 0xBD;\n                                break;\n                        }\n\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(function () {\n                            // for speed\n                            Entry.hw.sendQueue[port] = 0xfa - speed;\n                            setTimeout(function () {\n                                // for degree\n                                if (degree > 180) {\n                                    degree = 180;\n                                }\n                                if (degree < 0) {\n                                    degree = 0;\n                                }\n                                degree = degree + 0x01;\n                                degree *= 1;\n                                Entry.hw.sendQueue[port] = degree;\n                                script.timeFlag = 0;\n                            }, 200);\n                        }, 200);\n                    }\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        neobot_servo_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT1&2', 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_percent_10, '0'],\n                        [Lang.Blocks.neobot_percent_20, '1'],\n                        [Lang.Blocks.neobot_percent_30, '2'],\n                        [Lang.Blocks.neobot_percent_40, '3'],\n                        [Lang.Blocks.neobot_percent_50, '4'],\n                        [Lang.Blocks.neobot_percent_60, '5'],\n                        [Lang.Blocks.neobot_percent_70, '6'],\n                        [Lang.Blocks.neobot_percent_80, '7'],\n                        [Lang.Blocks.neobot_percent_90, '8'],\n                        [Lang.Blocks.neobot_percent_100, '9'],\n                    ],\n                    value: '9',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'neobot_servo_rotate',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'neobot_servo',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var direction = script.getNumberField('DIRECTION');\n                var speed = script.getNumberField('SPEED');\n\n                if (port == 'ALL') {\n                    switch (direction) {\n                        case 1:\n                            Entry.hw.sendQueue['OUT1'] = 0xC0 + (speed + 0x01);\n                            Entry.hw.sendQueue['OUT2'] = 0xC0 + (speed + 0x01);\n                            break;\n                        case 2:\n                            Entry.hw.sendQueue['OUT1'] = 0xD0 + (speed + 0x01);\n                            Entry.hw.sendQueue['OUT2'] = 0xD0 + (speed + 0x01);\n                            break;\n                    }\n                } else {\n                    switch (direction) {\n                        case 1:\n                            Entry.hw.sendQueue[port] = 0xC0 + (speed + 0x01);\n                            break;\n                        case 2:\n                            Entry.hw.sendQueue[port] = 0xD0 + (speed + 0x01);\n                            break;\n                    }\n                }\n                return script.callReturn();\n            },\n        },\n        neobot_servo_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT1&2', 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_servo_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_servo',\n            isNotFor: ['neobot'],\n            func: function (sprite, script) {\n                var port = script.getStringField('PORT', script);\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = 0xfe;\n                    Entry.hw.sendQueue['OUT2'] = 0xfe;\n                } else {\n                    Entry.hw.sendQueue[port] = 0xfe;\n                }\n                return script.callReturn();\n            },\n        },\n\n        /*   // deprecated by cky 191205\n          neobot_servo_turn_type1: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic',\n              statements: [],\n              params: [\n                  {\n                      type: 'Dropdown',\n                      options: [['OUT1', 'OUT1'], ['OUT2', 'OUT2'], ['OUT3', 'OUT3']],\n                      value: 'OUT1',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Dropdown',\n                      options: [\n                          [Lang.Blocks.neobot_servo_dir_1, '1'],\n                          [Lang.Blocks.neobot_servo_dir_2, '2'],\n                      ],\n                      value: '1',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Block',\n                      accept: 'string',\n                  },\n                  {\n                      type: 'Indicator',\n                      img: 'block_icon/hardware_icon.svg',\n                      size: 12,\n                  },\n              ],\n              events: {},\n              def: {\n                  params: [\n                      null,\n                      null,\n                      180,\n                      null,\n                  ],\n                  type: 'neobot_servo_turn_type1',\n              },\n              paramsKeyMap: {\n                  PORT: 0,\n                  DIRECTION: 1,\n                  DEGREE: 2\n              },\n              class: 'neobot_servo',\n              isNotFor: ['neobot'],\n              func: function(sprite, script) {\n                  if (!script.isStart) {\n                      var port = script.getStringField('PORT', script);\n                      var direction = script.getNumberField('DIRECTION');\n                      var value = script.getNumberValue('DEGREE');\n\n                      switch (direction) {\n                          case 1:\n                          Entry.hw.sendQueue[port] = 0xBC;\n                          break;\n                          case 2:\n                          Entry.hw.sendQueue[port] = 0xBD;\n                          break;\n                      }\n\n                      script.isStart = true;\n                      script.timeFlag = 1;\n                      setTimeout(function() {\n                          if(value > 180) {\n                              value = 180;\n                          }\n                          if (value < 0){\n                              value = 0;\n                          }\n                          value = value + 1;\n                          Entry.hw.sendQueue[port] = value;\n                          setTimeout(function() {\n                              script.timeFlag = 0;\n                          }, 1000);\n                      }, 200);\n                      return script;\n                  } else if (script.timeFlag == 1) {\n                      return script;\n                  } else {\n                      delete script.timeFlag;\n                      delete script.isStart;\n                      Entry.engine.isContinue = false;\n                      return script.callReturn();\n                  }\n              },\n          },\n          // deprecated by cky 191205\n          neobot_servo_turn_type2: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic',\n              statements: [],\n              params: [\n                  {\n                      type: 'Dropdown',\n                      options: [['OUT1', 'OUT1'], ['OUT2', 'OUT2'], ['OUT3', 'OUT3']],\n                      value: 'OUT1',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Block',\n                      accept: 'string',\n                  },\n                  {\n                      type: 'Indicator',\n                      img: 'block_icon/hardware_icon.svg',\n                      size: 12,\n                  },\n              ],\n              events: {},\n              def: {\n                  params: [\n                      null,\n                      180,\n                      null,\n                  ],\n                  type: 'neobot_servo_turn_type2',\n              },\n              paramsKeyMap: {\n                  PORT: 0,\n                  DEGREE: 1\n              },\n              class: 'neobot_servo',\n              isNotFor: ['neobot'],\n              func: function(sprite, script) {\n                  if (!script.isStart) {\n                      var port = script.getStringField('PORT', script);\n                      var value = script.getNumberValue('DEGREE');\n\n                      if(value > 0xB4) {\n                          value = 0xB4;\n                      }\n                      if (value < 0x00){\n                          value = 0x00;\n                      }\n                      value = value + 0x01;\n                      Entry.hw.sendQueue[port] = value;\n                      script.isStart = true;\n                      script.timeFlag = 1;\n                      setTimeout(function() {\n                          script.timeFlag = 0;\n                      }, 200);\n                      return script;\n                  } else if (script.timeFlag == 1) {\n                      return script;\n                  } else {\n                      delete script.timeFlag;\n                      delete script.isStart;\n                      Entry.engine.isContinue = false;\n                      return script.callReturn();\n                  }\n              },\n          },\n\n          // deprecated by cky 191205\n          neobot_servo_turn_type4: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic',\n              statements: [],\n              params: [\n                  {\n                      type: 'Dropdown',\n                      options: [['OUT1', 'OUT1'], ['OUT2', 'OUT2'], ['OUT3', 'OUT3']],\n                      value: 'OUT1',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Dropdown',\n                      options: [\n                          ['100%', '0'],\n                          ['90%', '1'],\n                          ['80%', '2'],\n                          ['70%', '3'],\n                          ['60%', '4'],\n                          ['50%', '5'],\n                          ['40%', '6'],\n                          ['30%', '7'],\n                          ['20%', '8'],\n                          ['10%', '9'],\n                      ],\n                      value: '0',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Indicator',\n                      img: 'block_icon/hardware_icon.svg',\n                      size: 12,\n                  },\n              ],\n              events: {},\n              def: {\n                  params: [\n                      null,\n                      null,\n                      null,\n                  ],\n                  type: 'neobot_servo_turn_type4',\n              },\n              paramsKeyMap: {\n                  PORT: 0,\n                  LEVEL: 1,\n              },\n              class: 'neobot_servo',\n              isNotFor: ['neobot'],\n              func: function(sprite, script) {\n                  if (!script.isStart) {\n                      var port = script.getStringField('PORT', script);\n                      var level = script.getNumberField('LEVEL');\n                      Entry.hw.sendQueue[port] = 0xFA - level;\n                      script.isStart = true;\n                      script.timeFlag = 1;\n                      setTimeout(function() {\n                          script.timeFlag = 0;\n                      }, 200);\n                      return script;\n                  } else if (script.timeFlag == 1) {\n                      return script;\n                  } else {\n                      delete script.timeFlag;\n                      delete script.isStart;\n                      Entry.engine.isContinue = false;\n                      return script.callReturn();\n                  }\n              },\n          },\n\n          // deprecated by cky 191205\n          neobot_servo_turn_type5: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic',\n              statements: [],\n              params: [\n                  {\n                      type: 'Dropdown',\n                      options: [['OUT1', 'OUT1'], ['OUT2', 'OUT2'], ['OUT3', 'OUT3']],\n                      value: 'OUT1',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Dropdown',\n                      options: [\n                          [Lang.Blocks.neobot_servo_dir_1, '1'],\n                          [Lang.Blocks.neobot_servo_dir_2, '2'],\n                      ],\n                      value: '1',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Dropdown',\n                      options: [\n                          ['100%', '0'],\n                          ['90%', '1'],\n                          ['80%', '2'],\n                          ['70%', '3'],\n                          ['60%', '4'],\n                          ['50%', '5'],\n                          ['40%', '6'],\n                          ['30%', '7'],\n                          ['20%', '8'],\n                          ['10%', '9'],\n                      ],\n                      value: '0',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Indicator',\n                      img: 'block_icon/hardware_icon.svg',\n                      size: 12,\n                  },\n              ],\n              events: {},\n              def: {\n                  params: [\n                      null,\n                      null,\n                      null,\n                      null,\n                  ],\n                  type: 'neobot_servo_turn_type5',\n              },\n              paramsKeyMap: {\n                  PORT: 0,\n                  DIRECTION: 1,\n                  LEVEL: 2,\n              },\n              class: 'neobot_servo',\n              isNotFor: ['neobot'],\n              func: function(sprite, script) {\n                  if (!script.isStart) {\n                      var port = script.getStringField('PORT', script);\n                      var direction = script.getNumberField('DIRECTION');\n                      var level = script.getNumberField('LEVEL');\n\n                      switch (direction) {\n                          case 1:\n                              Entry.hw.sendQueue[port] = 0xCA - level;\n                              break;\n                          case 2:\n                              Entry.hw.sendQueue[port] = 0xDA - level;\n                              break;\n                      }\n\n                      script.isStart = true;\n                      script.timeFlag = 1;\n                      setTimeout(function() {\n                          script.timeFlag = 0;\n                      }, 200);\n                      return script;\n                  } else if (script.timeFlag == 1) {\n                      return script;\n                  } else {\n                      delete script.timeFlag;\n                      delete script.isStart;\n                      Entry.engine.isContinue = false;\n                      return script.callReturn();\n                  }\n              },\n          },\n\n          // deprecated by cky 191205\n          neobot_servo_mode_manual: {\n              color: EntryStatic.colorSet.block.default.HARDWARE,\n              outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n              skeleton: 'basic',\n              statements: [],\n              params: [\n                  {\n                      type: 'Dropdown',\n                      options: [['OUT1', 'OUT1'], ['OUT2', 'OUT2'], ['OUT3', 'OUT3']],\n                      value: 'OUT1',\n                      fontSize: 11,\n                      bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                      arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                  },\n                  {\n                      type: 'Indicator',\n                      img: 'block_icon/hardware_icon.svg',\n                      size: 12,\n                  },\n              ],\n              events: {},\n              def: {\n                  params: [\n                      null,\n                      null,\n                  ],\n                  type: 'neobot_servo_mode_manual',\n              },\n              paramsKeyMap: {\n                  PORT: 0,\n              },\n              class: 'neobot_servo',\n              isNotFor: ['neobot'],\n              func: function(sprite, script) {\n                  if (!script.isStart) {\n                      var port = script.getStringField('PORT', script);\n\n                      Entry.hw.sendQueue[port] = 0x00;\n                      script.isStart = true;\n                      script.timeFlag = 1;\n                      setTimeout(function() {\n                          timeFlag = 0;\n                      }, 200);\n                      return script;\n                  } else if (script.timeFlag == 1) {\n                      return script;\n                  } else {\n                      delete script.timeFlag;\n                      delete script.isStart;\n                      Entry.engine.isContinue = false;\n                      return script.callReturn();\n                  }\n              },\n          }, */\n\n        //endregion neobot 네오봇\n    };\n};\n\nmodule.exports = Entry.Neobot;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neobot_game_theme.js",
    "content": "Entry.NeobotGameTheme = {\n    id: '5.4',\n    name: 'neobot_game_theme',\n    url: 'http://www.neobot.co.kr',\n    imageName: 'neobot_game_theme.png',\n    title: {\n        ko: '네오코딩 게임테마',\n        en: 'NEOCODING GameTheme',\n    },\n    LOCAL_MAP: [\n        'JoystickX',\n        'JoystickY',\n        'GyroX',\n        'GyroY',\n        'Acceleration',\n        'BtnPressEvent',\n        'JoystickPressEvent',\n        'JoystickMoveEvent',\n    ],\n    setZero: function() {\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neobot_game_theme.png',\n        width: 700,\n        height: 700,\n        listPorts: {\n            JoystickX: {\n                name: 'JoystickX',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            JoystickY: {\n                name: 'JoystickY',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            GyroX: {\n                name: 'GyroX',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            GyroY: {\n                name: 'GyroY',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            Acceleration: {\n                name: 'Accel',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            /* JoystickX: { \n                name: 'Joystick X', \n                type: 'input',\n                pos: { x: 200, y: 200 }\n            },\n            JoystickY: {\n                name: 'Joystick Y',\n                type: 'input', \n                pos: { x: 200, y: 200 } \n            },\n            GyroX: {\n                name: 'Gyro X', \n                type: 'input', \n                pos: { x: 400, y: 200 } \n            },\n            GyroY: {\n                name: 'Gyro Y', \n                type: 'input', \n                pos: { x: 400, y: 200 }\n            },\n            Acceleration: {\n                name: 'Accel', \n                type: 'input', \n                pos: { x: 500, y: 200 } \n            },\n            JoystickPressEvent: {\n                name: 'Joystick Press', \n                type: 'input', \n                pos: { x: 200, y: 500 } \n            },\n            JoystickMoveEvent: { \n                name: 'Joystick Move', \n                type: 'input', \n                pos: { x: 200, y: 500 } \n            },\n            BtnPressEvent: { \n                name: 'Button', \n                type: 'input', \n                pos: { x: 400, y: 500 } \n            }, */\n        },\n        mode: 'both',\n    },\n    isNumber: function(s) {\n        s += '';\n        s = s.replace(/^\\s*|\\s*$/g, '');\n        if (s == '' || isNaN(s)) return false;\n        return true;\n    },\n};\n\nEntry.NeobotGameTheme.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                // class neobot_value\n                neobot_gyro_value: '자이로 %1 값',\n                neobot_joystick_value: '조이스틱 %1 값',\n                neobot_crash_value: '가속값',\n                neobot_random_value: '%1 랜덤값',\n                // class neobot_judgement\n                neobot_judge_joystick_move: '조이스틱 컨트롤? %1',\n                neobot_judge_joystick_direction: '조이스틱 방향? %1',\n                neobot_judge_button: '%1 버튼 클릭?',\n                neobot_judge_gyro_direction_angle: '%1으로 기울었는가?',\n                neobot_judge_coord: '%1위치 %2 %3',\n                neobot_judge_crash: '가속값 %1 %2',\n                // class neobot_movement\n                neobot_locate: '%1위치로 %2이동하기%3',\n                neobot_look: '%1쪽 바라보기%2',\n\n                // dropdown\n                get_gyro_degree: '%1',\n                get_move_method: '%1',\n                get_number_type1: '%1',\n                get_number_type2: '%1',\n            },\n            Blocks: {\n                neobot_axis_x: 'X',\n                neobot_axis_y: 'Y',\n\n                neobot_joystick_move_1: '뒤에서 앞으로',\n                neobot_joystick_move_2: '밑에서 위로',\n                neobot_joystick_move_3: '아래 반바퀴',\n                neobot_joystick_move_4: '한 바퀴',\n\n                neobot_joystick_dir_right: '오른쪽',\n                neobot_joystick_dir_left: '왼쪽',\n                neobot_joystick_dir_up: '위',\n                neobot_joystick_dir_down: '아래',\n\n                neobot_button_a: 'A',\n                neobot_button_b: 'B',\n                neobot_button_c: 'C',\n\n                neobot_gyro_dir_left: '왼쪽',\n                neobot_gyro_dir_right: '오른쪽',\n                neobot_gyro_dir_front: '앞쪽',\n                neobot_gyro_dir_rear: '뒤쪽',\n\n                neobot_degree_0: '0',\n                neobot_degree_5: '5',\n                neobot_degree_10: '10',\n                neobot_degree_15: '15',\n                neobot_degree_20: '20',\n                neobot_degree_25: '25',\n                neobot_degree_30: '30',\n                neobot_degree_35: '35',\n                neobot_degree_40: '40',\n                neobot_degree_45: '45',\n                neobot_degree_50: '50',\n                neobot_degree_55: '55',\n                neobot_degree_60: '60',\n                neobot_degree_65: '65',\n                neobot_degree_70: '70',\n                neobot_degree_75: '75',\n                neobot_degree_80: '80',\n                neobot_degree_85: '85',\n                neobot_degree_90: '90',\n                neobot_degree_95: '95',\n                neobot_degree_100: '100',\n                neobot_degree_105: '105',\n                neobot_degree_110: '110',\n                neobot_degree_115: '115',\n                neobot_degree_120: '120',\n                neobot_degree_125: '125',\n                neobot_degree_130: '130',\n                neobot_degree_135: '135',\n                neobot_degree_140: '140',\n                neobot_degree_145: '145',\n                neobot_degree_150: '150',\n                neobot_degree_155: '155',\n                neobot_degree_160: '160',\n                neobot_degree_165: '165',\n                neobot_degree_170: '170',\n                neobot_degree_175: '175',\n                neobot_degree_180: '180',\n\n                neobot_joystick_x: '조이스틱 X',\n                neobot_joystick_y: '조이스틱 Y',\n                neobot_gyro_x: '자이로센서 X',\n                neobot_gyro_y: '자이로센서 Y',\n\n                neobot_compare_left_bigger: '>',\n                neobot_compare_equal: '=',\n                neobot_compare_right_bigger: '<',\n\n                neobot_joystick: '조이스틱',\n                neobot_gyro: '자이로센서',\n\n                neobot_realtime: '실시간',\n                neobot_from_distance: '거리대비',\n\n                neobot_joystick_coord: '조이스틱 위치',\n                neobot_gyro_coord: '자이로센서 위치',\n            },\n        },\n        en: {\n            template: {\n                // class neobot_value\n                neobot_gyro_value: 'Gyro sensor value %1',\n                neobot_joystick_value: 'Joystick position %1',\n                neobot_crash_value: 'Impact value',\n                neobot_random_value: 'Random position %1',\n                // class neobot_judgement // TODO translate english\n                neobot_judge_joystick_move: 'Moved the joystick? %1',\n                neobot_judge_joystick_direction: 'Joystick in the %1',\n                neobot_judge_button: 'Press the %1 button?',\n                neobot_judge_gyro_direction_angle: 'Is it tilted to %1',\n                neobot_judge_coord: 'The %1position %2 %3',\n                neobot_judge_crash: 'Impact value %1 %2',\n                // class neobot_movement\n                neobot_locate: 'Move to %1position %2 %3',\n                neobot_look: 'Looking at the %1 position %2',\n\n                // dropdown\n                get_gyro_degree: '%1',\n                get_move_method: '%1',\n                get_number_type1: '%1',\n                get_number_type2: '%1',\n            },\n            Blocks: {\n                neobot_axis_x: 'X',\n                neobot_axis_y: 'Y',\n\n                neobot_joystick_move_1: 'From back to front',\n                neobot_joystick_move_2: 'From bottom up',\n                neobot_joystick_move_3: 'Half turn down',\n                neobot_joystick_move_4: 'One rotation',\n\n                neobot_joystick_dir_right: 'right',\n                neobot_joystick_dir_left: 'left',\n                neobot_joystick_dir_up: 'up',\n                neobot_joystick_dir_down: 'down',\n\n                neobot_button_a: 'A',\n                neobot_button_b: 'B',\n                neobot_button_c: 'C',\n\n                neobot_gyro_dir_left: 'left',\n                neobot_gyro_dir_right: 'right',\n                neobot_gyro_dir_front: 'forward',\n                neobot_gyro_dir_rear: 'backward',\n\n                neobot_degree_0: '0',\n                neobot_degree_5: '5',\n                neobot_degree_10: '10',\n                neobot_degree_15: '15',\n                neobot_degree_20: '20',\n                neobot_degree_25: '25',\n                neobot_degree_30: '30',\n                neobot_degree_35: '35',\n                neobot_degree_40: '40',\n                neobot_degree_45: '45',\n                neobot_degree_50: '50',\n                neobot_degree_55: '55',\n                neobot_degree_60: '60',\n                neobot_degree_65: '65',\n                neobot_degree_70: '70',\n                neobot_degree_75: '75',\n                neobot_degree_80: '80',\n                neobot_degree_85: '85',\n                neobot_degree_90: '90',\n                neobot_degree_95: '95',\n                neobot_degree_100: '100',\n                neobot_degree_105: '105',\n                neobot_degree_110: '110',\n                neobot_degree_115: '115',\n                neobot_degree_120: '120',\n                neobot_degree_125: '125',\n                neobot_degree_130: '130',\n                neobot_degree_135: '135',\n                neobot_degree_140: '140',\n                neobot_degree_145: '145',\n                neobot_degree_150: '150',\n                neobot_degree_155: '155',\n                neobot_degree_160: '160',\n                neobot_degree_165: '165',\n                neobot_degree_170: '170',\n                neobot_degree_175: '175',\n                neobot_degree_180: '180',\n\n                neobot_joystick_x: 'joystick X',\n                neobot_joystick_y: 'joystick Y',\n                neobot_gyro_x: 'gyro sensor X',\n                neobot_gyro_y: 'gyro sensor Y',\n\n                neobot_compare_left_bigger: '>',\n                neobot_compare_equal: '=',\n                neobot_compare_right_bigger: '<',\n\n                neobot_joystick: 'joystick',\n                neobot_gyro: 'gyro sensor',\n\n                neobot_realtime: 'in real time',\n                neobot_from_distance: 'relative to distance',\n\n                neobot_joystick_coord: 'joystick position',\n                neobot_gyro_coord: 'gyro sensor position',\n            },\n        },\n    };\n};\n\nEntry.NeobotGameTheme.blockMenuBlocks = [\n    'neobot_gyro_value',\n    'neobot_joystick_value',\n    'neobot_crash_value',\n    'neobot_random_value',\n    'neobot_judge_joystick_move',\n    'neobot_judge_joystick_direction',\n    'neobot_judge_button',\n    'neobot_judge_gyro_direction_angle',\n    'neobot_judge_coord',\n    'neobot_judge_crash',\n    'neobot_locate',\n    'neobot_look',\n];\n\nEntry.NeobotGameTheme.getBlocks = function() {\n    return {\n        /**\n         *  Class neobot_value\n         */\n        neobot_gyro_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_axis_x, 'GyroX'],\n                        [Lang.Blocks.neobot_axis_y, 'GyroY'],\n                    ],\n                    value: 'GyroX',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_gyro_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_value',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return port == 'GyroX' ? Entry.hw.portData[port] : Entry.hw.portData[port];\n            },\n            syntax: { js: [], py: ['NeobotGameTheme.gyro_value(%1)'] },\n        },\n\n        neobot_joystick_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_axis_x, 'JoystickX'],\n                        [Lang.Blocks.neobot_axis_y, 'JoystickY'],\n                    ],\n                    value: 'JoystickX',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_joystick_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_value',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return port == 'JoystickX' ? Entry.hw.portData[port] : Entry.hw.portData[port];\n            },\n            syntax: { js: [], py: ['NeobotGameTheme.joystick_value(%1)'] },\n        },\n\n        neobot_crash_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            def: {\n                type: 'neobot_crash_value',\n            },\n            class: 'neobot_value',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                return Entry.hw.portData['Acceleration'];\n            },\n            syntax: { js: [], py: ['NeobotGameTheme.joystick_value(%1)'] },\n        },\n\n        neobot_random_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_axis_x, 'X'],\n                        [Lang.Blocks.neobot_axis_y, 'Y'],\n                    ],\n                    value: 'X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_random_value',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n            },\n            class: 'neobot_value',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var axis = script.getStringField('AXIS');\n                var randNum = 0;\n                if (axis == 'X') {\n                    randNum = Math.floor(Math.random() * 480) - 240;\n                } else if (axis == 'Y') {\n                    randNum = Math.floor(Math.random() * 270) - 135;\n                }\n                return randNum;\n            },\n            syntax: { js: [], py: ['NeobotGameTheme.random_value(%1)'] },\n        },\n\n        /**\n         *  Class neobot_judgement\n         */\n        neobot_judge_joystick_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_joystick_move_1, '1'],\n                        [Lang.Blocks.neobot_joystick_move_2, '2'],\n                        [Lang.Blocks.neobot_joystick_move_3, '3'],\n                        [Lang.Blocks.neobot_joystick_move_4, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_judge_joystick_move',\n            },\n            paramsKeyMap: {\n                MOVE: 0,\n            },\n            class: 'neobot_judgement',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var move = script.getNumberField('MOVE');\n                var value = Entry.hw.portData['JoystickMoveEvent'];\n\n                if (move == '1' && value == '1') return true;\n                else if (move == '2' && value == '3') return true;\n                else if (move == '3' && (value == '5' || value == '6')) return true;\n                else if (move == '4' && (value == '7' || value == '8')) return true;\n                else return false;\n            },\n        },\n\n        neobot_judge_joystick_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_joystick_dir_right, '3'],\n                        [Lang.Blocks.neobot_joystick_dir_left, '7'],\n                        [Lang.Blocks.neobot_joystick_dir_up, '1'],\n                        [Lang.Blocks.neobot_joystick_dir_down, '5'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_judge_joystick_direction',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            class: 'neobot_judgement',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var dir = script.getNumberField('DIR');\n                var value = Entry.hw.portData['JoystickPressEvent'];\n                return dir == value;\n            },\n        },\n\n        neobot_judge_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_button_a, '1'],\n                        [Lang.Blocks.neobot_button_b, '2'],\n                        [Lang.Blocks.neobot_button_c, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_judge_button',\n            },\n            paramsKeyMap: {\n                BTN: 0,\n            },\n            class: 'neobot_judgement',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var button = script.getNumberField('BTN');\n                var value = Entry.hw.portData['BtnPressEvent'];\n                return button == value;\n            },\n        },\n\n        // don't use\n        get_gyro_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_degree_0, '0'],\n                        [Lang.Blocks.neobot_degree_5, '5'],\n                        [Lang.Blocks.neobot_degree_10, '10'],\n                        [Lang.Blocks.neobot_degree_15, '15'],\n                        [Lang.Blocks.neobot_degree_20, '20'],\n                        [Lang.Blocks.neobot_degree_25, '25'],\n                        [Lang.Blocks.neobot_degree_30, '30'],\n                        [Lang.Blocks.neobot_degree_35, '35'],\n                        [Lang.Blocks.neobot_degree_40, '40'],\n                        [Lang.Blocks.neobot_degree_45, '45'],\n                        [Lang.Blocks.neobot_degree_50, '50'],\n                        [Lang.Blocks.neobot_degree_55, '55'],\n                        [Lang.Blocks.neobot_degree_60, '60'],\n                        [Lang.Blocks.neobot_degree_65, '65'],\n                        [Lang.Blocks.neobot_degree_70, '70'],\n                        [Lang.Blocks.neobot_degree_75, '75'],\n                        [Lang.Blocks.neobot_degree_80, '80'],\n                        [Lang.Blocks.neobot_degree_85, '85'],\n                        [Lang.Blocks.neobot_degree_90, '90'],\n                        [Lang.Blocks.neobot_degree_95, '95'],\n                        [Lang.Blocks.neobot_degree_100, '100'],\n                        [Lang.Blocks.neobot_degree_105, '105'],\n                        [Lang.Blocks.neobot_degree_110, '110'],\n                        [Lang.Blocks.neobot_degree_115, '115'],\n                        [Lang.Blocks.neobot_degree_120, '120'],\n                        [Lang.Blocks.neobot_degree_125, '125'],\n                        [Lang.Blocks.neobot_degree_130, '130'],\n                        [Lang.Blocks.neobot_degree_135, '135'],\n                        [Lang.Blocks.neobot_degree_140, '140'],\n                        [Lang.Blocks.neobot_degree_145, '145'],\n                        [Lang.Blocks.neobot_degree_150, '150'],\n                        [Lang.Blocks.neobot_degree_155, '155'],\n                        [Lang.Blocks.neobot_degree_160, '160'],\n                        [Lang.Blocks.neobot_degree_165, '165'],\n                        [Lang.Blocks.neobot_degree_170, '170'],\n                        [Lang.Blocks.neobot_degree_175, '175'],\n                        [Lang.Blocks.neobot_degree_180, '180'],\n                    ],\n                    value: '45',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: { js: [], py: ['%1get_gyro_degree#'] },\n        },\n\n        get_number_type1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['10', '10'],\n                        ['20', '20'],\n                        ['30', '30'],\n                        ['40', '40'],\n                        ['50', '50'],\n                        ['60', '60'],\n                        ['70', '70'],\n                        ['80', '80'],\n                        ['90', '90'],\n                        ['100', '100'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: { js: [], py: ['%1get_number_type1#'] },\n        },\n\n        get_number_type2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['10', '10'],\n                        ['20', '20'],\n                        ['30', '30'],\n                        ['40', '40'],\n                        ['50', '50'],\n                        ['60', '60'],\n                        ['70', '70'],\n                        ['80', '80'],\n                        ['90', '90'],\n                        ['100', '100'],\n                    ],\n                    value: '50',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: { js: [], py: ['%1get_number_type1#'] },\n        },\n\n        neobot_judge_gyro_direction_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_gyro_dir_left, '1'],\n                        [Lang.Blocks.neobot_gyro_dir_right, '2'],\n                        [Lang.Blocks.neobot_gyro_dir_front, '3'],\n                        [Lang.Blocks.neobot_gyro_dir_rear, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_judge_gyro_direction_angle',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            class: 'neobot_judgement',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var direction = script.getNumberField('DIR');\n                /* var degree = Entry.parseNumber(script.getStringValue('DEGREE')); */\n                var gyroX = Entry.hw.portData['GyroX'];\n                var gyroY = Entry.hw.portData['GyroY'];\n                var isTilted = false;\n\n                switch (direction) {\n                    case 1: // 왼쪽\n                        if (gyroX < -80) isTilted = true;\n                        break;\n                    case 2: // 오른쪽\n                        if (gyroX > 80) isTilted = true;\n                        break;\n                    case 3: // 앞\n                        if (gyroY > 45) isTilted = true;\n                        break;\n                    case 4: // 뒤\n                        if (gyroY < -45) isTilted = true;\n                        break;\n                }\n\n                return isTilted;\n            },\n        },\n\n        neobot_judge_coord: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_joystick_x, 'X'],\n                        [Lang.Blocks.neobot_joystick_y, 'Y'],\n                    ],\n                    value: 'X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_compare_left_bigger, '>'],\n                        [Lang.Blocks.neobot_compare_equal, '='],\n                        [Lang.Blocks.neobot_compare_right_bigger, '<'],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    '0',\n                    /* {\n                        type: 'get_number_type1',\n                        id: 'm200',\n                    }, */\n                ],\n                type: 'neobot_judge_coord',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n                COMPARE: 1,\n                VALUE: 2,\n            },\n            class: 'neobot_judgement',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var axis = script.getStringField('AXIS');\n                var compare = script.getStringField('COMPARE');\n                var targetValue = script.getNumberValue('VALUE');\n\n                var ret = false;\n                var portValue =\n                    axis == 'X' ? Entry.hw.portData['JoystickX'] : Entry.hw.portData['JoystickY'];\n                switch (compare) {\n                    case '>':\n                        if (portValue > targetValue) ret = true;\n                        else ret = false;\n                        break;\n                    case '=':\n                        if (portValue == targetValue) ret = true;\n                        else ret = false;\n                        break;\n                    case '<':\n                        if (portValue < targetValue) ret = true;\n                        else ret = false;\n                        break;\n                }\n\n                return ret;\n            },\n        },\n\n        neobot_judge_crash: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_compare_left_bigger, '>'],\n                        [Lang.Blocks.neobot_compare_equal, '='],\n                        [Lang.Blocks.neobot_compare_right_bigger, '<'],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'get_number_type2',\n                        id: 'm300',\n                    },\n                ],\n                type: 'neobot_judge_crash',\n            },\n            paramsKeyMap: {\n                COMPARE: 0,\n                VALUE: 1,\n            },\n            class: 'neobot_judgement',\n            isNotFor: ['neobot_game_theme'],\n            func: function(sprite, script) {\n                var compare = script.getStringField('COMPARE');\n                var targetValue = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                var ret = false;\n                var portValue = Entry.hw.portData['Acceleration'];\n                switch (compare) {\n                    case '>':\n                        if (portValue > targetValue) ret = true;\n                        else ret = false;\n                        break;\n                    case '=':\n                        if (portValue == targetValue) ret = true;\n                        else ret = false;\n                        break;\n                    case '<':\n                        if (portValue < targetValue) ret = true;\n                        else ret = false;\n                        break;\n                }\n\n                return ret;\n            },\n        },\n\n        get_move_method: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_realtime, 'Realtime'],\n                        [Lang.Blocks.neobot_from_distance, 'Distance'],\n                    ],\n                    value: 'Realtime',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n            syntax: { js: [], py: ['%1get_move_method#'] },\n        },\n\n        neobot_locate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_joystick, 'Joystick'],\n                        [Lang.Blocks.neobot_gyro, 'Gyro'],\n                        [Lang.Blocks.neobot_joystick_x, 'JX'],\n                        [Lang.Blocks.neobot_joystick_y, 'JY'],\n                        [Lang.Blocks.neobot_gyro_x, 'GX'],\n                        [Lang.Blocks.neobot_gyro_y, 'GY'],\n                    ],\n                    value: 'Joystick',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'get_move_method',\n                        id: 'm100',\n                    },\n                    null,\n                ],\n                type: 'neobot_locate',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                METHOD: 1,\n            },\n            class: 'neobot_movement',\n            isNotFor: ['neobot_game_theme'],\n            func(sprite, script) {\n                const targetDevice = script.getField('DEVICE', script);\n                const targetMethod = script.getStringValue('METHOD', script);\n\n                var targetX;\n                var targetY;\n\n                switch (targetDevice) {\n                    case 'Joystick':\n                        targetX = Entry.hw.portData['JoystickX'];\n                        targetY = Entry.hw.portData['JoystickY'];\n                        break;\n                    case 'Gyro':\n                        targetX = Entry.hw.portData['GyroX'];\n                        targetY = Entry.hw.portData['GyroY'];\n                        break;\n                    case 'JX':\n                        targetX = Entry.hw.portData['JoystickX'];\n                        targetY = sprite.getY();\n                        break;\n                    case 'JY':\n                        targetX = sprite.getX();\n                        targetY = Entry.hw.portData['JoystickY'];\n                        break;\n                    case 'GX':\n                        targetX = Entry.hw.portData['GyroX'];\n                        targetY = sprite.getY();\n                        break;\n                    case 'GY':\n                        targetX = sprite.getX();\n                        targetY = Entry.hw.portData['GyroY'];\n                        break;\n                }\n\n                /* var targetX = (targetDevice == 'Joystick' ?\n                 Entry.hw.portData['JoystickX'] : Entry.hw.portData['GyroX'] );\n                var targetY = (targetDevice == 'Joystick' \n                ? Entry.hw.portData['JoystickY'] : Entry.hw.portData['GyroY']\n                ); */\n\n                var distX = targetX - sprite.getX();\n                var distY = targetY - sprite.getY();\n\n                const isNumber = Entry.NeobotGameTheme.isNumber(targetMethod);\n                // 드롭다운 제거 후 별도 숫자, 센서 값 등을 입력한 경우\n                if (isNumber) {\n                    var dist = Math.sqrt(Math.pow(distX, 2) + Math.pow(distY, 2));\n                    if (dist > Number(targetMethod)) {\n                        // move direction\n                        var angle;\n                        if (distX === 0 && distY === 0) {\n                            angle = sprite.getDirection() + sprite.getRotation();\n                        } else if (distX >= 0) {\n                            angle = (-Math.atan(distY / distX) / Math.PI) * 180 + 90;\n                        } else {\n                            angle = (-Math.atan(distY / distX) / Math.PI) * 180 + 270;\n                        }\n                        sprite.setX(\n                            sprite.getX() +\n                                Number(targetMethod) * Math.cos(((angle - 90) / 180) * Math.PI)\n                        );\n                        sprite.setY(\n                            sprite.getY() -\n                                Number(targetMethod) * Math.sin(((angle - 90) / 180) * Math.PI)\n                        );\n                    } else {\n                        sprite.setX(targetX);\n                        sprite.setY(targetY);\n                    }\n                    return script.callReturn();\n                } else {\n                    // 드롭다운 값을 선택한 경우\n                    if (targetMethod == 'Distance') {\n                        sprite.setX(sprite.getX() + distX / 50);\n                        sprite.setY(sprite.getY() + distY / 50);\n                        return script.callReturn();\n                    } else {\n                        sprite.setX(targetX);\n                        sprite.setY(targetY);\n                        /* if (sprite.brush && !sprite.brush.stop) {\n                            sprite.brush.lineTo(sprite.getX(), sprite.getY() * -1);\n                        } */\n                        return script.callReturn();\n                    }\n                } // end else\n            }, // end func\n        },\n\n        neobot_look: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_joystick_coord, 'Joystick'],\n                        [Lang.Blocks.neobot_gyro_coord, 'Gyro'],\n                    ],\n                    value: 'Joystick',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_look',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'neobot_movement',\n            isNotFor: ['neobot_game_theme'],\n            func(sprite, script) {\n                const targetDevice = script.getField('DEVICE', script);\n                var targetX =\n                    targetDevice == 'Joystick'\n                        ? Entry.hw.portData['JoystickX']\n                        : Entry.hw.portData['GyroX'];\n                var targetY =\n                    targetDevice == 'Joystick'\n                        ? Entry.hw.portData['JoystickY']\n                        : Entry.hw.portData['GyroY'];\n                const spriteX = sprite.getX();\n                const spriteY = sprite.getY();\n                let deltaX = targetX - spriteX;\n                let deltaY = targetY - spriteY;\n                let value;\n\n                if (deltaX === 0 && deltaY === 0) {\n                    value = sprite.getDirection() + sprite.getRotation();\n                } else if (deltaX >= 0) {\n                    value = (-Math.atan(deltaY / deltaX) / Math.PI) * 180 + 90;\n                } else {\n                    value = (-Math.atan(deltaY / deltaX) / Math.PI) * 180 + 270;\n                }\n                if (this.entity.parent.getRotateMethod() === 'free') {\n                    const nativeDirection = sprite.getDirection() + sprite.getRotation();\n                    sprite.setRotation(sprite.getRotation() + value - nativeDirection);\n                } else {\n                    sprite.setDirection(value);\n                }\n                return script.callReturn();\n            },\n        },\n    }; // end getBlocks\n};\n\nmodule.exports = Entry.NeobotGameTheme;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neobot_purple.js",
    "content": "'use strict';\n\nEntry.NeobotPurple = {\n    id: '5.5',\n    name: 'neobot_purple',\n    url: 'http://www.neobot.co.kr',\n    imageName: 'neobot_purple.png',\n    title: {\n        ko: 'NEW 네오봇 Purple',\n        en: 'NEW NEOBOT Purple',\n    },\n    LOCAL_MAP: ['IN1', 'IN2', 'IN3', 'IR', 'BAT'],\n    REMOTE_MAP: ['OUT1', 'OUT2', 'OUT3', 'DCR', 'DCL', 'SND', 'FND', 'OPT'],\n    setZero: function() {\n        for (var port in Entry.NeobotPurple.REMOTE_MAP) {\n            Entry.hw.sendQueue[Entry.NeobotPurple.REMOTE_MAP[port]] = 0;\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neobot_purple.png',\n        width: 700,\n        height: 700,\n        listPorts: {\n            IR: { name: 'IR', type: 'input', pos: { x: 0, y: 0 } },\n            BAT: { name: 'BAT', type: 'input', pos: { x: 0, y: 0 } },\n            SND: { name: 'SND', type: 'output', pos: { x: 0, y: 0 } },\n            FND: { name: 'FND', type: 'output', pos: { x: 0, y: 0 } },\n        },\n        ports: {\n            IN1: { name: 'IN1', type: 'input', pos: { x: 270, y: 170 } },\n            IN2: { name: 'IN2', type: 'input', pos: { x: 325, y: 170 } },\n            IN3: { name: 'IN3', type: 'input', pos: { x: 325, y: 530 } },\n            DCL: { name: 'L-Motor', type: 'output', pos: { x: 270, y: 530 } },\n            DCR: { name: 'R-Motor', type: 'output', pos: { x: 435, y: 530 } },\n            OUT1: { name: 'OUT1', type: 'output', pos: { x: 380, y: 170 } },\n            OUT2: { name: 'OUT2', type: 'output', pos: { x: 435, y: 170 } },\n            OUT3: { name: 'OUT3', type: 'output', pos: { x: 380, y: 530 } },\n        },\n        mode: 'both',\n    },\n    log_to_console: false,\n};\n\nEntry.NeobotPurple.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                // sensor\n                neobot_purple_sensor_title: '센서',\n                neobot_purple_sensor_value: '%1',\n                neobot_purple_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환',\n                neobot_purple_decision_sensor_is_over: '%1 %2 %3',\n                neobot_purple_decision_equal_with_sensor: '%1 컬러가 %2',\n                neobot_purple_decision_sensor_angle: '%1 각도 %2 %3',\n                neobot_purple_remote_button: '리모컨 버튼 %1 을 누름',\n\n                // LED\n                neobot_purple_led_title: 'LED',\n                neobot_purple_arg_led_duration: '%1',\n                neobot_purple_led_on: 'LED 켜기   %1 %2 %3 %4',\n                neobot_purple_output_led_off: '%1 LED 끄기 %2',\n                neobot_purple_led_brightness_with_sensor: '%1 로 %2 LED 제어 %3',\n                neobot_purple_color_led_on: '%1 컬러LED 켜기   R %2 G %3 B %4 %5',\n\n                // output\n                neobot_purple_output_title: '출력',\n                neobot_purple_set_output: '%1 에 %2 값 출력하기 %3',\n\n                // motor\n                neobot_purple_motor_title: '회전모터',\n                neobot_purple_robot: '로봇 %1 %2',\n                neobot_purple_motor_start: '모터 회전하기   %1 %2 %3 %4 %5',\n                neobot_purple_motor_stop: '%1 모터 멈추기 %2',\n                neobot_purple_arg_motor_speed: '%1',\n                neobot_purple_arg_motor_duration: '%1',\n\n                // melody\n                neobot_purple_buzzer_title: '버저',\n                neobot_purple_play_note_for: '버저 울리기   옥타브: %2 음: %1 길이: %3 %4',\n                neobot_purple_melody_play_with_sensor: '%1 센서로 버저 울리기 %2',\n                neobot_purple_melody_stop: '버저 멈추기 %1',\n\n                // servo\n                neobot_purple_servo_title: '서보모터',\n                get_servo_degree: '%1',\n                neobot_purple_servo_init: '%1 서보모터 리셋 %2',\n                neobot_purple_servo_rotate: '서보모터 회전하기   %1 %2 %3 %4',\n                neobot_purple_servo_stop: '%1 서보모터 멈추기 %2',\n                neobot_purple_servo_change_degree: '서보모터 각도 바꾸기   %2 %3 %4 %1 %5',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_purple_port_1: 'IN1',\n                neobot_purple_port_2: 'IN2',\n                neobot_purple_port_3: 'IN3',\n                neobot_purple_port_4: 'IN4',\n                neobot_purple_port_12: 'IN1 & IN2',\n                neobot_purple_port_bat: '배터리',\n                neobot_purple_port_remot: '리모컨',\n                neobot_purple_color_white: '흰색',\n                neobot_purple_color_red: '빨강',\n                neobot_purple_color_yellow: '노랑',\n                neobot_purple_color_green: '녹색',\n                neobot_purple_color_blue: '파랑',\n                neobot_purple_direction_forward: '앞으로',\n                neobot_purple_direction_backward: '뒤로',\n                neobot_purple_sound_silent: '무음',\n                neobot_purple_sound_do: '도',\n                neobot_purple_sound_do_shop: '도#',\n                neobot_purple_sound_re: '레',\n                neobot_purple_sound_re_shop: '레#',\n                neobot_purple_sound_mi: '미',\n                neobot_purple_sound_fa: '파',\n                neobot_purple_sound_fa_shop: '파#',\n                neobot_purple_sound_so: '솔',\n                neobot_purple_sound_so_shop: '솔#',\n                neobot_purple_sound_la: '라',\n                neobot_purple_sound_la_shop: '라#',\n                neobot_purple_sound_ti: '시',\n                neobot_purple_sound_half_note: '2분 음표',\n                neobot_purple_sound_quarter_note: '4분 음표',\n                neobot_purple_sound_eighth_note: '8분 음표',\n                neobot_purple_sound_sixteenth_note: '16분 음표',\n                neobot_purple_sensor_infrared: '적외선센서',\n                neobot_purple_sensor_light: '빛센서',\n                neobot_purple_sensor_sound: '소리센서',\n                neobot_purple_compare_symbol1: '＝',\n                neobot_purple_compare_symbol2: '＞',\n                neobot_purple_compare_symbol3: '＜',\n                neobot_purple_compare_symbol4: '≥',\n                neobot_purple_compare_symbol5: '≤',\n                neobot_purple_remote_btn_a: 'A',\n                neobot_purple_remote_btn_b: 'B',\n                neobot_purple_remote_btn_c: 'C',\n                neobot_purple_remote_btn_d: 'D',\n                neobot_purple_remote_btn_1: '1',\n                neobot_purple_remote_btn_2: '2',\n                neobot_purple_remote_btn_3: '3',\n                neobot_purple_remote_btn_4: '4',\n                neobot_purple_remote_btn_up: '▲',\n                neobot_purple_remote_btn_down: '▼',\n                neobot_purple_remote_btn_left: '◀',\n                neobot_purple_remote_btn_right: '▶',\n                neobot_purple_duration_cont: '계속',\n                neobot_purple_duration_1s: '1초',\n                neobot_purple_duration_2s: '2초',\n                neobot_purple_duration_3s: '3초',\n                neobot_purple_duration_4s: '4초',\n                neobot_purple_duration_5s: '5초',\n                neobot_purple_duration_6s: '6초',\n                neobot_purple_duration_7s: '7초',\n                neobot_purple_duration_8s: '8초',\n                neobot_purple_duration_9s: '9초',\n                neobot_purple_motor_both: '양쪽',\n                neobot_purple_motor_left: '왼쪽',\n                neobot_purple_motor_right: '오른쪽',\n                neobot_purple_motor_move_forward: '전진',\n                neobot_purple_motor_move_backward: '후진',\n                neobot_purple_motor_move_left: '좌회전',\n                neobot_purple_motor_move_right: '우회전',\n                neobot_purple_motor_move_stop: '정지',\n\n                neobot_purple_servo_dir_1: '정방향',\n                neobot_purple_servo_dir_2: '역방향',\n\n                neobot_purple_percent_10: '10%속도',\n                neobot_purple_percent_20: '20%속도',\n                neobot_purple_percent_30: '30%속도',\n                neobot_purple_percent_40: '40%속도',\n                neobot_purple_percent_50: '50%속도',\n                neobot_purple_percent_60: '60%속도',\n                neobot_purple_percent_70: '70%속도',\n                neobot_purple_percent_80: '80%속도',\n                neobot_purple_percent_90: '90%속도',\n                neobot_purple_percent_100: '100%속도',\n\n                neobot_purple_angle_0: '0도',\n                neobot_purple_angle_5: '5도',\n                neobot_purple_angle_10: '10도',\n                neobot_purple_angle_15: '15도',\n                neobot_purple_angle_20: '20도',\n                neobot_purple_angle_25: '25도',\n                neobot_purple_angle_30: '30도',\n                neobot_purple_angle_35: '35도',\n                neobot_purple_angle_40: '40도',\n                neobot_purple_angle_45: '45도',\n                neobot_purple_angle_50: '50도',\n                neobot_purple_angle_55: '55도',\n                neobot_purple_angle_60: '60도',\n                neobot_purple_angle_65: '65도',\n                neobot_purple_angle_70: '70도',\n                neobot_purple_angle_75: '75도',\n                neobot_purple_angle_80: '80도',\n                neobot_purple_angle_85: '85도',\n                neobot_purple_angle_90: '90도',\n                neobot_purple_angle_95: '95도',\n                neobot_purple_angle_100: '100도',\n                neobot_purple_angle_105: '105도',\n                neobot_purple_angle_110: '110도',\n                neobot_purple_angle_115: '115도',\n                neobot_purple_angle_120: '120도',\n                neobot_purple_angle_125: '125도',\n                neobot_purple_angle_130: '130도',\n                neobot_purple_angle_135: '135도',\n                neobot_purple_angle_140: '140도',\n                neobot_purple_angle_145: '145도',\n                neobot_purple_angle_150: '150도',\n                neobot_purple_angle_155: '155도',\n                neobot_purple_angle_160: '160도',\n                neobot_purple_angle_165: '165도',\n                neobot_purple_angle_170: '170도',\n                neobot_purple_angle_175: '175도',\n                neobot_purple_angle_180: '180도',\n\n                neobot_purple_out_all: '모든',\n                neobot_purple_direction_left: '왼쪽으로',\n                neobot_purple_direction_right: '오른쪽으로',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                // sensor\n                neobot_purple_sensor_title: 'Sensor',\n                neobot_purple_sensor_value: '%1',\n                neobot_purple_sensor_convert_scale:\n                    \"%1 's changed value   range: %2 ~ %3 conversion: %4 ~ %5\",\n                neobot_purple_decision_sensor_is_over: '%1 %2 %3',\n                neobot_purple_decision_equal_with_sensor: \"%1 's color is %2\",\n                neobot_purple_decision_sensor_angle: '%1 angle %2 %3',\n                neobot_purple_remote_button: 'pressing button %1 of remote controller',\n\n                // LED\n                neobot_purple_led_title: 'LED',\n                neobot_purple_arg_led_duration: '%1',\n                neobot_purple_led_on: 'Turn on the LED    %1 %2 %3 %4',\n                neobot_purple_output_led_off: 'Turn off the %1 LED %2',\n                neobot_purple_led_brightness_with_sensor:\n                    \"Control %2 LED's brightness with %1 sensor %3\",\n                neobot_purple_color_led_on: 'Turn on the %1 color LED   R %2 G %3 B %4 %5',\n\n                // output\n                neobot_purple_output_title: 'Set output',\n                neobot_purple_set_output: 'Output %2 value to %1 port %3',\n\n                // motor\n                neobot_purple_motor_title: 'Motor',\n                neobot_purple_robot: 'Robot %1 %2',\n                neobot_purple_motor_start: 'Motor operation   %1 %2 %3 %4 %5',\n                neobot_purple_motor_stop: 'Stop the %1 motor(s) %2',\n                neobot_purple_arg_motor_speed: '%1',\n                neobot_purple_arg_motor_duration: '%1',\n\n                // melody\n                neobot_purple_buzzer_title: 'Buzzer',\n                neobot_purple_play_note_for: 'Buzzer   octave: %1 scale: %2 note: %3 %4',\n                neobot_purple_melody_play_with_sensor: 'Buzzer rings by %1 sensor value %2',\n                neobot_purple_melody_stop: 'Stop the buzzer %1',\n\n                // servo\n                neobot_purple_servo_title: 'Servo motor',\n                neobot_purple_servo_init: 'Reset the %1 servo motor %2',\n                neobot_purple_servo_rotate: 'Rotate the servo motor   %1 %2 %3 %4',\n                neobot_purple_servo_stop: 'Stop the %1 servo motor %2',\n                neobot_purple_servo_change_degree: 'Change servo angle   %1 %2 %3 %4 %5',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_purple_port_1: 'IN1',\n                neobot_purple_port_2: 'IN2',\n                neobot_purple_port_3: 'IN3',\n                neobot_purple_port_4: 'IN4',\n                neobot_purple_port_12: 'IN1 & IN2',\n                neobot_purple_port_bat: 'battery',\n                neobot_purple_port_remot: 'remote',\n                neobot_purple_color_white: 'white',\n                neobot_purple_color_red: 'red',\n                neobot_purple_color_yellow: 'yellow',\n                neobot_purple_color_green: 'green',\n                neobot_purple_color_blue: 'blue',\n                neobot_purple_direction_forward: 'forward',\n                neobot_purple_direction_backward: 'backward',\n                neobot_purple_sound_silent: 'silent',\n                neobot_purple_sound_do: 'Do',\n                neobot_purple_sound_do_shop: 'Do#',\n                neobot_purple_sound_re: 'Re',\n                neobot_purple_sound_re_shop: 'Re#',\n                neobot_purple_sound_mi: 'Mi',\n                neobot_purple_sound_fa: 'Fa',\n                neobot_purple_sound_fa_shop: 'Fa#',\n                neobot_purple_sound_so: 'So',\n                neobot_purple_sound_so_shop: 'So#',\n                neobot_purple_sound_la: 'La',\n                neobot_purple_sound_la_shop: 'La#',\n                neobot_purple_sound_ti: 'Si',\n                neobot_purple_sound_half_note: 'a half note',\n                neobot_purple_sound_quarter_note: 'a quarter note',\n                neobot_purple_sound_eighth_note: 'a eighth note',\n                neobot_purple_sound_sixteenth_note: 'a sixteenth note',\n                neobot_purple_sensor_infrared: 'IR sensor',\n                neobot_purple_sensor_light: 'light sensor',\n                neobot_purple_sensor_sound: 'sound sensor',\n                neobot_purple_compare_symbol1: '＝',\n                neobot_purple_compare_symbol2: '＞',\n                neobot_purple_compare_symbol3: '＜',\n                neobot_purple_compare_symbol4: '≥',\n                neobot_purple_compare_symbol5: '≤',\n                neobot_purple_remote_btn_a: 'A',\n                neobot_purple_remote_btn_b: 'B',\n                neobot_purple_remote_btn_c: 'C',\n                neobot_purple_remote_btn_d: 'D',\n                neobot_purple_remote_btn_1: '1',\n                neobot_purple_remote_btn_2: '2',\n                neobot_purple_remote_btn_3: '3',\n                neobot_purple_remote_btn_4: '4',\n                neobot_purple_remote_btn_up: '▲',\n                neobot_purple_remote_btn_down: '▼',\n                neobot_purple_remote_btn_left: '◀',\n                neobot_purple_remote_btn_right: '▶',\n                neobot_purple_duration_cont: 'constantly',\n                neobot_purple_duration_1s: '1 second',\n                neobot_purple_duration_2s: '2 seconds',\n                neobot_purple_duration_3s: '3 seconds',\n                neobot_purple_duration_4s: '4 seconds',\n                neobot_purple_duration_5s: '5 seconds',\n                neobot_purple_duration_6s: '6 seconds',\n                neobot_purple_duration_7s: '7 seconds',\n                neobot_purple_duration_8s: '8 seconds',\n                neobot_purple_duration_9s: '9 seconds',\n                neobot_purple_motor_both: 'both',\n                neobot_purple_motor_left: 'left',\n                neobot_purple_motor_right: 'right',\n                neobot_purple_motor_move_forward: 'go forward',\n                neobot_purple_motor_move_backward: 'go backward',\n                neobot_purple_motor_move_left: 'turn Left',\n                neobot_purple_motor_move_right: 'turn Right',\n                neobot_purple_motor_move_stop: 'stop',\n\n                neobot_purple_servo_dir_1: 'forward',\n                neobot_purple_servo_dir_2: 'backward',\n\n                neobot_purple_percent_10: '10% speed',\n                neobot_purple_percent_20: '20% speed',\n                neobot_purple_percent_30: '30% speed',\n                neobot_purple_percent_40: '40% speed',\n                neobot_purple_percent_50: '50% speed',\n                neobot_purple_percent_60: '60% speed',\n                neobot_purple_percent_70: '70% speed',\n                neobot_purple_percent_80: '80% speed',\n                neobot_purple_percent_90: '90% speed',\n                neobot_purple_percent_100: '100% speed',\n\n                neobot_purple_angle_0: '0 degree',\n                neobot_purple_angle_5: '5 degrees',\n                neobot_purple_angle_10: '10 degrees',\n                neobot_purple_angle_15: '15 degrees',\n                neobot_purple_angle_20: '20 degrees',\n                neobot_purple_angle_25: '25 degrees',\n                neobot_purple_angle_30: '30 degrees',\n                neobot_purple_angle_35: '35 degrees',\n                neobot_purple_angle_40: '40 degrees',\n                neobot_purple_angle_45: '45 degrees',\n                neobot_purple_angle_50: '50 degrees',\n                neobot_purple_angle_55: '55 degrees',\n                neobot_purple_angle_60: '60 degrees',\n                neobot_purple_angle_65: '65 degrees',\n                neobot_purple_angle_70: '70 degrees',\n                neobot_purple_angle_75: '75 degrees',\n                neobot_purple_angle_80: '80 degrees',\n                neobot_purple_angle_85: '85 degrees',\n                neobot_purple_angle_90: '90 degrees',\n                neobot_purple_angle_95: '95 degrees',\n                neobot_purple_angle_100: '100 degrees',\n                neobot_purple_angle_105: '105 degrees',\n                neobot_purple_angle_110: '110 degrees',\n                neobot_purple_angle_115: '115 degrees',\n                neobot_purple_angle_120: '120 degrees',\n                neobot_purple_angle_125: '125 degrees',\n                neobot_purple_angle_130: '130 degrees',\n                neobot_purple_angle_135: '135 degrees',\n                neobot_purple_angle_140: '140 degrees',\n                neobot_purple_angle_145: '145 degrees',\n                neobot_purple_angle_150: '150 degrees',\n                neobot_purple_angle_155: '155 degrees',\n                neobot_purple_angle_160: '160 degrees',\n                neobot_purple_angle_165: '165 degrees',\n                neobot_purple_angle_170: '170 degrees',\n                neobot_purple_angle_175: '175 degrees',\n                neobot_purple_angle_180: '180degrees',\n\n                neobot_purple_out_all: 'ALL',\n                neobot_purple_direction_left: 'to the left',\n                neobot_purple_direction_right: 'to the right',\n            },\n        }, //\n    };\n};\n\nEntry.NeobotPurple.blockMenuBlocks = [\n    // sensor\n    'neobot_purple_sensor_title',\n    'neobot_purple_sensor_value',\n    'neobot_purple_sensor_convert_scale',\n    'neobot_purple_decision_sensor_is_over',\n    'neobot_purple_decision_equal_with_sensor',\n    'neobot_purple_decision_sensor_angle',\n    'neobot_purple_remote_button',\n\n    // led\n    'neobot_purple_led_title',\n    'neobot_purple_led_on',\n    'neobot_purple_led_brightness_with_sensor',\n    'neobot_purple_color_led_on',\n    'neobot_purple_output_led_off',\n\n    // output\n    'neobot_purple_output_title',\n    'neobot_purple_set_output',\n\n    //  motor\n    'neobot_purple_motor_title',\n    'neobot_purple_robot',\n    'neobot_purple_motor_start',\n    'neobot_purple_motor_stop',\n\n    // servo\n    'neobot_purple_servo_title',\n    'neobot_purple_servo_init',\n    'neobot_purple_servo_rotate',\n    'neobot_purple_servo_stop',\n    'neobot_purple_servo_change_degree',\n\n    // melody\n    'neobot_purple_buzzer_title',\n    'neobot_purple_play_note_for',\n    'neobot_purple_melody_play_with_sensor',\n    'neobot_purple_melody_stop',\n];\n\nEntry.NeobotPurple.getBlocks = function() {\n    return {\n        /*************************\n         * class neobot_purple_sensor\n         *************************/\n        neobot_purple_sensor_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_purple_sensor_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_purple_sensor_title',\n            },\n            class: 'neobot_purple_sensor',\n            isNotFor: ['neobot_purple'],\n            events: {},\n        },\n        neobot_purple_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_purple_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_purple_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_purple_port_remot, 'IR'],\n                        [Lang.Blocks.neobot_purple_port_bat, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_purple_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_purple_sensor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port];\n            },\n        },\n\n        neobot_purple_sensor_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_purple_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_purple_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'neobot_purple_sensor_convert_scale',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OMIN: 1,\n                OMAX: 2,\n                MIN: 3,\n                MAX: 4,\n            },\n            class: 'neobot_purple_sensor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                var value = Entry.hw.portData[port];\n                var omin = script.getNumberValue('OMIN', script);\n                var omax = script.getNumberValue('OMAX', script);\n                var min = script.getNumberValue('MIN', script);\n                var max = script.getNumberValue('MAX', script);\n\n                if (omin > omax) {\n                    var temp = omin;\n                    omin = omax;\n                    omax = temp;\n                }\n\n                if (min > max) {\n                    var temp = min;\n                    min = max;\n                    max = temp;\n                }\n\n                value -= omin;\n                value = value * ((max - min) / (omax - omin));\n                value += min;\n                value = Math.min(max, value);\n                value = Math.max(min, value);\n\n                return Math.round(value);\n            },\n        },\n\n        neobot_purple_decision_sensor_is_over: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_purple_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_purple_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_purple_port_12, 'IN12'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_purple_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_purple_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_purple_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_purple_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, 10],\n                type: 'neobot_purple_decision_sensor_is_over',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                SYMBOL: 1,\n                VALUE: 2,\n            },\n            class: 'neobot_purple_sensor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                const sensorTemp = script.getStringField('SENSOR');\n                const symbol = script.getStringField('SYMBOL');\n                const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                if (sensorTemp == 'IN12') {\n                    const sensor1 = Entry.hw.portData['IN1'];\n                    const sensor2 = Entry.hw.portData['IN2'];\n                    if (symbol == '=') {\n                        return sensor1 == value && sensor2 == value;\n                    } else if (symbol == '>') {\n                        return sensor1 > value && sensor2 > value;\n                    } else if (symbol == '<') {\n                        return sensor1 < value && sensor2 < value;\n                    } else if (symbol == '>=') {\n                        return sensor1 >= value && sensor2 >= value;\n                    } else if (symbol == '<=') {\n                        return sensor1 <= value && sensor2 <= value;\n                    }\n                } else {\n                    const sensor = Entry.hw.portData[sensorTemp];\n                    if (symbol == '=') {\n                        if (sensor == value) return true;\n                        else return false;\n                    } else if (symbol == '>') {\n                        if (sensor > value) return true;\n                        else return false;\n                    } else if (symbol == '<') {\n                        if (sensor < value) return true;\n                        else return false;\n                    } else if (symbol == '>=') {\n                        if (sensor >= value) return true;\n                        else return false;\n                    } else if (symbol == '<=') {\n                        if (sensor <= value) return true;\n                        else return false;\n                    }\n                }\n                return false;\n            },\n        },\n\n        neobot_purple_decision_equal_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_purple_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_purple_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_color_white, 0],\n                        [Lang.Blocks.neobot_purple_color_red, 1],\n                        [Lang.Blocks.neobot_purple_color_yellow, 2],\n                        [Lang.Blocks.neobot_purple_color_green, 3],\n                        [Lang.Blocks.neobot_purple_color_blue, 4],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_purple_decision_equal_with_sensor',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                COLOR: 1,\n            },\n            class: 'neobot_purple_sensor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var color = script.getNumberField('COLOR');\n\n                if (sensor >= 10 && sensor <= 50) {\n                    if (color == 0) return true;\n                    else return false;\n                } else if (sensor >= 51 && sensor <= 90) {\n                    if (color == 1) return true;\n                    else return false;\n                } else if (sensor >= 91 && sensor <= 130) {\n                    if (color == 2) return true;\n                    else return false;\n                } else if (sensor >= 131 && sensor <= 170) {\n                    if (color == 3) return true;\n                    else return false;\n                } else if (sensor >= 171 && sensor <= 210) {\n                    if (color == 4) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        neobot_purple_decision_sensor_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_purple_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_purple_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_purple_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_purple_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_purple_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_purple_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_angle_0, '0'],\n                        [Lang.Blocks.neobot_purple_angle_10, '10'],\n                        [Lang.Blocks.neobot_purple_angle_20, '20'],\n                        [Lang.Blocks.neobot_purple_angle_30, '30'],\n                        [Lang.Blocks.neobot_purple_angle_40, '40'],\n                        [Lang.Blocks.neobot_purple_angle_50, '50'],\n                        [Lang.Blocks.neobot_purple_angle_60, '60'],\n                        [Lang.Blocks.neobot_purple_angle_70, '70'],\n                        [Lang.Blocks.neobot_purple_angle_80, '80'],\n                        [Lang.Blocks.neobot_purple_angle_90, '90'],\n                        [Lang.Blocks.neobot_purple_angle_100, '100'],\n                        [Lang.Blocks.neobot_purple_angle_110, '110'],\n                        [Lang.Blocks.neobot_purple_angle_120, '120'],\n                        [Lang.Blocks.neobot_purple_angle_130, '130'],\n                        [Lang.Blocks.neobot_purple_angle_140, '140'],\n                        [Lang.Blocks.neobot_purple_angle_150, '150'],\n                        [Lang.Blocks.neobot_purple_angle_160, '160'],\n                        [Lang.Blocks.neobot_purple_angle_170, '170'],\n                        [Lang.Blocks.neobot_purple_angle_180, '180'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'neobot_purple_decision_sensor_angle',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                SYMBOL: 1,\n                VALUE: 2,\n            },\n            class: 'neobot_purple_sensor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var symbol = script.getStringField('SYMBOL');\n                var value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                if (symbol == '=') {\n                    if (sensor == value) return true;\n                    else return false;\n                } else if (symbol == '>') {\n                    if (sensor > value) return true;\n                    else return false;\n                } else if (symbol == '<') {\n                    if (sensor < value) return true;\n                    else return false;\n                } else if (symbol == '>=') {\n                    if (sensor >= value) return true;\n                    else return false;\n                } else if (symbol == '<=') {\n                    if (sensor <= value) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        neobot_purple_remote_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_remote_btn_1, '10'],\n                        [Lang.Blocks.neobot_purple_remote_btn_2, '11'],\n                        [Lang.Blocks.neobot_purple_remote_btn_3, '12'],\n                        [Lang.Blocks.neobot_purple_remote_btn_4, '13'],\n                        [Lang.Blocks.neobot_purple_remote_btn_up, '1'],\n                        [Lang.Blocks.neobot_purple_remote_btn_down, '2'],\n                        [Lang.Blocks.neobot_purple_remote_btn_left, '3'],\n                        [Lang.Blocks.neobot_purple_remote_btn_right, '4'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_purple_remote_button',\n            },\n            paramsKeyMap: {\n                KEY: 0,\n            },\n            class: 'neobot_purple_sensor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                var key = script.getNumberField('KEY');\n                var value = Entry.hw.portData['IR'];\n                if (key == value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        /*************************\n         * class neobot_purple_led\n         *************************/\n        neobot_purple_led_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_purple_led_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_purple_led_title',\n            },\n            class: 'neobot_purple_led',\n            isNotFor: ['neobot_purple'],\n            events: {},\n        },\n        neobot_purple_led_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100%', '255'],\n                        ['90%', '230'],\n                        ['80%', '204'],\n                        ['70%', '179'],\n                        ['60%', '153'],\n                        ['50%', '128'],\n                        ['40%', '102'],\n                        ['30%', '77'],\n                        ['20%', '51'],\n                        ['10%', '26'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'neobot_purple_arg_led_duration',\n                        id: 'm311',\n                    },\n                    null,\n                ],\n                type: 'neobot_purple_led_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_purple_led',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const value = script.getNumberField('VALUE', script);\n                    const duration = script.getStringValue('DURATION', script);\n\n                    if (Entry.NeobotPurple.log_to_console) {\n                        Entry.console.print('=== neobot_purple_led_on ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('brightness : ' + value, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    if (\n                        duration != '계속' &&\n                        duration != 'constantly' &&\n                        Entry.parseNumber(duration) <= 0\n                    ) {\n                        return script.callReturn();\n                    }\n\n                    if (port == 'ALL') {\n                        Entry.hw.sendQueue['OUT1'] = value;\n                        Entry.hw.sendQueue['OUT2'] = value;\n                        Entry.hw.sendQueue['OUT3'] = value;\n                    } else {\n                        Entry.hw.sendQueue[port] = value;\n                    }\n\n                    if (duration == '계속' || duration == 'constantly') {\n                        return script.callReturn();\n                    }\n\n                    const durationValue = Entry.parseNumber(duration);\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        if (port == 'ALL') {\n                            Entry.hw.sendQueue['OUT1'] = 0;\n                            Entry.hw.sendQueue['OUT2'] = 0;\n                            Entry.hw.sendQueue['OUT3'] = 0;\n                        } else {\n                            Entry.hw.sendQueue[port] = 0;\n                        }\n                        if (Entry.NeobotPurple.log_to_console)\n                            Entry.console.print('neobot_purple_led_on : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, durationValue * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_purple_output_led_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_purple_output_led_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_purple_led',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print('=== neobot_purple_output_led_off ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = 0;\n                    Entry.hw.sendQueue['OUT2'] = 0;\n                    Entry.hw.sendQueue['OUT3'] = 0;\n                } else {\n                    Entry.hw.sendQueue[port] = 0;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_purple_led_brightness_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'neobot_purple_led_brightness_with_sensor',\n            },\n            paramsKeyMap: {\n                IN: 0,\n                OUT: 1,\n            },\n            class: 'neobot_purple_led',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                const inPort = script.getStringField('IN', script);\n                const outPort = script.getStringField('OUT', script);\n                let value = Entry.hw.portData[inPort];\n\n                // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함.\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n                value = Math.ceil((value / 100) * 255);\n\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print(\n                        '=== neobot_purple_led_brightness_with_sensor ===',\n                        'speak'\n                    );\n                    Entry.console.print('out port : ' + outPort, 'speak');\n                    Entry.console.print('in port : ' + inPort, 'speak');\n                    Entry.console.print('sensor value : ' + Entry.hw.portData[inPort], 'speak');\n                    Entry.console.print('output value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (outPort == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = value;\n                    Entry.hw.sendQueue['OUT2'] = value;\n                    Entry.hw.sendQueue['OUT3'] = value;\n                } else {\n                    Entry.hw.sendQueue[outPort] = value;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_purple_color_led_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_purple_color_led_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'neobot_purple_led',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT');\n                    let red = script.getNumberValue('RED');\n                    let green = script.getNumberValue('GREEN');\n                    let blue = script.getNumberValue('BLUE');\n\n                    let out1 = false;\n                    let out2 = false;\n                    let out3 = false;\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    } else {\n                        out1 = port == 'OUT1';\n                        out2 = port == 'OUT2';\n                        out3 = port == 'OUT3';\n                    }\n\n                    red = Math.max(red, 1);\n                    red = Math.min(red, 251);\n                    green = Math.max(green, 1);\n                    green = Math.min(green, 251);\n                    blue = Math.max(blue, 1);\n                    blue = Math.min(blue, 251);\n\n                    if (Entry.NeobotPurple.log_to_console) {\n                        Entry.console.print('=== neobot_purple_color_led_on ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('red : ' + red, 'speak');\n                        Entry.console.print('green : ' + green, 'speak');\n                        Entry.console.print('blue : ' + blue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    const valRed = 252;\n                    const valGreen = 253;\n                    const valBlue = 254;\n                    const valAccept = 255;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (out1) Entry.hw.sendQueue['OUT1'] = valRed;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = valRed;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = valRed;\n                    if (Entry.NeobotPurple.log_to_console)\n                        Entry.console.print('neobot_purple_color_led_on : ' + valRed, 'speak');\n                    setTimeout(function() {\n                        // set red\n                        if (out1) Entry.hw.sendQueue['OUT1'] = red;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = red;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = red;\n                        if (Entry.NeobotPurple.log_to_console)\n                            Entry.console.print('neobot_purple_color_led_on : ' + red, 'speak');\n                        setTimeout(function() {\n                            // choose green\n                            if (out1) Entry.hw.sendQueue['OUT1'] = valGreen;\n                            if (out2) Entry.hw.sendQueue['OUT2'] = valGreen;\n                            if (out3) Entry.hw.sendQueue['OUT3'] = valGreen;\n                            if (Entry.NeobotPurple.log_to_console)\n                                Entry.console.print(\n                                    'neobot_purple_color_led_on : ' + valGreen,\n                                    'speak'\n                                );\n                            setTimeout(function() {\n                                // set green\n                                if (out1) Entry.hw.sendQueue['OUT1'] = green;\n                                if (out2) Entry.hw.sendQueue['OUT2'] = green;\n                                if (out3) Entry.hw.sendQueue['OUT3'] = green;\n                                if (Entry.NeobotPurple.log_to_console)\n                                    Entry.console.print(\n                                        'neobot_purple_color_led_on : ' + green,\n                                        'speak'\n                                    );\n                                setTimeout(function() {\n                                    // choose blue\n                                    if (out1) Entry.hw.sendQueue['OUT1'] = valBlue;\n                                    if (out2) Entry.hw.sendQueue['OUT2'] = valBlue;\n                                    if (out3) Entry.hw.sendQueue['OUT3'] = valBlue;\n                                    if (Entry.NeobotPurple.log_to_console)\n                                        Entry.console.print(\n                                            'neobot_purple_color_led_on : ' + valBlue,\n                                            'speak'\n                                        );\n                                    setTimeout(function() {\n                                        // set blue\n                                        if (out1) Entry.hw.sendQueue['OUT1'] = blue;\n                                        if (out2) Entry.hw.sendQueue['OUT2'] = blue;\n                                        if (out3) Entry.hw.sendQueue['OUT3'] = blue;\n                                        if (Entry.NeobotPurple.log_to_console)\n                                            Entry.console.print(\n                                                'neobot_purple_color_led_on : ' + blue,\n                                                'speak'\n                                            );\n                                        setTimeout(function() {\n                                            // accept\n                                            if (out1) Entry.hw.sendQueue['OUT1'] = valAccept;\n                                            if (out2) Entry.hw.sendQueue['OUT2'] = valAccept;\n                                            if (out3) Entry.hw.sendQueue['OUT3'] = valAccept;\n                                            if (Entry.NeobotPurple.log_to_console)\n                                                Entry.console.print(\n                                                    'neobot_purple_color_led_on : ' + valAccept,\n                                                    'speak'\n                                                );\n                                            setTimeout(function() {\n                                                // final delay\n                                                script.timeFlag = 0;\n                                            }, 200);\n                                        }, 200);\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n                        }, 200);\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        /*************************\n         * class neobot_purple_output\n         *************************/\n        neobot_purple_output_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_purple_output_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_purple_output_title',\n            },\n            class: 'neobot_purple_output',\n            isNotFor: ['neobot_purple'],\n            events: {},\n        },\n        neobot_purple_set_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_purple_set_output',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'neobot_purple_output',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print('=== neobot_purple_set_output ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = value;\n                    Entry.hw.sendQueue['OUT2'] = value;\n                    Entry.hw.sendQueue['OUT3'] = value;\n                } else {\n                    Entry.hw.sendQueue[port] = value;\n                }\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_purple_motor\n         *************************/\n        neobot_purple_motor_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_purple_motor_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_purple_motor_title',\n            },\n            class: 'neobot_purple_motor',\n            isNotFor: ['neobot_purple'],\n            events: {},\n        },\n        neobot_purple_robot: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_motor_move_forward, '1'],\n                        [Lang.Blocks.neobot_purple_motor_move_backward, '2'],\n                        [Lang.Blocks.neobot_purple_motor_move_left, '3'],\n                        [Lang.Blocks.neobot_purple_motor_move_right, '4'],\n                        [Lang.Blocks.neobot_purple_motor_move_stop, '5'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_purple_robot',\n            },\n            paramsKeyMap: {\n                MOVE: 0,\n            },\n            class: 'neobot_purple_motor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                const move = script.getNumberField('MOVE');\n                let leftValue;\n                let rightValue;\n                switch (move) {\n                    case 1:\n                        leftValue = 0x10 + 10;\n                        rightValue = 0x10 + 10;\n                        break;\n                    case 2:\n                        leftValue = 0x20 + 10;\n                        rightValue = 0x20 + 10;\n                        break;\n                    case 3:\n                        leftValue = 0x20 + 5;\n                        rightValue = 0x10 + 5;\n                        break;\n                    case 4:\n                        leftValue = 0x10 + 5;\n                        rightValue = 0x20 + 5;\n                        break;\n                    case 5:\n                        leftValue = 0;\n                        rightValue = 0;\n                        break;\n                }\n\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print('=== neobot_purple_robot ===', 'speak');\n                    Entry.console.print('move : ' + move, 'speak');\n                    Entry.console.print('left value : ' + leftValue, 'speak');\n                    Entry.console.print('right value : ' + rightValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['DCL'] = leftValue;\n                Entry.hw.sendQueue['DCR'] = rightValue;\n                return script.callReturn();\n            },\n        },\n\n        neobot_purple_motor_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_motor_both, '1'],\n                        [Lang.Blocks.neobot_purple_motor_left, '2'],\n                        [Lang.Blocks.neobot_purple_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_direction_forward, '1'],\n                        [Lang.Blocks.neobot_purple_direction_backward, '2'],\n                        [Lang.Blocks.neobot_purple_direction_left, '3'],\n                        [Lang.Blocks.neobot_purple_direction_right, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'neobot_purple_arg_motor_speed',\n                        id: 'm411',\n                    },\n                    {\n                        type: 'neobot_purple_arg_motor_duration',\n                        id: 'm412',\n                    },\n                    null,\n                ],\n                type: 'neobot_purple_motor_start',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n                DURATION: 3,\n            },\n            class: 'neobot_purple_motor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const motor = script.getStringField('MOTOR', script);\n                    const direction = script.getStringField('DIRECTION', script);\n                    const speed = script.getStringValue('SPEED', script);\n                    const duration = script.getStringValue('DURATION', script);\n\n                    if (\n                        duration != '계속' &&\n                        duration != 'constantly' &&\n                        Entry.parseNumber(duration) <= 0\n                    ) {\n                        return script.callReturn();\n                    }\n\n                    let moveLeft = false;\n                    let moveRight = false;\n                    if (motor == 1) {\n                        moveLeft = true;\n                        moveRight = true;\n                    } else if (motor == 2) {\n                        moveLeft = true;\n                    } else {\n                        moveRight = true;\n                    }\n\n                    let leftDirectionValue;\n                    let rightDirectionValue;\n                    if (direction == 1) {\n                        leftDirectionValue = 0x10;\n                        rightDirectionValue = 0x10;\n                    } else if (direction == 2) {\n                        leftDirectionValue = 0x20;\n                        rightDirectionValue = 0x20;\n                    } else if (direction == 3) {\n                        leftDirectionValue = 0x20;\n                        rightDirectionValue = 0x10;\n                    } else {\n                        leftDirectionValue = 0x10;\n                        rightDirectionValue = 0x20;\n                    }\n\n                    // edited 210421, 0~100 을 0~15로 변환, 100 이상은 최대값(15)으로 처리함.\n                    let speedValue = 0;\n                    if (Entry.Utils.isNumber(speed)) {\n                        speedValue = Entry.parseNumber(speed);\n                    } else {\n                        speedValue = Entry.hw.portData[speed];\n                    }\n                    speedValue = Math.max(speedValue, 0);\n                    speedValue = Math.min(speedValue, 100);\n                    speedValue = Math.ceil((speedValue / 100) * 15);\n\n                    const leftOutValue = leftDirectionValue + speedValue;\n                    const rightOutValue = rightDirectionValue + speedValue;\n\n                    if (Entry.NeobotPurple.log_to_console) {\n                        Entry.console.print('=== neobot_purple_motor_start ===', 'speak');\n                        Entry.console.print('motor : ' + motor, 'speak');\n                        Entry.console.print('direction : ' + direction, 'speak');\n                        Entry.console.print('speed : ' + speed, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print(\n                            'left direction value : ' + leftDirectionValue,\n                            'speak'\n                        );\n                        Entry.console.print(\n                            'right direction value : ' + rightDirectionValue,\n                            'speak'\n                        );\n                        Entry.console.print('speed value : ' + speedValue, 'speak');\n                        Entry.console.print('left output value : ' + leftOutValue, 'speak');\n                        Entry.console.print('right output value : ' + rightOutValue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    if (moveLeft) {\n                        Entry.hw.sendQueue['DCL'] = leftOutValue;\n                    }\n                    if (moveRight) {\n                        Entry.hw.sendQueue['DCR'] = rightOutValue;\n                    }\n\n                    if (duration == '계속' || duration == 'constantly') {\n                        return script.callReturn();\n                    }\n\n                    const durationValue = Entry.parseNumber(duration);\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['DCL'] = 0;\n                        Entry.hw.sendQueue['DCR'] = 0;\n                        if (Entry.NeobotPurple.log_to_console)\n                            Entry.console.print('neobot_purple_motor_start : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, durationValue * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_purple_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_motor_both, '1'],\n                        [Lang.Blocks.neobot_purple_motor_left, '2'],\n                        [Lang.Blocks.neobot_purple_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_purple_motor_stop',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n            },\n            class: 'neobot_purple_motor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                const motor = script.getNumberField('MOTOR');\n\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print('=== neobot_purple_motor_stop ===', 'speak');\n                    Entry.console.print('motor : ' + motor, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (motor == 1) {\n                    Entry.hw.sendQueue['DCL'] = 0;\n                    Entry.hw.sendQueue['DCR'] = 0;\n                } else if (motor == 2) {\n                    Entry.hw.sendQueue['DCL'] = 0;\n                } else {\n                    Entry.hw.sendQueue['DCR'] = 0;\n                }\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_purple_melody\n         *************************/\n        neobot_purple_buzzer_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_purple_buzzer_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_purple_buzzer_title',\n            },\n            class: 'neobot_purple_melody',\n            isNotFor: ['neobot_purple'],\n            events: {},\n        },\n        neobot_purple_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_sound_silent, '0'],\n                        [Lang.Blocks.neobot_purple_sound_do, '1'],\n                        [Lang.Blocks.neobot_purple_sound_do_shop, '2'],\n                        [Lang.Blocks.neobot_purple_sound_re, '3'],\n                        [Lang.Blocks.neobot_purple_sound_re_shop, '4'],\n                        [Lang.Blocks.neobot_purple_sound_mi, '5'],\n                        [Lang.Blocks.neobot_purple_sound_fa, '6'],\n                        [Lang.Blocks.neobot_purple_sound_fa_shop, '7'],\n                        [Lang.Blocks.neobot_purple_sound_so, '8'],\n                        [Lang.Blocks.neobot_purple_sound_so_shop, '9'],\n                        [Lang.Blocks.neobot_purple_sound_la, '10'],\n                        [Lang.Blocks.neobot_purple_sound_la_shop, '11'],\n                        [Lang.Blocks.neobot_purple_sound_ti, '12'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_sound_half_note, '2'],\n                        [Lang.Blocks.neobot_purple_sound_quarter_note, '4'],\n                        [Lang.Blocks.neobot_purple_sound_eighth_note, '8'],\n                        [Lang.Blocks.neobot_purple_sound_sixteenth_note, '16'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '2', '4', null],\n                type: 'neobot_purple_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_purple_melody',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const note = script.getNumberField('NOTE', script);\n                    const octave = script.getNumberField('OCTAVE', script);\n                    const duration = script.getNumberField('DURATION', script);\n                    let value = note > 0 ? note + 12 * octave : 0;\n\n                    value = Math.min(value, 72);\n\n                    if (Entry.NeobotPurple.log_to_console) {\n                        Entry.console.print('=== neobot_purple_play_note_for ===', 'speak');\n                        Entry.console.print('note : ' + note, 'speak');\n                        Entry.console.print('octave : ' + octave, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print('value : ' + value, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SND'] = value;\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['SND'] = 0;\n                        if (Entry.NeobotPurple.log_to_console)\n                            Entry.console.print('neobot_purple_play_note_for : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, (1 / duration) * 2000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_purple_melody_play_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_purple_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_purple_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_purple_melody_play_with_sensor',\n            },\n            paramsKeyMap: {\n                INPUT: 0,\n            },\n            class: 'neobot_purple_melody',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                const input = script.getStringField('INPUT');\n                let value = Entry.hw.portData[input];\n\n                // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함.\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n                value = Math.ceil((value / 100) * 65);\n\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print('=== neobot_purple_melody_play_with_sensor ===', 'speak');\n                    Entry.console.print('input : ' + input, 'speak');\n                    Entry.console.print('value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['SND'] = value;\n                return script.callReturn();\n            },\n        },\n\n        neobot_purple_melody_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_purple_melody_stop',\n            },\n            paramsKeyMap: {},\n            class: 'neobot_purple_melody',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print('=== neobot_purple_melody_stop ===', 'speak');\n                    Entry.console.print('value : 0', 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['SND'] = 0;\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_purple_servo\n         *************************/\n        neobot_purple_servo_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_purple_servo_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_purple_servo_title',\n            },\n            class: 'neobot_purple_servo',\n            isNotFor: ['neobot_purple'],\n            events: {},\n        },\n        neobot_purple_servo_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_purple_servo_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_purple_servo',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const resetValue = 186;\n                    const initValue = 1;\n\n                    if (Entry.NeobotPurple.log_to_console) {\n                        Entry.console.print('=== neobot_purple_servo_init ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    let out1 = port == 'OUT1';\n                    let out2 = port == 'OUT2';\n                    let out3 = port == 'OUT3';\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (out1) Entry.hw.sendQueue['OUT1'] = resetValue;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = resetValue;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = resetValue;\n                    if (Entry.NeobotPurple.log_to_console)\n                        Entry.console.print('neobot_purple_servo_init : ' + resetValue, 'speak');\n                    setTimeout(function() {\n                        if (out1) Entry.hw.sendQueue['OUT1'] = initValue;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = initValue;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = initValue;\n                        if (Entry.NeobotPurple.log_to_console)\n                            Entry.console.print('neobot_purple_servo_init : ' + initValue, 'speak');\n                        setTimeout(function() {\n                            script.timeFlag = 0;\n                        }, 100);\n                    }, 200);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_purple_servo_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_purple_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['0%', 0],\n                        ['10%', 10],\n                        ['20%', 20],\n                        ['30%', 30],\n                        ['40%', 40],\n                        ['50%', 50],\n                        ['60%', 60],\n                        ['70%', 70],\n                        ['80%', 80],\n                        ['90%', 90],\n                        ['100%', 100],\n                    ],\n                    value: 50,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'neobot_purple_servo_rotate',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'neobot_purple_servo',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n                const direction = script.getNumberField('DIRECTION');\n                const speed = script.getStringField('SPEED');\n\n                let directionValue = 192; // 정방향\n                if (direction == 2) {\n                    directionValue = 208; // 역방향\n                }\n                let speedValue;\n                if (Entry.Utils.isNumber(speed)) {\n                    speedValue = Entry.parseNumber(speed);\n                } else {\n                    speedValue = Entry.hw.portData[speed];\n                }\n\n                // edited 210421, 0~100 을 0~10 으로 변환\n                speedValue = Math.max(speedValue, 0);\n                speedValue = Math.min(speedValue, 100);\n                speedValue = Math.ceil(speedValue / 10);\n\n                let outValue = directionValue + speedValue;\n                if (outValue == directionValue) {\n                    outValue = 254;\n                } else {\n                    outValue = outValue - 1;\n                }\n\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print('=== neobot_purple_servo_rotate ===');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('direction : ' + direction, 'speak');\n                    Entry.console.print('speed : ' + speed, 'speak');\n                    Entry.console.print('direction value : ' + directionValue, 'speak');\n                    Entry.console.print('speed value : ' + speedValue, 'speak');\n                    Entry.console.print('output value : ' + outValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = outValue;\n                    Entry.hw.sendQueue['OUT2'] = outValue;\n                    Entry.hw.sendQueue['OUT3'] = outValue;\n                } else {\n                    Entry.hw.sendQueue[port] = outValue;\n                }\n                return script.callReturn();\n            },\n        },\n        neobot_purple_servo_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_purple_servo_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_purple_servo',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n                let outValue = 254;\n\n                if (Entry.NeobotPurple.log_to_console) {\n                    Entry.console.print('=== neobot_purple_servo_stop ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('output value: ' + outValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = outValue;\n                    Entry.hw.sendQueue['OUT2'] = outValue;\n                    Entry.hw.sendQueue['OUT3'] = outValue;\n                } else {\n                    Entry.hw.sendQueue[port] = outValue;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_purple_servo_change_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_purple_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_purple_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['0%', 0],\n                        ['10%', 10],\n                        ['20%', 20],\n                        ['30%', 30],\n                        ['40%', 40],\n                        ['50%', 50],\n                        ['60%', 60],\n                        ['70%', 70],\n                        ['80%', 80],\n                        ['90%', 90],\n                        ['100%', 100],\n                    ],\n                    value: 50,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_servo_degree',\n                        id: 'm211',\n                    },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'neobot_purple_servo_change_degree',\n            },\n            paramsKeyMap: {\n                DEGREE: 0,\n                PORT: 1,\n                DIRECTION: 2,\n                SPEED: 3,\n            },\n            class: 'neobot_purple_servo',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const direction = script.getNumberField('DIRECTION');\n                    const speed = script.getStringValue('SPEED');\n                    const degree = script.getStringValue('DEGREE');\n\n                    let out1 = port == 'OUT1';\n                    let out2 = port == 'OUT2';\n                    let out3 = port == 'OUT3';\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    }\n\n                    let directionValue = 188;\n                    if (direction == 2) {\n                        directionValue = 189;\n                    }\n\n                    let speedValue;\n                    if (Entry.Utils.isNumber(speed)) {\n                        speedValue = Entry.parseNumber(speed);\n                    } else {\n                        speedValue = Entry.hw.portData[speed];\n                    }\n\n                    // edited 210421, 0~100 을 240~250 으로 변환\n                    speedValue = Math.max(speedValue, 0);\n                    speedValue = Math.min(speedValue, 100);\n                    speedValue = Math.ceil(speedValue / 10) + 240;\n\n                    let degreeValue;\n                    if (Entry.Utils.isNumber(degree)) {\n                        degreeValue = Entry.parseNumber(degree);\n                    } else {\n                        if (degree == 'IN1' || degree == 'IN2' || degree == 'IN3') {\n                            degreeValue = Entry.hw.portData[degree];\n                        } else {\n                            degreeValue = 0;\n                        }\n                    }\n                    // edited 210421, 별도의 변환없이 그대로 사용함\n                    degreeValue = Math.max(degreeValue, 0);\n                    degreeValue = Math.min(degreeValue, 180);\n                    degreeValue = degreeValue + 1;\n\n                    if (Entry.NeobotPurple.log_to_console) {\n                        Entry.console.print('=== neobot_purple_servo_change_degree ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('direction : ' + direction, 'speak');\n                        Entry.console.print('speed : ' + speed, 'speak');\n                        Entry.console.print('degree : ' + degree, 'speak');\n                        Entry.console.print('directionValue : ' + directionValue, 'speak');\n                        Entry.console.print('speedValue : ' + speedValue, 'speak');\n                        Entry.console.print('degreeValue : ' + degreeValue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    // direction\n                    if (out1) Entry.hw.sendQueue['OUT1'] = directionValue;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = directionValue;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = directionValue;\n                    if (Entry.NeobotPurple.log_to_console)\n                        Entry.console.print(\n                            'neobot_purple_servo_change_degree : ' + directionValue,\n                            'speak'\n                        );\n                    setTimeout(function() {\n                        // speed\n                        if (out1) Entry.hw.sendQueue['OUT1'] = speedValue;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = speedValue;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = speedValue;\n                        if (Entry.NeobotPurple.log_to_console)\n                            Entry.console.print(\n                                'neobot_purple_servo_change_degree : ' + speedValue,\n                                'speak'\n                            );\n                        setTimeout(function() {\n                            // degree\n                            if (out1) Entry.hw.sendQueue['OUT1'] = degreeValue;\n                            if (out2) Entry.hw.sendQueue['OUT2'] = degreeValue;\n                            if (out3) Entry.hw.sendQueue['OUT3'] = degreeValue;\n                            if (Entry.NeobotPurple.log_to_console)\n                                Entry.console.print(\n                                    'neobot_purple_servo_change_degree : ' + degreeValue,\n                                    'speak'\n                                );\n                            setTimeout(function() {\n                                // final delay\n                                script.timeFlag = 0;\n                            }, 200);\n                        }, 200);\n                    }, 200);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        /*****************\n         * ARG Blocks\n         *****************/\n        neobot_purple_arg_led_duration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_duration_cont, '계속'],\n                        [Lang.Blocks.neobot_purple_duration_1s, '1'],\n                        [Lang.Blocks.neobot_purple_duration_2s, '2'],\n                        [Lang.Blocks.neobot_purple_duration_3s, '3'],\n                        [Lang.Blocks.neobot_purple_duration_4s, '4'],\n                        [Lang.Blocks.neobot_purple_duration_5s, '5'],\n                        [Lang.Blocks.neobot_purple_duration_6s, '6'],\n                        [Lang.Blocks.neobot_purple_duration_7s, '7'],\n                        [Lang.Blocks.neobot_purple_duration_8s, '8'],\n                        [Lang.Blocks.neobot_purple_duration_9s, '9'],\n                    ],\n                    value: '계속',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_purple_led',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        neobot_purple_arg_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['100%', 100],\n                        ['90%', 90],\n                        ['80%', 80],\n                        ['70%', 70],\n                        ['60%', 60],\n                        ['50%', 50],\n                        ['40%', 40],\n                        ['30%', 30],\n                        ['20%', 20],\n                        ['10%', 10],\n                        ['0%', 0],\n                    ],\n                    value: 100,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_purple_motor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        neobot_purple_arg_motor_duration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_duration_cont, '계속'],\n                        [Lang.Blocks.neobot_purple_duration_1s, '1'],\n                        [Lang.Blocks.neobot_purple_duration_2s, '2'],\n                        [Lang.Blocks.neobot_purple_duration_3s, '3'],\n                        [Lang.Blocks.neobot_purple_duration_4s, '4'],\n                        [Lang.Blocks.neobot_purple_duration_5s, '5'],\n                        [Lang.Blocks.neobot_purple_duration_6s, '6'],\n                        [Lang.Blocks.neobot_purple_duration_7s, '7'],\n                        [Lang.Blocks.neobot_purple_duration_8s, '8'],\n                        [Lang.Blocks.neobot_purple_duration_9s, '9'],\n                    ],\n                    value: '계속',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_purple_motor',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        get_servo_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_purple_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_purple_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_purple_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_purple_angle_0, '0'],\n                        [Lang.Blocks.neobot_purple_angle_5, '5'],\n                        [Lang.Blocks.neobot_purple_angle_10, '10'],\n                        [Lang.Blocks.neobot_purple_angle_15, '15'],\n                        [Lang.Blocks.neobot_purple_angle_20, '20'],\n                        [Lang.Blocks.neobot_purple_angle_25, '25'],\n                        [Lang.Blocks.neobot_purple_angle_30, '30'],\n                        [Lang.Blocks.neobot_purple_angle_35, '35'],\n                        [Lang.Blocks.neobot_purple_angle_40, '40'],\n                        [Lang.Blocks.neobot_purple_angle_45, '45'],\n                        [Lang.Blocks.neobot_purple_angle_50, '50'],\n                        [Lang.Blocks.neobot_purple_angle_55, '55'],\n                        [Lang.Blocks.neobot_purple_angle_60, '60'],\n                        [Lang.Blocks.neobot_purple_angle_65, '65'],\n                        [Lang.Blocks.neobot_purple_angle_70, '70'],\n                        [Lang.Blocks.neobot_purple_angle_75, '75'],\n                        [Lang.Blocks.neobot_purple_angle_80, '80'],\n                        [Lang.Blocks.neobot_purple_angle_85, '85'],\n                        [Lang.Blocks.neobot_purple_angle_90, '90'],\n                        [Lang.Blocks.neobot_purple_angle_95, '95'],\n                        [Lang.Blocks.neobot_purple_angle_100, '100'],\n                        [Lang.Blocks.neobot_purple_angle_105, '105'],\n                        [Lang.Blocks.neobot_purple_angle_110, '110'],\n                        [Lang.Blocks.neobot_purple_angle_115, '115'],\n                        [Lang.Blocks.neobot_purple_angle_120, '120'],\n                        [Lang.Blocks.neobot_purple_angle_125, '125'],\n                        [Lang.Blocks.neobot_purple_angle_130, '130'],\n                        [Lang.Blocks.neobot_purple_angle_135, '135'],\n                        [Lang.Blocks.neobot_purple_angle_140, '140'],\n                        [Lang.Blocks.neobot_purple_angle_145, '145'],\n                        [Lang.Blocks.neobot_purple_angle_150, '150'],\n                        [Lang.Blocks.neobot_purple_angle_155, '155'],\n                        [Lang.Blocks.neobot_purple_angle_160, '160'],\n                        [Lang.Blocks.neobot_purple_angle_165, '165'],\n                        [Lang.Blocks.neobot_purple_angle_170, '170'],\n                        [Lang.Blocks.neobot_purple_angle_175, '175'],\n                        [Lang.Blocks.neobot_purple_angle_180, '180'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_purple_servo',\n            isNotFor: ['neobot_purple'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.NeobotPurple;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neobot_robot_theme.js",
    "content": "Entry.NeobotRobotTheme = {\n    id: '5.3',\n    name: 'neobot_robot_theme',\n    url: 'http://www.neobot.co.kr',\n    imageName: 'neobot_robot_theme.png',\n    title: {\n        ko: '네오코딩 로봇테마',\n        en: 'NEOCODING RobotTheme',\n    },\n    LOCAL_MAP: ['IN1', 'IN2', 'IN3', 'IR', 'IN4'],\n    REMOTE_MAP: ['OUT1', 'OUT2', 'OUT3', 'DCL', 'DCR', 'SND', 'LED', 'OPT'],\n    setZero: function() {\n        for (var port in Entry.NeobotRobotTheme.REMOTE_MAP) {\n            if (port == 3 || port == 4) {\n                // set motor values as 100. means stopping motors.\n                Entry.hw.sendQueue[Entry.NeobotRobotTheme.REMOTE_MAP[port]] = 100;\n            } else {\n                Entry.hw.sendQueue[Entry.NeobotRobotTheme.REMOTE_MAP[port]] = 0;\n            }\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neobot_robot_theme.png',\n        width: 800,\n        height: 800,\n        listPorts: {},\n        ports: {\n            IN1: { name: 'PORT1', type: 'input', pos: { x: 145, y: 100 } },\n            IN2: { name: 'PORT2', type: 'input', pos: { x: 314, y: 100 } },\n            IN3: { name: 'PORT3', type: 'input', pos: { x: 484, y: 100 } },\n            IN4: { name: 'PORT4', type: 'input', pos: { x: 653, y: 100 } },\n            // for test\n            /* OUT1: { name: 'OUT1', type: 'output', pos: { x: 145, y: 400} },\n            OUT2: { name: 'OUT2', type: 'output', pos: { x: 314, y: 400} },\n            DCL: { name: 'DCL', type: 'output', pos: { x: 484, y: 400} },\n            DCR: { name: 'DCR', type: 'output', pos: { x: 653, y: 400} }, */\n        },\n        mode: 'both',\n    },\n};\n\nEntry.NeobotRobotTheme.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                neobot_rb_port_value: '%1값',\n                neobot_rb_ir_sensor_value: '적외선센서값',\n                neobot_rb_light_sensor_value: '빛센서값',\n                neobot_rb_sound_sensor_value: '소리센서값',\n                neobot_rb_top_sensor_value: '윗면센서값',\n                neobot_rb_bottom_sensor_value: '바닥면센서값',\n\n                neobot_rb_led_on_type1: 'LED를 %1 밝기로 켜기 %2',\n                neobot_rb_led_on_type2: 'LED를 %1 밝기로 %2 초 켠 후 끄기 %3',\n                neobot_rb_led_off: 'LED 끄기 %1',\n                neobot_rb_led_on_type3: '%1에 연결한 LED를 %2 밝기로 켜기 %3',\n                neobot_rb_led_on_type4: '%1에 연결한 LED를 %2 밝기로 %3초 켠 후 끄기 %4',\n                neobot_rb_led_off_type1:'%1에 연결한 LED 끄기 %2',\n                \n                neobot_rb_output_type1: '%1에 연결한 외부포트에 %2만큼 출력하기 %3',\n\n                neobot_rb_motor_type1: '%1 모터를 %2 의 속도로 %3초 회전 후 정지 %4',\n                neobot_rb_motor_type2: '모터를 %1 %2 의 속도로 회전 %3',\n                neobot_rb_motor_type3: '%1 모터를 %2 의 속도로 회전 %3',\n                neobot_rb_motor_stop: '%1 모터 정지 %2',\n                neobot_rb_motor_type_select: '로봇 %1 %2',\n                neobot_rb_motor_type_stop: \"로봇 정지 %1\",\n\n                neobot_rb_ir_decision: '적외선센서 작동 (기준 값: %1)',\n                neobot_rb_light_decision: '빛센서 작동 (기준 값: %1)',\n                neobot_rb_sound_decision: '소리센서 작동 (기준 값: %1)',\n                neobot_rb_port_decision: ' %1 작동 (기준 값: %2)',\n                neobot_rb_top_decision: '윗면센서 작동 (기준 값: %1)',\n                neobot_rb_bottom_decision: '바닥면센서 작동 (기준 값: %1)',\n                neobot_rb_remote_decision : \"리모컨의 %1 버튼을 누름\",\n\n                neobot_rb_servo_init: '%1에 연결한 Servo모터를 현재 위치로 초기화하기 %2',\n                neobot_rb_servo_turn_type1: '%1에 연결한 Servo모터를 %2으로 %3도 회전하기 %4',\n                neobot_rb_servo_turn_type2: '%1에 연결한 Servo모터를 %2도 회전하기 %3',\n                neobot_rb_servo_turn_type4: '%1에 연결한 Servo모터의 회전속도를 %2로 정하기 %3',\n                neobot_rb_servo_turn_type5: '%1에 연결한 Servo모터를 %2 %3 빠르기로 계속 회전하기 %4',\n                neobot_rb_servo_mode_manual: '%1에 연결한 Servo모터를 수동 제어모드로 바꾸기 %2',\n                neobot_rb_servo_stop: '%1에 연결한 Servo모터 멈추기 %2',\n\n                neobot_rb_led: '%1',\n                neobot_rb_time: '%1',\n                neobot_rb_time2: '%1',\n                neobot_rb_speed: '%1',\n                neobot_rb_speed2: '%1',\n                neobot_rb_surface: '%1',\n            },\n            Blocks: {\n                neobot_rb_port_1: '1번 포트',\n                neobot_rb_port_2: '2번 포트',\n                neobot_rb_port_3: '3번 포트',\n                neobot_rb_port_4: '4번 포트',\n                neobot_rb_port_top: '윗면 포트',\n                neobot_rb_port_bottom: '바닥면 포트',\n\n                neobot_rb_top_face: '윗면',\n                neobot_rb_bottom_face: '바닥면',\n\n                neobot_rb_motor_both: '양쪽',\n                neobot_rb_motor_left: '왼쪽',\n                neobot_rb_motor_right: '오른쪽',\n\n                neobot_rb_motor_dir_front: '앞으로',\n                neobot_rb_motor_dir_rear: '뒤로',\n                neobot_rb_motor_dir_left: '왼쪽으로',\n                neobot_rb_motor_dir_right: '오른쪽으로',\n                neobot_rb_motor_dir_stand_left: '제자리에서 왼쪽으로',\n                neobot_rb_motor_dir_stand_right: '제자리에서 오른쪽으로',\n\n                neobot_rb_motor_move_forward: '전진',\n                neobot_rb_motor_move_backward: '후진',\n                neobot_rb_motor_move_left: '좌회전',\n                neobot_rb_motor_move_right: '우회전',\n                neobot_rb_motor_move_stop: '정지',\n\n                neobot_rb_remote_btn_a: 'A',\n                neobot_rb_remote_btn_b: 'B',\n                neobot_rb_remote_btn_c: 'C',\n                neobot_rb_remote_btn_d: 'D',\n                neobot_rb_remote_btn_1: '1',\n                neobot_rb_remote_btn_2: '2',\n                neobot_rb_remote_btn_3: '3',\n                neobot_rb_remote_btn_4: '4',\n                neobot_rb_remote_btn_up: '▲',\n                neobot_rb_remote_btn_down: '▼',\n                neobot_rb_remote_btn_left: '◀',\n                neobot_rb_remote_btn_right: '▶',\n\n                neobot_rb_servo_dir_1: '시계방향',\n                neobot_rb_servo_dir_2: '반시계방향',\n            },\n        },\n        en: {\n            template: {\n                neobot_rb_port_value: '%1 value',\n                neobot_rb_ir_sensor_value: 'infrared sensor value',    \n                neobot_rb_light_sensor_value: 'light sensor value',    \n                neobot_rb_sound_sensor_value: 'sound sensor value',    \n                neobot_rb_top_sensor_value: 'top sensor value',\n                neobot_rb_bottom_sensor_value: 'bottom sensor value',\n\n                neobot_rb_led_on_type1: 'Turn on the LED in %1 brightness %2',\n                neobot_rb_led_on_type2: 'Turn on the LED in %1 brightness for %2 second(s) and turn off %3',\n                neobot_rb_led_off: 'Turn off the LED %1',\n                neobot_rb_led_on_type3: 'Turn on the LED connected %1 in %2 briteness %3',\n                neobot_rb_led_on_type4: 'Turn on the LED connected %1 in %2 briteness for %3 second(s) and turn off %4',\n                neobot_rb_led_off_type1:'Turn off the LED connected %1 %2',\n\n                neobot_rb_output_type1: \"Output %2 to the external port connected %1 %3\",\n\n                neobot_rb_motor_type1: \"Rotate %1 motor(s) in %2 speed for %3 second(s) and stop %4\",\n                neobot_rb_motor_type2: \"Rotate both motors in %2 speed %1 %3\",\n                neobot_rb_motor_type3: \"Rotate %1 motor(s) to %2 speed %3\",\n                neobot_rb_motor_stop: \"Stop %1 motor(s) %2\",\n                neobot_rb_motor_type_select: \"Go %1 the robot %2\",\n                neobot_rb_motor_type_stop: \"Stop the robot %1\",\n\n                neobot_rb_ir_decision: 'infrared sensor activation (reference value: %1)',\n                neobot_rb_light_decision: 'light sensor activation (reference value: %1)',\n                neobot_rb_sound_decision: 'sound sensor activation (reference value: %1)',\n                neobot_rb_port_decision: ' %1 activation (reference value: %2)',\n                neobot_rb_top_decision: 'top sensor activation (reference value: %1)',\n                neobot_rb_bottom_decision: 'bottom sensor activation (reference value: %1)',\n                neobot_rb_remote_decision : 'pressing button %1 of the remote controller',\n                \n                neobot_rb_servo_init: 'Initialize servo motor connected %1 to current place %2',\n                neobot_rb_servo_turn_type1: 'Rotate servo motor connected %1 to %2 at %3 degrees %4',\n                neobot_rb_servo_turn_type2: 'Rotate servo motor connected %1 at %2 degrees %3',\n                neobot_rb_servo_turn_type4: 'Set to %2 the rotation speed of servo motor connected %1 %3', \n                neobot_rb_servo_turn_type5: 'Rotate servo motor connected %1 to %2 in %3 speed constantly',\n                neobot_rb_servo_mode_manual: 'Change servo motor connected %1 to manual control mode %2',\n                neobot_rb_servo_stop: 'Stop servo motor connected %1 %2',\n\n                neobot_rb_led: '%1',\n                neobot_rb_time: '%1',\n                neobot_rb_time2: '%1',\n                neobot_rb_speed: '%1',\n                neobot_rb_speed2: '%1',\n                neobot_rb_surface: '%1',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_rb_port_1: 'port 1',\n                neobot_rb_port_2: 'port 2',\n                neobot_rb_port_3: 'port 3',\n                neobot_rb_port_4: 'port 4',\n                neobot_rb_port_top: 'top port',\n                neobot_rb_port_bottom: 'bottom port',\n\n                neobot_rb_top_face: 'top face',\n                neobot_rb_bottom_face: 'bottom face',\n\n                neobot_rb_motor_both: 'both',\n                neobot_rb_motor_left: 'left',\n                neobot_rb_motor_right: 'right',\n\n                neobot_rb_motor_dir_front: 'forward',\n                neobot_rb_motor_dir_rear: 'backward',\n                neobot_rb_motor_dir_left: 'left',\n                neobot_rb_motor_dir_right: 'right',\n                neobot_rb_motor_dir_stand_left: 'left in place',\n                neobot_rb_motor_dir_stand_right: 'right in place',\n\n                neobot_rb_motor_move_forward: 'go forward',\n                neobot_rb_motor_move_backward: 'go backward',\n                neobot_rb_motor_move_left: 'turn Left',\n                neobot_rb_motor_move_right: 'turn Right',\n                neobot_rb_motor_move_stop: 'stop',\n\n                neobot_rb_remote_btn_a: 'A',\n                neobot_rb_remote_btn_b: 'B',\n                neobot_rb_remote_btn_c: 'C',\n                neobot_rb_remote_btn_d: 'D',\n                neobot_rb_remote_btn_1: '1',\n                neobot_rb_remote_btn_2: '2',\n                neobot_rb_remote_btn_3: '3',\n                neobot_rb_remote_btn_4: '4',\n                neobot_rb_remote_btn_up: '▲',\n                neobot_rb_remote_btn_down: '▼',\n                neobot_rb_remote_btn_left: '◀',\n                neobot_rb_remote_btn_right: '▶',\n\n                neobot_rb_servo_dir_1: 'Clockwise',\n                neobot_rb_servo_dir_2: 'Counterclockwise',\n            },\n        }, \n    };\n};\n\nEntry.NeobotRobotTheme.blockMenuBlocks = [\n    /* \n        class order : sensor - motor - decision - remote - led - servo\n    */\n    // class sensor\n    'neobot_rb_port_value',\n    'neobot_rb_ir_sensor_value',\n    'neobot_rb_light_sensor_value',\n    'neobot_rb_sound_sensor_value',\n    'neobot_rb_top_sensor_value',\n    'neobot_rb_bottom_sensor_value',\n    // class motor\n    'neobot_rb_motor_type1',\n    'neobot_rb_motor_type2',\n    'neobot_rb_motor_type3',\n    'neobot_rb_motor_stop',\n    'neobot_rb_motor_type_select',\n    'neobot_rb_motor_type_stop',\n    // class decision\n    'neobot_rb_ir_decision',\n    'neobot_rb_light_decision',\n    'neobot_rb_sound_decision',\n    'neobot_rb_top_decision',\n    'neobot_rb_bottom_decision',\n    'neobot_rb_port_decision',\n    // class remote\n    'neobot_rb_remote_decision',\n    // class led\n    'neobot_rb_led_on_type1',\n    'neobot_rb_led_on_type2',\n    'neobot_rb_led_off',\n    'neobot_rb_led_on_type3',\n    'neobot_rb_led_on_type4',\n    'neobot_rb_led_off_type1',\n    'neobot_rb_output_type1',\n    // class servo\n    'neobot_rb_servo_init',\n    'neobot_rb_servo_turn_type1',\n    'neobot_rb_servo_turn_type2',\n    'neobot_rb_servo_turn_type4',\n    'neobot_rb_servo_turn_type5',\n    'neobot_rb_servo_mode_manual',\n    'neobot_rb_servo_stop',\n];\n\n// macro function\nfunction sleep(ms){\n    return new Promise(resolve=>{\n        setTimeout(resolve,ms)\n    })\n}\n\n\nEntry.NeobotRobotTheme.getBlocks = function() {\n    return {\n        // class sensor\n        neobot_rb_port_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_rb_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_rb_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_rb_port_4, 'IN4'],\n                        [Lang.Blocks.neobot_rb_port_top, 'TOP'],\n                        [Lang.Blocks.neobot_rb_port_bottom, 'BOTTOM'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'neobot_rb_port_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            events: {},\n            class: 'sensor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                if(port == 'TOP') {\n                    port = 'IN1';\n                }\n                if(port == 'BOTTOM') {\n                    port = 'IN2';\n                }\n                return Entry.hw.portData[port];\n            },\n        },\n\n        neobot_rb_ir_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'neobot_rb_ir_sensor_value',\n            },\n            paramsKeyMap: {},\n            events: {},\n            class: 'sensor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var sensor1 = Entry.hw.portData['IN1'];\n                var sensor2 = Entry.hw.portData['IN2'];\n                return sensor1 >= sensor2 ? sensor1 : sensor2;\n            },\n        },\n\n        neobot_rb_light_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'neobot_rb_light_sensor_value',\n            },\n            paramsKeyMap: {},\n            events: {},\n            class: 'sensor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                return Entry.hw.portData['IN3'];\n            },\n        },\n\n        neobot_rb_sound_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'neobot_rb_sound_sensor_value',\n            },\n            paramsKeyMap: {},\n            events: {},\n            class: 'sensor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                return Entry.hw.portData['IN4'];\n            },\n        },\n\n        neobot_rb_top_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'neobot_rb_top_sensor_value',\n            },\n            paramsKeyMap: {},\n            events: {},\n            class: 'sensor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                return Entry.hw.portData['IN1'];\n            },\n        },\n\n        neobot_rb_bottom_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'neobot_rb_bottom_sensor_value',\n            },\n            paramsKeyMap: {},\n            events: {},\n            class: 'sensor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                return Entry.hw.portData['IN2'];\n            },\n        },\n\n        // class motor\n        neobot_rb_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['MAX', '+100'],\n                        ['+100', '+99'],\n                        ['+90', '+90'],\n                        ['+80', '+80'],\n                        ['+70', '+70'],\n                        ['+60', '+60'],\n                        ['+50', '+50'],\n                        ['+40', '+40'],\n                        ['+30', '+30'],\n                        ['+20', '+20'],\n                        ['+10', '+10'],\n                        ['-10', '-10'],\n                        ['-20', '-20'],\n                        ['-30', '-30'],\n                        ['-40', '-40'],\n                        ['-50', '-50'],\n                        ['-60', '-60'],\n                        ['-70', '-70'],\n                        ['-80', '-80'],\n                        ['-90', '-90'],\n                        ['-100', '-100'],\n                    ],\n                    value: '+50',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n        neobot_rb_speed2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100', '99'],\n                        ['90', '90'],\n                        ['80', '80'],\n                        ['70', '70'],\n                        ['60', '60'],\n                        ['50', '50'],\n                        ['40', '40'],\n                        ['30', '30'],\n                        ['20', '20'],\n                        ['10', '10'],\n                    ],\n                    value: '99',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n        neobot_rb_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n        neobot_rb_time2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n        neobot_rb_motor_type1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_motor_both, '1'],\n                        [Lang.Blocks.neobot_rb_motor_left, '2'],\n                        [Lang.Blocks.neobot_rb_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '1',\n                    {\n                        type: 'neobot_rb_speed',\n                        id: 'm41',\n                    },\n                    {\n                        type: 'neobot_rb_time',\n                        id: 'm21',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_motor_type1',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                SPEED: 1,\n                DURATION: 2,\n            },\n            class: 'motor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    var speed = Entry.parseNumber(script.getNumberValue('SPEED'));\n                    var motor = script.getNumberField('MOTOR');\n                    var duration = script.getNumberValue('DURATION');\n\n                    if (speed > 99) {\n                        speed = 99;\n                    } else if (speed < -99) {\n                        speed = -99;\n                    }\n\n                    speed += 100;\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    switch (motor) {\n                        case 1:\n                            Entry.hw.sendQueue['DCL'] = speed;\n                            Entry.hw.sendQueue['DCR'] = speed;\n                            break;\n                        case 2:\n                            Entry.hw.sendQueue['DCL'] = speed;\n                            break;\n                        case 3:\n                            Entry.hw.sendQueue['DCR'] = speed;\n                            break;\n                    }\n\n                    if (duration === 0) {\n                        return script.callReturn();\n                    } else {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(function() {\n                            script.timeFlag = 0;\n                        }, duration * 1000);\n                        return script;\n                    }\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['DCL'] = 100;\n                    Entry.hw.sendQueue['DCR'] = 100;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_rb_motor_type2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_motor_dir_front, '1'],\n                        [Lang.Blocks.neobot_rb_motor_dir_rear, '2'],\n                        [Lang.Blocks.neobot_rb_motor_dir_left, '3'],\n                        [Lang.Blocks.neobot_rb_motor_dir_right, '4'],\n                        [Lang.Blocks.neobot_rb_motor_dir_stand_left, '5'],\n                        [Lang.Blocks.neobot_rb_motor_dir_stand_right, '6'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '1',\n                    {\n                        type: 'neobot_rb_speed2',\n                        id: 'm51',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_motor_type2',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                SPEED: 1,\n            },\n            class: 'motor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var direction = script.getNumberField('DIRECTION');\n                var speed = Entry.parseNumber(script.getNumberValue('SPEED'));\n\n                if (speed > 99) {\n                    speed = 99;\n                } else if (speed < -99) {\n                    speed = -99;\n                }\n\n                switch (direction) {\n                    case 1: // forward\n                        Entry.hw.sendQueue['DCL'] = speed + 100;\n                        Entry.hw.sendQueue['DCR'] = speed + 100;\n                        break;\n                    case 2: // backward\n                        Entry.hw.sendQueue['DCL'] = 100 - speed;\n                        Entry.hw.sendQueue['DCR'] = 100 - speed;\n                        break;\n                    case 3: // left\n                        Entry.hw.sendQueue['DCL'] = (speed/5) + 100;\n                        Entry.hw.sendQueue['DCR'] = speed + 100;\n                        break;\n                    case 4: // right\n                        Entry.hw.sendQueue['DCL'] = speed + 100;\n                        Entry.hw.sendQueue['DCR'] = (speed/5) + 100;\n                        break;\n                    case 5: // left in place\n                        Entry.hw.sendQueue['DCL'] = 100 - speed;\n                        Entry.hw.sendQueue['DCR'] = speed + 100;\n                        break;\n                    case 6: // right in place\n                        Entry.hw.sendQueue['DCL'] = speed + 100;\n                        Entry.hw.sendQueue['DCR'] = 100 - speed;\n                        break;\n                }\n            },\n        },\n        \n        neobot_rb_motor_type3: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_motor_both, '1'],\n                        [Lang.Blocks.neobot_rb_motor_left, '2'],\n                        [Lang.Blocks.neobot_rb_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '1',\n                    {\n                        type: 'neobot_rb_port_value',\n                        id: 'm500',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_motor_type3',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                SPEED: 1,\n            },\n            class: 'motor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var motor = script.getNumberField('MOTOR');\n                var speed = Entry.parseNumber(script.getNumberValue('SPEED'));\n\n                if (speed > 99) {\n                    speed = 99;\n                } else if (speed < -99) {\n                    speed = -99;\n                }\n\n                switch (motor) {\n                    case 1:\n                        Entry.hw.sendQueue['DCL'] = speed + 100;\n                        Entry.hw.sendQueue['DCR'] = speed + 100;\n                        break;\n                    case 2:\n                        Entry.hw.sendQueue['DCL'] = (speed / 5) + 100;\n                        Entry.hw.sendQueue['DCR'] = 100;\n                        break;\n                    case 3:\n                        Entry.hw.sendQueue['DCL'] = 100;\n                        Entry.hw.sendQueue['DCR'] = (speed / 5) + 100;\n                        break;\n                }\n            },\n        },\n\n        neobot_rb_motor_type_select: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_motor_move_forward, '1'],\n                        [Lang.Blocks.neobot_rb_motor_move_backward, '2'],\n                        [Lang.Blocks.neobot_rb_motor_move_left, '3'],\n                        [Lang.Blocks.neobot_rb_motor_move_right, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'neobot_rb_motor_type_select',\n            },\n            paramsKeyMap: {\n                MOVE: 0,\n            },\n            class: 'motor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var move = script.getNumberField('MOVE');\n                switch (move) {\n                    case 1:\n                        Entry.hw.sendQueue['DCL'] = 100 + 99;\n                        Entry.hw.sendQueue['DCR'] = 100 + 99;\n                        break;\n                    case 2:\n                        Entry.hw.sendQueue['DCL'] = 100 - 99;\n                        Entry.hw.sendQueue['DCR'] = 100 - 99;\n                        break;\n                    case 3:\n                        Entry.hw.sendQueue['DCL'] = 100 - 20; // use 20 to make slower \n                        Entry.hw.sendQueue['DCR'] = 100 + 20;\n                        break;\n                    case 4:\n                        Entry.hw.sendQueue['DCL'] = 100 + 20;\n                        Entry.hw.sendQueue['DCR'] = 100 - 20;\n                        break;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_rb_motor_type_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_rb_motor_type_stop',\n            },\n            paramsKeyMap: {},\n            class: 'motor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                Entry.hw.sendQueue['DCL'] = 100;\n                Entry.hw.sendQueue['DCR'] = 100;\n                return script.callReturn();\n            },\n        },\n\n        neobot_rb_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_motor_both, '1'],\n                        [Lang.Blocks.neobot_rb_motor_left, '2'],\n                        [Lang.Blocks.neobot_rb_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '1',\n                    null,\n                ],\n                type: 'neobot_rb_motor_stop',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n            },\n            class: 'motor',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var motor = script.getNumberField('MOTOR');\n\n                switch (motor) {\n                    case 1:\n                        Entry.hw.sendQueue['DCL'] = 100;\n                        Entry.hw.sendQueue['DCR'] = 100;\n                        break;\n                    case 2:\n                        Entry.hw.sendQueue['DCL'] = 100;\n                        Entry.hw.sendQueue['DCR'] = 255;\n                        break;\n                    case 3:\n                        Entry.hw.sendQueue['DCL'] = 255;\n                        Entry.hw.sendQueue['DCR'] = 100;\n                        break;\n                }\n                return script.callReturn();\n            },\n        },\n\n        // class led\n        neobot_rb_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['10%', '10'],\n                        ['20%', '20'],\n                        ['30%', '30'],\n                        ['40%', '40'],\n                        ['50%', '50'],\n                        ['60%', '60'],\n                        ['70%', '70'],\n                        ['80%', '80'],\n                        ['90%', '90'],\n                        ['100%', '100'],\n                    ],\n                    value: '100',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberField('VALUE');\n            },\n        },\n\n        neobot_rb_surface: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_top_face, 'OUT1'],\n                        [Lang.Blocks.neobot_rb_bottom_face, 'OUT2'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        neobot_rb_led_on_type1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_led',\n                        id: 'm16',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_led_on_type1',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'led',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var value = script.getNumberValue('VALUE');\n                if (value > 100) {\n                    value = 100;\n                } else if (value < 0) {\n                    value = 0;\n                }\n                Entry.hw.sendQueue['LED'] = value;\n                return script.callReturn();\n            },\n        },\n\n        neobot_rb_led_on_type2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_led',\n                        id: 'm12',\n                    },\n                    {\n                        type: 'neobot_rb_time2',\n                        id: 'm31',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_led_on_type2',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                DURATION: 1,\n            },\n            class: 'led',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    var value = script.getNumberValue('VALUE');\n                    var duration = script.getNumberValue('DURATION');\n\n                    if (value > 100) {\n                        value = 100;\n                    } else if (value < 0) {\n                        value = 0;\n                    }\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    Entry.hw.sendQueue['LED'] = value;\n\n                    if (duration === 0) {\n                        return script.callReturn();\n                    } else {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(function() {\n                            script.timeFlag = 0;\n                        }, duration * 1000);\n                        return script;\n                    }\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['LED'] = 0;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        neobot_rb_led_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_rb_led_off',\n            },\n            class: 'led',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                Entry.hw.sendQueue['LED'] = 0;\n                return script.callReturn();\n            },\n        },\n\n        neobot_rb_led_on_type3: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm611',\n                    },\n                    {\n                        type: 'neobot_rb_led',\n                        id: 'm13',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_led_on_type3',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n                VALUE: 1,\n            },\n            class: 'led',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var face = script.getStringValue('SURFACE');\n                var value = script.getNumberValue('VALUE');\n\n                if (value > 100) {\n                    value = 100;\n                } else if (value < 0) {\n                    value = 0;\n                }\n\n                Entry.hw.sendQueue[face] = value;\n            },\n        },\n\n        neobot_rb_led_on_type4: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm612',\n                    },\n                    {\n                        type: 'neobot_rb_led',\n                        id: 'm14',\n                    },\n                    {\n                        type: 'neobot_rb_time2',\n                        id: 'm32',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_led_on_type4',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n                VALUE: 1,\n                DURATION: 2,\n            },\n            class: 'led',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    var face = script.getStringValue('SURFACE');\n                    var value = script.getNumberValue('VALUE');\n                    var duration = script.getNumberValue('DURATION');\n\n                    if (value > 100) {\n                        value = 100;\n                    } else if (value < 0) {\n                        value = 0;\n                    }\n                    \n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    \n                    Entry.hw.sendQueue[face] = value;\n                    \n                    if (duration === 0) {\n                        return script.callReturn();\n                    } else {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(function() {\n                            Entry.hw.sendQueue[face] = 0;\n                            script.timeFlag = 0;\n                        }, duration * 1000);\n                        return script;\n                    }\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    \n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_rb_led_off_type1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm613',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_led_off_type1',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n            },\n            class: 'led',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var face = script.getStringValue('SURFACE');\n                Entry.hw.sendQueue[face] = 0;\n                return script.callReturn();\n            },\n        },\n\n        neobot_rb_output_type1 : {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm614',\n                    },\n                    100,\n                    null,\n                ],\n                type: 'neobot_rb_output_type1',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n                VALUE: 1,\n            },\n            class: 'led',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var face = script.getStringValue('SURFACE');\n                var value = script.getNumberValue('VALUE');\n                \n                if(value > 255) {\n                    value = 255;\n                }\n                if(value < 0) {\n                    value = 0;\n                }\n\n                Entry.hw.sendQueue[face] = value;\n            },\n        },\n\n        // class decision\n        neobot_rb_ir_decision: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '10',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_rb_ir_decision',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var sensor1 = Entry.hw.portData['IN1'];\n                var sensor2 = Entry.hw.portData['IN2'];\n                var sensor = sensor1 >= sensor2 ? sensor1 : sensor2;\n\n                if (sensor >= value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n        neobot_rb_light_decision: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '10',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_rb_light_decision',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var sensor = Entry.hw.portData['IN3'];\n\n                if (sensor >= value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        neobot_rb_sound_decision: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '10',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_rb_sound_decision',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var sensor = Entry.hw.portData['IN4'];\n\n                if (sensor >= value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        neobot_rb_top_decision: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '10',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_rb_top_decision',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var sensor = Entry.hw.portData['IN1'];\n\n                if (sensor >= value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        neobot_rb_bottom_decision: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '10',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_rb_bottom_decision',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var value = script.getNumberValue('VALUE');\n                var sensor = Entry.hw.portData['IN2'];\n\n                if (sensor >= value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        neobot_rb_port_decision: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_rb_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_rb_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_rb_port_4, 'IN4'],\n                        [Lang.Blocks.neobot_rb_port_top, 'TOP'],\n                        [Lang.Blocks.neobot_rb_port_bottom, 'BOTTOM'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '10',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    'IN1',\n                    '10',\n                    null,\n                ],\n                type: 'neobot_rb_port_decision',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                // change port from TOP/BOTTOM face to IN1/IN2.\n                if(port == 'TOP') {\n                    port = 'IN1';\n                }\n                if(port == 'BOTTOM') {\n                    port = 'IN2';\n                }\n\n                var sensor = Entry.hw.portData[port];\n                var value = script.getNumberValue('VALUE');\n\n                if (sensor >= value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        // class remote\n        neobot_rb_remote_decision: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_remote_btn_a, '1'],\n                        [Lang.Blocks.neobot_rb_remote_btn_b, '2'],\n                        [Lang.Blocks.neobot_rb_remote_btn_c, '3'],\n                        [Lang.Blocks.neobot_rb_remote_btn_d, '4'],\n                        [Lang.Blocks.neobot_rb_remote_btn_1, '5'],\n                        [Lang.Blocks.neobot_rb_remote_btn_2, '6'],\n                        [Lang.Blocks.neobot_rb_remote_btn_3, '7'],\n                        [Lang.Blocks.neobot_rb_remote_btn_4, '8'],\n                        [Lang.Blocks.neobot_rb_remote_btn_up, '11'],\n                        [Lang.Blocks.neobot_rb_remote_btn_down, '12'],\n                        [Lang.Blocks.neobot_rb_remote_btn_left, '14'],\n                        [Lang.Blocks.neobot_rb_remote_btn_right, '13'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_rb_remote_decision',\n            },\n            paramsKeyMap: {\n                KEY: 0,\n            },\n            class: 'remote',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                var key = script.getNumberField('KEY');\n                var value = Entry.hw.portData['IR'];\n                if(key >= 5 && key <= 8)\n                    key -= 4;\n                if(key == value){\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        // class servo\n        neobot_rb_servo_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm615',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_servo_init',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n            },\n            class: 'servo',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var face = script.getStringValue('SURFACE');\n                    Entry.hw.sendQueue[face] = 0xBA;\n                    \n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        Entry.hw.sendQueue[face] = 0x01;\n                        setTimeout(function() {\n                            script.timeFlag = 0;\n                        }, 200);\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_rb_servo_turn_type1: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_rb_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm616',\n                    },\n                    null,\n                    180,\n                    null,\n                ],\n                type: 'neobot_rb_servo_turn_type1',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n                DIRECTION: 1,\n                DEGREE: 2\n            },\n            class: 'servo',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var face = script.getStringValue('SURFACE');\n                    var direction = script.getNumberField('DIRECTION');\n                    var value = script.getNumberValue('DEGREE');\n                    \n                    switch (direction) {\n                        case 1:\n                        Entry.hw.sendQueue[face] = 0xBC;\n                        break;\n                        case 2:\n                        Entry.hw.sendQueue[face] = 0xBD;\n                        break;\n                    }\n                    \n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        if(value > 180) {\n                            value = 180;\n                        }\n                        if (value < 0){\n                            value = 0;\n                        }\n                        value = value + 1;\n                        Entry.hw.sendQueue[face] = value;\n                        setTimeout(function() {\n                            script.timeFlag = 0;\n                        }, 1000);\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_rb_servo_turn_type2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm617',\n                    },\n                    180,\n                    null,\n                ],\n                type: 'neobot_rb_servo_turn_type2',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n                DEGREE: 1\n            },\n            class: 'servo',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var face = script.getStringValue('SURFACE');\n                    var value = script.getNumberValue('DEGREE');\n                    \n                    if(value > 0xB4) {\n                        value = 0xB4;\n                    }\n                    if (value < 0x00){\n                        value = 0x00;\n                    }\n                    value = value + 0x01;\n                    Entry.hw.sendQueue[face] = value;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_rb_servo_turn_type4: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100%', '0'],\n                        ['90%', '1'],\n                        ['80%', '2'],\n                        ['70%', '3'],\n                        ['60%', '4'],\n                        ['50%', '5'],\n                        ['40%', '6'],\n                        ['30%', '7'],\n                        ['20%', '8'],\n                        ['10%', '9'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm618',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'neobot_rb_servo_turn_type4',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n                LEVEL: 1,\n            },\n            class: 'servo',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var face = script.getStringValue('SURFACE');\n                    var level = script.getNumberField('LEVEL');\n                    Entry.hw.sendQueue[face] = 0xFA - level;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_rb_servo_turn_type5: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_rb_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_rb_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100%', '0'],\n                        ['90%', '1'],\n                        ['80%', '2'],\n                        ['70%', '3'],\n                        ['60%', '4'],\n                        ['50%', '5'],\n                        ['40%', '6'],\n                        ['30%', '7'],\n                        ['20%', '8'],\n                        ['10%', '9'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm619',\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'neobot_rb_servo_turn_type5',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n                DIRECTION: 1,\n                LEVEL: 2,\n            },\n            class: 'servo',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var face = script.getStringValue('SURFACE');\n                    var direction = script.getNumberField('DIRECTION');\n                    var level = script.getNumberField('LEVEL');\n    \n                    switch (direction) {\n                        case 1:\n                            Entry.hw.sendQueue[face] = 0xCA - level;\n                            break;\n                        case 2:\n                            Entry.hw.sendQueue[face] = 0xDA - level;\n                            break;\n                    }\n                    \n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_rb_servo_mode_manual: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm620',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_servo_mode_manual',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n            },\n            class: 'servo',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var face = script.getStringValue('SURFACE');\n                    \n                    Entry.hw.sendQueue[face] = 0x00;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        timeFlag = 0;\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_rb_servo_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'neobot_rb_surface',\n                        id: 'm621',\n                    },\n                    null,\n                ],\n                type: 'neobot_rb_servo_stop',\n            },\n            paramsKeyMap: {\n                SURFACE: 0,\n            },\n            class: 'servo',\n            isNotFor: ['neobot_robot_theme'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    var face = script.getStringValue('SURFACE');\n                    \n                    Entry.hw.sendQueue[face] = 0xFE;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        timeFlag = 0;\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        // end neobot robot theme region\n    };\n};\n\nmodule.exports = Entry.NeobotRobotTheme;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neobot_sensor_theme.js",
    "content": "Entry.NeobotSensorTheme = {\n    id: '5.2',\n    name: 'neobot_sensor_theme',\n    url: 'http://www.neobot.co.kr',\n    imageName: 'neobot_sensor_theme.png',\n    title: {\n        \"en\": \"NEOCODING SensorTheme\",\n        \"ko\": \"네오코딩 센서테마\"\n    },\n    LOCAL_MAP: [\n        'IN1',\n        'IN2',\n        'IN3',\n        'IR',\n        'BAT'\n    ],\n    REMOTE_MAP: [\n        'OUT1',\n        'OUT2',\n        'OUT3',\n        'DCR',\n        'DCL',\n        'SND',\n        'FND',\n        'OPT'\n    ],\n    setZero: function () {\n        for(var port in Entry.NeobotSensorTheme.REMOTE_MAP) {\n            Entry.hw.sendQueue[Entry.NeobotSensorTheme.REMOTE_MAP[port]] = 0;\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neobot_sensor_theme.png',\n        width: 800,\n        height: 800,\n        listPorts: {\n        },\n        ports: {\n            'IN1':{name: 'PORT1', type: 'input', pos: {x: 145, y: 429}},\n            'IN2':{name: 'PORT2', type: 'input', pos: {x : 314, y: 429}},\n            'IN3':{name: 'PORT3', type: 'input', pos: {x: 484, y: 429}},\n            'BAT':{name: 'PORT4', type: 'input', pos: {x: 653, y: 429}}\n        },\n        mode: 'both'\n    }\n};\n\n Entry.NeobotSensorTheme.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                neobot_st_sensor_value: '%1 값',\n                neobot_st_sensor_connect_external: '%1 에 연결한 %2 값',\n                neobot_st_sensor_convert_scale: '%1 센서값 %2 ~ %3 를 %4 ~ %5 (으)로 바꾼 값',\n\n                neobot_st_compare_symbol: '%1',\n                neobot_st_decision_sensor_is_over: '%1 의 센서값이 %2 %3',\n                neobot_st_decision_equal_with_sensor: '%1 에 연결한 컬러센서가 %2 을 감지함',\n\n                neobot_st_output_led_on: '%1 에 연결한 LED 켜기 %2',\n                neobot_st_output_led_off: '%1 에 연결한 LED 끄기 %2',\n                neobot_st_set_output: '%1 에 %2 값만큼 출력 %3',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_st_port_1 : \"1번 포트\",\n                neobot_st_port_2 : \"2번 포트\",\n                neobot_st_port_3 : \"3번 포트\",\n                neobot_st_port_4 : \"4번 포트\",\n                neobot_st_color_white : \"흰색\",\n                neobot_st_color_red : \"빨간색\",\n                neobot_st_color_yellow : \"노란색\",\n                neobot_st_color_green : \"초록색(연두색)\",\n                neobot_st_color_blue : \"파란색\",\n                neobot_st_sensor_infrared : '적외선센서',\n                neobot_st_sensor_light : '빛센서',\n                neobot_st_sensor_sound : '소리센서',\n                neobot_st_compare_symbol1 : '＝',\n                neobot_st_compare_symbol2 : '＞',\n                neobot_st_compare_symbol3 : '＜',\n                neobot_st_compare_symbol4 : '≥',\n                neobot_st_compare_symbol5 : '≤',\n            }\n        },\n        en: {\n            template: {\n                neobot_st_sensor_value: '%1 value',\n                neobot_st_sensor_connect_external: 'the %2 value connected %1',\n                neobot_st_sensor_convert_scale: \"the value that is changed %1 sensor value %2 ~%3 to %4 ~ %5\",\n\n                neobot_st_compare_symbol: '%1',\n                neobot_st_decision_sensor_is_over: \"%1 sensor value %2 %3\",\n                neobot_st_decision_equal_with_sensor: \"being detected %2 by %1 color sensor\",\n                neobot_st_remote_button : 'pressing button %1 of remote controller',\n\n                neobot_st_output_led_on: 'Turn on the LED connected %1 %2',\n                neobot_st_output_led_off: 'Turn off the LED connected %1 %2',\n                neobot_st_set_output: 'Output %1 port value to %2 %3',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_st_port_1: 'port1',\n                neobot_st_port_2: 'port2',\n                neobot_st_port_3: 'port3',\n                neobot_st_port_4: 'port4',\n                neobot_st_color_white: 'white',\n                neobot_st_color_red: 'red',\n                neobot_st_color_yellow: 'yellow',\n                neobot_st_color_green: 'green',\n                neobot_st_color_blue: 'blue',\n                neobot_st_sensor_infrared : 'IR sensor',\n                neobot_st_sensor_light : 'light sensor',\n                neobot_st_sensor_sound : 'sound sensor',\n                neobot_st_compare_symbol1 : '＝',\n                neobot_st_compare_symbol2 : '＞',\n                neobot_st_compare_symbol3 : '＜',\n                neobot_st_compare_symbol4 : '≥',\n                neobot_st_compare_symbol5 : '≤',\n            },\n        }, //\n    };\n};\n\nEntry.NeobotSensorTheme.blockMenuBlocks = [\n    // class sensor\n    'neobot_st_sensor_value',\n    'neobot_st_sensor_connect_external',\n    'neobot_st_sensor_convert_scale',\n    // class decision\n    'neobot_st_decision_sensor_is_over',\n    'neobot_st_decision_equal_with_sensor',\n    // class output\n    'neobot_st_output_led_on',\n    'neobot_st_output_led_off',\n    'neobot_st_set_output',\n];\n\nEntry.NeobotSensorTheme.getBlocks = function() {\n    return { // region neobot sensor theme\n\n        // class sensor\n        neobot_st_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_st_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_st_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_st_port_4, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_st_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port];\n            },\n        },\n\n        neobot_st_sensor_connect_external: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_st_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_st_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_st_port_4, 'BAT'],\n\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_sensor_infrared, '1'],\n                        [Lang.Blocks.neobot_st_sensor_light, '2'],\n                        [Lang.Blocks.neobot_st_sensor_sound, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_st_sensor_connect_external',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensor',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port];\n            },\n        },\n\n        neobot_st_sensor_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_st_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_st_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_st_port_4, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'neobot_st_sensor_convert_scale',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OMIN: 1,\n                OMAX: 2,\n                MIN: 3,\n                MAX: 4,\n            },\n            class: 'sensor',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                var value = Entry.hw.portData[port];\n                var omin = script.getNumberValue('OMIN', script);\n                var omax = script.getNumberValue('OMAX', script);\n                var min = script.getNumberValue('MIN', script);\n                var max = script.getNumberValue('MAX', script);\n\n                if (omin > omax) {\n                    var temp = omin;\n                    omin = omax;\n                    omax = temp;\n                }\n\n                if (min > max) {\n                    var temp = min;\n                    min = max;\n                    max = temp;\n                }\n\n                value -= omin;\n                value = value * ((max - min) / (omax - omin));\n                value += min;\n                value = Math.min(max, value);\n                value = Math.max(min, value);\n\n                return Math.round(value);\n            },\n        },\n\n        // class decision\n        // un-used. use if required pluggable block.\n        neobot_st_compare_symbol :{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_st_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_st_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_st_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_st_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_st_compare_symbol',\n            },\n            paramsKeyMap: {\n                SYMBOL: 0,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                return  script.getStringField('SYMBOL');\n            },\n        },\n\n        neobot_st_decision_sensor_is_over: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_st_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_st_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_st_port_4, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_st_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_st_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_st_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_st_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, 10],\n                type: 'neobot_st_decision_sensor_is_over',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                SYMBOL: 1,\n                VALUE: 2,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var symbol = script.getStringField('SYMBOL');\n                var value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                if (symbol == '=') {\n                    if(sensor == value) return true;\n                    else return false;\n                } else if (symbol == '>') {\n                    if(sensor > value) return true;\n                    else return false;\n                } else if (symbol == '<') {\n                    if(sensor < value) return true;\n                    else return false;\n                } else if (symbol == '>=') {\n                    if(sensor >= value) return true;\n                    else return false;\n                } else if (symbol == '<=') {\n                    if(sensor <= value) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        neobot_st_decision_equal_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_st_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_st_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_st_port_4, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_color_white, 0],\n                        [Lang.Blocks.neobot_st_color_red, 1],\n                        [Lang.Blocks.neobot_st_color_yellow, 2],\n                        [Lang.Blocks.neobot_st_color_green, 3],\n                        [Lang.Blocks.neobot_st_color_blue, 4],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_st_decision_equal_with_sensor',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                COLOR: 1,\n            },\n            class: 'decision',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var color = script.getNumberField('COLOR');\n\n                if (sensor >= 10 && sensor <= 50) {\n                    if (color == 0) return true;\n                    else return false;\n                } else if (sensor >= 51 && sensor <= 90) {\n                    if (color == 1) return true;\n                    else return false;\n                } else if (sensor >= 91 && sensor <= 130) {\n                    if (color == 2) return true;\n                    else return false;\n                } else if (sensor >= 131 && sensor <= 170) {\n                    if (color == 3) return true;\n                    else return false;\n                } else if (sensor >= 171 && sensor <= 210) {\n                    if (color == 4) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        // class output\n        neobot_st_output_led_on : {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_port_1, 'OUT1'],\n                        [Lang.Blocks.neobot_st_port_2, 'OUT2'],\n                        [Lang.Blocks.neobot_st_port_3, 'OUT3'],\n                        [Lang.Blocks.neobot_st_port_4, 'FND'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_st_output_led_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'output',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var option = port;\n                if (option === 3) {\n                    option = 4;\n                }\n                Entry.hw.sendQueue[port] = 255;\n                Entry.hw.sendQueue['OPT'] = Entry.hw.sendQueue['OPT'] & ~option;\n                return script.callReturn();\n            },\n        },\n        neobot_st_output_led_off : {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_port_1, 'OUT1'],\n                        [Lang.Blocks.neobot_st_port_2, 'OUT2'],\n                        [Lang.Blocks.neobot_st_port_3, 'OUT3'],\n                        [Lang.Blocks.neobot_st_port_4, 'FND'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_st_output_led_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'output',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var option = port;\n                if (option === 3) {\n                    option = 4;\n                }\n                Entry.hw.sendQueue[port] = 0;\n                Entry.hw.sendQueue['OPT'] = Entry.hw.sendQueue['OPT'] & ~option;\n                return script.callReturn();\n            },\n        },\n        neobot_st_set_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_st_port_1, 'OUT1'],\n                        [Lang.Blocks.neobot_st_port_2, 'OUT2'],\n                        [Lang.Blocks.neobot_st_port_3, 'OUT3'],\n                        [Lang.Blocks.neobot_st_port_4, 'FND'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_st_set_output',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'output',\n            isNotFor: ['neobot_sensor_theme'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                var option = port;\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n                var option = port;\n                if (option === 3) {\n                    option = 4;\n                }\n                Entry.hw.sendQueue[port] = value;\n                Entry.hw.sendQueue['OPT'] = Entry.hw.sendQueue['OPT'] & ~option;\n                return script.callReturn();\n            },\n        },\n    }; // end region neobot sensor theme\n};\nmodule.exports = Entry.NeobotSensorTheme;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neobot_soco.js",
    "content": "'use strict';\n\nEntry.NeobotSoco = {\n    id: '5.6',\n    name: 'neobot_soco',\n    url: 'http://www.neobot.co.kr',\n    imageName: 'neobot_soco.png',\n    title: {\n        ko: '네오쏘코(SoCo)',\n        en: 'NEO SoCo',\n    },\n    LOCAL_MAP: ['IN1', 'IN2', 'IN3', 'IR', 'BAT'],\n    REMOTE_MAP: ['OUT1', 'OUT2', 'OUT3', 'DCR', 'DCL', 'SND', 'FND', 'OPT'],\n    setZero: function() {\n        for (var port in Entry.NeobotSoco.REMOTE_MAP) {\n            Entry.hw.sendQueue[Entry.NeobotSoco.REMOTE_MAP[port]] = 0;\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neobot_soco.png',\n        width: 700,\n        height: 700,\n        listPorts: {\n            IR: { name: 'IR', type: 'input', pos: { x: 0, y: 0 } },\n            BAT: { name: 'BAT', type: 'input', pos: { x: 0, y: 0 } },\n            SND: { name: 'SND', type: 'output', pos: { x: 0, y: 0 } },\n            FND: { name: 'FND', type: 'output', pos: { x: 0, y: 0 } },\n        },\n        ports: {\n            IN1: { name: 'IN1', type: 'input', pos: { x: 270, y: 170 } },\n            IN2: { name: 'IN2', type: 'input', pos: { x: 325, y: 170 } },\n            IN3: { name: 'IN3', type: 'input', pos: { x: 325, y: 530 } },\n            DCL: { name: 'L-Motor', type: 'output', pos: { x: 270, y: 530 } },\n            DCR: { name: 'R-Motor', type: 'output', pos: { x: 435, y: 530 } },\n            OUT1: { name: 'OUT1', type: 'output', pos: { x: 380, y: 170 } },\n            OUT2: { name: 'OUT2', type: 'output', pos: { x: 435, y: 170 } },\n            OUT3: { name: 'OUT3', type: 'output', pos: { x: 380, y: 530 } },\n        },\n        mode: 'both',\n    },\n    log_to_console: false,\n};\n\nEntry.NeobotSoco.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                // sensor\n                neobot_soco_sensor_title: '센서',\n                neobot_soco_sensor_value: '%1',\n                neobot_soco_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환',\n                neobot_soco_decision_sensor_is_over: '%1 %2 %3',\n                neobot_soco_decision_equal_with_sensor: '%1 컬러가 %2',\n                neobot_soco_decision_sensor_angle: '%1 각도 %2 %3',\n                neobot_soco_remote_button: '리모컨 버튼 %1 을 누름',\n\n                // LED\n                neobot_soco_led_title: 'LED',\n                neobot_soco_arg_led_duration: '%1',\n                neobot_soco_led_on: 'LED 켜기   %1 %2 %3 %4',\n                neobot_soco_output_led_off: '%1 LED 끄기 %2',\n                neobot_soco_led_brightness_with_sensor: '%1 로 %2 LED 제어 %3',\n                neobot_soco_color_led_on: '%1 컬러LED 켜기   R %2 G %3 B %4 %5',\n\n                // output\n                neobot_soco_output_title: '출력',\n                neobot_soco_set_output: '%1 에 %2 값 출력하기 %3',\n\n                // motor\n                neobot_soco_motor_title: '회전모터',\n                neobot_soco_robot: '로봇 %1 %2',\n                neobot_soco_motor_start: '모터 회전하기   %1 %2 %3 %4 %5',\n                neobot_soco_motor_stop: '%1 모터 멈추기 %2',\n                neobot_soco_arg_motor_speed: '%1',\n                neobot_soco_arg_motor_duration: '%1',\n\n                // melody\n                neobot_soco_buzzer_title: '버저',\n                neobot_soco_play_note_for: '버저 울리기   옥타브: %2 음: %1 길이: %3 %4',\n                neobot_soco_melody_play_with_sensor: '%1 센서로 버저 울리기 %2',\n                neobot_soco_melody_stop: '버저 멈추기 %1',\n\n                // servo\n                neobot_soco_servo_title: '서보모터',\n                get_servo_degree: '%1',\n                neobot_soco_servo_init: '%1 서보모터 리셋 %2',\n                neobot_soco_servo_rotate: '서보모터 회전하기   %1 %2 %3 %4',\n                neobot_soco_servo_stop: '%1 서보모터 멈추기 %2',\n                neobot_soco_servo_change_degree: '서보모터 각도 바꾸기   %2 %3 %4 %1 %5',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_soco_port_1: 'IN1',\n                neobot_soco_port_2: 'IN2',\n                neobot_soco_port_3: 'IN3',\n                neobot_soco_port_4: 'IN4',\n                neobot_soco_port_12: 'IN1 & IN2',\n                neobot_soco_port_bat: '배터리',\n                neobot_soco_port_remot: '리모컨',\n                neobot_soco_color_white: '흰색',\n                neobot_soco_color_red: '빨강',\n                neobot_soco_color_yellow: '노랑',\n                neobot_soco_color_green: '녹색',\n                neobot_soco_color_blue: '파랑',\n                neobot_soco_direction_forward: '앞으로',\n                neobot_soco_direction_backward: '뒤로',\n                neobot_soco_sound_silent: '무음',\n                neobot_soco_sound_do: '도',\n                neobot_soco_sound_do_shop: '도#',\n                neobot_soco_sound_re: '레',\n                neobot_soco_sound_re_shop: '레#',\n                neobot_soco_sound_mi: '미',\n                neobot_soco_sound_fa: '파',\n                neobot_soco_sound_fa_shop: '파#',\n                neobot_soco_sound_so: '솔',\n                neobot_soco_sound_so_shop: '솔#',\n                neobot_soco_sound_la: '라',\n                neobot_soco_sound_la_shop: '라#',\n                neobot_soco_sound_ti: '시',\n                neobot_soco_sound_half_note: '2분 음표',\n                neobot_soco_sound_quarter_note: '4분 음표',\n                neobot_soco_sound_eighth_note: '8분 음표',\n                neobot_soco_sound_sixteenth_note: '16분 음표',\n                neobot_soco_sensor_infrared: '적외선센서',\n                neobot_soco_sensor_light: '빛센서',\n                neobot_soco_sensor_sound: '소리센서',\n                neobot_soco_compare_symbol1: '＝',\n                neobot_soco_compare_symbol2: '＞',\n                neobot_soco_compare_symbol3: '＜',\n                neobot_soco_compare_symbol4: '≥',\n                neobot_soco_compare_symbol5: '≤',\n                neobot_soco_remote_btn_a: 'A',\n                neobot_soco_remote_btn_b: 'B',\n                neobot_soco_remote_btn_c: 'C',\n                neobot_soco_remote_btn_d: 'D',\n                neobot_soco_remote_btn_1: '1',\n                neobot_soco_remote_btn_2: '2',\n                neobot_soco_remote_btn_3: '3',\n                neobot_soco_remote_btn_4: '4',\n                neobot_soco_remote_btn_up: '▲',\n                neobot_soco_remote_btn_down: '▼',\n                neobot_soco_remote_btn_left: '◀',\n                neobot_soco_remote_btn_right: '▶',\n                neobot_soco_duration_cont: '계속',\n                neobot_soco_duration_1s: '1초',\n                neobot_soco_duration_2s: '2초',\n                neobot_soco_duration_3s: '3초',\n                neobot_soco_duration_4s: '4초',\n                neobot_soco_duration_5s: '5초',\n                neobot_soco_duration_6s: '6초',\n                neobot_soco_duration_7s: '7초',\n                neobot_soco_duration_8s: '8초',\n                neobot_soco_duration_9s: '9초',\n                neobot_soco_motor_both: '양쪽',\n                neobot_soco_motor_left: '왼쪽',\n                neobot_soco_motor_right: '오른쪽',\n                neobot_soco_motor_move_forward: '전진',\n                neobot_soco_motor_move_backward: '후진',\n                neobot_soco_motor_move_left: '좌회전',\n                neobot_soco_motor_move_right: '우회전',\n                neobot_soco_motor_move_stop: '정지',\n\n                neobot_soco_servo_dir_1: '정방향',\n                neobot_soco_servo_dir_2: '역방향',\n\n                neobot_soco_percent_10: '10%속도',\n                neobot_soco_percent_20: '20%속도',\n                neobot_soco_percent_30: '30%속도',\n                neobot_soco_percent_40: '40%속도',\n                neobot_soco_percent_50: '50%속도',\n                neobot_soco_percent_60: '60%속도',\n                neobot_soco_percent_70: '70%속도',\n                neobot_soco_percent_80: '80%속도',\n                neobot_soco_percent_90: '90%속도',\n                neobot_soco_percent_100: '100%속도',\n\n                neobot_soco_angle_0: '0도',\n                neobot_soco_angle_5: '5도',\n                neobot_soco_angle_10: '10도',\n                neobot_soco_angle_15: '15도',\n                neobot_soco_angle_20: '20도',\n                neobot_soco_angle_25: '25도',\n                neobot_soco_angle_30: '30도',\n                neobot_soco_angle_35: '35도',\n                neobot_soco_angle_40: '40도',\n                neobot_soco_angle_45: '45도',\n                neobot_soco_angle_50: '50도',\n                neobot_soco_angle_55: '55도',\n                neobot_soco_angle_60: '60도',\n                neobot_soco_angle_65: '65도',\n                neobot_soco_angle_70: '70도',\n                neobot_soco_angle_75: '75도',\n                neobot_soco_angle_80: '80도',\n                neobot_soco_angle_85: '85도',\n                neobot_soco_angle_90: '90도',\n                neobot_soco_angle_95: '95도',\n                neobot_soco_angle_100: '100도',\n                neobot_soco_angle_105: '105도',\n                neobot_soco_angle_110: '110도',\n                neobot_soco_angle_115: '115도',\n                neobot_soco_angle_120: '120도',\n                neobot_soco_angle_125: '125도',\n                neobot_soco_angle_130: '130도',\n                neobot_soco_angle_135: '135도',\n                neobot_soco_angle_140: '140도',\n                neobot_soco_angle_145: '145도',\n                neobot_soco_angle_150: '150도',\n                neobot_soco_angle_155: '155도',\n                neobot_soco_angle_160: '160도',\n                neobot_soco_angle_165: '165도',\n                neobot_soco_angle_170: '170도',\n                neobot_soco_angle_175: '175도',\n                neobot_soco_angle_180: '180도',\n\n                neobot_soco_out_all: '모든',\n                neobot_soco_direction_left: '왼쪽으로',\n                neobot_soco_direction_right: '오른쪽으로',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                // sensor\n                neobot_soco_sensor_title: 'Sensor',\n                neobot_soco_sensor_value: '%1',\n                neobot_soco_sensor_convert_scale:\n                    \"%1 's changed value   range: %2 ~ %3 conversion: %4 ~ %5\",\n                neobot_soco_decision_sensor_is_over: '%1 %2 %3',\n                neobot_soco_decision_equal_with_sensor: \"%1 's color is %2\",\n                neobot_soco_decision_sensor_angle: '%1 angle %2 %3',\n                neobot_soco_remote_button: 'pressing button %1 of remote controller',\n\n                // LED\n                neobot_soco_led_title: 'LED',\n                neobot_soco_arg_led_duration: '%1',\n                neobot_soco_led_on: 'Turn on the LED    %1 %2 %3 %4',\n                neobot_soco_output_led_off: 'Turn off the %1 LED %2',\n                neobot_soco_led_brightness_with_sensor:\n                    \"Control %2 LED's brightness with %1 sensor %3\",\n                neobot_soco_color_led_on: 'Turn on the %1 color LED   R %2 G %3 B %4 %5',\n\n                // output\n                neobot_soco_output_title: 'Set output',\n                neobot_soco_set_output: 'Output %2 value to %1 port %3',\n\n                // motor\n                neobot_soco_motor_title: 'Motor',\n                neobot_soco_robot: 'Robot %1 %2',\n                neobot_soco_motor_start: 'Motor operation   %1 %2 %3 %4 %5',\n                neobot_soco_motor_stop: 'Stop the %1 motor(s) %2',\n                neobot_soco_arg_motor_speed: '%1',\n                neobot_soco_arg_motor_duration: '%1',\n\n                // melody\n                neobot_soco_buzzer_title: 'Buzzer',\n                neobot_soco_play_note_for: 'Buzzer   octave: %1 scale: %2 note: %3 %4',\n                neobot_soco_melody_play_with_sensor: 'Buzzer rings by %1 sensor value %2',\n                neobot_soco_melody_stop: 'Stop the buzzer %1',\n\n                // servo\n                neobot_soco_servo_title: 'Servo motor',\n                neobot_soco_servo_init: 'Reset the %1 servo motor %2',\n                neobot_soco_servo_rotate: 'Rotate the servo motor   %1 %2 %3 %4',\n                neobot_soco_servo_stop: 'Stop the %1 servo motor %2',\n                neobot_soco_servo_change_degree: 'Change servo angle   %1 %2 %3 %4 %5',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_soco_port_1: 'IN1',\n                neobot_soco_port_2: 'IN2',\n                neobot_soco_port_3: 'IN3',\n                neobot_soco_port_4: 'IN4',\n                neobot_soco_port_12: 'IN1 & IN2',\n                neobot_soco_port_bat: 'battery',\n                neobot_soco_port_remot: 'remote',\n                neobot_soco_color_white: 'white',\n                neobot_soco_color_red: 'red',\n                neobot_soco_color_yellow: 'yellow',\n                neobot_soco_color_green: 'green',\n                neobot_soco_color_blue: 'blue',\n                neobot_soco_direction_forward: 'forward',\n                neobot_soco_direction_backward: 'backward',\n                neobot_soco_sound_silent: 'silent',\n                neobot_soco_sound_do: 'Do',\n                neobot_soco_sound_do_shop: 'Do#',\n                neobot_soco_sound_re: 'Re',\n                neobot_soco_sound_re_shop: 'Re#',\n                neobot_soco_sound_mi: 'Mi',\n                neobot_soco_sound_fa: 'Fa',\n                neobot_soco_sound_fa_shop: 'Fa#',\n                neobot_soco_sound_so: 'So',\n                neobot_soco_sound_so_shop: 'So#',\n                neobot_soco_sound_la: 'La',\n                neobot_soco_sound_la_shop: 'La#',\n                neobot_soco_sound_ti: 'Si',\n                neobot_soco_sound_half_note: 'a half note',\n                neobot_soco_sound_quarter_note: 'a quarter note',\n                neobot_soco_sound_eighth_note: 'a eighth note',\n                neobot_soco_sound_sixteenth_note: 'a sixteenth note',\n                neobot_soco_sensor_infrared: 'IR sensor',\n                neobot_soco_sensor_light: 'light sensor',\n                neobot_soco_sensor_sound: 'sound sensor',\n                neobot_soco_compare_symbol1: '＝',\n                neobot_soco_compare_symbol2: '＞',\n                neobot_soco_compare_symbol3: '＜',\n                neobot_soco_compare_symbol4: '≥',\n                neobot_soco_compare_symbol5: '≤',\n                neobot_soco_remote_btn_a: 'A',\n                neobot_soco_remote_btn_b: 'B',\n                neobot_soco_remote_btn_c: 'C',\n                neobot_soco_remote_btn_d: 'D',\n                neobot_soco_remote_btn_1: '1',\n                neobot_soco_remote_btn_2: '2',\n                neobot_soco_remote_btn_3: '3',\n                neobot_soco_remote_btn_4: '4',\n                neobot_soco_remote_btn_up: '▲',\n                neobot_soco_remote_btn_down: '▼',\n                neobot_soco_remote_btn_left: '◀',\n                neobot_soco_remote_btn_right: '▶',\n                neobot_soco_duration_cont: 'constantly',\n                neobot_soco_duration_1s: '1 second',\n                neobot_soco_duration_2s: '2 seconds',\n                neobot_soco_duration_3s: '3 seconds',\n                neobot_soco_duration_4s: '4 seconds',\n                neobot_soco_duration_5s: '5 seconds',\n                neobot_soco_duration_6s: '6 seconds',\n                neobot_soco_duration_7s: '7 seconds',\n                neobot_soco_duration_8s: '8 seconds',\n                neobot_soco_duration_9s: '9 seconds',\n                neobot_soco_motor_both: 'both',\n                neobot_soco_motor_left: 'left',\n                neobot_soco_motor_right: 'right',\n                neobot_soco_motor_move_forward: 'go forward',\n                neobot_soco_motor_move_backward: 'go backward',\n                neobot_soco_motor_move_left: 'turn Left',\n                neobot_soco_motor_move_right: 'turn Right',\n                neobot_soco_motor_move_stop: 'stop',\n\n                neobot_soco_servo_dir_1: 'forward',\n                neobot_soco_servo_dir_2: 'backward',\n\n                neobot_soco_percent_10: '10% speed',\n                neobot_soco_percent_20: '20% speed',\n                neobot_soco_percent_30: '30% speed',\n                neobot_soco_percent_40: '40% speed',\n                neobot_soco_percent_50: '50% speed',\n                neobot_soco_percent_60: '60% speed',\n                neobot_soco_percent_70: '70% speed',\n                neobot_soco_percent_80: '80% speed',\n                neobot_soco_percent_90: '90% speed',\n                neobot_soco_percent_100: '100% speed',\n\n                neobot_soco_angle_0: '0 degree',\n                neobot_soco_angle_5: '5 degrees',\n                neobot_soco_angle_10: '10 degrees',\n                neobot_soco_angle_15: '15 degrees',\n                neobot_soco_angle_20: '20 degrees',\n                neobot_soco_angle_25: '25 degrees',\n                neobot_soco_angle_30: '30 degrees',\n                neobot_soco_angle_35: '35 degrees',\n                neobot_soco_angle_40: '40 degrees',\n                neobot_soco_angle_45: '45 degrees',\n                neobot_soco_angle_50: '50 degrees',\n                neobot_soco_angle_55: '55 degrees',\n                neobot_soco_angle_60: '60 degrees',\n                neobot_soco_angle_65: '65 degrees',\n                neobot_soco_angle_70: '70 degrees',\n                neobot_soco_angle_75: '75 degrees',\n                neobot_soco_angle_80: '80 degrees',\n                neobot_soco_angle_85: '85 degrees',\n                neobot_soco_angle_90: '90 degrees',\n                neobot_soco_angle_95: '95 degrees',\n                neobot_soco_angle_100: '100 degrees',\n                neobot_soco_angle_105: '105 degrees',\n                neobot_soco_angle_110: '110 degrees',\n                neobot_soco_angle_115: '115 degrees',\n                neobot_soco_angle_120: '120 degrees',\n                neobot_soco_angle_125: '125 degrees',\n                neobot_soco_angle_130: '130 degrees',\n                neobot_soco_angle_135: '135 degrees',\n                neobot_soco_angle_140: '140 degrees',\n                neobot_soco_angle_145: '145 degrees',\n                neobot_soco_angle_150: '150 degrees',\n                neobot_soco_angle_155: '155 degrees',\n                neobot_soco_angle_160: '160 degrees',\n                neobot_soco_angle_165: '165 degrees',\n                neobot_soco_angle_170: '170 degrees',\n                neobot_soco_angle_175: '175 degrees',\n                neobot_soco_angle_180: '180degrees',\n\n                neobot_soco_out_all: 'ALL',\n                neobot_soco_direction_left: 'to the left',\n                neobot_soco_direction_right: 'to the right',\n            },\n        }, //\n    };\n};\n\nEntry.NeobotSoco.blockMenuBlocks = [\n    // sensor\n    'neobot_soco_sensor_title',\n    'neobot_soco_sensor_value',\n    'neobot_soco_sensor_convert_scale',\n    'neobot_soco_decision_sensor_is_over',\n    'neobot_soco_decision_equal_with_sensor',\n    'neobot_soco_decision_sensor_angle',\n    'neobot_soco_remote_button',\n\n    // led\n    'neobot_soco_led_title',\n    'neobot_soco_led_on',\n    'neobot_soco_led_brightness_with_sensor',\n    'neobot_soco_color_led_on',\n    'neobot_soco_output_led_off',\n\n    // output\n    'neobot_soco_output_title',\n    'neobot_soco_set_output',\n\n    //  motor\n    'neobot_soco_motor_title',\n    'neobot_soco_robot',\n    'neobot_soco_motor_start',\n    'neobot_soco_motor_stop',\n\n    // servo\n    'neobot_soco_servo_title',\n    'neobot_soco_servo_init',\n    'neobot_soco_servo_rotate',\n    'neobot_soco_servo_stop',\n    'neobot_soco_servo_change_degree',\n\n    // melody\n    'neobot_soco_buzzer_title',\n    'neobot_soco_play_note_for',\n    'neobot_soco_melody_play_with_sensor',\n    'neobot_soco_melody_stop',\n];\n\nEntry.NeobotSoco.getBlocks = function() {\n    return {\n        /*************************\n         * class neobot_soco_sensor\n         *************************/\n        neobot_soco_sensor_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_soco_sensor_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_soco_sensor_title',\n            },\n            class: 'neobot_soco_sensor',\n            isNotFor: ['neobot_soco'],\n            events: {},\n        },\n        neobot_soco_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_soco_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_soco_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_soco_port_remot, 'IR'],\n                        [Lang.Blocks.neobot_soco_port_bat, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_soco_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_soco_sensor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port];\n            },\n        },\n\n        neobot_soco_sensor_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_soco_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_soco_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'neobot_soco_sensor_convert_scale',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OMIN: 1,\n                OMAX: 2,\n                MIN: 3,\n                MAX: 4,\n            },\n            class: 'neobot_soco_sensor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                var value = Entry.hw.portData[port];\n                var omin = script.getNumberValue('OMIN', script);\n                var omax = script.getNumberValue('OMAX', script);\n                var min = script.getNumberValue('MIN', script);\n                var max = script.getNumberValue('MAX', script);\n\n                if (omin > omax) {\n                    var temp = omin;\n                    omin = omax;\n                    omax = temp;\n                }\n\n                if (min > max) {\n                    var temp = min;\n                    min = max;\n                    max = temp;\n                }\n\n                value -= omin;\n                value = value * ((max - min) / (omax - omin));\n                value += min;\n                value = Math.min(max, value);\n                value = Math.max(min, value);\n\n                return Math.round(value);\n            },\n        },\n\n        neobot_soco_decision_sensor_is_over: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_soco_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_soco_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_soco_port_12, 'IN12'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_soco_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_soco_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_soco_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_soco_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, 10],\n                type: 'neobot_soco_decision_sensor_is_over',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                SYMBOL: 1,\n                VALUE: 2,\n            },\n            class: 'neobot_soco_sensor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                const sensorTemp = script.getStringField('SENSOR');\n                const symbol = script.getStringField('SYMBOL');\n                const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                if (sensorTemp == 'IN12') {\n                    const sensor1 = Entry.hw.portData['IN1'];\n                    const sensor2 = Entry.hw.portData['IN2'];\n                    if (symbol == '=') {\n                        return sensor1 == value && sensor2 == value;\n                    } else if (symbol == '>') {\n                        return sensor1 > value && sensor2 > value;\n                    } else if (symbol == '<') {\n                        return sensor1 < value && sensor2 < value;\n                    } else if (symbol == '>=') {\n                        return sensor1 >= value && sensor2 >= value;\n                    } else if (symbol == '<=') {\n                        return sensor1 <= value && sensor2 <= value;\n                    }\n                } else {\n                    const sensor = Entry.hw.portData[sensorTemp];\n                    if (symbol == '=') {\n                        if (sensor == value) return true;\n                        else return false;\n                    } else if (symbol == '>') {\n                        if (sensor > value) return true;\n                        else return false;\n                    } else if (symbol == '<') {\n                        if (sensor < value) return true;\n                        else return false;\n                    } else if (symbol == '>=') {\n                        if (sensor >= value) return true;\n                        else return false;\n                    } else if (symbol == '<=') {\n                        if (sensor <= value) return true;\n                        else return false;\n                    }\n                }\n                return false;\n            },\n        },\n\n        neobot_soco_decision_equal_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_soco_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_soco_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_color_white, 0],\n                        [Lang.Blocks.neobot_soco_color_red, 1],\n                        [Lang.Blocks.neobot_soco_color_yellow, 2],\n                        [Lang.Blocks.neobot_soco_color_green, 3],\n                        [Lang.Blocks.neobot_soco_color_blue, 4],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_soco_decision_equal_with_sensor',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                COLOR: 1,\n            },\n            class: 'neobot_soco_sensor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var color = script.getNumberField('COLOR');\n\n                if (sensor >= 10 && sensor <= 50) {\n                    if (color == 0) return true;\n                    else return false;\n                } else if (sensor >= 51 && sensor <= 90) {\n                    if (color == 1) return true;\n                    else return false;\n                } else if (sensor >= 91 && sensor <= 130) {\n                    if (color == 2) return true;\n                    else return false;\n                } else if (sensor >= 131 && sensor <= 170) {\n                    if (color == 3) return true;\n                    else return false;\n                } else if (sensor >= 171 && sensor <= 210) {\n                    if (color == 4) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        neobot_soco_decision_sensor_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_soco_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_soco_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_soco_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_soco_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_soco_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_soco_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_angle_0, '0'],\n                        [Lang.Blocks.neobot_soco_angle_10, '10'],\n                        [Lang.Blocks.neobot_soco_angle_20, '20'],\n                        [Lang.Blocks.neobot_soco_angle_30, '30'],\n                        [Lang.Blocks.neobot_soco_angle_40, '40'],\n                        [Lang.Blocks.neobot_soco_angle_50, '50'],\n                        [Lang.Blocks.neobot_soco_angle_60, '60'],\n                        [Lang.Blocks.neobot_soco_angle_70, '70'],\n                        [Lang.Blocks.neobot_soco_angle_80, '80'],\n                        [Lang.Blocks.neobot_soco_angle_90, '90'],\n                        [Lang.Blocks.neobot_soco_angle_100, '100'],\n                        [Lang.Blocks.neobot_soco_angle_110, '110'],\n                        [Lang.Blocks.neobot_soco_angle_120, '120'],\n                        [Lang.Blocks.neobot_soco_angle_130, '130'],\n                        [Lang.Blocks.neobot_soco_angle_140, '140'],\n                        [Lang.Blocks.neobot_soco_angle_150, '150'],\n                        [Lang.Blocks.neobot_soco_angle_160, '160'],\n                        [Lang.Blocks.neobot_soco_angle_170, '170'],\n                        [Lang.Blocks.neobot_soco_angle_180, '180'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'neobot_soco_decision_sensor_angle',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                SYMBOL: 1,\n                VALUE: 2,\n            },\n            class: 'neobot_soco_sensor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var symbol = script.getStringField('SYMBOL');\n                var value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                if (symbol == '=') {\n                    if (sensor == value) return true;\n                    else return false;\n                } else if (symbol == '>') {\n                    if (sensor > value) return true;\n                    else return false;\n                } else if (symbol == '<') {\n                    if (sensor < value) return true;\n                    else return false;\n                } else if (symbol == '>=') {\n                    if (sensor >= value) return true;\n                    else return false;\n                } else if (symbol == '<=') {\n                    if (sensor <= value) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        neobot_soco_remote_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_remote_btn_1, '10'],\n                        [Lang.Blocks.neobot_soco_remote_btn_2, '11'],\n                        [Lang.Blocks.neobot_soco_remote_btn_3, '12'],\n                        [Lang.Blocks.neobot_soco_remote_btn_4, '13'],\n                        [Lang.Blocks.neobot_soco_remote_btn_up, '1'],\n                        [Lang.Blocks.neobot_soco_remote_btn_down, '2'],\n                        [Lang.Blocks.neobot_soco_remote_btn_left, '3'],\n                        [Lang.Blocks.neobot_soco_remote_btn_right, '4'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_soco_remote_button',\n            },\n            paramsKeyMap: {\n                KEY: 0,\n            },\n            class: 'neobot_soco_sensor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                var key = script.getNumberField('KEY');\n                var value = Entry.hw.portData['IR'];\n                if (key == value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        /*************************\n         * class neobot_soco_led\n         *************************/\n        neobot_soco_led_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_soco_led_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_soco_led_title',\n            },\n            class: 'neobot_soco_led',\n            isNotFor: ['neobot_soco'],\n            events: {},\n        },\n        neobot_soco_led_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100%', '255'],\n                        ['90%', '230'],\n                        ['80%', '204'],\n                        ['70%', '179'],\n                        ['60%', '153'],\n                        ['50%', '128'],\n                        ['40%', '102'],\n                        ['30%', '77'],\n                        ['20%', '51'],\n                        ['10%', '26'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'neobot_soco_arg_led_duration',\n                        id: 'm311',\n                    },\n                    null,\n                ],\n                type: 'neobot_soco_led_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_soco_led',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const value = script.getNumberField('VALUE', script);\n                    const duration = script.getStringValue('DURATION', script);\n\n                    if (Entry.NeobotSoco.log_to_console) {\n                        Entry.console.print('=== neobot_soco_led_on ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('brightness : ' + value, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    if (\n                        duration != '계속' &&\n                        duration != 'constantly' &&\n                        Entry.parseNumber(duration) <= 0\n                    ) {\n                        return script.callReturn();\n                    }\n\n                    if (port == 'ALL') {\n                        Entry.hw.sendQueue['OUT1'] = value;\n                        Entry.hw.sendQueue['OUT2'] = value;\n                        Entry.hw.sendQueue['OUT3'] = value;\n                    } else {\n                        Entry.hw.sendQueue[port] = value;\n                    }\n\n                    if (duration == '계속' || duration == 'constantly') {\n                        return script.callReturn();\n                    }\n\n                    const durationValue = Entry.parseNumber(duration);\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        if (port == 'ALL') {\n                            Entry.hw.sendQueue['OUT1'] = 0;\n                            Entry.hw.sendQueue['OUT2'] = 0;\n                            Entry.hw.sendQueue['OUT3'] = 0;\n                        } else {\n                            Entry.hw.sendQueue[port] = 0;\n                        }\n                        if (Entry.NeobotSoco.log_to_console)\n                            Entry.console.print('neobot_soco_led_on : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, durationValue * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_soco_output_led_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_soco_output_led_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_soco_led',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_output_led_off ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = 0;\n                    Entry.hw.sendQueue['OUT2'] = 0;\n                    Entry.hw.sendQueue['OUT3'] = 0;\n                } else {\n                    Entry.hw.sendQueue[port] = 0;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_soco_led_brightness_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'neobot_soco_led_brightness_with_sensor',\n            },\n            paramsKeyMap: {\n                IN: 0,\n                OUT: 1,\n            },\n            class: 'neobot_soco_led',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                const inPort = script.getStringField('IN', script);\n                const outPort = script.getStringField('OUT', script);\n                let value = Entry.hw.portData[inPort];\n\n                // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함.\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n                value = Math.ceil((value / 100) * 255);\n\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_led_brightness_with_sensor ===', 'speak');\n                    Entry.console.print('out port : ' + outPort, 'speak');\n                    Entry.console.print('in port : ' + inPort, 'speak');\n                    Entry.console.print('sensor value : ' + Entry.hw.portData[inPort], 'speak');\n                    Entry.console.print('output value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (outPort == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = value;\n                    Entry.hw.sendQueue['OUT2'] = value;\n                    Entry.hw.sendQueue['OUT3'] = value;\n                } else {\n                    Entry.hw.sendQueue[outPort] = value;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_soco_color_led_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_soco_color_led_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'neobot_soco_led',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT');\n                    let red = script.getNumberValue('RED');\n                    let green = script.getNumberValue('GREEN');\n                    let blue = script.getNumberValue('BLUE');\n\n                    let out1 = false;\n                    let out2 = false;\n                    let out3 = false;\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    } else {\n                        out1 = port == 'OUT1';\n                        out2 = port == 'OUT2';\n                        out3 = port == 'OUT3';\n                    }\n\n                    red = Math.max(red, 1);\n                    red = Math.min(red, 251);\n                    green = Math.max(green, 1);\n                    green = Math.min(green, 251);\n                    blue = Math.max(blue, 1);\n                    blue = Math.min(blue, 251);\n\n                    if (Entry.NeobotSoco.log_to_console) {\n                        Entry.console.print('=== neobot_soco_color_led_on ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('red : ' + red, 'speak');\n                        Entry.console.print('green : ' + green, 'speak');\n                        Entry.console.print('blue : ' + blue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    const valRed = 252;\n                    const valGreen = 253;\n                    const valBlue = 254;\n                    const valAccept = 255;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (out1) Entry.hw.sendQueue['OUT1'] = valRed;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = valRed;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = valRed;\n                    if (Entry.NeobotSoco.log_to_console)\n                        Entry.console.print('neobot_soco_color_led_on : ' + valRed, 'speak');\n                    setTimeout(function() {\n                        // set red\n                        if (out1) Entry.hw.sendQueue['OUT1'] = red;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = red;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = red;\n                        if (Entry.NeobotSoco.log_to_console)\n                            Entry.console.print('neobot_soco_color_led_on : ' + red, 'speak');\n                        setTimeout(function() {\n                            // choose green\n                            if (out1) Entry.hw.sendQueue['OUT1'] = valGreen;\n                            if (out2) Entry.hw.sendQueue['OUT2'] = valGreen;\n                            if (out3) Entry.hw.sendQueue['OUT3'] = valGreen;\n                            if (Entry.NeobotSoco.log_to_console)\n                                Entry.console.print(\n                                    'neobot_soco_color_led_on : ' + valGreen,\n                                    'speak'\n                                );\n                            setTimeout(function() {\n                                // set green\n                                if (out1) Entry.hw.sendQueue['OUT1'] = green;\n                                if (out2) Entry.hw.sendQueue['OUT2'] = green;\n                                if (out3) Entry.hw.sendQueue['OUT3'] = green;\n                                if (Entry.NeobotSoco.log_to_console)\n                                    Entry.console.print(\n                                        'neobot_soco_color_led_on : ' + green,\n                                        'speak'\n                                    );\n                                setTimeout(function() {\n                                    // choose blue\n                                    if (out1) Entry.hw.sendQueue['OUT1'] = valBlue;\n                                    if (out2) Entry.hw.sendQueue['OUT2'] = valBlue;\n                                    if (out3) Entry.hw.sendQueue['OUT3'] = valBlue;\n                                    if (Entry.NeobotSoco.log_to_console)\n                                        Entry.console.print(\n                                            'neobot_soco_color_led_on : ' + valBlue,\n                                            'speak'\n                                        );\n                                    setTimeout(function() {\n                                        // set blue\n                                        if (out1) Entry.hw.sendQueue['OUT1'] = blue;\n                                        if (out2) Entry.hw.sendQueue['OUT2'] = blue;\n                                        if (out3) Entry.hw.sendQueue['OUT3'] = blue;\n                                        if (Entry.NeobotSoco.log_to_console)\n                                            Entry.console.print(\n                                                'neobot_soco_color_led_on : ' + blue,\n                                                'speak'\n                                            );\n                                        setTimeout(function() {\n                                            // accept\n                                            if (out1) Entry.hw.sendQueue['OUT1'] = valAccept;\n                                            if (out2) Entry.hw.sendQueue['OUT2'] = valAccept;\n                                            if (out3) Entry.hw.sendQueue['OUT3'] = valAccept;\n                                            if (Entry.NeobotSoco.log_to_console)\n                                                Entry.console.print(\n                                                    'neobot_soco_color_led_on : ' + valAccept,\n                                                    'speak'\n                                                );\n                                            setTimeout(function() {\n                                                // final delay\n                                                script.timeFlag = 0;\n                                            }, 200);\n                                        }, 200);\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n                        }, 200);\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        /*************************\n         * class neobot_soco_output\n         *************************/\n        neobot_soco_output_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_soco_output_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_soco_output_title',\n            },\n            class: 'neobot_soco_output',\n            isNotFor: ['neobot_soco'],\n            events: {},\n        },\n        neobot_soco_set_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_soco_set_output',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'neobot_soco_output',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_set_output ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = value;\n                    Entry.hw.sendQueue['OUT2'] = value;\n                    Entry.hw.sendQueue['OUT3'] = value;\n                } else {\n                    Entry.hw.sendQueue[port] = value;\n                }\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_soco_motor\n         *************************/\n        neobot_soco_motor_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_soco_motor_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_soco_motor_title',\n            },\n            class: 'neobot_soco_motor',\n            isNotFor: ['neobot_soco'],\n            events: {},\n        },\n        neobot_soco_robot: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_motor_move_forward, '1'],\n                        [Lang.Blocks.neobot_soco_motor_move_backward, '2'],\n                        [Lang.Blocks.neobot_soco_motor_move_left, '3'],\n                        [Lang.Blocks.neobot_soco_motor_move_right, '4'],\n                        [Lang.Blocks.neobot_soco_motor_move_stop, '5'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_soco_robot',\n            },\n            paramsKeyMap: {\n                MOVE: 0,\n            },\n            class: 'neobot_soco_motor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                const move = script.getNumberField('MOVE');\n                let leftValue;\n                let rightValue;\n                switch (move) {\n                    case 1:\n                        leftValue = 0x10 + 10;\n                        rightValue = 0x10 + 10;\n                        break;\n                    case 2:\n                        leftValue = 0x20 + 10;\n                        rightValue = 0x20 + 10;\n                        break;\n                    case 3:\n                        leftValue = 0x20 + 5;\n                        rightValue = 0x10 + 5;\n                        break;\n                    case 4:\n                        leftValue = 0x10 + 5;\n                        rightValue = 0x20 + 5;\n                        break;\n                    case 5:\n                        leftValue = 0;\n                        rightValue = 0;\n                        break;\n                }\n\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_robot ===', 'speak');\n                    Entry.console.print('move : ' + move, 'speak');\n                    Entry.console.print('left value : ' + leftValue, 'speak');\n                    Entry.console.print('right value : ' + rightValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['DCL'] = leftValue;\n                Entry.hw.sendQueue['DCR'] = rightValue;\n                return script.callReturn();\n            },\n        },\n\n        neobot_soco_motor_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_motor_both, '1'],\n                        [Lang.Blocks.neobot_soco_motor_left, '2'],\n                        [Lang.Blocks.neobot_soco_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_direction_forward, '1'],\n                        [Lang.Blocks.neobot_soco_direction_backward, '2'],\n                        [Lang.Blocks.neobot_soco_direction_left, '3'],\n                        [Lang.Blocks.neobot_soco_direction_right, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'neobot_soco_arg_motor_speed',\n                        id: 'm411',\n                    },\n                    {\n                        type: 'neobot_soco_arg_motor_duration',\n                        id: 'm412',\n                    },\n                    null,\n                ],\n                type: 'neobot_soco_motor_start',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n                DURATION: 3,\n            },\n            class: 'neobot_soco_motor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const motor = script.getStringField('MOTOR', script);\n                    const direction = script.getStringField('DIRECTION', script);\n                    const speed = script.getStringValue('SPEED', script);\n                    const duration = script.getStringValue('DURATION', script);\n\n                    if (\n                        duration != '계속' &&\n                        duration != 'constantly' &&\n                        Entry.parseNumber(duration) <= 0\n                    ) {\n                        return script.callReturn();\n                    }\n\n                    let moveLeft = false;\n                    let moveRight = false;\n                    if (motor == 1) {\n                        moveLeft = true;\n                        moveRight = true;\n                    } else if (motor == 2) {\n                        moveLeft = true;\n                    } else {\n                        moveRight = true;\n                    }\n\n                    let leftDirectionValue;\n                    let rightDirectionValue;\n                    if (direction == 1) {\n                        leftDirectionValue = 0x10;\n                        rightDirectionValue = 0x10;\n                    } else if (direction == 2) {\n                        leftDirectionValue = 0x20;\n                        rightDirectionValue = 0x20;\n                    } else if (direction == 3) {\n                        leftDirectionValue = 0x20;\n                        rightDirectionValue = 0x10;\n                    } else {\n                        leftDirectionValue = 0x10;\n                        rightDirectionValue = 0x20;\n                    }\n\n                    // edited 210421, 0~100 을 0~15로 변환, 100 이상은 최대값(15)으로 처리함.\n                    let speedValue = 0;\n                    if (Entry.Utils.isNumber(speed)) {\n                        speedValue = Entry.parseNumber(speed);\n                    } else {\n                        speedValue = Entry.hw.portData[speed];\n                    }\n                    speedValue = Math.max(speedValue, 0);\n                    speedValue = Math.min(speedValue, 100);\n                    speedValue = Math.ceil((speedValue / 100) * 15);\n\n                    const leftOutValue = leftDirectionValue + speedValue;\n                    const rightOutValue = rightDirectionValue + speedValue;\n\n                    if (Entry.NeobotSoco.log_to_console) {\n                        Entry.console.print('=== neobot_soco_motor_start ===', 'speak');\n                        Entry.console.print('motor : ' + motor, 'speak');\n                        Entry.console.print('direction : ' + direction, 'speak');\n                        Entry.console.print('speed : ' + speed, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print(\n                            'left direction value : ' + leftDirectionValue,\n                            'speak'\n                        );\n                        Entry.console.print(\n                            'right direction value : ' + rightDirectionValue,\n                            'speak'\n                        );\n                        Entry.console.print('speed value : ' + speedValue, 'speak');\n                        Entry.console.print('left output value : ' + leftOutValue, 'speak');\n                        Entry.console.print('right output value : ' + rightOutValue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    if (moveLeft) {\n                        Entry.hw.sendQueue['DCL'] = leftOutValue;\n                    }\n                    if (moveRight) {\n                        Entry.hw.sendQueue['DCR'] = rightOutValue;\n                    }\n\n                    if (duration == '계속' || duration == 'constantly') {\n                        return script.callReturn();\n                    }\n\n                    const durationValue = Entry.parseNumber(duration);\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['DCL'] = 0;\n                        Entry.hw.sendQueue['DCR'] = 0;\n                        if (Entry.NeobotSoco.log_to_console)\n                            Entry.console.print('neobot_soco_motor_start : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, durationValue * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_soco_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_motor_both, '1'],\n                        [Lang.Blocks.neobot_soco_motor_left, '2'],\n                        [Lang.Blocks.neobot_soco_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_soco_motor_stop',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n            },\n            class: 'neobot_soco_motor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                const motor = script.getNumberField('MOTOR');\n\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_motor_stop ===', 'speak');\n                    Entry.console.print('motor : ' + motor, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (motor == 1) {\n                    Entry.hw.sendQueue['DCL'] = 0;\n                    Entry.hw.sendQueue['DCR'] = 0;\n                } else if (motor == 2) {\n                    Entry.hw.sendQueue['DCL'] = 0;\n                } else {\n                    Entry.hw.sendQueue['DCR'] = 0;\n                }\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_soco_melody\n         *************************/\n        neobot_soco_buzzer_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_soco_buzzer_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_soco_buzzer_title',\n            },\n            class: 'neobot_soco_melody',\n            isNotFor: ['neobot_soco'],\n            events: {},\n        },\n        neobot_soco_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_sound_silent, '0'],\n                        [Lang.Blocks.neobot_soco_sound_do, '1'],\n                        [Lang.Blocks.neobot_soco_sound_do_shop, '2'],\n                        [Lang.Blocks.neobot_soco_sound_re, '3'],\n                        [Lang.Blocks.neobot_soco_sound_re_shop, '4'],\n                        [Lang.Blocks.neobot_soco_sound_mi, '5'],\n                        [Lang.Blocks.neobot_soco_sound_fa, '6'],\n                        [Lang.Blocks.neobot_soco_sound_fa_shop, '7'],\n                        [Lang.Blocks.neobot_soco_sound_so, '8'],\n                        [Lang.Blocks.neobot_soco_sound_so_shop, '9'],\n                        [Lang.Blocks.neobot_soco_sound_la, '10'],\n                        [Lang.Blocks.neobot_soco_sound_la_shop, '11'],\n                        [Lang.Blocks.neobot_soco_sound_ti, '12'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_sound_half_note, '2'],\n                        [Lang.Blocks.neobot_soco_sound_quarter_note, '4'],\n                        [Lang.Blocks.neobot_soco_sound_eighth_note, '8'],\n                        [Lang.Blocks.neobot_soco_sound_sixteenth_note, '16'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '2', '4', null],\n                type: 'neobot_soco_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_soco_melody',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const note = script.getNumberField('NOTE', script);\n                    const octave = script.getNumberField('OCTAVE', script);\n                    const duration = script.getNumberField('DURATION', script);\n                    let value = note > 0 ? note + 12 * octave : 0;\n\n                    value = Math.min(value, 72);\n\n                    if (Entry.NeobotSoco.log_to_console) {\n                        Entry.console.print('=== neobot_soco_play_note_for ===', 'speak');\n                        Entry.console.print('note : ' + note, 'speak');\n                        Entry.console.print('octave : ' + octave, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print('value : ' + value, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SND'] = value;\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['SND'] = 0;\n                        if (Entry.NeobotSoco.log_to_console)\n                            Entry.console.print('neobot_soco_play_note_for : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, (1 / duration) * 2000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_soco_melody_play_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_soco_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_soco_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_soco_melody_play_with_sensor',\n            },\n            paramsKeyMap: {\n                INPUT: 0,\n            },\n            class: 'neobot_soco_melody',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                const input = script.getStringField('INPUT');\n                let value = Entry.hw.portData[input];\n\n                // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함.\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n                value = Math.ceil((value / 100) * 65);\n\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_melody_play_with_sensor ===', 'speak');\n                    Entry.console.print('input : ' + input, 'speak');\n                    Entry.console.print('value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['SND'] = value;\n                return script.callReturn();\n            },\n        },\n\n        neobot_soco_melody_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_soco_melody_stop',\n            },\n            paramsKeyMap: {},\n            class: 'neobot_soco_melody',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_melody_stop ===', 'speak');\n                    Entry.console.print('value : 0', 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['SND'] = 0;\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_soco_servo\n         *************************/\n        neobot_soco_servo_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_soco_servo_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_soco_servo_title',\n            },\n            class: 'neobot_soco_servo',\n            isNotFor: ['neobot_soco'],\n            events: {},\n        },\n        neobot_soco_servo_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_soco_servo_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_soco_servo',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const resetValue = 186;\n                    const initValue = 1;\n\n                    if (Entry.NeobotSoco.log_to_console) {\n                        Entry.console.print('=== neobot_soco_servo_init ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    let out1 = port == 'OUT1';\n                    let out2 = port == 'OUT2';\n                    let out3 = port == 'OUT3';\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (out1) Entry.hw.sendQueue['OUT1'] = resetValue;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = resetValue;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = resetValue;\n                    if (Entry.NeobotSoco.log_to_console)\n                        Entry.console.print('neobot_soco_servo_init : ' + resetValue, 'speak');\n                    setTimeout(function() {\n                        if (out1) Entry.hw.sendQueue['OUT1'] = initValue;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = initValue;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = initValue;\n                        if (Entry.NeobotSoco.log_to_console)\n                            Entry.console.print('neobot_soco_servo_init : ' + initValue, 'speak');\n                        setTimeout(function() {\n                            script.timeFlag = 0;\n                        }, 100);\n                    }, 200);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_soco_servo_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_soco_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['0%', 0],\n                        ['10%', 10],\n                        ['20%', 20],\n                        ['30%', 30],\n                        ['40%', 40],\n                        ['50%', 50],\n                        ['60%', 60],\n                        ['70%', 70],\n                        ['80%', 80],\n                        ['90%', 90],\n                        ['100%', 100],\n                    ],\n                    value: 50,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'neobot_soco_servo_rotate',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'neobot_soco_servo',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n                const direction = script.getNumberField('DIRECTION');\n                const speed = script.getStringField('SPEED');\n\n                let directionValue = 192; // 정방향\n                if (direction == 2) {\n                    directionValue = 208; // 역방향\n                }\n                let speedValue;\n                if (Entry.Utils.isNumber(speed)) {\n                    speedValue = Entry.parseNumber(speed);\n                } else {\n                    speedValue = Entry.hw.portData[speed];\n                }\n\n                // edited 210421, 0~100 을 0~10 으로 변환\n                speedValue = Math.max(speedValue, 0);\n                speedValue = Math.min(speedValue, 100);\n                speedValue = Math.ceil(speedValue / 10);\n\n                let outValue = directionValue + speedValue;\n                if (outValue == directionValue) {\n                    outValue = 254;\n                } else {\n                    outValue = outValue - 1;\n                }\n\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_servo_rotate ===');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('direction : ' + direction, 'speak');\n                    Entry.console.print('speed : ' + speed, 'speak');\n                    Entry.console.print('direction value : ' + directionValue, 'speak');\n                    Entry.console.print('speed value : ' + speedValue, 'speak');\n                    Entry.console.print('output value : ' + outValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = outValue;\n                    Entry.hw.sendQueue['OUT2'] = outValue;\n                    Entry.hw.sendQueue['OUT3'] = outValue;\n                } else {\n                    Entry.hw.sendQueue[port] = outValue;\n                }\n                return script.callReturn();\n            },\n        },\n        neobot_soco_servo_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_soco_servo_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_soco_servo',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n                let outValue = 254;\n\n                if (Entry.NeobotSoco.log_to_console) {\n                    Entry.console.print('=== neobot_soco_servo_stop ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('output value: ' + outValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = outValue;\n                    Entry.hw.sendQueue['OUT2'] = outValue;\n                    Entry.hw.sendQueue['OUT3'] = outValue;\n                } else {\n                    Entry.hw.sendQueue[port] = outValue;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_soco_servo_change_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_soco_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_soco_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['0%', 0],\n                        ['10%', 10],\n                        ['20%', 20],\n                        ['30%', 30],\n                        ['40%', 40],\n                        ['50%', 50],\n                        ['60%', 60],\n                        ['70%', 70],\n                        ['80%', 80],\n                        ['90%', 90],\n                        ['100%', 100],\n                    ],\n                    value: 50,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_servo_degree',\n                        id: 'm211',\n                    },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'neobot_soco_servo_change_degree',\n            },\n            paramsKeyMap: {\n                DEGREE: 0,\n                PORT: 1,\n                DIRECTION: 2,\n                SPEED: 3,\n            },\n            class: 'neobot_soco_servo',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const direction = script.getNumberField('DIRECTION');\n                    const speed = script.getStringValue('SPEED');\n                    const degree = script.getStringValue('DEGREE');\n\n                    let out1 = port == 'OUT1';\n                    let out2 = port == 'OUT2';\n                    let out3 = port == 'OUT3';\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    }\n\n                    let directionValue = 188;\n                    if (direction == 2) {\n                        directionValue = 189;\n                    }\n\n                    let speedValue;\n                    if (Entry.Utils.isNumber(speed)) {\n                        speedValue = Entry.parseNumber(speed);\n                    } else {\n                        speedValue = Entry.hw.portData[speed];\n                    }\n\n                    // edited 210421, 0~100 을 240~250 으로 변환\n                    speedValue = Math.max(speedValue, 0);\n                    speedValue = Math.min(speedValue, 100);\n                    speedValue = Math.ceil(speedValue / 10) + 240;\n\n                    let degreeValue;\n                    if (Entry.Utils.isNumber(degree)) {\n                        degreeValue = Entry.parseNumber(degree);\n                    } else {\n                        if (degree == 'IN1' || degree == 'IN2' || degree == 'IN3') {\n                            degreeValue = Entry.hw.portData[degree];\n                        } else {\n                            degreeValue = 0;\n                        }\n                    }\n                    // edited 210421, 별도의 변환없이 그대로 사용함\n                    degreeValue = Math.max(degreeValue, 0);\n                    degreeValue = Math.min(degreeValue, 180);\n                    degreeValue = degreeValue + 1;\n\n                    if (Entry.NeobotSoco.log_to_console) {\n                        Entry.console.print('=== neobot_soco_servo_change_degree ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('direction : ' + direction, 'speak');\n                        Entry.console.print('speed : ' + speed, 'speak');\n                        Entry.console.print('degree : ' + degree, 'speak');\n                        Entry.console.print('directionValue : ' + directionValue, 'speak');\n                        Entry.console.print('speedValue : ' + speedValue, 'speak');\n                        Entry.console.print('degreeValue : ' + degreeValue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    // direction\n                    if (out1) Entry.hw.sendQueue['OUT1'] = directionValue;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = directionValue;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = directionValue;\n                    if (Entry.NeobotSoco.log_to_console)\n                        Entry.console.print(\n                            'neobot_soco_servo_change_degree : ' + directionValue,\n                            'speak'\n                        );\n                    setTimeout(function() {\n                        // speed\n                        if (out1) Entry.hw.sendQueue['OUT1'] = speedValue;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = speedValue;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = speedValue;\n                        if (Entry.NeobotSoco.log_to_console)\n                            Entry.console.print(\n                                'neobot_soco_servo_change_degree : ' + speedValue,\n                                'speak'\n                            );\n                        setTimeout(function() {\n                            // degree\n                            if (out1) Entry.hw.sendQueue['OUT1'] = degreeValue;\n                            if (out2) Entry.hw.sendQueue['OUT2'] = degreeValue;\n                            if (out3) Entry.hw.sendQueue['OUT3'] = degreeValue;\n                            if (Entry.NeobotSoco.log_to_console)\n                                Entry.console.print(\n                                    'neobot_soco_servo_change_degree : ' + degreeValue,\n                                    'speak'\n                                );\n                            setTimeout(function() {\n                                // final delay\n                                script.timeFlag = 0;\n                            }, 200);\n                        }, 200);\n                    }, 200);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        /*****************\n         * ARG Blocks\n         *****************/\n        neobot_soco_arg_led_duration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_duration_cont, '계속'],\n                        [Lang.Blocks.neobot_soco_duration_1s, '1'],\n                        [Lang.Blocks.neobot_soco_duration_2s, '2'],\n                        [Lang.Blocks.neobot_soco_duration_3s, '3'],\n                        [Lang.Blocks.neobot_soco_duration_4s, '4'],\n                        [Lang.Blocks.neobot_soco_duration_5s, '5'],\n                        [Lang.Blocks.neobot_soco_duration_6s, '6'],\n                        [Lang.Blocks.neobot_soco_duration_7s, '7'],\n                        [Lang.Blocks.neobot_soco_duration_8s, '8'],\n                        [Lang.Blocks.neobot_soco_duration_9s, '9'],\n                    ],\n                    value: '계속',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_soco_led',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        neobot_soco_arg_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['100%', 100],\n                        ['90%', 90],\n                        ['80%', 80],\n                        ['70%', 70],\n                        ['60%', 60],\n                        ['50%', 50],\n                        ['40%', 40],\n                        ['30%', 30],\n                        ['20%', 20],\n                        ['10%', 10],\n                        ['0%', 0],\n                    ],\n                    value: 100,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_soco_motor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        neobot_soco_arg_motor_duration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_duration_cont, '계속'],\n                        [Lang.Blocks.neobot_soco_duration_1s, '1'],\n                        [Lang.Blocks.neobot_soco_duration_2s, '2'],\n                        [Lang.Blocks.neobot_soco_duration_3s, '3'],\n                        [Lang.Blocks.neobot_soco_duration_4s, '4'],\n                        [Lang.Blocks.neobot_soco_duration_5s, '5'],\n                        [Lang.Blocks.neobot_soco_duration_6s, '6'],\n                        [Lang.Blocks.neobot_soco_duration_7s, '7'],\n                        [Lang.Blocks.neobot_soco_duration_8s, '8'],\n                        [Lang.Blocks.neobot_soco_duration_9s, '9'],\n                    ],\n                    value: '계속',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_soco_motor',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        get_servo_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_soco_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_soco_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_soco_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_soco_angle_0, '0'],\n                        [Lang.Blocks.neobot_soco_angle_5, '5'],\n                        [Lang.Blocks.neobot_soco_angle_10, '10'],\n                        [Lang.Blocks.neobot_soco_angle_15, '15'],\n                        [Lang.Blocks.neobot_soco_angle_20, '20'],\n                        [Lang.Blocks.neobot_soco_angle_25, '25'],\n                        [Lang.Blocks.neobot_soco_angle_30, '30'],\n                        [Lang.Blocks.neobot_soco_angle_35, '35'],\n                        [Lang.Blocks.neobot_soco_angle_40, '40'],\n                        [Lang.Blocks.neobot_soco_angle_45, '45'],\n                        [Lang.Blocks.neobot_soco_angle_50, '50'],\n                        [Lang.Blocks.neobot_soco_angle_55, '55'],\n                        [Lang.Blocks.neobot_soco_angle_60, '60'],\n                        [Lang.Blocks.neobot_soco_angle_65, '65'],\n                        [Lang.Blocks.neobot_soco_angle_70, '70'],\n                        [Lang.Blocks.neobot_soco_angle_75, '75'],\n                        [Lang.Blocks.neobot_soco_angle_80, '80'],\n                        [Lang.Blocks.neobot_soco_angle_85, '85'],\n                        [Lang.Blocks.neobot_soco_angle_90, '90'],\n                        [Lang.Blocks.neobot_soco_angle_95, '95'],\n                        [Lang.Blocks.neobot_soco_angle_100, '100'],\n                        [Lang.Blocks.neobot_soco_angle_105, '105'],\n                        [Lang.Blocks.neobot_soco_angle_110, '110'],\n                        [Lang.Blocks.neobot_soco_angle_115, '115'],\n                        [Lang.Blocks.neobot_soco_angle_120, '120'],\n                        [Lang.Blocks.neobot_soco_angle_125, '125'],\n                        [Lang.Blocks.neobot_soco_angle_130, '130'],\n                        [Lang.Blocks.neobot_soco_angle_135, '135'],\n                        [Lang.Blocks.neobot_soco_angle_140, '140'],\n                        [Lang.Blocks.neobot_soco_angle_145, '145'],\n                        [Lang.Blocks.neobot_soco_angle_150, '150'],\n                        [Lang.Blocks.neobot_soco_angle_155, '155'],\n                        [Lang.Blocks.neobot_soco_angle_160, '160'],\n                        [Lang.Blocks.neobot_soco_angle_165, '165'],\n                        [Lang.Blocks.neobot_soco_angle_170, '170'],\n                        [Lang.Blocks.neobot_soco_angle_175, '175'],\n                        [Lang.Blocks.neobot_soco_angle_180, '180'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_soco_servo',\n            isNotFor: ['neobot_soco'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.NeobotSoco;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_neobot_thinkcar.js",
    "content": "'use strict';\n\nEntry.NeobotThinkCar = {\n    id: '5.7',\n    name: 'neobot_think_car',\n    url: 'http://www.neobot.co.kr',\n    imageName: 'neobot_thinkcar.png',\n    title: {\n        ko: '네오씽카(ThinkCar)',\n        en: 'NEO ThinkCar',\n    },\n    LOCAL_MAP: ['IN1', 'IN2', 'IN3', 'IR', 'BAT'],\n    REMOTE_MAP: ['OUT1', 'OUT2', 'OUT3', 'DCR', 'DCL', 'SND', 'FND', 'OPT'],\n    setZero: function() {\n        for (var port in Entry.NeobotThinkCar.REMOTE_MAP) {\n            Entry.hw.sendQueue[Entry.NeobotThinkCar.REMOTE_MAP[port]] = 0;\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/neobot_thinkcar.png',\n        width: 700,\n        height: 700,\n        listPorts: {\n            IR: { name: 'IR', type: 'input', pos: { x: 0, y: 0 } },\n            BAT: { name: 'BAT', type: 'input', pos: { x: 0, y: 0 } },\n            SND: { name: 'SND', type: 'output', pos: { x: 0, y: 0 } },\n            FND: { name: 'FND', type: 'output', pos: { x: 0, y: 0 } },\n        },\n        ports: {\n            IN1: { name: 'IN1', type: 'input', pos: { x: 270, y: 170 } },\n            IN2: { name: 'IN2', type: 'input', pos: { x: 325, y: 170 } },\n            IN3: { name: 'IN3', type: 'input', pos: { x: 325, y: 530 } },\n            DCL: { name: 'L-Motor', type: 'output', pos: { x: 270, y: 530 } },\n            DCR: { name: 'R-Motor', type: 'output', pos: { x: 435, y: 530 } },\n            OUT1: { name: 'OUT1', type: 'output', pos: { x: 380, y: 170 } },\n            OUT2: { name: 'OUT2', type: 'output', pos: { x: 435, y: 170 } },\n            OUT3: { name: 'OUT3', type: 'output', pos: { x: 380, y: 530 } },\n        },\n        mode: 'both',\n    },\n    log_to_console: false,\n};\n\nEntry.NeobotThinkCar.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                // think car\n                neobot_think_car_auto_driving_title: '자율주행',\n                neobot_think_car_line_tracer_start: '차로를 유지하며 속도 %1 으로 자율주행 %2',\n                // neobot_think_car_line_tracer_change_speed: '자율주행 속도 변경 %1 %2',\n                neobot_think_car_reverse_parking_start: '%1 표지판에서 후면 주차 %2',\n                neobot_think_car_line_change: '1차로 %1 2차로 %2 표지판에서 차로 변경 %3',\n                neobot_think_car_driving_stop: '자율주행 중지 %1',\n\n                // sensor\n                neobot_think_car_sensor_title: '센서',\n                neobot_think_car_sensor_value: '%1',\n                neobot_think_car_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환',\n                neobot_think_car_decision_sensor_is_over: '%1 %2 %3',\n                neobot_think_car_decision_equal_with_sensor: '%1 컬러가 %2',\n                neobot_think_car_decision_sensor_angle: '%1 각도 %2 %3',\n                neobot_think_car_remote_button: '리모컨 버튼 %1 을 누름',\n\n                // LED\n                neobot_think_car_led_title: 'LED',\n                neobot_think_car_arg_led_duration: '%1',\n                neobot_think_car_led_on: 'LED 켜기   %1 %2 %3 %4',\n                neobot_think_car_output_led_off: '%1 LED 끄기 %2',\n                neobot_think_car_led_brightness_with_sensor: '%1 로 %2 LED 제어 %3',\n                neobot_think_car_color_led_on: '%1 컬러LED 켜기   R %2 G %3 B %4 %5',\n\n                // output\n                neobot_think_car_output_title: '출력',\n                neobot_think_car_set_output: '%1 에 %2 값 출력하기 %3',\n\n                // motor\n                neobot_think_car_motor_title: '회전모터',\n                neobot_think_car_robot: '로봇 %1 %2',\n                neobot_think_car_motor_start: '모터 회전하기   %1 %2 %3 %4 %5',\n                neobot_think_car_motor_stop: '%1 모터 멈추기 %2',\n                neobot_think_car_arg_motor_speed: '%1',\n                neobot_think_car_arg_motor_duration: '%1',\n\n                // melody\n                neobot_think_car_buzzer_title: '버저',\n                neobot_think_car_play_note_for: '버저 울리기   옥타브: %2 음: %1 길이: %3 %4',\n                neobot_think_car_melody_play_with_sensor: '%1 센서로 버저 울리기 %2',\n                neobot_think_car_melody_stop: '버저 멈추기 %1',\n\n                // servo\n                neobot_think_car_servo_title: '서보모터',\n                get_servo_degree: '%1',\n                neobot_think_car_servo_init: '%1 서보모터 리셋 %2',\n                neobot_think_car_servo_rotate: '서보모터 회전하기   %1 %2 %3 %4',\n                neobot_think_car_servo_stop: '%1 서보모터 멈추기 %2',\n                neobot_think_car_servo_change_degree: '서보모터 각도 바꾸기   %2 %3 %4 %1 %5',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_think_car_port_1: 'IN1',\n                neobot_think_car_port_2: 'IN2',\n                neobot_think_car_port_3: 'IN3',\n                neobot_think_car_port_4: 'IN4',\n                neobot_think_car_port_12: 'IN1 & IN2',\n                neobot_think_car_port_bat: '배터리',\n                neobot_think_car_port_remot: '리모컨',\n                neobot_think_car_color_white: '흰색',\n                neobot_think_car_color_red: '빨강',\n                neobot_think_car_color_yellow: '노랑',\n                neobot_think_car_color_green: '녹색',\n                neobot_think_car_color_blue: '파랑',\n                neobot_think_car_direction_forward: '앞으로',\n                neobot_think_car_direction_backward: '뒤로',\n                neobot_think_car_sound_silent: '무음',\n                neobot_think_car_sound_do: '도',\n                neobot_think_car_sound_do_shop: '도#',\n                neobot_think_car_sound_re: '레',\n                neobot_think_car_sound_re_shop: '레#',\n                neobot_think_car_sound_mi: '미',\n                neobot_think_car_sound_fa: '파',\n                neobot_think_car_sound_fa_shop: '파#',\n                neobot_think_car_sound_so: '솔',\n                neobot_think_car_sound_so_shop: '솔#',\n                neobot_think_car_sound_la: '라',\n                neobot_think_car_sound_la_shop: '라#',\n                neobot_think_car_sound_ti: '시',\n                neobot_think_car_sound_half_note: '2분 음표',\n                neobot_think_car_sound_quarter_note: '4분 음표',\n                neobot_think_car_sound_eighth_note: '8분 음표',\n                neobot_think_car_sound_sixteenth_note: '16분 음표',\n                neobot_think_car_sensor_infrared: '적외선센서',\n                neobot_think_car_sensor_light: '빛센서',\n                neobot_think_car_sensor_sound: '소리센서',\n                neobot_think_car_compare_symbol1: '＝',\n                neobot_think_car_compare_symbol2: '＞',\n                neobot_think_car_compare_symbol3: '＜',\n                neobot_think_car_compare_symbol4: '≥',\n                neobot_think_car_compare_symbol5: '≤',\n                neobot_think_car_remote_btn_a: 'A',\n                neobot_think_car_remote_btn_b: 'B',\n                neobot_think_car_remote_btn_c: 'C',\n                neobot_think_car_remote_btn_d: 'D',\n                neobot_think_car_remote_btn_1: '1',\n                neobot_think_car_remote_btn_2: '2',\n                neobot_think_car_remote_btn_3: '3',\n                neobot_think_car_remote_btn_4: '4',\n                neobot_think_car_remote_btn_up: '▲',\n                neobot_think_car_remote_btn_down: '▼',\n                neobot_think_car_remote_btn_left: '◀',\n                neobot_think_car_remote_btn_right: '▶',\n                neobot_think_car_duration_cont: '계속',\n                neobot_think_car_duration_1s: '1초',\n                neobot_think_car_duration_2s: '2초',\n                neobot_think_car_duration_3s: '3초',\n                neobot_think_car_duration_4s: '4초',\n                neobot_think_car_duration_5s: '5초',\n                neobot_think_car_duration_6s: '6초',\n                neobot_think_car_duration_7s: '7초',\n                neobot_think_car_duration_8s: '8초',\n                neobot_think_car_duration_9s: '9초',\n                neobot_think_car_motor_both: '양쪽',\n                neobot_think_car_motor_left: '왼쪽',\n                neobot_think_car_motor_right: '오른쪽',\n                neobot_think_car_motor_move_forward: '전진',\n                neobot_think_car_motor_move_backward: '후진',\n                neobot_think_car_motor_move_left: '좌회전',\n                neobot_think_car_motor_move_right: '우회전',\n                neobot_think_car_motor_move_stop: '정지',\n\n                neobot_think_car_servo_dir_1: '정방향',\n                neobot_think_car_servo_dir_2: '역방향',\n\n                neobot_think_car_percent_10: '10%속도',\n                neobot_think_car_percent_20: '20%속도',\n                neobot_think_car_percent_30: '30%속도',\n                neobot_think_car_percent_40: '40%속도',\n                neobot_think_car_percent_50: '50%속도',\n                neobot_think_car_percent_60: '60%속도',\n                neobot_think_car_percent_70: '70%속도',\n                neobot_think_car_percent_80: '80%속도',\n                neobot_think_car_percent_90: '90%속도',\n                neobot_think_car_percent_100: '100%속도',\n\n                neobot_think_car_angle_0: '0도',\n                neobot_think_car_angle_5: '5도',\n                neobot_think_car_angle_10: '10도',\n                neobot_think_car_angle_15: '15도',\n                neobot_think_car_angle_20: '20도',\n                neobot_think_car_angle_25: '25도',\n                neobot_think_car_angle_30: '30도',\n                neobot_think_car_angle_35: '35도',\n                neobot_think_car_angle_40: '40도',\n                neobot_think_car_angle_45: '45도',\n                neobot_think_car_angle_50: '50도',\n                neobot_think_car_angle_55: '55도',\n                neobot_think_car_angle_60: '60도',\n                neobot_think_car_angle_65: '65도',\n                neobot_think_car_angle_70: '70도',\n                neobot_think_car_angle_75: '75도',\n                neobot_think_car_angle_80: '80도',\n                neobot_think_car_angle_85: '85도',\n                neobot_think_car_angle_90: '90도',\n                neobot_think_car_angle_95: '95도',\n                neobot_think_car_angle_100: '100도',\n                neobot_think_car_angle_105: '105도',\n                neobot_think_car_angle_110: '110도',\n                neobot_think_car_angle_115: '115도',\n                neobot_think_car_angle_120: '120도',\n                neobot_think_car_angle_125: '125도',\n                neobot_think_car_angle_130: '130도',\n                neobot_think_car_angle_135: '135도',\n                neobot_think_car_angle_140: '140도',\n                neobot_think_car_angle_145: '145도',\n                neobot_think_car_angle_150: '150도',\n                neobot_think_car_angle_155: '155도',\n                neobot_think_car_angle_160: '160도',\n                neobot_think_car_angle_165: '165도',\n                neobot_think_car_angle_170: '170도',\n                neobot_think_car_angle_175: '175도',\n                neobot_think_car_angle_180: '180도',\n\n                neobot_think_car_out_all: '모든',\n                neobot_think_car_direction_left: '왼쪽으로',\n                neobot_think_car_direction_right: '오른쪽으로',\n\n                neobot_think_car_color_sign_red: '빨간색',\n                neobot_think_car_color_sign_yellow: '노란색',\n                neobot_think_car_color_sign_green: '녹색',\n                neobot_think_car_color_sign_blue: '파란색',\n            },\n        },\n        en: {\n            // en.js에 작성하던 내용\n            template: {\n                // think car\n                neobot_think_car_auto_driving_title: 'Self-driving',\n                neobot_think_car_line_tracer_start:\n                    'Start self-driving at %1 speed while keeping lanes %2',\n                // neobot_think_car_line_tracer_change_speed: 'Change the speed of self-driving %1 %2',\n                neobot_think_car_reverse_parking_start: 'Start reverse parking at %1 sign %2',\n                neobot_think_car_line_change:\n                    'Change the lane from primary %1 sign to secondary %2 sign %3',\n                neobot_think_car_driving_stop: 'Stop self-driving %1',\n\n                // sensor\n                neobot_think_car_sensor_title: 'Sensor',\n                neobot_think_car_sensor_value: '%1',\n                neobot_think_car_sensor_convert_scale:\n                    \"%1 's changed value   range: %2 ~ %3 conversion: %4 ~ %5\",\n                neobot_think_car_decision_sensor_is_over: '%1 %2 %3',\n                neobot_think_car_decision_equal_with_sensor: \"%1 's color is %2\",\n                neobot_think_car_decision_sensor_angle: '%1 angle %2 %3',\n                neobot_think_car_remote_button: 'pressing button %1 of remote controller',\n\n                // LED\n                neobot_think_car_led_title: 'LED',\n                neobot_think_car_arg_led_duration: '%1',\n                neobot_think_car_led_on: 'Turn on the LED    %1 %2 %3 %4',\n                neobot_think_car_output_led_off: 'Turn off the %1 LED %2',\n                neobot_think_car_led_brightness_with_sensor:\n                    \"Control %2 LED's brightness with %1 sensor %3\",\n                neobot_think_car_color_led_on: 'Turn on the %1 color LED   R %2 G %3 B %4 %5',\n\n                // output\n                neobot_think_car_output_title: 'Set output',\n                neobot_think_car_set_output: 'Output %2 value to %1 port %3',\n\n                // motor\n                neobot_think_car_motor_title: 'Motor',\n                neobot_think_car_robot: 'Robot %1 %2',\n                neobot_think_car_motor_start: 'Motor operation   %1 %2 %3 %4 %5',\n                neobot_think_car_motor_stop: 'Stop the %1 motor(s) %2',\n                neobot_think_car_arg_motor_speed: '%1',\n                neobot_think_car_arg_motor_duration: '%1',\n\n                // melody\n                neobot_think_car_buzzer_title: 'Buzzer',\n                neobot_think_car_play_note_for: 'Buzzer   octave: %1 scale: %2 note: %3 %4',\n                neobot_think_car_melody_play_with_sensor: 'Buzzer rings by %1 sensor value %2',\n                neobot_think_car_melody_stop: 'Stop the buzzer %1',\n\n                // servo\n                neobot_think_car_servo_title: 'Servo motor',\n                get_servo_degree: '%1',\n                neobot_think_car_servo_init: 'Reset the %1 servo motor %2',\n                neobot_think_car_servo_rotate: 'Rotate the servo motor   %1 %2 %3 %4',\n                neobot_think_car_servo_stop: 'Stop the %1 servo motor %2',\n                neobot_think_car_servo_change_degree: 'Change servo angle   %1 %2 %3 %4 %5',\n            },\n            Blocks: {\n                //for dropdown\n                neobot_think_car_port_1: 'IN1',\n                neobot_think_car_port_2: 'IN2',\n                neobot_think_car_port_3: 'IN3',\n                neobot_think_car_port_4: 'IN4',\n                neobot_think_car_port_12: 'IN1 & IN2',\n                neobot_think_car_port_bat: 'battery',\n                neobot_think_car_port_remot: 'remote',\n                neobot_think_car_color_white: 'white',\n                neobot_think_car_color_red: 'red',\n                neobot_think_car_color_yellow: 'yellow',\n                neobot_think_car_color_green: 'green',\n                neobot_think_car_color_blue: 'blue',\n                neobot_think_car_direction_forward: 'forward',\n                neobot_think_car_direction_backward: 'backward',\n                neobot_think_car_sound_silent: 'silent',\n                neobot_think_car_sound_do: 'Do',\n                neobot_think_car_sound_do_shop: 'Do#',\n                neobot_think_car_sound_re: 'Re',\n                neobot_think_car_sound_re_shop: 'Re#',\n                neobot_think_car_sound_mi: 'Mi',\n                neobot_think_car_sound_fa: 'Fa',\n                neobot_think_car_sound_fa_shop: 'Fa#',\n                neobot_think_car_sound_so: 'So',\n                neobot_think_car_sound_so_shop: 'So#',\n                neobot_think_car_sound_la: 'La',\n                neobot_think_car_sound_la_shop: 'La#',\n                neobot_think_car_sound_ti: 'Si',\n                neobot_think_car_sound_half_note: 'a half note',\n                neobot_think_car_sound_quarter_note: 'a quarter note',\n                neobot_think_car_sound_eighth_note: 'a eighth note',\n                neobot_think_car_sound_sixteenth_note: 'a sixteenth note',\n                neobot_think_car_sensor_infrared: 'IR sensor',\n                neobot_think_car_sensor_light: 'light sensor',\n                neobot_think_car_sensor_sound: 'sound sensor',\n                neobot_think_car_compare_symbol1: '＝',\n                neobot_think_car_compare_symbol2: '＞',\n                neobot_think_car_compare_symbol3: '＜',\n                neobot_think_car_compare_symbol4: '≥',\n                neobot_think_car_compare_symbol5: '≤',\n                neobot_think_car_remote_btn_a: 'A',\n                neobot_think_car_remote_btn_b: 'B',\n                neobot_think_car_remote_btn_c: 'C',\n                neobot_think_car_remote_btn_d: 'D',\n                neobot_think_car_remote_btn_1: '1',\n                neobot_think_car_remote_btn_2: '2',\n                neobot_think_car_remote_btn_3: '3',\n                neobot_think_car_remote_btn_4: '4',\n                neobot_think_car_remote_btn_up: '▲',\n                neobot_think_car_remote_btn_down: '▼',\n                neobot_think_car_remote_btn_left: '◀',\n                neobot_think_car_remote_btn_right: '▶',\n                neobot_think_car_duration_cont: 'constantly',\n                neobot_think_car_duration_1s: '1 second',\n                neobot_think_car_duration_2s: '2 seconds',\n                neobot_think_car_duration_3s: '3 seconds',\n                neobot_think_car_duration_4s: '4 seconds',\n                neobot_think_car_duration_5s: '5 seconds',\n                neobot_think_car_duration_6s: '6 seconds',\n                neobot_think_car_duration_7s: '7 seconds',\n                neobot_think_car_duration_8s: '8 seconds',\n                neobot_think_car_duration_9s: '9 seconds',\n                neobot_think_car_motor_both: 'both',\n                neobot_think_car_motor_left: 'left',\n                neobot_think_car_motor_right: 'right',\n                neobot_think_car_motor_move_forward: 'go forward',\n                neobot_think_car_motor_move_backward: 'go backward',\n                neobot_think_car_motor_move_left: 'turn Left',\n                neobot_think_car_motor_move_right: 'turn Right',\n                neobot_think_car_motor_move_stop: 'stop',\n\n                neobot_think_car_servo_dir_1: 'forward',\n                neobot_think_car_servo_dir_2: 'backward',\n\n                neobot_think_car_percent_10: '10% speed',\n                neobot_think_car_percent_20: '20% speed',\n                neobot_think_car_percent_30: '30% speed',\n                neobot_think_car_percent_40: '40% speed',\n                neobot_think_car_percent_50: '50% speed',\n                neobot_think_car_percent_60: '60% speed',\n                neobot_think_car_percent_70: '70% speed',\n                neobot_think_car_percent_80: '80% speed',\n                neobot_think_car_percent_90: '90% speed',\n                neobot_think_car_percent_100: '100% speed',\n\n                neobot_think_car_angle_0: '0 degree',\n                neobot_think_car_angle_5: '5 degrees',\n                neobot_think_car_angle_10: '10 degrees',\n                neobot_think_car_angle_15: '15 degrees',\n                neobot_think_car_angle_20: '20 degrees',\n                neobot_think_car_angle_25: '25 degrees',\n                neobot_think_car_angle_30: '30 degrees',\n                neobot_think_car_angle_35: '35 degrees',\n                neobot_think_car_angle_40: '40 degrees',\n                neobot_think_car_angle_45: '45 degrees',\n                neobot_think_car_angle_50: '50 degrees',\n                neobot_think_car_angle_55: '55 degrees',\n                neobot_think_car_angle_60: '60 degrees',\n                neobot_think_car_angle_65: '65 degrees',\n                neobot_think_car_angle_70: '70 degrees',\n                neobot_think_car_angle_75: '75 degrees',\n                neobot_think_car_angle_80: '80 degrees',\n                neobot_think_car_angle_85: '85 degrees',\n                neobot_think_car_angle_90: '90 degrees',\n                neobot_think_car_angle_95: '95 degrees',\n                neobot_think_car_angle_100: '100 degrees',\n                neobot_think_car_angle_105: '105 degrees',\n                neobot_think_car_angle_110: '110 degrees',\n                neobot_think_car_angle_115: '115 degrees',\n                neobot_think_car_angle_120: '120 degrees',\n                neobot_think_car_angle_125: '125 degrees',\n                neobot_think_car_angle_130: '130 degrees',\n                neobot_think_car_angle_135: '135 degrees',\n                neobot_think_car_angle_140: '140 degrees',\n                neobot_think_car_angle_145: '145 degrees',\n                neobot_think_car_angle_150: '150 degrees',\n                neobot_think_car_angle_155: '155 degrees',\n                neobot_think_car_angle_160: '160 degrees',\n                neobot_think_car_angle_165: '165 degrees',\n                neobot_think_car_angle_170: '170 degrees',\n                neobot_think_car_angle_175: '175 degrees',\n                neobot_think_car_angle_180: '180degrees',\n\n                neobot_think_car_out_all: 'ALL',\n                neobot_think_car_direction_left: 'to the left',\n                neobot_think_car_direction_right: 'to the right',\n\n                neobot_think_car_color_sign_red: 'red',\n                neobot_think_car_color_sign_yellow: 'yellow',\n                neobot_think_car_color_sign_green: 'green',\n                neobot_think_car_color_sign_blue: 'blue',\n            },\n        }, //\n    };\n};\n\nEntry.NeobotThinkCar.blockMenuBlocks = [\n    // think car\n    'neobot_think_car_auto_driving_title',\n    'neobot_think_car_line_tracer_start',\n    // 'neobot_think_car_line_tracer_change_speed',\n    'neobot_think_car_reverse_parking_start',\n    'neobot_think_car_line_change',\n    'neobot_think_car_driving_stop',\n\n    // sensor\n    'neobot_think_car_sensor_title',\n    'neobot_think_car_sensor_value',\n    'neobot_think_car_sensor_convert_scale',\n    'neobot_think_car_decision_sensor_is_over',\n    'neobot_think_car_decision_equal_with_sensor',\n    'neobot_think_car_decision_sensor_angle',\n    'neobot_think_car_remote_button',\n\n    // led\n    'neobot_think_car_led_title',\n    'neobot_think_car_led_on',\n    'neobot_think_car_led_brightness_with_sensor',\n    'neobot_think_car_color_led_on',\n    'neobot_think_car_output_led_off',\n\n    // output\n    'neobot_think_car_output_title',\n    'neobot_think_car_set_output',\n\n    //  motor\n    'neobot_think_car_motor_title',\n    'neobot_think_car_robot',\n    'neobot_think_car_motor_start',\n    'neobot_think_car_motor_stop',\n\n    // servo\n    'neobot_think_car_servo_title',\n    'neobot_think_car_servo_init',\n    'neobot_think_car_servo_rotate',\n    'neobot_think_car_servo_stop',\n    'neobot_think_car_servo_change_degree',\n\n    // melody\n    'neobot_think_car_buzzer_title',\n    'neobot_think_car_play_note_for',\n    'neobot_think_car_melody_play_with_sensor',\n    'neobot_think_car_melody_stop',\n];\n\nEntry.NeobotThinkCar.getBlocks = function() {\n    return {\n        neobot_think_car_auto_driving_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_think_car_auto_driving_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_think_car_auto_driving_title',\n            },\n            class: 'neobot_think_car_operation',\n            isNotFor: ['neobot_think_car'],\n            events: {},\n        },\n        neobot_think_car_line_tracer_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['10%', 10],\n                        ['20%', 20],\n                        ['30%', 30],\n                        ['40%', 40],\n                        ['50%', 50],\n                        ['60%', 60],\n                        ['70%', 70],\n                        ['80%', 80],\n                        ['90%', 90],\n                        ['100%', 100],\n                    ],\n                    value: 60,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_line_tracer_start',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'neobot_think_car_operation',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const speed = script.getNumberField('SPEED');\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    const out3Value = 221;\n                    const buzzerValue = 72;\n                    Entry.hw.sendQueue['OUT3'] = out3Value;\n                    Entry.hw.sendQueue['SND'] = buzzerValue;\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print('=== neobot_think_car_line_tracer_start ===', 'speak');\n                        Entry.console.print('out3 : ' + out3Value, 'speak');\n                        Entry.console.print('buzzer : ' + buzzerValue, 'speak');\n                    }\n\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['OUT1'] = speed;\n                        Entry.hw.sendQueue['SND'] = 0;\n                        if (Entry.NeobotThinkCar.log_to_console) {\n                            Entry.console.print('out1 : ' + speed, 'speak');\n                            Entry.console.print('buzzer : 0', 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n                        script.timeFlag = 0;\n                    }, 300);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        neobot_think_car_reverse_parking_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_color_sign_red, 80],\n                        [Lang.Blocks.neobot_think_car_color_sign_yellow, 120],\n                        [Lang.Blocks.neobot_think_car_color_sign_green, 160],\n                        [Lang.Blocks.neobot_think_car_color_sign_blue, 200],\n                    ],\n                    value: 160,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_reverse_parking_start',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'neobot_think_car_operation',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    const out3Value = 228;\n                    const buzzerValue = 72;\n                    const colorValue = script.getNumberField('COLOR');\n                    Entry.hw.sendQueue['OUT3'] = out3Value;\n                    Entry.hw.sendQueue['SND'] = buzzerValue;\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print(\n                            '=== neobot_think_car_reverse_parking_start ===',\n                            'speak'\n                        );\n                        Entry.console.print('out3 : ' + out3Value, 'speak');\n                        Entry.console.print('buzzer : ' + buzzerValue, 'speak');\n                    }\n\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['OUT1'] = colorValue;\n                        Entry.hw.sendQueue['SND'] = 0;\n                        if (Entry.NeobotThinkCar.log_to_console) {\n                            Entry.console.print('out1 : ' + colorValue, 'speak');\n                            Entry.console.print('buzzer : 0', 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        script.timeFlag = 0;\n                    }, 300);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        neobot_think_car_line_change: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_color_sign_red, 80],\n                        [Lang.Blocks.neobot_think_car_color_sign_yellow, 120],\n                        [Lang.Blocks.neobot_think_car_color_sign_green, 160],\n                        [Lang.Blocks.neobot_think_car_color_sign_blue, 200],\n                    ],\n                    value: 200,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_color_sign_red, 80],\n                        [Lang.Blocks.neobot_think_car_color_sign_yellow, 120],\n                        [Lang.Blocks.neobot_think_car_color_sign_green, 160],\n                        [Lang.Blocks.neobot_think_car_color_sign_blue, 200],\n                    ],\n                    value: 160,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'neobot_think_car_line_change',\n            },\n            paramsKeyMap: {\n                FROM_COLOR: 0,\n                TO_COLOR: 1,\n            },\n            class: 'neobot_think_car_operation',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    const out3Value = 223;\n                    const buzzerValue = 72;\n                    const fromColorValue = script.getNumberField('FROM_COLOR');\n                    const toColorValue = script.getNumberField('TO_COLOR');\n                    Entry.hw.sendQueue['OUT3'] = out3Value;\n                    Entry.hw.sendQueue['SND'] = buzzerValue;\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print('=== neobot_think_car_line_change ===', 'speak');\n                        Entry.console.print('out3 : ' + out3Value, 'speak');\n                        Entry.console.print('buzzer : ' + buzzerValue, 'speak');\n                    }\n\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['OUT1'] = fromColorValue;\n                        Entry.hw.sendQueue['OUT2'] = toColorValue;\n                        Entry.hw.sendQueue['SND'] = 0;\n                        if (Entry.NeobotThinkCar.log_to_console) {\n                            Entry.console.print('out1 : ' + fromColorValue, 'speak');\n                            Entry.console.print('out2 : ' + toColorValue, 'speak');\n                            Entry.console.print('buzzer : 0', 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        script.timeFlag = 0;\n                    }, 300);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        neobot_think_car_driving_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_think_car_driving_stop',\n            },\n            paramsKeyMap: {},\n            class: 'neobot_think_car_operation',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    const out3Value = 248;\n                    const buzzerValue = 72;\n                    Entry.hw.sendQueue['OUT3'] = out3Value;\n                    Entry.hw.sendQueue['SND'] = buzzerValue;\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print('=== neobot_think_car_driving_stop ===', 'speak');\n                        Entry.console.print('out3 : ' + out3Value, 'speak');\n                        Entry.console.print('buzzer : ' + buzzerValue, 'speak');\n                    }\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['OUT1'] = 0;\n                        Entry.hw.sendQueue['OUT2'] = 0;\n                        Entry.hw.sendQueue['OUT3'] = 0;\n                        Entry.hw.sendQueue['SND'] = 0;\n                        if (Entry.NeobotThinkCar.log_to_console) {\n                            Entry.console.print('out1 : 0', 'speak');\n                            Entry.console.print('out2 : 0', 'speak');\n                            Entry.console.print('out3 : 0', 'speak');\n                            Entry.console.print('buzzer : 0', 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n                        script.timeFlag = 0;\n                    }, 300);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        /*neobot_think_car_line_tracer_change_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0%', 0],\n                        ['10%', 10],\n                        ['20%', 20],\n                        ['30%', 30],\n                        ['40%', 40],\n                        ['50%', 50],\n                        ['60%', 60],\n                        ['70%', 70],\n                        ['80%', 80],\n                        ['90%', 90],\n                        ['100%', 100],\n                    ],\n                    value: 50,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'neobot_think_car_line_tracer_change_speed',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'neobot_think_car_operation',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const speed = script.getStringField('SPEED');\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print(\n                        '=== neobot_think_car_line_tracer_change_speed ===',\n                        'speak');\n                    Entry.console.print('out1 : ' + speed, 'speak');\n                    Entry.console.print('==========================',\n                        'speak');\n                }\n                Entry.hw.sendQueue['OUT1'] = speed;\n            },\n        },*/\n        /*************************\n         * class neobot_think_car_sensor\n         *************************/\n        neobot_think_car_sensor_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_think_car_sensor_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_think_car_sensor_title',\n            },\n            class: 'neobot_think_car_sensor',\n            isNotFor: ['neobot_think_car'],\n            events: {},\n        },\n        neobot_think_car_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_think_car_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_think_car_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_think_car_port_remot, 'IR'],\n                        [Lang.Blocks.neobot_think_car_port_bat, 'BAT'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_think_car_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_think_car_sensor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                return Entry.hw.portData[port];\n            },\n        },\n\n        neobot_think_car_sensor_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_think_car_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_think_car_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'neobot_think_car_sensor_convert_scale',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OMIN: 1,\n                OMAX: 2,\n                MIN: 3,\n                MAX: 4,\n            },\n            class: 'neobot_think_car_sensor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT');\n                var value = Entry.hw.portData[port];\n                var omin = script.getNumberValue('OMIN', script);\n                var omax = script.getNumberValue('OMAX', script);\n                var min = script.getNumberValue('MIN', script);\n                var max = script.getNumberValue('MAX', script);\n\n                if (omin > omax) {\n                    var temp = omin;\n                    omin = omax;\n                    omax = temp;\n                }\n\n                if (min > max) {\n                    var temp = min;\n                    min = max;\n                    max = temp;\n                }\n\n                value -= omin;\n                value = value * ((max - min) / (omax - omin));\n                value += min;\n                value = Math.min(max, value);\n                value = Math.max(min, value);\n\n                return Math.round(value);\n            },\n        },\n\n        neobot_think_car_decision_sensor_is_over: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_think_car_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_think_car_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_think_car_port_12, 'IN12'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_think_car_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_think_car_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_think_car_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_think_car_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, 10],\n                type: 'neobot_think_car_decision_sensor_is_over',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                SYMBOL: 1,\n                VALUE: 2,\n            },\n            class: 'neobot_think_car_sensor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const sensorTemp = script.getStringField('SENSOR');\n                const symbol = script.getStringField('SYMBOL');\n                const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                if (sensorTemp == 'IN12') {\n                    const sensor1 = Entry.hw.portData['IN1'];\n                    const sensor2 = Entry.hw.portData['IN2'];\n                    if (symbol == '=') {\n                        return sensor1 == value && sensor2 == value;\n                    } else if (symbol == '>') {\n                        return sensor1 > value && sensor2 > value;\n                    } else if (symbol == '<') {\n                        return sensor1 < value && sensor2 < value;\n                    } else if (symbol == '>=') {\n                        return sensor1 >= value && sensor2 >= value;\n                    } else if (symbol == '<=') {\n                        return sensor1 <= value && sensor2 <= value;\n                    }\n                } else {\n                    const sensor = Entry.hw.portData[sensorTemp];\n                    if (symbol == '=') {\n                        if (sensor == value) return true;\n                        else return false;\n                    } else if (symbol == '>') {\n                        if (sensor > value) return true;\n                        else return false;\n                    } else if (symbol == '<') {\n                        if (sensor < value) return true;\n                        else return false;\n                    } else if (symbol == '>=') {\n                        if (sensor >= value) return true;\n                        else return false;\n                    } else if (symbol == '<=') {\n                        if (sensor <= value) return true;\n                        else return false;\n                    }\n                }\n                return false;\n            },\n        },\n\n        neobot_think_car_decision_equal_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_think_car_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_think_car_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_color_white, 0],\n                        [Lang.Blocks.neobot_think_car_color_red, 1],\n                        [Lang.Blocks.neobot_think_car_color_yellow, 2],\n                        [Lang.Blocks.neobot_think_car_color_green, 3],\n                        [Lang.Blocks.neobot_think_car_color_blue, 4],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_decision_equal_with_sensor',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                COLOR: 1,\n            },\n            class: 'neobot_think_car_sensor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var color = script.getNumberField('COLOR');\n\n                if (sensor >= 10 && sensor <= 50) {\n                    if (color == 0) return true;\n                    else return false;\n                } else if (sensor >= 51 && sensor <= 90) {\n                    if (color == 1) return true;\n                    else return false;\n                } else if (sensor >= 91 && sensor <= 130) {\n                    if (color == 2) return true;\n                    else return false;\n                } else if (sensor >= 131 && sensor <= 170) {\n                    if (color == 3) return true;\n                    else return false;\n                } else if (sensor >= 171 && sensor <= 210) {\n                    if (color == 4) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        neobot_think_car_decision_sensor_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_think_car_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_think_car_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_compare_symbol1, '='],\n                        [Lang.Blocks.neobot_think_car_compare_symbol2, '>'],\n                        [Lang.Blocks.neobot_think_car_compare_symbol3, '<'],\n                        [Lang.Blocks.neobot_think_car_compare_symbol4, '>='],\n                        [Lang.Blocks.neobot_think_car_compare_symbol5, '<='],\n                    ],\n                    value: '>',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_angle_0, '0'],\n                        [Lang.Blocks.neobot_think_car_angle_10, '10'],\n                        [Lang.Blocks.neobot_think_car_angle_20, '20'],\n                        [Lang.Blocks.neobot_think_car_angle_30, '30'],\n                        [Lang.Blocks.neobot_think_car_angle_40, '40'],\n                        [Lang.Blocks.neobot_think_car_angle_50, '50'],\n                        [Lang.Blocks.neobot_think_car_angle_60, '60'],\n                        [Lang.Blocks.neobot_think_car_angle_70, '70'],\n                        [Lang.Blocks.neobot_think_car_angle_80, '80'],\n                        [Lang.Blocks.neobot_think_car_angle_90, '90'],\n                        [Lang.Blocks.neobot_think_car_angle_100, '100'],\n                        [Lang.Blocks.neobot_think_car_angle_110, '110'],\n                        [Lang.Blocks.neobot_think_car_angle_120, '120'],\n                        [Lang.Blocks.neobot_think_car_angle_130, '130'],\n                        [Lang.Blocks.neobot_think_car_angle_140, '140'],\n                        [Lang.Blocks.neobot_think_car_angle_150, '150'],\n                        [Lang.Blocks.neobot_think_car_angle_160, '160'],\n                        [Lang.Blocks.neobot_think_car_angle_170, '170'],\n                        [Lang.Blocks.neobot_think_car_angle_180, '180'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'neobot_think_car_decision_sensor_angle',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                SYMBOL: 1,\n                VALUE: 2,\n            },\n            class: 'neobot_think_car_sensor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                var sensorTemp = script.getStringField('SENSOR');\n                var sensor = Entry.hw.portData[sensorTemp];\n                var symbol = script.getStringField('SYMBOL');\n                var value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                if (symbol == '=') {\n                    if (sensor == value) return true;\n                    else return false;\n                } else if (symbol == '>') {\n                    if (sensor > value) return true;\n                    else return false;\n                } else if (symbol == '<') {\n                    if (sensor < value) return true;\n                    else return false;\n                } else if (symbol == '>=') {\n                    if (sensor >= value) return true;\n                    else return false;\n                } else if (symbol == '<=') {\n                    if (sensor <= value) return true;\n                    else return false;\n                }\n                return false;\n            },\n        },\n\n        neobot_think_car_remote_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#FFFFFF',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_remote_btn_1, '10'],\n                        [Lang.Blocks.neobot_think_car_remote_btn_2, '11'],\n                        [Lang.Blocks.neobot_think_car_remote_btn_3, '12'],\n                        [Lang.Blocks.neobot_think_car_remote_btn_4, '13'],\n                        [Lang.Blocks.neobot_think_car_remote_btn_up, '1'],\n                        [Lang.Blocks.neobot_think_car_remote_btn_down, '2'],\n                        [Lang.Blocks.neobot_think_car_remote_btn_left, '3'],\n                        [Lang.Blocks.neobot_think_car_remote_btn_right, '4'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_think_car_remote_button',\n            },\n            paramsKeyMap: {\n                KEY: 0,\n            },\n            class: 'neobot_think_car_sensor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                var key = script.getNumberField('KEY');\n                var value = Entry.hw.portData['IR'];\n                if (key == value) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n        },\n\n        /*************************\n         * class neobot_think_car_led\n         *************************/\n        neobot_think_car_led_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_think_car_led_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_think_car_led_title',\n            },\n            class: 'neobot_think_car_led',\n            isNotFor: ['neobot_think_car'],\n            events: {},\n        },\n        neobot_think_car_led_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100%', '255'],\n                        ['90%', '230'],\n                        ['80%', '204'],\n                        ['70%', '179'],\n                        ['60%', '153'],\n                        ['50%', '128'],\n                        ['40%', '102'],\n                        ['30%', '77'],\n                        ['20%', '51'],\n                        ['10%', '26'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'neobot_think_car_arg_led_duration',\n                        id: 'm311',\n                    },\n                    null,\n                ],\n                type: 'neobot_think_car_led_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_think_car_led',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const value = script.getNumberField('VALUE', script);\n                    const duration = script.getStringValue('DURATION', script);\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print('=== neobot_think_car_led_on ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('brightness : ' + value, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    if (\n                        duration != '계속' &&\n                        duration != 'constantly' &&\n                        Entry.parseNumber(duration) <= 0\n                    ) {\n                        return script.callReturn();\n                    }\n\n                    if (port == 'ALL') {\n                        Entry.hw.sendQueue['OUT1'] = value;\n                        Entry.hw.sendQueue['OUT2'] = value;\n                        Entry.hw.sendQueue['OUT3'] = value;\n                    } else {\n                        Entry.hw.sendQueue[port] = value;\n                    }\n\n                    if (duration == '계속' || duration == 'constantly') {\n                        return script.callReturn();\n                    }\n\n                    const durationValue = Entry.parseNumber(duration);\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        if (port == 'ALL') {\n                            Entry.hw.sendQueue['OUT1'] = 0;\n                            Entry.hw.sendQueue['OUT2'] = 0;\n                            Entry.hw.sendQueue['OUT3'] = 0;\n                        } else {\n                            Entry.hw.sendQueue[port] = 0;\n                        }\n                        if (Entry.NeobotThinkCar.log_to_console)\n                            Entry.console.print('neobot_think_car_led_on : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, durationValue * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_think_car_output_led_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_output_led_off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_think_car_led',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print('=== neobot_think_car_output_led_off ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = 0;\n                    Entry.hw.sendQueue['OUT2'] = 0;\n                    Entry.hw.sendQueue['OUT3'] = 0;\n                } else {\n                    Entry.hw.sendQueue[port] = 0;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_think_car_led_brightness_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'neobot_think_car_led_brightness_with_sensor',\n            },\n            paramsKeyMap: {\n                IN: 0,\n                OUT: 1,\n            },\n            class: 'neobot_think_car_led',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const inPort = script.getStringField('IN', script);\n                const outPort = script.getStringField('OUT', script);\n                let value = Entry.hw.portData[inPort];\n\n                // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함.\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n                value = Math.ceil((value / 100) * 255);\n\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print(\n                        '=== neobot_think_car_led_brightness_with_sensor ===',\n                        'speak'\n                    );\n                    Entry.console.print('out port : ' + outPort, 'speak');\n                    Entry.console.print('in port : ' + inPort, 'speak');\n                    Entry.console.print('sensor value : ' + Entry.hw.portData[inPort], 'speak');\n                    Entry.console.print('output value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (outPort == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = value;\n                    Entry.hw.sendQueue['OUT2'] = value;\n                    Entry.hw.sendQueue['OUT3'] = value;\n                } else {\n                    Entry.hw.sendQueue[outPort] = value;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_think_car_color_led_on: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_think_car_color_led_on',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'neobot_think_car_led',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT');\n                    let red = script.getNumberValue('RED');\n                    let green = script.getNumberValue('GREEN');\n                    let blue = script.getNumberValue('BLUE');\n\n                    let out1 = false;\n                    let out2 = false;\n                    let out3 = false;\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    } else {\n                        out1 = port == 'OUT1';\n                        out2 = port == 'OUT2';\n                        out3 = port == 'OUT3';\n                    }\n\n                    red = Math.max(red, 1);\n                    red = Math.min(red, 251);\n                    green = Math.max(green, 1);\n                    green = Math.min(green, 251);\n                    blue = Math.max(blue, 1);\n                    blue = Math.min(blue, 251);\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print('=== neobot_think_car_color_led_on ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('red : ' + red, 'speak');\n                        Entry.console.print('green : ' + green, 'speak');\n                        Entry.console.print('blue : ' + blue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    const valRed = 252;\n                    const valGreen = 253;\n                    const valBlue = 254;\n                    const valAccept = 255;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (out1) Entry.hw.sendQueue['OUT1'] = valRed;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = valRed;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = valRed;\n                    if (Entry.NeobotThinkCar.log_to_console)\n                        Entry.console.print('neobot_think_car_color_led_on : ' + valRed, 'speak');\n                    setTimeout(function() {\n                        // set red\n                        if (out1) Entry.hw.sendQueue['OUT1'] = red;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = red;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = red;\n                        if (Entry.NeobotThinkCar.log_to_console)\n                            Entry.console.print('neobot_think_car_color_led_on : ' + red, 'speak');\n                        setTimeout(function() {\n                            // choose green\n                            if (out1) Entry.hw.sendQueue['OUT1'] = valGreen;\n                            if (out2) Entry.hw.sendQueue['OUT2'] = valGreen;\n                            if (out3) Entry.hw.sendQueue['OUT3'] = valGreen;\n                            if (Entry.NeobotThinkCar.log_to_console)\n                                Entry.console.print(\n                                    'neobot_think_car_color_led_on : ' + valGreen,\n                                    'speak'\n                                );\n                            setTimeout(function() {\n                                // set green\n                                if (out1) Entry.hw.sendQueue['OUT1'] = green;\n                                if (out2) Entry.hw.sendQueue['OUT2'] = green;\n                                if (out3) Entry.hw.sendQueue['OUT3'] = green;\n                                if (Entry.NeobotThinkCar.log_to_console)\n                                    Entry.console.print(\n                                        'neobot_think_car_color_led_on : ' + green,\n                                        'speak'\n                                    );\n                                setTimeout(function() {\n                                    // choose blue\n                                    if (out1) Entry.hw.sendQueue['OUT1'] = valBlue;\n                                    if (out2) Entry.hw.sendQueue['OUT2'] = valBlue;\n                                    if (out3) Entry.hw.sendQueue['OUT3'] = valBlue;\n                                    if (Entry.NeobotThinkCar.log_to_console)\n                                        Entry.console.print(\n                                            'neobot_think_car_color_led_on : ' + valBlue,\n                                            'speak'\n                                        );\n                                    setTimeout(function() {\n                                        // set blue\n                                        if (out1) Entry.hw.sendQueue['OUT1'] = blue;\n                                        if (out2) Entry.hw.sendQueue['OUT2'] = blue;\n                                        if (out3) Entry.hw.sendQueue['OUT3'] = blue;\n                                        if (Entry.NeobotThinkCar.log_to_console)\n                                            Entry.console.print(\n                                                'neobot_think_car_color_led_on : ' + blue,\n                                                'speak'\n                                            );\n                                        setTimeout(function() {\n                                            // accept\n                                            if (out1) Entry.hw.sendQueue['OUT1'] = valAccept;\n                                            if (out2) Entry.hw.sendQueue['OUT2'] = valAccept;\n                                            if (out3) Entry.hw.sendQueue['OUT3'] = valAccept;\n                                            if (Entry.NeobotThinkCar.log_to_console)\n                                                Entry.console.print(\n                                                    'neobot_think_car_color_led_on : ' + valAccept,\n                                                    'speak'\n                                                );\n                                            setTimeout(function() {\n                                                // final delay\n                                                script.timeFlag = 0;\n                                            }, 200);\n                                        }, 200);\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n                        }, 200);\n                    }, 200);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        /*************************\n         * class neobot_think_car_output\n         *************************/\n        neobot_think_car_output_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_think_car_output_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_think_car_output_title',\n            },\n            class: 'neobot_think_car_output',\n            isNotFor: ['neobot_think_car'],\n            events: {},\n        },\n        neobot_think_car_set_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'neobot_think_car_set_output',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'neobot_think_car_output',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                var port = script.getStringField('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print('=== neobot_think_car_set_output ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = value;\n                    Entry.hw.sendQueue['OUT2'] = value;\n                    Entry.hw.sendQueue['OUT3'] = value;\n                } else {\n                    Entry.hw.sendQueue[port] = value;\n                }\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_think_car_motor\n         *************************/\n        neobot_think_car_motor_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_think_car_motor_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_think_car_motor_title',\n            },\n            class: 'neobot_think_car_motor',\n            isNotFor: ['neobot_think_car'],\n            events: {},\n        },\n        neobot_think_car_robot: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_motor_move_forward, '1'],\n                        [Lang.Blocks.neobot_think_car_motor_move_backward, '2'],\n                        [Lang.Blocks.neobot_think_car_motor_move_left, '3'],\n                        [Lang.Blocks.neobot_think_car_motor_move_right, '4'],\n                        [Lang.Blocks.neobot_think_car_motor_move_stop, '5'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_robot',\n            },\n            paramsKeyMap: {\n                MOVE: 0,\n            },\n            class: 'neobot_think_car_motor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const move = script.getNumberField('MOVE');\n                let leftValue;\n                let rightValue;\n                switch (move) {\n                    case 1:\n                        leftValue = 0x10 + 10;\n                        rightValue = 0x10 + 10;\n                        break;\n                    case 2:\n                        leftValue = 0x20 + 10;\n                        rightValue = 0x20 + 10;\n                        break;\n                    case 3:\n                        leftValue = 0x20 + 5;\n                        rightValue = 0x10 + 5;\n                        break;\n                    case 4:\n                        leftValue = 0x10 + 5;\n                        rightValue = 0x20 + 5;\n                        break;\n                    case 5:\n                        leftValue = 0;\n                        rightValue = 0;\n                        break;\n                }\n\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print('=== neobot_think_car_robot ===', 'speak');\n                    Entry.console.print('move : ' + move, 'speak');\n                    Entry.console.print('left value : ' + leftValue, 'speak');\n                    Entry.console.print('right value : ' + rightValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['DCL'] = leftValue;\n                Entry.hw.sendQueue['DCR'] = rightValue;\n                return script.callReturn();\n            },\n        },\n\n        neobot_think_car_motor_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_motor_both, '1'],\n                        [Lang.Blocks.neobot_think_car_motor_left, '2'],\n                        [Lang.Blocks.neobot_think_car_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_direction_forward, '1'],\n                        [Lang.Blocks.neobot_think_car_direction_backward, '2'],\n                        [Lang.Blocks.neobot_think_car_direction_left, '3'],\n                        [Lang.Blocks.neobot_think_car_direction_right, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'neobot_think_car_arg_motor_speed',\n                        id: 'm411',\n                    },\n                    {\n                        type: 'neobot_think_car_arg_motor_duration',\n                        id: 'm412',\n                    },\n                    null,\n                ],\n                type: 'neobot_think_car_motor_start',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n                DURATION: 3,\n            },\n            class: 'neobot_think_car_motor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const motor = script.getStringField('MOTOR', script);\n                    const direction = script.getStringField('DIRECTION', script);\n                    const speed = script.getStringValue('SPEED', script);\n                    const duration = script.getStringValue('DURATION', script);\n\n                    if (\n                        duration != '계속' &&\n                        duration != 'constantly' &&\n                        Entry.parseNumber(duration) <= 0\n                    ) {\n                        return script.callReturn();\n                    }\n\n                    let moveLeft = false;\n                    let moveRight = false;\n                    if (motor == 1) {\n                        moveLeft = true;\n                        moveRight = true;\n                    } else if (motor == 2) {\n                        moveLeft = true;\n                    } else {\n                        moveRight = true;\n                    }\n\n                    let leftDirectionValue;\n                    let rightDirectionValue;\n                    if (direction == 1) {\n                        leftDirectionValue = 0x10;\n                        rightDirectionValue = 0x10;\n                    } else if (direction == 2) {\n                        leftDirectionValue = 0x20;\n                        rightDirectionValue = 0x20;\n                    } else if (direction == 3) {\n                        leftDirectionValue = 0x20;\n                        rightDirectionValue = 0x10;\n                    } else {\n                        leftDirectionValue = 0x10;\n                        rightDirectionValue = 0x20;\n                    }\n\n                    // edited 210421, 0~100 을 0~15로 변환, 100 이상은 최대값(15)으로 처리함.\n                    let speedValue = 0;\n                    if (Entry.Utils.isNumber(speed)) {\n                        speedValue = Entry.parseNumber(speed);\n                    } else {\n                        speedValue = Entry.hw.portData[speed];\n                    }\n                    speedValue = Math.max(speedValue, 0);\n                    speedValue = Math.min(speedValue, 100);\n                    speedValue = Math.ceil((speedValue / 100) * 15);\n\n                    const leftOutValue = leftDirectionValue + speedValue;\n                    const rightOutValue = rightDirectionValue + speedValue;\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print('=== neobot_think_car_motor_start ===', 'speak');\n                        Entry.console.print('motor : ' + motor, 'speak');\n                        Entry.console.print('direction : ' + direction, 'speak');\n                        Entry.console.print('speed : ' + speed, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print(\n                            'left direction value : ' + leftDirectionValue,\n                            'speak'\n                        );\n                        Entry.console.print(\n                            'right direction value : ' + rightDirectionValue,\n                            'speak'\n                        );\n                        Entry.console.print('speed value : ' + speedValue, 'speak');\n                        Entry.console.print('left output value : ' + leftOutValue, 'speak');\n                        Entry.console.print('right output value : ' + rightOutValue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    if (moveLeft) {\n                        Entry.hw.sendQueue['DCL'] = leftOutValue;\n                    }\n                    if (moveRight) {\n                        Entry.hw.sendQueue['DCR'] = rightOutValue;\n                    }\n\n                    if (duration == '계속' || duration == 'constantly') {\n                        return script.callReturn();\n                    }\n\n                    const durationValue = Entry.parseNumber(duration);\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['DCL'] = 0;\n                        Entry.hw.sendQueue['DCR'] = 0;\n                        if (Entry.NeobotThinkCar.log_to_console)\n                            Entry.console.print('neobot_think_car_motor_start : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, durationValue * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_think_car_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_motor_both, '1'],\n                        [Lang.Blocks.neobot_think_car_motor_left, '2'],\n                        [Lang.Blocks.neobot_think_car_motor_right, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_motor_stop',\n            },\n            paramsKeyMap: {\n                MOTOR: 0,\n            },\n            class: 'neobot_think_car_motor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const motor = script.getNumberField('MOTOR');\n\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print('=== neobot_think_car_motor_stop ===', 'speak');\n                    Entry.console.print('motor : ' + motor, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (motor == 1) {\n                    Entry.hw.sendQueue['DCL'] = 0;\n                    Entry.hw.sendQueue['DCR'] = 0;\n                } else if (motor == 2) {\n                    Entry.hw.sendQueue['DCL'] = 0;\n                } else {\n                    Entry.hw.sendQueue['DCR'] = 0;\n                }\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_think_car_melody\n         *************************/\n        neobot_think_car_buzzer_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_think_car_buzzer_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_think_car_buzzer_title',\n            },\n            class: 'neobot_think_car_melody',\n            isNotFor: ['neobot_think_car'],\n            events: {},\n        },\n        neobot_think_car_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_sound_silent, '0'],\n                        [Lang.Blocks.neobot_think_car_sound_do, '1'],\n                        [Lang.Blocks.neobot_think_car_sound_do_shop, '2'],\n                        [Lang.Blocks.neobot_think_car_sound_re, '3'],\n                        [Lang.Blocks.neobot_think_car_sound_re_shop, '4'],\n                        [Lang.Blocks.neobot_think_car_sound_mi, '5'],\n                        [Lang.Blocks.neobot_think_car_sound_fa, '6'],\n                        [Lang.Blocks.neobot_think_car_sound_fa_shop, '7'],\n                        [Lang.Blocks.neobot_think_car_sound_so, '8'],\n                        [Lang.Blocks.neobot_think_car_sound_so_shop, '9'],\n                        [Lang.Blocks.neobot_think_car_sound_la, '10'],\n                        [Lang.Blocks.neobot_think_car_sound_la_shop, '11'],\n                        [Lang.Blocks.neobot_think_car_sound_ti, '12'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_sound_half_note, '2'],\n                        [Lang.Blocks.neobot_think_car_sound_quarter_note, '4'],\n                        [Lang.Blocks.neobot_think_car_sound_eighth_note, '8'],\n                        [Lang.Blocks.neobot_think_car_sound_sixteenth_note, '16'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['1', '2', '4', null],\n                type: 'neobot_think_car_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'neobot_think_car_melody',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const note = script.getNumberField('NOTE', script);\n                    const octave = script.getNumberField('OCTAVE', script);\n                    const duration = script.getNumberField('DURATION', script);\n                    let value = note > 0 ? note + 12 * octave : 0;\n\n                    value = Math.min(value, 72);\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print('=== neobot_think_car_play_note_for ===', 'speak');\n                        Entry.console.print('note : ' + note, 'speak');\n                        Entry.console.print('octave : ' + octave, 'speak');\n                        Entry.console.print('duration : ' + duration, 'speak');\n                        Entry.console.print('value : ' + value, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SND'] = value;\n                    setTimeout(function() {\n                        Entry.hw.sendQueue['SND'] = 0;\n                        if (Entry.NeobotThinkCar.log_to_console)\n                            Entry.console.print('neobot_think_car_play_note_for : 0', 'speak');\n                        script.timeFlag = 0;\n                    }, (1 / duration) * 2000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_think_car_melody_play_with_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_think_car_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_think_car_port_3, 'IN3'],\n                    ],\n                    value: 'IN1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_melody_play_with_sensor',\n            },\n            paramsKeyMap: {\n                INPUT: 0,\n            },\n            class: 'neobot_think_car_melody',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const input = script.getStringField('INPUT');\n                let value = Entry.hw.portData[input];\n\n                // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함.\n                value = Math.max(value, 0);\n                value = Math.min(value, 100);\n                value = Math.ceil((value / 100) * 65);\n\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print(\n                        '=== neobot_think_car_melody_play_with_sensor ===',\n                        'speak'\n                    );\n                    Entry.console.print('input : ' + input, 'speak');\n                    Entry.console.print('value : ' + value, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['SND'] = value;\n                return script.callReturn();\n            },\n        },\n\n        neobot_think_car_melody_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'neobot_think_car_melody_stop',\n            },\n            paramsKeyMap: {},\n            class: 'neobot_think_car_melody',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print('=== neobot_think_car_melody_stop ===', 'speak');\n                    Entry.console.print('value : 0', 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                Entry.hw.sendQueue['SND'] = 0;\n                return script.callReturn();\n            },\n        },\n\n        /*************************\n         * class neobot_think_car_servo\n         *************************/\n        neobot_think_car_servo_title: {\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: '#191970',\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                contentPos: {\n                    x: 5,\n                },\n            },\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.neobot_think_car_servo_title,\n                    color: '#191970',\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'neobot_think_car_servo_title',\n            },\n            class: 'neobot_think_car_servo',\n            isNotFor: ['neobot_think_car'],\n            events: {},\n        },\n        neobot_think_car_servo_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_servo_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_think_car_servo',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const resetValue = 186;\n                    const initValue = 1;\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print('=== neobot_think_car_servo_init ===', 'speak');\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    let out1 = port == 'OUT1';\n                    let out2 = port == 'OUT2';\n                    let out3 = port == 'OUT3';\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    if (out1) Entry.hw.sendQueue['OUT1'] = resetValue;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = resetValue;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = resetValue;\n                    if (Entry.NeobotThinkCar.log_to_console)\n                        Entry.console.print('neobot_think_car_servo_init : ' + resetValue, 'speak');\n                    setTimeout(function() {\n                        if (out1) Entry.hw.sendQueue['OUT1'] = initValue;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = initValue;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = initValue;\n                        if (Entry.NeobotThinkCar.log_to_console)\n                            Entry.console.print(\n                                'neobot_think_car_servo_init : ' + initValue,\n                                'speak'\n                            );\n                        setTimeout(function() {\n                            script.timeFlag = 0;\n                        }, 100);\n                    }, 200);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        neobot_think_car_servo_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_think_car_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['0%', 0],\n                        ['10%', 10],\n                        ['20%', 20],\n                        ['30%', 30],\n                        ['40%', 40],\n                        ['50%', 50],\n                        ['60%', 60],\n                        ['70%', 70],\n                        ['80%', 80],\n                        ['90%', 90],\n                        ['100%', 100],\n                    ],\n                    value: 50,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'neobot_think_car_servo_rotate',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'neobot_think_car_servo',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n                const direction = script.getNumberField('DIRECTION');\n                const speed = script.getStringField('SPEED');\n\n                let directionValue = 192; // 정방향\n                if (direction == 2) {\n                    directionValue = 208; // 역방향\n                }\n                let speedValue;\n                if (Entry.Utils.isNumber(speed)) {\n                    speedValue = Entry.parseNumber(speed);\n                } else {\n                    speedValue = Entry.hw.portData[speed];\n                }\n\n                // edited 210421, 0~100 을 0~10 으로 변환\n                speedValue = Math.max(speedValue, 0);\n                speedValue = Math.min(speedValue, 100);\n                speedValue = Math.ceil(speedValue / 10);\n\n                let outValue = directionValue + speedValue;\n                if (outValue == directionValue) {\n                    outValue = 254;\n                } else {\n                    outValue = outValue - 1;\n                }\n\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print('=== neobot_think_car_servo_rotate ===');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('direction : ' + direction, 'speak');\n                    Entry.console.print('speed : ' + speed, 'speak');\n                    Entry.console.print('direction value : ' + directionValue, 'speak');\n                    Entry.console.print('speed value : ' + speedValue, 'speak');\n                    Entry.console.print('output value : ' + outValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = outValue;\n                    Entry.hw.sendQueue['OUT2'] = outValue;\n                    Entry.hw.sendQueue['OUT3'] = outValue;\n                } else {\n                    Entry.hw.sendQueue[port] = outValue;\n                }\n                return script.callReturn();\n            },\n        },\n        neobot_think_car_servo_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'neobot_think_car_servo_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'neobot_think_car_servo',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                const port = script.getStringField('PORT', script);\n                let outValue = 254;\n\n                if (Entry.NeobotThinkCar.log_to_console) {\n                    Entry.console.print('=== neobot_think_car_servo_stop ===', 'speak');\n                    Entry.console.print('port : ' + port, 'speak');\n                    Entry.console.print('output value: ' + outValue, 'speak');\n                    Entry.console.print('==========================', 'speak');\n                }\n\n                if (port == 'ALL') {\n                    Entry.hw.sendQueue['OUT1'] = outValue;\n                    Entry.hw.sendQueue['OUT2'] = outValue;\n                    Entry.hw.sendQueue['OUT3'] = outValue;\n                } else {\n                    Entry.hw.sendQueue[port] = outValue;\n                }\n                return script.callReturn();\n            },\n        },\n\n        neobot_think_car_servo_change_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 'OUT1'],\n                        ['OUT2', 'OUT2'],\n                        ['OUT3', 'OUT3'],\n                        [Lang.Blocks.neobot_think_car_out_all, 'ALL'],\n                    ],\n                    value: 'OUT1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_servo_dir_1, '1'],\n                        [Lang.Blocks.neobot_think_car_servo_dir_2, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['0%', 0],\n                        ['10%', 10],\n                        ['20%', 20],\n                        ['30%', 30],\n                        ['40%', 40],\n                        ['50%', 50],\n                        ['60%', 60],\n                        ['70%', 70],\n                        ['80%', 80],\n                        ['90%', 90],\n                        ['100%', 100],\n                    ],\n                    value: 50,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'get_servo_degree',\n                        id: 'm211',\n                    },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'neobot_think_car_servo_change_degree',\n            },\n            paramsKeyMap: {\n                DEGREE: 0,\n                PORT: 1,\n                DIRECTION: 2,\n                SPEED: 3,\n            },\n            class: 'neobot_think_car_servo',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                if (!script.isStart) {\n                    const port = script.getStringField('PORT', script);\n                    const direction = script.getNumberField('DIRECTION');\n                    const speed = script.getStringValue('SPEED');\n                    const degree = script.getStringValue('DEGREE');\n\n                    let out1 = port == 'OUT1';\n                    let out2 = port == 'OUT2';\n                    let out3 = port == 'OUT3';\n                    if (port == 'ALL') {\n                        out1 = true;\n                        out2 = true;\n                        out3 = true;\n                    }\n\n                    let directionValue = 188;\n                    if (direction == 2) {\n                        directionValue = 189;\n                    }\n\n                    let speedValue;\n                    if (Entry.Utils.isNumber(speed)) {\n                        speedValue = Entry.parseNumber(speed);\n                    } else {\n                        speedValue = Entry.hw.portData[speed];\n                    }\n\n                    // edited 210421, 0~100 을 240~250 으로 변환\n                    speedValue = Math.max(speedValue, 0);\n                    speedValue = Math.min(speedValue, 100);\n                    speedValue = Math.ceil(speedValue / 10) + 240;\n\n                    let degreeValue;\n                    if (Entry.Utils.isNumber(degree)) {\n                        degreeValue = Entry.parseNumber(degree);\n                    } else {\n                        if (degree == 'IN1' || degree == 'IN2' || degree == 'IN3') {\n                            degreeValue = Entry.hw.portData[degree];\n                        } else {\n                            degreeValue = 0;\n                        }\n                    }\n                    // edited 210421, 별도의 변환없이 그대로 사용함\n                    degreeValue = Math.max(degreeValue, 0);\n                    degreeValue = Math.min(degreeValue, 180);\n                    degreeValue = degreeValue + 1;\n\n                    if (Entry.NeobotThinkCar.log_to_console) {\n                        Entry.console.print(\n                            '=== neobot_think_car_servo_change_degree ===',\n                            'speak'\n                        );\n                        Entry.console.print('port : ' + port, 'speak');\n                        Entry.console.print('direction : ' + direction, 'speak');\n                        Entry.console.print('speed : ' + speed, 'speak');\n                        Entry.console.print('degree : ' + degree, 'speak');\n                        Entry.console.print('directionValue : ' + directionValue, 'speak');\n                        Entry.console.print('speedValue : ' + speedValue, 'speak');\n                        Entry.console.print('degreeValue : ' + degreeValue, 'speak');\n                        Entry.console.print('==========================', 'speak');\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    // direction\n                    if (out1) Entry.hw.sendQueue['OUT1'] = directionValue;\n                    if (out2) Entry.hw.sendQueue['OUT2'] = directionValue;\n                    if (out3) Entry.hw.sendQueue['OUT3'] = directionValue;\n                    if (Entry.NeobotThinkCar.log_to_console)\n                        Entry.console.print(\n                            'neobot_think_car_servo_change_degree : ' + directionValue,\n                            'speak'\n                        );\n                    setTimeout(function() {\n                        // speed\n                        if (out1) Entry.hw.sendQueue['OUT1'] = speedValue;\n                        if (out2) Entry.hw.sendQueue['OUT2'] = speedValue;\n                        if (out3) Entry.hw.sendQueue['OUT3'] = speedValue;\n                        if (Entry.NeobotThinkCar.log_to_console)\n                            Entry.console.print(\n                                'neobot_think_car_servo_change_degree : ' + speedValue,\n                                'speak'\n                            );\n                        setTimeout(function() {\n                            // degree\n                            if (out1) Entry.hw.sendQueue['OUT1'] = degreeValue;\n                            if (out2) Entry.hw.sendQueue['OUT2'] = degreeValue;\n                            if (out3) Entry.hw.sendQueue['OUT3'] = degreeValue;\n                            if (Entry.NeobotThinkCar.log_to_console)\n                                Entry.console.print(\n                                    'neobot_think_car_servo_change_degree : ' + degreeValue,\n                                    'speak'\n                                );\n                            setTimeout(function() {\n                                // final delay\n                                script.timeFlag = 0;\n                            }, 200);\n                        }, 200);\n                    }, 200);\n\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n\n        /*****************\n         * ARG Blocks\n         *****************/\n        neobot_think_car_arg_led_duration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_duration_cont, '계속'],\n                        [Lang.Blocks.neobot_think_car_duration_1s, '1'],\n                        [Lang.Blocks.neobot_think_car_duration_2s, '2'],\n                        [Lang.Blocks.neobot_think_car_duration_3s, '3'],\n                        [Lang.Blocks.neobot_think_car_duration_4s, '4'],\n                        [Lang.Blocks.neobot_think_car_duration_5s, '5'],\n                        [Lang.Blocks.neobot_think_car_duration_6s, '6'],\n                        [Lang.Blocks.neobot_think_car_duration_7s, '7'],\n                        [Lang.Blocks.neobot_think_car_duration_8s, '8'],\n                        [Lang.Blocks.neobot_think_car_duration_9s, '9'],\n                    ],\n                    value: '계속',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_think_car_led',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        neobot_think_car_arg_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 'IN1'],\n                        ['IN2', 'IN2'],\n                        ['IN3', 'IN3'],\n                        ['100%', 100],\n                        ['90%', 90],\n                        ['80%', 80],\n                        ['70%', 70],\n                        ['60%', 60],\n                        ['50%', 50],\n                        ['40%', 40],\n                        ['30%', 30],\n                        ['20%', 20],\n                        ['10%', 10],\n                        ['0%', 0],\n                    ],\n                    value: 100,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_think_car_motor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        neobot_think_car_arg_motor_duration: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_duration_cont, '계속'],\n                        [Lang.Blocks.neobot_think_car_duration_1s, '1'],\n                        [Lang.Blocks.neobot_think_car_duration_2s, '2'],\n                        [Lang.Blocks.neobot_think_car_duration_3s, '3'],\n                        [Lang.Blocks.neobot_think_car_duration_4s, '4'],\n                        [Lang.Blocks.neobot_think_car_duration_5s, '5'],\n                        [Lang.Blocks.neobot_think_car_duration_6s, '6'],\n                        [Lang.Blocks.neobot_think_car_duration_7s, '7'],\n                        [Lang.Blocks.neobot_think_car_duration_8s, '8'],\n                        [Lang.Blocks.neobot_think_car_duration_9s, '9'],\n                    ],\n                    value: '계속',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_think_car_motor',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n\n        get_servo_degree: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.neobot_think_car_port_1, 'IN1'],\n                        [Lang.Blocks.neobot_think_car_port_2, 'IN2'],\n                        [Lang.Blocks.neobot_think_car_port_3, 'IN3'],\n                        [Lang.Blocks.neobot_think_car_angle_0, '0'],\n                        [Lang.Blocks.neobot_think_car_angle_5, '5'],\n                        [Lang.Blocks.neobot_think_car_angle_10, '10'],\n                        [Lang.Blocks.neobot_think_car_angle_15, '15'],\n                        [Lang.Blocks.neobot_think_car_angle_20, '20'],\n                        [Lang.Blocks.neobot_think_car_angle_25, '25'],\n                        [Lang.Blocks.neobot_think_car_angle_30, '30'],\n                        [Lang.Blocks.neobot_think_car_angle_35, '35'],\n                        [Lang.Blocks.neobot_think_car_angle_40, '40'],\n                        [Lang.Blocks.neobot_think_car_angle_45, '45'],\n                        [Lang.Blocks.neobot_think_car_angle_50, '50'],\n                        [Lang.Blocks.neobot_think_car_angle_55, '55'],\n                        [Lang.Blocks.neobot_think_car_angle_60, '60'],\n                        [Lang.Blocks.neobot_think_car_angle_65, '65'],\n                        [Lang.Blocks.neobot_think_car_angle_70, '70'],\n                        [Lang.Blocks.neobot_think_car_angle_75, '75'],\n                        [Lang.Blocks.neobot_think_car_angle_80, '80'],\n                        [Lang.Blocks.neobot_think_car_angle_85, '85'],\n                        [Lang.Blocks.neobot_think_car_angle_90, '90'],\n                        [Lang.Blocks.neobot_think_car_angle_95, '95'],\n                        [Lang.Blocks.neobot_think_car_angle_100, '100'],\n                        [Lang.Blocks.neobot_think_car_angle_105, '105'],\n                        [Lang.Blocks.neobot_think_car_angle_110, '110'],\n                        [Lang.Blocks.neobot_think_car_angle_115, '115'],\n                        [Lang.Blocks.neobot_think_car_angle_120, '120'],\n                        [Lang.Blocks.neobot_think_car_angle_125, '125'],\n                        [Lang.Blocks.neobot_think_car_angle_130, '130'],\n                        [Lang.Blocks.neobot_think_car_angle_135, '135'],\n                        [Lang.Blocks.neobot_think_car_angle_140, '140'],\n                        [Lang.Blocks.neobot_think_car_angle_145, '145'],\n                        [Lang.Blocks.neobot_think_car_angle_150, '150'],\n                        [Lang.Blocks.neobot_think_car_angle_155, '155'],\n                        [Lang.Blocks.neobot_think_car_angle_160, '160'],\n                        [Lang.Blocks.neobot_think_car_angle_165, '165'],\n                        [Lang.Blocks.neobot_think_car_angle_170, '170'],\n                        [Lang.Blocks.neobot_think_car_angle_175, '175'],\n                        [Lang.Blocks.neobot_think_car_angle_180, '180'],\n                    ],\n                    value: '90',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'neobot_think_car_servo',\n            isNotFor: ['neobot_think_car'],\n            func: function(sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.NeobotThinkCar;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_orange.js",
    "content": "'use strict';\n\nEntry.Orange = {\n    id: '1.E',\n    name: 'Orange',\n    url: 'https://www.kocoafab.cc/',\n    imageName: 'orange.png',\n    title: {\n        ko: '오렌지 보드',\n        en: 'Orange board',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n\tNEOPIXELINIT: 9,\n\tNEOPIXELCOLOR: 10,\n\tDHTINIT: 21,\n\tDHTTEMP: 22,\n\tDHTHUMI: 23,\n\tNOTONE: 24,\n\tPMINIT: 31,\n\tPMVALUE: 32,\n\tLCDINIT: 41,\n\tLCD: 42,\n\tLCDCLEAR: 43,\n\tLCDEMOTICON: 44,\n\t\t\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n\tduration: {\n        TIME_1ms: 1,\n        TIME_5ms: 5,\n        TIME_10ms: 10,\n        TIME_20ms: 20,\n        TIME_50ms: 50,\n        TIME_100ms: 100,\n        TIME_200ms: 200, \n        TIME_500ms: 500,    \n        TIME_600ms: 600,   \n    }, \n\ttoByte: function(data) {\n        switch (data) {\n            case ' ':\n                data = 32;\n                break;\n            case '!':\n                data = 33;\n                break;\n            case '\"':\n                data = 34;\n                break;\n            case '#':\n                data = 35;\n                break;\n            case '$':\n                data = 36;\n                break;\n            case '%':\n                data = 37;\n                break;\n            case '&':\n                data = 38;\n                break;\n            case \"'\":\n                data = 39;\n                break;\n            case '(':\n                data = 40;\n                break;\n            case ')':\n                data = 41;\n                break;\n            case '*':\n                data = 42;\n                break;\n            case '+':\n                data = 43;\n                break;\n            case ',':\n                data = 44;\n                break;\n            case '-':\n                data = 45;\n                break;\n            case '.':\n                data = 46;\n                break;\n            case '/':\n                data = 47;\n                break;\n            case '0':\n                data = 48;\n                break;\n            case '1':\n                data = 49;\n                break;\n            case '2':\n                data = 50;\n                break;\n            case '3':\n                data = 51;\n                break;\n            case '4':\n                data = 52;\n                break;\n            case '5':\n                data = 53;\n                break;\n            case '6':\n                data = 54;\n                break;\n            case '7':\n                data = 55;\n                break;\n            case '8':\n                data = 56;\n                break;\n            case '9':\n                data = 57;\n                break;\n            case ':':\n                data = 58;\n                break;\n            case ';':\n                data = 59;\n                break;\n            case '<':\n                data = 60;\n                break;\n            case '=':\n                data = 61;\n                break;\n            case '>':\n                data = 62;\n                break;\n            case '?':\n                data = 63;\n                break;\n            case '@':\n                data = 64;\n                break;\n            case 'A':\n                data = 65;\n                break;\n            case 'B':\n                data = 66;\n                break;\n            case 'C':\n                data = 67;\n                break;\n            case 'D':\n                data = 68;\n                break;\n            case 'E':\n                data = 69;\n                break;\n            case 'F':\n                data = 70;\n                break;\n            case 'G':\n                data = 71;\n                break;\n            case 'H':\n                data = 72;\n                break;\n            case 'I':\n                data = 73;\n                break;\n            case 'J':\n                data = 74;\n                break;\n            case 'K':\n                data = 75;\n                break;\n            case 'L':\n                data = 76;\n                break;\n            case 'M':\n                data = 77;\n                break;\n            case 'N':\n                data = 78;\n                break;\n            case 'O':\n                data = 79;\n                break;\n            case 'P':\n                data = 80;\n                break;\n            case 'Q':\n                data = 81;\n                break;\n            case 'R':\n                data = 82;\n                break;\n            case 'S':\n                data = 83;\n                break;\n            case 'T':\n                data = 84;\n                break;\n            case 'U':\n                data = 85;\n                break;\n            case 'V':\n                data = 86;\n                break;\n            case 'W':\n                data = 87;\n                break;\n            case 'X':\n                data = 88;\n                break;\n            case 'Y':\n                data = 89;\n                break;\n            case 'Z':\n                data = 90;\n                break;\n            case '[':\n                data = 91;\n                break;\n            case '\\\\':\n                data = 92;\n                break;\n            case ']':\n                data = 93;\n                break;\n            case '^':\n                data = 94;\n                break;\n            case '_':\n                data = 95;\n                break;\n            case '`':\n                data = 96;\n                break;\n            case 'a':\n                data = 97;\n                break;\n            case 'b':\n                data = 98;\n                break;\n            case 'c':\n                data = 99;\n                break;\n            case 'd':\n                data = 100;\n                break;\n            case 'e':\n                data = 101;\n                break;\n            case 'f':\n                data = 102;\n                break;\n            case 'g':\n                data = 103;\n                break;\n            case 'h':\n                data = 104;\n                break;\n            case 'i':\n                data = 105;\n                break;\n            case 'j':\n                data = 106;\n                break;\n            case 'k':\n                data = 107;\n                break;\n            case 'l':\n                data = 108;\n                break;\n            case 'm':\n                data = 109;\n                break;\n            case 'n':\n                data = 110;\n                break;\n            case 'o':\n                data = 111;\n                break;\n            case 'p':\n                data = 112;\n                break;\n            case 'q':\n                data = 113;\n                break;\n            case 'r':\n                data = 114;\n                break;\n            case 's':\n                data = 115;\n                break;\n            case 't':\n                data = 116;\n                break;\n            case 'u':\n                data = 117;\n                break;\n            case 'v':\n                data = 118;\n                break;\n            case 'w':\n                data = 119;\n                break;\n            case 'x':\n                data = 120;\n                break;\n            case 'y':\n                data = 121;\n                break;\n            case 'z':\n                data = 122;\n                break;\n            case '{':\n                data = 123;\n                break;\n            case '|':\n                data = 124;\n                break;\n            case '}':\n                data = 125;\n                break;\n            case '~':\n                data = 126;\n                break;\n        }\n\n        return data;\n    },\n    BlockState: {},\n};\n\nEntry.Orange.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                orange_get_analog_value: '아날로그 %1 번 센서값',\n                orange_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                orange_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                orange_toggle_led: '디지털 %1 번 핀 %2 %3',\n                orange_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                orange_set_tone: '디지털 %1 번 핀의 피에조 부저를 %3 옥타브 %2 음으로 %4 초 연주하기 %5',\n\t\t\t\torange_set_noTone: '디지털 %1 번 핀의 피에조 부저 소리 끄기 %2',\n                orange_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                orange_get_digital: '디지털 %1 번 센서값',\n\t\t\t\torange_set_neopixelinit: '디지털 %1 번 핀에 연결된 %2 개의 네오픽셀 LED 사용하기 %3',\n\t\t\t\torange_set_neopixel: '디지털 %1 번 핀에 연결된 %2 번째 네오픽셀 LED를 R: %3 , G: %4 , B: %5 색으로 켜기 %6',\n\t\t\t\torange_set_dht_init: '디지털 %1 번 핀에 연결된 온습도센서 사용하기 %2',\n\t\t\t\torange_get_dht_temp_value: '온습도센서의 온도값',\n\t\t\t\torange_get_dht_humi_value: '온습도센서의 습도값',\n\t\t\t\torange_set_pmsensor_init: '미세먼지 센서를 tx: %1 핀 rx: %2 핀에 연결해 사용하기 %3',\n\t\t\t\torange_get_pmsensor_value: '%1 미세먼지 농도(ug/m3)값',\n\t\t\t\torange_get_lcd_row: '%1',\n\t\t\t\torange_get_lcd_col: '%1',\n\t\t\t\torange_set_I2CLCD_init: 'I2C LCD사용하기 %3',\n\t\t\t\torange_set_I2CLCD_print: 'I2C LCD의 %1 번째 줄, %2 번째 칸에 %3 출력하기 %4',\n\t\t\t\torange_set_I2CLCD_clear: 'I2C LCD의 화면 모두 지우기 %3',\n\t\t\t\torange_set_I2CLCD_emoticon: 'I2C LCD의 %1 번째 줄, %2 번째 칸에 %3 이모티콘 출력하기 %4',\n            },\n        },\n        en: {\n            template: {\n                orange_get_analog_value: 'Analog %1 Sensor value',\n                orange_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                orange_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                orange_toggle_led: 'Digital %1 Pin %2 %3',\n                orange_digital_pwm: 'Digital %1 Pin %2 %3',\n                orange_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n\t\t\t\torange_set_noTone: '디지털 %1 번 핀의 버저 소리 끄기 %2',\n                orange_set_servo: 'Set servo pin %1 angle as %2 %3',\n                orange_get_digital: 'Digital %1 Sensor value',\n\t\t\t\torange_set_neopixelinit: '디지털 %1 번 핀에 연결된 %2 개의 네오픽셀 LED 사용하기 %3',\n\t\t\t\torange_set_neopixel: '디지털 %1 번 핀에 연결된 %2 번째 네오픽셀 LED를 R: %3 , G: %4 , B: %5 색으로 켜기 %6',\n\t\t\t\torange_set_dht_init: '디지털 %1 번 핀에 연결된 온습도센서 사용하기 %2',\n\t\t\t\torange_get_dht_temp_value: '온습도센서의 온도값',\n\t\t\t\torange_get_dht_humi_value: '온습도센서의 습도값',\n\t\t\t\torange_set_pmsensor_init: '미세먼지 센서를 tx: %1 핀 rx: %2 핀에 연결해 사용하기 %3',\n\t\t\t\torange_get_pmsensor_value: '%1 미세먼지 농도(ug/m3)값',\n\t\t\t\torange_get_lcd_row: '%1',\n\t\t\t\torange_get_lcd_col: '%1',\n\t\t\t\torange_set_I2CLCD_init: 'I2C LCD사용하기 %3',\n\t\t\t\torange_set_I2CLCD_print: 'I2C LCD의 %1 번째 줄, %2 번째 칸에 %3 출력하기 %4',\n\t\t\t\torange_set_I2CLCD_clear: 'I2C LCD의 화면 모두 지우기 %3',\n\t\t\t\torange_set_I2CLCD_emoticon: 'I2C LCD의 %1 번째 줄, %2 번째 칸에 %3 이모티콘 출력하기 %4',\n            },\n        },\n    };\n};\n\nEntry.Orange.blockMenuBlocks = [\n    'orange_get_analog_value',\n    'orange_get_analog_value_map',\n    'orange_get_ultrasonic_value',\n    'orange_get_digital',\n    'orange_toggle_led',\n    'orange_digital_pwm',\n    'orange_set_servo',\n    'orange_set_tone',\n\t'orange_set_noTone',\n\t'orange_set_neopixelinit',\n\t'orange_set_neopixel',\n\t'orange_set_dht_init',\n\t'orange_get_dht_temp_value',\n\t'orange_get_dht_humi_value',\n\t'orange_set_pmsensor_init',\n\t'orange_get_pmsensor_value',\n\t'orange_get_lcd_row',\n\t'orange_get_lcd_col',\n\t'orange_set_I2CLCD_init',\n\t'orange_set_I2CLCD_print',\n\t'orange_set_I2CLCD_clear',\n\t'orange_set_I2CLCD_emoticon',\n];\n\n//region arduinoExt 아두이노 확장모드\nEntry.Orange.getBlocks = function() {\n    return {\n        orange_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.orange_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'orange_analog_list',\n                    },\n                ],\n            },\n        },\n        orange_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'orange_analog_list',\n                    },\n                ],\n                type: 'orange_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'OrangeGet',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        orange_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'orange_get_analog_value',\n                        params: [\n                            {\n                                type: 'orange_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'orange_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'OrangeGet',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        orange_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                ],\n                type: 'orange_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'OrangeGet',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.Orange.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        orange_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'orange_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'OrangeGet',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Orange' || name === 'ArduinoNano') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Orange.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_get_digital_toggle[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_digital_toggle',\n                    },\n                ],\n            },\n        },\n        orange_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'orange_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Orange',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Orange.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Orange.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Orange.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        orange_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'orange_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Orange',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Orange.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        orange_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'orange_tone_list',\n                    },\n                ],\n            },\n        },\n        orange_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'orange_tone_list',\n                    },\n                ],\n                type: 'orange_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'orange_tone_value',\n                    },\n                ],\n            },\n        },\n        orange_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'orange_octave_list',\n                    },\n                ],\n            },\n        },\n        orange_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'orange_tone_list',\n                    },\n                    {\n                        type: 'orange_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'orange_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'Orange',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.Orange.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.Orange.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.Orange.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.Orange.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.Orange.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t\n\t\torange_set_noTone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'orange_set_noTone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Orange',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_100ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET[port] = {\n\t\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.NOTONE,\n\t\t\t\t\t\t\tdata: port,\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n\t\t\n        orange_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'orange_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Orange',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.Orange.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\t\n\t\t\n\t\torange_set_neopixelinit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n\t\t\t\t\t{\n                        type: 'number',\n                        params: ['25'],\n                    },\n                    null,\n                ],\n                type: 'orange_set_neopixelinit',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n            },\n            class: 'other',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('NUM', script);\n\n\t\t\t\tif (!script.isStart)\n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1; \n\t\t\t\t\t\n\t\t\t\t\tsq.SET[port] = {\n\t\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.NEOPIXELINIT,\n\t\t\t\t\t\t\tdata: value,\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1) \n                {\n                    return script;\n                } \n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                } \n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n\t\torange_set_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n\t\t\t\t\t{\n                        type: 'number',\n                        params: ['0'],\n                    },\n\t\t\t\t\t{\n                        type: 'number',\n                        params: ['255'],\n                    },\n\t\t\t\t\t{\n                        type: 'number',\n                        params: ['255'],\n                    },\n\t\t\t\t\t{\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'orange_set_neopixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUM: 1,\n\t\t\t\tRED: 2,\n\t\t\t\tGREEN: 3,\n\t\t\t\tBLUE: 4,\n            },\n            class: 'other',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var num = script.getNumberValue('NUM', script);\n\t\t\t\tvar r = script.getNumberValue('RED', script);\n\t\t\t\tvar g = script.getNumberValue('GREEN', script);\n\t\t\t\tvar b = script.getNumberValue('BLUE', script);\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_10ms;\n\t\t\t\t\t\tscript.isStart = true;\n\t\t\t\t\t\tscript.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET[num] = {\n\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.NEOPIXELCOLOR,\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\tport: port,\n\t\t\t\t\t\t\t\tnum: num,\n\t\t\t\t\t\t\t\tr: r,\n\t\t\t\t\t\t\t\tg: g,\n\t\t\t\t\t\t\t\tb: b,\n\t\t\t\t\t\t\t  },\n\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script; \n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1) \n                {\n                    return script;\n                } \n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\t\torange_set_dht_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'orange_set_dht_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'dht',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_500ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET[port] = {\n\t\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.DHTINIT,\n\t\t\t\t\t\t\tdata: port,\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n\t\torange_get_dht_temp_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n\t\t\t\t\t'0',\n                ],\n                type: 'orange_get_dht_temp_value',\n            },\n            paramsKeyMap: {\n                TEMP: 0,\n            },\n            class: 'dht',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const temp = script.getNumberValue('TEMP', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[temp];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n\t\t\t\t\n                Entry.hw.sendQueue.GET[Entry.Orange.sensorTypes.DHTTEMP] = {\n                    port: temp,\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.DHTTEMP || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                       \n                    },\n                ],\n            },\n        },\n\t\t\n\t\torange_get_dht_humi_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n\t\t\t\t\t'1',\n                ],\n                type: 'orange_get_dht_humi_value',\n            },\n            paramsKeyMap: {\n                HUMI: 0,\n            },\n            class: 'dht',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const humi = script.getNumberValue('HUMI', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[humi];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n\t\t\t\t\n                Entry.hw.sendQueue.GET[Entry.Orange.sensorTypes.DHTHUMI] = {\n                    port: humi,\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.DHTHUMI || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                       \n                    },\n                ],\n            },\n        },\n\t\t\n\t\torange_set_pmsensor_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['2'],\n                    },\n\t\t\t\t\t{\n                        type: 'arduino_get_port_number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'orange_set_pmsensor_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tPORT1: 1,\n            },\n            class: 'pmsensor',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\t\t\t\tvar port1 = script.getNumberValue('PORT1', script);\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET[port] = {\n\t\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.PMINIT,\n\t\t\t\t\t\t\tdata: port1,\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n\t\torange_get_pmsensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: \"Dropdown\",\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t[ \"PM10\", '0' ],\n\t\t\t\t\t\t[ \"PM2.5\", '1' ],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n\t\t\t\t\t'0',\n\t\t\t\t\tnull,\n                ],\n                type: 'orange_get_pmsensor_value',\n            },\n            paramsKeyMap: {\n                CAT: 0,\n            },\n            class: 'pmsensor',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                const cat = script.getNumberValue('CAT', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[cat];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n\t\t\t\t\n                Entry.hw.sendQueue.GET[Entry.Orange.sensorTypes.PMVALUE] = {\n                    port: cat,\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.PMVALUE || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                       \n                    },\n                ],\n            },\n        },\n\t\torange_get_lcd_row: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'orange_get_lcd_row',\n                    },\n                ],\n            },\n        },\n\t\t\n\t\torange_get_lcd_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n\t\t\t\t\t\t['2', '2'],\n                        ['3', '3'],\n\t\t\t\t\t\t['4', '4'],\n                        ['5', '5'],\n\t\t\t\t\t\t['6', '6'],\n                        ['7', '7'],\n\t\t\t\t\t\t['8', '8'],\n                        ['9', '9'],\n\t\t\t\t\t\t['10', '10'],\n                        ['11', '11'],\n\t\t\t\t\t\t['12', '12'],\n                        ['13', '13'],\n\t\t\t\t\t\t['14', '14'],\n                        ['15', '15'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROW: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('ROW');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n\t\t\t\t\t\t\t\t\t['1', '1'],\n\t\t\t\t\t\t\t\t\t['2', '2'],\n\t\t\t\t\t\t\t\t\t['3', '3'],\n\t\t\t\t\t\t\t\t\t['4', '4'],\n\t\t\t\t\t\t\t\t\t['5', '5'],\n\t\t\t\t\t\t\t\t\t['6', '6'],\n\t\t\t\t\t\t\t\t\t['7', '7'],\n\t\t\t\t\t\t\t\t\t['8', '8'],\n\t\t\t\t\t\t\t\t\t['9', '9'],\n\t\t\t\t\t\t\t\t\t['10', '10'],\n\t\t\t\t\t\t\t\t\t['11', '11'],\n\t\t\t\t\t\t\t\t\t['12', '12'],\n\t\t\t\t\t\t\t\t\t['13', '13'],\n\t\t\t\t\t\t\t\t\t['14', '14'],\n\t\t\t\t\t\t\t\t\t['15', '15'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'orange_get_lcd_col',\n                    },\n                ],\n            },\n        },\n\t\t\n\t\torange_set_I2CLCD_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tparams: ['14'],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tparams: ['1'],\n\t\t\t\t\t},\n\t\t\t\t\tnull,\n                ],\n                type: 'orange_set_I2CLCD_init',\n            },\n            paramsKeyMap: {\n\t\t\t\tPORT: 0,\n\t\t\t\tPORT1: 1,\n            },\n            class: 'LCD',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\t\t\t\tvar port1 = script.getNumberValue('PORT1', script);\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET[port] = {\n\t\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.LCDINIT,\n\t\t\t\t\t\t\tdata: port1,\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n\t\t\n\t\torange_set_I2CLCD_print: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n\t\t\t\t\t{\n                        type: 'orange_get_lcd_row',\n\t\t\t\t\t\tparams: ['0'],\n\n                    },\n\t\t\t\t\t{\n                        type: 'orange_get_lcd_col',\n                        params: ['0'],\n                    },\n\t\t\t\t\t{\n                        type: 'text',\n                        params: ['kocoafab'],\n                    },\n                    null,\n                ],\n                type: 'orange_set_I2CLCD_print',\n            },\n            paramsKeyMap: {\n\t\t\t\tROW: 0,\n\t\t\t\tCOL: 1,\n\t\t\t\tSTRING: 2,\n            },\n            class: 'LCD',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('ROW', script);\n\t\t\t\tvar col = script.getNumberValue('COL', script);\n\t\t\t\tvar string = script.getValue('STRING', script);\n\t\t\t\tvar text = [];\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (typeof string === 'string') \n                    {\n                        for (var i = 0; i < string.length; i++) {\n                            text[i] = Entry.Orange.toByte(string[i]);\n                        }\n                    }\n                    else if (typeof string === 'number') \n                    {\n                        //console.log(\"string\");\n                        //console.log(string);\n                        var num_to_string = string.toString();\n                        for (var i = 0; i < num_to_string.length; i++) {\n                            text[i] = Entry.Orange.toByte(num_to_string[i]);\n                        }\n                        //console.log(\"num_to_string\");\n                        //console.log(num_to_string);\n                        //text[0] = 1;\n                        //text[1] = string / 1;\n                    } \n                    else \n                    {\n                        text[0] = string;\n                    }\n\t\t\t\t\t\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_500ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET['15'] = {\n\t\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.LCD,\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\trow: port,\n\t\t\t\t\t\t\t\tcol: col,\n\t\t\t\t\t\t\t\ttext0: text[0],\n\t\t\t\t\t\t\t\ttext1: text[1],\n\t\t\t\t\t\t\t\ttext2: text[2],\n\t\t\t\t\t\t\t\ttext3: text[3],\n\t\t\t\t\t\t\t\ttext4: text[4],\n\t\t\t\t\t\t\t\ttext5: text[5],\n\t\t\t\t\t\t\t\ttext6: text[6],\n\t\t\t\t\t\t\t\ttext7: text[7],\n\t\t\t\t\t\t\t\ttext8: text[8],\n\t\t\t\t\t\t\t\ttext9: text[9],\n\t\t\t\t\t\t\t\ttext10: text[10],\n\t\t\t\t\t\t\t\ttext11: text[11],\n\t\t\t\t\t\t\t\ttext12: text[12],\n\t\t\t\t\t\t\t\ttext13: text[13],\n\t\t\t\t\t\t\t\ttext14: text[14],\n\t\t\t\t\t\t\t\ttext15: text[15],\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n\t\t\n\t\torange_set_I2CLCD_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tparams: ['15'],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\tparams: ['1'],\n\t\t\t\t\t},\n\t\t\t\t\tnull,\n                ],\n                type: 'orange_set_I2CLCD_clear',\n            },\n            paramsKeyMap: {\n\t\t\t\tPORT: 0,\n\t\t\t\tPORT1: 1,\n            },\n            class: 'LCD',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n\t\t\t\tvar port1 = script.getNumberValue('PORT1', script);\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET[port] = {\n\t\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.LCDCLEAR,\n\t\t\t\t\t\t\tdata: port1,\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n\t\t\n\t\torange_set_I2CLCD_emoticon: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n\t\t\t\t{\n                    type: \"Dropdown\",\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t[ \"온도\", '1' ],\n\t\t\t\t\t\t[ \"습도\", '2' ],\n\t\t\t\t\t\t[ \"미세먼지\", '3' ],\n\t\t\t\t\t\t[ \"하트\", '4' ],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t\t},\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n\t\t\tdef: {\n                params: [\n\t\t\t\t\t{\n                        type: 'orange_get_lcd_row',\n\t\t\t\t\t\tparams: ['0'],\n\n                    },\n\t\t\t\t\t{\n                        type: 'orange_get_lcd_col',\n                        params: ['0'],\n                    },\n\t\t\t\t\t'1',\n                    null,\n                ],\n                type: 'orange_set_I2CLCD_emoticon',\n            },\n            paramsKeyMap: {\n\t\t\t\tROW: 0,\n\t\t\t\tCOL: 1,\n\t\t\t\tEMOTICON: 2,\n            },\n            class: 'LCD',\n            isNotFor: ['Orange'],\n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var row = script.getNumberValue('ROW', script);\n\t\t\t\tvar col = script.getNumberValue('COL', script);\n\t\t\t\tvar emoticon = script.getValue('EMOTICON', script);\n\n\t\t\t\tif (!script.isStart) \n                {\n\t\t\t\t\tif (!sq.SET) {\n\t\t\t\t\t\tsq.SET = {};\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar duration = Entry.Orange.duration.TIME_200ms;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\t\t\t\t\t\n\t\t\t\t\tsq.SET['15'] = {\n\t\t\t\t\t\t\ttype: Entry.Orange.sensorTypes.LCDEMOTICON,\n\t\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\t\trow: row,\n\t\t\t\t\t\t\t\tcol: col,\n\t\t\t\t\t\t\t\temoticon: emoticon,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\ttime: new Date().getTime(),\n\t\t\t\t\t};\n\t\t\t\t\tsetTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration );\n                    return script;\n\t\t\t\t}\n\t\t\t\telse if (script.timeFlag == 1)\n                {\n                    return script;\n                }\n                else \n                {\n                    delete script.timeFlag;\n                    delete script.isStart;\n\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n\t\t\t\t\t\t\n                    },\n                ],\n            },\n        },\n    };\n};\n//endregion arduinoExt 아두이노 확장모드\n\nmodule.exports = Entry.Orange;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_ozobot.js",
    "content": "'use strict';\n\nvar OzobotState = {\n\tSTATE_READY: 'ready',\n\tSTATE_WAIT: 'wait',\n\tSTATE_DONE: 'done',\n};\n\nEntry.Ozobot = {\n\tPORT_MAP: {\n\t\tseq: 0,\n\t\tcat: 0,\n\t\tact: 0,\n\t\tpcnt: 0,\n\t\tp1: 0,\n\t\tp2: 0,\n\t\tp3: 0,\n\t\tp4: 0,\n\t\tp5: 0,\n\t\tp6: 0\n\t},\n\tsetZero: function () {\n\t\tvar portMap = Entry.Ozobot.PORT_MAP;\n\t\tvar sq = Entry.hw.sendQueue;\n\t\tEntry.Ozobot.sequance = 1;\n\t\tEntry.Ozobot.isStarted = false;\n\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\tfor (var port in portMap) {\n\t\t\tsq[port] = portMap[port];\n\t\t}\n\t\tEntry.hw.update();\n\t},\n\tid: '24.2',\n\tname: 'Ozobot Evo',\n\turl: 'http://www.ozobot.kr',\n\timageName: 'ozobot.png',\n\ttitle: {\n\t\tko: '오조봇 이보',\n\t\ten: 'Ozobot Evo',\n\t},\n\tmonitorTemplate: {\n\t\timgPath: 'hw/ozobot.png',\n\t\twidth: 605,\n\t\theight: 434,\n\t},\n\tsequance: 1,\n\tisStarted: false,\n\tstate: OzobotState.STATE_DONE,\n};\nEntry.Ozobot.blockMenuBlocks = [\n\t//region ozobot\n\t'Ozobot_Sensor_floor_color',\n\t'Ozobot_Sensor_line_color',\n\t'Ozobot_Sensor_obstacle',\n\t'Ozobot_Move_wheel',\n\t'Ozobot_Move1',\n\t'Ozobot_Move2',\n\t'Ozobot_Rotate1',\n\t'Ozobot_Rotate2',\n\t'Ozobot_Move_stop',\n\t'Ozobot_Line_trace',\n\t'Ozobot_LED_head',\n\t'Ozobot_LED_head_floor',\n\t'Ozobot_LED_head_random',\n\t'Ozobot_LED_head_off',\n\t'Ozobot_LED_front',\n\t'Ozobot_LED_front_floor',\n\t'Ozobot_LED_front_random',\n\t'Ozobot_LED_front_off',\n\t'Ozobot_Sound_emotion',\n\t'Ozobot_Sound_direction',\n\t'Ozobot_Sound_number',\n\t'Ozobot_Sound_color',\n\t'Ozobot_Sound_tone',\n\t'Ozobot_Sound_tone_time',\n\t'Ozobot_Sound_stop',\n\t'Ozobot_Power_off',\n\t//end region ozobot\n];\nEntry.Ozobot.getBlocks = function () {\n\treturn {\n\t\t// Sensor\n\t\tOzobot_Sensor_floor_color: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic_boolean_field',\n\t\t\ttemplate: '바닥 색깔 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['검은색', 0x00],\n\t\t\t\t\t\t['빨간색', 0x01],\n\t\t\t\t\t\t['초록색', 0x02],\n\t\t\t\t\t\t['노란색', 0x03],\n\t\t\t\t\t\t['파란색', 0x04],\n\t\t\t\t\t\t['자주색', 0x05],\n\t\t\t\t\t\t['청록색', 0x06],\n\t\t\t\t\t\t['흰색', 0x07],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\tparams: [0],\n\t\t\t\ttype: 'Ozobot_Sensor_floor_color',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tclass: 'Ozobot_Sensor',\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('VALUE', script);\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (var1 == pd.surface_color)\n\t\t\t\t\treturn true;\n\t\t\t\treturn false;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sensor_line_color: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic_boolean_field',\n\t\t\ttemplate: '선 색깔 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['검은색', 0x00],\n\t\t\t\t\t\t['빨간색', 0x01],\n\t\t\t\t\t\t['초록색', 0x02],\n\t\t\t\t\t\t['파란색', 0x04],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\tparams: [0],\n\t\t\t\ttype: 'Ozobot_Sensor_line_color',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tclass: 'Ozobot_Sensor',\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('VALUE', script);\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (var1 == pd.line_color)\n\t\t\t\t\treturn true;\n\t\t\t\treturn false;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sensor_obstacle: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic_boolean_field',\n\t\t\ttemplate: '%1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞쪽 장애물', 0x00],\n\t\t\t\t\t\t['앞쪽 오른편 장애물', 0x01],\n\t\t\t\t\t\t['앞쪽 왼편 장애물', 0x02],\n\t\t\t\t\t\t['뒤쪽 장애물', 0x03],\n\t\t\t\t\t\t['뒤쪽 오른편 장애물', 0x04],\n\t\t\t\t\t\t['뒤쪽 왼편 장애물', 0x05],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\tparams: [0],\n\t\t\t\ttype: 'Ozobot_Sensor_obstacle',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tclass: 'Ozobot_Sensor',\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('VALUE', script);\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tswitch (var1) {\n\t\t\t\t\tcase 0x00:\n\t\t\t\t\t\tif (pd.obstacle_front_left || pd.obstacle_front_right)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x01:\n\t\t\t\t\t\tif (pd.obstacle_front_right)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\tif (pd.obstacle_front_left)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x03:\n\t\t\t\t\t\tif (pd.obstacle_rear_left || pd.obstacle_rear_right)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x04:\n\t\t\t\t\t\tif (pd.obstacle_rear_right)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 0x05:\n\t\t\t\t\t\tif (pd.obstacle_rear_left)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t},\n\t\t// Movement\n\t\tOzobot_Move_wheel: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '왼쪽 바퀴 %1 (으)로 %2, 오른쪽 바퀴 %3 (으)로 %4 움직이기 %5',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 0x00],\n\t\t\t\t\t\t['뒤', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 25],\n\t\t\t\t\t\t['보통으로', 45],\n\t\t\t\t\t\t['빠르게', 65],\n\t\t\t\t\t\t['매우빠르게', 85],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 0x00],\n\t\t\t\t\t\t['뒤', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 25],\n\t\t\t\t\t\t['보통으로', 45],\n\t\t\t\t\t\t['빠르게', 65],\n\t\t\t\t\t\t['매우빠르게', 85],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 45, 0, 45],\n\t\t\t\ttype: 'Ozobot_Move_wheel',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION_LEFT: 0,\n\t\t\t\tSPEED_LEFT: 1,\n\t\t\t\tDIRECTION_RIGHT: 2,\n\t\t\t\tSPEED_RIGHT: 3,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Movement',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION_LEFT', script);\n\t\t\t\tvar var2 = script.getNumberField('SPEED_LEFT', script);\n\t\t\t\tvar var3 = script.getNumberField('DIRECTION_RIGHT', script);\n\t\t\t\tvar var4 = script.getNumberField('SPEED_RIGHT', script);\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 4;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2;\n\t\t\t\t\tsq.p3 = var3;\n\t\t\t\t\tsq.p4 = var4;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Move1: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 (으)로 %2 cm만큼 %3 이동하기 %4',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 0x00],\n\t\t\t\t\t\t['뒤', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 25],\n\t\t\t\t\t\t['보통으로', 45],\n\t\t\t\t\t\t['빠르게', 65],\n\t\t\t\t\t\t['매우빠르게', 85],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 5, 45],\n\t\t\t\ttype: 'Ozobot_Move1',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tDISTANCE: 1,\n\t\t\t\tSPEED: 2,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Movement',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tvar var2 = script.getNumberValue('DISTANCE', script);\n\t\t\t\tvar var3 = script.getNumberField('SPEED', script);\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 3;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2 * 10;\n\t\t\t\t\tsq.p3 = var3;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.movement_finish) {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.movement_finish) {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Move2: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 mm 거리를 %2 mm/s 속도로 이동하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [20, 30],\n\t\t\t\ttype: 'Ozobot_Move2',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDISTANCE: 0,\n\t\t\t\tSPEED: 1,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Movement',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberValue('DISTANCE', script);\n\t\t\t\tvar var2 = script.getNumberValue('SPEED', script);\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 3;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = var1;\n\t\t\t\t\tsq.p3 = var2;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.movement_finish) {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.movement_finish) {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Rotate1: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 으로 %2 만큼 회전하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시계 방향', 0x01],\n\t\t\t\t\t\t['반시계 방향', 0x00],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t\tdefaultType: 'angle',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 30],\n\t\t\t\ttype: 'Ozobot_Rotate1',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tANGLE: 1,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Movement',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tvar var2 = script.getNumberValue('ANGLE', script);\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.movement_finish) {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.movement_finish) {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Rotate2: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 으로 %2 회전하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시계 방향', 0x01],\n\t\t\t\t\t\t['반시계 방향', 0x00],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['한 바퀴', 0x00],\n\t\t\t\t\t\t['반 바퀴', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 0],\n\t\t\t\ttype: 'Ozobot_Rotate2',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tANGLE: 1,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Movement',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tvar var2 = script.getNumberField('ANGLE', script);\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2 == 0 ? 360 : 180;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.movement_finish) {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.movement_finish) {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Move_stop: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '바퀴 정지 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_Move_stop',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_Movement',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 4;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tsq.p3 = 0;\n\t\t\t\t\tsq.p4 = 0;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\t// Control\n\t\tOzobot_Line_trace: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '선을 따라 이동하기 %1 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시작', 0x01],\n\t\t\t\t\t\t['멈춤', 0x00],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Ozobot_Line_trace',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tON_OFF: 0,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Line_trace',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('ON_OFF', script);\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 5;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_LED_head: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '머리 불빛 색상 설정 %1 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_LED_head',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tCOLOR: 0,\n\t\t\t},\n\t\t\tclass: 'Ozobot_LED',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getStringField('COLOR', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 1;\n\t\t\t\t\tsq.p2 = parseInt(parseInt(var1.substr(1, 6), 16));\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_LED_head_floor: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '머리 불빛 바닥 색상 가져오기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_LED_head_floor',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_LED',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 1;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tif (pd.surface_color == 8) {\n\t\t\t\t\t\tsq.p1 = 4;\n\t\t\t\t\t}\n\t\t\t\t\tif (pd.surface_color & 1) sq.p2 |= 16711680;\n\t\t\t\t\tif (pd.surface_color & 2) sq.p2 |= 65280;\n\t\t\t\t\tif (pd.surface_color & 4) sq.p2 |= 255;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_LED_head_random: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '머리 불빛 색상 무작위 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_LED_head_random',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_LED',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getStringField('COLOR', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 1;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tsq.p2 |= (Math.floor(Math.random() * 256) << 16);\n\t\t\t\t\tsq.p2 |= (Math.floor(Math.random() * 256) << 8);\n\t\t\t\t\tsq.p2 |= Math.floor(Math.random() * 256);\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_LED_head_off: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '머리 불빛 끄기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_LED_head_off',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_LED',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 1;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_LED_front: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '정면 불빛 색상 설정 %1 %2 %3 %4 %5 %6',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_LED_front',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tCOLOR1: 0,\n\t\t\t\tCOLOR2: 1,\n\t\t\t\tCOLOR3: 2,\n\t\t\t\tCOLOR4: 3,\n\t\t\t\tCOLOR5: 4,\n\t\t\t},\n\t\t\tclass: 'Ozobot_LED',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getStringField('COLOR1', script);\n\t\t\t\tvar var2 = script.getStringField('COLOR2', script);\n\t\t\t\tvar var3 = script.getStringField('COLOR3', script);\n\t\t\t\tvar var4 = script.getStringField('COLOR4', script);\n\t\t\t\tvar var5 = script.getStringField('COLOR5', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 6;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = parseInt(parseInt(var5.substr(1, 6), 16));\n\t\t\t\t\tsq.p3 = parseInt(parseInt(var4.substr(1, 6), 16));\n\t\t\t\t\tsq.p4 = parseInt(parseInt(var3.substr(1, 6), 16));\n\t\t\t\t\tsq.p5 = parseInt(parseInt(var2.substr(1, 6), 16));\n\t\t\t\t\tsq.p6 = parseInt(parseInt(var1.substr(1, 6), 16));\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_LED_front_floor: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '정면 불빛 바닥 색상 가져오기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_LED_front_floor',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_LED',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 6;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tsq.p3 = 0;\n\t\t\t\t\tsq.p4 = 0;\n\t\t\t\t\tsq.p5 = 0;\n\t\t\t\t\tsq.p6 = 0;\n\t\t\t\t\tif (pd.surface_color == 8) {\n\t\t\t\t\t\tsq.p1 = 4;\n\t\t\t\t\t}\n\t\t\t\t\tif (pd.surface_color & 1) sq.p2 |= 16711680;\n\t\t\t\t\tif (pd.surface_color & 2) sq.p2 |= 65280;\n\t\t\t\t\tif (pd.surface_color & 4) sq.p2 |= 255;\n\t\t\t\t\tif (pd.surface_color & 1) sq.p3 |= 16711680;\n\t\t\t\t\tif (pd.surface_color & 2) sq.p3 |= 65280;\n\t\t\t\t\tif (pd.surface_color & 4) sq.p3 |= 255;\n\t\t\t\t\tif (pd.surface_color & 1) sq.p4 |= 16711680;\n\t\t\t\t\tif (pd.surface_color & 2) sq.p4 |= 65280;\n\t\t\t\t\tif (pd.surface_color & 4) sq.p4 |= 255;\n\t\t\t\t\tif (pd.surface_color & 1) sq.p5 |= 16711680;\n\t\t\t\t\tif (pd.surface_color & 2) sq.p5 |= 65280;\n\t\t\t\t\tif (pd.surface_color & 4) sq.p5 |= 255;\n\t\t\t\t\tif (pd.surface_color & 1) sq.p6 |= 16711680;\n\t\t\t\t\tif (pd.surface_color & 2) sq.p6 |= 65280;\n\t\t\t\t\tif (pd.surface_color & 4) sq.p6 |= 255;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_LED_front_random: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '정면 불빛 색상 무작위 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_LED_front_random',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_LED',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getStringField('COLOR1', script);\n\t\t\t\tvar var2 = script.getStringField('COLOR2', script);\n\t\t\t\tvar var3 = script.getStringField('COLOR3', script);\n\t\t\t\tvar var4 = script.getStringField('COLOR4', script);\n\t\t\t\tvar var5 = script.getStringField('COLOR5', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 6;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tsq.p3 = 0;\n\t\t\t\t\tsq.p4 = 0;\n\t\t\t\t\tsq.p5 = 0;\n\t\t\t\t\tsq.p6 = 0;\n\t\t\t\t\tsq.p2 |= (Math.floor(Math.random() * 256) << 16);\n\t\t\t\t\tsq.p2 |= (Math.floor(Math.random() * 256) << 8);\n\t\t\t\t\tsq.p2 |= Math.floor(Math.random() * 256);\n\t\t\t\t\tsq.p3 |= (Math.floor(Math.random() * 256) << 16);\n\t\t\t\t\tsq.p3 |= (Math.floor(Math.random() * 256) << 8);\n\t\t\t\t\tsq.p3 |= Math.floor(Math.random() * 256);\n\t\t\t\t\tsq.p4 |= (Math.floor(Math.random() * 256) << 16);\n\t\t\t\t\tsq.p4 |= (Math.floor(Math.random() * 256) << 8);\n\t\t\t\t\tsq.p4 |= Math.floor(Math.random() * 256);\n\t\t\t\t\tsq.p5 |= (Math.floor(Math.random() * 256) << 16);\n\t\t\t\t\tsq.p5 |= (Math.floor(Math.random() * 256) << 8);\n\t\t\t\t\tsq.p5 |= Math.floor(Math.random() * 256);\n\t\t\t\t\tsq.p6 |= (Math.floor(Math.random() * 256) << 16);\n\t\t\t\t\tsq.p6 |= (Math.floor(Math.random() * 256) << 8);\n\t\t\t\t\tsq.p6 |= Math.floor(Math.random() * 256);\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_LED_front_off: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '정면 불빛 끄기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_LED_front_off',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_LED',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tsq.p3 = 0;\n\t\t\t\t\tsq.p4 = 0;\n\t\t\t\t\tsq.p5 = 0;\n\t\t\t\t\tsq.p6 = 0;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sound_emotion: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '감정 %1 말하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['행복', 0x00],\n\t\t\t\t\t\t['슬픔', 0x01],\n\t\t\t\t\t\t['놀람', 0x02],\n\t\t\t\t\t\t['웃음', 0x03],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0],\n\t\t\t\ttype: 'Ozobot_Sound_emotion',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSOUND: 0,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Sound',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('SOUND', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 3100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sound_direction: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '방향 %1 말하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['Left', 0x01],\n\t\t\t\t\t\t['Right', 0x02],\n\t\t\t\t\t\t['Forward', 0x00],\n\t\t\t\t\t\t['Back', 0x03],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0],\n\t\t\t\ttype: 'Ozobot_Sound_direction',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Sound',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 4;\n\t\t\t\t\tsq.p2 = var1;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1600);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sound_number: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '숫자 %1 말하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['1', 0x01],\n\t\t\t\t\t\t['2', 0x02],\n\t\t\t\t\t\t['3', 0x03],\n\t\t\t\t\t\t['4', 0x04],\n\t\t\t\t\t\t['5', 0x05],\n\t\t\t\t\t\t['6', 0x06],\n\t\t\t\t\t\t['7', 0x07],\n\t\t\t\t\t\t['8', 0x08],\n\t\t\t\t\t\t['9', 0x09],\n\t\t\t\t\t\t['10', 0x0A],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Ozobot_Sound_number',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Sound',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 5;\n\t\t\t\t\tsq.p2 = var1;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1600);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sound_color: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '색깔 %1 말하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['Red', 0x01],\n\t\t\t\t\t\t['Green', 0x02],\n\t\t\t\t\t\t['Yellow', 0x03],\n\t\t\t\t\t\t['Blue', 0x04],\n\t\t\t\t\t\t['Cyan', 0x06],\n\t\t\t\t\t\t['White', 0x07],\n\t\t\t\t\t\t['Black', 0x00]\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 1 ],\n\t\t\t\ttype: 'Ozobot_Sound_color',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tCOLOR: 0,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Sound',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('COLOR', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 8;\n\t\t\t\t\tsq.p2 = var1;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1600);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sound_tone: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '음 %1 %2 연주 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['5 옥타브', 0x05],\n\t\t\t\t\t\t['6 옥타브', 0x06],\n\t\t\t\t\t\t['7 옥타브', 0x07],\n\t\t\t\t\t\t['8 옥타브', 0x08]\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['도', 0x01],\n\t\t\t\t\t\t['도#', 0x02],\n\t\t\t\t\t\t['레', 0x03],\n\t\t\t\t\t\t['레#', 0x04],\n\t\t\t\t\t\t['미', 0x05],\n\t\t\t\t\t\t['파', 0x06],\n\t\t\t\t\t\t['파#', 0x07],\n\t\t\t\t\t\t['솔', 0x08],\n\t\t\t\t\t\t['솔#', 0x09],\n\t\t\t\t\t\t['라', 0x0A],\n\t\t\t\t\t\t['라#', 0x0B],\n\t\t\t\t\t\t['시', 0x0C],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [6, 1],\n\t\t\t\ttype: 'Ozobot_Sound_tone',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tOCTAV: 0,\n\t\t\t\tTONE: 1,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Sound',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('OCTAV', script);\n\t\t\t\tvar var2 = script.getNumberField('TONE', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 3;\n\t\t\t\t\tsq.p1 = var2;\n\t\t\t\t\tsq.p2 = var1 + 1;\n\t\t\t\t\tsq.p3 = 500;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 600);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sound_tone_time: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '음 %1 %2 %3 초 동안 연주 %4',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['5 옥타브', 0x05],\n\t\t\t\t\t\t['6 옥타브', 0x06],\n\t\t\t\t\t\t['7 옥타브', 0x07],\n\t\t\t\t\t\t['8 옥타브', 0x08]\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['도', 0x01],\n\t\t\t\t\t\t['도#', 0x02],\n\t\t\t\t\t\t['레', 0x03],\n\t\t\t\t\t\t['레#', 0x04],\n\t\t\t\t\t\t['미', 0x05],\n\t\t\t\t\t\t['파', 0x06],\n\t\t\t\t\t\t['파#', 0x07],\n\t\t\t\t\t\t['솔', 0x08],\n\t\t\t\t\t\t['솔#', 0x09],\n\t\t\t\t\t\t['라', 0x0A],\n\t\t\t\t\t\t['라#', 0x0B],\n\t\t\t\t\t\t['시', 0x0C],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [6, 1, 1],\n\t\t\t\ttype: 'Ozobot_Sound_tone_time',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tOCTAV: 0,\n\t\t\t\tTONE: 1,\n\t\t\t\tTIME: 2,\n\t\t\t},\n\t\t\tclass: 'Ozobot_Sound',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('OCTAV', script);\n\t\t\t\tvar var2 = script.getNumberField('TONE', script);\n\t\t\t\tvar var3 = script.getNumberValue('TIME', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 3;\n\t\t\t\t\tsq.p1 = var2;\n\t\t\t\t\tsq.p2 = var1 + 1;\n\t\t\t\t\tsq.p3 = var3 * 1000;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, var3 * 1000 + 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Sound_stop: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '소리 정지 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_Sound_stop',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_Sound',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 3;\n\t\t\t\t\tsq.pcnt = 0;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tOzobot_Power_off: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '전원 끄기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Ozobot_Power_off',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Ozobot_Power',\n\t\t\tisNotFor: ['Ozobot Evo'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Ozobot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Ozobot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 4;\n\t\t\t\t\tsq.pcnt = 0;\n\t\t\t\t\tEntry.Ozobot.isStarted = true;\n\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Ozobot.state) {\n\t\t\t\t\t\tcase OzobotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Ozobot.state = OzobotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase OzobotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Ozobot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t};\n};\n\nmodule.exports = Entry.Ozobot;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_palmkit.js",
    "content": "'use strict';\n\nEntry.PalmKit = {\n    id: 'E.1',\n    name: 'palmkit',\n    url: 'http://http://www.needsrobot.com/',\n    imageName: 'palmkit.png',\n    title: {\n        'ko': '팜킷',\n        'en': 'PALM KIT',\n    },\n    setZero: function() {\n        var mcell = Entry.PalmKit.KEY;\n        var sq = Entry.hw.sendQueue;\n        for(var key in mcell)\n            delete sq[Entry.PalmKit.KEY[key]];\n        sq.set_zero = {};\n        Entry.hw.update();\n        delete sq.set_zero;\n    },\n    KEY: {\n        DC_MOTOR: 'dc_motor',\n        RC_MOTOR: 'rc_motor',\n        BUZZER: 'buzzer',\n        LED_R: 'led_r',\n        LED_G: 'led_g',\n        LED_B: 'led_b',\n    },\n    monitorTemplate:{\n        imgPath: 'hw/palmkit.png',\n        width: 700,\n        height: 524,\n        listPorts:{\n        },\n        ports:{\n            CDS0: {\n                name: '조도센서',\n                type: 'input',\n                pos: {x: 200, y: 290},\n            },\n            POT0: {\n                name: '가변저항',\n                type: 'input',\n                pos: {x: 500, y: 350},\n            },\n            TACT_SWITCH0: {\n                name: '버튼',\n                type: 'input',\n                pos: {x: 300, y: 260},\n            },\n        },\n        mode:'both',\n    },\n    toRGB: function(h) {\n        var rgb = {};\n        if(h > 1000) {\n            rgb.r = 255;\n            rgb.g = 255;\n            rgb.b = 255;\n            return rgb;\n        } else if(h < -1000) {\n            rgb.r = 0;\n            rgb.g = 0;\n            rgb.b = 0;\n            return rgb;\n        }\n\n        var _h = parseInt(h / 100);\n        var s = 100;\n        var l = 50 + 5*_h;\n        h = parseFloat(h) % 100;\n\n        h = h / 100;\n        s = parseFloat(s) / 100;\n        l = parseFloat(l) / 100;\n\n\n\n        var q = 0;\n\n        if (l < 0.5) q = l * (1+s);\n        else q = (l+s) - (s*l);\n\n        var p = 2*l - q;\n\n        var r = Math.max(0, Entry.PalmKit.hueToRGB(p, q, h + (1/3)));\n        var g = Math.max(0, Entry.PalmKit.hueToRGB(p, q, h));\n        var b = Math.max(0, Entry.PalmKit.hueToRGB(p, q, h - (1/3)));\n\n\n        rgb.r = Math.round(Math.min(r, 1) * 255);\n        rgb.g = Math.round(Math.min(g, 1) * 255);\n        rgb.b = Math.round(Math.min(b, 1) * 255);\n\n\n        return rgb;\n    },\n\n    hueToRGB: function(p, q, h) {\n        if (h < 0) h += 1;\n        if (h > 1) h -= 1;\n\n        if (6*h < 1) return p + ((q-p) * 6 * h);\n        if (2*h < 1) return q;\n        if (3*h < 2) return p + ((q-p) * 6 * ((2/3)-h));\n\n        return p;\n    },\n\n};\n\nEntry.PalmKit.blockMenuBlocks = [\n    'palmkit_inputsensor',\n    'palmkit_ispressed',\n\n    'palmkit_buzzer_off',\n    'palmkit_buzzer_note',\n    'palmkit_buzzer_note_delay',\n\n    'palmkit_led_toggle',\n    'palmkit_led_color',\n    'palmkit_led_color_number',\n    'palmkit_led',\n    'palmkit_led_pwm',\n\n    'palmkit_motor_stop',\n    'palmkit_dc_motor',\n    'palmkit_dc_motor_for_secs',\n    'palmkit_rc_motor',\n//    'palmkit_rc_motor_for_secs',\n];\n\nEntry.PalmKit.getBlocks = function() {\n    return {\n        palmkit_inputsensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_pot, 'POT'],\n                        [Lang.Blocks.PALMKIT_button, 'TACT_SWITCH'],\n                        [Lang.Blocks.PALMKIT_cds, 'CDS'],\n                    ],\n                    value: 'CDS',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '0'],\n                        [Lang.Blocks.PALMKIT_idx1, '1'],\n                        [Lang.Blocks.PALMKIT_idx2, '2'],\n                        [Lang.Blocks.PALMKIT_idx3, '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'palmkit_inputsensor'\n            },\n            paramsKeyMap: {\n                'TYPE': 0,\n                'INDEX': 1\n            },\n            class: 'palmkit_input',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var pd = Entry.hw.portData[script.getField('TYPE', script)+script.getField('INDEX', script)];\n                return pd;\n            },\n            syntax: { js: [], py: ['PalmKit.inputsensor(%1, %2)']},\n        },\n        palmkit_ispressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '0'],\n                        [Lang.Blocks.PALMKIT_idx1, '1'],\n                        [Lang.Blocks.PALMKIT_idx2, '2'],\n                        [Lang.Blocks.PALMKIT_idx3, '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'palmkit_ispressed'\n            },\n            paramsKeyMap: {\n                'INDEX': 0\n            },\n            class: 'palmkit_input',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var pd = Entry.hw.portData['TACT_SWITCH' + script.getField('INDEX', script)];\n                if(pd == 1) return true;\n                else return false;\n            },\n            syntax: { js: [], py: ['PalmKit.ispressed(%1)']},\n        },\n        palmkit_buzzer_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'palmkit_buzzer_off'\n            },\n            paramsKeyMap: {\n                'INDEX': 0,\n            },\n            class: 'palmkit_buzzer',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX', script);\n\n                buf.idx = idx;\n                buf.value = 0;\n\n                sq.buzzer = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.buzzer_off(%1, %2)']}\n        },\n        palmkit_buzzer_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_buzzer_note_c, '48'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_cs, '49'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_d, '50'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_ds, '51'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_e, '52'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_f, '53'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_fs, '54'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_g, '55'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_gs, '56'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_a, '57'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_as, '58'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_b, '59'],\n                    ],\n                    value:'48',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'palmkit_buzzer_note'\n            },\n            paramsKeyMap: {\n                'INDEX': 0,\n                'NOTE': 1,\n            },\n            class: 'palmkit_buzzer',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX', script);\n                var value = script.getNumberField('NOTE', script);\n\n                buf.idx = idx;\n                buf.value = value;\n\n                sq.buzzer = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.buzzer_note(%1, %2, %3)']}\n        },\n        palmkit_buzzer_note_delay: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_buzzer_note_c, '48'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_cs, '49'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_d, '50'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_ds, '51'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_e, '52'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_f, '53'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_fs, '54'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_g, '55'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_gs, '56'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_a, '57'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_as, '58'],\n                        [Lang.Blocks.PALMKIT_buzzer_note_b, '59'],\n                    ],\n                    value:'48',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    \"type\": \"Block\",\n                    \"accept\": \"string\"\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params:\n                    [\n                        null,\n                        null,\n                        {\n                            type: \"number\",\n                            params: [ \"0.5\" ]\n                        },\n                        null\n                    ],\n                type: 'palmkit_buzzer_note_delay'\n            },\n            paramsKeyMap: {\n                'INDEX': 0,\n                'NOTE': 1,\n                'SEC': 2,\n            },\n            class: 'palmkit_buzzer',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX', script);\n                var value = script.getNumberField('NOTE', script);\n                var sec = script.getNumberValue('SEC', script);\n\n                if(!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    buf.idx = idx;\n                    buf.value = value;\n                    sq.buzzer = buf;\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, sec * 1000);\n\n                    return script;\n                } else if(script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n\n                    buf.idx = idx;\n                    buf.value = 0;\n                    sq.buzzer = buf;\n                    Entry.hw.update();\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['PalmKit.buzzer_note_delay(%1, %2, %3, %4)']}\n        },\n        palmkit_led_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_led_on, '255'],\n                        [Lang.Blocks.PALMKIT_led_off, '0'],\n                    ],\n                    value:'255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'palmkit_led_toggle'\n            },\n            paramsKeyMap: {\n                'INDEX': 0,\n                'VALUE': 1,\n            },\n            class: 'palmkit_led',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX', script);\n                var value = script.getNumberField('VALUE', script);\n\n                buf.idx = idx;\n                buf.value_r = value;\n                buf.value_g = value;\n                buf.value_b = value;\n\n                sq.led_r = buf;\n                sq.led_g = buf;\n                sq.led_b = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.led_toggle(%1, %2, %3)']}\n        },\n        palmkit_led_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'palmkit_led_color'\n            },\n            paramsKeyMap: {\n                'INDEX': 0,\n                'VALUE': 1\n            },\n            class: 'palmkit_led',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX', script);\n                var value = script.getField('VALUE', script);\n                var rgb = Entry.hex2rgb(value);\n\n                buf.idx = idx;\n                buf.value_r = rgb.r;\n                buf.value_g = rgb.g;\n                buf.value_b = rgb.b;\n\n                sq.led_r = buf;\n                sq.led_g = buf;\n                sq.led_b = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.led_color(%1, %2, %3)']}\n        },\n        palmkit_led_color_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params:\n                    [\n                        null,\n                        {\n                            type: 'number',\n                            params: [ '0' ]\n                        },\n                        null\n                    ],\n                type: 'palmkit_led_color_number'\n            },\n            paramsKeyMap: {\n                'INDEX': 0,\n                'VALUE': 1\n            },\n            class: 'palmkit_led',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX', script);\n                var value = script.getNumberValue('VALUE', script);\n                var rgb = Entry.PalmKit.toRGB(value);\n\n                buf.idx = idx;\n                buf.value_r = rgb.r;\n                buf.value_g = rgb.g;\n                buf.value_b = rgb.b;\n\n                sq.led_r = buf;\n                sq.led_g = buf;\n                sq.led_b = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.led_color_number(%1, %2, %3)']}\n        },\n        palmkit_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_led_on, '255'],\n                        [Lang.Blocks.PALMKIT_led_off, '0'],\n                    ],\n                    value:'255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_led_on, '255'],\n                        [Lang.Blocks.PALMKIT_led_off, '0'],\n                    ],\n                    value:'255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_led_on, '255'],\n                        [Lang.Blocks.PALMKIT_led_off, '0'],\n                    ],\n                    value:'255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'palmkit_led'\n            },\n            paramsKeyMap: {\n                'INDEX': 0,\n                'R': 1,\n                'G': 2,\n                'B': 3,\n            },\n            class: 'palmkit_led',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX', script);\n                var r = script.getNumberField('R', script);\n                var g = script.getNumberField('G', script);\n                var b = script.getNumberField('B', script);\n\n                buf.idx = idx;\n                buf.value_r = r;\n                buf.value_g = g;\n                buf.value_b = b;\n\n                sq.led_r = buf;\n                sq.led_g = buf;\n                sq.led_b = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.led(%1, %2, %3, %4, %5)']}\n        },\n        palmkit_led_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params:\n                    [\n                        null,\n                        {\n                            type: 'number',\n                            params: [ '255' ]\n                        },\n                        {\n                            type: 'number',\n                            params: [ '255' ]\n                        },\n                        {\n                            type: 'number',\n                            params: [ '255' ]\n                        },\n                        null,\n                    ],\n                type: 'palmkit_led_pwm'\n            },\n            paramsKeyMap: {\n                'INDEX': 0,\n                'R': 1,\n                'G': 2,\n                'B': 3,\n            },\n            class: 'palmkit_led',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX', script);\n                var r = script.getNumberValue('R', script);\n                var g = script.getNumberValue('G', script);\n                var b = script.getNumberValue('B', script);\n\n                buf.idx = idx;\n                buf.value_r = r;\n                buf.value_g = g;\n                buf.value_b = b;\n\n                sq.led_r = buf;\n                sq.led_g = buf;\n                sq.led_b = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.led_pwm(%1, %2, %3, %4, %5)']}\n        },\n        palmkit_motor_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'palmkit_motor_stop'\n            },\n            paramsKeyMap: {},\n            class: 'palmkit_motor',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                if(sq.dc_motor) delete sq.dc_motor;\n                if(sq.servo_motor) delete sq.servo_motor;\n\n                sq.stop = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.motor_stop(%1)']}\n        },\n        palmkit_rc_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params:\n                    [\n                        null,\n                        {\n                            type: 'number',\n                            params: [ '15' ]\n                        },\n                        {\n                            type: 'number',\n                            params: [ '30' ]\n                        },\n                        null,\n                    ],\n                type: 'palmkit_rc_motor'\n            },\n            paramsKeyMap: {\n                 'INDEX': 0,\n                 'ANGLE': 1,\n                 'SPEED': 2,\n            },\n            class: 'palmkit_motor',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX');\n                var angle = script.getNumberValue('ANGLE');\n                var speed = script.getNumberValue('SPEED');\n                if(speed > 0xff) {\n                    speed = 0xff;\n                }\n\n                buf.idx = idx;\n                buf.angle = angle;\n                buf.speed = speed;\n\n                if(sq.stop) delete sq.stop;\n                sq.servo_motor = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.rc_motor(%1, %2, %3, %4)']}\n        },\n        palmkit_dc_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_motor_cw, '0'],\n                        [Lang.Blocks.PALMKIT_motor_ccw, '1'],\n                    ],\n                    value:'0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params:\n                    [\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: [ '30' ]\n                        },\n                        null,\n                    ],\n                type: 'palmkit_dc_motor'\n            },\n            paramsKeyMap: {\n                 'INDEX': 0,\n                 'DIR': 1,\n                 'SPEED': 2,\n            },\n            class: 'palmkit_motor',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n\n                var idx = script.getField('INDEX');\n                var dir = script.getField('DIR');\n                var speed = script.getNumberValue('SPEED');\n\n                buf.idx = idx;\n                buf.dir = dir;\n                buf.speed = speed;\n\n                if(sq.stop) delete sq.stop;\n                sq.dc_motor = buf;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['PalmKit.dc_motor(%1, %2, %3, %4)']}\n        },\n        palmkit_dc_motor_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_idx0, '1'],\n                        [Lang.Blocks.PALMKIT_idx1, '2'],\n                        [Lang.Blocks.PALMKIT_idx2, '3'],\n                        [Lang.Blocks.PALMKIT_idx3, '4'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PALMKIT_motor_cw, '0'],\n                        [Lang.Blocks.PALMKIT_motor_ccw, '1'],\n                    ],\n                    value:'0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    'type': 'Block',\n                    'accept': 'string'\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params:\n                    [\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: [ '30' ]\n                        },\n                        {\n                            type: 'number',\n                            params: [ '2' ]\n                        },\n                        null,\n                    ],\n                type: 'palmkit_dc_motor_for_secs'\n            },\n            paramsKeyMap: {\n                 'INDEX': 0,\n                 'DIR': 1,\n                 'SPEED': 2,\n                 'SECS' : 3,\n            },\n            class: 'palmkit_motor',\n            isNotFor: ['palmkit'],\n            func: function (sprite, script) {\n                var buf = {};\n                var sq = Entry.hw.sendQueue;\n                var idx = script.getField('INDEX');\n                var dir = script.getField('DIR');\n                var speed = script.getNumberValue('SPEED');\n                var secs = script.getNumberValue('SECS');\n\n                if(!script.isStart) {\n                    if(sq.stop) delete sq.stop;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    buf.idx = idx;\n                    buf.dir = dir;\n                    buf.speed = speed;\n\n                    sq.dc_motor = buf;\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, secs * 1000);\n\n                    return script;\n                } else if(script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n\n                    buf.idx = idx;\n                    buf.dir = dir;\n                    buf.speed = 0;\n\n                    sq.dc_motor = buf;\n                    Entry.hw.update();\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['PalmKit.dc_motor_for_secs(%1, %2, %3, %4, %5)']}\n        },\n    };\n};\n\nEntry.PalmKit.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                palmkit_inputsensor: '%1 %2 번',\n                palmkit_ispressed: '%1 번 버튼 누르기?',\n                palmkit_buzzer_off: '%1 번 부저 끄기 %2',\n                palmkit_buzzer_note: '%1 번 부저 %2 음 내기 %3',\n                palmkit_buzzer_note_delay: '%1 번 부저 %2 음 %3 박자로 연주하기 %4',\n                palmkit_led_toggle: '%1 번 LED %2 %3',\n                palmkit_led_color: '%1 번 LED 색 %2 으로 정하기 %3',\n                palmkit_led_color_number: '%1 번 LED 색 %2 으로 정하기 %3',\n                palmkit_led: '%1 번 LED R %2 G %3 B %4 %5',\n                palmkit_led_pwm: '%1 번 LED R %2 G %3 B %4 %5',\n                palmkit_motor_stop: '모터 정지하기 %1',\n                palmkit_dc_motor: '%1 번 DC모터 %2 속력 %3 으로 움직이기 %4',\n                palmkit_dc_motor_for_secs: '%1 번 DC모터 %2 속력 %3 으로 %4 초간 움직이기 %5',\n                palmkit_rc_motor: '%1 번 RC모터 각도 %2 속력 %3 으로 움직이기 %4',\n            },\n            Blocks: {\n                PALMKIT_idx0: '1',\n                PALMKIT_idx1: '2',\n                PALMKIT_idx2: '3',\n                PALMKIT_idx3: '4',\n                PALMKIT_ir: '바닥센서',\n                PALMKIT_pot: '가변저항',\n                PALMKIT_button: '버튼',\n                PALMKIT_cds: '조도센서',\n                PALMKIT_led_on: '켜기',\n                PALMKIT_led_off: '끄기',\n                PALMKIT_buzzer_note_c: '도',\n                PALMKIT_buzzer_note_cs: '도#',\n                PALMKIT_buzzer_note_d: '레',\n                PALMKIT_buzzer_note_ds: '레#',\n                PALMKIT_buzzer_note_e: '미',\n                PALMKIT_buzzer_note_f: '파',\n                PALMKIT_buzzer_note_fs: '파#',\n                PALMKIT_buzzer_note_g: '솔',\n                PALMKIT_buzzer_note_gs: '솔#',\n                PALMKIT_buzzer_note_a: '라',\n                PALMKIT_buzzer_note_as: '라#',\n                PALMKIT_buzzer_note_b: '시',\n                PALMKIT_motor_cw: '시계방향',\n                PALMKIT_motor_ccw: '반시계방향',\n            }\n\n        },\n        en: {\n            template: {\n                palmkit_inputsensor: '%1 No. %2',\n                palmkit_ispressed: 'No. %1 Button is pressed?',\n                palmkit_buzzer_off: 'No. %1 Buzzer off %2',\n                palmkit_buzzer_note: 'No. %1 Buzzer play note %2 %3',\n                palmkit_buzzer_note_delay: 'No. %1 Buzzer play note %2 for %3 beats %4',\n                palmkit_led_toggle: 'No. %1 LED %2 %3',\n                palmkit_led_color: 'No. %1 LED set color to %2 %3',\n                palmkit_led_color_number: 'No. %1 LED set color to %2 %3',\n                palmkit_led: 'No. %1 LED R %2 G %3 B %4 %5',\n                palmkit_led: 'No. %1 LED R %2 G %3 B %4 %5',\n                palmkit_motor_stop: 'Motor stop %1',\n                palmkit_dc_motor: 'No. %1 DC motor move to direction %2 at speed %3 %4',\n                palmkit_dc_motor: 'No. %1 DC motor move to direction %2 at speed %3 for %4 secs %5',\n                palmkit_rc_motor: 'No. %1 RC motor move to angle %2 at speed %3 %4',\n            },\n            Blocks: {\n                PALMKIT_idx0: '1',\n                PALMKIT_idx1: '2',\n                PALMKIT_idx2: '3',\n                PALMKIT_idx3: '4',\n                PALMKIT_ir: 'IR',\n                PALMKIT_pot: 'Potentiometer',\n                PALMKIT_button: 'Button',\n                PALMKIT_cds: 'CDS',\n                PALMKIT_led_on: 'On',\n                PALMKIT_led_off: 'Off',\n                PALMKIT_buzzer_note_c: 'C',\n                PALMKIT_buzzer_note_cs: 'C#',\n                PALMKIT_buzzer_note_d: 'D',\n                PALMKIT_buzzer_note_ds: 'D#',\n                PALMKIT_buzzer_note_e: 'E',\n                PALMKIT_buzzer_note_f: 'F',\n                PALMKIT_buzzer_note_fs: 'F#',\n                PALMKIT_buzzer_note_g: 'G',\n                PALMKIT_buzzer_note_gs: 'G#',\n                PALMKIT_buzzer_note_a: 'A',\n                PALMKIT_buzzer_note_as: 'A#',\n                PALMKIT_buzzer_note_b: 'B',\n                PALMKIT_motor_cw: 'Clockwise',\n                PALMKIT_motor_ccw: 'Counter clockwise',\n            }\n        }\n    }\n};\n\nmodule.exports = Entry.PalmKit;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_pingpong.js",
    "content": "'use strict';\n\nconst Buffer = require('buffer').Buffer;\n\nEntry.PingpongG1 = new (class PingpongG1 {\n    constructor() {\n        this.id = '35.1';\n        this.name = 'PingpongG1';\n        this.url = 'https://www.roborisen.com';\n        this.imageName = 'pingpong_g1.png';\n        this.delayTime = 50;\n        this.title = {\n            ko: '핑퐁 G1',\n            en: 'Pingpong G1',\n        };\n        this.communicationType = 'manual';\n\n        this.TILT_THRESHOLD = 20;\n        this.MOVE_THRESHOLD = 30;\n        this.send_cmd_id = 0;\n\n        this.sensor_data = {\n            MOVE_X: 0,\n            MOVE_Y: 0,\n            MOVE_Z: 0,\n            TILT_X: 0,\n            TILT_Y: 0,\n            TILT_Z: 0,\n            BUTTON: 0,\n            PROXIMITY: 0,\n            AIN: 0,\n        };\n        this.prev_sensor_data = {\n            MOVE_X: 0,\n            MOVE_Y: 0,\n            MOVE_Z: 0,\n            TILT_X: 0,\n            TILT_Y: 0,\n            TILT_Z: 0,\n            BUTTON: 0,\n            PROXIMITY: 0,\n            AIN: 0,\n        };\n\n        this.blockMenuBlocks = [\n            'pingpong_g1_when_button_pressed',\n            'pingpong_g1_is_button_pressed',\n            'pingpong_g1_when_tilted',\n            'pingpong_g1_is_tilted',\n            'pingpong_g1_get_tilt_value',\n            'pingpong_g1_is_top_shape',\n            'pingpong_g1_get_sensor_value',\n            'pingpong_g1_motor_rotate',\n            'pingpong_g1_start_motor_rotate',\n            'pingpong_g1_stop_motor_rotate',\n            'pingpong_g1_rotate_servo_mortor',\n            'pingpong_g1_set_dot_pixel',\n            'pingpong_g1_set_dot_string',\n            'pingpong_g1_set_dot_clear',\n            'pingpong_g1_playNoteForBeats',\n            'pingpong_g1_restForBeats',\n            'pingpong_g1_setTempo',\n            'pingpong_g1_getTempo',\n        ];\n\n        this.tempo = 60;\n    }\n\n    setZero() {\n        // all LED clear\n        this.sendCommand(this.makePacket(0xa2, 0xe3, [0x70, 1, 0, ' ']));\n        setTimeout(() => {\n            // all cube stop\n            this.sendCommand(this.makePacket(0xcc, 0x0004, [2, 0, 0, 1, 0, 0]));\n            setTimeout(() => {\n                Entry.hw.sendQueue.COMMAND = {\n                    id: -1,\n                };\n                Entry.hw.update();\n\n                this.send_cmd_id = 0;\n            }, this.delayTime);\n        }, this.delayTime);\n    }\n\n    sendCommand(packet) {\n        Entry.hw.sendQueue.COMMAND = {\n            id: ++this.send_cmd_id,\n            data: packet,\n        };\n        Entry.hw.update();\n    }\n\n    afterReceive(pd) {\n        //this.sensor_data = pd.SENSOR;\n\n        if (!Entry.engine.isState('run')) {\n            return;\n        }\n\n        if (this.prev_sensor_data.BUTTON != pd.BUTTON) {\n            //console.log('Button:', this.prev_sensor_data.BUTTON, pd.BUTTON);\n            this.prev_sensor_data.BUTTON = pd.BUTTON;\n            Entry.engine.fireEvent('pp_when_button_pressed');\n        }\n\n        if (\n            Math.abs(pd.TILT_X) >= this.TILT_THRESHOLD ||\n            Math.abs(pd.TILT_Y) >= this.TILT_THRESHOLD\n        ) {\n            Entry.engine.fireEvent('pp_when_tilted');\n        }\n    }\n\n    postCallReturn(script, myfunc) {\n        if (myfunc == undefined) {\n            return script.callReturn();\n        }\n\n        if (script.is_start == undefined) {\n            script.is_start = true;\n\n            const [packet, waitTime = this.delayTime] = myfunc();\n\n            if (packet && packet.length > 0) {\n                this.sendCommand(packet);\n            }\n\n            setTimeout(() => {\n                script.is_start = false;\n            }, waitTime);\n            return script;\n        } else if (script.is_start == true) {\n            return script;\n        } else {\n            delete script.is_start;\n\n            return script.callReturn();\n        }\n    }\n\n    _clampBeats(beats) {\n        return Math.min(Math.max(beats, 0), 40);\n        //return MathUtil.clamp(beats, 0, 40);\n    }\n\n    _clampTempo(tempo) {\n        return Math.min(Math.max(tempo, 20), 500);\n        //return MathUtil.clamp(tempo, 20, 500);\n    }\n\n    _beatsToDuration(beats) {\n        let duration = Math.round((60 / this.tempo) * beats * 100);\n        return duration;\n    }\n\n    makePacket(opcode, taskid, opt) {\n        // make heder - cubeid, cubecnt, op, size, method\n        const header = Buffer.from([0xff, 0xff, 0xff, 0xff, 0, 0, opcode, 0, 0]);\n        const property = Buffer.from(opt);\n\n        //header.writeUInt16BE(0xFFFF, 0);\n        //header.writeUInt16BE(0xFFFF, 2);\t// cubdid\n\n        header.writeUInt16BE(taskid, 4);\n        header.writeUInt16BE(header.length + property.length, 7);\n\n        return Buffer.concat([header, property]);\n    }\n\n    getBlocks() {\n        return {\n            pingpong_g1_when_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'pingpong_g1_when_button_pressed',\n                },\n                class: 'PingpongG1',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                event: 'pp_when_button_pressed',\n                func(sprite, script) {\n                    const buttonData = Entry.hw.portData.BUTTON;\n\n                    if (buttonData != 1) {\n                        return this.die();\n                    }\n                    return script.callReturn();\n                },\n            },\n            pingpong_g1_when_tilted: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'pingpong_g1_when_tilted',\n                },\n                paramsKeyMap: {\n                    TILT_DIR: 1,\n                },\n                class: 'PingpongG1',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                event: 'pp_when_tilted',\n                func(sprite, script) {\n                    const tiltDir = script.getStringField('TILT_DIR');\n                    const pd = Entry.hw.portData;\n\n                    let tiltValue = 0;\n                    switch (tiltDir) {\n                        case 'F_CIRCLE':\n                            tiltValue = pd.TILT_X * -1;\n                            break;\n                        case 'B_TRIANGLE':\n                            tiltValue = pd.TILT_X;\n                            break;\n                        case 'L_RECTANGLE':\n                            tiltValue = pd.TILT_Y * -1;\n                            break;\n                        case 'R_STAR':\n                            tiltValue = pd.TILT_Y;\n                            break;\n                        default:\n                            break;\n                    }\n\n                    if (tiltValue >= Entry.PingpongG1.TILT_THRESHOLD) {\n                        return script.callReturn();\n                    } else {\n                        return this.die();\n                    }\n                },\n            },\n            pingpong_g1_is_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                //statements: [],\n                //params: [],\n                //events: {},\n                def: {\n                    type: 'pingpong_g1_is_button_pressed',\n                },\n                //paramsKeyMap: { },\n                class: 'PingpongG1',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    const pd = Entry.hw.portData;\n                    //return Entry.PingpongG1.sensor_data.BUTTON == 1;\n                    return pd.BUTTON == 1;\n                },\n            },\n            pingpong_g1_is_tilted: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                //statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                //events: {},\n                def: { params: [], type: 'pingpong_g1_is_tilted' },\n                paramsKeyMap: {\n                    TILT_DIR: 0,\n                },\n                class: 'PingpongG1',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    const tiltDir = script.getStringField('TILT_DIR', script);\n                    const pd = Entry.hw.portData;\n                    let tiltValue = 0;\n                    switch (tiltDir) {\n                        case 'F_CIRCLE':\n                            tiltValue = pd.TILT_X * -1;\n                            break;\n                        case 'B_TRIANGLE':\n                            tiltValue = pd.TILT_X;\n                            break;\n                        case 'L_RECTANGLE':\n                            tiltValue = pd.TILT_Y * -1;\n                            break;\n                        case 'R_STAR':\n                            tiltValue = pd.TILT_Y;\n                            break;\n                        default:\n                            break;\n                    }\n                    return tiltValue >= Entry.PingpongG1.TILT_THRESHOLD;\n                },\n            },\n            pingpong_g1_get_tilt_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {\n                    viewAdd: [\n                        function() {\n                            //console.log('... viewAdd called!');\n                        },\n                    ],\n                    viewDestroy: [\n                        function() {\n                            //console.log('... viewDestroy called!');\n                        },\n                    ],\n                    dataAdd: [\n                        function(block) {\n                            //console.log(' ...... dataAdd called');\n                        },\n                    ],\n                    dataDestroy: [\n                        function(block) {\n                            //console.log(' ...... dataDestroy called');\n                        },\n                    ],\n                },\n                def: {\n                    params: [null],\n                    type: 'pingpong_g1_get_tilt_value',\n                },\n                paramsKeyMap: { DIR: 0 },\n                class: 'PingpongG1',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    const dir = script.getStringField('DIR', script);\n                    const pd = Entry.hw.portData;\n                    let value = 0;\n                    switch (dir) {\n                        case 'F_CIRCLE':\n                            value = pd.TILT_X * -1;\n                            break;\n                        case 'B_TRIANGLE':\n                            value = pd.TILT_X;\n                            break;\n                        case 'L_RECTANGLE':\n                            value = pd.TILT_Y * -1;\n                            break;\n                        case 'R_STAR':\n                            value = pd.TILT_Y;\n                            break;\n                        default:\n                            break;\n                    }\n                    return value;\n                },\n            },\n            pingpong_g1_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_sensor_proximity, 'PROXIMITY'],\n                            [Lang.Blocks.pingpong_sensor_ain, 'AIN'],\n                        ],\n                        value: 'PROXIMITY',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g1_get_sensor_value' },\n                paramsKeyMap: { SENSOR: 0 },\n                class: 'PingpongG1',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    const sensorType = script.getStringField('SENSOR', script);\n                    const pd = Entry.hw.portData;\n                    let value = 0;\n                    switch (sensorType) {\n                        case 'PROXIMITY':\n                            value = pd.PROXIMITY;\n                            break;\n                        case 'AIN':\n                            value = pd.AIN;\n                            break;\n                        default:\n                            break;\n                    }\n                    return value;\n                },\n            },\n            pingpong_g1_is_top_shape: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_dir6,\n                        value: 'DF_RECTANGLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g1_is_top_shape' },\n                paramsKeyMap: {\n                    TILT_DIR: 0,\n                },\n                class: 'PingpongG1',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    const tiltDir = script.getStringField('TILT_DIR', script);\n                    const pd = Entry.hw.portData;\n                    if (tiltDir == 'DF_RECTANGLE' && pd.TILT_Y > 70) return true;\n                    if (tiltDir == 'DB_STAR' && pd.TILT_Y < -70) return true;\n                    if (tiltDir == 'DR_CIRCLE' && pd.TILT_X > 70) return true;\n                    if (tiltDir == 'DL_TRIANGLE' && pd.TILT_X < -70) return true;\n                    if (tiltDir == 'DD_NONE' && pd.TILT_Z > 70) return true;\n                    if (tiltDir == 'DU_HEART' && pd.TILT_Z < -70) return true;\n                    return false;\n                },\n            },\n            pingpong_g1_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                //statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n                ],\n                //events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                    ],\n                    type: 'pingpong_g1_motor_rotate',\n                },\n                paramsKeyMap: { DIR: 0, DEGREE: 1 },\n                class: 'PingpongG1_motor',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        const dir = script.getStringField('DIR');\n                        let degree = script.getNumberValue('DEGREE');\n\n                        let speed = 800;\n                        if (dir == 'LEFT') {\n                            speed *= -1;\n                        }\n\n                        degree = Math.min(Math.max(degree, 0), 5000);\n\n                        let step = Math.round(degree * 5.5);\n                        if (step > 32768) {\n                            step = 32768;\n                        }\n\n                        const opt = [2, 1, 0, 2, 0, 0, 0, 0, 0, 0];\n                        const packet = Entry.PingpongG1.makePacket(0xc1, 0x0004, opt); // SETP_MOTOR\n\n                        packet.writeInt16BE(speed, 13);\n                        packet.writeUInt16BE(step, 17);\n\n                        const waitTime = Math.round(((1100 - Math.abs(speed)) / 99) * step) + 400;\n                        return [packet, waitTime];\n                    });\n                },\n            },\n\n            pingpong_g1_start_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                    ],\n                    type: 'pingpong_g1_start_motor_rotate',\n                },\n                paramsKeyMap: { SPEED: 0 },\n                class: 'PingpongG1_motor',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        let speed = script.getNumberValue('SPEED');\n                        if (speed > 100) {\n                            speed = 100;\n                        }\n                        if (speed < -100) {\n                            speed = -100;\n                        }\n\n                        let sps = 0;\n                        if (speed != 0) {\n                            if (speed < 0) {\n                                sps = 65536 + (speed * 9 - 100);\n                            } else {\n                                sps = speed * 9 + 100;\n                            }\n                            sps = Math.round(sps);\n                        }\n\n                        const opt = [2, 0, 0, 2, sps / 256, sps % 256];\n                        const packet = Entry.PingpongG1.makePacket(0xcc, 0x0004, opt);\n                        //packet.writeInt16BE(sps, 13);\n\n                        const waitTime = Math.round(((1100 - Math.abs(sps)) / 99) * 10) + 400;\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g1_stop_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g1_stop_motor_rotate',\n                },\n                paramsKeyMap: {},\n                class: 'PingpongG1_motor',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        const opt = [2, 0, 0, 1, 0, 0];\n                        const packet = Entry.PingpongG1.makePacket(0xcc, 0x0004, opt);\n                        return [packet];\n                    });\n                },\n            },\n\n            pingpong_g1_rotate_servo_mortor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                //statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                //events: {},\n                def: { params: [{ type: 'angle' }], type: 'pingpong_g1_rotate_servo_mortor' },\n                paramsKeyMap: { DEGREE: 0 },\n                class: 'PingpongG1_motor',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        let angle = script.getNumberValue('DEGREE', script);\n\n                        angle = Math.min(Math.max(angle, 0), 180);\n\n                        const packet = Entry.PingpongG1.makePacket(0xe1, 0x00, [2, 0, angle, 1]);\n                        return [packet, 400];\n                    });\n                },\n            },\n\n            pingpong_g1_set_dot_pixel: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                //statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '0' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '0' },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_dot_on, 1],\n                            [Lang.Blocks.pingpong_dot_off, 0],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                //events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'pingpong_g1_set_dot_pixel',\n                },\n                paramsKeyMap: { X: 0, Y: 1, onoff: 2 },\n                class: 'PingpongG1_peripheral_LED',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        let dotX = script.getNumberValue('X', script);\n                        let dotY = script.getNumberValue('Y', script);\n                        const onoff = script.getNumberField('onoff', script);\n\n                        dotX = Math.min(Math.max(dotX, 0), 7);\n                        dotY = Math.min(Math.max(dotY, 0), 7);\n\n                        const packet = Entry.PingpongG1.makePacket(0xa2, 0xe1, [\n                            0x70,\n                            dotY,\n                            dotX,\n                            onoff,\n                        ]); // turn on\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g1_set_dot_string: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                //statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', value: 'Hello!' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '2' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                //events: {},\n                def: { params: [null, null], type: 'pingpong_g1_set_dot_string' },\n                paramsKeyMap: { STR: 0, DURATION: 1 },\n                class: 'PingpongG1_peripheral_LED',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        const str = script.getStringValue('STR', script);\n                        const duration = script.getNumberValue('DURATION', script);\n\n                        let period = Math.round((duration * 100) / (str.length * 8));\n                        period = Math.min(Math.max(period, 1), 200);\n\n                        const opt = Buffer.concat([\n                            Buffer.from([0x70, period, 0]),\n                            Buffer.from(str.substring(0, 20)),\n                        ]);\n\n                        const packet = Entry.PingpongG1.makePacket(0xa2, 0xe3, opt);\n                        const waitTime = period * str.length * 8 * 10 + 400; // add wait for 400ms\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g1_set_dot_clear: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                //statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                //events: {},\n                def: { params: [], type: 'pingpong_g1_set_dot_clear' },\n                paramsKeyMap: {},\n                class: 'PingpongG1_peripheral_LED',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        const packet = Entry.PingpongG1.makePacket(0xa2, 0xe3, [0x70, 1, 0, ' ']);\n                        return [packet, 400];\n                    });\n                },\n            },\n            pingpong_g1_playNoteForBeats: {\n                //'%1 번 음을 %2 박자로 연주하기 %3',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g1_playNoteForBeats' },\n                paramsKeyMap: { NOTE: 0, BEATS: 1 },\n                class: 'PingpongG1_Music',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        const NOTE = script.getNumberField('NOTE', script);\n                        const BEATS = script.getNumberValue('BEATS', script);\n\n                        const cBeats = Entry.PingpongG1._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG1._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30; //XXX\n                        const opt = [0, 0x00 /*PLAY*/, NOTE - 8, durationSec, 0]; //type 1??\n                        //const opt = [0, 0x00/*PLAY*/, note-8, 0, durationSec];\t//type 2\n                        const packet = Entry.PingpongG1.makePacket(0xe8, 0xa1, opt);\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g1_restForBeats: {\n                //'%1 박자 쉬기 %2',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g1_restForBeats' },\n                paramsKeyMap: { BEATS: 0 },\n                class: 'PingpongG1_Music',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        const BEATS = script.getNumberValue('BEATS', script);\n\n                        const cBeats = Entry.PingpongG1._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG1._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30;\n\n                        return [null, waitTime];\n                    });\n                },\n            },\n            pingpong_g1_setTempo: {\n                //'악보 빠르기를 %1 으로 정하기 %2',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '60' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g1_setTempo' },\n                paramsKeyMap: { TEMPO: 0 },\n                class: 'PingpongG1_Music',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    let tempo = script.getNumberValue('TEMPO', script);\n                    Entry.PingpongG1.tempo = Entry.PingpongG1._clampTempo(tempo);\n                    //console.log('SET TEMPO = ', tempo, Entry.PingpongG1.tempo);\n                    return script.callReturn();\n                },\n            },\n            pingpong_g1_getTempo: {\n                //'악보 빠르기',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [],\n                def: { params: [], type: 'pingpong_g1_getTempo' },\n                paramsKeyMap: {},\n                class: 'PingpongG1_Music',\n                isNotFor: ['PingpongG1','PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.tempo;\n                },\n            },\n\n            set_steering_direction: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_mono,\n                        value: 90,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12, },\n                ],\n                events: {},\n                def: { params: [], type: 'set_steering_direction' },\n                paramsKeyMap: { DEGREE: 0,},\n                class: 'PingpongG1_motor',\n                isNotFor: ['PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        let angle = script.getNumberValue('DEGREE', script);\n\n                        angle = Math.min(Math.max(angle, 0), 180);\n\n                        const packet = Entry.PingpongG1.makePacket(0xe1, 0x00, [2, 0, angle, 1]);\n                        return [packet, 400];\n                    });\n                },\n            },\n\n            move_by_distance: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_direction,\n                        value: Lang.Blocks.pingpong_direction[0][1],\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12, },\n                ],\n                events: {},\n                def: { params: [], type: 'move_by_distance' },\n                paramsKeyMap: { DIR: 0, CM: 1 },\n                class: 'PingpongG1_motor',\n                isNotFor: ['PingpongPracticalArts'],\n                func(sprite, script) {\n                    return Entry.PingpongG1.postCallReturn(script, () => {\n                        const direction = script.getStringField('DIR');\n                        let degree = script.getNumberValue('CM');\n                        degree = degree*9; // convert cm to degree\n\n                        let speed = 800;\n                        if (direction == 'back') {\n                            speed *= -1;\n                        }\n\n                        degree = Math.min(Math.max(degree, 0), 5000);\n\n                        let step = Math.round(degree * 5.5);\n                        if (step > 32768) {\n                            step = 32768;\n                        }\n\n                        const opt = [2, 1, 0, 2, 0, 0, 0, 0, 0, 0];\n                        const packet = Entry.PingpongG1.makePacket(0xc1, 0x0004, opt); // SETP_MOTOR\n\n                        packet.writeInt16BE(speed, 13);\n                        packet.writeUInt16BE(step, 17);\n\n                        const waitTime = Math.round(((1100 - Math.abs(speed)) / 99) * step) + 400;\n                        return [packet, waitTime];\n                    });\n                },\n            },\n        };\n    }\n\n    setLanguage() {\n        return {\n            ko: {\n                template: {\n                    pingpong_g1_when_button_pressed: '%1 큐브 버튼을 눌렀을 때',\n                    pingpong_g1_when_tilted: '%1 큐브를 %2 방향으로 기울였을 때',\n                    pingpong_g1_is_button_pressed: '큐브 버튼이 눌렸는가?',\n                    pingpong_g1_is_tilted: '큐브가 %1 방향으로 기울어졌는가?',\n                    pingpong_g1_get_tilt_value: '%1 방향 큐브 기울기',\n                    pingpong_g1_get_sensor_value: '%1 센서값',\n                    pingpong_g1_motor_rotate: '모터를 %1 방향으로 %2 도 회전하기 %3',\n                    pingpong_g1_start_motor_rotate: '모터의 속도를 %1으로 계속 회전하기 %2',\n                    pingpong_g1_stop_motor_rotate: '모터 멈추기 %1',\n                    pingpong_g1_rotate_servo_mortor: '서보모터를 %1도로 설정하기 %2',\n                    pingpong_g1_is_top_shape: '큐브 윗면에 %1 모양이 있는가?',\n                    pingpong_g1_set_dot_pixel: '도트 X:%1 Y:%2 %3 %4',\n                    pingpong_g1_set_dot_string: '도트에 문자열 %1  %2초동안 출력 %3',\n                    pingpong_g1_set_dot_clear: '도트 화면 지우기 %1',\n                    pingpong_g1_playNoteForBeats: '%1 음을 %2 박자로 연주하기 %3',\n                    pingpong_g1_restForBeats: '%1 박자 쉬기 %2',\n                    pingpong_g1_setTempo: '악보 빠르기를 %1 으로 정하기 %2',\n                    pingpong_g1_getTempo: '악보 빠르기',\n                    set_steering_direction: '조향 바퀴를 %1 방향으로 설정',\n                    move_by_distance: '%1으로%2cm 이동하기',\n                },\n                Blocks: {\n                    pingpong_right: '오른쪽',\n                    pingpong_left: '왼쪽',\n\n                    pingpong_direction :[\n                        ['앞쪽','front'],\n                        ['뒤쪽','back']\n                    ],\n\n                    pingpong_rotate_cw: '시계',\n                    pingpong_rotate_ccw: '반시계',\n\n                    pingpong_sensor_proximity: '근접',\n                    pingpong_sensor_ain: '아날로그',\n                    pingpong_dot_on: '켜기',\n                    pingpong_dot_off: '끄기',\n\n                    pingpong_opts_cube_tiltDir: [\n                        ['동그라미', 'F_CIRCLE'],\n                        ['세모', 'B_TRIANGLE'],\n                        ['네모', 'L_RECTANGLE'],\n                        ['별', 'R_STAR'],\n                    ],\n\n                    pingpong_opts_cube_dir6: [\n                        ['네모', 'DF_RECTANGLE'],\n                        ['별', 'DB_STAR'],\n                        ['세모', 'DL_TRIANGLE'],\n                        ['동그라미', 'DR_CIRCLE'],\n                        ['하트', 'DU_HEART'],\n                        ['빈칸', 'DD_NONE'],\n                    ],\n\n                    pingpong_opts_music_notes: [\n                        ['라  (A3)', 45],\n                        ['라# (A3#)', 46],\n                        ['시  (B3)', 47],\n                        ['도  (C4)', 48],\n                        ['도# (C4#)', 49],\n                        ['레  (D4)', 50],\n                        ['레# (D4#)', 51],\n                        ['미  (E4)', 52],\n                        ['파  (F4)', 53],\n                        ['파# (F4#)', 54],\n                        ['솔  (G4)', 55],\n                        ['솔# (G4#)', 56],\n                        ['라  (A4)', 57],\n                        ['라# (A4#)', 58],\n                        ['시  (B4)', 59],\n                        ['도  (C5)', 60],\n                        ['도# (C5#)', 61],\n                        ['레  (D5)', 62],\n                        ['레# (D5#)', 63],\n                        ['미  (E5)', 64],\n                        ['파  (F5)', 65],\n                        ['파# (F5#)', 66],\n                        ['솔  (G5)', 67],\n                        ['솔# (G5#)', 68],\n                        ['라  (A5)', 69],\n                        ['라# (A5#)', 70],\n                        ['시  (B5)', 71],\n                        ['도  (C6)', 72],\n                    ],\n\n                    pingpong_opts_mono :[\n                        ['왼쪽 45°'   ,45],\n                        ['왼쪽 40°'   ,50],\n                        ['왼쪽 35°'   ,55],\n                        ['왼쪽 30°'   ,60],\n                        ['왼쪽 25°'   ,65],\n                        ['왼쪽 20°'   ,70],\n                        ['왼쪽 15°'   ,75],\n                        ['왼쪽 10°'   ,80],\n                        ['왼쪽 5°'    ,85],\n                        ['정면'     ,90],\n                        ['오른쪽 5°'  ,95],\n                        ['오른쪽 10°' ,100],\n                        ['오른쪽 15°' ,105],\n                        ['오른쪽 20°' ,110],\n                        ['오른쪽 25°' ,115],\n                        ['오른쪽 30°' ,120],\n                        ['오른쪽 35°' ,125],\n                        ['오른쪽 40°' ,130],\n                        ['오른쪽 45°' ,135],\n                    ]\n                },\n            },\n            en: {\n                template: {\n                    pingpong_g1_when_button_pressed: '%1 Button pressed',\n                    pingpong_g1_when_tilted: '%1 Tilted to %2',\n                    pingpong_g1_is_button_pressed: 'button pressed?',\n                    pingpong_g1_is_tilted: 'cube tilted to %1',\n                    pingpong_g1_get_tilt_value: 'tilt angle to %1',\n                    pingpong_g1_get_sensor_value: 'read sensor %1',\n                    pingpong_g1_motor_rotate: 'rotate %2 degrees %1 %3',\n                    pingpong_g1_start_motor_rotate: 'set motor speed to %1 %2',\n                    pingpong_g1_stop_motor_rotate: 'stop motor rotate %1',\n                    pingpong_g1_rotate_servo_mortor: 'set servo mortor to %1 degrees %2',\n                    pingpong_g1_is_top_shape: '%1 shown in top view?',\n                    pingpong_g1_set_dot_pixel: 'set %3 DOT X:%1 Y:%2 %4',\n                    pingpong_g1_set_dot_string: 'print string %1 during %2 seconds to DOT %3',\n                    pingpong_g1_set_dot_clear: 'clear DOT %1',\n                    pingpong_g1_playNoteForBeats: 'play note %1 for %2 beats %3',\n                    pingpong_g1_restForBeats: 'rest for %1 beats %2',\n                    pingpong_g1_setTempo: 'set tempo to %1 %2',\n                    pingpong_g1_getTempo: 'tempo',\n                    set_steering_direction: 'Set the steering wheel to %1 direction',\n                    move_by_distance: 'Move %1 by %2 cm',\n                },\n                Blocks: {\n                    pingpong_right: 'right',\n                    pingpong_left: 'left',\n\n                    pingpong_direction :[\n                        ['Front','front'],\n                        ['Back','back']\n                    ],\n\n                    pingpong_rotate_cw: 'clockwise',\n                    pingpong_rotate_ccw: 'counter clockwise',\n\n                    pingpong_sensor_proximity: 'proximity',\n                    pingpong_sensor_ain: 'ain',\n                    pingpong_dot_on: 'ON',\n                    pingpong_dot_off: 'OFF',\n\n                    pingpong_opts_cube_tiltDir: [\n                        ['circle', 'F_CIRCLE'],\n                        ['triangle', 'B_TRIANGLE'],\n                        ['rectangle', 'L_RECTANGLE'],\n                        ['star', 'R_STAR'],\n                    ],\n\n                    pingpong_opts_cube_dir6: [\n                        ['rectangle', 'DF_RECTANGLE'],\n                        ['star', 'DB_STAR'],\n                        ['triangle', 'DL_TRIANGLE'],\n                        ['circle', 'DR_CIRCLE'],\n                        ['heart', 'DU_HEART'],\n                        ['none', 'DD_NONE'],\n                    ],\n                    pingpong_opts_music_notes: [\n                        ['La  (A3)', 45],\n                        ['La# (A3#)', 46],\n                        ['Ti  (B3)', 47],\n                        ['Do  (C4)', 48],\n                        ['Do# (C4#)', 49],\n                        ['Re  (D4)', 50],\n                        ['Re# (D4#)', 51],\n                        ['Mi  (E4)', 52],\n                        ['Fa  (F4)', 53],\n                        ['Fa# (F4#)', 54],\n                        ['Sol (G4)', 55],\n                        ['Sol#(G4#)', 56],\n                        ['La  (A4)', 57],\n                        ['La# (A4#)', 58],\n                        ['Ti  (B4)', 59],\n                        ['Do  (C5)', 60],\n                        ['Do# (C5#)', 61],\n                        ['Re  (D5)', 62],\n                        ['Re# (D5#)', 63],\n                        ['Mi  (E5)', 64],\n                        ['Fa  (F5)', 65],\n                        ['Fa# (F5#)', 66],\n                        ['Sol (G5)', 67],\n                        ['Sol#(G5#)', 68],\n                        ['La  (A5)', 69],\n                        ['La# (A5#)', 70],\n                        ['Ti  (B5)', 71],\n                        ['Do  (C6)', 72],\n                    ],\n\n                    pingpong_opts_mono: [\n                        ['Left 45°', 45],\n                        ['Left 40°', 50],\n                        ['Left 35°', 55],\n                        ['Left 30°', 60],\n                        ['Left 25°', 65],\n                        ['Left 20°', 70],\n                        ['Left 15°', 75],\n                        ['Left 10°', 80],\n                        ['Left 5°', 85],\n                        ['Center', 90],\n                        ['Right 5°', 95],\n                        ['Right 10°', 100],\n                        ['Right 15°', 105],\n                        ['Right 20°', 110],\n                        ['Right 25°', 115],\n                        ['Right 30°', 120],\n                        ['Right 35°', 125],\n                        ['Right 40°', 130],\n                        ['Right 45°', 135],\n                    ]\n                },\n            },\n        };\n    }\n\n    monitorTemplate = {\n        imgPath: 'hw/pingpong_g1.png',\n        width: 400,\n        height: 400,\n        listPorts: {\n            BUTTON: {\n                name: 'button',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            MOVE_X: {\n                name: 'move_x',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            MOVE_Y: {\n                name: 'move_y',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            MOVE_Z: {\n                name: 'move_z',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            TILT_X: {\n                name: 'tilt_x',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            TILT_Y: {\n                name: 'tilt_y',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            TILT_Z: {\n                name: 'tilt_z',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            PROXIMITY: {\n                name: 'proximity',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            AIN: {\n                name: 'ain',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {},\n        mode: 'both',\n    };\n})();\n\nEntry.PingpongPracticalArts = new (class PingpongPracticalArts {\n    constructor() {\n        this.id = '35.5';\n        this.name = 'PingpongPracticalArts';\n        this.url = 'https://www.roborisen.com';\n        this.imageName = 'pingpong_g1.png';\n        this.delayTime = 50;\n        this.title = {\n            ko: '핑퐁(실과수업용)',\n            en: 'Pingpong (for Practical Arts class)',\n        };\n        this.communicationType = 'manual';\n\n        this.blockMenuBlocks = [\n            'pingpong_g1_when_button_pressed',\n            'pingpong_g1_is_button_pressed',\n            'pingpong_g1_when_tilted',\n            'pingpong_g1_is_tilted',\n            'pingpong_g1_get_tilt_value',\n            'pingpong_g1_is_top_shape',\n            'pingpong_g1_get_sensor_value',\n            'pingpong_g1_motor_rotate',\n            'pingpong_g1_start_motor_rotate',\n            'pingpong_g1_stop_motor_rotate',\n            'pingpong_g1_rotate_servo_mortor',\n            'set_steering_direction',\n            'move_by_distance',\n            'pingpong_g1_set_dot_pixel',\n            'pingpong_g1_set_dot_string',\n            'pingpong_g1_set_dot_clear',\n            'pingpong_g1_playNoteForBeats',\n            'pingpong_g1_restForBeats',\n            'pingpong_g1_setTempo',\n            'pingpong_g1_getTempo',\n        ];\n    }\n\n    setZero() {return Entry.PingpongG1.setZero();}\n    sendCommand(packet) {return Entry.PingpongG1.sendCommand(packet);}\n    afterReceive(pd) {return Entry.PingpongG1.afterReceive(pd);}\n    postCallReturn(script, myfunc) {return Entry.PingpongG1.postCallReturn(script, myfunc);}\n    _clampBeats(beats) {return Entry.PingpongG1._clampBeats(beats);}\n    _clampTempo(tempo) {return Entry.PingpongG1._clampTempo(tempo);}\n    _beatsToDuration(beats) {return Entry.PingpongG1._beatsToDuration(beats);}\n    makePacket(opcode, taskid, opt) {return Entry.PingpongG1.makePacket(opcode, taskid, opt);}\n    getBlocks() {return Entry.PingpongG1.getBlocks()}\n    setLanguage() {return Entry.PingpongG1.setLanguage();}\n\n})();\nmodule.exports = [Entry.PingpongG1, Entry.PingpongPracticalArts];\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_pingpong_multi.js",
    "content": "'use strict';\n\nconst Buffer = require('buffer').Buffer;\n\nconst OPCODE = {\n    SINGLE_STEPS: 0xc1,\n    SCHEDULED_STEPS: 0xca,\n    SCHEDULED_POINTS: 0xcb,\n    CONTINUOUS_STEPS: 0xcc,\n    AGGREGATE_STEPS: 0xcd,\n    LEDMATRIX: 0xa2,\n    SERVO: 0xe1,\n    MUSIC: 0xe8,\n};\n\nconst METHOD = {\n    CONTINOUS: 0,\n    RELATIVE_SINGLE: 1,\n    ABSOLUTE_SINGLE: 2,\n    SCHED_STEPS: 3,\n    sCHED_POINT: 4,\n};\n\nconst MODE = {\n    MULTIROLE: 2,\n    CHECKCRC: 3,\n};\n\nconst PROPERTY = {\n    PERI: 0x01,\n    MULTI: 0x02,\n    PORT: 0x80,\n    ADDRESS: 0x70,\n    PAUSE: 1,\n    RESUME: 2,\n    MUSIC_PLAY: 0,\n};\n\nconst DEFAULT_TEMPO = 60;\n\nclass PingpongBase {\n    constructor(cubecnt) {\n        this.TILT_THRESHOLD = 20;\n        this.MOVE_THRESHOLD = 30;\n\n        this.delayTime = 100;\n        this.send_cmd_id = 0;\n        this.cubeCnt = cubecnt || 2;\n\n        this.tempo = DEFAULT_TEMPO;\n\n        this.communicationType = 'manual';\n\n        this.prev_sensor_data = {\n            c0_TILT_X: false,\n            c0_TILT_Y: false,\n            c0_BUTTON: 0,\n            c1_TILT_X: false,\n            c1_TILT_Y: false,\n            c1_BUTTON: 0,\n            c2_TILT_X: false,\n            c2_TILT_Y: false,\n            c2_BUTTON: 0,\n            c3_TILT_X: false,\n            c3_TILT_Y: false,\n            c3_BUTTON: 0,\n        };\n\n        this.lang_defblock = {\n            ko: {\n                pingpong_right: '오른쪽',\n                pingpong_left: '왼쪽',\n\n                pingpong_rotate_cw: '시계',\n                pingpong_rotate_ccw: '반시계',\n\n                pingpong_sensor_proximity: '근접',\n                pingpong_sensor_ain: '아날로그',\n                pingpong_dot_on: '켜기',\n                pingpong_dot_off: '끄기',\n\n                pingpong_opts_cube_tiltDir: [\n                    ['동그라미', 'F_CIRCLE'],\n                    ['세모', 'B_TRIANGLE'],\n                    ['네모', 'L_RECTANGLE'],\n                    ['별', 'R_STAR'],\n                ],\n                pingpong_opts_cube_dir6: [\n                    ['네모', 'DF_RECTANGLE'],\n                    ['별', 'DB_STAR'],\n                    ['세모', 'DL_TRIANGLE'],\n                    ['동그라미', 'DR_CIRCLE'],\n                    ['하트', 'DU_HEART'],\n                    ['빈칸', 'DD_NONE'],\n                ],\n                pingpong_opts_music_notes: [\n                    ['라  (A3)', 45],\n                    ['라# (A3#)', 46],\n                    ['시  (B3)', 47],\n                    ['도  (C4)', 48],\n                    ['도# (C4#)', 49],\n                    ['레  (D4)', 50],\n                    ['레# (D4#)', 51],\n                    ['미  (E4)', 52],\n                    ['파  (F4)', 53],\n                    ['파# (F4#)', 54],\n                    ['솔  (G4)', 55],\n                    ['솔# (G4#)', 56],\n                    ['라  (A4)', 57],\n                    ['라# (A4#)', 58],\n                    ['시  (B4)', 59],\n                    ['도  (C5)', 60],\n                    ['도# (C5#)', 61],\n                    ['레  (D5)', 62],\n                    ['레# (D5#)', 63],\n                    ['미  (E5)', 64],\n                    ['파  (F5)', 65],\n                    ['파# (F5#)', 66],\n                    ['솔  (G5)', 67],\n                    ['솔# (G5#)', 68],\n                    ['라  (A5)', 69],\n                    ['라# (A5#)', 70],\n                    ['시  (B5)', 71],\n                    ['도  (C6)', 72],\n                ],\n            },\n            en: {\n                pingpong_right: 'right',\n                pingpong_left: 'left',\n\n                pingpong_rotate_cw: 'clockwise',\n                pingpong_rotate_ccw: 'counter clockwise',\n\n                pingpong_sensor_proximity: 'proximity',\n                pingpong_sensor_ain: 'ain',\n                pingpong_dot_on: 'ON',\n                pingpong_dot_off: 'OFF',\n\n                pingpong_opts_cube_tiltDir: [\n                    ['circle', 'F_CIRCLE'],\n                    ['triangle', 'B_TRIANGLE'],\n                    ['rectangle', 'L_RECTANGLE'],\n                    ['star', 'R_STAR'],\n                ],\n                pingpong_opts_cube_dir6: [\n                    ['rectangle', 'DF_RECTANGLE'],\n                    ['star', 'B_STAR'],\n                    ['triangle', 'L_TRIANGLE'],\n                    ['circle', 'R_CIRCLE'],\n                    ['heart', 'U_HEART'],\n                    ['none', 'D_NONE'],\n                ],\n                pingpong_opts_music_notes: [\n                    ['La  (A3)', 45],\n                    ['La# (A3#)', 46],\n                    ['Ti  (B3)', 47],\n                    ['Do  (C4)', 48],\n                    ['Do# (C4#)', 49],\n                    ['Re  (D4)', 50],\n                    ['Re# (D4#)', 51],\n                    ['Mi  (E4)', 52],\n                    ['Fa  (F4)', 53],\n                    ['Fa# (F4#)', 54],\n                    ['Sol (G4)', 55],\n                    ['Sol#(G4#)', 56],\n                    ['La  (A4)', 57],\n                    ['La# (A4#)', 58],\n                    ['Ti  (B4)', 59],\n                    ['Do  (C5)', 60],\n                    ['Do# (C5#)', 61],\n                    ['Re  (D5)', 62],\n                    ['Re# (D5#)', 63],\n                    ['Mi  (E5)', 64],\n                    ['Fa  (F5)', 65],\n                    ['Fa# (F5#)', 66],\n                    ['Sol (G5)', 67],\n                    ['Sol#(G5#)', 68],\n                    ['La  (A5)', 69],\n                    ['La# (A5#)', 70],\n                    ['Ti  (B5)', 71],\n                    ['Do  (C6)', 72],\n                ],\n            },\n        };\n    }\n\n    setZero() {\n        this.tempo = DEFAULT_TEMPO;\n\n        this.sendCommand(this.makePacket(OPCODE.LEDMATRIX, 0xe3, -1, [0x70, 1, 0, ' ']));\n        setTimeout(() => {\n            this.sendCommand(this.makePacket(OPCODE.CONTINUOUS_STEPS, 0, -1, [2, 0, 0, 1, 0, 0]));\n            setTimeout(() => {\n                Entry.hw.sendQueue.COMMAND = {\n                    id: -1,\n                };\n                Entry.hw.update();\n\n                this.send_cmd_id = 0;\n            }, this.delayTime);\n        }, this.delayTime);\n    }\n\n    sendCommand(packet) {\n        Entry.hw.sendQueue.COMMAND = {\n            id: ++this.send_cmd_id,\n            data: packet,\n        };\n        Entry.hw.update();\n    }\n\n    afterReceive(pd) {\n        if (!Entry.engine.isState('run')) {\n            return;\n        }\n\n        if (\n            this.prev_sensor_data.c0_BUTTON != pd.c0_BUTTON ||\n            this.prev_sensor_data.c1_BUTTON != pd.c1_BUTTON ||\n            this.prev_sensor_data.c2_BUTTON != pd.c2_BUTTON ||\n            this.prev_sensor_data.c3_BUTTON != pd.c3_BUTTON\n        ) {\n            Entry.engine.fireEvent('pp_when_button_pressed');\n\n            this.prev_sensor_data.c0_BUTTON = pd.c0_BUTTON;\n            this.prev_sensor_data.c1_BUTTON = pd.c1_BUTTON;\n            this.prev_sensor_data.c2_BUTTON = pd.c2_BUTTON;\n            this.prev_sensor_data.c3_BUTTON = pd.c3_BUTTON;\n        }\n\n        const tiltXc0 = Math.abs(pd.c0_TILT_X) >= this.TILT_THRESHOLD;\n        const tiltYc0 = Math.abs(pd.c0_TILT_Y) >= this.TILT_THRESHOLD;\n        const tiltXc1 = Math.abs(pd.c1_TILT_X) >= this.TILT_THRESHOLD;\n        const tiltYc1 = Math.abs(pd.c1_TILT_Y) >= this.TILT_THRESHOLD;\n        const tiltXc2 = Math.abs(pd.c2_TILT_X) >= this.TILT_THRESHOLD;\n        const tiltYc2 = Math.abs(pd.c2_TILT_Y) >= this.TILT_THRESHOLD;\n        const tiltXc3 = Math.abs(pd.c3_TILT_X) >= this.TILT_THRESHOLD;\n        const tiltYc3 = Math.abs(pd.c3_TILT_Y) >= this.TILT_THRESHOLD;\n\n        if (\n            tiltXc0 != this.prev_sensor_data.c0_TILT_X ||\n            tiltYc0 != this.prev_sensor_data.c0_TILT_Y ||\n            tiltXc1 != this.prev_sensor_data.c1_TILT_X ||\n            tiltYc1 != this.prev_sensor_data.c1_TILT_Y ||\n            tiltXc2 != this.prev_sensor_data.c2_TILT_X ||\n            tiltYc2 != this.prev_sensor_data.c2_TILT_Y ||\n            tiltXc3 != this.prev_sensor_data.c3_TILT_X ||\n            tiltYc3 != this.prev_sensor_data.c3_TILT_Y\n        ) {\n            Entry.engine.fireEvent('pp_when_tilted');\n        }\n        this.prev_sensor_data.c0_TILT_X = tiltXc0;\n        this.prev_sensor_data.c0_TILT_Y = tiltYc0;\n        this.prev_sensor_data.c1_TILT_X = tiltXc1;\n        this.prev_sensor_data.c1_TILT_Y = tiltYc1;\n        this.prev_sensor_data.c2_TILT_X = tiltXc2;\n        this.prev_sensor_data.c2_TILT_Y = tiltYc2;\n        this.prev_sensor_data.c3_TILT_X = tiltXc3;\n        this.prev_sensor_data.c3_TILT_Y = tiltYc3;\n    }\n\n    postCallReturn(script, myfunc) {\n        if (myfunc == undefined) {\n            return script.callReturn();\n        }\n\n        if (script.is_start == undefined) {\n            script.is_start = true;\n\n            const [packet, waitTime = this.delayTime] = myfunc();\n\n            if (packet && packet.length > 0) {\n                this.sendCommand(packet);\n            }\n\n            setTimeout(() => {\n                script.is_start = false;\n            }, waitTime);\n            return script;\n        } else if (script.is_start == true) {\n            return script;\n        } else {\n            delete script.is_start;\n\n            //Entry.engine.isContinue = false;\n            return script.callReturn();\n        }\n    }\n\n    makePacket(opcode, taskid, cubeNo, opt) {\n        // make heder   ( cubeid, cubecnt, op, size, method\n        const header = Buffer.from([0xff, 0xff, 0xff, 0xff, 0, 0, opcode, 0, 0]);\n        const property = Buffer.from(opt);\n\n        //header.writeUInt16BE(0xFFFF, 0);\n        //header.writeUInt16BE(0xFFFF, 2);\t// cubdid\n\n        if (cubeNo <= -1) {\n            header[3] = 0xff;\n        } else {\n            header[3] = cubeNo;\n        }\n\n        header.writeUInt16BE(taskid, 4);\n        header.writeUInt16BE(header.length + property.length, 7);\n\n        return Buffer.concat([header, property]);\n    }\n\n    _fillPacketIntoArray(data, opcode, taskid, cubeNo, size) {\n        data[0] = 0xff;\n        data[1] = 0xff;\n        data[2] = 0xff;\n\n        if (cubeNo <= -1) {\n            data[3] = 0xff;\n        } else {\n            data[3] = cubeNo;\n        }\n\n        data[4] = taskid / 256;\n        data[5] = taskid % 256;\n\n        data[6] = opcode;\n\n        data[7] = size / 256;\n        data[8] = size % 256;\n    }\n\n    makeSingleStepPacket(cubeNo, speed, degree) {\n        const packet = new Uint8Array(9 + 10);\n\n        this._fillPacketIntoArray(packet, OPCODE.SINGLE_STEPS, 0 /*cubeCnt*/, cubeNo, 19);\n\n        const sps = this._calcSpsFromSpeed(speed);\n        let step = Math.round(Math.min(Math.max(degree, 0), 5000) * 5.5);\n        if (step > 32768) {\n            step = 32768;\n        }\n\n        packet[9] = MODE.MULTIROLE;\n        packet[10] = METHOD.RELATIVE_SINGLE;\n        packet[11] = 0; //step_type; full=0, servo=4\n        packet[12] = PROPERTY.RESUME;\n\n        packet[13] = sps / 256;\n        packet[14] = sps % 256;\n        packet[15] = 0;\n        packet[16] = 0;\n        packet[17] = step / 256;\n        packet[18] = step % 256;\n\n        const waitTime = Math.round(((1000 - Math.abs(speed) * 9) / 99) * step) + 400;\n\n        return [packet, waitTime];\n    }\n\n    makeContStepPacket(cubeNo, speed) {\n        const packet = new Uint8Array(9 + 6);\n\n        this._fillPacketIntoArray(packet, OPCODE.CONTINUOUS_STEPS, 0, cubeNo, 15);\n\n        const sps = this._calcSpsFromSpeed(speed);\n\n        packet[9] = MODE.MULTIROLE;\n        packet[10] = METHOD.CONTINOUS;\n        packet[11] = 0; //step_type; full=0, servo=4\n\n        if (sps == 0) {\n            packet[12] = PROPERTY.PAUSE;\n            packet[13] = 0;\n            packet[14] = 0;\n        } else {\n            packet[12] = PROPERTY.RESUME;\n            packet[13] = sps / 256;\n            packet[14] = sps % 256;\n        }\n\n        return packet;\n    }\n\n    makeMusicNotePacket(cubeNo, note, duration) {\n        const packet = new Uint8Array(9 + 5);\n        this._fillPacketIntoArray(packet, OPCODE.MUSIC, 0xa1, cubeNo, 9 + 5);\n\n        packet[9] = 0;\n        packet[10] = PROPERTY.MUSIC_PLAY;\n        packet[11] = note - 8;\n        // type == 1\n        packet[12] = duration;\n        packet[13] = 0;\n\n        return packet;\n    }\n\n    makeAggregatePacket(opcode, taskid, packets, opt = []) {\n        let size = 9 + opt.length;\n        let options = opt;\n        let usedCubeIds = [];\n\n        packets.forEach((n) => {\n            size += n.length;\n            Array.prototype.push.apply(options, n);\n            usedCubeIds.push(n[3]);\n        });\n\n        // aggregate command must have cubeCount commands. add dummy packet\n        if (packets.length < this.cubeCnt) {\n            for (let i = 0; i < this.cubeCnt; i++) {\n                if (usedCubeIds.includes(i) == false) {\n                    let dummyPacket = packets[0].slice();\n                    dummyPacket[3] = i;\n                    dummyPacket[6] = 0; // set opcode to zero\n                    Array.prototype.push.apply(options, dummyPacket);\n                }\n            }\n        }\n\n        const cmd = this.makePacket(opcode, (packets.length << 12) | taskid, 0xaa, options);\n        return cmd;\n    }\n\n    _getTiltValue(cubeNo, tiltDir) {\n        const pd = Entry.hw.portData;\n        let tiltValue = 0;\n\n        if (cubeNo == 0) {\n            if (tiltDir == 'F_CIRCLE') {\n                tiltValue = pd.c0_TILT_X * -1;\n            } else if (tiltDir == 'B_TRIANGLE') {\n                tiltValue = pd.c0_TILT_X;\n            } else if (tiltDir == 'L_RECTANGLE') {\n                tiltValue = pd.c0_TILT_Y * -1;\n            } else if (tiltDir == 'R_STAR') {\n                tiltValue = pd.c0_TILT_Y;\n            }\n        } else if (cubeNo == 1) {\n            if (tiltDir == 'F_CIRCLE') {\n                tiltValue = pd.c1_TILT_X * -1;\n            } else if (tiltDir == 'B_TRIANGLE') {\n                tiltValue = pd.c1_TILT_X;\n            } else if (tiltDir == 'L_RECTANGLE') {\n                tiltValue = pd.c1_TILT_Y * -1;\n            } else if (tiltDir == 'R_STAR') {\n                tiltValue = pd.c1_TILT_Y;\n            }\n        } else if (cubeNo == 2) {\n            if (tiltDir == 'F_CIRCLE') {\n                tiltValue = pd.c2_TILT_X * -1;\n            } else if (tiltDir == 'B_TRIANGLE') {\n                tiltValue = pd.c2_TILT_X;\n            } else if (tiltDir == 'L_RECTANGLE') {\n                tiltValue = pd.c2_TILT_Y * -1;\n            } else if (tiltDir == 'R_STAR') {\n                tiltValue = pd.c2_TILT_Y;\n            }\n        } else if (cubeNo == 3) {\n            if (tiltDir == 'F_CIRCLE') {\n                tiltValue = pd.c3_TILT_X * -1;\n            } else if (tiltDir == 'B_TRIANGLE') {\n                tiltValue = pd.c3_TILT_X;\n            } else if (tiltDir == 'L_RECTANGLE') {\n                tiltValue = pd.c3_TILT_Y * -1;\n            } else if (tiltDir == 'R_STAR') {\n                tiltValue = pd.c3_TILT_Y;\n            }\n        }\n\n        return tiltValue;\n    }\n\n    _isUpperDir(cubeNo, tiltDir) {\n        const pd = Entry.hw.portData;\n        if (cubeNo == 0) {\n            if (tiltDir == 'DF_RECTANGLE' && pd.c0_TILT_Y > 70) return true;\n            if (tiltDir == 'DB_STAR' && pd.c0_TILT_Y < -70) return true;\n            if (tiltDir == 'DR_CIRCLE' && pd.c0_TILT_X > 70) return true;\n            if (tiltDir == 'DL_TRIANGLE' && pd.c0_TILT_X < -70) return true;\n            if (tiltDir == 'DD_NONE' && pd.c0_TILT_Z > 70) return true;\n            if (tiltDir == 'DU_HEART' && pd.c0_TILT_Z < -70) return true;\n            return false;\n        } else if (cubeNo == 1) {\n            if (tiltDir == 'DF_RECTANGLE' && pd.c1_TILT_Y > 70) return true;\n            if (tiltDir == 'DB_STAR' && pd.c1_TILT_Y < -70) return true;\n            if (tiltDir == 'DR_CIRCLE' && pd.c1_TILT_X > 70) return true;\n            if (tiltDir == 'DL_TRIANGLE' && pd.c1_TILT_X < -70) return true;\n            if (tiltDir == 'DD_NONE' && pd.c1_TILT_Z > 70) return true;\n            if (tiltDir == 'DU_HEART' && pd.c1_TILT_Z < -70) return true;\n            return false;\n        } else if (cubeNo == 2) {\n            if (tiltDir == 'DF_RECTANGLE' && pd.c2_TILT_Y > 70) return true;\n            if (tiltDir == 'DB_STAR' && pd.c2_TILT_Y < -70) return true;\n            if (tiltDir == 'DR_CIRCLE' && pd.c2_TILT_X > 70) return true;\n            if (tiltDir == 'DL_TRIANGLE' && pd.c2_TILT_X < -70) return true;\n            if (tiltDir == 'DD_NONE' && pd.c2_TILT_Z > 70) return true;\n            if (tiltDir == 'DU_HEART' && pd.c2_TILT_Z < -70) return true;\n            return false;\n        } else if (cubeNo == 3) {\n            if (tiltDir == 'DF_RECTANGLE' && pd.c3_TILT_Y > 70) return true;\n            if (tiltDir == 'DB_STAR' && pd.c3_TILT_Y < -70) return true;\n            if (tiltDir == 'DR_CIRCLE' && pd.c3_TILT_X > 70) return true;\n            if (tiltDir == 'DL_TRIANGLE' && pd.c3_TILT_X < -70) return true;\n            if (tiltDir == 'DD_NONE' && pd.c3_TILT_Z > 70) return true;\n            if (tiltDir == 'DU_HEART' && pd.c3_TILT_Z < -70) return true;\n            return false;\n        }\n    }\n\n    _getCubeNoFromBlock(script) {\n        let cubeNo = script.getNumberValue('cubeno') - 1;\n        if (cubeNo < 0) {\n            cubeNo = 0;\n        }\n        if (cubeNo >= this.cubeCnt) {\n            cubeNo = this.cubeCnt - 1;\n        }\n        return cubeNo;\n    }\n\n    _clampBeats(beats) {\n        return Math.min(Math.max(beats, 0), 40);\n    }\n\n    _clampTempo(tempo) {\n        return Math.min(Math.max(tempo, 20), 500);\n    }\n\n    _beatsToDuration(beats) {\n        let duration = Math.round((60 / this.tempo) * beats * 100);\n        return duration;\n    }\n\n    _calcSpsFromSpeed(speed_) {\n        let speed = speed_;\n        if (speed > 100) {\n            speed = 100;\n        }\n        if (speed < -100) {\n            speed = -100;\n        }\n\n        let sps = 0;\n        if (speed != 0) {\n            if (speed < 0) {\n                sps = 65536 + (speed * 9 - 100);\n            } else {\n                sps = speed * 9 + 100;\n            }\n            sps = Math.round(sps);\n        }\n        return sps;\n    }\n}\n\nEntry.PingpongG2 = new (class extends PingpongBase {\n    constructor() {\n        super(2);\n\n        this.id = '35.2';\n        this.name = 'PingpongG2';\n        this.url = 'https://www.roborisen.com';\n        this.imageName = 'pingpong_g2.png';\n        this.title = {\n            ko: '핑퐁 G2',\n            en: 'Pingpong G2',\n        };\n        this.blockMenuBlocks = [\n            'pingpong_g2_when_button_pressed',\n            'pingpong_g2_when_tilted',\n            'pingpong_g2_is_button_pressed',\n            'pingpong_g2_is_tilted',\n            'pingpong_g2_get_tilt_value',\n            'pingpong_g2_is_top_shape',\n            'pingpong_g2_get_sensor_value',\n            'pingpong_g2_multi_motor_rotate',\n            'pingpong_g2_motor_rotate',\n            'pingpong_g2_start_multi_motor_rotate',\n            'pingpong_g2_start_motor_rotate',\n            'pingpong_g2_stop_motor_rotate',\n            'pingpong_g2_rotate_servo_mortor',\n            'pingpong_g2_set_dot_pixel',\n            'pingpong_g2_set_dot_string',\n            'pingpong_g2_set_dot_clear',\n            'pingpong_g2_playNoteForBeats',\n            'pingpong_g2_playChordForBeats',\n            'pingpong_g2_restForBeats',\n            'pingpong_g2_setTempo',\n            'pingpong_g2_getTempo',\n        ];\n    }\n\n    getBlocks() {\n        return {\n            pingpong_g2_when_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'pingpong_g2_when_button_pressed',\n                },\n                paramsKeyMap: {\n                    CUBEID: 1,\n                },\n                class: 'PingpongG2',\n                isNotFor: ['PingpongG2'],\n                event: 'pp_when_button_pressed',\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const pd = Entry.hw.portData;\n\n                    if ((cubeId == 0 && pd.c0_BUTTON == 1) || (cubeId == 1 && pd.c1_BUTTON == 1)) {\n                        return script.callReturn();\n                    }\n                    return this.die();\n                },\n            },\n            pingpong_g2_when_tilted: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'pingpong_g2_when_tilted',\n                },\n                paramsKeyMap: {\n                    CUBEID: 1,\n                    TILT_DIR: 2,\n                },\n                class: 'PingpongG2',\n                isNotFor: ['PingpongG2'],\n                event: 'pp_when_tilted',\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR');\n\n                    const tiltValue = Entry.PingpongG2._getTiltValue(cubeId, tiltDir);\n                    if (tiltValue >= Entry.PingpongG2.TILT_THRESHOLD) {\n                        return script.callReturn();\n                    }\n\n                    return this.die();\n                },\n            },\n            pingpong_g2_is_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                def: {\n                    params: [null],\n                    type: 'pingpong_g2_is_button_pressed',\n                },\n                paramsKeyMap: {\n                    CUBEID: 0,\n                },\n                class: 'PingpongG2',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const pd = Entry.hw.portData;\n\n                    return (cubeId == 0 && pd.c0_BUTTON == 1) || (cubeId == 1 && pd.c1_BUTTON == 1);\n                },\n            },\n            pingpong_g2_is_tilted: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g2_is_tilted' },\n                paramsKeyMap: {\n                    CUBEID: 0,\n                    TILT_DIR: 1,\n                },\n                class: 'PingpongG2',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR', script);\n\n                    const tiltValue = Entry.PingpongG2._getTiltValue(cubeId, tiltDir);\n\n                    return tiltValue >= Entry.PingpongG2.TILT_THRESHOLD;\n                },\n            },\n            pingpong_g2_get_tilt_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'pingpong_g2_get_tilt_value',\n                },\n                paramsKeyMap: { CUBEID: 0, DIR: 1 },\n                class: 'PingpongG2',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('DIR', script);\n\n                    return Entry.PingpongG2._getTiltValue(cubeId, tiltDir);\n                },\n            },\n            pingpong_g2_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_sensor_proximity, 'PROXIMITY'],\n                            [Lang.Blocks.pingpong_sensor_ain, 'AIN'],\n                        ],\n                        value: 'PROXIMITY',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g2_get_sensor_value' },\n                paramsKeyMap: { CUBEID: 0, SENSOR: 1 },\n                class: 'PingpongG2',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const sensorType = script.getStringField('SENSOR', script);\n                    const pd = Entry.hw.portData;\n                    let value = 0;\n\n                    if (sensorType == 'PROXIMITY') {\n                        if (cubeId == 0) {\n                            value = pd.c0_PROXIMITY;\n                        } else if (cubeId == 1) {\n                            value = pd.c1_PROXIMITY;\n                        }\n                    } else if (sensorType == 'AIN') {\n                        if (cubeId == 0) {\n                            value = pd.c0_AIN;\n                        } else if (cubeId == 1) {\n                            value = pd.c1_AIN;\n                        }\n                    }\n\n                    return value;\n                },\n            },\n            pingpong_g2_is_top_shape: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_dir6,\n                        value: 'DF_RECTANGLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g2_is_top_shape' },\n                paramsKeyMap: { CUBEID: 0, TILT_DIR: 1 },\n                class: 'PingpongG2',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR', script);\n                    return Entry.PingpongG2._isUpperDir(cubeId, tiltDir);\n                },\n            },\n            pingpong_g2_multi_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 10,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 10,\n                    },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n                ],\n                def: {\n                    params: [null],\n                    type: 'pingpong_g2_multi_motor_rotate',\n                },\n                paramsKeyMap: { DIR_1: 0, DEGREE_1: 1, DIR_2: 2, DEGREE_2: 3 },\n                class: 'PingpongG2_motor',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const dir1 = script.getStringField('DIR_1');\n                        const dir2 = script.getStringField('DIR_2');\n                        const degree1 = script.getNumberValue('DEGREE_1');\n                        const degree2 = script.getNumberValue('DEGREE_2');\n\n                        const speed1 = 80 * (dir1 === 'LEFT' ? -1 : 1);\n                        const speed2 = 80 * (dir2 === 'LEFT' ? -1 : 1);\n\n                        const [arr1, delay1] = Entry.PingpongG2.makeSingleStepPacket(\n                            0,\n                            speed1,\n                            degree1\n                        );\n                        const [arr2, delay2] = Entry.PingpongG2.makeSingleStepPacket(\n                            1,\n                            speed2,\n                            degree2\n                        );\n\n                        const opt = [2, 1, 0, 2];\n                        const packet = Entry.PingpongG2.makeAggregatePacket(\n                            OPCODE.AGGREGATE_STEPS,\n                            0,\n                            [arr1, arr2],\n                            opt\n                        );\n\n                        const waitTime = Math.max(delay1, delay2);\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g2_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 10,\n                    },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'pingpong_g2_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0, DIR: 1, DEGREE: 2 },\n                class: 'PingpongG2_motor',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const dir = script.getStringField('DIR');\n                        const degree = script.getNumberValue('DEGREE');\n\n                        const speed = 80 * (dir === 'LEFT' ? -1 : 1);\n\n                        const [arr, waitTime] = Entry.PingpongG2.makeSingleStepPacket(\n                            cubeId,\n                            speed,\n                            degree\n                        );\n                        const packet = Buffer.from(arr);\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g2_start_multi_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g2_start_multi_motor_rotate',\n                },\n                paramsKeyMap: { SPEED_1: 0, SPEED_2: 1 },\n                class: 'PingpongG2_motor',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const speed1 = script.getNumberValue('SPEED_1');\n                        const speed2 = script.getNumberValue('SPEED_2');\n\n                        const arr1 = Entry.PingpongG2.makeContStepPacket(0, speed1);\n                        const arr2 = Entry.PingpongG2.makeContStepPacket(1, speed2);\n\n                        const opt = [MODE.MULTIROLE, 0, 0, 2];\n                        const packet = Entry.PingpongG2.makeAggregatePacket(\n                            OPCODE.AGGREGATE_STEPS,\n                            0,\n                            [arr1, arr2],\n                            opt\n                        );\n\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g2_start_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 100,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [null, null],\n                    type: 'pingpong_g2_start_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0, SPEED: 1 },\n                class: 'PingpongG2_motor',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const speed = script.getNumberValue('SPEED');\n\n                        const arr = Entry.PingpongG2.makeContStepPacket(cubeId, speed);\n\n                        const packet = Buffer.from(arr);\n                        const waitTime = Math.round(((1100 - Math.abs(speed)) / 99) * 10) + 400;\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g2_stop_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g2_stop_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0 },\n                class: 'PingpongG2_motor',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n\n                        const arr = Entry.PingpongG2.makeContStepPacket(cubeId, 0);\n                        const packet = Buffer.from(arr);\n\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g2_rotate_servo_mortor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [null, { type: 'angle' }], type: 'pingpong_g2_rotate_servo_mortor' },\n                paramsKeyMap: { cubeno: 0, DEGREE: 1 },\n                class: 'PingpongG2_motor',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG2._getCubeNoFromBlock(script);\n                        let angle = script.getNumberValue('DEGREE', script);\n\n                        angle = Math.min(Math.max(angle, 0), 180);\n\n                        const opt = [2, 0, angle, 1];\n                        const packet = Entry.PingpongG2.makePacket(OPCODE.SERVO, 0x00, cubeId, opt);\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g2_set_dot_pixel: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '0' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '0' },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_dot_on, 1],\n                            [Lang.Blocks.pingpong_dot_off, 0],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'pingpong_g2_set_dot_pixel',\n                },\n                paramsKeyMap: { cubeno: 0, X: 1, Y: 2, onoff: 3 },\n                class: 'PingpongG2_peripheral_LED',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG2._getCubeNoFromBlock(script);\n                        let dotX = script.getNumberValue('X', script);\n                        let dotY = script.getNumberValue('Y', script);\n                        const onoff = script.getNumberField('onoff', script);\n\n                        dotX = Math.min(Math.max(dotX, 0), 7);\n                        dotY = Math.min(Math.max(dotY, 0), 7);\n\n                        const opt = [0x70, dotY, dotX, onoff];\n                        const packet = Entry.PingpongG2.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe1,\n                            cubeId,\n                            opt\n                        );\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g2_set_dot_string: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    { type: 'Block', accept: 'string', value: 'Hello!' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '2' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [null, null], type: 'pingpong_g2_set_dot_string' },\n                paramsKeyMap: { cubeno: 0, STR: 1, DURATION: 2 },\n                class: 'PingpongG2_peripheral_LED',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG2._getCubeNoFromBlock(script);\n                        const str = script.getStringValue('STR', script);\n                        const duration = script.getNumberValue('DURATION', script);\n\n                        let period = Math.round((duration * 100) / (str.length * 8));\n                        period = Math.min(Math.max(period, 1), 200);\n\n                        const opt = Buffer.concat([\n                            Buffer.from([0x70, period, 0]),\n                            Buffer.from(str.substring(0, 20)),\n                        ]);\n\n                        const packet = Entry.PingpongG2.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe3,\n                            cubeId,\n                            opt\n                        );\n                        // add delay time for matrix stability (about 400ms)\n                        const waitTime = period * (str.length + 1) * 8 * 10 + 400;\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g2_set_dot_clear: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g2_set_dot_clear' },\n                paramsKeyMap: { cubeno: 0 },\n                class: 'PingpongG2_peripheral_LED',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG2._getCubeNoFromBlock(script);\n                        const opt = [0x70, 1, 0, ' '];\n                        const packet = Entry.PingpongG2.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe3,\n                            cubeId,\n                            opt\n                        );\n                        return [packet, 400];\n                    });\n                },\n            },\n            pingpong_g2_playNoteForBeats: {\n                //'%1 큐브의 %2 번 음을 %3 박자로 연주하기 %4',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g2_playNoteForBeats' },\n                paramsKeyMap: { CUBEID: 0, NOTE: 1, BEATS: 2 },\n                class: 'PingpongG2_Music',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const NOTE = script.getNumberField('NOTE', script);\n                        const BEATS = script.getNumberValue('BEATS', script);\n\n                        const cBeats = Entry.PingpongG2._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG2._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30; //XXX\n                        const arr = Entry.PingpongG2.makeMusicNotePacket(cubeId, NOTE, durationSec);\n                        const packet = Buffer.from(arr);\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g2_playChordForBeats: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g2_cube_id,\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g2_playChordForBeats' },\n                paramsKeyMap: {\n                    CUBEID_1: 0,\n                    NOTE_1: 1,\n                    CUBEID_2: 2,\n                    NOTE_2: 3,\n                    BEATS: 4,\n                },\n                class: 'PingpongG2_Music',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const cubeId1 = script.getNumberField('CUBEID_1');\n                        const cubeId2 = script.getNumberField('CUBEID_2');\n                        const NOTE1 = script.getNumberField('NOTE_1', script);\n                        const NOTE2 = script.getNumberField('NOTE_2', script);\n\n                        const BEATS = script.getNumberValue('BEATS', script);\n                        const cBeats = Entry.PingpongG2._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG2._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30;\n\n                        const arr1 = Entry.PingpongG2.makeMusicNotePacket(\n                            cubeId1,\n                            NOTE1,\n                            durationSec\n                        );\n                        const arr2 = Entry.PingpongG2.makeMusicNotePacket(\n                            cubeId2,\n                            NOTE2,\n                            durationSec\n                        );\n\n                        const packet = Entry.PingpongG2.makeAggregatePacket(\n                            OPCODE.MUSIC,\n                            0xa2,\n                            [arr1, arr2],\n                            [0, 0]\n                        );\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g2_restForBeats: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g2_restForBeats' },\n                paramsKeyMap: { BEATS: 0 },\n                class: 'PingpongG2_Music',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.postCallReturn(script, () => {\n                        const BEATS = script.getNumberValue('BEATS', script);\n\n                        const cBeats = Entry.PingpongG2._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG2._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30;\n\n                        //XXX\n                        return [null, waitTime];\n                    });\n                },\n            },\n            pingpong_g2_setTempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '60' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g2_setTempo' },\n                paramsKeyMap: { TEMPO: 0 },\n                class: 'PingpongG2_Music',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    let tempo = script.getNumberValue('TEMPO', script);\n                    Entry.PingpongG2.tempo = Entry.PingpongG2._clampTempo(tempo);\n                    return script.callReturn();\n                },\n            },\n            pingpong_g2_getTempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [],\n                def: { params: [], type: 'pingpong_g2_getTempo' },\n                paramsKeyMap: {},\n                class: 'PingpongG2_Music',\n                isNotFor: ['PingpongG2'],\n                func(sprite, script) {\n                    return Entry.PingpongG2.tempo;\n                },\n            },\n        };\n    }\n\n    setLanguage() {\n        return {\n            ko: {\n                template: {\n                    pingpong_g2_when_button_pressed: '%1 %2 큐브 버튼을 눌렀을 때',\n                    pingpong_g2_when_tilted: '%1 %2 큐브를 %3로 기울였을 때',\n                    pingpong_g2_is_button_pressed: '%1 큐브 버튼이 눌렸는가?',\n                    pingpong_g2_is_tilted: '%1 큐브가 %2로 기울어졌는가?',\n                    pingpong_g2_is_top_shape: '%1 큐브의 윗면에 %2 모양이 있는가?',\n                    pingpong_g2_get_tilt_value: '%1 큐브의 %2 방향 기울기',\n                    pingpong_g2_get_sensor_value: '%1 큐브의 %2 센서값',\n                    pingpong_g2_multi_motor_rotate:\n                        '모터1을 %1 방향 %2 도, 모터2를 %3 방향 %4 도 회전하기 %5',\n                    pingpong_g2_motor_rotate: '%1 모터를 %2 방향으로 %3 도 회전하기 %4',\n                    pingpong_g2_start_multi_motor_rotate:\n                        '모터1 속도를 %1, 모터2 속도를 %2으로 계속 회전하기 %3',\n                    pingpong_g2_start_motor_rotate: '%1 모터의 속도를 %2으로 계속 회전하기 %3',\n                    pingpong_g2_stop_motor_rotate: '%1 모터 멈추기 %2',\n                    pingpong_g2_set_dot_pixel: '%1 번째 큐브의 도트 X:%2 Y:%3 %4 %5',\n                    pingpong_g2_set_dot_string:\n                        '%1 번째 큐브에 도트 문자열 %2 %3초동안 보여주기 %4',\n                    pingpong_g2_set_dot_clear: '%1 번째 큐브의 화면 지우기 %2',\n                    pingpong_g2_rotate_servo_mortor: '%1 번째 큐브의 서보모터 %2도로 설정하기 %3',\n                    pingpong_g2_playNoteForBeats: '%1 큐브의 %2 음을 %3 박자로 연주하기 %4',\n                    pingpong_g2_playChordForBeats: '%1 큐브 %2, %3 큐브 %4, %5 박자로 연주하기 %6',\n                    pingpong_g2_restForBeats: '%1 박자 쉬기 %2',\n                    pingpong_g2_setTempo: '악보 빠르기를 %1 으로 정하기 %2',\n                    pingpong_g2_getTempo: '악보 빠르기',\n                },\n                Blocks: {\n                    ...this.lang_defblock.ko,\n\n                    pingpong_g2_cube_id: [\n                        ['1번', 0],\n                        ['2번', 1],\n                    ],\n                    pingpong_g2_cube_all: [\n                        ['1번', 0],\n                        ['2번', 1],\n                        ['모든', -1],\n                    ],\n                },\n            },\n            en: {\n                template: {\n                    pingpong_g2_when_button_pressed: '%1 %2 cube button pressed',\n                    pingpong_g2_when_tilted: '%1 %2 cube tilted to %3',\n                    pingpong_g2_is_button_pressed: '%1 cube button pressed?',\n                    pingpong_g2_is_tilted: '%1 cube tilted to %2',\n                    pingpong_g2_is_top_shape: '%1 cube shown %2 in top view?',\n                    pingpong_g2_get_tilt_value: '%1 cube tilt angle to %2',\n                    pingpong_g2_get_sensor_value: '%1 cube read sensor %2',\n                    pingpong_g2_multi_motor_rotate:\n                        'rotate motor1 %2 degrees %1, motor2 %4 degrees %3 %5',\n                    pingpong_g2_motor_rotate: 'rotate %2 degrees %1 %3',\n                    pingpong_g2_start_multi_motor_rotate:\n                        'set motor1 speed to %1, motor2 speed to %2 %3',\n                    pingpong_g2_start_motor_rotate: 'set motor speed to %1 %2',\n                    pingpong_g2_stop_motor_rotate: 'stop motor rotate %1',\n                    pingpong_g2_rotate_servo_mortor: 'set servo mortor to %1 degrees %2',\n                    pingpong_g2_set_dot_pixel: '%1 cube set DOT X:%2 Y:%3 %4 %5',\n                    pingpong_g2_set_dot_string:\n                        'print %1 cube string %2 during %3 seconds to DOT %4',\n                    pingpong_g2_set_dot_clear: '%1 cube clear DOT %2',\n                    pingpong_g2_playNoteForBeats: '%1 cube play note %2 for %3 beats %4',\n                    pingpong_g2_playChordForBeats: '%1 cube %2, %3 cube %4 for %5 beats %6',\n                    pingpong_g2_restForBeats: 'rest for %1 beats %2',\n                    pingpong_g2_setTempo: 'set tempo to %1 %2',\n                    pingpong_g2_getTempo: 'tempo',\n                },\n                Blocks: {\n                    ...this.lang_defblock.en,\n\n                    pingpong_g2_cube_id: [\n                        ['1st', 0],\n                        ['2nd', 1],\n                    ],\n                    pingpong_g2_cube_all: [\n                        ['1st', 0],\n                        ['2nd', 1],\n                        ['All', -1],\n                    ],\n                },\n            },\n        };\n    }\n})();\n\nEntry.PingpongG3 = new (class extends PingpongBase {\n    constructor() {\n        super(3);\n\n        this.id = '35.3';\n        this.name = 'PingpongG3';\n        this.url = 'https://www.roborisen.com';\n        this.imageName = 'pingpong_g3.png';\n        this.title = {\n            ko: '핑퐁 G3',\n            en: 'Pingpong G3',\n        };\n        this.blockMenuBlocks = [\n            'pingpong_g3_when_button_pressed',\n            'pingpong_g3_when_tilted',\n            'pingpong_g3_is_button_pressed',\n            'pingpong_g3_is_tilted',\n            'pingpong_g3_get_tilt_value',\n            'pingpong_g3_is_top_shape',\n            'pingpong_g3_get_sensor_value',\n            'pingpong_g3_multi_motor_rotate',\n            'pingpong_g3_motor_rotate',\n            'pingpong_g3_start_multi_motor_rotate',\n            'pingpong_g3_start_motor_rotate',\n            'pingpong_g3_stop_motor_rotate',\n            'pingpong_g3_rotate_servo_mortor',\n            'pingpong_g3_set_dot_pixel',\n            'pingpong_g3_set_dot_string',\n            'pingpong_g3_set_dot_clear',\n            'pingpong_g3_playNoteForBeats',\n            'pingpong_g3_playChordForBeats',\n            'pingpong_g3_restForBeats',\n            'pingpong_g3_setTempo',\n            'pingpong_g3_getTempo',\n        ];\n    }\n\n    getBlocks() {\n        return {\n            pingpong_g3_when_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'pingpong_g3_when_button_pressed',\n                },\n                paramsKeyMap: {\n                    CUBEID: 1,\n                },\n                class: 'PingpongG3',\n                isNotFor: ['PingpongG3'],\n                event: 'pp_when_button_pressed',\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const pd = Entry.hw.portData;\n\n                    if (\n                        (cubeId == 0 && pd.c0_BUTTON == 1) ||\n                        (cubeId == 1 && pd.c1_BUTTON == 1) ||\n                        (cubeId == 2 && pd.c2_BUTTON == 1)\n                    ) {\n                        return script.callReturn();\n                    }\n                    return this.die();\n                },\n            },\n            pingpong_g3_when_tilted: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'pingpong_g3_when_tilted',\n                },\n                paramsKeyMap: {\n                    CUBEID: 1,\n                    TILT_DIR: 2,\n                },\n                class: 'PingpongG3',\n                isNotFor: ['PingpongG3'],\n                event: 'pp_when_tilted',\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR');\n\n                    const tiltValue = Entry.PingpongG3._getTiltValue(cubeId, tiltDir);\n                    if (tiltValue >= Entry.PingpongG3.TILT_THRESHOLD) {\n                        return script.callReturn();\n                    }\n\n                    return this.die();\n                },\n            },\n            pingpong_g3_is_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                def: {\n                    params: [null],\n                    type: 'pingpong_g3_is_button_pressed',\n                },\n                paramsKeyMap: {\n                    CUBEID: 0,\n                },\n                class: 'PingpongG3',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const pd = Entry.hw.portData;\n\n                    return (\n                        (cubeId == 0 && pd.c0_BUTTON == 1) ||\n                        (cubeId == 1 && pd.c1_BUTTON == 1) ||\n                        (cubeId == 2 && pd.c2_BUTTON == 1)\n                    );\n                },\n            },\n            pingpong_g3_is_tilted: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g3_is_tilted' },\n                paramsKeyMap: {\n                    CUBEID: 0,\n                    TILT_DIR: 1,\n                },\n                class: 'PingpongG3',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR', script);\n\n                    const tiltValue = Entry.PingpongG3._getTiltValue(cubeId, tiltDir);\n\n                    return tiltValue >= Entry.PingpongG3.TILT_THRESHOLD;\n                },\n            },\n            pingpong_g3_get_tilt_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'pingpong_g3_get_tilt_value',\n                },\n                paramsKeyMap: { CUBEID: 0, DIR: 1 },\n                class: 'PingpongG3',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('DIR', script);\n\n                    return Entry.PingpongG3._getTiltValue(cubeId, tiltDir);\n                },\n            },\n            pingpong_g3_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_sensor_proximity, 'PROXIMITY'],\n                            [Lang.Blocks.pingpong_sensor_ain, 'AIN'],\n                        ],\n                        value: 'PROXIMITY',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g3_get_sensor_value' },\n                paramsKeyMap: { CUBEID: 0, SENSOR: 1 },\n                class: 'PingpongG3',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const sensorType = script.getStringField('SENSOR', script);\n                    const pd = Entry.hw.portData;\n                    let value = 0;\n\n                    if (sensorType == 'PROXIMITY') {\n                        if (cubeId == 0) {\n                            value = pd.c0_PROXIMITY;\n                        } else if (cubeId == 1) {\n                            value = pd.c1_PROXIMITY;\n                        } else if (cubeId == 2) {\n                            value = pd.c2_PROXIMITY;\n                        }\n                    } else if (sensorType == 'AIN') {\n                        if (cubeId == 0) {\n                            value = pd.c0_AIN;\n                        } else if (cubeId == 1) {\n                            value = pd.c1_AIN;\n                        } else if (cubeId == 2) {\n                            value = pd.c2_AIN;\n                        }\n                    }\n\n                    return value;\n                },\n            },\n            pingpong_g3_is_top_shape: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_dir6,\n                        value: 'DF_RECTANGLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g3_is_top_shape' },\n                paramsKeyMap: { CUBEID: 0, TILT_DIR: 1 },\n                class: 'PingpongG3',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR', script);\n                    return Entry.PingpongG3._isUpperDir(cubeId, tiltDir);\n                },\n            },\n            pingpong_g3_multi_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 10,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g3_multi_motor_rotate',\n                },\n                paramsKeyMap: {\n                    DIR_1: 0,\n                    DEGREE_1: 1,\n                    DIR_2: 2,\n                    DEGREE_2: 3,\n                    DIR_3: 4,\n                    DEGREE_3: 5,\n                },\n                class: 'PingpongG3_motor',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const dir1 = script.getStringField('DIR_1');\n                        const dir2 = script.getStringField('DIR_2');\n                        const dir3 = script.getStringField('DIR_3');\n                        const degree1 = script.getNumberValue('DEGREE_1');\n                        const degree2 = script.getNumberValue('DEGREE_2');\n                        const degree3 = script.getNumberValue('DEGREE_3');\n\n                        const speed1 = 80 * (dir1 === 'LEFT' ? -1 : 1);\n                        const speed2 = 80 * (dir2 === 'LEFT' ? -1 : 1);\n                        const speed3 = 80 * (dir3 === 'LEFT' ? -1 : 1);\n\n                        const [arr1, delay1] = Entry.PingpongG3.makeSingleStepPacket(\n                            0,\n                            speed1,\n                            degree1\n                        );\n                        const [arr2, delay2] = Entry.PingpongG3.makeSingleStepPacket(\n                            1,\n                            speed2,\n                            degree2\n                        );\n                        const [arr3, delay3] = Entry.PingpongG3.makeSingleStepPacket(\n                            2,\n                            speed3,\n                            degree3\n                        );\n\n                        const opt = [2, 1, 0, 2];\n                        const packet = Entry.PingpongG3.makeAggregatePacket(\n                            OPCODE.AGGREGATE_STEPS,\n                            0,\n                            [arr1, arr2, arr3],\n                            opt\n                        );\n\n                        const waitTime = Math.max(delay1, delay2, delay3);\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g3_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n                ],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'pingpong_g3_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0, DIR: 1, DEGREE: 2 },\n                class: 'PingpongG3_motor',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const dir = script.getStringField('DIR');\n                        const degree = script.getNumberValue('DEGREE');\n\n                        const speed = 80 * (dir === 'LEFT' ? -1 : 1);\n                        const [arr, waitTime] = Entry.PingpongG3.makeSingleStepPacket(\n                            cubeId,\n                            speed,\n                            degree\n                        );\n                        const packet = Buffer.from(arr);\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g3_start_multi_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g3_start_multi_motor_rotate',\n                },\n                paramsKeyMap: { SPEED_1: 0, SPEED_2: 1, SPEED_3: 2 },\n                class: 'PingpongG3_motor',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const speed1 = script.getNumberValue('SPEED_1');\n                        const speed2 = script.getNumberValue('SPEED_2');\n                        const speed3 = script.getNumberValue('SPEED_3');\n\n                        const arr1 = Entry.PingpongG3.makeContStepPacket(0, speed1);\n                        const arr2 = Entry.PingpongG3.makeContStepPacket(1, speed2);\n                        const arr3 = Entry.PingpongG3.makeContStepPacket(2, speed3);\n\n                        const opt = [2, 0, 0, 2];\n                        const packet = Entry.PingpongG3.makeAggregatePacket(\n                            OPCODE.AGGREGATE_STEPS,\n                            0,\n                            [arr1, arr2, arr3],\n                            opt\n                        );\n\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g3_start_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 100,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [null, null],\n                    type: 'pingpong_g3_start_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0, SPEED: 1 },\n                class: 'PingpongG3_motor',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const speed = script.getNumberValue('SPEED');\n\n                        const arr = Entry.PingpongG3.makeContStepPacket(cubeId, speed);\n                        const packet = Buffer.from(arr);\n\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g3_stop_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g3_stop_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0 },\n                class: 'PingpongG3_motor',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n\n                        const arr = Entry.PingpongG3.makeContStepPacket(cubeId, 0);\n                        const packet = Buffer.from(arr);\n\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g3_rotate_servo_mortor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    { type: 'Block', accept: 'string', defaultType: 'number' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [null, { type: 'angle' }], type: 'pingpong_g3_rotate_servo_mortor' },\n                paramsKeyMap: { cubeno: 0, DEGREE: 1 },\n                class: 'PingpongG3_motor',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG3._getCubeNoFromBlock(script);\n                        let angle = script.getNumberValue('DEGREE', script);\n\n                        angle = Math.min(Math.max(angle, 0), 180);\n\n                        const opt = [2, 0, angle, 1];\n                        const packet = Entry.PingpongG3.makePacket(OPCODE.SERVO, 0x00, cubeId, opt);\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g3_set_dot_pixel: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '0' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '0' },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_dot_on, 1],\n                            [Lang.Blocks.pingpong_dot_off, 0],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'pingpong_g3_set_dot_pixel',\n                },\n                paramsKeyMap: { cubeno: 0, X: 1, Y: 2, onoff: 3 },\n                class: 'PingpongG3_peripheral_LED',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG3._getCubeNoFromBlock(script);\n                        let dotX = script.getNumberValue('X', script);\n                        let dotY = script.getNumberValue('Y', script);\n                        const onoff = script.getNumberField('onoff', script);\n\n                        dotX = Math.min(Math.max(dotX, 0), 7);\n                        dotY = Math.min(Math.max(dotY, 0), 7);\n\n                        const opt = [0x70, dotY, dotX, onoff];\n                        const packet = Entry.PingpongG3.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe1,\n                            cubeId,\n                            opt\n                        );\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g3_set_dot_string: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    { type: 'Block', accept: 'string', value: 'Hello!' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '2' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [null, null], type: 'pingpong_g3_set_dot_string' },\n                paramsKeyMap: { cubeno: 0, STR: 1, DURATION: 2 },\n                class: 'PingpongG3_peripheral_LED',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG3._getCubeNoFromBlock(script);\n                        const str = script.getStringValue('STR', script);\n                        const duration = script.getNumberValue('DURATION', script);\n\n                        let period = Math.round((duration * 100) / (str.length * 8));\n                        period = Math.min(Math.max(period, 1), 200);\n\n                        const opt = Buffer.concat([\n                            Buffer.from([0x70, period, 0]),\n                            Buffer.from(str.substring(0, 20)),\n                        ]);\n\n                        const packet = Entry.PingpongG3.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe3,\n                            cubeId,\n                            opt\n                        );\n                        const waitTime = period * str.length * 8 * 10 + 400; // add wait for 400ms\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g3_set_dot_clear: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g3_set_dot_clear' },\n                paramsKeyMap: { cubeno: 0 },\n                class: 'PingpongG3_peripheral_LED',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG3._getCubeNoFromBlock(script);\n                        const opt = [0x70, 1, 0, ' '];\n                        const packet = Entry.PingpongG3.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe3,\n                            cubeId,\n                            opt\n                        );\n                        return [packet, 400];\n                    });\n                },\n            },\n            pingpong_g3_playNoteForBeats: {\n                //'%1 큐브의 %2 번 음을 %3 박자로 연주하기 %4',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g3_playNoteForBeats' },\n                paramsKeyMap: { CUBEID: 0, NOTE: 1, BEATS: 2 },\n                class: 'PingpongG3_Music',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const NOTE = script.getNumberField('NOTE', script);\n                        const BEATS = script.getNumberValue('BEATS', script);\n\n                        const cBeats = Entry.PingpongG3._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG3._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30; //XXX\n                        const arr = Entry.PingpongG3.makeMusicNotePacket(cubeId, NOTE, durationSec);\n                        const packet = Buffer.from(arr);\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g3_playChordForBeats: {\n                //'%1 큐브 %2, %3 큐브 %4, %5 큐브 %6 %7 박자로 연주하기 %8',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g3_cube_id,\n                        value: 2,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g3_playChordForBeats' },\n                paramsKeyMap: {\n                    CUBEID_1: 0,\n                    NOTE_1: 1,\n                    CUBEID_2: 2,\n                    NOTE_2: 3,\n                    CUBEID_3: 4,\n                    NOTE_3: 5,\n                    BEATS: 6,\n                },\n                class: 'PingpongG3_Music',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const cubeId1 = script.getNumberField('CUBEID_1');\n                        const cubeId2 = script.getNumberField('CUBEID_2');\n                        const cubeId3 = script.getNumberField('CUBEID_3');\n                        const NOTE1 = script.getNumberField('NOTE_1', script);\n                        const NOTE2 = script.getNumberField('NOTE_2', script);\n                        const NOTE3 = script.getNumberField('NOTE_3', script);\n\n                        const BEATS = script.getNumberValue('BEATS', script);\n                        const cBeats = Entry.PingpongG3._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG3._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30;\n\n                        const arr1 = Entry.PingpongG3.makeMusicNotePacket(\n                            cubeId1,\n                            NOTE1,\n                            durationSec\n                        );\n                        const arr2 = Entry.PingpongG3.makeMusicNotePacket(\n                            cubeId2,\n                            NOTE2,\n                            durationSec\n                        );\n                        const arr3 = Entry.PingpongG3.makeMusicNotePacket(\n                            cubeId3,\n                            NOTE3,\n                            durationSec\n                        );\n\n                        const packet = Entry.PingpongG3.makeAggregatePacket(\n                            OPCODE.MUSIC,\n                            0xa2,\n                            [arr1, arr2, arr3],\n                            [0, 0]\n                        );\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g3_restForBeats: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g3_restForBeats' },\n                paramsKeyMap: { BEATS: 0 },\n                class: 'PingpongG3_Music',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.postCallReturn(script, () => {\n                        const BEATS = script.getNumberValue('BEATS', script);\n\n                        const cBeats = Entry.PingpongG3._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG3._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30;\n\n                        //XXX\n                        return [null, waitTime];\n                    });\n                },\n            },\n            pingpong_g3_setTempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '60' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g3_setTempo' },\n                paramsKeyMap: { TEMPO: 0 },\n                class: 'PingpongG3_Music',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    let tempo = script.getNumberValue('TEMPO', script);\n                    Entry.PingpongG3.tempo = Entry.PingpongG3._clampTempo(tempo);\n                    return script.callReturn();\n                },\n            },\n            pingpong_g3_getTempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [],\n                def: { params: [], type: 'pingpong_g3_getTempo' },\n                paramsKeyMap: {},\n                class: 'PingpongG3_Music',\n                isNotFor: ['PingpongG3'],\n                func(sprite, script) {\n                    return Entry.PingpongG3.tempo;\n                },\n            },\n        };\n    }\n\n    setLanguage() {\n        return {\n            ko: {\n                template: {\n                    pingpong_g3_when_button_pressed: '%1 %2 큐브 버튼을 눌렀을 때',\n                    pingpong_g3_when_tilted: '%1 %2 큐브를 %3로 기울였을 때',\n                    pingpong_g3_is_button_pressed: '%1 큐브 버튼이 눌렸는가?',\n                    pingpong_g3_is_tilted: '%1 큐브가 %2로 기울어졌는가?',\n                    pingpong_g3_is_top_shape: '%1 큐브의 윗면에 %2 모양이 있는가?',\n                    pingpong_g3_get_tilt_value: '%1 큐브의 %2 방향 기울기',\n                    pingpong_g3_get_sensor_value: '%1 큐브의 %2 센서값',\n                    pingpong_g3_multi_motor_rotate:\n                        '모터1을 %1 방향 %2 도, 모터2를 %3 방향 %4 도, 모터3을 %5방향 %6도 회전하기 %7',\n                    pingpong_g3_motor_rotate: '%1 모터를 %2 방향으로 %3 도 회전하기 %4',\n                    pingpong_g3_start_multi_motor_rotate:\n                        '모터1 속도를 %1, 모터2 속도를 %2, 모터3 속도를 %3으로 계속 회전하기 %4',\n                    pingpong_g3_start_motor_rotate: '%1 모터의 속도를 %2으로 계속 회전하기 %3',\n                    pingpong_g3_stop_motor_rotate: '%1 모터 멈추기 %2',\n                    pingpong_g3_set_dot_pixel: '%1 번째 큐브의 도트 X:%2 Y:%3 %4 %5',\n                    pingpong_g3_set_dot_string:\n                        '%1 번째 큐브에 도트 문자열 %2 %3초동안 보여주기 %4',\n                    pingpong_g3_set_dot_clear: '%1 번째 큐브의 화면 지우기 %2',\n                    pingpong_g3_rotate_servo_mortor: '%1 번째 큐브의 서보모터 %2도로 설정하기 %3',\n                    pingpong_g3_playNoteForBeats: '%1 큐브의 %2 음을 %3 박자로 연주하기 %4',\n                    pingpong_g3_playChordForBeats:\n                        '%1 큐브 %2, %3 큐브 %4, %5 큐브 %6 %7 박자로 연주하기 %8',\n                    pingpong_g3_restForBeats: '%1 박자 쉬기 %2',\n                    pingpong_g3_setTempo: '악보 빠르기를 %1 으로 정하기 %2',\n                    pingpong_g3_getTempo: '악보 빠르기',\n                },\n                Blocks: {\n                    ...this.lang_defblock.ko,\n\n                    pingpong_g3_cube_id: [\n                        ['1번', 0],\n                        ['2번', 1],\n                        ['3번', 2],\n                    ],\n                    pingpong_g3_cube_all: [\n                        ['1번', 0],\n                        ['2번', 1],\n                        ['3번', 2],\n                        ['모든', -1],\n                    ],\n                },\n            },\n            en: {\n                template: {\n                    pingpong_g3_when_button_pressed: '%1 %2 cube button pressed',\n                    pingpong_g3_when_tilted: '%1 %2 cube tilted to %3',\n                    pingpong_g3_is_button_pressed: '%1 cube button pressed?',\n                    pingpong_g3_is_tilted: '%1 cube tilted to %2',\n                    pingpong_g3_is_top_shape: '%1 cube shown %2 in top view?',\n                    pingpong_g3_get_tilt_value: '%1 cube tilt angle to %2',\n                    pingpong_g3_get_sensor_value: '%1 cube read sensor %2',\n                    pingpong_g3_multi_motor_rotate:\n                        'rotate motor1 %2 degrees %1, ' +\n                        'motor2 %4 degrees %3, motor3 %6 degrees %5 %7',\n                    pingpong_g3_motor_rotate: 'rotate %2 degrees %1 %3',\n                    pingpong_g3_start_multi_motor_rotate:\n                        'set motor1 speed to %1, motor2 speed to %2, motor3 speed to %3 %4',\n                    pingpong_g3_start_motor_rotate: 'set motor speed to %1 %2',\n                    pingpong_g3_stop_motor_rotate: 'stop motor rotate %1',\n                    pingpong_g3_rotate_servo_mortor: 'set servo mortor to %1 degrees %2',\n                    pingpong_g3_set_dot_pixel: '%1 cube set DOT X:%2 Y:%3 %4 %5',\n                    pingpong_g3_set_dot_string:\n                        'print %1 cube string %2 during %3 seconds to DOT %4',\n                    pingpong_g3_set_dot_clear: '%1 cube clear DOT %2',\n                    pingpong_g3_playNoteForBeats: '%1 cube play note %2 for %3 beats %4',\n                    pingpong_g3_playChordForBeats:\n                        '%1 cube %2, %3 cube %4, %5 cube %6 for %7 beats %8',\n                    pingpong_g3_restForBeats: 'rest for %1 beats %2',\n                    pingpong_g3_setTempo: 'set tempo to %1 %2',\n                    pingpong_g3_getTempo: 'tempo',\n                },\n                Blocks: {\n                    ...this.lang_defblock.en,\n\n                    pingpong_g3_cube_id: [\n                        ['1st', 0],\n                        ['2nd', 1],\n                        ['3rd', 2],\n                    ],\n                    pingpong_g3_cube_all: [\n                        ['1st', 0],\n                        ['2nd', 1],\n                        ['3rd', 2],\n                        ['All', -1],\n                    ],\n                },\n            },\n        };\n    }\n})();\n\nEntry.PingpongG4 = new (class extends PingpongBase {\n    constructor() {\n        super(4);\n\n        this.id = '35.4';\n        this.name = 'PingpongG4';\n        this.url = 'https://www.roborisen.com';\n        this.imageName = 'pingpong_g4.png';\n        this.title = {\n            ko: '핑퐁 G4',\n            en: 'Pingpong G4',\n        };\n        this.blockMenuBlocks = [\n            'pingpong_g4_when_button_pressed',\n            'pingpong_g4_when_tilted',\n            'pingpong_g4_is_button_pressed',\n            'pingpong_g4_is_tilted',\n            'pingpong_g4_get_tilt_value',\n            'pingpong_g4_is_top_shape',\n            'pingpong_g4_get_sensor_value',\n            'pingpong_g4_multi_motor_rotate',\n            'pingpong_g4_motor_rotate',\n            'pingpong_g4_start_multi_motor_rotate',\n            'pingpong_g4_start_motor_rotate',\n            'pingpong_g4_stop_motor_rotate',\n            'pingpong_g4_rotate_servo_mortor',\n            'pingpong_g4_set_dot_pixel',\n            'pingpong_g4_set_dot_string',\n            'pingpong_g4_set_dot_clear',\n            'pingpong_g4_playNoteForBeats',\n            'pingpong_g4_playChordForBeats',\n            'pingpong_g4_restForBeats',\n            'pingpong_g4_setTempo',\n            'pingpong_g4_getTempo',\n        ];\n    }\n\n    getBlocks() {\n        return {\n            pingpong_g4_when_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'pingpong_g4_when_button_pressed',\n                },\n                paramsKeyMap: {\n                    CUBEID: 1,\n                },\n                class: 'PingpongG4',\n                isNotFor: ['PingpongG4'],\n                event: 'pp_when_button_pressed',\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const pd = Entry.hw.portData;\n\n                    if (\n                        (cubeId == 0 && pd.c0_BUTTON == 1) ||\n                        (cubeId == 1 && pd.c1_BUTTON == 1) ||\n                        (cubeId == 2 && pd.c2_BUTTON == 1) ||\n                        (cubeId == 3 && pd.c3_BUTTON == 1)\n                    ) {\n                        return script.callReturn();\n                    }\n                    return this.die();\n                },\n            },\n            pingpong_g4_when_tilted: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_event',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/start_icon_hardware.svg',\n                        size: 14,\n                        position: { x: 0, y: -2 },\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null],\n                    type: 'pingpong_g4_when_tilted',\n                },\n                paramsKeyMap: {\n                    CUBEID: 1,\n                    TILT_DIR: 2,\n                },\n                class: 'PingpongG4',\n                isNotFor: ['PingpongG4'],\n                event: 'pp_when_tilted',\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR');\n\n                    const tiltValue = Entry.PingpongG4._getTiltValue(cubeId, tiltDir);\n                    if (tiltValue >= Entry.PingpongG4.TILT_THRESHOLD) {\n                        return script.callReturn();\n                    }\n\n                    return this.die();\n                },\n            },\n            pingpong_g4_is_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                def: {\n                    params: [null],\n                    type: 'pingpong_g4_is_button_pressed',\n                },\n                paramsKeyMap: {\n                    CUBEID: 0,\n                },\n                class: 'PingpongG4',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const pd = Entry.hw.portData;\n\n                    return (\n                        (cubeId == 0 && pd.c0_BUTTON == 1) ||\n                        (cubeId == 1 && pd.c1_BUTTON == 1) ||\n                        (cubeId == 2 && pd.c2_BUTTON == 1) ||\n                        (cubeId == 3 && pd.c3_BUTTON == 1)\n                    );\n                },\n            },\n            pingpong_g4_is_tilted: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g4_is_tilted' },\n                paramsKeyMap: {\n                    CUBEID: 0,\n                    TILT_DIR: 1,\n                },\n                class: 'PingpongG4',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR', script);\n\n                    const tiltValue = Entry.PingpongG4._getTiltValue(cubeId, tiltDir);\n\n                    return tiltValue >= Entry.PingpongG4.TILT_THRESHOLD;\n                },\n            },\n            pingpong_g4_get_tilt_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_tiltDir,\n                        value: 'F_CIRCLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                    type: 'pingpong_g4_get_tilt_value',\n                },\n                paramsKeyMap: { CUBEID: 0, DIR: 1 },\n                class: 'PingpongG4',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('DIR', script);\n\n                    return Entry.PingpongG4._getTiltValue(cubeId, tiltDir);\n                },\n            },\n            pingpong_g4_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_sensor_proximity, 'PROXIMITY'],\n                            [Lang.Blocks.pingpong_sensor_ain, 'AIN'],\n                        ],\n                        value: 'PROXIMITY',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g4_get_sensor_value' },\n                paramsKeyMap: { CUBEID: 0, SENSOR: 1 },\n                class: 'PingpongG4',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const sensorType = script.getStringField('SENSOR', script);\n                    const pd = Entry.hw.portData;\n                    let value = 0;\n\n                    if (sensorType == 'PROXIMITY') {\n                        if (cubeId == 0) {\n                            value = pd.c0_PROXIMITY;\n                        } else if (cubeId == 1) {\n                            value = pd.c1_PROXIMITY;\n                        } else if (cubeId == 2) {\n                            value = pd.c2_PROXIMITY;\n                        } else if (cubeId == 3) {\n                            value = pd.c3_PROXIMITY;\n                        }\n                    } else if (sensorType == 'AIN') {\n                        if (cubeId == 0) {\n                            value = pd.c0_AIN;\n                        } else if (cubeId == 1) {\n                            value = pd.c1_AIN;\n                        } else if (cubeId == 2) {\n                            value = pd.c2_AIN;\n                        } else if (cubeId == 3) {\n                            value = pd.c3_AIN;\n                        }\n                    }\n\n                    return value;\n                },\n            },\n            pingpong_g4_is_top_shape: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_cube_dir6,\n                        value: 'DF_RECTANGLE',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g4_is_top_shape' },\n                paramsKeyMap: { CUBEID: 0, TILT_DIR: 1 },\n                class: 'PingpongG4',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    const cubeId = script.getNumberField('CUBEID');\n                    const tiltDir = script.getStringField('TILT_DIR', script);\n                    return Entry.PingpongG4._isUpperDir(cubeId, tiltDir);\n                },\n            },\n            pingpong_g4_multi_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g4_multi_motor_rotate',\n                },\n                paramsKeyMap: {\n                    DIR_1: 0,\n                    DEGREE_1: 1,\n                    DIR_2: 2,\n                    DEGREE_2: 3,\n                    DIR_3: 4,\n                    DEGREE_3: 5,\n                    DIR_4: 6,\n                    DEGREE_4: 7,\n                },\n                class: 'PingpongG4_motor',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const dir1 = script.getStringField('DIR_1');\n                        const dir2 = script.getStringField('DIR_2');\n                        const dir3 = script.getStringField('DIR_3');\n                        const dir4 = script.getStringField('DIR_4');\n                        const degree1 = script.getNumberValue('DEGREE_1');\n                        const degree2 = script.getNumberValue('DEGREE_2');\n                        const degree3 = script.getNumberValue('DEGREE_3');\n                        const degree4 = script.getNumberValue('DEGREE_4');\n\n                        const speed1 = 80 * (dir1 === 'LEFT' ? -1 : 1);\n                        const speed2 = 80 * (dir2 === 'LEFT' ? -1 : 1);\n                        const speed3 = 80 * (dir3 === 'LEFT' ? -1 : 1);\n                        const speed4 = 80 * (dir4 === 'LEFT' ? -1 : 1);\n\n                        const [arr1, delay1] = Entry.PingpongG4.makeSingleStepPacket(\n                            0,\n                            speed1,\n                            degree1\n                        );\n                        const [arr2, delay2] = Entry.PingpongG4.makeSingleStepPacket(\n                            1,\n                            speed2,\n                            degree2\n                        );\n                        const [arr3, delay3] = Entry.PingpongG4.makeSingleStepPacket(\n                            2,\n                            speed3,\n                            degree3\n                        );\n                        const [arr4, delay4] = Entry.PingpongG4.makeSingleStepPacket(\n                            3,\n                            speed4,\n                            degree4\n                        );\n\n                        const opt = [MODE.MULTIROLE, 1, 0, 2];\n                        const packet = Entry.PingpongG4.makeAggregatePacket(\n                            OPCODE.AGGREGATE_STEPS,\n                            0,\n                            [arr1, arr2, arr3, arr4],\n                            opt\n                        );\n                        const waitTime = Math.max(delay1, delay2, delay3, delay4);\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g4_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_rotate_cw, 'RIGHT'],\n                            [Lang.Blocks.pingpong_rotate_ccw, 'LEFT'],\n                        ],\n                        value: 'RIGHT',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 10 },\n                    { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n                ],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'pingpong_g4_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0, DIR: 1, DEGREE: 2 },\n                class: 'PingpongG4_motor',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const dir = script.getStringField('DIR');\n                        const degree = script.getNumberValue('DEGREE');\n                        const speed = 80 * (dir === 'LEFT' ? -1 : 1);\n\n                        const [arr, waitTime] = Entry.PingpongG4.makeSingleStepPacket(\n                            cubeId,\n                            speed,\n                            degree\n                        );\n                        const packet = Buffer.from(arr);\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g4_start_multi_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: 100 },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g4_start_multi_motor_rotate',\n                },\n                paramsKeyMap: { SPEED_1: 0, SPEED_2: 1, SPEED_3: 2, SPEED_4: 3 },\n                class: 'PingpongG4_motor',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const speed1 = script.getNumberValue('SPEED_1');\n                        const speed2 = script.getNumberValue('SPEED_2');\n                        const speed3 = script.getNumberValue('SPEED_3');\n                        const speed4 = script.getNumberValue('SPEED_4');\n\n                        const arr1 = Entry.PingpongG4.makeContStepPacket(0, speed1);\n                        const arr2 = Entry.PingpongG4.makeContStepPacket(1, speed2);\n                        const arr3 = Entry.PingpongG4.makeContStepPacket(2, speed3);\n                        const arr4 = Entry.PingpongG4.makeContStepPacket(3, speed4);\n\n                        const opt = [MODE.MULTIROLE, 0, 0, 2];\n                        const packet = Entry.PingpongG4.makeAggregatePacket(\n                            OPCODE.AGGREGATE_STEPS,\n                            0,\n                            [arr1, arr2, arr3, arr4],\n                            opt\n                        );\n\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g4_start_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defaultType: 'number',\n                        value: 100,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [null, null],\n                    type: 'pingpong_g4_start_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0, SPEED: 1 },\n                class: 'PingpongG4_motor',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const speed = script.getNumberValue('SPEED');\n\n                        const arr = Entry.PingpongG4.makeContStepPacket(cubeId, speed);\n                        const packet = Buffer.from(arr);\n\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g4_stop_motor_rotate: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_all,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    params: [],\n                    type: 'pingpong_g4_stop_motor_rotate',\n                },\n                paramsKeyMap: { CUBEID: 0 },\n                class: 'PingpongG4_motor',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n\n                        const arr = Entry.PingpongG4.makeContStepPacket(cubeId, 0);\n                        const packet = Buffer.from(arr);\n\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g4_rotate_servo_mortor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    { type: 'Block', accept: 'string', defaultType: 'number' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [null, { type: 'angle' }], type: 'pingpong_g4_rotate_servo_mortor' },\n                paramsKeyMap: { cubeno: 0, DEGREE: 1 },\n                class: 'PingpongG4_motor',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG4._getCubeNoFromBlock(script);\n                        let angle = script.getNumberValue('DEGREE', script);\n\n                        angle = Math.min(Math.max(angle, 0), 180);\n\n                        const opt = [2, 0, angle, 1];\n                        const packet = Entry.PingpongG4.makePacket(OPCODE.SERVO, 0x00, cubeId, opt);\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g4_set_dot_pixel: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '0' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '0' },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.pingpong_dot_on, 1],\n                            [Lang.Blocks.pingpong_dot_off, 0],\n                        ],\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null, null, null],\n                    type: 'pingpong_g4_set_dot_pixel',\n                },\n                paramsKeyMap: { cubeno: 0, X: 1, Y: 2, onoff: 3 },\n                class: 'PingpongG4_peripheral_LED',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG4._getCubeNoFromBlock(script);\n                        let dotX = script.getNumberValue('X', script);\n                        let dotY = script.getNumberValue('Y', script);\n                        const onoff = script.getNumberField('onoff', script);\n\n                        dotX = Math.min(Math.max(dotX, 0), 7);\n                        dotY = Math.min(Math.max(dotY, 0), 7);\n\n                        const opt = [0x70, dotY, dotX, onoff];\n                        const packet = Entry.PingpongG4.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe1,\n                            cubeId,\n                            opt\n                        );\n                        return [packet];\n                    });\n                },\n            },\n            pingpong_g4_set_dot_string: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    { type: 'Block', accept: 'string', value: 'Hello!' },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '2' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [null, null], type: 'pingpong_g4_set_dot_string' },\n                paramsKeyMap: { cubeno: 0, STR: 1, DURATION: 2 },\n                class: 'PingpongG4_peripheral_LED',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG4._getCubeNoFromBlock(script);\n                        const str = script.getStringValue('STR', script);\n                        const duration = script.getNumberValue('DURATION', script);\n\n                        let period = Math.round((duration * 100) / (str.length * 8));\n                        period = Math.min(Math.max(period, 1), 200);\n\n                        const opt = Buffer.concat([\n                            Buffer.from([0x70, period, 0]),\n                            Buffer.from(str.substring(0, 20)),\n                        ]);\n\n                        const packet = Entry.PingpongG4.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe3,\n                            cubeId,\n                            opt\n                        );\n                        const waitTime = period * str.length * 8 * 10 + 400; // add wait for 400ms\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g4_set_dot_clear: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g4_set_dot_clear' },\n                paramsKeyMap: { cubeno: 0 },\n                class: 'PingpongG4_peripheral_LED',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId = Entry.PingpongG4._getCubeNoFromBlock(script);\n                        const opt = [0x70, 1, 0, ' '];\n                        const packet = Entry.PingpongG4.makePacket(\n                            OPCODE.LEDMATRIX,\n                            0xe3,\n                            cubeId,\n                            opt\n                        );\n                        return [packet, 400];\n                    });\n                },\n            },\n            pingpong_g4_playNoteForBeats: {\n                //'%1 큐브의 %2 번 음을 %3 박자로 연주하기 %4',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g4_playNoteForBeats' },\n                paramsKeyMap: { CUBEID: 0, NOTE: 1, BEATS: 2 },\n                class: 'PingpongG4_Music',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId = script.getNumberField('CUBEID');\n                        const NOTE = script.getNumberField('NOTE', script);\n                        const BEATS = script.getNumberValue('BEATS', script);\n\n                        const cBeats = Entry.PingpongG4._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG4._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30; //XXX\n                        const arr = Entry.PingpongG4.makeMusicNotePacket(cubeId, NOTE, durationSec);\n                        const packet = Buffer.from(arr);\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g4_playChordForBeats: {\n                //'%1 큐브 %2, %3 큐브 %4, %5 큐브 %6 %7 박자로 연주하기 %8',\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 0,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 1,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_g4_cube_id,\n                        value: 2,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: Lang.Blocks.pingpong_opts_music_notes,\n                        value: 48,\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: { params: [], type: 'pingpong_g4_playChordForBeats' },\n                paramsKeyMap: {\n                    CUBEID_1: 0,\n                    NOTE_1: 1,\n                    CUBEID_2: 2,\n                    NOTE_2: 3,\n                    CUBEID_3: 4,\n                    NOTE_3: 5,\n                    BEATS: 6,\n                },\n                class: 'PingpongG4_Music',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const cubeId1 = script.getNumberField('CUBEID_1');\n                        const cubeId2 = script.getNumberField('CUBEID_2');\n                        const cubeId3 = script.getNumberField('CUBEID_3');\n                        const NOTE1 = script.getNumberField('NOTE_1', script);\n                        const NOTE2 = script.getNumberField('NOTE_2', script);\n                        const NOTE3 = script.getNumberField('NOTE_3', script);\n\n                        const BEATS = script.getNumberValue('BEATS', script);\n                        const cBeats = Entry.PingpongG4._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG4._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30;\n\n                        const arr1 = Entry.PingpongG4.makeMusicNotePacket(\n                            cubeId1,\n                            NOTE1,\n                            durationSec\n                        );\n                        const arr2 = Entry.PingpongG4.makeMusicNotePacket(\n                            cubeId2,\n                            NOTE2,\n                            durationSec\n                        );\n                        const arr3 = Entry.PingpongG4.makeMusicNotePacket(\n                            cubeId3,\n                            NOTE3,\n                            durationSec\n                        );\n\n                        const packet = Entry.PingpongG4.makeAggregatePacket(\n                            OPCODE.MUSIC,\n                            0xa2,\n                            [arr1, arr2, arr3],\n                            [0, 0]\n                        );\n\n                        return [packet, waitTime];\n                    });\n                },\n            },\n            pingpong_g4_restForBeats: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '1' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g4_restForBeats' },\n                paramsKeyMap: { BEATS: 0 },\n                class: 'PingpongG4_Music',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.postCallReturn(script, () => {\n                        const BEATS = script.getNumberValue('BEATS', script);\n\n                        const cBeats = Entry.PingpongG4._clampBeats(BEATS);\n                        const durationSec = Entry.PingpongG4._beatsToDuration(cBeats);\n\n                        const waitTime = durationSec * 10 + 30;\n\n                        //XXX\n                        return [null, waitTime];\n                    });\n                },\n            },\n            pingpong_g4_setTempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                params: [\n                    { type: 'Block', accept: 'string', defaultType: 'number', value: '60' },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: { params: [], type: 'pingpong_g4_setTempo' },\n                paramsKeyMap: { TEMPO: 0 },\n                class: 'PingpongG4_Music',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    let tempo = script.getNumberValue('TEMPO', script);\n                    Entry.PingpongG4.tempo = Entry.PingpongG4._clampTempo(tempo);\n                    return script.callReturn();\n                },\n            },\n            pingpong_g4_getTempo: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                params: [],\n                def: { params: [], type: 'pingpong_g4_getTempo' },\n                paramsKeyMap: {},\n                class: 'PingpongG4_Music',\n                isNotFor: ['PingpongG4'],\n                func(sprite, script) {\n                    return Entry.PingpongG4.tempo;\n                },\n            },\n        };\n    }\n\n    setLanguage() {\n        return {\n            ko: {\n                template: {\n                    pingpong_g4_when_button_pressed: '%1 %2 큐브 버튼을 눌렀을 때',\n                    pingpong_g4_when_tilted: '%1 %2 큐브를 %3로 기울였을 때',\n                    pingpong_g4_is_button_pressed: '%1 큐브 버튼이 눌렸는가?',\n                    pingpong_g4_is_tilted: '%1 큐브가 %2로 기울어졌는가?',\n                    pingpong_g4_is_top_shape: '%1 큐브의 윗면에 %2 모양이 있는가?',\n                    pingpong_g4_get_tilt_value: '%1 큐브의 %2 방향 기울기',\n                    pingpong_g4_get_sensor_value: '%1 큐브의 %2 센서값',\n                    pingpong_g4_multi_motor_rotate:\n                        '모터1은 %1방향 %2도, 모터2는 %3방향 %4도, ' +\n                        '모터3은 %5방향 %6도, 모터4는 %7방향 %8도 회전하기 %9',\n                    pingpong_g4_motor_rotate: '%1 모터를 %2 방향으로 %3 도 회전하기 %4',\n                    pingpong_g4_start_multi_motor_rotate:\n                        '모터1 속도를 %1, 모터2 속도를 %2, 모터3 속도를 %3, 모터4 속도를 %4으로 계속 회전하기 %5',\n                    pingpong_g4_start_motor_rotate: '%1 모터의 속도를 %2으로 계속 회전하기 %3',\n                    pingpong_g4_stop_motor_rotate: '%1 모터 멈추기 %2',\n                    pingpong_g4_set_dot_pixel: '%1 번째 큐브의 도트 X:%2 Y:%3 %4 %5',\n                    pingpong_g4_set_dot_string:\n                        '%1 번째 큐브에 도트 문자열 %2 %3초동안 보여주기 %4',\n                    pingpong_g4_set_dot_clear: '%1 번째 큐브의 화면 지우기 %2',\n                    pingpong_g4_rotate_servo_mortor: '%1 번째 큐브의 서보모터 %2도로 설정하기 %3',\n                    pingpong_g4_playNoteForBeats: '%1 큐브의 %2 음을 %3 박자로 연주하기 %4',\n                    pingpong_g4_playChordForBeats:\n                        '%1 큐브 %2, %3 큐브 %4, %5 큐브 %6 %7 박자로 연주하기 %8',\n                    pingpong_g4_restForBeats: '%1 박자 쉬기 %2',\n                    pingpong_g4_setTempo: '악보 빠르기를 %1 으로 정하기 %2',\n                    pingpong_g4_getTempo: '악보 빠르기',\n                },\n                Blocks: {\n                    ...this.lang_defblock.ko,\n\n                    pingpong_g4_cube_id: [\n                        ['1번', 0],\n                        ['2번', 1],\n                        ['3번', 2],\n                        ['4번', 3],\n                    ],\n                    pingpong_g4_cube_all: [\n                        ['1번', 0],\n                        ['2번', 1],\n                        ['3번', 2],\n                        ['4번', 3],\n                        ['모든', -1],\n                    ],\n                },\n            },\n            en: {\n                template: {\n                    pingpong_g4_when_button_pressed: '%1 %2 cube button pressed',\n                    pingpong_g4_when_tilted: '%1 %2 cube tilted to %3',\n                    pingpong_g4_is_button_pressed: '%1 cube button pressed?',\n                    pingpong_g4_is_tilted: '%1 cube tilted to %2',\n                    pingpong_g4_is_top_shape: '%1 cube shown %2 in top view?',\n                    pingpong_g4_get_tilt_value: '%1 cube tilt angle to %2',\n                    pingpong_g4_get_sensor_value: '%1 cube read sensor %2',\n                    pingpong_g4_multi_motor_rotate:\n                        'rotate motor1 %2 degrees %1, motor2 %4 degrees %3, ' +\n                        'motor3 %6 degrees %5, motor4 %8 degrees %7 %9',\n                    pingpong_g4_motor_rotate: 'rotate %2 degrees %1 %3',\n                    pingpong_g4_start_multi_motor_rotate:\n                        'set motor1 speed to %1, motor2 speed to %2, ' +\n                        'motor3 speed to %3, motor3 speed to %4, motor4 speed to %5 %6',\n                    pingpong_g4_start_motor_rotate: 'set motor speed to %1 %2',\n                    pingpong_g4_stop_motor_rotate: 'stop motor rotate %1',\n                    pingpong_g4_rotate_servo_mortor: 'set servo mortor to %1 degrees %2',\n                    pingpong_g4_set_dot_pixel: '%1 cube set DOT X:%2 Y:%3 %4 %5',\n                    pingpong_g4_set_dot_string:\n                        'print %1 cube string %2 during %3 seconds to DOT %4',\n                    pingpong_g4_set_dot_clear: '%1 cube clear DOT %2',\n                    pingpong_g4_playNoteForBeats: '%1 cube play note %2 for %3 beats %4',\n                    pingpong_g4_playChordForBeats:\n                        '%1 cube %2, %3 cube %4, %5 cube %6 for %7 beats %8',\n                    pingpong_g4_restForBeats: 'rest for %1 beats %2',\n                    pingpong_g4_setTempo: 'set tempo to %1 %2',\n                    pingpong_g4_getTempo: 'tempo',\n                },\n                Blocks: {\n                    ...this.lang_defblock.en,\n\n                    pingpong_g4_cube_id: [\n                        ['1st', 0],\n                        ['2nd', 1],\n                        ['3rd', 2],\n                        ['4th', 3],\n                    ],\n                    pingpong_g4_cube_all: [\n                        ['1st', 0],\n                        ['2nd', 1],\n                        ['3rd', 2],\n                        ['4th', 3],\n                        ['All', -1],\n                    ],\n                },\n            },\n        };\n    }\n})();\n\nmodule.exports = [Entry.PingpongG2, Entry.PingpongG3, Entry.PingpongG4];\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_playcode.js",
    "content": "﻿'use strict';\n\nEntry.playcode = {\n    id: '1E.1',\n    name: 'playcode',\n    url: 'http://www.playcode.kr/product',\n    imageName: 'playcode.png',\n    title: {\n        en: 'playcode',\n        ko: '플레이코드',\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    toByte: function(data) {\n        switch (data) {\n            case ' ':\n                data = 32;\n                break;\n            case '!':\n                data = 33;\n                break;\n            case '\"':\n                data = 34;\n                break;\n            case '#':\n                data = 35;\n                break;\n            case '$':\n                data = 36;\n                break;\n            case '%':\n                data = 37;\n                break;\n            case '&':\n                data = 38;\n                break;\n            case \"'\":\n                data = 39;\n                break;\n            case '(':\n                data = 40;\n                break;\n            case ')':\n                data = 41;\n                break;\n            case '*':\n                data = 42;\n                break;\n            case '+':\n                data = 43;\n                break;\n            case ',':\n                data = 44;\n                break;\n            case '-':\n                data = 45;\n                break;\n            case '.':\n                data = 46;\n                break;\n            case '/':\n                data = 47;\n                break;\n            case '0':\n                data = 48;\n                break;\n            case '1':\n                data = 49;\n                break;\n            case '2':\n                data = 50;\n                break;\n            case '3':\n                data = 51;\n                break;\n            case '4':\n                data = 52;\n                break;\n            case '5':\n                data = 53;\n                break;\n            case '6':\n                data = 54;\n                break;\n            case '7':\n                data = 55;\n                break;\n            case '8':\n                data = 56;\n                break;\n            case '9':\n                data = 57;\n                break;\n            case ':':\n                data = 58;\n                break;\n            case ';':\n                data = 59;\n                break;\n            case '<':\n                data = 60;\n                break;\n            case '=':\n                data = 61;\n                break;\n            case '>':\n                data = 62;\n                break;\n            case '?':\n                data = 63;\n                break;\n            case '@':\n                data = 64;\n                break;\n            case 'A':\n                data = 65;\n                break;\n            case 'B':\n                data = 66;\n                break;\n            case 'C':\n                data = 67;\n                break;\n            case 'D':\n                data = 68;\n                break;\n            case 'E':\n                data = 69;\n                break;\n            case 'F':\n                data = 70;\n                break;\n            case 'G':\n                data = 71;\n                break;\n            case 'H':\n                data = 72;\n                break;\n            case 'I':\n                data = 73;\n                break;\n            case 'J':\n                data = 74;\n                break;\n            case 'K':\n                data = 75;\n                break;\n            case 'L':\n                data = 76;\n                break;\n            case 'M':\n                data = 77;\n                break;\n            case 'N':\n                data = 78;\n                break;\n            case 'O':\n                data = 79;\n                break;\n            case 'P':\n                data = 80;\n                break;\n            case 'Q':\n                data = 81;\n                break;\n            case 'R':\n                data = 82;\n                break;\n            case 'S':\n                data = 83;\n                break;\n            case 'T':\n                data = 84;\n                break;\n            case 'U':\n                data = 85;\n                break;\n            case 'V':\n                data = 86;\n                break;\n            case 'W':\n                data = 87;\n                break;\n            case 'X':\n                data = 88;\n                break;\n            case 'Y':\n                data = 89;\n                break;\n            case 'Z':\n                data = 90;\n                break;\n            case '[':\n                data = 91;\n                break;\n            case '\\\\':\n                data = 92;\n                break;\n            case ']':\n                data = 93;\n                break;\n            case '^':\n                data = 94;\n                break;\n            case '_':\n                data = 95;\n                break;\n            case '`':\n                data = 96;\n                break;\n            case 'a':\n                data = 97;\n                break;\n            case 'b':\n                data = 98;\n                break;\n            case 'c':\n                data = 99;\n                break;\n            case 'd':\n                data = 100;\n                break;\n            case 'e':\n                data = 101;\n                break;\n            case 'f':\n                data = 102;\n                break;\n            case 'g':\n                data = 103;\n                break;\n            case 'h':\n                data = 104;\n                break;\n            case 'i':\n                data = 105;\n                break;\n            case 'j':\n                data = 106;\n                break;\n            case 'k':\n                data = 107;\n                break;\n            case 'l':\n                data = 108;\n                break;\n            case 'm':\n                data = 109;\n                break;\n            case 'n':\n                data = 110;\n                break;\n            case 'o':\n                data = 111;\n                break;\n            case 'p':\n                data = 112;\n                break;\n            case 'q':\n                data = 113;\n                break;\n            case 'r':\n                data = 114;\n                break;\n            case 's':\n                data = 115;\n                break;\n            case 't':\n                data = 116;\n                break;\n            case 'u':\n                data = 117;\n                break;\n            case 'v':\n                data = 118;\n                break;\n            case 'w':\n                data = 119;\n                break;\n            case 'x':\n                data = 120;\n                break;\n            case 'y':\n                data = 121;\n                break;\n            case 'z':\n                data = 122;\n                break;\n            case '{':\n                data = 123;\n                break;\n            case '|':\n                data = 124;\n                break;\n            case '}':\n                data = 125;\n                break;\n            case '~':\n                data = 126;\n                break;\n        }\n\n        return data;\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        LIGHT: 9,\n        MICROPHONE: 10,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    directionTable: {\n        Forward: 0,\n        Backward: 1,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.playcode.blockMenuBlocks = [\n    // playcode Added 2018-01-02\n    'playcode_get_light_value',\n    'playcode_get_mic_value',\n    'playcode_gpio',\n    'playcode_servo',\n    'playcode_speed',\n    // playcode Added 2018-01-02\n];\n\nEntry.playcode.getBlocks = function() {\n    return {\n        //region playcode\n        playcode_port_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        playcode_first_port_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [['1', '1'], ['2', '2'], ['3', '3'], ['4', '4']],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n        playcode_get_light_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '빛센서 : %1 포트 값',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'playcode_first_port_list',\n                    },\n                ],\n                type: 'playcode_get_light_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'playcode_get',\n            isNotFor: ['playcode'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.LIGHT;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.playcode.sensorTypes.LIGHT] = {\n                    port: [port],\n                    data: 1,\n                    time: new Date().getTime(),\n                };\n\n                return ANALOG;\n            },\n            syntax: { js: [], py: ['playcode.get_analog_value(%1)'] },\n        },\n        playcode_get_mic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: '마이크센서 : %1 포트 값',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'playcode_first_port_list',\n                    },\n                ],\n                type: 'playcode_get_mic_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'playcode_get',\n            isNotFor: ['playcode'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.MIC;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n\n                Entry.hw.sendQueue['GET'][Entry.playcode.sensorTypes.MICROPHONE] = {\n                    port: [port],\n                    data: 1,\n                    time: new Date().getTime(),\n                };\n\n                return ANALOG;\n            },\n            syntax: { js: [], py: ['playcode.get_analog_value(%1)'] },\n        },\n        playcode_gpio: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            template: 'GPIO : %1포트에 %2 보내기 %3',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'playcode_port_list',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'playcode_gpio',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'playcode_set',\n            isNotFor: ['playcode'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var operator = script.getField('OPERATOR');\n                var value = operator == 'on' ? 1 : 0;\n\n                var sq = Entry.hw.sendQueue;\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.playcode.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['playcode.playcode_gpio(%1)'] },\n        },\n        playcode_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: 'Servo : %1포트에 %2 보내기 %3',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'playcode_first_port_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'playcode_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'playcode_set',\n            isNotFor: ['playcode'],\n\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 180);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.playcode.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        playcode_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            template: 'Speed : %1포트에 %2 보내기 %3',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'playcode_first_port_list',\n                        params: [1],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'playcode_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'playcode_set',\n            isNotFor: ['playcode'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                value = Math.round(value);\n                value = Math.min(value, 255);\n                value = Math.max(value, 0);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.playcode.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        //endregion playcode\n    };\n};\n\nmodule.exports = Entry.playcode;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_plrun.js",
    "content": "'use strict';\n\nEntry.plrun = {\n    id: '2A.2',\n    name: 'plrun',\n    url: 'http://robotron.co.kr',\n    imageName: 'plrun.png',\n    title: {\n        en: 'coding plrun',\n        ko: '코딩 플런',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        LED: 9,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    direction: {\n        CENTER: 0,\n        UP: 1,\n        LEFT: 2,\n        RIGHT: 3,\n        DOWN: 4,\n        LEFT_UP: 5,\n        LEFT_DOWN: 6,\n        RIGHT_UP: 7,\n        RIGHT_DOWN: 8,\n    },\n    color: {\n        RED: [1.0, 0.0, 0.0],\n        GREEN: [0.0, 1.0, 0.0],\n        BLUE: [0.0, 0.0, 1.0],\n        TEAL: [0.0, 0.21, 0.26],\n        PINK: [1.0, 0.0, 0.56],\n        YELLOW: [1.0, 1.0, 0.0],\n        WHITE: [1.0, 1.0, 1.0],\n    },\n    move: {\n        FORWARD: [1.0, 1.0],\n        BACKWARD: [-1.0, -1.0],\n        LEFT: [0.5, 1.0],\n        RIGHT: [1.0, 0.5],\n    },\n};\nEntry.plrun.blockMenuBlocks = [\n    'get_ultrasonic',\n    'get_soil',\n    'get_analog_value',\n    'get_analog',\n    'get_digital',\n    'get_joystick',\n    'get_joystick_button',\n    'get_button',\n    'set_vibrator',\n    'set_fan',\n    'set_led_color',\n    'set_led',\n    'stop_led',\n    'set_audio_octave',\n    'set_audio_freq',\n    'stop_audio',\n\n    /*\n    'set_servor',    \n    'set_digital',\n    'set_motor',\n    'stop_motor',\n    'set_move',\n    'stop_move',\n    */\n];\nEntry.plrun.getBlocks = function() {\n    return {\n        set_vibrator: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.plrun_set_on, 'on'], [Lang.Blocks.plrun_set_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'set_vibrator',\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const operator = script.getField('OPERATOR');\n                const value = operator == 'on' ? 255 : 0;\n                Entry.hw.setDigitalPortValue(2, value);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[2] = {\n                    type: Entry.plrun.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        set_fan: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[0, 0], [20, 50], [40, 100], [60, 150], [80, 200], [100, 250]],\n                    value: 150,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'set_fan',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                let value = script.getField('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[3] = {\n                    type: Entry.plrun.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        set_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_motor_left, 0],\n                        [Lang.Blocks.plrun_motor_right, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[0, 0], [20, 50], [40, 100], [60, 150], [80, 200], [100, 250]],\n                    value: 150,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_motor_forward, 0],\n                        [Lang.Blocks.plrun_motor_reverse, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'set_motor',\n            },\n            paramsKeyMap: {\n                WHICH: 0,\n                SPEED: 1,\n                DIRECTION: 2,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const which = script.getField('WHICH', script);\n                const speed = script.getField('SPEED', script);\n                const direction = script.getField('DIRECTION', script);\n                const port = which == 0 ? [4, 5] : [7, 6];\n                const value = direction == 0 ? (which == 0 ? 0 : 1) : which == 0 ? 1 : 0;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port[0]] = {\n                    type: Entry.plrun.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port[1]] = {\n                    type: Entry.plrun.sensorTypes.PWM,\n                    data: speed,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        stop_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_motor_left, 0],\n                        [Lang.Blocks.plrun_motor_right, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'stop_motor',\n            },\n            paramsKeyMap: {\n                WHICH: 0,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const which = script.getField('WHICH', script);\n                const port = which == 0 ? [4, 5] : [7, 6];\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port[1]] = {\n                    type: Entry.plrun.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        set_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[0, 0], [20, 50], [40, 100], [60, 150], [80, 200], [100, 250]],\n                    value: 150,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_move_forward, Entry.plrun.move.FORWARD],\n                        [Lang.Blocks.plrun_move_backward, Entry.plrun.move.BACKWARD],\n                        [Lang.Blocks.plrun_move_left, Entry.plrun.move.LEFT],\n                        [Lang.Blocks.plrun_move_right, Entry.plrun.move.RIGHT],\n                    ],\n                    value: Entry.plrun.move.FORWARD,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'set_move',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n                DIRECTION: 1,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const direction = script.getField('DIRECTION', script);\n                const speed = script.getField('SPEED', script);\n                const value = [direction[0] * speed, direction[1] * speed];\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[4] = {\n                    type: Entry.plrun.sensorTypes.DIGITAL,\n                    data: value[0] > 0 ? 0 : 1,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[5] = {\n                    type: Entry.plrun.sensorTypes.PWM,\n                    data: Math.abs(value[0]),\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[7] = {\n                    type: Entry.plrun.sensorTypes.DIGITAL,\n                    data: value[1] > 0 ? 1 : 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[6] = {\n                    type: Entry.plrun.sensorTypes.PWM,\n                    data: Math.abs(value[1]),\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        stop_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'stop_move',\n            },\n            paramsKeyMap: {},\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[5] = {\n                    type: Entry.plrun.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[6] = {\n                    type: Entry.plrun.sensorTypes.PWM,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        set_servor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'set_servor',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue = {\n                        GET: {},\n                        SET: {},\n                    };\n                }\n                Entry.hw.sendQueue.SET[11] = {\n                    type: Entry.plrun.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        set_audio_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.do_name, 1],\n                        [Lang.Blocks.do_sharp_name, 2],\n                        [Lang.Blocks.re_name, 3],\n                        [Lang.Blocks.re_sharp_name, 4],\n                        [Lang.Blocks.mi_name, 5],\n                        [Lang.Blocks.fa_name, 6],\n                        [Lang.Blocks.fa_sharp_name, 7],\n                        [Lang.Blocks.sol_name, 8],\n                        [Lang.Blocks.sol_sharp_name, 9],\n                        [Lang.Blocks.la_name, 10],\n                        [Lang.Blocks.la_sharp_name, 11],\n                        [Lang.Blocks.si_name, 12],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7]],\n                    value: 4,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_buzzer_wn, 1000],\n                        [Lang.Blocks.plrun_buzzer_hn, 500],\n                        [Lang.Blocks.plrun_buzzer_qn, 250],\n                        [Lang.Blocks.plrun_buzzer_en, 125],\n                        [Lang.Blocks.plrun_buzzer_sn, 63],\n                        [Lang.Blocks.plrun_buzzer_tn, 31],\n                    ],\n                    value: 250,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'set_audio_octave',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const note = script.getField('NOTE', script);\n                    const octave = script.getField('OCTAVE', script) - 1;\n                    const duration = script.getField('DURATION', script);\n                    const value = Entry.plrun.toneMap[note][octave];\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue = {\n                            GET: {},\n                            SET: {},\n                        };\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue.SET[8] = {\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue.SET[8] = {\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        set_audio_freq: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 3000,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'set_audio_freq',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n                SECOND: 1,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const value = script.getNumberValue('HZ', script);\n                const duration = script.getNumberValue('SECOND', script) * 1000;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue = {\n                        GET: {},\n                        SET: {},\n                    };\n                }\n                Entry.hw.sendQueue.SET[8] = {\n                    type: Entry.ArduinoExt.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        stop_audio: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_buzzer_wn, 1000],\n                        [Lang.Blocks.plrun_buzzer_hn, 500],\n                        [Lang.Blocks.plrun_buzzer_qn, 250],\n                        [Lang.Blocks.plrun_buzzer_en, 125],\n                        [Lang.Blocks.plrun_buzzer_sn, 63],\n                        [Lang.Blocks.plrun_buzzer_tn, 31],\n                    ],\n                    value: 250,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'stop_audio',\n            },\n            paramsKeyMap: {\n                DURATION: 0,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const duration = script.getField('DURATION', script);\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue = {\n                            GET: {},\n                            SET: {},\n                        };\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue.SET[8] = {\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\n                        data: {\n                            value: 0,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue.SET[8] = {\n                        type: Entry.ArduinoExt.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        get_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'get_ultrasonic',\n            },\n            paramsKeyMap: {},\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[9];\n                delete Entry.hw.sendQueue.SET[10];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.plrun.sensorTypes.ULTRASONIC] = {\n                    port: [10, 9],\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n        },\n        get_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_joystick_up, Entry.plrun.direction.UP],\n                        [Lang.Blocks.plrun_joystick_down, Entry.plrun.direction.DOWN],\n                        [Lang.Blocks.plrun_joystick_left, Entry.plrun.direction.LEFT],\n                        [Lang.Blocks.plrun_joystick_right, Entry.plrun.direction.RIGHT],\n                        [Lang.Blocks.plrun_joystick_left_up, Entry.plrun.direction.LEFT_UP],\n                        [Lang.Blocks.plrun_joystick_left_down, Entry.plrun.direction.LEFT_DOWN],\n                        [Lang.Blocks.plrun_joystick_right_up, Entry.plrun.direction.RIGHT_UP],\n                        [Lang.Blocks.plrun_joystick_right_down, Entry.plrun.direction.RIGHT_DOWN],\n                        [Lang.Blocks.plrun_joystick_center, Entry.plrun.direction.CENTER],\n                    ],\n                    value: Entry.plrun.direction.CENTER,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'get_joystick',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const direction = script.getField('DIRECTION', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n\n                const getValue = function(w) {\n                    return ANALOG[w] == 0 ? 0 : ANALOG[w] == 1023 ? 2 : 1;\n                };\n\n                if (\n                    direction == Entry.plrun.direction.CENTER &&\n                    getValue(0) == 1 &&\n                    getValue(1) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.plrun.direction.DOWN &&\n                    getValue(0) == 1 &&\n                    getValue(1) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.plrun.direction.LEFT &&\n                    getValue(0) == 0 &&\n                    getValue(1) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.plrun.direction.LEFT_DOWN &&\n                    getValue(0) == 0 &&\n                    getValue(1) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.plrun.direction.LEFT_UP &&\n                    getValue(0) == 0 &&\n                    getValue(1) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.plrun.direction.RIGHT &&\n                    getValue(0) == 2 &&\n                    getValue(1) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.plrun.direction.RIGHT_DOWN &&\n                    getValue(0) == 2 &&\n                    getValue(1) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.plrun.direction.RIGHT_UP &&\n                    getValue(0) == 2 &&\n                    getValue(1) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.plrun.direction.UP &&\n                    getValue(0) == 1 &&\n                    getValue(1) == 0\n                ) {\n                    return 1;\n                }\n\n                return 0;\n            },\n        },\n        get_joystick_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'get_joystick_button',\n            },\n            paramsKeyMap: {},\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[1] && ANALOG[2] != 0 : 0;\n            },\n        },\n        get_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_button_blue, 6],\n                        [Lang.Blocks.plrun_button_red, 7],\n                    ],\n                    value: 6,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'get_button',\n            },\n            paramsKeyMap: {\n                WHICH: 0,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const which = script.getField('WHICH', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[which] != 0 : 0;\n            },\n        },\n        set_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 100,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 100,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 100,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'set_led',\n            },\n            paramsKeyMap: {\n                R: 0,\n                G: 1,\n                B: 2,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    let r = script.getNumberValue('R', script);\n                    let g = script.getNumberValue('G', script);\n                    let b = script.getNumberValue('B', script);\n\n                    r = Math.max(Math.min(r, 255), 0);\n                    g = Math.max(Math.min(g, 255), 0);\n                    b = Math.max(Math.min(b, 255), 0);\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue = {\n                            GET: {},\n                            SET: {},\n                        };\n                    }\n\n                    Entry.hw.sendQueue.SET[13] = {\n                        type: Entry.plrun.sensorTypes.LED,\n                        data: {\n                            r,\n                            g,\n                            b,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, 50);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        set_led_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.plrun_color_red, 'RED'],\n                        [Lang.Blocks.plrun_color_green, 'GREEN'],\n                        [Lang.Blocks.plrun_color_blue, 'BLUE'],\n                        [Lang.Blocks.plrun_color_teal, 'TEAL'],\n                        [Lang.Blocks.plrun_color_pink, 'PINK'],\n                        [Lang.Blocks.plrun_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.plrun_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 100,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'set_led_color',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const color_type = script.getField('COLOR', script);\n                    const color = Entry.plrun.color[color_type];\n                    let brightness = script.getNumberValue('BRIGHTNESS', script);\n\n                    brightness = Math.max(Math.min(brightness, 255), 0);\n\n                    let r = parseInt(color[0] * brightness);\n                    let g = parseInt(color[1] * brightness);\n                    let b = parseInt(color[2] * brightness);\n                    r = Math.max(Math.min(r, 255), 0);\n                    g = Math.max(Math.min(g, 255), 0);\n                    b = Math.max(Math.min(b, 255), 0);\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue = {\n                            GET: {},\n                            SET: {},\n                        };\n                    }\n\n                    Entry.hw.sendQueue.SET[13] = {\n                        type: Entry.plrun.sensorTypes.LED,\n                        data: {\n                            r,\n                            g,\n                            b,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, 50);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        stop_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'stop_led',\n            },\n            paramsKeyMap: {},\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue = {\n                        GET: {},\n                        SET: {},\n                    };\n                }\n\n                Entry.hw.sendQueue.SET[13] = {\n                    type: Entry.plrun.sensorTypes.LED,\n                    data: {\n                        r: 0,\n                        g: 0,\n                        b: 0,\n                    },\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n        },\n        get_soil: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'get_soil',\n            },\n            paramsKeyMap: {},\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[3] || 0 : 0;\n            },\n        },\n        get_analog: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'get_analog',\n            },\n            paramsKeyMap: {},\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[5] || 0 : 0;\n            },\n        },\n        get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[1, 11], [2, 12]],\n                    value: 11,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const port = script.getField('PORT', script);\n                const DIGITAL = Entry.hw.portData.DIGITAL;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.plrun.sensorTypes.DIGITAL] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                return DIGITAL ? DIGITAL[port] || 0 : 0;\n            },\n        },\n        set_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[11, 11], [12, 12]],\n                    value: 11,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.plrun_set_on, 'on'], [Lang.Blocks.plrun_set_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'set_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const port = script.getField('PORT', script);\n                const operator = script.getField('OPERATOR');\n                const value = operator == 'on' ? 255 : 0;\n                Entry.hw.setDigitalPortValue(port, value);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.plrun.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n        },\n        get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'get_analog_value',\n            },\n            paramsKeyMap: {},\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func(sprite, script) {\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[4] || 0 : 0;\n            },\n        },\n        /*\n        plrun_set_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['M0', 'M0'],\n                        ['M1', 'M1'],\n                    ],\n                    value: 'M0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞', 'forward'],\n                        ['뒤', 'backward'],\n                    ],\n                    value: 'forward',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    value: 255,\n                    accept: 'number',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'plrun_set_motor',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n            },\n            class: 'plrun',\n            isNotFor: ['plrun'],\n            func: function(sprite, script) {\n                var pin1 = 0;\n                var pin2 = 0;\n                var mode = script.getField('MODE');\n                var direction = script.getField('DIRECTION');\n                var value1 = 0;\n                var value2 = script.getNumberValue('VALUE');\n\n                if (mode == 'M0') {\n                    pin1 = 4;\n                    pin2 = 5;\n                    value1 = direction == 'forward' ? 0 : 1;\n                } else {\n                    pin1 = 7;\n                    pin2 = 6;\n                    value1 = direction == 'forward' ? 1 : 0;\n                }\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][pin1] = {\n                    type: Entry.plrun.pinTypes.DIGITAL,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue['SET'][pin2] = {\n                    type: Entry.plrun.pinTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];\n                }\n                Entry.hw.sendQueue.digitalPinMode[pin1] = Entry.plrun.pinTypes.DIGITAL;\n                Entry.hw.sendQueue.digitalPinMode[pin2] = Entry.plrun.pinTypes.PWM;\n\n                Entry.hw.setDigitalPortValue(pin1, value1);\n                Entry.hw.setDigitalPortValue(pin2, value2);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        */\n    };\n};\nEntry.plrun.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n                plrun_set_on: '켜기',\n                plrun_set_off: '끄기',\n                plrun_color_red: '빨간',\n                plrun_color_green: '초록',\n                plrun_color_blue: '파란',\n                plrun_color_teal: '청록',\n                plrun_color_pink: '분홍',\n                plrun_color_yellow: '노란',\n                plrun_color_white: '하얀',\n                plrun_motor_left: '왼쪽',\n                plrun_motor_right: '오른쪽',\n                plrun_motor_forward: '정방향',\n                plrun_motor_reverse: '역방향',\n                plrun_move_forward: '전진',\n                plrun_move_backward: '후진',\n                plrun_move_left: '좌회전',\n                plrun_move_right: '우회전',\n                plrun_buzzer_hn: '2분음표',\n                plrun_buzzer_qn: '4분음표',\n                plrun_buzzer_en: '8분음표',\n                plrun_buzzer_sn: '16분음표',\n                plrun_buzzer_tn: '32분음표',\n                plrun_buzzer_wn: '온음표',\n                plrun_joystick_center: '가운데',\n                plrun_joystick_down: '아래',\n                plrun_joystick_left: '왼쪽',\n                plrun_joystick_left_down: '왼쪽 아래',\n                plrun_joystick_left_up: '왼쪽 위',\n                plrun_joystick_right: '오른쪽',\n                plrun_joystick_right_down: '오른쪽 아래',\n                plrun_joystick_right_up: '오른쪽 위',\n                plrun_joystick_up: '위',\n                plrun_button_red: '빨강',\n                plrun_button_blue: '파랑',\n            },\n            template: {\n                set_vibrator: '진동 알림 %1 %2',\n                set_fan: '팬을 속도 %1(으)로 회전 시키기 %2',\n                set_servor: '서보모터의 각도를 %1도로 정하기 %2',\n                set_motor: 'DC모터 %1을 %2의 속도로 %3으로 회전하기 %4',\n                stop_motor: 'DC모터 %1을 정지하기 %2',\n                set_move: '로봇을 %1의 속도로 %2 하기 %3',\n                stop_move: '로봇 정지하기 %1',\n                set_audio_octave: '계명 %1음을 %2옥타브 %3으로 연주하기 %4',\n                set_audio_freq: '펄스 %1Hz 음을 %2초 연주하기 %3',\n                stop_audio: '%1 만큼 연주쉬기 %2',\n                get_ultrasonic: '초음파센서 값 읽기',\n                get_joystick: '조이스틱 방향이 %1 인가?',\n                get_joystick_button: '조이스틱 버튼이 눌렸는가?',\n                get_button: '%1색 버튼이 눌렸는가?',\n                set_led: '컬러 LED 켜기- 빨강%1 초록%2 파랑%3 %4',\n                set_led_color: 'LED %1색을 밝기 %2으로 켜기 %3',\n                stop_led: 'LED 끄기 %1',\n                get_soil: '토양 센서 값 읽기',\n                get_analog: '아날로그 값 읽기',\n                get_digital: '디지털 %1번 포트가 참인가?',\n                set_digital: '디지털 %1 포트에 %2 출력하기 %3',\n                get_analog_value: '가변저항 값 읽기',\n            },\n        },\n        en: {\n            Blocks: {\n                plrun_set_on: 'on',\n                plrun_set_off: 'off',\n                plrun_color_red: 'red',\n                plrun_color_green: 'green',\n                plrun_color_blue: 'blue',\n                plrun_color_teal: 'teal',\n                plrun_color_pink: 'pink',\n                plrun_color_yellow: 'yellow',\n                plrun_color_white: 'white',\n                plrun_motor_left: 'left',\n                plrun_motor_right: 'right',\n                plrun_motor_forward: 'forward',\n                plrun_motor_reverse: 'reverse',\n                plrun_move_forward: 'forward',\n                plrun_move_backward: 'backward',\n                plrun_move_left: 'left',\n                plrun_move_right: 'right',\n                plrun_buzzer_hn: 'half note',\n                plrun_buzzer_qn: 'quarter note',\n                plrun_buzzer_en: 'eighth note',\n                plrun_buzzer_sn: 'sixteenth note',\n                plrun_buzzer_tn: 'thirtysecond note',\n                plrun_buzzer_wn: 'whole note',\n                plrun_joystick_center: 'center',\n                plrun_joystick_down: 'bottom',\n                plrun_joystick_left: 'left',\n                plrun_joystick_left_down: 'left bottom',\n                plrun_joystick_left_up: 'left top',\n                plrun_joystick_right: 'right',\n                plrun_joystick_right_down: 'right bottom',\n                plrun_joystick_right_up: 'right top',\n                plrun_joystick_up: 'top',\n                plrun_button_red: 'red',\n                plrun_button_blue: 'blue',\n            },\n            template: {\n                set_vibrator: 'Set vibrator %1 %2',\n                set_fan: 'Rotating fan at %1 speed %2',\n                set_motor: 'Turn on motor %1 a %2 at speed of %3 %4',\n                stop_motor: 'Turn off motor %1 %2',\n                set_move: 'Moving robot %2 at %1 speed %3',\n                stop_move: 'Stop robot %1',\n                set_servor: 'Set servo motor angle to %1 degrees %2',\n                set_audio_octave: 'Play note %1 octave %2 beat %3 %4',\n                set_audio_freq: 'Play note %1Hz beat %3',\n                stop_audio: 'Rest audio as %1 %2',\n                get_ultrasonic: 'Get ultrasonic value',\n                get_joystick: 'Get joystick value',\n                get_joystick_button: 'Get joystick button pressed',\n                get_button: 'Get switch %1 preesed',\n                set_led: 'Turn on LED in red%1 green%2 blue%3 %4',\n                set_led_color: 'Turn on LED in %1 with %2 brightness %3',\n                stop_led: 'Turn off LED %1',\n                get_soil: 'Get soil sensor value',\n                get_analog: 'Read analog value',\n                get_digital: 'Read digital port %1',\n                set_digital: 'Write digital port %1 to value %2 %3',\n                get_analog_value: 'Read variable resistance',\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.plrun;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robico.js",
    "content": "'use strict';\n\nlet RobicoState = {\n\tSTATE_READY: 'ready',\n\tSTATE_WAIT: 'wait',\n\tSTATE_DONE: 'done',\n};\n\nEntry.Robico = {\n\tPORT_MAP: {\n\t\tseq: 0,\n\t\tcat: 0,\n\t\tact: 0,\n\t\tpcnt: 0,\n\t\tp1: 0,\n\t\tp2: 0,\n\t\tp3: 0,\n\t\tp4: 0,\n\t\tp5: 0,\n\t\tp6: 0\n\t},\n\tsetZero: function () {\n\t\tlet portMap = Entry.Robico.PORT_MAP;\n\t\tlet sq = Entry.hw.sendQueue;\n\t\tEntry.Robico.sequance = 1;\n\t\tEntry.Robico.isStarted = false;\n\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\tfor (let port in portMap) {\n\t\t\tsq[port] = portMap[port];\n\t\t}\n\t\tEntry.hw.update();\n\t},\n\tid: '24.5',\n\tname: 'Robico',\n\turl: 'https://robico.info',\n\timageName: 'robico.png',\n\ttitle: {\n\t\tko: '로비코',\n\t\ten: 'RoBico',\n\t},\n\tsequance: 1,\n\tisStarted: false,\n\tstate: RobicoState.STATE_DONE,\n};\nEntry.Robico.blockMenuBlocks = [\n\t'Robico_SensorColF',\n\t'Robico_SensorIR',\n\t'Robico_SensorDrop',\n\t'Robico_Move1',\n\t'Robico_Move2',\n\t'Robico_Wheel',\n\t'Robico_Rotate1',\n\t'Robico_Rotate2',\n\t'Robico_Stop',\n\t'Robico_Linetrace',\n\t'Robico_Ladder',\n\t'Robico_Maze',\n\t'Robico_TracingSpeed',\n\t'Robico_LightColorL',\n\t'Robico_LightColorF',\n\t'Robico_LightOff',\n\t'Robico_LightFun',\n\t'Robico_SoundNum',\n\t'Robico_SoundCol',\n\t'Robico_SoundMov',\n\t'Robico_SoundAni',\n\t'Robico_SoundEmo',\n\t'Robico_SoundGre',\n\t'Robico_SoundMis',\n\t'Robico_SoundTon',\n\t'Robico_SoundColF',\n\t'Robico_SoundRec',\n\t'Robico_Fun'\n];\nEntry.Robico.getBlocks = function () {\n\treturn {\n\t\tRobico_SensorColF: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic_boolean_field',\n\t\t\ttemplate: '바닥 색깔 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['검은색', 3],\n\t\t\t\t\t\t['빨간색', 4],\n\t\t\t\t\t\t['초록색', 5],\n\t\t\t\t\t\t['파란색', 6],\n\t\t\t\t\t\t['노란색', 7],\n\t\t\t\t\t\t['흰색', 1],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\tparams: [3],\n\t\t\t\ttype: 'Robico_SensorColF',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tisNotFor: ['Robico'],\n\t\t\tclass: 'Robico_Sensor',\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet var1 = script.getNumberField('VALUE', script);\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tif (var1 == pd.color)\n\t\t\t\t\treturn true;\n\t\t\t\treturn false;\n\t\t\t},\n\t\t},\n\t\tRobico_SensorIR: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic_boolean_field',\n\t\t\ttemplate: '%1 장애물',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞쪽', 1],\n\t\t\t\t\t\t['뒤쪽', 2],\n\t\t\t\t\t\t['앞뒤', 3],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_SensorIR',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tisNotFor: ['Robico'],\n\t\t\tclass: 'Robico_Sensor',\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet var1 = script.getNumberField('VALUE', script);\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tswitch (var1) {\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\treturn pd.ir_front_left == 1 || pd.ir_front_right == 1;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\treturn pd.ir_rear == 1;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\treturn (pd.ir_front_left == 1 || pd.ir_front_right == 1) && pd.ir_rear == 1;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t},\n\t\tRobico_Sensor6: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic_boolean_field',\n\t\t\ttemplate: '로비코 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['들림', 1],\n\t\t\t\t\t\t['내림', 2],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_Sensor6',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tisNotFor: ['Robico'],\n\t\t\tclass: 'Robico_Sensor',\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet var1 = script.getNumberField('VALUE', script);\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tswitch (var1) {\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\treturn (pd.acc & 8) > 0;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\treturn (pd.acc & 4) > 0;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t},\n\t\tRobico_SensorDrop: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic_boolean_field',\n\t\t\ttemplate: '로비코 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['들림', 1],\n\t\t\t\t\t\t['내림', 2],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_SensorDrop',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tisNotFor: ['Robico'],\n\t\t\tclass: 'Robico_Sensor',\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet var1 = script.getNumberField('VALUE', script);\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tswitch (var1) {\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\treturn pd.drop == 1;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\treturn pd.drop == 0;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t},\n\t\tRobico_DetectLine: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic_boolean_field',\n\t\t\ttemplate: '%1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['라인 감지', 1],\n\t\t\t\t\t\t['갈림길 감지', 2],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t],\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_DetectLine',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tisNotFor: ['Robico'],\n\t\t\tclass: 'Robico_Sensor',\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet var1 = script.getNumberField('VALUE', script);\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tswitch (var1) {\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\tif (pd.line)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\tif (pd.line_mode)\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t},\n\t\tRobico_Move1: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 (으)로 %2 cm만큼 %3 이동하기 %4',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 1],\n\t\t\t\t\t\t['뒤', -1],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 4],\n\t\t\t\t\t\t['보통으로', 6],\n\t\t\t\t\t\t['빠르게', 9],\n\t\t\t\t\t\t['부스터', 12],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1, 10, 6],\n\t\t\t\ttype: 'Robico_Move1',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tDISTANCE: 1,\n\t\t\t\tSPEED: 2,\n\t\t\t},\n\t\t\tclass: 'Robico_Movement',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tlet var2 = script.getNumberValue('DISTANCE', script);\n\t\t\t\tlet var3 = script.getNumberValue('SPEED', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var2 * var1 * 10;\n\t\t\t\t\tsq.p2 = var3 * 10;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.motor) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.motor) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_Move2: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 cm 거리를 %2 cm/s 속도로 이동하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [5, 5],\n\t\t\t\ttype: 'Robico_Move2',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDISTANCE: 0,\n\t\t\t\tSPEED: 1,\n\t\t\t},\n\t\t\tclass: 'Robico_Movement',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberValue('DISTANCE', script);\n\t\t\t\tlet var2 = script.getNumberValue('SPEED', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1 * 10;\n\t\t\t\t\tsq.p2 = var2 * 10;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.motor) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.motor) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_Wheel: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '왼쪽 바퀴 %1 (으)로 %2, 오른쪽 바퀴 %3 (으)로 %4 움직이기 %5',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 1],\n\t\t\t\t\t\t['뒤', -1],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 4],\n\t\t\t\t\t\t['보통으로', 6],\n\t\t\t\t\t\t['빠르게', 9],\n\t\t\t\t\t\t['부스터', 12],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 1],\n\t\t\t\t\t\t['뒤', -1],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 4],\n\t\t\t\t\t\t['보통으로', 6],\n\t\t\t\t\t\t['빠르게', 9],\n\t\t\t\t\t\t['부스터', 12],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1, 6, 1, 6],\n\t\t\t\ttype: 'Robico_Wheel',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION_L: 0,\n\t\t\t\tSPEED_L: 1,\n\t\t\t\tDIRECTION_R: 2,\n\t\t\t\tSPEED_R: 3,\n\t\t\t},\n\t\t\tclass: 'Robico_Movement',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('DIRECTION_L', script);\n\t\t\t\tlet var2 = script.getNumberField('SPEED_L', script);\n\t\t\t\tlet var3 = script.getNumberField('DIRECTION_R', script);\n\t\t\t\tlet var4 = script.getNumberField('SPEED_R', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1 * var2 * 10;\n\t\t\t\t\tsq.p2 = var3 * var4 * 10;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_Rotate1: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 으로 %2 만큼 회전하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시계 방향', 1],\n\t\t\t\t\t\t['반 시계 방향', -1],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t\tdefaultType: 'angle',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1, 90],\n\t\t\t\ttype: 'Robico_Rotate1',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tANGLE: 1,\n\t\t\t},\n\t\t\tclass: 'Robico_Movement',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tlet var2 = script.getNumberValue('ANGLE', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 3;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1 * var2;\n\t\t\t\t\tsq.p2 = 90;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.motor) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.motor) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_Rotate2: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 으로 %2 만큼 회전하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시계 방향', 1],\n\t\t\t\t\t\t['반 시계 방향', -1],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['반 바퀴', 180],\n\t\t\t\t\t\t['한 바퀴', 360],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1, 360],\n\t\t\t\ttype: 'Robico_Rotate2',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tANGLE: 1,\n\t\t\t},\n\t\t\tclass: 'Robico_Movement',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tlet var2 = script.getNumberValue('ANGLE', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 3;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1 * var2;\n\t\t\t\t\tsq.p2 = 90;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.motor) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.motor) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_Stop: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '바퀴 정지 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\ttype: 'Robico_Stop',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Robico_Movement',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 0;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_Linetrace: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '선을 따라 이동하기 %1 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시작', 0],\n\t\t\t\t\t\t['멈춤', 3],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0],\n\t\t\t\ttype: 'Robico_Linetrace',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tMODE: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Linetrace',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberValue('MODE', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_Ladder: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '선을 따라 사다리 타기 %1 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시작', 1],\n\t\t\t\t\t\t['멈춤', 3],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_Ladder',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tMODE: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Linetrace',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberValue('MODE', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_Maze: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '선을 따라 %1 으로 미로 찾기 %2 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['랜덤', 0],\n\t\t\t\t\t\t['왼쪽', 1],\n\t\t\t\t\t\t['오른쪽', 2],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시작', 2],\n\t\t\t\t\t\t['멈춤', 3],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 2],\n\t\t\t\ttype: 'Robico_Maze',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tRULE: 0,\n\t\t\t\tMODE: 1,\n\t\t\t},\n\t\t\tclass: 'Robico_Linetrace',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberValue('RULE', script);\n\t\t\t\tlet var2 = script.getNumberValue('MODE', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_WaitCL: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '다음 갈림길까지 기다리기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [],\n\t\t\t\ttype: 'Robico_WaitCL',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t},\n\t\t\tclass: 'Robico_Linetrace',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif(pd.line_mode) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_HR: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '갈림길에서 방향을 %1 으로 선택하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['좌회전', 1],\n\t\t\t\t\t\t['우회전', 2],\n\t\t\t\t\t\t['직진', 3],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_HR',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tHR: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Linetrace',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberValue('HR', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 500);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_TracingSpeed: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '선을 따라가는 속도를 %1 설정하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 0],\n\t\t\t\t\t\t['보통으로', 1],\n\t\t\t\t\t\t['빠르게', 2],\n\t\t\t\t\t\t['부스터', 3],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_TracingSpeed',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSPEED: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Linetrace',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberValue('SPEED', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 3;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 500);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_LightColorP: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 불빛 %2 색으로 켜기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['왼쪽', 5],\n\t\t\t\t\t\t['오른쪽', 10],\n\t\t\t\t\t\t['양쪽', 15],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [5, null],\n\t\t\t\ttype: 'Robico_LightColorP',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t\tCOLOR: 1,\n\t\t\t},\n\t\t\tclass: 'Robico_LEDs',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tlet var2 = script.getStringField('COLOR', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 3;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = parseInt(parseInt(var2.substr(1, 6), 16));\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_LightColorL: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 불빛 %2 색으로 켜기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['왼쪽', 5],\n\t\t\t\t\t\t['오른쪽', 10],\n\t\t\t\t\t\t['양쪽', 15],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['빨강', 0],\n\t\t\t\t\t\t['주황', 1],\n\t\t\t\t\t\t['노랑', 2],\n\t\t\t\t\t\t['초록', 3],\n\t\t\t\t\t\t['파랑', 4],\n\t\t\t\t\t\t['분홍', 5],\n\t\t\t\t\t\t['보라', 6],\n\t\t\t\t\t\t['하양', 7],\n\t\t\t\t\t\t['무작위', -1],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [15, 0],\n\t\t\t\ttype: 'Robico_LightColorL',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t\tCOLOR: 1,\n\t\t\t},\n\t\t\tclass: 'Robico_LEDs',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tlet var2 = script.getNumberField('COLOR', script);\n\t\t\t\tlet pool = new Array(0xFF0000, 0xFF4500, 0xFFFF00, 0x008000, 0x1E32FF, 0xFF00FF, 0x4B00C8, 0xFFFFFF);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 3;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tif (var2 >= 0) {\n\t\t\t\t\t\tsq.p2 = pool[var2];\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tsq.p2 = pool[Math.floor(Math.random() * 8)];\n\t\t\t\t\t}\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_LightColorF: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '바닥 색상을 불빛으로 켜기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\ttype: 'Robico_LightColorF',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Robico_LEDs',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 3;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 15;\n\t\t\t\t\tswitch (pd.color) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tsq.p1 = 0xFFFFFF;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tsq.p1 = 0x000000;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tsq.p1 = 0xFF0000;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\tsq.p1 = 0x00FF00;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\tsq.p1 = 0x0000FF;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\tsq.p1 = 0xFFFF00;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tsq.p1 = 0x010101;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_LightOff: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 불빛 끄기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['왼쪽', 5],\n\t\t\t\t\t\t['오른쪽', 10],\n\t\t\t\t\t\t['양쪽', 15],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [15],\n\t\t\t\ttype: 'Robico_LightOff',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_LEDs',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 3;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_LightFun: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '재미있는 불빛 %1 켜기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['신호등', 1],\n\t\t\t\t\t\t['무지개', 3],\n\t\t\t\t\t\t['경찰차', 4],\n\t\t\t\t\t\t['크리스마스', 2],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_LightFun',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_LEDs',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 5;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundNum: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '숫자 %1 소리 내기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['1', 311],\n\t\t\t\t\t\t['2', 312],\n\t\t\t\t\t\t['3', 313],\n\t\t\t\t\t\t['4', 314],\n\t\t\t\t\t\t['5', 315],\n\t\t\t\t\t\t['6', 316],\n\t\t\t\t\t\t['7', 317],\n\t\t\t\t\t\t['8', 318],\n\t\t\t\t\t\t['9', 319],\n\t\t\t\t\t\t['10', 320],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [311],\n\t\t\t\ttype: 'Robico_SoundNum',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundCol: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '색상 %1 소리 내기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['빨강', 301],\n\t\t\t\t\t\t['주황', 302],\n\t\t\t\t\t\t['노랑', 303],\n\t\t\t\t\t\t['초록', 304],\n\t\t\t\t\t\t['파랑', 305],\n\t\t\t\t\t\t['분홍', 308],\n\t\t\t\t\t\t['보라', 307],\n\t\t\t\t\t\t['하양', 310],\n\t\t\t\t\t\t['검정', 309],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [301],\n\t\t\t\ttype: 'Robico_SoundCol',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundMov: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '이동 %1 소리 내기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['사이렌', 23],\n\t\t\t\t\t\t['경적', 24],\n\t\t\t\t\t\t['엔진음', 25],\n\t\t\t\t\t\t['헬리콥터', 26],\n\t\t\t\t\t\t['뱃고동', 27],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [23],\n\t\t\t\ttype: 'Robico_SoundMov',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundAni: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '동물 %1 소리 내기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['개', 28],\n\t\t\t\t\t\t['호랑이', 29],\n\t\t\t\t\t\t['소', 30],\n\t\t\t\t\t\t['닭', 31],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [28],\n\t\t\t\ttype: 'Robico_SoundAni',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundEmo: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '감정 %1 소리 내기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['행복', 321],\n\t\t\t\t\t\t['슬픔', 322],\n\t\t\t\t\t\t['신남', 323],\n\t\t\t\t\t\t['지루함', 324],\n\t\t\t\t\t\t['화남', 325],\n\t\t\t\t\t\t['사랑', 326],\n\t\t\t\t\t\t['놀람', 336],\n\t\t\t\t\t\t['안심', 335],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [321],\n\t\t\t\ttype: 'Robico_SoundEmo',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundGre: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '인사 %1 소리 내기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['안녕?', 112],\n\t\t\t\t\t\t['반가워!', 332],\n\t\t\t\t\t\t['고마워!', 350],\n\t\t\t\t\t\t['도와줘!', 340],\n\t\t\t\t\t\t['걱정 마!', 342],\n\t\t\t\t\t\t['조심해!', 347],\n\t\t\t\t\t\t['맛있어!', 348],\n\t\t\t\t\t\t['응', 337],\n\t\t\t\t\t\t['아니', 338],\n\t\t\t\t\t\t['좋아', 204],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [112],\n\t\t\t\ttype: 'Robico_SoundGre',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundMis: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '미션 %1 소리 내기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시작!', 330],\n\t\t\t\t\t\t['출발!', 201],\n\t\t\t\t\t\t['도착!', 331],\n\t\t\t\t\t\t['짜잔', 334],\n\t\t\t\t\t\t['한번 해 볼까?', 341],\n\t\t\t\t\t\t['앗, 큰일이야!', 346],\n\t\t\t\t\t\t['야호!', 203],\n\t\t\t\t\t\t['박수', 22],\n\t\t\t\t\t\t['미션 성공!', 345],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [330],\n\t\t\t\ttype: 'Robico_SoundMis',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundTon: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 음을 %2 음으로 %3 초동안 연주하기 %4',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['도', 523],\n\t\t\t\t\t\t['레', 587],\n\t\t\t\t\t\t['미', 659],\n\t\t\t\t\t\t['파', 699],\n\t\t\t\t\t\t['솔', 784],\n\t\t\t\t\t\t['라', 880],\n\t\t\t\t\t\t['시', 988],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['낮은', 2],\n\t\t\t\t\t\t['높은', 4],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [523, 2, 0.5],\n\t\t\t\ttype: 'Robico_SoundTon',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t\tOCTAVE: 1,\n\t\t\t\tINTERVAL: 2,\n\t\t\t},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tlet var2 = script.getNumberField('OCTAVE', script);\n\t\t\t\tlet var3 = script.getNumberValue('INTERVAL', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1 * var2;\n\t\t\t\t\tsq.p2 = var3 * 1000;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundColF: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '바닥 색상을 소리 내기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [],\n\t\t\t\ttype: 'Robico_SoundColF',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 4;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tswitch (pd.color) {\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tsq.p1 = 310;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tsq.p1 = 309;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tsq.p1 = 301;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\tsq.p1 = 304;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\tsq.p1 = 305;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\tsq.p1 = 303;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundRec: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '녹음된 소리 내기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Robico_SoundRec',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 3;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.audio) {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tRobico_SoundStop: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '소리 끄기 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [],\n\t\t\t\ttype: 'Robico_SoundStop',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Robico_Sounds',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 4;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 0;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\n\t\tRobico_Fun: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 움직이기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['댄스', 5],\n\t\t\t\t\t\t['소용돌이', 6],\n\t\t\t\t\t\t['뒤로가기', 7],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [5],\n\t\t\t\ttype: 'Robico_Fun',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Robico_Fun',\n\t\t\tisNotFor: ['Robico'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tlet sq = Entry.hw.sendQueue;\n\t\t\t\tlet pd = Entry.hw.portData;\n\t\t\t\tlet var1 = script.getNumberField('SELECT', script);\n\t\t\t\tif (!Entry.Robico.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Robico.sequance++;\n\t\t\t\t\tsq.cat = 5;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Robico.isStarted = true;\n\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Robico.state) {\n\t\t\t\t\t\tcase RobicoState.STATE_READY:\n\t\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Robico.state = RobicoState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase RobicoState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Robico.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t};\n};\n\nmodule.exports = Entry.Robico;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robodog.js",
    "content": "'use strict';\nlet headLED_Backup = new Int8Array(16);\nlet bodyLED_Backup = new Int8Array(16);\nlet mp3ID = 0;\nEntry.RoboDog = {\n\n\n    Cmd: {\n        CMD_CHECKSUM: 5,\n        CMD_MP3TRACK: 7,\n        CMD_MP3VOLUME: 8,\n        CMD_EXTSERVO: 12,\n        CMD_SERVOSPEED: 13,\n        CMD_LEDTYPE: 14,\n        CMD_TYPE: 15,\n        CMD_GESTURE: 16,\n        CMD_LEG0: 16,\n        CMD_LEG1: 17,\n        CMD_LEG2: 18,\n        CMD_LEG3: 19,\n        CMD_MOVEVEL: 20,\n        CMD_DEG_VEL:21,\n        CMD_DEG_LOW:22,\n        CMD_DEG_HIGH:23,\n        CMD_LEDDRAW: 24,\n        CMD_BODYLED0: 24,\n        CMD_BODYLED1: 28,\n        CMD_BODYLED2: 32,\n        CMD_BODYLED3: 36,\n        CMD_SERVOSPEED_EXT: 40,\n    },\n    Sensor: {\n        SENSOR_BATTERY: 6,\n        SENSOR_TOF: 7,\n        SENSOR_TILT_LR: 8,\n        SENSOR_TILT_FB: 9,\n        SENSOR_YAW_LOW: 10,\n        SENSOR_YAW_HIGH: 11,\n        SENSOR_RB_DATA: 12,\n        SENSOR_BUTTON: 16,\n        SENSOR_RB_WATHDOG: 17,\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.CMD = [\n            0x26, 0xA8, 0x14, 0x81, 0x30, 0x20, 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, 100, 100, 100, 100, 100, 100, 100, 100\n        ];\n        for (let n=0; n<16; n++){\n            headLED_Backup[n] = 0;\n            bodyLED_Backup[n] = 0;\n        }\n        Entry.hw.update();\n    },\n    id: '1D.5',\n    name: 'RoboDog',\n    url: 'http://www.junilab.co.kr',\n    imageName: 'robodog.png',\n    title: {\n        'en': 'RoboDog',\n        'ko': '로보독',\n    },\n    monitorTemplate: {\n        width: 1500,\n        height: 600,\n        listPorts: {\n            'BATTERY': {\n                name: '배터리(%)',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            'TOF': {\n                name: '거리센서',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 20,\n                },\n            },\n            'BUTTON': {\n                name: '버튼',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 40,\n                },\n            },\n            'ROLL': {\n                name: '좌/우 기울기',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 60,\n                },\n            },\n            'PITCH': {\n                name: '앞/뒤 기울기',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 80,\n                },\n            },\n\n            'YAW': {\n                name: '회전',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 100,\n                },\n            },\n            'RB_WATCHDOG': {\n                name: '라즈베리파이 준비상태',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 40,\n                },\n            },\n            'RB0': {\n                name: '라즈베리파이D1',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 120,\n                },\n            },\n            'RB1': {\n                name: '라즈베리파이D2',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 140,\n                },\n            },\n            'RB2': {\n                name: '라즈베리파이D3',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 160,\n                },\n            },\n            'RB3': {\n                name: '라즈베리파이D4',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 160,\n                },\n            },\n            'RB4': {\n                name: '라즈베리파이D5',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 160,\n                },\n            },\n            'RB5': {\n                name: '라즈베리파이D6',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 160,\n                },\n            },\n        },\n        ports: {  \n        },\n        mode: 'both',\n    },\n};\n\nfunction checksum(cmd){\n    let sum = 0;\n\n    cmd.forEach(function (value, idx) {\n        if(idx > 5)\n            sum += value;\n    });\n    return sum&0xFF;\n}\n\nfunction check_cmdInit(){\n    if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n        Entry.hw.sendQueue.CMD = [\n            0x26, 0xA8, 0x14, 0x81, 0x30, 0x20, 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, 100, 100, 100, 100, 100, 100, 100, 100\n        ];\n    }\n}\n\n\nfunction set_option(cmd, option, initValue) {\n    console.log(\"set option : \"+cmd[Entry.RoboDog.Cmd.CMD_TYPE]+\" \"+option)\n    if(cmd[Entry.RoboDog.Cmd.CMD_TYPE] != option){\n        for (let n = 0; n < 8; n++){\n            cmd[Entry.RoboDog.Cmd.CMD_LEG0+n] = initValue;\n        }\n    }\n    cmd[Entry.RoboDog.Cmd.CMD_TYPE] = option;\n}\n\nEntry.RoboDog.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                'robodog_gesture': '%1 자세 취하기 %2',\n                'robodog_gesture0': '준비',\n                'robodog_gesture1': '앉기',\n                'robodog_gesture2': '물구나무서기',\n                'robodog_gesture3': '기지개 켜기',\n                'robodog_gesture4': '인사하기',\n\n                'robodog_legact': '%1를 %2높이로 설정하기 %3',\n                'robodog_legact0': '네다리',\n                'robodog_legact1': '앞다리',\n                'robodog_legact2': '뒷다리',\n                'robodog_legact3': '왼쪽다리',\n                'robodog_legact4': '오른쪽다리',\n\n                'robodog_move': '%1(으)로 %2빠르기로 이동하기 %3',\n                'robodog_move0': '앞',\n                'robodog_move1': '뒤',\n\n                'robodog_leg': '%1다리높이 %2, 발끝앞뒤%3로 설정하기 %4',\n                'robodog_leg0': '왼쪽 위',\n                'robodog_leg1': '왼쪽 아래',\n                'robodog_leg2': '오른쪽 아래',\n                'robodog_leg3': '오른쪽 위',\n                'robodog_leg4': '앞다리',\n                'robodog_leg5': '뒷다리',\n                'robodog_leg6': '왼쪽다리',\n                'robodog_leg7': '오른쪽다리',\n                'robodog_leg8': '네다리',\n\n                'robodog_motor': '%1어깨 %2도, 무릎%3도 설정하기 %4',\n\n                'robodog_rotation': '%1으로 %2도를 %3각속도로 회전하기 %4',\n                'robodog_rotation0': '시계방향',\n                'robodog_rotation1': '반시계방향',\n\n                'robodog_servospeed': '%1 회전속도를 어깨 %2, 무릎 %3(으)로 설정하기 %4',\n\n                'robodog_headledexp': '%1 표정을 헤드LED에 표현하기 %2',\n                'robodog_headledexp0': '초롱초롱',\n                'robodog_headledexp1': 'I❤U',\n                'robodog_headledexp2': '눈감기',\n                'robodog_headledexp3': '감사',\n                'robodog_headledexp4': '고마워요',\n                'robodog_headledexp5': '뱁새',\n                'robodog_headledexp6': '좌우굴리기',\n                'robodog_headledexp7': '찢눈',\n                'robodog_headledexp8': '찢눈 깜박임',\n                'robodog_headledexp9': '곤충',\n                'robodog_headledexp10': '깜박',\n                'robodog_headledexp11': '뱀눈',\n                'robodog_headledexp12': '바람개비',\n                'robodog_headledexp13': '왕눈이',\n\n                'robodog_headledprint': '%1 헤드LED에 %2 문자 출력하기 %3',\n                'robodog_headledprint0': '왼쪽',\n                'robodog_headledprint1': '오른쪽',\n\n                'robodog_bodyled': '%1번 바디LED를 R:%2, G:%3, B:%4색상 출력하기 %5',\n\n                'robodog_mp3play': '%1소리를 %2출력하기 %3',\n                'robodog_mp3play01': '멍멍',\n                'robodog_mp3play02': '으르렁',\n                'robodog_mp3play03': '화난',\n                'robodog_mp3play04': '신음',\n                'robodog_mp3play05': '거친숨',\n                'robodog_mp3play11': '안녕',\n                'robodog_mp3play12': '기다려',\n                'robodog_mp3play13': '비켜',\n                'robodog_mp3play14': '출발',\n                'robodog_mp3play21': '레이저',\n                'robodog_mp3play22': '모터회전',\n                'robodog_mp3play23': '띠리리',\n                'robodog_mp3play24': '외계신호',\n                'robodog_mp3play25': '동작',\n                'robodog_mp3play26': '충돌',\n                'robodog_mp3play31': '도',\n                'robodog_mp3play32': '레',\n                'robodog_mp3play33': '미',\n                'robodog_mp3play34': '파',\n                'robodog_mp3play35': '솔',\n                'robodog_mp3play36': '라',\n                'robodog_mp3play37': '시',\n                'robodog_mp3play38': '#도',\n\n                'robodog_mp3playvol0': '작게',\n                'robodog_mp3playvol1': '중간으로',\n                'robodog_mp3playvol2': '크게',\n\n                'robodog_expservo': '확장 서보모터를 %1도 설정하기 %2',\n\n                'robodog_button': '버튼',\n                'robodog_battery': '배터리(%)',\n                'robodog_getalt': '거리센서',\n                'robodog_gettilt': '%1기울기',\n                'robodog_tilt0': '좌우',\n                'robodog_tilt1': '앞뒤',\n                'robodog_getrot': '회전',\n\n                'robodog_isrbalive': '라즈베리파이 준비상태',\n                'robodog_getrbdata': '라즈베리파이 %1번 값',\n                'robodog_getrbstr': '라즈베리파이 문자열',\n            },\n        },\n        en: {\n            template: {\n                'robodog_gesture': '%1 자세 취하기 %2',\n                'robodog_gesture0': '준비',\n                'robodog_gesture1': '앉기',\n                'robodog_gesture2': '물구나무서기',\n                'robodog_gesture3': '기지개 켜기',\n                'robodog_gesture4': '인사하기',\n\n                'robodog_legact': '%1를 %2높이로 설정하기 %3',\n                'robodog_legact0': '네다리',\n                'robodog_legact1': '앞다리',\n                'robodog_legact2': '뒷다리',\n                'robodog_legact3': '왼쪽다리',\n                'robodog_legact4': '오른쪽다리',\n\n                'robodog_move': '%1(으)로 %2빠르기로 이동하기 %3',\n                'robodog_move0': '앞',\n                'robodog_move1': '뒤',\n\n                'robodog_leg': '%1다리높이 %2, 발끝앞뒤%3로 설정하기 %4',\n                'robodog_leg0': '왼쪽 위',\n                'robodog_leg1': '왼쪽 아래',\n                'robodog_leg2': '오른쪽 아래',\n                'robodog_leg3': '오른쪽 위',\n                'robodog_leg4': '앞다리',\n                'robodog_leg5': '뒷다리',\n                'robodog_leg6': '왼쪽다리',\n                'robodog_leg7': '오른쪽다리',\n                'robodog_leg8': '네다리',\n\n                'robodog_motor': '%1어깨 %2도, 무릎%3도 설정하기 %4',\n\n                'robodog_rotation': '%1으로 %2도를 %3각속도로 회전하기 %4',\n                'robodog_rotation0': '시계방향',\n                'robodog_rotation1': '반시계방향',\n\n                'robodog_servospeed': '%1 회전속도를 어깨 %2, 무릎 %3(으)로 설정하기 %4',\n\n                'robodog_headledexp': '%1 표정을 헤드LED에 표현하기 %2',\n                'robodog_headledexp0': '초롱초롱',\n                'robodog_headledexp1': 'I❤U',\n                'robodog_headledexp2': '눈감기',\n                'robodog_headledexp3': '감사',\n                'robodog_headledexp4': '고마워요',\n                'robodog_headledexp5': '뱁새',\n                'robodog_headledexp6': '좌우굴리기',\n                'robodog_headledexp7': '찢눈',\n                'robodog_headledexp8': '찢눈 깜박임',\n                'robodog_headledexp9': '곤충',\n                'robodog_headledexp10': '깜박',\n                'robodog_headledexp11': '뱀눈',\n                'robodog_headledexp12': '바람개비',\n                'robodog_headledexp13': '왕눈이',\n\n                'robodog_headledprint': '%1 헤드LED에 %2 문자 출력하기',\n                'robodog_headledprint0': '왼쪽',\n                'robodog_headledprint1': '오른쪽',\n\n                'robodog_bodyled': '%1번 바디LED를 R:%2, G:%3, B:%4색상 출력하기 %5',\n\n                'robodog_mp3play': '%1소리를 %2출력하기 %3',\n                'robodog_mp3play01': '멍멍',\n                'robodog_mp3play02': '으르렁',\n                'robodog_mp3play03': '화난',\n                'robodog_mp3play04': '신음',\n                'robodog_mp3play05': '거친숨',\n                'robodog_mp3play11': '안녕',\n                'robodog_mp3play12': '기다려',\n                'robodog_mp3play13': '비켜',\n                'robodog_mp3play14': '출발',\n                'robodog_mp3play21': '레이저',\n                'robodog_mp3play22': '모터회전',\n                'robodog_mp3play23': '띠리리',\n                'robodog_mp3play24': '외계신호',\n                'robodog_mp3play25': '동작',\n                'robodog_mp3play26': '충돌',\n                'robodog_mp3play31': '도',\n                'robodog_mp3play32': '레',\n                'robodog_mp3play33': '미',\n                'robodog_mp3play34': '파',\n                'robodog_mp3play35': '솔',\n                'robodog_mp3play36': '라',\n                'robodog_mp3play37': '시',\n                'robodog_mp3play38': '#도',\n\n                'robodog_mp3playvol0': '작게',\n                'robodog_mp3playvol1': '중간으로',\n                'robodog_mp3playvol2': '크게',\n\n                'robodog_expservo': '확장 서보모터를 %1도 설정하기 %2',\n\n                'robodog_button': '버튼',\n                'robodog_battery': '배터리(%)',\n                'robodog_getalt': '거리센서',\n                'robodog_gettilt': '%1기울기',\n                'robodog_tilt0': '좌우',\n                'robodog_tilt1': '앞뒤',\n                'robodog_getrot': '회전',\n\n                'robodog_isrbalive': '라즈베리파이 준비상태',\n                'robodog_getrbdata': '라즈베리파이 %1번 값',\n                'robodog_getrbstr': '라즈베리파이 문자열',\n            },\n        },\n    };\n};\n\n\nEntry.RoboDog.blockMenuBlocks = [\n    'robodog_gesture',\n    'robodog_legact',\n    'robodog_move',\n    'robodog_leg',\n    'robodog_motor',\n    'robodog_rotation',\n    'robodog_servospeed',\n    'robodog_headledexp',\n    'robodog_headledprint',\n    'robodog_bodyled',\n    'robodog_mp3play',\n    'robodog_expservo',\n    'robodog_button',\n    'robodog_battery',\n    'robodog_getalt',\n    'robodog_gettilt',\n    'robodog_getrot',\n    'robodog_isrbalive',\n    'robodog_getrbdata',\n    'robodog_getrbstr'\n];\n\n\n\nEntry.RoboDog.getBlocks = function() {\n    return {\n        //region RoboDog\n        robodog_gesture: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_gesture0, 0],\n                        [Lang.template.robodog_gesture1, 1],\n                        [Lang.template.robodog_gesture2, 2],\n                        [Lang.template.robodog_gesture3, 3],\n                        [Lang.template.robodog_gesture4, 4],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_gesture',\n            },\n            paramsKeyMap: {\n                MOTION: 0\n            },\n            class: 'RoboDog_Action',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let motion = script.getField('MOTION', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n\n                set_option(cmd, 0x04, 0);\n                cmd[Entry.RoboDog.Cmd.CMD_GESTURE] = motion;\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        robodog_legact: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_legact0, 0],\n                        [Lang.template.robodog_legact1, 1],\n                        [Lang.template.robodog_legact2, 2],\n                        [Lang.template.robodog_legact3, 3],\n                        [Lang.template.robodog_legact4, 4],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '60',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_legact',\n            },\n            paramsKeyMap: {\n                WHAT_LEG: 0,\n                LEG_ALT: 1\n            },\n            class: 'RoboDog_Action',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let what_leg = script.getField('WHAT_LEG', script);\n                let alt_leg = script.getNumberValue('LEG_ALT', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n\n                set_option(cmd, 0x01, 0);\n\n                if(what_leg == 0) {\n                    for (let n = 0; n < 4; n++)\n                        cmd[Entry.RoboDog.Cmd.CMD_LEG0 + n] = alt_leg;\n                }\n                if(what_leg == 1)\n                    cmd[Entry.RoboDog.Cmd.CMD_LEG0] = cmd[Entry.RoboDog.Cmd.CMD_LEG0+3] = alt_leg;\n                if(what_leg == 2)\n                    cmd[Entry.RoboDog.Cmd.CMD_LEG0+1] = cmd[Entry.RoboDog.Cmd.CMD_LEG0+2] = alt_leg;\n                if(what_leg == 3)\n                    cmd[Entry.RoboDog.Cmd.CMD_LEG0] = cmd[Entry.RoboDog.Cmd.CMD_LEG0+1] = alt_leg;\n                if(what_leg == 4)\n                    cmd[Entry.RoboDog.Cmd.CMD_LEG0+2] = cmd[Entry.RoboDog.Cmd.CMD_LEG0+3] = alt_leg;\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        robodog_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_move0, 0],\n                        [Lang.template.robodog_move1, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '50',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_move',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VELOCITY: 1\n            },\n            class: 'RoboDog_Action',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let direction = script.getField('DIRECTION', script);\n                let velocity = script.getNumberValue('VELOCITY', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n                set_option(cmd, 0x01, 0);\n\n                velocity = velocity>100? 100 : velocity<-100? -100 : velocity;\n                if(direction == 1)\n                    velocity = -1*velocity;\n                cmd[Entry.RoboDog.Cmd.CMD_MOVEVEL] = velocity;\n\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n\n        robodog_leg: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_leg0, 0],\n                        [Lang.template.robodog_leg1, 1],\n                        [Lang.template.robodog_leg2, 2],\n                        [Lang.template.robodog_leg3, 3],\n                        [Lang.template.robodog_leg4, 4],\n                        [Lang.template.robodog_leg5, 5],\n                        [Lang.template.robodog_leg6, 6],\n                        [Lang.template.robodog_leg7, 7],\n                        [Lang.template.robodog_leg8, 8],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '60',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_leg',\n            },\n            paramsKeyMap: {\n                WHAT_LEG: 0,\n                LEG_ALT: 1,\n                LEG_FB: 2\n            },\n            class: 'RoboDog_Action',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let what_leg = script.getField('WHAT_LEG', script);\n                let leg_alt = script.getNumberValue('LEG_ALT', script);\n                let leg_fb = script.getNumberValue('LEG_FB', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n\n                set_option(cmd, 0x02, -127);\n\n                const pos = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1],[1, 0, 0, 1],[0, 1, 1, 0],[1, 1, 0, 0],[0, 0, 1, 1],[1, 1, 1, 1]];\n                leg_alt = leg_alt>90? 90 : leg_alt<20? 20 : leg_alt;\n                leg_fb = leg_fb>90? 90 : leg_fb<-90? -90 : leg_fb;\n                let _pos = pos[what_leg];\n                for(let n=0; n<4; n++){\n                    if(_pos[n] == 1){\n                        cmd[Entry.RoboDog.Cmd.CMD_LEG0+n*2] = leg_alt;\n                        cmd[Entry.RoboDog.Cmd.CMD_LEG0+n*2+1] = leg_fb;\n                    }\n                }\n                \n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n\n        robodog_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_leg0, 0],\n                        [Lang.template.robodog_leg1, 1],\n                        [Lang.template.robodog_leg2, 2],\n                        [Lang.template.robodog_leg3, 3],\n                        [Lang.template.robodog_leg4, 4],\n                        [Lang.template.robodog_leg5, 5],\n                        [Lang.template.robodog_leg6, 6],\n                        [Lang.template.robodog_leg7, 7],\n                        [Lang.template.robodog_leg8, 8],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_motor',\n            },\n            paramsKeyMap: {\n                WHAT_LEG: 0,\n                MOTOR_DEG0: 1,\n                MOTOR_DEG1: 2\n            },\n            class: 'RoboDog_Action',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let what_leg = script.getField('WHAT_LEG', script);\n                let motor_deg0 = script.getNumberValue('MOTOR_DEG0', script);\n                let motor_deg1 = script.getNumberValue('MOTOR_DEG1', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n                const pos = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1],[1, 0, 0, 1],[0, 1, 1, 0],[1, 1, 0, 0],[0, 0, 1, 1],[1, 1, 1, 1]];\n                set_option(cmd, 0x03, -127);\n\n                motor_deg0 = motor_deg0>90? 90 : motor_deg0<-90? -90 : motor_deg0;\n                motor_deg1 = motor_deg1>70? 70 : motor_deg1<-90? -90 : motor_deg1;\n\n                let _pos = pos[what_leg];\n                for(let n=0; n<4; n++){\n                    if(_pos[n] == 1){\n                        cmd[Entry.RoboDog.Cmd.CMD_LEG0+n*2] = motor_deg0;\n                        cmd[Entry.RoboDog.Cmd.CMD_LEG0+n*2+1] = motor_deg1;\n                    }\n                }\n\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        robodog_rotation: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_rotation0, 0],\n                        [Lang.template.robodog_rotation1, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '90',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '100',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_rotation',\n            },\n            paramsKeyMap: {\n                ROT_DIR: 0,\n                DEGREE: 1,\n                DEG_VEL: 2\n            },\n            class: 'RoboDog_Action',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let rot_dir = script.getField('ROT_DIR', script);\n                let degree = script.getNumberValue('DEGREE', script);\n                let deg_vel = script.getNumberValue('DEG_VEL', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n\n                set_option(cmd, 0x01, 0)\n\n                degree = degree>1000? 1000 : degree<-1000? -1000 : degree;\n                deg_vel = deg_vel>100? 100 : deg_vel<10? 10 : deg_vel;\n                if(rot_dir == 1)\n                    degree = -1*degree;\n                cmd[Entry.RoboDog.Cmd.CMD_DEG_VEL] = deg_vel;\n                cmd[Entry.RoboDog.Cmd.CMD_DEG_LOW] = degree&0xFF;\n                cmd[Entry.RoboDog.Cmd.CMD_DEG_HIGH] = (degree>>8)&0xFF;\n\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        robodog_servospeed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_leg0, 0],\n                        [Lang.template.robodog_leg1, 1],\n                        [Lang.template.robodog_leg2, 2],\n                        [Lang.template.robodog_leg3, 3],\n                        [Lang.template.robodog_leg4, 4],\n                        [Lang.template.robodog_leg5, 5],\n                        [Lang.template.robodog_leg6, 6],\n                        [Lang.template.robodog_leg7, 7],\n                        [Lang.template.robodog_leg8, 8],\n                    ],\n                    value: 8,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '50',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '50',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_servospeed',\n            },\n            paramsKeyMap: {\n                WHAT_LEG: 0,\n                MOTOR1: 1,\n                MOTOR2: 2,\n            },\n            class: 'RoboDog_Action',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let what_leg = script.getField('WHAT_LEG', script);\n                let motor1_speed = script.getNumberValue('MOTOR1', script);\n                let motor2_speed = script.getNumberValue('MOTOR2', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n                console.log(typeof motor1_speed + \" \"+motor1_speed)\n                motor1_speed = motor1_speed>100? 100 : motor1_speed<10? 10 : motor1_speed;\n                motor2_speed = motor2_speed>100? 100 : motor2_speed<10? 10 : motor2_speed;\n\n                const pos = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1],[1, 0, 0, 1],[0, 1, 1, 0],[1, 1, 0, 0],[0, 0, 1, 1],[1, 1, 1, 1]];\n                let _pos = pos[what_leg];\n                for(let n=0; n<4; n++){\n                    if(_pos[n] == 1){\n                        cmd[Entry.RoboDog.Cmd.CMD_SERVOSPEED_EXT+n*2] = motor1_speed;\n                        cmd[Entry.RoboDog.Cmd.CMD_SERVOSPEED_EXT+n*2+1] = motor2_speed;\n                    }\n                }\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        robodog_headledexp: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_headledexp0, 0],\n                        [Lang.template.robodog_headledexp1, 1],\n                        [Lang.template.robodog_headledexp2, 2],\n                        [Lang.template.robodog_headledexp3, 3],\n                        [Lang.template.robodog_headledexp4, 4],\n                        [Lang.template.robodog_headledexp5, 5],\n                        [Lang.template.robodog_headledexp6, 6],\n                        [Lang.template.robodog_headledexp7, 7],\n                        [Lang.template.robodog_headledexp8, 8],\n                        [Lang.template.robodog_headledexp9, 9],\n                        [Lang.template.robodog_headledexp10, 10],\n                        [Lang.template.robodog_headledexp11, 11],\n                        [Lang.template.robodog_headledexp12, 12],\n                        [Lang.template.robodog_headledexp13, 13],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_headledexp',\n            },\n            paramsKeyMap: {\n                LED_EXP: 0\n            },\n            class: 'RoboDog_LED',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let led_exp = script.getField('LED_EXP', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n                for (let n=0; n<16; n++)\n                    cmd[Entry.RoboDog.Cmd.CMD_LEDDRAW+n] = headLED_Backup[n];\n\n                cmd[Entry.RoboDog.Cmd.CMD_LEDDRAW] = led_exp;\n                cmd[Entry.RoboDog.Cmd.CMD_LEDTYPE] = 0x02;\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n\n                for (let n=0; n<16; n++)\n                    headLED_Backup[n] = cmd[Entry.RoboDog.Cmd.CMD_LEDDRAW+n];\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        robodog_headledprint: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_headledprint0, 0],\n                        [Lang.template.robodog_headledprint1, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 'A',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_headledprint',\n            },\n            paramsKeyMap: {\n                WHAT_LED: 0,\n                WHAT_CHAR: 1,\n            },\n            class: 'RoboDog_LED',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let what_led = script.getField('WHAT_LED', script);\n                let what_char = script.getStringValue('WHAT_CHAR', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n                \n                for (let n=0; n<16; n++)\n                    cmd[Entry.RoboDog.Cmd.CMD_LEDDRAW+n] = headLED_Backup[n];\n\n                cmd[Entry.RoboDog.Cmd.CMD_LEDDRAW+what_led*8] = what_char.charCodeAt(0)\n\n                cmd[Entry.RoboDog.Cmd.CMD_LEDTYPE] = 0x03;\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                for (let n=0; n<16; n++)\n                    headLED_Backup[n] = cmd[Entry.RoboDog.Cmd.CMD_LEDDRAW+n];\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        robodog_bodyled: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\"1~4\", 0],\n                        [\"1\", 1],\n                        [\"2\", 2],\n                        [\"3\", 3],\n                        [\"4\", 4],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '255',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '255',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '255',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_bodyled',\n            },\n            paramsKeyMap: {\n                WHAT_LED: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3\n            },\n            class: 'RoboDog_LED',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                script.get\n                let what = script.getField('WHAT_LED', script);\n                let red = script.getNumberValue('RED', script);\n                let green = script.getNumberValue('GREEN', script);\n                let blue = script.getNumberValue('BLUE', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n\n                for (let n=0; n<16; n++)\n                    cmd[Entry.RoboDog.Cmd.CMD_BODYLED0+n] = bodyLED_Backup[n];\n\n                const pos = [[1, 1, 1, 1], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];\n                let _pos = pos[what];\n\n                for(let n=0; n<4; n++){\n                    if(_pos[n] == 1){\n                        cmd[Entry.RoboDog.Cmd.CMD_BODYLED0+n*4] = red;\n                        cmd[Entry.RoboDog.Cmd.CMD_BODYLED0+n*4+1] = green;\n                        cmd[Entry.RoboDog.Cmd.CMD_BODYLED0+n*4+2] = blue;\n                    }\n                }\n                cmd[Entry.RoboDog.Cmd.CMD_LEDTYPE] = 0x04;\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n\n                for (let n=0; n<16; n++)\n                    bodyLED_Backup[n] = cmd[Entry.RoboDog.Cmd.CMD_BODYLED0+n];\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n\n        robodog_mp3play: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_mp3play01, 1],\n                        [Lang.template.robodog_mp3play02, 2],\n                        [Lang.template.robodog_mp3play03, 3],\n                        [Lang.template.robodog_mp3play04, 4],\n                        [Lang.template.robodog_mp3play05, 5],\n                        [Lang.template.robodog_mp3play11, 11],\n                        [Lang.template.robodog_mp3play12, 12],\n                        [Lang.template.robodog_mp3play13, 13],\n                        [Lang.template.robodog_mp3play14, 14],\n                        [Lang.template.robodog_mp3play21, 21],\n                        [Lang.template.robodog_mp3play22, 22],\n                        [Lang.template.robodog_mp3play23, 23],\n                        [Lang.template.robodog_mp3play24, 24],\n                        [Lang.template.robodog_mp3play25, 25],\n                        [Lang.template.robodog_mp3play26, 26],\n                        [Lang.template.robodog_mp3play31, 31],\n                        [Lang.template.robodog_mp3play32, 32],\n                        [Lang.template.robodog_mp3play33, 33],\n                        [Lang.template.robodog_mp3play34, 34],\n                        [Lang.template.robodog_mp3play35, 35],\n                        [Lang.template.robodog_mp3play36, 36],\n                        [Lang.template.robodog_mp3play37, 37],\n                        [Lang.template.robodog_mp3play38, 38],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_mp3playvol0, 1],\n                        [Lang.template.robodog_mp3playvol1, 2],\n                        [Lang.template.robodog_mp3playvol2, 3],\n                    ],\n                    value: 3,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_mp3play',\n            },\n            paramsKeyMap: {\n                WHAT_MP3: 0,\n                VOLUME: 1,\n            },\n            class: 'RoboDog_ETC',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                script.get\n                let what_mp3 = script.getField('WHAT_MP3', script);\n                let volume = script.getField('VOLUME', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n                mp3ID = (mp3ID&0x80)==0x80? 0 : 0x80;\n                cmd[Entry.RoboDog.Cmd.CMD_MP3TRACK] = what_mp3 | mp3ID;\n                cmd[Entry.RoboDog.Cmd.CMD_MP3VOLUME] = volume;\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        robodog_expservo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '45',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_expservo',\n            },\n            paramsKeyMap: {\n                SERVO_DEG: 0,\n            },\n            class: 'RoboDog_ETC',\n            isNotFor: ['RoboDog'],\n\n            func: function(sprite, script) {\n                check_cmdInit();\n                let servo_deg = script.getNumberValue('SERVO_DEG', script);\n                let cmd = Entry.hw.sendQueue.CMD;\n\n                servo_deg = servo_deg>90? 90 : servo_deg<-90? -90 : servo_deg;\n                cmd[Entry.RoboDog.Cmd.CMD_EXTSERVO] = servo_deg;\n\n                cmd[Entry.RoboDog.Cmd.CMD_CHECKSUM] = checksum(cmd);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        robodog_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_button',\n            },\n            class: 'RoboDog_Sensor',\n            isNotFor: ['RoboDog'],\n            func: function(sprite, script) {\n                let sensorData = Entry.hw.portData.SENSORDATA;\n                return sensorData[Entry.RoboDog.Sensor.SENSOR_BUTTON];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        robodog_battery: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_battery',\n            },\n            class: 'RoboDog_Sensor',\n            isNotFor: ['RoboDog'],\n            func: function(sprite, script) {\n                let sensorData = Entry.hw.portData.SENSORDATA;\n                console.log(\"battery:\" + sensorData[6], \" len:\"+sensorData.length);\n                return sensorData[Entry.RoboDog.Sensor.SENSOR_BATTERY];\n            },\n            syntax: { js: [], py: [] },\n        },\n        robodog_getalt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_getalt',\n            },\n            class: 'RoboDog_Sensor',\n            isNotFor: ['RoboDog'],\n            func: function(sprite, script) {\n                let sensorData = Entry.hw.portData.SENSORDATA;\n                console.log(\"tof:\" + sensorData[7], \" len:\"+sensorData.length);\n                return sensorData[Entry.RoboDog.Sensor.SENSOR_TOF];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        robodog_gettilt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.robodog_tilt0, 0],\n                        [Lang.template.robodog_tilt1, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_gettilt',\n            },\n            class: 'RoboDog_Sensor',\n            paramsKeyMap: {\n                TILT_DIR: 0,\n            },\n            isNotFor: ['RoboDog'],\n            func: function(sprite, script) {\n                let tilt_dir = script.getField('TILT_DIR', script);\n                let sensorData = Entry.hw.portData.SENSORDATA;\n                console.log(\"tilt:\" + sensorData[Entry.RoboDog.Sensor.SENSOR_TILT_LR], \" FB:\"+sensorData[Entry.RoboDog.Sensor.SENSOR_TILT_FB]);\n                let val = tilt_dir==0? sensorData[Entry.RoboDog.Sensor.SENSOR_TILT_LR] : sensorData[Entry.RoboDog.Sensor.SENSOR_TILT_FB];\n                val = val>127? val-256 : val;\n                return val;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        robodog_getrot: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_getrot',\n            },\n            class: 'RoboDog_Sensor',\n            isNotFor: ['RoboDog'],\n            func: function(sprite, script) {\n                let sensorData = Entry.hw.portData.SENSORDATA;\n                let yaw = sensorData[Entry.RoboDog.Sensor.SENSOR_YAW_LOW];\n                yaw |= (sensorData[Entry.RoboDog.Sensor.SENSOR_YAW_HIGH]<<8); \n                yaw = yaw>0x7FFF? yaw-0x10000 : yaw;\n                return yaw;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        robodog_isrbalive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_isrbalive',\n            },\n            class: 'RoboDog_Sensor',\n            isNotFor: ['RoboDog'],\n            func: function(sprite, script) {\n                let sensorData = Entry.hw.portData.SENSORDATA;\n                return sensorData[Entry.RoboDog.Sensor.SENSOR_RB_WATHDOG];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        robodog_getrbdata: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\"0\", 0],\n                        [\"1\", 1],\n                        [\"2\", 2],\n                        [\"3\", 3],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_getrbdata',\n            },\n            class: 'RoboDog_Sensor',\n            paramsKeyMap: {\n                WHAT_RB: 0,\n            },\n            isNotFor: ['RoboDog'],\n            func: function(sprite, script) {\n                let what_rb = script.getField('WHAT_RB', script);\n\n                let sensorData = Entry.hw.portData.SENSORDATA;\n                let val = sensorData[Entry.RoboDog.Sensor.SENSOR_RB_DATA + what_rb];\n                val = val>127? val-256 : val;\n                return val;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        \n        robodog_getrbstr: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robodog_getrbstr',\n            },\n            class: 'RoboDog_Sensor',\n            isNotFor: ['RoboDog'],\n            func: function(sprite, script) {\n                let sensorData = Entry.hw.portData.SENSORDATA;\n                let tmp = new Int8Array(6)\n                for( let n=0; n<4; n++)\n                    tmp[n] = sensorData[Entry.RoboDog.Sensor.SENSOR_RB_DATA+n];\n                tmp[4] = sensorData[Entry.RoboDog.Sensor.SENSOR_RB_DATA+6];\n                tmp[5] = sensorData[Entry.RoboDog.Sensor.SENSOR_RB_DATA+7];\n\n                let stop = 5;\n                for(; stop>=0; stop--){\n                    if(tmp[stop] != 0)\n                        break;\n                }\n        \n                const slicedArray = tmp.slice(0, stop+1);\n                const decoder = new TextDecoder();\n                return decoder.decode(slicedArray);\n            },\n            syntax: { js: [], py: [] },\n        },\n        //endregion RoboDog\n    };\n};\n\nmodule.exports = Entry.RoboDog;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_roboid.js",
    "content": "'use strict';\n\nEntry.Roboid = {\n    setZero() {\n        Entry.Robomation.setZero();\n    },\n    afterReceive(pd) {\n        Entry.Robomation.afterReceive(pd, true);\n    },\n    afterSend(sq) {\n        Entry.Robomation.afterSend(sq);\n    },\n    getHamster(index) {\n        return Entry.Robomation.getRobot('hamster', index);\n    },\n    getHamsterS(index) {\n        return Entry.Robomation.getRobot('hamster', index);\n    },\n    getTurtle(index) {\n        return Entry.Robomation.getRobot('turtle', index);\n    },\n    getCheese(index) {\n        return Entry.Robomation.getRobot('cheese', index);\n    },\n    id: '2.FF',\n    name: 'roboid',\n    url: 'http://www.robomation.net',\n    imageName: 'block_roboid.png',\n    title: {\n        en: 'Roboid',\n        ko: '로보이드',\n        jp: 'ロボイド',\n        vn: 'Roboid',\n    },\n    monitorTemplate: () => ({\n        imgPath: 'hw/transparent.png',\n        width: 2,\n        height: 2,\n        listPorts: {\n            hamster0leftProximity: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_left_proximity}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0rightProximity: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_right_proximity}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0leftFloor: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_left_floor}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0rightFloor: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_right_floor}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0accelerationX: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_acceleration_x}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0accelerationY: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_acceleration_y}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0accelerationZ: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_acceleration_z}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0light: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_light}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0temperature: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_temperature}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0inputA: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_input_a}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            hamster0inputB: {\n                name: `${Lang.Menus.hamster} 0: ${Lang.Blocks.HAMSTER_sensor_input_b}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n\n            turtle0colorNumber: {\n                name: `${Lang.Menus.turtle} 0: ${Lang.Blocks.ROBOID_color_number}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            turtle0floor: {\n                name: `${Lang.Menus.turtle} 0: ${Lang.Blocks.ROBOID_floor}`,\n                type: 'input',\n                pos: { x: 193, y: 342 },\n            },\n            turtle0button: {\n                name: `${Lang.Menus.turtle} 0: ${Lang.Blocks.ROBOID_button}`,\n                type: 'input',\n                pos: { x: 290, y: 30 },\n            },\n            turtle0accelerationX: {\n                name: `${Lang.Menus.turtle} 0: ${Lang.Blocks.ROBOID_acceleration_x}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            turtle0accelerationY: {\n                name: `${Lang.Menus.turtle} 0: ${Lang.Blocks.ROBOID_acceleration_y}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            turtle0accelerationZ: {\n                name: `${Lang.Menus.turtle} 0: ${Lang.Blocks.ROBOID_acceleration_z}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n\n            cheese0inputSa: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_input_sa}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0inputSb: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_input_sb}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0inputSc: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_input_sc}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0inputLa: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_input_la}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0inputLb: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_input_lb}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0inputLc: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_input_lc}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0accelerationX: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_acceleration_x}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0accelerationY: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_acceleration_y}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0accelerationZ: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_acceleration_z}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            cheese0stepCount: {\n                name: `${Lang.Blocks.ROBOID_cheese_stick} 0: ${Lang.Blocks.ROBOID_sensor_step_count}`,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    }),\n};\n\nEntry.Roboid.setLanguage = () => ({\n    ko: {\n        template: {\n            roboid_hamster_beep: '햄스터 %1: 삐 소리내기 %2',\n            roboid_hamster_change_both_wheels_by:\n                '햄스터 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n            roboid_hamster_change_buzzer_by: '햄스터 %1: 버저 음을 %2 만큼 바꾸기 %3',\n            roboid_hamster_change_output_by: '햄스터 %1: 출력 %2 를 %3 만큼 바꾸기 %4',\n            roboid_hamster_change_tempo_by: '햄스터 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n            roboid_hamster_change_wheel_by: '햄스터 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n            roboid_hamster_clear_buzzer: '햄스터 %1: 버저 끄기 %2',\n            roboid_hamster_clear_led: '햄스터 %1: %2 LED 끄기 %3',\n            roboid_hamster_follow_line_until: '햄스터 %1: %2 선을 따라 %3 교차로까지 이동하기 %4',\n            roboid_hamster_follow_line_using: '햄스터 %1: %2 선을 %3 바닥 센서로 따라가기 %4',\n            roboid_hamster_hand_found: '햄스터 %1: 손 찾음?',\n            roboid_hamster_move_backward_for_secs: '햄스터 %1: 뒤로 %2 초 이동하기 %3',\n            roboid_hamster_move_forward_for_secs: '햄스터 %1: 앞으로 %2 초 이동하기 %3',\n            roboid_hamster_move_forward_once: '햄스터 %1: 말판 앞으로 한 칸 이동하기 %2',\n            roboid_hamster_play_note_for: '햄스터 %1: %2 %3 음을 %4 박자 연주하기 %5',\n            roboid_hamster_rest_for: '햄스터 %1: %2 박자 쉬기 %3',\n            roboid_hamster_set_both_wheels_to:\n                '햄스터 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n            roboid_hamster_set_buzzer_to: '햄스터 %1: 버저 음을 %2 (으)로 정하기 %3',\n            roboid_hamster_set_following_speed_to:\n                '햄스터 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n            roboid_hamster_set_led_to: '햄스터 %1: %2 LED를 %3 으로 정하기 %4',\n            roboid_hamster_set_output_to: '햄스터 %1: 출력 %2 를 %3 (으)로 정하기 %4',\n            roboid_hamster_set_port_to: '햄스터 %1: 포트 %2 를 %3 으로 정하기 %4',\n            roboid_hamster_set_tempo_to: '햄스터 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n            roboid_hamster_set_wheel_to: '햄스터 %1: %2 바퀴 %3 (으)로 정하기 %4',\n            roboid_hamster_stop: '햄스터 %1: 정지하기 %2',\n            roboid_hamster_turn_for_secs: '햄스터 %1: %2 으로 %3 초 돌기 %4',\n            roboid_hamster_turn_once: '햄스터 %1: 말판 %2 으로 한 번 돌기 %3',\n            roboid_hamster_value: '햄스터 %1: %2',\n            roboid_turtle_button_state: '거북이 %1: 버튼을 %2 ?',\n            roboid_turtle_change_buzzer_by: '거북이 %1: 버저 음을 %2 만큼 바꾸기 %3',\n            roboid_turtle_change_head_led_by_rgb:\n                '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n            roboid_turtle_change_tempo_by: '거북이 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n            roboid_turtle_change_wheel_by: '거북이 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n            roboid_turtle_change_wheels_by_left_right:\n                '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n            roboid_turtle_clear_head_led: '거북이 %1: 머리 LED 끄기 %2',\n            roboid_turtle_clear_sound: '거북이 %1: 소리 끄기 %2',\n            roboid_turtle_cross_intersection: '거북이 %1: 검은색 교차로 건너가기 %2',\n            roboid_turtle_follow_line: '거북이 %1: %2 선을 따라가기 %3',\n            roboid_turtle_follow_line_until: '거북이 %1: 검은색 선을 따라 %2 까지 이동하기 %3',\n            roboid_turtle_follow_line_until_black: '거북이 %1: %2 선을 따라 검은색까지 이동하기 %3',\n            roboid_turtle_is_color_pattern: '거북이 %1: 색깔 패턴이 %2 %3 인가?',\n            roboid_turtle_move_backward_unit: '거북이 %1: 뒤로 %2 %3 이동하기 %4',\n            roboid_turtle_move_forward_unit: '거북이 %1: 앞으로 %2 %3 이동하기 %4',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                '거북이 %1: %2 바퀴 중심으로 %3 %4 %5 방향으로 돌기 %6',\n            roboid_turtle_play_note: '거북이 %1: %2 %3 음을 연주하기 %4',\n            roboid_turtle_play_note_for_beats: '거북이 %1: %2 %3 음을 %4 박자 연주하기 %5',\n            roboid_turtle_play_sound_times: '거북이 %1: %2 소리 %3 번 재생하기 %4',\n            roboid_turtle_play_sound_times_until_done:\n                '거북이 %1: %2 소리 %3 번 재생하고 기다리기 %4',\n            roboid_turtle_rest_for_beats: '거북이 %1: %2 박자 쉬기 %3',\n            roboid_turtle_set_buzzer_to: '거북이 %1: 버저 음을 %2 (으)로 정하기 %3',\n            roboid_turtle_set_following_speed_to:\n                '거북이 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n            roboid_turtle_set_head_led_to: '거북이 %1: 머리 LED를 %2 으로 정하기 %3',\n            roboid_turtle_set_head_led_to_rgb:\n                '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n            roboid_turtle_set_tempo_to: '거북이 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n            roboid_turtle_set_wheel_to: '거북이 %1: %2 바퀴 %3 (으)로 정하기 %4',\n            roboid_turtle_set_wheels_to_left_right:\n                '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n            roboid_turtle_stop: '거북이 %1: 정지하기 %2',\n            roboid_turtle_touching_color: '거북이 %1: %2 에 닿았는가?',\n            roboid_turtle_turn_at_intersection: '거북이 %1: 검은색 교차로에서 %2 으로 돌기 %3',\n            roboid_turtle_turn_unit_in_place: '거북이 %1: %2 으로 %3 %4 제자리 돌기 %5',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                '거북이 %1: %2 으로 %3 %4 반지름 %5 cm를 %6 방향으로 돌기 %7',\n            roboid_turtle_value: '거북이 %1: %2',\n            roboid_hamster_gripper: '햄스터 %1: 집게 %2 %3',\n            roboid_hamster_release_gripper: '햄스터 %1: 집게 끄기 %2',\n            roboid_hamster_boolean: '햄스터 %1: %2?',\n            roboid_hamster_play_note: '햄스터 %1: %2 %3 음을 연주하기 %4',\n            roboid_hamster_s_hand_found: '햄스터S %1: 손 찾음?',\n            roboid_hamster_s_boolean: '햄스터S %1: %2?',\n            roboid_hamster_s_value: '햄스터S %1: %2',\n            roboid_hamster_s_move_forward_once: '햄스터S %1: 말판 앞으로 한 칸 이동하기 %2',\n            roboid_hamster_s_turn_once: '햄스터S %1: 말판 %2 으로 한 번 돌기 %3',\n            roboid_hamster_s_move_forward_unit: '햄스터S %1: 앞으로 %2 %3 이동하기 %4',\n            roboid_hamster_s_move_backward_unit: '햄스터S %1: 뒤로 %2 %3 이동하기 %4',\n            roboid_hamster_s_turn_unit_in_place: '햄스터S %1: %2 으로 %3 %4 제자리 돌기 %5',\n            roboid_hamster_s_pivot_around_unit_in_direction:\n                '햄스터S %1: %2 중심으로 %3 %4 %5 방향으로 돌기 %6',\n            roboid_hamster_s_turn_unit_with_radius_in_direction:\n                '햄스터S %1: %2 %3 으로 %4 %5 반지름 %6 cm를 %7 방향으로 돌기 %8',\n            roboid_hamster_s_change_both_wheels_by:\n                '햄스터S %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n            roboid_hamster_s_set_both_wheels_to:\n                '햄스터S %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n            roboid_hamster_s_change_wheel_by: '햄스터S %1: %2 바퀴 %3 만큼 바꾸기 %4',\n            roboid_hamster_s_set_wheel_to: '햄스터S %1: %2 바퀴 %3 (으)로 정하기 %4',\n            roboid_hamster_s_follow_line_using: '햄스터S %1: %2 선을 %3 바닥 센서로 따라가기 %4',\n            roboid_hamster_s_follow_line_until:\n                '햄스터S %1: %2 선을 따라 %3 교차로까지 이동하기 %4',\n            roboid_hamster_s_set_following_speed_to:\n                '햄스터S %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n            roboid_hamster_s_set_following_gain_to:\n                '햄스터S %1: 선 따라가기 방향 변화량을 %2 (으)로 정하기 %3',\n            roboid_hamster_s_stop: '햄스터S %1: 정지하기 %2',\n            roboid_hamster_s_set_led_to: '햄스터S %1: %2 LED를 %3 으로 정하기 %4',\n            roboid_hamster_s_pick_led: '햄스터S %1: %2 LED를 %3로 정하기 %4',\n            roboid_hamster_s_change_led_by_rgb:\n                '햄스터S %1: %2 LED를 R: %3 G: %4 B: %5 만큼 바꾸기 %6',\n            roboid_hamster_s_set_led_to_rgb:\n                '햄스터S %1: %2 LED를 R: %3 G: %4 B: %5 (으)로 정하기 %6',\n            roboid_hamster_s_clear_led: '햄스터S %1: %2 LED 끄기 %3',\n            roboid_hamster_s_play_sound_times: '햄스터S %1: %2 소리 %3 번 재생하기 %4',\n            roboid_hamster_s_play_sound_times_until_done:\n                '햄스터S %1: %2 소리 %3 번 재생하고 기다리기 %4',\n            roboid_hamster_s_change_buzzer_by: '햄스터S %1: 버저 음을 %2 만큼 바꾸기 %3',\n            roboid_hamster_s_set_buzzer_to: '햄스터S %1: 버저 음을 %2 (으)로 정하기 %3',\n            roboid_hamster_s_clear_sound: '햄스터S %1: 소리 끄기 %2',\n            roboid_hamster_s_play_note: '햄스터S %1: %2 %3 음을 연주하기 %4',\n            roboid_hamster_s_play_note_for: '햄스터S %1: %2 %3 음을 %4 박자 연주하기 %5',\n            roboid_hamster_s_rest_for: '햄스터S %1: %2 박자 쉬기 %3',\n            roboid_hamster_s_change_tempo_by: '햄스터S %1: 연주 속도를 %2 만큼 바꾸기 %3',\n            roboid_hamster_s_set_tempo_to: '햄스터S %1: 연주 속도를 %2 BPM으로 정하기 %3',\n            roboid_hamster_s_set_port_to: '햄스터S %1: 포트 %2 를 %3 으로 정하기 %4',\n            roboid_hamster_s_change_output_by: '햄스터S %1: 출력 %2 를 %3 만큼 바꾸기 %4',\n            roboid_hamster_s_set_output_to: '햄스터S %1: 출력 %2 를 %3 (으)로 정하기 %4',\n            roboid_hamster_s_gripper: '햄스터S %1: 집게 %2 %3',\n            roboid_hamster_s_release_gripper: '햄스터S %1: 집게 끄기 %2',\n            roboid_hamster_s_write_serial: '햄스터S %1: 시리얼 %2 %3 쓰기 %4',\n            roboid_hamster_s_read_serial_until: '햄스터S %1: 시리얼 %2 읽기 %3',\n            roboid_hamster_s_set_serial_rate_to: '햄스터S %1: 시리얼 속도를 %2 Bd로 정하기 %3',\n            roboid_turtle_button_state: '거북이 %1: 버튼을 %2 ?',\n            roboid_turtle_change_buzzer_by: '거북이 %1: 버저 음을 %2 만큼 바꾸기 %3',\n            roboid_turtle_change_head_led_by_rgb:\n                '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n            roboid_turtle_change_tempo_by: '거북이 %1: 연주 속도를 %2 만큼 바꾸기 %3',\n            roboid_turtle_change_wheel_by: '거북이 %1: %2 바퀴 %3 만큼 바꾸기 %4',\n            roboid_turtle_change_wheels_by_left_right:\n                '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 만큼 바꾸기 %4',\n            roboid_turtle_clear_head_led: '거북이 %1: 머리 LED 끄기 %2',\n            roboid_turtle_clear_sound: '거북이 %1: 소리 끄기 %2',\n            roboid_turtle_cross_intersection: '거북이 %1: 검은색 교차로 건너가기 %2',\n            roboid_turtle_follow_line: '거북이 %1: %2 선을 따라가기 %3',\n            roboid_turtle_follow_line_until: '거북이 %1: 검은색 선을 따라 %2 까지 이동하기 %3',\n            roboid_turtle_follow_line_until_black: '거북이 %1: %2 선을 따라 검은색까지 이동하기 %3',\n            roboid_turtle_is_color_pattern: '거북이 %1: 색깔 패턴이 %2 %3 인가?',\n            roboid_turtle_move_backward_unit: '거북이 %1: 뒤로 %2 %3 이동하기 %4',\n            roboid_turtle_move_forward_unit: '거북이 %1: 앞으로 %2 %3 이동하기 %4',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                '거북이 %1: %2 바퀴 중심으로 %3 %4 %5 방향으로 돌기 %6',\n            roboid_turtle_play_note: '거북이 %1: %2 %3 음을 연주하기 %4',\n            roboid_turtle_play_note_for_beats: '거북이 %1: %2 %3 음을 %4 박자 연주하기 %5',\n            roboid_turtle_play_sound_times: '거북이 %1: %2 소리 %3 번 재생하기 %4',\n            roboid_turtle_play_sound_times_until_done:\n                '거북이 %1: %2 소리 %3 번 재생하고 기다리기 %4',\n            roboid_turtle_rest_for_beats: '거북이 %1: %2 박자 쉬기 %3',\n            roboid_turtle_set_buzzer_to: '거북이 %1: 버저 음을 %2 (으)로 정하기 %3',\n            roboid_turtle_set_following_speed_to:\n                '거북이 %1: 선 따라가기 속도를 %2 (으)로 정하기 %3',\n            roboid_turtle_set_head_led_to: '거북이 %1: 머리 LED를 %2 으로 정하기 %3',\n            roboid_turtle_set_head_led_to_rgb:\n                '거북이 %1: 머리 LED를 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n            roboid_turtle_set_tempo_to: '거북이 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n            roboid_turtle_set_wheel_to: '거북이 %1: %2 바퀴 %3 (으)로 정하기 %4',\n            roboid_turtle_set_wheels_to_left_right:\n                '거북이 %1: 왼쪽 바퀴 %2 오른쪽 바퀴 %3 (으)로 정하기 %4',\n            roboid_turtle_stop: '거북이 %1: 정지하기 %2',\n            roboid_turtle_touching_color: '거북이 %1: %2 에 닿았는가?',\n            roboid_turtle_turn_at_intersection: '거북이 %1: 검은색 교차로에서 %2 으로 돌기 %3',\n            roboid_turtle_turn_unit_in_place: '거북이 %1: %2 으로 %3 %4 제자리 돌기 %5',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                '거북이 %1: %2 으로 %3 %4 반지름 %5 cm를 %6 방향으로 돌기 %7',\n            roboid_turtle_value: '거북이 %1: %2',\n            roboid_turtle_boolean: '거북이 %1: %2?',\n            roboid_turtle_pick_head_led: '거북이 %1: 머리 LED를 %2로 정하기 %3',\n\n            roboid_cheese_value: '치즈 스틱 %1: %2',\n            roboid_cheese_boolean: '치즈 스틱 %1: %2?',\n            roboid_cheese_play_sound_times: '치즈 스틱 %1: %2 소리 %3 번 재생하기 %4',\n            roboid_cheese_play_sound_times_until_done:\n                '치즈 스틱 %1: %2 소리 %3 번 재생하고 기다리기 %4',\n            roboid_cheese_change_buzzer_by: '치즈 스틱 %1: 버저 음을 %2 Hz만큼 바꾸기 %3',\n            roboid_cheese_set_buzzer_to: '치즈 스틱 %1: 버저 음을 %2 Hz로 정하기 %3',\n            roboid_cheese_clear_sound: '치즈 스틱 %1: 소리 끄기 %2',\n            roboid_cheese_play_note: '치즈 스틱 %1: %2 %3 음을 연주하기 %4',\n            roboid_cheese_play_note_for: '치즈 스틱 %1: %2 %3 음을 %4 박자 연주하기 %5',\n            roboid_cheese_rest_for: '치즈 스틱 %1: %2 박자 쉬기 %3',\n            roboid_cheese_change_tempo_by: '치즈 스틱 %1: 연주 속도를 %2 BPM만큼 바꾸기 %3',\n            roboid_cheese_set_tempo_to: '치즈 스틱 %1: 연주 속도를 %2 BPM으로 정하기 %3',\n            roboid_cheese_set_sound_port_to: '치즈 스틱 %1: 소리 출력을 %2로 정하기 %3',\n            roboid_cheese_set_input_mode_to: '치즈 스틱 %1: 포트 %2를 %3 입력으로 정하기 %4',\n            roboid_cheese_set_input_range_to:\n                '치즈 스틱 %1: 입력 %2의 범위 %3 ~ %4을(를) %5 ~ %6 소수점 %7으로 정하기 %8',\n            roboid_cheese_set_three_input_ranges_to:\n                '치즈 스틱 %1: 입력 %2의 범위 %3 ~ %4 ~ %5을(를) %6 ~ %7 ~ %8 소수점 %9으로 정하기 %10',\n            roboid_cheese_analog_input: '치즈 스틱 %1: 입력 %2',\n            roboid_cheese_digital_input: '치즈 스틱 %1: 입력 %2 %3 ?',\n            roboid_cheese_button_state: '치즈 스틱 %1: 버튼 %2를 %3?',\n            roboid_cheese_set_pulse_mode_to: '치즈 스틱 %1: 포트 %2를 %3 입력으로 정하기 %4',\n            roboid_cheese_pulse_input: '치즈 스틱 %1: 포트 %2에서 펄스 감지?',\n            roboid_cheese_set_digital_output_to:\n                '치즈 스틱 %1: 디지털 출력 %2를 %3(으)로 정하기 %4',\n            roboid_cheese_change_pwm_output_by: '치즈 스틱 %1: PWM 출력 %2를 %3%만큼 바꾸기 %4',\n            roboid_cheese_set_pwm_output_to: '치즈 스틱 %1: PWM 출력 %2를 %3%로 정하기 %4',\n            roboid_cheese_change_servo_motor_angle_by:\n                '치즈 스틱 %1: 서보 모터 %2의 각도를 %3도만큼 바꾸기 %4',\n            roboid_cheese_set_servo_motor_angle_to:\n                '치즈 스틱 %1: 서보 모터 %2의 각도를 %3도로 정하기 %4',\n            roboid_cheese_turn_off_servo_motor: '치즈 스틱 %1: 서보 모터 %2 전원 끄기 %3',\n            roboid_cheese_change_dc_motor_velocity_by:\n                '치즈 스틱 %1: DC 모터 %2의 속도를 %3%만큼 바꾸기 %4',\n            roboid_cheese_set_dc_motor_velocity_to:\n                '치즈 스틱 %1: DC 모터 %2의 속도를 %3%로 정하기 %4',\n            roboid_cheese_stop_dc_motor: '치즈 스틱 %1: DC 모터 %2 정지하기 %3',\n            roboid_cheese_rotate_step_motor:\n                '치즈 스틱 %1: 스텝 모터 %2 스텝을 속도 %3 스텝/초로 회전하기 %4',\n            roboid_cheese_change_step_motor_velocity_by:\n                '치즈 스틱 %1: 스텝 모터의 속도를 %2 스텝/초만큼 바꾸기 %3',\n            roboid_cheese_set_step_motor_velocity_to:\n                '치즈 스틱 %1: 스텝 모터의 속도를 %2 스텝/초로 정하기 %3',\n            roboid_cheese_stop_off_step_motor: '치즈 스틱 %1: 스텝 모터 %2 %3',\n            roboid_cheese_set_step_motor_mode_to: '치즈 스틱 %1: 스텝 모터를 %2 모드로 정하기 %3',\n            roboid_cheese_step_count: '치즈 스틱 %1: 스텝 수',\n            roboid_cheese_set_led_to_color: '치즈 스틱 %1: RGB LED %2을(를) %3 %4으로 정하기 %5',\n            roboid_cheese_pick_led_to: '치즈 스틱 %1: RGB LED %2을(를) %3로 정하기 %4',\n            roboid_cheese_change_led_by_rgb:\n                '치즈 스틱 %1: RGB LED %2을(를) R: %3 G: %4 B: %5만큼 바꾸기 %6',\n            roboid_cheese_setLed_to_rgb:\n                '치즈 스틱 %1: RGB LED %2을(를) R: %3 G: %4 B: %5(으)로 정하기 %6',\n            roboid_cheese_clear_led: '치즈 스틱 %1: RGB LED %2 끄기 %3',\n            roboid_cheese_set_led_type_to: '치즈 스틱 %1: RGB LED %2을(를) %3형으로 정하기 %4',\n            roboid_cheese_neopixel_set_number_and_type_to:\n                '치즈 스틱 %1: 네오픽셀 LED %2개, %3로 정하기 %4',\n            roboid_cheese_neopixel_set_all_leds_to_pattern:\n                '치즈 스틱 %1: 네오픽셀 모든 LED를 %2 패턴으로 정하기 %3',\n            roboid_cheese_neopixel_set_all_leds_to_color:\n                '치즈 스틱 %1: 네오픽셀 모든 LED를 %2으로 정하기 %3',\n            roboid_cheese_neopixel_pick_all_leds_to:\n                '치즈 스틱 %1: 네오픽셀 모든 LED를 %2로 정하기 %3',\n            roboid_cheese_neopixel_change_all_leds_by_rgb:\n                '치즈 스틱 %1: 네오픽셀 모든 LED를 R: %2 G: %3 B: %4만큼 바꾸기 %5',\n            roboid_cheese_neopixel_set_all_leds_to_rgb:\n                '치즈 스틱 %1: 네오픽셀 모든 LED를 R: %2 G: %3 B: %4(으)로 정하기 %5',\n            roboid_cheese_neopixel_clear_all_leds: '치즈 스틱 %1: 네오픽셀 모든 LED 끄기 %2',\n            roboid_cheese_neopixel_set_led_to_color:\n                '치즈 스틱 %1: 네오픽셀 %2번째 LED를 %3으로 정하기 %4',\n            roboid_cheese_neopixel_pick_led_to:\n                '치즈 스틱 %1: 네오픽셀 %2번째 LED를 %3로 정하기 %4',\n            roboid_cheese_neopixel_change_led_by_rgb:\n                '치즈 스틱 %1: 네오픽셀 %2번째 LED를 R: %3 G: %4 B: %5만큼 바꾸기 %6',\n            roboid_cheese_neopixel_set_led_to_rgb:\n                '치즈 스틱 %1: 네오픽셀 %2번째 LED를 R: %3 G: %4 B: %5(으)로 정하기 %6',\n            roboid_cheese_neopixel_clear_led: '치즈 스틱 %1: 네오픽셀 %2번째 LED 끄기 %3',\n            roboid_cheese_neopixel_set_led_range_to_pattern:\n                '치즈 스틱 %1: 네오픽셀 %2번째부터 %3번째까지의 LED를 %4 패턴으로 정하기 %5',\n            roboid_cheese_neopixel_set_led_range_to_color:\n                '치즈 스틱 %1: 네오픽셀 %2번째부터 %3번째까지 %4칸 간격의 LED를 %5으로 정하기 %6',\n            roboid_cheese_neopixel_pick_led_range_to:\n                '치즈 스틱 %1: 네오픽셀 %2번째부터 %3번째까지 %4칸 간격의 LED를 %5로 정하기 %6',\n            roboid_cheese_neopixel_change_led_range_by_rgb:\n                '치즈 스틱 %1: 네오픽셀 %2번째부터 %3번째까지 %4칸 간격의 LED를 R: %5 G: %6 B: %7만큼 바꾸기 %8',\n            roboid_cheese_neopixel_set_led_range_to_rgb:\n                '치즈 스틱 %1: 네오픽셀 %2번째부터 %3번째까지 %4칸 간격의 LED를 R: %5 G: %6 B: %7(으)로 정하기 %8',\n            roboid_cheese_neopixel_clear_led_range:\n                '치즈 스틱 %1: 네오픽셀 %2번째부터 %3번째까지 %4칸 간격의 LED 끄기 %5',\n            roboid_cheese_neopixel_shift: '치즈 스틱 %1: 네오픽셀 %2칸 이동하기 %3',\n            roboid_cheese_neopixel_rotate: '치즈 스틱 %1: 네오픽셀 %2칸 회전하기 %3',\n            roboid_cheese_neopixel_change_brightness_by:\n                '치즈 스틱 %1: 네오픽셀 밝기를 %2%만큼 바꾸기 %3',\n            roboid_cheese_neopixel_set_brightness_to:\n                '치즈 스틱 %1: 네오픽셀 밝기를 %2%로 정하기 %3',\n            roboid_cheese_write_serial: '치즈 스틱 %1: 시리얼 %2 %3 쓰기 %4',\n            roboid_cheese_read_serial_until: '치즈 스틱 %1: 시리얼 %2 읽기 %3',\n            roboid_cheese_set_serial_port_to: '치즈 스틱 %1: 시리얼 포트를 %2로 정하기 %3',\n            roboid_cheese_set_serial_rate_to: '치즈 스틱 %1: 시리얼 속도를 %2Bd로 정하기 %3',\n            roboid_cheese_serial_input: '치즈 스틱 %1: 시리얼 입력',\n            roboid_cheese_pid_start: '치즈 스틱 %1: %2 시작하기 %3',\n            roboid_cheese_pid_set_range_to:\n                '치즈 스틱 %1: PID %2의 범위 %3 ~ %4을(를) %5 ~ %6 소수점 %7으로 정하기 %8',\n            roboid_cheese_pid_set_three_ranges_to:\n                '치즈 스틱 %1: PID %2의 범위 %3 ~ %4 ~ %5을(를) %6 ~ %7 ~ %8 소수점 %9으로 정하기 %10',\n            roboid_cheese_pid_reset_encoder: '치즈 스틱 %1: PID 엔코더 값 초기화하기 %2',\n            roboid_cheese_pid_input: '치즈 스틱 %1: PID %2',\n            roboid_cheese_pid_button_state: '치즈 스틱 %1: PID 버튼 %2을(를) %3?',\n            roboid_cheese_hat010_start: '치즈 스틱 %1: HAT-010 5x5 매트릭스 시작하기 %2',\n            roboid_cheese_hat010_button: '치즈 스틱 %1: HAT-010 버튼 %2',\n            roboid_cheese_hat010_button_state: '치즈 스틱 %1: HAT-010 버튼 %2를 %3?',\n            roboid_cheese_hat010_background_turn_on_xy:\n                '치즈 스틱 %1: HAT-010 배경 x: %2 y: %3 %4으로 켜기 %5',\n            roboid_cheese_hat010_background_turn_off_xy:\n                '치즈 스틱 %1: HAT-010 배경 x: %2 y: %3 끄기 %4',\n            roboid_cheese_hat010_background_draw_shape_at_xy:\n                '치즈 스틱 %1: HAT-010 배경 %2 %3을(를) x: %4 y: %5에 그리기 %6',\n            roboid_cheese_hat010_background_draw_string_at_xy:\n                '치즈 스틱 %1: HAT-010 배경 %2 글자 %3을(를) x: %4 y: %5에 그리기 %6',\n            roboid_cheese_hat010_background_draw_pattern_at_xy:\n                '치즈 스틱 %1: HAT-010 배경 %2 패턴 %3을(를) x: %4 y: %5에 그리기 %6',\n            roboid_cheese_hat010_clear: '치즈 스틱 %1: HAT-010 %2 지우기 %3',\n            roboid_cheese_hat010_scroll_by_xy:\n                '치즈 스틱 %1: HAT-010 %2 x: %3 y: %4만큼 이동하기 %5',\n            roboid_cheese_hat010_sprite_set_to_shape:\n                '치즈 스틱 %1: HAT-010 그림 %2을(를) %3 %4(으)로 정하기 %5',\n            roboid_cheese_hat010_sprite_set_to_string:\n                '치즈 스틱 %1: HAT-010 그림 %2을(를) %3 글자 %4(으)로 정하기 %5',\n            roboid_cheese_hat010_sprite_set_to_pattern:\n                '치즈 스틱 %1: HAT-010 그림 %2을(를) %3 패턴 %4(으)로 정하기 %5',\n            roboid_cheese_hat010_sprite_clear_show_hide: '치즈 스틱 %1: HAT-010 그림 %2 %3 %4',\n            roboid_cheese_hat010_sprite_change_positions_by_xy:\n                '치즈 스틱 %1: HAT-010 그림 %2의 위치를 x: %3 y: %4만큼 바꾸기 %5',\n            roboid_cheese_hat010_sprite_set_positions_to_xy:\n                '치즈 스틱 %1: HAT-010 그림 %2의 위치를 x: %3 y: %4(으)로 정하기 %5',\n            roboid_cheese_hat010_sprite_change_position_by_value:\n                '치즈 스틱 %1: HAT-010 그림 %2의 %3 위치를 %4만큼 바꾸기 %5',\n            roboid_cheese_hat010_sprite_set_position_to_value:\n                '치즈 스틱 %1: HAT-010 그림 %2의 %3 위치를 %4(으)로 정하기 %5',\n            roboid_cheese_hat010_sprite_rotate:\n                '치즈 스틱 %1: HAT-010 그림 %2을(를) %3 방향으로 회전하기 %4',\n            roboid_cheese_hat010_sprite_flip_in_direction:\n                '치즈 스틱 %1: HAT-010 그림 %2을(를) %3 방향으로 뒤집기 %4',\n            roboid_cheese_hat010_sprite_stamp_to_background:\n                '치즈 스틱 %1: HAT-010 그림 %2을(를) 배경에 도장 찍기 %3',\n            roboid_cheese_hat010_sprite_position: '치즈 스틱 %1: HAT-010 그림 %2의 %3 위치',\n            roboid_cheese_hat010_sprite_touching_sprite:\n                '치즈 스틱 %1: HAT-010 그림 %2이(가) 그림 %3에 닿았는가?',\n            roboid_cheese_hat010_sprite_touching:\n                '치즈 스틱 %1: HAT-010 그림 %2이(가) %3에 닿았는가?',\n            roboid_cheese_hat010_change_brightness_by:\n                '치즈 스틱 %1: HAT-010 밝기를 %2%만큼 바꾸기 %3',\n            roboid_cheese_hat010_set_brightness_to: '치즈 스틱 %1: HAT-010 밝기를 %2%로 정하기 %3',\n        },\n        Helper: {\n            roboid_hamster_beep: '버저 소리를 짧게 냅니다.',\n            roboid_hamster_change_both_wheels_by:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            roboid_hamster_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            roboid_hamster_change_output_by:\n                '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n            roboid_hamster_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            roboid_hamster_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            roboid_hamster_clear_buzzer: '버저 소리를 끕니다.',\n            roboid_hamster_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n            roboid_hamster_follow_line_until:\n                '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n            roboid_hamster_follow_line_using:\n                '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n            roboid_hamster_hand_found:\n                \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_hamster_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n            roboid_hamster_move_forward_for_secs: '입력한 시간(초) 동안 앞으로 이동합니다.',\n            roboid_hamster_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n            roboid_hamster_play_note_for:\n                '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            roboid_hamster_rest_for: '입력한 박자만큼 쉽니다.',\n            roboid_hamster_set_both_wheels_to:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            roboid_hamster_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n            roboid_hamster_set_following_speed_to:\n                '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            roboid_hamster_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n            roboid_hamster_set_output_to:\n                '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n            roboid_hamster_set_port_to:\n                '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n            roboid_hamster_set_tempo_to:\n                '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n            roboid_hamster_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            roboid_hamster_stop: '양쪽 바퀴를 정지합니다.',\n            roboid_hamster_turn_for_secs:\n                '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            roboid_hamster_turn_once:\n                '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n            roboid_hamster_value:\n                '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n            roboid_turtle_button_state:\n                \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_turtle_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            roboid_turtle_change_head_led_by_rgb:\n                '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            roboid_turtle_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            roboid_turtle_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            roboid_turtle_change_wheels_by_left_right:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            roboid_turtle_clear_head_led: '머리 LED를 끕니다.',\n            roboid_turtle_clear_sound: '소리를 끕니다.',\n            roboid_turtle_cross_intersection:\n                '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n            roboid_turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n            roboid_turtle_follow_line_until:\n                '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n            roboid_turtle_follow_line_until_black:\n                '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n            roboid_turtle_is_color_pattern:\n                \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            roboid_turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n            roboid_turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            roboid_turtle_play_note_for_beats:\n                '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            roboid_turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            roboid_turtle_play_sound_times_until_done:\n                '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            roboid_turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n            roboid_turtle_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n            roboid_turtle_set_following_speed_to:\n                '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            roboid_turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n            roboid_turtle_set_head_led_to_rgb:\n                '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            roboid_turtle_set_tempo_to:\n                '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n            roboid_turtle_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            roboid_turtle_set_wheels_to_left_right:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            roboid_turtle_stop: '양쪽 바퀴를 정지합니다.',\n            roboid_turtle_touching_color:\n                \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_turtle_turn_at_intersection:\n                '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n            roboid_turtle_turn_unit_in_place:\n                '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n            roboid_turtle_value:\n                '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n            roboid_hamster_gripper: '집게를 열거나 닫습니다.',\n            roboid_hamster_release_gripper: '집게의 전원을 끄고 자유롭게 움직일 수 있도록 합니다.',\n            roboid_hamster_boolean:\n                \"앞으로 기울임: 앞으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_hamster_play_note: '선택한 계이름과 옥타브의 음을 소리 냅니다.',\n            roboid_hamster_s_hand_found:\n                \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_hamster_s_boolean:\n                \"앞으로 기울임: 앞으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_hamster_s_value:\n                '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n            roboid_hamster_s_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n            roboid_hamster_s_turn_once:\n                '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n            roboid_hamster_s_move_forward_unit:\n                '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            roboid_hamster_s_move_backward_unit:\n                '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            roboid_hamster_s_turn_unit_in_place:\n                '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            roboid_hamster_s_pivot_around_unit_in_direction:\n                '왼쪽/오른쪽 펜/바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 앞쪽/뒤쪽 방향으로 회전합니다.',\n            roboid_hamster_s_turn_unit_with_radius_in_direction:\n                '왼쪽/오른쪽 펜이 입력한 반지름의 원을 왼쪽/오른쪽에 그리면서 입력한 각도(도)/시간(초)/펄스만큼 앞쪽/뒤쪽 방향으로 회전합니다.',\n            roboid_hamster_s_change_both_wheels_by:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            roboid_hamster_s_set_both_wheels_to:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            roboid_hamster_s_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            roboid_hamster_s_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            roboid_hamster_s_follow_line_using:\n                '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n            roboid_hamster_s_follow_line_until:\n                '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n            roboid_hamster_s_set_following_speed_to:\n                '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            roboid_hamster_s_set_following_gain_to:\n                '선을 따라 이동하는 방향 변화량(1 ~ 8)을 설정합니다. 숫자가 클수록 급커브를 잘 따라가지만 직선에서 좌우로 더 흔들립니다.',\n            roboid_hamster_s_stop: '양쪽 바퀴를 정지합니다.',\n            roboid_hamster_s_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n            roboid_hamster_s_pick_led: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n            roboid_hamster_s_change_led_by_rgb:\n                '왼쪽/오른쪽/양쪽 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            roboid_hamster_s_set_led_to_rgb:\n                '왼쪽/오른쪽/양쪽 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            roboid_hamster_s_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n            roboid_hamster_s_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            roboid_hamster_s_play_sound_times_until_done:\n                '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            roboid_hamster_s_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            roboid_hamster_s_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n            roboid_hamster_s_clear_sound: '소리를 끕니다.',\n            roboid_hamster_s_play_note: '선택한 계이름과 옥타브의 음을 소리 냅니다.',\n            roboid_hamster_s_play_note_for:\n                '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            roboid_hamster_s_rest_for: '입력한 박자만큼 쉽니다.',\n            roboid_hamster_s_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            roboid_hamster_s_set_tempo_to:\n                '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n            roboid_hamster_s_set_port_to:\n                '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n            roboid_hamster_s_change_output_by:\n                '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n            roboid_hamster_s_set_output_to:\n                '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n            roboid_hamster_s_gripper: '집게를 열거나 닫습니다.',\n            roboid_hamster_s_release_gripper:\n                '집게의 전원을 끄고 자유롭게 움직일 수 있도록 합니다.',\n            roboid_hamster_s_write_serial: '시리얼 통신으로 글자를 전송합니다.',\n            roboid_hamster_s_read_serial_until: '시리얼 통신으로 받은 글자를 읽습니다.',\n            roboid_hamster_s_set_serial_rate_to: '시리얼 통신의 속도를 설정합니다.',\n            roboid_turtle_button_state:\n                \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_turtle_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            roboid_turtle_change_head_led_by_rgb:\n                '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            roboid_turtle_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            roboid_turtle_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            roboid_turtle_change_wheels_by_left_right:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            roboid_turtle_clear_head_led: '머리 LED를 끕니다.',\n            roboid_turtle_clear_sound: '소리를 끕니다.',\n            roboid_turtle_cross_intersection:\n                '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n            roboid_turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n            roboid_turtle_follow_line_until:\n                '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n            roboid_turtle_follow_line_until_black:\n                '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n            roboid_turtle_is_color_pattern:\n                \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            roboid_turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n            roboid_turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            roboid_turtle_play_note_for_beats:\n                '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            roboid_turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            roboid_turtle_play_sound_times_until_done:\n                '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            roboid_turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n            roboid_turtle_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n            roboid_turtle_set_following_speed_to:\n                '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            roboid_turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n            roboid_turtle_set_head_led_to_rgb:\n                '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            roboid_turtle_set_tempo_to:\n                '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n            roboid_turtle_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            roboid_turtle_set_wheels_to_left_right:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            roboid_turtle_stop: '양쪽 바퀴를 정지합니다.',\n            roboid_turtle_touching_color:\n                \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_turtle_turn_at_intersection:\n                '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n            roboid_turtle_turn_unit_in_place:\n                '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n            roboid_turtle_value:\n                '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n            roboid_turtle_boolean:\n                \"앞으로 기울임: 앞으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            roboid_turtle_pick_head_led: '머리 LED를 선택한 색깔로 켭니다.',\n        },\n        Blocks: {\n            ROBOID_acceleration_x: 'x축 가속도',\n            ROBOID_acceleration_y: 'y축 가속도',\n            ROBOID_acceleration_z: 'z축 가속도',\n            ROBOID_back: '뒤쪽',\n            ROBOID_both: '양쪽',\n            ROBOID_button: '버튼',\n            ROBOID_buzzer: '버저',\n            ROBOID_clicked: '클릭했는가',\n            ROBOID_color_any: '아무 색',\n            ROBOID_color_black: '검은색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_number: '색깔 번호',\n            ROBOID_color_orange: '주황색',\n            ROBOID_color_pattern: '색깔 패턴',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_violet: '보라색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_double_clicked: '더블클릭했는가',\n            ROBOID_floor: '바닥 센서',\n            ROBOID_head: '머리',\n            ROBOID_head_color: '머리 색깔',\n            ROBOID_left: '왼쪽',\n            ROBOID_left_wheel: '왼쪽 바퀴',\n            ROBOID_long_pressed: '길게~눌렀는가',\n            ROBOID_note: '음표',\n            ROBOID_right: '오른쪽',\n            ROBOID_right_wheel: '오른쪽 바퀴',\n            ROBOID_sound_beep: '삐',\n            ROBOID_sound_birthday: '생일',\n            ROBOID_sound_dibidibidip: '디비디비딥',\n            ROBOID_sound_engine: '엔진',\n            ROBOID_sound_good_job: '잘 했어요',\n            ROBOID_sound_march: '행진',\n            ROBOID_sound_random_beep: '무작위 삐',\n            ROBOID_sound_robot: '로봇',\n            ROBOID_sound_siren: '사이렌',\n            ROBOID_tail: '꼬리',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_deg: '도',\n            ROBOID_unit_pulse: '펄스',\n            ROBOID_unit_sec: '초',\n            hamster_note_c: '도',\n            hamster_note_c_sharp: '도♯(레♭)',\n            hamster_note_d: '레',\n            hamster_note_d_sharp: '레♯(미♭)',\n            hamster_note_e: '미',\n            hamster_note_f: '파',\n            hamster_note_f_sharp: '파♯(솔♭)',\n            hamster_note_g: '솔',\n            hamster_note_g_sharp: '솔♯(라♭)',\n            hamster_note_a: '라',\n            hamster_note_a_sharp: '라♯(시♭)',\n            hamster_note_b: '시',\n            hamster_tilt_forward: '앞으로 기울임',\n            hamster_tilt_backward: '뒤로 기울임',\n            hamster_tilt_left: '왼쪽으로 기울임',\n            hamster_tilt_right: '오른쪽으로 기울임',\n            hamster_tilt_flip: '거꾸로 뒤집음',\n            hamster_tilt_not: '기울이지 않음',\n            hamster_battery_normal: '배터리 정상',\n            hamster_battery_low: '배터리 부족',\n            hamster_battery_empty: '배터리 없음',\n            hamster_open_gripper: '열기',\n            hamster_close_gripper: '닫기',\n            hamster_s_color_black: '검은색',\n            hamster_s_color_blue: '파란색',\n            hamster_s_color_green: '초록색',\n            hamster_s_color_orange: '주황색',\n            hamster_s_color_purple: '자주색',\n            hamster_s_color_red: '빨간색',\n            hamster_s_color_sky_blue: '하늘색',\n            hamster_s_color_violet: '보라색',\n            hamster_s_color_white: '하얀색',\n            hamster_s_color_yellow: '노란색',\n            hamster_s_left: '왼쪽',\n            hamster_s_right: '오른쪽',\n            hamster_s_both: '양쪽',\n            hamster_s_note_c: '도',\n            hamster_s_note_c_sharp: '도♯(레♭)',\n            hamster_s_note_d: '레',\n            hamster_s_note_d_sharp: '레♯(미♭)',\n            hamster_s_note_e: '미',\n            hamster_s_note_f: '파',\n            hamster_s_note_f_sharp: '파♯(솔♭)',\n            hamster_s_note_g: '솔',\n            hamster_s_note_g_sharp: '솔♯(라♭)',\n            hamster_s_note_a: '라',\n            hamster_s_note_a_sharp: '라♯(시♭)',\n            hamster_s_note_b: '시',\n            hamster_s_port_a: 'A',\n            hamster_s_port_b: 'B',\n            hamster_s_port_ab: 'A와 B',\n            hamster_s_tilt_forward: '앞으로 기울임',\n            hamster_s_tilt_backward: '뒤로 기울임',\n            hamster_s_tilt_left: '왼쪽으로 기울임',\n            hamster_s_tilt_right: '오른쪽으로 기울임',\n            hamster_s_tilt_flip: '거꾸로 뒤집음',\n            hamster_s_tilt_not: '기울이지 않음',\n            hamster_s_tap: '두드림',\n            hamster_s_free_fall: '자유 낙하',\n            hamster_s_battery_normal: '배터리 정상',\n            hamster_s_battery_low: '배터리 부족',\n            hamster_s_battery_empty: '배터리 없음',\n            hamster_s_forward: '앞쪽',\n            hamster_s_backward: '뒤쪽',\n            hamster_s_front: '앞쪽',\n            hamster_s_rear: '뒤쪽',\n            hamster_s_left_pen: '왼쪽 펜',\n            hamster_s_right_pen: '오른쪽 펜',\n            hamster_s_left_wheel: '왼쪽 바퀴',\n            hamster_s_right_wheel: '오른쪽 바퀴',\n            hamster_s_robot: '로봇',\n            hamster_s_gain_default: '기본 값',\n            hamster_s_sensor_acceleration_x: 'x축 가속도',\n            hamster_s_sensor_acceleration_y: 'y축 가속도',\n            hamster_s_sensor_acceleration_z: 'z축 가속도',\n            hamster_s_sensor_input_a: '입력 A',\n            hamster_s_sensor_input_b: '입력 B',\n            hamster_s_sensor_left_floor: '왼쪽 바닥 센서',\n            hamster_s_sensor_left_proximity: '왼쪽 근접 센서',\n            hamster_s_sensor_light: '밝기',\n            hamster_s_sensor_right_floor: '오른쪽 바닥 센서',\n            hamster_s_sensor_right_proximity: '오른쪽 근접 센서',\n            hamster_s_sensor_signal_strength: '신호 세기',\n            hamster_s_sensor_temperature: '온도',\n            hamster_s_buzzer: '버저',\n            hamster_s_left_led: '왼쪽 LED',\n            hamster_s_left_wheel: '왼쪽 바퀴',\n            hamster_s_note: '음표',\n            hamster_s_output_a: '출력 A',\n            hamster_s_output_b: '출력 B',\n            hamster_s_right_led: '오른쪽 LED',\n            hamster_s_right_wheel: '오른쪽 바퀴',\n            hamster_s_sound_angry: '화남',\n            hamster_s_sound_beep: '삐',\n            hamster_s_sound_birthday: '생일',\n            hamster_s_sound_chop: '쩝',\n            hamster_s_sound_dibidibidip: '디비디비딥',\n            hamster_s_sound_engine: '엔진',\n            hamster_s_sound_good_job: '잘 했어요',\n            hamster_s_sound_happy: '행복',\n            hamster_s_sound_march: '행진',\n            hamster_s_sound_noise: '지지직',\n            hamster_s_sound_random_beep: '무작위 삐',\n            hamster_s_sound_robot: '로봇',\n            hamster_s_sound_sad: '슬픔',\n            hamster_s_sound_siren: '사이렌',\n            hamster_s_sound_sleep: '졸림',\n            hamster_s_unit_cm: 'cm',\n            hamster_s_unit_deg: '도',\n            hamster_s_unit_pulse: '펄스',\n            hamster_s_unit_sec: '초',\n            hamster_s_analog_input: '아날로그 입력',\n            hamster_s_digital_input: '디지털 입력',\n            hamster_s_digital_input_pull_down: '디지털 입력 (풀다운)',\n            hamster_s_digital_input_pull_up: '디지털 입력 (풀업)',\n            hamster_s_digital_output: '디지털 출력',\n            hamster_s_pwm_output: 'PWM 출력',\n            hamster_s_servo_output: '서보 출력',\n            hamster_s_voltage_input: '전압 입력',\n            hamster_s_open_gripper: '열기',\n            hamster_s_close_gripper: '닫기',\n            hamster_s_serial_string: '글자',\n            hamster_s_serial_string_line: '글자 한 줄',\n            hamster_s_serial_all: '모두',\n            hamster_s_serial_until_new_line: '줄 바꿈까지',\n            hamster_s_serial_until_comma: ',(쉼표)까지',\n            hamster_s_serial_until_colon: ':(쌍점)까지',\n            hamster_s_serial_until_dollar: '$까지',\n            hamster_s_serial_until_sharp: '#까지',\n            hamster_s_serial_input: '시리얼 입력',\n            turtle_acceleration_x: 'x축 가속도',\n            turtle_acceleration_y: 'y축 가속도',\n            turtle_acceleration_z: 'z축 가속도',\n            turtle_back: '뒤쪽',\n            turtle_both: '양쪽',\n            turtle_button: '버튼',\n            turtle_buzzer: '버저',\n            turtle_clicked: '클릭했는가',\n            turtle_color_any: '아무 색',\n            turtle_color_black: '검은색',\n            turtle_color_blue: '파란색',\n            turtle_color_green: '초록색',\n            turtle_color_number: '색깔 번호',\n            turtle_color_orange: '주황색',\n            turtle_color_pattern: '색깔 패턴',\n            turtle_color_purple: '자주색',\n            turtle_color_red: '빨간색',\n            turtle_color_sky_blue: '하늘색',\n            turtle_color_violet: '보라색',\n            turtle_color_white: '하얀색',\n            turtle_color_yellow: '노란색',\n            turtle_double_clicked: '더블클릭했는가',\n            turtle_floor: '바닥 센서',\n            turtle_head: '머리',\n            turtle_head_color: '머리 색깔',\n            turtle_left: '왼쪽',\n            turtle_left_wheel: '왼쪽 바퀴',\n            turtle_long_pressed: '길게~눌렀는가',\n            turtle_note: '음표',\n            turtle_right: '오른쪽',\n            turtle_right_wheel: '오른쪽 바퀴',\n            turtle_sound_beep: '삐',\n            turtle_sound_birthday: '생일',\n            turtle_sound_dibidibidip: '디비디비딥',\n            turtle_sound_engine: '엔진',\n            turtle_sound_good_job: '잘 했어요',\n            turtle_sound_march: '행진',\n            turtle_sound_random_beep: '무작위 삐',\n            turtle_sound_robot: '로봇',\n            turtle_sound_siren: '사이렌',\n            turtle_tail: '꼬리',\n            turtle_unit_cm: 'cm',\n            turtle_unit_deg: '도',\n            turtle_unit_pulse: '펄스',\n            turtle_unit_sec: '초',\n            turtle_note_c: '도',\n            turtle_note_c_sharp: '도♯(레♭)',\n            turtle_note_d: '레',\n            turtle_note_d_sharp: '레♯(미♭)',\n            turtle_note_e: '미',\n            turtle_note_f: '파',\n            turtle_note_f_sharp: '파♯(솔♭)',\n            turtle_note_g: '솔',\n            turtle_note_g_sharp: '솔♯(라♭)',\n            turtle_note_a: '라',\n            turtle_note_a_sharp: '라♯(시♭)',\n            turtle_note_b: '시',\n            turtle_tilt_forward: '앞으로 기울임',\n            turtle_tilt_backward: '뒤로 기울임',\n            turtle_tilt_left: '왼쪽으로 기울임',\n            turtle_tilt_right: '오른쪽으로 기울임',\n            turtle_tilt_flip: '거꾸로 뒤집음',\n            turtle_tilt_not: '기울이지 않음',\n            turtle_battery_normal: '배터리 정상',\n            turtle_battery_low: '배터리 부족',\n            turtle_battery_empty: '배터리 없음',\n            ROBOID_cheese_stick: '치즈 스틱',\n            ROBOID_sensor_signal_strength: '신호 세기',\n            ROBOID_sensor_signal_strength_dbm: '신호 세기 (dBm)',\n            ROBOID_sensor_acceleration_x: 'x축 가속도',\n            ROBOID_sensor_acceleration_y: 'y축 가속도',\n            ROBOID_sensor_acceleration_z: 'z축 가속도',\n            ROBOID_sensor_input_sa: '입력 Sa',\n            ROBOID_sensor_input_sb: '입력 Sb',\n            ROBOID_sensor_input_sc: '입력 Sc',\n            ROBOID_sensor_input_la: '입력 La',\n            ROBOID_sensor_input_lb: '입력 Lb',\n            ROBOID_sensor_input_lc: '입력 Lc',\n            ROBOID_sensor_step_count: '스텝 수',\n            ROBOID_monitor_output_sa: '출력 Sa',\n            ROBOID_monitor_output_sb: '출력 Sb',\n            ROBOID_monitor_output_sc: '출력 Sc',\n            ROBOID_monitor_output_la: '출력 La',\n            ROBOID_monitor_output_lb: '출력 Lb',\n            ROBOID_monitor_output_lc: '출력 Lc',\n            ROBOID_monitor_output_mab: '출력 Mab',\n            ROBOID_monitor_output_mcd: '출력 Mcd',\n            ROBOID_monitor_buzzer: '버저',\n            ROBOID_monitor_note: '음표',\n            ROBOID_logo_sky_direction: '로고가 하늘 방향',\n            ROBOID_logo_earth_direction: '로고가 땅 방향',\n            ROBOID_power_switch_sky_direction: '전원 스위치가 하늘 방향',\n            ROBOID_power_switch_earth_direction: '전원 스위치가 땅 방향',\n            ROBOID_port_s_sky_direction: '포트 S가 하늘 방향',\n            ROBOID_port_s_earth_direction: '포트 S가 땅 방향',\n            ROBOID_tap: '두드림',\n            ROBOID_free_fall: '자유 낙하',\n            ROBOID_battery_normal: '배터리 정상',\n            ROBOID_battery_low: '배터리 부족',\n            ROBOID_battery_empty: '배터리 없음',\n            ROBOID_sound_beep: '삐',\n            ROBOID_sound_random_beep: '무작위 삐',\n            ROBOID_sound_noise: '지지직',\n            ROBOID_sound_siren: '사이렌',\n            ROBOID_sound_engine: '엔진',\n            ROBOID_sound_chop: '쩝',\n            ROBOID_sound_robot: '로봇',\n            ROBOID_sound_dibidibidip: '디비디비딥',\n            ROBOID_sound_good_job: '잘 했어요',\n            ROBOID_sound_happy: '행복',\n            ROBOID_sound_angry: '화남',\n            ROBOID_sound_sad: '슬픔',\n            ROBOID_sound_sleep: '졸림',\n            ROBOID_sound_march: '행진',\n            ROBOID_sound_birthday: '생일',\n            ROBOID_note_c: '도',\n            ROBOID_note_c_sharp: '도♯(레♭)',\n            ROBOID_note_d: '레',\n            ROBOID_note_d_sharp: '레♯(미♭)',\n            ROBOID_note_e: '미',\n            ROBOID_note_f: '파',\n            ROBOID_note_f_sharp: '파♯(솔♭)',\n            ROBOID_note_g: '솔',\n            ROBOID_note_g_sharp: '솔♯(라♭)',\n            ROBOID_note_a: '라',\n            ROBOID_note_a_sharp: '라♯(시♭)',\n            ROBOID_note_b: '시',\n            ROBOID_speaker_internal: '내부 스피커',\n            ROBOID_speaker_port_mab: '포트 Mab',\n            ROBOID_io_mode_makey: '메이키',\n            ROBOID_io_mode_button: '버튼',\n            ROBOID_io_mode_digital_pull_up: '디지털 (풀업)',\n            ROBOID_io_mode_digital_pull_down: '디지털 (풀다운)',\n            ROBOID_io_mode_analog: '아날로그',\n            ROBOID_io_mode_voltage: '전압',\n            ROBOID_io_mode_pulse: '펄스',\n            ROBOID_io_mode_pulse_pull_up: '펄스 (풀업)',\n            ROBOID_io_mode_pulse_pull_down: '펄스 (풀다운)',\n            ROBOID_io_mode_normal: '기본',\n            ROBOID_io_mode_power: '파워',\n            ROBOID_io_port_high_current_mab: '고전류 Ma(-)b',\n            ROBOID_io_port_high_current_mcd: '고전류 Mc(-)d',\n            ROBOID_io_action_stop: '정지하기',\n            ROBOID_io_action_turn_off: '전원 끄기',\n            ROBOID_range_integer: '없음',\n            ROBOID_range_real: '있음',\n            ROBOID_led_intensity_dark: '어두운',\n            ROBOID_led_intensity_normal: '기본',\n            ROBOID_led_intensity_bright: '밝은',\n            ROBOID_led_type_default: '기본',\n            ROBOID_led_type_crgb: '-RGB',\n            ROBOID_led_type_crbg: '-RBG',\n            ROBOID_led_type_cgrb: '-GRB',\n            ROBOID_led_type_cgbr: '-GBR',\n            ROBOID_led_type_cbrg: '-BRG',\n            ROBOID_led_type_cbgr: '-BGR',\n            ROBOID_led_type_argb: '+RGB',\n            ROBOID_led_type_arbg: '+RBG',\n            ROBOID_led_type_agrb: '+GRB',\n            ROBOID_led_type_agbr: '+GBR',\n            ROBOID_led_type_abrg: '+BRG',\n            ROBOID_led_type_abgr: '+BGR',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_orange: '주황색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_violet: '보라색',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_neopixel_3_colors: '3색',\n            ROBOID_neopixel_6_colors: '6색',\n            ROBOID_neopixel_12_colors: '12색',\n            ROBOID_neopixel_red_green: '빨간색부터 초록색까지',\n            ROBOID_neopixel_red_blue: '빨간색부터 파란색까지',\n            ROBOID_neopixel_red_white: '빨간색부터 하얀색까지',\n            ROBOID_neopixel_green_red: '초록색부터 빨간색까지',\n            ROBOID_neopixel_green_blue: '초록색부터 파란색까지',\n            ROBOID_neopixel_green_white: '초록색부터 하얀색까지',\n            ROBOID_neopixel_blue_red: '파란색부터 빨간색까지',\n            ROBOID_neopixel_blue_green: '파란색부터 초록색까지',\n            ROBOID_neopixel_blue_white: '파란색부터 하얀색까지',\n            ROBOID_neopixel_white_red: '하얀색부터 빨간색까지',\n            ROBOID_neopixel_white_green: '하얀색부터 초록색까지',\n            ROBOID_neopixel_white_blue: '하얀색부터 파란색까지',\n            ROBOID_neopixel_red_black: '빨간색 점점 어둡게',\n            ROBOID_neopixel_green_black: '초록색 점점 어둡게',\n            ROBOID_neopixel_blue_black: '파란색 점점 어둡게',\n            ROBOID_neopixel_white_black: '하얀색 점점 어둡게',\n            ROBOID_neopixel_black_red: '빨간색 점점 밝게',\n            ROBOID_neopixel_black_green: '초록색 점점 밝게',\n            ROBOID_neopixel_black_blue: '파란색 점점 밝게',\n            ROBOID_neopixel_black_white: '하얀색 점점 밝게',\n            ROBOID_serial_string: '글자',\n            ROBOID_serial_string_line: '글자 한 줄',\n            ROBOID_serial_all: '모두',\n            ROBOID_serial_until_comma: ',(쉼표)까지',\n            ROBOID_serial_until_colon: ':(쌍점)까지',\n            ROBOID_serial_until_dollar: '$까지',\n            ROBOID_serial_until_sharp: '#까지',\n            ROBOID_serial_until_new_line: '줄 바꿈까지',\n            ROBOID_serial_port_wa_rb: 'La(쓰기) Lb(읽기)',\n            ROBOID_serial_port_ra_wb: 'La(읽기) Lb(쓰기)',\n            ROBOID_serial_port_wa: 'La(쓰기)',\n            ROBOID_serial_port_ra: 'La(읽기)',\n            ROBOID_pid_10: 'PID-10 초음파 센서(HC-SR04+)',\n            ROBOID_pid_11_1: 'PID-11-1 온습도 센서(DHT11)',\n            ROBOID_pid_11_2: 'PID-11-2 온습도 센서(DHT21)',\n            ROBOID_pid_11_3: 'PID-11-3 온습도 센서(DHT22)',\n            ROBOID_pid_12: 'PID-12 온도 센서(DS18B20)',\n            ROBOID_pid_13: 'PID-13 조이스틱과 버튼',\n            ROBOID_pid_14: 'PID-14 듀얼 조이스틱',\n            ROBOID_pid_15: 'PID-15 IR 송수신기',\n            ROBOID_pid_16: 'PID-16 엔코더',\n            ROBOID_pid_distance: '거리 (cm)',\n            ROBOID_pid_temperature: '온도 (℃)',\n            ROBOID_pid_humidity: '습도 (%RH)',\n            ROBOID_pid_x1: 'x1',\n            ROBOID_pid_y1: 'y1',\n            ROBOID_pid_x2: 'x2',\n            ROBOID_pid_y2: 'y2',\n            ROBOID_pid_button1: '버튼1',\n            ROBOID_pid_button2: '버튼2',\n            ROBOID_pid_encoder: '엔코더',\n            ROBOID_clicked: '클릭했는가',\n            ROBOID_double_clicked: '더블클릭했는가',\n            ROBOID_long_pressed: '오래 눌렀는가',\n            ROBOID_shape_square: '사각형',\n            ROBOID_shape_triangle: '삼각형',\n            ROBOID_shape_diamond: '다이아몬드',\n            ROBOID_shape_circle: '원',\n            ROBOID_shape_x: 'X',\n            ROBOID_shape_like: '좋음',\n            ROBOID_shape_dislike: '싫음',\n            ROBOID_shape_angry: '화남',\n            ROBOID_shape_open_mouth: '입 열기',\n            ROBOID_shape_close_mouth: '입 닫기',\n            ROBOID_shape_walk1: '걷기 1',\n            ROBOID_shape_walk2: '걷기 2',\n            ROBOID_shape_heart: '하트',\n            ROBOID_shape_star: '별',\n            ROBOID_shape_airplane: '비행기',\n            ROBOID_shape_puppy: '강아지',\n            ROBOID_shape_butterfly: '나비',\n            ROBOID_shape_quarter_note: '4분 음표',\n            ROBOID_shape_eighth_note: '8분 음표',\n            ROBOID_shape_left_arrow: '왼쪽 화살표',\n            ROBOID_shape_right_arrow: '오른쪽 화살표',\n            ROBOID_shape_up_arrow: '위쪽 화살표',\n            ROBOID_shape_down_arrow: '아래쪽 화살표',\n            ROBOID_hat_background: '배경',\n            ROBOID_hat_all: '모두',\n            ROBOID_hat_clear: '지우기',\n            ROBOID_hat_show: '보이기',\n            ROBOID_hat_hide: '숨기기',\n            ROBOID_hat_clockwise: '시계',\n            ROBOID_hat_counterclockwise: '반시계',\n            ROBOID_hat_left_right: '왼쪽-오른쪽',\n            ROBOID_hat_up_down: '위-아래',\n            ROBOID_hat_auto: '자동',\n            ROBOID_hat_manual: '수동',\n            ROBOID_hat_other_sprite: '다른 그림',\n            ROBOID_hat_left_wall: '왼쪽 벽',\n            ROBOID_hat_right_wall: '오른쪽 벽',\n            ROBOID_hat_top_wall: '위쪽 벽',\n            ROBOID_hat_bottom_wall: '아래쪽 벽',\n            ROBOID_hat_any_wall: '아무 벽',\n        },\n    },\n    en: {\n        template: {\n            roboid_hamster_beep: 'Hamster %1: beep %2',\n            roboid_hamster_change_both_wheels_by:\n                'Hamster %1: change wheels by left: %2 right: %3 %4',\n            roboid_hamster_change_buzzer_by: 'Hamster %1: change buzzer by %2 %3',\n            roboid_hamster_change_output_by: 'Hamster %1: change output %2 by %3 %4',\n            roboid_hamster_change_tempo_by: 'Hamster %1: change tempo by %2 %3',\n            roboid_hamster_change_wheel_by: 'Hamster %1: change %2 wheel by %3 %4',\n            roboid_hamster_clear_buzzer: 'Hamster %1: clear buzzer %2',\n            roboid_hamster_clear_led: 'Hamster %1: clear %2 led %3',\n            roboid_hamster_follow_line_until: 'Hamster %1: follow %2 line until %3 intersection %4',\n            roboid_hamster_follow_line_using: 'Hamster %1: follow %2 line using %3 floor sensor %4',\n            roboid_hamster_hand_found: 'Hamster %1: hand found?',\n            roboid_hamster_move_backward_for_secs: 'Hamster %1: move backward for %2 secs %3',\n            roboid_hamster_move_forward_for_secs: 'Hamster %1: move forward for %2 secs %3',\n            roboid_hamster_move_forward_once: 'Hamster %1: move forward once on board %2',\n            roboid_hamster_play_note_for: 'Hamster %1: play note %2 %3 for %4 beats %5',\n            roboid_hamster_rest_for: 'Hamster %1: rest for %2 beats %3',\n            roboid_hamster_set_both_wheels_to: 'Hamster %1: set wheels to left: %2 right: %3 %4',\n            roboid_hamster_set_buzzer_to: 'Hamster %1: set buzzer to %2 %3',\n            roboid_hamster_set_following_speed_to: 'Hamster %1: set following speed to %2 %3',\n            roboid_hamster_set_led_to: 'Hamster %1: set %2 led to %3 %4',\n            roboid_hamster_set_output_to: 'Hamster %1: set output %2 to %3 %4',\n            roboid_hamster_set_port_to: 'Hamster %1: set port %2 to %3 %4',\n            roboid_hamster_set_tempo_to: 'Hamster %1: set tempo to %2 bpm %3',\n            roboid_hamster_set_wheel_to: 'Hamster %1: set %2 wheel to %3 %4',\n            roboid_hamster_stop: 'Hamster %1: stop %2',\n            roboid_hamster_turn_for_secs: 'Hamster %1: turn %2 for %3 secs %4',\n            roboid_hamster_turn_once: 'Hamster %1: turn %2 once on board %3',\n            roboid_hamster_value: 'Hamster %1: %2',\n            roboid_turtle_button_state: 'Turtle %1: button %2 ?',\n            roboid_turtle_change_buzzer_by: 'Turtle %1: change buzzer by %2 %3',\n            roboid_turtle_change_head_led_by_rgb:\n                'Turtle %1: change head led by r: %2 g: %3 b: %4 %5',\n            roboid_turtle_change_tempo_by: 'Turtle %1: change tempo by %2 %3',\n            roboid_turtle_change_wheel_by: 'Turtle %1: change %2 wheel by %3 %4',\n            roboid_turtle_change_wheels_by_left_right:\n                'Turtle %1: change wheels by left: %2 right: %3 %4',\n            roboid_turtle_clear_head_led: 'Turtle %1: clear head led %2',\n            roboid_turtle_clear_sound: 'Turtle %1: clear sound %2',\n            roboid_turtle_cross_intersection: 'Turtle %1: cross black intersection %2',\n            roboid_turtle_follow_line: 'Turtle %1: follow %2 line %3',\n            roboid_turtle_follow_line_until: 'Turtle %1: follow black line until %2 %3',\n            roboid_turtle_follow_line_until_black: 'Turtle %1: follow %2 line until black %3',\n            roboid_turtle_is_color_pattern: 'Turtle %1: color pattern %2 %3 ?',\n            roboid_turtle_move_backward_unit: 'Turtle %1: move backward %2 %3 %4',\n            roboid_turtle_move_forward_unit: 'Turtle %1: move forward %2 %3 %4',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                'Turtle %1: pivot around %2 wheel %3 %4 in %5 direction %6',\n            roboid_turtle_play_note: 'Turtle %1: play note %2 %3 %4',\n            roboid_turtle_play_note_for_beats: 'Turtle %1: play note %2 %3 for %4 beats %5',\n            roboid_turtle_play_sound_times: 'Turtle %1: play sound %2 %3 times %4',\n            roboid_turtle_play_sound_times_until_done:\n                'Turtle %1: play sound %2 %3 times until done %4',\n            roboid_turtle_rest_for_beats: 'Turtle %1: rest for %2 beats %3',\n            roboid_turtle_set_buzzer_to: 'Turtle %1: set buzzer to %2 %3',\n            roboid_turtle_set_following_speed_to: 'Turtle %1: set following speed to %2 %3',\n            roboid_turtle_set_head_led_to: 'Turtle %1: set head led to %2 %3',\n            roboid_turtle_set_head_led_to_rgb: 'Turtle %1: set head led to r: %2 g: %3 b: %4 %5',\n            roboid_turtle_set_tempo_to: 'Turtle %1: set tempo to %2 bpm %3',\n            roboid_turtle_set_wheel_to: 'Turtle %1: set %2 wheel to %3 %4',\n            roboid_turtle_set_wheels_to_left_right:\n                'Turtle %1: set wheels to left: %2 right: %3 %4',\n            roboid_turtle_stop: 'Turtle %1: stop %2',\n            roboid_turtle_touching_color: 'Turtle %1: touching %2 ?',\n            roboid_turtle_turn_at_intersection: 'Turtle %1: turn %2 at black intersection %3',\n            roboid_turtle_turn_unit_in_place: 'Turtle %1: turn %2 %3 %4 in place %5',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                'Turtle %1: turn %2 %3 %4 with radius %5 cm in %6 direction %7',\n            roboid_turtle_value: 'Turtle %1: %2',\n            roboid_hamster_gripper: 'Hamster %1: %2 gripper %3',\n            roboid_hamster_release_gripper: 'Hamster %1: release gripper %2',\n            roboid_hamster_boolean: 'Hamster %1: %2?',\n            roboid_hamster_play_note: 'Hamster %1: play note %2 %3 %4',\n            roboid_hamster_s_hand_found: 'HamsterS %1: hand found?',\n            roboid_hamster_s_boolean: 'HamsterS %1: %2?',\n            roboid_hamster_s_value: 'HamsterS %1: %2',\n            roboid_hamster_s_move_forward_once: 'HamsterS %1: move forward once on board %2',\n            roboid_hamster_s_turn_once: 'HamsterS %1: turn %2 once on board %3',\n            roboid_hamster_s_move_forward_unit: 'HamsterS %1: move forward %2 %3 %4',\n            roboid_hamster_s_move_backward_unit: 'HamsterS %1: move backward %2 %3 %4',\n            roboid_hamster_s_turn_unit_in_place: 'HamsterS %1: turn %2 %3 %4 in place %5',\n            roboid_hamster_s_pivot_around_unit_in_direction:\n                'HamsterS %1: pivot around %2 %3 %4 in %5 direction %6',\n            roboid_hamster_s_turn_unit_with_radius_in_direction:\n                'HamsterS %1: %2 turn %3 %4 %5 with radius %6 cm in %7 direction %8',\n            roboid_hamster_s_change_both_wheels_by:\n                'HamsterS %1: change wheels by left: %2 right: %3 %4',\n            roboid_hamster_s_set_both_wheels_to: 'HamsterS %1: set wheels to left: %2 right: %3 %4',\n            roboid_hamster_s_change_wheel_by: 'HamsterS %1: change %2 wheel by %3 %4',\n            roboid_hamster_s_set_wheel_to: 'HamsterS %1: set %2 wheel to %3 %4',\n            roboid_hamster_s_follow_line_using:\n                'HamsterS %1: follow %2 line using %3 floor sensor %4',\n            roboid_hamster_s_follow_line_until:\n                'HamsterS %1: follow %2 line until %3 intersection %4',\n            roboid_hamster_s_set_following_speed_to: 'HamsterS %1: set following speed to %2 %3',\n            roboid_hamster_s_set_following_gain_to:\n                'HamsterS %1: set following directional variation to %2 %3',\n            roboid_hamster_s_stop: 'HamsterS %1: stop %2',\n            roboid_hamster_s_set_led_to: 'HamsterS %1: set %2 led to %3 %4',\n            roboid_hamster_s_pick_led: 'HamsterS %1: set %2 led to %3 %4',\n            roboid_hamster_s_change_led_by_rgb:\n                'HamsterS %1: change %2 led by r: %3 g: %4 b: %5 %6',\n            roboid_hamster_s_set_led_to_rgb: 'HamsterS %1: set %2 led to r: %3 g: %4 b: %5 %6',\n            roboid_hamster_s_clear_led: 'HamsterS %1: clear %2 led %3',\n            roboid_hamster_s_play_sound_times: 'HamsterS %1: play sound %2 %3 times %4',\n            roboid_hamster_s_play_sound_times_until_done:\n                'HamsterS %1: play sound %2 %3 times until done %4',\n            roboid_hamster_s_change_buzzer_by: 'HamsterS %1: change buzzer by %2 %3',\n            roboid_hamster_s_set_buzzer_to: 'HamsterS %1: set buzzer to %2 %3',\n            roboid_hamster_s_clear_sound: 'HamsterS %1: clear sound %2',\n            roboid_hamster_s_play_note: 'HamsterS %1: play note %2 %3 %4',\n            roboid_hamster_s_play_note_for: 'HamsterS %1: play note %2 %3 for %4 beats %5',\n            roboid_hamster_s_rest_for: 'HamsterS %1: rest for %2 beats %3',\n            roboid_hamster_s_change_tempo_by: 'HamsterS %1: change tempo by %2 %3',\n            roboid_hamster_s_set_tempo_to: 'HamsterS %1: set tempo to %2 bpm %3',\n            roboid_hamster_s_set_port_to: 'HamsterS %1: set port %2 to %3 %4',\n            roboid_hamster_s_change_output_by: 'HamsterS %1: change output %2 by %3 %4',\n            roboid_hamster_s_set_output_to: 'HamsterS %1: set output %2 to %3 %4',\n            roboid_hamster_s_gripper: 'HamsterS %1: %2 gripper %3',\n            roboid_hamster_s_release_gripper: 'HamsterS %1: release gripper %2',\n            roboid_hamster_s_write_serial: 'HamsterS %1: write %2 %3 to serial %4',\n            roboid_hamster_s_read_serial_until: 'HamsterS %1: read serial %2 %3',\n            roboid_hamster_s_set_serial_rate_to: 'HamsterS %1: set serial rate to %2 Bd %3',\n            roboid_turtle_button_state: 'Turtle %1: button %2 ?',\n            roboid_turtle_change_buzzer_by: 'Turtle %1: change buzzer by %2 %3',\n            roboid_turtle_change_head_led_by_rgb:\n                'Turtle %1: change head led by r: %2 g: %3 b: %4 %5',\n            roboid_turtle_change_tempo_by: 'Turtle %1: change tempo by %2 %3',\n            roboid_turtle_change_wheel_by: 'Turtle %1: change %2 wheel by %3 %4',\n            roboid_turtle_change_wheels_by_left_right:\n                'Turtle %1: change wheels by left: %2 right: %3 %4',\n            roboid_turtle_clear_head_led: 'Turtle %1: clear head led %2',\n            roboid_turtle_clear_sound: 'Turtle %1: clear sound %2',\n            roboid_turtle_cross_intersection: 'Turtle %1: cross black intersection %2',\n            roboid_turtle_follow_line: 'Turtle %1: follow %2 line %3',\n            roboid_turtle_follow_line_until: 'Turtle %1: follow black line until %2 %3',\n            roboid_turtle_follow_line_until_black: 'Turtle %1: follow %2 line until black %3',\n            roboid_turtle_is_color_pattern: 'Turtle %1: color pattern %2 %3 ?',\n            roboid_turtle_move_backward_unit: 'Turtle %1: move backward %2 %3 %4',\n            roboid_turtle_move_forward_unit: 'Turtle %1: move forward %2 %3 %4',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                'Turtle %1: pivot around %2 wheel %3 %4 in %5 direction %6',\n            roboid_turtle_play_note: 'Turtle %1: play note %2 %3 %4',\n            roboid_turtle_play_note_for_beats: 'Turtle %1: play note %2 %3 for %4 beats %5',\n            roboid_turtle_play_sound_times: 'Turtle %1: play sound %2 %3 times %4',\n            roboid_turtle_play_sound_times_until_done:\n                'Turtle %1: play sound %2 %3 times until done %4',\n            roboid_turtle_rest_for_beats: 'Turtle %1: rest for %2 beats %3',\n            roboid_turtle_set_buzzer_to: 'Turtle %1: set buzzer to %2 %3',\n            roboid_turtle_set_following_speed_to: 'Turtle %1: set following speed to %2 %3',\n            roboid_turtle_set_head_led_to: 'Turtle %1: set head led to %2 %3',\n            roboid_turtle_set_head_led_to_rgb: 'Turtle %1: set head led to r: %2 g: %3 b: %4 %5',\n            roboid_turtle_set_tempo_to: 'Turtle %1: set tempo to %2 bpm %3',\n            roboid_turtle_set_wheel_to: 'Turtle %1: set %2 wheel to %3 %4',\n            roboid_turtle_set_wheels_to_left_right:\n                'Turtle %1: set wheels to left: %2 right: %3 %4',\n            roboid_turtle_stop: 'Turtle %1: stop %2',\n            roboid_turtle_touching_color: 'Turtle %1: touching %2 ?',\n            roboid_turtle_turn_at_intersection: 'Turtle %1: turn %2 at black intersection %3',\n            roboid_turtle_turn_unit_in_place: 'Turtle %1: turn %2 %3 %4 in place %5',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                'Turtle %1: turn %2 %3 %4 with radius %5 cm in %6 direction %7',\n            roboid_turtle_value: 'Turtle %1: %2',\n            roboid_turtle_boolean: 'Turtle %1: %2?',\n            roboid_turtle_pick_head_led: 'Turtle %1: set head led to %2 %3',\n\n            roboid_cheese_value: 'Cheese Stick %1: %2',\n            roboid_cheese_boolean: 'Cheese Stick %1: %2?',\n            roboid_cheese_play_sound_times: 'Cheese Stick %1: play sound %2 %3 times %4',\n            roboid_cheese_play_sound_times_until_done:\n                'Cheese Stick %1: play sound %2 %3 times until done %4',\n            roboid_cheese_change_buzzer_by: 'Cheese Stick %1: change buzzer by %2 Hz %3',\n            roboid_cheese_set_buzzer_to: 'Cheese Stick %1: set buzzer to %2 Hz %3',\n            roboid_cheese_clear_sound: 'Cheese Stick %1: clear sound %2',\n            roboid_cheese_play_note: 'Cheese Stick %1: play note %2 %3 %4',\n            roboid_cheese_play_note_for: 'Cheese Stick %1: play note %2 %3 for %4 beats %5',\n            roboid_cheese_rest_for: 'Cheese Stick %1: rest for %2 beats %3',\n            roboid_cheese_change_tempo_by: 'Cheese Stick %1: change tempo by %2 BPM %3',\n            roboid_cheese_set_tempo_to: 'Cheese Stick %1: set tempo to %2 BPM %3',\n            roboid_cheese_set_sound_port_to: 'Cheese Stick %1: set sound output to %2 %3',\n            roboid_cheese_set_input_mode_to: 'Cheese Stick %1: set port %2 to %3 input %4',\n            roboid_cheese_set_input_range_to:\n                'Cheese Stick %1: set input %2 range %3 - %4 to %5 - %6 %7 decimal point %8',\n            roboid_cheese_set_three_input_ranges_to:\n                'Cheese Stick %1: set input %2 range %3 - %4 - %5 to %6 - %7 - %8 %9 decimal point %10',\n            roboid_cheese_analog_input: 'Cheese Stick %1: input %2',\n            roboid_cheese_digital_input: 'Cheese Stick %1: input %2 %3 ?',\n            roboid_cheese_button_state: 'Cheese Stick %1: button %2 %3 ?',\n            roboid_cheese_set_pulse_mode_to: 'Cheese Stick %1: set port %2 to %3 input %4',\n            roboid_cheese_pulse_input: 'Cheese Stick %1: pulse detected on port %2 ?',\n            roboid_cheese_set_digital_output_to: 'Cheese Stick %1: set digital output %2 to %3 %4',\n            roboid_cheese_change_pwm_output_by: 'Cheese Stick %1: change pwm output %2 by %3% %4',\n            roboid_cheese_set_pwm_output_to: 'Cheese Stick %1: set pwm output %2 to %3% %4',\n            roboid_cheese_change_servo_motor_angle_by:\n                'Cheese Stick %1: change servo motor %2 by %3 degrees %4',\n            roboid_cheese_set_servo_motor_angle_to:\n                'Cheese Stick %1: set servo motor %2 to %3 degrees %4',\n            roboid_cheese_turn_off_servo_motor: 'Cheese Stick %1: turn off servo motor %2 %3',\n            roboid_cheese_change_dc_motor_velocity_by:\n                'Cheese Stick %1: change dc motor %2 velocity by %3% %4',\n            roboid_cheese_set_dc_motor_velocity_to:\n                'Cheese Stick %1: set dc motor %2 velocity to %3% %4',\n            roboid_cheese_stop_dc_motor: 'Cheese Stick %1: stop dc motor %2 %3',\n            roboid_cheese_rotate_step_motor:\n                'Cheese Stick %1: rotate step motor %2 steps with velocity %3 step/sec %4',\n            roboid_cheese_change_step_motor_velocity_by:\n                'Cheese Stick %1: change step motor velocity by %2 step/sec %3',\n            roboid_cheese_set_step_motor_velocity_to:\n                'Cheese Stick %1: set step motor velocity to %2 step/sec %3',\n            roboid_cheese_stop_off_step_motor: 'Cheese Stick %1: %2 step motor %3',\n            roboid_cheese_set_step_motor_mode_to: 'Cheese Stick %1: set step motor to %2 mode %3',\n            roboid_cheese_step_count: 'Cheese Stick %1: step count',\n            roboid_cheese_set_led_to_color: 'Cheese Stick %1: set rgb led %2 to %3 %4 %5',\n            roboid_cheese_pick_led_to: 'Cheese Stick %1: set rgb led %2 to %3 %4',\n            roboid_cheese_change_led_by_rgb:\n                'Cheese Stick %1: change rgb led %2 by r: %3 g: %4 b: %5 %6',\n            roboid_cheese_setLed_to_rgb: 'Cheese Stick %1: set rgb led %2 to r: %3 g: %4 b: %5 %6',\n            roboid_cheese_clear_led: 'Cheese Stick %1: clear rgb led %2 %3',\n            roboid_cheese_set_led_type_to: 'Cheese Stick %1: set rgb led %2 to %3 type %4',\n            roboid_cheese_neopixel_set_number_and_type_to:\n                'Cheese Stick %1 neopixel: set %2 leds as %3 %4',\n            roboid_cheese_neopixel_set_all_leds_to_pattern:\n                'Cheese Stick %1 neopixel: set all leds to pattern %2 %3',\n            roboid_cheese_neopixel_set_all_leds_to_color:\n                'Cheese Stick %1 neopixel: set all leds to %2 %3',\n            roboid_cheese_neopixel_pick_all_leds_to:\n                'Cheese Stick %1 neopixel: set all leds to %2 %3',\n            roboid_cheese_neopixel_change_all_leds_by_rgb:\n                'Cheese Stick %1 neopixel: change all leds by r: %2 g: %3 b: %4 %5',\n            roboid_cheese_neopixel_set_all_leds_to_rgb:\n                'Cheese Stick %1 neopixel: set all leds to r: %2 g: %3 b: %4 %5',\n            roboid_cheese_neopixel_clear_all_leds: 'Cheese Stick %1 neopixel: clear all leds %2',\n            roboid_cheese_neopixel_set_led_to_color:\n                'Cheese Stick %1 neopixel: set led %2 to %3 %4',\n            roboid_cheese_neopixel_pick_led_to: 'Cheese Stick %1 neopixel: set led %2 to %3 %4',\n            roboid_cheese_neopixel_change_led_by_rgb:\n                'Cheese Stick %1 neopixel: change led %2 by r: %3 g: %4 b: %5 %6',\n            roboid_cheese_neopixel_set_led_to_rgb:\n                'Cheese Stick %1 neopixel: set led %2 to r: %3 g: %4 b: %5 %6',\n            roboid_cheese_neopixel_clear_led: 'Cheese Stick %1 neopixel: clear led %2 %3',\n            roboid_cheese_neopixel_set_led_range_to_pattern:\n                'Cheese Stick %1 neopixel: set leds (from %2 to %3) to pattern %4 %5',\n            roboid_cheese_neopixel_set_led_range_to_color:\n                'Cheese Stick %1 neopixel: set leds (from %2 to %3 with %4 increments) to %5 %6',\n            roboid_cheese_neopixel_pick_led_range_to:\n                'Cheese Stick %1 neopixel: set leds (from %2 to %3 with %4 increments) to %5 %6',\n            roboid_cheese_neopixel_change_led_range_by_rgb:\n                'Cheese Stick %1 neopixel: change leds (from %2 to %3 with %4 increments) by r: %5 g: %6 b: %7 %8',\n            roboid_cheese_neopixel_set_led_range_to_rgb:\n                'Cheese Stick %1 neopixel: set leds (from %2 to %3 with %4 increments) to r: %5 g: %6 b: %7 %8',\n            roboid_cheese_neopixel_clear_led_range:\n                'Cheese Stick %1 neopixel: clear leds (from %2 to %3 with %4 increments) %5',\n            roboid_cheese_neopixel_shift: 'Cheese Stick %1 neopixel: shift %2 pixels %3',\n            roboid_cheese_neopixel_rotate: 'Cheese Stick %1 neopixel: rotate %2 pixels %3',\n            roboid_cheese_neopixel_change_brightness_by:\n                'Cheese Stick %1 neopixel: change brightness by %2% %3',\n            roboid_cheese_neopixel_set_brightness_to:\n                'Cheese Stick %1 neopixel: set brightness to %2% %3',\n            roboid_cheese_write_serial: 'Cheese Stick %1: write %2 %3 to serial %4',\n            roboid_cheese_read_serial_until: 'Cheese Stick %1: read serial %2 %3',\n            roboid_cheese_set_serial_port_to: 'Cheese Stick %1: set serial port to %2 %3',\n            roboid_cheese_set_serial_rate_to: 'Cheese Stick %1: set serial rate to %2Bd %3',\n            roboid_cheese_serial_input: 'Cheese Stick %1: serial input',\n            roboid_cheese_pid_start: 'Cheese Stick %1: start %2 %3',\n            roboid_cheese_pid_set_range_to:\n                'Cheese Stick %1 PID: set %2 range %3 - %4 to %5 - %6 %7 decimal point %8',\n            roboid_cheese_pid_set_three_ranges_to:\n                'Cheese Stick %1 PID: set %2 range %3 - %4 - %5 to %6 - %7 - %8 %9 decimal point %10',\n            roboid_cheese_pid_reset_encoder: 'Cheese Stick %1 PID: clear encoder %2',\n            roboid_cheese_pid_input: 'Cheese Stick %1 PID: %2',\n            roboid_cheese_pid_button_state: 'Cheese Stick %1 PID: button %2 %3?',\n            roboid_cheese_hat010_start: 'Cheese Stick %1: start HAT-010 5x5 matrix %2',\n            roboid_cheese_hat010_button: 'Cheese Stick %1 HAT-010: button %2',\n            roboid_cheese_hat010_button_state: 'Cheese Stick %1 HAT-010: button %2 %3?',\n            roboid_cheese_hat010_background_turn_on_xy:\n                'Cheese Stick %1 HAT-010 background: turn on x: %2 y: %3 in %4 %5',\n            roboid_cheese_hat010_background_turn_off_xy:\n                'Cheese Stick %1 HAT-010 background: turn off x: %2 y: %3 %4',\n            roboid_cheese_hat010_background_draw_shape_at_xy:\n                'Cheese Stick %1 HAT-010 background: draw %2 %3 at x: %4 y: %5 %6',\n            roboid_cheese_hat010_background_draw_string_at_xy:\n                'Cheese Stick %1 HAT-010 background: draw %2 string %3 at x: %4 y: %5 %6',\n            roboid_cheese_hat010_background_draw_pattern_at_xy:\n                'Cheese Stick %1 HAT-010 background: draw %2 pattern %3 at x: %4 y: %5 %6',\n            roboid_cheese_hat010_clear: 'Cheese Stick %1 HAT-010: clear %2 %3',\n            roboid_cheese_hat010_scroll_by_xy:\n                'Cheese Stick %1 HAT-010: scroll %2 by x: %3 y: %4 %5',\n            roboid_cheese_hat010_sprite_set_to_shape:\n                'Cheese Stick %1 HAT-010 sprite %2: set sprite to %3 %4 %5',\n            roboid_cheese_hat010_sprite_set_to_string:\n                'Cheese Stick %1 HAT-010 sprite %2: set sprite to %3 string %4 %5',\n            roboid_cheese_hat010_sprite_set_to_pattern:\n                'Cheese Stick %1 HAT-010 sprite %2: set sprite to %3 pattern %4 %5',\n            roboid_cheese_hat010_sprite_clear_show_hide:\n                'Cheese Stick %1 HAT-010 sprite %2: %3 sprite %4',\n            roboid_cheese_hat010_sprite_change_positions_by_xy:\n                'Cheese Stick %1 HAT-010 sprite %2: change position by x: %3 y: %4 %5',\n            roboid_cheese_hat010_sprite_set_positions_to_xy:\n                'Cheese Stick %1 HAT-010 sprite %2: set position to x: %3 y: %4 %5',\n            roboid_cheese_hat010_sprite_change_position_by_value:\n                'Cheese Stick %1 HAT-010 sprite %2: change %3 position by %4 %5',\n            roboid_cheese_hat010_sprite_set_position_to_value:\n                'Cheese Stick %1 HAT-010 sprite %2: set %3 position to %4 %5',\n            roboid_cheese_hat010_sprite_rotate: 'Cheese Stick %1 HAT-010 sprite %2: rotate %3 %4',\n            roboid_cheese_hat010_sprite_flip_in_direction:\n                'Cheese Stick %1 HAT-010 sprite %2: flip in %3 direction %4',\n            roboid_cheese_hat010_sprite_stamp_to_background:\n                'Cheese Stick %1 HAT-010 sprite %2: stamp to background %3',\n            roboid_cheese_hat010_sprite_position: 'Cheese Stick %1 HAT-010 sprite %2: %3 position',\n            roboid_cheese_hat010_sprite_touching_sprite:\n                'Cheese Stick %1 HAT-010 sprite %2: touching sprite %3?',\n            roboid_cheese_hat010_sprite_touching: 'Cheese Stick %1 HAT-010 sprite %2: touching %3?',\n            roboid_cheese_hat010_change_brightness_by:\n                'Cheese Stick %1 HAT-010: change brightness by %2% %3',\n            roboid_cheese_hat010_set_brightness_to:\n                'Cheese Stick %1 HAT-010: set brightness to %2% %3',\n        },\n        Helper: {\n            roboid_hamster_beep: 'Plays beep sound.',\n            roboid_hamster_change_both_wheels_by:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_hamster_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            roboid_hamster_change_output_by:\n                'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            roboid_hamster_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            roboid_hamster_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_hamster_clear_buzzer: 'Turns off buzzer sound.',\n            roboid_hamster_clear_led: 'Turns off the left/right/both LEDs.',\n            roboid_hamster_follow_line_until:\n                'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n            roboid_hamster_follow_line_using:\n                'Moves along the black/white line by using the left/right/both floor sensors.',\n            roboid_hamster_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            roboid_hamster_move_backward_for_secs:\n                'Moves backward for the number of seconds entered.',\n            roboid_hamster_move_forward_for_secs:\n                'Moves forward for the number of seconds entered.',\n            roboid_hamster_move_forward_once: 'Moves one space forward on the board.',\n            roboid_hamster_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            roboid_hamster_rest_for: 'Rests as much as the beat you entered.',\n            roboid_hamster_set_both_wheels_to:\n                'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_hamster_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            roboid_hamster_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            roboid_hamster_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n            roboid_hamster_set_output_to:\n                'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            roboid_hamster_set_port_to:\n                'Sets the io mode of the selected external port to the selected mode.',\n            roboid_hamster_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            roboid_hamster_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_hamster_stop: 'Stops both wheels.',\n            roboid_hamster_turn_for_secs: 'Turns left/right for the number of seconds entered.',\n            roboid_hamster_turn_once: 'Turns left/right 90 degrees on the board.',\n            roboid_hamster_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n            roboid_turtle_button_state:\n                'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            roboid_turtle_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            roboid_turtle_change_head_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of the head LED, respectively.',\n            roboid_turtle_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            roboid_turtle_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_turtle_change_wheels_by_left_right:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_turtle_clear_head_led: 'Turns off the head LED.',\n            roboid_turtle_clear_sound: 'Turns off sound.',\n            roboid_turtle_cross_intersection:\n                'Moves forward for a moment at the black intersection, then finds the black line and moves again.',\n            roboid_turtle_follow_line: 'Moves along the selected color line on a white background.',\n            roboid_turtle_follow_line_until:\n                'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            roboid_turtle_follow_line_until_black:\n                'Moves along the selected color line on a white background and stops when the color sensor detects black.',\n            roboid_turtle_is_color_pattern:\n                'If the color sensor detects the selected color pattern, true, otherwise false.',\n            roboid_turtle_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            roboid_turtle_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                'Pivots around the left/right wheel in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_play_note: 'It sounds the selected tone and octave.',\n            roboid_turtle_play_note_for_beats:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            roboid_turtle_play_sound_times: 'Plays the selected sound as many times as entered.',\n            roboid_turtle_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            roboid_turtle_rest_for_beats: 'Rests as much as the beat you entered.',\n            roboid_turtle_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            roboid_turtle_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            roboid_turtle_set_head_led_to: 'Turns the head LED to the selected color.',\n            roboid_turtle_set_head_led_to_rgb:\n                'Sets the R, G, B values of the head LED to the entered values.',\n            roboid_turtle_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            roboid_turtle_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-400 to 400%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_turtle_set_wheels_to_left_right:\n                'Sets the speed of the left and right wheels to the entered values (-400 to 400%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_turtle_stop: 'Stops both wheels.',\n            roboid_turtle_touching_color:\n                'If the color sensor detects the selected color, true, otherwise false.',\n            roboid_turtle_turn_at_intersection:\n                'Moves forward for a moment at the black intersection, then turns left/right/back in place, finds the black line and moves again.',\n            roboid_turtle_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                'Turns left/right drawing the circle of the entered radius in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_value:\n                'color number: color number detected by the color sensor (range: -1 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1) <br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.',\n            roboid_hamster_gripper: 'Opens or closes the gripper.',\n            roboid_hamster_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            roboid_hamster_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_hamster_play_note: 'It sounds the selected tone and octave.',\n            roboid_hamster_s_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            roboid_hamster_s_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_hamster_s_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n            roboid_hamster_s_move_forward_once: 'Moves one space forward on the board.',\n            roboid_hamster_s_turn_once: 'Turns left/right 90 degrees on the board.',\n            roboid_hamster_s_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            roboid_hamster_s_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            roboid_hamster_s_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_pivot_around_unit_in_direction:\n                'Pivots around the left/right pen/wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_turn_unit_with_radius_in_direction:\n                'Turns left/right so that the left/right pen draws the circle of the entered radius in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_change_both_wheels_by:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_hamster_s_set_both_wheels_to:\n                'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_hamster_s_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_hamster_s_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_hamster_s_follow_line_using:\n                'Moves along the black/white line by using the left/right/both floor sensors.',\n            roboid_hamster_s_follow_line_until:\n                'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n            roboid_hamster_s_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            roboid_hamster_s_set_following_gain_to:\n                'Sets the directional variation (1 to 8) 선을 따라 이동하는 방향 변화량(1 ~ 8)을 설정합니다. 숫자가 클수록 급커브를 잘 따라가지만 직선에서 좌우로 더 흔들립니다.',\n            roboid_hamster_s_stop: 'Stops both wheels.',\n            roboid_hamster_s_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n            roboid_hamster_s_pick_led: 'Turns left/right/both LEDs to the selected color.',\n            roboid_hamster_s_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of left/right/both LEDs, respectively.',\n            roboid_hamster_s_set_led_to_rgb:\n                'Sets the R, G, B values of left/right/both LEDs to the entered values.',\n            roboid_hamster_s_clear_led: 'Turns off the left/right/both LEDs.',\n            roboid_hamster_s_play_sound_times: 'Plays the selected sound as many times as entered.',\n            roboid_hamster_s_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            roboid_hamster_s_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            roboid_hamster_s_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            roboid_hamster_s_clear_sound: 'Turns off sound.',\n            roboid_hamster_s_play_note: 'It sounds the selected tone and octave.',\n            roboid_hamster_s_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            roboid_hamster_s_rest_for: 'Rests as much as the beat you entered.',\n            roboid_hamster_s_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            roboid_hamster_s_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            roboid_hamster_s_set_port_to:\n                'Sets the io mode of the selected external port to the selected mode.',\n            roboid_hamster_s_change_output_by:\n                'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            roboid_hamster_s_set_output_to:\n                'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            roboid_hamster_s_gripper: 'Opens or closes the gripper.',\n            roboid_hamster_s_release_gripper:\n                'Turns off the gripper so that it can be moved freely.',\n            roboid_hamster_s_write_serial: 'Sends strings via serial communication.',\n            roboid_hamster_s_read_serial_until:\n                'Read the strings received by serial communication.',\n            roboid_hamster_s_set_serial_rate_to: 'Sets the speed of serial communication.',\n            roboid_turtle_button_state:\n                'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            roboid_turtle_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            roboid_turtle_change_head_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of the head LED, respectively.',\n            roboid_turtle_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            roboid_turtle_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_turtle_change_wheels_by_left_right:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_turtle_clear_head_led: 'Turns off the head LED.',\n            roboid_turtle_clear_sound: 'Turns off sound.',\n            roboid_turtle_cross_intersection:\n                'Moves forward for a moment at the black intersection, then finds the black line and moves again.',\n            roboid_turtle_follow_line: 'Moves along the selected color line on a white background.',\n            roboid_turtle_follow_line_until:\n                'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            roboid_turtle_follow_line_until_black:\n                'Moves along the selected color line on a white background and stops when the color sensor detects black.',\n            roboid_turtle_is_color_pattern:\n                'If the color sensor detects the selected color pattern, true, otherwise false.',\n            roboid_turtle_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            roboid_turtle_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                'Pivots around the left/right wheel in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_play_note: 'It sounds the selected tone and octave.',\n            roboid_turtle_play_note_for_beats:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            roboid_turtle_play_sound_times: 'Plays the selected sound as many times as entered.',\n            roboid_turtle_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            roboid_turtle_rest_for_beats: 'Rests as much as the beat you entered.',\n            roboid_turtle_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            roboid_turtle_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            roboid_turtle_set_head_led_to: 'Turns the head LED to the selected color.',\n            roboid_turtle_set_head_led_to_rgb:\n                'Sets the R, G, B values of the head LED to the entered values.',\n            roboid_turtle_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            roboid_turtle_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-400 to 400%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_turtle_set_wheels_to_left_right:\n                'Sets the speed of the left and right wheels to the entered values (-400 to 400%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_turtle_stop: 'Stops both wheels.',\n            roboid_turtle_touching_color:\n                'If the color sensor detects the selected color, true, otherwise false.',\n            roboid_turtle_turn_at_intersection:\n                'Moves forward for a moment at the black intersection, then turns left/right/back in place, finds the black line and moves again.',\n            roboid_turtle_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                'Turns left/right drawing the circle of the entered radius in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_value:\n                'color number: color number detected by the color sensor (range: -1 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1) <br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.',\n            roboid_turtle_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_turtle_pick_head_led: 'Turns the head LED to the selected color.',\n        },\n        Blocks: {\n            ROBOID_acceleration_x: 'x acceleration',\n            ROBOID_acceleration_y: 'y acceleration',\n            ROBOID_acceleration_z: 'z acceleration',\n            ROBOID_back: 'back',\n            ROBOID_both: 'both',\n            ROBOID_button: 'button',\n            ROBOID_buzzer: 'buzzer',\n            ROBOID_clicked: 'clicked',\n            ROBOID_color_any: 'any color',\n            ROBOID_color_black: 'black',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_green: 'green',\n            ROBOID_color_number: 'color number',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_pattern: 'color pattern',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_red: 'red',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_white: 'white',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_floor: 'floor',\n            ROBOID_head: 'head',\n            ROBOID_head_color: 'head color',\n            ROBOID_left: 'left',\n            ROBOID_left_wheel: 'left wheel',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_note: 'note',\n            ROBOID_right: 'right',\n            ROBOID_right_wheel: 'right wheel',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_tail: 'tail',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_sec: 'seconds',\n            hamster_note_c: 'C',\n            hamster_note_c_sharp: 'C♯(D♭)',\n            hamster_note_d: 'D',\n            hamster_note_d_sharp: 'D♯(E♭)',\n            hamster_note_e: 'E',\n            hamster_note_f: 'F',\n            hamster_note_f_sharp: 'F♯(G♭)',\n            hamster_note_g: 'G',\n            hamster_note_g_sharp: 'G♯(A♭)',\n            hamster_note_a: 'A',\n            hamster_note_a_sharp: 'A♯(B♭)',\n            hamster_note_b: 'B',\n            hamster_tilt_forward: 'tilt forward',\n            hamster_tilt_backward: 'tilt backward',\n            hamster_tilt_left: 'tilt left',\n            hamster_tilt_right: 'tilt right',\n            hamster_tilt_flip: 'tilt flip',\n            hamster_tilt_not: 'not tilt',\n            hamster_battery_normal: 'battery normal',\n            hamster_battery_low: 'battery low',\n            hamster_battery_empty: 'battery empty',\n            hamster_open_gripper: 'open',\n            hamster_close_gripper: 'close',\n            hamster_s_color_black: 'black',\n            hamster_s_color_blue: 'blue',\n            hamster_s_color_green: 'green',\n            hamster_s_color_orange: 'orange',\n            hamster_s_color_purple: 'purple',\n            hamster_s_color_red: 'red',\n            hamster_s_color_sky_blue: 'sky blue',\n            hamster_s_color_violet: 'violet',\n            hamster_s_color_white: 'white',\n            hamster_s_color_yellow: 'yellow',\n            hamster_s_left: 'left',\n            hamster_s_right: 'right',\n            hamster_s_both: 'both',\n            hamster_s_note_c: 'C',\n            hamster_s_note_c_sharp: 'C♯(D♭)',\n            hamster_s_note_d: 'D',\n            hamster_s_note_d_sharp: 'D♯(E♭)',\n            hamster_s_note_e: 'E',\n            hamster_s_note_f: 'F',\n            hamster_s_note_f_sharp: 'F♯(G♭)',\n            hamster_s_note_g: 'G',\n            hamster_s_note_g_sharp: 'G♯(A♭)',\n            hamster_s_note_a: 'A',\n            hamster_s_note_a_sharp: 'A♯(B♭)',\n            hamster_s_note_b: 'B',\n            hamster_s_port_a: 'A',\n            hamster_s_port_b: 'B',\n            hamster_s_port_ab: 'A and B',\n            hamster_s_tilt_forward: 'tilt forward',\n            hamster_s_tilt_backward: 'tilt backward',\n            hamster_s_tilt_left: 'tilt left',\n            hamster_s_tilt_right: 'tilt right',\n            hamster_s_tilt_flip: 'tilt flip',\n            hamster_s_tilt_not: 'not tilt',\n            hamster_s_tap: 'tap',\n            hamster_s_free_fall: 'free fall',\n            hamster_s_battery_normal: 'battery normal',\n            hamster_s_battery_low: 'battery low',\n            hamster_s_battery_empty: 'battery empty',\n            hamster_s_forward: 'forward',\n            hamster_s_backward: 'backward',\n            hamster_s_front: 'front',\n            hamster_s_rear: 'rear',\n            hamster_s_left_pen: 'left pen',\n            hamster_s_right_pen: 'right pen',\n            hamster_s_left_wheel: 'left wheel',\n            hamster_s_right_wheel: 'right wheel',\n            hamster_s_robot: 'robot',\n            hamster_s_gain_default: 'default',\n            hamster_s_sensor_acceleration_x: 'x acceleration',\n            hamster_s_sensor_acceleration_y: 'y acceleration',\n            hamster_s_sensor_acceleration_z: 'z acceleration',\n            hamster_s_sensor_input_a: 'input A',\n            hamster_s_sensor_input_b: 'input B',\n            hamster_s_sensor_left_floor: 'left floor',\n            hamster_s_sensor_left_proximity: 'left proximity',\n            hamster_s_sensor_light: 'light',\n            hamster_s_sensor_right_floor: 'right floor',\n            hamster_s_sensor_right_proximity: 'right proximity',\n            hamster_s_sensor_signal_strength: 'signal strength',\n            hamster_s_sensor_temperature: 'temperature',\n            hamster_s_buzzer: 'buzzer',\n            hamster_s_left_led: 'left LED',\n            hamster_s_left_wheel: 'left wheel',\n            hamster_s_note: 'note',\n            hamster_s_output_a: 'output A',\n            hamster_s_output_b: 'output B',\n            hamster_s_right_led: 'right LED',\n            hamster_s_right_wheel: 'right wheel',\n            hamster_s_sound_angry: 'angry',\n            hamster_s_sound_beep: 'beep',\n            hamster_s_sound_birthday: 'birthday',\n            hamster_s_sound_chop: 'chop',\n            hamster_s_sound_dibidibidip: 'dibidibidip',\n            hamster_s_sound_engine: 'engine',\n            hamster_s_sound_good_job: 'good job',\n            hamster_s_sound_happy: 'happy',\n            hamster_s_sound_march: 'march',\n            hamster_s_sound_noise: 'noise',\n            hamster_s_sound_random_beep: 'random beep',\n            hamster_s_sound_robot: 'robot',\n            hamster_s_sound_sad: 'sad',\n            hamster_s_sound_siren: 'siren',\n            hamster_s_sound_sleep: 'sleep',\n            hamster_s_unit_cm: 'cm',\n            hamster_s_unit_deg: 'degrees',\n            hamster_s_unit_pulse: 'pulses',\n            hamster_s_unit_sec: 'seconds',\n            hamster_s_analog_input: 'analog input',\n            hamster_s_digital_input: 'digital input',\n            hamster_s_digital_input_pull_down: 'digital input (pull down)',\n            hamster_s_digital_input_pull_up: 'digital input (pull up)',\n            hamster_s_digital_output: 'digital output',\n            hamster_s_pwm_output: 'pwm output',\n            hamster_s_servo_output: 'servo output',\n            hamster_s_voltage_input: 'voltage input',\n            hamster_s_open_gripper: 'open',\n            hamster_s_close_gripper: 'close',\n            hamster_s_serial_string: 'string',\n            hamster_s_serial_string_line: 'string line',\n            hamster_s_serial_all: 'all',\n            hamster_s_serial_until_new_line: 'until new line',\n            hamster_s_serial_until_comma: 'until ,(comma)',\n            hamster_s_serial_until_colon: 'until :(colon)',\n            hamster_s_serial_until_dollar: 'until $',\n            hamster_s_serial_until_sharp: 'until #',\n            hamster_s_serial_input: 'serial input',\n            turtle_acceleration_x: 'x acceleration',\n            turtle_acceleration_y: 'y acceleration',\n            turtle_acceleration_z: 'z acceleration',\n            turtle_back: 'back',\n            turtle_both: 'both',\n            turtle_button: 'button',\n            turtle_buzzer: 'buzzer',\n            turtle_clicked: 'clicked',\n            turtle_color_any: 'any color',\n            turtle_color_black: 'black',\n            turtle_color_blue: 'blue',\n            turtle_color_green: 'green',\n            turtle_color_number: 'color number',\n            turtle_color_orange: 'orange',\n            turtle_color_pattern: 'color pattern',\n            turtle_color_purple: 'purple',\n            turtle_color_red: 'red',\n            turtle_color_sky_blue: 'sky blue',\n            turtle_color_violet: 'violet',\n            turtle_color_white: 'white',\n            turtle_color_yellow: 'yellow',\n            turtle_double_clicked: 'double-clicked',\n            turtle_floor: 'floor',\n            turtle_head: 'head',\n            turtle_head_color: 'head color',\n            turtle_left: 'left',\n            turtle_left_wheel: 'left wheel',\n            turtle_long_pressed: 'long-pressed',\n            turtle_note: 'note',\n            turtle_right: 'right',\n            turtle_right_wheel: 'right wheel',\n            turtle_sound_beep: 'beep',\n            turtle_sound_birthday: 'birthday',\n            turtle_sound_dibidibidip: 'dibidibidip',\n            turtle_sound_engine: 'engine',\n            turtle_sound_good_job: 'good job',\n            turtle_sound_march: 'march',\n            turtle_sound_random_beep: 'random beep',\n            turtle_sound_robot: 'robot',\n            turtle_sound_siren: 'siren',\n            turtle_tail: 'tail',\n            turtle_unit_cm: 'cm',\n            turtle_unit_deg: 'degrees',\n            turtle_unit_pulse: 'pulses',\n            turtle_unit_sec: 'seconds',\n            turtle_note_c: 'C',\n            turtle_note_c_sharp: 'C♯(D♭)',\n            turtle_note_d: 'D',\n            turtle_note_d_sharp: 'D♯(E♭)',\n            turtle_note_e: 'E',\n            turtle_note_f: 'F',\n            turtle_note_f_sharp: 'F♯(G♭)',\n            turtle_note_g: 'G',\n            turtle_note_g_sharp: 'G♯(A♭)',\n            turtle_note_a: 'A',\n            turtle_note_a_sharp: 'A♯(B♭)',\n            turtle_note_b: 'B',\n            turtle_tilt_forward: 'tilt forward',\n            turtle_tilt_backward: 'tilt backward',\n            turtle_tilt_left: 'tilt left',\n            turtle_tilt_right: 'tilt right',\n            turtle_tilt_flip: 'tilt flip',\n            turtle_tilt_not: 'not tilt',\n            turtle_battery_normal: 'battery normal',\n            turtle_battery_low: 'battery low',\n            turtle_battery_empty: 'battery empty',\n            ROBOID_cheese_stick: 'Cheese Stick',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_signal_strength_dbm: 'signal strength (dBm)',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_input_sa: 'input Sa',\n            ROBOID_sensor_input_sb: 'input Sb',\n            ROBOID_sensor_input_sc: 'input Sc',\n            ROBOID_sensor_input_la: 'input La',\n            ROBOID_sensor_input_lb: 'input Lb',\n            ROBOID_sensor_input_lc: 'input Lc',\n            ROBOID_sensor_step_count: 'step count',\n            ROBOID_monitor_output_sa: 'output Sa',\n            ROBOID_monitor_output_sb: 'output Sb',\n            ROBOID_monitor_output_sc: 'output Sc',\n            ROBOID_monitor_output_la: 'output La',\n            ROBOID_monitor_output_lb: 'output Lb',\n            ROBOID_monitor_output_lc: 'output Lc',\n            ROBOID_monitor_output_mab: 'output Mab',\n            ROBOID_monitor_output_mcd: 'output Mcd',\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_logo_sky_direction: 'logo in sky direction',\n            ROBOID_logo_earth_direction: 'logo in earth direction',\n            ROBOID_power_switch_sky_direction: 'power switch in sky direction',\n            ROBOID_power_switch_earth_direction: 'power switch in earth direction',\n            ROBOID_port_s_sky_direction: 'port S in sky direction',\n            ROBOID_port_s_earth_direction: 'port S in earth direction',\n            ROBOID_tap: 'tap',\n            ROBOID_free_fall: 'free fall',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n            ROBOID_speaker_internal: 'internal speaker',\n            ROBOID_speaker_port_mab: 'port Mab',\n            ROBOID_io_mode_makey: 'makey',\n            ROBOID_io_mode_button: 'button',\n            ROBOID_io_mode_digital_pull_up: 'digital (pull up)',\n            ROBOID_io_mode_digital_pull_down: 'digital (pull down)',\n            ROBOID_io_mode_analog: 'analog',\n            ROBOID_io_mode_voltage: 'voltage',\n            ROBOID_io_mode_pulse: 'pulse',\n            ROBOID_io_mode_pulse_pull_up: 'pulse (pull up)',\n            ROBOID_io_mode_pulse_pull_down: 'pulse (pull down)',\n            ROBOID_io_mode_normal: 'normal',\n            ROBOID_io_mode_power: 'power',\n            ROBOID_io_port_high_current_mab: 'high current Ma(-)b',\n            ROBOID_io_port_high_current_mcd: 'high current Mc(-)d',\n            ROBOID_io_action_stop: 'stop',\n            ROBOID_io_action_turn_off: 'turn off',\n            ROBOID_range_integer: 'without',\n            ROBOID_range_real: 'with',\n            ROBOID_led_intensity_dark: 'dark',\n            ROBOID_led_intensity_normal: 'normal',\n            ROBOID_led_intensity_bright: 'bright',\n            ROBOID_led_type_default: 'default',\n            ROBOID_led_type_crgb: '-rgb',\n            ROBOID_led_type_crbg: '-rbg',\n            ROBOID_led_type_cgrb: '-grb',\n            ROBOID_led_type_cgbr: '-gbr',\n            ROBOID_led_type_cbrg: '-brg',\n            ROBOID_led_type_cbgr: '-bgr',\n            ROBOID_led_type_argb: '+rgb',\n            ROBOID_led_type_arbg: '+rbg',\n            ROBOID_led_type_agrb: '+grb',\n            ROBOID_led_type_agbr: '+gbr',\n            ROBOID_led_type_abrg: '+brg',\n            ROBOID_led_type_abgr: '+bgr',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_neopixel_3_colors: '3 colors',\n            ROBOID_neopixel_6_colors: '6 colors',\n            ROBOID_neopixel_12_colors: '12 colors',\n            ROBOID_neopixel_red_green: 'red to green',\n            ROBOID_neopixel_red_blue: 'red to blue',\n            ROBOID_neopixel_red_white: 'red to white',\n            ROBOID_neopixel_green_red: 'green to red',\n            ROBOID_neopixel_green_blue: 'green to blue',\n            ROBOID_neopixel_green_white: 'green to white',\n            ROBOID_neopixel_blue_red: 'blue to red',\n            ROBOID_neopixel_blue_green: 'blue to green',\n            ROBOID_neopixel_blue_white: 'blue to white',\n            ROBOID_neopixel_white_red: 'white to red',\n            ROBOID_neopixel_white_green: 'white to green',\n            ROBOID_neopixel_white_blue: 'white to blue',\n            ROBOID_neopixel_red_black: 'red getting darker',\n            ROBOID_neopixel_green_black: 'green getting darker',\n            ROBOID_neopixel_blue_black: 'blue getting darker',\n            ROBOID_neopixel_white_black: 'white getting darker',\n            ROBOID_neopixel_black_red: 'red getting brighter',\n            ROBOID_neopixel_black_green: 'green getting brighter',\n            ROBOID_neopixel_black_blue: 'blue getting brighter',\n            ROBOID_neopixel_black_white: 'white getting brighter',\n            ROBOID_serial_string: 'string',\n            ROBOID_serial_string_line: 'string line',\n            ROBOID_serial_all: 'all',\n            ROBOID_serial_until_comma: 'until ,(comma)',\n            ROBOID_serial_until_colon: 'until :(colon)',\n            ROBOID_serial_until_dollar: 'until $',\n            ROBOID_serial_until_sharp: 'until #',\n            ROBOID_serial_until_new_line: 'until new line',\n            ROBOID_serial_port_wa_rb: 'La(write) Lb(read)',\n            ROBOID_serial_port_ra_wb: 'La(read) Lb(write)',\n            ROBOID_serial_port_wa: 'La(write)',\n            ROBOID_serial_port_ra: 'La(read)',\n            ROBOID_pid_10: 'PID-10 ultrasonic sensor (HC-SR04+)',\n            ROBOID_pid_11_1: 'PID-11-1 humidity/temperature sensor (DHT11)',\n            ROBOID_pid_11_2: 'PID-11-2 humidity/temperature sensor (DHT21)',\n            ROBOID_pid_11_3: 'PID-11-3 humidity/temperature sensor (DHT22)',\n            ROBOID_pid_12: 'PID-12 temperature sensor (DS18B20)',\n            ROBOID_pid_13: 'PID-13 joystick and button',\n            ROBOID_pid_14: 'PID-14 dual joystick',\n            ROBOID_pid_15: 'PID-15 IR transceiver',\n            ROBOID_pid_16: 'PID-16 encoder',\n            ROBOID_pid_distance: 'distance (cm)',\n            ROBOID_pid_temperature: 'temperature (℃)',\n            ROBOID_pid_humidity: 'humidity (%RH)',\n            ROBOID_pid_x1: 'x1',\n            ROBOID_pid_y1: 'y1',\n            ROBOID_pid_x2: 'x2',\n            ROBOID_pid_y2: 'y2',\n            ROBOID_pid_button1: 'button1',\n            ROBOID_pid_button2: 'button2',\n            ROBOID_pid_encoder: 'encoder',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_shape_square: 'square',\n            ROBOID_shape_triangle: 'triangle',\n            ROBOID_shape_diamond: 'diamond',\n            ROBOID_shape_circle: 'circle',\n            ROBOID_shape_x: 'X',\n            ROBOID_shape_like: 'like',\n            ROBOID_shape_dislike: 'dislike',\n            ROBOID_shape_angry: 'angry',\n            ROBOID_shape_open_mouth: 'open mouth',\n            ROBOID_shape_close_mouth: 'close mouth',\n            ROBOID_shape_walk1: 'walk 1',\n            ROBOID_shape_walk2: 'walk 2',\n            ROBOID_shape_heart: 'heart',\n            ROBOID_shape_star: 'star',\n            ROBOID_shape_airplane: 'airplane',\n            ROBOID_shape_puppy: 'puppy',\n            ROBOID_shape_butterfly: 'butterfly',\n            ROBOID_shape_quarter_note: 'quarter note',\n            ROBOID_shape_eighth_note: 'eighth note',\n            ROBOID_shape_left_arrow: 'left arrow',\n            ROBOID_shape_right_arrow: 'right arrow',\n            ROBOID_shape_up_arrow: 'up arrow',\n            ROBOID_shape_down_arrow: 'down arrow',\n            ROBOID_hat_background: 'background',\n            ROBOID_hat_all: 'all',\n            ROBOID_hat_clear: 'clear',\n            ROBOID_hat_show: 'show',\n            ROBOID_hat_hide: 'hide',\n            ROBOID_hat_clockwise: 'clockwise',\n            ROBOID_hat_counterclockwise: 'counterclockwise',\n            ROBOID_hat_left_right: 'left-right',\n            ROBOID_hat_up_down: 'up-down',\n            ROBOID_hat_auto: 'auto',\n            ROBOID_hat_manual: 'manual',\n            ROBOID_hat_other_sprite: 'other sprite',\n            ROBOID_hat_left_wall: 'left wall',\n            ROBOID_hat_right_wall: 'right wall',\n            ROBOID_hat_top_wall: 'top wall',\n            ROBOID_hat_bottom_wall: 'bottom wall',\n            ROBOID_hat_any_wall: 'any wall',\n        },\n    },\n    jp: {\n        template: {\n            roboid_hamster_gripper: 'ハムスター %1: グリッパを %2 %3',\n            roboid_hamster_release_gripper: 'ハムスター %1: グリッパをオフ %2',\n            roboid_hamster_boolean: 'ハムスター %1: %2?',\n            roboid_hamster_play_note: 'ハムスター %1: %2 %3 を演奏する %4',\n            roboid_hamster_s_hand_found: 'ハムスターS %1: 手を見つけたか?',\n            roboid_hamster_s_boolean: 'ハムスターS %1: %2?',\n            roboid_hamster_s_value: 'ハムスターS %1: %2',\n            roboid_hamster_s_move_forward_once: 'ハムスターS %1: ボード板上で前へ動かす %2',\n            roboid_hamster_s_turn_once: 'ハムスターS %1: ボード板上で%2に回す %3',\n            roboid_hamster_s_move_forward_unit: 'ハムスターS %1: 前へ%2%3動かす %4',\n            roboid_hamster_s_move_backward_unit: 'ハムスターS %1: 後ろへ%2%3動かす %4',\n            roboid_hamster_s_turn_unit_in_place: 'ハムスターS %1: 所定位置で%2に%3%4回す %5',\n            roboid_hamster_s_pivot_around_unit_in_direction:\n                'ハムスターS %1: %2を中心に%3%4%5方向に回す %6',\n            roboid_hamster_s_turn_unit_with_radius_in_direction:\n                'ハムスターS %1: %2%3に%4%5半径%6cmを%7方向に回す %8',\n            roboid_hamster_s_change_both_wheels_by:\n                'ハムスターS %1: 左車輪を%2右車輪を%3ずつ変える %4',\n            roboid_hamster_s_set_both_wheels_to: 'ハムスターS %1: 左車輪を%2右車輪を%3にする %4',\n            roboid_hamster_s_change_wheel_by: 'ハムスターS %1: %2車輪を%3ずつ変える %4',\n            roboid_hamster_s_set_wheel_to: 'ハムスターS %1: %2車輪を%3にする %4',\n            roboid_hamster_s_follow_line_using:\n                'ハムスターS %1: %2線を%3フロアセンサーで追従する %4',\n            roboid_hamster_s_follow_line_until:\n                'ハムスターS %1: %2線を追従して%3交差点まで動かす %4',\n            roboid_hamster_s_set_following_speed_to:\n                'ハムスターS %1: 線を追従する速度を%2にする %3',\n            roboid_hamster_s_set_following_gain_to:\n                'ハムスターS %1: 線を追従する方向変化量を%2にする %3',\n            roboid_hamster_s_stop: 'ハムスターS %1: 停止する %2',\n            roboid_hamster_s_set_led_to: 'ハムスターS %1: %2LEDを%3にする %4',\n            roboid_hamster_s_pick_led: 'ハムスターS %1: %2LEDを%3にする %4',\n            roboid_hamster_s_change_led_by_rgb: 'ハムスターS %1: %2LEDをR:%3G:%4B:%5ずつ変える %6',\n            roboid_hamster_s_set_led_to_rgb: 'ハムスターS %1: %2LEDをR:%3G:%4B:%5にする %6',\n            roboid_hamster_s_clear_led: 'ハムスターS %1: %2LEDをオフ %3',\n            roboid_hamster_s_play_sound_times: 'ハムスターS %1: %2音を%3回鳴らす %4',\n            roboid_hamster_s_play_sound_times_until_done:\n                'ハムスターS %1: 終わるまで%2音を%3回鳴らす %4',\n            roboid_hamster_s_change_buzzer_by: 'ハムスターS %1: ブザー音を%2ずつ変える %3',\n            roboid_hamster_s_set_buzzer_to: 'ハムスターS %1: ブザー音を%2にする %3',\n            roboid_hamster_s_clear_sound: 'ハムスターS %1: 音を止める %2',\n            roboid_hamster_s_play_note: 'ハムスターS %1: %2%3音を鳴らす %4',\n            roboid_hamster_s_play_note_for: 'ハムスターS %1: %2%3音を%4拍鳴らす %5',\n            roboid_hamster_s_rest_for: 'ハムスターS %1: %2拍休む %3',\n            roboid_hamster_s_change_tempo_by: 'ハムスターS %1: テンポを%2ずつ変える %3',\n            roboid_hamster_s_set_tempo_to: 'ハムスターS %1: テンポを%2BPMにする %3',\n            roboid_hamster_s_set_port_to: 'ハムスターS %1: ポート%2を%3にする %4',\n            roboid_hamster_s_change_output_by: 'ハムスターS %1: 出力%2を%3ずつ変える %4',\n            roboid_hamster_s_set_output_to: 'ハムスターS %1: 出力%2を%3にする %4',\n            roboid_hamster_s_gripper: 'ハムスターS %1: グリッパを%2 %3',\n            roboid_hamster_s_release_gripper: 'ハムスターS %1: グリッパをオフ %2',\n            roboid_hamster_s_write_serial: 'ハムスターS %1: シリアルに%2%3を書き出す %4',\n            roboid_hamster_s_read_serial_until: 'ハムスターS %1: シリアルを%2読み取る %3',\n            roboid_hamster_s_set_serial_rate_to: 'ハムスターS %1: シリアル速度を%2Bdにする %3',\n            roboid_turtle_button_state: 'カメ %1: 背中を %2 した？',\n            roboid_turtle_change_buzzer_by: 'カメ %1: ブザー音の高さを %2 だけ変えて鳴らす %3',\n            roboid_turtle_change_head_led_by_rgb:\n                'カメ %1: 頭のLEDの色をR（赤：あか） %2  G（緑：みどり） %3  B（青：あお） %4 だけ変える %5',\n            roboid_turtle_change_tempo_by: 'カメ %1: 演奏の速さを %2 だけ変える %3',\n            roboid_turtle_change_wheel_by:\n                'カメ %1: %2 の車輪（しゃりん）の速さを %3 だけ変える %4',\n            roboid_turtle_change_wheels_by_left_right:\n                'カメ %1: 車輪（しゃりん）の速さを左 %2 右 %3 だけ変える %4',\n            roboid_turtle_clear_head_led: 'カメ %1: 頭のLEDを消す %2',\n            roboid_turtle_clear_sound: 'カメ %1: 音を消す %2',\n            roboid_turtle_cross_intersection: 'カメ %1: 黒の線が交わる点を渡る %2',\n            roboid_turtle_follow_line: 'カメ %1: %2 の線にそって移動する %3',\n            roboid_turtle_follow_line_until: 'カメ %1: 黒の線にそって %2 まで移動する %3',\n            roboid_turtle_follow_line_until_black: 'カメ %1: %2 の線にそって黒まで移動する %3',\n            roboid_turtle_is_color_pattern: 'カメ %1: 色の順番 %2 %3 を感知した?',\n            roboid_turtle_move_backward_unit: 'カメ %1: 後ろへ %2 %3 移動する %4',\n            roboid_turtle_move_forward_unit: 'カメ %1: 前へ %2 %3 移動する %4',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                'カメ %1: %2 の車輪を中心に %3 %4 %5 方向に回る %6',\n            roboid_turtle_play_note: 'カメ %1: %2 %3 を演奏する %4',\n            roboid_turtle_play_note_for_beats: 'カメ %1: %2 %3 を %4 拍演奏する %5',\n            roboid_turtle_play_sound_times: 'カメ %1: 音 %2 を %3 回鳴らす %4',\n            roboid_turtle_play_sound_times_until_done:\n                'カメ %1: 音 %2 を %3 回鳴らして終わるまで待つ %4',\n            roboid_turtle_rest_for_beats: 'カメ %1: %2 拍休む %3',\n            roboid_turtle_set_buzzer_to: 'カメ %1: ブザー音の高さを %2 にして鳴らす %3',\n            roboid_turtle_set_following_speed_to: 'カメ %1: 線にそって移動する速さを %2 にする %3',\n            roboid_turtle_set_head_led_to: 'カメ %1: 頭のLEDの色を %2 にする %3',\n            roboid_turtle_set_head_led_to_rgb:\n                'カメ %1: 頭のLEDの色をR（赤：あか） %2  G（緑：みどり） %3  B（青：あお） %4 にする %5',\n            roboid_turtle_set_tempo_to: 'カメ %1: 演奏の速さを1分間に %2 拍にする %3',\n            roboid_turtle_set_wheel_to: 'カメ %1: %2 の車輪（しゃりん）の速さを %3 にする %4',\n            roboid_turtle_set_wheels_to_left_right:\n                'カメ %1: 車輪（しゃりん）の速さを左 %2 右 %3 にする %4',\n            roboid_turtle_stop: 'カメ %1: 移動を停止する %2',\n            roboid_turtle_touching_color: 'カメ %1: %2 を感知した？',\n            roboid_turtle_turn_at_intersection: 'カメ %1: 黒の線が交わる点で %2 へ方向を変える %3',\n            roboid_turtle_turn_unit_in_place: 'カメ %1: %2 へ %3 %4 その場で回る %5',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                'カメ %1: %2 へ %3 %4 半径 %5 cmで %6 方向に回る %7',\n            roboid_turtle_value: 'カメ %1: %2',\n            roboid_turtle_boolean: 'カメ %1: %2?',\n            roboid_turtle_pick_head_led: 'カメ %1: 頭のLEDの色を %2 にする %3',\n\n            roboid_cheese_value: 'チーズスティック %1: %2',\n            roboid_cheese_boolean: 'チーズスティック %1: %2?',\n            roboid_cheese_play_sound_times: 'チーズスティック %1: %2 音を %3 回再生する %4',\n            roboid_cheese_play_sound_times_until_done:\n                'チーズスティック %1: %2 音を %3 回再生して待つ %4',\n            roboid_cheese_change_buzzer_by: 'チーズスティック %1: ブザー音を %2 Hzずつ変える %3',\n            roboid_cheese_set_buzzer_to: 'チーズスティック %1: ブザー音を %2 Hzにする %3',\n            roboid_cheese_clear_sound: 'チーズスティック %1: 音をオフにする %2',\n            roboid_cheese_play_note: 'チーズスティック %1: %2 %3 音をならす %4',\n            roboid_cheese_play_note_for: 'チーズスティック %1: %2 %3 音を %4 拍子ならす %5',\n            roboid_cheese_rest_for: 'チーズスティック %1: %2 拍子休む %3',\n            roboid_cheese_change_tempo_by:\n                'チーズスティック %1: 演奏のテンポを %2 BPMずつ変える %3',\n            roboid_cheese_set_tempo_to: 'チーズスティック %1: 演奏のテンポを %2 BPMにする %3',\n            roboid_cheese_set_sound_port_to: 'チーズスティック %1: 音出力を %2にする %3',\n            roboid_cheese_set_input_mode_to: 'チーズスティック %1: ポート %2を %3 入力にする %4',\n            roboid_cheese_set_input_range_to:\n                'チーズスティック %1: 入力 %2の範囲 %3 ~ %4を %5 ~ %6 小数点 %7にする %8',\n            roboid_cheese_set_three_input_ranges_to:\n                'チーズスティック %1: 入力 %2の範囲 %3 ~ %4 ~ %5を %6 ~ %7 ~ %8 小数点 %9にする %10',\n            roboid_cheese_analog_input: 'チーズスティック %1: 入力 %2',\n            roboid_cheese_digital_input: 'チーズスティック %1: 入力 %2 %3 ?',\n            roboid_cheese_button_state: 'チーズスティック %1: ボタン %2を %3?',\n            roboid_cheese_set_pulse_mode_to: 'チーズスティック %1: ポート %2を %3 入力にする %4',\n            roboid_cheese_pulse_input: 'チーズスティック %1: ポート %2でパルスが感知されたか?',\n            roboid_cheese_set_digital_output_to:\n                'チーズスティック %1: デジタル出力 %2を %3にする %4',\n            roboid_cheese_change_pwm_output_by:\n                'チーズスティック %1: PWM出力 %2を %3%ずつ変える %4',\n            roboid_cheese_set_pwm_output_to: 'チーズスティック %1: PWM出力 %2を %3%にする %4',\n            roboid_cheese_change_servo_motor_angle_by:\n                'チーズスティック %1: サーボモータ %2の角度を %3度ずつ変える %4',\n            roboid_cheese_set_servo_motor_angle_to:\n                'チーズスティック %1: サーボモータ %2の角度を %3度にする %4',\n            roboid_cheese_turn_off_servo_motor:\n                'チーズスティック %1: サーボモータ %2 の電源をオフにする %3',\n            roboid_cheese_change_dc_motor_velocity_by:\n                'チーズスティック %1: DCモータ %2の速度を %3%ずつ変える %4',\n            roboid_cheese_set_dc_motor_velocity_to:\n                'チーズスティック %1: DCモータ %2の速度を %3%にする %4',\n            roboid_cheese_stop_dc_motor: 'チーズスティック %1: DCモータ %2 を停止する %3',\n            roboid_cheese_rotate_step_motor:\n                'チーズスティック %1: ステップモータ %2 ステップを速度 %3 ステップ/秒に回る %4',\n            roboid_cheese_change_step_motor_velocity_by:\n                'チーズスティック %1: ステップモータの速度を %2 ステップ/秒ずつ変える %3',\n            roboid_cheese_set_step_motor_velocity_to:\n                'チーズスティック %1: ステップモータの速度を %2 ステップ/秒にする %3',\n            roboid_cheese_stop_off_step_motor: 'チーズスティック %1: ステップモータを %2 %3',\n            roboid_cheese_set_step_motor_mode_to:\n                'チーズスティック %1: ステップモータを %2 モードにする %3',\n            roboid_cheese_step_count: 'チーズスティック %1: ステップ数',\n            roboid_cheese_set_led_to_color: 'チーズスティック %1: RGBLED %2を %3 %4にする %5',\n            roboid_cheese_pick_led_to: 'チーズスティック %1: RGBLED %2を %3にする %4',\n            roboid_cheese_change_led_by_rgb:\n                'チーズスティック %1: RGBLED %2を R: %3 G: %4 B: %5ずつ変える %6',\n            roboid_cheese_setLed_to_rgb:\n                'チーズスティック %1: RGBLED %2を R: %3 G: %4 B: %5にする %6',\n            roboid_cheese_clear_led: 'チーズスティック %1: RGBLED %2 をオフにする %3',\n            roboid_cheese_set_led_type_to: 'チーズスティック %1: RGBLED %2を %3形にする %4',\n            roboid_cheese_neopixel_set_number_and_type_to:\n                'チーズスティック %1 ネオピクセル: LED %2個、%3にする %4',\n            roboid_cheese_neopixel_set_all_leds_to_pattern:\n                'チーズスティック %1 ネオピクセル: すべてのLEDを %2 パターンにする %3',\n            roboid_cheese_neopixel_set_all_leds_to_color:\n                'チーズスティック %1 ネオピクセル: すべてのLEDを %2にする %3',\n            roboid_cheese_neopixel_pick_all_leds_to:\n                'チーズスティック %1 ネオピクセル: すべてのLEDを %2にする %3',\n            roboid_cheese_neopixel_change_all_leds_by_rgb:\n                'チーズスティック %1 ネオピクセル: すべてのLEDを R: %2 G: %3 B: %4ずつ変える %5',\n            roboid_cheese_neopixel_set_all_leds_to_rgb:\n                'チーズスティック %1 ネオピクセル: すべてのLEDを R: %2 G: %3 B: %4にする %5',\n            roboid_cheese_neopixel_clear_all_leds:\n                'チーズスティック %1 ネオピクセル: すべてのLEDをオフにする %2',\n            roboid_cheese_neopixel_set_led_to_color:\n                'チーズスティック %1 ネオピクセル: %2番目のLEDを %3にする %4',\n            roboid_cheese_neopixel_pick_led_to:\n                'チーズスティック %1 ネオピクセル: %2番目のLEDを %3にする %4',\n            roboid_cheese_neopixel_change_led_by_rgb:\n                'チーズスティック %1 ネオピクセル: %2番目のLEDを R: %3 G: %4 B: %5ずつ変える %6',\n            roboid_cheese_neopixel_set_led_to_rgb:\n                'チーズスティック %1 ネオピクセル: %2番目のLEDを R: %3 G: %4 B: %5にする %6',\n            roboid_cheese_neopixel_clear_led:\n                'チーズスティック %1 ネオピクセル: %2番目のLEDをオフにする %3',\n            roboid_cheese_neopixel_set_led_range_to_pattern:\n                'チーズスティック %1 ネオピクセル: %2番目から %3番目までのLEDを %4 パターンにする %5',\n            roboid_cheese_neopixel_set_led_range_to_color:\n                'チーズスティック %1 ネオピクセル: %2番目から %3番目まで %4間隔のLEDを %5にする %6',\n            roboid_cheese_neopixel_pick_led_range_to:\n                'チーズスティック %1 ネオピクセル: %2番目から %3番目まで %4間隔のLEDを %5にする %6',\n            roboid_cheese_neopixel_change_led_range_by_rgb:\n                'チーズスティック %1 ネオピクセル: %2番目から %3番目まで %4間隔のLEDを R: %5 G: %6 B: %7ずつ変える %8',\n            roboid_cheese_neopixel_set_led_range_to_rgb:\n                'チーズスティック %1 ネオピクセル: %2番目から %3番目まで %4間隔のLEDを R: %5 G: %6 B: %7にする %8',\n            roboid_cheese_neopixel_clear_led_range:\n                'チーズスティック %1 ネオピクセル: %2番目から %3番目まで %4間隔のLEDをオフにする %5',\n            roboid_cheese_neopixel_shift: 'チーズスティック %1 ネオピクセル: %2ピクセル移動する %3',\n            roboid_cheese_neopixel_rotate:\n                'チーズスティック %1 ネオピクセル: %2ピクセル回転する %3',\n            roboid_cheese_neopixel_change_brightness_by:\n                'チーズスティック %1 ネオピクセル: 明るさを %2%ずつ変える %3',\n            roboid_cheese_neopixel_set_brightness_to:\n                'チーズスティック %1 ネオピクセル: 明るさを %2%にする %3',\n            roboid_cheese_write_serial: 'チーズスティック %1: シリアルに %2 %3 を書き出す %4',\n            roboid_cheese_read_serial_until: 'チーズスティック %1: シリアルを %2 読み取る %3',\n            roboid_cheese_set_serial_port_to: 'チーズスティック %1: シリアルポートを %2にする %3',\n            roboid_cheese_set_serial_rate_to: 'チーズスティック %1: シリアル速度を %2Bdにする %3',\n            roboid_cheese_serial_input: 'チーズスティック %1: シリアル入力',\n            roboid_cheese_pid_start: 'チーズスティック %1: %2 を開始する %3',\n            roboid_cheese_pid_set_range_to:\n                'チーズスティック %1: PID %2の範囲 %3 ~ %4を %5 ~ %6 小数点 %7にする %8',\n            roboid_cheese_pid_set_three_ranges_to:\n                'チーズスティック %1: PID %2の範囲 %3 ~ %4 ~ %5を %6 ~ %7 ~ %8 小数点 %9にする %10',\n            roboid_cheese_pid_reset_encoder: 'チーズスティック %1: PID エンコーダ値を初期化する %2',\n            roboid_cheese_pid_input: 'チーズスティック %1: PID %2',\n            roboid_cheese_pid_button_state: 'チーズスティック %1: PID ボタン %2を %3?',\n            roboid_cheese_hat010_start: 'チーズスティック %1: HAT-010 5x5マトリックスを開始する %2',\n            roboid_cheese_hat010_button: 'チーズスティック %1: HAT-010 ボタン %2',\n            roboid_cheese_hat010_button_state: 'チーズスティック %1: HAT-010 ボタン %2を %3?',\n            roboid_cheese_hat010_background_turn_on_xy:\n                'チーズスティック %1: HAT-010 背景 x: %2 y: %3を %4に点灯する %5',\n            roboid_cheese_hat010_background_turn_off_xy:\n                'チーズスティック %1: HAT-010 背景 x: %2 y: %3をオフにする %4',\n            roboid_cheese_hat010_background_draw_shape_at_xy:\n                'チーズスティック %1: HAT-010 背景 %2 %3を x: %4 y: %5に描画する %6',\n            roboid_cheese_hat010_background_draw_string_at_xy:\n                'チーズスティック %1: HAT-010 背景 %2 文字列 %3を x: %4 y: %5に描画する %6',\n            roboid_cheese_hat010_background_draw_pattern_at_xy:\n                'チーズスティック %1: HAT-010 背景 %2 パターン %3を x: %4 y: %5に描画する %6',\n            roboid_cheese_hat010_clear: 'チーズスティック %1: HAT-010 %2 を消す %3',\n            roboid_cheese_hat010_scroll_by_xy:\n                'チーズスティック %1: HAT-010 %2 x: %3 y: %4だけ移動する %5',\n            roboid_cheese_hat010_sprite_set_to_shape:\n                'チーズスティック %1: HAT-010 図 %2を %3 %4にする %5',\n            roboid_cheese_hat010_sprite_set_to_string:\n                'チーズスティック %1: HAT-010 図 %2を %3 文字列 %4にする %5',\n            roboid_cheese_hat010_sprite_set_to_pattern:\n                'チーズスティック %1: HAT-010 図 %2を %3 パターン %4にする %5',\n            roboid_cheese_hat010_sprite_clear_show_hide:\n                'チーズスティック %1: HAT-010 図 %2を %3 %4',\n            roboid_cheese_hat010_sprite_change_positions_by_xy:\n                'チーズスティック %1: HAT-010 図 %2の位置を x: %3 y: %4ずつ変える %5',\n            roboid_cheese_hat010_sprite_set_positions_to_xy:\n                'チーズスティック %1: HAT-010 図 %2の位置を x: %3 y: %4にする %5',\n            roboid_cheese_hat010_sprite_change_position_by_value:\n                'チーズスティック %1: HAT-010 図 %2の %3 位置を %4ずつ変える %5',\n            roboid_cheese_hat010_sprite_set_position_to_value:\n                'チーズスティック %1: HAT-010 図 %2の %3 位置を %4にする %5',\n            roboid_cheese_hat010_sprite_rotate:\n                'チーズスティック %1: HAT-010 図 %2を %3 方向に回転する %4',\n            roboid_cheese_hat010_sprite_flip_in_direction:\n                'チーズスティック %1: HAT-010 図 %2を %3 方向に反転する %4',\n            roboid_cheese_hat010_sprite_stamp_to_background:\n                'チーズスティック %1: HAT-010 図 %2を背景にスタンプする %3',\n            roboid_cheese_hat010_sprite_position: 'チーズスティック %1: HAT-010 図 %2の %3 位置',\n            roboid_cheese_hat010_sprite_touching_sprite:\n                'チーズスティック %1: HAT-010 図 %2が 図 %3に着いたか?',\n            roboid_cheese_hat010_sprite_touching:\n                'チーズスティック %1: HAT-010 図 %2が %3に着いたか?',\n            roboid_cheese_hat010_change_brightness_by:\n                'チーズスティック %1: HAT-010 明るさを %2%ずつ変える %3',\n            roboid_cheese_hat010_set_brightness_to:\n                'チーズスティック %1: HAT-010 明るさを %2%にする %3',\n        },\n        Helper: {\n            roboid_hamster_gripper: 'Opens or closes the gripper.',\n            roboid_hamster_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            roboid_hamster_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_hamster_play_note: '選択された音階（音名、オクターブ）が鳴ります。',\n            roboid_hamster_s_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            roboid_hamster_s_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_hamster_s_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n            roboid_hamster_s_move_forward_once: 'Moves one space forward on the board.',\n            roboid_hamster_s_turn_once: 'Turns left/right 90 degrees on the board.',\n            roboid_hamster_s_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            roboid_hamster_s_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            roboid_hamster_s_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_pivot_around_unit_in_direction:\n                'Pivots around the left/right pen/wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_turn_unit_with_radius_in_direction:\n                'Turns left/right so that the left/right pen draws the circle of the entered radius in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_change_both_wheels_by:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_hamster_s_set_both_wheels_to:\n                'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_hamster_s_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_hamster_s_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_hamster_s_follow_line_using:\n                'Moves along the black/white line by using the left/right/both floor sensors.',\n            roboid_hamster_s_follow_line_until:\n                'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n            roboid_hamster_s_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            roboid_hamster_s_set_following_gain_to:\n                'Sets the directional variation (1 to 8) 선을 따라 이동하는 방향 변화량(1 ~ 8)을 설정합니다. 숫자가 클수록 급커브를 잘 따라가지만 직선에서 좌우로 더 흔들립니다.',\n            roboid_hamster_s_stop: 'Stops both wheels.',\n            roboid_hamster_s_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n            roboid_hamster_s_pick_led: 'Turns left/right/both LEDs to the selected color.',\n            roboid_hamster_s_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of left/right/both LEDs, respectively.',\n            roboid_hamster_s_set_led_to_rgb:\n                'Sets the R, G, B values of left/right/both LEDs to the entered values.',\n            roboid_hamster_s_clear_led: 'Turns off the left/right/both LEDs.',\n            roboid_hamster_s_play_sound_times: 'Plays the selected sound as many times as entered.',\n            roboid_hamster_s_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            roboid_hamster_s_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            roboid_hamster_s_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            roboid_hamster_s_clear_sound: 'Turns off sound.',\n            roboid_hamster_s_play_note: 'It sounds the selected tone and octave.',\n            roboid_hamster_s_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            roboid_hamster_s_rest_for: 'Rests as much as the beat you entered.',\n            roboid_hamster_s_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            roboid_hamster_s_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            roboid_hamster_s_set_port_to:\n                'Sets the io mode of the selected external port to the selected mode.',\n            roboid_hamster_s_change_output_by:\n                'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            roboid_hamster_s_set_output_to:\n                'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            roboid_hamster_s_gripper: 'Opens or closes the gripper.',\n            roboid_hamster_s_release_gripper:\n                'Turns off the gripper so that it can be moved freely.',\n            roboid_hamster_s_write_serial: 'Sends strings via serial communication.',\n            roboid_hamster_s_read_serial_until:\n                'Read the strings received by serial communication.',\n            roboid_hamster_s_set_serial_rate_to: 'Sets the speed of serial communication.',\n            roboid_turtle_button_state:\n                '背中（ボタン）が[クリック/ダブルクリック/長押し]された場合は｢正しい｣と判断します。それ以外の場合は｢正しくない｣と判断します。',\n            roboid_turtle_change_buzzer_by:\n                'ブザーの現在の音の高さ（ヘルツ）に入力された数値を足して鳴らします。小数点以下2桁まで入力できます。',\n            roboid_turtle_change_head_led_by_rgb:\n                '頭のLEDライトの色に、入力されたR（赤：あか）、G（緑：みどり）、B（青：あお）の数値（範囲:0～255）を足します。',\n            roboid_turtle_change_tempo_by:\n                '入力された数値を現在の演奏速度（１分あたりの拍数）に足します。',\n            roboid_turtle_change_wheel_by:\n                '[左/右]の車輪（しゃりん）の速さ（%）に入力された数値を足します。足した結果が、正の数の場合は前方向に、負の数の場合は後方向に、車輪が回転します。',\n            roboid_turtle_change_wheels_by_left_right:\n                '左右の車輪（しゃりん）の速さ（%）にそれぞれ入力された数値を足します。足した結果が、正の数の場合は前方向に、負の数の場合は後方向に、車輪が回転します。',\n            roboid_turtle_clear_head_led: '頭のLEDライトを消します。',\n            roboid_turtle_clear_sound: '音を消します。',\n            roboid_turtle_cross_intersection:\n                '黒の線が交わる点を越えて、前方の黒の線にそって移動します。',\n            roboid_turtle_follow_line: '白地の上の選択された色の線にそって移動します。',\n            roboid_turtle_follow_line_until:\n                '白地の上の黒の線にそって移動し、カラーセンサーが選択された色を感知したら停止します。',\n            roboid_turtle_follow_line_until_black:\n                '白地の上の選択された色の線にそって移動し、カラーセンサーが黒を感知したら停止します。',\n            roboid_turtle_is_color_pattern:\n                'カラーセンサーが選択された色の順番（パターン）を感知した場合は｢正しい｣と判断します。それ以外の場合は｢正しくない｣と判断します。',\n            roboid_turtle_move_backward_unit:\n                '入力された数値[cm/秒/パルス]だけ後方向に移動します。',\n            roboid_turtle_move_forward_unit: '入力された数値[cm/秒/パルス]だけ前方向に移動します。',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                '[左/右]の車輪を中心に、入力された数値[角度/秒/パルス]だけ、[前/後]方向に回転します。',\n            roboid_turtle_play_note: '選択された音階（音名、オクターブ）が鳴ります。',\n            roboid_turtle_play_note_for_beats:\n                '選択された音階（音名、オクターブ）が、入力された拍数分鳴ります。',\n            roboid_turtle_play_sound_times: '選択された音を入力された回数だけ再生します。',\n            roboid_turtle_play_sound_times_until_done:\n                '選択された音を入力された回数だけ再生します。再生が終わってから次の命令を実行します。',\n            roboid_turtle_rest_for_beats: '入力された拍数分だけ音を鳴らすのを休みます。',\n            roboid_turtle_set_buzzer_to:\n                'ブザーの現在の音の高さ（ヘルツ）を入力された数値にして鳴らします。小数点以下2桁まで入力できます。',\n            roboid_turtle_set_following_speed_to:\n                '線にそって移動する速度（範囲：1〜8）を入力された数値にします。数字が大きいほど動きが速くなります。',\n            roboid_turtle_set_head_led_to: '頭のLEDライトを選択された色にします。',\n            roboid_turtle_set_head_led_to_rgb:\n                '頭のLEDライトを入力されたR（赤：あか）、G（緑：みどり）、B（青：あお）の数値（範囲:0～255）の色にします。',\n            roboid_turtle_set_tempo_to:\n                '入力された数値を現在の演奏速度（１分あたりの拍数）にします。',\n            roboid_turtle_set_wheel_to:\n                '[左/右]の車輪（しゃりん）の速さ（範囲：-400～400%）を入力された数値にします。正の数の場合は前方向に、負の数の場合は後方向に、車輪が回転します。0を入力すると車輪が停止します。',\n            roboid_turtle_set_wheels_to_left_right:\n                '左右の車輪（しゃりん）の速さ（範囲：-400～400%）をそれぞれ入力された数値にします。正の数の場合は前方向に、負の数の場合は後方向に、車輪が回転します。0を入力すると車輪が停止します。',\n            roboid_turtle_stop: '移動を停止します。',\n            roboid_turtle_touching_color:\n                'カラーセンサーが選択された色を感知した場合は｢正しい｣と判断します。それ以外の場合は｢正しくない｣と判断します。',\n            roboid_turtle_turn_at_intersection:\n                '黒の線が交わる点で[左/右/後]方向に回転して、黒い線にそって移動します。',\n            roboid_turtle_turn_unit_in_place:\n                '入力された数値[角度/秒/パルス]だけ、その場で[左/右]に回転します。',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                '入力された数値[角度/秒/パルス]だけ、入力された半径（cm）で、[前/後]方向に回転します。',\n            roboid_turtle_value:\n                '色番号：カラーセンサーが感知した色の番号（範囲：-1〜8、初期値：-1）<br/>色のパターン：カラーセンサーが感知した色のパターンの値（範囲：-1〜88、初期値：-1）<br/>床センサー：床センサーの値（範囲：0〜100、初期値：0）<br/>ボタン：ボタンの状態（クリックした時：1、それ以外：0、初期値：0）<br/>前後の速さ：加速度センサーの前後（x軸）の速さの値（範囲：-32768〜32767、初期値：0）タートルが前進する方向はx軸の正方向です。<br/>左右の速さ：加速度センサーの左右（y軸）の速さの値（範囲：-32768〜32767、初期値：0）タートルの左方向がy軸の正方向です。<br/>上下の速さ：加速度センサーの上下（z軸）の速さの値（範囲：-32768〜32767、初期値：0）タートルの上方向がz軸の正方向です。<br/>',\n            roboid_turtle_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_turtle_pick_head_led: '頭のLEDライトを選択された色にします。',\n        },\n        Blocks: {\n            hamster_note_c: 'ド',\n            hamster_note_c_sharp: 'ド♯(レ♭)',\n            hamster_note_d: 'レ',\n            hamster_note_d_sharp: 'レ♯(ミ♭)',\n            hamster_note_e: 'ミ',\n            hamster_note_f: 'ファ',\n            hamster_note_f_sharp: 'ファ♯(ソ♭)',\n            hamster_note_g: 'ソ',\n            hamster_note_g_sharp: 'ソ♯(ラ♭)',\n            hamster_note_a: 'ラ',\n            hamster_note_a_sharp: 'ラ♯(シ♭)',\n            hamster_note_b: 'シ',\n            hamster_tilt_forward: '前に傾けたか',\n            hamster_tilt_backward: '後に傾けたか',\n            hamster_tilt_left: '左に傾けたか',\n            hamster_tilt_right: '右に傾けたか',\n            hamster_tilt_flip: '上下裏返したか',\n            hamster_tilt_not: '傾けなかったか',\n            hamster_battery_normal: '電池が正常か',\n            hamster_battery_low: '電池が足りないか',\n            hamster_battery_empty: '電池がないか',\n            hamster_open_gripper: '開く',\n            hamster_close_gripper: '閉める',\n            hamster_s_color_black: '黒',\n            hamster_s_color_blue: '青',\n            hamster_s_color_green: '緑',\n            hamster_s_color_orange: 'オレンジ',\n            hamster_s_color_purple: '紫',\n            hamster_s_color_red: '赤',\n            hamster_s_color_sky_blue: '水色',\n            hamster_s_color_violet: '赤紫',\n            hamster_s_color_white: '白',\n            hamster_s_color_yellow: '黄色',\n            hamster_s_left: '左',\n            hamster_s_right: '右',\n            hamster_s_both: '両方',\n            hamster_s_note_c: 'ド',\n            hamster_s_note_c_sharp: 'ド♯(レ♭)',\n            hamster_s_note_d: 'レ',\n            hamster_s_note_d_sharp: 'レ♯(ミ♭)',\n            hamster_s_note_e: 'ミ',\n            hamster_s_note_f: 'ファ',\n            hamster_s_note_f_sharp: 'ファ♯(ソ♭)',\n            hamster_s_note_g: 'ソ',\n            hamster_s_note_g_sharp: 'ソ♯(ラ♭)',\n            hamster_s_note_a: 'ラ',\n            hamster_s_note_a_sharp: 'ラ♯(シ♭)',\n            hamster_s_note_b: 'シ',\n            hamster_s_port_a: 'A',\n            hamster_s_port_b: 'B',\n            hamster_s_port_ab: 'AとB',\n            hamster_s_tilt_forward: '前に傾けたか',\n            hamster_s_tilt_backward: '後に傾けたか',\n            hamster_s_tilt_left: '左に傾けたか',\n            hamster_s_tilt_right: '右に傾けたか',\n            hamster_s_tilt_flip: '上下裏返したか',\n            hamster_s_tilt_not: '傾けなかったか',\n            hamster_s_tap: '叩いたか',\n            hamster_s_free_fall: '自由落下したか',\n            hamster_s_battery_normal: '電池が正常か',\n            hamster_s_battery_low: '電池が足りないか',\n            hamster_s_battery_empty: '電池がないか',\n            hamster_s_forward: '前',\n            hamster_s_backward: '後',\n            hamster_s_front: '前',\n            hamster_s_rear: '後',\n            hamster_s_left_pen: '左ペン',\n            hamster_s_right_pen: '右ペン',\n            hamster_s_left_wheel: '左車輪',\n            hamster_s_right_wheel: '右車輪',\n            hamster_s_robot: 'ロボット',\n            hamster_s_gain_default: '基本値',\n            hamster_s_sensor_acceleration_x: '前後の速さ',\n            hamster_s_sensor_acceleration_y: '左右の速さ',\n            hamster_s_sensor_acceleration_z: '上下の速さ',\n            hamster_s_sensor_input_a: '入力A',\n            hamster_s_sensor_input_b: '入力B',\n            hamster_s_sensor_left_floor: '左床センサー',\n            hamster_s_sensor_left_proximity: '左近接センサー',\n            hamster_s_sensor_light: '照度',\n            hamster_s_sensor_right_floor: '右床センサー',\n            hamster_s_sensor_right_proximity: '右近接センサー',\n            hamster_s_sensor_signal_strength: '信号強度',\n            hamster_s_sensor_temperature: '温度',\n            hamster_s_buzzer: 'ブーザー',\n            hamster_s_left_led: '左LED',\n            hamster_s_left_wheel: '左車輪',\n            hamster_s_note: '音符',\n            hamster_s_output_a: '出力A',\n            hamster_s_output_b: '出力B',\n            hamster_s_right_led: '右LED',\n            hamster_s_right_wheel: '右車輪',\n            hamster_s_sound_angry: '怒った',\n            hamster_s_sound_beep: 'ビープ音',\n            hamster_s_sound_birthday: '誕生日',\n            hamster_s_sound_chop: 'チョップ',\n            hamster_s_sound_dibidibidip: 'ディビディビディップ',\n            hamster_s_sound_engine: 'エンジン',\n            hamster_s_sound_good_job: 'よくできました',\n            hamster_s_sound_happy: '幸福',\n            hamster_s_sound_march: '行進',\n            hamster_s_sound_noise: 'ノイズ',\n            hamster_s_sound_random_beep: 'ビープ音のどれか',\n            hamster_s_sound_robot: 'ロボット',\n            hamster_s_sound_sad: '悲しみ',\n            hamster_s_sound_siren: 'サイレン',\n            hamster_s_sound_sleep: '睡眠',\n            hamster_s_unit_cm: 'cm',\n            hamster_s_unit_deg: '°',\n            hamster_s_unit_pulse: 'パルス',\n            hamster_s_unit_sec: '秒',\n            hamster_s_analog_input: 'アナログ入力',\n            hamster_s_digital_input: 'デジタル入力',\n            hamster_s_digital_input_pull_down: 'デジタル入力 (プルダウン)',\n            hamster_s_digital_input_pull_up: 'デジタル入力 (プルアップ)',\n            hamster_s_digital_output: 'デジタル出力',\n            hamster_s_pwm_output: 'PWM出力',\n            hamster_s_servo_output: 'サーボ出力',\n            hamster_s_voltage_input: '電圧入力',\n            hamster_s_open_gripper: '開く',\n            hamster_s_close_gripper: '閉める',\n            hamster_s_serial_string: '文字列',\n            hamster_s_serial_string_line: '文字列1行',\n            hamster_s_serial_all: '全部',\n            hamster_s_serial_until_new_line: '改行まで',\n            hamster_s_serial_until_comma: '、(読点)まで',\n            hamster_s_serial_until_colon: '：(コロン)まで',\n            hamster_s_serial_until_dollar: '$まで',\n            hamster_s_serial_until_sharp: '#まで',\n            hamster_s_serial_input: 'シリアル入力',\n            turtle_acceleration_x: '前後の速さ',\n            turtle_acceleration_y: '左右の速さ',\n            turtle_acceleration_z: '上下の速さ',\n            turtle_back: '後',\n            turtle_both: '両方',\n            turtle_button: 'ボタン',\n            turtle_buzzer: 'ブザー',\n            turtle_clicked: 'クリック',\n            turtle_color_any: 'すべての色',\n            turtle_color_black: '黒',\n            turtle_color_blue: '青',\n            turtle_color_green: '緑',\n            turtle_color_number: '色番号',\n            turtle_color_orange: 'オレンジ',\n            turtle_color_pattern: '色のパターン',\n            turtle_color_purple: '紫',\n            turtle_color_red: '赤',\n            turtle_color_sky_blue: '水色',\n            turtle_color_violet: '赤紫',\n            turtle_color_white: '白',\n            turtle_color_yellow: '黄色',\n            turtle_double_clicked: 'ダブルクリック',\n            turtle_floor: '床センサー',\n            turtle_head: '前',\n            turtle_head_color: '頭のLEDの色',\n            turtle_left: '左',\n            turtle_left_wheel: '左の車輪',\n            turtle_long_pressed: '長押し',\n            turtle_note: '音符',\n            turtle_right: '右',\n            turtle_right_wheel: '右の車輪',\n            turtle_sound_beep: 'ビープ音',\n            turtle_sound_birthday: '誕生日',\n            turtle_sound_dibidibidip: 'ディビディビディップ',\n            turtle_sound_engine: 'エンジン',\n            turtle_sound_good_job: 'よくできました',\n            turtle_sound_march: '行進',\n            turtle_sound_random_beep: 'ビープ音のどれか',\n            turtle_sound_robot: 'ロボット',\n            turtle_sound_siren: 'サイレン',\n            turtle_tail: '後',\n            turtle_unit_cm: 'cm',\n            turtle_unit_deg: '°',\n            turtle_unit_pulse: 'パルス',\n            turtle_unit_sec: '秒',\n            turtle_note_c: 'ド',\n            turtle_note_c_sharp: 'ド♯(レ♭)',\n            turtle_note_d: 'レ',\n            turtle_note_d_sharp: 'レ♯(ミ♭)',\n            turtle_note_e: 'ミ',\n            turtle_note_f: 'ファ',\n            turtle_note_f_sharp: 'ファ♯(ソ♭)',\n            turtle_note_g: 'ソ',\n            turtle_note_g_sharp: 'ソ♯(ラ♭)',\n            turtle_note_a: 'ラ',\n            turtle_note_a_sharp: 'ラ♯(シ♭)',\n            turtle_note_b: 'シ',\n            turtle_tilt_forward: '前に傾けたか',\n            turtle_tilt_backward: '後に傾けたか',\n            turtle_tilt_left: '左に傾けたか',\n            turtle_tilt_right: '右に傾けたか',\n            turtle_tilt_flip: '上下裏返したか',\n            turtle_tilt_not: '傾けなかったか',\n            turtle_battery_normal: '電池が正常か',\n            turtle_battery_low: '電池が足りないか',\n            turtle_battery_empty: '電池がないか',\n            ROBOID_cheese_stick: 'チーズスティック',\n            ROBOID_sensor_signal_strength: '信号の強さ',\n            ROBOID_sensor_signal_strength_dbm: '信号の強さ(dBm)',\n            ROBOID_sensor_acceleration_x: 'x軸の加速度',\n            ROBOID_sensor_acceleration_y: 'y軸の加速度',\n            ROBOID_sensor_acceleration_z: 'z軸の加速度',\n            ROBOID_sensor_input_sa: '入力Sa',\n            ROBOID_sensor_input_sb: '入力Sb',\n            ROBOID_sensor_input_sc: '入力Sc',\n            ROBOID_sensor_input_la: '入力La',\n            ROBOID_sensor_input_lb: '入力Lb',\n            ROBOID_sensor_input_lc: '入力Lc',\n            ROBOID_sensor_step_count: 'ステップ数',\n            ROBOID_monitor_output_sa: '出力Sa',\n            ROBOID_monitor_output_sb: '出力Sb',\n            ROBOID_monitor_output_sc: '出力Sc',\n            ROBOID_monitor_output_la: '出力La',\n            ROBOID_monitor_output_lb: '出力Lb',\n            ROBOID_monitor_output_lc: '出力Lc',\n            ROBOID_monitor_output_mab: '出力Mab',\n            ROBOID_monitor_output_mcd: '出力Mcd',\n            ROBOID_monitor_buzzer: 'ブザー',\n            ROBOID_monitor_note: '音符',\n            ROBOID_logo_sky_direction: 'ロゴが空の方向か',\n            ROBOID_logo_earth_direction: 'ロゴが地の方向か',\n            ROBOID_power_switch_sky_direction: '電源スイッチが空の方向か',\n            ROBOID_power_switch_earth_direction: '電源スイッチが地の方向か',\n            ROBOID_port_s_sky_direction: 'ポートSが空の方向か',\n            ROBOID_port_s_earth_direction: 'ポートSが地の方向か',\n            ROBOID_tap: '叩いたか',\n            ROBOID_free_fall: '落下したか',\n            ROBOID_battery_normal: '電池残量が充分か',\n            ROBOID_battery_low: '電池残量が足りないか',\n            ROBOID_battery_empty: '電池残量がなくなったか',\n            ROBOID_sound_beep: 'ビープ',\n            ROBOID_sound_random_beep: 'ランダムビープ',\n            ROBOID_sound_noise: 'ノイズ',\n            ROBOID_sound_siren: 'サイレン',\n            ROBOID_sound_engine: 'エンジン',\n            ROBOID_sound_chop: 'チョップ',\n            ROBOID_sound_robot: 'ロボット',\n            ROBOID_sound_dibidibidip: 'ディビディビディ',\n            ROBOID_sound_good_job: 'よくできました',\n            ROBOID_sound_happy: 'よろこび',\n            ROBOID_sound_angry: 'いかり',\n            ROBOID_sound_sad: 'かなしみ',\n            ROBOID_sound_sleep: 'ねむい',\n            ROBOID_sound_march: 'マーチ',\n            ROBOID_sound_birthday: 'たんじょうび',\n            ROBOID_note_c: 'ド',\n            ROBOID_note_c_sharp: 'ド♯(レ♭)',\n            ROBOID_note_d: 'レ',\n            ROBOID_note_d_sharp: 'レ♯(ミ♭)',\n            ROBOID_note_e: 'ミ',\n            ROBOID_note_f: 'ファ',\n            ROBOID_note_f_sharp: 'ファ♯(ソ♭)',\n            ROBOID_note_g: 'ソ',\n            ROBOID_note_g_sharp: 'ソ♯(ラ♭)',\n            ROBOID_note_a: 'ラ',\n            ROBOID_note_a_sharp: 'ラ♯(シ♭)',\n            ROBOID_note_b: 'シ',\n            ROBOID_speaker_internal: '内蔵スピーカー',\n            ROBOID_speaker_port_mab: 'ポートMab',\n            ROBOID_io_mode_makey: 'メイキー',\n            ROBOID_io_mode_button: 'ボタン',\n            ROBOID_io_mode_digital_pull_up: 'デジタル(プルアップ)',\n            ROBOID_io_mode_digital_pull_down: 'デジタル(プルダウン)',\n            ROBOID_io_mode_analog: 'アナログ',\n            ROBOID_io_mode_voltage: '電圧',\n            ROBOID_io_mode_pulse: 'パルス',\n            ROBOID_io_mode_pulse_pull_up: 'パルス(プルアップ)',\n            ROBOID_io_mode_pulse_pull_down: 'パルス(プルダウン)',\n            ROBOID_io_mode_normal: '基本',\n            ROBOID_io_mode_power: 'パワー',\n            ROBOID_io_port_high_current_mab: '大電流Ma(-)b',\n            ROBOID_io_port_high_current_mcd: '大電流Mc(-)d',\n            ROBOID_io_action_stop: '停止する',\n            ROBOID_io_action_turn_off: 'オフにする',\n            ROBOID_range_integer: 'なし',\n            ROBOID_range_real: 'あり',\n            ROBOID_led_intensity_dark: '暗い',\n            ROBOID_led_intensity_normal: '基本',\n            ROBOID_led_intensity_bright: '明るい',\n            ROBOID_led_type_default: '基本',\n            ROBOID_led_type_crgb: '-RGB',\n            ROBOID_led_type_crbg: '-RBG',\n            ROBOID_led_type_cgrb: '-GRB',\n            ROBOID_led_type_cgbr: '-GBR',\n            ROBOID_led_type_cbrg: '-BRG',\n            ROBOID_led_type_cbgr: '-BGR',\n            ROBOID_led_type_argb: '+RGB',\n            ROBOID_led_type_arbg: '+RBG',\n            ROBOID_led_type_agrb: '+GRB',\n            ROBOID_led_type_agbr: '+GBR',\n            ROBOID_led_type_abrg: '+BRG',\n            ROBOID_led_type_abgr: '+BGR',\n            ROBOID_color_red: '赤色',\n            ROBOID_color_orange: 'オレンジ色',\n            ROBOID_color_yellow: '黄色',\n            ROBOID_color_green: '緑色',\n            ROBOID_color_sky_blue: '水色',\n            ROBOID_color_blue: '青色',\n            ROBOID_color_violet: '青むらさき色',\n            ROBOID_color_purple: 'むらさき色',\n            ROBOID_color_white: '白色',\n            ROBOID_neopixel_3_colors: '3色',\n            ROBOID_neopixel_6_colors: '6色',\n            ROBOID_neopixel_12_colors: '12色',\n            ROBOID_neopixel_red_green: '赤色から緑色まで',\n            ROBOID_neopixel_red_blue: '赤色から青色まで',\n            ROBOID_neopixel_red_white: '赤色から白色まで',\n            ROBOID_neopixel_green_red: '緑色から赤色まで',\n            ROBOID_neopixel_green_blue: '緑色から青色まで',\n            ROBOID_neopixel_green_white: '緑色から白色まで',\n            ROBOID_neopixel_blue_red: '青色から赤色まで',\n            ROBOID_neopixel_blue_green: '青色から緑色まで',\n            ROBOID_neopixel_blue_white: '青色から白色まで',\n            ROBOID_neopixel_white_red: '白色から赤色まで',\n            ROBOID_neopixel_white_green: '白色から緑色まで',\n            ROBOID_neopixel_white_blue: '白色から青色まで',\n            ROBOID_neopixel_red_black: '赤色ますます暗く',\n            ROBOID_neopixel_green_black: '緑色ますます暗く',\n            ROBOID_neopixel_blue_black: '青色ますます暗く',\n            ROBOID_neopixel_white_black: '白色ますます暗く',\n            ROBOID_neopixel_black_red: '赤色ますます明るく',\n            ROBOID_neopixel_black_green: '緑色ますます明るく',\n            ROBOID_neopixel_black_blue: '青色ますます明るく',\n            ROBOID_neopixel_black_white: '白色ますます明るく',\n            ROBOID_serial_string: '文字列',\n            ROBOID_serial_string_line: '文字列1行',\n            ROBOID_serial_all: '全部',\n            ROBOID_serial_until_comma: '、(読点)まで',\n            ROBOID_serial_until_colon: '：(コロン)まで',\n            ROBOID_serial_until_dollar: '$まで',\n            ROBOID_serial_until_sharp: '#まで',\n            ROBOID_serial_until_new_line: '改行まで',\n            ROBOID_serial_port_wa_rb: 'La(書く)Lb(読む)',\n            ROBOID_serial_port_ra_wb: 'La(読む)Lb(書く)',\n            ROBOID_serial_port_wa: 'La(書く)',\n            ROBOID_serial_port_ra: 'La(読む)',\n            ROBOID_pid_10: 'PID-10 超音波センサー(HC-SR04+)',\n            ROBOID_pid_11_1: 'PID-11-1 温湿度センサー(DHT11)',\n            ROBOID_pid_11_2: 'PID-11-2 温湿度センサー(DHT21)',\n            ROBOID_pid_11_3: 'PID-11-3 温湿度センサー(DHT22)',\n            ROBOID_pid_12: 'PID-12 温度センサー(DS18B20)',\n            ROBOID_pid_13: 'PID-13 ジョイスティックとボタン',\n            ROBOID_pid_14: 'PID-14 デュアルジョイスティック',\n            ROBOID_pid_15: 'PID-15 IRトランシーバー',\n            ROBOID_pid_16: 'PID-16 エンコーダ',\n            ROBOID_pid_distance: '距離(cm)',\n            ROBOID_pid_temperature: '温度(℃)',\n            ROBOID_pid_humidity: '湿度(%RH)',\n            ROBOID_pid_x1: 'x1',\n            ROBOID_pid_y1: 'y1',\n            ROBOID_pid_x2: 'x2',\n            ROBOID_pid_y2: 'y2',\n            ROBOID_pid_button1: 'ボタン1',\n            ROBOID_pid_button2: 'ボタン2',\n            ROBOID_pid_encoder: 'エンコーダ',\n            ROBOID_clicked: 'クリックしたか',\n            ROBOID_double_clicked: 'ダブルクリックしたか',\n            ROBOID_long_pressed: '長く押したか',\n            ROBOID_shape_square: '四角形',\n            ROBOID_shape_triangle: '三角形',\n            ROBOID_shape_diamond: 'ダイヤモンド',\n            ROBOID_shape_circle: '円',\n            ROBOID_shape_x: 'X',\n            ROBOID_shape_like: 'すき',\n            ROBOID_shape_dislike: 'きらい',\n            ROBOID_shape_angry: 'いかり',\n            ROBOID_shape_open_mouth: '開けた口',\n            ROBOID_shape_close_mouth: '閉じた口',\n            ROBOID_shape_walk1: '歩く1',\n            ROBOID_shape_walk2: '歩く2',\n            ROBOID_shape_heart: 'ハート',\n            ROBOID_shape_star: '星',\n            ROBOID_shape_airplane: '飛行機',\n            ROBOID_shape_puppy: '子犬',\n            ROBOID_shape_butterfly: '蝶',\n            ROBOID_shape_quarter_note: '4分音符',\n            ROBOID_shape_eighth_note: '8分音符',\n            ROBOID_shape_left_arrow: '左矢印',\n            ROBOID_shape_right_arrow: '右矢印',\n            ROBOID_shape_up_arrow: '上矢印',\n            ROBOID_shape_down_arrow: '下矢印',\n            ROBOID_hat_background: '背景',\n            ROBOID_hat_all: '全部',\n            ROBOID_hat_clear: '消す',\n            ROBOID_hat_show: 'みせる',\n            ROBOID_hat_hide: 'かくす',\n            ROBOID_hat_clockwise: '時計',\n            ROBOID_hat_counterclockwise: '反時計',\n            ROBOID_hat_left_right: '左-右',\n            ROBOID_hat_up_down: '上-下',\n            ROBOID_hat_auto: '自動',\n            ROBOID_hat_manual: '手動',\n            ROBOID_hat_other_sprite: '他の図',\n            ROBOID_hat_left_wall: '左壁',\n            ROBOID_hat_right_wall: '右壁',\n            ROBOID_hat_top_wall: '上壁',\n            ROBOID_hat_bottom_wall: '下壁',\n            ROBOID_hat_any_wall: '全ての壁',\n        },\n    },\n    vn: {\n        template: {\n            roboid_hamster_gripper: 'Hamster %1: %2 gripper %3',\n            roboid_hamster_release_gripper: 'Hamster %1: release gripper %2',\n            roboid_hamster_boolean: 'Hamster %1: %2?',\n            roboid_hamster_play_note: 'Hamster %1: play note %2 %3 %4',\n            roboid_hamster_s_hand_found: 'HamsterS %1: hand found?',\n            roboid_hamster_s_boolean: 'HamsterS %1: %2?',\n            roboid_hamster_s_value: 'HamsterS %1: %2',\n            roboid_hamster_s_move_forward_once: 'HamsterS %1: move forward once on board %2',\n            roboid_hamster_s_turn_once: 'HamsterS %1: turn %2 once on board %3',\n            roboid_hamster_s_move_forward_unit: 'HamsterS %1: move forward %2 %3 %4',\n            roboid_hamster_s_move_backward_unit: 'HamsterS %1: move backward %2 %3 %4',\n            roboid_hamster_s_turn_unit_in_place: 'HamsterS %1: turn %2 %3 %4 in place %5',\n            roboid_hamster_s_pivot_around_unit_in_direction:\n                'HamsterS %1: pivot around %2 %3 %4 in %5 direction %6',\n            roboid_hamster_s_turn_unit_with_radius_in_direction:\n                'HamsterS %1: %2 turn %3 %4 %5 with radius %6 cm in %7 direction %8',\n            roboid_hamster_s_change_both_wheels_by:\n                'HamsterS %1: change wheels by left: %2 right: %3 %4',\n            roboid_hamster_s_set_both_wheels_to: 'HamsterS %1: set wheels to left: %2 right: %3 %4',\n            roboid_hamster_s_change_wheel_by: 'HamsterS %1: change %2 wheel by %3 %4',\n            roboid_hamster_s_set_wheel_to: 'HamsterS %1: set %2 wheel to %3 %4',\n            roboid_hamster_s_follow_line_using:\n                'HamsterS %1: follow %2 line using %3 floor sensor %4',\n            roboid_hamster_s_follow_line_until:\n                'HamsterS %1: follow %2 line until %3 intersection %4',\n            roboid_hamster_s_set_following_speed_to: 'HamsterS %1: set following speed to %2 %3',\n            roboid_hamster_s_set_following_gain_to:\n                'HamsterS %1: set following directional variation to %2 %3',\n            roboid_hamster_s_stop: 'HamsterS %1: stop %2',\n            roboid_hamster_s_set_led_to: 'HamsterS %1: set %2 led to %3 %4',\n            roboid_hamster_s_pick_led: 'HamsterS %1: set %2 led to %3 %4',\n            roboid_hamster_s_change_led_by_rgb:\n                'HamsterS %1: change %2 led by r: %3 g: %4 b: %5 %6',\n            roboid_hamster_s_set_led_to_rgb: 'HamsterS %1: set %2 led to r: %3 g: %4 b: %5 %6',\n            roboid_hamster_s_clear_led: 'HamsterS %1: clear %2 led %3',\n            roboid_hamster_s_play_sound_times: 'HamsterS %1: play sound %2 %3 times %4',\n            roboid_hamster_s_play_sound_times_until_done:\n                'HamsterS %1: play sound %2 %3 times until done %4',\n            roboid_hamster_s_change_buzzer_by: 'HamsterS %1: change buzzer by %2 %3',\n            roboid_hamster_s_set_buzzer_to: 'HamsterS %1: set buzzer to %2 %3',\n            roboid_hamster_s_clear_sound: 'HamsterS %1: clear sound %2',\n            roboid_hamster_s_play_note: 'HamsterS %1: play note %2 %3 %4',\n            roboid_hamster_s_play_note_for: 'HamsterS %1: play note %2 %3 for %4 beats %5',\n            roboid_hamster_s_rest_for: 'HamsterS %1: rest for %2 beats %3',\n            roboid_hamster_s_change_tempo_by: 'HamsterS %1: change tempo by %2 %3',\n            roboid_hamster_s_set_tempo_to: 'HamsterS %1: set tempo to %2 bpm %3',\n            roboid_hamster_s_set_port_to: 'HamsterS %1: set port %2 to %3 %4',\n            roboid_hamster_s_change_output_by: 'HamsterS %1: change output %2 by %3 %4',\n            roboid_hamster_s_set_output_to: 'HamsterS %1: set output %2 to %3 %4',\n            roboid_hamster_s_gripper: 'HamsterS %1: %2 gripper %3',\n            roboid_hamster_s_release_gripper: 'HamsterS %1: release gripper %2',\n            roboid_hamster_s_write_serial: 'HamsterS %1: write %2 %3 to serial %4',\n            roboid_hamster_s_read_serial_until: 'HamsterS %1: read serial %2 %3',\n            roboid_hamster_s_set_serial_rate_to: 'HamsterS %1: set serial rate to %2 Bd %3',\n            roboid_turtle_button_state: 'Turtle %1: button %2 ?',\n            roboid_turtle_change_buzzer_by: 'Turtle %1: change buzzer by %2 %3',\n            roboid_turtle_change_head_led_by_rgb:\n                'Turtle %1: change head led by r: %2 g: %3 b: %4 %5',\n            roboid_turtle_change_tempo_by: 'Turtle %1: change tempo by %2 %3',\n            roboid_turtle_change_wheel_by: 'Turtle %1: change %2 wheel by %3 %4',\n            roboid_turtle_change_wheels_by_left_right:\n                'Turtle %1: change wheels by left: %2 right: %3 %4',\n            roboid_turtle_clear_head_led: 'Turtle %1: clear head led %2',\n            roboid_turtle_clear_sound: 'Turtle %1: clear sound %2',\n            roboid_turtle_cross_intersection: 'Turtle %1: cross black intersection %2',\n            roboid_turtle_follow_line: 'Turtle %1: follow %2 line %3',\n            roboid_turtle_follow_line_until: 'Turtle %1: follow black line until %2 %3',\n            roboid_turtle_follow_line_until_black: 'Turtle %1: follow %2 line until black %3',\n            roboid_turtle_is_color_pattern: 'Turtle %1: color pattern %2 %3 ?',\n            roboid_turtle_move_backward_unit: 'Turtle %1: move backward %2 %3 %4',\n            roboid_turtle_move_forward_unit: 'Turtle %1: move forward %2 %3 %4',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                'Turtle %1: pivot around %2 wheel %3 %4 in %5 direction %6',\n            roboid_turtle_play_note: 'Turtle %1: play note %2 %3 %4',\n            roboid_turtle_play_note_for_beats: 'Turtle %1: play note %2 %3 for %4 beats %5',\n            roboid_turtle_play_sound_times: 'Turtle %1: play sound %2 %3 times %4',\n            roboid_turtle_play_sound_times_until_done:\n                'Turtle %1: play sound %2 %3 times until done %4',\n            roboid_turtle_rest_for_beats: 'Turtle %1: rest for %2 beats %3',\n            roboid_turtle_set_buzzer_to: 'Turtle %1: set buzzer to %2 %3',\n            roboid_turtle_set_following_speed_to: 'Turtle %1: set following speed to %2 %3',\n            roboid_turtle_set_head_led_to: 'Turtle %1: set head led to %2 %3',\n            roboid_turtle_set_head_led_to_rgb: 'Turtle %1: set head led to r: %2 g: %3 b: %4 %5',\n            roboid_turtle_set_tempo_to: 'Turtle %1: set tempo to %2 bpm %3',\n            roboid_turtle_set_wheel_to: 'Turtle %1: set %2 wheel to %3 %4',\n            roboid_turtle_set_wheels_to_left_right:\n                'Turtle %1: set wheels to left: %2 right: %3 %4',\n            roboid_turtle_stop: 'Turtle %1: stop %2',\n            roboid_turtle_touching_color: 'Turtle %1: touching %2 ?',\n            roboid_turtle_turn_at_intersection: 'Turtle %1: turn %2 at black intersection %3',\n            roboid_turtle_turn_unit_in_place: 'Turtle %1: turn %2 %3 %4 in place %5',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                'Turtle %1: turn %2 %3 %4 with radius %5 cm in %6 direction %7',\n            roboid_turtle_value: 'Turtle %1: %2',\n            roboid_turtle_boolean: 'Turtle %1: %2?',\n            roboid_turtle_pick_head_led: 'Turtle %1: set head led to %2 %3',\n\n            roboid_cheese_value: 'Cheese Stick %1: %2',\n            roboid_cheese_boolean: 'Cheese Stick %1: %2?',\n            roboid_cheese_play_sound_times: 'Cheese Stick %1: play sound %2 %3 times %4',\n            roboid_cheese_play_sound_times_until_done:\n                'Cheese Stick %1: play sound %2 %3 times until done %4',\n            roboid_cheese_change_buzzer_by: 'Cheese Stick %1: change buzzer by %2 Hz %3',\n            roboid_cheese_set_buzzer_to: 'Cheese Stick %1: set buzzer to %2 Hz %3',\n            roboid_cheese_clear_sound: 'Cheese Stick %1: clear sound %2',\n            roboid_cheese_play_note: 'Cheese Stick %1: play note %2 %3 %4',\n            roboid_cheese_play_note_for: 'Cheese Stick %1: play note %2 %3 for %4 beats %5',\n            roboid_cheese_rest_for: 'Cheese Stick %1: rest for %2 beats %3',\n            roboid_cheese_change_tempo_by: 'Cheese Stick %1: change tempo by %2 BPM %3',\n            roboid_cheese_set_tempo_to: 'Cheese Stick %1: set tempo to %2 BPM %3',\n            roboid_cheese_set_sound_port_to: 'Cheese Stick %1: set sound output to %2 %3',\n            roboid_cheese_set_input_mode_to: 'Cheese Stick %1: set port %2 to %3 input %4',\n            roboid_cheese_set_input_range_to:\n                'Cheese Stick %1: set input %2 range %3 - %4 to %5 - %6 %7 decimal point %8',\n            roboid_cheese_set_three_input_ranges_to:\n                'Cheese Stick %1: set input %2 range %3 - %4 - %5 to %6 - %7 - %8 %9 decimal point %10',\n            roboid_cheese_analog_input: 'Cheese Stick %1: input %2',\n            roboid_cheese_digital_input: 'Cheese Stick %1: input %2 %3 ?',\n            roboid_cheese_button_state: 'Cheese Stick %1: button %2 %3 ?',\n            roboid_cheese_set_pulse_mode_to: 'Cheese Stick %1: set port %2 to %3 input %4',\n            roboid_cheese_pulse_input: 'Cheese Stick %1: pulse detected on port %2 ?',\n            roboid_cheese_set_digital_output_to: 'Cheese Stick %1: set digital output %2 to %3 %4',\n            roboid_cheese_change_pwm_output_by: 'Cheese Stick %1: change pwm output %2 by %3% %4',\n            roboid_cheese_set_pwm_output_to: 'Cheese Stick %1: set pwm output %2 to %3% %4',\n            roboid_cheese_change_servo_motor_angle_by:\n                'Cheese Stick %1: change servo motor %2 by %3 degrees %4',\n            roboid_cheese_set_servo_motor_angle_to:\n                'Cheese Stick %1: set servo motor %2 to %3 degrees %4',\n            roboid_cheese_turn_off_servo_motor: 'Cheese Stick %1: turn off servo motor %2 %3',\n            roboid_cheese_change_dc_motor_velocity_by:\n                'Cheese Stick %1: change dc motor %2 velocity by %3% %4',\n            roboid_cheese_set_dc_motor_velocity_to:\n                'Cheese Stick %1: set dc motor %2 velocity to %3% %4',\n            roboid_cheese_stop_dc_motor: 'Cheese Stick %1: stop dc motor %2 %3',\n            roboid_cheese_rotate_step_motor:\n                'Cheese Stick %1: rotate step motor %2 steps with velocity %3 step/sec %4',\n            roboid_cheese_change_step_motor_velocity_by:\n                'Cheese Stick %1: change step motor velocity by %2 step/sec %3',\n            roboid_cheese_set_step_motor_velocity_to:\n                'Cheese Stick %1: set step motor velocity to %2 step/sec %3',\n            roboid_cheese_stop_off_step_motor: 'Cheese Stick %1: %2 step motor %3',\n            roboid_cheese_set_step_motor_mode_to: 'Cheese Stick %1: set step motor to %2 mode %3',\n            roboid_cheese_step_count: 'Cheese Stick %1: step count',\n            roboid_cheese_set_led_to_color: 'Cheese Stick %1: set rgb led %2 to %3 %4 %5',\n            roboid_cheese_pick_led_to: 'Cheese Stick %1: set rgb led %2 to %3 %4',\n            roboid_cheese_change_led_by_rgb:\n                'Cheese Stick %1: change rgb led %2 by r: %3 g: %4 b: %5 %6',\n            roboid_cheese_setLed_to_rgb: 'Cheese Stick %1: set rgb led %2 to r: %3 g: %4 b: %5 %6',\n            roboid_cheese_clear_led: 'Cheese Stick %1: clear rgb led %2 %3',\n            roboid_cheese_set_led_type_to: 'Cheese Stick %1: set rgb led %2 to %3 type %4',\n            roboid_cheese_neopixel_set_number_and_type_to:\n                'Cheese Stick %1 neopixel: set %2 leds as %3 %4',\n            roboid_cheese_neopixel_set_all_leds_to_pattern:\n                'Cheese Stick %1 neopixel: set all leds to pattern %2 %3',\n            roboid_cheese_neopixel_set_all_leds_to_color:\n                'Cheese Stick %1 neopixel: set all leds to %2 %3',\n            roboid_cheese_neopixel_pick_all_leds_to:\n                'Cheese Stick %1 neopixel: set all leds to %2 %3',\n            roboid_cheese_neopixel_change_all_leds_by_rgb:\n                'Cheese Stick %1 neopixel: change all leds by r: %2 g: %3 b: %4 %5',\n            roboid_cheese_neopixel_set_all_leds_to_rgb:\n                'Cheese Stick %1 neopixel: set all leds to r: %2 g: %3 b: %4 %5',\n            roboid_cheese_neopixel_clear_all_leds: 'Cheese Stick %1 neopixel: clear all leds %2',\n            roboid_cheese_neopixel_set_led_to_color:\n                'Cheese Stick %1 neopixel: set led %2 to %3 %4',\n            roboid_cheese_neopixel_pick_led_to: 'Cheese Stick %1 neopixel: set led %2 to %3 %4',\n            roboid_cheese_neopixel_change_led_by_rgb:\n                'Cheese Stick %1 neopixel: change led %2 by r: %3 g: %4 b: %5 %6',\n            roboid_cheese_neopixel_set_led_to_rgb:\n                'Cheese Stick %1 neopixel: set led %2 to r: %3 g: %4 b: %5 %6',\n            roboid_cheese_neopixel_clear_led: 'Cheese Stick %1 neopixel: clear led %2 %3',\n            roboid_cheese_neopixel_set_led_range_to_pattern:\n                'Cheese Stick %1 neopixel: set leds (from %2 to %3) to pattern %4 %5',\n            roboid_cheese_neopixel_set_led_range_to_color:\n                'Cheese Stick %1 neopixel: set leds (from %2 to %3 with %4 increments) to %5 %6',\n            roboid_cheese_neopixel_pick_led_range_to:\n                'Cheese Stick %1 neopixel: set leds (from %2 to %3 with %4 increments) to %5 %6',\n            roboid_cheese_neopixel_change_led_range_by_rgb:\n                'Cheese Stick %1 neopixel: change leds (from %2 to %3 with %4 increments) by r: %5 g: %6 b: %7 %8',\n            roboid_cheese_neopixel_set_led_range_to_rgb:\n                'Cheese Stick %1 neopixel: set leds (from %2 to %3 with %4 increments) to r: %5 g: %6 b: %7 %8',\n            roboid_cheese_neopixel_clear_led_range:\n                'Cheese Stick %1 neopixel: clear leds (from %2 to %3 with %4 increments) %5',\n            roboid_cheese_neopixel_shift: 'Cheese Stick %1 neopixel: shift %2 pixels %3',\n            roboid_cheese_neopixel_rotate: 'Cheese Stick %1 neopixel: rotate %2 pixels %3',\n            roboid_cheese_neopixel_change_brightness_by:\n                'Cheese Stick %1 neopixel: change brightness by %2% %3',\n            roboid_cheese_neopixel_set_brightness_to:\n                'Cheese Stick %1 neopixel: set brightness to %2% %3',\n            roboid_cheese_write_serial: 'Cheese Stick %1: write %2 %3 to serial %4',\n            roboid_cheese_read_serial_until: 'Cheese Stick %1: read serial %2 %3',\n            roboid_cheese_set_serial_port_to: 'Cheese Stick %1: set serial port to %2 %3',\n            roboid_cheese_set_serial_rate_to: 'Cheese Stick %1: set serial rate to %2Bd %3',\n            roboid_cheese_serial_input: 'Cheese Stick %1: serial input',\n            roboid_cheese_pid_start: 'Cheese Stick %1: start %2 %3',\n            roboid_cheese_pid_set_range_to:\n                'Cheese Stick %1 PID: set %2 range %3 - %4 to %5 - %6 %7 decimal point %8',\n            roboid_cheese_pid_set_three_ranges_to:\n                'Cheese Stick %1 PID: set %2 range %3 - %4 - %5 to %6 - %7 - %8 %9 decimal point %10',\n            roboid_cheese_pid_reset_encoder: 'Cheese Stick %1 PID: clear encoder %2',\n            roboid_cheese_pid_input: 'Cheese Stick %1 PID: %2',\n            roboid_cheese_pid_button_state: 'Cheese Stick %1 PID: button %2 %3?',\n            roboid_cheese_hat010_start: 'Cheese Stick %1: start HAT-010 5x5 matrix %2',\n            roboid_cheese_hat010_button: 'Cheese Stick %1 HAT-010: button %2',\n            roboid_cheese_hat010_button_state: 'Cheese Stick %1 HAT-010: button %2 %3?',\n            roboid_cheese_hat010_background_turn_on_xy:\n                'Cheese Stick %1 HAT-010 background: turn on x: %2 y: %3 in %4 %5',\n            roboid_cheese_hat010_background_turn_off_xy:\n                'Cheese Stick %1 HAT-010 background: turn off x: %2 y: %3 %4',\n            roboid_cheese_hat010_background_draw_shape_at_xy:\n                'Cheese Stick %1 HAT-010 background: draw %2 %3 at x: %4 y: %5 %6',\n            roboid_cheese_hat010_background_draw_string_at_xy:\n                'Cheese Stick %1 HAT-010 background: draw %2 string %3 at x: %4 y: %5 %6',\n            roboid_cheese_hat010_background_draw_pattern_at_xy:\n                'Cheese Stick %1 HAT-010 background: draw %2 pattern %3 at x: %4 y: %5 %6',\n            roboid_cheese_hat010_clear: 'Cheese Stick %1 HAT-010: clear %2 %3',\n            roboid_cheese_hat010_scroll_by_xy:\n                'Cheese Stick %1 HAT-010: scroll %2 by x: %3 y: %4 %5',\n            roboid_cheese_hat010_sprite_set_to_shape:\n                'Cheese Stick %1 HAT-010 sprite %2: set sprite to %3 %4 %5',\n            roboid_cheese_hat010_sprite_set_to_string:\n                'Cheese Stick %1 HAT-010 sprite %2: set sprite to %3 string %4 %5',\n            roboid_cheese_hat010_sprite_set_to_pattern:\n                'Cheese Stick %1 HAT-010 sprite %2: set sprite to %3 pattern %4 %5',\n            roboid_cheese_hat010_sprite_clear_show_hide:\n                'Cheese Stick %1 HAT-010 sprite %2: %3 sprite %4',\n            roboid_cheese_hat010_sprite_change_positions_by_xy:\n                'Cheese Stick %1 HAT-010 sprite %2: change position by x: %3 y: %4 %5',\n            roboid_cheese_hat010_sprite_set_positions_to_xy:\n                'Cheese Stick %1 HAT-010 sprite %2: set position to x: %3 y: %4 %5',\n            roboid_cheese_hat010_sprite_change_position_by_value:\n                'Cheese Stick %1 HAT-010 sprite %2: change %3 position by %4 %5',\n            roboid_cheese_hat010_sprite_set_position_to_value:\n                'Cheese Stick %1 HAT-010 sprite %2: set %3 position to %4 %5',\n            roboid_cheese_hat010_sprite_rotate: 'Cheese Stick %1 HAT-010 sprite %2: rotate %3 %4',\n            roboid_cheese_hat010_sprite_flip_in_direction:\n                'Cheese Stick %1 HAT-010 sprite %2: flip in %3 direction %4',\n            roboid_cheese_hat010_sprite_stamp_to_background:\n                'Cheese Stick %1 HAT-010 sprite %2: stamp to background %3',\n            roboid_cheese_hat010_sprite_position: 'Cheese Stick %1 HAT-010 sprite %2: %3 position',\n            roboid_cheese_hat010_sprite_touching_sprite:\n                'Cheese Stick %1 HAT-010 sprite %2: touching sprite %3?',\n            roboid_cheese_hat010_sprite_touching: 'Cheese Stick %1 HAT-010 sprite %2: touching %3?',\n            roboid_cheese_hat010_change_brightness_by:\n                'Cheese Stick %1 HAT-010: change brightness by %2% %3',\n            roboid_cheese_hat010_set_brightness_to:\n                'Cheese Stick %1 HAT-010: set brightness to %2% %3',\n        },\n        Helper: {\n            roboid_hamster_gripper: 'Opens or closes the gripper.',\n            roboid_hamster_release_gripper: 'Turns off the gripper so that it can be moved freely.',\n            roboid_hamster_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_hamster_play_note: 'It sounds the selected tone and octave.',\n            roboid_hamster_s_hand_found:\n                'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            roboid_hamster_s_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_hamster_s_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n            roboid_hamster_s_move_forward_once: 'Moves one space forward on the board.',\n            roboid_hamster_s_turn_once: 'Turns left/right 90 degrees on the board.',\n            roboid_hamster_s_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            roboid_hamster_s_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            roboid_hamster_s_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_pivot_around_unit_in_direction:\n                'Pivots around the left/right pen/wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_turn_unit_with_radius_in_direction:\n                'Turns left/right so that the left/right pen draws the circle of the entered radius in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            roboid_hamster_s_change_both_wheels_by:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_hamster_s_set_both_wheels_to:\n                'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_hamster_s_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_hamster_s_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_hamster_s_follow_line_using:\n                'Moves along the black/white line by using the left/right/both floor sensors.',\n            roboid_hamster_s_follow_line_until:\n                'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n            roboid_hamster_s_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            roboid_hamster_s_set_following_gain_to:\n                'Sets the directional variation (1 to 8) 선을 따라 이동하는 방향 변화량(1 ~ 8)을 설정합니다. 숫자가 클수록 급커브를 잘 따라가지만 직선에서 좌우로 더 흔들립니다.',\n            roboid_hamster_s_stop: 'Stops both wheels.',\n            roboid_hamster_s_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n            roboid_hamster_s_pick_led: 'Turns left/right/both LEDs to the selected color.',\n            roboid_hamster_s_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of left/right/both LEDs, respectively.',\n            roboid_hamster_s_set_led_to_rgb:\n                'Sets the R, G, B values of left/right/both LEDs to the entered values.',\n            roboid_hamster_s_clear_led: 'Turns off the left/right/both LEDs.',\n            roboid_hamster_s_play_sound_times: 'Plays the selected sound as many times as entered.',\n            roboid_hamster_s_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            roboid_hamster_s_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            roboid_hamster_s_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            roboid_hamster_s_clear_sound: 'Turns off sound.',\n            roboid_hamster_s_play_note: 'It sounds the selected tone and octave.',\n            roboid_hamster_s_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            roboid_hamster_s_rest_for: 'Rests as much as the beat you entered.',\n            roboid_hamster_s_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            roboid_hamster_s_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            roboid_hamster_s_set_port_to:\n                'Sets the io mode of the selected external port to the selected mode.',\n            roboid_hamster_s_change_output_by:\n                'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            roboid_hamster_s_set_output_to:\n                'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n            roboid_hamster_s_gripper: 'Opens or closes the gripper.',\n            roboid_hamster_s_release_gripper:\n                'Turns off the gripper so that it can be moved freely.',\n            roboid_hamster_s_write_serial: 'Sends strings via serial communication.',\n            roboid_hamster_s_read_serial_until:\n                'Read the strings received by serial communication.',\n            roboid_hamster_s_set_serial_rate_to: 'Sets the speed of serial communication.',\n            roboid_turtle_button_state:\n                'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            roboid_turtle_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            roboid_turtle_change_head_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of the head LED, respectively.',\n            roboid_turtle_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            roboid_turtle_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_turtle_change_wheels_by_left_right:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            roboid_turtle_clear_head_led: 'Turns off the head LED.',\n            roboid_turtle_clear_sound: 'Turns off sound.',\n            roboid_turtle_cross_intersection:\n                'Moves forward for a moment at the black intersection, then finds the black line and moves again.',\n            roboid_turtle_follow_line: 'Moves along the selected color line on a white background.',\n            roboid_turtle_follow_line_until:\n                'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            roboid_turtle_follow_line_until_black:\n                'Moves along the selected color line on a white background and stops when the color sensor detects black.',\n            roboid_turtle_is_color_pattern:\n                'If the color sensor detects the selected color pattern, true, otherwise false.',\n            roboid_turtle_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            roboid_turtle_move_forward_unit:\n                'Moves forward for the number of cm/seconds/pulses entered.',\n            roboid_turtle_pivot_around_wheel_unit_in_direction:\n                'Pivots around the left/right wheel in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_play_note: 'It sounds the selected tone and octave.',\n            roboid_turtle_play_note_for_beats:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            roboid_turtle_play_sound_times: 'Plays the selected sound as many times as entered.',\n            roboid_turtle_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            roboid_turtle_rest_for_beats: 'Rests as much as the beat you entered.',\n            roboid_turtle_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            roboid_turtle_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            roboid_turtle_set_head_led_to: 'Turns the head LED to the selected color.',\n            roboid_turtle_set_head_led_to_rgb:\n                'Sets the R, G, B values of the head LED to the entered values.',\n            roboid_turtle_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            roboid_turtle_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-400 to 400%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_turtle_set_wheels_to_left_right:\n                'Sets the speed of the left and right wheels to the entered values (-400 to 400%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            roboid_turtle_stop: 'Stops both wheels.',\n            roboid_turtle_touching_color:\n                'If the color sensor detects the selected color, true, otherwise false.',\n            roboid_turtle_turn_at_intersection:\n                'Moves forward for a moment at the black intersection, then turns left/right/back in place, finds the black line and moves again.',\n            roboid_turtle_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_turn_unit_with_radius_in_direction:\n                'Turns left/right drawing the circle of the entered radius in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            roboid_turtle_value:\n                'color number: color number detected by the color sensor (range: -1 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1) <br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.',\n            roboid_turtle_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            roboid_turtle_pick_head_led: 'Turns the head LED to the selected color.',\n        },\n        Blocks: {\n            hamster_note_c: 'C',\n            hamster_note_c_sharp: 'C♯(D♭)',\n            hamster_note_d: 'D',\n            hamster_note_d_sharp: 'D♯(E♭)',\n            hamster_note_e: 'E',\n            hamster_note_f: 'F',\n            hamster_note_f_sharp: 'F♯(G♭)',\n            hamster_note_g: 'G',\n            hamster_note_g_sharp: 'G♯(A♭)',\n            hamster_note_a: 'A',\n            hamster_note_a_sharp: 'A♯(B♭)',\n            hamster_note_b: 'B',\n            hamster_tilt_forward: 'tilt forward',\n            hamster_tilt_backward: 'tilt backward',\n            hamster_tilt_left: 'tilt left',\n            hamster_tilt_right: 'tilt right',\n            hamster_tilt_flip: 'tilt flip',\n            hamster_tilt_not: 'not tilt',\n            hamster_battery_normal: 'battery normal',\n            hamster_battery_low: 'battery low',\n            hamster_battery_empty: 'battery empty',\n            hamster_open_gripper: 'open',\n            hamster_close_gripper: 'close',\n            hamster_s_color_black: 'black',\n            hamster_s_color_blue: 'blue',\n            hamster_s_color_green: 'green',\n            hamster_s_color_orange: 'orange',\n            hamster_s_color_purple: 'purple',\n            hamster_s_color_red: 'red',\n            hamster_s_color_sky_blue: 'sky blue',\n            hamster_s_color_violet: 'violet',\n            hamster_s_color_white: 'white',\n            hamster_s_color_yellow: 'yellow',\n            hamster_s_left: 'left',\n            hamster_s_right: 'right',\n            hamster_s_both: 'both',\n            hamster_s_note_c: 'C',\n            hamster_s_note_c_sharp: 'C♯(D♭)',\n            hamster_s_note_d: 'D',\n            hamster_s_note_d_sharp: 'D♯(E♭)',\n            hamster_s_note_e: 'E',\n            hamster_s_note_f: 'F',\n            hamster_s_note_f_sharp: 'F♯(G♭)',\n            hamster_s_note_g: 'G',\n            hamster_s_note_g_sharp: 'G♯(A♭)',\n            hamster_s_note_a: 'A',\n            hamster_s_note_a_sharp: 'A♯(B♭)',\n            hamster_s_note_b: 'B',\n            hamster_s_port_a: 'A',\n            hamster_s_port_b: 'B',\n            hamster_s_port_ab: 'A and B',\n            hamster_s_tilt_forward: 'tilt forward',\n            hamster_s_tilt_backward: 'tilt backward',\n            hamster_s_tilt_left: 'tilt left',\n            hamster_s_tilt_right: 'tilt right',\n            hamster_s_tilt_flip: 'tilt flip',\n            hamster_s_tilt_not: 'not tilt',\n            hamster_s_tap: 'tap',\n            hamster_s_free_fall: 'free fall',\n            hamster_s_battery_normal: 'battery normal',\n            hamster_s_battery_low: 'battery low',\n            hamster_s_battery_empty: 'battery empty',\n            hamster_s_forward: 'forward',\n            hamster_s_backward: 'backward',\n            hamster_s_front: 'front',\n            hamster_s_rear: 'rear',\n            hamster_s_left_pen: 'left pen',\n            hamster_s_right_pen: 'right pen',\n            hamster_s_left_wheel: 'left wheel',\n            hamster_s_right_wheel: 'right wheel',\n            hamster_s_robot: 'robot',\n            hamster_s_gain_default: 'default',\n            hamster_s_sensor_acceleration_x: 'x acceleration',\n            hamster_s_sensor_acceleration_y: 'y acceleration',\n            hamster_s_sensor_acceleration_z: 'z acceleration',\n            hamster_s_sensor_input_a: 'input A',\n            hamster_s_sensor_input_b: 'input B',\n            hamster_s_sensor_left_floor: 'left floor',\n            hamster_s_sensor_left_proximity: 'left proximity',\n            hamster_s_sensor_light: 'light',\n            hamster_s_sensor_right_floor: 'right floor',\n            hamster_s_sensor_right_proximity: 'right proximity',\n            hamster_s_sensor_signal_strength: 'signal strength',\n            hamster_s_sensor_temperature: 'temperature',\n            hamster_s_buzzer: 'buzzer',\n            hamster_s_left_led: 'left LED',\n            hamster_s_left_wheel: 'left wheel',\n            hamster_s_note: 'note',\n            hamster_s_output_a: 'output A',\n            hamster_s_output_b: 'output B',\n            hamster_s_right_led: 'right LED',\n            hamster_s_right_wheel: 'right wheel',\n            hamster_s_sound_angry: 'angry',\n            hamster_s_sound_beep: 'beep',\n            hamster_s_sound_birthday: 'birthday',\n            hamster_s_sound_chop: 'chop',\n            hamster_s_sound_dibidibidip: 'dibidibidip',\n            hamster_s_sound_engine: 'engine',\n            hamster_s_sound_good_job: 'good job',\n            hamster_s_sound_happy: 'happy',\n            hamster_s_sound_march: 'march',\n            hamster_s_sound_noise: 'noise',\n            hamster_s_sound_random_beep: 'random beep',\n            hamster_s_sound_robot: 'robot',\n            hamster_s_sound_sad: 'sad',\n            hamster_s_sound_siren: 'siren',\n            hamster_s_sound_sleep: 'sleep',\n            hamster_s_unit_cm: 'cm',\n            hamster_s_unit_deg: 'degrees',\n            hamster_s_unit_pulse: 'pulses',\n            hamster_s_unit_sec: 'seconds',\n            hamster_s_analog_input: 'analog input',\n            hamster_s_digital_input: 'digital input',\n            hamster_s_digital_input_pull_down: 'digital input (pull down)',\n            hamster_s_digital_input_pull_up: 'digital input (pull up)',\n            hamster_s_digital_output: 'digital output',\n            hamster_s_pwm_output: 'pwm output',\n            hamster_s_servo_output: 'servo output',\n            hamster_s_voltage_input: 'voltage input',\n            hamster_s_open_gripper: 'open',\n            hamster_s_close_gripper: 'close',\n            hamster_s_serial_string: 'string',\n            hamster_s_serial_string_line: 'string line',\n            hamster_s_serial_all: 'all',\n            hamster_s_serial_until_new_line: 'until new line',\n            hamster_s_serial_until_comma: 'until ,(comma)',\n            hamster_s_serial_until_colon: 'until :(colon)',\n            hamster_s_serial_until_dollar: 'until $',\n            hamster_s_serial_until_sharp: 'until #',\n            hamster_s_serial_input: 'serial input',\n            turtle_acceleration_x: 'x acceleration',\n            turtle_acceleration_y: 'y acceleration',\n            turtle_acceleration_z: 'z acceleration',\n            turtle_back: 'back',\n            turtle_both: 'both',\n            turtle_button: 'button',\n            turtle_buzzer: 'buzzer',\n            turtle_clicked: 'clicked',\n            turtle_color_any: 'any color',\n            turtle_color_black: 'black',\n            turtle_color_blue: 'blue',\n            turtle_color_green: 'green',\n            turtle_color_number: 'color number',\n            turtle_color_orange: 'orange',\n            turtle_color_pattern: 'color pattern',\n            turtle_color_purple: 'purple',\n            turtle_color_red: 'red',\n            turtle_color_sky_blue: 'sky blue',\n            turtle_color_violet: 'violet',\n            turtle_color_white: 'white',\n            turtle_color_yellow: 'yellow',\n            turtle_double_clicked: 'double-clicked',\n            turtle_floor: 'floor',\n            turtle_head: 'head',\n            turtle_head_color: 'head color',\n            turtle_left: 'left',\n            turtle_left_wheel: 'left wheel',\n            turtle_long_pressed: 'long-pressed',\n            turtle_note: 'note',\n            turtle_right: 'right',\n            turtle_right_wheel: 'right wheel',\n            turtle_sound_beep: 'beep',\n            turtle_sound_birthday: 'birthday',\n            turtle_sound_dibidibidip: 'dibidibidip',\n            turtle_sound_engine: 'engine',\n            turtle_sound_good_job: 'good job',\n            turtle_sound_march: 'march',\n            turtle_sound_random_beep: 'random beep',\n            turtle_sound_robot: 'robot',\n            turtle_sound_siren: 'siren',\n            turtle_tail: 'tail',\n            turtle_unit_cm: 'cm',\n            turtle_unit_deg: 'degrees',\n            turtle_unit_pulse: 'pulses',\n            turtle_unit_sec: 'seconds',\n            turtle_note_c: 'C',\n            turtle_note_c_sharp: 'C♯(D♭)',\n            turtle_note_d: 'D',\n            turtle_note_d_sharp: 'D♯(E♭)',\n            turtle_note_e: 'E',\n            turtle_note_f: 'F',\n            turtle_note_f_sharp: 'F♯(G♭)',\n            turtle_note_g: 'G',\n            turtle_note_g_sharp: 'G♯(A♭)',\n            turtle_note_a: 'A',\n            turtle_note_a_sharp: 'A♯(B♭)',\n            turtle_note_b: 'B',\n            turtle_tilt_forward: 'tilt forward',\n            turtle_tilt_backward: 'tilt backward',\n            turtle_tilt_left: 'tilt left',\n            turtle_tilt_right: 'tilt right',\n            turtle_tilt_flip: 'tilt flip',\n            turtle_tilt_not: 'not tilt',\n            turtle_battery_normal: 'battery normal',\n            turtle_battery_low: 'battery low',\n            turtle_battery_empty: 'battery empty',\n            ROBOID_cheese_stick: 'Cheese Stick',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_signal_strength_dbm: 'signal strength (dBm)',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_input_sa: 'input Sa',\n            ROBOID_sensor_input_sb: 'input Sb',\n            ROBOID_sensor_input_sc: 'input Sc',\n            ROBOID_sensor_input_la: 'input La',\n            ROBOID_sensor_input_lb: 'input Lb',\n            ROBOID_sensor_input_lc: 'input Lc',\n            ROBOID_sensor_step_count: 'step count',\n            ROBOID_monitor_output_sa: 'output Sa',\n            ROBOID_monitor_output_sb: 'output Sb',\n            ROBOID_monitor_output_sc: 'output Sc',\n            ROBOID_monitor_output_la: 'output La',\n            ROBOID_monitor_output_lb: 'output Lb',\n            ROBOID_monitor_output_lc: 'output Lc',\n            ROBOID_monitor_output_mab: 'output Mab',\n            ROBOID_monitor_output_mcd: 'output Mcd',\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_logo_sky_direction: 'logo in sky direction',\n            ROBOID_logo_earth_direction: 'logo in earth direction',\n            ROBOID_power_switch_sky_direction: 'power switch in sky direction',\n            ROBOID_power_switch_earth_direction: 'power switch in earth direction',\n            ROBOID_port_s_sky_direction: 'port S in sky direction',\n            ROBOID_port_s_earth_direction: 'port S in earth direction',\n            ROBOID_tap: 'tap',\n            ROBOID_free_fall: 'free fall',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n            ROBOID_speaker_internal: 'internal speaker',\n            ROBOID_speaker_port_mab: 'port Mab',\n            ROBOID_io_mode_makey: 'makey',\n            ROBOID_io_mode_button: 'button',\n            ROBOID_io_mode_digital_pull_up: 'digital (pull up)',\n            ROBOID_io_mode_digital_pull_down: 'digital (pull down)',\n            ROBOID_io_mode_analog: 'analog',\n            ROBOID_io_mode_voltage: 'voltage',\n            ROBOID_io_mode_pulse: 'pulse',\n            ROBOID_io_mode_pulse_pull_up: 'pulse (pull up)',\n            ROBOID_io_mode_pulse_pull_down: 'pulse (pull down)',\n            ROBOID_io_mode_normal: 'normal',\n            ROBOID_io_mode_power: 'power',\n            ROBOID_io_port_high_current_mab: 'high current Ma(-)b',\n            ROBOID_io_port_high_current_mcd: 'high current Mc(-)d',\n            ROBOID_io_action_stop: 'stop',\n            ROBOID_io_action_turn_off: 'turn off',\n            ROBOID_range_integer: 'without',\n            ROBOID_range_real: 'with',\n            ROBOID_led_intensity_dark: 'dark',\n            ROBOID_led_intensity_normal: 'normal',\n            ROBOID_led_intensity_bright: 'bright',\n            ROBOID_led_type_default: 'default',\n            ROBOID_led_type_crgb: '-rgb',\n            ROBOID_led_type_crbg: '-rbg',\n            ROBOID_led_type_cgrb: '-grb',\n            ROBOID_led_type_cgbr: '-gbr',\n            ROBOID_led_type_cbrg: '-brg',\n            ROBOID_led_type_cbgr: '-bgr',\n            ROBOID_led_type_argb: '+rgb',\n            ROBOID_led_type_arbg: '+rbg',\n            ROBOID_led_type_agrb: '+grb',\n            ROBOID_led_type_agbr: '+gbr',\n            ROBOID_led_type_abrg: '+brg',\n            ROBOID_led_type_abgr: '+bgr',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_neopixel_3_colors: '3 colors',\n            ROBOID_neopixel_6_colors: '6 colors',\n            ROBOID_neopixel_12_colors: '12 colors',\n            ROBOID_neopixel_red_green: 'red to green',\n            ROBOID_neopixel_red_blue: 'red to blue',\n            ROBOID_neopixel_red_white: 'red to white',\n            ROBOID_neopixel_green_red: 'green to red',\n            ROBOID_neopixel_green_blue: 'green to blue',\n            ROBOID_neopixel_green_white: 'green to white',\n            ROBOID_neopixel_blue_red: 'blue to red',\n            ROBOID_neopixel_blue_green: 'blue to green',\n            ROBOID_neopixel_blue_white: 'blue to white',\n            ROBOID_neopixel_white_red: 'white to red',\n            ROBOID_neopixel_white_green: 'white to green',\n            ROBOID_neopixel_white_blue: 'white to blue',\n            ROBOID_neopixel_red_black: 'red getting darker',\n            ROBOID_neopixel_green_black: 'green getting darker',\n            ROBOID_neopixel_blue_black: 'blue getting darker',\n            ROBOID_neopixel_white_black: 'white getting darker',\n            ROBOID_neopixel_black_red: 'red getting brighter',\n            ROBOID_neopixel_black_green: 'green getting brighter',\n            ROBOID_neopixel_black_blue: 'blue getting brighter',\n            ROBOID_neopixel_black_white: 'white getting brighter',\n            ROBOID_serial_string: 'string',\n            ROBOID_serial_string_line: 'string line',\n            ROBOID_serial_all: 'all',\n            ROBOID_serial_until_comma: 'until ,(comma)',\n            ROBOID_serial_until_colon: 'until :(colon)',\n            ROBOID_serial_until_dollar: 'until $',\n            ROBOID_serial_until_sharp: 'until #',\n            ROBOID_serial_until_new_line: 'until new line',\n            ROBOID_serial_port_wa_rb: 'La(write) Lb(read)',\n            ROBOID_serial_port_ra_wb: 'La(read) Lb(write)',\n            ROBOID_serial_port_wa: 'La(write)',\n            ROBOID_serial_port_ra: 'La(read)',\n            ROBOID_pid_10: 'PID-10 ultrasonic sensor (HC-SR04+)',\n            ROBOID_pid_11_1: 'PID-11-1 humidity/temperature sensor (DHT11)',\n            ROBOID_pid_11_2: 'PID-11-2 humidity/temperature sensor (DHT21)',\n            ROBOID_pid_11_3: 'PID-11-3 humidity/temperature sensor (DHT22)',\n            ROBOID_pid_12: 'PID-12 temperature sensor (DS18B20)',\n            ROBOID_pid_13: 'PID-13 joystick and button',\n            ROBOID_pid_14: 'PID-14 dual joystick',\n            ROBOID_pid_15: 'PID-15 IR transceiver',\n            ROBOID_pid_16: 'PID-16 encoder',\n            ROBOID_pid_distance: 'distance (cm)',\n            ROBOID_pid_temperature: 'temperature (℃)',\n            ROBOID_pid_humidity: 'humidity (%RH)',\n            ROBOID_pid_x1: 'x1',\n            ROBOID_pid_y1: 'y1',\n            ROBOID_pid_x2: 'x2',\n            ROBOID_pid_y2: 'y2',\n            ROBOID_pid_button1: 'button1',\n            ROBOID_pid_button2: 'button2',\n            ROBOID_pid_encoder: 'encoder',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_shape_square: 'square',\n            ROBOID_shape_triangle: 'triangle',\n            ROBOID_shape_diamond: 'diamond',\n            ROBOID_shape_circle: 'circle',\n            ROBOID_shape_x: 'X',\n            ROBOID_shape_like: 'like',\n            ROBOID_shape_dislike: 'dislike',\n            ROBOID_shape_angry: 'angry',\n            ROBOID_shape_open_mouth: 'open mouth',\n            ROBOID_shape_close_mouth: 'close mouth',\n            ROBOID_shape_walk1: 'walk 1',\n            ROBOID_shape_walk2: 'walk 2',\n            ROBOID_shape_heart: 'heart',\n            ROBOID_shape_star: 'star',\n            ROBOID_shape_airplane: 'airplane',\n            ROBOID_shape_puppy: 'puppy',\n            ROBOID_shape_butterfly: 'butterfly',\n            ROBOID_shape_quarter_note: 'quarter note',\n            ROBOID_shape_eighth_note: 'eighth note',\n            ROBOID_shape_left_arrow: 'left arrow',\n            ROBOID_shape_right_arrow: 'right arrow',\n            ROBOID_shape_up_arrow: 'up arrow',\n            ROBOID_shape_down_arrow: 'down arrow',\n            ROBOID_hat_background: 'background',\n            ROBOID_hat_all: 'all',\n            ROBOID_hat_clear: 'clear',\n            ROBOID_hat_show: 'show',\n            ROBOID_hat_hide: 'hide',\n            ROBOID_hat_clockwise: 'clockwise',\n            ROBOID_hat_counterclockwise: 'counterclockwise',\n            ROBOID_hat_left_right: 'left-right',\n            ROBOID_hat_up_down: 'up-down',\n            ROBOID_hat_auto: 'auto',\n            ROBOID_hat_manual: 'manual',\n            ROBOID_hat_other_sprite: 'other sprite',\n            ROBOID_hat_left_wall: 'left wall',\n            ROBOID_hat_right_wall: 'right wall',\n            ROBOID_hat_top_wall: 'top wall',\n            ROBOID_hat_bottom_wall: 'bottom wall',\n            ROBOID_hat_any_wall: 'any wall',\n        },\n    },\n});\n\nEntry.Roboid.blockMenuBlocks = [\n    'roboid_hamster_hand_found',\n    'roboid_hamster_boolean',\n    'roboid_hamster_value',\n    'roboid_hamster_move_forward_once',\n    'roboid_hamster_turn_once',\n    'roboid_hamster_move_forward_for_secs',\n    'roboid_hamster_move_backward_for_secs',\n    'roboid_hamster_turn_for_secs',\n    'roboid_hamster_change_both_wheels_by',\n    'roboid_hamster_set_both_wheels_to',\n    'roboid_hamster_change_wheel_by',\n    'roboid_hamster_set_wheel_to',\n    'roboid_hamster_follow_line_using',\n    'roboid_hamster_follow_line_until',\n    'roboid_hamster_set_following_speed_to',\n    'roboid_hamster_stop',\n    'roboid_hamster_set_led_to',\n    'roboid_hamster_clear_led',\n    'roboid_hamster_beep',\n    'roboid_hamster_change_buzzer_by',\n    'roboid_hamster_set_buzzer_to',\n    'roboid_hamster_clear_buzzer',\n    'roboid_hamster_play_note',\n    'roboid_hamster_play_note_for',\n    'roboid_hamster_rest_for',\n    'roboid_hamster_change_tempo_by',\n    'roboid_hamster_set_tempo_to',\n    'roboid_hamster_set_port_to',\n    'roboid_hamster_change_output_by',\n    'roboid_hamster_set_output_to',\n    'roboid_hamster_gripper',\n    'roboid_hamster_release_gripper',\n    'roboid_hamster_s_hand_found',\n    'roboid_hamster_s_boolean',\n    'roboid_hamster_s_value',\n    'roboid_hamster_s_move_forward_once',\n    'roboid_hamster_s_turn_once',\n    'roboid_hamster_s_move_forward_unit',\n    'roboid_hamster_s_move_backward_unit',\n    'roboid_hamster_s_turn_unit_in_place',\n    'roboid_hamster_s_pivot_around_unit_in_direction',\n    'roboid_hamster_s_turn_unit_with_radius_in_direction',\n    'roboid_hamster_s_change_both_wheels_by',\n    'roboid_hamster_s_set_both_wheels_to',\n    'roboid_hamster_s_change_wheel_by',\n    'roboid_hamster_s_set_wheel_to',\n    'roboid_hamster_s_follow_line_using',\n    'roboid_hamster_s_follow_line_until',\n    'roboid_hamster_s_set_following_speed_to',\n    'roboid_hamster_s_set_following_gain_to',\n    'roboid_hamster_s_stop',\n    'roboid_hamster_s_set_led_to',\n    'roboid_hamster_s_pick_led',\n    'roboid_hamster_s_change_led_by_rgb',\n    'roboid_hamster_s_set_led_to_rgb',\n    'roboid_hamster_s_clear_led',\n    'roboid_hamster_s_play_sound_times',\n    'roboid_hamster_s_play_sound_times_until_done',\n    'roboid_hamster_s_change_buzzer_by',\n    'roboid_hamster_s_set_buzzer_to',\n    'roboid_hamster_s_clear_sound',\n    'roboid_hamster_s_play_note',\n    'roboid_hamster_s_play_note_for',\n    'roboid_hamster_s_rest_for',\n    'roboid_hamster_s_change_tempo_by',\n    'roboid_hamster_s_set_tempo_to',\n    'roboid_hamster_s_set_port_to',\n    'roboid_hamster_s_change_output_by',\n    'roboid_hamster_s_set_output_to',\n    'roboid_hamster_s_gripper',\n    'roboid_hamster_s_release_gripper',\n    'roboid_hamster_s_write_serial',\n    'roboid_hamster_s_read_serial_until',\n    'roboid_hamster_s_set_serial_rate_to',\n    'roboid_turtle_touching_color',\n    'roboid_turtle_is_color_pattern',\n    'roboid_turtle_button_state',\n    'roboid_turtle_boolean',\n    'roboid_turtle_value',\n    'roboid_turtle_move_forward_unit',\n    'roboid_turtle_move_backward_unit',\n    'roboid_turtle_turn_unit_in_place',\n    'roboid_turtle_pivot_around_wheel_unit_in_direction',\n    'roboid_turtle_turn_unit_with_radius_in_direction',\n    'roboid_turtle_change_wheels_by_left_right',\n    'roboid_turtle_set_wheels_to_left_right',\n    'roboid_turtle_change_wheel_by',\n    'roboid_turtle_set_wheel_to',\n    'roboid_turtle_follow_line',\n    'roboid_turtle_follow_line_until',\n    'roboid_turtle_follow_line_until_black',\n    'roboid_turtle_cross_intersection',\n    'roboid_turtle_turn_at_intersection',\n    'roboid_turtle_set_following_speed_to',\n    'roboid_turtle_stop',\n    'roboid_turtle_set_head_led_to',\n    'roboid_turtle_pick_head_led',\n    'roboid_turtle_change_head_led_by_rgb',\n    'roboid_turtle_set_head_led_to_rgb',\n    'roboid_turtle_clear_head_led',\n    'roboid_turtle_play_sound_times',\n    'roboid_turtle_play_sound_times_until_done',\n    'roboid_turtle_change_buzzer_by',\n    'roboid_turtle_set_buzzer_to',\n    'roboid_turtle_clear_sound',\n    'roboid_turtle_play_note',\n    'roboid_turtle_play_note_for_beats',\n    'roboid_turtle_rest_for_beats',\n    'roboid_turtle_change_tempo_by',\n    'roboid_turtle_set_tempo_to',\n    'roboid_cheese_value',\n    'roboid_cheese_boolean',\n    'roboid_cheese_play_sound_times',\n    'roboid_cheese_play_sound_times_until_done',\n    'roboid_cheese_change_buzzer_by',\n    'roboid_cheese_set_buzzer_to',\n    'roboid_cheese_clear_sound',\n    'roboid_cheese_play_note',\n    'roboid_cheese_play_note_for',\n    'roboid_cheese_rest_for',\n    'roboid_cheese_change_tempo_by',\n    'roboid_cheese_set_tempo_to',\n    'roboid_cheese_set_sound_port_to',\n    'roboid_cheese_set_input_mode_to',\n    'roboid_cheese_set_input_range_to',\n    'roboid_cheese_set_three_input_ranges_to',\n    'roboid_cheese_analog_input',\n    'roboid_cheese_digital_input',\n    'roboid_cheese_button_state',\n    'roboid_cheese_set_pulse_mode_to',\n    'roboid_cheese_pulse_input',\n    'roboid_cheese_set_digital_output_to',\n    'roboid_cheese_change_pwm_output_by',\n    'roboid_cheese_set_pwm_output_to',\n    'roboid_cheese_change_servo_motor_angle_by',\n    'roboid_cheese_set_servo_motor_angle_to',\n    'roboid_cheese_turn_off_servo_motor',\n    'roboid_cheese_change_dc_motor_velocity_by',\n    'roboid_cheese_set_dc_motor_velocity_to',\n    'roboid_cheese_stop_dc_motor',\n    'roboid_cheese_rotate_step_motor',\n    'roboid_cheese_change_step_motor_velocity_by',\n    'roboid_cheese_set_step_motor_velocity_to',\n    'roboid_cheese_stop_off_step_motor',\n    'roboid_cheese_set_step_motor_mode_to',\n    'roboid_cheese_step_count',\n    'roboid_cheese_set_led_to_color',\n    'roboid_cheese_pick_led_to',\n    'roboid_cheese_change_led_by_rgb',\n    'roboid_cheese_setLed_to_rgb',\n    'roboid_cheese_clear_led',\n    'roboid_cheese_set_led_type_to',\n    'roboid_cheese_neopixel_set_number_and_type_to',\n    'roboid_cheese_neopixel_set_all_leds_to_pattern',\n    'roboid_cheese_neopixel_set_all_leds_to_color',\n    'roboid_cheese_neopixel_pick_all_leds_to',\n    'roboid_cheese_neopixel_change_all_leds_by_rgb',\n    'roboid_cheese_neopixel_set_all_leds_to_rgb',\n    'roboid_cheese_neopixel_clear_all_leds',\n    'roboid_cheese_neopixel_set_led_to_color',\n    'roboid_cheese_neopixel_pick_led_to',\n    'roboid_cheese_neopixel_change_led_by_rgb',\n    'roboid_cheese_neopixel_set_led_to_rgb',\n    'roboid_cheese_neopixel_clear_led',\n    'roboid_cheese_neopixel_set_led_range_to_pattern',\n    'roboid_cheese_neopixel_set_led_range_to_color',\n    'roboid_cheese_neopixel_pick_led_range_to',\n    'roboid_cheese_neopixel_change_led_range_by_rgb',\n    'roboid_cheese_neopixel_set_led_range_to_rgb',\n    'roboid_cheese_neopixel_clear_led_range',\n    'roboid_cheese_neopixel_shift',\n    'roboid_cheese_neopixel_rotate',\n    'roboid_cheese_neopixel_change_brightness_by',\n    'roboid_cheese_neopixel_set_brightness_to',\n    'roboid_cheese_write_serial',\n    'roboid_cheese_read_serial_until',\n    'roboid_cheese_set_serial_port_to',\n    'roboid_cheese_set_serial_rate_to',\n    'roboid_cheese_serial_input',\n    'roboid_cheese_pid_start',\n    'roboid_cheese_pid_set_range_to',\n    'roboid_cheese_pid_set_three_ranges_to',\n    'roboid_cheese_pid_reset_encoder',\n    'roboid_cheese_pid_input',\n    'roboid_cheese_pid_button_state',\n    'roboid_cheese_hat010_start',\n    'roboid_cheese_hat010_button',\n    'roboid_cheese_hat010_button_state',\n    'roboid_cheese_hat010_background_turn_on_xy',\n    'roboid_cheese_hat010_background_turn_off_xy',\n    'roboid_cheese_hat010_background_draw_shape_at_xy',\n    'roboid_cheese_hat010_background_draw_string_at_xy',\n    'roboid_cheese_hat010_background_draw_pattern_at_xy',\n    'roboid_cheese_hat010_clear',\n    'roboid_cheese_hat010_scroll_by_xy',\n    'roboid_cheese_hat010_sprite_set_to_shape',\n    'roboid_cheese_hat010_sprite_set_to_string',\n    'roboid_cheese_hat010_sprite_set_to_pattern',\n    'roboid_cheese_hat010_sprite_clear_show_hide',\n    'roboid_cheese_hat010_sprite_change_positions_by_xy',\n    'roboid_cheese_hat010_sprite_set_positions_to_xy',\n    'roboid_cheese_hat010_sprite_change_position_by_value',\n    'roboid_cheese_hat010_sprite_set_position_to_value',\n    'roboid_cheese_hat010_sprite_rotate',\n    'roboid_cheese_hat010_sprite_flip_in_direction',\n    'roboid_cheese_hat010_sprite_stamp_to_background',\n    'roboid_cheese_hat010_sprite_position',\n    'roboid_cheese_hat010_sprite_touching_sprite',\n    'roboid_cheese_hat010_sprite_touching',\n    'roboid_cheese_hat010_change_brightness_by',\n    'roboid_cheese_hat010_set_brightness_to',\n];\n\nEntry.Roboid.getBlocks = function() {\n    return {\n        roboid_hamster_hand_found: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'roboid_hamster_hand_found',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.checkHandFound(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_hand_found(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.hamster_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.hamster_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.hamster_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.hamster_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.hamster_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.hamster_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.hamster_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.hamster_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_boolean',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'hamster_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_boolean_value(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.hamster_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.hamster_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.hamster_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.hamster_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.hamster_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.hamster_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.hamster_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.hamster_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_sensor_left_proximity, 'leftProximity'],\n                        [Lang.Blocks.HAMSTER_sensor_right_proximity, 'rightProximity'],\n                        [Lang.Blocks.HAMSTER_sensor_left_floor, 'leftFloor'],\n                        [Lang.Blocks.HAMSTER_sensor_right_floor, 'rightFloor'],\n                        [Lang.Blocks.HAMSTER_sensor_acceleration_x, 'accelerationX'],\n                        [Lang.Blocks.HAMSTER_sensor_acceleration_y, 'accelerationY'],\n                        [Lang.Blocks.HAMSTER_sensor_acceleration_z, 'accelerationZ'],\n                        [Lang.Blocks.HAMSTER_sensor_light, 'light'],\n                        [Lang.Blocks.HAMSTER_sensor_temperature, 'temperature'],\n                        [Lang.Blocks.HAMSTER_sensor_signal_strength, 'signalStrength'],\n                        [Lang.Blocks.HAMSTER_sensor_input_a, 'inputA'],\n                        [Lang.Blocks.HAMSTER_sensor_input_b, 'inputB'],\n                    ],\n                    value: 'leftProximity',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_value',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'hamster_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_sensor_value(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_sensor_left_proximity, 'leftProximity'],\n                                    [Lang.Blocks.HAMSTER_sensor_right_proximity, 'rightProximity'],\n                                    [Lang.Blocks.HAMSTER_sensor_left_floor, 'leftFloor'],\n                                    [Lang.Blocks.HAMSTER_sensor_right_floor, 'rightFloor'],\n                                    [Lang.Blocks.HAMSTER_sensor_acceleration_x, 'accelerationX'],\n                                    [Lang.Blocks.HAMSTER_sensor_acceleration_y, 'accelerationY'],\n                                    [Lang.Blocks.HAMSTER_sensor_acceleration_z, 'accelerationZ'],\n                                    [Lang.Blocks.HAMSTER_sensor_light, 'light'],\n                                    [Lang.Blocks.HAMSTER_sensor_temperature, 'temperature'],\n                                    [Lang.Blocks.HAMSTER_sensor_signal_strength, 'signalStrength'],\n                                    [Lang.Blocks.HAMSTER_sensor_input_a, 'inputA'],\n                                    [Lang.Blocks.HAMSTER_sensor_input_b, 'inputB'],\n                                ],\n                                value: 'leftProximity',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_move_forward_once: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_move_forward_once',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_board',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.boardForward(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_board_forward(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_turn_once: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_turn_once_left, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_turn_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_turn_once',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIRECTION: 1,\n            },\n            class: 'hamster_board',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.boardTurn(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_board_turn(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_turn_once_left, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_turn_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_move_forward_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_move_forward_for_secs',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SECS: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.moveForwardSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_move_forward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_move_backward_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_move_backward_for_secs',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SECS: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.moveBackwardSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_move_backward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_turn_for_secs: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_turn_once_left, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_turn_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_turn_for_secs',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIRECTION: 1,\n                SECS: 2,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.turnSecs(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_turn_once_left, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_turn_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_change_both_wheels_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_change_both_wheels_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LEFT: 1,\n                RIGHT: 2,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_add_wheels(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_set_both_wheels_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_set_both_wheels_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LEFT: 1,\n                RIGHT: 2,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_wheels(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_wheel, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_wheel, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_wheels, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_change_wheel_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                WHEEL: 1,\n                VELOCITY: 2,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_add_wheel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_wheel, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_wheel, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_wheels, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_wheel, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_wheel, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_wheels, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_set_wheel_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                WHEEL: 1,\n                VELOCITY: 2,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_wheel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_wheel, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_wheel, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_wheels, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_follow_line_using: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_color_black, 'BLACK'],\n                        [Lang.Blocks.HAMSTER_color_white, 'WHITE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_floor_sensor, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_floor_sensor, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_floor_sensors, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_follow_line_using',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n                SENSOR: 2,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_follow_line(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_black, 'BLACK'],\n                                    [Lang.Blocks.HAMSTER_color_white, 'WHITE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_floor_sensor, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_floor_sensor, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_floor_sensors, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_color_black, 'BLACK'],\n                        [Lang.Blocks.HAMSTER_color_white, 'WHITE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_floor_sensor, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_floor_sensor, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_front, 'FRONT'],\n                        [Lang.Blocks.HAMSTER_rear, 'REAR'],\n                    ],\n                    value: 'FRONT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_follow_line_until',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n                DIRECTION: 2,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_follow_line_until(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_black, 'BLACK'],\n                                    [Lang.Blocks.HAMSTER_color_white, 'WHITE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_floor_sensor, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_floor_sensor, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_front, 'FRONT'],\n                                    [Lang.Blocks.HAMSTER_rear, 'REAR'],\n                                ],\n                                value: 'FRONT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    '5',\n                    null,\n                ],\n                type: 'roboid_hamster_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPEED: 1,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_line_speed(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_stop',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_stop(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_set_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_color_red, '4'],\n                        [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                        [Lang.Blocks.HAMSTER_color_green, '2'],\n                        [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                        [Lang.Blocks.HAMSTER_color_blue, '1'],\n                        [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                        [Lang.Blocks.HAMSTER_color_white, '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_set_led_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LED: 1,\n                COLOR: 2,\n            },\n            class: 'hamster_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.setLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_led_red(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '4'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_led_yellow(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '6'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_led_green(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '2'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_led_sky_blue(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '3'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_led_blue(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '1'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_led_purple(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '5'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_led_white(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_color_red, '4'],\n                                    [Lang.Blocks.HAMSTER_color_yellow, '6'],\n                                    [Lang.Blocks.HAMSTER_color_green, '2'],\n                                    [Lang.Blocks.HAMSTER_color_cyan, '3'],\n                                    [Lang.Blocks.HAMSTER_color_blue, '1'],\n                                    [Lang.Blocks.HAMSTER_color_magenta, '5'],\n                                    [Lang.Blocks.HAMSTER_color_white, '7'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '7'],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                        [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                        [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_clear_led',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LED: 1,\n            },\n            class: 'hamster_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_clear_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_left_led, 'LEFT'],\n                                    [Lang.Blocks.HAMSTER_right_led, 'RIGHT'],\n                                    [Lang.Blocks.HAMSTER_both_leds, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_beep: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_beep',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.beep(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_beep(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                HZ: 1,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_add_buzzer(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                HZ: 1,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_buzzer(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_clear_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_clear_buzzer',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.clearBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_clear_buzzer(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_note_c, '4'],\n                        [Lang.Blocks.hamster_note_c_sharp, '5'],\n                        [Lang.Blocks.hamster_note_d, '6'],\n                        [Lang.Blocks.hamster_note_d_sharp, '7'],\n                        [Lang.Blocks.hamster_note_e, '8'],\n                        [Lang.Blocks.hamster_note_f, '9'],\n                        [Lang.Blocks.hamster_note_f_sharp, '10'],\n                        [Lang.Blocks.hamster_note_g, '11'],\n                        [Lang.Blocks.hamster_note_g_sharp, '12'],\n                        [Lang.Blocks.hamster_note_a, '13'],\n                        [Lang.Blocks.hamster_note_a_sharp, '14'],\n                        [Lang.Blocks.hamster_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    '4',\n                    null,\n                ],\n                type: 'roboid_hamster_play_note',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_c(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '4'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_c_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '5'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_d(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '6'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_d_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '7'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_e(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '8'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_f(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '9'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_f_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '10'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_g(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '11'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_g_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '12'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_a(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '13'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_a_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '14'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_pitch_b(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '15'],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_note_c, '4'],\n                        [Lang.Blocks.hamster_note_c_sharp, '5'],\n                        [Lang.Blocks.hamster_note_d, '6'],\n                        [Lang.Blocks.hamster_note_d_sharp, '7'],\n                        [Lang.Blocks.hamster_note_e, '8'],\n                        [Lang.Blocks.hamster_note_f, '9'],\n                        [Lang.Blocks.hamster_note_f_sharp, '10'],\n                        [Lang.Blocks.hamster_note_g, '11'],\n                        [Lang.Blocks.hamster_note_g_sharp, '12'],\n                        [Lang.Blocks.hamster_note_a, '13'],\n                        [Lang.Blocks.hamster_note_a_sharp, '14'],\n                        [Lang.Blocks.hamster_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_play_note_for',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                BEAT: 3,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_play_note_c(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '4'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_c_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '5'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_d(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '6'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_d_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '7'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_e(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '8'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_f(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '9'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_f_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '10'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_g(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '11'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_g_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '12'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_a(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '13'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_a_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '14'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_play_note_b(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_note_c, '4'],\n                                    [Lang.Blocks.hamster_note_c_sharp, '5'],\n                                    [Lang.Blocks.hamster_note_d, '6'],\n                                    [Lang.Blocks.hamster_note_d_sharp, '7'],\n                                    [Lang.Blocks.hamster_note_e, '8'],\n                                    [Lang.Blocks.hamster_note_f, '9'],\n                                    [Lang.Blocks.hamster_note_f_sharp, '10'],\n                                    [Lang.Blocks.hamster_note_g, '11'],\n                                    [Lang.Blocks.hamster_note_g_sharp, '12'],\n                                    [Lang.Blocks.hamster_note_a, '13'],\n                                    [Lang.Blocks.hamster_note_a_sharp, '14'],\n                                    [Lang.Blocks.hamster_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '15'],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_rest_for',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BEAT: 1,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_rest(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_change_tempo_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BPM: 1,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_add_tempo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_set_tempo_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BPM: 1,\n            },\n            class: 'hamster_buzzer',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_tempo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_set_port_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_port_a, 'A'],\n                        [Lang.Blocks.HAMSTER_port_b, 'B'],\n                        [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_analog_input, '0'],\n                        [Lang.Blocks.HAMSTER_digital_input, '1'],\n                        [Lang.Blocks.HAMSTER_servo_output, '8'],\n                        [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                        [Lang.Blocks.HAMSTER_digital_output, '10'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_set_port_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                MODE: 2,\n            },\n            class: 'hamster_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.setIoMode(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_io_mode_analog_input(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '0'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_io_mode_digital_input(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '1'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_io_mode_servo_output(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '8'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_io_mode_pwm_output(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '9'],\n                    },\n                    {\n                        syntax: 'Roboid.hamster_set_io_mode_digital_output(%1, %2)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_analog_input, '0'],\n                                    [Lang.Blocks.HAMSTER_digital_input, '1'],\n                                    [Lang.Blocks.HAMSTER_servo_output, '8'],\n                                    [Lang.Blocks.HAMSTER_pwm_output, '9'],\n                                    [Lang.Blocks.HAMSTER_digital_output, '10'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, null, '10'],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_change_output_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_port_a, 'A'],\n                        [Lang.Blocks.HAMSTER_port_b, 'B'],\n                        [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_change_output_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'hamster_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.changeOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_add_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_set_output_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HAMSTER_port_a, 'A'],\n                        [Lang.Blocks.HAMSTER_port_b, 'B'],\n                        [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_set_output_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'hamster_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.setOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.HAMSTER_port_a, 'A'],\n                                    [Lang.Blocks.HAMSTER_port_b, 'B'],\n                                    [Lang.Blocks.HAMSTER_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_gripper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_open_gripper, 'OPEN'],\n                        [Lang.Blocks.hamster_close_gripper, 'CLOSE'],\n                    ],\n                    value: 'OPEN',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_gripper',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                ACTION: 1,\n            },\n            class: 'hamster_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.gripper(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_set_gripper(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_open_gripper, 'OPEN'],\n                                    [Lang.Blocks.hamster_close_gripper, 'CLOSE'],\n                                ],\n                                value: 'OPEN',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_release_gripper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_release_gripper',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamster(index);\n                return robot ? robot.releaseGripper(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_release_gripper(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_hand_found: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'roboid_hamster_s_hand_found',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_s_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.checkHandFound(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_hand_found(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.hamster_s_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.hamster_s_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.hamster_s_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.hamster_s_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.hamster_s_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.hamster_s_tap, 'TAP'],\n                        [Lang.Blocks.hamster_s_free_fall, 'FREE_FALL'],\n                        [Lang.Blocks.hamster_s_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.hamster_s_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.hamster_s_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_boolean',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'hamster_s_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_boolean_value(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.hamster_s_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.hamster_s_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.hamster_s_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.hamster_s_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.hamster_s_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.hamster_s_tap, 'TAP'],\n                                    [Lang.Blocks.hamster_s_free_fall, 'FREE_FALL'],\n                                    [Lang.Blocks.hamster_s_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.hamster_s_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.hamster_s_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                        [Lang.Blocks.hamster_s_sensor_right_proximity, 'RIGHT_PROXIMITY'],\n                        [Lang.Blocks.hamster_s_sensor_left_floor, 'LEFT_FLOOR'],\n                        [Lang.Blocks.hamster_s_sensor_right_floor, 'RIGHT_FLOOR'],\n                        [Lang.Blocks.hamster_s_sensor_acceleration_x, 'ACCELERATION_X'],\n                        [Lang.Blocks.hamster_s_sensor_acceleration_y, 'ACCELERATION_Y'],\n                        [Lang.Blocks.hamster_s_sensor_acceleration_z, 'ACCELERATION_Z'],\n                        [Lang.Blocks.hamster_s_sensor_light, 'LIGHT'],\n                        [Lang.Blocks.hamster_s_sensor_temperature, 'TEMPERATURE'],\n                        [Lang.Blocks.hamster_s_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                        [Lang.Blocks.hamster_s_sensor_input_a, 'INPUT_A'],\n                        [Lang.Blocks.hamster_s_sensor_input_b, 'INPUT_B'],\n                        [Lang.Blocks.hamster_s_serial_input, 'SERIAL_INPUT'],\n                    ],\n                    value: 'LEFT_PROXIMITY',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_value',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'hamster_s_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_sensor_value(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                                    [\n                                        Lang.Blocks.hamster_s_sensor_right_proximity,\n                                        'RIGHT_PROXIMITY',\n                                    ],\n                                    [Lang.Blocks.hamster_s_sensor_left_floor, 'LEFT_FLOOR'],\n                                    [Lang.Blocks.hamster_s_sensor_right_floor, 'RIGHT_FLOOR'],\n                                    [Lang.Blocks.hamster_s_sensor_acceleration_x, 'ACCELERATION_X'],\n                                    [Lang.Blocks.hamster_s_sensor_acceleration_y, 'ACCELERATION_Y'],\n                                    [Lang.Blocks.hamster_s_sensor_acceleration_z, 'ACCELERATION_Z'],\n                                    [Lang.Blocks.hamster_s_sensor_light, 'LIGHT'],\n                                    [Lang.Blocks.hamster_s_sensor_temperature, 'TEMPERATURE'],\n                                    [\n                                        Lang.Blocks.hamster_s_sensor_signal_strength,\n                                        'SIGNAL_STRENGTH',\n                                    ],\n                                    [Lang.Blocks.hamster_s_sensor_input_a, 'INPUT_A'],\n                                    [Lang.Blocks.hamster_s_sensor_input_b, 'INPUT_B'],\n                                    [Lang.Blocks.hamster_s_serial_input, 'SERIAL_INPUT'],\n                                ],\n                                value: 'LEFT_PROXIMITY',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_move_forward_once: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_move_forward_once',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_s_board',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.boardForward(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_board_forward(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_turn_once: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_turn_once',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIRECTION: 1,\n            },\n            class: 'hamster_s_board',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.boardTurn(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_board_turn(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_cm, 'CM'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_move_forward_unit',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_move_forward(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_cm, 'CM'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_cm, 'CM'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_move_backward_unit',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_move_backward(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_cm, 'CM'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n                UNIT: 3,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_turn(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_pivot_around_unit_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left_pen, 'LEFT_PEN'],\n                        [Lang.Blocks.hamster_s_right_pen, 'RIGHT_PEN'],\n                        [Lang.Blocks.hamster_s_left_wheel, 'LEFT_WHEEL'],\n                        [Lang.Blocks.hamster_s_right_wheel, 'RIGHT_WHEEL'],\n                    ],\n                    value: 'LEFT_PEN',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_forward, 'FORWARD'],\n                        [Lang.Blocks.hamster_s_backward, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_pivot_around_unit_in_direction',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PART: 1,\n                VALUE: 2,\n                UNIT: 3,\n                TOWARD: 4,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.pivotUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_pivot(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left_pen, 'LEFT_PEN'],\n                                    [Lang.Blocks.hamster_s_right_pen, 'RIGHT_PEN'],\n                                    [Lang.Blocks.hamster_s_left_wheel, 'LEFT_WHEEL'],\n                                    [Lang.Blocks.hamster_s_right_wheel, 'RIGHT_WHEEL'],\n                                ],\n                                value: 'LEFT_PEN',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_forward, 'FORWARD'],\n                                    [Lang.Blocks.hamster_s_backward, 'BACKWARD'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_turn_unit_with_radius_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left_pen, 'LEFT_PEN'],\n                        [Lang.Blocks.hamster_s_right_pen, 'RIGHT_PEN'],\n                        [Lang.Blocks.hamster_s_robot, 'ROBOT'],\n                    ],\n                    value: 'LEFT_PEN',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                        [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                        [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_forward, 'FORWARD'],\n                        [Lang.Blocks.hamster_s_backward, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_turn_unit_with_radius_in_direction',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PART: 1,\n                DIRECTION: 2,\n                VALUE: 3,\n                UNIT: 4,\n                RADIUS: 5,\n                TOWARD: 6,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.swingUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_circle(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left_pen, 'LEFT_PEN'],\n                                    [Lang.Blocks.hamster_s_right_pen, 'RIGHT_PEN'],\n                                    [Lang.Blocks.hamster_s_robot, 'ROBOT'],\n                                ],\n                                value: 'LEFT_PEN',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_unit_deg, 'DEG'],\n                                    [Lang.Blocks.hamster_s_unit_sec, 'SEC'],\n                                    [Lang.Blocks.hamster_s_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_forward, 'FORWARD'],\n                                    [Lang.Blocks.hamster_s_backward, 'BACKWARD'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_change_both_wheels_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_change_both_wheels_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LEFT: 1,\n                RIGHT: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_add_wheels(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_both_wheels_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_both_wheels_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LEFT: 1,\n                RIGHT: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_wheels(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_change_wheel_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                WHEEL: 1,\n                VELOCITY: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_add_wheel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['30'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_wheel_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                WHEEL: 1,\n                VELOCITY: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_wheel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_follow_line_using: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_color_black, 'BLACK'],\n                        [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_follow_line_using',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n                SENSOR: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_follow_line(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_color_black, 'BLACK'],\n                                    [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_color_black, 'BLACK'],\n                        [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_front, 'FRONT'],\n                        [Lang.Blocks.hamster_s_rear, 'REAR'],\n                    ],\n                    value: 'FRONT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_follow_line_until',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n                DIRECTION: 2,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_follow_line_until(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_color_black, 'BLACK'],\n                                    [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_front, 'FRONT'],\n                                    [Lang.Blocks.hamster_s_rear, 'REAR'],\n                                ],\n                                value: 'FRONT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    '5',\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPEED: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_line_speed(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_following_gain_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_gain_default, 'DEFAULT'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: 'DEFAULT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_following_gain_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                GAIN: 1,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setLineTracerGain(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_line_gain(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_gain_default, 'DEFAULT'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: 'DEFAULT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_stop',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_s_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_stop(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_color_red, 'RED'],\n                        [Lang.Blocks.hamster_s_color_orange, 'ORANGE'],\n                        [Lang.Blocks.hamster_s_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.hamster_s_color_green, 'GREEN'],\n                        [Lang.Blocks.hamster_s_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.hamster_s_color_blue, 'BLUE'],\n                        [Lang.Blocks.hamster_s_color_violet, 'VIOLET'],\n                        [Lang.Blocks.hamster_s_color_purple, 'PURPLE'],\n                        [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_led_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LED: 1,\n                COLOR: 2,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_led(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_color_red, 'RED'],\n                                    [Lang.Blocks.hamster_s_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.hamster_s_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.hamster_s_color_green, 'GREEN'],\n                                    [Lang.Blocks.hamster_s_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.hamster_s_color_blue, 'BLUE'],\n                                    [Lang.Blocks.hamster_s_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.hamster_s_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.hamster_s_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_pick_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_pick_led',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LED: 1,\n                COLOR: 2,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.pickLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_pick_led(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LED: 1,\n                RED: 2,\n                GREEN: 3,\n                BLUE: 4,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.changeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_add_rgb(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_led_to_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LED: 1,\n                RED: 2,\n                GREEN: 3,\n                BLUE: 4,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_rgb(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_left, 'LEFT'],\n                        [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                        [Lang.Blocks.hamster_s_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_clear_led',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LED: 1,\n            },\n            class: 'hamster_s_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_clear_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_left, 'LEFT'],\n                                    [Lang.Blocks.hamster_s_right, 'RIGHT'],\n                                    [Lang.Blocks.hamster_s_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_sound_beep, 'BEEP'],\n                        [Lang.Blocks.hamster_s_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.hamster_s_sound_noise, 'NOISE'],\n                        [Lang.Blocks.hamster_s_sound_siren, 'SIREN'],\n                        [Lang.Blocks.hamster_s_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.hamster_s_sound_chop, 'CHOP'],\n                        [Lang.Blocks.hamster_s_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.hamster_s_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.hamster_s_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.hamster_s_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.hamster_s_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.hamster_s_sound_sad, 'SAD'],\n                        [Lang.Blocks.hamster_s_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.hamster_s_sound_march, 'MARCH'],\n                        [Lang.Blocks.hamster_s_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_play_sound_times',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SOUND: 1,\n                COUNT: 2,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_play_sound(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.hamster_s_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.hamster_s_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.hamster_s_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.hamster_s_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.hamster_s_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.hamster_s_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.hamster_s_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.hamster_s_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.hamster_s_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.hamster_s_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.hamster_s_sound_sad, 'SAD'],\n                                    [Lang.Blocks.hamster_s_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.hamster_s_sound_march, 'MARCH'],\n                                    [Lang.Blocks.hamster_s_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_sound_beep, 'BEEP'],\n                        [Lang.Blocks.hamster_s_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.hamster_s_sound_noise, 'NOISE'],\n                        [Lang.Blocks.hamster_s_sound_siren, 'SIREN'],\n                        [Lang.Blocks.hamster_s_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.hamster_s_sound_chop, 'CHOP'],\n                        [Lang.Blocks.hamster_s_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.hamster_s_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.hamster_s_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.hamster_s_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.hamster_s_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.hamster_s_sound_sad, 'SAD'],\n                        [Lang.Blocks.hamster_s_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.hamster_s_sound_march, 'MARCH'],\n                        [Lang.Blocks.hamster_s_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SOUND: 1,\n                COUNT: 2,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_play_sound_until_done(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.hamster_s_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.hamster_s_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.hamster_s_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.hamster_s_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.hamster_s_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.hamster_s_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.hamster_s_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.hamster_s_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.hamster_s_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.hamster_s_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.hamster_s_sound_sad, 'SAD'],\n                                    [Lang.Blocks.hamster_s_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.hamster_s_sound_march, 'MARCH'],\n                                    [Lang.Blocks.hamster_s_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                HZ: 1,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_add_buzzer(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                HZ: 1,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_buzzer(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_clear_sound',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_clear_sound(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_note_c, 'C'],\n                        [Lang.Blocks.hamster_s_note_c_sharp, 'C#'],\n                        [Lang.Blocks.hamster_s_note_d, 'D'],\n                        [Lang.Blocks.hamster_s_note_d_sharp, 'D#'],\n                        [Lang.Blocks.hamster_s_note_e, 'E'],\n                        [Lang.Blocks.hamster_s_note_f, 'F'],\n                        [Lang.Blocks.hamster_s_note_f_sharp, 'F#'],\n                        [Lang.Blocks.hamster_s_note_g, 'G'],\n                        [Lang.Blocks.hamster_s_note_g_sharp, 'G#'],\n                        [Lang.Blocks.hamster_s_note_a, 'A'],\n                        [Lang.Blocks.hamster_s_note_a_sharp, 'A#'],\n                        [Lang.Blocks.hamster_s_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    '4',\n                    null,\n                ],\n                type: 'roboid_hamster_s_play_note',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_play_pitch(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_note_c, 'C'],\n                                    [Lang.Blocks.hamster_s_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.hamster_s_note_d, 'D'],\n                                    [Lang.Blocks.hamster_s_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.hamster_s_note_e, 'E'],\n                                    [Lang.Blocks.hamster_s_note_f, 'F'],\n                                    [Lang.Blocks.hamster_s_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.hamster_s_note_g, 'G'],\n                                    [Lang.Blocks.hamster_s_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.hamster_s_note_a, 'A'],\n                                    [Lang.Blocks.hamster_s_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.hamster_s_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_note_c, 'C'],\n                        [Lang.Blocks.hamster_s_note_c_sharp, 'C#'],\n                        [Lang.Blocks.hamster_s_note_d, 'D'],\n                        [Lang.Blocks.hamster_s_note_d_sharp, 'D#'],\n                        [Lang.Blocks.hamster_s_note_e, 'E'],\n                        [Lang.Blocks.hamster_s_note_f, 'F'],\n                        [Lang.Blocks.hamster_s_note_f_sharp, 'F#'],\n                        [Lang.Blocks.hamster_s_note_g, 'G'],\n                        [Lang.Blocks.hamster_s_note_g_sharp, 'G#'],\n                        [Lang.Blocks.hamster_s_note_a, 'A'],\n                        [Lang.Blocks.hamster_s_note_a_sharp, 'A#'],\n                        [Lang.Blocks.hamster_s_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_play_note_for',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                BEAT: 3,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_play_note(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_note_c, 'C'],\n                                    [Lang.Blocks.hamster_s_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.hamster_s_note_d, 'D'],\n                                    [Lang.Blocks.hamster_s_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.hamster_s_note_e, 'E'],\n                                    [Lang.Blocks.hamster_s_note_f, 'F'],\n                                    [Lang.Blocks.hamster_s_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.hamster_s_note_g, 'G'],\n                                    [Lang.Blocks.hamster_s_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.hamster_s_note_a, 'A'],\n                                    [Lang.Blocks.hamster_s_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.hamster_s_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_rest_for',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BEAT: 1,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_rest(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_change_tempo_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BPM: 1,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_add_tempo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_tempo_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BPM: 1,\n            },\n            class: 'hamster_s_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_tempo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_port_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_port_a, 'A'],\n                        [Lang.Blocks.hamster_s_port_b, 'B'],\n                        [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_analog_input, 'ANALOG_INPUT'],\n                        [Lang.Blocks.hamster_s_digital_input, 'DIGITAL_INPUT'],\n                        [Lang.Blocks.hamster_s_digital_input_pull_up, 'DIGITAL_INPUT_PULL_UP'],\n                        [Lang.Blocks.hamster_s_digital_input_pull_down, 'DIGITAL_INPUT_PULL_DOWN'],\n                        [Lang.Blocks.hamster_s_voltage_input, 'VOLTAGE_INPUT'],\n                        [Lang.Blocks.hamster_s_servo_output, 'SERVO_OUTPUT'],\n                        [Lang.Blocks.hamster_s_pwm_output, 'PWM_OUTPUT'],\n                        [Lang.Blocks.hamster_s_digital_output, 'DIGITAL_OUTPUT'],\n                    ],\n                    value: 'ANALOG_INPUT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_port_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                MODE: 2,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setIoMode(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_io_mode(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_port_a, 'A'],\n                                    [Lang.Blocks.hamster_s_port_b, 'B'],\n                                    [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_analog_input, 'ANALOG_INPUT'],\n                                    [Lang.Blocks.hamster_s_digital_input, 'DIGITAL_INPUT'],\n                                    [\n                                        Lang.Blocks.hamster_s_digital_input_pull_up,\n                                        'DIGITAL_INPUT_PULL_UP',\n                                    ],\n                                    [\n                                        Lang.Blocks.hamster_s_digital_input_pull_down,\n                                        'DIGITAL_INPUT_PULL_DOWN',\n                                    ],\n                                    [Lang.Blocks.hamster_s_voltage_input, 'VOLTAGE_INPUT'],\n                                    [Lang.Blocks.hamster_s_servo_output, 'SERVO_OUTPUT'],\n                                    [Lang.Blocks.hamster_s_pwm_output, 'PWM_OUTPUT'],\n                                    [Lang.Blocks.hamster_s_digital_output, 'DIGITAL_OUTPUT'],\n                                ],\n                                value: 'ANALOG_INPUT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_change_output_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_port_a, 'A'],\n                        [Lang.Blocks.hamster_s_port_b, 'B'],\n                        [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_change_output_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.changeOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_add_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_port_a, 'A'],\n                                    [Lang.Blocks.hamster_s_port_b, 'B'],\n                                    [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_output_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_port_a, 'A'],\n                        [Lang.Blocks.hamster_s_port_b, 'B'],\n                        [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_output_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_port_a, 'A'],\n                                    [Lang.Blocks.hamster_s_port_b, 'B'],\n                                    [Lang.Blocks.hamster_s_port_ab, 'AB'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_gripper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_open_gripper, 'OPEN'],\n                        [Lang.Blocks.hamster_s_close_gripper, 'CLOSE'],\n                    ],\n                    value: 'OPEN',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_gripper',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                ACTION: 1,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.gripper(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_gripper(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_open_gripper, 'OPEN'],\n                                    [Lang.Blocks.hamster_s_close_gripper, 'CLOSE'],\n                                ],\n                                value: 'OPEN',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_release_gripper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_release_gripper',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.releaseGripper(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_release_gripper(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_write_serial: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_serial_string, 'STRING'],\n                        [Lang.Blocks.hamster_s_serial_string_line, 'STRING_LINE'],\n                    ],\n                    value: 'STRING',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['abc123'],\n                    },\n                    null,\n                ],\n                type: 'roboid_hamster_s_write_serial',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                MODE: 1,\n                STRING: 2,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.writeSerial(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_write_serial(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_serial_string, 'STRING'],\n                                    [Lang.Blocks.hamster_s_serial_string_line, 'STRING_LINE'],\n                                ],\n                                value: 'STRING',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_read_serial_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.hamster_s_serial_all, 'ALL'],\n                        [Lang.Blocks.hamster_s_serial_until_comma, 'COMMA'],\n                        [Lang.Blocks.hamster_s_serial_until_colon, 'COLON'],\n                        [Lang.Blocks.hamster_s_serial_until_dollar, 'DOLLAR'],\n                        [Lang.Blocks.hamster_s_serial_until_sharp, 'SHARP'],\n                        [Lang.Blocks.hamster_s_serial_until_new_line, 'NEW_LINE'],\n                    ],\n                    value: 'ALL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_read_serial_until',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DELIMITER: 1,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.readSerialUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_read_serial(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.hamster_s_serial_all, 'ALL'],\n                                    [Lang.Blocks.hamster_s_serial_until_comma, 'COMMA'],\n                                    [Lang.Blocks.hamster_s_serial_until_colon, 'COLON'],\n                                    [Lang.Blocks.hamster_s_serial_until_dollar, 'DOLLAR'],\n                                    [Lang.Blocks.hamster_s_serial_until_sharp, 'SHARP'],\n                                    [Lang.Blocks.hamster_s_serial_until_new_line, 'NEW_LINE'],\n                                ],\n                                value: 'ALL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_hamster_s_set_serial_rate_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['9600', '9600'],\n                        ['14400', '14400'],\n                        ['19200', '19200'],\n                        ['28800', '28800'],\n                        ['38400', '38400'],\n                        ['57600', '57600'],\n                        ['76800', '76800'],\n                        ['115200', '115200'],\n                    ],\n                    value: '9600',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_hamster_s_set_serial_rate_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BAUD: 1,\n            },\n            class: 'hamster_s_port',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getHamsterS(index);\n                return robot ? robot.setSerialRate(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.hamster_s_set_serial_rate(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['9600', '9600'],\n                                    ['14400', '14400'],\n                                    ['19200', '19200'],\n                                    ['28800', '28800'],\n                                    ['38400', '38400'],\n                                    ['57600', '57600'],\n                                    ['76800', '76800'],\n                                    ['115200', '115200'],\n                                ],\n                                value: '9600',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_touching_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '2'],\n                        [Lang.Blocks.turtle_color_orange, '3'],\n                        [Lang.Blocks.turtle_color_yellow, '4'],\n                        [Lang.Blocks.turtle_color_green, '5'],\n                        [Lang.Blocks.turtle_color_sky_blue, '6'],\n                        [Lang.Blocks.turtle_color_blue, '7'],\n                        [Lang.Blocks.turtle_color_purple, '8'],\n                        [Lang.Blocks.turtle_color_black, '1'],\n                        [Lang.Blocks.turtle_color_white, '9'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_touching_color',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.checkTouchingColor(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_is_color_red(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '2'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_orange(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_yellow(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_green(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_sky_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_purple(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '8'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_black(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_white(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '9'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_is_color_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '1'],\n                        [Lang.Blocks.turtle_color_yellow, '3'],\n                        [Lang.Blocks.turtle_color_green, '4'],\n                        [Lang.Blocks.turtle_color_sky_blue, '5'],\n                        [Lang.Blocks.turtle_color_blue, '6'],\n                        [Lang.Blocks.turtle_color_purple, '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '1'],\n                        [Lang.Blocks.turtle_color_yellow, '3'],\n                        [Lang.Blocks.turtle_color_green, '4'],\n                        [Lang.Blocks.turtle_color_sky_blue, '5'],\n                        [Lang.Blocks.turtle_color_blue, '6'],\n                        [Lang.Blocks.turtle_color_purple, '7'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_is_color_pattern',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR1: 1,\n                COLOR2: 2,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.checkColorPattern(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_red_red(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1', '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_red_yellow(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1', '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_red_green(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1', '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_red_sky_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1', '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_red_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1', '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_red_purple(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '1', '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_yellow_red(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '3', '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_yellow_yellow(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '3', '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_yellow_green(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '3', '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_yellow_sky_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '3', '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_yellow_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '3', '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_yellow_purple(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '3', '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_green_red(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '4', '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_green_yellow(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '4', '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_green_green(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '4', '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_green_sky_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '4', '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_green_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '4', '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_green_purple(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '4', '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_sky_blue_red(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '5', '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_sky_blue_yellow(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '5', '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_sky_blue_green(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '5', '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_sky_blue_sky_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '5', '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_sky_blue_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '5', '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_sky_blue_purple(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '5', '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_blue_red(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '6', '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_blue_yellow(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '6', '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_blue_green(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '6', '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_blue_sky_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '6', '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_blue_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '6', '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_blue_purple(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '6', '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_purple_red(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '7', '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_purple_yellow(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '7', '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_purple_green(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '7', '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_purple_sky_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '7', '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_purple_blue(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '7', '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_is_color_pattern_purple_purple(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '7', '7'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_clicked, 'clicked'],\n                        [Lang.Blocks.turtle_double_clicked, 'doubleClicked'],\n                        [Lang.Blocks.turtle_long_pressed, 'longPressed'],\n                    ],\n                    value: 'clicked',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_button_state',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                STATE: 1,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.checkButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_is_button(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_clicked, 'clicked'],\n                                    [Lang.Blocks.turtle_double_clicked, 'doubleClicked'],\n                                    [Lang.Blocks.turtle_long_pressed, 'longPressed'],\n                                ],\n                                value: 'clicked',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.turtle_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.turtle_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.turtle_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.turtle_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.turtle_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.turtle_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.turtle_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.turtle_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'roboid_turtle_boolean',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_boolean_value(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.turtle_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.turtle_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.turtle_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.turtle_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.turtle_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.turtle_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.turtle_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.turtle_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_number, 'colorNumber'],\n                        [Lang.Blocks.turtle_color_pattern, 'colorPattern'],\n                        [Lang.Blocks.turtle_floor, 'floor'],\n                        [Lang.Blocks.turtle_button, 'button'],\n                        [Lang.Blocks.turtle_acceleration_x, 'accelerationX'],\n                        [Lang.Blocks.turtle_acceleration_y, 'accelerationY'],\n                        [Lang.Blocks.turtle_acceleration_z, 'accelerationZ'],\n                    ],\n                    value: 'colorNumber',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_value',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_sensor_value(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_number, 'colorNumber'],\n                                    [Lang.Blocks.turtle_color_pattern, 'colorPattern'],\n                                    [Lang.Blocks.turtle_floor, 'floor'],\n                                    [Lang.Blocks.turtle_button, 'button'],\n                                    [Lang.Blocks.turtle_acceleration_x, 'accelerationX'],\n                                    [Lang.Blocks.turtle_acceleration_y, 'accelerationY'],\n                                    [Lang.Blocks.turtle_acceleration_z, 'accelerationZ'],\n                                ],\n                                value: 'colorNumber',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_cm, 'CM'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_move_forward_unit',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_move_forward(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_cm, 'CM'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_cm, 'CM'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_move_backward_unit',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_move_backward(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_cm, 'CM'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n                UNIT: 3,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_turn(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_turn_unit_with_radius_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_head, 'HEAD'],\n                        [Lang.Blocks.turtle_tail, 'TAIL'],\n                    ],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_turn_unit_with_radius_in_direction',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIRECTION: 1,\n                VALUE: 2,\n                UNIT: 3,\n                RADIUS: 4,\n                TOWARD: 5,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.swingUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_circle(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_head, 'HEAD'],\n                                    [Lang.Blocks.turtle_tail, 'TAIL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_pivot_around_wheel_unit_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_head, 'HEAD'],\n                        [Lang.Blocks.turtle_tail, 'TAIL'],\n                    ],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_pivot_around_wheel_unit_in_direction',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                WHEEL: 1,\n                VALUE: 2,\n                UNIT: 3,\n                TOWARD: 4,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.pivotUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_pivot(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_head, 'HEAD'],\n                                    [Lang.Blocks.turtle_tail, 'TAIL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_change_wheels_by_left_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_change_wheels_by_left_right',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LEFT: 1,\n                RIGHT: 2,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_add_wheels(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_set_wheels_to_left_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_set_wheels_to_left_right',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                LEFT: 1,\n                RIGHT: 2,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_set_wheels(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                        [Lang.Blocks.turtle_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_change_wheel_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                WHEEL: 1,\n                VELOCITY: 2,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_add_wheel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                    [Lang.Blocks.turtle_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                        [Lang.Blocks.turtle_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_set_wheel_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                WHEEL: 1,\n                VELOCITY: 2,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_set_wheel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                    [Lang.Blocks.turtle_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_follow_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_black, '10'],\n                        [Lang.Blocks.turtle_color_red, '11'],\n                        [Lang.Blocks.turtle_color_green, '13'],\n                        [Lang.Blocks.turtle_color_blue, '15'],\n                        [Lang.Blocks.turtle_color_any, '17'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_follow_line',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_follow_black_line(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '10'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_red_line(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '11'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_green_line(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '13'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_blue_line(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '15'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_any_line(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '17'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '61'],\n                        [Lang.Blocks.turtle_color_yellow, '62'],\n                        [Lang.Blocks.turtle_color_green, '63'],\n                        [Lang.Blocks.turtle_color_sky_blue, '64'],\n                        [Lang.Blocks.turtle_color_blue, '65'],\n                        [Lang.Blocks.turtle_color_purple, '66'],\n                        [Lang.Blocks.turtle_color_any, '67'],\n                    ],\n                    value: '61',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_follow_line_until',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_follow_black_line_until_red(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '61'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_black_line_until_yellow(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '62'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_black_line_until_green(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '63'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_black_line_until_sky_blue(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '64'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_black_line_until_blue(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '65'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_black_line_until_purple(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '66'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_black_line_until_any(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '67'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_follow_line_until_black: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '71'],\n                        [Lang.Blocks.turtle_color_green, '73'],\n                        [Lang.Blocks.turtle_color_blue, '75'],\n                        [Lang.Blocks.turtle_color_any, '77'],\n                    ],\n                    value: '71',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_follow_line_until_black',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.followLineUntilBlack(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_follow_red_line_until_black(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '71'],\n                                    [Lang.Blocks.turtle_color_green, '73'],\n                                    [Lang.Blocks.turtle_color_blue, '75'],\n                                    [Lang.Blocks.turtle_color_any, '77'],\n                                ],\n                                value: '71',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '71'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_green_line_until_black(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '71'],\n                                    [Lang.Blocks.turtle_color_green, '73'],\n                                    [Lang.Blocks.turtle_color_blue, '75'],\n                                    [Lang.Blocks.turtle_color_any, '77'],\n                                ],\n                                value: '71',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '73'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_blue_line_until_black(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '71'],\n                                    [Lang.Blocks.turtle_color_green, '73'],\n                                    [Lang.Blocks.turtle_color_blue, '75'],\n                                    [Lang.Blocks.turtle_color_any, '77'],\n                                ],\n                                value: '71',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '75'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_follow_any_line_until_black(%1)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '71'],\n                                    [Lang.Blocks.turtle_color_green, '73'],\n                                    [Lang.Blocks.turtle_color_blue, '75'],\n                                    [Lang.Blocks.turtle_color_any, '77'],\n                                ],\n                                value: '71',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '77'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_cross_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_cross_intersection',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.crossIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_cross_forward(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_turn_at_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, '20'],\n                        [Lang.Blocks.turtle_right, '30'],\n                        [Lang.Blocks.turtle_back, '50'],\n                    ],\n                    value: '20',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_turn_at_intersection',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DIRECTION: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.turnAtIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_cross_left(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, '20'],\n                                    [Lang.Blocks.turtle_right, '30'],\n                                    [Lang.Blocks.turtle_back, '50'],\n                                ],\n                                value: '20',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '20'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_cross_right(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, '20'],\n                                    [Lang.Blocks.turtle_right, '30'],\n                                    [Lang.Blocks.turtle_back, '50'],\n                                ],\n                                value: '20',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '30'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_cross_uturn(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, '20'],\n                                    [Lang.Blocks.turtle_right, '30'],\n                                    [Lang.Blocks.turtle_back, '50'],\n                                ],\n                                value: '20',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: [null, '50'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    '5',\n                    null,\n                ],\n                type: 'roboid_turtle_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPEED: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_set_line_speed(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_stop',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_stop(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_set_head_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, 'RED'],\n                        [Lang.Blocks.turtle_color_orange, 'ORANGE'],\n                        [Lang.Blocks.turtle_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.turtle_color_green, 'GREEN'],\n                        [Lang.Blocks.turtle_color_sky_blue, 'CYAN'],\n                        [Lang.Blocks.turtle_color_blue, 'BLUE'],\n                        [Lang.Blocks.turtle_color_violet, 'VIOLET'],\n                        [Lang.Blocks.turtle_color_purple, 'MAGENTA'],\n                        [Lang.Blocks.turtle_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_set_head_led_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n            },\n            class: 'turtle_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.setHeadColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_set_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, 'RED'],\n                                    [Lang.Blocks.turtle_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.turtle_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.turtle_color_green, 'GREEN'],\n                                    [Lang.Blocks.turtle_color_sky_blue, 'CYAN'],\n                                    [Lang.Blocks.turtle_color_blue, 'BLUE'],\n                                    [Lang.Blocks.turtle_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.turtle_color_purple, 'MAGENTA'],\n                                    [Lang.Blocks.turtle_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_pick_head_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_turtle_pick_head_led',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n            },\n            class: 'turtle_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.pickHeadColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_pick_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_change_head_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_change_head_led_by_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'turtle_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.changeHeadRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_add_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_set_head_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_set_head_led_to_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'turtle_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.setHeadRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_set_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_clear_head_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_clear_head_led',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'turtle_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.clearHead(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_clear_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_sound_beep, '1'],\n                        [Lang.Blocks.turtle_sound_random_beep, '2'],\n                        [Lang.Blocks.turtle_sound_siren, '3'],\n                        [Lang.Blocks.turtle_sound_engine, '4'],\n                        [Lang.Blocks.turtle_sound_robot, '5'],\n                        [Lang.Blocks.turtle_sound_march, '6'],\n                        [Lang.Blocks.turtle_sound_birthday, '7'],\n                        [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                        [Lang.Blocks.turtle_sound_good_job, '9'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_play_sound_times',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SOUND: 1,\n                COUNT: 2,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_play_sound_beep(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_random_beep(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '2'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_siren(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_engine(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_robot(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_march(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_birthday(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_dibidibidip(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '8'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_good_job(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '9'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_sound_beep, '1'],\n                        [Lang.Blocks.turtle_sound_random_beep, '2'],\n                        [Lang.Blocks.turtle_sound_siren, '3'],\n                        [Lang.Blocks.turtle_sound_engine, '4'],\n                        [Lang.Blocks.turtle_sound_robot, '5'],\n                        [Lang.Blocks.turtle_sound_march, '6'],\n                        [Lang.Blocks.turtle_sound_birthday, '7'],\n                        [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                        [Lang.Blocks.turtle_sound_good_job, '9'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SOUND: 1,\n                COUNT: 2,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_beep(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '1'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_random_beep(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '2'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_siren(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '3'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_engine(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_robot(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_march(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_birthday(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_dibidibidip(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '8'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_sound_until_done_good_job(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '9'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                HZ: 1,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_add_buzzer(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                HZ: 1,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_set_buzzer(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_clear_sound',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_clear_sound(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                        params: [null],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_note_c, '4'],\n                        [Lang.Blocks.turtle_note_c_sharp, '5'],\n                        [Lang.Blocks.turtle_note_d, '6'],\n                        [Lang.Blocks.turtle_note_d_sharp, '7'],\n                        [Lang.Blocks.turtle_note_e, '8'],\n                        [Lang.Blocks.turtle_note_f, '9'],\n                        [Lang.Blocks.turtle_note_f_sharp, '10'],\n                        [Lang.Blocks.turtle_note_g, '11'],\n                        [Lang.Blocks.turtle_note_g_sharp, '12'],\n                        [Lang.Blocks.turtle_note_a, '13'],\n                        [Lang.Blocks.turtle_note_a_sharp, '14'],\n                        [Lang.Blocks.turtle_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    '4',\n                    null,\n                ],\n                type: 'roboid_turtle_play_note',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_c(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_c_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_d(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_d_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_e(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '8'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_f(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '9'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_f_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '10'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_g(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '11'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_g_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '12'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_a(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '13'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_a_sharp(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '14'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_pitch_b(%1, %3)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: [null, '15'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_play_note_for_beats: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_note_c, '4'],\n                        [Lang.Blocks.turtle_note_c_sharp, '5'],\n                        [Lang.Blocks.turtle_note_d, '6'],\n                        [Lang.Blocks.turtle_note_d_sharp, '7'],\n                        [Lang.Blocks.turtle_note_e, '8'],\n                        [Lang.Blocks.turtle_note_f, '9'],\n                        [Lang.Blocks.turtle_note_f_sharp, '10'],\n                        [Lang.Blocks.turtle_note_g, '11'],\n                        [Lang.Blocks.turtle_note_g_sharp, '12'],\n                        [Lang.Blocks.turtle_note_a, '13'],\n                        [Lang.Blocks.turtle_note_a_sharp, '14'],\n                        [Lang.Blocks.turtle_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_play_note_for_beats',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                BEAT: 3,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_play_note_c(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '4'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_c_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '5'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_d(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '6'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_d_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '7'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_e(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '8'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_f(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '9'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_f_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '10'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_g(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '11'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_g_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '12'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_a(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '13'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_a_sharp(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '14'],\n                    },\n                    {\n                        syntax: 'Roboid.turtle_play_note_b(%1, %3, %4)',\n                        textParams: [\n                            { type: 'Block', accept: 'string' },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: [null, '15'],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_rest_for_beats: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_rest_for_beats',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BEAT: 1,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_rest(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_change_tempo_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BPM: 1,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_add_tempo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_turtle_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'roboid_turtle_set_tempo_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BPM: 1,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getTurtle(index);\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.turtle_set_tempo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                        [Lang.Blocks.ROBOID_sensor_signal_strength_dbm, 'SIGNAL_STRENGTH'],\n                    ],\n                    value: 'ACCELERATION_X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_value',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'cheese_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_sensor_value(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                                    [\n                                        Lang.Blocks.ROBOID_sensor_signal_strength_dbm,\n                                        'SIGNAL_STRENGTH',\n                                    ],\n                                ],\n                                value: 'ACCELERATION_X',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_logo_sky_direction, 'TILT_NOT'],\n                        [Lang.Blocks.ROBOID_logo_earth_direction, 'TILT_FLIP'],\n                        [Lang.Blocks.ROBOID_power_switch_sky_direction, 'TILT_LEFT'],\n                        [Lang.Blocks.ROBOID_power_switch_earth_direction, 'TILT_RIGHT'],\n                        [Lang.Blocks.ROBOID_port_s_sky_direction, 'TILT_FORWARD'],\n                        [Lang.Blocks.ROBOID_port_s_earth_direction, 'TILT_BACKWARD'],\n                        [Lang.Blocks.ROBOID_tap, 'TAP'],\n                        [Lang.Blocks.ROBOID_free_fall, 'FREE_FALL'],\n                        [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_NOT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_boolean',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'cheese_sensor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_boolean_value(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_logo_sky_direction, 'TILT_NOT'],\n                                    [Lang.Blocks.ROBOID_logo_earth_direction, 'TILT_FLIP'],\n                                    [Lang.Blocks.ROBOID_power_switch_sky_direction, 'TILT_LEFT'],\n                                    [Lang.Blocks.ROBOID_power_switch_earth_direction, 'TILT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_port_s_sky_direction, 'TILT_FORWARD'],\n                                    [Lang.Blocks.ROBOID_port_s_earth_direction, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.ROBOID_tap, 'TAP'],\n                                    [Lang.Blocks.ROBOID_free_fall, 'FREE_FALL'],\n                                    [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_NOT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_play_sound_times',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SOUND: 1,\n                COUNT: 2,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_play_sound(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SOUND: 1,\n                COUNT: 2,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_play_sound_until_done(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                HZ: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_buzzer(%1, %2)',\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                HZ: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_buzzer(%1, %2)',\n                    },\n                ],\n            },\n        },\n        roboid_cheese_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_clear_sound',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_clear_sound(%1)',\n                    },\n                ],\n            },\n        },\n        roboid_cheese_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    '4',\n                    null,\n                ],\n                type: 'roboid_cheese_play_note',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_play_pitch(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_play_note_for',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                BEAT: 3,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_play_note(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_rest_for',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BEAT: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_rest(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_change_tempo_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BPM: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_tempo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_set_tempo_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BPM: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_tempo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_sound_port_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_speaker_internal, 'INTERNAL'],\n                        [Lang.Blocks.ROBOID_speaker_port_mab, 'MAB'],\n                    ],\n                    value: 'INTERNAL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_sound_port_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n            },\n            class: 'cheese_sound',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setSoundPort(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_sound_port(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_speaker_internal, 'INTERNAL'],\n                                    [Lang.Blocks.ROBOID_speaker_port_mab, 'MAB'],\n                                ],\n                                value: 'INTERNAL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_input_mode_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_io_mode_makey, 'MAKEY'],\n                        [Lang.Blocks.ROBOID_io_mode_button, 'BUTTON'],\n                        [Lang.Blocks.ROBOID_io_mode_digital_pull_up, 'DIGITAL_PULL_UP'],\n                        [Lang.Blocks.ROBOID_io_mode_digital_pull_down, 'DIGITAL_PULL_DOWN'],\n                        [Lang.Blocks.ROBOID_io_mode_analog, 'ANALOG'],\n                        [Lang.Blocks.ROBOID_io_mode_voltage, 'VOLTAGE'],\n                    ],\n                    value: 'MAKEY',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_input_mode_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                MODE: 2,\n            },\n            class: 'cheese_input',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setInputModeTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_input_mode(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_io_mode_makey, 'MAKEY'],\n                                    [Lang.Blocks.ROBOID_io_mode_button, 'BUTTON'],\n                                    [Lang.Blocks.ROBOID_io_mode_digital_pull_up, 'DIGITAL_PULL_UP'],\n                                    [\n                                        Lang.Blocks.ROBOID_io_mode_digital_pull_down,\n                                        'DIGITAL_PULL_DOWN',\n                                    ],\n                                    [Lang.Blocks.ROBOID_io_mode_analog, 'ANALOG'],\n                                    [Lang.Blocks.ROBOID_io_mode_voltage, 'VOLTAGE'],\n                                ],\n                                value: 'MAKEY',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_input_range_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                        [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                    ],\n                    value: 'INTEGER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_input_range_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                LOW1: 2,\n                HIGH1: 3,\n                LOW2: 4,\n                HIGH2: 5,\n                DECIMAL: 6,\n            },\n            class: 'cheese_input',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setInputRangeTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_input_range(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                                    [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                                ],\n                                value: 'INTEGER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_three_input_ranges_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                        [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                    ],\n                    value: 'INTEGER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['127'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['-100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_three_input_ranges_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                LOW1: 2,\n                MIDDLE1: 3,\n                HIGH1: 4,\n                LOW2: 5,\n                MIDDLE2: 6,\n                HIGH2: 7,\n                DECIMAL: 8,\n            },\n            class: 'cheese_input',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setThreeInputRangesTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax:\n                            'Roboid.cheese_set_input_range_middle(%1, %2, %3, %4, %5, %6, %7, %8, %9)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                                    [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                                ],\n                                value: 'INTEGER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_analog_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_analog_input',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n            },\n            class: 'cheese_input',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                if (robot) {\n                    return robot.getAnalogInput(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_analog_input(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_digital_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_digital_input',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_input',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.checkDigitalInput(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_digital_input(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_button_state',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                STATE: 2,\n            },\n            class: 'cheese_input',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.checkButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_button_state(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_pulse_mode_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sc', 'SC'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SC',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_io_mode_pulse, 'PULSE'],\n                        [Lang.Blocks.ROBOID_io_mode_pulse_pull_up, 'PULSE_PULL_UP'],\n                        [Lang.Blocks.ROBOID_io_mode_pulse_pull_down, 'PULSE_PULL_DOWN'],\n                    ],\n                    value: 'PULSE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_pulse_mode_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                MODE: 2,\n            },\n            class: 'cheese_input',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setInputModeTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_pulse_mode(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sc', 'SC'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SC',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_io_mode_pulse, 'PULSE'],\n                                    [Lang.Blocks.ROBOID_io_mode_pulse_pull_up, 'PULSE_PULL_UP'],\n                                    [Lang.Blocks.ROBOID_io_mode_pulse_pull_down, 'PULSE_PULL_DOWN'],\n                                ],\n                                value: 'PULSE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_pulse_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sc', 'SC'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SC',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_pulse_input',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n            },\n            class: 'cheese_input',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.checkPulseInput(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pulse_input(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sc', 'SC'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SC',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_digital_output_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                        [Lang.Blocks.ROBOID_io_port_high_current_mab, 'MAB'],\n                        [Lang.Blocks.ROBOID_io_port_high_current_mcd, 'MCD'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_digital_output_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_digital_output',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setDigitalOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_digital_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                    [Lang.Blocks.ROBOID_io_port_high_current_mab, 'MAB'],\n                                    [Lang.Blocks.ROBOID_io_port_high_current_mcd, 'MCD'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '0'],\n                                    ['1', '1'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_change_pwm_output_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_change_pwm_output_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_pwm_output',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.changePwmOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_pwm_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_pwm_output_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_set_pwm_output_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_pwm_output',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setPwmOutput(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_pwm_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_change_servo_motor_angle_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                        ['Ma(-)b(+)c', 'MABC'],\n                        ['Ma(-)b', 'MAB'],\n                        ['Mc(-)d', 'MCD'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_change_servo_motor_angle_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_servo_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.changeServoMotorAngle(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_servo_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                    ['Ma(-)b(+)c', 'MABC'],\n                                    ['Ma(-)b', 'MAB'],\n                                    ['Mc(-)d', 'MCD'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_servo_motor_angle_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                        ['Ma(-)b(+)c', 'MABC'],\n                        ['Ma(-)b', 'MAB'],\n                        ['Mc(-)d', 'MCD'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_set_servo_motor_angle_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_servo_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setServoMotorAngle(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_servo_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                    ['Ma(-)b(+)c', 'MABC'],\n                                    ['Ma(-)b', 'MAB'],\n                                    ['Mc(-)d', 'MCD'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_turn_off_servo_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Sa', 'SA'],\n                        ['Sb', 'SB'],\n                        ['Sc', 'SC'],\n                        ['La', 'LA'],\n                        ['Lb', 'LB'],\n                        ['Lc', 'LC'],\n                        ['Ma(-)b(+)c', 'MABC'],\n                        ['Ma(-)b', 'MAB'],\n                        ['Mc(-)d', 'MCD'],\n                    ],\n                    value: 'SA',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_turn_off_servo_motor',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n            },\n            class: 'cheese_servo_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.turnOffServoMotor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_release_servo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Sa', 'SA'],\n                                    ['Sb', 'SB'],\n                                    ['Sc', 'SC'],\n                                    ['La', 'LA'],\n                                    ['Lb', 'LB'],\n                                    ['Lc', 'LC'],\n                                    ['Ma(-)b(+)c', 'MABC'],\n                                    ['Ma(-)b', 'MAB'],\n                                    ['Mc(-)d', 'MCD'],\n                                ],\n                                value: 'SA',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_change_dc_motor_velocity_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Mab', 'MAB'],\n                        ['Mcd', 'MCD'],\n                    ],\n                    value: 'MAB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_change_dc_motor_velocity_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_dc_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.changeDcMotorVelocity(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_dc_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Mab', 'MAB'],\n                                    ['Mcd', 'MCD'],\n                                ],\n                                value: 'MAB',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_dc_motor_velocity_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Mab', 'MAB'],\n                        ['Mcd', 'MCD'],\n                    ],\n                    value: 'MAB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_set_dc_motor_velocity_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                VALUE: 2,\n            },\n            class: 'cheese_dc_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setDcMotorVelocity(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_dc_output(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Mab', 'MAB'],\n                                    ['Mcd', 'MCD'],\n                                ],\n                                value: 'MAB',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_stop_dc_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Mab', 'MAB'],\n                        ['Mcd', 'MCD'],\n                    ],\n                    value: 'MAB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_stop_dc_motor',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n            },\n            class: 'cheese_dc_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.stopDcMotor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_stop_dc(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['Mab', 'MAB'],\n                                    ['Mcd', 'MCD'],\n                                ],\n                                value: 'MAB',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_rotate_step_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_rotate_step_motor',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                STEP: 1,\n                VELOCITY: 2,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.rotateStepMotor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_rotate_step(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_change_step_motor_velocity_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_change_step_motor_velocity_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VELOCITY: 1,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.changeStepMotorVelocity(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_step_velocity(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_step_motor_velocity_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['300'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_set_step_motor_velocity_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VELOCITY: 1,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setStepMotorVelocity(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_step_velocity(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_stop_off_step_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_io_action_stop, 'STOP'],\n                        [Lang.Blocks.ROBOID_io_action_turn_off, 'OFF'],\n                    ],\n                    value: 'STOP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_stop_off_step_motor',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                ACTION: 1,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.stopOffStepMotor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_step_motor(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_io_action_stop, 'STOP'],\n                                    [Lang.Blocks.ROBOID_io_action_turn_off, 'OFF'],\n                                ],\n                                value: 'STOP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_step_motor_mode_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_io_mode_normal, 'NORMAL'],\n                        [Lang.Blocks.ROBOID_io_mode_power, 'POWER'],\n                    ],\n                    value: 'NORMAL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_step_motor_mode_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                MODE: 1,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setStepMotorMode(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_step_mode(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_io_mode_normal, 'NORMAL'],\n                                    [Lang.Blocks.ROBOID_io_mode_power, 'POWER'],\n                                ],\n                                value: 'NORMAL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_step_count: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_step_count',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'cheese_step_motor',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                if (robot) {\n                    return robot.getStepCount(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_step_count(%1)',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_led_to_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_intensity_dark, 'DARK'],\n                        [Lang.Blocks.ROBOID_led_intensity_normal, 'NORMAL'],\n                        [Lang.Blocks.ROBOID_led_intensity_bright, 'BRIGHT'],\n                    ],\n                    value: 'NORMAL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_led_to_color',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                INTENSITY: 2,\n                COLOR: 3,\n            },\n            class: 'cheese_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setLedColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_led(%1, %2 %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_intensity_dark, 'DARK'],\n                                    [Lang.Blocks.ROBOID_led_intensity_normal, 'NORMAL'],\n                                    [Lang.Blocks.ROBOID_led_intensity_bright, 'BRIGHT'],\n                                ],\n                                value: 'NORMAL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_pick_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_pick_led_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                COLOR: 2,\n            },\n            class: 'cheese_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setLedRgbArray(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pick_led(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                RED: 2,\n                GREEN: 3,\n                BLUE: 4,\n            },\n            class: 'cheese_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.changeLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_rgb(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_setLed_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_setLed_to_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                RED: 2,\n                GREEN: 3,\n                BLUE: 4,\n            },\n            class: 'cheese_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_rgb(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_clear_led',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n            },\n            class: 'cheese_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_clear_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_led_type_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['L', 'L'],\n                        ['S', 'S'],\n                    ],\n                    value: 'L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_type_default, 'DEFAULT'],\n                        [Lang.Blocks.ROBOID_led_type_crgb, '-RGB'],\n                        [Lang.Blocks.ROBOID_led_type_crbg, '-RBG'],\n                        [Lang.Blocks.ROBOID_led_type_cgrb, '-GRB'],\n                        [Lang.Blocks.ROBOID_led_type_cgbr, '-GBR'],\n                        [Lang.Blocks.ROBOID_led_type_cbrg, '-BRG'],\n                        [Lang.Blocks.ROBOID_led_type_cbgr, '-BGR'],\n                        [Lang.Blocks.ROBOID_led_type_argb, '+RGB'],\n                        [Lang.Blocks.ROBOID_led_type_arbg, '+RBG'],\n                        [Lang.Blocks.ROBOID_led_type_agrb, '+GRB'],\n                        [Lang.Blocks.ROBOID_led_type_agbr, '+GBR'],\n                        [Lang.Blocks.ROBOID_led_type_abrg, '+BRG'],\n                        [Lang.Blocks.ROBOID_led_type_abgr, '+BGR'],\n                    ],\n                    value: 'DEFAULT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_led_type_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n                TYPE: 2,\n            },\n            class: 'cheese_led',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setLedType(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_led_type(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['L', 'L'],\n                                    ['S', 'S'],\n                                ],\n                                value: 'L',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_type_default, 'DEFAULT'],\n                                    [Lang.Blocks.ROBOID_led_type_crgb, '-RGB'],\n                                    [Lang.Blocks.ROBOID_led_type_crbg, '-RBG'],\n                                    [Lang.Blocks.ROBOID_led_type_cgrb, '-GRB'],\n                                    [Lang.Blocks.ROBOID_led_type_cgbr, '-GBR'],\n                                    [Lang.Blocks.ROBOID_led_type_cbrg, '-BRG'],\n                                    [Lang.Blocks.ROBOID_led_type_cbgr, '-BGR'],\n                                    [Lang.Blocks.ROBOID_led_type_argb, '+RGB'],\n                                    [Lang.Blocks.ROBOID_led_type_arbg, '+RBG'],\n                                    [Lang.Blocks.ROBOID_led_type_agrb, '+GRB'],\n                                    [Lang.Blocks.ROBOID_led_type_agbr, '+GBR'],\n                                    [Lang.Blocks.ROBOID_led_type_abrg, '+BRG'],\n                                    [Lang.Blocks.ROBOID_led_type_abgr, '+BGR'],\n                                ],\n                                value: 'DEFAULT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_number_and_type_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['GRB', 'GRB'],\n                        ['GRBW', 'GRBW'],\n                    ],\n                    value: 'GRB',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_number_and_type_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                NUMBER: 1,\n                TYPE: 2,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetNumberAndType(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_neopixel_number_type(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['GRB', 'GRB'],\n                                    ['GRBW', 'GRBW'],\n                                ],\n                                value: 'GRB',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_all_leds_to_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_neopixel_3_colors, 'FILL_3_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_6_colors, 'FILL_6_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_12_colors, 'FILL_12_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_red_green, 'GRADIENT_RED_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_red_blue, 'GRADIENT_RED_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_red_white, 'GRADIENT_RED_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_green_red, 'GRADIENT_GREEN_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_green_blue, 'GRADIENT_GREEN_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_green_white, 'GRADIENT_GREEN_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_red, 'GRADIENT_BLUE_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_green, 'GRADIENT_BLUE_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_white, 'GRADIENT_BLUE_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_white_red, 'GRADIENT_WHITE_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_white_green, 'GRADIENT_WHITE_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_white_blue, 'GRADIENT_WHITE_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_red_black, 'GRADIENT_RED_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_green_black, 'GRADIENT_GREEN_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_black, 'GRADIENT_BLUE_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_white_black, 'GRADIENT_WHITE_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_black_red, 'GRADIENT_BLACK_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_black_green, 'GRADIENT_BLACK_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_black_blue, 'GRADIENT_BLACK_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_black_white, 'GRADIENT_BLACK_WHITE'],\n                    ],\n                    value: 'FILL_3_COLORS',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_all_leds_to_pattern',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PATTERN: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetAllPattern(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_all_neopixel_pattern(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_neopixel_3_colors, 'FILL_3_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_6_colors, 'FILL_6_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_12_colors, 'FILL_12_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_green, 'GRADIENT_RED_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_blue, 'GRADIENT_RED_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_white, 'GRADIENT_RED_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_red, 'GRADIENT_GREEN_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_blue, 'GRADIENT_GREEN_BLUE'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_green_white,\n                                        'GRADIENT_GREEN_WHITE',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_red, 'GRADIENT_BLUE_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_green, 'GRADIENT_BLUE_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_white, 'GRADIENT_BLUE_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_red, 'GRADIENT_WHITE_RED'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_white_green,\n                                        'GRADIENT_WHITE_GREEN',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_white_blue, 'GRADIENT_WHITE_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_black, 'GRADIENT_RED_BLACK'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_green_black,\n                                        'GRADIENT_GREEN_BLACK',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_black, 'GRADIENT_BLUE_BLACK'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_white_black,\n                                        'GRADIENT_WHITE_BLACK',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_black_red, 'GRADIENT_BLACK_RED'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_black_green,\n                                        'GRADIENT_BLACK_GREEN',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_black_blue, 'GRADIENT_BLACK_BLUE'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_black_white,\n                                        'GRADIENT_BLACK_WHITE',\n                                    ],\n                                ],\n                                value: 'FILL_3_COLORS',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_all_leds_to_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_all_leds_to_color',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetAllColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_all_neopixel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_pick_all_leds_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_pick_all_leds_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetAllRgbArray(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pick_all_neopixel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_change_all_leds_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_change_all_leds_by_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelChangeAllRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_all_neopixel_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_all_leds_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_all_leds_to_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetAllRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_all_neopixel_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_clear_all_leds: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_clear_all_leds',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelClearAll(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_clear_all_neopixel(%1)',\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_led_to_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_led_to_color',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PIXEL: 1,\n                COLOR: 2,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetLedColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_neopixel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_pick_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_pick_led_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PIXEL: 1,\n                COLOR: 2,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetLedRgbArray(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pick_neopixel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PIXEL: 1,\n                RED: 2,\n                GREEN: 3,\n                BLUE: 4,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelChangeLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_neopixel_rgb(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_led_to_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PIXEL: 1,\n                RED: 2,\n                GREEN: 3,\n                BLUE: 4,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_neopixel_rgb(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_clear_led',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PIXEL: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelClearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_clear_neopixel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_led_range_to_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_neopixel_3_colors, 'FILL_3_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_6_colors, 'FILL_6_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_12_colors, 'FILL_12_COLORS'],\n                        [Lang.Blocks.ROBOID_neopixel_red_green, 'GRADIENT_RED_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_red_blue, 'GRADIENT_RED_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_red_white, 'GRADIENT_RED_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_green_red, 'GRADIENT_GREEN_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_green_blue, 'GRADIENT_GREEN_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_green_white, 'GRADIENT_GREEN_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_red, 'GRADIENT_BLUE_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_green, 'GRADIENT_BLUE_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_white, 'GRADIENT_BLUE_WHITE'],\n                        [Lang.Blocks.ROBOID_neopixel_white_red, 'GRADIENT_WHITE_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_white_green, 'GRADIENT_WHITE_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_white_blue, 'GRADIENT_WHITE_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_red_black, 'GRADIENT_RED_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_green_black, 'GRADIENT_GREEN_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_blue_black, 'GRADIENT_BLUE_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_white_black, 'GRADIENT_WHITE_BLACK'],\n                        [Lang.Blocks.ROBOID_neopixel_black_red, 'GRADIENT_BLACK_RED'],\n                        [Lang.Blocks.ROBOID_neopixel_black_green, 'GRADIENT_BLACK_GREEN'],\n                        [Lang.Blocks.ROBOID_neopixel_black_blue, 'GRADIENT_BLACK_BLUE'],\n                        [Lang.Blocks.ROBOID_neopixel_black_white, 'GRADIENT_BLACK_WHITE'],\n                    ],\n                    value: 'FILL_3_COLORS',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_led_range_to_pattern',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                START: 1,\n                END: 2,\n                PATTERN: 3,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetRangePattern(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_neopixel_range_pattern(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_neopixel_3_colors, 'FILL_3_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_6_colors, 'FILL_6_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_12_colors, 'FILL_12_COLORS'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_green, 'GRADIENT_RED_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_blue, 'GRADIENT_RED_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_white, 'GRADIENT_RED_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_red, 'GRADIENT_GREEN_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_green_blue, 'GRADIENT_GREEN_BLUE'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_green_white,\n                                        'GRADIENT_GREEN_WHITE',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_red, 'GRADIENT_BLUE_RED'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_green, 'GRADIENT_BLUE_GREEN'],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_white, 'GRADIENT_BLUE_WHITE'],\n                                    [Lang.Blocks.ROBOID_neopixel_white_red, 'GRADIENT_WHITE_RED'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_white_green,\n                                        'GRADIENT_WHITE_GREEN',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_white_blue, 'GRADIENT_WHITE_BLUE'],\n                                    [Lang.Blocks.ROBOID_neopixel_red_black, 'GRADIENT_RED_BLACK'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_green_black,\n                                        'GRADIENT_GREEN_BLACK',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_blue_black, 'GRADIENT_BLUE_BLACK'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_white_black,\n                                        'GRADIENT_WHITE_BLACK',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_black_red, 'GRADIENT_BLACK_RED'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_black_green,\n                                        'GRADIENT_BLACK_GREEN',\n                                    ],\n                                    [Lang.Blocks.ROBOID_neopixel_black_blue, 'GRADIENT_BLACK_BLUE'],\n                                    [\n                                        Lang.Blocks.ROBOID_neopixel_black_white,\n                                        'GRADIENT_BLACK_WHITE',\n                                    ],\n                                ],\n                                value: 'FILL_3_COLORS',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_led_range_to_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_led_range_to_color',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                START: 1,\n                END: 2,\n                INCREMENT: 3,\n                COLOR: 4,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetRangeColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_neopixel_range(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_pick_led_range_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_pick_led_range_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                START: 1,\n                END: 2,\n                INCREMENT: 3,\n                COLOR: 4,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetRangeRgbArray(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pick_neopixel_range(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_change_led_range_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_change_led_range_by_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                START: 1,\n                END: 2,\n                INCREMENT: 3,\n                RED: 4,\n                GREEN: 5,\n                BLUE: 6,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelChangeRangeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_neopixel_range_rgb(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_led_range_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_led_range_to_rgb',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                START: 1,\n                END: 2,\n                INCREMENT: 3,\n                RED: 4,\n                GREEN: 5,\n                BLUE: 6,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetRangeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_neopixel_range_rgb(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_clear_led_range: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_clear_led_range',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                START: 1,\n                END: 2,\n                INCREMENT: 3,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelClearRange(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_clear_neopixel_range(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_shift: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_shift',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BIT: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelShift(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_shift_neopixel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_rotate',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BIT: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelRotate(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_rotate_neopixel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_change_brightness_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_change_brightness_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelChangeBrightness(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_add_neopixel_brightness(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_neopixel_set_brightness_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_neopixel_set_brightness_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                VALUE: 1,\n            },\n            class: 'cheese_neopixel',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.neopixelSetBrightness(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_neopixel_brightness(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_write_serial: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_serial_string, 'STRING'],\n                        [Lang.Blocks.ROBOID_serial_string_line, 'STRING_LINE'],\n                    ],\n                    value: 'STRING',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['abc123'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_write_serial',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                MODE: 1,\n                STRING: 2,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.writeSerial(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_write_serial(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_serial_string, 'STRING'],\n                                    [Lang.Blocks.ROBOID_serial_string_line, 'STRING_LINE'],\n                                ],\n                                value: 'STRING',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_read_serial_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_serial_all, 'ALL'],\n                        [Lang.Blocks.ROBOID_serial_until_comma, 'COMMA'],\n                        [Lang.Blocks.ROBOID_serial_until_colon, 'COLON'],\n                        [Lang.Blocks.ROBOID_serial_until_dollar, 'DOLLAR'],\n                        [Lang.Blocks.ROBOID_serial_until_sharp, 'SHARP'],\n                        [Lang.Blocks.ROBOID_serial_until_new_line, 'NEW_LINE'],\n                    ],\n                    value: 'ALL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_read_serial_until',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DELIMITER: 1,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.readSerialUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_read_serial(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_serial_all, 'ALL'],\n                                    [Lang.Blocks.ROBOID_serial_until_comma, 'COMMA'],\n                                    [Lang.Blocks.ROBOID_serial_until_colon, 'COLON'],\n                                    [Lang.Blocks.ROBOID_serial_until_dollar, 'DOLLAR'],\n                                    [Lang.Blocks.ROBOID_serial_until_sharp, 'SHARP'],\n                                    [Lang.Blocks.ROBOID_serial_until_new_line, 'NEW_LINE'],\n                                ],\n                                value: 'ALL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_serial_port_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_serial_port_wa_rb, 'WRITE_READ'],\n                        [Lang.Blocks.ROBOID_serial_port_ra_wb, 'READ_WRITE'],\n                        [Lang.Blocks.ROBOID_serial_port_wa, 'WRITE'],\n                        [Lang.Blocks.ROBOID_serial_port_ra, 'READ'],\n                    ],\n                    value: 'WRITE_READ',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_serial_port_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                PORT: 1,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setSerialPort(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_serial_port(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_serial_port_wa_rb, 'WRITE_READ'],\n                                    [Lang.Blocks.ROBOID_serial_port_ra_wb, 'READ_WRITE'],\n                                    [Lang.Blocks.ROBOID_serial_port_wa, 'WRITE'],\n                                    [Lang.Blocks.ROBOID_serial_port_ra, 'READ'],\n                                ],\n                                value: 'WRITE_READ',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_set_serial_rate_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['9600', '9600'],\n                        ['14400', '14400'],\n                        ['19200', '19200'],\n                        ['28800', '28800'],\n                        ['38400', '38400'],\n                        ['57600', '57600'],\n                        ['76800', '76800'],\n                        ['115200', '115200'],\n                    ],\n                    value: '9600',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_set_serial_rate_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BAUD: 1,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.setSerialRate(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_set_serial_rate(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['9600', '9600'],\n                                    ['14400', '14400'],\n                                    ['19200', '19200'],\n                                    ['28800', '28800'],\n                                    ['38400', '38400'],\n                                    ['57600', '57600'],\n                                    ['76800', '76800'],\n                                    ['115200', '115200'],\n                                ],\n                                value: '9600',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_serial_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'roboid_cheese_serial_input',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'cheese_serial',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                if (robot) {\n                    return robot.getSerialInput(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_serial_input(%1)',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        roboid_cheese_pid_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_pid_10, '10'],\n                        [Lang.Blocks.ROBOID_pid_11_1, '11-1'],\n                        [Lang.Blocks.ROBOID_pid_11_2, '11-2'],\n                        [Lang.Blocks.ROBOID_pid_11_3, '11-3'],\n                        [Lang.Blocks.ROBOID_pid_12, '12'],\n                        [Lang.Blocks.ROBOID_pid_13, '13'],\n                        [Lang.Blocks.ROBOID_pid_14, '14'],\n                        //                        [Lang.Blocks.ROBOID_pid_15, '15'],\n                        [Lang.Blocks.ROBOID_pid_16, '16'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_pid_start',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                DEVICE: 1,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.pidStart(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pid_start(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_pid_10, '10'],\n                                    [Lang.Blocks.ROBOID_pid_11_1, '11-1'],\n                                    [Lang.Blocks.ROBOID_pid_11_2, '11-2'],\n                                    [Lang.Blocks.ROBOID_pid_11_3, '11-3'],\n                                    [Lang.Blocks.ROBOID_pid_12, '12'],\n                                    [Lang.Blocks.ROBOID_pid_13, '13'],\n                                    [Lang.Blocks.ROBOID_pid_14, '14'],\n                                    //                                    [Lang.Blocks.ROBOID_pid_15, '15'],\n                                    [Lang.Blocks.ROBOID_pid_16, '16'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_pid_set_range_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                        [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                        [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                        [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                    ],\n                    value: 'X1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                        [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                    ],\n                    value: 'INTEGER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_pid_set_range_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                INPUT: 1,\n                LOW1: 2,\n                HIGH1: 3,\n                LOW2: 4,\n                HIGH2: 5,\n                DECIMAL: 6,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.pidSetRangeTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pid_set_input_range(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                                    [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                                    [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                                    [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                                ],\n                                value: 'X1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                                    [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                                ],\n                                value: 'INTEGER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_pid_set_three_ranges_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                        [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                        [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                        [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                    ],\n                    value: 'X1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                        [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                    ],\n                    value: 'INTEGER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['127'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['-100'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['100'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_pid_set_three_ranges_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                INPUT: 1,\n                LOW1: 2,\n                MIDDLE1: 3,\n                HIGH1: 4,\n                LOW2: 5,\n                MIDDLE2: 6,\n                HIGH2: 7,\n                DECIMAL: 8,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.pidSetThreeRangesTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax:\n                            'Roboid.cheese_pid_set_input_range_middle(%1, %2, %3, %4, %5, %6, %7, %8, %9)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                                    [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                                    [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                                    [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                                ],\n                                value: 'X1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_range_integer, 'INTEGER'],\n                                    [Lang.Blocks.ROBOID_range_real, 'REAL'],\n                                ],\n                                value: 'INTEGER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_pid_reset_encoder: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_pid_reset_encoder',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.pidResetEncoder(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pid_reset_encoder(%1)',\n                    },\n                ],\n            },\n        },\n        roboid_cheese_pid_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_pid_distance, 'DISTANCE'],\n                        [Lang.Blocks.ROBOID_pid_temperature, 'TEMPERATURE'],\n                        [Lang.Blocks.ROBOID_pid_humidity, 'HUMIDITY'],\n                        [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                        [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                        [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                        [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                        [Lang.Blocks.ROBOID_pid_button1, 'BUTTON1'],\n                        [Lang.Blocks.ROBOID_pid_button2, 'BUTTON2'],\n                        [Lang.Blocks.ROBOID_pid_encoder, 'ENCODER'],\n                    ],\n                    value: 'DISTANCE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_pid_input',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                INPUT: 1,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                if (robot) {\n                    return robot.pidGetInput(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pid_input(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_pid_distance, 'DISTANCE'],\n                                    [Lang.Blocks.ROBOID_pid_temperature, 'TEMPERATURE'],\n                                    [Lang.Blocks.ROBOID_pid_humidity, 'HUMIDITY'],\n                                    [Lang.Blocks.ROBOID_pid_x1, 'X1'],\n                                    [Lang.Blocks.ROBOID_pid_y1, 'Y1'],\n                                    [Lang.Blocks.ROBOID_pid_x2, 'X2'],\n                                    [Lang.Blocks.ROBOID_pid_y2, 'Y2'],\n                                    [Lang.Blocks.ROBOID_pid_button1, 'BUTTON1'],\n                                    [Lang.Blocks.ROBOID_pid_button2, 'BUTTON2'],\n                                    [Lang.Blocks.ROBOID_pid_encoder, 'ENCODER'],\n                                ],\n                                value: 'DISTANCE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_pid_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_pid_button_state',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BUTTON: 1,\n                STATE: 2,\n            },\n            class: 'cheese_pid',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.pidCheckButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_pid_button_state(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_start: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_start',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010Start(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_start(%1)',\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_button',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BUTTON: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                if (robot) {\n                    return robot.hat010GetButton(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_button(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A', 'A'],\n                                    ['B', 'B'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A', 'A'],\n                        ['B', 'B'],\n                    ],\n                    value: 'A',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_button_state',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BUTTON: 1,\n                STATE: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010CheckButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_button_state(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A', 'A'],\n                                    ['B', 'B'],\n                                ],\n                                value: 'A',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_double_clicked, 'DOUBLE_CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_background_turn_on_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_background_turn_on_xy',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                X: 1,\n                Y: 2,\n                COLOR: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010BackgroundTurnOnXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_turn_on_background_pixel(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_background_turn_off_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_background_turn_off_xy',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                X: 1,\n                Y: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010BackgroundTurnOffXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_turn_off_background_pixel(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_background_draw_shape_at_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_shape_square, 'SQUARE'],\n                        [Lang.Blocks.ROBOID_shape_triangle, 'TRIANGLE'],\n                        [Lang.Blocks.ROBOID_shape_diamond, 'DIAMOND'],\n                        [Lang.Blocks.ROBOID_shape_circle, 'CIRCLE'],\n                        [Lang.Blocks.ROBOID_shape_x, 'X'],\n                        [Lang.Blocks.ROBOID_shape_like, 'LIKE'],\n                        [Lang.Blocks.ROBOID_shape_dislike, 'DISLIKE'],\n                        [Lang.Blocks.ROBOID_shape_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_shape_open_mouth, 'OPEN_MOUTH'],\n                        [Lang.Blocks.ROBOID_shape_close_mouth, 'CLOSE_MOUTH'],\n                        [Lang.Blocks.ROBOID_shape_walk1, 'WALK1'],\n                        [Lang.Blocks.ROBOID_shape_walk2, 'WALK2'],\n                        [Lang.Blocks.ROBOID_shape_heart, 'HEART'],\n                        [Lang.Blocks.ROBOID_shape_star, 'STAR'],\n                        [Lang.Blocks.ROBOID_shape_airplane, 'AIRPLANE'],\n                        [Lang.Blocks.ROBOID_shape_puppy, 'PUPPY'],\n                        [Lang.Blocks.ROBOID_shape_butterfly, 'BUTTERFLY'],\n                        [Lang.Blocks.ROBOID_shape_quarter_note, 'QUARTER_NOTE'],\n                        [Lang.Blocks.ROBOID_shape_eighth_note, 'EIGHTH_NOTE'],\n                        [Lang.Blocks.ROBOID_shape_left_arrow, 'LEFT_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_right_arrow, 'RIGHT_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_up_arrow, 'UP_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_down_arrow, 'DOWN_ARRAY'],\n                    ],\n                    value: 'SQUARE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_background_draw_shape_at_xy',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n                SHAPE: 2,\n                X: 3,\n                Y: 4,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010BackgroundDrawShapeAtXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_draw_background_shape(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_shape_square, 'SQUARE'],\n                                    [Lang.Blocks.ROBOID_shape_triangle, 'TRIANGLE'],\n                                    [Lang.Blocks.ROBOID_shape_diamond, 'DIAMOND'],\n                                    [Lang.Blocks.ROBOID_shape_circle, 'CIRCLE'],\n                                    [Lang.Blocks.ROBOID_shape_x, 'X'],\n                                    [Lang.Blocks.ROBOID_shape_like, 'LIKE'],\n                                    [Lang.Blocks.ROBOID_shape_dislike, 'DISLIKE'],\n                                    [Lang.Blocks.ROBOID_shape_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_shape_open_mouth, 'OPEN_MOUTH'],\n                                    [Lang.Blocks.ROBOID_shape_close_mouth, 'CLOSE_MOUTH'],\n                                    [Lang.Blocks.ROBOID_shape_walk1, 'WALK1'],\n                                    [Lang.Blocks.ROBOID_shape_walk2, 'WALK2'],\n                                    [Lang.Blocks.ROBOID_shape_heart, 'HEART'],\n                                    [Lang.Blocks.ROBOID_shape_star, 'STAR'],\n                                    [Lang.Blocks.ROBOID_shape_airplane, 'AIRPLANE'],\n                                    [Lang.Blocks.ROBOID_shape_puppy, 'PUPPY'],\n                                    [Lang.Blocks.ROBOID_shape_butterfly, 'BUTTERFLY'],\n                                    [Lang.Blocks.ROBOID_shape_quarter_note, 'QUARTER_NOTE'],\n                                    [Lang.Blocks.ROBOID_shape_eighth_note, 'EIGHTH_NOTE'],\n                                    [Lang.Blocks.ROBOID_shape_left_arrow, 'LEFT_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_right_arrow, 'RIGHT_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_up_arrow, 'UP_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_down_arrow, 'DOWN_ARRAY'],\n                                ],\n                                value: 'SQUARE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_background_draw_string_at_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['abc123'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_background_draw_string_at_xy',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n                TEXT: 2,\n                X: 3,\n                Y: 4,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010BackgroundDrawStringAtXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_draw_background_string(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_background_draw_pattern_at_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10010'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_background_draw_pattern_at_xy',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                COLOR: 1,\n                PATTERN: 2,\n                X: 3,\n                Y: 4,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010BackgroundDrawPatternAtXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_draw_background_pattern(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                        [Lang.Blocks.ROBOID_hat_all, 'ALL'],\n                    ],\n                    value: 'BACKGROUND',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_clear',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                TARGET: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010Clear(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_clear(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                                    [Lang.Blocks.ROBOID_hat_all, 'ALL'],\n                                ],\n                                value: 'BACKGROUND',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_scroll_by_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                        [Lang.Blocks.ROBOID_hat_all, 'ALL'],\n                    ],\n                    value: 'BACKGROUND',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_scroll_by_xy',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                TARGET: 1,\n                X: 2,\n                Y: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010ScrollByXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_scroll(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                                    [Lang.Blocks.ROBOID_hat_all, 'ALL'],\n                                ],\n                                value: 'BACKGROUND',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_set_to_shape: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_shape_square, 'SQUARE'],\n                        [Lang.Blocks.ROBOID_shape_triangle, 'TRIANGLE'],\n                        [Lang.Blocks.ROBOID_shape_diamond, 'DIAMOND'],\n                        [Lang.Blocks.ROBOID_shape_circle, 'CIRCLE'],\n                        [Lang.Blocks.ROBOID_shape_x, 'X'],\n                        [Lang.Blocks.ROBOID_shape_like, 'LIKE'],\n                        [Lang.Blocks.ROBOID_shape_dislike, 'DISLIKE'],\n                        [Lang.Blocks.ROBOID_shape_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_shape_open_mouth, 'OPEN_MOUTH'],\n                        [Lang.Blocks.ROBOID_shape_close_mouth, 'CLOSE_MOUTH'],\n                        [Lang.Blocks.ROBOID_shape_walk1, 'WALK1'],\n                        [Lang.Blocks.ROBOID_shape_walk2, 'WALK2'],\n                        [Lang.Blocks.ROBOID_shape_heart, 'HEART'],\n                        [Lang.Blocks.ROBOID_shape_star, 'STAR'],\n                        [Lang.Blocks.ROBOID_shape_airplane, 'AIRPLANE'],\n                        [Lang.Blocks.ROBOID_shape_puppy, 'PUPPY'],\n                        [Lang.Blocks.ROBOID_shape_butterfly, 'BUTTERFLY'],\n                        [Lang.Blocks.ROBOID_shape_quarter_note, 'QUARTER_NOTE'],\n                        [Lang.Blocks.ROBOID_shape_eighth_note, 'EIGHTH_NOTE'],\n                        [Lang.Blocks.ROBOID_shape_left_arrow, 'LEFT_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_right_arrow, 'RIGHT_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_up_arrow, 'UP_ARROW'],\n                        [Lang.Blocks.ROBOID_shape_down_arrow, 'DOWN_ARRAY'],\n                    ],\n                    value: 'SQUARE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_set_to_shape',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                COLOR: 2,\n                SHAPE: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteSetToShape(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_set_sprite_shape(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_shape_square, 'SQUARE'],\n                                    [Lang.Blocks.ROBOID_shape_triangle, 'TRIANGLE'],\n                                    [Lang.Blocks.ROBOID_shape_diamond, 'DIAMOND'],\n                                    [Lang.Blocks.ROBOID_shape_circle, 'CIRCLE'],\n                                    [Lang.Blocks.ROBOID_shape_x, 'X'],\n                                    [Lang.Blocks.ROBOID_shape_like, 'LIKE'],\n                                    [Lang.Blocks.ROBOID_shape_dislike, 'DISLIKE'],\n                                    [Lang.Blocks.ROBOID_shape_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_shape_open_mouth, 'OPEN_MOUTH'],\n                                    [Lang.Blocks.ROBOID_shape_close_mouth, 'CLOSE_MOUTH'],\n                                    [Lang.Blocks.ROBOID_shape_walk1, 'WALK1'],\n                                    [Lang.Blocks.ROBOID_shape_walk2, 'WALK2'],\n                                    [Lang.Blocks.ROBOID_shape_heart, 'HEART'],\n                                    [Lang.Blocks.ROBOID_shape_star, 'STAR'],\n                                    [Lang.Blocks.ROBOID_shape_airplane, 'AIRPLANE'],\n                                    [Lang.Blocks.ROBOID_shape_puppy, 'PUPPY'],\n                                    [Lang.Blocks.ROBOID_shape_butterfly, 'BUTTERFLY'],\n                                    [Lang.Blocks.ROBOID_shape_quarter_note, 'QUARTER_NOTE'],\n                                    [Lang.Blocks.ROBOID_shape_eighth_note, 'EIGHTH_NOTE'],\n                                    [Lang.Blocks.ROBOID_shape_left_arrow, 'LEFT_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_right_arrow, 'RIGHT_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_up_arrow, 'UP_ARROW'],\n                                    [Lang.Blocks.ROBOID_shape_down_arrow, 'DOWN_ARRAY'],\n                                ],\n                                value: 'SQUARE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_set_to_string: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['abc123'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_set_to_string',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                COLOR: 2,\n                TEXT: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteSetToString(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_set_sprite_string(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_set_to_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10010'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_set_to_pattern',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                COLOR: 2,\n                PATTERN: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteSetToPattern(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_set_sprite_pattern(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_clear_show_hide: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_clear, 'CLEAR'],\n                        [Lang.Blocks.ROBOID_hat_show, 'SHOW'],\n                        [Lang.Blocks.ROBOID_hat_hide, 'HIDE'],\n                    ],\n                    value: 'CLEAR',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_clear_show_hide',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                ACTION: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteClearShowHide(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_sprite(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_clear, 'CLEAR'],\n                                    [Lang.Blocks.ROBOID_hat_show, 'SHOW'],\n                                    [Lang.Blocks.ROBOID_hat_hide, 'HIDE'],\n                                ],\n                                value: 'CLEAR',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_change_positions_by_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_change_positions_by_xy',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                X: 2,\n                Y: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteChangePositionsByXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_add_sprite_positions(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_set_positions_to_xy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_set_positions_to_xy',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                X: 2,\n                Y: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteSetPositionsToXY(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_set_sprite_positions(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_change_position_by_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', 'X'],\n                        ['y', 'Y'],\n                    ],\n                    value: 'X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_change_position_by_value',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                POSITION: 2,\n                VALUE: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteChangePositionByValue(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_add_sprite_position(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['x', 'X'],\n                                    ['y', 'Y'],\n                                ],\n                                value: 'X',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_set_position_to_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', 'X'],\n                        ['y', 'Y'],\n                    ],\n                    value: 'X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_set_position_to_value',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                POSITION: 2,\n                VALUE: 3,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteSetPositionToValue(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_set_sprite_position(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['x', 'X'],\n                                    ['y', 'Y'],\n                                ],\n                                value: 'X',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_clockwise, 'CLOCKWISE'],\n                        [Lang.Blocks.ROBOID_hat_counterclockwise, 'COUNTERCLOCKWISE'],\n                    ],\n                    value: 'CLOCKWISE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_rotate',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                DIRECTION: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteRotate(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_rotate_sprite(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_clockwise, 'CLOCKWISE'],\n                                    [Lang.Blocks.ROBOID_hat_counterclockwise, 'COUNTERCLOCKWISE'],\n                                ],\n                                value: 'CLOCKWISE',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_flip_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_left_right, 'LEFT_RIGHT'],\n                        [Lang.Blocks.ROBOID_hat_up_down, 'UP_DOWN'],\n                    ],\n                    value: 'LEFT_RIGHT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_flip_in_direction',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                DIRECTION: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteFlipInDirection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_flip_sprite(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_left_right, 'LEFT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_hat_up_down, 'UP_DOWN'],\n                                ],\n                                value: 'LEFT_RIGHT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_stamp_to_background: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_stamp_to_background',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SpriteStampToBackground(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_stamp(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_position: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', 'X'],\n                        ['y', 'Y'],\n                    ],\n                    value: 'X',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_position',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                POSITION: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                if (robot) {\n                    return robot.hat010GetSpritePosition(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_sprite_position(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['x', 'X'],\n                                    ['y', 'Y'],\n                                ],\n                                value: 'X',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_touching_sprite: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['2'],\n                    },\n                ],\n                type: 'roboid_cheese_hat010_sprite_touching_sprite',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                TARGET: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010CheckCheckSpriteSpriteTouched(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_touching_sprite(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_sprite_touching: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                        [Lang.Blocks.ROBOID_hat_other_sprite, 'OTHER_SPRITE'],\n                        [Lang.Blocks.ROBOID_hat_left_wall, 'LEFT_WALL'],\n                        [Lang.Blocks.ROBOID_hat_right_wall, 'RIGHT_WALL'],\n                        [Lang.Blocks.ROBOID_hat_top_wall, 'TOP_WALL'],\n                        [Lang.Blocks.ROBOID_hat_bottom_wall, 'BOTTOM_WALL'],\n                        [Lang.Blocks.ROBOID_hat_any_wall, 'ANY_WALL'],\n                    ],\n                    value: 'BACKGROUND',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_sprite_touching',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                SPRITE: 1,\n                TARGET: 2,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010CheckCheckSpriteTouched(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_touching(%1, %2, %3)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_hat_background, 'BACKGROUND'],\n                                    [Lang.Blocks.ROBOID_hat_other_sprite, 'OTHER_SPRITE'],\n                                    [Lang.Blocks.ROBOID_hat_left_wall, 'LEFT_WALL'],\n                                    [Lang.Blocks.ROBOID_hat_right_wall, 'RIGHT_WALL'],\n                                    [Lang.Blocks.ROBOID_hat_top_wall, 'TOP_WALL'],\n                                    [Lang.Blocks.ROBOID_hat_bottom_wall, 'BOTTOM_WALL'],\n                                    [Lang.Blocks.ROBOID_hat_any_wall, 'ANY_WALL'],\n                                ],\n                                value: 'BACKGROUND',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_change_brightness_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_change_brightness_by',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010ChangeBrightnessBy(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_add_brightness(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        roboid_cheese_hat010_set_brightness_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'roboid_cheese_hat010_set_brightness_to',\n            },\n            paramsKeyMap: {\n                INDEX: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'cheese_hat010',\n            isNotFor: ['roboid'],\n            func(sprite, script) {\n                const index = script.getNumberValue('INDEX');\n                const robot = Entry.Roboid.getCheese(index);\n                return robot ? robot.hat010SetBrightnessTo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roboid.cheese_hat010_set_brightness(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Roboid;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robolink_codrone_diy.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.robolink_codrone_diy = \n{\n    id       : '4A.1',\n    name     : 'robolink_codrone_diy',\n    url      : 'http://www.robolink.co.kr',\n    imageName: 'robolink_codrone_diy.png',\n    title    : {\n        en: 'ROBOLINK CODRONE DIY',\n        ko: '로보링크 코드론 DIY',\n    },\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero() {\n        // 초기화\n        Entry.byrobot_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++) {\n            if (Entry.hw.portData['state_modeFlight'] == 0x10)\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x01, 0); // 드론, command = 0x01 (Stop)\n            }\n            else\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x07, 0x12); // 0x12 : FlightEvent::Landing\n            }\n            Entry.byrobot_base.transferBuzzer(0x20, 0, 0, 0);\n            Entry.byrobot_base.transferLightManual(0x10, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightManual(0x20, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightModeColor(0x10, 0x22, 200, 255, 0, 0); // LED 초기화(드론)\n            Entry.byrobot_base.transferLightModeColor(0x20, 0x22, 200, 255, 0, 0); // LED 초기화(조종기)\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.robolink_codrone_diy.setLanguage = function () {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                // 정보창\n                value_state_mode_system               : '시스템 모드',\n                value_state_mode_flight               : '비행 상태',\n                value_state_mode_control_flight       : '제어 방식',\n                value_state_mode_movement             : '동작 상태',\n                value_state_headless                  : '방향 기준',\n                value_state_control_speed             : '속도',\n                value_state_sensor_orientation        : '센서 방향',\n                value_state_battery                   : '배터리 잔량(%)',\n                value_altitude_temperature            : '드론의 온도',\n                value_altitude_pressure               : '기압',\n                value_altitude_altitude               : '해발 고도',\n                value_altitude_range_height           : '지면과의 거리',\n                value_position_x                      : '위치 X',\n                value_position_y                      : '위치 Y',\n                value_position_z                      : '위치 Z',\n                value_motion_accel_x                  : 'X방향 가속도',\n                value_motion_accel_y                  : 'Y방향 가속도',\n                value_motion_accel_z                  : 'Z방향 가속도',\n                value_motion_gyro_roll                : '롤 각속도',\n                value_motion_gyro_pitch               : '피치 각속도',\n                value_motion_gyro_yaw                 : '요우 각속도',\n                value_motion_angle_roll               : '롤',\n                value_motion_angle_pitch              : '피치',\n                value_motion_angle_yaw                : '요우',\n                value_trim_roll                       : '미세조정 롤값',\n                value_trim_pitch                      : '미세조정 피치값',\n                value_joystick_left_x                 : '왼쪽 조이스틱 X',\n                value_joystick_left_y                 : '왼쪽 조이스틱 Y',\n                value_joystick_left_direction         : '왼쪽 조이스틱 방향',\n                value_joystick_left_event             : '왼쪽 조이스틱 이벤트',\n                value_joystick_right_x                : '오른쪽 조이스틱 X',\n                value_joystick_right_y                : '오른쪽 조이스틱 Y',\n                value_joystick_right_direction        : '오른쪽 조이스틱 방향',\n                value_joystick_right_event            : '오른쪽 조이스틱 이벤트',\n                value_button_button                   : '버튼 입력',\n                value_button_event                    : '버튼 상태',\n                value_entry_hw_count_transfer_reserved: '전송 예정 데이터',\n\n                // 일반 블럭\n                common_light_color_red                  : '빨강',\n                common_light_color_yellow               : '노랑',\n                common_light_color_green                : '초록',\n                common_light_color_cyan                 : '하늘색',\n                common_light_color_blue                 : '파랑',\n                common_light_color_magenta              : '자홍',\n                common_light_color_white                : '흰색',\n                common_light_color_black                : '검정',\n                common_light_color_cotton_candy         : '구름솜사탕',\n                common_light_color_emerald              : '에메랄드',\n                common_light_color_lavender             : '라벤더',\n                common_light_color_muscat               : '청포도',\n                common_light_color_strawberry_milk      : '딸기우유',\n                common_light_color_sunset               : '저녁노을',\n                common_light_mode_hold                  : '유지하기',\n                common_light_mode_flicker               : '깜빡이기',\n                common_light_mode_flicker_double        : '두번 깜빡이기',\n                common_light_mode_dimming               : '천천히 점멸',\n                common_light_mode_sunrise               : '천천히 밝아짐',\n                common_light_mode_sunset                : '천천히 어두워짐',\n                common_light_mode_rainbow               : '무지개',\n                common_light_mode_rainbow2              : '무지개2',\n                common_left                             : '왼쪽',\n                common_right                            : '오른쪽',\n                common_drone                            : '드론',\n                common_controller                       : '조종기',\n                common_wait                             : '기다리기',\n                common_next                             : '넘어가기',\n                controller_button_front_left            : '전면 왼쪽 버튼',\n                controller_button_front_right           : '전면 오른쪽 버튼',\n                controller_button_top_left              : '상단 왼쪽 버튼',\n                controller_button_top_right             : '상단 오른쪽 버튼',\n                controller_button_center_up             : '중앙 위 버튼',\n                controller_button_center_left           : '중앙 왼쪽 버튼',\n                controller_button_center_right          : '중앙 오른쪽 버튼',\n                controller_button_center_down           : '중앙 아래쪽 버튼',\n                controller_buzzer                       : '버저',\n                controller_buzzer_a                     : '라',\n                controller_buzzer_as                    : '라#',\n                controller_buzzer_b                     : '시',\n                controller_buzzer_c                     : '도',\n                controller_buzzer_cs                    : '도#',\n                controller_buzzer_d                     : '레',\n                controller_buzzer_ds                    : '레#',\n                controller_buzzer_e                     : '미',\n                controller_buzzer_f                     : '파',\n                controller_buzzer_fs                    : '파#',\n                controller_buzzer_g                     : '솔',\n                controller_buzzer_gs                    : '솔#',\n                controller_buzzer_mute                  : '쉼',\n                controller_buzzer_play                  : '연주',\n                controller_buzzer_reserve               : '예약',\n                controller_joystick_direction_left_up   : '왼쪽 위',\n                controller_joystick_direction_up        : '위',\n                controller_joystick_direction_right_up  : '오른쪽 위',\n                controller_joystick_direction_left      : '왼쪽',\n                controller_joystick_direction_center    : '중앙',\n                controller_joystick_direction_right     : '오른쪽',\n                controller_joystick_direction_left_down : '왼쪽 아래',\n                controller_joystick_direction_down      : '아래',\n                controller_joystick_direction_right_down: '오른쪽 아래',\n                controller_joystick_direction           : '방향',\n                controller_joystick_event               : '이벤트',\n                controller_joystick_x                   : '가로축',\n                controller_joystick_y                   : '세로축',\n                drone_level_1                           : '레벨 1',\n                drone_level_2                           : '레벨 2',\n                drone_level_3                           : '레벨 3',\n                drone_trim_roll_increase                : '롤 증가',\n                drone_trim_roll_decrease                : '롤 감소',\n                drone_trim_pitch_increase               : '피치 증가',\n                drone_trim_pitch_decrease               : '피치 감소',\n                drone_trim_yaw_increase                 : '요 증가',\n                drone_trim_yaw_decrease                 : '요 감소',\n                drone_trim_throttle_increase            : '쓰로틀 증가',\n                drone_trim_throttle_decrease            : '쓰로틀 감소',\n                drone_trim_reset                        : '초기화',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : '뒤',\n                drone_control_quad_pitch_forward        : '앞',\n                drone_control_quad_roll_left            : '왼쪽',\n                drone_control_quad_roll_right           : '오른쪽',\n                drone_control_quad_throttle_down        : '아래',\n                drone_control_quad_throttle_up          : '위',\n                drone_control_quad_yaw_ccw              : '반시계 방향',\n                drone_control_quad_yaw_cw               : '시계 방향',\n                drone_headless_off                      : '끄기',\n                drone_headless_on                       : '켜기',\n                drone_light_color_body                  : '몸체',\n                drone_light_manual_body_blue            : '파랑',\n                drone_light_manual_body_green           : '초록',\n                drone_light_manual_body_red             : '빨강',\n                drone_motor_rotation_clockwise          : '시계 방향',\n                drone_motor_rotation_counterclockwise   : '반시계 방향',\n            },\n\n            template: {\n                robolink_codrone_diy_drone_information                : '드론 정보 %1',\n                robolink_codrone_diy_drone_sensor                     : '센서값 %1',\n                robolink_codrone_diy_controller_value_button          : '%1',\n                robolink_codrone_diy_controller_value_button_event    : '%1',\n                robolink_codrone_diy_controller_value_joystick_left   : '왼쪽 조이스틱 %1',\n                robolink_codrone_diy_controller_value_joystick_right  : '오른쪽 조이스틱 %1',\n                robolink_codrone_diy_controller_if_button_press       : '조종기 %1 눌렀을 때',\n                robolink_codrone_diy_controller_if_joystick_direction : '조종기 %1 조이스틱 %2 (으)로 움직였을 때',\n                robolink_codrone_diy_drone_control_drone_takeoff      : '이륙하기 %1',\n                robolink_codrone_diy_drone_control_drone_landing      : '착륙하기 %1',\n                robolink_codrone_diy_drone_control_drone_stop         : '멈춤 %1',\n                robolink_codrone_diy_drone_trim_direction             : '미세조정 %1 %2',\n                robolink_codrone_diy_drone_trim                       : '미세조정 롤 %1, 피치 %2 %3',\n                robolink_codrone_diy_drone_speed                      : '속도 %1 %2',\n                robolink_codrone_diy_drone_sensor_reset               : '센서 초기화 %1',\n                robolink_codrone_diy_drone_control_headless           : '방향 고정 %1 %2',\n                robolink_codrone_diy_drone_control_drone_reset_heading: '방향 초기화 %1',\n                robolink_codrone_diy_drone_control_quad_one           : '드론 %1 %2% 정하기 %3',\n                robolink_codrone_diy_drone_control_quad_one_delay     : '드론 %1 %2% %3 초 실행 %4',\n                robolink_codrone_diy_drone_control_quad               : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% 정하기 %5',\n                robolink_codrone_diy_drone_control_quad_delay         : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5초 실행 %6',\n                robolink_codrone_diy_drone_control_position_one       : '드론 %1(으)로 %2m를 %3m/s로 이동 %4 %5',\n                robolink_codrone_diy_drone_control_position_turn      : '드론 %1(으)로 %2도를 %3deg/s로 회전 %4 %5',\n                robolink_codrone_diy_drone_control_position_location  : '드론 %1 %2m, %3 %4m, %5 %6m를 %7m/s로 이동 %8 %9',\n                robolink_codrone_diy_drone_motor_stop                 : '드론 모터 정지 %1',\n                robolink_codrone_diy_drone_motor_single               : '드론 %1번 모터를 %2(으)로 회전 %3',\n                robolink_codrone_diy_drone_light_manual_single_off    : '드론 LED 끄기 %1',\n                robolink_codrone_diy_drone_light_manual_single_input  : '드론 LED %1 밝기 %2 %3',\n                robolink_codrone_diy_drone_light_color_select         : '드론 LED %1 %2 %3 %4',\n                robolink_codrone_diy_drone_light_color_input          : '드론 LED R %1, G %2, B %3 %4 %5 %6',\n                robolink_codrone_diy_controller_buzzer_off            : '버저 끄기 %1',\n                robolink_codrone_diy_controller_buzzer_hz             : '%1Hz 소리를 %2초 %3 %4',\n                robolink_codrone_diy_controller_buzzer_scale          : '%1 옥타브 %2을(를) %3초 %4 %5',\n            },\n\n            Helper: {\n                robolink_codrone_diy_drone_information                : \"드론의 정보를 반환합니다.\",\n                robolink_codrone_diy_drone_sensor                     : \"드론 센서와 관련된 값들을 반환합니다.<br><br><font color='crimson'>롤</font> : 좌우 기울기(-90 ~ 90)<br><font color='crimson'>피치</font> : 앞뒤 기울기(-90 ~ 90)<br><font color='crimson'>요우</font> : 방향(-180 ~ 180)\",\n                robolink_codrone_diy_controller_value_button          : \"조종기 전체 버튼 입력 상태를 비트 플래그로 반환합니다.\",\n                robolink_codrone_diy_controller_value_button_event    : \"조종기 버튼 중 현재 사용 중인 버튼의 입력 상태를 반환합니다.\",\n                robolink_codrone_diy_controller_value_joystick_left   : \"조종기의 왼쪽 조이스틱과 관련된 값을 반환합니다.\",\n                robolink_codrone_diy_controller_value_joystick_right  : \"조종기의 오른쪽 조이스틱과 관련된 값을 반환합니다.\",\n                robolink_codrone_diy_controller_if_button_press       : \"지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.\",\n                robolink_codrone_diy_controller_if_joystick_direction : \"조종기의 조이스틱이 지정한 방향으로 움직였을 때 true를 반환합니다.\",\n                robolink_codrone_diy_drone_control_drone_takeoff      : \"드론을 이륙시킵니다.\",\n                robolink_codrone_diy_drone_control_drone_landing      : \"드론을 착륙시킵니다.\",\n                robolink_codrone_diy_drone_control_drone_stop         : \"드론 작동을 정지합니다.\",\n                robolink_codrone_diy_drone_trim_direction             : \"드론 미세 조정 설정을 현재 값에서 5단위로 증가시키거나 감소시킵니다.\",\n                robolink_codrone_diy_drone_trim                       : \"드론 미세 조정 설정을 변경합니다.\",\n                robolink_codrone_diy_drone_speed                      : \"드론 이동 속도를 변경합니다.\",\n                robolink_codrone_diy_drone_sensor_reset               : \"드론의 자이로 바이어스와 트림 설정을 초기화합니다.\",\n                robolink_codrone_diy_drone_control_headless           : \"드론 좌표 기준을 변경합니다.<br><br><font color='dodgerblue'>방향 고정 켜기</font>를 하면 '이륙 시'와 '방향초기화'를 했을 때 드론이 바라보는 방향이 0도로 고정됩니다. 이 때에는 Yaw를 조작하여 드론이 다른 방향을 보게 하여도 처음 지정한 방향을 기준으로 움직입니다.<br><font color='crimson'>방향 고정 끄기</font>를 선택하면 드론이 바라보는 방향이 0도가 됩니다.\",\n                robolink_codrone_diy_drone_control_drone_reset_heading: \"드론의 방향을 초기화합니다.<br><br><font color='dodgerblue'>방향 고정 켜기</font> 설정이 되어 있는 경우 이 블럭을 실행하면 드론이 바라보는 방향을 0으로 초기화합니다.\",\n                robolink_codrone_diy_drone_control_quad_one           : \"드론 조종 값을 지정합니다.<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.\",\n                robolink_codrone_diy_drone_control_quad_one_delay     : \"드론 조종 값을 지정합니다.<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.\",\n                robolink_codrone_diy_drone_control_quad               : \"드론 조종 값을 지정합니다.<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.\",\n                robolink_codrone_diy_drone_control_quad_delay         : \"드론 조종 값을 지정합니다.<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.\",\n                robolink_codrone_diy_drone_control_position_one       : \"드론의 방향과 거리, 이동 속도를 지정하여 지정한 위치로 이동합니다.<br><br>'기다리기'를 선택한 경우 동작이 끝나기까지 충분한 시간을 현재 블럭에서 기다립니다. '넘어가기'를 선택한 경우 블럭 실행 후 바로 다음 블럭으로 넘어갑니다.\",\n                robolink_codrone_diy_drone_control_position_turn      : \"드론의 회전 방향과 각도, 회전 속도를 지정하여 지정한 각도로 회전합니다.<br><br>'기다리기'를 선택한 경우 동작이 끝나기까지 충분한 시간을 현재 블럭에서 기다립니다. '넘어가기'를 선택한 경우 블럭 실행 후 바로 다음 블럭으로 넘어갑니다.\",\n                robolink_codrone_diy_drone_control_position_location  : \"드론의 X, Y, Z 축의 방향과 거리, 이동 속도를 설정하여 지정한 위치로 이동합니다.<br><br>'기다리기'를 선택한 경우 동작이 끝나기까지 충분한 시간을 현재 블럭에서 기다립니다. '넘어가기'를 선택한 경우 블럭 실행 후 바로 다음 블럭으로 넘어갑니다.\",\n                robolink_codrone_diy_drone_motor_stop                 : \"모든 모터의 작동을 정지합니다.\",\n                robolink_codrone_diy_drone_motor_single               : \"모터 제어 블럭입니다.<br><br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다.\",\n                robolink_codrone_diy_drone_light_manual_single_off    : \"드론의 모든 LED를 끕니다.\",\n                robolink_codrone_diy_drone_light_manual_single_input  : \"드론 LED를 조작하는데 사용합니다.<br><br>10진수(0 ~ 65535) 또는 16진수(0x00 ~ 0xFFFF) 값을 사용할 수 있습니다.<br>각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.\",\n                robolink_codrone_diy_drone_light_color_select         : \"미리 설정된 색상을 선택하여 드론의 LED를 제어하는 블럭입니다.\",\n                robolink_codrone_diy_drone_light_color_input          : \"Red, Green, Blue 값을 지정하여 드론의 LED를 제어하는 블럭입니다.\",\n                robolink_codrone_diy_controller_buzzer_off            : \"버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.\",\n                robolink_codrone_diy_controller_buzzer_scale          : \"지정한 옥타브의 음을 지정한 시간동안 연주하거나 예약합니다.<br><br><font color='dodgerblue'>연주</font>를 선택할 경우 소리를 즉시 연주하고, 연주를 명령한 시간동안 기다립니다. <font color='crimson'>예약</font>을 선택한 경우에는 소리를 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다.\",\n                robolink_codrone_diy_controller_buzzer_hz             : \"지정한 주파수의 소리를 지정한 시간동안 연주하거나 예약합니다.<br><br>권장 사용 범위는 250 ~ 8000 입니다.<br><br>4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다.<br><br><font color='dodgerblue'>연주</font>를 선택할 경우 소리를 즉시 연주하고, 연주를 명령한 시간동안 기다립니다. <font color='crimson'>예약</font>을 선택한 경우에는 소리를 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다.\",\n            },\n        },\n\n        en: {\n            Blocks: {\n                // 정보창\n                value_state_mode_flight               : 'Flight Mode',\n                value_state_mode_control_flight       : 'Control Mode',\n                value_state_mode_movement             : 'Movement',\n                value_state_headless                  : 'Headless',\n                value_state_control_speed             : 'Control Speed',\n                value_state_sensor_orientation        : 'Sensor Orientation',\n                value_state_battery                   : 'Battery',\n                value_altitude_temperature            : 'Temperature',\n                value_altitude_pressure               : 'Pressure',\n                value_altitude_altitude               : 'Altitude',\n                value_altitude_range_height           : 'Distance from ground',\n                value_position_x                      : 'Position X',\n                value_position_y                      : 'Position Y',\n                value_position_z                      : 'Position Z',\n                value_motion_accel_x                  : 'Accel X',\n                value_motion_accel_y                  : 'Accel Y',\n                value_motion_accel_z                  : 'Accel Z',\n                value_motion_gyro_roll                : 'Gyro Roll',\n                value_motion_gyro_pitch               : 'Gyro Pitch',\n                value_motion_gyro_yaw                 : 'Gyro Yaw',\n                value_motion_angle_roll               : 'Roll',\n                value_motion_angle_pitch              : 'Pitch',\n                value_motion_angle_yaw                : 'Yaw',\n                value_trim_roll                       : 'Trim Roll',\n                value_trim_pitch                      : 'Trim Pitch',\n                value_joystick_left_x                 : 'Left Joystick X',\n                value_joystick_left_y                 : 'Left Joystick Y',\n                value_joystick_left_direction         : 'Left Joystick Direction',\n                value_joystick_left_event             : 'Left Joystick Event',\n                value_joystick_right_x                : 'Right Joystick X',\n                value_joystick_right_y                : 'Right Joystick Y',\n                value_joystick_right_direction        : 'Right Joystick Direction',\n                value_joystick_right_event            : 'Right Joystick Event',\n                value_button_button                   : 'Button',\n                value_button_event                    : 'Button Event',\n                value_entry_hw_count_transfer_reserved: 'Count of data to transfer',\n\n                // 일반 블럭\n                common_light_color_red                  : 'red',\n                common_light_color_yellow               : 'yellow',\n                common_light_color_green                : 'green',\n                common_light_color_cyan                 : 'cyan',\n                common_light_color_blue                 : 'blue',\n                common_light_color_magenta              : 'magenta',\n                common_light_color_white                : 'white',\n                common_light_color_black                : 'black',\n                common_light_color_cotton_candy         : 'cotton candy',\n                common_light_color_emerald              : 'emerald',\n                common_light_color_lavender             : 'lavender',\n                common_light_color_muscat               : 'muscat',\n                common_light_color_strawberry_milk      : 'strawberry milk',\n                common_light_color_sunset               : 'sunset',\n                common_light_mode_hold                  : 'hold',\n                common_light_mode_flicker               : 'flicker',\n                common_light_mode_flicker_double        : 'flicker double',\n                common_light_mode_dimming               : 'dimming',\n                common_light_mode_sunrise               : 'sunrise',\n                common_light_mode_sunset                : 'sunset',\n                common_light_mode_rainbow               : 'rainbow',\n                common_light_mode_rainbow2              : 'rainbow2',\n                common_left                             : 'left',\n                common_right                            : 'right',\n                common_drone                            : 'drone',\n                common_controller                       : 'controller',\n                common_wait                             : 'wait',\n                common_next                             : 'next',\n                controller_button_front_left            : 'Front left button',\n                controller_button_front_right           : 'Front right button',\n                controller_button_top_left              : 'Top left button',\n                controller_button_top_right             : 'Top right button',\n                controller_button_center_up             : 'Trim up button',\n                controller_button_center_left           : 'Trim left button',\n                controller_button_center_right          : 'Trim right button',\n                controller_button_center_down           : 'Trim down button',\n                controller_buzzer                       : 'buzzer',\n                controller_buzzer_a                     : 'A',\n                controller_buzzer_as                    : 'A#',\n                controller_buzzer_b                     : 'B',\n                controller_buzzer_c                     : 'C',\n                controller_buzzer_cs                    : 'C#',\n                controller_buzzer_d                     : 'D',\n                controller_buzzer_ds                    : 'D#',\n                controller_buzzer_e                     : 'E',\n                controller_buzzer_f                     : 'F',\n                controller_buzzer_fs                    : 'F#',\n                controller_buzzer_g                     : 'G',\n                controller_buzzer_gs                    : 'G#',\n                controller_buzzer_mute                  : 'mute',\n                controller_buzzer_play                  : 'play',\n                controller_buzzer_reserve               : 'reserve',\n                controller_joystick_direction_left_up   : 'Left top',\n                controller_joystick_direction_up        : 'Top',\n                controller_joystick_direction_right_up  : 'Right top',\n                controller_joystick_direction_left      : 'Left',\n                controller_joystick_direction_center    : 'Center',\n                controller_joystick_direction_right     : 'Right',\n                controller_joystick_direction_left_down : 'Left Bottom',\n                controller_joystick_direction_down      : 'Bottom',\n                controller_joystick_direction_right_down: 'Right Bottom',\n                controller_joystick_direction           : 'direction',\n                controller_joystick_event               : 'event',\n                controller_joystick_x                   : 'X',\n                controller_joystick_y                   : 'Y',\n                drone_level_1                           : 'Level 1',\n                drone_level_2                           : 'Level 2',\n                drone_level_3                           : 'Level 2',\n                drone_trim_roll_increase                : 'Roll increase',\n                drone_trim_roll_decrease                : 'Roll decrease',\n                drone_trim_pitch_increase               : 'Pitch increase',\n                drone_trim_pitch_decrease               : 'Pitch decrease',\n                drone_trim_yaw_increase                 : 'Yaw increase',\n                drone_trim_yaw_decrease                 : 'Yaw decrease',\n                drone_trim_throttle_increase            : 'Throttle increase',\n                drone_trim_throttle_decrease            : 'Throttle decrease',\n                drone_trim_reset                        : 'Reset Trim',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : 'Backward',\n                drone_control_quad_pitch_forward        : 'Forward',\n                drone_control_quad_roll_left            : 'Left',\n                drone_control_quad_roll_right           : 'Right',\n                drone_control_quad_throttle_down        : 'Down',\n                drone_control_quad_throttle_up          : 'Up',\n                drone_control_quad_yaw_ccw              : 'Counterclockwise',\n                drone_control_quad_yaw_cw               : 'Clockwise',\n                drone_headless_off                      : 'Off',\n                drone_headless_on                       : 'On',\n                drone_light_color_body                  : 'Body',\n                drone_light_manual_body_blue            : 'Blue',\n                drone_light_manual_body_green           : 'Green',\n                drone_light_manual_body_red             : 'Red',\n                drone_motor_rotation_clockwise          : 'Clockwise',\n                drone_motor_rotation_counterclockwise   : 'Counterclockwise',\n            },\n\n            template: {\n                robolink_codrone_diy_drone_information                : 'Drone information %1',\n                robolink_codrone_diy_drone_sensor                     : 'Sensor %1',\n                robolink_codrone_diy_controller_value_button          : '%1',\n                robolink_codrone_diy_controller_value_button_event    : '%1',\n                robolink_codrone_diy_controller_value_joystick_left   : 'Left joystick %1',\n                robolink_codrone_diy_controller_value_joystick_right  : 'Right joystick %1',\n                robolink_codrone_diy_controller_if_button_press       : 'when press %1',\n                robolink_codrone_diy_controller_if_joystick_direction : 'when %1 stick move to %2',\n                robolink_codrone_diy_drone_control_drone_takeoff      : 'Takeoff %1',\n                robolink_codrone_diy_drone_control_drone_landing      : 'Landing %1',\n                robolink_codrone_diy_drone_control_drone_stop         : 'Stop %1',\n                robolink_codrone_diy_drone_trim_direction             : 'Trim %1 %2',\n                robolink_codrone_diy_drone_trim                       : 'Trim Roll %1%, Pitch %2% %3',\n                robolink_codrone_diy_drone_speed                      : 'Speed %1 %2',\n                robolink_codrone_diy_drone_sensor_reset               : 'Sensor reset %1',\n                robolink_codrone_diy_drone_control_headless           : 'Headless %1 %2',\n                robolink_codrone_diy_drone_control_drone_reset_heading: 'Reset heading %1',\n                robolink_codrone_diy_drone_control_quad_one           : 'Set %1 %2% %3',\n                robolink_codrone_diy_drone_control_quad_one_delay     : 'Set %1 %2% %3 sec %4',\n                robolink_codrone_diy_drone_control_quad               : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5',\n                robolink_codrone_diy_drone_control_quad_delay         : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% for %5sec %6',\n                robolink_codrone_diy_drone_control_position_one       : 'Move %2 meter(s) %1 to %3 m/s %4 %5',\n                robolink_codrone_diy_drone_control_position_turn      : 'Rotate %2 degree(s) %1 to %3 deg/s %4 %5',\n                robolink_codrone_diy_drone_control_position_location  : 'Move %2 meter(s) %1, %4 meter(s) %3, %6 meter(s) %5 to %7 m/s %8 %9',\n                robolink_codrone_diy_drone_motor_stop                 : 'Motor stop %1',\n                robolink_codrone_diy_drone_motor_single               : 'No. %1 Motor rotate for %2 %3',\n                robolink_codrone_diy_drone_light_manual_single_off    : 'Drone LED Off %1',\n                robolink_codrone_diy_drone_light_manual_single_input  : 'Drone LED %1 lightness %2 %3',\n                robolink_codrone_diy_drone_light_color_select         : 'Drone LED %1 %2 %3 %4',\n                robolink_codrone_diy_drone_light_color_input          : 'Drone LED R %1, G %2, B %3 %4 %5 %6',\n                robolink_codrone_diy_controller_buzzer_off            : 'turn off the buzzer %1',\n                robolink_codrone_diy_controller_buzzer_scale          : '%4 %1 octave %2 for %3 second %5',\n                robolink_codrone_diy_controller_buzzer_hz             : '%3 %1 Hz for %2 second %4',\n            },\n\n            Helper: {\n                robolink_codrone_diy_drone_information                : '',\n                robolink_codrone_diy_drone_sensor                     : '',\n                robolink_codrone_diy_controller_value_button          : '',\n                robolink_codrone_diy_controller_value_button_event    : '',\n                robolink_codrone_diy_controller_value_joystick_left   : '',\n                robolink_codrone_diy_controller_value_joystick_right  : '',\n                robolink_codrone_diy_controller_if_button_press       : '',\n                robolink_codrone_diy_controller_if_joystick_direction : '',\n                robolink_codrone_diy_drone_control_drone_takeoff      : '',\n                robolink_codrone_diy_drone_control_drone_landing      : '',\n                robolink_codrone_diy_drone_control_drone_stop         : '',\n                robolink_codrone_diy_drone_trim_direction             : '',\n                robolink_codrone_diy_drone_trim                       : '',\n                robolink_codrone_diy_drone_speed                      : '',\n                robolink_codrone_diy_drone_sensor_reset               : '',\n                robolink_codrone_diy_drone_control_headless           : '',\n                robolink_codrone_diy_drone_control_drone_reset_heading: '',\n                robolink_codrone_diy_drone_control_quad_one           : '',\n                robolink_codrone_diy_drone_control_quad_one_delay     : '',\n                robolink_codrone_diy_drone_control_quad               : '',\n                robolink_codrone_diy_drone_control_quad_delay         : '',\n                robolink_codrone_diy_drone_control_position_one       : '',\n                robolink_codrone_diy_drone_control_position_turn      : '',\n                robolink_codrone_diy_drone_control_position_location  : '',\n                robolink_codrone_diy_drone_motor_stop                 : '',\n                robolink_codrone_diy_drone_motor_single               : '',\n                robolink_codrone_diy_drone_light_manual_single_off    : '',\n                robolink_codrone_diy_drone_light_manual_single_input  : '',\n                robolink_codrone_diy_drone_light_color_select         : '',\n                robolink_codrone_diy_drone_light_color_input          : '',\n                robolink_codrone_diy_controller_buzzer_off            : '',\n                robolink_codrone_diy_controller_buzzer_scale          : '',\n                robolink_codrone_diy_controller_buzzer_hz             : '',\n            },\n        },\n    };\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.robolink_codrone_diy.monitorTemplate = function () {\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/robolink_codrone_diy.png\",   // 배경 이미지\n        width  : 256,                             // 이미지의 폭\n        height : 256,                             // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeFlight             : { name: Lang.Blocks.value_state_mode_flight, type: 'input', pos: { x: 0, y: 0 } },\n            state_modeControlFlight      : { name: Lang.Blocks.value_state_mode_control_flight, type: 'input', pos: { x: 0, y: 0 } },\n            state_modeMovement           : { name: Lang.Blocks.value_state_mode_movement, type: 'input', pos: { x: 0, y: 0 } },\n            state_headless               : { name: Lang.Blocks.value_state_headless, type: 'input', pos: { x: 0, y: 0 } },\n            state_controlSpeed           : { name: Lang.Blocks.value_state_control_speed, type: 'input', pos: { x: 0, y: 0 } },\n            state_sensorOrientation      : { name: Lang.Blocks.value_state_sensor_orientation, type: 'input', pos: { x: 0, y: 0 } },\n            state_battery                : { name: Lang.Blocks.value_state_battery, type: 'input', pos: { x: 0, y: 0 } },\n            altitude_temperature         : { name: Lang.Blocks.value_altitude_temperature, type: 'input', pos: { x: 0, y: 0 } },\n            altitude_pressure            : { name: Lang.Blocks.value_altitude_pressure, type: 'input', pos: { x: 0, y: 0 } },\n            altitude_altitude            : { name: Lang.Blocks.value_altitude_altitude, type: 'input', pos: { x: 0, y: 0 } },\n            altitude_rangeHeight         : { name: Lang.Blocks.value_altitude_range_height, type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelX                : { name: Lang.Blocks.value_motion_accel_x, type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelY                : { name: Lang.Blocks.value_motion_accel_y, type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelZ                : { name: Lang.Blocks.value_motion_accel_z, type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroRoll              : { name: Lang.Blocks.value_motion_gyro_roll, type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroPitch             : { name: Lang.Blocks.value_motion_gyro_pitch, type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroYaw               : { name: Lang.Blocks.value_motion_gyro_yaw, type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleRoll             : { name: Lang.Blocks.value_motion_angle_roll, type: 'input', pos: { x: 0, y: 0 } },\n            motion_anglePitch            : { name: Lang.Blocks.value_motion_angle_pitch, type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleYaw              : { name: Lang.Blocks.value_motion_angle_yaw, type: 'input', pos: { x: 0, y: 0 } },\n            trim_roll                    : { name: Lang.Blocks.value_trim_roll, type: 'input', pos: { x: 0, y: 0 } },\n            trim_pitch                   : { name: Lang.Blocks.value_trim_pitch, type: 'input', pos: { x: 0, y: 0 } },\n            position_x                   : { name: Lang.Blocks.value_position_x, type: 'input', pos: { x: 0, y: 0 } },\n            position_y                   : { name: Lang.Blocks.value_position_y, type: 'input', pos: { x: 0, y: 0 } },\n            position_z                   : { name: Lang.Blocks.value_position_z, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_x              : { name: Lang.Blocks.value_joystick_left_x, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_y              : { name: Lang.Blocks.value_joystick_left_y, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_direction      : { name: Lang.Blocks.value_joystick_left_direction, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_event          : { name: Lang.Blocks.value_joystick_left_event, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_x             : { name: Lang.Blocks.value_joystick_right_x, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_y             : { name: Lang.Blocks.value_joystick_right_y, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_direction     : { name: Lang.Blocks.value_joystick_right_direction, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_event         : { name: Lang.Blocks.value_joystick_right_event, type: 'input', pos: { x: 0, y: 0 } },\n            button_button                : { name: Lang.Blocks.value_button_button, type: 'input', pos: { x: 0, y: 0 } },\n            button_event                 : { name: Lang.Blocks.value_button_event, type: 'input', pos: { x: 0, y: 0 } },\n            entryhw_countTransferReserved: { name: Lang.Blocks.value_entry_hw_count_transfer_reserved, type: 'output', pos: { x: 0, y: 0 } },\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both',   // 표시 모드\n    };\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 블록명(다른 장치의 블록 이름과 달라야 함)\n ***************************************************************************************/\nEntry.robolink_codrone_diy.blockMenuBlocks = [\n    'robolink_codrone_diy_drone_information',\n    'robolink_codrone_diy_drone_sensor',\n    'robolink_codrone_diy_controller_value_button',\n    'robolink_codrone_diy_controller_value_button_event',\n    'robolink_codrone_diy_controller_value_joystick_left',\n    'robolink_codrone_diy_controller_value_joystick_right',\n    'robolink_codrone_diy_controller_if_button_press',\n    'robolink_codrone_diy_controller_if_joystick_direction',\n    'robolink_codrone_diy_drone_control_drone_takeoff',\n    'robolink_codrone_diy_drone_control_drone_landing',\n    'robolink_codrone_diy_drone_control_drone_stop',\n    'robolink_codrone_diy_drone_trim_direction',\n    'robolink_codrone_diy_drone_trim',\n    'robolink_codrone_diy_drone_speed',\n    'robolink_codrone_diy_drone_sensor_reset',\n    'robolink_codrone_diy_drone_control_headless',\n    'robolink_codrone_diy_drone_control_drone_reset_heading',\n    'robolink_codrone_diy_drone_control_quad_one',\n    'robolink_codrone_diy_drone_control_quad_one_delay',\n    'robolink_codrone_diy_drone_control_quad',\n    'robolink_codrone_diy_drone_control_quad_delay',\n    'robolink_codrone_diy_drone_control_position_one',\n    'robolink_codrone_diy_drone_control_position_turn',\n    'robolink_codrone_diy_drone_control_position_location',\n    'robolink_codrone_diy_drone_motor_stop',\n    'robolink_codrone_diy_drone_motor_single',\n    'robolink_codrone_diy_drone_light_manual_single_off',\n    'robolink_codrone_diy_drone_light_manual_single_input',\n    'robolink_codrone_diy_drone_light_color_select',\n    'robolink_codrone_diy_drone_light_color_input',\n    'robolink_codrone_diy_controller_buzzer_off',\n    'robolink_codrone_diy_controller_buzzer_scale',\n    'robolink_codrone_diy_controller_buzzer_hz',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 정의\n ***************************************************************************************/\nEntry.robolink_codrone_diy.getBlocks = function () {\n    return {\n        robolink_codrone_diy_drone_information: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.value_state_mode_flight, 'state_modeFlight'],\n                        [Lang.Blocks.value_state_mode_control_flight, 'state_modeControlFlight'],\n                        [Lang.Blocks.value_state_mode_movement, 'state_modeMovement'],\n                        [Lang.Blocks.value_state_headless, 'state_headless'],\n                        [Lang.Blocks.value_state_control_speed, 'state_controlSpeed'],\n                        [Lang.Blocks.value_trim_pitch, 'trim_pitch'],\n                        [Lang.Blocks.value_trim_roll, 'trim_roll'],\n                        [Lang.Blocks.value_state_sensor_orientation, 'state_sensorOrientation'],\n                        [Lang.Blocks.value_state_battery, 'state_battery'],\n                    ],\n                    value     : 'state_modeFlight',                     // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_information',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        robolink_codrone_diy_drone_sensor: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.value_motion_angle_roll, 'motion_angleRoll'],\n                        [Lang.Blocks.value_motion_angle_pitch, 'motion_anglePitch'],\n                        [Lang.Blocks.value_motion_angle_yaw, 'motion_angleYaw'],\n                        [Lang.Blocks.value_altitude_range_height, 'altitude_rangeHeight'],\n                        [Lang.Blocks.value_position_x, 'informationAssembledForEntry_positionX'],\n                        [Lang.Blocks.value_position_y, 'informationAssembledForEntry_positionY'],\n                        [Lang.Blocks.value_position_z, 'informationAssembledForEntry_positionZ'],\n                        [Lang.Blocks.value_altitude_temperature, 'altitude_temperature'],\n                        [Lang.Blocks.value_altitude_pressure, 'altitude_pressure'],\n                    ],\n                    value     : 'motion_angleRoll',     // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_sensor',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        robolink_codrone_diy_controller_value_button: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.value_button_button,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_diy_controller_value_button',\n            },\n            paramsKeyMap: {\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const button = Entry.hw.portData['button_button'];\n                if( button == undefined )\n                {\n                    return 0;\n                }\n                return button;\n            },\n        },\n\n\n        robolink_codrone_diy_controller_value_button_event: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.value_button_event,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_diy_controller_value_button_event',\n            },\n            paramsKeyMap: {\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const button_event = Entry.hw.portData['button_event'];\n                if( button_event == undefined )\n                {\n                    return 0;\n                }\n                return button_event;\n            },\n        },\n\n\n        robolink_codrone_diy_controller_value_joystick_left: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_x, 'joystick_left_x'],\n                        [Lang.Blocks.controller_joystick_y, 'joystick_left_y'],\n                        [Lang.Blocks.controller_joystick_direction, 'joystick_left_direction'],\n                        [Lang.Blocks.controller_joystick_event, 'joystick_left_event'],\n                    ],\n                    value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_diy_controller_value_joystick_left',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        robolink_codrone_diy_controller_value_joystick_right: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_x, 'joystick_right_x'],\n                        [Lang.Blocks.controller_joystick_y, 'joystick_right_y'],\n                        [Lang.Blocks.controller_joystick_direction, 'joystick_right_direction'],\n                        [Lang.Blocks.controller_joystick_event, 'joystick_right_event'],\n                    ],\n                    value     : 'joystick_right_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_diy_controller_value_joystick_right',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        robolink_codrone_diy_controller_if_button_press: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button_front_left, '1'],\n                        [Lang.Blocks.controller_button_front_right, '2'],\n                        [Lang.Blocks.controller_button_top_left, '4'],\n                        [Lang.Blocks.controller_button_top_right, '8'],\n                        [Lang.Blocks.controller_button_center_up, '16'],\n                        [Lang.Blocks.controller_button_center_left, '32'],\n                        [Lang.Blocks.controller_button_center_right, '128'],\n                        [Lang.Blocks.controller_button_center_down, '256'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_diy_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const read        = Entry.hw.portData;\n                const button      = 'button_button';    // paramsKeyMap에 정의된 이름 사용\n                const button_event = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n                \n                if (read[button] == script.getField('BUTTON') && read[button_event] == 2) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        robolink_codrone_diy_controller_if_joystick_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.common_right, 'joystick_right_direction'],\n                    ],\n                    value     : 'joystick_left_direction',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_direction_left_up, '17'],\n                        [Lang.Blocks.controller_joystick_direction_up, '18'],\n                        [Lang.Blocks.controller_joystick_direction_right_up, '20'],\n                        [Lang.Blocks.controller_joystick_direction_left, '33'],\n                        [Lang.Blocks.controller_joystick_direction_center, '34'],\n                        [Lang.Blocks.controller_joystick_direction_right, '36'],\n                        [Lang.Blocks.controller_joystick_direction_left_down, '65'],\n                        [Lang.Blocks.controller_joystick_direction_down, '66'],\n                        [Lang.Blocks.controller_joystick_direction_right_down, '68'],\n                    ],\n                    value     : '34',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_diy_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE   : 0,\n                DIRECTION: 1,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const read   = Entry.hw.portData;\n                const device = script.getField('DEVICE');  // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION')) {\n                    return true;\n                }\n                else {\n                    return false;\n                }\n            },\n        },\n\n\n\n        robolink_codrone_diy_drone_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'drone_light',\n            isNotFor    : ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.byrobot_base.setLightManual(script, 0x10, 0xff, 0);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x3F'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'robolink_codrone_diy_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x10, flags, brightness);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold, '2'],              // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker, '3'],           // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double, '4'],    // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming, '5'],           // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise, '6'],           // BodySunrise         = 0x26\n                        [Lang.Blocks.common_light_mode_sunset, '7'],            // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow, '8'],           // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2, '9'],          // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'robolink_codrone_diy_drone_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                const interval = script.getNumberValue('INTERVAL');\n                return Entry.byrobot_base.setLightModeColor(script, 0x10, mode, interval, red, green, blue);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red, 'red'],\n                        [Lang.Blocks.common_light_color_green, 'green'],\n                        [Lang.Blocks.common_light_color_blue, 'blue'],\n                        [Lang.Blocks.common_light_color_yellow, 'yellow'],\n                        [Lang.Blocks.common_light_color_magenta, 'magenta'],\n                        [Lang.Blocks.common_light_color_cyan, 'cyan'],\n                        [Lang.Blocks.common_light_color_white, 'white'],\n                        [Lang.Blocks.common_light_color_sunset, 'sunset'],\n                        [Lang.Blocks.common_light_color_cotton_candy, 'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat, 'muscat'],\n                        [Lang.Blocks.common_light_color_strawberry_milk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald, 'emerald'],\n                        [Lang.Blocks.common_light_color_lavender, 'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold, '2'],              // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker, '3'],           // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double, '4'],    // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming, '5'],           // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise, '6'],           // BodySunrise         = 0x26\n                        [Lang.Blocks.common_light_mode_sunset, '7'],            // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow, '8'],           // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2, '9'],          // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'robolink_codrone_diy_drone_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n        },\n\n\n        robolink_codrone_diy_controller_buzzer_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_diy_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class       : 'buzzer',\n            isNotFor    : ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.byrobot_base.setBuzzerStop(script, 0x20);\n            },\n        },\n\n\n        robolink_codrone_diy_controller_buzzer_scale: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c, '0'],\n                        [Lang.Blocks.controller_buzzer_cs, '1'],\n                        [Lang.Blocks.controller_buzzer_d, '2'],\n                        [Lang.Blocks.controller_buzzer_ds, '3'],\n                        [Lang.Blocks.controller_buzzer_e, '4'],\n                        [Lang.Blocks.controller_buzzer_f, '5'],\n                        [Lang.Blocks.controller_buzzer_fs, '6'],\n                        [Lang.Blocks.controller_buzzer_g, '7'],\n                        [Lang.Blocks.controller_buzzer_gs, '8'],\n                        [Lang.Blocks.controller_buzzer_a, '9'],\n                        [Lang.Blocks.controller_buzzer_as, '10'],\n                        [Lang.Blocks.controller_buzzer_b, '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_play,    1],\n                        [Lang.Blocks.controller_buzzer_reserve, 0],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                    null\n                ],\n                type: 'robolink_codrone_diy_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n                WAIT  : 3,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n                const wait   = script.getNumberValue('WAIT');\n\n                if (scale == -1) {\n                    if (wait == 1)\n                    {\n                        return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, true, true);\n                    }\n                    else\n                    {\n                        return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, false, false);\n                    }\n                } else {\n                    if (wait == 1)\n                    {\n                        return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, true, true);\n                    }\n                    else\n                    {\n                        return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, false, false);\n                    }\n                }\n            },\n        },\n\n\n        robolink_codrone_diy_controller_buzzer_hz: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_play,    1],\n                        [Lang.Blocks.controller_buzzer_reserve, 0],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['1000'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                    null,\n                ],\n                type: 'robolink_codrone_diy_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ   : 0,\n                TIME : 1,\n                WAIT : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                const wait = script.getNumberValue('WAIT');\n                \n                if (wait == 1)\n                {\n                    return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, true, true);\n                }\n                else\n                {\n                    return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, false, false);\n                }\n            },\n        },\n\n\n        robolink_codrone_diy_drone_motor_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'motor',\n            isNotFor    : ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_motor_single: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, { type: 'text', params: ['120'] }, null],\n                type  : 'robolink_codrone_diy_drone_motor_single',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const motorIndex = script.getNumberValue('MOTORINDEX') - 1;\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.byrobot_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_drone_takeoff: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_control_drone_takeoff',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x11, 5000); // 0x11 : FlightEvent::TakeOff\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_drone_landing: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_control_drone_landing',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x12, 5000); // 0x12 : FlightEvent::Landing\n            },\n        },\n\n        robolink_codrone_diy_drone_control_drone_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_control_drone_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_headless: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_headless_on, '1'],\n                        [Lang.Blocks.drone_headless_off, '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_diy_drone_control_headless',\n            },\n            paramsKeyMap: {\n                HEADLESS: 0,\n            },\n            class   : 'control_flight',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const headless = script.getField('HEADLESS');\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x03, headless);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_drone_reset_heading: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_control_drone_reset_heading',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x07, 0xA0); // 0x22 : CommandType::FlightEvent  // 0xA0 : FlightEvent::ResetHeading\n            },\n        },\n\n\n        robolink_codrone_diy_drone_trim_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_trim_pitch_increase, 'pitch_inc'],\n                        [Lang.Blocks.drone_trim_pitch_decrease, 'pitch_dec'],\n                        [Lang.Blocks.drone_trim_roll_increase, 'roll_inc'],\n                        [Lang.Blocks.drone_trim_roll_decrease, 'roll_dec'],\n                        [Lang.Blocks.drone_trim_reset, 'reset'],\n                    ],\n                    value     : 'pitch_inc',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_diy_drone_trim_direction',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class   : 'trim',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const direction = script.getField('DIRECTION');\n\n                let r = Entry.hw.portData['trim_roll'];\n                let p = Entry.hw.portData['trim_pitch'];\n                let y = Entry.hw.portData['trim_yaw'];\n                let t = Entry.hw.portData['trim_throttle'];\n\n                const interval = 5;\n\n                switch (direction)\n                {\n                    case    'pitch_inc': { p = p + interval; } break;\n                    case    'pitch_dec': { p = p - interval; } break;\n                    case    'roll_inc':  { r = r + interval; } break;\n                    case    'roll_dec':  { r = r - interval; } break;\n                    case    'reset':     { r=0; p=0; y=0; t=0; } break;\n                    default: break;\n                }\n\n                return Entry.byrobot_base.sendTrim(script, 0x10, r, p, y, t);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_trim: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    null,\n                ],\n                type: 'robolink_codrone_diy_drone_trim',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n            },\n            class   : 'trim',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const r = script.getNumberValue('ROLL');\n                const p = script.getNumberValue('PITCH');\n                const y = Entry.hw.portData['trim_yaw'];\n                const t = Entry.hw.portData['trim_throttle'];\n\n                return Entry.byrobot_base.sendTrim(script, 0x10, r, p, y, t);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_speed: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_level_1, 1],\n                        [Lang.Blocks.drone_level_2, 2],\n                        [Lang.Blocks.drone_level_3, 3],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_diy_drone_speed',\n            },\n            paramsKeyMap: {\n                LEVEL: 0,\n            },\n            class   : 'trim',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const level = script.getField('LEVEL');\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x04, level);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_sensor_reset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_diy_drone_sensor_reset',\n            },\n            paramsKeyMap: {\n            },\n            class   : 'sensor',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x05, 0, 3000);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_quad_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll, 'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch, 'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw, 'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['0'] }, null],\n                type  : 'robolink_codrone_diy_drone_control_quad_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, 0, false);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_quad_one_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll, 'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch, 'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw, 'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['100'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_diy_drone_control_quad_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n                TIME         : 2,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n                const time          = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, time, true);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_quad: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    null,\n                ],\n                type: 'robolink_codrone_diy_drone_control_quad',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, 0, false);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_quad_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_diy_drone_control_quad_delay',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n                TIME    : 4,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n                const time     = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, time, true);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_position_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward, 'pitch_forward'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, 'pitch_backward'],\n                        [Lang.Blocks.drone_control_quad_roll_left, 'roll_left'],\n                        [Lang.Blocks.drone_control_quad_roll_right, 'roll_right'],\n                        [Lang.Blocks.drone_control_quad_throttle_up, 'throttle_up'],\n                        [Lang.Blocks.drone_control_quad_throttle_down, 'throttle_down'],\n                    ],\n                    value     : 'pitch_forward',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_next, 0],\n                        [Lang.Blocks.common_wait, 1],\n                    ],\n                    value     : 0,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['1'] }, { type: 'number', params: ['1'] }, null, null],\n                type  : 'robolink_codrone_diy_drone_control_position_one',\n            },\n            paramsKeyMap: {\n                CONTROLDIRECTION: 0,\n                DISTANCE        : 1,\n                SPEED           : 2,\n                WAIT            : 3,\n            },\n            class   : 'control_position',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const controlDirection = script.getField('CONTROLDIRECTION');\n                const distance         = script.getNumberValue('DISTANCE');\n                const speed            = script.getNumberValue('SPEED');\n                const wait             = script.getNumberValue('WAIT');\n                let   time             = 40;\n\n                if (speed > 0 && wait == 1) {\n                    time = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                let x = 0;\n                let y = 0;\n                let z = 0;\n\n                switch (controlDirection) {\n                    case    'pitch_forward': x  = distance; break;\n                    case    'pitch_backward': x = -distance; break;\n                    case    'roll_left': y      = distance; break;\n                    case    'roll_right': y     = -distance; break;\n                    case    'throttle_up': z    = distance; break;\n                    default: z                  = -distance; break;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, x, y, z, speed, 0, 0, time, true);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_position_turn: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_yaw_cw, '-1'],\n                        [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_next, 0],\n                        [Lang.Blocks.common_wait, 1],\n                    ],\n                    value     : 0,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['90'] },\n                    { type: 'number', params: ['45'] },\n                    null,\n                    null\n                ],\n                type: 'robolink_codrone_diy_drone_control_position_turn',\n            },\n            paramsKeyMap: {\n                DIRECTION_YAW: 0,\n                DEGREE_YAW   : 1,\n                SPEED_YAW    : 2,\n                WAIT         : 3,\n            },\n            class   : 'control_position',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const directionYaw = script.getNumberValue('DIRECTION_YAW');\n                const degree       = script.getNumberValue('DEGREE_YAW');\n                const yaw          = directionYaw * degree;\n                const speedYaw     = script.getNumberValue('SPEED_YAW');\n                const wait         = script.getNumberValue('WAIT');\n\n                let time = 40;\n\n                if (speedYaw > 0 && wait == 1) {\n                    time = Math.abs(degree / speedYaw) * 2 * 1000 + 3000;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, 0, 0, 0, 0, yaw, speedYaw, time, true);\n            },\n        },\n\n\n        robolink_codrone_diy_drone_control_position_location: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward, '+1'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll_left, '+1'],\n                        [Lang.Blocks.drone_control_quad_roll_right, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_throttle_up, '+1'],\n                        [Lang.Blocks.drone_control_quad_throttle_down, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_next, 0],\n                        [Lang.Blocks.common_wait, 1],\n                    ],\n                    value     : 0,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                    null\n                ],\n                type: 'robolink_codrone_diy_drone_control_position_location',\n            },\n            paramsKeyMap: {\n                DIRECTION_PITCH   : 0,\n                DISTANCE_PITCH    : 1,\n                DIRECTION_ROLL    : 2,\n                DISTANCE_ROLL     : 3,\n                DIRECTION_THROTTLE: 4,\n                DISTANCE_THROTTLE : 5,\n                SPEED             : 6,\n                WAIT              : 7,\n            },\n            class   : 'control_position',\n            isNotFor: ['robolink_codrone_diy'],\n            func(sprite, script) {\n                const directionPitch    = script.getNumberValue('DIRECTION_PITCH');\n                const directionRoll     = script.getNumberValue('DIRECTION_ROLL');\n                const directionThrottle = script.getNumberValue('DIRECTION_THROTTLE');\n\n                const x = directionPitch * script.getNumberValue('DISTANCE_PITCH');\n                const y = directionRoll * script.getNumberValue('DISTANCE_ROLL');\n                const z = directionThrottle * script.getNumberValue('DISTANCE_THROTTLE');\n\n                const distance = Math.sqrt((x * x) + (y * y) + (z * z));\n\n                const speed = script.getNumberValue('SPEED');\n                const wait  = script.getNumberValue('WAIT');\n\n                let time = 40;\n\n                if (speed > 0 && wait == 1) {\n                    time = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                return Entry.byrobot_base.sendControlPosition(script, 0x10, x, y, z, speed, 0, 0, time, true);\n            },\n        },\n    };\n};\n\n\nmodule.exports = Entry.robolink_codrone_diy;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robolink_codrone_edu.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n\n/***************************************************************************************\n *  장치 사용 함수\n ***************************************************************************************/\n\n Entry.robolink_base = \n {\n     /***************************************************************************************\n      *  시간 지연 함수\n      ***************************************************************************************/\n \n     // 시간 지연\n     checkFinish(script, ms)\n     {\n         const _ms = this.fit(0, ms, 60000);\n \n         if (!script.isStart)\n         {\n             script.isStart  = true;\n             script.timeFlag = 1;\n \n             const fps       = Entry.FPS || 60;\n             const timeValue = (60 / fps) * _ms;\n \n             setTimeout(() => {\n                 script.timeFlag = 0;\n             }, timeValue);\n \n             return 'Start';\n         }\n         else if (script.timeFlag == 1)\n         {\n             return 'Running';\n         }\n         else\n         {\n             delete script.timeFlag;\n             delete script.isStart;\n             Entry.engine.isContinue = false;\n             return 'Finish';\n         }\n     },\n \n \n     /***************************************************************************************\n      *  기능 함수\n      ***************************************************************************************/\n \n     transferBufferClear()\n     {\n         Entry.hw.sendQueue.buffer_clear = 0;\n         Entry.hw.update();\n         delete Entry.hw.sendQueue.buffer_clear;\n     },\n \n \n     fit(min, value, max)\n     {\n         return Math.max(Math.min(value, max), min);\n     },\n \n \n     /***************************************************************************************\n      *  데이터 전송 함수 (Entry -> Hardware)\n      ***************************************************************************************/\n \n     // -- IR -----------------------------------------------------------------------------\n     transferIrMessage(target, irmessage)\n     {\n         // 전송\n         Entry.hw.sendQueue.target            = target;\n         Entry.hw.sendQueue.battle_ir_message = irmessage;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.battle_ir_message;\n     },\n \n \n     // -- Light -----------------------------------------------------------------------------\n     transferLightManual(target, flags, brightness)\n     {\n         Entry.hw.sendQueue.target                  = target;\n         Entry.hw.sendQueue.light_manual_flags      = flags;\n         Entry.hw.sendQueue.light_manual_brightness = brightness;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.light_manual_flags;\n         delete Entry.hw.sendQueue.light_manual_brightness;\n     },\n \n \n     transferLightMode(target, mode, interval)\n     {\n         Entry.hw.sendQueue.target              = target;\n         Entry.hw.sendQueue.light_mode_mode     = mode;\n         Entry.hw.sendQueue.light_mode_interval = interval;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.light_mode_mode;\n         delete Entry.hw.sendQueue.light_mode_interval;\n     },\n \n \n     transferLightModeColor(target, mode, interval, red, green, blue)\n     {\n         Entry.hw.sendQueue.target              = target;\n         Entry.hw.sendQueue.light_mode_mode     = mode;\n         Entry.hw.sendQueue.light_mode_interval = interval;\n         Entry.hw.sendQueue.light_color_r       = red;\n         Entry.hw.sendQueue.light_color_g       = green;\n         Entry.hw.sendQueue.light_color_b       = blue;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.light_mode_mode;\n         delete Entry.hw.sendQueue.light_mode_interval;\n         delete Entry.hw.sendQueue.light_color_r;\n         delete Entry.hw.sendQueue.light_color_g;\n         delete Entry.hw.sendQueue.light_color_b;\n     },\n \n \n     transferLightEvent(target, event, interval, repeat)\n     {\n         Entry.hw.sendQueue.target               = target;\n         Entry.hw.sendQueue.light_event_event    = event;\n         Entry.hw.sendQueue.light_event_interval = interval;\n         Entry.hw.sendQueue.light_event_repeat   = repeat;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.light_event_event;\n         delete Entry.hw.sendQueue.light_event_interval;\n         delete Entry.hw.sendQueue.light_event_repeat;\n     },\n \n \n     transferLightEventColor(target, event, interval, repeat, red, green, blue)\n     {\n         Entry.hw.sendQueue.target               = target;\n         Entry.hw.sendQueue.light_event_event    = event;\n         Entry.hw.sendQueue.light_event_interval = interval;\n         Entry.hw.sendQueue.light_event_repeat   = repeat;\n         Entry.hw.sendQueue.light_color_r        = red;\n         Entry.hw.sendQueue.light_color_g        = green;\n         Entry.hw.sendQueue.light_color_b        = blue;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.light_event_event;\n         delete Entry.hw.sendQueue.light_event_interval;\n         delete Entry.hw.sendQueue.light_event_repeat;\n         delete Entry.hw.sendQueue.light_color_r;\n         delete Entry.hw.sendQueue.light_color_g;\n         delete Entry.hw.sendQueue.light_color_b;\n     },\n \n \n     // -- Display -----------------------------------------------------------------------------\n     transferDisplayClearAll(target, pixel)\n     {\n         Entry.hw.sendQueue.target                  = target;\n         Entry.hw.sendQueue.display_clear_all_pixel = pixel;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_clear_all_pixel;\n     },\n \n \n     transferDisplayClear(target, pixel, x, y, width, height)\n     {\n         Entry.hw.sendQueue.target               = target;\n         Entry.hw.sendQueue.display_clear_x      = x;\n         Entry.hw.sendQueue.display_clear_y      = y;\n         Entry.hw.sendQueue.display_clear_width  = width;\n         Entry.hw.sendQueue.display_clear_height = height;\n         Entry.hw.sendQueue.display_clear_pixel  = pixel;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_clear_x;\n         delete Entry.hw.sendQueue.display_clear_y;\n         delete Entry.hw.sendQueue.display_clear_width;\n         delete Entry.hw.sendQueue.display_clear_height;\n         delete Entry.hw.sendQueue.display_clear_pixel;\n     },\n \n \n     transferDisplayInvert(target, x, y, width, height)\n     {\n         Entry.hw.sendQueue.target                = target;\n         Entry.hw.sendQueue.display_invert_x      = x;\n         Entry.hw.sendQueue.display_invert_y      = y;\n         Entry.hw.sendQueue.display_invert_width  = width;\n         Entry.hw.sendQueue.display_invert_height = height;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_invert_x;\n         delete Entry.hw.sendQueue.display_invert_y;\n         delete Entry.hw.sendQueue.display_invert_width;\n         delete Entry.hw.sendQueue.display_invert_height;\n     },\n \n \n     transferDisplayDrawPoint(target, x, y, pixel)\n     {\n         Entry.hw.sendQueue.target                   = target;\n         Entry.hw.sendQueue.display_draw_point_x     = x;\n         Entry.hw.sendQueue.display_draw_point_y     = y;\n         Entry.hw.sendQueue.display_draw_point_pixel = pixel;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_draw_point_x;\n         delete Entry.hw.sendQueue.display_draw_point_y;\n         delete Entry.hw.sendQueue.display_draw_point_pixel;\n     },\n \n \n     transferDisplayDrawLine(target, x1, y1, x2, y2, pixel, line)\n     {\n         Entry.hw.sendQueue.target                  = target;\n         Entry.hw.sendQueue.display_draw_line_x1    = x1;\n         Entry.hw.sendQueue.display_draw_line_y1    = y1;\n         Entry.hw.sendQueue.display_draw_line_x2    = x2;\n         Entry.hw.sendQueue.display_draw_line_y2    = y2;\n         Entry.hw.sendQueue.display_draw_line_pixel = pixel;\n         Entry.hw.sendQueue.display_draw_line_line  = line;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_draw_line_x1;\n         delete Entry.hw.sendQueue.display_draw_line_y1;\n         delete Entry.hw.sendQueue.display_draw_line_x2;\n         delete Entry.hw.sendQueue.display_draw_line_y2;\n         delete Entry.hw.sendQueue.display_draw_line_pixel;\n         delete Entry.hw.sendQueue.display_draw_line_line;\n     },\n \n \n     transferDisplayDrawRect(target, x, y, width, height, pixel, flagFill, line)\n     {\n         Entry.hw.sendQueue.target                     = target;\n         Entry.hw.sendQueue.display_draw_rect_x        = x;\n         Entry.hw.sendQueue.display_draw_rect_y        = y;\n         Entry.hw.sendQueue.display_draw_rect_width    = width;\n         Entry.hw.sendQueue.display_draw_rect_height   = height;\n         Entry.hw.sendQueue.display_draw_rect_pixel    = pixel;\n         Entry.hw.sendQueue.display_draw_rect_flagfill = flagFill;\n         Entry.hw.sendQueue.display_draw_rect_line     = line;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_draw_rect_x;\n         delete Entry.hw.sendQueue.display_draw_rect_y;\n         delete Entry.hw.sendQueue.display_draw_rect_width;\n         delete Entry.hw.sendQueue.display_draw_rect_height;\n         delete Entry.hw.sendQueue.display_draw_rect_pixel;\n         delete Entry.hw.sendQueue.display_draw_rect_flagfill;\n         delete Entry.hw.sendQueue.display_draw_rect_line;\n     },\n \n \n     transferDisplayDrawCircle(target, x, y, radius, pixel, flagFill)\n     {\n         Entry.hw.sendQueue.target                       = target;\n         Entry.hw.sendQueue.display_draw_circle_x        = x;\n         Entry.hw.sendQueue.display_draw_circle_y        = y;\n         Entry.hw.sendQueue.display_draw_circle_radius   = radius;\n         Entry.hw.sendQueue.display_draw_circle_pixel    = pixel;\n         Entry.hw.sendQueue.display_draw_circle_flagfill = flagFill;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_draw_circle_x;\n         delete Entry.hw.sendQueue.display_draw_circle_y;\n         delete Entry.hw.sendQueue.display_draw_circle_radius;\n         delete Entry.hw.sendQueue.display_draw_circle_pixel;\n         delete Entry.hw.sendQueue.display_draw_circle_flagfill;\n     },\n \n \n     transferDisplayDrawString(target, x, y, font, pixel, string)\n     {\n         Entry.hw.sendQueue.target                     = target;\n         Entry.hw.sendQueue.display_draw_string_x      = x;\n         Entry.hw.sendQueue.display_draw_string_y      = y;\n         Entry.hw.sendQueue.display_draw_string_font   = font;\n         Entry.hw.sendQueue.display_draw_string_pixel  = pixel;\n         Entry.hw.sendQueue.display_draw_string_string = string;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_draw_string_x;\n         delete Entry.hw.sendQueue.display_draw_string_y;\n         delete Entry.hw.sendQueue.display_draw_string_font;\n         delete Entry.hw.sendQueue.display_draw_string_pixel;\n         delete Entry.hw.sendQueue.display_draw_string_string;\n     },\n \n \n     transferDisplayDrawStringAlign(target, xStart, xEnd, y, align, font, pixel, string)\n     {\n         Entry.hw.sendQueue.target                            = target;\n         Entry.hw.sendQueue.display_draw_string_align_x_start = xStart;\n         Entry.hw.sendQueue.display_draw_string_align_x_end   = xEnd;\n         Entry.hw.sendQueue.display_draw_string_align_y       = y;\n         Entry.hw.sendQueue.display_draw_string_align_align   = align;\n         Entry.hw.sendQueue.display_draw_string_align_font    = font;\n         Entry.hw.sendQueue.display_draw_string_align_pixel   = pixel;\n         Entry.hw.sendQueue.display_draw_string_align_string  = string;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.display_draw_string_align_x_start;\n         delete Entry.hw.sendQueue.display_draw_string_align_x_end;\n         delete Entry.hw.sendQueue.display_draw_string_align_y;\n         delete Entry.hw.sendQueue.display_draw_string_align_align;\n         delete Entry.hw.sendQueue.display_draw_string_align_font;\n         delete Entry.hw.sendQueue.display_draw_string_align_pixel;\n         delete Entry.hw.sendQueue.display_draw_string_align_string;\n     },\n \n \n     // -- Buzzer -----------------------------------------------------------------------------\n     transferBuzzer(target, mode, value, time)\n     {\n         Entry.hw.sendQueue.target       = target;\n         Entry.hw.sendQueue.buzzer_mode  = mode;\n         Entry.hw.sendQueue.buzzer_value = value;\n         Entry.hw.sendQueue.buzzer_time  = time;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.buzzer_mode;\n         delete Entry.hw.sendQueue.buzzer_value;\n         delete Entry.hw.sendQueue.buzzer_time;\n     },\n \n \n     // -- Vibrator -----------------------------------------------------------------------------\n     transferVibrator(target, mode, timeOn, timeOff, timeRun)\n     {\n         Entry.hw.sendQueue.target         = target;\n         Entry.hw.sendQueue.vibrator_mode  = mode;\n         Entry.hw.sendQueue.vibrator_on    = timeOn;\n         Entry.hw.sendQueue.vibrator_off   = timeOff;\n         Entry.hw.sendQueue.vibrator_total = timeRun;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.vibrator_mode;\n         delete Entry.hw.sendQueue.vibrator_on;\n         delete Entry.hw.sendQueue.vibrator_off;\n         delete Entry.hw.sendQueue.vibrator_total;\n     },\n \n \n     // -- MotorSingle -----------------------------------------------------------------------------\n     transferMotorSingleRV(target, motorIndex, motorRotation, motorSpeed)\n     {\n         Entry.hw.sendQueue.target               = target;\n         Entry.hw.sendQueue.motorsingle_target   = motorIndex;\n         Entry.hw.sendQueue.motorsingle_rotation = motorRotation;\n         Entry.hw.sendQueue.motorsingle_value    = motorSpeed;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.motorsingle_target;\n         delete Entry.hw.sendQueue.motorsingle_rotation;\n         delete Entry.hw.sendQueue.motorsingle_value;\n     },\n \n \n     transferMotorSingleV(target, motorIndex, motorSpeed)\n     {\n         Entry.hw.sendQueue.target             = target;\n         Entry.hw.sendQueue.motorsingle_target = motorIndex;\n         Entry.hw.sendQueue.motorsingle_value  = motorSpeed;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.motorsingle_target;\n         delete Entry.hw.sendQueue.motorsingle_value;\n     },\n \n \n     // -- Command -----------------------------------------------------------------------------\n     transferCommand(target, command, option)\n     {\n         Entry.hw.sendQueue.target          = target;\n         Entry.hw.sendQueue.command_command = command;\n         Entry.hw.sendQueue.command_option  = option;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.command_command;\n         delete Entry.hw.sendQueue.command_option;\n     },\n \n \n     // -- Trim -----------------------------------------------------------------------------\n     transferTrim(target, roll, pitch, yaw, throttle)\n     {\n         Entry.hw.sendQueue.target        = target;\n         Entry.hw.sendQueue.trim_roll     = roll;\n         Entry.hw.sendQueue.trim_pitch    = pitch;\n         Entry.hw.sendQueue.trim_yaw      = yaw;\n         Entry.hw.sendQueue.trim_throttle = throttle;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.trim_roll;\n         delete Entry.hw.sendQueue.trim_pitch;\n         delete Entry.hw.sendQueue.trim_yaw;\n         delete Entry.hw.sendQueue.trim_throttle;\n     },\n \n \n     // -- Control -----------------------------------------------------------------------------\n     transferControlQuad(target, roll, pitch, yaw, throttle)\n     {\n         Entry.hw.sendQueue.target                 = target;\n         Entry.hw.sendQueue.control_quad8_roll     = roll;\n         Entry.hw.sendQueue.control_quad8_pitch    = pitch;\n         Entry.hw.sendQueue.control_quad8_yaw      = yaw;\n         Entry.hw.sendQueue.control_quad8_throttle = throttle;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.control_quad8_roll;\n         delete Entry.hw.sendQueue.control_quad8_pitch;\n         delete Entry.hw.sendQueue.control_quad8_yaw;\n         delete Entry.hw.sendQueue.control_quad8_throttle;\n     },\n \n \n     transferControlPosition(target, x, y, z, velocity, heading, rotationalVelocity)\n     {\n         Entry.hw.sendQueue.target                               = target;\n         Entry.hw.sendQueue.control_position_x                   = x;\n         Entry.hw.sendQueue.control_position_y                   = y;\n         Entry.hw.sendQueue.control_position_z                   = z;\n         Entry.hw.sendQueue.control_position_velocity            = velocity;\n         Entry.hw.sendQueue.control_position_heading             = heading;\n         Entry.hw.sendQueue.control_position_rotational_velocity = rotationalVelocity;\n \n         Entry.hw.update();\n \n         delete Entry.hw.sendQueue.target;\n         delete Entry.hw.sendQueue.control_position_x;\n         delete Entry.hw.sendQueue.control_position_y;\n         delete Entry.hw.sendQueue.control_position_z;\n         delete Entry.hw.sendQueue.control_position_velocity;\n         delete Entry.hw.sendQueue.control_position_heading;\n         delete Entry.hw.sendQueue.control_position_rotational_velocity;\n     },\n \n \n     /***************************************************************************************\n      *  기능\n      ***************************************************************************************/\n \n     // 데이터 읽기\n     getData(script, device)\n     {\n         return Entry.hw.portData[device];\n     },\n \n \n     getRgbFromString(stringColor)\n     {\n         let red   = 0;\n         let green = 0;\n         let blue  = 0;\n \n         switch (stringColor)\n         {\n             case 'red'           : { red = 255;  green = 0;    blue = 0;   }   break;\n             case 'green'         : { red = 0;    green = 255;  blue = 0;   }   break;\n             case 'blue'          : { red = 0;    green = 0;    blue = 255; }   break;\n             case 'cyan'          : { red = 0;    green = 255;  blue = 255; }   break;\n             case 'magenta'       : { red = 255;  green = 0;    blue = 255; }   break;\n             case 'yellow'        : { red = 255;  green = 255;  blue = 0;   }   break;\n             case 'white'         : { red = 255;  green = 255;  blue = 255; }   break;\n             case 'sunset'        : { red = 255;  green = 100;  blue = 0;   }   break;\n             case 'cottonCandy'   : { red = 20;   green = 250;  blue = 150; }   break;\n             case 'muscat'        : { red = 70;   green = 255;  blue = 0;   }   break;\n             case 'strawberryMilk': { red = 150;  green = 60;   blue = 20;  }   break;\n             case 'emerald'       : { red = 0;    green = 255;  blue = 30;  }   break;\n             case 'lavender'      : { red = 80;   green = 0;    blue = 200; }   break;\n         }\n \n         return { r:red, g:green, b:blue };\n     },\n \n \n \n     /***************************************************************************************\n      *  블럭 연동 함수\n      ***************************************************************************************/\n \n     // -- IR -----------------------------------------------------------------------------\n     // IR 데이터 송신\n     setIrMessage(script, target, irmessage)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferIrMessage(target, irmessage);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- Light -----------------------------------------------------------------------------\n     // LED 수동 설정\n     setLightManual(script, target, flags, brightness)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferLightManual(target, flags, brightness);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // LED 모드 설정\n     setLightMode(script, target, mode, interval)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferLightMode(target, mode, interval);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // LED 모드 설정, RGB\n     setLightModeColor(script, target, mode, interval, red, green, blue)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferLightModeColor(target, mode, interval, red, green, blue);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // LED 모드 설정, RGB\n     setLightModeColorString(script, target, mode, interval, stringColor)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     const color = this.getRgbFromString(stringColor);\n                     this.transferLightModeColor(target, mode, interval, color.r, color.g, color.b);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // LED 이벤트 설정\n     setLightEvent(script, target, mode, interval, repeat)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferLightEvent(target, mode, interval, repeat);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // LED 이벤트 설정, RGB\n     setLightEventColor(script, target, mode, interval, repeat, red, green, blue)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferLightEventColor(target, mode, interval, repeat, red, green, blue);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // LED 이벤트 설정, RGB\n     setLightEventColorString(script, target, mode, interval, repeat, stringColor)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     const color = this.getRgbFromString(stringColor);\n                     this.transferLightEventColor(target, mode, interval, repeat, color.r, color.g, color.b);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- Display -----------------------------------------------------------------------------\n     // 화면 전체 지우기, 선택 영역 지우기\n     setDisplayClearAll(script, target, pixel)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferDisplayClearAll(target, pixel);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 화면 전체 지우기, 선택 영역 지우기\n     setDisplayClear(script, target, pixel, x, y, width, height)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferDisplayClear(target, pixel, x, y, width, height);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 선택 영역 반전\n     setDisplayInvert(script, target, x, y, width, height)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferDisplayInvert(target, x, y, width, height);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 화면에 점 찍기\n     setDisplayDrawPoint(script, target, x, y, pixel)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferDisplayDrawPoint(target, x, y, pixel);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 화면에 선 그리기\n     setDisplayDrawLine(script, target, x1, y1, x2, y2, pixel, line)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferDisplayDrawLine(target, x1, y1, x2, y2, pixel, line);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 화면에 사각형 그리기\n     setDisplayDrawRect(script, target, x, y, width, height, pixel, flagFill, line)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferDisplayDrawRect(target, x, y, width, height, pixel, flagFill, line);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 화면에 원 그리기\n     setDisplayDrawCircle(script, target, x, y, radius, pixel, flagFill)\n     {\n         switch (this.checkFinish(script, 40)) {\n             case 'Start': \n                 {\n                     this.transferDisplayDrawCircle(target, x, y, radius, pixel, flagFill);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 화면에 문자열 쓰기\n     setDisplayDrawString(script, target, x, y, font, pixel, string)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferDisplayDrawString(target, x, y, font, pixel, string);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 화면에 문자열 정렬하여 그리기\n     setDisplayDrawStringAlign(script, target, xStart, xEnd, y, align, font, pixel, string)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferDisplayDrawStringAlign(target, xStart, xEnd, y, align, font, pixel, string);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- Buzzer -----------------------------------------------------------------------------\n     // 버저 설정(함수 호출 시 시간은 모두 ms 단위 사용)\n     /*\n         MuteInstantally = 1,   // 묵음 즉시 적용\n         MuteContinually = 2,   // 묵음 예약\n \n         ScaleInstantally = 3,   // 음계 즉시 적용\n         ScaleContinually = 4,   // 음계 예약\n \n         HzInstantally = 5,   // 주파수 즉시 적용\n         HzContinually = 6,   // 주파수 예약\n      */\n     // 정지\n     setBuzzerStop(script, target)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferBuzzer(target, 0, 0, 0);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // 묵음\n     setBuzzerMute(script, target, time, flagDelay, flagInstantly)\n     {\n         let timeDelay = 40;\n         if (flagDelay)\n         {\n             timeDelay = Math.max(timeDelay, time);\n         }\n \n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     let mode = 2;  // 묵음 연속\n                     if (flagInstantly)\n                     {\n                         mode = 1;\n                     } // 묵음 즉시\n \n                     this.transferBuzzer(target, mode, 0xee, time);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     setBuzzerScale(script, target, octave, scale, time, flagDelay, flagInstantly)\n     {\n         let timeDelay = 40;\n         if (flagDelay)\n         {\n             timeDelay = Math.max(timeDelay, time);\n         }\n \n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     let mode = 4;  // Scale 연속\n                     if (flagInstantly)\n                     {\n                         mode = 3;\n                     } // Scale 즉시\n \n                     const scale_index = octave * 12 + scale;\n \n                     this.transferBuzzer(target, mode, scale_index, time);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     setBuzzerHz(script, target, hz, time, flagDelay, flagInstantly)\n     {\n         let timeDelay = 40;\n         if (flagDelay)\n         {\n             timeDelay = Math.max(timeDelay, time);\n         }\n \n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     let mode = 6;  // Hz 연속\n                     if (flagInstantly)\n                     {\n                         mode = 5;\n                     } // Hz 즉시\n                     this.transferBuzzer(target, mode, hz, time);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- Vibrator -----------------------------------------------------------------------------\n     // 진동 제어\n     /*\n         Stop        = 0,   // 정지\n         Instantally = 1,   // 즉시 적용\n         Continually = 2,   // 예약\n      */\n     setVibratorStop(script, target)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferVibrator(target, 0, 0, 0, 0);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     setVibrator(script, target, timeOn, timeOff, timeRun, flagDelay, flagInstantly)\n     {\n         let timeDelay = 40;\n         if (flagDelay)\n         {\n             timeDelay = Math.max(timeDelay, timeRun);\n         }\n \n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     let mode = 2;  // 예약\n                     if (flagInstantly)\n                     {\n                         mode = 1;  // 즉시\n                     }\n \n                     this.transferVibrator(target, mode, timeOn, timeOff, timeRun);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- Command -----------------------------------------------------------------------------\n     sendStop(script, target)\n     {\n         return this.sendCommand(script, target, 0x01);\n     },\n \n \n     sendCommand(script, target, command, option = 0, timeDelay = 40)\n     {\n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     this.transferCommand(target, command, option);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- MotorSingle -----------------------------------------------------------------------------\n     setMotorSingleRV(script, target, motorIndex, motorRotation, motorSpeed)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferMotorSingleRV(target, motorIndex, motorRotation, motorSpeed);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     setMotorSingleV(script, target, motorIndex, motorSpeed)\n     {\n         switch (this.checkFinish(script, 40))\n         {\n             case 'Start': \n                 {\n                     this.transferMotorSingleV(target, motorIndex, motorSpeed);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- EventFlight -----------------------------------------------------------------------------\n     setEventFlight(script, target, eventFlight, time)\n     {\n         switch (this.checkFinish(script, time))\n         {\n             case 'Start': \n                 {\n                     this.transferControlQuad(0, 0, 0, 0); // 기존 입력되었던 조종기 방향 초기화 (수직으로 이륙, 착륙 하도록)\n                     this.transferCommand(target, 0x07, eventFlight); // 0x07 : CommandType::FlightEvent\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- Trim -----------------------------------------------------------------------------\n     sendTrim(script, target, roll, pitch, yaw, throttle)\n     {\n         let timeDelay = 40;\n \n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     this.transferTrim(target, roll, pitch, yaw, throttle);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish':\n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     // -- Control -----------------------------------------------------------------------------\n     sendControlQuadSingle(script, target, controlTarget, value, time = 40, flagDelay = false)\n     {\n         let timeDelay = 40;\n         if (flagDelay)\n         {\n             timeDelay = Math.max(timeDelay, time);\n         }\n \n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     Entry.hw.sendQueue.target           = target;\n                     Entry.hw.sendQueue[controlTarget]   = value;\n \n                     Entry.hw.update();\n \n                     delete Entry.hw.sendQueue.target;\n                     delete Entry.hw.sendQueue[controlTarget];\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 if (flagDelay)\n                 {\n                     // 블럭을 빠져나갈 때 변경했던 값을 초기화\n                     Entry.hw.sendQueue.target           = target;\n                     Entry.hw.sendQueue[controlTarget]   = 0;\n \n                     Entry.hw.update();\n \n                     delete Entry.hw.sendQueue.target;\n                     delete Entry.hw.sendQueue[controlTarget];\n                 }\n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     sendControlQuad(script, target, roll, pitch, yaw, throttle, time = 40, flagDelay = false)\n     {\n         let timeDelay = 40;\n         if (flagDelay)\n         {\n             timeDelay = Math.max(timeDelay, time);\n         }\n \n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     this.transferControlQuad(target, roll, pitch, yaw, throttle);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 if (flagDelay)\n                 {\n                     this.transferControlQuad(target, 0, 0, 0, 0);\n                 }\n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n \n \n     sendControlPosition(script, target, x, y, z, velocity, heading, rotationalVelocity, time = 40, flagDelay = false)\n     {\n         let timeDelay = 40;\n         if (flagDelay)\n         {\n             timeDelay = Math.max(timeDelay, time);\n         }\n \n         switch (this.checkFinish(script, timeDelay))\n         {\n             case 'Start': \n                 {\n                     this.transferControlQuad(target, 0, 0, 0, 0);\n                     this.transferControlPosition(target, x, y, z, velocity, heading, rotationalVelocity);\n                 }\n                 return script;\n \n             case 'Running': \n                 return script;\n \n             case 'Finish': \n                 return script.callReturn();\n \n             default: \n                 return script.callReturn();\n         }\n     },\n };\n  \n module.exports = Entry.robolink_base;\n \n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.robolink_codrone_edu = \n{\n    id       : '4A.4',\n    name     : 'robolink_codrone_edu',\n    url      : 'http://www.robolink.co.kr',\n    imageName: 'robolink_codrone_edu.png',\n    title    : {\n        en: 'Robolink CoDrone EDU',\n        ko: '로보링크 코드론 EDU',\n    },\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero()\n    {\n        // 초기화\n        Entry.robolink_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++)\n        {\n            if( Entry.hw.portData['state_modeFlight'] == 0x10 )\n            {\n                Entry.robolink_base.transferCommand(0x10, 0x01, 0); // 드론, command = 0x01 (Stop)\n            }\n            else\n            {\n                Entry.robolink_base.transferCommand(0x10, 0x07, 0x12); // 0x12 : FlightEvent::Landing\n            }\n\n            Entry.robolink_base.transferBuzzer(0x10, 0, 0, 0);\n            Entry.robolink_base.transferBuzzer(0x20, 0, 0, 0);\n            Entry.robolink_base.transferVibrator(0x20, 0, 0, 0, 0);\n            Entry.robolink_base.transferLightManual(0x10, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.robolink_base.transferLightManual(0x20, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.robolink_base.transferLightModeColor(0x10, 0x22, 200, 255, 0, 0); // LED 초기화(드론)\n            Entry.robolink_base.transferLightModeColor(0x20, 0x22, 200, 255, 0, 0); // LED 초기화(조종기)\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.robolink_codrone_edu.setLanguage = function() {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                // 정보창\n                monitor_state_modeFlight                        : '비행 모드',\n                monitor_state_modeControlFlight                 : '비행 제어기 모드',\n                monitor_state_modeMovement                      : '이동 상태',\n                monitor_state_headless                          : '헤드리스',\n                monitor_state_controlSpeed                      : '제어 속도',\n                monitor_state_sensorOrientation                 : '센서 방향',\n                monitor_state_battery                           : '배터리',\n                monitor_motion_accelX                           : '가속도 X',\n                monitor_motion_accelY                           : '가속도 Y',\n                monitor_motion_accelZ                           : '가속도 Z',\n                monitor_motion_gyroRoll                         : '자이로 Roll',\n                monitor_motion_gyroPitch                        : '자이로 Pitch',\n                monitor_motion_gyroYaw                          : '자이로 Yaw',\n                monitor_motion_angleRoll                        : '자세 Roll',\n                monitor_motion_anglePitch                       : '자세 Pitch',\n                monitor_motion_angleYaw                         : '자세 Yaw',\n                monitor_range_front                             : '정면 거리 센서',\n                monitor_range_bottom                            : '바닥 거리 센서',\n                monitor_cardColor_frontHue                      : '카드 위 색상',\n                monitor_cardColor_frontSaturation               : '카드 위 채도',\n                monitor_cardColor_frontValue                    : '카드 위 명도',\n                monitor_cardColor_frontLightness                : '카드 위 밝기',\n                monitor_cardColor_rearHue                       : '카드 아래 색상',\n                monitor_cardColor_rearSaturation                : '카드 아래 채도',\n                monitor_cardColor_rearValue                     : '카드 아래 명도',\n                monitor_cardColor_rearLightness                 : '카드 아래 밝기',\n                monitor_cardColor_frontColor                    : '카드 위 색',\n                monitor_cardColor_rearColor                     : '카드 아래 색',\n                monitor_cardColor_card                          : '카드',\n                monitor_informationAssembledForEntry_positionX  : '위치 X',\n                monitor_informationAssembledForEntry_positionY  : '위치 Y',\n                monitor_informationAssembledForEntry_positionZ  : '위치 Z',\n                monitor_informationAssembledForEntry_altitude   : '고도',\n                monitor_informationAssembledForEntry_rangeHeight: '거리 센서의 높이',\n                monitor_joystick_left_x                         : '왼쪽 조이스틱 X',\n                monitor_joystick_left_y                         : '왼쪽 조이스틱 Y',\n                monitor_joystick_left_direction                 : '왼쪽 조이스틱 방향',\n                monitor_joystick_left_event                     : '왼쪽 조이스틱 이벤트',\n                monitor_joystick_right_x                        : '오른쪽 조이스틱 X',\n                monitor_joystick_right_y                        : '오른쪽 조이스틱 Y',\n                monitor_joystick_right_direction                : '오른쪽 조이스틱 방향',\n                monitor_joystick_right_event                    : '오른쪽 조이스틱 이벤트',\n                monitor_button_button                           : '버튼',\n                monitor_button_event                            : '버튼 이벤트',\n                monitor_entryhw_countTransferReserved           : '전송 예정 데이터',\n\n                // 일반 블럭\n                common_light_color_red                  : '빨강',\n                common_light_color_yellow               : '노랑',\n                common_light_color_green                : '초록',\n                common_light_color_cyan                 : '하늘색',\n                common_light_color_blue                 : '파랑',\n                common_light_color_magenta              : '자홍',\n                common_light_color_white                : '흰색',\n                common_light_color_black                : '검정',\n                common_light_color_cottoncandy          : '구름솜사탕',\n                common_light_color_emerald              : '에메랄드',\n                common_light_color_lavender             : '라벤더',\n                common_light_color_muscat               : '청포도',\n                common_light_color_strawberrymilk       : '딸기우유',\n                common_light_color_sunset               : '저녁노을',\n                common_light_mode_hold                  : '켜짐',\n                common_light_mode_flicker               : '깜빡임',\n                common_light_mode_flicker_double        : '2번 연속 깜빡임',\n                common_light_mode_dimming               : '천천히 깜빡임',\n                common_light_mode_sunrise               : '점점 밝아짐',\n                common_light_mode_sunset                : '점점 어두워짐',\n                common_light_mode_rainbow               : '무지개',\n                common_light_mode_rainbow2              : '무지개2',\n                common_light_brightness_all             : '전체',\n                common_light_brightness_b100            : '밝기 100%',\n                common_light_brightness_b25             : '밝기 25%',\n                common_light_brightness_b50             : '밝기 50%',\n                common_light_brightness_b75             : '밝기 75%',\n                common_light_brightness_off             : '끄기',\n                common_light_brightness_on              : '켜기',\n                common_left                             : '왼쪽',\n                common_right                            : '오른쪽',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                common_drone                            : '드론',\n                common_controller                       : '조종기',                \n                controller_button                       : '버튼',\n                controller_button_event                 : '버튼 이벤트',\n                controller_button_front_left_top        : '전면 왼쪽 상단 버튼',\n                controller_button_front_left_bottom     : '전면 왼쪽 하단 버튼',\n                controller_button_front_right_top       : '전면 오른쪽 상단 버튼',\n                controller_button_front_right_bottom    : '전면 오른쪽 하단 버튼',\n                controller_button_top_left              : '상단 왼쪽 버튼',\n                controller_button_top_right             : '상단 오른쪽 버튼',\n                controller_button_center_up             : '중앙 위 버튼',\n                controller_button_center_left           : '중앙 왼쪽 버튼',\n                controller_button_center_right          : '중앙 오른쪽 버튼',\n                controller_button_center_down           : '중앙 아래쪽 버튼',\n                controller_button_bottom_left           : '하단 왼쪽 버튼',\n                controller_button_bottom_right          : '하단 오른쪽 버튼',\n                controller_buzzer                       : '버저',\n                controller_buzzer_a                     : '라',\n                controller_buzzer_as                    : '라#',\n                controller_buzzer_b                     : '시',\n                controller_buzzer_c                     : '도',\n                controller_buzzer_cs                    : '도#',\n                controller_buzzer_d                     : '레',\n                controller_buzzer_ds                    : '레#',\n                controller_buzzer_e                     : '미',\n                controller_buzzer_f                     : '파',\n                controller_buzzer_fs                    : '파#',\n                controller_buzzer_g                     : '솔',\n                controller_buzzer_gs                    : '솔#',\n                controller_buzzer_mute                  : '쉼',\n                controller_display_align_center         : '가운데',\n                controller_display_align_left           : '왼쪽',\n                controller_display_align_right          : '오른쪽',\n                controller_display_flagfill_off         : '채우지 않음',\n                controller_display_flagfill_on          : '채움',\n                controller_display_font_10x16           : '큼',\n                controller_display_font_5x8             : '작음',\n                controller_display_line_dashed          : '파선',\n                controller_display_line_dotted          : '점선',\n                controller_display_line_solid           : '실선',\n                controller_display_pixel_black          : '검은색',\n                controller_display_pixel_white          : '흰색',\n                controller_display_pixel_inverse        : '반전',\n                controller_joystick_direction_left_up   : '왼쪽 위',\n                controller_joystick_direction_up        : '위',\n                controller_joystick_direction_right_up  : '오른쪽 위',\n                controller_joystick_direction_left      : '왼쪽',\n                controller_joystick_direction_center    : '중앙',\n                controller_joystick_direction_right     : '오른쪽',\n                controller_joystick_direction_left_down : '왼쪽 아래',\n                controller_joystick_direction_down      : '아래',\n                controller_joystick_direction_right_down: '오른쪽 아래',\n                controller_joystick_left_direction      : '왼쪽 조이스틱 방향',\n                controller_joystick_left_event          : '왼쪽 조이스틱 이벤트',\n                controller_joystick_left_x              : '왼쪽 조이스틱 가로축',\n                controller_joystick_left_y              : '왼쪽 조이스틱 세로축',\n                controller_joystick_right_direction     : '오른쪽 조이스틱 방향',\n                controller_joystick_right_event         : '오른쪽 조이스틱 이벤트',\n                controller_joystick_right_x             : '오른쪽 조이스틱 가로축',\n                controller_joystick_right_y             : '오른쪽 조이스틱 세로축',\n                drone_accel_x                           : '가속도 x',\n                drone_accel_y                           : '가속도 y',\n                drone_accel_z                           : '가속도 z',\n                drone_gyro_pitch                        : '각속도 Pitch',\n                drone_gyro_roll                         : '각속도 Roll',\n                drone_gyro_yaw                          : '각속도 Yaw',\n                drone_attitude_pitch                    : '자세 Pitch',\n                drone_attitude_roll                     : '자세 Roll',\n                drone_attitude_yaw                      : '자세 Yaw',\n                drone_positionX                         : '위치 X',\n                drone_positionY                         : '위치 Y',\n                drone_positionZ                         : '위치 Z',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : '뒤',\n                drone_control_quad_pitch_forward        : '앞',\n                drone_control_quad_roll_left            : '왼쪽',\n                drone_control_quad_roll_right           : '오른쪽',\n                drone_control_quad_throttle_down        : '아래',\n                drone_control_quad_throttle_up          : '위',\n                drone_control_quad_yaw_ccw              : '반시계 방향',\n                drone_control_quad_yaw_cw               : '시계 방향',\n                drone_headless_normal                   : 'off (숙련자용)',\n                drone_headless_headless                 : 'on (초보자용)',\n                drone_light_color_body                  : '몸체',\n                drone_light_manual_body_blue            : '파랑',\n                drone_light_manual_body_green           : '초록',\n                drone_light_manual_body_red             : '빨강',\n                drone_motor_rotation_clockwise          : '시계 방향',\n                drone_motor_rotation_counterclockwise   : '반시계 방향',\n                drone_altitude                          : '해발고도',\n                drone_range_height                      : '바닥과의 거리',\n                drone_range_front                       : '정면과의 거리',\n                drone_cardcolor_front_hue               : '앞 색상 H',\n                drone_cardcolor_front_saturation        : '앞 채도 S',\n                drone_cardcolor_front_value             : '앞 명도 V',\n                drone_cardcolor_front_lightness         : '앞 밝기 L',\n                drone_cardcolor_rear_hue                : '뒤 색상 H',\n                drone_cardcolor_rear_saturation         : '뒤 채도 S',\n                drone_cardcolor_rear_value              : '뒤 명도 V',\n                drone_cardcolor_rear_lightness          : '뒤 밝기 L',\n                drone_cardcolor_front_color             : '앞 카드 색',\n                drone_cardcolor_rear_color              : '뒤 카드 색',\n                drone_cardcolor_card                    : '카드',\n                drone_state_mode_system                 : '시스템 모드',\n                drone_state_mode_flight                 : '비행 동작 상태',\n                drone_state_mode_control_flight         : '비행 제어 모드',\n                drone_state_mode_movement               : '이동 상태',\n                drone_state_headless                    : 'Headless',\n                drone_state_control_speed               : '제어 속도',\n                drone_state_sensor_orientation          : '센서 방향',\n                drone_state_battery                     : '배터리',\n                entryhw_count_transfer_reserved         : '전송 예약된 데이터 수',\n                drone_state_mode_flight_ready           : '대기 상태',\n                drone_state_mode_flight_start           : '시동 상태',\n                drone_state_mode_flight_takeoff         : '이륙 상태',\n                drone_state_mode_flight_flight          : '비행 상태',\n                drone_state_mode_flight_landing         : '착륙 상태',\n                drone_state_mode_flight_stop            : '정지 상태',\n                controller_display_shape_line           : '직선',\n                controller_display_shape_square         : '사각형',\n                controller_display_shape_ellipse        : '타원',\n                drone_control_flip_front                : '앞으로 뒤집기',\n                drone_control_flip_rear                 : '뒤로 뒤집기',\n                drone_control_flip_left                 : '왼쪽으로 뒤집기',\n                drone_control_flip_right                : '오른쪽으로 뒤집기',\n                common_wait                             : '기다리기',\n                common_next                             : '넘어가기',\n                common_instant                          : '즉시',\n                common_reserve                          : '예약',\n\n\n            },\n\n            template: {\n                robolink_codrone_edu_controller_buzzer_hz                : '%1 %2Hz 소리를 %3초 %4연주 %5',\n                robolink_codrone_edu_controller_buzzer_hz_delay          : '%1 %2Hz 소리를 %3초 연주 %4',\n                robolink_codrone_edu_controller_buzzer_hz_reserve        : '%1 %2Hz 소리를 %3초 예약 %4',\n                robolink_codrone_edu_controller_buzzer_off               : '%1 버저 끄기 %2',\n                robolink_codrone_edu_controller_buzzer_scale             : '%1 %2 옥타브 %3을(를) %4초 %5연주 %6',\n                robolink_codrone_edu_controller_buzzer_scale_delay       : '%1 %2 옥타브 %3을(를) %4초 연주 %5',\n                robolink_codrone_edu_controller_buzzer_scale_reserve     : '%1 %2 옥타브 %3을(를) %4초 예약 %5',\n                robolink_codrone_edu_controller_display_clear            : '지우기 x %1, y %2, 너비 %3, 높이 %4 %5 %6',\n                robolink_codrone_edu_controller_display_clear_all        : '화면 전체 지우기%1 %2',\n                robolink_codrone_edu_controller_display_draw_shape       : '%1 x1 %2, y1 %3, x2(너비,반지름) %4, y2(높이) %5 %6 %7 %8 %9',\n                robolink_codrone_edu_controller_display_draw_circle      : '타원 x %1, y %2, 반지름 %3 %4 %5 %6',                \n                robolink_codrone_edu_controller_display_draw_line        : '선 x1 %1, y1 %2, x2 %3, y2 %4 %5 %6 %7',\n                robolink_codrone_edu_controller_display_draw_point       : '점 그리기 x %1, y %2 %3 %4',\n                robolink_codrone_edu_controller_display_draw_rect        : '사각형 x %1, y %2, 너비 %3, 높이 %4 %5 %6 %7 %8',\n                robolink_codrone_edu_controller_display_draw_string      : '문자열 x %1, y %2 %3 %4 입력 %5 %6',\n                robolink_codrone_edu_controller_display_draw_string_align: '문자열 정렬 x1 %1, x2 %2, y %3 %4 %5 %6 입력 %7 %8',\n                robolink_codrone_edu_drone_if_state                      : '드론 비행 상태가 %1 일 때',\n                robolink_codrone_edu_controller_if_button_press          : '조종기 %1 눌렀을 때',\n                robolink_codrone_edu_controller_if_joystick_direction    : '조종기 %1 조이스틱 %2 (으)로 움직였을 때',\n                robolink_codrone_edu_light_manual_single_off             : '%1 LED 끄기 %2',\n                robolink_codrone_edu_light_color_input                   : '%1 LED R %2, G %3, B %4 %5 %6 %7',\n                robolink_codrone_edu_light_color_select                  : '%1 LED %2 %3 %4 %5',\n                robolink_codrone_edu_light_color_preset                  : '%1 LED %2 %3 %4',\n                robolink_codrone_edu_light_manual_single_input           : '%1 LED %2 밝기 %3 %4',\n                robolink_codrone_edu_controller_light_color_input        : '조종기 LED R %1, G %2, B %3 %4 %5 %6',\n                robolink_codrone_edu_controller_light_color_select       : '조종기 LED %1 %2 %3 %4',\n                robolink_codrone_edu_controller_light_color_preset       : '조종기 LED %1 %2 %3',\n                robolink_codrone_edu_controller_light_manual_single_input: '조종기 LED %1 밝기 %2 %3',\n                robolink_codrone_edu_controller_light_manual_single_off  : '조종기 LED 끄기 %1',\n                robolink_codrone_edu_controller_value_button             : '%1',\n                robolink_codrone_edu_controller_value_joystick           : '%1',\n                robolink_codrone_edu_controller_vibrator_delay           : '조종기 진동 %1초 켜기, %2초 끄기를 %3초 실행 %4',\n                robolink_codrone_edu_controller_vibrator_off             : '조종기 진동 끄기 %1',\n                robolink_codrone_edu_controller_vibrator_on_delay        : '조종기 진동 %1초 켜기 %2',\n                robolink_codrone_edu_controller_vibrator_on_reserve      : '조종기 진동 %1초 실행 %2',\n                robolink_codrone_edu_controller_vibrator_reserve         : '조종기 진동 %1초 켜기, %2초 끄기를 %3초 예약 %4',\n                robolink_codrone_edu_drone_control_headless              : '헤드리스 모드 %1 %2',\n                robolink_codrone_edu_drone_control_drone_landing         : '드론 착륙 %1',\n                robolink_codrone_edu_drone_control_drone_reset_heading   : '드론 방향 초기화 %1',\n                robolink_codrone_edu_drone_control_drone_stop            : '드론 정지 %1',\n                robolink_codrone_edu_drone_control_drone_takeoff         : '드론 이륙 %1',\n                robolink_codrone_edu_drone_control_drone_return_home     : '리턴 홈 %1',\n                robolink_codrone_edu_drone_control_flip                  : '플립 %1 %2',\n                robolink_codrone_edu_drone_control_quad_one              : '드론 %1 %2% 정하기 %3',\n                robolink_codrone_edu_drone_control_quad_one_delay        : '드론 %1 %2% %3 초 실행 %4',\n                robolink_codrone_edu_drone_control_quad                  : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% 정하기 %5',\n                robolink_codrone_edu_drone_control_quad_delay            : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5초 실행 %6',\n                robolink_codrone_edu_drone_control_position_one          : '드론 %1(으)로 %2m를 %3m/s로 이동 %4 %5',\n                robolink_codrone_edu_drone_control_position_turn         : '드론 %1(으)로 %2도를 %3deg/s로 회전 %4 %5',\n                robolink_codrone_edu_drone_control_position_location     : '드론 %1 %2m, %3 %4m, %5 %6m를 %7m/s로 이동 %8 %9',\n                robolink_codrone_edu_drone_control_position_location_turn: '드론 %1 %2m, %3 %4m, %5 %6m를 %7m/s로 이동, %8 %9도를 %10deg/s로 회전 %11',\n                robolink_codrone_edu_drone_light_color_input             : '드론 LED R %1, G %2, B %3 %4 %5 %6',\n                robolink_codrone_edu_drone_light_color_select            : '드론 LED %1 %2 %3 %4',\n                robolink_codrone_edu_drone_light_color_preset            : '드론 LED %1 %2 %3',\n                robolink_codrone_edu_drone_light_manual_single_input     : '드론 LED %1 밝기 %2 %3',\n                robolink_codrone_edu_drone_light_manual_single_off       : '드론 LED 끄기 %1',\n                robolink_codrone_edu_drone_motor_stop                    : '드론 모터 정지 %1',\n                robolink_codrone_edu_drone_motorsingle                   : '드론 %1번 모터를 %2(으)로 회전 %3',\n                robolink_codrone_edu_drone_motorsingle_input             : '드론 %1번 모터를 %2(으)로 회전 %3',\n                robolink_codrone_edu_drone_value_attitude                : '%1',\n                robolink_codrone_edu_drone_value_motion                  : '%1',\n                robolink_codrone_edu_drone_value_position                : '%1',\n                robolink_codrone_edu_drone_value_sensor                  : '%1',\n                robolink_codrone_edu_drone_value_card                    : '%1',\n                robolink_codrone_edu_drone_value_etc                     : '%1',\n            },\n\n            Helper: {\n                robolink_codrone_edu_controller_buzzer_hz                : \"지정한 주파수의 소리를 연주합니다. <br><br>즉시로 선택한 경우 계속해서 연주합니다.(최대 60초) 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br>예약으로 선택한경우 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br>권장 사용 hz 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. <br><br><font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font>\",\n                robolink_codrone_edu_controller_buzzer_hz_delay          : \"지정한 주파수의 소리를 지정한 시간동안 연주합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                robolink_codrone_edu_controller_buzzer_hz_reserve        : \"지정한 주파수의 소리를 지정한 시간동안 연주하도록 예약합니다. 권장 사용 범위는 250 ~ 8000 입니다. 4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브를 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브를 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다. 이 블럭은 소리가 나도록 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#주파수</font> <font color='peru'>#예약</font>\",\n                robolink_codrone_edu_controller_buzzer_off               : \"버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.<br><br><font color='dodgerblue'>#버저끄기</font>\",\n                robolink_codrone_edu_controller_buzzer_scale             : \"지정한 옥타브의 음을 연주합니다.<br><br>즉시로 선택한 경우 계속해서 연주합니다.(최대 60초) 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭은 연주 명령을 실행 후 바로 다음 블럭으로 넘어갑니다.<br><br>예약으로 선택한경우 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font>\",\n                robolink_codrone_edu_controller_buzzer_scale_delay       : \"지정한 옥타브의 음을 지정한 시간동안 연주합니다. 이 블럭을 만났을 경우 소리가 켜져있거나 예약된 소리가 있다면 모두 삭제합니다. 이 블럭을 사용하면 소리가 끝날때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#즉시</font> <font color='blueviolet'>#시간지연</font>\",\n                robolink_codrone_edu_controller_buzzer_scale_reserve     : \"지정한 옥타브의 음을 지정한 시간동안 연주하도록 예약합니다. 이 블럭은 소리가 나도록 예약하고 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다. 이 블럭은 주로 버저 소리와 함께 다른 행동을 동시에 할 때 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#버저</font> <font color='forestgreen'>#음계</font> <font color='peru'>#예약</font>\",\n                robolink_codrone_edu_controller_display_clear            : \"조종기 OLED 화면의 선택한 영역을 지웁니다.<br>x, y 좌표값과 너비, 높이를 지정합니다. 좌표(x, y) = (가로, 세로) 화면상의 위치입니다. 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_controller_display_clear_all        : \"조종기 OLED 화면 전체를 지웁니다.<br> 흰색/검은색 중에서 원하는 색을 선택할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_controller_display_draw_shape       : \"조종기 OLED 화면에서 지정한 위치에 선택한 모양을 그립니다.<br>모양에 따라 파라미터가 다르게 사용됩니다.<br>(x, y)좌표에 관한 설명은 [점 그리기]블럭을 참조해주세요.<br><br>*직선 그리기는 시작점과 끝나는점을 이어주는 기능입니다.<br>시작점 = (x1, y1), 끝나는점 = (x2, y2)<br>사용 가능한 x값은 (0~128), y값은 (0~64)입니다. <br>선의 색과 선의 종류를 선택할 수 있습니다.<br><br>*사각형 그리기는 x, y 좌표값과 너비, 높이를 지정합니다. <br>시작점 = (x, y), 사용 가능한 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br>선의 색과 선의 종류, 채움을 선택할 수 있습니다.<br><br>*타원 그리기는 x, y 좌표값과 반지름을 지정합니다.<br>원의 중심은 (x, y), 반지름은 원의 크기를 결정합니다.<br>사용 가능한 x값은 (-50~178), y값은 (-50~114), 반지름은 (1~200)입니다.<br>선의 색과 채움을 선택할 수 있습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_controller_display_draw_circle      : \"조종기 OLED 화면에서 지정한 위치에 원을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 반지름을 지정합니다. 원의 중심 = (x, y),<br>반지름은 원의 크기를 결정합니다.<br><br>★☆사용 가능한 값의 범위는 x값은 (-50~178), y값은 (-50~114), 반지름은 (1~200)입니다.☆★<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_controller_display_draw_line        : \"조종기 OLED 화면에서 지정한 위치에 선을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>시작점 = (x1, y1), 끝나는점 = (x2, y2)<br>선 그리기는 시작점과 끝나는점을 이어주는 기능입니다.<br>사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_controller_display_draw_point       : \"조종기 OLED 화면에서 지정한 위치에 점을 찍습니다.<br>흰색/검은색 중에서 원하는 색을 선택할 수 있습니다.<br>x, y 좌표값으로 지정합니다. <br>좌표(x, y) = (가로, 세로) 화면상의 위치입니다.<br>사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_controller_display_draw_rect        : \"조종기 OLED 화면에서 지정한 위치에 사각형을 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>x, y 좌표값과 너비, 높이를 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값과 너비는 (0~128), y값과 높이는 (0~64)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_controller_display_draw_string      : \"조종기 OLED 화면에서 지정한 위치에 문자열을 씁니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 글자 크기, 색을 지정합니다. 시작점 = (x, y), 사용 가능한 값의 범위는 x값은 (0~120), y값과 높이는 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_controller_display_draw_string_align: \"조종기 OLED 화면에서 지정한 위치에 문자열을 정렬하여 그립니다.<br><br>☆★ (x, y)좌표에 관한 설명은 [조종기 화면 점 찍기]블럭을 참조해주세요. ★☆<br><br>글자 입력은 영문자 알파벳 대문자, 소문자와 숫자, 공백(space), 특수문자만 가능합니다.(한글은 아직 지원되지 않습니다.)<br>x, y 좌표값과 정렬 방향, 글자 크기, 색을 지정합니다. 시작점 = (x1, y), 끝나는점 = (x2, y), 사용 가능한 값의 범위는 x값은 (0~128), y값은 (0~60)입니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#Display</font>\",\n                robolink_codrone_edu_drone_if_state                      : \"드론의 비행 상태에 따라 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#상태</font>\",\n                robolink_codrone_edu_controller_if_button_press          : \"조종기의 지정한 버튼이 눌러졌을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                robolink_codrone_edu_controller_if_joystick_direction    : \"조종기의 조이스틱을 지정한 방향으로 움직였을 때 true를 반환합니다.<br><br><font color='crimson'>#조건</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                robolink_codrone_edu_light_manual_single_off             : \"선택한 장치의 모든 LED를 끕니다.<br><br><font color='dodgerblue'>#LED끄기</font>\",\n                robolink_codrone_edu_light_color_input                   : \"빛의 삼원색인 Red, Green, Blue 값을 지정하여 선택한 장치의 LED의 색상을 원하는대로 만들 수 있습니다.10진수(0 ~ 255) 값을 사용합니다.<br>LED패턴을 사용하는 경우에는 갱신되는 주기 값을 변경할 수 있습니다.10진수 (0 ~ 65535)값을 사용합니다.<br><br><font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_light_color_select                  : \"RGB 색지정 블록을 이용해서 만들 수 있는<br> 선택한 장치의 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_light_color_preset                  : \"선택한 장치의 LED를 조작하는데 사용합니다.<br><br><font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_light_manual_single_input           : \"선택한 장치의 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255) 또는 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 LED의 Red, Green, Blue 색을 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_controller_light_color_input        : \"빛의 삼원색인 Red, Green, Blue 값을 지정하여 조종기 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_controller_light_color_select       : \"RGB 색지정 블록을 이용해서 만들 수 있는<br> 조종기 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_controller_light_color_preset       : \"조종기 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_controller_light_manual_single_input: \"조종기 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255) 또는 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 LED의 Red, Green, Blue 색을 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다. <br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_controller_light_manual_single_off  : \"조종기의 모든 LED를 끕니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#LED끄기</font>\",\n                robolink_codrone_edu_controller_value_button             : \"조종기에서 눌러진 버튼과 관련된 이벤트를 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#버튼</font>\",\n                robolink_codrone_edu_controller_value_joystick           : \"조종기의 조이스틱과 관련된 입력 값을 반환합니다.<br>각 축의 범위는 -100 ~ 100 입니다.<br><br>조이스틱 방향은 가로x세로 = 3x3 = 총9방향입니다.<br>위(왼쪽=17, 가운데=18, 오른쪽=20)<br>중간(왼쪽=33, 센터=34, 오른쪽=36)<br>아래(왼쪽=65, 가운데=66, 오른쪽=68)<br>기본값은 센터=34입니다.<br><br>조이스틱 이벤트는 값이 있을때 2, 없으면 0, 진입 1, 벗어남 3입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#조종기</font> <font color='forestgreen'>#조이스틱</font>\",\n                robolink_codrone_edu_controller_vibrator_delay           : \"진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복합니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                robolink_codrone_edu_controller_vibrator_off             : \"진동을 끕니다. 예약된 진동이 있다면 모두 삭제합니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동끄기</font>\",\n                robolink_codrone_edu_controller_vibrator_on_delay        : \"진동을 지정한 시간동안 켭니다. 이 블럭을 만났을 경우 진동이 켜져있거나 예약된 진동이 있다면 모두 삭제합니다. 이 블럭은 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#즉시</font> <font color='peru'>#시간지연</font>\",\n                robolink_codrone_edu_controller_vibrator_on_reserve      : \"진동을 지정한 시간동안 켜는 것을 예약합니다. <br>이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                robolink_codrone_edu_controller_vibrator_reserve         : \"진동을 지정한 시간동안 켜고 끄는 것을 지정한 시간동안 반복하도록 예약합니다. 이 블럭은 명령을 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#조종기</font> <font color='dodgerblue'>#진동</font> <font color='forestgreen'>#예약</font>\",\n                robolink_codrone_edu_drone_control_headless              : \"드론 좌표 기준을 변경합니다.<br>헤드리스 모드를 on으로 하면 이륙 시와 '방향초기화'를 했을 때 드론이 바라보는 방향을 기준으로 앞뒤좌우가 고정됩니다.<br>이 때에는 Yaw를 조작하여 드론이 다른 방향을 보게 하여도 처음 지정한 방향을 기준으로 앞뒤좌우로 움직입니다.<br>사용자가 바라보는 방향과 드론의 기준 방향이 같을 때 조작하기 편리한 장점이 있습니다.<br>Headless mode를 off로 선택하면 현재 드론이 바라보는 방향을 기준으로 앞뒤좌우가 결정됩니다. 드론의 움직임에 따라 앞뒤좌우가 계속 바뀌기 때문에 익숙해지기 전까지는 사용하기 어려울 수 있습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#좌표기준</font>\",\n                robolink_codrone_edu_drone_control_drone_landing         : \"드론을 착륙시킵니다.<br><br>5초간 작동합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#착륙</font>\",\n                robolink_codrone_edu_drone_control_drone_reset_heading   : \"드론의 방향을 초기화합니다.<br>헤드리스 모드가 off 인 경우 현재 드론이 바라보는 방향을 0도로 변경합니다.<br>일반 모드에서는 아무런 영향이 없습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#방향초기화</font>\",\n                robolink_codrone_edu_drone_control_drone_stop            : \"드론 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#정지</font>\",\n                robolink_codrone_edu_drone_control_drone_takeoff         : \"드론을 이륙시킵니다.<br><br>5초간 작동합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이륙</font>\",\n                robolink_codrone_edu_drone_control_drone_return_home     : \"비행 중에 드론이 최초 이륙했던 위치로 돌아올 수 있습니다.<br><br> 주변 환경에 따라 오차가 발생할 수 있습니다.<br> 리턴홈 명령전에 주변의 장애물이 없는지 확인해주세요.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#리턴홈</font>\",\n                robolink_codrone_edu_drone_control_flip                  : \"드론을 지정한 방향으로 공중 회전합니다.<br><br>배터리가 낮은 경우 작동하지 않을 수 있습니다.<br>드론의 높이가 낮거나 주변에 장애물이 있는 경우에는 사용에 주의해주세요.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#플립</font>\",\n                robolink_codrone_edu_drone_control_quad                  : \"드론 조종 값을 지정합니다. <br><br>Roll : 좌측, 우측이동<br>Pitch : 전진, 후진이동<br>Yaw : 좌회전, 우회전이동<br>Throttle : 상하수직이동<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. <br>정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. <br>명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                robolink_codrone_edu_drone_control_quad_delay            : \"지정한 시간동안 작동하는 드론 조종 값을 지정합니다.<br>지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다.<br><br>Roll : 좌측, 우측이동<br>Pitch : 전진, 후진이동<br>Yaw : 좌회전, 우회전이동<br>Throttle : 상하수직이동<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. <br>정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다.<br>지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                robolink_codrone_edu_drone_control_quad_one              : \"드론 조종 값을 지정합니다. <br><br>Roll : 좌측, 우측이동<br>Pitch : 전진, 후진이동<br>Yaw : 좌회전, 우회전이동<br>Throttle : 상하수직이동<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. <br>정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. <br>명령 전달 후 바로 다음 블럭으로 넘어갑니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font>\",\n                robolink_codrone_edu_drone_control_quad_one_delay        : \"지정한 시간동안 작동하는 드론 조종 값을 지정합니다.<br>지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다.<br><br>Roll : 좌측, 우측이동<br>Pitch : 전진, 후진이동<br>Yaw : 좌회전, 우회전이동<br>Throttle : 상하수직이동<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. <br>정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. <br>지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#조종</font> <font color='forestgreen'>#시간지연</font>\",\n                robolink_codrone_edu_drone_control_position_one          : \"드론의 방향과 거리, 이동 속도를 지정하여 지정한 위치로 이동합니다. <br><br>'기다리기'를 선택한 경우 거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭에서 기다립니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                robolink_codrone_edu_drone_control_position_turn         : \"드론의 회전 방향과 각도, 회전 속도를 지정하여 지정한 각도로 회전합니다. <br><br>'기다리기'를 선택한 경우 목표 각도를 회전 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭블럭에서 기다립니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#회전</font> <font color='forestgreen'>#시간지연</font>\",\n                robolink_codrone_edu_drone_control_position_location     : \"드론의 X, Y, Z 축의 방향과 거리, 이동 속도를 설정하여 지정한 위치로 이동합니다. <br><br>'기다리기'를 선택한 경우 거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간만큼 해당 블럭에서 기다립니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                robolink_codrone_edu_drone_control_position_location_turn: \"드론의 X, Y, Z 축의 방향과 거리, 이동 속도, 회전 방향과 목표 각도, 회전 속도를 설정하여 지정한 위치로의 이동과 회전을 실행합니다. <br>거리를 속도로 나누어 얻은 시간에 1.2를 곱한 시간 또는 목표 각도를 회전 속도로 나누어 얻은 시간에 1.2를 곱한 시간 중에 긴 시간만큼 해당 블럭에 머뭅니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#이동</font> <font color='forestgreen'>#시간지연</font>\",\n                robolink_codrone_edu_drone_light_color_input             : \"빛의 삼원색인 Red, Green, Blue 값을 지정하여 드론의 눈 또는 팔 LED의 색상을 원하는대로 만들 수 있습니다.<br>10진수(0 ~ 255) 값을 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_drone_light_color_select            : \"RGB 색지정 블록을 이용해서 만들 수 있는<br> 드론 LED 예시입니다.<br>RGB 색지정 블록을 이용해서 멋진 색깔을<br> 다양하게 만들어보세요.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_drone_light_color_preset            : \"드론의 LED를 조작하는데 사용합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_drone_light_manual_single_input     : \"드론 LED를 조작하는데 사용합니다.<br>10진수(0 ~ 255), 16진수(0x00 ~ 0xFF) 값을 사용할 수 있습니다.<br>2진수로 표현한 값에서 각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED제어</font>\",\n                robolink_codrone_edu_drone_light_manual_single_off       : \"드론의 모든 LED를 끕니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#LED끄기</font>\",\n                robolink_codrone_edu_drone_motor_stop                    : \"모든 모터의 작동을 정지합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터정지</font>\",\n                robolink_codrone_edu_drone_motorsingle                   : \"모터 제어 블럭입니다.<br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                robolink_codrone_edu_drone_motorsingle_input             : \"모터 제어 블럭입니다.<br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다. <br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#모터제어</font>\",\n                robolink_codrone_edu_drone_value_attitude                : \"드론의 현재 자세를 각도로 반환합니다.<br><br>Roll은 좌우 기울기(-90 ~ 90), <br>Pitch는 앞뒤 기울기(-90 ~ 90), <br>Yaw는 회전 각도(-180 ~ 180) 입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#자세</font>\",\n                robolink_codrone_edu_drone_value_etc                     : \"드론의 비행 상태 및 설정과 배터리 등의 상태 값들을 반환합니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#기타</font>\",\n                robolink_codrone_edu_drone_value_motion                  : \"드론 IMU센서와 관련된 값들을 반환합니다.<br>(병진운동) 가속도는 x, y, z축에 대한 중력가속도입니다. 1g = 9.8m/s^2<br>(회전운동) 각속도는 x, y, z축을 기준으로 회전하는 속력을 나타내는 벡터입니다.(pitch, roll, yaw) <br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#IMU센서</font> <font color='crimson'>#가속도</font> <font color='dodgerblue'>#병진운동</font> <font color='crimson'>#각속도</font> <font color='dodgerblue'>#회전운동</font>\",\n                robolink_codrone_edu_drone_value_position                : \"드론 위치와 관련된 값들을 반환합니다.(단위:m)<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#위치</font>\",\n                robolink_codrone_edu_drone_value_sensor                  : \"드론 거리 및 고도 센서와 관련된 값들을 반환합니다(단위:m)<br>거리 센서의 유효 측정 거리는 2m입니다.<br><br>해발고도는 기압계와 고도계를 사용하여 측정된 값입니다.<br><br><font color='crimson'>#값</font> <font color='dodgerblue'>#드론</font> <font color='forestgreen'>#센서</font> <font color='crimson'>#거리센서</font> <font color='dodgerblue'>#대기압</font>\",\n                robolink_codrone_edu_drone_value_card                    : \"드론 카드 센서와 관련된 값들을 반환합니다.<br><br>카드 : 드론에서 판단한 색상 카드 값을 반환합니다. 먼저 드론에서 컬러 캘리브레이션을 진행해야 사용 가능합니다.<br><br>센서의 색 공간 값 : HSVL 형식으로 앞면과 뒷면의 센서에서 Hue(색상), Saturation(채도), Value(명도), Light(밝기) 값을 반환합니다.<br><br><font color='crimson'>#드론</font> <font color='dodgerblue'>#카드</font>\",\n            },\n        },\n\n        en: {\n            Blocks: {\n                // 정보창\n                monitor_state_modeFlight                        : 'Flight Mode',\n                monitor_state_modeControlFlight                 : 'Control Flight Mode',\n                monitor_state_modeMovement                      : 'Movement Mode',\n                monitor_state_headless                          : 'Headless',\n                monitor_state_controlSpeed                      : 'Control Speed',\n                monitor_state_sensorOrientation                 : 'Sensor Orientation',\n                monitor_state_battery                           : 'Battery',\n                monitor_motion_accelX                           : 'Accel X',\n                monitor_motion_accelY                           : 'Accel Y',\n                monitor_motion_accelZ                           : 'Accel Z',\n                monitor_motion_gyroRoll                         : 'Gyro Roll',\n                monitor_motion_gyroPitch                        : 'Gyro Pitch',\n                monitor_motion_gyroYaw                          : 'Gyro Yaw',\n                monitor_motion_angleRoll                        : 'Roll',\n                monitor_motion_anglePitch                       : 'Pitch',\n                monitor_motion_angleYaw                         : 'Yaw',\n                monitor_range_front                             : 'Range Front',\n                monitor_range_bottom                            : 'Range Bottom',\n                monitor_cardColor_frontHue                      : 'Front Hue',\n                monitor_cardColor_frontSaturation               : 'Front Saturation',\n                monitor_cardColor_frontValue                    : 'Front Value',\n                monitor_cardColor_frontLightness                : 'Front Lightness',\n                monitor_cardColor_rearHue                       : 'Rear Hue',\n                monitor_cardColor_rearSaturation                : 'Rear Saturation',\n                monitor_cardColor_rearValue                     : 'Rear Value',\n                monitor_cardColor_rearLightness                 : 'Rear Lightness',\n                monitor_cardColor_frontColor                    : 'Front Color',\n                monitor_cardColor_rearColor                     : 'Rear Color',\n                monitor_cardColor_card                          : 'Card',\n                monitor_informationAssembledForEntry_positionX  : 'Position X',\n                monitor_informationAssembledForEntry_positionY  : 'Position Y',\n                monitor_informationAssembledForEntry_positionZ  : 'Position Z',\n                monitor_informationAssembledForEntry_altitude   : 'Altitude',\n                monitor_informationAssembledForEntry_rangeHeight: 'Height',\n                monitor_joystick_left_x                         : 'Left Joystick X',\n                monitor_joystick_left_y                         : 'Left Joystick Y',\n                monitor_joystick_left_direction                 : 'Left Joystick Direction',\n                monitor_joystick_left_event                     : 'Left Joystick Event',\n                monitor_joystick_right_x                        : 'Right Joystick X',\n                monitor_joystick_right_y                        : 'Right Joystick Y',\n                monitor_joystick_right_direction                : 'Right Joystick Direction',\n                monitor_joystick_right_event                    : 'Right Joystick Event',\n                monitor_button_button                           : 'Button',\n                monitor_button_event                            : 'Button Event',\n                monitor_entryhw_countTransferReserved           : 'Transfer Buffer',\n                drone_state_mode_flight_ready                   : 'ready state',\n                drone_state_mode_flight_start                   : 'start state',\n                drone_state_mode_flight_takeoff                 : 'takeoff state',\n                drone_state_mode_flight_flight                  : 'flight state',\n                drone_state_mode_flight_landing                 : 'landing state',\n                drone_state_mode_flight_stop                    : 'stop state',\n                controller_display_shape_line                   : 'line',\n                controller_display_shape_square                 : 'square',\n                controller_display_shape_ellipse                : 'ellipse',\n                drone_control_flip_front                        : 'flip forward',\n                drone_control_flip_rear                         : 'flip back',\n                drone_control_flip_left                         : 'flip left',\n                drone_control_flip_right                        : 'flip right',\n                common_wait                                     : 'wait',\n                common_next                                     : 'next',\n                common_instant                                  : 'instant',\n                common_reserve                                  : 'reserve',\n\n                // 일반 블럭\n                common_light_color_red                  : 'red',\n                common_light_color_yellow               : 'yellow',\n                common_light_color_green                : 'green',\n                common_light_color_cyan                 : 'cyan',\n                common_light_color_blue                 : 'blue',\n                common_light_color_magenta              : 'magenta',\n                common_light_color_white                : 'white',\n                common_light_color_cottoncandy          : 'cotton candy',\n                common_light_color_emerald              : 'emerald',\n                common_light_color_lavender             : 'lavender',\n                common_light_color_muscat               : 'muscat',\n                common_light_color_strawberrymilk       : 'strawberry milk',\n                common_light_color_sunset               : 'sunset',\n                common_light_mode_hold                  : 'hold',\n                common_light_mode_flicker               : 'flicker',\n                common_light_mode_flicker_double        : 'flicker double',\n                common_light_mode_dimming               : 'dimming',\n                common_light_mode_sunrise               : 'sunrise',\n                common_light_mode_sunset                : 'sunset',\n                common_light_mode_rainbow               : 'rainbow',\n                common_light_mode_rainbow2              : 'rainbow2',\n                common_light_brightness_all             : 'all',\n                common_light_brightness_b100            : 'brightness 100%',\n                common_light_brightness_b25             : 'brightness 25%',\n                common_light_brightness_b50             : 'brightness 50%',\n                common_light_brightness_b75             : 'brightness 75%',\n                common_light_brightness_off             : 'off',\n                common_light_brightness_on              : 'on',\n                common_left                             : 'left',\n                common_right                            : 'right',\n                common_roll                             : 'Roll',\n                common_pitch                            : 'Pitch',\n                common_yaw                              : 'Yaw',\n                common_throttle                         : 'Throttle',\n                common_drone                            : 'drone',\n                common_controller                       : 'controller',\n                controller_button                       : 'button',\n                controller_button_event                 : 'button event',\n                controller_button_front_left_top        : 'Front left top button',\n                controller_button_front_left_bottom     : 'Front left bottom button',\n                controller_button_front_right_top       : 'Front right top button',\n                controller_button_front_right_bottom    : 'Front right bottom button',\n                controller_button_top_left              : 'Top left button',\n                controller_button_top_right             : 'Top right button',\n                controller_button_center_up             : 'Trim up button',\n                controller_button_center_left           : 'Trim left button',\n                controller_button_center_right          : 'Trim right button',\n                controller_button_center_down           : 'Trim down button',\n                controller_button_bottom_left           : 'Bottom left button',\n                controller_button_bottom_right          : 'Bottom right button',\n                controller_buzzer                       : 'buzzer',\n                controller_buzzer_a                     : 'A',\n                controller_buzzer_as                    : 'A#',\n                controller_buzzer_b                     : 'B',\n                controller_buzzer_c                     : 'C',\n                controller_buzzer_cs                    : 'C#',\n                controller_buzzer_d                     : 'D',\n                controller_buzzer_ds                    : 'D#',\n                controller_buzzer_e                     : 'E',\n                controller_buzzer_f                     : 'F',\n                controller_buzzer_fs                    : 'F#',\n                controller_buzzer_g                     : 'G',\n                controller_buzzer_gs                    : 'G#',\n                controller_buzzer_mute                  : 'mute',\n                controller_display_align_center         : 'center',\n                controller_display_align_left           : 'left',\n                controller_display_align_right          : 'right',\n                controller_display_flagfill_off         : 'not fill',\n                controller_display_flagfill_on          : 'fill',\n                controller_display_font_10x16           : 'big',\n                controller_display_font_5x8             : 'small',\n                controller_display_line_dashed          : 'dashed',\n                controller_display_line_dotted          : 'dotted',\n                controller_display_line_solid           : 'solid',\n                controller_display_pixel_black          : 'black',\n                controller_display_pixel_white          : 'white',\n                controller_display_pixel_inverse        : 'inverse',\n                controller_joystick_direction_left_up   : 'Left top',\n                controller_joystick_direction_up        : 'Top',\n                controller_joystick_direction_right_up  : 'Right top',\n                controller_joystick_direction_left      : 'Left',\n                controller_joystick_direction_center    : 'Center',\n                controller_joystick_direction_right     : 'Right',\n                controller_joystick_direction_left_down : 'Left Bottom',\n                controller_joystick_direction_down      : 'Bottom',\n                controller_joystick_direction_right_down: 'Right Bottom',\n                controller_joystick_left_direction      : 'left joystick direction',\n                controller_joystick_left_event          : 'left joystick event',\n                controller_joystick_left_x              : 'left joystick X',\n                controller_joystick_left_y              : 'left joystick Y',\n                controller_joystick_right_direction     : 'right joystick direction',\n                controller_joystick_right_event         : 'right joystick event',\n                controller_joystick_right_x             : 'right joystick X',\n                controller_joystick_right_y             : 'right joystick Y',\n                drone_accel_x                           : 'Accel x',\n                drone_accel_y                           : 'Accel y',\n                drone_accel_z                           : 'Accel z',\n                drone_gyro_pitch                        : 'Gyro Pitch',\n                drone_gyro_roll                         : 'Gyro Roll',\n                drone_gyro_yaw                          : 'Gyro Yaw',\n                drone_attitude_pitch                    : 'Attitude Pitch',\n                drone_attitude_roll                     : 'Attitude Roll',\n                drone_attitude_yaw                      : 'Attitude Yaw',\n                drone_positionX                         : 'Position X',\n                drone_positionY                         : 'Position Y',\n                drone_positionZ                         : 'Position Z',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : 'Backward',\n                drone_control_quad_pitch_forward        : 'Forward',\n                drone_control_quad_roll_left            : 'Left',\n                drone_control_quad_roll_right           : 'Right',\n                drone_control_quad_throttle_down        : 'Down',\n                drone_control_quad_throttle_up          : 'Up',\n                drone_control_quad_yaw_ccw              : 'Counterclockwise',\n                drone_control_quad_yaw_cw               : 'clockwise',\n                drone_headless_normal                   : 'Normal',\n                drone_headless_headless                 : 'Headless',\n                drone_light_color_body                  : 'Body',\n                drone_light_manual_body_blue            : 'Blue',\n                drone_light_manual_body_green           : 'Green',\n                drone_light_manual_body_red             : 'Red',\n                drone_motor_rotation_clockwise          : 'Clockwise',\n                drone_motor_rotation_counterclockwise   : 'Counterclockwise',\n                drone_altitude                          : 'Altitude',\n                drone_range_height                      : 'Height',\n                drone_range_front                       : 'Distance from front obstacle',\n                drone_cardcolor_front_hue               : 'Front Hue',\n                drone_cardcolor_front_saturation        : 'Front Saturation',\n                drone_cardcolor_front_value             : 'Front Value',\n                drone_cardcolor_front_lightness         : 'Front Lightness',\n                drone_cardcolor_rear_hue                : 'Rear Hue',\n                drone_cardcolor_rear_saturation         : 'Rear Saturation',\n                drone_cardcolor_rear_value              : 'Rear Value',\n                drone_cardcolor_rear_lightness          : 'Rear Lightness',\n                drone_cardcolor_front_color             : 'Front Card Color',\n                drone_cardcolor_rear_color              : 'Rear Card Color',\n                drone_cardcolor_card                    : 'Card',\n                drone_state_mode_system                 : 'System Mode',\n                drone_state_mode_flight                 : 'Flight Mode',\n                drone_state_mode_control_flight         : 'Flight Control Mode',\n                drone_state_mode_movement               : 'mode movement',\n                drone_state_headless                    : 'Headless',\n                drone_state_control_speed               : 'Speed',\n                drone_state_sensor_orientation          : 'Sensor direction',\n                drone_state_battery                     : 'Battery',\n                entryhw_count_transfer_reserved         : 'Reserved data for transfer',\n            },\n\n            template: {\n                robolink_codrone_edu_controller_buzzer_hz                : '%1 play Buzzer %2 Hz for %3 second %4sound %5',\n                robolink_codrone_edu_controller_buzzer_hz_delay          : '%1 play Buzzer %2 Hz sound for %3 second %4',\n                robolink_codrone_edu_controller_buzzer_hz_reserve        : '%1 reserve to play Buzzer %2 Hz for %3 second %4',\n                robolink_codrone_edu_controller_buzzer_off               : '%1 turn off the buzzer %2',\n                robolink_codrone_edu_controller_buzzer_scale             : '%1 play %2 octave %3 for %4 second %5 %6',\n                robolink_codrone_edu_controller_buzzer_scale_delay       : '%1 play %2 octave %3 for %4 second %5',\n                robolink_codrone_edu_controller_buzzer_scale_reserve     : '%1 reserve to play %2 octave %3 for %4 second %5',\n                robolink_codrone_edu_controller_display_clear            : 'clear controller display x:%1, y:%2, width:%3, height:%4, color:%5 %6',\n                robolink_codrone_edu_controller_display_clear_all        : 'clear controller display with %1 color %2',\n                robolink_codrone_edu_controller_display_draw_shape       : 'draw a shape %1 x1 %2, y1 %3, x2 %4, y2 %5 %6 %7 %8 %9',  \n                robolink_codrone_edu_controller_display_draw_circle      : 'draw a ellipse x:%1, y:%2, radius:%3, %4, %5, %6',\n                robolink_codrone_edu_controller_display_draw_line        : 'draw a line x1:%1, y1:%2, x2:%3, y2:%4, %5, %6 %7',\n                robolink_codrone_edu_controller_display_draw_point       : 'draw a point x:%1, y:%2, color:%3 %4',\n                robolink_codrone_edu_controller_display_draw_rect        : 'draw a rectangle x:%1, y:%2, width:%3, height:%4, %5, %6, %7 %8',\n                robolink_codrone_edu_controller_display_draw_string      : 'draw a string x:%1, y:%2, font size:%3, %4, input:%5, %6',\n                robolink_codrone_edu_controller_display_draw_string_align: 'draw aligned string x1:%1, x2:%2, y:%3, align:%4, font size:%5, %6, input:%7, %8',\n                robolink_codrone_edu_drone_if_state                      : 'drone flight state %1',\n                robolink_codrone_edu_controller_if_button_press          : 'when press %1',\n                robolink_codrone_edu_controller_if_joystick_direction    : 'when %1 stick move to %2',\n                robolink_codrone_edu_light_manual_single_off             : '%1 turn off the LED %2',\n                robolink_codrone_edu_light_color_input                   : '%1 LED R %2, G %3, B %4 %5 %6 %7',\n                robolink_codrone_edu_light_color_select                  : '%1 LED %2 %3 %4 %5',\n                robolink_codrone_edu_light_color_preset                  : '%1 LED %2 %3 %4',\n                robolink_codrone_edu_light_manual_single_input           : '%1 LED %2 bright %3 %4',\n                robolink_codrone_edu_controller_light_color_input        : 'Controller LED R %1, G %2, B %3 %4 %5 %6',\n                robolink_codrone_edu_controller_light_color_select       : 'Controller LED Preset %1 %2 %3 %4',\n                robolink_codrone_edu_controller_light_color_preset       : 'Controller LED %1 %2 %3',\n                robolink_codrone_edu_controller_light_manual_single_input: 'Controller LED %1 Lightness %2 %3',\n                robolink_codrone_edu_controller_light_manual_single_off  : 'Controller LED Off %1',\n                robolink_codrone_edu_controller_value_button             : '%1',\n                robolink_codrone_edu_controller_value_joystick           : '%1',\n                robolink_codrone_edu_controller_vibrator_delay           : 'Controller vibrator %1 sec On, %2 sec Off for %3 sec run %4',\n                robolink_codrone_edu_controller_vibrator_off             : 'Controller vibrator Off %1',\n                robolink_codrone_edu_controller_vibrator_on_delay        : 'Controller vibrator %1 sec on %2',\n                robolink_codrone_edu_controller_vibrator_on_reserve      : 'Controller vibrator %1 sec reserve %2',\n                robolink_codrone_edu_controller_vibrator_reserve         : 'Controller vibrator %1 sec On, %2 sec Off for %3 sec reserve %4',\n                robolink_codrone_edu_drone_control_headless              : 'Headless mode %1 %2',\n                robolink_codrone_edu_drone_control_drone_landing         : 'Landing %1',\n                robolink_codrone_edu_drone_control_drone_reset_heading   : 'Reset heading %1',\n                robolink_codrone_edu_drone_control_drone_stop            : 'Stop flight %1',\n                robolink_codrone_edu_drone_control_drone_takeoff         : 'Takeoff %1',\n                robolink_codrone_edu_drone_control_drone_return_home     : 'Return Home %1',\n                robolink_codrone_edu_drone_control_flip                  : 'Flip %1 %2',\n                robolink_codrone_edu_drone_control_quad_one              : 'Set %1 %2% %3',\n                robolink_codrone_edu_drone_control_quad_one_delay        : 'Set %1 %2% %3 sec %4',\n                robolink_codrone_edu_drone_control_quad                  : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5',\n                robolink_codrone_edu_drone_control_quad_delay            : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% for %5sec %6',\n                robolink_codrone_edu_drone_control_position_one          : 'Move %2 meter(s) %1 to %3 m/s %4 %5',\n                robolink_codrone_edu_drone_control_position_turn         : 'Rotate %2 degree(s) %1 to %3 deg/s %4 %5',\n                robolink_codrone_edu_drone_control_position_location     : 'Move %2 meter(s) %1, %4 meter(s) %3, %6 meter(s) %5 to %7 m/s %8 %9',\n                robolink_codrone_edu_drone_control_position_location_turn: 'Move %2 meter(s) %1, %4 meter(s) %3, %6 meter(s) %5 to %7 m/s, Rotate %9 degree(s) %8 to %10 deg/s %11',\n                robolink_codrone_edu_drone_light_color_input             : 'Drone LED R %1, G %2, B %3 %4 %5 %6',\n                robolink_codrone_edu_drone_light_color_select            : 'Drone LED Preset %1 %2 %3 %4',\n                robolink_codrone_edu_drone_light_color_preset            : 'Drone LED %1 %2 %3',\n                robolink_codrone_edu_drone_light_manual_single_input     : 'Drone LED %1 lightness %2 %3',\n                robolink_codrone_edu_drone_light_manual_single_off       : 'Drone LED Off %1',\n                robolink_codrone_edu_drone_motor_stop                    : 'Motor stop %1',\n                robolink_codrone_edu_drone_motorsingle                   : 'No. %1 Motor rotate for %2 %3',\n                robolink_codrone_edu_drone_motorsingle_input             : 'No. %1 Motor rotate for %2 %3',\n                robolink_codrone_edu_drone_value_attitude                : '%1',\n                robolink_codrone_edu_drone_value_motion                  : '%1',\n                robolink_codrone_edu_drone_value_position                : '%1',\n                robolink_codrone_edu_drone_value_sensor                  : '%1',\n                robolink_codrone_edu_drone_value_card                    : '%1',\n                robolink_codrone_edu_drone_value_etc                     : '%1',\n            },\n\n            Helper: {\n                robolink_codrone_edu_controller_buzzer_hz                : '',\n                robolink_codrone_edu_controller_buzzer_hz_delay          : '',\n                robolink_codrone_edu_controller_buzzer_hz_reserve        : '',\n                robolink_codrone_edu_controller_buzzer_off               : '',\n                robolink_codrone_edu_controller_buzzer_scale             : '',\n                robolink_codrone_edu_controller_buzzer_scale_delay       : '',\n                robolink_codrone_edu_controller_buzzer_scale_reserve     : '',\n                robolink_codrone_edu_controller_display_clear            : '',\n                robolink_codrone_edu_controller_display_clear_all        : '',\n                robolink_codrone_edu_controller_display_draw_shape       : '',\n                robolink_codrone_edu_controller_display_draw_circle      : '',\n                robolink_codrone_edu_controller_display_draw_line        : '',\n                robolink_codrone_edu_controller_display_draw_point       : '',\n                robolink_codrone_edu_controller_display_draw_rect        : '',\n                robolink_codrone_edu_controller_display_draw_string      : '',\n                robolink_codrone_edu_controller_display_draw_string_align: '',\n                robolink_codrone_edu_drone_if_state                      : '',\n                robolink_codrone_edu_controller_if_button_press          : '',\n                robolink_codrone_edu_controller_if_joystick_direction    : '',\n                robolink_codrone_edu_light_manual_single_off             : '',\n                robolink_codrone_edu_light_color_input                   : '',\n                robolink_codrone_edu_light_color_select                  : '',\n                robolink_codrone_edu_light_color_preset                  : '',\n                robolink_codrone_edu_light_manual_single_input           : '',\n                robolink_codrone_edu_controller_light_color_input        : '',\n                robolink_codrone_edu_controller_light_color_select       : '',\n                robolink_codrone_edu_controller_light_color_preset       : '',\n                robolink_codrone_edu_controller_light_manual_single_input: '',\n                robolink_codrone_edu_controller_light_manual_single_off  : '',\n                robolink_codrone_edu_controller_value_button             : '',\n                robolink_codrone_edu_controller_value_joystick           : '',\n                robolink_codrone_edu_controller_vibrator_delay           : '',\n                robolink_codrone_edu_controller_vibrator_off             : '',\n                robolink_codrone_edu_controller_vibrator_on_delay        : '',\n                robolink_codrone_edu_controller_vibrator_on_reserve      : '',\n                robolink_codrone_edu_controller_vibrator_reserve         : '',\n                robolink_codrone_edu_drone_control_headless              : '',\n                robolink_codrone_edu_drone_control_drone_landing         : '',\n                robolink_codrone_edu_drone_control_drone_reset_heading   : '',\n                robolink_codrone_edu_drone_control_drone_stop            : '',\n                robolink_codrone_edu_drone_control_drone_takeoff         : '',\n                robolink_codrone_edu_drone_control_drone_return_home     : '',\n                robolink_codrone_edu_drone_control_flip                  : '',\n                robolink_codrone_edu_drone_control_quad                  : '',\n                robolink_codrone_edu_drone_control_quad_delay            : '',\n                robolink_codrone_edu_drone_control_quad_one              : '',\n                robolink_codrone_edu_drone_control_quad_one_delay        : '',\n                robolink_codrone_edu_drone_control_position_one          : '',\n                robolink_codrone_edu_drone_control_position_turn         : '',\n                robolink_codrone_edu_drone_control_position_location     : '',\n                robolink_codrone_edu_drone_control_position_location_turn: '',\n                robolink_codrone_edu_drone_light_color_input             : '',\n                robolink_codrone_edu_drone_light_color_select            : '',\n                robolink_codrone_edu_drone_light_color_preset            : '',\n                robolink_codrone_edu_drone_light_manual_single_input     : '',\n                robolink_codrone_edu_drone_light_manual_single_off       : '',\n                robolink_codrone_edu_drone_motor_stop                    : '',\n                robolink_codrone_edu_drone_motorsingle                   : '',\n                robolink_codrone_edu_drone_motorsingle_input             : '',\n                robolink_codrone_edu_drone_value_attitude                : '',\n                robolink_codrone_edu_drone_value_etc                     : '',\n                robolink_codrone_edu_drone_value_motion                  : '',\n                robolink_codrone_edu_drone_value_position                : '',\n                robolink_codrone_edu_drone_value_sensor                  : '',\n                robolink_codrone_edu_drone_value_card                    : '',\n            },\n        },\n    };\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.robolink_codrone_edu.monitorTemplate = function()\n{\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/robolink_codrone_edu.png\",   // 배경 이미지\n        width  : 256,                        // 이미지의 폭\n        height : 256,                        // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeFlight                        : { name: Lang.Blocks.monitor_state_modeFlight,                          type: 'input', pos: { x: 0, y: 0 } },\n            state_modeControlFlight                 : { name: Lang.Blocks.monitor_state_modeControlFlight,                   type: 'input', pos: { x: 0, y: 0 } },\n            state_modeMovement                      : { name: Lang.Blocks.monitor_state_modeMovement,                        type: 'input', pos: { x: 0, y: 0 } },\n            state_headless                          : { name: Lang.Blocks.monitor_state_headless,                            type: 'input', pos: { x: 0, y: 0 } },\n            state_controlSpeed                      : { name: Lang.Blocks.monitor_state_controlSpeed,                        type: 'input', pos: { x: 0, y: 0 } },\n            state_sensorOrientation                 : { name: Lang.Blocks.monitor_state_sensorOrientation,                   type: 'input', pos: { x: 0, y: 0 } },\n            state_battery                           : { name: Lang.Blocks.monitor_state_battery,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelX                           : { name: Lang.Blocks.monitor_motion_accelX,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelY                           : { name: Lang.Blocks.monitor_motion_accelY,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelZ                           : { name: Lang.Blocks.monitor_motion_accelZ,                             type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroRoll                         : { name: Lang.Blocks.monitor_motion_gyroRoll,                           type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroPitch                        : { name: Lang.Blocks.monitor_motion_gyroPitch,                          type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroYaw                          : { name: Lang.Blocks.monitor_motion_gyroYaw,                            type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleRoll                        : { name: Lang.Blocks.monitor_motion_angleRoll,                          type: 'input', pos: { x: 0, y: 0 } },\n            motion_anglePitch                       : { name: Lang.Blocks.monitor_motion_anglePitch,                         type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleYaw                         : { name: Lang.Blocks.monitor_motion_angleYaw,                           type: 'input', pos: { x: 0, y: 0 } },\n            range_front                             : { name: Lang.Blocks.monitor_range_front,                               type: 'input', pos: { x: 0, y: 0 } },\n            range_bottom                            : { name: Lang.Blocks.monitor_range_bottom,                              type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontHue                      : { name: Lang.Blocks.monitor_cardColor_frontHue,                        type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontSaturation               : { name: Lang.Blocks.monitor_cardColor_frontSaturation,                 type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontValue                    : { name: Lang.Blocks.monitor_cardColor_frontValue,                      type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontLightness                : { name: Lang.Blocks.monitor_cardColor_frontLightness,                  type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearHue                       : { name: Lang.Blocks.monitor_cardColor_rearHue,                         type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearSaturation                : { name: Lang.Blocks.monitor_cardColor_rearSaturation,                  type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearValue                     : { name: Lang.Blocks.monitor_cardColor_rearValue,                       type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearLightness                 : { name: Lang.Blocks.monitor_cardColor_rearLightness,                   type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_frontColor                    : { name: Lang.Blocks.monitor_cardColor_frontColor,                      type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_rearColor                     : { name: Lang.Blocks.monitor_cardColor_rearColor,                       type: 'input', pos: { x: 0, y: 0 } },\n            cardColor_card                          : { name: Lang.Blocks.monitor_cardColor_card,                            type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionX  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionX,    type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionY  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionY,    type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_positionZ  : { name: Lang.Blocks.monitor_informationAssembledForEntry_positionZ,    type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_altitude   : { name: Lang.Blocks.monitor_informationAssembledForEntry_altitude,     type: 'input', pos: { x: 0, y: 0 } },\n            informationAssembledForEntry_rangeHeight: { name: Lang.Blocks.monitor_informationAssembledForEntry_rangeHeight,  type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_x                         : { name: Lang.Blocks.monitor_joystick_left_x,                           type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_y                         : { name: Lang.Blocks.monitor_joystick_left_y,                           type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_direction                 : { name: Lang.Blocks.monitor_joystick_left_direction,                   type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_event                     : { name: Lang.Blocks.monitor_joystick_left_event,                       type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_x                        : { name: Lang.Blocks.monitor_joystick_right_x,                          type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_y                        : { name: Lang.Blocks.monitor_joystick_right_y,                          type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_direction                : { name: Lang.Blocks.monitor_joystick_right_direction,                  type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_event                    : { name: Lang.Blocks.monitor_joystick_right_event,                      type: 'input', pos: { x: 0, y: 0 } },\n            button_button                           : { name: Lang.Blocks.monitor_button_button,                             type: 'input', pos: { x: 0, y: 0 } },\n            button_event                            : { name: Lang.Blocks.monitor_button_event,                              type: 'input', pos: { x: 0, y: 0 } },\n            entryhw_countTransferReserved           : { name: Lang.Blocks.monitor_entryhw_countTransferReserved,             type: 'output', pos: { x: 0, y: 0 } },\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both',   // 표시 모드\n    };\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 블록명(다른 장치의 블록 이름과 달라야 함)\n ***************************************************************************************/\nEntry.robolink_codrone_edu.blockMenuBlocks = [\n    'robolink_codrone_edu_drone_control_drone_takeoff',\n    'robolink_codrone_edu_drone_control_drone_landing',\n    'robolink_codrone_edu_drone_control_drone_stop',\n    'robolink_codrone_edu_drone_control_drone_return_home',\n    'robolink_codrone_edu_drone_control_flip',\n    'robolink_codrone_edu_drone_control_headless',\n    'robolink_codrone_edu_drone_control_drone_reset_heading',\n    'robolink_codrone_edu_drone_control_quad_one',\n    'robolink_codrone_edu_drone_control_quad_one_delay',\n    'robolink_codrone_edu_drone_control_quad',\n    'robolink_codrone_edu_drone_control_quad_delay',\n    'robolink_codrone_edu_drone_control_position_one',\n    'robolink_codrone_edu_drone_control_position_turn',\n    'robolink_codrone_edu_drone_control_position_location',\n    //'robolink_codrone_edu_drone_control_position_location_turn',\n    'robolink_codrone_edu_light_manual_single_off',\n    'robolink_codrone_edu_light_color_preset',\n    //'robolink_codrone_edu_light_color_select',\n    'robolink_codrone_edu_light_color_input',\n    //'robolink_codrone_edu_light_manual_single_input',\n    //'robolink_codrone_edu_drone_light_manual_single_off',\n    //'robolink_codrone_edu_drone_light_manual_single_input',\n    //'robolink_codrone_edu_drone_light_color_preset',\n    //'robolink_codrone_edu_drone_light_color_input',\n    //'robolink_codrone_edu_drone_light_color_select',\n    //'robolink_codrone_edu_controller_light_manual_single_off',\n    //'robolink_codrone_edu_controller_light_manual_single_input',\n    //'robolink_codrone_edu_controller_light_color_preset',\n    //'robolink_codrone_edu_controller_light_color_input',\n    //'robolink_codrone_edu_controller_light_color_select',\n    'robolink_codrone_edu_controller_buzzer_off',\n    'robolink_codrone_edu_controller_buzzer_scale',\n    //'robolink_codrone_edu_controller_buzzer_scale_delay',\n    //'robolink_codrone_edu_controller_buzzer_scale_reserve',\n    'robolink_codrone_edu_controller_buzzer_hz',\n    //'robolink_codrone_edu_controller_buzzer_hz_delay',\n    //'robolink_codrone_edu_controller_buzzer_hz_reserve',\n    'robolink_codrone_edu_controller_display_clear_all',\n    //'robolink_codrone_edu_controller_display_clear',\n    'robolink_codrone_edu_controller_display_draw_point',\n    'robolink_codrone_edu_controller_display_draw_shape',\n    //'robolink_codrone_edu_controller_display_draw_line',\n    //'robolink_codrone_edu_controller_display_draw_rect',\n    //'robolink_codrone_edu_controller_display_draw_circle',\n    'robolink_codrone_edu_controller_display_draw_string',\n    //'robolink_codrone_edu_controller_display_draw_string_align',\n    'robolink_codrone_edu_controller_vibrator_off',\n    //'robolink_codrone_edu_controller_vibrator_on_delay',\n    'robolink_codrone_edu_controller_vibrator_on_reserve',\n    //'robolink_codrone_edu_controller_vibrator_delay',\n    //'robolink_codrone_edu_controller_vibrator_reserve',\n    //'robolink_codrone_edu_drone_motor_stop',\n    //'robolink_codrone_edu_drone_motorsingle',\n    //'robolink_codrone_edu_drone_motorsingle_input',\n    'robolink_codrone_edu_drone_value_attitude',\n    'robolink_codrone_edu_drone_value_motion',\n    'robolink_codrone_edu_drone_value_position',\n    'robolink_codrone_edu_drone_value_sensor',\n    'robolink_codrone_edu_drone_value_card',\n    'robolink_codrone_edu_drone_value_etc',\n    'robolink_codrone_edu_controller_value_button',\n    'robolink_codrone_edu_controller_value_joystick',\n    'robolink_codrone_edu_drone_if_state',\n    'robolink_codrone_edu_controller_if_button_press',\n    'robolink_codrone_edu_controller_if_joystick_direction',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 정의\n ***************************************************************************************/\nEntry.robolink_codrone_edu.getBlocks = function()\n{\n    return {\n        robolink_codrone_edu_drone_value_attitude: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_attitude_roll,   'motion_angleRoll'],\n                        [Lang.Blocks.drone_attitude_pitch,  'motion_anglePitch'],\n                        [Lang.Blocks.drone_attitude_yaw,    'motion_angleYaw'],\n                    ],\n                    value     : 'motion_angleRoll',                            // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_value_attitude',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.attitude(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_attitude_roll,   'motion_angleRoll'],\n                                    [Lang.Blocks.drone_attitude_pitch,  'motion_anglePitch'],\n                                    [Lang.Blocks.drone_attitude_yaw,    'motion_angleYaw'],\n                                ],\n                                value     : 'motion_angleRoll',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_value_motion: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_accel_x,     'motion_accelX'],\n                        [Lang.Blocks.drone_accel_y,     'motion_accelY'],\n                        [Lang.Blocks.drone_accel_z,     'motion_accelZ'],\n                        [Lang.Blocks.drone_gyro_roll,   'motion_gyroRoll'],\n                        [Lang.Blocks.drone_gyro_pitch,  'motion_gyroPitch'],\n                        [Lang.Blocks.drone_gyro_yaw,    'motion_gyroYaw'],\n                    ],\n                    value     : 'motion_accelX',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_value_motion',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.motion(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_accel_x,     'motion_accelX'],\n                                    [Lang.Blocks.drone_accel_y,     'motion_accelY'],\n                                    [Lang.Blocks.drone_accel_z,     'motion_accelZ'],\n                                    [Lang.Blocks.drone_gyro_roll,   'motion_gyroRoll'],\n                                    [Lang.Blocks.drone_gyro_pitch,  'motion_gyroPitch'],\n                                    [Lang.Blocks.drone_gyro_yaw,    'motion_gyroYaw'],\n                                ],\n                                value     : 'motion_accelX',                               // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_value_position: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_positionX,       'informationAssembledForEntry_positionX'],\n                        [Lang.Blocks.drone_positionY,       'informationAssembledForEntry_positionY'],\n                        [Lang.Blocks.drone_positionZ,       'informationAssembledForEntry_positionZ'],\n                    ],\n                    value     : 'informationAssembledForEntry_positionX',      // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_value_position',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.position(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_positionX,       'informationAssembledForEntry_positionX'],\n                                    [Lang.Blocks.drone_positionY,       'informationAssembledForEntry_positionY'],\n                                    [Lang.Blocks.drone_positionZ,       'informationAssembledForEntry_positionZ'],\n                                ],\n                                value     : 'informationAssembledForEntry_positionX',      // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_value_sensor: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_range_front,     'range_front'],\n                        [Lang.Blocks.drone_range_height,    'informationAssembledForEntry_rangeHeight'],\n                        [Lang.Blocks.drone_altitude,        'informationAssembledForEntry_altitude'],\n                    ],\n                    value     : 'range_front',                                 // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_value_sensor',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.sensor(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_range_front,     'range_front'],\n                                    [Lang.Blocks.drone_range_height,    'informationAssembledForEntry_rangeHeight'],\n                                    [Lang.Blocks.drone_altitude,        'informationAssembledForEntry_altitude'],\n                                ],\n                                value     : 'range_front',                                 // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_value_card: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_cardcolor_front_color,            'cardColor_frontColor'],\n                        [Lang.Blocks.drone_cardcolor_rear_color,             'cardColor_rearColor'],\n                        [Lang.Blocks.drone_cardcolor_card,                   'cardColor_card'],\n                        [Lang.Blocks.drone_cardcolor_front_hue,              'cardColor_frontHue'],\n                        [Lang.Blocks.drone_cardcolor_front_saturation,       'cardColor_frontSaturation'],\n                        [Lang.Blocks.drone_cardcolor_front_value,            'cardColor_frontValue'],\n                        [Lang.Blocks.drone_cardcolor_front_lightness,        'cardColor_frontLightness'],\n                        [Lang.Blocks.drone_cardcolor_rear_hue,               'cardColor_rearHue'],\n                        [Lang.Blocks.drone_cardcolor_rear_saturation,        'cardColor_rearSaturation'],\n                        [Lang.Blocks.drone_cardcolor_rear_value,             'cardColor_rearValue'],\n                        [Lang.Blocks.drone_cardcolor_rear_lightness,         'cardColor_rearLightness'],\n                    ],\n                    value     : 'cardColor_frontColor',                        // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_value_card',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.card(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_cardcolor_front_color,            'cardColor_frontColor'],\n                                    [Lang.Blocks.drone_cardcolor_rear_color,             'cardColor_rearColor'],\n                                    [Lang.Blocks.drone_cardcolor_card,                   'cardColor_card'],\n                                    [Lang.Blocks.drone_cardcolor_front_hue,              'cardColor_frontHue'],\n                                    [Lang.Blocks.drone_cardcolor_front_saturation,       'cardColor_frontSaturation'],\n                                    [Lang.Blocks.drone_cardcolor_front_value,            'cardColor_frontValue'],\n                                    [Lang.Blocks.drone_cardcolor_front_lightness,        'cardColor_frontLightness'],\n                                    [Lang.Blocks.drone_cardcolor_rear_hue,               'cardColor_rearHue'],\n                                    [Lang.Blocks.drone_cardcolor_rear_saturation,        'cardColor_rearSaturation'],\n                                    [Lang.Blocks.drone_cardcolor_rear_value,             'cardColor_rearValue'],\n                                    [Lang.Blocks.drone_cardcolor_rear_lightness,         'cardColor_rearLightness'],\n                                ],\n                                value     : 'cardColor_frontColor',                        // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_value_etc: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_state_mode_flight,           'state_modeFlight'],\n                        [Lang.Blocks.drone_state_mode_control_flight,   'state_modeControlFlight'],\n                        [Lang.Blocks.drone_state_mode_movement,         'state_modeMovement'],\n                        [Lang.Blocks.drone_state_headless,              'state_headless'],\n                        [Lang.Blocks.drone_state_control_speed,         'state_controlSpeed'],\n                        [Lang.Blocks.drone_state_sensor_orientation,    'state_sensorOrientation'],\n                        [Lang.Blocks.drone_state_battery,               'state_battery'],\n                    ],\n                    value     : 'state_battery',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_value_etc',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.state(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_state_mode_flight,           'state_modeFlight'],\n                                    [Lang.Blocks.drone_state_mode_control_flight,   'state_modeControlFlight'],\n                                    [Lang.Blocks.drone_state_mode_movement,         'state_modeMovement'],\n                                    [Lang.Blocks.drone_state_headless,              'state_headless'],\n                                    [Lang.Blocks.drone_state_control_speed,         'state_controlSpeed'],\n                                    [Lang.Blocks.drone_state_sensor_orientation,    'state_sensorOrientation'],\n                                    [Lang.Blocks.drone_state_battery,               'state_battery'],\n                                ],\n                                value     : 'state_battery',                               // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_value_button: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button,         'button_button'],\n                        [Lang.Blocks.controller_button_event,   'button_event'],\n                    ],\n                    value     : 'button_button',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_controller_value_button',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.button(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_button,         'button_button'],\n                                    [Lang.Blocks.controller_button_event,   'button_event'],\n                                ],\n                                value     : 'button_button',                               // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_value_joystick: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_left_x,            'joystick_left_x'],\n                        [Lang.Blocks.controller_joystick_left_y,            'joystick_left_y'],\n                        [Lang.Blocks.controller_joystick_left_direction,    'joystick_left_direction'],\n                        [Lang.Blocks.controller_joystick_left_event,        'joystick_left_event'],\n                        [Lang.Blocks.controller_joystick_right_x,           'joystick_right_x'],\n                        [Lang.Blocks.controller_joystick_right_y,           'joystick_right_y'],\n                        [Lang.Blocks.controller_joystick_right_direction,   'joystick_right_direction'],\n                        [Lang.Blocks.controller_joystick_right_event,       'joystick_right_event'],\n                    ],\n                    value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_controller_value_joystick',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',             // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.joystick(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_joystick_left_x,            'joystick_left_x'],\n                                    [Lang.Blocks.controller_joystick_left_y,            'joystick_left_y'],\n                                    [Lang.Blocks.controller_joystick_left_direction,    'joystick_left_direction'],\n                                    [Lang.Blocks.controller_joystick_left_event,        'joystick_left_event'],\n                                    [Lang.Blocks.controller_joystick_right_x,           'joystick_right_x'],\n                                    [Lang.Blocks.controller_joystick_right_y,           'joystick_right_y'],\n                                    [Lang.Blocks.controller_joystick_right_direction,   'joystick_right_direction'],\n                                    [Lang.Blocks.controller_joystick_right_event,       'joystick_right_event'],\n                                ],\n                                value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_if_state: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_state_mode_flight_ready,     '16'],\n                        [Lang.Blocks.drone_state_mode_flight_start,     '17'],\n                        [Lang.Blocks.drone_state_mode_flight_takeoff,   '18'],\n                        [Lang.Blocks.drone_state_mode_flight_flight,    '19'],\n                        [Lang.Blocks.drone_state_mode_flight_landing,   '20'],\n                        [Lang.Blocks.drone_state_mode_flight_stop,      '32'],\n                    ],\n                    value     : '16',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_if_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const read        = Entry.hw.portData;\n                const state_fligh = 'state_modeFlight';    // paramsKeyMap에 정의된 이름 사용\n                const buttonevent = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n\n                //if (read[state_flight] == script.getField('STATE') && read[state_flight] == 16) {\n                //if (read[state_flight] == 0x10) {\n                if (Entry.hw.portData['state_modeFlight'] == script.getField('STATE')){\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.state(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_state_mode_flight_ready,     '16'],\n                                    [Lang.Blocks.drone_state_mode_flight_start,     '17'],\n                                    [Lang.Blocks.drone_state_mode_flight_takeoff,   '18'],\n                                    [Lang.Blocks.drone_state_mode_flight_flight,    '19'],\n                                    [Lang.Blocks.drone_state_mode_flight_landing,   '20'],\n                                    [Lang.Blocks.drone_state_mode_flight_stop,      '32'],\n                                ],\n                                value     : '16',\n                                fontSize  : 16,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_if_button_press: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button_front_left_top,      '1'],\n                        [Lang.Blocks.controller_button_front_left_bottom,   '2'],\n                        [Lang.Blocks.controller_button_front_right_top,     '4'],\n                        [Lang.Blocks.controller_button_front_right_bottom,  '8'],\n                        [Lang.Blocks.controller_button_top_left,            '16'],\n                        [Lang.Blocks.controller_button_top_right,           '32'],\n                        [Lang.Blocks.controller_button_center_up,           '64'],\n                        [Lang.Blocks.controller_button_center_left,         '128'],\n                        [Lang.Blocks.controller_button_center_right,        '256'],\n                        [Lang.Blocks.controller_button_center_down,         '512'],\n                        [Lang.Blocks.controller_button_bottom_left,         '1024'],\n                        [Lang.Blocks.controller_button_bottom_right,        '2048'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_edu_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const read        = Entry.hw.portData;\n                const button      = 'button_button';    // paramsKeyMap에 정의된 이름 사용\n                const buttonevent = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n\n                if (read[button] == script.getField('BUTTON') && read[buttonevent] == 2) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.button_pressed(%1)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_button_front_left_top,      '1'],\n                                    [Lang.Blocks.controller_button_front_left_bottom,   '2'],\n                                    [Lang.Blocks.controller_button_front_right_top,     '4'],\n                                    [Lang.Blocks.controller_button_front_right_bottom,  '8'],\n                                    [Lang.Blocks.controller_button_top_left,            '16'],\n                                    [Lang.Blocks.controller_button_top_right,           '32'],\n                                    [Lang.Blocks.controller_button_center_up,           '64'],\n                                    [Lang.Blocks.controller_button_center_left,         '128'],\n                                    [Lang.Blocks.controller_button_center_right,        '256'],\n                                    [Lang.Blocks.controller_button_center_down,         '512'],\n                                    [Lang.Blocks.controller_button_bottom_left,         '1024'],\n                                    [Lang.Blocks.controller_button_bottom_right,        '2048'],\n                                ],\n                                value     : '1',                                           // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_if_joystick_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.common_right, 'joystick_right_direction'],\n                    ],\n                    value     : 'joystick_left_direction',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_direction_left_up,     '17'],\n                        [Lang.Blocks.controller_joystick_direction_up,          '18'],\n                        [Lang.Blocks.controller_joystick_direction_right_up,    '20'],\n                        [Lang.Blocks.controller_joystick_direction_left,        '33'],\n                        [Lang.Blocks.controller_joystick_direction_center,      '34'],\n                        [Lang.Blocks.controller_joystick_direction_right,       '36'],\n                        [Lang.Blocks.controller_joystick_direction_left_down,   '65'],\n                        [Lang.Blocks.controller_joystick_direction_down,        '66'],\n                        [Lang.Blocks.controller_joystick_direction_right_down,  '68'],\n                    ],\n                    value     : '34',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_edu_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE   : 0,\n                DIRECTION: 1,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const read   = Entry.hw.portData;\n                const device = script.getField('DEVICE');  // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION'))\n                {\n                    return true;\n                }\n                else\n                {\n                    return false;\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.joystick_direction(%1, %2)',\n                        blockType : 'param',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_left, 'joystick_left_direction'],\n                                    [Lang.Blocks.common_right, 'joystick_right_direction'],\n                                ],\n                                value     : 'joystick_left_direction',                     // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_joystick_direction_left_up,     '17'],\n                                    [Lang.Blocks.controller_joystick_direction_up,          '18'],\n                                    [Lang.Blocks.controller_joystick_direction_right_up,    '20'],\n                                    [Lang.Blocks.controller_joystick_direction_left,        '33'],\n                                    [Lang.Blocks.controller_joystick_direction_center,      '34'],\n                                    [Lang.Blocks.controller_joystick_direction_right,       '36'],\n                                    [Lang.Blocks.controller_joystick_direction_left_down,   '65'],\n                                    [Lang.Blocks.controller_joystick_direction_down,        '66'],\n                                    [Lang.Blocks.controller_joystick_direction_right_down,  '68'],\n                                ],\n                                value     : '34',                                          // 초기 선택항목 지정\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n\n\n\n\n        robolink_codrone_edu_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_edu_light_manual_single_off',\n            },\n            paramsKeyMap: {\n                TARGET: 0\n            },\n            class   : 'light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                return Entry.robolink_base.setLightManual(script, target, 0xffff, 0);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'LED_off(%1)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null, null],\n                type  : 'robolink_codrone_edu_light_color_preset',\n            },\n            paramsKeyMap: {\n                TARGET    : 0,\n                COLOR     : 1,\n                BRIGHTNESS: 2,\n            },\n            class   : 'light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                const target = parseInt(script.getStringValue('TARGET'));\n                //return Entry.robolink_base.setLightModeColorString(script, target, mode, interval, colorString);\n                return Entry.robolink_base.setLightModeColorString(script, target, mode, interval, colorString);\n            },\n            \n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_preset(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_brightness_on,    '220'],\n                                    [Lang.Blocks.common_light_brightness_off,   '0'],\n                                    [Lang.Blocks.common_light_brightness_b25,   '75'],\n                                    [Lang.Blocks.common_light_brightness_b50,   '125'],\n                                    [Lang.Blocks.common_light_brightness_b75,   '200'],\n                                    [Lang.Blocks.common_light_brightness_b100,  '255'],\n                                ],\n                                value     : '220',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },            \n        },\n\n        robolink_codrone_edu_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'text', params: ['0x07'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                TARGET    : 0,\n                FLAGS     : 1,\n                BRIGHTNESS: 2,\n            },\n            class   : 'light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                const target = parseInt(script.getStringValue('TARGET'));\n                return Entry.robolink_base.setLightManual(script, target, flags, brightness);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'light_color_manual(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_light_color_input',\n            },\n            paramsKeyMap: {\n                TARGET  : 0,\n                RED     : 1,\n                GREEN   : 2,\n                BLUE    : 3,\n                MODE    : 4,\n                INTERVAL: 5,\n            },\n            class   : 'light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval = script.getNumberValue('INTERVAL');\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                const target = parseInt(script.getStringValue('TARGET'));\n                return Entry.robolink_base.setLightModeColor(script, target, mode, interval, red, green, blue);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'light_color_input(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'robolink_codrone_edu_light_color_select',\n            },\n            paramsKeyMap: {\n                TARGET  : 0,\n                COLOR   : 1,\n                MODE    : 2,\n                INTERVAL: 3,\n            },\n            class   : 'light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                const target = parseInt(script.getStringValue('TARGET'));\n                return Entry.robolink_base.setLightModeColorString(script, target, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'light_color_select(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n\n\n\n\n        robolink_codrone_edu_controller_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_controller_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'controller_light',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.robolink_base.setLightManual(script, 0x20, 0xffff, 0);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Controller.light_off()',\n                    },\n                ],\n            },\n        },        \n\n        robolink_codrone_edu_controller_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'robolink_codrone_edu_controller_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.robolink_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.light_color_preset(%1, %2)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_brightness_on,    '220'],\n                                    [Lang.Blocks.common_light_brightness_off,   '0'],\n                                    [Lang.Blocks.common_light_brightness_b25,   '75'],\n                                    [Lang.Blocks.common_light_brightness_b50,   '125'],\n                                    [Lang.Blocks.common_light_brightness_b75,   '200'],\n                                    [Lang.Blocks.common_light_brightness_b100,  '255'],\n                                ],\n                                value     : '220',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x07'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'controller_light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.robolink_base.setLightManual(script, 0x20, flags, brightness);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.light_color_manual(%1, %2)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'controller_light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval = script.getNumberValue('INTERVAL');\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                return Entry.robolink_base.setLightModeColor(script, 0x20, mode, interval, red, green, blue);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.light_color_input(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'robolink_codrone_edu_controller_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'controller_light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.robolink_base.setLightModeColorString(script, 0x20, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.light_color_select(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'drone_light',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.robolink_base.setLightManual(script, 0x10, 0xff, 0);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.light_off()',\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_light_color_preset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_brightness_on,    '220'],\n                        [Lang.Blocks.common_light_brightness_off,   '0'],\n                        [Lang.Blocks.common_light_brightness_b25,   '75'],\n                        [Lang.Blocks.common_light_brightness_b50,   '125'],\n                        [Lang.Blocks.common_light_brightness_b75,   '200'],\n                        [Lang.Blocks.common_light_brightness_b100,  '255'],\n                    ],\n                    value     : '220',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null],\n                type  : 'robolink_codrone_edu_drone_light_color_preset',\n            },\n            paramsKeyMap: {\n                COLOR     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode        = 0x22;\n                const interval    = parseInt(script.getField('BRIGHTNESS'), 10);\n                const colorString = script.getField('COLOR');\n                return Entry.robolink_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_preset(%1, %2)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_brightness_on,    '220'],\n                                    [Lang.Blocks.common_light_brightness_off,   '0'],\n                                    [Lang.Blocks.common_light_brightness_b25,   '75'],\n                                    [Lang.Blocks.common_light_brightness_b50,   '125'],\n                                    [Lang.Blocks.common_light_brightness_b75,   '200'],\n                                    [Lang.Blocks.common_light_brightness_b100,  '255'],\n                                ],\n                                value     : '200',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x3F'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.robolink_base.setLightManual(script, 0x10, flags, brightness);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_manual(%1, %2)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_drone_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                const interval = script.getNumberValue('INTERVAL');\n                return Entry.robolink_base.setLightModeColor(script, 0x10, mode, interval, red, green, blue);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_input(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red,            'red'],\n                        [Lang.Blocks.common_light_color_green,          'green'],\n                        [Lang.Blocks.common_light_color_blue,           'blue'],\n                        [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                        [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                        [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                        [Lang.Blocks.common_light_color_white,          'white'],\n                        [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                        [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                        [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                        [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                        [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'robolink_codrone_edu_drone_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.robolink_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.light_color_select(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_color_red,            'red'],\n                                    [Lang.Blocks.common_light_color_green,          'green'],\n                                    [Lang.Blocks.common_light_color_blue,           'blue'],\n                                    [Lang.Blocks.common_light_color_yellow,         'yellow'],\n                                    [Lang.Blocks.common_light_color_magenta,        'magenta'],\n                                    [Lang.Blocks.common_light_color_cyan,           'cyan'],\n                                    [Lang.Blocks.common_light_color_white,          'white'],\n                                    [Lang.Blocks.common_light_color_sunset,         'sunset'],\n                                    [Lang.Blocks.common_light_color_cottoncandy,    'cottonCandy'],\n                                    [Lang.Blocks.common_light_color_muscat,         'muscat'],\n                                    [Lang.Blocks.common_light_color_strawberrymilk, 'strawberryMilk'],\n                                    [Lang.Blocks.common_light_color_emerald,        'emerald'],\n                                    [Lang.Blocks.common_light_color_lavender,       'lavender'],\n                                ],\n                                value     : 'red',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_light_mode_hold,            '2'],   // BodyHold            = 0x22\n                                    [Lang.Blocks.common_light_mode_flicker,         '3'],   // BodyFlicker         = 0x23\n                                    [Lang.Blocks.common_light_mode_flicker_double,  '4'],   // BodyFlickerDouble   = 0x24\n                                    [Lang.Blocks.common_light_mode_dimming,         '5'],   // BodyDimming         = 0x25\n                                    [Lang.Blocks.common_light_mode_sunrise,         '6'],   // BodyS8unrise        = 0x26\n                                    [Lang.Blocks.common_light_mode_sunset,          '7'],   // BodySunset          = 0x27\n                                    [Lang.Blocks.common_light_mode_rainbow,         '8'],   // BodyRainbow         = 0x28\n                                    [Lang.Blocks.common_light_mode_rainbow2,        '9'],   // BodyRainbow2        = 0x29\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_display_clear_all: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_edu_controller_display_clear_all',\n            },\n            paramsKeyMap: {\n                PIXEL: 0,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                return Entry.robolink_base.setDisplayClearAll(script, 0x20, pixel);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_clear_all(%1)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_display_clear: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_display_clear',\n            },\n            paramsKeyMap: {\n                X     : 0,\n                Y     : 1,\n                WIDTH : 2,\n                HEIGHT: 3,\n                PIXEL : 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const x      = script.getNumberValue('X');\n                const y      = script.getNumberValue('Y');\n                const width  = script.getNumberValue('WIDTH');\n                const height = script.getNumberValue('HEIGHT');\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                return Entry.robolink_base.setDisplayClear(script, 0x20, pixel, x, y, width, height);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_clear(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_display_draw_point: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    null,\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_display_draw_point',\n            },\n            paramsKeyMap: {\n                X    : 0,\n                Y    : 1,\n                PIXEL: 2,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const x     = script.getNumberValue('X');\n                const y     = script.getNumberValue('Y');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                return Entry.robolink_base.setDisplayDrawPoint(script, 0x20, x, y, pixel);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_point(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_display_draw_shape: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_shape_line, '1'],\n                        [Lang.Blocks.controller_display_shape_square, '2'],\n                        [Lang.Blocks.controller_display_shape_ellipse, '3'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                \n\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'text', params: ['54'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['20'] },\n                    { type: 'text', params: ['20'] },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_display_draw_shape',\n            },\n            paramsKeyMap: {\n                SHAPE   : 0,\n                X1      : 1,\n                Y1      : 2,\n                X2      : 3,\n                Y2      : 4,\n                PIXEL   : 5,\n                LINE    : 6,\n                FLAGFILL: 7,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const shape = parseInt(script.getField('SHAPE'), 10);\n                const x1    = script.getNumberValue('X1');\n                const y1    = script.getNumberValue('Y1');\n                const x2    = script.getNumberValue('X2');\n                const y2    = script.getNumberValue('Y2');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                const line  = parseInt(script.getField('LINE'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n\n                if(shape == 1)\n                {\n                    return Entry.robolink_base.setDisplayDrawLine(script, 0x20, x1, y1, x2, y2, pixel, line);\n                }\n                else if(shape == 2)\n                {\n                    return Entry.robolink_base.setDisplayDrawRect(script, 0x20, x1, y1, x2, y2, pixel, flagFill, line);\n                    //return Entry.robolink_base.setDisplayDrawRect(script, 0x20, x, y, width, height, pixel, flagFill, line);\n                }\n                else if(shape == 3)\n                {\n                    return Entry.robolink_base.setDisplayDrawCircle(script, 0x20, x1, y1, x2, pixel, flagFill);\n                    //return Entry.robolink_base.setDisplayDrawCircle(script, 0x20, x, y, radius, pixel, flagFill);\n                }    \n\n            },\n            /*\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_line(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_line_solid, '0'],\n                                    [Lang.Blocks.controller_display_line_dotted, '1'],\n                                    [Lang.Blocks.controller_display_line_dashed, '2'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n            */\n        },\n\n        robolink_codrone_edu_controller_display_draw_line: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    { type: 'text', params: ['96'] },\n                    { type: 'text', params: ['48'] },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_display_draw_line',\n            },\n            paramsKeyMap: {\n                X1   : 0,\n                Y1   : 1,\n                X2   : 2,\n                Y2   : 3,\n                PIXEL: 4,\n                LINE : 5,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const x1    = script.getNumberValue('X1');\n                const y1    = script.getNumberValue('Y1');\n                const x2    = script.getNumberValue('X2');\n                const y2    = script.getNumberValue('Y2');\n                const pixel = parseInt(script.getField('PIXEL'), 10);\n                const line  = parseInt(script.getField('LINE'), 10);\n                return Entry.robolink_base.setDisplayDrawLine(script, 0x20, x1, y1, x2, y2, pixel, line);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_line(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_line_solid, '0'],\n                                    [Lang.Blocks.controller_display_line_dotted, '1'],\n                                    [Lang.Blocks.controller_display_line_dashed, '2'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_display_draw_rect: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_line_solid, '0'],\n                        [Lang.Blocks.controller_display_line_dotted, '1'],\n                        [Lang.Blocks.controller_display_line_dashed, '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_display_draw_rect',\n            },\n            paramsKeyMap: {\n                X       : 0,\n                Y       : 1,\n                WIDTH   : 2,\n                HEIGHT  : 3,\n                PIXEL   : 4,\n                FLAGFILL: 5,\n                LINE    : 6,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const x        = script.getNumberValue('X');\n                const y        = script.getNumberValue('Y');\n                const width    = script.getNumberValue('WIDTH');\n                const height   = script.getNumberValue('HEIGHT');\n                const pixel    = parseInt(script.getField('PIXEL'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n                const line     = parseInt(script.getField('LINE'), 10);\n                return Entry.robolink_base.setDisplayDrawRect(script, 0x20, x, y, width, height, pixel, flagFill, line);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_rect(%1, %2, %3, %4, %5, %6)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_flagfill_off, '0'],\n                                    [Lang.Blocks.controller_display_flagfill_on, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_line_solid, '0'],\n                                    [Lang.Blocks.controller_display_line_dotted, '1'],\n                                    [Lang.Blocks.controller_display_line_dashed, '2'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_display_draw_circle: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_flagfill_off, '0'],\n                        [Lang.Blocks.controller_display_flagfill_on, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['64'] },\n                    { type: 'text', params: ['32'] },\n                    { type: 'text', params: ['24'] },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_display_draw_circle',\n            },\n            paramsKeyMap: {\n                X       : 0,\n                Y       : 1,\n                RADIUS  : 2,\n                PIXEL   : 3,\n                FLAGFILL: 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const x        = script.getNumberValue('X');\n                const y        = script.getNumberValue('Y');\n                const radius   = script.getNumberValue('RADIUS');\n                const pixel    = parseInt(script.getField('PIXEL'), 10);\n                const flagFill = parseInt(script.getField('FLAGFILL'), 10);\n                return Entry.robolink_base.setDisplayDrawCircle(script, 0x20, x, y, radius, pixel, flagFill);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_circle(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_flagfill_off, '0'],\n                                    [Lang.Blocks.controller_display_flagfill_on, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_display_draw_string: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_font_5x8, '0'],\n                        [Lang.Blocks.controller_display_font_10x16, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['39'] },\n                    { type: 'text', params: ['16'] },\n                    null,\n                    null,\n                    { type: 'text', params: ['HELLO'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_display_draw_string',\n            },\n            paramsKeyMap: {\n                X     : 0,\n                Y     : 1,\n                FONT  : 2,\n                PIXEL : 3,\n                STRING: 4,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const x      = script.getNumberValue('X');\n                const y      = script.getNumberValue('Y');\n                const font   = parseInt(script.getField('FONT'), 10);\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                const string = script.getStringValue('STRING');\n                return Entry.robolink_base.setDisplayDrawString(script, 0x20, x, y, font, pixel, string);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_string(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_font_5x8, '0'],\n                                    [Lang.Blocks.controller_display_font_10x16, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_display_draw_string_align: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_align_left, '0'],\n                        [Lang.Blocks.controller_display_align_center, '1'],\n                        [Lang.Blocks.controller_display_align_right, '2'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_font_5x8, '0'],\n                        [Lang.Blocks.controller_display_font_10x16, '1'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_display_pixel_black, '0'],\n                        [Lang.Blocks.controller_display_pixel_white, '1'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0'] },\n                    { type: 'text', params: ['128'] },\n                    { type: 'text', params: ['42'] },\n                    null,\n                    null,\n                    null,\n                    { type: 'text', params: ['DRONE'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_display_draw_string_align',\n            },\n            paramsKeyMap: {\n                XSTART: 0,\n                XEND  : 1,\n                Y     : 2,\n                ALIGN : 3,\n                FONT  : 4,\n                PIXEL : 5,\n                STRING: 6,\n            },\n            class   : 'controller_display',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const xStart = script.getNumberValue('XSTART');\n                const xEnd   = script.getNumberValue('XEND');\n                const y      = script.getNumberValue('Y');\n                const align  = parseInt(script.getField('ALIGN'), 10);\n                const font   = parseInt(script.getField('FONT'), 10);\n                const pixel  = parseInt(script.getField('PIXEL'), 10);\n                const string = script.getStringValue('STRING');\n                return Entry.robolink_base.setDisplayDrawStringAlign(script, 0x20, xStart, xEnd, y, align, font, pixel, string);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.display_draw_string_align(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_align_left, '0'],\n                                    [Lang.Blocks.controller_display_align_center, '1'],\n                                    [Lang.Blocks.controller_display_align_right, '2'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_font_5x8, '0'],\n                                    [Lang.Blocks.controller_display_font_10x16, '1'],\n                                ],\n                                value     : '1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_display_pixel_black, '0'],\n                                    [Lang.Blocks.controller_display_pixel_white, '1'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_buzzer_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_edu_controller_buzzer_off',\n            },\n            paramsKeyMap: {\n                TARGET: 0\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                return Entry.robolink_base.setBuzzerStop(script, target);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_off(%1)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_buzzer_scale: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_instant, '1'],\n                        [Lang.Blocks.common_reserve, '2'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },                \n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, null, { type: 'text', params: ['1'] }, null, null],\n                type  : 'robolink_codrone_edu_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                OCTAVE: 1,\n                SCALE : 2,\n                TIME  : 3,\n                MODE  : 4,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n                const mode  = parseInt(script.getField('MODE'), 10);\n\n                if(mode == 1)\n                {\n                    if (scale == -1) {\n                        return Entry.robolink_base.setBuzzerMute(script, target, time, true, true);                    \n                    } else {\n                        return Entry.robolink_base.setBuzzerScale(script, target, octave, scale, time, true, true);\n                    }\n                }\n                else if(mode == 2)\n                {\n                    if (scale == -1) {\n                        return Entry.robolink_base.setBuzzerMute(script, target, time, false, false);\n                    } else {\n                        return Entry.robolink_base.setBuzzerScale(script, target, octave, scale, time, false, false);\n                    }\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_scale(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    ['1', '0'],\n                                    ['2', '1'],\n                                    ['3', '2'],\n                                    ['4', '3'],\n                                    ['5', '4'],\n                                    ['6', '5'],\n                                    ['7', '6'],\n                                    ['8', '7'],\n                                ],\n                                value     : '4',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_buzzer_mute, '-1'],\n                                    [Lang.Blocks.controller_buzzer_c,    '0'],\n                                    [Lang.Blocks.controller_buzzer_cs,   '1'],\n                                    [Lang.Blocks.controller_buzzer_d,    '2'],\n                                    [Lang.Blocks.controller_buzzer_ds,   '3'],\n                                    [Lang.Blocks.controller_buzzer_e,    '4'],\n                                    [Lang.Blocks.controller_buzzer_f,    '5'],\n                                    [Lang.Blocks.controller_buzzer_fs,   '6'],\n                                    [Lang.Blocks.controller_buzzer_g,    '7'],\n                                    [Lang.Blocks.controller_buzzer_gs,   '8'],\n                                    [Lang.Blocks.controller_buzzer_a,    '9'],\n                                    [Lang.Blocks.controller_buzzer_as,   '10'],\n                                    [Lang.Blocks.controller_buzzer_b,    '11'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_buzzer_scale_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_buzzer_scale_delay',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                OCTAVE: 1,\n                SCALE : 2,\n                TIME  : 3,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.robolink_base.setBuzzerMute(script, target, time, true, true);\n                } else {\n                    return Entry.robolink_base.setBuzzerScale(script, target, octave, scale, time, true, true);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_scale_delay(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    ['1', '0'],\n                                    ['2', '1'],\n                                    ['3', '2'],\n                                    ['4', '3'],\n                                    ['5', '4'],\n                                    ['6', '5'],\n                                    ['7', '6'],\n                                    ['8', '7'],\n                                ],\n                                value     : '4',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_buzzer_mute, '-1'],\n                                    [Lang.Blocks.controller_buzzer_c,    '0'],\n                                    [Lang.Blocks.controller_buzzer_cs,   '1'],\n                                    [Lang.Blocks.controller_buzzer_d,    '2'],\n                                    [Lang.Blocks.controller_buzzer_ds,   '3'],\n                                    [Lang.Blocks.controller_buzzer_e,    '4'],\n                                    [Lang.Blocks.controller_buzzer_f,    '5'],\n                                    [Lang.Blocks.controller_buzzer_fs,   '6'],\n                                    [Lang.Blocks.controller_buzzer_g,    '7'],\n                                    [Lang.Blocks.controller_buzzer_gs,   '8'],\n                                    [Lang.Blocks.controller_buzzer_a,    '9'],\n                                    [Lang.Blocks.controller_buzzer_as,   '10'],\n                                    [Lang.Blocks.controller_buzzer_b,    '11'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_buzzer_scale_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,    '0'],\n                        [Lang.Blocks.controller_buzzer_cs,   '1'],\n                        [Lang.Blocks.controller_buzzer_d,    '2'],\n                        [Lang.Blocks.controller_buzzer_ds,   '3'],\n                        [Lang.Blocks.controller_buzzer_e,    '4'],\n                        [Lang.Blocks.controller_buzzer_f,    '5'],\n                        [Lang.Blocks.controller_buzzer_fs,   '6'],\n                        [Lang.Blocks.controller_buzzer_g,    '7'],\n                        [Lang.Blocks.controller_buzzer_gs,   '8'],\n                        [Lang.Blocks.controller_buzzer_a,    '9'],\n                        [Lang.Blocks.controller_buzzer_as,   '10'],\n                        [Lang.Blocks.controller_buzzer_b,    '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_buzzer_scale_reserve',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                OCTAVE: 1,\n                SCALE : 2,\n                TIME  : 3,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n\n                if (scale == -1) {\n                    return Entry.robolink_base.setBuzzerMute(script, target, time, false, false);\n                } else {\n                    return Entry.robolink_base.setBuzzerScale(script, target, octave, scale, time, false, false);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_scale_reserve(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    ['1', '0'],\n                                    ['2', '1'],\n                                    ['3', '2'],\n                                    ['4', '3'],\n                                    ['5', '4'],\n                                    ['6', '5'],\n                                    ['7', '6'],\n                                    ['8', '7'],\n                                ],\n                                value     : '4',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.controller_buzzer_mute, '-1'],\n                                    [Lang.Blocks.controller_buzzer_c,    '0'],\n                                    [Lang.Blocks.controller_buzzer_cs,   '1'],\n                                    [Lang.Blocks.controller_buzzer_d,    '2'],\n                                    [Lang.Blocks.controller_buzzer_ds,   '3'],\n                                    [Lang.Blocks.controller_buzzer_e,    '4'],\n                                    [Lang.Blocks.controller_buzzer_f,    '5'],\n                                    [Lang.Blocks.controller_buzzer_fs,   '6'],\n                                    [Lang.Blocks.controller_buzzer_g,    '7'],\n                                    [Lang.Blocks.controller_buzzer_gs,   '8'],\n                                    [Lang.Blocks.controller_buzzer_a,    '9'],\n                                    [Lang.Blocks.controller_buzzer_as,   '10'],\n                                    [Lang.Blocks.controller_buzzer_b,    '11'],\n                                ],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_buzzer_hz: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_instant, '1'],\n                        [Lang.Blocks.common_reserve, '2'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },                \n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'text', params: ['1000'] }, { type: 'text', params: ['1'] }, null, null],\n                type  : 'robolink_codrone_edu_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                HZ    : 1,\n                TIME  : 2,\n                MODE  : 3,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const hz     = script.getNumberValue('HZ');\n                const time   = script.getNumberValue('TIME') * 1000;\n                const mode  = parseInt(script.getField('MODE'), 10);\n                \n                if(mode == 1)\n                {              \n                    return Entry.robolink_base.setBuzzerHz(script, target, hz, time, true, true);\n                }\n                else if(mode == 2)\n                {\n                    return Entry.robolink_base.setBuzzerHz(script, target, hz, time, false, false);\n                }\n            \n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_hz(%1, %2)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_buzzer_hz_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'text', params: ['1000'] }, { type: 'text', params: ['1'] }, null],\n                type  : 'robolink_codrone_edu_controller_buzzer_hz_delay',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                HZ    : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const hz     = script.getNumberValue('HZ');\n                const time   = script.getNumberValue('TIME') * 1000;\n                return Entry.robolink_base.setBuzzerHz(script, target, hz, time, true, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_hz_delay(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_buzzer_hz_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_drone, '0x10'],\n                        [Lang.Blocks.common_controller, '0x20'],\n                    ],\n                    value     : '0x20',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'text', params: ['1000'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_buzzer_hz_reserve',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                HZ    : 1,\n                TIME  : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const target = parseInt(script.getStringValue('TARGET'));\n                const hz     = script.getNumberValue('HZ');\n                const time   = script.getNumberValue('TIME') * 1000;\n                return Entry.robolink_base.setBuzzerHz(script, target, hz, time, false, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.buzzer_hz_reserve(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.common_drone, '0x10'],\n                                    [Lang.Blocks.common_controller, '0x20'],\n                                ],\n                                value     : '0x20',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_vibrator_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_controller_vibrator_off',\n            },\n            paramsKeyMap: {},\n            class       : 'vibrator',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.robolink_base.setVibratorStop(script, 0x20);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Controller.vibrator_off()',\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_vibrator_on_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'robolink_codrone_edu_controller_vibrator_on_delay',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.robolink_base.setVibrator(script, 0x20, timeOn, 0, timeOn, true, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.vibrator_on_delay(%1)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_vibrator_on_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, null],\n                type  : 'robolink_codrone_edu_controller_vibrator_on_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON: 0,\n            },\n            class   : 'vibrator',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const timeOn = script.getNumberValue('TIMEON') * 1000;\n                return Entry.robolink_base.setVibrator(script, 0x20, timeOn, 0, timeOn, false, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.vibrator_on_reserve(%1)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_vibrator_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_vibrator_delay',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.robolink_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, true, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.vibrator_delay(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_controller_vibrator_reserve: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['0.3'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_controller_vibrator_reserve',\n            },\n            paramsKeyMap: {\n                TIMEON : 0,\n                TIMEOFF: 1,\n                TIMERUN: 2,\n            },\n            class   : 'vibrator',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const timeOn  = script.getNumberValue('TIMEON') * 1000;\n                const timeOff = script.getNumberValue('TIMEOFF') * 1000;\n                const timeRun = script.getNumberValue('TIMERUN') * 1000;\n                return Entry.robolink_base.setVibrator(script, 0x20, timeOn, timeOff, timeRun, false, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Controller.vibrator_reserve(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_motor_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'motor',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.robolink_base.sendStop(script, 0x10);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.motor_stop()',\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_motorsingle: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type      : 'Dropdown',\n                    options   : [['1(FR)', '0'], ['2(RR)', '1'], ['3(RL)', '2'], ['4(FL)', '3']],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'text', params: ['120'] }, null],\n                type  : 'robolink_codrone_edu_drone_motorsingle',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const motorIndex = parseInt(script.getField('MOTORINDEX'), 10);\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.robolink_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.motor_single(%1, %2)',\n                        textParams: [\n                            {\n                                type      : 'Dropdown',\n                                options   : [['1(FR)', '0'], ['2(RR)', '1'], ['3(RL)', '2'], ['4(FL)', '3']],\n                                value     : '0',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_motorsingle_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, { type: 'text', params: ['120'] }, null],\n                type  : 'robolink_codrone_edu_drone_motorsingle_input',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const motorIndex = script.getNumberValue('MOTORINDEX') - 1;\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.robolink_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.motor_single_input(%1, %2)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n\n        robolink_codrone_edu_drone_control_flip: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_flip_front, '0x14'],\n                        [Lang.Blocks.drone_control_flip_rear,  '0x15'],\n                        [Lang.Blocks.drone_control_flip_left,  '0x16'],\n                        [Lang.Blocks.drone_control_flip_right, '0x17'],\n                    ],\n                    value     : '0x14',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_edu_drone_control_flip',\n            },\n            paramsKeyMap: {\n                FLIP: 0,\n            },\n            class   : 'control_flight',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                //const headless = script.getField('HEADLESS');\n                //return Entry.robolink_base.sendCommand(script, 0x10, 0x03, headless);\n                const flip = parseInt(script.getStringValue('FLIP'));\n                //transferCommand(target, 0x07, eventFlight); // 0x07 : CommandType::FlightEvent\n                //return Entry.robolink_base.setEventFlight(script, 0x10, flip, 0); // 0x18 : FlightEvent::return\n                return Entry.robolink_base.sendCommand(script, 0x10, 0x07, flip); // 0x18 : FlightEvent::return\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.headless(%1)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_headless_headless, '1'],\n                                    [Lang.Blocks.drone_headless_normal,   '2'],\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n\n        robolink_codrone_edu_drone_control_drone_return_home: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_control_drone_return_home',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n              //  return Entry.robolink_base.setEventFlight(script, 0x10, 0x18, 5000); // 0x11 : FlightEvent::TakeOff\n             \n              return Entry.robolink_base.setEventFlight(script, 0x10, 0x18, 0); // 0x18 : FlightEvent::return\n              //return Entry.robolink_base.sendCommand(script, 0x10, 0x07, 0x18); // 0x18 : FlightEvent::return\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.takeoff()',\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_drone_takeoff: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_control_drone_takeoff',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.robolink_base.setEventFlight(script, 0x10, 0x11, 5000); // 0x11 : FlightEvent::TakeOff\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.takeoff()',\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_drone_landing: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_control_drone_landing',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.robolink_base.setEventFlight(script, 0x10, 0x12, 5000); // 0x12 : FlightEvent::Landing\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.landing()',\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_drone_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_control_drone_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.robolink_base.sendStop(script, 0x10);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.stop()',\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_headless: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_headless_headless, '1'],\n                        [Lang.Blocks.drone_headless_normal,   '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_edu_drone_control_headless',\n            },\n            paramsKeyMap: {\n                HEADLESS: 0,\n            },\n            class   : 'control_flight',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const headless = script.getField('HEADLESS');\n                return Entry.robolink_base.sendCommand(script, 0x10, 0x03, headless);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.headless(%1)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_headless_headless, '1'],\n                                    [Lang.Blocks.drone_headless_normal,   '2'],\n                                ],\n                                value     : '2',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_drone_reset_heading: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_edu_drone_control_drone_reset_heading',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                return Entry.robolink_base.sendCommand(script, 0x10, 0x07, 0xA0); // 0x22 : CommandType::FlightEvent  // 0xA0 : FlightEvent::ResetHeading\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Drone.reset_heading()',\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_quad_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['0'] }, null],\n                type  : 'robolink_codrone_edu_drone_control_quad_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n\n                return Entry.robolink_base.sendControlQuadSingle(script, 0x10, controlTarget, value, 0, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_quad_one(%1, %2)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                                    [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                                    [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                                    [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                                ],\n                                value     : 'control_quad8_pitch',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_quad_one_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['100'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_drone_control_quad_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n                TIME         : 2,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n                const time          = script.getNumberValue('TIME') * 1000;\n\n                return Entry.robolink_base.sendControlQuadSingle(script, 0x10, controlTarget, value, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_quad_one_delay(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_roll,     'control_quad8_roll'],\n                                    [Lang.Blocks.drone_control_quad_pitch,    'control_quad8_pitch'],\n                                    [Lang.Blocks.drone_control_quad_yaw,      'control_quad8_yaw'],\n                                    [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                                ],\n                                value     : 'control_quad8_pitch',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_quad: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_drone_control_quad',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n\n                return Entry.robolink_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, 0, false);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_quad(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_quad_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_edu_drone_control_quad_delay',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n                TIME    : 4,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n                const time     = script.getNumberValue('TIME') * 1000;\n\n                return Entry.robolink_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_quad_delay(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_position_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  'pitch_forward'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, 'pitch_backward'],\n                        [Lang.Blocks.drone_control_quad_roll_left,      'roll_left'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     'roll_right'],\n                        [Lang.Blocks.drone_control_quad_throttle_up,    'throttle_up'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  'throttle_down'],\n                    ],\n                    value     : 'pitch_forward',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_next, 0],\n                        [Lang.Blocks.common_wait, 1],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['1'] }, { type: 'number', params: ['1'] }, null, null],\n                type  : 'robolink_codrone_edu_drone_control_position_one',\n            },\n            paramsKeyMap: {\n                CONTROLDIRECTION: 0,\n                DISTANCE        : 1,\n                SPEED           : 2,\n                WAIT            : 3,\n            },\n            class   : 'control_position',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const controlDirection = script.getField('CONTROLDIRECTION');\n                const distance         = script.getNumberValue('DISTANCE');\n                const speed            = script.getNumberValue('SPEED');\n                let   time             = 40;\n                const wait             = script.getNumberValue('WAIT');\n                \n                if( speed > 0 && wait == 1)\n                {\n                    time = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                let x = 0;\n                let y = 0;\n                let z = 0;\n\n                switch( controlDirection )\n                {\n                    case    'pitch_forward':   x = distance;   break;\n                    case    'pitch_backward':  x = -distance;  break;\n                    case    'roll_left':       y = distance;   break;\n                    case    'roll_right':      y = -distance;  break;\n                    case    'throttle_up':     z = distance;   break;\n                    default:                z    = -distance;  break;\n                }\n\n                return Entry.robolink_base.sendControlPosition(script, 0x10, x, y, z, speed, 0, 0, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_position_one(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_pitch_forward,  'pitch_forward'],\n                                    [Lang.Blocks.drone_control_quad_pitch_backward, 'pitch_backward'],\n                                    [Lang.Blocks.drone_control_quad_roll_left,      'roll_left'],\n                                    [Lang.Blocks.drone_control_quad_roll_right,     'roll_right'],\n                                    [Lang.Blocks.drone_control_quad_throttle_up,    'throttle_up'],\n                                    [Lang.Blocks.drone_control_quad_throttle_down,  'throttle_down'],\n                                ],\n                                value     : 'pitch_forward',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_position_turn: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                        [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_next, 0],\n                        [Lang.Blocks.common_wait, 1],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['90'] },\n                    { type: 'number', params: ['45'] },\n                    null,\n                    null\n                ],\n                type: 'robolink_codrone_edu_drone_control_position_turn',\n            },\n            paramsKeyMap: {\n                DIRECTION_YAW: 0,\n                DEGREE_YAW   : 1,\n                SPEED_YAW    : 2,\n                WAIT         : 3,\n            },\n            class   : 'control_position',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const directionYaw = script.getNumberValue('DIRECTION_YAW');\n                const degree       = script.getNumberValue('DEGREE_YAW');\n                const yaw          = directionYaw * degree;\n                const speedYaw     = script.getNumberValue('SPEED_YAW');\n                const wait             = script.getNumberValue('WAIT');\n\n                let time = 40;\n\n                if( speedYaw > 0 && wait == 1)\n                {\n                    time = Math.abs(degree / speedYaw) * 2 * 1000 + 3000;\n                }\n\n                return Entry.robolink_base.sendControlPosition(script, 0x10, 0, 0, 0, 0, yaw, speedYaw, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_position_turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                                    [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_position_location: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_next, 0],\n                        [Lang.Blocks.common_wait, 1],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                    null],\n                type: 'robolink_codrone_edu_drone_control_position_location',\n            },\n            paramsKeyMap: {\n                DIRECTION_PITCH   : 0,\n                DISTANCE_PITCH    : 1,\n                DIRECTION_ROLL    : 2,\n                DISTANCE_ROLL     : 3,\n                DIRECTION_THROTTLE: 4,\n                DISTANCE_THROTTLE : 5,\n                SPEED             : 6,\n                WAIT              : 7,\n            },\n            class   : 'control_position',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const directionPitch    = script.getNumberValue('DIRECTION_PITCH');\n                const directionRoll     = script.getNumberValue('DIRECTION_ROLL');\n                const directionThrottle = script.getNumberValue('DIRECTION_THROTTLE');\n                \n                const x = directionPitch     * script.getNumberValue('DISTANCE_PITCH');\n                const y = directionRoll      * script.getNumberValue('DISTANCE_ROLL');\n                const z = directionThrottle  * script.getNumberValue('DISTANCE_THROTTLE');\n\n                const distance = Math.sqrt((x * x) + (y * y) + (z * z));\n\n                const speed = script.getNumberValue('SPEED');\n\n                const wait             = script.getNumberValue('WAIT');\n\n                let time = 40;\n\n                if( speed > 0 && wait == 1) \n                {\n                    time = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                return Entry.robolink_base.sendControlPosition(script, 0x10, x, y, z, speed, 0, 0, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_position_location(%1, %2, %3, %4, %5, %6, %7)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                                    [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                                    [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                                    [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n\n        robolink_codrone_edu_drone_control_position_location_turn: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                        [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                        [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                        [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                        [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                    ],\n                    value     : '+1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    null,\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                    { type: 'number', params: ['90'] },\n                    { type: 'number', params: ['45'] },\n                    null],\n                type: 'robolink_codrone_edu_drone_control_position_location_turn',\n            },\n            paramsKeyMap: {\n                DIRECTION_PITCH   : 0,\n                DISTANCE_PITCH    : 1,\n                DIRECTION_ROLL    : 2,\n                DISTANCE_ROLL     : 3,\n                DIRECTION_THROTTLE: 4,\n                DISTANCE_THROTTLE : 5,\n                SPEED             : 6,\n                DIRECTION_YAW     : 7,\n                DEGREE_YAW        : 8,\n                SPEED_YAW         : 9,\n            },\n            class   : 'control_position',\n            isNotFor: ['robolink_codrone_edu'],\n            func(sprite, script)\n            {\n                const directionPitch    = script.getNumberValue('DIRECTION_PITCH');\n                const directionRoll     = script.getNumberValue('DIRECTION_ROLL');\n                const directionThrottle = script.getNumberValue('DIRECTION_THROTTLE');\n                \n                const x = directionPitch     * script.getNumberValue('DISTANCE_PITCH');\n                const y = directionRoll      * script.getNumberValue('DISTANCE_ROLL');\n                const z = directionThrottle  * script.getNumberValue('DISTANCE_THROTTLE');\n\n                const distance = Math.sqrt((x * x) + (y * y) + (z * z));\n                const speed    = script.getNumberValue('SPEED');\n\n                const directionYaw = script.getNumberValue('DIRECTION_YAW');\n                const degree       = script.getNumberValue('DEGREE_YAW');\n                const yaw          = directionYaw * degree;\n                const speedYaw     = script.getNumberValue('SPEED_YAW');\n\n                let timePosition = 0;\n                let timeRotation = 0;\n\n                if( speed > 0 )\n                {\n                    timePosition = Math.abs(distance / speed) * 1000 + Math.min(1000 * speed, 3000) + 3000;\n                }\n\n                if( speedYaw > 0 )\n                {\n                    timeRotation = Math.abs(degree / speedYaw) * 2 * 1000 + 3000;\n                }\n\n                const time = Math.max(timePosition, timeRotation);\n\n                return Entry.robolink_base.sendControlPosition(script, 0x10, x, y, z, speed, yaw, speedYaw, time, true);\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax    : 'Drone.control_position_location_turn(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10)',\n                        textParams: [\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_pitch_forward,  '+1'],\n                                    [Lang.Blocks.drone_control_quad_pitch_backward, '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_roll_left,      '+1'],\n                                    [Lang.Blocks.drone_control_quad_roll_right,     '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_throttle_up,    '+1'],\n                                    [Lang.Blocks.drone_control_quad_throttle_down,  '-1'],\n                                ],\n                                value     : '+1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type   : 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.drone_control_quad_yaw_cw,  '-1'],\n                                    [Lang.Blocks.drone_control_quad_yaw_ccw, '+1'],\n                                ],\n                                value     : '-1',\n                                fontSize  : 11,\n                                bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter : Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type  : 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\n\nmodule.exports = Entry.robolink_codrone_edu;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robolink_codrone_mini.js",
    "content": "/* eslint-disable prettier/prettier */\n/* eslint-disable brace-style */\n/* eslint-disable max-len */\n/* jshint esversion: 6 */\n'use strict';\n\n/***************************************************************************************\n *  장치 기본 정의\n ***************************************************************************************/\n\nEntry.robolink_codrone_mini = \n{\n    id       : '4A.2',\n    name     : 'robolink_codrone_mini',\n    url      : 'http://www.robolink.co.kr',\n    imageName: 'robolink_codrone_mini.png',\n    title    : {\n        en: 'ROBOLINK CODRONE MINI',\n        ko: '로보링크 코드론 미니',\n    },\n\n    // 엔트리 정지시 하드웨어 초기화 로직\n    setZero() {\n        // 초기화\n        Entry.byrobot_base.transferBufferClear();\n\n        // 한 번에 명령을 전송하면 hw까지 제대로 전달되지 않는 경우가 있어\n        // 명령을 각각 분리하여 전송하게 함(2017.01.03)\n        for (let i = 0; i < 1; i++) {\n            if (Entry.hw.portData['state_modeFlight'] == 0x10)\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x01, 0); // 드론, command = 0x01 (Stop)\n            }\n            else\n            {\n                Entry.byrobot_base.transferCommand(0x10, 0x07, 0x12); // 0x12 : FlightEvent::Landing\n            }\n            Entry.byrobot_base.transferBuzzer(0x20, 0, 0, 0);\n            Entry.byrobot_base.transferLightManual(0x10, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightManual(0x20, 0xffff, 0); // LED 초기화(모두 꺼짐)\n            Entry.byrobot_base.transferLightModeColor(0x10, 0x22, 200, 255, 0, 0); // LED 초기화(드론)\n            Entry.byrobot_base.transferLightModeColor(0x20, 0x22, 200, 255, 0, 0); // LED 초기화(조종기)\n        }\n    },\n};\n\n\n/***************************************************************************************\n *  언어 적용\n ***************************************************************************************/\nEntry.robolink_codrone_mini.setLanguage = function () {\n    return {\n        ko: {\n            // ko.js에 작성하던 내용\n            Blocks: {\n                // 정보창\n                value_state_mode_system               : '시스템 모드',\n                value_state_mode_flight               : '비행 상태',\n                value_state_mode_control_flight       : '제어 방식',\n                value_state_mode_movement             : '동작 상태',\n                value_state_headless                  : '방향 기준',\n                value_state_control_speed             : '속도',\n                value_state_sensor_orientation        : '센서 방향',\n                value_state_battery                   : '배터리 잔량(%)',\n                value_altitude_temperature            : '드론의 온도',\n                value_altitude_pressure               : '기압',\n                value_altitude_altitude               : '해발 고도',\n                value_motion_accel_x                  : 'X방향 가속도',\n                value_motion_accel_y                  : 'Y방향 가속도',\n                value_motion_accel_z                  : 'Z방향 가속도',\n                value_motion_gyro_roll                : '롤 각속도',\n                value_motion_gyro_pitch               : '피치 각속도',\n                value_motion_gyro_yaw                 : '요우 각속도',\n                value_motion_angle_roll               : '롤',\n                value_motion_angle_pitch              : '피치',\n                value_motion_angle_yaw                : '요우',\n                value_trim_roll                       : '미세조정 롤값',\n                value_trim_pitch                      : '미세조정 피치값',\n                value_joystick_left_x                 : '왼쪽 조이스틱 X',\n                value_joystick_left_y                 : '왼쪽 조이스틱 Y',\n                value_joystick_left_direction         : '왼쪽 조이스틱 방향',\n                value_joystick_left_event             : '왼쪽 조이스틱 이벤트',\n                value_joystick_right_x                : '오른쪽 조이스틱 X',\n                value_joystick_right_y                : '오른쪽 조이스틱 Y',\n                value_joystick_right_direction        : '오른쪽 조이스틱 방향',\n                value_joystick_right_event            : '오른쪽 조이스틱 이벤트',\n                value_button_button                   : '버튼 입력',\n                value_button_event                    : '버튼 상태',\n                value_entry_hw_count_transfer_reserved: '전송 예정 데이터',\n\n                // 일반 블럭\n                common_light_color_red                  : '빨강',\n                common_light_color_yellow               : '노랑',\n                common_light_color_green                : '초록',\n                common_light_color_cyan                 : '하늘색',\n                common_light_color_blue                 : '파랑',\n                common_light_color_magenta              : '자홍',\n                common_light_color_white                : '흰색',\n                common_light_color_black                : '검정',\n                common_light_color_cotton_candy         : '구름솜사탕',\n                common_light_color_emerald              : '에메랄드',\n                common_light_color_lavender             : '라벤더',\n                common_light_color_muscat               : '청포도',\n                common_light_color_strawberry_milk      : '딸기우유',\n                common_light_color_sunset               : '저녁노을',\n                common_light_mode_hold                  : '유지하기',\n                common_light_mode_flicker               : '깜빡이기',\n                common_light_mode_flicker_double        : '두번 깜빡이기',\n                common_light_mode_dimming               : '천천히 점멸',\n                common_light_mode_sunrise               : '천천히 밝아짐',\n                common_light_mode_sunset                : '천천히 어두워짐',\n                common_light_mode_rainbow               : '무지개',\n                common_light_mode_rainbow2              : '무지개2',\n                common_left                             : '왼쪽',\n                common_right                            : '오른쪽',\n                common_drone                            : '드론',\n                common_controller                       : '조종기',\n                controller_button_front_left            : '전면 왼쪽 버튼',\n                controller_button_front_right           : '전면 오른쪽 버튼',\n                controller_button_top_left              : '상단 왼쪽 버튼',\n                controller_button_top_right             : '상단 오른쪽 버튼',\n                controller_button_center_up             : '중앙 위 버튼',\n                controller_button_center_left           : '중앙 왼쪽 버튼',\n                controller_button_center_right          : '중앙 오른쪽 버튼',\n                controller_button_center_down           : '중앙 아래쪽 버튼',\n                controller_buzzer                       : '버저',\n                controller_buzzer_a                     : '라',\n                controller_buzzer_as                    : '라#',\n                controller_buzzer_b                     : '시',\n                controller_buzzer_c                     : '도',\n                controller_buzzer_cs                    : '도#',\n                controller_buzzer_d                     : '레',\n                controller_buzzer_ds                    : '레#',\n                controller_buzzer_e                     : '미',\n                controller_buzzer_f                     : '파',\n                controller_buzzer_fs                    : '파#',\n                controller_buzzer_g                     : '솔',\n                controller_buzzer_gs                    : '솔#',\n                controller_buzzer_mute                  : '쉼',\n                controller_buzzer_play                  : '연주',\n                controller_buzzer_reserve               : '예약',\n                controller_joystick_direction_left_up   : '왼쪽 위',\n                controller_joystick_direction_up        : '위',\n                controller_joystick_direction_right_up  : '오른쪽 위',\n                controller_joystick_direction_left      : '왼쪽',\n                controller_joystick_direction_center    : '중앙',\n                controller_joystick_direction_right     : '오른쪽',\n                controller_joystick_direction_left_down : '왼쪽 아래',\n                controller_joystick_direction_down      : '아래',\n                controller_joystick_direction_right_down: '오른쪽 아래',\n                controller_joystick_direction           : '방향',\n                controller_joystick_event               : '이벤트',\n                controller_joystick_x                   : '가로축',\n                controller_joystick_y                   : '세로축',\n                drone_level_1                           : '레벨 1',\n                drone_level_2                           : '레벨 2',\n                drone_level_3                           : '레벨 3',\n                drone_flip_forward                      : '앞',\n                drone_flip_rear                         : '뒤',\n                drone_flip_left                         : '왼쪽',\n                drone_flip_right                        : '오른쪽',\n                drone_trim_roll_increase                : '롤 증가',\n                drone_trim_roll_decrease                : '롤 감소',\n                drone_trim_pitch_increase               : '피치 증가',\n                drone_trim_pitch_decrease               : '피치 감소',\n                drone_trim_yaw_increase                 : '요 증가',\n                drone_trim_yaw_decrease                 : '요 감소',\n                drone_trim_throttle_increase            : '쓰로틀 증가',\n                drone_trim_throttle_decrease            : '쓰로틀 감소',\n                drone_trim_reset                        : '초기화',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : '뒤',\n                drone_control_quad_pitch_forward        : '앞',\n                drone_control_quad_roll_left            : '왼쪽',\n                drone_control_quad_roll_right           : '오른쪽',\n                drone_control_quad_throttle_down        : '아래',\n                drone_control_quad_throttle_up          : '위',\n                drone_control_quad_yaw_ccw              : '반시계 방향',\n                drone_control_quad_yaw_cw               : '시계 방향',\n                drone_headless_off                      : '끄기',\n                drone_headless_on                       : '켜기',\n                drone_light_color_body                  : '몸체',\n                drone_light_manual_body_blue            : '파랑',\n                drone_light_manual_body_green           : '초록',\n                drone_light_manual_body_red             : '빨강',\n                drone_motor_rotation_clockwise          : '시계 방향',\n                drone_motor_rotation_counterclockwise   : '반시계 방향',\n            },\n\n            template: {\n                robolink_codrone_mini_drone_information                   : '드론 정보 %1',\n                robolink_codrone_mini_drone_sensor                        : '센서값 %1',\n                robolink_codrone_mini_controller_value_button             : '%1',\n                robolink_codrone_mini_controller_value_button_event       : '%1',\n                robolink_codrone_mini_controller_value_joystick_left      : '왼쪽 조이스틱 %1',\n                robolink_codrone_mini_controller_value_joystick_right     : '오른쪽 조이스틱 %1',\n                robolink_codrone_mini_controller_if_button_press          : '조종기 %1 눌렀을 때',\n                robolink_codrone_mini_controller_if_joystick_direction    : '조종기 %1 조이스틱 %2 (으)로 움직였을 때',\n                robolink_codrone_mini_drone_control_drone_takeoff         : '이륙하기 %1',\n                robolink_codrone_mini_drone_control_drone_landing         : '착륙하기 %1',\n                robolink_codrone_mini_drone_control_drone_stop            : '멈춤 %1',\n                robolink_codrone_mini_drone_trim_direction                : '미세조정 %1 %2',\n                robolink_codrone_mini_drone_trim                          : '미세조정 롤 %1, 피치 %2 %3',\n                robolink_codrone_mini_drone_speed                         : '속도 %1 %2',\n                robolink_codrone_mini_drone_flip                          : '재주넘기 %1 %2',\n                robolink_codrone_mini_drone_sensor_reset                  : '센서 초기화 %1',\n                robolink_codrone_mini_drone_control_headless              : '방향 고정 %1 %2',\n                robolink_codrone_mini_drone_control_drone_reset_heading   : '방향 초기화 %1',\n                robolink_codrone_mini_drone_control_quad_one              : '드론 %1 %2% 정하기 %3',\n                robolink_codrone_mini_drone_control_quad_one_delay        : '드론 %1 %2% %3 초 실행 %4',\n                robolink_codrone_mini_drone_control_quad                  : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% 정하기 %5',\n                robolink_codrone_mini_drone_control_quad_delay            : '드론 Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5초 실행 %6',\n                robolink_codrone_mini_drone_motor_stop                    : '드론 모터 정지 %1',\n                robolink_codrone_mini_drone_motor_single                  : '드론 %1번 모터를 %2(으)로 회전 %3',\n                robolink_codrone_mini_drone_light_manual_single_input     : '드론 LED %1 밝기 %2 %3',\n                robolink_codrone_mini_drone_light_manual_single_off       : '드론 LED 끄기 %1',\n                robolink_codrone_mini_drone_light_color_select            : '드론 LED %1 %2 %3 %4',\n                robolink_codrone_mini_drone_light_color_input             : '드론 LED R %1, G %2, B %3 %4 %5 %6',\n                robolink_codrone_mini_controller_buzzer_off               : '버저 끄기 %1',\n                robolink_codrone_mini_controller_buzzer_hz                : '%1Hz 소리를 %2초 %3 %4',\n                robolink_codrone_mini_controller_buzzer_scale             : '%1 옥타브 %2을(를) %3초 %4 %5',\n            },\n\n            Helper: {\n                robolink_codrone_mini_drone_information                   : \"드론의 정보를 반환합니다.\",\n                robolink_codrone_mini_drone_sensor                        : \"드론 센서와 관련된 값들을 반환합니다.<br><br><font color='crimson'>롤</font> : 좌우 기울기(-90 ~ 90)<br><font color='crimson'>피치</font> : 앞뒤 기울기(-90 ~ 90)<br><font color='crimson'>요우</font> : 방향(-180 ~ 180)\",\n                robolink_codrone_mini_controller_value_button             : \"조종기 전체 버튼 입력 상태를 비트 플래그로 반환합니다.\",\n                robolink_codrone_mini_controller_value_button_event       : \"조종기 버튼 중 현재 사용 중인 버튼의 입력 상태를 반환합니다.\",\n                robolink_codrone_mini_controller_value_joystick_left      : \"조종기의 왼쪽 조이스틱과 관련된 값을 반환합니다.\",\n                robolink_codrone_mini_controller_value_joystick_right     : \"조종기의 오른쪽 조이스틱과 관련된 값을 반환합니다.\",\n                robolink_codrone_mini_controller_if_button_press          : \"지정한 조종기의 버튼이 눌러졌을 때 true를 반환합니다.\",\n                robolink_codrone_mini_controller_if_joystick_direction    : \"조종기의 조이스틱이 지정한 방향으로 움직였을 때 true를 반환합니다.\",\n                robolink_codrone_mini_drone_control_drone_takeoff         : \"드론을 이륙시킵니다.\",\n                robolink_codrone_mini_drone_control_drone_landing         : \"드론을 착륙시킵니다.\",\n                robolink_codrone_mini_drone_control_drone_stop            : \"드론 작동을 정지합니다.\",\n                robolink_codrone_mini_drone_trim_direction                : \"드론 미세 조정 설정을 현재 값에서 5단위로 증가시키거나 감소시킵니다.\",\n                robolink_codrone_mini_drone_trim                          : \"드론 미세 조정 설정을 변경합니다.\",\n                robolink_codrone_mini_drone_speed                         : \"드론 이동 속도를 변경합니다.\",\n                robolink_codrone_mini_drone_flip                          : \"드론을 지정한 방향으로 공중 회전합니다.\",\n                robolink_codrone_mini_drone_sensor_reset                  : \"드론의 자이로 바이어스와 트림 설정을 초기화합니다.\",\n                robolink_codrone_mini_drone_control_headless              : \"드론 좌표 기준을 변경합니다.<br><br><font color='dodgerblue'>방향 고정 켜기</font>를 하면 '이륙 시'와 '방향초기화'를 했을 때 드론이 바라보는 방향이 0도로 고정됩니다. 이 때에는 Yaw를 조작하여 드론이 다른 방향을 보게 하여도 처음 지정한 방향을 기준으로 움직입니다.<br><font color='crimson'>방향 고정 끄기</font>를 선택하면 드론이 바라보는 방향이 0도가 됩니다.\",\n                robolink_codrone_mini_drone_control_drone_reset_heading   : \"드론의 방향을 초기화합니다.<br><br><font color='dodgerblue'>방향 고정 켜기</font> 설정이 되어 있는 경우 이 블럭을 실행하면 드론이 바라보는 방향을 0으로 초기화합니다.\",\n                robolink_codrone_mini_drone_control_quad_one              : \"드론 조종 값을 지정합니다.<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.\",\n                robolink_codrone_mini_drone_control_quad_one_delay        : \"드론 조종 값을 지정합니다.<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.\",\n                robolink_codrone_mini_drone_control_quad                  : \"드론 조종 값을 지정합니다.<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 명령 전달 후 바로 다음 블럭으로 넘어갑니다.\",\n                robolink_codrone_mini_drone_control_quad_delay            : \"드론 조종 값을 지정합니다.<br><br>입력 가능한 값의 범위는 -100 ~ 100입니다. 정지 상태에서 Throttle 값을 50이상으로 지정하면 드론이 이륙합니다. 지정한 시간이 지나면 해당 조종 값을 0으로 변경합니다. 지정한 시간이 끝날 때까지 다음 블럭으로 넘어가지 않습니다.\",\n                robolink_codrone_mini_drone_motor_stop                    : \"모든 모터의 작동을 정지합니다.\",\n                robolink_codrone_mini_drone_motor_single                  : \"모터 제어 블럭입니다.<br><br>모터의 순서는 12시 방향부터 차례대로 1(앞 오른쪽), 2(뒤 오른쪽), 3(뒤 왼쪽), 4(앞 왼쪽) 입니다.<br>모터 회전에 사용 가능한 값의 범위는 0 ~ 4095입니다.\",\n                robolink_codrone_mini_drone_light_manual_single_off       : \"드론의 모든 LED를 끕니다.\",\n                robolink_codrone_mini_drone_light_manual_single_input     : \"드론 LED를 조작하는데 사용합니다.<br><br>10진수(0 ~ 65535) 또는 16진수(0x00 ~ 0xFFFF) 값을 사용할 수 있습니다.<br>각각의 비트는 LED를 선택하는 스위치 역할을 합니다.<br>밝기 값은 0 ~ 255 사이의 값을 사용할 수 있습니다.<br>값이 커질수록 더 밝아집니다.\",\n                robolink_codrone_mini_drone_light_color_select            : \"미리 설정된 색상을 선택하여 드론의 LED를 제어하는 블럭입니다.\",\n                robolink_codrone_mini_drone_light_color_input             : \"Red, Green, Blue 값을 지정하여 드론의 LED를 제어하는 블럭입니다.\",\n                robolink_codrone_mini_controller_buzzer_off               : \"버저 작동을 중단합니다. 예약된 소리가 있다면 모두 삭제합니다.\",\n                robolink_codrone_mini_controller_buzzer_scale             : \"지정한 옥타브의 음을 지정한 시간동안 연주하거나 예약합니다.<br><br><font color='dodgerblue'>연주</font>를 선택할 경우 소리를 즉시 연주하고, 연주를 명령한 시간동안 기다립니다. <font color='crimson'>예약</font>을 선택한 경우에는 소리를 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다.\",\n                robolink_codrone_mini_controller_buzzer_hz                : \"지정한 주파수의 소리를 지정한 시간동안 연주하거나 예약합니다.<br><br>권장 사용 범위는 250 ~ 8000 입니다.<br><br>4옥타브를 기준으로 도(261), 도#(277), 레(293), 레#(311), 미(329), 파(349), 파#(370), 솔(392), 솔#(415), 라(440), 라#(466), 시(493)입니다. 여기에서 한 옥타브 올라갈 때마다 주파수 값이 두 배가 됩니다. 한 옥타브 내려갈 때에는 주파수 값이 절반이 됩니다. 예를 들면 3옥타브의 도는 130.8128Hz, 4옥타브의 도는 261.6256Hz, 5옥타브의 도는 523.2511Hz 입니다.<br><br><font color='dodgerblue'>연주</font>를 선택할 경우 소리를 즉시 연주하고, 연주를 명령한 시간동안 기다립니다. <font color='crimson'>예약</font>을 선택한 경우에는 소리를 예약하고, 바로 다음 블럭으로 넘어갑니다. 예약은 최대 12개까지 누적할 수 있습니다.\",\n            },\n        },\n\n        en: {\n            Blocks: {\n                // 정보창\n                value_state_mode_flight               : 'Flight Mode',\n                value_state_mode_control_flight       : 'Control Mode',\n                value_state_mode_movement             : 'Movement',\n                value_state_headless                  : 'Headless',\n                value_state_control_speed             : 'Control Speed',\n                value_state_sensor_orientation        : 'Sensor Orientation',\n                value_state_battery                   : 'Battery',\n                value_altitude_temperature            : 'Temperature',\n                value_altitude_pressure               : 'Pressure',\n                value_altitude_altitude               : 'Altitude',\n                value_motion_accel_x                  : 'Accel X',\n                value_motion_accel_y                  : 'Accel Y',\n                value_motion_accel_z                  : 'Accel Z',\n                value_motion_gyro_roll                : 'Gyro Roll',\n                value_motion_gyro_pitch               : 'Gyro Pitch',\n                value_motion_gyro_yaw                 : 'Gyro Yaw',\n                value_motion_angle_roll               : 'Roll',\n                value_motion_angle_pitch              : 'Pitch',\n                value_motion_angle_yaw                : 'Yaw',\n                value_trim_roll                       : 'Trim Roll',\n                value_trim_pitch                      : 'Trim Pitch',\n                value_joystick_left_x                 : 'Left Joystick X',\n                value_joystick_left_y                 : 'Left Joystick Y',\n                value_joystick_left_direction         : 'Left Joystick Direction',\n                value_joystick_left_event             : 'Left Joystick Event',\n                value_joystick_right_x                : 'Right Joystick X',\n                value_joystick_right_y                : 'Right Joystick Y',\n                value_joystick_right_direction        : 'Right Joystick Direction',\n                value_joystick_right_event            : 'Right Joystick Event',\n                value_button_button                   : 'Button',\n                value_button_event                    : 'Button Event',\n                value_entry_hw_count_transfer_reserved: 'Count of data to transfer',\n\n                // 일반 블럭\n                common_light_color_red                  : 'red',\n                common_light_color_yellow               : 'yellow',\n                common_light_color_green                : 'green',\n                common_light_color_cyan                 : 'cyan',\n                common_light_color_blue                 : 'blue',\n                common_light_color_magenta              : 'magenta',\n                common_light_color_white                : 'white',\n                common_light_color_black                : 'black',\n                common_light_color_cotton_candy         : 'cotton candy',\n                common_light_color_emerald              : 'emerald',\n                common_light_color_lavender             : 'lavender',\n                common_light_color_muscat               : 'muscat',\n                common_light_color_strawberry_milk      : 'strawberry milk',\n                common_light_color_sunset               : 'sunset',\n                common_light_mode_hold                  : 'hold',\n                common_light_mode_flicker               : 'flicker',\n                common_light_mode_flicker_double        : 'flicker double',\n                common_light_mode_dimming               : 'dimming',\n                common_light_mode_sunrise               : 'sunrise',\n                common_light_mode_sunset                : 'sunset',\n                common_light_mode_rainbow               : 'rainbow',\n                common_light_mode_rainbow2              : 'rainbow2',\n                common_left                             : 'left',\n                common_right                            : 'right',\n                common_drone                            : 'drone',\n                common_controller                       : 'controller',\n                controller_button_front_left            : 'Front left button',\n                controller_button_front_right           : 'Front right button',\n                controller_button_top_left              : 'Top left button',\n                controller_button_top_right             : 'Top right button',\n                controller_button_center_up             : 'Trim up button',\n                controller_button_center_left           : 'Trim left button',\n                controller_button_center_right          : 'Trim right button',\n                controller_button_center_down           : 'Trim down button',\n                controller_buzzer                       : 'buzzer',\n                controller_buzzer_a                     : 'A',\n                controller_buzzer_as                    : 'A#',\n                controller_buzzer_b                     : 'B',\n                controller_buzzer_c                     : 'C',\n                controller_buzzer_cs                    : 'C#',\n                controller_buzzer_d                     : 'D',\n                controller_buzzer_ds                    : 'D#',\n                controller_buzzer_e                     : 'E',\n                controller_buzzer_f                     : 'F',\n                controller_buzzer_fs                    : 'F#',\n                controller_buzzer_g                     : 'G',\n                controller_buzzer_gs                    : 'G#',\n                controller_buzzer_mute                  : 'mute',\n                controller_buzzer_play                  : 'play',\n                controller_buzzer_reserve               : 'reserve',\n                controller_joystick_direction_left_up   : 'Left top',\n                controller_joystick_direction_up        : 'Top',\n                controller_joystick_direction_right_up  : 'Right top',\n                controller_joystick_direction_left      : 'Left',\n                controller_joystick_direction_center    : 'Center',\n                controller_joystick_direction_right     : 'Right',\n                controller_joystick_direction_left_down : 'Left Bottom',\n                controller_joystick_direction_down      : 'Bottom',\n                controller_joystick_direction_right_down: 'Right Bottom',\n                controller_joystick_direction           : 'direction',\n                controller_joystick_event               : 'event',\n                controller_joystick_x                   : 'X',\n                controller_joystick_y                   : 'Y',\n                drone_level_1                           : 'Level 1',\n                drone_level_2                           : 'Level 2',\n                drone_level_3                           : 'Level 2',\n                drone_flip_forward                      : 'Forward',\n                drone_flip_rear                         : 'Rear',\n                drone_flip_left                         : 'Left',\n                drone_flip_right                        : 'Right',\n                drone_trim_roll_increase                : 'Roll increase',\n                drone_trim_roll_decrease                : 'Roll decrease',\n                drone_trim_pitch_increase               : 'Pitch increase',\n                drone_trim_pitch_decrease               : 'Pitch decrease',\n                drone_trim_yaw_increase                 : 'Yaw increase',\n                drone_trim_yaw_decrease                 : 'Yaw decrease',\n                drone_trim_throttle_increase            : 'Throttle increase',\n                drone_trim_throttle_decrease            : 'Throttle decrease',\n                drone_trim_reset                        : 'Reset Trim',\n                drone_control_quad_roll                 : 'Roll',\n                drone_control_quad_pitch                : 'Pitch',\n                drone_control_quad_yaw                  : 'Yaw',\n                drone_control_quad_throttle             : 'Throttle',\n                drone_control_quad_pitch_backward       : 'Backward',\n                drone_control_quad_pitch_forward        : 'Forward',\n                drone_control_quad_roll_left            : 'Left',\n                drone_control_quad_roll_right           : 'Right',\n                drone_control_quad_throttle_down        : 'Down',\n                drone_control_quad_throttle_up          : 'Up',\n                drone_control_quad_yaw_ccw              : 'Counterclockwise',\n                drone_control_quad_yaw_cw               : 'Clockwise',\n                drone_headless_off                      : 'Off',\n                drone_headless_on                       : 'On',\n                drone_light_color_body                  : 'Body',\n                drone_light_manual_body_blue            : 'Blue',\n                drone_light_manual_body_green           : 'Green',\n                drone_light_manual_body_red             : 'Red',\n                drone_motor_rotation_clockwise          : 'Clockwise',\n                drone_motor_rotation_counterclockwise   : 'Counterclockwise',\n            },\n\n            template: {\n                robolink_codrone_mini_drone_information                : 'Drone information %1',\n                robolink_codrone_mini_drone_sensor                     : 'Sensor %1',\n                robolink_codrone_mini_controller_value_button          : '%1',\n                robolink_codrone_mini_controller_value_button_event    : '%1',\n                robolink_codrone_mini_controller_value_joystick_left   : 'Left joystick %1',\n                robolink_codrone_mini_controller_value_joystick_right  : 'Right joystick %1',\n                robolink_codrone_mini_controller_if_button_press       : 'when press %1',\n                robolink_codrone_mini_controller_if_joystick_direction : 'when %1 stick move to %2',\n                robolink_codrone_mini_drone_control_drone_takeoff      : 'Takeoff %1',\n                robolink_codrone_mini_drone_control_drone_landing      : 'Landing %1',\n                robolink_codrone_mini_drone_control_drone_stop         : 'Stop %1',\n                robolink_codrone_mini_drone_trim_direction             : 'Trim %1 %2',\n                robolink_codrone_mini_drone_trim                       : 'Trim Roll %1%, Pitch %2% %3',\n                robolink_codrone_mini_drone_speed                      : 'Speed %1 %2',\n                robolink_codrone_mini_drone_flip                       : 'Flip %1 %2',\n                robolink_codrone_mini_drone_sensor_reset               : 'Sensor reset %1',\n                robolink_codrone_mini_drone_control_headless           : 'Headless %1 %2',\n                robolink_codrone_mini_drone_control_drone_reset_heading: 'Reset heading %1',\n                robolink_codrone_mini_drone_control_quad_one           : 'Set %1 %2% %3',\n                robolink_codrone_mini_drone_control_quad_one_delay     : 'Set %1 %2% %3 sec %4',\n                robolink_codrone_mini_drone_control_quad               : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% %5',\n                robolink_codrone_mini_drone_control_quad_delay         : 'Set Roll %1%, Pitch %2%, Yaw %3%, Throttle %4% for %5sec %6',\n                robolink_codrone_mini_drone_motor_stop                 : 'Motor stop %1',\n                robolink_codrone_mini_drone_motor_single               : 'No. %1 Motor rotate for %2 %3',\n                robolink_codrone_mini_drone_light_manual_single_off    : 'Drone LED Off %1',\n                robolink_codrone_mini_drone_light_manual_single_input  : 'Drone LED %1 lightness %2 %3',\n                robolink_codrone_mini_drone_light_color_select         : 'Drone LED %1 %2 %3 %4',\n                robolink_codrone_mini_drone_light_color_input          : 'Drone LED R %1, G %2, B %3 %4 %5 %6',\n                robolink_codrone_mini_controller_buzzer_off            : 'turn off the buzzer %1',\n                robolink_codrone_mini_controller_buzzer_scale          : '%4 %1 octave %2 for %3 second %5',\n                robolink_codrone_mini_controller_buzzer_hz             : '%3 %1 Hz for %2 second %4',\n            },\n\n            Helper: {\n                robolink_codrone_mini_drone_information                : '',\n                robolink_codrone_mini_drone_sensor                     : '',\n                robolink_codrone_mini_controller_value_button          : '',\n                robolink_codrone_mini_controller_value_button_event    : '',\n                robolink_codrone_mini_controller_value_joystick_left   : '',\n                robolink_codrone_mini_controller_value_joystick_right  : '',\n                robolink_codrone_mini_controller_if_button_press       : '',\n                robolink_codrone_mini_controller_if_joystick_direction : '',\n                robolink_codrone_mini_drone_control_drone_takeoff      : '',\n                robolink_codrone_mini_drone_control_drone_landing      : '',\n                robolink_codrone_mini_drone_control_drone_stop         : '',\n                robolink_codrone_mini_drone_trim_direction             : '',\n                robolink_codrone_mini_drone_trim                       : '',\n                robolink_codrone_mini_drone_speed                      : '',\n                robolink_codrone_mini_drone_flip                       : '',\n                robolink_codrone_mini_drone_sensor_reset               : '',\n                robolink_codrone_mini_drone_control_headless           : '',\n                robolink_codrone_mini_drone_control_drone_reset_heading: '',\n                robolink_codrone_mini_drone_control_quad_one           : '',\n                robolink_codrone_mini_drone_control_quad_one_delay     : '',\n                robolink_codrone_mini_drone_control_quad               : '',\n                robolink_codrone_mini_drone_control_quad_delay         : '',\n                robolink_codrone_mini_drone_motor_stop                 : '',\n                robolink_codrone_mini_drone_motor_single               : '',\n                robolink_codrone_mini_drone_light_manual_single_off    : '',\n                robolink_codrone_mini_drone_light_manual_single_input  : '',\n                robolink_codrone_mini_drone_light_color_select         : '',\n                robolink_codrone_mini_drone_light_color_input          : '',\n                robolink_codrone_mini_controller_buzzer_off            : '',\n                robolink_codrone_mini_controller_buzzer_scale          : '',\n                robolink_codrone_mini_controller_buzzer_hz             : '',\n            },\n        },\n    };\n};\n\n\n// Entry 좌측 하단 하드웨어 모니터 화면에 표시하는 속성\n// listPorts와 ports 두 곳 동시에 동일한 속성을 표시할 수는 없음\nEntry.robolink_codrone_mini.monitorTemplate = function () {\n    return {\n        /* 센서창 가림 현상을 해결하기 위해서 주석 처리함(2017.11.06)\n        imgPath: \"hw/robolink_codrone_mini.png\",   // 배경 이미지\n        width  : 256,                             // 이미지의 폭\n        height : 256,                             // 이미지의 높이\n        */\n\n        // 모니터 화면 상단에 차례대로 나열하는 값\n        listPorts: {\n            state_modeFlight             : { name: Lang.Blocks.value_state_mode_flight, type: 'input', pos: { x: 0, y: 0 } },\n            state_modeControlFlight      : { name: Lang.Blocks.value_state_mode_control_flight, type: 'input', pos: { x: 0, y: 0 } },\n            state_modeMovement           : { name: Lang.Blocks.value_state_mode_movement, type: 'input', pos: { x: 0, y: 0 } },\n            state_headless               : { name: Lang.Blocks.value_state_headless, type: 'input', pos: { x: 0, y: 0 } },\n            state_controlSpeed           : { name: Lang.Blocks.value_state_control_speed, type: 'input', pos: { x: 0, y: 0 } },\n            state_sensorOrientation      : { name: Lang.Blocks.value_state_sensor_orientation, type: 'input', pos: { x: 0, y: 0 } },\n            state_battery                : { name: Lang.Blocks.value_state_battery, type: 'input', pos: { x: 0, y: 0 } },\n            altitude_temperature         : { name: Lang.Blocks.value_altitude_temperature, type: 'input', pos: { x: 0, y: 0 } },\n            altitude_pressure            : { name: Lang.Blocks.value_altitude_pressure, type: 'input', pos: { x: 0, y: 0 } },\n            altitude_altitude            : { name: Lang.Blocks.value_altitude_altitude, type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelX                : { name: Lang.Blocks.value_motion_accel_x, type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelY                : { name: Lang.Blocks.value_motion_accel_y, type: 'input', pos: { x: 0, y: 0 } },\n            motion_accelZ                : { name: Lang.Blocks.value_motion_accel_z, type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroRoll              : { name: Lang.Blocks.value_motion_gyro_roll, type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroPitch             : { name: Lang.Blocks.value_motion_gyro_pitch, type: 'input', pos: { x: 0, y: 0 } },\n            motion_gyroYaw               : { name: Lang.Blocks.value_motion_gyro_yaw, type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleRoll             : { name: Lang.Blocks.value_motion_angle_roll, type: 'input', pos: { x: 0, y: 0 } },\n            motion_anglePitch            : { name: Lang.Blocks.value_motion_angle_pitch, type: 'input', pos: { x: 0, y: 0 } },\n            motion_angleYaw              : { name: Lang.Blocks.value_motion_angle_yaw, type: 'input', pos: { x: 0, y: 0 } },\n            trim_roll                    : { name: Lang.Blocks.value_trim_roll, type: 'input', pos: { x: 0, y: 0 } },\n            trim_pitch                   : { name: Lang.Blocks.value_trim_pitch, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_x              : { name: Lang.Blocks.value_joystick_left_x, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_y              : { name: Lang.Blocks.value_joystick_left_y, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_direction      : { name: Lang.Blocks.value_joystick_left_direction, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_left_event          : { name: Lang.Blocks.value_joystick_left_event, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_x             : { name: Lang.Blocks.value_joystick_right_x, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_y             : { name: Lang.Blocks.value_joystick_right_y, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_direction     : { name: Lang.Blocks.value_joystick_right_direction, type: 'input', pos: { x: 0, y: 0 } },\n            joystick_right_event         : { name: Lang.Blocks.value_joystick_right_event, type: 'input', pos: { x: 0, y: 0 } },\n            button_button                : { name: Lang.Blocks.value_button_button, type: 'input', pos: { x: 0, y: 0 } },\n            button_event                 : { name: Lang.Blocks.value_button_event, type: 'input', pos: { x: 0, y: 0 } },\n            entryhw_countTransferReserved: { name: Lang.Blocks.value_entry_hw_count_transfer_reserved, type: 'output', pos: { x: 0, y: 0 } },\n        },\n\n        // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n        ports: {},\n\n        mode: 'both',   // 표시 모드\n    };\n};\n\n\n/***************************************************************************************\n *  엔트리에 등록할 블록들의 블록명(다른 장치의 블록 이름과 달라야 함)\n ***************************************************************************************/\nEntry.robolink_codrone_mini.blockMenuBlocks = [\n    'robolink_codrone_mini_drone_information',\n    'robolink_codrone_mini_drone_sensor',\n    'robolink_codrone_mini_controller_value_button',\n    'robolink_codrone_mini_controller_value_button_event',\n    'robolink_codrone_mini_controller_value_joystick_left',\n    'robolink_codrone_mini_controller_value_joystick_right',\n    'robolink_codrone_mini_controller_if_button_press',\n    'robolink_codrone_mini_controller_if_joystick_direction',\n    'robolink_codrone_mini_drone_control_drone_takeoff',\n    'robolink_codrone_mini_drone_control_drone_landing',\n    'robolink_codrone_mini_drone_control_drone_stop',\n    'robolink_codrone_mini_drone_trim_direction',\n    'robolink_codrone_mini_drone_trim',\n    'robolink_codrone_mini_drone_speed',\n    'robolink_codrone_mini_drone_flip',\n    'robolink_codrone_mini_drone_sensor_reset',\n    'robolink_codrone_mini_drone_control_headless',\n    'robolink_codrone_mini_drone_control_drone_reset_heading',\n    'robolink_codrone_mini_drone_control_quad_one',\n    'robolink_codrone_mini_drone_control_quad_one_delay',\n    'robolink_codrone_mini_drone_control_quad',\n    'robolink_codrone_mini_drone_control_quad_delay',\n    'robolink_codrone_mini_drone_motor_stop',\n    'robolink_codrone_mini_drone_motor_single',\n    'robolink_codrone_mini_drone_light_manual_single_off',\n    'robolink_codrone_mini_drone_light_manual_single_input',\n    'robolink_codrone_mini_drone_light_color_select',\n    'robolink_codrone_mini_drone_light_color_input',\n    'robolink_codrone_mini_controller_buzzer_off',\n    'robolink_codrone_mini_controller_buzzer_scale',\n    'robolink_codrone_mini_controller_buzzer_hz',\n];\n\n\n/***************************************************************************************\n *  엔트리 블록 정의\n ***************************************************************************************/\nEntry.robolink_codrone_mini.getBlocks = function () {\n    return {\n        robolink_codrone_mini_drone_information: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.value_state_mode_flight, 'state_modeFlight'],\n                        [Lang.Blocks.value_state_mode_control_flight, 'state_modeControlFlight'],\n                        [Lang.Blocks.value_state_mode_movement, 'state_modeMovement'],\n                        [Lang.Blocks.value_state_headless, 'state_headless'],\n                        [Lang.Blocks.value_state_control_speed, 'state_controlSpeed'],\n                        [Lang.Blocks.value_trim_pitch, 'trim_pitch'],\n                        [Lang.Blocks.value_trim_roll, 'trim_roll'],\n                        [Lang.Blocks.value_state_sensor_orientation, 'state_sensorOrientation'],\n                        [Lang.Blocks.value_state_battery, 'state_battery'],\n                    ],\n                    value     : 'state_modeFlight',                     // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_information',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        robolink_codrone_mini_drone_sensor: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.value_motion_accel_x, 'motion_accelX'],\n                        [Lang.Blocks.value_motion_accel_y, 'motion_accelY'],\n                        [Lang.Blocks.value_motion_accel_z, 'motion_accelZ'],\n                        [Lang.Blocks.value_motion_gyro_roll, 'motion_gyroRoll'],\n                        [Lang.Blocks.value_motion_gyro_pitch, 'motion_gyroPitch'],\n                        [Lang.Blocks.value_motion_gyro_yaw, 'motion_gyroYaw'],\n                        [Lang.Blocks.value_motion_angle_roll, 'motion_angleRoll'],\n                        [Lang.Blocks.value_motion_angle_pitch, 'motion_anglePitch'],\n                        [Lang.Blocks.value_motion_angle_yaw, 'motion_angleYaw'],\n                        [Lang.Blocks.value_altitude_temperature, 'altitude_temperature'],\n                        [Lang.Blocks.value_altitude_pressure, 'altitude_pressure'],\n                        [Lang.Blocks.value_altitude_altitude, 'altitude_altitude'],\n                    ],\n                    value     : 'motion_accelX',                               // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_sensor',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n        \n        robolink_codrone_mini_controller_value_button: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.value_button_button,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_mini_controller_value_button',\n            },\n            paramsKeyMap: {\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const button = Entry.hw.portData['button_button'];\n                if( button == undefined )\n                {\n                    return 0;\n                }\n                return button;\n            },\n        },\n\n\n        robolink_codrone_mini_controller_value_button_event: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.value_button_event,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_mini_controller_value_button_event',\n            },\n            paramsKeyMap: {\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const button_event = Entry.hw.portData['button_event'];\n                if( button_event == undefined )\n                {\n                    return 0;\n                }\n                return button_event;\n            },\n        },\n\n\n        robolink_codrone_mini_controller_value_joystick_left: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_x, 'joystick_left_x'],\n                        [Lang.Blocks.controller_joystick_y, 'joystick_left_y'],\n                        [Lang.Blocks.controller_joystick_direction, 'joystick_left_direction'],\n                        [Lang.Blocks.controller_joystick_event, 'joystick_left_event'],\n                    ],\n                    value     : 'joystick_left_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_mini_controller_value_joystick_left',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        robolink_codrone_mini_controller_value_joystick_right: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic_string_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_x, 'joystick_right_x'],\n                        [Lang.Blocks.controller_joystick_y, 'joystick_right_y'],\n                        [Lang.Blocks.controller_joystick_direction, 'joystick_right_direction'],\n                        [Lang.Blocks.controller_joystick_event, 'joystick_right_event'],\n                    ],\n                    value     : 'joystick_right_x',                             // 초기 선택항목 지정\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_mini_controller_value_joystick_right',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class   : 'monitor',                  // 같은 이름인 객체들이 그룹으로 형성됨\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.hw.portData[script.getField('DEVICE')];\n            },\n        },\n\n\n        robolink_codrone_mini_controller_if_button_press: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_button_front_left, '1'],\n                        [Lang.Blocks.controller_button_front_right, '2'],\n                        [Lang.Blocks.controller_button_top_left, '4'],\n                        [Lang.Blocks.controller_button_top_right, '8'],\n                        [Lang.Blocks.controller_button_center_up, '16'],\n                        [Lang.Blocks.controller_button_center_left, '32'],\n                        [Lang.Blocks.controller_button_center_right, '128'],\n                        [Lang.Blocks.controller_button_center_down, '256'],\n                    ],\n                    value     : '1',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_mini_controller_if_button_press',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const read        = Entry.hw.portData;\n                const button      = 'button_button';    // paramsKeyMap에 정의된 이름 사용\n                const button_event = 'button_event';     // paramsKeyMap에 정의된 이름 사용\n                \n                if (read[button] == script.getField('BUTTON') && read[button_event] == 2) {\n                    return true;\n                } else {\n                    return false;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\n        robolink_codrone_mini_controller_if_joystick_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor : '#fff',\n            skeleton  : 'basic_boolean_field',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_left, 'joystick_left_direction'],\n                        [Lang.Blocks.common_right, 'joystick_right_direction'],\n                    ],\n                    value     : 'joystick_left_direction',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_joystick_direction_left_up, '17'],\n                        [Lang.Blocks.controller_joystick_direction_up, '18'],\n                        [Lang.Blocks.controller_joystick_direction_right_up, '20'],\n                        [Lang.Blocks.controller_joystick_direction_left, '33'],\n                        [Lang.Blocks.controller_joystick_direction_center, '34'],\n                        [Lang.Blocks.controller_joystick_direction_right, '36'],\n                        [Lang.Blocks.controller_joystick_direction_left_down, '65'],\n                        [Lang.Blocks.controller_joystick_direction_down, '66'],\n                        [Lang.Blocks.controller_joystick_direction_right_down, '68'],\n                    ],\n                    value     : '34',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_mini_controller_if_joystick_direction',\n            },\n            paramsKeyMap: {\n                DEVICE   : 0,\n                DIRECTION: 1,\n            },\n            class   : 'boolean_input',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const read   = Entry.hw.portData;\n                const device = script.getField('DEVICE');  // paramsKeyMap에 정의된 이름 사용\n\n                if (read[device] == script.getField('DIRECTION')) {\n                    return true;\n                }\n                else {\n                    return false;\n                }\n            },\n        },\n\n\n        robolink_codrone_mini_drone_light_manual_single_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_light_manual_single_off',\n            },\n            paramsKeyMap: {},\n            class       : 'drone_light',\n            isNotFor    : ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.byrobot_base.setLightManual(script, 0x10, 0xff, 0);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_light_manual_single_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['0x3F'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                ],\n                type: 'robolink_codrone_mini_drone_light_manual_single_input',\n            },\n            paramsKeyMap: {\n                FLAGS     : 0,\n                BRIGHTNESS: 1,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const flags      = parseInt(script.getStringValue('FLAGS'));\n                const brightness = script.getNumberValue('BRIGHTNESS');\n                return Entry.byrobot_base.setLightManual(script, 0x10, flags, brightness);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_light_color_input: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold, '2'],              // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker, '3'],           // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double, '4'],    // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming, '5'],           // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise, '6'],           // BodySunrise         = 0x26\n                        [Lang.Blocks.common_light_mode_sunset, '7'],            // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow, '8'],           // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2, '9'],          // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    { type: 'text', params: ['255'] },\n                    null,\n                    { type: 'text', params: ['250'] },\n                    null,\n                ],\n                type: 'robolink_codrone_mini_drone_light_color_input',\n            },\n            paramsKeyMap: {\n                RED     : 0,\n                GREEN   : 1,\n                BLUE    : 2,\n                MODE    : 3,\n                INTERVAL: 4,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const mode     = 0x20 + parseInt(script.getField('MODE'), 10);\n                const red      = script.getNumberValue('RED');\n                const green    = script.getNumberValue('GREEN');\n                const blue     = script.getNumberValue('BLUE');\n                const interval = script.getNumberValue('INTERVAL');\n                return Entry.byrobot_base.setLightModeColor(script, 0x10, mode, interval, red, green, blue);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_light_color_select: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_color_red, 'red'],\n                        [Lang.Blocks.common_light_color_green, 'green'],\n                        [Lang.Blocks.common_light_color_blue, 'blue'],\n                        [Lang.Blocks.common_light_color_yellow, 'yellow'],\n                        [Lang.Blocks.common_light_color_magenta, 'magenta'],\n                        [Lang.Blocks.common_light_color_cyan, 'cyan'],\n                        [Lang.Blocks.common_light_color_white, 'white'],\n                        [Lang.Blocks.common_light_color_sunset, 'sunset'],\n                        [Lang.Blocks.common_light_color_cotton_candy, 'cottonCandy'],\n                        [Lang.Blocks.common_light_color_muscat, 'muscat'],\n                        [Lang.Blocks.common_light_color_strawberry_milk, 'strawberryMilk'],\n                        [Lang.Blocks.common_light_color_emerald, 'emerald'],\n                        [Lang.Blocks.common_light_color_lavender, 'lavender'],\n                    ],\n                    value     : 'red',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.common_light_mode_hold, '2'],              // BodyHold            = 0x22\n                        [Lang.Blocks.common_light_mode_flicker, '3'],           // BodyFlicker         = 0x23\n                        [Lang.Blocks.common_light_mode_flicker_double, '4'],    // BodyFlickerDouble   = 0x24\n                        [Lang.Blocks.common_light_mode_dimming, '5'],           // BodyDimming         = 0x25\n                        [Lang.Blocks.common_light_mode_sunrise, '6'],           // BodySunrise         = 0x26\n                        [Lang.Blocks.common_light_mode_sunset, '7'],            // BodySunset          = 0x27\n                        [Lang.Blocks.common_light_mode_rainbow, '8'],           // BodyRainbow         = 0x28\n                        [Lang.Blocks.common_light_mode_rainbow2, '9'],          // BodyRainbow2        = 0x29\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null, { type: 'text', params: ['250'] }, null],\n                type  : 'robolink_codrone_mini_drone_light_color_select',\n            },\n            paramsKeyMap: {\n                COLOR   : 0,\n                MODE    : 1,\n                INTERVAL: 2,\n            },\n            class   : 'drone_light',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const mode        = 0x20 + parseInt(script.getField('MODE'), 10);\n                const interval    = script.getNumberValue('INTERVAL');\n                const colorString = script.getField('COLOR');\n                return Entry.byrobot_base.setLightModeColorString(script, 0x10, mode, interval, colorString);\n            },\n        },\n\n\n        robolink_codrone_mini_controller_buzzer_off: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_mini_controller_buzzer_off',\n            },\n            paramsKeyMap: {},\n            class       : 'buzzer',\n            isNotFor    : ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.byrobot_base.setBuzzerStop(script, 0x20);\n            },\n        },\n\n\n        robolink_codrone_mini_controller_buzzer_scale: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                    ],\n                    value     : '4',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_mute, '-1'],\n                        [Lang.Blocks.controller_buzzer_c,  '0'],\n                        [Lang.Blocks.controller_buzzer_cs, '1'],\n                        [Lang.Blocks.controller_buzzer_d,  '2'],\n                        [Lang.Blocks.controller_buzzer_ds, '3'],\n                        [Lang.Blocks.controller_buzzer_e,  '4'],\n                        [Lang.Blocks.controller_buzzer_f,  '5'],\n                        [Lang.Blocks.controller_buzzer_fs, '6'],\n                        [Lang.Blocks.controller_buzzer_g,  '7'],\n                        [Lang.Blocks.controller_buzzer_gs, '8'],\n                        [Lang.Blocks.controller_buzzer_a,  '9'],\n                        [Lang.Blocks.controller_buzzer_as, '10'],\n                        [Lang.Blocks.controller_buzzer_b,  '11'],\n                    ],\n                    value     : '0',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_play,    1],\n                        [Lang.Blocks.controller_buzzer_reserve, 0],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    null,\n                    { type: 'text', params: ['1'] },\n                    null,\n                    null\n                ],\n                type: 'robolink_codrone_mini_controller_buzzer_scale',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                SCALE : 1,\n                TIME  : 2,\n                WAIT  : 3,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const octave = parseInt(script.getField('OCTAVE'), 10);\n                const scale  = parseInt(script.getField('SCALE'), 10);\n                const time   = script.getNumberValue('TIME') * 1000;\n                const wait   = script.getNumberValue('WAIT');\n\n                if (scale == -1) {\n                    if (wait == 1)\n                    {\n                        return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, true, true);\n                    }\n                    else\n                    {\n                        return Entry.byrobot_base.setBuzzerMute(script, 0x20, time, false, false);\n                    }\n                } else {\n                    if (wait == 1)\n                    {\n                        return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, true, true);\n                    }\n                    else\n                    {\n                        return Entry.byrobot_base.setBuzzerScale(script, 0x20, octave, scale, time, false, false);\n                    }\n                }\n            },\n        },\n\n\n        robolink_codrone_mini_controller_buzzer_hz: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.controller_buzzer_play,    1],\n                        [Lang.Blocks.controller_buzzer_reserve, 0],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'text', params: ['1000'] },\n                    { type: 'text', params: ['1'] },\n                    null,\n                    null,\n                ],\n                type: 'robolink_codrone_mini_controller_buzzer_hz',\n            },\n            paramsKeyMap: {\n                HZ   : 0,\n                TIME : 1,\n                WAIT : 2,\n            },\n            class   : 'buzzer',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const hz   = script.getNumberValue('HZ');\n                const time = script.getNumberValue('TIME') * 1000;\n                const wait   = script.getNumberValue('WAIT');\n                \n                if (wait == 1)\n                {\n                    return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, true, true);\n                }\n                else\n                {\n                    return Entry.byrobot_base.setBuzzerHz(script, 0x20, hz, time, false, false);\n                }\n            },\n        },\n\n\n        robolink_codrone_mini_drone_motor_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_motor_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'motor',\n            isNotFor    : ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_motor_single: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [{ type: 'text', params: ['1'] }, { type: 'text', params: ['120'] }, null],\n                type  : 'robolink_codrone_mini_drone_motor_single',\n            },\n            paramsKeyMap: {\n                MOTORINDEX: 0,\n                MOTORSPEED: 1,\n            },\n            class   : 'motor',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const motorIndex = script.getNumberValue('MOTORINDEX') - 1;\n                const motorSpeed = script.getNumberValue('MOTORSPEED');\n\n                return Entry.byrobot_base.setMotorSingleV(script, 0x10, motorIndex, motorSpeed);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_drone_takeoff: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_control_drone_takeoff',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x11, 5000); // 0x11 : FlightEvent::TakeOff\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_drone_landing: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_control_drone_landing',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.byrobot_base.setEventFlight(script, 0x10, 0x12, 5000); // 0x12 : FlightEvent::Landing\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_drone_stop: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_control_drone_stop',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.byrobot_base.sendStop(script, 0x10);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_headless: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_headless_on, '1'],\n                        [Lang.Blocks.drone_headless_off, '2'],\n                    ],\n                    value     : '2',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_mini_drone_control_headless',\n            },\n            paramsKeyMap: {\n                HEADLESS: 0,\n            },\n            class   : 'control_flight',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const headless = script.getField('HEADLESS');\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x03, headless);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_drone_reset_heading: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\n            events    : {},\n            def       : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_control_drone_reset_heading',\n            },\n            paramsKeyMap: {},\n            class       : 'control_flight',\n            isNotFor    : ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x07, 0xA0); // 0x22 : CommandType::FlightEvent  // 0xA0 : FlightEvent::ResetHeading\n            },\n        },\n\n\n        robolink_codrone_mini_drone_trim_direction: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_trim_pitch_increase, 'pitch_inc'],\n                        [Lang.Blocks.drone_trim_pitch_decrease, 'pitch_dec'],\n                        [Lang.Blocks.drone_trim_roll_increase, 'roll_inc'],\n                        [Lang.Blocks.drone_trim_roll_decrease, 'roll_dec'],\n                        [Lang.Blocks.drone_trim_reset, 'reset'],\n                    ],\n                    value     : 'pitch_inc',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_mini_drone_trim_direction',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class   : 'trim',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const direction = script.getField('DIRECTION');\n\n                let r = Entry.hw.portData['trim_roll'];\n                let p = Entry.hw.portData['trim_pitch'];\n                let y = Entry.hw.portData['trim_yaw'];\n                let t = Entry.hw.portData['trim_throttle'];\n\n                const interval = 5;\n\n                switch (direction)\n                {\n                    case    'pitch_inc': { p = p + interval; } break;\n                    case    'pitch_dec': { p = p - interval; } break;\n                    case    'roll_inc':  { r = r + interval; } break;\n                    case    'roll_dec':  { r = r - interval; } break;\n                    case    'reset':     { r=0; p=0; y=0; t=0; } break;\n                    default: break;\n                }\n\n                return Entry.byrobot_base.sendTrim(script, 0x10, r, p, y, t);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_trim: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    null,\n                ],\n                type: 'robolink_codrone_mini_drone_trim',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n            },\n            class   : 'trim',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const r = script.getNumberValue('ROLL');\n                const p = script.getNumberValue('PITCH');\n                const y = Entry.hw.portData['trim_yaw'];\n                const t = Entry.hw.portData['trim_throttle'];\n\n                return Entry.byrobot_base.sendTrim(script, 0x10, r, p, y, t);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_speed: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_level_1, 1],\n                        [Lang.Blocks.drone_level_2, 2],\n                        [Lang.Blocks.drone_level_3, 3],\n                    ],\n                    value     : 1,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_mini_drone_speed',\n            },\n            paramsKeyMap: {\n                LEVEL: 0,\n            },\n            class   : 'trim',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const level = script.getField('LEVEL');\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x04, level);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_flip: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_flip_forward, 0x14],\n                        [Lang.Blocks.drone_flip_rear,    0x15],\n                        [Lang.Blocks.drone_flip_left,    0x16],\n                        [Lang.Blocks.drone_flip_right,   0x17],\n                    ],\n                    value     : 0x14,\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, null],\n                type  : 'robolink_codrone_mini_drone_flip',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class   : 'flip',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const direction = script.getField('DIRECTION');\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x07, direction);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_sensor_reset: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null],\n                type  : 'robolink_codrone_mini_drone_sensor_reset',\n            },\n            paramsKeyMap: {\n            },\n            class   : 'sensor',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                return Entry.byrobot_base.sendCommand(script, 0x10, 0x05, 0, 3000);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_quad_one: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll, 'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch, 'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw, 'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [null, { type: 'number', params: ['0'] }, null],\n                type  : 'robolink_codrone_mini_drone_control_quad_one',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, 0, false);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_quad_one_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                {\n                    type   : 'Dropdown',\n                    options: [\n                        [Lang.Blocks.drone_control_quad_roll, 'control_quad8_roll'],\n                        [Lang.Blocks.drone_control_quad_pitch, 'control_quad8_pitch'],\n                        [Lang.Blocks.drone_control_quad_yaw, 'control_quad8_yaw'],\n                        [Lang.Blocks.drone_control_quad_throttle, 'control_quad8_throttle'],\n                    ],\n                    value     : 'control_quad8_pitch',\n                    fontSize  : 11,\n                    bgColor   : EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    null,\n                    { type: 'number', params: ['100'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_mini_drone_control_quad_one_delay',\n            },\n            paramsKeyMap: {\n                CONTROLTARGET: 0,\n                VALUE        : 1,\n                TIME         : 2,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const controlTarget = script.getField('CONTROLTARGET');\n                const value         = script.getNumberValue('VALUE');\n                const time          = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuadSingle(script, 0x10, controlTarget, value, time, true);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_quad: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    null,\n                ],\n                type: 'robolink_codrone_mini_drone_control_quad',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, 0, false);\n            },\n        },\n\n\n        robolink_codrone_mini_drone_control_quad_delay: {\n            color     : EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine : EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton  : 'basic',\n            statements: [],\n            params    : [\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Block', accept: 'string' },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\n            ],\n            events: {},\n            def   : {\n                params: [\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['0'] },\n                    { type: 'number', params: ['1'] },\n                    null,\n                ],\n                type: 'robolink_codrone_mini_drone_control_quad_delay',\n            },\n            paramsKeyMap: {\n                ROLL    : 0,\n                PITCH   : 1,\n                YAW     : 2,\n                THROTTLE: 3,\n                TIME    : 4,\n            },\n            class   : 'control_quad',\n            isNotFor: ['robolink_codrone_mini'],\n            func(sprite, script) {\n                const roll     = script.getNumberValue('ROLL');\n                const pitch    = script.getNumberValue('PITCH');\n                const yaw      = script.getNumberValue('YAW');\n                const throttle = script.getNumberValue('THROTTLE');\n                const time     = script.getNumberValue('TIME') * 1000;\n\n                return Entry.byrobot_base.sendControlQuad(script, 0x10, roll, pitch, yaw, throttle, time, true);\n            },\n        },\n\n\n    };\n};\n\n\nmodule.exports = Entry.robolink_codrone_mini;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robomation.js",
    "content": "'use strict';\n\nfunction RoboidWriteQueue(size) {\n    this.setSize(size);\n    this.output = new Array(19);\n}\n\nRoboidWriteQueue.prototype.setSize = function(size) {\n    this.buffer = new Array(size);\n    this.mask = size - 1;\n    this.provider = 0;\n    this.consumer = 0;\n};\n\nRoboidWriteQueue.prototype.reset = function() {\n    this.provider = 0;\n    this.consumer = 0;\n};\n\n// from https://github.com/google/closure-library/blob/8598d87242af59aac233270742c8984e2b2bdbe0/closure/goog/crypt/crypt.js\nRoboidWriteQueue.prototype.stringToUtf8ByteArray = function(str) {\n    const out = [];\n    let p = 0, c;\n    for(let i = 0; i < str.length; i++) {\n        c = str.charCodeAt(i);\n        if(c < 128) {\n            out[p++] = c;\n        } else if(c < 2048) {\n            out[p++] = (c >> 6) | 192;\n            out[p++] = (c & 63) | 128;\n        } else if(((c & 0xFC00) == 0xD800) && (i + 1) < str.length && ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {\n            c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);\n            out[p++] = (c >> 18) | 240;\n            out[p++] = ((c >> 12) & 63) | 128;\n            out[p++] = ((c >> 6) & 63) | 128;\n            out[p++] = (c & 63) | 128;\n        } else {\n            out[p++] = (c >> 12) | 224;\n            out[p++] = ((c >> 6) & 63) | 128;\n            out[p++] = (c & 63) | 128;\n        }\n    }\n    return out;\n};\n\nRoboidWriteQueue.prototype.push = function(str, line) {\n    const buffer = this.buffer;\n    const mask = this.mask;\n    let provider = this.provider;\n    let consumer = this.consumer;\n    \n    if(str.length > 0) {\n        const out = this.stringToUtf8ByteArray(str);\n        for(let i = 0; i < out.length; ++i) {\n            if(((provider - consumer) & mask) == mask) { // full\n                consumer = (consumer + 1) & mask;\n            }\n            buffer[provider] = out[i];\n            provider = (provider + 1) & mask;\n        }\n    }\n    if(line) {\n        if(((provider - consumer) & mask) == mask) { // full\n            consumer = (consumer + 1) & mask;\n        }\n        buffer[provider] = 0x0D;\n        provider = (provider + 1) & mask;\n    }\n    this.provider = provider;\n    this.consumer = consumer;\n};\n\nRoboidWriteQueue.prototype.pop = function() {\n    const provider = this.provider;\n    let consumer = this.consumer;\n    if(provider == consumer) return undefined; // empty\n    \n    const buffer = this.buffer;\n    const mask = this.mask;\n    const output = this.output;\n    let len = (provider - consumer) & mask;\n    if(len > 18) len = 18;\n    \n    output[0] = len;\n    let i = 1;\n    for(; i <= len && consumer != provider; ++i) {\n        output[i] = buffer[consumer];\n        consumer = (consumer + 1) & mask;\n    }\n    for(; i <= 18; ++i) {\n        output[i] = 0;\n    }\n    this.consumer = consumer;\n    return output;\n};\n\nfunction RoboidReadQueue(size) {\n    this.setSize(size);\n}\n\nRoboidReadQueue.prototype.setSize = function(size) {\n    this.buffer = new Array(size);\n    this.mask = size - 1;\n    this.provider = 0;\n    this.consumer = 0;\n};\n\nRoboidReadQueue.prototype.reset = function() {\n    this.provider = 0;\n    this.consumer = 0;\n};\n\nRoboidReadQueue.prototype.utf8ByteArrayToString = function(bytes, current, end) {\n    const mask = this.mask, out = [];\n    let c = 0, c1, c2, c3, c4, u;\n    while(current != end) {\n        c1 = bytes[current];\n        current = (current + 1) & mask;\n        if(c1 < 128) {\n            out[c++] = String.fromCharCode(c1);\n        } else if(c1 > 191 && c1 < 224) {\n            if(current == end) break;\n            c2 = bytes[current];\n            current = (current + 1) & mask;\n            out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);\n        } else if(c1 > 239 && c1 < 365) {\n            if(current == end) break;\n            c2 = bytes[current];\n            current = (current + 1) & mask;\n            if(current == end) break;\n            c3 = bytes[current];\n            current = (current + 1) & mask;\n            if(current == end) break;\n            c4 = bytes[current];\n            current = (current + 1) & mask;\n            u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) - 0x10000;\n            out[c++] = String.fromCharCode(0xD800 + (u >> 10));\n            out[c++] = String.fromCharCode(0xDC00 + (u & 1023));\n        } else {\n            if(current == end) break;\n            c2 = bytes[current];\n            current = (current + 1) & mask;\n            if(current == end) break;\n            c3 = bytes[current];\n            current = (current + 1) & mask;\n            out[c++] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);\n        }\n    }\n    this.consumer = current;\n    return out.join('');\n};\n\nRoboidReadQueue.prototype.push = function(packet, offset) {\n    let len = packet[offset];\n    if(len > 0) {\n        if(len > 18) len = 18;\n        \n        const buffer = this.buffer;\n        const mask = this.mask;\n        let provider = this.provider;\n        let consumer = this.consumer;\n        const end = len + offset;\n        for(let i = 1 + offset; i <= end; ++i) {\n            if(((provider - consumer) & mask) == mask) { // full\n                consumer = (consumer + 1) & mask;\n            }\n            buffer[provider] = packet[i];\n            provider = (provider + 1) & mask;\n        }\n        this.provider = provider;\n        this.consumer = consumer;\n    }\n};\n\nRoboidReadQueue.prototype.pop = function(delimiter) {\n    const provider = this.provider;\n    let consumer = this.consumer;\n    if(provider == consumer) return undefined; // empty\n    \n    if(delimiter == 0) {\n        return this.utf8ByteArrayToString(this.buffer, consumer, provider);\n    } else {\n        const buffer = this.buffer;\n        const mask = this.mask;\n        let found = -1;\n        while(consumer != provider) {\n            if(buffer[consumer] == delimiter) {\n                found = consumer;\n                break;\n            }\n            consumer = (consumer + 1) & mask;\n        }\n        if(found >= 0) {\n            const str = this.utf8ByteArrayToString(buffer, this.consumer, found);\n            this.consumer = (this.consumer + 1) & mask;\n            return str;\n        }\n    }\n};\n\n/**HamsterRobot**/\nfunction HamsterRobot(index) {\n    this.sensory = {\n        signalStrength: 0,\n        leftProximity: 0,\n        rightProximity: 0,\n        leftFloor: 0,\n        rightFloor: 0,\n        accelerationX: 0,\n        accelerationY: 0,\n        accelerationZ: 0,\n        light: 0,\n        temperature: 0,\n        inputA: 0,\n        inputB: 0,\n        tilt: 0,\n        batteryState: 2,\n    };\n    this.motoring = {\n        group: 'hamster',\n        module: 'hamster',\n        index,\n    };\n    this.lineTracerModeId = 0;\n    this.lineTracerStateId = -1;\n    this.blockId = 0;\n    this.wheelBlockId = 0;\n    this.wheelTimer = undefined;\n    this.lineTracerCallback = undefined;\n    this.boardCommand = 0;\n    this.boardState = 0;\n    this.boardCount = 0;\n    this.boardCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.ioBlockId = 0;\n    this.ioTimer = undefined;\n    this.tempo = 60;\n    this.timeouts = [];\n}\n\nHamsterRobot.prototype.__PORT_MAP = {\n    group: 'hamster',\n    module: 'hamster',\n    motion: 0,\n    leftWheel: 0,\n    rightWheel: 0,\n    buzzer: 0,\n    outputA: 0,\n    outputB: 0,\n    leftLed: 0,\n    rightLed: 0,\n    note: 0,\n    lineTracerMode: 0,\n    lineTracerModeId: 0,\n    lineTracerSpeed: 5,\n    ioModeA: 0,\n    ioModeB: 0,\n    radius: 5,\n};\n\nHamsterRobot.prototype.setZero = function() {\n    const portMap = this.__PORT_MAP;\n    const motoring = this.motoring;\n    for (const port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    this.lineTracerModeId = 0;\n    this.lineTracerStateId = -1;\n    this.blockId = 0;\n    this.wheelBlockId = 0;\n    this.wheelTimer = undefined;\n    this.lineTracerCallback = undefined;\n    this.boardCommand = 0;\n    this.boardState = 0;\n    this.boardCount = 0;\n    this.boardCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.ioBlockId = 0;\n    this.ioTimer = undefined;\n    this.tempo = 60;\n    this.__removeAllTimeouts();\n};\n\nHamsterRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nHamsterRobot.prototype.afterSend = function(sq) {};\n\nHamsterRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nHamsterRobot.prototype.__setModule = function() {\n    this.motoring.group = 'hamster';\n    this.motoring.module = 'hamster';\n};\n\nHamsterRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    const idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nHamsterRobot.prototype.__removeAllTimeouts = function() {\n    const timeouts = this.timeouts;\n    for (const i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nHamsterRobot.prototype.__issueWheelBlockId = function() {\n    this.wheelBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.wheelBlockId;\n};\n\nHamsterRobot.prototype.__cancelWheel = function() {\n    this.wheelBlockId = 0;\n    if (this.wheelTimer !== undefined) {\n        this.__removeTimeout(this.wheelTimer);\n    }\n    this.wheelTimer = undefined;\n};\n\nHamsterRobot.prototype.__setLineTracerMode = function(mode) {\n    this.lineTracerModeId = (this.lineTracerModeId % 255) + 1;\n    this.motoring.lineTracerMode = mode;\n    this.motoring.lineTracerModeId = this.lineTracerModeId;\n};\n\nHamsterRobot.prototype.__cancelLineTracer = function() {\n    this.lineTracerCallback = undefined;\n};\n\nHamsterRobot.prototype.__cancelBoard = function() {\n    this.boardCommand = 0;\n    this.boardState = 0;\n    this.boardCount = 0;\n    this.boardCallback = undefined;\n};\n\nHamsterRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nHamsterRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nHamsterRobot.prototype.__issueIoBlockId = function() {\n    this.ioBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.ioBlockId;\n};\n\nHamsterRobot.prototype.__cancelIo = function() {\n    this.ioBlockId = 0;\n    if (this.ioTimer !== undefined) {\n        this.__removeTimeout(this.ioTimer);\n    }\n    this.ioTimer = undefined;\n};\n\nHamsterRobot.prototype.handleSensory = function() {\n    const self = this;\n    const sensory = self.sensory;\n    if (self.lineTracerCallback) {\n        if (sensory.lineTracerStateId != self.lineTracerStateId) {\n            self.lineTracerStateId = sensory.lineTracerStateId;\n            if (sensory.lineTracerState == 0x40) {\n                self.__setLineTracerMode(0);\n                var callback = self.lineTracerCallback;\n                self.__cancelLineTracer();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n    if (self.boardCallback) {\n        const motoring = self.motoring;\n        if (self.boardCommand == 1) {\n            switch (self.boardState) {\n                case 1: {\n                    if (self.boardCount < 2) {\n                        if (sensory.leftFloor < 50 && sensory.rightFloor < 50) {\n                            self.boardCount++;\n                        } else {\n                            self.boardCount = 0;\n                        }\n                        var diff = sensory.leftFloor - sensory.rightFloor;\n                        motoring.leftWheel = 45 + diff * 0.25;\n                        motoring.rightWheel = 45 - diff * 0.25;\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 2;\n                    }\n                    break;\n                }\n                case 2: {\n                    var diff = sensory.leftFloor - sensory.rightFloor;\n                    motoring.leftWheel = 45 + diff * 0.25;\n                    motoring.rightWheel = 45 - diff * 0.25;\n                    self.boardState = 3;\n                    self.wheelTimer = setTimeout(() => {\n                        motoring.leftWheel = 0;\n                        motoring.rightWheel = 0;\n                        self.boardState = 4;\n                        if (self.wheelTimer !== undefined) {\n                            self.__removeTimeout(self.wheelTimer);\n                        }\n                        self.wheelTimer = undefined;\n                    }, 250);\n                    self.timeouts.push(self.wheelTimer);\n                    break;\n                }\n                case 3: {\n                    var diff = sensory.leftFloor - sensory.rightFloor;\n                    motoring.leftWheel = 45 + diff * 0.25;\n                    motoring.rightWheel = 45 - diff * 0.25;\n                    break;\n                }\n                case 4: {\n                    motoring.leftWheel = 0;\n                    motoring.rightWheel = 0;\n                    var callback = self.boardCallback;\n                    self.__cancelBoard();\n                    if (callback) {\n                        callback();\n                    }\n                    break;\n                }\n            }\n        } else if (self.boardCommand == 2) {\n            switch (self.boardState) {\n                case 1: {\n                    if (self.boardCount < 2) {\n                        if (sensory.leftFloor > 50) {\n                            self.boardCount++;\n                        }\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 2;\n                    }\n                    break;\n                }\n                case 2: {\n                    if (sensory.leftFloor < 20) {\n                        self.boardState = 3;\n                    }\n                    break;\n                }\n                case 3: {\n                    if (self.boardCount < 2) {\n                        if (sensory.leftFloor < 20) {\n                            self.boardCount++;\n                        }\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 4;\n                    }\n                    break;\n                }\n                case 4: {\n                    if (sensory.leftFloor > 50) {\n                        self.boardState = 5;\n                    }\n                    break;\n                }\n                case 5: {\n                    var diff = sensory.leftFloor - sensory.rightFloor;\n                    if (diff > -15) {\n                        motoring.leftWheel = 0;\n                        motoring.rightWheel = 0;\n                        var callback = self.boardCallback;\n                        self.__cancelBoard();\n                        if (callback) {\n                            callback();\n                        }\n                    } else {\n                        motoring.leftWheel = diff * 0.5;\n                        motoring.rightWheel = -diff * 0.5;\n                    }\n                    break;\n                }\n            }\n        } else if (self.boardCommand == 3) {\n            switch (self.boardState) {\n                case 1: {\n                    if (self.boardCount < 2) {\n                        if (sensory.rightFloor > 50) {\n                            self.boardCount++;\n                        }\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 2;\n                    }\n                    break;\n                }\n                case 2: {\n                    if (sensory.rightFloor < 20) {\n                        self.boardState = 3;\n                    }\n                    break;\n                }\n                case 3: {\n                    if (self.boardCount < 2) {\n                        if (sensory.rightFloor < 20) {\n                            self.boardCount++;\n                        }\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 4;\n                    }\n                    break;\n                }\n                case 4: {\n                    if (sensory.rightFloor > 50) {\n                        self.boardState = 5;\n                    }\n                    break;\n                }\n                case 5: {\n                    var diff = sensory.rightFloor - sensory.leftFloor;\n                    if (diff > -15) {\n                        motoring.leftWheel = 0;\n                        motoring.rightWheel = 0;\n                        var callback = self.boardCallback;\n                        self.__cancelBoard();\n                        if (callback) {\n                            callback();\n                        }\n                    } else {\n                        motoring.leftWheel = -diff * 0.5;\n                        motoring.rightWheel = diff * 0.5;\n                    }\n                    break;\n                }\n            }\n        }\n    }\n};\n\nHamsterRobot.prototype.__SENSORS = {\n    SIGNAL_STRENGTH: 'signalStrength',\n    LEFT_PROXIMITY: 'leftProximity',\n    RIGHT_PROXIMITY: 'rightProximity',\n    LEFT_FLOOR: 'leftFloor',\n    RIGHT_FLOOR: 'rightFloor',\n    ACCELERATION_X: 'accelerationX',\n    ACCELERATION_Y: 'accelerationY',\n    ACCELERATION_Z: 'accelerationZ',\n    LIGHT: 'light',\n    TEMPERATURE: 'temperature',\n    INPUT_A: 'inputA',\n    INPUT_B: 'inputB',\n};\n\nHamsterRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n\n    const sensor = this.__SENSORS[dev] || dev;\n    return this.sensory[sensor];\n};\n\nHamsterRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    const sensory = this.sensory;\n    let value = 0;\n    const dev = script.getField('DEVICE');\n    if (dev.startsWith('TILT')) {\n        if (sensory.tilt === undefined) {\n            if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationX > 8192 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = 1;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationX < -8192 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = -1;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationY > 8192 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096\n            ) {\n                value = 2;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationY < -8192 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096\n            ) {\n                value = -2;\n            } else if (\n                sensory.accelerationZ > 12288 &&\n                sensory.accelerationX > -8192 &&\n                sensory.accelerationX < 8192 &&\n                sensory.accelerationY > -8192 &&\n                sensory.accelerationY < 8192\n            ) {\n                value = 3;\n            } else if (\n                sensory.accelerationZ < -12288 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = -3;\n            } else {\n                value = 0;\n            }\n        } else {\n            value = sensory.tilt;\n        }\n        switch (dev) {\n            case 'TILT_FORWARD':\n                return value == 1;\n            case 'TILT_BACKWARD':\n                return value == -1;\n            case 'TILT_LEFT':\n                return value == 2;\n            case 'TILT_RIGHT':\n                return value == -2;\n            case 'TILT_FLIP':\n                return value == 3;\n            case 'TILT_NOT':\n                return value == -3;\n        }\n        return false;\n    } else {\n        switch (dev) {\n            case 'BATTERY_NORMAL':\n                return sensory.batteryState === 2;\n            case 'BATTERY_LOW':\n                return sensory.batteryState === 1;\n            case 'BATTERY_EMPTY':\n                return sensory.batteryState === 0;\n        }\n        return false;\n    }\n};\n\nHamsterRobot.prototype.checkHandFound = function(script) {\n    this.__setModule();\n    const sensory = this.sensory;\n    return sensory.handFound === undefined\n        ? sensory.leftProximity > 40 || sensory.rightProximity > 40\n        : sensory.handFound;\n};\n\nHamsterRobot.prototype.__board = function(leftVelocity, rightVelocity, command, callback) {\n    const motoring = this.motoring;\n    this.__cancelWheel();\n    this.__cancelLineTracer();\n\n    motoring.leftWheel = leftVelocity;\n    motoring.rightWheel = rightVelocity;\n    motoring.motion = 0;\n    this.boardCommand = command;\n    this.boardCount = 0;\n    this.boardState = 1;\n    this.boardCallback = callback;\n    this.__setLineTracerMode(0);\n};\n\nHamsterRobot.prototype.boardForward = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__board(45, 45, 1, () => {\n            script.isMoving = false;\n        });\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.boardTurn = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const direction = script.getField('DIRECTION');\n        if (direction == 'LEFT') {\n            this.__board(-45, 45, 2, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__board(45, -45, 3, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.__motion = function(type, leftVelocity, rightVelocity, secs, callback) {\n    const self = this;\n    const motoring = self.motoring;\n    self.__cancelBoard();\n    self.__cancelWheel();\n    self.__cancelLineTracer();\n\n    secs = parseFloat(secs);\n    if (secs && secs > 0) {\n        const id = self.__issueWheelBlockId();\n        motoring.leftWheel = leftVelocity;\n        motoring.rightWheel = rightVelocity;\n        motoring.motion = type;\n        self.__setLineTracerMode(0);\n        self.wheelTimer = setTimeout(() => {\n            if (self.wheelBlockId == id) {\n                motoring.leftWheel = 0;\n                motoring.rightWheel = 0;\n                motoring.motion = 0;\n                self.__cancelWheel();\n                callback();\n            }\n        }, secs * 1000);\n        self.timeouts.push(self.wheelTimer);\n    } else {\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        motoring.motion = 0;\n        self.__setLineTracerMode(0);\n        callback();\n    }\n};\n\nHamsterRobot.prototype.moveForwardSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const secs = script.getNumberValue('SECS');\n        if (secs < 0) {\n            this.__motion(2, -30, -30, -secs, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motion(1, 30, 30, secs, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.moveBackwardSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const secs = script.getNumberValue('SECS');\n        if (secs < 0) {\n            this.__motion(1, 30, 30, -secs, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motion(2, -30, -30, secs, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.turnSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const direction = script.getField('DIRECTION');\n        const secs = script.getNumberValue('SECS');\n        if (direction == 'LEFT') {\n            if (secs < 0) {\n                this.__motion(4, 30, -30, -secs, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motion(3, -30, 30, secs, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (secs < 0) {\n                this.__motion(3, -30, 30, -secs, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motion(4, 30, -30, secs, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.__stopMotion = function() {\n    const motoring = this.motoring;\n    this.__cancelBoard();\n    this.__cancelWheel();\n    this.__cancelLineTracer();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    motoring.motion = 0;\n    this.__setLineTracerMode(0);\n};\n\nHamsterRobot.prototype.moveForwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n        if (unit == 'SEC') {\n            if (value < 0) {\n                this.__motion(2, -30, -30, -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motion(1, 30, 30, value, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            this.__stopMotion();\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.moveBackwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n        if (unit == 'SEC') {\n            if (value < 0) {\n                this.__motion(1, 30, 30, -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motion(2, -30, -30, value, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            this.__stopMotion();\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.turnUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n        if (unit == 'SEC') {\n            if (direction == 'LEFT') {\n                if (value < 0) {\n                    this.__motion(4, 30, -30, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motion(3, -30, 30, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motion(3, -30, 30, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motion(4, 30, -30, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else {\n            this.__stopMotion();\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.pivotUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const part = script.getField('PART');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n        const toward = script.getField('TOWARD');\n        if (unit == 'SEC') {\n            if (part == 'LEFT_PEN') {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motion(14, 0, 0, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(13, 0, 0, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motion(13, 0, 0, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(14, 0, 0, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            } else if (part == 'RIGHT_PEN') {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motion(16, 0, 0, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(15, 0, 0, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motion(15, 0, 0, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(16, 0, 0, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            } else if (part == 'LEFT_WHEEL') {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motion(6, 0, -30, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(5, 0, 30, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motion(5, 0, 30, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(6, 0, -30, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            } else {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motion(8, -30, 0, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(7, 30, 0, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motion(7, 30, 0, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(8, -30, 0, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            }\n        } else {\n            this.__stopMotion();\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.swingUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const part = script.getField('PART');\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n        let radius = script.getNumberValue('RADIUS');\n        const toward = script.getField('TOWARD');\n        if (unit == 'SEC') {\n            radius = parseFloat(radius);\n            if (typeof radius == 'number' && radius >= 0) {\n                this.motoring.radius = radius;\n                if (part == 'LEFT_PEN') {\n                    if (direction == 'LEFT') {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(18, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(17, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(17, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(18, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    } else {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(20, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(19, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(19, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(20, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    }\n                } else if (part == 'RIGHT_PEN') {\n                    if (direction == 'LEFT') {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(22, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(21, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(21, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(22, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    } else {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(24, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(23, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(23, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(24, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    }\n                } else {\n                    if (direction == 'LEFT') {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(10, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(9, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(9, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(10, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    } else {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(12, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(11, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(11, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(12, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    }\n                }\n            } else {\n                this.__stopMotion();\n                script.isMoving = false;\n            }\n        } else {\n            this.__stopMotion();\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.setWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelWheel();\n    this.__cancelLineTracer();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel = leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel = rightVelocity;\n    }\n    motoring.motion = 0;\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.changeWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelWheel();\n    this.__cancelLineTracer();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel =\n            motoring.leftWheel !== undefined ? motoring.leftWheel + leftVelocity : leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel =\n            motoring.rightWheel !== undefined ? motoring.rightWheel + rightVelocity : rightVelocity;\n    }\n    motoring.motion = 0;\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.setWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelWheel();\n    this.__cancelLineTracer();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel = velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel = velocity;\n        } else {\n            motoring.leftWheel = velocity;\n            motoring.rightWheel = velocity;\n        }\n    }\n    motoring.motion = 0;\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.changeWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelWheel();\n    this.__cancelLineTracer();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        } else {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        }\n    }\n    motoring.motion = 0;\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.followLine = function(script) {\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelWheel();\n    this.__cancelLineTracer();\n\n    const color = script.getField('COLOR');\n    const sensor = script.getField('SENSOR');\n\n    let mode = 1;\n    if (sensor == 'RIGHT') {\n        mode = 2;\n    } else if (sensor == 'BOTH') {\n        mode = 3;\n    }\n    if (color == 'WHITE') {\n        mode += 7;\n    }\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    motoring.motion = 0;\n    this.__setLineTracerMode(mode);\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.followLineUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelBoard();\n        this.__cancelWheel();\n\n        const color = script.getField('COLOR');\n        const direction = script.getField('DIRECTION');\n\n        let mode = 4;\n        if (direction == 'RIGHT') {\n            mode = 5;\n        } else if (direction == 'FRONT') {\n            mode = 6;\n        } else if (direction == 'REAR') {\n            mode = 7;\n        }\n        if (color == 'WHITE') {\n            mode += 7;\n        }\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        motoring.motion = 0;\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.setLineTracerSpeed = function(script) {\n    this.__setModule();\n    const speed = parseInt(script.getField('SPEED'));\n\n    if (typeof speed == 'number') {\n        this.motoring.lineTracerSpeed = speed;\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.setLineTracerGain = function(script) {\n    this.__setModule();\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.stop = function(script) {\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelWheel();\n    this.__cancelLineTracer();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    motoring.motion = 0;\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.__COLORS = {\n    RED: 4,\n    ORANGE: 4,\n    YELLOW: 6,\n    GREEN: 2,\n    SKY_BLUE: 3,\n    BLUE: 1,\n    VIOLET: 5,\n    PURPLE: 5,\n    WHITE: 7,\n    '4': 4,\n    '6': 6,\n    '2': 2,\n    '3': 3,\n    '1': 1,\n    '5': 5,\n    '7': 7,\n};\n\nHamsterRobot.prototype.setLed = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    let color = script.getField('COLOR');\n    color = parseInt(this.__COLORS[color]);\n\n    if (color && color > 0) {\n        if (led == 'LEFT') {\n            this.motoring.leftLed = color;\n        } else if (led == 'RIGHT') {\n            this.motoring.rightLed = color;\n        } else {\n            this.motoring.leftLed = color;\n            this.motoring.rightLed = color;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.pickLed = function(script) {\n    this.__setModule();\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.clearLed = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n\n    if (led == 'LEFT') {\n        this.motoring.leftLed = 0;\n    } else if (led == 'RIGHT') {\n        this.motoring.rightLed = 0;\n    } else {\n        this.motoring.leftLed = 0;\n        this.motoring.rightLed = 0;\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.setRgb = function(script) {\n    this.__setModule();\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.changeRgb = function(script) {\n    this.__setModule();\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.__runBeep = function(count, id, callback) {\n    if (count) {\n        const self = this;\n        const motoring = self.motoring;\n        motoring.buzzer = 440;\n        motoring.note = 0;\n        self.noteTimer1 = setTimeout(() => {\n            if (!id || self.noteBlockId == id) {\n                motoring.buzzer = 0;\n                if (self.noteTimer1 !== undefined) {\n                    self.__removeTimeout(self.noteTimer1);\n                }\n                self.noteTimer1 = undefined;\n            }\n        }, 100);\n        self.timeouts.push(self.noteTimer1);\n        self.noteTimer2 = setTimeout(() => {\n            if (!id || self.noteBlockId == id) {\n                motoring.buzzer = 0;\n                if (self.noteTimer2 !== undefined) {\n                    self.__removeTimeout(self.noteTimer2);\n                }\n                self.noteTimer2 = undefined;\n                if (count < 0) {\n                    self.__runBeep(-1, id, callback);\n                } else if (count == 1) {\n                    self.__cancelNote();\n                    if (id && callback) {\n                        callback();\n                    }\n                } else {\n                    self.__runBeep(count - 1, id, callback);\n                }\n            }\n        }, 200);\n        self.timeouts.push(self.noteTimer2);\n    }\n};\n\nHamsterRobot.prototype.beep = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        const id = this.__issueNoteBlockId();\n        this.__runBeep(1, id, () => {\n            script.isPlaying = false;\n        });\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.playSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n\n    const sound = script.getField('SOUND');\n    let count = script.getNumberValue('COUNT');\n\n    count = parseInt(count);\n    if (sound == 'BEEP' && count) {\n        this.__runBeep(count);\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.playSoundUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.motoring.buzzer = 0;\n        this.motoring.note = 0;\n\n        const sound = script.getField('SOUND');\n        let count = script.getNumberValue('COUNT');\n\n        count = parseInt(count);\n        if (count) {\n            if (sound == 'BEEP') {\n                const id = this.__issueNoteBlockId();\n                this.__runBeep(count, id, () => {\n                    script.isPlaying = false;\n                });\n            }\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.motoring.note = 0;\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    let hz = script.getNumberValue('HZ');\n\n    const motoring = this.motoring;\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    motoring.note = 0;\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.clearBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.clearSound = function(script, motoring) {\n    return this.clearBuzzer(script);\n};\n\nHamsterRobot.prototype.__NOTES = {\n    C: 4,\n    'C#': 5,\n    Db: 5,\n    D: 6,\n    'D#': 7,\n    Eb: 7,\n    E: 8,\n    F: 9,\n    'F#': 10,\n    Gb: 10,\n    G: 11,\n    'G#': 12,\n    Ab: 12,\n    A: 13,\n    'A#': 14,\n    Bb: 14,\n    B: 15,\n    '4': 4,\n    '5': 5,\n    '6': 6,\n    '7': 7,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n    '11': 11,\n    '12': 12,\n    '13': 13,\n    '14': 14,\n    '15': 15,\n};\n\nHamsterRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n\n    let note = script.getField('NOTE');\n    let octave = script.getNumberField('OCTAVE');\n\n    note = parseInt(this.__NOTES[note]);\n    octave = parseInt(octave);\n    const motoring = this.motoring;\n    motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        motoring.note = note + (octave - 1) * 12;\n    } else {\n        motoring.note = 0;\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.playNoteBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n\n        const motoring = self.motoring;\n        let note = script.getField('NOTE');\n        let octave = script.getNumberField('OCTAVE');\n        let beat = script.getNumberValue('BEAT');\n\n        note = parseInt(this.__NOTES[note]);\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            motoring.note = note;\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        motoring.note = 0;\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    motoring.note = 0;\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n        } else {\n            motoring.note = 0;\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.motoring.note = 0;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.restBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        let beat = script.getNumberValue('BEAT');\n\n        const motoring = self.motoring;\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        motoring.note = 0;\n        if (beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.__IO_MODES = {\n    ANALOG_INPUT: 0,\n    DIGITAL_INPUT: 1,\n    DIGITAL_INPUT_PULL_UP: 2,\n    DIGITAL_INPUT_PULL_DOWN: 3,\n    VOLTAGE_INPUT: 5,\n    SERVO_OUTPUT: 8,\n    PWM_OUTPUT: 9,\n    DIGITAL_OUTPUT: 10,\n    '0': 0,\n    '1': 1,\n    '2': 2,\n    '3': 3,\n    '5': 5,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n};\n\nHamsterRobot.prototype.setIoMode = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n\n    const port = script.getField('PORT');\n    const mode = parseInt(this.__IO_MODES[script.getField('MODE')]);\n\n    const motoring = this.motoring;\n    if (typeof mode == 'number') {\n        if (port == 'A') {\n            motoring.ioModeA = mode;\n        } else if (port == 'B') {\n            motoring.ioModeB = mode;\n        } else {\n            motoring.ioModeA = mode;\n            motoring.ioModeB = mode;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.setOutput = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n\n    const motoring = this.motoring;\n    const port = script.getField('PORT');\n    let value = script.getNumberValue('VALUE');\n\n    value = parseFloat(value);\n    if (typeof value == 'number') {\n        if (port == 'A') {\n            motoring.outputA = value;\n        } else if (port == 'B') {\n            motoring.outputB = value;\n        } else {\n            motoring.outputA = value;\n            motoring.outputB = value;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.changeOutput = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n\n    const motoring = this.motoring;\n    const port = script.getField('PORT');\n    let value = script.getNumberValue('VALUE');\n\n    value = parseFloat(value);\n    if (typeof value == 'number') {\n        if (port == 'A') {\n            motoring.outputA = motoring.outputA != undefined ? motoring.outputA + value : value;\n        } else if (port == 'B') {\n            motoring.outputB = motoring.outputB != undefined ? motoring.outputB + value : value;\n        } else {\n            motoring.outputA = motoring.outputA != undefined ? motoring.outputA + value : value;\n            motoring.outputB = motoring.outputB != undefined ? motoring.outputB + value : value;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.gripper = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelIo();\n\n        const id = self.__issueIoBlockId();\n        const action = script.getField('ACTION');\n\n        const motoring = this.motoring;\n        motoring.ioModeA = 10;\n        motoring.ioModeB = 10;\n        if (action == 'OPEN') {\n            motoring.outputA = 1;\n            motoring.outputB = 0;\n        } else {\n            motoring.outputA = 0;\n            motoring.outputB = 1;\n        }\n        self.ioTimer = setTimeout(() => {\n            if (self.ioBlockId == id) {\n                self.__cancelIo();\n                script.isPlaying = false;\n            }\n        }, 500);\n        self.timeouts.push(self.ioTimer);\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterRobot.prototype.releaseGripper = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n\n    const motoring = this.motoring;\n    motoring.ioModeA = 10;\n    motoring.ioModeB = 10;\n    motoring.outputA = 0;\n    motoring.outputB = 0;\n    return script.callReturn();\n};\n\nHamsterRobot.prototype.writeSerial = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n    return script;\n};\n\nHamsterRobot.prototype.readSerialUntil = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n    return script;\n};\n\nHamsterRobot.prototype.setSerialRate = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n    return script;\n};\n\nHamsterRobot.prototype.getSerialInput = function(script) {\n    this.__setModule();\n    return '';\n};\n\n/**HamsterSRobot**/\nfunction HamsterSRobot(index) {\n    this.sensory = {\n        signalStrength: 0,\n        leftProximity: 0,\n        rightProximity: 0,\n        leftFloor: 0,\n        rightFloor: 0,\n        accelerationX: 0,\n        accelerationY: 0,\n        accelerationZ: 0,\n        light: 0,\n        temperature: 0,\n        inputA: 0,\n        inputB: 0,\n        tilt: 0,\n        batteryState: 2,\n    };\n    this.motoring = {\n        group: 'hamster',\n        module: 'hamsterS',\n        index,\n    };\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.lineTracerModeId = 0;\n    this.motionId = 0;\n    this.writeSerialId = 0;\n    this.tapId = -1;\n    this.freeFallId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.lineTracerStateId = -1;\n    this.readSerialId = -1;\n    this.serialStateId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.lineTracerCallback = undefined;\n    this.boardCommand = 0;\n    this.boardState = 0;\n    this.boardCount = 0;\n    this.boardCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.ioBlockId = 0;\n    this.ioTimer = undefined;\n    this.serialDelimiter = 0;\n    this.serialRate = 176;\n    this.writeSerialCallbacks = [];\n    this.readSerialCallbacks = [];\n    this.serialInput = '';\n    this.freeFall = false;\n    this.tap = false;\n    this.tempo = 60;\n    this.speed = 5;\n    this.gain = -1;\n    this.writeQueue = new RoboidWriteQueue(64);\n    this.readQueue = new RoboidReadQueue(64);\n    this.timeouts = [];\n}\n\nHamsterSRobot.prototype.__PORT_MAP = {\n    group: 'hamster',\n    module: 'hamsterS',\n    leftWheel: 0,\n    rightWheel: 0,\n    leftRgb: '0,0,0',\n    leftRed: 0,\n    leftGreen: 0,\n    leftBlue: 0,\n    rightRgb: '0,0,0',\n    rightRed: 0,\n    rightGreen: 0,\n    rightBlue: 0,\n    buzzer: 0,\n    outputA: 0,\n    outputB: 0,\n    pulse: 0,\n    pulseId: 0,\n    note: 0,\n    sound: 0,\n    soundRepeat: 1,\n    soundId: 0,\n    lineTracerMode: 0,\n    lineTracerModeId: 0,\n    lineTracerGain: 4,\n    lineTracerSpeed: 5,\n    ioModeA: 0,\n    ioModeB: 0,\n    motionId: 0,\n    motionType: 0,\n    motionUnit: 0,\n    motionSpeed: 0,\n    motionValue: 0,\n    motionRadius: 0,\n};\n\nHamsterSRobot.prototype.setZero = function() {\n    const portMap = this.__PORT_MAP;\n    const motoring = this.motoring;\n    for (const port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.lineTracerModeId = 0;\n    this.motionId = 0;\n    this.writeSerialId = 0;\n    this.tapId = -1;\n    this.freeFallId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.lineTracerStateId = -1;\n    this.readSerialId = -1;\n    this.serialStateId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.lineTracerCallback = undefined;\n    this.boardCommand = 0;\n    this.boardState = 0;\n    this.boardCount = 0;\n    this.boardCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.ioBlockId = 0;\n    this.ioTimer = undefined;\n    this.serialDelimiter = 0;\n    this.serialRate = 176;\n    this.writeSerialCallbacks = [];\n    this.readSerialCallbacks = [];\n    this.serialInput = '';\n    this.freeFall = false;\n    this.tap = false;\n    this.tempo = 60;\n    this.speed = 5;\n    this.gain = -1;\n    this.__removeAllTimeouts();\n    this.writeQueue.reset();\n    this.readQueue.reset();\n};\n\nHamsterSRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nHamsterSRobot.prototype.afterSend = function(sq) {\n    this.freeFall = false;\n    this.tap = false;\n};\n\nHamsterSRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nHamsterSRobot.prototype.__setModule = function() {\n    this.motoring.group = 'hamster';\n    this.motoring.module = 'hamsterS';\n};\n\nHamsterSRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    const idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nHamsterSRobot.prototype.__removeAllTimeouts = function() {\n    const timeouts = this.timeouts;\n    for (const i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nHamsterSRobot.prototype.__fireWriteSerialCallbacks = function() {\n    const callbacks = this.writeSerialCallbacks;\n    for (const i in callbacks) {\n        callbacks[i]();\n    }\n    this.writeSerialCallbacks = [];\n};\n\nHamsterSRobot.prototype.__fireReadSerialCallbacks = function() {\n    const callbacks = this.readSerialCallbacks;\n    for (const i in callbacks) {\n        callbacks[i]();\n    }\n    this.readSerialCallbacks = [];\n};\n\nHamsterSRobot.prototype.__setPulse = function(pulse) {\n    this.pulseId = (this.pulseId % 255) + 1;\n    this.motoring.pulse = pulse;\n    this.motoring.pulseId = this.pulseId;\n};\n\nHamsterSRobot.prototype.__setLineTracerMode = function(mode) {\n    this.lineTracerModeId = (this.lineTracerModeId % 255) + 1;\n    this.motoring.lineTracerMode = mode;\n    this.motoring.lineTracerModeId = this.lineTracerModeId;\n};\n\nHamsterSRobot.prototype.__cancelLineTracer = function() {\n    this.lineTracerCallback = undefined;\n};\n\nHamsterSRobot.prototype.__setMotion = function(type, unit, speed, value, radius) {\n    this.motionId = (this.motionId % 255) + 1;\n    const motoring = this.motoring;\n    motoring.motionType = type;\n    motoring.motionUnit = unit;\n    motoring.motionSpeed = speed;\n    motoring.motionValue = value;\n    motoring.motionRadius = radius;\n    motoring.motionId = this.motionId;\n};\n\nHamsterSRobot.prototype.__cancelMotion = function() {\n    this.motionCallback = undefined;\n};\n\nHamsterSRobot.prototype.__cancelBoard = function() {\n    this.boardCommand = 0;\n    this.boardState = 0;\n    this.boardCount = 0;\n    this.boardCallback = undefined;\n};\n\nHamsterSRobot.prototype.__runSound = function(sound, count) {\n    if (typeof count != 'number') {\n        count = 1;\n    }\n    if (count < 0) {\n        count = -1;\n    }\n    if (count) {\n        this.soundId = (this.soundId % 255) + 1;\n        const motoring = this.motoring;\n        motoring.sound = sound;\n        motoring.soundRepeat = count;\n        motoring.soundId = this.soundId;\n    }\n};\n\nHamsterSRobot.prototype.__cancelSound = function() {\n    this.soundCallback = undefined;\n};\n\nHamsterSRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nHamsterSRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nHamsterSRobot.prototype.__issueIoBlockId = function() {\n    this.ioBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.ioBlockId;\n};\n\nHamsterSRobot.prototype.__cancelIo = function() {\n    this.ioBlockId = 0;\n    if (this.ioTimer !== undefined) {\n        this.__removeTimeout(this.ioTimer);\n    }\n    this.ioTimer = undefined;\n};\n\nHamsterSRobot.prototype.__setSerial = function(arr) {\n    this.writeSerialId = (this.writeSerialId % 255) + 1;\n    const motoring = this.motoring;\n    if (motoring.writeSerial == undefined) {\n        motoring.writeSerial = new Array(19);\n    }\n    for (let i = 0; i < 19; ++i) {\n        motoring.writeSerial[i] = arr[i];\n    }\n    motoring.writeSerialId = this.writeSerialId;\n};\n\nHamsterSRobot.prototype.handleSensory = function() {\n    const self = this;\n    const sensory = self.sensory;\n\n    self.freeFall = sensory.freeFall == 1;\n    self.tap = sensory.tap == 1;\n\n    if (self.lineTracerCallback) {\n        if (sensory.lineTracerStateId != self.lineTracerStateId) {\n            self.lineTracerStateId = sensory.lineTracerStateId;\n            if (sensory.lineTracerState == 0x40) {\n                self.__setLineTracerMode(0);\n                var callback = self.lineTracerCallback;\n                self.__cancelLineTracer();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n    if (self.boardCallback) {\n        const motoring = self.motoring;\n        if (self.boardCommand == 1) {\n            switch (self.boardState) {\n                case 1: {\n                    if (self.boardCount < 2) {\n                        if (sensory.leftFloor < 50 && sensory.rightFloor < 50) {\n                            self.boardCount++;\n                        } else {\n                            self.boardCount = 0;\n                        }\n                        var diff = sensory.leftFloor - sensory.rightFloor;\n                        motoring.leftWheel = 45 + diff * 0.25;\n                        motoring.rightWheel = 45 - diff * 0.25;\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 2;\n                    }\n                    break;\n                }\n                case 2: {\n                    var diff = sensory.leftFloor - sensory.rightFloor;\n                    motoring.leftWheel = 45 + diff * 0.25;\n                    motoring.rightWheel = 45 - diff * 0.25;\n                    self.boardState = 3;\n                    self.wheelTimer = setTimeout(() => {\n                        motoring.leftWheel = 0;\n                        motoring.rightWheel = 0;\n                        self.boardState = 4;\n                        if (self.wheelTimer !== undefined) {\n                            self.__removeTimeout(self.wheelTimer);\n                        }\n                        self.wheelTimer = undefined;\n                    }, 250);\n                    self.timeouts.push(self.wheelTimer);\n                    break;\n                }\n                case 3: {\n                    var diff = sensory.leftFloor - sensory.rightFloor;\n                    motoring.leftWheel = 45 + diff * 0.25;\n                    motoring.rightWheel = 45 - diff * 0.25;\n                    break;\n                }\n                case 4: {\n                    motoring.leftWheel = 0;\n                    motoring.rightWheel = 0;\n                    var callback = self.boardCallback;\n                    self.__cancelBoard();\n                    if (callback) {\n                        callback();\n                    }\n                    break;\n                }\n            }\n        } else if (self.boardCommand == 2) {\n            switch (self.boardState) {\n                case 1: {\n                    if (self.boardCount < 2) {\n                        if (sensory.leftFloor > 50) {\n                            self.boardCount++;\n                        }\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 2;\n                    }\n                    break;\n                }\n                case 2: {\n                    if (sensory.leftFloor < 20) {\n                        self.boardState = 3;\n                    }\n                    break;\n                }\n                case 3: {\n                    if (self.boardCount < 2) {\n                        if (sensory.leftFloor < 20) {\n                            self.boardCount++;\n                        }\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 4;\n                    }\n                    break;\n                }\n                case 4: {\n                    if (sensory.leftFloor > 50) {\n                        self.boardState = 5;\n                    }\n                    break;\n                }\n                case 5: {\n                    var diff = sensory.leftFloor - sensory.rightFloor;\n                    if (diff > -15) {\n                        motoring.leftWheel = 0;\n                        motoring.rightWheel = 0;\n                        var callback = self.boardCallback;\n                        self.__cancelBoard();\n                        if (callback) {\n                            callback();\n                        }\n                    } else {\n                        motoring.leftWheel = diff * 0.5;\n                        motoring.rightWheel = -diff * 0.5;\n                    }\n                    break;\n                }\n            }\n        } else if (self.boardCommand == 3) {\n            switch (self.boardState) {\n                case 1: {\n                    if (self.boardCount < 2) {\n                        if (sensory.rightFloor > 50) {\n                            self.boardCount++;\n                        }\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 2;\n                    }\n                    break;\n                }\n                case 2: {\n                    if (sensory.rightFloor < 20) {\n                        self.boardState = 3;\n                    }\n                    break;\n                }\n                case 3: {\n                    if (self.boardCount < 2) {\n                        if (sensory.rightFloor < 20) {\n                            self.boardCount++;\n                        }\n                    } else {\n                        self.boardCount = 0;\n                        self.boardState = 4;\n                    }\n                    break;\n                }\n                case 4: {\n                    if (sensory.rightFloor > 50) {\n                        self.boardState = 5;\n                    }\n                    break;\n                }\n                case 5: {\n                    var diff = sensory.rightFloor - sensory.leftFloor;\n                    if (diff > -15) {\n                        motoring.leftWheel = 0;\n                        motoring.rightWheel = 0;\n                        var callback = self.boardCallback;\n                        self.__cancelBoard();\n                        if (callback) {\n                            callback();\n                        }\n                    } else {\n                        motoring.leftWheel = -diff * 0.5;\n                        motoring.rightWheel = diff * 0.5;\n                    }\n                    break;\n                }\n            }\n        }\n    }\n    if (self.motionCallback) {\n        if (sensory.wheelStateId != self.wheelStateId) {\n            self.wheelStateId = sensory.wheelStateId;\n            if (sensory.wheelState == 2) {\n                self.motoring.leftWheel = 0;\n                self.motoring.rightWheel = 0;\n                var callback = self.motionCallback;\n                self.__cancelMotion();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n    if (self.soundCallback) {\n        if (sensory.soundStateId != self.soundStateId) {\n            self.soundStateId = sensory.soundStateId;\n            if (sensory.soundState == 0) {\n                var callback = self.soundCallback;\n                self.__cancelSound();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n    if (sensory.readSerialId != self.readSerialId) {\n        if (sensory.readSerial && self.readSerialId >= 0) {\n            self.readQueue.push(sensory.readSerial, 0);\n        }\n        self.readSerialId = sensory.readSerialId;\n    }\n    if (sensory.serialStateId != self.serialStateId) {\n        self.serialStateId = sensory.serialStateId;\n        if (sensory.serialState == 1) {\n            var tmp = self.writeQueue.pop();\n            if (tmp) {\n                self.__setSerial(tmp);\n            } else {\n                self.__fireWriteSerialCallbacks();\n            }\n        }\n    }\n    if (self.readSerialCallbacks.length > 0) {\n        var tmp = self.readQueue.pop(self.serialDelimiter);\n        if (tmp) {\n            self.serialInput = tmp;\n            self.__fireReadSerialCallbacks();\n        }\n    }\n};\n\nHamsterSRobot.prototype.__SENSORS = {\n    SIGNAL_STRENGTH: 'signalStrength',\n    LEFT_PROXIMITY: 'leftProximity',\n    RIGHT_PROXIMITY: 'rightProximity',\n    LEFT_FLOOR: 'leftFloor',\n    RIGHT_FLOOR: 'rightFloor',\n    ACCELERATION_X: 'accelerationX',\n    ACCELERATION_Y: 'accelerationY',\n    ACCELERATION_Z: 'accelerationZ',\n    LIGHT: 'light',\n    TEMPERATURE: 'temperature',\n    INPUT_A: 'inputA',\n    INPUT_B: 'inputB',\n    SERIAL_INPUT: 'readSerial',\n};\n\nHamsterSRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n\n    if (dev == 'SERIAL_INPUT') {\n        return this.getSerialInput();\n    } else {\n        const sensor = this.__SENSORS[dev] || dev;\n        return this.sensory[sensor];\n    }\n};\n\nHamsterSRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    const sensory = this.sensory;\n    let value = 0;\n    const dev = script.getField('DEVICE');\n    if (dev.startsWith('TILT')) {\n        if (sensory.tilt === undefined) {\n            if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationX > 8192 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = 1;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationX < -8192 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = -1;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationY > 8192 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096\n            ) {\n                value = 2;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationY < -8192 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096\n            ) {\n                value = -2;\n            } else if (\n                sensory.accelerationZ > 12288 &&\n                sensory.accelerationX > -8192 &&\n                sensory.accelerationX < 8192 &&\n                sensory.accelerationY > -8192 &&\n                sensory.accelerationY < 8192\n            ) {\n                value = 3;\n            } else if (\n                sensory.accelerationZ < -12288 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = -3;\n            } else {\n                value = 0;\n            }\n        } else {\n            value = sensory.tilt;\n        }\n        switch (dev) {\n            case 'TILT_FORWARD':\n                return value == 1;\n            case 'TILT_BACKWARD':\n                return value == -1;\n            case 'TILT_LEFT':\n                return value == 2;\n            case 'TILT_RIGHT':\n                return value == -2;\n            case 'TILT_FLIP':\n                return value == 3;\n            case 'TILT_NOT':\n                return value == -3;\n        }\n        return false;\n    } else {\n        switch (dev) {\n            case 'TAP':\n                return this.tap;\n            case 'FREE_FALL':\n                return this.freeFall;\n            case 'BATTERY_NORMAL':\n                return sensory.batteryState === 2;\n            case 'BATTERY_LOW':\n                return sensory.batteryState === 1;\n            case 'BATTERY_EMPTY':\n                return sensory.batteryState === 0;\n        }\n        return false;\n    }\n};\n\nHamsterSRobot.prototype.checkHandFound = function(script) {\n    this.__setModule();\n    const sensory = this.sensory;\n    return sensory.handFound === undefined\n        ? sensory.leftProximity > 50 || sensory.rightProximity > 50\n        : sensory.handFound;\n};\n\nHamsterSRobot.prototype.__board = function(leftVelocity, rightVelocity, command, callback) {\n    const motoring = this.motoring;\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    motoring.leftWheel = leftVelocity;\n    motoring.rightWheel = rightVelocity;\n    this.boardCommand = command;\n    this.boardCount = 0;\n    this.boardState = 1;\n    this.boardCallback = callback;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n};\n\nHamsterSRobot.prototype.boardForward = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__board(45, 45, 1, () => {\n            script.isMoving = false;\n        });\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.boardTurn = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const direction = script.getField('DIRECTION');\n        if (direction == 'LEFT') {\n            this.__board(-45, 45, 2, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__board(45, -45, 3, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.__motionUnit = function(type, unit, value, callback) {\n    const motoring = this.motoring;\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    if (value && value > 0) {\n        this.__setMotion(type, unit, 0, value, 0); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n        this.__setLineTracerMode(0);\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(0);\n        callback();\n    }\n};\n\nHamsterSRobot.prototype.__motionUnitRadius = function(type, unit, value, radius, callback) {\n    const motoring = this.motoring;\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    radius = parseFloat(radius);\n    if (value && value > 0 && typeof radius == 'number' && radius >= 0) {\n        this.__setMotion(type, unit, 0, value, radius); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n        this.__setLineTracerMode(0);\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(0);\n        callback();\n    }\n};\n\nHamsterSRobot.prototype.moveForwardSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const secs = script.getNumberValue('SECS');\n        if (secs < 0) {\n            this.__motionUnit(2, 2, -secs, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(1, 2, secs, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.moveBackwardSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const secs = script.getNumberValue('SECS');\n        if (secs < 0) {\n            this.__motionUnit(1, 2, -secs, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(2, 2, secs, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.turnSecs = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        const direction = script.getField('DIRECTION');\n        const secs = script.getNumberValue('SECS');\n        if (direction == 'LEFT') {\n            if (secs < 0) {\n                this.__motionUnit(4, 2, -secs, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(3, 2, secs, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (secs < 0) {\n                this.__motionUnit(3, 2, -secs, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(4, 2, secs, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.__stopMotion = function() {\n    const motoring = this.motoring;\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n};\n\nHamsterSRobot.prototype.__UNITS = {\n    CM: 1,\n    DEG: 1,\n    SEC: 2,\n    PULSE: 3,\n};\n\nHamsterSRobot.prototype.moveForwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(2, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(1, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.moveBackwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(1, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(2, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.turnUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (direction == 'LEFT') {\n            if (value < 0) {\n                this.__motionUnit(4, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(3, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (value < 0) {\n                this.__motionUnit(3, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(4, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.pivotUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const part = script.getField('PART');\n        const value = script.getNumberValue('VALUE');\n        let unit = script.getField('UNIT');\n        const toward = script.getField('TOWARD');\n\n        unit = this.__UNITS[unit];\n        if (part == 'LEFT_PEN') {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(14, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(13, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(13, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(14, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else if (part == 'RIGHT_PEN') {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(16, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(15, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(15, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(16, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else if (part == 'LEFT_WHEEL') {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(6, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(5, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(5, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(6, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(8, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(7, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(7, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(8, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.swingUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const part = script.getField('PART');\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        let unit = script.getField('UNIT');\n        const radius = script.getNumberValue('RADIUS');\n        const toward = script.getField('TOWARD');\n\n        unit = this.__UNITS[unit];\n        if (part == 'LEFT_PEN') {\n            if (direction == 'LEFT') {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motionUnitRadius(18, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(17, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motionUnitRadius(17, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(18, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            } else {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motionUnitRadius(20, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(19, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motionUnitRadius(19, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(20, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            }\n        } else if (part == 'RIGHT_PEN') {\n            if (direction == 'LEFT') {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motionUnitRadius(22, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(21, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motionUnitRadius(21, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(22, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            } else {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motionUnitRadius(24, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(23, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motionUnitRadius(23, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(24, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            }\n        } else {\n            if (direction == 'LEFT') {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motionUnitRadius(10, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(9, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motionUnitRadius(9, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(10, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            } else {\n                if (toward == 'FORWARD') {\n                    if (value < 0) {\n                        this.__motionUnitRadius(12, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(11, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (value < 0) {\n                        this.__motionUnitRadius(11, unit, -value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motionUnitRadius(12, unit, value, radius, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.setWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel = leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel = rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.changeWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel =\n            motoring.leftWheel !== undefined ? motoring.leftWheel + leftVelocity : leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel =\n            motoring.rightWheel !== undefined ? motoring.rightWheel + rightVelocity : rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.setWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel = velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel = velocity;\n        } else {\n            motoring.leftWheel = velocity;\n            motoring.rightWheel = velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.changeWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = parseFloat(script.getNumberValue('VELOCITY'));\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        } else {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.followLine = function(script) {\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    const color = script.getField('COLOR');\n    const sensor = script.getField('SENSOR');\n\n    let mode = 1;\n    if (sensor == 'RIGHT') {\n        mode = 2;\n    } else if (sensor == 'BOTH') {\n        mode = 3;\n    }\n    if (color == 'WHITE') {\n        mode += 7;\n    }\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(mode);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.followLineUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelBoard();\n        this.__cancelMotion();\n\n        const color = script.getField('COLOR');\n        const direction = script.getField('DIRECTION');\n\n        let mode = 4;\n        if (direction == 'RIGHT') {\n            mode = 5;\n        } else if (direction == 'FRONT') {\n            mode = 6;\n        } else if (direction == 'REAR') {\n            mode = 7;\n        }\n        if (color == 'WHITE') {\n            mode += 7;\n        }\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.__GAINS = {\n    1: 6,\n    2: 6,\n    3: 5,\n    4: 5,\n    5: 4,\n    6: 4,\n    7: 3,\n    8: 3,\n};\n\nHamsterSRobot.prototype.setLineTracerSpeed = function(script) {\n    this.__setModule();\n    const speed = parseInt(script.getField('SPEED'));\n\n    let gain = this.gain;\n    if (gain < 0) {\n        gain = this.__GAINS[speed];\n    }\n    if (speed && gain && speed > 0 && gain > 0) {\n        this.speed = speed;\n        this.motoring.lineTracerSpeed = speed;\n        this.motoring.lineTracerGain = gain;\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.setLineTracerGain = function(script) {\n    this.__setModule();\n    let gain = parseInt(script.getField('GAIN'));\n\n    if (gain && gain > 0) {\n        this.gain = gain;\n        this.motoring.lineTracerGain = gain;\n    } else {\n        this.gain = -1;\n        gain = this.__GAINS[this.speed];\n        if (gain && gain > 0) {\n            this.motoring.lineTracerGain = gain;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.stop = function(script) {\n    this.__setModule();\n    this.__cancelBoard();\n    this.__cancelMotion();\n    this.__cancelLineTracer();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.__RGB_COLORS = {\n    RED: [255, 0, 0],\n    ORANGE: [255, 63, 0],\n    YELLOW: [255, 255, 0],\n    GREEN: [0, 255, 0],\n    SKY_BLUE: [0, 255, 255],\n    BLUE: [0, 0, 255],\n    VIOLET: [63, 0, 255],\n    PURPLE: [255, 0, 255],\n    WHITE: [255, 255, 255],\n    '4': [255, 0, 0],\n    '6': [255, 255, 0],\n    '2': [0, 255, 0],\n    '3': [0, 255, 255],\n    '1': [0, 0, 255],\n    '5': [255, 0, 255],\n    '7': [255, 255, 255],\n};\n\nHamsterSRobot.prototype.setLed = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    const color = script.getField('COLOR');\n\n    const rgb = this.__RGB_COLORS[color];\n    if (rgb) {\n        const motoring = this.motoring;\n        if (led == 'LEFT') {\n            motoring.leftRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.leftRed = rgb[0];\n            motoring.leftGreen = rgb[1];\n            motoring.leftBlue = rgb[2];\n        } else if (led == 'RIGHT') {\n            motoring.rightRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.rightRed = rgb[0];\n            motoring.rightGreen = rgb[1];\n            motoring.rightBlue = rgb[2];\n        } else {\n            motoring.leftRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.leftRed = rgb[0];\n            motoring.leftGreen = rgb[1];\n            motoring.leftBlue = rgb[2];\n            motoring.rightRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.rightRed = rgb[0];\n            motoring.rightGreen = rgb[1];\n            motoring.rightBlue = rgb[2];\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.pickLed = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    const color = script.getField('COLOR');\n\n    const red = parseInt(color.slice(1, 3), 16);\n    const green = parseInt(color.slice(3, 5), 16);\n    const blue = parseInt(color.slice(5, 7), 16);\n\n    const motoring = this.motoring;\n    if (led == 'LEFT') {\n        motoring.leftRgb = `${red},${green},${blue}`;\n        motoring.leftRed = red;\n        motoring.leftGreen = green;\n        motoring.leftBlue = blue;\n    } else if (led == 'RIGHT') {\n        motoring.rightRgb = `${red},${green},${blue}`;\n        motoring.rightRed = red;\n        motoring.rightGreen = green;\n        motoring.rightBlue = blue;\n    } else {\n        motoring.leftRgb = `${red},${green},${blue}`;\n        motoring.leftRed = red;\n        motoring.leftGreen = green;\n        motoring.leftBlue = blue;\n        motoring.rightRgb = `${red},${green},${blue}`;\n        motoring.rightRed = red;\n        motoring.rightGreen = green;\n        motoring.rightBlue = blue;\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.clearLed = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n\n    const motoring = this.motoring;\n    if (led == 'LEFT') {\n        motoring.leftRgb = '0,0,0';\n        motoring.leftRed = 0;\n        motoring.leftGreen = 0;\n        motoring.leftBlue = 0;\n    } else if (led == 'RIGHT') {\n        motoring.rightRgb = '0,0,0';\n        motoring.rightRed = 0;\n        motoring.rightGreen = 0;\n        motoring.rightBlue = 0;\n    } else {\n        motoring.leftRgb = '0,0,0';\n        motoring.leftRed = 0;\n        motoring.leftGreen = 0;\n        motoring.leftBlue = 0;\n        motoring.rightRgb = '0,0,0';\n        motoring.rightRed = 0;\n        motoring.rightGreen = 0;\n        motoring.rightBlue = 0;\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.setRgb = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    const motoring = this.motoring;\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if (led == 'LEFT') {\n        if (typeof red == 'number') {\n            motoring.leftRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue = blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n    } else if (led == 'RIGHT') {\n        if (typeof red == 'number') {\n            motoring.rightRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.rightGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.rightBlue = blue;\n        }\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    } else {\n        if (typeof red == 'number') {\n            motoring.leftRed = red;\n            motoring.rightRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen = green;\n            motoring.rightGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue = blue;\n            motoring.rightBlue = blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.changeRgb = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    const motoring = this.motoring;\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if (led == 'LEFT') {\n        if (typeof red == 'number') {\n            motoring.leftRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue += blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n    } else if (led == 'RIGHT') {\n        if (typeof red == 'number') {\n            motoring.rightRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.rightGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.rightBlue += blue;\n        }\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    } else {\n        if (typeof red == 'number') {\n            motoring.leftRed += red;\n            motoring.rightRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen += green;\n            motoring.rightGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue += blue;\n            motoring.rightBlue += blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.beep = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.__cancelSound();\n\n        this.motoring.buzzer = 0;\n        this.motoring.note = 0;\n        this.__runSound(1, 1);\n        this.soundCallback = function() {\n            script.isPlaying = false;\n        };\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.__SOUNDS = {\n    BEEP: 1,\n    RANDOM_BEEP: 2,\n    NOISE: 10,\n    SIREN: 3,\n    ENGINE: 4,\n    CHOP: 11,\n    ROBOT: 5,\n    DIBIDIBIDIP: 8,\n    GOOD_JOB: 9,\n    HAPPY: 12,\n    ANGRY: 13,\n    SAD: 14,\n    SLEEP: 15,\n    MARCH: 6,\n    BIRTHDAY: 7,\n};\n\nHamsterSRobot.prototype.playSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let sound = script.getField('SOUND');\n    let count = script.getNumberValue('COUNT');\n\n    sound = this.__SOUNDS[sound];\n    count = parseInt(count);\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    if (sound && count) {\n        this.__runSound(sound, count);\n    } else {\n        this.__runSound(0);\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.playSoundUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.__cancelSound();\n\n        let sound = script.getField('SOUND');\n        let count = script.getNumberValue('COUNT');\n        sound = this.__SOUNDS[sound];\n        count = parseInt(count);\n        this.motoring.buzzer = 0;\n        this.motoring.note = 0;\n        if (sound && count) {\n            this.__runSound(sound, count);\n            this.soundCallback = function() {\n                script.isPlaying = false;\n            };\n        } else {\n            this.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    const motoring = this.motoring;\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.clearBuzzer = function(script) {\n    return this.clearSound(script);\n};\n\nHamsterSRobot.prototype.clearSound = function(script, motoring) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.__NOTES = {\n    C: 4,\n    'C#': 5,\n    Db: 5,\n    D: 6,\n    'D#': 7,\n    Eb: 7,\n    E: 8,\n    F: 9,\n    'F#': 10,\n    Gb: 10,\n    G: 11,\n    'G#': 12,\n    Ab: 12,\n    A: 13,\n    'A#': 14,\n    Bb: 14,\n    B: 15,\n    '4': 4,\n    '5': 5,\n    '6': 6,\n    '7': 7,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n    '11': 11,\n    '12': 12,\n    '13': 13,\n    '14': 14,\n    '15': 15,\n};\n\nHamsterSRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let note = script.getField('NOTE');\n    let octave = script.getNumberField('OCTAVE');\n\n    note = parseInt(this.__NOTES[note]);\n    octave = parseInt(octave);\n    const motoring = this.motoring;\n    motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        motoring.note = note + (octave - 1) * 12;\n    } else {\n        motoring.note = 0;\n    }\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.playNoteBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n\n        const motoring = self.motoring;\n        let note = script.getField('NOTE');\n        let octave = script.getNumberField('OCTAVE');\n        let beat = script.getNumberValue('BEAT');\n\n        note = parseInt(this.__NOTES[note]);\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            motoring.note = note;\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        motoring.note = 0;\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    motoring.note = 0;\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n            self.__runSound(0);\n        } else {\n            motoring.note = 0;\n            self.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.motoring.note = 0;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.restBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n        let beat = script.getNumberValue('BEAT');\n\n        const motoring = self.motoring;\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        motoring.note = 0;\n        self.__runSound(0);\n        if (beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.__IO_MODES = {\n    ANALOG_INPUT: 0,\n    DIGITAL_INPUT: 1,\n    DIGITAL_INPUT_PULL_UP: 2,\n    DIGITAL_INPUT_PULL_DOWN: 3,\n    VOLTAGE_INPUT: 5,\n    SERVO_OUTPUT: 8,\n    PWM_OUTPUT: 9,\n    DIGITAL_OUTPUT: 10,\n    '0': 0,\n    '1': 1,\n    '2': 2,\n    '3': 3,\n    '5': 5,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n};\n\nHamsterSRobot.prototype.setIoMode = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n\n    const port = script.getField('PORT');\n    const mode = parseInt(this.__IO_MODES[script.getField('MODE')]);\n\n    const motoring = this.motoring;\n    if (typeof mode == 'number') {\n        if (port == 'A') {\n            motoring.ioModeA = mode;\n        } else if (port == 'B') {\n            motoring.ioModeB = mode;\n        } else {\n            motoring.ioModeA = mode;\n            motoring.ioModeB = mode;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.setOutput = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n\n    const motoring = this.motoring;\n    const port = script.getField('PORT');\n    let value = script.getNumberValue('VALUE');\n\n    value = parseFloat(value);\n    if (typeof value == 'number') {\n        if (port == 'A') {\n            motoring.outputA = value;\n        } else if (port == 'B') {\n            motoring.outputB = value;\n        } else {\n            motoring.outputA = value;\n            motoring.outputB = value;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.changeOutput = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n\n    const motoring = this.motoring;\n    const port = script.getField('PORT');\n    let value = script.getNumberValue('VALUE');\n\n    value = parseFloat(value);\n    if (typeof value == 'number') {\n        if (port == 'A') {\n            motoring.outputA = motoring.outputA != undefined ? motoring.outputA + value : value;\n        } else if (port == 'B') {\n            motoring.outputB = motoring.outputB != undefined ? motoring.outputB + value : value;\n        } else {\n            motoring.outputA = motoring.outputA != undefined ? motoring.outputA + value : value;\n            motoring.outputB = motoring.outputB != undefined ? motoring.outputB + value : value;\n        }\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.gripper = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelIo();\n\n        const id = self.__issueIoBlockId();\n        const action = script.getField('ACTION');\n\n        const motoring = this.motoring;\n        motoring.ioModeA = 10;\n        motoring.ioModeB = 10;\n        if (action == 'OPEN') {\n            motoring.outputA = 1;\n            motoring.outputB = 0;\n        } else {\n            motoring.outputA = 0;\n            motoring.outputB = 1;\n        }\n        self.ioTimer = setTimeout(() => {\n            if (self.ioBlockId == id) {\n                self.__cancelIo();\n                script.isPlaying = false;\n            }\n        }, 500);\n        self.timeouts.push(self.ioTimer);\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.releaseGripper = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n\n    const motoring = this.motoring;\n    motoring.ioModeA = 10;\n    motoring.ioModeB = 10;\n    motoring.outputA = 0;\n    motoring.outputB = 0;\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.writeSerial = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWriting = true;\n        self.__cancelIo();\n\n        const mode = script.getField('MODE');\n        const text = script.getValue('STRING');\n\n        const motoring = self.motoring;\n        motoring.ioModeA = self.serialRate;\n        motoring.ioModeB = self.serialRate;\n        const queue = this.writeQueue;\n        queue.push(text, mode != 'STRING');\n        const data = queue.pop();\n        if (data) {\n            this.writeSerialCallbacks.push(() => {\n                script.isWriting = false;\n            });\n            this.__setSerial(data);\n        }\n        return script;\n    } else if (script.isWriting) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWriting;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.__SERIAL_DELIMITERS = {\n    ALL: 0,\n    COMMA: 0x2c,\n    COLON: 0x3a,\n    DOLLAR: 0x24,\n    SHARP: 0x23,\n    NEW_LINE: 0x0d,\n};\n\nHamsterSRobot.prototype.readSerialUntil = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isReading = true;\n        self.__cancelIo();\n\n        let delimiter = script.getField('DELIMITER');\n\n        const motoring = self.motoring;\n        motoring.ioModeA = self.serialRate;\n        motoring.ioModeB = self.serialRate;\n        delimiter = this.__SERIAL_DELIMITERS[delimiter];\n        if (typeof delimiter == 'number') {\n            this.serialDelimiter = delimiter;\n            this.readSerialCallbacks.push(() => {\n                script.isReading = false;\n            });\n        }\n        return script;\n    } else if (script.isReading) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isReading;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nHamsterSRobot.prototype.__SERIAL_BAUDS = {\n    '9600': 176,\n    '14400': 177,\n    '19200': 178,\n    '28800': 179,\n    '38400': 180,\n    '57600': 181,\n    '76800': 182,\n    '115200': 183,\n};\n\nHamsterSRobot.prototype.setSerialRate = function(script) {\n    this.__setModule();\n    this.__cancelIo();\n    const baud = this.__SERIAL_BAUDS[script.getField('BAUD')];\n\n    if (baud && baud > 0) {\n        this.serialRate = baud;\n        this.motoring.ioModeA = baud;\n        this.motoring.ioModeB = baud;\n    }\n    return script.callReturn();\n};\n\nHamsterSRobot.prototype.getSerialInput = function(script) {\n    this.__setModule();\n    return this.serialInput;\n};\n\n/**TurtleRobot**/\nfunction TurtleRobot(index) {\n    this.sensory = {\n        floor: 0,\n        accelerationX: 0,\n        accelerationY: 0,\n        accelerationZ: 0,\n        button: 0,\n        colorNumber: -1,\n        colorPattern: -1,\n        tilt: 0,\n        batteryState: 2,\n    };\n    this.motoring = {\n        group: 'turtle',\n        module: 'turtle',\n        index,\n    };\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.lineTracerModeId = 0;\n    this.motionId = 0;\n    this.clickedId = -1;\n    this.doubleClickedId = -1;\n    this.longPressedId = -1;\n    this.colorPatternId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.lineTracerStateId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.lineTracerCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.colorPattern = -1;\n    this.tempo = 60;\n    this.timeouts = [];\n}\n\nTurtleRobot.prototype.__PORT_MAP = {\n    group: 'turtle',\n    module: 'turtle',\n    leftWheel: 0,\n    rightWheel: 0,\n    ledRed: 0,\n    ledGreen: 0,\n    ledBlue: 0,\n    buzzer: 0,\n    pulse: 0,\n    pulseId: 0,\n    note: 0,\n    sound: 0,\n    soundRepeat: 1,\n    soundId: 0,\n    lineTracerMode: 0,\n    lineTracerModeId: 0,\n    lineTracerGain: 5,\n    lineTracerSpeed: 5,\n    motionId: 0,\n    motionType: 0,\n    motionUnit: 0,\n    motionSpeed: 0,\n    motionValue: 0,\n    motionRadius: 0,\n};\n\nTurtleRobot.prototype.setZero = function() {\n    const portMap = this.__PORT_MAP;\n    const motoring = this.motoring;\n    for (const port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.lineTracerModeId = 0;\n    this.motionId = 0;\n    this.clickedId = -1;\n    this.doubleClickedId = -1;\n    this.longPressedId = -1;\n    this.colorPatternId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.lineTracerStateId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.lineTracerCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.colorPattern = -1;\n    this.tempo = 60;\n    this.__removeAllTimeouts();\n};\n\nTurtleRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nTurtleRobot.prototype.afterSend = function(sq) {\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.colorPattern = -1;\n};\n\nTurtleRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nTurtleRobot.prototype.__setModule = function() {\n    this.motoring.group = 'turtle';\n    this.motoring.module = 'turtle';\n};\n\nTurtleRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    const idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nTurtleRobot.prototype.__removeAllTimeouts = function() {\n    const timeouts = this.timeouts;\n    for (const i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nTurtleRobot.prototype.__setPulse = function(pulse) {\n    this.pulseId = (this.pulseId % 255) + 1;\n    this.motoring.pulse = pulse;\n    this.motoring.pulseId = this.pulseId;\n};\n\nTurtleRobot.prototype.__setLineTracerMode = function(mode) {\n    this.lineTracerModeId = (this.lineTracerModeId % 255) + 1;\n    this.motoring.lineTracerMode = mode;\n    this.motoring.lineTracerModeId = this.lineTracerModeId;\n};\n\nTurtleRobot.prototype.__cancelLineTracer = function() {\n    this.lineTracerCallback = undefined;\n};\n\nTurtleRobot.prototype.__setMotion = function(type, unit, speed, value, radius) {\n    this.motionId = (this.motionId % 255) + 1;\n    const motoring = this.motoring;\n    motoring.motionType = type;\n    motoring.motionUnit = unit;\n    motoring.motionSpeed = speed;\n    motoring.motionValue = value;\n    motoring.motionRadius = radius;\n    motoring.motionId = this.motionId;\n};\n\nTurtleRobot.prototype.__cancelMotion = function() {\n    this.motionCallback = undefined;\n};\n\nTurtleRobot.prototype.__runSound = function(sound, count) {\n    if (typeof count != 'number') {\n        count = 1;\n    }\n    if (count < 0) {\n        count = -1;\n    }\n    if (count) {\n        this.soundId = (this.soundId % 255) + 1;\n        const motoring = this.motoring;\n        motoring.sound = sound;\n        motoring.soundRepeat = count;\n        motoring.soundId = this.soundId;\n    }\n};\n\nTurtleRobot.prototype.__cancelSound = function() {\n    this.soundCallback = undefined;\n};\n\nTurtleRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nTurtleRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nTurtleRobot.prototype.handleSensory = function() {\n    const self = this;\n    const sensory = self.sensory;\n\n    self.clicked = sensory.clicked == 1;\n    self.doubleClicked = sensory.doubleClicked == 1;\n    self.longPressed = sensory.longPressed == 1;\n    self.colorPattern = sensory.colorPattern;\n\n    if (self.lineTracerCallback) {\n        if (sensory.lineTracerStateId != self.lineTracerStateId) {\n            self.lineTracerStateId = sensory.lineTracerStateId;\n            if (sensory.lineTracerState == 0x02) {\n                self.__setLineTracerMode(0);\n                var callback = self.lineTracerCallback;\n                self.__cancelLineTracer();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n    if (self.motionCallback) {\n        if (sensory.wheelStateId != self.wheelStateId) {\n            self.wheelStateId = sensory.wheelStateId;\n            if (sensory.wheelState == 0) {\n                self.motoring.leftWheel = 0;\n                self.motoring.rightWheel = 0;\n                var callback = self.motionCallback;\n                self.__cancelMotion();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n    if (self.soundCallback) {\n        if (sensory.soundStateId != self.soundStateId) {\n            self.soundStateId = sensory.soundStateId;\n            if (sensory.soundState == 0) {\n                var callback = self.soundCallback;\n                self.__cancelSound();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n};\n\nTurtleRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n    if (dev == 'colorPattern') {\n        return this.colorPattern;\n    } else {\n        return this.sensory[dev];\n    }\n};\n\nTurtleRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    const sensory = this.sensory;\n    let value = 0;\n    const dev = script.getField('DEVICE');\n    if (dev.startsWith('TILT')) {\n        if (sensory.tilt === undefined) {\n            if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationX > 8192 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = 1;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationX < -8192 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = -1;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationY > 8192 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096\n            ) {\n                value = 2;\n            } else if (\n                sensory.accelerationZ < 8192 &&\n                sensory.accelerationY < -8192 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096\n            ) {\n                value = -2;\n            } else if (\n                sensory.accelerationZ > 12288 &&\n                sensory.accelerationX > -8192 &&\n                sensory.accelerationX < 8192 &&\n                sensory.accelerationY > -8192 &&\n                sensory.accelerationY < 8192\n            ) {\n                value = 3;\n            } else if (\n                sensory.accelerationZ < -12288 &&\n                sensory.accelerationX > -4096 &&\n                sensory.accelerationX < 4096 &&\n                sensory.accelerationY > -4096 &&\n                sensory.accelerationY < 4096\n            ) {\n                value = -3;\n            } else {\n                value = 0;\n            }\n        } else {\n            value = sensory.tilt;\n        }\n        switch (dev) {\n            case 'TILT_FORWARD':\n                return value == 1;\n            case 'TILT_BACKWARD':\n                return value == -1;\n            case 'TILT_LEFT':\n                return value == 2;\n            case 'TILT_RIGHT':\n                return value == -2;\n            case 'TILT_FLIP':\n                return value == 3;\n            case 'TILT_NOT':\n                return value == -3;\n        }\n        return false;\n    } else {\n        switch (dev) {\n            case 'BATTERY_NORMAL':\n                return sensory.batteryState === 2;\n            case 'BATTERY_LOW':\n                return sensory.batteryState === 1;\n            case 'BATTERY_EMPTY':\n                return sensory.batteryState === 0;\n        }\n        return false;\n    }\n};\n\nTurtleRobot.prototype.checkTouchingColor = function(script) {\n    this.__setModule();\n    const color = Number(script.getField('COLOR'));\n\n    if (typeof color == 'number') {\n        return this.sensory.colorNumber == color - 1;\n    }\n    return false;\n};\n\nTurtleRobot.prototype.checkColorPattern = function(script) {\n    this.__setModule();\n    const color1 = Number(script.getField('COLOR1'));\n    const color2 = Number(script.getField('COLOR2'));\n\n    if (typeof color1 == 'number' && typeof color2 == 'number') {\n        return this.colorPattern == color1 * 10 + color2;\n    }\n    return false;\n};\n\nTurtleRobot.prototype.checkButtonState = function(script) {\n    this.__setModule();\n    const state = script.getField('STATE');\n    switch (state) {\n        case 'clicked':\n            return this.clicked;\n        case 'doubleClicked':\n            return this.doubleClicked;\n        case 'longPressed':\n            return this.longPressed;\n    }\n    return false;\n};\n\nTurtleRobot.prototype.__motionUnit = function(type, unit, value, callback) {\n    const motoring = this.motoring;\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    if (value && value > 0) {\n        this.__setMotion(type, unit, 0, value, 0); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n        this.__setLineTracerMode(0);\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(0);\n        callback();\n    }\n};\n\nTurtleRobot.prototype.__motionUnitRadius = function(type, unit, value, radius, callback) {\n    const motoring = this.motoring;\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    radius = parseFloat(radius);\n    if (value && value > 0 && typeof radius == 'number' && radius >= 0) {\n        this.__setMotion(type, unit, 0, value, radius); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n        this.__setLineTracerMode(0);\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(0);\n        callback();\n    }\n};\n\nTurtleRobot.prototype.__UNITS = {\n    CM: 1,\n    DEG: 1,\n    SEC: 2,\n    PULSE: 3,\n};\n\nTurtleRobot.prototype.moveForwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(2, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(1, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.moveBackwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(1, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(2, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.turnUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (direction == 'LEFT') {\n            if (value < 0) {\n                this.__motionUnit(4, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(3, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (value < 0) {\n                this.__motionUnit(3, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(4, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.pivotUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const wheel = script.getField('WHEEL');\n        const value = script.getNumberValue('VALUE');\n        let unit = script.getField('UNIT');\n        const toward = script.getField('TOWARD');\n\n        unit = this.__UNITS[unit];\n        if (wheel == 'LEFT') {\n            if (toward == 'HEAD') {\n                if (value < 0) {\n                    this.__motionUnit(6, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(5, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(5, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(6, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else {\n            if (toward == 'HEAD') {\n                if (value < 0) {\n                    this.__motionUnit(8, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(7, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(7, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(8, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.swingUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        let unit = script.getField('UNIT');\n        const radius = script.getNumberValue('RADIUS');\n        const toward = script.getField('TOWARD');\n\n        unit = this.__UNITS[unit];\n        if (direction == 'LEFT') {\n            if (toward == 'HEAD') {\n                if (value < 0) {\n                    this.__motionUnitRadius(10, unit, -value, radius, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnitRadius(9, unit, value, radius, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnitRadius(9, unit, -value, radius, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnitRadius(10, unit, value, radius, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else {\n            if (toward == 'HEAD') {\n                if (value < 0) {\n                    this.__motionUnitRadius(12, unit, -value, radius, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnitRadius(11, unit, value, radius, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnitRadius(11, unit, -value, radius, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnitRadius(12, unit, value, radius, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.setWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel = leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel = rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.changeWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel =\n            motoring.leftWheel !== undefined ? motoring.leftWheel + leftVelocity : leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel =\n            motoring.rightWheel !== undefined ? motoring.rightWheel + rightVelocity : rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.setWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel = velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel = velocity;\n        } else {\n            motoring.leftWheel = velocity;\n            motoring.rightWheel = velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.changeWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        } else {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.followLine = function(script) {\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const mode = Number(script.getField('COLOR'));\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(mode);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.followLineUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        const mode = Number(script.getField('COLOR'));\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.followLineUntilBlack = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        const mode = Number(script.getField('COLOR'));\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.crossIntersection = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(40);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.turnAtIntersection = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        const mode = Number(script.getField('DIRECTION'));\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.setLineTracerSpeed = function(script) {\n    this.__setModule();\n    let speed = Number(script.getField('SPEED'));\n\n    speed = parseInt(speed);\n    if (typeof speed == 'number') {\n        this.motoring.lineTracerSpeed = speed;\n        this.motoring.lineTracerGain = speed;\n    }\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.stop = function(script) {\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.__RGB_COLORS = {\n    RED: [255, 0, 0],\n    ORANGE: [255, 63, 0],\n    YELLOW: [255, 255, 0],\n    GREEN: [0, 255, 0],\n    CYAN: [0, 255, 255],\n    BLUE: [0, 0, 255],\n    VIOLET: [63, 0, 255],\n    MAGENTA: [255, 0, 255],\n    WHITE: [255, 255, 255],\n};\n\nTurtleRobot.prototype.setHeadColor = function(script) {\n    this.__setModule();\n    const color = script.getField('COLOR');\n\n    const rgb = this.__RGB_COLORS[color];\n    if (rgb) {\n        const motoring = this.motoring;\n        motoring.ledRed = rgb[0];\n        motoring.ledGreen = rgb[1];\n        motoring.ledBlue = rgb[2];\n    }\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.pickHeadColor = function(script) {\n    this.__setModule();\n    const color = script.getField('COLOR');\n\n    const motoring = this.motoring;\n    motoring.ledRed = parseInt(color.slice(1, 3), 16);\n    motoring.ledGreen = parseInt(color.slice(3, 5), 16);\n    motoring.ledBlue = parseInt(color.slice(5, 7), 16);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.setHeadRgb = function(script) {\n    this.__setModule();\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    const motoring = this.motoring;\n    if (typeof red == 'number') {\n        motoring.ledRed = red;\n    }\n    if (typeof green == 'number') {\n        motoring.ledGreen = green;\n    }\n    if (typeof blue == 'number') {\n        motoring.ledBlue = blue;\n    }\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.changeHeadRgb = function(script) {\n    this.__setModule();\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    const motoring = this.motoring;\n    if (typeof red == 'number') {\n        motoring.ledRed = motoring.ledRed != undefined ? motoring.ledRed + red : red;\n    }\n    if (typeof green == 'number') {\n        motoring.ledGreen = motoring.ledGreen != undefined ? motoring.ledGreen + green : green;\n    }\n    if (typeof blue == 'number') {\n        motoring.ledBlue = motoring.ledBlue != undefined ? motoring.ledBlue + blue : blue;\n    }\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.clearHead = function(script) {\n    this.__setModule();\n    const motoring = this.motoring;\n    motoring.ledRed = 0;\n    motoring.ledGreen = 0;\n    motoring.ledBlue = 0;\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.playSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    const sound = Number(script.getField('SOUND'));\n    let count = script.getNumberValue('COUNT');\n\n    count = parseInt(count);\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    if (sound && count) {\n        this.__runSound(sound, count);\n    } else {\n        this.__runSound(0);\n    }\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.playSoundUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.__cancelSound();\n\n        const sound = Number(script.getField('SOUND'));\n        let count = script.getNumberValue('COUNT');\n\n        count = parseInt(count);\n        this.motoring.buzzer = 0;\n        this.motoring.note = 0;\n        if (sound && count) {\n            this.__runSound(sound, count);\n            this.soundCallback = function() {\n                script.isPlaying = false;\n            };\n        } else {\n            this.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let hz = script.getNumberValue('HZ');\n\n    const motoring = this.motoring;\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.clearSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    const note = script.getNumberField('NOTE');\n    let octave = script.getNumberField('OCTAVE');\n\n    octave = parseInt(octave);\n    const motoring = this.motoring;\n    motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        motoring.note = note + (octave - 1) * 12;\n    } else {\n        motoring.note = 0;\n    }\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.playNoteBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n\n        const motoring = self.motoring;\n        let note = script.getNumberField('NOTE');\n        let octave = script.getNumberField('OCTAVE');\n        let beat = script.getNumberValue('BEAT');\n\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            motoring.note = note;\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        motoring.note = 0;\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    motoring.note = 0;\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n            self.__runSound(0);\n            return script;\n        } else {\n            motoring.note = 0;\n            self.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.motoring.note = 0;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.restBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n\n        const motoring = self.motoring;\n        let beat = script.getNumberValue('BEAT');\n\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        motoring.note = 0;\n        self.__runSound(0);\n        if (beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n            return script;\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nTurtleRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nTurtleRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\n/**LineRobot**/\nfunction LineRobot(index, module) {\n    this.sensory = {\n        signalStrength: 0,\n        colorRed: 0,\n        colorGreen: 0,\n        colorBlue: 0,\n        floor: 0,\n        accelerationX: 0,\n        accelerationY: 0,\n        accelerationZ: 0,\n        temperature: 0,\n        button: 0,\n        colorNumber: -1,\n        colorPattern: -1,\n        pulseCount: 0,\n        tilt: 0,\n        batteryState: 2,\n    };\n    this.motoring = {\n        group: 'line',\n        module: module,\n        index,\n    };\n    this.module = module;\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.lineTracerModeId = 0;\n    this.motionId = 0;\n    this.clickedId = -1;\n    this.doubleClickedId = -1;\n    this.longPressedId = -1;\n    this.colorPatternId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.lineTracerStateId = -1;\n    this.freeFallId = -1;\n    this.tapId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.lineTracerCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.colorPattern = -1;\n    this.freeFall = false;\n    this.tap = false;\n    this.tempo = 60;\n    this.timeouts = [];\n}\n\nLineRobot.prototype.__PORT_MAP = {\n    group: 'line',\n    leftWheel: 0,\n    rightWheel: 0,\n    ledRed: 0,\n    ledGreen: 0,\n    ledBlue: 0,\n    buzzer: 0,\n    pulse: 0,\n    pulseId: 0,\n    note: 0,\n    sound: 0,\n    soundRepeat: 1,\n    soundId: 0,\n    lineTracerMode: 0,\n    lineTracerModeId: 0,\n    lineTracerSpeed: 4,\n    motionId: 0,\n    motionType: 0,\n    motionUnit: 0,\n    motionSpeed: 0,\n    motionValue: 0,\n    motionRadius: 0,\n};\n\nLineRobot.prototype.setZero = function() {\n    const portMap = this.__PORT_MAP;\n    const motoring = this.motoring;\n    for (const port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    motoring.module = this.module;\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.lineTracerModeId = 0;\n    this.motionId = 0;\n    this.clickedId = -1;\n    this.doubleClickedId = -1;\n    this.longPressedId = -1;\n    this.colorPatternId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.lineTracerStateId = -1;\n    this.freeFallId = -1;\n    this.tapId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.lineTracerCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.colorPattern = -1;\n    this.freeFall = false;\n    this.tap = false;\n    this.tempo = 60;\n    this.__removeAllTimeouts();\n};\n\nLineRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nLineRobot.prototype.afterSend = function(sq) {\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.colorPattern = -1;\n    this.freeFall = false;\n    this.tap = false;\n};\n\nLineRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nLineRobot.prototype.__setModule = function() {\n    this.motoring.group = 'line';\n    this.motoring.module = this.module;\n};\n\nLineRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    const idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nLineRobot.prototype.__removeAllTimeouts = function() {\n    const timeouts = this.timeouts;\n    for (const i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nLineRobot.prototype.__setPulse = function(pulse) {\n    this.pulseId = (this.pulseId % 255) + 1;\n    this.motoring.pulse = pulse;\n    this.motoring.pulseId = this.pulseId;\n};\n\nLineRobot.prototype.__setLineTracerMode = function(mode) {\n    this.lineTracerModeId = (this.lineTracerModeId % 255) + 1;\n    this.motoring.lineTracerMode = mode;\n    this.motoring.lineTracerModeId = this.lineTracerModeId;\n};\n\nLineRobot.prototype.__cancelLineTracer = function() {\n    this.lineTracerCallback = undefined;\n};\n\nLineRobot.prototype.__setMotion = function(type, unit, speed, value, radius) {\n    this.motionId = (this.motionId % 255) + 1;\n    const motoring = this.motoring;\n    motoring.motionType = type;\n    motoring.motionUnit = unit;\n    motoring.motionSpeed = speed;\n    motoring.motionValue = value;\n    motoring.motionRadius = radius;\n    motoring.motionId = this.motionId;\n};\n\nLineRobot.prototype.__cancelMotion = function() {\n    this.motionCallback = undefined;\n};\n\nLineRobot.prototype.__runSound = function(sound, count) {\n    if(typeof count != 'number') count = 1;\n    if(count < 0) count = -1;\n    if(count) {\n        this.soundId = (this.soundId % 255) + 1;\n        const motoring = this.motoring;\n        motoring.sound = sound;\n        motoring.soundRepeat = count;\n        motoring.soundId = this.soundId;\n    }\n};\n\nLineRobot.prototype.__cancelSound = function() {\n    this.soundCallback = undefined;\n};\n\nLineRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nLineRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nLineRobot.prototype.handleSensory = function() {\n    const self = this;\n    const sensory = self.sensory;\n    \n    self.clicked = sensory.clicked == 1;\n    self.doubleClicked = sensory.doubleClicked == 1;\n    self.longPressed = sensory.longPressed == 1;\n    self.colorPattern = sensory.colorPattern;\n    self.freeFall = sensory.freeFall == 1;\n    self.tap = sensory.tap == 1;\n\n    if(self.lineTracerCallback) {\n        if(sensory.lineTracerStateId != self.lineTracerStateId) {\n            self.lineTracerStateId = sensory.lineTracerStateId;\n            if(sensory.lineTracerState == 0x02) {\n                self.__setLineTracerMode(0);\n                var callback = self.lineTracerCallback;\n                self.__cancelLineTracer();\n                if(callback) callback();\n            }\n        }\n    }\n    if(self.motionCallback) {\n        if(sensory.wheelStateId != self.wheelStateId) {\n            self.wheelStateId = sensory.wheelStateId;\n            if(sensory.wheelState == 0) {\n                self.motoring.leftWheel = 0;\n                self.motoring.rightWheel = 0;\n                var callback = self.motionCallback;\n                self.__cancelMotion();\n                if(callback) callback();\n            }\n        }\n    }\n    if(self.soundCallback) {\n        if(sensory.soundStateId != self.soundStateId) {\n            self.soundStateId = sensory.soundStateId;\n            if(sensory.soundState == 0) {\n                var callback = self.soundCallback;\n                self.__cancelSound();\n                if(callback) callback();\n            }\n        }\n    }\n};\n\nLineRobot.prototype.__SENSORS = {\n    SIGNAL_STRENGTH: 'signalStrength',\n    COLOR_R: 'colorRed',\n    COLOR_G: 'colorGreen',\n    COLOR_B: 'colorBlue',\n    FLOOR: 'floor',\n    ACCELERATION_X: 'accelerationX',\n    ACCELERATION_Y: 'accelerationY',\n    ACCELERATION_Z: 'accelerationZ',\n    TEMPERATURE: 'temperature',\n    BUTTON: 'button',\n    COLOR_NUMBER: 'colorNumber',\n};\n\nLineRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n    \n    if(dev == 'COLOR_PATTERN') {\n        return this.colorPattern;\n    } else {\n        const sensor = this.__SENSORS[dev] || dev;\n        return this.sensory[sensor];\n    }\n};\n\nLineRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n    \n    const sensory = this.sensory;\n    switch(dev) {\n        case 'TILT_FORWARD': return sensory.tilt == 1;\n        case 'TILT_BACKWARD': return sensory.tilt == -1;\n        case 'TILT_LEFT': return sensory.tilt == 2;\n        case 'TILT_RIGHT': return sensory.tilt == -2;\n        case 'TILT_FLIP': return sensory.tilt == 3;\n        case 'TILT_NOT': return sensory.tilt == -3;\n        case 'FREE_FALL': return this.freeFall;\n        case 'TAP': return this.tap;\n        case 'BATTERY_NORMAL': return sensory.batteryState === 2;\n        case 'BATTERY_LOW': return sensory.batteryState === 1;\n        case 'BATTERY_EMPTY': return sensory.batteryState === 0;\n    }\n    return false;\n};\n\nLineRobot.prototype.__TOUCHING_COLORS = {\n    RED: 1,\n    ORANGE: 7,\n    YELLOW: 2,\n    GREEN: 3,\n    SKY_BLUE: 4,\n    BLUE: 5,\n    PURPLE: 6,\n    BLACK: 0,\n    WHITE: 8,\n};\n\nLineRobot.prototype.checkTouchingColor = function(script) {\n    this.__setModule();\n    const color = this.__TOUCHING_COLORS[script.getField('COLOR')];\n\n    if(typeof color == 'number') {\n        return this.sensory.colorNumber == color;\n    }\n    return false;\n};\n\nLineRobot.prototype.__PATTERN_COLORS = {\n\tBLACK: 0,\n\tRED: 1,\n\tYELLOW: 2,\n\tGREEN: 3,\n\tSKY_BLUE: 4,\n\tBLUE: 5,\n\tPURPLE: 6\n};\n\nLineRobot.prototype.checkColorPattern = function(script) {\n    this.__setModule();\n    const color1 = this.__TOUCHING_COLORS[script.getField('COLOR1')];\n    const color2 = this.__TOUCHING_COLORS[script.getField('COLOR2')];\n\n    if((typeof color1 == 'number') && (typeof color2 == 'number')) {\n        return this.colorPattern == color1 * 10 + color2;\n    }\n    return false;\n};\n\nLineRobot.prototype.checkButtonState = function(script) {\n    this.__setModule();\n    const state = script.getField('STATE');\n    \n    switch(state) {\n        case 'CLICKED': return this.clicked;\n        case 'DOUBLE_CLICKED': return this.doubleClicked;\n        case 'LONG_PRESSED': return this.longPressed;\n    }\n    return false;\n};\n\nLineRobot.prototype.__motionUnit = function(type, unit, value, callback) {\n    const motoring = this.motoring;\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    if (value && value > 0) {\n        this.__setMotion(type, unit, 0, value, 0); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n        this.__setLineTracerMode(0);\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(0);\n        callback();\n    }\n};\n\nLineRobot.prototype.__motionUnitRadius = function(type, unit, value, radius, callback) {\n    const motoring = this.motoring;\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    radius = parseFloat(radius);\n    if (value && value > 0 && typeof radius == 'number' && radius >= 0) {\n        this.__setMotion(type, unit, 0, value, radius); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n        this.__setLineTracerMode(0);\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(0);\n        callback();\n    }\n};\n\nLineRobot.prototype.__UNITS = {\n    CM: 1,\n    DEG: 1,\n    SEC: 2,\n    PULSE: 3,\n};\n\nLineRobot.prototype.moveForwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(2, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(1, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.moveBackwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(1, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(2, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.turnUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (direction == 'LEFT') {\n            if (value < 0) {\n                this.__motionUnit(4, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(3, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (value < 0) {\n                this.__motionUnit(3, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(4, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.pivotUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const wheel = script.getField('WHEEL');\n        const value = script.getNumberValue('VALUE');\n        let unit = script.getField('UNIT');\n        const toward = script.getField('TOWARD');\n\n        unit = this.__UNITS[unit];\n        if (wheel == 'LEFT') {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(6, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(5, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(5, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(6, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(8, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(7, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(7, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(8, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.circleUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        let unit = script.getField('UNIT');\n        const radius = script.getNumberValue('RADIUS');\n        const toward = script.getField('TOWARD');\n\n        unit = this.__UNITS[unit];\n        if (direction == 'LEFT') {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnitRadius(10, unit, -value, radius, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnitRadius(9, unit, value, radius, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnitRadius(9, unit, -value, radius, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnitRadius(10, unit, value, radius, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnitRadius(12, unit, -value, radius, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnitRadius(11, unit, value, radius, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnitRadius(11, unit, -value, radius, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnitRadius(12, unit, value, radius, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.setWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel = leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel = rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.changeWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel =\n            motoring.leftWheel !== undefined ? motoring.leftWheel + leftVelocity : leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel =\n            motoring.rightWheel !== undefined ? motoring.rightWheel + rightVelocity : rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.setWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel = velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel = velocity;\n        } else {\n            motoring.leftWheel = velocity;\n            motoring.rightWheel = velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.changeWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        } else {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.followLine = function(script) {\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(1); // LINE_TRACER_MODE_FOLLOW\n    return script.callReturn();\n};\n\nLineRobot.prototype.followLineUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        let mode = 2; // LINE_TRACER_MODE_UNTIL_ANY\n        switch(script.getField('COLOR')) {\n            case 'RED': mode = 10; break;\n            case 'YELLOW': mode = 11; break;\n            case 'GREEN': mode = 12; break;\n            case 'SKY_BLUE': mode = 13; break;\n            case 'BLUE': mode = 14; break;\n            case 'PURPLE': mode = 15; break;\n        }\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.followLineUntilIntersection = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(9); // LINE_TRACER_MODE_UNTIL_CROSS\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.crossIntersection = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(3); // LINE_TRACER_MODE_MOVE_FORWARD\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.turnAtIntersection = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        let mode = 4; // LINE_TRACER_MODE_TURN_LEFT\n        switch(script.getField('DIRECTION')) {\n            case 'RIGHT': mode = 5; break;\n            case 'BACK': mode = 6; break;\n        }\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.jumpLine = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        let mode = 7; // LINE_TRACER_MODE_JUMP_LEFT\n        if(script.getField('DIRECTION') == 'RIGHT') mode = 8;\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.setLineTracerSpeed = function(script) {\n    this.__setModule();\n    let speed = Number(script.getField('SPEED'));\n\n    speed = parseInt(speed);\n    if (typeof speed == 'number') {\n        this.motoring.lineTracerSpeed = speed;\n    }\n    return script.callReturn();\n};\n\nLineRobot.prototype.stop = function(script) {\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.__RGB_COLORS = {\n    RED: [255, 0, 0],\n    ORANGE: [255, 63, 0],\n    YELLOW: [255, 255, 0],\n    GREEN: [0, 255, 0],\n    SKY_BLUE: [0, 255, 255],\n    BLUE: [0, 0, 255],\n    VIOLET: [63, 0, 255],\n    PURPLE: [255, 0, 255],\n    WHITE: [255, 255, 255],\n};\n\nLineRobot.prototype.setLedColor = function(script) {\n    this.__setModule();\n    const color = script.getField('COLOR');\n\n    const rgb = this.__RGB_COLORS[color];\n    if (rgb) {\n        const motoring = this.motoring;\n        motoring.ledRed = rgb[0];\n        motoring.ledGreen = rgb[1];\n        motoring.ledBlue = rgb[2];\n    }\n    return script.callReturn();\n};\n\nLineRobot.prototype.pickLedColor = function(script) {\n    this.__setModule();\n    const color = script.getField('COLOR');\n\n    const motoring = this.motoring;\n    motoring.ledRed = parseInt(color.slice(1, 3), 16);\n    motoring.ledGreen = parseInt(color.slice(3, 5), 16);\n    motoring.ledBlue = parseInt(color.slice(5, 7), 16);\n    return script.callReturn();\n};\n\nLineRobot.prototype.setLedRgb = function(script) {\n    this.__setModule();\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    const motoring = this.motoring;\n    if (typeof red == 'number') {\n        motoring.ledRed = red;\n    }\n    if (typeof green == 'number') {\n        motoring.ledGreen = green;\n    }\n    if (typeof blue == 'number') {\n        motoring.ledBlue = blue;\n    }\n    return script.callReturn();\n};\n\nLineRobot.prototype.changeLedRgb = function(script) {\n    this.__setModule();\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    const motoring = this.motoring;\n    if (typeof red == 'number') {\n        motoring.ledRed = motoring.ledRed != undefined ? motoring.ledRed + red : red;\n    }\n    if (typeof green == 'number') {\n        motoring.ledGreen = motoring.ledGreen != undefined ? motoring.ledGreen + green : green;\n    }\n    if (typeof blue == 'number') {\n        motoring.ledBlue = motoring.ledBlue != undefined ? motoring.ledBlue + blue : blue;\n    }\n    return script.callReturn();\n};\n\nLineRobot.prototype.clearLed = function(script) {\n    this.__setModule();\n    const motoring = this.motoring;\n    motoring.ledRed = 0;\n    motoring.ledGreen = 0;\n    motoring.ledBlue = 0;\n    return script.callReturn();\n};\n\nLineRobot.prototype.__SOUNDS = {\n    BEEP: 1,\n    RANDOM_BEEP: 2,\n    NOISE: 10,\n    SIREN: 3,\n    ENGINE: 4,\n    CHOP: 11,\n    ROBOT: 5,\n    DIBIDIBIDIP: 8,\n    GOOD_JOB: 9,\n    HAPPY: 12,\n    ANGRY: 13,\n    SAD: 14,\n    SLEEP: 15,\n    MARCH: 6,\n    BIRTHDAY: 7,\n};\n\nLineRobot.prototype.playSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let sound = script.getField('SOUND');\n    let count = script.getNumberValue('COUNT');\n\n    sound = this.__SOUNDS[sound];\n    count = parseInt(count);\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    if (sound && count) {\n        this.__runSound(sound, count);\n    } else {\n        this.__runSound(0);\n    }\n    return script.callReturn();\n};\n\nLineRobot.prototype.playSoundUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.__cancelSound();\n\n        let sound = script.getField('SOUND');\n        let count = script.getNumberValue('COUNT');\n        \n        sound = this.__SOUNDS[sound];\n        count = parseInt(count);\n        this.motoring.buzzer = 0;\n        this.motoring.note = 0;\n        if (sound && count) {\n            this.__runSound(sound, count);\n            this.soundCallback = function() {\n                script.isPlaying = false;\n            };\n        } else {\n            this.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    const motoring = this.motoring;\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.clearSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.__NOTES = {\n    C: 4,\n    'C#': 5,\n    Db: 5,\n    D: 6,\n    'D#': 7,\n    Eb: 7,\n    E: 8,\n    F: 9,\n    'F#': 10,\n    Gb: 10,\n    G: 11,\n    'G#': 12,\n    Ab: 12,\n    A: 13,\n    'A#': 14,\n    Bb: 14,\n    B: 15,\n    '4': 4,\n    '5': 5,\n    '6': 6,\n    '7': 7,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n    '11': 11,\n    '12': 12,\n    '13': 13,\n    '14': 14,\n    '15': 15,\n};\n\nLineRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let note = script.getField('NOTE');\n    let octave = script.getNumberField('OCTAVE');\n\n    note = parseInt(this.__NOTES[note]);\n    octave = parseInt(octave);\n    const motoring = this.motoring;\n    motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        motoring.note = note + (octave - 1) * 12;\n    } else {\n        motoring.note = 0;\n    }\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nLineRobot.prototype.playNoteBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n\n        const motoring = self.motoring;\n        let note = script.getField('NOTE');\n        let octave = script.getNumberField('OCTAVE');\n        let beat = script.getNumberValue('BEAT');\n\n        note = parseInt(this.__NOTES[note]);\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            motoring.note = note;\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        motoring.note = 0;\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    motoring.note = 0;\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n            self.__runSound(0);\n        } else {\n            motoring.note = 0;\n            self.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.motoring.note = 0;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.restBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n        let beat = script.getNumberValue('BEAT');\n\n        const motoring = self.motoring;\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        motoring.note = 0;\n        self.__runSound(0);\n        if (beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nLineRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nLineRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\n/**ZeroneRobot**/\nfunction ZeroneRobot(index) {\n    this.sensory = {\n        signalStrength: 0,\n        leftProximity: 0,\n        rightProximity: 0,\n        frontProximity: 0,\n        rearProximity: 0,\n        colorRed: 0,\n        colorGreen: 0,\n        colorBlue: 0,\n        floor: 0,\n        button: 0,\n        gesture: -1,\n        colorNumber: -1,\n        colorPattern: -1,\n        pulseCount: 0,\n        batteryState: 2,\n    };\n    this.motoring = {\n        group: 'zerone',\n        module: 'zerone',\n        index,\n    };\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.lineTracerModeId = 0;\n    this.motionId = 0;\n    this.clickedId = -1;\n    this.doubleClickedId = -1;\n    this.longPressedId = -1;\n    this.gestureId = -1;\n    this.colorPatternId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.lineTracerStateId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.lineTracerCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.gesture = -1;\n    this.colorPattern = -1;\n    this.tempo = 60;\n    this.timeouts = [];\n}\n\nZeroneRobot.prototype.__PORT_MAP = {\n    group: 'zerone',\n    module: 'zerone',\n    leftWheel: 0,\n    rightWheel: 0,\n    leftHeadRgb: '0,0,0',\n    leftHeadRed: 0,\n    leftHeadGreen: 0,\n    leftHeadBlue: 0,\n    rightHeadRgb: '0,0,0',\n    rightHeadRed: 0,\n    rightHeadGreen: 0,\n    rightHeadBlue: 0,\n    leftTailRgb: '0,0,0',\n    leftTailRed: 0,\n    leftTailGreen: 0,\n    leftTailBlue: 0,\n    rightTailRgb: '0,0,0',\n    rightTailRed: 0,\n    rightTailGreen: 0,\n    rightTailBlue: 0,\n    buzzer: 0,\n    pulse: 0,\n    pulseId: 0,\n    note: 0,\n    sound: 0,\n    soundRepeat: 1,\n    soundId: 0,\n    lineTracerMode: 0,\n    lineTracerModeId: 0,\n    lineTracerSpeed: 4,\n    motionId: 0,\n    motionType: 0,\n    motionUnit: 0,\n    motionSpeed: 0,\n    motionValue: 0,\n    motionRadius: 0,\n};\n\nZeroneRobot.prototype.setZero = function() {\n    const portMap = this.__PORT_MAP;\n    const motoring = this.motoring;\n    for (const port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.lineTracerModeId = 0;\n    this.motionId = 0;\n    this.clickedId = -1;\n    this.doubleClickedId = -1;\n    this.longPressedId = -1;\n    this.gestureId = -1;\n    this.colorPatternId = -1;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.lineTracerStateId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.lineTracerCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.gesture = -1;\n    this.colorPattern = -1;\n    this.tempo = 60;\n    \n    this.__removeAllTimeouts();\n};\n\nZeroneRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nZeroneRobot.prototype.afterSend = function(sq) {\n    this.clicked = false;\n    this.doubleClicked = false;\n    this.longPressed = false;\n    this.gesture = -1;\n    this.colorPattern = -1;\n};\n\nZeroneRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nZeroneRobot.prototype.__setModule = function() {\n    this.motoring.group = 'zerone';\n    this.motoring.module = 'zerone';\n};\n\nZeroneRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    const idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nZeroneRobot.prototype.__removeAllTimeouts = function() {\n    const timeouts = this.timeouts;\n    for (const i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nZeroneRobot.prototype.__setPulse = function(pulse) {\n    this.pulseId = (this.pulseId % 255) + 1;\n    this.motoring.pulse = pulse;\n    this.motoring.pulseId = this.pulseId;\n};\n\nZeroneRobot.prototype.__setLineTracerMode = function(mode) {\n    this.lineTracerModeId = (this.lineTracerModeId % 255) + 1;\n    this.motoring.lineTracerMode = mode;\n    this.motoring.lineTracerModeId = this.lineTracerModeId;\n};\n\nZeroneRobot.prototype.__cancelLineTracer = function() {\n    this.lineTracerCallback = undefined;\n};\n\nZeroneRobot.prototype.__setMotion = function(type, unit, speed, value, radius) {\n    this.motionId = (this.motionId % 255) + 1;\n    const motoring = this.motoring;\n    motoring.motionType = type;\n    motoring.motionUnit = unit;\n    motoring.motionSpeed = speed;\n    motoring.motionValue = value;\n    motoring.motionRadius = radius;\n    motoring.motionId = this.motionId;\n};\n\nZeroneRobot.prototype.__cancelMotion = function() {\n    this.motionCallback = undefined;\n};\n\nZeroneRobot.prototype.__runSound = function(sound, count) {\n    if(typeof count != 'number') count = 1;\n    if(count < 0) count = -1;\n    if(count) {\n        this.soundId = (this.soundId % 255) + 1;\n        const motoring = this.motoring;\n        motoring.sound = sound;\n        motoring.soundRepeat = count;\n        motoring.soundId = this.soundId;\n    }\n};\n\nZeroneRobot.prototype.__cancelSound = function() {\n    this.soundCallback = undefined;\n};\n\nZeroneRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nZeroneRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nZeroneRobot.prototype.handleSensory = function() {\n    const self = this;\n    const sensory = self.sensory;\n    \n    self.clicked = sensory.clicked == 1;\n    self.doubleClicked = sensory.doubleClicked == 1;\n    self.longPressed = sensory.longPressed == 1;\n    self.gesture = sensory.gesture;\n    self.colorPattern = sensory.colorPattern;\n    \n    if(self.lineTracerCallback) {\n        if(sensory.lineTracerStateId != self.lineTracerStateId) {\n            self.lineTracerStateId = sensory.lineTracerStateId;\n            if(sensory.lineTracerState == 0x02) {\n                self.__setLineTracerMode(0);\n                var callback = self.lineTracerCallback;\n                self.__cancelLineTracer();\n                if(callback) callback();\n            }\n        }\n    }\n    if(self.motionCallback) {\n        if(sensory.wheelStateId != self.wheelStateId) {\n            self.wheelStateId = sensory.wheelStateId;\n            if(sensory.wheelState == 0) {\n                self.motoring.leftWheel = 0;\n                self.motoring.rightWheel = 0;\n                var callback = self.motionCallback;\n                self.__cancelMotion();\n                if(callback) callback();\n            }\n        }\n    }\n    if(self.soundCallback) {\n        if(sensory.soundStateId != self.soundStateId) {\n            self.soundStateId = sensory.soundStateId;\n            if(sensory.soundState == 0) {\n                var callback = self.soundCallback;\n                self.__cancelSound();\n                if(callback) callback();\n            }\n        }\n    }\n};\n\nZeroneRobot.prototype.checkGesture = function(script) {\n    this.__setModule();\n    const gesture = script.getField('GESTURE');\n    \n    switch(gesture) {\n        case 'FORWARD': return this.gesture == 0;\n        case 'BACKWARD': return this.gesture == 1;\n        case 'LEFTWARD': return this.gesture == 2;\n        case 'RIGHTWARD': return this.gesture == 3;\n        case 'NEAR': return this.gesture == 4;\n        case 'FAR': return this.gesture == 5;\n        case 'LONG_TOUCH': return this.gesture == 6;\n    }\n    return false;\n};\n\nZeroneRobot.prototype.__TOUCHING_COLORS = {\n    RED: 1,\n    ORANGE: 7,\n    YELLOW: 2,\n    GREEN: 3,\n    SKY_BLUE: 4,\n    BLUE: 5,\n    PURPLE: 6,\n    BLACK: 0,\n    WHITE: 8,\n};\n\nZeroneRobot.prototype.checkTouchingColor = function(script) {\n    this.__setModule();\n    const color = this.__TOUCHING_COLORS[script.getField('COLOR')];\n\n    if(typeof color == 'number') {\n        return this.sensory.colorNumber == color;\n    }\n    return false;\n};\n\nZeroneRobot.prototype.__PATTERN_COLORS = {\n\tBLACK: 0,\n\tRED: 1,\n\tYELLOW: 2,\n\tGREEN: 3,\n\tSKY_BLUE: 4,\n\tBLUE: 5,\n\tPURPLE: 6\n};\n\nZeroneRobot.prototype.checkColorPattern = function(script) {\n    this.__setModule();\n    const color1 = this.__TOUCHING_COLORS[script.getField('COLOR1')];\n    const color2 = this.__TOUCHING_COLORS[script.getField('COLOR2')];\n\n    if((typeof color1 == 'number') && (typeof color2 == 'number')) {\n        return this.colorPattern == color1 * 10 + color2;\n    }\n    return false;\n};\n\nZeroneRobot.prototype.checkButtonState = function(script) {\n    this.__setModule();\n    const state = script.getField('STATE');\n    \n    switch(state) {\n        case 'CLICKED': return this.clicked;\n        case 'DOUBLE_CLICKED': return this.doubleClicked;\n        case 'LONG_PRESSED': return this.longPressed;\n    }\n    return false;\n};\n\nZeroneRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    const state = script.getField('STATE');\n    \n    switch (state) {\n        case 'BATTERY_NORMAL': return this.sensory.batteryState === 2;\n        case 'BATTERY_LOW': return this.sensory.batteryState === 1;\n        case 'BATTERY_EMPTY': return this.sensory.batteryState === 0;\n    }\n    return false;\n};\n\nZeroneRobot.prototype.__SENSORS = {\n    SIGNAL_STRENGTH: 'signalStrength',\n    LEFT_PROXIMITY: 'leftProximity',\n    RIGHT_PROXIMITY: 'rightProximity',\n    FRONT_PROXIMITY: 'frontProximity',\n    REAR_PROXIMITY: 'rearProximity',\n    COLOR_R: 'colorRed',\n    COLOR_G: 'colorGreen',\n    COLOR_B: 'colorBlue',\n    FLOOR: 'floor',\n    BUTTON: 'button',\n    COLOR_NUMBER: 'colorNumber',\n};\n\nZeroneRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n    \n    if(dev == 'GESTURE') {\n        return this.gesture;\n    } else if(dev == 'COLOR_PATTERN') {\n        return this.colorPattern;\n    } else {\n        const sensor = this.__SENSORS[dev] || dev;\n        return this.sensory[sensor];\n    }\n};\n\nZeroneRobot.prototype.__motionUnit = function(type, unit, value, callback) {\n    const motoring = this.motoring;\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    if (value && value > 0) {\n        this.__setMotion(type, unit, 0, value, 0); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n        this.__setLineTracerMode(0);\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(0);\n        callback();\n    }\n};\n\nZeroneRobot.prototype.__UNITS = {\n    CM: 1,\n    DEG: 1,\n    SEC: 2,\n    PULSE: 3,\n};\n\nZeroneRobot.prototype.moveForwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(2, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(1, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.moveBackwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(1, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(2, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.turnUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (direction == 'LEFT') {\n            if (value < 0) {\n                this.__motionUnit(4, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(3, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (value < 0) {\n                this.__motionUnit(3, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(4, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.changeWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel =\n            motoring.leftWheel !== undefined ? motoring.leftWheel + leftVelocity : leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel =\n            motoring.rightWheel !== undefined ? motoring.rightWheel + rightVelocity : rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.setWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel = leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel = rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.changeWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        } else {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.setWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel = velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel = velocity;\n        } else {\n            motoring.leftWheel = velocity;\n            motoring.rightWheel = velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.followLine = function(script) {\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(1); // LINE_TRACER_MODE_FOLLOW\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.followLineUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        let mode = 2; // LINE_TRACER_MODE_UNTIL_ANY\n        switch(script.getField('COLOR')) {\n            case 'RED': mode = 10; break;\n            case 'YELLOW': mode = 11; break;\n            case 'GREEN': mode = 12; break;\n            case 'SKY_BLUE': mode = 13; break;\n            case 'BLUE': mode = 14; break;\n            case 'PURPLE': mode = 15; break;\n        }\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.followLineUntilIntersection = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(9); // LINE_TRACER_MODE_UNTIL_CROSS\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.crossIntersection = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(3); // LINE_TRACER_MODE_MOVE_FORWARD\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.turnAtIntersection = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        let mode = 4; // LINE_TRACER_MODE_TURN_LEFT\n        switch(script.getField('DIRECTION')) {\n            case 'RIGHT': mode = 5; break;\n            case 'BACK': mode = 6; break;\n        }\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.jumpLine = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelMotion();\n\n        let mode = 7; // LINE_TRACER_MODE_JUMP_LEFT\n        if(script.getField('DIRECTION') == 'RIGHT') mode = 8;\n\n        const motoring = this.motoring;\n        motoring.leftWheel = 0;\n        motoring.rightWheel = 0;\n        this.__setPulse(0);\n        this.__setMotion(0, 0, 0, 0, 0);\n        this.__setLineTracerMode(mode);\n        this.lineTracerCallback = function() {\n            script.isMoving = false;\n        };\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.setLineTracerSpeed = function(script) {\n    this.__setModule();\n    let speed = Number(script.getField('SPEED'));\n\n    speed = parseInt(speed);\n    if (typeof speed == 'number') {\n        this.motoring.lineTracerSpeed = speed;\n    }\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.stop = function(script) {\n    this.__setModule();\n    this.__cancelLineTracer();\n    this.__cancelMotion();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    this.__setLineTracerMode(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.__setRgb = function(led, red, green, blue) {\n    const motoring = this.motoring;\n    \n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if(led == 'LEFT_HEAD' || led == 'LEFT' || led == 'HEAD' || led == 'ALL') {\n        if(typeof red == 'number') {\n            motoring.leftHeadRed = red;\n        }\n        if(typeof green == 'number') {\n            motoring.leftHeadGreen = green;\n        }\n        if(typeof blue == 'number') {\n            motoring.leftHeadBlue = blue;\n        }\n        motoring.leftHeadRgb = `${motoring.leftHeadRed},${motoring.leftHeadGreen},${motoring.leftHeadBlue}`;\n    }\n    if(led == 'RIGHT_HEAD' || led == 'RIGHT' || led == 'HEAD' || led == 'ALL') {\n        if(typeof red == 'number') {\n            motoring.rightHeadRed = red;\n        }\n        if(typeof green == 'number') {\n            motoring.rightHeadGreen = green;\n        }\n        if(typeof blue == 'number') {\n            motoring.rightHeadBlue = blue;\n        }\n        motoring.rightHeadRgb = `${motoring.rightHeadRed},${motoring.rightHeadGreen},${motoring.rightHeadBlue}`;\n    }\n    if(led == 'LEFT_TAIL' || led == 'LEFT' || led == 'TAIL' || led == 'ALL') {\n        if(typeof red == 'number') {\n            motoring.leftTailRed = red;\n        }\n        if(typeof green == 'number') {\n            motoring.leftTailGreen = green;\n        }\n        if(typeof blue == 'number') {\n            motoring.leftTailBlue = blue;\n        }\n        motoring.leftTailRgb = `${motoring.leftTailRed},${motoring.leftTailGreen},${motoring.leftTailBlue}`;\n    }\n    if(led == 'RIGHT_TAIL' || led == 'RIGHT' || led == 'TAIL' || led == 'ALL') {\n        if(typeof red == 'number') {\n            motoring.rightTailRed = red;\n        }\n        if(typeof green == 'number') {\n            motoring.rightTailGreen = green;\n        }\n        if(typeof blue == 'number') {\n            motoring.rightTailBlue = blue;\n        }\n        motoring.rightTailRgb = `${motoring.rightTailRed},${motoring.rightTailGreen},${motoring.rightTailBlue}`;\n    }\n};\n\nZeroneRobot.prototype.__changeRgb = function(led, red, green, blue) {\n    const motoring = this.motoring;\n    \n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if(led == 'LEFT_HEAD' || led == 'LEFT' || led == 'HEAD' || led == 'ALL') {\n        if(typeof red == 'number') {\n            motoring.leftHeadRed += red;\n        }\n        if(typeof green == 'number') {\n            motoring.leftHeadGreen += green;\n        }\n        if(typeof blue == 'number') {\n            motoring.leftHeadBlue += blue;\n        }\n        motoring.leftHeadRgb = `${motoring.leftHeadRed},${motoring.leftHeadGreen},${motoring.leftHeadBlue}`;\n    }\n    if(led == 'RIGHT_HEAD' || led == 'RIGHT' || led == 'HEAD' || led == 'ALL') {\n        if(typeof red == 'number') {\n            motoring.rightHeadRed += red;\n        }\n        if(typeof green == 'number') {\n            motoring.rightHeadGreen += green;\n        }\n        if(typeof blue == 'number') {\n            motoring.rightHeadBlue += blue;\n        }\n        motoring.rightHeadRgb = `${motoring.rightHeadRed},${motoring.rightHeadGreen},${motoring.rightHeadBlue}`;\n    }\n    if(led == 'LEFT_TAIL' || led == 'LEFT' || led == 'TAIL' || led == 'ALL') {\n        if(typeof red == 'number') {\n            motoring.leftTailRed += red;\n        }\n        if(typeof green == 'number') {\n            motoring.leftTailGreen += green;\n        }\n        if(typeof blue == 'number') {\n            motoring.leftTailBlue += blue;\n        }\n        motoring.leftTailRgb = `${motoring.leftTailRed},${motoring.leftTailGreen},${motoring.leftTailBlue}`;\n    }\n    if(led == 'RIGHT_TAIL' || led == 'RIGHT' || led == 'TAIL' || led == 'ALL') {\n        if(typeof red == 'number') {\n            motoring.rightTailRed += red;\n        }\n        if(typeof green == 'number') {\n            motoring.rightTailGreen += green;\n        }\n        if(typeof blue == 'number') {\n            motoring.rightTailBlue += blue;\n        }\n        motoring.rightTailRgb = `${motoring.rightTailRed},${motoring.rightTailGreen},${motoring.rightTailBlue}`;\n    }\n};\n\nZeroneRobot.prototype.__RGB_COLORS = {\n    RED: [255, 0, 0],\n    ORANGE: [255, 63, 0],\n    YELLOW: [255, 255, 0],\n    GREEN: [0, 255, 0],\n    SKY_BLUE: [0, 255, 255],\n    BLUE: [0, 0, 255],\n    VIOLET: [63, 0, 255],\n    PURPLE: [255, 0, 255],\n    WHITE: [255, 255, 255],\n};\n\nZeroneRobot.prototype.setLed = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    const color = script.getField('COLOR');\n\n    const rgb = this.__RGB_COLORS[color];\n    if (rgb) {\n        this.__setRgb(led, rgb[0], rgb[1], rgb[2]);\n    }\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.pickLed = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    const color = script.getField('COLOR');\n\n    const red = parseInt(color.slice(1, 3), 16);\n    const green = parseInt(color.slice(3, 5), 16);\n    const blue = parseInt(color.slice(5, 7), 16);\n\n    this.__setRgb(led, red, green, blue);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.clearLed = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    \n    this.__setRgb(led, 0, 0, 0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.changeRgb = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    const red = script.getNumberValue('RED');\n    const green = script.getNumberValue('GREEN');\n    const blue = script.getNumberValue('BLUE');\n    \n    this.__changeRgb(led, red, green, blue);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.setRgb = function(script) {\n    this.__setModule();\n    const led = script.getField('LED');\n    const red = script.getNumberValue('RED');\n    const green = script.getNumberValue('GREEN');\n    const blue = script.getNumberValue('BLUE');\n    \n    this.__setRgb(led, red, green, blue);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.__SOUNDS = {\n    BEEP: 1,\n    RANDOM_BEEP: 2,\n    NOISE: 10,\n    SIREN: 3,\n    ENGINE: 4,\n    CHOP: 11,\n    ROBOT: 5,\n    DIBIDIBIDIP: 8,\n    GOOD_JOB: 9,\n    HAPPY: 12,\n    ANGRY: 13,\n    SAD: 14,\n    SLEEP: 15,\n    MARCH: 6,\n    BIRTHDAY: 7,\n};\n\nZeroneRobot.prototype.playSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let sound = script.getField('SOUND');\n    let count = script.getNumberValue('COUNT');\n\n    sound = this.__SOUNDS[sound];\n    count = parseInt(count);\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    if (sound && count) {\n        this.__runSound(sound, count);\n    } else {\n        this.__runSound(0);\n    }\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.playSoundUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.__cancelSound();\n\n        let sound = script.getField('SOUND');\n        let count = script.getNumberValue('COUNT');\n        \n        sound = this.__SOUNDS[sound];\n        count = parseInt(count);\n        this.motoring.buzzer = 0;\n        this.motoring.note = 0;\n        if (sound && count) {\n            this.__runSound(sound, count);\n            this.soundCallback = function() {\n                script.isPlaying = false;\n            };\n        } else {\n            this.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    const motoring = this.motoring;\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.clearSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.__NOTES = {\n    C: 4,\n    'C#': 5,\n    Db: 5,\n    D: 6,\n    'D#': 7,\n    Eb: 7,\n    E: 8,\n    F: 9,\n    'F#': 10,\n    Gb: 10,\n    G: 11,\n    'G#': 12,\n    Ab: 12,\n    A: 13,\n    'A#': 14,\n    Bb: 14,\n    B: 15,\n    '4': 4,\n    '5': 5,\n    '6': 6,\n    '7': 7,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n    '11': 11,\n    '12': 12,\n    '13': 13,\n    '14': 14,\n    '15': 15,\n};\n\nZeroneRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let note = script.getField('NOTE');\n    let octave = script.getNumberField('OCTAVE');\n\n    note = parseInt(this.__NOTES[note]);\n    octave = parseInt(octave);\n    const motoring = this.motoring;\n    motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        motoring.note = note + (octave - 1) * 12;\n    } else {\n        motoring.note = 0;\n    }\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.playNoteBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n\n        const motoring = self.motoring;\n        let note = script.getField('NOTE');\n        let octave = script.getNumberField('OCTAVE');\n        let beat = script.getNumberValue('BEAT');\n\n        note = parseInt(this.__NOTES[note]);\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            motoring.note = note;\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        motoring.note = 0;\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    motoring.note = 0;\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n            self.__runSound(0);\n        } else {\n            motoring.note = 0;\n            self.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.motoring.note = 0;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.restBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n        let beat = script.getNumberValue('BEAT');\n\n        const motoring = self.motoring;\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        motoring.note = 0;\n        self.__runSound(0);\n        if (beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nZeroneRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nZeroneRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\n/**CheeseRobot Lib**/\nconst CHEESE_HAT_SHAPES = {\n    'SQUARE': [0xf8, 0x88, 0x88, 0x88, 0xf8], //1111 1/1000 1/1000 1/1000 1/1111 1\n    'TRIANGLE': [0x00, 0x20, 0x50, 0xf8, 0x00], //0000 0/0010 0/0101 0/1111 1/0000 0\n    'DIAMOND': [0x20, 0x50, 0x88, 0x50, 0x20], //0010 0/0101 0/1000 1/0101 0/0010 0\n    'CIRCLE': [0x70, 0x88, 0x88, 0x88, 0x70], //0111 0/1000 1/1000 1/1000 1/0111 0\n    'X': [0x88, 0x50, 0x20, 0x50, 0x88], //1000 1/0101 0/0010 0/0101 0/1000 1\n    'LIKE': [0x50, 0x50, 0x00, 0x88, 0x70], //0101 0/0101 0/0000 0/1000 1/0111 0\n    'DISLIKE': [0x50, 0x50, 0x00, 0x70, 0x88], //0101 0/0101 0/0000 0/0111 0/1000 1\n    'ANGRY': [0x88, 0x50, 0x00, 0xf8, 0x88], //1000 1/0101 0/0000 0/1111 1/1000 1\n    'OPEN_MOUTH': [0x50, 0x00, 0x70, 0x88, 0x70], //0101 0/0000 0/0111 0/1000 1/0111 0\n    'CLOSE_MOUTH': [0x50, 0x00, 0x00, 0xf8, 0x00], //0101 0/0000 0/0000 0/1111 1/0000 0\n    'WALK1': [0x20, 0x30, 0x60, 0x20, 0x50], //0010 0/0011 0/0110 0/0010 0/0101 0\n    'WALK2': [0x20, 0x60, 0x30, 0x20, 0x20], //0010 0/0110 0/0011 0/0010 0/0010 0\n    'HEART': [0x50, 0xf8, 0xf8, 0x70, 0x20], //0101 0/1111 1/1111 1/0111 0/0010 0\n    'STAR': [0x20, 0xf8, 0x70, 0x70, 0x88], //0010 0/1111 1/0111 0/0111 0/1000 1\n    'AIRPLANE': [0x20, 0xb0, 0xc8, 0xb0, 0x20], //0010 0/1011 0/1100 1/1011 0/0010 0\n    'PUPPY': [0x30, 0x38, 0xf0, 0x70, 0x50], //0011 0/0011 1/1111 0/0111 0/0101 0\n    'BUTTERFLY': [0x88, 0xd8, 0xa8, 0xd8, 0x88], //1000 1/1101 1/1010 1/1101 1/1000 1\n    'QUARTER_NOTE': [0x10, 0x10, 0x10, 0x70, 0x70], //0001 0/0001 0/0001 0/0111 0/0111 0\n    'EIGHTH_NOTE': [0x20, 0x30, 0x28, 0xe0, 0xe0], //0010 0/0011 0/0010 1/1110 0/1110 0\n    'LEFT_ARROW': [0x20, 0x40, 0xf8, 0x40, 0x20], //0010 0/0100 0/1111 1/0100 0/0010 0\n    'RIGHT_ARROW': [0x20, 0x10, 0xf8, 0x10, 0x20], //0010 0/0001 0/1111 1/0001 0/0010 0\n    'UP_ARROW': [0x20, 0x70, 0xa8, 0x20, 0x20], //0010 0/0111 0/1010 1/0010 0/0010 0\n    'DOWN_ARRAY': [0x20, 0x20, 0xa8, 0x70, 0x20] //0010 0/0010 0/1010 1/0111 0/0010 0\n};\n\nconst CHEESE_HAT_ALPHABETS = {\n    'a': { width: 5, data: [0x00, 0x70, 0x90, 0x90, 0x70] }, //0000 0/0111 0/1001 0/1001 0/0111 0\n    'b': { width: 5, data: [0x80, 0xe0, 0x90, 0x90, 0xe0] }, //1000 0/1110 0/1001 0/1001 0/1110 0\n    'c': { width: 5, data: [0x00, 0x70, 0x80, 0x80, 0x70] }, //0000 0/0111 0/1000 0/1000 0/0111 0\n    'd': { width: 5, data: [0x10, 0x70, 0x90, 0x90, 0x70] }, //0001 0/0111 0/1001 0/1001 0/0111 0\n    'e': { width: 5, data: [0x00, 0x70, 0xf0, 0x80, 0x70] }, //0000 0/0111 0/1111 0/1000 0/0111 0\n    'f': { width: 5, data: [0x30, 0x40, 0xf0, 0x40, 0x40] }, //0011 0/0100 0/1111 0/0100 0/0100 0\n    'g': { width: 5, data: [0x70, 0x90, 0x70, 0x10, 0xe0] }, //0111 0/1001 0/0111 0/0001 0/1110 0\n    'h': { width: 5, data: [0x80, 0x80, 0xe0, 0x90, 0x90] }, //1000 0/1000 0/1110 0/1001 0/1001 0\n    'i': { width: 2, data: [0x80, 0x00, 0x80, 0x80, 0x80] }, //10/00/10/10/10\n    'j': { width: 4, data: [0x20, 0x00, 0x20, 0xa0, 0x40] }, //0010/0000/0010/1010/0100\n    'k': { width: 4, data: [0x80, 0x80, 0xa0, 0xc0, 0xa0] }, //1000/1000/1010/1100/1010\n    'l': { width: 3, data: [0x80, 0x80, 0x80, 0x80, 0x40] }, //100/100/100/100/010\n    'm': { width: 6, data: [0x00, 0xf0, 0xa8, 0xa8, 0xa8] }, //0000 00/1111 00/1010 10/1010 10/1010 10\n    'n': { width: 5, data: [0x00, 0xe0, 0x90, 0x90, 0x90] }, //0000 0/1110 0/1001 0/1001 0/1001 0\n    'o': { width: 5, data: [0x00, 0x60, 0x90, 0x90, 0x60] }, //0000 0/0110 0/1001 0/1001 0/0110 0\n    'p': { width: 5, data: [0x00, 0xe0, 0x90, 0xe0, 0x80] }, //0000 0/1110 0/1001 0/1110 0/1000 0\n    'q': { width: 5, data: [0x00, 0x70, 0x90, 0x70, 0x10] }, //0000 0/0111 0/1001 0/0111 0/0001 0\n    'r': { width: 4, data: [0x00, 0x60, 0x80, 0x80, 0x80] }, //0000/0110/1000/1000/1000\n    's': { width: 5, data: [0x00, 0x70, 0xc0, 0x30, 0xe0] }, //0000 0/0111 0/1100 0/0011 0/1110 0\n    't': { width: 5, data: [0x40, 0xf0, 0x40, 0x40, 0x30] }, //0100 0/1111 0/0100 0/0100 0/0011 0\n    'u': { width: 5, data: [0x00, 0x90, 0x90, 0x90, 0x70] }, //0000 0/1001 0/1001 0/1001 0/0111 0\n    'v': { width: 6, data: [0x00, 0x88, 0x50, 0x50, 0x20] }, //0000 00/1000 10/0101 00/0101 00/0010 00\n    'w': { width: 6, data: [0x00, 0x88, 0xa8, 0xa8, 0x50] }, //0000 00/1000 10/1010 10/1010 10/0101 00\n    'x': { width: 4, data: [0x00, 0xa0, 0x40, 0x40, 0xa0] }, //0000/1010/0100/0100/1010\n    'y': { width: 5, data: [0x00, 0x90, 0x70, 0x10, 0x60] }, //0000 0/1001 0/0111 0/0001 0/0110 0\n    'z': { width: 5, data: [0x00, 0xf0, 0x20, 0x40, 0xf0] }, //0000 0/1111 0/0010 0/0100 0/1111 0\n    'A': { width: 5, data: [0x60, 0x90, 0xf0, 0x90, 0x90] }, //0110 0/1001 0/1111 0/1001 0/1001 0\n    'B': { width: 5, data: [0xe0, 0x90, 0xe0, 0x90, 0xe0] }, //1110 0/1001 0/1110 0/1001 0/1110 0\n    'C': { width: 5, data: [0x60, 0x90, 0x80, 0x90, 0x60] }, //0110 0/1001 0/1000 0/1001 0/0110 0\n    'D': { width: 5, data: [0xe0, 0x90, 0x90, 0x90, 0xe0] }, //1110 0/1001 0/1001 0/1001 0/1110 0\n    'E': { width: 5, data: [0xf0, 0x80, 0xf0, 0x80, 0xf0] }, //1111 0/1000 0/1111 0/1000 0/1111 0\n    'F': { width: 5, data: [0xf0, 0x80, 0xf0, 0x80, 0x80] }, //1111 0/1000 0/1111 0/1000 0/1000 0\n    'G': { width: 5, data: [0x70, 0x80, 0xb0, 0x90, 0x60] }, //0111 0/1000 0/1011 0/1001 0/0110 0\n    'H': { width: 5, data: [0x90, 0x90, 0xf0, 0x90, 0x90] }, //1001 0/1001 0/1111 0/1001 0/1001 0\n    'I': { width: 4, data: [0xe0, 0x40, 0x40, 0x40, 0xe0] }, //1110/0100/0100/0100/1110\n    'J': { width: 5, data: [0xf0, 0x20, 0x20, 0xa0, 0x40] }, //1111 0/0010 0/0010 0/1010 0/0100 0\n    'K': { width: 5, data: [0x90, 0xa0, 0xc0, 0xa0, 0x90] }, //1001 0/1010 0/1100 0/1010 0/1001 0\n    'L': { width: 5, data: [0x80, 0x80, 0x80, 0x80, 0xf0] }, //1000 0/1000 0/1000 0/1000 0/1111 0\n    'M': { width: 6, data: [0x88, 0xd8, 0xa8, 0x88, 0x88] }, //1000 10/1101 10/1010 10/1000 10/1000 10\n    'N': { width: 6, data: [0x88, 0xc8, 0xa8, 0x98, 0x88] }, //1000 10/1100 10/1010 10/1001 10/1000 10\n    'O': { width: 5, data: [0x60, 0x90, 0x90, 0x90, 0x60] }, //0110 0/1001 0/1001 0/1001 0/0110 0\n    'P': { width: 5, data: [0xe0, 0x90, 0xe0, 0x80, 0x80] }, //1110 0/1001 0/1110 0/1000 0/1000 0\n    'Q': { width: 5, data: [0x60, 0x90, 0x90, 0xa0, 0x50] }, //0110 0/1001 0/1001 0/1010 0/0101 0\n    'R': { width: 5, data: [0xe0, 0x90, 0xe0, 0x90, 0x90] }, //1110 0/1001 0/1110 0/1001 0/1001 0\n    'S': { width: 5, data: [0x70, 0x80, 0x60, 0x10, 0xe0] }, //0111 0/1000 0/0110 0/0001 0/1110 0\n    'T': { width: 6, data: [0xf8, 0x20, 0x20, 0x20, 0x20] }, //1111 10/0010 00/0010 00/0010 00/0010 00\n    'U': { width: 5, data: [0x90, 0x90, 0x90, 0x90, 0x60] }, //1001 0/1001 0/1001 0/1001 0/0110 0\n    'V': { width: 6, data: [0x88, 0x88, 0x50, 0x50, 0x20] }, //1000 10/1000 10/0101 00/0101 00/0010 00\n    'W': { width: 6, data: [0x88, 0xa8, 0xa8, 0xa8, 0x50] }, //1000 10/1010 10/1010 10/1010 10/0101 00\n    'X': { width: 5, data: [0x90, 0x90, 0x60, 0x90, 0x90] }, //1001 0/1001 0/0110 0/1001 0/1001 0\n    'Y': { width: 6, data: [0x88, 0x50, 0x20, 0x20, 0x20] }, //1000 10/0101 00/0010 00/0010 00/0010 00\n    'Z': { width: 5, data: [0xf0, 0x10, 0x60, 0x80, 0xf0] }, //1111 0/0001 0/0110 0/1000 0/1111 0\n    '1': { width: 4, data: [0x40, 0xc0, 0x40, 0x40, 0xe0] }, //0100/1100/0100/0100/1110\n    '2': { width: 5, data: [0x60, 0x90, 0x20, 0x40, 0xf0] }, //0110 0/1001 0/0010 0/0100 0/1111 0\n    '3': { width: 5, data: [0x60, 0x90, 0x20, 0x90, 0x60] }, //0110 0/1001 0/0010 0/1001 0/0110 0\n    '4': { width: 5, data: [0x20, 0x60, 0xa0, 0xf0, 0x20] }, //0010 0/0110 0/1010 0/1111 0/0010 0\n    '5': { width: 5, data: [0xf0, 0x80, 0xe0, 0x10, 0xe0] }, //1111 0/1000 0/1110 0/0001 0/1110 0\n    '6': { width: 5, data: [0x60, 0x80, 0xe0, 0x90, 0x60] }, //0110 0/1000 0/1110 0/1001 0/0110 0\n    '7': { width: 5, data: [0xf0, 0x10, 0x20, 0x40, 0x80] }, //1111 0/0001 0/0010 0/0100 0/1000 0\n    '8': { width: 5, data: [0x60, 0x90, 0x60, 0x90, 0x60] }, //0110 0/1001 0/0110 0/1001 0/0110 0\n    '9': { width: 5, data: [0x60, 0x90, 0x70, 0x10, 0x60] }, //0110 0/1001 0/0111 0/0001 0/0110 0\n    '0': { width: 5, data: [0x60, 0x90, 0x90, 0x90, 0x60] }, //0110 0/1001 0/1001 0/1001 0/0110 0\n    '`': { width: 3, data: [0x80, 0x40] }, //100/010/000/000/000\n    '~': { width: 6, data: [0x00, 0x40, 0xa8, 0x10] }, //0000 00/0100 00/1010 10/0001 00/0000 00\n    '!': { width: 2, data: [0x80, 0x80, 0x80, 0x00, 0x80] }, //10/10/10/00/10\n    '@': { width: 5, data: [0x00, 0x60, 0x90, 0xb0, 0xb0] }, //0000 0/0110 0/1001 0/1011 0/1011 0\n    '#': { width: 6, data: [0x50, 0xf8, 0x50, 0xf8, 0x50] }, //0101 00/1111 10/0101 00/1111 10/0101 00\n    '$': { width: 6, data: [0x70, 0xa0, 0x70, 0x28, 0x70] }, //0111 00/1010 00/0111 00/0010 10/0111 00\n    '%': { width: 5, data: [0x00, 0x90, 0x20, 0x40, 0x90] }, //0000 0/1001 0/0010 0/0100 0/1001 0\n    '^': { width: 4, data: [0x40, 0xa0] }, //0100/1010/0000/0000/0000\n    '&': { width: 5, data: [0x60, 0x90, 0x60, 0xb0, 0x50] }, //0110 0/1001 0/0110 0/1011 0/0101 0\n    '*': { width: 4, data: [0x00, 0xa0, 0x40, 0xa0] }, //0000/1010/0100/1010/0000\n    '(': { width: 3, data: [0x40, 0x80, 0x80, 0x80, 0x40] }, //010/100/100/100/010\n    ')': { width: 3, data: [0x80, 0x40, 0x40, 0x40, 0x80] }, //100/010/010/010/100\n    '_': { width: 5, data: [0x00, 0x00, 0x00, 0x00, 0xf0] }, //0000 0/0000 0/0000 0/0000 0/1111 0\n    '-': { width: 4, data: [0x00, 0x00, 0xe0] }, //0000/0000/1110/0000/0000\n    '+': { width: 4, data: [0x00, 0x40, 0xe0, 0x40] }, //0000/0100/1110/0100/0000\n    '|': { width: 2, data: [0x80, 0x80, 0x80, 0x80, 0x80] }, //10/10/10/10/10\n    '=': { width: 4, data: [0x00, 0xe0, 0x00, 0xe0] }, //0000/1110/0000/1110/0000\n    '\\\\': { width: 5, data: [0x00, 0x80, 0x40, 0x20, 0x10] }, //0000 0/1000 0/0100 0/0010 0/0001 0\n    '{': { width: 4, data: [0x60, 0x40, 0xc0, 0x40, 0x60] }, //0110/0100/1100/0100/0110\n    '}': { width: 4, data: [0xc0, 0x40, 0x60, 0x40, 0xc0] }, //1100/0100/0110/0100/1100\n    '[': { width: 3, data: [0xc0, 0x80, 0x80, 0x80, 0xc0] }, //110/100/100/100/110\n    ']': { width: 3, data: [0xc0, 0x40, 0x40, 0x40, 0xc0] }, //110/010/010/010/110\n    ':': { width: 2, data: [0x00, 0x80, 0x00, 0x80] }, //00/10/00/10/00\n    ';': { width: 3, data: [0x00, 0x40, 0x00, 0x40, 0x80] }, //000/010/000/010/100\n    '\"': { width: 4, data: [0xa0, 0xa0] }, //1010/1010/0000/0000/0000\n    '\\'': { width: 2, data: [0x80, 0x80] }, //10/10/00/00/00\n    '<': { width: 4, data: [0x20, 0x40, 0x80, 0x40, 0x20] }, //0010/0100/1000/0100/0010\n    '>': { width: 4, data: [0x80, 0x40, 0x20, 0x40, 0x80] }, //1000/0100/0010/0100/1000\n    '?': { width: 5, data: [0x60, 0x90, 0x20, 0x00, 0x20] }, //0110 0/1001 0/0010 0/0000 0/0010 0\n    ',': { width: 3, data: [0x00, 0x00, 0x00, 0x40, 0x80] }, //000/000/000/010/100\n    '.': { width: 2, data: [0x00, 0x00, 0x00, 0x00, 0x80] }, //00/00/00/00/10\n    '/': { width: 5, data: [0x00, 0x10, 0x20, 0x40, 0x80] } //0000 0/0001 0/0010 0/0100 0/1000 0\n};\n\nconst CHEESE_HAT_KO_CHO_JONG = [\n    { width: 5, data: [0xf0, 0x10, 0x10, 0x10, 0x10] }, //1111 0/0001 0/0001 0/0001 0/0001 0\n    { width: 5, data: [0xf0, 0x50, 0x50, 0x50, 0x50] }, //1111 0/0101 0/0101 0/0101 0/0101 0\n    { width: 5, data: [0x80, 0x80, 0x80, 0x80, 0xf0] }, //1000 0/1000 0/1000 0/1000 0/1111 0\n    { width: 5, data: [0xf0, 0x80, 0x80, 0x80, 0xf0] }, //1111 0/1000 0/1000 0/1000 0/1111 0\n    { width: 5, data: [0xf0, 0xa0, 0xa0, 0xa0, 0xf0] }, //1111 0/1010 0/1010 0/1010 0/1111 0\n    { width: 5, data: [0xf0, 0x10, 0xf0, 0x80, 0xf0] }, //1111 0/0001 0/1111 0/1000 0/1111 0\n    { width: 5, data: [0xf0, 0x90, 0x90, 0x90, 0xf0] }, //1111 0/1001 0/1001 0/1001 0/1111 0\n    { width: 5, data: [0x90, 0x90, 0xf0, 0x90, 0xf0] }, //1001 0/1001 0/1111 0/1001 0/1111 0\n    { width: 6, data: [0xa8, 0xa8, 0xf8, 0xa8, 0xf8] }, //1010 1/1010 1/1111 1/1010 1/1111 1\n    { width: 5, data: [0x40, 0x40, 0xa0, 0x90, 0x90] }, //0100 0/0100 0/1010 0/1001 0/1001 0\n    { width: 6, data: [0x50, 0x50, 0xa8, 0xa8, 0xa8] }, //0101 0/0101 0/1010 1/1010 1/1010 1\n    { width: 5, data: [0x60, 0x90, 0x90, 0x90, 0x60] }, //0110 0/1001 0/1001 0/1001 0/0110 0\n    { width: 5, data: [0xf0, 0x40, 0x40, 0xa0, 0x90] }, //1111 0/0100 0/0100 0/1010 0/1001 0\n    { width: 6, data: [0xf8, 0x50, 0x50, 0xa8, 0xa8] }, //1111 1/0101 0/0101 0/1010 1/1010 1\n    { width: 5, data: [0x40, 0xf0, 0x40, 0xa0, 0x90] }, //0100 0/1111 0/0100 0/1010 0/1001 0\n    { width: 5, data: [0xf0, 0x10, 0xf0, 0x10, 0x10] }, //1111 0/0001 0/1111 0/0001 0/0001 0\n    { width: 5, data: [0xf0, 0x80, 0xf0, 0x80, 0xf0] }, //1111 0/1000 0/1111 0/1000 0/1111 0\n    { width: 5, data: [0xf0, 0x60, 0x60, 0x60, 0xf0] }, //1111 0/0110 0/0110 0/0110 0/1111 0\n    { width: 5, data: [0x60, 0xf0, 0x60, 0x90, 0x60] }, //0110 0/1111 0/0110 0/1001 0/0110 0\n    { width: 6, data: [0xd0, 0x50, 0x68, 0x68, 0x68] }, //1101 0/0101 0/0110 1/0110 1/0110 1\n    { width: 6, data: [0xb8, 0x90, 0x90, 0xa8, 0xe8] }, //1011 1/1001 0/1001 0/1010 1/1110 1\n    { width: 6, data: [0x90, 0xb8, 0x90, 0xa8, 0xd0] }, //1001 0/1011 1/1001 0/1010 1/1101 0\n    { width: 5, data: [0xf0, 0x50, 0xd0, 0x90, 0xd0] }, //1111 0/0101 0/1101 0/1001 0/1101 0\n    { width: 6, data: [0xf8, 0x68, 0xe8, 0xa8, 0xf8] }, //1111 1/0110 1/1110 1/1010 1/1111 1\n    { width: 6, data: [0xe8, 0x68, 0xf8, 0xa8, 0xf8] }, //1110 1/0110 1/1111 1/1010 1/1111 1\n    { width: 6, data: [0xd0, 0x50, 0xe8, 0xa8, 0xe8] }, //1101 0/0101 0/1110 1/1010 1/1110 1\n    { width: 5, data: [0xf0, 0x60, 0xf0, 0xa0, 0xf0] }, //1111 0/0110 0/1111 0/1010 0/1111 0\n    { width: 6, data: [0xf8, 0x50, 0xf8, 0x90, 0xf8] }, //1111 1/0101 0/1111 1/1001 0/1111 1\n    { width: 6, data: [0xd0, 0x78, 0xd0, 0xa8, 0xd0] }, //1101 0/0111 1/1101 0/1010 1/1101 0\n    { width: 7, data: [0xa8, 0xa8, 0xf4, 0xb4, 0xf4] } //1010 10/1010 10/1111 01/1011 01/1111 01\n];\n\nconst CHEESE_HAT_KO_JUNG = [\n    { width: 4, data: [0x80, 0x80, 0xe0, 0x80, 0x80] }, //1000 0/1000 0/1110 0/1000 0/1000 0\n    { width: 4, data: [0xa0, 0xa0, 0xe0, 0xa0, 0xa0] }, //1010 0/1010 0/1110 0/1010 0/1010 0\n    { width: 4, data: [0x80, 0xe0, 0x80, 0xe0, 0x80] }, //1000 0/1110 0/1000 0/1110 0/1000 0\n    { width: 4, data: [0xa0, 0xe0, 0xa0, 0xe0, 0xa0] }, //1010 0/1110 0/1010 0/1110 0/1010 0\n    { width: 4, data: [0x20, 0x20, 0xe0, 0x20, 0x20] }, //0010 0/0010 0/1110 0/0010 0/0010 0\n    { width: 4, data: [0x60, 0x60, 0xe0, 0x60, 0x60] }, //0110 0/0110 0/1110 0/0110 0/0110 0\n    { width: 4, data: [0x20, 0xe0, 0x20, 0xe0, 0x20] }, //0010 0/1110 0/0010 0/1110 0/0010 0\n    { width: 4, data: [0x60, 0xe0, 0x60, 0xe0, 0x60] }, //0110 0/1110 0/0110 0/1110 0/0110 0\n    { width: 6, data: [0x00, 0x20, 0x20, 0xf8, 0x00] }, //0000 0/0010 0/0010 0/1111 1/0000 0\n    { width: 6, data: [0x10, 0x50, 0x58, 0xf0, 0x10] }, //0001 0/0101 0/0101 1/1111 0/0001 0\n    { width: 6, data: [0x18, 0x58, 0x58, 0xf8, 0x18] }, //0001 1/0101 1/0101 1/1111 1/0001 1\n    { width: 5, data: [0x10, 0x50, 0x50, 0xf0, 0x10] }, //0001 0/0101 0/0101 0/1111 0/0001 0\n    { width: 6, data: [0x00, 0x50, 0x50, 0xf8, 0x00] }, //0000 0/0101 0/0101 0/1111 1/0000 0\n    { width: 6, data: [0x00, 0xf8, 0x20, 0x20, 0x00] }, //0000 0/1111 1/0010 0/0010 0/0000 0\n    { width: 6, data: [0x08, 0xf8, 0x48, 0x58, 0x08] }, //0000 1/1111 1/0100 1/0101 1/0000 1\n    { width: 6, data: [0x18, 0xf8, 0x58, 0x78, 0x18] }, //0001 1/1111 1/0101 1/0111 1/0001 1\n    { width: 5, data: [0x10, 0x10, 0xf0, 0x50, 0x50] }, //0001 0/0001 0/1111 0/0101 0/0101 0\n    { width: 6, data: [0x00, 0xf8, 0x50, 0x50, 0x00] }, //0000 0/1111 1/0101 0/0101 0/0000 0\n    { width: 5, data: [0x00, 0x00, 0x00, 0xf0, 0x00] }, //0000 0/0000 0/0000 0/1111 0/0000 0\n    { width: 5, data: [0x10, 0x10, 0x10, 0xf0, 0x10] }, //0001 0/0001 0/0001 0/1111 0/0001 0\n    { width: 2, data: [0x80, 0x80, 0x80, 0x80, 0x80] } //1000 0/1000 0/1000 0/1000 0/1000 0\n];\n\nfunction CheeseHatColorLedBackground(size) {\n    this.display = new Array(size);\n    this.pos = { x: 0, y: 0 };\n    this.reset();\n}\n\nCheeseHatColorLedBackground.prototype.clearDisplay = function() {\n    const display = this.display;\n    for(let i = 0; i < display.length; ++i) {\n        display[i] = 0;\n    }\n};\n\nCheeseHatColorLedBackground.prototype.clear = function() {\n    this.data = {};\n    this.clearDisplay();\n    this.pos.x = 0;\n    this.pos.y = 0;\n};\n\nCheeseHatColorLedBackground.prototype.reset = function() {\n    this.clear();\n};\n\nfunction CheeseHatColorLedSprite(size) {\n    this.size = size;\n    this.display = new Array(size);\n    this.pos = { x: 0, y: 0 };\n    this.roi = {};\n    this.rot = new Array(4);\n    this.rotTmp = new Array(4);\n    this.reset();\n}\n\nCheeseHatColorLedSprite.prototype.clearDisplay = function() {\n    const display = this.display;\n    for(let i = 0; i < display.length; ++i) {\n        display[i] = 0;\n    }\n};\n\nCheeseHatColorLedSprite.prototype.clear = function() {\n    this.data = {};\n    this.clearDisplay();\n    this.width = 0;\n    this.height = 0;\n    const roi = this.roi;\n    roi.left = this.size;\n    roi.right = 0;\n    roi.top = this.size;\n    roi.bottom = 0;\n};\n\nCheeseHatColorLedSprite.prototype.reset = function() {\n    this.clear();\n    this.pos.x = 0;\n    this.pos.y = 0;\n    const rot = this.rot;\n    rot[0] = 0; rot[1] = 1; rot[2] = 2; rot[3] = 3;\n    this.visible = true;\n};\n\nfunction CheeseHatColorLedTouchCalculator(size) {\n    this.size = size;\n}\n\nCheeseHatColorLedTouchCalculator.prototype.__checkTouch = function(display1, display2) {\n    const size = this.size;\n    for(let i = 0; i < size; ++i) {\n        if(display1[i] & display2[i]) return true;\n    }\n    return false;\n};\n\nCheeseHatColorLedTouchCalculator.prototype.checkSprites = function(sprite1, sprite2) {\n    if(sprite1 && sprite2) return this.__checkTouch(sprite1.display, sprite2.display);\n    return false;\n};\n\nCheeseHatColorLedTouchCalculator.prototype.checkOtherSprite = function(sprites, i) {\n    if(sprites) {\n        const sprite = sprites[i];\n        if(sprite) {\n            let other;\n            for(const j in sprites) {\n                if(i != j) {\n                    other = sprites[j];\n                    if(other) {\n                        if(this.__checkTouch(sprite.display, other.display)) return true;\n                    }\n                }\n            }\n        }\n    }\n    return false;\n};\n\nCheeseHatColorLedTouchCalculator.prototype.checkBackground = function(sprite, background) {\n    if(sprite && background) return this.__checkTouch(sprite.display, background.display);\n    return false;\n};\n\nCheeseHatColorLedTouchCalculator.prototype.checkLeftWall = function(sprite) {\n    if(sprite) return sprite.roi.left < 0;\n    return false;\n};\n\nCheeseHatColorLedTouchCalculator.prototype.checkRightWall = function(sprite) {\n    if(sprite) return sprite.roi.right >= this.size;\n    return false;\n};\n\nCheeseHatColorLedTouchCalculator.prototype.checkTopWall = function(sprite) {\n    if(sprite) return sprite.roi.top < 0;\n    return false;\n};\n\nCheeseHatColorLedTouchCalculator.prototype.checkBottomWall = function(sprite) {\n    if(sprite) return sprite.roi.bottom >= this.size;\n    return false;\n};\n\nCheeseHatColorLedTouchCalculator.prototype.checkAnyWall = function(sprite) {\n    if(sprite) {\n        const roi = sprite.roi;\n        const size = this.size;\n        return roi.left < 0 || roi.right >= size || roi.top < 0 || roi.bottom >= size;\n    }\n    return false;\n};\n\nfunction CheeseHatColorLedMatrix(id, size) {\n    this.size = size;\n    this.packet = new Array(20);\n    this.packet[0] = (id & 0x0f) | 0x20;\n    this.packet[1] = (id >> 4) & 0xff;\n    this.background = new CheeseHatColorLedBackground(size);\n    this.touchCalculator = new CheeseHatColorLedTouchCalculator(size);\n    this.reset();\n}\n\nCheeseHatColorLedMatrix.prototype.reset = function() {\n    const packet = this.packet;\n    for(let i = 2; i < 20; ++i) {\n        packet[i] = 0;\n    }\n    packet[19] = 20;\n    this.background.reset();\n    this.sprites = {};\n    this.orderedKey = [];\n    this.brightness = 20;\n};\n\nCheeseHatColorLedMatrix.prototype.getPacket = function() {\n    return this.packet;\n};\n\nCheeseHatColorLedMatrix.prototype.__updateBackground = function(target, packet) {\n    const data = target.data;\n    const display = target.display;\n    const pos = target.pos;\n    let xy, px, py, value, index;\n    \n    target.clearDisplay();\n    \n    const size = this.size;\n    for(const i in data) {\n        if(data[i] > 0) {\n            xy = parseInt(i);\n            px = (xy >> 16) & 0xffff;\n            if(px > 0x7fff) px -= 0x10000;\n            px += pos.x;\n            if(px >= 0 && px < size) {\n                py = xy & 0xffff;\n                if(py > 0x7fff) py -= 0x10000;\n                py += pos.y;\n                if(py >= 0 && py < size) {\n                    value = 0x10 >> py;\n                    display[px] |= value;\n                    value = py * 5 + px;\n                    index = parseInt(value / 2) + 2;\n                    if(value % 2 == 1) {\n                        packet[index] = (packet[index] & 0xf0) | (data[i] & 0x0f);\n                    } else {\n                        packet[index] = (packet[index] & 0x0f) | ((data[i] << 4) & 0xf0);\n                    }\n                }\n            }\n        }\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.__updateSprite = function(target, packet) {\n    const data = target.data;\n    const display = target.display;\n    const pos = target.pos;\n    const rot = target.rot;\n    const rmp = target.rotTmp;\n    const width = target.width, height = target.height;\n    let xy, px, py, t, value, index;\n    \n    target.clearDisplay();\n    \n    if(width > 0 && height > 0) {\n        const size = this.size;\n        const roi = target.roi;\n        const flip = ((rot[0] + 1) % 4) != rot[1];\n        if(flip) {\n            rmp[0] = rot[1];\n            rmp[1] = rot[0];\n            rmp[2] = rot[3];\n            rmp[3] = rot[2];\n        } else {\n            rmp[0] = rot[0];\n            rmp[1] = rot[1];\n            rmp[2] = rot[2];\n            rmp[3] = rot[3];\n        }\n        \n        let count = 0;\n        for(let i = 0; i < 4; ++i) {\n            if(rmp[i] == 0) {\n                count = i;\n                break;\n            }\n        }\n        \n        if(flip) {\n            if(count == 1) count = 3;\n            else if(count == 3) count = 1;\n        }\n        \n        for(const i in data) {\n            if(data[i] > 0) {\n                xy = parseInt(i);\n                px = (xy >> 16) & 0xffff;\n                if(px > 0x7fff) px -= 0x10000;\n                py = xy & 0xffff;\n                if(py > 0x7fff) py -= 0x10000;\n                if(flip) {\n                    px = width - 1 - px;\n                }\n                switch(count) {\n                    case 1: {\n                        t = px;\n                        px = width - 1 - py;\n                        py = t;\n                        break;\n                    }\n                    case 2: {\n                        px = width - 1 - px;\n                        py = height - 1 - py;\n                        break;\n                    }\n                    case 3: {\n                        t = px;\n                        px = py;\n                        py = height - 1 - t;\n                        break;\n                    }\n                }\n                px += pos.x;\n                if(px >= 0 && px < size) {\n                    py += pos.y;\n                    if(py >= 0 && py < size) {\n                        value = 0x10 >> py;\n                        display[px] |= value;\n                        value = py * 5 + px;\n                        index = parseInt(value / 2) + 2;\n                        if(value % 2 == 1) {\n                            packet[index] = (packet[index] & 0xf0) | (data[i] & 0x0f);\n                        } else {\n                            packet[index] = (packet[index] & 0x0f) | ((data[i] << 4) & 0xf0);\n                        }\n                    }\n                }\n                if(px < roi.left) roi.left = px;\n                if(px > roi.right) roi.right = px;\n                if(py < roi.top) roi.top = py;\n                if(py > roi.bottom) roi.bottom = py;\n            }\n        }\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.update = function() {\n    const packet = this.packet;\n    for(let i = 2; i < 20; ++i) {\n        packet[i] = 0;\n    }\n    this.__updateBackground(this.background, packet);\n    const sprites = this.sprites;\n    const orderedKey = this.orderedKey;\n    let sprite, roi;\n    const size = this.size;\n    for(const i in orderedKey) {\n        sprite = sprites[orderedKey[i]];\n        if(sprite) {\n            roi = sprite.roi;\n            roi.left = size;\n            roi.right = 0;\n            roi.top = size;\n            roi.bottom = 0;\n            if(sprite.visible) {\n                this.__updateSprite(sprite, packet);\n            }\n        }\n    }\n    packet[19] = this.brightness;\n    return packet;\n};\n\nCheeseHatColorLedMatrix.prototype.__drawPixel = function(data, tx, ty, color) {\n    data[((tx & 0xffff) << 16) | (ty & 0xffff)] = color;\n};\n\nCheeseHatColorLedMatrix.prototype.__drawShape = function(data, tx, ty, shape, width, color) {\n    let value, mask;\n    for(let y = 0; y < shape.length; ++y) {\n        value = shape[y];\n        mask = 0x80;\n        for(let x = 0; x < width; ++x) {\n            if(value & mask) {\n                data[(((tx + x) & 0xffff) << 16) | (ty & 0xffff)] = color;\n            }\n            mask >>= 1;\n        }\n        ++ ty;\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.__KO_JAMO = [ [0], [0, 0], [0, 9], [2], [2, 12], [2, 18], [3], [3, 3], [5], [5, 0], [5, 6], [5, 7], [5, 9], [5, 16], [5, 17], [5, 18], [6], [7], [7, 7], [7, 9], [9], [9, 9], [11], [12], [12, 12], [14], [15], [16], [17], [18] ];\nCheeseHatColorLedMatrix.prototype.__KO_CHO = [ [0], [0, 0], [2], [3], [3, 3], [5], [6], [7], [7, 7], [9], [9, 9], [11], [12], [12, 12], [14], [15], [16], [17], [18] ];\nCheeseHatColorLedMatrix.prototype.__KO_JUNG = [ [0], [1], [2], [3], [4], [5], [6], [7], [8], [8, 0], [8, 1], [8, 20], [12], [13], [13, 4], [13, 5], [13, 20], [17], [18], [18, 20], [20] ];\nCheeseHatColorLedMatrix.prototype.__KO_JONG = [ [], [0], [0, 0], [0, 9], [2], [2, 12], [2, 18], [3], [5], [5, 0], [5, 6], [5, 7], [5, 9], [5, 16], [5, 17], [5, 18], [6], [7], [7, 9], [9], [9, 9], [11], [12], [14], [15], [16], [17], [18] ];\n\nCheeseHatColorLedMatrix.prototype.__drawString = function(data, tx, ty, text, len, color) {\n    let t, width = 0, blank, index, shape;\n    for(let j = 0; j < len; ++j) {\n        t = text.charCodeAt(j);\n        if(t == 32) {\n            blank = true;\n            tx += 5;\n            width += 5;\n        } else {\n            blank = false;\n            if(t >= 0x3131 && t <= 0x314E) {\n                index = t - 0x3131;\n                if(index >= 0 && index < 30) {\n                    index = this.__KO_JAMO[index];\n                    for(const i in index) {\n                        shape = CHEESE_HAT_KO_CHO_JONG[index[i]];\n                        this.__drawShape(data, tx, ty, shape.data, shape.width - 1, color);\n                        tx += shape.width;\n                        width += shape.width;\n                        if(index.length > 1 && i == 0) {\n                            tx --;\n                            width --;\n                        }\n                    }\n                }\n            } else if(t >= 0x314F && t <= 0x3163) {\n                index = t - 0x314F;\n                if(index >= 0 && index < 21) {\n                    index = this.__KO_JUNG[index];\n                    for(const i in index) {\n                        shape = CHEESE_HAT_KO_JUNG[index[i]];\n                        this.__drawShape(data, tx, ty, shape.data, shape.width - 1, color);\n                        tx += shape.width;\n                        width += shape.width;\n                        if(index.length > 1 && i == 0) {\n                            tx --;\n                            width --;\n                        }\n                    }\n                }\n            } else if(t >= 0xAC00 && t <= 0xD7A3) {\n                t -= 0xAC00;\n                \n                index = Math.floor((t / 28) / 21);\n                if(index >= 0 && index < 19) {\n                    index = this.__KO_CHO[index];\n                    for(const i in index) {\n                        shape = CHEESE_HAT_KO_CHO_JONG[index[i]];\n                        this.__drawShape(data, tx, ty, shape.data, shape.width - 1, color);\n                        tx += shape.width;\n                        width += shape.width;\n                        if(index.length > 1 && i == 0) {\n                            tx --;\n                            width --;\n                        }\n                    }\n                }\n                \n                index = Math.floor((t / 28) % 21);\n                if(index >= 0 && index < 21) {\n                    index = this.__KO_JUNG[index];\n                    for(const i in index) {\n                        shape = CHEESE_HAT_KO_JUNG[index[i]];\n                        this.__drawShape(data, tx, ty, shape.data, shape.width - 1, color);\n                        tx += shape.width;\n                        width += shape.width;\n                        if(index.length > 1 && i == 0) {\n                            tx --;\n                            width --;\n                        }\n                    }\n                }\n                \n                index = t % 28;\n                if(index > 0 && index < 28) {\n                    index = this.__KO_JONG[index];\n                    for(const i in index) {\n                        shape = CHEESE_HAT_KO_CHO_JONG[index[i]];\n                        this.__drawShape(data, tx, ty, shape.data, shape.width - 1, color);\n                        tx += shape.width;\n                        width += shape.width;\n                        if(index.length > 1 && i == 0) {\n                            tx --;\n                            width --;\n                        }\n                    }\n                }\n                \n                tx += 2;\n                width += 2;\n            } else {\n                shape = CHEESE_HAT_ALPHABETS[text.charAt(j)];\n                if(shape) {\n                    this.__drawShape(data, tx, ty, shape.data, shape.width - 1, color);\n                    tx += shape.width;\n                    width += shape.width;\n                }\n            }\n        }\n    }\n    if(blank) width -= 5; // last blank\n    return width - 1;\n};\n\nCheeseHatColorLedMatrix.prototype.__drawPattern = function(data, tx, ty, value, start, len, color) {\n    let ch, pos;\n    for(let x = 0; x < len; ++x) {\n        ch = value.charAt(start + x);\n        pos = (((tx + x) & 0xffff) << 16) | (ty & 0xffff);\n        if(ch === '1') {\n            data[pos] = color;\n        } else if(ch === '0') {\n            data[pos] = 0;\n        } else if(ch === '~') {\n            if(data[pos] > 0) data[pos] = 0;\n            else data[pos] = color;\n        }\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.setBackgroundPixel = function(x, y, color) {\n    const background = this.background;\n    const pos = background.pos;\n    const tx = x - pos.x, ty = y - pos.y;\n    this.__drawPixel(background.data, tx, ty, color);\n};\n\nCheeseHatColorLedMatrix.prototype.drawBackgroundShape = function(x, y, shape, color) {\n    shape = CHEESE_HAT_SHAPES[shape];\n    if(shape) {\n        const background = this.background;\n        const pos = background.pos;\n        const tx = x - pos.x, ty = y - pos.y;\n        this.__drawShape(background.data, tx, ty, shape, 5, color);\n        return true;\n    }\n    return false;\n};\n\nCheeseHatColorLedMatrix.prototype.drawBackgroundString = function(x, y, text, color) {\n    const len = text.length;\n    if(len > 0) {\n        const background = this.background;\n        const pos = background.pos;\n        const tx = x - pos.x, ty = y - pos.y;\n        this.__drawString(background.data, tx, ty, text, len, color);\n        return true;\n    }\n    return false;\n};\n\nCheeseHatColorLedMatrix.prototype.drawBackgroundPattern = function(x, y, pattern, color) {\n    pattern = pattern.trim();\n    let len = pattern.length;\n    if(len > 0) {\n        const background = this.background;\n        const data = background.data;\n        const pos = background.pos;\n        let start, end;\n        const tx = x - pos.x;\n        let ty = y - pos.y;\n        const patterns = pattern.split('/');\n        \n        const candidates = {};\n        let del = false;\n        let cy = ty;\n        for(const i in patterns) {\n            pattern = patterns[i].trim();\n            len = pattern.length;\n            if(len > 0) {\n                start = 0;\n                end = false;\n                if(pattern == '$') {\n                    start = 1;\n                    end = true;\n                    len = 0;\n                    del = true;\n                } else {\n                    if(pattern[len - 1] == '$') {\n                        end = true;\n                        -- len;\n                        del = true;\n                    }\n                    if(pattern[0] == '$') {\n                        start = 1;\n                        -- len;\n                        del = true;\n                    }\n                }\n                candidates[cy] = [start, end, len, pattern];\n            } else {\n                candidates[cy] = undefined;\n            }\n            ++ cy;\n        }\n        \n        let candidate;\n        if(del) {\n            let xy, px, py;\n            for(const i in data) {\n                xy = parseInt(i);\n                py = xy & 0xffff;\n                if(py > 0x7fff) py -= 0x10000;\n                py += pos.y;\n                candidate = candidates[py];\n                if(candidate) {\n                    px = (xy >> 16) & 0xffff;\n                    if(px > 0x7fff) px -= 0x10000;\n                    px += pos.x;\n                    if((candidate[0] > 0 && px < tx) || (candidate[1] && px >= tx + candidate[2])) {\n                        delete data[i];\n                    }\n                }\n            }\n        }\n        \n        for(const i in candidates) {\n            candidate = candidates[i];\n            if(candidate) {\n                this.__drawPattern(data, tx, i, candidate[3], candidate[0], candidate[2], color);\n            }\n        }\n        return true;\n    }\n    return false;\n};\n\nCheeseHatColorLedMatrix.prototype.clearBackground = function() {\n    this.background.clear();\n};\n\nCheeseHatColorLedMatrix.prototype.clearAll = function() {\n    this.background.clear();\n    const sprites = this.sprites;\n    let sprite;\n    for(const i in sprites) {\n        sprite = sprites[i];\n        if(sprite) sprite.clear();\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.scrollBackgroundBy = function(x, y) {\n    const pos = this.background.pos;\n    pos.x += x;\n    pos.y += y;\n};\n\nCheeseHatColorLedMatrix.prototype.scrollAllBy = function(x, y) {\n    this.scrollBackgroundBy(x, y);\n    const sprites = this.sprites;\n    let sprite;\n    for(const i in sprites) {\n        sprite = sprites[i];\n        if(sprite) {\n            sprite.pos.x += x;\n            sprite.pos.y += y;\n        }\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.__getOrCreateSprite = function(i) {\n    let sprite = this.sprites[i];\n    if(!sprite) {\n        sprite = this.sprites[i] = new CheeseHatColorLedSprite(this.size);\n        this.orderedKey.push(i);\n        this.orderedKey.sort((a, b) => {\n            return a - b;\n        });\n    }\n    return sprite;\n};\n\nCheeseHatColorLedMatrix.prototype.__getOrCreateEmptySprite = function(i) {\n    let sprite = this.sprites[i];\n    if(sprite) {\n        sprite.data = {};\n    } else {\n        sprite = this.sprites[i] = new CheeseHatColorLedSprite(this.size);\n        this.orderedKey.push(i);\n        this.orderedKey.sort((a, b) => {\n            return a - b;\n        });\n    }\n    return sprite;\n};\n\nCheeseHatColorLedMatrix.prototype.__setSpriteShape = function(sprite, shape, color) {\n    if(sprite) {\n        shape = CHEESE_HAT_SHAPES[shape];\n        if(shape) {\n            sprite.width = 5;\n            sprite.height = 5;\n            this.__drawShape(sprite.data, 0, 0, shape, 5, color);\n            return true;\n        }\n    }\n    return false;\n};\n\nCheeseHatColorLedMatrix.prototype.setSpriteShape = function(i, shape, color) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let res = false;\n        for(const j in sprites) {\n            if(this.__setSpriteShape(sprites[j], shape, color)) res = true;\n        }\n        return res;\n    } else {\n        const sprite = this.__getOrCreateEmptySprite(i);\n        return this.__setSpriteShape(sprite, shape, color);\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.__setSpriteString = function(sprite, text, color) {\n    if(sprite) {\n        const len = text.length;\n        if(len > 0) {\n            sprite.width = this.__drawString(sprite.data, 0, 0, text, len, color);\n            sprite.height = 5;\n            return true;\n        }\n    }\n    return false;\n};\n\nCheeseHatColorLedMatrix.prototype.setSpriteString = function(i, text, color) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let res = false;\n        for(const j in sprites) {\n            if(this.__setSpriteString(sprites[j], text, color)) res = true;\n        }\n        return res;\n    } else {\n        const sprite = this.__getOrCreateEmptySprite(i);\n        return this.__setSpriteString(sprite, text, color);\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.__setSpritePattern = function(sprite, pattern, color) {\n    if(sprite) {\n        pattern = pattern.trim();\n        const len = pattern.length;\n        if(len > 0) {\n            const data = sprite.data;\n            let ty = 0, width = 0;\n            const patterns = pattern.split('/');\n            for(const i in patterns) {\n                pattern = patterns[i].trim();\n                this.__drawPattern(data, 0, ty, pattern, 0, pattern.length, color);\n                width = Math.max(width, pattern.length);\n                ++ ty;\n            }\n            sprite.width = width;\n            sprite.height = ty;\n            return true;\n        }\n    }\n    return false;\n};\n\nCheeseHatColorLedMatrix.prototype.setSpritePattern = function(i, pattern, color) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let res = false;\n        for(const j in sprites) {\n            if(this.__setSpritePattern(sprites[j], pattern, color)) res = true;\n        }\n        return res;\n    } else {\n        const sprite = this.__getOrCreateEmptySprite(i);\n        return this.__setSpritePattern(sprite, pattern, color);\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.clearSprite = function(i) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let sprite;\n        for(const j in sprites) {\n            sprite = sprites[j];\n            if(sprite) sprite.clear();\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        sprite.clear();\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.showSprite = function(i) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let sprite;\n        for(const j in sprites) {\n            sprite = sprites[j];\n            if(sprite) sprite.visible = true;\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        sprite.visible = true;\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.hideSprite = function(i) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let sprite;\n        for(const j in sprites) {\n            sprite = sprites[j];\n            if(sprite) sprite.visible = false;\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        sprite.visible = false;\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.changeSpritePositionsBy = function(i, x, y) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let sprite;\n        for(const j in sprites) {\n            sprite = sprites[j];\n            if(sprite) {\n                sprite.pos.x += x;\n                sprite.pos.y += y;\n            }\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        sprite.pos.x += x;\n        sprite.pos.y += y;\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.setSpritePositionsTo = function(i, x, y) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let sprite;\n        for(const j in sprites) {\n            sprite = sprites[j];\n            if(sprite) {\n                sprite.pos.x = x;\n                sprite.pos.y = y;\n            }\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        sprite.pos.x = x;\n        sprite.pos.y = y;\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.changeSpritePositionBy = function(i, positionX, value) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let sprite;\n        for(const j in sprites) {\n            sprite = sprites[j];\n            if(sprite) {\n                if(positionX) sprite.pos.x += value;\n                else sprite.pos.y += value;\n            }\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        if(positionX) sprite.pos.x += value;\n        else sprite.pos.y += value;\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.setSpritePositionTo = function(i, positionX, value) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        let sprite;\n        for(const j in sprites) {\n            sprite = sprites[j];\n            if(sprite) {\n                if(positionX) sprite.pos.x = value;\n                else sprite.pos.y = value;\n            }\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        if(positionX) sprite.pos.x = value;\n        else sprite.pos.y = value;\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.__rotateSprite = function(sprite, clockwise) {\n    if(sprite) {\n        const rot = sprite.rot;\n        const t0 = rot[0], t1 = rot[1], t2 = rot[2], t3 = rot[3];\n        if(clockwise) {\n            rot[0] = t3;\n            rot[1] = t0;\n            rot[2] = t1;\n            rot[3] = t2;\n        } else {\n            rot[0] = t1;\n            rot[1] = t2;\n            rot[2] = t3;\n            rot[3] = t0;\n        }\n        \n        const width = sprite.width, height = sprite.height;\n        const shift = parseInt((width - height) / 2);\n        sprite.pos.x += shift;\n        sprite.pos.y -= shift;\n        sprite.width = height;\n        sprite.height = width;\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.rotateSprite = function(i, clockwise) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        for(const j in sprites) {\n            this.__rotateSprite(sprites[j], clockwise);\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        this.__rotateSprite(sprite, clockwise);\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.__flipSprite = function(sprite, horz) {\n    if(sprite) {\n        const rot = sprite.rot;\n        const t0 = rot[0], t1 = rot[1], t2 = rot[2], t3 = rot[3];\n        if(horz) {\n            rot[0] = t1;\n            rot[1] = t0;\n            rot[2] = t3;\n            rot[3] = t2;\n        } else {\n            rot[0] = t3;\n            rot[1] = t2;\n            rot[2] = t1;\n            rot[3] = t0;\n        }\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.flipSprite = function(i, horz) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        for(const j in sprites) {\n            this.__flipSprite(sprites[j], horz);\n        }\n    } else {\n        const sprite = this.__getOrCreateSprite(i);\n        this.__flipSprite(sprite, horz);\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.__stampSprite = function(sprite) {\n    if(sprite) {\n        const background = this.background;\n        const spriteData = sprite.data;\n        const backgroundData = background.data;\n        const spritePos = sprite.pos;\n        const backgroundPos = background.pos;\n        let xy, px, py;\n        for(const i in spriteData) {\n            xy = parseInt(i);\n            px = (xy >> 16) & 0xffff;\n            if(px > 0x7fff) px -= 0x10000;\n            px += spritePos.x - backgroundPos.x;\n            py = xy & 0xffff;\n            if(py > 0x7fff) py -= 0x10000;\n            py += spritePos.y - backgroundPos.y;\n            backgroundData[((px & 0xffff) << 16) | (py & 0xffff)] = spriteData[i];\n        }\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.stampSprite = function(i) {\n    if(i < 0) {\n        const sprites = this.sprites;\n        for(const j in sprites) {\n            this.__stampSprite(sprites[j]);\n        }\n    } else {\n        this.__stampSprite(this.sprites[i]);\n    }\n};\n\nCheeseHatColorLedMatrix.prototype.changeBrightnessBy = function(value) {\n    value += this.brightness;\n    if(value < 0) value = 0;\n    else if(value > 100) value = 100;\n    this.brightness = value;\n};\n\nCheeseHatColorLedMatrix.prototype.setBrightnessTo = function(value) {\n    if(value < 0) value = 0;\n    else if(value > 100) value = 100;\n    this.brightness = value;\n};\n\nCheeseHatColorLedMatrix.prototype.getSpritePosition = function(i, positionX) {\n    const sprite = this.sprites[i];\n    if(sprite) {\n        if(positionX) return sprite.pos.x;\n        else return sprite.pos.y;\n    }\n    return 0;\n};\n\nCheeseHatColorLedMatrix.prototype.checkSpritesTouched = function(i, j) {\n    return this.touchCalculator.checkSprites(this.sprites[i], this.sprites[j]);\n};\n\nCheeseHatColorLedMatrix.prototype.checkOtherSpriteTouched = function(i) {\n    return this.touchCalculator.checkOtherSprite(this.sprites, i);\n};\n\nCheeseHatColorLedMatrix.prototype.checkBackgroundTouched = function(i) {\n    return this.touchCalculator.checkBackground(this.sprites[i], this.background);\n};\n\nCheeseHatColorLedMatrix.prototype.checkWallTouched = function(i, direction) {\n    switch(direction) {\n        case -1: return this.touchCalculator.checkAnyWall(this.sprites[i]);\n        case 0: return this.touchCalculator.checkLeftWall(this.sprites[i]);\n        case 1: return this.touchCalculator.checkRightWall(this.sprites[i]);\n        case 2: return this.touchCalculator.checkTopWall(this.sprites[i]);\n        case 3: return this.touchCalculator.checkBottomWall(this.sprites[i]);\n    }\n    return false;\n};\n\nfunction CheeseRange() {\n    this.__ranges = {};\n}\n\nCheeseRange.prototype.__getOrCreate = function(port) {\n    let range = this.__ranges[port];\n    if(!range) {\n        range = this.__ranges[port] = {};\n        this.__reset(range);\n    }\n    return range;\n};\n\nCheeseRange.prototype.__reset = function(range) {\n    range.active = false;\n    range.has_middle = false;\n    range.has_decimal = true;\n    range.in_lower = 0;\n    range.in_middle = 127;\n    range.in_upper = 255;\n    range.out_lower = -100;\n    range.out_middle = 0;\n    range.out_upper = 100;\n    range.out_min = -100;\n    range.out_max = 100;\n};\n\nCheeseRange.prototype.reset = function() {\n    const ranges = this.__ranges;\n    for(const i in ranges) {\n        this.__reset(ranges[i]);\n    }\n};\n\nCheeseRange.prototype.setLowHigh = function(port, low1, high1, low2, high2, decimal) {\n    const range = this.__getOrCreate(port);\n    range.has_middle = false;\n    range.has_decimal = decimal;\n    range.in_lower = low1;\n    range.in_upper = high1;\n    range.out_lower = low2;\n    range.out_upper = high2;\n    range.out_min = Math.min(low2, high2);\n    range.out_max = Math.max(low2, high2);\n    range.active = true;\n};\n\nCheeseRange.prototype.setLowMidHigh = function(port, low1, mid1, high1, low2, mid2, high2, decimal) {\n    const range = this.__getOrCreate(port);\n    if(mid1 == low1 || mid1 == high1) {\n        range.has_middle = false;\n    } else {\n        range.has_middle = true;\n    }\n    range.has_decimal = decimal;\n    range.in_lower = low1;\n    range.in_middle = mid1;\n    range.in_upper = high1;\n    range.out_lower = low2;\n    range.out_middle = mid2;\n    range.out_upper = high2;\n    range.out_min = Math.min(low2, mid2, high2);\n    range.out_max = Math.max(low2, mid2, high2);\n    range.active = true;\n};\n\nCheeseRange.prototype.calc = function(port, value) {\n    const range = this.__getOrCreate(port);\n    if(range.active) {\n        if(range.has_middle) {\n            if(range.in_middle == range.in_upper || range.in_middle == range.in_lower) {\n                if(range.in_lower == range.in_upper) {\n                } else {\n                    value = (range.out_upper - range.out_lower) * (value - range.in_lower) / (range.in_upper - range.in_lower) + range.out_lower;\n                }\n            } else {\n                if(value > range.in_middle) {\n                    value = (range.out_upper - range.out_middle) * (value - range.in_middle) / (range.in_upper - range.in_middle) + range.out_middle;\n                } else {\n                    value = (range.out_middle - range.out_lower) * (value - range.in_lower) / (range.in_middle - range.in_lower) + range.out_lower;\n                }\n            }\n        } else {\n            if(range.in_lower == range.in_upper) {\n            } else {\n                value = (range.out_upper - range.out_lower) * (value - range.in_lower) / (range.in_upper - range.in_lower) + range.out_lower;\n            }\n        }\n        if(value < range.out_min) value = range.out_min;\n        else if(value > range.out_max) value = range.out_max;\n    }\n    if(range.has_decimal) return value;\n    else return Math.round(value);\n};\n\nfunction CheeseButtonCounter() {\n    this.__counters = {};\n}\n\nCheeseButtonCounter.prototype.reset = function() {\n    const counters = this.__counters;\n    for(const i in counters) {\n        counters[i] = 0;\n    }\n};\n\nCheeseButtonCounter.prototype.tick = function() {\n    const counters = this.__counters;\n    for(const i in counters) {\n        if(counters[i] > 0) --counters[i];\n    }\n};\n\nCheeseButtonCounter.prototype.setCount = function(port, value) {\n    this.__counters[port] = value;\n};\n\nCheeseButtonCounter.prototype.isCounting = function(port) {\n    const counter = this.__counters[port];\n    return (counter === undefined) ? false : counter > 0;\n};\n\nfunction CheeseLed(port) {\n    this.__port = port;\n    this.__PORT_A = port + 'a';\n    this.__PORT_B = port + 'b';\n    this.__PORT_C = port + 'c';\n    this.reset();\n}\n\nCheeseLed.prototype.reset = function() {\n    this.__r = 0;\n    this.__g = 0;\n    this.__b = 0;\n    this.__anode = false;\n    this.__portR = this.__PORT_A;\n    this.__portG = this.__PORT_B;\n    this.__portB = this.__PORT_C;\n};\n\nCheeseLed.prototype.setType = function(type) {\n    switch(type) {\n        case 'DEFAULT':\n        case '-RGB': this.__anode = false; this.__portR = this.__PORT_A; this.__portG = this.__PORT_B; this.__portB = this.__PORT_C; break;\n        case '-RBG': this.__anode = false; this.__portR = this.__PORT_A; this.__portB = this.__PORT_B; this.__portG = this.__PORT_C; break;\n        case '-GRB': this.__anode = false; this.__portG = this.__PORT_A; this.__portR = this.__PORT_B; this.__portB = this.__PORT_C; break;\n        case '-GBR': this.__anode = false; this.__portG = this.__PORT_A; this.__portB = this.__PORT_B; this.__portR = this.__PORT_C; break;\n        case '-BRG': this.__anode = false; this.__portB = this.__PORT_A; this.__portR = this.__PORT_B; this.__portG = this.__PORT_C; break;\n        case '-BGR': this.__anode = false; this.__portB = this.__PORT_A; this.__portG = this.__PORT_B; this.__portR = this.__PORT_C; break;\n        case '+RGB': this.__anode = true; this.__portR = this.__PORT_A; this.__portG = this.__PORT_B; this.__portB = this.__PORT_C; break;\n        case '+RBG': this.__anode = true; this.__portR = this.__PORT_A; this.__portB = this.__PORT_B; this.__portG = this.__PORT_C; break;\n        case '+GRB': this.__anode = true; this.__portG = this.__PORT_A; this.__portR = this.__PORT_B; this.__portB = this.__PORT_C; break;\n        case '+GBR': this.__anode = true; this.__portG = this.__PORT_A; this.__portB = this.__PORT_B; this.__portR = this.__PORT_C; break;\n        case '+BRG': this.__anode = true; this.__portB = this.__PORT_A; this.__portR = this.__PORT_B; this.__portG = this.__PORT_C; break;\n        case '+BGR': this.__anode = true; this.__portB = this.__PORT_A; this.__portG = this.__PORT_B; this.__portR = this.__PORT_C; break;\n    }\n};\n\nCheeseLed.prototype.getR = function() {\n    return this.__r;\n};\n\nCheeseLed.prototype.getG = function() {\n    return this.__g;\n};\n\nCheeseLed.prototype.getB = function() {\n    return this.__b;\n};\n\nCheeseLed.prototype.setRgb = function(r, g, b) {\n    this.__r = r;\n    this.__g = g;\n    this.__b = b;\n};\n\nCheeseLed.prototype.isAnode = function() {\n    return this.__anode;\n};\n\nCheeseLed.prototype.getPortR = function() {\n    return this.__portR;\n};\n\nCheeseLed.prototype.getPortG = function() {\n    return this.__portG;\n};\n\nCheeseLed.prototype.getPortB = function() {\n    return this.__portB;\n};\n\nfunction CheeseButtonChecker() {\n    this.reset();\n}\n\nCheeseButtonChecker.prototype.reset = function() {\n    this.__state = 0;\n    this.__pressTime = 0;\n    this.__clicked = false;\n    this.__longPressed = false;\n    this.__clickedEvent = false;\n    this.__longPressedEvent = false;\n};\n\nCheeseButtonChecker.prototype.clearEvent = function() {\n    this.__clickedEvent = false;\n    this.__longPressedEvent = false;\n};\n\nCheeseButtonChecker.prototype.check = function(pressed) {\n    this.__clicked = false;\n    this.__longPressed = false;\n    switch(this.__state) {\n        case 0: // ready state and wait for press\n            if(pressed) {\n                this.__pressTime = Date.now();\n                this.__state = 1;\n            }\n            break;\n        case 1: // check how long button is pressed\n            if(pressed) {\n                if(Date.now() - this.__pressTime > 1500) {\n                    this.__longPressed = true;\n                    this.__state = 2;\n                }\n            } else {\n                if(Date.now() - this.__pressTime < 750) {\n                    this.__clicked = true;\n                }\n                this.__state = 0;\n            }\n            break;\n        case 2: // check release of long-click\n            if(!pressed) this.__state = 0;\n            break;\n    }\n    if(this.__clicked) this.__clickedEvent = true;\n    if(this.__longPressed) this.__longPressedEvent = true;\n};\n\nCheeseButtonChecker.prototype.isClicked = function() {\n    return this.__clickedEvent;\n};\n\nCheeseButtonChecker.prototype.isLongPressed = function() {\n    return this.__longPressedEvent;\n};\n\nfunction CheeseNeopixel() {\n    const packet = this.__packet = new Array(20);\n    for(let i = 0; i < 20; ++i) packet[i] = 0;\n    this.__reset();\n}\n\nCheeseNeopixel.prototype.__reset = function() {\n    this.__cmdId = 0;\n    this.__hasWhite = false;\n    this.__numLeds = 0;\n    this.__brightness = 128;\n    this.__brightnessPerc = 50;\n    this.__auto = true;\n};\n\nCheeseNeopixel.prototype.getPacket = function() {\n    return this.__packet;\n};\n\nCheeseNeopixel.prototype.end = function() {\n    const packet = this.__packet;\n    packet[0] = this.__hasWhite ? 0x4d : 0x45;\n    packet[1] = 0x50;\n    packet[19] = 1;\n    \n    this.__reset();\n    return packet;\n};\n\nCheeseNeopixel.prototype.setType = function(type) {\n    switch(type) {\n        case 0: // grb\n            this.__hasWhite = false;\n            break;\n        case 1: // grbw\n            this.__hasWhite = true;\n            break;\n    }\n};\n\nCheeseNeopixel.prototype.setNumLeds = function(value) {\n    if(value < 0) value = 0;\n    else if(value > 144) value = 144;\n    this.__numLeds = value;\n};\n\nCheeseNeopixel.prototype.__preparePacket = function(cmd) {\n    this.__cmdId = (this.__cmdId % 15) + 1;\n    const packet = this.__packet;\n    packet[0] = this.__hasWhite ? 0x4d : 0x45;\n    packet[1] = ((cmd << 4) & 0xf0) | (this.__cmdId & 0x0f);\n    for(let i = 2; i < 20; ++i) packet[i] = 0;\n    packet[19] = this.__auto ? 1 : 0;\n    return packet;\n};\n\nCheeseNeopixel.prototype.__setRgb = function(from, to, inc, r, g, b) {\n    const packet = this.__preparePacket(0);\n    if(from > to) {\n        packet[2] = (inc == 0) ? from : ((from - to) % inc) + to;\n        packet[3] = from;\n    } else {\n        packet[2] = from;\n        packet[3] = to;\n    }\n    packet[4] = inc;\n    packet[5] = 0;\n    packet[6] = r;\n    packet[7] = g;\n    packet[8] = b;\n    packet[9] = this.__brightness;\n};\n\nCheeseNeopixel.prototype.__changeRgb = function(from, to, inc, r, g, b) {\n    const packet = this.__preparePacket(1);\n    if(from > to) {\n        packet[2] = (inc == 0) ? from : ((from - to) % inc) + to;\n        packet[3] = from;\n    } else {\n        packet[2] = from;\n        packet[3] = to;\n    }\n    packet[4] = inc;\n    packet[10] = 0;\n    if(r < 0) {\n        r = -r;\n        packet[10] |= 0x04;\n    }\n    if(g < 0) {\n        g = -g;\n        packet[10] |= 0x02;\n    }\n    if(b < 0) {\n        b = -b;\n        packet[10] |= 0x01;\n    }\n    packet[5] = 0;\n    packet[6] = r;\n    packet[7] = g;\n    packet[8] = b;\n    packet[9] = this.__brightness;\n};\n\nCheeseNeopixel.prototype.__clear = function(from, to, inc) {\n    const packet = this.__preparePacket(3);\n    if(from > to) {\n        packet[2] = (inc == 0) ? from : ((from - to) % inc) + to;\n        packet[3] = from;\n    } else {\n        packet[2] = from;\n        packet[3] = to;\n    }\n    packet[4] = 0;\n    packet[5] = this.__brightness;\n    packet[6] = 1;\n    packet[7] = (inc > 0) ? inc - 1 : inc;\n};\n\nCheeseNeopixel.prototype.__setPattern = function(from, to, pattern) {\n    const packet = this.__preparePacket(3);\n    if(from > to) {\n        packet[2] = to;\n        packet[3] = from;\n    } else {\n        packet[2] = from;\n        packet[3] = to;\n    }\n    packet[4] = pattern;\n    packet[5] = this.__brightness;\n    packet[6] = packet[3] - packet[2] + 1;\n    packet[7] = 0;\n};\n\nCheeseNeopixel.prototype.__shift = function(from, to, bit, shift, left) {\n    const packet = this.__preparePacket(4);\n    if(from > to) {\n        packet[2] = to;\n        packet[3] = from;\n    } else {\n        packet[2] = from;\n        packet[3] = to;\n    }\n    packet[4] = bit;\n    packet[5] = shift ? 0 : 1;\n    packet[6] = left? 1 : 0;\n    packet[7] = this.__brightness;\n};\n\nCheeseNeopixel.prototype.__setBrightness = function(from, to, inc, perc) {\n    this.__brightnessPerc = perc;\n    this.__brightness = parseInt(perc * 2.55);\n    const packet = this.__preparePacket(2);\n    if(from > to) {\n        packet[2] = (inc == 0) ? from : ((from - to) % inc) + to;\n        packet[3] = from;\n    } else {\n        packet[2] = from;\n        packet[3] = to;\n    }\n    packet[4] = inc;\n    packet[5] = this.__brightness;\n    packet[6] = 255;\n    packet[7] = 255;\n    packet[8] = 255;\n    packet[9] = 255;\n};\n\nCheeseNeopixel.prototype.setAllRgb = function(r, g, b) {\n    this.__setRgb(0, this.__numLeds - 1, 1, r, g, b);\n};\n\nCheeseNeopixel.prototype.changeAllRgb = function(r, g, b) {\n    this.__changeRgb(0, this.__numLeds - 1, 1, r, g, b);\n};\n\nCheeseNeopixel.prototype.setAllPattern = function(pattern) {\n    this.__setPattern(0, this.__numLeds - 1, pattern);\n};\n\nCheeseNeopixel.prototype.setRgbAt = function(index, r, g, b) {\n    if(index < 0 || index >= this.__numLeds) return false;\n    this.__setRgb(index, index, 0, r, g, b);\n    return true;\n};\n\nCheeseNeopixel.prototype.changeRgbAt = function(index, r, g, b) {\n    if(index < 0 || index >= this.__numLeds) return false;\n    this.__changeRgb(index, index, 0, r, g, b);\n    return true;\n};\n\nCheeseNeopixel.prototype.setPatternAt = function(index, pattern) {\n    if(index < 0 || index >= this.__numLeds) return false;\n    this.__setPattern(index, index, pattern);\n    return true;\n};\n\nCheeseNeopixel.prototype.setRgbFromTo = function(from, to, interval, r, g, b) {\n    if(from < 0 || from >= this.__numLeds) return false;\n    if(to < 0 || to >= this.__numLeds) return false;\n    if(interval < 0) interval = -interval;\n    if(interval >= this.__numLeds) return false;\n    if(interval == 0) to = from;\n    this.__setRgb(from, to, interval, r, g, b);\n    return true;\n};\n\nCheeseNeopixel.prototype.changeRgbFromTo = function(from, to, interval, r, g, b) {\n    if(from < 0 || from >= this.__numLeds) return false;\n    if(to < 0 || to >= this.__numLeds) return false;\n    if(interval < 0) interval = -interval;\n    if(interval >= this.__numLeds) return false;\n    if(interval == 0) to = from;\n    this.__changeRgb(from, to, interval, r, g, b);\n    return true;\n};\n\nCheeseNeopixel.prototype.setPatternFromTo = function(from, to, pattern) {\n    if(from < 0 || from >= this.__numLeds) return false;\n    if(to < 0 || to >= this.__numLeds) return false;\n    this.__setPattern(from, to, pattern);\n    return true;\n};\n\nCheeseNeopixel.prototype.clearAll = function() {\n    this.__preparePacket(5);\n};\n\nCheeseNeopixel.prototype.clearAt = function(index) {\n    if(index < 0 || index >= this.__numLeds) return false;\n    this.__clear(index, index, 0);\n    return true;\n};\n\nCheeseNeopixel.prototype.clearFromTo = function(from, to, interval) {\n    if(from < 0 || from >= this.__numLeds) return false;\n    if(to < 0 || to >= this.__numLeds) return false;\n    if(interval < 0) interval = -interval;\n    if(interval >= this.__numLeds) return false;\n    if(interval >= 127) return false;\n    if(interval == 0) to = from;\n    this.__clear(from, to, interval);\n    return true;\n};\n\nCheeseNeopixel.prototype.shiftAll = function(bit) {\n    if(bit == 0) return false;\n    if(bit < 0) {\n        if(bit < -143) return false;\n        this.__shift(0, this.__numLeds - 1, -bit, true, true);\n    } else {\n        if(bit > 143) return false;\n        this.__shift(0, this.__numLeds - 1, bit, true, false);\n    }\n    return true;\n};\n\nCheeseNeopixel.prototype.rotateAll = function(bit) {\n    if(bit == 0) return false;\n    if(bit < 0) {\n        if(bit < -143) return false;\n        this.__shift(0, this.__numLeds - 1, -bit, false, true);\n    } else {\n        if(bit > 143) return false;\n        this.__shift(0, this.__numLeds - 1, bit, false, false);\n    }\n    return true;\n};\n\nCheeseNeopixel.prototype.changeBrightnessBy = function(value) {\n    value += this.__brightnessPerc;\n    if(value < 0) value = 0;\n    else if(value > 100) value = 100;\n    this.__setBrightness(0, this.__numLeds - 1, 1, value);\n};\n\nCheeseNeopixel.prototype.setBrightnessTo = function(value) {\n    if(value < 0) value = 0;\n    else if(value > 100) value = 100;\n    this.__setBrightness(0, this.__numLeds - 1, 1, value);\n};\n\nfunction CheesePid() {\n    this.__buttonChecker1 = new CheeseButtonChecker();\n    this.__buttonChecker2 = new CheeseButtonChecker();\n    this.reset();\n}\n\nCheesePid.prototype.reset = function() {\n    this.__distance = 0;\n    this.__time = 0;\n    this.__temperature = 0;\n    this.__humidity = 0;\n    this.__x1 = 0;\n    this.__y1 = 0;\n    this.__x2 = 0;\n    this.__y2 = 0;\n    this.__button1 = 0;\n    this.__button2 = 0;\n    this.__buttonChecker1.reset();\n    this.__buttonChecker2.reset();\n    this.__encoder = 0;\n};\n\nCheesePid.prototype.clearEvent = function() {\n    this.__buttonChecker1.clearEvent();\n    this.__buttonChecker2.clearEvent();\n};\n\nCheesePid.prototype.handleSensory = function(modePid, recv) {\n    switch(modePid) {\n        case 10: // ultrasonic\n            this.__distance = (((recv[1] & 0xff) << 8) | (recv[2] & 0xff)) / 10.0;\n            this.__time = ((recv[3] & 0xff) << 8) | (recv[4] & 0xff);\n            break;\n        case 11: // dht\n            this.__humidity = (((recv[1] & 0xff) << 8) | (recv[2] & 0xff)) / 10.0;\n            this.__temperature = (((recv[4] & 0xff) << 8) | (recv[5] & 0xff)) / 10.0;\n            if(recv[3] > 0) this.__temperature = -this.__temperature;\n            break;\n        case 12: // ds18b20\n            this.__temperature = (((recv[2] & 0xff) << 8) | (recv[3] & 0xff)) / 100.0;\n            if(recv[1] > 0) this.__temperature = -this.__temperature;\n            break;\n        case 13: // joystick + button\n            this.__x1 = recv[1];\n            this.__y1 = recv[2];\n            this.__button1 = recv[4];\n            this.__button2 = recv[3];\n            this.__buttonChecker1.check(this.__button1 == 1);\n            this.__buttonChecker2.check(this.__button2 == 1);\n            break;\n        case 14: // dual joystick\n            this.__x1 = recv[4];\n            this.__y1 = recv[5];\n            this.__button1 = recv[3];\n            this.__x2 = recv[1];\n            this.__y2 = recv[2];\n            this.__button2 = recv[6];\n            this.__buttonChecker1.check(this.__button1 == 1);\n            this.__buttonChecker2.check(this.__button2 == 1);\n            break;\n        case 15: // ir transceiver\n            break;\n        case 16: { // encoder\n            this.__button1 = 1 - recv[1];\n            let val = (((recv[2] & 0xff) << 8) | (recv[3] & 0xff)) & 0x7ff;\n            if(val > 0x3ff) val -= 0x800;\n            this.__encoder = val;\n            this.__buttonChecker1.check(this.__button1 == 1);\n            break;\n        }\n    }\n};\n\nCheesePid.prototype.getDistance = function() {\n    return this.__distance;\n};\n\nCheesePid.prototype.getTime = function() {\n    return this.__time;\n};\n\nCheesePid.prototype.getTemperature = function() {\n    return this.__temperature;\n};\n\nCheesePid.prototype.getHumidity = function() {\n    return this.__humidity;\n};\n\nCheesePid.prototype.getX1 = function() {\n    return this.__x1;\n};\n\nCheesePid.prototype.getY1 = function() {\n    return this.__y1;\n};\n\nCheesePid.prototype.getX2 = function() {\n    return this.__x2;\n};\n\nCheesePid.prototype.getY2 = function() {\n    return this.__y2;\n};\n\nCheesePid.prototype.getButton1 = function() {\n    return this.__button1;\n};\n\nCheesePid.prototype.getButton2 = function() {\n    return this.__button2;\n};\n\nCheesePid.prototype.isButton1Clicked = function() {\n    return this.__buttonChecker1.isClicked();\n};\n\nCheesePid.prototype.isButton2Clicked = function() {\n    return this.__buttonChecker2.isClicked();\n};\n\nCheesePid.prototype.isButton1LongPressed = function() {\n    return this.__buttonChecker1.isLongPressed();\n};\n\nCheesePid.prototype.isButton2LongPressed = function() {\n    return this.__buttonChecker2.isLongPressed();\n};\n\nCheesePid.prototype.getEncoder = function() {\n    return this.__encoder;\n};\n\nfunction CheeseHat010(sendPacket) {\n    this.__sendPacket = sendPacket;\n    this.__ledMatrix = new CheeseHatColorLedMatrix(10, 5);\n    this.__buttonCheckerA = new CheeseButtonChecker();\n    this.__buttonCheckerB = new CheeseButtonChecker();\n    this.reset();\n}\n\nCheeseHat010.prototype.reset = function() { // mandatory\n    this.__waiting = false;\n    this.__requestId = 0;\n    this.__requestPrevId = 0;\n    this.__buttonA = 0;\n    this.__buttonB = 0;\n    this.__ledMatrix.reset();\n    this.__buttonCheckerA.reset();\n    this.__buttonCheckerB.reset();\n};\n\nCheeseHat010.prototype.clearEvent = function() { // mandatory\n    this.__buttonCheckerA.clearEvent();\n    this.__buttonCheckerB.clearEvent();\n};\n\nCheeseHat010.prototype.getPacket = function() { // mandatory\n    return this.__ledMatrix.getPacket();\n};\n\nCheeseHat010.prototype.getLedMatrix = function() {\n    return this.__ledMatrix;\n};\n\nCheeseHat010.prototype.getButtonA = function() {\n    return this.__buttonA;\n};\n\nCheeseHat010.prototype.getButtonB = function() {\n    return this.__buttonB;\n};\n\nCheeseHat010.prototype.isButtonAClicked = function() {\n    return this.__buttonCheckerA.isClicked();\n};\n\nCheeseHat010.prototype.isButtonBClicked = function() {\n    return this.__buttonCheckerB.isClicked();\n};\n\nCheeseHat010.prototype.isButtonALongPressed = function() {\n    return this.__buttonCheckerA.isLongPressed();\n};\n\nCheeseHat010.prototype.isButtonBLongPressed = function() {\n    return this.__buttonCheckerB.isLongPressed();\n};\n\nCheeseHat010.prototype.issueMatrixUpdate = function() {\n    this.__ledMatrix.update();\n    this.__requestId = (this.__requestId % 255) + 1;\n};\n\nCheeseHat010.prototype.handleSensory = function(recv) { // mandatory\n    this.__buttonA = 1 - recv[2];\n    this.__buttonB = 1 - recv[3];\n    this.__buttonCheckerA.check(this.__buttonA == 1);\n    this.__buttonCheckerB.check(this.__buttonB == 1);\n};\n\nCheeseHat010.prototype.handleRequest = function(sent) {\n    if(this.__waiting && sent) this.__waiting = false;\n    if(!this.__waiting) {\n        if(this.__requestId != this.__requestPrevId) {\n            this.__requestPrevId = this.__requestId;\n            const packet = this.__ledMatrix.getPacket();\n            if(packet) {\n                this.__sendPacket(packet);\n            }\n        }\n    }\n};\n\nfunction CheeseHat(sendPacket) {\n    this.__sendPacket = sendPacket;\n    this.__id = -1;\n    this.__hat = undefined;\n}\n\nCheeseHat.prototype.__createHat = function(id) {\n    this.__hat = undefined;\n    switch(id) {\n        case 10: this.__hat = new CheeseHat010(this.__sendPacket); break;\n    }\n    if(this.__hat) this.__id = id;\n    return this.__hat;\n};\n\nCheeseHat.prototype.getHat = function(id) {\n    if(id == this.__id) return this.__hat;\n};\n\nCheeseHat.prototype.reset = function() {\n    if(this.__hat) this.__hat.reset();\n    this.__id = -1;\n    this.__hat = undefined;\n};\n\nCheeseHat.prototype.start = function(id) {\n    let hat = this.getHat(id);\n    if(!hat) {\n        hat = this.__createHat(id);\n        if(hat) {\n            this.__sendPacket(hat.getPacket());\n        }\n    }\n};\n\nCheeseHat.prototype.end = function() {\n    const hat = this.__hat;\n    this.reset();\n    if(hat) {\n        this.__sendPacket(hat.getPacket());\n    }\n};\n\nCheeseHat.prototype.clearEvent = function() {\n    if(this.__hat) this.__hat.clearEvent();\n};\n\nCheeseHat.prototype.handleSensory = function(recv) {\n    if(recv && (recv[0] & 0xf0) == 0x20) {\n        const id = ((recv[1] & 0xff) << 4) | (recv[0] & 0x0f);\n        if(id == this.__id && this.__hat) {\n            this.__hat.handleSensory(recv);\n        }\n    }\n};\n\nCheeseHat.prototype.handleRequest = function(sent) {\n    if(this.__hat && this.__hat.handleRequest) this.__hat.handleRequest(sent);\n};\n\n/**CheeseRobot**/\nfunction CheeseRobot(index) {\n    const self = this;\n    self.sensory = {\n        signalStrength: 0,\n        accelerationX: 0,\n        accelerationY: 0,\n        accelerationZ: 0,\n        internalTemperature: 0,\n        inputSa: 0,\n        inputSb: 0,\n        inputSc: 0,\n        inputLa: 0,\n        inputLb: 0,\n        inputLc: 0,\n        tilt: 0,\n        stepCount: 0,\n        batteryState: 2,\n    };\n    self.motoring = {\n        group: 'cheese',\n        module: 'cheese',\n        index,\n    };\n    self.stepId = 0;\n    self.soundId = 0;\n    self.writeHatId = 0;\n    self.writePidId = 0;\n    self.writeNeopixelId = 0;\n    self.pulseScId = -1;\n    self.pulseLcId = -1;\n    self.freeFallId = -1;\n    self.tapId = -1;\n    self.stepStateId = -1;\n    self.soundStateId = -1;\n    self.hatStateId = -1;\n    self.pidStateId = -1;\n    self.neopixelStateId = -1;\n    self.readHatId = -1;\n    self.readPidId = -1;\n    \n    self.blockId = 0;\n    self.stepMode = 0x90; // sw wave\n    self.stepCallback = undefined;\n    self.soundCallback = undefined;\n    self.noteBlockId = 0;\n    self.noteTimer1 = undefined;\n    self.noteTimer2 = undefined;\n    self.writeSerialCallbacks = [];\n    self.readSerialCallbacks = [];\n    self.serialInput = '';\n    self.serialDelimiter = 0;\n    self.serialPin = 2;\n    self.serialRate = 0;\n    self.serialSendId = 0;\n    self.serialRecvId = -1;\n    self.neopixelCallback = undefined;\n    self.pulseSc = false;\n    self.pulseLc = false;\n    self.freeFall = false;\n    self.tap = false;\n    self.modeMab = 0;\n    self.resetEncoderFlag = 0;\n    self.tempo = 60;\n    self.range = new CheeseRange();\n    self.buttonCounter = new CheeseButtonCounter();\n    self.buttonChecker = {};\n    self.leds = {\n        'S': new CheeseLed('S'),\n        'L': new CheeseLed('L')\n    };\n    self.pid = new CheesePid();\n    self.hat = new CheeseHat((packet) => {\n        if(packet) {\n            self.motoring.writeHat = packet;\n            self.__issueHat();\n        }\n    });\n    self.neopixel = new CheeseNeopixel();\n    self.writeQueue = new RoboidWriteQueue(64);\n    self.readQueue = new RoboidReadQueue(64);\n    self.timeouts = [];\n}\n\nCheeseRobot.prototype.__PORT_MAP = {\n    group: 'cheese',\n    module: 'cheese',\n    outputSa: 0,\n    outputSb: 0,\n    outputSc: 0,\n    outputLa: 0,\n    outputLb: 0,\n    outputLc: 0,\n    outputMab: 0,\n    outputMcd: 0,\n    buzzer: 0,\n    velocity: 0,\n    step: 0,\n    stepId: 0,\n    note: 0,\n    sound: 0,\n    soundRepeat: 1,\n    soundId: 0,\n    modeSa: 0,\n    modeSb: 0,\n    modeSc: 0,\n    modeLa: 0,\n    modeLb: 0,\n    modeLc: 0,\n    modeMab: 0,\n    modeMcd: 0,\n    modePid: 0,\n    modeExt: 0\n};\n\nCheeseRobot.prototype.setZero = function() {\n    const portMap = this.__PORT_MAP;\n    const motoring = this.motoring;\n    for (const port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    this.stepId = 0;\n    this.soundId = 0;\n    this.writeHatId = 0;\n    this.writePidId = 0;\n    this.writeNeopixelId = 0;\n    this.pulseScId = -1;\n    this.pulseLcId = -1;\n    this.freeFallId = -1;\n    this.tapId = -1;\n    this.stepStateId = -1;\n    this.soundStateId = -1;\n    this.hatStateId = -1;\n    this.pidStateId = -1;\n    this.neopixelStateId = -1;\n    this.readHatId = -1;\n    this.readPidId = -1;\n    \n    this.blockId = 0;\n    this.stepMode = 0x90; // sw wave\n    this.stepCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.writeSerialCallbacks = [];\n    this.readSerialCallbacks = [];\n    this.serialInput = '';\n    this.serialDelimiter = 0;\n    this.serialPin = 2;\n    this.serialRate = 0;\n    this.serialRecvId = -1;\n    this.neopixelCallback = undefined;\n    this.pulseSc = false;\n    this.pulseLc = false;\n    this.freeFall = false;\n    this.tap = false;\n    this.modeMab = 0;\n    this.tempo = 60;\n    \n    this.range.reset();\n    this.buttonCounter.reset();\n    this.buttonChecker = {};\n    for(const i in this.leds) {\n        this.leds[i].reset();\n    }\n    this.pid.reset();\n    this.hat.end();\n    this.__cancelNeopixel();\n    this.__setNeopixel(this.neopixel.end());\n    this.__removeAllTimeouts();\n    this.writeQueue.reset();\n    this.readQueue.reset();\n};\n\nCheeseRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nCheeseRobot.prototype.afterSend = function(sq) {\n    this.pulseSc = false;\n    this.pulseLc = false;\n    this.freeFall = false;\n    this.tap = false;\n    let bc;\n    for(const i in this.buttonChecker) {\n        bc = this.buttonChecker[i];\n        if(bc) bc.clearEvent();\n    }\n    this.pid.clearEvent();\n    this.hat.clearEvent();\n};\n\nCheeseRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nCheeseRobot.prototype.__setModule = function() {\n    this.motoring.group = 'cheese';\n    this.motoring.module = 'cheese';\n};\n\nCheeseRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    const idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nCheeseRobot.prototype.__removeAllTimeouts = function() {\n    const timeouts = this.timeouts;\n    for (const i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nCheeseRobot.prototype.__fireWriteSerialCallbacks = function() {\n    const callbacks = this.writeSerialCallbacks;\n    for (const i in callbacks) {\n        callbacks[i]();\n    }\n    this.writeSerialCallbacks = [];\n};\n\nCheeseRobot.prototype.__fireReadSerialCallbacks = function() {\n    const callbacks = this.readSerialCallbacks;\n    for (const i in callbacks) {\n        callbacks[i]();\n    }\n    this.readSerialCallbacks = [];\n};\n\nCheeseRobot.prototype.__setStep = function(step) {\n    this.stepId = (this.stepId % 255) + 1;\n    this.motoring.step = step;\n    this.motoring.stepId = this.stepId;\n};\n\nCheeseRobot.prototype.__cancelStep = function() {\n    this.stepCallback = undefined;\n};\n\nCheeseRobot.prototype.__setNote = function(note) {\n    this.motoring.note = note;\n};\n\nCheeseRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nCheeseRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nCheeseRobot.prototype.__setSound = function(sound) {\n    this.soundId = (this.soundId % 255) + 1;\n    this.motoring.sound = sound;\n    this.motoring.soundId = this.soundId;\n};\n\nCheeseRobot.prototype.__runSound = function(sound, count) {\n    if(typeof count != 'number') count = 1;\n    if(count < 0) count = -1;\n    if(count) {\n        this.motoring.soundRepeat = count;\n        this.__setSound(sound);\n    }\n};\n\nCheeseRobot.prototype.__cancelSound = function() {\n    this.soundCallback = undefined;\n};\n\nCheeseRobot.prototype.__setModeSa = function(mode) {\n    this.motoring.modeSa = mode;\n};\n\nCheeseRobot.prototype.__setModeSb = function(mode) {\n    this.motoring.modeSb = mode;\n};\n\nCheeseRobot.prototype.__setModeSc = function(mode) {\n    this.motoring.modeSc = mode;\n};\n\nCheeseRobot.prototype.__setModeLa = function(mode) {\n    this.motoring.modeLa = mode;\n};\n\nCheeseRobot.prototype.__setModeLb = function(mode) {\n    this.motoring.modeLb = mode;\n};\n\nCheeseRobot.prototype.__setModeLc = function(mode) {\n    this.motoring.modeLc = mode;\n};\n\nCheeseRobot.prototype.__setModeMab = function(mode) {\n    this.modeMab = mode;\n    this.motoring.modeMab = mode;\n};\n\nCheeseRobot.prototype.__setModeMcd = function(mode) {\n    this.motoring.modeMcd = mode;\n};\n\nCheeseRobot.prototype.__setModePid = function(mode) {\n    this.motoring.modePid = mode;\n};\n\nCheeseRobot.prototype.__setSerialModePid = function() {\n    this.motoring.outputLa = ((this.serialPin & 0x3) << 4) | (this.serialRate & 0x7);\n    this.__setModeLa(255);\n    this.__setModePid(0x03); // serial\n};\n\nCheeseRobot.prototype.__setModeExt = function(mode) {\n    this.motoring.modeExt = mode;\n};\n\nCheeseRobot.prototype.__issueHat = function() {\n    this.writeHatId = (this.writeHatId % 255) + 1;\n    this.motoring.writeHatId = this.writeHatId;\n};\n\nCheeseRobot.prototype.__getOrCreateWritePidArray = function() {\n    const motoring = this.motoring;\n    if(motoring.writePid == undefined) {\n        motoring.writePid = new Array(20);\n        for(let i = 0; i < 20; ++i) motoring.writePid[i] = 0;\n    }\n    return motoring.writePid;\n};\n\nCheeseRobot.prototype.__issuePid = function() {\n    this.writePidId = (this.writePidId % 255) + 1;\n    this.motoring.writePidId = this.writePidId;\n};\n\nCheeseRobot.prototype.__setSerial = function(arr) {\n    var pid = this.__getOrCreateWritePidArray();\n    this.serialSendId = (this.serialSendId % 15) + 1;\n    pid[0] = 0x30 | (this.serialSendId & 0x0f);\n    for(let i = 1, j = 0; i < 20; ++i, ++j) {\n        pid[i] = arr[j];\n    }\n    this.__issuePid();\n};\n\nCheeseRobot.prototype.__setNeopixel = function(packet) {\n    this.__setModeSa(0x08); // neopixel output\n    this.motoring.writeNeopixel = packet;\n    this.__issueNeopixel();\n};\n\nCheeseRobot.prototype.__issueNeopixel = function() {\n    this.writeNeopixelId = (this.writeNeopixelId % 255) + 1;\n    this.motoring.writeNeopixelId = this.writeNeopixelId;\n};\n\nCheeseRobot.prototype.__cancelNeopixel = function() {\n    this.neopixelCallback = undefined;\n};\n\nCheeseRobot.prototype.__isNeopixelIdle = function() {\n    return this.neopixelCallback === undefined;\n};\n\nCheeseRobot.prototype.handleSensory = function() {\n    const self = this;\n    const sensory = self.sensory;\n\n    self.pulseSc = sensory.pulseSc == 1;\n    self.pulseLc = sensory.pulseLc == 1;\n    self.freeFall = sensory.freeFall == 1;\n    self.tap = sensory.tap == 1;\n    \n    if(self.stepCallback) {\n        if(sensory.stepStateId != self.stepStateId) {\n            self.stepStateId = sensory.stepStateId;\n            if(sensory.stepState == 0) {\n                self.motoring.velocity = 0;\n                var callback = self.stepCallback;\n                self.__cancelStep();\n                if(callback) callback();\n            }\n        }\n    }\n    if(self.soundCallback) {\n        if(sensory.soundStateId != self.soundStateId) {\n            self.soundStateId = sensory.soundStateId;\n            if(sensory.soundState == 0) {\n                var callback = self.soundCallback;\n                self.__cancelSound();\n                if(callback) callback();\n            }\n        }\n    }\n    self.buttonCounter.tick();\n    let bc;\n    for(const i in self.buttonChecker) {\n        bc = self.buttonChecker[i];\n        if(bc) {\n            if(self.buttonCounter.isCounting(i)) {\n                bc.check(false);\n            } else {\n                bc.check(sensory['input' + i] == 1);\n            }\n        }\n    }\n    \n    if(sensory.readPidId != self.readPidId) {\n        if(self.readPidId >= 0) {\n            const recv = sensory.readPid;\n            if(recv && (recv[0] & 0xf0) == 0x30) {\n                const id = recv[0] & 0x0f;\n                if(self.motoring.modePid == 3) { // serial\n                    if(id != self.serialRecvId) {\n                        if(self.serialRecvId != -1) {\n                            self.readQueue.push(recv, 1);\n                        }\n                        self.serialRecvId = id;\n                    }\n                } else if(id > 0) {\n                    self.pid.handleSensory(self.motoring.modePid, recv);\n                }\n            }\n        }\n        self.readPidId = sensory.readPidId;\n    }\n    if(sensory.readHatId != self.readHatId) {\n        if(self.readHatId >= 0) {\n            self.hat.handleSensory(sensory.readHat);\n        }\n        self.readHatId = sensory.readHatId;\n    }\n    let hatSent = false;\n    if(sensory.hatStateId != self.hatStateId) {\n        self.hatStateId = sensory.hatStateId;\n        if(sensory.hatState == 1) {\n            hatSent = true;\n        }\n    }\n    this.hat.handleRequest(hatSent);\n    if(sensory.pidStateId != self.pidStateId) {\n        self.pidStateId = sensory.pidStateId;\n        if(sensory.pidState == 1) {\n            const tmp = self.writeQueue.pop();\n            if(self.motoring.modePid == 3) { // serial\n                if(tmp) {\n                    self.__setSerial(tmp);\n                } else {\n                    self.__fireWriteSerialCallbacks();\n                }\n            }\n        }\n    }\n    if(sensory.neopixelStateId != self.neopixelStateId) {\n        self.neopixelStateId = sensory.neopixelStateId;\n        if(sensory.neopixelState == 1) {\n            const callback = self.neopixelCallback;\n            self.__cancelNeopixel();\n            if(callback) callback();\n        }\n    }\n    if(self.readSerialCallbacks.length > 0) {\n        const tmp = self.readQueue.pop(self.serialDelimiter);\n        if(tmp && self.motoring.modePid == 3) { // serial\n            self.serialInput = tmp;\n            self.__fireReadSerialCallbacks();\n        }\n    }\n};\n\nCheeseRobot.prototype.__SENSORS = {\n    SIGNAL_STRENGTH: 'signalStrength',\n    ACCELERATION_X: 'accelerationX',\n    ACCELERATION_Y: 'accelerationY',\n    ACCELERATION_Z: 'accelerationZ',\n};\n\nCheeseRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n\n    const sensor = this.__SENSORS[dev] || dev;\n    return this.sensory[sensor];\n};\n\nCheeseRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n    switch(dev) {\n        case 'TILT_FORWARD': return this.sensory.tilt == 1;\n        case 'TILT_BACKWARD': return this.sensory.tilt == -1;\n        case 'TILT_LEFT': return this.sensory.tilt == 2;\n        case 'TILT_RIGHT': return this.sensory.tilt == -2;\n        case 'TILT_FLIP': return this.sensory.tilt == 3;\n        case 'TILT_NOT': return this.sensory.tilt == -3;\n        case 'TAP': return this.tap;\n        case 'FREE_FALL': return this.freeFall;\n        case 'BATTERY_NORMAL': return this.sensory.batteryState === 2;\n        case 'BATTERY_LOW': return this.sensory.batteryState === 1;\n        case 'BATTERY_EMPTY': return this.sensory.batteryState === 0;\n    }\n    return false;\n};\n\nCheeseRobot.prototype.__SOUNDS = {\n    BEEP: 1,\n    RANDOM_BEEP: 2,\n    NOISE: 10,\n    SIREN: 3,\n    ENGINE: 4,\n    CHOP: 11,\n    ROBOT: 5,\n    DIBIDIBIDIP: 8,\n    GOOD_JOB: 9,\n    HAPPY: 12,\n    ANGRY: 13,\n    SAD: 14,\n    SLEEP: 15,\n    MARCH: 6,\n    BIRTHDAY: 7,\n};\n\nCheeseRobot.prototype.playSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let sound = script.getField('SOUND');\n    let count = script.getNumberValue('COUNT');\n\n    sound = this.__SOUNDS[sound];\n    count = parseInt(count);\n    this.motoring.buzzer = 0;\n    this.__setNote(0);\n    if (sound && count) {\n        this.__runSound(sound, count);\n    } else {\n        this.__runSound(0);\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.playSoundUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.__cancelSound();\n\n        let sound = script.getField('SOUND');\n        let count = script.getNumberValue('COUNT');\n        \n        sound = this.__SOUNDS[sound];\n        count = parseInt(count);\n        this.motoring.buzzer = 0;\n        this.__setNote(0);\n        if (sound && count) {\n            this.__runSound(sound, count);\n            this.soundCallback = function() {\n                script.isPlaying = false;\n            };\n        } else {\n            this.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.__setNote(0);\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        const motoring = this.motoring;\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    this.__setNote(0);\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.clearSound = function(script, motoring) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    this.motoring.buzzer = 0;\n    this.__setNote(0);\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__NOTES = {\n    C: 4,\n    'C#': 5,\n    Db: 5,\n    D: 6,\n    'D#': 7,\n    Eb: 7,\n    E: 8,\n    F: 9,\n    'F#': 10,\n    Gb: 10,\n    G: 11,\n    'G#': 12,\n    Ab: 12,\n    A: 13,\n    'A#': 14,\n    Bb: 14,\n    B: 15,\n    '4': 4,\n    '5': 5,\n    '6': 6,\n    '7': 7,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n    '11': 11,\n    '12': 12,\n    '13': 13,\n    '14': 14,\n    '15': 15,\n};\n\nCheeseRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let note = script.getField('NOTE');\n    let octave = script.getNumberField('OCTAVE');\n\n    note = parseInt(this.__NOTES[note]);\n    octave = parseInt(octave);\n    this.motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        note += (octave - 1) * 12;\n        this.__setNote(note);\n    } else {\n        this.__setNote(0);\n    }\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.playNoteBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n\n        let note = script.getField('NOTE');\n        let octave = script.getNumberField('OCTAVE');\n        let beat = script.getNumberValue('BEAT');\n\n        note = parseInt(this.__NOTES[note]);\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        self.motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            self.__setNote(note);\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        self.__setNote(0);\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__setNote(0);\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n            self.__runSound(0);\n        } else {\n            self.__setNote(0);\n            self.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.__setNote(0);\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.restBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n        let beat = script.getNumberValue('BEAT');\n\n        beat = parseFloat(beat);\n        self.motoring.buzzer = 0;\n        self.__setNote(0);\n        self.__runSound(0);\n        if (beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setSoundPort = function(script) {\n    this.__setModule();\n    const port = script.getField('PORT');\n    \n    if(port == 'INTERNAL') {\n        this.motoring.modeMab = this.modeMab;\n    } else {\n        this.motoring.modeMab = 0x03; // sound out\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__LITERAL_TO_PORT = {\n    SA: 'Sa',\n    SB: 'Sb',\n    SC: 'Sc',\n    LA: 'La',\n    LB: 'Lb',\n    LC: 'Lc',\n    MAB: 'Mab',\n    MCD: 'Mcd',\n    MABC: 'Mabc'\n};\n\nCheeseRobot.prototype.__INPUT_SL_MODES = {\n    MAKEY: 0x00,\n    BUTTON: 0x90,\n    DIGITAL_PULL_UP: 0x10,\n    DIGITAL_PULL_DOWN: 0x20,\n    PULSE: 0x04,\n    PULSE_PULL_UP: 0x14,\n    PULSE_PULL_DOWN: 0x24,\n    ANALOG: 0x01,\n    VOLTAGE: 0xc1,\n};\n\nCheeseRobot.prototype.setInputModeTo = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let mode = script.getField('MODE');\n\n    mode = this.__INPUT_SL_MODES[mode];\n    if(mode == 0x90) {\n        this.buttonCounter.setCount(port, 10);\n        this.buttonChecker[port] = new CheeseButtonChecker();\n    } else {\n        this.buttonCounter.setCount(port, 0);\n    }\n    switch(port) {\n        case 'Sa': this.__setModeSa(mode); break;\n        case 'Sb': this.__setModeSb(mode); break;\n        case 'Sc': this.__setModeSc(mode); break;\n        case 'La': this.__setModeLa(mode); break;\n        case 'Lb': this.__setModeLb(mode); break;\n        case 'Lc': this.__setModeLc(mode); break;\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setInputRangeTo = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let low1 = script.getNumberValue('LOW1');\n    let high1 = script.getNumberValue('HIGH1');\n    let low2 = script.getNumberValue('LOW2');\n    let high2 = script.getNumberValue('HIGH2');\n    const decimal = script.getField('DECIMAL');\n\n    low1 = parseFloat(low1);\n    high1 = parseFloat(high1);\n    low2 = parseFloat(low2);\n    high2 = parseFloat(high2);\n    if((typeof low1 == 'number') && (typeof high1 == 'number') && (typeof low2 == 'number') && (typeof high2 == 'number')) {\n        this.range.setLowHigh(port, low1, high1, low2, high2, decimal == 'REAL');\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setThreeInputRangesTo = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let low1 = script.getNumberValue('LOW1');\n    let mid1 = script.getNumberValue('MIDDLE1');\n    let high1 = script.getNumberValue('HIGH1');\n    let low2 = script.getNumberValue('LOW2');\n    let mid2 = script.getNumberValue('MIDDLE2');\n    let high2 = script.getNumberValue('HIGH2');\n    const decimal = script.getField('DECIMAL');\n\n    low1 = parseFloat(low1);\n    mid1 = parseFloat(mid1);\n    high1 = parseFloat(high1);\n    low2 = parseFloat(low2);\n    mid2 = parseFloat(mid2);\n    high2 = parseFloat(high2);\n    if((typeof low1 == 'number') && (typeof mid1 == 'number') && (typeof high1 == 'number') && (typeof low2 == 'number') && (typeof mid2 == 'number') && (typeof high2 == 'number')) {\n        this.range.setLowMidHigh(port, low1, mid1, high1, low2, mid2, high2, decimal == 'REAL');\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__PORT_TO_INPUTS = {\n    Sa: 'inputSa',\n    Sb: 'inputSb',\n    Sc: 'inputSc',\n    La: 'inputLa',\n    Lb: 'inputLb',\n    Lc: 'inputLc'\n};\n\nCheeseRobot.prototype.getAnalogInput = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    \n    const dev = this.__PORT_TO_INPUTS[port];\n    if(dev) {\n        let val = this.sensory[dev];\n        if(this.buttonCounter.isCounting(port)) val = 0;\n        return this.range.calc(port, val);\n    }\n    return 0;\n};\n\nCheeseRobot.prototype.checkDigitalInput = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    const value = Number(script.getField('VALUE'));\n    \n    const dev = this.__PORT_TO_INPUTS[port];\n    if(dev) {\n        let val = this.sensory[dev];\n        if(this.buttonCounter.isCounting(port)) val = 0;\n        return val === parseInt(value);\n    }\n    return false;\n};\n\nCheeseRobot.prototype.checkButtonState = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    const state = script.getField('STATE');\n    \n    if(this.buttonCounter.isCounting(port)) return false;\n    const bc = this.buttonChecker[port];\n    if(bc) {\n        switch(state) {\n            case 'CLICKED': return bc.isClicked();\n            case 'LONG_PRESSED': return bc.isLongPressed();\n        }\n    }\n    return false;\n};\n\nCheeseRobot.prototype.checkPulseInput = function(script) {\n    this.__setModule();\n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    \n    switch(port) {\n        case 'Sc': return this.pulseSc;\n        case 'Lc': return this.pulseLc;\n    }\n    return false;\n};\n\nCheeseRobot.prototype.__setDigitalOutputMode = function(port) {\n    switch(port) {\n        case 'Sa': this.__setModeSa(0x82); break;\n        case 'Sb': this.__setModeSb(0x82); break;\n        case 'Sc': this.__setModeSc(0x82); break;\n        case 'La': this.__setModeLa(0x82); break;\n        case 'Lb': this.__setModeLb(0x82); break;\n        case 'Lc': this.__setModeLc(0x82); break;\n        case 'Mab': this.__setModeMab(0x00); break;\n        case 'Mcd': this.__setModeMcd(0x00); break;\n    }\n};\n\nCheeseRobot.prototype.__PORT_TO_OUTPUTS = {\n    Sa: 'outputSa',\n    Sb: 'outputSb',\n    Sc: 'outputSc',\n    La: 'outputLa',\n    Lb: 'outputLb',\n    Lc: 'outputLc',\n    Mab: 'outputMab',\n    Mcd: 'outputMcd',\n    Mabc: 'outputMab'\n};\n\nCheeseRobot.prototype.setDigitalOutput = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let value = Number(script.getField('VALUE'));\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        value = parseInt(value);\n        if(typeof value == 'number') {\n            this.__setDigitalOutputMode(port);\n            this.motoring[dev] = value;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__setPwmOutputMode = function(port) {\n    switch(port) {\n        case 'Sa': this.__setModeSa(0x02); break;\n        case 'Sb': this.__setModeSb(0x02); break;\n        case 'Sc': this.__setModeSc(0x02); break;\n        case 'La': this.__setModeLa(0x02); break;\n        case 'Lb': this.__setModeLb(0x02); break;\n        case 'Lc': this.__setModeLc(0x02); break;\n    }\n};\n\nCheeseRobot.prototype.changePwmOutput = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let value = script.getNumberValue('VALUE');\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        value = parseFloat(value);\n        if(typeof value == 'number') {\n            let val = this.motoring[dev];\n            this.__setPwmOutputMode(port);\n            this.motoring[dev] = (val != undefined) ? val + value : value;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setPwmOutput = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let value = script.getNumberValue('VALUE');\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        value = parseFloat(value);\n        if(typeof value == 'number') {\n            this.__setPwmOutputMode(port);\n            this.motoring[dev] = value;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__setServoMotorMode = function(port) {\n    switch(port) {\n        case 'Sa': this.__setModeSa(0x03); break;\n        case 'Sb': this.__setModeSb(0x03); break;\n        case 'Sc': this.__setModeSc(0x03); break;\n        case 'La': this.__setModeLa(0x03); break;\n        case 'Lb': this.__setModeLb(0x03); break;\n        case 'Lc': this.__setModeLc(0x03); break;\n        case 'Mab': this.__setModeMab(0x02); break;\n        case 'Mcd': this.__setModeMcd(0x02); break;\n        case 'Mabc': this.__setModeMab(0x40); break;\n    }\n};\n\nCheeseRobot.prototype.changeServoMotorAngle = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let value = script.getNumberValue('VALUE');\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        value = parseFloat(value);\n        if(typeof value == 'number') {\n            let val = this.motoring[dev];\n            value = (val != undefined) ? val + value : value;\n            if(value < 1) value = 1;\n            else if(value > 180) value = 180;\n            this.__setServoMotorMode(port);\n            this.motoring[dev] = value;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setServoMotorAngle = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let value = script.getNumberValue('VALUE');\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        value = parseFloat(value);\n        if(typeof value == 'number') {\n            if(value < 1) value = 1;\n            else if(value > 180) value = 180;\n            this.__setServoMotorMode(port);\n            this.motoring[dev] = value;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.turnOffServoMotor = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        this.__setServoMotorMode(port);\n        this.motoring[dev] = 0;\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__setDcMotorMode = function(port) {\n    switch(port) {\n        case 'Mab': this.__setModeMab(0x01); break;\n        case 'Mcd': this.__setModeMcd(0x01); break;\n    }\n};\n\nCheeseRobot.prototype.changeDcMotorVelocity = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let value = script.getNumberValue('VALUE');\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        value = parseFloat(value);\n        if(typeof value == 'number') {\n            let val = this.motoring[dev];\n            value = (val != undefined) ? val + value : value;\n            if(value < -100) value = -100;\n            else if(value > 100) value = 100;\n            this.__setDcMotorMode(port);\n            this.motoring[dev] = value;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setDcMotorVelocity = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    let value = script.getNumberValue('VALUE');\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        value = parseFloat(value);\n        if(typeof value == 'number') {\n            if(value < -100) value = -100;\n            else if(value > 100) value = 100;\n            this.__setDcMotorMode(port);\n            this.motoring[dev] = value;\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.stopDcMotor = function(script) {\n    this.__setModule();\n    \n    const port = this.__LITERAL_TO_PORT[script.getField('PORT')];\n    \n    const dev = this.__PORT_TO_OUTPUTS[port];\n    if(dev) {\n        this.__setDcMotorMode(port);\n        this.motoring[dev] = 0;\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.rotateStepMotor = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n        this.__cancelStep();\n        this.__setModeMab(this.stepMode);\n\n        let step = script.getNumberValue('STEP');\n        let velocity = script.getNumberValue('VELOCITY');\n        \n        step = parseInt(step);\n        velocity = parseFloat(velocity);\n\n        if((typeof step == 'number') && (typeof velocity == 'number')) {\n            if(velocity < -500) velocity = -500;\n            else if(velocity > 500) velocity = 500;\n            this.motoring.velocity = velocity;\n            this.__setStep(step);\n            this.stepCallback = function() {\n                script.isMoving = false;\n            };\n        } else {\n            this.motoring.velocity = 0;\n            this.__setStep(0);\n            script.isMoving = false;\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.changeStepMotorVelocity = function(script) {\n    this.__setModule();\n    this.__cancelStep();\n    this.__setModeMab(this.stepMode);\n    \n    let velocity = script.getNumberValue('VELOCITY');\n    \n    velocity = parseFloat(velocity);\n    if(typeof velocity == 'number') {\n        let vel = this.motoring.velocity;\n        velocity = (vel != undefined) ? vel + velocity : velocity;\n        if(velocity < -500) velocity = -500;\n        else if(velocity > 500) velocity = 500;\n        this.motoring.velocity = velocity;\n    }\n    this.__setStep(0);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setStepMotorVelocity = function(script) {\n    this.__setModule();\n    this.__cancelStep();\n    this.__setModeMab(this.stepMode);\n    \n    let velocity = script.getNumberValue('VELOCITY');\n    \n    velocity = parseFloat(velocity);\n    if(typeof velocity == 'number') {\n        if(velocity < -500) velocity = -500;\n        else if(velocity > 500) velocity = 500;\n        this.motoring.velocity = velocity;\n    }\n    this.__setStep(0);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.stopOffStepMotor = function(script) {\n    this.__setModule();\n    this.__cancelStep();\n    \n    const action = script.getField('ACTION');\n    if(action == 'STOP') {\n        this.__setModeMab(this.stepMode);\n    } else {\n        this.__setModeMab(0x80); // sw off\n    }\n    this.motoring.velocity = 0;\n    this.__setStep(0);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__MODE_STEP_MOTORS = {\n    NORMAL: 0x90,\n    POWER: 0xa0\n};\n\nCheeseRobot.prototype.setStepMotorMode = function(script) {\n    this.__setModule();\n    \n    let mode = script.getField('MODE');\n    \n    mode = this.__MODE_STEP_MOTORS[mode];\n    if(typeof mode == 'number') {\n        this.stepMode = mode;\n        this.__setModeMab(mode);\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.getStepCount = function(script) {\n    this.__setModule();\n    return this.sensory.stepCount;\n};\n\nCheeseRobot.prototype.__RGB_COLORS = {\n    DARK: {\n        RED: [15, 0, 0],\n        ORANGE: [15, 3, 0],\n        YELLOW: [15, 15, 0],\n        GREEN: [0, 15, 0],\n        SKY_BLUE: [0, 15, 15],\n        BLUE: [0, 0, 15],\n        VIOLET: [3, 0, 15],\n        PURPLE: [15, 0, 15],\n        WHITE: [15, 15, 15]\n    },\n    NORMAL: {\n        RED: [63, 0, 0],\n        ORANGE: [63, 15, 0],\n        YELLOW: [63, 63, 0],\n        GREEN: [0, 63, 0],\n        SKY_BLUE: [0, 63, 63],\n        BLUE: [0, 0, 63],\n        VIOLET: [15, 0, 63],\n        PURPLE: [63, 0, 63],\n        WHITE: [63, 63, 63]\n    },\n    BRIGHT: {\n        RED: [255, 0, 0],\n        ORANGE: [255, 63, 0],\n        YELLOW: [255, 255, 0],\n        GREEN: [0, 255, 0],\n        SKY_BLUE: [0, 255, 255],\n        BLUE: [0, 0, 255],\n        VIOLET: [63, 0, 255],\n        PURPLE: [255, 0, 255],\n        WHITE: [255, 255, 255]\n    }\n};\n\nCheeseRobot.prototype.__setLedMode = function(port) {\n\tswitch(port) {\n\t\tcase 'S':\n\t\t\tthis.__setModeSa(0x02);\n\t\t\tthis.__setModeSb(0x02);\n\t\t\tthis.__setModeSc(0x02);\n\t\t\tbreak;\n\t\tcase 'L':\n\t\t\tthis.__setModeLa(0x02);\n\t\t\tthis.__setModeLb(0x02);\n\t\t\tthis.__setModeLc(0x02);\n\t\t\tbreak;\n\t}\n};\n\nCheeseRobot.prototype.__setLedRgb = function(port, red, green, blue) {\n    const led = this.leds[port];\n    if(led) {\n        led.setRgb(red, green, blue);\n        red = parseInt(red * 100 / 255.0);\n        green = parseInt(green * 100 / 255.0);\n        blue = parseInt(blue * 100 / 255.0);\n        if(red < 0) red = 0;\n        else if(red > 100) red = 100;\n        if(green < 0) green = 0;\n        else if(green > 100) green = 100;\n        if(blue < 0) blue = 0;\n        else if(blue > 100) blue = 100;\n        if(led.isAnode()) {\n            red = 100 - red;\n            green = 100 - green;\n            blue = 100 - blue;\n        }\n        this.__setLedMode(port);\n        let dev = this.__PORT_TO_OUTPUTS[led.getPortR()];\n        if(dev) this.motoring[dev] = red;\n        dev = this.__PORT_TO_OUTPUTS[led.getPortG()];\n        if(dev) this.motoring[dev] = green;\n        dev = this.__PORT_TO_OUTPUTS[led.getPortB()];\n        if(dev) this.motoring[dev] = blue;\n    }\n};\n\nCheeseRobot.prototype.setLedColor = function(script) {\n    this.__setModule();\n    \n    const port = script.getField('PORT');\n    const intensity = script.getField('INTENSITY');\n    const color = script.getField('COLOR');\n    \n    const rgb = this.__RGB_COLORS[intensity][color];\n    if(rgb) {\n        this.__setLedRgb(port, rgb[0], rgb[1], rgb[2]);\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setLedRgbArray = function(script) {\n    this.__setModule();\n    \n    const port = script.getField('PORT');\n    const color = script.getField('COLOR');\n    \n    const r = parseInt(color.slice(1, 3), 16);\n    const g = parseInt(color.slice(3, 5), 16);\n    const b = parseInt(color.slice(5, 7), 16);\n    this.__setLedRgb(port, r, g, b);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.changeLedRgb = function(script) {\n    this.__setModule();\n    \n    const port = script.getField('PORT');\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n    \n    const led = this.leds[port];\n    if(led) {\n        red = parseInt(red);\n        green = parseInt(green);\n        blue = parseInt(blue);\n        if((typeof red == 'number') && (typeof green == 'number') && (typeof blue == 'number')) {\n            red += led.getR();\n            green += led.getG();\n            blue += led.getB();\n            if(red < 0) red = 0;\n            else if(red > 255) red = 255;\n            if(green < 0) green = 0;\n            else if(green > 255) green = 255;\n            if(blue < 0) blue = 0;\n            else if(blue > 255) blue = 255;\n            this.__setLedRgb(port, red, green, blue);\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setLedRgb = function(script) {\n    this.__setModule();\n    \n    const port = script.getField('PORT');\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n    \n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if((typeof red == 'number') && (typeof green == 'number') && (typeof blue == 'number')) {\n        if(red < 0) red = 0;\n        else if(red > 255) red = 255;\n        if(green < 0) green = 0;\n        else if(green > 255) green = 255;\n        if(blue < 0) blue = 0;\n        else if(blue > 255) blue = 255;\n        this.__setLedRgb(port, red, green, blue);\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.clearLed = function(script) {\n    this.__setModule();\n    \n    const port = script.getField('PORT');\n    \n    this.__setLedRgb(port, 0, 0, 0);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.setLedType = function(script) {\n    this.__setModule();\n    \n    const port = script.getField('PORT');\n    const type = script.getField('TYPE');\n    \n    const led = this.leds[port];\n    if(led) {\n        led.setType(type);\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__refreshNeopixel = function(callback) {\n    const packet = this.neopixel.getPacket();\n    if(packet) {\n        this.__setNeopixel(packet);\n        this.neopixelCallback = callback;\n    } else {\n        callback();\n    }\n};\n\nCheeseRobot.prototype.__NEOPIXEL_TYPES = {\n    GRB: 0,\n    GRBW: 1\n};\n\nCheeseRobot.prototype.neopixelSetNumberAndType = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let number = script.getNumberValue('NUMBER');\n            let type = script.getField('TYPE');\n            \n            number = parseInt(number);\n            type = this.__NEOPIXEL_TYPES[type];\n            if((typeof number == 'number') && (typeof type == 'number')) {\n                this.neopixel.setNumLeds(number);\n                this.neopixel.setType(type);\n\n                this.neopixel.clearAll();\n                this.__refreshNeopixel(function() {\n                    script.isWorking = false;\n                });\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetAllColor = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            const color = script.getField('COLOR');\n            \n            const rgb = this.__RGB_COLORS['BRIGHT'][color];\n            if(rgb) {\n                this.neopixel.setAllRgb(rgb[0], rgb[1], rgb[2]);\n                this.__refreshNeopixel(function() {\n                    script.isWorking = false;\n                });\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetAllRgbArray = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            const color = script.getField('COLOR');\n            \n            const r = parseInt(color.slice(1, 3), 16);\n            const g = parseInt(color.slice(3, 5), 16);\n            const b = parseInt(color.slice(5, 7), 16);\n            if((typeof r == 'number') && (typeof g == 'number') && (typeof b == 'number')) {\n                this.neopixel.setAllRgb(r, g, b);\n                this.__refreshNeopixel(function() {\n                    script.isWorking = false;\n                });\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelChangeAllRgb = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let red = script.getNumberValue('RED');\n            let green = script.getNumberValue('GREEN');\n            let blue = script.getNumberValue('BLUE');\n            \n            red = parseInt(red);\n            green = parseInt(green);\n            blue = parseInt(blue);\n            if((typeof red == 'number') && (typeof green == 'number') && (typeof blue == 'number')) {\n                this.neopixel.changeAllRgb(red, green, blue);\n                this.__refreshNeopixel(function() {\n                    script.isWorking = false;\n                });\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetAllRgb = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let red = script.getNumberValue('RED');\n            let green = script.getNumberValue('GREEN');\n            let blue = script.getNumberValue('BLUE');\n            \n            red = parseInt(red);\n            green = parseInt(green);\n            blue = parseInt(blue);\n            if((typeof red == 'number') && (typeof green == 'number') && (typeof blue == 'number')) {\n                this.neopixel.setAllRgb(red, green, blue);\n                this.__refreshNeopixel(function() {\n                    script.isWorking = false;\n                });\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.__NEOPIXEL_PATTERNS = {\n    GRADIENT_RED_GREEN: 128,\n    GRADIENT_RED_BLUE: 129,\n    GRADIENT_RED_WHITE: 130,\n    GRADIENT_RED_BLACK: 131,\n    GRADIENT_GREEN_BLUE: 132,\n    GRADIENT_GREEN_RED: 133,\n    GRADIENT_GREEN_WHITE: 134,\n    GRADIENT_GREEN_BLACK: 135,\n    GRADIENT_BLUE_RED: 136,\n    GRADIENT_BLUE_GREEN: 137,\n    GRADIENT_BLUE_WHITE: 138,\n    GRADIENT_BLUE_BLACK: 139,\n    GRADIENT_WHITE_RED: 140,\n    GRADIENT_WHITE_GREEN: 141,\n    GRADIENT_WHITE_BLUE: 142,\n    GRADIENT_WHITE_BLACK: 143,\n    GRADIENT_BLACK_RED: 144,\n    GRADIENT_BLACK_GREEN: 145,\n    GRADIENT_BLACK_BLUE: 146,\n    GRADIENT_BLACK_WHITE: 147,\n    FILL_3_COLORS: 192,\n    FILL_6_COLORS: 193,\n    FILL_12_COLORS: 194,\n};\n\nCheeseRobot.prototype.neopixelSetAllPattern = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let pattern = script.getField('PATTERN');\n            \n            pattern = this.__NEOPIXEL_PATTERNS[pattern];\n            if(typeof pattern == 'number') {\n                this.neopixel.setAllPattern(pattern);\n                this.__refreshNeopixel(function() {\n                    script.isWorking = false;\n                });\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelClearAll = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            \n            this.neopixel.clearAll();\n            this.__refreshNeopixel(function() {\n                script.isWorking = false;\n            });\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetLedColor = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let pixel = script.getNumberValue('PIXEL');\n            const color = script.getField('COLOR');\n            \n            pixel = parseInt(pixel);\n            const rgb = this.__RGB_COLORS['BRIGHT'][color];\n            if((typeof pixel == 'number') && rgb) {\n                if(this.neopixel.setRgbAt(pixel - 1, rgb[0], rgb[1], rgb[2])) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetLedRgbArray = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let pixel = script.getNumberValue('PIXEL');\n            const color = script.getField('COLOR');\n            \n            pixel = parseInt(pixel);\n            const r = parseInt(color.slice(1, 3), 16);\n            const g = parseInt(color.slice(3, 5), 16);\n            const b = parseInt(color.slice(5, 7), 16);\n            if((typeof pixel == 'number') && (typeof r == 'number') && (typeof g == 'number') && (typeof b == 'number')) {\n                if(this.neopixel.setRgbAt(pixel - 1, r, g, b)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelChangeLedRgb = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let pixel = script.getNumberValue('PIXEL');\n            let red = script.getNumberValue('RED');\n            let green = script.getNumberValue('GREEN');\n            let blue = script.getNumberValue('BLUE');\n            \n            pixel = parseInt(pixel);\n            red = parseInt(red);\n            green = parseInt(green);\n            blue = parseInt(blue);\n            if((typeof pixel == 'number') && (typeof red == 'number') && (typeof green == 'number') && (typeof blue == 'number')) {\n                if(this.neopixel.changeRgbAt(pixel - 1, red, green, blue)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetLedRgb = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let pixel = script.getNumberValue('PIXEL');\n            let red = script.getNumberValue('RED');\n            let green = script.getNumberValue('GREEN');\n            let blue = script.getNumberValue('BLUE');\n            \n            pixel = parseInt(pixel);\n            red = parseInt(red);\n            green = parseInt(green);\n            blue = parseInt(blue);\n            if((typeof pixel == 'number') && (typeof red == 'number') && (typeof green == 'number') && (typeof blue == 'number')) {\n                if(this.neopixel.setRgbAt(pixel - 1, red, green, blue)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelClearLed = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let pixel = script.getNumberValue('PIXEL');\n            \n            pixel = parseInt(pixel);\n            if(typeof pixel == 'number') {\n                if(this.neopixel.clearAt(pixel - 1)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetRangeColor = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let start = script.getNumberValue('START');\n            let end = script.getNumberValue('END');\n            let increment = script.getNumberValue('INCREMENT');\n            const color = script.getField('COLOR');\n            \n            start = parseInt(start);\n            end = parseInt(end);\n            increment = parseInt(increment);\n            const rgb = this.__RGB_COLORS['BRIGHT'][color];\n            if((typeof start == 'number') && (typeof end == 'number') && (typeof increment == 'number') && rgb) {\n                if(this.neopixel.setRgbFromTo(start - 1, end - 1, increment, rgb[0], rgb[1], rgb[2])) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetRangeRgbArray = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let start = script.getNumberValue('START');\n            let end = script.getNumberValue('END');\n            let increment = script.getNumberValue('INCREMENT');\n            const color = script.getField('COLOR');\n            \n            start = parseInt(start);\n            end = parseInt(end);\n            increment = parseInt(increment);\n            const r = parseInt(color.slice(1, 3), 16);\n            const g = parseInt(color.slice(3, 5), 16);\n            const b = parseInt(color.slice(5, 7), 16);\n            if((typeof start == 'number') && (typeof end == 'number') && (typeof increment == 'number') && (typeof r == 'number') && (typeof g == 'number') && (typeof b == 'number')) {\n                if(this.neopixel.setRgbFromTo(start - 1, end - 1, increment, r, g, b)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelChangeRangeRgb = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let start = script.getNumberValue('START');\n            let end = script.getNumberValue('END');\n            let increment = script.getNumberValue('INCREMENT');\n            let red = script.getNumberValue('RED');\n            let green = script.getNumberValue('GREEN');\n            let blue = script.getNumberValue('BLUE');\n            \n            start = parseInt(start);\n            end = parseInt(end);\n            increment = parseInt(increment);\n            red = parseInt(red);\n            green = parseInt(green);\n            blue = parseInt(blue);\n            if((typeof start == 'number') && (typeof end == 'number') && (typeof increment == 'number') && (typeof red == 'number') && (typeof green == 'number') && (typeof blue == 'number')) {\n                if(this.neopixel.changeRgbFromTo(start - 1, end - 1, increment, red, green, blue)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetRangeRgb = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let start = script.getNumberValue('START');\n            let end = script.getNumberValue('END');\n            let increment = script.getNumberValue('INCREMENT');\n            let red = script.getNumberValue('RED');\n            let green = script.getNumberValue('GREEN');\n            let blue = script.getNumberValue('BLUE');\n            \n            start = parseInt(start);\n            end = parseInt(end);\n            increment = parseInt(increment);\n            red = parseInt(red);\n            green = parseInt(green);\n            blue = parseInt(blue);\n            if((typeof start == 'number') && (typeof end == 'number') && (typeof increment == 'number') && (typeof red == 'number') && (typeof green == 'number') && (typeof blue == 'number')) {\n                if(this.neopixel.setRgbFromTo(start - 1, end - 1, increment, red, green, blue)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetRangePattern = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let start = script.getNumberValue('START');\n            let end = script.getNumberValue('END');\n            let pattern = script.getField('PATTERN');\n            \n            start = parseInt(start);\n            end = parseInt(end);\n            pattern = this.__NEOPIXEL_PATTERNS[pattern];\n            if((typeof start == 'number') && (typeof end == 'number') && (typeof pattern == 'number')) {\n                if(this.neopixel.setPatternFromTo(start - 1, end - 1, pattern)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelClearRange = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let start = script.getNumberValue('START');\n            let end = script.getNumberValue('END');\n            let increment = script.getNumberValue('INCREMENT');\n            \n            start = parseInt(start);\n            end = parseInt(end);\n            increment = parseInt(increment);\n            if((typeof start == 'number') && (typeof end == 'number') && (typeof increment == 'number')) {\n                if(this.neopixel.clearFromTo(start - 1, end - 1, increment)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelShift = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let bit = script.getNumberValue('BIT');\n            \n            bit = parseInt(bit);\n            if(typeof bit == 'number') {\n                if(this.neopixel.shiftAll(bit)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelRotate = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let bit = script.getNumberValue('BIT');\n            \n            bit = parseInt(bit);\n            if(typeof bit == 'number') {\n                if(this.neopixel.rotateAll(bit)) {\n                    this.__refreshNeopixel(function() {\n                        script.isWorking = false;\n                    });\n                } else {\n                    script.isWorking = false;\n                }\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelChangeBrightness = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let value = script.getNumberValue('VALUE');\n            \n            value = parseInt(value);\n            if(typeof value == 'number') {\n                this.neopixel.changeBrightnessBy(value);\n                this.__refreshNeopixel(function() {\n                    script.isWorking = false;\n                });\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.neopixelSetBrightness = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWaiting = true;\n        script.isWorking = true;\n        return script;\n    } else if (script.isWaiting) {\n        if(this.__isNeopixelIdle()) {\n            script.isWaiting = false;\n            let value = script.getNumberValue('VALUE');\n            \n            value = parseInt(value);\n            if(typeof value == 'number') {\n                this.neopixel.setBrightnessTo(value);\n                this.__refreshNeopixel(function() {\n                    script.isWorking = false;\n                });\n            } else {\n                script.isWorking = false;\n            }\n        }\n        return script;\n    } else if (script.isWorking) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWaiting;\n        delete script.isWorking;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.writeSerial = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isWriting = true;\n\n        const mode = script.getField('MODE');\n        const text = script.getValue('STRING');\n\n        this.__setSerialModePid();\n        const queue = this.writeQueue;\n        queue.push(text, mode != 'STRING');\n        const data = queue.pop();\n        if(data) {\n            this.writeSerialCallbacks.push(() => {\n                script.isWriting = false;\n            });\n            this.__setSerial(data);\n        } else {\n            script.isWriting = false;\n        }\n        return script;\n    } else if (script.isWriting) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isWriting;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.__SERIAL_DELIMITERS = {\n    ALL: 0,\n    COMMA: 0x2c,\n    COLON: 0x3a,\n    DOLLAR: 0x24,\n    SHARP: 0x23,\n    NEW_LINE: 0x0d,\n};\n        \nCheeseRobot.prototype.readSerialUntil = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isReading = true;\n\n        let delimiter = script.getField('DELIMITER');\n\n        this.__setSerialModePid();\n        delimiter = this.__SERIAL_DELIMITERS[delimiter];\n        if(typeof delimiter == 'number') {\n            this.serialDelimiter = delimiter;\n            this.readSerialCallbacks.push(() => {\n                script.isReading = false;\n            });\n        } else {\n            script.isReading = false;\n        }\n        return script;\n    } else if (script.isReading) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isReading;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nCheeseRobot.prototype.__SERIAL_PORTS = {\n    WRITE_READ: 2,\n    READ_WRITE: 3,\n    WRITE: 0,\n    READ: 1,\n};\n        \nCheeseRobot.prototype.setSerialPort = function(script) {\n    this.__setModule();\n    const port = this.__SERIAL_PORTS[script.getField('PORT')];\n\n    if(typeof port == 'number') {\n        this.serialPin = port;\n        this.__setSerialModePid();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__SERIAL_BAUDS = {\n    '9600': 0,\n    '14400': 1,\n    '19200': 2,\n    '28800': 3,\n    '38400': 4,\n    '57600': 5,\n    '76800': 6,\n    '115200': 7\n};\n        \nCheeseRobot.prototype.setSerialRate = function(script) {\n    this.__setModule();\n    const baud = this.__SERIAL_BAUDS[script.getField('BAUD')];\n\n    if(typeof baud == 'number') {\n        this.serialRate = baud;\n        this.__setSerialModePid();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.getSerialInput = function(script) {\n    this.__setModule();\n    return this.serialInput;\n};\n\nCheeseRobot.prototype.pidStart = function(script) {\n    this.__setModule();\n    \n    const dev = script.getField('DEVICE');\n    switch(dev) {\n        case '10': // PID-10 ultrasonic sensor (HC-SR04+)\n            // 0: La(trigger) Lb(echo) Lc(GND)\n            // 1: La(trigger) Lb(echo)\n            this.motoring.outputLa = 0;\n            this.__setModeLa(255);\n            this.__setModePid(10);\n            break;\n        case '11-1': // PID-11-1 humidity/temperature sensor (DHT11)\n            // upper 4bits\n            // 0: La(data)\n            // 1: La(data), Lb(GND)\n            // 2: La(data), Lb(VCC)\n            this.motoring.outputLa = 1;\n            this.__setModeLa(255);\n            this.__setModePid(11);\n            break;\n        case '11-2': // PID-11-2 humidity/temperature sensor (DHT21)\n            // upper 4bits\n            // 0: La(data)\n            // 1: La(data), Lb(GND)\n            // 2: La(data), Lb(VCC)\n            this.motoring.outputLa = 2;\n            this.__setModeLa(255);\n            this.__setModePid(11);\n            break;\n        case '11-3': // PID-11-3 humidity/temperature sensor (DHT22)\n            // upper 4bits\n            // 0: La(data)\n            // 1: La(data), Lb(GND)\n            // 2: La(data), Lb(VCC)\n            this.motoring.outputLa = 3;\n            this.__setModeLa(255);\n            this.__setModePid(11);\n            break;\n        case '12': // PID-12 temperature sensor (DS18B20)\n            this.__setModePid(12);\n            break;\n        case '13': // PID-13 joystick and button\n            this.__setModePid(13);\n            break;\n        case '14': // PID-14 dual joystick\n            this.__setModePid(14);\n            break;\n        case '15': // PID-15 IR transceiver\n            this.__setModePid(15);\n            break;\n        case '16': // PID-16 encoder\n            this.__setModePid(16);\n            this.__resetEncoder();\n            break;\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.pidSetRangeTo = function(script) {\n    this.__setModule();\n    \n    const input = script.getField('INPUT');\n    let low1 = script.getNumberValue('LOW1');\n    let high1 = script.getNumberValue('HIGH1');\n    let low2 = script.getNumberValue('LOW2');\n    let high2 = script.getNumberValue('HIGH2');\n    const decimal = script.getField('DECIMAL');\n\n    low1 = parseFloat(low1);\n    high1 = parseFloat(high1);\n    low2 = parseFloat(low2);\n    high2 = parseFloat(high2);\n    if((typeof low1 == 'number') && (typeof high1 == 'number') && (typeof low2 == 'number') && (typeof high2 == 'number')) {\n        this.range.setLowHigh(input, low1, high1, low2, high2, decimal == 'REAL');\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.pidSetThreeRangesTo = function(script) {\n    this.__setModule();\n    \n    const input = script.getField('INPUT');\n    let low1 = script.getNumberValue('LOW1');\n    let mid1 = script.getNumberValue('MIDDLE1');\n    let high1 = script.getNumberValue('HIGH1');\n    let low2 = script.getNumberValue('LOW2');\n    let mid2 = script.getNumberValue('MIDDLE2');\n    let high2 = script.getNumberValue('HIGH2');\n    const decimal = script.getField('DECIMAL');\n\n    low1 = parseFloat(low1);\n    mid1 = parseFloat(mid1);\n    high1 = parseFloat(high1);\n    low2 = parseFloat(low2);\n    mid2 = parseFloat(mid2);\n    high2 = parseFloat(high2);\n    if((typeof low1 == 'number') && (typeof mid1 == 'number') && (typeof high1 == 'number') && (typeof low2 == 'number') && (typeof mid2 == 'number') && (typeof high2 == 'number')) {\n        this.range.setLowMidHigh(input, low1, mid1, high1, low2, mid2, high2, decimal == 'REAL');\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.__resetEncoder = function() {\n    if(this.motoring.modePid == 16) { // encoder\n        this.resetEncoderFlag = (this.resetEncoderFlag % 255) + 1;\n        const pid = this.__getOrCreateWritePidArray();\n        pid[0] = 0x31;\n        pid[1] = this.resetEncoderFlag;\n        this.__issuePid();\n    }\n};\n\nCheeseRobot.prototype.pidResetEncoder = function(script) {\n    this.__setModule();\n    this.__resetEncoder();\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.pidGetInput = function(script) {\n    this.__setModule();\n    const input = script.getField('INPUT');\n    switch(input) {\n        case 'DISTANCE': return this.pid.getDistance();\n        case 'TEMPERATURE': return this.pid.getTemperature();\n        case 'HUMIDITY': return this.pid.getHumidity();\n        case 'X1': return this.range.calc('X1', this.pid.getX1());\n        case 'Y1': return this.range.calc('Y1', this.pid.getY1());\n        case 'X2': return this.range.calc('X2', this.pid.getX2());\n        case 'Y2': return this.range.calc('Y2', this.pid.getY2());\n        case 'BUTTON1': return this.pid.getButton1();\n        case 'BUTTON2': return this.pid.getButton2();\n        case 'ENCODER': return this.pid.getEncoder();\n    }\n    return 0;\n};\n\nCheeseRobot.prototype.pidCheckButtonState = function(script) {\n    this.__setModule();\n    \n    const button = script.getField('BUTTON');\n    const state = script.getField('STATE');\n    switch(button) {\n        case '1':\n            switch(state) {\n                case 'CLICKED': return this.pid.isButton1Clicked();\n                case 'LONG_PRESSED': return this.pid.isButton1LongPressed();\n            }\n            break;\n        case '2':\n            switch(state) {\n                case 'CLICKED': return this.pid.isButton2Clicked();\n                case 'LONG_PRESSED': return this.pid.isButton2LongPressed();\n            }\n            break;\n    }\n    return false;\n};\n\nCheeseRobot.prototype.hat010Start = function(script) {\n    this.__setModule();\n    this.hat.start(10);\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010GetButton = function(script) {\n    this.__setModule();\n    \n    const hat = this.hat.getHat(10);\n    if(hat) {\n        const button = script.getField('BUTTON');\n        switch(button) {\n            case 'A': return hat.getButtonA();\n            case 'B': return hat.getButtonB();\n        }\n    }\n    return 0;\n};\n\nCheeseRobot.prototype.hat010CheckButtonState = function(script) {\n    this.__setModule();\n    \n    const hat = this.hat.getHat(10);\n    if(hat) {\n        const button = script.getField('BUTTON');\n        const state = script.getField('STATE');\n        switch(button) {\n            case 'A':\n                switch(state) {\n                    case 'CLICKED': return hat.isButtonAClicked();\n                    case 'LONG_PRESSED': return hat.isButtonALongPressed();\n                }\n                break;\n            case 'B':\n                switch(state) {\n                    case 'CLICKED': return hat.isButtonBClicked();\n                    case 'LONG_PRESSED': return hat.isButtonBLongPressed();\n                }\n                break;\n        }\n    }\n    return false;\n};\n\nCheeseRobot.prototype.__LED_MATRIX_COLORS = {\n    RED: 4,\n    ORANGE: 8,\n    YELLOW: 6,\n    GREEN: 2,\n    SKY_BLUE: 3,\n    BLUE: 1,\n    PURPLE: 5,\n    VIOLET: 9,\n    WHITE: 7\n};\n\nCheeseRobot.prototype.hat010BackgroundTurnOnXY = function(script) {\n    this.__setModule();\n    \n    let x = script.getNumberValue('X');\n    let y = script.getNumberValue('Y');\n    let color = script.getField('COLOR');\n    const hat = this.hat.getHat(10);\n    \n    x = parseInt(x);\n    y = parseInt(y);\n    color = this.__LED_MATRIX_COLORS[color];\n    if(hat && (typeof x == 'number') && (typeof y == 'number') && (typeof color == 'number')) {\n        hat.getLedMatrix().setBackgroundPixel(x, y, color);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010BackgroundTurnOffXY = function(script) {\n    this.__setModule();\n    \n    let x = script.getNumberValue('X');\n    let y = script.getNumberValue('Y');\n    const hat = this.hat.getHat(10);\n    \n    x = parseInt(x);\n    y = parseInt(y);\n    if(hat && (typeof x == 'number') && (typeof y == 'number')) {\n        hat.getLedMatrix().setBackgroundPixel(x, y, 0);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010BackgroundDrawShapeAtXY = function(script) {\n    this.__setModule();\n    \n    let color = script.getField('COLOR');\n    const shape = script.getField('SHAPE');\n    let x = script.getNumberValue('X');\n    let y = script.getNumberValue('Y');\n    const hat = this.hat.getHat(10);\n    \n    x = parseInt(x);\n    y = parseInt(y);\n    color = this.__LED_MATRIX_COLORS[color];\n    if(hat && (typeof x == 'number') && (typeof y == 'number') && (typeof color == 'number') && shape) {\n        if(hat.getLedMatrix().drawBackgroundShape(x, y, shape, color)) {\n            hat.issueMatrixUpdate();\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010BackgroundDrawStringAtXY = function(script) {\n    this.__setModule();\n    \n    let color = script.getField('COLOR');\n    const text = script.getStringValue('TEXT');\n    let x = script.getNumberValue('X');\n    let y = script.getNumberValue('Y');\n    const hat = this.hat.getHat(10);\n    \n    x = parseInt(x);\n    y = parseInt(y);\n    color = this.__LED_MATRIX_COLORS[color];\n    if(hat && (typeof x == 'number') && (typeof y == 'number') && (typeof color == 'number') && text) {\n        if(hat.getLedMatrix().drawBackgroundString(x, y, text, color)) {\n            hat.issueMatrixUpdate();\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010BackgroundDrawPatternAtXY = function(script) {\n    this.__setModule();\n    \n    let color = script.getField('COLOR');\n    const pattern = script.getStringValue('PATTERN');\n    let x = script.getNumberValue('X');\n    let y = script.getNumberValue('Y');\n    const hat = this.hat.getHat(10);\n    \n    x = parseInt(x);\n    y = parseInt(y);\n    color = this.__LED_MATRIX_COLORS[color];\n    if(hat && (typeof x == 'number') && (typeof y == 'number') && (typeof color == 'number') && pattern) {\n        if(hat.getLedMatrix().drawBackgroundPattern(x, y, pattern, color)) {\n            hat.issueMatrixUpdate();\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010Clear = function(script) {\n    this.__setModule();\n    \n    const target = script.getField('TARGET');\n    const hat = this.hat.getHat(10);\n    \n    if(hat) {\n        if(target == 'ALL') hat.getLedMatrix().clearAll();\n        else hat.getLedMatrix().clearBackground();\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010ScrollByXY = function(script) {\n    this.__setModule();\n    \n    const target = script.getField('TARGET');\n    let x = script.getNumberValue('X');\n    let y = script.getNumberValue('Y');\n    const hat = this.hat.getHat(10);\n    \n    x = parseInt(x);\n    y = parseInt(y);\n    if(hat && (typeof x == 'number') && (typeof y == 'number')) {\n        if(target == 'ALL') hat.getLedMatrix().scrollAllBy(x, y);\n        else hat.getLedMatrix().scrollBackgroundBy(x, y);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteSetToShape = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    let color = script.getField('COLOR');\n    const shape = script.getField('SHAPE');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    color = this.__LED_MATRIX_COLORS[color];\n    if(hat && (typeof sprite == 'number') && (typeof color == 'number') && shape) {\n        if(hat.getLedMatrix().setSpriteShape(sprite, shape, color)) {\n            hat.issueMatrixUpdate();\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteSetToString = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    let color = script.getField('COLOR');\n    const text = script.getStringValue('TEXT');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    color = this.__LED_MATRIX_COLORS[color];\n    if(hat && (typeof sprite == 'number') && (typeof color == 'number') && text) {\n        if(hat.getLedMatrix().setSpriteString(sprite, text, color)) {\n            hat.issueMatrixUpdate();\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteSetToPattern = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    let color = script.getField('COLOR');\n    const pattern = script.getStringValue('PATTERN');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    color = this.__LED_MATRIX_COLORS[color];\n    if(hat && (typeof sprite == 'number') && (typeof color == 'number') && pattern) {\n        if(hat.getLedMatrix().setSpritePattern(sprite, pattern, color)) {\n            hat.issueMatrixUpdate();\n        }\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteClearShowHide = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    const action = script.getField('ACTION');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    if(hat && (typeof sprite == 'number')) {\n        switch(action) {\n            case 'CLEAR': hat.getLedMatrix().clearSprite(sprite); break;\n            case 'SHOW': hat.getLedMatrix().showSprite(sprite); break;\n            case 'HIDE': hat.getLedMatrix().hideSprite(sprite); break;\n        }\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteChangePositionsByXY = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    let x = script.getNumberValue('X');\n    let y = script.getNumberValue('Y');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    x = parseInt(x);\n    y = parseInt(y);\n    if(hat && (typeof sprite == 'number') && (typeof x == 'number') && (typeof y == 'number')) {\n        hat.getLedMatrix().changeSpritePositionsBy(sprite, x, y);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteSetPositionsToXY = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    let x = script.getNumberValue('X');\n    let y = script.getNumberValue('Y');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    x = parseInt(x);\n    y = parseInt(y);\n    if(hat && (typeof sprite == 'number') && (typeof x == 'number') && (typeof y == 'number')) {\n        hat.getLedMatrix().setSpritePositionsTo(sprite, x, y);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteChangePositionByValue = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    const position = script.getField('POSITION');\n    let value = script.getNumberValue('VALUE');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    value = parseInt(value);\n    if(hat && (typeof sprite == 'number') && (typeof value == 'number')) {\n        hat.getLedMatrix().changeSpritePositionBy(sprite, position == 'X', value);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteSetPositionToValue = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    const position = script.getField('POSITION');\n    let value = script.getNumberValue('VALUE');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    value = parseInt(value);\n    if(hat && (typeof sprite == 'number') && (typeof value == 'number')) {\n        hat.getLedMatrix().setSpritePositionTo(sprite, position == 'X', value);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteRotate = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    const direction = script.getField('DIRECTION');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    if(hat && (typeof sprite == 'number')) {\n        hat.getLedMatrix().rotateSprite(sprite, direction == 'CLOCKWISE');\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteFlipInDirection = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    const direction = script.getField('DIRECTION');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    if(hat && (typeof sprite == 'number')) {\n        hat.getLedMatrix().flipSprite(sprite, direction == 'LEFT_RIGHT');\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SpriteStampToBackground = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    if(hat && (typeof sprite == 'number')) {\n        hat.getLedMatrix().stampSprite(sprite);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010GetSpritePosition = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    const position = script.getField('POSITION');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    if(hat && (typeof sprite == 'number')) {\n        return hat.getLedMatrix().getSpritePosition(sprite, position == 'X');\n    }\n    return 0;\n};\n\nCheeseRobot.prototype.hat010CheckCheckSpriteSpriteTouched = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    let target = script.getNumberValue('TARGET');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    target = parseInt(target);\n    if(hat && (typeof sprite == 'number') && (typeof target == 'number')) {\n        const matrix = hat.getLedMatrix();\n        matrix.update();\n        return matrix.checkSpritesTouched(sprite, target);\n    }\n    return false;\n};\n\nCheeseRobot.prototype.hat010CheckCheckSpriteTouched = function(script) {\n    this.__setModule();\n    \n    let sprite = script.getNumberValue('SPRITE');\n    const target = script.getField('TARGET');\n    const hat = this.hat.getHat(10);\n    \n    sprite = parseInt(sprite);\n    if(hat && (typeof sprite == 'number')) {\n        const matrix = hat.getLedMatrix();\n        matrix.update();\n        switch(target) {\n            case 'BACKGROUND': return matrix.checkBackgroundTouched(sprite);\n            case 'OTHER_SPRITE': return matrix.checkOtherSpriteTouched(sprite);\n            case 'LEFT_WALL': return matrix.checkWallTouched(sprite, 0);\n            case 'RIGHT_WALL': return matrix.checkWallTouched(sprite, 1);\n            case 'TOP_WALL': return matrix.checkWallTouched(sprite, 2);\n            case 'BOTTOM_WALL': return matrix.checkWallTouched(sprite, 3);\n            case 'ANY_WALL': return matrix.checkWallTouched(sprite, -1);\n        }\n    }\n    return false;\n};\n\nCheeseRobot.prototype.hat010ChangeBrightnessBy = function(script) {\n    this.__setModule();\n    \n    let brightness = script.getNumberValue('BRIGHTNESS');\n    const hat = this.hat.getHat(10);\n    \n    brightness = parseInt(brightness);\n    if(hat && (typeof brightness == 'number')) {\n        hat.getLedMatrix().changeBrightnessBy(brightness);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nCheeseRobot.prototype.hat010SetBrightnessTo = function(script) {\n    this.__setModule();\n    \n    let brightness = script.getNumberValue('BRIGHTNESS');\n    const hat = this.hat.getHat(10);\n    \n    brightness = parseInt(brightness);\n    if(hat && (typeof brightness == 'number')) {\n        hat.getLedMatrix().setBrightnessTo(brightness);\n        hat.issueMatrixUpdate();\n    }\n    return script.callReturn();\n};\n\nEntry.Robomation = {\n    robots: {},\n    robotsByGroup: {},\n    afterReceive(pd, multi) {\n        let index = pd.index;\n        if (index === undefined) {\n            index = 0;\n        }\n        let group = undefined,\n            module = undefined;\n        switch (pd.model) {\n            case 0x04:\n                group = 'hamster';\n                module = 'hamster';\n                break;\n            case 0x0e:\n                group = 'hamster';\n                module = 'hamsterS';\n                break;\n            case 0x09:\n                group = 'turtle';\n                module = 'turtle';\n                break;\n            case 0x0d:\n                group = 'cheese';\n                module = 'cheese';\n                break;\n            case 0x0f:\n                group = 'zerone';\n                module = 'zerone';\n                break;\n            case 0x10:\n                group = 'line';\n                module = 'brown';\n                break;\n            case 0x11:\n                group = 'line';\n                module = 'sally';\n                break;\n            case 0xff:\n                group = pd.group;\n                module = pd.module;\n                break;\n        }\n        if (group && module) {\n            const key = module + index;\n            let robot = this.robots[key];\n            if (!robot) {\n                if (module == 'hamster') {\n                    robot = new HamsterRobot(index);\n                } else if (module == 'hamsterS') {\n                    robot = new HamsterSRobot(index);\n                } else if (module == 'turtle') {\n                    robot = new TurtleRobot(index);\n                } else if (module == 'cheese') {\n                    robot = new CheeseRobot(index);\n                } else if (module == 'zerone') {\n                    robot = new ZeroneRobot(index);\n                } else if (module == 'brown') {\n                    robot = new LineRobot(index, module);\n                } else if (module == 'sally') {\n                    robot = new LineRobot(index, module);\n                }\n                if (robot) {\n                    this.robots[key] = robot;\n                }\n            }\n            if (robot) {\n                if (multi) {\n                    Entry.hw.sendQueue[key] = robot.motoring;\n                }\n                robot.afterReceive(pd);\n            }\n            this.robotsByGroup[group + index] = robot;\n        }\n    },\n    afterSend(sq) {\n        const robots = this.robots;\n        for (const i in robots) {\n            robots[i].afterSend(sq);\n        }\n    },\n    getRobot(group, index) {\n        return this.robotsByGroup[group + index];\n    },\n    setZero() {\n        const robots = this.robots;\n        for (const i in robots) {\n            robots[i].setZero();\n        }\n        Entry.hw.update();\n    },\n};\n\nmodule.exports = Entry.Robomation;"
  },
  {
    "path": "src/playground/blocks/hardware/block_roborobo_base.js",
    "content": "'use strict';\n\nconst PinMode = {\n    INPUT: 0x00,\n    OUTPUT: 0x01,\n    ANALOG: 0x02,\n    I2C: 0x06,\n};\n\nclass ArduinoBase {\n    constructor () {\n        this.resetState();\n    }\n\n    setLanguage () {throw new Error('재정의 필요');}\n    getBlocks () {throw new Error('재정의 필요');}\n\n    setZero () {\n        this.resetState();\n        this.request('reset', null, null, true);\n    }\n\n    afterReceive = function (data) {\n        const keys = data.state ? Object.keys(data.state) : [];\n        keys.forEach(key => this.state[key] = data.state[key]);\n    };\n\n    afterSend = function () {\n        Entry.hw.sendQueue = {};\n    };\n\n    request (func, subkey, value, updateNow = false) {\n        if (!Entry.hw.sendQueue[func]) Entry.hw.sendQueue[func] = {};\n\n        if (subkey) {\n            Entry.hw.sendQueue[func][subkey.toString()] = value;\n        } else {\n            Entry.hw.sendQueue[func] = value;\n        }\n\n        if (updateNow) Entry.hw.update();\n    }\n\n    resetState () {\n        this.state = {\n            pin: [],\n            rx: {}\n        };\n    }\n\n    pinToNumber (pin) {\n        if (pin === undefined || pin === null) return 0;\n        if (typeof pin === 'number') {\n            if (Number.isNaN(pin)) return 0;\n            return pin;\n        }\n\n        const pinStr = pin.toString().toLowerCase();\n        switch (pinStr) {\n            case 'd2': return 2;\n            case 'd3': return 3;\n            case 'd4': return 4;\n            case 'd5': return 5;\n            case 'd6': return 6;\n            case 'd7': return 7;\n            case 'd8': return 8;\n            case 'd9': return 9;\n            case 'd10': return 10;\n            case 'd11': return 11;\n            case 'd12': return 12;\n            case 'd13': return 13;\n            case 'a0': return 14;\n            case 'a1': return 15;\n            case 'a2': return 16;\n            case 'a3': return 17;\n            case 'a4': return 18;\n            case 'a5': return 19;\n            default: {\n                const n = Number(pin);\n                if (Number.isNaN(n)) return 0;\n                return n;\n            }\n        }\n    }\n\n    isEqualsPinMode (pin, mode) {\n        return typeof pin === 'number' && this.state.pin[pin] && this.state.pin[pin].mode == mode;\n    }\n\n    isDigitalPin (pin) {\n        return typeof pin === 'number' && 2 <= pin && pin <= 15;\n    }\n\n    isAnalogPin (pin) {\n        return typeof pin === 'number' && 14 <= pin && pin <= 19;\n    }\n\n    measureAnalogPin (pin) {\n        const analogPin = pin - 14;\n        return Math.min(5, Math.max(0, analogPin));\n    }\n\n    getDigitalValue (pin) {\n        if (!this.isDigitalPin(pin)) return 0;\n\n        if (!this.isEqualsPinMode(pin, PinMode.INPUT)) {\n            this.request('enableDigitalInput', pin, {pin}, true);\n        }\n\n        return this.state.rx.digital && typeof this.state.rx.digital[pin] === 'number'\n            ? this.state.rx.digital[pin]\n            : 0;\n    }\n\n    getAnalogValue (pin, defValue = 0) {\n        if (!this.isAnalogPin(pin)) return defValue;\n\n        if (!this.isEqualsPinMode(pin, PinMode.ANALOG)) {\n            this.request('enableAnalogInput', pin, {pin}, true);\n        }\n\n        const analogPin = this.measureAnalogPin(pin);\n        return this.state.rx.analog && typeof this.state.rx.analog[analogPin] === 'number'\n            ? this.state.rx.analog[analogPin]\n            : defValue;\n    }\n\n    set_digital (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const value = script.getNumberValue('VALUE');\n\n        this.request('setDigital', pin, {pin, value});\n        return script.callReturn();\n    }\n\n    set_motor (sprite, script) {\n        const motor = script.getNumberValue('MOTOR');\n        const speed = script.getNumberValue('SPEED');\n        const state = script.getStringValue('STATE');\n\n        let stateNum = 0;\n        if (state == 'cw') stateNum = 1;\n        else if (state == 'ccw') stateNum = 2;\n\n        this.request('setMotor', motor, {motor, speed, state: stateNum});\n        return script.callReturn();\n    }\n\n    set_motors (sprite, script) {\n        const motors = script.getNumberValue('MOTORS');\n        const speed1 = script.getNumberValue('SPEED1');\n        const speed2 = script.getNumberValue('SPEED2');\n        const state = script.getStringValue('STATE');\n\n        const speed = [speed1, speed2];\n        let motor = [];\n        if (motors == 12) {\n            motor = [1, 2];\n        } else if (motors == 34) {\n            motor = [3, 4];\n        }\n\n        let stateNum = [0, 0];\n        switch (state) {\n            case 'forward':\n                stateNum = [2, 1];\n                break;\n            case 'turn-left':\n                stateNum = [1, 1];\n                break;\n            case 'backward':\n                stateNum = [1, 2];\n                break;\n            case 'turn-right':\n                stateNum = [2, 2];\n                break;\n        }\n\n        for (let i = 0; i < 2; i++) {\n            this.request('setMotor', i + 1, {motor: motor[i], speed: speed[i], state: stateNum[i]});\n        }\n        return script.callReturn();\n    }\n\n    set_servo_angle (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const angle = script.getNumberValue('ANGLE');\n\n        this.request('setServo', pin, {pin, angle});\n        return script.callReturn();\n    }\n\n    set_rgbled_color (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const color = Cast.toRgbColorObject(script.getStringValue('COLOR'));\n\n        this.request('setRgbLedColor', pin, {pin, color});\n        return script.callReturn();\n    }\n\n    change_rgbled_brightness_by (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const brightness = script.getNumberValue('BRIGHTNESS');\n\n        this.request('changeRgbLedBrightnessBy', pin, {pin, brightness});\n        return script.callReturn();\n    }\n\n    set_rgbled_brightness_to (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const brightness = script.getNumberValue('BRIGHTNESS');\n\n        this.request('setRgbLedBrightnessTo', pin, {pin, brightness});\n        return script.callReturn();\n    }\n\n    play_piezobuzzer (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const octave = script.getNumberValue('OCTAVE');\n        const duration = script.getNumberValue('DURATION');\n        let note = script.getNumberValue('NOTE');\n        note = (octave - 1) * 12 + note;\n\n        this.request('setPiezoBuzzer', pin, {pin, note, duration});\n        return script.callReturn();\n    }\n\n    play_piezobuzzer_until_done (sprite, script) {\n        if (script.executeState) {\n            const duration = (script.getNumberValue('DURATION') * 1000);\n            if (Date.now() - script.executeState.startTime > duration) {\n                return script.callReturn();\n            } else {\n                return script;\n            }\n        } else {\n            script.executeState = {startTime: Date.now()};\n            this.play_piezobuzzer(sprite, script);\n            return script;\n        }\n    }\n\n    get_digital_value (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        return this.getDigitalValue(pin);\n    }\n\n    is_digital_detected (sprite, script) {\n        return this.get_digital_value(sprite, script) == 1;\n    }\n\n    get_analog_value (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        return this.getAnalogValue(pin);\n    }\n\n    compare_analog_value (sprite, script) {\n        const value1 = this.get_analog_value(sprite, script);\n        const symbol = script.getStringValue('SYMBOL');\n        const value2 = script.getStringValue('VALUE');\n\n        return this._compare(value1, value2, symbol);\n    }\n\n    _compare (v1, v2, symbol) {\n        switch (symbol) {\n            case 'greater-than':\n                return v1 > v2;\n            case 'equal':\n                return v1 == v2;\n            case 'less-than':\n                return v1 < v2;\n            default: return false;\n        }\n    }\n\n    get_sensor_value (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const sensor = script.getStringValue('SENSOR');\n\n        if (sensor == 'ultrasonic') {\n            if (!this.isEqualsPinMode(pin, PinMode.INPUT)) {\n                this.request('enableSonarSensor', pin, {pin}, true);\n            }\n            return this.state.rx.digital[pin];\n        }\n\n        if (!this.isEqualsPinMode(pin, PinMode.ANALOG)) {\n            this.request('enableAnalogInput', pin, {pin}, true);\n        }\n        const analogPin = this.measureAnalogPin(pin);\n        switch (sensor) {\n            case \"joystickx\":\n            case \"joysticky\": {\n                const analogValue = this.getAnalogValue(pin, 512);\n                const value = analogValue >> 6;\n\n                if (value > 14) return 2;\n                else if (value > 9) return 1;\n                else if (value > 5) return 0;\n                else if (value > 1) return -1;\n                else return -2;\n            }\n            case \"light\": {\n                const analogValue = this.getAnalogValue(pin);\n                return parseInt(Math.round(analogValue * 0.1));\n            }\n            case \"dial\": {\n                const analogValue = this.getAnalogValue(pin);\n                return Math.round(analogValue * 0.1);\n            }\n            case \"akeypad\": {\n                const analogValue = this.getAnalogValue(pin);\n                if (analogValue >= 450) return 1;\n                else if (analogValue >= 390) return 2;\n                else if (analogValue >= 310) return 3;\n                else if (analogValue >= 200) return 4;\n                else if (analogValue >= 100) return 5;\n                else return 0;\n            }\n            case 'temperature': {\n                if (!this.state.rx.temperature[analogPin] || !this.state.rx.temperature[analogPin].enable) {\n                    this.request('enableTemperatureSensor', pin, {pin}, true);\n                }\n\n                if (this.state.rx.temperature[analogPin] && this.state.rx.temperature[analogPin].value) {\n                    return this.state.rx.temperature[analogPin].value;\n                }\n            } break;\n            case 'magnetic': {\n                const analogValue = this.getAnalogValue(pin, 512);\n\n                const zero = 512;\n                const zeroGap = 32;\n                const startS = zero + zeroGap;\n                const startN = zero - zeroGap;\n                const maxArea = 64;\n\n                let value = 0;\n                if (analogValue > startS) {\n                    value = (analogValue > 1024 - maxArea) ? 1024 - maxArea : analogValue;\n                    value = Math.min(10, parseInt(Math.round((value - startS) / 32)));\n                } else if (analogValue < startN) {\n                    value = (analogValue < maxArea) ? maxArea : analogValue;\n                    value = Math.min(10, parseInt(Math.round((startN - value) / 32))) * -1;\n                }\n                return value;\n            }\n            case 'rotaryposition': {\n                if (!this.state.rx.rotaryPosition[analogPin] || !this.state.rx.rotaryPosition[analogPin].enable) {\n                    this.request('enableRotaryPositionSensor', pin, {pin}, true);\n                }\n\n                if (this.state.rx.rotaryPosition[analogPin] && this.state.rx.rotaryPosition[analogPin].rotation) {\n                    return this.state.rx.rotaryPosition[analogPin].originAngle;\n                }\n            } break;\n        }\n        return 0;\n    }\n\n    compare_sensor_value (sprite, script) {\n        const value1 = this.get_sensor_value(sprite, script);\n        const symbol = script.getStringValue('SYMBOL');\n        const value2 = script.getStringValue('VALUE');\n\n        return this._compare(value1, value2, symbol);\n    }\n\n    get_rotary_position_sensor_value (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const analogPin = this.measureAnalogPin(pin);\n        const type = script.getStringValue('PROPERTY');\n\n        if (!this.state.rx.rotaryPosition[analogPin] || !this.state.rx.rotaryPosition[analogPin].enable) {\n            this.request('enableRotaryPositionSensor', pin, {pin}, true);\n        }\n\n        if (!this.state.rx.rotaryPosition[analogPin] || !this.state.rx.rotaryPosition[analogPin].rotation) return 0;\n\n        const obj = this.state.rx.rotaryPosition[analogPin];\n        let value = 0;\n        switch (type) {\n            case 'rotation': {\n                if (obj.isIntegerRotation) {\n                    value = parseInt(obj.rotation);\n                } else {\n                    value = obj.rotation;\n                }\n            } break;\n            case 'position': {\n                if (obj.isIntegerPosition) {\n                    value = parseInt(Math.round(obj.position));\n                } else {\n                    value = obj.position;\n                }\n            } break;\n            case 'angle': {\n                value = obj.angle;\n            } break;\n            case 'angle-origin': {\n                value = obj.originAngle;\n            } break;\n        }\n        return value;\n    }\n\n    reset_rotary_position_sensor (sprite, script) {\n        const pin = this.pinToNumber(script.getStringValue('PIN'));\n        const type = script.getStringValue('PROPERTY');\n        const value = script.getNumberValue('VALUE');\n\n        this.request('resetRotaryPositionSensor', pin, {pin, type, value});\n    }\n}\n\nclass Cast {\n    static toRgbColorObject (value) {\n        let color;\n        if (typeof value === 'string' && value.substring(0, 1) === '#') {\n            color = Color.hexToRgb(value);\n\n            // If the color wasn't *actually* a hex color, cast to black\n            if (!color) color = {r: 0, g: 0, b: 0};\n        } else {\n            color = Color.decimalToRgb(Cast.toNumber(value));\n            if (color.hasOwnProperty('a')) {\n                delete color.a;\n            }\n        }\n        return color;\n    }\n}\n\nclass Color {\n    static decimalToHex (decimal) {\n        if (decimal < 0) {\n            decimal += 0xFFFFFF + 1;\n        }\n        let hex = Number(decimal).toString(16);\n        hex = `#${'000000'.substr(0, 6 - hex.length)}${hex}`;\n        return hex;\n    }\n\n    static decimalToRgb (decimal) {\n        const a = (decimal >> 24) & 0xFF;\n        const r = (decimal >> 16) & 0xFF;\n        const g = (decimal >> 8) & 0xFF;\n        const b = decimal & 0xFF;\n        return {r: r, g: g, b: b, a: a > 0 ? a : 255};\n    }\n\n    static hexToRgb (hex) {\n        const shorthandRegex = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\n        hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);\n        const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n        return result ? {\n            r: parseInt(result[1], 16),\n            g: parseInt(result[2], 16),\n            b: parseInt(result[3], 16)\n        } : null;\n    }\n\n    static rgbToHex (rgb) {\n        return Color.decimalToHex(Color.rgbToDecimal(rgb));\n    }\n\n    static rgbToDecimal (rgb) {\n        return (rgb.r << 16) + (rgb.g << 8) + rgb.b;\n    }\n}\n\nmodule.exports = {ArduinoBase, PinMode, Cast, Color};\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_roborobo_cube.js",
    "content": "'use strict';\nconst {ArduinoBase, Cast} = require('./block_roborobo_base.js');\n\nclass Cube extends ArduinoBase {\n    constructor () {\n        super();\n\n        this.id = '10.4';\n        this.name = 'roborobo_cube';\n        this.url = 'http://www.roborobo.co.kr';\n        this.imageName = 'roborobo_cube.png';\n        this.title = {\n            ko: '큐브',\n            en: 'Cube',\n        };\n        this.blockMenuBlocks = this.getBlockMenuBlocks();\n    }\n\n    /**\n     * 언어 번역 사용을 위해 함수 형태로 유지\n     */\n    monitorTemplate () {\n        return {\n            //imgPath: 'hw/~~.png',\n            //width: 256,\n            //height: 256,\n            // 모니터 화면 상단에 차례대로 나열하는 값\n            listPorts: {\n                sensor_gesture: {name: Lang.Blocks.cube_sensor_gesture, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_proximity: {name: Lang.Blocks.cube_sensor_proximity, type: 'input', pos: {x: 0, y: 0, }},\n            },\n            // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n            ports: {},\n            mode: 'both',\n        };\n    }\n\n    getBlockMenuBlocks () {\n        return [\n            'cube_menu_digital_value',\n            'cube_menu_dotmatrix_row',\n            'cube_menu_proximity_level',\n\n            'cube_set_dot_state_of_dotmatrix',\n            'cube_set_dotmatrix_row',\n            //'cube_set_dotmatrix',\n            'cube_clear_dotmatrix',\n            'cube_play_piezobuzzer',\n            'cube_play_piezobuzzer_until_done',\n            'cube_set_sensor_mode',\n            'cube_get_sensor_value',\n            'cube_is_direction_detected_on_gesture_sensor',\n            'cube_is_proximity_sensor_detected',\n            'cube_compare_proximity_sensor_level',\n            'cube_is_tilted_in_direction',\n            'cube_is_shaken',\n            'cube_is_color_button_pressed',\n        ];\n    }\n\n    setLanguage () {\n        return {\n            ko: {\n                template: {\n                    cube_menu_digital_value: '%1',\n                    cube_menu_dotmatrix_row: '%1',\n                    cube_menu_proximity_level: '%1',\n\n                    cube_set_dot_state_of_dotmatrix: '도트 매트릭스 x: %1 y: %2 좌표를 %3 (으)로 정하기 %4',\n                    cube_set_dotmatrix_row: '도트 매트릭스 y: %1 행에 %2 %3 %4 %5 %6 %7 %8 그리기 %9',\n                    //cube_set_dotmatrix: '도트 매트릭스에 %1 그리기 %2',\n                    cube_clear_dotmatrix: '도트 매트릭스 모두 지우기 %1',\n                    cube_play_piezobuzzer: '스피커로 %1 옥타브 %2 음을 %3 초 소리내기 %4',\n                    cube_play_piezobuzzer_until_done: '스피커로 %1 옥타브 %2 음을 %3 초 소리내며 기다리기 %4',\n                    cube_set_sensor_mode: '센서 동작을 %1 (으)로 정하기 %2',\n                    cube_get_sensor_value: '%1 값',\n                    cube_is_direction_detected_on_gesture_sensor: '제스처 센서에 내 %1 방향 움직임이 %2 ?',\n                    cube_is_proximity_sensor_detected: '근접 센서가 %1 ?',\n                    cube_compare_proximity_sensor_level: '근접 센서 값 %1 %2',\n                    cube_is_tilted_in_direction: '큐브가 내 %1 방향으로 기울었는가?',\n                    cube_is_shaken: '큐브를 흔들었는가?',\n                    cube_is_color_button_pressed: '%1 색 버튼을 %2 ?',\n                },\n                Blocks: {\n                    cube_menu_digital_value_on: '켜기 (1)',\n                    cube_menu_digital_value_off: '끄기 (0)',\n\n                    cube_piezobuzzer_tone_c: '도',\n                    cube_piezobuzzer_tone_c_sharp: '도♯(레♭)',\n                    cube_piezobuzzer_tone_d: '레',\n                    cube_piezobuzzer_tone_d_sharp: '레♯(미♭)',\n                    cube_piezobuzzer_tone_e: '미',\n                    cube_piezobuzzer_tone_f: '파',\n                    cube_piezobuzzer_tone_f_sharp: '파♯(솔♭)',\n                    cube_piezobuzzer_tone_g: '솔',\n                    cube_piezobuzzer_tone_g_sharp: '솔♯(라♭)',\n                    cube_piezobuzzer_tone_a: '라',\n                    cube_piezobuzzer_tone_a_sharp: '라♯(시♭)',\n                    cube_piezobuzzer_tone_b: '시',\n\n                    cube_sensor_gesture: '제스처 센서',\n                    cube_sensor_proximity: '근접 센서',\n                    cube_sensor_unused: '사용하지 않기',\n\n                    cube_sensor_gesture_direction_up: '위쪽',\n                    cube_sensor_gesture_direction_right: '오른쪽',\n                    cube_sensor_gesture_direction_down: '아래쪽',\n                    cube_sensor_gesture_direction_left: '왼쪽',\n\n                    cube_sensor_tilted_direction_forward: '앞쪽',\n                    cube_sensor_tilted_direction_right: '오른쪽',\n                    cube_sensor_tilted_direction_backward: '뒤쪽',\n                    cube_sensor_tilted_direction_left: '왼쪽',\n\n                    cube_check_detected: '감지되었는가',\n                    cube_check_not_detected: '감지되지 않았는가',\n                    cube_check_pressed: '눌렀는가',\n                    cube_check_not_pressed: '누르지 않았는가',\n\n                    cube_sensor_color_red: '빨간색',\n                    cube_sensor_color_yellow: '노란색',\n                    cube_sensor_color_green: '초록색',\n                    cube_sensor_color_blue: '파란색',\n                },\n            },\n            en: {\n                template: {\n                    cube_menu_digital_value: '%1',\n                    cube_menu_dotmatrix_row: '%1',\n                    cube_menu_proximity_level: '%1',\n\n                    cube_set_dot_state_of_dotmatrix: 'set dot matrix X: %1  Y: %2  to %3 %4',\n                    cube_set_dotmatrix_row: 'draw %2 %3 %4 %5 %6 %7 %8 on dot matrix y:%1 column %9',\n                    //cube_set_dotmatrix: 'draw %1 on dotmatrix %2',\n                    cube_clear_dotmatrix: 'clear all dot matrix %1',\n                    cube_play_piezobuzzer: 'play %1 otave %2 note for %3 seconds through the speaker %4',\n                    cube_play_piezobuzzer_until_done: 'wait with speaker to play %1 otave %2 note for %3 seconds %4',\n                    cube_set_sensor_mode: 'set sensor action to %1 %2',\n                    cube_get_sensor_value: '%1 value',\n                    cube_is_direction_detected_on_gesture_sensor: '%1 direction movement is %2 on the gesture sensor?',\n                    cube_is_proximity_sensor_detected: 'is proximity sensor %1 ?',\n                    cube_compare_proximity_sensor_level: 'proximity sensor value %1 %2',\n                    cube_is_tilted_in_direction: 'is the cube tilted on my %1 ?',\n                    cube_is_shaken: 'did the cube shaken?',\n                    cube_is_color_button_pressed: '%1 color button %2 ?',\n                },\n                Blocks: {\n                    cube_menu_digital_value_on: 'on (1)',\n                    cube_menu_digital_value_off: 'off (0)',\n\n                    cube_piezobuzzer_tone_c: 'C',\n                    cube_piezobuzzer_tone_c_sharp: 'C♯(D♭)',\n                    cube_piezobuzzer_tone_d: 'D',\n                    cube_piezobuzzer_tone_d_sharp: 'D♯(E♭)',\n                    cube_piezobuzzer_tone_e: 'E',\n                    cube_piezobuzzer_tone_f: 'F',\n                    cube_piezobuzzer_tone_f_sharp: 'F♯(G♭)',\n                    cube_piezobuzzer_tone_g: 'G',\n                    cube_piezobuzzer_tone_g_sharp: 'G♯(A♭)',\n                    cube_piezobuzzer_tone_a: 'A',\n                    cube_piezobuzzer_tone_a_sharp: 'A♯(B♭)',\n                    cube_piezobuzzer_tone_b: 'B',\n\n                    cube_sensor_gesture: 'gesture sensor',\n                    cube_sensor_proximity: 'proximity sensor',\n                    cube_sensor_unused: 'unuse',\n\n                    cube_sensor_gesture_direction_up: 'up',\n                    cube_sensor_gesture_direction_right: 'right',\n                    cube_sensor_gesture_direction_down: 'down',\n                    cube_sensor_gesture_direction_left: 'left',\n\n                    cube_sensor_tilted_direction_forward: 'forward',\n                    cube_sensor_tilted_direction_right: 'right',\n                    cube_sensor_tilted_direction_backward: 'backward',\n                    cube_sensor_tilted_direction_left: 'left',\n\n                    cube_check_detected: 'detected',\n                    cube_check_not_detected: 'not detected',\n                    cube_check_pressed: 'pressed',\n                    cube_check_not_pressed: 'not pressed',\n\n                    cube_sensor_color_red: 'red',\n                    cube_sensor_color_yellow: 'yellow',\n                    cube_sensor_color_green: 'green',\n                    cube_sensor_color_blue: 'blue',\n                },\n            },\n        };\n    };\n\n    getBlocks () {\n        return {\n            cube_menu_digital_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_menu_digital_value_on, '1'],\n                            [Lang.Blocks.cube_menu_digital_value_off, '0'],\n\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    VALUE: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringValue('VALUE');\n                },\n            },\n            cube_menu_dotmatrix_row: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['0', '0'],\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    Y: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('Y');\n                },\n            },\n            cube_menu_proximity_level: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    LEVEL: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringValue('LEVEL');\n                },\n            },\n            cube_set_dot_state_of_dotmatrix: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'cube_menu_digital_value',\n                        },\n                        null,\n                    ],\n                    type: 'cube_set_dot_state_of_dotmatrix',\n                },\n                paramsKeyMap: {\n                    X: 0,\n                    Y: 1,\n                    STATE: 2,\n                },\n                class: 'looks_dot_matrix',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.set_dot_state_of_dotmatrix(sprite, script)\n            },\n            cube_set_dotmatrix_row: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'cube_menu_dotmatrix_row'\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        null,\n\n                    ],\n                    type: 'cube_set_dotmatrix_row',\n                },\n                paramsKeyMap: {\n                    Y: 0,\n                    X0: 1, X1: 2, X2: 3, X3: 4, X4: 5, X5: 6, X6: 7,\n                },\n                class: 'looks_dot_matrix',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.set_dotmatrix_row(sprite, script)\n            },\n            //cube_set_dotmatrix: {\n            //    color: EntryStatic.colorSet.block.default.HARDWARE,\n            //    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            //    skeleton: 'basic',\n            //    statements: [],\n            //    params: [\n            //        {\n            //            type: 'Dropdown',\n            //            options: [],\n            //            value: '',\n            //            fontSize: 11,\n            //            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n            //            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n            //        },\n            //        {\n            //            type: 'Indicator',\n            //            img: 'block_icon/hardware_icon.svg',\n            //            size: 12,\n            //        },\n            //    ],\n            //    events: {},\n            //    def: {\n            //        params: [\n            //            null,\n            //            null,\n            //        ],\n            //        type: 'cube_set_dotmatrix',\n            //    },\n            //    paramsKeyMap: {\n            //        MATRIX: 0\n            //    },\n            //    class: 'looks_dot_matrix',\n            //    isNotFor: ['roborobo_cube'],\n            //    func: (sprite, script) => this.set_dotmatrix(sprite, script)\n            //},\n            cube_clear_dotmatrix: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'cube_clear_dotmatrix',\n                },\n                paramsKeyMap: {},\n                class: 'looks_dot_matrix',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.clear_dotmatrix(sprite, script)\n            },\n            cube_play_piezobuzzer: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_piezobuzzer_tone_c, '0'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_c_sharp, '1'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_d, '2'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_d_sharp, '3'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_e, '4'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_f, '5'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_f_sharp, '6'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_g, '7'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_g_sharp, '8'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_a, '9'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_a_sharp, '10'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_b, '11'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0.5'],\n                        },\n                        null,\n\n                    ],\n                    type: 'cube_play_piezobuzzer',\n                },\n                paramsKeyMap: {\n                    OCTAVE: 0,\n                    NOTE: 1,\n                    DURATION: 2,\n                },\n                class: 'sound',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.play_piezobuzzer(sprite, script)\n            },\n            cube_play_piezobuzzer_until_done: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_piezobuzzer_tone_c, '0'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_c_sharp, '1'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_d, '2'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_d_sharp, '3'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_e, '4'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_f, '5'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_f_sharp, '6'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_g, '7'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_g_sharp, '8'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_a, '9'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_a_sharp, '10'],\n                            [Lang.Blocks.cube_piezobuzzer_tone_b, '11'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0.5'],\n                        },\n                        null,\n\n                    ],\n                    type: 'cube_play_piezobuzzer_until_done',\n                },\n                paramsKeyMap: {\n                    OCTAVE: 0,\n                    NOTE: 1,\n                    DURATION: 2,\n                },\n                class: 'sound',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.play_piezobuzzer_until_done(sprite, script)\n            },\n            cube_set_sensor_mode: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_sensor_gesture, 'gesture'],\n                            [Lang.Blocks.cube_sensor_proximity, 'proximity'],\n                            [Lang.Blocks.cube_sensor_unused, 'unused'],\n                        ],\n                        value: 'gesture',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                    ],\n                    type: 'cube_set_sensor_mode',\n                },\n                paramsKeyMap: {\n                    OPTION: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.set_sensor_mode(sprite, script),\n            },\n            cube_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_sensor_gesture, 'gesture'],\n                            [Lang.Blocks.cube_sensor_proximity, 'proximity'],\n                        ],\n                        value: 'gesture',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'cube_get_sensor_value',\n                },\n                paramsKeyMap: {\n                    SENSOR: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.get_sensor_value(sprite, script),\n            },\n            cube_is_direction_detected_on_gesture_sensor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_sensor_gesture_direction_up, 'up'],\n                            [Lang.Blocks.cube_sensor_gesture_direction_right, 'right'],\n                            [Lang.Blocks.cube_sensor_gesture_direction_down, 'down'],\n                            [Lang.Blocks.cube_sensor_gesture_direction_left, 'left'],\n                        ],\n                        value: 'up',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_check_detected, 'detected'],\n                            [Lang.Blocks.cube_check_not_detected, 'not-detected'],\n                        ],\n                        value: 'detected',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                    ],\n                    type: 'cube_is_direction_detected_on_gesture_sensor',\n                },\n                paramsKeyMap: {\n                    DIRECTION: 0,\n                    MODE: 1,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.is_direction_detected_on_gesture_sensor(sprite, script)\n            },\n            cube_is_proximity_sensor_detected: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_check_detected, 'detected'],\n                            [Lang.Blocks.cube_check_not_detected, 'not-detected'],\n                        ],\n                        value: 'detected',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'cube_is_proximity_sensor_detected',\n                },\n                paramsKeyMap: {\n                    MODE: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.is_proximity_sensor_detected(sprite, script)\n            },\n            cube_compare_proximity_sensor_level: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['＞', 'greater-than'],\n                            ['＝', 'equal'],\n                            ['＜', 'less-than'],\n                        ],\n                        value: 'greater-than',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'cube_menu_proximity_level',\n                        },\n                    ],\n                    type: 'cube_compare_proximity_sensor_level',\n                },\n                paramsKeyMap: {\n                    SYMBOL: 0,\n                    LEVEL: 1,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.compare_proximity_sensor_level(sprite, script),\n            },\n            cube_is_tilted_in_direction: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_sensor_tilted_direction_forward, 'forward'],\n                            [Lang.Blocks.cube_sensor_tilted_direction_right, 'right'],\n                            [Lang.Blocks.cube_sensor_tilted_direction_backward, 'backward'],\n                            [Lang.Blocks.cube_sensor_tilted_direction_left, 'left'],\n                        ],\n                        value: 'forward',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'cube_is_tilted_in_direction',\n                },\n                paramsKeyMap: {\n                    DIRECTION: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.is_tilted_in_direction(sprite, script),\n            },\n            cube_is_shaken: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'cube_is_shaken',\n                },\n                paramsKeyMap: {},\n                class: 'sensing',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.is_shaken(sprite, script),\n            },\n\n\n            cube_is_color_button_pressed: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_sensor_color_red, '#FF0000'],\n                            [Lang.Blocks.cube_sensor_color_yellow, '#FFEE00'],\n                            [Lang.Blocks.cube_sensor_color_green, '#00AA00'],\n                            [Lang.Blocks.cube_sensor_color_blue, '#0055FF'],\n                        ],\n                        value: '#FF0000',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.cube_check_pressed, 'detected'],\n                            [Lang.Blocks.cube_check_not_pressed, 'not-detected'],\n                        ],\n                        value: 'detected',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                    ],\n                    type: 'cube_is_color_button_pressed',\n                },\n                paramsKeyMap: {\n                    COLOR: 0,\n                    MODE: 1,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_cube'],\n                func: (sprite, script) => this.is_color_button_pressed(sprite, script),\n            },\n        };\n    }\n\n    setZero () {\n        super.setZero();\n    }\n\n    afterReceive (data) {\n        super.afterReceive(data);\n    }\n\n    afterSend () {\n        super.afterSend();\n    }\n\n    request (func, subkey, value, updateNow = false) {\n        super.request(func, subkey, value, updateNow);\n    }\n\n    resetState () {\n        super.resetState();\n    }\n\n    /**\n     * -----------------------------------block execute-----------------------------------\n     * 공통 사용 함수를 제외한 나머지 블록 동작을 작성\n     * -----------------------------------------------------------------------------------\n     */\n\n    set_dot_state_of_dotmatrix (sprite, script) {\n        const x = script.getNumberValue('X');\n        const y = script.getNumberValue('Y');\n        const state = script.getNumberValue('STATE');\n        if (x < 0 || x > 14 || y < 0 || y > 6) return script.callReturn();\n\n        this.request('setDotMatrix', null, {type: 'dot', x, y, dot: Math.min(1, Math.max(0, state)).toString()}, true);\n        return script.callReturn();\n    }\n\n    set_dotmatrix_row (sprite, script) {\n        const y = script.getNumberValue('Y');\n        if (y < 0 || y > 6) return script.callReturn();\n\n        let dots = '';\n        for (let i = 0; i < 7; i++) {\n            const value = script.getNumberValue('X' + i);\n            dots += Math.max(0, Math.min(1, value)).toString();\n        }\n\n        this.request('setDotMatrix', null, {type: 'row', y, dots}, true);\n        return script.callReturn();\n    }\n\n    set_dotmatrix (sprite, script) {\n        const example = script.getStringValue('MATRIX');\n        this.request('setDotMatrix', null, {type: 'all', dots: example}, true);\n        return script.callReturn();\n    }\n\n    clear_dotmatrix (sprite, script) {\n        const length = 7 * 7;\n        let dots = '';\n        for (let i = 0; i < length; i++) {dots += 0;}\n\n        this.request('setDotMatrix', null, {type: 'all', dots});\n        return script.callReturn();\n    }\n\n    play_piezobuzzer (sprite, script) {\n        const octave = script.getNumberValue('OCTAVE');\n        const duration = script.getNumberValue('DURATION');\n        let note = script.getNumberValue('NOTE');\n        note = (octave - 1) * 12 + note;\n\n        this.request('setPiezoBuzzer', null, {note, duration});\n        return script.callReturn();\n    }\n\n    play_piezobuzzer_until_done (sprite, script) {\n        if (script.executeState) {\n            const duration = (script.getNumberValue('DURATION') * 1000);\n            if (Date.now() - script.executeState.startTime > duration) {\n                return script.callReturn();\n            } else {\n                return script;\n            }\n        } else {\n            script.executeState = {startTime: Date.now()};\n            this.play_piezobuzzer(sprite, script);\n            return script;\n        }\n    }\n\n    set_sensor_mode (sprite, script) {\n        let optionNum = 0;\n        const option = script.getStringValue('OPTION');\n        if (option === 'gesture') {\n            optionNum = 3;\n        } else if (option === 'proximity') {\n            optionNum = 2;\n        }\n        this.request('setSensorMode', null, {option: optionNum});\n        return script.callReturn();\n    }\n\n    get_sensor_value (sprite, script) {\n        const sensor = script.getStringValue('SENSOR');\n        if (sensor === 'gesture') {\n            switch (this.state.rx.gesture) {\n                case 1: return 'RIGHT';\n                case 2: return 'DOWN';\n                case 4: return 'LEFT';\n                case 8: return 'UP';\n                default: return 'NONE';\n            }\n        } else if (sensor === 'proximity') {\n            let value = this._getProximitySensorValue();\n            if (value == 6) {\n                value = 'NONE';\n            }\n            return value;\n        }\n        return 0;\n    }\n\n    is_direction_detected_on_gesture_sensor (sprite, script) {\n        const direction = script.getStringValue('DIRECTION');\n        const mode = (script.getStringValue('MODE') === 'detected');\n        switch (this.state.rx.gesture) {\n            case 1: return (direction == 'right' && mode) || (direction != 'right' && !mode);\n            case 2: return (direction == 'down' && mode) || (direction != 'down' && !mode);\n            case 4: return (direction == 'left' && mode) || (direction != 'left' && !mode);\n            case 8: return (direction == 'up' && mode) || (direction != 'up' && !mode);\n            default: return (!mode);\n        }\n    }\n\n    is_proximity_sensor_detected (sprite, script) {\n        return this._getProximitySensorValue() < 6;\n    }\n\n    compare_proximity_sensor_level (sprite, script) {\n        const value1 = this._getProximitySensorValue();\n        if (value1 == 6) return false;\n\n        const value2 = script.getNumberValue('LEVEL');\n        const symbol = script.getStringValue('SYMBOL');\n        switch (symbol) {\n            case 'greater-than':\n                return value1 > value2;\n            case 'equal':\n                return value1 == value2;\n            case 'less-than':\n                return value1 < value2;\n        }\n        return false;\n    }\n\n    _getProximitySensorValue () {\n        const value = this.state.rx.proximity;\n        let result = 0; // not detected\n        if (value >= 255) {\n            result = 0;\n        } else if (value >= 115) {\n            result = 1;\n        } else if (value >= 50) {\n            result = 2;\n        } else if (value >= 30) {\n            result = 3;\n        } else if (value >= 15) {\n            result = 4;\n        } else if (value >= 8) {\n            result = 5;\n        } else {\n            result = 6;\n        }\n        return result;\n    }\n\n    is_tilted_in_direction (sprite, script) {\n        const reference = 35;\n        switch (script.getStringValue('DIRECTION')) {\n            case 'forward': return this.state.rx.gyro.angle.y >= reference;\n            case 'right': return this.state.rx.gyro.angle.x >= reference;\n            case 'backward': return this.state.rx.gyro.angle.y <= -reference;\n            case 'left': return this.state.rx.gyro.angle.x <= -reference;\n            default: return false;\n        }\n    }\n\n    is_shaken (sprite, script) {\n        return this.state.rx.gyro.shake == 1;\n    }\n\n    is_color_button_pressed (sprite, script) {\n        let isPressed = false;\n        switch (script.getStringValue('COLOR')) {\n            case '#FF0000': {\n                isPressed = this.state.rx.buttons.r;\n            } break;\n            case '#00AA00': {\n                isPressed = this.state.rx.buttons.g;\n            } break;\n            case '#0055FF': {\n                isPressed = this.state.rx.buttons.b;\n            } break;\n            case '#FFEE00': {\n                isPressed = this.state.rx.buttons.y;\n            } break;\n        }\n        const mode = (script.getStringValue('MODE') === 'detected');\n        return (mode && isPressed) || (!mode && !isPressed);\n    }\n}\n\nmodule.exports = new Cube();\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_roborobo_robokit_rs.js",
    "content": "'use strict';\nconst {ArduinoBase, PinMode} = require('./block_roborobo_base.js');\n\nclass RobokitRS extends ArduinoBase {\n    constructor () {\n        super();\n\n        this.id = '10.3';\n        this.name = 'roborobo_robokit_rs';\n        this.url = 'http://www.roborobo.co.kr';\n        this.imageName = 'roborobo_robokit_rs.png';\n        this.title = {\n            ko: '로보키트 RS',\n            en: 'Robokit RS',\n        }\n        this.blockMenuBlocks = this.getBlockMenuBlocks();\n    }\n\n    /**\n     * 언어 번역 사용을 위해 함수 형태로 유지\n     */\n    monitorTemplate () {\n        return {\n            //imgPath: 'hw/~~.png',\n            //width: 256,\n            //height: 256,\n            // 모니터 화면 상단에 차례대로 나열하는 값\n            listPorts: {\n                digital_2: {name: (Lang.Blocks.monitor_digital + ': 2'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_3: {name: (Lang.Blocks.monitor_digital + ': 3'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_4: {name: (Lang.Blocks.monitor_digital + ': 4'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_5: {name: (Lang.Blocks.monitor_digital + ': 5'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_6: {name: (Lang.Blocks.monitor_digital + ': 6'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_7: {name: (Lang.Blocks.monitor_digital + ': 7'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_8: {name: (Lang.Blocks.monitor_digital + ': 8'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_9: {name: (Lang.Blocks.monitor_digital + ': 9'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_10: {name: (Lang.Blocks.monitor_digital + ': 10'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_11: {name: (Lang.Blocks.monitor_digital + ': 11'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_12: {name: (Lang.Blocks.monitor_digital + ': 12'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_13: {name: (Lang.Blocks.monitor_digital + ': 13'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_0: {name: (Lang.Blocks.monitor_analog + ': A0'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_1: {name: (Lang.Blocks.monitor_analog + ': A1'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_2: {name: (Lang.Blocks.monitor_analog + ': A2'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_3: {name: (Lang.Blocks.monitor_analog + ': A3'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_4: {name: (Lang.Blocks.monitor_analog + ': A4'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_5: {name: (Lang.Blocks.monitor_analog + ': A5'), type: 'input', pos: {x: 0, y: 0, }},\n                sensor_gyroscope_angle_x: {name: Lang.Blocks.monitor_gyroscope_angle_x, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_gyroscope_angle_y: {name: Lang.Blocks.monitor_gyroscope_angle_y, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_gyroscope_angle_z: {name: Lang.Blocks.monitor_gyroscope_angle_z, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_gyroscope_gyro_x: {name: Lang.Blocks.monitor_gyroscope_x, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_gyroscope_gyro_y: {name: Lang.Blocks.monitor_gyroscope_y, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_gyroscope_gyro_z: {name: Lang.Blocks.monitor_gyroscope_z, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_gyroscope_shake: {name: Lang.Blocks.monitor_gyroscope_shake, type: 'input', pos: {x: 0, y: 0, }},\n            },\n            // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n            ports: {},\n            mode: 'both',\n        }\n    }\n\n    getBlockMenuBlocks () {\n        return [\n            'robokit_rs_menu_digital_pin',\n            'robokit_rs_menu_analog_pin',\n            'robokit_rs_menu_pin',\n            'robokit_rs_menu_digital_value',\n            'robokit_rs_menu_motor_number',\n\n            'robokit_rs_set_digital',\n            'robokit_rs_set_motor',\n            'robokit_rs_set_motors',\n            'robokit_rs_set_mecanumwheels',\n            'robokit_rs_set_servo_angle',\n            'robokit_rs_set_rgbled_color',\n            'robokit_rs_change_rgbled_brightness_by',\n            'robokit_rs_set_rgbled_brightness_to',\n            'robokit_rs_set_dot_state_of_dotmatrix',\n            'robokit_rs_set_dotmatrix_row',\n            'robokit_rs_set_dotmatrix',\n            'robokit_rs_clear_dotmatrix',\n            'robokit_rs_play_piezobuzzer',\n            'robokit_rs_play_piezobuzzer_until_done',\n            'robokit_rs_get_digital_value',\n            'robokit_rs_get_analog_value',\n            'robokit_rs_get_sensor_value',\n            'robokit_rs_is_digital_detected',\n            'robokit_rs_compare_analog_value',\n            'robokit_rs_compare_sensor_value',\n            'robokit_rs_get_gyro_sensor_value',\n            'robokit_rs_is_shaken_gyro_sensor',\n            'robokit_rs_reset_gyro_sensor',\n            'robokit_rs_get_rotary_position_sensor_value',\n            'robokit_rs_reset_rotary_position_sensor',\n        ];\n    }\n\n    setLanguage () {\n        return {\n            ko: {\n                template: {\n                    robokit_rs_menu_digital_pin: '%1',\n                    robokit_rs_menu_analog_pin: '%1',\n                    robokit_rs_menu_pin: '%1',\n                    robokit_rs_menu_digital_value: '%1',\n                    robokit_rs_menu_motor_number: '%1',\n                    robokit_rs_menu_dotmatrix_row: '%1',\n\n                    robokit_rs_set_digital: '%1 번 핀 디지털 값을 %2 (으)로 정하기 %3',\n                    robokit_rs_set_motor: '%1 번 모터를 속도 %2 (으)로 %3 %4',\n                    robokit_rs_set_motors: '%1 번 모터, 속도 %2, %3 (으)로 로봇을 %4 %5',\n                    robokit_rs_set_mecanumwheels: '메카넘 휠 로봇을 속도 %1 (으)로 %2 %3',\n                    robokit_rs_set_servo_angle: '%1 번 핀 서보 모터를 %2 도로 회전하기 %3',\n                    robokit_rs_set_rgbled_color: '%1 번 핀 RGB LED 색상을 %2 색으로 정하기 %3',\n                    robokit_rs_change_rgbled_brightness_by: '%1 번 핀 RGB LED 밝기를 %2 만큼 바꾸기 %3',\n                    robokit_rs_set_rgbled_brightness_to: '%1 번 핀 RGB LED 밝기를 %2 %로 정하기 %3',\n                    robokit_rs_set_dot_state_of_dotmatrix: '도트 매트릭스 x: %1 y: %2 좌표를 %3 (으)로 정하기 %4',\n                    robokit_rs_set_dotmatrix_row: '도트 매트릭스 y: %1 행에 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 그리기 %17',\n                    robokit_rs_set_dotmatrix: '도트 매트릭스에 %1 그리기 %2',\n                    robokit_rs_clear_dotmatrix: '도트 매트릭스 모두 지우기 %1',\n                    robokit_rs_play_piezobuzzer: '%1 번 핀 피에조 버저로 %2 옥타브 %3 음을 %4 초 소리내기 %5',\n                    robokit_rs_play_piezobuzzer_until_done: '%1 번 핀 피에조 버저로 %2 옥타브 %3 음을 %4 초 소리내며 기다리기 %5',\n                    robokit_rs_get_digital_value: '%1 번 핀 디지털 값',\n                    robokit_rs_get_analog_value: '%1 번 핀 아날로그 값',\n                    robokit_rs_get_sensor_value: '%1 번 핀 %2 값',\n                    robokit_rs_is_digital_detected: '%1 번 핀이 감지되었는가?',\n                    robokit_rs_compare_analog_value: '%1 번 핀 아날로그 값 %2 %3',\n                    robokit_rs_compare_sensor_value: '%1 번 핀 %2 값 %3 %4',\n                    robokit_rs_get_gyro_sensor_value: '자이로 센서 %1 값',\n                    robokit_rs_is_shaken_gyro_sensor: '자이로 센서를 흔들었는가?',\n                    robokit_rs_reset_gyro_sensor: '자이로 센서 기본 자세의 방향을 %1 정하기 %2',\n                    robokit_rs_get_rotary_position_sensor_value: '%1 번 핀 회전 위치 센서 %2 값',\n                    robokit_rs_reset_rotary_position_sensor: '%1 번 핀 회전 위치 센서 %2 값을 %3 (으)로 정하기 %4'\n                },\n                Blocks: {\n                    monitor_digital: '디지털',\n                    monitor_analog: '아날로그',\n                    monitor_gyroscope_angle_x: '자이로 센서 : 기울기 x',\n                    monitor_gyroscope_angle_y: '자이로 센서 : 기울기 y',\n                    monitor_gyroscope_angle_z: '자이로 센서 : 기울기 z',\n                    monitor_gyroscope_x: '자이로 센서 : 각속도 x',\n                    monitor_gyroscope_y: '자이로 센서 : 각속도 y',\n                    monitor_gyroscope_z: '자이로 센서 : 각속도 z',\n                    monitor_gyroscope_shake: '자이로 센서 : 흔들림',\n\n                    robokit_rs_motor_state_cw: '시계 방향 회전',\n                    robokit_rs_motor_state_ccw: '시계 반대 방향 회전',\n                    robokit_rs_motor_state_stop: '정지',\n\n                    robokit_rs_motors_state_forward: '앞으로 이동',\n                    robokit_rs_motors_state_backward: '뒤로 이동',\n                    robokit_rs_motors_state_turn_left: '왼쪽으로 회전',\n                    robokit_rs_motors_state_turn_right: '오른쪽으로 회전',\n                    robokit_rs_motors_state_stop: '정지',\n\n                    robokit_rs_mecanumwheels_state_0: '앞으로 이동',\n                    robokit_rs_mecanumwheels_state_180: '뒤로 이동',\n                    robokit_rs_mecanumwheels_state_270: '왼쪽으로 이동',\n                    robokit_rs_mecanumwheels_state_90: '오른쪽으로 이동',\n                    robokit_rs_mecanumwheels_state_45: '45도 방향으로 이동',\n                    robokit_rs_mecanumwheels_state_135: '135도 방향으로 이동',\n                    robokit_rs_mecanumwheels_state_315: '-45도 방향으로 이동',\n                    robokit_rs_mecanumwheels_state_225: '-135도 방향으로 이동',\n                    robokit_rs_mecanumwheels_state_cw: '시계 방향 회전',\n                    robokit_rs_mecanumwheels_state_ccw: '시계 반대 방향 회전',\n                    robokit_rs_mecanumwheels_state_stop: '정지',\n\n                    robokit_rs_dotmatrix_example_all: '모두',\n                    robokit_rs_dotmatrix_example_eighth_note: '8분 음표',\n                    robokit_rs_dotmatrix_example_sixteenth_note: '16분 음표',\n                    robokit_rs_dotmatrix_example_square: '네모',\n                    robokit_rs_dotmatrix_example_triangle: '세모',\n                    robokit_rs_dotmatrix_example_circle: '동그라미',\n                    robokit_rs_dotmatrix_example_heart: '하트',\n                    robokit_rs_dotmatrix_example_ga: '가',\n                    robokit_rs_dotmatrix_example_na: '나',\n                    robokit_rs_dotmatrix_example_speech_bubble: '말풍선',\n                    robokit_rs_dotmatrix_example_looking_at_top_right: '오른쪽 위 보기',\n                    robokit_rs_dotmatrix_example_looking_at_bottom_right: '오른쪽 아래 보기',\n                    robokit_rs_dotmatrix_example_looking_at_top_left: '왼쪽 위 보기',\n                    robokit_rs_dotmatrix_example_looking_at_bottom_left: '왼쪽 아래 보기',\n                    robokit_rs_dotmatrix_example_square_basic: '네모 기본',\n                    robokit_rs_dotmatrix_example_square_basic_2: '네모 기본2',\n                    robokit_rs_dotmatrix_example_square_square_eyes: '네모 네모 눈',\n                    robokit_rs_dotmatrix_example_square_surprised_mouth: '네모 놀란 입',\n                    robokit_rs_dotmatrix_example_big_round_eyes: '크고 둥근 눈',\n                    robokit_rs_dotmatrix_example_small_round_eyes: '작고 둥근 눈',\n                    robokit_rs_dotmatrix_example_wink_right_eye: '오른쪽 윙크',\n                    robokit_rs_dotmatrix_example_wink_left_eye: '왼쪽 윙크',\n                    robokit_rs_dotmatrix_example_eyebrow_eye_right: '오른쪽 눈썹 눈',\n                    robokit_rs_dotmatrix_example_eyebrow_eye_left: '왼쪽 눈썹 눈',\n                    robokit_rs_dotmatrix_example_expressionless: '무표정',\n                    robokit_rs_dotmatrix_example_cutie: '귀요미',\n                    robokit_rs_dotmatrix_example_cute: '깜찍이',\n                    robokit_rs_dotmatrix_example_small_eyes_smile: '작은 눈 웃는 표정',\n                    robokit_rs_dotmatrix_example_half_moon_shape_eyes: '반달 눈',\n                    robokit_rs_dotmatrix_example_half_moon_shape_eyes_smiling: '반달 눈 웃기',\n                    robokit_rs_dotmatrix_example_half_moon_shape_eyes_closed: '반달 눈 감기',\n                    robokit_rs_dotmatrix_example_sad_expression: '슬픈 표정',\n                    robokit_rs_dotmatrix_example_sullen: '시무룩',\n                    robokit_rs_dotmatrix_example_crying_eyes: '우는 눈',\n                    robokit_rs_dotmatrix_example_melancholy_look: '우울한 표정',\n                    robokit_rs_dotmatrix_example_angry_eyes: '화난 눈',\n                    robokit_rs_dotmatrix_example_o_shape_mouth: '오모양 입',\n                    robokit_rs_dotmatrix_example_yo_shape_mouth: '요모양 입',\n\n                    robokit_rs_piezobuzzer_tone_c: '도',\n                    robokit_rs_piezobuzzer_tone_c_sharp: '도♯(레♭)',\n                    robokit_rs_piezobuzzer_tone_d: '레',\n                    robokit_rs_piezobuzzer_tone_d_sharp: '레♯(미♭)',\n                    robokit_rs_piezobuzzer_tone_e: '미',\n                    robokit_rs_piezobuzzer_tone_f: '파',\n                    robokit_rs_piezobuzzer_tone_f_sharp: '파♯(솔♭)',\n                    robokit_rs_piezobuzzer_tone_g: '솔',\n                    robokit_rs_piezobuzzer_tone_g_sharp: '솔♯(라♭)',\n                    robokit_rs_piezobuzzer_tone_a: '라',\n                    robokit_rs_piezobuzzer_tone_a_sharp: '라♯(시♭)',\n                    robokit_rs_piezobuzzer_tone_b: '시',\n\n                    robokit_rs_sensor_temperutre: '온도 센서',\n                    robokit_rs_sensor_joystick_x: '조이스틱 x',\n                    robokit_rs_sensor_joystick_y: '조이스틱 y',\n                    robokit_rs_sensor_light: '빛 센서',\n                    robokit_rs_sensor_dial: '다이얼',\n                    robokit_rs_sensor_a_keypad: 'A 키패드',\n                    robokit_rs_sensor_rotaryposition: '회전 위치 센서',\n                    robokit_rs_sensor_magnetic: '자기 센서',\n                    robokit_rs_sensor_ultrasonic: '초음파 센서',\n\n                    robokit_rs_sensor_gyroscope_angle_x: '기울기 x',\n                    robokit_rs_sensor_gyroscope_angle_y: '기울기 y',\n                    robokit_rs_sensor_gyroscope_angle_z: '기울기 z',\n                    robokit_rs_sensor_gyroscope_x: '각속도 x',\n                    robokit_rs_sensor_gyroscope_y: '각속도 y',\n                    robokit_rs_sensor_gyroscope_z: '각속도 z',\n                    robokit_rs_sensor_gyroscope_shake: '흔들림',\n\n                    robokit_rs_sensor_gyroscope_direction_up: '위로',\n                    robokit_rs_sensor_gyroscope_direction_forward: '앞으로',\n                    robokit_rs_sensor_gyroscope_direction_right: '오른쪽으로',\n                    robokit_rs_sensor_gyroscope_direction_backward: '뒤로',\n                    robokit_rs_sensor_gyroscope_direction_left: '왼쪽으로',\n\n                    robokit_rs_sensor_rotaryposition_rotation: '회전',\n                    robokit_rs_sensor_rotaryposition_position: '위치',\n                    robokit_rs_sensor_rotaryposition_angle: '각도',\n                },\n            },\n            en: {\n                template: {\n                    robokit_rs_menu_digital_pin: '%1',\n                    robokit_rs_menu_analog_pin: '%1',\n                    robokit_rs_menu_pin: '%1',\n                    robokit_rs_menu_digital_value: '%1',\n                    robokit_rs_menu_motor_number: '%1',\n                    robokit_rs_menu_dotmatrix_row: '%1',\n\n                    robokit_rs_set_digital: 'set pin %1 digital value to %2 %3',\n                    robokit_rs_set_motor: 'set motor %1 speed to %2 %3 %4',\n                    robokit_rs_set_motors: '%4 a robot with motor %1 at speed %2 %3 %5',\n                    robokit_rs_set_mecanumwheels: 'mecanum wheel robot %1 at speed %2 %3',\n                    robokit_rs_set_servo_angle: 'rotate pin %1 servo motor to %2 degree %3',\n                    robokit_rs_set_rgbled_color: 'set %1 pin RGB LED color to the %2 color %3',\n                    robokit_rs_change_rgbled_brightness_by: 'change pin %1 RGB LED brightness by %2 %3',\n                    robokit_rs_set_rgbled_brightness_to: 'set pin %1 RGB LED brightness to %2 % %3',\n                    robokit_rs_set_dot_state_of_dotmatrix: 'set dot matrix X: %1  Y: %2  to %3 %4',\n                    robokit_rs_set_dotmatrix_row: 'draw %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 on dot matrix y:%1 column %17',\n                    robokit_rs_set_dotmatrix: 'draw %1 on dotmatrix %2',\n                    robokit_rs_clear_dotmatrix: 'clear all dot matrix %1',\n                    robokit_rs_play_piezobuzzer: 'play pin %1 peizo buzzer with %2 otave %3 note for %4 sec %5',\n                    robokit_rs_play_piezobuzzer_until_done: 'Play pin %1 peizo buzzer with %2 otave %3 note for %4 sec and wait %5',\n                    robokit_rs_get_digital_value: 'pin %1 digital value',\n                    robokit_rs_get_analog_value: 'pin %1 analog value',\n                    robokit_rs_get_sensor_value: 'pin %1 %2 value',\n                    robokit_rs_is_digital_detected: 'pin %1 detected?',\n                    robokit_rs_compare_analog_value: 'pin %1 analog value %2 %3',\n                    robokit_rs_compare_sensor_value: 'pin %1 %2 value %3 %4',\n                    robokit_rs_get_gyro_sensor_value: '%1 value of gyrosensor',\n                    robokit_rs_is_shaken_gyro_sensor: 'is gyrosensor shaken?',\n                    robokit_rs_reset_gyro_sensor: 'set basic position of gyrosensor %1 %2',\n                    robokit_rs_get_rotary_position_sensor_value: 'rotary position sensor of pin %1 %2 value',\n                    robokit_rs_reset_rotary_position_sensor: 'rotary position sensor of pin %1 set %2 value to %3 %4'\n                },\n                Blocks: {\n                    monitor_digital: 'Digital',\n                    monitor_analog: 'Analog',\n                    monitor_gyroscope_angle_x: 'Gyroscope sensor : angle x',\n                    monitor_gyroscope_angle_y: 'Gyroscope sensor : angle y',\n                    monitor_gyroscope_angle_z: 'Gyroscope sensor : angle z',\n                    monitor_gyroscope_x: 'Gyroscope sensor : angular velocity x',\n                    monitor_gyroscope_y: 'Gyroscope sensor : angular velocity y',\n                    monitor_gyroscope_z: 'Gyroscope sensor : angular velocity z',\n                    monitor_gyroscope_shake: 'Gyroscope sensor : shake',\n\n                    robokit_rs_motor_state_cw: 'rotate clockwise',\n                    robokit_rs_motor_state_ccw: 'rotate counterclockwise',\n                    robokit_rs_motor_state_stop: 'stop',\n\n                    robokit_rs_motors_state_forward: 'move forward',\n                    robokit_rs_motors_state_backward: 'move backword',\n                    robokit_rs_motors_state_turn_left: 'turn left',\n                    robokit_rs_motors_state_turn_right: 'turn right',\n                    robokit_rs_motors_state_stop: 'stop',\n\n                    robokit_rs_mecanumwheels_state_0: 'move forward',\n                    robokit_rs_mecanumwheels_state_180: 'move backward',\n                    robokit_rs_mecanumwheels_state_270: 'move left',\n                    robokit_rs_mecanumwheels_state_90: 'move right',\n                    robokit_rs_mecanumwheels_state_45: 'move 45 degree',\n                    robokit_rs_mecanumwheels_state_135: 'move 135 degree',\n                    robokit_rs_mecanumwheels_state_315: 'move -45 degree',\n                    robokit_rs_mecanumwheels_state_225: 'move -135 degree',\n                    robokit_rs_mecanumwheels_state_cw: 'rotate clockwise',\n                    robokit_rs_mecanumwheels_state_ccw: 'rotate counterclockwise',\n                    robokit_rs_mecanumwheels_state_stop: 'stop',\n\n                    robokit_rs_dotmatrix_example_all: 'all',\n                    robokit_rs_dotmatrix_example_eighth_note: 'eighth note',\n                    robokit_rs_dotmatrix_example_sixteenth_note: 'sixteenth note',\n                    robokit_rs_dotmatrix_example_square: 'square',\n                    robokit_rs_dotmatrix_example_triangle: 'triangle',\n                    robokit_rs_dotmatrix_example_circle: 'circle',\n                    robokit_rs_dotmatrix_example_heart: 'heart',\n                    robokit_rs_dotmatrix_example_ga: 'ga',\n                    robokit_rs_dotmatrix_example_ga: 'na',\n                    robokit_rs_dotmatrix_example_speech_bubble: 'speech bubble',\n                    robokit_rs_dotmatrix_example_looking_at_top_right: 'looking at top right',\n                    robokit_rs_dotmatrix_example_looking_at_bottom_right: 'looking at bottom right',\n                    robokit_rs_dotmatrix_example_looking_at_top_left: 'looking at top left',\n                    robokit_rs_dotmatrix_example_looking_at_bottom_left: 'looking at bottom left',\n                    robokit_rs_dotmatrix_example_square_basic: 'square basic',\n                    robokit_rs_dotmatrix_example_square_basic_2: 'square basic2',\n                    robokit_rs_dotmatrix_example_square_square_eyes: 'square square eyes',\n                    robokit_rs_dotmatrix_example_square_surprised_mouth: 'square surprised mouth',\n                    robokit_rs_dotmatrix_example_big_round_eyes: 'big round eyes',\n                    robokit_rs_dotmatrix_example_small_round_eyes: 'small round eyes',\n                    robokit_rs_dotmatrix_example_wink_right_eye: 'wink right eye',\n                    robokit_rs_dotmatrix_example_wink_left_eye: 'wink left eye',\n                    robokit_rs_dotmatrix_example_eyebrow_eye_right: 'eyebrow eye to the right',\n                    robokit_rs_dotmatrix_example_eyebrow_eye_left: 'eyebrow eye to the left',\n                    robokit_rs_dotmatrix_example_expressionless: 'expressionless',\n                    robokit_rs_dotmatrix_example_cutie: 'cutie',\n                    robokit_rs_dotmatrix_example_cute: 'cute',\n                    robokit_rs_dotmatrix_example_small_eyes_smile: 'small eyes smile',\n                    robokit_rs_dotmatrix_example_half_moon_shape_eyes: 'half moon shape eyes',\n                    robokit_rs_dotmatrix_example_half_moon_shape_eyes_smiling: 'half moon shape eyes smiling',\n                    robokit_rs_dotmatrix_example_half_moon_shape_eyes_closed: 'half moon shape eyes closed',\n                    robokit_rs_dotmatrix_example_sad_expression: 'sad expression',\n                    robokit_rs_dotmatrix_example_sullen: 'sullen',\n                    robokit_rs_dotmatrix_example_crying_eyes: 'crying eyes',\n                    robokit_rs_dotmatrix_example_melancholy_look: 'melancholy look',\n                    robokit_rs_dotmatrix_example_angry_eyes: 'angry eyes',\n                    robokit_rs_dotmatrix_example_o_shape_mouth: 'o shape mouth',\n                    robokit_rs_dotmatrix_example_yo_shape_mouth: 'yo shape mouth',\n\n                    robokit_rs_piezobuzzer_tone_c: 'C',\n                    robokit_rs_piezobuzzer_tone_c_sharp: 'C♯(D♭)',\n                    robokit_rs_piezobuzzer_tone_d: 'D',\n                    robokit_rs_piezobuzzer_tone_d_sharp: 'D♯(E♭)',\n                    robokit_rs_piezobuzzer_tone_e: 'E',\n                    robokit_rs_piezobuzzer_tone_f: 'F',\n                    robokit_rs_piezobuzzer_tone_f_sharp: 'F♯(G♭)',\n                    robokit_rs_piezobuzzer_tone_g: 'G',\n                    robokit_rs_piezobuzzer_tone_g_sharp: 'G♯(A♭)',\n                    robokit_rs_piezobuzzer_tone_a: 'A',\n                    robokit_rs_piezobuzzer_tone_a_sharp: 'A♯(B♭)',\n                    robokit_rs_piezobuzzer_tone_b: 'B',\n\n                    robokit_rs_sensor_temperutre: 'temperature sensor',\n                    robokit_rs_sensor_joystick_x: 'joystick x',\n                    robokit_rs_sensor_joystick_y: 'joystick y',\n                    robokit_rs_sensor_light: 'light sensor',\n                    robokit_rs_sensor_dial: 'dial',\n                    robokit_rs_sensor_a_keypad: 'A keypad',\n                    robokit_rs_sensor_rotaryposition: 'rotary position sensor',\n                    robokit_rs_sensor_magnetic: 'magnetic sensor',\n                    robokit_rs_sensor_ultrasonic: 'ultrasonic sensor',\n\n                    robokit_rs_sensor_gyroscope_angle_x: 'angle x',\n                    robokit_rs_sensor_gyroscope_angle_y: 'angle y',\n                    robokit_rs_sensor_gyroscope_angle_z: 'angle z',\n                    robokit_rs_sensor_gyroscope_x: 'angular velocity x',\n                    robokit_rs_sensor_gyroscope_y: 'angular velocity y',\n                    robokit_rs_sensor_gyroscope_z: 'angular velocity z',\n                    robokit_rs_sensor_gyroscope_shake: 'shake',\n\n                    robokit_rs_sensor_gyroscope_direction_up: 'up',\n                    robokit_rs_sensor_gyroscope_direction_forward: 'forward',\n                    robokit_rs_sensor_gyroscope_direction_right: 'right',\n                    robokit_rs_sensor_gyroscope_direction_backward: 'backward',\n                    robokit_rs_sensor_gyroscope_direction_left: 'left',\n\n                    robokit_rs_sensor_rotaryposition_rotation: 'rotation',\n                    robokit_rs_sensor_rotaryposition_position: 'position',\n                    robokit_rs_sensor_rotaryposition_angle: 'angle',\n                },\n            },\n        };\n    };\n\n    getBlocks () {\n        return {\n            robokit_rs_menu_digital_pin: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                            ['9', '9'],\n                            ['10', '10'],\n                            ['11', '11'],\n                            ['12', '12'],\n                            ['13', '13']\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('PIN');\n                },\n            },\n            robokit_rs_menu_analog_pin: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A0', '14'],\n                            ['A1', '15'],\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                        ],\n                        value: '14',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('PIN');\n                },\n            },\n            robokit_rs_menu_pin: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A0', '14'],\n                            ['A1', '15'],\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                            ['9', '9'],\n                            ['10', '10'],\n                            ['11', '11'],\n                            ['12', '12'],\n                            ['13', '13'],\n                        ],\n                        value: '14',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('PIN');\n                },\n            },\n            robokit_rs_menu_digital_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['0', '0'],\n                            ['1', '1'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    NUM: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('NUM');\n                },\n            },\n            robokit_rs_menu_motor_number: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    NUM: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('NUM');\n                },\n            },\n            robokit_rs_menu_dotmatrix_row: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['0', '0'],\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    Y: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('Y');\n                },\n            },\n            robokit_rs_set_digital: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    }\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin',\n                        },\n                        {\n                            type: 'robokit_rs_menu_digital_value',\n                        },\n                        null,\n                    ],\n                    type: 'robokit_rs_set_digital',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_digital(sprite, script),\n            },\n            robokit_rs_set_motor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_motor_state_cw, 'cw'],\n                            [Lang.Blocks.robokit_rs_motor_state_ccw, 'ccw'],\n                            [Lang.Blocks.robokit_rs_motor_state_stop, 'stop'],\n                        ],\n                        value: 'cw',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_motor_number'\n                        },\n                        {\n                            type: 'number',\n                            params: ['15'],\n                        },\n                        null,\n                        null,\n\n                    ],\n                    type: 'robokit_rs_set_motor',\n                },\n                paramsKeyMap: {\n                    MOTOR: 0,\n                    SPEED: 1,\n                    STATE: 2,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_motor(sprite, script)\n            },\n            robokit_rs_set_motors: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1, 2', '12'],\n                            ['3, 4', '34']\n                        ],\n                        value: '12',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_motors_state_forward, 'forward'],\n                            [Lang.Blocks.robokit_rs_motors_state_backward, 'backward'],\n                            [Lang.Blocks.robokit_rs_motors_state_turn_left, 'turn-left'],\n                            [Lang.Blocks.robokit_rs_motors_state_turn_right, 'turn-right'],\n                            [Lang.Blocks.robokit_rs_motors_state_stop, 'stop'],\n                        ],\n                        value: 'forward',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['15'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['15'],\n                        },\n                        null,\n                        null,\n\n                    ],\n                    type: 'robokit_rs_set_motors',\n                },\n                paramsKeyMap: {\n                    MOTORS: 0,\n                    SPEED1: 1,\n                    SPEED2: 2,\n                    STATE: 3,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_motors(sprite, script)\n            },\n            robokit_rs_set_mecanumwheels: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_0, '0'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_180, '180'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_270, '270'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_90, '90'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_45, '45'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_135, '135'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_315, '315'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_225, '225'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_cw, 'cw'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_ccw, 'ccw'],\n                            [Lang.Blocks.robokit_rs_mecanumwheels_state_stop, 'stop'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['15'],\n                        },\n                        null,\n                        null,\n\n                    ],\n                    type: 'robokit_rs_set_mecanumwheels',\n                },\n                paramsKeyMap: {\n                    SPEED: 0,\n                    STATE: 1,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_mecanumwheels(sprite, script)\n            },\n            robokit_rs_set_servo_angle: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin'\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        null,\n\n                    ],\n                    type: 'robokit_rs_set_servo_angle',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    ANGLE: 1,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_servo_angle(sprite, script)\n            },\n            robokit_rs_set_rgbled_color: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Color',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin'\n                        },\n                        null,\n                        null,\n\n                    ],\n                    type: 'robokit_rs_set_rgbled_color',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    COLOR: 1,\n                },\n                class: 'looks',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_rgbled_color(sprite, script)\n            },\n            robokit_rs_change_rgbled_brightness_by: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin'\n                        },\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n\n                    ],\n                    type: 'robokit_rs_change_rgbled_brightness_by',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    BRIGHTNESS: 1,\n                },\n                class: 'looks',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.change_rgbled_brightness_by(sprite, script)\n            },\n            robokit_rs_set_rgbled_brightness_to: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin'\n                        },\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                        null,\n\n                    ],\n                    type: 'robokit_rs_set_rgbled_brightness_to',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    BRIGHTNESS: 1,\n                },\n                class: 'looks',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_rgbled_brightness_to(sprite, script)\n            },\n            robokit_rs_set_dot_state_of_dotmatrix: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'robokit_rs_menu_digital_value',\n                        },\n                        null,\n                    ],\n                    type: 'robokit_rs_set_dot_state_of_dotmatrix',\n                },\n                paramsKeyMap: {\n                    X: 0,\n                    Y: 1,\n                    STATE: 2,\n                },\n                class: 'looks_dot_matrix',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_dot_state_of_dotmatrix(sprite, script)\n            },\n            robokit_rs_set_dotmatrix_row: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_dotmatrix_row'\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        null,\n\n                    ],\n                    type: 'robokit_rs_set_dotmatrix_row',\n                },\n                paramsKeyMap: {\n                    Y: 0,\n                    X0: 1, X1: 2, X2: 3, X3: 4, X4: 5, X5: 6, X6: 7, X7: 8, X8: 9, X9: 10, X10: 11, X11: 12, X12: 13, X13: 14, X14: 15, X15: 16,\n                },\n                class: 'looks_dot_matrix',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_dotmatrix_row(sprite, script)\n            },\n            robokit_rs_set_dotmatrix: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_all, '111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_eighth_note, '000000000000000000000011000000000000010100000000000010100000000001110100000000011110000000000001100000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_sixteenth_note, '000000001111000000000011001000000000010001000000000010011000000001110111000000011110111000000001100000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_square, '000111111111000000111111111000000110000011000000110000011000000110000011000000111111111000000111111111000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_triangle, '000000010000000000000111000000000001101100000000011000110000000110000011000001100000001100001111111111100'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_circle, '000001111100000000011000110000000110000011000000100000001000000110000011000000011000110000000001111100000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_heart, '000011000110000000111101111000001111111111100001111111111100000111111111000000001111100000000000010000000'],\n                            ['X', '000110000011000000011000110000000001111100000000000111000000000001111100000000011000110000000110000011000'],\n                            ['A', '000000111000000000001000100000000001000100000000001111100000000001000100000000001000100000000001000100000'],\n                            ['B', '000001111000000000001000100000000001000100000000001111100000000001000100000000001000100000000001111000000'],\n                            ['C', '000000111000000000001000100000000001000000000000001000000000000001000000000000001000100000000000111000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_ga, '000000000000000000011101000000000000101000000000000101100000000001001000000000000001000000000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_na, '000000000000000000010001000000000010001000000000010001100000000011101000000000000001000000000000000000000'],\n                            ['!', '000000010000000000000010000000000000010000000000000010000000000000010000000000000000000000000000010000000'],\n                            ['?', '000000111000000000001000100000000000000100000000000001000000000000010000000000000000000000000000010000000'],\n                            ['0', '000001111100000000001000100000000001000100000000001000100000000001000100000000001000100000000001111100000'],\n                            ['1', '000000010000000000000110000000000001010000000000000010000000000000010000000000000010000000000001111100000'],\n                            ['2', '000001111100000000000000100000000000000100000000001111100000000001000000000000001000000000000001111100000'],\n                            ['3', '000001111100000000000000100000000000000100000000001111100000000000000100000000000000100000000001111100000'],\n                            ['4', '000001000100000000001000100000000001000100000000001000100000000001111110000000000000100000000000000100000'],\n                            ['5', '000001111100000000001000000000000001000000000000001111100000000000000100000000000000100000000001111100000'],\n                            ['6', '000001111100000000001000000000000001000000000000001111100000000001000100000000001000100000000001111100000'],\n                            ['7', '000001111100000000001000100000000001000100000000000000100000000000000100000000000000100000000000000100000'],\n                            ['8', '000001111100000000001000100000000001000100000000001111100000000001000100000000001000100000000001111100000'],\n                            ['9', '000001111100000000001000100000000001000100000000001111100000000000000100000000000000100000000001111100000'],\n                            ['10', '000010001111100000110001000100001010001000100000010001000100000010001000100000010001000100001111101111100'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_speech_bubble, '111111111111111100000000000001100111111111001100000000000001111110011111111000010100000000000011000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_looking_at_top_right, '011111000111110111100101111001111100101111001111111101111111111111101111111111111101111111011111000111110'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_looking_at_bottom_right, '011111000111110111111101111111111111101111111111111101111111111100101111001111100101111001011111000111110'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_looking_at_top_left, '011111000111110100111101001111100111101001111111111101111111111111101111111111111101111111011111000111110'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_looking_at_bottom_left, '011111000111110111111101111111111111101111111111111101111111100111101001111100111101001111011111000111110'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_square_basic, '111111111111111100000000000001100100000001001100000000000001100111111111001100000000000001111111111111111'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_square_basic_2, '111111111111111100000000000001101111000111101100110000011001100110010011001100000000000001111111111111111'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_square_square_eyes, '111111111111111100000000000001101111000111101101001000100101101111010111101100000000000001111111111111111'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_square_surprised_mouth, '111111111111111100000000000001100100111001001100000101000001100000101000001100000111000001111111111111111'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_big_round_eyes, '001111000111100011111101111110011111101111110011111101111110011111101111110011111101111110001111000111100'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_small_round_eyes, '000000000000000001111000111100011111101111110011111101111110011111101111110001111000111100000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_wink_right_eye, '000000000000000001111000000000011111100000000011111100111100011111101111110001111000111100000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_wink_left_eye, '000000000000000000000000111100000000001111110001111001111110011111101111110001111000111100000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_eyebrow_eye_right, '111111000111111000000000000000111111000111111011101000111010011111000111110011110000011110000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_eyebrow_eye_left, '111111000111111000000000000000111111000111111010111000101110011111000111110011110000011110000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_expressionless, '000000000000000011111000111110000000000000000000111000111000000111000111000000111000111000000111000111000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_cutie, '000000000000000001110000011100001110000011100001010010010100001110010011100000000101000000000011000110000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_cute, '001000000000100000100000001000000010000010000000100000001000001000010000100000000000000000000111111111000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_small_eyes_smile, '000000000000000000100000001000000100000001000000000000000000001111111111100001111111111100000111111111000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_half_moon_shape_eyes, '000000000000000001111000111100011111101111110010000101000010000000000000000000000000000000000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_half_moon_shape_eyes_smiling, '001111000111100011111101111110010000101000010000000000000000001100000001100000110000011000000011111110000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_half_moon_shape_eyes_closed, '000000000000000000000000000000000000000000000010000101000010011111101111110001111000111100000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_sad_expression, '000000000000000000010000010000000100000001000001000000000100010110000011010000110000011000000110000011000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_sullen, '000000000000000001100000001100011110000011110011110000011110001100111001100000001111100000000011000110000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_crying_eyes, '000000000000000000000000000000011111000111110001010000010100001010000010100001010000010100000000000000000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_melancholy_look, '011111000111110001100000001100001100000001100000001111100000000011000110000000110000011000000100000001000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_angry_eyes, '100000000000001010000000000010001000000000100000100000001000011010000010110011001000100110011000000000110'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_o_shape_mouth, '000000000000000001100000001100011010000011010011110000011110001100010001100000000010000000000001111100000'],\n                            [Lang.Blocks.robokit_rs_dotmatrix_example_yo_shape_mouth, '000000000000000010001000100010010001000100010001110000011100000000000000000000000101000000000000111000000'],\n                            ['↑', '000000010000000000000111000000000001010100000000000010000000000000010000000000000010000000000000010000000'],\n                            ['↗', '000000011110000000000000110000000000001010000000000010010000000000100000000000001000000000000010000000000'],\n                            ['→', '000000000000000000000001000000000000000100000000011111110000000000000100000000000001000000000000000000000'],\n                            ['↘', '000010000000000000001000000000000000100000000000000010010000000000001010000000000000110000000000011110000'],\n                            ['↓', '000000010000000000000010000000000000010000000000000010000000000001010100000000000111000000000000010000000'],\n                            ['↙', '000000000010000000000000100000000000001000000000010010000000000010100000000000011000000000000011110000000'],\n                            ['←', '000000000000000000000100000000000001000000000000011111110000000001000000000000000100000000000000000000000'],\n                            ['↖', '000011110000000000011000000000000010100000000000010010000000000000001000000000000000100000000000000010000'],\n                        ],\n                        value: '111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                    ],\n                    type: 'robokit_rs_set_dotmatrix',\n                },\n                paramsKeyMap: {\n                    MATRIX: 0\n                },\n                class: 'looks_dot_matrix',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.set_dotmatrix(sprite, script)\n            },\n            robokit_rs_clear_dotmatrix: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'robokit_rs_clear_dotmatrix',\n                },\n                paramsKeyMap: {},\n                class: 'looks_dot_matrix',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.clear_dotmatrix(sprite, script)\n            },\n            robokit_rs_play_piezobuzzer: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_c, '0'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_c_sharp, '1'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_d, '2'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_d_sharp, '3'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_e, '4'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_f, '5'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_f_sharp, '6'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_g, '7'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_g_sharp, '8'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_a, '9'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_a_sharp, '10'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_b, '11'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin'\n                        },\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0.5'],\n                        },\n                        null,\n\n                    ],\n                    type: 'robokit_rs_play_piezobuzzer',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    OCTAVE: 1,\n                    NOTE: 2,\n                    DURATION: 3,\n                },\n                class: 'sound',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.play_piezobuzzer(sprite, script)\n            },\n            robokit_rs_play_piezobuzzer_until_done: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_c, '0'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_c_sharp, '1'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_d, '2'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_d_sharp, '3'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_e, '4'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_f, '5'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_f_sharp, '6'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_g, '7'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_g_sharp, '8'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_a, '9'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_a_sharp, '10'],\n                            [Lang.Blocks.robokit_rs_piezobuzzer_tone_b, '11'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin'\n                        },\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0.5'],\n                        },\n                        null,\n\n                    ],\n                    type: 'robokit_rs_play_piezobuzzer_until_done',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    OCTAVE: 1,\n                    NOTE: 2,\n                    DURATION: 3,\n                },\n                class: 'sound',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.play_piezobuzzer_until_done(sprite, script)\n            },\n            robokit_rs_get_digital_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin',\n                        },\n                    ],\n                    type: 'robokit_rs_get_digital_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.get_digital_value(sprite, script),\n            },\n            robokit_rs_get_analog_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_analog_pin',\n                        },\n                    ],\n                    type: 'robokit_rs_get_analog_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.get_analog_value(sprite, script),\n            },\n            robokit_rs_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_sensor_temperutre, 'temperature'],\n                            [Lang.Blocks.robokit_rs_sensor_joystick_x, 'joystickx'],\n                            [Lang.Blocks.robokit_rs_sensor_joystick_y, 'joysticky'],\n                            [Lang.Blocks.robokit_rs_sensor_light, 'light'],\n                            [Lang.Blocks.robokit_rs_sensor_dial, 'dial'],\n                            [Lang.Blocks.robokit_rs_sensor_a_keypad, 'akeypad'],\n                            [Lang.Blocks.robokit_rs_sensor_rotaryposition, 'rotaryposition'],\n                            [Lang.Blocks.robokit_rs_sensor_magnetic, 'magnetic'],\n                            [Lang.Blocks.robokit_rs_sensor_ultrasonic, 'ultrasonic'],\n                        ],\n                        value: 'temperature',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_pin',\n                        },\n                        null,\n                    ],\n                    type: 'robokit_rs_get_sensor_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    SENSOR: 1,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.get_sensor_value(sprite, script)\n            },\n            robokit_rs_is_digital_detected: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_digital_pin',\n                        },\n                    ],\n                    type: 'robokit_rs_is_digital_detected',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.is_digital_detected(sprite, script),\n            },\n            robokit_rs_compare_analog_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['>', 'greater-than'],\n                            ['=', 'equal'],\n                            ['<', 'less-than'],\n                        ],\n                        value: 'greater-than',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_analog_pin',\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['512'],\n                        },\n                    ],\n                    type: 'robokit_rs_compare_analog_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    SYMBOL: 1,\n                    VALUE: 2,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.compare_analog_value(sprite, script),\n            },\n            robokit_rs_compare_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_sensor_temperutre, 'temperature'],\n                            [Lang.Blocks.robokit_rs_sensor_joystick_x, 'joystickx'],\n                            [Lang.Blocks.robokit_rs_sensor_joystick_y, 'joysticky'],\n                            [Lang.Blocks.robokit_rs_sensor_light, 'light'],\n                            [Lang.Blocks.robokit_rs_sensor_dial, 'dial'],\n                            [Lang.Blocks.robokit_rs_sensor_a_keypad, 'akeypad'],\n                            [Lang.Blocks.robokit_rs_sensor_rotaryposition, 'rotaryposition'],\n                            [Lang.Blocks.robokit_rs_sensor_magnetic, 'magnetic'],\n                            [Lang.Blocks.robokit_rs_sensor_ultrasonic, 'ultrasonic'],\n                        ],\n                        value: 'temperature',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['>', 'greater-than'],\n                            ['=', 'equal'],\n                            ['<', 'less-than'],\n                        ],\n                        value: 'greater-than',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_pin',\n                        },\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                    ],\n                    type: 'robokit_rs_compare_sensor_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    SENSOR: 1,\n                    SYMBOL: 2,\n                    VALUE: 3,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.compare_sensor_value(sprite, script),\n            },\n            robokit_rs_get_gyro_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_angle_x, \"anglex\"],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_angle_y, \"angley\"],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_angle_z, \"anglez\"],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_x, \"gyrox\"],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_y, \"gyroy\"],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_z, \"gyroz\"],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_shake, \"shake\"]\n                        ],\n                        value: 'anglex',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                    ],\n                    type: 'robokit_rs_get_gyro_sensor_value',\n                },\n                paramsKeyMap: {\n                    PROPERTY: 0,\n                },\n                class: 'sensing_gyro_sensor',\n                isNotFor: ['roborobo_robokit_rs'],\n\n                func: (sprite, script) => this.get_gyro_sensor_value(sprite, script),\n            },\n            robokit_rs_is_shaken_gyro_sensor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [],\n                events: {},\n                def: {\n                    params: [],\n                    type: 'robokit_rs_is_shaken_gyro_sensor',\n                },\n                paramsKeyMap: {},\n                class: 'sensing_gyro_sensor',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.is_shaken_gyro_sensor(sprite, script)\n            },\n            robokit_rs_reset_gyro_sensor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_direction_up, 'up'],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_direction_forward, 'forward'],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_direction_right, 'right'],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_direction_backward, 'backward'],\n                            [Lang.Blocks.robokit_rs_sensor_gyroscope_direction_left, 'left']\n                        ],\n                        value: 'up',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                    ],\n                    type: 'robokit_rs_reset_gyro_sensor',\n                },\n                paramsKeyMap: {\n                    DIRECTION: 0,\n                },\n                class: 'sensing_gyro_sensor',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.reset_gyro_sensor(sprite, script)\n            },\n\n            robokit_rs_get_rotary_position_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_sensor_rotaryposition_rotation, 'rotation'],\n                            [Lang.Blocks.robokit_rs_sensor_rotaryposition_position, 'position'],\n                            [Lang.Blocks.robokit_rs_sensor_rotaryposition_angle, 'angle']\n                        ],\n                        value: 'rotation',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_analog_pin',\n                        },\n                        null,\n                    ],\n                    type: 'robokit_rs_get_rotary_position_sensor_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    PROPERTY: 1,\n                },\n                class: 'sensing_rotary_position_sensor',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.get_rotary_position_sensor_value(sprite, script)\n            },\n\n            robokit_rs_reset_rotary_position_sensor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robokit_rs_sensor_rotaryposition_rotation, 'rotation'],\n                            [Lang.Blocks.robokit_rs_sensor_rotaryposition_position, 'position'],\n                            [Lang.Blocks.robokit_rs_sensor_rotaryposition_angle, 'angle']\n                        ],\n                        value: 'rotation',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'robokit_rs_menu_analog_pin',\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        null,\n                    ],\n                    type: 'robokit_rs_reset_rotary_position_sensor',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    PROPERTY: 1,\n                    VALUE: 2,\n                },\n                class: 'sensing_rotary_position_sensor',\n                isNotFor: ['roborobo_robokit_rs'],\n                func: (sprite, script) => this.reset_rotary_position_sensor(sprite, script)\n            },\n        };\n    };\n\n    setZero () {\n        super.setZero();\n    }\n\n    afterReceive (data) {\n        super.afterReceive(data);\n    }\n\n    afterSend () {\n        super.afterSend();\n    }\n\n    request (func, subkey, value, updateNow = false) {\n        super.request(func, subkey, value, updateNow);\n    }\n\n     resetState () {\n        super.resetState();\n    }\n\n    /**\n     * -----------------------------------block execute-----------------------------------\n     * 공통 사용 함수를 제외한 나머지 블록 동작을 작성\n     * -----------------------------------------------------------------------------------\n     */\n\n    set_mecanumwheels (sprite, script) {\n        const speed = script.getNumberValue('SPEED');\n        const state = script.getStringValue('STATE');\n\n        let data = []\n        for (let i = 0; i < 4; i++) {\n            data[i] = {motor: i + 1, speed: speed, state: 0}\n        }\n\n        switch (state) {\n            case '0': {\n                data[0].state = 2;\n                data[1].state = 1;\n                data[2].state = 2;\n                data[3].state = 1;\n            }\n                break;\n            case '45': {\n                data[0].state = 2;\n                data[3].state = 1;\n            }\n                break;\n            case '90': {\n                data[0].state = 2;\n                data[1].state = 2;\n                data[2].state = 1;\n                data[3].state = 1;\n            }\n                break;\n            case '135': {\n                data[1].state = 2;\n                data[2].state = 1;\n            }\n                break;\n            case '180': {\n                data[0].state = 1;\n                data[1].state = 2;\n                data[2].state = 1;\n                data[3].state = 2;\n            }\n                break;\n            case '225': {\n                data[0].state = 1;\n                data[3].state = 2;\n            }\n                break;\n            case '270': {\n                data[0].state = 1;\n                data[1].state = 1;\n                data[2].state = 2;\n                data[3].state = 2;\n            }\n                break;\n            case '315': {\n                data[1].state = 1;\n                data[2].state = 2;\n            }\n                break;\n            case 'cw': {\n                data[0].state = 2;\n                data[1].state = 2;\n                data[2].state = 2;\n                data[3].state = 2;\n            }\n                break;\n            case 'ccw': {\n                data[0].state = 1;\n                data[1].state = 1;\n                data[2].state = 1;\n                data[3].state = 1;\n            }\n                break;\n            case 'stop':\n                break;\n        }\n\n        for (let i = 0; i < 4; i++) {\n            this.request('setMotor', i + 1, data[i]);\n        }\n        return script.callReturn();\n    }\n\n    set_dot_state_of_dotmatrix (sprite, script) {\n        const x = script.getNumberValue('X');\n        const y = script.getNumberValue('Y');\n        const state = script.getNumberValue('STATE');\n        if (x < 0 || x > 14 || y < 0 || y > 6) return script.callReturn();\n\n        this.request('setDotMatrix', null, {type: 'dot', x, y, dot: Math.min(1, Math.max(0, state)).toString()}, true);\n        return script.callReturn();\n    }\n\n    set_dotmatrix_row (sprite, script) {\n        const y = script.getNumberValue('Y');\n        if (y < 0 || y > 6) return script.callReturn();\n\n        let dots = '';\n        for (let i = 0; i < 16; i++) {\n            const value = script.getNumberValue('X' + i);\n            dots += Math.max(0, Math.min(1, value)).toString();\n        }\n\n        this.request('setDotMatrix', null, {type: 'row', y, dots}, true);\n        return script.callReturn();\n    }\n\n    set_dotmatrix (sprite, script) {\n        const example = script.getStringValue('MATRIX')\n        this.request('setDotMatrix', null, {type: 'all', dots: example}, true);\n        return script.callReturn();\n    }\n\n    clear_dotmatrix (sprite, script) {\n        const length = 15 * 7;\n        let dots = '';\n        for (let i = 0; i < length; i++) {dots += 0;}\n\n        this.request('setDotMatrix', null, {type: 'all', dots});\n        return script.callReturn();\n    }\n\n    get_gyro_sensor_value (sprite, script) {\n        const type = script.getStringValue('PROPERTY');\n\n        const obj = this.state.rx.gyro;\n        if (!this.isEqualsPinMode(18, PinMode.I2C) || !this.isEqualsPinMode(19, PinMode.I2C) || !obj || !obj.enable) {\n            this.request('enableGyroSensor', null, null, true);\n        }\n\n        if (!obj) return 0;\n        switch (type) {\n            case 'anglex': return obj.angle.x;\n            case 'angley': return obj.angle.y;\n            case 'anglez': return obj.angle.z;\n            case 'gyrox': return obj.gyro.x;\n            case 'gyroy': return obj.gyro.y;\n            case 'gyroz': return obj.gyro.z;\n            case 'shake': return obj.shake;\n            default: return 0;\n        }\n    }\n\n    is_shaken_gyro_sensor (sprite, script) {\n        const obj = this.state.rx.gyro;\n\n        if (!this.isEqualsPinMode(18, PinMode.I2C) || !this.isEqualsPinMode(19, PinMode.I2C) || !obj || !obj.enable) {\n            this.request('enableGyroSensor', null, null, true);\n        }\n\n        return obj ? obj.shake == 1 : false;\n    }\n\n    reset_gyro_sensor (sprite, script) {\n        const dir = script.getStringValue('DIRECTION');\n        let dirNum = 0;\n        switch (dir) {\n            case 'up':\n                dirNum = 0;\n                break;\n            case 'forward':\n                dirNum = 1;\n                break;\n            case 'right':\n                dirNum = 2;\n                break;\n            case 'backward':\n                dirNum = 3;\n                break;\n            case 'left':\n                dirNum = 4;\n                break;\n        }\n        this.request('resetGyroSensor', null, {direction: dirNum}, true);\n        return new Promise(resolve => setTimeout(() => resolve(), 500));\n    }\n}\n\nmodule.exports = new RobokitRS();"
  },
  {
    "path": "src/playground/blocks/hardware/block_roborobo_roduino.js",
    "content": "'use strict';\nconst {ArduinoBase} = require('./block_roborobo_base.js');\n\nclass Roduino extends ArduinoBase {\n    constructor () {\n        super();\n\n        this.id = '10.1';\n        this.name = 'roborobo_roduino';\n        this.url = 'http://www.roborobo.co.kr';\n        this.imageName = 'roborobo_roduino.png';\n        this.title = {\n            ko: '로두이노',\n            en: 'Roduino',\n        }\n        this.blockMenuBlocks = this.getBlockMenuBlocks();\n    }\n\n    /**\n     * 언어 번역 사용을 위해 함수 형태로 유지\n     */\n    monitorTemplate () {\n        return {\n            //imgPath: 'hw/~~.png',\n            //width: 256,\n            //height: 256,\n            // 모니터 화면 상단에 차례대로 나열하는 값\n            listPorts: {\n                digital_2: {name: (Lang.Blocks.monitor_digital + ': 2'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_3: {name: (Lang.Blocks.monitor_digital + ': 3'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_4: {name: (Lang.Blocks.monitor_digital + ': 4'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_5: {name: (Lang.Blocks.monitor_digital + ': 5'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_6: {name: (Lang.Blocks.monitor_digital + ': 6'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_7: {name: (Lang.Blocks.monitor_digital + ': 7'), type: 'input', pos: {x: 0, y: 0, }},\n                digital_8: {name: (Lang.Blocks.monitor_digital + ': 8'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_0: {name: (Lang.Blocks.monitor_analog + ': A0'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_1: {name: (Lang.Blocks.monitor_analog + ': A1'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_2: {name: (Lang.Blocks.monitor_analog + ': A2'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_3: {name: (Lang.Blocks.monitor_analog + ': A3'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_4: {name: (Lang.Blocks.monitor_analog + ': A4'), type: 'input', pos: {x: 0, y: 0, }},\n                analog_5: {name: (Lang.Blocks.monitor_analog + ': A5'), type: 'input', pos: {x: 0, y: 0, }},\n            },\n            // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n            ports: {},\n            mode: 'both',\n        }\n    }\n\n    getBlockMenuBlocks () {\n        return [\n            'roduino_menu_digital_pin',\n            'roduino_menu_analog_pin',\n            'roduino_menu_pin',\n            'roduino_menu_digital_value',\n            'roduino_menu_motor_number',\n\n            'roduino_set_digital',\n            'roduino_set_motor_rotation',\n            'roduino_set_rgbled_color',\n            'roduino_change_rgbled_brightness_by',\n            'roduino_set_rgbled_brightness_to',\n            'roduino_play_piezobuzzer',\n            'roduino_play_piezobuzzer_until_done',\n            'roduino_get_digital_value',\n            'roduino_get_analog_value',\n            'roduino_get_sensor_value',\n            'roduino_is_digital_detected',\n            'roduino_compare_analog_value',\n            'roduino_compare_sensor_value',\n            'roduino_get_rotary_position_sensor_value',\n            'roduino_reset_rotary_position_sensor',\n            'roduino_get_color_sensor_detected_value',\n            'roduino_is_color_sensor_detected',\n            'roduino_set_color_sensor_pins',\n        ];\n    }\n\n    setLanguage () {\n        return {\n            ko: {\n                template: {\n                    roduino_menu_digital_pin: '%1',\n                    roduino_menu_analog_pin: '%1',\n                    roduino_menu_pin: '%1',\n                    roduino_menu_digital_value: '%1',\n                    roduino_menu_motor_number: '%1',\n\n                    roduino_set_digital: '%1 번 핀 디지털 값을 %2 (으)로 정하기 %3',\n                    roduino_set_motor_rotation: '%1 번 모터를 %2 하기 %3',\n                    roduino_set_rgbled_color: '%1 번 핀 RGB LED 색상을 %2 색으로 정하기 %3',\n                    roduino_change_rgbled_brightness_by: '%1 번 핀 RGB LED 밝기를 %2 만큼 바꾸기 %3',\n                    roduino_set_rgbled_brightness_to: '%1 번 핀 RGB LED 밝기를 %2 %로 정하기 %3',\n                    roduino_play_piezobuzzer: '%1 번 핀 피에조 버저로 %2 옥타브 %3 음을 %4 초 소리내기 %5',\n                    roduino_play_piezobuzzer_until_done: '%1 번 핀 피에조 버저로 %2 옥타브 %3 음을 %4 초 소리내며 기다리기 %5',\n                    roduino_get_digital_value: '%1 번 핀 디지털 값',\n                    roduino_get_analog_value: '%1 번 핀 아날로그 값',\n                    roduino_get_sensor_value: '%1 번 핀 %2 값',\n                    roduino_is_digital_detected: '%1 번 핀이 감지되었는가?',\n                    roduino_compare_analog_value: '%1 번 핀 아날로그 값 %2 %3',\n                    roduino_compare_sensor_value: '%1 번 핀 %2 값 %3 %4',\n                    roduino_get_rotary_position_sensor_value: '%1 번 핀 회전 위치 센서 %2 값',\n                    roduino_reset_rotary_position_sensor: '%1 번 핀 회전 위치 센서 %2 값을 %3 (으)로 정하기 %4',\n                    roduino_get_color_sensor_detected_value: '%1 감지 값',\n                    roduino_is_color_sensor_detected: '%1 이 감지되었는가?',\n                    roduino_set_color_sensor_pins: '컬러 센서 핀을 R: %1 G: %2 B: %3 번으로 정하기 %4',\n                },\n                Blocks: {\n                    monitor_digital: '디지털',\n                    monitor_analog: '아날로그',\n\n                    roduino_motor_state_cw: '시계 방향 회전',\n                    roduino_motor_state_ccw: '시계 반대 방향 회전',\n                    roduino_motor_state_stop: '정지',\n\n                    roduino_piezobuzzer_tone_c: '도',\n                    roduino_piezobuzzer_tone_c_sharp: '도♯(레♭)',\n                    roduino_piezobuzzer_tone_d: '레',\n                    roduino_piezobuzzer_tone_d_sharp: '레♯(미♭)',\n                    roduino_piezobuzzer_tone_e: '미',\n                    roduino_piezobuzzer_tone_f: '파',\n                    roduino_piezobuzzer_tone_f_sharp: '파♯(솔♭)',\n                    roduino_piezobuzzer_tone_g: '솔',\n                    roduino_piezobuzzer_tone_g_sharp: '솔♯(라♭)',\n                    roduino_piezobuzzer_tone_a: '라',\n                    roduino_piezobuzzer_tone_a_sharp: '라♯(시♭)',\n                    roduino_piezobuzzer_tone_b: '시',\n\n                    roduino_sensor_temperutre: '온도 센서',\n                    roduino_sensor_joystick_x: '조이스틱 x',\n                    roduino_sensor_joystick_y: '조이스틱 y',\n                    roduino_sensor_light: '빛 센서',\n                    roduino_sensor_dial: '다이얼',\n                    roduino_sensor_a_keypad: 'A 키패드',\n                    roduino_sensor_rotaryposition: '회전 위치 센서',\n                    roduino_sensor_magnetic: '자기 센서',\n                    roduino_sensor_ultrasonic: '초음파 센서',\n\n                    roduino_sensor_rotaryposition_rotation: '회전',\n                    roduino_sensor_rotaryposition_position: '위치',\n                    roduino_sensor_rotaryposition_angle: '각도',\n\n                    roduino_sensor_color_red: '빨간색',\n                    roduino_sensor_color_yellow: '노란색',\n                    roduino_sensor_color_green: '초록색',\n                    roduino_sensor_color_blue: '파란색',\n                },\n            },\n            en: {\n                template: {\n                    roduino_menu_digital_pin: '%1',\n                    roduino_menu_analog_pin: '%1',\n                    roduino_menu_pin: '%1',\n                    roduino_menu_digital_value: '%1',\n                    roduino_menu_motor_number: '%1',\n\n                    roduino_set_digital: 'set pin %1 digital value to %2 %3',\n                    roduino_set_motor_rotation: 'set %1 the %2 motor %3',\n                    roduino_set_rgbled_color: 'set %1 pin RGB LED color to the %2 color %3',\n                    roduino_change_rgbled_brightness_by: 'change pin %1 RGB LED brightness by %2 %3',\n                    roduino_set_rgbled_brightness_to: 'set pin %1 RGB LED brightness to %2 % %3',\n                    roduino_play_piezobuzzer: 'Play pin %1 peizo buzzer with %2 otave %3 note for %4 sec %5',\n                    roduino_play_piezobuzzer_until_done: 'Play pin %1 peizo buzzer with %2 otave %3 note for %4 sec and wait %5',\n                    roduino_get_digital_value: 'pin %1 digital value',\n                    roduino_get_analog_value: 'pin %1 analog value',\n                    roduino_get_sensor_value: 'pin %1 %2 value',\n                    roduino_is_digital_detected: 'pin %1 detected?',\n                    roduino_compare_analog_value: 'pin %1 analog value %2 %3',\n                    roduino_compare_sensor_value: 'pin %1 %2 value %3 %4',\n                    roduino_get_rotary_position_sensor_value: 'rotary position sensor of pin %1 %2 value',\n                    roduino_reset_rotary_position_sensor: 'rotary position sensor of pin %1 set %2 value to %3 %4',\n                    roduino_get_color_sensor_detected_value: '%1 detection value',\n                    roduino_is_color_sensor_detected: 'is %1 detected?',\n                    roduino_set_color_sensor_pins: 'set color sensor pins to R: %1 G: %2 B: %3 %4',\n                },\n                Blocks: {\n                    monitor_digital: 'Digital',\n                    monitor_analog: 'Analog',\n\n                    roduino_motor_state_cw: 'rotate clockwise',\n                    roduino_motor_state_ccw: 'rotate counterclockwise',\n                    roduino_motor_state_stop: 'stop',\n\n                    roduino_piezobuzzer_tone_c: 'C',\n                    roduino_piezobuzzer_tone_c_sharp: 'C♯(D♭)',\n                    roduino_piezobuzzer_tone_d: 'D',\n                    roduino_piezobuzzer_tone_d_sharp: 'D♯(E♭)',\n                    roduino_piezobuzzer_tone_e: 'E',\n                    roduino_piezobuzzer_tone_f: 'F',\n                    roduino_piezobuzzer_tone_f_sharp: 'F♯(G♭)',\n                    roduino_piezobuzzer_tone_g: 'G',\n                    roduino_piezobuzzer_tone_g_sharp: 'G♯(A♭)',\n                    roduino_piezobuzzer_tone_a: 'A',\n                    roduino_piezobuzzer_tone_a_sharp: 'A♯(B♭)',\n                    roduino_piezobuzzer_tone_b: 'B',\n\n                    roduino_sensor_temperutre: 'temperature sensor',\n                    roduino_sensor_joystick_x: 'joystick x',\n                    roduino_sensor_joystick_y: 'joystick y',\n                    roduino_sensor_light: 'light sensor',\n                    roduino_sensor_dial: 'dial',\n                    roduino_sensor_a_keypad: 'A keypad',\n                    roduino_sensor_rotaryposition: 'rotary position sensor',\n                    roduino_sensor_magnetic: 'magnetic sensor',\n                    roduino_sensor_ultrasonic: 'ultrasonic sensor',\n\n                    roduino_sensor_rotaryposition_rotation: 'rotation',\n                    roduino_sensor_rotaryposition_position: 'position',\n                    roduino_sensor_rotaryposition_angle: 'angle',\n\n                    roduino_sensor_color_red: 'red',\n                    roduino_sensor_color_yellow: 'yellow',\n                    roduino_sensor_color_green: 'green',\n                    roduino_sensor_color_blue: 'blue',\n                },\n            },\n        };\n    };\n\n    getBlocks () {\n        return {\n            roduino_menu_digital_pin: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '2',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('PIN');\n                },\n            },\n            roduino_menu_analog_pin: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A0', '14'],\n                            ['A1', '15'],\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                        ],\n                        value: '14',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('PIN');\n                },\n            },\n            roduino_menu_pin: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['A0', '14'],\n                            ['A1', '15'],\n                            ['A2', '16'],\n                            ['A3', '17'],\n                            ['A4', '18'],\n                            ['A5', '19'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '14',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('PIN');\n                },\n            },\n            roduino_menu_digital_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['0', '0'],\n                            ['1', '1'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    NUM: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('NUM');\n                },\n            },\n            roduino_menu_motor_number: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2']\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [null],\n                },\n                paramsKeyMap: {\n                    NUM: 0,\n                },\n                func: (sprite, script) => {\n                    return script.getStringField('NUM');\n                },\n            },\n            roduino_set_digital: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    }\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin',\n                        },\n                        {\n                            type: 'roduino_menu_digital_value',\n                        },\n                        null,\n                    ],\n                    type: 'roduino_set_digital',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    VALUE: 1,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.set_digital(sprite, script),\n            },\n            roduino_set_motor_rotation: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_motor_state_cw, 'cw'],\n                            [Lang.Blocks.roduino_motor_state_ccw, 'ccw'],\n                            [Lang.Blocks.roduino_motor_state_stop, 'stop'],\n                        ],\n                        value: 'cw',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_motor_number'\n                        },\n                        null,\n                        null,\n\n                    ],\n                    type: 'roduino_set_motor_rotation',\n                },\n                paramsKeyMap: {\n                    MOTOR: 0,\n                    STATE: 1,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.set_motor_rotation(sprite, script)\n            },\n            roduino_set_rgbled_color: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Color',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin'\n                        },\n                        null,\n                        null,\n\n                    ],\n                    type: 'roduino_set_rgbled_color',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    COLOR: 1,\n                },\n                class: 'looks',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.set_rgbled_color(sprite, script)\n            },\n            roduino_change_rgbled_brightness_by: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin'\n                        },\n                        {\n                            type: 'number',\n                            params: ['10'],\n                        },\n                        null,\n\n                    ],\n                    type: 'roduino_change_rgbled_brightness_by',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    BRIGHTNESS: 1,\n                },\n                class: 'looks',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.change_rgbled_brightness_by(sprite, script)\n            },\n            roduino_set_rgbled_brightness_to: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin'\n                        },\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                        null,\n\n                    ],\n                    type: 'roduino_set_rgbled_brightness_to',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    BRIGHTNESS: 1,\n                },\n                class: 'looks',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.set_rgbled_brightness_to(sprite, script)\n            },\n            roduino_play_piezobuzzer: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_piezobuzzer_tone_c, '0'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_c_sharp, '1'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_d, '2'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_d_sharp, '3'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_e, '4'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_f, '5'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_f_sharp, '6'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_g, '7'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_g_sharp, '8'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_a, '9'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_a_sharp, '10'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_b, '11'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin'\n                        },\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0.5'],\n                        },\n                        null,\n\n                    ],\n                    type: 'roduino_play_piezobuzzer',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    OCTAVE: 1,\n                    NOTE: 2,\n                    DURATION: 3,\n                },\n                class: 'sound',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.play_piezobuzzer(sprite, script)\n            },\n            roduino_play_piezobuzzer_until_done: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_piezobuzzer_tone_c, '0'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_c_sharp, '1'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_d, '2'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_d_sharp, '3'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_e, '4'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_f, '5'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_f_sharp, '6'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_g, '7'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_g_sharp, '8'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_a, '9'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_a_sharp, '10'],\n                            [Lang.Blocks.roduino_piezobuzzer_tone_b, '11'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin'\n                        },\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0.5'],\n                        },\n                        null,\n\n                    ],\n                    type: 'roduino_play_piezobuzzer_until_done',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    OCTAVE: 1,\n                    NOTE: 2,\n                    DURATION: 3,\n                },\n                class: 'sound',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.play_piezobuzzer_until_done(sprite, script)\n            },\n            roduino_get_digital_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin',\n                        },\n                    ],\n                    type: 'roduino_get_digital_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.get_digital_value(sprite, script),\n            },\n            roduino_get_analog_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_analog_pin',\n                        },\n                    ],\n                    type: 'roduino_get_analog_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.get_analog_value(sprite, script),\n            },\n            roduino_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_sensor_temperutre, 'temperature'],\n                            [Lang.Blocks.roduino_sensor_joystick_x, 'joystickx'],\n                            [Lang.Blocks.roduino_sensor_joystick_y, 'joysticky'],\n                            [Lang.Blocks.roduino_sensor_light, 'light'],\n                            [Lang.Blocks.roduino_sensor_dial, 'dial'],\n                            [Lang.Blocks.roduino_sensor_a_keypad, 'akeypad'],\n                            [Lang.Blocks.roduino_sensor_rotaryposition, 'rotaryposition'],\n                            [Lang.Blocks.roduino_sensor_magnetic, 'magnetic'],\n                            [Lang.Blocks.roduino_sensor_ultrasonic, 'ultrasonic'],\n                        ],\n                        value: 'temperature',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_pin',\n                        },\n                        null,\n                    ],\n                    type: 'roduino_get_sensor_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    SENSOR: 1,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.get_sensor_value(sprite, script)\n            },\n            roduino_is_digital_detected: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin',\n                        },\n                    ],\n                    type: 'roduino_is_digital_detected',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.is_digital_detected(sprite, script),\n            },\n            roduino_compare_analog_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['>', 'greater-than'],\n                            ['=', 'equal'],\n                            ['<', 'less-than'],\n                        ],\n                        value: 'greater-than',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_analog_pin',\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['512'],\n                        },\n                    ],\n                    type: 'roduino_compare_analog_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    SYMBOL: 1,\n                    VALUE: 2,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.compare_analog_value(sprite, script),\n            },\n            roduino_compare_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_sensor_temperutre, 'temperature'],\n                            [Lang.Blocks.roduino_sensor_joystick_x, 'joystickx'],\n                            [Lang.Blocks.roduino_sensor_joystick_y, 'joysticky'],\n                            [Lang.Blocks.roduino_sensor_light, 'light'],\n                            [Lang.Blocks.roduino_sensor_dial, 'dial'],\n                            [Lang.Blocks.roduino_sensor_a_keypad, 'akeypad'],\n                            [Lang.Blocks.roduino_sensor_rotaryposition, 'rotaryposition'],\n                            [Lang.Blocks.roduino_sensor_magnetic, 'magnetic'],\n                            [Lang.Blocks.roduino_sensor_ultrasonic, 'ultrasonic'],\n                        ],\n                        value: 'temperature',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['>', 'greater-than'],\n                            ['=', 'equal'],\n                            ['<', 'less-than'],\n                        ],\n                        value: 'greater-than',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_pin',\n                        },\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                    ],\n                    type: 'roduino_compare_sensor_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    SENSOR: 1,\n                    SYMBOL: 2,\n                    VALUE: 3,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.compare_sensor_value(sprite, script),\n            },\n\n            roduino_get_rotary_position_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_sensor_rotaryposition_rotation, 'rotation'],\n                            [Lang.Blocks.roduino_sensor_rotaryposition_position, 'position'],\n                            [Lang.Blocks.roduino_sensor_rotaryposition_angle, 'angle']\n                        ],\n                        value: 'rotation',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_analog_pin',\n                        },\n                        null,\n                    ],\n                    type: 'roduino_get_rotary_position_sensor_value',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    PROPERTY: 1,\n                },\n                class: 'sensing_rotary_position_sensor',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.get_rotary_position_sensor_value(sprite, script)\n            },\n\n            roduino_reset_rotary_position_sensor: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_sensor_rotaryposition_rotation, 'rotation'],\n                            [Lang.Blocks.roduino_sensor_rotaryposition_position, 'position'],\n                            [Lang.Blocks.roduino_sensor_rotaryposition_angle, 'angle']\n                        ],\n                        value: 'rotation',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_analog_pin',\n                        },\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0'],\n                        },\n                        null,\n                    ],\n                    type: 'roduino_reset_rotary_position_sensor',\n                },\n                paramsKeyMap: {\n                    PIN: 0,\n                    PROPERTY: 1,\n                    VALUE: 2,\n                },\n                class: 'sensing_rotary_position_sensor',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.reset_rotary_position_sensor(sprite, script)\n            },\n            roduino_get_color_sensor_detected_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_sensor_color_red, '#FF0000'],\n                            [Lang.Blocks.roduino_sensor_color_yellow, '#FFEE00'],\n                            [Lang.Blocks.roduino_sensor_color_green, '#00AA00'],\n                            [Lang.Blocks.roduino_sensor_color_blue, '#0055FF'],\n                        ],\n                        value: '#FF0000',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'roduino_get_color_sensor_detected_value',\n                },\n                paramsKeyMap: {\n                    COLOR: 0,\n                },\n                class: 'sensing_color_sensor',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.get_color_sensor_detected_value(sprite, script)\n            },\n            roduino_is_color_sensor_detected: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roduino_sensor_color_red, '#FF0000'],\n                            [Lang.Blocks.roduino_sensor_color_yellow, '#FFEE00'],\n                            [Lang.Blocks.roduino_sensor_color_green, '#00AA00'],\n                            [Lang.Blocks.roduino_sensor_color_blue, '#0055FF'],\n                        ],\n                        value: '#FF0000',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'roduino_is_color_sensor_detected',\n                },\n                paramsKeyMap: {\n                    COLOR: 0,\n                },\n                class: 'sensing_color_sensor',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.is_color_sensor_detected(sprite, script)\n            },\n            roduino_set_color_sensor_pins: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'roduino_menu_digital_pin',\n                            params: ['6'],\n                        },\n                        {\n                            type: 'roduino_menu_digital_pin',\n                            params: ['7'],\n                        },\n                        {\n                            type: 'roduino_menu_digital_pin',\n                            params: ['8'],\n                        },\n                        null,\n                    ],\n                    type: 'roduino_set_color_sensor_pins',\n                },\n                paramsKeyMap: {\n                    RED: 0,\n                    GREEN: 1,\n                    BLUE: 2,\n                },\n                class: 'sensing_color_sensor',\n                isNotFor: ['roborobo_roduino'],\n                func: (sprite, script) => this.set_color_sensor_pins(sprite, script)\n            },\n        };\n    };\n\n    setZero () {\n        super.setZero();\n    }\n\n    afterReceive (data) {\n        super.afterReceive(data);\n    }\n\n    afterSend () {\n        super.afterSend();\n    }\n\n    request (func, subkey, value, updateNow = false) {\n        super.request(func, subkey, value, updateNow);\n    }\n\n    resetState () {\n        super.resetState();\n        this.state.tx = {color: {pins: {r: -1, g: -1, b: -1}}};\n    }\n\n    /**\n     * -----------------------------------block execute-----------------------------------\n     * 공통 사용 함수를 제외한 나머지 블록 동작을 작성\n     * -----------------------------------------------------------------------------------\n     */\n\n    set_motor_rotation (sprite, script) {\n        const motor = script.getNumberValue('MOTOR');\n        const state = script.getStringValue('STATE');\n\n        let stateNum = 0;\n        if (state == 'cw') stateNum = 1;\n        else if (state == 'ccw') stateNum = 2;\n\n        this.request('setMotor', motor, {motor, speed: 0, state: stateNum});\n        return script.callReturn();\n    }\n\n    get_color_sensor_detected_value (sprite, script) {\n        const color = script.getStringValue('COLOR');\n        return this._isColorSensorDetected(color) ? 1 : 0;\n    }\n\n    is_color_sensor_detected (sprite, script) {\n        const color = script.getStringValue('COLOR');\n        return this._isColorSensorDetected(color);\n    }\n\n    _isColorSensorDetected (color) {\n        const pins = this.state.tx.color.pins;\n        if (!pins || !this.isDigitalPin(pins.r) || !this.isDigitalPin(pins.g) || !this.isDigitalPin(pins.b)) return false;\n\n        const r = this.getDigitalValue(pins.r);\n        const g = this.getDigitalValue(pins.g);\n        const b = this.getDigitalValue(pins.b);\n\n        switch (color) {\n            case '#FF0000':\n                return r == 1 && g == 0 && b == 0;\n            case '#00AA00':\n                return r == 0 && g == 1 && b == 0;\n            case '#0055FF':\n                return r == 0 && g == 0 && b == 1;\n            case '#FFEE00':\n                return r == 1 && g == 1 && b == 1;\n        }\n        return false;\n    }\n\n    set_color_sensor_pins (sprite, script) {\n        const r = this.pinToNumber(script.getStringValue('RED'));\n        const g = this.pinToNumber(script.getStringValue('GREEN'));\n        const b = this.pinToNumber(script.getStringValue('BLUE'));\n\n        const colorPins = this.state.tx.color.pins;\n        if (!colorPins) return;\n\n        if (colorPins.r != r) {\n            this.request('enableDigitalInput', r, {pin: r});\n            colorPins.r = r;\n        }\n        if (colorPins.g != g) {\n            this.request('enableDigitalInput', g, {pin: g});\n            colorPins.g = g;\n        }\n        if (colorPins.b != b) {\n            this.request('enableDigitalInput', b, {pin: b}, true);\n            colorPins.b = b;\n        }\n    }\n}\n\nmodule.exports = new Roduino();"
  },
  {
    "path": "src/playground/blocks/hardware/block_roborobo_roe.js",
    "content": "'use strict';\nconst {ArduinoBase, Cast} = require('./block_roborobo_base.js');\n\nclass RoE extends ArduinoBase {\n    constructor () {\n        super();\n\n        this.id = '48.1';\n        this.name = 'roborobo_roe';\n        this.url = 'http://www.roborobo.co.kr';\n        this.imageName = 'roborobo_roe.png';\n        this.title = {\n            ko: '로이',\n            en: 'Ro-E',\n        };\n        this.blockMenuBlocks = this.getBlockMenuBlocks();\n    }\n\n    /**\n     * 언어 번역 사용을 위해 함수 형태로 유지\n     */\n    monitorTemplate () {\n        return {\n            //imgPath: 'hw/~~.png',\n            //width: 256,\n            //height: 256,\n            // 모니터 화면 상단에 차례대로 나열하는 값\n            listPorts: {\n                sensor_touch: {name: Lang.Blocks.roe_sensor_touch, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_infrared: {name: Lang.Blocks.roe_sensor_infrared, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_color_left: {name: Lang.Blocks.roe_sensor_color_left, type: 'input', pos: {x: 0, y: 0, }},\n                sensor_color_right: {name: Lang.Blocks.roe_sensor_color_right, type: 'input', pos: {x: 0, y: 0, }},\n            },\n            // 모니터 화면 지정 위치와 선으로 연결하여 표시하는 값\n            ports: {},\n            mode: 'both',\n        };\n    }\n\n    getBlockMenuBlocks () {\n        return [\n            'roe_set_both_step_motors',\n            'roe_set_both_step_motors_by_distance',\n            'roe_set_step_motor_by_distance',\n            'roe_set_line_tracing_mode',\n            'roe_stop_line_tracing',\n            'roe_set_rgbled_color',\n            'roe_set_rgbled_off',\n            'roe_play_piezobuzzer',\n            'roe_play_piezobuzzer_until_done',\n            'roe_get_sensor_value',\n            'roe_get_color_sensor_value',\n            'roe_is_sensor_detected',\n            'roe_is_color_sensor_detected',\n            'roe_is_both_color_sensor_detected',\n        ];\n    }\n\n    setLanguage () {\n        return {\n            ko: {\n                template: {\n                    roe_set_both_step_motors: '%1 하기 %2',\n                    roe_set_both_step_motors_by_distance: '%1 만큼 %2 %3',\n                    roe_set_step_motor_by_distance: '%1 모터 %2 만큼 %3 %4',\n                    roe_set_line_tracing_mode: '%1 (을)를 따라 이동하기 %2',\n                    roe_stop_line_tracing: '선 따라 이동하기를 멈추기 %1',\n                    roe_set_rgbled_color: 'led 색상을 %1 으로 정하기 %2',\n                    roe_set_rgbled_off: 'led 끄기 %1',\n                    roe_play_piezobuzzer: '스피커로 %1 옥타브 %2 음을 %3 초 소리내기 %4',\n                    roe_play_piezobuzzer_until_done: '스피커로 %1 옥타브 %2 음을 %3 초 소리내며 기다리기 %4',\n                    roe_get_sensor_value: '%1 센서 값',\n                    roe_get_color_sensor_value: '%1 컬러 센서에 감지된 색',\n                    roe_is_sensor_detected: '%1 센서가 %2 ?',\n                    roe_is_color_sensor_detected: '%1 컬러 센서에 %2 이 %3 ?',\n                    roe_is_both_color_sensor_detected: '왼쪽 컬러 센서에 %1 이 %2, 오른쪽 컬러 센서에 %3 색이 %4 ?',\n                },\n                Blocks: {\n                    roe_parts_position_left: '왼쪽',\n                    roe_parts_position_right: '오른쪽',\n                    roe_parts_position_both: '양쪽',\n\n                    roe_motor_state_cw: '시계 방향 회전',\n                    roe_motor_state_ccw: '시계 반대 방향 회전',\n                    roe_motor_state_stop: '정지',\n\n                    roe_motors_state_forward: '앞으로 이동',\n                    roe_motors_state_backward: '뒤로 이동',\n                    roe_motors_state_turn_left: '왼쪽으로 회전',\n                    roe_motors_state_turn_right: '오른쪽으로 회전',\n                    roe_motors_state_stop: '정지',\n\n                    roe_line_type_curve: '곡선',\n                    roe_line_type_intersection: '교차선',\n\n                    roe_piezobuzzer_tone_c: '도',\n                    roe_piezobuzzer_tone_c_sharp: '도♯(레♭)',\n                    roe_piezobuzzer_tone_d: '레',\n                    roe_piezobuzzer_tone_d_sharp: '레♯(미♭)',\n                    roe_piezobuzzer_tone_e: '미',\n                    roe_piezobuzzer_tone_f: '파',\n                    roe_piezobuzzer_tone_f_sharp: '파♯(솔♭)',\n                    roe_piezobuzzer_tone_g: '솔',\n                    roe_piezobuzzer_tone_g_sharp: '솔♯(라♭)',\n                    roe_piezobuzzer_tone_a: '라',\n                    roe_piezobuzzer_tone_a_sharp: '라♯(시♭)',\n                    roe_piezobuzzer_tone_b: '시',\n\n                    roe_check_detected: '감지되었는가',\n                    roe_check_not_detected: '감지되지 않았는가',\n                    roe_sensing_detected_between: '감지되고',\n                    roe_sensing_not_detected_between: '감지되지 않고',\n\n                    roe_sensor_touch: '접촉 센서',\n                    roe_sensor_infrared: '적외선 센서',\n                    roe_sensor_color_left: '왼쪽 컬러 센서',\n                    roe_sensor_color_right: '오른쪽 컬러 센서',\n\n                    roe_sensor_color_red: '빨간색',\n                    roe_sensor_color_orange: '주황색',\n                    roe_sensor_color_yellow: '노란색',\n                    roe_sensor_color_yellow_green: '연두색',\n                    roe_sensor_color_green: '초록색',\n                    roe_sensor_color_sky_blue: '하늘색',\n                    roe_sensor_color_blue: '파란색',\n                    roe_sensor_color_purple: '보라색',\n                    roe_sensor_color_pink: '분홍색',\n                    roe_sensor_color_white: '흰색',\n                    roe_sensor_color_black: '검정색',\n                    roe_sensor_color_any: '아무 색',\n                    roe_sensor_color_unknown: '알 수 없음',\n                },\n            },\n            en: {\n                template: {\n                    roe_set_both_step_motors: '%1 %2',\n                    roe_set_both_step_motors_by_distance: '%1 by %2 %3',\n                    roe_set_step_motor_by_distance: '%1 motor %2 by %3 %4',\n                    roe_set_line_tracing_mode: 'move tracing %1 %2',\n                    roe_stop_line_tracing: 'stop moving along a line %1',\n                    roe_set_rgbled_color: 'set led color to %1 %2',\n                    roe_set_rgbled_off: 'turn off led %1',\n                    roe_play_piezobuzzer: 'play %1 otave %2 note for %3 seconds through the speaker %4',\n                    roe_play_piezobuzzer_until_done: 'wait with speaker to play %1 otave %2 note for %3 seconds %4',\n                    roe_get_sensor_value: '%1 sensor value',\n                    roe_get_color_sensor_value: 'color detected by %1 color sensor',\n                    roe_is_sensor_detected: 'is %1 sensor %2 ?',\n                    roe_is_color_sensor_detected: 'is %2 color on %1 color sensor %3 ?',\n                    roe_is_both_color_sensor_detected: 'is %1 color on left color sensor %2 and %3 color on right color sensor %4 ?',\n                },\n                Blocks: {\n                    roe_parts_position_left: 'left',\n                    roe_parts_position_right: 'right',\n                    roe_parts_position_both: 'both sides',\n\n                    roe_motor_state_cw: 'rotate clockwise',\n                    roe_motor_state_ccw: 'rotate counterclockwise',\n                    roe_motor_state_stop: 'stop',\n\n                    roe_motors_state_forward: 'move forward',\n                    roe_motors_state_backward: 'move backword',\n                    roe_motors_state_turn_left: 'turn left',\n                    roe_motors_state_turn_right: 'turn right',\n                    roe_motors_state_stop: 'stop',\n\n                    roe_line_type_curve: 'curve',\n                    roe_line_type_intersection: 'intersection',\n\n                    roe_piezobuzzer_tone_c: 'C',\n                    roe_piezobuzzer_tone_c_sharp: 'C♯(D♭)',\n                    roe_piezobuzzer_tone_d: 'D',\n                    roe_piezobuzzer_tone_d_sharp: 'D♯(E♭)',\n                    roe_piezobuzzer_tone_e: 'E',\n                    roe_piezobuzzer_tone_f: 'F',\n                    roe_piezobuzzer_tone_f_sharp: 'F♯(G♭)',\n                    roe_piezobuzzer_tone_g: 'G',\n                    roe_piezobuzzer_tone_g_sharp: 'G♯(A♭)',\n                    roe_piezobuzzer_tone_a: 'A',\n                    roe_piezobuzzer_tone_a_sharp: 'A♯(B♭)',\n                    roe_piezobuzzer_tone_b: 'B',\n\n                    roe_check_detected: 'detected',\n                    roe_check_not_detected: 'not detected',\n                    roe_sensing_detected_between: 'detected',\n                    roe_sensing_not_detected_between: 'not detected',\n\n                    roe_sensor_touch: 'touch sensor',\n                    roe_sensor_infrared: 'infrared sensor',\n                    roe_sensor_color_left: 'left color sensor',\n                    roe_sensor_color_right: 'right color sensor',\n\n                    roe_sensor_color_red: 'red',\n                    roe_sensor_color_orange: 'orange',\n                    roe_sensor_color_yellow: 'yellow',\n                    roe_sensor_color_yellow_green: 'yellow green',\n                    roe_sensor_color_green: 'green',\n                    roe_sensor_color_sky_blue: 'sky blue',\n                    roe_sensor_color_blue: 'blue',\n                    roe_sensor_color_purple: 'purple',\n                    roe_sensor_color_pink: 'pink',\n                    roe_sensor_color_white: 'white',\n                    roe_sensor_color_black: 'black',\n                    roe_sensor_color_any: 'any',\n                    roe_sensor_color_unknown: 'unknown',\n                },\n            },\n        };\n    };\n\n    getBlocks () {\n        return {\n            roe_set_both_step_motors: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_motors_state_forward, 'forward'],\n                            [Lang.Blocks.roe_motors_state_backward, 'backward'],\n                            [Lang.Blocks.roe_motors_state_turn_left, 'turn-left'],\n                            [Lang.Blocks.roe_motors_state_turn_right, 'turn-right'],\n                            [Lang.Blocks.roe_motors_state_stop, 'stop'],\n                        ],\n                        value: 'forward',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n\n                    ],\n                    type: 'roe_set_both_step_motors',\n                },\n                paramsKeyMap: {\n                    STATE: 0,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.set_both_step_motors(sprite, script)\n            },\n            roe_set_both_step_motors_by_distance: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_motors_state_forward, 'forward'],\n                            [Lang.Blocks.roe_motors_state_backward, 'backward'],\n                            [Lang.Blocks.roe_motors_state_turn_left, 'turn-left'],\n                            [Lang.Blocks.roe_motors_state_turn_right, 'turn-right'],\n                            [Lang.Blocks.roe_motors_state_stop, 'stop'],\n                        ],\n                        value: 'forward',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    }\n                ],\n                events: {},\n                def: {\n                    params: [\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                        null,\n                        null,\n                    ],\n                    type: 'roe_set_both_step_motors_by_distance',\n                },\n                paramsKeyMap: {\n                    DISTANCE: 0,\n                    STATE: 1,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.set_both_step_motors_by_distance(sprite, script),\n            },\n            roe_set_step_motor_by_distance: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_parts_position_left, 'left'],\n                            [Lang.Blocks.roe_parts_position_right, 'right'],\n                        ],\n                        value: 'left',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_motor_state_cw, 'cw'],\n                            [Lang.Blocks.roe_motor_state_ccw, 'ccw'],\n                            [Lang.Blocks.roe_motor_state_stop, 'stop'],\n                        ],\n                        value: 'cw',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        {\n                            type: 'number',\n                            params: ['100'],\n                        },\n                        null,\n                        null,\n\n                    ],\n                    type: 'roe_set_step_motor_by_distance',\n                },\n                paramsKeyMap: {\n                    POSITION: 0,\n                    DISTANCE: 1,\n                    STATE: 2,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.set_step_motor_by_distance(sprite, script)\n            },\n            roe_set_line_tracing_mode: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_line_type_curve, 'curve'],\n                            [Lang.Blocks.roe_line_type_intersection, 'intersection'],\n                        ],\n                        value: 'curve',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n\n                    ],\n                    type: 'roe_set_line_tracing_mode',\n                },\n                paramsKeyMap: {\n                    OPTION: 0,\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.set_line_tracing_mode(sprite, script)\n            },\n            roe_stop_line_tracing: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'roe_stop_line_tracing',\n                },\n                paramsKeyMap: {\n                },\n                class: 'motion',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.stop_line_tracing(sprite, script)\n            },\n            roe_set_rgbled_color: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_sensor_color_red, '#FF0000'],\n                            [Lang.Blocks.roe_sensor_color_orange, '#FF8800'],\n                            [Lang.Blocks.roe_sensor_color_yellow, '#FFEE00'],\n                            [Lang.Blocks.roe_sensor_color_yellow_green, '#88EE00'],\n                            [Lang.Blocks.roe_sensor_color_green, '#00AA00'],\n                            [Lang.Blocks.roe_sensor_color_sky_blue, '#00DDFF'],\n                            [Lang.Blocks.roe_sensor_color_blue, '#0055FF'],\n                            [Lang.Blocks.roe_sensor_color_purple, '#8800FF'],\n                            [Lang.Blocks.roe_sensor_color_pink, '#FF55FF'],\n                            [Lang.Blocks.roe_sensor_color_white, '#FFFFFF'],\n                            [Lang.Blocks.roe_sensor_color_black, '#000000'],\n                            [Lang.Blocks.roe_sensor_color_any, 'random'],\n                        ],\n                        value: 'random',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                    ],\n                    type: 'roe_set_rgbled_color',\n                },\n                paramsKeyMap: {\n                    COLOR: 0,\n                },\n                class: 'looks',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.set_rgbled_color(sprite, script)\n            },\n            roe_set_rgbled_off: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'roe_set_rgbled_off',\n                },\n                paramsKeyMap: {},\n                class: 'looks',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.set_rgbled_off(sprite, script)\n            },\n            roe_play_piezobuzzer: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_piezobuzzer_tone_c, '0'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_c_sharp, '1'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_d, '2'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_d_sharp, '3'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_e, '4'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_f, '5'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_f_sharp, '6'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_g, '7'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_g_sharp, '8'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_a, '9'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_a_sharp, '10'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_b, '11'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0.5'],\n                        },\n                        null,\n\n                    ],\n                    type: 'roe_play_piezobuzzer',\n                },\n                paramsKeyMap: {\n                    OCTAVE: 0,\n                    NOTE: 1,\n                    DURATION: 2,\n                },\n                class: 'sound',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.play_piezobuzzer(sprite, script)\n            },\n            roe_play_piezobuzzer_until_done: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            ['1', '1'],\n                            ['2', '2'],\n                            ['3', '3'],\n                            ['4', '4'],\n                            ['5', '5'],\n                            ['6', '6'],\n                            ['7', '7'],\n                            ['8', '8'],\n                        ],\n                        value: '4',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_piezobuzzer_tone_c, '0'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_c_sharp, '1'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_d, '2'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_d_sharp, '3'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_e, '4'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_f, '5'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_f_sharp, '6'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_g, '7'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_g_sharp, '8'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_a, '9'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_a_sharp, '10'],\n                            [Lang.Blocks.roe_piezobuzzer_tone_b, '11'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Block',\n                        accept: 'string',\n                        defualtType: 'number',\n                    },\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardware_icon.svg',\n                        size: 12,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        {\n                            type: 'number',\n                            params: ['0.5'],\n                        },\n                        null,\n\n                    ],\n                    type: 'roe_play_piezobuzzer_until_done',\n                },\n                paramsKeyMap: {\n                    OCTAVE: 0,\n                    NOTE: 1,\n                    DURATION: 2,\n                },\n                class: 'sound',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.play_piezobuzzer_until_done(sprite, script)\n            },\n            roe_get_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_sensor_touch, 'touch'],\n                            [Lang.Blocks.roe_sensor_infrared, 'infrared'],\n                        ],\n                        value: 'touch',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'roe_get_sensor_value',\n                },\n                paramsKeyMap: {\n                    SENSOR: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.get_sensor_value(sprite, script),\n            },\n            roe_get_color_sensor_value: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_string_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_parts_position_left, 'left'],\n                            [Lang.Blocks.roe_parts_position_right, 'right'],\n                        ],\n                        value: 'left',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                    ],\n                    type: 'roe_get_color_sensor_value',\n                },\n                paramsKeyMap: {\n                    POSITION: 0,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.get_color_sensor_value(sprite, script),\n            },\n            roe_is_sensor_detected: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_sensor_touch, 'touch'],\n                            [Lang.Blocks.roe_sensor_infrared, 'infrared'],\n                        ],\n                        value: 'touch',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_check_detected, 'detected'],\n                            [Lang.Blocks.roe_check_not_detected, 'not-detected'],\n                        ],\n                        value: 'detected',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                    ],\n                    type: 'roe_is_sensor_detected',\n                },\n                paramsKeyMap: {\n                    SENSOR: 0,\n                    MODE: 1,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.is_sensor_detected(sprite, script)\n            },\n            roe_is_color_sensor_detected: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_parts_position_both, 'both'],\n                            [Lang.Blocks.roe_parts_position_left, 'left'],\n                            [Lang.Blocks.roe_parts_position_right, 'right'],\n                        ],\n                        value: 'both',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_sensor_color_red, '#FF0000'],\n                            [Lang.Blocks.roe_sensor_color_orange, '#FF8800'],\n                            [Lang.Blocks.roe_sensor_color_yellow, '#FFEE00'],\n                            [Lang.Blocks.roe_sensor_color_yellow_green, '#88EE00'],\n                            [Lang.Blocks.roe_sensor_color_green, '#00AA00'],\n                            [Lang.Blocks.roe_sensor_color_sky_blue, '#00DDFF'],\n                            [Lang.Blocks.roe_sensor_color_blue, '#0055FF'],\n                            [Lang.Blocks.roe_sensor_color_purple, '#8800FF'],\n                            [Lang.Blocks.roe_sensor_color_pink, '#FF55FF'],\n                            [Lang.Blocks.roe_sensor_color_white, '#FFFFFF'],\n                            [Lang.Blocks.roe_sensor_color_black, '#000000'],\n                            [Lang.Blocks.roe_sensor_color_any, 'random'],\n                        ],\n                        value: 'random',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_check_detected, 'detected'],\n                            [Lang.Blocks.roe_check_not_detected, 'not-detected'],\n                        ],\n                        value: 'detected',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        null,\n                    ],\n                    type: 'roe_is_color_sensor_detected',\n                },\n                paramsKeyMap: {\n                    POSITION: 0,\n                    COLOR: 1,\n                    MODE: 2,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.is_color_sensor_detected(sprite, script),\n            },\n            roe_is_both_color_sensor_detected: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                skeleton: 'basic_boolean_field',\n                statements: [],\n                params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_sensor_color_red, '#FF0000'],\n                            [Lang.Blocks.roe_sensor_color_orange, '#FF8800'],\n                            [Lang.Blocks.roe_sensor_color_yellow, '#FFEE00'],\n                            [Lang.Blocks.roe_sensor_color_yellow_green, '#88EE00'],\n                            [Lang.Blocks.roe_sensor_color_green, '#00AA00'],\n                            [Lang.Blocks.roe_sensor_color_sky_blue, '#00DDFF'],\n                            [Lang.Blocks.roe_sensor_color_blue, '#0055FF'],\n                            [Lang.Blocks.roe_sensor_color_purple, '#8800FF'],\n                            [Lang.Blocks.roe_sensor_color_pink, '#FF55FF'],\n                            [Lang.Blocks.roe_sensor_color_white, '#FFFFFF'],\n                            [Lang.Blocks.roe_sensor_color_black, '#000000'],\n                            [Lang.Blocks.roe_sensor_color_any, 'random'],\n                        ],\n                        value: 'random',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_sensing_detected_between, 'detected'],\n                            [Lang.Blocks.roe_sensing_not_detected_between, 'not-detected'],\n                        ],\n                        value: 'detected',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_sensor_color_red, '#FF0000'],\n                            [Lang.Blocks.roe_sensor_color_orange, '#FF8800'],\n                            [Lang.Blocks.roe_sensor_color_yellow, '#FFEE00'],\n                            [Lang.Blocks.roe_sensor_color_yellow_green, '#88EE00'],\n                            [Lang.Blocks.roe_sensor_color_green, '#00AA00'],\n                            [Lang.Blocks.roe_sensor_color_sky_blue, '#00DDFF'],\n                            [Lang.Blocks.roe_sensor_color_blue, '#0055FF'],\n                            [Lang.Blocks.roe_sensor_color_purple, '#8800FF'],\n                            [Lang.Blocks.roe_sensor_color_pink, '#FF55FF'],\n                            [Lang.Blocks.roe_sensor_color_white, '#FFFFFF'],\n                            [Lang.Blocks.roe_sensor_color_black, '#000000'],\n                            [Lang.Blocks.roe_sensor_color_any, 'random'],\n                        ],\n                        value: 'random',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.roe_check_detected, 'detected'],\n                            [Lang.Blocks.roe_check_not_detected, 'not-detected'],\n                        ],\n                        value: 'detected',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                ],\n                events: {},\n                def: {\n                    params: [\n                        null,\n                        null,\n                        null,\n                        null,\n                    ],\n                    type: 'roe_is_both_color_sensor_detected',\n                },\n                paramsKeyMap: {\n                    COLOR_LEFT: 0,\n                    MODE_LEFT: 1,\n                    COLOR_RIGHT: 2,\n                    MODE_RIGHT: 3,\n                },\n                class: 'sensing',\n                isNotFor: ['roborobo_roe'],\n                func: (sprite, script) => this.is_both_color_sensor_detected(sprite, script),\n            },\n        };\n    }\n\n    /**\n     * @override\n     */\n    setZero () {\n        this.stop_line_tracing();\n        super.setZero();\n    }\n\n    afterReceive (data) {\n        super.afterReceive(data);\n    }\n\n    afterSend () {\n        super.afterSend();\n    }\n\n    request (func, subkey, value, updateNow = false) {\n        super.request(func, subkey, value, updateNow);\n    }\n\n    resetState () {\n        super.resetState();\n    }\n\n    /**\n     * -----------------------------------block execute-----------------------------------\n     * 공통 사용 함수를 제외한 나머지 블록 동작을 작성\n     * -----------------------------------------------------------------------------------\n     */\n\n    set_both_step_motors (sprite, script) {\n        const state = script.getStringValue('STATE');\n        this._setBothStepMotors(script, state);\n    }\n\n    set_both_step_motors_by_distance (sprite, script) {\n        const state = script.getStringValue('STATE');\n        const distance = script.getNumberValue('DISTANCE');\n        this._setBothStepMotors(script, state, distance);\n    }\n\n    _setBothStepMotors (script, state, distance = null) {\n        let stateNum = [0, 0];\n        switch (state) {\n            case 'forward':\n                stateNum = [2, 1];\n                break;\n            case 'turn-left':\n                stateNum = [1, 1];\n                break;\n            case 'backward':\n                stateNum = [1, 2];\n                break;\n            case 'turn-right':\n                stateNum = [2, 2];\n                break;\n        }\n\n        for (let i = 0; i < 2; i++) {\n            this.request('setStepMotor', i + 1, {motor: i + 1, distance: distance, state: stateNum[i]});\n        }\n        return script.callReturn();\n    }\n\n    set_step_motor_by_distance (sprite, script) {\n        const position = script.getStringValue('POSITION');\n        const state = script.getStringValue('STATE');\n        const distance = script.getNumberValue('DISTANCE');\n        this._setStepMotor(script, position, state, distance);\n    }\n\n    _setStepMotor (script, position, state, distance = null) {\n        let stateNum = 0;\n        if (state == 'cw') stateNum = 1;\n        else if (state == 'ccw') stateNum = 2;\n\n        let motorNum = 1;\n        if (position == 'left') motorNum = 1;\n        else if (position == 'right') motorNum = 2;\n\n        this.request('setStepMotor', motorNum, {motor: motorNum, distance: distance, state: stateNum});\n        return script.callReturn();\n    }\n\n    set_line_tracing_mode (sprite, script) {\n        if (this.state.isLineTracerRunning) {\n            if (script.executeState) {\n                if (!script.executeState.isStart) {\n                    script.executeState.isStart = true;\n                }\n                return script;\n            } else {\n                return script.callReturn();\n            }\n        } else {\n            if (script.executeState) {\n                if (script.executeState.isStart) {\n                    return script.callReturn();\n                } else {\n                    return script;\n                }\n            } else {\n                script.executeState = {startTime: Date.now(), isStart: false};\n                this.request('setLineTracingMode', null, {mode: script.getStringValue('OPTION')}, true);\n                return script;\n            }\n        }\n    }\n\n    stop_line_tracing (sprite, script) {\n        if (!script) {\n            this.request('stopLineTracing', null, null, true);\n            return;\n        }\n\n        if (this.state.isLineTracerRunning) {\n            if (!script.executeState) {\n                script.executeState = {startTime: Date.now()};\n                this.request('stopLineTracing', null, null, true);\n            }\n            return script;\n        } else {\n            return script.callReturn();\n        }\n    }\n\n    set_rgbled_color (sprite, script) {\n        let color = script.getStringValue('COLOR');\n        if (color === 'random') {\n            const colors = ['#FF0000', '#FF8800', '#FFEE00', '#88EE00', '#00AA00', '#00DDFF', '#0055FF', '#8800FF', '#FF55FF', '#FFFFFF'];\n            const num = Math.floor(Math.random() * colors.length);\n            color = colors[num];\n        }\n\n        color = Cast.toRgbColorObject(this._toRoEColor(color));\n        this.request('setRgbLedColor', null, {color});\n        return script.callReturn();\n    }\n\n    set_rgbled_off (sprite, script) {\n        const color = Cast.toRgbColorObject('#000000');\n        this.request('setRgbLedColor', null, {color});\n        return script.callReturn();\n    }\n\n    play_piezobuzzer (sprite, script) {\n        const octave = script.getNumberValue('OCTAVE');\n        const duration = script.getNumberValue('DURATION');\n        let note = script.getNumberValue('NOTE');\n        note = (octave - 1) * 12 + note;\n\n        this.request('setPiezoBuzzer', null, {note, duration});\n        return script.callReturn();\n    }\n\n    play_piezobuzzer_until_done (sprite, script) {\n        if (script.executeState) {\n            const duration = (script.getNumberValue('DURATION') * 1000);\n            if (Date.now() - script.executeState.startTime > duration) {\n                return script.callReturn();\n            } else {\n                return script;\n            }\n        } else {\n            script.executeState = {startTime: Date.now()};\n            this.play_piezobuzzer(sprite, script);\n            return script;\n        }\n    }\n\n    get_sensor_value (sprite, script) {\n        const sensor = script.getStringValue('SENSOR');\n        let isDetected = false;\n\n        if (sensor === 'infrared') {\n            isDetected = this.state.rx.infrared;\n        } else if (sensor === 'touch') {\n            isDetected = this.state.rx.touch;\n        }\n        return isDetected ? 1 : 0;\n    }\n\n    get_color_sensor_value (sprite, script) {\n        const position = script.getStringValue('POSITION');\n        if (position === 'left') {\n            return this._toRoEColorString(this.state.rx.colorSensor.left);\n        } else if (position === 'right') {\n            return this._toRoEColorString(this.state.rx.colorSensor.right);\n        }\n    }\n\n    is_sensor_detected (sprite, script) {\n        const sensor = script.getStringValue('SENSOR');\n        let isDetected = false;\n        if (sensor === 'infrared') {\n            isDetected = this.state.rx.infrared;\n        } else if (sensor === 'touch') {\n            isDetected = this.state.rx.touch;\n        } else return false;\n\n        const mode = (script.getStringValue('MODE') === 'detected');\n        return (mode && isDetected) || (!mode && !isDetected);\n    }\n\n    is_color_sensor_detected (sprite, script) {\n        const color = script.getStringValue('COLOR');\n        const mode = (script.getStringValue('MODE') === 'detected');\n\n        const position = script.getStringValue('POSITION');\n        if (position === 'left') {\n            return this._isColorSensorDetected(true, color, mode);\n        } else if (position === 'right') {\n            return this._isColorSensorDetected(false, color, mode);\n        } else {\n            return this._isColorSensorDetected(true, color, mode) && this._isColorSensorDetected(false, color, mode);\n        }\n    }\n\n    is_both_color_sensor_detected (sprite, script) {\n        const leftColor = script.getStringValue('COLOR_LEFT');\n        const leftMode = (script.getStringValue('MODE_LEFT') === 'detected');\n\n        const rightColor = script.getStringValue('COLOR_RIGHT');\n        const rightMode = (script.getStringValue('MODE_RIGHT') === 'detected');\n\n        return this._isColorSensorDetected(device, true, leftColor, leftMode) && this._isColorSensorDetected(device, false, rightColor, rightMode);\n    }\n\n    _isColorSensorDetected (isLeft, color, mode = true) {\n        const result = isLeft ? this.state.rx.colorSensor.left : this.state.rx.colorSensor.right;\n        const targetProtocol = this._toRoEColorProtocol(color);\n\n        let isDetected = false;\n        if (color === 'random') {\n            isDetected = result != targetProtocol;\n        } else {\n            isDetected = result == targetProtocol;\n        }\n        return (mode && isDetected) || (!mode && !isDetected);\n    }\n\n    _toRoEColor (color) {\n        switch (color) {\n            case '#FF0000': return '#FF0000';\n            case '#FF8800': return '#FF7F00';\n            case '#FFEE00': return '#80FF00';\n            case '#88EE00': return '#10D000';\n            case '#00AA00': return '#00FF00';\n            case '#00DDFF': return '#00D8FF';\n            case '#0055FF': return '#0000FF';\n            case '#8800FF': return '#DF00FF';\n            case '#FF55FF': return '#FF3399';\n            case '#FFFFFF': return '#7FFF7F';\n            default: return '#000000';\n        }\n    }\n\n    _toRoEColorString (protocol) {\n        switch (protocol) {\n            case 1: return 'RED';\n            case 2: return 'ORANGE';\n            case 3: return 'YELLOW';\n            case 7: return 'YELLOW GREEN';\n            case 4: return 'GREEN';\n            case 8: return 'SKY BLUE';\n            case 5: return 'BLUE';\n            case 6: return 'PURPLE';\n            case 9: return 'PINK';\n            case 10: return 'BLACK';\n            case 11: return 'WHITE';\n            default: return 'UNKNOWN';\n        }\n    }\n\n    _toRoEColorProtocol (color) {\n        switch (color) {\n            case '#FF0000': return 1;\n            case '#FF8800': return 2;\n            case '#FFEE00': return 3;\n            case '#88EE00': return 7;\n            case '#00AA00': return 4;\n            case '#00DDFF': return 8;\n            case '#0055FF': return 5;\n            case '#8800FF': return 6;\n            case '#FF55FF': return 9;\n            case '#000000': return 10;\n            case '#FFFFFF': return 11;\n            default: return 127;\n        }\n    }\n}\n\nmodule.exports = new RoE();\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_roborobo_schoolkit.js",
    "content": "'use strict';\n\nEntry.Roborobo_SchoolKit = {\n    hasPracticalCourse: true,\n    id: '10.2',\n    name: 'roborobo_schoolkit',\n    url: 'http://www.roborobo.co.kr',\n    imageName: 'roborobo_schoolkit.png',\n    title: {\n        ko: '스쿨키트',\n        en: 'School Kit',\n    },\n    pinMode: {\n        INPUT: 0,\n        OUTPUT: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO: 4,\n    },\n    inputPort: {\n        ir: 7,\n        sound: 8,\n        contact: 9,\n        cds: 10,\n    },\n    setZero: function () {\n        Entry.hw.sendQueue.digitalPinMode = [];\n        Entry.hw.sendQueue.previousValue = [];\n\n        for (var port = 0; port < 14; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.digitalPinMode[port] = 0;\n            Entry.hw.sendQueue.previousValue[port] = -1;\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/roborobo_schoolkit.png',\n        keys: ['value'],\n        width: 256,\n        height: 256,\n        listPorts: {\n            '0': {\n                name: 'D1',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            '1': {\n                name: 'D2',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            '2': {\n                name: 'D3',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            '3': {\n                name: 'D4',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            '4': {\n                name: 'D5',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            '5': {\n                name: 'D6',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            '6': {\n                name: 'D7',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.Roborobo_SchoolKit.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                schoolkit_get_in_port_number: '%1  ',\n                schoolkit_get_out_port_number: '%1  ',\n                schoolkit_get_servo_port_number: '%1  ',\n                schoolkit_get_input_value: '디지털 %1 번 센서값  ',\n                schoolkit_set_output: '디지털 %1 번 핀 %2 %3',\n                schoolkit_motor: '%1 속도 %2(으)로 %3 %4',\n                schoolkit_set_servo_value: '서보모터 %1 번 핀 %2˚ %3',\n                schoolkit_on_block: ' On ',\n                schoolkit_off_block: ' Off ',\n            },\n        },\n        en: {\n            template: {\n                schoolkit_get_in_port_number: '%1  ',\n                schoolkit_get_out_port_number: '%1  ',\n                schoolkit_get_servo_port_number: '%1  ',\n                schoolkit_get_input_value: 'Digital %1 Sensor value  ',\n                schoolkit_set_output: 'Digital %1 Pin %2 %3',\n                schoolkit_motor: '%1 Speed %2 %3 %4',\n                schoolkit_set_servo_value: 'Servo %1 Pin %2˚ %3',\n                schoolkit_on_block: ' On ',\n                schoolkit_off_block: ' Off ',\n            },\n        },\n    };\n};\n\nEntry.Roborobo_SchoolKit.blockMenuBlocks = [\n    'schoolkit_on_block',\n    'schoolkit_off_block',\n    'schoolkit_get_input_value',\n    'schoolkit_set_output',\n    'schoolkit_motor',\n    'schoolkit_set_servo_value',\n];\n\nEntry.Roborobo_SchoolKit.practicalBlockMenuBlocks = {\n    hw_motor: [\n        // 'roborobo_motor_speed',\n        'roborobo_move_for_secs',\n        'roborobo_move_for',\n        'roborobo_turn_for',\n        'roborobo_stop_for',\n    ],\n    hw_melody: [\n\n    ],\n    hw_sensor: [\n        'roborobo_touch_value',\n        'roborobo_touch_value_boolean',\n        'roborobo_light_value',\n        'roborobo_light_value_boolean',\n        'roborobo_sound_value',\n        'roborobo_sound_value_boolean',\n        'roborobo_irs_value',\n        'roborobo_irs_value_boolean',\n    ],\n    hw_led: [\n        'roborobo_diode_secs_toggle',\n        'roborobo_diode_toggle',\n        'roborobo_diode_inout_toggle',\n        'roborobo_diode_set_output',\n        'roborobo_diode_input_value',\n    ],\n}\n\nEntry.Roborobo_SchoolKit.getBlocks = function () {\n    return {\n        //region schoolkit 스쿨키트\n        schoolkit_on_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'schoolkit_on_block',\n            },\n            paramsKeyMap: {},\n            class: 'schoolkit_value',\n            isNotFor: ['roborobo_schoolkit'],\n            func: function (sprite, script) {\n                return '1';\n            },\n            syntax: {\n                js: [],\n                py: ['Roborobo_SchoolKit.schoolkit_on_block()'],\n            },\n        },\n        schoolkit_off_block: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'schoolkit_off_block',\n            },\n            paramsKeyMap: {},\n            class: 'schoolkit_value',\n            isNotFor: ['roborobo_schoolkit'],\n            func: function (sprite, script) {\n                return '0';\n            },\n            syntax: {\n                js: [],\n                py: ['Roborobo_SchoolKit.schoolkit_off_block()'],\n            },\n        },\n        schoolkit_get_out_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 2],\n                        ['OUT2', 3],\n                        ['OUT3', 4],\n                        ['OUT4', 5],\n                        ['OUT5', 6],\n                    ],\n                    value: 2,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function (sprite, script) {\n                return script.getNumberField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['OUT1', 2],\n                                    ['OUT2', 3],\n                                    ['OUT3', 4],\n                                    ['OUT4', 5],\n                                    ['OUT5', 6],\n                                ],\n                                value: 2,\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        keyOption: 'schoolkit_get_out_port_number',\n                    },\n                ],\n            },\n        },\n        schoolkit_get_servo_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['OUT1', 2],\n                        ['OUT2', 3],\n                        ['OUT3', 4],\n                    ],\n                    value: 2,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function (sprite, script) {\n                return script.getNumberField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['OUT1', 2],\n                                    ['OUT2', 3],\n                                    ['OUT3', 4],\n                                ],\n                                value: 2,\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        keyOption: 'schoolkit_get_servo_port_number',\n                    },\n                ],\n            },\n        },\n        schoolkit_get_in_port_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN1', 7],\n                        ['IN2', 8],\n                        ['IN3', 9],\n                        ['IN4', 10],\n                        ['IN5', 11],\n                        ['IN6', 12],\n                        ['IN7', 13],\n                    ],\n                    value: 7,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function (sprite, script) {\n                return script.getNumberField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['IN1', 7],\n                                    ['IN2', 8],\n                                    ['IN3', 9],\n                                    ['IN4', 10],\n                                    ['IN5', 11],\n                                    ['IN6', 12],\n                                    ['IN7', 13],\n                                ],\n                                value: 7,\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        keyOption: 'schoolkit_get_in_port_number',\n                    },\n                ],\n            },\n        },\n        schoolkit_set_output: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.roborobo_on, 'on'],\n                        [Lang.Blocks.roborobo_off, 'off'],\n                    ],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'schoolkit_get_out_port_number',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'schoolkit_set_output',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                OPERATOR: 1,\n            },\n            class: 'schoolkit_set',\n            isNotFor: ['roborobo_schoolkit'],\n            func: function (sprite, script) {\n                var pin = script.getNumberValue('VALUE', script);\n                var operator = script.getField('OPERATOR');\n                var value = operator == 'on' ? 1 : 0;\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n\n                Entry.hw.sendQueue.digitalPinMode[pin] = Entry.Roborobo_SchoolKit.pinMode.OUTPUT;\n                Entry.hw.sendQueue[pin] = value;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roborobo_schoolkit.wirte_digital(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.roborobo_on, 'on'],\n                                    [Lang.Blocks.roborobo_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        schoolkit_get_input_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'schoolkit_get_in_port_number',\n                    },\n                ],\n                type: 'schoolkit_get_input_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'schoolkit_value',\n            isNotFor: ['roborobo_schoolkit'],\n            func: function (sprite, script) {\n                var signal = script.getNumberValue('VALUE', script);\n                return Entry.hw.portData[signal - 7];\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roborobo_schoolkit.read_digital(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        schoolkit_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.roborobo_motor1, 'motor1'],\n                        [Lang.Blocks.roborobo_motor2, 'motor2'],\n                    ],\n                    value: 'motor1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '45'],\n                        ['1', '59'],\n                        ['2', '73'],\n                        ['3', '87'],\n                        ['4', '101'],\n                        ['5', '115'],\n                        ['6', '129'],\n                        ['7', '143'],\n                        ['8', '157'],\n                        ['9', '171'],\n                        ['10', '185'],\n                        ['11', '199'],\n                        ['12', '213'],\n                        ['13', '227'],\n                        ['14', '241'],\n                        ['15', '255'],\n                    ],\n                    value: '45',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.roborobo_motor_CW, 'cw'],\n                        [Lang.Blocks.roborobo_motor_CCW, 'ccw'],\n                        [Lang.Blocks.roborobo_motor_stop, 'stop'],\n                    ],\n                    value: 'cw',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'schoolkit_motor',\n            },\n            paramsKeyMap: {\n                MODE: 0,\n                VALUE: 1,\n                OPERATOR: 2,\n            },\n            class: 'schoolkit_set',\n            isNotFor: ['roborobo_schoolkit'],\n            func: function (sprite, script) {\n                var mode = script.getField('MODE');\n                var pin = 0;\n                var operator = script.getField('OPERATOR');\n                var value = script.getField('VALUE');\n\n                if (mode == 'motor1') {\n                    pin = 0;\n                } else {\n                    pin = 1;\n                }\n\n                if (value > 255) {\n                    value = 255;\n                } else if (value < 0) {\n                    value = 0;\n                }\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n\n                Entry.hw.sendQueue.digitalPinMode[pin] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                Entry.hw.sendQueue.digitalPinMode[pin + 7] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                if (operator == 'cw') {\n                    Entry.hw.sendQueue[pin] = value;\n                } else if (operator == 'ccw') {\n                    Entry.hw.sendQueue[pin] = -value;\n                } else if (operator == 'stop') {\n                    Entry.hw.sendQueue[pin] = 0x00;\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roborobo_schoolkit.move_motor_speed(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.roborobo_motor1, 'motor1'],\n                                    [Lang.Blocks.roborobo_motor2, 'motor2'],\n                                ],\n                                value: 'motor1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '45'],\n                                    ['1', '59'],\n                                    ['2', '73'],\n                                    ['3', '87'],\n                                    ['4', '101'],\n                                    ['5', '115'],\n                                    ['6', '129'],\n                                    ['7', '143'],\n                                    ['8', '157'],\n                                    ['9', '171'],\n                                    ['10', '185'],\n                                    ['11', '199'],\n                                    ['12', '213'],\n                                    ['13', '227'],\n                                    ['14', '241'],\n                                    ['15', '255'],\n                                ],\n                                value: '45',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.roborobo_motor_CW, 'cw'],\n                                    [Lang.Blocks.roborobo_motor_CCW, 'ccw'],\n                                    [Lang.Blocks.roborobo_motor_stop, 'stop'],\n                                ],\n                                value: 'cw',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        schoolkit_set_servo_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'schoolkit_get_servo_port_number',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'schoolkit_set_servo_value',\n            },\n            paramsKeyMap: {\n                PIN: 0,\n                VALUE: 1,\n            },\n            class: 'schoolkit_set',\n            isNotFor: ['roborobo_schoolkit'],\n            func: function (sprite, script) {\n                var pin = script.getNumberValue('PIN', script);\n                var value = script.getNumberValue('VALUE');\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n                Entry.hw.sendQueue.digitalPinMode[pin] = Entry.Roborobo_SchoolKit.pinMode.SERVO;\n\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 180) {\n                    value = 180;\n                }\n                Entry.hw.sendQueue[pin] = value;\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Roborobo_schoolkit.move_servo(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        //endregion schoolkit 스쿨키트\n    };\n};\n\nEntry.Roborobo_SchoolKit.getPracticalBlocks = function () {\n    return {\n        // roborobo_mini\n        roborobo_motor_speed: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic_string_field',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '52'],\n                        ['2', '66'],\n                        ['3', '80'],\n                        ['4', '94'],\n                        ['5', '107'],\n                        ['6', '120'],\n                        ['7', '134'],\n                        ['8', '148'],\n                        ['9', '162'],\n                        ['10', '176'],\n                        ['11', '190'],\n                        ['12', '204'],\n                        ['13', '218'],\n                        ['14', '232'],\n                        ['15', '255'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func (sprite, script) {\n                return script.getStringField('VALUE');\n            },\n        },\n        roborobo_move_for_secs: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1모터를 %2 %3의 속도로 %4초 동안 회전 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['양쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['왼쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '1'],\n                        ['뒤로', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'roborobo_motor_speed',\n                    },\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'roborobo_move_for_secs',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n                DURATION: 3,\n            },\n            class: 'roborobo_motor',\n            func (sprite, script) {\n                const motor1 = 0;\n                const motor2 = 1;\n                const wheel = script.getNumberField('WHEEL');\n                const speed = script.getNumberValue('SPEED');\n                const direction = script.getNumberField('DIRECTION');\n                const duration = script.getNumberValue('DURATION');\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n\n                if (!script.isStart) {\n                    if (wheel == 1) {\n                        Entry.hw.sendQueue.digitalPinMode[7] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                        Entry.hw.sendQueue.digitalPinMode[0] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                        Entry.hw.sendQueue.digitalPinMode[8] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                        Entry.hw.sendQueue.digitalPinMode[1] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                        if (direction == 1) {\n                            Entry.hw.sendQueue[motor1] = speed;\n                            Entry.hw.sendQueue[motor2] = speed;\n                        } else if (direction == 2) {\n                            Entry.hw.sendQueue[motor1] = -speed;\n                            Entry.hw.sendQueue[motor2] = -speed;\n                        }\n                    } else if (wheel == 2) {\n                        Entry.hw.sendQueue.digitalPinMode[8] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                        Entry.hw.sendQueue.digitalPinMode[1] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                        if (direction == 1) {\n                            Entry.hw.sendQueue[motor1] = 0x00;\n                            Entry.hw.sendQueue[motor2] = speed;\n                        } else if (direction == 2) {\n                            Entry.hw.sendQueue[motor1] = 0x00;\n                            Entry.hw.sendQueue[motor2] = -speed;\n                        }\n                    } else if (wheel == 3) {\n                        Entry.hw.sendQueue.digitalPinMode[7] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                        Entry.hw.sendQueue.digitalPinMode[0] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                        if (direction == 1) {\n                            Entry.hw.sendQueue[motor1] = speed;\n                            Entry.hw.sendQueue[motor2] = 0x00;\n                        } else if (direction == 2) {\n                            Entry.hw.sendQueue[motor1] = -speed;\n                            Entry.hw.sendQueue[motor2] = 0x00;\n                        }\n                    }\n\n                    script.wheelMode = wheel;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue[motor1] = 0x00;\n                    Entry.hw.sendQueue[motor2] = 0x00;\n\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    delete script.wheelMode;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        roborobo_move_for: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1모터를 %2 %3의 속도로 계속 회전 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['양쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['왼쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '1'],\n                        ['뒤로', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'roborobo_motor_speed',\n                    },\n                    null,\n                ],\n                type: 'roborobo_move_for',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'roborobo_motor',\n            //'isNotFor': ['mini'],\n            func (sprite, script) {\n                const motor1 = 0;\n                const motor2 = 1;\n                const wheel = script.getNumberField('WHEEL');\n                const speed = script.getNumberValue('SPEED');\n                const direction = script.getNumberField('DIRECTION');\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n\n                if (wheel == 1) {\n                    Entry.hw.sendQueue.digitalPinMode[7] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[0] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[8] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[1] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                    if (direction == 1) {\n                        Entry.hw.sendQueue[motor1] = speed;\n                        Entry.hw.sendQueue[motor2] = speed;\n                    } else if (direction == 2) {\n                        Entry.hw.sendQueue[motor1] = -speed;\n                        Entry.hw.sendQueue[motor2] = -speed;\n                    }\n                } else if (wheel == 2) {\n                    Entry.hw.sendQueue.digitalPinMode[8] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[1] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                    if (direction == 1) {\n                        Entry.hw.sendQueue[motor1] = 0x00;\n                        Entry.hw.sendQueue[motor2] = speed;\n                    } else if (direction == 2) {\n                        Entry.hw.sendQueue[motor1] = 0x00;\n                        Entry.hw.sendQueue[motor2] = -speed;\n                    }\n                } else if (wheel == 3) {\n                    Entry.hw.sendQueue.digitalPinMode[7] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[0] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                    if (direction == 1) {\n                        Entry.hw.sendQueue[motor1] = speed;\n                        Entry.hw.sendQueue[motor2] = 0x00;\n                    } else if (direction == 2) {\n                        Entry.hw.sendQueue[motor1] = -speed;\n                        //Entry.hw.sendQueue[motor2] = 0x00;\n                    }\n                }\n\n                return script.callReturn();\n            },\n        },\n        roborobo_turn_for: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '오른쪽 모터를 %1 %2, 왼쪽 모터를 %3 %4의 속도로 계속 회전 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '1'],\n                        ['뒤로', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['앞으로', '1'],\n                        ['뒤로', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {type: 'roborobo_motor_speed'},\n                    null,\n                    {type: 'roborobo_motor_speed'},\n                    null,\n                ],\n                type: 'roborobo_turn_for',\n            },\n            paramsKeyMap: {\n                RDIR: 0,\n                RSPEED: 1,\n                LDIR: 2,\n                LSPEED: 3,\n            },\n            class: 'roborobo_motor',\n            //'isNotFor': ['mini'],\n            func (sprite, script) {\n                const motor1 = 0;\n                const motor2 = 1;\n\n                const rightDir = script.getNumberField('RDIR');\n                const rightSpeed = script.getNumberValue('RSPEED');\n                const leftDir = script.getNumberField('LDIR');\n                const leftSpeed = script.getNumberValue('LSPEED');\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n\n                Entry.hw.sendQueue.digitalPinMode[7] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                Entry.hw.sendQueue.digitalPinMode[0] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                Entry.hw.sendQueue.digitalPinMode[8] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                Entry.hw.sendQueue.digitalPinMode[1] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                if (leftDir == 1) {\n                    Entry.hw.sendQueue[motor1] = leftSpeed;\n                } else {\n                    Entry.hw.sendQueue[motor1] = -leftSpeed;\n                }\n\n                if (rightDir == 1) {\n                    Entry.hw.sendQueue[motor2] = rightSpeed;\n                } else {\n                    Entry.hw.sendQueue[motor2] = -rightSpeed;\n                }\n\n                return script.callReturn();\n            },\n        },\n        roborobo_stop_for: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1모터를 정지 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['양쪽', '1'],\n                        ['오른쪽', '2'],\n                        ['왼쪽', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'roborobo_stop_for',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n            },\n            class: 'roborobo_motor',\n            func (sprite, script) {\n                const motor1 = 0;\n                const motor2 = 1;\n                const wheel = script.getNumberField('WHEEL');\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n\n                if (wheel == 1) {\n                    Entry.hw.sendQueue.digitalPinMode[7] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[0] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[8] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[1] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                    Entry.hw.sendQueue[motor1] = 0x00;\n                    Entry.hw.sendQueue[motor2] = 0x00;\n                } else if (wheel == 2) {\n                    Entry.hw.sendQueue.digitalPinMode[8] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[1] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                    Entry.hw.sendQueue[motor2] = 0x00;\n                } else if (wheel == 3) {\n                    Entry.hw.sendQueue.digitalPinMode[7] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                    Entry.hw.sendQueue.digitalPinMode[0] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                    Entry.hw.sendQueue[motor1] = 0x00;\n                }\n\n                return script.callReturn();\n            },\n        },\n        roborobo_touch_value: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '접촉 센서 값',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'roborobo_touch_value',\n            },\n            paramsKeyMap: {},\n            class: 'roborobo_touch',\n            func (sprite, script) {\n                const port = Entry.Roborobo_SchoolKit.inputPort.contact;\n                Entry.hw.sendQueue.digitalPinMode[port] = Entry.Roborobo_SchoolKit.pinMode.INPUT;\n                Entry.hw.update();\n                return Entry.hw.portData[port - 7];\n            },\n        },\n        roborobo_touch_value_boolean: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['roborobo_schoolkit'],\n            template: '접촉 센서가 %1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['접촉 되면', '1'],\n                        ['접촉 안되면', '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'roborobo_touch_value_boolean',\n            },\n            paramsKeyMap: {\n                TOUCH: 0,\n            },\n            class: 'roborobo_touch',\n            func (sprite, script) {\n                const port = Entry.Roborobo_SchoolKit.inputPort.contact;\n                const touch = script.getNumberField('TOUCH', script);\n\n                Entry.hw.sendQueue.digitalPinMode[port] = Entry.Roborobo_SchoolKit.pinMode.INPUT;\n                Entry.hw.update();\n\n                const value = Entry.hw.portData[port - 7];\n                const isTouch = touch == value;\n\n                return isTouch;\n            },\n        },\n        roborobo_light_value: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: 'CDS 센서 값',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'roborobo_light_value',\n            },\n            paramsKeyMap: {},\n            class: 'roborobo_light',\n            func (sprite, script) {\n                const port = Entry.Roborobo_SchoolKit.inputPort.cds;\n                return Entry.hw.portData[port - 7];\n            },\n        },\n        roborobo_light_value_boolean: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['roborobo_schoolkit'],\n            template: 'CDS 센서 값 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['512'],\n                    },\n                ],\n                type: 'roborobo_light_value_boolean',\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n                RIGHTVALUE: 1,\n            },\n            class: 'roborobo_light',\n            func (sprite, script) {\n                const port = Entry.Roborobo_SchoolKit.inputPort.cds;\n                const operator = script.getField('OPERATOR', script);\n                let rightValue = script.getNumberValue('RIGHTVALUE', script);\n                const leftValue = Entry.hw.portData[port - 7];\n                let isCheck = false;\n\n                if (rightValue < 0) {\n                    rightValue = 0;\n                } else if (rightValue > 1023) {\n                    rightValue = 1023;\n                }\n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n                return isCheck;\n            },\n        },\n        roborobo_sound_value: {\n            color: '#01d67f',\n            outerLine: '#00b36a',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '소리 센서에 감지되는 소리 값',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'roborobo_sound_value',\n            },\n            paramsKeyMap: {},\n            class: 'roborobo_sound',\n            func (sprite, script) {\n                const port = Entry.Roborobo_SchoolKit.inputPort.sound;\n                return Entry.hw.portData[port - 7];\n            },\n        },\n        roborobo_sound_value_boolean: {\n            color: '#01d67f',\n            outerLine: '#00b36a',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['roborobo_schoolkit'],\n            template: '소리 센서에 감지되는 소리 값 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#00b36a',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['512'],\n                    },\n                ],\n                type: 'roborobo_sound_value_boolean',\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n                RIGHTVALUE: 1,\n            },\n            class: 'roborobo_sound',\n            func (sprite, script) {\n                const port = Entry.Roborobo_SchoolKit.inputPort.sound;\n                const operator = script.getField('OPERATOR', script);\n                let rightValue = script.getNumberValue('RIGHTVALUE', script);\n                const leftValue = Entry.hw.portData[port - 7];\n                let isCheck = false;\n\n                if (rightValue < 0) {\n                    rightValue = 0;\n                } else if (rightValue > 1023) {\n                    rightValue = 1023;\n                }\n\n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n\n                return isCheck;\n            },\n        },\n        roborobo_irs_value: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '적외선 센서 값',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'roborobo_irs_value',\n            },\n            paramsKeyMap: {},\n            class: 'roborobo_irs',\n            //'isNotFor': ['mini'],\n            func (sprite, script) {\n                const port = Entry.Roborobo_SchoolKit.inputPort.ir;\n                const value =\n                    Entry.hw.portData[port - 7] == undefined ? 0 : Entry.hw.portData[port - 7];\n                return value;\n            },\n        },\n        roborobo_irs_value_boolean: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['roborobo_schoolkit'],\n            template: '적외선 센서가 %1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['감지 되면', '1'],\n                        ['감지 안되면', '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'roborobo_irs_value_boolean',\n            },\n            paramsKeyMap: {\n                DETECT: 0,\n            },\n            class: 'roborobo_irs',\n            //'isNotFor': ['mini'],\n            func (sprite, script) {\n                const port = Entry.Roborobo_SchoolKit.inputPort.ir;\n                const detect = script.getNumberField('DETECT', script);\n\n                Entry.hw.sendQueue.digitalPinMode[port] = Entry.Roborobo_SchoolKit.pinMode.INPUT;\n                Entry.hw.update();\n\n                const value = Entry.hw.portData[port - 7];\n                const isDetect = detect == value;\n\n                return isDetect;\n            },\n        },\n        roborobo_diode_secs_toggle: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1번 포트의 발광다이오드를 %2초 동안 %3 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LED 1', '5'],\n                        ['LED 2', '4'],\n                        ['R - A', '3'],\n                        ['R - B', '2'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', '255'],\n                        ['끄기', '0'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/diode.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'roborobo_diode_secs_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DURATION: 1,\n                VALUE: 2,\n            },\n            class: 'roborobo_diode',\n            func (sprite, script) {\n                const port = script.getNumberField('PORT');\n                const duration = script.getNumberValue('DURATION');\n                const value = script.getNumberField('VALUE');\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n                Entry.hw.sendQueue.digitalPinMode[port] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    Entry.hw.sendQueue[port] = value;\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration * 1000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    Entry.hw.sendQueue[port] = 0;\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        roborobo_diode_toggle: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1번 포트의 발광다이오드를 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LED 1', '5'],\n                        ['LED 2', '4'],\n                        ['R - A', '3'],\n                        ['R - B', '2'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', '255'],\n                        ['끄기', '0'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/diode.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'roborobo_diode_toggle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'roborobo_diode',\n            //'isNotFor': ['mini'],\n            func (sprite, script) {\n                const port = script.getNumberField('PORT');\n                const value = script.getNumberField('VALUE');\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n\n                Entry.hw.sendQueue.digitalPinMode[port] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                Entry.hw.sendQueue[port] = value;\n\n                return script.callReturn();\n            },\n        },\n        roborobo_diode_inout_toggle: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1번 포트의 발광다이오드를 %2번 포트의 %3~%4의 범위로 켜기%5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LED 1', '5'],\n                        ['LED 2', '4'],\n                        ['R - A', '3'],\n                        ['R - B', '2'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['소 리', '8'],\n                        ['CDS', '10'],\n                    ],\n                    value: '8',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/diode.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {type: 'number', params: ['0']},\n                    {type: 'number', params: ['255']},\n                    null,\n                ],\n                type: 'roborobo_diode_inout_toggle',\n            },\n            paramsKeyMap: {\n                OUTPUT: 0,\n                INPUT: 1,\n                MIN: 2,\n                MAX: 3,\n            },\n            class: 'roborobo_diode',\n            //'isNotFor': ['mini'],\n            func (sprite, script) {\n                const outputPort = script.getNumberField('OUTPUT');\n                const inputPort = script.getNumberField('INPUT');\n\n                const oMin = script.getNumberValue('MIN');\n                const oMax = script.getNumberValue('MAX');\n                const nMin = 0;\n                const nMax = 255;\n                const x = Entry.hw.portData[inputPort - 7] / 4;\n                const percent = (x - oMin) / (oMax - oMin);\n                let result = percent * (nMax - nMin) + nMin;\n                if (result > nMax) {\n                    result = nMax;\n                }\n                if (result < nMin) {\n                    result = nMin;\n                }\n\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n\n                Entry.hw.sendQueue.digitalPinMode[outputPort] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                Entry.hw.sendQueue[outputPort] = result;\n\n                return script.callReturn();\n            },\n        },\n        roborobo_diode_set_output: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1번 포트의 발광다이오드를 %2의 밝기로 켜기 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LED 1', '5'],\n                        ['LED 2', '4'],\n                        ['R - A', '3'],\n                        ['R - B', '2'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/diode.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'roborobo_diode_set_output',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'roborobo_diode',\n            //'isNotFor': ['mini'],\n            func (sprite, script) {\n                const port = script.getStringField('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n\n                if (value < 0) {\n                    value = 0;\n                } else if (value > 255) {\n                    value = 255;\n                }\n                if (!Entry.hw.sendQueue.digitalPinMode) {\n                    Entry.hw.sendQueue.digitalPinMode = {};\n                }\n                Entry.hw.sendQueue.digitalPinMode[port] = Entry.Roborobo_SchoolKit.pinMode.PWM;\n                Entry.hw.sendQueue[port] = value;\n\n                return script.callReturn();\n            },\n        },\n        roborobo_diode_input_value: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['roborobo_schoolkit'],\n            template: '%1 포트의 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['적외선', '7'],\n                        ['소 리', '8'],\n                        ['접 촉', '9'],\n                        ['CDS', '10'],\n                    ],\n                    value: '8',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'roborobo_diode_input_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'roborobo_diode',\n            func (sprite, script) {\n                const port = script.getNumberField('PORT');\n                return Entry.hw.portData[port - 7];\n            },\n        },\n    }\n}\n\nmodule.exports = Entry.Roborobo_SchoolKit;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotamicoding.js",
    "content": "'use strict';\n\nEntry.RobotamiCoding = {\n    id: '2A.1',\n    name: 'RobotamiCoding',\n    url: 'http://robotron.co.kr/',\n    imageName: 'robotamicoding.png', //thumbnail. 신규등록시 images/hw, images/hardware 에 이미지가 있어야합니다.\n    title: {\n        \"ko\": '로보타미코딩',\n        \"en\": 'RobotamiCoding'\n    },\n    setZero: function() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        NOTONE: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        DC_MOTOR: 9,\n        DC_STOP: 10,\n        ROBOT: 11,\n        ROBOT_STOP: 12,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    direction: {\n        CENTER: 0,\n        UP: 1,\n        DOWN: 2,\n        LEFT: 3,\n        LEFT_UP: 4,\n        LEFT_DOWN: 5,\n        RIGHT: 6,\n        RIGHT_UP: 7,\n        RIGHT_DOWN: 8,\n    },\n    move: {\n        FORWARD: [1.0, 1.0],\n        BACKWARD: [-1.0, -1.0],\n        LEFT: [0.5, 1.0],\n        RIGHT: [1.0, 0.5],\n    },\n    color: {\n        RED: [1.0, 0.0, 0.0],\n        ORANGE: [1.0, 0.6, 0.0],\n        YELLOW: [1.0, 1.0, 0.0],\n        GREEN: [0.0, 1.0, 0.0],\n        BLUE: [0.0, 0.0, 1.0],\n        INDIGO: [0.2, 0.2, 1.0],\n        PURPLE: [1.0, 0.0, 1.0],\n        PINK: [1.0, 0.6, 1.0],\n        SKYBLUE: [0.2, 1.0, 1.0],        \n        WHITE: [1.0, 1.0, 1.0],\n        ALL: [1.0, 1.0, 1.0],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.RobotamiCoding.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n                ROBOTAMICODING_DCM_CLOCKWISE: '시계방향',\n                ROBOTAMICODING_DCM_COUNTERCLOCKWISE: '반시계방향',\n                ROBOTAMICODING_ROBOT_FORWARD: '전진',\n                ROBOTAMICODING_ROBOT_BACKWARD: '후진',\n                ROBOTAMICODING_ROBOT_LEFT: '좌회전',\n                ROBOTAMICODING_ROBOT_RIGHT: '우회전',\n                ROBOTAMICODING_ROBOT_GOLEFT: '전진좌회전',\n                ROBOTAMICODING_ROBOT_GORIGHT: '전진우회전',\n                ROBOTAMICODING_ROBOT_TURNLEFT: '제자리좌회전',\n                ROBOTAMICODING_ROBOT_TURNRIGHT: '제자리우회전',\n\n                ROBOTAMICODING_JOYSTICK_CENTER: '가운데',\n\t            ROBOTAMICODING_JOYSTICK_UP: '위',\n                ROBOTAMICODING_JOYSTICK_DOWN: '아래',\n                ROBOTAMICODING_JOYSTICK_LEFT: '왼쪽',\n\t            ROBOTAMICODING_JOYSTICK_LEFT_UP: '왼쪽 위',\n                ROBOTAMICODING_JOYSTICK_LEFT_DOWN: '왼쪽 아래',                \n                ROBOTAMICODING_JOYSTICK_RIGHT: '오른쪽',\n                ROBOTAMICODING_JOYSTICK_RIGHT_UP: '오른쪽 위',\n                ROBOTAMICODING_JOYSTICK_RIGHT_DOWN: '오른쪽 아래',\n\n                ROBOTAMICODING_COLOR_RED: '빨강',\n                ROBOTAMICODING_COLOR_ORANGE: '주황',\n                ROBOTAMICODING_COLOR_YELLOW: '노랑',\n                ROBOTAMICODING_COLOR_GREEN: '초록',\n                ROBOTAMICODING_COLOR_BLUE: '파랑',\n                ROBOTAMICODING_COLOR_INDIGO: '남색',\n                ROBOTAMICODING_COLOR_PURPLE: '보라',\n                ROBOTAMICODING_COLOR_PINK: '분홍',\n                ROBOTAMICODING_COLOR_SKYBLUE: '하늘색',  \n                ROBOTAMICODING_COLOR_WHITE: '하양',\n                ROBOTAMICODING_COLOR_ALL: '모두',                \n\n                ROBOTAMICODING_BUZZER_WN: '온음표',\n                ROBOTAMICODING_BUZZER_HN: '2분음표',\n                ROBOTAMICODING_BUZZER_QN: '4분음표',\n                ROBOTAMICODING_BUZZER_EN: '8분음표',\n                ROBOTAMICODING_BUZZER_SN: '16분음표',\n                ROBOTAMICODING_BUZZER_TN: '32분음표',                \n\n            },\n            template: {\n                robotami_coding_get_analog_value: '아날로그 %1 번 포트 입력값',\n                robotami_coding_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 변환값',                \n                robotami_coding_get_digital_value: '디지털 %1 번 포트 입력값이 참',                \n                robotami_coding_get_joystick:'조이스틱 방향이 %1',\n                robotami_coding_get_joystick_button: '조이스틱 버튼 %1 번이 눌러져 있다',\n                robotami_coding_set_digital_value: '디지털 %1 번 포트로 %2 출력하기 %3',\n                robotami_coding_toggle_led:  'LED %1 번 포트로 %2 %3',\n                robotami_coding_set_pwm: 'PWM %1 번 포트로 %2 출력하기 %3',\n                robotami_coding_set_rgb: 'RGB LED 빨강을 %1번 포트로 %4%  초록을 %2번 포트로 %5%  파랑을 %3번 포트로 %6% 켜기 %7',\n                robotami_coding_set_rgb_color: 'RGB LED %1색을 밝기 %2%로 켜기 %3',\n                robotami_coding_set_tone_octav_time: '계명 %1 를 %2 옥타브로 %3 초 동안 연주하기 %4',\n                robotami_coding_set_tone_octav_beat: '계명 %1 를 %2 옥타브로 %3  로 연주하기 %4',\n                robotami_coding_set_tone_freq: '주파수 %1 Hz음을 %2 초 연주하기 %3',\n                robotami_coding_set_tone_off: '%1 민큼 연주쉬기 %2',\n                robotami_coding_set_servo: '서보모터 %1 을 %2 도 위치로 회전 시키기 %3',\n                robotami_coding_set_dcm_value: 'DC모터 %1 번을 %2 의 속도로 %3 으로 회전 시키기 %4',\n                robotami_coding_set_dcm_stop: 'DC모터 %1 번 정지시키기 %2',\n                robotami_coding_set_robot_value: '로봇을 %1 의 속도로 %2 시키기 %3',\n                robotami_coding_set_robot_stop: '로봇 정지시키기 %1',\n            },\n        },\n        en: {\n            Blocks: {\n                ROBOTAMICODING_DCM_CLOCKWISE: 'CW',\n                ROBOTAMICODING_DCM_COUNTERCLOCKWISE: 'CCW',\n                ROBOTAMICODING_ROBOT_FORWARD: 'go forward',\n                ROBOTAMICODING_ROBOT_BACKWARD: 'go backward',\n                ROBOTAMICODING_ROBOT_LEFT: 'turn left',\n                ROBOTAMICODING_ROBOT_RIGHT: 'turn right',\n                ROBOTAMICODING_ROBOT_GOLEFT: 'move forward to the left',\n                ROBOTAMICODING_ROBOT_GORIGHT: 'move forward to the right',\n                ROBOTAMICODING_ROBOT_TURNLEFT: 'turn left in place',\n                ROBOTAMICODING_ROBOT_TURNRIGHT: 'turn right in place',\n\n                ROBOTAMICODING_JOYSTICK_CENTER: 'CENTER데',\n\t            ROBOTAMICODING_JOYSTICK_UP: 'UP',\n                ROBOTAMICODING_JOYSTICK_DOWN: 'DOWN',\n                ROBOTAMICODING_JOYSTICK_LEFT: 'LEF',\n\t            ROBOTAMICODING_JOYSTICK_LEFT_UP: 'LEFT_UP',\n                ROBOTAMICODING_JOYSTICK_LEFT_DOWN: 'ㅣEFT_DOWN',                \n                ROBOTAMICODING_JOYSTICK_RIGHT: 'RIGHT',\n                ROBOTAMICODING_JOYSTICK_RIGHT_UP: 'RIGHT_UP',\n                ROBOTAMICODING_JOYSTICK_RIGHT_DOWN: 'RIGHT_DOWN',\n\n                ROBOTAMICODING_COLOR_RED: 'RED',\n                ROBOTAMICODING_COLOR_ORANGE: 'ORANGE',\n                ROBOTAMICODING_COLOR_YELLOW: 'YELLOW',\n                ROBOTAMICODING_COLOR_GREEN: 'GREEN',\n                ROBOTAMICODING_COLOR_BLUE: 'BLUE',\n                ROBOTAMICODING_COLOR_INDIGO: 'INDIGO',\n                ROBOTAMICODING_COLOR_PURPLE: 'PURPLE',\n                ROBOTAMICODING_COLOR_PINK: 'PINK',\n                ROBOTAMICODING_COLOR_SKYBLUE: 'SKYBLUE',  \n                ROBOTAMICODING_COLOR_WHITE: 'WHITE',\n                ROBOTAMICODING_COLOR_ALL: 'ALL', \n\n                ROBOTAMICODING_BUZZER_WN: '온음표',\n                ROBOTAMICODING_BUZZER_HN: '2분음표',\n                ROBOTAMICODING_BUZZER_QN: '4분음표',\n                ROBOTAMICODING_BUZZER_EN: '8분음표',\n                ROBOTAMICODING_BUZZER_SN: '16분음표',\n                ROBOTAMICODING_BUZZER_TN: '32분음표',\n            },\n            template: {\n                robotami_coding_get_analog_value: 'value of analog %1',\n                robotami_coding_get_analog_value_map: 'Map value %1 %2 ~ %3 to %4 ~ %5',\n                robotami_coding_get_digital_value: 'value of digital %1',                \n                robotami_coding_get_joystick:'Joystic Direction %1?',\n                robotami_coding_get_joystick_button: 'joystic button %1 pressed',\n                robotami_coding_set_digital_value: 'set digital port %1 for output %2 %3',\n                robotami_coding_toggle_led: 'turn LED port %1 for output %2 %3',\n                robotami_coding_set_pwm: 'set PWM port %1 for output %2 %3',\n                robotami_coding_set_rgb: 'set RGB LED Red %1 port %4%, Green %2 port %5%, Blue %3 port %6% output %7',\n                robotami_coding_set_rgb_color: 'turn on RGB  %1color  %2 brightness %3',\n                robotami_coding_set_tone_octav_time: 'play tone on note %1 octave %2 for %3 seconds %4',\n                robotami_coding_set_tone_octav_beat: 'play tone on note %1 octave %2 for %3 beat %4',\n                robotami_coding_set_tone_freq: 'frequency %1 Hz note %2 play tone %3',\n                robotami_coding_set_tone_off: '%1  no play tone %2',\n                robotami_coding_set_servo: 'set servo motor %1 for angle %2 %3',\n                robotami_coding_set_dcm_value: 'set DC motor %1 speed %2, direction %3 %4',\n                robotami_coding_set_dcm_stop: 'stop DC motor %1 %2',\n                robotami_coding_set_robot_value: 'move robot %2 at speed %1 %3',\n                robotami_coding_set_robot_stop: 'stop robot %1',\n            },\n        },\n    };\n};\n\nEntry.RobotamiCoding.blockMenuBlocks = [\n    'robotami_coding_get_analog_value',\n    'robotami_coding_get_analog_value_map',\n    'robotami_coding_get_digital_value',\n    'robotami_coding_get_joystick',\n    'robotami_coding_get_joystick_button',\n    'robotami_coding_set_digital_value',\n    'robotami_coding_toggle_led',\n    'robotami_coding_set_pwm',\n    'robotami_coding_set_rgb',\n    'robotami_coding_set_rgb_color',\n    'robotami_coding_set_tone_octav_time',\n    'robotami_coding_set_tone_octav_beat',\n    'robotami_coding_set_tone_freq',\n    'robotami_coding_set_tone_off',\n    'robotami_coding_set_servo',\n    'robotami_coding_set_dcm_value',\n    'robotami_coding_set_dcm_stop',\n    'robotami_coding_set_robot_value',\n    'robotami_coding_set_robot_stop',\n];\n\nEntry.RobotamiCoding.getBlocks = function() {\n    return {\n\n        // 로보타미 코딩 아날로그 리스트\n        robotami_coding_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: undefined,\n        },\n        \n        robotami_coding_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_analog_list',\n                    },\n                ],\n                type: 'robotami_coding_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'RobotamiCodingGet',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') port = port.substring(1);\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: undefined,\n        },\n        robotami_coding_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_get_analog_value',\n                        params: [\n                            {\n                                type: 'robotami_coding_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'robotami_coding_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'RobotamiCodingGet',\n            isNotFor: ['RobotamiCoding'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        // 로보타미 코딩 디지털 리스트\n        robotami_coding_digital_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: undefined,\n        },\n\n        robotami_coding_get_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_digital_list',\n                    },\n                ],\n                type: 'robotami_coding_get_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'RobotamiCodingGet',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'RobotamiCoding') {\n                    var port = script.getNumberValue('PORT', script);\n                    var DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue['GET']) {\n                        Entry.hw.sendQueue['GET'] = {};\n                    }\n                    Entry.hw.sendQueue['GET'][Entry.RobotamiCoding.sensorTypes.DIGITAL] = {\n                        port: port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.robotami_coding_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: undefined,\n        },\n        \n        robotami_coding_get_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n\t\t                [Lang.Blocks.ROBOTAMICODING_JOYSTICK_CENTER, '0'],\n                        [Lang.Blocks.ROBOTAMICODING_JOYSTICK_UP, '1'],\n                        [Lang.Blocks.ROBOTAMICODING_JOYSTICK_DOWN, '2'],\n                        [Lang.Blocks.ROBOTAMICODING_JOYSTICK_LEFT, '3'],                        \n                        [Lang.Blocks.ROBOTAMICODING_JOYSTICK_LEFT_UP, '4'],\n                        [Lang.Blocks.ROBOTAMICODING_JOYSTICK_LEFT_DOWN,'5'],\n                        [Lang.Blocks.ROBOTAMICODING_JOYSTICK_RIGHT,'6'],\n                        [Lang.Blocks.ROBOTAMICODING_JOYSTICK_RIGHT_UP, '7'],\n                        [Lang.Blocks.ROBOTAMICODING_JOYSTICK_RIGHT_DOWN, '8'],                        \n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotami_coding_get_joystick',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'RobotamiCodingGet',\n            isNotFor: ['RobotamiCoding'],\n            func(sprite, script) {\n                const direction = script.getField('DIRECTION', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n\n                const getValue = function(w) {\n                    return ANALOG[w] <= 20 ? 0 : ANALOG[w] >= 42 ? 2 : 1;\n                };\n\n                if (\n                    direction == Entry.RobotamiCoding.direction.CENTER &&\n                    getValue(0) == 1 &&\n                    getValue(1) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.RobotamiCoding.direction.UP &&\n                    getValue(0) == 1 &&\n                    getValue(1) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.RobotamiCoding.direction.DOWN &&\n                    getValue(0) == 1 &&\n                    getValue(1) == 2\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.RobotamiCoding.direction.LEFT &&\n                    getValue(0) == 0 &&\n                    getValue(1) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.RobotamiCoding.direction.LEFT_UP &&\n                    getValue(0) == 0 &&\n                    getValue(1) == 0\n                ) {\n                    return 1;\n                }  else if (\n                    direction == Entry.RobotamiCoding.direction.LEFT_DOWN &&\n                    getValue(0) == 0 &&\n                    getValue(1) == 2\n                ) {\n                    return 1;\n                }else if (\n                    direction == Entry.RobotamiCoding.direction.RIGHT &&\n                    getValue(0) == 2 &&\n                    getValue(1) == 1\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.RobotamiCoding.direction.RIGHT_UP &&\n                    getValue(0) == 2 &&\n                    getValue(1) == 0\n                ) {\n                    return 1;\n                } else if (\n                    direction == Entry.RobotamiCoding.direction.RIGHT_DOWN &&\n                    getValue(0) == 2 &&\n                    getValue(1) == 2\n                ) {\n                    return 1;\n                }\n                return 0;\n            },\n        },              \n        robotami_coding_get_joystick_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n\t\t                ['A2', '2'],                                               \n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },                 \n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotami_coding_get_joystick_button',\n            },\n            paramsKeyMap: {},        \n            class: 'RobotamiCodingGet',\n            isNotFor: ['RobotamiCoding'],\n            func(sprite, script) {\n                const ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[2] == 0 : 1;\n            },\n        },\n        // 로보타미 코딩 디지털 리스트\n        robotami_coding_digital_value_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('VALUE');\n            },\n            syntax: undefined,\n        },\n\n        robotami_coding_set_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_digital_list',\n                    },\n                    {\n                        type: 'robotami_coding_digital_value_list',\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_set_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RobotamiCoding.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: undefined,\n        },\n        robotami_coding_toggle_led_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],                       \n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: undefined,\n        },\n        robotami_coding_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_toggle_led_list',                       \n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.RobotamiCoding.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.RobotamiCoding.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.RobotamiCoding.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        // 로보타미 코딩 PWM 포트 리스트\n        robotami_coding_pwm_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: undefined,\n        },\n\n        robotami_coding_set_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_pwm_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_set_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RobotamiCoding.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: undefined,\n        },        \n                \n        robotami_coding_set_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            //template: Lang.template.robotami_coding_set_rgb,\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['11', '11'],                       \n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['10', '10'],                       \n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['9', '9'],                       \n                    ],\n                    value: '9',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,                    \n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,                    \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'robotami_coding_set_rgb',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n                VALUE1: 3,\n                VALUE2: 4,\n                VALUE3: 5,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var port1 = script.getNumberValue('PORT1', script);\n                var port2 = script.getNumberValue('PORT2', script);\n                var port3 = script.getNumberValue('PORT3', script);\n\n                var value1 = script.getNumberValue('VALUE1', script);\n                    value1 = Math.round(2.55*value1);\n                    value1 =Math.max(Math.min(value1, 255), 0);                    \n\n                var value2 = script.getNumberValue('VALUE2', script);\n                    value2 = Math.round(2.55*value2);\n                    value2 =Math.max(Math.min(value2, 255), 0);\n                    \n                var value3 = script.getNumberValue('VALUE3', script);\n                    value3 = Math.round(2.55*value3);\n                    value3 =Math.max(Math.min(value3, 255), 0);                                                   \n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[8] = {\n                    type: Entry.RobotamiCoding.sensorTypes.DIGITAL,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.RobotamiCoding.sensorTypes.PWM,\n                    data: value1,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.RobotamiCoding.sensorTypes.PWM,\n                    data: value2,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port3] = {\n                    type: Entry.RobotamiCoding.sensorTypes.PWM,\n                    data: value3,\n                    time: new Date().getTime(),\n                };\n                 return script.callReturn();\n            },\n            syntax: { js: [], py: [{}] },\n        },\n        robotami_coding_set_rgb_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_RED, '빨강'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_ORANGE, '주황'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_YELLOW, '노랑'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_GREEN, '초록'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_BLUE, '파랑'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_INDIGO, '남색'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_PURPLE, '보라'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_PINK, '분홍'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_SKYBLUE, '하늘색'],         \n                        [Lang.Blocks.ROBOTAMICODING_COLOR_WHITE, '하양'],\n                        [Lang.Blocks.ROBOTAMICODING_COLOR_ALL, '모두'],\n                    ],\n                    value: '빨강',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,                   \n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'robotami_coding_set_rgb_color',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                BRIGHTNESS: 1,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func(sprite, script) {               \n                const colorType = script.getField('COLOR', script);\n                const color = Entry.RobotamiCoding.color[colorType];\n                let brightness = script.getNumberValue('BRIGHTNESS', script);\n                brightness = Math.round(2.55*brightness);\n                brightness = Math.max(Math.min(brightness, 255), 0);\n                let r = brightness;\n                let g = brightness;\n                let b = brightness;\n\n                if (colorType == '빨강') {\n                    r = 1*brightness; g = 0*brightness; b = 0*brightness;\n                } else if (colorType == '주황') {\n                    r = 1*brightness; g = 0.6*brightness; b = 0*brightness;\n                } else if (colorType == '노랑') {\n                    r = 1*brightness; g = 1*brightness; b = 0*brightness;\n                }  else if (colorType == '초록') {\n                    r = 0*brightness; g = 1*brightness; b = 0*brightness;\n                } else if (colorType == '파랑') {\n                    r = 0*brightness; g = 0*brightness; b = 1*brightness;\n                }  else if (colorType == '남색') {\n                    r = 0.2*brightness; g = 0.2*brightness; b = 1*brightness;\n                } else if (colorType == '보라') {\n                    r = 1*brightness; g = 0*brightness; b = 1*brightness;\n                } else if (colorType == '분홍') {\n                    r = 1*brightness; g = 0.6*brightness; b = 1*brightness;\n                }  else if (colorType == '하늘색') {\n                    r = 0.2*brightness; g = 1*brightness; b = 1*brightness;\n                } else if (colorType == '하양') {\n                    r = 1*brightness; g = 1*brightness; b = 1*brightness;\n                } else if (colorType == '모두') {\n                    r = 1*brightness; g = 1*brightness; b = 1*brightness;\n                }                  \n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[8] = {\n                    type: Entry.RobotamiCoding.sensorTypes.DIGITAL,\n                    data: 0,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[11] = {\n                    type: Entry.RobotamiCoding.sensorTypes.PWM,\n                    data: r,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[10] = {\n                    type: Entry.RobotamiCoding.sensorTypes.PWM,\n                    data: g,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[9] = {\n                    type: Entry.RobotamiCoding.sensorTypes.PWM,\n                    data: b,\n                    time: new Date().getTime(),\n                };                                                          \n                return script.callReturn();                             \n            },\n        },\n        // 로보타미 코딩 계명 리스트\n        robotami_coding_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: undefined,\n        },\n\n        robotami_coding_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_tone_list',\n                    },\n                ],\n                type: 'robotami_coding_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: undefined,\n        },\n\n        // 로보타미 코딩 옥타브 리스트\n        robotami_coding_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: undefined,\n        },\n\n        robotami_coding_set_tone_octav_time: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_tone_list',\n                    },\n                    {\n                        type: 'robotami_coding_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_set_tone_octav_time',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = 13;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);                    \n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    var duration = script.getNumberValue('DURATION', script);\n                    var value = 0;\n                    if (!Entry.Utils.isNumber(note)) note = Entry.RobotamiCoding.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }                \n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.RobotamiCoding.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    if (note != 0) {\n                        value = Entry.RobotamiCoding.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.RobotamiCoding.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.RobotamiCoding.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: undefined,\n        },\n        robotami_coding_set_tone_octav_beat: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_WN, 1000],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_HN, 500],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_QN, 250],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_EN, 125],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_SN, 63],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_TN, 31],\n                    ],\n                    value: 250,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_tone_list',\n                    },\n                    {\n                        type: 'robotami_coding_octave_list',\n                    },\n                    null, null,\n                ],\n                type: 'robotami_coding_set_tone_octav_beat',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],            \n            func(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = 13;\n\n                if (!script.isStart) {\n                    var note = script.getValue('NOTE', script);\n                    var octave = script.getNumberValue('OCTAVE', script) - 1;\n                    var duration = script.getNumberValue('DURATION', script);\n                    var value = 0;\n\n                    if (!Entry.Utils.isNumber(note)) note = Entry.RobotamiCoding.toneTable[note];\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }                   \n\n                    if (note != 0) {\n                        value = Entry.RobotamiCoding.toneMap[note][octave];\n                    }                    \n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq['SET']) {\n                        sq['SET'] = {};\n                    }\n\n                    if (duration === 0) {\n                        sq['SET'][port] = {\n                            type: Entry.RobotamiCoding.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }          \n                    //duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq['SET'][port] = {\n                        type: Entry.RobotamiCoding.sensorTypes.TONE,\n                        data: {\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq['SET'][port] = {\n                        type: Entry.RobotamiCoding.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: undefined,\n        },\n        robotami_coding_set_tone_freq: {            \n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],            \n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['3000'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_set_tone_freq',\n            },\n            paramsKeyMap: {\n                FREQ: 0,\n                DURATION: 1,\n            },           \n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = 13;\n\n                var freq = script.getValue('FREQ');\n                var duration = parseInt(parseFloat(script.getValue('DURATION')) * 1000);\n\n                if (duration < 0) {\n                    duration = 0;\n                }\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                if (duration === 0) {\n                    sq.SET[port] = {\n                        type: Entry.RobotamiCoding.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n                }\n                let value = freq;\n\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                sq.SET[port] = {\n                    type: Entry.RobotamiCoding.sensorTypes.TONE,\n                    data: {\n                        value,\n                        duration,\n                    },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: undefined,\n        },\n        robotami_coding_set_tone_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_WN, 1000],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_HN, 500],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_QN, 250],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_EN, 125],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_SN, 63],\n                        [Lang.Blocks.ROBOTAMICODING_BUZZER_TN, 31],\n                    ],\n                    value: 250,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotami_coding_set_tone_off',\n            },\n            paramsKeyMap: {         \n                DURATION: 0,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func(sprite, script) {\n                if (!script.isStart) {\n                    const duration = script.getField('DURATION', script);\n\n                    if (!Entry.hw.sendQueue.SET) {\n                        Entry.hw.sendQueue = {\n                            GET: {},\n                            SET: {},\n                        };\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue.SET[13] = {\n                        type: Entry.RobotamiCoding.sensorTypes.TONE,\n                        data: {\n                            value: 0,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue.SET[13] = {\n                        type: Entry.RobotamiCoding.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n        },\n        robotami_coding_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_pwm_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq['SET']) {\n                    sq['SET'] = {};\n                }\n                sq['SET'][port] = {\n                    type: Entry.ArduinoExt.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: undefined,\n        },\n\n        // 로보타미 코딩 DC 모터 리스트\n        robotami_coding_dcm_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: undefined,\n        },\n\n        // 로보타미 코딩 DC 모터 방향 리스트\n        robotami_coding_dcm_dir_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOTAMICODING_DCM_CLOCKWISE, '0'],\n                        [Lang.Blocks.ROBOTAMICODING_DCM_COUNTERCLOCKWISE, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                MOTOR_DIR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('MOTOR_DIR');\n            },\n            syntax: undefined,\n        },\n\n        robotami_coding_set_dcm_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_dcm_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'robotami_coding_dcm_dir_list',\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_set_dcm_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n                MOTOR_DIR: 2,\n            },\n\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var value = script.getNumberValue('VALUE', script);\n                var motor_dir = script.getNumberValue('MOTOR_DIR', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RobotamiCoding.sensorTypes.DC_MOTOR,\n                    data: {\n                        value: value,\n                        motor_dir: motor_dir,\n                    },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: undefined,\n        },\n        robotami_coding_set_dcm_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'robotami_coding_dcm_list',\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_set_dcm_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var value = 0;\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RobotamiCoding.sensorTypes.DC_STOP,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: undefined,\n        },\n\n        // 로보타미 코딩 로봇 동작 리스트\n        robotami_coding_robot_move_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOTAMICODING_ROBOT_FORWARD,'0'],\n                        [Lang.Blocks.ROBOTAMICODING_ROBOT_BACKWARD,'1'],\n                        [Lang.Blocks.ROBOTAMICODING_ROBOT_LEFT,'2'],\n                        [Lang.Blocks.ROBOTAMICODING_ROBOT_RIGHT,'3'],\n                        [Lang.Blocks.ROBOTAMICODING_ROBOT_GOLEFT,'4'],\n                        [Lang.Blocks.ROBOTAMICODING_ROBOT_GORIGHT,'5'],\n                        [Lang.Blocks.ROBOTAMICODING_ROBOT_TURNLEFT,'6'],\n                        [Lang.Blocks.ROBOTAMICODING_ROBOT_TURNRIGHT,'7'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                ROBOT_MOVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('ROBOT_MOVE');\n            },\n            syntax: undefined,\n        },\n\n        robotami_coding_set_robot_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'robotami_coding_robot_move_list',\n                    },\n                    null,\n                ],\n                type: 'robotami_coding_set_robot_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                ROBOT_MOVE: 1,\n            },\n\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var port = 0;\n                var value = script.getNumberValue('VALUE', script);\n                var robot_move = script.getNumberValue('ROBOT_MOVE', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RobotamiCoding.sensorTypes.ROBOT,\n                    data: {\n                        value: value,\n                        robot_move: robot_move,\n                    },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: undefined,\n        },\n        robotami_coding_set_robot_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotami_coding_set_robot_stop',\n            },\n            paramsKeyMap: {\n\n            },\n\n            class: 'RobotamiCoding',\n            isNotFor: ['RobotamiCoding'],\n            func: function(sprite, script) {\n                var port = 0;\n                var value = 0;\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.RobotamiCoding.sensorTypes.ROBOT_STOP,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: undefined,\n        },\n    };\n};\n\nmodule.exports = Entry.RobotamiCoding;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotis.js",
    "content": "'use strict';\r\n\r\nEntry.Robotis_carCont = {\r\n    INSTRUCTION: {\r\n        NONE: 0,\r\n        WRITE: 3,\r\n        READ: 2,\r\n    },\r\n    CONTROL_TABLE: {\r\n        // [default address, default length, address (when reads together), length (when reads together)]\r\n        CM_LED: [67, 1],\r\n        CM_SPRING_RIGHT: [69, 1, 69, 2],\r\n        CM_SPRING_LEFT: [70, 1, 69, 2],\r\n        CM_SWITCH: [71, 1],\r\n        CM_SOUND_DETECTED: [86, 1],\r\n        CM_SOUND_DETECTING: [87, 1],\r\n        CM_IR_LEFT: [91, 2, 91, 4],\r\n        CM_IR_RIGHT: [93, 2, 91, 4],\r\n        CM_CALIBRATION_LEFT: [95, 2],\r\n        CM_CALIBRATION_RIGHT: [97, 2],\r\n\r\n        AUX_MOTOR_SPEED_LEFT: [152, 2], // car_cont\r\n        AUX_MOTOR_SPEED_RIGHT: [154, 2],\r\n    },\r\n    setZero: function() {\r\n        // instruction / address / length / value / default length\r\n        Entry.hw.sendQueue['setZero'] = [1];\r\n        this.update();\r\n        this.setRobotisData(null);\r\n        Entry.hw.sendQueue['setZero'] = null;\r\n        this.update();\r\n        this.setRobotisData([\r\n            [Entry.Robotis_carCont.INSTRUCTION.WRITE, 152, 2, 0],\r\n            [Entry.Robotis_carCont.INSTRUCTION.WRITE, 154, 2, 0],\r\n        ]);\r\n\r\n        this.update();\r\n    },\r\n    id: '7.1',\r\n    name: 'robotis_carCont',\r\n    url: 'http://www.robotis.com/index/product.php?cate_code=111310',\r\n    imageName: 'robotis_carCont.png',\r\n    title: {\r\n        ko: '로보티즈 로봇자동차',\r\n        en: 'Robotis Robot car',\r\n    },\r\n    delay: 40,\r\n    postCallReturn: function(script, data, ms) {\r\n        if (ms <= 0) {\r\n            this.setRobotisData(data);\r\n            this.update();\r\n            return script.callReturn();\r\n        }\r\n        // clear portData only if not RB-100\r\n        if (Entry.hw.hwModule.id != \"7.A,7.B\" &&\r\n            Entry.hw.hwModule.id != \"7.C\"  &&\r\n            Entry.hw.hwModule.id != \"7.5,7.6\"  &&\r\n            Entry.hw.hwModule.id != \"7.7,7.8\" &&\r\n            Entry.hw.hwModule.id != \"7.9\") {\r\n            Entry.hw.portData = {};\r\n        }\r\n        setTimeout(function() {\r\n            Entry.hw.sendQueue = {}\r\n           // Entry.hw.portData = {};\r\n        }, ms - 100);\r\n\r\n        setTimeout(function() {\r\n            Entry.hw.sendQueue = {}\r\n            //Entry.hw.portData = {};\r\n        }, ms);\r\n\r\n        setTimeout(function() {\r\n            Entry.hw.sendQueue = {}\r\n            //Entry.hw.portData = {};\r\n        }, ms + 100);\r\n\r\n        setTimeout(function() {\r\n            Entry.hw.sendQueue = {}\r\n           // Entry.hw.portData = {};\r\n        }, ms + 200);\r\n\r\n        if (!script.isStart) {\r\n            script.isStart = true;\r\n            script.timeFlag = 1;\r\n            //data setting\r\n            this.setRobotisData(data);\r\n            this.update();\r\n\r\n            //delay xx ms\r\n            setTimeout(function() {\r\n                script.timeFlag = 0;\r\n                \r\n            }, ms);\r\n\r\n            return script;\r\n        } else if (script.timeFlag == 1) {\r\n            this.setRobotisData(null);\r\n            this.update();\r\n            return script;\r\n        } else {\r\n            delete script.timeFlag;\r\n            delete script.isStart;\r\n            Entry.engine.isContinue = false;\r\n            this.update();\r\n            return script.callReturn();\r\n        }\r\n    },\r\n    wait: function(sq, ms) {\r\n        Entry.hw.socket.send(JSON.stringify(sq));\r\n\r\n        var start = new Date().getTime();\r\n        var end = start;\r\n        while (end < start + ms) {\r\n            //wait XX ms\r\n            end = new Date().getTime();\r\n        }\r\n    },\r\n    update: function() {\r\n        Entry.hw.update();\r\n        var ROBOTIS_DATA = Entry.hw.sendQueue['ROBOTIS_DATA'];\r\n        if (ROBOTIS_DATA) {\r\n            ROBOTIS_DATA.forEach(function(data) {\r\n                data['send'] = true;\r\n            });\r\n        }\r\n        this.setRobotisData(null);\r\n    },\r\n    filterSendData: function() {\r\n        var ROBOTIS_DATA = Entry.hw.sendQueue['ROBOTIS_DATA'];\r\n        if (ROBOTIS_DATA) {\r\n            return ROBOTIS_DATA.filter(function(data) {\r\n                return data.send !== true;\r\n            });\r\n        } else {\r\n            return null;\r\n        }\r\n    },\r\n    setRobotisData: function(data) {\r\n        var filterData = this.filterSendData();\r\n        if (data == null) {\r\n            Entry.hw.sendQueue['ROBOTIS_DATA'] = filterData;\r\n        } else {\r\n            Entry.hw.sendQueue['ROBOTIS_DATA'] = filterData ? filterData.concat(data) : data;\r\n        }\r\n    },\r\n};\r\n\r\nEntry.Robotis_openCM70 = {\r\n    hasPracticalCourse: true,\r\n    INSTRUCTION: {\r\n        NONE: 0,\r\n        WRITE: 3,\r\n        READ: 2,\r\n    },\r\n    CONTROL_TABLE: {\r\n        // [default address, default length, address (when reads together), length (when reads together)]\r\n        CM_LED_R: [79, 1],\r\n        CM_LED_G: [80, 1],\r\n        CM_LED_B: [81, 1],\r\n        CM_BUZZER_INDEX: [84, 1],\r\n        CM_BUZZER_TIME: [85, 1],\r\n        CM_SOUND_DETECTED: [86, 1],\r\n        CM_SOUND_DETECTING: [87, 1],\r\n        CM_USER_BUTTON: [26, 1],\r\n        CM_MOTION: [66, 1],\r\n        CM_AUTODRIVE: [40, 1],\r\n        CM_AUTODRIVE_LEFT_MOTOR_PORT: [42, 1],\r\n        CM_AUTODRIVE_RIGHT_MOTOR_PORT: [43, 1],\r\n        CM_AUTODRIVE_LEFT_IR_PORT: [44, 1],\r\n        CM_AUTODRIVE_RIGHT_IR_PORT: [45, 1],\r\n        CM_POWEROFF_TIMER: [76, 1],\r\n\r\n        AUX_SERVO_POSITION: [152, 2],\r\n        AUX_IR: [168, 2],\r\n        AUX_TOUCH: [202, 1],\r\n        AUX_TEMPERATURE: [234, 1],\r\n        AUX_ULTRASONIC: [242, 1],\r\n        AUX_MAGNETIC: [250, 1],\r\n        AUX_MOTION_DETECTION: [258, 1],\r\n        AUX_COLOR: [266, 1],\r\n        AUX_CUSTOM: [216, 2],\r\n        AUX_BRIGHTNESS: [288, 2],\r\n        AUX_HYDRO_THEMO_HUMIDITY: [274, 1],\r\n        AUX_HYDRO_THEMO_TEMPER: [282, 1],\r\n\r\n        AUX_SERVO_MODE: [126, 1],\r\n        AUX_SERVO_SPEED: [136, 2],\r\n        AUX_MOTOR_SPEED: [136, 2],\r\n        AUX_LED_MODULE: [210, 1],\r\n    },\r\n    IRS_MODULEWRITE: {\r\n        PORT3: false,\r\n        PORT4: false,\r\n        PORT5: false,\r\n        PORT6: false,\r\n    },\r\n    SERVO_MODULEWRITE: {\r\n        PORT3: false,\r\n        PORT4: false,\r\n        PORT5: false,\r\n        PORT6: false,\r\n    },\r\n    setZero: function() {\r\n        // instruction / address / length / value / default length\r\n        Entry.hw.sendQueue['setZero'] = [1];\r\n        Entry.Robotis_carCont.update();\r\n        Entry.Robotis_carCont.setRobotisData(null);\r\n        Entry.hw.sendQueue['setZero'] = null;\r\n        Entry.Robotis_carCont.update();\r\n        Entry.Robotis_carCont.setRobotisData([\r\n            /*[Entry.Robotis_openCM70.INSTRUCTION.WRITE, 136, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 138, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 140, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 142, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 144, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 146, 2, 0],*/\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 136, 12, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 79, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 81, 1, 0],\r\n            /*[Entry.Robotis_openCM70.INSTRUCTION.WRITE, 79, 1, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 80, 1, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 81, 1, 0],*/\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 86, 1, 0], // 최종 소리 // add by kjs start 170605\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 108, 4, 0],\r\n            /*[Entry.Robotis_openCM70.INSTRUCTION.WRITE, 108, 1, 0], // port 3\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 109, 1, 0], // port 4\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 110, 1, 0], // port 5\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 111, 1, 0] // port 6 // add by kjs end 170605*/\r\n        ]);\r\n\r\n        Entry.Robotis_carCont.update();\r\n\r\n        Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 = false;\r\n        Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 = false;\r\n        Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 = false;\r\n        Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 = false;\r\n\r\n        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT3 = false;\r\n        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT4 = false;\r\n        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT5 = false;\r\n        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT6 = false;\r\n        /*\r\n        Entry.hw.sendQueue['temp'] = [0];\r\n        Entry.Robotis_carCont.update();\r\n        Entry.hw.sendQueue['temp'] = null;*/\r\n        //Entry.Robotis_carCont.update();\r\n    },\r\n    id: '7.2',\r\n    name: 'robotis_openCM70',\r\n    url: 'http://www.robotis.com/index/product.php?cate_code=111310',\r\n    imageName: 'robotis_openCM70.png',\r\n    title: {\r\n        ko: '로보티즈 IoT',\r\n        en: 'Robotis Open CM70',\r\n    },\r\n    delay: 50, // 20240401 15ms -> 50ms 동글 또는 제어기에서 buffer overflow 발생 \r\n    readDelay: 30\r\n};\r\n\r\nEntry.Robotis_openCM70EDU = {\r\n    hasPracticalCourse: true,\r\n    INSTRUCTION: {\r\n        NONE: 0,\r\n        WRITE: 3,\r\n        READ: 2,\r\n    },\r\n    CONTROL_TABLE: {\r\n        // [default address, default length, address (when reads together), length (when reads together)]\r\n        CM_LED_R: [79, 1],\r\n        CM_LED_G: [80, 1],\r\n        CM_LED_B: [81, 1],\r\n        CM_BUZZER_INDEX: [84, 1],\r\n        CM_BUZZER_TIME: [85, 1],\r\n        CM_SOUND_DETECTED: [86, 1],\r\n        CM_SOUND_DETECTING: [87, 1],\r\n        CM_USER_BUTTON: [26, 1],\r\n        CM_MOTION: [66, 1],\r\n        CM_AUTODRIVE: [40, 1],\r\n        CM_AUTODRIVE_LEFT_MOTOR_PORT: [42, 1],\r\n        CM_AUTODRIVE_RIGHT_MOTOR_PORT: [43, 1],\r\n        CM_AUTODRIVE_LEFT_IR_PORT: [44, 1],\r\n        CM_AUTODRIVE_RIGHT_IR_PORT: [45, 1],\r\n        CM_POWEROFF_TIMER: [76, 1],\r\n\r\n        AUX_SERVO_POSITION: [152, 2],\r\n        AUX_IR: [168, 2],\r\n        AUX_TOUCH: [202, 1],\r\n        AUX_TEMPERATURE: [234, 1],\r\n        AUX_ULTRASONIC: [242, 1],\r\n        AUX_MAGNETIC: [250, 1],\r\n        AUX_MOTION_DETECTION: [258, 1],\r\n        AUX_COLOR: [266, 1],\r\n        AUX_CUSTOM: [216, 2],\r\n        AUX_BRIGHTNESS: [288, 2],\r\n        AUX_HYDRO_THEMO_HUMIDITY: [274, 1],\r\n        AUX_HYDRO_THEMO_TEMPER: [282, 1],\r\n\r\n        AUX_SERVO_MODE: [126, 1],\r\n        AUX_SERVO_SPEED: [136, 2],\r\n        AUX_MOTOR_SPEED: [136, 2],\r\n        AUX_LED_MODULE: [210, 1],\r\n    },\r\n    IRS_MODULEWRITE: {\r\n        PORT3: false,\r\n        PORT4: false,\r\n        PORT5: false,\r\n        PORT6: false,\r\n    },\r\n    SERVO_MODULEWRITE: {\r\n        PORT3: false,\r\n        PORT4: false,\r\n        PORT5: false,\r\n        PORT6: false,\r\n    },\r\n    setZero: function() {\r\n        // instruction / address / length / value / default length\r\n        Entry.hw.sendQueue['setZero'] = [1];\r\n        Entry.Robotis_carCont.update();\r\n        Entry.Robotis_carCont.setRobotisData(null);\r\n        Entry.hw.sendQueue['setZero'] = null;\r\n        Entry.Robotis_carCont.update();\r\n        Entry.Robotis_carCont.setRobotisData([\r\n            /*[Entry.Robotis_openCM70.INSTRUCTION.WRITE, 136, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 138, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 140, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 142, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 144, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 146, 2, 0],*/\r\n            [Entry.Robotis_openCM70EDU.INSTRUCTION.WRITE, 136, 12, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 79, 2, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 81, 1, 0],\r\n            /*[Entry.Robotis_openCM70.INSTRUCTION.WRITE, 79, 1, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 80, 1, 0],\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 81, 1, 0],*/\r\n            [Entry.Robotis_openCM70EDU.INSTRUCTION.WRITE, 86, 1, 0], // 최종 소리 // add by kjs start 170605\r\n            [Entry.Robotis_openCM70EDU.INSTRUCTION.WRITE, 108, 4, 0],\r\n            /*[Entry.Robotis_openCM70.INSTRUCTION.WRITE, 108, 1, 0], // port 3\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 109, 1, 0], // port 4\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 110, 1, 0], // port 5\r\n            [Entry.Robotis_openCM70.INSTRUCTION.WRITE, 111, 1, 0] // port 6 // add by kjs end 170605*/\r\n        ]);\r\n\r\n        Entry.Robotis_carCont.update();\r\n\r\n        Entry.Robotis_openCM70EDU.IRS_MODULEWRITE.PORT3 = false;\r\n        Entry.Robotis_openCM70EDU.IRS_MODULEWRITE.PORT4 = false;\r\n        Entry.Robotis_openCM70EDU.IRS_MODULEWRITE.PORT5 = false;\r\n        Entry.Robotis_openCM70EDU.IRS_MODULEWRITE.PORT6 = false;\r\n\r\n        Entry.Robotis_openCM70EDU.SERVO_MODULEWRITE.PORT3 = false;\r\n        Entry.Robotis_openCM70EDU.SERVO_MODULEWRITE.PORT4 = false;\r\n        Entry.Robotis_openCM70EDU.SERVO_MODULEWRITE.PORT5 = false;\r\n        Entry.Robotis_openCM70EDU.SERVO_MODULEWRITE.PORT6 = false;\r\n\r\n        Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 = false;\r\n        Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 = false;\r\n        Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 = false;\r\n        Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 = false;\r\n\r\n        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT3 = false;\r\n        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT4 = false;\r\n        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT5 = false;\r\n        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT6 = false;\r\n        /*\r\n        Entry.hw.sendQueue['temp'] = [0];\r\n        Entry.Robotis_carCont.update();\r\n        Entry.hw.sendQueue['temp'] = null;*/\r\n        //Entry.Robotis_carCont.update();\r\n    },\r\n    monitorTemplate: {\r\n        imgPath: 'hw/robotis_opencm70.png',\r\n        width: 800,\r\n        height: 800,\r\n        listPorts: {\r\n            DETECTEDSOUNDE: { name: '최종소리', type: 'input', pos: { x: 0, y: 0 } },\r\n            DETECTINGSOUNDE1: { name: '실시간소리', type: 'input', pos: { x: 0, y: 0 } },\r\n            //SND: { name: Lang.Hw.buzzer, type: 'output', pos: { x: 0, y: 0 } },\r\n            //FND: { name: '전원', type: 'output', pos: { x: 0, y: 0 } },\r\n        },\r\n        ports: {\r\n            USERBUTTONSTATE: { name: 'USERBUTTON', type: 'input', pos: { x: 565, y: 335 } },\r\n            //'LEDR': { name: 'R', type: 'input', pos: { x: 140, y: 300 } },\r\n            //'LEDG': { name: 'G', type: 'input', pos: { x: 170, y: 300 } },\r\n            //'LEDB': { name: 'B', type: 'input', pos: { x: 200, y: 300 } },\r\n            //'GM1': { name: 'GEARD1', type: 'input', pos: { x: 450, y: 300 } },\r\n            //'GM2': { name: 'GEARD2', type: 'input', pos: { x: 450, y: 480 } },\r\n            MONITORPORT0: { name: 'PORT3', type: 'input', pos: { x: 320, y: 320 } },\r\n            MONITORPORT1: { name: 'PORT4', type: 'input', pos: { x: 330, y: 330 } },\r\n            MONITORPORT2: { name: 'PORT5', type: 'input', pos: { x: 320, y: 440 } },\r\n            MONITORPORT3: { name: 'PORT6', type: 'input', pos: { x: 330, y: 460 } },\r\n        },\r\n        mode: 'both',\r\n    },\r\n    id: '7.3',\r\n    name: 'robotis_openCM70EDU',\r\n    url: 'http://www.robotis.com/index/product.php?cate_code=111310',\r\n    imageName: 'robotis_openCM70EDU.png',\r\n    title: {\r\n        ko: '로보티즈 실과',\r\n        en: 'ROBOTIS InfoRobot',\r\n    },\r\n    delay: 15,\r\n};\r\n\r\nEntry.Robotis_carCont.blockMenuBlocks = [\r\n    'robotis_carCont_sensor_value',\r\n    'robotis_carCont_cm_led',\r\n    'robotis_carCont_cm_sound_detected_clear',\r\n    'robotis_carCont_aux_motor_speed',\r\n    'robotis_carCont_aux_motor_speed2',\r\n    'robotis_carCont_cm_calibration',\r\n];\r\n\r\nEntry.Robotis_carCont.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                robotis_carCont_sensor_value: '%1   값',\r\n                robotis_carCont_cm_led: '4번 LED %1 ,  1번 LED %2 %3',\r\n                robotis_carCont_cm_sound_detected_clear: '최종소리감지횟수 초기화 %1',\r\n                robotis_carCont_aux_motor_speed:\r\n                    '%1 감속모터 속도를 %2 , 출력값을 %3 (으)로 정하기 %4',\r\n                robotis_carCont_cm_calibration:\r\n                    '%1 적외선 센서 캘리브레이션 값을 %2 (으)로 정하기 %3',\r\n                robotis_openCM70_cm_custom_value: '직접입력 주소 ( %1 ) %2 값',\r\n                robotis_openCM70_sensor_value: '제어기 %1 값',\r\n                robotis_openCM70_aux_sensor_value: '%1   %2 값',\r\n                robotis_openCM70_cm_buzzer_index: '제어기 음계값 %1 을(를) %2 초 동안 연주 %3',\r\n                robotis_openCM70_cm_buzzer_melody: '제어기 멜로디 %1 번 연주 %2',\r\n                robotis_openCM70_cm_sound_detected_clear: '최종소리감지횟수 초기화 %1',\r\n                robotis_openCM70_cm_led: '제어기 %1 LED %2 %3',\r\n                //robotis_openCM70_cm_motion: '모션 %1 번 실행 %2',\r\n                robotis_openCM70_cm_autodrive_motor: '🚗 자율주행 자동차 %1 모터를 %2 에 연결 %3',\r\n                robotis_openCM70_cm_autodrive_ir: '🚗 자율주행 자동차 %1 적외선센서를 %2 에 연결 %3',\r\n                robotis_openCM70_cm_autodrive_speed: '🚗 차로를 따라 %1의 속도로 자율주행 %2',\r\n                robotis_openCM70_aux_car_move: '로봇을 %1% 의 속도로 %2 %3',\r\n                robotis_openCM70_aux_motor_speed:\r\n                    '%1 감속모터 속도를 %2 , 출력값을 %3%로 정하기 %4',\r\n                robotis_openCM70_aux_servo_mode: '%1 서보모터 모드를 %2 (으)로 정하기 %3',\r\n                robotis_openCM70_aux_servo_speed:\r\n                    '%1 서보모터 속도를 %2 , 출력값을 %3%로 정하기 %4',\r\n                robotis_openCM70_aux_servo_position: '%1 서보모터 위치를 %2도로 정하기 %3',\r\n                robotis_openCM70_aux_led_module: '%1 LED 모듈을 %2 (으)로 정하기 %3',\r\n                robotis_openCM70_cm_poweroff_timer: '제어기 자동꺼짐 타이머 %1 %2',\r\n                robotis_openCM70_aux_custom: '%1 사용자 장치를 %2 (으)로 정하기 %3',\r\n                robotis_openCM70_cm_custom: '직접입력 주소 ( %1 ) (을)를 %2 (으)로 정하기 %3',\r\n            },\r\n            Helper: {\r\n                robotis_carCont_sensor_value:\r\n                    '왼쪽 접속 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>오른쪽 접촉 센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>선택 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.<br/>최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>왼쪽 적외선 센서 : 물체와 가까울 수록 큰 값 입니다.<br/>오른쪽 적외선 센서 : 물체와 가까울 수록 큰 값 값 입니다.<br/>왼쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>오른쪽 적외선 센서 캘리브레이션 값 : 적외선 센서의 캘리브레이션 값 입니다.<br/>(*캘리브레이션 값 - 적외선센서 조정 값)',\r\n                robotis_carCont_cm_led:\r\n                    '4개의 LED 중 1번 또는 4번 LED 를 켜거나 끕니다.<br/>LED 2번과 3번은 동작 지원하지 않습니다.',\r\n                robotis_carCont_cm_sound_detected_clear:\r\n                    '최종 소리 감지횟 수를 0 으로 초기화 합니다.',\r\n                robotis_carCont_aux_motor_speed: '감속모터 속도를 0 ~ 1023 의 값(으)로 정합니다.',\r\n                robotis_carCont_cm_calibration:\r\n                    '적외선센서 조정 값(http://support.robotis.com/ko/: 자동차로봇> 2. B. 적외선 값 조정)을 직접 정합니다.',\r\n                robotis_openCM70_sensor_value:\r\n                    '최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.최종 소리 감지 횟수 : 마지막 실시간 소리 감지 횟수 값 입니다.<br/>실시간 소리 감지 횟수 : 약 1초 안에 다음 소리가 감지되면 1씩 증가합니다.<br/>사용자 버튼 상태 : 접촉(1), 비접촉(0) 값 입니다.',\r\n                robotis_openCM70_aux_sensor_value:\r\n                    '서보모터 위치 : 0 ~ 1023, 중간 위치의 값은 512 입니다.<br/>적외선센서 :  물체와 가까울 수록 큰 값 입니다.<br/>접촉센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>조도센서(CDS) : 0 ~ 1023, 밝을 수록 큰 값 입니다.<br/>온습도센서(습도) : 0 ~ 100, 습할 수록 큰 값 입니다.<br/>온습도센서(온도) : -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>온도센서 :  -20 ~ 100, 온도가 높을 수록 큰 값 입니다.<br/>초음파센서 : -<br/>자석센서 : 접촉(1), 비접촉(0) 값 입니다.<br/>동작감지센서 : 동작 감지(1), 동작 미감지(0) 값 입니다.<br/>컬러센서 : 알수없음(0), 흰색(1), 검은색(2), 빨간색(3), 녹색(4), 파란색(5), 노란색(6) 값 입니다.<br/>사용자 장치 : 사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\r\n                robotis_openCM70_cm_buzzer_index: '음계를 0.1 ~ 5 초 동안 연주 합니다.',\r\n                robotis_openCM70_cm_buzzer_melody:\r\n                    \"멜로디를 연주 합니다.<br/>멜로디를 연속으로 재생하는 경우, 다음 소리가 재생되지 않으면 '흐름 > X 초 기다리기' 블록을 사용하여 기다린 후 실행합니다.\",\r\n                robotis_openCM70_cm_sound_detected_clear:\r\n                    '최종 소리 감지횟 수를 0 으로 초기화 합니다.',\r\n                robotis_openCM70_cm_led: '제어기의 빨간색, 녹색, 파란색 LED 를 켜거나 끕니다.',\r\n                //robotis_openCM70_cm_motion: '제어기에 다운로드 되어있는 모션을 실행합니다.',\r\n                robotis_openCM70_cm_autodrive_motor: '자율주행 자동차의 모터 포트를 지정합니다.',\r\n                robotis_openCM70_cm_autodrive_ir: '자율주행 자동차의 적외선 센서 포트를 지정합니다.',\r\n                robotis_openCM70_cm_autodrive_speed: '지정한 속도로 자율주행을 수행합니다.',\r\n                robotis_openCM70_aux_car_move: '로봇을 지정한 속도와 방향으로 움직이도록 합니다.',\r\n                robotis_openCM70_aux_motor_speed: '감속모터 속도를 0 ~ 100% 의 값으로 정합니다.',\r\n                robotis_openCM70_aux_servo_mode:\r\n                    '서보모터를 회전모드 또는 관절모드로 정합니다.<br/>한번 설정된 모드는 계속 적용됩니다.<br/>회전모드는 서보모터 속도를 지정하여 서보모터를 회전 시킵니다.<br/>관절모드는 지정한 서보모터 속도로 서보모터 위치를 이동 시킵니다.',\r\n                robotis_openCM70_aux_servo_speed: '서보모터 속도를 0 ~ 100% 의 값으로 정합니다.',\r\n                robotis_openCM70_aux_servo_position:\r\n                    '서보모터 위치를 -150 ~ 150도 의 값(으)로 정합니다.<br/>서보모터 속도와 같이 사용해야 합니다.',\r\n                robotis_openCM70_aux_led_module: 'LED 모듈의 LED 를 켜거나 끕니다.',\r\n                robotis_openCM70_aux_custom:\r\n                    '사용자 센서 제작에 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\r\n                robotis_openCM70_cm_poweroff_timer: \r\n                    '제어기의 자동꺼짐 타이머를 설정합니다.<br/>설정된 만큼의 시간동안 통신이 진행되지 않으면 제어기는 자동으로 꺼집니다.',\r\n                robotis_openCM70_cm_custom_value:\r\n                    '컨트롤 테이블 주소를 직접 입력하여 값을 확인 합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\r\n                robotis_openCM70_cm_custom:\r\n                    '컨트롤 테이블 주소를 직접 입력하여 값을 정합니다.<br/>컨트롤 테이블 대한 설명은 ROBOTIS e-매뉴얼(http://support.robotis.com/ko/)을 참고하세요.',\r\n            },\r\n            Blocks: {\r\n                robotis_carCont_aux_motor_speed_1: '감속모터 속도를',\r\n                robotis_carCont_aux_motor_speed_2: ', 출력값을',\r\n                robotis_carCont_calibration_1: '적외선 센서 캘리브레이션 값을',\r\n                robotis_common_case_01: '(을)를',\r\n                robotis_common_set: '(으)로 정하기',\r\n                robotis_common_value: '값',\r\n                robotis_common_clockwhise: '시계방향',\r\n                robotis_common_counter_clockwhise: '반시계방향',\r\n                robotis_common_wheel_mode: '회전모드',\r\n                robotis_common_joint_mode: '관절모드',\r\n                robotis_common_red_color: '빨간색',\r\n                robotis_common_green_color: '녹색',\r\n                robotis_common_blue_color: '파란색',\r\n                robotis_common_on: '켜기',\r\n                robotis_common_off: '끄기',\r\n                robotis_common_cm: '제어기',\r\n                robotis_common_port_1: '포트 1',\r\n                robotis_common_port_2: '포트 2',\r\n                robotis_common_port_3: '포트 3',\r\n                robotis_common_port_4: '포트 4',\r\n                robotis_common_port_5: '포트 5',\r\n                robotis_common_port_6: '포트 6',\r\n                robotis_common_play_buzzer: '연주',\r\n                robotis_common_play_motion: '실행',\r\n                robotis_common_motion: '모션',\r\n                robotis_common_index_number: '번',\r\n                robotis_common_left: '왼쪽',\r\n                robotis_common_right: '오른쪽',\r\n                robotis_common_minute: '분',\r\n                robotis_common_forward: '직진',\r\n                robotis_common_backward: '후진',\r\n                robotis_common_turn_left: '좌회전',\r\n                robotis_common_turn_right: '우회전',\r\n                robotis_common_stop: '정지',\r\n                robotis_cm_custom: '직접입력 주소',\r\n                robotis_cm_spring_left: '왼쪽 접촉 센서',\r\n                robotis_cm_spring_right: '오른쪽 접촉 센서',\r\n                robotis_cm_led_left: '왼쪽 LED',\r\n                robotis_cm_led_right: '오른쪽 LED',\r\n                robotis_cm_led_both: '양 쪽 LED',\r\n                robotis_cm_switch: '선택 버튼 상태',\r\n                robotis_cm_user_button: '사용자 버튼 상태',\r\n                robotis_cm_sound_detected: '최종 소리 감지 횟수',\r\n                robotis_cm_sound_detecting: '실시간 소리 감지 횟수',\r\n                robotis_cm_ir_left: '왼쪽 적외선 센서',\r\n                robotis_cm_ir_right: '오른쪽 적외선 센서',\r\n                robotis_cm_calibration_left: '왼쪽 적외선 센서 캘리브레이션 값',\r\n                robotis_cm_calibration_right: '오른쪽 적외선 센서 캘리브레이션 값',\r\n                robotis_cm_clear_sound_detected: '최종소리감지횟수 초기화',\r\n                robotis_cm_buzzer_index: '음계값',\r\n                robotis_cm_buzzer_melody: '멜로디',\r\n                robotis_cm_led_1: '1번 LED',\r\n                robotis_cm_led_4: '4번 LED',\r\n                robotis_aux_servo_position: '서보모터 위치',\r\n                robotis_aux_ir: '적외선센서',\r\n                robotis_aux_touch: '접촉센서',\r\n                robotis_aux_brightness: '조도센서(CDS)',\r\n                robotis_aux_hydro_themo_humidity: '온습도센서(습도)',\r\n                robotis_aux_hydro_themo_temper: '온습도센서(온도)',\r\n                robotis_aux_temperature: '온도센서',\r\n                robotis_aux_ultrasonic: '초음파센서',\r\n                robotis_aux_magnetic: '자석센서',\r\n                robotis_aux_motion_detection: '동작감지센서',\r\n                robotis_aux_color: '컬러센서',\r\n                robotis_aux_custom: '사용자 장치',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                robotis_carCont_sensor_value: 'Value   %1',\r\n                robotis_carCont_cm_led: '%1 LED 4,  %2 LED %3',\r\n                robotis_carCont_cm_sound_detected_clear:\r\n                    'Initialize the final number of sound detection  %1',\r\n                robotis_carCont_aux_motor_speed:\r\n                    'Set the speed of decelerating motor of %1 to %2, and the output value to %3  %4',\r\n                robotis_carCont_cm_calibration:\r\n                    'Set %1 value of infrared sensor calibration to %2  %3',\r\n                robotis_openCM70_cm_custom_value: 'Custom address ( %1 ) value %2',\r\n                robotis_openCM70_sensor_value: 'Controller value %1',\r\n                robotis_openCM70_aux_sensor_value: 'Value %1   %2',\r\n                robotis_openCM70_cm_buzzer_index:\r\n                    'Play %1 controller scale value for %2 seconds %3 ',\r\n                robotis_openCM70_cm_buzzer_melody: 'Play controller melody %1 times %2',\r\n                robotis_openCM70_cm_sound_detected_clear:\r\n                    'Initialize the final number of sound detection  %1',\r\n                robotis_openCM70_cm_led: 'Controller %1 LED %2 %3',\r\n                //robotis_openCM70_cm_motion: 'Play the motion %1 times',\r\n                robotis_openCM70_cm_autodrive_motor: 'Autonomous driving car %1 motor uses %2 %3',\r\n                robotis_openCM70_cm_autodrive_ir: 'Autonomous driving car %1 IR sensor uses %2 %3',\r\n                robotis_openCM70_cm_autodrive_speed: 'Perform autonomous driving at the speed of %1 %2',\r\n                robotis_openCM70_aux_car_move: 'Make the robot %2 at a speed of %1% %3',\r\n                robotis_openCM70_aux_motor_speed:\r\n                    'Set the speed of decelerating motor of %1 to %2 , and the output value to %3%  %4',\r\n                robotis_openCM70_aux_servo_mode: 'Set the mode of %1 servo motor to %2  %3',\r\n                robotis_openCM70_aux_servo_speed:\r\n                    'Set the speed of servo motor of %1 to %2 , and the output value to %3%  %4',\r\n                robotis_openCM70_aux_servo_position: 'Set the position of %1 servo motor to %2 degree %3',\r\n                robotis_openCM70_aux_led_module: 'Set the LED module of %1 as %2  %3',\r\n                robotis_openCM70_aux_custom: 'Set the user device of %1 as %2  %3',\r\n                robotis_openCM70_cm_poweroff_timer: 'Set auto-off timer as %1 %2',\r\n                robotis_openCM70_cm_custom: 'Set the custom address ( %1 ) as %2  %3',\r\n            },\r\n            Helper: {\r\n                robotis_openCM70_sensor_value:\r\n                    'Final number of sound detection : the value of the final detected sound times.<br/>Number of live sound detection : increases by 1 when it detects the next sound within 1 second.<br/>Status of user button: the value of contact (1), non-contact (0).Final number of sound detection : the value of the number of last live sound detection.<br/>Number of live sound detection : increases by 1 when it detects the next sound within 1 second.<br/>Status of user button : the value of contact (1), non-contact (0).',\r\n                robotis_openCM70_aux_sensor_value:\r\n                    \"Position of servo motor: 0-1023, the value of the middle is 512.<br/>Infrared sensor : the value is larger when it's close to an object.<br/>Contact sensor: the value of contact(1), non-contact(0).<br/>CDS: 0-1023, the value is larger when it's brighter.<br/>Temperature-humidity sensor (humidity) : 0-100, the value is larger when it's more humid.<br/>Temperature-humidity sensor (temperature) : -20 - 100, the value is larger when it's higher in temperature.<br/>Temperature sensor : -20 - 100, the value is larger when it's higher in temperature.<br/>Ultrasound sensor: -<br/>Magnetic sensor : the value of contact(1), non-contact(0).<br/>Motion detector: the value of detected motion(1), non-detected motion(0).<br/>Color sensor: the value of unknown(0), white(1), black(2), red(3), green(4), blue(5), yellow(6).<br/>User device: please refer to ROBOTIS e-manual (http://support.robotis.com/ko/) for the explanation on user sensor production.\",\r\n                robotis_openCM70_cm_buzzer_index: 'Plays the scale for 0.1 to 5 seconds.',\r\n                robotis_openCM70_cm_buzzer_melody:\r\n                    \"Plays melody.<br/>If the following sound doesn't play when repeatedly playing melodies, use the block 'flow > wait for X seconds' and execute it again.\",\r\n                robotis_openCM70_cm_sound_detected_clear: 'Final number of sound detection ',\r\n                robotis_openCM70_cm_led: 'Turns the red, green, blue LED of the device on or off.',\r\n                //robotis_openCM70_cm_motion: 'Executes the motion downloaded on the device.',\r\n                robotis_openCM70_cm_autodrive_motor: 'Specifies the motor port of the autonomous driving car.',\r\n                robotis_openCM70_cm_autodrive_ir: 'Specifies the IR sensor port of the autonomous driving car.',\r\n                robotis_openCM70_cm_autodrive_speed: 'Perform autonomous driving at the specified speed along the lane.',\r\n                robotis_openCM70_aux_car_move: 'Make the robot move at the specified speed and direction.',\r\n                robotis_openCM70_aux_motor_speed:\r\n                    'Sets the speed of decelerating motor to the value of 0 - 100%.',\r\n                robotis_openCM70_aux_servo_mode:\r\n                    \"Sets the servo motor as wheel mode or joint mode.<br/>The same mode continues to apply once it's set.<br/>Wheel mode designates the servo motor's speed, and spins the servo motor.<br/>Joint mode moves the servo motor's position with the set servo motor speed.\",\r\n                robotis_openCM70_aux_servo_speed:\r\n                    \"Sets servo motor's speed to the value of 0 - 1023.\",\r\n                robotis_openCM70_aux_servo_position:\r\n                    \"Sets servo motor's position to the value of -150 ~ 150 degree.<br/>Use as servo motor speed\",\r\n                robotis_openCM70_aux_led_module: 'Turns the LED of LED module on or off.',\r\n                robotis_openCM70_aux_custom:\r\n                    'Please refer to the ROBOTIS e-manual (http://support.robotis.com/ko/) for the explanation of user sensor production.',\r\n                robotis_openCM70_cm_poweroff_timer: \"Set the controllers auto-off timer.<br/>If there is no communication for the set amount of time, the controller will automatically turn off.\",\r\n                robotis_openCM70_cm_custom_value:\r\n                    'Checks the value by directly inputting the control table address.<br/>Please refer to the ROBOTIS e-manual (http://support.robotis.com/ko/) for the explanation about control table.',\r\n                robotis_openCM70_cm_custom:\r\n                    'Checks the value by directly inputting the control table address.<br/>Please refer to the ROBOTIS e-manual (http://support.robotis.com/ko/) for the explanation about control table.',\r\n                robotis_carCont_sensor_value:\r\n                    \"Left connected sensor : the value of contact (1), non-contact (0).<br/>Right contact sensor: the value of contact (1), non-contact (0).<br/>Final number of sound detection : the value of the number of last live sound detection.<br/>Number of live sound detection : increases by 1 when it detects the next sound within 1 second.<br/>Right infrared sensor: the value is larger when it's closer to an object.<br/>Value of left infrared sensor calibration : the calibration value of the infrared sensor.<br/>Value of right infrared sensor calibration : the calibration value of the infrared sensor.<br/>(*Calibration value - control value of infrared sensor)\",\r\n                robotis_carCont_cm_led:\r\n                    'Turns LED 1 or LED 4 among the 4 LEDs on or off. <br/>Not applicable to LED 2 and LED 3.',\r\n                robotis_carCont_cm_sound_detected_clear:\r\n                    'Initializes the final amount of detected sound to 0.',\r\n                robotis_carCont_aux_motor_speed:\r\n                    'Sets the speed of decelerating motor to the value of 0-1023.',\r\n                robotis_carCont_cm_calibration:\r\n                    'Sets the controlling value of infrared sensor (http://support.robotis.com/ko/: automobile robot> 2. B. control infrared value).',\r\n            },\r\n            Blocks: {\r\n                robotis_carCont_aux_motor_speed_1: 'Speed of decelerating motor',\r\n                robotis_carCont_aux_motor_speed_2: ', the output value',\r\n                robotis_carCont_calibration_1: 'Value of the infrared sensor calibration ',\r\n                robotis_common_case_01: '(을)를',\r\n                robotis_common_set: 'the output value',\r\n                robotis_common_value: 'Value',\r\n                robotis_common_clockwhise: 'Clockwise',\r\n                robotis_common_counter_clockwhise: 'Counterclockwise',\r\n                robotis_common_wheel_mode: 'Wheel mode',\r\n                robotis_common_joint_mode: 'Joint mode',\r\n                robotis_common_red_color: 'Red',\r\n                robotis_common_green_color: 'Green',\r\n                robotis_common_blue_color: 'Blue',\r\n                robotis_common_on: 'Turn on',\r\n                robotis_common_off: 'Turn off',\r\n                robotis_common_cm: 'Controller',\r\n                robotis_common_port_1: 'Port 1',\r\n                robotis_common_port_2: 'Port 2',\r\n                robotis_common_port_3: 'Port 3',\r\n                robotis_common_port_4: 'Port 4',\r\n                robotis_common_port_5: 'Port 5',\r\n                robotis_common_port_6: 'Port 6',\r\n                robotis_common_play_buzzer: 'Play',\r\n                robotis_common_play_motion: 'Play',\r\n                robotis_common_motion: 'Motion',\r\n                robotis_common_index_number: 'Number',\r\n                robotis_common_left: 'Left',\r\n                robotis_common_right: 'Right',\r\n                robotis_common_minute: 'minute(s)',\r\n                robotis_common_forward: 'Forward',\r\n                robotis_common_backward: 'Backword',\r\n                robotis_common_turn_left: 'Turn left',\r\n                robotis_common_turn_right: 'Turn Right',\r\n                robotis_common_stop: 'Stop',\r\n                robotis_cm_custom: 'Custom address',\r\n                robotis_cm_spring_left: 'Left contact sensor',\r\n                robotis_cm_spring_right: 'Right contact sensor',\r\n                robotis_cm_led_left: 'Left LED',\r\n                robotis_cm_led_right: 'Right LED',\r\n                robotis_cm_led_both: 'Both LED',\r\n                robotis_cm_switch: 'Status of the switch',\r\n                robotis_cm_user_button: 'Status of user button',\r\n                robotis_cm_sound_detected: 'Final number of sound detection ',\r\n                robotis_cm_sound_detecting: 'Number of live sound detection ',\r\n                robotis_cm_ir_left: 'Left infrared sensor',\r\n                robotis_cm_ir_right: 'Right infrared sensor',\r\n                robotis_cm_calibration_left: 'Value of the left infrared sensor calibration ',\r\n                robotis_cm_calibration_right: 'Value of the right infrared sensor calibration ',\r\n                robotis_cm_clear_sound_detected: 'Initialize the final number of sound detection',\r\n                robotis_cm_buzzer_index: 'Scale index',\r\n                robotis_cm_buzzer_melody: 'Melody',\r\n                robotis_cm_led_1: 'LED 1',\r\n                robotis_cm_led_4: 'LED 4',\r\n                robotis_aux_servo_position: 'Position of servo motor',\r\n                robotis_aux_ir: 'Infrared sensor',\r\n                robotis_aux_touch: 'Contact sensor',\r\n                robotis_aux_brightness: 'CDS',\r\n                robotis_aux_hydro_themo_humidity: 'Temperature-humidity sensor (humidity)',\r\n                robotis_aux_hydro_themo_temper: 'Temperature-humidity sensor (temperature)',\r\n                robotis_aux_temperature: 'Temperature sensor',\r\n                robotis_aux_ultrasonic: 'Ultrasonic sensor',\r\n                robotis_aux_magnetic: 'Magnetic sensor',\r\n                robotis_aux_motion_detection: 'Motion detector',\r\n                robotis_aux_color: 'Color sensor',\r\n                robotis_aux_custom: 'User device',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.Robotis_carCont.getBlocks = function() {\r\n    return {\r\n        //region robotis 로보티즈 carCont\r\n        robotis_carCont_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_cm_spring_left, 'CM_SPRING_LEFT'],\r\n                        [Lang.Blocks.robotis_cm_spring_right, 'CM_SPRING_RIGHT'],\r\n                        [Lang.Blocks.robotis_cm_switch, 'CM_SWITCH'],\r\n                        [Lang.Blocks.robotis_cm_sound_detected, 'CM_SOUND_DETECTED'],\r\n                        [Lang.Blocks.robotis_cm_sound_detecting, 'CM_SOUND_DETECTING'],\r\n                        [Lang.Blocks.robotis_cm_ir_left, 'CM_IR_LEFT'],\r\n                        [Lang.Blocks.robotis_cm_ir_right, 'CM_IR_RIGHT'],\r\n                        [Lang.Blocks.robotis_cm_calibration_left, 'CM_CALIBRATION_LEFT'],\r\n                        [Lang.Blocks.robotis_cm_calibration_right, 'CM_CALIBRATION_RIGHT'],\r\n                    ],\r\n                    value: 'CM_SPRING_LEFT',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_carCont_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                SENSOR: 0,\r\n            },\r\n            class: 'robotis_carCont_cm',\r\n            isNotFor: ['robotis_carCont'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_carCont.INSTRUCTION.READ;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                var data_default_address = 0;\r\n                var data_default_length = 0;\r\n\r\n                var sensor = script.getStringField('SENSOR');\r\n\r\n                if (sensor == 'CM_SPRING_LEFT') {\r\n                    data_default_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SPRING_LEFT[0];\r\n                    data_default_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SPRING_LEFT[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SPRING_LEFT[2];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SPRING_LEFT[3];\r\n                } else if (sensor == 'CM_SPRING_RIGHT') {\r\n                    data_default_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SPRING_RIGHT[0];\r\n                    data_default_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SPRING_RIGHT[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SPRING_RIGHT[2];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SPRING_RIGHT[3];\r\n                } else if (sensor == 'CM_SWITCH') {\r\n                    data_default_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SWITCH[0];\r\n                    data_default_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SWITCH[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SWITCH[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SWITCH[1];\r\n                } else if (sensor == 'CM_SOUND_DETECTED') {\r\n                    data_default_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                    data_default_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                } else if (sensor == 'CM_SOUND_DETECTING') {\r\n                    data_default_address =\r\n                        Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTING[0];\r\n                    data_default_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTING[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTING[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTING[1];\r\n                } else if (sensor == 'CM_IR_LEFT') {\r\n                    data_default_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_IR_LEFT[0];\r\n                    data_default_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_IR_LEFT[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_IR_LEFT[2];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_IR_LEFT[3];\r\n                } else if (sensor == 'CM_IR_RIGHT') {\r\n                    data_default_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_IR_RIGHT[0];\r\n                    data_default_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_IR_RIGHT[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_IR_RIGHT[2];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_IR_RIGHT[3];\r\n                } else if (sensor == 'CM_CALIBRATION_LEFT') {\r\n                    data_default_address =\r\n                        Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_LEFT[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_LEFT[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_LEFT[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_LEFT[1];\r\n                } else if (sensor == 'CM_CALIBRATION_RIGHT') {\r\n                    data_default_address =\r\n                        Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_RIGHT[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_RIGHT[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_RIGHT[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_RIGHT[1];\r\n                } else if (sensor == 'CM_BUTTON_STATUS') {\r\n                    data_default_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_BUTTON_STATUS[0];\r\n                    data_default_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_BUTTON_STATUS[1];\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_BUTTON_STATUS[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_BUTTON_STATUS[1];\r\n                }\r\n\r\n                //Entry.Robotis_carCont.setRobotisData([[data_instruction, data_address, data_length, data_value, data_default_length]]);\r\n                //// Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\r\n                //Entry.Robotis_carCont.update();\r\n                //\r\n                //return Entry.hw.portData[data_default_address];\r\n\r\n                if (\r\n                    Entry.hw.sendQueue.prevAddress &&\r\n                    Entry.hw.sendQueue.prevAddress == data_default_address\r\n                ) {\r\n                    if (\r\n                        Entry.hw.sendQueue.prevTime &&\r\n                        new Date() - Entry.hw.sendQueue.prevTime < 300\r\n                    ) {\r\n                        //throw new Entry.Utils.AsyncError();\r\n                        return Entry.hw.sendQueue.prevResult;\r\n                    }\r\n                }\r\n\r\n                Entry.Robotis_carCont.setRobotisData([\r\n                    [data_instruction, data_address, data_length, data_value, data_default_length],\r\n                ]);\r\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\r\n                Entry.Robotis_carCont.update();\r\n\r\n                var result = Entry.hw.portData[data_default_address];\r\n                Entry.hw.sendQueue.prevAddress = data_default_address;\r\n                Entry.hw.sendQueue.prevTime = new Date();\r\n                Entry.hw.sendQueue.prevResult = result;\r\n\r\n                return result;\r\n            },\r\n            syntax: { js: [], py: ['Robotis.carcont_sensor_value(%1)'] },\r\n        },\r\n        robotis_carCont_cm_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_on, '1'],\r\n                        [Lang.Blocks.robotis_common_off, '0'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_on, '1'],\r\n                        [Lang.Blocks.robotis_common_off, '0'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_carCont_cm_led',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE_LEFT: 0,\r\n                VALUE_RIGHT: 1,\r\n            },\r\n            class: 'robotis_carCont_cm',\r\n            isNotFor: ['robotis_carCont'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var value_left = script.getField('VALUE_LEFT', script);\r\n                var value_right = script.getField('VALUE_RIGHT', script);\r\n\r\n                var data_instruction = Entry.Robotis_carCont.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_LED[0];\r\n                data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_LED[1];\r\n\r\n                if (value_left == 1 && value_right == 1) {\r\n                    data_value = 9;\r\n                } else if (value_left == 1 && value_right == 0) {\r\n                    data_value = 8;\r\n                }\r\n                if (value_left == 0 && value_right == 1) {\r\n                    data_value = 1;\r\n                }\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_carCont.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.carcont_cm_led(%1, %2)'] },\r\n        },\r\n        robotis_carCont_cm_sound_detected_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_carCont_cm_sound_detected_clear',\r\n            },\r\n            class: 'robotis_carCont_cm',\r\n            isNotFor: ['robotis_carCont'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n\r\n                var data_instruction = Entry.Robotis_carCont.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                data_value = 0;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_carCont.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\r\n        },\r\n        robotis_carCont_aux_motor_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.General.left, 'LEFT'],\r\n                        [Lang.General.right, 'RIGHT'],\r\n                    ],\r\n                    value: 'LEFT',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_clockwhise, 'CW'],\r\n                        [Lang.Blocks.robotis_common_counter_clockwhise, 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['500'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_carCont_aux_motor_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION: 0,\r\n                DIRECTION_ANGLE: 1,\r\n                VALUE: 2,\r\n            },\r\n            class: 'robotis_carCont_cm',\r\n            isNotFor: ['robotis_carCont'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var direction = script.getField('DIRECTION', script);\r\n                var directionAngle = script.getField('DIRECTION_ANGLE', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_carCont.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                if (direction == 'LEFT') {\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.AUX_MOTOR_SPEED_LEFT[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.AUX_MOTOR_SPEED_LEFT[1];\r\n                } else {\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.AUX_MOTOR_SPEED_RIGHT[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.AUX_MOTOR_SPEED_RIGHT[1];\r\n                }\r\n\r\n                if (directionAngle == 'CW') {\r\n                    value = value + 1024;\r\n                    if (value > 2047) {\r\n                        value = 2047;\r\n                    }\r\n                } else {\r\n                    if (value > 1023) {\r\n                        value = 1023;\r\n                    }\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_carCont.delay\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.carcont_aux_motor_speed(%1, %2, %3)'],\r\n            },\r\n        },\r\n        robotis_carCont_aux_motor_speed2: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template:\r\n                '왼쪽 감속모터 속도를 %1, 출력값을 %2 (으)로 오른쪽 감속모터 속도를 %3, 출력값을 %4 (으)로 정하기 %5',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_clockwhise, 'CW'],\r\n                        [Lang.Blocks.robotis_common_counter_clockwhise, 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_clockwhise, 'CW'],\r\n                        [Lang.Blocks.robotis_common_counter_clockwhise, 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['500'],\r\n                    },\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['500'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_carCont_aux_motor_speed2',\r\n            },\r\n            paramsKeyMap: {\r\n                LEFT_ANGLE: 0,\r\n                LEFT_VALUE: 1,\r\n                RIGHT_ANGLE: 2,\r\n                RIGHT_VALUE: 3,\r\n            },\r\n            class: 'robotis_carCont_cm',\r\n            isNotFor: ['robotis_carCont'],\r\n            func: function(sprite, script) {\r\n                var data_instruction = Entry.Robotis_carCont.INSTRUCTION.WRITE,\r\n                    address = Entry.Robotis_carCont.CONTROL_TABLE.AUX_MOTOR_SPEED_LEFT[0];\r\n\r\n                var leftAngle = script.getField('LEFT_ANGLE', script);\r\n                var leftValue = script.getNumberValue('LEFT_VALUE');\r\n                var rightAngle = script.getField('RIGHT_ANGLE', script);\r\n                var rightValue = script.getNumberValue('RIGHT_VALUE');\r\n\r\n                leftValue = Math.min(leftValue, 1023);\r\n                leftValue = Math.max(leftValue, 0);\r\n                rightValue = Math.min(rightValue, 1023);\r\n                rightValue = Math.max(rightValue, 0);\r\n\r\n                if (leftAngle === 'CW') {\r\n                    leftValue += 1024;\r\n                }\r\n                if (rightAngle === 'CW') {\r\n                    rightValue += 1024;\r\n                }\r\n\r\n                var value = leftValue + (rightValue << 16);\r\n                var data_sendqueue = [[data_instruction, address, 4, value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_carCont.delay\r\n                );\r\n            },\r\n        },\r\n        robotis_carCont_cm_calibration: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.General.left, 'LEFT'],\r\n                        [Lang.General.right, 'RIGHT'],\r\n                    ],\r\n                    value: 'LEFT',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_carCont_cm_calibration',\r\n            },\r\n            paramsKeyMap: {\r\n                DIRECTION: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_carCont_cm',\r\n            isNotFor: ['robotis_carCont'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var direction = script.getField('DIRECTION', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_carCont.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                if (direction == 'LEFT') {\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_LEFT[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_LEFT[1];\r\n                } else {\r\n                    data_address = Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_RIGHT[0];\r\n                    data_length = Entry.Robotis_carCont.CONTROL_TABLE.CM_CALIBRATION_RIGHT[1];\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_carCont.delay\r\n                );\r\n\r\n                // Entry.hw.sendQueue['ROBOTIS_DATA'] = [[data_instruction, data_address, data_length, data_value]];\r\n                // update();\r\n                // return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: ['Robotis.carcont_cm_calibration(%1, %2)'] },\r\n        },\r\n        //endregion robotis 로보티즈\r\n    };\r\n};\r\n\r\nEntry.Robotis_openCM70.blockMenuBlocks = [\r\n    //robotis_openCM70\r\n    'robotis_irs_value',\r\n    'robotis_irs_value_boolean',\r\n    'robotis_color_value',\r\n    'robotis_color_value_boolean',\r\n    'robotis_openCM70_sensor_value',\r\n    'robotis_openCM70_aux_sensor_value',\r\n    'robotis_openCM70_cm_buzzer_index',\r\n    'robotis_openCM70_cm_buzzer_melody',\r\n    'robotis_openCM70_cm_sound_detected_clear',\r\n    'robotis_openCM70_cm_led',\r\n    //'robotis_openCM70_cm_motion',\r\n    'robotis_openCM70_cm_autodrive_motor',\r\n    'robotis_openCM70_cm_autodrive_ir',\r\n    'robotis_openCM70_cm_autodrive_speed',\r\n    'robotis_openCM70_aux_car_move',\r\n    'robotis_openCM70_aux_motor_speed',\r\n    'robotis_openCM70_aux_servo_mode',\r\n    'robotis_openCM70_aux_servo_speed',\r\n    'robotis_openCM70_aux_servo_position',\r\n    'robotis_openCM70_aux_led_module',\r\n    'robotis_openCM70_aux_custom',\r\n    'robotis_openCM70_cm_poweroff_timer',\r\n    'robotis_openCM70_cm_custom_value',\r\n    'robotis_openCM70_cm_custom',\r\n];\r\n\r\nlet opencm70_last_valid_value = [];\r\n\r\nEntry.Robotis_openCM70.getBlocks = function() {\r\n    return {\r\n        //region robotis 로보티즈 openCM70\r\n        robotis_openCM70_cm_custom_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['BYTE', 'BYTE'],\r\n                        ['WORD', 'WORD'],\r\n                        ['DWORD', 'DWORD'],\r\n                    ],\r\n                    value: 'BYTE',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_cm_custom_value',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n                SIZE: 1,\r\n            },\r\n            class: 'robotis_openCM70_custom',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                var scope = script.executor.scope;\r\n\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.READ;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                var data_default_address = 0;\r\n                var data_default_length = 0;\r\n\r\n                var size = script.getStringField('SIZE');\r\n\r\n                if (size == 'BYTE') {\r\n                    data_length = 1;\r\n                } else if (size == 'WORD') {\r\n                    data_length = 2;\r\n                } else if (size == 'DWORD') {\r\n                    data_length = 4;\r\n                }\r\n\r\n                data_address = script.getNumberValue('VALUE');\r\n\r\n                data_default_address = data_address;\r\n                data_default_length = data_length;\r\n\r\n                if (\r\n                    Entry.hw.sendQueue.prevAddress &&\r\n                    Entry.hw.sendQueue.prevAddress == data_default_address\r\n                ) {\r\n                    if (\r\n                        Entry.hw.sendQueue.prevTime &&\r\n                        new Date() - Entry.hw.sendQueue.prevTime < 200\r\n                    ) {\r\n                        //throw new Entry.Utils.AsyncError();\r\n                        return Entry.hw.sendQueue.prevResult;\r\n                    }\r\n                }\r\n\r\n                Entry.Robotis_carCont.setRobotisData([\r\n                    [data_instruction, data_address, data_length, data_value, data_default_length],\r\n                ]);\r\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\r\n                Entry.Robotis_carCont.update();\r\n\r\n                var result = Entry.hw.portData[data_default_address];\r\n                Entry.hw.sendQueue.prevAddress = data_default_address;\r\n                Entry.hw.sendQueue.prevTime = new Date();\r\n                Entry.hw.sendQueue.prevResult = result;\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_cm_custom_value(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_openCM70_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_cm_sound_detected, 'CM_SOUND_DETECTED'],\r\n                        [Lang.Blocks.robotis_cm_sound_detecting, 'CM_SOUND_DETECTING'],\r\n                        [Lang.Blocks.robotis_cm_user_button, 'CM_USER_BUTTON'],\r\n                    ],\r\n                    value: 'CM_SOUND_DETECTED',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_openCM70_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                SENSOR: 0,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                var scope = script.executor.scope;\r\n\r\n                scope.isStart = true;\r\n                scope.count = 0;\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.READ;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                var data_default_address = 0;\r\n                var data_default_length = 0;\r\n\r\n                var sensor = script.getStringField('SENSOR');\r\n\r\n                var increase = 0;\r\n                var sensor_name = '';\r\n\r\n                if (sensor == 'CM_SOUND_DETECTED') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                    sensor_name = 'DETECTEDSOUNDE'; \r\n                } else if (sensor == 'CM_SOUND_DETECTING') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTING[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTING[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTING[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTING[1];\r\n                    sensor_name = 'DETECTINGSOUNDE1'; \r\n                } else if (sensor == 'CM_USER_BUTTON') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_USER_BUTTON[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_USER_BUTTON[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_USER_BUTTON[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_USER_BUTTON[1];\r\n                    sensor_name = 'USERBUTTONSTATE'; \r\n                }\r\n\r\n                data_default_address = data_default_address + increase * data_default_length;\r\n\r\n                if (\r\n                    Entry.hw.sendQueue.prevAddress &&\r\n                    Entry.hw.sendQueue.prevAddress == data_default_address\r\n                ) {\r\n                    if (\r\n                        Entry.hw.sendQueue.prevTime &&\r\n                        new Date() - Entry.hw.sendQueue.prevTime < 200\r\n                    ) {\r\n                        //throw new Entry.Utils.AsyncError();\r\n                        return Entry.hw.sendQueue.prevResult;\r\n                    }\r\n                }\r\n\r\n                Entry.Robotis_carCont.setRobotisData([\r\n                    [data_instruction, data_address, data_length, data_value, data_default_length],\r\n                ]);\r\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\r\n                Entry.Robotis_carCont.update();\r\n\r\n                var result = Entry.hw.portData[sensor_name];\r\n                Entry.hw.sendQueue.prevAddress = data_default_address;\r\n                Entry.hw.sendQueue.prevTime = new Date();\r\n                Entry.hw.sendQueue.prevResult = result;\r\n\r\n                return result;\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_sensor_value(%1)'] },\r\n        },\r\n        robotis_openCM70_aux_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_aux_servo_position, 'AUX_SERVO_POSITION'],\r\n                        [Lang.Blocks.robotis_aux_ir, 'AUX_IR'],\r\n                        [Lang.Blocks.robotis_aux_touch, 'AUX_TOUCH'],\r\n                        [Lang.Blocks.robotis_aux_brightness, 'AUX_BRIGHTNESS'],\r\n                        [Lang.Blocks.robotis_aux_hydro_themo_humidity, 'AUX_HYDRO_THEMO_HUMIDITY'],\r\n                        [Lang.Blocks.robotis_aux_hydro_themo_temper, 'AUX_HYDRO_THEMO_TEMPER'],\r\n                        [Lang.Blocks.robotis_aux_temperature, 'AUX_TEMPERATURE'],\r\n                        [Lang.Blocks.robotis_aux_ultrasonic, 'AUX_ULTRASONIC'],\r\n                        [Lang.Blocks.robotis_aux_magnetic, 'AUX_MAGNETIC'],\r\n                        [Lang.Blocks.robotis_aux_motion_detection, 'AUX_MOTION_DETECTION'],\r\n                        [Lang.Blocks.robotis_aux_color, 'AUX_COLOR'],\r\n                        [Lang.Blocks.robotis_aux_custom, 'AUX_CUSTOM'],\r\n                    ],\r\n                    value: 'AUX_SERVO_POSITION',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'robotis_openCM70_aux_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                SENSOR: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                var scope = script.executor.scope;\r\n\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.READ;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                var data_default_address = 0;\r\n                var data_default_length = 0;\r\n\r\n                var port = script.getStringField('PORT');\r\n                var sensor = script.getStringField('SENSOR');\r\n\r\n                var aux_name = '';\r\n\r\n                var increase = 0;\r\n                if (port == '3') {\r\n                    increase = 2;\r\n                } else if (port == '4') {\r\n                    increase = 3;\r\n                } else if (port == '5') {\r\n                    increase = 4;\r\n                } else if (port == '6') {\r\n                    increase = 5;\r\n                }\r\n\r\n                if (sensor == 'AUX_SERVO_POSITION') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[1];\r\n                    aux_name = 'LIGHT' + (increase-2);\r\n                } else if (sensor == 'AUX_IR') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_IR[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_IR[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_IR[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_IR[1];\r\n                    aux_name = 'IR' + (increase-2);\r\n                } else if (sensor == 'AUX_TOUCH') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TOUCH[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TOUCH[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TOUCH[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TOUCH[1];\r\n                    aux_name = 'TOUCH' + (increase-2);\r\n                } else if (sensor == 'AUX_TEMPERATURE') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TEMPERATURE[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TEMPERATURE[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TEMPERATURE[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TEMPERATURE[1];\r\n                    aux_name = 'TEMPERATURE' + (increase-2);\r\n                } else if (sensor == 'AUX_BRIGHTNESS') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_BRIGHTNESS[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_BRIGHTNESS[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_BRIGHTNESS[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_BRIGHTNESS[1];\r\n                    aux_name = 'LIGHT' + (increase-2);\r\n                } else if (sensor == 'AUX_HYDRO_THEMO_HUMIDITY') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_HYDRO_THEMO_HUMIDITY[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_HYDRO_THEMO_HUMIDITY[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_HYDRO_THEMO_HUMIDITY[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_HYDRO_THEMO_HUMIDITY[1];\r\n                    aux_name = 'HUMIDTY' + (increase-2);\r\n                } else if (sensor == 'AUX_HYDRO_THEMO_TEMPER') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_HYDRO_THEMO_TEMPER[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_HYDRO_THEMO_TEMPER[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_HYDRO_THEMO_TEMPER[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_HYDRO_THEMO_TEMPER[1];\r\n                    aux_name = 'HT_TEMPERATURE' + (increase-2);\r\n                } else if (sensor == 'AUX_ULTRASONIC') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_ULTRASONIC[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_ULTRASONIC[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_ULTRASONIC[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_ULTRASONIC[1];\r\n                    aux_name = 'ULTRASONIC' + (increase-2);\r\n                } else if (sensor == 'AUX_MAGNETIC') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MAGNETIC[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MAGNETIC[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MAGNETIC[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MAGNETIC[1];\r\n                    aux_name = 'MAGNETIC' + (increase-2);\r\n                } else if (sensor == 'AUX_MOTION_DETECTION') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTION_DETECTION[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTION_DETECTION[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTION_DETECTION[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTION_DETECTION[1];\r\n                    aux_name = 'MOTION' + (increase-2);\r\n                } else if (sensor == 'AUX_COLOR') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_COLOR[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_COLOR[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_COLOR[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_COLOR[1];\r\n                    aux_name = 'COLOR' + (increase-2);\r\n                } else if (sensor == 'AUX_CUSTOM') {\r\n                    data_default_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[0];\r\n                    data_default_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[1];\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[1];\r\n                    aux_name = 'LIGHT' + (increase-2);\r\n                }\r\n\r\n                data_default_address = data_default_address + increase * data_default_length;\r\n                data_address = data_default_address;\r\n                // if (increase != 0) {\r\n                // data_length = 6 * data_default_length;\r\n                // }\r\n\r\n                if (\r\n                    Entry.hw.sendQueue.prevAddress &&\r\n                    Entry.hw.sendQueue.prevAddress == data_default_address\r\n                ) {\r\n                    if (\r\n                        Entry.hw.sendQueue.prevTime &&\r\n                        new Date() - Entry.hw.sendQueue.prevTime < 200\r\n                    ) {\r\n                        //throw new Entry.Utils.AsyncError();\r\n                        return Entry.hw.sendQueue.prevResult;\r\n                    }\r\n                }\r\n\r\n                Entry.Robotis_carCont.setRobotisData([\r\n                    [data_instruction, data_address, data_length, data_value, data_default_length],\r\n                ]);\r\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\r\n                Entry.Robotis_carCont.update();\r\n\r\n                var result = Entry.hw.portData[aux_name];\r\n                if (result == undefined)\r\n                {\r\n                    result = opencm70_last_valid_value[data_default_address];\r\n                }\r\n                else\r\n                {\r\n                    if (sensor == 'AUX_SERVO_POSITION') {\r\n                        if (result < 0) result = 0;\r\n                        else if (result > 1023) result = 1023;\r\n\r\n                        result = (512 - result) * 300 / 1023;\r\n\r\n                        result = Math.floor(result * 9 / 8);\r\n\r\n                        if (result > 150) result = 150;\r\n                        else if (result < -150) result = -150;\r\n                    }\r\n                    opencm70_last_valid_value[data_default_address] = result;\r\n                }\r\n                Entry.hw.sendQueue.prevAddress = data_default_address;\r\n                Entry.hw.sendQueue.prevTime = new Date();\r\n                Entry.hw.sendQueue.prevResult = result;\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_sensor_value(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_openCM70_cm_buzzer_index: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.General.note_a + '(0)', '0'],\r\n                        [Lang.General.note_a + '#(1)', '1'],\r\n                        [Lang.General.note_b + '(2)', '2'],\r\n                        [Lang.General.note_c + '(3)', '3'],\r\n                        [Lang.General.note_c + '#(4)', '4'],\r\n                        [Lang.General.note_d + '(5)', '5'],\r\n                        [Lang.General.note_d + '#(6)', '6'],\r\n                        [Lang.General.note_e + '(7)', '7'],\r\n                        [Lang.General.note_f + '(8)', '8'],\r\n                        [Lang.General.note_f + '#(9)', '9'],\r\n                        [Lang.General.note_g + '(10)', '10'],\r\n                        [Lang.General.note_g + '#(11)', '11'],\r\n                        [Lang.General.note_a + '(12)', '12'],\r\n                        [Lang.General.note_a + '#(13)', '13'],\r\n                        [Lang.General.note_b + '(14)', '14'],\r\n                        [Lang.General.note_c + '(15)', '15'],\r\n                        [Lang.General.note_c + '#(16)', '16'],\r\n                        [Lang.General.note_d + '(17)', '17'],\r\n                        [Lang.General.note_d + '#(18)', '18'],\r\n                        [Lang.General.note_e + '(19)', '19'],\r\n                        [Lang.General.note_f + '(20)', '20'],\r\n                        [Lang.General.note_f + '#(21)', '21'],\r\n                        [Lang.General.note_g + '(22)', '22'],\r\n                        [Lang.General.note_g + '#(23)', '23'],\r\n                        [Lang.General.note_a + '(24)', '24'],\r\n                        [Lang.General.note_a + '#(25)', '25'],\r\n                        [Lang.General.note_b + '(26)', '26'],\r\n                        [Lang.General.note_c + '(27)', '27'],\r\n                        [Lang.General.note_c + '#(28)', '28'],\r\n                        [Lang.General.note_d + '(29)', '29'],\r\n                        [Lang.General.note_d + '#(30)', '30'],\r\n                        [Lang.General.note_e + '(31)', '31'],\r\n                        [Lang.General.note_f + '(32)', '32'],\r\n                        [Lang.General.note_f + '#(33)', '33'],\r\n                        [Lang.General.note_g + '(34)', '34'],\r\n                        [Lang.General.note_g + '#(35)', '35'],\r\n                        [Lang.General.note_a + '(36)', '36'],\r\n                        [Lang.General.note_a + '#(37)', '37'],\r\n                        [Lang.General.note_b + '(38)', '38'],\r\n                        [Lang.General.note_c + '(39)', '39'],\r\n                        [Lang.General.note_c + '#(40)', '40'],\r\n                        [Lang.General.note_d + '(41)', '41'],\r\n                        [Lang.General.note_d + '#(42)', '42'],\r\n                        [Lang.General.note_e + '(43)', '43'],\r\n                        [Lang.General.note_f + '(44)', '44'],\r\n                        [Lang.General.note_f + '#(45)', '45'],\r\n                        [Lang.General.note_g + '(46)', '46'],\r\n                        [Lang.General.note_g + '#(47)', '47'],\r\n                        [Lang.General.note_a + '(48)', '48'],\r\n                        [Lang.General.note_a + '#(49)', '49'],\r\n                        [Lang.General.note_b + '(50)', '50'],\r\n                        [Lang.General.note_c + '(51)', '51'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_cm_buzzer_index',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_BUZZER_INDEX: 0,\r\n                CM_BUZZER_TIME: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var cmBuzzerIndex = script.getField('CM_BUZZER_INDEX', script);\r\n                var cmBuzzerTime = script.getNumberValue('CM_BUZZER_TIME', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address_1 = 0;\r\n                var data_length_1 = 0;\r\n                var data_value_1 = 0;\r\n                var data_address_2 = 0;\r\n                var data_length_2 = 0;\r\n                var data_value_2 = 0;\r\n                var interval = 100;\r\n\r\n                data_address_1 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[0];\r\n                data_length_1 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[1];\r\n                // data_value_1 = cmBuzzerTime * 10;\r\n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\r\n                data_value_1 = parseInt(cmBuzzerTime * 10);\r\n                if (data_value_1 > 50) {\r\n                    data_value_1 = 50;\r\n                }\r\n\r\n                data_address_2 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[0];\r\n                data_length_2 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[1];\r\n                data_value_2 = cmBuzzerIndex;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address_1, data_length_1, data_value_1],\r\n                    [data_instruction, data_address_2, data_length_2, data_value_2],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    cmBuzzerTime * 1000 + interval\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_cm_buzzer_index(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_openCM70_cm_buzzer_melody: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                        ['12', '12'],\r\n                        ['13', '13'],\r\n                        ['14', '14'],\r\n                        ['15', '15'],\r\n                        ['16', '16'],\r\n                        ['17', '17'],\r\n                        ['18', '18'],\r\n                        ['19', '19'],\r\n                        ['20', '20'],\r\n                        ['21', '21'],\r\n                        ['22', '22'],\r\n                        ['23', '23'],\r\n                        ['24', '24'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'robotis_openCM70_cm_buzzer_melody',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_BUZZER_MELODY: 0,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var cmBuzzerMelody = script.getField('CM_BUZZER_MELODY', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address_1 = 0;\r\n                var data_length_1 = 0;\r\n                var data_value_1 = 0;\r\n                var data_address_2 = 0;\r\n                var data_length_2 = 0;\r\n                var data_value_2 = 0;\r\n                var interval = 100;\r\n\r\n                data_address_1 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[0];\r\n                data_length_1 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[1];\r\n                data_value_1 = 255;\r\n\r\n                data_address_2 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[0];\r\n                data_length_2 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[1];\r\n                data_value_2 = cmBuzzerMelody;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address_1, data_length_1, data_value_1],\r\n                    [data_instruction, data_address_2, data_length_2, data_value_2],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    1000 + interval\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_buzzer_melody(%1)'] },\r\n        },\r\n        robotis_openCM70_cm_sound_detected_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_openCM70_cm_sound_detected_clear',\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                data_value = 0;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_sound_clear()'] },\r\n        },\r\n        robotis_openCM70_cm_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_red_color, 'CM_LED_R'],\r\n                        [Lang.Blocks.robotis_common_green_color, 'CM_LED_G'],\r\n                        [Lang.Blocks.robotis_common_blue_color, 'CM_LED_B'],\r\n                    ],\r\n                    value: 'CM_LED_R',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_on, '1'],\r\n                        [Lang.Blocks.robotis_common_off, '0'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_openCM70_cm_led',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_LED: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var cmLed = script.getField('CM_LED', script);\r\n                var value = script.getField('VALUE', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                if (cmLed == 'CM_LED_R') {\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_R[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_R[1];\r\n                } else if (cmLed == 'CM_LED_G') {\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_G[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_G[1];\r\n                } else if (cmLed == 'CM_LED_B') {\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_B[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_B[1];\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_led(%1, %2)'] },\r\n        },\r\n        /*\r\n        robotis_openCM70_cm_motion: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_cm_motion',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_MOTION[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_MOTION[1];\r\n                data_value = script.getNumberValue('VALUE', script);\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_motion(%1)'] },\r\n        },\r\n        */\r\n        robotis_openCM70_cm_autodrive_motor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_left, 'CM_LEFT'],\r\n                        [Lang.Blocks.robotis_common_right, 'CM_RIGHT'],\r\n                    ],\r\n                    value: 'CM_LEFT',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 1', '1'],\r\n                        ['PORT 2', '2'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_openCM70_cm_autodrive_motor',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_MOTOR_POSITION: 0,\r\n                PORT_NUM: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var motor_position = script.getField('CM_MOTOR_POSITION', script);\r\n                var port_num = script.getField('PORT_NUM', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                if (motor_position == 'CM_LEFT') {\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE_LEFT_MOTOR_PORT[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE_LEFT_MOTOR_PORT[1];\r\n                } else if (motor_position == 'CM_RIGHT') {\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE_RIGHT_MOTOR_PORT[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE_RIGHT_MOTOR_PORT[1];\r\n                }\r\n\r\n                data_value = port_num;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_autodrive_motor_port(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_cm_autodrive_ir: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_left, 'CM_LEFT'],\r\n                        [Lang.Blocks.robotis_common_right, 'CM_RIGHT'],\r\n                    ],\r\n                    value: 'CM_LEFT',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_openCM70_cm_autodrive_ir',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_IR_POSITION: 0,\r\n                PORT_NUM: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var ir_position = script.getField('CM_IR_POSITION', script);\r\n                var port_num = script.getField('PORT_NUM', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                if (ir_position == 'CM_LEFT') {\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE_LEFT_IR_PORT[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE_LEFT_IR_PORT[1];\r\n                } else if (ir_position == 'CM_RIGHT') {\r\n                    data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE_RIGHT_IR_PORT[0];\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE_RIGHT_IR_PORT[1];\r\n                }\r\n\r\n                data_value = port_num;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_autodrive_ir_port(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_cm_autodrive_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['100%', '100'],\r\n                        ['90%', '90'],\r\n                        ['80%', '80'],\r\n                        ['70%', '70'],\r\n                        ['60%', '60'],\r\n                        ['50%', '50'],\r\n                        ['40%', '40'],\r\n                        ['30%', '30'],\r\n                        ['20%', '20'],\r\n                        ['10%', '10'],\r\n                        ['0%', '0'],\r\n                    ],\r\n                    value: '80',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_openCM70_cm_autodrive_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_AUTODRIVE_SPEED: 0,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var autodrive_speed = script.getField('CM_AUTODRIVE_SPEED', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_AUTODRIVE[1];\r\n                data_value = autodrive_speed;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_autodrive_speed(%1)'] },\r\n        },\r\n        robotis_openCM70_aux_car_move: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_forward, 'F'],\r\n                        [Lang.Blocks.robotis_common_backward, 'B'],\r\n                        [Lang.Blocks.robotis_common_turn_left, 'L'],\r\n                        [Lang.Blocks.robotis_common_turn_right, 'R'],\r\n                        [Lang.Blocks.robotis_common_stop, 'S'],\r\n                    ],\r\n                    value: 'F',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['50'],\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_car_move',\r\n            },\r\n            paramsKeyMap: {\r\n                SPEED: 0,\r\n                MOVE_DIRECTION: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var speed = script.getNumberValue('SPEED');\r\n                var direction = script.getField('MOVE_DIRECTION', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[1] * 2;\r\n\r\n                if (speed < 0) speed = 0;\r\n                else if (speed > 100) speed = 100;\r\n\r\n                speed = Math.floor(speed * 1023 /100);\r\n\r\n                if (direction == 'F') {\r\n                    data_value = speed + (speed + 1024) * 65536;\r\n                } else if (direction == 'B'){\r\n                    data_value = (speed + 1024) + speed * 65536;\r\n                } else if (direction == 'L'){\r\n                    data_value = (speed + 1024) + (speed + 1024) * 65536;\r\n                } else if (direction == 'R'){\r\n                    data_value = speed + speed * 65536;\r\n                } else if (direction == 'S'){\r\n                    data_value = 0;\r\n                }\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_car_move(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_irs_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1 적외선 센서 값',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_irs_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_irs',\r\n            //'isNotFor': ['mini'],\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                let value = 0;\r\n                let data_address = 0;\r\n                switch (port) {\r\n                    case '3':\r\n                        value = Entry.hw.portData.IR0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        value = Entry.hw.portData.IR1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        value = Entry.hw.portData.IR2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        value = Entry.hw.portData.IR3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 2;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                //Entry.Robotis_carCont.update();\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 && port == '3') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 && port == '4') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 && port == '5') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 && port == '6') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 = true;\r\n                }\r\n                //var value = (Entry.hw.portData['IN' + port] > 125) ? 1 : 0;\r\n                return value;\r\n            },\r\n        },\r\n        robotis_irs_value_boolean: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1 적외선 센서 값 %2 %3',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'GREATER',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'robotis_irs_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n                RIGHTVALUE: 2,\r\n            },\r\n            class: 'robotis_irs',\r\n            //'isNotFor': ['mini'],\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT', script);\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\r\n                let leftValue = 0;\r\n                let isCheck = false;\r\n                let data_address = 0;\r\n    \r\n                switch (port) {\r\n                    case '3':\r\n                        leftValue = Entry.hw.portData.IR0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        leftValue = Entry.hw.portData.IR1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        leftValue = Entry.hw.portData.IR2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        leftValue = Entry.hw.portData.IR3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 2;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                //Entry.Robotis_carCont.update();\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 && port == '3') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 && port == '4') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 && port == '5') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 && port == '6') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 = true;\r\n                }\r\n    \r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n    \r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_color_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1 컬러 센서 값',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_color_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_color',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                let value = 0;\r\n                let data_address = 0;\r\n                switch (port) {\r\n                    case '3':\r\n                        value = Entry.hw.portData.COLOR0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        value = Entry.hw.portData.COLOR1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        value = Entry.hw.portData.COLOR2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        value = Entry.hw.portData.COLOR3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 4;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                Entry.Robotis_carCont.update();\r\n    \r\n                switch (value) {\r\n                    case 0:\r\n                        value = '알 수 없음';\r\n                        break;\r\n                    case 1:\r\n                        value = '흰색';\r\n                        break;\r\n                    case 2:\r\n                        value = '검은색';\r\n                        break;\r\n                    case 3:\r\n                        value = '빨강색';\r\n                        break;\r\n                    case 4:\r\n                        value = '초록색';\r\n                        break;\r\n                    case 5:\r\n                        value = '파랑색';\r\n                        break;\r\n                    case 6:\r\n                        value = '노랑색';\r\n                        break;\r\n                }\r\n    \r\n                return value;\r\n            },\r\n        },\r\n        robotis_color_value_boolean: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1 컬러 센서 값 %2 %3',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['!=', 'NOT_EQUAL'],\r\n                    ],\r\n                    value: 'EQUAL',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['알 수 없음 : 0', '0'],\r\n                        ['흰색 : 1', '1'],\r\n                        ['검은색 : 2', '2'],\r\n                        ['빨강색 : 3', '3'],\r\n                        ['초록색 : 4', '4'],\r\n                        ['파랑색 : 5', '5'],\r\n                        ['노랑색 : 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_color_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n                RIGHTVALUE: 2,\r\n            },\r\n            class: 'robotis_color',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getField('PORT', script);\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberField('RIGHTVALUE', script);\r\n                let leftValue = 0;\r\n                let data_address = 0;\r\n                let isCheck = false;\r\n    \r\n                switch (port) {\r\n                    case '3':\r\n                        leftValue = Entry.hw.portData.COLOR0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        leftValue = Entry.hw.portData.COLOR1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        leftValue = Entry.hw.portData.COLOR2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        leftValue = Entry.hw.portData.COLOR3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 4;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                Entry.Robotis_carCont.update();\r\n    \r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'NOT_EQUAL':\r\n                        isCheck = Number(leftValue) != Number(rightValue);\r\n                        break;\r\n                }\r\n    \r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_openCM70_aux_motor_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 1', '1'],\r\n                        ['PORT 2', '2'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_clockwhise, 'CW'],\r\n                        [Lang.Blocks.robotis_common_counter_clockwhise, 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['50'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_motor_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                DIRECTION_ANGLE: 1,\r\n                VALUE: 2,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var directionAngle = script.getField('DIRECTION_ANGLE', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n\r\n                if (value < 0) value = 0;\r\n                else if (value > 100) value = 100;\r\n\r\n                value = Math.floor(value * 1023 / 100);\r\n\r\n                if (directionAngle == 'CW') {\r\n                    value = value + 1024;\r\n                    if (value > 2047) {\r\n                        value = 2047;\r\n                    }\r\n                } else {\r\n                    if (value > 1023) {\r\n                        value = 1023;\r\n                    }\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_motor_speed(%1, %2, %3)'],\r\n            },\r\n        },\r\n        robotis_openCM70_aux_servo_mode: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_wheel_mode, '0'],\r\n                        [Lang.Blocks.robotis_common_joint_mode, '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_openCM70_aux_servo_mode',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                MODE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var mode = script.getField('MODE', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_MODE[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_MODE[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n                data_value = mode;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_aux_servo_mode(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_aux_servo_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_clockwhise, 'CW'],\r\n                        [Lang.Blocks.robotis_common_counter_clockwhise, 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['50'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_servo_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                DIRECTION_ANGLE: 1,\r\n                VALUE: 2,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var directionAngle = script.getField('DIRECTION_ANGLE', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_SPEED[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_SPEED[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n\r\n                if (value < 0) value = 0;\r\n                else if (value > 100) value = 100;\r\n\r\n                value = Math.floor(value * 1023 / 100);\r\n\r\n                if (directionAngle == 'CW') {\r\n                    value = value + 1024;\r\n                    if (value > 2047) {\r\n                        value = 2047;\r\n                    }\r\n                } else {\r\n                    if (value > 1023) {\r\n                        value = 1023;\r\n                    }\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_servo_speed(%1, %2, %3)'],\r\n            },\r\n        },\r\n        robotis_openCM70_aux_servo_position: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_servo_position',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n\r\n                if (value > 150) {\r\n                    value = 150;\r\n                } else if (value < -150) {\r\n                    value = -150;\r\n                }\r\n\r\n                value = value * 8 / 9;\r\n\r\n                data_value = 512 - Math.floor(value * 1023 / 300);\r\n\r\n                if (data_value < 0) data_value = 0;\r\n                else if (data_value > 1023) data_value = 1023;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_servo_position(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_openCM70_aux_led_module: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_cm_led_both + Lang.Blocks.robotis_common_off, '0'],\r\n                        [Lang.Blocks.robotis_cm_led_right + Lang.Blocks.robotis_common_on, '1'],\r\n                        [Lang.Blocks.robotis_cm_led_left + Lang.Blocks.robotis_common_on, '2'],\r\n                        [Lang.Blocks.robotis_cm_led_both + Lang.Blocks.robotis_common_on, '3'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_openCM70_aux_led_module',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                LED_MODULE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var ledModule = script.getField('LED_MODULE', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_LED_MODULE[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_LED_MODULE[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n                data_value = ledModule;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_aux_led_module(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_aux_custom: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_custom',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_aux_custom(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_cm_poweroff_timer: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_off, '0'],\r\n                        ['1' + Lang.Blocks.robotis_common_minute, '1'],\r\n                        ['2' + Lang.Blocks.robotis_common_minute, '2'],\r\n                        ['3' + Lang.Blocks.robotis_common_minute, '3'],\r\n                        ['4' + Lang.Blocks.robotis_common_minute, '4'],\r\n                        ['5' + Lang.Blocks.robotis_common_minute, '5'],\r\n                        ['6' + Lang.Blocks.robotis_common_minute, '6'],\r\n                        ['7' + Lang.Blocks.robotis_common_minute, '7'],\r\n                        ['8' + Lang.Blocks.robotis_common_minute, '8'],\r\n                        ['9' + Lang.Blocks.robotis_common_minute, '9'],\r\n                        ['10' + Lang.Blocks.robotis_common_minute, '10'],\r\n                        ['11' + Lang.Blocks.robotis_common_minute, '11'],\r\n                        ['12' + Lang.Blocks.robotis_common_minute, '12'],\r\n                        ['13' + Lang.Blocks.robotis_common_minute, '13'],\r\n                        ['14' + Lang.Blocks.robotis_common_minute, '14'],\r\n                        ['15' + Lang.Blocks.robotis_common_minute, '15'],\r\n                        ['16' + Lang.Blocks.robotis_common_minute, '16'],\r\n                        ['17' + Lang.Blocks.robotis_common_minute, '17'],\r\n                        ['18' + Lang.Blocks.robotis_common_minute, '18'],\r\n                        ['19' + Lang.Blocks.robotis_common_minute, '19'],\r\n                        ['20' + Lang.Blocks.robotis_common_minute, '20'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'robotis_openCM70_cm_poweroff_timer',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_POWEROFF_TIMER: 0,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var cm_poweroff_timer = script.getField('CM_POWEROFF_TIMER', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_POWEROFF_TIMER[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_POWEROFF_TIMER[1];\r\n                data_value = cm_poweroff_timer;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_poweroff_timer(%1)'] },\r\n        },\r\n        robotis_openCM70_cm_custom: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_cm_custom',\r\n            },\r\n            paramsKeyMap: {\r\n                ADDRESS: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_openCM70_custom',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            func: function(sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = script.getNumberValue('ADDRESS');\r\n                data_value = script.getNumberValue('VALUE');\r\n                if (data_value > 65535) {\r\n                    data_length = 4;\r\n                } else if (data_value > 255) {\r\n                    data_length = 2;\r\n                } else {\r\n                    data_length = 1;\r\n                }\r\n\r\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_custom(%1, %2)'] },\r\n        },\r\n        //endregion robotis 로보티즈\r\n    };\r\n};\r\n\r\nEntry.Robotis_openCM70.practicalBlockMenuBlocks = {\r\n    hw_motor: [\r\n        'robotis_aux_move_for',\r\n        'robotis_aux_stop_for',\r\n        'robotis_set_servo_joint',\r\n        'robotis_set_servo_wheel',\r\n        'robotis_move_for_secs',\r\n    ],\r\n    hw_melody: [\r\n        'robotis_melody_note_for',\r\n    ],\r\n    hw_sensor: [\r\n        'robotis_touch_value',\r\n        'robotis_touch_value_boolean',\r\n        'robotis_irs_value',\r\n        'robotis_irs_value_boolean',\r\n        'robotis_light_value',\r\n        'robotis_light_value_boolean',\r\n        'robotis_detectedsound_value',\r\n        'robotis_detectingsound_value',\r\n        'robotis_detectedsound_value_boolean',\r\n        'robotis_detectingsound_value_boolean',\r\n        'robotis_detectedsound_value_init',\r\n        'robotis_color_value',\r\n        'robotis_color_value_boolean',\r\n        'robotis_humidity_value',\r\n        'robotis_humidity_value_boolean',\r\n        'robotis_temperature_value',\r\n        'robotis_temperature_value_boolean',\r\n        'robotis_userbutton_value',\r\n        'robotis_userbutton_value_boolean',\r\n    ],\r\n    hw_led: [\r\n        'robotis_set_led',\r\n    ],\r\n}\r\n\r\nEntry.Robotis_openCM70.getPracticalBlocks = function() {\r\n    return{\r\n        robotis_set_led: {\r\n            color: '#2AB4D3',\r\n            outerLine: '#0e93b1',\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 LED를 %2 %3',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#0e93b1',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['모두 끄기', '0'],\r\n                        ['노랑색 켜기', '1'],\r\n                        ['파랑색 켜기', '2'],\r\n                        ['모두 켜기', '3'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: '#0e93b1',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/light.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_set_led',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                COLOR: 1,\r\n            },\r\n            class: 'robotis_led',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n    \r\n                const port = script.getStringField('PORT');\r\n                const value = 0;\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                let data_address = 0;\r\n                const data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_LED_MODULE[1];\r\n                const data_value = script.getNumberField('COLOR');\r\n                switch (port) {\r\n                    case '3':\r\n                        data_address = 212;\r\n                        break;\r\n                    case '4':\r\n                        data_address = 213;\r\n                        break;\r\n                    case '5':\r\n                        data_address = 214;\r\n                        break;\r\n                    case '6':\r\n                        data_address = 215;\r\n                        break;\r\n                }\r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                //Entry.Robotis_carCont.update();\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n        },\r\n        robotis_touch_value: {\r\n            color: '#2AB4D3',\r\n            outerLine: '#0e93b1',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 접촉 센서 값',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#0e93b1',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_touch_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_touch',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                let value = 0;\r\n    \r\n                switch (port) {\r\n                    case '3':\r\n                        value = Entry.hw.portData.TOUCH0;\r\n                        break;\r\n                    case '4':\r\n                        value = Entry.hw.portData.TOUCH1;\r\n                        break;\r\n                    case '5':\r\n                        value = Entry.hw.portData.TOUCH2;\r\n                        break;\r\n                    case '6':\r\n                        value = Entry.hw.portData.TOUCH3;\r\n                        break;\r\n                }\r\n                return value;\r\n            },\r\n        },\r\n        robotis_touch_value_boolean: {\r\n            color: '#2AB4D3',\r\n            outerLine: '#0e93b1',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 접촉 센서가 %2',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#0e93b1',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['접촉 되면', '1'],\r\n                        ['접촉 안되면', '0'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: '#0e93b1',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_touch_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                TOUCH: 1,\r\n            },\r\n            class: 'robotis_touch',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                const touch = script.getNumberField('TOUCH', script);\r\n                let value = 0;\r\n                switch (port) {\r\n                    case '3':\r\n                        value = Entry.hw.portData.TOUCH0;\r\n                        break;\r\n                    case '4':\r\n                        value = Entry.hw.portData.TOUCH1;\r\n                        break;\r\n                    case '5':\r\n                        value = Entry.hw.portData.TOUCH2;\r\n                        break;\r\n                    case '6':\r\n                        value = Entry.hw.portData.TOUCH3;\r\n                        break;\r\n                }\r\n                const isTouch = !((value == 1) ^ touch);\r\n    \r\n                return isTouch;\r\n            },\r\n        },\r\n        robotis_irs_value: {\r\n            color: '#C4065C',\r\n            outerLine: '#9a0045',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 적외선 센서 값',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_irs_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_irs',\r\n            //'isNotFor': ['mini'],\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                let value = 0;\r\n                let data_address = 0;\r\n                switch (port) {\r\n                    case '3':\r\n                        value = Entry.hw.portData.IR0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        value = Entry.hw.portData.IR1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        value = Entry.hw.portData.IR2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        value = Entry.hw.portData.IR3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 2;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                //Entry.Robotis_carCont.update();\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 && port == '3') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 && port == '4') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 && port == '5') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 && port == '6') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 = true;\r\n                }\r\n                //var value = (Entry.hw.portData['IN' + port] > 125) ? 1 : 0;\r\n                return value;\r\n            },\r\n        },\r\n        robotis_irs_value_boolean: {\r\n            color: '#C4065C',\r\n            outerLine: '#9a0045',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 적외선 센서 값 %2 %3',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'LESS',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'robotis_irs_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n                RIGHTVALUE: 2,\r\n            },\r\n            class: 'robotis_irs',\r\n            //'isNotFor': ['mini'],\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT', script);\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\r\n                let leftValue = 0;\r\n                let isCheck = false;\r\n                let data_address = 0;\r\n    \r\n                switch (port) {\r\n                    case '3':\r\n                        leftValue = Entry.hw.portData.IR0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        leftValue = Entry.hw.portData.IR1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        leftValue = Entry.hw.portData.IR2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        leftValue = Entry.hw.portData.IR3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 2;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                //Entry.Robotis_carCont.update();\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 && port == '3') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT3 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 && port == '4') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT4 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 && port == '5') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT5 = true;\r\n                }\r\n                if (!Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 && port == '6') {\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    Entry.Robotis_openCM70.IRS_MODULEWRITE.PORT6 = true;\r\n                }\r\n    \r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n    \r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_light_value: {\r\n            color: '#ff8d0f',\r\n            outerLine: '#e37100',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 빛 감지 센서 값',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '0'],\r\n                        ['PORT 4', '1'],\r\n                        ['PORT 5', '2'],\r\n                        ['PORT 6', '3'],\r\n                    ],\r\n                    value: '0',\r\n                    outerLine: '#e37100',\r\n                    fontSize: 11,\r\n                    bgColor: '#e37100',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_light_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_light',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                return Entry.hw.portData[`LIGHT${port}`];\r\n            },\r\n        },\r\n        robotis_light_value_boolean: {\r\n            color: '#ff8d0f',\r\n            outerLine: '#e37100',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 빛 감지 센서 값 %2 %3',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '0'],\r\n                        ['PORT 4', '1'],\r\n                        ['PORT 5', '2'],\r\n                        ['PORT 6', '3'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: '#e37100',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'LESS',\r\n                    fontSize: 11,\r\n                    bgColor: '#e37100',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'robotis_light_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n                RIGHTVALUE: 2,\r\n            },\r\n            class: 'robotis_light',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getNumberField('PORT', script);\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\r\n                const leftValue = Entry.hw.portData[`LIGHT${port}`];\r\n                let isCheck = false;\r\n    \r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n    \r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_userbutton_value: {\r\n            color: '#2AB4D3',\r\n            outerLine: '#0e93b1',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '사용자 버튼',\r\n            events: {},\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_userbutton_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'robotis_userbutton',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                return Entry.hw.portData.USERBUTTONSTATE;\r\n            },\r\n        },\r\n        robotis_userbutton_value_boolean: {\r\n            color: '#2AB4D3',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '사용자 버튼이 %1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['접촉 되면', '1'],\r\n                        ['접촉 안되면', '0'],\r\n                    ],\r\n                    value: '1',\r\n                    fontsIze: 11,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_userbutton_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_userbutton',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                const value = Entry.hw.portData.USERBUTTONSTATE;\r\n                var isTouch = false;\r\n    \r\n                var isTouch = port == value;\r\n    \r\n                return isTouch;\r\n            },\r\n        },\r\n        robotis_detectedsound_value: {\r\n            color: '#01d67f',\r\n            outerLine: '#00b36a',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '소리 센서 최종 소리 횟수',\r\n            events: {},\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_detectedsound_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'robotis_sound',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                return Entry.hw.portData.DETECTEDSOUNDE;\r\n            },\r\n        },\r\n        robotis_detectedsound_value_boolean: {\r\n            color: '#01d67f',\r\n            outerLine: '#00b36a',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '소리 센서 최종 소리 횟수 %1 %2',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'LESS',\r\n                    fontSize: 11,\r\n                    bgColor: '#00b36a',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'robotis_detectedsound_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                OPERATOR: 0,\r\n                RIGHTVALUE: 1,\r\n            },\r\n            class: 'robotis_sound',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\r\n                const leftValue = Entry.hw.portData.DETECTEDSOUNDE;\r\n                let isCheck = false;\r\n    \r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n    \r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_detectedsound_value_init: {\r\n            color: '#00D67F',\r\n            outerLine: '#00b36a',\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '소리 센서 최종 소리 횟수 초기화 %1',\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/sound.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_detectedsound_value_init',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'robotis_sound',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                const data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                const data_value = 0;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                //Entry.Robotis_carCont.update();\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n        },\r\n        robotis_detectingsound_value: {\r\n            color: '#01d67f',\r\n            outerLine: '#00b36a',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '소리 센서 실시간 소리 횟수',\r\n            events: {},\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_detectingsound_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'robotis_sound',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                return Entry.hw.portData.DETECTINGSOUNDE1;\r\n            },\r\n        },\r\n        robotis_detectedsound_value_boolean: {\r\n            color: '#01d67f',\r\n            outerLine: '#00b36a',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '소리 센서 최종 소리 횟수 %1 %2',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'LESS',\r\n                    fontSize: 11,\r\n                    bgColor: '#00b36a',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'robotis_detectedsound_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                OPERATOR: 0,\r\n                RIGHTVALUE: 1,\r\n            },\r\n            class: 'robotis_sound',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\r\n                const leftValue = Entry.hw.portData.DETECTEDSOUNDE;\r\n                let isCheck = false;\r\n    \r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n    \r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_detectedsound_value_init: {\r\n            color: '#00D67F',\r\n            outerLine: '#00b36a',\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '소리 센서 최종 소리 횟수 초기화 %1',\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/sound.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_detectedsound_value_init',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'robotis_sound',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                const data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                const data_value = 0;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                //Entry.Robotis_carCont.update();\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n        },\r\n        robotis_detectingsound_value: {\r\n            color: '#01d67f',\r\n            outerLine: '#00b36a',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '소리 센서 실시간 소리 횟수',\r\n            events: {},\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_detectingsound_value',\r\n            },\r\n            paramsKeyMap: {},\r\n            class: 'robotis_sound',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                return Entry.hw.portData.DETECTINGSOUNDE1;\r\n            },\r\n        },\r\n        robotis_detectingsound_value_boolean: {\r\n            color: '#01d67f',\r\n            outerLine: '#00b36a',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '소리 센서 실시간 소리 횟수 %1 %2',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'LESS',\r\n                    fontSize: 11,\r\n                    bgColor: '#00b36a',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'robotis_detectingsound_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                OPERATOR: 0,\r\n                RIGHTVALUE: 1,\r\n            },\r\n            class: 'robotis_sound',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\r\n                const leftValue = Entry.hw.portData.DETECTINGSOUNDE1;\r\n                let isCheck = false;\r\n    \r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n    \r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_color_value: {\r\n            color: '#2AB4D3',\r\n            outerLine: '#0e93b1',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 컬러 센서 값',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#0e93b1',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_color_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_color',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                let value = 0;\r\n                let data_address = 0;\r\n                switch (port) {\r\n                    case '3':\r\n                        value = Entry.hw.portData.COLOR0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        value = Entry.hw.portData.COLOR1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        value = Entry.hw.portData.COLOR2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        value = Entry.hw.portData.COLOR3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 4;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                Entry.Robotis_carCont.update();\r\n    \r\n                switch (value) {\r\n                    case 0:\r\n                        value = '알 수 없음';\r\n                        break;\r\n                    case 1:\r\n                        value = '흰색';\r\n                        break;\r\n                    case 2:\r\n                        value = '검은색';\r\n                        break;\r\n                    case 3:\r\n                        value = '빨강색';\r\n                        break;\r\n                    case 4:\r\n                        value = '초록색';\r\n                        break;\r\n                    case 5:\r\n                        value = '파랑색';\r\n                        break;\r\n                    case 6:\r\n                        value = '노랑색';\r\n                        break;\r\n                }\r\n    \r\n                return value;\r\n            },\r\n        },\r\n        robotis_color_value_boolean: {\r\n            color: '#C4065C',\r\n            outerLine: '#9a0045',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 컬러 센서 값 %2 %3',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'LESS',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['알 수 없음 : 0', '0'],\r\n                        ['흰색 : 1', '1'],\r\n                        ['검은색 : 2', '2'],\r\n                        ['빨강색 : 3', '3'],\r\n                        ['초록색 : 4', '4'],\r\n                        ['파랑색 : 5', '5'],\r\n                        ['노랑색 : 6', '6'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_color_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n                RIGHTVALUE: 2,\r\n            },\r\n            class: 'robotis_color',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getField('PORT', script);\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberField('RIGHTVALUE', script);\r\n                let leftValue = 0;\r\n                let data_address = 0;\r\n                let isCheck = false;\r\n    \r\n                switch (port) {\r\n                    case '3':\r\n                        leftValue = Entry.hw.portData.COLOR0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        leftValue = Entry.hw.portData.COLOR1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        leftValue = Entry.hw.portData.COLOR2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        leftValue = Entry.hw.portData.COLOR3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 4;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                Entry.Robotis_carCont.update();\r\n    \r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n    \r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_humidity_value: {\r\n            color: '#2AB4D3',\r\n            outerLine: '#0e93b1',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 습도 센서 값',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#0e93b1',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_humidity_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_humidity',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                let value = 0;\r\n                let data_address = 0;\r\n                switch (port) {\r\n                    case '3':\r\n                        value = Entry.hw.portData.HUMIDTY0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        value = Entry.hw.portData.HUMIDTY1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        value = Entry.hw.portData.HUMIDTY2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        value = Entry.hw.portData.HUMIDTY3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 5;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                Entry.Robotis_carCont.update();\r\n    \r\n                return value;\r\n            },\r\n        },\r\n        robotis_humidity_value_boolean: {\r\n            color: '#C4065C',\r\n            outerLine: '#9a0045',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 습도 센서 값 %2 %3',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'LESS',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['50'],\r\n                    },\r\n                ],\r\n                type: 'robotis_humidity_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n                RIGHTVALUE: 2,\r\n            },\r\n            class: 'robotis_humidity',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getNumberField('PORT', script);\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\r\n                let leftValue = 0;\r\n                let data_address = 0;\r\n                let isCheck = true;\r\n    \r\n                switch (port) {\r\n                    case 3:\r\n                        leftValue = Entry.hw.portData.HUMIDTY0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case 4:\r\n                        leftValue = Entry.hw.portData.HUMIDTY1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case 5:\r\n                        leftValue = Entry.hw.portData.HUMIDTY2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case 6:\r\n                        leftValue = Entry.hw.portData.HUMIDTY3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 5;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                Entry.Robotis_carCont.update();\r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_temperature_value: {\r\n            color: '#2AB4D3',\r\n            outerLine: '#0e93b1',\r\n            skeleton: 'basic_string_field',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 온도 센서 값',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#0e93b1',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_temperature_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'robotis_temperature',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getStringField('PORT');\r\n                let value = 0;\r\n                let data_address = 0;\r\n                switch (port) {\r\n                    case '3':\r\n                        value = Entry.hw.portData.TEMPERATURE0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case '4':\r\n                        value = Entry.hw.portData.TEMPERATURE1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case '5':\r\n                        value = Entry.hw.portData.TEMPERATURE2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case '6':\r\n                        value = Entry.hw.portData.TEMPERATURE3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 5;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                Entry.Robotis_carCont.update();\r\n    \r\n                return value;\r\n            },\r\n        },\r\n        robotis_temperature_value_boolean: {\r\n            color: '#C4065C',\r\n            outerLine: '#9a0045',\r\n            skeleton: 'basic_boolean_field',\r\n            fontColor: '#fff',\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1번 포트 온도 센서 값 %2 %3',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['=', 'EQUAL'],\r\n                        ['>', 'GREATER'],\r\n                        ['<', 'LESS'],\r\n                        ['≥', 'GREATER_OR_EQUAL'],\r\n                        ['≤', 'LESS_OR_EQUAL'],\r\n                    ],\r\n                    value: 'LESS',\r\n                    fontSize: 11,\r\n                    bgColor: '#9a0045',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                    noaRrow: true,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['50'],\r\n                    },\r\n                ],\r\n                type: 'robotis_temperature_value_boolean',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                OPERATOR: 1,\r\n                RIGHTVALUE: 2,\r\n            },\r\n            class: 'robotis_temperature',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const port = script.getNumberField('PORT', script);\r\n                const operator = script.getField('OPERATOR', script);\r\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\r\n                let leftValue = 0;\r\n                let data_address = 0;\r\n                let isCheck = true;\r\n    \r\n                switch (port) {\r\n                    case 3:\r\n                        leftValue = Entry.hw.portData.TEMPERATURE0;\r\n                        data_address = 108;\r\n                        break;\r\n                    case 4:\r\n                        leftValue = Entry.hw.portData.TEMPERATURE1;\r\n                        data_address = 109;\r\n                        break;\r\n                    case 5:\r\n                        leftValue = Entry.hw.portData.TEMPERATURE2;\r\n                        data_address = 110;\r\n                        break;\r\n                    case 6:\r\n                        leftValue = Entry.hw.portData.TEMPERATURE3;\r\n                        data_address = 111;\r\n                        break;\r\n                }\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                const data_length = 1;\r\n                const data_value = 5;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                Entry.Robotis_carCont.update();\r\n                switch (operator) {\r\n                    case 'EQUAL':\r\n                        isCheck = leftValue == rightValue;\r\n                        break;\r\n                    case 'GREATER':\r\n                        isCheck = Number(leftValue) > Number(rightValue);\r\n                        break;\r\n                    case 'LESS':\r\n                        isCheck = Number(leftValue) < Number(rightValue);\r\n                        break;\r\n                    case 'GREATER_OR_EQUAL':\r\n                        isCheck = Number(leftValue) >= Number(rightValue);\r\n                        break;\r\n                    case 'LESS_OR_EQUAL':\r\n                        isCheck = Number(leftValue) <= Number(rightValue);\r\n                        break;\r\n                }\r\n                return isCheck;\r\n            },\r\n        },\r\n        robotis_move_for_secs: {\r\n            color: '#00B200',\r\n            outerLine: '#019101',\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1모터를 %2 %3의 속도로 %4초 동안 회전 %5',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['왼쪽', '1'],\r\n                        ['오른쪽', '2'],\r\n                        ['양쪽', '3'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: '#019101',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['앞으로', 'CW'],\r\n                        ['뒤로', 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: '#019101',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/dcmotor.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'practical_course_motor_speed',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['2'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_move_for_secs',\r\n            },\r\n            paramsKeyMap: {\r\n                WHEEL: 0,\r\n                DIRECTION: 1,\r\n                SPEED: 2,\r\n                DURATION: 3,\r\n            },\r\n            class: 'robotis_motor',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const duration = script.getNumberValue('DURATION');\r\n                const wheel = script.getNumberField('WHEEL');\r\n                let value = script.getNumberValue('SPEED');\r\n                const direction = script.getStringField('DIRECTION');\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                let data_address = 0;\r\n                let data_length = 0;\r\n                let data_value = 0;\r\n    \r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\r\n    \r\n                if (wheel == '3') {\r\n                    data_length = 4;\r\n                    data_address = 136;\r\n                } else {\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\r\n                    data_address = data_address + (wheel - 1) * data_length;\r\n                }\r\n    \r\n                if (!script.isStart) {\r\n                    value = value * 68;\r\n                    if (wheel == '3' || wheel == '1') {\r\n                        if (direction == 'CCW') {\r\n                            value = value + 1024;\r\n                            if (value > 2047) {\r\n                                value = 2047;\r\n                            }\r\n                        } else {\r\n                            if (value > 1023) {\r\n                                value = 1023;\r\n                            }\r\n                        }\r\n                    } else {\r\n                        if (direction == 'CW') {\r\n                            value = value + 1024;\r\n                            if (value > 2047) {\r\n                                value = 2047;\r\n                            }\r\n                        } else {\r\n                            if (value > 1023) {\r\n                                value = 1023;\r\n                            }\r\n                        }\r\n                    }\r\n\r\n                    if ( value < 1024) {\r\n                        value = value + (value + 1024) * 0x10000;\r\n                    }\r\n                    else {\r\n                        value = value + (value - 1024) * 0x10000;\r\n                    }\r\n    \r\n                    data_value = value;\r\n    \r\n                    var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n    \r\n                    script.wheelMode = wheel;\r\n    \r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration * 1000);\r\n    \r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.Robotis_carCont.update();\r\n                    //return Entry.Robotis_carCont.postCallReturn(script, data_sendqueue, 2000);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    //data_sendqueue = [[data_instruction, data_address, data_length, 0]];\r\n                    //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    delete script.wheelMode;\r\n                    Entry.engine.isContinue = false;\r\n    \r\n                    data_sendqueue = [[data_instruction, data_address, data_length, 0]];\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.engine.isContinue = false;\r\n                    Entry.Robotis_carCont.update();\r\n                    return script.callReturn();\r\n                }\r\n                //return Entry.Robotis_carCont.postCallReturn(script, data_sendqueue, 2000);\r\n            },\r\n        },\r\n        robotis_aux_move_for: {\r\n            color: '#00B200',\r\n            outerLine: '#019101',\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1모터를 %2 %3의 속도로 계속 회전 %4',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['왼쪽', '1'],\r\n                        ['오른쪽', '2'],\r\n                        ['양쪽', '3'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: '#019101',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['앞으로', 'CW'],\r\n                        ['뒤로', 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: '#019101',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/dcmotor.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'practical_course_motor_speed',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_aux_move_for',\r\n            },\r\n            paramsKeyMap: {\r\n                WHEEL: 0,\r\n                DIRECTION: 1,\r\n                SPEED: 2,\r\n            },\r\n            class: 'robotis_motor',\r\n            //'isNotFor': ['mini'],\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const wheel = script.getNumberField('WHEEL');\r\n                let value = script.getNumberValue('SPEED');\r\n                const direction = script.getStringField('DIRECTION');\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                let data_address = 0;\r\n                let data_length = 0;\r\n                let data_value = 0;\r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\r\n    \r\n                if (wheel == '3') {\r\n                    data_length = 4;\r\n                    data_address = 136;\r\n                } else {\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\r\n                    data_address = data_address + (wheel - 1) * data_length;\r\n                }\r\n                value = value * 68;\r\n    \r\n                if (wheel == '3' || wheel == '1') {\r\n                    if (direction == 'CCW') {\r\n                        value = value + 1024;\r\n                        if (value > 2047) {\r\n                            value = 2047;\r\n                        }\r\n                    } else {\r\n                        if (value > 1023) {\r\n                            value = 1023;\r\n                        }\r\n                    }\r\n                } else {\r\n                    if (direction == 'CW') {\r\n                        value = value + 1024;\r\n                        if (value > 2047) {\r\n                            value = 2047;\r\n                        }\r\n                    } else {\r\n                        if (value > 1023) {\r\n                            value = 1023;\r\n                        }\r\n                    }\r\n                }\r\n\r\n                if ( value < 1024) {\r\n                    value = value + (value + 1024) * 0x10000;\r\n                }\r\n                else {\r\n                    value = value + (value - 1024) * 0x10000;\r\n                }\r\n    \r\n                data_value = value;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n        },\r\n        robotis_aux_stop_for: {\r\n            color: '#00B200',\r\n            outerLine: '#019101',\r\n            skeleton: 'basic',\r\n            fontColor: '#fff',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1모터를 정지 %2',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['왼쪽', '1'],\r\n                        ['오른쪽', '2'],\r\n                        ['양쪽', '3'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: '#019101',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/dcmotor.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'robotis_aux_stop_for',\r\n            },\r\n            paramsKeyMap: {\r\n                WHEEL: 0,\r\n            },\r\n            class: 'robotis_motor',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const wheel = script.getNumberField('WHEEL');\r\n                const value = 0;\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                let data_address = 0;\r\n                let data_length = 0;\r\n                let data_value = 0;\r\n    \r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\r\n                if (wheel == '3') {\r\n                    data_length = 4;\r\n                    data_address = 136;\r\n                } else {\r\n                    data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\r\n                    data_address = data_address + (wheel - 1) * data_length;\r\n                }\r\n    \r\n                data_value = value;\r\n    \r\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n        },\r\n        robotis_set_servo_wheel: {\r\n            color: '#D128BD',\r\n            outerLine: '#a2049e',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1 포트의 서보모터를 %2 %3속도로 회전 %4',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#A2049E',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['시계방향', 'CW'],\r\n                        ['반시계방향', 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: '#A2049E',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', 1],\r\n                        ['2', 2],\r\n                        ['3', 3],\r\n                        ['4', 4],\r\n                        ['5', 5],\r\n                        ['6', 6],\r\n                        ['7', 7],\r\n                        ['8', 8],\r\n                        ['9', 9],\r\n                        ['10', 10],\r\n                        ['11', 11],\r\n                        ['12', 12],\r\n                        ['13', 13],\r\n                        ['14', 14],\r\n                        ['15', 15],\r\n                    ],\r\n                    value: 7,\r\n                    fontSize: 11,\r\n                    bgColor: '#A2049E',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/servo.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null, null],\r\n                type: 'robotis_set_servo_wheel',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                DIRECTION: 1,\r\n                SPEED: 2,\r\n            },\r\n            class: 'robotis_servo_motor',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                // instruction / address / length / value / default length\r\n                const port = script.getField('PORT', script);\r\n                const direction = script.getStringField('DIRECTION');\r\n                const speed = script.getNumberField('SPEED');\r\n                const value = 0;\r\n    \r\n                let data_address3 = 0;\r\n                let data_length3 = 0;\r\n                let data_value3 = 0;\r\n    \r\n                let data_address2 = 0;\r\n                const data_length2 = 1;\r\n                const data_value2 = 7;\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                let data_address = 0;\r\n                let data_length = 0;\r\n                let data_value = 0;\r\n    \r\n                let data_address4 = 0; // servo speed\r\n                let data_length4 = 2;\r\n                let data_value4 = 0;\r\n    \r\n                data_value4 = speed * 68;\r\n                if (data_value4 > 1023) {\r\n                    data_value4 = 1023;\r\n                }\r\n                switch (port) {\r\n                    case '3':\r\n                        data_address2 = 108;\r\n                        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT3 = true;\r\n                        break;\r\n                    case '4':\r\n                        data_address2 = 109;\r\n                        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT4 = true;\r\n                        break;\r\n                    case '5':\r\n                        data_address2 = 110;\r\n                        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT5 = true;\r\n                        break;\r\n                    case '6':\r\n                        data_address2 = 111;\r\n                        Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT6 = true;\r\n                        break;\r\n                }\r\n    \r\n                data_address3 = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[0];\r\n                data_length3 = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[1];\r\n    \r\n                data_address3 = data_address3 + (port - 1) * data_length3;\r\n    \r\n                data_address4 = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_SPEED[0];\r\n                data_length4 = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_SPEED[1];\r\n    \r\n                data_address4 = data_address4 + (port - 1) * data_length4;\r\n    \r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_MODE[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_MODE[1];\r\n    \r\n                data_address = data_address + (port - 1) * data_length;\r\n                data_value = 0;\r\n    \r\n                if (direction == 'CW') {\r\n                    data_value4 = data_value4 + 1024;\r\n                    if (data_value4 > 2047) {\r\n                        data_value4 = 2047;\r\n                    }\r\n                } else {\r\n                    if (data_value4 > 1023) {\r\n                        data_value4 = 1023;\r\n                    }\r\n                }\r\n    \r\n                data_value3 = direction;\r\n    \r\n                //var data_sendqueue = [[data_instruction, data_address2, data_length2, data_value2], [data_instruction, data_address, data_length, data_value], [data_instruction, data_address4, data_length4, data_value4]];\r\n                //return Entry.Robotis_carCont.postCallReturn(script, data_sendqueue, Entry.Robotis_openCM70.delay);\r\n                //\r\n                if (!script.isStart) {\r\n                    if (\r\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT3 && port == '3') ||\r\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT4 && port == '4') ||\r\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT5 && port == '5') ||\r\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT6 && port == '6')\r\n                    ) {\r\n                        var data_sendqueue = [\r\n                            [data_instruction, data_address2, data_length2, data_value2],\r\n                        ];\r\n                        Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                        Entry.Robotis_carCont.update();\r\n                        script.isStart = true;\r\n                        script.timeFlag = 1;\r\n                        setTimeout(() => {\r\n                            script.timeFlag = 0;\r\n                        }, 1 * 650);\r\n                    } else {\r\n                        script.isStart = true;\r\n                        script.timeFlag = 0;\r\n                    }\r\n    \r\n                    /*\r\n                        var data_sendqueue = [[data_instruction, data_address2, data_length2, data_value2]];\r\n                        Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                        Entry.Robotis_carCont.update();\r\n                        script.isStart = true;\r\n                        script.timeFlag = 1;\r\n                        setTimeout(function () {\r\n                            script.timeFlag = 0;\r\n                        }, 1 * 650);\r\n                        */\r\n    \r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    //data_sendqueue = [[data_instruction, data_address, data_length, 0]];\r\n                    //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    delete script.wheelMode;\r\n                    Entry.engine.isContinue = false;\r\n    \r\n                    data_sendqueue = [\r\n                        [data_instruction, data_address, data_length, data_value],\r\n                        [data_instruction, data_address4, data_length4, data_value4],\r\n                    ];\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.engine.isContinue = false;\r\n                    Entry.Robotis_carCont.update();\r\n                    return script.callReturn();\r\n                }\r\n                //\r\n            },\r\n        },\r\n        robotis_set_servo_joint: {\r\n            color: '#D128BD',\r\n            outerLine: '#a2049e',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '%1 포트의 서보모터를 %2 도 %3속도로 이동 %4',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['PORT 3', '3'],\r\n                        ['PORT 4', '4'],\r\n                        ['PORT 5', '5'],\r\n                        ['PORT 6', '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: '#A2049E',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', 1],\r\n                        ['2', 2],\r\n                        ['3', 3],\r\n                        ['4', 4],\r\n                        ['5', 5],\r\n                        ['6', 6],\r\n                        ['7', 7],\r\n                        ['8', 8],\r\n                        ['9', 9],\r\n                        ['10', 10],\r\n                        ['11', 11],\r\n                        ['12', 12],\r\n                        ['13', 13],\r\n                        ['14', 14],\r\n                        ['15', 15],\r\n                    ],\r\n                    value: 7,\r\n                    fontSize: 11,\r\n                    bgColor: '#A2049E',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/servo.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['512'],\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'robotis_set_servo_joint',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n                SPEED: 2,\r\n            },\r\n            class: 'robotis_servo_motor',\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                // instruction / address / length / value / default length\r\n                const port = script.getField('PORT', script);\r\n                let value = script.getNumberValue('VALUE');\r\n                const speed = script.getNumberField('SPEED');\r\n    \r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                let data_address3 = 0;\r\n                let data_length3 = 0;\r\n                let data_value3 = 0;\r\n    \r\n                let data_address2 = 0;\r\n                const data_length2 = 1;\r\n                const data_value2 = 7;\r\n    \r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                let data_address = 0;\r\n                let data_length = 0;\r\n                let data_value = 0;\r\n    \r\n                let data_address4 = 0; // servo speed\r\n                let data_length4 = 2;\r\n                let data_value4 = 0;\r\n    \r\n                data_value4 = speed * 68;\r\n                if (data_value4 > 1023) {\r\n                    data_value4 = 1023;\r\n                }\r\n                switch (port) {\r\n                    case '3':\r\n                        data_address2 = 108;\r\n                        break;\r\n                    case '4':\r\n                        data_address2 = 109;\r\n                        break;\r\n                    case '5':\r\n                        data_address2 = 110;\r\n                        break;\r\n                    case '6':\r\n                        data_address2 = 111;\r\n                        break;\r\n                }\r\n    \r\n                data_address3 = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[0];\r\n                data_length3 = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[1];\r\n    \r\n                data_address3 = data_address3 + (port - 1) * data_length3;\r\n    \r\n                data_address4 = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_SPEED[0];\r\n                data_length4 = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_SPEED[1];\r\n    \r\n                data_address4 = data_address4 + (port - 1) * data_length4;\r\n    \r\n                data_address = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_MODE[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_MODE[1];\r\n    \r\n                data_address = data_address + (port - 1) * data_length;\r\n                data_value = 1;\r\n    \r\n                if (value > 1023) {\r\n                    value = 1023;\r\n                } else if (value < 0) {\r\n                    value = 0;\r\n                }\r\n    \r\n                data_value3 = value;\r\n    \r\n                if (!script.isStart) {\r\n                    var data_sendqueue = [[data_instruction, data_address2, data_length2, data_value2]];\r\n                    //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    //Entry.Robotis_carCont.update();\r\n                    if (\r\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT3 && port == '3') ||\r\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT4 && port == '4') ||\r\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT5 && port == '5') ||\r\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT6 && port == '6')\r\n                    ) {\r\n                        script.isStart = true;\r\n                        script.timeFlag = 1;\r\n                        setTimeout(() => {\r\n                            script.timeFlag = 0;\r\n                        }, 1 * 650);\r\n                    } else {\r\n                        script.isStart = true;\r\n                        script.timeFlag = 0;\r\n                    }\r\n    \r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    delete script.wheelMode;\r\n                    Entry.engine.isContinue = false;\r\n    \r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, 1 * 70);\r\n    \r\n                    data_sendqueue = [\r\n                        [data_instruction, data_address, data_length, data_value],\r\n                        [data_instruction, data_address4, data_length4, data_value4],\r\n                        [data_instruction, data_address3, data_length3, data_value3],\r\n                    ];\r\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\r\n                    Entry.engine.isContinue = false;\r\n                    Entry.Robotis_carCont.update();\r\n                    return script.callReturn();\r\n                }\r\n                //\r\n            },\r\n        },\r\n        robotis_melody_note_for: {\r\n            color: '#FC327F',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            isNotFor: ['robotis_openCM70', 'robotis_openCM70EDU'],\r\n            template: '멜로디 %1 을(를) %2 옥타브로 %3 만큼 소리내기 %4',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        //['무음', '12'],\r\n                        ['도', '0'],\r\n                        ['도#(레♭)', '1'],\r\n                        ['레', '2'],\r\n                        ['레#(미♭)', '3'],\r\n                        ['미', '4'],\r\n                        ['파', '5'],\r\n                        ['파#(솔♭)', '6'],\r\n                        ['솔', '7'],\r\n                        ['솔#(라♭)', '8'],\r\n                        ['라', '9'],\r\n                        ['라#(시♭)', '10'],\r\n                        ['시', '11'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: '#ce105e',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '0'],\r\n                        ['2', '1'],\r\n                        ['3', '2'],\r\n                        ['4', '3'],\r\n                        ['5', '4'],\r\n                        ['6', '5'],\r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: '#ce105e',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['온음표', '4'],\r\n                        ['2분음표', '2'],\r\n                        ['4분음표', '1'],\r\n                        ['8분음표', '0.5'],\r\n                        ['16분음표', '0.25'],\r\n                        /*['4분음표', '4'],\r\n                        ['8분음표', '8'],\r\n                        ['16분음표', '16'],*/\r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 11,\r\n                    bgColor: '#ce105e',\r\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/practical_course/melody.png',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null, null],\r\n                type: 'robotis_melody_note_for',\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n                OCTAVE: 1,\r\n                DURATION: 2,\r\n            },\r\n            class: 'robotis_melody',\r\n            //'isNotFor': ['mini'],\r\n            func(sprite, script) {\r\n                Entry.hw.sendQueue.IS_EDU = true;\r\n                const note = script.getNumberField('NOTE', script);\r\n                const octave = script.getNumberField('OCTAVE', script);\r\n                const cmBuzzerTime = script.getNumberField('DURATION', script);\r\n    \r\n                let cmBuzzerIndex = note + octave * 12;\r\n                if (cmBuzzerIndex > 51) {\r\n                    cmBuzzerIndex = 51;\r\n                }\r\n                if (cmBuzzerIndex < 0) {\r\n                    cmBuzzerIndex = 0;\r\n                }\r\n    \r\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                let data_address_1 = 0;\r\n                let data_length_1 = 0;\r\n                let data_value_1 = 0;\r\n                let data_address_2 = 0;\r\n                let data_length_2 = 0;\r\n                let data_value_2 = 0;\r\n    \r\n                data_address_1 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[0];\r\n                data_length_1 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[1];\r\n    \r\n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\r\n    \r\n                data_value_1 = parseInt(cmBuzzerTime * 10);\r\n                if (data_value_1 > 50) {\r\n                    data_value_1 = 50;\r\n                }\r\n                //data_value_1\r\n                data_address_2 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[0];\r\n                data_length_2 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[1];\r\n                data_value_2 = cmBuzzerIndex;\r\n    \r\n                const data_sendqueue = [\r\n                    [data_instruction, data_address_1, data_length_1, data_value_1],\r\n                    [data_instruction, data_address_2, data_length_2, data_value_2],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    cmBuzzerTime * 1000\r\n                );\r\n            },\r\n        },\r\n    }\r\n}\r\n/*Entry.Robotis_openCM70EDU.blockMenuBlocks = [\r\n    //Robotis_openCM70EDU\r\n    'robotis_openCM70_sensor_value',\r\n    'robotis_openCM70_aux_sensor_value',\r\n    'robotis_openCM70_cm_buzzer_index',\r\n    'robotis_openCM70_cm_buzzer_melody',\r\n    'robotis_openCM70_cm_sound_detected_clear',\r\n    'robotis_openCM70_cm_led',\r\n    'robotis_openCM70_cm_motion',\r\n    'robotis_openCM70_aux_motor_speed',\r\n    'robotis_openCM70_aux_servo_mode',\r\n    'robotis_openCM70_aux_servo_speed',\r\n    'robotis_openCM70_aux_servo_position',\r\n    'robotis_openCM70_aux_led_module',\r\n    'robotis_openCM70_aux_custom',\r\n    'robotis_openCM70_cm_custom_value',\r\n    'robotis_openCM70_cm_custom',\r\n];\r\nEntry.Robotis_openCM70EDU.getBlocks = function () {\r\n    return {\r\n        //region robotis 로보티즈 openCM70\r\n        robotis_openCM70_cm_custom_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['BYTE', 'BYTE'],\r\n                        ['WORD', 'WORD'],\r\n                        ['DWORD', 'DWORD'],\r\n                    ],\r\n                    value: 'BYTE',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_cm_custom_value',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n                SIZE: 1,\r\n            },\r\n            class: 'robotis_openCM70_custom',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                var scope = script.executor.scope;\r\n\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.READ;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                var data_default_address = 0;\r\n                var data_default_length = 0;\r\n\r\n                var size = script.getStringField('SIZE');\r\n\r\n                if (size == 'BYTE') {\r\n                    data_length = 1;\r\n                } else if (size == 'WORD') {\r\n                    data_length = 2;\r\n                } else if (size == 'DWORD') {\r\n                    data_length = 4;\r\n                }\r\n\r\n                data_address = script.getNumberValue('VALUE');\r\n\r\n                data_default_address = data_address;\r\n                data_default_length = data_length;\r\n\r\n                if (\r\n                    Entry.hw.sendQueue.prevAddress &&\r\n                    Entry.hw.sendQueue.prevAddress == data_default_address\r\n                ) {\r\n                    if (\r\n                        Entry.hw.sendQueue.prevTime &&\r\n                        new Date() - Entry.hw.sendQueue.prevTime < 200\r\n                    ) {\r\n                        //throw new Entry.Utils.AsyncError();\r\n                        return Entry.hw.sendQueue.prevResult;\r\n                    }\r\n                }\r\n\r\n                Entry.Robotis_carCont.setRobotisData([\r\n                    [\r\n                        data_instruction,\r\n                        data_address,\r\n                        data_length,\r\n                        data_value,\r\n                        data_default_length,\r\n                    ],\r\n                ]);\r\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\r\n                Entry.Robotis_carCont.update();\r\n\r\n                var result = Entry.hw.portData[data_default_address];\r\n                Entry.hw.sendQueue.prevAddress = data_default_address;\r\n                Entry.hw.sendQueue.prevTime = new Date();\r\n                Entry.hw.sendQueue.prevResult = result;\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_cm_custom_value(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_openCM70_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [\r\n                            Lang.Blocks.robotis_cm_sound_detected,\r\n                            'CM_SOUND_DETECTED',\r\n                        ],\r\n                        [\r\n                            Lang.Blocks.robotis_cm_sound_detecting,\r\n                            'CM_SOUND_DETECTING',\r\n                        ],\r\n                        [Lang.Blocks.robotis_cm_user_button, 'CM_USER_BUTTON'],\r\n                    ],\r\n                    value: 'CM_SOUND_DETECTED',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_openCM70_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                SENSOR: 0,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                var scope = script.executor.scope;\r\n\r\n                scope.isStart = true;\r\n                scope.count = 0;\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.READ;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                var data_default_address = 0;\r\n                var data_default_length = 0;\r\n\r\n                var sensor = script.getStringField('SENSOR');\r\n\r\n                var increase = 0;\r\n\r\n                if (sensor == 'CM_SOUND_DETECTED') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .CM_SOUND_DETECTED[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .CM_SOUND_DETECTED[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .CM_SOUND_DETECTED[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .CM_SOUND_DETECTED[1];\r\n                } else if (sensor == 'CM_SOUND_DETECTING') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .CM_SOUND_DETECTING[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .CM_SOUND_DETECTING[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .CM_SOUND_DETECTING[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .CM_SOUND_DETECTING[1];\r\n                } else if (sensor == 'CM_USER_BUTTON') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_USER_BUTTON[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_USER_BUTTON[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_USER_BUTTON[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_USER_BUTTON[1];\r\n                }\r\n\r\n                data_default_address =\r\n                    data_default_address + increase * data_default_length;\r\n\r\n                if (\r\n                    Entry.hw.sendQueue.prevAddress &&\r\n                    Entry.hw.sendQueue.prevAddress == data_default_address\r\n                ) {\r\n                    if (\r\n                        Entry.hw.sendQueue.prevTime &&\r\n                        new Date() - Entry.hw.sendQueue.prevTime < 200\r\n                    ) {\r\n                        //throw new Entry.Utils.AsyncError();\r\n                        return Entry.hw.sendQueue.prevResult;\r\n                    }\r\n                }\r\n\r\n                Entry.Robotis_carCont.setRobotisData([\r\n                    [\r\n                        data_instruction,\r\n                        data_address,\r\n                        data_length,\r\n                        data_value,\r\n                        data_default_length,\r\n                    ],\r\n                ]);\r\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\r\n                Entry.Robotis_carCont.update();\r\n\r\n                var result = Entry.hw.portData[data_default_address];\r\n                Entry.hw.sendQueue.prevAddress = data_default_address;\r\n                Entry.hw.sendQueue.prevTime = new Date();\r\n                Entry.hw.sendQueue.prevResult = result;\r\n\r\n                return result;\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_sensor_value(%1)'] },\r\n        },\r\n        robotis_openCM70_aux_sensor_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['3', 'PORT_3'],\r\n                        ['4', 'PORT_4'],\r\n                        ['5', 'PORT_5'],\r\n                        ['6', 'PORT_6'],\r\n                    ],\r\n                    value: 'PORT_3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [\r\n                            Lang.Blocks.robotis_aux_servo_position,\r\n                            'AUX_SERVO_POSITION',\r\n                        ],\r\n                        [Lang.Blocks.robotis_aux_ir, 'AUX_IR'],\r\n                        [Lang.Blocks.robotis_aux_touch, 'AUX_TOUCH'],\r\n                        [Lang.Blocks.robotis_aux_brightness, 'AUX_BRIGHTNESS'],\r\n                        [\r\n                            Lang.Blocks.robotis_aux_hydro_themo_humidity,\r\n                            'AUX_HYDRO_THEMO_HUMIDITY',\r\n                        ],\r\n                        [\r\n                            Lang.Blocks.robotis_aux_hydro_themo_temper,\r\n                            'AUX_HYDRO_THEMO_TEMPER',\r\n                        ],\r\n                        [\r\n                            Lang.Blocks.robotis_aux_temperature,\r\n                            'AUX_TEMPERATURE',\r\n                        ],\r\n                        [Lang.Blocks.robotis_aux_ultrasonic, 'AUX_ULTRASONIC'],\r\n                        [Lang.Blocks.robotis_aux_magnetic, 'AUX_MAGNETIC'],\r\n                        [\r\n                            Lang.Blocks.robotis_aux_motion_detection,\r\n                            'AUX_MOTION_DETECTION',\r\n                        ],\r\n                        [Lang.Blocks.robotis_aux_color, 'AUX_COLOR'],\r\n                        [Lang.Blocks.robotis_aux_custom, 'AUX_CUSTOM'],\r\n                    ],\r\n                    value: 'AUX_SERVO_POSITION',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'robotis_openCM70_aux_sensor_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                SENSOR: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                var scope = script.executor.scope;\r\n\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.READ;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                var data_default_address = 0;\r\n                var data_default_length = 0;\r\n\r\n                var port = script.getStringField('PORT');\r\n                var sensor = script.getStringField('SENSOR');\r\n\r\n                var increase = 0;\r\n                if (port == 'PORT_3') {\r\n                    increase = 2;\r\n                } else if (port == 'PORT_4') {\r\n                    increase = 3;\r\n                } else if (port == 'PORT_5') {\r\n                    increase = 4;\r\n                } else if (port == 'PORT_6') {\r\n                    increase = 5;\r\n                }\r\n\r\n                if (sensor == 'AUX_SERVO_POSITION') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_SERVO_POSITION[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_SERVO_POSITION[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_SERVO_POSITION[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_SERVO_POSITION[1];\r\n                } else if (sensor == 'AUX_IR') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_IR[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_IR[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_IR[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_IR[1];\r\n                } else if (sensor == 'AUX_TOUCH') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TOUCH[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TOUCH[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TOUCH[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TOUCH[1];\r\n                } else if (sensor == 'AUX_TEMPERATURE') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TEMPERATURE[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TEMPERATURE[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TEMPERATURE[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_TEMPERATURE[1];\r\n                } else if (sensor == 'AUX_BRIGHTNESS') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_BRIGHTNESS[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_BRIGHTNESS[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_BRIGHTNESS[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_BRIGHTNESS[1];\r\n                } else if (sensor == 'AUX_HYDRO_THEMO_HUMIDITY') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_HYDRO_THEMO_HUMIDITY[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_HYDRO_THEMO_HUMIDITY[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_HYDRO_THEMO_HUMIDITY[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_HYDRO_THEMO_HUMIDITY[1];\r\n                } else if (sensor == 'AUX_HYDRO_THEMO_TEMPER') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_HYDRO_THEMO_TEMPER[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_HYDRO_THEMO_TEMPER[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_HYDRO_THEMO_TEMPER[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_HYDRO_THEMO_TEMPER[1];\r\n                } else if (sensor == 'AUX_ULTRASONIC') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_ULTRASONIC[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_ULTRASONIC[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_ULTRASONIC[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_ULTRASONIC[1];\r\n                } else if (sensor == 'AUX_MAGNETIC') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MAGNETIC[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MAGNETIC[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MAGNETIC[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MAGNETIC[1];\r\n                } else if (sensor == 'AUX_MOTION_DETECTION') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_MOTION_DETECTION[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_MOTION_DETECTION[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_MOTION_DETECTION[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE\r\n                            .AUX_MOTION_DETECTION[1];\r\n                } else if (sensor == 'AUX_COLOR') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_COLOR[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_COLOR[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_COLOR[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_COLOR[1];\r\n                } else if (sensor == 'AUX_CUSTOM') {\r\n                    data_default_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[0];\r\n                    data_default_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[1];\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[1];\r\n                }\r\n\r\n                data_default_address =\r\n                    data_default_address + increase * data_default_length;\r\n                data_address = data_default_address;\r\n                // if (increase != 0) {\r\n                // data_length = 6 * data_default_length;\r\n                // }\r\n\r\n                if (\r\n                    Entry.hw.sendQueue.prevAddress &&\r\n                    Entry.hw.sendQueue.prevAddress == data_default_address\r\n                ) {\r\n                    if (\r\n                        Entry.hw.sendQueue.prevTime &&\r\n                        new Date() - Entry.hw.sendQueue.prevTime < 200\r\n                    ) {\r\n                        //throw new Entry.Utils.AsyncError();\r\n                        return Entry.hw.sendQueue.prevResult;\r\n                    }\r\n                }\r\n\r\n                Entry.Robotis_carCont.setRobotisData([\r\n                    [\r\n                        data_instruction,\r\n                        data_address,\r\n                        data_length,\r\n                        data_value,\r\n                        data_default_length,\r\n                    ],\r\n                ]);\r\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\r\n                Entry.Robotis_carCont.update();\r\n\r\n                var result = Entry.hw.portData[data_default_address];\r\n                Entry.hw.sendQueue.prevAddress = data_default_address;\r\n                Entry.hw.sendQueue.prevTime = new Date();\r\n                Entry.hw.sendQueue.prevResult = result;\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_sensor_value(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_openCM70_cm_buzzer_index: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.General.note_a + '(0)', '0'],\r\n                        [Lang.General.note_a + '#(1)', '1'],\r\n                        [Lang.General.note_b + '(2)', '2'],\r\n                        [Lang.General.note_c + '(3)', '3'],\r\n                        [Lang.General.note_c + '#(4)', '4'],\r\n                        [Lang.General.note_d + '(5)', '5'],\r\n                        [Lang.General.note_d + '#(6)', '6'],\r\n                        [Lang.General.note_e + '(7)', '7'],\r\n                        [Lang.General.note_f + '(8)', '8'],\r\n                        [Lang.General.note_f + '#(9)', '9'],\r\n                        [Lang.General.note_g + '(10)', '10'],\r\n                        [Lang.General.note_g + '#(11)', '11'],\r\n                        [Lang.General.note_a + '(12)', '12'],\r\n                        [Lang.General.note_a + '#(13)', '13'],\r\n                        [Lang.General.note_b + '(14)', '14'],\r\n                        [Lang.General.note_c + '(15)', '15'],\r\n                        [Lang.General.note_c + '#(16)', '16'],\r\n                        [Lang.General.note_d + '(17)', '17'],\r\n                        [Lang.General.note_d + '#(18)', '18'],\r\n                        [Lang.General.note_e + '(19)', '19'],\r\n                        [Lang.General.note_f + '(20)', '20'],\r\n                        [Lang.General.note_f + '#(21)', '21'],\r\n                        [Lang.General.note_g + '(22)', '22'],\r\n                        [Lang.General.note_g + '#(23)', '23'],\r\n                        [Lang.General.note_a + '(24)', '24'],\r\n                        [Lang.General.note_a + '#(25)', '25'],\r\n                        [Lang.General.note_b + '(26)', '26'],\r\n                        [Lang.General.note_c + '(27)', '27'],\r\n                        [Lang.General.note_c + '#(28)', '28'],\r\n                        [Lang.General.note_d + '(29)', '29'],\r\n                        [Lang.General.note_d + '#(30)', '30'],\r\n                        [Lang.General.note_e + '(31)', '31'],\r\n                        [Lang.General.note_f + '(32)', '32'],\r\n                        [Lang.General.note_f + '#(33)', '33'],\r\n                        [Lang.General.note_g + '(34)', '34'],\r\n                        [Lang.General.note_g + '#(35)', '35'],\r\n                        [Lang.General.note_a + '(36)', '36'],\r\n                        [Lang.General.note_a + '#(37)', '37'],\r\n                        [Lang.General.note_b + '(38)', '38'],\r\n                        [Lang.General.note_c + '(39)', '39'],\r\n                        [Lang.General.note_c + '#(40)', '40'],\r\n                        [Lang.General.note_d + '(41)', '41'],\r\n                        [Lang.General.note_d + '#(42)', '42'],\r\n                        [Lang.General.note_e + '(43)', '43'],\r\n                        [Lang.General.note_f + '(44)', '44'],\r\n                        [Lang.General.note_f + '#(45)', '45'],\r\n                        [Lang.General.note_g + '(46)', '46'],\r\n                        [Lang.General.note_g + '#(47)', '47'],\r\n                        [Lang.General.note_a + '(48)', '48'],\r\n                        [Lang.General.note_a + '#(49)', '49'],\r\n                        [Lang.General.note_b + '(50)', '50'],\r\n                        [Lang.General.note_c + '(51)', '51'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_cm_buzzer_index',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_BUZZER_INDEX: 0,\r\n                CM_BUZZER_TIME: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var cmBuzzerIndex = script.getField('CM_BUZZER_INDEX', script);\r\n                var cmBuzzerTime = script.getNumberValue(\r\n                    'CM_BUZZER_TIME',\r\n                    script\r\n                );\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address_1 = 0;\r\n                var data_length_1 = 0;\r\n                var data_value_1 = 0;\r\n                var data_address_2 = 0;\r\n                var data_length_2 = 0;\r\n                var data_value_2 = 0;\r\n                var interval = 100;\r\n\r\n                data_address_1 =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[0];\r\n                data_length_1 =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[1];\r\n                // data_value_1 = cmBuzzerTime * 10;\r\n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\r\n                data_value_1 = parseInt(cmBuzzerTime * 10);\r\n                if (data_value_1 > 50) {\r\n                    data_value_1 = 50;\r\n                }\r\n\r\n                data_address_2 =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[0];\r\n                data_length_2 =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[1];\r\n                data_value_2 = cmBuzzerIndex;\r\n\r\n                var data_sendqueue = [\r\n                    [\r\n                        data_instruction,\r\n                        data_address_1,\r\n                        data_length_1,\r\n                        data_value_1,\r\n                    ],\r\n                    [\r\n                        data_instruction,\r\n                        data_address_2,\r\n                        data_length_2,\r\n                        data_value_2,\r\n                    ],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    cmBuzzerTime * 1000 + interval\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_cm_buzzer_index(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_openCM70_cm_buzzer_melody: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['0', '0'],\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                        ['9', '9'],\r\n                        ['10', '10'],\r\n                        ['11', '11'],\r\n                        ['12', '12'],\r\n                        ['13', '13'],\r\n                        ['14', '14'],\r\n                        ['15', '15'],\r\n                        ['16', '16'],\r\n                        ['17', '17'],\r\n                        ['18', '18'],\r\n                        ['19', '19'],\r\n                        ['20', '20'],\r\n                        ['21', '21'],\r\n                        ['22', '22'],\r\n                        ['23', '23'],\r\n                        ['24', '24'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'robotis_openCM70_cm_buzzer_melody',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_BUZZER_MELODY: 0,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var cmBuzzerMelody = script.getField(\r\n                    'CM_BUZZER_MELODY',\r\n                    script\r\n                );\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address_1 = 0;\r\n                var data_length_1 = 0;\r\n                var data_value_1 = 0;\r\n                var data_address_2 = 0;\r\n                var data_length_2 = 0;\r\n                var data_value_2 = 0;\r\n                var interval = 100;\r\n\r\n                data_address_1 =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[0];\r\n                data_length_1 =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[1];\r\n                data_value_1 = 255;\r\n\r\n                data_address_2 =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[0];\r\n                data_length_2 =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[1];\r\n                data_value_2 = cmBuzzerMelody;\r\n\r\n                var data_sendqueue = [\r\n                    [\r\n                        data_instruction,\r\n                        data_address_1,\r\n                        data_length_1,\r\n                        data_value_1,\r\n                    ],\r\n                    [\r\n                        data_instruction,\r\n                        data_address_2,\r\n                        data_length_2,\r\n                        data_value_2,\r\n                    ],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    1000 + interval\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_buzzer_melody(%1)'] },\r\n        },\r\n        robotis_openCM70_cm_sound_detected_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'robotis_openCM70_cm_sound_detected_clear',\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[0];\r\n                data_length =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[1];\r\n                data_value = 0;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_sound_clear()'] },\r\n        },\r\n        robotis_openCM70_cm_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_red_color, 'CM_LED_R'],\r\n                        [Lang.Blocks.robotis_common_green_color, 'CM_LED_G'],\r\n                        [Lang.Blocks.robotis_common_blue_color, 'CM_LED_B'],\r\n                    ],\r\n                    value: 'CM_LED_R',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_on, '1'],\r\n                        [Lang.Blocks.robotis_common_off, '0'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_openCM70_cm_led',\r\n            },\r\n            paramsKeyMap: {\r\n                CM_LED: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var cmLed = script.getField('CM_LED', script);\r\n                var value = script.getField('VALUE', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                if (cmLed == 'CM_LED_R') {\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_R[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_R[1];\r\n                } else if (cmLed == 'CM_LED_G') {\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_G[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_G[1];\r\n                } else if (cmLed == 'CM_LED_B') {\r\n                    data_address =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_B[0];\r\n                    data_length =\r\n                        Entry.Robotis_openCM70.CONTROL_TABLE.CM_LED_B[1];\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_led(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_cm_motion: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_cm_motion',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.CM_MOTION[0];\r\n                data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_MOTION[1];\r\n                data_value = script.getNumberValue('VALUE', script);\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_motion(%1)'] },\r\n        },\r\n        robotis_openCM70_aux_motor_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_port_1, '1'],\r\n                        [Lang.Blocks.robotis_common_port_2, '2'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_clockwhise, 'CW'],\r\n                        [Lang.Blocks.robotis_common_counter_clockwhise, 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['500'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_motor_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                DIRECTION_ANGLE: 1,\r\n                VALUE: 2,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var directionAngle = script.getField('DIRECTION_ANGLE', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\r\n                data_length =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n\r\n                if (directionAngle == 'CW') {\r\n                    value = value + 1024;\r\n                    if (value > 2047) {\r\n                        value = 2047;\r\n                    }\r\n                } else {\r\n                    if (value > 1023) {\r\n                        value = 1023;\r\n                    }\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_motor_speed(%1, %2, %3)'],\r\n            },\r\n        },\r\n        robotis_openCM70_aux_servo_mode: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_port_3, '3'],\r\n                        [Lang.Blocks.robotis_common_port_4, '4'],\r\n                        [Lang.Blocks.robotis_common_port_5, '5'],\r\n                        [Lang.Blocks.robotis_common_port_6, '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_wheel_mode, '0'],\r\n                        [Lang.Blocks.robotis_common_joint_mode, '1'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_openCM70_aux_servo_mode',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                MODE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var mode = script.getField('MODE', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_MODE[0];\r\n                data_length =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_MODE[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n                data_value = mode;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_aux_servo_mode(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_aux_servo_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_port_3, '3'],\r\n                        [Lang.Blocks.robotis_common_port_4, '4'],\r\n                        [Lang.Blocks.robotis_common_port_5, '5'],\r\n                        [Lang.Blocks.robotis_common_port_6, '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_clockwhise, 'CW'],\r\n                        [Lang.Blocks.robotis_common_counter_clockwhise, 'CCW'],\r\n                    ],\r\n                    value: 'CW',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['500'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_servo_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                DIRECTION_ANGLE: 1,\r\n                VALUE: 2,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var directionAngle = script.getField('DIRECTION_ANGLE', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_SPEED[0];\r\n                data_length =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_SPEED[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n\r\n                if (directionAngle == 'CW') {\r\n                    value = value + 1024;\r\n                    if (value > 2047) {\r\n                        value = 2047;\r\n                    }\r\n                } else {\r\n                    if (value > 1023) {\r\n                        value = 1023;\r\n                    }\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_servo_speed(%1, %2, %3)'],\r\n            },\r\n        },\r\n        robotis_openCM70_aux_servo_position: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_port_3, '3'],\r\n                        [Lang.Blocks.robotis_common_port_4, '4'],\r\n                        [Lang.Blocks.robotis_common_port_5, '5'],\r\n                        [Lang.Blocks.robotis_common_port_6, '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['512'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_servo_position',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[0];\r\n                data_length =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_SERVO_POSITION[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n\r\n                if (value > 1023) {\r\n                    value = 1023;\r\n                } else if (value < 0) {\r\n                    value = 0;\r\n                }\r\n\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: ['Robotis.opencm70_aux_servo_position(%1, %2)'],\r\n            },\r\n        },\r\n        robotis_openCM70_aux_led_module: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_port_3, '3'],\r\n                        [Lang.Blocks.robotis_common_port_4, '4'],\r\n                        [Lang.Blocks.robotis_common_port_5, '5'],\r\n                        [Lang.Blocks.robotis_common_port_6, '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [\r\n                            Lang.Blocks.robotis_cm_led_both +\r\n                                Lang.Blocks.robotis_common_off,\r\n                            '0',\r\n                        ],\r\n                        [\r\n                            Lang.Blocks.robotis_cm_led_right +\r\n                                Lang.Blocks.robotis_common_on,\r\n                            '1',\r\n                        ],\r\n                        [\r\n                            Lang.Blocks.robotis_cm_led_left +\r\n                                Lang.Blocks.robotis_common_on,\r\n                            '2',\r\n                        ],\r\n                        [\r\n                            Lang.Blocks.robotis_cm_led_both +\r\n                                Lang.Blocks.robotis_common_on,\r\n                            '3',\r\n                        ],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null, null],\r\n                type: 'robotis_openCM70_aux_led_module',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                LED_MODULE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var ledModule = script.getField('LED_MODULE', script);\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_LED_MODULE[0];\r\n                data_length =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_LED_MODULE[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n                data_value = ledModule;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_aux_led_module(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_aux_custom: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.robotis_common_port_3, '3'],\r\n                        [Lang.Blocks.robotis_common_port_4, '4'],\r\n                        [Lang.Blocks.robotis_common_port_5, '5'],\r\n                        [Lang.Blocks.robotis_common_port_6, '6'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_aux_custom',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_openCM70_cm',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var port = script.getField('PORT', script);\r\n                var value = script.getNumberValue('VALUE');\r\n\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[0];\r\n                data_length =\r\n                    Entry.Robotis_openCM70.CONTROL_TABLE.AUX_CUSTOM[1];\r\n\r\n                data_address = data_address + (port - 1) * data_length;\r\n                data_value = value;\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_aux_custom(%1, %2)'] },\r\n        },\r\n        robotis_openCM70_cm_custom: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'robotis_openCM70_cm_custom',\r\n            },\r\n            paramsKeyMap: {\r\n                ADDRESS: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'robotis_openCM70_custom',\r\n            isNotFor: ['Robotis_openCM70EDU'],\r\n            func: function (sprite, script) {\r\n                // instruction / address / length / value / default length\r\n                var data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\r\n                var data_address = 0;\r\n                var data_length = 0;\r\n                var data_value = 0;\r\n\r\n                data_address = script.getNumberValue('ADDRESS');\r\n                data_value = script.getNumberValue('VALUE');\r\n                if (data_value > 65535) {\r\n                    data_length = 4;\r\n                } else if (data_value > 255) {\r\n                    data_length = 2;\r\n                } else {\r\n                    data_length = 1;\r\n                }\r\n\r\n                var data_sendqueue = [\r\n                    [data_instruction, data_address, data_length, data_value],\r\n                ];\r\n                return Entry.Robotis_carCont.postCallReturn(\r\n                    script,\r\n                    data_sendqueue,\r\n                    Entry.Robotis_openCM70.delay\r\n                );\r\n            },\r\n            syntax: { js: [], py: ['Robotis.opencm70_cm_custom(%1, %2)'] },\r\n        },\r\n        //endregion robotis 로보티즈\r\n    };\r\n};*/\r\n\r\nmodule.exports = [Entry.Robotis_carCont, Entry.Robotis_openCM70, Entry.Robotis_openCM70EDU];\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotisDream.js",
    "content": "'use strict';\n\nEntry.Robotis_DREAM2 = {\n    hasPracticalCourse: false,\n    MODULE_VALUE:{\n        DEFAULT: 0,\n        PASSIVE: 1,\n        IR: 2,\n        LED: 3,\n        COLOR: 4,\n        MOISTURE: 5,\n        IRARRAY: 6,\n        SERVO: 7,\n    },\n    INSTRUCTION: {\n        NONE: 0,\n        WRITE: 3,\n        READ: 2,\n    },\n    CONTROL_TABLE: {\n        // [default address, default length, address (when reads together), length (when reads together)]\n        CM_LED: [212, 1, 213, 1],\n        CM_SPRING_RIGHT: [69, 1, 69, 2],\n        CM_SPRING_LEFT: [70, 1, 69, 2],\n        CM_SWITCH: [71, 1],\n        CM_SOUND_DETECTED: [86, 1],\n        CM_SOUND_DETECTING: [87, 1],\n        CM_IR_LEFT: [91, 2],\n        CM_IR_RIGHT: [93, 2],\n        CM_IR_CENTER: [95, 2],\n        CM_IR_SENSOR: [172, 2, 174, 2],\n        CM_TOUCH_SENSOR: [204, 1, 205, 1],\n        CM_TEMPERATURE_SENSOR: [236, 1, 237, 1],\n        CM_ULTRASONIC_SENSOR: [244, 1, 245, 1],\n        CM_MAGNETIC_SENSOR: [252, 1, 253, 1],\n        CM_MOTION_SENSOR: [260, 1, 261, 1],\n        CM_COLOR_SENSOR: [268, 1, 269, 1],\n        CM_HUMIDITY_SENSOR: [276, 1, 277, 1],\n        CM_HTEMPERATURE_SENSOR: [284, 1, 285, 1],\n        CM_BRIGHTNESS_SENSOR: [292, 2, 294, 2],\n        CM_MODULE_CLASS: [104, 105],\n\n        AUX_SERVO_MODE: [128, 1, 129, 1],\n        AUX_SERVO_SPEED: [136, 2, 138, 2],\n        AUX_SERVO_POSITION: [156, 2, 158, 2],\n        AUX_MOTOR_SPEED: [152, 2, 154, 2],\n    },\n    IRS_MODULEWRITE: {\n        PORT3: false,\n        PORT4: false,\n    },\n    SERVO_MODULEWRITE: {\n        PORT3: false,\n        PORT4: false,\n    },\n    SERVO_WHEELWRITE: {\n        PORT3: false,\n        PORT4: false,\n    },\n    SERVO_POSITIONWRITE: {\n        PORT3: false,\n        PORT4: false,\n    },\n    COLOR_MODULEWRITE: {\n        PORT3: false,\n        PORT4: false,\n    },\n    TEMPER_MOISTURE_MODULEWRITE: {\n        PORT3: false,\n        PORT4: false,\n    },\n    setZero: function () {\n        // instruction / address / length / value / default length\n        Entry.hw.sendQueue['setZero'] = [1];\n        this.update();\n        this.setRobotisData(null);\n        Entry.hw.sendQueue['setZero'] = null;\n        this.update();\n        this.setRobotisData([\n            [Entry.Robotis_DREAM2.INSTRUCTION.WRITE, 86, 1, 0],\n            [Entry.Robotis_DREAM2.INSTRUCTION.WRITE, 136, 4, 0],\n            [Entry.Robotis_DREAM2.INSTRUCTION.WRITE, 152, 4, 0],\n            [Entry.Robotis_DREAM2.INSTRUCTION.WRITE, Entry.Robotis_DREAM2.CONTROL_TABLE.CM_MODULE_CLASS[0], 2, 0],\n            //[Entry.Robotis_DREAM2.INSTRUCTION.WRITE, 154, 2, 0],\n        ]);\n\n        this.update();\n\n\n        Entry.Robotis_DREAM2.IRS_MODULEWRITE.PORT3 = false;\n        Entry.Robotis_DREAM2.IRS_MODULEWRITE.PORT4 = false;\n\n        Entry.Robotis_DREAM2.SERVO_MODULEWRITE.PORT3 = false;\n        Entry.Robotis_DREAM2.SERVO_MODULEWRITE.PORT4 = false;\n\n        Entry.Robotis_DREAM2.SERVO_WHEELWRITE.PORT3 = false;\n        Entry.Robotis_DREAM2.SERVO_WHEELWRITE.PORT4 = false;\n\n        Entry.Robotis_DREAM2.SERVO_POSITIONWRITE.PORT3 = false;\n        Entry.Robotis_DREAM2.SERVO_POSITIONWRITE.PORT4 = false;\n\n        Entry.Robotis_DREAM2.COLOR_MODULEWRITE.PORT3 = false;\n        Entry.Robotis_DREAM2.COLOR_MODULEWRITE.PORT4 = false;\n\n        Entry.Robotis_DREAM2.TEMPER_MOISTURE_MODULEWRITE.PORT3 = false;\n        Entry.Robotis_DREAM2.TEMPER_MOISTURE_MODULEWRITE.PORT4 = false;\n\n    },\n    id: '7.4',\n    name: 'Robotis_DREAM2',\n    url: 'http://www.robotis.com/index/product.php?cate_code=111310',\n    imageName: 'robotis_carCont.png',\n    title: {\n        \"ko\": \"로보티즈 드림\",\n        \"en\": \"Robotis Robot car\"\n    },\n    delay: 15,\n    postCallReturn: function (script, data, ms) {\n        if (ms <= 0) {\n            this.setRobotisData(data);\n            this.update();\n            return script.callReturn();\n        }\n\n        if (!script.isStart) {\n            script.isStart = true;\n            script.timeFlag = 1;\n            //data setting\n            this.setRobotisData(data);\n            this.update();\n\n            //delay xx ms\n            setTimeout(function () {\n                script.timeFlag = 0;\n            }, ms);\n\n            return script;\n        } else if (script.timeFlag == 1) {\n            this.setRobotisData(null);\n            this.update();\n            return script;\n        } else {\n            delete script.timeFlag;\n            delete script.isStart;\n            Entry.engine.isContinue = false;\n            this.update();\n            return script.callReturn();\n        }\n    },\n    wait: function (sq, ms) {\n        Entry.hw.socket.send(JSON.stringify(sq));\n\n        var start = new Date().getTime();\n        var end = start;\n        while (end < start + ms) {\n            //wait XX ms\n            end = new Date().getTime();\n        }\n    },\n\n    update: function () {\n        Entry.hw.update();\n        var ROBOTIS_DATA = Entry.hw.sendQueue['ROBOTIS_DATA'];\n        if (ROBOTIS_DATA) {\n            ROBOTIS_DATA.forEach(function (data) {\n                data['send'] = true;\n            });\n        }\n        this.setRobotisData(null);\n    },\n    filterSendData: function () {\n        var ROBOTIS_DATA = Entry.hw.sendQueue['ROBOTIS_DATA'];\n        if (ROBOTIS_DATA) {\n            return ROBOTIS_DATA.filter(function (data) {\n                return data.send !== true;\n            });\n        } else {\n            return null;\n        }\n    },\n    setRobotisData: function (data) {\n        var filterData = this.filterSendData();\n        if (data == null) {\n            Entry.hw.sendQueue['ROBOTIS_DATA'] = filterData;\n        } else {\n            Entry.hw.sendQueue['ROBOTIS_DATA'] = filterData\n                ? filterData.concat(data)\n                : data;\n        }\n    },\n};\n\nEntry.Robotis_DREAM2.blockMenuBlocks = [\n    'robotis_dream_drive',\n    'robotis_dream_stop',\n    'robotis_gm_control',\n\n    'robotis_sm_setting',\n    'robotis_sm_joint_move',\n    'robotis_sm_wheel_move',\n\n    'robotis_internal_led_control',\n    'robotis_led_module_control',\n\n    'robotis_internal_ir_compare',\n    'robotis_port_ir_compare',\n    'robotis_port_touch_compare',\n    'robotis_sound_count_compare',\n\n    'robotis_detected_sound_initialize',\n    'robotis_play_piano',\n    'robotis_play_melody',\n    'robotis_play_melody_wait',\n\n    'robotis_internal_ir_value',\n    'robotis_port_ir_value',\n    'robotis_sound_count',\n    'robotis_sm_position',\n    'robotis_user_device'\n\n];\n\nEntry.Robotis_DREAM2.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                robotis_dream_drive: \"로봇 %1 속도로 %2하기 %3\",\n                robotis_dream_stop: \"로봇 정지하기%1\",\n                robotis_gm_control: \"%1 번 감속모터 %2 속도, %3 으로 %4 하기 %5\",\n\n                robotis_sm_setting: \"%1번 서보모터 %2모드로 설정하기 %3\",\n                robotis_sm_joint_move: \"%1번 서보모터 %2 속도, %3도 위치로 이동하기(관절모드) %4\",\n                robotis_sm_wheel_move: \"%1번 서보모터 %2 속도, %3으로 %4하기(바퀴모드) %5\",\n                \n                robotis_internal_led_control: \"제어기 내장 초록 LED %1 %2\",\n                robotis_led_module_control: \"%1번 LED 모듈 %2 %3\",\n\n                robotis_internal_ir_compare: \"%1 적외선 센서 값 %2 %3 이면\",\n                robotis_port_ir_compare: \"%1번 적외선 센서 %2 %3 이면\",\n                robotis_port_touch_compare: \"%1번 접촉 센서가 %2 이면\",\n                robotis_sound_count_compare: \"%1 소리 감지 횟수 %2 %3 이면\",\n\n                robotis_detected_sound_initialize: \"최종 소리 감지 횟수 초기화%1\",\n                robotis_play_piano: \"%1 옥타브 %2 음계를 %3초 동안 연주하기 %4\",\n                robotis_play_melody: \"%1 번 멜로디 연주하기 %2\",\n                robotis_play_melody_wait: \"%1 번 멜로디 연주하고 기다리기 %2\",\n\n                robotis_internal_ir_value: \"%1 내장 적외선 센서 값\",\n                robotis_port_ir_value: \"%1 번 %2 값\",\n                robotis_sound_count: \"%1 소리 횟수\",\n                robotis_sm_position: \"%1 번 서보모터 위치\",\n                robotis_user_device: \"%1번 사용자 장치\" \n            },\n            Helper: {\n\n            },\n            Blocks: {\n                robotis_moveF: \"전진\",\n                robotis_moveB: \"후진\",\n                robotis_moveL: \"좌회전\",\n                robotis_moveR: \"우회전\",\n\n                robotis_direction_cw: \"시계방향\",\n                robotis_direction_ccw: \"반시계방향\",\n\n                robotis_rotate: \"회전\",\n                robotis_stop: \"정지\",\n\n                robotis_joint: \"관절\",\n                robotis_wheel: \"바퀴\",\n\n                robotis_on: \"켜기\",\n                robotis_off: \"끄기\",\n\n                robotis_ir: \"적외선 센서\",\n                robotis_touch: \"터치 센서\",\n\n                robotis_final: \"최종\",\n                robotis_sync: \"실시간\",\n\n                robotis_left: \"왼쪽\",\n                robotis_center: \"중앙\",\n                robotis_right: \"오른쪽\",\n\n                robotis_touched: \"눌림\",\n                robotis_no_touched: \"안눌림\",\n\n                robotis_on_on: \"주황 켜기, 파랑 켜기\",\n                robotis_on_off: \"주황 켜기, 파랑 끄기\",\n                robotis_off_on: \"주황 끄기, 파랑 켜기\",\n                robotis_off_off: \"주황 끄기, 파랑 끄기\"\n            },\n        },\n        en: {\n            template: {\n                robotis_dream_drive: \"Robot with %1 speed %2 %3\",\n                robotis_dream_stop: \"Robot stop\",\n                robotis_gm_control: \"%1 GM Motor with %2 speed, %3 direction %4 %5\",\n\n                robotis_sm_setting: \"%1 Servo Motor setting with %2 %3\",\n                robotis_sm_joint_move: \"%1 Servo Motor %2 Speed %3 angle(joint mode) %4\",\n                robotis_sm_wheel_move: \"%1 Servo Motor %2 Speed %3 direction %4 %5\",\n\n                robotis_internal_led_control: \"Internal green LED %1 %2\",\n                robotis_led_module_control: \"%1 port LED module %2 %3\",\n\n                robotis_internal_ir_compare: \"%1 IR sensor value is %2 %3 \",\n                robotis_port_ir_compare: \"%1 port IR sensor value is %2 %3 \",\n                robotis_port_touch_compare: \"%1 port touch sensor value is %2 \",\n                robotis_sound_count_compare: \"%1 detected sound count %2 %3 \",\n\n                robotis_detected_sound_initialize: \"Initialize detected sound %1\",\n                robotis_play_piano: \"%1 octave %2 sound during %3 play %4\",\n                robotis_play_melody: \"%1 melody play %2\",\n                robotis_play_melody_wait: \"%1 melody play and wait %2\",\n\n                robotis_internal_ir_value: \"%1 internal ir value\",\n                robotis_port_ir_value: \"%1 port %2 value \",\n                robotis_sound_count: \"%1 sound count \",\n                robotis_sm_position: \"%1 port servo motor position \",\n                robotis_user_device: \"%1 port user device \" \n            },\n            Helper: {\n\n            },\n            Blocks: {\n                robotis_moveF: \"Forward\",\n                robotis_moveB: \"Backward\",\n                robotis_moveL: \"LeftTurn\",\n                robotis_moveR: \"RightTurn\",\n\n                robotis_direction_cw: \"clockwise\",\n                robotis_direction_ccw: \"counterclockwise\",\n\n                robotis_rotate: \"rotate\",\n                robotis_stop: \"stop\",\n\n                robotis_joint: \"joint\",\n                robotis_wheel: \"wheel\",\n                \n                robotis_on: \"on\",\n                robotis_off: \"off\",\n                \n                robotis_ir: \"IR sensor\",\n                robotis_touch: \"Touch sensor\",\n\n                robotis_final: \"final\",\n                robotis_sync: \"sync\",\n\n                robotis_left: \"left\",\n                robotis_center: \"center\",\n                robotis_right: \"right\",\n\n                robotis_touched: \"touched\",\n                robotis_no_touched: \"no touched\",\n\n                robotis_on_on: \"Orange LED on, Blue LED on\",\n                robotis_on_off: \"Orange LED on, Blue LED off\",\n                robotis_off_on: \"Orange LED off, Blue LED on\",\n                robotis_off_off: \"Orange LED off, Blue LED off\"\n            }\n        },\n    };\n};\n\nEntry.Robotis_DREAM2.getBlocks = function() {\n    return {\n        robotis_dream_drive: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '0'],\n                        [Lang.Blocks.robotis_moveB, '1'],\n                        [Lang.Blocks.robotis_moveL, '2'],\n                        [Lang.Blocks.robotis_moveR, '3']\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '50',\n                    null,\n                    null\n                ],\n                type: 'robotis_dream_drive',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n                var data_address1 = 0;\n                var data_address2 = 0;\n\n                var data_length1 = 0;\n                var data_length2 = 0;\n\n                var direction = 0;\n\n                var data_value = 0;\n\n                data_address1 = Entry.Robotis_DREAM2.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\n                data_address2 = Entry.Robotis_DREAM2.CONTROL_TABLE.AUX_MOTOR_SPEED[2];\n\n                data_length1 = Entry.Robotis_DREAM2.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\n                data_length2 = Entry.Robotis_DREAM2.CONTROL_TABLE.AUX_MOTOR_SPEED[3];\n\n                direction = script.getNumberValue('DIRECTION', script);\n                data_value = script.getNumberValue('SPEED', script) * 10;\n\n                var data_sendqueue = [];\n                switch(direction) {\n                    case 0:\n                    case '0':\n                        //console.log(direction, data_value);\n                        data_sendqueue = [\n                            [data_instruction, data_address1, data_length1, data_value],\n                            [data_instruction, data_address2, data_length2, data_value + 1024],\n                        ];\n                        break;\n                    case 1:\n                        data_sendqueue = [\n                            [data_instruction, data_address1, data_length1, data_value + 1024],\n                            [data_instruction, data_address2, data_length2, data_value],\n                        ];\n                        break;\n                    case 2:\n                        data_sendqueue = [\n                            [data_instruction, data_address1, data_length1, data_value + 1024],\n                            [data_instruction, data_address2, data_length2, data_value + 1024],\n                        ];\n                        break;\n                    case 3:\n                        data_sendqueue = [\n                            [data_instruction, data_address1, data_length1, data_value],\n                            [data_instruction, data_address2, data_length2, data_value],\n                        ];\n                        break;\n                }\n\n                //console.log(data_sendqueue)\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        robotis_dream_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                type:'robotis_dream_stop',\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n                var data_address1 = Entry.Robotis_DREAM2.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\n                var data_length = 4;\n                var data_value = 0;\n\n                var data_sendqueue = [[data_instruction, data_address1, data_length, data_value]];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            }\n        },\n\n        //%1 번 감속모터 %2 속도, %3 으로 %4 하기 %5\n        robotis_gm_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_direction_cw, '0'],\n                        [Lang.Blocks.robotis_direction_ccw, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_rotate, '0'],\n                        [Lang.Blocks.robotis_stop, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '50',\n                    null,\n                    null,\n                    null\n                ],\n                type: 'robotis_gm_control',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                SPEED: 1,\n                DIRECTION: 2,\n                OP: 3\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n\n                var port = script.getNumberValue('PORT', script);\n                var speed = script.getNumberValue('SPEED', script) * 10;\n                var direction = script.getNumberValue('DIRECTION', script);\n                var op = script.getNumberValue('OP', script);\n\n                var data_address = 152; //포트 1번 감속 모터 주소 \n                var data_length = 2;\n                var data_value = speed;\n\n                switch(port) {\n                    case 1:\n                        data_address = 152;\n                        break;\n                    case 2:\n                        data_address = 154;\n                        break;\n                }\n                \n                if(direction == 0) {\n                    data_value += 1024;\n                }\n                \n                if(op == 1) {\n                    data_value = 0;\n                }\n\n            \n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        //%1번 서보모터 %2모드로 설정하기 %3\n        robotis_sm_setting: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['4', '4']\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_joint, '1'],\n                        [Lang.Blocks.robotis_wheel, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null\n                ],\n                type: 'robotis_sm_setting',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                MODE: 1,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n\n                var port = script.getNumberValue('PORT', script);\n                var mode = script.getNumberValue('MODE', script);\n\n                var data_address = 128;\n                var data_length = 1;\n                var data_value = mode;\n\n                switch(port) {\n                    case 3:\n                        data_address = 128;\n                        break;\n                    case 4:\n                        data_address = 129;\n                        break;\n                }\n\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        //%1번 서보모터 %2 속도 %3도 위치로 이동하기(관절모드) %4\n        robotis_sm_joint_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['4', '4']\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '50',\n                    '0',\n                    null,\n                ],\n                type: 'robotis_sm_joint_move',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                SPEED: 1,\n                ANGLE: 2,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n\n                var port = script.getNumberValue('PORT', script);\n                var speed = script.getNumberValue('SPEED', script);\n                var angle = script.getNumberValue('ANGLE', script);\n\n                var data_address1 = 136;\n                var data_address2 = 156;\n\n                var data_length = 2;\n\n                if(angle < -150) {\n                    angle = -150;\n                }\n                if(angle > 150) {\n                    angle = 150;\n                }\n\n                var data_value1 = speed * 10;\n                var data_value2 = angle * (-1024);\n                data_value2 = Math.floor(data_value2 / 300);\n                data_value2 += 512;\n\n                if(port == 3) {\n                    data_address1 = 136;\n                    data_address2 = 156;\n                } else {\n                    data_address1 = 138;\n                    data_address2 = 158;\n                }\n\n\n                var data_sendqueue = [\n                    [data_instruction, data_address1, data_length, data_value1],\n                    [data_instruction, data_address2, data_length, data_value2]\n                ];\n                \n                //console.log(data_sendqueue);\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        //%1번 서보모터 %2 속도, %3으로 %4하기(바퀴모드) %5\n        robotis_sm_wheel_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['4', '4']\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_direction_cw, '0'],\n                        [Lang.Blocks.robotis_direction_ccw, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_rotate, '0'],\n                        [Lang.Blocks.robotis_stop, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '50',\n                    null,\n                    null,\n                    null\n                ],\n                type: 'robotis_sm_wheel_move',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                SPEED: 1,\n                DIRECTION: 2,\n                OP: 3\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n\n                var port = script.getNumberValue('PORT', script);\n                var speed = script.getNumberValue('SPEED', script);\n                var direction = script.getNumberValue('DIRECTION', script);\n                var op = script.getNumberValue('OP', script);\n\n                var data_address = 136;\n                var data_length = 2;\n                var data_value = speed * 10;\n\n                if(port == 3) {\n                    data_address = 136;\n                } else {\n                    data_address = 138;\n                }\n                \n                if(direction == 0) {\n                    data_value += 1024;\n                }\n\n                if(op == 1) {\n                    data_value = 0; \n                }\n\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                \n                //console.log(data_sendqueue);\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] }, \n        },\n\n        // 제어기 내장 초록 LED %1 %2\n        robotis_internal_led_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_on, '1'],\n                        [Lang.Blocks.robotis_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_internal_led_control',\n            },\n            paramsKeyMap: {\n                OP: 0\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n\n                var on_off = script.getNumberValue('OP', script);\n\n                var data_address = 79;\n                var data_length = 1;\n                var data_value = on_off;\n\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        // \n        robotis_led_module_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['4', '4']\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_on_on, '3'],\n                        [Lang.Blocks.robotis_on_off, '1'],\n                        [Lang.Blocks.robotis_off_on, '2'],\n                        [Lang.Blocks.robotis_off_off, '0'],\n\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_led_module_control',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OP: 1,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n\n                var port = script.getNumberValue('PORT', script);\n                var op = script.getNumberValue('OP', script);\n\n                var data_address = 212; \n                var data_length = 1;\n                var data_value = op;\n\n                if(port == 3) {\n                    data_address = 212;\n                } else {\n                    data_address = 213;\n                }\n\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        //최종 소리 감지 횟수 초기화%1\n        robotis_detected_sound_initialize: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator', \n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_detected_sound_initialize',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n                var data_address = 86;\n                var data_length = 1;\n                var data_value = 0;\n\n                var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        //%1 옥타브 %2 음계를 %3초 동안 연주하기 %4\n        robotis_play_piano: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.General.note_c + '', '3'],\n                        [Lang.General.note_c + '#', '4'],\n                        [Lang.General.note_d + '', '5'],\n                        [Lang.General.note_d + '#', '6'],\n                        [Lang.General.note_e + '', '7'],\n                        [Lang.General.note_f + '', '8'],\n                        [Lang.General.note_f + '#', '9'],\n                        [Lang.General.note_g + '', '10'],\n                        [Lang.General.note_g + '#', '11'],\n                        [Lang.General.note_a + '', '12'],\n                        [Lang.General.note_a + '#', '13'],\n                        [Lang.General.note_b + '', '14'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    '0.2',\n                    null\n                ],\n                type: 'robotis_play_piano',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                KEY: 1,\n                TIME: 2,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n                var data_address1 = 84; //부저 인덱스\n                var data_address2 = 85; //시간 \n\n                var interval = 100;\n\n                var data_length = 1;\n\n                var octave = script.getNumberValue('OCTAVE', script);\n                var key = script.getNumberValue('KEY', script);\n                var time = script.getNumberValue('TIME', script);\n\n                var data_value2 = parseInt(time * 10);\n                \n                if(data_value2 > 50) {\n                    data_value2 = 50;\n                }\n\n                var data_value1 = Number(key) + Number(octave * 12);\n\n                var data_sendqueue = [\n                    [data_instruction, data_address2, data_length, data_value2],\n                    [data_instruction, data_address1, data_length, data_value1]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    time * 1000 + interval \n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        // %1 번 멜로디 연주하기 %2\n        robotis_play_melody: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                        ['9', '8'],\n                        ['10', '9'],\n\n                        ['11', '10'],\n                        ['12', '11'],\n                        ['13', '12'],\n                        ['14', '13'],\n                        ['15', '14'],\n                        ['16', '15'],\n                        ['17', '16'],\n                        ['18', '17'],\n                        ['19', '18'],\n                        ['20', '19'],\n\n                        ['21', '20'],\n                        ['22', '21'],\n                        ['23', '22'],\n                        ['24', '23'],\n                        ['25', '24'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    \n                ],\n                type: 'robotis_play_melody',\n            },\n            paramsKeyMap: {\n                MELODY: 0\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n\n                var melody = script.getNumberValue('MELODY', script);\n\n                var data_address = 84;\n                var data_length = 1;\n                var data_value = melody;\n\n                var data_sendqueue = [\n                    [data_instruction, 85, 1, 255],\n                    [data_instruction, data_address, data_length, data_value]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_carCont.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        // %1 번 멜로디 연주하고 기다리기 %2\n        robotis_play_melody_wait: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                        ['7', '6'],\n                        ['8', '7'],\n                        ['9', '8'],\n                        ['10', '9'],\n\n                        ['11', '10'],\n                        ['12', '11'],\n                        ['13', '12'],\n                        ['14', '13'],\n                        ['15', '14'],\n                        ['16', '15'],\n                        ['17', '16'],\n                        ['18', '17'],\n                        ['19', '18'],\n                        ['20', '19'],\n\n                        ['21', '20'],\n                        ['22', '21'],\n                        ['23', '22'],\n                        ['24', '23'],\n                        ['25', '24'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_play_melody_wait',\n            },\n            paramsKeyMap: {\n                MELODY: 0\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_DREAM2.INSTRUCTION.WRITE;\n\n                var melody = script.getNumberValue('MELODY', script);\n\n                var data_address = 84;\n                var data_length = 1;\n                var data_value = melody;\n\n                var data_sendqueue = [\n                    [data_instruction, 85, 1, 255],\n                    [data_instruction, data_address, data_length, data_value]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    3000\n                );\n            },\n            syntax: { js: [], py: ['Robotis.carcont_cm_sound_clear()'] },\n        },\n\n        robotis_internal_ir_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '2'],\n                        [Lang.Blocks.robotis_center, '4'],\n                        [Lang.Blocks.robotis_right, '0'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    \n                ],\n                type: 'robotis_internal_ir_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_openCM70_custom',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 91;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                \n                var port = script.getNumberValue('PORT', script);\n\n                data_address += port;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        var innerValue = Entry.hw.sendQueue.prevResult;\n                        \n                        if(innerValue > 400) {\n                            innerValue = 400;\n                        }\n\n                        return innerValue;\n                        \n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                \n                \n                if(result > 400) {\n                    result = 400;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_ir_compare(%1)'],\n            },\n        },\n\n        //%1 번 %2 값 %3\n        robotis_port_ir_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '3'],\n                        ['4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ir, '0'],\n                        [Lang.Blocks.robotis_touch, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                \n               \n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    \n                ],\n                type: 'robotis_port_ir_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                SENSOR: 1\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var port = script.getNumberValue('PORT', script);\n                var sensor = script.getNumberValue('SENSOR', script);\n\n                if(port == 3) {\n                    if(sensor == 0) {\n                        data_address = 172;\n                        data_length = 2;\n                    } else {\n                        data_address = 204;\n                        data_length = 1;\n                    }\n                } else {\n                    if(sensor == 0) {\n                        data_address = 174;\n                        data_length = 2;\n                    } else {\n                        data_address = 205;\n                        data_length = 1;\n                    }\n                }\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        \n                        var innerValue = Entry.hw.sendQueue.prevResult;\n                        innerValue *= 4;\n                        innerValue = Math.floor(innerValue / 10);\n\n                        if(innerValue > 400) {\n                            innerValue = 400;\n                        }\n\n\n                        return innerValue;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n                    //console.log('result is undefined')\n                    return 0;\n                }\n                result *= 4;\n                result = Math.floor(result / 10);\n\n                if(result > 400) {\n                    result = 400;\n                }\n                return result;\n            }\n        },\n\n        //%1 sound count %2\n        robotis_sound_count: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_final, '0'], //최종\n                        [Lang.Blocks.robotis_sync, '1'],  //실시간 \n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                \n             \n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    \n                ],\n                type: 'robotis_sound_count',\n            },\n            paramsKeyMap: {\n                METHOD: 0\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 1;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var method = script.getNumberValue('METHOD', script);\n\n                if(method == 0) {\n                    data_address = 86;\n                } else {\n                    data_address = 87;\n                }\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        \n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n                    //console.log('result is undefined')\n                    return 0;\n                }\n                \n                return result;\n            }\n        },\n\n        //%1 번 서보모터 위치 %2\n        robotis_sm_position: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '0'], \n                        ['4', '2'],   \n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                \n               \n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    \n                ],\n                type: 'robotis_sm_position',\n            },\n            paramsKeyMap: {\n                PORT: 0\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 156;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var port = script.getNumberValue('PORT', script);\n\n                data_address += port;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        \n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n                    //console.log('result is undefined')\n                    return 0;\n                }\n                \n                result -= 512;\n                result *= 300;\n                result = Math.floor(result / -1024);\n\n                return result;\n            }\n        },\n        \n        robotis_user_device: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '0'], \n                        ['4', '2'],   \n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                \n              \n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    \n                ],\n                type: 'robotis_user_device',\n            },\n            paramsKeyMap: {\n                PORT: 0\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function(sprite, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 220;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var port = script.getNumberValue('PORT', script);\n\n                data_address += port;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        \n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n                    //console.log('result is undefined')\n                    return 0;\n                }\n            \n\n                return result;\n            }\n        },\n\n        //%1 적외선 센서 값 %2 %3 이면 %4\n        robotis_internal_ir_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '2'],\n                        [Lang.Blocks.robotis_center, '4'],\n                        [Lang.Blocks.robotis_right, '0'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['>', '0'],\n                        ['<', '1'],\n                        ['=', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    200,\n                    \n                ],\n                type: 'robotis_internal_ir_compare',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COMPARE_OP: 1,\n                COMPARE_VAL: 2,\n            },\n            class: 'robotis_openCM70_custom',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 91;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                \n                var port = script.getNumberValue('PORT', script);\n                var compareOP = script.getNumberValue('COMPARE_OP', script);\n                var compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                data_address += port;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        var innerValue = Entry.hw.sendQueue.prevResult;\n                        \n                        if(innerValue > 400) {\n                            innerValue = 400;\n                        }\n\n                        switch(compareOP) {\n                            case 0:\n                                return innerValue > compareValue;\n                            case 1:\n                                return innerValue < compareValue;\n                            case 2:\n                                return innerValue == compareValue;\n                        }\n\n                        \n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                \n                \n                if(result > 400) {\n                    result = 400;\n                }\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_ir_compare(%1)'],\n            },\n        },\n\n        robotis_port_ir_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '0'],\n                        ['4', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['>', '0'],\n                        ['<', '1'],\n                        ['=', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n               \n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    200,\n                    \n                ],\n                type: 'robotis_port_ir_compare',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COMPARE_OP: 1,\n                COMPARE_VAL: 2,\n            },\n            class: 'robotis_openCM70_custom',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 172;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var port = script.getNumberValue('PORT', script);\n                data_address += port;\n\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        var innerValue = Entry.hw.sendQueue.prevResult;\n                        innerValue *= 4;\n                        innerValue = Math.floor(innerValue / 10);\n\n                        if(innerValue > 400) {\n                            innerValue = 400;\n                        }\n\n                        switch(compareOP) {\n                            case 0:\n                                return innerValue > compareValue;\n                            case 1:\n                                return innerValue < compareValue;\n                            case 2:\n                                return innerValue == compareValue;\n                        }\n\n                        \n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                result *= 4;\n                result = Math.floor(result / 10);\n\n                if(result > 400) {\n                    result = 400;\n                }\n                //console.log(result)\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_ir_compare(%1)'],\n            },\n        },\n\n        robotis_port_touch_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '0'],\n                        ['4', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_touched, '1'],\n                        [Lang.Blocks.robotis_no_touched, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                \n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    \n                ],\n                type: 'robotis_port_touch_compare',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                TOUCHED: 1,\n            },\n            class: 'robotis_openCM70_custom',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 204;\n                var data_length = 1;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var port = script.getNumberValue('PORT');\n                var touched = script.getNumberValue('TOUCHED');\n               \n\n                data_address += port;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        return Entry.hw.sendQueue.prevResult == touched;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                return result == touched;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_ir_compare(%1)'],\n            },\n        },\n\n        robotis_sound_count_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_final, '0'],\n                        [Lang.Blocks.robotis_sync, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['>', '0'],\n                        ['<', '1'],\n                        ['=', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n               \n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    '0',\n                    \n                ],\n                type: 'robotis_sound_count_compare',\n            },\n            paramsKeyMap: {\n                METHOD: 0,\n                COMPARE_OP: 1,\n                COMPARE_VAL: 2,\n            },\n            class: 'robotis_openCM70_custom',\n            isNotFor: ['Robotis_DREAM2'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 86;\n                var data_length =1;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var method = script.getNumberValue('METHOD');\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n\n                data_address += method;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        switch(compareOP) {\n                            case 0:\n                                return Entry.hw.sendQueue.prevResult > compareValue;\n                            case 1:\n                                return Entry.hw.sendQueue.prevResult < compareValue;\n                            case 2:\n                                return Entry.hw.sendQueue.prevResult == compareValue;\n                        }\n\n                        \n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_ir_compare(%1)'],\n            },\n        }\n    };\n}\n\nEntry.Robotis_DREAM2.practicalBlockMenuBlocks = {\n    hw_motor: [\n        'robotis_move_for_secs_dream',\n        'robotis_aux_move_for_dream',\n        'robotis_aux_stop_for_dream',\n        //'robotis_set_servo_wheel_dream',\n        //'robotis_set_servo_joint_dream',\n        'robotis_set_servo_mode_dream',\n        'robotis_set_servo_speed_dream',\n        'robotis_set_servo_position_dream',\n        'robotis_servo_stop_for_dream',\n    ],\n    hw_melody: [\n        'robotis_melody_note_for',\n    ],\n    hw_sensor: [\n        'robotis_detectedsound_value',\n        'robotis_detectedsound_value_boolean',\n        'robotis_detectedsound_value_init',\n        'robotis_detectingsound_value',\n        'robotis_touch_value_dream',\n        'robotis_touch_value_boolean_dream',\n        'robotis_irs_value_dream',\n        'robotis_irs_value_boolean_dream',\n        'robotis_irsInner_value_dream',\n        'robotis_light_value_dream',\n        'robotis_light_value_boolean_dream',\n        'robotis_color_value_dream',\n        'robotis_color_value_boolean_dream',\n        'robotis_humidity_value_dream',\n        'robotis_humidity_value_boolean_dream',\n        'robotis_temperature_value_dream',\n        'robotis_temperature_value_boolean_dream',\n    ],\n    hw_led: [\n        'robotis_set_led_dream',\n    ],\n}\n\nEntry.Robotis_DREAM2.getPracticalBlocks = function () {\n    return{\n        robotis_melody_note_for: {\n            color: '#FC327F',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '멜로디 %1 을(를) %2 옥타브로 %3 만큼 소리내기 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        //['무음', '12'],\n                        ['도', '0'],\n                        ['도#(레♭)', '1'],\n                        ['레', '2'],\n                        ['레#(미♭)', '3'],\n                        ['미', '4'],\n                        ['파', '5'],\n                        ['파#(솔♭)', '6'],\n                        ['솔', '7'],\n                        ['솔#(라♭)', '8'],\n                        ['라', '9'],\n                        ['라#(시♭)', '10'],\n                        ['시', '11'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: '#ce105e',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                        ['6', '5'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: '#ce105e',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['온음표', '4'],\n                        ['2분음표', '2'],\n                        ['4분음표', '1'],\n                        ['8분음표', '0.5'],\n                        ['16분음표', '0.25'],\n                        /*['4분음표', '4'],\n                        ['8분음표', '8'],\n                        ['16분음표', '16'],*/\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: '#ce105e',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/melody.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'robotis_melody_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                DURATION: 2,\n            },\n            class: 'robotis_melody',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const note = script.getNumberField('NOTE', script);\n                const octave = script.getNumberField('OCTAVE', script);\n                const cmBuzzerTime = script.getNumberField('DURATION', script);\n    \n                let cmBuzzerIndex = note + octave * 12;\n                if (cmBuzzerIndex > 51) {\n                    cmBuzzerIndex = 51;\n                }\n                if (cmBuzzerIndex < 0) {\n                    cmBuzzerIndex = 0;\n                }\n    \n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\n                let data_address_1 = 0;\n                let data_length_1 = 0;\n                let data_value_1 = 0;\n                let data_address_2 = 0;\n                let data_length_2 = 0;\n                let data_value_2 = 0;\n    \n                data_address_1 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[0];\n                data_length_1 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_TIME[1];\n    \n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n    \n                data_value_1 = parseInt(cmBuzzerTime * 10);\n                if (data_value_1 > 50) {\n                    data_value_1 = 50;\n                }\n                //data_value_1\n                data_address_2 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[0];\n                data_length_2 = Entry.Robotis_openCM70.CONTROL_TABLE.CM_BUZZER_INDEX[1];\n                data_value_2 = cmBuzzerIndex;\n    \n                const data_sendqueue = [\n                    [data_instruction, data_address_1, data_length_1, data_value_1],\n                    [data_instruction, data_address_2, data_length_2, data_value_2],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime * 1000\n                );\n            },\n        },\n        robotis_detectedsound_value: {\n            color: '#01d67f',\n            outerLine: '#00b36a',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '소리 센서 최종 소리 횟수',\n            events: {},\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'robotis_detectedsound_value',\n            },\n            paramsKeyMap: {},\n            class: 'robotis_sound',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                return Entry.hw.portData.DETECTEDSOUNDE;\n            },\n        },\n        robotis_detectedsound_value_boolean: {\n            color: '#01d67f',\n            outerLine: '#00b36a',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['robotis_Dream'],\n            template: '소리 센서 최종 소리 횟수 %1 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#00b36a',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'robotis_detectedsound_value_boolean',\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n                RIGHTVALUE: 1,\n            },\n            class: 'robotis_sound',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\n                const leftValue = Entry.hw.portData.DETECTEDSOUNDE;\n                let isCheck = false;\n    \n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n    \n                return isCheck;\n            },\n        },\n        robotis_detectedsound_value_init: {\n            color: '#00D67F',\n            outerLine: '#00b36a',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '소리 센서 최종 소리 횟수 초기화 %1',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/sound.png',\n                    size: 12,\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'robotis_detectedsound_value_init',\n            },\n            paramsKeyMap: {},\n            class: 'robotis_sound',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\n                const data_address = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[0];\n                const data_length = Entry.Robotis_openCM70.CONTROL_TABLE.CM_SOUND_DETECTED[1];\n                const data_value = 0;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                //Entry.Robotis_carCont.update();\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n        },\n        robotis_detectingsound_value: {\n            color: '#01d67f',\n            outerLine: '#00b36a',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '소리 센서 실시간 소리 횟수',\n            events: {},\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [null],\n                type: 'robotis_detectingsound_value',\n            },\n            paramsKeyMap: {},\n            class: 'robotis_sound',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                return Entry.hw.portData.DETECTINGSOUNDE1;\n            },\n        },\n        robotis_set_led_dream: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 LED를 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['모두 끄기', '0'],\n                        ['노랑색 켜기', '1'],\n                        ['파랑색 켜기', '2'],\n                        ['모두 켜기', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/light.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_set_led_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COLOR: 1,\n            },\n            class: 'robotis_set_led_dream',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n    \n                const port = script.getStringField('PORT');\n                const value = 0;\n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                let data_address = 0;\n                const data_length = Entry.Robotis_DREAM.CONTROL_TABLE.CM_LED[1];\n                const data_value = script.getNumberField('COLOR');\n                switch (port) {\n                    case '3':\n                        //data_address = 212;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_LED[0];\n                        break;\n                    case '4':\n                        // data_address = 213;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_LED[2];\n                        break;\n                }\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                //Entry.Robotis_carCont.update();\n                return Entry.Robotis_DREAM.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n        },\n        robotis_touch_value_dream: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 접촉 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_touch_value_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_touch',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT');\n                let value = 0;\n    \n                switch (port) {\n                    case '3':\n                        value = Entry.hw.portData.TOUCH0;\n                        break;\n                    case '4':\n                        value = Entry.hw.portData.TOUCH1;\n                        break;\n                }\n                return value;\n            },\n        },\n        robotis_touch_value_boolean_dream: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 접촉 센서가 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['접촉 되면', '1'],\n                        ['접촉 안되면', '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            def: {\n                params: [null, null, null],\n                type: 'robotis_touch_value_boolean_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                TOUCH: 1,\n            },\n            class: 'robotis_touch',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT');\n                const touch = script.getNumberField('TOUCH', script);\n                let value = 0;\n                switch (port) {\n                    case '3':\n                        value = Entry.hw.portData.TOUCH0;\n                        break;\n                    case '4':\n                        value = Entry.hw.portData.TOUCH1;\n                        break;\n                }\n                const isTouch = !((value == 1) ^ touch);\n    \n                return isTouch;\n            },\n        },\n        robotis_irs_value_dream: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 적외선 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_irs_value_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_irs',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT');\n                let value = 0;\n                let data_address = 0;\n                switch (port) {\n                    case '3':\n                        value = Entry.hw.portData.IR0;\n                        // data_address = 108;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case '4':\n                        value = Entry.hw.portData.IR1;\n                        // data_address = 109;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\n                const data_length = 1;\n                // const data_value = 2;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.IR;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                //Entry.Robotis_carCont.update();\n                if (!Entry.Robotis_DREAM.IRS_MODULEWRITE.PORT3 && port == '3') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.IRS_MODULEWRITE.PORT3 = true;\n                }\n                if (!Entry.Robotis_DREAM.IRS_MODULEWRITE.PORT4 && port == '4') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.IRS_MODULEWRITE.PORT4 = true;\n                }\n                //var value = (Entry.hw.portData['IN' + port] > 125) ? 1 : 0;\n                return value;\n            },\n        },\n        robotis_irs_value_boolean_dream: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 적외선 센서 값 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'robotis_irs_value_boolean_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                RIGHTVALUE: 2,\n            },\n            class: 'robotis_irs',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT', script);\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\n                let leftValue = 0;\n                let isCheck = false;\n                let data_address = 0;\n    \n                switch (port) {\n                    case '3':\n                        leftValue = Entry.hw.portData.IR0;\n                        // data_address = 108;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case '4':\n                        leftValue = Entry.hw.portData.IR1;\n                        // data_address = 109;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\n                const data_length = 1;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.IR;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                //Entry.Robotis_carCont.update();\n                if (!Entry.Robotis_DREAM.IRS_MODULEWRITE.PORT3 && port == '3') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.IRS_MODULEWRITE.PORT3 = true;\n                }\n                if (!Entry.Robotis_DREAM.IRS_MODULEWRITE.PORT4 && port == '4') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.IRS_MODULEWRITE.PORT4 = true;\n                }\n    \n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n    \n                return isCheck;\n            },\n        },\n        robotis_irsInner_value_dream: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1 적외선 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['오른쪽', '0'],\n                        ['왼쪽', '1'],\n                        ['중앙', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_irsInner_value_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_irs',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT');\n                let value = 0;\n                const data_address = 0;\n                switch (port) {\n                    case '0':\n                        value = Entry.hw.portData.IRINNER0;\n                        break;\n                    case '1':\n                        value = Entry.hw.portData.IRINNER1;\n                        break;\n                    case '2':\n                        value = Entry.hw.portData.IRINNER2;\n                        break;\n                }\n                //var value = (Entry.hw.portData['IN' + port] > 125) ? 1 : 0;\n                return value;\n            },\n        },\n        robotis_light_value_dream: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 빛 감지 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '0'],\n                        ['PORT 4', '1'],\n                    ],\n                    value: '0',\n                    outerLine: '#e37100',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_light_value_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_light',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT');\n                return Entry.hw.portData[`LIGHT${port}`];\n            },\n        },\n        robotis_light_value_boolean_dream: {\n            color: '#ff8d0f',\n            outerLine: '#e37100',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 빛 감지 센서 값 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '0'],\n                        ['PORT 4', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#e37100',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'robotis_light_value_boolean_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                RIGHTVALUE: 2,\n            },\n            class: 'robotis_light',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getNumberField('PORT', script);\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\n                const leftValue = Entry.hw.portData[`LIGHT${port}`];\n                let isCheck = false;\n    \n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n    \n                return isCheck;\n            },\n        },\n        robotis_color_value_dream: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 컬러 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_color_value_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_color',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT');\n                let value = 0;\n                let data_address = 0;\n                switch (port) {\n                    case '3':\n                        value = Entry.hw.portData.COLOR0;\n                        // data_address = 108;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case '4':\n                        value = Entry.hw.portData.COLOR1;\n                        // data_address = 109;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                const data_length = 1;\n                // const data_value = 4;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.COLOR;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n    \n                if (!Entry.Robotis_DREAM.COLOR_MODULEWRITE.PORT3 && port == '3') {\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                    Entry.Robotis_carCont.update();\n                    Entry.Robotis_DREAM.COLOR_MODULEWRITE.PORT3 = true;\n                } else if (!Entry.Robotis_DREAM.COLOR_MODULEWRITE.PORT4 && port == '4') {\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                    Entry.Robotis_carCont.update();\n                    Entry.Robotis_DREAM.COLOR_MODULEWRITE.PORT4 = true;\n                }\n    \n                switch (value) {\n                    case 0:\n                        value = '알 수 없음';\n                        break;\n                    case 1:\n                        value = '흰색';\n                        break;\n                    case 2:\n                        value = '검은색';\n                        break;\n                    case 3:\n                        value = '빨강색';\n                        break;\n                    case 4:\n                        value = '초록색';\n                        break;\n                    case 5:\n                        value = '파랑색';\n                        break;\n                    case 6:\n                        value = '노랑색';\n                        break;\n                }\n    \n                return value;\n            },\n        },\n        robotis_color_value_boolean_dream: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 컬러 센서 값 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['알 수 없음 : 0', '0'],\n                        ['흰색 : 1', '1'],\n                        ['검은색 : 2', '2'],\n                        ['빨강색 : 3', '3'],\n                        ['초록색 : 4', '4'],\n                        ['파랑색 : 5', '5'],\n                        ['노랑색 : 6', '6'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            def: {\n                params: [null, null, null],\n                type: 'robotis_color_value_boolean_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                RIGHTVALUE: 2,\n            },\n            class: 'robotis_color',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getField('PORT', script);\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberField('RIGHTVALUE', script);\n                let leftValue = 0;\n                let data_address = 0;\n                let isCheck = false;\n    \n                switch (port) {\n                    case '3':\n                        leftValue = Entry.hw.portData.COLOR0;\n                        // data_address = 108;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case '4':\n                        leftValue = Entry.hw.portData.COLOR1;\n                        // data_address = 109;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n    \n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                const data_length = 1;\n                // const data_value = 4;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.COLOR;\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n    \n                if (!Entry.Robotis_DREAM.COLOR_MODULEWRITE.PORT3 && port == '3') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.COLOR_MODULEWRITE.PORT3 = true;\n                } else if (!Entry.Robotis_DREAM.COLOR_MODULEWRITE.PORT4 && port == '4') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.COLOR_MODULEWRITE.PORT4 = true;\n                }\n                // const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                // Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                // Entry.Robotis_carCont.update();\n    \n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n    \n                return isCheck;\n            },\n        },\n        robotis_humidity_value_dream: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 습도 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_humidity_value_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_humidity',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT');\n                let value = 0;\n                let data_address = 0;\n                switch (port) {\n                    case '3':\n                        value = Entry.hw.portData.HUMIDTY0;\n                        // data_address = 108;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case '4':\n                        value = Entry.hw.portData.HUMIDTY1;\n                        // data_address = 109;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                const data_length = 1;\n                // const data_value = 5;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.MOISTURE;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n    \n                if (!Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT3 && port == '3') {\n                    console.log(`address : ${data_address} value : ${data_value}`);\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                    Entry.Robotis_carCont.update();\n                    Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT3 = true;\n                } else if (!Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT4 && port == '4') {\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                    Entry.Robotis_carCont.update();\n                    Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT4 = true;\n                }\n                // Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                // Entry.Robotis_carCont.update();\n    \n                return value;\n            },\n        },\n        robotis_humidity_value_boolean_dream: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 습도 센서 값 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                ],\n                type: 'robotis_humidity_value_boolean_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                RIGHTVALUE: 2,\n            },\n            class: 'robotis_humidity',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getNumberField('PORT', script);\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\n                let leftValue = 0;\n                let data_address = 0;\n                let isCheck = true;\n    \n                switch (port) {\n                    case 3:\n                        leftValue = Entry.hw.portData.HUMIDTY0;\n                        // data_address = 108;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case 4:\n                        leftValue = Entry.hw.portData.HUMIDTY1;\n                        // data_address = 109;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n    \n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                const data_length = 1;\n                // const data_value = 5;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.MOISTURE;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                if (!Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT3 && port == '3') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT3 = true;\n                } else if (!Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT4 && port == '4') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT4 = true;\n                }\n                // Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                // Entry.Robotis_carCont.update();\n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n                return isCheck;\n            },\n        },\n        robotis_temperature_value_dream: {\n            color: '#2AB4D3',\n            outerLine: '#0e93b1',\n            skeleton: 'basic_string_field',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 온도 센서 값',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#0e93b1',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_temperature_value_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_temperature',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getStringField('PORT');\n                let value = 0;\n                let data_address = 0;\n                switch (port) {\n                    case '3':\n                        value = Entry.hw.portData.TEMPERATURE0;\n                        // data_address = 108;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case '4':\n                        value = Entry.hw.portData.TEMPERATURE1;\n                        // data_address = 109;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                const data_length = 1;\n                // const data_value = 5;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.MOISTURE;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                if (!Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT3 && port == '3') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT3 = true;\n                } else if (!Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT4 && port == '4') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT4 = true;\n                }\n    \n                // const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                // Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                // Entry.Robotis_carCont.update();\n    \n                return value;\n            },\n        },\n        robotis_temperature_value_boolean_dream: {\n            color: '#C4065C',\n            outerLine: '#9a0045',\n            skeleton: 'basic_boolean_field',\n            fontColor: '#fff',\n            isNotFor: ['robotis_Dream'],\n            template: '%1번 포트 온도 센서 값 %2 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['=', 'EQUAL'],\n                        ['>', 'GREATER'],\n                        ['<', 'LESS'],\n                        ['≥', 'GREATER_OR_EQUAL'],\n                        ['≤', 'LESS_OR_EQUAL'],\n                    ],\n                    value: 'LESS',\n                    fontSize: 11,\n                    bgColor: '#9a0045',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                    noaRrow: true,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                ],\n                type: 'robotis_temperature_value_boolean_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n                RIGHTVALUE: 2,\n            },\n            class: 'robotis_temperature',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getNumberField('PORT', script);\n                const operator = script.getField('OPERATOR', script);\n                const rightValue = script.getNumberValue('RIGHTVALUE', script);\n                let leftValue = 0;\n                let data_address = 0;\n                let isCheck = true;\n    \n                switch (port) {\n                    case 3:\n                        leftValue = Entry.hw.portData.TEMPERATURE0;\n                        // data_address = 108;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case 4:\n                        leftValue = Entry.hw.portData.TEMPERATURE1;\n                        // data_address = 109;\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n    \n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\n                const data_length = 1;\n                // const data_value = 5;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.MOISTURE;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                if (!Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT3 && port == '3') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT3 = true;\n                } else if (!Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT4 && port == '4') {\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    Entry.Robotis_DREAM.TEMPER_MOISTURE_MODULEWRITE.PORT4 = true;\n                }\n    \n                // const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                // Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                // Entry.Robotis_carCont.update();\n                switch (operator) {\n                    case 'EQUAL':\n                        isCheck = leftValue == rightValue;\n                        break;\n                    case 'GREATER':\n                        isCheck = Number(leftValue) > Number(rightValue);\n                        break;\n                    case 'LESS':\n                        isCheck = Number(leftValue) < Number(rightValue);\n                        break;\n                    case 'GREATER_OR_EQUAL':\n                        isCheck = Number(leftValue) >= Number(rightValue);\n                        break;\n                    case 'LESS_OR_EQUAL':\n                        isCheck = Number(leftValue) <= Number(rightValue);\n                        break;\n                }\n                return isCheck;\n            },\n        },\n        robotis_move_for_secs_dream: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1모터를 %2 %3의 속도로 %4초 동안 회전 %5',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1번 포트', '1'],\n                        ['2번 포트', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', 'CW'],\n                        ['반시계방향', 'CCW'],\n                    ],\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'practical_course_motor_speed',\n                    },\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    null,\n                ],\n                type: 'robotis_move_for_secs_dream',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n                DURATION: 3,\n            },\n            class: 'robotis_motor',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const duration = script.getNumberValue('DURATION');\n                const wheel = script.getNumberField('WHEEL');\n                let value = script.getNumberValue('SPEED');\n                const direction = script.getStringField('DIRECTION');\n    \n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                // let data_address = 0;\n                let data_address = (data_address =\n                    Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[0]);\n                let data_length = 0;\n                let data_value = 0;\n    \n                //data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\n    \n                if (wheel == '3') {\n                    data_length = 4;\n                    // data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\n                } else {\n                    data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\n                    data_address = data_address + (wheel - 1) * data_length;\n                }\n    \n                if (!script.isStart) {\n                    value = value * 68;\n    \n                    if (direction == 'CW') {\n                        value = value + 1024;\n                        if (value > 2047) {\n                            value = 2047;\n                        }\n                    } else {\n                        if (value > 1023) {\n                            value = 1023;\n                        }\n                    }\n                    /*if (wheel == '3' || wheel == '1') {\n                        if (direction == 'CCW') {\n                            value = value + 1024;\n                            if (value > 2047) {\n                                value = 2047;\n                            }\n                        } else {\n                            if (value > 1023) {\n                                value = 1023;\n                            }\n                        }\n                    } else {\n                        if (direction == 'CW') {\n                            value = value + 1024;\n                            if (value > 2047) {\n                                value = 2047;\n                            }\n                        } else {\n                            if (value > 1023) {\n                                value = 1023;\n                            }\n                        }\n                    }*/\n    \n                    data_value = value;\n    \n                    var data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n    \n                    script.wheelMode = wheel;\n    \n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration * 1000);\n    \n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.Robotis_DREAM.update();\n                    //return Entry.Robotis_carCont.postCallReturn(script, data_sendqueue, 2000);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    //data_sendqueue = [[data_instruction, data_address, data_length, 0]];\n                    //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    delete script.wheelMode;\n                    Entry.engine.isContinue = false;\n    \n                    data_sendqueue = [[data_instruction, data_address, data_length, 0]];\n                    Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    Entry.engine.isContinue = false;\n                    Entry.Robotis_DREAM.update();\n                    return script.callReturn();\n                }\n                //return Entry.Robotis_carCont.postCallReturn(script, data_sendqueue, 2000);\n            },\n        },\n        robotis_aux_move_for_dream: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1모터를 %2 %3의 속도로 계속 회전 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1번 포트', '1'],\n                        ['2번 포트', '2'],\n                        ['모두', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', 'CW'],\n                        ['반시계방향', 'CCW'],\n                    ],\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    {\n                        type: 'practical_course_motor_speed',\n                    },\n                    null,\n                ],\n                type: 'robotis_aux_move_for_dream',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'robotis_motor',\n            //'isNotFor': ['mini'],\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const wheel = script.getNumberField('WHEEL');\n                let value = script.getNumberValue('SPEED');\n                const direction = script.getStringField('DIRECTION');\n    \n                const data_instruction = Entry.Robotis_openCM70.INSTRUCTION.WRITE;\n                let data_address = 0;\n                let data_length = 0;\n                // let data_value = 0;\n                let data_value = Entry.Robotis_DREAM.MODULE_VALUE.DEFAULT;\n                data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\n    \n                if (wheel == '3') {\n                    data_length = 4;\n                    // data_address = 136;\n                } else {\n                    data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\n                    data_address = data_address + (wheel - 1) * data_length;\n                }\n                value = value * 68;\n    \n                if (direction == 'CW') {\n                    value = value + 1024;\n                    if (value > 2047) {\n                        value = 2047;\n                    }\n                } else {\n                    if (value > 1023) {\n                        value = 1023;\n                    }\n                }\n                /*if (wheel == '3' || wheel == '1') {\n                    if (direction == 'CCW') {\n                        value = value + 1024;\n                        if (value > 2047) {\n                            value = 2047;\n                        }\n                    } else {\n                        if (value > 1023) {\n                            value = 1023;\n                        }\n                    }\n                } else {\n                    if (direction == 'CW') {\n                        value = value + 1024;\n                        if (value > 2047) {\n                            value = 2047;\n                        }\n                    } else {\n                        if (value > 1023) {\n                            value = 1023;\n                        }\n                    }\n                }*/\n    \n                data_value = value;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                return Entry.Robotis_DREAM.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n        },\n        robotis_aux_stop_for_dream: {\n            color: '#00B200',\n            outerLine: '#019101',\n            skeleton: 'basic',\n            fontColor: '#fff',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1모터를 정지 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1번 포트', '1'],\n                        ['2번 포트', '2'],\n                        ['모두', '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#019101',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/dcmotor.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'robotis_aux_stop_for_dream',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n            },\n            class: 'robotis_motor',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const wheel = script.getNumberField('WHEEL');\n                const value = 0;\n    \n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                // let data_address = 0;\n                let data_address = (data_address =\n                    Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[0]);\n                let data_length = 0;\n                // let data_value = 0;\n                let data_value = Entry.Robotis_DREAM.MODULE_VALUE.DEFAULT;\n    \n                data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[0];\n    \n                console.log(`wheel ${wheel}`);\n                if (wheel == '3') {\n                    data_length = 4;\n                    // data_address = 136;\n                } else {\n                    data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[1];\n                    data_address = data_address + (wheel - 1) * data_length;\n                }\n    \n                data_value = value;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n        },\n        robotis_set_servo_mode_dream: {\n            color: '#D128BD',\n            outerLine: '#a2049e',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1 포트의 서보모터를 %2 지정 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['회전모드', 0],\n                        ['관절모드', 1],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/servo.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotis_set_servo_mode_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                MODE: 1,\n            },\n            class: 'robotis_servo_motor',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                // instruction / address / length / value / default length\n                const port = script.getField('PORT', script);\n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                let data_address = 0;\n                const data_length = 1;\n                const data_value = Entry.Robotis_DREAM.MODULE_VALUE.SERVO;\n                const data_mode = script.getNumberField('MODE');\n                switch (port) {\n                    case '3':\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[0];\n                        break;\n                    case '4':\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.CM_MODULE_CLASS[1];\n                        break;\n                }\n                //\n                if (\n                    (!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT3 && port == '3') ||\n                    (!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT4 && port == '4')\n                ) {\n                    let data_sendqueue;\n                    if (port == '3') {\n                        Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT3 = true;\n                        data_sendqueue = [\n                            [\n                                data_instruction,\n                                Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[0],\n                                Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[1],\n                                data_mode,\n                            ],\n                        ];\n                    } else if (port == '4') {\n                        Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT4 = true;\n                        data_sendqueue = [\n                            [\n                                data_instruction,\n                                Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[2],\n                                Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[1],\n                                data_mode,\n                            ],\n                        ];\n                    }\n    \n                    return Entry.Robotis_carCont.postCallReturn(\n                        script,\n                        data_sendqueue,\n                        Entry.Robotis_openCM70.delay\n                    );\n                }\n                /*\n                if (!script.isStart) {\n                    if (\n                        (!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT3 && port == '3') ||\n                        (!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT4 && port == '4')\n                    ) {\n                        var data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                        Entry.Robotis_DREAM.update();\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(() => {\n                            script.timeFlag = 0;\n                        }, 1 * 650); // 이게 문제?\n                    } else {\n                        script.isStart = true;\n                        script.timeFlag = 0;\n                    }\n    \n                       return script;\n                    } else if (script.timeFlag == 1) {\n                        return script;\n                    } else {\n                        delete script.timeFlag;\n                        delete script.isStart;\n                        delete script.wheelMode;\n                        Entry.engine.isContinue = false;\n                        if(!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT3 && port == '3' || !Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT4 && port == '4')\n                        {\n    \n                            if(port == '3'){\n                                Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT3 = true;\n                                data_sendqueue = [\n                                    [data_instruction, Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[0], Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[1], data_mode],\n                                ];\n                            }else if (port == '4'){\n                                Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT4 = true;\n                                data_sendqueue = [\n                                    [data_instruction, Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[2], Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[1], data_mode],\n                                ];\n                            }\n    \n                            Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                            Entry.engine.isContinue = false;\n                            Entry.Robotis_DREAM.update();\n                            console.log(\"datasend mode \" + data_sendqueue);\n                        }\n                        return script.callReturn();\n                    }*/\n                //\n            },\n        },\n        robotis_set_servo_speed_dream: {\n            color: '#D128BD',\n            outerLine: '#a2049e',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1 포트의 서보모터를 %2 %3 속도로 회전%4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', 'CW'],\n                        ['반시계방향', 'CCW'],\n                    ],\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        ['5', 5],\n                        ['6', 6],\n                        ['7', 7],\n                        ['8', 8],\n                        ['9', 9],\n                        ['10', 10],\n                        ['11', 11],\n                        ['12', 12],\n                        ['13', 13],\n                        ['14', 14],\n                        ['15', 15],\n                    ],\n                    value: 7,\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/servo.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'robotis_set_servo_speed_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'robotis_servo_motor',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                // instruction / address / length / value / default length\n                const port = script.getField('PORT', script);\n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                let data_address = 0;\n                let data_length = 0;\n                let data_value = script.getNumberField('SPEED');\n                const direction = script.getStringField('DIRECTION');\n                data_value = data_value * 68;\n    \n                console.log(`kjsDebug ${data_value}  ${direction}`);\n                if (direction == 'CW') {\n                    data_value = data_value + 1024;\n                    if (data_value > 2047) {\n                        data_value = 2047;\n                    }\n                } else {\n                    if (data_value > 1023) {\n                        data_value = 1023;\n                    }\n                }\n    \n                switch (port) {\n                    case '3':\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[0];\n                        data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[1];\n                        break;\n                    case '4':\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[2];\n                        data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[1];\n                        break;\n                }\n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                return Entry.Robotis_DREAM.postCallReturn(script, data_sendqueue, 300);\n                /*\n                if(!Entry.Robotis_DREAM.SERVO_WHEELWRITE.PORT3 && port == '3' || !Entry.Robotis_DREAM.SERVO_WHEELWRITE.PORT4 && port == '4')\n                {\n                    console.log(\"datasend \" + data_sendqueue);\n                    if(port == '3'){\n                        Entry.Robotis_DREAM.SERVO_WHEELWRITE.PORT3 = true;\n                    }else if (port == '4'){\n                        Entry.Robotis_DREAM.SERVO_WHEELWRITE.PORT4 = true;\n                    }\n    \n                    return Entry.Robotis_DREAM.postCallReturn(\n                        script,\n                        data_sendqueue,\n                        300\n                    );\n                }*/\n            },\n        },\n        robotis_servo_stop_for_dream: {\n            color: '#D128BD',\n            outerLine: '#a2049e',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1모터를 정지 %2',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '1'],\n                        ['PORT 4', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/servo.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'robotis_servo_stop_for_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'robotis_servo_motor',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                const port = script.getField('PORT', script);\n                const value = 0;\n    \n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                // let data_address = 0;\n                let data_address = (data_address =\n                    Entry.Robotis_DREAM.CONTROL_TABLE.AUX_MOTOR_SPEED[0]);\n                let data_length = 0;\n                // let data_value = 0;\n                let data_value = 0;\n    \n                data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[0];\n    \n                switch (port) {\n                    case '1':\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[0];\n                        data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[1];\n                        break;\n                    case '2':\n                        data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[2];\n                        data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[1];\n                        break;\n                }\n    \n                data_value = value;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                console.log(`kjsDebug data_sendqueue : ${data_sendqueue}`);\n                return Entry.Robotis_DREAM.postCallReturn(script, data_sendqueue, 300);\n            },\n        },\n        robotis_set_servo_position_dream: {\n            color: '#D128BD',\n            outerLine: '#a2049e',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1 포트의 서보모터를 %2 이동 %3',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/servo.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['512'],\n                    },\n                    null,\n                ],\n                type: 'robotis_set_servo_position_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'robotis_servo_motor',\n            func(sprite, script) {\n                const port = script.getField('PORT', script);\n                let value = script.getNumberValue('VALUE');\n    \n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                let data_address = 0;\n                let data_length = 0;\n                let data_value = 0;\n    \n                data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_POSITION[0];\n                data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_POSITION[1];\n    \n                data_address = data_address + (port - 3) * data_length;\n    \n                if (value > 1023) {\n                    value = 1023;\n                } else if (value < 0) {\n                    value = 0;\n                }\n    \n                data_value = value;\n    \n                const data_sendqueue = [[data_instruction, data_address, data_length, data_value]];\n                return Entry.Robotis_carCont.postCallReturn(script, data_sendqueue, 300);\n            },\n        },\n        robotis_set_servo_wheel_dream: {\n            color: '#D128BD',\n            outerLine: '#a2049e',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1 포트의 서보모터를 %2 %3속도로 회전 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계방향', 'CW'],\n                        ['반시계방향', 'CCW'],\n                    ],\n                    value: 'CW',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        ['5', 5],\n                        ['6', 6],\n                        ['7', 7],\n                        ['8', 8],\n                        ['9', 9],\n                        ['10', 10],\n                        ['11', 11],\n                        ['12', 12],\n                        ['13', 13],\n                        ['14', 14],\n                        ['15', 15],\n                    ],\n                    value: 7,\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/servo.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null, null],\n                type: 'robotis_set_servo_wheel_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIRECTION: 1,\n                SPEED: 2,\n            },\n            class: 'robotis_servo_motor',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                // instruction / address / length / value / default length\n                const port = script.getField('PORT', script);\n                const direction = script.getStringField('DIRECTION');\n                const speed = script.getNumberField('SPEED');\n                const value = 0;\n    \n                const data_address3 = 0;\n                32;\n                const data_length3 = 0;\n                let data_value3 = 0;\n    \n                let data_address2 = 0;\n                const data_length2 = 1;\n                const data_value2 = 7;\n    \n                const data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                let data_address = 0;\n                let data_length = 0;\n                let data_value = 0;\n    \n                let data_address4 = 0; // servo speed\n                let data_length4 = 2;\n                let data_value4 = 0;\n    \n                data_value4 = speed * 68;\n                if (data_value4 > 1023) {\n                    data_value4 = 1023;\n                }\n                switch (port) {\n                    case '3':\n                        data_address2 = 104;\n                        break;\n                    case '4':\n                        data_address2 = 105;\n                        break;\n                }\n    \n                // data_address3 = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_POSITION[0];\n                // data_length3 = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_POSITION[1];\n    \n                // data_address3 = data_address3 + (port - 1) * data_length3;\n    \n                data_address4 = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[0];\n                data_length4 = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[1];\n    \n                data_address4 = data_address4 + (port - 3) * data_length4;\n    \n                data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[0];\n                data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[1];\n    \n                data_address = data_address + (port - 3) * data_length;\n                data_value = 0;\n    \n                if (direction == 'CW') {\n                    data_value4 = data_value4 + 1024;\n                    if (data_value4 > 2047) {\n                        data_value4 = 2047;\n                    }\n                } else {\n                    if (data_value4 > 1023) {\n                        data_value4 = 1023;\n                    }\n                }\n    \n                data_value3 = direction;\n    \n                //var data_sendqueue = [[data_instruction, data_address2, data_length2, data_value2], [data_instruction, data_address, data_length, data_value], [data_instruction, data_address4, data_length4, data_value4]];\n                //return Entry.Robotis_carCont.postCallReturn(script, data_sendqueue, Entry.Robotis_openCM70.delay);\n                //\n                if (!script.isStart) {\n                    if (\n                        (!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT3 && port == '3') ||\n                        (!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT4 && port == '4')\n                    ) {\n                        var data_sendqueue = [\n                            [data_instruction, data_address2, data_length2, data_value2],\n                        ];\n                        console.log(`kjDebug : ${data_sendqueue}`);\n                        Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                        Entry.Robotis_DREAM.update();\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(() => {\n                            script.timeFlag = 0;\n                        }, 1 * 650);\n                    } else {\n                        script.isStart = true;\n                        script.timeFlag = 0;\n                    }\n    \n                    /*\n                        var data_sendqueue = [[data_instruction, data_address2, data_length2, data_value2]];\n                        Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                        Entry.Robotis_carCont.update();\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(function () {\n                            script.timeFlag = 0;\n                        }, 1 * 650);\n                        */\n    \n                    return script;\n                } else if (script.timeFlag == 1) {\n                    //data_sendqueue = [[data_instruction, data_address, data_length, 0]];\n                    //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    delete script.wheelMode;\n                    Entry.engine.isContinue = false;\n                    if (\n                        (!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT3 && port == '3') ||\n                        (!Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT4 && port == '4')\n                    ) {\n                        data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, data_address4, data_length4, data_value4],\n                        ];\n                        console.log(`kjsDebug port :${port} data ${data_sendqueue}`);\n                        Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                        Entry.engine.isContinue = false;\n                        Entry.Robotis_DREAM.update();\n    \n                        if (port == '3') {\n                            Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT3 = true;\n                        } else if (port == '4') {\n                            Entry.Robotis_DREAM.SERVO_MODULEWRITE.PORT4 = true;\n                        }\n                    }\n                    // data_sendqueue = [\n                    //     [data_instruction, data_address, data_length, data_value],\n                    //     [data_instruction, data_address4, data_length4, data_value4],\n                    // ];\n    \n                    // Entry.Robotis_DREAM.setRobotisData(data_sendqueue);\n                    // Entry.engine.isContinue = false;\n                    // Entry.Robotis_DREAM.update();\n    \n                    return script.callReturn();\n                }\n                //\n            },\n        },\n        robotis_set_servo_joint_dream: {\n            color: '#D128BD',\n            outerLine: '#a2049e',\n            skeleton: 'basic',\n            statements: [],\n            isNotFor: ['robotis_Dream'],\n            template: '%1 포트의 서보모터를 %2 도 %3속도로 이동 %4',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['PORT 3', '3'],\n                        ['PORT 4', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 1],\n                        ['2', 2],\n                        ['3', 3],\n                        ['4', 4],\n                        ['5', 5],\n                        ['6', 6],\n                        ['7', 7],\n                        ['8', 8],\n                        ['9', 9],\n                        ['10', 10],\n                        ['11', 11],\n                        ['12', 12],\n                        ['13', 13],\n                        ['14', 14],\n                        ['15', 15],\n                    ],\n                    value: 7,\n                    fontSize: 11,\n                    bgColor: '#A2049E',\n                    arrowColor: EntryStatic.colorSet.common.WHITE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/practical_course/servo.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['512'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'robotis_set_servo_joint_dream',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n                SPEED: 2,\n            },\n            class: 'robotis_servo_motor',\n            func(sprite, script) {\n                Entry.hw.sendQueue.IS_EDU = true;\n                // instruction / address / length / value / default length\n                const port = script.getField('PORT', script);\n                let value = script.getNumberValue('VALUE');\n                const speed = script.getNumberField('SPEED');\n    \n                var data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                let data_address3 = 0;\n                let data_length3 = 0;\n                let data_value3 = 0;\n    \n                let data_address2 = 0;\n                const data_length2 = 1;\n                const data_value2 = 7;\n    \n                var data_instruction = Entry.Robotis_DREAM.INSTRUCTION.WRITE;\n                let data_address = 0;\n                let data_length = 0;\n                let data_value = 0;\n    \n                let data_address4 = 0; // servo speed\n                let data_length4 = 2;\n                let data_value4 = 0;\n    \n                data_value4 = speed * 68;\n                if (data_value4 > 1023) {\n                    data_value4 = 1023;\n                }\n                switch (port) {\n                    case '3':\n                        5;\n                        data_address2 = 104;\n                        break;\n                    case '4':\n                        data_address2 = 105;\n                        break;\n                }\n    \n                data_address3 = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_POSITION[0];\n                data_length3 = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_POSITION[1];\n    \n                data_address3 = data_address3 + (port - 3) * data_length3;\n    \n                data_address4 = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[0];\n                data_length4 = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_SPEED[1];\n    \n                data_address4 = data_address4 + (port - 3) * data_length4;\n    \n                data_address = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[0];\n                data_length = Entry.Robotis_DREAM.CONTROL_TABLE.AUX_SERVO_MODE[1];\n    \n                data_address = data_address + (port - 3) * data_length;\n                data_value = 1;\n    \n                if (value > 1023) {\n                    value = 1023;\n                } else if (value < 0) {\n                    value = 0;\n                }\n    \n                data_value3 = value;\n    \n                if (!script.isStart) {\n                    var data_sendqueue = [[data_instruction, data_address2, data_length2, data_value2]];\n                    //Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                    //Entry.Robotis_carCont.update();\n                    if (\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT3 && port == '3') ||\n                        (!Entry.Robotis_openCM70.SERVO_MODULEWRITE.PORT4 && port == '4')\n                    ) {\n                        script.isStart = true;\n                        script.timeFlag = 1;\n                        setTimeout(() => {\n                            script.timeFlag = 0;\n                        }, 1 * 650);\n                    } else {\n                        script.isStart = true;\n                        script.timeFlag = 0;\n                    }\n    \n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    delete script.wheelMode;\n                    Entry.engine.isContinue = false;\n    \n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, 1 * 70);\n    \n                    data_sendqueue = [\n                        [data_instruction, data_address, data_length, data_value],\n                        [data_instruction, data_address4, data_length4, data_value4],\n                        [data_instruction, data_address3, data_length3, data_value3],\n                    ];\n                    Entry.Robotis_carCont.setRobotisData(data_sendqueue);\n                    Entry.engine.isContinue = false;\n                    Entry.Robotis_carCont.update();\n                    return script.callReturn();\n                }\n                //\n            },\n        },\n    }\n}\n\nmodule.exports = Entry.Robotis_DREAM2;\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotisRB.js",
    "content": "'use strict';\nEntry.Robotis_rb = {\n    INSTRUCTION: {\n        NONE: 0,\n        WRITE: 3,\n        READ: 2,\n        SYNCWRITE: 4,\n        REGWRITE: 5,\n        ACTION: 6,\n        BYPASS_READ: 0xA2,\n        BYPASS_WRITE: 0xA3,\n    },\n    CONTROL_TABLE: {\n        // [default address, default length, address (when reads together), length (when reads together)]\n        CM_LED_R: [79, 1],\n        CM_LED_G: [80, 1],\n        CM_LED_B: [81, 1],\n\n        RB_LED_L: [40, 1],\n        RB_LED_R: [41, 1],\n        RB_LED_B: [40, 2],\n\n        CM_BUZZER_INDEX: [60, 1], //[84, 1]\n        CM_BUZZER_TIME: [63, 1], //[85, 1]\n        CM_SOUND_DETECTED: [86, 1],\n        CM_SOUND_DETECTING: [87, 1],\n        CM_USER_BUTTON: [26, 1],\n        CM_MOTION: [66, 2], //[66,1]\n\n        AUX_SERVO_POSITION: [152, 2],\n        \n        AUX_CUSTOM: [216, 2],\n        \n        AUX_SERVO_MODE: [126, 1],\n        AUX_SERVO_SPEED: [136, 2],\n        AUX_MOTOR_SPEED: [136, 2],\n        AUX_LED_MODULE: [210, 1],\n        \n        MOTION_PARAMETER: [270, 4],\n\n        CM_DXL_MULTITURN_ID: [580, 1],\n        CM_DXL_MULTITURN_SPEED: [582, 2],\n        CM_DXL_MULTITURN_DISTANCE: [584, 4],\n\n        DXL_OPERATING_MODE: [11, 1],\n        DXL_TORQUE_ENABLE: [64, 1],\n        DXL_GOAL_VELOCITY: [104, 4],\n        DXL_PROFILE_VELOCITY: [112, 4],\n        DXL_GOAL_POSITION: [116, 4],\n        DXL_IS_MOVING: [122, 1],\n        DXL_PRESENT_VELOCITY: [128, 4],\n        DXL_PRESENT_POSITION: [132, 4],\n    },\n    DXL_POSITION: {\n        values: [0,0,0,0,0,0,0,0]\n    },\n    setZero: function () {\n        // instruction / address / length / value / default length\n        Entry.hw.sendQueue['setZero'] = [1];\n        Entry.Robotis_carCont.update();\n        Entry.Robotis_carCont.setRobotisData(null);\n        Entry.hw.sendQueue['setZero'] = null;\n        Entry.Robotis_carCont.update();\n        Entry.Robotis_carCont.setRobotisData([\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 21, 2, 20],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 40, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 66, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 710, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 19, 1, 1], // bypass 모드 켜기\n            // [Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 30759],\n            // [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1],\n        ]);\n        Entry.Robotis_carCont.update();\n    },\n    id: ['7.5', '7.6'],\n    name: 'Robotis_rb',\n    url: 'http://www.robotis.com/index/product.php?cate_code=111310',\n    imageName: 'robotis_RB100im_RGee.png',\n    title: {\n        \"ko\": \"로보티즈 알쥐\",\n        \"en\": \"ROBOTIS RGee\"\n    },\n    delay: 30,\n    readDelay: 30,\n};\n\nEntry.Robotis_rb.blockMenuBlocks = [\n    \n    'robotis_RB_cm_ir_value',\n    'robotis_RB_cm_ir_compare',\n    'robotis_RB_detectFrontObj',\n    'robotis_RB_cm_btn_value',\n    'robotis_RB_cm_joystick_value',\n    'robotis_RB_mic',\n    'robotis_RB_detectSound_compare',\n    'robotis_RB_imu',\n    'robotis_RB_roll_pitch', // 값 안나옴.\n    /*\n    'robotis_RB_environment_value',\n    'robotis_RB_environment_compare',\n    'robotis_RB_distance_value',\n    'robotis_RB_distance_compare',\n   */\n    'robotis_RB_cm_buzzer_index',\n\n    'robotis_RB_cm_screen',\n    'robotis_RB_cm_anim_screen',\n    'robotis_RB_rsp_screen',\n    'robotis_RB_text_screen',\n\n    'robotis_RB_LCDBright',\n    'robotis_RB_LCDColor',\n    \n    'robotis_RB_LEDBright',\n    'robotis_RB_cm_led',\n    'robotis_RB_Hello',\n    'robotis_RB_effectSound',\n    'robotis_RB_record',\n    'robotis_RB_playRecord',\n\n    'robotis_RB_car_screen',\n    'robotis_RB_car_anim_screen',\n    'robotis_RB_kkokdu_screen',\n    'robotis_RB_kkokdu_anim_screen',\n    \n    'robotis_openCM70_RGee_go',\n    'robotis_openCM70_RGee_stop',\n    'robotis_openCM70_RGee_motion',\n\n    \n    'robotis_RB_follow_line',\n    'robotis_RB_follow_line_stop',\n    \n    'robotis_dxl_control',\n    'robotis_dxl_each_control',\n\n    // 'robotis_RB_cm_custom_value',\n    // 'robotis_RB_cm_custom',\n];\n\nEntry.Robotis_rb.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                robotis_RB_cm_ir_value: \"%1 번 IR 센서 값\",\n                robotis_RB_cm_ir_compare: \"%1 번 IR 센서 값이 %2  %3이면\",\n                robotis_RB_detectFrontObj: \"앞에 물체가 있으면\",\n                robotis_RB_cm_btn_value: \"%1 버튼이 %2 이면\",\n                robotis_RB_cm_joystick_value: \"조이스틱 위치가 %1 이면\",\n                robotis_RB_mic: \"마이크 음량(dB)\",\n                robotis_RB_detectSound_compare: \"소리가 %1에서 나면\",\n                robotis_RB_imu: \"%1축의 %2 값\",\n                robotis_RB_roll_pitch: \"제어기 각도 %1 값\",\n                robotis_RB_environment_value: \"%1 %2 값\",\n                robotis_RB_environment_compare: \"%1 %2 값이 %3 %4이면\",\n                robotis_RB_distance_value: \"%1 %2 값\",\n                robotis_RB_distance_compare: \"%1 %2 값이 %3 %4이면\",\n\n                //robotis_RB_detectPose: \"로봇이 %1 넘어지면\",\n\n                robotis_RB_cm_buzzer_index: \"제어기 음계값 %1 을(를) %2 옥타브로 %3 초 동안 %4 %5\",\n\n                robotis_RB_kkokdu_screen: \"제어기 화면 배경을 꼭두 %1 로 선택 %2\",\n                robotis_RB_kkokdu_anim_screen: \"제어기 화면 애니메이션을 꼭두 %1 로 선택 %2\",\n\n                robotis_RB_rsp_screen: \"제어기 화면에 %1를 (%2, %3)위치에 %4 크기로 출력하기 %5\",\n                robotis_RB_text_screen: \"제어기 화면에 %1를 (%2, %3)위치에 %4 로 %5으로 출력하기 %6\",\n\n                robotis_RB_LCDBright: \"제어기 화면 밝기를 %1로 정하기 %2\",\n                robotis_RB_LCDColor: \"제어기 화면 색상을 %1 으로 정하기 %2\",\n                \n                robotis_RB_LEDBright: \"제어기 %1 LED 밝기를 %2로 정하기 %3\",\n                robotis_RB_cm_led: \"제어기 %1 LED %2 %3\",\n\n                robotis_RB_Hello: \"%1 말하기 %2\",\n                robotis_RB_effectSound: \"효과음 %1 재생하기 %2\",\n                robotis_RB_record: \"%1 번 방에 녹음하기 %2\",\n                robotis_RB_playRecord: \"%1 번 방 소리 재생하기 %2\",\n                robotis_openCM70_RGee_go: \"알쥐 %1 속도로 %2 하기 %3\",\n                robotis_openCM70_RGee_stop: \"알쥐 정지하기 %1\",\n                robotis_openCM70_RGee_motion: \"알쥐 %1 %2\",\n                \n                robotis_RB_follow_line: \"%1 속도로 라인 따라가기 %2\",\n                robotis_RB_follow_line_stop: \"라인 따라가기 종료 %1\",\n\n                robotis_RB_cm_screen: \"제어기 화면 배경을 알쥐 %1 로 선택 %2\",\n                robotis_RB_cm_anim_screen: \"제어기 화면 애니메이션을 알쥐 %1 로 선택 %2\",\n\n                robotis_RB_car_screen: \"제어기 화면 배경을 알라 %1 로 선택 %2\",\n                robotis_RB_car_anim_screen: \"제어기 화면 애니메이션을 알라 %1 로 선택 %2\",\n            },\n            Blocks: {\n                robotis_white: \"흰색\",\n                robotis_gray: \"회색\",\n                robotis_darkgray: \"진회색\",\n                robotis_black: \"검정\",\n                robotis_purple: \"보라\",\n                robotis_pink: \"분홍색\",\n                robotis_red: \"빨강\",\n                robotis_orange: \"주황\",\n                robotis_brown: \"갈색\",\n                robotis_yellow: \"노랑\",\n                robotis_green: \"초록\",\n                robotis_blue: \"파랑\",\n                robotis_lightblue: \"연파랑\",\n                robotis_darkblue: \"남색\",\n                robotis_left: \"왼쪽\",\n                robotis_center: \"중앙\",\n                robotis_right: \"오른쪽\",\n                robotis_both: \"양쪽\",\n                robotis_korean1: \"안녕하세요\",\n                robotis_korean2: \"반가워요\",\n                robotis_korean3: \"알겠어요\",\n                robotis_korean4: \"아니에요\",\n                robotis_korean5: \"모르겠어요\",\n                robotis_korean6: \"좋아요\",\n                robotis_korean7: \"싫어요\",\n                robotis_korean8: \"이름을말하세요\",\n                robotis_korean9: \"무엇을도와줄까?\",\n                robotis_korean10: \"잘했어\",\n                robotis_korean11: \"괜찮아\",\n                robotis_korean12: \"다시해보자\",\n                robotis_korean13: \"고마워\",\n                robotis_korean14: \"다시말해줄래?\",\n                robotis_korean15: \"최고야!\",\n                robotis_korean16: \"신나요\",\n                robotis_korean17: \"즐거워요\",\n                robotis_korean18: \"미안해요\",\n                robotis_korean19: \"화나요\",\n                robotis_korean20: \"부끄러워요\",\n                robotis_korean21: \"무서워요\",\n                robotis_korean22: \"속상해요\",\n                robotis_korean23: \"사랑해요\",\n                robotis_korean24: \"예뻐요\",\n                robotis_korean25: \"신기해요\",\n                robotis_korean26: \"초조해요\",\n                robotis_korean27: \"앞으로가자\",\n                robotis_korean28: \"뒤로가자\",\n                robotis_korean29: \"일어나자\",\n                robotis_korean30: \"넘어졌네?\",\n                robotis_korean31: \"오예\",\n                robotis_korean32: \"아싸\",\n                robotis_korean33: \"어머\",\n                robotis_korean34: \"이런\",\n                robotis_korean35: \"오호\",\n                robotis_korean36: \"하하하\",\n                robotis_korean37: \"호호호\",\n                robotis_korean38: \"졸려\",\n                robotis_korean39: \"자장가를들려줘\",\n                robotis_korean40: \"안녕\",\n                robotis_korean41: \"배고프다\",\n                robotis_korean42: \"도토리땡긴다\",\n                robotis_korean43: \"아.씻고싶어\",\n                robotis_korean44: \"비누목욕시간이야\",\n                robotis_korean45: \"심심한데\",\n                robotis_korean46: \"간식먹을까\",\n                robotis_korean47: \"아파요\",\n                robotis_korean48: \"약은없나요?\",\n                robotis_korean49: \"어디로가야하지?\",\n                robotis_korean50: \"와아도착이다\",\n                robotis_korean51: \"왼쪽으로가자\",\n                robotis_korean52: \"오른쪽으로가자\",\n                robotis_korean53: \"깜짝이야\",\n                robotis_korean54: \"찾았다\",\n                robotis_korean55: \"여긴없네\",\n                robotis_korean56: \"혹시나불렀어?\",\n                robotis_korean57: \"내려주세요\",\n                robotis_korean58: \"앗\",\n                robotis_korean59: \"힝\",\n                robotis_korean60: \"이익\",\n                robotis_dog: \"개\",\n                robotis_frog: \"개구리\",\n                robotis_cat: \"고양이\",\n                robotis_chicken: \"닭\",\n                robotis_tiger: \"호랑이\",\n                robotis_mouse: \"쥐\",\n                robotis_ambul: \"앰뷸런스\",\n                robotis_Horn: \"경적(빵빵)\",\n                robotis_siren: \"사이렌(경찰차)\",\n                robotis_whistle: \"호루라기\",\n                robotis_gun: \"총소리\",\n                robotis_clap: \"박수소리\",\n                robotis_melody1: \"멜로디1\",\n                robotis_melody2: \"멜로디2\",\n                robotis_melody3: \"멜로디3\",\n                robotis_melody4: \"멜로디4\",\n                robotis_forward: \"앞으로\",\n                robotis_backward: \"뒤로\",\n                robotis_acceleration: \"가속도\",\n                robotis_gyro: \"자이로\",\n                robotis_run: \"실행\",\n                robotis_cancel: \"취소\",\n                robotis_push: \"눌림\",\n                robotis_notPush: \"안눌림\",\n                robotis_play: \"연주\",\n                robotis_rest: \"쉼표\",\n                robotis_face01: \"와하하\",\n                robotis_face02: \"싱글벙글\",\n                robotis_face03: \"큭큭큭\",\n                robotis_face04: \"냠냠\",\n                robotis_face05: \"겁먹음\",\n                robotis_face06: \"답답\",\n                robotis_face07: \"갸우뚱\",\n                robotis_face08: \"어벙벙\",\n                robotis_face09: \"고함\",\n                robotis_face10: \"화남\",\n                robotis_face11: \"킁킁(왼쪽)\",\n                robotis_face12: \"킁킁(오른쪽)\",\n                robotis_face13: \"킁킁(아래)\",\n                robotis_face14: \"안심\",\n                robotis_face15: \"기절\",\n                robotis_face16: \"헤롱헤롱\",\n                robotis_face17: \"하품\",\n                robotis_face18: \"졸림\",\n                robotis_face19: \"잠듦\",\n                robotis_face20: \"마음앓이\",\n                robotis_face21: \"폭풍눈물\",\n                robotis_face22: \"목욕\",\n                robotis_face23: \"햐트뿅뿅\",\n\n                robotis_car_anim01: \"기본 표정\",\n                robotis_car_anim02: \"감동\",\n                robotis_car_anim03: \"미소\",\n                robotis_car_anim04: \"웃음\",\n                robotis_car_anim05: \"기쁨\",\n                robotis_car_anim06: \"행복\",\n                robotis_car_anim07: \"자신감\",\n                robotis_car_anim08: \"화남\",\n                robotis_car_anim09: \"우울\",\n                robotis_car_anim10: \"슬픔\",\n                robotis_car_anim11: \"고통\",\n                robotis_car_anim12: \"기절\",\n                robotis_car_anim13: \"공포\",\n                robotis_car_anim14: \"하품\",\n                robotis_car_anim15: \"졸림\",\n                robotis_car_anim16: \"오른쪽보기\",\n                robotis_car_anim17: \"왼쪽보기\",\n                robotis_car_anim18: \"앞쪽보기\",\n                robotis_car_anim19: \"깜짝놀람\",\n\n                robotis_flashing1: \"점멸1\",\n                robotis_flashing2: \"점멸2\",\n                robotis_flashing3: \"점멸3\",\n                robotis_flashing4: \"점멸4\",\n                robotis_flashing5: \"점멸5\",\n                robotis_flashing6: \"점멸6\",\n                robotis_flashing7: \"점멸7\",\n                robotis_flashing8: \"점멸8\",\n                robotis_flashing9: \"점멸9\",\n                robotis_moveF: \"전진\",\n                robotis_moveB: \"후진\",\n                robotis_moveL: \"좌회전\",\n                robotis_moveR: \"우회전\",\n                robotis_moveRG1: \"일어서기\",\n                robotis_moveRG2: \"앉기\",\n                robotis_moveRG3: \"발버둥\",\n                robotis_moveRG4: \"발들기\",\n                robotis_stMotion1: \"기본자세\",\n                robotis_stMotion2: \"전진\",\n                robotis_stMotion3: \"우전진\",\n                robotis_stMotion4: \"좌전진\",\n                robotis_stMotion5: \"후진\",\n                robotis_stMotion6: \"오른쪽으로\",\n                robotis_stMotion7: \"왼쪽으로\",\n                robotis_stMotion8: \"우회전\",\n                robotis_stMotion9: \"좌회전\",\n                robotis_spMotion1: \"오른손 들기\",\n                robotis_spMotion2: \"오른손 내리기\",\n                robotis_spMotion3: \"왼손 들기\",\n                robotis_spMotion4: \"왼손 내리기\",\n                robotis_spMotion5: \"양손 들기\",\n                robotis_spMotion6: \"양손 내리기\",\n                robotis_spMotion7: \"뒤로 넘어지기\",\n                robotis_spMotion8: \"앞으로 넘어지기\",\n                robotis_spMotion9: \"앞으로 일어서기\",\n                robotis_spMotion10: \"뒤로 일어서기\",\n                robotis_spMotion11: \"방어\",\n                robotis_spMotion12: \"공격1\",\n                robotis_spMotion13: \"공격2\",\n                robotis_spMotion14: \"공격3\",\n                robotis_spMotion15: \"공격4\",\n                robotis_screen1: \"가위\",\n                robotis_screen2: \"바위\",\n                robotis_screen3: \"보\",\n                robotis_screen_text_font_small: \"작은 폰트\",\n                robotis_screen_text_font_big: \"큰 폰트\",\n                robotis_sensing_temperature: \"온도센서\",\n                robotis_sensing_humidity: \"습도센서\",\n                robotis_sensing_brightness: \"밝기센서\",\n                robotis_sensing_motion: \"움직임센서\",\n                robotis_sensing_button: \"버튼센서\",\n                robotis_sensing_distance: \"거리센서\",\n                robotis_sensing_ir_left: \"왼쪽 적외선센서\",\n                robotis_sensing_ir_right: \"오른쪽 적외선센서\",\n            },\n        },\n        en: {\n            template: {\n                robotis_RB_cm_ir_value:\"IR sensor value of %1 Value of IR Sensor\",\n                robotis_RB_cm_ir_compare:\"If IR sensor value of %1 is %2 %3\",\n                robotis_RB_detectFrontObj:\"If there is an object in front\",\n                robotis_RB_cm_btn_value:\"If %1 button is %2\",\n                robotis_RB_cm_joystick_value:\"If the joystick location is %1\",\n                robotis_RB_mic:\"MIC volume(dB)\",\n                robotis_RB_detectSound_compare:\"If sound is detected from %1\",\n                robotis_RB_imu:\"%1 axis' %2 value\",\n                robotis_RB_roll_pitch:\"%1 Controller position \",\n                robotis_RB_environment_value: \"%1 %2 value\",\n                robotis_RB_environment_compare: \"If %1 %2 value is %3 %4\",\n                robotis_RB_distance_value: \"%1 %2 value\",\n                robotis_RB_distance_compare: \"If %1 %2 value is %3 %4\",\n                //robotis_RB_detectPose:\"If robot falls %1\",\n                \n                robotis_RB_cm_buzzer_index:\"%1 at %2 octaves for %3 second(s) -> %4 %5\",\n\n                robotis_RB_kkokdu_screen: \"Choose %1 Tiger as a screen background %2\",\n                robotis_RB_kkokdu_anim_screen: \"Choose %1 Tiger as a screen animation %2\",\n\n                robotis_RB_rsp_screen: \"Display %1 on the controller screen at position (%2, %3) with a size of %4 %5\",\n                robotis_RB_text_screen: \"Display %1 on the controller screen at position (%2, %3) with %4 %5 %6\",\n                \n                robotis_RB_LCDBright:\"Adjust screen brightness to %1 %2\",\n                robotis_RB_LCDColor:\"Set screen color to %1 %2\",\n                \n                robotis_RB_LEDBright:\"Set the brightness of the %1 LED to %2 %3\",\n                robotis_RB_cm_led:\"%1 LED %2 %3\",\n                \n                robotis_RB_Hello:\"Say %1 %2\",\n                robotis_RB_effectSound:\"Play the sound of %1 %2\",\n                robotis_RB_record:\"Record in room %1 %2\",\n                robotis_RB_playRecord:\"Play recorded sound in room %1 %2\",\n                robotis_openCM70_RGee_go:\"With %1 velocity, move R-G %2\",\n                robotis_openCM70_RGee_stop:\"R-G STOP\",\n                robotis_openCM70_RGee_motion:\"Do %1 %2 \",\n                \n                robotis_RB_follow_line: \"Follow line with speed level %1 %2\",\n                robotis_RB_follow_line_stop: \"Stop following line %1\",\n\n                robotis_RB_cm_screen:\"Choose %1 R-Gee as a screen background %2\",\n                robotis_RB_cm_anim_screen: \"Choose %1 R-Gee as a screen animation %2\",\n\n                robotis_RB_car_screen: \"Choose %1 R-La as a screen background %2\",\n                robotis_RB_car_anim_screen: \"Choose %1 R-La as a screen animation %2\",\n            },\n            Blocks: {\n                robotis_white: \"White\",\n                robotis_gray: \"Gray\",\n                robotis_darkgray: \"Dark gray\",\n                robotis_black: \"Black\",\n                robotis_purple: \"Purple\",\n                robotis_pink: \"Pink\",\n                robotis_red: \"Red\",\n                robotis_orange: \"Orange\",\n                robotis_brown: \"Brown\",\n                robotis_yellow: \"Yellow\",\n                robotis_green: \"Green\",\n                robotis_blue: \"Blue\",\n                robotis_lightblue: \"Light blue\",\n                robotis_darkblue: \"Dark blue\",\n                robotis_left: \"Left\",\n                robotis_center: \"Center\",\n                robotis_right: \"Right\",\n                robotis_both: \"Both\",\n                robotis_korean1: \"Hello!\",\n                robotis_korean2: \"Great to see you.\",\n                robotis_korean3: \"Okay ~\",\n                robotis_korean4: \"No!\",\n                robotis_korean5: \"I don't know.\",\n                robotis_korean6: \"I like it.\",\n                robotis_korean7: \"I don't like it.\",\n                robotis_korean8: \"What is your name? \",\n                robotis_korean9: \"How can I help you? \",\n                robotis_korean10: \"Great job! \",\n                robotis_korean11: \"It's alright.\",\n                robotis_korean12: \"Let's do it again! \",\n                robotis_korean13: \"Thank you! \",\n                robotis_korean14: \"Can you say that one more time?\",\n                robotis_korean15: \"Awesome!\",\n                robotis_korean16: \"I'm excited! \",\n                robotis_korean17: \"I'm having a great time! \",\n                robotis_korean18: \"I'm sorry.\",\n                robotis_korean19: \"I'm angry! \",\n                robotis_korean20: \"I'm embarassed.\",\n                robotis_korean21: \"I'm scared.\",\n                robotis_korean22: \"I'm upset.\",\n                robotis_korean23: \"I love you.\",\n                robotis_korean24: \"Very pretty! \",\n                robotis_korean25: \"Interesting.\",\n                robotis_korean26: \"I'm nervous.\",\n                robotis_korean27: \"Let's move forward! \",\n                robotis_korean28: \"Let's move backward! \",\n                robotis_korean29: \"Let's stand up! \",\n                robotis_korean30: \"Did you fall down? \",\n                robotis_korean31: \"Oh Yeah~\",\n                robotis_korean32: \"Sweet! \",\n                robotis_korean33: \"Oh no\",\n                robotis_korean34: \"My My \",\n                robotis_korean35: \"Whoo hoo! \",\n                robotis_korean36: \"Ha Ha Ha\",\n                robotis_korean37: \"Ho Ho Ho \",\n                robotis_korean38: \"I'm sleepy.\",\n                robotis_korean39: \"Sing me a bedtime song! \",\n                robotis_korean40: \"Hello!\",\n                robotis_korean41: \"I'm hungry.\",\n                robotis_korean42: \"I'm craving an acorn! \",\n                robotis_korean43: \"I want to take a bath! \",\n                robotis_korean44: \"Time for a bath! \",\n                robotis_korean45: \"I'm bored. \",\n                robotis_korean46: \"Do you want a snack? \",\n                robotis_korean47: \"I'm sick.\",\n                robotis_korean48: \"Do you have any medicine? \",\n                robotis_korean49: \"Where do we have to go? \",\n                robotis_korean50: \"We're here! \",\n                robotis_korean51: \"Let's go to the left side! \",\n                robotis_korean52: \"Let's go to the right side! \",\n                robotis_korean53: \"Oh my, you scared me! \",\n                robotis_korean54: \"Found you! \",\n                robotis_korean55: \"There's nothing here. \",\n                robotis_korean56: \"Did you call me?\",\n                robotis_korean57: \"Please let me down. \",\n                robotis_korean58: \"Oops! \",\n                robotis_korean59: \"Hmmph! \",\n                robotis_korean60: \"Eek! \",\n                robotis_dog: \"Dog\",\n                robotis_frog: \"Frog\",\n                robotis_cat: \"Cat\",\n                robotis_chicken: \"Rooster\",\n                robotis_tiger: \"Tiger\",\n                robotis_mouse: \"Mouse\",\n                robotis_ambul: \"Ambulance\",\n                robotis_Horn: \"CarHorn\",\n                robotis_siren: \"Siren\",\n                robotis_whistle: \"Whistle\",\n                robotis_gun: \"Gunshot\",\n                robotis_clap: \"Clap\",\n                robotis_melody1: \"Melody1\",\n                robotis_melody2: \"Melody2\",\n                robotis_melody3: \"Melody3\",\n                robotis_melody4: \"Melody4\",\n                robotis_forward: \"Forward\",\n                robotis_backward: \"Backward\",\n                robotis_acceleration: \"acceleration\",\n                robotis_gyro: \"gyro\",\n                robotis_run: \"Run\",\n                robotis_cancel: \"Cancel\",\n                robotis_push: \"Pressed\",\n                robotis_notPush: \"Unpressed\",\n                robotis_play: \"Play\",\n                robotis_rest: \"Rest\",\n                robotis_face01: \"Haha\",\n                robotis_face02: \"Smile\",\n                robotis_face03: \"Laugh\",\n                robotis_face04: \"Yum Yum\",\n                robotis_face05: \"Scared\",\n                robotis_face06: \"Uncomfortable\",\n                robotis_face07: \"Confused\",\n                robotis_face08: \"Dazed\",\n                robotis_face09: \"Yell\",\n                robotis_face10: \"Angry\",\n                robotis_face11: \"Sniff (Left)\",\n                robotis_face12: \"Sniff (Right)\",\n                robotis_face13: \"Sniff (Down)\",\n                robotis_face14: \"Whew\",\n                robotis_face15: \"Faint\",\n                robotis_face16: \"Dizzy\",\n                robotis_face17: \"Yawn\",\n                robotis_face18: \"Sleepy\",\n                robotis_face19: \"Sleep\",\n                robotis_face20: \"Sad\",\n                robotis_face21: \"Cry\",\n                robotis_face22: \"Bath\",\n                robotis_face23: \"Heart-Eyes\",\n\n                robotis_car_anim01: \"anim01\",\n                robotis_car_anim02: \"anim02\",\n                robotis_car_anim03: \"anim03\",\n                robotis_car_anim04: \"anim04\",\n                robotis_car_anim05: \"anim05\",\n                robotis_car_anim06: \"anim06\",\n                robotis_car_anim07: \"anim07\",\n                robotis_car_anim08: \"anim08\",\n                robotis_car_anim09: \"anim09\",\n                robotis_car_anim10: \"anim10\",\n                robotis_car_anim11: \"anim11\",\n                robotis_car_anim12: \"anim12\",\n                robotis_car_anim13: \"anim13\",\n                robotis_car_anim14: \"anim14\",\n                robotis_car_anim15: \"anim15\",\n                robotis_car_anim16: \"anim16\",\n                robotis_car_anim17: \"anim17\",\n                robotis_car_anim18: \"anim18\",\n                robotis_car_anim19: \"anim19\",\n\n                robotis_flashing1: \"Flashing1\",\n                robotis_flashing2: \"Flashing2\",\n                robotis_flashing3: \"Flashing3\",\n                robotis_flashing4: \"Flashing4\",\n                robotis_flashing5: \"Flashing5\",\n                robotis_flashing6: \"Flashing6\",\n                robotis_flashing7: \"Flashing7\",\n                robotis_flashing8: \"Flashing8\",\n                robotis_flashing9: \"Flashing9\",\n                robotis_moveF: \"Forward\",\n                robotis_moveB: \"Backward\",\n                robotis_moveL: \"LeftTurn\",\n                robotis_moveR: \"RightTurn\",\n                robotis_moveRG1: \"Stand\",\n                robotis_moveRG2: \"Sit\",\n                robotis_moveRG3: \"Struggle\",\n                robotis_moveRG4: \"RaiseFeet\",\n                robotis_stMotion1: \"Standard\",\n                robotis_stMotion2: \"Forward\",\n                robotis_stMotion3: \"TurnRight\",\n                robotis_stMotion4: \"TurnLeft\",\n                robotis_stMotion5: \"Backward\",\n                robotis_stMotion6: \"ToRight\",\n                robotis_stMotion7: \"ToLeft\",\n                robotis_stMotion8: \"TurnAroundRight\",\n                robotis_stMotion9: \"TurnAroundLeft\",\n                robotis_spMotion1: \"RightHandUp\",\n                robotis_spMotion2: \"RightHandDown\",\n                robotis_spMotion3: \"LeftHandUp\",\n                robotis_spMotion4: \"LeftHandDown\",\n                robotis_spMotion5: \"BothHandsUp\",\n                robotis_spMotion6: \"BothHandsDown\",\n                robotis_spMotion7: \"FallBackward\",\n                robotis_spMotion8: \"FallForward\",\n                robotis_spMotion9: \"StandForward\",\n                robotis_spMotion10: \"StandBackward\",\n                robotis_spMotion11: \"Defence\",\n                robotis_spMotion12: \"Offense1\",\n                robotis_spMotion13: \"Offense2\",\n                robotis_spMotion14: \"Offense3\",\n                robotis_spMotion15: \"Offense4\",\n                robotis_screen1: \"Sissor\",\n                robotis_screen2: \"Rock\",\n                robotis_screen3: \"Paper\",\n                robotis_screen_text_font_small: \"small font\",\n                robotis_screen_text_font_big: \"big font\",\n                robotis_sensing_temperature: \"Temperature\",\n                robotis_sensing_humidity: \"Humidity\",\n                robotis_sensing_brightness: \"Brightness\",\n                robotis_sensing_motion: \"Motion\",\n                robotis_sensing_button: \"Button\",\n                robotis_sensing_distance: \"Distance\",\n                robotis_sensing_ir_left: \"Left IR\",\n                robotis_sensing_ir_right: \"Right IR\",\n                \n            },\n        }\n    }\n};\n\nlet rb100_last_valid_value = [];\n\nEntry.Robotis_rb.getBlocks = function () {\n    return {\n        //region robotis 로보티즈 openCM70\n        robotis_RB_rsp_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_screen1, '11545'],\n                        [Lang.Blocks.robotis_screen2, '11546'],\n                        [Lang.Blocks.robotis_screen3, '11547'],\n                        ['0', '11283'],\n                        ['1', '11284'],\n                        ['2', '11285'],\n                        ['3', '11286'],\n                        ['4', '11287'],\n                        ['5', '11288'],\n                        ['6', '11289'],\n                        ['7', '11290'],\n                        ['8', '11291'],\n                        ['9', '11292'],\n                        ['10', '11293'],\n                    ],\n                    value: '11545',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    100,\n                    null,\n                ],\n                type: 'robotis_RB_rsp_screen',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    // [\n                    //     Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 2817\n                    // ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 255\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_rsp_screen(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RB_text_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_screen_text_font_small, '0'],\n                        [Lang.Blocks.robotis_screen_text_font_big, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \" \",\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'robotis_RB_text_screen',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                X: 1,\n                Y: 2,\n                FONT: 3,\n                COLOR: 4,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var text = script.getStringValue('TEXT', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var font = script.getNumberValue('FONT', script);\n                var color = script.getNumberValue('COLOR', script);\n                var data_buf = [];\n                var i = 0;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                var encoder = new TextEncoder('utf-8');\n                var byteArray = encoder.encode(text);\n\n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(font);\n                data_buf.push(color);\n                data_buf.push(byteArray.length);\n                for (i = 0; i < byteArray.length; i++) {\n                    data_buf.push(byteArray[i]);\n                }\n               \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 900;\n                var data_length = 7 + byteArray.length;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_text_screen(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RB_cm_custom_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['BYTE', 'BYTE'],\n                        ['WORD', 'WORD'],\n                        ['DWORD', 'DWORD'],\n                    ],\n                    value: 'BYTE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RB_cm_custom_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                SIZE: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var size = script.getStringField('SIZE');\n\n                if (size == 'BYTE') {\n                    data_length = 1;\n                } else if (size == 'WORD') {\n                    data_length = 2;\n                } else if (size == 'DWORD') {\n                    data_length = 4;\n                }\n\n                data_address = script.getNumberValue('VALUE');\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_custom_value(%1, %2)'],\n            },\n        },\n        robotis_RB_cm_custom_value2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['BYTE', 'BYTE'],\n                        ['WORD', 'WORD'],\n                        ['DWORD', 'DWORD'],\n                    ],\n                    value: 'BYTE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RB_cm_custom_value2',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                SIZE: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_H'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                var size = script.getStringField('SIZE');\n\n                if (size == 'BYTE') {\n                    data_length = 1;\n                } else if (size == 'WORD') {\n                    data_length = 2;\n                } else if (size == 'DWORD') {\n                    data_length = 4;\n                }\n\n                data_address = script.getNumberValue('VALUE');\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_custom_value(%1, %2)'],\n            },\n        },\n        robotis_RB_cm_ir_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '360'],\n                        ['2', '362'],\n                        ['3', '364'],\n                        ['4', '366'],\n                        ['5', '368'],\n                        ['6', '370'],\n                    ],\n                    value: '360',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_RB_cm_ir_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                \n                data_address = script.getNumberValue('VALUE');\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_ir_value(%1)'],\n            },\n        },\n        robotis_RB_cm_ir_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '360'],\n                        ['2', '362'],\n                        ['3', '364'],\n                        ['4', '366'],\n                        ['5', '368'],\n                        ['6', '370'],\n                    ],\n                    value: '360',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['>', '0'],\n                        ['<', '1'],\n                        ['=', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    200\n                ],\n                type: 'robotis_RB_cm_ir_compare',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                COMPARE_OP: 1,\n                COMPARE_VAL: 2,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n\n                data_address = script.getNumberValue('VALUE');\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < 200//Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                \n                        //  return false;\n                        switch(compareOP) {\n                            case 0:\n                                return Entry.hw.sendQueue.prevResult > compareValue;\n                            case 1:\n                                return Entry.hw.sendQueue.prevResult < compareValue;\n                            case 2:\n                                return Entry.hw.sendQueue.prevResult == compareValue;\n                            default:\n                                return false;\n                        }\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                \n                \n                Entry.Robotis_carCont.update();\n\n                \n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                    default:\n                        return false;\n                }\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_ir_compare(%1)'],\n            },\n        },\n        robotis_RB_LCDBright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_LCDBright',\n            },\n            paramsKeyMap: {\n                BRIGHT: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var bright = script.getNumberValue('BRIGHT', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 180;\n                var data_length = 1;\n                var data_value = 0;\n                \n                data_value = bright;\n                \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_LCDBright(%1)'],\n            },\n        },\n        robotis_RB_LCDColor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '224',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_LCDColor',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var color = script.getField('COLOR', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = 0;\n                \n                data_value = color;\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 2817\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [3, 162, 1, 1]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_LCDColor(%1)'],\n            },\n        },\n        robotis_RB_detectSound_compare:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '1'],\n                        [Lang.Blocks.robotis_center, '0'],\n                        [Lang.Blocks.robotis_right, '255'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_detectSound_compare',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 5031;\n                var data_length = 1;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                var compareValue = script.getNumberValue('VALUE');\n\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n\n                        // return false;\n                        return Entry.hw.sendQueue.prevResult == compareValue;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(result == undefined) {\n                    return false;\n                }\n\n\n                return result == compareValue;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_detectSound_compare(%1)'],\n            },\n        },\n        robotis_RB_LEDBright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, 'RB_LED_L'],\n                        [Lang.Blocks.robotis_right, 'RB_LED_R'],\n                        [Lang.Blocks.robotis_both, 'RB_LED_B'],\n                    ],\n                    value: 'RB_LED_L',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: [100]\n                    }\n                ],\n                type: 'robotis_RB_LEDBright',\n            },\n            paramsKeyMap: {\n                CMLED: 0,\n                BRIGHT: 1,\n            },\n            class: 'robotis_rb100_led',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmLed = script.getField('CMLED', script);\n                var bright = script.getNumberValue('BRIGHT', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 0;\n                var data_length = 1;\n                var data_value = 0;\n            \n                if(bright < 0){ \n                    bright = 0;\n                } else if(bright > 100) {\n                    bright = 100\n                }\n                data_value = 100+bright;\n            \n\n                if (cmLed == 'RB_LED_L') {\n                    data_address =\n                        Entry.Robotis_rb.CONTROL_TABLE.RB_LED_L[0];\n                    data_length =\n                        Entry.Robotis_rb.CONTROL_TABLE.RB_LED_L[1];\n                } else if (cmLed == 'RB_LED_R') {\n                    data_address =\n                        Entry.Robotis_rb.CONTROL_TABLE.RB_LED_R[0];\n                    data_length =\n                        Entry.Robotis_rb.CONTROL_TABLE.RB_LED_R[1];\n                } else if (cmLed == 'RB_LED_B') {\n                    data_address =\n                        Entry.Robotis_rb.CONTROL_TABLE.RB_LED_B[0];\n                    data_length =\n                        Entry.Robotis_rb.CONTROL_TABLE.RB_LED_B[1];\n                    if(bright != 0){\n                        data_value = 257*(bright+100);\n                    }\n                }\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_LEDBright(%1, %2)'],\n            },\n        },\n        robotis_RB_Hello: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_korean1,'0'],\n                        [Lang.Blocks.robotis_korean2,'1'],\n                        [Lang.Blocks.robotis_korean3,'2'],\n                        [Lang.Blocks.robotis_korean4,'3'],\n                        [Lang.Blocks.robotis_korean5,'4'],\n                        [Lang.Blocks.robotis_korean6,'5'],\n                        [Lang.Blocks.robotis_korean7,'6'],\n                        [Lang.Blocks.robotis_korean8,'7'],\n                        [Lang.Blocks.robotis_korean9,'8'],\n                        [Lang.Blocks.robotis_korean10,'9'],\n                        [Lang.Blocks.robotis_korean11,'10'],\n                        [Lang.Blocks.robotis_korean12,'11'],\n                        [Lang.Blocks.robotis_korean13,'12'],\n                        [Lang.Blocks.robotis_korean14,'13'],\n                        [Lang.Blocks.robotis_korean15,'14'],\n                        [Lang.Blocks.robotis_korean16,'15'],\n                        [Lang.Blocks.robotis_korean17,'16'],\n                        [Lang.Blocks.robotis_korean18,'17'],\n                        [Lang.Blocks.robotis_korean19,'18'],\n                        [Lang.Blocks.robotis_korean20,'19'],\n                        [Lang.Blocks.robotis_korean21,'20'],\n                        [Lang.Blocks.robotis_korean22,'21'],\n                        [Lang.Blocks.robotis_korean23,'22'],\n                        [Lang.Blocks.robotis_korean24,'23'],\n                        [Lang.Blocks.robotis_korean25,'24'],\n                        [Lang.Blocks.robotis_korean26,'25'],\n                        [Lang.Blocks.robotis_korean27,'26'],\n                        [Lang.Blocks.robotis_korean28,'27'],\n                        [Lang.Blocks.robotis_korean29,'28'],\n                        [Lang.Blocks.robotis_korean30,'29'],\n                        [Lang.Blocks.robotis_korean31,'30'],\n                        [Lang.Blocks.robotis_korean32,'31'],\n                        [Lang.Blocks.robotis_korean33,'32'],\n                        [Lang.Blocks.robotis_korean34,'33'],\n                        [Lang.Blocks.robotis_korean35,'34'],\n                        [Lang.Blocks.robotis_korean36,'35'],\n                        [Lang.Blocks.robotis_korean37,'36'],\n                        [Lang.Blocks.robotis_korean38,'37'],\n                        [Lang.Blocks.robotis_korean39,'38'],\n                        [Lang.Blocks.robotis_korean40,'39'],\n                        [Lang.Blocks.robotis_korean41,'40'],\n                        [Lang.Blocks.robotis_korean42,'41'],\n                        [Lang.Blocks.robotis_korean43,'42'],\n                        [Lang.Blocks.robotis_korean44,'43'],\n                        [Lang.Blocks.robotis_korean45,'44'],\n                        [Lang.Blocks.robotis_korean46,'45'],\n                        [Lang.Blocks.robotis_korean47,'46'],\n                        [Lang.Blocks.robotis_korean48,'47'],\n                        [Lang.Blocks.robotis_korean49,'48'],\n                        [Lang.Blocks.robotis_korean50,'49'],\n                        [Lang.Blocks.robotis_korean51,'50'],\n                        [Lang.Blocks.robotis_korean52,'51'],\n                        [Lang.Blocks.robotis_korean53,'52'],\n                        [Lang.Blocks.robotis_korean54,'53'],\n                        [Lang.Blocks.robotis_korean55,'54'],\n                        [Lang.Blocks.robotis_korean56,'55'],\n                        [Lang.Blocks.robotis_korean57,'56'],\n                        [Lang.Blocks.robotis_korean58,'57'],\n                        [Lang.Blocks.robotis_korean59,'58'],\n                        [Lang.Blocks.robotis_korean60,'59'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_Hello',\n            },\n            paramsKeyMap: {\n                HELLO: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmHello = script.getField('HELLO', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 110;\n                var data_length = 2;\n                var data_value = 0;\n            \n               \n                data_value = 25601+Number(cmHello);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        data_instruction,\n                        0,\n                        2,\n                        0\n                    ]\n                ];\n\n\n                let extraTime = 0; \n                \n                if(cmHello == '38' || cmHello == '55') {\n                    extraTime = 2000;\n                }\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    2000 + extraTime\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_Hello(%1)'],\n            },\n        },\n        robotis_RB_effectSound:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_dog, '0'],\n                        [Lang.Blocks.robotis_frog, '1'],\n                        [Lang.Blocks.robotis_cat, '2'],\n                        [Lang.Blocks.robotis_chicken, '7'],\n                        [Lang.Blocks.robotis_tiger, '19'],\n                        [Lang.Blocks.robotis_mouse, '17'],\n\n                        [Lang.Blocks.robotis_ambul, '773'],\n                        [Lang.Blocks.robotis_Horn, '781'],\n                        [Lang.Blocks.robotis_siren, '774'],\n                        [Lang.Blocks.robotis_whistle, '274'],\n                        [Lang.Blocks.robotis_gun, '775'],\n                        [Lang.Blocks.robotis_clap, '260'],\n\n                        [Lang.Blocks.robotis_melody1, '786'],\n                        [Lang.Blocks.robotis_melody2, '787'],\n                        [Lang.Blocks.robotis_melody3, '788'],\n                        [Lang.Blocks.robotis_melody4, '789'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_effectSound',\n            },\n            paramsKeyMap: {\n                HELLO: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmHello = script.getField('HELLO', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 110;\n                var data_length = 2;\n                var data_value = 0;\n            \n               \n                data_value = Number(cmHello);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        data_instruction,\n                        0,\n                        2,\n                        0\n                    ]\n                ];\n                \n                let extraTime = 0;\n                if(cmHello == '272' || cmHello == '786' || cmHello == '787' || cmHello == '788' || cmHello == '789') { //오리\n                    extraTime = 0;\n                    if(cmHello == '788' || cmHello == '789') {\n                        extraTime += 500;\n                    }\n                }\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    3000 + extraTime\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_Hello(%1)'],\n            },\n        },\n        robotis_RB_record:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_record',\n            },\n            paramsKeyMap: {\n                ROOM: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var roomNum = script.getField('ROOM', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 115;\n                var data_length = 1;\n                var data_value = 0;\n            \n               \n                data_value = roomNum;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    6000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_record(%1)'],\n            },\n        },\n        robotis_RB_playRecord:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_playRecord',\n            },\n            paramsKeyMap: {\n                ROOM: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var roomNum = script.getField('ROOM', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 116;\n                var data_length = 1;\n                var data_value = 0;\n            \n               \n                data_value = roomNum;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    6000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_playRecord(%1)'],\n            },\n        },\n        robotis_RB_detectFrontObj:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                \n            ],\n            events: {},\n            def: {\n                params: [\n                  \n                ],\n                type: 'robotis_RB_detectFrontObj',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 360;\n                var data_length = 4;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                var compareValue = script.getNumberValue('VALUE');\n\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        // return false;\n                        let ir_1 = Entry.hw.sendQueue.prevResult & 0xffff;\n                        let ir_2 =  Entry.hw.sendQueue.prevResult >> 16;\n                        \n                        return ir_1 > 100 || ir_2 > 100//Entry.hw.sendQueue.prevResult// > 10000000;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(result == undefined) {\n                    return false;\n                }\n\n\n                let ir_1 = Entry.hw.sendQueue.prevResult & 0xffff;\n                let ir_2 =  Entry.hw.sendQueue.prevResult >> 16;\n                \n\n                return ir_1 > 100 || ir_2 > 100\n                return result// > 10000000;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_detectFrontObj()'],\n            },\n        },\n        /*\n        robotis_RB_detectPose:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_forward, '1'],//72\n                        [Lang.Blocks.robotis_backward, '2'],//74\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                  null\n                ],\n                type: 'robotis_RB_detectPose',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_H'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 78;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                var compareValue = script.getNumberValue('VALUE');\n\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        // return false;\n                        switch(compareValue) {\n                            case 1:\n                                return Entry.hw.sendQueue.prevResult > 30;\n                            case 2:\n                                return Entry.hw.sendQueue.prevResult < -30;\n                        }                        \n\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                switch(compareValue) {\n                    case 1:\n                        return result > 30;\n                    case 2:\n                        return result < -30;\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_detectFrontObj()'],\n            },\n        },*/\n        robotis_RB_mic:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_RB_mic',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 1;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                \n                data_address = 119;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_mic()'],\n            },\n        },\n        robotis_RB_imu:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', '78'],//72\n                        ['y', '80'],//74\n                        ['z', '82']//76\n                    ],\n                    value: '78',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_acceleration, '0'],//72\n                        [Lang.Blocks.robotis_gyro, '6'],//74\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_RB_imu',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n                MODE: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                \n                data_address = script.getField('AXIS', script) - script.getField('MODE', script);\n                \n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n                    \n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_imu()'],\n            },\n        },\n        robotis_RB_roll_pitch:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['Roll', '70'],//72\n                        ['Pitch', '88'],//74\n                    ],\n                    value: '70',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_roll_pitch',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                \n                data_address = script.getNumberValue('AXIS');\n                \n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_roll_pitch(%1)'],\n            },\n        },\n        /*\n        robotis_RB_environment_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID 100', '100'],\n                        ['ID 101', '101'],\n                        ['ID 102', '102'],\n                        ['ID 103', '103'],\n                        ['ID 104', '104'],\n                    ],\n                    value: '100',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_temperature, '28'],\n                        [Lang.Blocks.robotis_sensing_humidity, '29'],\n                        [Lang.Blocks.robotis_sensing_brightness, '30'],\n                        [Lang.Blocks.robotis_sensing_motion, '27'],\n                    ],\n                    value: '28',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_RB_environment_value',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                ADDR: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: [],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_READ;\n                var data_address = 0;\n                var data_length = 1;\n                var data_value = script.getNumberValue('ID');;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                \n                data_address = script.getNumberValue('ADDR');\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                // 통합센서의 컨트롤 테이블 주소는 RB-100블록에서 사용하지 않는 주소를 사용\n                // 주소 겹침 방지\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_environment_value(%1)'],\n            },\n        },\n        robotis_RB_environment_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID 100', '100'],\n                        ['ID 101', '101'],\n                        ['ID 102', '102'],\n                        ['ID 103', '103'],\n                        ['ID 104', '104'],\n                    ],\n                    value: '100',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_temperature, '28'],\n                        [Lang.Blocks.robotis_sensing_humidity, '29'],\n                        [Lang.Blocks.robotis_sensing_brightness, '30'],\n                        [Lang.Blocks.robotis_sensing_motion, '27'],\n                    ],\n                    value: '28',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['>', '0'],\n                        ['<', '1'],\n                        ['=', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 'asdfasdf',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: [0]\n                    }\n                ],\n                type: 'robotis_RB_environment_compare',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                ADDR: 1,\n                COMPARE_OP: 2,\n                COMPARE_VAL: 3,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: [],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_READ;\n                var data_address = 0;\n                var data_length = 1;\n                var data_id = script.getNumberValue('ID');\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n\n                data_address = script.getNumberValue('ADDR');\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < 200//Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                \n                        //  return false;\n                        switch(compareOP) {\n                            case 0:\n                                return Entry.hw.sendQueue.prevResult > compareValue;\n                            case 1:\n                                return Entry.hw.sendQueue.prevResult < compareValue;\n                            case 2:\n                                return Entry.hw.sendQueue.prevResult == compareValue;\n                            default:\n                                return false;\n                        }\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_id,\n                        data_default_length,\n                    ],\n                ]);\n                \n                \n                Entry.Robotis_carCont.update();\n\n                \n                // 통합센서의 컨트롤 테이블 주소는 RB-100블록에서 사용하지 않는 주소를 사용\n                // 주소 겹침 방지\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                    default:\n                        return false;\n                }\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_environment_compare(%1)'],\n            },\n        },\n        robotis_RB_distance_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID 110', '110'],\n                        ['ID 111', '111'],\n                        ['ID 112', '112'],\n                        ['ID 113', '113'],\n                        ['ID 114', '114'],\n                    ],\n                    value: '110',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_distance, '25'],\n                        [Lang.Blocks.robotis_sensing_button, '24'],\n                        [Lang.Blocks.robotis_sensing_ir_left, '31'],\n                        [Lang.Blocks.robotis_sensing_ir_right, '33'],\n                    ],\n                    value: '25',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_RB_distance_value',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                ADDR: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: [],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_value = script.getNumberValue('ID');;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                \n                data_address = script.getNumberValue('ADDR');\n\n                if (data_address == 24) data_length = 1;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                // 통합센서의 컨트롤 테이블 주소는 RB-100블록에서 사용하지 않는 주소를 사용\n                // 주소 겹침 방지\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_distance_value(%1)'],\n            },\n        },\n        robotis_RB_distance_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['ID 110', '110'],\n                        ['ID 111', '111'],\n                        ['ID 112', '112'],\n                        ['ID 113', '113'],\n                        ['ID 114', '114'],\n                    ],\n                    value: '110',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_distance, '25'],\n                        [Lang.Blocks.robotis_sensing_button, '24'],\n                        [Lang.Blocks.robotis_sensing_ir_left, '31'],\n                        [Lang.Blocks.robotis_sensing_ir_right, '33'],\n                    ],\n                    value: '25',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['>', '0'],\n                        ['<', '1'],\n                        ['=', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 'asdfasdf',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'number',\n                        params: [0]\n                    }\n                ],\n                type: 'robotis_RB_distance_compare',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                ADDR: 1,\n                COMPARE_OP: 2,\n                COMPARE_VAL: 3,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: [],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_id = script.getNumberValue('ID');\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n\n                data_address = script.getNumberValue('ADDR');\n\n                if (data_address == 24) data_length = 1;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < 200//Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                \n                        //  return false;\n                        switch(compareOP) {\n                            case 0:\n                                return Entry.hw.sendQueue.prevResult > compareValue;\n                            case 1:\n                                return Entry.hw.sendQueue.prevResult < compareValue;\n                            case 2:\n                                return Entry.hw.sendQueue.prevResult == compareValue;\n                            default:\n                                return false;\n                        }\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_id,\n                        data_default_length,\n                    ],\n                ]);\n                \n                \n                Entry.Robotis_carCont.update();\n\n                \n                // 통합센서의 컨트롤 테이블 주소는 RB-100블록에서 사용하지 않는 주소를 사용\n                // 주소 겹침 방지\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                    default:\n                        return false;\n                }\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_distance_compare(%1)'],\n            },\n        },*/\n        robotis_RB_cm_joystick_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [ \n                        [Lang.Blocks.robotis_center, '0'],\n                        ['←', '1'],\n                        ['→', '2'],\n                        ['↑', '3'],\n                        ['↓', '4'],\n                        ['↖', '5'],\n                        ['↗', '6'],\n                        ['↙', '7'],\n                        ['↘', '8'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_RB_cm_joystick_value',\n            },\n            paramsKeyMap: {\n                COMPARE_VAL: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 1;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                \n                data_address = 50;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                var compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < 200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                         \n                        return (Entry.hw.sendQueue.prevResult == compareValue);\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n                \n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.openCM70_cm_joystick_value()'],\n            },\n        },\n        robotis_RB_cm_btn_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_run, '45'],\n                        [Lang.Blocks.robotis_cancel, '42'],\n                    ],\n                    value: '45',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_push, '1'],\n                        [Lang.Blocks.robotis_notPush, '0'],\n\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_RB_cm_btn_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                COMPARE_VAL: 1\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 0;\n                var data_length = 1;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n\n                \n                data_address = script.getNumberValue('VALUE');\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < 200\n                    ) {\n                        \n                        //throw new Entry.Utils.AsyncError();\n                        return (Entry.hw.sendQueue.prevResult == compareValue);\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_btn_value(%1)'],\n            },\n        },\n        robotis_RB_cm_buzzer_index: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.General.note_c + '', '37'],\n                        [Lang.General.note_c + '#', '38'],\n                        [Lang.General.note_d + '', '39'],\n                        [Lang.General.note_d + '#', '40'],\n                        [Lang.General.note_e + '', '41'],\n                        [Lang.General.note_f + '', '42'],\n                        [Lang.General.note_f + '#', '43'],\n                        [Lang.General.note_g + '', '44'],\n                        [Lang.General.note_g + '#', '45'],\n                        [Lang.General.note_a + '', '46'],\n                        [Lang.General.note_a + '#', '47'],\n                        [Lang.General.note_b + '', '48'],\n                    ],\n                    value: '47',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', '-1'],\n                        ['4', '0'],\n                        ['5', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_play, '1'],\n                        [Lang.Blocks.robotis_rest, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    '1',\n                    null,\n                    null,\n                ],\n                type: 'robotis_RB_cm_buzzer_index',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_INDEX: 0,\n                CM_BUZZER_OCTAV: 1,\n                CM_BUZZER_DELAY: 2,\n                CM_BUZZER_PLAY: 3\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerIndex = script.getField('CM_BUZZER_INDEX', script);\n                var cmBuzzerOffset = script.getField('CM_BUZZER_OCTAV', script);\n                var cmBuzzerTime = script.getNumberValue('CM_BUZZER_DELAY', script);\n                var cmBuzzerPlay = script.getField('CM_BUZZER_PLAY', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address_1 = 0;\n                var data_length_1 = 0;\n                var data_value_1 = 0;\n                var data_address_2 = 0;\n                var data_length_2 = 0;\n                var data_value_2 = 0;\n                var interval = 500;\n\n                data_address_1 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_BUZZER_TIME[0];\n                data_length_1 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_BUZZER_TIME[1];\n                // data_value_1 = cmBuzzerTime * 10;\n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                data_value_1 = parseInt(cmBuzzerTime * 10);\n                if (data_value_2 < 0) {\n                    data_value_1 = 0;\n                }\n                if (data_value_1 > 50) {\n                    data_value_1 = 50;\n                }\n\n                data_address_2 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_BUZZER_INDEX[0];\n                data_length_2 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_BUZZER_INDEX[1];\n                data_value_2 = Number(cmBuzzerIndex) + Number(cmBuzzerOffset * 12);\n\n                // console.log(\"buzzer send\");\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address_1,\n                        data_length_1,\n                        data_value_1,\n                    ],\n                    [\n                        data_instruction,\n                        data_address_2,\n                        data_length_2,\n                        data_value_2,\n                    ],\n                ];\n\n                if(cmBuzzerPlay == '2') {\n                    data_sendqueue = [];\n                }\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime * 1000+ interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_buzzer_index(%1, %2)'],\n            },\n        }, \n        \n\n        robotis_RB_kkokdu_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_car_anim01, '3585'],\n                        [Lang.Blocks.robotis_car_anim02, '3586'],\n                        [Lang.Blocks.robotis_car_anim03, '3587'],\n                        [Lang.Blocks.robotis_car_anim04, '3588'],\n                        [Lang.Blocks.robotis_car_anim05, '3589'],\n\n                        [Lang.Blocks.robotis_car_anim06, '3590'],\n                        [Lang.Blocks.robotis_car_anim07, '3591'], \n                        [Lang.Blocks.robotis_car_anim08, '3592'],\n                        [Lang.Blocks.robotis_car_anim09, '3593'],\n                        [Lang.Blocks.robotis_car_anim10, '3594'],\n\n                        [Lang.Blocks.robotis_car_anim11, '3595'],\n                        [Lang.Blocks.robotis_car_anim12, '3596'], \n                        [Lang.Blocks.robotis_car_anim13, '3597'],\n                        [Lang.Blocks.robotis_car_anim14, '3598'],\n                        [Lang.Blocks.robotis_car_anim15, '3599'],\n\n                        [Lang.Blocks.robotis_car_anim16, '3600'],\n                        [Lang.Blocks.robotis_car_anim17, '3601'], \n                        [Lang.Blocks.robotis_car_anim18, '3602'],\n                        [Lang.Blocks.robotis_car_anim19, '3603'],\n                    ],\n                    value: '3585',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_RB_kkokdu_screen',\n            },\n            paramsKeyMap: {\n                BACKGROUND: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var screenValue = script.getNumberValue('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [3, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 1000\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_screen(%1)'] },\n        },\n\n        robotis_RB_kkokdu_anim_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_car_anim01, '31234'],\n                        [Lang.Blocks.robotis_car_anim02, '31237'],\n                        [Lang.Blocks.robotis_car_anim03, '31238'],\n                        [Lang.Blocks.robotis_car_anim04, '31239'],\n                        [Lang.Blocks.robotis_car_anim05, '31240'],\n\n                        [Lang.Blocks.robotis_car_anim06, '31241'],\n                        [Lang.Blocks.robotis_car_anim07, '31242'], \n                        [Lang.Blocks.robotis_car_anim08, '31243'],\n                        [Lang.Blocks.robotis_car_anim09, '31244'],\n                        [Lang.Blocks.robotis_car_anim10, '31245'],\n\n                        [Lang.Blocks.robotis_car_anim11, '31246'],\n                        [Lang.Blocks.robotis_car_anim12, '31247'], \n                        [Lang.Blocks.robotis_car_anim13, '31248'],\n                        [Lang.Blocks.robotis_car_anim14, '31249'],\n                        [Lang.Blocks.robotis_car_anim15, '31250'],\n\n                        [Lang.Blocks.robotis_car_anim16, '31251'],\n                        [Lang.Blocks.robotis_car_anim17, '31252'], \n                        [Lang.Blocks.robotis_car_anim18, '31253'],\n                        [Lang.Blocks.robotis_car_anim19, '31254'],\n                    ],\n                    value: '31234',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_RB_kkokdu_anim_screen',\n            },\n            paramsKeyMap: {\n                BACKGROUND: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var screenValue = script.getNumberValue('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [3, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay //+ 1000\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_screen(%1)'] },\n        },\n        robotis_RB_cm_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        // [\"센서 로그\", '30759'],\n                        // [\"다이나믹셀 로그\", '30760'],\n                        [Lang.Blocks.robotis_face01, '2817'],\n                        [Lang.Blocks.robotis_face02, '2818'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_face03, '2819'],\n                        [Lang.Blocks.robotis_face04, '2820'],\n                        [Lang.Blocks.robotis_face05, '2821'],\n\n                        [Lang.Blocks.robotis_face06, '2822'],\n                        [Lang.Blocks.robotis_face07, '2823'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_face08, '2824'],\n                        [Lang.Blocks.robotis_face09, '2825'],\n                        [Lang.Blocks.robotis_face10, '2826'],\n\n                        [Lang.Blocks.robotis_face11, '2827'],\n                        [Lang.Blocks.robotis_face12, '2828'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_face13, '2829'],\n                        \n                        [Lang.Blocks.robotis_face14, '2830'],\n                        [Lang.Blocks.robotis_face15, '2831'],\n                        [Lang.Blocks.robotis_face16, '2832'],\n                        [Lang.Blocks.robotis_face17, '2833'],\n                        [Lang.Blocks.robotis_face18, '2834'],\n\n                        [Lang.Blocks.robotis_face19, '2835'],\n                        [Lang.Blocks.robotis_face20, '2836'],\n                        [Lang.Blocks.robotis_face21, '2837'],\n                        [Lang.Blocks.robotis_face22, '2838'],\n                        [Lang.Blocks.robotis_face23, '2839'],\n                    ],\n                    value: '2817',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotis_RB_cm_screen',\n            },\n            paramsKeyMap: {\n                BACKGROUND: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var screenValue = script.getField('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [3, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_screen(%1)'] },\n        },\n        robotis_RB_cm_anim_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        // [\"센서 로그\", '30759'],\n                        // [\"다이나믹셀 로그\", '30760'],\n                        [Lang.Blocks.robotis_face01, '30748'],\n                        [Lang.Blocks.robotis_face02, '30749'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_face03, '30750'],\n                        [Lang.Blocks.robotis_face04, '30756'],\n                        [Lang.Blocks.robotis_face05, '30754'],\n\n                        [Lang.Blocks.robotis_face06, '30741'],\n                        [Lang.Blocks.robotis_face07, '30747'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_face08, '30738'],\n                        [Lang.Blocks.robotis_face09, '30740'],\n                        [Lang.Blocks.robotis_face10, '30739'],\n\n                        [Lang.Blocks.robotis_face11, '30733'],\n                        [Lang.Blocks.robotis_face12, '30734'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_face13, '30732'],\n                        \n                        [Lang.Blocks.robotis_face14, '30757'],\n                        [Lang.Blocks.robotis_face15, '30736'],\n                        [Lang.Blocks.robotis_face16, '30731'],\n                        [Lang.Blocks.robotis_face17, '30742'],\n                        [Lang.Blocks.robotis_face18, '30743'],\n\n                        [Lang.Blocks.robotis_face19, '30744'],\n                        [Lang.Blocks.robotis_face20, '30751'],\n                        [Lang.Blocks.robotis_face21, '30752'],\n                        [Lang.Blocks.robotis_face22, '30755'],\n                        [Lang.Blocks.robotis_face23, '30758'],\n                    ],\n                    value: '30748',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotis_RB_cm_anim_screen',\n            },\n            paramsKeyMap: {\n                BACKGROUND: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var screenValue = script.getField('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [3, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 1000\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_screen(%1)'] },\n        },\n\n        robotis_RB_car_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_car_anim01, '3329'],\n                        [Lang.Blocks.robotis_car_anim02, '3330'],\n                        [Lang.Blocks.robotis_car_anim03, '3331'],\n                        [Lang.Blocks.robotis_car_anim04, '3332'],\n                        [Lang.Blocks.robotis_car_anim05, '3333'],\n\n                        [Lang.Blocks.robotis_car_anim06, '3334'],\n                        [Lang.Blocks.robotis_car_anim07, '3335'], \n                        [Lang.Blocks.robotis_car_anim08, '3336'],\n                        [Lang.Blocks.robotis_car_anim09, '3337'],\n                        [Lang.Blocks.robotis_car_anim10, '3338'],\n\n                        [Lang.Blocks.robotis_car_anim11, '3339'],\n                        [Lang.Blocks.robotis_car_anim12, '3340'], \n                        [Lang.Blocks.robotis_car_anim13, '3341'],\n                        [Lang.Blocks.robotis_car_anim14, '3342'],\n                        [Lang.Blocks.robotis_car_anim15, '3343'],\n\n                        [Lang.Blocks.robotis_car_anim16, '3344'],\n                        [Lang.Blocks.robotis_car_anim17, '3345'], \n                        [Lang.Blocks.robotis_car_anim18, '3346'],\n                        [Lang.Blocks.robotis_car_anim19, '3347'],\n                    ],\n                    value: '3329',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_RB_car_screen',\n            },\n            paramsKeyMap: {\n                BACKGROUND: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var screenValue = script.getNumberValue('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [3, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 1000\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_screen(%1)'] },\n        },\n\n        robotis_RB_car_anim_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_car_anim01, '30978'],\n                        [Lang.Blocks.robotis_car_anim02, '30981'],\n                        [Lang.Blocks.robotis_car_anim03, '30982'],\n                        [Lang.Blocks.robotis_car_anim04, '30983'],\n                        [Lang.Blocks.robotis_car_anim05, '30984'],\n\n                        [Lang.Blocks.robotis_car_anim06, '30985'],\n                        [Lang.Blocks.robotis_car_anim07, '30986'], \n                        [Lang.Blocks.robotis_car_anim08, '30987'],\n                        [Lang.Blocks.robotis_car_anim09, '30988'],\n                        [Lang.Blocks.robotis_car_anim10, '30989'],\n\n                        [Lang.Blocks.robotis_car_anim11, '30990'],\n                        [Lang.Blocks.robotis_car_anim12, '30991'], \n                        [Lang.Blocks.robotis_car_anim13, '30992'],\n                        [Lang.Blocks.robotis_car_anim14, '30993'],\n                        [Lang.Blocks.robotis_car_anim15, '30994'],\n\n                        [Lang.Blocks.robotis_car_anim16, '30995'],\n                        [Lang.Blocks.robotis_car_anim17, '30996'], \n                        [Lang.Blocks.robotis_car_anim18, '30997'],\n                        [Lang.Blocks.robotis_car_anim19, '30998'],\n                    ],\n                    value: '30978',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_RB_car_anim_screen',\n            },\n            paramsKeyMap: {\n                BACKGROUND: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var screenValue = script.getNumberValue('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [3, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay //+ 1000\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_screen(%1)'] },\n        },\n\n        robotis_RB_cm_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_flashing1, '11'],\n                        [Lang.Blocks.robotis_flashing2, '12'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_flashing3, '13'],\n\n                        [Lang.Blocks.robotis_flashing4, '21'],\n                        [Lang.Blocks.robotis_flashing5, '22'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_flashing6, '23'],\n\n                        [Lang.Blocks.robotis_flashing7, '31'],\n                        [Lang.Blocks.robotis_flashing8, '32'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_flashing9, '33'],\n\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_common_on, '1'],\n                        [Lang.Blocks.robotis_common_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotis_RB_cm_led',\n            },\n            paramsKeyMap: {\n                RB_LED: 0,\n                VALUE: 1,\n            },\n            class: 'robotis_rb100_led',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmLed = script.getField('RB_LED', script);\n                var value = script.getField('VALUE', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 40;\n                var data_length = 1;\n                var data_value = 0;\n\n                \n                data_value = value * cmLed;\n              \n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_led(%1, %2)'] },\n        },\n        robotis_dxl_test: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                \n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'robotis_dxl_test',\n            },\n            paramsKeyMap: {\n                \n            },\n            class: 'robotis_rb100_dxl',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_H'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                //19번지에 1바이트로 1 설정 \n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 19;\n                var data_length = 1;\n                var data_value = 1;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    // [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [1]],\n                    // [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [2]],\n                    // [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [3]],\n                    // [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [4]],\n                    // [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [5]],\n                    // [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [6]],\n                    // [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [7]],\n                    // [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [8]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [33]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [34]],\n                    [Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0],\n               \n\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [1]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [2]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [3]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [4]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [5]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [6]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [7]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [8]],\n                    [Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0],\n\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2548, [1]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 1548, [2]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [3]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [4]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [5]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2048, [6]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 2248, [7]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 116, 4, 1848, [8]],\n                    [Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0],\n                    \n                    /*[Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 64, 1, 60, [1,2], [1,1]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 64, 1, 60, [3,4], [1,1]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 64, 1, 60, [5,6], [1,1]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 64, 1, 60, [7,8], [1,1]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [1], [2048]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [2], [2048]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [3], [2048]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [4], [2048]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [5], [2048]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [6], [2048]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [7], [2048]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [8], [2048]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [1], [1948]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [2], [1948]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [3], [1948]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [4], [1948]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [5], [1948]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [6], [1948]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [7], [1948]],\n                    [Entry.Robotis_rb.INSTRUCTION.SYNCWRITE, 116, 4, 60, [8], [1948]],*/\n\n                ];\n               \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    100\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_led(%1, %2)'] },\n        },\n        robotis_openCM70_RGee_go: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '2'],\n                        [Lang.Blocks.robotis_moveL, '3'],\n                        [Lang.Blocks.robotis_moveR, '4'],\n\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robotis_openCM70_RGee_go',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var speed = script.getNumberValue('SPEED', script);\n                var direction = script.getField('DIRECTION', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n                \n                switch(direction) {\n                    case '1':\n                        data_value = speed * 256 + speed;\n                        break;\n                    case '2':\n                        data_value = (256 - speed) * 256 + (256 - speed);\n                        break;\n                    case '3':\n                        data_value = speed * 256 + (256 - speed);\n                        break;\n                    case '4':\n                        data_value = (256 - speed) * 256 + speed;\n                        break;\n                    default:\n                        data_value = 0;\n                        break;\n                }\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_RGee_go(%1, %2)'],\n            },\n        },\n        robotis_openCM70_RGee_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                   null\n                ],\n                type: 'robotis_openCM70_RGee_stop',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var speed = script.getNumberValue('SPEED', script);\n                var direction = script.getField('DIRECTION', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n            \n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_RGee_stop()'],\n            },\n        },\n        robotis_openCM70_RGee_motion: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveRG1, '50007'],\n                        [Lang.Blocks.robotis_moveRG2, '50008'], //Lang.Blocks.robotis_robotis_common_green_color\n                        [Lang.Blocks.robotis_moveRG3, '50071'],\n                        [Lang.Blocks.robotis_moveRG4, '50072'],\n                    ],\n                    value: '50007',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotis_openCM70_RGee_motion',\n            },\n            paramsKeyMap: {\n                MotionNumber: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n\n                data_address =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[0];\n                data_length = Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[1];\n                data_value = script.getField('MotionNumber', script);\n\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    //[data_instruction, data_address, data_length, 0],\n                ];\n                \n                //console.log(script);\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    \n                    data_value > 50070 ? 2000 : 1000 \n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_RGee_motion(%1)'] },\n        }, \n        robotis_RB_follow_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1단계', '1'],\n                        ['2단계', '2'],\n                        ['3단계', '3'],\n\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RB_follow_line',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var speed_level = script.getNumberValue('SPEED', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 5200;\n                var data_length = 1;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        speed_level,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_follow_line(%1)'],\n            },\n        },\n        robotis_RB_follow_line_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                   null\n                ],\n                type: 'robotis_RB_follow_line_stop',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb', 'Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 5200;\n                var data_length = 1;\n                var data_value = 0;\n            \n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_follow_line_stop()'],\n            },\n        },\n        robotis_RB_cm_custom: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['BYTE', 'BYTE'],\n                        ['WORD', 'WORD'],\n                        ['DWORD', 'DWORD'],\n                    ],\n                    value: 'BYTE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RB_cm_custom',\n            },\n            paramsKeyMap: {\n                ADDRESS: 0,\n                LENGTH: 1,\n                VALUE: 2,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n\n                data_address = script.getNumberValue('ADDRESS');\n                data_value = script.getNumberValue('VALUE');\n               \n                switch(script.getField('LENGTH')){\n                    case 'BYTE':\n                        data_length = 1;\n                        break;\n                    case 'WORD':\n                        data_length = 2;\n                        break;\n                    case 'DWORD':\n                        data_length = 4;\n                        break;\n                    default:\n                        break;\n                }\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_custom(%1, %2)'] },\n        },\n        robotis_RB_cm_custom2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['BYTE', 'BYTE'],\n                        ['WORD', 'WORD'],\n                        ['DWORD', 'DWORD'],\n                    ],\n                    value: 'BYTE',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RB_cm_custom2',\n            },\n            paramsKeyMap: {\n                ADDRESS: 0,\n                LENGTH: 1,\n                VALUE: 2,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_H'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n\n                data_address = script.getNumberValue('ADDRESS');\n                data_value = script.getNumberValue('VALUE');\n               \n                switch(script.getField('LENGTH')){\n                    case 'BYTE':\n                        data_length = 1;\n                        break;\n                    case 'WORD':\n                        data_length = 2;\n                        break;\n                    case 'DWORD':\n                        data_length = 4;\n                        break;\n                    default:\n                        break;\n                }\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_custom(%1, %2)'] },\n        },\n        //endregion robotis 로보티즈\n    };\n};\n\n\nmodule.exports = [Entry.Robotis_rb];"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotisRBCar.js",
    "content": "'use strict';\n\nEntry.Robotis_rb_car = {\n    INSTRUCTION: {\n        NONE: 0,\n        WRITE: 3,\n        READ: 2,\n        SYNCWRITE: 4,\n        REGWRITE: 5,\n        ACTION: 6\n    },\n    CONTROL_TABLE: {\n        // [default address, default length, address (when reads together), length (when reads together)]\n        CM_LED_R: [79, 1],\n        CM_LED_G: [80, 1],\n        CM_LED_B: [81, 1],\n\n        RB_LED_L: [40, 1],\n        RB_LED_R: [41, 1],\n        RB_LED_B: [40, 2],\n\n        CM_BUZZER_INDEX: [60, 1], //[84, 1]\n        CM_BUZZER_TIME: [63, 1], //[85, 1]\n        CM_SOUND_DETECTED: [86, 1],\n        CM_SOUND_DETECTING: [87, 1],\n        CM_USER_BUTTON: [26, 1],\n        CM_MOTION: [66, 2], //[66,1]\n\n        AUX_SERVO_POSITION: [152, 2],\n        \n        AUX_CUSTOM: [216, 2],\n        \n        AUX_SERVO_MODE: [126, 1],\n        AUX_SERVO_SPEED: [136, 2],\n        AUX_MOTOR_SPEED: [136, 2],\n        AUX_LED_MODULE: [210, 1],\n    },\n    DXL_POSITION: {\n        values: [0,0,0,0,0,0,0,0]\n    },\n    setZero: function () {\n        // instruction / address / length / value / default length\n        Entry.hw.sendQueue['setZero'] = [1];\n        Entry.Robotis_carCont.update();\n        Entry.Robotis_carCont.setRobotisData(null);\n        Entry.hw.sendQueue['setZero'] = null;\n        Entry.Robotis_carCont.update();\n        Entry.Robotis_carCont.setRobotisData([\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 21, 2, 20],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 40, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 66, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 710, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 19, 1, 1], // bypass 모드 켜기\n            // [Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 30759],\n            // [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1],\n        ]);\n        Entry.Robotis_carCont.update();\n    },\n    id: ['7.9'],\n    name: 'Robotis_rb_car',\n    url: 'http://www.robotis.com/index/product.php?cate_code=111310',\n    imageName: 'robotis_RB100im_Rla.png',\n    title: {\n        \"ko\": \"로보티즈 알라\",\n        \"en\": \"ROBOTIS RLa\"\n    },\n    delay: 30,\n    readDelay: 30,\n};\n\nEntry.Robotis_rb_car.blockMenuBlocks = [\n    'robotis_RB_cm_ir_value',\n    'robotis_RB_cm_ir_compare',\n    'robotis_RB_detectFrontObj',\n    'robotis_RB_cm_btn_value',\n    'robotis_RB_cm_joystick_value',\n    'robotis_RB_mic',\n    'robotis_RB_detectSound_compare',\n    'robotis_RB_imu',\n    'robotis_RB_roll_pitch', \n    //'robotis_RB_environment_value',\n    //'robotis_RB_environment_compare',\n    //'robotis_RB_distance_value',\n    //'robotis_RB_distance_compare',\n\n    'robotis_RB_cm_buzzer_index',\n\n    \n    //알라표정 \n    //화면 애니메이션 \n    'robotis_RB_cm_screen',\n    'robotis_RB_cm_anim_screen',\n    'robotis_RB_rsp_screen',\n\n    'robotis_RB_LCDBright',\n    'robotis_RB_LCDColor',\n\n    'robotis_RB_LEDBright',\n    'robotis_RB_cm_led',\n\n    'robotis_RB_Hello',\n    'robotis_RB_effectSound',\n    'robotis_RB_record',\n    'robotis_RB_playRecord',\n\n    'robotis_RB_car_screen',\n    'robotis_RB_car_anim_screen',\n    'robotis_RB_kkokdu_screen',\n    'robotis_RB_kkokdu_anim_screen',\n \n    'robotis_openCM70_RLa_go',\n    'robotis_openCM70_RLa_stop',\n\n    'robotis_RB_rotate',\n    'robotis_RB_rotate_stop',\n\n    'robotis_RB_go_distance',\n    'robotis_RB_turn',\n    'robotis_RB_pen'\n];\n\nEntry.Robotis_rb_car.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                robotis_RB_cm_ir_value: \"%1 번 IR 센서 값\",\n                robotis_RB_cm_ir_compare: \"%1 번 IR 센서 값이 %2  %3이면\",\n                robotis_RB_detectFrontObj: \"앞에 물체가 있으면\",\n                robotis_RB_cm_btn_value: \"%1 버튼이 %2 이면\",\n                robotis_RB_cm_joystick_value: \"조이스틱 위치가 %1 이면\",\n                robotis_RB_mic: \"마이크 음량(dB)\",\n                robotis_RB_detectSound_compare: \"소리가 %1에서 나면\",\n                robotis_RB_imu: \"%1축의 %2 값\",\n                robotis_RB_roll_pitch: \"제어기 각도 %1 값\",\n                robotis_RB_environment_value: \"%1 %2 값\",\n                robotis_RB_environment_compare: \"%1 %2 값이 %3 %4이면\",\n                robotis_RB_distance_value: \"%1 %2 값\",\n                robotis_RB_distance_compare: \"%1 %2 값이 %3 %4이면\",\n\n                robotis_RB_cm_buzzer_index: \"제어기 음계값 %1 을(를) %2 옥타브로 %3 초 동안 %4 %5\",\n                robotis_RB_cm_screen: \"제어기 화면 배경을 알쥐 %1 로 선택 %2\",\n                robotis_RB_cm_anim_screen: \"제어기 화면 애니메이션을 알쥐 %1 로 선택 %2\",\n                robotis_RB_rsp_screen: \"제어기 화면에 %1 출력하기 %5\",\n\n                robotis_RB_LCDBright: \"제어기 화면 밝기를 %1로 정하기 %2\",\n                robotis_RB_LCDColor: \"제어기 화면 색상을 %1 으로 정하기 %2\",\n                \n                robotis_RB_LEDBright: \"제어기 %1 LED 밝기를 %2로 정하기 %3\",\n                robotis_RB_cm_led: \"제어기 %1 LED %2 %3\",\n\n                robotis_RB_Hello: \"%1 말하기 %2\",\n                robotis_RB_effectSound: \"효과음 %1 재생하기 %2\",\n                robotis_RB_record: \"%1 번 방에 녹음하기 %2\",\n                robotis_RB_playRecord: \"%1 번 방 소리 재생하기 %2\",\n\n                robotis_openCM70_RLa_go: \"알라 %1 속도로 %2 하기 %3\",\n                robotis_openCM70_RLa_stop: \"알라 정지하기 %1\",\n\n                robotis_RB_rotate:\"%1 모터 %2의 속도로 %3 회전하기%4\",\n                robotis_RB_rotate_stop:\"%1 모터 정지하기 %2\",\n\n                robotis_RB_go_distance:\"알라 로봇 %1 cm %2 하기 %3\",\n                robotis_RB_turn:\"알라 로봇 제자리 %1 도 회전하기%2\",\n                robotis_RB_pen:\"알라 로봇 펜 %1 %2\",\n\n            },\n            Blocks: {\n                robotis_red: \"빨강\",\n                robotis_orange: \"주황\",\n                robotis_yellow: \"노랑\",\n                robotis_green: \"초록\",\n                robotis_blue: \"파랑\",\n                robotis_brown: \"갈색\",\n                robotis_black: \"검정\",\n                robotis_white: \"흰색\",\n                robotis_left: \"왼쪽\",\n                robotis_center: \"중앙\",\n                robotis_right: \"오른쪽\",\n                robotis_both: \"양쪽\",\n                robotis_korean1: \"안녕하세요\",\n                robotis_korean2: \"반가워요\",\n                robotis_korean3: \"알겠어요\",\n                robotis_korean4: \"아니에요\",\n                robotis_korean5: \"모르겠어요\",\n                robotis_korean6: \"좋아요\",\n                robotis_korean7: \"싫어요\",\n                robotis_korean8: \"이름을말하세요\",\n                robotis_korean9: \"무엇을도와줄까?\",\n                robotis_korean10: \"잘했어\",\n                robotis_korean11: \"괜찮아\",\n                robotis_korean12: \"다시해보자\",\n                robotis_korean13: \"고마워\",\n                robotis_korean14: \"다시말해줄래?\",\n                robotis_korean15: \"최고야!\",\n                robotis_korean16: \"신나요\",\n                robotis_korean17: \"즐거워요\",\n                robotis_korean18: \"미안해요\",\n                robotis_korean19: \"화나요\",\n                robotis_korean20: \"부끄러워요\",\n                robotis_korean21: \"무서워요\",\n                robotis_korean22: \"속상해요\",\n                robotis_korean23: \"사랑해요\",\n                robotis_korean24: \"예뻐요\",\n                robotis_korean25: \"신기해요\",\n                robotis_korean26: \"초조해요\",\n                robotis_korean27: \"앞으로가자\",\n                robotis_korean28: \"뒤로가자\",\n                robotis_korean29: \"일어나자\",\n                robotis_korean30: \"넘어졌네?\",\n                robotis_korean31: \"오예\",\n                robotis_korean32: \"아싸\",\n                robotis_korean33: \"어머\",\n                robotis_korean34: \"이런\",\n                robotis_korean35: \"오호\",\n                robotis_korean36: \"하하하\",\n                robotis_korean37: \"호호호\",\n                robotis_korean38: \"졸려\",\n                robotis_korean39: \"자장가를들려줘\",\n                robotis_korean40: \"안녕\",\n                robotis_korean41: \"배고프다\",\n                robotis_korean42: \"도토리땡긴다\",\n                robotis_korean43: \"아.씻고싶어\",\n                robotis_korean44: \"비누목욕시간이야\",\n                robotis_korean45: \"심심한데\",\n                robotis_korean46: \"간식먹을까\",\n                robotis_korean47: \"아파요\",\n                robotis_korean48: \"약은없나요?\",\n                robotis_korean49: \"어디로가야하지?\",\n                robotis_korean50: \"와아도착이다\",\n                robotis_korean51: \"왼쪽으로가자\",\n                robotis_korean52: \"오른쪽으로가자\",\n                robotis_korean53: \"깜짝이야\",\n                robotis_korean54: \"찾았다\",\n                robotis_korean55: \"여긴없네\",\n                robotis_korean56: \"혹시나불렀어?\",\n                robotis_korean57: \"내려주세요\",\n                robotis_korean58: \"앗\",\n                robotis_korean59: \"힝\",\n                robotis_korean60: \"이익\",\n                robotis_dog: \"개\",\n                robotis_frog: \"개구리\",\n                robotis_cat: \"고양이\",\n                robotis_chicken: \"닭\",\n                robotis_tiger: \"호랑이\",\n                robotis_mouse: \"쥐\",\n                robotis_ambul: \"앰뷸런스\",\n                robotis_Horn: \"경적(빵빵)\",\n                robotis_siren: \"사이렌(경찰차)\",\n                robotis_whistle: \"호루라기\",\n                robotis_gun: \"총소리\",\n                robotis_clap: \"박수소리\",\n                robotis_melody1: \"멜로디1\",\n                robotis_melody2: \"멜로디2\",\n                robotis_melody3: \"멜로디3\",\n                robotis_melody4: \"멜로디4\",\n                robotis_forward: \"앞으로\",\n                robotis_backward: \"뒤로\",\n                robotis_acceleration: \"가속도\",\n                robotis_gyro: \"자이로\",\n                robotis_run: \"실행\",\n                robotis_cancel: \"취소\",\n                robotis_push: \"눌림\",\n                robotis_notPush: \"안눌림\",\n                robotis_play: \"연주\",\n                robotis_rest: \"쉼표\",\n                robotis_face01: \"와하하\",\n                robotis_face02: \"싱글벙글\",\n                robotis_face03: \"큭큭큭\",\n                robotis_face04: \"냠냠\",\n                robotis_face05: \"겁먹음\",\n                robotis_face06: \"답답\",\n                robotis_face07: \"갸우뚱\",\n                robotis_face08: \"어벙벙\",\n                robotis_face09: \"고함\",\n                robotis_face10: \"화남\",\n                robotis_face11: \"킁킁(왼쪽)\",\n                robotis_face12: \"킁킁(오른쪽)\",\n                robotis_face13: \"킁킁(아래)\",\n                robotis_face14: \"안심\",\n                robotis_face15: \"기절\",\n                robotis_face16: \"헤롱헤롱\",\n                robotis_face17: \"하품\",\n                robotis_face18: \"졸림\",\n                robotis_face19: \"잠듦\",\n                robotis_face20: \"마음앓이\",\n                robotis_face21: \"폭풍눈물\",\n                robotis_face22: \"목욕\",\n                robotis_face23: \"햐트뿅뿅\",\n\n                robotis_flashing1: \"점멸1\",\n                robotis_flashing2: \"점멸2\",\n                robotis_flashing3: \"점멸3\",\n                robotis_flashing4: \"점멸4\",\n                robotis_flashing5: \"점멸5\",\n                robotis_flashing6: \"점멸6\",\n                robotis_flashing7: \"점멸7\",\n                robotis_flashing8: \"점멸8\",\n                robotis_flashing9: \"점멸9\",\n                robotis_moveF: \"전진\",\n                robotis_moveB: \"후진\",\n                robotis_moveL: \"좌회전\",\n                robotis_moveR: \"우회전\",\n                robotis_moveRG1: \"일어서기\",\n                robotis_moveRG2: \"앉기\",\n                robotis_moveRG3: \"발버둥\",\n                robotis_moveRG4: \"발들기\",\n                robotis_stMotion1: \"기본자세\",\n                robotis_stMotion2: \"전진\",\n                robotis_stMotion3: \"우전진\",\n                robotis_stMotion4: \"좌전진\",\n                robotis_stMotion5: \"후진\",\n                robotis_stMotion6: \"오른쪽으로\",\n                robotis_stMotion7: \"왼쪽으로\",\n                robotis_stMotion8: \"우회전\",\n                robotis_stMotion9: \"좌회전\",\n                robotis_spMotion1: \"오른손 들기\",\n                robotis_spMotion2: \"오른손 내리기\",\n                robotis_spMotion3: \"왼손 들기\",\n                robotis_spMotion4: \"왼손 내리기\",\n                robotis_spMotion5: \"양손 들기\",\n                robotis_spMotion6: \"양손 내리기\",\n                robotis_spMotion7: \"뒤로 넘어지기\",\n                robotis_spMotion8: \"앞으로 넘어지기\",\n                robotis_spMotion9: \"앞으로 일어서기\",\n                robotis_spMotion10: \"뒤로 일어서기\",\n                robotis_spMotion11: \"방어\",\n                robotis_spMotion12: \"공격1\",\n                robotis_spMotion13: \"공격2\",\n                robotis_spMotion14: \"공격3\",\n                robotis_spMotion15: \"공격4\",\n                robotis_screen1: \"가위\",\n                robotis_screen2: \"바위\",\n                robotis_screen3: \"보\",\n                robotis_clockwise: \"시계방향\",\n                robotis_counterclockwise: \"반시계방향\",\n                robotis_up: \"들기\",\n                robotis_down: \"내리기\",\n            },\n        },\n        en: {\n            template: {\n                robotis_RB_cm_ir_value:\"IR sensor value of %1 Value of IR Sensor\",\n                robotis_RB_cm_ir_compare:\"If IR sensor value of %1 is %2 %3\",\n                robotis_RB_detectFrontObj:\"If there is an object in front\",\n                robotis_RB_cm_btn_value:\"If %1 button is %2\",\n                robotis_RB_cm_joystick_value:\"If the joystick location is %1\",\n                robotis_RB_mic:\"MIC volume(dB)\",\n                robotis_RB_detectSound_compare:\"If sound is detected from %1\",\n                robotis_RB_imu:\"%1 axis' %2 value\",\n                robotis_RB_roll_pitch:\"%1 Controller position \",\n                robotis_RB_environment_value: \"%1 %2 value\",\n                robotis_RB_environment_compare: \"If %1 %2 value is %3 %4\",\n                robotis_RB_distance_value: \"%1 %2 value\",\n                robotis_RB_distance_compare: \"If %1 %2 value is %3 %4\",\n\n                //robotis_RB_detectPose:\"If robot falls %1\",\n                \n                robotis_RB_cm_buzzer_index:\"%1 at %2 octaves for %3 second(s) -> %4 %5\",\n                robotis_RB_cm_screen:\"Choose %1 as a screen background %2\",\n                robotis_RB_cm_anim_screen: \"Choose %1 as a screen animation %2\",\n                robotis_RB_rsp_screen:\"Print %1 on the screen %5\",\n                \n                robotis_RB_LCDBright:\"Adjust screen brightness to %1 %2\",\n                robotis_RB_LCDColor:\"Set screen color to %1 %2\",\n                \n                robotis_RB_LEDBright:\"Set the brightness of the %1 LED to %2 %3\",\n                robotis_RB_cm_led:\"%1 LED %2 %3\",\n                \n                robotis_RB_Hello:\"Say %1 %2\",\n                robotis_RB_effectSound:\"Play the sound of %1 %2\",\n                robotis_RB_record:\"Record in room %1 %2\",\n                robotis_RB_playRecord:\"Play recorded sound in room %1 %2\",\n\n                robotis_openCM70_RLa_go:\"With %1 velocity, move R-La %2 %3\",\n                robotis_openCM70_RLa_stop:\"R-La STOP\",\n\n                robotis_RB_rotate:\"%1 motor with %2 velocity %3 rotate%4\",\n                robotis_RB_rotate_stop:\"%1 motor stop%2\",\n                robotis_RB_go_distance:\"Rla robot %1 cm %2 moving %3\",\n                robotis_RB_turn:\"Rla robot turn %1 degree %2\",\n                robotis_RB_pen:\"Rla robot %1 pen %2\",\n\n                \n            },\n            Blocks: {\n                robotis_red: \"Red\",\n                robotis_orange: \"Orange\",\n                robotis_yellow: \"Yellow\",\n                robotis_green: \"Green\",\n                robotis_blue: \"Blue\",\n                robotis_brown: \"Brown\",\n                robotis_black: \"Black\",\n                robotis_white: \"White\",\n                robotis_left: \"Left\",\n                robotis_center: \"Center\",\n                robotis_right: \"Right\",\n                robotis_both: \"Both\",\n                robotis_korean1: \"Hello!\",\n                robotis_korean2: \"Great to see you.\",\n                robotis_korean3: \"Okay ~\",\n                robotis_korean4: \"No!\",\n                robotis_korean5: \"I don't know.\",\n                robotis_korean6: \"I like it.\",\n                robotis_korean7: \"I don't like it.\",\n                robotis_korean8: \"What is your name? \",\n                robotis_korean9: \"How can I help you? \",\n                robotis_korean10: \"Great job! \",\n                robotis_korean11: \"It's alright.\",\n                robotis_korean12: \"Let's do it again! \",\n                robotis_korean13: \"Thank you! \",\n                robotis_korean14: \"Can you say that one more time?\",\n                robotis_korean15: \"Awesome!\",\n                robotis_korean16: \"I'm excited! \",\n                robotis_korean17: \"I'm having a great time! \",\n                robotis_korean18: \"I'm sorry.\",\n                robotis_korean19: \"I'm angry! \",\n                robotis_korean20: \"I'm embarassed.\",\n                robotis_korean21: \"I'm scared.\",\n                robotis_korean22: \"I'm upset.\",\n                robotis_korean23: \"I love you.\",\n                robotis_korean24: \"Very pretty! \",\n                robotis_korean25: \"Interesting.\",\n                robotis_korean26: \"I'm nervous.\",\n                robotis_korean27: \"Let's move forward! \",\n                robotis_korean28: \"Let's move backward! \",\n                robotis_korean29: \"Let's stand up! \",\n                robotis_korean30: \"Did you fall down? \",\n                robotis_korean31: \"Oh Yeah~\",\n                robotis_korean32: \"Sweet! \",\n                robotis_korean33: \"Oh no\",\n                robotis_korean34: \"My My \",\n                robotis_korean35: \"Whoo hoo! \",\n                robotis_korean36: \"Ha Ha Ha\",\n                robotis_korean37: \"Ho Ho Ho \",\n                robotis_korean38: \"I'm sleepy.\",\n                robotis_korean39: \"Sing me a bedtime song! \",\n                robotis_korean40: \"Hello!\",\n                robotis_korean41: \"I'm hungry.\",\n                robotis_korean42: \"I'm craving an acorn! \",\n                robotis_korean43: \"I want to take a bath! \",\n                robotis_korean44: \"Time for a bath! \",\n                robotis_korean45: \"I'm bored. \",\n                robotis_korean46: \"Do you want a snack? \",\n                robotis_korean47: \"I'm sick.\",\n                robotis_korean48: \"Do you have any medicine? \",\n                robotis_korean49: \"Where do we have to go? \",\n                robotis_korean50: \"We're here! \",\n                robotis_korean51: \"Let's go to the left side! \",\n                robotis_korean52: \"Let's go to the right side! \",\n                robotis_korean53: \"Oh my, you scared me! \",\n                robotis_korean54: \"Found you! \",\n                robotis_korean55: \"There's nothing here. \",\n                robotis_korean56: \"Did you call me?\",\n                robotis_korean57: \"Please let me down. \",\n                robotis_korean58: \"Oops! \",\n                robotis_korean59: \"Hmmph! \",\n                robotis_korean60: \"Eek! \",\n                robotis_dog: \"Dog\",\n                robotis_frog: \"Frog\",\n                robotis_cat: \"Cat\",\n                robotis_chicken: \"Rooster\",\n                robotis_tiger: \"Tiger\",\n                robotis_mouse: \"Mouse\",\n                robotis_ambul: \"Ambulance\",\n                robotis_Horn: \"CarHorn\",\n                robotis_siren: \"Siren\",\n                robotis_whistle: \"Whistle\",\n                robotis_gun: \"Gunshot\",\n                robotis_clap: \"Clap\",\n                robotis_melody1: \"Melody1\",\n                robotis_melody2: \"Melody2\",\n                robotis_melody3: \"Melody3\",\n                robotis_melody4: \"Melody4\",\n                robotis_forward: \"Forward\",\n                robotis_backward: \"Backward\",\n                robotis_acceleration: \"acceleration\",\n                robotis_gyro: \"gyro\",\n                robotis_run: \"Run\",\n                robotis_cancel: \"Cancel\",\n                robotis_push: \"Pressed\",\n                robotis_notPush: \"Unpressed\",\n                robotis_play: \"Play\",\n                robotis_rest: \"Rest\",\n                robotis_face01: \"Haha\",\n                robotis_face02: \"Smile\",\n                robotis_face03: \"Laugh\",\n                robotis_face04: \"Yum Yum\",\n                robotis_face05: \"Scared\",\n                robotis_face06: \"Uncomfortable\",\n                robotis_face07: \"Confused\",\n                robotis_face08: \"Dazed\",\n                robotis_face09: \"Yell\",\n                robotis_face10: \"Angry\",\n                robotis_face11: \"Sniff (Left)\",\n                robotis_face12: \"Sniff (Right)\",\n                robotis_face13: \"Sniff (Down)\",\n                robotis_face14: \"Whew\",\n                robotis_face15: \"Faint\",\n                robotis_face16: \"Dizzy\",\n                robotis_face17: \"Yawn\",\n                robotis_face18: \"Sleepy\",\n                robotis_face19: \"Sleep\",\n                robotis_face20: \"Sad\",\n                robotis_face21: \"Cry\",\n                robotis_face22: \"Bath\",\n                robotis_face23: \"Heart-Eyes\",       \n\n                robotis_flashing1: \"Flashing1\",\n                robotis_flashing2: \"Flashing2\",\n                robotis_flashing3: \"Flashing3\",\n                robotis_flashing4: \"Flashing4\",\n                robotis_flashing5: \"Flashing5\",\n                robotis_flashing6: \"Flashing6\",\n                robotis_flashing7: \"Flashing7\",\n                robotis_flashing8: \"Flashing8\",\n                robotis_flashing9: \"Flashing9\",\n                robotis_moveF: \"Forward\",\n                robotis_moveB: \"Backward\",\n                robotis_moveL: \"LeftTurn\",\n                robotis_moveR: \"RightTurn\",\n                robotis_moveRG1: \"Stand\",\n                robotis_moveRG2: \"Sit\",\n                robotis_moveRG3: \"Struggle\",\n                robotis_moveRG4: \"RaiseFeet\",\n                robotis_stMotion1: \"Standard\",\n                robotis_stMotion2: \"Forward\",\n                robotis_stMotion3: \"TurnRight\",\n                robotis_stMotion4: \"TurnLeft\",\n                robotis_stMotion5: \"Backward\",\n                robotis_stMotion6: \"ToRight\",\n                robotis_stMotion7: \"ToLeft\",\n                robotis_stMotion8: \"TurnAroundRight\",\n                robotis_stMotion9: \"TurnAroundLeft\",\n                robotis_spMotion1: \"RightHandUp\",\n                robotis_spMotion2: \"RightHandDown\",\n                robotis_spMotion3: \"LeftHandUp\",\n                robotis_spMotion4: \"LeftHandDown\",\n                robotis_spMotion5: \"BothHandsUp\",\n                robotis_spMotion6: \"BothHandsDown\",\n                robotis_spMotion7: \"FallBackward\",\n                robotis_spMotion8: \"FallForward\",\n                robotis_spMotion9: \"StandForward\",\n                robotis_spMotion10: \"StandBackward\",\n                robotis_spMotion11: \"Defence\",\n                robotis_spMotion12: \"Offense1\",\n                robotis_spMotion13: \"Offense2\",\n                robotis_spMotion14: \"Offense3\",\n                robotis_spMotion15: \"Offense4\",\n                robotis_screen1: \"Sissor\",\n                robotis_screen2: \"Rock\",\n                robotis_screen3: \"Paper\",\n                robotis_clockwise: \"clockwise\",\n                robotis_counterclockwise: \"counterclockwise\",\n                robotis_up: \"up\",\n                robotis_down: \"down\",\n            },\n        }\n    }\n};\n\nEntry.Robotis_rb_car.getBlocks = function() {\n    return {\n        robotis_openCM70_RLa_go: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '2'],\n                        [Lang.Blocks.robotis_moveL, '3'],\n                        [Lang.Blocks.robotis_moveR, '4'],\n\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robotis_openCM70_RLa_go',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_car'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var speed = script.getNumberValue('SPEED', script);\n                var direction = script.getField('DIRECTION', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n                \n                if(speed > 100) {\n                    speed = 100;\n                } else if(speed < -100) {\n                    speed = -100;\n                }\n\n                switch(direction) {\n                    case '1':\n                        data_value = speed * 256 + speed;\n                        break;\n                    case '2':\n                        data_value = (256 - speed) * 256 + (256 - speed);\n                        break;\n                    case '3':\n                        data_value = speed * 256 + (256 - speed);\n                        break;\n                    case '4':\n                        data_value = (256 - speed) * 256 + speed;\n                        break;\n                    default:\n                        data_value = 0;\n                        break;\n                }\n                console.log(speed);\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.openCM70_RLa_go(%1, %2)'],\n            },\n        },\n\n        robotis_openCM70_RLa_stop:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                   null\n                ],\n                type: 'robotis_openCM70_RLa_stop',\n            },\n            paramsKeyMap: {\n                \n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_car'],\n            func: function (sprite, script) {\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n            \n                console.log(\"rg stop send\");\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_RLa_stop()'],\n            },\n        },\n\n        robotis_RB_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '36'],\n                        [Lang.Blocks.robotis_right, '35'], //Lang.Blocks.robotis_common_green_color\n                    ],\n                    value: '36',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_clockwise, '-10'],\n                        [Lang.Blocks.robotis_counterclockwise, '10'], //Lang.Blocks.robotis_common_green_color\n                    ],\n                    value: '-10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null\n                ],\n                type: 'robotis_RB_rotate',\n            },\n            \n            paramsKeyMap: {\n                DXLNUM: 0,\n                VEL: 1,\n                DIRECTION: 2,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_car'],\n            func(entity, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 19;\n                var data_length = 1;\n                var data_value = 1;\n        \n                var data_sendqueue = [\n                     [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [36]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [35]],\n                ]\n                \n                var dxlID = script.getField('DXLNUM', script);\n                var velocity = script.getNumberValue('VEL', script);\n                var direction = script.getNumberValue('DIRECTION', script);\n        \n                if(velocity > 100) {\n                    velocity = 100;\n                } else if(velocity < -100) {\n                    velocity = -100;\n                }\n                \n                var dxlPosition = dxlID == 35 ? -1 : 1;\n                velocity = Math.floor(velocity * direction * dxlPosition);\n                \n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.REGWRITE, 104, 4, velocity, [dxlID]]);\n                \n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0]);\n        \n                \n        \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        },\n\n        robotis_RB_rotate_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '36'],\n                        [Lang.Blocks.robotis_right, '35'], //Lang.Blocks.robotis_common_green_color\n                    ],\n                    value: '36',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RB_rotate_stop',\n            },\n            \n            paramsKeyMap: {\n                DXLNUM: 0,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_car'],\n            func(entity, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 19;\n                var data_length = 1;\n                var data_value = 1;\n        \n                var data_sendqueue = [\n                     [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [36]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [35]],\n                ]\n                \n                var dxlID = script.getField('DXLNUM', script);\n                \n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.REGWRITE, 104, 4, 0, [dxlID]]);\n                \n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0]);\n        \n                \n        \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        },\n\n        robotis_RB_go_distance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '-1'], //Lang.Blocks.robotis_common_green_color\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RB_go_distance',\n            },\n            \n            paramsKeyMap: {\n                DISTANCE: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_car'],\n            func(entity, script) {\n                var distance = script.getNumberValue('DISTANCE', script);\n                var direction = script.getField('DIRECTION', script);\n\n                if(distance > 1000) {\n                    distance = 1000;\n                } else if(distance < -1000) {\n                    distance = -1000;\n                }\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 270;\n                var data_length = 4;\n                var data_value = Math.floor(10 * distance * direction);\n        \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                data_sendqueue.push([data_instruction, 66, 2, 50491]);\n        \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 500 * Math.abs(distance)\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        },\n\n        robotis_RB_turn:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                ],\n                type: 'robotis_RB_turn',\n            },\n            \n            paramsKeyMap: {\n                ANGLE: 0,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_car'],\n            func(entity, script) {\n                var angle = script.getNumberValue('ANGLE', script);\n\n                if(angle > 180) {\n                    angle = 180;\n                } else if(angle < -180) {\n                    angle = -180;\n                }\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 270;\n                var data_length = 4;\n                var data_value = Math.floor(-angle);\n        \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n            \n                data_sendqueue.push([data_instruction, 66, 2, 50492]);\n        \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 2000*(Math.abs(angle) / 90) + 1000\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        },\n\n        robotis_RB_pen:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_up, '50007'],\n                        [Lang.Blocks.robotis_down, '50008'], //Lang.Blocks.robotis_common_green_color\n                    ],\n                    value: '50007',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_RB_pen',\n            },\n            \n            paramsKeyMap: {\n                MOTION: 0,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_car'],\n            func(entity, script) {\n                var motion = script.getNumberValue('MOTION', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 66;\n                var data_length = 2;\n                var data_value = motion;\n        \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        }\n    };\n}\n\nmodule.exports = [Entry.Robotis_rb_car];\n\n\n\n\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotisRBHumanoid.js",
    "content": "'use strict';\n\nEntry.Robotis_rb_H = {\n    INSTRUCTION: {\n        NONE: 0,\n        WRITE: 3,\n        READ: 2,\n        SYNCWRITE: 4,\n        REGWRITE: 5,\n        ACTION: 6\n    },\n    CONTROL_TABLE: {\n        // [default address, default length, address (when reads together), length (when reads together)]\n        CM_LED_R: [79, 1],\n        CM_LED_G: [80, 1],\n        CM_LED_B: [81, 1],\n\n        RB_LED_L: [40, 1],\n        RB_LED_R: [41, 1],\n        RB_LED_B: [40, 2],\n\n        CM_BUZZER_INDEX: [60, 1], //[84, 1]\n        CM_BUZZER_TIME: [63, 1], //[85, 1]\n        CM_SOUND_DETECTED: [86, 1],\n        CM_SOUND_DETECTING: [87, 1],\n        CM_USER_BUTTON: [26, 1],\n        CM_MOTION: [66, 2], //[66,1]\n\n        AUX_SERVO_POSITION: [152, 2],\n        \n        AUX_CUSTOM: [216, 2],\n        \n        AUX_SERVO_MODE: [126, 1],\n        AUX_SERVO_SPEED: [136, 2],\n        AUX_MOTOR_SPEED: [136, 2],\n        AUX_LED_MODULE: [210, 1],\n    },\n    DXL_POSITION: {\n        values: [0,0,0,0,0,0,0,0]\n    },\n    setZero: function () {\n        // instruction / address / length / value / default length\n        Entry.hw.sendQueue['setZero'] = [1];\n        Entry.Robotis_carCont.update();\n        Entry.Robotis_carCont.setRobotisData(null);\n        Entry.hw.sendQueue['setZero'] = null;\n        Entry.Robotis_carCont.update();\n        Entry.Robotis_carCont.setRobotisData([\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 21, 2, 20],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 40, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 66, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 710, 2, 0],\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 19, 1, 1], // bypass 모드 켜기\n            // [Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 30759],\n            // [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1],\n        ]);\n        \n        Entry.Robotis_carCont.update();\n    },\n    id: ['7.7', '7.8'],\n    name: 'Robotis_rb_H',\n    url: 'http://www.robotis.com/index/product.php?cate_code=111310',\n    imageName: 'robotis_RB100im_Humanoid.png',\n    title: {\n        \"ko\": \"로보티즈 꼭두\",\n        \"en\": \"ROBOTIS Humanoid\"\n    },\n    delay: 30,\n    readDelay: 30,\n};\n\nEntry.Robotis_rb_H.blockMenuBlocks = [\n    //robotis_openCM70\n    // 'robotis_openCM70_sensor_value',\n    \n    //입력\n    'robotis_RB_cm_ir_value',\n    'robotis_RB_cm_ir_compare',\n    'robotis_RB_detectFrontObj',\n    'robotis_RB_cm_btn_value',\n    'robotis_RB_cm_joystick_value',\n    'robotis_RB_mic',\n    'robotis_RB_detectSound_compare',\n    'robotis_RB_imu',\n    'robotis_RB_roll_pitch', \n    'robotis_RB_environment_value',\n    'robotis_RB_environment_compare',\n    'robotis_RB_distance_value',\n    'robotis_RB_distance_compare',\n\n    //'robotis_RB_detectPose',\n\n    'robotis_RB_cm_buzzer_index',\n\n    'robotis_RB_cm_screen',\n    'robotis_RB_cm_anim_screen',\n    'robotis_RB_rsp_screen',\n\n    'robotis_RB_LCDBright',\n    'robotis_RB_LCDColor',\n    \n    'robotis_RB_LEDBright',\n    'robotis_RB_cm_led',\n\n    'robotis_RB_Hello',\n    'robotis_RB_effectSound',\n    'robotis_RB_record',\n    'robotis_RB_playRecord',\n\n    'robotis_RB_car_screen',\n    'robotis_RB_car_anim_screen',\n    'robotis_RB_kkokdu_screen',\n    'robotis_RB_kkokdu_anim_screen',\n\n    'robotis_RB_cm_motion',\n    'robotis_RB_cm_motion2',\n    'robotis_RB_cm_motion_custom',\n    'robotis_dxl_control',\n    'robotis_dxl_each_control',\n    \n    // 'robotis_RB_cm_custom_value2',\n    // 'robotis_RB_cm_custom2',\n];\n\nEntry.Robotis_rb_H.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                robotis_RB_cm_ir_value: \"%1 번 IR 센서 값\",\n                robotis_RB_cm_ir_compare: \"%1 번 IR 센서 값이 %2  %3이면\",\n                robotis_RB_detectFrontObj: \"앞에 물체가 있으면\",\n                robotis_RB_cm_btn_value: \"%1 버튼이 %2 이면\",\n                robotis_RB_cm_joystick_value: \"조이스틱 위치가 %1 이면\",\n                robotis_RB_mic: \"마이크 음량(dB)\",\n                robotis_RB_detectSound_compare: \"소리가 %1에서 나면\",\n                robotis_RB_imu: \"%1축의 %2 값\",\n                robotis_RB_roll_pitch: \"제어기 각도 %1 값\",\n                robotis_RB_environment_value: \"%1 %2 값\",\n                robotis_RB_environment_compare: \"%1 %2 값이 %3 %4이면\",\n                robotis_RB_distance_value: \"%1 %2 값\",\n                robotis_RB_distance_compare: \"%1 %2 값이 %3 %4이면\",\n                //robotis_RB_detectPose: \"로봇이 %1 넘어지면\",\n\n                robotis_RB_cm_buzzer_index: \"제어기 음계값 %1 을(를) %2 옥타브로 %3 초 동안 %4 %5\",\n                robotis_RB_cm_screen: \"제어기 화면 배경을 알쥐 %1 로 선택 %2\",\n                robotis_RB_cm_anim_screen: \"제어기 화면 애니메이션을 알쥐 %1 로 선택 %2\",\n                robotis_RB_rsp_screen: \"제어기 화면에 %1 출력하기 %5\",\n\n                robotis_RB_LCDBright: \"제어기 화면 밝기를 %1로 정하기 %2\",\n                robotis_RB_LCDColor: \"제어기 화면 색상을 %1 으로 정하기 %2\",\n                \n                robotis_RB_LEDBright: \"제어기 %1 LED 밝기를 %2로 정하기 %3\",\n                robotis_RB_cm_led: \"제어기 %1 LED %2 %3\",\n\n                robotis_RB_Hello: \"%1 말하기 %2\",\n                robotis_RB_effectSound: \"효과음 %1 재생하기 %2\",\n                robotis_RB_record: \"%1 번 방에 녹음하기 %2\",\n                robotis_RB_playRecord: \"%1 번 방 소리 재생하기 %2\",\n                \n                robotis_RB_cm_motion: \"휴머노이드 이동 모션 %1 실행 %2\",\n                robotis_RB_cm_motion2: \"휴머노이드 기타 모션 %1 실행 %2\",\n                robotis_RB_cm_motion_custom: \"휴머노이드 커스텀 모션 %1 실행 %2\",\n                robotis_dxl_control: \"1번 모터 %1° 2번 모터 %2° 3번 모터 %3° 4번 모터 %4° 5번 모터 %5° 6번 모터 %6° 7번 모터 %7° 8번 모터 %8° %9초 동안 움직이기 %10\",\n                robotis_dxl_each_control: \"%1 모터 %2° %3 초 동안 움직이기 %4\",\n            },\n            Blocks: {\n                robotis_red: \"빨강\",\n                robotis_orange: \"주황\",\n                robotis_yellow: \"노랑\",\n                robotis_green: \"초록\",\n                robotis_blue: \"파랑\",\n                robotis_brown: \"갈색\",\n                robotis_black: \"검정\",\n                robotis_white: \"흰색\",\n                robotis_left: \"왼쪽\",\n                robotis_center: \"중앙\",\n                robotis_right: \"오른쪽\",\n                robotis_both: \"양쪽\",\n                robotis_korean1: \"안녕하세요\",\n                robotis_korean2: \"반가워요\",\n                robotis_korean3: \"알겠어요\",\n                robotis_korean4: \"아니에요\",\n                robotis_korean5: \"모르겠어요\",\n                robotis_korean6: \"좋아요\",\n                robotis_korean7: \"싫어요\",\n                robotis_korean8: \"이름을말하세요\",\n                robotis_korean9: \"무엇을도와줄까?\",\n                robotis_korean10: \"잘했어\",\n                robotis_korean11: \"괜찮아\",\n                robotis_korean12: \"다시해보자\",\n                robotis_korean13: \"고마워\",\n                robotis_korean14: \"다시말해줄래?\",\n                robotis_korean15: \"최고야!\",\n                robotis_korean16: \"신나요\",\n                robotis_korean17: \"즐거워요\",\n                robotis_korean18: \"미안해요\",\n                robotis_korean19: \"화나요\",\n                robotis_korean20: \"부끄러워요\",\n                robotis_korean21: \"무서워요\",\n                robotis_korean22: \"속상해요\",\n                robotis_korean23: \"사랑해요\",\n                robotis_korean24: \"예뻐요\",\n                robotis_korean25: \"신기해요\",\n                robotis_korean26: \"초조해요\",\n                robotis_korean27: \"앞으로가자\",\n                robotis_korean28: \"뒤로가자\",\n                robotis_korean29: \"일어나자\",\n                robotis_korean30: \"넘어졌네?\",\n                robotis_korean31: \"오예\",\n                robotis_korean32: \"아싸\",\n                robotis_korean33: \"어머\",\n                robotis_korean34: \"이런\",\n                robotis_korean35: \"오호\",\n                robotis_korean36: \"하하하\",\n                robotis_korean37: \"호호호\",\n                robotis_korean38: \"졸려\",\n                robotis_korean39: \"자장가를들려줘\",\n                robotis_korean40: \"안녕\",\n                robotis_korean41: \"배고프다\",\n                robotis_korean42: \"도토리땡긴다\",\n                robotis_korean43: \"아.씻고싶어\",\n                robotis_korean44: \"비누목욕시간이야\",\n                robotis_korean45: \"심심한데\",\n                robotis_korean46: \"간식먹을까\",\n                robotis_korean47: \"아파요\",\n                robotis_korean48: \"약은없나요?\",\n                robotis_korean49: \"어디로가야하지?\",\n                robotis_korean50: \"와아도착이다\",\n                robotis_korean51: \"왼쪽으로가자\",\n                robotis_korean52: \"오른쪽으로가자\",\n                robotis_korean53: \"깜짝이야\",\n                robotis_korean54: \"찾았다\",\n                robotis_korean55: \"여긴없네\",\n                robotis_korean56: \"혹시나불렀어?\",\n                robotis_korean57: \"내려주세요\",\n                robotis_korean58: \"앗\",\n                robotis_korean59: \"힝\",\n                robotis_korean60: \"이익\",\n                robotis_dog: \"개\",\n                robotis_frog: \"개구리\",\n                robotis_cat: \"고양이\",\n                robotis_chicken: \"닭\",\n                robotis_tiger: \"호랑이\",\n                robotis_mouse: \"쥐\",\n                robotis_ambul: \"앰뷸런스\",\n                robotis_Horn: \"경적(빵빵)\",\n                robotis_siren: \"사이렌(경찰차)\",\n                robotis_whistle: \"호루라기\",\n                robotis_gun: \"총소리\",\n                robotis_clap: \"박수소리\",\n                robotis_melody1: \"멜로디1\",\n                robotis_melody2: \"멜로디2\",\n                robotis_melody3: \"멜로디3\",\n                robotis_melody4: \"멜로디4\",\n                robotis_forward: \"앞으로\",\n                robotis_backward: \"뒤로\",\n                robotis_acceleration: \"가속도\",\n                robotis_gyro: \"자이로\",\n                robotis_run: \"실행\",\n                robotis_cancel: \"취소\",\n                robotis_push: \"눌림\",\n                robotis_notPush: \"안눌림\",\n                robotis_play: \"연주\",\n                robotis_rest: \"쉼표\",\n                robotis_face01: \"와하하\",\n                robotis_face02: \"싱글벙글\",\n                robotis_face03: \"큭큭큭\",\n                robotis_face04: \"냠냠\",\n                robotis_face05: \"겁먹음\",\n                robotis_face06: \"답답\",\n                robotis_face07: \"갸우뚱\",\n                robotis_face08: \"어벙벙\",\n                robotis_face09: \"고함\",\n                robotis_face10: \"화남\",\n                robotis_face11: \"킁킁(왼쪽)\",\n                robotis_face12: \"킁킁(오른쪽)\",\n                robotis_face13: \"킁킁(아래)\",\n                robotis_face14: \"안심\",\n                robotis_face15: \"기절\",\n                robotis_face16: \"헤롱헤롱\",\n                robotis_face17: \"하품\",\n                robotis_face18: \"졸림\",\n                robotis_face19: \"잠듦\",\n                robotis_face20: \"마음앓이\",\n                robotis_face21: \"폭풍눈물\",\n                robotis_face22: \"목욕\",\n                robotis_face23: \"햐트뿅뿅\",\n                robotis_flashing1: \"점멸1\",\n                robotis_flashing2: \"점멸2\",\n                robotis_flashing3: \"점멸3\",\n                robotis_flashing4: \"점멸4\",\n                robotis_flashing5: \"점멸5\",\n                robotis_flashing6: \"점멸6\",\n                robotis_flashing7: \"점멸7\",\n                robotis_flashing8: \"점멸8\",\n                robotis_flashing9: \"점멸9\",\n                robotis_moveF: \"전진\",\n                robotis_moveB: \"후진\",\n                robotis_moveL: \"좌회전\",\n                robotis_moveR: \"우회전\",\n                robotis_moveRG1: \"일어서기\",\n                robotis_moveRG2: \"앉기\",\n                robotis_moveRG3: \"발버둥\",\n                robotis_moveRG4: \"발들기\",\n                robotis_stMotion1: \"기본자세\",\n                robotis_stMotion2: \"전진\",\n                robotis_stMotion3: \"우전진\",\n                robotis_stMotion4: \"좌전진\",\n                robotis_stMotion5: \"후진\",\n                robotis_stMotion6: \"오른쪽으로\",\n                robotis_stMotion7: \"왼쪽으로\",\n                robotis_stMotion8: \"우회전\",\n                robotis_stMotion9: \"좌회전\",\n                robotis_spMotion1: \"오른손 들기\",\n                robotis_spMotion2: \"오른손 내리기\",\n                robotis_spMotion3: \"왼손 들기\",\n                robotis_spMotion4: \"왼손 내리기\",\n                robotis_spMotion5: \"양손 들기\",\n                robotis_spMotion6: \"양손 내리기\",\n                robotis_spMotion7: \"뒤로 넘어지기\",\n                robotis_spMotion8: \"앞으로 넘어지기\",\n                robotis_spMotion9: \"앞으로 일어서기\",\n                robotis_spMotion10: \"뒤로 일어서기\",\n                robotis_spMotion11: \"방어\",\n                robotis_spMotion12: \"공격1\",\n                robotis_spMotion13: \"공격2\",\n                robotis_spMotion14: \"공격3\",\n                robotis_spMotion15: \"공격4\",\n                robotis_screen1: \"가위\",\n                robotis_screen2: \"바위\",\n                robotis_screen3: \"보\",\n            },\n        },\n        en: {\n            template: {\n                robotis_RB_cm_ir_value:\"IR sensor value of %1 Value of IR Sensor\",\n                robotis_RB_cm_ir_compare:\"If IR sensor value of %1 is %2 %3\",\n                robotis_RB_detectFrontObj:\"If there is an object in front\",\n                robotis_RB_cm_btn_value:\"If %1 button is %2\",\n                robotis_RB_cm_joystick_value:\"If the joystick location is %1\",\n                robotis_RB_mic:\"MIC volume(dB)\",\n                robotis_RB_detectSound_compare:\"If sound is detected from %1\",\n                robotis_RB_imu:\"%1 axis' %2 value\",\n                robotis_RB_roll_pitch:\"%1 Controller position \",\n                robotis_RB_environment_value: \"%1 %2 value\",\n                robotis_RB_environment_compare: \"If %1 %2 value is %3 %4\",\n                robotis_RB_distance_value: \"%1 %2 value\",\n                robotis_RB_distance_compare: \"If %1 %2 value is %3 %4\",\n                //robotis_RB_detectPose:\"If robot falls %1\",\n                \n                robotis_RB_cm_buzzer_index:\"%1 at %2 octaves for %3 second(s) -> %4 %5\",\n                robotis_RB_cm_screen:\"Choose %1 as a screen background %2\",\n                robotis_RB_cm_anim_screen: \"Choose %1 as a screen animation %2\",\n                robotis_RB_rsp_screen:\"Print %1 on the screen %5\",\n                \n                robotis_RB_LCDBright:\"Adjust screen brightness to %1 %2\",\n                robotis_RB_LCDColor:\"Set screen color to %1 %2\",\n                \n                robotis_RB_LEDBright:\"Set the brightness of the %1 LED to %2 %3\",\n                robotis_RB_cm_led:\"%1 LED %2 %3\",\n                \n                robotis_RB_Hello:\"Say %1 %2\",\n                robotis_RB_effectSound:\"Play the sound of %1 %2\",\n                robotis_RB_record:\"Record in room %1 %2\",\n                robotis_RB_playRecord:\"Play recorded sound in room %1 %2\",\n                \n                robotis_dxl_control:\"Move 1st motor %1°, 2nd motor %2°, 3rd motor %3°, 4th motor %4°, 5th motor %5°, 6th motor %6°, 7th motor %7°, 8th motor %8° for  second %9 %10\",\n                robotis_dxl_each_control:\"Move %1th motor %2° for %3 second\",\n                robotis_RB_cm_motion:\"Execute Humonoid motion %1 %2\",\n                robotis_RB_cm_motion2:\"Execute Humonoid motion2 %1 %2\",\n                robotis_RB_cm_motion_custom:\"Execute custom motion %1 %2\",\n                \n                \n            },\n            Blocks: {\n                robotis_red: \"Red\",\n                robotis_orange: \"Orange\",\n                robotis_yellow: \"Yellow\",\n                robotis_green: \"Green\",\n                robotis_blue: \"Blue\",\n                robotis_brown: \"Brown\",\n                robotis_black: \"Black\",\n                robotis_white: \"White\",\n                robotis_left: \"Left\",\n                robotis_center: \"Center\",\n                robotis_right: \"Right\",\n                robotis_both: \"Both\",\n                robotis_korean1: \"Hello!\",\n                robotis_korean2: \"Great to see you.\",\n                robotis_korean3: \"Okay ~\",\n                robotis_korean4: \"No!\",\n                robotis_korean5: \"I don't know.\",\n                robotis_korean6: \"I like it.\",\n                robotis_korean7: \"I don't like it.\",\n                robotis_korean8: \"What is your name? \",\n                robotis_korean9: \"How can I help you? \",\n                robotis_korean10: \"Great job! \",\n                robotis_korean11: \"It's alright.\",\n                robotis_korean12: \"Let's do it again! \",\n                robotis_korean13: \"Thank you! \",\n                robotis_korean14: \"Can you say that one more time?\",\n                robotis_korean15: \"Awesome!\",\n                robotis_korean16: \"I'm excited! \",\n                robotis_korean17: \"I'm having a great time! \",\n                robotis_korean18: \"I'm sorry.\",\n                robotis_korean19: \"I'm angry! \",\n                robotis_korean20: \"I'm embarassed.\",\n                robotis_korean21: \"I'm scared.\",\n                robotis_korean22: \"I'm upset.\",\n                robotis_korean23: \"I love you.\",\n                robotis_korean24: \"Very pretty! \",\n                robotis_korean25: \"Interesting.\",\n                robotis_korean26: \"I'm nervous.\",\n                robotis_korean27: \"Let's move forward! \",\n                robotis_korean28: \"Let's move backward! \",\n                robotis_korean29: \"Let's stand up! \",\n                robotis_korean30: \"Did you fall down? \",\n                robotis_korean31: \"Oh Yeah~\",\n                robotis_korean32: \"Sweet! \",\n                robotis_korean33: \"Oh no\",\n                robotis_korean34: \"My My \",\n                robotis_korean35: \"Whoo hoo! \",\n                robotis_korean36: \"Ha Ha Ha\",\n                robotis_korean37: \"Ho Ho Ho \",\n                robotis_korean38: \"I'm sleepy.\",\n                robotis_korean39: \"Sing me a bedtime song! \",\n                robotis_korean40: \"Hello!\",\n                robotis_korean41: \"I'm hungry.\",\n                robotis_korean42: \"I'm craving an acorn! \",\n                robotis_korean43: \"I want to take a bath! \",\n                robotis_korean44: \"Time for a bath! \",\n                robotis_korean45: \"I'm bored. \",\n                robotis_korean46: \"Do you want a snack? \",\n                robotis_korean47: \"I'm sick.\",\n                robotis_korean48: \"Do you have any medicine? \",\n                robotis_korean49: \"Where do we have to go? \",\n                robotis_korean50: \"We're here! \",\n                robotis_korean51: \"Let's go to the left side! \",\n                robotis_korean52: \"Let's go to the right side! \",\n                robotis_korean53: \"Oh my, you scared me! \",\n                robotis_korean54: \"Found you! \",\n                robotis_korean55: \"There's nothing here. \",\n                robotis_korean56: \"Did you call me?\",\n                robotis_korean57: \"Please let me down. \",\n                robotis_korean58: \"Oops! \",\n                robotis_korean59: \"Hmmph! \",\n                robotis_korean60: \"Eek! \",\n                robotis_dog: \"Dog\",\n                robotis_frog: \"Frog\",\n                robotis_cat: \"Cat\",\n                robotis_chicken: \"Rooster\",\n                robotis_tiger: \"Tiger\",\n                robotis_mouse: \"Mouse\",\n                robotis_ambul: \"Ambulance\",\n                robotis_Horn: \"CarHorn\",\n                robotis_siren: \"Siren\",\n                robotis_whistle: \"Whistle\",\n                robotis_gun: \"Gunshot\",\n                robotis_clap: \"Clap\",\n                robotis_melody1: \"Melody1\",\n                robotis_melody2: \"Melody2\",\n                robotis_melody3: \"Melody3\",\n                robotis_melody4: \"Melody4\",\n                robotis_forward: \"Forward\",\n                robotis_backward: \"Backward\",\n                robotis_acceleration: \"acceleration\",\n                robotis_gyro: \"gyro\",\n                robotis_run: \"Run\",\n                robotis_cancel: \"Cancel\",\n                robotis_push: \"Pressed\",\n                robotis_notPush: \"Unpressed\",\n                robotis_play: \"Play\",\n                robotis_rest: \"Rest\",\n                robotis_face01: \"Haha\",\n                robotis_face02: \"Smile\",\n                robotis_face03: \"Laugh\",\n                robotis_face04: \"Yum Yum\",\n                robotis_face05: \"Scared\",\n                robotis_face06: \"Uncomfortable\",\n                robotis_face07: \"Confused\",\n                robotis_face08: \"Dazed\",\n                robotis_face09: \"Yell\",\n                robotis_face10: \"Angry\",\n                robotis_face11: \"Sniff (Left)\",\n                robotis_face12: \"Sniff (Right)\",\n                robotis_face13: \"Sniff (Down)\",\n                robotis_face14: \"Whew\",\n                robotis_face15: \"Faint\",\n                robotis_face16: \"Dizzy\",\n                robotis_face17: \"Yawn\",\n                robotis_face18: \"Sleepy\",\n                robotis_face19: \"Sleep\",\n                robotis_face20: \"Sad\",\n                robotis_face21: \"Cry\",\n                robotis_face22: \"Bath\",\n                robotis_face23: \"Heart-Eyes\",\n                robotis_flashing1: \"Flashing1\",\n                robotis_flashing2: \"Flashing2\",\n                robotis_flashing3: \"Flashing3\",\n                robotis_flashing4: \"Flashing4\",\n                robotis_flashing5: \"Flashing5\",\n                robotis_flashing6: \"Flashing6\",\n                robotis_flashing7: \"Flashing7\",\n                robotis_flashing8: \"Flashing8\",\n                robotis_flashing9: \"Flashing9\",\n                robotis_moveF: \"Forward\",\n                robotis_moveB: \"Backward\",\n                robotis_moveL: \"LeftTurn\",\n                robotis_moveR: \"RightTurn\",\n                robotis_moveRG1: \"Stand\",\n                robotis_moveRG2: \"Sit\",\n                robotis_moveRG3: \"Struggle\",\n                robotis_moveRG4: \"RaiseFeet\",\n                robotis_stMotion1: \"Standard\",\n                robotis_stMotion2: \"Forward\",\n                robotis_stMotion3: \"TurnRight\",\n                robotis_stMotion4: \"TurnLeft\",\n                robotis_stMotion5: \"Backward\",\n                robotis_stMotion6: \"ToRight\",\n                robotis_stMotion7: \"ToLeft\",\n                robotis_stMotion8: \"TurnAroundRight\",\n                robotis_stMotion9: \"TurnAroundLeft\",\n                robotis_spMotion1: \"RightHandUp\",\n                robotis_spMotion2: \"RightHandDown\",\n                robotis_spMotion3: \"LeftHandUp\",\n                robotis_spMotion4: \"LeftHandDown\",\n                robotis_spMotion5: \"BothHandsUp\",\n                robotis_spMotion6: \"BothHandsDown\",\n                robotis_spMotion7: \"FallBackward\",\n                robotis_spMotion8: \"FallForward\",\n                robotis_spMotion9: \"StandForward\",\n                robotis_spMotion10: \"StandBackward\",\n                robotis_spMotion11: \"Defence\",\n                robotis_spMotion12: \"Offense1\",\n                robotis_spMotion13: \"Offense2\",\n                robotis_spMotion14: \"Offense3\",\n                robotis_spMotion15: \"Offense4\",\n                robotis_screen1: \"Sissor\",\n                robotis_screen2: \"Rock\",\n                robotis_screen3: \"Paper\",\n            },\n        }\n    }\n};\n\nEntry.Robotis_rb_H.getBlocks = function() {\n    return {\n        robotis_RB_cm_motion: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_stMotion1, '1'],\n                        [Lang.Blocks.robotis_stMotion2, '25'],\n                        [Lang.Blocks.robotis_stMotion3, '46'],\n                        [Lang.Blocks.robotis_stMotion4, '47'],\n                        [Lang.Blocks.robotis_stMotion5, '37'], //Lang.Blocks.robotis_common_green_color\n                        [Lang.Blocks.robotis_stMotion6, '38'],\n                        [Lang.Blocks.robotis_stMotion7, '39'],\n                        [Lang.Blocks.robotis_stMotion8, '41'],\n                        [Lang.Blocks.robotis_stMotion9, '40'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RB_cm_motion',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n                var extraTime = 0; \n\n                data_address =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[0];\n                data_length = Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[1];\n                data_value = script.getField('VALUE', script);\n\n\n                console.log(\"motion send\");\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, 0],\n                    [data_instruction, data_address, data_length, data_value]\n                ];\n               \n                switch(data_value){\n                    case '1':\n                        extraTime = 100;\n                        break;\n                    case '25':\n                    case '46':\n                    case '47':\n                        extraTime = 3000;\n                        break;\n                    case '37':\n                        extraTime = 3000;\n                        break;\n                    case '38':\n                        extraTime = 1000;\n                        break;\n                    case '39':\n                        extraTime = 1000;\n                        break;\n                    case '40':\n                        extraTime = 2300;\n                        break;\n                    case '41':\n                        extraTime = 2300;\n                        break;\n                    \n                    \n                }\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + extraTime + 300\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_motion(%1)'] },\n        },\n        robotis_RB_cm_motion2: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_spMotion1, '26'],\n                        [Lang.Blocks.robotis_spMotion2, '27'],\n                        [Lang.Blocks.robotis_spMotion3, '28'],\n                        [Lang.Blocks.robotis_spMotion4, '29'],\n                        [Lang.Blocks.robotis_spMotion5, '30'], //Lang.Blocks.robotis_common_green_color\n                        [Lang.Blocks.robotis_spMotion6, '31'],\n                        [Lang.Blocks.robotis_spMotion7, '32'],\n                        [Lang.Blocks.robotis_spMotion8, '33'],\n                        [Lang.Blocks.robotis_spMotion9, '48'],\n                        [Lang.Blocks.robotis_spMotion10, '35'],\n                        [Lang.Blocks.robotis_spMotion11, '36'],\n                        [Lang.Blocks.robotis_spMotion12, '42'],\n                        [Lang.Blocks.robotis_spMotion13, '43'],\n                        [Lang.Blocks.robotis_spMotion14, '44'],\n                        [Lang.Blocks.robotis_spMotion15, '45'],\n                    ],\n                    value: '26',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RB_cm_motion2',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n                var extraTime = 0; \n\n                data_address =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[0];\n                data_length = Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[1];\n                data_value = script.getField('VALUE', script);\n\n\n                console.log(\"motion send\");\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, 0],\n                    [data_instruction, data_address, data_length, data_value]\n                ];\n               \n                switch(data_value){\n                    case '26':\n                        extraTime = 800;\n                        break;\n                    case '27':\n                        extraTime = 1000;\n                        break;\n                    case '28':\n                        extraTime = 800;\n                        break;\n                    case '29':\n                        extraTime = 1000;\n                        break;\n                    case '30':\n                        extraTime = 800;\n                        break;\n                    case '31':\n                        extraTime = 1000;\n                        break;\n                    case '32':\n                        extraTime = 5800;\n                        break;\n                    case '33':\n                        extraTime = 3800;\n                        break;\n                    case '34':\n                        extraTime = 8400;\n                        break;\n                    case '35':\n                        extraTime = 4000;\n                        break;\n                    case '36':\n                        extraTime = 300;\n                        break;\n                    case '42':\n                        extraTime = 600;\n                        break;\n                    case '43':\n                        extraTime = 800;\n                        break;\n                    case '44':\n                        extraTime = 800;\n                        break;\n                    case '45':\n                        extraTime = 1000;\n                        break;  \n                    case '48':\n                        extraTime = 12400;\n                        break;     \n                }\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + extraTime + 200\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_motion(%1)'] },\n        },\n        \n       \n        robotis_RB_cm_motion_custom: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RB_cm_motion_custom',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n                var extraTime = 0; \n\n                data_address =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[0];\n                data_length = Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[1];\n                data_value = script.getNumberValue('VALUE', script);\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, 0],\n                    [data_instruction, data_address, data_length, data_value]\n                ];\n            \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_rb_H.delay\n                    //Entry.Robotis_openCM70.delay + extraTime + 200\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_motion_custom(%1)'] },\n        },\n        robotis_dxl_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                ],\n                type: 'robotis_dxl_control',\n            },\n            \n            paramsKeyMap: {\n                ANGLE1: 0,\n                ANGLE2: 1,\n                ANGLE3: 2,\n                ANGLE4: 3,\n                \n                ANGLE5: 4,\n                ANGLE6: 5,\n                ANGLE7: 6,\n                ANGLE8: 7,\n                TIME: 8\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H'],\n            func(entity, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 19;\n                var data_length = 1;\n                var data_value = 1;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [1]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [2]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [3]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [4]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [5]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [6]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [7]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [8]],\n                    [Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0],\n                ]\n                \n                var keyWord = 'ANGLE';\n                for(let i = 1; i < 9; i++) {   \n                    keyWord = 'ANGLE' + i;\n                    var value = script.getNumberValue('ANGLE' + i, script);\n                \n                    var engValue = 2048;\n                    engValue = Math.floor(2048 - Math.round(value * 4096) / 360);\n\n                    var time = script.getNumberValue('TIME', script) * 1000;\n                    \n                    var velocity = 0;\n                \n                    if(time == 0) {\n                        velocity = 0;\n                    } else {\n                        velocity = Math.round(Math.floor(60 * Math.abs(value - Entry.Robotis_rb.DXL_POSITION.values[i - 1]) * 1000 / 360 / time)/0.229);\n                    }\n\n                    Entry.Robotis_rb.DXL_POSITION.values[i - 1] = value;\n\n                    data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.REGWRITE, 112, 8, velocity * 4294967296 + engValue, [i]]);\n                    \n                }\n                \n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0]);\n\n                for(let j = 1; j < 9; j++) {\n                    data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.REGWRITE, 112, 4, 0, [j]]);\n\n                }\n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0]);\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    time + Entry.Robotis_openCM70.delay\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_control(%1)'] },\n        },\n\n        robotis_dxl_each_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [\"1\", '1'],\n                        [\"2\", '2'], //Lang.Blocks.robotis_common_green_color\n                        [\"3\", '3'],\n                        [\"4\", '4'],\n                        [\"5\", '5'],\n                        [\"6\", '6'],\n                        [\"7\", '7'],\n                        [\"8\", '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'robotis_dxl_each_control',\n            },\n            \n            paramsKeyMap: {\n                DXLNUM: 0,\n                ANGLE: 1,\n                TIME: 2,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H'],\n            func(entity, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 19;\n                var data_length = 1;\n                var data_value = 1;\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [1]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [2]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [3]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [4]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [5]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [6]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [7]],\n                    [Entry.Robotis_rb.INSTRUCTION.REGWRITE, 64, 1, 1, [8]],\n                    [Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0],\n\n                    \n                ]\n                \n                var dxlID = script.getField('DXLNUM', script);\n                var angle = script.getNumberValue('ANGLE', script);\n                var time = script.getNumberValue('TIME', script) * 1000;\n\n                var engValue = 2048;\n                engValue = Math.floor(2048 - Math.round(angle * 4096) / 360);\n                var velocity = 0;\n                \n                if(time == 0) {\n                    velocity = 0;\n                } else {\n                    velocity = Math.round(Math.floor(60 * Math.abs(angle - Entry.Robotis_rb.DXL_POSITION.values[dxlID - 1]) * 1000 / 360 / time)/0.229);\n                }\n\n                Entry.Robotis_rb.DXL_POSITION.values[dxlID - 1] = angle;\n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.REGWRITE, 112, 8, velocity * 4294967296 + engValue, [dxlID]]);\n                \n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0]);\n\n                for(let j = 1; j < 9; j++) {\n                    data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.REGWRITE, 112, 4, 0, [j]]);\n\n                }\n                data_sendqueue.push([Entry.Robotis_rb.INSTRUCTION.ACTION, 0, 0, 0]);\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    time + Entry.Robotis_openCM70.delay\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        },\n\n    };\n};\n\nmodule.exports = [Entry.Robotis_rb_H];\n\n\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotisRBKoala.js",
    "content": "'use strict';\n\nEntry.Robotis_rb_koala = {\n    INSTRUCTION: {\n        NONE: 0,\n        WRITE: 3,\n        READ: 2,\n        SYNCWRITE: 4,\n        REGWRITE: 5,\n        ACTION: 6\n    },\n    CONTROL_TABLE: {\n        // [default address, default length, address (when reads together), length (when reads together)]\n        RB_LED_L: [40, 1],\n        RB_LED_R: [41, 1],\n        RB_LED_B: [40, 2],\n    },\n    DXL_POSITION: {\n        values: [0,0,0,0,0,0,0,0]\n    },\n    setZero: function () {\n        // instruction / address / length / value / default length\n        Entry.hw.sendQueue['setZero'] = [1];\n        Entry.Robotis_carCont.update();\n        Entry.Robotis_carCont.setRobotisData(null);\n        Entry.hw.sendQueue['setZero'] = null;\n        Entry.Robotis_carCont.update();\n        Entry.Robotis_carCont.setRobotisData([\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 2100, 1, 2], // 값 2는 코알라 얼굴이 뜨도록(펌웨어는 v1.15.4부터)\n        ]);\n        Entry.Robotis_carCont.update();\n    },\n    id: ['7.C'],\n    name: 'Robotis_rb_koala',\n    url: 'https://www.robotis.com/shop/list.php?ca_id=1050',\n    imageName: 'robotis_RB100im_Koala.png',\n    title: {\n        \"ko\": \"코알라봇\",\n        \"en\": \"KoalaBot\"\n    },\n    delay: 30,\n    readDelay: 30,\n};\n\nEntry.Robotis_rb_koala.blockMenuBlocks = [\n\n    // 주행 제어\n    'robotis_RCar_drive_simple',\n    'robotis_RCar_drive_advanced',\n    'robotis_RCar_drive_seperate',\n    'robotis_RCar_drive_angle',\n    'robotis_RCar_go_distance',\n    'robotis_RCar_turn_angle',\n    'robotis_RCar_follow_line',\n    'robotis_RCar_stop_at_cross',\n    'robotis_RCar_turn_at_line',\n    'robotis_RCar_drive_stop',\n    //'robotis_RCar_follow_line_stop',\n    /*\n    'robotis_practice_robot_go',\n    'robotis_practice_robot_stop',\n    'robotis_practice_robot_rotate',\n    */\n\n    // 값 블록\n    'robotis_RCar_cm_ir_value',\n    'robotis_RCar_cm_ir_compare',\n    'robotis_RCar_detectFrontObj',\n    'robotis_RCar_cm_btn_value',\n    'robotis_RCar_cm_joystick_value',\n    'robotis_RCar_mic',\n    'robotis_RCar_detectSound_compare',\n    'robotis_RCar_imu',\n    'robotis_RCar_roll_pitch', \n    /*\n    'robotis_RCar_environment_value',\n    'robotis_RCar_environment_compare',\n    */\n    'robotis_RCar_distance_value',\n    'robotis_RCar_distance_compare',\n    'robotis_RCar_dxl_value',\n    'robotis_RCar_line_cross_compare',\n\n    // 소리\n    'robotis_RCar_scale_simple',\n    'robotis_RCar_scale_advanced',\n    'robotis_RCar_rest_simple',\n    'robotis_RCar_rest_advanced',\n    'robotis_RCar_beat_per_minute',\n    'robotis_RCar_Hello',\n    'robotis_RCar_effectSound',\n    'robotis_RCar_record',\n    'robotis_RCar_playRecord',\n\n    // LCD 제어\n    'robotis_RCar_screen',\n    'robotis_RCar_anim_screen',\n    'robotis_RCar_icon_screen_food_plant',\n    'robotis_RCar_icon_screen_animal_human',\n    'robotis_RCar_icon_screen_object_tool',\n    'robotis_RCar_icon_screen_vehicle_number',\n    'robotis_RCar_icon_screen_game_character',\n    'robotis_RCar_text_screen',\n    'robotis_RCar_text_screen_redraw',\n    'robotis_RCar_pixel',\n    'robotis_RCar_LCDColor',\n    'robotis_RCar_LCDBright',\n\n    // LED 제어\n    'robotis_RCar_cm_led',\n    'robotis_RCar_cm_led_pattern',\n\n    // AI 카메라 값 블록\n    'robotis_RCar_ai_camera_connection_status',\n    'robotis_RCar_ai_camera_if_detected',\n\n    'robotis_RCar_ai_camera_block_value_closest_to_center',\n    'robotis_RCar_ai_camera_arrow_value_closest_to_center',\n    'robotis_RCar_ai_camera_number_of_learned_id',\n    'robotis_RCar_ai_camera_block_value_of_id',\n    'robotis_RCar_ai_camera_arrow_value_of_id',\n\n    'robotis_RCar_ai_camera_if_learned_id',\n    'robotis_RCar_ai_camera_if_detected_id_type',\n\n    // AI 카메라 제어\n    'robotis_RCar_ai_camera_set_mode',\n    'robotis_RCar_ai_camera_print_custom_text',\n    'robotis_RCar_ai_camera_clear_custom_text',\n];\n\nEntry.Robotis_rb_koala.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                // 주행 제어\n                robotis_RCar_drive_simple: \"속도 %1 (으)로 %2 하기 %3\",\n                robotis_RCar_drive_advanced: \"왼쪽바퀴 %1 속도로 %2, 오른쪽바퀴 %3 속도로 %4 %5\",\n                robotis_RCar_drive_seperate: \"%1 바퀴 %2 속도로 %3 으로 회전하기 %4\",\n                robotis_RCar_drive_angle: \"양쪽 바퀴 %1 도만큼 %2 으로 회전하기 %3\",\n                robotis_RCar_go_distance: \"%1 cm %2 하기 %3\",\n                robotis_RCar_turn_angle: \"로봇 %1 도 %2 하기%3\",\n                robotis_RCar_follow_line: \"%1 속도로 라인 따라가기 %2\",\n                robotis_RCar_stop_at_cross: \"교차로 %1 에서 멈추기 %2\",\n                robotis_RCar_turn_at_line: \"교차로에서 %1 하고 멈추기 %2\",\n                robotis_RCar_drive_stop: \"정지하기 %1\",\n\n\n                // 값 블록\n                robotis_RCar_cm_ir_value: \"%1 적외선센서 값\",\n                robotis_RCar_cm_ir_compare: \"%1 적외선센서 값이 %2 보다 %3\",\n                robotis_RCar_detectFrontObj: \"%1의 앞에 물체가 있으면\",\n                robotis_RCar_cm_btn_value: \"로봇의 %1 버튼을 눌렀을 때\",\n                robotis_RCar_cm_joystick_value: \"로봇의 노랑 조이스틱 위치가 %1 이면\",\n                robotis_RCar_mic: \"소리의 크기(dB)\",\n                robotis_RCar_detectSound_compare: \"소리가 로봇의 %1에서 들리면\",\n                robotis_RCar_imu: \"%1축의 %2 값\",\n                robotis_RCar_roll_pitch: \"로봇의 %1 값\",\n                robotis_RCar_distance_value: \"%1 값\",\n                robotis_RCar_distance_compare: \"%1 값이 %2보다 %3\",\n                robotis_RCar_line_cross_compare: \"교차로 모양이 %1이면\",\n                robotis_RCar_dxl_value: \"%1의 각도값\",\n\n\n                // 소리\n                robotis_RCar_scale_simple: \"옥타브%1 로 %2 음을 %3로 연주하기 %4\",\n                robotis_RCar_scale_advanced: \"옥타브%1 로 %2 음을 %3박자 연주하기 %4\",\n                robotis_RCar_rest_simple: \"%1 %2\",\n                robotis_RCar_rest_advanced: \"쉼표 %1 박자 %2\",\n                robotis_RCar_beat_per_minute: \"연주 빠르기를 %1 (으)로 정하기 %2\",\n                robotis_RCar_Hello: \"로봇 %1 말하기 %2\",\n                robotis_RCar_effectSound: \"효과음 %1 재생하기 %2\",\n                robotis_RCar_record: \"소리 %1번에 녹음하기 %2\",\n                robotis_RCar_playRecord: \"소리 %1번을 재생하기 %2\",\n\n                \n                // LCD 제어\n                robotis_RCar_screen: \"화면 표정을 %1 %2 (으)로 정하기 %3\",\n                robotis_RCar_anim_screen: \"화면 애니메이션을 %1 %2 (으)로 정하기 %3\",\n                robotis_RCar_icon_screen_food_plant: \"화면에 [음식/식물]중 %1 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_RCar_icon_screen_animal_human: \"화면에 [동물/사람]중 %1 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_RCar_icon_screen_object_tool: \"화면에 [물건/도구]중 %1 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_RCar_icon_screen_vehicle_number: \"화면에 [탈것/숫자]중 %1 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_RCar_icon_screen_game_character: \"화면에 [게임/캐릭터]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_RCar_text_screen: \"화면에 %1 (%2, %3)위치에 %4 로 %5으로 표시 %6\",\n                robotis_RCar_text_screen_redraw: \"화면에 %1 (%2, %3)위치에 %4으로 새로 표시 %5\",\n                robotis_RCar_pixel: \"화면 (%1, %2)위치에 %3 색 점 표시 %4\",\n                robotis_RCar_LCDBright: \"화면 밝기를 %1 (으)로 정하기 %2\",\n                robotis_RCar_LCDColor: \"화면 색상을 %1 (으)로 정하기 %2\",\n                \n                \n                // LED 제어\n                robotis_RCar_cm_led: \"로봇 %1 LED %2 %3\",\n                robotis_RCar_cm_led_pattern: \"LED %1 %2로 깜박이기 %3\",\n                \n                // AI Camera 값 블록\n                robotis_RCar_ai_camera_connection_status: \"AI 카메라 %1이면\",\n                robotis_RCar_ai_camera_if_detected: \"AI 카메라 %1 이/가 표시되면\",\n\n                robotis_RCar_ai_camera_block_value_closest_to_center: \"AI 카메라 화면 중앙과 가장 가까운 사각형의 %1\",\n                robotis_RCar_ai_camera_arrow_value_closest_to_center: \"AI 카메라 화면 중앙과 가장 가까운 화살표의 %1\",\n                robotis_RCar_ai_camera_number_of_learned_id: \"AI 카메라 학습한 ID의 갯수\",\n                robotis_RCar_ai_camera_block_value_of_id: \"AI 카메라 감지된 ID가 %1인 사각형의 %2\",\n                robotis_RCar_ai_camera_arrow_value_of_id: \"AI 카메라 감지된 ID가 %1인 화살표의 %2\",\n\n                robotis_RCar_ai_camera_if_learned_id: \"AI 카메라 ID가 %1인 데이터를 학습하였으면\",\n                robotis_RCar_ai_camera_if_detected_id_type: \"AI 카메라 ID가 %1인 %2데이터를 인식하였으면\",\n\n                // AI 카메라 제어\n                robotis_RCar_ai_camera_set_mode: \"AI 카메라 모드를 %1(으)로 설정 %2\",\n                robotis_RCar_ai_camera_print_custom_text: \"AI 카메라 화면 위치 (%1,%2)에 %3를 보여주기%4\",\n                robotis_RCar_ai_camera_clear_custom_text: \"AI 카메라 화면의 글 지우기 %1\",\n\n            },\n            Helper: {\n                // 주행 제어\n                robotis_RCar_drive_simple: \"코알라봇을 지정한 속도와 방향으로 주행\\n속도범위: -100 ~ 100\\n속도단위: %\",\n                robotis_RCar_drive_advanced: \"코알라봇의 좌,우 바퀴를 각각 지정한 속도와 방향으로 회전\\n속도범위: -100 ~ 100\\n속도단위: %\",\n                robotis_RCar_drive_seperate: \"코알라봇의 지정한 바퀴를 지정한 속도와 방향으로 회전\\n속도범위: -100 ~ 100\\n속도단위: %\",\n                robotis_RCar_drive_angle: \"코알라봇의 두 바퀴를 지정한 방향과 지정한 각도만큼 회전\\n각도범위: -5760 ~ 5760\\n각도단위: 도\",\n                robotis_RCar_go_distance: \"지정거리만큼 앞 또는 뒤로 이동\\n거리범위: -1000 ~ 1000\\n거리단위: mm\",\n                robotis_RCar_turn_angle: \"지정한 각도와 방향으로 제자리회전\\n각도범위: -360 ~ 360\\n각도단위: 도\",\n                robotis_RCar_follow_line: \"지정한 수준의 속도로 라인 따라가기 시작\",\n                robotis_RCar_stop_at_cross: \"지정한 교차로에서 멈추기\",\n                robotis_RCar_turn_at_line: \"교차로에서 지정한 회전을 하고 멈추기\",\n                robotis_RCar_drive_stop: \"코알라봇 정지하기\",\n\n                // 값 블록\n                robotis_RCar_cm_ir_value: \"지정한 번호의 IR 센서 값(범위: 0 ~ 200)\",\n                robotis_RCar_cm_ir_compare: \"지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_detectFrontObj: \"지정한 센서 앞에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_cm_btn_value: \"지정한 버튼이 눌렸다가 해제되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_cm_joystick_value: \"조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_mic: \"마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.\",\n                robotis_RCar_detectSound_compare: \"소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_imu: \"지정한 축의 지정한 가속도센서/자이로센서의 값\\n범위: -100 ~ 100\",\n                robotis_RCar_roll_pitch: \"roll/pitch 값\\nroll: -180° ~ 180°, pitch: -90° ~ 90°\",\n                robotis_RCar_distance_value: \"지정한 센서값\\n거리범위: 0 ~ 1000mm\\n밝기범위: 0 ~ 100%\\n버튼센서: 0(눌리지 않음) / 1(눌림)\",\n                robotis_RCar_distance_compare: \"지정한 센서값의 지정한 수식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_line_cross_compare: \"지정한 교차로 모양이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_dxl_value: \"지정한 모터의 위치 각도값\\n범위: -180° ~ 180°\",\n\n\n                // 소리\n                robotis_RCar_scale_simple: \"지정한 옥타브, 음계, 음표로 연주하기\",\n                robotis_RCar_scale_advanced: \"지정한 옥타브, 음계, 박자로 연주하기\",\n                robotis_RCar_rest_simple: \"지정한 쉼표 쉬기\",\n                robotis_RCar_rest_advanced: \"지정한 박자 쉬기\",\n                robotis_RCar_beat_per_minute: \"연주 빠르기를 지정하기 (BPM)\\n범위: 10 ~ 600\",\n                robotis_RCar_Hello: \"로봇이 지정한 말소리를 재생하기\",\n                robotis_RCar_effectSound: \"로봇이 지정한 효과음을 재생하기\",\n                robotis_RCar_record: \"지정번호 보관함에 녹음하여 저장하기\",\n                robotis_RCar_playRecord: \"지정번호 보관함의 녹음음성을 재생하기\",\n\n                \n                // LCD 제어\n                robotis_RCar_screen: \"제어기 화면배경의 캐릭터와 표정을 설정\",\n                robotis_RCar_anim_screen: \"제어기 화면 애니메이션의 캐릭터와 표정을 설정\",\n                robotis_RCar_icon_screen_food_plant: \"화면에 [음식/식물]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_RCar_icon_screen_animal_human: \"화면에 [동물/사람]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_RCar_icon_screen_object_tool: \"화면에 [물건/도구]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_RCar_icon_screen_vehicle_number: \"화면에 [탈것/숫자]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_RCar_icon_screen_game_character: \"화면에 [게임/캐릭터]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_RCar_text_screen: \"화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\",\n                robotis_RCar_text_screen_redraw: \"화면에 지정한 문구를 새롭게(문구의 배경 지움) 표시할 위치와 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_RCar_pixel: \"화면에 표시할 점의 위치와 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\",\n                robotis_RCar_LCDBright: \"화면 밝기를 설정\\n밝기범위: 1% ~ 100%\",\n                robotis_RCar_LCDColor: \"화면 색상을 설정\",\n\n                // LED 제어\n                robotis_RCar_cm_led: \"제어기의 지정한 LED를 켜거나 끄기\",\n                robotis_RCar_cm_led_pattern: \"제어기의 LED의 깜박임 패턴 설정\",\n                \n                // AI Camera 값 블록\n                robotis_RCar_ai_camera_connection_status: \"AI 카메라가 연결된 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_ai_camera_if_detected: \"AI 카메라의 LCD화면에 선택한 기호(사각형/화살표)가 표시되면 '참', 아니면 '거짓'으로 판단합니다.\",\n\n                robotis_RCar_ai_camera_block_value_closest_to_center: \"AI 카메라 화면 중앙과 가장 가까운 사각형의 X좌표/Y좌표/너비/높이/학습ID\",\n                robotis_RCar_ai_camera_arrow_value_closest_to_center: \"AI 카메라 화면 중앙과 가장 가까운 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표/학습ID\",\n                robotis_RCar_ai_camera_number_of_learned_id: \"AI 카메라가 학습한 ID의 갯수\",\n                robotis_RCar_ai_camera_block_value_of_id: \"AI 카메라가 감지한 사각형중 지정한 ID의 사각형의 X좌표/Y좌표/너비/높이\",\n                robotis_RCar_ai_camera_arrow_value_of_id: \"AI 카메라가 감지한 화살표중 지정한 ID의 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표\",\n\n                robotis_RCar_ai_camera_if_learned_id: \"AI 카메라가 지정한 ID인 데이터를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_RCar_ai_camera_if_detected_id_type: \"AI 카메라가 지정한 ID인 지정한 데이터(사각형/화살표)를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.\",\n\n                // AI 카메라 제어\n                robotis_RCar_ai_camera_set_mode: \"AI 카메라의 모드를 설정\",\n                robotis_RCar_ai_camera_print_custom_text: \"AI 카메라 화면의 지정한 위치에 지정한 문구 출력\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\",\n                robotis_RCar_ai_camera_clear_custom_text: \"AI 카메라 화면에 표시한 모든 문구 지우기\",\n            },\n            Blocks: {\n                robotis_red: \"빨강\",\n                robotis_orange: \"주황\",\n                robotis_yellow: \"노랑\",\n                robotis_green: \"초록\",\n                robotis_blue: \"파랑\",\n                robotis_brown: \"갈색\",\n                robotis_black: \"검정\",\n                robotis_white: \"흰색\",\n                robotis_left: \"왼쪽\",\n                robotis_center: \"중앙\",\n                robotis_right: \"오른쪽\",\n                robotis_both: \"양쪽\",\n                robotis_rgee: \"알쥐\",\n                robotis_rla: \"알라\",\n                robotis_kkokdu: \"꼭두\",\n                robotis_korean1: \"안녕하세요\",\n                robotis_korean2: \"반가워요\",\n                robotis_korean3: \"알겠어요\",\n                robotis_korean4: \"아니에요\",\n                robotis_korean5: \"모르겠어요\",\n                robotis_korean6: \"좋아요\",\n                robotis_korean7: \"싫어요\",\n                robotis_korean8: \"이름을말하세요\",\n                robotis_korean9: \"무엇을도와줄까?\",\n                robotis_korean10: \"잘했어\",\n                robotis_korean11: \"괜찮아\",\n                robotis_korean12: \"다시해보자\",\n                robotis_korean13: \"고마워\",\n                robotis_korean14: \"다시말해줄래?\",\n                robotis_korean15: \"최고야!\",\n                robotis_korean16: \"신나요\",\n                robotis_korean17: \"즐거워요\",\n                robotis_korean18: \"미안해요\",\n                robotis_korean19: \"화나요\",\n                robotis_korean20: \"부끄러워요\",\n                robotis_korean21: \"무서워요\",\n                robotis_korean22: \"속상해요\",\n                robotis_korean23: \"사랑해요\",\n                robotis_korean24: \"예뻐요\",\n                robotis_korean25: \"신기해요\",\n                robotis_korean26: \"초조해요\",\n                robotis_korean27: \"앞으로가자\",\n                robotis_korean28: \"뒤로가자\",\n                robotis_korean29: \"일어나자\",\n                robotis_korean30: \"넘어졌네?\",\n                robotis_korean31: \"오예\",\n                robotis_korean32: \"아싸\",\n                robotis_korean33: \"어머\",\n                robotis_korean34: \"이런\",\n                robotis_korean35: \"오호\",\n                robotis_korean36: \"하하하\",\n                robotis_korean37: \"호호호\",\n                robotis_korean38: \"졸려\",\n                robotis_korean39: \"자장가를들려줘\",\n                robotis_korean40: \"안녕\",\n                robotis_korean41: \"배고프다\",\n                robotis_korean42: \"도토리땡긴다\",\n                robotis_korean43: \"아.씻고싶어\",\n                robotis_korean44: \"비누목욕시간이야\",\n                robotis_korean45: \"심심한데\",\n                robotis_korean46: \"간식먹을까\",\n                robotis_korean47: \"아파요\",\n                robotis_korean48: \"약은없나요?\",\n                robotis_korean49: \"어디로가야하지?\",\n                robotis_korean50: \"와아도착이다\",\n                robotis_korean51: \"왼쪽으로가자\",\n                robotis_korean52: \"오른쪽으로가자\",\n                robotis_korean53: \"깜짝이야\",\n                robotis_korean54: \"찾았다\",\n                robotis_korean55: \"여긴없네\",\n                robotis_korean56: \"혹시나불렀어?\",\n                robotis_korean57: \"내려주세요\",\n                robotis_korean58: \"앗\",\n                robotis_korean59: \"힝\",\n                robotis_korean60: \"이익\",\n                robotis_koala: \"코알라\",\n                robotis_dog: \"개\",\n                robotis_frog: \"개구리\",\n                robotis_cat: \"고양이\",\n                robotis_chicken: \"닭\",\n                robotis_tiger: \"호랑이\",\n                robotis_mouse: \"쥐\",\n                robotis_whistle: \"호루라기\",\n                robotis_ambul: \"앰뷸런스\",\n                robotis_Horn: \"경적(빵빵)\",\n                robotis_siren: \"사이렌(경찰차)\",\n                robotis_gun: \"총소리\",\n                robotis_clap: \"박수소리\",\n                robotis_melody1: \"멜로디1\",\n                robotis_melody2: \"멜로디2\",\n                robotis_melody3: \"멜로디3\",\n                robotis_melody4: \"멜로디4\",\n                robotis_forward: \"앞으로\",\n                robotis_backward: \"뒤로\",\n                robotis_acceleration: \"가속도\",\n                robotis_gyro: \"자이로\",\n                robotis_run: \"실행\",\n                robotis_cancel: \"취소\",\n                robotis_push: \"눌림\",\n                robotis_notPush: \"안눌림\",\n                robotis_play: \"연주\",\n                robotis_rest: \"쉼표\",\n                robotis_face01: \"와하하\",\n                robotis_face02: \"싱글벙글\",\n                robotis_face03: \"큭큭큭\",\n                robotis_face04: \"냠냠\",\n                robotis_face05: \"겁먹음\",\n                robotis_face06: \"답답\",\n                robotis_face07: \"갸우뚱\",\n                robotis_face08: \"어벙벙\",\n                robotis_face09: \"고함\",\n                robotis_face10: \"화남\",\n                robotis_face11: \"킁킁(왼쪽)\",\n                robotis_face12: \"킁킁(오른쪽)\",\n                robotis_face13: \"킁킁(아래)\",\n                robotis_face14: \"안심\",\n                robotis_face15: \"기절\",\n                robotis_face16: \"헤롱헤롱\",\n                robotis_face17: \"하품\",\n                robotis_face18: \"졸림\",\n                robotis_face19: \"잠듦\",\n                robotis_face20: \"마음앓이\",\n                robotis_face21: \"폭풍눈물\",\n                robotis_face22: \"목욕\",\n                robotis_face23: \"햐트뿅뿅\",\n\n                robotis_pattern1: \"패턴1\",\n                robotis_pattern2: \"패턴2\",\n                robotis_pattern3: \"패턴3\",\n                robotis_moveF: \"전진\",\n                robotis_moveB: \"후진\",\n                robotis_moveL: \"좌회전\",\n                robotis_moveR: \"우회전\",\n                robotis_moveU: \"U턴\",\n                robotis_moveL_in_place: \"제자리 좌회전\",\n                robotis_moveR_in_place: \"제자리 우회전\",\n                robotis_moveU_in_place: \"제자리 U턴\",\n                robotis_moveRG1: \"일어서기\",\n                robotis_moveRG2: \"앉기\",\n                robotis_moveRG3: \"발버둥\",\n                robotis_moveRG4: \"발들기\",\n                robotis_fast: '빠른',\n                robotis_normal: '보통',\n                robotis_slow: '느린',\n                robotis_stop: \"정지\",\n                robotis_roll: \"좌우 회전각 (roll)\",\n                robotis_pitch: \"앞뒤 회전각 (pitch)\",\n                robotis_direction_forward: \"전진방향\",\n                robotis_direction_backward: \"후진방향\",\n                robotis_stMotion1: \"기본자세\",\n                robotis_stMotion2: \"전진\",\n                robotis_stMotion3: \"우전진\",\n                robotis_stMotion4: \"좌전진\",\n                robotis_stMotion5: \"후진\",\n                robotis_stMotion6: \"오른쪽으로\",\n                robotis_stMotion7: \"왼쪽으로\",\n                robotis_stMotion8: \"우회전\",\n                robotis_stMotion9: \"좌회전\",\n                robotis_spMotion1: \"오른손 들기\",\n                robotis_spMotion2: \"오른손 내리기\",\n                robotis_spMotion3: \"왼손 들기\",\n                robotis_spMotion4: \"왼손 내리기\",\n                robotis_spMotion5: \"양손 들기\",\n                robotis_spMotion6: \"양손 내리기\",\n                robotis_spMotion7: \"뒤로 넘어지기\",\n                robotis_spMotion8: \"앞으로 넘어지기\",\n                robotis_spMotion9: \"앞으로 일어서기\",\n                robotis_spMotion10: \"뒤로 일어서기\",\n                robotis_spMotion11: \"방어\",\n                robotis_spMotion12: \"공격1\",\n                robotis_spMotion13: \"공격2\",\n                robotis_spMotion14: \"공격3\",\n                robotis_spMotion15: \"공격4\",\n                robotis_screen1: \"가위\",\n                robotis_screen2: \"바위\",\n                robotis_screen3: \"보\",\n                robotis_icon_food_plant_1: \"우유\",\n                robotis_icon_food_plant_2: \"나무\",\n                robotis_icon_food_plant_3: \"스프\",\n                robotis_icon_food_plant_4: \"케익\",\n                robotis_icon_food_plant_5: \"물\",\n                robotis_icon_food_plant_6: \"주스\",\n                robotis_icon_food_plant_7: \"당근\",\n                robotis_icon_food_plant_8: \"사과\",\n                robotis_icon_food_plant_9: \"오렌지\",\n                robotis_icon_food_plant_10: \"고기\",\n                robotis_icon_food_plant_11: \"화분\",\n                robotis_icon_food_plant_12: \"장미\",\n                robotis_icon_food_plant_13: \"포도\",\n                robotis_icon_food_plant_14: \"감자\",\n                robotis_icon_food_plant_15: \"사탕\",\n                robotis_icon_food_plant_16: \"치즈\",\n                robotis_icon_food_plant_17: \"식빵\",\n                robotis_icon_food_plant_18: \"꽃들\",\n                robotis_icon_food_plant_19: \"커피\",\n                robotis_icon_food_plant_20: \"튤립\",\n                robotis_icon_food_plant_21: \"바나나\",\n                robotis_icon_food_plant_22: \"과일들\",\n                robotis_icon_food_plant_23: \"햄버거\",\n                robotis_icon_food_plant_24: \"피자\",\n                robotis_icon_animal_human_1: \"시바견\",\n                robotis_icon_animal_human_2: \"강아지\",\n                robotis_icon_animal_human_3: \"곰\",\n                robotis_icon_animal_human_4: \"새\",\n                robotis_icon_animal_human_5: \"오리\",\n                robotis_icon_animal_human_6: \"사자\",\n                robotis_icon_animal_human_7: \"호랑이\",\n                robotis_icon_animal_human_8: \"말\",\n                robotis_icon_animal_human_9: \"양\",\n                robotis_icon_animal_human_10: \"상어1(왼쪽)\",\n                robotis_icon_animal_human_11: \"상어1(오른쪽)\",\n                robotis_icon_animal_human_12: \"상어2(왼쪽)\",\n                robotis_icon_animal_human_13: \"상어2(오른쪽)\",\n                robotis_icon_animal_human_14: \"물고기1\",\n                robotis_icon_animal_human_15: \"물고기2\",\n                robotis_icon_animal_human_16: \"물고기3\",\n                robotis_icon_animal_human_17: \"문어\",\n                robotis_icon_animal_human_18: \"원숭이\",\n                robotis_icon_animal_human_19: \"닭\",\n                robotis_icon_animal_human_20: \"돼지\",\n                robotis_icon_animal_human_21: \"사람(살찐)\",\n                robotis_icon_animal_human_22: \"사람(수영복)\",\n                robotis_icon_animal_human_23: \"아기\",\n                robotis_icon_animal_human_24: \"사람(달리는)\",\n                robotis_icon_animal_human_25: \"사람(노래하는)\",\n                robotis_icon_animal_human_26: \"사람(앉은)\",\n                robotis_icon_animal_human_27: \"사람(화난)\",\n                robotis_icon_animal_human_28: \"사람(만세)\",\n                robotis_icon_animal_human_29: \"왕\",\n                robotis_icon_animal_human_30: \"왕자\",\n                robotis_icon_animal_human_31: \"공주\",\n                robotis_icon_animal_human_32: \"요리사\",\n                robotis_icon_animal_human_33: \"의사\",\n                robotis_icon_animal_human_34: \"간호사\",\n                robotis_icon_object_tool_1: \"가방\",\n                robotis_icon_object_tool_2: \"상자\",\n                robotis_icon_object_tool_3: \"머그컵\",\n                robotis_icon_object_tool_4: \"모자(중절모)\",\n                robotis_icon_object_tool_5: \"모자(캡모자)\",\n                robotis_icon_object_tool_6: \"열쇠\",\n                robotis_icon_object_tool_7: \"장난감\",\n                robotis_icon_object_tool_8: \"책\",\n                robotis_icon_object_tool_9: \"곰인형\",\n                robotis_icon_object_tool_10: \"드럼\",\n                robotis_icon_object_tool_11: \"메모장\",\n                robotis_icon_object_tool_12: \"볼펜\",\n                robotis_icon_object_tool_13: \"책상\",\n                robotis_icon_object_tool_14: \"테이블\",\n                robotis_icon_object_tool_15: \"의자\",\n                robotis_icon_object_tool_16: \"침대\",\n                robotis_icon_object_tool_17: \"텐트\",\n                robotis_icon_object_tool_18: \"접시\",\n                robotis_icon_object_tool_19: \"축구공\",\n                robotis_icon_object_tool_20: \"종\",\n                robotis_icon_object_tool_21: \"손목시계\",\n                robotis_icon_object_tool_22: \"신발\",\n                robotis_icon_object_tool_23: \"전등\",\n                robotis_icon_object_tool_24: \"라디오\",\n                robotis_icon_object_tool_25: \"지폐\",\n                robotis_icon_object_tool_26: \"자\",\n                robotis_icon_object_tool_27: \"카메라\",\n                robotis_icon_object_tool_28: \"스푼\",\n                robotis_icon_object_tool_29: \"건반\",\n                robotis_icon_object_tool_30: \"달력\",\n                robotis_icon_object_tool_31: \"칼\",\n                robotis_icon_object_tool_32: \"풍선\",\n                robotis_icon_object_tool_33: \"물통\",\n                robotis_icon_object_tool_34: \"나무막대(가로)\",\n                robotis_icon_object_tool_35: \"나무막대(세로)\",\n                robotis_icon_object_tool_36: \"낚시바늘\",\n                robotis_icon_vehicle_number_1: \"자동차\",\n                robotis_icon_vehicle_number_2: \"버스\",\n                robotis_icon_vehicle_number_3: \"트럭\",\n                robotis_icon_vehicle_number_4: \"지프\",\n                robotis_icon_vehicle_number_5: \"자전거\",\n                robotis_icon_vehicle_number_6: \"전철\",\n                robotis_icon_vehicle_number_7: \"기차\",\n                robotis_icon_vehicle_number_8: \"비행기\",\n                robotis_icon_vehicle_number_9: \"전투기(세로)\",\n                robotis_icon_vehicle_number_10: \"전투기(가로)\",\n                robotis_icon_vehicle_number_11: \"로켓\",\n                robotis_icon_vehicle_number_12: \"어선\",\n                robotis_icon_vehicle_number_13: \"여객선\",\n                robotis_icon_vehicle_number_14: \"잠수함(왼쪽)\",\n                robotis_icon_vehicle_number_15: \"잠수함(오른쪽)\",\n                robotis_icon_vehicle_number_16: \"비행기(왼쪽)\",\n                robotis_icon_vehicle_number_17: \"비행기(오른쪽)\",\n                robotis_icon_vehicle_number_18: \"비행기(윗쪽)\",\n                robotis_icon_vehicle_number_19: \"우주선(왼쪽)\",\n                robotis_icon_vehicle_number_20: \"우주선(오른쪽)\",\n                robotis_icon_vehicle_number_21: \"우주선(윗쪽)\",\n                robotis_icon_vehicle_number_22: \"주사위(1)\",\n                robotis_icon_vehicle_number_23: \"주사위(2)\",\n                robotis_icon_vehicle_number_24: \"주사위(3)\",\n                robotis_icon_vehicle_number_25: \"주사위(4)\",\n                robotis_icon_vehicle_number_26: \"주사위(5)\",\n                robotis_icon_vehicle_number_27: \"주사위(6)\",\n                robotis_icon_vehicle_number_28: \"0\",\n                robotis_icon_vehicle_number_29: \"1\",\n                robotis_icon_vehicle_number_30: \"2\",\n                robotis_icon_vehicle_number_31: \"3\",\n                robotis_icon_vehicle_number_32: \"4\",\n                robotis_icon_vehicle_number_33: \"5\",\n                robotis_icon_vehicle_number_34: \"6\",\n                robotis_icon_vehicle_number_35: \"7\",\n                robotis_icon_vehicle_number_36: \"8\",\n                robotis_icon_vehicle_number_37: \"9\",\n                robotis_icon_vehicle_number_38: \"10\",\n                robotis_icon_game_character_1: '알쥐(정면)',\n                robotis_icon_game_character_2: '알쥐(왼쪽)',\n                robotis_icon_game_character_3: '알쥐(오른쪽)',\n                robotis_icon_game_character_4: '알라(정면)',\n                robotis_icon_game_character_5: '알라(왼쪽))',\n                robotis_icon_game_character_6: '알라(오른쪽)',\n                robotis_icon_game_character_7: '유령',\n                robotis_icon_game_character_8: '괴물',\n                robotis_icon_game_character_9: '바이러스',\n                robotis_icon_game_character_10: '세균',\n                robotis_icon_game_character_11: '나는 알쥐(왼쪽)',\n                robotis_icon_game_character_12: '나는 알쥐(오른쪽)',\n                robotis_icon_game_character_13: '나는 알쥐(정면)',\n                robotis_icon_game_character_14: '메달',\n                robotis_icon_game_character_15: '돈(G)',\n                robotis_icon_game_character_16: '돈($)',\n                robotis_icon_game_character_17: '하트',\n                robotis_icon_game_character_18: '폭탄',\n                robotis_icon_game_character_19: '불',\n                robotis_icon_game_character_20: '구름1',\n                robotis_icon_game_character_21: '구름2',\n                robotis_icon_game_character_22: '포탄1',\n                robotis_icon_game_character_23: '포탄2',\n                robotis_icon_game_character_24: '대포(수평)',\n                robotis_icon_game_character_25: '대포(수직)',\n                robotis_icon_game_character_26: '레이저(수직)',\n                robotis_icon_game_character_27: '게이저(수평)',\n                robotis_icon_game_character_28: '화살(수평)',\n                robotis_icon_game_character_29: '화살(수직)',\n                robotis_icon_game_character_30: '미사일(U)',\n                robotis_icon_game_character_31: '미사일(D)',\n                robotis_icon_game_character_32: '미사일(L)',\n                robotis_icon_game_character_33: '미사일(R)',\n                robotis_icon_game_character_34: '낙하산',\n                robotis_icon_game_character_35: '폭발1',\n                robotis_icon_game_character_36: '폭발2',\n                robotis_icon_game_character_37: '조준경',\n                robotis_icon_game_character_38: '가위',\n                robotis_icon_game_character_39: '바위',\n                robotis_icon_game_character_40: '보',\n                robotis_icon_game_character_41: '걷는 사람1',\n                robotis_icon_game_character_42: '걷는 사람2',\n                robotis_icon_game_character_43: '뛰는 사람1',\n                robotis_icon_game_character_44: '뛰는 사람2',\n                robotis_speed_fast: \"빠른 속도\",\n                robotis_speed_midium: \"중간 속도\",\n                robotis_speed_slow: \"느린 속도\",\n                robotis_clockwise: \"시계방향\",\n                robotis_counterclockwise: \"반시계방향\",\n                robotis_up: \"들기\",\n                robotis_down: \"내리기\",\n                robotis_if_greater: \"크면\",\n                robotis_if_smaller: \"작으면\",\n                robotis_if_equal: \"같으면\",\n                robotis_front_right: \"앞 오른쪽\",\n                robotis_front_left: \"앞 왼쪽\",\n                robotis_bottom_right: \"아래 오른쪽\",\n                robotis_bottom_left: \"아래 왼쪽\",\n                robotis_side_right: \"오른쪽 모서리\",\n                robotis_side_left: \"왼쪽 모서리\",\n                robotis_front_ir_sensor: \"적외선센서\",\n                robotis_distance_sensor: \"거리센서\",\n                robotis_front: \"앞\",\n                robotis_right: \"오른쪽\",\n                robotis_left_wheel: \"왼쪽바퀴\",\n                robotis_right_wheel: \"오른쪽바퀴\",\n                // https://namu.wiki/w/%EC%9D%8C%ED%91%9C\n                robotis_beat_sound_8th_note: \"8분음표 (♪)\",\n                robotis_beat_sound_dotted_8th_note: \"점8분음표 (♪.)\",\n                robotis_beat_sound_quarter_note: \"4분음표 (♩)\",\n                robotis_beat_sound_dotted_quarter_note: \"점4분음표 (♩.)\",\n                robotis_beat_sound_half_note: \"2분음표 (𝅗𝅥)\",\n                robotis_beat_sound_dotted_half_note: \"점2분음표 (𝅗𝅥.)\",\n                robotis_beat_sound_whole_note: \"온음표 (𝅝)\",\n                robotis_beat_sound_dotted_note: \"점온음표 (𝅝.)\",\n                robotis_beat_rest_8th_note: \"8분쉼표 (𝄾)\",\n                robotis_beat_rest_dotted_8th_note: \"점8분쉼표 (𝄾.)\",\n                robotis_beat_rest_quarter_note: \"4분쉼표 (𝄽)\",\n                robotis_beat_rest_dotted_quarter_note: \"점4분쉼표 (𝄽.)\",\n                robotis_beat_rest_half_note: \"2분쉼표 (𝄼)\",\n                robotis_beat_rest_dotted_half_note: \"점2분쉼표 (𝄼˙)\",\n                robotis_beat_rest_whole_note: \"온쉼표 (𝄻)\",\n                robotis_beat_rest_dotted_note: \"점온쉼표 (𝄻˙)\",\n                robotis_line_cross_type_0: \"|\",\n                robotis_line_cross_type_1: \" (공백)\",\n                robotis_line_cross_type_5: \"🞣\",\n                robotis_line_cross_type_6: \"⏉\",\n                robotis_line_cross_type_7: \"⊣\",\n                robotis_line_cross_type_8: \"⊢\",\n                robotis_line_cross_type_9: \"⏋\",\n                robotis_line_cross_type_10: \"⎾\",\n                robotis_line_cross_type_11: \"¦\",\n                robotis_line_cross_type_12: \"︙\",\n\n                robotis_connected: \"연결\",\n                robotis_disconnected: \"없음\",\n                robotis_ai_camera_mode_face_recognition: \"얼굴인식\",\n                robotis_ai_camera_mode_object_tracking: \"물체추적\",\n                robotis_ai_camera_mode_object_recognition: \"물체인식\",\n                robotis_ai_camera_mode_line_tracking: \"라인인식\",\n                robotis_ai_camera_mode_color_recognition: \"색상인식\",\n                robotis_ai_camera_mode_tag_recognition: \"태그인식\",\n                robotis_ai_camera_mode_object_classification: \"물체분류\",\n                robotis_ai_camera_block: \"사각형\",\n                robotis_ai_camera_arrow: \"화살표\",\n                robotis_ai_camera_center_block_center_x: \"중심 X좌표\",\n                robotis_ai_camera_center_block_center_y: \"중심 Y좌표\",\n                robotis_ai_camera_center_block_width: \"너비\",\n                robotis_ai_camera_center_block_height: \"높이\",\n                robotis_ai_camera_center_leared_id: \"학습ID\",\n                robotis_ai_camera_center_arrow_origin_x: \"시작점 X좌표\",\n                robotis_ai_camera_center_arrow_origin_y: \"시작점 Y좌표\",\n                robotis_ai_camera_center_arrow_target_x: \"끝점 X좌표\",\n                robotis_ai_camera_center_arrow_target_y: \"끝점 Y좌표\",\n            },\n        },\n        en: {\n            template: {\n                // 주행 제어\n                robotis_RCar_drive_simple: \"Move %2 with velocity %1 %3\",\n                robotis_RCar_drive_advanced: \"Left wheel %2 with velocity %1, right wheel %4 with velocity %3 %5\",\n                robotis_RCar_drive_seperate: \"%1 wheel rotate %3 with velocity %2 %4\",\n                robotis_RCar_drive_angle: \"Both wheels rotate %1 degree %2 %3\",\n                robotis_RCar_go_distance: \"Moves %2 %1 cm %3\",\n                robotis_RCar_turn_angle: \"Rotates %1 degree(s) %2 in place %3\",\n                robotis_RCar_follow_line: \"Follow line with %1 speed %2\",\n                robotis_RCar_stop_at_cross: \"Stop at cross %1 %2\",\n                robotis_RCar_turn_at_line: \"%1 at cross and stop %2\",\n                robotis_RCar_drive_stop: \"Stop %1\",\n        \n        \n                // 값 블록\n                robotis_RCar_cm_ir_value: \"Value of %1 IR Sensor\",\n                robotis_RCar_cm_ir_compare: \"If the number %1 IR sensor value is %3 than %2\",\n                robotis_RCar_detectFrontObj: \"If there is an object in front of %1\",\n                robotis_RCar_cm_btn_value: \"When the robot's %1 button is pressed\",\n                robotis_RCar_cm_joystick_value: \"If the robot's yellow joystick position is %1\",\n                robotis_RCar_mic: \"MIC volume(dB)\",\n                robotis_RCar_detectSound_compare: \"If sound is detected from %1 of the robot\",\n                robotis_RCar_imu: \"%1 axis' %2 value\",\n                robotis_RCar_roll_pitch: \"%1 value of the controller\",\n                robotis_RCar_distance_value: \"%1 value\",\n                robotis_RCar_distance_compare: \"If %1 value is %3 than %2\",\n                robotis_RCar_line_cross_compare: \"If the type of cross is %1\",\n                robotis_RCar_dxl_value: \"The angle of ID %1\",\n        \n        \n                // 소리\n                robotis_RCar_scale_simple: \"Play the note %2 as %3 in octave %1 %4\",\n                robotis_RCar_scale_advanced: \"Play the note %2 in octave %1 for %3 beat %4\",\n                robotis_RCar_rest_simple: \"%1 %2\",\n                robotis_RCar_rest_advanced: \"Rest %1 beat %2\",\n                robotis_RCar_beat_per_minute: \"Set playing speed to %1 %2\",\n                robotis_RCar_Hello: \"Robot speaks %1 %2\",\n                robotis_RCar_effectSound: \"Play sound effect %1 %2\",\n                robotis_RCar_record: \"Record to sound slot %1 %2\",\n                robotis_RCar_playRecord: \"Play sound from slot %1 %2\",\n        \n                \n                // LCD 제어\n                robotis_RCar_screen: \"Set screen expression to %1 %2 %3\",\n                robotis_RCar_anim_screen: \"Set screen animation to %1 %2 %3\",\n                robotis_RCar_icon_screen_food_plant: \"Display %1 from [Food/Plants] at position (%2, %3) in size %4 %5\",\n                robotis_RCar_icon_screen_animal_human: \"Display %1 from [Animal/Human] at position (%2, %3) in size %4 %5\",\n                robotis_RCar_icon_screen_object_tool: \"Display %1 from [Object/Tool] at position (%2, %3) in size %4 %5\",\n                robotis_RCar_icon_screen_vehicle_number: \"Display %1 from [Vehicle/Number] at position (%2, %3) in size %4 %5\",\n                robotis_RCar_icon_screen_game_character: \"Display %1 from [Game/Character] at position (%2, %3) in size %4 %5\",\n                robotis_RCar_text_screen: \"Display %1 in %5 in %4 at (%2, %3) on the screen %6\",\n                robotis_RCar_text_screen_redraw: \"Newly display %1 in %4 at (%2, %3) %5\",\n                robotis_RCar_pixel: \"Display %3 colored dot at (%1, %2) %4\",\n                robotis_RCar_LCDBright: \"Set screen brightness as %1 %2\",\n                robotis_RCar_LCDColor: \"Set screen color as %1 %2\",\n                \n                \n                // LED 제어\n                robotis_RCar_cm_led: \"%2 the robot's %1 LED %3\",\n                robotis_RCar_cm_led_pattern: \"LED %1 blinks at a %2 speed %3\",\n                \n                // AI Camera 값 블록\n                robotis_RCar_ai_camera_connection_status: \"AI Camera: If %1\",\n                robotis_RCar_ai_camera_if_detected: \"AI Camera: If %1 is displayed\",\n        \n                robotis_RCar_ai_camera_block_value_closest_to_center: \"AI Camera: %1 of the rectangle closest to the center of the screen\",\n                robotis_RCar_ai_camera_arrow_value_closest_to_center: \"AI Camera: %1 of the arrow closest to the center of the screen\",\n                robotis_RCar_ai_camera_number_of_learned_id: \"AI Camera: the number of learned ID\",\n                robotis_RCar_ai_camera_block_value_of_id: \"AI Camera: %2 of rectangle with detected ID %1\",\n                robotis_RCar_ai_camera_arrow_value_of_id: \"AI Camera: %2 of arrow with detected ID %1\",\n        \n                robotis_RCar_ai_camera_if_learned_id: \"AI Camera: If learned data with ID %1\",\n                robotis_RCar_ai_camera_if_detected_id_type: \"AI Camera: If learned %2 data with ID %1\",\n        \n                // AI 카메라 제어\n                robotis_RCar_ai_camera_set_mode: \"AI Camera: Set mode to %1 %2\",\n                robotis_RCar_ai_camera_print_custom_text: \"AI Camera: Display %3 at screen position (%1, %2) %4\",\n                robotis_RCar_ai_camera_clear_custom_text: \"AI Camera: Clear screen text %1\",\n            },            \n            Helper: {\n                // Driving Control\n                robotis_RCar_drive_simple: \"Drive the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %\",\n                robotis_RCar_drive_advanced: \"Rotate the left and right wheels of the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %\",\n                robotis_RCar_drive_seperate: \"Rotate the specified wheel of the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %\",\n                robotis_RCar_drive_angle: \"Rotate the two wheels of the robot in the specified direction and by the specified angle\\nAngle range: -5760 ~ 5760\\nAngle unit: degrees\",\n                robotis_RCar_go_distance: \"Move forward or backward by the specified distance\\nDistance range: -1000 ~ 1000\\nDistance unit: mm\",\n                robotis_RCar_turn_angle: \"Rotate in place by the specified angle and direction\\nAngle range: -360 ~ 360\\nAngle unit: degrees\",\n                robotis_RCar_follow_line: \"Start following the line at the specified speed\",\n                robotis_RCar_stop_at_cross: \"Stop at the specified intersection\",\n                robotis_RCar_turn_at_line: \"Make the specified turn at the intersection and stop\",\n                robotis_RCar_drive_stop: \"Stop the robot\",\n\n                // Value Blocks\n                robotis_RCar_cm_ir_value: \"IR sensor value of the specified number (range: 0 ~ 200)\",\n                robotis_RCar_cm_ir_compare: \"If the IR sensor value of the specified number matches the specified value, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_detectFrontObj: \"If an object is detected in front of the specified sensor, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_cm_btn_value: \"If the specified button is clicked, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_cm_joystick_value: \"If the joystick position is in the specified state, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_mic: \"Displays the intensity of the sound detected by the microphone in decibels (dB).\",\n                robotis_RCar_detectSound_compare: \"If the direction of the sound matches the specified direction, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_imu: \"Value of the specified accelerometer/gyro sensor on the specified axis\\nRange: -100 ~ 100\",\n                robotis_RCar_roll_pitch: \"roll/pitch value\\nroll: -180° ~ 180°, pitch: -90° ~ 90°\",\n                robotis_RCar_distance_value: \"Value of the specified sensor\\nDistance range: 0 ~ 1000mm\\nIlluminance range: 0 ~ 100%\\nButton sensor: 0 (not pressed) / 1 (pressed)\",\n                robotis_RCar_distance_compare: \"If the specified equation of the specified sensor value is correct, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_line_cross_compare: \"If the specified intersection shape is correct, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_dxl_value: \"Position angle value of the specified motor\\nRange: -180° ~ 180°\",\n\n                // Sound\n                robotis_RCar_scale_simple: \"Play with the specified octave, scale, and note\",\n                robotis_RCar_scale_advanced: \"Play with the specified octave, scale, and beat\",\n                robotis_RCar_rest_simple: \"Rest for the specified rest note\",\n                robotis_RCar_rest_advanced: \"Rest for the specified beat\",\n                robotis_RCar_beat_per_minute: \"Set the playing speed (BPM)\\nRange: 10 ~ 600\",\n                robotis_RCar_Hello: \"Play the specified voice of the robot\",\n                robotis_RCar_effectSound: \"Play the specified sound effect of the robot\",\n                robotis_RCar_record: \"Record and save to the specified number storage\",\n                robotis_RCar_playRecord: \"Play the recorded voice in the specified number storage\",\n\n                // LCD Control\n                robotis_RCar_screen: \"Set the character and expression of the controller screen background\",\n                robotis_RCar_anim_screen: \"Set the character and expression of the controller screen animation\",\n                robotis_RCar_icon_screen_food_plant: \"Set the position and size of a specific icon in [food/plant] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\",\n                robotis_RCar_icon_screen_animal_human: \"Set the position and size of a specific icon in [animal/human] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\",\n                robotis_RCar_icon_screen_object_tool: \"Set the position and size of a specific icon in [object/tool] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\",\n                robotis_RCar_icon_screen_vehicle_number: \"Set the position and size of a specific icon in [vehicle/number] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\",\n                robotis_RCar_icon_screen_game_character: \"Set the position and size of a specific icon in [game/character] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\",\n                robotis_RCar_text_screen: \"Set the position, font size, and color of the specified text on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\",\n                robotis_RCar_text_screen_redraw: \"Set the position and color of the specified text to be newly displayed (clearing the background of the text) on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\",\n                robotis_RCar_pixel: \"Set the position and color of the dot to be displayed on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\",\n                robotis_RCar_LCDBright: \"Set the screen brightness\\nBrightness range: 0% ~ 100%\",\n                robotis_RCar_LCDColor: \"Set the screen color\",\n\n                // LED Control\n                robotis_RCar_cm_led: \"Turn the specified LED of the controller on or off\",\n                robotis_RCar_cm_led_pattern: \"Set the blinking pattern of LEDs of the controller\",\n                \n                // AI Camera Value Blocks\n                robotis_RCar_ai_camera_connection_status: \"If the AI camera is connected, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_ai_camera_if_detected: \"If the selected symbol (rectangle/arrow) is displayed on the LCD screen of the AI camera, it is determined as 'true'; otherwise, 'false'.\",\n\n                robotis_RCar_ai_camera_block_value_closest_to_center: \"X coordinate/Y coordinate/width/height/learning ID of the rectangle closest to the center of the AI camera screen\",\n                robotis_RCar_ai_camera_arrow_value_closest_to_center: \"Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate/learning ID of the arrow closest to the center of the AI camera screen\",\n                robotis_RCar_ai_camera_number_of_learned_id: \"Number of IDs learned by the AI camera\",\n                robotis_RCar_ai_camera_block_value_of_id: \"X coordinate/Y coordinate/width/height of the rectangle with the specified ID detected by the AI camera\",\n                robotis_RCar_ai_camera_arrow_value_of_id: \"Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate of the arrow with the specified ID detected by the AI camera\",\n\n                robotis_RCar_ai_camera_if_learned_id: \"If the AI camera has learned data with the specified ID, it is determined as 'true'; otherwise, 'false'.\",\n                robotis_RCar_ai_camera_if_detected_id_type: \"If the AI camera has learned the specified data (rectangle/arrow) with the specified ID, it is determined as 'true'; otherwise, 'false'.\",\n\n                // AI Camera Control\n                robotis_RCar_ai_camera_set_mode: \"Set the mode of the AI camera\",\n                robotis_RCar_ai_camera_print_custom_text: \"Print the specified text at the specified position on the AI camera screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\",\n                robotis_RCar_ai_camera_clear_custom_text: \"Clear all texts displayed on the AI camera screen\",\n            },\n            Blocks: {\n                robotis_red: \"Red\",\n                robotis_orange: \"Orange\",\n                robotis_yellow: \"Yellow\",\n                robotis_green: \"Green\",\n                robotis_blue: \"Blue\",\n                robotis_brown: \"Brown\",\n                robotis_black: \"Black\",\n                robotis_white: \"White\",\n                robotis_left: \"Left\",\n                robotis_center: \"Center\",\n                robotis_right: \"Right\",\n                robotis_both: \"Both\",\n                robotis_rgee: \"R-GEE\",\n                robotis_rla: \"KODALA\",\n                robotis_kkokdu: \"TIG\",\n                robotis_korean1: \"Hello!\",\n                robotis_korean2: \"Great to see you.\",\n                robotis_korean3: \"Okay ~\",\n                robotis_korean4: \"No!\",\n                robotis_korean5: \"I don't know.\",\n                robotis_korean6: \"I like it.\",\n                robotis_korean7: \"I don't like it.\",\n                robotis_korean8: \"What is your name? \",\n                robotis_korean9: \"How can I help you? \",\n                robotis_korean10: \"Great job! \",\n                robotis_korean11: \"It's alright.\",\n                robotis_korean12: \"Let's do it again! \",\n                robotis_korean13: \"Thank you! \",\n                robotis_korean14: \"Can you say that one more time?\",\n                robotis_korean15: \"Awesome!\",\n                robotis_korean16: \"I'm excited! \",\n                robotis_korean17: \"I'm having a great time! \",\n                robotis_korean18: \"I'm sorry.\",\n                robotis_korean19: \"I'm angry! \",\n                robotis_korean20: \"I'm embarassed.\",\n                robotis_korean21: \"I'm scared.\",\n                robotis_korean22: \"I'm upset.\",\n                robotis_korean23: \"I love you.\",\n                robotis_korean24: \"Very pretty! \",\n                robotis_korean25: \"Interesting.\",\n                robotis_korean26: \"I'm nervous.\",\n                robotis_korean27: \"Let's move forward! \",\n                robotis_korean28: \"Let's move backward! \",\n                robotis_korean29: \"Let's stand up! \",\n                robotis_korean30: \"Did you fall down? \",\n                robotis_korean31: \"Oh Yeah~\",\n                robotis_korean32: \"Sweet! \",\n                robotis_korean33: \"Oh no\",\n                robotis_korean34: \"My My \",\n                robotis_korean35: \"Whoo hoo! \",\n                robotis_korean36: \"Ha Ha Ha\",\n                robotis_korean37: \"Ho Ho Ho \",\n                robotis_korean38: \"I'm sleepy.\",\n                robotis_korean39: \"Sing me a bedtime song! \",\n                robotis_korean40: \"Hello!\",\n                robotis_korean41: \"I'm hungry.\",\n                robotis_korean42: \"I'm craving an acorn! \",\n                robotis_korean43: \"I want to take a bath! \",\n                robotis_korean44: \"Time for a bath! \",\n                robotis_korean45: \"I'm bored. \",\n                robotis_korean46: \"Do you want a snack? \",\n                robotis_korean47: \"I'm sick.\",\n                robotis_korean48: \"Do you have any medicine? \",\n                robotis_korean49: \"Where do we have to go? \",\n                robotis_korean50: \"We're here! \",\n                robotis_korean51: \"Let's go to the left side! \",\n                robotis_korean52: \"Let's go to the right side! \",\n                robotis_korean53: \"Oh my, you scared me! \",\n                robotis_korean54: \"Found you! \",\n                robotis_korean55: \"There's nothing here. \",\n                robotis_korean56: \"Did you call me?\",\n                robotis_korean57: \"Please let me down. \",\n                robotis_korean58: \"Oops! \",\n                robotis_korean59: \"Hmmph! \",\n                robotis_korean60: \"Eek! \",\n                robotis_dog: \"Dog\",\n                robotis_frog: \"Frog\",\n                robotis_cat: \"Cat\",\n                robotis_chicken: \"Rooster\",\n                robotis_tiger: \"Tiger\",\n                robotis_mouse: \"Mouse\",\n                robotis_whistle: \"Whistle\",\n                robotis_ambul: \"Ambulance\",\n                robotis_Horn: \"CarHorn\",\n                robotis_siren: \"Siren\",\n                robotis_gun: \"Gunshot\",\n                robotis_clap: \"Clap\",\n                robotis_melody1: \"Melody1\",\n                robotis_melody2: \"Melody2\",\n                robotis_melody3: \"Melody3\",\n                robotis_melody4: \"Melody4\",\n                robotis_forward: \"Forward\",\n                robotis_backward: \"Backward\",\n                robotis_acceleration: \"acceleration\",\n                robotis_gyro: \"gyro\",\n                robotis_run: \"Run\",\n                robotis_cancel: \"Cancel\",\n                robotis_push: \"Pressed\",\n                robotis_notPush: \"Unpressed\",\n                robotis_play: \"Play\",\n                robotis_rest: \"Rest\",\n                robotis_face01: \"Haha\",\n                robotis_face02: \"Smile\",\n                robotis_face03: \"Laugh\",\n                robotis_face04: \"Yum Yum\",\n                robotis_face05: \"Scared\",\n                robotis_face06: \"Uncomfortable\",\n                robotis_face07: \"Confused\",\n                robotis_face08: \"Dazed\",\n                robotis_face09: \"Yell\",\n                robotis_face10: \"Angry\",\n                robotis_face11: \"Sniff (Left)\",\n                robotis_face12: \"Sniff (Right)\",\n                robotis_face13: \"Sniff (Down)\",\n                robotis_face14: \"Whew\",\n                robotis_face15: \"Faint\",\n                robotis_face16: \"Dizzy\",\n                robotis_face17: \"Yawn\",\n                robotis_face18: \"Sleepy\",\n                robotis_face19: \"Sleep\",\n                robotis_face20: \"Sad\",\n                robotis_face21: \"Cry\",\n                robotis_face22: \"Bath\",\n                robotis_face23: \"Heart-Eyes\",     \n\n                robotis_pattern1: \"Pattern1\",\n                robotis_pattern2: \"Pattern2\",\n                robotis_pattern3: \"Pattern3\",  \n                robotis_moveF: \"Forward\",\n                robotis_moveB: \"Backward\",\n                robotis_moveL: \"LeftTurn\",\n                robotis_moveR: \"RightTurn\",\n                robotis_moveU: \"U-turn\",\n                robotis_moveL_in_place: \"Turn left in place\",\n                robotis_moveR_in_place: \"Trun right in place\",\n                robotis_moveU_in_place: \"U-turn in place\",\n                robotis_moveRG1: \"Stand\",\n                robotis_moveRG2: \"Sit\",\n                robotis_moveRG3: \"Struggle\",\n                robotis_moveRG4: \"RaiseFeet\",\n                robotis_fast: 'Fast',\n                robotis_normal: 'Normal',\n                robotis_slow: 'Slow',\n                robotis_stop: \"Stop\",\n                robotis_roll: \"Left-right rotate angle (roll)\",\n                robotis_pitch: \"Forward-backward rotate angle (pitch)\",\n                robotis_direction_forward: \"Forward\",\n                robotis_direction_backward: \"Backward\",\n                robotis_stMotion1: \"Standard\",\n                robotis_stMotion2: \"Forward\",\n                robotis_stMotion3: \"TurnRight\",\n                robotis_stMotion4: \"TurnLeft\",\n                robotis_stMotion5: \"Backward\",\n                robotis_stMotion6: \"ToRight\",\n                robotis_stMotion7: \"ToLeft\",\n                robotis_stMotion8: \"TurnAroundRight\",\n                robotis_stMotion9: \"TurnAroundLeft\",\n                robotis_spMotion1: \"RightHandUp\",\n                robotis_spMotion2: \"RightHandDown\",\n                robotis_spMotion3: \"LeftHandUp\",\n                robotis_spMotion4: \"LeftHandDown\",\n                robotis_spMotion5: \"BothHandsUp\",\n                robotis_spMotion6: \"BothHandsDown\",\n                robotis_spMotion7: \"FallBackward\",\n                robotis_spMotion8: \"FallForward\",\n                robotis_spMotion9: \"StandForward\",\n                robotis_spMotion10: \"StandBackward\",\n                robotis_spMotion11: \"Defence\",\n                robotis_spMotion12: \"Offense1\",\n                robotis_spMotion13: \"Offense2\",\n                robotis_spMotion14: \"Offense3\",\n                robotis_spMotion15: \"Offense4\",\n                robotis_screen1: \"Sissor\",\n                robotis_screen2: \"Rock\",\n                robotis_screen3: \"Paper\",\n                robotis_icon_food_plant_1: \"Milk\",\n                robotis_icon_food_plant_2: \"Tree\",\n                robotis_icon_food_plant_3: \"Soup\",\n                robotis_icon_food_plant_4: \"Cake\",\n                robotis_icon_food_plant_5: \"Water\",\n                robotis_icon_food_plant_6: \"Juice\",\n                robotis_icon_food_plant_7: \"Carrot\",\n                robotis_icon_food_plant_8: \"Apple\",\n                robotis_icon_food_plant_9: \"Orange\",\n                robotis_icon_food_plant_10: \"Meat\",\n                robotis_icon_food_plant_11: \"Flowerpot\",\n                robotis_icon_food_plant_12: \"Rose\",\n                robotis_icon_food_plant_13: \"Grape\",\n                robotis_icon_food_plant_14: \"Potato\",\n                robotis_icon_food_plant_15: \"Candy\",\n                robotis_icon_food_plant_16: \"Cheese\",\n                robotis_icon_food_plant_17: \"Bread\",\n                robotis_icon_food_plant_18: \"Flowers\",\n                robotis_icon_food_plant_19: \"Coffee\",\n                robotis_icon_food_plant_20: \"Tulip\",\n                robotis_icon_food_plant_21: \"Banana\",\n                robotis_icon_food_plant_22: \"Fruits\",\n                robotis_icon_food_plant_23: \"Hamburger\",\n                robotis_icon_food_plant_24: \"Pizza\",\n                robotis_icon_animal_human_1: \"Shiba Dog\",\n                robotis_icon_animal_human_2: \"Puppy\",\n                robotis_icon_animal_human_3: \"Bear\",\n                robotis_icon_animal_human_4: \"Bird\",\n                robotis_icon_animal_human_5: \"Duck\",\n                robotis_icon_animal_human_6: \"Lion\",\n                robotis_icon_animal_human_7: \"Tiger\",\n                robotis_icon_animal_human_8: \"Horse\",\n                robotis_icon_animal_human_9: \"Sheep\",\n                robotis_icon_animal_human_10: \"Shark 1 (Left)\",\n                robotis_icon_animal_human_11: \"Shark 1 (Right)\",\n                robotis_icon_animal_human_12: \"Shark 2 (Left)\",\n                robotis_icon_animal_human_13: \"Shark 2 (Right)\",\n                robotis_icon_animal_human_14: \"Fish 1\",\n                robotis_icon_animal_human_15: \"Fish 2\",\n                robotis_icon_animal_human_16: \"Fish 3\",\n                robotis_icon_animal_human_17: \"Octopus\",\n                robotis_icon_animal_human_18: \"Monkey\",\n                robotis_icon_animal_human_19: \"Chicken\",\n                robotis_icon_animal_human_20: \"Pig\",\n                robotis_icon_animal_human_21: \"Person (Chubby)\",\n                robotis_icon_animal_human_22: \"Person (Swimsuit)\",\n                robotis_icon_animal_human_23: \"Baby\",\n                robotis_icon_animal_human_24: \"Person (Running)\",\n                robotis_icon_animal_human_25: \"Person (Singing)\",\n                robotis_icon_animal_human_26: \"Person (Sitting)\",\n                robotis_icon_animal_human_27: \"Person (Angry)\",\n                robotis_icon_animal_human_28: \"Person (Cheering)\",\n                robotis_icon_animal_human_29: \"King\",\n                robotis_icon_animal_human_30: \"Prince\",\n                robotis_icon_animal_human_31: \"Princess\",\n                robotis_icon_animal_human_32: \"Chef\",\n                robotis_icon_animal_human_33: \"Doctor\",\n                robotis_icon_animal_human_34: \"Nurse\",\n                robotis_icon_object_tool_1: \"Bag\",\n                robotis_icon_object_tool_2: \"Box\",\n                robotis_icon_object_tool_3: \"Mug\",\n                robotis_icon_object_tool_4: \"Hat (Fedora)\",\n                robotis_icon_object_tool_5: \"Hat (Cap)\",\n                robotis_icon_object_tool_6: \"Key\",\n                robotis_icon_object_tool_7: \"Toy\",\n                robotis_icon_object_tool_8: \"Book\",\n                robotis_icon_object_tool_9: \"Teddy Bear\",\n                robotis_icon_object_tool_10: \"Drum\",\n                robotis_icon_object_tool_11: \"Notebook\",\n                robotis_icon_object_tool_12: \"Pen\",\n                robotis_icon_object_tool_13: \"Desk\",\n                robotis_icon_object_tool_14: \"Table\",\n                robotis_icon_object_tool_15: \"Chair\",\n                robotis_icon_object_tool_16: \"Bed\",\n                robotis_icon_object_tool_17: \"Tent\",\n                robotis_icon_object_tool_18: \"Plate\",\n                robotis_icon_object_tool_19: \"Soccer Ball\",\n                robotis_icon_object_tool_20: \"Bell\",\n                robotis_icon_object_tool_21: \"Watch\",\n                robotis_icon_object_tool_22: \"Shoes\",\n                robotis_icon_object_tool_23: \"Lamp\",\n                robotis_icon_object_tool_24: \"Radio\",\n                robotis_icon_object_tool_25: \"Banknote\",\n                robotis_icon_object_tool_26: \"Ruler\",\n                robotis_icon_object_tool_27: \"Camera\",\n                robotis_icon_object_tool_28: \"Spoon\",\n                robotis_icon_object_tool_29: \"Keyboard\",\n                robotis_icon_object_tool_30: \"Calendar\",\n                robotis_icon_object_tool_31: \"Knife\",\n                robotis_icon_object_tool_32: \"Balloon\",\n                robotis_icon_object_tool_33: \"Water Bottle\",\n                robotis_icon_object_tool_34: \"Wooden Stick (Horizontal)\",\n                robotis_icon_object_tool_35: \"Wooden Stick (Vertical)\",\n                robotis_icon_object_tool_36: \"Fishing Hook\",\n                robotis_icon_vehicle_number_1: \"Car\",\n                robotis_icon_vehicle_number_2: \"Bus\",\n                robotis_icon_vehicle_number_3: \"Truck\",\n                robotis_icon_vehicle_number_4: \"Jeep\",\n                robotis_icon_vehicle_number_5: \"Bicycle\",\n                robotis_icon_vehicle_number_6: \"Subway\",\n                robotis_icon_vehicle_number_7: \"Train\",\n                robotis_icon_vehicle_number_8: \"Airplane\",\n                robotis_icon_vehicle_number_9: \"Fighter Jet (Vertical)\",\n                robotis_icon_vehicle_number_10: \"Fighter Jet (Horizontal)\",\n                robotis_icon_vehicle_number_11: \"Rocket\",\n                robotis_icon_vehicle_number_12: \"Fishing Boat\",\n                robotis_icon_vehicle_number_13: \"Passenger Ship\",\n                robotis_icon_vehicle_number_14: \"Submarine (Left)\",\n                robotis_icon_vehicle_number_15: \"Submarine (Right)\",\n                robotis_icon_vehicle_number_16: \"Airplane (Left)\",\n                robotis_icon_vehicle_number_17: \"Airplane (Right)\",\n                robotis_icon_vehicle_number_18: \"Airplane (Top)\",\n                robotis_icon_vehicle_number_19: \"Spaceship (Left)\",\n                robotis_icon_vehicle_number_20: \"Spaceship (Right)\",\n                robotis_icon_vehicle_number_21: \"Spaceship (Top)\",\n                robotis_icon_vehicle_number_22: \"Dice (1)\",\n                robotis_icon_vehicle_number_23: \"Dice (2)\",\n                robotis_icon_vehicle_number_24: \"Dice (3)\",\n                robotis_icon_vehicle_number_25: \"Dice (4)\",\n                robotis_icon_vehicle_number_26: \"Dice (5)\",\n                robotis_icon_vehicle_number_27: \"Dice (6)\",\n                robotis_icon_vehicle_number_28: \"0\",\n                robotis_icon_vehicle_number_29: \"1\",\n                robotis_icon_vehicle_number_30: \"2\",\n                robotis_icon_vehicle_number_31: \"3\",\n                robotis_icon_vehicle_number_32: \"4\",\n                robotis_icon_vehicle_number_33: \"5\",\n                robotis_icon_vehicle_number_34: \"6\",\n                robotis_icon_vehicle_number_35: \"7\",\n                robotis_icon_vehicle_number_36: \"8\",\n                robotis_icon_vehicle_number_37: \"9\",\n                robotis_icon_vehicle_number_38: \"10\",\n                robotis_icon_game_character_1: 'R-GEE(F)',\n                robotis_icon_game_character_2: 'R-GEE(L)',\n                robotis_icon_game_character_3: 'R-GEE(R)',\n                robotis_icon_game_character_4: 'KODALA(F)',\n                robotis_icon_game_character_5: 'KODALA(L))',\n                robotis_icon_game_character_6: 'KODALA(R)',\n                robotis_icon_game_character_7: 'Ghost',\n                robotis_icon_game_character_8: 'Monster',\n                robotis_icon_game_character_9: 'Virus',\n                robotis_icon_game_character_10: 'Bacteria',\n                robotis_icon_game_character_11: 'Flying R-GEE (L)',\n                robotis_icon_game_character_12: 'Flying R-GEE (R)',\n                robotis_icon_game_character_13: 'Flying R-GEE (F)',\n                robotis_icon_game_character_14: 'Medal',\n                robotis_icon_game_character_15: 'Money (G)',\n                robotis_icon_game_character_16: 'Money ($)',\n                robotis_icon_game_character_17: 'Heart',\n                robotis_icon_game_character_18: 'Bomb',\n                robotis_icon_game_character_19: 'Fire',\n                robotis_icon_game_character_20: 'Cloud 1',\n                robotis_icon_game_character_21: 'Cloud 2',\n                robotis_icon_game_character_22: 'Shell 1',\n                robotis_icon_game_character_23: 'Shell 2',\n                robotis_icon_game_character_24: 'Cannon (Horizontal)',\n                robotis_icon_game_character_25: 'Cannon (Vertical)',\n                robotis_icon_game_character_26: 'Laser (Vertical)',\n                robotis_icon_game_character_27: 'Laser (Horizontal)',\n                robotis_icon_game_character_28: 'Arrow (Horizontal)',\n                robotis_icon_game_character_29: 'Arrow (Vertical)',\n                robotis_icon_game_character_30: 'Missile (Up)',\n                robotis_icon_game_character_31: 'Missile (Down)',\n                robotis_icon_game_character_32: 'Missile (Left)',\n                robotis_icon_game_character_33: 'Missile (Right)',\n                robotis_icon_game_character_34: 'Parachute',\n                robotis_icon_game_character_35: 'Explosion 1',\n                robotis_icon_game_character_36: 'Explosion 2',\n                robotis_icon_game_character_37: 'Scope',\n                robotis_icon_game_character_38: 'Scissors',\n                robotis_icon_game_character_39: 'Rock',\n                robotis_icon_game_character_40: 'Paper',\n                robotis_icon_game_character_41: 'Walking Person 1',\n                robotis_icon_game_character_42: 'Walking Person 2',\n                robotis_icon_game_character_43: 'Running Person 1',\n                robotis_icon_game_character_44: 'Running Person 2',  \n                robotis_speed_fast: \"Fast Speed\",\n                robotis_speed_midium: \"Medium Speed\",\n                robotis_speed_slow: \"Slow Speed\",\n                robotis_clockwise: \"Clockwise\",\n                robotis_counterclockwise: \"Counterclockwise\",\n                robotis_up: \"Lift\",\n                robotis_down: \"Lower\",\n                robotis_if_greater: \"If Greater\",\n                robotis_if_smaller: \"If Smaller\",\n                robotis_if_equal: \"If Equal\",\n                robotis_front_right: \"Front Right\",\n                robotis_front_left: \"Front Left\",\n                robotis_bottom_right: \"Bottom Right\",\n                robotis_bottom_left: \"Bottom Left\",\n                robotis_side_right: \"Right Edge\",\n                robotis_side_left: \"Left Edge\",\n                robotis_front_ir_sensor: \"Infrared Sensor\",\n                robotis_distance_sensor: \"Distance Sensor\",\n                robotis_front: \"Front\",\n                robotis_right: \"Right\",\n                robotis_left_wheel: \"Left Wheel\",\n                robotis_right_wheel: \"Right Wheel\",\n                robotis_beat_sound_8th_note: \"Eighth Note (♪)\",\n                robotis_beat_sound_dotted_8th_note: \"Dotted Eighth Note (♪.)\",\n                robotis_beat_sound_quarter_note: \"Quarter Note (♩)\",\n                robotis_beat_sound_dotted_quarter_note: \"Dotted Quarter Note (♩.)\",\n                robotis_beat_sound_half_note: \"Half Note (𝅗𝅥)\",\n                robotis_beat_sound_dotted_half_note: \"Dotted Half Note (𝅗𝅥.)\",\n                robotis_beat_sound_whole_note: \"Whole Note (𝅝)\",\n                robotis_beat_sound_dotted_note: \"Dotted Whole Note (𝅝.)\",\n                robotis_beat_rest_8th_note: \"Eighth Rest (𝄾)\",\n                robotis_beat_rest_dotted_8th_note: \"Dotted Eighth Rest (𝄾.)\",\n                robotis_beat_rest_quarter_note: \"Quarter Rest (𝄽)\",\n                robotis_beat_rest_dotted_quarter_note: \"Dotted Quarter Rest (𝄽.)\",\n                robotis_beat_rest_half_note: \"Half Rest (𝄼)\",\n                robotis_beat_rest_dotted_half_note: \"Dotted Half Rest (𝄼˙)\",\n                robotis_beat_rest_whole_note: \"Whole Rest (𝄻)\",\n                robotis_beat_rest_dotted_note: \"Dotted Whole Rest (𝄻˙)\",\n                robotis_line_cross_type_0: \"|\",\n                robotis_line_cross_type_1: \" (Blank)\",\n                robotis_line_cross_type_5: \"🞣\",\n                robotis_line_cross_type_6: \"⏉\",\n                robotis_line_cross_type_7: \"⊣\",\n                robotis_line_cross_type_8: \"⊢\",\n                robotis_line_cross_type_9: \"⏋\",\n                robotis_line_cross_type_10: \"⎾\",\n                robotis_line_cross_type_11: \"¦\",\n                robotis_line_cross_type_12: \"︙\",\n                robotis_connected: \"Connected\",\n                robotis_disconnected: \"Not connected\",\n                robotis_ai_camera_mode_face_recognition: \"Face Recognition\",\n                robotis_ai_camera_mode_object_tracking: \"Object Tracking\",\n                robotis_ai_camera_mode_object_recognition: \"Object Recognition\",\n                robotis_ai_camera_mode_line_tracking: \"Line Tracking\",\n                robotis_ai_camera_mode_color_recognition: \"Color Recognition\",\n                robotis_ai_camera_mode_tag_recognition: \"Tag Recognition\",\n                robotis_ai_camera_mode_object_classification: \"Object Classification\",\n                robotis_ai_camera_block: \"Block\",\n                robotis_ai_camera_arrow: \"Arrow\",\n                robotis_ai_camera_center_block_center_x: \"Center X Coordinate\",\n                robotis_ai_camera_center_block_center_y: \"Center Y Coordinate\",\n                robotis_ai_camera_center_block_width: \"Width\",\n                robotis_ai_camera_center_block_height: \"Height\",\n                robotis_ai_camera_center_leared_id: \"Learned ID\",\n                robotis_ai_camera_center_arrow_origin_x: \"Start X Coordinate\",\n                robotis_ai_camera_center_arrow_origin_y: \"Start Y Coordinate\",\n                robotis_ai_camera_center_arrow_target_x: \"End X Coordinate\",\n                robotis_ai_camera_center_arrow_target_y: \"End Y Coordinate\",\n            },\n        }\n    }\n};\n\nlet rb100_last_valid_value = [];\nlet bg_color = 0;\nlet beat_per_minute = 75;\n\nEntry.Robotis_rb_koala.getBlocks = function() {\n    return {\n        robotis_RCar_drive_simple: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '2'],\n                        [Lang.Blocks.robotis_moveL_in_place, '3'],\n                        [Lang.Blocks.robotis_moveR_in_place, '4'],\n\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    5,\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_drive_simple',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var speed = script.getNumberValue('SPEED', script);\n                var direction = script.getField('DIRECTION', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n                \n                switch(direction) {\n                    case '1':\n                        data_value = speed * 256 + speed;\n                        break;\n                    case '2':\n                        data_value = (256 - speed) * 256 + (256 - speed);\n                        break;\n                    case '3':\n                        data_value = speed * 256 + (256 - speed);\n                        break;\n                    case '4':\n                        data_value = (256 - speed) * 256 + speed;\n                        break;\n                    default:\n                        data_value = 0;\n                        break;\n                }\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RCar_go_simple(%1, %2)'],\n            },\n        },\n        robotis_RCar_drive_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_drive_stop',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        5200,\n                        1,\n                        0,\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RCar_stop(%1, %2)'],\n            },\n        },\n        robotis_RCar_drive_advanced: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RCar_drive_advanced',\n            },\n            paramsKeyMap: {\n                LEFT_SPEED: 0,\n                LEFT_DIRECTION: 1,\n                RIGHT_SPEED: 2,\n                RIGHT_DIRECTION: 3,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                let leftSpeed = script.getNumberValue('LEFT_SPEED', script);\n                let leftDirection = script.getNumberValue('LEFT_DIRECTION', script);\n                let rightSpeed = script.getNumberValue('RIGHT_SPEED', script);\n                let rightDirection = script.getNumberValue('RIGHT_DIRECTION', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n\n                if (leftSpeed < -100) leftSpeed = -100;\n                else if (leftSpeed > 100) leftSpeed = 100;\n\n                if (rightSpeed < -100) rightSpeed = -100;\n                else if (rightSpeed > 100) rightSpeed = 100;\n\n                if (leftDirection == '2') {\n                    leftSpeed = -leftSpeed;\n                }\n                if (rightDirection == '2') {\n                    rightSpeed = -rightSpeed;\n                }\n                \n                if (leftSpeed < 0) leftSpeed = 256 + leftSpeed;\n                if (rightSpeed < 0) rightSpeed = 256 + rightSpeed;\n                \n                data_value = leftSpeed + rightSpeed * 256;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RCar_go_advanced(%1, %2)'],\n            },\n        },\n        robotis_RCar_drive_seperate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '1'],\n                        [Lang.Blocks.robotis_right, '0'],\n                        [Lang.Blocks.robotis_both, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_direction_forward, '1'],\n                        [Lang.Blocks.robotis_direction_backward, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RCar_drive_seperate',\n            },\n            paramsKeyMap: {\n                WHEEL_SIDE: 0,\n                WHEEL_SPEED: 1,\n                WHEEL_DIRECTION: 2,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                let wheelSide = script.getNumberValue('WHEEL_SIDE', script);\n                let wheelSpeed = script.getNumberValue('WHEEL_SPEED', script);\n                let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n\n                let leftSpeed = 0;\n                let rightSpeed = 0;\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n                \n\n                if (wheelSpeed < -100) wheelSpeed = -100;\n                else if (wheelSpeed > 100) wheelSpeed = 100;\n\n                wheelSpeed = (wheelSpeed + 256) % 256;\n                if (wheelDirection == '2') {\n                    wheelSpeed = (256 - wheelSpeed) % 256;\n                }\n\n                if (wheelSide == 1) {\n                    leftSpeed = wheelSpeed;\n                    rightSpeed = 127; // 속도제어 안함\n                } else if (wheelSide == 0) {\n                    leftSpeed = 127; // 속도제어 안함\n                    rightSpeed = wheelSpeed;\n                } else {\n                    leftSpeed = wheelSpeed;\n                    rightSpeed = wheelSpeed;\n                }\n\n                data_value = leftSpeed + rightSpeed * 256;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RCar_go_seperate(%1, %2)'],\n            },\n        },\n        robotis_RCar_drive_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_direction_forward, '1'],\n                        [Lang.Blocks.robotis_direction_backward, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['180'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RCar_drive_angle',\n            },\n            paramsKeyMap: {\n                WHEEL_ANGLE: 0,\n                WHEEL_DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                let wheelAngle = script.getNumberValue('WHEEL_ANGLE', script);\n                let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n                \n                const data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                let data_address = 580;\n                let data_length = 8;\n                let angleValue = 0;\n                let data_buf_left = [];\n                let data_buf_right = [];\n                let i = 0;\n                let speed = 50;\n\n                if (wheelDirection == '2') {\n                    wheelAngle = -wheelAngle;\n                }\n\n                wheelAngle = Math.round(wheelAngle * 4096 / 360);\n\n                if (wheelAngle > 65535) wheelAngle = 65535;\n                else if (wheelAngle < -65535) wheelAngle = -65535;\n\n                angleValue = wheelAngle;\n                if (wheelAngle < 0) angleValue = 65536 + angleValue;\n\n                data_buf_left.push(35);\n                data_buf_left.push(0);\n                data_buf_left.push(speed % 256);\n                data_buf_left.push(Math.floor(speed/256));\n                data_buf_left.push(angleValue % 256);\n                data_buf_left.push(Math.floor(angleValue/256) % 256);\n                if (wheelAngle >= 0) {\n                    data_buf_left.push(0);\n                    data_buf_left.push(0);\n                } else {\n                    data_buf_left.push(0xFF);\n                    data_buf_left.push(0xFF);\n                }\n                data_buf_right.push(36);\n                data_buf_right.push(0);\n                data_buf_right.push(speed % 256);\n                data_buf_right.push(Math.floor(speed/256));\n                data_buf_right.push(angleValue % 256);\n                data_buf_right.push(Math.floor(angleValue/256) % 256);\n                if (wheelAngle >= 0) {\n                    data_buf_right.push(0);\n                    data_buf_right.push(0);\n                } else {\n                    data_buf_right.push(0xFF);\n                    data_buf_right.push(0xFF);\n                }\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf_left,\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf_right,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RCar_go_angle(%1, %2)'],\n            },\n        },\n        robotis_RCar_go_distance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '-1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RCar_go_distance',\n            },\n            \n            paramsKeyMap: {\n                DISTANCE: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func(entity, script) {\n                var distance = script.getNumberValue('DISTANCE', script);\n                var direction = script.getNumberValue('DIRECTION', script);\n\n                if(distance > 1000) {\n                    distance = 1000;\n                } else if(distance < -1000) {\n                    distance = -1000;\n                }\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 270;\n                var data_length = 4;\n                var data_value = Math.floor(10 * distance * direction);\n        \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                data_sendqueue.push([data_instruction, 66, 2, 50491]);\n        \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 150 * Math.abs(distance) + 1200\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.RCar_go_distance(%1, %2)'] },\n        },\n\n        robotis_RCar_turn_angle:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveL_in_place, '1'],\n                        [Lang.Blocks.robotis_moveR_in_place, '-1'],\n\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RCar_turn_angle',\n            },\n            \n            paramsKeyMap: {\n                ANGLE: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func(entity, script) {\n                var angle = script.getNumberValue('ANGLE', script);\n                var direction = script.getNumberValue('DIRECTION', script);\n\n                angle *= direction;\n\n                if(angle > 360) {\n                    angle = 360;\n                } else if(angle < -360) {\n                    angle = -360;\n                }\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 270;\n                var data_length = 4;\n                var data_value = Math.floor(angle);\n        \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n            \n                data_sendqueue.push([data_instruction, 66, 2, 50492]);\n        \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + Math.abs(angle) * 16 + 1500\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.RCar_turn_angle(%1)'] },\n        },\n        robotis_RCar_follow_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_slow, '1'],\n                        [Lang.Blocks.robotis_normal, '2'],\n                        [Lang.Blocks.robotis_fast, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_follow_line',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var speed_level = script.getNumberValue('SPEED', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 5200;\n                var data_length = 1;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        speed_level,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_follow_line(%1)'],\n            },\n        },\n        robotis_RCar_stop_at_cross: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_line_cross_type_5, '5'],\n                        [Lang.Blocks.robotis_line_cross_type_6, '6'],\n                        [Lang.Blocks.robotis_line_cross_type_7, '7'],\n                        [Lang.Blocks.robotis_line_cross_type_8, '8'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_stop_at_cross',\n            },\n            paramsKeyMap: {\n                CROSS: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: async function (sprite, script) {\n                // instruction / address / length / value / default length\n                var corss_type = script.getNumberValue('CROSS', script);\n                var data_address = 5201;\n\n                // max 10 seconds\n                for (let i = 0; i < 100; i++) {\n                    await Entry.Utils.sleep(100);\n                    console.log(Entry.hw.portData[data_address]);\n                    if (Entry.hw.portData[data_address] == corss_type) {\n                        break;\n                    }\n                    if (Entry.engine.isState('stop') == true) {\n                        break;\n                    }\n                }\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE,\n                        5200,\n                        1,\n                        0,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_follow_line(%1)'],\n            },\n        },\n        robotis_RCar_turn_at_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveL_in_place, '0'],\n                        [Lang.Blocks.robotis_moveR_in_place, '1'],\n                        [Lang.Blocks.robotis_moveU_in_place, '2'],\n\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_turn_at_line',\n            },\n            paramsKeyMap: {\n                TURN_TYPE: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var turn_type = script.getNumberValue('TURN_TYPE', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 66;\n                var data_length = 2;\n                let extra_delay = 0;\n\n                switch (turn_type) {\n                    case 0:\n                    case 1:\n                        extra_delay = 2000;\n                        break;\n                        \n                    case 2:\n                        extra_delay = 3500;\n                        break;\n                }\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        50045 + turn_type,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + extra_delay,\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RCar_turn_at_line(%1)'],\n            },\n        },\n        robotis_RCar_follow_line_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                   null\n                ],\n                type: 'robotis_RCar_follow_line_stop',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 5200;\n                var data_length = 1;\n                var data_value = 0;\n            \n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_follow_line_stop()'],\n            },\n        },\n\n        \n\n\n        robotis_RCar_cm_ir_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_front_right, '360'],\n                        [Lang.Blocks.robotis_front_left, '362'],\n                        [Lang.Blocks.robotis_bottom_right, '364'],\n                        [Lang.Blocks.robotis_bottom_left, '366'],\n                        [Lang.Blocks.robotis_side_right, '368'],\n                        [Lang.Blocks.robotis_side_left, '370'],\n                    ],\n                    value: '360',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_RCar_cm_ir_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                var data_default_address = script.getNumberValue('VALUE');\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return Math.round((result % 65536) / 2);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_ir_value(%1)'],\n            },\n        },\n        robotis_RCar_cm_ir_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_front_right, '360'],\n                        [Lang.Blocks.robotis_front_left, '362'],\n                        [Lang.Blocks.robotis_bottom_right, '364'],\n                        [Lang.Blocks.robotis_bottom_left, '366'],\n                        [Lang.Blocks.robotis_side_right, '368'],\n                        [Lang.Blocks.robotis_side_left, '370'],\n                    ],\n                    value: '360',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_if_greater, '0'],\n                        [Lang.Blocks.robotis_if_smaller, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    50,\n                    null,\n                ],\n                type: 'robotis_RCar_cm_ir_compare',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                COMPARE_VAL: 1,\n                COMPARE_OP: 2,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('VALUE');\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n                \n                var result = Entry.hw.portData[data_address];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                result = Math.round((result % 65536) / 2);\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    default:\n                        return false;\n                }\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_ir_compare(%1)'],\n            },\n        },\n        robotis_RCar_detectFrontObj:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_front_ir_sensor, '0'],\n                        [Lang.Blocks.robotis_distance_sensor, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                /*\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_front, '0'],\n                        [Lang.Blocks.robotis_right, '1'],\n                        [Lang.Blocks.robotis_left, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                */\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    //null,\n                ],\n                type: 'robotis_RCar_detectFrontObj',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                //DIRECTION: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                let sensorType = script.getNumberValue('SENSOR');\n                let ir_1 = 0;\n                let ir_2 = 0;\n\n                if (sensorType == 0)\n                {\n                    ir_1 = Entry.hw.portData[360];\n                    ir_2 = Entry.hw.portData[362];\n                    if (ir_1 == undefined) ir_1 = 0;\n                    if (ir_2 == undefined) ir_2 = 0;\n                    return ir_1 > 100 || ir_2 > 100;\n                } else if (sensorType == 1) {\n                    let device_id_name = \"DIST_110_DISTANCE\";\n    \n                    var result = Entry.hw.portData[device_id_name];\n    \n                    if(typeof result == 'undefined') {\n                        return false;\n                    } else {\n                        return result < 200;\n                    }\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_detectFrontObj()'],\n            },\n        },\n        robotis_RCar_cm_btn_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_blue, '47'],\n                        [Lang.Blocks.robotis_red, '44'],\n                    ],\n                    value: '47',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_cm_btn_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('VALUE');\n                var compareValue = 1;\n\n                var result = Entry.hw.portData[data_address];\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_btn_value(%1)'],\n            },\n        },\n        robotis_RCar_cm_joystick_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [ \n                        [Lang.Blocks.robotis_center, '0'],\n                        ['←', '1'],\n                        ['→', '2'],\n                        ['↑', '3'],\n                        ['↓', '4'],\n                        ['↖', '5'],\n                        ['↗', '6'],\n                        ['↙', '7'],\n                        ['↘', '8'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_RCar_cm_joystick_value',\n            },\n            paramsKeyMap: {\n                COMPARE_VAL: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 50;\n                var compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                var result = Entry.hw.portData[data_address];\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_joystick_value()'],\n            },\n        },\n        robotis_RCar_mic:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_RCar_mic',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 119;\n\n                var result = Entry.hw.portData[data_address];\n\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_mic()'],\n            },\n        },\n        robotis_RCar_detectSound_compare:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '1'],\n                        [Lang.Blocks.robotis_center, '0'],\n                        [Lang.Blocks.robotis_right, '255'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_detectSound_compare',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 5031;\n                var compareValue = script.getNumberValue('VALUE');\n\n\n                var result = Entry.hw.portData[data_address];\n                if(result == undefined) {\n                    return false;\n                }\n\n                return result == compareValue;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_detectSound_compare(%1)'],\n            },\n        },\n        robotis_RCar_imu:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', '78'],//72\n                        ['y', '80'],//74\n                        ['z', '82']//76\n                    ],\n                    value: '78',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_acceleration, '0'],//72\n                        [Lang.Blocks.robotis_gyro, '6'],//74\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_RCar_imu',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n                MODE: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('AXIS', script) - script.getNumberValue('MODE', script);\n\n                var result = Entry.hw.portData[data_address];\n\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_imu()'],\n            },\n        },\n        robotis_RCar_roll_pitch:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_roll, '70'],//72\n                        [Lang.Blocks.robotis_pitch, '88'],//74\n                    ],\n                    value: '70',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_roll_pitch',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('AXIS');\n\n                var result = Entry.hw.portData[data_address];\n\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_roll_pitch(%1)'],\n            },\n        },\n        robotis_RCar_distance_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_distance, '25'],\n                        [Lang.Blocks.robotis_sensing_button, '24'],\n                        [Lang.Blocks.robotis_sensing_brightness, '30'],\n                    ],\n                    value: '25',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_distance_value',\n            },\n            paramsKeyMap: {\n                ADDR: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('ADDR');\n                let device_id_name = \"\";\n\n                switch (data_address) {\n                    case 25:\n                        device_id_name = \"DIST_110_DISTANCE\";\n                        break;\n                    \n                    case 24:\n                        device_id_name = \"DIST_110_BUTTON\";\n                        break;\n                        \n                    case 30:\n                        device_id_name = \"DIST_110_BRIGHTNESS\";\n                        break;\n                }\n\n                var result = Entry.hw.portData[device_id_name];\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n\n                if (device_id_name == \"DIST_110_DISTANCE\") {\n                    if (result > 1000) result = 1000;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_distance_value(%1)'],\n            },\n        },\n        robotis_RCar_distance_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_distance, '25'],\n                        [Lang.Blocks.robotis_sensing_button, '24'],\n                        [Lang.Blocks.robotis_sensing_brightness, '30'],\n                    ],\n                    value: '25',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_if_greater, '0'],\n                        [Lang.Blocks.robotis_if_smaller, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: [0]\n                    },\n                    null,\n                ],\n                type: 'robotis_RCar_distance_compare',\n            },\n            paramsKeyMap: {\n                ADDR: 0,\n                COMPARE_VAL: 1,\n                COMPARE_OP: 2,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                var data_address = script.getNumberValue('ADDR');\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n\n                let device_id_name = \"\";\n\n                switch (data_address) {\n                    case 25:\n                        device_id_name = \"DIST_110_DISTANCE\";\n                        break;\n                    \n                    case 24:\n                        device_id_name = \"DIST_110_BUTTON\";\n                        break;\n                        \n                    case 30:\n                        device_id_name = \"DIST_110_BRIGHTNESS\";\n                        break;\n                }\n\n                var result = Entry.hw.portData[device_id_name];\n                if (typeof result == 'undefined') {\n                    return false;\n                }\n\n                if (device_id_name == \"DIST_110_DISTANCE\") {\n                    if (result > 1000) result = 1000;\n                }\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                    default:\n                        return false;\n                }\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB10_distance_compare(%1)'],\n            },\n        },\n        robotis_RCar_dxl_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left_wheel, '36'],\n                        [Lang.Blocks.robotis_right_wheel, '35'],\n                    ],\n                    value: '36',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_dxl_value_angle, '1'],\n                        [Lang.Blocks.robotis_dxl_value_velocity, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    36,\n                    null,\n                ],\n                type: 'robotis_RCar_dxl_value',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                var dxl_id = script.getNumberValue('ID');\n                //var data_type = script.getNumberValue('TYPE');\n                let device_id_name = `DXL_POS_${dxl_id}`;\n\n                var result = Entry.hw.portData[device_id_name];\n\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n                result = 180 - Math.round(result * 360 / 4096);\n                while (result < -180) result += 360;\n                while (result > 180) result -= 360;\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.get_dxl_value(%1, %2)'],\n            },\n        },\n        robotis_RCar_line_cross_compare:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_line_cross_type_5, '5'],\n                        [Lang.Blocks.robotis_line_cross_type_6, '6'],\n                        [Lang.Blocks.robotis_line_cross_type_7, '7'],\n                        [Lang.Blocks.robotis_line_cross_type_8, '8'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_line_cross_compare',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 5201;\n                var compareValue = script.getNumberValue('VALUE');\n\n                var result = Entry.hw.portData[data_address];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n\n                return result == compareValue;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_cross_type_compare(%1)'],\n            },\n        },\n\n\n\n        \n        robotis_RCar_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_rla, '2'],\n                        [Lang.Blocks.robotis_rgee, '0'],\n                        [Lang.Blocks.robotis_kkokdu, '3'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_car_anim01, '2817'],\n                        [Lang.Blocks.robotis_car_anim02, '2818'],\n                        [Lang.Blocks.robotis_car_anim03, '2819'],\n                        [Lang.Blocks.robotis_car_anim04, '2820'],\n                        [Lang.Blocks.robotis_car_anim05, '2821'],\n\n                        [Lang.Blocks.robotis_car_anim06, '2822'],\n                        //[Lang.Blocks.robotis_car_anim07, '2823'], \n                        [Lang.Blocks.robotis_car_anim08, '2824'],\n                        [Lang.Blocks.robotis_car_anim09, '2825'],\n                        [Lang.Blocks.robotis_car_anim10, '2826'],\n\n                        [Lang.Blocks.robotis_car_anim11, '2827'],\n                        [Lang.Blocks.robotis_car_anim12, '2828'], \n                        //[Lang.Blocks.robotis_car_anim13, '2829'],\n                        [Lang.Blocks.robotis_car_anim14, '2830'],\n                        [Lang.Blocks.robotis_car_anim15, '2831'],\n\n                        [Lang.Blocks.robotis_car_anim16, '2832'],\n                        [Lang.Blocks.robotis_car_anim17, '2833'], \n                        [Lang.Blocks.robotis_car_anim18, '2834'],\n                        [Lang.Blocks.robotis_car_anim19, '2835'],\n                    ],\n                    value: '2817',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_screen',\n            },\n            paramsKeyMap: {\n                ROBOT_TYPE: 0,\n                BACKGROUND: 1,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var robotType = script.getNumberValue('ROBOT_TYPE', script);\n                var screenValue = script.getNumberValue('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue + robotType * 256;\n\n                if (robotType == 0) {\n                    switch (screenValue) {\n                        case 2817:\n                            data_value = 2841;\n                            break;\n                        \n                        case 2818:\n                            data_value = 2842;\n                            break;\n                        \n                        case 2819:\n                            data_value = 2820;\n                            break;\n                            \n                        case 2820:\n                            data_value = 2817;\n                            break;\n                        \n                        case 2821:\n                            data_value = 2819;\n                            break;\n                        \n                        case 2822:\n                            data_value = 2818;\n                            break;\n                        \n                        //case 2823:\n                        //    break;\n                        \n                        case 2824:\n                            data_value = 2826;\n                            break;\n                        \n                        case 2825:\n                            data_value = 2836;\n                            break;\n                        \n                        case 2826:\n                            data_value = 2837;\n                            break;\n                        \n                        case 2827:\n                            data_value = 2843;\n                            break;\n                        \n                        case 2828:\n                            data_value = 2831;\n                            break;\n                        \n                        //case 2829:\n                        //    break;\n                        \n                        case 2830:\n                            data_value = 2833;\n                            break;\n                            \n                        case 2831:\n                            data_value = 2834;\n                            break;\n                            \n                        case 2832:\n                            data_value = 2828;\n                            break;\n                            \n                        case 2833:\n                            data_value = 2827;\n                            break;\n                            \n                        case 2834:\n                            data_value = 2829;\n                            break;\n                            \n                        case 2835:\n                            data_value = 2840;\n                            break;\n                        \n                        default:\n                            data_value = 2841;\n                            break;\n                    }\n                }\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: { js: [], py: ['Robotis.RB100_screen(%1, %2)'] },\n        },\n\n        robotis_RCar_anim_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_rla, '0'],\n                        [Lang.Blocks.robotis_rgee, '-1'],\n                        [Lang.Blocks.robotis_kkokdu, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_car_anim01, '30978'],\n                        [Lang.Blocks.robotis_car_anim02, '30981'],\n                        //[Lang.Blocks.robotis_car_anim03, '30982'],\n                        [Lang.Blocks.robotis_car_anim04, '30983'],\n                        [Lang.Blocks.robotis_car_anim05, '30984'],\n\n                        [Lang.Blocks.robotis_car_anim06, '30985'],\n                        //[Lang.Blocks.robotis_car_anim07, '30986'], \n                        [Lang.Blocks.robotis_car_anim08, '30987'],\n                        [Lang.Blocks.robotis_car_anim09, '30988'],\n                        [Lang.Blocks.robotis_car_anim10, '30989'],\n\n                        [Lang.Blocks.robotis_car_anim11, '30990'],\n                        [Lang.Blocks.robotis_car_anim12, '30991'], \n                        //[Lang.Blocks.robotis_car_anim13, '30992'],\n                        [Lang.Blocks.robotis_car_anim14, '30993'],\n                        [Lang.Blocks.robotis_car_anim15, '30994'],\n\n                        [Lang.Blocks.robotis_car_anim16, '30995'],\n                        [Lang.Blocks.robotis_car_anim17, '30996'], \n                        [Lang.Blocks.robotis_car_anim18, '30997'],\n                        [Lang.Blocks.robotis_car_anim19, '30998'],\n                    ],\n                    value: '30978',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_anim_screen',\n            },\n            paramsKeyMap: {\n                ROBOT_TYPE: 0,\n                BACKGROUND: 1,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var robotType = script.getNumberValue('ROBOT_TYPE', script);\n                var screenValue = script.getNumberValue('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue;\n\n                if (robotType >= 0) {\n                    data_value += 256 * robotType;\n                } else {\n                    switch (screenValue) {\n                        case 30978:\n                            data_value = 30724;\n                            break;\n                        \n                        case 30981:\n                            data_value = 30761;\n                            break;\n                        \n                        //case 30982:\n                        //    break;\n                            \n                        case 30983:\n                            data_value = 30748;\n                            break;\n                        \n                        case 30984:\n                            data_value = 30750;\n                            break;\n                        \n                        case 30985:\n                            data_value = 30749;\n                            break;\n                        \n                        //case 30986:\n                        //    break;\n                        \n                        case 30987:\n                            data_value = 30739;\n                            break;\n                        \n                        case 30988:\n                            data_value = 30751;\n                            break;\n                        \n                        case 30989:\n                            data_value = 30752;\n                            break;\n                        \n                        case 30990:\n                            data_value = 30762;\n                            break;\n                        \n                        case 30991:\n                            data_value = 30736;\n                            break;\n                        \n                        //case 30992:\n                        //    break;\n                        \n                        case 30993:\n                            data_value = 30742;\n                            break;\n                            \n                        case 30994:\n                            data_value = 30743;\n                            break;\n                            \n                        case 30995:\n                            data_value = 30734;\n                            break;\n                            \n                        case 30996:\n                            data_value = 30733;\n                            break;\n                            \n                        case 30997:\n                            data_value = 30732;\n                            break;\n                            \n                        case 30998:\n                            data_value = 30760;\n                            break;\n                        \n                        default:\n                            data_value = 30724;\n                            break;\n                    }\n                }\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay //+ 1000\n                );\n            },\n            syntax: { js: [], py: ['Robotis.RB100_anim_screen(%1)'] },\n        },\n        robotis_RCar_icon_screen_food_plant: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_food_plant_1, '10496'],\n                        [Lang.Blocks.robotis_icon_food_plant_2, '10497'],\n                        [Lang.Blocks.robotis_icon_food_plant_3, '10498'],\n                        [Lang.Blocks.robotis_icon_food_plant_4, '10499'],\n                        [Lang.Blocks.robotis_icon_food_plant_5, '10500'],\n                        [Lang.Blocks.robotis_icon_food_plant_6, '10501'],\n                        [Lang.Blocks.robotis_icon_food_plant_7, '10502'],\n                        [Lang.Blocks.robotis_icon_food_plant_8, '10503'],\n                        [Lang.Blocks.robotis_icon_food_plant_9, '10504'],\n                        [Lang.Blocks.robotis_icon_food_plant_10, '10505'],\n                        [Lang.Blocks.robotis_icon_food_plant_11, '10506'],\n                        [Lang.Blocks.robotis_icon_food_plant_12, '10507'],\n                        [Lang.Blocks.robotis_icon_food_plant_13, '10508'],\n                        [Lang.Blocks.robotis_icon_food_plant_14, '10509'],\n                        [Lang.Blocks.robotis_icon_food_plant_15, '10510'],\n                        [Lang.Blocks.robotis_icon_food_plant_16, '10511'],\n                        [Lang.Blocks.robotis_icon_food_plant_17, '10512'],\n                        [Lang.Blocks.robotis_icon_food_plant_18, '10513'],\n                        [Lang.Blocks.robotis_icon_food_plant_19, '10514'],\n                        [Lang.Blocks.robotis_icon_food_plant_20, '10515'],\n                        [Lang.Blocks.robotis_icon_food_plant_21, '10516'],\n                        [Lang.Blocks.robotis_icon_food_plant_22, '10517'],\n                        [Lang.Blocks.robotis_icon_food_plant_23, '10518'],\n                        [Lang.Blocks.robotis_icon_food_plant_24, '10519'],\n                    ],\n                    value: '10496',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_RCar_icon_screen_food_plant',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script) * 2;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_icon_screen_food_plant(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RCar_icon_screen_animal_human: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_animal_human_1, '10752'],\n                        [Lang.Blocks.robotis_icon_animal_human_2, '10753'],\n                        [Lang.Blocks.robotis_icon_animal_human_3, '10754'],\n                        [Lang.Blocks.robotis_icon_animal_human_4, '10755'],\n                        [Lang.Blocks.robotis_icon_animal_human_5, '10756'],\n                        [Lang.Blocks.robotis_icon_animal_human_6, '10757'],\n                        [Lang.Blocks.robotis_icon_animal_human_7, '10758'],\n                        [Lang.Blocks.robotis_icon_animal_human_8, '10759'],\n                        [Lang.Blocks.robotis_icon_animal_human_9, '10760'],\n                        [Lang.Blocks.robotis_icon_animal_human_10, '11787'],\n                        [Lang.Blocks.robotis_icon_animal_human_11, '11788'],\n                        [Lang.Blocks.robotis_icon_animal_human_12, '11789'],\n                        [Lang.Blocks.robotis_icon_animal_human_13, '11790'],\n                        [Lang.Blocks.robotis_icon_animal_human_14, '11805'],\n                        [Lang.Blocks.robotis_icon_animal_human_15, '11806'],\n                        [Lang.Blocks.robotis_icon_animal_human_16, '11807'],\n                        [Lang.Blocks.robotis_icon_animal_human_17, '11808'],\n                        [Lang.Blocks.robotis_icon_animal_human_18, '10761'],\n                        [Lang.Blocks.robotis_icon_animal_human_19, '10762'],\n                        [Lang.Blocks.robotis_icon_animal_human_20, '10763'],\n                        [Lang.Blocks.robotis_icon_animal_human_21, '10764'],\n                        [Lang.Blocks.robotis_icon_animal_human_22, '10765'],\n                        [Lang.Blocks.robotis_icon_animal_human_23, '10766'],\n                        [Lang.Blocks.robotis_icon_animal_human_24, '10767'],\n                        [Lang.Blocks.robotis_icon_animal_human_25, '10768'],\n                        [Lang.Blocks.robotis_icon_animal_human_26, '10769'],\n                        [Lang.Blocks.robotis_icon_animal_human_27, '10770'],\n                        [Lang.Blocks.robotis_icon_animal_human_28, '10771'],\n                        [Lang.Blocks.robotis_icon_animal_human_29, '10772'],\n                        [Lang.Blocks.robotis_icon_animal_human_30, '10773'],\n                        [Lang.Blocks.robotis_icon_animal_human_31, '10774'],\n                        [Lang.Blocks.robotis_icon_animal_human_32, '10775'],\n                        [Lang.Blocks.robotis_icon_animal_human_33, '10776'],\n                        [Lang.Blocks.robotis_icon_animal_human_34, '10777'],\n                    ],\n                    value: '10752',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_RCar_icon_screen_animal_human',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script) * 2;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_icon_screen_animal_human(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RCar_icon_screen_object_tool: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_object_tool_1, '11008'],\n                        [Lang.Blocks.robotis_icon_object_tool_2, '11009'],\n                        [Lang.Blocks.robotis_icon_object_tool_3, '11010'],\n                        [Lang.Blocks.robotis_icon_object_tool_4, '11011'],\n                        [Lang.Blocks.robotis_icon_object_tool_5, '11012'],\n                        [Lang.Blocks.robotis_icon_object_tool_6, '11013'],\n                        [Lang.Blocks.robotis_icon_object_tool_7, '11014'],\n                        [Lang.Blocks.robotis_icon_object_tool_8, '11015'],\n                        [Lang.Blocks.robotis_icon_object_tool_9, '11016'],\n                        [Lang.Blocks.robotis_icon_object_tool_10, '11017'],\n                        [Lang.Blocks.robotis_icon_object_tool_11, '11018'],\n                        [Lang.Blocks.robotis_icon_object_tool_12, '11019'],\n                        [Lang.Blocks.robotis_icon_object_tool_13, '11020'],\n                        [Lang.Blocks.robotis_icon_object_tool_14, '11021'],\n                        [Lang.Blocks.robotis_icon_object_tool_15, '11022'],\n                        [Lang.Blocks.robotis_icon_object_tool_16, '11023'],\n                        [Lang.Blocks.robotis_icon_object_tool_17, '11024'],\n                        [Lang.Blocks.robotis_icon_object_tool_18, '11025'],\n                        [Lang.Blocks.robotis_icon_object_tool_19, '11026'],\n                        [Lang.Blocks.robotis_icon_object_tool_20, '11027'],\n                        [Lang.Blocks.robotis_icon_object_tool_21, '11028'],\n                        [Lang.Blocks.robotis_icon_object_tool_22, '11029'],\n                        [Lang.Blocks.robotis_icon_object_tool_23, '11030'],\n                        [Lang.Blocks.robotis_icon_object_tool_24, '11031'],\n                        [Lang.Blocks.robotis_icon_object_tool_25, '11032'],\n                        [Lang.Blocks.robotis_icon_object_tool_26, '11033'],\n                        [Lang.Blocks.robotis_icon_object_tool_27, '11034'],\n                        [Lang.Blocks.robotis_icon_object_tool_28, '11035'],\n                        [Lang.Blocks.robotis_icon_object_tool_29, '11036'],\n                        [Lang.Blocks.robotis_icon_object_tool_30, '11037'],\n                        [Lang.Blocks.robotis_icon_object_tool_31, '11038'],\n                        [Lang.Blocks.robotis_icon_object_tool_32, '11039'],\n                        [Lang.Blocks.robotis_icon_object_tool_33, '11040'],\n                        [Lang.Blocks.robotis_icon_object_tool_34, '11801'],\n                        [Lang.Blocks.robotis_icon_object_tool_35, '11802'],\n                        [Lang.Blocks.robotis_icon_object_tool_36, '11809'],\n                    ],\n                    value: '11008',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_RCar_icon_screen_object_tool',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script) * 2;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_icon_screen_object_tool(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RCar_icon_screen_vehicle_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_vehicle_number_1, '11264'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_2, '11265'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_3, '11266'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_4, '11267'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_5, '11268'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_6, '11269'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_7, '11270'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_8, '11271'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_9, '11272'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_10, '11273'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_11, '11274'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_12, '11275'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_13, '11276'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_14, '11776'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_15, '11777'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_16, '11778'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_17, '11779'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_18, '11780'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_19, '11781'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_20, '11782'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_21, '11783'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_22, '11277'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_23, '11278'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_24, '11279'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_25, '11280'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_26, '11281'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_27, '11282'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_28, '11283'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_29, '11284'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_30, '11285'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_31, '11286'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_32, '11287'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_33, '11288'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_34, '11289'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_35, '11290'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_36, '11291'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_37, '11292'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_38, '11293'],\n                    ],\n                    value: '11264',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_RCar_icon_screen_vehicle_number',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script) * 2;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_icon_screen_vehicle_number(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RCar_icon_screen_game_character: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_game_character_1, '11520'], // 알쥐(정면)\n                        [Lang.Blocks.robotis_icon_game_character_2, '11521'], // 알쥐(왼쪽)\n                        [Lang.Blocks.robotis_icon_game_character_3, '11522'], // 알쥐(오른쪽)\n                        [Lang.Blocks.robotis_icon_game_character_4, '11523'], // 알라(정면)\n                        [Lang.Blocks.robotis_icon_game_character_5, '11524'], // 알라(왼쪽)\n                        [Lang.Blocks.robotis_icon_game_character_6, '11525'], // 알라(오른쪽)\n                        [Lang.Blocks.robotis_icon_game_character_7, '11526'], // 유령\n                        [Lang.Blocks.robotis_icon_game_character_8, '11527'], // 괴물\n                        [Lang.Blocks.robotis_icon_game_character_9, '11528'], // 바이러스\n                        [Lang.Blocks.robotis_icon_game_character_10, '11529'], // 세균\n                        [Lang.Blocks.robotis_icon_game_character_11, '11784'], // 나는 알쥐(L)\n                        [Lang.Blocks.robotis_icon_game_character_12, '11785'], // 나는 알쥐(R)\n                        [Lang.Blocks.robotis_icon_game_character_13, '11786'], // 나는 알쥐(U)\n                        [Lang.Blocks.robotis_icon_game_character_14, '11530'], // 메달\n                        [Lang.Blocks.robotis_icon_game_character_15, '11531'], // 돈(G)\n                        [Lang.Blocks.robotis_icon_game_character_16, '11532'], // 돈($)\n                        [Lang.Blocks.robotis_icon_game_character_17, '11533'], // 하트\n                        [Lang.Blocks.robotis_icon_game_character_18, '11534'], // 포탄\n                        [Lang.Blocks.robotis_icon_game_character_19, '11535'], // 불\n                        [Lang.Blocks.robotis_icon_game_character_20, '11803'], // 구름1\n                        [Lang.Blocks.robotis_icon_game_character_21, '11804'], // 구름2\n                        [Lang.Blocks.robotis_icon_game_character_22, '11536'], // 포탄1\n                        [Lang.Blocks.robotis_icon_game_character_23, '11791'], // 포탄2\n                        [Lang.Blocks.robotis_icon_game_character_24, '11537'], // 대포(수평)\n                        [Lang.Blocks.robotis_icon_game_character_25, '11538'], // 대포(수직)\n                        [Lang.Blocks.robotis_icon_game_character_27, '11540'], // 레이저(수평)\n                        [Lang.Blocks.robotis_icon_game_character_26, '11539'], // 레이저(수직)\n                        [Lang.Blocks.robotis_icon_game_character_28, '11541'], // 화살(수평)\n                        [Lang.Blocks.robotis_icon_game_character_29, '11542'], // 화살(수직)\n                        [Lang.Blocks.robotis_icon_game_character_30, '11792'], // 미사일(U)\n                        [Lang.Blocks.robotis_icon_game_character_31, '11793'], // 미사일(D)\n                        [Lang.Blocks.robotis_icon_game_character_32, '11794'], // 미사일(L)\n                        [Lang.Blocks.robotis_icon_game_character_33, '11795'], // 미사일(R)\n                        [Lang.Blocks.robotis_icon_game_character_34, '11796'], // 낙하산\n                        [Lang.Blocks.robotis_icon_game_character_35, '11543'], // 폭발1\n                        [Lang.Blocks.robotis_icon_game_character_36, '11544'], // 폭발2\n                        [Lang.Blocks.robotis_icon_game_character_37, '11810'], // 조준경\n                        [Lang.Blocks.robotis_icon_game_character_38, '11545'], // 가위\n                        [Lang.Blocks.robotis_icon_game_character_39, '11546'], // 바위\n                        [Lang.Blocks.robotis_icon_game_character_40, '11547'], // 보\n                        [Lang.Blocks.robotis_icon_game_character_41, '11797'], // 걷는 사람1\n                        [Lang.Blocks.robotis_icon_game_character_42, '11798'], // 걷는 사람2\n                        [Lang.Blocks.robotis_icon_game_character_43, '11799'], // 뛰는 사람1\n                        [Lang.Blocks.robotis_icon_game_character_44, '11800'], // 뛰는 사람2\n                    ],\n                    value: '11520',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_RCar_icon_screen_game_character',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func(sprite, script) {\n                // instruction / address / length / value / default length\n                let iconNum = script.getField('ICON', script);\n                let x = script.getNumberValue('X', script);\n                let y = script.getNumberValue('Y', script);\n                let size = script.getNumberValue('SIZE', script) * 2;\n\n                let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                let data_address = 166;\n                let data_length = 2;\n                let data_value = 10496;\n\n                if (x < -160) {\n                    x = -160;\n                } else if (x > 160) {\n                    x = 160;\n                }\n\n                if (y < -120) {\n                    y = -120;\n                } else if (y > 120) {\n                    y = 120;\n                }\n\n                if (size < 0) {\n                    size = 0;\n                } else if (size > 400) {\n                    size = 400;\n                }\n\n                data_value = iconNum;\n\n                let data_sendqueue = [\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size],\n                    [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_icon_screen_game_and_character(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RCar_text_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_screen_text_font_small, '0'],\n                        [Lang.Blocks.robotis_screen_text_font_big, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \" \",\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_text_screen',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                X: 1,\n                Y: 2,\n                FONT: 3,\n                COLOR: 4,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var text = script.getStringValue('TEXT', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var font = script.getNumberValue('FONT', script);\n                var color = script.getNumberValue('COLOR', script);\n                var data_buf = [];\n                var i = 0;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 900;\n                var data_length = 2;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                var encoder = new TextEncoder('utf-8');\n                var byteArray = encoder.encode(text);\n\n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(font);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(color);\n                data_buf.push(byteArray.length);\n                for (i = 0; i < byteArray.length; i++) {\n                    data_buf.push(byteArray[i]);\n                }\n               \n                data_length = 9 + byteArray.length;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_text_screen(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RCar_pixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RCar_pixel',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                COLOR: 2,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var color = script.getNumberValue('COLOR', script);\n                var data_buf = [];\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 130;\n                var data_length = 11;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n\n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(color);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 161, 2, 1 * 256 + 8\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_pixel(%1,%2,%3)'],\n            },\n        },\n        robotis_RCar_text_screen_redraw: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \" \",\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'robotis_RCar_text_screen_redraw',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                X: 1,\n                Y: 2,\n                COLOR: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var text = script.getStringValue('TEXT', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var font = 0;\n                var color = script.getNumberValue('COLOR', script);\n                var data_buf = [];\n                var i = 0;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                var encoder = new TextEncoder('utf-8');\n                var byteArray = encoder.encode(text);\n\n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(font);\n                data_buf.push(1);\n                data_buf.push(bg_color);\n                data_buf.push(color);\n                data_buf.push(byteArray.length);\n                for (i = 0; i < byteArray.length; i++) {\n                    data_buf.push(byteArray[i]);\n                }\n               \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 900;\n                var data_length = 9 + byteArray.length;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_text_screen_redraw(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_RCar_LCDBright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    50,\n                ],\n                type: 'robotis_RCar_LCDBright',\n            },\n            paramsKeyMap: {\n                BRIGHT: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var bright = script.getNumberValue('BRIGHT', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 180;\n                var data_length = 1;\n                var data_value = 0;\n\n                bright = Math.min(Math.max(bright, 0), 100);\n                \n                data_value = bright;\n                \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_LCDBright(%1)'],\n            },\n        },\n        robotis_RCar_LCDColor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '224',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_LCDColor',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var color = script.getNumberValue('COLOR', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = 0;\n                \n                data_value = color;\n                bg_color = color;\n                \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_LCDColor(%1)'],\n            },\n        },\n\n        \n        robotis_RCar_cm_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '1'],\n                        [Lang.Blocks.robotis_right, '2'],\n                        [Lang.Blocks.robotis_both, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_common_on, '1'],\n                        [Lang.Blocks.robotis_common_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotis_RCar_cm_led',\n            },\n            paramsKeyMap: {\n                RB_LED: 0,\n                VALUE: 1,\n            },\n            class: 'robotis_rb100_led',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmLed = script.getField('RB_LED', script);\n                var value = script.getField('VALUE', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 40;\n                var data_length = 1;\n                var data_value = 0;\n\n                if (cmLed == 1) {\n                    data_value = 200 * value;\n                } else if (cmLed == 2) {\n                    data_address = 41;\n                    data_value = 200 * value;\n                } else if (cmLed == 3) {\n                    data_address = 40;\n                    data_length = 2;\n                    data_value = 200 * 257 * value;\n                }\n              \n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.RB100_led(%1, %2)'] },\n        },\n        robotis_RCar_cm_led_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_pattern1, '11'],\n                        [Lang.Blocks.robotis_pattern2, '21'],\n                        [Lang.Blocks.robotis_pattern3, '31'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_speed_fast, '0'],\n                        [Lang.Blocks.robotis_speed_midium, '1'],\n                        [Lang.Blocks.robotis_speed_slow, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotis_RCar_cm_led_pattern',\n            },\n            paramsKeyMap: {\n                PATTERN: 0,\n                SPEED: 1,\n            },\n            class: 'robotis_rb100_led',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var pattern = script.getNumberValue('PATTERN', script);\n                var speed = script.getNumberValue('SPEED', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 40;\n                var data_length = 1;\n                var data_value = 0;\n\n                \n                data_value = pattern + speed;\n              \n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.RB100_led_pattern(%1, %2)'] },\n        },\n\n\n\n\n\n\n        \n        robotis_RCar_scale_simple: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.General.note_c + '', '1'],\n                        [Lang.General.note_c + '#', '2'],\n                        [Lang.General.note_d + '', '3'],\n                        [Lang.General.note_d + '#', '4'],\n                        [Lang.General.note_e + '', '5'],\n                        [Lang.General.note_f + '', '6'],\n                        [Lang.General.note_f + '#', '7'],\n                        [Lang.General.note_g + '', '8'],\n                        [Lang.General.note_g + '#', '9'],\n                        [Lang.General.note_a + '', '10'],\n                        [Lang.General.note_a + '#', '11'],\n                        [Lang.General.note_b + '', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_beat_sound_8th_note, '3'],\n                        [Lang.Blocks.robotis_beat_sound_dotted_8th_note, '4'],\n                        [Lang.Blocks.robotis_beat_sound_quarter_note, '5'],\n                        [Lang.Blocks.robotis_beat_sound_dotted_quarter_note, '6'],\n                        [Lang.Blocks.robotis_beat_sound_half_note, '7'],\n                        [Lang.Blocks.robotis_beat_sound_dotted_half_note, '8'],\n                        [Lang.Blocks.robotis_beat_sound_whole_note, '9'],\n                        [Lang.Blocks.robotis_beat_sound_dotted_note, '10'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_scale_simple',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_OCTAV: 0,\n                CM_BUZZER_INDEX: 1,\n                CM_BUZZER_NOTE: 2,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                var cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                var cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script);\n                let cmBuzzerTime = 0;\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address_1 = 0;\n                var data_length_1 = 0;\n                var data_value_1 = 0;\n                var data_address_2 = 0;\n                var data_length_2 = 0;\n                var data_value_2 = 0;\n                var interval = 0;\n\n                switch (cmBuzzerNote) {\n                    case 3:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute / 2);\n                        break;\n\n                    case 4:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute / 2 * 1.5);\n                        break;\n\n                    case 5:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute);\n                        break;\n\n                    case 6:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 1.5);\n                        break;\n\n                    case 7:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 2);\n                        break;\n\n                    case 8:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 2 * 1.5);\n                        break;\n\n                    case 9:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 4);\n                        break;\n    \n                    case 10:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 4 * 1.5);\n                        break;\n                }\n\n                data_address_1 = 740;\n                data_length_1 = 2;\n                // data_value_1 = cmBuzzerTime * 10;\n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                data_value_1 = cmBuzzerTime;\n                if (data_value_1 < 0) {\n                    data_value_1 = 0;\n                }\n                if (data_value_1 > 50000) {\n                    data_value_1 = 50000;\n                }\n\n                data_address_2 = 742;\n                data_length_2 = 1;\n                data_value_2 = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n\n                // console.log(\"buzzer send\");\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address_1,\n                        data_length_1,\n                        data_value_1,\n                    ],\n                    [\n                        data_instruction,\n                        data_address_2,\n                        data_length_2,\n                        data_value_2,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime + interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_buzzer_simple(%1, %2, %3)'],\n            },\n        }, \n        robotis_RCar_scale_advanced: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.General.note_c + '', '1'],\n                        [Lang.General.note_c + '#', '2'],\n                        [Lang.General.note_d + '', '3'],\n                        [Lang.General.note_d + '#', '4'],\n                        [Lang.General.note_e + '', '5'],\n                        [Lang.General.note_f + '', '6'],\n                        [Lang.General.note_f + '#', '7'],\n                        [Lang.General.note_g + '', '8'],\n                        [Lang.General.note_g + '#', '9'],\n                        [Lang.General.note_a + '', '10'],\n                        [Lang.General.note_a + '#', '11'],\n                        [Lang.General.note_b + '', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    1,\n                    null,\n                ],\n                type: 'robotis_RCar_scale_advanced',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_OCTAV: 0,\n                CM_BUZZER_INDEX: 1,\n                CM_BUZZER_BEAT: 2,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                var cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                var cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script);\n                let cmBuzzerTime = 0;\n\n                cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address_1 = 0;\n                var data_length_1 = 0;\n                var data_value_1 = 0;\n                var data_address_2 = 0;\n                var data_length_2 = 0;\n                var data_value_2 = 0;\n                var interval = 0;\n\n                cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * cmBuzzerBeat);\n\n                data_address_1 = 740;\n                data_length_1 = 2;\n                // data_value_1 = cmBuzzerTime * 10;\n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                data_value_1 = cmBuzzerTime;\n                if (data_value_1 < 0) {\n                    data_value_1 = 0;\n                }\n                if (data_value_1 > 50000) {\n                    data_value_1 = 50000;\n                }\n\n                data_address_2 = 742;\n                data_length_2 = 1;\n                data_value_2 = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n\n                // console.log(\"buzzer send\");\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address_1,\n                        data_length_1,\n                        data_value_1,\n                    ],\n                    [\n                        data_instruction,\n                        data_address_2,\n                        data_length_2,\n                        data_value_2,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime + interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_buzzer_advanced(%1, %2, %3)'],\n            },\n        }, \n        robotis_RCar_rest_simple: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_beat_rest_8th_note, '3'],\n                        [Lang.Blocks.robotis_beat_rest_quarter_note, '5'],\n                        [Lang.Blocks.robotis_beat_rest_half_note, '7'],\n                        [Lang.Blocks.robotis_beat_rest_whole_note, '9'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_rest_simple',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_NOTE: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script);\n                let cmBuzzerTime = 0;\n\n                var interval = 0;\n\n                switch (cmBuzzerNote) {\n                    case 3:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute / 2);\n                        break;\n\n                    case 5:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute);\n                        break;\n\n                    case 7:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 2);\n                        break;\n\n                    case 9:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 4);\n                        break;\n                }\n                \n                var data_sendqueue = [\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime + interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_rest_simple(%1)'],\n            },\n        }, \n        robotis_RCar_rest_advanced: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    1,\n                    null,\n                ],\n                type: 'robotis_RCar_rest_advanced',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_BEAT: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script);\n                let cmBuzzerTime = 0;\n\n                var interval = 0;\n                \n                cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100);\n\n                cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * cmBuzzerBeat);\n                \n                var data_sendqueue = [\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime + interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_rest_advanced(%1)'],\n            },\n        }, \n        robotis_RCar_beat_per_minute: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    75,\n                    null,\n                ],\n                type: 'robotis_RCar_beat_per_minute',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_BPM: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerBpm = script.getNumberValue('CM_BUZZER_BPM', script);\n\n                beat_per_minute = Math.min(Math.max(cmBuzzerBpm, 10), 600);\n\n                // console.log(\"buzzer send\");\n                var data_sendqueue = [\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    0,\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_bpm(%1)'],\n            },\n        }, \n        \n        robotis_RCar_Hello: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_korean1,'0'],\n                        [Lang.Blocks.robotis_korean2,'1'],\n                        [Lang.Blocks.robotis_korean3,'2'],\n                        [Lang.Blocks.robotis_korean4,'3'],\n                        [Lang.Blocks.robotis_korean5,'4'],\n                        [Lang.Blocks.robotis_korean6,'5'],\n                        [Lang.Blocks.robotis_korean7,'6'],\n                        [Lang.Blocks.robotis_korean8,'7'],\n                        [Lang.Blocks.robotis_korean9,'8'],\n                        [Lang.Blocks.robotis_korean10,'9'],\n                        [Lang.Blocks.robotis_korean11,'10'],\n                        [Lang.Blocks.robotis_korean12,'11'],\n                        [Lang.Blocks.robotis_korean13,'12'],\n                        [Lang.Blocks.robotis_korean14,'13'],\n                        [Lang.Blocks.robotis_korean15,'14'],\n                        [Lang.Blocks.robotis_korean16,'15'],\n                        [Lang.Blocks.robotis_korean17,'16'],\n                        [Lang.Blocks.robotis_korean18,'17'],\n                        [Lang.Blocks.robotis_korean19,'18'],\n                        [Lang.Blocks.robotis_korean20,'19'],\n                        [Lang.Blocks.robotis_korean21,'20'],\n                        [Lang.Blocks.robotis_korean22,'21'],\n                        [Lang.Blocks.robotis_korean23,'22'],\n                        [Lang.Blocks.robotis_korean24,'23'],\n                        [Lang.Blocks.robotis_korean25,'24'],\n                        [Lang.Blocks.robotis_korean26,'25'],\n                        [Lang.Blocks.robotis_korean27,'26'],\n                        [Lang.Blocks.robotis_korean28,'27'],\n                        [Lang.Blocks.robotis_korean29,'28'],\n                        [Lang.Blocks.robotis_korean30,'29'],\n                        [Lang.Blocks.robotis_korean31,'30'],\n                        [Lang.Blocks.robotis_korean32,'31'],\n                        [Lang.Blocks.robotis_korean33,'32'],\n                        [Lang.Blocks.robotis_korean34,'33'],\n                        [Lang.Blocks.robotis_korean35,'34'],\n                        [Lang.Blocks.robotis_korean36,'35'],\n                        [Lang.Blocks.robotis_korean37,'36'],\n                        [Lang.Blocks.robotis_korean38,'37'],\n                        [Lang.Blocks.robotis_korean39,'38'],\n                        [Lang.Blocks.robotis_korean40,'39'],\n                        [Lang.Blocks.robotis_korean41,'40'],\n                        [Lang.Blocks.robotis_korean42,'41'],\n                        [Lang.Blocks.robotis_korean43,'42'],\n                        [Lang.Blocks.robotis_korean44,'43'],\n                        [Lang.Blocks.robotis_korean45,'44'],\n                        [Lang.Blocks.robotis_korean46,'45'],\n                        [Lang.Blocks.robotis_korean47,'46'],\n                        [Lang.Blocks.robotis_korean48,'47'],\n                        [Lang.Blocks.robotis_korean49,'48'],\n                        [Lang.Blocks.robotis_korean50,'49'],\n                        [Lang.Blocks.robotis_korean51,'50'],\n                        [Lang.Blocks.robotis_korean52,'51'],\n                        [Lang.Blocks.robotis_korean53,'52'],\n                        [Lang.Blocks.robotis_korean54,'53'],\n                        [Lang.Blocks.robotis_korean55,'54'],\n                        [Lang.Blocks.robotis_korean56,'55'],\n                        [Lang.Blocks.robotis_korean57,'56'],\n                        [Lang.Blocks.robotis_korean58,'57'],\n                        [Lang.Blocks.robotis_korean59,'58'],\n                        [Lang.Blocks.robotis_korean60,'59'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_Hello',\n            },\n            paramsKeyMap: {\n                HELLO: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmHello = script.getField('HELLO', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 110;\n                var data_length = 2;\n                var data_value = 0;\n            \n               \n                data_value = 25601+Number(cmHello);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        data_instruction,\n                        0,\n                        2,\n                        0\n                    ]\n                ];\n\n\n                let extraTime = 0; \n                \n                if(cmHello == '38' || cmHello == '55') {\n                    extraTime = 2000;\n                }\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    2000 + extraTime\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_Hello(%1)'],\n            },\n        },\n        robotis_RCar_effectSound:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_koala, '8'],\n\n                        [Lang.Blocks.robotis_whistle, '274'],\n                        [Lang.Blocks.robotis_ambul, '773'],\n                        [Lang.Blocks.robotis_Horn, '781'],\n                        [Lang.Blocks.robotis_siren, '774'],\n                        \n\n                        [Lang.Blocks.robotis_gun, '775'],\n                        [Lang.Blocks.robotis_clap, '260'],\n\n                        [Lang.Blocks.robotis_melody1, '786'],\n                        [Lang.Blocks.robotis_melody2, '787'],\n                        [Lang.Blocks.robotis_melody3, '788'],\n                        [Lang.Blocks.robotis_melody4, '789'],\n\n                        [Lang.Blocks.robotis_dog, '0'],\n                        [Lang.Blocks.robotis_frog, '1'],\n                        [Lang.Blocks.robotis_cat, '2'],\n                        [Lang.Blocks.robotis_chicken, '7'],\n                        [Lang.Blocks.robotis_tiger, '19'],\n                        [Lang.Blocks.robotis_mouse, '17'],\n                    ],\n                    value: '8',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_effectSound',\n            },\n            paramsKeyMap: {\n                HELLO: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmHello = script.getField('HELLO', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 110;\n                var data_length = 2;\n                var data_value = 0;\n            \n               \n                data_value = Number(cmHello);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        data_instruction,\n                        0,\n                        2,\n                        0\n                    ]\n                ];\n                \n                let extraTime = 0;\n                if(cmHello == '272' || cmHello == '786' || cmHello == '787' || cmHello == '788' || cmHello == '789') { //오리\n                    extraTime = 0;\n                    if(cmHello == '788' || cmHello == '789') {\n                        extraTime += 500;\n                    }\n                }\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    3000 + extraTime\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_effect_sound(%1)'],\n            },\n        },\n        robotis_RCar_record:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_record',\n            },\n            paramsKeyMap: {\n                ROOM: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var roomNum = script.getField('ROOM', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 115;\n                var data_length = 1;\n                var data_value = 0;\n            \n               \n                data_value = roomNum;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    6000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_record(%1)'],\n            },\n        },\n        robotis_RCar_playRecord:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_playRecord',\n            },\n            paramsKeyMap: {\n                ROOM: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var roomNum = script.getField('ROOM', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 116;\n                var data_length = 1;\n                var data_value = 0;\n            \n               \n                data_value = roomNum;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    6000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB100_playRecord(%1)'],\n            },\n        },\n\n\n\n\n\n        \n        robotis_RCar_ai_camera_block_value_closest_to_center: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'],\n                        [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'],\n                        [Lang.Blocks.robotis_ai_camera_center_block_width, '2'],\n                        [Lang.Blocks.robotis_ai_camera_center_block_height, '3'],\n                        [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_ai_camera_block_value_closest_to_center',\n            },\n            paramsKeyMap: {\n                DATA_TYPE: 0,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4009;\n                var data_type = script.getNumberValue('DATA_TYPE');\n                data_address += data_type * 2;\n                var result = Entry.hw.portData[data_address];\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_block_value_closest_to_center(%1)'],\n            },\n        },\n        robotis_RCar_ai_camera_arrow_value_closest_to_center: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'],\n                        [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'],\n                        [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'],\n                        [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'],\n                        [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_ai_camera_arrow_value_closest_to_center',\n            },\n            paramsKeyMap: {\n                DATA_TYPE: 0,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4019;\n                var data_type = script.getNumberValue('DATA_TYPE');\n                data_address += data_type * 2;\n                var result = Entry.hw.portData[data_address];\n\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_arrow_value_closest_to_center(%1)'],\n            },\n        },\n        robotis_RCar_ai_camera_number_of_learned_id: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'robotis_RCar_ai_camera_number_of_learned_id',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4003;\n                var result = Entry.hw.portData[data_address];\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_number_of_learned_id()'],\n            },\n        },\n        robotis_RCar_ai_camera_block_value_of_id: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [\"1\", '1'],\n                            [\"2\", '2'],\n                            [\"3\", '3'],\n                            [\"4\", '4'],\n                            [\"5\", '5'],\n                            [\"6\", '6'],\n                            [\"7\", '7'],\n                            [\"8\", '8'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'],\n                            [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'],\n                            [Lang.Blocks.robotis_ai_camera_center_block_width, '2'],\n                            [Lang.Blocks.robotis_ai_camera_center_block_height, '3'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_ai_camera_block_value_of_id',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4029; // ID_FOR_USE\n                var data_length = 2;\n                var data_value = script.getNumberValue('ID');\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n\n                Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n\n                data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER\n\n                data_address += script.getNumberValue('TYPE') * 2;\n\n                var result = Entry.hw.portData[data_address];\n\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_block_value_of_id(%1, %2)'],\n            },\n        },\n        robotis_RCar_ai_camera_arrow_value_of_id: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [\"1\", '1'],\n                            [\"2\", '2'],\n                            [\"3\", '3'],\n                            [\"4\", '4'],\n                            [\"5\", '5'],\n                            [\"6\", '6'],\n                            [\"7\", '7'],\n                            [\"8\", '8'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'],\n                            [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'],\n                            [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'],\n                            [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_RCar_ai_camera_arrow_value_of_id',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4029; // ID_FOR_USE\n                var data_length = 2;\n                var data_value = script.getNumberValue('ID');\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n\n                Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n\n                data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN\n\n                data_address += script.getNumberValue('TYPE') * 2;\n                var result = Entry.hw.portData[data_address];\n\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_arrow_value_of_id(%1, %2)'],\n            },\n        },\n        robotis_RCar_ai_camera_connection_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_connected, '1'],\n                        [Lang.Blocks.robotis_disconnected, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_ai_camera_connection_status',\n            },\n            paramsKeyMap: {\n                STATUS: 0,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4000;\n                var compareValue = script.getNumberValue('STATUS');\n                var result = Entry.hw.portData[data_address];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_connection_status(%1)'],\n            },\n        },\n        robotis_RCar_ai_camera_if_detected: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_block, '0'],\n                        [Lang.Blocks.robotis_ai_camera_arrow, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_ai_camera_if_detected',\n            },\n            paramsKeyMap: {\n                DETECT_TYPE: 0,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4005; // block\n                var detect_type = script.getNumberValue('DETECT_TYPE');\n\n                if (detect_type == 1) data_address = 4006; // arrow\n\n                var result = Entry.hw.portData[data_address];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == 1);\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_if_detected(%1)'],\n            },\n        },\n        robotis_RCar_ai_camera_set_mode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_mode_face_recognition, '0'],\n                        [Lang.Blocks.robotis_ai_camera_mode_object_tracking, '1'],\n                        [Lang.Blocks.robotis_ai_camera_mode_object_recognition, '2'],\n                        [Lang.Blocks.robotis_ai_camera_mode_line_tracking, '3'],\n                        [Lang.Blocks.robotis_ai_camera_mode_color_recognition, '4'],\n                        [Lang.Blocks.robotis_ai_camera_mode_tag_recognition, '5'],\n                        [Lang.Blocks.robotis_ai_camera_mode_object_classification, '6'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_RCar_ai_camera_set_mode',\n            },\n            paramsKeyMap: {\n                AI_CAMERA_MODE: 0,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var ai_camera_mode = script.getField('AI_CAMERA_MODE', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4001;\n                var data_length = 1;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        ai_camera_mode,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.set_ai_camera_mode(%1)'],\n            },\n        },\n        robotis_RCar_ai_camera_print_custom_text: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    \"Hello!\"\n                ],\n                type: 'robotis_RCar_ai_camera_print_custom_text',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                TEXT: 2,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var text = script.getStringValue('TEXT', script);\n                var data_buf = [];\n                var i = 0;\n\n                // Encode the text as UTF-8\n                let encoder = new TextEncoder();\n                let utf8Array = encoder.encode(text);\n\n                // utf8Array is now a Uint8Array containing the UTF-8 bytes of the text\n                let text_len = utf8Array.length;\n\n                if (text_len > 45) text_len = 45;\n                \n                if (x < -160) x = 160;\n                else if (x > 160) x = 160;\n\n                if (y < -120) y = 120;\n                else if (y > 120) y = 120;\n\n                if (x < 0) x = 65536 + x;\n                if (y < 0) y = 65536 + y;\n                \n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(0);\n                data_buf.push(0);\n                for (i = 0; i < text_len; i++) {\n                    data_buf.push(utf8Array[i]);\n                }\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4200;\n                var data_length = 6 + text_len;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_print_custom_text(%1,%2,%3)'],\n            },\n        },\n        robotis_RCar_ai_camera_clear_custom_text: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'robotis_RCar_ai_camera_clear_custom_text',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_koala'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4250;\n                var data_length = 1;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        1,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_clear_custom_text()'],\n            },\n        },\n    };\n}\n\nmodule.exports = [Entry.Robotis_rb_koala];\n\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js",
    "content": "'use strict';\n\nEntry.Robotis_rb_P_Assembly = {\n    INSTRUCTION: {\n        NONE: 0,\n        WRITE: 3,\n        READ: 2,\n        SYNCWRITE: 4,\n        REGWRITE: 5,\n        ACTION: 6,\n        BYPASS_READ: 0xA2,\n        BYPASS_WRITE: 0xA3\n    },\n    CONTROL_TABLE: {\n        // [default address, default length, address (when reads together), length (when reads together)]\n        CM_LED_R: [79, 1],\n        CM_LED_G: [80, 1],\n        CM_LED_B: [81, 1],\n\n        RB_LED_L: [40, 1],\n        RB_LED_R: [41, 1],\n        RB_LED_B: [40, 2],\n\n        CM_BUZZER_INDEX: [60, 1], //[84, 1]\n        CM_BUZZER_TIME: [63, 1], //[85, 1]\n        CM_SOUND_DETECTED: [86, 1],\n        CM_SOUND_DETECTING: [87, 1],\n        CM_USER_BUTTON: [26, 1],\n        CM_MOTION: [66, 2], //[66,1]\n\n        AUX_SERVO_POSITION: [152, 2],\n\n        AUX_CUSTOM: [216, 2],\n\n        AUX_SERVO_MODE: [126, 1],\n        AUX_SERVO_SPEED: [136, 2],\n        AUX_MOTOR_SPEED: [136, 2],\n        AUX_LED_MODULE: [210, 1],\n    },\n    DXL_POSITION: {\n        values: [0, 0, 0, 0, 0, 0, 0, 0]\n    },\n    setZero: function () {\n        // instruction / address / length / value / default length\n        Entry.Robotis_carCont.setRobotisData([\n            [Entry.Robotis_rb.INSTRUCTION.WRITE, 2100, 1, 1], // PracticeBot Finish\n        ]);\n        camera_id_for_use = 0;\n        Entry.Robotis_carCont.update();\n    },\n    id: ['7.A', '7.B'],\n    name: 'Robotis_rb_P_Assembly',\n    url: 'http://www.robotis.com/index/product.php?cate_code=111310',\n    imageName: 'robotis_RB100_Practical_Assembly.png',\n    title: {\n        \"ko\": \"로봇아이(AI)\",\n        \"en\": \"Robot AI\"\n    },\n    delay: 30,\n    readDelay: 30,\n};\n\nEntry.Robotis_rb_P_Assembly.blockMenuBlocks = [\n    // 주행 제어\n    'robotis_Practice_drive_simple',\n    'robotis_Practice_drive_advanced',\n    'robotis_Practice_drive_seperate',\n    'robotis_Practice_drive_angle',\n    'robotis_Practice_go_distance',\n    'robotis_Practice_turn_angle',\n    'robotis_Practice_follow_line',\n    'robotis_Practice_stop_at_cross',\n    'robotis_Practice_turn_at_line',\n    'robotis_Practice_drive_stop',\n\n    'robotis_Practice_securitybot_init',\n    'robotis_Practice_securitybot_hi',\n    'robotis_Practice_securitybot_alert',\n\n    'robotis_Practice_petbot_happy',\n    'robotis_Practice_petbot_sad',\n\n    'robotis_Practice_farmbot_init',\n    'robotis_Practice_farmbot_seek',\n    'robotis_Practice_farmbot_plant_type',\n    'robotis_Practice_farmbot_harvest_or_not_and_go',\n\n    // 값 블록\n    'robotis_Practice_cm_ir_value',\n    'robotis_Practice_detectFrontObj',\n    'robotis_Practice_cm_ir_compare',\n    'robotis_Practice_cm_btn_value',\n    'robotis_Practice_cm_joystick_value',\n    'robotis_Practice_mic',\n    'robotis_Practice_detectSound_compare',\n    'robotis_Practice_imu',\n    'robotis_Practice_roll_pitch', \n    //'robotis_Practice_distance_value',\n    'robotis_Practice_environment_value',\n    'robotis_Practice_line_cross_compare',\n    //'robotis_Practice_distance_compare',\n    'robotis_Practice_environment_compare',\n    'robotis_Practice_dxl_value',\n\n    // 소리\n    'robotis_Practice_scale_simple',\n    'robotis_Practice_scale_advanced',\n    'robotis_Practice_rest_simple',\n    'robotis_Practice_rest_advanced',\n    'robotis_Practice_beat_per_minute',\n    'robotis_Practice_Hello',\n    'robotis_Practice_effectSound',\n    'robotis_Practice_record',\n    'robotis_Practice_playRecord',\n\n    // LCD 제어\n    'robotis_Practice_screen',\n    'robotis_Practice_anim_screen',\n    'robotis_Practice_icon_screen_food_plant',\n    'robotis_Practice_icon_screen_animal_human',\n    'robotis_Practice_icon_screen_object_tool',\n    'robotis_Practice_icon_screen_vehicle_number',\n    'robotis_Practice_icon_screen_game_character',\n    'robotis_Practice_text_screen',\n    'robotis_Practice_text_screen_redraw',\n    'robotis_Practice_pixel',\n    'robotis_Practice_LCDColor',\n    'robotis_Practice_LCD_Flash',\n    'robotis_Practice_LCDBright',\n\n    // LED 제어\n    'robotis_Practice_cm_led',\n    'robotis_Practice_cm_led_pattern',\n\n    // 다이나믹셀 제어\n    'robotis_Practice_dxl_set_mode',\n    'robotis_Practice_dxl_each_control',\n    'robotis_Practice_dxl_set_position',\n    'robotis_Practice_dxl_set_rotate',\n    'robotis_Practice_dxl_set_multiturn_round',\n\n    // 인공지능 카메라 값 블록\n    'robotis_Practice_ai_camera_connection_status',\n    'robotis_Practice_ai_camera_if_detected',\n\n    'robotis_Practice_ai_camera_block_value_closest_to_center',\n    'robotis_Practice_ai_camera_arrow_value_closest_to_center',\n    'robotis_Practice_ai_camera_number_of_learned_id',\n    'robotis_Practice_ai_camera_block_value_of_id',\n    'robotis_Practice_ai_camera_arrow_value_of_id',\n\n    'robotis_Practice_ai_camera_if_learned_id',\n    'robotis_Practice_ai_camera_if_detected_id_type',\n\n    // AI Camera 제어\n    'robotis_Practice_ai_camera_set_mode',\n    'robotis_Practice_ai_camera_print_custom_text',\n    'robotis_Practice_ai_camera_clear_custom_text',\n];\n\nfunction sleepBlocking(milliseconds) {\n    const start = new Date().getTime();\n    while (true) {\n        if (new Date().getTime() - start > milliseconds) {\n            break;\n        }\n    }\n}\n\nEntry.Robotis_rb_P_Assembly.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                // 주행 제어\n                robotis_Practice_drive_simple: \"속도 %1 (으)로 %2 하기 %3\",\n                robotis_Practice_drive_advanced: \"왼쪽바퀴 %1 속도로 %2 하기, 오른쪽바퀴 %3 속도로 %4 하기 %5\",\n                robotis_Practice_drive_seperate: \"%1 바퀴 %2 속도로 %3 으로 회전하기 %4\",\n                robotis_Practice_drive_angle: \"%1 바퀴 %2 도만큼 %3 으로 회전하기 %4\",\n                robotis_Practice_go_distance:\"%1 cm %2 하기 %3\",\n                robotis_Practice_turn_angle:\"%1 도 %2 하기%3\",\n                robotis_Practice_follow_line: \"%1 속도로 라인 따라가기 %2\",\n                robotis_Practice_stop_at_cross: \"교차로 %1 에서 멈추기 %2\",\n                robotis_Practice_turn_at_line: \"교차로에서 %1 하고 멈추기 %2\",\n                robotis_Practice_drive_stop: \"정지하기 %1\",\n\n                robotis_Practice_securitybot_init: \"보안 로봇 초기화 %1\",\n                robotis_Practice_securitybot_hi: \"보안 로봇 긍정적 행동하기 %1\",\n                robotis_Practice_securitybot_alert: \"보안 로봇 부정적 행동하기 %1\",\n\n                robotis_Practice_petbot_happy: \"반려 로봇 행복한 행동하기 %1\",\n                robotis_Practice_petbot_sad: \"반려 로봇 화난 행동하기 %1\",\n\n                robotis_Practice_farmbot_init: \"스마트팜 로봇 초기화 %1\",\n                robotis_Practice_farmbot_seek: \"농작물 찾기 %1\",\n                robotis_Practice_farmbot_plant_type: \"%1 농작물이면\",\n                robotis_Practice_farmbot_harvest_or_not_and_go: \"농작물 %1 돌아가기 %2\",\n\n\n                // 값 블록\n                robotis_Practice_cm_ir_value: \"%1 적외선센서 값\",\n                robotis_Practice_cm_ir_compare: \"%1 적외선센서 값이 %2 보다 %3\",\n                //robotis_Practice_detectFrontObj: \"%1의 %2에 물체가 있으면\",  // 거리센서도 사용할 경우\n                robotis_Practice_detectFrontObj: \"적외선센서의 %2에 물체가 있으면\",  // 거리센서를 사용하지 않을 경우\n                robotis_Practice_cm_btn_value: \"제어기의 %1 버튼을 클릭했을때\",\n                robotis_Practice_cm_joystick_value: \"제어기의 노랑 조이스틱 위치가 %1 이면\",\n                robotis_Practice_mic: \"소리의 크기(dB)\",\n                robotis_Practice_detectSound_compare: \"소리가 제어기의 %1에서 들리면\",\n                robotis_Practice_imu: \"%1축의 %2 값\",\n                robotis_Practice_roll_pitch: \"제어기의 %1 값\",\n                robotis_Practice_line_cross_compare: \"교차로 모양이 %1이면\",\n                robotis_Practice_distance_value: \"%1 값\",\n                robotis_Practice_distance_compare: \"%1 값이 %2보다 %3\",\n                robotis_Practice_environment_value: \"%1 값\",\n                robotis_Practice_environment_compare: \"%1 값이 %2보다 %3\",\n                robotis_Practice_dxl_value: \"%1의 각도값\",\n\n\n                // 소리\n                robotis_Practice_scale_simple: \"옥타브%1 로 %2 음을 %3로 연주하기 %4\",\n                robotis_Practice_scale_advanced: \"옥타브%1 로 %2 음을 %3박자 연주하기 %4\",\n                robotis_Practice_rest_simple: \"%1 %2\",\n                robotis_Practice_rest_advanced: \"쉼표 %1 박자 %2\",\n                robotis_Practice_beat_per_minute: \"연주 빠르기를 %1 (으)로 정하기 %2\",\n                robotis_Practice_Hello: \"로봇 %1 말하기 %2\",\n                robotis_Practice_effectSound: \"효과음 %1 재생하기 %2\",\n                robotis_Practice_record: \"소리 %1번에 녹음하기 %2\",\n                robotis_Practice_playRecord: \"소리 %1번을 재생하기 %2\",\n\n                \n                // LCD 제어\n                robotis_Practice_screen: \"화면 표정을 %1 %2 (으)로 정하기 %3\",\n                robotis_Practice_anim_screen: \"화면 애니메이션을 %1 %2 (으)로 정하기 %3\",\n                robotis_Practice_icon_screen_food_plant: \"화면에 [음식/식물]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_Practice_icon_screen_animal_human: \"화면에 [동물/사람]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_Practice_icon_screen_object_tool: \"화면에 [물건/도구]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_Practice_icon_screen_vehicle_number: \"화면에 [탈것/숫자]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_Practice_icon_screen_game_character: \"화면에 [게임/캐릭터]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5\",\n                robotis_Practice_text_screen: \"화면에 %1를 (%2, %3)위치에 %4 로 %5으로 표시 %6\",\n                robotis_Practice_pixel: \"화면 (%1, %2)위치에 %3 색 점 표시 %4\",\n                robotis_Practice_text_screen_redraw: \"화면에 %1를 (%2, %3)위치에 %4으로 새로 표시 %5\",\n                robotis_Practice_LCDColor: \"화면 색상을 %1 (으)로 정하기 %2\",\n                robotis_Practice_LCD_Flash: \"화면을 %1과 %2으로 %3초 간격으로 깜박이기 %4\",\n                robotis_Practice_LCDBright: \"화면 밝기를 %1 (으)로 정하기 %2\",\n                \n                \n                // LED 제어\n                robotis_Practice_cm_led: \"로봇 %1 LED %2 %3\",\n                robotis_Practice_cm_led_pattern: \"LED %1 %2로 깜박이기 %3\",\n                \n\n                // DXL 제어\n                robotis_Practice_dxl_set_mode: \"%1 모터 %2 모드로 설정 %3\",\n                robotis_Practice_dxl_each_control: \"%1 모터 %2°로 %3 초 동안 움직이기 %4\",\n                robotis_Practice_dxl_set_position: \"%1 모터 %2 속도로 %3° 위치로 회전 %4\",\n                robotis_Practice_dxl_set_rotate: \"%1 모터 %2 속도로 %3 으로 %4 %5\",\n                robotis_Practice_dxl_set_multiturn_round: \"%1 모터 %2 속도로 %3 바퀴 %4으로 회전 %5\",\n                \n\n                \n                // 인공지능 카메라 값 블록\n                robotis_Practice_ai_camera_connection_status: \"인공지능 카메라가 %1이면\",\n                robotis_Practice_ai_camera_if_detected: \"인공지능 카메라에 %1 이/가 표시되면\",\n\n                robotis_Practice_ai_camera_block_value_closest_to_center: \"인공지능 카메라가 인식한 %1의 %2\",\n                robotis_Practice_ai_camera_arrow_value_closest_to_center: \"인공지능 카메라가 인식한 화살표의 %1\",\n                robotis_Practice_ai_camera_number_of_learned_id: \"인공지능 카메라가 학습한 클래스의 갯수\",\n                robotis_Practice_ai_camera_block_value_of_id: \"인공지능 카메라가 감지한 클래스가 %1인 %2의 %3\",\n                robotis_Practice_ai_camera_arrow_value_of_id: \"인공지능 카메라가 감지한 클래스가 %1인 화살표의 %2\",\n\n                robotis_Practice_ai_camera_if_learned_id: \"인공지능 카메라가 클래스가 %1인 데이터를 학습하였으면\",\n                robotis_Practice_ai_camera_if_detected_id_type: \"인공지능 카메라가 클래스가 %1인 %2데이터를 인식하였으면\",\n                \n\n                // 인공지능 카메라 제어\n                robotis_Practice_ai_camera_set_mode: \"인공지능 카메라의 작동방식을 %1(으)로 설정 %2\",\n                robotis_Practice_ai_camera_print_custom_text: \"인공지능 카메라의 화면 위치 (%1,%2)에 %3를 보여주기%4\",\n                robotis_Practice_ai_camera_clear_custom_text: \"인공지능 카메라의 화면의 글 지우기 %1\",\n            },\n            Helper: {\n                // 주행 제어\n                robotis_Practice_drive_simple: \"로봇아이를 지정한 속도와 방향으로 주행\\n속도범위: -100 ~ 100\\n속도단위: %\",\n                robotis_Practice_drive_advanced: \"로봇아이의 좌,우 바퀴를 각각 지정한 속도와 방향으로 회전\\n속도범위: -100 ~ 100\\n속도단위: %\",\n                robotis_Practice_drive_seperate: \"로봇아이의 지정한 바퀴를 지정한 속도와 방향으로 회전\\n속도범위: -100 ~ 100\\n속도단위: %\",\n                robotis_Practice_drive_angle: \"로봇아이의 두 바퀴를 지정한 방향과 지정한 각도만큼 회전\\n각도범위: -5760 ~ 5760\\n각도단위: 도\",\n                robotis_Practice_go_distance: \"지정거리만큼 앞 또는 뒤로 이동\\n거리범위: -1000 ~ 1000\\n거리단위: mm\",\n                robotis_Practice_turn_angle: \"지정한 각도와 방향으로 제자리회전\\n각도범위: -360 ~ 360\\n각도단위: 도\",\n                robotis_Practice_follow_line: \"지정한 수준의 속도로 라인 따라가기 시작\",\n                robotis_Practice_stop_at_cross: \"지정한 교차로에서 멈추기\",\n                robotis_Practice_turn_at_line: \"교차로에서 지정한 회전을 하고 멈추기\",\n                robotis_Practice_drive_stop: \"로봇아이 정지하기\",\n\n                robotis_robotai_lite_securitybot_init:\n                    '보안 로봇을 초기화합니다. 두 모터를 관절모드로 설정하고 카메라를 얼굴인식모드로 설정합니다.',\n                robotis_robotai_lite_securitybot_hi:\n                    '보안 로봇이 \"사용자를 확인하였습니다.\" 문구를 화면에 표시하고 팔을 위아래로 흔듭니다.',\n                robotis_robotai_lite_securitybot_alert:\n                    '보안 로봇이 \"사용자가 아닙니다.\" 문구를 화면에 표시하고 몸을 좌우로 흔듭니다.',\n\n                robotis_robotai_lite_petbot_happy:\n                    '반려 로봇이 웃는 표정을 하고 \"즐거워요\" 라고 말을 하면서 제자리에서 한바퀴 회전합니다.',\n                robotis_robotai_lite_petbot_sad:\n                    '반려 로봇이 화난 표정을 하고 \"무서워요\" 라고 말을 하면서 뒤로 5cm 후진합니다.',\n\n                robotis_robotai_lite_farmbot_init:\n                    '스마트팜 로봇을 초기화 합니다. 1번 모터를 시작위치로 이동시키고 카메라를 색상인식모드로 설정합니다.',\n                robotis_robotai_lite_farmbot_seek: '농작물을 발견하면 가까이로 이동합니다.',\n                robotis_robotai_lite_farmbot_plant_type: '농작물의 유형을 판단합니다.',\n                robotis_robotai_lite_farmbot_harvest_or_not_and_go:\n                    '농작물을 수확하거나 수확하지 않습니다. 그 이후 우측으로 회전합니다.',\n\n                // 값 블록\n                robotis_Practice_cm_ir_value: \"지정한 번호의 IR 센서 값(범위: 0 ~ 200)\",\n                robotis_Practice_cm_ir_compare: \"지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_detectFrontObj: \"지정한 방향의 적외선센서에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_cm_btn_value: \"지정한 버튼이 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_cm_joystick_value: \"조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_mic: \"마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.\",\n                robotis_Practice_detectSound_compare: \"소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_imu: \"지정한 축의 지정한 가속도센서/자이로센서의 값\\n범위: -100 ~ 100\",\n                robotis_Practice_roll_pitch: \"roll/pitch 값\\nroll: -180° ~ 180°, pitch: -90° ~ 90°\",\n                robotis_Practice_distance_value: \"지정한 센서값\\n거리범위: 0 ~ 1000mm\\n조도범위: 0 ~ 100%\\n버튼센서: 0(눌리지 않음) / 1(눌림)\",\n                robotis_Practice_distance_compare: \"지정한 센서값의 지정한 수식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_environment_value: \"지정한 센서값\\n움직임센서: 0(움직임 없음) / 1(움직임 있음)\\n밝기범위: 0 ~ 100%\\n온도범위: -25°C ~ 85°C\",\n                robotis_Practice_environment_compare: \"지정한 센서값의 지정한 수식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_line_cross_compare: \"지정한 교차로 모양이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_dxl_value: \"지정한 모터의 위치 각도값\\n범위: -180° ~ 180°\",\n\n\n                // 소리\n                robotis_Practice_scale_simple: \"지정한 옥타브, 음계, 음표로 연주하기\",\n                robotis_Practice_scale_advanced: \"지정한 옥타브, 음계, 박자로 연주하기\",\n                robotis_Practice_rest_simple: \"지정한 쉼표 쉬기\",\n                robotis_Practice_rest_advanced: \"지정한 박자 쉬기\",\n                robotis_Practice_beat_per_minute: \"연주 빠르기를 지정하기 (BPM)\\n범위: 10 ~ 600\",\n                robotis_Practice_Hello: \"로봇이 지정한 말소리를 재생하기\",\n                robotis_Practice_effectSound: \"로봇이 지정한 효과음을 재생하기\",\n                robotis_Practice_record: \"지정번호 보관함에 녹음하여 저장하기\",\n                robotis_Practice_playRecord: \"지정번호 보관함의 녹음음성을 재생하기\",\n\n                \n                // LCD 제어\n                robotis_Practice_screen: \"제어기 화면배경의 캐릭터와 표정을 설정\",\n                robotis_Practice_anim_screen: \"제어기 화면 애니메이션의 캐릭터와 표정을 설정\",\n                robotis_Practice_icon_screen_food_plant: \"화면에 [음식/식물]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_Practice_icon_screen_animal_human: \"화면에 [동물/사람]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_Practice_icon_screen_object_tool: \"화면에 [물건/도구]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_Practice_icon_screen_vehicle_number: \"화면에 [탈것/숫자]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_Practice_icon_screen_game_character: \"화면에 [게임/캐릭터]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_Practice_text_screen: \"화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\",\n                robotis_Practice_text_screen_redraw: \"화면에 지정한 문구를 새롭게(문구의 배경 지움) 표시할 위치와 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200\",\n                robotis_Practice_pixel: \"화면에 표시할 점의 위치와 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\",\n                robotis_Practice_LCDBright: \"화면 밝기를 설정\\n밝기범위: 1% ~ 100%\",\n                robotis_Practice_LCDColor: \"화면 색상을 설정\",\n                robotis_Practice_LCD_Flash: \"화면이 깜박이는 2가지 색상과 간격을 지정\",\n\n                // LED 제어\n                robotis_Practice_cm_led: \"제어기의 지정한 LED를 켜거나 끄기\",\n                robotis_Practice_cm_led_pattern: \"제어기의 LED의 깜박임 패턴 설정\",\n                \n                // DXL 제어\n                robotis_Practice_dxl_set_mode: \"지정한 ID의 모터의 동작모드를 설정\",\n                robotis_Practice_dxl_each_control: \"지정한 ID의 모터가 지정한 각도로 지정한 시간(초)동안 움직이도록 설정\",\n                robotis_Practice_dxl_set_position: \"지정한 ID의 모터가 지정한 속도로 지정한 각도로 움직이도록 설정\",\n                robotis_Practice_dxl_set_rotate: \"지정한 ID의 모터의 회전 속도와 방향을 설정\",\n                robotis_Practice_dxl_set_multiturn_round: \"지정한 ID의 모터가 지정한 속도와 방향으로 지정한 바퀴만큼 회전\",\n                \n                // AI Camera 값 블록\n                robotis_Practice_ai_camera_connection_status: \"인공지능 카메라가 연결된 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_ai_camera_if_detected: \"인공지능 카메라의 LCD화면에 선택한 기호(사각형/화살표)가 표시되면 '참', 아니면 '거짓'으로 판단합니다.\",\n\n                robotis_Practice_ai_camera_block_value_closest_to_center: \"인공지능 카메라 화면 중앙과 가장 가까운 사각형의 X좌표/Y좌표/너비/높이/클래스\",\n                robotis_Practice_ai_camera_arrow_value_closest_to_center: \"인공지능 카메라 화면 중앙과 가장 가까운 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표/클래스\",\n                robotis_Practice_ai_camera_number_of_learned_id: \"인공지능 카메라가 학습한 번호의 갯수\",\n                robotis_Practice_ai_camera_block_value_of_id: \"인공지능 카메라가 감지한 사각형중 지정한 번호의 사각형의 X좌표/Y좌표/너비/높이\",\n                robotis_Practice_ai_camera_arrow_value_of_id: \"인공지능 카메라가 감지한 화살표중 지정한 번호의 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표\",\n\n                robotis_Practice_ai_camera_if_learned_id: \"인공지능 카메라가 지정한 번호인 데이터를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                robotis_Practice_ai_camera_if_detected_id_type: \"인공지능 카메라가 지정한 번호인 지정한 데이터(사각형/화살표)를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.\",\n\n                // 인공지능 카메라 제어\n                robotis_Practice_ai_camera_set_mode: \"인공지능 카메라의 모드를 설정\",\n                robotis_Practice_ai_camera_print_custom_text: \"인공지능 카메라 화면의 지정한 위치에 지정한 문구 출력\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\",\n                robotis_Practice_ai_camera_clear_custom_text: \"인공지능 카메라 화면에 표시한 모든 문구 지우기\",\n            },\n            Blocks: {\n                robotis_red: \"빨강\",\n                robotis_orange: \"주황\",\n                robotis_yellow: \"노랑\",\n                robotis_green: \"초록\",\n                robotis_blue: \"파랑\",\n                robotis_brown: \"갈색\",\n                robotis_black: \"검정\",\n                robotis_white: \"흰색\",\n                robotis_left: \"왼쪽\",\n                robotis_center: \"중앙\",\n                robotis_right: \"오른쪽\",\n                robotis_both: \"양쪽\",\n                robotis_rgee: \"알쥐\",\n                robotis_rla: \"알라\",\n                robotis_kkokdu: \"꼭두\",\n                robotis_korean1: \"안녕하세요\",\n                robotis_korean2: \"반가워요\",\n                robotis_korean3: \"알겠어요\",\n                robotis_korean4: \"아니에요\",\n                robotis_korean5: \"모르겠어요\",\n                robotis_korean6: \"좋아요\",\n                robotis_korean7: \"싫어요\",\n                robotis_korean8: \"이름을말하세요\",\n                robotis_korean9: \"무엇을도와줄까?\",\n                robotis_korean10: \"잘했어\",\n                robotis_korean11: \"괜찮아\",\n                robotis_korean12: \"다시해보자\",\n                robotis_korean13: \"고마워\",\n                robotis_korean14: \"다시말해줄래?\",\n                robotis_korean15: \"최고야!\",\n                robotis_korean16: \"신나요\",\n                robotis_korean17: \"즐거워요\",\n                robotis_korean18: \"미안해요\",\n                robotis_korean19: \"화나요\",\n                robotis_korean20: \"부끄러워요\",\n                robotis_korean21: \"무서워요\",\n                robotis_korean22: \"속상해요\",\n                robotis_korean23: \"사랑해요\",\n                robotis_korean24: \"예뻐요\",\n                robotis_korean25: \"신기해요\",\n                robotis_korean26: \"초조해요\",\n                robotis_korean27: \"앞으로가자\",\n                robotis_korean28: \"뒤로가자\",\n                robotis_korean29: \"일어나자\",\n                robotis_korean30: \"넘어졌네?\",\n                robotis_korean31: \"오예\",\n                robotis_korean32: \"아싸\",\n                robotis_korean33: \"어머\",\n                robotis_korean34: \"이런\",\n                robotis_korean35: \"오호\",\n                robotis_korean36: \"하하하\",\n                robotis_korean37: \"호호호\",\n                robotis_korean38: \"졸려\",\n                robotis_korean39: \"자장가를들려줘\",\n                robotis_korean40: \"안녕\",\n                robotis_korean41: \"배고프다\",\n                robotis_korean42: \"도토리땡긴다\",\n                robotis_korean43: \"아.씻고싶어\",\n                robotis_korean44: \"비누목욕시간이야\",\n                robotis_korean45: \"심심한데\",\n                robotis_korean46: \"간식먹을까\",\n                robotis_korean47: \"아파요\",\n                robotis_korean48: \"약은없나요?\",\n                robotis_korean49: \"어디로가야하지?\",\n                robotis_korean50: \"와아도착이다\",\n                robotis_korean51: \"왼쪽으로가자\",\n                robotis_korean52: \"오른쪽으로가자\",\n                robotis_korean53: \"깜짝이야\",\n                robotis_korean54: \"찾았다\",\n                robotis_korean55: \"여긴없네\",\n                robotis_korean56: \"혹시나불렀어?\",\n                robotis_korean57: \"내려주세요\",\n                robotis_korean58: \"앗\",\n                robotis_korean59: \"힝\",\n                robotis_korean60: \"이익\",\n                robotis_dog: \"개\",\n                robotis_frog: \"개구리\",\n                robotis_cat: \"고양이\",\n                robotis_chicken: \"닭\",\n                robotis_tiger: \"호랑이\",\n                robotis_mouse: \"쥐\",\n                robotis_ambul: \"앰뷸런스\",\n                robotis_Horn: \"경적(빵빵)\",\n                robotis_siren: \"사이렌(경찰차)\",\n                robotis_whistle: \"호루라기\",\n                robotis_gun: \"총소리\",\n                robotis_clap: \"박수소리\",\n                robotis_melody1: \"멜로디1\",\n                robotis_melody2: \"멜로디2\",\n                robotis_melody3: \"멜로디3\",\n                robotis_melody4: \"멜로디4\",\n                robotis_forward: \"앞으로\",\n                robotis_backward: \"뒤로\",\n                robotis_acceleration: \"가속도\",\n                robotis_gyro: \"자이로\",\n                robotis_run: \"실행\",\n                robotis_cancel: \"취소\",\n                robotis_push: \"눌림\",\n                robotis_notPush: \"안눌림\",\n                robotis_play: \"연주\",\n                robotis_rest: \"쉼표\",\n                robotis_face01: \"와하하\",\n                robotis_face02: \"싱글벙글\",\n                robotis_face03: \"큭큭큭\",\n                robotis_face04: \"냠냠\",\n                robotis_face05: \"겁먹음\",\n                robotis_face06: \"답답\",\n                robotis_face07: \"갸우뚱\",\n                robotis_face08: \"어벙벙\",\n                robotis_face09: \"고함\",\n                robotis_face10: \"화남\",\n                robotis_face11: \"킁킁(왼쪽)\",\n                robotis_face12: \"킁킁(오른쪽)\",\n                robotis_face13: \"킁킁(아래)\",\n                robotis_face14: \"안심\",\n                robotis_face15: \"기절\",\n                robotis_face16: \"헤롱헤롱\",\n                robotis_face17: \"하품\",\n                robotis_face18: \"졸림\",\n                robotis_face19: \"잠듦\",\n                robotis_face20: \"마음앓이\",\n                robotis_face21: \"폭풍눈물\",\n                robotis_face22: \"목욕\",\n                robotis_face23: \"햐트뿅뿅\",\n\n                robotis_flashing1: \"깜박임1\",\n                robotis_flashing2: \"깜박임2\",\n                robotis_flashing3: \"깜박임3\",\n                robotis_flashing4: \"깜박임4\",\n                robotis_flashing5: \"깜박임5\",\n                robotis_flashing6: \"깜박임6\",\n                robotis_flashing7: \"깜박임7\",\n                robotis_flashing8: \"깜박임8\",\n                robotis_flashing9: \"깜박임9\",\n                robotis_moveF: \"전진\",\n                robotis_moveB: \"후진\",\n                robotis_moveL: \"좌회전\",\n                robotis_moveR: \"우회전\",\n                robotis_moveU: \"U턴\",\n                robotis_moveL_in_place: \"제자리 좌회전\",\n                robotis_moveR_in_place: \"제자리 우회전\",\n                robotis_moveU_in_place: \"제자리 U턴\",\n                robotis_moveRG1: \"일어서기\",\n                robotis_moveRG2: \"앉기\",\n                robotis_moveRG3: \"발버둥\",\n                robotis_moveRG4: \"발들기\",\n                robotis_fast: '빠른',\n                robotis_normal: '보통',\n                robotis_slow: '느린',\n                robotis_stop: \"정지\",\n                robotis_roll: \"좌우 회전각 (roll)\",\n                robotis_pitch: \"앞뒤 회전각 (pitch)\",\n                robotis_direction_forward: \"전진방향\",\n                robotis_direction_backward: \"후진방향\",\n                robotis_stMotion1: \"기본자세\",\n                robotis_stMotion2: \"전진\",\n                robotis_stMotion3: \"우전진\",\n                robotis_stMotion4: \"좌전진\",\n                robotis_stMotion5: \"후진\",\n                robotis_stMotion6: \"오른쪽으로\",\n                robotis_stMotion7: \"왼쪽으로\",\n                robotis_stMotion8: \"우회전\",\n                robotis_stMotion9: \"좌회전\",\n                robotis_spMotion1: \"오른손 들기\",\n                robotis_spMotion2: \"오른손 내리기\",\n                robotis_spMotion3: \"왼손 들기\",\n                robotis_spMotion4: \"왼손 내리기\",\n                robotis_spMotion5: \"양손 들기\",\n                robotis_spMotion6: \"양손 내리기\",\n                robotis_spMotion7: \"뒤로 넘어지기\",\n                robotis_spMotion8: \"앞으로 넘어지기\",\n                robotis_spMotion9: \"앞으로 일어서기\",\n                robotis_spMotion10: \"뒤로 일어서기\",\n                robotis_spMotion11: \"방어\",\n                robotis_spMotion12: \"공격1\",\n                robotis_spMotion13: \"공격2\",\n                robotis_spMotion14: \"공격3\",\n                robotis_spMotion15: \"공격4\",\n                robotis_screen1: \"가위\",\n                robotis_screen2: \"바위\",\n                robotis_screen3: \"보\",\n                robotis_icon_food_plant_1: \"우유\",\n                robotis_icon_food_plant_2: \"나무\",\n                robotis_icon_food_plant_3: \"스프\",\n                robotis_icon_food_plant_4: \"케익\",\n                robotis_icon_food_plant_5: \"물\",\n                robotis_icon_food_plant_6: \"주스\",\n                robotis_icon_food_plant_7: \"당근\",\n                robotis_icon_food_plant_8: \"사과\",\n                robotis_icon_food_plant_9: \"오렌지\",\n                robotis_icon_food_plant_10: \"고기\",\n                robotis_icon_food_plant_11: \"화분\",\n                robotis_icon_food_plant_12: \"장미\",\n                robotis_icon_food_plant_13: \"포도\",\n                robotis_icon_food_plant_14: \"감자\",\n                robotis_icon_food_plant_15: \"사탕\",\n                robotis_icon_food_plant_16: \"치즈\",\n                robotis_icon_food_plant_17: \"식빵\",\n                robotis_icon_food_plant_18: \"꽃들\",\n                robotis_icon_food_plant_19: \"커피\",\n                robotis_icon_food_plant_20: \"튤립\",\n                robotis_icon_food_plant_21: \"바나나\",\n                robotis_icon_food_plant_22: \"과일들\",\n                robotis_icon_food_plant_23: \"햄버거\",\n                robotis_icon_food_plant_24: \"피자\",\n                robotis_icon_animal_human_1: \"시바견\",\n                robotis_icon_animal_human_2: \"강아지\",\n                robotis_icon_animal_human_3: \"곰\",\n                robotis_icon_animal_human_4: \"새\",\n                robotis_icon_animal_human_5: \"오리\",\n                robotis_icon_animal_human_6: \"사자\",\n                robotis_icon_animal_human_7: \"호랑이\",\n                robotis_icon_animal_human_8: \"말\",\n                robotis_icon_animal_human_9: \"양\",\n                robotis_icon_animal_human_10: \"상어1(왼쪽)\",\n                robotis_icon_animal_human_11: \"상어1(오른쪽)\",\n                robotis_icon_animal_human_12: \"상어2(왼쪽)\",\n                robotis_icon_animal_human_13: \"상어2(오른쪽)\",\n                robotis_icon_animal_human_14: \"물고기1\",\n                robotis_icon_animal_human_15: \"물고기2\",\n                robotis_icon_animal_human_16: \"물고기3\",\n                robotis_icon_animal_human_17: \"문어\",\n                robotis_icon_animal_human_18: \"원숭이\",\n                robotis_icon_animal_human_19: \"닭\",\n                robotis_icon_animal_human_20: \"돼지\",\n                robotis_icon_animal_human_21: \"사람(살찐)\",\n                robotis_icon_animal_human_22: \"사람(수영복)\",\n                robotis_icon_animal_human_23: \"아기\",\n                robotis_icon_animal_human_24: \"사람(달리는)\",\n                robotis_icon_animal_human_25: \"사람(노래하는)\",\n                robotis_icon_animal_human_26: \"사람(앉은)\",\n                robotis_icon_animal_human_27: \"사람(화난)\",\n                robotis_icon_animal_human_28: \"사람(만세)\",\n                robotis_icon_animal_human_29: \"왕\",\n                robotis_icon_animal_human_30: \"왕자\",\n                robotis_icon_animal_human_31: \"공주\",\n                robotis_icon_animal_human_32: \"요리사\",\n                robotis_icon_animal_human_33: \"의사\",\n                robotis_icon_animal_human_34: \"간호사\",\n                robotis_icon_object_tool_1: \"가방\",\n                robotis_icon_object_tool_2: \"상자\",\n                robotis_icon_object_tool_3: \"머그컵\",\n                robotis_icon_object_tool_4: \"모자(중절모)\",\n                robotis_icon_object_tool_5: \"모자(캡모자)\",\n                robotis_icon_object_tool_6: \"열쇠\",\n                robotis_icon_object_tool_7: \"장난감\",\n                robotis_icon_object_tool_8: \"책\",\n                robotis_icon_object_tool_9: \"곰인형\",\n                robotis_icon_object_tool_10: \"드럼\",\n                robotis_icon_object_tool_11: \"메모장\",\n                robotis_icon_object_tool_12: \"볼펜\",\n                robotis_icon_object_tool_13: \"책상\",\n                robotis_icon_object_tool_14: \"테이블\",\n                robotis_icon_object_tool_15: \"의자\",\n                robotis_icon_object_tool_16: \"침대\",\n                robotis_icon_object_tool_17: \"텐트\",\n                robotis_icon_object_tool_18: \"접시\",\n                robotis_icon_object_tool_19: \"축구공\",\n                robotis_icon_object_tool_20: \"종\",\n                robotis_icon_object_tool_21: \"손목시계\",\n                robotis_icon_object_tool_22: \"신발\",\n                robotis_icon_object_tool_23: \"전등\",\n                robotis_icon_object_tool_24: \"라디오\",\n                robotis_icon_object_tool_25: \"지폐\",\n                robotis_icon_object_tool_26: \"자\",\n                robotis_icon_object_tool_27: \"카메라\",\n                robotis_icon_object_tool_28: \"스푼\",\n                robotis_icon_object_tool_29: \"건반\",\n                robotis_icon_object_tool_30: \"달력\",\n                robotis_icon_object_tool_31: \"칼\",\n                robotis_icon_object_tool_32: \"풍선\",\n                robotis_icon_object_tool_33: \"물통\",\n                robotis_icon_object_tool_34: \"나무막대(세로)\",\n                robotis_icon_object_tool_35: \"나무막대(가로)\",\n                robotis_icon_object_tool_36: \"낚시바늘\",\n                robotis_icon_vehicle_number_1: \"자동차\",\n                robotis_icon_vehicle_number_2: \"버스\",\n                robotis_icon_vehicle_number_3: \"트럭\",\n                robotis_icon_vehicle_number_4: \"지프\",\n                robotis_icon_vehicle_number_5: \"자전거\",\n                robotis_icon_vehicle_number_6: \"전철\",\n                robotis_icon_vehicle_number_7: \"기차\",\n                robotis_icon_vehicle_number_8: \"비행기\",\n                robotis_icon_vehicle_number_9: \"전투기(세로)\",\n                robotis_icon_vehicle_number_10: \"전투기(가로)\",\n                robotis_icon_vehicle_number_11: \"로켓\",\n                robotis_icon_vehicle_number_12: \"어선\",\n                robotis_icon_vehicle_number_13: \"여객선\",\n                robotis_icon_vehicle_number_14: \"잠수함(왼쪽)\",\n                robotis_icon_vehicle_number_15: \"잠수함(오른쪽)\",\n                robotis_icon_vehicle_number_16: \"비행기(왼쪽)\",\n                robotis_icon_vehicle_number_17: \"비행기(오른쪽)\",\n                robotis_icon_vehicle_number_18: \"비행기(윗쪽)\",\n                robotis_icon_vehicle_number_19: \"우주선(왼쪽)\",\n                robotis_icon_vehicle_number_20: \"우주선(오른쪽)\",\n                robotis_icon_vehicle_number_21: \"우주선(윗쪽)\",\n                robotis_icon_vehicle_number_22: \"주사위(1)\",\n                robotis_icon_vehicle_number_23: \"주사위(2)\",\n                robotis_icon_vehicle_number_24: \"주사위(3)\",\n                robotis_icon_vehicle_number_25: \"주사위(4)\",\n                robotis_icon_vehicle_number_26: \"주사위(5)\",\n                robotis_icon_vehicle_number_27: \"주사위(6)\",\n                robotis_icon_vehicle_number_28: \"0\",\n                robotis_icon_vehicle_number_29: \"1\",\n                robotis_icon_vehicle_number_30: \"2\",\n                robotis_icon_vehicle_number_31: \"3\",\n                robotis_icon_vehicle_number_32: \"4\",\n                robotis_icon_vehicle_number_33: \"5\",\n                robotis_icon_vehicle_number_34: \"6\",\n                robotis_icon_vehicle_number_35: \"7\",\n                robotis_icon_vehicle_number_36: \"8\",\n                robotis_icon_vehicle_number_37: \"9\",\n                robotis_icon_vehicle_number_38: \"10\",\n                robotis_icon_game_character_1: '알쥐(정면)',\n                robotis_icon_game_character_2: '알쥐(왼쪽)',\n                robotis_icon_game_character_3: '알쥐(오른쪽)',\n                robotis_icon_game_character_4: '알라(정면)',\n                robotis_icon_game_character_5: '알라(왼쪽))',\n                robotis_icon_game_character_6: '알라(오른쪽)',\n                robotis_icon_game_character_7: '유령',\n                robotis_icon_game_character_8: '괴물',\n                robotis_icon_game_character_9: '바이러스',\n                robotis_icon_game_character_10: '세균',\n                robotis_icon_game_character_11: '나는 알쥐(왼쪽)',\n                robotis_icon_game_character_12: '나는 알쥐(오른쪽)',\n                robotis_icon_game_character_13: '나는 알쥐(정면)',\n                robotis_icon_game_character_14: '메달',\n                robotis_icon_game_character_15: '돈(G)',\n                robotis_icon_game_character_16: '돈($)',\n                robotis_icon_game_character_17: '하트',\n                robotis_icon_game_character_18: '폭탄',\n                robotis_icon_game_character_19: '불',\n                robotis_icon_game_character_20: '구름1',\n                robotis_icon_game_character_21: '구름2',\n                robotis_icon_game_character_22: '포탄1',\n                robotis_icon_game_character_23: '포탄2',\n                robotis_icon_game_character_24: '대포(수평)',\n                robotis_icon_game_character_25: '대포(수직)',\n                robotis_icon_game_character_26: '레이저(수직)',\n                robotis_icon_game_character_27: '게이저(수평)',\n                robotis_icon_game_character_28: '화살(수평)',\n                robotis_icon_game_character_29: '화살(수직)',\n                robotis_icon_game_character_30: '미사일(U)',\n                robotis_icon_game_character_31: '미사일(D)',\n                robotis_icon_game_character_32: '미사일(L)',\n                robotis_icon_game_character_33: '미사일(R)',\n                robotis_icon_game_character_34: '낙하산',\n                robotis_icon_game_character_35: '폭발1',\n                robotis_icon_game_character_36: '폭발2',\n                robotis_icon_game_character_37: '조준경',\n                robotis_icon_game_character_38: '가위',\n                robotis_icon_game_character_39: '바위',\n                robotis_icon_game_character_40: '보',\n                robotis_icon_game_character_41: '걷는 사람1',\n                robotis_icon_game_character_42: '걷는 사람2',\n                robotis_icon_game_character_43: '뛰는 사람1',\n                robotis_icon_game_character_44: '뛰는 사람2',\n                robotis_clockwise: \"시계방향\",\n                robotis_counterclockwise: \"반시계방향\",\n                robotis_up: \"들기\",\n                robotis_down: \"내리기\",\n                robotis_if_greater: \"크면\",\n                robotis_if_smaller: \"작으면\",\n                robotis_if_equal: \"같으면\",\n                robotis_front_right: \"앞 오른쪽\",\n                robotis_front_left: \"앞 왼쪽\",\n                robotis_bottom_right: \"아래 오른쪽\",\n                robotis_bottom_left: \"아래 왼쪽\",\n                robotis_side_right: \"우측\",\n                robotis_side_left: \"좌측\",\n                robotis_front_ir_sensor: \"적외선센서\",\n                robotis_distance_sensor: \"거리센서\",\n                robotis_front: \"앞\",\n                robotis_right: \"오른쪽\",\n                robotis_left_wheel: \"왼쪽바퀴(52)\",\n                robotis_right_wheel: \"오른쪽바퀴(51)\",\n                // https://namu.wiki/w/%EC%9D%8C%ED%91%9C\n                robotis_beat_sound_8th_note: \"8분음표 (♪)\",\n                robotis_beat_sound_dotted_8th_note: \"점8분음표 (♪.)\",\n                robotis_beat_sound_quarter_note: \"4분음표 (♩)\",\n                robotis_beat_sound_dotted_quarter_note: \"점4분음표 (♩.)\",\n                robotis_beat_sound_half_note: \"2분음표 (𝅗𝅥)\",\n                robotis_beat_sound_dotted_half_note: \"점2분음표 (𝅗𝅥.)\",\n                robotis_beat_sound_whole_note: \"온음표 (𝅝)\",\n                robotis_beat_sound_dotted_note: \"점온음표 (𝅝.)\",\n                robotis_beat_rest_8th_note: \"8분쉼표 (𝄾)\",\n                robotis_beat_rest_dotted_8th_note: \"점8분쉼표 (𝄾.)\",\n                robotis_beat_rest_quarter_note: \"4분쉼표 (𝄽)\",\n                robotis_beat_rest_dotted_quarter_note: \"점4분쉼표 (𝄽.)\",\n                robotis_beat_rest_half_note: \"2분쉼표 (𝄼)\",\n                robotis_beat_rest_dotted_half_note: \"점2분쉼표 (𝄼˙)\",\n                robotis_beat_rest_whole_note: \"온쉼표 (𝄻)\",\n                robotis_beat_rest_dotted_note: \"점온쉼표 (𝄻˙)\",\n                robotis_line_cross_type_0: \"|\",\n                robotis_line_cross_type_1: \" (공백)\",\n                robotis_line_cross_type_5: \"🞣\",\n                robotis_line_cross_type_6: \"⏉\",\n                robotis_line_cross_type_7: \"⊣\",\n                robotis_line_cross_type_8: \"⊢\",\n                robotis_line_cross_type_9: \"⏋\",\n                robotis_line_cross_type_10: \"⎾\",\n                robotis_line_cross_type_11: \"¦\",\n                robotis_line_cross_type_12: \"︙\",\n\n                robotis_dxl_mode_joint: \"관절\",\n                robotis_dxl_mode_wheel: \"바퀴\",\n                robotis_dxl_mode_multi_turn: \"여러바퀴회전\",\n                robotis_dxl_move_rotate: \"회전\",\n                robotis_dxl_move_stop: \"정지\",\n                robotis_dxl_rotate_cw: \"시계방향\",\n                robotis_dxl_rotate_ccw: \"반시계방향\",\n                robotis_dxl_value_angle: \"각도\",\n                robotis_dxl_value_velocity: \"속도\",\n                robotis_dxl_value_moving: \"움직임\",\n\n                robotis_connected: \"연결\",\n                robotis_disconnected: \"없음\",\n                robotis_ai_camera_mode_face_recognition: \"얼굴 인식\",\n                robotis_ai_camera_mode_line_tracking: \"라인 인식\",\n                robotis_ai_camera_mode_color_recognition: \"색상 인식\",\n                robotis_ai_camera_mode_tag_recognition: \"태그 인식\",\n                robotis_ai_camera_mode_object_classification: \"사물 분류\",\n                robotis_ai_camera_mode_expression_recognition: '표정 인식',\n                robotis_ai_camera_target_face: \"얼굴\",\n                robotis_ai_camera_target_expression: \"표정\",\n                robotis_ai_camera_target_object: \"사물\",\n                robotis_ai_camera_target_color: \"색상\",\n                robotis_ai_camera_target_tag: \"태그\",\n                robotis_ai_camera_target_qr: \"QR코드\",\n                robotis_ai_camera_target_block: \"사각형\",\n                robotis_ai_camera_target_arrow: \"화살표\",\n                robotis_ai_camera_center_block_center_x: \"중심 X좌표\",\n                robotis_ai_camera_center_block_center_y: \"중심 Y좌표\",\n                robotis_ai_camera_center_block_width: \"너비\",\n                robotis_ai_camera_center_block_height: \"높이\",\n                robotis_ai_camera_center_leared_id: \"클래스\",\n                robotis_ai_camera_center_arrow_origin_x: \"시작점 X좌표\",\n                robotis_ai_camera_center_arrow_origin_y: \"시작점 Y좌표\",\n                robotis_ai_camera_center_arrow_target_x: \"끝점 X좌표\",\n                robotis_ai_camera_center_arrow_target_y: \"끝점 Y좌표\",\n\n                robotis_plant_ripe: \"빨간색\",\n                robotis_plant_unripe: \"초록색\",\n                robotis_harvest: \"수확하고\",\n                robotis_not_harvest: \"수확하지 않고\",\n            },\n        },\n        en: {\n            template: {\n                // 주행 제어\n                robotis_Practice_drive_simple: \"Move %2 with velocity %1 %3\",\n                robotis_Practice_drive_advanced: \"Left wheel %2 with velocity %1, right wheel %4 with velocity %3 %5\",\n                robotis_Practice_drive_seperate: \"%1 wheel rotate %3 with velocity %2 %4\",\n                robotis_Practice_drive_angle: \"Both wheels rotate %1 degree %2 %3\",\n                robotis_Practice_go_distance: \"Moves %2 %1 cm %3\",\n                robotis_Practice_turn_angle: \"Rotates %1 degree(s) %2 in place %3\",\n                robotis_Practice_follow_line: \"Follow line with %1 speed %2\",\n                robotis_Practice_stop_at_cross: \"Stop at cross %1 %2\",\n                robotis_Practice_turn_at_line: \"%1 at cross and stop %2\",\n                robotis_Practice_drive_stop: \"Stop %1\",\n\n                robotis_Practice_securitybot_init: \"Security robot init %1\",\n                robotis_Practice_securitybot_hi: \"Security robot shake up and down %1\",\n                robotis_Practice_securitybot_alert: \"Security robot shake left and right %1\",\n\n                robotis_Practice_petbot_happy: \"Petbot laugh %1\",\n                robotis_Practice_petbot_sad: \"Petbot angry %1\",\n\n                robotis_Practice_farmbot_init: \"SmartFarm Robot init %1\",\n                robotis_Practice_farmbot_seek: \"Look for plant %1\",\n                robotis_Practice_farmbot_plant_type: \"If it is %1 plant\",\n                robotis_Practice_farmbot_harvest_or_not_and_go: \"%1 the plant and go back %2\",\n        \n        \n        \n                // 값 블록\n                robotis_Practice_cm_ir_value: \"Value of %1 IR Sensor\",\n                robotis_Practice_cm_ir_compare: \"If the number %1 IR sensor value is %3 than %2\",\n                robotis_Practice_detectFrontObj: \"If %2 IR sensor detected an object\",\n                robotis_Practice_cm_btn_value: \"When the controller's %1 button is clicked\",\n                robotis_Practice_cm_joystick_value: \"If the controller's yellow joystick position is %1\",\n                robotis_Practice_mic: \"MIC volume(dB)\",\n                robotis_Practice_detectSound_compare: \"If sound is detected from %1 of the robot\",\n                robotis_Practice_imu: \"%1 axis' %2 value\",\n                robotis_Practice_roll_pitch: \"%1 value of the controller\",\n                robotis_Practice_environment_value: \"%1 value\",\n                robotis_Practice_environment_compare: \"If %1 value is %3 than %2\",\n                robotis_Practice_line_cross_compare: \"If the type of cross is %1\",\n                robotis_Practice_dxl_value: \"The angle of ID %1\",\n\n                // 소리\n                robotis_Practice_scale_simple: \"Play the note %2 as %3 in octave %1 %4\",\n                robotis_Practice_scale_advanced: \"Play the note %2 in octave %1 for %3 beat %4\",\n                robotis_Practice_rest_simple: \"%1 %2\",\n                robotis_Practice_rest_advanced: \"Rest %1 beat %2\",\n                robotis_Practice_beat_per_minute: \"Set playing speed to %1 %2\",\n                robotis_Practice_Hello: \"Robot speaks %1 %2\",\n                robotis_Practice_effectSound: \"Play sound effect %1 %2\",\n                robotis_Practice_record: \"Record to sound slot %1 %2\",\n                robotis_Practice_playRecord: \"Play sound from slot %1 %2\",\n\n                \n                // LCD 제어\n                robotis_Practice_screen: \"Set screen expression to %1 %2 %3\",\n                robotis_Practice_anim_screen: \"Set screen animation to %1 %2 %3\",\n                robotis_Practice_icon_screen_food_plant: \"Display %1 from [Food/Plants] at position (%2, %3) in size %4 %5\",\n                robotis_Practice_icon_screen_animal_human: \"Display %1 from [Animal/Human] at position (%2, %3) in size %4 %5\",\n                robotis_Practice_icon_screen_object_tool: \"Display %1 from [Object/Tool] at position (%2, %3) in size %4 %5\",\n                robotis_Practice_icon_screen_vehicle_number: \"Display %1 from [Vehicle/Number] at position (%2, %3) in size %4 %5\",\n                robotis_Practice_icon_screen_game_character: \"Display %1 from [Game/Character] at position (%2, %3) in size %4 %5\",\n                robotis_Practice_text_screen: \"Display %1 in %5 in %4 at (%2, %3) on the screen %6\",\n                robotis_Practice_text_screen_redraw: \"Newly display %1 in %4 at (%2, %3) %5\",\n                robotis_Practice_pixel: \"Display %3 colored dot at (%1, %2) %4\",\n                robotis_Practice_LCDColor: \"Set screen color as %1 %2\",\n                robotis_Practice_LCD_Flash: \"Blink the screen with %1 and %2 at intervals of %3 seconds %4\",\n                robotis_Practice_LCDBright: \"Set screen brightness as %1 %2\",\n\n                // LED 제어\n                robotis_Practice_cm_led: \"%2 the robot's %1 LED %3\",\n                robotis_Practice_cm_led_pattern: \"LED %1 blinks at a %2 speed %3\",\n\n\n                // DXL 제어\n                robotis_Practice_dxl_set_mode: \"Set ID %1 motor as %2 mode %3\",\n                robotis_Practice_dxl_each_control: \"Move %1th motor %2° for %3 second\",\n                robotis_Practice_dxl_set_position: \"Rotate ID %1 motor to angle %3° at speed %2 %4\",\n                robotis_Practice_dxl_set_rotate: \"%4 ID %1 motor %3 at speed %2 %4\",\n                robotis_Practice_dxl_set_multiturn_round: \"Rotate ID %1 motor %3 times %4 at speed %2 %5\",\n\n                \n                // AI Camera 값 블록\n                robotis_Practice_ai_camera_connection_status: \"AI Camera: If %1\",\n                robotis_Practice_ai_camera_if_detected: \"AI Camera: If %1 is displayed\",\n        \n                robotis_Practice_ai_camera_block_value_closest_to_center: \"AI Camera: %2 of the %1 closest to the center of the screen\",\n                robotis_Practice_ai_camera_arrow_value_closest_to_center: \"AI Camera: %1 of the arrow closest to the center of the screen\",\n                robotis_Practice_ai_camera_number_of_learned_id: \"AI Camera: the number of learned ID\",\n                robotis_Practice_ai_camera_block_value_of_id: \"AI Camera: %3 of %2 with detected ID %1\",\n                robotis_Practice_ai_camera_arrow_value_of_id: \"AI Camera: %2 of arrow with detected ID %1\",\n        \n                robotis_Practice_ai_camera_if_learned_id: \"AI Camera: If learned data with ID %1\",\n                robotis_Practice_ai_camera_if_detected_id_type: \"AI Camera: If learned %2 data with ID %1\",\n        \n                // 인공지능 카메라 제어\n                robotis_Practice_ai_camera_set_mode: \"AI Camera: Set mode to %1 %2\",\n                robotis_Practice_ai_camera_print_custom_text: \"AI Camera: Display %3 at screen position (%1, %2) %4\",\n                robotis_Practice_ai_camera_clear_custom_text: \"AI Camera: Clear screen text %1\",\n            },            \n            Helper: {\n                // 주행 제어\n                robotis_Practice_drive_simple: \"Drive the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %\", \n                robotis_Practice_drive_advanced: \"Rotate the left and right wheels of the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %\", \n                robotis_Practice_drive_seperate: \"Rotate the specified wheel of the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %\", \n                robotis_Practice_drive_angle: \"Rotate the two wheels of the robot in the specified direction and by the specified angle\\nAngle range: -5760 ~ 5760\\nAngle unit: degrees\", \n                robotis_Practice_go_distance: \"Move forward or backward by the specified distance\\nDistance range: -1000 ~ 1000\\nDistance unit: mm\", \n                robotis_Practice_turn_angle: \"Rotate in place by the specified angle and direction\\nAngle range: -360 ~ 360\\nAngle unit: degrees\", \n                robotis_Practice_follow_line: \"Start following the line at the specified speed\", \n                robotis_Practice_stop_at_cross: \"Stop at the specified intersection\", \n                robotis_Practice_turn_at_line: \"Make the specified turn at the intersection and stop\", \n                robotis_Practice_drive_stop: \"Stop the robot\", \n\n                // 값 블록\n                robotis_Practice_cm_ir_value: \"IR sensor value of the specified number (range: 0 ~ 200)\", \n                robotis_Practice_cm_ir_compare: \"If the IR sensor value of the specified number matches the specified value, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_detectFrontObj: \"It returns 'true' if an object is detected by the infrared sensor in the specified direction; otherwise, it returns 'false'.\", \n                robotis_Practice_cm_btn_value: \"If the specified button is clicked, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_cm_joystick_value: \"If the joystick position is in the specified state, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_mic: \"Displays the intensity of the sound detected by the microphone in decibels (dB).\", \n                robotis_Practice_detectSound_compare: \"If the direction of the sound matches the specified direction, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_imu: \"Value of the specified accelerometer/gyro sensor on the specified axis\\nRange: -100 ~ 100\", \n                robotis_Practice_roll_pitch: \"roll/pitch value\\nroll: -180° ~ 180°, pitch: -90° ~ 90°\", \n                robotis_Practice_distance_value: \"Value of the specified sensor\\nDistance range: 0 ~ 1000mm\\nIlluminance range: 0 ~ 100%\\nButton sensor: 0 (not pressed) / 1 (pressed)\", \n                robotis_Practice_distance_compare: \"If the specified equation of the specified sensor value is correct, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_environment_value: \"Value of the specified sensor\\nMotion sensor: 0 (no movement) / 1 (movement)\\nBrightness range: 0 ~ 100%\\nTemperature range: -25°C ~ 85°C\", \n                robotis_Practice_environment_compare: \"If the specified equation of the specified sensor value is correct, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_line_cross_compare: \"If the specified intersection shape is correct, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_dxl_value: \"Position angle value of the specified motor\\nRange: -180° ~ 180°\", \n\n                // 소리\n                robotis_Practice_scale_simple: \"Play with the specified octave, scale, and note\", \n                robotis_Practice_scale_advanced: \"Play with the specified octave, scale, and beat\", \n                robotis_Practice_rest_simple: \"Rest for the specified rest note\", \n                robotis_Practice_rest_advanced: \"Rest for the specified beat\", \n                robotis_Practice_beat_per_minute: \"Set the playing speed (BPM)\\nRange: 10 ~ 600\", \n                robotis_Practice_Hello: \"Play the specified voice of the robot\", \n                robotis_Practice_effectSound: \"Play the specified sound effect of the robot\", \n                robotis_Practice_record: \"Record and save to the specified number storage\", \n                robotis_Practice_playRecord: \"Play the recorded voice in the specified number storage\", \n\n                // LCD 제어\n                robotis_Practice_screen: \"Set the character and expression of the controller screen background\", \n                robotis_Practice_anim_screen: \"Set the character and expression of the controller screen animation\", \n                robotis_Practice_icon_screen_food_plant: \"Set the position and size of a specific icon in [food/plant] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\", \n                robotis_Practice_icon_screen_animal_human: \"Set the position and size of a specific icon in [animal/human] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\", \n                robotis_Practice_icon_screen_object_tool: \"Set the position and size of a specific icon in [object/tool] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\", \n                robotis_Practice_icon_screen_vehicle_number: \"Set the position and size of a specific icon in [vehicle/number] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\", \n                robotis_Practice_icon_screen_game_character: \"Set the position and size of a specific icon in [game/character] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\",\n                robotis_Practice_text_screen: \"Set the position, font size, and color of the specified text on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\", \n                robotis_Practice_text_screen_redraw: \"Set the position and color of the specified text to be newly displayed (clearing the background of the text) on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200\", \n                robotis_Practice_pixel: \"Set the position and color of the dot to be displayed on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\", \n                robotis_Practice_LCDBright: \"Set the screen brightness\\nBrightness range: 0% ~ 100%\", \n                robotis_Practice_LCDColor: \"Set the screen color\", \n                robotis_Practice_LCD_Flash: \"Specify two colors and the interval for the screen to blink.\",\n\n                // LED 제어\n                robotis_Practice_cm_led: \"Turn the specified LED of the controller on or off\", \n                robotis_Practice_cm_led_pattern: \"Set the blinking pattern of LEDs of the controller\", \n\n                // DXL 제어\n                robotis_Practice_dxl_set_mode: \"Set the operating mode of the motor with the specified ID\",\n                robotis_Practice_dxl_each_control: \"Set the motor with the specified ID to move to the specified angle for the specified time (seconds)\",\n                robotis_Practice_dxl_set_position: \"Set the motor with the specified ID to move to the specified angle at the specified speed\",\n                robotis_Practice_dxl_set_rotate: \"Set the rotation speed and direction of the motor with the specified ID\",\n                robotis_Practice_dxl_set_multiturn_round: \"Set the motor with the specified ID to rotate the specified number of turns at the specified speed and direction\",\n\n                // AI Camera 값 블록\n                robotis_Practice_ai_camera_connection_status: \"If the AI camera is connected, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_ai_camera_if_detected: \"If the selected symbol (rectangle/arrow) is displayed on the LCD screen of the AI camera, it is determined as 'true'; otherwise, 'false'.\", \n\n                robotis_Practice_ai_camera_block_value_closest_to_center: \"X coordinate/Y coordinate/width/height/learning ID of the rectangle closest to the center of the AI camera screen\", \n                robotis_Practice_ai_camera_arrow_value_closest_to_center: \"Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate/learning ID of the arrow closest to the center of the AI camera screen\", \n                robotis_Practice_ai_camera_number_of_learned_id: \"Number of IDs learned by the AI camera\", \n                robotis_Practice_ai_camera_block_value_of_id: \"X coordinate/Y coordinate/width/height of the rectangle with the specified ID detected by the AI camera\", \n                robotis_Practice_ai_camera_arrow_value_of_id: \"Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate of the arrow with the specified ID detected by the AI camera\", \n\n                robotis_Practice_ai_camera_if_learned_id: \"If the AI camera has learned the data of the specified ID, it is determined as 'true'; otherwise, 'false'.\", \n                robotis_Practice_ai_camera_if_detected_id_type: \"If the AI camera has learned the specified data (rectangle/arrow) of the specified ID, it is determined as 'true'; otherwise, 'false'.\", \n\n                // 인공지능 카메라 제어\n                robotis_Practice_ai_camera_set_mode: \"Set the mode of the AI camera\", \n                robotis_Practice_ai_camera_print_custom_text: \"Print the specified text at the specified position on the AI camera screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\", \n                robotis_Practice_ai_camera_clear_custom_text: \"Clear all the text displayed on the AI camera screen\", \n            },\n\n            Blocks: {\n                robotis_red: \"Red\",\n                robotis_orange: \"Orange\",\n                robotis_yellow: \"Yellow\",\n                robotis_green: \"Green\",\n                robotis_blue: \"Blue\",\n                robotis_brown: \"Brown\",\n                robotis_black: \"Black\",\n                robotis_white: \"White\",\n                robotis_left: \"Left\",\n                robotis_center: \"Center\",\n                robotis_right: \"Right\",\n                robotis_both: \"Both\",\n                robotis_rgee: \"R-GEE\",\n                robotis_rla: \"KODALA\",\n                robotis_kkokdu: \"TIG\",\n                robotis_korean1: \"Hello!\",\n                robotis_korean2: \"Great to see you.\",\n                robotis_korean3: \"Okay ~\",\n                robotis_korean4: \"No!\",\n                robotis_korean5: \"I don't know.\",\n                robotis_korean6: \"I like it.\",\n                robotis_korean7: \"I don't like it.\",\n                robotis_korean8: \"What is your name? \",\n                robotis_korean9: \"How can I help you? \",\n                robotis_korean10: \"Great job! \",\n                robotis_korean11: \"It's alright.\",\n                robotis_korean12: \"Let's do it again! \",\n                robotis_korean13: \"Thank you! \",\n                robotis_korean14: \"Can you say that one more time?\",\n                robotis_korean15: \"Awesome!\",\n                robotis_korean16: \"I'm excited! \",\n                robotis_korean17: \"I'm having a great time! \",\n                robotis_korean18: \"I'm sorry.\",\n                robotis_korean19: \"I'm angry! \",\n                robotis_korean20: \"I'm embarassed.\",\n                robotis_korean21: \"I'm scared.\",\n                robotis_korean22: \"I'm upset.\",\n                robotis_korean23: \"I love you.\",\n                robotis_korean24: \"Very pretty! \",\n                robotis_korean25: \"Interesting.\",\n                robotis_korean26: \"I'm nervous.\",\n                robotis_korean27: \"Let's move forward! \",\n                robotis_korean28: \"Let's move backward! \",\n                robotis_korean29: \"Let's stand up! \",\n                robotis_korean30: \"Did you fall down? \",\n                robotis_korean31: \"Oh Yeah~\",\n                robotis_korean32: \"Sweet! \",\n                robotis_korean33: \"Oh no\",\n                robotis_korean34: \"My My \",\n                robotis_korean35: \"Whoo hoo! \",\n                robotis_korean36: \"Ha Ha Ha\",\n                robotis_korean37: \"Ho Ho Ho \",\n                robotis_korean38: \"I'm sleepy.\",\n                robotis_korean39: \"Sing me a bedtime song! \",\n                robotis_korean40: \"Hello!\",\n                robotis_korean41: \"I'm hungry.\",\n                robotis_korean42: \"I'm craving an acorn! \",\n                robotis_korean43: \"I want to take a bath! \",\n                robotis_korean44: \"Time for a bath! \",\n                robotis_korean45: \"I'm bored. \",\n                robotis_korean46: \"Do you want a snack? \",\n                robotis_korean47: \"I'm sick.\",\n                robotis_korean48: \"Do you have any medicine? \",\n                robotis_korean49: \"Where do we have to go? \",\n                robotis_korean50: \"We're here! \",\n                robotis_korean51: \"Let's go to the left side! \",\n                robotis_korean52: \"Let's go to the right side! \",\n                robotis_korean53: \"Oh my, you scared me! \",\n                robotis_korean54: \"Found you! \",\n                robotis_korean55: \"There's nothing here. \",\n                robotis_korean56: \"Did you call me?\",\n                robotis_korean57: \"Please let me down. \",\n                robotis_korean58: \"Oops! \",\n                robotis_korean59: \"Hmmph! \",\n                robotis_korean60: \"Eek! \",\n                robotis_dog: \"Dog\",\n                robotis_frog: \"Frog\",\n                robotis_cat: \"Cat\",\n                robotis_chicken: \"Rooster\",\n                robotis_tiger: \"Tiger\",\n                robotis_mouse: \"Mouse\",\n                robotis_ambul: \"Ambulance\",\n                robotis_Horn: \"CarHorn\",\n                robotis_siren: \"Siren\",\n                robotis_whistle: \"Whistle\",\n                robotis_gun: \"Gunshot\",\n                robotis_clap: \"Clap\",\n                robotis_melody1: \"Melody1\",\n                robotis_melody2: \"Melody2\",\n                robotis_melody3: \"Melody3\",\n                robotis_melody4: \"Melody4\",\n                robotis_forward: \"Forward\",\n                robotis_backward: \"Backward\",\n                robotis_acceleration: \"acceleration\",\n                robotis_gyro: \"gyro\",\n                robotis_run: \"Run\",\n                robotis_cancel: \"Cancel\",\n                robotis_push: \"Pressed\",\n                robotis_notPush: \"Unpressed\",\n                robotis_play: \"Play\",\n                robotis_rest: \"Rest\",\n                robotis_face01: \"Haha\",\n                robotis_face02: \"Smile\",\n                robotis_face03: \"Laugh\",\n                robotis_face04: \"Yum Yum\",\n                robotis_face05: \"Scared\",\n                robotis_face06: \"Uncomfortable\",\n                robotis_face07: \"Confused\",\n                robotis_face08: \"Dazed\",\n                robotis_face09: \"Yell\",\n                robotis_face10: \"Angry\",\n                robotis_face11: \"Sniff (Left)\",\n                robotis_face12: \"Sniff (Right)\",\n                robotis_face13: \"Sniff (Down)\",\n                robotis_face14: \"Whew\",\n                robotis_face15: \"Faint\",\n                robotis_face16: \"Dizzy\",\n                robotis_face17: \"Yawn\",\n                robotis_face18: \"Sleepy\",\n                robotis_face19: \"Sleep\",\n                robotis_face20: \"Sad\",\n                robotis_face21: \"Cry\",\n                robotis_face22: \"Bath\",\n                robotis_face23: \"Heart-Eyes\",\n                robotis_flashing1: \"Flashing1\",\n                robotis_flashing2: \"Flashing2\",\n                robotis_flashing3: \"Flashing3\",\n                robotis_flashing4: \"Flashing4\",\n                robotis_flashing5: \"Flashing5\",\n                robotis_flashing6: \"Flashing6\",\n                robotis_flashing7: \"Flashing7\",\n                robotis_flashing8: \"Flashing8\",\n                robotis_flashing9: \"Flashing9\",\n                robotis_moveF: \"Forward\",\n                robotis_moveB: \"Backward\",\n                robotis_moveL: \"LeftTurn\",\n                robotis_moveR: \"RightTurn\",\n                robotis_moveU: \"U-turn\",\n                robotis_moveL_in_place: \"Turn left in place\",\n                robotis_moveR_in_place: \"Trun right in place\",\n                robotis_moveU_in_place: \"U-turn in place\",\n                robotis_moveRG1: \"Stand\",\n                robotis_moveRG2: \"Sit\",\n                robotis_moveRG3: \"Struggle\",\n                robotis_moveRG4: \"RaiseFeet\",\n                robotis_fast: \"Fast\",\n                robotis_normal: \"Normal\",\n                robotis_slow: \"Slow\",\n                robotis_stop: \"Stop\",\n                robotis_roll: \"Left-right rotate angle (roll)\",\n                robotis_pitch: \"Forward-backward rotate angle (pitch)\",\n                robotis_direction_forward: \"Forward\",\n                robotis_direction_backward: \"Backward\",\n                robotis_stMotion1: \"Standard\",\n                robotis_stMotion2: \"Forward\",\n                robotis_stMotion3: \"TurnRight\",\n                robotis_stMotion4: \"TurnLeft\",\n                robotis_stMotion5: \"Backward\",\n                robotis_stMotion6: \"ToRight\",\n                robotis_stMotion7: \"ToLeft\",\n                robotis_stMotion8: \"TurnAroundRight\",\n                robotis_stMotion9: \"TurnAroundLeft\",\n                robotis_spMotion1: \"RightHandUp\",\n                robotis_spMotion2: \"RightHandDown\",\n                robotis_spMotion3: \"LeftHandUp\",\n                robotis_spMotion4: \"LeftHandDown\",\n                robotis_spMotion5: \"BothHandsUp\",\n                robotis_spMotion6: \"BothHandsDown\",\n                robotis_spMotion7: \"FallBackward\",\n                robotis_spMotion8: \"FallForward\",\n                robotis_spMotion9: \"StandForward\",\n                robotis_spMotion10: \"StandBackward\",\n                robotis_spMotion11: \"Defence\",\n                robotis_spMotion12: \"Offense1\",\n                robotis_spMotion13: \"Offense2\",\n                robotis_spMotion14: \"Offense3\",\n                robotis_spMotion15: \"Offense4\",\n                robotis_screen1: \"Sissor\",\n                robotis_screen2: \"Rock\",\n                robotis_screen3: \"Paper\",\n                robotis_dxl_mode_joint: \"Joint\",\n                robotis_dxl_mode_wheel: \"Wheel\",\n                robotis_dxl_mode_multi_turn: \"Multi-turn\",\n                robotis_dxl_move_rotate: \"Rotate\",\n                robotis_dxl_move_stop: \"Stop\",\n                robotis_dxl_rotate_cw: \"clockwise\",\n                robotis_dxl_rotate_ccw: \"counter clockwise\",\n                robotis_dxl_value_angle: \"angle\",\n                robotis_dxl_value_velocity: \"velocity\",\n                robotis_dxl_value_moving: \"moving\",\n                robotis_icon_food_plant_1: \"Milk\",\n                robotis_icon_food_plant_2: \"Tree\",\n                robotis_icon_food_plant_3: \"Soup\",\n                robotis_icon_food_plant_4: \"Cake\",\n                robotis_icon_food_plant_5: \"Water\",\n                robotis_icon_food_plant_6: \"Juice\",\n                robotis_icon_food_plant_7: \"Carrot\",\n                robotis_icon_food_plant_8: \"Apple\",\n                robotis_icon_food_plant_9: \"Orange\",\n                robotis_icon_food_plant_10: \"Meat\",\n                robotis_icon_food_plant_11: \"Flowerpot\",\n                robotis_icon_food_plant_12: \"Rose\",\n                robotis_icon_food_plant_13: \"Grape\",\n                robotis_icon_food_plant_14: \"Potato\",\n                robotis_icon_food_plant_15: \"Candy\",\n                robotis_icon_food_plant_16: \"Cheese\",\n                robotis_icon_food_plant_17: \"Bread\",\n                robotis_icon_food_plant_18: \"Flowers\",\n                robotis_icon_food_plant_19: \"Coffee\",\n                robotis_icon_food_plant_20: \"Tulip\",\n                robotis_icon_food_plant_21: \"Banana\",\n                robotis_icon_food_plant_22: \"Fruits\",\n                robotis_icon_food_plant_23: \"Hamburger\",\n                robotis_icon_food_plant_24: \"Pizza\",\n                robotis_icon_animal_human_1: \"Shiba Dog\",\n                robotis_icon_animal_human_2: \"Puppy\",\n                robotis_icon_animal_human_3: \"Bear\",\n                robotis_icon_animal_human_4: \"Bird\",\n                robotis_icon_animal_human_5: \"Duck\",\n                robotis_icon_animal_human_6: \"Lion\",\n                robotis_icon_animal_human_7: \"Tiger\",\n                robotis_icon_animal_human_8: \"Horse\",\n                robotis_icon_animal_human_9: \"Sheep\",\n                robotis_icon_animal_human_10: \"Shark 1 (Left)\",\n                robotis_icon_animal_human_11: \"Shark 1 (Right)\",\n                robotis_icon_animal_human_12: \"Shark 2 (Left)\",\n                robotis_icon_animal_human_13: \"Shark 2 (Right)\",\n                robotis_icon_animal_human_14: \"Fish 1\",\n                robotis_icon_animal_human_15: \"Fish 2\",\n                robotis_icon_animal_human_16: \"Fish 3\",\n                robotis_icon_animal_human_17: \"Octopus\",\n                robotis_icon_animal_human_18: \"Monkey\",\n                robotis_icon_animal_human_19: \"Chicken\",\n                robotis_icon_animal_human_20: \"Pig\",\n                robotis_icon_animal_human_21: \"Person (Chubby)\",\n                robotis_icon_animal_human_22: \"Person (Swimsuit)\",\n                robotis_icon_animal_human_23: \"Baby\",\n                robotis_icon_animal_human_24: \"Person (Running)\",\n                robotis_icon_animal_human_25: \"Person (Singing)\",\n                robotis_icon_animal_human_26: \"Person (Sitting)\",\n                robotis_icon_animal_human_27: \"Person (Angry)\",\n                robotis_icon_animal_human_28: \"Person (Cheering)\",\n                robotis_icon_animal_human_29: \"King\",\n                robotis_icon_animal_human_30: \"Prince\",\n                robotis_icon_animal_human_31: \"Princess\",\n                robotis_icon_animal_human_32: \"Chef\",\n                robotis_icon_animal_human_33: \"Doctor\",\n                robotis_icon_animal_human_34: \"Nurse\",\n                robotis_icon_object_tool_1: \"Bag\",\n                robotis_icon_object_tool_2: \"Box\",\n                robotis_icon_object_tool_3: \"Mug\",\n                robotis_icon_object_tool_4: \"Hat (Fedora)\",\n                robotis_icon_object_tool_5: \"Hat (Cap)\",\n                robotis_icon_object_tool_6: \"Key\",\n                robotis_icon_object_tool_7: \"Toy\",\n                robotis_icon_object_tool_8: \"Book\",\n                robotis_icon_object_tool_9: \"Teddy Bear\",\n                robotis_icon_object_tool_10: \"Drum\",\n                robotis_icon_object_tool_11: \"Notebook\",\n                robotis_icon_object_tool_12: \"Pen\",\n                robotis_icon_object_tool_13: \"Desk\",\n                robotis_icon_object_tool_14: \"Table\",\n                robotis_icon_object_tool_15: \"Chair\",\n                robotis_icon_object_tool_16: \"Bed\",\n                robotis_icon_object_tool_17: \"Tent\",\n                robotis_icon_object_tool_18: \"Plate\",\n                robotis_icon_object_tool_19: \"Soccer Ball\",\n                robotis_icon_object_tool_20: \"Bell\",\n                robotis_icon_object_tool_21: \"Watch\",\n                robotis_icon_object_tool_22: \"Shoes\",\n                robotis_icon_object_tool_23: \"Lamp\",\n                robotis_icon_object_tool_24: \"Radio\",\n                robotis_icon_object_tool_25: \"Banknote\",\n                robotis_icon_object_tool_26: \"Ruler\",\n                robotis_icon_object_tool_27: \"Camera\",\n                robotis_icon_object_tool_28: \"Spoon\",\n                robotis_icon_object_tool_29: \"Keyboard\",\n                robotis_icon_object_tool_30: \"Calendar\",\n                robotis_icon_object_tool_31: \"Knife\",\n                robotis_icon_object_tool_32: \"Balloon\",\n                robotis_icon_object_tool_33: \"Water Bottle\",\n                robotis_icon_object_tool_34: \"Wooden Stick (Horizontal)\",\n                robotis_icon_object_tool_35: \"Wooden Stick (Vertical)\",\n                robotis_icon_object_tool_36: \"Fishing Hook\",\n                robotis_icon_vehicle_number_1: \"Car\",\n                robotis_icon_vehicle_number_2: \"Bus\",\n                robotis_icon_vehicle_number_3: \"Truck\",\n                robotis_icon_vehicle_number_4: \"Jeep\",\n                robotis_icon_vehicle_number_5: \"Bicycle\",\n                robotis_icon_vehicle_number_6: \"Subway\",\n                robotis_icon_vehicle_number_7: \"Train\",\n                robotis_icon_vehicle_number_8: \"Airplane\",\n                robotis_icon_vehicle_number_9: \"Fighter Jet (Vertical)\",\n                robotis_icon_vehicle_number_10: \"Fighter Jet (Horizontal)\",\n                robotis_icon_vehicle_number_11: \"Rocket\",\n                robotis_icon_vehicle_number_12: \"Fishing Boat\",\n                robotis_icon_vehicle_number_13: \"Passenger Ship\",\n                robotis_icon_vehicle_number_14: \"Submarine (Left)\",\n                robotis_icon_vehicle_number_15: \"Submarine (Right)\",\n                robotis_icon_vehicle_number_16: \"Airplane (Left)\",\n                robotis_icon_vehicle_number_17: \"Airplane (Right)\",\n                robotis_icon_vehicle_number_18: \"Airplane (Top)\",\n                robotis_icon_vehicle_number_19: \"Spaceship (Left)\",\n                robotis_icon_vehicle_number_20: \"Spaceship (Right)\",\n                robotis_icon_vehicle_number_21: \"Spaceship (Top)\",\n                robotis_icon_vehicle_number_22: \"Dice (1)\",\n                robotis_icon_vehicle_number_23: \"Dice (2)\",\n                robotis_icon_vehicle_number_24: \"Dice (3)\",\n                robotis_icon_vehicle_number_25: \"Dice (4)\",\n                robotis_icon_vehicle_number_26: \"Dice (5)\",\n                robotis_icon_vehicle_number_27: \"Dice (6)\",\n                robotis_icon_vehicle_number_28: \"0\",\n                robotis_icon_vehicle_number_29: \"1\",\n                robotis_icon_vehicle_number_30: \"2\",\n                robotis_icon_vehicle_number_31: \"3\",\n                robotis_icon_vehicle_number_32: \"4\",\n                robotis_icon_vehicle_number_33: \"5\",\n                robotis_icon_vehicle_number_34: \"6\",\n                robotis_icon_vehicle_number_35: \"7\",\n                robotis_icon_vehicle_number_36: \"8\",\n                robotis_icon_vehicle_number_37: \"9\",\n                robotis_icon_vehicle_number_38: \"10\",\n                robotis_icon_game_character_1: \"R-GEE(F)\",\n                robotis_icon_game_character_2: \"R-GEE(L)\",\n                robotis_icon_game_character_3: \"R-GEE(R)\",\n                robotis_icon_game_character_4: \"KODALA(F)\",\n                robotis_icon_game_character_5: \"KODALA(L))\",\n                robotis_icon_game_character_6: \"KODALA(R)\",\n                robotis_icon_game_character_7: \"Ghost\",\n                robotis_icon_game_character_8: \"Monster\",\n                robotis_icon_game_character_9: \"Virus\",\n                robotis_icon_game_character_10: \"Bacteria\",\n                robotis_icon_game_character_11: \"Flying R-GEE (L)\",\n                robotis_icon_game_character_12: \"Flying R-GEE (R)\",\n                robotis_icon_game_character_13: \"Flying R-GEE (F)\",\n                robotis_icon_game_character_14: \"Medal\",\n                robotis_icon_game_character_15: \"Money (G)\",\n                robotis_icon_game_character_16: \"Money ($)\",\n                robotis_icon_game_character_17: \"Heart\",\n                robotis_icon_game_character_18: \"Bomb\",\n                robotis_icon_game_character_19: \"Fire\",\n                robotis_icon_game_character_20: \"Cloud 1\",\n                robotis_icon_game_character_21: \"Cloud 2\",\n                robotis_icon_game_character_22: \"Shell 1\",\n                robotis_icon_game_character_23: \"Shell 2\",\n                robotis_icon_game_character_24: \"Cannon (Horizontal)\",\n                robotis_icon_game_character_25: \"Cannon (Vertical)\",\n                robotis_icon_game_character_26: \"Laser (Vertical)\",\n                robotis_icon_game_character_27: \"Laser (Horizontal)\",\n                robotis_icon_game_character_28: \"Arrow (Horizontal)\",\n                robotis_icon_game_character_29: \"Arrow (Vertical)\",\n                robotis_icon_game_character_30: \"Missile (Up)\",\n                robotis_icon_game_character_31: \"Missile (Down)\",\n                robotis_icon_game_character_32: \"Missile (Left)\",\n                robotis_icon_game_character_33: \"Missile (Right)\",\n                robotis_icon_game_character_34: \"Parachute\",\n                robotis_icon_game_character_35: \"Explosion 1\",\n                robotis_icon_game_character_36: \"Explosion 2\",\n                robotis_icon_game_character_37: \"Scope\",\n                robotis_icon_game_character_38: \"Scissors\",\n                robotis_icon_game_character_39: \"Rock\",\n                robotis_icon_game_character_40: \"Paper\",\n                robotis_icon_game_character_41: \"Walking Person 1\",\n                robotis_icon_game_character_42: \"Walking Person 2\",\n                robotis_icon_game_character_43: \"Running Person 1\",\n                robotis_icon_game_character_44: \"Running Person 2\",                        \n                robotis_speed_fast: \"Fast Speed\",\n                robotis_speed_midium: \"Medium Speed\",\n                robotis_speed_slow: \"Slow Speed\",\n                robotis_clockwise: \"Clockwise\",\n                robotis_counterclockwise: \"Counterclockwise\",\n                robotis_up: \"Lift\",\n                robotis_down: \"Lower\",\n                robotis_if_greater: \"If Greater\",\n                robotis_if_smaller: \"If Smaller\",\n                robotis_if_equal: \"If Equal\",\n                robotis_front_right: \"Front Right\",\n                robotis_front_left: \"Front Left\",\n                robotis_bottom_right: \"Bottom Right\",\n                robotis_bottom_left: \"Bottom Left\",\n                robotis_side_right: \"Right Edge\",\n                robotis_side_left: \"Left Edge\",\n                robotis_front_ir_sensor: \"Infrared Sensor\",\n                robotis_distance_sensor: \"Distance Sensor\",\n                robotis_front: \"Front\",\n                robotis_right: \"Right\",\n                robotis_left_wheel: \"Left Wheel\",\n                robotis_right_wheel: \"Right Wheel\",\n                robotis_beat_sound_8th_note: \"Eighth Note (♪)\",\n                robotis_beat_sound_dotted_8th_note: \"Dotted Eighth Note (♪.)\",\n                robotis_beat_sound_quarter_note: \"Quarter Note (♩)\",\n                robotis_beat_sound_dotted_quarter_note: \"Dotted Quarter Note (♩.)\",\n                robotis_beat_sound_half_note: \"Half Note (𝅗𝅥)\",\n                robotis_beat_sound_dotted_half_note: \"Dotted Half Note (𝅗𝅥.)\",\n                robotis_beat_sound_whole_note: \"Whole Note (𝅝)\",\n                robotis_beat_sound_dotted_note: \"Dotted Whole Note (𝅝.)\",\n                robotis_beat_rest_8th_note: \"Eighth Rest (𝄾)\",\n                robotis_beat_rest_dotted_8th_note: \"Dotted Eighth Rest (𝄾.)\",\n                robotis_beat_rest_quarter_note: \"Quarter Rest (𝄽)\",\n                robotis_beat_rest_dotted_quarter_note: \"Dotted Quarter Rest (𝄽.)\",\n                robotis_beat_rest_half_note: \"Half Rest (𝄼)\",\n                robotis_beat_rest_dotted_half_note: \"Dotted Half Rest (𝄼˙)\",\n                robotis_beat_rest_whole_note: \"Whole Rest (𝄻)\",\n                robotis_beat_rest_dotted_note: \"Dotted Whole Rest (𝄻˙)\",\n                robotis_line_cross_type_0: \"|\",\n                robotis_line_cross_type_1: \" (Blank)\",\n                robotis_line_cross_type_5: \"🞣\",\n                robotis_line_cross_type_6: \"⏉\",\n                robotis_line_cross_type_7: \"⊣\",\n                robotis_line_cross_type_8: \"⊢\",\n                robotis_line_cross_type_9: \"⏋\",\n                robotis_line_cross_type_10: \"⎾\",\n                robotis_line_cross_type_11: \"¦\",\n                robotis_line_cross_type_12: \"︙\",\n                robotis_connected: \"Connected\",\n                robotis_disconnected: \"Not connected\",\n                robotis_ai_camera_mode_face_recognition: \"Face recognition\",\n                robotis_ai_camera_mode_object_tracking: \"Object tracking\",\n                robotis_ai_camera_mode_object_recognition: \"Object recognition\",\n                robotis_ai_camera_mode_line_recognition: \"Line tracking\",\n                robotis_ai_camera_mode_color_recognition: \"Color recognition\",\n                robotis_ai_camera_mode_tag_recognition: \"Tag recognition\",\n                robotis_ai_camera_mode_object_classification: \"Object classification\",\n                robotis_ai_camera_mode_expression_recognition: \"Expression recognition\",\n                robotis_ai_camera_target_face: \"Face\",\n                robotis_ai_camera_target_expression: \"Expression\",\n                robotis_ai_camera_target_object: \"Object\",\n                robotis_ai_camera_target_color: \"Color\",\n                robotis_ai_camera_target_tag: \"Tag\",\n                robotis_ai_camera_target_qr: \"QR\",\n                robotis_ai_camera_target_block: \"Rectangle\",\n                robotis_ai_camera_target_arrow: \"Arrow\",\n                robotis_ai_camera_center_block_center_x: \"Center X\",\n                robotis_ai_camera_center_block_center_y: \"Center Y\",\n                robotis_ai_camera_center_block_width: \"Width\",\n                robotis_ai_camera_center_block_height: \"Height\",\n                robotis_ai_camera_center_leared_id: \"Learned ID\",\n                robotis_ai_camera_center_arrow_origin_x: \"Origin X\",\n                robotis_ai_camera_center_arrow_origin_y: \"Origin Y\",\n                robotis_ai_camera_center_arrow_target_x: \"Target X\",\n                robotis_ai_camera_center_arrow_target_y: \"Target Y\",\n\n                robotis_plant_ripe: \"ripe in red\",\n                robotis_plant_unripe: \"green and unripe\",\n                robotis_harvest: \"Harvest\",\n                robotis_not_harvest: \"Skip harvesting\",\n            },\n        }\n    }\n};\n\nlet dxl_last_valid_value = [];\nlet rb100_last_valid_value = [];\nlet bg_color = 0;\nlet beat_per_minute = 75;\nlet camera_id_for_use = 0;\n\nconst _doevent = ms => new Promise(res => setTimeout(res, ms));\nasync function wait(nTime) { await _doevent(nTime); }\n\nEntry.Robotis_rb_P_Assembly.getBlocks = function () {\n    return {\n        robotis_Practice_drive_simple: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '2'],\n                        [Lang.Blocks.robotis_moveL_in_place, '3'],\n                        [Lang.Blocks.robotis_moveR_in_place, '4'],\n\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    5,\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_drive_simple',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var speed = script.getNumberValue('SPEED', script);\n                var direction = script.getField('DIRECTION', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n                \n                switch(direction) {\n                    case '1':\n                        data_value = speed * 256 + speed;\n                        break;\n                    case '2':\n                        data_value = (256 - speed) * 256 + (256 - speed);\n                        break;\n                    case '3':\n                        data_value = speed * 256 + (256 - speed);\n                        break;\n                    case '4':\n                        data_value = (256 - speed) * 256 + speed;\n                        break;\n                    default:\n                        data_value = 0;\n                        break;\n                }\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_RCar_go_simple(%1, %2)'],\n            },\n        },\n        robotis_Practice_drive_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_drive_stop',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        5200,\n                        1,\n                        0,\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_RCar_stop(%1, %2)'],\n            },\n        },\n        robotis_Practice_drive_advanced: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_drive_advanced',\n            },\n            paramsKeyMap: {\n                LEFT_SPEED: 0,\n                LEFT_DIRECTION: 1,\n                RIGHT_SPEED: 2,\n                RIGHT_DIRECTION: 3,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                let leftSpeed = script.getNumberValue('LEFT_SPEED', script);\n                let leftDirection = script.getField('LEFT_DIRECTION', script);\n                let rightSpeed = script.getNumberValue('RIGHT_SPEED', script);\n                let rightDirection = script.getField('RIGHT_DIRECTION', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n\n                if (leftSpeed < -100) leftSpeed = -100;\n                else if (leftSpeed > 100) leftSpeed = 100;\n\n                if (rightSpeed < -100) rightSpeed = -100;\n                else if (rightSpeed > 100) rightSpeed = 100;\n\n                if (leftDirection == '2') {\n                    leftSpeed = -leftSpeed;\n                }\n                if (rightDirection == '2') {\n                    rightSpeed = -rightSpeed;\n                }\n\n                if (leftSpeed < 0) {\n                    leftSpeed = 256 + leftSpeed;\n                }\n                if (rightSpeed < 0) {\n                    rightSpeed = 256 + rightSpeed;\n                }\n                \n                data_value = leftSpeed + rightSpeed * 256;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_RCar_go_advanced(%1, %2)'],\n            },\n        },\n        robotis_Practice_drive_seperate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '1'],\n                        [Lang.Blocks.robotis_right, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_direction_forward, '1'],\n                        [Lang.Blocks.robotis_direction_backward, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['5'],\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_drive_seperate',\n            },\n            paramsKeyMap: {\n                WHEEL_SIDE: 0,\n                WHEEL_SPEED: 1,\n                WHEEL_DIRECTION: 2,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                let wheelSide = script.getNumberValue('WHEEL_SIDE', script);\n                let wheelSpeed = script.getNumberValue('WHEEL_SPEED', script);\n                let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n\n                let leftSpeed = 0;\n                let rightSpeed = 0;\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 710;\n                var data_length = 2;\n                var data_value = 0;\n                \n\n                if (wheelSpeed < -100) wheelSpeed = -100;\n                else if (wheelSpeed > 100) wheelSpeed = 100;\n\n                wheelSpeed = (wheelSpeed + 256) % 256;\n                if (wheelDirection == '2') {\n                    wheelSpeed = (256 - wheelSpeed) % 256;\n                }\n\n                if (wheelSide == 1) {\n                    leftSpeed = wheelSpeed;\n                    rightSpeed = 127; // 속도제어 안함\n                } else if (wheelSide == 0) {\n                    leftSpeed = 127; // 속도제어 안함\n                    rightSpeed = wheelSpeed;\n                } else {\n                    leftSpeed = wheelSpeed;\n                    rightSpeed = wheelSpeed;\n                }\n\n                data_value = leftSpeed + rightSpeed * 256;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    25, //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_RCar_go_seperate(%1, %2)'],\n            },\n        },\n        robotis_Practice_drive_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '1'],\n                        [Lang.Blocks.robotis_right, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_direction_forward, '1'],\n                        [Lang.Blocks.robotis_direction_backward, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['15'],\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_drive_angle',\n            },\n            paramsKeyMap: {\n                WHEEL_SIDE: 0,\n                WHEEL_ANGLE: 1,\n                WHEEL_DIRECTION: 2,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                let wheelSide = script.getNumberValue('WHEEL_SIDE', script);\n                let wheelAngle = script.getNumberValue('WHEEL_ANGLE', script);\n                let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n                \n                const data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                let data_address = 580;\n                let data_length = 8;\n                let angleValue = 0;\n                let id = 51 + wheelSide;\n                let data_buf = [];\n                let i = 0;\n                let speed = 150;\n\n                if (wheelDirection == '2') {\n                    wheelAngle = -wheelAngle;\n                }\n\n                wheelAngle = Math.round(wheelAngle * 4096 / 360);\n\n                if (wheelAngle > 65535) wheelAngle = 65535;\n                else if (wheelAngle < -65535) wheelAngle = -65535;\n\n                angleValue = wheelAngle;\n                if (wheelAngle < 0) angleValue = 65536 + angleValue;\n                \n                data_buf.push(id);\n                data_buf.push(0);\n                data_buf.push(speed % 256);\n                data_buf.push(Math.floor(speed/256));\n                data_buf.push(angleValue % 256);\n                data_buf.push(Math.floor(angleValue/256) % 256);\n                if (wheelAngle >= 0) {\n                    data_buf.push(0);\n                    data_buf.push(0);\n                } else {\n                    data_buf.push(0xFF);\n                    data_buf.push(0xFF);\n                }\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_RCar_go_angle(%1, %2)'],\n            },\n        },\n        robotis_Practice_go_distance: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveF, '1'],\n                        [Lang.Blocks.robotis_moveB, '-1'], //Lang.Blocks.robotis_common_green_color\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_go_distance',\n            },\n            \n            paramsKeyMap: {\n                DISTANCE: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func(entity, script) {\n                var distance = script.getNumberValue('DISTANCE', script);\n                var direction = script.getField('DIRECTION', script);\n\n                if(distance > 1000) {\n                    distance = 1000;\n                } else if(distance < -1000) {\n                    distance = -1000;\n                }\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 270;\n                var data_length = 4;\n                var data_value = Math.floor(10 * distance * direction); \n        \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                data_sendqueue.push([data_instruction, 66, 2, 50491]);\n        \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 150 * Math.abs(distance) + 1200\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        },\n\n        robotis_Practice_turn_angle:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveL_in_place, '1'],\n                        [Lang.Blocks.robotis_moveR_in_place, '-1'],\n\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_turn_angle',\n            },\n            \n            paramsKeyMap: {\n                ANGLE: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func(entity, script) {\n                var angle = script.getNumberValue('ANGLE', script);\n                var direction = script.getNumberValue('DIRECTION', script);\n\n                angle *= direction;\n\n                if(angle > 720) {\n                    angle = 720;\n                } else if(angle < -720) {\n                    angle = -720;\n                }\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 270;\n                var data_length = 4;\n                var data_value = Math.floor(angle);\n        \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n            \n                data_sendqueue.push([data_instruction, 66, 2, 50492]);\n        \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + Math.abs(angle) * 16 + 1500\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        },\n        robotis_Practice_follow_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_slow, '1'],\n                        [Lang.Blocks.robotis_normal, '2'],\n                        [Lang.Blocks.robotis_fast, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_follow_line',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var speed_level = script.getNumberValue('SPEED', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 5200;\n                var data_length = 1;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        speed_level,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_follow_line(%1)'],\n            },\n        },\n        robotis_Practice_stop_at_cross: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_line_cross_type_5, '5'],\n                        [Lang.Blocks.robotis_line_cross_type_6, '6'],\n                        [Lang.Blocks.robotis_line_cross_type_7, '7'],\n                        [Lang.Blocks.robotis_line_cross_type_8, '8'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_stop_at_cross',\n            },\n            paramsKeyMap: {\n                CROSS: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: async function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cross_type = script.getNumberValue('CROSS', script);\n                var data_address = 5201;\n\n                // max 10 seconds\n                for (let i = 0; i < 100; i++) {\n                    await Entry.Utils.sleep(100);\n                    console.log(Entry.hw.portData[data_address]);\n                    if (Entry.hw.portData[data_address] == cross_type) {\n                        break;\n                    }\n                    if (Entry.engine.isState('stop') == true) {\n                        break;\n                    }\n                }\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE,\n                        5200,\n                        1,\n                        0,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_stop_at_cross(%1)'],\n            },\n        },\n        robotis_Practice_turn_at_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_moveL_in_place, '0'],\n                        [Lang.Blocks.robotis_moveR_in_place, '1'],\n                        [Lang.Blocks.robotis_moveU_in_place, '2'],\n\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_turn_at_line',\n            },\n            paramsKeyMap: {\n                TURN_TYPE: 0,\n            },\n            class: 'robotis_rb100_move',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var turn_type = script.getNumberValue('TURN_TYPE', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 66;\n                var data_length = 2;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        50045 + turn_type,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.rb100_follow_line(%1)'],\n            },\n        },\n        robotis_Practice_securitybot_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_securitybot_init',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 2110, 1, 1\n                    ]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    1100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.securitybot_init()'],\n            },\n        },\n        robotis_Practice_securitybot_hi: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_securitybot_hi',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 2111, 1, 1\n                    ]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    3000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.securitybot_hi()'],\n            },\n        },\n        robotis_Practice_securitybot_alert: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_securitybot_alert',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 2112, 1, 1\n                    ]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    3000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.securitybot_alert()'],\n            },\n        },\n        robotis_Practice_petbot_happy: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_petbot_happy',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 2121, 1, 1\n                    ]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    7100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.petbot_happy()'],\n            },\n        },\n        robotis_Practice_petbot_sad: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_petbot_sad',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 2122, 1, 1\n                    ]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    2500\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.petbot_sad()'],\n            },\n        },\n\n        \n        robotis_Practice_farmbot_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_farmbot_init',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 2130, 1, 1\n                    ]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    3000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.farmbot_init()'],\n            },\n        },\n        robotis_Practice_farmbot_seek: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_farmbot_seek',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 2131, 1, 1\n                    ]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.farmbot_seek()'],\n            },\n        },\n        robotis_Practice_farmbot_plant_type: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_plant_ripe, '1'],\n                        [Lang.Blocks.robotis_plant_unripe, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_farmbot_plant_type',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var compareValue = script.getNumberValue('TYPE');\n\n                var result = Entry.hw.portData[2134];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.farmbot_is_type(%1)'],\n            },\n        },\n        robotis_Practice_farmbot_harvest_or_not_and_go: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_harvest, '1'],\n                        [Lang.Blocks.robotis_not_harvest, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_farmbot_harvest_or_not_and_go',\n            },\n            paramsKeyMap: {\n                ACTION: 0,\n            },\n            class: 'robotis_rb100_practice_special',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n\n                let action = script.getNumberValue('ACTION', script);\n                let address = 2132;\n                let wait_time = 6000;\n\n                switch (action)\n                {\n                    case 1:\n                        address = 2132;\n                        wait_time = 6500;\n                        break;\n\n                    case 2:\n                        address = 2133;\n                        wait_time = 2100;\n                        break;\n                }\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, address, 1, 1\n                    ]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    wait_time\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.farmbot_harvest_or_not_and_go(%1)'],\n            },\n        },\n\n        \n\n\n        robotis_Practice_cm_ir_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_front_right, '360'],\n                        [Lang.Blocks.robotis_front_left, '362'],\n                        [Lang.Blocks.robotis_bottom_right, '364'],\n                        [Lang.Blocks.robotis_bottom_left, '366'],\n                        [Lang.Blocks.robotis_side_right, '368'],\n                        [Lang.Blocks.robotis_side_left, '370'],\n                    ],\n                    value: '360',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_Practice_cm_ir_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                var data_default_address = script.getNumberValue('VALUE');\n\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return Math.round((result % 65536) / 2);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_ir_value(%1)'],\n            },\n        },\n        robotis_Practice_cm_ir_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_front_right, '360'],\n                        [Lang.Blocks.robotis_front_left, '362'],\n                        [Lang.Blocks.robotis_bottom_right, '364'],\n                        [Lang.Blocks.robotis_bottom_left, '366'],\n                        [Lang.Blocks.robotis_side_right, '368'],\n                        [Lang.Blocks.robotis_side_left, '370'],\n                    ],\n                    value: '360',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_if_greater, '0'],\n                        [Lang.Blocks.robotis_if_smaller, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    50,\n                    null,\n                ],\n                type: 'robotis_Practice_cm_ir_compare',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                COMPARE_VAL: 1,\n                COMPARE_OP: 2,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('VALUE');\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n                \n                var result = Entry.hw.portData[data_address];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                result = Math.round((result % 65536) / 2);\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    default:\n                        return false;\n                }\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_ir_compare(%1)'],\n            },\n        },\n        robotis_Practice_detectFrontObj:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_front_ir_sensor, '0'],\n                        [Lang.Blocks.robotis_distance_sensor, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_front, '0'],\n                        [Lang.Blocks.robotis_right, '1'],\n                        [Lang.Blocks.robotis_left, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_detectFrontObj',\n            },\n            paramsKeyMap: {\n                SENSOR: 0,\n                DIRECTION: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.READ;\n                var data_address = 360;\n                var data_length = 4;\n                var data_value = 0;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                let sensorType = script.getNumberValue('SENSOR');\n                let direction = script.getNumberValue('DIRECTION');\n                let ir_1 = 0;\n                let ir_2 = 0;\n\n                if (sensorType == 0)\n                {\n                    if (direction == 0) {\n                        ir_1 = Entry.hw.portData[360];\n                        ir_2 = Entry.hw.portData[362];\n                        if (ir_1 == undefined) ir_1 = 0;\n                        if (ir_2 == undefined) ir_2 = 0;\n                        return ir_1 > 100 || ir_2 > 100;\n                    } else if (direction == 1) {\n                        ir_1 = Entry.hw.portData[368];\n                        if (ir_1 == undefined) ir_1 = 0;\n                        return ir_1 > 100;\n                    } else if (direction == 2) {\n                        ir_1 = Entry.hw.portData[370];\n                        if (ir_1 == undefined) ir_1 = 0;\n                        return ir_1 > 100;\n                    }\n                } else if (sensorType == 1) {\n                    data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_READ;\n                    data_address = 25;\n                    data_length = 2;\n                    data_value = 110; // id\n                    \n                    data_default_address = data_address;\n                    data_default_length = data_length;\n\n                    if (\n                        Entry.hw.sendQueue.prevAddress &&\n                        Entry.hw.sendQueue.prevAddress == data_default_address\n                    ) {\n                        if (\n                            Entry.hw.sendQueue.prevTime &&\n                            new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                        ) {\n                            //throw new Entry.Utils.AsyncError();\n                            if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                                return false;\n                            }\n                            return Entry.hw.sendQueue.prevResult < 200;\n                        }\n                    }\n\n                    Entry.Robotis_carCont.setRobotisData([\n                        [\n                            data_instruction,\n                            data_address,\n                            data_length,\n                            data_value,\n                            data_default_length,\n                        ],\n                    ]);\n                    // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                    Entry.Robotis_carCont.update();\n\n                    // 통합센서의 컨트롤 테이블 주소는 RB-100블록에서 사용하지 않는 주소를 사용\n                    // 주소 겹침 방지\n                    var result = Entry.hw.portData[data_default_address];\n                    if (result == undefined)\n                    {\n                        result = rb100_last_valid_value[data_default_address];\n                    }\n                    else\n                    {\n                        rb100_last_valid_value[data_default_address] = result;\n                    }\n                    Entry.hw.sendQueue.prevAddress = data_default_address;\n                    Entry.hw.sendQueue.prevTime = new Date();\n                    Entry.hw.sendQueue.prevResult = result;\n\n                    if(typeof result == 'undefined') {\n                        return false;\n                    } else {\n                        return result < 200;\n                    }\n                }\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_detectFrontObj()'],\n            },\n        },\n        robotis_Practice_cm_btn_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_blue, '47'],\n                        [Lang.Blocks.robotis_red, '44'],\n                    ],\n                    value: '47',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_cm_btn_value',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('VALUE');\n                var compareValue = 1;\n\n                var result = Entry.hw.portData[data_address];\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_btn_value(%1)'],\n            },\n        },\n        robotis_Practice_cm_joystick_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [ \n                        [Lang.Blocks.robotis_center, '0'],\n                        ['←', '1'],\n                        ['→', '2'],\n                        ['↑', '3'],\n                        ['↓', '4'],\n                        ['↖', '5'],\n                        ['↗', '6'],\n                        ['↙', '7'],\n                        ['↘', '8'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_Practice_cm_joystick_value',\n            },\n            paramsKeyMap: {\n                COMPARE_VAL: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 50;\n                var compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                var result = Entry.hw.portData[data_address];\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.openCM70_cm_joystick_value()'],\n            },\n        },\n        robotis_Practice_mic:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_Practice_mic',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: async function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 119;\n\n                var result = Entry.hw.portData[data_address];\n\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_mic()'],\n            },\n        },\n        robotis_Practice_detectSound_compare:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '1'],\n                        [Lang.Blocks.robotis_center, '0'],\n                        [Lang.Blocks.robotis_right, '255'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_detectSound_compare',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 5031;\n                var compareValue = script.getNumberValue('VALUE');\n\n\n                var result = Entry.hw.portData[data_address];\n                if(result == undefined) {\n                    return false;\n                }\n\n                return result == compareValue;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_detectSound_compare(%1)'],\n            },\n        },\n        robotis_Practice_imu:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['x', '78'],//72\n                        ['y', '80'],//74\n                        ['z', '82']//76\n                    ],\n                    value: '78',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_acceleration, '0'],//72\n                        [Lang.Blocks.robotis_gyro, '6'],//74\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null\n                ],\n                type: 'robotis_Practice_imu',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n                MODE: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getField('AXIS', script) - script.getField('MODE', script);\n\n                var result = Entry.hw.portData[data_address];\n\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_imu()'],\n            },\n        },\n        robotis_Practice_roll_pitch:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_roll, '70'],//72\n                        [Lang.Blocks.robotis_pitch, '88'],//74\n                    ],\n                    value: '70',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_roll_pitch',\n            },\n            paramsKeyMap: {\n                AXIS: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('AXIS');\n\n                var result = Entry.hw.portData[data_address];\n\n                if(typeof result == 'undefined') {\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_roll_pitch(%1)'],\n            },\n        },\n        robotis_Practice_distance_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_distance, '25'],\n                        [Lang.Blocks.robotis_sensing_button, '24'],\n                    ],\n                    value: '25',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_distance_value',\n            },\n            paramsKeyMap: {\n                ADDR: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_value = 110;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                \n                data_address = script.getNumberValue('ADDR');\n\n                if (data_address == 24) data_length = 1;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < Entry.Robotis_openCM70.readDelay\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                        if(typeof Entry.hw.sendQueue.prevResult == 'undefined') {\n                            return 0;\n                        }\n                        return Entry.hw.sendQueue.prevResult;\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                        data_default_length,\n                    ],\n                ]);\n                // Entry.hw.socket.send(JSON.stringify(Entry.hw.sendQueue));\n                Entry.Robotis_carCont.update();\n\n                // 통합센서의 컨트롤 테이블 주소는 RB-100블록에서 사용하지 않는 주소를 사용\n                // 주소 겹침 방지\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_distance_value(%1)'],\n            },\n        },\n        robotis_Practice_distance_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_distance, '25'],\n                        [Lang.Blocks.robotis_sensing_button, '24'],\n                    ],\n                    value: '25',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_if_greater, '0'],\n                        [Lang.Blocks.robotis_if_smaller, '1'],\n                        [Lang.Blocks.robotis_if_equal, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: [0]\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_distance_compare',\n            },\n            paramsKeyMap: {\n                ADDR: 0,\n                COMPARE_VAL: 1,\n                COMPARE_OP: 2,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_READ;\n                var data_address = 0;\n                var data_length = 2;\n                var data_id = 110;\n\n                var data_default_address = 0;\n                var data_default_length = 0;\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n\n                data_address = script.getNumberValue('ADDR');\n\n                if (data_address == 24) data_length = 1;\n\n                data_default_address = data_address;\n                data_default_length = data_length;\n\n                if (\n                    Entry.hw.sendQueue.prevAddress &&\n                    Entry.hw.sendQueue.prevAddress == data_default_address\n                ) {\n                    if (\n                        Entry.hw.sendQueue.prevTime &&\n                        new Date() - Entry.hw.sendQueue.prevTime < 200//Entry.Robotis_openCM70.readDelay//200\n                    ) {\n                        //throw new Entry.Utils.AsyncError();\n                \n                        //  return false;\n                        switch(compareOP) {\n                            case 0:\n                                return Entry.hw.sendQueue.prevResult > compareValue;\n                            case 1:\n                                return Entry.hw.sendQueue.prevResult < compareValue;\n                            case 2:\n                                return Entry.hw.sendQueue.prevResult == compareValue;\n                            default:\n                                return false;\n                        }\n                    }\n                }\n\n                Entry.Robotis_carCont.setRobotisData([\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_id,\n                        data_default_length,\n                    ],\n                ]);\n                \n                \n                Entry.Robotis_carCont.update();\n\n                \n                // 통합센서의 컨트롤 테이블 주소는 RB-100블록에서 사용하지 않는 주소를 사용\n                // 주소 겹침 방지\n                var result = Entry.hw.portData[data_default_address];\n                if (result == undefined)\n                {\n                    result = rb100_last_valid_value[data_default_address];\n                }\n                else\n                {\n                    rb100_last_valid_value[data_default_address] = result;\n                }\n                Entry.hw.sendQueue.prevAddress = data_default_address;\n                Entry.hw.sendQueue.prevTime = new Date();\n                Entry.hw.sendQueue.prevResult = result;\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                    default:\n                        return false;\n                }\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_distance_compare(%1)'],\n            },\n        },\n        robotis_Practice_environment_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_temperature, '28'],\n                        [Lang.Blocks.robotis_sensing_humidity, '29'],\n                        [Lang.Blocks.robotis_sensing_brightness, '30'],\n                        [Lang.Blocks.robotis_sensing_motion, '27'],\n                    ],\n                    value: '28',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null\n                ],\n                type: 'robotis_Practice_environment_value',\n            },\n            paramsKeyMap: {\n                ADDR: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = script.getNumberValue('ADDR');\n                let device_id_name = \"\";\n\n                switch (data_address) {\n                    case 28:\n                        device_id_name = \"PIR_100_TEMPERATURE\";\n                        break;\n                    \n                    case 29:\n                        device_id_name = \"PIR_100_HUMIDITY\";\n                        break;\n                        \n                    case 30:\n                        device_id_name = \"PIR_100_BRIGHTNESS\";\n                        break;\n\n                    case 27:\n                        device_id_name = \"PIR_100_PIR\";\n                        break;\n                }\n\n                var result = Entry.hw.portData[device_id_name];\n\n                if(typeof result == 'undefined') {\n\n                    return 0;\n                }\n                else {\n                    if (device_id_name == \"PIR_100_TEMPERATURE\") {\n                        result = result % 256;\n                        if (result > 128) {\n                            result = result - 256;\n                        }\n                    }\n                }\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_environment_value(%1)'],\n            },\n        },\n        robotis_Practice_environment_compare: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_sensing_temperature, '28'],\n                        [Lang.Blocks.robotis_sensing_humidity, '29'],\n                        [Lang.Blocks.robotis_sensing_brightness, '30'],\n                        [Lang.Blocks.robotis_sensing_motion, '27'],\n                    ],\n                    value: '28',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: 'asdfasdf',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_if_greater, '0'],\n                        [Lang.Blocks.robotis_if_smaller, '1'],\n                        [Lang.Blocks.robotis_if_equal, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: [0]\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_environment_compare',\n            },\n            paramsKeyMap: {\n                ADDR: 0,\n                COMPARE_VAL: 1,\n                COMPARE_OP: 2,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                var data_address = script.getNumberValue('ADDR');\n                var compareValue = script.getNumberValue('COMPARE_VAL');\n                var compareOP = script.getNumberValue('COMPARE_OP');\n\n                let device_id_name = \"\";\n\n                switch (data_address) {\n                    case 28:\n                        device_id_name = \"PIR_100_TEMPERATURE\";\n                        break;\n                    \n                    case 29:\n                        device_id_name = \"PIR_100_HUMIDITY\";\n                        break;\n                        \n                    case 30:\n                        device_id_name = \"PIR_100_BRIGHTNESS\";\n                        break;\n\n                    case 27:\n                        device_id_name = \"PIR_100_PIR\";\n                        break;\n                }\n\n                var result = Entry.hw.portData[device_id_name];\n                if (typeof result == 'undefined') {\n                    return false;\n                }\n\n                switch(compareOP) {\n                    case 0:\n                        return result > compareValue;\n                    case 1:\n                        return result < compareValue;\n                    case 2:\n                        return result == compareValue;\n                    default:\n                        return false;\n                }\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_RB_cm_environment_compare(%1)'],\n            },\n        },\n        robotis_Practice_dxl_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left_wheel, '52'],\n                        [Lang.Blocks.robotis_right_wheel, '51'],\n                        [\"ID 1\", '1'],\n                        [\"ID 2\", '2'],\n                        [\"ID 3\", '3'],\n                        [\"ID 4\", '4'],\n                        [\"ID 5\", '5'],\n                        [\"ID 6\", '6'],\n                        [\"ID 7\", '7'],\n                        [\"ID 8\", '8'],\n                    ],\n                    value: '52',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_dxl_value_angle, '1'],\n                        [Lang.Blocks.robotis_dxl_value_velocity, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    52,\n                    null,\n                ],\n                type: 'robotis_Practice_dxl_value',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                var dxl_id = script.getNumberValue('ID');\n                //var data_type = script.getNumberValue('TYPE');\n                let device_id_name = `DXL_POS_${dxl_id}`;\n\n                var result = Entry.hw.portData[device_id_name];\n\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n                result = 180 - Math.round(result * 360 / 4096);\n                while (result < -180) result += 360;\n                while (result > 180) result -= 360;\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.get_dxl_value(%1)'],\n            },\n        },\n        robotis_Practice_line_cross_compare:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_line_cross_type_5, '5'],\n                        [Lang.Blocks.robotis_line_cross_type_6, '6'],\n                        [Lang.Blocks.robotis_line_cross_type_7, '7'],\n                        [Lang.Blocks.robotis_line_cross_type_8, '8'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_line_cross_compare',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'robotis_rb100_custom',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 5201;\n                var compareValue = script.getNumberValue('VALUE');\n\n                var result = Entry.hw.portData[data_address];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n\n                return result == compareValue;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_line_cross_compare(%1)'],\n            },\n        },\n\n\n\n        \n        robotis_Practice_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_kkokdu, '3'],\n                        [Lang.Blocks.robotis_rla, '2'],\n                        [Lang.Blocks.robotis_rgee, '0'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_car_anim01, '2817'],\n                        [Lang.Blocks.robotis_car_anim02, '2818'],\n                        [Lang.Blocks.robotis_car_anim03, '2819'],\n                        [Lang.Blocks.robotis_car_anim04, '2820'],\n                        [Lang.Blocks.robotis_car_anim05, '2821'],\n\n                        [Lang.Blocks.robotis_car_anim06, '2822'],\n                        //[Lang.Blocks.robotis_car_anim07, '2823'], \n                        [Lang.Blocks.robotis_car_anim08, '2824'],\n                        [Lang.Blocks.robotis_car_anim09, '2825'],\n                        [Lang.Blocks.robotis_car_anim10, '2826'],\n\n                        [Lang.Blocks.robotis_car_anim11, '2827'],\n                        [Lang.Blocks.robotis_car_anim12, '2828'], \n                        //[Lang.Blocks.robotis_car_anim13, '2829'],\n                        [Lang.Blocks.robotis_car_anim14, '2830'],\n                        [Lang.Blocks.robotis_car_anim15, '2831'],\n\n                        [Lang.Blocks.robotis_car_anim16, '2832'],\n                        [Lang.Blocks.robotis_car_anim17, '2833'], \n                        [Lang.Blocks.robotis_car_anim18, '2834'],\n                        [Lang.Blocks.robotis_car_anim19, '2835'],\n                    ],\n                    value: '2817',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_screen',\n            },\n            paramsKeyMap: {\n                ROBOT_TYPE: 0,\n                BACKGROUND: 1,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var robotType = script.getNumberValue('ROBOT_TYPE', script);\n                var screenValue = script.getNumberValue('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue + robotType * 256;\n\n                if (robotType == 0) {\n                    switch (screenValue) {\n                        case 2817:\n                            data_value = 2841;\n                            break;\n                        \n                        case 2818:\n                            data_value = 2842;\n                            break;\n                        \n                        case 2819:\n                            data_value = 2820;\n                            break;\n                            \n                        case 2820:\n                            data_value = 2817;\n                            break;\n                        \n                        case 2821:\n                            data_value = 2819;\n                            break;\n                        \n                        case 2822:\n                            data_value = 2818;\n                            break;\n                        \n                        //case 2823:\n                        //    break;\n                        \n                        case 2824:\n                            data_value = 2826;\n                            break;\n                        \n                        case 2825:\n                            data_value = 2836;\n                            break;\n                        \n                        case 2826:\n                            data_value = 2837;\n                            break;\n                        \n                        case 2827:\n                            data_value = 2843;\n                            break;\n                        \n                        case 2828:\n                            data_value = 2831;\n                            break;\n                        \n                        //case 2829:\n                        //    break;\n                        \n                        case 2830:\n                            data_value = 2833;\n                            break;\n                            \n                        case 2831:\n                            data_value = 2834;\n                            break;\n                            \n                        case 2832:\n                            data_value = 2828;\n                            break;\n                            \n                        case 2833:\n                            data_value = 2827;\n                            break;\n                            \n                        case 2834:\n                            data_value = 2829;\n                            break;\n                            \n                        case 2835:\n                            data_value = 2840;\n                            break;\n                        \n                        default:\n                            data_value = 2841;\n                            break;\n                    }\n                }\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_screen(%1)'] },\n        },\n\n        robotis_Practice_anim_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_kkokdu, '1'],\n                        [Lang.Blocks.robotis_rla, '0'],\n                        [Lang.Blocks.robotis_rgee, '-1'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_car_anim01, '30978'],\n                        [Lang.Blocks.robotis_car_anim02, '30981'],\n                        //[Lang.Blocks.robotis_car_anim03, '30982'],\n                        [Lang.Blocks.robotis_car_anim04, '30983'],\n                        [Lang.Blocks.robotis_car_anim05, '30984'],\n\n                        [Lang.Blocks.robotis_car_anim06, '30985'],\n                        [Lang.Blocks.robotis_car_anim07, '30986'], \n                        [Lang.Blocks.robotis_car_anim08, '30987'],\n                        [Lang.Blocks.robotis_car_anim09, '30988'],\n                        [Lang.Blocks.robotis_car_anim10, '30989'],\n\n                        [Lang.Blocks.robotis_car_anim11, '30990'],\n                        [Lang.Blocks.robotis_car_anim12, '30991'], \n                        //[Lang.Blocks.robotis_car_anim13, '30992'],\n                        [Lang.Blocks.robotis_car_anim14, '30993'],\n                        [Lang.Blocks.robotis_car_anim15, '30994'],\n\n                        [Lang.Blocks.robotis_car_anim16, '30995'],\n                        [Lang.Blocks.robotis_car_anim17, '30996'], \n                        [Lang.Blocks.robotis_car_anim18, '30997'],\n                        [Lang.Blocks.robotis_car_anim19, '30998'],\n                    ],\n                    value: '30978',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_anim_screen',\n            },\n            paramsKeyMap: {\n                ROBOT_TYPE: 0,\n                BACKGROUND: 1,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var robotType = script.getNumberValue('ROBOT_TYPE', script);\n                var screenValue = script.getNumberValue('BACKGROUND', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = screenValue;\n\n                if (robotType >= 0) {\n                    data_value += 256 * robotType;\n                } else {\n                    switch (screenValue) {\n                        case 30978:\n                            data_value = 30724;\n                            break;\n                        \n                        case 30981:\n                            data_value = 30761;\n                            break;\n                        \n                        //case 30982:\n                        //    break;\n                            \n                        case 30983:\n                            data_value = 30748;\n                            break;\n                        \n                        case 30984:\n                            data_value = 30750;\n                            break;\n                        \n                        case 30985:\n                            data_value = 30749;\n                            break;\n                        \n                        //case 30986:\n                        //    break;\n                        \n                        case 30987:\n                            data_value = 30739;\n                            break;\n                        \n                        case 30988:\n                            data_value = 30751;\n                            break;\n                        \n                        case 30989:\n                            data_value = 30752;\n                            break;\n                        \n                        case 30990:\n                            data_value = 30762;\n                            break;\n                        \n                        case 30991:\n                            data_value = 30736;\n                            break;\n                        \n                        //case 30992:\n                        //    break;\n                        \n                        case 30993:\n                            data_value = 30742;\n                            break;\n                            \n                        case 30994:\n                            data_value = 30743;\n                            break;\n                            \n                        case 30995:\n                            data_value = 30734;\n                            break;\n                            \n                        case 30996:\n                            data_value = 30733;\n                            break;\n                            \n                        case 30997:\n                            data_value = 30732;\n                            break;\n                            \n                        case 30998:\n                            data_value = 30760;\n                            break;\n                        \n                        default:\n                            data_value = 30724;\n                            break;\n                    }\n                }\n\n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1]\n                ];\n              \n\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay //+ 1000\n                );\n            },\n            syntax: { js: [], py: ['Robotis.opencm70_cm_screen(%1)'] },\n        },\n        robotis_Practice_icon_screen_food_plant: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_food_plant_1, '10496'],\n                        [Lang.Blocks.robotis_icon_food_plant_2, '10497'],\n                        [Lang.Blocks.robotis_icon_food_plant_3, '10498'],\n                        [Lang.Blocks.robotis_icon_food_plant_4, '10499'],\n                        [Lang.Blocks.robotis_icon_food_plant_5, '10500'],\n                        [Lang.Blocks.robotis_icon_food_plant_6, '10501'],\n                        [Lang.Blocks.robotis_icon_food_plant_7, '10502'],\n                        [Lang.Blocks.robotis_icon_food_plant_8, '10503'],\n                        [Lang.Blocks.robotis_icon_food_plant_9, '10504'],\n                        [Lang.Blocks.robotis_icon_food_plant_10, '10505'],\n                        [Lang.Blocks.robotis_icon_food_plant_11, '10506'],\n                        [Lang.Blocks.robotis_icon_food_plant_12, '10507'],\n                        [Lang.Blocks.robotis_icon_food_plant_13, '10508'],\n                        [Lang.Blocks.robotis_icon_food_plant_14, '10509'],\n                        [Lang.Blocks.robotis_icon_food_plant_15, '10510'],\n                        [Lang.Blocks.robotis_icon_food_plant_16, '10511'],\n                        [Lang.Blocks.robotis_icon_food_plant_17, '10512'],\n                        [Lang.Blocks.robotis_icon_food_plant_18, '10513'],\n                        [Lang.Blocks.robotis_icon_food_plant_19, '10514'],\n                        [Lang.Blocks.robotis_icon_food_plant_20, '10515'],\n                        [Lang.Blocks.robotis_icon_food_plant_21, '10516'],\n                        [Lang.Blocks.robotis_icon_food_plant_22, '10517'],\n                        [Lang.Blocks.robotis_icon_food_plant_23, '10518'],\n                        [Lang.Blocks.robotis_icon_food_plant_24, '10519'],\n                    ],\n                    value: '10496',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_Practice_icon_screen_food_plant',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script) * 2;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.icon_screen_food_and_plant(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_Practice_icon_screen_animal_human: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_animal_human_1, '10752'],\n                        [Lang.Blocks.robotis_icon_animal_human_2, '10753'],\n                        [Lang.Blocks.robotis_icon_animal_human_3, '10754'],\n                        [Lang.Blocks.robotis_icon_animal_human_4, '10755'],\n                        [Lang.Blocks.robotis_icon_animal_human_5, '10756'],\n                        [Lang.Blocks.robotis_icon_animal_human_6, '10757'],\n                        [Lang.Blocks.robotis_icon_animal_human_7, '10758'],\n                        [Lang.Blocks.robotis_icon_animal_human_8, '10759'],\n                        [Lang.Blocks.robotis_icon_animal_human_9, '10760'],\n                        [Lang.Blocks.robotis_icon_animal_human_10, '11787'],\n                        [Lang.Blocks.robotis_icon_animal_human_11, '11788'],\n                        [Lang.Blocks.robotis_icon_animal_human_12, '11789'],\n                        [Lang.Blocks.robotis_icon_animal_human_13, '11790'],\n                        [Lang.Blocks.robotis_icon_animal_human_14, '11805'],\n                        [Lang.Blocks.robotis_icon_animal_human_15, '11806'],\n                        [Lang.Blocks.robotis_icon_animal_human_16, '11807'],\n                        [Lang.Blocks.robotis_icon_animal_human_17, '11808'],\n                        [Lang.Blocks.robotis_icon_animal_human_18, '10761'],\n                        [Lang.Blocks.robotis_icon_animal_human_19, '10762'],\n                        [Lang.Blocks.robotis_icon_animal_human_20, '10763'],\n                        [Lang.Blocks.robotis_icon_animal_human_21, '10764'],\n                        [Lang.Blocks.robotis_icon_animal_human_22, '10765'],\n                        [Lang.Blocks.robotis_icon_animal_human_23, '10766'],\n                        [Lang.Blocks.robotis_icon_animal_human_24, '10767'],\n                        [Lang.Blocks.robotis_icon_animal_human_25, '10768'],\n                        [Lang.Blocks.robotis_icon_animal_human_26, '10769'],\n                        [Lang.Blocks.robotis_icon_animal_human_27, '10770'],\n                        [Lang.Blocks.robotis_icon_animal_human_28, '10771'],\n                        [Lang.Blocks.robotis_icon_animal_human_29, '10772'],\n                        [Lang.Blocks.robotis_icon_animal_human_30, '10773'],\n                        [Lang.Blocks.robotis_icon_animal_human_31, '10774'],\n                        [Lang.Blocks.robotis_icon_animal_human_32, '10775'],\n                        [Lang.Blocks.robotis_icon_animal_human_33, '10776'],\n                        [Lang.Blocks.robotis_icon_animal_human_34, '10777'],\n                    ],\n                    value: '10752',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_Practice_icon_screen_animal_human',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script) * 2;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.icon_screen_animal_and_human(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_Practice_icon_screen_object_tool: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_object_tool_1, '11008'],\n                        [Lang.Blocks.robotis_icon_object_tool_2, '11009'],\n                        [Lang.Blocks.robotis_icon_object_tool_3, '11010'],\n                        [Lang.Blocks.robotis_icon_object_tool_4, '11011'],\n                        [Lang.Blocks.robotis_icon_object_tool_5, '11012'],\n                        [Lang.Blocks.robotis_icon_object_tool_6, '11013'],\n                        [Lang.Blocks.robotis_icon_object_tool_7, '11014'],\n                        [Lang.Blocks.robotis_icon_object_tool_8, '11015'],\n                        [Lang.Blocks.robotis_icon_object_tool_9, '11016'],\n                        [Lang.Blocks.robotis_icon_object_tool_10, '11017'],\n                        [Lang.Blocks.robotis_icon_object_tool_11, '11018'],\n                        [Lang.Blocks.robotis_icon_object_tool_12, '11019'],\n                        [Lang.Blocks.robotis_icon_object_tool_13, '11020'],\n                        [Lang.Blocks.robotis_icon_object_tool_14, '11021'],\n                        [Lang.Blocks.robotis_icon_object_tool_15, '11022'],\n                        [Lang.Blocks.robotis_icon_object_tool_16, '11023'],\n                        [Lang.Blocks.robotis_icon_object_tool_17, '11024'],\n                        [Lang.Blocks.robotis_icon_object_tool_18, '11025'],\n                        [Lang.Blocks.robotis_icon_object_tool_19, '11026'],\n                        [Lang.Blocks.robotis_icon_object_tool_20, '11027'],\n                        [Lang.Blocks.robotis_icon_object_tool_21, '11028'],\n                        [Lang.Blocks.robotis_icon_object_tool_22, '11029'],\n                        [Lang.Blocks.robotis_icon_object_tool_23, '11030'],\n                        [Lang.Blocks.robotis_icon_object_tool_24, '11031'],\n                        [Lang.Blocks.robotis_icon_object_tool_25, '11032'],\n                        [Lang.Blocks.robotis_icon_object_tool_26, '11033'],\n                        [Lang.Blocks.robotis_icon_object_tool_27, '11034'],\n                        [Lang.Blocks.robotis_icon_object_tool_28, '11035'],\n                        [Lang.Blocks.robotis_icon_object_tool_29, '11036'],\n                        [Lang.Blocks.robotis_icon_object_tool_30, '11037'],\n                        [Lang.Blocks.robotis_icon_object_tool_31, '11038'],\n                        [Lang.Blocks.robotis_icon_object_tool_32, '11039'],\n                        [Lang.Blocks.robotis_icon_object_tool_33, '11040'],\n                        [Lang.Blocks.robotis_icon_object_tool_34, '11801'],\n                        [Lang.Blocks.robotis_icon_object_tool_35, '11802'],\n                        [Lang.Blocks.robotis_icon_object_tool_36, '11809'],\n                    ],\n                    value: '11008',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_Practice_icon_screen_object_tool',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script) * 2;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.icon_screen_object_and_tool(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_Practice_icon_screen_vehicle_number: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_vehicle_number_1, '11264'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_2, '11265'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_3, '11266'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_4, '11267'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_5, '11268'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_6, '11269'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_7, '11270'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_8, '11271'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_9, '11272'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_10, '11273'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_11, '11274'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_12, '11275'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_13, '11276'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_14, '11776'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_15, '11777'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_16, '11778'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_17, '11779'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_18, '11780'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_19, '11781'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_20, '11782'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_21, '11783'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_22, '11277'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_23, '11278'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_24, '11279'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_25, '11280'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_26, '11281'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_27, '11282'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_28, '11283'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_29, '11284'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_30, '11285'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_31, '11286'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_32, '11287'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_33, '11288'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_34, '11289'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_35, '11290'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_36, '11291'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_37, '11292'],\n                        [Lang.Blocks.robotis_icon_vehicle_number_38, '11293'],\n                    ],\n                    value: '11264',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_Practice_icon_screen_vehicle_number',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var iconNum = script.getField('ICON', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var size = script.getNumberValue('SIZE', script) * 2;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 166;\n                var data_length = 2;\n                var data_value = 10496;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                if (size < 0) size = 0;\n                else if (size > 400) size = 400;\n               \n                data_value = iconNum;\n\n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.icon_screen_vehicle_and_number(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_Practice_icon_screen_game_character: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_icon_game_character_1, '11520'], // 알쥐(정면)\n                        [Lang.Blocks.robotis_icon_game_character_2, '11521'], // 알쥐(왼쪽)\n                        [Lang.Blocks.robotis_icon_game_character_3, '11522'], // 알쥐(오른쪽)\n                        [Lang.Blocks.robotis_icon_game_character_4, '11523'], // 알라(정면)\n                        [Lang.Blocks.robotis_icon_game_character_5, '11524'], // 알라(왼쪽)\n                        [Lang.Blocks.robotis_icon_game_character_6, '11525'], // 알라(오른쪽)\n                        [Lang.Blocks.robotis_icon_game_character_7, '11526'], // 유령\n                        [Lang.Blocks.robotis_icon_game_character_8, '11527'], // 괴물\n                        [Lang.Blocks.robotis_icon_game_character_9, '11528'], // 바이러스\n                        [Lang.Blocks.robotis_icon_game_character_10, '11529'], // 세균\n                        [Lang.Blocks.robotis_icon_game_character_11, '11784'], // 나는 알쥐(L)\n                        [Lang.Blocks.robotis_icon_game_character_12, '11785'], // 나는 알쥐(R)\n                        [Lang.Blocks.robotis_icon_game_character_13, '11786'], // 나는 알쥐(U)\n                        [Lang.Blocks.robotis_icon_game_character_14, '11530'], // 메달\n                        [Lang.Blocks.robotis_icon_game_character_15, '11531'], // 돈(G)\n                        [Lang.Blocks.robotis_icon_game_character_16, '11532'], // 돈($)\n                        [Lang.Blocks.robotis_icon_game_character_17, '11533'], // 하트\n                        [Lang.Blocks.robotis_icon_game_character_18, '11534'], // 포탄\n                        [Lang.Blocks.robotis_icon_game_character_19, '11535'], // 불\n                        [Lang.Blocks.robotis_icon_game_character_20, '11803'], // 구름1\n                        [Lang.Blocks.robotis_icon_game_character_21, '11804'], // 구름2\n                        [Lang.Blocks.robotis_icon_game_character_22, '11536'], // 포탄1\n                        [Lang.Blocks.robotis_icon_game_character_23, '11791'], // 포탄2\n                        [Lang.Blocks.robotis_icon_game_character_24, '11537'], // 대포(수평)\n                        [Lang.Blocks.robotis_icon_game_character_25, '11538'], // 대포(수직)\n                        [Lang.Blocks.robotis_icon_game_character_27, '11540'], // 레이저(수평)\n                        [Lang.Blocks.robotis_icon_game_character_26, '11539'], // 레이저(수직)\n                        [Lang.Blocks.robotis_icon_game_character_28, '11541'], // 화살(수평)\n                        [Lang.Blocks.robotis_icon_game_character_29, '11542'], // 화살(수직)\n                        [Lang.Blocks.robotis_icon_game_character_30, '11792'], // 미사일(U)\n                        [Lang.Blocks.robotis_icon_game_character_31, '11793'], // 미사일(D)\n                        [Lang.Blocks.robotis_icon_game_character_32, '11794'], // 미사일(L)\n                        [Lang.Blocks.robotis_icon_game_character_33, '11795'], // 미사일(R)\n                        [Lang.Blocks.robotis_icon_game_character_34, '11796'], // 낙하산\n                        [Lang.Blocks.robotis_icon_game_character_35, '11543'], // 폭발1\n                        [Lang.Blocks.robotis_icon_game_character_36, '11544'], // 폭발2\n                        [Lang.Blocks.robotis_icon_game_character_37, '11810'], // 조준경\n                        [Lang.Blocks.robotis_icon_game_character_38, '11545'], // 가위\n                        [Lang.Blocks.robotis_icon_game_character_39, '11546'], // 바위\n                        [Lang.Blocks.robotis_icon_game_character_40, '11547'], // 보\n                        [Lang.Blocks.robotis_icon_game_character_41, '11797'], // 걷는 사람1\n                        [Lang.Blocks.robotis_icon_game_character_42, '11798'], // 걷는 사람2\n                        [Lang.Blocks.robotis_icon_game_character_43, '11799'], // 뛰는 사람1\n                        [Lang.Blocks.robotis_icon_game_character_44, '11800'], // 뛰는 사람2\n                    ],\n                    value: '11520',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    50,\n                    null,\n                ],\n                type: 'robotis_Practice_icon_screen_game_character',\n            },\n            paramsKeyMap: {\n                ICON: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func(sprite, script) {\n                // instruction / address / length / value / default length\n                let iconNum = script.getField('ICON', script);\n                let x = script.getNumberValue('X', script);\n                let y = script.getNumberValue('Y', script);\n                let size = script.getNumberValue('SIZE', script) * 2;\n\n                let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                let data_address = 166;\n                let data_length = 2;\n                let data_value = 10496;\n\n                if (x < -160) {\n                    x = -160;\n                } else if (x > 160) {\n                    x = 160;\n                }\n\n                if (y < -120) {\n                    y = -120;\n                } else if (y > 120) {\n                    y = 120;\n                }\n\n                if (size < 0) {\n                    size = 0;\n                } else if (size > 400) {\n                    size = 400;\n                }\n\n                data_value = iconNum;\n\n                let data_sendqueue = [\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size],\n                    [data_instruction, data_address, data_length, data_value],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.icon_screen_game_and_character(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_Practice_text_screen: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_screen_text_font_small, '0'],\n                        [Lang.Blocks.robotis_screen_text_font_big, '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \" \",\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_text_screen',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                X: 1,\n                Y: 2,\n                FONT: 3,\n                COLOR: 4,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var text = script.getStringValue('TEXT', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var font = script.getNumberValue('FONT', script);\n                var color = script.getNumberValue('COLOR', script);\n                var data_buf = [];\n                var i = 0;\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 900;\n                var data_length = 2;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                var encoder = new TextEncoder('utf-8');\n                var byteArray = encoder.encode(text);\n\n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(font);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(color);\n                data_buf.push(byteArray.length);\n                for (i = 0; i < byteArray.length; i++) {\n                    data_buf.push(byteArray[i]);\n                }\n               \n                data_length = 9 + byteArray.length;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 200\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_text_screen(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_Practice_pixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_pixel',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                COLOR: 2,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var color = script.getNumberValue('COLOR', script);\n                var data_buf = [];\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 130;\n                var data_length = 11;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n\n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(0);\n                data_buf.push(color);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 161, 2, 1 * 256 + 8\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_text_screen(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_Practice_text_screen_redraw: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \" \",\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'robotis_Practice_text_screen_redraw',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                X: 1,\n                Y: 2,\n                COLOR: 3,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var text = script.getStringValue('TEXT', script);\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var font = 0;\n                var color = script.getNumberValue('COLOR', script);\n                var data_buf = [];\n                var i = 0;\n            \n                if (x < -160) x = -160;\n                else if (x > 160) x = 160;\n                \n                if (y < -120) y = -120;\n                else if (y > 120) y = 120;\n                \n                var encoder = new TextEncoder('utf-8');\n                var byteArray = encoder.encode(text);\n\n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(font);\n                data_buf.push(1);\n                data_buf.push(bg_color);\n                data_buf.push(color);\n                data_buf.push(byteArray.length);\n                for (i = 0; i < byteArray.length; i++) {\n                    data_buf.push(byteArray[i]);\n                }\n               \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 900;\n                var data_length = 9 + byteArray.length;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1\n                    ]\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_text_screen(%1,%2,%3,%4)'],\n            },\n        },\n        robotis_Practice_LCDBright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    50,\n                ],\n                type: 'robotis_Practice_LCDBright',\n            },\n            paramsKeyMap: {\n                BRIGHT: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var bright = script.getNumberValue('BRIGHT', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 180;\n                var data_length = 1;\n                var data_value = 0;\n\n                bright = Math.min(Math.max(bright, 0), 100);\n                \n                data_value = bright;\n                \n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_LCDBright(%1)'],\n            },\n        },\n        robotis_Practice_LCDColor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '224',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_LCDColor',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var color = script.getNumberValue('COLOR', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 163;\n                var data_length = 2;\n                var data_value = 0;\n                \n                data_value = color;\n                bg_color = color;\n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 2817\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1]\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_LCDColor(%1)'],\n            },\n        },\n        robotis_Practice_LCD_Flash: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '224',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_red, '224'],\n                        [Lang.Blocks.robotis_orange, '244'],\n                        [Lang.Blocks.robotis_yellow, '252'],\n                        [Lang.Blocks.robotis_green, '28'],\n                        [Lang.Blocks.robotis_blue, '3'],\n                        [Lang.Blocks.robotis_darkblue, '2'],\n                        [Lang.Blocks.robotis_purple, '130'],\n                        [Lang.Blocks.robotis_brown, '173'],\n                        [Lang.Blocks.robotis_black, '0'],\n                        [Lang.Blocks.robotis_white, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [0.3, '3'],\n                        [0.4, '4'],\n                        [0.5, '5'],\n                        [0.6, '6'],\n                        [0.7, '7'],\n                        [0.8, '8'],\n                        [0.9, '9'],\n                        [1.0, '10'],\n                        [1.1, '11'],\n                        [1.2, '12'],\n                        [1.3, '13'],\n                        [1.4, '14'],\n                        [1.5, '15'],\n                        [1.6, '16'],\n                        [1.7, '17'],\n                        [1.8, '18'],\n                        [1.9, '19'],\n                        [2.0, '20'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_LCD_Flash',\n            },\n            paramsKeyMap: {\n                COLOR_ON: 0,\n                COLOR_OFF: 1,\n                PERIOD: 2,\n            },\n            class: 'robotis_rb100_lcd',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                const color_on = script.getNumberValue('COLOR_ON', script);\n                const color_off = script.getNumberValue('COLOR_OFF', script);\n                const period = script.getNumberValue('PERIOD', script);\n                const colors = color_on + (color_off << 8);\n\n                // 0x8000: use flashing mode, \n                // (period << 8): on time (0.1 sec)\n                // period: off time (0.1 sec)\n                const time_parameter = 0x8000 + (period << 8) + period; \n                \n                var data_sendqueue = [\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 158, 2, colors\n                    ],\n                    [\n                        Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, time_parameter\n                    ],\n                ];\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay + 100\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_LCD_Flash(%1, %2, %3)'],\n            },\n        },\n\n        \n        robotis_Practice_cm_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left, '1'],\n                        [Lang.Blocks.robotis_right, '2'],\n                        [Lang.Blocks.robotis_both, '3'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_common_on, '1'],\n                        [Lang.Blocks.robotis_common_off, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotis_Practice_cm_led',\n            },\n            paramsKeyMap: {\n                RB_LED: 0,\n                VALUE: 1,\n            },\n            class: 'robotis_rb100_led',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmLed = script.getField('RB_LED', script);\n                var value = script.getField('VALUE', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 40;\n                var data_length = 1;\n                var data_value = 0;\n\n                if (cmLed == 1) {\n                    data_value = 200 * value;\n                } else if (cmLed == 2) {\n                    data_address = 41;\n                    data_value = 200 * value;\n                } else if (cmLed == 3) {\n                    data_address = 40;\n                    data_length = 2;\n                    data_value = 200 * 257 * value;\n                } else {\n                    data_value = value * cmLed;\n                }\n              \n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.RB100_led(%1, %2)'] },\n        },\n        robotis_Practice_cm_led_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_pattern1, '11'],\n                        [Lang.Blocks.robotis_pattern2, '21'],\n                        [Lang.Blocks.robotis_pattern3, '31'],\n                    ],\n                    value: '11',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_speed_fast, '0'],\n                        [Lang.Blocks.robotis_speed_midium, '1'],\n                        [Lang.Blocks.robotis_speed_slow, '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotis_Practice_cm_led_pattern',\n            },\n            paramsKeyMap: {\n                PATTERN: 0,\n                SPEED: 1,\n            },\n            class: 'robotis_rb100_led',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var pattern = script.getNumberValue('PATTERN', script);\n                var speed = script.getNumberValue('SPEED', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 40;\n                var data_length = 1;\n                var data_value = 0;\n\n                \n                data_value = pattern + speed;\n              \n                var data_sendqueue = [\n                    [data_instruction, data_address, data_length, data_value],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.RB100_led_pattern(%1, %2)'] },\n        },\n\n\n        \n        robotis_Practice_dxl_set_mode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left_wheel, '52'],\n                        [Lang.Blocks.robotis_right_wheel, '51'],\n                        [\"ID 1\", '1'],\n                        [\"ID 2\", '2'],\n                        [\"ID 3\", '3'],\n                        [\"ID 4\", '4'],\n                        [\"ID 5\", '5'],\n                        [\"ID 6\", '6'],\n                        [\"ID 7\", '7'],\n                        [\"ID 8\", '8'],\n                    ],\n                    value: '52',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_dxl_mode_joint, '3'],\n                        [Lang.Blocks.robotis_dxl_mode_wheel, '1'],\n                        [Lang.Blocks.robotis_dxl_mode_multi_turn, '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '52',\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_dxl_set_mode',\n            },\n            paramsKeyMap: {\n                DXL_ID: 0,\n                DXL_MODE: 1,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H', 'Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var dxl_id = script.getNumberValue('DXL_ID', script);\n                var dxl_mode = script.getField('DXL_MODE', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n\n                data_address =\n                    Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[0];\n                data_length =\n                    Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[1];\n\n                data_value = dxl_mode;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0],\n                        Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1],\n                        dxl_id,\n                        0\n                    ],\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        dxl_id,\n                        data_value\n                    ],\n                    [\n                        data_instruction,\n                        Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0],\n                        Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1],\n                        dxl_id,\n                        1\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.set_dxl_mode(%1, %2)'],\n            },\n        },\n        robotis_Practice_dxl_each_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left_wheel, '52'],\n                        [Lang.Blocks.robotis_right_wheel, '51'],\n                        [\"ID 1\", '1'],\n                        [\"ID 2\", '2'],\n                        [\"ID 3\", '3'],\n                        [\"ID 4\", '4'],\n                        [\"ID 5\", '5'],\n                        [\"ID 6\", '6'],\n                        [\"ID 7\", '7'],\n                        [\"ID 8\", '8'],\n                    ],\n                    value: '52',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '52',\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                ],\n                type: 'robotis_Practice_dxl_each_control',\n            },\n\n            paramsKeyMap: {\n                DXLNUM: 0,\n                ANGLE: 1,\n                TIME: 2,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func(entity, script) {\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                var data_address = 0;\n                var data_length = 0;\n\n                data_address =\n                    Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0];\n                data_length =\n                    Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] + Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1];\n\n\n                var dxlID = script.getField('DXLNUM', script);\n                var angle = script.getNumberValue('ANGLE', script);\n                var time = script.getNumberValue('TIME', script) * 1000;\n                var data_buf = [];\n\n                var engValue = 2048;\n                engValue = Math.floor(2048 - Math.round(angle * 4096) / 360);\n                var velocity = 0;\n\n                if (time == 0) {\n                    velocity = 0;\n                } else {\n                    velocity = Math.round(Math.floor(60 * Math.abs(angle - Entry.Robotis_rb.DXL_POSITION.values[dxlID - 1]) * 1000 / 360 / time) / 0.229);\n                }\n                Entry.Robotis_rb.DXL_POSITION.values[dxlID - 1] = angle;\n\n                data_buf.push(velocity%256);\n                data_buf.push(Math.floor(velocity/256));\n                data_buf.push(0);\n                data_buf.push(0);\n\n                data_buf.push(engValue%256);\n                data_buf.push(Math.floor(engValue/256));\n                data_buf.push(0);\n                data_buf.push(0);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        dxlID,\n                        data_buf\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    time + Entry.Robotis_openCM70.delay\n                    //Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: { js: [], py: ['Robotis.robotis_dxl_each_control(%1)'] },\n        },\n        robotis_Practice_dxl_set_position: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left_wheel, '52'],\n                        [Lang.Blocks.robotis_right_wheel, '51'],\n                        [\"ID 1\", '1'],\n                        [\"ID 2\", '2'],\n                        [\"ID 3\", '3'],\n                        [\"ID 4\", '4'],\n                        [\"ID 5\", '5'],\n                        [\"ID 6\", '6'],\n                        [\"ID 7\", '7'],\n                        [\"ID 8\", '8'],\n                    ],\n                    value: '52',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '52',\n                    '50',\n                    '0',\n                    null,\n                ],\n                type: 'robotis_Practice_dxl_set_position',\n            },\n            paramsKeyMap: {\n                DXL_ID: 0,\n                DXL_SPEED: 1,\n                DXL_ANGLE: 2,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H', 'Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var dxl_id = script.getNumberValue('DXL_ID', script);\n                var dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                var dxl_angle = script.getNumberValue('DXL_ANGLE', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_buf = [];\n\n                data_address =\n                    Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0];\n                data_length =\n                    Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] + Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1];\n\n                if (dxl_speed < 0) dxl_speed = 0;\n                else if (dxl_speed > 100) dxl_speed = 100;\n\n                data_buf.push((dxl_speed*10)%256);\n                data_buf.push(Math.floor(dxl_speed*10/256));\n                data_buf.push(0);\n                data_buf.push(0);\n\n                if (dxl_angle < -179) dxl_angle = -179;\n                else if (dxl_angle > 180) dxl_angle = 180;\n\n                dxl_angle = 180 - dxl_angle;\n\n                data_buf.push(Math.floor(dxl_angle*4096/360)%256);\n                data_buf.push(Math.floor(dxl_angle*4096/360/256));\n                data_buf.push(0);\n                data_buf.push(0);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        dxl_id,\n                        data_buf\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.set_dxl_position(%1, %2, %3)'],\n            },\n        },\n        robotis_Practice_dxl_set_rotate: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left_wheel, '52'],\n                        [Lang.Blocks.robotis_right_wheel, '51'],\n                        [\"ID 1\", '1'],\n                        [\"ID 2\", '2'],\n                        [\"ID 3\", '3'],\n                        [\"ID 4\", '4'],\n                        [\"ID 5\", '5'],\n                        [\"ID 6\", '6'],\n                        [\"ID 7\", '7'],\n                        [\"ID 8\", '8'],\n                    ],\n                    value: '52',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_dxl_rotate_cw, '1'],\n                        [Lang.Blocks.robotis_dxl_rotate_ccw, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_dxl_move_rotate, '1'],\n                        [Lang.Blocks.robotis_dxl_move_stop, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '52',\n                    '50',\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_dxl_set_rotate',\n            },\n            paramsKeyMap: {\n                DXL_ID: 0,\n                DXL_SPEED: 1,\n                DXL_DIRECTION: 2,\n                DXL_MOVE: 3,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H', 'Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var dxl_id = script.getNumberValue('DXL_ID', script);\n                var dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                var dxl_direction = script.getNumberValue('DXL_DIRECTION', script);\n                var dxl_move = script.getNumberValue('DXL_MOVE', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                var data_address = 0;\n                var data_length = 0;\n                var data_value = 0;\n\n                data_address =\n                    Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[0];\n                data_length =\n                    Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[1];\n\n                if (dxl_speed < 0) dxl_speed = 0;\n                else if (dxl_speed > 100) dxl_speed = 100;\n\n                data_value = dxl_speed * 10;\n\n                // cw일 경우 음수처리\n                if (dxl_direction == 1) data_value = -data_value;\n\n                // 바퀴형 로봇인 경우 reverse mode이므로 방향 반대\n                if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) data_value = -data_value;\n\n                data_value = data_value * dxl_move;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        dxl_id,\n                        data_value\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.set_dxl_rotate(%1, %2, %3)'],\n            },\n        },\n        robotis_Practice_dxl_set_multiturn_round: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_left_wheel, '52'],\n                        [Lang.Blocks.robotis_right_wheel, '51'],\n                        [\"ID 1\", '1'],\n                        [\"ID 2\", '2'],\n                        [\"ID 3\", '3'],\n                        [\"ID 4\", '4'],\n                        [\"ID 5\", '5'],\n                        [\"ID 6\", '6'],\n                        [\"ID 7\", '7'],\n                        [\"ID 8\", '8'],\n                    ],\n                    value: '52',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_dxl_rotate_cw, '1'],\n                        [Lang.Blocks.robotis_dxl_rotate_ccw, '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    '52',\n                    '50',\n                    '1',\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_dxl_set_multiturn_round',\n            },\n            paramsKeyMap: {\n                DXL_ID: 0,\n                DXL_SPEED: 1,\n                DXL_ROUND: 2,\n                DXL_DIRECTION: 3,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_H', 'Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var dxl_id = script.getNumberValue('DXL_ID', script);\n                var dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                var dxl_round = script.getNumberValue('DXL_ROUND', script);\n                var dxl_direction = script.getNumberValue('DXL_DIRECTION', script);\n\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address_1 = 0;\n                var data_length_1 = 0;\n                var data_value_1 = 0;\n                var data_address_2 = 0;\n                var data_length_2 = 0;\n                var data_value_2 = 0;\n                var data_address_3 = 0;\n                var data_length_3 = 0;\n                var data_value_3 = 0;\n\n                var data_sendqueue = [];\n                var result = undefined;\n\n                if (dxl_id == 0 || dxl_speed == 0 || dxl_round == 0) {\n                    return;\n                }\n\n                data_address_1 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[0];\n                data_length_1 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[1];\n\n                data_address_2 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[0];\n                data_length_2 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[1];\n\n                if (dxl_speed < 0) dxl_speed = 0;\n                else if (dxl_speed > 100) dxl_speed = 100;\n\n                data_value_2 = dxl_speed * 10;\n\n                data_address_3 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[0];\n                data_length_3 =\n                    Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[1];\n\n                if (dxl_round < 0) dxl_round = 0;\n                else if (dxl_round > 100) dxl_round = 100;\n\n                // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대\n                if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) {\n                    dxl_round = -dxl_round;\n                }\n\n                data_value_3 = dxl_round * 4096;\n\n                if (dxl_direction == 1) data_value_3 = -data_value_3;\n\n                data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address_1,\n                        data_length_1,\n                        dxl_id,\n                    ],\n                    [\n                        data_instruction,\n                        data_address_2,\n                        data_length_2,\n                        data_value_2,\n                    ],\n                    [\n                        data_instruction,\n                        data_address_3,\n                        data_length_3,\n                        data_value_3,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.set_dxl_rotate(%1, %2, %3)'],\n            },\n        },\n\n\n\n\n\n\n        \n        robotis_Practice_scale_simple: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.General.note_c + '', '1'],\n                        [Lang.General.note_c + '#', '2'],\n                        [Lang.General.note_d + '', '3'],\n                        [Lang.General.note_d + '#', '4'],\n                        [Lang.General.note_e + '', '5'],\n                        [Lang.General.note_f + '', '6'],\n                        [Lang.General.note_f + '#', '7'],\n                        [Lang.General.note_g + '', '8'],\n                        [Lang.General.note_g + '#', '9'],\n                        [Lang.General.note_a + '', '10'],\n                        [Lang.General.note_a + '#', '11'],\n                        [Lang.General.note_b + '', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_beat_sound_8th_note, '3'],\n                        [Lang.Blocks.robotis_beat_sound_dotted_8th_note, '4'],\n                        [Lang.Blocks.robotis_beat_sound_quarter_note, '5'],\n                        [Lang.Blocks.robotis_beat_sound_dotted_quarter_note, '6'],\n                        [Lang.Blocks.robotis_beat_sound_half_note, '7'],\n                        [Lang.Blocks.robotis_beat_sound_dotted_half_note, '8'],\n                        [Lang.Blocks.robotis_beat_sound_whole_note, '9'],\n                        [Lang.Blocks.robotis_beat_sound_dotted_note, '10'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_scale_simple',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_OCTAV: 0,\n                CM_BUZZER_INDEX: 1,\n                CM_BUZZER_NOTE: 2,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                var cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                var cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script);\n                let cmBuzzerTime = 0;\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address_1 = 0;\n                var data_length_1 = 0;\n                var data_value_1 = 0;\n                var data_address_2 = 0;\n                var data_length_2 = 0;\n                var data_value_2 = 0;\n                var interval = 0;\n\n                switch (cmBuzzerNote) {\n                    case 3:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute / 2);\n                        break;\n\n                    case 4:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute / 2 * 1.5);\n                        break;\n\n                    case 5:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute);\n                        break;\n\n                    case 6:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 1.5);\n                        break;\n\n                    case 7:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 2);\n                        break;\n\n                    case 8:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 2 * 1.5);\n                        break;\n\n                    case 9:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 4);\n                        break;\n    \n                    case 10:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 4 * 1.5);\n                        break;\n                }\n\n                data_address_1 = 740;\n                data_length_1 = 2;\n                // data_value_1 = cmBuzzerTime * 10;\n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                data_value_1 = cmBuzzerTime;\n                if (data_value_1 < 0) {\n                    data_value_1 = 0;\n                }\n                if (data_value_1 > 50000) {\n                    data_value_1 = 50000;\n                }\n\n                data_address_2 = 742;\n                data_length_2 = 1;\n                data_value_2 = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n\n                // console.log(\"buzzer send\");\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address_1,\n                        data_length_1,\n                        data_value_1,\n                    ],\n                    [\n                        data_instruction,\n                        data_address_2,\n                        data_length_2,\n                        data_value_2,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime + interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_buzzer_index(%1, %2)'],\n            },\n        }, \n        robotis_Practice_scale_advanced: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.General.note_c + '', '1'],\n                        [Lang.General.note_c + '#', '2'],\n                        [Lang.General.note_d + '', '3'],\n                        [Lang.General.note_d + '#', '4'],\n                        [Lang.General.note_e + '', '5'],\n                        [Lang.General.note_f + '', '6'],\n                        [Lang.General.note_f + '#', '7'],\n                        [Lang.General.note_g + '', '8'],\n                        [Lang.General.note_g + '#', '9'],\n                        [Lang.General.note_a + '', '10'],\n                        [Lang.General.note_a + '#', '11'],\n                        [Lang.General.note_b + '', '12'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    1,\n                    null,\n                ],\n                type: 'robotis_Practice_scale_advanced',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_OCTAV: 0,\n                CM_BUZZER_INDEX: 1,\n                CM_BUZZER_BEAT: 2,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                var cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                var cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script);\n                let cmBuzzerTime = 0;\n\n                cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address_1 = 0;\n                var data_length_1 = 0;\n                var data_value_1 = 0;\n                var data_address_2 = 0;\n                var data_length_2 = 0;\n                var data_value_2 = 0;\n                var interval = 0;\n\n                cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * cmBuzzerBeat);\n\n                data_address_1 = 740;\n                data_length_1 = 2;\n                // data_value_1 = cmBuzzerTime * 10;\n                // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                data_value_1 = cmBuzzerTime;\n                if (data_value_1 < 0) {\n                    data_value_1 = 0;\n                }\n                if (data_value_1 > 50000) {\n                    data_value_1 = 50000;\n                }\n\n                data_address_2 = 742;\n                data_length_2 = 1;\n                data_value_2 = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n\n                // console.log(\"buzzer send\");\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address_1,\n                        data_length_1,\n                        data_value_1,\n                    ],\n                    [\n                        data_instruction,\n                        data_address_2,\n                        data_length_2,\n                        data_value_2,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime + interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_buzzer_index(%1, %2)'],\n            },\n        }, \n        robotis_Practice_rest_simple: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_beat_rest_8th_note, '3'],\n                        [Lang.Blocks.robotis_beat_rest_quarter_note, '5'],\n                        [Lang.Blocks.robotis_beat_rest_half_note, '7'],\n                        [Lang.Blocks.robotis_beat_rest_whole_note, '9'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_rest_simple',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_NOTE: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script);\n                let cmBuzzerTime = 0;\n\n                var interval = 0;\n\n                switch (cmBuzzerNote) {\n                    case 3:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute / 2);\n                        break;\n\n                    case 5:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute);\n                        break;\n\n                    case 7:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 2);\n                        break;\n\n                    case 9:\n                        cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * 4);\n                        break;\n                }\n                \n                var data_sendqueue = [\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime + interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_buzzer_index(%1, %2)'],\n            },\n        }, \n        robotis_Practice_rest_advanced: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    1,\n                    null,\n                ],\n                type: 'robotis_Practice_rest_advanced',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_BEAT: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script);\n                let cmBuzzerTime = 0;\n\n                var interval = 0;\n                \n                cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100);\n\n                cmBuzzerTime = Math.round(60 * 1000 / beat_per_minute * cmBuzzerBeat);\n                \n                var data_sendqueue = [\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    cmBuzzerTime + interval\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_buzzer_index(%1, %2)'],\n            },\n        }, \n        robotis_Practice_beat_per_minute: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    75,\n                    null,\n                ],\n                type: 'robotis_Practice_beat_per_minute',\n            },\n            paramsKeyMap: {\n                CM_BUZZER_BPM: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmBuzzerBpm = script.getNumberValue('CM_BUZZER_BPM', script);\n\n                beat_per_minute = Math.min(Math.max(cmBuzzerBpm, 10), 600);\n\n                // console.log(\"buzzer send\");\n                var data_sendqueue = [\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    0,\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.opencm70_cm_buzzer_index(%1, %2)'],\n            },\n        }, \n        \n        robotis_Practice_Hello: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_korean1,'0'],\n                        [Lang.Blocks.robotis_korean2,'1'],\n                        [Lang.Blocks.robotis_korean3,'2'],\n                        [Lang.Blocks.robotis_korean4,'3'],\n                        [Lang.Blocks.robotis_korean5,'4'],\n                        [Lang.Blocks.robotis_korean6,'5'],\n                        [Lang.Blocks.robotis_korean7,'6'],\n                        [Lang.Blocks.robotis_korean8,'7'],\n                        [Lang.Blocks.robotis_korean9,'8'],\n                        [Lang.Blocks.robotis_korean10,'9'],\n                        [Lang.Blocks.robotis_korean11,'10'],\n                        [Lang.Blocks.robotis_korean12,'11'],\n                        [Lang.Blocks.robotis_korean13,'12'],\n                        [Lang.Blocks.robotis_korean14,'13'],\n                        [Lang.Blocks.robotis_korean15,'14'],\n                        [Lang.Blocks.robotis_korean16,'15'],\n                        [Lang.Blocks.robotis_korean17,'16'],\n                        [Lang.Blocks.robotis_korean18,'17'],\n                        [Lang.Blocks.robotis_korean19,'18'],\n                        [Lang.Blocks.robotis_korean20,'19'],\n                        [Lang.Blocks.robotis_korean21,'20'],\n                        [Lang.Blocks.robotis_korean22,'21'],\n                        [Lang.Blocks.robotis_korean23,'22'],\n                        [Lang.Blocks.robotis_korean24,'23'],\n                        [Lang.Blocks.robotis_korean25,'24'],\n                        [Lang.Blocks.robotis_korean26,'25'],\n                        [Lang.Blocks.robotis_korean27,'26'],\n                        [Lang.Blocks.robotis_korean28,'27'],\n                        [Lang.Blocks.robotis_korean29,'28'],\n                        [Lang.Blocks.robotis_korean30,'29'],\n                        [Lang.Blocks.robotis_korean31,'30'],\n                        [Lang.Blocks.robotis_korean32,'31'],\n                        [Lang.Blocks.robotis_korean33,'32'],\n                        [Lang.Blocks.robotis_korean34,'33'],\n                        [Lang.Blocks.robotis_korean35,'34'],\n                        [Lang.Blocks.robotis_korean36,'35'],\n                        [Lang.Blocks.robotis_korean37,'36'],\n                        [Lang.Blocks.robotis_korean38,'37'],\n                        [Lang.Blocks.robotis_korean39,'38'],\n                        [Lang.Blocks.robotis_korean40,'39'],\n                        [Lang.Blocks.robotis_korean41,'40'],\n                        [Lang.Blocks.robotis_korean42,'41'],\n                        [Lang.Blocks.robotis_korean43,'42'],\n                        [Lang.Blocks.robotis_korean44,'43'],\n                        [Lang.Blocks.robotis_korean45,'44'],\n                        [Lang.Blocks.robotis_korean46,'45'],\n                        [Lang.Blocks.robotis_korean47,'46'],\n                        [Lang.Blocks.robotis_korean48,'47'],\n                        [Lang.Blocks.robotis_korean49,'48'],\n                        [Lang.Blocks.robotis_korean50,'49'],\n                        [Lang.Blocks.robotis_korean51,'50'],\n                        [Lang.Blocks.robotis_korean52,'51'],\n                        [Lang.Blocks.robotis_korean53,'52'],\n                        [Lang.Blocks.robotis_korean54,'53'],\n                        [Lang.Blocks.robotis_korean55,'54'],\n                        [Lang.Blocks.robotis_korean56,'55'],\n                        [Lang.Blocks.robotis_korean57,'56'],\n                        [Lang.Blocks.robotis_korean58,'57'],\n                        [Lang.Blocks.robotis_korean59,'58'],\n                        [Lang.Blocks.robotis_korean60,'59'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_Hello',\n            },\n            paramsKeyMap: {\n                HELLO: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmHello = script.getField('HELLO', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 110;\n                var data_length = 2;\n                var data_value = 0;\n            \n               \n                data_value = 25601+Number(cmHello);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        data_instruction,\n                        0,\n                        2,\n                        0\n                    ]\n                ];\n\n\n                let extraTime = 0; \n                \n                if(cmHello == '38' || cmHello == '55') {\n                    extraTime = 2000;\n                }\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    2000 + extraTime\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_Hello(%1)'],\n            },\n        },\n        robotis_Practice_effectSound:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_dog, '0'],\n                        [Lang.Blocks.robotis_frog, '1'],\n                        [Lang.Blocks.robotis_cat, '2'],\n                        [Lang.Blocks.robotis_chicken, '7'],\n                        [Lang.Blocks.robotis_tiger, '19'],\n                        [Lang.Blocks.robotis_mouse, '17'],\n\n                        [Lang.Blocks.robotis_ambul, '773'],\n                        [Lang.Blocks.robotis_Horn, '781'],\n                        [Lang.Blocks.robotis_siren, '774'],\n                        [Lang.Blocks.robotis_whistle, '274'],\n                        [Lang.Blocks.robotis_gun, '775'],\n                        [Lang.Blocks.robotis_clap, '260'],\n\n                        [Lang.Blocks.robotis_melody1, '786'],\n                        [Lang.Blocks.robotis_melody2, '787'],\n                        [Lang.Blocks.robotis_melody3, '788'],\n                        [Lang.Blocks.robotis_melody4, '789'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_effectSound',\n            },\n            paramsKeyMap: {\n                HELLO: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var cmHello = script.getField('HELLO', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 110;\n                var data_length = 2;\n                var data_value = 0;\n            \n               \n                data_value = Number(cmHello);\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                    [\n                        data_instruction,\n                        0,\n                        2,\n                        0\n                    ]\n                ];\n                \n                let extraTime = 0;\n                if(cmHello == '272' || cmHello == '786' || cmHello == '787' || cmHello == '788' || cmHello == '789') { //오리\n                    extraTime = 0;\n                    if(cmHello == '788' || cmHello == '789') {\n                        extraTime += 500;\n                    }\n                }\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    3000 + extraTime\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_Hello(%1)'],\n            },\n        },\n        robotis_Practice_record:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_record',\n            },\n            paramsKeyMap: {\n                ROOM: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var roomNum = script.getField('ROOM', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 115;\n                var data_length = 1;\n                var data_value = 0;\n            \n               \n                data_value = roomNum;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    6000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_record(%1)'],\n            },\n        },\n        robotis_Practice_playRecord:{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '0'],\n                        ['2', '1'],\n                        ['3', '2'],\n                        ['4', '3'],\n                        ['5', '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_playRecord',\n            },\n            paramsKeyMap: {\n                ROOM: 0,\n            },\n            class: 'robotis_rb100_sound',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var roomNum = script.getField('ROOM', script);\n                \n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 116;\n                var data_length = 1;\n                var data_value = 0;\n            \n               \n                data_value = roomNum;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_value,\n                    ],\n                ];\n                \n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    6000\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.RB_playRecord(%1)'],\n            },\n        },\n\n\n\n\n\n        \n        robotis_Practice_ai_camera_block_value_closest_to_center: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_target_face, '0'],\n                        [Lang.Blocks.robotis_ai_camera_target_expression, '1'],\n                        [Lang.Blocks.robotis_ai_camera_target_object, '2'],\n                        [Lang.Blocks.robotis_ai_camera_target_color, '3'],\n                        [Lang.Blocks.robotis_ai_camera_target_tag, '4'],\n                        [Lang.Blocks.robotis_ai_camera_target_qr, '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'],\n                        [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'],\n                        [Lang.Blocks.robotis_ai_camera_center_block_width, '2'],\n                        [Lang.Blocks.robotis_ai_camera_center_block_height, '3'],\n                        [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_ai_camera_block_value_closest_to_center',\n            },\n            paramsKeyMap: {\n                TARGET: 0,\n                DATA_TYPE: 1,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4009;\n                var data_type = script.getNumberValue('DATA_TYPE');\n                data_address += data_type * 2;\n                var result = Entry.hw.portData[data_address];\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_block_value_closest_to_center(%1)'],\n            },\n        },\n        robotis_Practice_ai_camera_arrow_value_closest_to_center: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'],\n                        [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'],\n                        [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'],\n                        [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'],\n                        [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_ai_camera_arrow_value_closest_to_center',\n            },\n            paramsKeyMap: {\n                DATA_TYPE: 0,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4019;\n                var data_type = script.getNumberValue('DATA_TYPE');\n                data_address += data_type * 2;\n                var result = Entry.hw.portData[data_address];\n\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_arrow_value_closest_to_center(%1)'],\n            },\n        },\n        robotis_Practice_ai_camera_number_of_learned_id: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'robotis_Practice_ai_camera_number_of_learned_id',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4003;\n                var result = Entry.hw.portData[data_address];\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_number_of_learned_id()'],\n            },\n        },\n        robotis_Practice_ai_camera_block_value_of_id: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [\"1\", '1'],\n                            [\"2\", '2'],\n                            [\"3\", '3'],\n                            [\"4\", '4'],\n                            [\"5\", '5'],\n                            [\"6\", '6'],\n                            [\"7\", '7'],\n                            [\"8\", '8'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robotis_ai_camera_target_face, '0'],\n                            [Lang.Blocks.robotis_ai_camera_target_expression, '1'],\n                            [Lang.Blocks.robotis_ai_camera_target_object, '2'],\n                            [Lang.Blocks.robotis_ai_camera_target_color, '3'],\n                            [Lang.Blocks.robotis_ai_camera_target_tag, '4'],\n                            [Lang.Blocks.robotis_ai_camera_target_qr, '5'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'],\n                            [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'],\n                            [Lang.Blocks.robotis_ai_camera_center_block_width, '2'],\n                            [Lang.Blocks.robotis_ai_camera_center_block_height, '3'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_ai_camera_block_value_of_id',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TARGET: 1,\n                TYPE: 2,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4029; // ID_FOR_USE\n                var data_length = 2;\n                var data_value = script.getNumberValue('ID');\n\n                if (camera_id_for_use != data_value) {\n                    var data_sendqueue = [\n                        [\n                            data_instruction,\n                            data_address,\n                            data_length,\n                            data_value,\n                        ],\n                    ];\n\n                    Entry.Robotis_carCont.postCallReturn(\n                        script,\n                        data_sendqueue,\n                        Entry.Robotis_openCM70.delay\n                    );\n                    camera_id_for_use = data_value;\n                }\n\n                data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER\n\n                data_address += script.getNumberValue('TYPE') * 2;\n\n                var result = Entry.hw.portData[data_address];\n\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_block_value_of_id(%1, %2)'],\n            },\n        },\n        robotis_Practice_ai_camera_arrow_value_of_id: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [\"1\", '1'],\n                            [\"2\", '2'],\n                            [\"3\", '3'],\n                            [\"4\", '4'],\n                            [\"5\", '5'],\n                            [\"6\", '6'],\n                            [\"7\", '7'],\n                            [\"8\", '8'],\n                        ],\n                        value: '1',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n                    {\n                        type: 'Dropdown',\n                        options: [\n                            [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'],\n                            [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'],\n                            [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'],\n                            [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'],\n                        ],\n                        value: '0',\n                        fontSize: 11,\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'robotis_Practice_ai_camera_arrow_value_of_id',\n            },\n            paramsKeyMap: {\n                ID: 0,\n                TYPE: 1,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n\n                // instruction / address / length / value / default length\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4029; // ID_FOR_USE\n                var data_length = 2;\n                var data_value = script.getNumberValue('ID');\n\n                if (camera_id_for_use != data_value) {\n                    var data_sendqueue = [\n                        [\n                            data_instruction,\n                            data_address,\n                            data_length,\n                            data_value,\n                        ],\n                    ];\n\n                    Entry.Robotis_carCont.postCallReturn(\n                        script,\n                        data_sendqueue,\n                        Entry.Robotis_openCM70.delay\n                    );\n                    camera_id_for_use = data_value;\n                }\n\n                data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN\n\n                data_address += script.getNumberValue('TYPE') * 2;\n                var result = Entry.hw.portData[data_address];\n\n                if (typeof result == 'undefined') {\n                    return 0;\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_arrow_value_of_id(%1, %2)'],\n            },\n        },\n        robotis_Practice_ai_camera_connection_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_connected, '1'],\n                        [Lang.Blocks.robotis_disconnected, '0'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_ai_camera_connection_status',\n            },\n            paramsKeyMap: {\n                STATUS: 0,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4000;\n                var compareValue = script.getNumberValue('STATUS');\n                var result = Entry.hw.portData[data_address];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == compareValue);\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_connection_status(%1)'],\n            },\n        },\n        robotis_Practice_ai_camera_if_detected: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_target_face, '0'],\n                        [Lang.Blocks.robotis_ai_camera_target_expression, '1'],\n                        [Lang.Blocks.robotis_ai_camera_target_object, '2'],\n                        [Lang.Blocks.robotis_ai_camera_target_color, '3'],\n                        [Lang.Blocks.robotis_ai_camera_target_tag, '4'],\n                        [Lang.Blocks.robotis_ai_camera_target_qr, '5'],\n                        [Lang.Blocks.robotis_ai_camera_target_arrow, '6'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_ai_camera_if_detected',\n            },\n            paramsKeyMap: {\n                DETECT_TYPE: 0,\n            },\n            class: 'robotis_rb100_custom_ai_camera',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                var scope = script.executor.scope;\n                var data_address = 4005; // block\n                var detect_type = script.getNumberValue('DETECT_TYPE');\n\n                if (detect_type == 6) data_address = 4006; // arrow\n\n                var result = Entry.hw.portData[data_address];\n\n                if(result == undefined) {\n                    return false;\n                }\n\n                return (result == 1);\n               \n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_if_detected(%1)'],\n            },\n        },\n        robotis_Practice_ai_camera_set_mode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotis_ai_camera_mode_face_recognition, '0'],\n                        [Lang.Blocks.robotis_ai_camera_mode_expression_recognition, '9'],\n                        [Lang.Blocks.robotis_ai_camera_mode_line_tracking, '3'],\n                        [Lang.Blocks.robotis_ai_camera_mode_color_recognition, '4'],\n                        [Lang.Blocks.robotis_ai_camera_mode_tag_recognition, '5'],\n                        [Lang.Blocks.robotis_ai_camera_mode_object_classification, '6'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'robotis_Practice_ai_camera_set_mode',\n            },\n            paramsKeyMap: {\n                AI_CAMERA_MODE: 0,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var ai_camera_mode = script.getField('AI_CAMERA_MODE', script);\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4001;\n                var data_length = 1;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        ai_camera_mode,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.set_ai_camera_mode(%1)'],\n            },\n        },\n        robotis_Practice_ai_camera_print_custom_text: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    \"Hello!\"\n                ],\n                type: 'robotis_Practice_ai_camera_print_custom_text',\n            },\n            paramsKeyMap: {\n                X: 0,\n                Y: 1,\n                TEXT: 2,\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n                var x = script.getNumberValue('X', script);\n                var y = script.getNumberValue('Y', script);\n                var text = script.getStringValue('TEXT', script);\n                var data_buf = [];\n                var i = 0;\n\n                // Encode the text as UTF-8\n                let encoder = new TextEncoder();\n                let utf8Array = encoder.encode(text);\n\n                // utf8Array is now a Uint8Array containing the UTF-8 bytes of the text\n                let text_len = utf8Array.length;\n\n                if (text_len > 45) text_len = 45;\n                \n                if (x < -160) x = 160;\n                else if (x > 160) x = 160;\n\n                if (y < -120) y = 120;\n                else if (y > 120) y = 120;\n\n                if (x < 0) x = 65536 + x;\n                if (y < 0) y = 65536 + y;\n                \n                data_buf.push(x % 256);\n                data_buf.push(Math.floor(x/256));\n                data_buf.push(y % 256);\n                data_buf.push(Math.floor(y/256));\n                data_buf.push(0);\n                data_buf.push(0);\n                for (i = 0; i < text_len; i++) {\n                    data_buf.push(utf8Array[i]);\n                }\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4200;\n                var data_length = 6 + text_len;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        data_buf,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_print_custom_text(%1,%2,%3)'],\n            },\n        },\n        robotis_Practice_ai_camera_clear_custom_text: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                ],\n                type: 'robotis_Practice_ai_camera_clear_custom_text',\n            },\n            paramsKeyMap: {\n            },\n            class: 'robotis_openCM70_cm',\n            isNotFor: ['Robotis_rb_P_Assembly'],\n            func: function (sprite, script) {\n                // instruction / address / length / value / default length\n\n                var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                var data_address = 4250;\n                var data_length = 1;\n\n                var data_sendqueue = [\n                    [\n                        data_instruction,\n                        data_address,\n                        data_length,\n                        1,\n                    ],\n                ];\n\n                return Entry.Robotis_carCont.postCallReturn(\n                    script,\n                    data_sendqueue,\n                    Entry.Robotis_openCM70.delay\n                );\n            },\n            syntax: {\n                js: [],\n                py: ['Robotis.robotis_ai_camera_clear_custom_text()'],\n            },\n        },\n\n\n\n\n\n\n\n    };\n};\n\nmodule.exports = [Entry.Robotis_rb_P_Assembly];\n\n\n\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotori.js",
    "content": "'use strict';\n\nEntry.robotori = {\n    PORT_MAP: {\n        A0: 0,\n        A1: 0,\n        A2: 0,\n        A3: 0,\n        A4: 0,\n        A5: 0,\n        D2: 0,\n        D3: 0,\n        D10: 0,\n        D11: 0,\n        D12: 0,\n        D13: 0,\n        AOUT5: 0,\n        AOUT6: 0,\n        AOUT9: 0,\n        SERVO: 90,\n        RIGHT_MOTOR: 0xff, //default stop\n        LEFT_MOTOR: 0xff, //default stop\n    },\n    setZero: function () {\n        //Entry.hw.sendQueue.readablePorts = [];\n\n        var portMap = Entry.robotori.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n            //sq[portMap[port] = 0;\n\n            //Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n        var Robotori = Entry.robotori;\n    },\n    id: 'D.1',\n    name: 'robotori',\n    url: 'http://www.robotori.com/',\n    imageName: 'robotori.png',\n    title: {\n        ko: '로보토리',\n        en: 'robotori',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/robotori.png',\n        width: 395,\n        height: 372,\n        listPorts: {\n            A0: { name: 'A1', type: 'input', pos: { x: 0, y: 0 } },\n            A1: { name: 'A2', type: 'input', pos: { x: 0, y: 0 } },\n            A2: { name: 'A3', type: 'input', pos: { x: 0, y: 0 } },\n            A3: { name: 'A4', type: 'input', pos: { x: 0, y: 0 } },\n            A4: { name: 'A5', type: 'input', pos: { x: 0, y: 0 } },\n            A5: { name: 'A6', type: 'input', pos: { x: 0, y: 0 } },\n            D2: { name: 'D7', type: 'input', pos: { x: 0, y: 0 } },\n            D3: { name: 'D8', type: 'input', pos: { x: 0, y: 0 } },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.robotori.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                robotori_digitalInput: '%1',\n                robotori_analogInput: '%1',\n                robotori_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n                robotori_analogOutput: '아날로그 %1 %2 %3',\n                robotori_servo: '서보모터 각도 %1 %2',\n                robotori_dc_direction: 'DC모터 %1 회전 %2 %3',\n                robotori_dc_forward: 'DC모터 %1 %2 %3',\n                robotori_dc_stop: 'DC모터 정지   ',\n                robotori_temperature_sensor: '%1 보드, 온도 센서 %2 핀',\n                robotori_gas_sensor: '%1 보드, 가스 센서 %2 핀',\n            },\n            Blocks: {\n                robotori_D2_Input: '디지털 7번 핀 입력 값',\n                robotori_D3_Input: '디지털 8번 핀 입력 값',\n                robotori_A0_Input: '아날로그 1번',\n                robotori_A1_Input: '아날로그 2번',\n                robotori_A2_Input: '아날로그 3번',\n                robotori_A3_Input: '아날로그 4번',\n                robotori_A4_Input: '아날로그 5번',\n                robotori_A5_Input: '아날로그 6번',\n                robotori_board_type_1: 'BASE(E5-1)',\n                robotori_board_type_2: 'TORIANO(E10)',\n                robotori_digital: '디지털',\n                robotori_D10_Output: '11번',\n                robotori_D11_Output: '12번',\n                robotori_D12_Output: '13번',\n                robotori_D13_Output: '14번',\n                robotori_pin_OutputValue: '핀, 출력 값',\n                robotori_On: '켜짐',\n                robotori_Off: '꺼짐',\n                robotori_analog: '아날로그',\n                robotori_analog5: '15번 핀 출력 값',\n                robotori_analog6: '16번 핀 출력 값',\n                robotori_analog9: '17번 핀 출력 값',\n                robotori_Servo: '서보모터',\n                robotori_DC: 'DC모터',\n                robotori_DC_rightmotor: '오른쪽',\n                robotori_DC_leftmotor: '왼쪽',\n                robotori_DC_forward: '전진',\n                robotori_DC_backward: '후진',\n                robotori_DC_STOP: '정지',\n                robotori_DC_CW: '시계방향',\n                robotori_DC_CCW: '반시계방향',\n                robotori_DC_select: '회전',\n\n            },\n        },\n        en: {\n            template: {\n                robotori_digitalInput: '%1',\n                robotori_analogInput: '%1',\n                robotori_digitalOutput: 'Digital %1 PIN, Output Value %2 %3',\n                robotori_analogOutput: 'Analog %1 %2 %3',\n                robotori_servo: 'Servo Motor Angle %1 %2',\n                robotori_dc_direction: 'DC Motor %1 Direction %2 %3',\n                robotori_dc_forward: 'DC Motor Forward',\n                robotori_dc_backward: 'DC Motor Backward',\n                robotori_temperature_sensor: '%1 Board, Tempture Sensor %2 PIN',\n                robotori_gas_sensor: '%1 Board, Gas Sensor %2 PIN',\n            },\n            Blocks: {\n                robotori_D2_Input: 'Digital Pin 7 Input Value',\n                robotori_D3_Input: 'Digital Pin 8 Input Value',\n                robotori_A0_Input: 'Analog Pin 1 Input Value',\n                robotori_A1_Input: 'Analog Pin 2 Input Value',\n                robotori_A2_Input: 'Analog Pin 3 Input Value',\n                robotori_A3_Input: 'Analog Pin 4 Input Value',\n                robotori_A4_Input: 'Analog Pin 5 Input Value',\n                robotori_A5_Input: 'Analog Pin 6 Input Value',\n                robotori_board_type_1: 'BASE(E5-1)',\n                robotori_board_type_2: 'TORIANO(E10)',\n                robotori_digital: 'Digital',\n                robotori_D10_Output: 'Pin 11',\n                robotori_D11_Output: 'Pin 12',\n                robotori_D12_Output: 'Pin 13',\n                robotori_D13_Output: 'Pin 14',\n                robotori_pin_OutputValue: 'Output Value',\n                robotori_On: 'On',\n                robotori_Off: 'Off',\n                robotori_analog: 'Analog',\n                robotori_analog5: 'Pin 15 Output Value',\n                robotori_analog6: 'Pin 16 Output Value',\n                robotori_analog9: 'Pin 17 Output Value',\n                robotori_Servo: 'Servo Motor',\n                robotori_DC: 'DC Motor',\n                robotori_DC_rightmotor: 'Right',\n                robotori_DC_leftmotor: 'Left',\n                robotori_DC_forward: 'Forward',\n                robotori_DC_backward: 'Backward',\n                robotori_DC_STOP: 'Stop',\n                robotori_DC_CW: 'clockwise',\n                robotori_DC_CCW: 'anticlockwise',\n                robotori_DC_select: 'direction',\n            },\n        },\n    };\n};\n\nEntry.robotori.blockMenuBlocks = [\n    //robotori Add 20161129 begin\n    'robotori_digitalInput',\n    'robotori_analogInput',\n    'robotori_digitalOutput',\n    'robotori_analogOutput',\n    'robotori_servo',\n    'robotori_dc_direction',\n    'robotori_dc_forward',\n    'robotori_dc_stop',\n    'robotori_temperature_sensor',\n    'robotori_gas_sensor'\n    //robotori add 20161129 end\n];\n\nEntry.robotori.getBlocks = function () {\n    return {\n        //region robotori 로보토리\n        robotori_digitalInput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_D2_Input, 'D2'],\n                        [Lang.Blocks.robotori_D3_Input, 'D3'],\n                    ],\n                    value: 'D2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotori_digitalInput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'robotori_sensor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n        },\n        robotori_analogInput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_A0_Input, 'A0'],\n                        [Lang.Blocks.robotori_A1_Input, 'A1'],\n                        [Lang.Blocks.robotori_A2_Input, 'A2'],\n                        [Lang.Blocks.robotori_A3_Input, 'A3'],\n                        [Lang.Blocks.robotori_A4_Input, 'A4'],\n                        [Lang.Blocks.robotori_A5_Input, 'A5'],\n                    ],\n                    value: 'A0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'robotori_analogInput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'robotori_sensor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n        },\n        robotori_digitalOutput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_D10_Output, 'D10'],\n                        [Lang.Blocks.robotori_D11_Output, 'D11'],\n                        [Lang.Blocks.robotori_D12_Output, 'D12'],\n                        [Lang.Blocks.robotori_D13_Output, 'D13'],\n                    ],\n                    value: 'D10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_On, 'ON'],\n                        [Lang.Blocks.robotori_Off, 'OFF'],\n                    ],\n                    value: 'ON',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotori_digitalOutput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'robotori_sensor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getStringField('VALUE', script);\n\n                if (dev == 'D10') {\n                    if (value == 'ON') {\n                        sq.D10 = 1;\n                    } else {\n                        sq.D10 = 0;\n                    }\n                } else if (dev == 'D11') {\n                    if (value == 'ON') {\n                        sq.D11 = 1;\n                    } else {\n                        sq.D11 = 0;\n                    }\n                } else if (dev == 'D12') {\n                    if (value == 'ON') {\n                        sq.D12 = 1;\n                    } else {\n                        sq.D12 = 0;\n                    }\n                } else if (dev == 'D13') {\n                    if (value == 'ON') {\n                        sq.D13 = 1;\n                    } else {\n                        sq.D13 = 0;\n                    }\n                }\n                return script.callReturn();\n            },\n        },\n        robotori_analogOutput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_analog5, 'AOUT5'],\n                        [Lang.Blocks.robotori_analog6, 'AOUT6'],\n                        [Lang.Blocks.robotori_analog9, 'AOUT9'],\n                    ],\n                    value: 'AOUT5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'robotori_analogOutput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'robotori_sensor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getNumberValue('VALUE', script);\n\n                if (dev == 'AOUT5') {\n                    sq.AOUT5 = value;\n                } else if (dev == 'AOUT6') {\n                    sq.AOUT6 = value;\n                } else if (dev == 'AOUT9') {\n                    sq.AOUT9 = value;\n                }\n\n                return script.callReturn();\n            },\n        },\n        robotori_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'robotori_servo',\n            },\n            paramsKeyMap: {\n                SERVO: 0,\n            },\n            class: 'robotori_motor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                sq.SERVO = script.getNumberValue('SERVO');\n\n                return script.callReturn();\n            },\n        },\n        robotori_dc_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_DC_rightmotor, 'RIGHT_MOTOR'],\n                        [Lang.Blocks.robotori_DC_leftmotor, 'LEFT_MOTOR'],\n                    ],\n                    value: 'RIGHT_MOTOR',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_DC_STOP, 'STOP'],\n                        [Lang.Blocks.robotori_DC_CW, 'CW'],\n                        [Lang.Blocks.robotori_DC_CCW, 'CCW'],\n                    ],\n                    value: 'STOP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotori_dc_direction',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'robotori_motor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getStringField('VALUE', script);\n                if (dev == 'RIGHT_MOTOR') {\n                    if (value == 'STOP') {\n                        sq.RIGHT_MOTOR = 0xff;\n                    } else if (value == 'CW') {\n                        sq.RIGHT_MOTOR = 0x00;\n                    } else if (value == 'CCW') {\n                        sq.RIGHT_MOTOR = 0xb4;\n                    }\n                }\n                if (dev == 'LEFT_MOTOR') {\n                    if (value == 'STOP') {\n                        sq.LEFT_MOTOR = 0xff;\n                    } else if (value == 'CW') {\n                        sq.LEFT_MOTOR = 0x00;\n                    } else if (value == 'CCW') {\n                        sq.LEFT_MOTOR = 0xb4;\n                    }\n                }\n                return script.callReturn();\n            },\n        },\n        robotori_dc_forward: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_DC_forward, 'FORWARD'],\n                        [Lang.Blocks.robotori_DC_backward, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'robotori_dc_forward',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'robotori_motor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getStringField('VALUE', script);\n                if (dev == 'FORWARD') {\n                    sq.RIGHT_MOTOR = 0x00;\n                    sq.LEFT_MOTOR = 0xb4;\n\n                }\n                else {\n                    sq.RIGHT_MOTOR = 0xb4;\n                    sq.LEFT_MOTOR = 0x00;\n                }\n\n\n                return script.callReturn();\n            },\n        },\n        robotori_dc_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'robotori_dc_stop',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'robotori_motor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getStringField('VALUE', script);\n\n                sq.RIGHT_MOTOR = 0xff;\n                sq.LEFT_MOTOR = 0xff;\n\n                return script.callReturn();\n            },\n        },\n        robotori_temperature_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_board_type_1, 'AT128'],\n                        [Lang.Blocks.robotori_board_type_2, 'TORIANO'],\n                    ],\n                    value: 'AT128',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_A0_Input, 'A0'],\n                        [Lang.Blocks.robotori_A1_Input, 'A1'],\n                        [Lang.Blocks.robotori_A2_Input, 'A2'],\n                        [Lang.Blocks.robotori_A3_Input, 'A3'],\n                        [Lang.Blocks.robotori_A4_Input, 'A4'],\n                        [Lang.Blocks.robotori_A5_Input, 'A5'],\n                    ],\n                    value: 'A0',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'robotori_temperature_sensor',  // 블록의 타입 이름을 변경\n            },\n            paramsKeyMap: {\n                board: 0,\n                pin: 1,\n\n            },\n            class: 'robotori_sensor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var pd = Entry.hw.portData;\n                var board_type = script.getField('board', script);\n                var dev = script.getField('pin', script);\n\n                var originValue = pd[dev];\n                var temperature;\n\n                if (board_type == 'AT128') {\n                    temperature = originValue * 0.42;\n                }\n                if (board_type == 'TORIANO') {\n                    temperature = originValue * 0.30;\n                }\n\n                return temperature;\n            },\n        },\n        robotori_gas_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_board_type_1, 'AT128'],\n                        [Lang.Blocks.robotori_board_type_2, 'TORIANO'],\n                    ],\n                    value: 'AT128',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.robotori_A0_Input, 'A0'],\n                        [Lang.Blocks.robotori_A1_Input, 'A1'],\n                        [Lang.Blocks.robotori_A2_Input, 'A2'],\n                        [Lang.Blocks.robotori_A3_Input, 'A3'],\n                        [Lang.Blocks.robotori_A4_Input, 'A4'],\n                        [Lang.Blocks.robotori_A5_Input, 'A5'],\n                    ],\n                    value: 'A0',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'robotori_gas_sensor',  // 블록의 타입 이름을 변경\n            },\n            paramsKeyMap: {\n                board: 0,\n                pin: 1,\n\n            },\n            class: 'robotori_sensor',\n            isNotFor: ['robotori'],\n            func: function (sprite, script) {\n                var pd = Entry.hw.portData;\n                var board_type = script.getField('board', script);\n                var dev = script.getField('pin', script);\n\n                var originValue = pd[dev];\n                var temperature;\n\n                if (board_type == 'AT128') {\n                    temperature = originValue * 0.42;\n                }\n                if (board_type == 'TORIANO') {\n                    temperature = originValue * 0.30;\n                }\n\n                return temperature;\n            },\n        },\n\n        //endregion robotori 로보토리\n    };\n};\n\nmodule.exports = Entry.robotori;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotry_parodule.js",
    "content": "'use strict';\n\nEntry.Robotry_Parodule = {\n    id: ['4B.2'],\n    name: 'Robotry_Parodule',\n    url: 'http://robotry.co.kr',\n    imageName: 'arduinoNano.png',\n    title: {\n        ko: '파로듈',\n        en: 'Parodule',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                SET: {},\n                CMD: {},\n                GET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n    getOffsetX(str) {\n        return str.indexOf('\\0') * 5 - 10;\n    },\n    getTerminal(port) {\n        return this.Terminal[port];\n    },\n    setTerminal(port1, port2, port3, port4) {\n        this.Terminal = [port1, port2, port3, port4];\n    },\n    Terminal: ['', '', '', ''],\n    moduleType: {\n        NONE: 0,\n        PIXEL: 1,\n        MOTOR: 2,\n        BUZZER: 3,\n    },\n    controlTypes: {\n        DIGITAL: 0,\n        ANALOG: 1,\n        STRING: 2,\n    },\n    BlockState: {},\n};\n\nEntry.Robotry_Parodule.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                Parodule_Input_title: '센서 블럭\\0',\n                Parodule_Sensor_Data: '%1 센서',\n                Parodule_Sensor_Kind: '%1 모듈 종류',\n\n                Parodule_title: '제어 블럭\\0',\n                Parodule_Set: '세모 : %1 원 : %4 네모 : %2  십자 : %3 으로 설정 %5',\n                Parodule_PIXEL: '%1 (으)로 픽셀 설정 %2',\n                Parodule_Motor: '%1 의 파워로 %2 %3',\n                Parodule_Buzzer: '%1 옥타브 %2 (으)로 재생 %3',\n\n                Parodule_Custom_title: '커스텀 제어 블럭\\0',\n                Parodule_Custom_Pixel: '%1 에 연결된 픽셀을 %2 으로 설정 %3',\n                Parodule_Custom_Motor: '%1 에 연결된 모터를 %2 의 파워로 %3 %4',\n                Parodule_Custom_Buzzer: '%1 에 연결된 부저를 %2 옥타브 %3 (으)로 재생 %4',\n                Parodule_Module_Off: '%1 에 연결된 모듈 동작 종료 %2',\n                Parodule_Module_Standby: '%1 에 연결된 모듈 동작 유지 %2',\n\n                Parodule_Func_title: '내장 동작\\0',\n                Parodule_Func_Pixel: '%1 에 연결된 픽셀을 %2 으로 설정 %3',\n                Parodule_Func_Buzzer: '%1 에 연결된 부저를 %2 으로 설정 %3',\n\n                Parodule_Update: '파로듈 업데이트 %1',\n            },\n            Helper: { // 블록 선택시 나타나는 한글 설명\n\n                //Parodule_Update: '파로듈 업데이트',\n            },\n            Blocks: {\n                parodule_triangle: '세모',\n                parodule_square: '네모',\n                parodule_cross: '십자',\n                parodule_circle: '원',\n                parodule_light: '빛',\n                parodule_sound: '소리',\n                parodule_pixel: '픽셀',\n                parodule_motor: '모터',\n                parodule_buzzer: '부저',\n                parodule_none: '없음',\n                parodule_unknown: '모름',\n\n                parodule_off: '없음',\n                parodule_cycle: '순환',\n                parodule_aura: '알록달록',\n                parodule_red: '빨강색',\n                parodule_vermilion: '주홍색',\n                parodule_orange: '주황색',\n                parodule_tangerine: '귤색',\n                parodule_yellow: '노랑색',\n                parodule_green_yellow: '연두색',\n                parodule_green: '녹색',\n                parodule_blue_green: '청록색',\n                parodule_blue: '파랑색',\n                parodule_prussian_blue: '감청색',\n                parodule_indigo: '남색',\n                parodule_blue_violet: '남보라색',\n                parodule_purple: '보라색',\n                parodule_reddish_purple: '자주색',\n\n                parodule_forward: '정회전',\n                parodule_backward: '역회전',\n                parodule_left: '좌회전',\n                parodule_right: '우회전',\n\n                parodule_silent: '무음',\n                parodule_horn: '빵빵',\n                parodule_weeoo: '삐용삐용',\n                parodule_do: '도',\n                parodule_do_sharp: '도#(레♭)',\n                parodule_re: '레',\n                parodule_re_sharp: '레#(미♭)',\n                parodule_mi: '미',\n                parodule_fa: '파',\n                parodule_fa_sharp: '파#(솔♭)',\n                parodule_sol: '솔',\n                parodule_sol_sharp: '솔#(라♭)',\n                parodule_la: '라',\n                parodule_la_sharp: '라#(시♭)',\n                parodule_si: '시',\n            },\n        },\n        en: {\n            template: {\n                Parodule_Input_title: 'Sensor Block\\0',\n                Parodule_Sensor_Data: 'Sensor values ​of %1',\n                Parodule_Sensor_Kind: 'kind of %1 ?',\n\n                Parodule_title: 'Controll Block\\0',\n                Parodule_Set: 'Set to triangle : %1 circle : %4 square : %2  cross : %3 %5',\n                Parodule_PIXEL: 'Set pixel to %1 %2',\n                Parodule_Motor: '%2 with power and move %1 %3',\n                Parodule_Buzzer: 'Play %1 octave %2 %3',\n\n                Parodule_Custom_title: 'Custom Control Block\\0',\n                Parodule_Custom_Pixel: 'Set pixels of  %1 to %2 %3',\n\n                Parodule_Custom_Motor: 'Set the motor of  %1 to %2 power and move %3 %4',\n                Parodule_Custom_Buzzer: 'Play the buzzer of  %1 in %2 octave %3 %4',\n                Parodule_Module_Off: 'Set Off module of  %1 %2',\n                Parodule_Module_Standby: 'Set Stand-by module of  %1 %2',\n\n                Parodule_Func_title: '내장 동작\\0',\n                Parodule_Func_Pixel: 'Set pixels of  %1 to %2 %3',\n                Parodule_Func_Buzzer: '%1 에 연결된 부저를 %2 으로 설정 %3',\n\n                Parodule_Update: '파로듈 업데이트 %1',\n            },\n            Helper: {\n\n                //Parodule_Update: '파로듈 업데이트',\n            },\n            Blocks: {\n                parodule_triangle: 'triangle',\n                parodule_square: 'square',\n                parodule_cross: 'cross',\n                parodule_circle: 'circle',\n                parodule_light: 'light',\n                parodule_sound: 'sound',\n                parodule_pixel: 'pixel',\n                parodule_motor: 'motor',\n                parodule_buzzer: 'buzzer',\n                parodule_none: 'none',\n                parodule_unknown: 'unknown',\n\n                parodule_off: 'off',\n                parodule_cycle: 'cycle',\n                parodule_aura: 'aura',\n                parodule_red: 'red',\n                parodule_vermilion: 'vermilion',\n                parodule_orange: 'orange',\n                parodule_tangerine: 'tangerine',\n                parodule_yellow: 'yellow',\n                parodule_green_yellow: 'green yellow',\n                parodule_green: 'green',\n                parodule_blue_green: 'blue green',\n                parodule_blue: 'blue',\n                parodule_prussian_blue: 'prussian blue',\n                parodule_indigo: 'indigo',\n                parodule_blue_violet: 'blue violet',\n                parodule_purple: 'purple',\n                parodule_reddish_purple: 'reddish purple',\n\n                parodule_forward: 'forward',\n                parodule_backward: 'backward',\n                parodule_left: 'left',\n                parodule_right: 'right',\n\n                parodule_silent: 'Silent',\n                parodule_do: 'C',\n                parodule_do_sharp: 'C#(D♭)',\n                parodule_re: 'D',\n                parodule_re_sharp: 'D#(E♭)',\n                parodule_mi: 'E',\n                parodule_fa: 'F',\n                parodule_fa_sharp: 'F#(G♭)',\n                parodule_sol: 'G',\n                parodule_sol_sharp: 'G#(A♭)',\n                parodule_la: 'A',\n                parodule_la_sharp: 'A#(B♭)',\n                parodule_si: 'B',\n            },\n        },\n    };\n};\n\nEntry.Robotry_Parodule.monitorTemplate = function () {\n\n    return {\n\n        imgPath: 'hw/robotry_parodule.png',\n        width: 500,\n        height: 500,\n        listPorts: {\n        },\n        ports: {\n            MODULE1: {\n                name: Lang.Blocks.parodule_triangle,\n                type: 'input',\n                pos: { x: [140], y: [100] },\n            },\n            MODULE2: {\n                name: Lang.Blocks.parodule_square,\n                type: 'input',\n                pos: { x: [140], y: [500 - 100] },\n            },\n            MODULE3: {\n                name: Lang.Blocks.parodule_cross,\n                type: 'input',\n                pos: { x: [500 - 140], y: [500 - 100] },\n            },\n            MODULE4: {\n                name: Lang.Blocks.parodule_circle,\n                type: 'input',\n                pos: { x: [500 - 140], y: [100] },\n            },\n        },\n        mode: 'both',\n\n    }\n},\n\n    // 블록의 배치 순서\n    Entry.Robotry_Parodule.blockMenuBlocks = [\n        'Parodule_Input_title',\n        //'Parodule_Sensor_Data', // 센서 모듈은 아직 출시 예정 없음\n        'Parodule_Sensor_Kind',\n\n        'Parodule_title',\n        'Parodule_Set',\n        'Parodule_PIXEL',\n        'Parodule_Motor',\n        'Parodule_Buzzer',\n\n        'Parodule_Custom_title',\n        'Parodule_Custom_Pixel',\n        'Parodule_Custom_Motor',\n        'Parodule_Custom_Buzzer',\n        'Parodule_Module_Off',\n        'Parodule_Module_Standby',\n\n        'Parodule_Func_title',\n        'Parodule_Func_Pixel',\n        'Parodule_Func_Buzzer',\n\n        //'Parodule_Update',\n    ];\n\n/* \n *  로보트리의 아두이노 제어 블록 리스트\n *  주석에 블록이라고 표시된것만 제어 블록임 나머진 포트 리스트\n */\nEntry.Robotry_Parodule.getBlocks = function () {\n    return {\n        /* Parodule_Custom_List Start */\n        Parodule_Custom_Port_List: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.parodule_triangle, 0], // 0\n                        [Lang.Blocks.parodule_circle, 1], // 3\n                        [Lang.Blocks.parodule_square, 2], // 1\n                        [Lang.Blocks.parodule_cross, 3], // 2\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                return port;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.parodule_triangle, 0], // 0\n                                [Lang.Blocks.parodule_circle, 1], // 3\n                                [Lang.Blocks.parodule_square, 2], // 1\n                                [Lang.Blocks.parodule_cross, 3], // 2\n                            ],\n                            value: [0],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Custom_Port_List',\n                }],\n            },\n        },\n\n        Parodule_Module_List: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.parodule_none, Entry.Robotry_Parodule.moduleType.NONE],\n                        [Lang.Blocks.parodule_pixel, Entry.Robotry_Parodule.moduleType.PIXEL],\n                        [Lang.Blocks.parodule_motor, Entry.Robotry_Parodule.moduleType.MOTOR],\n                        [Lang.Blocks.parodule_buzzer, Entry.Robotry_Parodule.moduleType.BUZZER],\n                    ],\n                    value: Entry.Robotry_Parodule.moduleType.NONE,\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                MODULE: 0,\n            },\n            func(sprite, script) {\n                const module = script.getNumberValue('MODULE');\n                return module;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.parodule_none, Entry.Robotry_Parodule.moduleType.NONE],\n                                [Lang.Blocks.parodule_pixel, Entry.Robotry_Parodule.moduleType.PIXEL],\n                                [Lang.Blocks.parodule_motor, Entry.Robotry_Parodule.moduleType.MOTOR],\n                                [Lang.Blocks.parodule_buzzer, Entry.Robotry_Parodule.moduleType.BUZZER],\n                            ],\n                            value: Entry.Robotry_Parodule.moduleType.NONE,\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Module_List',\n                }],\n            },\n        },\n\n        Parodule_Custom_Pixel_List: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.parodule_off, 0],//200\n                        [Lang.Blocks.parodule_red, 1],//19\n                        [Lang.Blocks.parodule_vermilion, 2],//20\n                        [Lang.Blocks.parodule_orange, 3],//21\n                        [Lang.Blocks.parodule_tangerine, 4],//22\n                        [Lang.Blocks.parodule_yellow, 5],//23\n                        [Lang.Blocks.parodule_green_yellow, 6],//24\n                        [Lang.Blocks.parodule_green, 7],//25\n                        [Lang.Blocks.parodule_blue_green, 8],//26\n                        [Lang.Blocks.parodule_blue, 9],//27\n                        [Lang.Blocks.parodule_prussian_blue, 10],//28\n                        [Lang.Blocks.parodule_indigo, 11],//29\n                        [Lang.Blocks.parodule_blue_violet, 12],//30\n                        [Lang.Blocks.parodule_purple, 13],//31\n                        [Lang.Blocks.parodule_reddish_purple, 14],//32\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            func(sprite, script) {\n                const color = script.getNumberValue('COLOR');\n                return color;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.parodule_off, 0],//200\n                                [Lang.Blocks.parodule_red, 1],//19\n                                [Lang.Blocks.parodule_vermilion, 2],//20\n                                [Lang.Blocks.parodule_orange, 3],//21\n                                [Lang.Blocks.parodule_tangerine, 4],//22\n                                [Lang.Blocks.parodule_yellow, 5],//23\n                                [Lang.Blocks.parodule_green_yellow, 6],//24\n                                [Lang.Blocks.parodule_green, 7],//25\n                                [Lang.Blocks.parodule_blue_green, 8],//26\n                                [Lang.Blocks.parodule_blue, 9],//27\n                                [Lang.Blocks.parodule_prussian_blue, 10],//28\n                                [Lang.Blocks.parodule_indigo, 11],//29\n                                [Lang.Blocks.parodule_blue_violet, 12],//30\n                                [Lang.Blocks.parodule_purple, 13],//31\n                                [Lang.Blocks.parodule_reddish_purple, 14],//32\n                            ],\n                            value: [0],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Custom_Pixel_List',\n                }],\n            },\n        },\n\n        Parodule_Func_Pixel_List: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.parodule_off, 0],//200\n                        [Lang.Blocks.parodule_cycle, 1],//17\n                        [Lang.Blocks.parodule_aura, 2],//18\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            func(sprite, script) {\n                const color = script.getNumberValue('COLOR');\n                return color;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.parodule_off, 0],//200\n                                [Lang.Blocks.parodule_aura, 1],//17\n                                [Lang.Blocks.parodule_aura, 2],//18\n                            ],\n                            value: [0],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Func_Pixel_List',\n                }],\n            },\n        },\n\n        Parodule_Custom_Motor_List: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['100%', 100], // 39\n                        ['75%', 75], // 38\n                        ['50%', 50], // 37\n                        ['25%', 25],// 36\n                        ['0%', 0],  // 200\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                POWER: 0,\n            },\n            func(sprite, script) {\n                const power = script.getNumberValue('POWER');\n                return power;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['100%', 100], // 39\n                                ['75%', 75], // 38\n                                ['50%', 50], // 37\n                                ['25%', 25],// 36\n                                ['0%', 0],  // 200\n                            ],\n                            value: [100],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Custom_Motor_List',\n                }],\n            },\n        },\n\n        Parodule_Motor_Sign: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.parodule_forward, 0],\n                        [Lang.Blocks.parodule_backward, 1],\n                        [Lang.Blocks.parodule_left, 2],\n                        [Lang.Blocks.parodule_right, 3],\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                SIGN: 0,\n            },\n            func(sprite, script) {\n                const sign = script.getNumberValue('SIGN');\n                return sign;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.parodule_forward, 0],\n                                [Lang.Blocks.parodule_backward, 1],\n                                [Lang.Blocks.parodule_left, 2],\n                                [Lang.Blocks.parodule_right, 3],\n                            ],\n                            value: [0],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Custom_Motor_Sign',\n                }],\n            },\n        },\n\n        Parodule_Custom_Motor_Sign: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.parodule_forward, 0], // 0\n                        [Lang.Blocks.parodule_backward, 1], // 4\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                SIGN: 0,\n            },\n            func(sprite, script) {\n                const sign = script.getNumberValue('SIGN');\n                return sign;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.parodule_forward, 0], // 0\n                                [Lang.Blocks.parodule_backward, 1], // 4\n                            ],\n                            value: [0],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Custom_Motor_Sign',\n                }],\n            },\n        },\n\n        Parodule_Custom_Octaves_List: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['3', 3], // 0\n                        ['4', 4], //12\n                        ['5', 5], //24\n                        ['6', 6], //36\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                const octave = script.getNumberValue('OCTAVE');\n                return octave;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['3', 3], // 0\n                                ['4', 4], //12\n                                ['5', 5], //24\n                                ['6', 6], //36\n                            ],\n                            value: [3],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Custom_Octaves_List',\n                }],\n            },\n        },\n\n        Parodule_Custom_Tone_List: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.parodule_silent, 0], // 200\n                        [Lang.Blocks.parodule_do, 1],// 47\n                        [Lang.Blocks.parodule_do_sharp, 2], // 48\n                        [Lang.Blocks.parodule_re, 3], // 49\n                        [Lang.Blocks.parodule_re_sharp, 4], // 50\n                        [Lang.Blocks.parodule_mi, 5], // 51\n                        [Lang.Blocks.parodule_fa, 6], //52\n                        [Lang.Blocks.parodule_fa_sharp, 7],  //53\n                        [Lang.Blocks.parodule_sol, 8],  //54\n                        [Lang.Blocks.parodule_sol_sharp, 9],  //55\n                        [Lang.Blocks.parodule_la, 10],  //56\n                        [Lang.Blocks.parodule_la_sharp, 11],  //57\n                        [Lang.Blocks.parodule_si, 12],  //58\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                TONE: 0,\n            },\n            func(sprite, script) {\n                const tone = script.getNumberValue('TONE');\n                return tone;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.parodule_silent, 0], // 200\n                                [Lang.Blocks.parodule_do, 1],// 47\n                                [Lang.Blocks.parodule_do_sharp, 2], // 48\n                                [Lang.Blocks.parodule_re, 3], // 49\n                                [Lang.Blocks.parodule_re_sharp, 4], // 50\n                                [Lang.Blocks.parodule_mi, 5], // 51\n                                [Lang.Blocks.parodule_fa, 6], //52\n                                [Lang.Blocks.parodule_fa_sharp, 7],  //53\n                                [Lang.Blocks.parodule_sol, 8],  //54\n                                [Lang.Blocks.parodule_sol_sharp, 9],  //55\n                                [Lang.Blocks.parodule_la, 10],  //56\n                                [Lang.Blocks.parodule_la_sharp, 11],  //57\n                                [Lang.Blocks.parodule_si, 12],  //58\n                            ],\n                            value: [0],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Custom_Tone_List',\n                }],\n            },\n        },\n\n        Parodule_Func_Tone_List: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.parodule_silent, 0], // 200\n                        [Lang.Blocks.parodule_horn, 1],// 45\n                        [Lang.Blocks.parodule_weeoo, 2], // 46\n                    ],\n                    value: [0],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                TONE: 0,\n            },\n            func(sprite, script) {\n                const tone = script.getNumberValue('TONE');\n                return tone;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: '%1',\n                    textParams: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.parodule_silent, 0], // 200\n                                [Lang.Blocks.parodule_horn, 1],// 45\n                                [Lang.Blocks.parodule_weeoo, 2], // 46\n                            ],\n                            value: [0],\n                            fontSize: 12,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    keyOption: 'Parodule_Func_Tone_List',\n                }],\n            },\n        },\n        /* Parodule_Custom_List End */\n\n        Parodule_Input_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: Entry.Robotry_Parodule.getOffsetX(Lang.template.Parodule_Input_title),\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: EntryStatic.colorSet.common.TEXT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.Parodule_Input_title,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'Parodule_Input_title',\n            },\n            class: 'TITLE',\n            isNotFor: ['Robotry_Parodule'],\n            events: {},\n        },\n\n        Parodule_Sensor_Data: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: [0],\n                    }\n                ],\n                type: 'Parodule_Sensor_Data',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Get',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                const sensor_data = Entry.hw.portData.SENSOR\n                let value = false;\n                if (sensor_data[port] === 48) {\n                    value = false;\n                }\n                else if (sensor_data[port] === 49) {\n                    value = true;\n                }\n                return value;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n\n        Parodule_Sensor_Kind: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: [0],\n                    }\n                ],\n                type: 'Parodule_Sensor_Kind',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Get',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const UNKNOWN = 207;\n                const NONE = 208;\n                const PIXEL = 209;\n                const MOTOR = 210;\n                const BUZZER = 211;\n                const port = script.getNumberValue('PORT') % 4;\n                const module_data = Entry.hw.portData.MODULE;\n                let correction_port = port === 1 ? 3 : port === 2 ? 1 : port === 3 ? 2 : 0;\n                let value = \"\";\n\n                if (module_data[correction_port] === PIXEL) {\n                    value = [Lang.Blocks.parodule_pixel];\n                }\n                else if (module_data[correction_port] === MOTOR) {\n                    value = [Lang.Blocks.parodule_motor];\n                }\n                else if (module_data[correction_port] === BUZZER) {\n                    value = [Lang.Blocks.parodule_buzzer];\n                }\n                else if (module_data[correction_port] === NONE) {\n                    value = [Lang.Blocks.parodule_none];\n                }\n                else if (module_data[correction_port] == UNKNOWN) {\n                    value = [Lang.Blocks.parodule_unknown];\n                }\n                return value;\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.get_Module(%1)',\n                    blockType: 'param',\n                    replaceBlockType: 'Parodule_Sensor_Kind',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                }],\n            },\n        },\n\n        Parodule_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: Entry.Robotry_Parodule.getOffsetX(Lang.template.Parodule_title),\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: EntryStatic.colorSet.common.TEXT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.Parodule_title,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'Parodule_title',\n            },\n            class: 'TITLE',\n            isNotFor: ['Robotry_Parodule'],\n            events: {},\n        },\n\n        /* Paroduel Set Start */\n        Parodule_Set: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Module_List',\n                        params: [Entry.Robotry_Parodule.moduleType.PIXEL],\n                    },\n                    {\n                        type: 'Parodule_Module_List',\n                        params: [Entry.Robotry_Parodule.moduleType.MOTOR],\n                    },\n                    {\n                        type: 'Parodule_Module_List',\n                        params: [Entry.Robotry_Parodule.moduleType.MOTOR],\n                    },\n                    {\n                        type: 'Parodule_Module_List',\n                        params: [Entry.Robotry_Parodule.moduleType.BUZZER],\n                    },\n                ],\n                type: 'Parodule_Set',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                PORT3: 2,\n                PORT4: 3,\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1'); // 1번 모터\n                const port2 = script.getNumberValue('PORT2'); // 1번 모터\n                const port3 = script.getNumberValue('PORT3'); // 1번 모터\n                const port4 = script.getNumberValue('PORT4'); // 1번 모터\n                //let port4 = script.getField('PORT4', script); // 1번 모터\n                Entry.Robotry_Parodule.setTerminal(port1, port2, port3, port4);\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Port(%1, %2, %3, %4)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                }],\n            }\n        },\n        /* Paroduel Set Start */\n\n        /* Paroduel PIXEL Start */\n        Parodule_PIXEL: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Pixel_List',\n                        params: [2],\n                    },\n                ],\n                type: 'Parodule_PIXEL',\n            },\n            paramsKeyMap: {\n                COLOR: 0\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const color = script.getNumberValue('COLOR') % 15;\n                let correction_color = !color ? 200 : color + 18;\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                for (let i = 0; i < 4; i++) {\n                    if (Entry.Robotry_Parodule.getTerminal(i) === Entry.Robotry_Parodule.moduleType.PIXEL) {\n                        Entry.hw.sendQueue.SET[i] = {\n                            type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                            data: correction_color,\n                            time: new Date().getTime(),\n                        }\n                    }\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Pixel(%1)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        }\n                    ],\n                }],\n            }\n        },\n        /* Parodule PIXEL End */\n\n        /* Paroduel Motor Start */\n        Parodule_Motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Motor_List',\n                        params: [100],\n                    },\n                    {\n                        type: 'Parodule_Motor_Sign',\n                        params: [0],\n                    }\n                ],\n                type: 'Parodule_Motor',\n            },\n            paramsKeyMap: {\n                POWER: 0,\n                SIGNED: 1,\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const power = script.getNumberValue('POWER');\n                const sign = script.getNumberValue('SIGNED') % 4;\n                let correction_power = power === 100 ? 39 : power === 75 ? 38 : power === 50 ? 37 : power === 25 ? 36 : 200;\n                let normal = 0;\n                let shift = 4; // 회전 반향 반전\n                let motorR = 0;\n                let motorL = 0;\n\n                if (sign === 0) {\n                    motorR = normal;\n                    motorL = shift;\n                }\n                else if (sign === 1) {\n                    motorR = shift;\n                    motorL = normal;\n                }\n                else if (sign === 2) {\n                    motorR = normal;\n                    motorL = normal;\n                }\n                else if (sign === 3) {\n                    motorR = shift;\n                    motorL = shift;\n                }\n                else { }\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n\n                if (correction_power === 200) {\n                    motorR = 0;\n                    motorL = 0;\n                }\n\n                for (let i = 0; i < 4; i++) {\n                    if (Entry.Robotry_Parodule.getTerminal(i) === Entry.Robotry_Parodule.moduleType.MOTOR) {\n                        if (i === 0 || i === 1) {\n                            Entry.hw.sendQueue.SET[i] = {\n                                type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                                data: motorR + correction_power,\n                                time: new Date().getTime(),\n                            }\n                        }\n                        else if (i === 2 || i === 3) {\n                            Entry.hw.sendQueue.SET[i] = {\n                                type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                                data: motorL + correction_power,\n                                time: new Date().getTime(),\n                            }\n                        }\n                        else { }\n\n                    }\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Motor(%1, %2)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        }\n                    ],\n                }],\n            }\n        },\n        /* Parodule Motor End */\n\n        /* Paroduel Buzzer Start */\n        Parodule_Buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr2.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Octaves_List',\n                        params: ['3'],\n                    },\n                    {\n                        type: 'Parodule_Custom_Tone_List',\n                        params: ['0'],\n                    },\n                ],\n                type: 'Parodule_Buzzer',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                TONE: 1\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const octave = (script.getNumberValue('OCTAVE') - 3) % 4;\n                const tone = script.getNumberValue('TONE') % 13;\n                let correction_octave = octave * 12;\n                let correction_tone = tone ? tone + 46 : 200;\n\n                if (correction_tone === 200) {\n                    correction_octave = 0;\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                for (let i = 0; i < 4; i++) {\n                    if (Entry.Robotry_Parodule.getTerminal(i) === Entry.Robotry_Parodule.moduleType.BUZZER) {\n                        Entry.hw.sendQueue.SET[i] = {\n                            type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                            data: correction_octave + correction_tone,\n                            time: new Date().getTime(),\n                        }\n                    }\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Buzzer(%1, %2)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        }\n                    ],\n                }],\n            }\n        },\n        /* Parodule Buzzer End */\n\n\n        Parodule_Custom_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: Entry.Robotry_Parodule.getOffsetX(Lang.template.Parodule_Custom_title),\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: EntryStatic.colorSet.common.TEXT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.Parodule_Custom_title,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'Parodule_Custom_title',\n            },\n            class: 'TITLE',\n            isNotFor: ['Robotry_Parodule'],\n            events: {},\n        },\n\n\n\n        /* Paroduel Custom PIXEL Start */\n        Parodule_Custom_Pixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'Parodule_Custom_Pixel_List',\n                        params: ['2'],\n                    }\n                ],\n                type: 'Parodule_Custom_Pixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COLOR: 1\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT') % 4;\n                const color = script.getNumberValue('COLOR') % 15;\n                let correction_port = port === 1 ? 3 : port === 2 ? 1 : port === 3 ? 2 : 0;\n                let correction_color = !color ? 200 : color + 18;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[correction_port] = {\n                    type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                    data: correction_color,\n                    time: new Date().getTime(),\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Custom_Pixel(%1, %2)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                },],\n            }\n        },\n        /* Parodule Custom PIXEL End */\n\n        /* Paroduel Custom Motor Start */\n        Parodule_Custom_Motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: [0],\n                    },\n                    {\n                        type: 'Parodule_Custom_Motor_List',\n                        params: [100],\n                    },\n                    {\n                        type: 'Parodule_Custom_Motor_Sign',\n                        params: [0],\n                    }\n                ],\n                type: 'Parodule_Custom_Motor',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                POWER: 1,\n                SIGNED: 2,\n\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT') % 4;\n                const power = script.getNumberValue('POWER');\n                const sign = script.getNumberValue('SIGNED') % 2;\n                let correction_port = port === 1 ? 3 : port === 2 ? 1 : port === 3 ? 2 : 0;\n                let correction_power = power === 100 ? 39 : power === 75 ? 38 : power === 50 ? 37 : power === 25 ? 36 : 200;\n                let correction_sign = sign ? 4 : 0;\n\n                if (correction_power === 200) {\n                    correction_sign = 0;\n                }\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[correction_port] = {\n                    type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                    data: correction_power + correction_sign,\n                    time: new Date().getTime(),\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Custom_Motor(%1, %2, %3)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                }],\n            }\n        },\n        /* Parodule Custom Motor End */\n\n        /* Paroduel Custom Buzzer Start */\n        Parodule_Custom_Buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr2.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'Parodule_Custom_Octaves_List',\n                        params: ['3'],\n                    },\n                    {\n                        type: 'Parodule_Custom_Tone_List',\n                        params: ['0'],\n                    },\n                ],\n                type: 'Parodule_Custom_Buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OCTAVE: 1,\n                TONE: 2\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT') % 4;\n                const octave = (script.getNumberValue('OCTAVE') - 3) % 4;\n                const tone = script.getNumberValue('TONE') % 13;\n                let correction_port = port === 1 ? 3 : port === 2 ? 1 : port === 3 ? 2 : 0;\n                let correction_octave = octave * 12;\n                let correction_tone = tone ? tone + 46 : 200;\n\n                if (correction_tone === 200) {\n                    correction_octave = 0;\n                }\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[correction_port] = {\n                    type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                    data: correction_octave + correction_tone,\n                    time: new Date().getTime(),\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Custom_Buzzer(%1, %2, %3)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                }],\n            }\n        },\n        /* Parodule Custom Buzzer End */\n\n        /* Paroduel Module Off Start */\n        Parodule_Module_Off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: ['0'],\n                    }\n                ],\n                type: 'Parodule_Module_Off',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT') % 4;\n                const value = 200; // 끄기\n                let correction_port = port === 1 ? 3 : port === 2 ? 1 : port === 3 ? 2 : 0;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[correction_port] = {\n                    type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Off(%1)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                }],\n            }\n        },\n        /* Parodule Custom Module Off End */\n\n        /* Paroduel Module Standby Start */\n        Parodule_Module_Standby: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: ['0'],\n                    }\n                ],\n                type: 'Parodule_Module_Standby',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT') % 4;\n                const value = 238; // 대기 동작유지\n                let correction_port = port === 1 ? 3 : port === 2 ? 1 : port === 3 ? 2 : 0;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[correction_port] = {\n                    type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Standby(%1)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                }],\n            }\n        },\n        /* Parodule Module Standby End */\n\n        Parodule_Func_title: {\n            skeleton: 'basic_text',\n            skeletonOptions: {\n                box: {\n                    offsetX: Entry.Robotry_Parodule.getOffsetX(Lang.template.Parodule_Func_title),\n                },\n            },\n            color: EntryStatic.colorSet.common.TRANSPARENT,\n            fontColor: EntryStatic.colorSet.common.TEXT,\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.template.Parodule_Func_title,\n                    color: EntryStatic.colorSet.common.TEXT,\n                    align: 'left',\n                },\n            ],\n            def: {\n                type: 'Parodule_Func_title',\n            },\n            class: 'TITLE',\n            isNotFor: ['Robotry_Parodule'],\n            events: {},\n        },\n\n        /* Paroduel Func Pixel Start */\n        Parodule_Func_Pixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'Parodule_Func_Pixel_List',\n                        params: ['1'],\n                    }\n                ],\n                type: 'Parodule_Func_Pixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                COLOR: 1\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT') % 4;\n                const color = script.getNumberValue('COLOR') % 3;\n                let correction_port = port === 1 ? 3 : port === 2 ? 1 : port === 3 ? 2 : 0;\n                let correction_color = !color ? 200 : color + 16;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n\n                Entry.hw.sendQueue.SET[correction_port] = {\n                    type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                    data: correction_color,\n                    time: new Date().getTime(),\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Func_Pixel(%1, %2)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                },],\n            }\n        },\n        /* Paroduel Func Pixel  End */\n\n        /* Paroduel Func Buzzer Start */\n        Parodule_Func_Buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr2.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Parodule_Custom_Port_List',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'Parodule_Func_Tone_List',\n                        params: ['1'],\n                    },\n                ],\n                type: 'Parodule_Func_Buzzer',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                TONE: 1\n            },\n            class: 'SET',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT') % 4;\n                const tone = script.getNumberValue('TONE') % 3;\n                let correction_port = port === 1 ? 3 : port === 2 ? 1 : port === 3 ? 2 : 0;\n                let correction_tone = !tone ? 200 : tone + 44;\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[correction_port] = {\n                    type: Entry.Robotry_Parodule.controlTypes.DIGITAL,\n                    data: correction_tone,\n                    time: new Date().getTime(),\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [{\n                    syntax: 'Parodule.set_Func_Buzzer(%1, %2)',\n                    textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                }],\n            }\n        },\n        /* Parodule Func Buzzer End */\n\n        /* Parodule Upadate Start */\n        Parodule_Update: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                }\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'Parodule_Update',\n            },\n            paramsKeyMap: {},\n            class: 'CMD',\n            isNotFor: ['Robotry_Parodule'],\n            func(sprite, script) {\n                const update = \"update\\r\\n\";\n                if (!Entry.hw.sendQueue.CMD) {\n                    Entry.hw.sendQueue.CMD = {};\n                }\n                Entry.hw.sendQueue.CMD = {\n                    type: Entry.Robotry_Parodule.controlTypes.STRING,\n                    data: update,\n                    time: new Date().getTime(),\n                }\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            }\n        },\n        /* Parodule Update END */\n    };\n};\n\n\nmodule.exports = Entry.Robotry_Parodule;"
  },
  {
    "path": "src/playground/blocks/hardware/block_robotry_robit_stage.js",
    "content": "'use strict';\n\nEntry.Robotry_Robit_Stage = {\n    id: ['4B.1'],\n    name: 'Robotry_Robit_Stage',\n    url: 'http://robotry.co.kr',\n    imageName: 'arduinoNano.png',\n    title: {\n        ko: '로빗 무대',\n        en: 'Robit Stage',\n    },\n\n   setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n        Entry.hw.update();\n    },\n\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    BlockState: {},\n};\n\nEntry.Robotry_Robit_Stage.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                // 로빗 무대 블록\n                Robotry_Robit_Stage_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                Robotry_Robit_Stage_get_ultrasonic: '초음파 센서 (cm) ',\n                Robotry_Robit_Stage_get_sensor_value: '%1 센서 (0 ~ 1023)',\n\n                Robotry_Robit_Stage_set_tone: '%2 옥타브 %3 %4 초 동안 연주하기 %5',\n                Robotry_Robit_Stage_set_led:'%1 LED %2 %3',\n                Robotry_Robit_Stage_set_bidirectional_motor:'%3 으로 모터 회전시키기 %4',\n                Robotry_Robit_Stage_set_stop_the_motor: '모터를 정지합니다. %3',\n                \n                Robotry_Robit_Stage_set_led_pwm: '%1 LED 를 %2 의 밝기로 켜기 %3',\n                Robotry_Robit_Stage_set_bidirectional_motor_pwm:'%3 으로 %4 만큼 모터 회전시키기 %5',\n            },\n            Helper:{ // 블록 선택시 나타나는 한글 설명\n                // Get\n                Robotry_Robit_Stage_get_analog_value_map:\n                \"놓여진 센서블록 값의 범위를 원하는 범위로 변환합니다. </br></br>이 블록을 사용하면 센서로부터 받은 데이터를 </br>사용자의 상황에 맞게 가공할 수 있습니다. </br></br>ex) 0 부터 1023 까지의 값을 0 부터 255 까지의 값으로 맵핑합니다.\",\n                Robotry_Robit_Stage_get_ultrasonic:\n                \"로빗무대에 전면에 있는 초음파 센서로부터 앞에 놓여진 </br>대상과의 거리를 계산합니다. (단위는 cm 입니다.)\",\n                Robotry_Robit_Stage_get_sensor_value:\n                \"로빗무대는 제품 상단에 위치한 구멍으로 부터 </br>빛(왼쪽 구멍)과 소리(오른쪽 구멍)를 감지할 수 있습니다. </br></br>센서블록은 각 센서로부터 주변 환경 데이터를 받아 </br>0 부터 1023 까지의 값으로 표현합니다. </br></br>블럭의 값은 센서에 입력되는 빛 혹은 소리의 세기가 </br>강하면 값이 높아지고 약하면 낮아집니다.\",\n                // Set\n                Robotry_Robit_Stage_set_tone:\n                \"옥타브와 음계를 선택해서 해당하는 음을 내장된 부저를 통해 </br>연주할 수 있습니다.\",\n                Robotry_Robit_Stage_set_led:\n                \"LED 를 On / Off 할 수 있습니다.\",\n                Robotry_Robit_Stage_set_bidirectional_motor:\n                \"모터는 정방향과 역방향으로 회전할 수 있습니다.\",\n                Robotry_Robit_Stage_set_stop_the_motor:\n                \"모터의 회전을 멈출수 있습니다.\",\n                // PMW\n                Robotry_Robit_Stage_set_led_pwm:\n                \"LED 의 밝기를 0 부터 255까지 값으로 조절할 수 있습니다. </br></br>LED 의 밝기는 0 에 가까워 질수록 어두워지고 </br>255 에 가까워 질수록 밝아집니다.\",\n                Robotry_Robit_Stage_set_bidirectional_motor_pwm:\n                \"모터의 회전 방향과 0 부터 255 값으로 모터의 회전력을 </br>제어할 수 있습니다. </br></br>모터의 회전력은 0 에 가까워 질수록 약해지고 </br>255 에 가까워 질수록 강해집니다.\",\n            },  \n            Blocks : {\n                silent : '무음',\n                do_name : '도',\n                do_sharp_name : '도#(레♭)',\n                re_name :'레',\n                re_sharp_name : '레#(미♭)', \n                mi_name : '미',\n                fa_name : '파',\n                fa_sharp_name : '파#(솔♭)',\n                sol_name : '솔',\n                sol_sharp_name : '솔#(라♭)' ,\n                la_name : '라',\n                la_sharp_name : '라#(시♭)' ,\n                si_name : '시',\n                // 드롭 다운 메뉴\n                left : '왼쪽',\n                right : '오른쪽',\n                light_s : '빛 감지',\n                mic_s : '소리 감지',\n                clockwise : '정방향',\n                counter_clockwise : '역방향',\n                position_the_sensorblock : '센서블록을 놓아주세요.',\n                on : '켜기',\n                off : '끄기',\n            }\n        },\n        en: {\n            template: {\n                // 로빗 무대 블록\n                Robotry_Robit_Stage_get_analog_value_map: 'Convert the range of %1 %2 ~ %3 to %4 ~ %5',\n                Robotry_Robit_Stage_get_ultrasonic: 'Ultrasonic Sensor (cm) ',\n                Robotry_Robit_Stage_get_sensor_value: '%1 Sensor (0 ~ 1023)',\n\n                Robotry_Robit_Stage_set_tone: 'Perform %2 Octave %3 for %4 second %5',\n                Robotry_Robit_Stage_set_led:'%1 LED %2 %3',\n                Robotry_Robit_Stage_set_bidirectional_motor:'Rotate Motor to %3 %4',\n                Robotry_Robit_Stage_set_stop_the_motor:'Stop the motor rotation %3',\n                \n                Robotry_Robit_Stage_set_led_pwm: 'Set %1 LED tp %2 Brightness %3',\n                Robotry_Robit_Stage_set_bidirectional_motor_pwm:'Rotate Motor to %3 for %4 %5',\n            },\n            Helper:{\n                // Get\n                Robotry_Robit_Stage_get_analog_value_map:\n                \"The data from each Sensor is represented by a range (0 ~ 1023). </br></br>This data range must be converted. </br>This Block converted the old data range the Sensor to a range (0 ~ 1023).\",\n                Robotry_Robit_Stage_get_ultrasonic:\n                \"Measure the distance from the Ultrasonic Sensor to the object. ( by cm )\",\n                Robotry_Robit_Stage_get_sensor_value:\n                \"Robit Stage senses Light ( Left hole ) and Sound ( Right hole ) via the Sensor above the product.</br></br>Sensor Block represents the data from each Sensor by the range of 0 ~ 1023.</br></br>The higher the number means that the Sensor has detected stronger stimuli.\",\n                // Set\n                Robotry_Robit_Stage_set_tone:\n                \"Choose Octave and Scale to perform the Buzzer.\",\n                Robotry_Robit_Stage_set_led:\n                \"On / Off the LED\",\n                Robotry_Robit_Stage_set_bidirectional_motor:\n                \"Motor rotates to either Forward or Backward.\",\n                Robotry_Robit_Stage_set_stop_the_motor:\n                \"Stop the motor rotation\",\n                // PMW\n                Robotry_Robit_Stage_set_led_pwm:\n                \"The LED has a brightness setting that ranges from 0 to 255.</br>The numbers indicate brightness level.</br></br>The higher the number, the brighter the LED.\",\n                Robotry_Robit_Stage_set_bidirectional_motor_pwm:\n                \"The motor has direction and rotatory power.</br></br>The numbers ( 0~255 ) indicate rotatory power.</br></br>The higher the number, the faster the motor runs.\",\n            }, \n            Blocks : {\n                silent : 'Silent',\n                do_name : 'C',\n                do_sharp_name : 'C#(D♭)',\n                re_name :'D',\n                re_sharp_name : 'D#(E♭)', \n                mi_name : 'E',\n                fa_name : 'F',\n                fa_sharp_name : 'F#(G♭)',\n                sol_name : 'G',\n                sol_sharp_name : 'G#(A♭)' ,\n                la_name : 'A',\n                la_sharp_name : 'A#(B♭)' ,\n                si_name : 'B',\n                // 드롭 다운 메뉴\n                left : 'Left',\n                right : 'Right',\n                light_s : 'Light',\n                mic_s : 'Sound',\n                clockwise : 'Forward',\n                counter_clockwise : 'Backward',\n                position_the_sensorblock : 'Put Sensor Block here',\n                on : 'On',\n                off : 'Off',\n            },\n        },\n    };\n};\n\n// 블록의 배치 순서\nEntry.Robotry_Robit_Stage.blockMenuBlocks = [\n    // Get\n    'Robotry_Robit_Stage_get_analog_value_map',\n    'Robotry_Robit_Stage_get_ultrasonic',\n    'Robotry_Robit_Stage_get_sensor_value',\n    // Set\n    'Robotry_Robit_Stage_set_tone',\n    'Robotry_Robit_Stage_set_led',\n    'Robotry_Robit_Stage_set_bidirectional_motor',\n    'Robotry_Robit_Stage_set_stop_the_motor',\n    // PWM\n    'Robotry_Robit_Stage_set_led_pwm',\n    'Robotry_Robit_Stage_set_bidirectional_motor_pwm',\n];\n\n/* \n *  로보트리의 아두이노 제어 블록 리스트\n *  주석에 블록이라고 표시된것만 제어 블록임 나머진 포트 리스트\n */\nEntry.Robotry_Robit_Stage.getBlocks = function() {\n    const FILLTERSIZE = 30;\n    let checkOnce = false;\n    let stateMIC = false;\n    let sensorVals1 = new Array(FILLTERSIZE);\n    let sensorVals2 = new Array(FILLTERSIZE);\n    sensorVals1.fill(0);\n    sensorVals2.fill(0);\n\n    const ALS = 0;\n    const CMS = 1;\n    const Buzzer = 2;\n    const US_T = 3;\n    const US_E = 4;\n    const Motor_P = 5;\n    const Motor_N = 6;\n    const Led_R = 9;\n    const Led_L = 10;\n\n    return {\n        Robotry_Robit_Stage_text: {\n            color: '#FFD974',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'TextInput',\n                },\n            ],\n            events: {},\n            def: {\n                params: ['10'],\n            },\n            paramsKeyMap: {\n                NAME: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('NAME');\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n       \n        // Buzzer define Start\n        Robotry_Robit_Stage_tone_list: {         // 버저 톤 리스트\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        Robotry_Robit_Stage_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'Robotry_Robit_Stage_tone_list',\n                    },\n                ],\n                type: 'Robotry_Robit_Stage_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'Robotry_Robit_Stage_tone_value',\n                    },\n                ],\n            },\n        },\n        Robotry_Robit_Stage_octave_list: {      // 옥타브 조절\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        }, \n        // Buzzer define End\n\n        /* Robit Stage Block Code Script Start */\n        // Analog value Mapping Start\n        Robotry_Robit_Stage_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: [Lang.Blocks.position_the_sensorblock],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                ],\n                type: 'Robotry_Robit_Stage_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'Get',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        // Analog value Mapping End\n\n        // Sensor Start \n        // TODO 소리감지센서 값 최적화 필요.\n        Robotry_Robit_Stage_get_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.light_s, ALS], [Lang.Blocks.mic_s, CMS]],\n                    value: [ALS],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'Robotry_Robit_Stage_get_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'Get',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                let value = 0;\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1); // 아날로그 핀 넘버\n                }\n                if (port === CMS){\n                    let data = ANALOG[port];\n                    if (checkOnce === false) {\n                        if (data > 80) {\n                            stateMIC = true;\n                        }\n                        else { \n                            stateMIC = false;\n                        }\n                        checkOnce = true;\n                    }\n                    if (!stateMIC) {\n                        data = data - 77;\n                    }\n                    else {\n                        data = data - 88;\n                    }\n                 \n                    let fillterVal = 0;\n                    \n                    data = Math.max(0, data);\n                    data = Math.pow(2, data);\n                    data = Math.min(1024, data);\n                    sensorVals1[FILLTERSIZE - 1] = data;\n                    \n                    for (let i = 0; i < FILLTERSIZE - 1; i++) {\n                        sensorVals1[i] = sensorVals1[i + 1];\n                    }\n                    for (let i = 0; i < FILLTERSIZE; i++) {\n                        // console.log(i + \" array >> \" + sensorVals1[i]);\n                        fillterVal += sensorVals1[i];\n                    }\n                    value = Math.abs(Math.round(fillterVal / FILLTERSIZE));\n                    \n                }\n                else {\n                    let data = ANALOG[port]; \n                    let fillterVal = 0;\n                    sensorVals2[FILLTERSIZE - 1] = data;\n                    for (let i = 0; i < FILLTERSIZE - 1; i++) {\n                        sensorVals2[i] = sensorVals2[i + 1];\n                    }\n                    for (let i = 0; i < FILLTERSIZE; i++) {\n                        // console.log(i + \" array >> \" + sensorVals2[i]);\n                        fillterVal += sensorVals2[i];\n                    }\n                    value = Math.round(fillterVal / FILLTERSIZE); \n                }\n                return value;\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        }, // Sensor End\n        \n        // Ultra Sonic Driver Start (Unit of length : 1cm)\n        Robotry_Robit_Stage_get_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    value: [US_T]\n                },\n                {\n                    value: [US_E]\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'Robotry_Robit_Stage_get_ultrasonic',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'Get',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.Robotry_Robit_Stage.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return  parseInt(Entry.hw.portData.ULTRASONIC) || 0; // cm 소수점 이하 표시 안함\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        }, // Ultra Sonic Driver End\n\n        // LED ON/OFF Start\n        Robotry_Robit_Stage_set_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.right, Led_R], [Lang.Blocks.left, Led_L]],\n                    value: [Led_R],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.on, 'on'], [Lang.Blocks.off, 'off']],\n                    value: 'on',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'Robotry_Robit_Stage_set_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'Set',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                const operator = script.getField('OPERATOR');\n                const value = operator == 'on' ? 255 : 0;\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Robotry_Robit_Stage.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        }, // LED ON/OFF Block End \n\n\n        // LED PWM Start\n        Robotry_Robit_Stage_set_led_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.right, Led_R], [Lang.Blocks.left, Led_L]],\n                    value: [Led_R],\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            event: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'Robotry_Robit_Stage_text',\n                        params: ['255'],\n                    },\n                ],\n                type: 'Robotry_Robit_Stage_set_led_pwm',\n            },\n            paramsKeyMap:{\n                PORT: 0,\n                VALUE: 1\n            },\n            class: 'Set_PWM',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script){\n                const port = script.getNumberValue('PORT');\n                const value = script.getNumberValue('VALUE');\n                // console.log(value);\n                if(!Entry.hw.sendQueue.SET){\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Robotry_Robit_Stage.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        },\n        // LED PWM End\n\n        // Buzzer Control Start\n        Robotry_Robit_Stage_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    value: [Buzzer],\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'Robotry_Robit_Stage_octave_list',\n                    },\n                    {\n                        type: 'Robotry_Robit_Stage_tone_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'Robotry_Robit_Stage_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OCTAVE: 1,\n                NOTE: 2,\n                DURATION: 3,\n            },\n            class: 'Set',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.Robotry_Robit_Stage.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.Robotry_Robit_Stage.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.Robotry_Robit_Stage.toneMap[note][octave];\n                    }\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    sq.SET[port] = {\n                        type: Entry.Robotry_Robit_Stage.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.Robotry_Robit_Stage.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        }, // Buzzer Control End\n\n        // Bidirectional DC Motor Start\n        // 드롭다운 메뉴에서 정방향 역방향을 선택해서 모터의 방향을 제어할수 있따.\n        Robotry_Robit_Stage_set_bidirectional_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    value: [Motor_P],\n                },\n                {\n                    value: [Motor_N],\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.clockwise, 'on'], [Lang.Blocks.counter_clockwise, 'off']],\n                    value: 'on',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'Robotry_Robit_Stage_set_bidirectional_motor',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                OPERATOR: 2,\n            },\n            class: 'Set',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1');\n                const port2 = script.getNumberValue('PORT2');\n                const operator = script.getField('OPERATOR');\n                const forward = operator == 'on' ? 255 : 0;\n                const backward = operator == 'on' ? 0 : 255;\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.Robotry_Robit_Stage.sensorTypes.DIGITAL,\n                    data: forward,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.Robotry_Robit_Stage.sensorTypes.DIGITAL,\n                    data: backward,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        }, // Bidirectional DC Motor End\n\n        // Bidirectional DC Motor PWM Start\n        // 드롭다운 메뉴에서 정방향 역방향을 선택해서 모터의 방향을 제어할수 있따.\n        Robotry_Robit_Stage_set_bidirectional_motor_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    value: [Motor_P],\n                },\n                {\n                    value: [Motor_N],\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.clockwise, 'on'], [Lang.Blocks.counter_clockwise, 'off']],\n                    value: 'on',\n                    fontSize: 12,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                    null,\n                    {\n                        type: 'Robotry_Robit_Stage_text',\n                        params: ['255'],\n                    },\n                ],\n                type: 'Robotry_Robit_Stage_set_bidirectional_motor_pwm',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n                OPERATOR: 2,\n                VALUE: 3,\n            },\n            class: 'Set_PWM',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1');\n                const port2 = script.getNumberValue('PORT2');\n                \n                const operator = script.getField('OPERATOR');\n                const value = script.getNumberValue('VALUE');\n\n                const forward = operator == 'on' ? value : 0;\n                const backward = operator == 'on' ? 0 : value;\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.Robotry_Robit_Stage.sensorTypes.PWM,\n                    data: forward,\n                    time: new Date().getTime(),\n                };\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.Robotry_Robit_Stage.sensorTypes.PWM,\n                    data: backward,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        }, // Bidirectional DC Motor PWM End\n        /* Robit Stage Block Code Script End */\n\n        // Stop the DC Motor Start\n        // 모터 작동을 중지합니다.\n        Robotry_Robit_Stage_set_stop_the_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    value: [Motor_P],\n                },\n                {\n                    value: [Motor_N],\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'Robotry_Robit_Stage_set_stop_the_motor',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'Set',\n            isNotFor: ['Robotry_Robit_Stage'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1');\n                const port2 = script.getNumberValue('PORT2');\n                const operator = 0;\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port1] = {\n                    type: Entry.Robotry_Robit_Stage.sensorTypes.DIGITAL,\n                    data: operator,\n                    time: new Date().getTime(),\n                }\n                Entry.hw.sendQueue.SET[port2] = {\n                    type: Entry.Robotry_Robit_Stage.sensorTypes.DIGITAL,\n                    data: operator,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [],\n            },\n        }, // Stop the DC Motor End\n    };\n};\n\n\nmodule.exports = Entry.Robotry_Robit_Stage;"
  },
  {
    "path": "src/playground/blocks/hardware/block_rokoboard.js",
    "content": "'use strict';\n\nEntry.rokoboard = {\n    id: '13.1',\n    name: 'rokoboard',\n    url: 'http://www.r-steam.com/',\n    imageName: 'rokoboard.png',\n    title: {\n        ko: '로코보드',\n        en: 'rokoboard',\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        imgPath: 'hw/arduino.png',\n        width: 605,\n        height: 434,\n        listPorts: {\n            '2': {\n                name: Lang.Hw.port_en + ' 2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '3': {\n                name: Lang.Hw.port_en + ' 3 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '4': {\n                name: Lang.Hw.port_en + ' 4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '5': {\n                name: Lang.Hw.port_en + ' 5 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '6': {\n                name: Lang.Hw.port_en + ' 6 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '7': {\n                name: Lang.Hw.port_en + ' 7 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '8': {\n                name: Lang.Hw.port_en + ' 8 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '9': {\n                name: Lang.Hw.port_en + ' 9 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '10': {\n                name: Lang.Hw.port_en + ' 10 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '11': {\n                name: Lang.Hw.port_en + ' 11 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '12': {\n                name: Lang.Hw.port_en + ' 12 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '13': {\n                name: Lang.Hw.port_en + ' 13 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: Lang.Hw.port_en + ' A0 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: Lang.Hw.port_en + ' A1 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a2: {\n                name: Lang.Hw.port_en + ' A2 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a3: {\n                name: Lang.Hw.port_en + ' A3 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a4: {\n                name: Lang.Hw.port_en + ' A4 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a5: {\n                name: Lang.Hw.port_en + ' A5 ' + Lang.Hw.port_ko,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.rokoboard.blockMenuBlocks = [\n    //rokoboard Blocks\n    'rokoboard_get_sensor_value_by_name',\n    'rokoboard_is_button_pressed',\n];\n\nEntry.rokoboard.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                rokoboard_get_sensor_value_by_name: '%1 의 센서값',\n            },\n            Blocks: {\n                rokoboard_sensor_name_0: '소리',\n                rokoboard_sensor_name_1: '빛',\n                rokoboard_sensor_name_2: '슬라이더',\n                rokoboard_sensor_name_3: '저항-A',\n                rokoboard_sensor_name_4: '저항-B',\n                rokoboard_sensor_name_5: '저항-C',\n                rokoboard_sensor_name_6: '저항-D',\n                rokoboard_string_1: '버튼을 눌렀는가?',\n            },\n        },\n        en: {\n            template: {\n                rokoboard_get_sensor_value_by_name: '%1 value',\n            },\n            Blocks: {\n                rokoboard_sensor_name_0: 'Sound',\n                rokoboard_sensor_name_1: 'Light',\n                rokoboard_sensor_name_2: 'Slider',\n                rokoboard_sensor_name_3: 'resistance-A',\n                rokoboard_sensor_name_4: 'resistance-B',\n                rokoboard_sensor_name_5: 'resistance-C',\n                rokoboard_sensor_name_6: 'resistance-D',\n                rokoboard_string_1: 'Button Pressed',\n            },\n        },\n    };\n};\n\nEntry.rokoboard.getBlocks = function() {\n    return {\n        //region rokoboard 로코보드\n        // rokoboard Implementation\n        rokoboard_get_sensor_value_by_name: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.rokoboard_sensor_name_1, '1'],\n                        [Lang.Blocks.rokoboard_sensor_name_0, '0'],\n                        [Lang.Blocks.rokoboard_sensor_name_2, '2'],\n                        [Lang.Blocks.rokoboard_sensor_name_3, '3'],\n                        [Lang.Blocks.rokoboard_sensor_name_4, '4'],\n                        [Lang.Blocks.rokoboard_sensor_name_5, '5'],\n                        [Lang.Blocks.rokoboard_sensor_name_6, '6'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'rokoboard_get_sensor_value_by_name',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'rokoboard_sensor',\n            isNotFor: ['rokoboard'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n        },\n        rokoboard_is_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Text',\n                    text: Lang.Blocks.rokoboard_string_1,\n                    color: '#fff',\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'rokoboard_is_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'rokoboard_sensor',\n            isNotFor: ['rokoboard'],\n            func: function(sprite, script) {\n                var port = 7;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                return ANALOG ? ANALOG[port] < 1 : false;\n            },\n        },\n        //endregion rokoboard 로코보드\n    };\n};\n\nmodule.exports = Entry.rokoboard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_runcoding.js",
    "content": "'use strict';\n\nEntry.Runcoding = {\n    id: '17.1',\n    name: 'Runcoding',\n    url: 'https://runcoding.co.kr/',\n    imageName: 'runcoding.png',\n    title: {\n        ko: '코마크레',\n        en: 'runcoding',\n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });\n        }\n\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        SERVO_PIN: 4,\n        TONE: 5,\n        PULSEIN: 6,\n        ULTRASONIC: 7,\n        TIMER: 8,\n        METRIX : 9,\n        METRIXCLEAR: 11,\n        METRIXROWCOLCLEAR: 12,\n        METRIXDRAW : 13,\n        NEOPIXEL : 14,\n        NEOPIXELCLEAR : 15,\n        NEOPIXELINIT : 16,\n        NEOPIXELRAINBOW: 17,\n        NEOPIXELEACH: 18,\n        LCDINIT: 19,\n        LCD: 20,\n        LCDCLEAR: 21,\n        TEMPCHECK: 22,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3, \n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\nEntry.Runcoding.setLanguage = function() {\n\n    return {\n        ko: {\n            template: {\n                arduino_runcoding_get_analog_value: '아날로그 %1 번 센서값',\n                arduino_runcoding_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                arduino_runcoding_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값',\n                arduino_runcoding_toggle_led: '디지털 %1 번 핀 %2 %3',\n                arduino_runcoding_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                arduino_runcoding_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5',\n                arduino_runcoding_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3',\n                arduino_runcoding_get_digital: '디지털 %1 번 센서값',\n\n                arduino_runcoding_get_temp: '온도 값 가져오기',\n\n                arduino_runcoding_set_neopixel_init: '네오픽셀 설정 (%1 핀) led %2 개를 %3 밝기로 설정하기 %4',\n                arduino_runcoding_set_neopixel: '네오픽셀 (%1 핀) RGB ( %2, %3, %4) %5',\n                arduino_runcoding_set_neopixel_each: '네오픽셀(%1 핀) LED (%2 번 쨰) RGB ( %3, %4, %5) %6',\n                arduino_runcoding_set_neopixel_rainbow: '무지개 표현하기 (%1 핀) %2 %3',\n                arduino_runcoding_set_neopixel_clear: '네오픽셀 지우기 (%1 핀) %2',\n\n                arduino_runcoding_set_metrix: '도트매트릭스 그리기 (열 %1 - 행 %2) %3',\n                arduino_runcoding_set_metrix_draw: '도트매트릭스 그리기 %1 %2',\n                arduino_runcoding_set_metrix_rowcol_clear: '도트매트릭스 지우기 (열 %1 - 행 %2) %3',\n                arduino_runcoding_set_metrix_clear: '도트매트릭스 전체 지우기 %1',\n\n                arduino_runcoding_set_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 열: 16, 행: 2) %2',\n                arduino_runcoding_lcd_row_col: 'LCD %1 행 %2 열 부터 %3 출력 %4',\n                arduino_runcoding_lcd_clear: 'LCD 화면 지우기 %1',\n\n               \n\n\n            },\n        },\n        en: {\n            template: {\n                arduino_runcoding_get_analog_value: 'Analog %1 Sensor value',\n                arduino_runcoding_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                arduino_runcoding_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2',\n                arduino_runcoding_toggle_led: 'Digital %1 Pin %2 %3',\n                arduino_runcoding_digital_pwm: 'Digital %1 Pin %2 %3',\n                arduino_runcoding_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5',\n                arduino_runcoding_set_servo: 'Set servo pin %1 angle as %2 %3',\n                arduino_runcoding_get_digital: 'Digital %1 Sensor value',\n\n                arduino_runcoding_get_temp: '온도 값 가져오기',\n\n\n                arduino_runcoding_set_neopixel_init: 'set neopixel pin: %1 led-count: %2 bright: %3 %4',\n                arduino_runcoding_set_neopixel: 'neopixel pin: %1 (R:%2 G:%3 B:%4) %5',\n                arduino_runcoding_set_neopixel_each: 'neopixel pin: %1 LED %2 RGB ( %3, %4, %5) %6',\n                arduino_runcoding_set_neopixel_rainbow: 'neopixel pin: %1 %2 %4',\n                arduino_runcoding_set_neopixel_clear: 'clear neopixel pin: %1 %2',\n\n                arduino_runcoding_set_metrix: '8x8 paint dot-merix (row : %1, col: %2) %3',\n                arduino_runcoding_set_metrix_draw: '8x8 paint dot-merix %1 %2',\n                arduino_runcoding_set_metrix_rowcol_clear: 'Clear dot-metrix (row : %1, col: %2) %3',\n                arduino_runcoding_set_metrix_clear: 'Clear all dot-metrix %1',\n\n                arduino_runcoding_set_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1, 열: 16, 행: 2) %2',\n                arduino_runcoding_lcd_row_col: 'LCD %1 행 %2 열 부터 %3 출력 %4',\n                arduino_runcoding_lcd_clear: 'LCD 화면 지우기 %1',\n\n              \n               \n            },\n        },\n    };\n};\n\nEntry.Runcoding.blockMenuBlocks = [\n    'arduino_runcoding_get_analog_value',\n    'arduino_runcoding_get_analog_value_map',\n    'arduino_runcoding_get_ultrasonic_value',\n    'arduino_runcoding_get_digital',\n    'arduino_runcoding_toggle_led',\n    'arduino_runcoding_digital_pwm',\n    'arduino_runcoding_set_servo',\n    'arduino_runcoding_set_tone',\n    'arduino_runcoding_get_temp',\n    'arduino_runcoding_set_neopixel_init',\n    'arduino_runcoding_set_neopixel',\n    'arduino_runcoding_set_neopixel_each',\n    'arduino_runcoding_set_neopixel_rainbow',\n    'arduino_runcoding_set_neopixel_clear',\n    'arduino_runcoding_set_metrix',\n    'arduino_runcoding_set_metrix_draw',\n    'arduino_runcoding_set_metrix_rowcol_clear',\n    'arduino_runcoding_set_metrix_clear',\n    'arduino_runcoding_set_lcd_init',\n    'arduino_runcoding_lcd_row_col',\n    'arduino_runcoding_lcd_clear',\n   \n];\n\n//region Runcoding 아두이노 확장모드\nEntry.Runcoding.getBlocks = function() {\n    return {\n        arduino_runcoding_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_runcoding_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_runcoding_analog_list',\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_runcoding_analog_list',\n                    },\n                ],\n                type: 'arduino_runcoding_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'RuncodingGet',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_runcoding_get_analog_value',\n                        params: [\n                            {\n                                type: 'arduino_runcoding_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'arduino_runcoding_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'RuncodingGet',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_get_ultrasonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['6'],\n                    },\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['5'],\n                    },\n                ],\n                type: 'arduino_runcoding_get_ultrasonic_value',\n            },\n            paramsKeyMap: {\n                PORT1: 0,\n                PORT2: 1,\n            },\n            class: 'RuncodingGet',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const port1 = script.getNumberValue('PORT1', script);\n                const port2 = script.getNumberValue('PORT2', script);\n\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                delete Entry.hw.sendQueue.SET[port1];\n                delete Entry.hw.sendQueue.SET[port2];\n\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.Runcoding.sensorTypes.ULTRASONIC] = {\n                    port: [port1, port2],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.ULTRASONIC || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.ultrasonicRead(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'arduino_runcoding_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'RuncodingGet',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Runcoding' || name === 'ArduinoNano') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Runcoding.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_get_digital_toggle[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_get_digital_toggle',\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'arduino_runcoding_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Runcoding.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Runcoding.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Runcoding.sensorTypes.DIGITAL,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'arduino_runcoding_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Runcoding.sensorTypes.PWM,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_tone_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.silent, '0'],\n                                    [Lang.Blocks.do_name, 'C'],\n                                    [Lang.Blocks.do_sharp_name, 'CS'],\n                                    [Lang.Blocks.re_name, 'D'],\n                                    [Lang.Blocks.re_sharp_name, 'DS'],\n                                    [Lang.Blocks.mi_name, 'E'],\n                                    [Lang.Blocks.fa_name, 'F'],\n                                    [Lang.Blocks.fa_sharp_name, 'FS'],\n                                    [Lang.Blocks.sol_name, 'G'],\n                                    [Lang.Blocks.sol_sharp_name, 'GS'],\n                                    [Lang.Blocks.la_name, 'A'],\n                                    [Lang.Blocks.la_sharp_name, 'AS'],\n                                    [Lang.Blocks.si_name, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_runcoding_tone_list',\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_tone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_runcoding_tone_list',\n                    },\n                ],\n                type: 'arduino_runcoding_tone_value',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func(sprite, script) {\n                return script.getNumberValue('NOTE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'arduino_runcoding_tone_value',\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_octave_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        keyOption: 'arduino_runcoding_octave_list',\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_runcoding_tone_list',\n                    },\n                    {\n                        type: 'arduino_runcoding_octave_list',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'arduino_runcoding_set_tone',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NOTE: 1,\n                OCTAVE: 2,\n                DURATION: 3,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    let note = script.getValue('NOTE', script);\n                    if (!Entry.Utils.isNumber(note)) {\n                        note = Entry.Runcoding.toneTable[note];\n                    }\n\n                    if (note < 0) {\n                        note = 0;\n                    } else if (note > 12) {\n                        note = 12;\n                    }\n\n                    let duration = script.getNumberValue('DURATION', script);\n\n                    if (duration < 0) {\n                        duration = 0;\n                    }\n\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    if (duration === 0) {\n                        sq.SET[port] = {\n                            type: Entry.Runcoding.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\n                    let octave = script.getNumberValue('OCTAVE', script) - 1;\n                    if (octave < 0) {\n                        octave = 0;\n                    } else if (octave > 5) {\n                        octave = 5;\n                    }\n\n                    let value = 0;\n\n                    if (note != 0) {\n                        value = Entry.Runcoding.toneMap[note][octave];\n                    }\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.TONE,\n                        data: {\n                            value,\n                            duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(() => {\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tone(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_neopixel_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    {\n                        type: 'number',\n                        params: ['16'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                ],\n                type: 'arduino_runcoding_set_neopixel_init',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE1: 1,\n                VALUE2: 2,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value1 = script.getNumberValue('VALUE1', script);\n                let value2 = script.getNumberValue('VALUE2', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.NEOPIXELINIT,\n                        data:{value1,value2},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixel_init(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_neopixel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_runcoding_set_neopixel',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                R: 1,\n                G: 2,\n                B: 3,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let R_val = script.getNumberValue('R', script);\n                let G_val = script.getNumberValue('G', script);\n                let B_val = script.getNumberValue('B', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.NEOPIXEL,\n                        data:{R_val,G_val,B_val},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixel(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_neopixel_each: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_runcoding_set_neopixel_each',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                CNT: 1,\n                R: 2,\n                G: 3,\n                B: 4,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let CNT_val = script.getNumberValue('CNT', script);\n                let R_val = script.getNumberValue('R', script);\n                let G_val = script.getNumberValue('G', script);\n                let B_val = script.getNumberValue('B', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.NEOPIXELEACH,\n                        data:{CNT_val,R_val,G_val,B_val},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixel_each(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_neopixel_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['무지개', '1'],\n                        ['조명효과', '2'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['무지개', '1'],\n                                    ['조명효과', '2'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_runcoding_set_neopixel_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_runcoding_set_neopixel_list',\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_neopixel_rainbow: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [ \n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_runcoding_set_neopixel_rainbow',\n            },\n            paramsKeyMap: {\n                PORT : 0,\n                VALUE: 1,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.NEOPIXELRAINBOW,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.neopixel_rainbow(%1, %2)',\n                        \n                        textParams: \n                        [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ]\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_neopixel_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [6],\n                    },\n                    \n                ],\n                type: 'arduino_runcoding_set_neopixel_clear',\n            },\n            paramsKeyMap: {\n                PORT : 0,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port =  script.getNumberValue('PORT', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.NEOPIXELCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    { \n\n                        syntax: 'Arduino.neopixeclear(%1)',\n                        textParams: \n                        [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ]\n                    }\n                ],\n            },\n        },\n        arduino_runcoding_set_metrix: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_runcoding_set_metrix',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let value1 = script.getNumberValue('VALUE1', script) +10;\n                let value2 = script.getNumberValue('VALUE2', script) + 10;\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[12] = {\n                        type: Entry.Runcoding.sensorTypes.METRIX,\n                        data:{value1,value2},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.metrix(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_metrix_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '10'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            func(sprite, script) {\n                return script.getField('VALUE');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['0', '10'],\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                    ['9', '9'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_runcoding_set_metrix_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_runcoding_set_metrix_list',\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_metrix_draw: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [ \n                    {\n                        type: 'arduino_runcoding_set_metrix_list',\n                    }\n                ],\n                type: 'arduino_runcoding_set_metrix_draw',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                let value = script.getNumberValue('VALUE', script);\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n\n                    sq.SET[12] = {\n                        type: Entry.Runcoding.sensorTypes.METRIXDRAW,\n                        data: value,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.draw(%1)',\n                        textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ]\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_metrix_rowcol_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_runcoding_set_metrix_rowcol_clear',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let value1 = script.getNumberValue('VALUE1', script) + 10;\n                let value2 = script.getNumberValue('VALUE2', script) + 10;\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[12] = {\n                        type: Entry.Runcoding.sensorTypes.METRIXROWCOLCLEAR,\n                        data:{value1,value2},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.metrix_rowcol_clear(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_metrix_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    \n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \n                ],\n                type: 'arduino_runcoding_set_metrix_clear',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 12;\n\n                if (!script.isStart) {\n             \n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.METRIXCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    { }\n                ],\n            },\n        },\n        arduino_runcoding_lcd_list_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0x27', '0'],\n                        ['0x3F', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        arduino_runcoding_lcd_row_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                        ['9', '9'],\n                        ['10', '10'],\n                        ['11', '11'],\n                        ['12', '12'],\n                        ['13', '13'],\n                        ['14', '14'],\n                        ['15', '15'],\n\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        arduino_runcoding_lcd_col_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                LINE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('LINE');\n            },\n        },\n        arduino_runcoding_set_lcd_init: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_runcoding_lcd_list_init',\n                        params: ['0'],\n                    },\n                ],\n                type: 'arduino_runcoding_set_lcd_init',\n            },\n            paramsKeyMap: {\n                LIST: 0,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const list = script.getNumberValue('LIST', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n \n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n\n                    sq.SET[1] = {\n                        type: Entry.Runcoding.sensorTypes.LCDINIT,\n                        data: {\n                            list: list,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.lcd_init(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_lcd_row_col: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [ \n                    {\n                        type: 'arduino_runcoding_lcd_row_list',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'arduino_runcoding_lcd_col_list',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['coding'],\n                    },\n                ],\n                type: 'arduino_runcoding_lcd_row_col',\n            },\n            paramsKeyMap: {\n                ROW: 0,\n                COL: 1,\n                VALUE: 2,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n\n                let row = script.getNumberValue('ROW', script);\n                let col = script.getNumberValue('COL', script);\n                let value = script.getValue('VALUE', script);\n                value += '';\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 100;\n\n\n                    sq.SET[1] = {\n                        type: Entry.Runcoding.sensorTypes.LCD,\n                        data: {row, col, value},\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.lcd(%1,%2,%3)',\n                        textParams: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ]\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_lcd_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    \n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    \n                ],\n                type: 'arduino_runcoding_lcd_clear',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = 1;\n\n                if (!script.isStart) {\n            \n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[port] = {\n                        type: Entry.Runcoding.sensorTypes.LCDCLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                }else if (script.timeFlag == 1) {\n                    return script;\n                }else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    { }\n                ],\n            },\n        },\n        arduino_runcoding_get_temp: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'arduino_runcoding_get_temp',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'RuncodingGet',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const port = 2;\n                const TEMPCHECK = Entry.hw.portData.TEMPCHECK;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.Runcoding.sensorTypes.TEMPCHECK] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n\n                return TEMPCHECK;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.tempcheckRead(%1,%2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        arduino_runcoding_set_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: ['4'],\n                    },\n                    null,\n                ],\n                type: 'arduino_runcoding_set_servo',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const port = script.getNumberValue('PORT', script);\n                let value = script.getNumberValue('VALUE', script);\n                value = Math.min(180, value);\n                value = Math.max(0, value);\n\n                if (!sq.SET) {\n                    sq.SET = {};\n                }\n                sq.SET[port] = {\n                    type: Entry.Runcoding.sensorTypes.SERVO_PIN,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n\n                return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.servomotorWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n//endregion Runcoding 아두이노 확장모드\n\nmodule.exports = Entry.Runcoding;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_runcoding_display.js",
    "content": "'use strict';\n\nEntry.Runcoding_display = {\n    id: '17.2',\n    name: 'Runcoding_display',\n    url: 'https://runcoding.co.kr/',\n    imageName: 'runcoding_display.png',\n    title: {\n        ko: '코마크레 display',\n        en: 'runcoding display',    \n    },\n    setZero() {\n        if (!Entry.hw.sendQueue.SET) {\n            Entry.hw.sendQueue = {\n                GET: {},\n                SET: {},\n            };\n        } else {\n            const keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach((key) => {\n                const command = Entry.hw.sendQueue.SET[key];\n                // OLED 관련 명령은 setZero에서 제외\n                if (command && \n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_TEXT &&\n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_CLEAR &&\n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_SMILE &&\n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_SAD &&\n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_ANGRY &&\n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_ANIM_STAR &&\n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_ANIM_FLOWER &&\n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_ANIM_SNOW &&\n                    command.type !== Entry.Runcoding_led.sensorTypes.OLED_ANIM_STOP) {\n                Entry.hw.sendQueue.SET[key].data = 0;\n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n                } else {\n                    // OLED 명령은 삭제\n                    delete Entry.hw.sendQueue.SET[key];\n                }\n            });\n        }\n\n        Entry.hw.update();\n    },\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        PWM: 3,\n        PULSEIN: 6,\n        TIMER: 8,\n        OLED_ADDR: 23,\n        OLED_TEXT: 24,\n        OLED_CLEAR: 25,\n        OLED_SMILE: 26,\n        OLED_SAD: 27,\n        OLED_ANGRY: 28,\n        OLED_ANIM_STAR: 29,\n        OLED_ANIM_FLOWER: 30,\n        OLED_ANIM_SNOW: 31,\n        OLED_ANIM_STOP: 32,\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\n};\n\n// Keep legacy namespace references working.\nEntry.Runcoding_led = Entry.Runcoding_led || Entry.Runcoding_display;\n\nEntry.Runcoding_led.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                runcoding_led_get_analog_value: '아날로그 %1 번 센서값',\n                runcoding_led_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                runcoding_led_get_digital: '디지털 %1 번 센서값',\n                runcoding_led_toggle_led: '디지털 %1 번 핀 %2 %3',\n                runcoding_led_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n\n                runcoding_led_display: 'OLED %1 표현하기 X: %2 Y: %3 크기: %4 %5',\n                runcoding_led_display_clear: 'OLED 화면 지우기 %1',\n                runcoding_led_display_smile: '웃는얼굴 표현하기 %1',\n                runcoding_led_display_sad: '슬픈표정 표현하기 %1',\n                runcoding_led_display_angry: '화난얼굴 표현하기 %1',\n                runcoding_led_display_emotion: '%1 표정 표현하기 %2',\n                runcoding_led_animation_star: 'OLED 별 떨어지기 개수:%1(max:20) 속도:%2(max:10) %3',\n                runcoding_led_animation_flower: 'OLED 꽃송이 떨어지기 개수:%1(max:20) 속도:%2(max:10) %3',\n                runcoding_led_animation_snow: 'OLED 눈송이 떨어지기 개수:%1(max:20) 속도:%2(max:10) %3',\n                runcoding_led_animation_stop: 'OLED 애니메이션 정지하기 %1',\n            },\n        },\n        en: {\n            template: {\n                runcoding_led_get_analog_value: 'analog %1 sensor value',\n                runcoding_led_get_analog_value_map: 'map %1 from %2 ~ %3 to %4 ~ %5',\n                runcoding_led_get_digital: 'digital %1 sensor value',\n                runcoding_led_toggle_led: 'digital %1 pin %2 %3',\n                runcoding_led_digital_pwm: 'set digital %1 pin to %2 %3',\n\n                runcoding_led_display: 'display %1 on OLED X:%2 Y:%3 size:%4 %5',\n                runcoding_led_display_clear: 'clear OLED display %1',\n                runcoding_led_display_smile: 'display smile face %1',\n                runcoding_led_display_sad: 'display sad face %1',\n                runcoding_led_display_angry: 'display angry face %1',\n                runcoding_led_display_emotion: 'display %1 emotion %2',\n                runcoding_led_animation_star: 'OLED falling stars count:%1(max:20) speed:%2(max:10) %3',\n                runcoding_led_animation_flower: 'OLED falling flowers count:%1(max:20) speed:%2(max:10) %3',\n                runcoding_led_animation_snow: 'OLED falling snowflakes count:%1(max:20) speed:%2(max:10) %3',\n                runcoding_led_animation_stop: 'stop OLED animation %1',\n            },\n        },\n    };\n};\n\nEntry.Runcoding_led.blockMenuBlocks = [\n    'runcoding_led_get_analog_value',\n    'runcoding_led_get_analog_value_map',\n    'runcoding_led_get_digital',\n    'runcoding_led_toggle_led',\n    'runcoding_led_digital_pwm',\n    'runcoding_led_display',\n    'runcoding_led_display_emotion',\n    'runcoding_led_display_clear',\n    'runcoding_led_animation_star',\n    'runcoding_led_animation_flower',\n    'runcoding_led_animation_snow',\n    'runcoding_led_animation_stop',\n];\n\nEntry.Runcoding_led.getBlocks = function() {\n    return {\n        runcoding_led_analog_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['A0', '0'],\n                        ['A1', '1'],\n                        ['A2', '2'],\n                        ['A3', '3'],\n                        ['A4', '4'],\n                        ['A5', '5'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func(sprite, script) {\n                return script.getField('PORT');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['A0', '0'],\n                                    ['A1', '1'],\n                                    ['A2', '2'],\n                                    ['A3', '3'],\n                                    ['A4', '4'],\n                                    ['A5', '5'],\n                                ],\n                                value: '0',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_runcoding_analog_list[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'arduino_runcoding_analog_list',\n                    },\n                ],\n            },\n        },\n        runcoding_led_emotion_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['웃는얼굴', 'smile'],\n                        ['슬픈표정', 'sad'],\n                        ['화난얼굴', 'angry'],\n                    ],\n                    value: 'smile',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                EMOTION: 0,\n            },\n            func(sprite, script) {\n                return script.getField('EMOTION');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['웃는얼굴', 'smile'],\n                                    ['슬픈표정', 'sad'],\n                                    ['화난얼굴', 'angry'],\n                                ],\n                                value: 'smile',\n                                fontSize: 11,\n                                converter: Entry.block.converters.returnStringKey,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'runcoding_led_emotion_list',\n                    },\n                ],\n            },\n        },\n        runcoding_led_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'runcoding_led_analog_list',\n                    },\n                ],\n                type: 'runcoding_led_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'runcoding_led_get',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                let port = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                return ANALOG ? ANALOG[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_get_analog_value_map: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'runcoding_led_get_analog_value',\n                        params: [\n                            {\n                                type: 'runcoding_led_analog_list',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'runcoding_led_get_analog_value_map',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'runcoding_led_get',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                let result = script.getValue('PORT', script);\n                const ANALOG = Entry.hw.portData.ANALOG;\n                let value2 = script.getNumberValue('VALUE2', script);\n                let value3 = script.getNumberValue('VALUE3', script);\n                let value4 = script.getNumberValue('VALUE4', script);\n                let value5 = script.getNumberValue('VALUE5', script);\n                const stringValue4 = script.getValue('VALUE4', script);\n                const stringValue5 = script.getValue('VALUE5', script);\n                let isFloat = false;\n\n                if (\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                ) {\n                    isFloat = true;\n                }\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                if (isFloat) {\n                    result = Math.round(result * 100) / 100;\n                } else {\n                    result = Math.round(result);\n                }\n\n                return result;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.map(%1, %2, %3, %4, %5)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_get_digital: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'runcoding_led_get_digital',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'RuncodingGet',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const { hwModule = {} } = Entry.hw;\n                const { name } = hwModule;\n                if (name === 'Runcoding' || name === 'ArduinoNano') {\n                    const port = script.getNumberValue('PORT', script);\n                    const DIGITAL = Entry.hw.portData.DIGITAL;\n                    if (!Entry.hw.sendQueue.GET) {\n                        Entry.hw.sendQueue.GET = {};\n                    }\n                    Entry.hw.sendQueue.GET[Entry.Runcoding_led.sensorTypes.DIGITAL] = {\n                        port,\n                        time: new Date().getTime(),\n                    };\n                    return DIGITAL ? DIGITAL[port] || 0 : 0;\n                } else {\n                    return Entry.block.arduino_get_digital_value.func(sprite, script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalRead(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_get_digital_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\n                    value: 'on',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OPERATOR: 0,\n            },\n            func(sprite, script) {\n                return script.getStringField('OPERATOR');\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: '%1',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\n                                ],\n                                value: 'on',\n                                fontSize: 11,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValueUpperCase,\n                                codeMap: 'Entry.CodeMap.Arduino.arduino_get_digital_toggle[0]',\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            },\n                        ],\n                        keyOption: 'runcoding_led_get_digital_toggle',\n                    },\n                ],\n            },\n        },\n        runcoding_led_get_pulse: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [2],\n                    },\n                ],\n                type: 'runcoding_led_get_pulse',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'runcoding_led_get',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT', script);\n                const PULSEIN = Entry.hw.portData.PULSEIN;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.Runcoding_led.sensorTypes.PULSEIN] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n                return PULSEIN ? PULSEIN[port] || 0 : 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.pulseIn(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_get_timer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'runcoding_led_get_timer',\n            },\n            paramsKeyMap: {},\n            class: 'runcoding_led_get',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const TIMER = Entry.hw.portData.TIMER;\n                if (!Entry.hw.sendQueue.GET) {\n                    Entry.hw.sendQueue.GET = {};\n                }\n                Entry.hw.sendQueue.GET[Entry.Runcoding_led.sensorTypes.TIMER] = {\n                    port: 0,\n                    time: new Date().getTime(),\n                };\n                return TIMER || 0;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.timer()',\n                        blockType: 'param',\n                        textParams: [],\n                            },\n                        ],\n                    },\n            },\n        runcoding_led_toggle_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                        params: [3],\n                    },\n                    {\n                        type: 'arduino_get_digital_toggle',\n                        params: ['on'],\n                    },\n                    null,\n                ],\n                type: 'runcoding_led_toggle_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getValue('VALUE');\n\n                if (typeof value === 'string') {\n                    value = value.toLowerCase();\n                }\n                if (Entry.Runcoding_led.highList.indexOf(value) > -1) {\n                    value = 255;\n                } else if (Entry.Runcoding_led.lowList.indexOf(value) > -1) {\n                    value = 0;\n                } else {\n                    throw new Error();\n                }\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                    }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Runcoding_led.sensorTypes.DIGITAL,\n                    data: value,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.digitalWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_digital_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'runcoding_led_digital_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'Runcoding',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const port = script.getNumberValue('PORT');\n                let value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                if (!Entry.hw.sendQueue.SET) {\n                    Entry.hw.sendQueue.SET = {};\n                    }\n                Entry.hw.sendQueue.SET[port] = {\n                    type: Entry.Runcoding_led.sensorTypes.PWM,\n                    data: value,\n                        time: new Date().getTime(),\n                    };\n                    return script.callReturn();\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.analogWrite(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_display: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1 (작게)', '1'],\n                        ['2 (중간)', '2'],\n                        ['3 (크게)', '3'],\n                        ['4 (매우크게)', '4'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['PLAY'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['2'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'runcoding_led_display',\n            },\n            paramsKeyMap: {\n                TEXT: 0,\n                X: 1,\n                Y: 2,\n                SIZE: 3,\n            },\n            class: 'Runcoding_display',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                let text = script.getValue('TEXT', script);\n                text += '';\n                const x = script.getNumberValue('X', script);\n                const y = script.getNumberValue('Y', script);\n                const size = script.getNumberValue('SIZE', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 200;\n\n                    console.log('[OLED Display] 텍스트 표시 요청:', text, 'X:', x, 'Y:', y, 'Size:', size);\n                    sq.SET[0] = {\n                        type: Entry.Runcoding_led.sensorTypes.OLED_TEXT,\n                        data: { \n                            x: x,\n                            y: y,\n                            size: size,\n                            value: text \n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    console.log('[OLED Display] 블록 완료');\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.runcoding_led_display(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1 (작게)', '1'],\n                                    ['2 (중간)', '2'],\n                                    ['3 (크게)', '3'],\n                                    ['4 (매우크게)', '4'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_display_clear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'runcoding_led_display_clear',\n            },\n            paramsKeyMap: {},\n            class: 'Runcoding_display',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    sq.SET[0] = {\n                        type: Entry.Runcoding_led.sensorTypes.OLED_CLEAR,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.runcoding_led_display_clear()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        runcoding_led_display_smile: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'runcoding_led_display_smile',\n            },\n            paramsKeyMap: {},\n            class: 'Runcoding_display',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    // 명령 전송 후 짧은 시간만 대기 (1초 기다리기 블록과 함께 사용)\n                    var timeValue = (60 / fps) * 50; // 약 50ms 대기 (명령 전송 확인용)\n\n                    // 호출 횟수 확인을 위한 로그\n                    const callCount = script.callCount || 0;\n                    script.callCount = callCount + 1;\n                    console.log('[OLED Display] 웃는얼굴 표시 요청 - 호출 횟수:', script.callCount, '타임스탬프:', new Date().getTime());\n                    \n                    // 포트 0 사용 (isRecentData에서 OLED_SMILE은 항상 허용하도록 수정됨)\n                    sq.SET[0] = {\n                        type: Entry.Runcoding_led.sensorTypes.OLED_SMILE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    console.log('[OLED Display] 웃는얼굴 블록 완료 - 호출 횟수:', script.callCount, '타임스탬프:', new Date().getTime());\n                    // 상태 초기화 - 다음 반복을 위해\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    // callCount는 유지하여 다음 반복에서도 추적 가능\n                    // Entry.engine.isContinue = false; 제거 - 반복 블록과 호환을 위해\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.runcoding_led_display_smile()',\n                        textParams: [],\n                            },\n                        ],\n                    },\n            },\n        runcoding_led_display_sad: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'runcoding_led_display_sad',\n            },\n            paramsKeyMap: {},\n            class: 'Runcoding_display',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    console.log('[OLED Display] 슬픈표정 표시 요청');\n                    sq.SET[0] = {\n                        type: Entry.Runcoding_led.sensorTypes.OLED_SAD,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    console.log('[OLED Display] 슬픈표정 블록 완료');\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.runcoding_led_display_sad()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n        runcoding_led_display_emotion: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'runcoding_led_emotion_list',\n                    },\n                ],\n                type: 'runcoding_led_display_emotion',\n            },\n            paramsKeyMap: {\n                EMOTION: 0,\n            },\n            class: 'Runcoding_display',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const emotion = script.getValue('EMOTION', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    console.log('[OLED Display] 표정 표현하기 요청:', emotion);\n                    \n                    // emotion 값에 따라 다른 센서 타입 사용\n                    let sensorType;\n                    if (emotion === 'smile') {\n                        sensorType = Entry.Runcoding_led.sensorTypes.OLED_SMILE;\n                    } else if (emotion === 'sad') {\n                        sensorType = Entry.Runcoding_led.sensorTypes.OLED_SAD;\n                    } else if (emotion === 'angry') {\n                        sensorType = Entry.Runcoding_led.sensorTypes.OLED_ANGRY;\n                    } else {\n                        sensorType = Entry.Runcoding_led.sensorTypes.OLED_SMILE; // 기본값\n                    }\n                    \n                    sq.SET[0] = {\n                        type: sensorType,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    console.log('[OLED Display] 표정 표현하기 블록 완료');\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.runcoding_led_display_emotion(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_animation_star: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'runcoding_led_animation_star',\n            },\n            paramsKeyMap: {\n                COUNT: 0,\n                SPEED: 1,\n            },\n            class: 'Runcoding_animation',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const count = script.getNumberValue('COUNT', script);\n                const speed = script.getNumberValue('SPEED', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    // 값 제한 (범위: 1~20, 1~10)\n                    const limitedCount = Math.max(1, Math.min(20, count));\n                    const limitedSpeed = Math.max(1, Math.min(10, speed));\n                    \n                    // 범위를 벗어난 입력 시 경고 로그\n                    if (count < 1) {\n                        console.log(`[OLED Animation] 개수 ${count}는 최소값 1 미만이므로 1로 조정되었습니다.`);\n                    } else if (count > 20) {\n                        console.log(`[OLED Animation] 개수 ${count}는 최대값 20을 초과하여 20으로 조정되었습니다.`);\n                    }\n                    \n                    if (speed < 1) {\n                        console.log(`[OLED Animation] 속도 ${speed}는 최소값 1 미만이므로 1로 조정되었습니다.`);\n                    } else if (speed > 10) {\n                        console.log(`[OLED Animation] 속도 ${speed}는 최대값 10을 초과하여 10으로 조정되었습니다.`);\n                    }\n                    \n                    console.log('[OLED Animation] 별 떨어지기 시작 - 개수:', limitedCount, '속도:', limitedSpeed);\n                    \n                    sq.SET[0] = {\n                        type: Entry.Runcoding_led.sensorTypes.OLED_ANIM_STAR,\n                        data: {\n                            count: limitedCount,\n                            speed: limitedSpeed\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    console.log('[OLED Animation] 별 떨어지기 블록 완료');\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.oled_animation_star(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_animation_flower: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'runcoding_led_animation_flower',\n            },\n            paramsKeyMap: {\n                COUNT: 0,\n                SPEED: 1,\n            },\n            class: 'Runcoding_animation',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const count = script.getNumberValue('COUNT', script);\n                const speed = script.getNumberValue('SPEED', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    // 값 제한 (범위: 1~20, 1~10)\n                    const limitedCount = Math.max(1, Math.min(20, count));\n                    const limitedSpeed = Math.max(1, Math.min(10, speed));\n                    \n                    // 범위를 벗어난 입력 시 경고 로그\n                    if (count < 1) {\n                        console.log(`[OLED Animation] 개수 ${count}는 최소값 1 미만이므로 1로 조정되었습니다.`);\n                    } else if (count > 20) {\n                        console.log(`[OLED Animation] 개수 ${count}는 최대값 20을 초과하여 20으로 조정되었습니다.`);\n                    }\n                    \n                    if (speed < 1) {\n                        console.log(`[OLED Animation] 속도 ${speed}는 최소값 1 미만이므로 1로 조정되었습니다.`);\n                    } else if (speed > 10) {\n                        console.log(`[OLED Animation] 속도 ${speed}는 최대값 10을 초과하여 10으로 조정되었습니다.`);\n                    }\n                    \n                    console.log('[OLED Animation] 꽃송이 떨어지기 시작 - 개수:', limitedCount, '속도:', limitedSpeed);\n                    \n                    sq.SET[0] = {\n                        type: Entry.Runcoding_led.sensorTypes.OLED_ANIM_FLOWER,\n                        data: {\n                            count: limitedCount,\n                            speed: limitedSpeed\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    console.log('[OLED Animation] 꽃송이 떨어지기 블록 완료');\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.oled_animation_flower(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_animation_snow: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['3'],\n                    },\n                    null,\n                ],\n                type: 'runcoding_led_animation_snow',\n            },\n            paramsKeyMap: {\n                COUNT: 0,\n                SPEED: 1,\n            },\n            class: 'Runcoding_animation',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                const count = script.getNumberValue('COUNT', script);\n                const speed = script.getNumberValue('SPEED', script);\n\n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    // 값 제한 (범위: 1~20, 1~10)\n                    const limitedCount = Math.max(1, Math.min(20, count));\n                    const limitedSpeed = Math.max(1, Math.min(10, speed));\n                    \n                    // 범위를 벗어난 입력 시 경고 로그\n                    if (count < 1) {\n                        console.log(`[OLED Animation] 개수 ${count}는 최소값 1 미만이므로 1로 조정되었습니다.`);\n                    } else if (count > 20) {\n                        console.log(`[OLED Animation] 개수 ${count}는 최대값 20을 초과하여 20으로 조정되었습니다.`);\n                    }\n                    \n                    if (speed < 1) {\n                        console.log(`[OLED Animation] 속도 ${speed}는 최소값 1 미만이므로 1로 조정되었습니다.`);\n                    } else if (speed > 10) {\n                        console.log(`[OLED Animation] 속도 ${speed}는 최대값 10을 초과하여 10으로 조정되었습니다.`);\n                    }\n                    \n                    console.log('[OLED Animation] 눈송이 떨어지기 시작 - 개수:', limitedCount, '속도:', limitedSpeed);\n                    \n                    sq.SET[0] = {\n                        type: Entry.Runcoding_led.sensorTypes.OLED_ANIM_SNOW,\n                        data: {\n                            count: limitedCount,\n                            speed: limitedSpeed\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    console.log('[OLED Animation] 눈송이 떨어지기 블록 완료');\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.oled_animation_snow(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        runcoding_led_animation_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'runcoding_led_animation_stop',\n            },\n            paramsKeyMap: {},\n            class: 'Runcoding_animation',\n            isNotFor: ['Runcoding_display'],\n            func(sprite, script) {\n                const sq = Entry.hw.sendQueue;\n                \n                if (!script.isStart) {\n                    if (!sq.SET) {\n                        sq.SET = {};\n                    }\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    var fps = Entry.FPS || 60;\n                    var timeValue = (60 / fps) * 50;\n\n                    console.log('[OLED Animation] 애니메이션 정지');\n                    \n                    sq.SET[0] = {\n                        type: Entry.Runcoding_led.sensorTypes.OLED_ANIM_STOP,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, timeValue);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    console.log('[OLED Animation] 정지 블록 완료');\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Arduino.oled_animation_stop()',\n                        textParams: [],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Runcoding_display;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_sally.js",
    "content": "'use strict';\n\nEntry.Sally = {\n    setZero() {\n        Entry.Robomation.setZero();\n    },\n    afterReceive(pd) {\n        Entry.Robomation.afterReceive(pd, false);\n    },\n    afterSend(sq) {\n        Entry.Robomation.afterSend(sq);\n    },\n    getRobot() {\n        const robot = Entry.Robomation.getRobot('line', 0);\n        if (robot) {\n            robot.setMotoring(Entry.hw.sendQueue);\n        }\n        return robot;\n    },\n    id: '2.11',\n    name: 'sally',\n    url: 'http://robomation.jp',\n    imageName: 'sally.png',\n    title: {\n        en: 'Sally',\n        ko: '샐리',\n        jp: 'サリー',\n        vn: 'Sally',\n    },\n    monitorTemplate: () => ({\n        imgPath: 'hw/sally.png',\n        width: 300,\n        height: 370,\n        listPorts: {\n            colorNumber: {\n                name: Lang.Blocks.ROBOID_sensor_color_number,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorRed: {\n                name: Lang.Blocks.ROBOID_sensor_color_r,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorGreen: {\n                name: Lang.Blocks.ROBOID_sensor_color_g,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorBlue: {\n                name: Lang.Blocks.ROBOID_sensor_color_b,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationX: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            temperature: {\n                name: Lang.Blocks.ROBOID_sensor_temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            button: {\n                name: Lang.Blocks.ROBOID_sensor_button,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Blocks.ROBOID_monitor_buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: {\n                name: Lang.Blocks.ROBOID_monitor_note,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            floor: {\n                name: Lang.Blocks.ROBOID_sensor_floor,\n                type: 'input',\n                pos: { x: 94, y: 366 },\n            },\n            ledRed: {\n                name: `LED R`,\n                type: 'output',\n                pos: { x: 94, y: 262 },\n            },\n            ledGreen: {\n                name: `LED G`,\n                type: 'output',\n                pos: { x: 94, y: 262 },\n            },\n            ledBlue: {\n                name: `LED B`,\n                type: 'output',\n                pos: { x: 94, y: 262 },\n            },\n            leftWheel: {\n                name: Lang.Blocks.ROBOID_monitor_left_wheel,\n                type: 'output',\n                pos: { x: 288, y: 305 },\n            },\n            rightWheel: {\n                name: Lang.Blocks.ROBOID_monitor_right_wheel,\n                type: 'output',\n                pos: { x: 10, y: 305 },\n            },\n        },\n        mode: 'both',\n    }),\n};\n\nEntry.Sally.setLanguage = () => ({\n    ko: {\n        template: {\n            sally_touching_color: '%1 에 닿았는가?',\n            sally_is_color_pattern: '색깔 패턴이 %1 %2 인가?',\n            sally_button_state: '버튼을 %1 ?',\n            sally_boolean: '%1?',\n            sally_value: '%1',\n            sally_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n            sally_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n            sally_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n            sally_pivot_around_wheel_unit_in_direction: '%1 바퀴 중심으로 %2 %3 %4 방향으로 돌기 %5',\n            sally_turn_unit_with_radius_in_direction: '%1 으로 %2 %3 반지름 %4 cm를 %5 방향으로 돌기 %6',\n            sally_change_wheels_by_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            sally_set_wheels_to_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            sally_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            sally_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            sally_follow_line: '선 따라가기 %1',\n            sally_follow_line_until: '선을 따라 %1 까지 이동하기 %2',\n            sally_follow_line_until_intersection: '선을 따라 교차로까지 이동하기 %1',\n            sally_cross_intersection: '교차로 건너가기 %1',\n            sally_turn_at_intersection: '교차로에서 %1 으로 돌기 %2',\n            sally_jump_line: '%1 선으로 건너가기 %2',\n            sally_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n            sally_stop: '정지하기 %1',\n            sally_set_led_to: 'LED를 %1 으로 정하기 %2',\n            sally_pick_led: 'LED를 %1로 정하기 %2',\n            sally_change_led_by_rgb: 'LED를 R: %1 G: %2 B: %3 만큼 바꾸기 %4',\n            sally_set_led_to_rgb: 'LED를 R: %1 G: %2 B: %3 (으)로 정하기 %4',\n            sally_clear_led: 'LED 끄기 %1',\n            sally_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n            sally_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n            sally_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            sally_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            sally_clear_sound: '소리 끄기 %1',\n            sally_play_note: '%1 %2 음을 연주하기 %3',\n            sally_play_note_for_beats: '%1 %2 음을 %3 박자 연주하기 %4',\n            sally_rest_for_beats: '%1 박자 쉬기 %2',\n            sally_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            sally_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n        },\n        Helper: {\n            sally_touching_color: \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            sally_is_color_pattern: \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            sally_button_state: \"버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            sally_boolean: \"앞으로 기울임: 앞으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집었으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않았으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>두드림: 두드렸으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>자유 낙하: 자유 낙하했으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            sally_value: '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -2 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>색깔 R: 컬러 센서가 감지한 색깔의 빨간색(R) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>색깔 G: 컬러 센서가 감지한 색깔의 초록색(G) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>색깔 B: 컬러 센서가 감지한 색깔의 파란색(B) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -41 ~ 87도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.',\n            sally_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            sally_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            sally_turn_unit_in_place: '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            sally_pivot_around_wheel_unit_in_direction: '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 앞쪽/뒤쪽 방향으로 회전합니다.',\n            sally_turn_unit_with_radius_in_direction: '입력한 반지름의 원을 그리면서 입력한 시간(초)/펄스만큼 왼쪽/오른쪽, 앞쪽/뒤쪽 방향으로 회전합니다.',\n            sally_change_wheels_by_left_right: '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            sally_set_wheels_to_left_right: '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            sally_change_wheel_by: '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            sally_set_wheel_to: '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            sally_follow_line: '하얀색 바탕 위에서 검은색 선을 따라 이동합니다.',\n            sally_follow_line_until: '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n            sally_follow_line_until_intersection: '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 교차로에 도착하면 정지합니다.',\n            sally_cross_intersection: '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾습니다.',\n            sally_turn_at_intersection: '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾습니다.',\n            sally_jump_line: '제자리에서 왼쪽/오른쪽으로 90도 회전한 후 앞으로 이동하다가 컬러 센서가 검은색 선을 감지하면 원래 방향으로 다시 회전합니다.',\n            sally_set_following_speed_to: '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            sally_stop: '양쪽 바퀴를 정지합니다.',\n            sally_set_led_to: 'LED를 선택한 색깔로 켭니다.',\n            sally_pick_led: 'LED를 선택한 색깔로 켭니다.',\n            sally_change_led_by_rgb: 'LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            sally_set_led_to_rgb: 'LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            sally_clear_led: 'LED를 끕니다.',\n            sally_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            sally_play_sound_times_until_done: '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            sally_change_buzzer_by: '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            sally_set_buzzer_to: '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n            sally_clear_sound: '소리를 끕니다.',\n            sally_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            sally_play_note_for_beats: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            sally_rest_for_beats: '입력한 박자만큼 쉽니다.',\n            sally_change_tempo_by: '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            sally_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: '버저',\n            ROBOID_monitor_note: '음표',\n            ROBOID_monitor_left_wheel: '왼쪽 바퀴',\n            ROBOID_monitor_right_wheel: '오른쪽 바퀴',\n            ROBOID_sensor_signal_strength: '신호 세기',\n            ROBOID_sensor_color_r: '색깔 R',\n            ROBOID_sensor_color_g: '색깔 G',\n            ROBOID_sensor_color_b: '색깔 B',\n            ROBOID_sensor_floor: '바닥 센서',\n            ROBOID_sensor_acceleration_x: 'x축 가속도',\n            ROBOID_sensor_acceleration_y: 'y축 가속도',\n            ROBOID_sensor_acceleration_z: 'z축 가속도',\n            ROBOID_sensor_temperature: '온도',\n            ROBOID_sensor_button: '버튼',\n            ROBOID_sensor_color_number: '색깔 번호',\n            ROBOID_sensor_color_pattern: '색깔 패턴',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_orange: '주황색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_violet: '보라색',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_color_black: '검은색',\n            ROBOID_color_any: '아무 색',\n            ROBOID_clicked: '클릭했는가',\n            ROBOID_double_clicked: '더블클릭했는가',\n            ROBOID_long_pressed: '오래 눌렀는가',\n            ROBOID_tilt_forward: '앞으로 기울임',\n            ROBOID_tilt_backward: '뒤로 기울임',\n            ROBOID_tilt_left: '왼쪽으로 기울임',\n            ROBOID_tilt_right: '오른쪽으로 기울임',\n            ROBOID_tilt_flip: '거꾸로 뒤집음',\n            ROBOID_tilt_not: '기울이지 않음',\n            ROBOID_battery_normal: '배터리 정상',\n            ROBOID_battery_low: '배터리 부족',\n            ROBOID_battery_empty: '배터리 없음',\n            ROBOID_free_fall: '자유 낙하',\n            ROBOID_tap: '두드림',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '초',\n            ROBOID_unit_pulse: '펄스',\n            ROBOID_unit_deg: '도',\n            ROBOID_left: '왼쪽',\n            ROBOID_right: '오른쪽',\n            ROBOID_both: '양쪽',\n            ROBOID_back: '뒤쪽',\n            ROBOID_forward: '앞쪽',\n            ROBOID_backward: '뒤쪽',\n            ROBOID_sound_beep: '삐',\n            ROBOID_sound_random_beep: '무작위 삐',\n            ROBOID_sound_noise: '지지직',\n            ROBOID_sound_siren: '사이렌',\n            ROBOID_sound_engine: '엔진',\n            ROBOID_sound_chop: '쩝',\n            ROBOID_sound_robot: '로봇',\n            ROBOID_sound_dibidibidip: '디비디비딥',\n            ROBOID_sound_good_job: '잘 했어요',\n            ROBOID_sound_happy: '행복',\n            ROBOID_sound_angry: '화남',\n            ROBOID_sound_sad: '슬픔',\n            ROBOID_sound_sleep: '졸림',\n            ROBOID_sound_march: '행진',\n            ROBOID_sound_birthday: '생일',\n            ROBOID_note_c: '도',\n            ROBOID_note_c_sharp: '도♯(레♭)',\n            ROBOID_note_d: '레',\n            ROBOID_note_d_sharp: '레♯(미♭)',\n            ROBOID_note_e: '미',\n            ROBOID_note_f: '파',\n            ROBOID_note_f_sharp: '파♯(솔♭)',\n            ROBOID_note_g: '솔',\n            ROBOID_note_g_sharp: '솔♯(라♭)',\n            ROBOID_note_a: '라',\n            ROBOID_note_a_sharp: '라♯(시♭)',\n            ROBOID_note_b: '시',\n        },\n    },\n    en: {\n        template: {\n            sally_touching_color: 'touching %1 ?',\n            sally_is_color_pattern: 'color pattern %1 %2 ?',\n            sally_button_state: 'button %1 ?',\n            sally_boolean: '%1?',\n            sally_value: '%1',\n            sally_move_forward_unit: 'move forward %1 %2 %3',\n            sally_move_backward_unit: 'move backward %1 %2 %3',\n            sally_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            sally_pivot_around_wheel_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n            sally_turn_unit_with_radius_in_direction: 'turn %1 %2 %3 with radius %4 cm in %5 direction %6',\n            sally_change_wheels_by_left_right: 'change wheels by left: %1 right: %2 %3',\n            sally_set_wheels_to_left_right: 'set wheels to left: %1 right: %2 %3',\n            sally_change_wheel_by: 'change %1 wheel by %2 %3',\n            sally_set_wheel_to: 'set %1 wheel to %2 %3',\n            sally_follow_line: 'follow line %1',\n            sally_follow_line_until: 'follow line until %1 %2',\n            sally_follow_line_until_intersection: 'follow line until intersection %1',\n            sally_cross_intersection: 'cross intersection %1',\n            sally_turn_at_intersection: 'turn %1 at intersection %2',\n            sally_jump_line: 'jump to %1 line %2',\n            sally_set_following_speed_to: 'set following speed to %1 %2',\n            sally_stop: 'stop %1',\n            sally_set_led_to: 'set led to %1 %2',\n            sally_pick_led: 'set led to %1 %2',\n            sally_change_led_by_rgb: 'change led by r: %1 g: %2 b: %3 %4',\n            sally_set_led_to_rgb: 'set led to r: %1 g: %2 b: %3 %4',\n            sally_clear_led: 'clear led %1',\n            sally_play_sound_times: 'play sound %1 %2 times %3',\n            sally_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            sally_change_buzzer_by: 'change buzzer by %1 %2',\n            sally_set_buzzer_to: 'set buzzer to %1 %2',\n            sally_clear_sound: 'clear sound %1',\n            sally_play_note: 'play note %1 %2 %3',\n            sally_play_note_for_beats: 'play note %1 %2 for %3 beats %4',\n            sally_rest_for_beats: 'rest for %1 beats %2',\n            sally_change_tempo_by: 'change tempo by %1 %2',\n            sally_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            sally_touching_color: 'If the color sensor detects the selected color, true, otherwise false.',\n            sally_is_color_pattern: 'If the color sensor detects the selected color pattern, true, otherwise false.',\n            sally_button_state: 'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            sally_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>tap: If tapped, true, otherwise false<br/>free fall: If free fall, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            sally_value: 'color number: color number detected by the color sensor (range: -2 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1)<br/>color r: red component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color g: green component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color b: blue component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>temperature: temperature value inside the robot (range: -41 to 87 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.',\n            sally_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            sally_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            sally_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            sally_pivot_around_wheel_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            sally_turn_unit_with_radius_in_direction: 'Turns left/right drawing the circle of the entered radius in the forward/backward direction for the number of seconds/pulses entered.',\n            sally_change_wheels_by_left_right: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            sally_set_wheels_to_left_right: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            sally_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            sally_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            sally_follow_line: 'Moves along the black line on a white background.',\n            sally_follow_line_until: 'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            sally_follow_line_until_intersection: 'Moves along the black line on a white background and stops when the robot reaches the intersection.',\n            sally_cross_intersection: 'Moves forward for a moment at the black intersection, then finds the black line.',\n            sally_turn_at_intersection: 'Moves forward for a moment at the black intersection, then turns left/right/back in place and finds the black line.',\n            sally_jump_line: 'Turns left/right 90 degrees in place and moves forward. Stops when the color sensor detects the black line and turns to its original direction.',\n            sally_set_following_speed_to: 'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            sally_stop: 'Stops both wheels.',\n            sally_set_led_to: 'Turns the LED to the selected color.',\n            sally_pick_led: 'Turns the LED to the selected color.',\n            sally_change_led_by_rgb: 'Adds the entered values to the current R, G, B values of the LED, respectively.',\n            sally_set_led_to_rgb: 'Sets the R, G, B values of the LED to the entered values.',\n            sally_clear_led: 'Turns off the LED.',\n            sally_play_sound_times: 'Plays the selected sound as many times as entered.',\n            sally_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            sally_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            sally_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            sally_clear_sound: 'Turns off sound.',\n            sally_play_note: 'It sounds the selected tone and octave.',\n            sally_play_note_for_beats: 'It sounds the selected tone and octave as much as the beat you entered.',\n            sally_rest_for_beats: 'Rests as much as the beat you entered.',\n            sally_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            sally_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_color_r: 'color r',\n            ROBOID_sensor_color_g: 'color g',\n            ROBOID_sensor_color_b: 'color b',\n            ROBOID_sensor_floor: 'floor',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_temperature: 'temperature',\n            ROBOID_sensor_button: 'button',\n            ROBOID_sensor_color_number: 'color number',\n            ROBOID_sensor_color_pattern: 'color pattern',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_color_black: 'black',\n            ROBOID_color_any: 'any color',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_free_fall: 'free fall',\n            ROBOID_tap: 'tap',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_back: 'back',\n            ROBOID_forward: 'forward',\n            ROBOID_backward: 'backward',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n    jp: {\n        template: {\n            sally_touching_color: '%1 に着いたか？',\n            sally_is_color_pattern: '色パターンが %1 %2 か？',\n            sally_button_state: 'ボタンを %1 ?',\n            sally_boolean: '%1?',\n            sally_value: '%1',\n            sally_move_forward_unit: '前へ %1 %2 移動する %3',\n            sally_move_backward_unit: '後ろへ %1 %2 移動する %3',\n            sally_turn_unit_in_place: '%1 へ %2 %3 その場で回る %4',\n            sally_pivot_around_wheel_unit_in_direction: '%1 車輪を中心に %2 %3 %4 方向に回る %5',\n            sally_turn_unit_with_radius_in_direction: '%1 へ %2 %3 半径 %4 cmを %5 方向に回る %6',\n            sally_change_wheels_by_left_right: '左車輪を %1 右車輪を %2 ずつ変える %3',\n            sally_set_wheels_to_left_right: '左車輪を %1 右車輪を %2 にする %3',\n            sally_change_wheel_by: '%1 車輪を %2 ずつ変える %3',\n            sally_set_wheel_to: '%1 車輪を %2 にする %3',\n            sally_follow_line: '線にそって移動する %1',\n            sally_follow_line_until: '線にそって %1 まで移動する %2',\n            sally_follow_line_until_intersection: '線にそって交差点まで移動する %1',\n            sally_cross_intersection: '交差点を渡る %1',\n            sally_turn_at_intersection: '交差点で %1 へ回る %2',\n            sally_jump_line: '%1 線へわたる %2',\n            sally_set_following_speed_to: '線にそって移動する速さを %1 にする %2',\n            sally_stop: '停止する %1',\n            sally_set_led_to: 'LEDを %1 にする %2',\n            sally_pick_led: 'LEDを %1 にする %2',\n            sally_change_led_by_rgb: 'LEDをR: %1 G: %2 B: %3 ずつ変える %4',\n            sally_set_led_to_rgb: 'LEDをR: %1 G: %2 B: %3 にする %4',\n            sally_clear_led: 'LEDをオフにする %1',\n            sally_play_sound_times: '%1 音を %2 回再生する %3',\n            sally_play_sound_times_until_done: '%1 音を %2 回再生して待つ %3',\n            sally_change_buzzer_by: 'ブザー音を %1 ずつ変える %2',\n            sally_set_buzzer_to: 'ブザー音を %1 にする %2',\n            sally_clear_sound: '音をオフにする %1',\n            sally_play_note: '%1 %2 音をならす %3',\n            sally_play_note_for_beats: '%1 %2 音を %3 拍子ならす %4',\n            sally_rest_for_beats: '%1 拍子休む %2',\n            sally_change_tempo_by: '演奏のテンポを %1 ずつ変える %2',\n            sally_set_tempo_to: '演奏のテンポを %1 BPMにする %2',\n        },\n        Helper: {\n            sally_touching_color: '選択した色をカラーセンサーが感知したら「正しい」と判断してその他は｢正しくない｣と判断します。',\n            sally_is_color_pattern: '選択した色パターンをカラーセンサーが感知したら「正しい」と判断してその他は｢正しくない｣と判断します。',\n            sally_button_state: 'ボタンをクリックしたら、/ダブルクリックしたら、/長く押したら「正しい」と判断してその他は｢正しくない｣と判断します。',\n            sally_boolean: \"前にかたむけたか：前にかたむいたら「正しい」と判断してその他は「正しくない」と判断します。<br/>後にかたむけたか: 後ろにかたむいたら「正しい」と判断してその他は「正しくない」と判断します。<br/>左にかたむけたか：左にかたむいたら「正しい」と判断してその他は「正しくない」と判断します。<br/>右にかたむけたか：右にかたむいたら「正しい」と判断してその他は「正しくない」と判断します。<br/>うら返したか: うら裏返しになったら「正しい」と判断してその他は「正しくない」と判断します。<br/>かたむいてないか：かたむいてなかったら「正しい」と判断してその他は「正しくない」と判断します。<br/>叩いたか：叩いたら「正しい」と判断してその他は「正しくない」と判断します。<br/>落下したか：落下したら「正しい」と判断してその他は「正しくない」と判断します。<br/>電池残量が充分か：電池の残量が充分であれば「正しい」と判断してその他は「正しくない」と判断します。<br/>電池残量が足りないか：電池の残量が不足すると「正しい」と判断してその他は「正しくない」と判断します。<br/>電池残量がなくなったか：電池の残量がない場合「正しい」と判断してその他は「正しくない」と判断します。\",\n            sally_value: '色番号：カラーセンサーが感知した色の番号（値の範囲：-2〜8、初期値：-1）<br/>色パターン：カラーセンサーが感知した色パターンの値（値の範囲：-1〜88、初期値：-1）<br/>色R：カラーセンサーが感知した色の赤（R）成分（値の範囲：0〜255、初期値：0）<br/>色G：カラーセンサーが感知した色の緑（G）成分（値の範囲：0〜255、初期値：0）<br/>色B：カラーセンサーが感知した色の青色（B）成分（値の範囲：0〜255、初期値：0）<br/>床面センサー：床面センサーの値（値の範囲：0〜100、初期値：0）<br/>ボタン：ボタンの状態値（押すと1、違うと0、初期値：0）<br/>x軸の加速度：加速度センサーのX軸の値（値の範囲：-32768〜32767、初期値：0）ロボットが前進する方向がX軸の正の値方向です。<br/>y軸の加速度：加速度センサーのY軸の値（値の範囲：-32768〜32767、初期値：0）ロボットの左方向がY軸の正の値方向です。<br/>z軸の加速度：加速度センサーのZ軸の値（値の範囲：-32768〜32767、初期値：0）ロボットの上部方向がZ軸の正の値方向です。<br/>温度：ロボット内部の温度値（値の範囲：摂氏-41〜87度、初期値：0）<br/>信号の強さ：Bluetoothワイヤレス通信の信号強度（値の範囲：-128〜0 dBm、初期値：0）信号の強度が強いほど値が大きくなります。',\n            sally_move_forward_unit: '入力された距離(cm)/時間(秒)/パルスだけ前方に移動します。',\n            sally_move_backward_unit: '入力された距離(cm)/時間(秒)/パルスだけ後方に移動します。',\n            sally_turn_unit_in_place: '入力した角度(度)/時間(秒)/パルスだけ左/右方向にその場で回転します。',\n            sally_pivot_around_wheel_unit_in_direction: '左/右の車輪中心に入力した角度(度)/時間(秒)/パルスだけ前方/後方の方向に回転します。',\n            sally_turn_unit_with_radius_in_direction: '入力された半径の円形を描きながら入力した時間(秒)/パルスだけ左/右、前方/後方の方向に回転します。',\n            sally_change_wheels_by_left_right: '左と右の車輪の現在の速度値(％)で入力した値をそれぞれ加算します。加算した結果が正の値であれば、車輪が前方に回転し、負の値であれば後ろに回転します。',\n            sally_set_wheels_to_left_right: '左と右の車輪の速度を入力した値(-100〜100％)でそれぞれ設定します。正の値を入力すると車輪が前方に回転し、負の値を入力すると後ろに回転します。「0」を入力すると停止します。',\n            sally_change_wheel_by: '左/右/両方車輪の現在速度値(％)で入力した値を加算します。加算した結果が正の値であれば車輪が前方に回転し、負の値であれば後ろに回転します。',\n            sally_set_wheel_to: '左/右/両方車輪の速度を入力した値(-100〜100％)に設定します。正の値を入力すると車輪が前方に回転し、負の値を入力すると後ろに回転します。「0」を入力すると停止します。',\n            sally_follow_line: '白地にある黒い線にそって移動します。',\n            sally_follow_line_until: '白地にある黒い線にそって移動している途中で、選択した色をカラーセンサーが感知すると停止します。',\n            sally_follow_line_until_intersection: '白地にある黒い線にそって移動している途中で、交差点に到達すると停止します。',\n            sally_cross_intersection: '黒い線の交差点で少し前に移動した後、黒い線を探します。',\n            sally_turn_at_intersection: '黒い線の交差点で少し前に移動した後、その場で左/右/後ろに回転して黒い線を探します。',\n            sally_jump_line: 'その場で左/右に90度回転した後、前方に移動している途中で、黒い線をカラーセンサーが感知すると停止し、元の方向に回転します。',\n            sally_set_following_speed_to: '線にそって移動する速度(1〜8)を設定します。数字が大きいほど移動速度が速くなります。',\n            sally_stop: '両方の車輪を停止します。',\n            sally_set_led_to: 'LEDの色を選択した色に設定します。',\n            sally_pick_led: 'LEDの色を選択した色に設定します。',\n            sally_change_led_by_rgb: '現在のLEDの色に入力したR・G・Bの値をそれぞれ加算します。',\n            sally_set_led_to_rgb: 'LEDの色を入力したR・G・Bの値に設定します。',\n            sally_clear_led: 'LEDをオフにします。',\n            sally_play_sound_times: '選択された音を入力した回数だけ再生し、再生が完了するまで待ちます。',\n            sally_play_sound_times_until_done: '選択された音を入力した回数だけ再生し、再生が完了するまで待ちます。',\n            sally_change_buzzer_by: '現在のブザー音の高さ（Hz)に入力した値を加算します。 小数点以下2桁まで入力できます。',\n            sally_set_buzzer_to: 'ブザー音の高さを入力した値（Hz）に設定します。 小数点以下2桁まで入力できます。「0」を入力すると音がオフになります。',\n            sally_clear_sound: '音をオフにします。',\n            sally_play_note: '選択した音階（音名、オクターブ）の音をならします。',\n            sally_play_note_for_beats: '選択した音階（音名、オクターブ）の音を入力した拍子だけならします。',\n            sally_rest_for_beats: '入力した拍子だけ止めます。',\n            sally_change_tempo_by: '現在の演奏のBPM(毎分拍数)に入力した値を加算します。',\n            sally_set_tempo_to: '演奏の速度を入力したBPM(毎分拍数)に設定します。',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'ブザー',\n            ROBOID_monitor_note: '音符',\n            ROBOID_monitor_left_wheel: '左車輪',\n            ROBOID_monitor_right_wheel: '右車輪',\n            ROBOID_sensor_signal_strength: '信号の強さ',\n            ROBOID_sensor_color_r: '色R',\n            ROBOID_sensor_color_g: '色G',\n            ROBOID_sensor_color_b: '色B',\n            ROBOID_sensor_floor: '床面センサー',\n            ROBOID_sensor_acceleration_x: 'x軸の加速度',\n            ROBOID_sensor_acceleration_y: 'y軸の加速度',\n            ROBOID_sensor_acceleration_z: 'z軸の加速度',\n            ROBOID_sensor_temperature: '温度',\n            ROBOID_sensor_button: 'ボタン',\n            ROBOID_sensor_color_number: '色番号',\n            ROBOID_sensor_color_pattern: '色パターン',\n            ROBOID_color_red: '赤色',\n            ROBOID_color_orange: 'オレンジ色',\n            ROBOID_color_yellow: '黄色',\n            ROBOID_color_green: '緑色',\n            ROBOID_color_sky_blue: '水色',\n            ROBOID_color_blue: '青色',\n            ROBOID_color_violet: '青むらさき色',\n            ROBOID_color_purple: 'むらさき色',\n            ROBOID_color_white: '白色',\n            ROBOID_color_black: '黒色',\n            ROBOID_color_any: '全ての色',\n            ROBOID_clicked: 'クリックしたか',\n            ROBOID_double_clicked: 'ダブルクリックしたか',\n            ROBOID_long_pressed: '長く押したか',\n            ROBOID_tilt_forward: '前にかたむけたか',\n            ROBOID_tilt_backward: '後にかたむけたか',\n            ROBOID_tilt_left: '左にかたむけたか',\n            ROBOID_tilt_right: '右にかたむけたか',\n            ROBOID_tilt_flip: 'うら返したか',\n            ROBOID_tilt_not: 'かたむいてないか',\n            ROBOID_battery_normal: '電池残量が充分か',\n            ROBOID_battery_low: '電池残量が足りないか',\n            ROBOID_battery_empty: '電池残量がなくなったか',\n            ROBOID_free_fall: '落下したか',\n            ROBOID_tap: '叩いたか',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '秒',\n            ROBOID_unit_pulse: 'パルス',\n            ROBOID_unit_deg: '度',\n            ROBOID_left: '左',\n            ROBOID_right: '右',\n            ROBOID_both: '両方',\n            ROBOID_back: '後ろ',\n            ROBOID_forward: '前',\n            ROBOID_backward: '後',\n            ROBOID_sound_beep: 'ビープ',\n            ROBOID_sound_random_beep: 'ランダムビープ',\n            ROBOID_sound_noise: 'ノイズ',\n            ROBOID_sound_siren: 'サイレン',\n            ROBOID_sound_engine: 'エンジン',\n            ROBOID_sound_chop: 'チョップ',\n            ROBOID_sound_robot: 'ロボット',\n            ROBOID_sound_dibidibidip: 'ディビディビディ',\n            ROBOID_sound_good_job: 'よくできました',\n            ROBOID_sound_happy: 'よろこび',\n            ROBOID_sound_angry: 'いかり',\n            ROBOID_sound_sad: 'かなしみ',\n            ROBOID_sound_sleep: 'ねむい',\n            ROBOID_sound_march: 'マーチ',\n            ROBOID_sound_birthday: 'たんじょうび',\n            ROBOID_note_c: 'ド',\n            ROBOID_note_c_sharp: 'ド♯(レ♭)',\n            ROBOID_note_d: 'レ',\n            ROBOID_note_d_sharp: 'レ♯(ミ♭)',\n            ROBOID_note_e: 'ミ',\n            ROBOID_note_f: 'ファ',\n            ROBOID_note_f_sharp: 'ファ♯(ソ♭)',\n            ROBOID_note_g: 'ソ',\n            ROBOID_note_g_sharp: 'ソ♯(ラ♭)',\n            ROBOID_note_a: 'ラ',\n            ROBOID_note_a_sharp: 'ラ♯(シ♭)',\n            ROBOID_note_b: 'シ',\n        },\n    },\n    vn: {\n        template: {\n            sally_touching_color: 'touching %1 ?',\n            sally_is_color_pattern: 'color pattern %1 %2 ?',\n            sally_button_state: 'button %1 ?',\n            sally_boolean: '%1?',\n            sally_value: '%1',\n            sally_move_forward_unit: 'move forward %1 %2 %3',\n            sally_move_backward_unit: 'move backward %1 %2 %3',\n            sally_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            sally_pivot_around_wheel_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n            sally_turn_unit_with_radius_in_direction: 'turn %1 %2 %3 with radius %4 cm in %5 direction %6',\n            sally_change_wheels_by_left_right: 'change wheels by left: %1 right: %2 %3',\n            sally_set_wheels_to_left_right: 'set wheels to left: %1 right: %2 %3',\n            sally_change_wheel_by: 'change %1 wheel by %2 %3',\n            sally_set_wheel_to: 'set %1 wheel to %2 %3',\n            sally_follow_line: 'follow line %1',\n            sally_follow_line_until: 'follow line until %1 %2',\n            sally_follow_line_until_intersection: 'follow line until intersection %1',\n            sally_cross_intersection: 'cross intersection %1',\n            sally_turn_at_intersection: 'turn %1 at intersection %2',\n            sally_jump_line: 'jump to %1 line %2',\n            sally_set_following_speed_to: 'set following speed to %1 %2',\n            sally_stop: 'stop %1',\n            sally_set_led_to: 'set led to %1 %2',\n            sally_pick_led: 'set led to %1 %2',\n            sally_change_led_by_rgb: 'change led by r: %1 g: %2 b: %3 %4',\n            sally_set_led_to_rgb: 'set led to r: %1 g: %2 b: %3 %4',\n            sally_clear_led: 'clear led %1',\n            sally_play_sound_times: 'play sound %1 %2 times %3',\n            sally_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            sally_change_buzzer_by: 'change buzzer by %1 %2',\n            sally_set_buzzer_to: 'set buzzer to %1 %2',\n            sally_clear_sound: 'clear sound %1',\n            sally_play_note: 'play note %1 %2 %3',\n            sally_play_note_for_beats: 'play note %1 %2 for %3 beats %4',\n            sally_rest_for_beats: 'rest for %1 beats %2',\n            sally_change_tempo_by: 'change tempo by %1 %2',\n            sally_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            sally_touching_color: 'If the color sensor detects the selected color, true, otherwise false.',\n            sally_is_color_pattern: 'If the color sensor detects the selected color pattern, true, otherwise false.',\n            sally_button_state: 'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            sally_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>tap: If tapped, true, otherwise false<br/>free fall: If free fall, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            sally_value: 'color number: color number detected by the color sensor (range: -2 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1)<br/>color r: red component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color g: green component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color b: blue component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>temperature: temperature value inside the robot (range: -41 to 87 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.',\n            sally_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            sally_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            sally_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            sally_pivot_around_wheel_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            sally_turn_unit_with_radius_in_direction: 'Turns left/right drawing the circle of the entered radius in the forward/backward direction for the number of seconds/pulses entered.',\n            sally_change_wheels_by_left_right: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            sally_set_wheels_to_left_right: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            sally_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            sally_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            sally_follow_line: 'Moves along the black line on a white background.',\n            sally_follow_line_until: 'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            sally_follow_line_until_intersection: 'Moves along the black line on a white background and stops when the robot reaches the intersection.',\n            sally_cross_intersection: 'Moves forward for a moment at the black intersection, then finds the black line.',\n            sally_turn_at_intersection: 'Moves forward for a moment at the black intersection, then turns left/right/back in place and finds the black line.',\n            sally_jump_line: 'Turns left/right 90 degrees in place and moves forward. Stops when the color sensor detects the black line and turns to its original direction.',\n            sally_set_following_speed_to: 'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            sally_stop: 'Stops both wheels.',\n            sally_set_led_to: 'Turns the LED to the selected color.',\n            sally_pick_led: 'Turns the LED to the selected color.',\n            sally_change_led_by_rgb: 'Adds the entered values to the current R, G, B values of the LED, respectively.',\n            sally_set_led_to_rgb: 'Sets the R, G, B values of the LED to the entered values.',\n            sally_clear_led: 'Turns off the LED.',\n            sally_play_sound_times: 'Plays the selected sound as many times as entered.',\n            sally_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            sally_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            sally_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            sally_clear_sound: 'Turns off sound.',\n            sally_play_note: 'It sounds the selected tone and octave.',\n            sally_play_note_for_beats: 'It sounds the selected tone and octave as much as the beat you entered.',\n            sally_rest_for_beats: 'Rests as much as the beat you entered.',\n            sally_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            sally_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_color_r: 'color r',\n            ROBOID_sensor_color_g: 'color g',\n            ROBOID_sensor_color_b: 'color b',\n            ROBOID_sensor_floor: 'floor',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_temperature: 'temperature',\n            ROBOID_sensor_button: 'button',\n            ROBOID_sensor_color_number: 'color number',\n            ROBOID_sensor_color_pattern: 'color pattern',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_color_black: 'black',\n            ROBOID_color_any: 'any color',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_free_fall: 'free fall',\n            ROBOID_tap: 'tap',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_back: 'back',\n            ROBOID_forward: 'forward',\n            ROBOID_backward: 'backward',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n});\n\nEntry.Sally.blockMenuBlocks = [\n    'sally_value',\n    'sally_touching_color',\n    'sally_is_color_pattern',\n    'sally_button_state',\n    'sally_boolean',\n    'sally_move_forward_unit',\n    'sally_move_backward_unit',\n    'sally_turn_unit_in_place',\n    'sally_pivot_around_wheel_unit_in_direction',\n    'sally_turn_unit_with_radius_in_direction',\n    'sally_change_wheels_by_left_right',\n    'sally_set_wheels_to_left_right',\n    'sally_change_wheel_by',\n    'sally_set_wheel_to',\n    'sally_follow_line',\n    'sally_follow_line_until',\n    'sally_follow_line_until_intersection',\n    'sally_cross_intersection',\n    'sally_turn_at_intersection',\n    'sally_jump_line',\n    'sally_set_following_speed_to',\n    'sally_stop',\n    'sally_set_led_to',\n    'sally_pick_led',\n    'sally_change_led_by_rgb',\n    'sally_set_led_to_rgb',\n    'sally_clear_led',\n    'sally_play_sound_times',\n    'sally_play_sound_times_until_done',\n    'sally_change_buzzer_by',\n    'sally_set_buzzer_to',\n    'sally_clear_sound',\n    'sally_play_note',\n    'sally_play_note_for_beats',\n    'sally_rest_for_beats',\n    'sally_change_tempo_by',\n    'sally_set_tempo_to',\n];\n\nEntry.Sally.getBlocks = function() {\n    return {\n        sally_touching_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_touching_color',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'sally_sensor',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.checkTouchingColor(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.is_color(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_is_color_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'sally_is_color_pattern',\n            },\n            paramsKeyMap: {\n                COLOR1: 0,\n                COLOR2: 1,\n            },\n            class: 'sally_sensor',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.checkColorPattern(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.is_color_pattern(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_double_clicked, 'DOUBLE_CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_button_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'sally_sensor',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.checkButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.is_button(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_double_clicked, 'DOUBLE_CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.ROBOID_tap, 'TAP'],\n                        [Lang.Blocks.ROBOID_free_fall, 'FREE_FALL'],\n                        [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'sally_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'sally_sensor',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.ROBOID_tap, 'TAP'],\n                                    [Lang.Blocks.ROBOID_free_fall, 'FREE_FALL'],\n                                    [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sensor_color_number, 'COLOR_NUMBER'],\n                        [Lang.Blocks.ROBOID_sensor_color_pattern, 'COLOR_PATTERN'],\n                        [Lang.Blocks.ROBOID_sensor_color_r, 'COLOR_R'],\n                        [Lang.Blocks.ROBOID_sensor_color_g, 'COLOR_G'],\n                        [Lang.Blocks.ROBOID_sensor_color_b, 'COLOR_B'],\n                        [Lang.Blocks.ROBOID_sensor_floor, 'FLOOR'],\n                        [Lang.Blocks.ROBOID_sensor_button, 'BUTTON'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                        [Lang.Blocks.ROBOID_sensor_temperature, 'TEMPERATURE'],\n                        [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                    ],\n                    value: 'COLOR_NUMBER',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'sally_sensor',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sensor_color_number, 'COLOR_NUMBER'],\n                                    [Lang.Blocks.ROBOID_sensor_color_pattern, 'COLOR_PATTERN'],\n                                    [Lang.Blocks.ROBOID_sensor_color_r, 'COLOR_R'],\n                                    [Lang.Blocks.ROBOID_sensor_color_g, 'COLOR_G'],\n                                    [Lang.Blocks.ROBOID_sensor_color_b, 'COLOR_B'],\n                                    [Lang.Blocks.ROBOID_sensor_floor, 'FLOOR'],\n                                    [Lang.Blocks.ROBOID_sensor_button, 'BUTTON'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                                    [Lang.Blocks.ROBOID_sensor_temperature, 'TEMPERATURE'],\n                                    [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                                ],\n                                value: 'COLOR_NUMBER',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'sally_move_forward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.move_forward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'sally_move_backward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.move_backward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'sally_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_pivot_around_wheel_unit_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_backward, 'BACKWARD']\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'sally_pivot_around_wheel_unit_in_direction',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VALUE: 1,\n                UNIT: 2,\n                TOWARD: 3,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.pivotUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.pivot(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_backward, 'BACKWARD']\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_turn_unit_with_radius_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'SEC',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_backward, 'BACKWARD']\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['3'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'sally_turn_unit_with_radius_in_direction',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n                RADIUS: 3,\n                TOWARD: 4,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.circleUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.circle(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'SEC',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_backward, 'BACKWARD']\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_change_wheels_by_left_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'sally_change_wheels_by_left_right',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_set_wheels_to_left_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['40'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['40'],\n                    },\n                    null,\n                ],\n                type: 'sally_set_wheels_to_left_right',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'sally_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['40'],\n                    },\n                    null,\n                ],\n                type: 'sally_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_follow_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_follow_line',\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.follow_line()',\n                    },\n                ],\n            },\n        },\n        sally_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_any, 'ANY'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'sally_follow_line_until',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.follow_line_until(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_any, 'ANY'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_follow_line_until_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_follow_line_until_intersection',\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.followLineUntilIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.follow_line_until_intersection()',\n                    },\n                ],\n            },\n        },\n        sally_cross_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_cross_intersection',\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.crossIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.cross_forward()',\n                    },\n                ],\n            },\n        },\n        sally_turn_at_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_back, 'BACK'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'sally_turn_at_intersection',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.turnAtIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.cross_turn(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_back, 'BACK'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_jump_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'sally_jump_line',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.jumpLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.jump_line(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4', null],\n                type: 'sally_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.set_line_speed(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_stop',\n            },\n            class: 'sally_wheel',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.stop()',\n                    },\n                ],\n            },\n        },\n        sally_set_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'sally_set_led_to',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'sally_led',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.setLedColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.set_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_pick_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'sally_pick_led',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'sally_led',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.pickLedColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.pick_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'sally_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'sally_led',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.changeLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.add_rgb(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_set_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'sally_set_led_to_rgb',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'sally_led',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.setLedRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.set_rgb(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_clear_led',\n            },\n            class: 'sally_led',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.clear_led()',\n                    },\n                ],\n            },\n        },\n        sally_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'sally_play_sound_times',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.play_sound(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'sally_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.play_sound_until_done(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'sally_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.add_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        sally_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'sally_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.set_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        sally_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sally_clear_sound',\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.clear_sound()',\n                    },\n                ],\n            },\n        },\n        sally_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'sally_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.play_pitch(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_play_note_for_beats: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'sally_play_note_for_beats',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.play_note(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_rest_for_beats: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'sally_rest_for_beats',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.rest(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'sally_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        sally_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'sally_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'sally_sound',\n            isNotFor: ['sally'],\n            func(sprite, script) {\n                const robot = Entry.Sally.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Sally.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Sally;"
  },
  {
    "path": "src/playground/blocks/hardware/block_sciencecube.js",
    "content": "'use strict';\n\nEntry.sciencecube = {\n    id: '25.1',\n    name: 'sciencecube',\n    url: 'http://www.koreadigital.com/kr/main.asp',\n    imageName: 'sciencecube.png',\n    value: {},\n    title: {\n        'ko': '사이언스큐브',\n        'en': 'sciencecube',\n    },\n    setZero: function() {},\n    dataHandler: function(data) {\n\n        Entry.hw.sendQueue.data = {};\n\n        if (data['tempData']) {\n            this.value['tempData'] = data['tempData'];\n        } else if (data['pressueData']) {\n            this.value['pressueData'] = data['pressueData'];\n        } else if (data['currentData']) {\n            this.value['currentData'] = data['currentData'];\n        } else if (data['voltageData']) {\n            this.value['voltageData'] = data['voltageData'];\n        } else if (data['phData']) {\n            this.value['phData'] = data['phData'];\n        } else if (data['motionData']) {\n            this.value['motionData'] = data['motionData'];\n        } else if (data['forceData']) {\n            this.value['forceData'] = data['forceData'];\n        }\n    },\n};\nEntry.sciencecube.setLanguage = () => {\n    return {\n        ko: {\n            template: {\n                sciencecube_temper: '온도 센서값',\n                sciencecube_current: '전류 센서값',\n                sciencecube_pressue: '압력 센서값',\n                sciencecube_voltage: '전압 센서값',\n                sciencecube_ph: 'ph 센서값',\n                sciencecube_force: '힘 센서값',\n                sciencecube_motion: '운동 센서값',\n            },\n        },\n        en: {\n            template: {\n                sciencecube_temper: 'temper sensor',\n                sciencecube_current: 'current sensor',\n                sciencecube_pressue: 'pressue sensor',\n                sciencecube_voltage: 'voltage sensor',\n                sciencecube_ph: 'ph sensor',\n                sciencecube_force: 'force sensor',\n                sciencecube_motion: 'motion sensor',\n            },\n        },\n    };\n};\n\nEntry.sciencecube.blockMenuBlocks = [\n    //sciencecube start\n    'sciencecube_temper',\n    'sciencecube_voltage',\n    'sciencecube_current',\n    'sciencecube_pressue',\n    'sciencecube_ph',\n    'sciencecube_force',\n    'sciencecube_motion',\n    //sciencecube end\n];\n\nEntry.sciencecube.getBlocks = () => {\n    return {\n        sciencecube_temper: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Text',\n                text: '온도 센서값',\n            }, ],\n            def: {\n                type: 'sciencecube_temper',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'sciencecubeBlock',\n            isNotFor: ['sciencecube'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                if (Entry.sciencecube.value['tempData']) {\n                    return Entry.sciencecube.value['tempData'].toFixed(2);\n                } else return '현재 센서와 다릅니다. 다시 연결해주세요.';\n            },\n        },\n        sciencecube_current: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Text',\n                text: '전류 센서값',\n            }, ],\n            def: {\n                type: 'sciencecube_current',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'sciencecubeBlock',\n            isNotFor: ['sciencecube'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                if (Entry.sciencecube.value['currentData']) {\n                    return Entry.sciencecube.value['currentData'].toFixed(2);\n                } else return '현재 센서와 다릅니다. 다시 연결해주세요.';\n            },\n        },\n        sciencecube_pressue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Text',\n                text: '압력 센서값',\n            }, ],\n            def: {\n                type: 'sciencecube_pressue',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'sciencecubeBlock',\n            isNotFor: ['sciencecube'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                if (Entry.sciencecube.value['pressueData']) {\n                    return Entry.sciencecube.value['pressueData'].toFixed(2);\n                } else return '현재 센서와 다릅니다. 다시 연결해주세요.';\n            },\n        },\n        sciencecube_voltage: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Text',\n                text: '전압 센서값',\n            }, ],\n            def: {\n                type: 'sciencecube_voltage',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'sciencecubeBlock',\n            isNotFor: ['sciencecube'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                if (Entry.sciencecube.value['voltageData']) {\n                    return Entry.sciencecube.value['voltageData'].toFixed(2);\n                } else return '현재 센서와 다릅니다. 다시 연결해주세요.';\n            },\n        },\n        sciencecube_ph: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Text',\n                text: 'ph 센서값',\n            }, ],\n            def: {\n                type: 'sciencecube_ph',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'sciencecubeBlock',\n            isNotFor: ['sciencecube'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                if (Entry.sciencecube.value['phData']) {\n                    return Entry.sciencecube.value['phData'].toFixed(2);\n                } else return '현재 센서와 다릅니다. 다시 연결해주세요.';\n            },\n        },\n        sciencecube_force: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Text',\n                text: '힘 센서값',\n            }, ],\n            def: {\n                type: 'sciencecube_force',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'sciencecubeBlock',\n            isNotFor: ['sciencecube'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                if (Entry.sciencecube.value['forceData']) {\n                    return Entry.sciencecube.value['forceData'].toFixed(2);\n                } else return '현재 센서와 다릅니다. 다시 연결해주세요.';\n            },\n        },\n        sciencecube_motion: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [{\n                type: 'Text',\n                text: '운동 센서값',\n            }, ],\n            def: {\n                type: 'sciencecube_motion',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                sensor: 1,\n            },\n            events: {},\n            class: 'sciencecubeBlock',\n            isNotFor: ['sciencecube'],\n            func: function(sprite, script) {\n                Entry.hw.update();\n                if (Entry.sciencecube.value['motionData']) {\n                    return Entry.sciencecube.value['motionData'].toFixed(2);\n                } else return '현재 센서와 다릅니다. 다시 연결해주세요.';\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.sciencecube;"
  },
  {
    "path": "src/playground/blocks/hardware/block_sensorboard.js",
    "content": "'use strict';\n\nEntry.SensorBoard = {\n    id: '1.2',\n    name: 'sensorBoard',\n    url: 'http://www.neweducation.co.kr/',\n    imageName: 'entrybt.png',\n    title: {\n        ko: 'E-센서보드',\n        en: 'E-Sensorboard',\n    },\n    setZero: function() {\n        Entry.hw.sendQueue.readablePorts = [];\n        for (var port = 0; port < 20; port++) {\n            Entry.hw.sendQueue[port] = 0;\n            Entry.hw.sendQueue.readablePorts.push(port);\n        }\n        Entry.hw.update();\n    },\n};\n\nEntry.SensorBoard.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                sensorBoard_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                sensorBoard_get_digital_value: '디지털 %1 번 센서값  ',\n                sensorBoard_toggle_led: '디지털 %1 번 핀 %2 %3',\n                sensorBoard_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                sensorBoard_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                sensorBoard_get_named_sensor_value: '%1  센서값',\n                sensorBoard_is_button_pressed: '%1  버튼을 눌렀는가?',\n                sensorBoard_led: '%1  LED %2   %3',\n            },\n        },\n        en: {\n            template: {\n                sensorBoard_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                sensorBoard_get_digital_value: 'Digital %1 Sensor value  ',\n                sensorBoard_toggle_led: 'Digital %1 Pin %2 %3',\n                sensorBoard_toggle_pwm: 'Digital %1 Pin %2 %3',\n                sensorBoard_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n                sensorBoard_get_named_sensor_value: '%1  Sensor value',\n                sensorBoard_is_button_pressed: 'Pressed %1 button?',\n                sensorBoard_led: '%1  LED %2   %3',\n            },\n        },\n    };\n};\n\nEntry.SensorBoard.blockMenuBlocks = [\n    //sensorBoard\n    'sensorBoard_get_named_sensor_value',\n    'sensorBoard_is_button_pressed',\n    'sensorBoard_led',\n    'sensorBoard_get_number_sensor_value',\n    'sensorBoard_get_digital_value',\n    'sensorBoard_toggle_led',\n    'sensorBoard_toggle_pwm',\n    'sensorBoard_convert_scale',\n];\n\nEntry.SensorBoard.getBlocks = function() {\n    return {\n        //region sensorBoard e센서보드\n        sensorBoard_get_named_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['소리', '0'],\n                        ['빛 감지', '1'],\n                        ['슬라이더', '2'],\n                        ['온도', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sensorBoard_get_named_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensorBoard',\n            isNotFor: ['sensorBoard'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue(script.getField('PORT', script));\n            },\n            syntax: { js: [], py: ['Sensorboard.sensor_value(%1)'] },\n        },\n        sensorBoard_is_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빨간', '8'],\n                        ['파란', '9'],\n                        ['노랑', '10'],\n                        ['초록', '11'],\n                    ],\n                    value: '8',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'sensorBoard_is_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'sensorBoard',\n            isNotFor: ['sensorBoard'],\n            func: function(sprite, script) {\n                return Entry.hw.getDigitalPortValue(script.getNumberField('PORT', script));\n            },\n            syntax: { js: [], py: ['Sensorboard.is_button_pressed(%1)'] },\n        },\n        sensorBoard_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['빨간', '2'],\n                        ['초록', '3'],\n                        ['파란', '4'],\n                        ['노랑', '5'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', '255'],\n                        ['끄기', '0'],\n                    ],\n                    value: '255',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'sensorBoard_led',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'sensorBoard',\n            isNotFor: ['sensorBoard'],\n            func: function(sprite, script) {\n                Entry.hw.setDigitalPortValue(\n                    script.getField('PORT'),\n                    script.getNumberField('OPERATOR')\n                );\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Sensorboard.led(%1, %2)'] },\n        },\n        //endregion sensorBoard e센서보드\n        //region sensorBoard e센서보드\n        sensorBoard_get_number_sensor_value: {\n            parent: 'arduino_get_number_sensor_value',\n            isNotFor: ['sensorBoard'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_sensor_number',\n                    },\n                ],\n                type: 'sensorBoard_get_number_sensor_value',\n            },\n            class: 'arduino_value',\n            syntax: { js: [], py: ['SensorBoard.get_number_sensor_value(%1)'] },\n        },\n        sensorBoard_get_digital_value: {\n            parent: 'arduino_get_digital_value',\n            isNotFor: ['sensorBoard'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                ],\n                type: 'sensorBoard_get_digital_value',\n            },\n            class: 'arduino_value',\n            syntax: { js: [], py: ['SensorBoard.get_digital_value(%1)'] },\n        },\n        sensorBoard_toggle_led: {\n            parent: 'arduino_toggle_led',\n            isNotFor: ['sensorBoard'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_port_number',\n                    },\n                    null,\n                    null,\n                ],\n                type: 'sensorBoard_toggle_led',\n            },\n            class: 'arduino_set',\n            syntax: { js: [], py: ['SensorBoard.toggle_led(%1)'] },\n        },\n        sensorBoard_toggle_pwm: {\n            parent: 'arduino_toggle_pwm',\n            isNotFor: ['sensorBoard'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_pwm_port_number',\n                    },\n                    {\n                        type: 'arduino_text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'sensorBoard_toggle_pwm',\n            },\n            class: 'arduino_set',\n            syntax: { js: [], py: ['SensorBoard.toggle_pwm(%1, %2)'] },\n        },\n        sensorBoard_convert_scale: {\n            parent: 'arduino_convert_scale',\n            isNotFor: ['sensorBoard'],\n            def: {\n                params: [\n                    {\n                        type: 'arduino_get_number_sensor_value',\n                        params: [\n                            {\n                                type: 'arduino_get_sensor_number',\n                                id: 'bl5e',\n                            },\n                        ],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'sensorBoard_convert_scale',\n            },\n            class: 'arduino',\n            syntax: {\n                js: [],\n                py: ['SensorBoard.convert_scale(%1, %2, %3, %4, %5)'],\n            },\n        },\n        //endregion sensorBoard e센서보드\n    };\n};\n\nmodule.exports = Entry.SensorBoard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_smartCodingHouse.js",
    "content": "'use strict';\r\n\r\nEntry.smartCodingHouse = {\r\n    id: '67.1',\r\n    name: 'smartCodingHouse',\r\n    url: 'http://www.sciencetime.co.kr/',\r\n    imageName: 'smartCodingHouse.png',\r\n    title: {\r\n        en: 'smartCodingHouse',\r\n        ko: '스마트 코딩 하우스',\r\n    },\r\n    // 하드웨어 출력을 초기화할 때, 센서용 포트와 출력용 포트를 분리합니다.\r\n    setZero: function () {\r\n        // sendQueue 객체 초기화\r\n        Entry.hw.sendQueue = {};\r\n        // 센서는 아날로그 채널(0~5)만 읽기용으로 등록합니다.\r\n        Entry.hw.sendQueue.readablePorts = [\r\n            Entry.smartCodingHouse.analogPin.ULTRASONIC_ECHO,\r\n            Entry.smartCodingHouse.analogPin.TEMP_HUM,\r\n            Entry.smartCodingHouse.analogPin.IR_SENSOR,\r\n            Entry.smartCodingHouse.analogPin.LIGHT_SENSOR,\r\n            Entry.smartCodingHouse.analogPin.RAIN_SENSOR,\r\n        ];\r\n        // 출력용 디지털 포트는 0으로 초기화 (readablePorts에 포함시키지 않음)\r\n        for (let key in Entry.smartCodingHouse.digitalPin) {\r\n            let port = Entry.smartCodingHouse.digitalPin[key];\r\n            Entry.hw.sendQueue[port] = 0;\r\n        }\r\n        Entry.hw.update && Entry.hw.update();\r\n    },\r\n\r\n    // 핀 매핑 (참고용)\r\n    analogPin: {\r\n        ULTRASONIC_TRIG: 0, // 초음파센서 trig\r\n        ULTRASONIC_ECHO: 1, // 초음파센서 echo\r\n        TEMP_HUM: 2, // 온습도센서\r\n        IR_SENSOR: 3, // 적외선센서\r\n        LIGHT_SENSOR: 4, // 조도센서\r\n        RAIN_SENSOR: 5, // 레인센서서\r\n    },\r\n    digitalPin: {\r\n        SERVO_MOTOR: 2, // 서보모터\r\n        DC_MOTOR: 3, // DC모터 – 방향과 속도를 하나의 값으로 결합\r\n        OUTDOOR1_LED_RED: 5, // 1층 실외 빨강 LED\r\n        OUTDOOR1_LED_GREEN: 6, // 1층 실외 초록 LED\r\n        OUTDOOR1_LED_BLUE: 7, // 1층 실외 파란 LED\r\n        INDOOR_LED_RED: 8, // 실내 빨강 LED\r\n        INDOOR_LED_GREEN: 9, // 실내 초록 LED\r\n        INDOOR_LED_BLUE: 10, // 실내 파란 LED\r\n        TERRACE2_LED_RED: 11, // 2층 테라스 빨강 LED\r\n        TERRACE2_LED_GREEN: 12, // 2층 테라스 초록 LED\r\n        TERRACE2_LED_BLUE: 13, // 2층 테라스 파란 LED\r\n    },\r\n};\r\n\r\nEntry.smartCodingHouse.setLanguage = function () {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                // 입력 블록\r\n                set_ultrasonic_input: '초음파 센서: %1',\r\n                set_light_input: '조도 센서: %1',\r\n                set_temp_hum_input: '온습도 센서의 %1 가 %2 ',\r\n                set_ir_input: '적외선 센서: %1',\r\n                set_rain_input: '빗물 감지 센서: %1',\r\n                // 모드 블록\r\n                run_smart_mode: '스마트코딩하우스 모드 실행: %1 시작하기',\r\n                // 출력 블록\r\n                auto_door: '서보모터: 자동문 시스템',\r\n                open_door: '서보모터: 출입문 열기',\r\n                close_door: '서보모터: 출입문 닫기',\r\n                run_ceiling_fan: 'DC모터: 실링팬 가동 (%1)',\r\n                led_set_color: 'LED 조명 제어: 위치 %1, 색상 %2 으로 설정',\r\n                led_off: 'LED 끄기: 위치 %1',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                set_ultrasonic_input: 'Ultrasonic Sensor: %1',\r\n                set_light_input: 'Light Sensor: %1',\r\n                set_temp_hum_input: 'Temp/Humidity Sensor: %1 %2',\r\n                set_ir_input: 'IR Sensor: %1',\r\n                set_rain_input: 'Rain Sensor: %1',\r\n                run_smart_mode: 'Run SmartCodingHouse mode: %1',\r\n                auto_door: 'Servo Motor: Auto Door',\r\n                open_door: 'Servo Motor: Open Door',\r\n                close_door: 'Servo Motor: Close Door',\r\n                run_ceiling_fan: 'DC Motor: Run ceiling fan (%1)',\r\n                led_set_color: 'LED Control: Location %1, Color %2',\r\n                led_off: 'LED Off: Location %1',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.smartCodingHouse.blockMenuBlocks = [\r\n    // 입력 블록\r\n    'set_ultrasonic_input',\r\n    'set_light_input',\r\n    'set_temp_hum_input',\r\n    'set_ir_input',\r\n    'set_rain_input',\r\n    // 모드 블록\r\n    'run_smart_mode',\r\n    // 출력 블록\r\n    'auto_door',\r\n    'open_door',\r\n    'close_door',\r\n    'run_ceiling_fan',\r\n    'led_set_color',\r\n    'led_off',\r\n];\r\n\r\nfunction hexToRgb(hex) {\r\n    hex = hex.replace(/^#/, '');\r\n    if (hex.length === 3) {\r\n        hex = hex\r\n            .split('')\r\n            .map((x) => x + x)\r\n            .join('');\r\n    }\r\n    let num = parseInt(hex, 16);\r\n    return { r: (num >> 16) & 255, g: (num >> 8) & 255, b: num & 255 };\r\n}\r\n\r\n// RGB를 HSV로 변환하는 함수\r\nfunction rgbToHsv(r, g, b) {\r\n    // 0~255 범위의 값을 0~1 범위로 정규화\r\n    r /= 255;\r\n    g /= 255;\r\n    b /= 255;\r\n  \r\n    // 최대값과 최소값 찾기\r\n    let max = Math.max(r, g, b);\r\n    let min = Math.min(r, g, b);\r\n    let h,\r\n      s,\r\n      v = max;\r\n    let d = max - min;\r\n  \r\n    // 채도(saturation) 계산: 최대값이 0이면 0, 아니면 (최대-최소)/최대\r\n    s = max === 0 ? 0 : d / max;\r\n  \r\n    // 색조(hue) 계산\r\n    if (max === min) {\r\n      // 무채색인 경우(hue는 정의할 수 없음; 0으로 지정)\r\n      h = 0;\r\n    } else {\r\n      if (max === r) {\r\n        h = (g - b) / d + (g < b ? 6 : 0);\r\n      } else if (max === g) {\r\n        h = (b - r) / d + 2;\r\n      } else {\r\n        h = (r - g) / d + 4;\r\n      }\r\n      h /= 6; // 0~1 사이의 값으로 정규화\r\n    }\r\n  \r\n    // 결과 객체 반환: h는 0~1, s는 0~1, v는 0~1\r\n    return { h: h, s: s, v: v };\r\n  }\r\n  \r\n  // HSV 값을 RGB로 변환하는 함수\r\n  function hsvToRgb(h, s, v) {\r\n    let r, g, b;\r\n    const i = Math.floor(h * 6);\r\n    const f = h * 6 - i;\r\n    const p = v * (1 - s);\r\n    const q = v * (1 - f * s);\r\n    const t = v * (1 - (1 - f) * s);\r\n    switch (i % 6) {\r\n      case 0:\r\n        (r = v), (g = t), (b = p);\r\n        break;\r\n      case 1:\r\n        (r = q), (g = v), (b = p);\r\n        break;\r\n      case 2:\r\n        (r = p), (g = v), (b = t);\r\n        break;\r\n      case 3:\r\n        (r = p), (g = q), (b = v);\r\n        break;\r\n      case 4:\r\n        (r = t), (g = p), (b = v);\r\n        break;\r\n      case 5:\r\n        (r = v), (g = p), (b = q);\r\n        break;\r\n    }\r\n    return {\r\n      r: Math.round(r * 255),\r\n      g: Math.round(g * 255),\r\n      b: Math.round(b * 255),\r\n    };\r\n  }\r\n\r\n// 블록이 아니라, 일반 함수로 선언\r\nEntry.smartCodingHouse.modeDoor = function() {\r\n    let port = Entry.smartCodingHouse.digitalPin.SERVO_MOTOR;\r\n    // 서보모터를 90도로 설정\r\n    Entry.hw.sendQueue[port] = 4;\r\n    Entry.hw.update && Entry.hw.update();\r\n    \r\n    setTimeout(() => {\r\n        Entry.hw.sendQueue[port] = 0;\r\n        Entry.hw.update && Entry.hw.update();\r\n    }, 26);\r\n};\r\n\r\n\r\nEntry.smartCodingHouse.getBlocks = function () {\r\n    return {\r\n        set_ultrasonic_input: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['가까움', 'near'],\r\n                        ['멀음', 'far'],\r\n                    ],\r\n                    value: 'near',\r\n                    fontSize: 11,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            paramsKeyMap: { EXPECTED: 0, THRESHOLD: 1 },\r\n            def: {\r\n                type: 'set_ultrasonic_input',\r\n                params: [null, { type: 'number', params: ['20'] }],\r\n            },\r\n            class: 'SmartCodingHouseSensor',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                var expected = script.getField('EXPECTED', script); // \"near\" 또는 \"far\"\r\n                var threshold = script.getNumberValue('THRESHOLD', script); // 임계값 (기본 20cm)\r\n                var distance = Number(Entry.hw.portData.ultrasonic);\r\n                \r\n                if (isNaN(distance)) {\r\n                    // 만약 ultrasonic이 NaN이면, a1 값을 대신 사용\r\n                    distance = Number(Entry.hw.portData.a1);\r\n                }\r\n                // console.log('[DEBUG] Ultrasonic sensor reading: ' + distance + ' cm');\r\n\r\n                // 센서 값이 임계값보다 작으면 \"near\", 이상이면 \"far\"\r\n                var actual = distance < threshold ? 'near' : 'far';\r\n                return actual === expected;\r\n            },\r\n        },\r\n\r\n        set_temp_hum_input: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['온도', 'temperature'],\r\n                        ['습도', 'humidity'],\r\n                    ],\r\n                    value: 'temperature',\r\n                    fontSize: 11,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    // 온도일 경우 \"덥다\"/\"춥다\", 습도일 경우 \"습하다\"/\"건조하다\"\r\n                    options: [\r\n                        ['덥다', 'hot'],\r\n                        ['춥다', 'cold'],\r\n                        ['습하다', 'wet'],\r\n                        ['건조하다', 'dry'],\r\n                    ],\r\n                    value: 'hot',\r\n                    fontSize: 11,\r\n                },\r\n            ],\r\n            paramsKeyMap: { TYPE: 0, EXPECTED: 1 },\r\n            def: { type: 'set_temp_hum_input', params: [null, null] },\r\n            class: 'SmartCodingHouseSensor',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                var sensorType = script.getField('TYPE', script); // \"temperature\" 또는 \"humidity\"\r\n                var expected = script.getField('EXPECTED', script);\r\n                // a2 채널에서 수신한 결합된 값을 가져옴\r\n                var combined = Number(Entry.hw.portData.a2);\r\n                // Arduino에서 보낸 값은 (온도×100 + 습도)를 5로 나눈 값이므로,\r\n                // 원래 값을 복원하려면 5를 곱해줌\r\n                var value = combined * 5;\r\n                // 온도는 몫, 습도는 나머지로 분리 (예: 25°C, 50% → 25×100+50 = 2550)\r\n                var temp = Math.floor(value / 100);\r\n                var humi = value % 100;\r\n\r\n                console.log('[DEBUG] combined: ' + combined);\r\n                console.log('[DEBUG] temp: ' + temp);\r\n                console.log('[DEBUG] humi: ' + humi);\r\n\r\n                if (isNaN(combined)) {\r\n                    combined = Number(Entry.hw.portData.a2);\r\n                }\r\n                \r\n                if (sensorType === 'temperature') {\r\n                    var actual = temp > 25 ? 'hot' : 'cold';\r\n                    if (expected !== 'hot' && expected !== 'cold') return false;\r\n                    return actual === expected;\r\n                } else {\r\n                    var actual = humi > 50 ? 'wet' : 'dry';\r\n                    if (expected !== 'wet' && expected !== 'dry') return false;\r\n                    return actual === expected;\r\n                }\r\n                \r\n            },\r\n        },\r\n        \r\n\r\n        set_light_input: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['어둡다', 'dark'],\r\n                        ['밝다', 'bright'],\r\n                    ],\r\n                    value: 'dark',\r\n                    fontSize: 11,\r\n                },\r\n            ],\r\n            paramsKeyMap: { EXPECTED: 0 },\r\n            def: { type: 'set_light_input', params: [null] },\r\n            class: 'SmartCodingHouseSensor',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                var expected = script.getField('EXPECTED', script); // \"dark\" 또는 \"bright\"\r\n                var value = Number(Entry.hw.portData.a4);\r\n                if (isNaN(value)) return false;\r\n                // 값이 500 미만이면 \"dark\", 이상이면 \"bright\"\r\n                var actual = value > 500 ? 'dark' : 'bright';\r\n                return actual === expected;\r\n            },\r\n        },\r\n\r\n        set_ir_input: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['움직임 있음', 'move'],\r\n                        ['움직임 없음', 'nomove'],\r\n                    ],\r\n                    value: 'move',\r\n                    fontSize: 11,\r\n                },\r\n            ],\r\n            paramsKeyMap: { EXPECTED: 0 },\r\n            def: { type: 'set_ir_input', params: [null] },\r\n            class: 'SmartCodingHouseSensor',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                var expected = script.getField('EXPECTED', script); // 'move' 또는 'nomove'\r\n                var sensorVal = Number(Entry.hw.portData.a3);\r\n                if (isNaN(sensorVal)) return false;\r\n                // 예를 들어, 센서가 움직임 있을 때 높은 값을 반환한다면:\r\n                var actual = sensorVal < 500 ? 'move' : 'nomove';\r\n                return actual === expected;\r\n            },\r\n        },\r\n\r\n        set_rain_input: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['빗물 있음', 'rain'],\r\n                        ['빗물 없음', 'norain'],\r\n                    ],\r\n                    value: 'rain',\r\n                    fontSize: 11,\r\n                },\r\n            ],\r\n            paramsKeyMap: { EXPECTED: 0 },\r\n            def: { type: 'set_rain_input', params: [null] },\r\n            class: 'SmartCodingHouseSensor',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                var expected = script.getField('EXPECTED', script); // 'rain' 또는 'norain'\r\n                let value = Number(Entry.hw.portData.a5);\r\n                if (isNaN(value)) return false;\r\n                var actual = value > 100 && value < 800 ? 'rain' : 'norain';\r\n                return actual === expected;\r\n            },\r\n        },\r\n        // 모드 실행 블록 – 기획안의 모드(아침, 저녁, 비상, 시험 공부, 생일 파티)에 따라 LED, 모터, 서보모터를 제어\r\n        // 모드 실행 블록 – 수정된 morning 케이스\r\n        run_smart_mode: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['아침 루틴', 'morning'],\r\n                        ['저녁 루틴', 'evening'],\r\n                        ['비상 상황 모드', 'emergency'],\r\n                        ['시험 공부 모드', 'study'],\r\n                        ['생일 파티 모드', 'party'],\r\n                    ],\r\n                    value: 'morning',\r\n                    fontSize: 11,\r\n                },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            paramsKeyMap: { MODE: 0 },\r\n            def: { params: [null, null], type: 'run_smart_mode' },\r\n            class: 'SmartCodingHouseMode',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                var mode = script.getField('MODE', script);\r\n                var sq = Entry.hw.sendQueue;\r\n                switch (mode) {\r\n                    case 'morning':\r\n                        // 1,2층 실내: white LED\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_GREEN] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_BLUE] = 255;\r\n\r\n                        // 1층 실외: green LED\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_RED] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_GREEN] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_BLUE] = 0;\r\n\r\n                        // 2층 테라스: green LED\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_RED] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_GREEN] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_BLUE] = 0;\r\n\r\n                        // 실링팬 구동\r\n                        sq[Entry.smartCodingHouse.digitalPin.DC_MOTOR] = 127 | 0x80;\r\n                        break;\r\n\r\n                    case 'evening':\r\n                        // 1층 실외(yellow), 2층 테라스(yellow)는 고정\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_GREEN] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_BLUE] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_GREEN] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_BLUE] = 0;\r\n\r\n                        // 실내 조명을 여러 색상으로 순환\r\n                        const indoorR = Entry.smartCodingHouse.digitalPin.INDOOR_LED_RED;\r\n                        const indoorG = Entry.smartCodingHouse.digitalPin.INDOOR_LED_GREEN;\r\n                        const indoorB = Entry.smartCodingHouse.digitalPin.INDOOR_LED_BLUE;\r\n\r\n                        // 반복할 색상 배열 (red, orange, yellow, green, blue, purple)\r\n                        const colorCycle = [\r\n                            [255, 0, 0], // red\r\n                            [255, 165, 0], // orange\r\n                            [255, 255, 0], // yellow\r\n                            [0, 255, 0], // green\r\n                            [0, 0, 255], // blue\r\n                            [128, 0, 128], // purple\r\n                        ];\r\n                        let idx = 0;\r\n\r\n                        // 재귀적으로 호출해서 색 변경\r\n                        function cycleIndoorColor() {\r\n                            const [r, g, b] = colorCycle[idx];\r\n                            sq[indoorR] = r;\r\n                            sq[indoorG] = g;\r\n                            sq[indoorB] = b;\r\n                            // 하드웨어에 갱신\r\n                            Entry.hw.update && Entry.hw.update();\r\n\r\n                            // 다음 색상\r\n                            idx = (idx + 1) % colorCycle.length;\r\n\r\n                            // 1초 후 다음 색으로\r\n                            setTimeout(cycleIndoorColor, 2000);\r\n                        }\r\n\r\n                        // 순환 시작\r\n                        cycleIndoorColor();\r\n\r\n                        break;\r\n\r\n                    case 'emergency':\r\n                        // 비상 상황 모드: 모든 LED red, 2층 테라스 팬, 1층 출입문 개방(서보모터 90도)\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_GREEN] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_BLUE] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_GREEN] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_BLUE] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_GREEN] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_BLUE] = 0;\r\n\r\n                        // 실링팬 구동\r\n                        sq[Entry.smartCodingHouse.digitalPin.DC_MOTOR] = 127 | 0x80;\r\n                        // 서보모터 구동\r\n                        sq[Entry.smartCodingHouse.digitalPin.SERVO_MOTOR] = 90;\r\n                        Entry.smartCodingHouse.modeDoor();\r\n                        break;\r\n\r\n                    case 'study':\r\n                        // 시험 공부 모드: 실내 yellow, 야외/테라스 orange\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_GREEN] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_BLUE] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_GREEN] = 165;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_BLUE] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_GREEN] = 165;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_BLUE] = 0;\r\n                        break;\r\n\r\n                    case 'party':\r\n                        // 생일 파티 모드: 실내 red, 1층 실외 white, 2층 테라스 purple, 팬과 출입문 개방\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_GREEN] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.INDOOR_LED_BLUE] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_RED] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_GREEN] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_BLUE] = 255;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_RED] = 128;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_GREEN] = 0;\r\n                        sq[Entry.smartCodingHouse.digitalPin.TERRACE2_LED_BLUE] = 128;\r\n\r\n                        // 실링팬 구동\r\n                        sq[Entry.smartCodingHouse.digitalPin.DC_MOTOR] = 127 | 0x80;\r\n                        // 서보모터 구동\r\n                        sq[Entry.smartCodingHouse.digitalPin.SERVO_MOTOR] = 90;\r\n                        Entry.smartCodingHouse.modeDoor();\r\n                        break;\r\n                    default:\r\n                        console.log('Unknown mode: ' + mode);\r\n                }\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        auto_door: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\r\n            def: { type: 'auto_door' },\r\n            class: 'SmartCodingHouseActuator',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                let port = Entry.smartCodingHouse.digitalPin.SERVO_MOTOR;\r\n\r\n                // 서보모터를 90으로 설정\r\n                Entry.hw.sendQueue[port] = 3;\r\n                Entry.hw.update && Entry.hw.update();\r\n\r\n                // 1초 후 서보모터를 다시 0으로 자동 복귀\r\n                setTimeout(() => {\r\n                    Entry.hw.sendQueue[port] = 0;\r\n                    Entry.hw.update && Entry.hw.update();\r\n                }, 26);\r\n\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        open_door: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\r\n            def: { type: 'open_door' },\r\n            class: 'SmartCodingHouseActuator',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                let port = Entry.smartCodingHouse.digitalPin.SERVO_MOTOR;\r\n\r\n                // 서보모터를 90으로 설정\r\n                Entry.hw.sendQueue[port] = 1;\r\n                Entry.hw.update && Entry.hw.update();\r\n\r\n                // 1초 후 서보모터를 다시 0으로 자동 복귀\r\n                setTimeout(() => {\r\n                    Entry.hw.sendQueue[port] = 0;\r\n                    Entry.hw.update && Entry.hw.update();\r\n                }, 26);\r\n\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        close_door: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [{ type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 }],\r\n            def: { type: 'close_door' },\r\n            class: 'SmartCodingHouseActuator',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                let port = Entry.smartCodingHouse.digitalPin.SERVO_MOTOR;\r\n\r\n                // 서보모터를 90으로 설정\r\n                Entry.hw.sendQueue[port] = 2;\r\n                Entry.hw.update && Entry.hw.update();\r\n\r\n                // 1초 후 서보모터를 다시 0으로 자동 복귀\r\n                setTimeout(() => {\r\n                    Entry.hw.sendQueue[port] = 0;\r\n                    Entry.hw.update && Entry.hw.update();\r\n                }, 26);\r\n\r\n                return script.callReturn();\r\n            },\r\n        },\r\n\r\n        run_ceiling_fan: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['ON', 'on'],\r\n                        ['OFF', 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            paramsKeyMap: { STATE: 0 },\r\n            def: { type: 'run_ceiling_fan', params: [null, null] },\r\n            class: 'SmartCodingHouseActuator',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                // 드롭다운 메뉴에서 선택한 상태 읽기 (\"on\" 또는 \"off\")\r\n                var state = script.getField('STATE', script);\r\n                let port = Entry.smartCodingHouse.digitalPin.DC_MOTOR;\r\n                // \"ON\"이면 최대 속도 127, \"OFF\"이면 0\r\n                let speed = state === 'on' ? 127 : 0;\r\n                // 기존값에서 방향 비트를 유지하고 속도 값만 업데이트\r\n                let current = Entry.hw.sendQueue[port] || 0;\r\n                current = (current & 0x80) | speed;\r\n                // 강제로 시계방향 (0x80) 설정\r\n                current |= 0x80;\r\n                Entry.hw.sendQueue[port] = current;\r\n                Entry.hw.update && Entry.hw.update();\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        led_set_color: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1층 실외', 'OUTDOOR1'],\r\n                        ['실내', 'INDOOR'],\r\n                        ['2층 테라스', 'TERRACE2'],\r\n                    ],\r\n                    value: 'OUTDOOR1',\r\n                    fontSize: 11,\r\n                },\r\n                { type: 'Color' },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            paramsKeyMap: { LOCATION: 0, COLOR: 1 },\r\n            def: { params: [null, null, null], type: 'led_set_color' },\r\n            class: 'SmartCodingHouseLED',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                let location = script.getField('LOCATION', script);\r\n                let color = script.getStringField('COLOR', script);\r\n                if (!location) {\r\n                    console.error('Error: LOCATION 값이 undefined!');\r\n                    return script.callReturn();\r\n                }\r\n                let rgb = hexToRgb(color);\r\n                let pinR, pinG, pinB;\r\n                if (location === 'OUTDOOR1') {\r\n                    pinR = Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_RED;\r\n                    pinG = Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_GREEN;\r\n                    pinB = Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_BLUE;\r\n                } else if (location === 'INDOOR') {\r\n                    pinR = Entry.smartCodingHouse.digitalPin.INDOOR_LED_RED;\r\n                    pinG = Entry.smartCodingHouse.digitalPin.INDOOR_LED_GREEN;\r\n                    pinB = Entry.smartCodingHouse.digitalPin.INDOOR_LED_BLUE;\r\n                } else if (location === 'TERRACE2') {\r\n                    pinR = Entry.smartCodingHouse.digitalPin.TERRACE2_LED_RED;\r\n                    pinG = Entry.smartCodingHouse.digitalPin.TERRACE2_LED_GREEN;\r\n                    pinB = Entry.smartCodingHouse.digitalPin.TERRACE2_LED_BLUE;\r\n                }\r\n                // 콘솔 로그로 선택된 포트 번호 확인\r\n                // console.log('LED OFF - Location:', location);\r\n                // console.log('Port Red:', pinR, 'Port Green:', pinG, 'Port Blue:', pinB);\r\n\r\n                // LED 출력: 하드웨어 업데이트 전에 값 할당\r\n                Entry.hw.sendQueue[pinR] = rgb.r;\r\n                Entry.hw.sendQueue[pinG] = rgb.g;\r\n                Entry.hw.sendQueue[pinB] = rgb.b;\r\n                // 강제로 하드웨어 업데이트 호출 (다른 LED 블록에서도 사용하는 패턴)\r\n                Entry.hw.update && Entry.hw.update();\r\n                return script.callReturn();\r\n            },\r\n        },\r\n\r\n        led_off: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.default.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['실내', 'INDOOR'],\r\n                        ['1층 실외', 'OUTDOOR1'],\r\n                        ['2층 테라스', 'TERRACE2'],\r\n                    ],\r\n                    value: 'INDOOR',\r\n                    fontSize: 11,\r\n                },\r\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 12 },\r\n            ],\r\n            paramsKeyMap: { LOCATION: 0 },\r\n            def: { type: 'led_off', params: [null] },\r\n            class: 'SmartCodingHouseLED',\r\n            isNotFor: ['smartCodingHouse'],\r\n            func: function (sprite, script) {\r\n                let location = script.getField('LOCATION', script);\r\n                let portR, portG, portB;\r\n                if (location === 'INDOOR') {\r\n                    portR = Entry.smartCodingHouse.digitalPin.INDOOR_LED_RED;\r\n                    portG = Entry.smartCodingHouse.digitalPin.INDOOR_LED_GREEN;\r\n                    portB = Entry.smartCodingHouse.digitalPin.INDOOR_LED_BLUE;\r\n                } else if (location === 'OUTDOOR1') {\r\n                    portR = Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_RED;\r\n                    portG = Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_GREEN;\r\n                    portB = Entry.smartCodingHouse.digitalPin.OUTDOOR1_LED_BLUE;\r\n                } else if (location === 'TERRACE2') {\r\n                    portR = Entry.smartCodingHouse.digitalPin.TERRACE2_LED_RED;\r\n                    portG = Entry.smartCodingHouse.digitalPin.TERRACE2_LED_GREEN;\r\n                    portB = Entry.smartCodingHouse.digitalPin.TERRACE2_LED_BLUE;\r\n                }\r\n                Entry.hw.sendQueue[portR] = 0;\r\n                Entry.hw.sendQueue[portG] = 0;\r\n                Entry.hw.sendQueue[portB] = 0;\r\n                return script.callReturn();\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.smartCodingHouse;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_smartboard.js",
    "content": "'use strict';\n\nEntry.SmartBoard = {\n    id: 'A.1',\n    name: 'smartBoard',\n    url: 'http://www.sciencebox.co.kr',\n    imageName: 'smartboard.png',\n    title: {\n        ko: '과학상자 코딩보드',\n        en: 'Sciencebox Codingboard',\n        vn: 'Sciencebox Codingboard',\n    },\n    setZero: function() {\n        for (var port = 2; port < 9; port++) {\n            Entry.hw.sendQueue[port] = 0;\n        }\n        Entry.hw.update();\n    },\n    monitorTemplate: {\n        listPorts: {\n            '2': {\n                name: ' GS2 ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '3': {\n                name: ' GS1 ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '4': {\n                name: ' MT1 direction',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '5': {\n                name: ' MT1 PWM ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '6': {\n                name: ' MT2 PWM ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '7': {\n                name: ' MT2 direction ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '8': {\n                name: ' RELAY ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '9': {\n                name: ' SM3 angle ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '10': {\n                name: ' SM2 angle ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '11': {\n                name: ' SM1 angle ',\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            '12': {\n                name: ' RED button ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '13': {\n                name: ' YELLOW button ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '14': {\n                name: ' GREEN button ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            '15': {\n                name: ' BLUE button ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a2: {\n                name: ' SENSOR 1 ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a3: {\n                name: ' SENSOR 2 ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a4: {\n                name: ' SENSOR 3 ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a5: {\n                name: ' SENSOR 4 ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a0: {\n                name: ' SENSOR 5 ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a1: {\n                name: ' SENSOR 6 ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a6: {\n                name: ' SENSOR 7 ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            a7: {\n                name: ' SENSOR 8 ',\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.SmartBoard.setLanguage = function() {\n    return {\n        en: {\n            Blocks: {\n                MT1direction: 'MT1 Direction of rotation',\n                MT2direction: 'MT2 Direction of rotation',\n                SM3angle: 'SM3 angle',\n                SM2angle: 'SM2 angle',\n                SM13angle: 'SM1 angle',\n                Red: 'Red',\n                Yellow: 'Yellow',\n                Green: 'Green',\n                Blue: 'Blue',\n                One: 'Number 1',\n                Two: 'Number 2',\n                Three: 'Number 3',\n                Four: 'Number 4',\n                Five: 'Number 5',\n                Six: 'Number 6',\n                Seven: 'Number 7',\n                Eight: 'Number 8',\n                Clockwise: 'Forward',\n                Counterclockwise: 'Backward',\n                Stopmotor: 'Stop',\n                Slowermotor: 'Very slow',\n                Slowmotor: 'Slow',\n                Normalmotor: 'Normal',\n                Fastmotor: 'Fast',\n                Fastermotor: 'Very fast',\n                Slowservo: 'Slow',\n                Normalservo: 'Normal',\n                Fastservo: 'Fast',\n                On: 'On',\n                Off: 'Off',\n            },\n            template: {\n                smartBoard_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\n                smartBoard_get_named_sensor_value: '%1 Sensor value',\n                smartBoard_is_button_pressed: 'Pressed %1 button?',\n                smartBoard_set_dc_motor_direction: '%1 DC Motor direction %2 %3',\n                smartBoard_set_dc_motor_speed: '%1 DC Motor Speed %2 %3',\n                smartBoard_set_dc_motor_pwm: '%1 DC Motor set speed %2 %3',\n                smartBoard_set_servo_speed: '%1 RC Servo Motor Speed %2 %3',\n                smartBoard_set_servo_angle: '%1 RC Servo Motor set angle %2 %3',\n                smartBoard_set_number_eight_pin: '%1 port %2 %3',\n                smartBoard_set_gs1_pwm: 'Set PWM port of GS1 port %1 %2',\n            },\n        },\n        ko: {\n            Blocks: {\n                MT1direction: 'MT1 회전 방향',\n                MT2direction: 'MT2 회전 방향',\n                SM3angle: 'SM3 각도',\n                SM2angle: 'SM2 각도',\n                SM13angle: 'SM1 각도',\n                Red: '빨간',\n                Yellow: '노란',\n                Green: '초록',\n                Blue: '파란',\n                One: '1번',\n                Two: '2번',\n                Three: '3번',\n                Four: '4번',\n                Five: '5번',\n                Six: '6번',\n                Seven: '7번',\n                Eight: '8번',\n                Clockwise: '정',\n                Counterclockwise: '역',\n                Stopmotor: '정지 시키기',\n                Slowermotor: '매우 느린 속도로 돌리기',\n                Slowmotor: '느린 속도로 돌리기',\n                Normalmotor: '보통 속도로 돌리기',\n                Fastmotor: '빠른 속도로 돌리기',\n                Fastermotor: '매우 빠른 속도로 돌리기',\n                Slowservo: '느린 속도로',\n                Normalservo: '보통 속도로',\n                Fastservo: '빠른 속도로',\n                On: '켜기',\n                Off: '끄기',\n            },\n            template: {\n                smartBoard_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값',\n                smartBoard_get_named_sensor_value: '%1 센서값',\n                smartBoard_is_button_pressed: '%1 버튼을 눌렀는가?',\n                smartBoard_set_dc_motor_direction: '%1 DC 모터를 %2 방향으로 정하기 %3',\n                smartBoard_set_dc_motor_speed: '%1 DC모터를 %2 %3',\n                smartBoard_set_dc_motor_pwm: '%1 DC모터를 %2 속도로 돌리기 %3',\n                smartBoard_set_servo_speed: '%1 번 서보모터의 속도를 %2 %3',\n                smartBoard_set_servo_angle: '%1 번 서보모터를 %2 도 로 움직이기 %3',\n                smartBoard_set_number_eight_pin: '%1 포트를 %2 %3',\n                smartBoard_set_gs1_pwm: 'GS1 포트의 PWM을 %1 로 정하기 %2',\n            },\n        },\n        vn: {\n            Blocks: {\n                MT1direction: 'Hướng quay tròn MT1',\n                MT2direction: 'Hướng quay tròn MT1',\n                SM3angle: 'Góc độ SM3',\n                SM2angle: 'Góc độ SM2',\n                SM13angle: 'Góc độ SM1',\n                Red: 'Đỏ',\n                Yellow: 'Vàng',\n                Green: 'Xanh lá cây',\n                Blue: 'Xanh da trời',\n                One: '1 lần',\n                Two: '2 lần',\n                Three: '3 lần',\n                Four: '4 lần',\n                Five: '5 lần',\n                Six: '6 lần',\n                Seven: '7 lần',\n                Eight: '8 lần',\n                Clockwise: 'Thuận',\n                Counterclockwise: 'Ngược',\n                Stopmotor: 'Ngừng lại',\n                Slowermotor: 'Quay với tốc độ rất chậm',\n                Slowmotor: 'Quay với tốc độ chậm',\n                Normalmotor: 'Quay với tốc độ thường',\n                Fastmotor: 'Quay với tốc độ nhanh',\n                Fastermotor: 'Quay với tốc độ rất nhanh',\n                Slowservo: 'với tốc độ chậm',\n                Normalservo: 'với tốc độ thường',\n                Fastservo: 'với tốc độ nhanh',\n                On: 'Tắt',\n                Off: 'Mở',\n            },\n            template: {\n                smartBoard_convert_scale:\n                    'Phạm vi của giá trị %1 đã thay đổi từ %2 ~ %3 thành %4 ~ %5',\n                smartBoard_get_named_sensor_value: '%1 Giá trị cảm biến',\n                smartBoard_is_button_pressed: 'Bạn đã nhấn chọn %1?',\n                smartBoard_set_dc_motor_direction: 'Chỉnh Mô tơ DC %1 theo hướng %2 %3',\n                smartBoard_set_dc_motor_speed: '%2 mô tơ DC %1 %3',\n                smartBoard_set_dc_motor_pwm: 'Quay Mô tơ DC %1 với tốc độ %2 %3',\n                smartBoard_set_servo_speed: '%1 tốc độ của Mô tơ Servo %2 %3',\n                smartBoard_set_servo_angle: 'Di chuyển Mô tơ Servo %1 theo hướng %2 độ %3',\n                smartBoard_set_number_eight_pin: '%2 cổng %1 %3',\n                smartBoard_set_gs1_pwm: 'Chỉnh PWM của cổng GS1 thành %1 %2',\n            },\n        },\n    };\n};\n\nEntry.SmartBoard.blockMenuBlocks = [\n    //jeil science smartBoard. 2016-11-03\n    //smartBoard\n    'smartBoard_get_named_sensor_value',\n    'smartBoard_convert_scale',\n    'smartBoard_is_button_pressed',\n    'smartBoard_set_dc_motor_direction',\n    'smartBoard_set_dc_motor_speed',\n    'smartBoard_set_dc_motor_pwm',\n    'smartBoard_set_servo_speed',\n    'smartBoard_set_servo_angle',\n    'smartBoard_set_number_eight_pin',\n    'smartBoard_set_gs1_pwm',\n];\n\nEntry.SmartBoard.getBlocks = function() {\n    return {\n        //region smartBoard 스마트보드\n        smartBoard_get_named_sensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['SEN1', '2'],\n                        ['SEN2', '3'],\n                        ['SEN3', '4'],\n                        ['SEN4', '5'],\n                        ['SEN5', '0'],\n                        ['SEN6', '1'],\n                        ['SEN7', '6'],\n                        ['SEN8', '7'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'smartBoard_get_named_sensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'smartBoard_sensor',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                return Entry.hw.getAnalogPortValue(script.getField('PORT', script));\n            },\n        },\n        smartBoard_convert_scale: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'smartBoard_get_named_sensor_value',\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'smartBoard_convert_scale',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'smartBoard_sensor',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                var value1 = script.getNumberValue('VALUE1', script);\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n                var result = value1;\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n                return Math.round(result);\n            },\n            syntax: {\n                js: [],\n                py: ['smartBoard.convert_scale(%1, %2, %3, %4, %5)'],\n            },\n        },\n        smartBoard_is_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.Red, '12'],\n                        [Lang.Blocks.Yellow, '13'],\n                        [Lang.Blocks.Green, '14'],\n                        [Lang.Blocks.Blue, '15'],\n                    ],\n                    value: '12',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'smartBoard_is_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'smartBoard_button',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                return Entry.hw.getDigitalPortValue(script.getNumberField('PORT', script));\n            },\n        },\n        smartBoard_set_dc_motor_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['MT1', '4'],\n                        ['MT2', '7'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.Clockwise, '0'],\n                        [Lang.Blocks.Counterclockwise, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'smartBoard_set_dc_motor_direction',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'dc_motor',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                Entry.hw.setDigitalPortValue(\n                    script.getField('PORT'),\n                    script.getNumberField('OPERATOR')\n                );\n                return script.callReturn();\n            },\n        },\n        smartBoard_set_dc_motor_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['MT1', '5'],\n                        ['MT2', '6'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.Stopmotor, '0'],\n                        [Lang.Blocks.Slowermotor, '70'],\n                        [Lang.Blocks.Slowmotor, '115'],\n                        [Lang.Blocks.Normalmotor, '160'],\n                        [Lang.Blocks.Fastmotor, '205'],\n                        [Lang.Blocks.Fastermotor, '255'],\n                    ],\n                    value: '160',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'smartBoard_set_dc_motor_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'dc_motor',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                Entry.hw.setDigitalPortValue(\n                    script.getField('PORT'),\n                    script.getNumberField('OPERATOR')\n                );\n                return script.callReturn();\n            },\n        },\n        smartBoard_set_dc_motor_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['MT1', '5'],\n                        ['MT2', '6'],\n                    ],\n                    value: '5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'arduino_text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'smartBoard_set_dc_motor_pwm',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'dc_motor',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n        },\n        smartBoard_set_servo_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['SM3', '9'],\n                        ['SM2', '10'],\n                        ['SM1', '11'],\n                    ],\n                    value: '9',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.Slowservo, '187'],\n                        [Lang.Blocks.Normalservo, '193'],\n                        [Lang.Blocks.Fastservo, '243'],\n                    ],\n                    value: '193',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'smartBoard_set_servo_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'smartBoard_servo_motor',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                Entry.hw.setDigitalPortValue(\n                    script.getField('PORT'),\n                    script.getNumberField('OPERATOR')\n                );\n                if (!script.isStart) {\n                    script.isStart = true;\n                    script.timeFlag = 1;\n                    setTimeout(function() {\n                        script.timeFlag = 0;\n                    }, 250);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    return script.callReturn();\n                }\n            },\n        },\n        smartBoard_set_servo_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['SM3', '9'],\n                        ['SM2', '10'],\n                        ['SM1', '11'],\n                    ],\n                    value: '9',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'arduino_text',\n                        params: ['180'],\n                    },\n                    null,\n                ],\n                type: 'smartBoard_set_servo_angle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE: 1,\n            },\n            class: 'smartBoard_servo_motor',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                var port = script.getField('PORT');\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 1);\n                value = Math.min(value, 180);\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n        },\n        smartBoard_set_number_eight_pin: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['GS1', '3'],\n                        ['GS2', '2'],\n                        ['RELAY', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.On, '0'],\n                        [Lang.Blocks.Off, '255'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'smartBoard_set_number_eight_pin',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                OPERATOR: 1,\n            },\n            class: 'ext',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                Entry.hw.setDigitalPortValue(\n                    script.getField('PORT'),\n                    script.getNumberField('OPERATOR')\n                );\n                return script.callReturn();\n            },\n        },\n        smartBoard_set_gs1_pwm: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'arduino_text',\n                        params: ['255'],\n                    },\n                ],\n                type: 'smartBoard_set_gs1_pwm',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'ext',\n            isNotFor: ['smartBoard'],\n            func: function(sprite, script) {\n                var port = 3;\n                var value = script.getNumberValue('VALUE');\n                value = Math.round(value);\n                value = Math.max(value, 0);\n                value = Math.min(value, 255);\n                Entry.hw.setDigitalPortValue(port, value);\n                return script.callReturn();\n            },\n        },\n        //endregion smartBoard 스마트보드\n    };\n};\n\nmodule.exports = Entry.SmartBoard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_ssboard_nano.js",
    "content": "'use strict';\r\n\r\nlet delay_time = 0;\r\nlet lmotor_speed = 0;\r\nlet rmotor_speed = 0;\r\nlet rgbled_r = [];\r\nlet rgbled_g = [];\r\nlet rgbled_b = [];\r\n\r\nEntry.ssboard_nano = {\r\n    id: '3D.2',\r\n    name: 'ssboard_nano',\r\n    url: 'http://www.ssmaker.co.kr/',\r\n    imageName: 'ssboard_nano.png',\r\n    title: {\r\n        'ko': '상상보드 나노', \r\n        'en': 'ssboard_nano'\r\n    },\r\n\r\n    setZero: () => {\r\n        ///  하드웨어 초기화 로직\r\n        if (!Entry.hw.sendQueue.SET) {\r\n            Entry.hw.sendQueue = {\r\n                GET: {},\r\n                SET: {},\r\n            };\r\n        } else {\r\n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\r\n            keySet.forEach((key) => {\r\n                Entry.hw.sendQueue.SET[parseInt(key, 10)].data = 0;\r\n                Entry.hw.sendQueue.SET[parseInt(key, 10)].time = new Date().getTime();\r\n            });\r\n        }\r\n        Entry.hw.update();\r\n        lmotor_speed = 0;\r\n        rmotor_speed = 0;\r\n        for (var i = 0; i < 255; i++) {\r\n            rgbled_r[i] = 0;\r\n            rgbled_g[i] = 0;\r\n            rgbled_b[i] = 0;\r\n        }\r\n    },\r\n    Static: {\r\n//        ssboard_nano_BLOCK_COLOR: '#00979D', // gray(#848484)\r\n//        ssboard_nano_ARROW_COLOR_HW: '#00979D',\r\n    },\r\n    sensorTypes: {\r\n        ALIVE: 0,\r\n        DIGITAL: 1,\r\n        ANALOG: 2,\r\n        BUZZER: 3,\r\n        SERVO: 4,\r\n        TONE: 5,\r\n        TEMP: 6,\r\n        USONIC: 7,\r\n        RGBLED: 11,\r\n        MOTOR: 12,\r\n        RGBLEDSHOW: 13,\r\n        PWM: 32,\r\n        USONIC_SET: 33,\r\n        I2C_SET: 34,\r\n        LCD_SET: 40,\r\n    },\r\n    toneTable: {\r\n        '0': 0,\r\n        C: 1,\r\n        CS: 2,\r\n        D: 3,\r\n        DS: 4,\r\n        E: 5,\r\n        F: 6,\r\n        FS: 7,\r\n        G: 8,\r\n        GS: 9,\r\n        A: 10,\r\n        AS: 11,\r\n        B: 12,\r\n    },\r\n    toneMap: {\r\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\r\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\r\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\r\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\r\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\r\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\r\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\r\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\r\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\r\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\r\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\r\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\r\n    },\r\n    BlockState: {},\t\r\n};\r\n\r\nEntry.ssboard_nano.blockMenuBlocks = [\r\n    /// 하드웨어 블록 등록 , 여기에 등록된 블록이 순서대로 나열되며 설정한 이름으로 화면에 보임\r\n    'ssboard_nano_buzzer_onoff',\t\t\t            // 스피커 삐 소리\r\n    'ssboard_nano_set_digital_buzzer',               // 스피커 멜로디\r\n    'ssboard_nano_set_motor_speed',                  // DC모터 속도제어\r\n  //  'ssboard_nano_motor_stop',            // DC모터 정지하기\t\r\n    'ssboard_nano_set_servo',                        // 서보모터 제어\r\n\r\n    'ssboard_nano_set_rgbled_onoff',                // rgb led로 지정색 제어\r\n    'ssboard_nano_rgbled_seting',                // rgb led 핀번호 설정\r\n    'ssboard_nano_set_rgbled_value',                //rgb led 개별색 제어\r\n    'ssboard_nano_rgbled_all_onoff',                // rgb led all show, all off\r\n\r\n    'ssboard_nano_digital_onoff',                   /// 디지털 포트 제어\r\n    'ssboard_nano_get_digital_value',\t            //디지탈 입력\r\n    'ssboard_nano_get_analog_value',                 // 아날로그 입력\r\n    'ssboard_nano_set_pwm',                          //PWM제어\r\n\r\n    'ssboard_nano_set_ultrasonic',                   //초음파센서 포트설정\r\n    'ssboard_nano_get_usonic_value',              //초음파센서 읽기\r\n    'ssboard_nano_set_temp',                  //온도센서 연결포트 설정\r\n    'ssboard_nano_get_temp_value',                   // 온도센서 입력\r\n    'ssboard_nano_set_i2c',                   //I2C포트 센서연결설정\r\n    'ssboard_nano_get_color_value',                  // 컬러센서 입력\r\n    'ssboard_nano_get_gyro_value',                   // 자이로센서 입력\r\n\r\n    'ssboard_nano_set_lcd_string',\r\n    'ssboard_nano_set_lcd_init',\r\n    'ssboard_nano_set_lcd_clear',\r\n\r\n\t'ssboard_nano_get_analog_mapping',\r\n\r\n\t\t\r\n];\r\n\r\nEntry.ssboard_nano.setLanguage = function() {    // 블록 이름  번역\r\n    return {\r\n        ko: {\r\n            template: {\r\n                ssboard_nano_buzzer_onoff: '스피커 삐 소리 %1 초 연주 %2',\t\t\t\t\r\n                ssboard_nano_set_digital_buzzer: '스피커음계 %1 옥타브 %2 음 %3 초 연주 %4',\t\r\n                ssboard_nano_set_motor_speed: 'DC모터 왼쪽 속도%1 오른쪽 속도%2 으로 정하기 %3', \r\n                ssboard_nano_motor_stop: 'DC모터 정지하기 %1',\t\r\n                ssboard_nano_set_servo: '서보모터 %1번 핀 각도 %2 %3',\t\t\r\n\r\n                ssboard_nano_set_rgbled_onoff: 'RGB LED %1 번째 색깔 %2 %3',\t\r\n                ssboard_nano_rgbled_seting: 'RGB LED %1핀에 %2개  밝기%3  %4',   \r\n                ssboard_nano_set_rgbled_value: 'RGB LED %1번째  빨강%2 초록%3 파랑%4 %5',\r\n                ssboard_nano_rgbled_all_onoff: 'RGB LED  %1 %2',\r\n\r\n                ssboard_nano_digital_onoff: '디지털 %1 핀 %2 %3',         \r\n                ssboard_nano_get_digital_value: '디지털 %1 핀 읽기',\t\t\t\t\r\n                ssboard_nano_get_analog_value: '아날로그 %1 핀 읽기',\r\n                ssboard_nano_set_pwm: 'PWM %1 핀에 %2 %3',\t\r\n\r\n                ssboard_nano_set_ultrasonic: '초음파센서 설정 트리거 %1 핀, 에코 %2 핀 으로 연결 %3',\t\r\n                ssboard_nano_get_usonic_value: '초음파센서 값 읽기',\t\r\n                ssboard_nano_set_temp: '온도센서 %1 핀에 연결 %2',\t\r\n                ssboard_nano_get_temp_value: '온도센서 값 읽기',\t\r\n                ssboard_nano_set_i2c: 'I2C포트  %1 연결 %2',\t\r\n                ssboard_nano_get_color_value: '컬러센서 %1 값 읽기',\r\n                ssboard_nano_get_gyro_value: '자이로센서 %1 값 읽기',\r\n\r\n                ssboard_nano_set_lcd_string: 'lcd 세로%1줄,  가로%2줄 에  %3 표시 %4',\r\n                ssboard_nano_set_lcd_init: 'lcd 설정 : I2C 주소 0x%1 , 가로줄 수 %2 , 세로줄 수 %3 으로 설정하기%4',\r\n                ssboard_nano_set_lcd_clear: 'lcd 지우기 %1',\r\n\r\n\r\n                ssboard_nano_get_analog_mapping: ' %1 값 %2 ~ %3 에서 %4 ~ %5 으로 변환값', \r\n            },\r\n            Blocks: {\r\n                On_block: '켜짐(HIGH, 5V)',\r\n                Off_block: '꺼짐(LOW, 0V)',\r\n                AllOn_block: '모두 켜짐',\r\n                AllOff_block: '모두 꺼짐',\r\n                RGB_red: '빨강색',\r\n                RGB_blue: '파란색',\r\n                RGB_green: '초록색',\r\n                RGB_white: '하얀색',\r\n                RGB_skyblue: '하늘색',\r\n                RGB_yellow: '노란색',\r\n                RGB_purple: '보라색',\r\n                RGB_off: '끄기',\r\n            }\r\n        },\r\n        en: {\r\n            template: {\r\n                ssboard_nano_buzzer_onoff: 'Speakers Beep %1 Playing Second %2',\t\t\t\t\r\n                ssboard_nano_set_digital_buzzer: 'Speakers  %1 Octave %2 Play %3 seconds %4',\t\r\n                ssboard_nano_set_motor_speed: 'Set DC motor left speed %1  right speed %2 %3', \t\r\n                ssboard_nano_motor_stop: 'Stop DC Motor %1',\t\r\n                ssboard_nano_set_servo: 'Servo motor %1 pin angle %2 movement %3',\t\t\r\n\r\n                ssboard_nano_set_rgbled_onoff: 'RGB LED %1 First Color %2 %3',\t\t\r\n                ssboard_nano_rgbled_seting: 'Setting %2 brightness %3 on RGB LED %1 pin %4',\r\n                ssboard_nano_set_rgbled_value: 'RGB LED %1 st Red %2 Green %3 Blue %4',\r\n                ssboard_nano_rgbled_all_onoff: 'RGB LED %1 %2',\t\t\r\n\r\n                ssboard_nano_digital_onoff: 'Setting up digital %1 pin %2 %3',\t\r\n                ssboard_nano_get_digital_value: 'Read digital %1 pins',\t\t\t\t\r\n                ssboard_nano_get_analog_value: 'Analog %1 pin read',\r\n                ssboard_nano_set_pwm: 'Send %2 to pin %1 %3',\t\t\r\n\r\n                ssboard_nano_set_ultrasonic: 'Connecting to the ultrasonic sensor setting trigger %1 pin, echo %2 pin %3',\t\t\r\n                ssboard_nano_get_usonic_value: 'Reading ultrasonic sensor values',\t\t\r\n                ssboard_nano_set_temp: 'Connecting to the temperature sensor %1 pin %2',\t\t\r\n                ssboard_nano_get_temp_value: 'Reading temperature sensor values',\t\t\r\n                ssboard_nano_set_i2c: 'Connect I2Cport %1 %2',\t\t\r\n                ssboard_nano_get_color_value: 'Reading the color sensor %1 value',\r\n                ssboard_nano_get_gyro_value: 'Read gyro sensor %1 value',\r\n\r\n                ssboard_nano_set_lcd_string: 'lcd Display %3 on line %1 and line %2 %4',\t\t\r\n                ssboard_nano_set_lcd_init: 'setting lcd : I2C address 0x%1 , horizontal line number %2 , vertical line number %3 %4',\t\r\n                ssboard_nano_set_lcd_clear: 'Clear lcd %1',\t\t\r\n\r\n\t\t\t\t\r\n                ssboard_nano_get_analog_mapping: '%1 value %2 to %3 ; to %4 to %5 conversion value ',\t\r\n\t\t\t\t\t\t\t\t\r\n            },\r\n            Blocks: {\r\n                On_block: 'On(HIGH, 5V)',\r\n                Off_block: 'Off(LOW, 0V)',\r\n                AllOn_block: 'ALL ON',\r\n                AllOff_block: 'ALL OFF',\r\n                RGB_red: 'Red',\r\n                RGB_blue: 'Blue',\r\n                RGB_green: 'Green',\r\n                RGB_white: 'White',\r\n                RGB_skyblue: 'Sky blue',\r\n                RGB_yellow: 'Yellow',\r\n                RGB_purple: 'Purple',\r\n                RGB_off: 'Off',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\n\r\nEntry.ssboard_nano.getBlocks = function() {\r\n    return {\r\n        ssboard_nano_digital_port_onoff_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.On_block, '1'],\r\n                        [Lang.Blocks.Off_block, '0'],\r\n                    ],\t\t\t\t\t\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getField('PORT');\r\n            },\r\n        },\t\r\n        \r\n        ssboard_nano_list_digital_octave: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                        ['8', '8'],\r\n                    ],\r\n                    value: '5',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getField('OCTAVE');\r\n            },\r\n        },\r\n\t\t\r\n        ssboard_nano_list_digital_tone: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.silent, '0'],\r\n                        [Lang.Blocks.do_name, 'C'],\r\n                        [Lang.Blocks.do_sharp_name, 'CS'],\r\n                        [Lang.Blocks.re_name, 'D'],\r\n                        [Lang.Blocks.re_sharp_name, 'DS'],\r\n                        [Lang.Blocks.mi_name, 'E'],\r\n                        [Lang.Blocks.fa_name, 'F'],\r\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\r\n                        [Lang.Blocks.sol_name, 'G'],\r\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\r\n                        [Lang.Blocks.la_name, 'A'],\r\n                        [Lang.Blocks.la_sharp_name, 'AS'],\r\n                        [Lang.Blocks.si_name, 'B'],\r\n                    ],\r\n                    value: 'C',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                NOTE: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getField('NOTE');\r\n            },\r\n        },\r\n        ssboard_nano_digital_port_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['D3', '3'],\r\n                        ['D4', '4'],\r\n                        ['D5', '5'],\r\n                        ['D13', '13'],\r\n                        ['A0', '14'],\r\n                        ['A1', '15'],\r\n                        ['A2', '16'],\r\n                        ['KEY_UP', '17'],\r\n                        ['KEY_DN', '20'],\r\n                        ['KEY_LEFT', '21'],\r\n                        ['KEY_RIGHT', '2'],\r\n                        ['KEY_A', '12'],\r\n                        ['KEY_B', '11'],\r\n\r\n                    ],\r\n                    value: '3',       // 기본 표시값\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n        ssboard_nano_digital_out_port_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['D3', '3'],\r\n                        ['D4', '4'],\r\n                        ['D5', '5'],\r\n                        ['D13', '13'],\r\n                        ['A0', '14'],\r\n                        ['A1', '15'],\r\n                        ['A2', '16'],\r\n                     ],\r\n                    value: '3',       // 기본 표시값\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getStringField('PORT');\r\n            },\r\n        },\r\n\r\n        ssboard_nano_pwn_port_list: \r\n        {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['3', '3'],\r\n                        ['5', '5'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PWMPORT: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getStringField('PWMPORT');\r\n            },\r\n        },\r\n        ssboard_nano_lcd_add_list: \r\n        {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['27', '39'],\r\n                        ['3f', '63'],\r\n                    ],\r\n                    value: '39',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                LCDADD: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getStringField('LCDADD');\r\n            },\r\n        },\r\n        ssboard_nano_i2c_sen_list: \r\n        {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['Color Sensor', '1'],\r\n                        ['Gyro Sensor', '2'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                SENSOR: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getStringField('SENSOR');\r\n            },\r\n        },\r\n\r\n        ssboard_nano_all_onoff_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n\t\t\tfontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.AllOff_block, '2'],\r\n                        [Lang.Blocks.AllOn_block, '3'],\r\n                    ],\t\t\t\t\t\r\n                    value: '2',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getField('VALUE');\r\n            },\r\n        },\r\n        ssboard_nano_analog_port_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['A0', '0'],\r\n                        ['A1', '1'],\r\n                        ['A2', '2'],\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n\r\n        ssboard_nano_ultrasonic_port_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                    ],\r\n                    value: '3',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n        ssboard_nano_analog_rgb_color_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\r\n            fontColor: '#fff',\t\t\t\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.RGB_red, '0'],\r\n                        [Lang.Blocks.RGB_blue, '1'],\r\n                        [Lang.Blocks.RGB_green, '2'],\r\n                        [Lang.Blocks.RGB_white, '3'],\r\n                        [Lang.Blocks.RGB_skyblue, '4'],\r\n                        [Lang.Blocks.RGB_yellow, '5'],\r\n                        [Lang.Blocks.RGB_purple, '6'],\r\n                        [Lang.Blocks.RGB_off, '7'],\t\t\t\t\t\t\r\n                    ],\r\n                    value: '0',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func: (sprite, script) => {\r\n                return script.getField('PORT');\r\n            },\r\n        },\r\n\r\n\r\n\t\t// 1. 삐소리\r\n        ssboard_nano_buzzer_onoff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_buzzer_onoff',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'ssboard_nano_LV1',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const port = 10;\r\n                let duration = script.getNumberValue('VALUE');\t// 길이\t\r\n                //var octave = 5;    // 옥타브\r\n                const value = 2400;//698;   // 음 주파수\r\n                //var mode = 1;\r\n\r\n                if (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    if (duration == 0) {// 음 길이가 0 이면\r\n\t                    Entry.hw.sendQueue.SET[port] = {\r\n                            type: Entry.ssboard_nano.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n                    if(duration > 300)\r\n                        duration = 300;\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;  // 출력 시작 플래그 셋\r\n                    script.timeFlag = 1;    // 시간플래그 셋\r\n\r\n                    Entry.hw.sendQueue.SET[port] = {\r\n                        type: Entry.ssboard_nano.sensorTypes.TONE,\r\n                        data: \r\n                        {\r\n                            value: value,\r\n                            duration: duration / 10,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } \r\n\t\t\t\telse    // 설정 시간이 지나면 출력 리셋\r\n\t\t\t\t{\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue.SET[port] = \r\n\t\t\t\t\t{\r\n                        type: Entry.ssboard_nano.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            \t\t\t\t\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\t\t\r\n\t\t// 2) 옥타브/음/초 동안 연주\r\n        ssboard_nano_set_digital_buzzer: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            template: Lang.template.ssboard_nano_set_digital_buzzer,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_list_digital_octave',\t\t\t\t\t\t\r\n                    },\r\n                    {\r\n                        type: 'ssboard_nano_list_digital_tone',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['0.25'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_digital_buzzer',\r\n            },\r\n            paramsKeyMap: {\r\n                OCTAVE: 0,\t\t\t\t\r\n                NOTE: 1,\r\n                DURATION: 2,\r\n            },\r\n            class: 'ssboard_nano_LV1',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const port = 10; //script.getNumberValue('PORT');\r\n                let duration = script.getNumberValue('DURATION');\r\n                let octave = script.getNumberValue('OCTAVE') - 1;\r\n                let value = 0;\r\n\r\n                if (!script.isStart) {\r\n                    var note = script.getValue('NOTE');\r\n                    if (!Entry.Utils.isNumber(note)) {\r\n                        note = Entry.ssboard_nano.toneTable[note];\r\n                    }\r\n                    if (note < 0) note = 0;\r\n                    else if (note > 12) note = 12;\r\n\r\n                    if (duration < 0) duration = 0;\r\n\t\t\t\t\t\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n\t\t\t\t\t\r\n                    if (duration == 0) {\r\n                        Entry.hw.sendQueue.SET[port] = \r\n\t\t\t\t\t\t{\r\n                            type: Entry.ssboard_nano.sensorTypes.TONE,\r\n                            data: 0,\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        return script.callReturn();\r\n                    }\r\n\t\t\t\t\t\r\n                    if (octave < 0) octave = 0;\r\n                    else if (octave > 8) octave = 8;\r\n                    if (note != 0) value = Entry.ssboard_nano.toneMap[note][octave];\r\n                    if(duration > 300)\r\n                        duration = 300;\r\n                    duration = duration * 1000;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue.SET[port] = \r\n\t\t\t\t\t{\r\n                        type: Entry.ssboard_nano.sensorTypes.TONE,\r\n                        data: \r\n\t\t\t\t\t\t{\r\n                            value: value,\r\n                            duration: duration / 10,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, duration + 32);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.hw.sendQueue.SET[port] = \r\n\t\t\t\t\t{\r\n                        type: Entry.ssboard_nano.sensorTypes.TONE,\r\n                        data: 0,\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        \r\n        // 3. DC 모터 속도 정하기\t\t\r\n        ssboard_nano_set_motor_speed: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n                 statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_motor_speed',\r\n            },\r\n            paramsKeyMap: {\r\n                LSPEED: 0,\r\n                RSPEED: 1,\r\n            },\r\n            class: 'ssboard_nano_LV1',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                let lspeed = script.getNumberValue('LSPEED', script);\r\n                let rspeed = script.getNumberValue('RSPEED', script);\r\n                const port = 3;\r\n                \t\t\r\n                lspeed = Math.min(100, lspeed);\r\n                lspeed = Math.max(-100, lspeed);\t\t\r\n                rspeed = Math.min(100, rspeed);\r\n                rspeed = Math.max(-100, rspeed);\t\t\r\n                \r\n                if(!(lmotor_speed == lspeed) || !(rmotor_speed == rspeed))\r\n                {\r\n                    if (!script.isStart) \r\n                    {\r\n                        if (!Entry.hw.sendQueue.SET) {\r\n                            Entry.hw.sendQueue.SET = {};\r\n                        }\r\n                        Entry.hw.sendQueue.SET[port] = \r\n                        {\r\n                            type: Entry.ssboard_nano.sensorTypes.MOTOR,\r\n                            data: [lspeed, rspeed],\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        lmotor_speed = lspeed;\r\n                        rmotor_speed = rspeed;\r\n                        script.isStart = true;  // 출력 시작 플래그 셋\r\n                        script.timeFlag = 1;    // 시간플래그 셋\r\n                        setTimeout(() => {\r\n                            script.timeFlag = 0;\r\n                        }, delay_time );\r\n                        return script;\r\n                    }\r\n                    else if (script.timeFlag == 1) \r\n                    {\r\n                        return script;\r\n                    } \r\n                    else    // 설정 시간이 지나면 출력 리셋\r\n                    {\r\n                        delete script.timeFlag;\r\n                        delete script.isStart;\r\n                        Entry.engine.isContinue = false;\r\n                        return script.callReturn();\r\n                    }\r\n                }\r\n                else\r\n                    return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\t\t\r\n\t\t// 4. DC 모터 정지하기\t\t\r\n        ssboard_nano_motor_stop: \r\n        {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_motor_stop',\r\n            },\r\n            paramsKeyMap: {\r\n                //PORT: 0,\r\n            },\r\n            class: 'ssboard_nano_LV1',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                var port = 19;//script.getNumberValue('PORT', script);\r\n\t\t\t\t//port += 2;\r\n\t\t\t\tconst lspeed = 0;\r\n                const rspeed = 0;\r\n                \r\n                if(!(lmotor_speed == 0) || !(rmotor_speed == 0)) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[port] = \r\n                    {\r\n                        type: Entry.ssboard_nano.sensorTypes.MOTOR,\r\n                        data: [lspeed, rspeed],\r\n                        time: new Date().getTime(),\r\n                    };\r\n                }\r\n\r\n                lmotor_speed = 0;\r\n                rmotor_speed = 0;\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 5.  서보 모터 각도 설정하기\t\t\r\n        ssboard_nano_set_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_digital_out_port_list',\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_servo',\r\n            },\r\n            paramsKeyMap: \r\n            {\r\n                PORT: 0,\r\n                ANGLE: 1,\r\n            },\r\n            class: 'ssboard_nano_LV1',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const port = script.getNumberValue('PORT', script);\r\n                let angle = script.getNumberValue('ANGLE', script);\r\n\t\t\t\t\r\n                angle = Math.min(180, angle);\r\n                angle = Math.max(0, angle);\r\n                angle += 1;\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = \r\n                {\r\n                    type: Entry.ssboard_nano.sensorTypes.SERVO,\r\n                    data: angle,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n\r\n        // 6. RGBLED  색상 설정 및 show\r\n        ssboard_nano_set_rgbled_onoff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'text',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'ssboard_nano_analog_rgb_color_list',\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_rgbled_onoff',\r\n            },\r\n            paramsKeyMap: {\r\n                LEDNUM: 0,\r\n                COLOR: 1,\r\n            },\r\n            class: 'ssboard_nano_LV2',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\t\r\n                const port = script.getNumberValue('LEDNUM');\r\n                const color = script.getNumberValue('COLOR', script);\r\n                const ledmode = 1;\r\n                let rLED, gLED, bLED;\r\n\r\n                switch(color) {\r\n                        case 0: \trLED = 255; gLED = 0; bLED = 0;\t\t// Red\r\n                                    break;\t\t\t\t\r\n                        case 1: \trLED = 0; gLED = 0; bLED = 255;\t\t// Blue\r\n                                    break;\t\t\t\t\t\r\n                        case 2: \trLED = 0; gLED = 255;\tbLED = 0;\t// Lime\r\n                                    break;\t\t\t\t\t\r\n                        case 3: \trLED = 255; gLED = 255; bLED = 255;\t// white\r\n                                    break;\t\t\t\t\t\r\n                        case 4: \trLED = 0; gLED = 255; bLED = 255;\t// Cyan\r\n                                    break;\r\n                        case 5: \trLED = 255; gLED = 255; bLED = 0;\t// Yellow\r\n                                    break;\t\t\t\t\t\r\n\t\t\t\t\t\tcase 6: \trLED = 255; gLED = 0;\tbLED = 255;\t// Magenta\r\n                                    break;\r\n                        case 7: \trLED = 0; gLED = 0;\tbLED = 0;\t    // 끄기\r\n                                    break;\r\n\t\t\t\t}\r\n                \r\n                \r\n                if(!(rgbled_r[port] == rLED) || !(rgbled_g[port] == gLED) || !(rgbled_b[port] == bLED)) {\r\n                    if (!script.isStart) {\r\n                        if (!Entry.hw.sendQueue.SET) {\r\n                            Entry.hw.sendQueue.SET = {};\r\n                        }\r\n                        Entry.hw.sendQueue.SET[port] = {  // port 를 \r\n                            type: Entry.ssboard_nano.sensorTypes.RGBLED,\r\n                            data: {\t\t\t\r\n                                r: rLED,\r\n                                g: gLED,\r\n                                b: bLED,\r\n                                mode: ledmode,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        rgbled_r[port] = rLED;\r\n                        rgbled_g[port] = gLED;\r\n                        rgbled_b[port] = bLED;\r\n                        script.isStart = true;  // 출력 시작 플래그 셋\r\n                        script.timeFlag = 1;    // 시간플래그 셋\r\n                        setTimeout(() => {\r\n                            script.timeFlag = 0;\r\n                        }, delay_time + 110 );\r\n                        return script;\r\n                    } else if (script.timeFlag == 1) {\r\n                        return script;\r\n                    } else {// 설정 시간이 지나면 출력 리셋\r\n                        delete script.timeFlag;\r\n                        delete script.isStart;\r\n                        Entry.engine.isContinue = false;\r\n                        return script.callReturn();\r\n                    }\r\n                } else\r\n                    return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 7. rgb led 연결 설정\r\n        ssboard_nano_rgbled_seting: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_digital_out_port_list', \r\n                        params: ['4'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['2'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['255'],\r\n                    },\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_rgbled_seting',\r\n            },\r\n            paramsKeyMap: {\r\n                RGBPIN:0,\r\n                VALUE0:1,\r\n                VALUE1:2,\r\n            },\r\n            class: 'ssboard_nano_LV2',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const port = 0;\r\n                const rLED = script.getNumberValue('RGBPIN', script);  // 핀번호\r\n                const gLED = script.getNumberValue('VALUE0', script);  // 수량\r\n                const bLED = script.getNumberValue('VALUE1', script);  // 밝기\r\n                const ledmode = 4;  // 핀번호설정\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.ssboard_nano.sensorTypes.RGBLED,\r\n                    data: {\r\n                        r: rLED,\r\n                        g: gLED,\r\n                        b: bLED,\r\n                        mode: ledmode,\r\n                    },\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\t\t\r\n\t\t// 8. RGBLED 색상설정\r\n        ssboard_nano_set_rgbled_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\t\t\t\t\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_rgbled_value',\r\n            },\r\n            paramsKeyMap: {\r\n                RGBNUM:0,\r\n                VALUE0:1,\r\n                VALUE1:2,\r\n                VALUE2:3,\r\n            },\r\n            class: 'ssboard_nano_LV2',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const port = script.getNumberValue('RGBNUM', script);\r\n                const rLED = script.getNumberValue('VALUE0', script);\r\n                const gLED = script.getNumberValue('VALUE1', script);\r\n                const bLED = script.getNumberValue('VALUE2', script);\r\n                const ledmode = 7;\r\n\r\n                if(!(rgbled_r[port] == rLED) || !(rgbled_g[port] == gLED) || !(rgbled_b[port] == bLED)) {\r\n                    if (!script.isStart) {\r\n                        if (!Entry.hw.sendQueue.SET) {\r\n                            Entry.hw.sendQueue.SET = {};\r\n                        }\r\n                        Entry.hw.sendQueue.SET[port] = {\r\n                            type: Entry.ssboard_nano.sensorTypes.RGBLED,\r\n                            data: {\r\n                                r: rLED,\r\n                                g: gLED,\r\n                                b: bLED,\r\n                                mode: ledmode,\r\n                            },\r\n                            time: new Date().getTime(),\r\n                        };\r\n                        \r\n                        script.isStart = true;  // 출력 시작 플래그 셋\r\n                        script.timeFlag = 1;    // 시간플래그 셋\r\n                        setTimeout(() => {\r\n                            script.timeFlag = 0;\r\n                        }, 100 );\r\n                        return script;\r\n                    } else if (script.timeFlag == 1) {\r\n                        return script;\r\n                    } else {// 설정 시간이 지나면 출력 리셋\r\n                        rgbled_r[port] = rLED;\r\n                        rgbled_g[port] = gLED;\r\n                        rgbled_b[port] = bLED;\r\n                        delete script.timeFlag;\r\n                        delete script.isStart;\r\n                        Entry.engine.isContinue = false;\r\n                        return script.callReturn();\r\n                    }\r\n                }\r\n                else\r\n                    return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n        \r\n\t\t// 9. RGBLED 끄기, SHOW\r\n        ssboard_nano_rgbled_all_onoff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_all_onoff_list',\r\n                    },\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_rgbled_all_onoff',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n            },\r\n            class: 'ssboard_nano_LV2',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const port = 4;//script.getNumberValue('PORT');\r\n                const ledmode = script.getNumberValue('VALUE', script);\r\n\r\n\t\t\t\tif (ledmode == 2) {\r\n                    for (var i = 0; i < 255; i++) {\r\n                        rgbled_r[i] = 0;\r\n                        rgbled_g[i] = 0;\r\n                        rgbled_b[i] = 0;\r\n                    }\r\n                }\r\n\t\t\t\tif (!script.isStart) {\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n                    Entry.hw.sendQueue.SET[port] = {\r\n                        type: Entry.ssboard_nano.sensorTypes.RGBLEDSHOW,\r\n                        data: {\r\n                            mode: ledmode,\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n                    script.isStart = true;  // 출력 시작 플래그 셋\r\n                    script.timeFlag = 1;    // 시간플래그 셋\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, delay_time + 80 );\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {// 설정 시간이 지나면 출력 리셋\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 10. 디지털  출력\r\n        ssboard_nano_digital_onoff: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_digital_out_port_list',      \r\n                    },\r\n                    {\r\n                        type: 'ssboard_nano_digital_port_onoff_list',\r\n                    },\t\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_digital_onoff',\r\n            },\r\n            paramsKeyMap: {   // 실제 블록의 로직인 func에서 key값으로 사용할 파라미터의 인덱스 번호\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'ssboard_nano_LV3',    // 블록을 묶는 그룹 이름. 이 값이 다르면 사이에 가로줄이 생깁니다\r\n            isNotFor: ['ssboard_nano'],\r\n           func: (sprite, script) => {\r\n                const port = script.getNumberValue('PORT');\r\n                const value = script.getNumberValue('VALUE');\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = {\r\n                    type: Entry.ssboard_nano.sensorTypes.DIGITAL,    /// 출력 디바이스\r\n                    data: value,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\t\t\t\t\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n\t\t\r\n\t\t// 11. 디지털입력\t\t\r\n        ssboard_nano_get_digital_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            template: Lang.template.ssboard_nano_get_digital_value,\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_digital_port_list',\r\n                    },\r\n                ],\r\n                type: 'ssboard_nano_get_digital_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'ssboard_nano_LV3',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\t\t\r\n                const port = script.getNumberValue('PORT');\r\n                const DIGITAL = Entry.hw.portData.DIGITAL;\r\n\r\n                if (!Entry.hw.sendQueue.GET) {\r\n                    Entry.hw.sendQueue.GET = {};\r\n                }\r\n                Entry.hw.sendQueue.GET[Entry.ssboard_nano.sensorTypes.DIGITAL] = {\r\n                    port: port,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return DIGITAL[port];\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\t\r\n\r\n        // 12. 아날로그 읽기\r\n        ssboard_nano_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.ssboard_nano_get_analog_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_analog_port_list',\r\n                    },\t\t\t\t\r\n                ],\r\n                type: 'ssboard_nano_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                TYPE: 1,\r\n            },\r\n            class: 'ssboard_nano_LV3',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const btn_index = script.getNumberValue('PORT');\t\t\t\t\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n\r\n                return ANALOG[btn_index];\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 13.  PWM 제어 \t\r\n        ssboard_nano_set_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_pwn_port_list',\r\n                    },\t\t\t\r\n                    {\r\n                        type: 'number',\r\n\t\t\t\t\t\tparams: ['0'],\r\n                    },\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n\t\t\t\tPORT: 0,\r\n                ANGLE: 1,\r\n            },\r\n            class: 'ssboard_nano_LV3',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const port = script.getNumberValue('PORT', script);\r\n                let angle = script.getNumberValue('ANGLE', script);\r\n                \r\n                angle = Math.min(180, angle);\r\n                angle = Math.max(0, angle);\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = \r\n                {\r\n                    type: Entry.ssboard_nano.sensorTypes.PWM,\r\n                    data: angle,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 14. 초음파센서 설정\r\n        ssboard_nano_set_ultrasonic: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_digital_out_port_list',\r\n                        params: ['13'],\r\n                    },\t\t\t\r\n                    {\r\n                        type: 'ssboard_nano_digital_out_port_list',\r\n                        params: ['5'],\r\n                    },\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_ultrasonic',\r\n            },\r\n            paramsKeyMap: {\r\n                TRIG: 0,\r\n                ECHO: 1,\r\n            },\r\n            class: 'ssboard_nano_LV4',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const trig = script.getNumberValue('TRIG', script);\r\n                const echo = script.getNumberValue('ECHO', script);\r\n\t\t\t\t//var mode = 2;\r\n                const port = trig;\r\n\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = \r\n                {\r\n                    type: Entry.ssboard_nano.sensorTypes.USONIC,\r\n                    data: echo,\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 15. 초음파 센서 값\t\t\r\n        ssboard_nano_get_usonic_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.ssboard_nano_get_usonic_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_get_usonic_value',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'ssboard_nano_LV4',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                return Entry.hw.portData.USONIC;// || 0;\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        //16. 온도센서 연결핀 설정\r\n        ssboard_nano_set_temp: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_digital_out_port_list',\r\n                        params: ['14'],\r\n                    },\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_temp',\r\n            },\r\n            paramsKeyMap: {\r\n                SENSOR: 0,\r\n            },\r\n            class: 'ssboard_nano_LV4',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const sensor = script.getNumberValue('SENSOR', script);\r\n                const port = sensor;\r\n\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = \r\n                {\r\n                    type: Entry.ssboard_nano.sensorTypes.TEMP,\r\n                    data: sensor,\r\n                    time: new Date().getTime(),\r\n                };\r\n               // return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 17. 온도센서값 읽기\r\n        ssboard_nano_get_temp_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.ssboard_nano_get_temp_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_get_temp_value',\r\n            },\r\n            paramsKeyMap: {\r\n            },\r\n            class: 'ssboard_nano_LV4',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n \r\n                return Entry.hw.portData.TEMP;// || 0;\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 18. i2c포트 센서연결 설정\r\n        ssboard_nano_set_i2c: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_i2c_sen_list',\r\n                        params: ['1'],\r\n                    },\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_i2c',\r\n            },\r\n            paramsKeyMap: {\r\n                SENSOR: 0,\r\n            },\r\n            class: 'ssboard_nano_LV4',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const sensor = script.getNumberValue('SENSOR', script);\r\n                const port = sensor;\r\n\r\n\t\t\t\t\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[port] = \r\n                {\r\n                    type: Entry.ssboard_nano.sensorTypes.I2C_SET,\r\n                    data: sensor,\r\n                    time: new Date().getTime(),\r\n                };\r\n               // return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 19. 컬러센서값\r\n        ssboard_nano_get_color_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.ssboard_nano_get_color_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['R', '1'],\r\n                        ['G', '2'],\r\n                        ['B', '3']\r\n                    ],\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                }\r\n\t\t\t\t\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['1'],\r\n                type: 'ssboard_nano_get_color_value',\r\n            },\r\n            paramsKeyMap: {\r\n                COLOR: 0,\r\n            },\r\n            class: 'ssboard_nano_LV4',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                var btn_index = script.getField('COLOR');\t\t\t\t\r\n\r\n                return Entry.hw.portData.COLOR_SEN[btn_index-1];\r\n            },\r\n           \r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 20. 자이로센서값\r\n        ssboard_nano_get_gyro_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.ssboard_nano_get_gyro_value,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['angle X', '1'],\r\n                        ['angle Y', '2'],\r\n                        ['angle Z', '3'],\r\n                        ['acc X', '4'],\r\n                        ['acc Y', '5'],\r\n                        ['acc Z', '6']\r\n                    ],\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                }\r\n\t\t\t\t\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['1'],\r\n                type: 'ssboard_nano_get_gyro_value',\r\n            },\r\n            paramsKeyMap: {\r\n                GYRO: 0,\r\n            },\r\n            class: 'ssboard_nano_LV4',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                const btn_index = script.getField('GYRO');\t\t\t\t\r\n\r\n                return Entry.hw.portData.GYRO_SEN[btn_index-1];\r\n            },\r\n           \r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 21. LCD글자출력\r\n        ssboard_nano_set_lcd_string: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'text', \r\n                        params: ['ssmaker.co.kr'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_lcd_string',\r\n            },\r\n            paramsKeyMap: {\r\n                COLUMN: 0,\r\n                LINE: 1,\r\n                STRING: 2,\r\n            },\r\n            class: 'ssboard_nano_LV5',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                // var sq = Entry.hw.sendQueue;\r\n                const line = script.getValue('LINE', script);\r\n                const column = script.getValue('COLUMN', script);\r\n                const string = script.getValue('STRING', script);\r\n                let text = [];\r\n                let buf;\r\n\r\n                if (!script.isStart) {\r\n                    if (typeof string === 'string') {\r\n                        for (var i = 0; i < string.length; i++) {\r\n                            buf = Entry.memaker.toByte(string[parseInt(i, 10)]);\r\n                            text[parseInt(i, 10)] = buf;\r\n                        }\r\n                    } else if (typeof string === 'number') {\r\n                        var num_to_string = string.toString();\r\n                        for (var i = 0; i < num_to_string.length; i++) {\r\n                            text[i] = Entry.memaker.toByte(num_to_string[i]);\r\n                        }\r\n                    } else {\r\n                        text[0] = string;\r\n                    }\r\n\r\n                    if (!Entry.hw.sendQueue.SET) {\r\n                        Entry.hw.sendQueue.SET = {};\r\n                    }\r\n\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n                    //var fps = Entry.FPS || 60;\r\n                   // var timeValue = 60 / fps * 50;\r\n\r\n                    Entry.hw.sendQueue.SET[3] = {\r\n                        type: Entry.ssboard_nano.sensorTypes.LCD_SET,\r\n                        data: {\r\n                            line: line,\r\n                            column: column,\r\n                            text0: text[0],\r\n                            text1: text[1],\r\n                            text2: text[2],\r\n                            text3: text[3],\r\n                            text4: text[4],\r\n                            text5: text[5],\r\n                            text6: text[6],\r\n                            text7: text[7],\r\n                            text8: text[8],\r\n                            text9: text[9],\r\n                            text10: text[10],\r\n                            text11: text[11],\r\n                            text12: text[12],\r\n                            text13: text[13],\r\n                            text14: text[14],\r\n                            text15: text[15],\r\n                            text15: text[16],\r\n                            text15: text[17],\r\n                            text15: text[18],\r\n                            text15: text[19],\r\n                        },\r\n                        time: new Date().getTime(),\r\n                    };\r\n\r\n                    setTimeout(() => {\r\n                        script.timeFlag = 0;\r\n                    }, delay_time);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else {\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = true;\r\n                    return script.callReturn();\r\n                }\r\n                 \r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\r\n        // 22. LCD 연결설정\r\n        ssboard_nano_set_lcd_init: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\t\t\t\t\t\t\t\t\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'ssboard_nano_lcd_add_list', \r\n                        params: ['39'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['16'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['2'],\r\n                    },\t\t\t\t\r\n                    null,\r\n                ],\r\n                type: 'ssboard_nano_set_lcd_init',\r\n            },\r\n            paramsKeyMap: {\r\n                LCD_ADD:0,\r\n                Y_LINE:1,\r\n                X_LINE:2,\r\n            },\r\n            class: 'ssboard_nano_LV5',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                //var port = 0;\r\n                const lcd_add = script.getNumberValue('LCD_ADD', script);  // 주소\r\n                const y_line = script.getNumberValue('Y_LINE', script);  // 세로 줄수\r\n                const x_line = script.getNumberValue('X_LINE', script);  // 가로 줄수\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[1] = {\r\n                    type: Entry.ssboard_nano.sensorTypes.LCD_SET,\r\n                    data: [\r\n                        lcd_add,\r\n                        y_line,\r\n                        x_line,\r\n                    ],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\t\r\n        // 23. LCD 지우기\r\n        ssboard_nano_set_lcd_clear: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\r\n            fontColor: '#fff',\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'ssboard_nano_set_lcd_clear',\r\n            },\r\n            paramsKeyMap: {\r\n\r\n            },\r\n            class: 'ssboard_nano_LV5',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                //var port = 0;\r\n\r\n                if (!Entry.hw.sendQueue.SET) {\r\n                    Entry.hw.sendQueue.SET = {};\r\n                }\r\n                Entry.hw.sendQueue.SET[4] = {\r\n                    type: Entry.ssboard_nano.sensorTypes.LCD_SET,\r\n                    data: [4, 4, 4,],\r\n                    time: new Date().getTime(),\r\n                };\r\n                return script.callReturn();\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n\t\t// 3. 소리/빛/가변저항 - 2) mapping 값\t\t\t\r\n        ssboard_nano_get_analog_mapping: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            template: Lang.template.ssboard_nano_get_analog_mapping,\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\t\t\t\t\t\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'ssboard_nano_get_analog_mapping',\r\n            },\r\n            paramsKeyMap: {\r\n                IDATA: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'ssboard_nano_ANA',\r\n            isNotFor: ['ssboard_nano'],\r\n            func: (sprite, script) => {\r\n                let result = script.getNumberValue('IDATA', script);\t\t\t\t\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                let swap;\r\n                if (value2 > value3) {\r\n                    swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                return Math.round(result);\r\n            },\r\n            syntax: { js: [], py: [] },\r\n        },\r\n    };\r\n};\r\nmodule.exports = Entry.ssboard_nano;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_suno.js",
    "content": "'use strict';\r\n\r\nEntry.SensorUno = {\r\n    id: '57.1',\r\n    name: 'SensorUno',\r\n    url: 'https://excitetouch.com/', \r\n    imageName: 'suno.png',\r\n    title: {\r\n        ko: '센서우노',\r\n        en: 'Sensor Uno',\r\n    },\r\n    \r\n    setZero: function() {\r\n        Entry.hw.sendQueue.readablePorts = [];\r\n        for (var port = 0; port < 20; port++) {\r\n            Entry.hw.sendQueue[port] = 0;\r\n            Entry.hw.sendQueue.readablePorts.push(port);\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n};\r\n\r\nEntry.SensorUno.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                suno_sensor_title: '       센서 블록',\r\n                suno_output_title: '       출력 블록',\r\n                suno_ext_get_analog_value: ' %1 센서값',\r\n                suno_ext_get_analog_value_map: '%1을  {%2~%3}의  범위에서  {%4~%5}의  범위로 변환한 값',\r\n                suno_get_trig_number: '%1',\r\n                suno_get_echo_number: '%1',\r\n                suno_get_digital_toggle: '%1',\r\n                suno_ext_get_ultrasonic_value: '초음파센서 / 📏(cm)  :   트리거(Trig)%1, 에코(Echo)%2',\r\n                suno_get_output_number: '%1',\r\n                suno_ext_toggle_output: ' %1  %2 %3',\r\n                suno_get_pwm_port_number: '%1',\r\n                suno_ext_digital_pwm: ' %1을 %2(으)로 정하기 (0~255) %3',\r\n                suno_get_servo_number:  '%1',\r\n                suno_ext_set_servo: ' %1핀에 연결된 서보모터를 %2º(으)로 정하기 (1~180) %3',\r\n                suno_ext_get_digital: ' %1버튼이 눌렸는가',\r\n                \r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                suno_sensor_title: '     Sensor Block',\r\n                suno_output_title: '     Output Block',\r\n                suno_sensor_title: 'Sensor Block',\r\n                suno_ext_get_analog_value: ' %1 Sensor value',\r\n                suno_ext_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5',\r\n                suno_get_trig_number: '%1',\r\n                suno_get_echo_number: '%1',\r\n                suno_get_digital_toggle: '%1',\r\n                suno_ext_get_ultrasonic_value: 'Reads 📏(cm) of ultrasonic sensor trig pin %1 echo pin %2',\r\n                suno_get_output_number: '%1',\r\n                suno_ext_toggle_output: ' %1 %2 %3',\r\n                suno_get_pwm_port_number: '%1',\r\n                suno_ext_digital_pwm: ' Set %1 with %2 (0~255) %3',\r\n                suno_get_servo_number:  '%1',\r\n                suno_ext_set_servo: ' Set servo pin as %1 and angle as %2º (1~180) %3',\r\n                suno_ext_get_digital: ' %1Button is pressed',\r\n                \r\n            },\r\n        },\r\n    };\r\n};\r\n\r\n\r\nEntry.SensorUno.blockMenuBlocks = [\r\n    'suno_sensor_title',\r\n    'suno_ext_get_analog_value',\r\n    'suno_ext_get_analog_value_map',\r\n    'suno_ext_get_digital',\r\n    'suno_output_title',\r\n    'suno_ext_toggle_output',\r\n    'suno_ext_digital_pwm',\r\n    'suno_ext_set_servo',\r\n  \r\n];\r\n\r\n\r\nEntry.SensorUno.getBlocks = function() {\r\n    return {\r\n        suno_sensor_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: 0,\r\n                    offsetY: 5,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#4682B4',\r\n\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.suno_sensor_title,\r\n                    color: '#4682B4',\r\n                    align: 'left',\r\n\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'suno_sensor_title',\r\n            },\r\n            class: 'SensorUnoGet',\r\n            isNotFor: ['SensorUno'],\r\n            \r\n            events: {},\r\n\r\n\r\n        },\r\n\r\n\r\n        suno_output_title: {\r\n            skeleton: 'basic_text',\r\n            skeletonOptions: {\r\n                box: {\r\n                    offsetX: 0,\r\n                    offsetY: 5,\r\n                },\r\n            },\r\n            color: EntryStatic.colorSet.common.TRANSPARENT,\r\n            fontColor: '#4682B4',\r\n\r\n            params: [\r\n                {\r\n                    type: 'Text',\r\n                    text: Lang.template.suno_output_title,\r\n                    color: '#4682B4',\r\n                    align: 'left',\r\n\r\n                },\r\n            ],\r\n            def: {\r\n                type: 'suno_output_title',\r\n            },\r\n            class: 'SensorUno',\r\n            isNotFor: ['SensorUno'],\r\n            \r\n            events: {},\r\n\r\n\r\n        },\r\n\r\n\r\n        suno_ext_analog_list: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            template: '%1',\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['초음파   📏(cm)',    'A7'],\r\n                        ['조이스틱 X축',        'A2'],\r\n                        ['조이스틱 Y축',        'A6'],\r\n                        ['마이크      ',        'A0'],\r\n                        ['빛 (A1)      🔶',    'A1'],\r\n                        ['빛 (A4)      🔷',    'A4'],\r\n                        ['라인/온도 (A3)💚',    'A3'],\r\n                        ['라인/온도 (A5)💛',    'A5'],\r\n                    ],\r\n                    value: 'A7',\r\n                    fontSize: 12,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['초음파   📏(cm)',    'A7'],\r\n                                    ['조이스틱 X축',        'A2'],\r\n                                    ['조이스틱 Y축',        'A6'],\r\n                                    ['마이크      ',        'A0'],\r\n                                    ['빛 (A1)      🔶',    'A1'],\r\n                                    ['빛 (A4)      🔷',    'A4'],\r\n                                    ['라인/온도 (A3)💚',    'A3'],\r\n                                    ['라인/온도 (A5)💛',    'A5'],\r\n                                ],\r\n                                value: 'A7',\r\n                                fontSize: 12,\r\n                                converter: Entry.block.converters.returnStringKey,\r\n                                codeMap: 'Entry.CodeMap.Arduino.suno_ext_analog_list[0]',\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'suno_ext_analog_list',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        suno_ext_get_analog_value: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'suno_ext_analog_list',\r\n                    },\r\n                ],\r\n                type: 'suno_ext_get_analog_value',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'SensorUnoGet',\r\n            isNotFor: ['SensorUno'],\r\n                        \r\n            \r\n            func(sprite, script) {\r\n                const signal = script.getValue('PORT', script);\r\n                return Entry.hw.getAnalogPortValue(signal[1]);\r\n            },\r\n            \r\n\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'SensorUno.analogRead(%1)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        suno_ext_get_analog_value_map: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'suno_ext_get_analog_value',\r\n                        params: [\r\n                            {\r\n                                type: 'suno_ext_analog_list',\r\n                            },\r\n                        ],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['1023'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['0'],\r\n                    },\r\n                    {\r\n                        type: 'number',\r\n                        params: ['100'],\r\n                    },\r\n                ],\r\n                type: 'suno_ext_get_analog_value_map',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE2: 1,\r\n                VALUE3: 2,\r\n                VALUE4: 3,\r\n                VALUE5: 4,\r\n            },\r\n            class: 'SensorUnoGet',\r\n            isNotFor: ['SensorUno'],\r\n            func(sprite, script) {\r\n                let result = script.getValue('PORT', script);\r\n                const ANALOG = Entry.hw.portData.ANALOG;\r\n                let value2 = script.getNumberValue('VALUE2', script);\r\n                let value3 = script.getNumberValue('VALUE3', script);\r\n                let value4 = script.getNumberValue('VALUE4', script);\r\n                let value5 = script.getNumberValue('VALUE5', script);\r\n                const stringValue4 = script.getValue('VALUE4', script);\r\n                const stringValue5 = script.getValue('VALUE5', script);\r\n                let isFloat = false;\r\n\r\n                if (\r\n                    (Entry.Utils.isNumber(stringValue4) && stringValue4.indexOf('.') > -1) ||\r\n                    (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\r\n                ) {\r\n                    isFloat = true;\r\n                }\r\n\r\n                if (value2 > value3) {\r\n                    var swap = value2;\r\n                    value2 = value3;\r\n                    value3 = swap;\r\n                }\r\n                if (value4 > value5) {\r\n                    var swap = value4;\r\n                    value4 = value5;\r\n                    value5 = swap;\r\n                }\r\n                result -= value2;\r\n                result = result * ((value5 - value4) / (value3 - value2));\r\n                result += value4;\r\n                result = Math.min(value5, result);\r\n                result = Math.max(value4, result);\r\n\r\n                if (isFloat) {\r\n                    result = Math.round(result * 100) / 100;\r\n                } else {\r\n                    result = Math.round(result);\r\n                }\r\n\r\n                return result;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'SensorUno.map(%1, %2, %3, %4, %5)',\r\n                        blockType: 'param',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        suno_get_trig_number: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['D2', '2'],\r\n                    \r\n                    ],\r\n                    value: '2',\r\n                    fontSize: 12,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['D2', '2'],\r\n                                \r\n                                ],\r\n                                value: '2',\r\n                                fontSize: 12,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'suno_get_trig_number',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        suno_get_echo_number: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['D4', '4'],\r\n                    \r\n                    ],\r\n                    value: '4',\r\n                    fontSize: 12,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['D4', '4'],\r\n                                \r\n                                ],\r\n                                value: '4',\r\n                                fontSize: 12,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'suno_get_echo_number',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n  \r\n        suno_get_output_number: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['DC 모터 ( ⚙ )',  '7'],\r\n                        ['빨간 LED (📏❌)', '2'],\r\n                        ['초록 LED (⚙2❌)', '3'],\r\n                        ['파란 LED (📏❌)', '4'],\r\n                        ['노란 LED', '5'],\r\n                    ],\r\n                    value: '7',\r\n                    fontSize: 12,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['DC 모터 ( ⚙ )',  '7'],\r\n                                    ['빨간 LED (📏❌)', '2'],\r\n                                    ['초록 LED (⚙2❌)', '3'],\r\n                                    ['파란 LED (📏❌)', '4'],\r\n                                    ['노란 LED', '5'],\r\n                                ], \r\n                                value: '7',\r\n                                fontSize: 12,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'suno_get_output_number',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n \r\n        suno_ext_get_digital: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['빨간 / 조이스틱',     '8'],\r\n                        ['초록 (⚙❌)', '11'],\r\n                        ['파란 (⚙❌)', '9'],\r\n                        ['노란 (⚙❌)', '10'],\r\n                    ],\r\n                    value: '8',\r\n                    fontSize: 12,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'suno_ext_get_digital',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'SensorUnoGet',\r\n            isNotFor: ['SensorUno'],\r\n            func: function(sprite, script) {\r\n                return Entry.hw.getDigitalPortValue(script.getNumberField('PORT', script));\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'SensorUno.servomotorWrite(%1, %2)',\r\n                        textParam: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['빨간 / 조이스틱',     '8'],\r\n                                    ['초록(⚙❌)', '11'],\r\n                                    ['파란(⚙❌)', '9'],\r\n                                    ['노란(⚙❌)', '10'],\r\n                                ],\r\n                                value: '8',\r\n                                fontSize: 12,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n\r\n        suno_get_digital_toggle: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n\r\n            \r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']],\r\n                    value: 'on',\r\n                    fontSize: 12,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n               \r\n            },\r\n            paramsKeyMap: {\r\n                OPERATOR: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('OPERATOR');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\r\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 12,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValueUpperCase,\r\n                                codeMap: 'Entry.CodeMap.Arduino.suno_get_digital_toggle[0]',\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'suno_get_digital_toggle',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        \r\n        suno_toggle_led: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.ARDUINO_on, 'on'],\r\n                        [Lang.Blocks.ARDUINO_off, 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'suno_get_output_number',\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'suno_toggle_led',\r\n            },\r\n            paramsKeyMap: {\r\n                VALUE: 0,\r\n                OPERATOR: 1,\r\n            },\r\n            class: 'SensorUno',\r\n            isNotFor: ['SensorUno'],\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('VALUE');\r\n                const operator = script.getField('OPERATOR');\r\n                const value = operator == 'on' ? 255 : 0;\r\n                Entry.hw.setDigitalPortValue(port, value);\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'SensorUno.pin_digital(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.ARDUINO_on, 'on'],\r\n                                    [Lang.Blocks.ARDUINO_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },        \r\n\r\n        suno_ext_toggle_output: {\r\n            parent: 'suno_toggle_led',\r\n            isNotFor: ['SensorUno'],\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'suno_get_output_number',\r\n                    },\r\n                    null,\r\n                    null,\r\n                ],\r\n                type: 'suno_ext_toggle_output',\r\n            },\r\n            class: 'SensorUno',\r\n            syntax: { js: [], py: ['SensorUno.toggle_led(%1)'] },\r\n        },\r\n\r\n\r\n        suno_get_pwm_port_number: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['⚙1(🔴)', '11'],\r\n                        ['⚙1(🔵)', '10'],\r\n                        ['⚙2(🔴)', '3'],\r\n                        ['⚙2(🔵)', '9'],\r\n                    ],\r\n                    value: '11',\r\n                    fontSize: 16,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['⚙1(🔴)', '11'],\r\n                                    ['⚙1(🔵)', '10'],\r\n                                    ['⚙2(🔴)', '3'],\r\n                                    ['⚙2(🔵)', '9'],\r\n                                ], \r\n                                value: '11',\r\n                                fontSize: 16,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'suno_get_pwm_port_number',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        \r\n        suno_ext_digital_pwm: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'suno_get_pwm_port_number',\r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['255'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'suno_ext_digital_pwm',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'SensorUno',\r\n            isNotFor: ['SensorUno'],\r\n\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 255);\r\n                Entry.hw.setDigitalPortValue(port, value);\r\n                return script.callReturn();\r\n            },\r\n\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'SensorUno.analogWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        suno_get_servo_number: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['D6', '6'],\r\n                    \r\n                    ],\r\n                    value: '6',\r\n                    fontSize: 12,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            func(sprite, script) {\r\n                return script.getStringField('PORT');\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: '%1',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    ['D6', '6'],\r\n                                \r\n                                ],\r\n                                value: '6',\r\n                                fontSize: 12,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                            },\r\n                        ],\r\n                        keyOption: 'suno_get_servo_number',\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n       \r\n\r\n        suno_ext_set_servo: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                    defaultType: 'number',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [\r\n                    {\r\n                        type: 'suno_get_servo_number',\r\n                        \r\n                    },\r\n                    {\r\n                        type: 'text',\r\n                        params: ['10'],\r\n                    },\r\n                    null,\r\n                ],\r\n                type: 'suno_ext_set_servo',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'SensorUno',\r\n            isNotFor: ['SensorUno'],\r\n\r\n            func(sprite, script) {\r\n                const port = script.getNumberValue('PORT');\r\n                let value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, 0);\r\n                value = Math.min(value, 180);\r\n                Entry.hw.setDigitalPortValue(port, value);\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'SensorUno.servomotorWrite(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.SensorUno;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_talebot.js",
    "content": "'use strict';\n\nvar TalebotState = {\n\tSTATE_READY: 'ready',\n\tSTATE_WAIT: 'wait',\n\tSTATE_DONE: 'done',\n};\n\nEntry.Talebot = {\n\tPORT_MAP: {\n\t\tseq: 0,\n\t\tcat: 0,\n\t\tact: 0,\n\t\tpcnt: 0,\n\t\tp1: 0,\n\t\tp2: 0,\n\t\tp3: 0,\n\t\tp4: 0,\n\t\tp5: 0,\n\t\tp6: 0\n\t},\n\tsetZero: function () {\n\t\tvar portMap = Entry.Talebot.PORT_MAP;\n\t\tvar sq = Entry.hw.sendQueue;\n\t\tEntry.Talebot.sequance = 1;\n\t\tEntry.Talebot.isStarted = false;\n\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\tfor (var port in portMap) {\n\t\t\tsq[port] = portMap[port];\n\t\t}\n\t\tEntry.hw.update();\n\t},\n\tid: '24.4',\n\tname: 'Talebot Pro',\n\turl: 'http://www.marusysedu.kr',\n\timageName: 'talebot.png',\n\ttitle: {\n\t\tko: '테일봇',\n\t\ten: 'Talebot',\n\t},\n\tmonitorTemplate: {\n\t\timgPath: 'hw/talebot.png',\n\t\twidth: 605,\n\t\theight: 434,\n\t},\n\tsequance: 1,\n\tisStarted: false,\n\tstate: TalebotState.STATE_DONE,\n};\nEntry.Talebot.blockMenuBlocks = [\n\t'Talebot_Move',\n\t'Talebot_Rotate',\n\t'Talebot_Rotate_round',\n\t'Talebot_Rotate_wheel',\n\t'Talebot_Speed',\n\t'Talebot_Stop',\n\t'Talebot_LED_all',\n\t'Talebot_LED_select',\n\t'Talebot_LED_eyes',\n\t'Talebot_LED_eyes_random',\n\t'Talebot_Sound_play',\n\t'Talebot_Sound_play_animal',\n\t'Talebot_Sound_play_praise',\n\t'Talebot_Sound_record',\n\t'Talebot_Sound_volume',\n\t'Talebot_Dance',\n\t'Talebot_Play_instruments',\n\t'Talebot_Play_tone',\n];\nEntry.Talebot.getBlocks = function () {\n\treturn {\n\t\tTalebot_Move: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 (으)로 %2 cm만큼 이동하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 0x00],\n\t\t\t\t\t\t['뒤', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 10],\n\t\t\t\ttype: 'Talebot_Move',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tDISTANCE: 1,\n\t\t\t},\n\t\t\tclass: 'Talebot_Movement',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tvar var2 = script.getNumberValue('DISTANCE', script);\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2 * 10;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Rotate: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 으로 %2 만큼 회전하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시계 방향', 0x00],\n\t\t\t\t\t\t['반시계 방향', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t\tdefaultType: 'angle',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 90],\n\t\t\t\ttype: 'Talebot_Rotate',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tANGLE: 1,\n\t\t\t},\n\t\t\tclass: 'Talebot_Movement',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tvar var2 = script.getNumberValue('ANGLE', script);\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Rotate_round: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 으로 %2 회전하기 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['시계 방향', 0x00],\n\t\t\t\t\t\t['반시계 방향', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['한 바퀴', 0x00],\n\t\t\t\t\t\t['반 바퀴', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 0],\n\t\t\t\ttype: 'Talebot_Rotate_round',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION: 0,\n\t\t\t\tVALUE: 1\n\t\t\t},\n\t\t\tclass: 'Talebot_Movement',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION', script);\n\t\t\t\tvar var2 = script.getNumberField('VALUE', script);\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2 == 0 ? 360 : 180;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Rotate_wheel: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '왼쪽 바퀴 %1(으)로 %2 오른쪽 바퀴 %3(으)로 %4 회전하기 %5',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 0x00],\n\t\t\t\t\t\t['뒤', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 0x00],\n\t\t\t\t\t\t['보통으로', 0x01],\n\t\t\t\t\t\t['빠르게', 0x02],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['앞', 0x00],\n\t\t\t\t\t\t['뒤', 0x01],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 0x00],\n\t\t\t\t\t\t['보통으로', 0x01],\n\t\t\t\t\t\t['빠르게', 0x02],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [0, 1, 0, 1],\n\t\t\t\ttype: 'Talebot_Rotate_wheel',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tDIRECTION_L: 0,\n\t\t\t\tSPEED_L: 1,\n\t\t\t\tDIRECTION_R: 2,\n\t\t\t\tSPEED_R: 3\n\t\t\t},\n\t\t\tclass: 'Talebot_Movement',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('DIRECTION_L', script);\n\t\t\t\tvar var2 = script.getNumberField('SPEED_L', script);\n\t\t\t\tvar var3 = script.getNumberField('DIRECTION_R', script);\n\t\t\t\tvar var4 = script.getNumberField('SPEED_R', script);\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 0;\n\t\t\t\t\tsq.pcnt = 4;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tsq.p2 = var2;\n\t\t\t\t\tsq.p3 = var3;\n\t\t\t\t\tsq.p4 = var4;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Speed: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '바퀴 속도 %1 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['느리게', 0x00],\n\t\t\t\t\t\t['보통으로', 0x01],\n\t\t\t\t\t\t['빠르게', 0x02],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Talebot_Speed',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSPEED: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Movement',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tvar var1 = script.getNumberField('SPEED', script);\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 3;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Stop: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '바퀴 정지 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Talebot_Stop',\n\t\t\t},\n\t\t\tparamsKeyMap: {},\n\t\t\tclass: 'Talebot_Movement',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\t// sq.cat = 2;\n\t\t\t\t\t// sq.act = 0;\n\t\t\t\t\t// sq.pcnt = 0;\n\t\t\t\t\tsq.cat = 1;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = 0;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 100);\n\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_LED_all: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '모든 머리 불빛 색상 %1 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [null],\n\t\t\t\ttype: 'Talebot_LED_all',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tCOLOR: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Lights',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getStringField('COLOR', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = parseInt(parseInt(var1.substr(1, 6), 16));\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_LED_select: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 머리 불빛 색상 %2 %3',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['1번', 0x01],\n\t\t\t\t\t\t['2번', 0x02],\n\t\t\t\t\t\t['3번', 0x03],\n\t\t\t\t\t\t['4번', 0x04],\n\t\t\t\t\t\t['5번', 0x05],\n\t\t\t\t\t\t['6번', 0x06],\n\t\t\t\t\t\t['7번', 0x07],\n\t\t\t\t\t\t['8번', 0x08],\n\t\t\t\t\t\t['9번', 0x09],\n\t\t\t\t\t\t['10번', 0xA],\n\t\t\t\t\t\t['11번', 0x0B],\n\t\t\t\t\t\t['12번', 0x0C],\n\t\t\t\t\t\t['무작위', 0x00],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 1 ],\n\t\t\t\ttype: 'Talebot_LED_select',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t\tCOLOR: 1,\n\t\t\t},\n\t\t\tclass: 'Talebot_Lights',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('SELECT', script);\n\t\t\t\tvar var2 = script.getStringField('COLOR', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 3;\n\t\t\t\t\tsq.p1 = 1;\n\t\t\t\t\tif(var1 == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tsq.p2 = Math.floor(Math.random() * 13);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tsq.p2 = var1 - 1;\n\t\t\t\t\t}\n\t\t\t\t\tsq.p3 = parseInt(parseInt(var2.substr(1, 6), 16));\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_LED_eyes: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '눈 불빛 색상 %1 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Color',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [],\n\t\t\t\ttype: 'Talebot_LED_eyes',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tCOLOR: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Lights',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getStringField('COLOR', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 3;\n\t\t\t\t\tsq.p1 = 2;\n\t\t\t\t\tsq.p2 = parseInt(parseInt(var1.substr(1, 6), 16));\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_LED_eyes_random: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '눈 불빛 색상 무작위 %1',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [],\n\t\t\t\ttype: 'Talebot_LED_eyes_random',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tCOLOR: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Lights',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 1;\n\t\t\t\t\tsq.pcnt = 4;\n\t\t\t\t\tsq.p1 = 2;\n\t\t\t\t\tsq.p2 = (Math.floor(Math.random() * 256) << 16) | (Math.floor(Math.random() * 256) << 8) | Math.floor(Math.random() * 256);\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Play_instruments: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '악기를 %1(으)로 정하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['피아노', 0x00],\n\t\t\t\t\t\t['오르간', 0x02],\n\t\t\t\t\t\t['기타', 0x03],\n\t\t\t\t\t\t['베이스', 0x05],\n\t\t\t\t\t\t['첼로', 0x07],\n\t\t\t\t\t\t['트롬본', 0x08],\n\t\t\t\t\t\t['클라리넷', 0x09],\n\t\t\t\t\t\t['색소폰', 0x0A],\n\t\t\t\t\t\t['플루트', 0x0B],\n\t\t\t\t\t\t['바순', 0x0D],\n\t\t\t\t\t\t['비브라폰', 0x0F],\n\t\t\t\t\t\t['오르골', 0x10],\n\t\t\t\t\t\t['마림바', 0x12],\n\t\t\t\t\t\t['합창단', 0x0E],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 0 ],\n\t\t\t\ttype: 'Talebot_Play_instruments',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tSELECT: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Play',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberField('SELECT', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 2;\n\t\t\t\t\tsq.p1 = 0;\n\t\t\t\t\tsq.p2 = var1;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tvar timer = setTimeout(() => {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}, 500);\n\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Play_tone: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '음 %1 %2 %3 박자로 연주하기 %4',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['5 옥타브', 0x05],\n\t\t\t\t\t\t['6 옥타브', 0x06],\n\t\t\t\t\t\t['7 옥타브', 0x07],\n\t\t\t\t\t\t['8 옥타브', 0x08]\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['도', 0x01],\n\t\t\t\t\t\t['도#', 0x02],\n\t\t\t\t\t\t['레', 0x03],\n\t\t\t\t\t\t['레#', 0x04],\n\t\t\t\t\t\t['미', 0x05],\n\t\t\t\t\t\t['파', 0x06],\n\t\t\t\t\t\t['파#', 0x07],\n\t\t\t\t\t\t['솔', 0x08],\n\t\t\t\t\t\t['솔#', 0x09],\n\t\t\t\t\t\t['라', 0x0A],\n\t\t\t\t\t\t['라#', 0x0B],\n\t\t\t\t\t\t['시', 0x0C],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Block',\n\t\t\t\t\taccept: 'string',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 6, 1, 1 ],\n\t\t\t\ttype: 'Talebot_Play_tone',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tOCTAV: 0,\n\t\t\t\tTONE: 1,\n\t\t\t\tLENGTH: 2,\n\t\t\t},\n\t\t\tclass: 'Talebot_Play',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberValue('OCTAV', script);\n\t\t\t\tvar var2 = script.getNumberValue('TONE', script);\n\t\t\t\tvar var3 = script.getNumberValue('LENGTH', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 2;\n\t\t\t\t\tsq.pcnt = 4;\n\t\t\t\t\tsq.p1 = 1;\n\t\t\t\t\tsq.p2 = var1;\n\t\t\t\t\tsq.p3 = var2;\n\t\t\t\t\tsq.p4 = var3;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\t\t\n\t\tTalebot_Dance: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 춤추기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['까불까불', 0x01],\n\t\t\t\t\t\t['빙글빙글', 0x02],\n\t\t\t\t\t\t['살랑살랑', 0x03],\n\t\t\t\t\t\t['뱅그르르', 0x04],\n\t\t\t\t\t\t['실룩실룩', 0x05],\n\t\t\t\t\t\t['쿵짝쿵짝', 0x06],\n\t\t\t\t\t\t['무작위', 0x00],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 1 ],\n\t\t\t\ttype: 'Talebot_Dance',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Dance',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberValue('VALUE', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 3;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tif(var1 == 0) {\n\t\t\t\t\t\tsq.p1 = Math.floor(Math.random() * 7);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\t}\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Sound_record: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '녹음 %1 말하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['1', 0x01],\n\t\t\t\t\t\t['2', 0x02],\n\t\t\t\t\t\t['3', 0x03],\n\t\t\t\t\t\t['4', 0x04],\n\t\t\t\t\t\t['5', 0x05],\n\t\t\t\t\t\t['6', 0x06],\n\t\t\t\t\t\t['7', 0x07],\n\t\t\t\t\t\t['8', 0x08],\n\t\t\t\t\t\t['무작위', 0x00],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [1],\n\t\t\t\ttype: 'Talebot_Sound_record',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Sound',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tvar var1 = script.getNumberField('VALUE', script);\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 4;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tif (var1 == 0) {\n\t\t\t\t\t\tsq.p1 = Math.floor(Math.random() * 9);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\t}\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Sound_volume: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '소리 크기 %1 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['작게', 0x00],\n\t\t\t\t\t\t['보통으로', 0x01],\n\t\t\t\t\t\t['크게', 0x02],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 1 ],\n\t\t\t\ttype: 'Talebot_Sound_volume',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Sound',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberValue('VALUE', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 5;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Sound_play: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '%1 소리 내기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['자동차', 0x00],\n\t\t\t\t\t\t['경찰차', 0x01],\n\t\t\t\t\t\t['소방차', 0x02],\n\t\t\t\t\t\t['박수', 0x03],\n\t\t\t\t\t\t['뾰로롱', 0x04],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 0x00 ],\n\t\t\t\ttype: 'Talebot_Sound_play',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Sound',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberValue('VALUE', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 6;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Sound_play_animal: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '동물 %1 말하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['돼지', 0x10],\n\t\t\t\t\t\t['양', 0x11],\n\t\t\t\t\t\t['소', 0x12],\n\t\t\t\t\t\t['말', 0x13],\n\t\t\t\t\t\t['오리', 0x14],\n\t\t\t\t\t\t['암탉', 0x15],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 0x10 ],\n\t\t\t\ttype: 'Talebot_Sound_play_animal',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Sound',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberValue('VALUE', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 6;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t\tTalebot_Sound_play_praise: {\n\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\n\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tskeleton: 'basic',\n\t\t\tfontColor: '#fff',\n\t\t\tstatements: [],\n\t\t\ttemplate: '칭찬 %1 말하기 %2',\n\t\t\tparams: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'Dropdown',\n\t\t\t\t\toptions: [\n\t\t\t\t\t\t['좋아!', 0x20],\n\t\t\t\t\t\t['맞아!', 0x21],\n\t\t\t\t\t\t['훌륭해!', 0x22],\n\t\t\t\t\t\t['우아!', 0x23],\n\t\t\t\t\t\t['만세!', 0x24],\n\t\t\t\t\t],\n\t\t\t\t\tfontSize: 11,\n\t\t\t\t\tbgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\t\t\tarrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'Indicator',\n\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\n\t\t\t\t\tsize: 12,\n\t\t\t\t},\n\t\t\t],\n\t\t\tevents: {},\n\t\t\tdef: {\n\t\t\t\tparams: [ 0x20 ],\n\t\t\t\ttype: 'Talebot_Sound_play_praise',\n\t\t\t},\n\t\t\tparamsKeyMap: {\n\t\t\t\tVALUE: 0,\n\t\t\t},\n\t\t\tclass: 'Talebot_Sound',\n\t\t\tisNotFor: ['Talebot Pro'],\n\t\t\tfunc: function (sprite, script) {\n\t\t\t\tvar var1 = script.getNumberValue('VALUE', script);\n\t\t\t\tvar sq = Entry.hw.sendQueue;\n\t\t\t\tvar pd = Entry.hw.portData;\n\t\t\t\tif (!Entry.Talebot.isStarted) {\n\t\t\t\t\tsq.seq = Entry.Talebot.sequance++;\n\t\t\t\t\tsq.cat = 2;\n\t\t\t\t\tsq.act = 6;\n\t\t\t\t\tsq.pcnt = 1;\n\t\t\t\t\tsq.p1 = var1;\n\t\t\t\t\tEntry.Talebot.isStarted = true;\n\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_READY;\n\t\t\t\t\treturn script;\n\t\t\t\t} else {\n\t\t\t\t\tswitch (Entry.Talebot.state) {\n\t\t\t\t\t\tcase TalebotState.STATE_READY:\n\t\t\t\t\t\t\tif (!pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_WAIT;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_WAIT:\n\t\t\t\t\t\t\tif (pd.done) {\n\t\t\t\t\t\t\t\tEntry.Talebot.state = TalebotState.STATE_DONE;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn script;\n\t\t\t\t\t\tcase TalebotState.STATE_DONE:\n\t\t\t\t\t\t\tEntry.Talebot.isStarted = false;\n\t\t\t\t\t\t\treturn script.callReturn();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn script;\n\t\t\t},\n\t\t},\n\t};\n};\n\nmodule.exports = Entry.Talebot;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_telliot_Base.js",
    "content": "'use strict';\r\n\r\nconst PreAction = {\r\n\tSTOP: 0x00,\r\n\tMOVE_FORWARD: 0x01,\r\n\tMOVE_BACKWARD: 0x02,\r\n\tTURN_LEFT: 0x03,\r\n\tTURN_RIGHT: 0x04,\r\n\r\n\tACTION_UNKNOWN: 0xFF,\r\n}\r\n\r\nclass TelliotBase {\r\n\tconstructor() {\r\n\t\tthis.resetState();\r\n\t}\r\n\r\n\tsetZero() {\r\n\t\tthis.resetState();\r\n\t\tEntry.hw.update();\r\n\t}\r\n\r\n\tafterReceive = function (data) {\r\n\t\tconst keys = data.state ? Object.keys(data.state) : [];\r\n\t\tkeys.forEach(key => {\r\n\t\t\tthis.state[key] = data.state[key];\r\n\t\t\t// console.log(typeof (this.state.sensors));\r\n\t\t});\r\n\r\n\t\t// console.log('[afterReceive] : ' + keys);\r\n\t\t// console.log('[afterReceive] : ', data.state);\r\n\t}\r\n\r\n\tafterSend = function () {\r\n\t\tthis.resetState();\r\n\t\tEntry.hw.sendQueue = {};\r\n\t}\r\n\r\n\tresetState() {\r\n\t\tthis.state = {\r\n\t\t\tsensors: 0,\r\n\t\t\trfid: []\r\n\t\t};\r\n\t}\r\n\r\n\tasync delay(ms) {\r\n\t\treturn new Promise(resolve => setTimeout(resolve, ms));\r\n\t}\r\n\r\n\tasync request(func, subkey, value, updateNow = false) {\r\n\t\tconst test = []\r\n\t\tif (!Entry.hw.sendQueue[func])\r\n\t\t\tEntry.hw.sendQueue[func] = {};\r\n\r\n\t\tif (subkey) {\r\n\t\t\tEntry.hw.sendQueue[func][subkey.toString()] = value;\r\n\t\t} else {\r\n\t\t\tEntry.hw.sendQueue[func] = value;\r\n\t\t}\r\n\r\n\t\tconsole.log('[' + func + '] : ' + value);\r\n\r\n\t\tconsole.log(test)\r\n\r\n\t\tif (updateNow)\r\n\t\t\tEntry.hw.update();\r\n\r\n\t\t// 딜레이 추가\r\n\r\n\t}\r\n\r\n\tasync req_add_chatbot(sprite, script) {\r\n\t\tconst ask = script.getStringValue('AI_CHATBOT_ASK');\r\n\t\tconst resp = script.getStringValue('AI_CHATBOT_RESP');\r\n\r\n\t\tconsole.log('[req_chatbot] : ' + ask + ' => ' + resp);\r\n\t\tawait this.request('add_chatbot', null, { ask, resp }, true);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\tasync req_voice_trigger(sprite, script) {\r\n\t\tawait this.request('req_voice_trigger_click', null, 1);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\tasync req_speech_to_text(sprite, script) {\r\n\t\tawait this.request('req_stt', null, 1);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\tasync req_text_to_speech(sprite, script) {\r\n\t\tconst stot = script.getStringValue('TEXT_TO_SPEECH');\r\n\r\n\t\tconsole.log('[req_tts] : ' + stot);\r\n\t\tawait this.request('req_tts', null, stot, true);\r\n\t\tawait this.delay(3000);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\tasync req_add_prompt(sprite, script) {\r\n\t\tconst ai_prompt = script.getStringValue('AI_PROMPT');\r\n\r\n\t\tconsole.log('[add_prompt] : ' + ai_prompt);\r\n\t\tawait this.request('add_prompt', null, ai_prompt, true);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\tasync req_predefined_action(sprite, script) {\r\n\t\tconst action_stridx = script.getStringValue('PREDEFINED_MOTION_ID');\r\n\t\tconst action_value = script.getNumberValue('PREDEFINED_MOTION_VALUE');\r\n\t\tlet action_id = PreAction.ACTION_UNKNOWN;\r\n\r\n\t\tswitch (action_stridx) {\r\n\t\t\tcase 'forward':\r\n\t\t\t\taction_id = PreAction.MOVE_FORWARD;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'backward':\r\n\t\t\t\taction_id = PreAction.MOVE_BACKWARD;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'left':\r\n\t\t\t\taction_id = PreAction.TURN_LEFT;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'right':\r\n\t\t\t\taction_id = PreAction.TURN_RIGHT;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tawait this.request('pre_action', null, { action_id, action_value }, true);\r\n\t\tawait this.delay(1250);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\tasync req_action_stop(sprite, script) {\r\n\t\tconst action_id = PreAction.STOP;\r\n\t\tconst action_value = 0;\r\n\r\n\t\tawait this.request('pre_action', null, { action_id, action_value }, true);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\tasync req_motor_control(sprite, script) {\r\n\t\tconst port = script.getStringValue('MOTOR_PORT_ID');\r\n\t\tconst motor_value = script.getNumberValue('MOTOR_PORT_VALUE');\r\n\t\tconst dir = script.getStringValue('MOTOR_DIRECTION');\r\n\t\tvar motor_id, motor_dir;\r\n\r\n\t\tswitch (port) {\r\n\t\t\tcase 'left wheel': motor_id = 0; break;\r\n\t\t\tcase 'right wheel': motor_id = 1; break;\r\n\t\t\tcase 'left foot': motor_id = 0; break;\r\n\t\t\tcase 'right foot': motor_id = 1; break;\r\n\t\t\tcase 'left Leg': motor_id = 2; break;\r\n\t\t\tcase 'right Leg': motor_id = 3; break;\r\n\t\t\tcase 'left arm': motor_id = 4; break;\r\n\t\t\tcase 'right arm': motor_id = 5; break;\r\n\t\t\tcase 'head': motor_id = 6; break;\r\n\t\t}\r\n\r\n\t\tswitch (dir) {\r\n\t\t\tcase 'clockwise':\r\n\t\t\t\tmotor_dir = 0;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'counterclockwise':\r\n\t\t\t\tmotor_dir = 1;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tawait this.request('motor_ctrl', null, { motor_id, motor_dir, motor_value }, true);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\tasync req_line_trace(sprite, script) {\r\n\t\tconst dir = script.getStringField('LINE_TRACE_DIR');\r\n\t\tvar line_color = 0;\r\n\t\tvar line_dir;\r\n\r\n\t\tswitch (dir) {\r\n\t\t\tcase 'forward':\r\n\t\t\t\tline_dir = 0;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 'backward':\r\n\t\t\t\tline_dir = 1;\r\n\t\t\t\tbreak;\r\n\t\t}\r\n\r\n\t\tawait this.request('line_trace', null, { line_color, line_dir }, true);\r\n\t\treturn script.callReturn();\r\n\t}\r\n\r\n\treq_detect_object(sprite, script) {\r\n\t\tconst obj = script.getStringField('OBJECT_DETECT');\r\n\t\tvar sensor_id = 0;\r\n\t\tvar detect_object = 0;\r\n\r\n\t\tif (obj === 'detected')\r\n\t\t\tdetect_object = 1;\r\n\t\telse\r\n\t\t\tdetect_object = 0;\r\n\t\tconsole.log(this.state.sensors)\r\n\t\tconsole.log('[req_detect_object] : ' + this.state.sensors);\r\n\t\tif (detect_object === 1 && this.state.sensors !== 0 && typeof (this.state.sensors) === 'number') {\r\n\t\t\tconsole.log('1111111111111111')\r\n\t\t\treturn true;\r\n\t\t} else if (detect_object === 0 && this.state.sensors.length === 0) {\r\n\t\t\tconsole.log('22222222222222222')\r\n\t\t\treturn true;\r\n\t\t} else {\r\n\t\t\tconsole.log('123981237980123091238079231809')\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n\r\n\treq_rfid_tag_detect(sprite, script) {\r\n\t\tconst tag = script.getStringField('TAG_DETECT');\r\n\t\tvar tag_id = 0;\r\n\r\n\t\tswitch (tag) {\r\n\t\t\tcase 'circle': tag_id = 0; break;\r\n\t\t\tcase 'rectangle': tag_id = 1; break;\r\n\t\t\tcase 'triangle': tag_id = 2; break;\r\n\t\t\tcase 'star': tag_id = 3; break;\r\n\t\t\tcase 'diamond': tag_id = 4; break;\r\n\t\t\tcase 'heart': tag_id = 5; break;\r\n\t\t}\r\n\r\n\t\tconsole.log('[req_rfid_tag_detect] : ' + tag_id + '   ' + this.state.rfid);\r\n\t\tif (this.state.rfid[tag_id]) {\r\n\t\t\treturn true;\r\n\t\t} else {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nmodule.exports = { TelliotBase, PreAction };\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_telliot_lite.js",
    "content": "'use strict';\r\nconst {TelliotBase, PreAction} = require('./block_telliot_Base.js');\r\n\r\nclass TelliotLite extends TelliotBase {\r\n\tconstructor() {\r\n\t\tsuper();\r\n\r\n\t\tthis.id =  '60.1';\r\n\t\tthis.name = 'GoldenKidsAICar';\r\n\t\tthis.url = 'https://www.iotedcorp.com';\r\n\t\tthis.imageName = 'telliot_lite.png';\r\n\t\tthis.title = {\r\n\t\t\tko: '금쪽이 카',\r\n\t\t\ten: 'GoldenKidsAICar',\r\n\t\t};\r\n\t\tthis.blockMenuBlocks = this.getBlockMenuBlocks();\r\n\t}\r\n\r\n\tgetBlockMenuBlocks() {\r\n\t\treturn [\r\n\t\t\t// Telliot Car flow\r\n\t\t\t'telliot_car_move',\r\n\t\t\t'telliot_car_turn',\r\n\t\t\t'telliot_car_stop',\r\n\t\t\t'telliot_car_wheel_move',\r\n\t\t\t'telliot_car_line_move',\r\n\r\n\t\t\t// Telliot Car sensors\r\n\t\t\t'telliot_car_sensor_is_detected',\r\n\t\t\t'telliot_car_sensor_RFID_detect',\r\n//\t\t\t'telliot_car_camera_detect',\r\n\r\n\t\t\t// AI\r\n//\t\t\t'telliot_car_chatbot',\r\n//\t\t\t'telliot_car_voice_command',\r\n\t\t\t'telliot_car_voice_trigger',\r\n//\t\t\t'telliot_car_STT',\r\n\t\t\t'telliot_car_TTS',\r\n\r\n\t\t\t// AI prompt\r\n//\t\t\t'telliot_car_add_prompt',\r\n//\t\t\t'telliot_car_set_prompt'\r\n\t\t];\r\n\t}\r\n\r\n\tsetLanguage() {\r\n\t\treturn {\r\n\t\t\tko: {\r\n\t\t\t\ttemplate: {\r\n\t\t\t\t\t// Telliot Car flow\r\n\t\t\t\t\ttelliot_car_move: '%1(으)로 %2초간 이동하기 %3',\r\n\t\t\t\t\ttelliot_car_turn: '%1으로 회전하기 %2',\r\n\t\t\t\t\ttelliot_car_stop: '현재 위치에서 정지하기 %1',\r\n\t\t\t\t\t//telliot_car_wheel_move: '%1 모터를 %2 만큼 %3으로 회전하기 %4',\r\n\t\t\t\t\ttelliot_car_line_move : '라인을 따라 앞으로 이동 하기 %2',\r\n\r\n\t\t\t\t\t// Telliot Car sensors\r\n\t\t\t\t\ttelliot_car_sensor_is_detected : '거리 센서가 물체를 %1 했을때 %2',\r\n\t\t\t\t\ttelliot_car_sensor_RFID_detect : '태그가 %1모양이 감지되었을때 %2',\r\n//\t\t\t\t\ttelliot_car_camera_detect : '카메라에 %1 되었을때 %2',\r\n\r\n\t\t\t\t\t// AI\r\n//\t\t\t\t\ttelliot_car_chatbot : '%1 라고 말하면 %2라고 대답하기 %3',\r\n//\t\t\t\t\ttelliot_car_voice_command : '%1라고 말하면 %2',\r\n\t\t\t\t\ttelliot_car_voice_trigger: '금쪽이 스피커에 음성 명령어 전달하기 %1',\r\n//\t\t\t\t\ttelliot_car_STT: '텔리엇에 전달한 음성을 문자로 전달 받기 %1',\r\n\t\t\t\t\ttelliot_car_TTS: '%1을 금쪽이 스피커에서 듣기 %2',\r\n\r\n\t\t\t\t\t// AI prompt\r\n\t\t\t\t\ttelliot_car_add_prompt : '%1 프롬프트 추가하기 %2',\r\n//\t\t\t\t\ttelliot_car_set_prompt : '%1 프롬프트로 설정하기'\r\n\r\n\t\t\t\t},\r\n\t\t\t},\r\n\t\t\ten: {\r\n\t\t\t\ttemplate: {\r\n\t\t\t\t\t// Telliot Car flow\r\n\t\t\t\t\ttelliot_car_move: 'Move %1 during %2sec %3',\r\n\t\t\t\t\ttelliot_car_turn: 'Rotate %2 degree to the %1 %3',\r\n\t\t\t\t\ttelliot_car_stop: 'Stop at current position %1',\r\n\t\t\t\t\t//telliot_car_wheel_move: '%1 모터를 %2 만큼 %3 회전하기 %4',\r\n\t\t\t\t\ttelliot_car_line_move : '라인을 따라 앞으로 이동하기 %2',\r\n\r\n\t\t\t\t\t// Telliot Car sensors\r\n\t\t\t\t\ttelliot_car_sensor_is_detected : ' 거리 센서가 %1 했을때 %2',\r\n\t\t\t\t\ttelliot_car_sensor_RFID_detect : '태그가 %1모양이 감지 되었을때 %2',\r\n//\t\t\t\t\ttelliot_car_camera_detect : '카메라에 %1 되었을때 %2',\r\n\r\n\t\t\t\t\t// AI\r\n//\t\t\t\t\ttelliot_car_chatbot : '%1 라고 말하면 %2라고 대답하기 %3',\r\n//\t\t\t\t\ttelliot_car_voice_command : '%1라고 말하면 %2',\r\n\t\t\t\t\ttelliot_car_voice_trigger: 'Send voice command to Speaker %1',\r\n//\t\t\t\t\ttelliot_car_STT: 'Receive speech to text from telliot %1',\r\n\t\t\t\t\ttelliot_car_TTS: 'Speech from %1 %2',\r\n\r\n\t\t\t\t\t// AI prompt\r\n//\t\t\t\t\ttelliot_car_add_prompt : 'Add %1 prompt %2',\r\n//\t\t\t\t\ttelliot_car_set_prompt : 'Set %1 prompt'\r\n\t\t\t\t},\r\n\t\t\t},\r\n\t\t};\r\n\t}\r\n\r\n\tgetBlocks() {\r\n\t\treturn {\r\n\t\t\t// Telliot Car flow\r\n\t\t\ttelliot_car_move : {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'Dropdown',\r\n                        options: [\r\n                            ['앞', 'forward'],\r\n                            ['뒤', 'backward'],\r\n                        ],\r\n                        value: 'forward',\r\n                        fontSize: 11,\r\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'Dropdown',\r\n                        options: [\r\n                            ['1', '1'],\r\n                            ['2', '2'],\r\n                            ['3', '3'],\r\n                            ['4', '4'],\r\n                            ['5', '5'],\r\n                        ],\r\n                        value: '1',\r\n                        fontSize: 11,\r\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'Indicator',\r\n\t\t\t\t\t\timg: 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize: 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [null, null, null],\r\n\t\t\t\t\ttype: 'telliot_car_move',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n                    PREDEFINED_MOTION_ID: 0,\r\n\t\t\t\t\tPREDEFINED_MOTION_VALUE: 1,\r\n                },\r\n\t\t\t\tclass: 'telliot_car_flow',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_predefined_action(sprite, script)\r\n\t\t\t},\r\n\r\n\t\t\ttelliot_car_turn : {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'Dropdown',\r\n                        options: [\r\n                            ['왼쪽', 'left'],\r\n                            ['오른쪽', 'right'],\r\n                        ],\r\n                        value: 'left',\r\n                        fontSize: 11,\r\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t\t\t},\r\n\t\t\t\t\t// {\r\n\t\t\t\t\t// \ttype: 'Dropdown',\r\n                    //     options: [\r\n                    //         ['15', '15'],\r\n                    //         ['30', '30'],\r\n                    //         ['45', '45'],\r\n                    //         ['60', '60'],\r\n                    //         ['75', '75'],\r\n                    //         ['90', '90'],\r\n                    //         ['105', '105'],\r\n                    //         ['120', '120'],\r\n                    //         ['135', '135'],\r\n                    //         ['150', '150'],\r\n                    //         ['165', '165'],\r\n                    //         ['180', '180'],\r\n                    //     ],\r\n                    //     value: '45',\r\n                    //     fontSize: 11,\r\n                    //     bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    //     arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t\t\t// },\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [null, null, null],\r\n\t\t\t\t\ttype: 'telliot_car_turn',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n                    PREDEFINED_MOTION_ID: 0,\r\n\t\t\t\t\tPREDEFINED_MOTION_VALUE: 1,\r\n                },\r\n\t\t\t\tclass: 'telliot_car_flow',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_predefined_action(sprite, script)\r\n\t\t\t},\r\n\r\n\t\t\ttelliot_car_stop: {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams: [null],\r\n\t\t\t\t\ttype: 'telliot_car_stop',\r\n\t\t\t\t},\r\n\t\t\t\tclass: 'telliot_car_flow',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_action_stop(sprite, script)\r\n\t\t\t},\r\n\r\n\t\t\t// telliot_car_wheel_move : {\r\n\t\t\t// \tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t// \touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t// \tskeleton: 'basic',\r\n\t\t\t// \tstatements: [],\r\n\t\t\t// \tparams: [\r\n\t\t\t// \t\t{\r\n\t\t\t// \t\t\ttype: 'Dropdown',\r\n            //             options: [\r\n            //                 ['왼쪽 바퀴', 'left wheel'],\r\n            //                 ['오른쪽 바퀴', 'right wheel'],\r\n            //             ],\r\n            //             value: 'left wheel',\r\n            //             fontSize: 11,\r\n            //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t// \t\t},\r\n\t\t\t// \t\t{\r\n            //             type: 'Block',\r\n            //             accept: 'string',\r\n\t\t\t// \t\t\tdefaultType: 'number',\r\n            //         },\r\n\t\t\t// \t\t{\r\n\t\t\t// \t\t\ttype: 'Dropdown',\r\n            //             options: [\r\n            //                 ['시계방향', 'clockwise'],\r\n            //                 ['반시계방향', 'counterclockwise'],\r\n            //             ],\r\n            //             value: 'clockwise',\r\n            //             fontSize: 11,\r\n            //             bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            //             arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t// \t\t},\r\n\t\t\t// \t\t{\r\n\t\t\t// \t\t\ttype : 'Indicator',\r\n\t\t\t// \t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t// \t\t\tsize : 11,\r\n\t\t\t// \t\t},\r\n\t\t\t// \t],\r\n\t\t\t// \tevents: {},\r\n\t\t\t// \tdef: {\r\n\t\t\t// \t\tparams : [\r\n\t\t\t// \t\t\tnull,\r\n\t\t\t// \t\t\t{\r\n\t\t\t// \t\t\t\ttype: 'number',\r\n\t\t\t// \t\t\t\tparams: ['100'],\r\n\t\t\t// \t\t\t},\r\n\t\t\t// \t\t\tnull,\r\n\t\t\t// \t\t\tnull,\r\n\t\t\t// \t\t],\r\n\t\t\t// \t\ttype: 'telliot_car_wheel_move',\r\n\t\t\t// \t},\r\n\t\t\t// \tparamsKeyMap: {\r\n            //         MOTOR_PORT_ID: 0,\r\n\t\t\t// \t\tMOTOR_PORT_VALUE: 1,\r\n\t\t\t// \t\tMOTOR_DIRECTION: 2,\r\n            //     },\r\n\t\t\t// \tclass: 'telliot_car_flow',\r\n\t\t\t// \t//isNotFor : ['TelliotLite'],\r\n\t\t\t// \tfunc: (sprite, script) => this.req_motor_control(sprite, script)\r\n\t\t\t// },\r\n\r\n\t\t\ttelliot_car_line_move : {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'Dropdown',\r\n                        options: [\r\n                            ['앞으로', 'forward'],\r\n                           // ['뒤로', 'backward'],\r\n                        ],\r\n                        value: 'forward',\r\n                        fontSize: 11,\r\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [null, null],\r\n\t\t\t\t\ttype: 'telliot_car_line_move',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n                    LINE_TRACE_DIR: 0,\r\n                },\r\n\t\t\t\tclass: 'telliot_car_flow',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_line_trace(sprite, script)\r\n\t\t\t},\r\n\r\n\t\t\t// Telliot Car sensors\r\n\t\t\ttelliot_car_sensor_is_detected : {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic_boolean_field',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'Dropdown',\r\n                        options: [\r\n                            ['감지', 'detected'],\r\n                            ['미감지', 'not detected'],\r\n                        ],\r\n                        value: 'detected',\r\n                        fontSize: 11,\r\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [null, null],\r\n\t\t\t\t\ttype: 'telliot_car_sensor_is_detected',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n                    OBJECT_DETECT: 0,\r\n                },\r\n\t\t\t\tclass: 'telliot_car_sensors',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_detect_object(sprite, script),\r\n\t\t\t},\r\n\r\n\t\t\ttelliot_car_sensor_RFID_detect : {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic_boolean_field',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype: 'Dropdown',\r\n                        options: [\r\n                            ['동그라미', 'circle'],\r\n                            ['네모', 'rectangle'],\r\n\t\t\t\t\t\t\t['세모', 'triangle'],\r\n\t\t\t\t\t\t\t['별', 'star'],\r\n\t\t\t\t\t\t\t['다이아몬드', 'diamond'],\r\n\t\t\t\t\t\t\t['하트', 'heart'],\r\n                        ],\r\n                        value: 'circle',\r\n                        fontSize: 11,\r\n                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n\t\t\t\t\t},\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [null, null],\r\n\t\t\t\t\ttype: 'telliot_car_sensor_RFID_detect',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n                    TAG_DETECT: 0,\r\n                },\r\n\t\t\t\tclass: 'telliot_car_sensors',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_rfid_tag_detect(sprite, script),\r\n\t\t\t},\r\n\r\n//\t\t\ttelliot_car_camera_detect : {\r\n//\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n//\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n//\t\t\t\tskeleton: 'basic',\r\n//\t\t\t\tstatements: [],\r\n//\t\t\t\tparams: [\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\ttype : 'Indicator',\r\n//\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n//\t\t\t\t\t\tsize : 12,\r\n//\t\t\t\t\t},\r\n//\t\t\t\t],\r\n//\t\t\t\tevents: {},\r\n//\t\t\t\tdef: {\r\n//\t\t\t\t\tparams : [null],\r\n//\t\t\t\t\ttype: 'telliot_lite_STT',\r\n//\t\t\t\t},\r\n//\t\t\t\tclass: 'telliot_ai',\r\n//\t\t\t\t//isNotFor : ['TelliotLite'],\r\n//\t\t\t\tfunc(sprite, script) {\r\n//\t\t\t\t\treturn script.callReturn();\r\n//\t\t\t\t},\r\n//\t\t\t},\r\n//\r\n\t\t\t// AI\r\n\t\t\ttelliot_car_chatbot : {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic_string_field',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n                      type: 'Block',\r\n                      accept: 'string',\r\n\t\t\t\t\t\tdefaultType: 'string',\r\n                  },\r\n\t\t\t\t\t{\r\n                      type: 'Block',\r\n                      accept: 'string',\r\n\t\t\t\t\t\tdefaultType: 'string',\r\n                  },\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttype: 'text',\r\n\t\t\t\t\t\t\tparams: ['<질문>'],\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttype: 'text',\r\n\t\t\t\t\t\t\tparams: ['<답변>'],\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tnull,\r\n\t\t\t\t\t],\r\n\t\t\t\t\ttype: 'telliot_car_chatbot',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n\t\t\t\t\tAI_CHATBOT_ASK: 0,\r\n\t\t\t\t\tAI_CHATBOT_RESP: 1,\r\n              },\r\n\t\t\t\tclass: 'telliot_ai',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_add_chatbot(sprite, script)\r\n\t\t\t},\r\n\r\n\t\t\ttelliot_car_voice_command : {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n                        type: 'Block',\r\n                        accept: 'string',\r\n\t\t\t\t\t\tdefaultType: 'string',\r\n                    },\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttype: 'text',\r\n\t\t\t\t\t\t\tparams: ['<command>'],\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tnull\r\n\t\t\t\t\t],\r\n\t\t\t\t\ttype: 'telliot_car_voice_command',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n                    CAR_CHATBOT_CMD: 0,\r\n                },\r\n\t\t\t\tclass: 'telliot_ai',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc(sprite, script) {\r\n\t\t\t\t\treturn script.callReturn();\r\n\t\t\t\t},\r\n\t\t\t},\r\n\r\n\t\t\t// Voice Capture\r\n\t\t\ttelliot_car_voice_trigger: {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams: [null],\r\n\t\t\t\t\ttype: 'telliot_car_voice_trigger',\r\n\t\t\t\t},\r\n\t\t\t\tclass: 'telliot_ai',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_voice_trigger(sprite, script)\r\n\t\t\t},\r\n\r\n\t\t\t// Speech to Text\r\n\t\t\ttelliot_car_STT: {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [null],\r\n\t\t\t\t\ttype: 'telliot_car_STT',\r\n\t\t\t\t},\r\n\t\t\t\tclass: 'telliot_ai',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_speech_to_text(sprite, script)\r\n\t\t\t},\r\n\r\n\t\t\t// Text To Speech\r\n\t\t\ttelliot_car_TTS: {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t    {\r\n                        type: 'Block',\r\n                        accept: 'string',\r\n                    },\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams: [\r\n\t\t\t\t\t\t{\r\n\t\t\t\t\t\t\ttype: 'text',\r\n\t\t\t\t\t\t\tparams: ['<Text>'],\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tnull\r\n\t\t\t\t\t],\r\n\t\t\t\t\ttype: 'telliot_car_TTS',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n                    TEXT_TO_SPEECH: 0,\r\n                },\r\n\t\t\t\tclass: 'telliot_ai',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_text_to_speech(sprite, script)\r\n\t\t\t},\r\n\r\n\t\t\t// AI prompt\r\n\t\t\ttelliot_car_add_prompt : {\r\n\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n\t\t\t\tskeleton: 'basic',\r\n\t\t\t\tstatements: [],\r\n\t\t\t\tparams: [\r\n\t\t\t\t\t{\r\n                        type: 'Block',\r\n                        accept: 'string',\r\n                    },\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\ttype : 'Indicator',\r\n\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n\t\t\t\t\t\tsize : 11,\r\n\t\t\t\t\t},\r\n\t\t\t\t],\r\n\t\t\t\tevents: {},\r\n\t\t\t\tdef: {\r\n\t\t\t\t\tparams : [\r\n\t\t\t\t\t   {\r\n\t\t\t\t\t\t\ttype: 'text',\r\n\t\t\t\t\t\t\tparams: ['<Prompt>'],\r\n\t\t\t\t\t\t},\r\n\t\t\t\t\t\tnull\r\n\t\t\t\t\t],\r\n\t\t\t\t\ttype: 'telliot_car_add_prompt',\r\n\t\t\t\t},\r\n\t\t\t\tparamsKeyMap: {\r\n                    AI_PROMPT: 0,\r\n                },\r\n\t\t\t\tclass: 'telliot_ai',\r\n\t\t\t\tisNotFor : ['GoldenKidsAICar'],\r\n\t\t\t\tfunc: (sprite, script) => this.req_add_prompt(sprite, script)\r\n\t\t\t},\r\n\r\n//\t\t\ttelliot_car_set_prompt : {\r\n//\t\t\t\tcolor: EntryStatic.colorSet.block.default.HARDWARE,\r\n//\t\t\t\touterLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n//\t\t\t\tskeleton: 'basic',\r\n//\t\t\t\tstatements: [],\r\n//\t\t\t\tparams: [\r\n//\t\t\t\t\t{\r\n//\t\t\t\t\t\ttype : 'Indicator',\r\n//\t\t\t\t\t\timg : 'block_icon/hardware_icon.svg',\r\n//\t\t\t\t\t\tsize : 12,\r\n//\t\t\t\t\t},\r\n//\t\t\t\t],\r\n//\t\t\t\tevents: {},\r\n//\t\t\t\tdef: {\r\n//\t\t\t\t\tparams : [null],\r\n//\t\t\t\t\ttype: 'telliot_lite_STT',\r\n//\t\t\t\t},\r\n//\t\t\t\tclass: 'telliot_ai',\r\n//\t\t\t\t//isNotFor : ['TelliotLite'],\r\n//\t\t\t\tfunc: (sprite, script) => this.req_speech_to_text(sprite, script)\r\n//\t\t\t},\r\n\t\t};\r\n\t};\r\n\r\n    setZero () {\r\n        super.setZero();\r\n    }\r\n\r\n    afterReceive (data) {\r\n        super.afterReceive(data);\r\n    }\r\n\r\n    afterSend () {\r\n        super.afterSend();\r\n    }\r\n}\r\n\r\nmodule.exports = new TelliotLite();\r\n//module.exports = Entry.TelliotLite;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_thinkboard.js",
    "content": "'use strict';\n\nEntry.ThinkBoard = \n{\n\tid: '21.2',\t\n    name: 'ThinkBoard',\n    url: 'http://www.thinkfunedu.co.kr/',\n    imageName: 'Thinkboard.png',\n    title: \n\t{\n        \"ko\": \"씽크보드\", \n        \"en\": \"ThinkBoard\"\n    },\n\n    setZero: function() \n    {\n        if (!Entry.hw.sendQueue.SET) \n        {\n            Entry.hw.sendQueue = \n            {\n                GET: {},\n                SET: {},\n            };    \n        } \n\t\telse \n\t\t{ \n            var keySet = Object.keys(Entry.hw.sendQueue.SET);\n            keySet.forEach(function(key) \n            {             \n                if(Entry.hw.sendQueue.SET[key].type === 4)\n                {             \n                    Entry.hw.sendQueue.SET[key].data[0] = 0;          \n                    Entry.hw.sendQueue.SET[key].data[1] = 0;                                          \n                }\n                else Entry.hw.sendQueue.SET[key].data = 0;                                                                  \n                Entry.hw.sendQueue.SET[key].time = new Date().getTime();\n            });                                 \n        } \n        Entry.hw.update();    \n    },\n\t\n    sensorTypes: {\n        ALIVE: 0,\n        DIGITAL: 1,\n        ANALOG: 2,\n        BUZZER: 3,\n        SERVO: 4,\n        TONE: 5,\n        TEMP: 6,\n        USONIC: 7,\n        TIMER: 8,\n        RD_BT: 9,\n        WRT_BT: 10,\n        RGBLED: 11,\n        MOTOR: 12,\n        LASER: 13,\n    },\n    toneTable: {\n        '0': 0,\n        C: 1,\n        CS: 2,\n        D: 3,\n        DS: 4,\n        E: 5,\n        F: 6,\n        FS: 7,\n        G: 8,\n        GS: 9,\n        A: 10,\n        AS: 11,\n        B: 12,\n    },\n    toneMap: {\n        '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n        '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n        '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n        '4': [39, 78, 156, 311, 622, 1245, 2849, 4978],\n        '5': [41, 82, 165, 330, 659, 1319, 2637, 5274],\n        '6': [44, 87, 175, 349, 698, 1397, 2794, 5588],\n        '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n        '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n        '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n        '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n        '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n        '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n    },\n    highList: ['high', '1', 'on'],\n    lowList: ['low', '0', 'off'],\n    BlockState: {},\t\n    sValue1: 0,               // LEEJC 2020/03/17\n    sValue2: 0\t\n};\n\nEntry.ThinkBoard.blockMenuBlocks = [\n\t\t'thinkboard_buzzer_onoff',\t\t\t\n        'thinkboard_set_digital_buzzer',\n\t\t'thinkboard_get_digital_value',\t\n\t\t'thinkboard_digital_button_pressed',\n\t\t'thinkboard_get_analog_value',\n\t\t'thinkboard_get_analog_mapping',\n\t\t'thinkboard_get_distsensor_value',\n\t\t'thinkboard_get_analog_ir_mapping',\t\n\t\t'thinkboard_get_usonic_value',\n\t\t'thinkboard_get_analog_usonic_mapping',\n\t\t'thinkboard_get_analog_temp_value',\n\t\t'thinkboard_digital_Laser_onoff',\n        'thinkboard_digital_rgbled_onoff',\n\t\t'thinkboard_digital_rgbled_off',        \n//[4/19]'thinkboard_digital_set_rgbled_value',\n//[4/19]'thinkboard_digital_rgbled_percent',\n\t\t'thinkboard_get_digital_servo_value',\n\t\t'thinkboard_digital_set_servo_angle',\n\t\t'thinkboard_digital_set_servo_direction',\n        'thinkboard_digital_set_servo_stop',\n        'thinkboard_get_digital_servo_360_value',\n        'thinkboard_digital_set_servo_360_angle',\n        'thinkboard_digital_set_servo_360_stop',        \n\t\t'thinkboard_digital_set_motor_direction',\n\t\t'thinkboard_digital_set_motor_speed',\n\t\t'thinkboard_digital_motor_stop',\t\n];\n\nEntry.ThinkBoard.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n\t\t\t\t\"thinkboard_buzzer_onoff\": \"버저 %1 %2\",\t\t\t\t\n                \"thinkboard_set_digital_buzzer\": \"버저를 %1 옥타브 %2 음 %3 초 연주 %4\",\t\n\t\t\t\t\"thinkboard_get_digital_value\": \"포트 %1 버튼 센서 값\",\t\t\t\t\n\t\t\t\t\"thinkboard_digital_button_pressed\": \" 포트 %1 버튼 센서 눌림\",\t\n\t\t\t\t\"thinkboard_get_analog_value\": \"포트 %1 의 %2 센서 값\",\n\t\t\t\t\"thinkboard_get_analog_mapping\": \"포트 %1 의 %2 센서 값 %3 ~ %4 에서 %5 ~ %6 으로 변환값\", \n\t\t\t\t\"thinkboard_get_distsensor_value\": \"포트 %1 거리(IR) 센서 값\",\t\n\t\t\t\t\"thinkboard_get_analog_ir_mapping\": \"포트 %1 의 거리(IR) 센서 값 %2 ~ %3 에서 %4 ~ %5 으로 변환값\", \t\t\t\t\n\t\t\t\t\"thinkboard_get_usonic_value\": \"포트 %1 초음파 센서 값\",\t\n\t\t\t\t\"thinkboard_get_analog_usonic_mapping\": \"포트 %1 의 초음파 센서 값 %2 ~ %3 에서 %4 ~ %5 으로 변환값\", \t\n\t\t\t\t\"thinkboard_get_analog_temp_value\": \"포트 %1 의 %2 센서 값\",\t\n                \"thinkboard_digital_Laser_onoff\": \"포트 %1 의 레이저포인터 %2 %3\",             \n                \"thinkboard_digital_rgbled_onoff\": \"RGB LED %1 색 켜기 %2\",\t\n\t\t\t\t\"thinkboard_digital_rgbled_off\": \"RGB LED 끄기 %1\",\t                \n//[4/19]  \"thinkboard_digital_set_rgbled_value\": \"RGB LED 빨강 %1 초록 %2 파랑 %3 으로 켜기 %4\",\n//[4/19]  \"thinkboard_digital_rgbled_percent\": \"RGB LED 밝기를 %1 로 정하기 %2\",\n                \"thinkboard_get_digital_servo_value\": \"포트 %1 180 서보모터 각도 값\",\n                \"thinkboard_digital_set_servo_angle\": \"포트 %1 의 180 서보모터의 각도를 %2 으로 정하기 %3\",\n                \"thinkboard_digital_set_servo_direction\": \"포트 %1 의 180 서보모터를 %2 방향으로 1도 바꾸기 %3\",\n                \"thinkboard_digital_set_servo_stop\": \"포트 %1 의 180 서보모터 정지하기 %2\",                \n                \"thinkboard_get_digital_servo_360_value\": \"포트 %1 360 서보모터 각도 값\",\n                \"thinkboard_digital_set_servo_360_angle\": \"포트 %1 의 360 서보모터의 각도를 %2 으로 정하기 %3\",\n                \"thinkboard_digital_set_servo_360_stop\": \"포트 %1 의 360 서보모터 정지하기 %2\",                \n\t\t\t\t\"thinkboard_digital_set_motor_direction\": \"포트 %1 의 DC모터 방향을 %2 방향으로 정하기 %3\",\n\t\t\t\t\"thinkboard_digital_set_motor_speed\": \"포트 %1 의 DC모터의 속도를 %2 %로 정하기 %3\", \n\t\t\t\t\"thinkboard_digital_motor_stop\": \"포트 %1 의 DC모터 정지하기 %2\",\t\t\t\n            }\n        },\n        en: {\n            template: {\n\t\t\t\t\"thinkboard_buzzer_onoff\": \"Buzzer %1 %2\",\t\t\t\t\n                \"thinkboard_set_digital_buzzer\": \"Play Buzzer %1 Octave %2 Note %3 Sec %4\",\t\n\t\t\t\t\"thinkboard_get_digital_value\": \"Port %1 Button Sensor Value\",\t\t\t\t\n\t\t\t\t\"thinkboard_digital_button_pressed\": \" Port %1 Button Sensor Pressed\",\t\t\n\t\t\t\t\"thinkboard_get_analog_value\": \"Port %1 and %2 Sensor Value\",\n                \"thinkboard_get_analog_mapping\": \"Map analog %1 pin %2 Sensor Value from %3 ~ %4 to %5 ~ %6\",\t\n\t\t\t\t\"thinkboard_get_distsensor_value\": \"Port %1 Distance(IR) Sensor Value\",\t\t\n\t\t\t\t\"thinkboard_get_analog_ir_mapping\": \"Map analog %1 Distance(IR) Sensor Value from %2 ~ %3 to %4 ~ %5\", \t\t\n\t\t\t\t\"thinkboard_get_usonic_value\": \"Port %1 Ultrasonic Sensor Value\",\t\t\n\t\t\t\t\"thinkboard_get_analog_usonic_mapping\": \"Map analog %1 Ultrasonic Sensor Value from %2 ~ %3 to %4 ~ %5\", \t\n\t\t\t\t\"thinkboard_get_analog_temp_value\": \"Port %1 and %2 Sensor Value\",\t\n                \"thinkboard_digital_Laser_onoff\": \"Port %1 and Laserpoint %2 %3\",\t\n//[4/19]  \"thinkboard_digital_rgbled_onoff\": \"RGB LED %1 Color %2 %3\",\t\t                \n                \"thinkboard_digital_rgbled_onoff\": \"RGB LED %1 Color Turn On %2\",\t\n\t\t\t\t\"thinkboard_digital_rgbled_off\": \"RGB LED Turn Off %1\",\t                \t\n//[4/19]  \"thinkboard_digital_set_rgbled_value\": \"Turn On RGB LED with RED %1 GREEN %2 BLUE %3 value %4\",\n//[4/19]  \"thinkboard_digital_rgbled_percent\": \"Set RGB LED Brightness to %1 %2\",\t\t\n                \"thinkboard_get_digital_servo_value\": \"Port %1 180 Servo Motor Angle Value\",\n                \"thinkboard_digital_set_servo_angle\": \"Set Port %1 180 Servor Motor Angle Value to %2 %3\",\n                \"thinkboard_digital_set_servo_direction\": \"Set Port %1 180 Servor Motor Direction 1 Angle to %2 %3\",\n                \"thinkboard_digital_set_servo_stop\": \"Stop Port %1 180 Servo Motor %2\",\n                \"thinkboard_get_digital_servo_360_value\": \"Port %1 360 Servo Motor Angle Value\",\n                \"thinkboard_digital_set_servo_360_angle\": \"Set Port %1 360 Servor Motor Angle Value to %2 %3\",  \n                \"thinkboard_digital_set_servo_360_stop\": \"Stop Port %1 360 Servo Motor %2\",          \n\t\t\t\t\"thinkboard_digital_set_motor_direction\": \"Set Port %1 DC Motor Direction to %2 %3\",\t\t\n\t\t\t\t\"thinkboard_digital_set_motor_speed\": \"Set Port %1 의 DC Motor Speed to %2 % %3\", \t\n\t\t\t\t\"thinkboard_digital_motor_stop\": \"Stop Port %1 DC Motor %2\",\t\t\t\t\t\n            }\n        }\n    }\n};\n\nEntry.ThinkBoard.getBlocks = function() {\n    return {\n        thinkboard_digital_port_onoff_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['켜기', '1'],\n                        ['끄기', '0'],\n                    ],\t\t\t\t\t\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\t\n\t\t\n\t\t// 1. 버저 - 1) 버저 On/Off\n\t\tthinkboard_buzzer_onoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr2.png',        // img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_port_onoff_list',\n                    },\n                    null,\n                ],\n                type: 'thinkboard_buzzer_onoff',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'ThinkBoard_BUZ',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n\t\t\t\tvar port = 10;\n                var mode = script.getNumberValue('VALUE');\t\t\n\t\t\t\t\n                if (!Entry.hw.sendQueue['SET']) {\n                Entry.hw.sendQueue['SET'] = {};\n                }\n\t\t\t\t\n                Entry.hw.sendQueue['SET'][port] = {\n                type: Entry.ThinkBoard.sensorTypes.BUZZER,\n                data: mode,\n                time: new Date().getTime(),\n                };\t\t\t\t\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n       thinkboard_list_digital_octave: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('OCTAVE');\n            },\n        },\n\t\t\n        thinkboard_list_digital_tone: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.silent, '0'],\n                        [Lang.Blocks.do_name, 'C'],\n                        [Lang.Blocks.do_sharp_name, 'CS'],\n                        [Lang.Blocks.re_name, 'D'],\n                        [Lang.Blocks.re_sharp_name, 'DS'],\n                        [Lang.Blocks.mi_name, 'E'],\n                        [Lang.Blocks.fa_name, 'F'],\n                        [Lang.Blocks.fa_sharp_name, 'FS'],\n                        [Lang.Blocks.sol_name, 'G'],\n                        [Lang.Blocks.sol_sharp_name, 'GS'],\n                        [Lang.Blocks.la_name, 'A'],\n                        [Lang.Blocks.la_sharp_name, 'AS'],\n                        [Lang.Blocks.si_name, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('NOTE');\n            },\n        },\n\t\t\n\t\t// 1. 버저 - 2) 버저 옥타브/음/초 동안 연주\n        thinkboard_set_digital_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            template: Lang.template.thinkboard_set_digital_buzzer,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_bzr2.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_list_digital_octave',\t\t\t\t\t\t\n                    },\n                    {\n                        type: 'thinkboard_list_digital_tone',\n                    },\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'thinkboard_set_digital_buzzer',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\t\t\t\t\n                NOTE: 1,\n                DURATION: 2,\n            },\n            class: 'ThinkBoard_BUZ',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) {\n                var port = 10;\n                var duration = script.getNumberValue('DURATION');\n                var octave = script.getNumberValue('OCTAVE') - 1;\n                var value = 0;\n\n                if (!script.isStart) \n\t\t\t\t{\n                    var note = script.getValue('NOTE');\n                    if (!Entry.Utils.isNumber(note)) \n\t\t\t\t\t{\n                        note = Entry.ThinkBoard.toneTable[note];\n                    }\n                    if (note < 0) note = 0;\n                    else if (note > 12) note = 12;\n\n                    if (duration < 0) duration = 0;\n\t\t\t\t\t\n                    if (!Entry.hw.sendQueue['SET']) \n\t\t\t\t\t{\n                        Entry.hw.sendQueue['SET'] = {};\n                    }\n\t\t\t\t\t\n                    if (duration == 0) \n\t\t\t\t\t{\n                        Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t\t\t{\n                            type: Entry.ThinkBoard.sensorTypes.TONE,\n                            data: 0,\n                            time: new Date().getTime(),\n                        };\n                        return script.callReturn();\n                    }\n\t\t\t\t\t\n                    if (octave < 0) octave = 0;\n                    else if (octave > 8) octave = 8;\n                    if (note != 0) value = Entry.ThinkBoard.toneMap[note][octave];\n\n                    duration = duration * 1000;\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t\t{\n                        type: Entry.ThinkBoard.sensorTypes.TONE,\n                        data: \n\t\t\t\t\t\t{\n                            value: value,\n                            duration: duration,\n                        },\n                        time: new Date().getTime(),\n                    };\n\n                    setTimeout(function() \n\t\t\t\t\t{\n                        script.timeFlag = 0;\n                    }, duration + 32);\n                    return script;\n                } \n\t\t\t\telse if (script.timeFlag == 1) \n\t\t\t\t{\n                    return script;\n                } \n\t\t\t\telse \n\t\t\t\t{\n                    delete script.timeFlag;\n                    delete script.isStart;\n                    Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t\t{\n                        type: Entry.ThinkBoard.sensorTypes.TONE,\n                        data: 0,\n                        time: new Date().getTime(),\n                    };\n                    Entry.engine.isContinue = false;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n        thinkboard_digital_port_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN/OUT1', '0'],\n                        ['IN/OUT2', '1'],\n                        ['IN/OUT3', '2'],\n                        ['IN/OUT4', '3'],\t\t\t\t\t\t\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n\n        thinkboard_digital_2_port_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['IN/OUT2', '1'],\n                        ['IN/OUT4', '3'],\t\t\t\t\t\t\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('PORT');\n            },\n        },\n\n\t\tthinkboard_motor_direction_list: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['시계', '0'],\n                        ['반시계', '1'],\t\t\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                    arrowColor: EntryStatic.ARROW_COLOR_HW,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            func: function(sprite, script) {\n                return script.getStringField('DIR');\n            },\n        },\n\t\t\n\t\t// 2. 버튼 - 1) 버튼 센서 값\t\t\n        thinkboard_get_digital_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.thinkboard_get_digital_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },            \n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_port_list',\n                    },\n                ],\n                type: 'thinkboard_get_digital_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_BTN',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\t\t\n                var port = script.getNumberValue('PORT');\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n\t\t\t\t\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][\n                    Entry.ThinkBoard.sensorTypes.DIGITAL\n                ] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\t\t\n\t\t\t\treturn DIGITAL[port+2];\n            },\n            syntax: { js: [], py: [] },\n        },\t\n\t\t\n\t\t// 2. 버튼 - 2) 버튼 센서 누름\t\n\t\tthinkboard_digital_button_pressed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_port_list',\n                    },\n                ],\n                type: 'thinkboard_digital_button_pressed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_BTN',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script)\n\t\t\t{\n                var btn_index = script.getNumberValue('PORT');\n                var value = 0;\n                var btn_pressed = 0;\n\n                var DIGITAL = Entry.hw.portData.DIGITAL;\n                value = DIGITAL[btn_index+2];\n                btn_pressed = value > 0 ? 1 : 0;\n\n                return btn_pressed;\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n        thinkboard_analog_port_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['INPUT1', '0'],\n                        ['INPUT2', '1'],\n                        ['INPUT3', '2'],\n                        ['INPUT4', '3'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n\n        thinkboard_analog_port_name: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['소리', '0'],\n                        ['빛', '1'],\n                        ['가변저항', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n\t\t\n\t\t// 3. 소리/빛/가변저항 - 1) 센서 값 \t\t\t\t\n        thinkboard_get_analog_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.thinkboard_get_analog_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_analog_port_list',\n                    },\n                    {\n                        type: 'thinkboard_analog_port_name',\n                    },\t\t\t\t\t\n                ],\n                type: 'thinkboard_get_analog_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tTYPE: 1,\n            },\n            class: 'ThinkBoard_ANA',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getNumberValue('PORT');\t\t\n                var type = script.getValue('TYPE', script);\t\t\t                \t\t\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if(type === \"2\") return (1023-ANALOG[port]);\n                else return ANALOG[port];\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 3. 소리/빛/가변저항 - 2) mapping 값\t\t\t\n        thinkboard_get_analog_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.thinkboard_get_analog_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_analog_port_list',\n                    },\n                    {\n                        type: 'thinkboard_analog_port_name',\n                    },\t\t\t\t\t\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'thinkboard_get_analog_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tTYPE: 1,\n                VALUE2: 2,\n                VALUE3: 3,\n                VALUE4: 4,\n                VALUE5: 5,\n            },\n            class: 'ThinkBoard_ANA',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getValue('PORT', script);\n                var type = script.getValue('TYPE', script);\t\t\t\t\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\t\t\t\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n//[4/18]  result = ANALOG ? ANALOG[port] || 0 : 0;           \n                if(type === \"2\") result = 1023-ANALOG[port];\n                else result = ANALOG[port];\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return Math.round(result);\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\t\n\t\t// 6. 거리 - 1) 센서 값\t\t\n        thinkboard_get_distsensor_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.thinkboard_get_distsensor_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_analog_port_list',\n                    },\n                ],\n                type: 'thinkboard_get_distsensor_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_IR',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var ANALOG = Entry.hw.portData.ANALOG;\n\n                if (port[0] === 'A') port = port.substring(1);\n\n                return ANALOG ? (1023-ANALOG[port]) || 0 : 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 6. 거리 센서 - 2) mapping 값\t\t\t\n        thinkboard_get_analog_ir_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.thinkboard_get_analog_ir_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_analog_port_list',\n                    },\t\t\t\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['1023'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'thinkboard_get_analog_ir_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'ThinkBoard_IR',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n                var ANALOG = Entry.hw.portData.ANALOG;\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n                if (port[0] === 'A') {\n                    port = port.substring(1);\n                }\n                //[4/19] add\n                result = ANALOG ? (1023-ANALOG[port]) || 0 : 0;\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n\n                return Math.round(result);\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 7. 초음파 - 1) 센서 값\t\t\n        thinkboard_get_usonic_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.thinkboard_get_usonic_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_port_list',\n                    },\n                ],\n                type: 'thinkboard_get_usonic_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_USONIC',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                \n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n\t\t\t\t\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][\n                    Entry.ThinkBoard.sensorTypes.USONIC\t\t\n                ] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };\n\n                return Entry.hw.portData.USONIC[port] || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 7. 초음파 센서 - 2) mapping 값\t\t\t\n        thinkboard_get_analog_usonic_mapping: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.thinkboard_get_analog_usonic_mapping,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_port_list',\n                    },\t\t\t\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['400'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                ],\n                type: 'thinkboard_get_analog_usonic_mapping',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                VALUE2: 1,\n                VALUE3: 2,\n                VALUE4: 3,\n                VALUE5: 4,\n            },\n            class: 'ThinkBoard_USONIC',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) {\n                var port = script.getValue('PORT', script);\n                var result = 0;\n\t\t\t\t\n                var value2 = script.getNumberValue('VALUE2', script);\n                var value3 = script.getNumberValue('VALUE3', script);\n                var value4 = script.getNumberValue('VALUE4', script);\n                var value5 = script.getNumberValue('VALUE5', script);\n\n               if (!Entry.hw.sendQueue['SET']) {\n                Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n            \n                if (!Entry.hw.sendQueue['GET']) {\n                Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][\n                    Entry.ThinkBoard.sensorTypes.USONIC\t\t\n                ] = {\n                    port: port,\n                    time: new Date().getTime(),\n                };               \n                result = Entry.hw.portData.USONIC[port];\n\n                if (value2 > value3) {\n                    var swap = value2;\n                    value2 = value3;\n                    value3 = swap;\n                }\n                if (value4 > value5) {\n                    var swap = value4;\n                    value4 = value5;\n                    value5 = swap;\n                }\n                result -= value2;\n                result = result * ((value5 - value4) / (value3 - value2));\n                result += value4;\n                result = Math.min(value5, result);\n                result = Math.max(value4, result);\n                \n                return Math.round(result);\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\t\t\n       thinkboard_analog_temp_name: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['습도', '0'],\n                        ['온도(화씨)', '1'],\n                        ['온도(섭씨)', '2'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n\t\t\n\t\t// 8. 온습도 - 1) 센서 값 \t\t\t\t\n        thinkboard_get_analog_temp_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            template: Lang.template.thinkboard_get_temp_value,\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_port_list',\n                    },\n                    {\n                        type: 'thinkboard_analog_temp_name',\n                    },\t\t\t\t\t\n                ],\n                type: 'thinkboard_get_analog_temp_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tTYPE: 1,\n            },\n            class: 'ThinkBoard_TMP',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n            {\n                var port = script.getNumberValue('PORT');\n                var type = script.getNumberValue('TYPE');\t\t\t\t\n                \n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n        \t\t\t\t\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][\n                    Entry.ThinkBoard.sensorTypes.TEMP\t\t\n                ] = {\n                    port,\n                    time: new Date().getTime(),\n                };\n\n                var temp;\n                switch(type)\n                {\n                    case 0: temp = Entry.hw.portData.TEMP[0];        // humidity\n                                break;\n                    case 1: temp = Entry.hw.portData.TEMP[1];        // temp_F\n                                temp = Math.round(temp*1.8+32);                                               \n                                break;                \n                    case 2: temp = Entry.hw.portData.TEMP[1];        // temp_C              \n                                break;                                                \n                }\n                return temp || 0;                \n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 9. 레이저 - 1) On/Off\n\t\tthinkboard_digital_Laser_onoff: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_laser.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_port_list',\n                    },\n                    {\n                        type: 'thinkboard_digital_port_onoff_list',\n                    },\t\t\t\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_Laser_onoff',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tVALUE: 1,\n            },\n            class: 'ThinkBoard_LASER',\n            isNotFor: ['ThinkBoard'],\n           func: function(sprite, script) \n\t\t   {\n                var port = script.getNumberValue('PORT');\n                var value = script.getNumberValue('VALUE');\n                \n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port+2] = {\n                    type: Entry.ThinkBoard.sensorTypes.LASER,\n                    data: value,\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\t\t\t\t\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\t\t//\n       thinkboard_analog_rgb_color_list: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: '%1',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['흰', '1'],\n                        ['빨간', '2'],\n                        ['연두', '3'],\n                        ['파란', '4'],\n                        ['노란', '5'],\n                        ['하늘', '6'],\n                        ['보라', '7'],\t\t\t\t\t\t\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            func: function(sprite, script) {\n                return script.getField('PORT');\n            },\n        },\n\t\t\n\t\t// 10. RGBLED - 1) 종류 선택 및 On/Off\n\t\tthinkboard_digital_rgbled_onoff: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n/*[4/19]                \n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n*/                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_analog_rgb_color_list',\n                    },\n/*[4/19]                    \n                    {\n                        type: 'thinkboard_digital_port_onoff_list',\n                    },\t\n*/                    \t\t\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_rgbled_onoff',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n//[4/19]  ONOFF: 1,\n            },\n            class: 'ThinkBoard_RGB',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\t\n\t\t\t\tvar port = 11;\n                var color = script.getNumberValue('COLOR', script);\n//[4/19]  var onoff = script.getNumberValue('ONOFF', script);\n\n\t\t\t\tvar rLED, gLED, bLED;\n\n//[4/19]  if(onoff === 0) color = 0;\n\t\t\t\tswitch(color)\n\t\t\t\t{\n\t\t\t\t\tcase 0:\trLED = gLED = bLED = 0;\t\t\t            // Black\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 1:\trLED = gLED = bLED = 255;\t\t         // white\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\n\t\t\t\t\tcase 2:\trLED = 255; gLED = bLED = 0;\t        // Red\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\n\t\t\t\t\tcase 3:\trLED = bLED = 0; gLED = 255;\t        // Lime\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\n\t\t\t\t\tcase 4:\trLED = gLED = 0; bLED = 255;\t        // Blue\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\n\t\t\t\t\tcase 5:\trLED = gLED = 255; bLED = 0;            // Yellow\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\n\t\t\t\t\tcase 6:\trLED = 0; gLED = bLED = 255;            // Cyan\n\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\n\t\t\t\t\tcase 7:\trLED = bLED = 255; gLED = 0;\t\t   // Magenta\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n                if (!Entry.hw.sendQueue['SET']) \n\t\t\t\t{\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ThinkBoard.sensorTypes.RGBLED,\n                    data: {\t\t\t\n                        r: rLED,\n                        g: gLED,\n                        b: bLED,\n                    },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n\t\t// 10. RGBLED - 2) Off\n\t\tthinkboard_digital_rgbled_off: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [    \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [ \t\t\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_rgbled_off',\n            },\n            paramsKeyMap: {\n            },\n            class: 'ThinkBoard_RGB',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\t\n\t\t\t\tvar port = 11;\n\t\t\t\tvar rLED = 0, gLED = 0, bLED = 0;\n\t\t\t\t\t\t\t\n                if (!Entry.hw.sendQueue['SET']) \n\t\t\t\t{\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ThinkBoard.sensorTypes.RGBLED,\n                    data: {\t\t\t\n                        r: rLED,\n                        g: gLED,\n                        b: bLED,\n                    },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },        \n\n\t\t// 10. RGBLED - 2) RGB 값으로 켜기\n\t\tthinkboard_digital_set_rgbled_value: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\t\t\t\t\n\t\t\t\t\t{\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\t\n                    null,\n                ],\n                type: 'thinkboard_digital_set_rgbled_value',\n            },\n            paramsKeyMap: {\n                VALUE0:0,\n                VALUE1:1,\n\t\t\t\tVALUE2:2,\n            },\n            class: 'ThinkBoard_RGB',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = 12;      \n                var rLED = script.getNumberValue('VALUE0', script);\n                var gLED = script.getNumberValue('VALUE1', script);\n                var bLED = script.getNumberValue('VALUE2', script);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ThinkBoard.sensorTypes.RGBLED,\n                    data: {\n                        r: rLED,\n                        g: gLED,\n                        b: bLED,\n                    },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n\t\t// 10. RGBLED - 3) 밝기 설정\n\t\tthinkboard_digital_rgbled_percent: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_led.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\t\t\t\t\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_rgbled_percent',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'ThinkBoard_RGB',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = 13;      \n                var value = script.getNumberValue('VALUE', script);\n\n\t\t\t\tvar rLED, gLED, bLED;\n\t\t\t\tif(value == 0)\n\t\t\t\t{\n\t\t\t\t\trLED = gLED = bLED = 0;\n\t\t\t\t}\n\t\t\t\telse if(value <= 100)\n\t\t\t\t{\n\t\t\t\t\trLED = (255*value)/100;\n\t\t\t\t\tgLED = (255*value)/100;\n\t\t\t\t\tbLED = (255*value)/100;\t\t\t\t\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\trLED = gLED = bLED = 255;\n\t\t\t\t}\n\t\t\t\t\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ThinkBoard.sensorTypes.RGBLED,\n                    data: {\n                        r: rLED,\n                        g: gLED,\n                        b: bLED,\n                    },\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n        \n\t\t// 11. 180 서보 모터 - 1) 모터 현재 각도 값\t얻어오기\t\n        thinkboard_get_digital_servo_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\t\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.thinkboard_get_digital_servo_value,\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },      \n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_2_port_list',\n                    },            \n                ],\n                type: 'thinkboard_get_digital_servo_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_SVO',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getNumberValue('PORT');\t\n                var mode = 0;       \n                \n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                    }\n                    delete Entry.hw.sendQueue['SET'][port];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][Entry.ThinkBoard.sensorTypes.SERVO] = \n\t\t\t\t{\n                    port: [port, mode],\n                    time: new Date().getTime(),\n                };\n\t\t\t\t\n                // LEEJC 2020.3.17\n                if(port === 1)  Entry.hw.portData.SERVO[port] = Entry.ThinkBoard.sValue1;     \n                else Entry.hw.portData.SERVO[port] = Entry.ThinkBoard.sValue2;    \n\t\t\t\t\n                return Entry.hw.portData.SERVO[port] || 0;\n            },\n            syntax: { js: [], py: [] },\n        },\t\n\n\t\t// 11. 180 서보 모터 - 2) 모터 각도 설정하기\t\t\n\t\tthinkboard_digital_set_servo_angle: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },                \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_servo.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_2_port_list',\n                    },\t\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\t\t\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_set_servo_angle',\n            },\n            paramsKeyMap: \n\t\t\t{\n                PORT: 0,\n                ANGLE: 1,\n            },\n            class: 'ThinkBoard_SVO',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getNumberValue('PORT', script);\n                var mode = 2;                \n                var angle = script.getNumberValue('ANGLE', script);\n                \n                angle = Math.min(180, angle);\n                angle = Math.max(0, angle);\n\t\t\t\t\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t{\n                    type: Entry.ThinkBoard.sensorTypes.SERVO,\n                    data: [mode, angle],\n                    time: new Date().getTime(),\n                };\n\t\t\t\t\n                // LEEJC 2020.3.17\n                if(port === 1)  Entry.ThinkBoard.sValue1 = angle;     \n                else Entry.ThinkBoard.sValue2 = angle;    \n\t\t\t\t\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 11. 180 서보 모터 - 3) 설정 방향 및 1도 바꾸기\t\t\n\t\tthinkboard_digital_set_servo_direction: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t         \t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_servo.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_2_port_list',\n                    },\t\t\t                       \n                    {\n                        type: 'thinkboard_motor_direction_list',\n                    },\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_set_servo_direction',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                DIR: 1,\n            },\n            class: 'ThinkBoard_SVO',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getNumberValue('PORT', script);\n                var mode = 3;                \n                var dir = script.getNumberValue('DIR', script);\n                \n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t{\n                    type: Entry.ThinkBoard.sensorTypes.SERVO,\n                    data: [mode, dir],\n                    time: new Date().getTime(),\n                };\n\t\t\t\t\n                if(dir === 0) // 반시계 방향 (-)\n                {\n                    // LEEJC 2020.3.17\n                    if(port === 1)\n                    {\n                        if(Entry.ThinkBoard.sValue1 > 0) Entry.ThinkBoard.sValue1--;     \n                    }\n                    else \n                    {\n                        if(Entry.ThinkBoard.sValue2 > 0) Entry.ThinkBoard.sValue2--;                  \n                    }\n                }\n                else    // (dir === 1) 시계 방향(++)\n                {\n                    // LEEJC 2020.3.17\n                    if(port === 1)\n                    {\n                        if(Entry.ThinkBoard.sValue1 < 180) Entry.ThinkBoard.sValue1++;     \n                    }\n                    else \n                    {\n                        if(Entry.ThinkBoard.sValue2 < 180) Entry.ThinkBoard.sValue2++;                  \n                    }\n                }\n\t\t\t\t\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n\t\t// 11. 180 서보 모터 - 4) 모터 정지하기\t\t\n\t\tthinkboard_digital_set_servo_stop: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },              \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_servo.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_2_port_list',\n                    },\t                \t\n                    null,\n                ],\n                type: 'thinkboard_digital_set_servo_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_SVO',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getNumberValue('PORT', script);\n                var mode = 4;                \n\t\t\t\tvar angle = 0;\n                \n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t{\n                    type: Entry.ThinkBoard.sensorTypes.SERVO,\n                    data: [mode, angle],\n                    time: new Date().getTime(),\n                };\n\t\t\t\n                    // LEEJC 2020.3.17\n                if(port === 1) Entry.ThinkBoard.sValue1 = 0;    \n                else Entry.ThinkBoard.sValue2 = 0;  \t\n\t\t\t\t\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n           \n        // 12. 360도 서보 모터 - 1) 모터 각도 값\t\t\n        thinkboard_get_digital_servo_360_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            template: Lang.template.thinkboard_get_digital_servo_360_value,\n            params: [{\n                type: 'Block',\n                accept: 'string',\n            }, ],\n            events: {},\n            def: {\n                params: [{\n                    type: 'thinkboard_digital_2_port_list',\n                }, ],\n                type: 'thinkboard_get_digital_servo_360_value',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_SVO2',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT');\n                var mode = 1; // get current 360-Angle\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                delete Entry.hw.sendQueue['SET'][port];\n\n                if (!Entry.hw.sendQueue['GET']) {\n                    Entry.hw.sendQueue['GET'] = {};\n                }\n                Entry.hw.sendQueue['GET'][\n                    Entry.ThinkBoard.sensorTypes.SERVO\n                ] = {\n                    port: [port, mode],\n                    time: new Date().getTime(),\n                };\n                return Entry.hw.portData.SERVO[port] || 0;                \n            },\n            syntax: { js: [], py: [] },\n        },\n\n        // 12. 360도 서보 모터 - 2) 모터 각도 설정하기\t\t\n        thinkboard_digital_set_servo_360_angle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [{\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },           \n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_servo.png',                    \n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [{\n                        type: 'thinkboard_digital_2_port_list',\n                    },                    \n                    {\n                        type: 'number',\n                        params: [\"0\"],\n                    },\n                    null,\n                ],\n                type: 'thinkboard_digital_set_servo_360_angle',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                SPEED: 1,\n            },\n            class: 'ThinkBoard_SVO2',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var speed = script.getNumberValue('SPEED', script);\n                var mode = 5;\n\n                speed = Math.min(360, speed);\n                speed = Math.max(0, speed);\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ThinkBoard.sensorTypes.SERVO,\n                    data: [mode, speed],\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        // 14. 360도 서보 모터 - 4) 모터 정지하기\t\t\n        thinkboard_digital_set_servo_360_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [{\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_servo.png',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [{\n                        type: 'thinkboard_digital_2_port_list',\n                    },\n                    null,\n                ],\n                type: 'thinkboard_digital_set_servo_360_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_SVO2',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) {\n                var port = script.getNumberValue('PORT', script);\n                var mode = 6; //script.getNumberValue('VALUE', script);\n                var angle = 90;\n\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = {\n                    type: Entry.ThinkBoard.sensorTypes.SERVO,\n                    data: [mode, angle],\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n      \n\n\t\t// 15. DC 모터 - 1) 방향 바꾸기\t\t\n\t\tthinkboard_digital_set_motor_direction: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_2_port_list',\n                    },\t\t\t\n                    {\n                        type: 'thinkboard_motor_direction_list',\n                    },\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_set_motor_direction',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tDIR: 1,\n\t\t\t},\n            class: 'ThinkBoard_DC',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getNumberValue('PORT', script);\n                var dir = script.getNumberValue('DIR', script);\n\t\t\t\tvar mode = 1;\n\t\t\t\t\t\t\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t{\n                    type: Entry.ThinkBoard.sensorTypes.MOTOR,\n                    data: [mode, dir],\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 16. DC 모터 - 2) 모터 속도 정하기\t\t\n\t\tthinkboard_digital_set_motor_speed: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\t\t\t\t\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_2_port_list',\n                    },\n                    {\n                        type: 'number',\n\t\t\t\t\t\tparams: [\"0\"],\n                    },\t\t\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_set_motor_speed',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n\t\t\t\tSPEED: 1,\n            },\n            class: 'ThinkBoard_DC',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getNumberValue('PORT', script);\n                var speed = script.getNumberValue('SPEED', script);\n\t\t\t\tvar mode = 2;\n\t\t\t\t\t\t\n                speed = Math.min(100, speed);\n                speed = Math.max(0, speed);\t\t                           \n                \n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t{\n                    type: Entry.ThinkBoard.sensorTypes.MOTOR,\n                    data: [mode, speed],\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\t\t\n\t\t// 17. DC 모터 - 4) 모터 정지하기\t\t\n\t\tthinkboard_digital_motor_stop: \n\t\t{\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\t\t\n\t\t\tfontColor: '#fff',\t\t\t\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_dc.png',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'thinkboard_digital_2_port_list',\n                    },\t\t\n                    null,\n                ],\n                type: 'thinkboard_digital_motor_stop',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'ThinkBoard_DC',\n            isNotFor: ['ThinkBoard'],\n            func: function(sprite, script) \n\t\t\t{\n                var port = script.getNumberValue('PORT', script);\n\t\t\t\tvar mode = 3;\n\t\t\t\tvar speed = 0;\n\t\t\n                if (!Entry.hw.sendQueue['SET']) {\n                    Entry.hw.sendQueue['SET'] = {};\n                }\n                Entry.hw.sendQueue['SET'][port] = \n\t\t\t\t{\n                    type: Entry.ThinkBoard.sensorTypes.MOTOR,\n                    data: [mode, speed],\n                    time: new Date().getTime(),\n                };\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n    };\n};\n\nmodule.exports = Entry.ThinkBoard;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_timbo.js",
    "content": "'use strict';\r\n\r\nEntry.Timbo = {\r\n    id: '6A.1',\r\n    name: 'Timbo',\r\n\r\n    title: {\r\n        ko: '팀보 커뮤니케이션 블록',\r\n        en: 'Timbo Communication Block',\r\n    },\r\n    setZero() {\r\n        Entry.hw.sendQueue.readablePorts = [];\r\n        for (let port = 0; port < 20; port++) {\r\n            Entry.hw.sendQueue[port] = 0;\r\n            Entry.hw.sendQueue.readablePorts.push(port);\r\n        }\r\n        Entry.hw.update();\r\n    },\r\n};\r\n\r\nEntry.Timbo.setLanguage = function () {\r\n    return {\r\n        ko: {\r\n            template: {\r\n                timbo_queen_play: '퀸의 %1 켜기',\r\n                timbo_queen_stop: '퀸의 동작 끄기',\r\n                timbo_motion_play: '모션 %1의 %2 켜기',\r\n                timbo_motion_stop: '모션 %1의 동작 끄기',\r\n                timbo_check_queen: '퀸의 동작여부 체크',\r\n                timbo_check_motion: '모션 %1의 동작여부 체크',\r\n            },\r\n            Device: {\r\n                timbo: '팀보',\r\n            },\r\n            Menus: {\r\n                timbo: '팀보',\r\n            },\r\n            Helper: {\r\n                timbo_queen_play: '퀸의 동작을 선택하여 켭니다.',\r\n                timbo_queen_stop: '퀸의 동작을 멈춥니다.',\r\n                timbo_motion_play: '지정한 모션 번호와 동작 타입으로 모션을 실행합니다.',\r\n                timbo_motion_stop: '지정한 모션 번호의 동작을 멈춥니다.',\r\n                timbo_check_queen: '퀸이 동작 중인지 확인합니다.',\r\n                timbo_check_motion: '지정한 모션 번호가 동작 중인지 확인합니다.',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                timbo_queen_play: 'Turn on Queen %1',\r\n                timbo_queen_stop: 'Turn off Queen action',\r\n                timbo_motion_play: 'Turn on Motion %1 of %2',\r\n                timbo_motion_stop: 'Turn off Motion %1 action',\r\n                timbo_check_queen: 'Check if Queen is operating',\r\n                timbo_check_motion: 'Check if Motion %1 is operating',\r\n            },\r\n            Device: {\r\n                timbo: 'Timbo',\r\n            },\r\n            Menus: {\r\n                timbo: 'Timbo',\r\n            },\r\n            Helper: {\r\n                timbo_queen_play: 'Turn on selected Queen action.',\r\n                timbo_queen_stop: 'Stop all Queen actions.',\r\n                timbo_motion_play: 'Execute specific Motion with given type.',\r\n                timbo_motion_stop: 'Stop Motion action of given ID.',\r\n                timbo_check_queen: 'Check if Queen is currently operating.',\r\n                timbo_check_motion: 'Check if selected Motion is currently operating.',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nEntry.Timbo.blockMenuBlocks = [\r\n    'timbo_queen_play',\r\n    'timbo_queen_stop',\r\n    'timbo_motion_play',\r\n    'timbo_motion_stop',\r\n    'timbo_check_queen',\r\n    'timbo_check_motion',\r\n];\r\n\r\nEntry.Timbo.getBlocks = function () {\r\n    return {\r\n        timbo_queen_play: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            template: Lang.template.timbo_queen_play,\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['동작', '1'],\r\n                        ['반복동작', '2'],\r\n                        ['한번동작', '3'],\r\n                        ['거꾸로동작', '4'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            paramsKeyMap: {\r\n                ACTION: 0,\r\n            },\r\n            class: 'timbo',\r\n            isNotFor: ['Timbo'],\r\n            func(sprite, script) {\r\n                const action = Number(script.getField('ACTION'));\r\n                Entry.hw.setDigitalPortValue(1, action);\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        timbo_queen_stop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            template: Lang.template.timbo_queen_stop,\r\n            params: [],\r\n            class: 'timbo',\r\n            isNotFor: ['Timbo'],\r\n            func(sprite, script) {\r\n                Entry.hw.setDigitalPortValue(1, 5);\r\n                return script.callReturn();\r\n            },\r\n        },\r\n        timbo_motion_play: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['동작', '1'],\r\n                        ['반복동작', '2'],\r\n                        ['한번동작', '3'],\r\n                        ['거꾸로동작', '4'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null, null],\r\n                type: 'timbo_motion_play',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                ACTION: 1,\r\n            },\r\n            class: 'timbo_motion',\r\n            isNotFor: ['Timbo'],\r\n            func(sprite, script) {\r\n                const port = Number(script.getField('PORT'));\r\n                const action = Number(script.getField('ACTION'));\r\n                Entry.hw.setDigitalPortValue(port + 1, action);\r\n                return script.callReturn();\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'Arduino.pin_digital(%1, 1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        timbo_motion_stop: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'timbo_motion_stop',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n            },\r\n            class: 'timbo_motion',\r\n            isNotFor: ['Timbo'],\r\n            func(sprite, script) {\r\n                const port = Number(script.getField('PORT'));\r\n                Entry.hw.setDigitalPortValue(port + 1, 5);\r\n                return script.callReturn();\r\n            },\r\n        },\r\n\r\n        timbo_check_motion: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        ['1', '1'],\r\n                        ['2', '2'],\r\n                        ['3', '3'],\r\n                        ['4', '4'],\r\n                        ['5', '5'],\r\n                        ['6', '6'],\r\n                        ['7', '7'],\r\n                    ],\r\n                    value: '1',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [null],\r\n                type: 'timbo_check_motion',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 1,\r\n            },\r\n            class: 'timbo_motion_value',\r\n            isNotFor: ['Timbo'],\r\n            func(sprite, script) {\r\n                const port = Number(script.getField('PORT'));\r\n                return Entry.hw.getDigitalPortValue(port + 1);\r\n            },\r\n        },\r\n\r\n        timbo_check_queen: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_boolean_field',\r\n            statements: [],\r\n            params: [],\r\n            events: {},\r\n            def: {\r\n                params: [],\r\n                type: 'timbo_check_queen',\r\n            },\r\n\r\n            class: 'timbo_motion_value',\r\n            isNotFor: ['Timbo'],\r\n            func(sprite, script) {\r\n                return Entry.hw.getDigitalPortValue(1);\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.Timbo;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_truerobot.js",
    "content": "'use strict';\r\n\r\nEntry.trueRobot = {\r\n    id: '19.1',\r\n    name: 'trueRobot',\r\n    url: 'http://www.i-screammedia.co.kr',\r\n    imageName: 'truetrue.png',\r\n    delayTime: 30,\r\n    title: {\r\n        ko: '뚜루뚜루',\r\n        en: 'TrueTrueRobot',\r\n    },\r\n    PORT_MAP: {\r\n        singlemotor: 0x0a,\r\n        dualmotor: 0x0a,\r\n        colorled: 0x08,\r\n        leds: 0x46,\r\n        linetracer: 0x4c,\r\n        led_line: 0x05,\r\n        leftWheel: 0x09,\r\n        rightWheel: 0x0a,\r\n        allWheel: 0x0b,\r\n        colorRed: 0,\r\n        colorGreen: 0,\r\n        colorBlue: 0,\r\n        ledPort: 0,\r\n        dualPort: 11,\r\n        linePort: 0xf0,\r\n    },\r\n    setZero: function() {\r\n        Entry.hw.sendQueue['SET'] = {};\r\n\r\n        Entry.hw.sendQueue.leftValue = 0;\r\n        Entry.hw.sendQueue.rightValue = 0;\r\n        Entry.hw.sendQueue['SET'][Entry.trueRobot.PORT_MAP.dualmotor] = {\r\n            port: Entry.trueRobot.PORT_MAP.dualPort,\r\n            dataA: 0,\r\n            dataB: 0,\r\n            dataC: 1,\r\n        };\r\n\r\n        Entry.hw.update();\r\n\r\n        Entry.hw.sendQueue['SET'][Entry.trueRobot.PORT_MAP.colorled] = {\r\n            port: Entry.trueRobot.PORT_MAP.colorled,\r\n            dataA: 0,\r\n            dataB: 0,\r\n            dataC: 255,\r\n        };\r\n\r\n        Entry.hw.update();\r\n\r\n        Entry.hw.sendQueue['SET'] = {};\r\n        Entry.hw.sendQueue['SET'][Entry.trueRobot.PORT_MAP.linetracer] = {\r\n            port: Entry.trueRobot.PORT_MAP.led_line,\r\n            dataA: 0,\r\n            dataB: 0x07,\r\n            dataC: 0x07,\r\n        };\r\n\r\n        Entry.hw.update();\r\n\r\n        var portArray = new Array(4, 9, 10);\r\n\r\n        Entry.hw.sendQueue['SET'] = {};\r\n\r\n        var settimer = 100;\r\n        for (var port in portArray) {\r\n            var tempport = 0;\r\n\r\n            setTimeout(function() {\r\n                Entry.hw.sendQueue['SET'][Entry.trueRobot.PORT_MAP.leds] = {\r\n                    port: portArray[tempport],\r\n                    dataA: 1,\r\n                    dataB: 0x07,\r\n                    dataC: 0x07,\r\n                };\r\n\r\n                Entry.hw.update();\r\n                tempport++;\r\n                settimer = settimer + 30;\r\n            }, settimer);\r\n        }\r\n    },\r\n    monitorTemplate: {\r\n        imgPath: 'hw/truebot.png',\r\n        width: 254,\r\n        height: 377,\r\n        listPorts: {\r\n            AccX: {\r\n                name: 'acc X',\r\n                type: 'input',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            AccY: {\r\n                name: 'acc Y',\r\n                type: 'input',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            AccZ: {\r\n                name: 'acc Z',\r\n                type: 'input',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            AccStatus: {\r\n                name: 'acc Tilt',\r\n                type: 'input',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            BColorRed: {\r\n                name: 'bottom R Value',\r\n                type: 'input',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            BColorGreen: {\r\n                name: 'bottom G Value',\r\n                type: 'input',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            BColorBlue: {\r\n                name: 'bottom B Value',\r\n                type: 'input',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            BColorKey: {\r\n                name: 'bottom Color Key',\r\n                type: 'input',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            leftValue: {\r\n                name: 'leftValue',\r\n                type: 'output',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n            rightValue: {\r\n                name: 'rightValue',\r\n                type: 'output',\r\n                pos: { x: 0, y: 0 },\r\n            },\r\n        },\r\n        ports: {\r\n            FColorLeftKey: {\r\n                name: 'frontcolor Left',\r\n                type: 'input',\r\n                pos: { x: 135, y: 170 },\r\n            },\r\n            FColorRightKey: {\r\n                name: 'frontcolor Right',\r\n                type: 'input',\r\n                pos: { x: 115, y: 170 },\r\n            },\r\n            ProxiRight: {\r\n                name: 'proxi right',\r\n                type: 'input',\r\n                pos: { x: 102, y: 260 },\r\n            },\r\n            ProxiLeft: {\r\n                name: 'proxi left',\r\n                type: 'input',\r\n                pos: { x: 155, y: 260 },\r\n            },\r\n\r\n            L2: {\r\n                name: 'line Left Out',\r\n                type: 'input',\r\n                pos: { x: 50, y: 360 },\r\n            },\r\n            L1: {\r\n                name: 'line Left In',\r\n                type: 'input',\r\n                pos: { x: 80, y: 360 },\r\n            },\r\n            R1: {\r\n                name: 'line Right In',\r\n                type: 'input',\r\n                pos: { x: 170, y: 360 },\r\n            },\r\n            R2: {\r\n                name: 'line Right Out',\r\n                type: 'input',\r\n                pos: { x: 200, y: 360 },\r\n            },\r\n        },\r\n        mode: 'both',\r\n    },\r\n};\r\n\r\nEntry.trueRobot.blockMenuBlocks = [\r\n    //truetrue\r\n    'truetrue_get_linesensor',\r\n    'truetrue_get_proxisensor',\r\n    'truetrue_get_accsensor',\r\n    'truetrue_get_bottomcolorsensor',\r\n    'truetrue_get_frontcolorsensor',\r\n    'truetrue_set_singlemotor',\r\n    'truetrue_set_dualmotor',\r\n    'truetrue_set_colorled',\r\n    'truetrue_set_led_proxi',\r\n    'truetrue_set_led_colorsensor',\r\n    'truetrue_set_led_linesensor',\r\n    'truetrue_set_linetracer',\r\n    'truetrue_set_head_colorled',\r\n    'truetrue_set_move',\r\n    'truetrue_set_sec_move',\r\n    'truetrue_set_rotate',\r\n    'truetrue_set_sec_rotate',\r\n    'truetrue_set_grid_block',\r\n    'truetrue_set_grid_rotate',\r\n];\r\n\r\nEntry.trueRobot.getBlocks = function() {\r\n    return {\r\n        //region TrueTrueRobot 뚜루뚜루로봇\r\n        truetrue_get_linesensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_left + ' 2', 'L2'],\r\n                        [Lang.Blocks.truetruebot_left + ' 1', 'L1'],\r\n                        [Lang.Blocks.truetruebot_right + ' 1', 'R1'],\r\n                        [Lang.Blocks.truetruebot_right + ' 2', 'R2'],\r\n                    ],\r\n                    value: 'Left_Out',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['L2'],\r\n                type: 'truetrue_get_linesensor',\r\n            },\r\n            paramsKeyMap: {\r\n                position: 0,\r\n            },\r\n            class: 'trueRobot_sensor',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var pd = Entry.hw.portData;\r\n                var dev = script.getField('position');\r\n                return pd[dev];\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.get_linesensor(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_left + ' 2', 'L2'],\r\n                                    [Lang.Blocks.truetruebot_left + ' 1', 'L1'],\r\n                                    [Lang.Blocks.truetruebot_right + ' 1', 'R1'],\r\n                                    [Lang.Blocks.truetruebot_right + ' 2', 'R2'],\r\n                                ],\r\n                                value: 'Left_Out',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_get_proxisensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_left, 'ProxiLeft'],\r\n                        [Lang.Blocks.truetruebot_right, 'ProxiRight'],\r\n                    ],\r\n                    value: 'Left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['ProxiLeft'],\r\n                type: 'truetrue_get_proxisensor',\r\n            },\r\n            paramsKeyMap: {\r\n                position: 0,\r\n            },\r\n            class: 'trueRobot_sensor',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var pd = Entry.hw.portData;\r\n                var dev = script.getField('position');\r\n\r\n                Entry.trueRobot.monitorTemplate.listPorts.temperature = pd[dev];\r\n\r\n                return pd[dev];\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.get_proxisensor(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_left, 'ProxiLeft'],\r\n                                    [Lang.Blocks.truetruebot_right, 'ProxiRight'],\r\n                                ],\r\n                                value: 'Left',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_get_accsensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_Xaxis, 'AccX'],\r\n                        [Lang.Blocks.truetruebot_Yaxis, 'AccY'],\r\n                        [Lang.Blocks.truetruebot_Zaxis, 'AccZ'],\r\n                        [Lang.Blocks.truetruebot_Tilt, 'AccStatus'],\r\n                    ],\r\n                    value: 'X-axis',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['AccX'],\r\n                type: 'truetrue_get_accsensor',\r\n            },\r\n            paramsKeyMap: {\r\n                position: 0,\r\n            },\r\n            class: 'trueRobot_sensor',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var pd = Entry.hw.portData;\r\n                var dev = script.getField('position');\r\n\r\n                return pd[dev];\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.get_accsensor(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_Xaxis, 'AccX'],\r\n                                    [Lang.Blocks.truetruebot_Yaxis, 'AccY'],\r\n                                    [Lang.Blocks.truetruebot_Zaxis, 'AccZ'],\r\n                                    [Lang.Blocks.truetruebot_Tilt, 'AccStatus'],\r\n                                ],\r\n                                value: 'X-axis',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_get_bottomcolorsensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_head_color_red, 'BColorRed'],\r\n                        [Lang.Blocks.truetruebot_head_color_green, 'BColorGreen'],\r\n                        [Lang.Blocks.truetruebot_head_color_blue, 'BColorBlue'],\r\n                        [Lang.Blocks.truetruebot_ColorKey, 'BColorKey'],\r\n                    ],\r\n                    value: 'Red',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['BColorRed'],\r\n                type: 'truetrue_get_bottomcolorsensor',\r\n            },\r\n            paramsKeyMap: {\r\n                position: 0,\r\n            },\r\n            class: 'trueRobot_sensor',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var pd = Entry.hw.portData;\r\n                var dev = script.getField('position');\r\n\r\n                return pd[dev];\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.get_bottomcolorsensor(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_head_color_red, 'BColorRed'],\r\n                                    [Lang.Blocks.truetruebot_head_color_green, 'BColorGreen'],\r\n                                    [Lang.Blocks.truetruebot_head_color_blue, 'BColorBlue'],\r\n                                    [Lang.Blocks.truetruebot_ColorKey, 'BColorKey'],\r\n                                ],\r\n                                value: 'Red',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_get_frontcolorsensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            fontColor: '#fff',\r\n            skeleton: 'basic_string_field',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_left, 'FColorLeftKey'],\r\n                        [Lang.Blocks.truetruebot_right, 'FColorRightKey'],\r\n                    ],\r\n                    value: 'Left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['FColorLeftKey'],\r\n                type: 'truetrue_get_frontcolorsensor',\r\n            },\r\n            paramsKeyMap: {\r\n                position: 0,\r\n            },\r\n            class: 'trueRobot_sensor',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var pd = Entry.hw.portData;\r\n                var dev = script.getField('position');\r\n\r\n                return pd[dev];\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.get_frontcolorsensor(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_left, 'FColorLeftKey'],\r\n                                    [Lang.Blocks.truetruebot_right, 'FColorRightKey'],\r\n                                ],\r\n                                value: 'Left',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_singlemotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_left, '9'],\r\n                        [Lang.Blocks.truetruebot_right, '10'],\r\n                        ['All', '11'],\r\n                    ],\r\n                    value: 'Left',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['9', '0', null],\r\n                type: 'truetrue_set_singlemotor',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                VALUE: 1,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.singlemotor;\r\n                var value = script.getNumberValue('VALUE');\r\n                value = Math.round(value);\r\n                value = Math.max(value, -100);\r\n                value = Math.min(value, 100);\r\n                //set two bytes.\r\n                var speed = 0;\r\n                var direction = 0;\r\n                if (value < 0) {\r\n                    speed = -1 * value;\r\n                    direction = 1;\r\n                } else {\r\n                    speed = value;\r\n                    direction = 0;\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    if (script.getNumberField('PORT') == 11) {\r\n                        device = Entry.trueRobot.PORT_MAP.dualmotor;\r\n                        Entry.hw.sendQueue['SET'][device] = {\r\n                            port: script.getNumberField('PORT'),\r\n                            dataA: value,\r\n                            dataB: value,\r\n                            dataC: 1,\r\n                        };\r\n                    } else {\r\n                        Entry.hw.sendQueue['SET'][device] = {\r\n                            port: script.getNumberField('PORT'),\r\n                            dataA: speed,\r\n                            dataB: direction,\r\n                            dataC: 0,\r\n                        };\r\n                    }\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_singlemotor(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_left, '9'],\r\n                                    [Lang.Blocks.truetruebot_right, '10'],\r\n                                    ['All', '11'],\r\n                                ],\r\n                                value: 'Left',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_dualmotor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['0', '0', '1', null],\r\n                type: 'truetrue_set_dualmotor',\r\n            },\r\n            paramsKeyMap: {\r\n                leftValue: 0,\r\n                rightValue: 1,\r\n                delayValue: 2,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.dualmotor;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    var leftValue = script.getNumberValue('leftValue');\r\n                    leftValue = Math.round(leftValue);\r\n                    leftValue = Math.max(leftValue, -100);\r\n                    leftValue = Math.min(leftValue, 100);\r\n\r\n                    var rightValue = script.getNumberValue('rightValue');\r\n                    rightValue = Math.round(rightValue);\r\n                    rightValue = Math.max(rightValue, -100);\r\n                    rightValue = Math.min(rightValue, 100);\r\n\r\n                    var delayValue = script.getNumberValue('delayValue');\r\n                    delayValue = Math.round(delayValue);\r\n                    delayValue = Math.max(delayValue, -100);\r\n                    delayValue = Math.min(delayValue, 100);\r\n\r\n                    Entry.hw.sendQueue.leftValue = leftValue;\r\n                    Entry.hw.sendQueue.rightValue = rightValue;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: leftValue,\r\n                        dataB: rightValue,\r\n                        dataC: delayValue,\r\n                    };\r\n\r\n                    var timeValue = script.getNumberValue('delayValue');\r\n\r\n                    if (timeValue == 0) {\r\n                        var myTimer = setTimeout(function() {\r\n                            script.timeFlag = 2;\r\n                        }, Entry.trueRobot.delayTime);\r\n                        return script;\r\n                    }\r\n\r\n                    timeValue = Math.round(timeValue);\r\n                    timeValue = Math.max(timeValue, -100);\r\n                    timeValue = Math.min(timeValue, 100);\r\n                    var fps = Entry.FPS || 60;\r\n                    timeValue = (60 / fps) * timeValue * 1000;\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                } else {\r\n                    Entry.engine.isContinue = false;\r\n                    Entry.hw.sendQueue.leftValue = 0;\r\n                    Entry.hw.sendQueue.rightValue = 0;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: 0,\r\n                        dataB: 0,\r\n                        dataC: 0,\r\n                    };\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_dualmotor(%1, %2 , %3)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_colorled: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['0', '0', '0', null],\r\n                type: 'truetrue_set_colorled',\r\n            },\r\n            paramsKeyMap: {\r\n                redColor: 0,\r\n                greenColor: 1,\r\n                blueColor: 2,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.colorled;\r\n\r\n                var redColor = script.getNumberValue('redColor');\r\n                redColor = Math.round(redColor);\r\n                redColor = Math.max(redColor, 0);\r\n                redColor = Math.min(redColor, 255);\r\n\r\n                var greenColor = script.getNumberValue('greenColor');\r\n                greenColor = Math.round(greenColor);\r\n                greenColor = Math.max(greenColor, 0);\r\n                greenColor = Math.min(greenColor, 255);\r\n\r\n                var blueColor = script.getNumberValue('blueColor');\r\n                blueColor = Math.round(blueColor);\r\n                blueColor = Math.max(blueColor, 0);\r\n                blueColor = Math.min(blueColor, 255);\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.colorled,\r\n                        dataA: redColor,\r\n                        dataB: greenColor,\r\n                        dataC: blueColor,\r\n                    };\r\n\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_colorled(%1, %2 , %3)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_led_proxi: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_front_near_left, 9],\r\n                        [Lang.Blocks.truetruebot_front_near_right, 10],\r\n                    ],\r\n                    value: 9,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_on, 'on'],\r\n                        [Lang.Blocks.truetruebot_off, 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [9, 'on', null],\r\n                type: 'truetrue_set_led_proxi',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                ONOFF: 1,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.leds;\r\n\r\n                var onoff = script.getField('ONOFF');\r\n                var value = onoff == 'on' ? 1 : 0;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: script.getNumberField('PORT'),\r\n                        dataA: value,\r\n                        dataB: 0x07,\r\n                        dataC: 0x07,\r\n                    };\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_led_proxi(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_front_near_left, 9],\r\n                                    [Lang.Blocks.truetruebot_front_near_right, 10],\r\n                                ],\r\n                                value: 9,\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_on, 'on'],\r\n                                    [Lang.Blocks.truetruebot_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_led_colorsensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_front_color, 3],\r\n                        [Lang.Blocks.truetruebot_bottom_color, 4],\r\n                    ],\r\n                    value: 3,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_on, 'on'],\r\n                        [Lang.Blocks.truetruebot_off, 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [3, 'on', null],\r\n                type: 'truetrue_set_led_colorsensor',\r\n            },\r\n            paramsKeyMap: {\r\n                PORT: 0,\r\n                ONOFF: 1,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.leds;\r\n\r\n                var onoff = script.getField('ONOFF');\r\n                var value = onoff == 'on' ? 1 : 0;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: script.getNumberField('PORT'),\r\n                        dataA: value,\r\n                        dataB: 0x07,\r\n                        dataC: 0x07,\r\n                    };\r\n\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_led_colorsensor(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_front_color, 3],\r\n                                    [Lang.Blocks.truetruebot_bottom_color, 4],\r\n                                ],\r\n                                value: 3,\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_on, 'on'],\r\n                                    [Lang.Blocks.truetruebot_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_led_linesensor: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_on, 'on'],\r\n                        [Lang.Blocks.truetruebot_off, 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['on', null],\r\n                type: 'truetrue_set_led_linesensor',\r\n            },\r\n            paramsKeyMap: {\r\n                ONOFF: 0,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.leds;\r\n\r\n                var onoff = script.getField('ONOFF');\r\n                var value = onoff == 'on' ? 1 : 0;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.led_line,\r\n                        dataA: value,\r\n                        dataB: 0x07,\r\n                        dataC: 0x07,\r\n                    };\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_led_linesensor(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_on, 'on'],\r\n                                    [Lang.Blocks.truetruebot_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_linetracer: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_on, 'on'],\r\n                        [Lang.Blocks.truetruebot_off, 'off'],\r\n                    ],\r\n                    value: 'on',\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['on', null],\r\n                type: 'truetrue_set_linetracer',\r\n            },\r\n            paramsKeyMap: {\r\n                ONOFF: 0,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.linetracer;\r\n\r\n                var onoff = script.getField('ONOFF');\r\n                var value = onoff == 'on' ? 1 : 0;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.led_line,\r\n                        dataA: value,\r\n                        dataB: 0x07,\r\n                        dataC: 0x07,\r\n                    };\r\n\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_linetracer(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_on, 'on'],\r\n                                    [Lang.Blocks.truetruebot_off, 'off'],\r\n                                ],\r\n                                value: 'on',\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_head_colorled: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_head_color_white, 101],\r\n                        [Lang.Blocks.truetruebot_head_color_red, 102],\r\n                        [Lang.Blocks.truetruebot_head_color_green, 103],\r\n                        [Lang.Blocks.truetruebot_head_color_blue, 104],\r\n                        [Lang.Blocks.truetruebot_head_color_cyan, 105],\r\n                        [Lang.Blocks.truetruebot_head_color_magenta, 106],\r\n                        [Lang.Blocks.truetruebot_head_color_yellow, 107],\r\n                        [Lang.Blocks.truetruebot_head_color_off, 100],\r\n                    ],\r\n                    value: 101,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [101, null],\r\n                type: 'truetrue_set_head_colorled',\r\n            },\r\n            paramsKeyMap: {\r\n                headColor: 0,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.colorled;\r\n\r\n                var headColor = script.getField('headColor');\r\n\r\n                var redColor;\r\n                var greenColor;\r\n                var blueColor;\r\n\r\n                if (headColor == 101) {\r\n                    redColor = 255;\r\n                    greenColor = 255;\r\n                    blueColor = 255;\r\n                } else if (headColor == 102) {\r\n                    redColor = 255;\r\n                    greenColor = 0;\r\n                    blueColor = 0;\r\n                } else if (headColor == 103) {\r\n                    redColor = 0;\r\n                    greenColor = 255;\r\n                    blueColor = 0;\r\n                } else if (headColor == 104) {\r\n                    redColor = 0;\r\n                    greenColor = 0;\r\n                    blueColor = 255;\r\n                } else if (headColor == 105) {\r\n                    redColor = 0;\r\n                    greenColor = 255;\r\n                    blueColor = 255;\r\n                } else if (headColor == 106) {\r\n                    redColor = 255;\r\n                    greenColor = 0;\r\n                    blueColor = 255;\r\n                } else if (headColor == 107) {\r\n                    redColor = 255;\r\n                    greenColor = 255;\r\n                    blueColor = 0;\r\n                } else if (headColor == 100) {\r\n                    redColor = 0;\r\n                    greenColor = 0;\r\n                    blueColor = 0;\r\n                }\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.colorled,\r\n                        dataA: redColor,\r\n                        dataB: greenColor,\r\n                        dataC: blueColor,\r\n                    };\r\n\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_head_colorled(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_head_color_white, 101],\r\n                                    [Lang.Blocks.truetruebot_head_color_red, 102],\r\n                                    [Lang.Blocks.truetruebot_head_color_green, 103],\r\n                                    [Lang.Blocks.truetruebot_head_color_blue, 104],\r\n                                    [Lang.Blocks.truetruebot_head_color_cyan, 105],\r\n                                    [Lang.Blocks.truetruebot_head_color_magenta, 106],\r\n                                    [Lang.Blocks.truetruebot_head_color_yellow, 107],\r\n                                    [Lang.Blocks.truetruebot_head_color_off, 100],\r\n                                ],\r\n                                value: 101,\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_move: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_move_forward, 101],\r\n                        [Lang.Blocks.truetruebot_move_backward, 102],\r\n                    ],\r\n                    value: 101,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [101, null],\r\n                type: 'truetrue_set_move',\r\n            },\r\n            paramsKeyMap: {\r\n                moveValue: 0,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.dualmotor;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    var moveValue = script.getField('moveValue');\r\n                    var leftValue;\r\n                    var rightValue;\r\n                    var delayValue;\r\n\r\n                    if (moveValue == 101) {\r\n                        leftValue = 100;\r\n                        rightValue = 100;\r\n                        delayValue = 0;\r\n                    } else if (moveValue == 102) {\r\n                        leftValue = -100;\r\n                        rightValue = -100;\r\n                        delayValue = 0;\r\n                    }\r\n\r\n                    Entry.hw.sendQueue.leftValue = leftValue;\r\n                    Entry.hw.sendQueue.rightValue = rightValue;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: leftValue,\r\n                        dataB: rightValue,\r\n                        dataC: delayValue,\r\n                    };\r\n\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_move(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_move_forward, 101],\r\n                                    [Lang.Blocks.truetruebot_move_backward, 102],\r\n                                ],\r\n                                value: 101,\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_sec_move: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_move_forward, 101],\r\n                        [Lang.Blocks.truetruebot_move_backward, 102],\r\n                    ],\r\n                    value: 101,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [101, '1', null],\r\n                type: 'truetrue_set_sec_move',\r\n            },\r\n            paramsKeyMap: {\r\n                moveValue: 0,\r\n                delayValue: 1,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.dualmotor;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                var timeValue = script.getNumberValue('delayValue');\r\n                var delayValue = script.getNumberValue('delayValue');\r\n\r\n                if (delayValue == 0) {\r\n                    script.isStart = true;\r\n                }\r\n\r\n                delayValue = Math.round(delayValue);\r\n                delayValue = Math.max(delayValue, -100);\r\n                delayValue = Math.min(delayValue, 100);\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    var moveValue = script.getField('moveValue');\r\n                    var leftValue;\r\n                    var rightValue;\r\n\r\n                    if (moveValue == 101) {\r\n                        leftValue = 100;\r\n                        rightValue = 100;\r\n                    } else if (moveValue == 102) {\r\n                        leftValue = -100;\r\n                        rightValue = -100;\r\n                    }\r\n                    Entry.hw.sendQueue.leftValue = leftValue;\r\n                    Entry.hw.sendQueue.rightValue = rightValue;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: leftValue,\r\n                        dataB: rightValue,\r\n                        dataC: delayValue,\r\n                    };\r\n\r\n                    if (timeValue == 0) {\r\n                        var myTimer = setTimeout(function() {\r\n                            script.timeFlag = 2;\r\n                        }, Entry.trueRobot.delayTime);\r\n                        return script;\r\n                    }\r\n\r\n                    timeValue = Math.round(timeValue);\r\n                    timeValue = Math.max(timeValue, -100);\r\n                    timeValue = Math.min(timeValue, 100);\r\n                    var fps = Entry.FPS || 60;\r\n                    timeValue = (60 / fps) * timeValue * 1000;\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                } else {\r\n                    Entry.engine.isContinue = false;\r\n                    Entry.hw.sendQueue.leftValue = 0;\r\n                    Entry.hw.sendQueue.rightValue = 0;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: 0,\r\n                        dataB: 0,\r\n                        dataC: 0,\r\n                    };\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_sec_move(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_move_forward, 101],\r\n                                    [Lang.Blocks.truetruebot_move_backward, 102],\r\n                                ],\r\n                                value: 101,\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_rotate: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_move_right, 101],\r\n                        [Lang.Blocks.truetruebot_move_left, 102],\r\n                    ],\r\n                    value: 101,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [101, null],\r\n                type: 'truetrue_set_rotate',\r\n            },\r\n            paramsKeyMap: {\r\n                moveValue: 0,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.dualmotor;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    var moveValue = script.getField('moveValue');\r\n                    var leftValue;\r\n                    var rightValue;\r\n                    var delayValue;\r\n\r\n                    if (moveValue == 101) {\r\n                        leftValue = 100;\r\n                        rightValue = -100;\r\n                        delayValue = 0;\r\n                    } else if (moveValue == 102) {\r\n                        leftValue = -100;\r\n                        rightValue = 100;\r\n                        delayValue = 0;\r\n                    }\r\n                    Entry.hw.sendQueue.leftValue = leftValue;\r\n                    Entry.hw.sendQueue.rightValue = rightValue;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: leftValue,\r\n                        dataB: rightValue,\r\n                        dataC: delayValue,\r\n                    };\r\n\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_rotate(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_move_right, 101],\r\n                                    [Lang.Blocks.truetruebot_move_left, 102],\r\n                                ],\r\n                                value: 101,\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n        truetrue_set_sec_rotate: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_move_right, 101],\r\n                        [Lang.Blocks.truetruebot_move_left, 102],\r\n                    ],\r\n                    value: 101,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [101, '1', null],\r\n                type: 'truetrue_set_sec_rotate',\r\n            },\r\n            paramsKeyMap: {\r\n                moveValue: 0,\r\n                delayValue: 1,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.dualmotor;\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                var timeValue = script.getNumberValue('delayValue');\r\n                var delayValue = script.getNumberValue('delayValue');\r\n\r\n                if (delayValue == 0) {\r\n                    script.isStart = true;\r\n                }\r\n\r\n                delayValue = Math.round(delayValue);\r\n                delayValue = Math.max(delayValue, -100);\r\n                delayValue = Math.min(delayValue, 100);\r\n\r\n                if (!script.isStart) {\r\n                    script.isStart = true;\r\n                    script.timeFlag = 1;\r\n\r\n                    var moveValue = script.getField('moveValue');\r\n                    var leftValue;\r\n                    var rightValue;\r\n\r\n                    if (moveValue == 101) {\r\n                        leftValue = 50;\r\n                        rightValue = -20;\r\n                    } else if (moveValue == 102) {\r\n                        leftValue = -20;\r\n                        rightValue = 50;\r\n                    }\r\n                    Entry.hw.sendQueue.leftValue = leftValue;\r\n                    Entry.hw.sendQueue.rightValue = rightValue;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: leftValue,\r\n                        dataB: rightValue,\r\n                        dataC: delayValue,\r\n                    };\r\n\r\n                    if (timeValue == 0) {\r\n                        var myTimer = setTimeout(function() {\r\n                            script.timeFlag = 2;\r\n                        }, Entry.trueRobot.delayTime);\r\n                        return script;\r\n                    }\r\n\r\n                    timeValue = Math.round(timeValue);\r\n                    timeValue = Math.max(timeValue, -100);\r\n                    timeValue = Math.min(timeValue, 100);\r\n                    var fps = Entry.FPS || 60;\r\n                    timeValue = (60 / fps) * timeValue * 1000;\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 0;\r\n                    }, timeValue);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    delete script.timeFlag;\r\n                    delete script.isStart;\r\n                    Entry.engine.isContinue = false;\r\n                    return script.callReturn();\r\n                } else {\r\n                    Entry.engine.isContinue = false;\r\n                    Entry.hw.sendQueue.leftValue = 0;\r\n                    Entry.hw.sendQueue.rightValue = 0;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: 0,\r\n                        dataB: 0,\r\n                        dataC: 0,\r\n                    };\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = 2;\r\n                    }, Entry.trueRobot.delayTime);\r\n                    return script;\r\n                }\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_sec_rotate(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_move_right, 101],\r\n                                    [Lang.Blocks.truetruebot_move_left, 102],\r\n                                ],\r\n                                value: 101,\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        truetrue_set_grid_block: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: ['1', null],\r\n                type: 'truetrue_set_grid_block',\r\n            },\r\n            paramsKeyMap: {\r\n                gridValue: 0,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.dualmotor;\r\n                var pd = Entry.hw.portData;\r\n                var leftValue;\r\n                var rightValue;\r\n                var delayValue = 0;\r\n                var gridValue = script.getNumberValue('gridValue');\r\n                if (!script.isStart) {\r\n                    script.flag = 0;\r\n                    script.stop = 0;\r\n                    script.checkCount = 0;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 0;\r\n                    script.bufferFlag = 2;\r\n                }\r\n\r\n                if (gridValue == 0) {\r\n                    script.timeFlag = 3;\r\n                }\r\n\r\n                if (script.timeFlag == 0) {\r\n                    script.timeFlag = 1;\r\n\r\n                    if (pd['L1'] > 110 && pd['R1'] > 110) {\r\n                        leftValue = 100;\r\n                        rightValue = 100;\r\n                    } else if (pd['L1'] >= 0 || pd['R1'] >= 0) {\r\n                        if (pd['L1'] > pd['R1'] - 20) {\r\n                            leftValue = 100;\r\n                            rightValue = pd['L1'] - pd['R1'];\r\n\r\n                            // var maxright = rightValue;\r\n\r\n                            rightValue = Math.max(\r\n                                Math.min(Math.round(100 - (100 * rightValue) / 230), 100),\r\n                                30\r\n                            );\r\n                        } else if (pd['R1'] > pd['L1'] - 20) {\r\n                            leftValue = pd['R1'] - pd['L1'];\r\n\r\n                            leftValue = Math.max(\r\n                                Math.min(Math.round(100 - (100 * leftValue) / 230), 100),\r\n                                30\r\n                            );\r\n\r\n                            rightValue = 100;\r\n                        } else {\r\n                            leftValue = 100;\r\n                            rightValue = 100;\r\n                        }\r\n                    } else {\r\n                        leftValue = 100;\r\n                        rightValue = 100;\r\n                    }\r\n                    //console.log( script.tempcheck +\"//\"+ pd['L2'] +\" :: \"+ pd['L1'] +\" :: \"+ pd['R1'] +\" :: \"+ pd['R2'] );\r\n                    if (\r\n                        pd['L1'] >= 0 &&\r\n                        pd['R1'] >= 0 &&\r\n                        pd['L2'] > 0 &&\r\n                        pd['R2'] > 0 &&\r\n                        pd['L2'] + pd['L1'] >= 130 &&\r\n                        pd['R2'] + pd['R1'] >= 130\r\n                    ) {\r\n                        if (script.flag == 1) {\r\n                            script.checkCount++;\r\n                            script.flag = 0;\r\n\r\n                            if (script.checkCount < gridValue) {\r\n                                Entry.hw.sendQueue.leftValue = 0;\r\n                                Entry.hw.sendQueue.rightValue = 0;\r\n                                Entry.hw.sendQueue['SET'][device] = {\r\n                                    port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                                    dataA: 0,\r\n                                    dataB: 0,\r\n                                    dataC: 1,\r\n                                };\r\n\r\n                                script.timeFlag = 1;\r\n\r\n                                var myTimer = setTimeout(function() {\r\n                                    script.timeFlag = 0;\r\n                                }, 200);\r\n\r\n                                return script;\r\n                            }\r\n                        }\r\n                        if (script.checkCount >= gridValue) {\r\n                            if (\r\n                                pd['L1'] < 170 &&\r\n                                pd['R1'] < 170 &&\r\n                                pd['L2'] < 170 &&\r\n                                pd['R2'] < 170\r\n                            ) {\r\n                                script.stop = 1;\r\n                            } else {\r\n                                script.stop = 1;\r\n                            }\r\n                        }\r\n                    } else {\r\n                        script.flag = 1;\r\n                    }\r\n\r\n                    if (script.stop == 1 && script.flag == 1) {\r\n                        script.timeFlag = 1;\r\n                        script.bufferFlag = 3;\r\n\r\n                        var myTimer = setTimeout(function() {\r\n                            script.timeFlag = script.bufferFlag;\r\n                        }, 80);\r\n                        return script;\r\n                    }\r\n\r\n                    if (!Entry.hw.sendQueue['SET']) {\r\n                        Entry.hw.sendQueue['SET'] = {};\r\n                    }\r\n                    Entry.hw.sendQueue.leftValue = leftValue;\r\n                    Entry.hw.sendQueue.rightValue = rightValue;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: leftValue,\r\n                        dataB: rightValue,\r\n                        dataC: delayValue,\r\n                    };\r\n\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = script.bufferFlag;\r\n                    }, Entry.trueRobot.delayTime / 2);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    script.timeFlag = 0;\r\n                    return script;\r\n                } else if (script.timeFlag == 3) {\r\n                    clearTimeout(myTimer);\r\n                    Entry.hw.sendQueue.leftValue = 0;\r\n                    Entry.hw.sendQueue.rightValue = 0;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: 0,\r\n                        dataB: 0,\r\n                        dataC: 1,\r\n                    };\r\n\r\n                    return script.callReturn();\r\n                }\r\n\r\n                return script;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_grid_block(%1)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n\r\n        truetrue_set_grid_rotate: {\r\n            color: EntryStatic.colorSet.block.default.HARDWARE,\r\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\r\n            skeleton: 'basic',\r\n            statements: [],\r\n            params: [\r\n                {\r\n                    type: 'Dropdown',\r\n                    options: [\r\n                        [Lang.Blocks.truetruebot_move_right, 101],\r\n                        [Lang.Blocks.truetruebot_move_left, 102],\r\n                    ],\r\n                    value: 101,\r\n                    fontSize: 11,\r\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                },\r\n                {\r\n                    type: 'Block',\r\n                    accept: 'string',\r\n                },\r\n                {\r\n                    type: 'Indicator',\r\n                    img: 'block_icon/hardware_icon.svg',\r\n                    size: 12,\r\n                },\r\n            ],\r\n            events: {},\r\n            def: {\r\n                params: [101, '1', null],\r\n                type: 'truetrue_set_grid_rotate',\r\n            },\r\n            paramsKeyMap: {\r\n                moveValue: 0,\r\n                rotateValue: 1,\r\n            },\r\n            class: 'trueRobot_control',\r\n            isNotFor: ['trueRobot'],\r\n            func: function(sprite, script) {\r\n                var device = Entry.trueRobot.PORT_MAP.dualmotor;\r\n                var pd = Entry.hw.portData;\r\n                var leftValue;\r\n                var rightValue;\r\n                var delayValue;\r\n\r\n                var moveValue = script.getField('moveValue');\r\n                var rotateValue = script.getNumberValue('rotateValue');\r\n\r\n                if (!Entry.hw.sendQueue['SET']) {\r\n                    Entry.hw.sendQueue['SET'] = {};\r\n                }\r\n\r\n                if (!script.isStart) {\r\n                    script.flag = 0;\r\n                    script.stop = 0;\r\n                    script.checkCount = 0;\r\n                    script.isStart = true;\r\n                    script.timeFlag = 0;\r\n                    script.bufferFlag = 2;\r\n                    script.tempcheck = 0;\r\n                }\r\n\r\n                if (rotateValue == 0) {\r\n                    script.timeFlag = 3;\r\n                }\r\n\r\n                if (script.timeFlag == 0) {\r\n                    script.timeFlag = 1;\r\n\r\n                    if (moveValue == 101) {\r\n                        leftValue = 50;\r\n                        rightValue = -20;\r\n                        delayValue = 0;\r\n                    } else if (moveValue == 102) {\r\n                        leftValue = -20;\r\n                        rightValue = 50;\r\n                        delayValue = 0;\r\n                    }\r\n\r\n                    if (moveValue == 101) {\r\n                        if (\r\n                            (pd['L1'] > 170 ||\r\n                                (pd['L1'] + pd['L2'] > 170) & (pd['L1'] > pd['L2'])) &&\r\n                            pd['L2'] >= 0 &&\r\n                            pd['R2'] < 10 &&\r\n                            pd['R1'] < 10\r\n                        ) {\r\n                            if (script.flag == 1) {\r\n                                script.tempcheck = 1;\r\n                            }\r\n                        } else if (pd['L2'] > 0 && pd['L1'] < 10) {\r\n                            script.flag = 1;\r\n                        }\r\n                    } else if (moveValue == 102) {\r\n                        if (\r\n                            (pd['R1'] > 170 ||\r\n                                (pd['R1'] + pd['R2'] > 170) & (pd['R1'] > pd['R2'])) &&\r\n                            pd['R2'] >= 0 &&\r\n                            pd['L2'] < 10 &&\r\n                            pd['L1'] < 10\r\n                        ) {\r\n                            if (script.flag == 1) {\r\n                                script.tempcheck = 1;\r\n                            }\r\n                        } else if (pd['R2'] > 0 && pd['R1'] < 10) {\r\n                            script.flag = 1;\r\n                        }\r\n                    }\r\n                    //console.log( script.tempcheck +\"//\"+ pd['L2'] +\" :: \"+ pd['L1'] +\" :: \"+ pd['R1'] +\" :: \"+ pd['R2'] + \" script.tempcheck : \" + script.tempcheck + \" script.flag : \"+script.flag );\r\n\r\n                    if (script.tempcheck == 1 && pd['L1'] < 230) {\r\n                        script.tempcheck = 0;\r\n                        script.checkCount++;\r\n                        script.flag = 0;\r\n\r\n                        if (script.flag == 0 && script.checkCount < rotateValue) {\r\n                            Entry.hw.sendQueue.leftValue = 0;\r\n                            Entry.hw.sendQueue.rightValue = 0;\r\n                            Entry.hw.sendQueue['SET'][device] = {\r\n                                port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                                dataA: 0,\r\n                                dataB: 0,\r\n                                dataC: 1,\r\n                            };\r\n\r\n                            script.timeFlag = 1;\r\n                            //console.log( \"!!!!!!!!!!!\" );\r\n                            var myTimer = setTimeout(function() {\r\n                                script.timeFlag = 0;\r\n                            }, 200);\r\n\r\n                            return script;\r\n                        }\r\n                    }\r\n\r\n                    if (script.tempcheck == 1 && pd['R1'] < 230) {\r\n                        script.tempcheck = 0;\r\n                        script.checkCount++;\r\n                        script.flag = 0;\r\n\r\n                        if (script.flag == 0 && script.checkCount < rotateValue) {\r\n                            Entry.hw.sendQueue.leftValue = 0;\r\n                            Entry.hw.sendQueue.rightValue = 0;\r\n                            Entry.hw.sendQueue['SET'][device] = {\r\n                                port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                                dataA: 0,\r\n                                dataB: 0,\r\n                                dataC: 1,\r\n                            };\r\n\r\n                            script.timeFlag = 1;\r\n                            //console.log( \"!!!!!!!!!!!\" );\r\n                            var myTimer = setTimeout(function() {\r\n                                script.timeFlag = 0;\r\n                            }, 200);\r\n\r\n                            return script;\r\n                        }\r\n                    }\r\n\r\n                    if (script.checkCount >= rotateValue) {\r\n                        leftValue = 0;\r\n                        rightValue = 0;\r\n                        script.timeFlag = 1;\r\n                        script.bufferFlag = 3;\r\n                    }\r\n                    Entry.hw.sendQueue.leftValue = leftValue;\r\n                    Entry.hw.sendQueue.rightValue = rightValue;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: leftValue,\r\n                        dataB: rightValue,\r\n                        dataC: delayValue,\r\n                    };\r\n\r\n                    var myTimer = setTimeout(function() {\r\n                        script.timeFlag = script.bufferFlag;\r\n                    }, Entry.trueRobot.delayTime / 5);\r\n                    return script;\r\n                } else if (script.timeFlag == 1) {\r\n                    return script;\r\n                } else if (script.timeFlag == 2) {\r\n                    clearTimeout(myTimer);\r\n                    script.timeFlag = 0;\r\n                    return script;\r\n                } else if (script.timeFlag == 3) {\r\n                    clearTimeout(myTimer);\r\n                    Entry.hw.sendQueue.leftValue = 0;\r\n                    Entry.hw.sendQueue.rightValue = 0;\r\n                    Entry.hw.sendQueue['SET'][device] = {\r\n                        port: Entry.trueRobot.PORT_MAP.dualPort,\r\n                        dataA: 0,\r\n                        dataB: 0,\r\n                        dataC: 1,\r\n                    };\r\n\r\n                    return script.callReturn();\r\n                }\r\n\r\n                return script;\r\n            },\r\n            syntax: {\r\n                js: [],\r\n                py: [\r\n                    {\r\n                        syntax: 'trueRobot.set_grid_rotate(%1, %2)',\r\n                        textParams: [\r\n                            {\r\n                                type: 'Dropdown',\r\n                                options: [\r\n                                    [Lang.Blocks.truetruebot_move_right, 101],\r\n                                    [Lang.Blocks.truetruebot_move_left, 102],\r\n                                ],\r\n                                value: 101,\r\n                                fontSize: 11,\r\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\r\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\r\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\r\n                            },\r\n                            {\r\n                                type: 'Block',\r\n                                accept: 'string',\r\n                            },\r\n                        ],\r\n                    },\r\n                ],\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\n// 언어 적용\r\nEntry.trueRobot.setLanguage = function() {\r\n    return {\r\n        ko: {\r\n            // ko.js에 작성하던 내용\r\n            template: {\r\n                truetrue_get_accsensor: '가속도센서 %1 의 값',\r\n                truetrue_get_bottomcolorsensor: '바닥컬러센서 %1 의 값',\r\n                truetrue_get_frontcolorsensor: '전면컬러센서 %1 의 값',\r\n                truetrue_get_linesensor: '라인센서 %1 의 값',\r\n                truetrue_get_proxisensor: '근접센서 %1 의 값',\r\n                truetrue_set_colorled: '컬러LED Red %1  Green %2 Blue %3 로 설정 %4',\r\n                truetrue_set_dualmotor: 'DC모터 좌 %1  우 %2 속도로 %3 초 구동 %4',\r\n                truetrue_set_led_colorsensor: '%1 조명용 LED %2 %3',\r\n                truetrue_set_led_linesensor: '라인센서 조명용 LED %1 %2',\r\n                truetrue_set_led_proxi: '%1 조명용 LED %2 %3',\r\n                truetrue_set_linetracer: '라인트레이싱 모드 %1 %2',\r\n                truetrue_set_singlemotor: 'DC모터 %1  속도 %2 로 설정 %3',\r\n                truetrue_set_head_colorled: '머리 LED를 %1 로 변경 %2',\r\n                truetrue_set_move: '로봇을 %1 계속이동 %2',\r\n                truetrue_set_sec_move: '로봇을 %1  %2 초 이동 %3',\r\n                truetrue_set_rotate: '로봇을 %1 계속 회전 %2',\r\n                truetrue_set_sec_rotate: '로봇을 %1  %2 초 회전 %3',\r\n                truetrue_set_grid_block: '뚜루뚜루를 격자 %1 칸 만큼 이동 %2 ',\r\n                truetrue_set_grid_rotate: '뚜루뚜루를 격자에서 %1 %2 회 회전 %3 ',\r\n            },\r\n            Blocks: {\r\n                truetruebot_on: '켜기',\r\n                truetruebot_off: '끄기',\r\n                truetruebot_front_near_right: '근접센서오른쪽',\r\n                truetruebot_front_near_left: '근접센서왼쪽',\r\n                truetruebot_front_color: '전면컬러센서',\r\n                truetruebot_bottom_color: '바닥컬러센서',\r\n                truetruebot_head_color_white: '흰색',\r\n                truetruebot_head_color_red: '빨간색',\r\n                truetruebot_head_color_green: '초록색',\r\n                truetruebot_head_color_blue: '파란색',\r\n                truetruebot_head_color_cyan: '하늘색',\r\n                truetruebot_head_color_magenta: '자주색',\r\n                truetruebot_head_color_yellow: '노란색',\r\n                truetruebot_head_color_off: '끄기',\r\n                truetruebot_move_forward: '앞으로',\r\n                truetruebot_move_backward: '뒤로',\r\n                truetruebot_move_right: '오른쪽으로',\r\n                truetruebot_move_left: '왼쪽으로',\r\n                truetruebot_right: '오른쪽',\r\n                truetruebot_left: '왼쪽',\r\n                truetruebot_Xaxis: 'X축',\r\n                truetruebot_Yaxis: 'Y축',\r\n                truetruebot_Zaxis: 'Z축',\r\n                truetruebot_Tilt: '기울기',\r\n                truetruebot_ColorKey: '컬러키',\r\n            },\r\n        },\r\n        code: {\r\n            template: {\r\n                truetrue_get_accsensor: '가속도센서 %1 의 값',\r\n                truetrue_get_bottomcolorsensor: '바닥컬러센서 %1 의 값',\r\n                truetrue_get_frontcolorsensor: '전면컬러센서 %1 의 값',\r\n                truetrue_get_linesensor: '라인센서 %1 의 값',\r\n                truetrue_get_proxisensor: '근접센서 %1 의 값',\r\n                truetrue_set_colorled: '컬러LED Red %1  Green %2 Blue %3 로 설정 %4',\r\n                truetrue_set_dualmotor: 'DC모터 좌 %1  우 %2 속도로 %3 초 구동 %4',\r\n                truetrue_set_led_colorsensor: '%1 조명용 LED %2 %3',\r\n                truetrue_set_led_linesensor: '라인센서 조명용 LED %1 %2',\r\n                truetrue_set_led_proxi: '%1 조명용 LED %2 %3',\r\n                truetrue_set_linetracer: '라인트레이싱 모드 %1 %2',\r\n                truetrue_set_singlemotor: 'DC모터 %1  속도 %2 로 설정 %3',\r\n                truetrue_set_head_colorled: '머리 LED를 %1 로 변경 %2',\r\n                truetrue_set_move: '로봇을 %1 계속이동 %2',\r\n                truetrue_set_sec_move: '로봇을 %1  %2 초 이동 %3',\r\n                truetrue_set_rotate: '로봇을 %1 계속 회전 %2',\r\n                truetrue_set_sec_rotate: '로봇을 %1  %2 초 회전 %3',\r\n                truetrue_set_grid_block: '뚜루뚜루를 격자 %1 칸 만큼 이동 %2 ',\r\n                truetrue_set_grid_rotate: '뚜루뚜루를 격자에서 %1 %2 회 회전 %3 ',\r\n            },\r\n            Blocks: {\r\n                truetruebot_on: '켜기',\r\n                truetruebot_off: '끄기',\r\n                truetruebot_front_near_right: '근접센서오른쪽',\r\n                truetruebot_front_near_left: '근접센서왼쪽',\r\n                truetruebot_front_color: '전면컬러센서',\r\n                truetruebot_bottom_color: '바닥컬러센서',\r\n                truetruebot_head_color_white: '흰색',\r\n                truetruebot_head_color_red: '빨간색',\r\n                truetruebot_head_color_green: '초록색',\r\n                truetruebot_head_color_blue: '파란색',\r\n                truetruebot_head_color_cyan: '하늘색',\r\n                truetruebot_head_color_magenta: '자주색',\r\n                truetruebot_head_color_yellow: '노란색',\r\n                truetruebot_head_color_off: '끄기',\r\n                truetruebot_move_forward: '앞으로',\r\n                truetruebot_move_backward: '뒤로',\r\n                truetruebot_move_right: '오른쪽으로',\r\n                truetruebot_move_left: '왼쪽으로',\r\n                truetruebot_right: '오른쪽',\r\n                truetruebot_left: '왼쪽',\r\n                truetruebot_Xaxis: 'X축',\r\n                truetruebot_Yaxis: 'Y축',\r\n                truetruebot_Zaxis: 'Z축',\r\n                truetruebot_Tilt: '기울기',\r\n                truetruebot_ColorKey: '컬러키',\r\n            },\r\n        },\r\n        ebs: {\r\n            template: {\r\n                truetrue_get_accsensor: '가속도센서 %1 의 값',\r\n                truetrue_get_bottomcolorsensor: '바닥컬러센서 %1 의 값',\r\n                truetrue_get_frontcolorsensor: '전면컬러센서 %1 의 값',\r\n                truetrue_get_linesensor: '라인센서 %1 의 값',\r\n                truetrue_get_proxisensor: '근접센서 %1 의 값',\r\n                truetrue_set_colorled: '컬러LED Red %1  Green %2 Blue %3 로 설정 %4',\r\n                truetrue_set_dualmotor: 'DC모터 좌 %1  우 %2 속도로 %3 초 구동 %4',\r\n                truetrue_set_led_colorsensor: '%1 조명용 LED %2 %3',\r\n                truetrue_set_led_linesensor: '라인센서 조명용 LED %1 %2',\r\n                truetrue_set_led_proxi: '%1 조명용 LED %2 %3',\r\n                truetrue_set_linetracer: '라인트레이싱 모드 %1 %2',\r\n                truetrue_set_singlemotor: 'DC모터 %1  속도 %2 로 설정 %3',\r\n                truetrue_set_head_colorled: '머리 LED를 %1 로 변경 %2',\r\n                truetrue_set_move: '로봇을 %1 계속이동 %2',\r\n                truetrue_set_sec_move: '로봇을 %1  %2 초 이동 %3',\r\n                truetrue_set_rotate: '로봇을 %1 계속 회전 %2',\r\n                truetrue_set_sec_rotate: '로봇을 %1  %2 초 회전 %3',\r\n                truetrue_set_grid_block: '뚜루뚜루를 격자 %1 칸 만큼 이동 %2 ',\r\n                truetrue_set_grid_rotate: '뚜루뚜루를 격자에서 %1 %2 회 회전 %3 ',\r\n            },\r\n            Blocks: {\r\n                truetruebot_on: '켜기',\r\n                truetruebot_off: '끄기',\r\n                truetruebot_front_near_right: '근접센서오른쪽',\r\n                truetruebot_front_near_left: '근접센서왼쪽',\r\n                truetruebot_front_color: '전면컬러센서',\r\n                truetruebot_bottom_color: '바닥컬러센서',\r\n                truetruebot_head_color_white: '흰색',\r\n                truetruebot_head_color_red: '빨간색',\r\n                truetruebot_head_color_green: '초록색',\r\n                truetruebot_head_color_blue: '파란색',\r\n                truetruebot_head_color_cyan: '하늘색',\r\n                truetruebot_head_color_magenta: '자주색',\r\n                truetruebot_head_color_yellow: '노란색',\r\n                truetruebot_head_color_off: '끄기',\r\n                truetruebot_move_forward: '앞으로',\r\n                truetruebot_move_backward: '뒤로',\r\n                truetruebot_move_right: '오른쪽으로',\r\n                truetruebot_move_left: '왼쪽으로',\r\n                truetruebot_right: '오른쪽',\r\n                truetruebot_left: '왼쪽',\r\n                truetruebot_Xaxis: 'X축',\r\n                truetruebot_Yaxis: 'Y축',\r\n                truetruebot_Zaxis: 'Z축',\r\n                truetruebot_Tilt: '기울기',\r\n                truetruebot_ColorKey: '컬러키',\r\n            },\r\n        },\r\n        jp: {\r\n            template: {\r\n                truetrue_get_accsensor: '3-AXIS Accelerometer %1 Sensor value',\r\n                truetrue_get_bottomcolorsensor: 'Bottom Color %1 Sensor value',\r\n                truetrue_get_frontcolorsensor: 'Front Color %1 Sensor value',\r\n                truetrue_get_linesensor: 'Line %1 Sensor value',\r\n                truetrue_get_proxisensor: 'Proximity %1 Sensor value',\r\n                truetrue_set_colorled: 'Set Color LED Red %1  Green %2 Blue %3 %4',\r\n                truetrue_set_dualmotor: 'Set DC motor left %1  right %2 during %3 seconds %4',\r\n                truetrue_set_led_colorsensor: 'LED for %1 color sensor %2 %3',\r\n                truetrue_set_led_linesensor: 'LED for line sensor %1 %2',\r\n                truetrue_set_led_proxi: 'LED for %1 proximity sensor %2 %3',\r\n                truetrue_set_linetracer: 'Line tracing mode %1 %2',\r\n                truetrue_set_singlemotor: 'Set DC motor %1  speed %2 %3',\r\n                truetrue_set_head_colorled: 'Change LED color to %1 %2',\r\n                truetrue_set_move: 'Move TRUETRUE %1 forever %2',\r\n                truetrue_set_sec_move: 'Move TRUETRUE %1 for %2 second(s) %3',\r\n                truetrue_set_rotate: 'Rotate TRUETRUE %1 forever %2',\r\n                truetrue_set_sec_rotate: 'Rotate TRUETRUE %1 for %2 Second(s) %3',\r\n                truetrue_set_grid_block: 'Move TRUETRUE %1 block(s) on the GRID %2',\r\n                truetrue_set_grid_rotate: 'Rotate TRUETRUE %1 %2 time(s) on the GRID %3',\r\n            },\r\n            Blocks: {\r\n                truetruebot_on: 'on',\r\n                truetruebot_off: 'off',\r\n                truetruebot_front_near_right: 'Proxi Right',\r\n                truetruebot_front_near_left: 'Proxi Left',\r\n                truetruebot_front_color: 'Color sensor (Card)',\r\n                truetruebot_bottom_color: 'Color sensor (Bottom)',\r\n                truetruebot_head_color_white: 'White',\r\n                truetruebot_head_color_red: 'Red',\r\n                truetruebot_head_color_green: 'Green',\r\n                truetruebot_head_color_blue: 'Blue',\r\n                truetruebot_head_color_cyan: 'Cyan',\r\n                truetruebot_head_color_magenta: 'Magenta',\r\n                truetruebot_head_color_yellow: 'Yellow',\r\n                truetruebot_head_color_off: 'off',\r\n                truetruebot_move_forward: 'forward',\r\n                truetruebot_move_backward: 'backward',\r\n                truetruebot_move_right: 'right',\r\n                truetruebot_move_left: 'left',\r\n                truetruebot_right: 'right',\r\n                truetruebot_left: 'left',\r\n                truetruebot_Xaxis: 'X-axis',\r\n                truetruebot_Yaxis: 'Y-axis',\r\n                truetruebot_Zaxis: 'Z-axis',\r\n                truetruebot_Tilt: 'Tilt',\r\n                truetruebot_ColorKey: 'ColorKey',\r\n            },\r\n        },\r\n        vn: {\r\n            template: {\r\n                truetrue_get_accsensor: '3-AXIS Accelerometer %1 Sensor value',\r\n                truetrue_get_bottomcolorsensor: 'Bottom Color %1 Sensor value',\r\n                truetrue_get_frontcolorsensor: 'Front Color %1 Sensor value',\r\n                truetrue_get_linesensor: 'Line %1 Sensor value',\r\n                truetrue_get_proxisensor: 'Proximity %1 Sensor value',\r\n                truetrue_set_colorled: 'Set Color LED Red %1  Green %2 Blue %3 %4',\r\n                truetrue_set_dualmotor: 'Set DC motor left %1  right %2 during %3 seconds %4',\r\n                truetrue_set_led_colorsensor: 'LED for %1 color sensor %2 %3',\r\n                truetrue_set_led_linesensor: 'LED for line sensor %1 %2',\r\n                truetrue_set_led_proxi: 'LED for %1 proximity sensor %2 %3',\r\n                truetrue_set_linetracer: 'Line tracing mode %1 %2',\r\n                truetrue_set_singlemotor: 'Set DC motor %1  speed %2 %3',\r\n                truetrue_set_head_colorled: 'Change LED color to %1 %2',\r\n                truetrue_set_move: 'Move TRUETRUE %1 forever %2',\r\n                truetrue_set_sec_move: 'Move TRUETRUE %1 for %2 second(s) %3',\r\n                truetrue_set_rotate: 'Rotate TRUETRUE %1 forever %2',\r\n                truetrue_set_sec_rotate: 'Rotate TRUETRUE %1 for %2 Second(s) %3',\r\n                truetrue_set_grid_block: 'Move TRUETRUE %1 block(s) on the GRID %2',\r\n                truetrue_set_grid_rotate: 'Rotate TRUETRUE %1 %2 time(s) on the GRID %3',\r\n            },\r\n            Blocks: {\r\n                truetruebot_on: 'on',\r\n                truetruebot_off: 'off',\r\n                truetruebot_front_near_right: 'Proxi Right',\r\n                truetruebot_front_near_left: 'Proxi Left',\r\n                truetruebot_front_color: 'Color sensor (Card)',\r\n                truetruebot_bottom_color: 'Color sensor (Bottom)',\r\n                truetruebot_head_color_white: 'White',\r\n                truetruebot_head_color_red: 'Red',\r\n                truetruebot_head_color_green: 'Green',\r\n                truetruebot_head_color_blue: 'Blue',\r\n                truetruebot_head_color_cyan: 'Cyan',\r\n                truetruebot_head_color_magenta: 'Magenta',\r\n                truetruebot_head_color_yellow: 'Yellow',\r\n                truetruebot_head_color_off: 'off',\r\n                truetruebot_move_forward: 'forward',\r\n                truetruebot_move_backward: 'backward',\r\n                truetruebot_move_right: 'right',\r\n                truetruebot_move_left: 'left',\r\n                truetruebot_right: 'right',\r\n                truetruebot_left: 'left',\r\n                truetruebot_Xaxis: 'X-axis',\r\n                truetruebot_Yaxis: 'Y-axis',\r\n                truetruebot_Zaxis: 'Z-axis',\r\n                truetruebot_Tilt: 'Tilt',\r\n                truetruebot_ColorKey: 'ColorKey',\r\n            },\r\n        },\r\n        en: {\r\n            template: {\r\n                truetrue_get_accsensor: '3-AXIS Accelerometer %1 Sensor value',\r\n                truetrue_get_bottomcolorsensor: 'Bottom Color %1 Sensor value',\r\n                truetrue_get_frontcolorsensor: 'Front Color %1 Sensor value',\r\n                truetrue_get_linesensor: 'Line %1 Sensor value',\r\n                truetrue_get_proxisensor: 'Proximity %1 Sensor value',\r\n                truetrue_set_colorled: 'Set Color LED Red %1  Green %2 Blue %3 %4',\r\n                truetrue_set_dualmotor: 'Set DC motor left %1  right %2 during %3 seconds %4',\r\n                truetrue_set_led_colorsensor: 'LED for %1 color sensor %2 %3',\r\n                truetrue_set_led_linesensor: 'LED for line sensor %1 %2',\r\n                truetrue_set_led_proxi: 'LED for %1 proximity sensor %2 %3',\r\n                truetrue_set_linetracer: 'Line tracing mode %1 %2',\r\n                truetrue_set_singlemotor: 'Set DC motor %1  speed %2 %3',\r\n                truetrue_set_head_colorled: 'Change LED color to %1 %2',\r\n                truetrue_set_move: 'Move TRUETRUE %1 forever %2',\r\n                truetrue_set_sec_move: 'Move TRUETRUE %1 for %2 second(s) %3',\r\n                truetrue_set_rotate: 'Rotate TRUETRUE %1 forever %2',\r\n                truetrue_set_sec_rotate: 'Rotate TRUETRUE %1 for %2 Second(s) %3',\r\n                truetrue_set_grid_block: 'Move TRUETRUE %1 block(s) on the GRID %2',\r\n                truetrue_set_grid_rotate: 'Rotate TRUETRUE %1 %2 time(s) on the GRID %3',\r\n            },\r\n            Blocks: {\r\n                truetruebot_on: 'on',\r\n                truetruebot_off: 'off',\r\n                truetruebot_front_near_right: 'Proxi Right',\r\n                truetruebot_front_near_left: 'Proxi Left',\r\n                truetruebot_front_color: 'Color sensor (Card)',\r\n                truetruebot_bottom_color: 'Color sensor (Bottom)',\r\n                truetruebot_head_color_white: 'White',\r\n                truetruebot_head_color_red: 'Red',\r\n                truetruebot_head_color_green: 'Green',\r\n                truetruebot_head_color_blue: 'Blue',\r\n                truetruebot_head_color_cyan: 'Cyan',\r\n                truetruebot_head_color_magenta: 'Magenta',\r\n                truetruebot_head_color_yellow: 'Yellow',\r\n                truetruebot_head_color_off: 'off',\r\n                truetruebot_move_forward: 'forward',\r\n                truetruebot_move_backward: 'backward',\r\n                truetruebot_move_right: 'right',\r\n                truetruebot_move_left: 'left',\r\n                truetruebot_right: 'right',\r\n                truetruebot_left: 'left',\r\n                truetruebot_Xaxis: 'X-axis',\r\n                truetruebot_Yaxis: 'Y-axis',\r\n                truetruebot_Zaxis: 'Z-axis',\r\n                truetruebot_Tilt: 'Tilt',\r\n                truetruebot_ColorKey: 'ColorKey',\r\n            },\r\n        },\r\n    };\r\n};\r\n\r\nmodule.exports = Entry.trueRobot;\r\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_turtle.js",
    "content": "'use strict';\n\nEntry.Turtle = {\n    setZero() {\n        Entry.Robomation.setZero();\n    },\n    afterReceive(pd) {\n        Entry.Robomation.afterReceive(pd, false);\n    },\n    afterSend(sq) {\n        Entry.Robomation.afterSend(sq);\n    },\n    getRobot() {\n        const robot = Entry.Robomation.getRobot('turtle', 0);\n        if (robot) {\n            robot.setMotoring(Entry.hw.sendQueue);\n        }\n        return robot;\n    },\n    id: '2.9',\n    name: 'turtle',\n    url: 'http://www.robomation.net',\n    imageName: 'turtle.png',\n    title: {\n        en: 'Turtle',\n        ko: '거북이',\n        jp: 'カメ',\n        vn: 'Turtle',\n    },\n    monitorTemplate: () => ({\n        imgPath: 'hw/turtle.png',\n        width: 480,\n        height: 354,\n        listPorts: {\n            colorNumber: {\n                name: Lang.Blocks.turtle_color_number,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationX: {\n                name: Lang.Blocks.turtle_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.turtle_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.turtle_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Blocks.turtle_buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: {\n                name: Lang.Blocks.turtle_note,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            floor: {\n                name: Lang.Blocks.turtle_floor,\n                type: 'input',\n                pos: { x: 193, y: 342 },\n            },\n            button: {\n                name: Lang.Blocks.turtle_button,\n                type: 'input',\n                pos: { x: 290, y: 30 },\n            },\n            ledRed: {\n                name: `${Lang.Blocks.turtle_head_color} R`,\n                type: 'output',\n                pos: { x: 140, y: 280 },\n            },\n            ledGreen: {\n                name: `${Lang.Blocks.turtle_head_color} G`,\n                type: 'output',\n                pos: { x: 140, y: 280 },\n            },\n            ledBlue: {\n                name: `${Lang.Blocks.turtle_head_color} B`,\n                type: 'output',\n                pos: { x: 140, y: 280 },\n            },\n            leftWheel: {\n                name: Lang.Blocks.turtle_left_wheel,\n                type: 'output',\n                pos: { x: 363, y: 319 },\n            },\n            rightWheel: {\n                name: Lang.Blocks.turtle_right_wheel,\n                type: 'output',\n                pos: { x: 120, y: 86 },\n            },\n        },\n        mode: 'both',\n    }),\n};\n\nEntry.Turtle.setLanguage = () => ({\n    ko: {\n        template: {\n            turtle_button_state: '버튼을 %1 ?',\n            turtle_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            turtle_change_head_led_by_rgb: '머리 LED를 R: %1 G: %2 B: %3 만큼 바꾸기 %4',\n            turtle_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            turtle_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            turtle_change_wheels_by_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            turtle_clear_head_led: '머리 LED 끄기 %1',\n            turtle_clear_sound: '소리 끄기 %1',\n            turtle_cross_intersection: '검은색 교차로 건너가기 %1',\n            turtle_follow_line: '%1 선을 따라가기 %2',\n            turtle_follow_line_until: '검은색 선을 따라 %1 까지 이동하기 %2',\n            turtle_follow_line_until_black: '%1 선을 따라 검은색까지 이동하기 %2',\n            turtle_is_color_pattern: '색깔 패턴이 %1 %2 인가?',\n            turtle_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n            turtle_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n            turtle_pivot_around_wheel_unit_in_direction:\n                '%1 바퀴 중심으로 %2 %3 %4 방향으로 돌기 %5',\n            turtle_play_note: '%1 %2 음을 연주하기 %3',\n            turtle_play_note_for_beats: '%1 %2 음을 %3 박자 연주하기 %4',\n            turtle_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n            turtle_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n            turtle_rest_for_beats: '%1 박자 쉬기 %2',\n            turtle_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            turtle_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n            turtle_set_head_led_to: '머리 LED를 %1 으로 정하기 %2',\n            turtle_set_head_led_to_rgb: '머리 LED를 R: %1 G: %2 B: %3 (으)로 정하기 %4',\n            turtle_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n            turtle_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            turtle_set_wheels_to_left_right: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            turtle_stop: '정지하기 %1',\n            turtle_touching_color: '%1 에 닿았는가?',\n            turtle_turn_at_intersection: '검은색 교차로에서 %1 으로 돌기 %2',\n            turtle_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n            turtle_turn_unit_with_radius_in_direction:\n                '%1 으로 %2 %3 반지름 %4 cm를 %5 방향으로 돌기 %6',\n            turtle_value: '%1',\n            turtle_boolean: '%1?',\n            turtle_pick_head_led: '머리 LED를 %1로 정하기 %2',\n        },\n        Helper: {\n            turtle_button_state:\n                \"등 버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            turtle_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            turtle_change_head_led_by_rgb:\n                '머리 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            turtle_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            turtle_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            turtle_change_wheels_by_left_right:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            turtle_clear_head_led: '머리 LED를 끕니다.',\n            turtle_clear_sound: '소리를 끕니다.',\n            turtle_cross_intersection:\n                '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾아 다시 이동합니다.',\n            turtle_follow_line: '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동합니다.',\n            turtle_follow_line_until:\n                '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n            turtle_follow_line_until_black:\n                '하얀색 바탕 위에서 선택한 색깔의 선을 따라 이동하다가 컬러 센서가 검은색을 감지하면 정지합니다.',\n            turtle_is_color_pattern:\n                \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            turtle_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            turtle_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            turtle_pivot_around_wheel_unit_in_direction:\n                '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 머리/꼬리 방향으로 회전합니다.',\n            turtle_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            turtle_play_note_for_beats:\n                '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            turtle_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            turtle_play_sound_times_until_done:\n                '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            turtle_rest_for_beats: '입력한 박자만큼 쉽니다.',\n            turtle_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n            turtle_set_following_speed_to:\n                '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            turtle_set_head_led_to: '머리 LED를 선택한 색깔로 켭니다.',\n            turtle_set_head_led_to_rgb: '머리 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            turtle_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n            turtle_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            turtle_set_wheels_to_left_right:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-400 ~ 400%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            turtle_stop: '양쪽 바퀴를 정지합니다.',\n            turtle_touching_color:\n                \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            turtle_turn_at_intersection:\n                '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾아 다시 이동합니다.',\n            turtle_turn_unit_in_place:\n                '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            turtle_turn_unit_with_radius_in_direction:\n                '입력한 반지름의 원을 그리면서 입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽, 머리/꼬리 방향으로 회전합니다.',\n            turtle_value:\n                '색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 8, 초기값: -1)<br/>색깔 패턴: 컬러 센서가 감지한 색깔 패턴의 값 (값의 범위: -1 ~ 88, 초기값: -1)<br/>바닥 센서: 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>버튼: 거북이 등 버튼의 상태 값 (누르면 1, 아니면 0, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.',\n            turtle_boolean:\n                \"앞으로 기울임: 앞으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            turtle_pick_head_led: '머리 LED를 선택한 색깔로 켭니다.',\n        },\n        Blocks: {\n            turtle_acceleration_x: 'x축 가속도',\n            turtle_acceleration_y: 'y축 가속도',\n            turtle_acceleration_z: 'z축 가속도',\n            turtle_back: '뒤쪽',\n            turtle_both: '양쪽',\n            turtle_button: '버튼',\n            turtle_buzzer: '버저',\n            turtle_clicked: '클릭했는가',\n            turtle_color_any: '아무 색',\n            turtle_color_black: '검은색',\n            turtle_color_blue: '파란색',\n            turtle_color_green: '초록색',\n            turtle_color_number: '색깔 번호',\n            turtle_color_orange: '주황색',\n            turtle_color_pattern: '색깔 패턴',\n            turtle_color_purple: '자주색',\n            turtle_color_red: '빨간색',\n            turtle_color_sky_blue: '하늘색',\n            turtle_color_violet: '보라색',\n            turtle_color_white: '하얀색',\n            turtle_color_yellow: '노란색',\n            turtle_double_clicked: '더블클릭했는가',\n            turtle_floor: '바닥 센서',\n            turtle_head: '머리',\n            turtle_head_color: '머리 색깔',\n            turtle_left: '왼쪽',\n            turtle_left_wheel: '왼쪽 바퀴',\n            turtle_long_pressed: '길게~눌렀는가',\n            turtle_note: '음표',\n            turtle_right: '오른쪽',\n            turtle_right_wheel: '오른쪽 바퀴',\n            turtle_sound_beep: '삐',\n            turtle_sound_birthday: '생일',\n            turtle_sound_dibidibidip: '디비디비딥',\n            turtle_sound_engine: '엔진',\n            turtle_sound_good_job: '잘 했어요',\n            turtle_sound_march: '행진',\n            turtle_sound_random_beep: '무작위 삐',\n            turtle_sound_robot: '로봇',\n            turtle_sound_siren: '사이렌',\n            turtle_tail: '꼬리',\n            turtle_unit_cm: 'cm',\n            turtle_unit_deg: '도',\n            turtle_unit_pulse: '펄스',\n            turtle_unit_sec: '초',\n            turtle_note_c: '도',\n            turtle_note_c_sharp: '도♯(레♭)',\n            turtle_note_d: '레',\n            turtle_note_d_sharp: '레♯(미♭)',\n            turtle_note_e: '미',\n            turtle_note_f: '파',\n            turtle_note_f_sharp: '파♯(솔♭)',\n            turtle_note_g: '솔',\n            turtle_note_g_sharp: '솔♯(라♭)',\n            turtle_note_a: '라',\n            turtle_note_a_sharp: '라♯(시♭)',\n            turtle_note_b: '시',\n            turtle_tilt_forward: '앞으로 기울임',\n            turtle_tilt_backward: '뒤로 기울임',\n            turtle_tilt_left: '왼쪽으로 기울임',\n            turtle_tilt_right: '오른쪽으로 기울임',\n            turtle_tilt_flip: '거꾸로 뒤집음',\n            turtle_tilt_not: '기울이지 않음',\n            turtle_battery_normal: '배터리 정상',\n            turtle_battery_low: '배터리 부족',\n            turtle_battery_empty: '배터리 없음',\n        },\n    },\n    en: {\n        template: {\n            turtle_button_state: 'button %1 ?',\n            turtle_change_buzzer_by: 'change buzzer by %1 %2',\n            turtle_change_head_led_by_rgb: 'change head led by r: %1 g: %2 b: %3 %4',\n            turtle_change_tempo_by: 'change tempo by %1 %2',\n            turtle_change_wheel_by: 'change %1 wheel by %2 %3',\n            turtle_change_wheels_by_left_right: 'change wheels by left: %1 right: %2 %3',\n            turtle_clear_head_led: 'clear head led %1',\n            turtle_clear_sound: 'clear sound %1',\n            turtle_cross_intersection: 'cross black intersection %1',\n            turtle_follow_line: 'follow %1 line %2',\n            turtle_follow_line_until: 'follow black line until %1 %2',\n            turtle_follow_line_until_black: 'follow %1 line until black %2',\n            turtle_is_color_pattern: 'color pattern %1 %2 ?',\n            turtle_move_backward_unit: 'move backward %1 %2 %3',\n            turtle_move_forward_unit: 'move forward %1 %2 %3',\n            turtle_pivot_around_wheel_unit_in_direction:\n                'pivot around %1 wheel %2 %3 in %4 direction %5',\n            turtle_play_note: 'play note %1 %2 %3',\n            turtle_play_note_for_beats: 'play note %1 %2 for %3 beats %4',\n            turtle_play_sound_times: 'play sound %1 %2 times %3',\n            turtle_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            turtle_rest_for_beats: 'rest for %1 beats %2',\n            turtle_set_buzzer_to: 'set buzzer to %1 %2',\n            turtle_set_following_speed_to: 'set following speed to %1 %2',\n            turtle_set_head_led_to: 'set head led to %1 %2',\n            turtle_set_head_led_to_rgb: 'set head led to r: %1 g: %2 b: %3 %4',\n            turtle_set_tempo_to: 'set tempo to %1 bpm %2',\n            turtle_set_wheel_to: 'set %1 wheel to %2 %3',\n            turtle_set_wheels_to_left_right: 'set wheels to left: %1 right: %2 %3',\n            turtle_stop: 'stop %1',\n            turtle_touching_color: 'touching %1 ?',\n            turtle_turn_at_intersection: 'turn %1 at black intersection %2',\n            turtle_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            turtle_turn_unit_with_radius_in_direction:\n                'turn %1 %2 %3 with radius %4 cm in %5 direction %6',\n            turtle_value: '%1',\n            turtle_boolean: '%1?',\n            turtle_pick_head_led: 'set head led to %1 %2',\n        },\n        Helper: {\n            turtle_button_state:\n                'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            turtle_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            turtle_change_head_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of the head LED, respectively.',\n            turtle_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            turtle_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            turtle_change_wheels_by_left_right:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            turtle_clear_head_led: 'Turns off the head LED.',\n            turtle_clear_sound: 'Turns off sound.',\n            turtle_cross_intersection:\n                'Moves forward for a moment at the black intersection, then finds the black line and moves again.',\n            turtle_follow_line: 'Moves along the selected color line on a white background.',\n            turtle_follow_line_until:\n                'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            turtle_follow_line_until_black:\n                'Moves along the selected color line on a white background and stops when the color sensor detects black.',\n            turtle_is_color_pattern:\n                'If the color sensor detects the selected color pattern, true, otherwise false.',\n            turtle_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            turtle_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            turtle_pivot_around_wheel_unit_in_direction:\n                'Pivots around the left/right wheel in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            turtle_play_note: 'It sounds the selected tone and octave.',\n            turtle_play_note_for_beats:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            turtle_play_sound_times: 'Plays the selected sound as many times as entered.',\n            turtle_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            turtle_rest_for_beats: 'Rests as much as the beat you entered.',\n            turtle_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            turtle_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            turtle_set_head_led_to: 'Turns the head LED to the selected color.',\n            turtle_set_head_led_to_rgb:\n                'Sets the R, G, B values of the head LED to the entered values.',\n            turtle_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            turtle_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-400 to 400%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            turtle_set_wheels_to_left_right:\n                'Sets the speed of the left and right wheels to the entered values (-400 to 400%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            turtle_stop: 'Stops both wheels.',\n            turtle_touching_color:\n                'If the color sensor detects the selected color, true, otherwise false.',\n            turtle_turn_at_intersection:\n                'Moves forward for a moment at the black intersection, then turns left/right/back in place, finds the black line and moves again.',\n            turtle_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            turtle_turn_unit_with_radius_in_direction:\n                'Turns left/right drawing the circle of the entered radius in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            turtle_value:\n                'color number: color number detected by the color sensor (range: -1 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1) <br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.',\n            turtle_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            turtle_pick_head_led: 'Turns the head LED to the selected color.',\n        },\n        Blocks: {\n            turtle_acceleration_x: 'x acceleration',\n            turtle_acceleration_y: 'y acceleration',\n            turtle_acceleration_z: 'z acceleration',\n            turtle_back: 'back',\n            turtle_both: 'both',\n            turtle_button: 'button',\n            turtle_buzzer: 'buzzer',\n            turtle_clicked: 'clicked',\n            turtle_color_any: 'any color',\n            turtle_color_black: 'black',\n            turtle_color_blue: 'blue',\n            turtle_color_green: 'green',\n            turtle_color_number: 'color number',\n            turtle_color_orange: 'orange',\n            turtle_color_pattern: 'color pattern',\n            turtle_color_purple: 'purple',\n            turtle_color_red: 'red',\n            turtle_color_sky_blue: 'sky blue',\n            turtle_color_violet: 'violet',\n            turtle_color_white: 'white',\n            turtle_color_yellow: 'yellow',\n            turtle_double_clicked: 'double-clicked',\n            turtle_floor: 'floor',\n            turtle_head: 'head',\n            turtle_head_color: 'head color',\n            turtle_left: 'left',\n            turtle_left_wheel: 'left wheel',\n            turtle_long_pressed: 'long-pressed',\n            turtle_note: 'note',\n            turtle_right: 'right',\n            turtle_right_wheel: 'right wheel',\n            turtle_sound_beep: 'beep',\n            turtle_sound_birthday: 'birthday',\n            turtle_sound_dibidibidip: 'dibidibidip',\n            turtle_sound_engine: 'engine',\n            turtle_sound_good_job: 'good job',\n            turtle_sound_march: 'march',\n            turtle_sound_random_beep: 'random beep',\n            turtle_sound_robot: 'robot',\n            turtle_sound_siren: 'siren',\n            turtle_tail: 'tail',\n            turtle_unit_cm: 'cm',\n            turtle_unit_deg: 'degrees',\n            turtle_unit_pulse: 'pulses',\n            turtle_unit_sec: 'seconds',\n            turtle_note_c: 'C',\n            turtle_note_c_sharp: 'C♯(D♭)',\n            turtle_note_d: 'D',\n            turtle_note_d_sharp: 'D♯(E♭)',\n            turtle_note_e: 'E',\n            turtle_note_f: 'F',\n            turtle_note_f_sharp: 'F♯(G♭)',\n            turtle_note_g: 'G',\n            turtle_note_g_sharp: 'G♯(A♭)',\n            turtle_note_a: 'A',\n            turtle_note_a_sharp: 'A♯(B♭)',\n            turtle_note_b: 'B',\n            turtle_tilt_forward: 'tilt forward',\n            turtle_tilt_backward: 'tilt backward',\n            turtle_tilt_left: 'tilt left',\n            turtle_tilt_right: 'tilt right',\n            turtle_tilt_flip: 'tilt flip',\n            turtle_tilt_not: 'not tilt',\n            turtle_battery_normal: 'battery normal',\n            turtle_battery_low: 'battery low',\n            turtle_battery_empty: 'battery empty',\n        },\n    },\n    jp: {\n        template: {\n            turtle_button_state: '背中を %1 した？',\n            turtle_change_buzzer_by: 'ブザー音の高さを %1 だけ変えて鳴らす %2',\n            turtle_change_head_led_by_rgb:\n                '頭のLEDの色をR（赤：あか） %1  G（緑：みどり） %2  B（青：あお） %3 だけ変える %4',\n            turtle_change_tempo_by: '演奏の速さを %1 だけ変える %2',\n            turtle_change_wheel_by: '%1 の車輪（しゃりん）の速さを %2 だけ変える %3',\n            turtle_change_wheels_by_left_right: '車輪（しゃりん）の速さを左 %1 右 %2 だけ変える %3',\n            turtle_clear_head_led: '頭のLEDを消す %1',\n            turtle_clear_sound: '音を消す %1',\n            turtle_cross_intersection: '黒の線が交わる点を渡る %1',\n            turtle_follow_line: '%1 の線にそって移動する %2',\n            turtle_follow_line_until: '黒の線にそって %1 まで移動する %2',\n            turtle_follow_line_until_black: '%1 の線にそって黒まで移動する %2',\n            turtle_is_color_pattern: '色の順番 %1 %2 を感知した?',\n            turtle_move_backward_unit: '後ろへ %1 %2 移動する %3',\n            turtle_move_forward_unit: '前へ %1 %2 移動する %3',\n            turtle_pivot_around_wheel_unit_in_direction: '%1 の車輪を中心に %2 %3 %4 方向に回る %5',\n            turtle_play_note: '%1 %2 を演奏する %3',\n            turtle_play_note_for_beats: '%1 %2 を %3 拍演奏する %4',\n            turtle_play_sound_times: '音 %1 を %2 回鳴らす %3',\n            turtle_play_sound_times_until_done: '音 %1 を %2 回鳴らして終わるまで待つ %3',\n            turtle_rest_for_beats: '%1 拍休む %2',\n            turtle_set_buzzer_to: 'ブザー音の高さを %1 にして鳴らす %2',\n            turtle_set_following_speed_to: '線にそって移動する速さを %1 にする %2',\n            turtle_set_head_led_to: '頭のLEDの色を %1 にする %2',\n            turtle_set_head_led_to_rgb:\n                '頭のLEDの色をR（赤：あか） %1  G（緑：みどり） %2  B（青：あお） %3 にする %4',\n            turtle_set_tempo_to: '演奏の速さを1分間に %1 拍にする %2',\n            turtle_set_wheel_to: '%1 の車輪（しゃりん）の速さを %2 にする %3',\n            turtle_set_wheels_to_left_right: '車輪（しゃりん）の速さを左 %1 右 %2 にする %3',\n            turtle_stop: '移動を停止する %1',\n            turtle_touching_color: '%1 を感知した？',\n            turtle_turn_at_intersection: '黒の線が交わる点で %1 へ方向を変える %2',\n            turtle_turn_unit_in_place: '%1 へ %2 %3 その場で回る %4',\n            turtle_turn_unit_with_radius_in_direction: '%1 へ %2 %3 半径 %4 cmで %5 方向に回る %6',\n            turtle_value: '%1',\n            turtle_boolean: '%1?',\n            turtle_pick_head_led: '頭のLEDの色を %1 にする %2',\n        },\n        Helper: {\n            turtle_button_state:\n                '背中（ボタン）が[クリック/ダブルクリック/長押し]された場合は｢正しい｣と判断します。それ以外の場合は｢正しくない｣と判断します。',\n            turtle_change_buzzer_by:\n                'ブザーの現在の音の高さ（ヘルツ）に入力された数値を足して鳴らします。小数点以下2桁まで入力できます。',\n            turtle_change_head_led_by_rgb:\n                '頭のLEDライトの色に、入力されたR（赤：あか）、G（緑：みどり）、B（青：あお）の数値（範囲:0～255）を足します。',\n            turtle_change_tempo_by:\n                '入力された数値を現在の演奏速度（１分あたりの拍数）に足します。',\n            turtle_change_wheel_by:\n                '[左/右]の車輪（しゃりん）の速さ（%）に入力された数値を足します。足した結果が、正の数の場合は前方向に、負の数の場合は後方向に、車輪が回転します。',\n            turtle_change_wheels_by_left_right:\n                '左右の車輪（しゃりん）の速さ（%）にそれぞれ入力された数値を足します。足した結果が、正の数の場合は前方向に、負の数の場合は後方向に、車輪が回転します。',\n            turtle_clear_head_led: '頭のLEDライトを消します。',\n            turtle_clear_sound: '音を消します。',\n            turtle_cross_intersection: '黒の線が交わる点を越えて、前方の黒の線にそって移動します。',\n            turtle_follow_line: '白地の上の選択された色の線にそって移動します。',\n            turtle_follow_line_until:\n                '白地の上の黒の線にそって移動し、カラーセンサーが選択された色を感知したら停止します。',\n            turtle_follow_line_until_black:\n                '白地の上の選択された色の線にそって移動し、カラーセンサーが黒を感知したら停止します。',\n            turtle_is_color_pattern:\n                'カラーセンサーが選択された色の順番（パターン）を感知した場合は｢正しい｣と判断します。それ以外の場合は｢正しくない｣と判断します。',\n            turtle_move_backward_unit: '入力された数値[cm/秒/パルス]だけ後方向に移動します。',\n            turtle_move_forward_unit: '入力された数値[cm/秒/パルス]だけ前方向に移動します。',\n            turtle_pivot_around_wheel_unit_in_direction:\n                '[左/右]の車輪を中心に、入力された数値[角度/秒/パルス]だけ、[前/後]方向に回転します。',\n            turtle_play_note: '選択された音階（音名、オクターブ）が鳴ります。',\n            turtle_play_note_for_beats:\n                '選択された音階（音名、オクターブ）が、入力された拍数分鳴ります。',\n            turtle_play_sound_times: '選択された音を入力された回数だけ再生します。',\n            turtle_play_sound_times_until_done:\n                '選択された音を入力された回数だけ再生します。再生が終わってから次の命令を実行します。',\n            turtle_rest_for_beats: '入力された拍数分だけ音を鳴らすのを休みます。',\n            turtle_set_buzzer_to:\n                'ブザーの現在の音の高さ（ヘルツ）を入力された数値にして鳴らします。小数点以下2桁まで入力できます。',\n            turtle_set_following_speed_to:\n                '線にそって移動する速度（範囲：1〜8）を入力された数値にします。数字が大きいほど動きが速くなります。',\n            turtle_set_head_led_to: '頭のLEDライトを選択された色にします。',\n            turtle_set_head_led_to_rgb:\n                '頭のLEDライトを入力されたR（赤：あか）、G（緑：みどり）、B（青：あお）の数値（範囲:0～255）の色にします。',\n            turtle_set_tempo_to: '入力された数値を現在の演奏速度（１分あたりの拍数）にします。',\n            turtle_set_wheel_to:\n                '[左/右]の車輪（しゃりん）の速さ（範囲：-400～400%）を入力された数値にします。正の数の場合は前方向に、負の数の場合は後方向に、車輪が回転します。0を入力すると車輪が停止します。',\n            turtle_set_wheels_to_left_right:\n                '左右の車輪（しゃりん）の速さ（範囲：-400～400%）をそれぞれ入力された数値にします。正の数の場合は前方向に、負の数の場合は後方向に、車輪が回転します。0を入力すると車輪が停止します。',\n            turtle_stop: '移動を停止します。',\n            turtle_touching_color:\n                'カラーセンサーが選択された色を感知した場合は｢正しい｣と判断します。それ以外の場合は｢正しくない｣と判断します。',\n            turtle_turn_at_intersection:\n                '黒の線が交わる点で[左/右/後]方向に回転して、黒い線にそって移動します。',\n            turtle_turn_unit_in_place:\n                '入力された数値[角度/秒/パルス]だけ、その場で[左/右]に回転します。',\n            turtle_turn_unit_with_radius_in_direction:\n                '入力された数値[角度/秒/パルス]だけ、入力された半径（cm）で、[前/後]方向に回転します。',\n            turtle_value:\n                '色番号：カラーセンサーが感知した色の番号（範囲：-1〜8、初期値：-1）<br/>色のパターン：カラーセンサーが感知した色のパターンの値（範囲：-1〜88、初期値：-1）<br/>床センサー：床センサーの値（範囲：0〜100、初期値：0）<br/>ボタン：ボタンの状態（クリックした時：1、それ以外：0、初期値：0）<br/>前後の速さ：加速度センサーの前後（x軸）の速さの値（範囲：-32768〜32767、初期値：0）タートルが前進する方向はx軸の正方向です。<br/>左右の速さ：加速度センサーの左右（y軸）の速さの値（範囲：-32768〜32767、初期値：0）タートルの左方向がy軸の正方向です。<br/>上下の速さ：加速度センサーの上下（z軸）の速さの値（範囲：-32768〜32767、初期値：0）タートルの上方向がz軸の正方向です。<br/>',\n            turtle_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            turtle_pick_head_led: '頭のLEDライトを選択された色にします。',\n        },\n        Blocks: {\n            turtle_acceleration_x: '前後の速さ',\n            turtle_acceleration_y: '左右の速さ',\n            turtle_acceleration_z: '上下の速さ',\n            turtle_back: '後',\n            turtle_both: '両方',\n            turtle_button: 'ボタン',\n            turtle_buzzer: 'ブザー',\n            turtle_clicked: 'クリック',\n            turtle_color_any: 'すべての色',\n            turtle_color_black: '黒',\n            turtle_color_blue: '青',\n            turtle_color_green: '緑',\n            turtle_color_number: '色番号',\n            turtle_color_orange: 'オレンジ',\n            turtle_color_pattern: '色のパターン',\n            turtle_color_purple: '紫',\n            turtle_color_red: '赤',\n            turtle_color_sky_blue: '水色',\n            turtle_color_violet: '赤紫',\n            turtle_color_white: '白',\n            turtle_color_yellow: '黄色',\n            turtle_double_clicked: 'ダブルクリック',\n            turtle_floor: '床センサー',\n            turtle_head: '前',\n            turtle_head_color: '頭のLEDの色',\n            turtle_left: '左',\n            turtle_left_wheel: '左の車輪',\n            turtle_long_pressed: '長押し',\n            turtle_note: '音符',\n            turtle_right: '右',\n            turtle_right_wheel: '右の車輪',\n            turtle_sound_beep: 'ビープ音',\n            turtle_sound_birthday: '誕生日',\n            turtle_sound_dibidibidip: 'ディビディビディップ',\n            turtle_sound_engine: 'エンジン',\n            turtle_sound_good_job: 'よくできました',\n            turtle_sound_march: '行進',\n            turtle_sound_random_beep: 'ビープ音のどれか',\n            turtle_sound_robot: 'ロボット',\n            turtle_sound_siren: 'サイレン',\n            turtle_tail: '後',\n            turtle_unit_cm: 'cm',\n            turtle_unit_deg: '°',\n            turtle_unit_pulse: 'パルス',\n            turtle_unit_sec: '秒',\n            turtle_note_c: 'ド',\n            turtle_note_c_sharp: 'ド♯(レ♭)',\n            turtle_note_d: 'レ',\n            turtle_note_d_sharp: 'レ♯(ミ♭)',\n            turtle_note_e: 'ミ',\n            turtle_note_f: 'ファ',\n            turtle_note_f_sharp: 'ファ♯(ソ♭)',\n            turtle_note_g: 'ソ',\n            turtle_note_g_sharp: 'ソ♯(ラ♭)',\n            turtle_note_a: 'ラ',\n            turtle_note_a_sharp: 'ラ♯(シ♭)',\n            turtle_note_b: 'シ',\n            turtle_tilt_forward: '前に傾けたか',\n            turtle_tilt_backward: '後に傾けたか',\n            turtle_tilt_left: '左に傾けたか',\n            turtle_tilt_right: '右に傾けたか',\n            turtle_tilt_flip: '上下裏返したか',\n            turtle_tilt_not: '傾けなかったか',\n            turtle_battery_normal: '電池が正常か',\n            turtle_battery_low: '電池が足りないか',\n            turtle_battery_empty: '電池がないか',\n        },\n    },\n    vn: {\n        template: {\n            turtle_button_state: 'button %1 ?',\n            turtle_change_buzzer_by: 'change buzzer by %1 %2',\n            turtle_change_head_led_by_rgb: 'change head led by r: %1 g: %2 b: %3 %4',\n            turtle_change_tempo_by: 'change tempo by %1 %2',\n            turtle_change_wheel_by: 'change %1 wheel by %2 %3',\n            turtle_change_wheels_by_left_right: 'change wheels by left: %1 right: %2 %3',\n            turtle_clear_head_led: 'clear head led %1',\n            turtle_clear_sound: 'clear sound %1',\n            turtle_cross_intersection: 'cross black intersection %1',\n            turtle_follow_line: 'follow %1 line %2',\n            turtle_follow_line_until: 'follow black line until %1 %2',\n            turtle_follow_line_until_black: 'follow %1 line until black %2',\n            turtle_is_color_pattern: 'color pattern %1 %2 ?',\n            turtle_move_backward_unit: 'move backward %1 %2 %3',\n            turtle_move_forward_unit: 'move forward %1 %2 %3',\n            turtle_pivot_around_wheel_unit_in_direction:\n                'pivot around %1 wheel %2 %3 in %4 direction %5',\n            turtle_play_note: 'play note %1 %2 %3',\n            turtle_play_note_for_beats: 'play note %1 %2 for %3 beats %4',\n            turtle_play_sound_times: 'play sound %1 %2 times %3',\n            turtle_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            turtle_rest_for_beats: 'rest for %1 beats %2',\n            turtle_set_buzzer_to: 'set buzzer to %1 %2',\n            turtle_set_following_speed_to: 'set following speed to %1 %2',\n            turtle_set_head_led_to: 'set head led to %1 %2',\n            turtle_set_head_led_to_rgb: 'set head led to r: %1 g: %2 b: %3 %4',\n            turtle_set_tempo_to: 'set tempo to %1 bpm %2',\n            turtle_set_wheel_to: 'set %1 wheel to %2 %3',\n            turtle_set_wheels_to_left_right: 'set wheels to left: %1 right: %2 %3',\n            turtle_stop: 'stop %1',\n            turtle_touching_color: 'touching %1 ?',\n            turtle_turn_at_intersection: 'turn %1 at black intersection %2',\n            turtle_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            turtle_turn_unit_with_radius_in_direction:\n                'turn %1 %2 %3 with radius %4 cm in %5 direction %6',\n            turtle_value: '%1',\n            turtle_boolean: '%1?',\n            turtle_pick_head_led: 'set head led to %1 %2',\n        },\n        Helper: {\n            turtle_button_state:\n                'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            turtle_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            turtle_change_head_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of the head LED, respectively.',\n            turtle_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            turtle_change_wheel_by:\n                'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            turtle_change_wheels_by_left_right:\n                'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            turtle_clear_head_led: 'Turns off the head LED.',\n            turtle_clear_sound: 'Turns off sound.',\n            turtle_cross_intersection:\n                'Moves forward for a moment at the black intersection, then finds the black line and moves again.',\n            turtle_follow_line: 'Moves along the selected color line on a white background.',\n            turtle_follow_line_until:\n                'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            turtle_follow_line_until_black:\n                'Moves along the selected color line on a white background and stops when the color sensor detects black.',\n            turtle_is_color_pattern:\n                'If the color sensor detects the selected color pattern, true, otherwise false.',\n            turtle_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            turtle_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            turtle_pivot_around_wheel_unit_in_direction:\n                'Pivots around the left/right wheel in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            turtle_play_note: 'It sounds the selected tone and octave.',\n            turtle_play_note_for_beats:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            turtle_play_sound_times: 'Plays the selected sound as many times as entered.',\n            turtle_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            turtle_rest_for_beats: 'Rests as much as the beat you entered.',\n            turtle_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            turtle_set_following_speed_to:\n                'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            turtle_set_head_led_to: 'Turns the head LED to the selected color.',\n            turtle_set_head_led_to_rgb:\n                'Sets the R, G, B values of the head LED to the entered values.',\n            turtle_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n            turtle_set_wheel_to:\n                'Sets the speed of the left/right/both wheels to the entered value (-400 to 400%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            turtle_set_wheels_to_left_right:\n                'Sets the speed of the left and right wheels to the entered values (-400 to 400%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            turtle_stop: 'Stops both wheels.',\n            turtle_touching_color:\n                'If the color sensor detects the selected color, true, otherwise false.',\n            turtle_turn_at_intersection:\n                'Moves forward for a moment at the black intersection, then turns left/right/back in place, finds the black line and moves again.',\n            turtle_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            turtle_turn_unit_with_radius_in_direction:\n                'Turns left/right drawing the circle of the entered radius in the head/tail direction for the number of degrees/seconds/pulses entered.',\n            turtle_value:\n                'color number: color number detected by the color sensor (range: -1 to 8, initial value: -1)<br/>color pattern: value of the color pattern detected by the color sensor (range: -1 ~ 88, initial value: -1) <br/>floor: value of floor sensor (range: 0 to 100, initial value: 0)<br/>button: status of the button (when pressed 1, otherwise 0, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.',\n            turtle_boolean:\n                'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            turtle_pick_head_led: 'Turns the head LED to the selected color.',\n        },\n        Blocks: {\n            turtle_acceleration_x: 'x acceleration',\n            turtle_acceleration_y: 'y acceleration',\n            turtle_acceleration_z: 'z acceleration',\n            turtle_back: 'back',\n            turtle_both: 'both',\n            turtle_button: 'button',\n            turtle_buzzer: 'buzzer',\n            turtle_clicked: 'clicked',\n            turtle_color_any: 'any color',\n            turtle_color_black: 'black',\n            turtle_color_blue: 'blue',\n            turtle_color_green: 'green',\n            turtle_color_number: 'color number',\n            turtle_color_orange: 'orange',\n            turtle_color_pattern: 'color pattern',\n            turtle_color_purple: 'purple',\n            turtle_color_red: 'red',\n            turtle_color_sky_blue: 'sky blue',\n            turtle_color_violet: 'violet',\n            turtle_color_white: 'white',\n            turtle_color_yellow: 'yellow',\n            turtle_double_clicked: 'double-clicked',\n            turtle_floor: 'floor',\n            turtle_head: 'head',\n            turtle_head_color: 'head color',\n            turtle_left: 'left',\n            turtle_left_wheel: 'left wheel',\n            turtle_long_pressed: 'long-pressed',\n            turtle_note: 'note',\n            turtle_right: 'right',\n            turtle_right_wheel: 'right wheel',\n            turtle_sound_beep: 'beep',\n            turtle_sound_birthday: 'birthday',\n            turtle_sound_dibidibidip: 'dibidibidip',\n            turtle_sound_engine: 'engine',\n            turtle_sound_good_job: 'good job',\n            turtle_sound_march: 'march',\n            turtle_sound_random_beep: 'random beep',\n            turtle_sound_robot: 'robot',\n            turtle_sound_siren: 'siren',\n            turtle_tail: 'tail',\n            turtle_unit_cm: 'cm',\n            turtle_unit_deg: 'degrees',\n            turtle_unit_pulse: 'pulses',\n            turtle_unit_sec: 'seconds',\n            turtle_note_c: 'C',\n            turtle_note_c_sharp: 'C♯(D♭)',\n            turtle_note_d: 'D',\n            turtle_note_d_sharp: 'D♯(E♭)',\n            turtle_note_e: 'E',\n            turtle_note_f: 'F',\n            turtle_note_f_sharp: 'F♯(G♭)',\n            turtle_note_g: 'G',\n            turtle_note_g_sharp: 'G♯(A♭)',\n            turtle_note_a: 'A',\n            turtle_note_a_sharp: 'A♯(B♭)',\n            turtle_note_b: 'B',\n            turtle_tilt_forward: 'tilt forward',\n            turtle_tilt_backward: 'tilt backward',\n            turtle_tilt_left: 'tilt left',\n            turtle_tilt_right: 'tilt right',\n            turtle_tilt_flip: 'tilt flip',\n            turtle_tilt_not: 'not tilt',\n            turtle_battery_normal: 'battery normal',\n            turtle_battery_low: 'battery low',\n            turtle_battery_empty: 'battery empty',\n        },\n    },\n});\n\nEntry.Turtle.blockMenuBlocks = [\n    'turtle_touching_color',\n    'turtle_is_color_pattern',\n    'turtle_button_state',\n    'turtle_boolean',\n    'turtle_value',\n    'turtle_move_forward_unit',\n    'turtle_move_backward_unit',\n    'turtle_turn_unit_in_place',\n    'turtle_pivot_around_wheel_unit_in_direction',\n    'turtle_turn_unit_with_radius_in_direction',\n    'turtle_change_wheels_by_left_right',\n    'turtle_set_wheels_to_left_right',\n    'turtle_change_wheel_by',\n    'turtle_set_wheel_to',\n    'turtle_follow_line',\n    'turtle_follow_line_until',\n    'turtle_follow_line_until_black',\n    'turtle_cross_intersection',\n    'turtle_turn_at_intersection',\n    'turtle_set_following_speed_to',\n    'turtle_stop',\n    'turtle_set_head_led_to',\n    'turtle_pick_head_led',\n    'turtle_change_head_led_by_rgb',\n    'turtle_set_head_led_to_rgb',\n    'turtle_clear_head_led',\n    'turtle_play_sound_times',\n    'turtle_play_sound_times_until_done',\n    'turtle_change_buzzer_by',\n    'turtle_set_buzzer_to',\n    'turtle_clear_sound',\n    'turtle_play_note',\n    'turtle_play_note_for_beats',\n    'turtle_rest_for_beats',\n    'turtle_change_tempo_by',\n    'turtle_set_tempo_to',\n];\n\nEntry.Turtle.getBlocks = function() {\n    return {\n        turtle_touching_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '2'],\n                        [Lang.Blocks.turtle_color_orange, '3'],\n                        [Lang.Blocks.turtle_color_yellow, '4'],\n                        [Lang.Blocks.turtle_color_green, '5'],\n                        [Lang.Blocks.turtle_color_sky_blue, '6'],\n                        [Lang.Blocks.turtle_color_blue, '7'],\n                        [Lang.Blocks.turtle_color_purple, '8'],\n                        [Lang.Blocks.turtle_color_black, '1'],\n                        [Lang.Blocks.turtle_color_white, '9'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'turtle_touching_color',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.checkTouchingColor(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.is_color_red()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['2'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_orange()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['3'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_yellow()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['4'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_green()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['5'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_sky_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['6'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['7'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_purple()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['8'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_black()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['1'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_white()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '2'],\n                                    [Lang.Blocks.turtle_color_orange, '3'],\n                                    [Lang.Blocks.turtle_color_yellow, '4'],\n                                    [Lang.Blocks.turtle_color_green, '5'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '6'],\n                                    [Lang.Blocks.turtle_color_blue, '7'],\n                                    [Lang.Blocks.turtle_color_purple, '8'],\n                                    [Lang.Blocks.turtle_color_black, '1'],\n                                    [Lang.Blocks.turtle_color_white, '9'],\n                                ],\n                                value: '2',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['9'],\n                    },\n                ],\n            },\n        },\n        turtle_is_color_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '1'],\n                        [Lang.Blocks.turtle_color_yellow, '3'],\n                        [Lang.Blocks.turtle_color_green, '4'],\n                        [Lang.Blocks.turtle_color_sky_blue, '5'],\n                        [Lang.Blocks.turtle_color_blue, '6'],\n                        [Lang.Blocks.turtle_color_purple, '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '1'],\n                        [Lang.Blocks.turtle_color_yellow, '3'],\n                        [Lang.Blocks.turtle_color_green, '4'],\n                        [Lang.Blocks.turtle_color_sky_blue, '5'],\n                        [Lang.Blocks.turtle_color_blue, '6'],\n                        [Lang.Blocks.turtle_color_purple, '7'],\n                    ],\n                    value: '3',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'turtle_is_color_pattern',\n            },\n            paramsKeyMap: {\n                COLOR1: 0,\n                COLOR2: 1,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.checkColorPattern(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.is_color_pattern_red_red()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['1', '1'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_red_yellow()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['1', '3'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_red_green()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['1', '4'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_red_sky_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['1', '5'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_red_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['1', '6'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_red_purple()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['1', '7'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_yellow_red()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['3', '1'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_yellow_yellow()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['3', '3'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_yellow_green()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['3', '4'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_yellow_sky_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['3', '5'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_yellow_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['3', '6'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_yellow_purple()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['3', '7'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_green_red()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['4', '1'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_green_yellow()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['4', '3'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_green_green()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['4', '4'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_green_sky_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['4', '5'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_green_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['4', '6'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_green_purple()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['4', '7'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_sky_blue_red()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['5', '1'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_sky_blue_yellow()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['5', '3'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_sky_blue_green()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['5', '4'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_sky_blue_sky_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['5', '5'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_sky_blue_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['5', '6'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_sky_blue_purple()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['5', '7'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_blue_red()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['6', '1'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_blue_yellow()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['6', '3'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_blue_green()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['6', '4'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_blue_sky_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['6', '5'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_blue_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['6', '6'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_blue_purple()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['6', '7'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_purple_red()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['7', '1'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_purple_yellow()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['7', '3'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_purple_green()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['7', '4'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_purple_sky_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['7', '5'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_purple_blue()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['7', '6'],\n                    },\n                    {\n                        syntax: 'Turtle.is_color_pattern_purple_purple()',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '1'],\n                                    [Lang.Blocks.turtle_color_yellow, '3'],\n                                    [Lang.Blocks.turtle_color_green, '4'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '5'],\n                                    [Lang.Blocks.turtle_color_blue, '6'],\n                                    [Lang.Blocks.turtle_color_purple, '7'],\n                                ],\n                                value: '3',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['7', '7'],\n                    },\n                ],\n            },\n        },\n        turtle_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_clicked, 'clicked'],\n                        [Lang.Blocks.turtle_double_clicked, 'doubleClicked'],\n                        [Lang.Blocks.turtle_long_pressed, 'longPressed'],\n                    ],\n                    value: 'clicked',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'turtle_button_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.checkButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.is_button(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_clicked, 'clicked'],\n                                    [Lang.Blocks.turtle_double_clicked, 'doubleClicked'],\n                                    [Lang.Blocks.turtle_long_pressed, 'longPressed'],\n                                ],\n                                value: 'clicked',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.turtle_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.turtle_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.turtle_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.turtle_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.turtle_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.turtle_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.turtle_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.turtle_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'turtle_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.turtle_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.turtle_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.turtle_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.turtle_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.turtle_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.turtle_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.turtle_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.turtle_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_number, 'colorNumber'],\n                        [Lang.Blocks.turtle_color_pattern, 'colorPattern'],\n                        [Lang.Blocks.turtle_floor, 'floor'],\n                        [Lang.Blocks.turtle_button, 'button'],\n                        [Lang.Blocks.turtle_acceleration_x, 'accelerationX'],\n                        [Lang.Blocks.turtle_acceleration_y, 'accelerationY'],\n                        [Lang.Blocks.turtle_acceleration_z, 'accelerationZ'],\n                    ],\n                    value: 'colorNumber',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'turtle_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'turtle_sensor',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_number, 'colorNumber'],\n                                    [Lang.Blocks.turtle_color_pattern, 'colorPattern'],\n                                    [Lang.Blocks.turtle_floor, 'floor'],\n                                    [Lang.Blocks.turtle_button, 'button'],\n                                    [Lang.Blocks.turtle_acceleration_x, 'accelerationX'],\n                                    [Lang.Blocks.turtle_acceleration_y, 'accelerationY'],\n                                    [Lang.Blocks.turtle_acceleration_z, 'accelerationZ'],\n                                ],\n                                value: 'colorNumber',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_cm, 'CM'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'turtle_move_forward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.move_forward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_cm, 'CM'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_cm, 'CM'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'turtle_move_backward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.move_backward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_cm, 'CM'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'turtle_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_turn_unit_with_radius_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.turtle_head, 'HEAD'], [Lang.Blocks.turtle_tail, 'TAIL']],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'turtle_turn_unit_with_radius_in_direction',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n                RADIUS: 3,\n                TOWARD: 4,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.swingUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.circle(%1, %2, %3, %4, %5)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_head, 'HEAD'],\n                                    [Lang.Blocks.turtle_tail, 'TAIL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_pivot_around_wheel_unit_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                        [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                        [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [[Lang.Blocks.turtle_head, 'HEAD'], [Lang.Blocks.turtle_tail, 'TAIL']],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'turtle_pivot_around_wheel_unit_in_direction',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VALUE: 1,\n                UNIT: 2,\n                TOWARD: 3,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.pivotUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.pivot(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_unit_deg, 'DEG'],\n                                    [Lang.Blocks.turtle_unit_sec, 'SEC'],\n                                    [Lang.Blocks.turtle_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_head, 'HEAD'],\n                                    [Lang.Blocks.turtle_tail, 'TAIL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_change_wheels_by_left_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'turtle_change_wheels_by_left_right',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_set_wheels_to_left_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'turtle_set_wheels_to_left_right',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                        [Lang.Blocks.turtle_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'turtle_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                    [Lang.Blocks.turtle_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, 'LEFT'],\n                        [Lang.Blocks.turtle_right, 'RIGHT'],\n                        [Lang.Blocks.turtle_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'turtle_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, 'LEFT'],\n                                    [Lang.Blocks.turtle_right, 'RIGHT'],\n                                    [Lang.Blocks.turtle_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_follow_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_black, '10'],\n                        [Lang.Blocks.turtle_color_red, '11'],\n                        [Lang.Blocks.turtle_color_green, '13'],\n                        [Lang.Blocks.turtle_color_blue, '15'],\n                        [Lang.Blocks.turtle_color_any, '17'],\n                    ],\n                    value: '10',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'turtle_follow_line',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.follow_black_line()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['10'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_red_line()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['11'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_green_line()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['13'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_blue_line()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['15'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_any_line()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_black, '10'],\n                                    [Lang.Blocks.turtle_color_red, '11'],\n                                    [Lang.Blocks.turtle_color_green, '13'],\n                                    [Lang.Blocks.turtle_color_blue, '15'],\n                                    [Lang.Blocks.turtle_color_any, '17'],\n                                ],\n                                value: '10',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['17'],\n                    },\n                ],\n            },\n        },\n        turtle_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '61'],\n                        [Lang.Blocks.turtle_color_yellow, '62'],\n                        [Lang.Blocks.turtle_color_green, '63'],\n                        [Lang.Blocks.turtle_color_sky_blue, '64'],\n                        [Lang.Blocks.turtle_color_blue, '65'],\n                        [Lang.Blocks.turtle_color_purple, '66'],\n                        [Lang.Blocks.turtle_color_any, '67'],\n                    ],\n                    value: '61',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'turtle_follow_line_until',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.follow_black_line_until_red()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['61'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_black_line_until_yellow()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['62'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_black_line_until_green()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['63'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_black_line_until_sky_blue()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['64'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_black_line_until_blue()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['65'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_black_line_until_purple()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['66'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_black_line_until_any()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '61'],\n                                    [Lang.Blocks.turtle_color_yellow, '62'],\n                                    [Lang.Blocks.turtle_color_green, '63'],\n                                    [Lang.Blocks.turtle_color_sky_blue, '64'],\n                                    [Lang.Blocks.turtle_color_blue, '65'],\n                                    [Lang.Blocks.turtle_color_purple, '66'],\n                                    [Lang.Blocks.turtle_color_any, '67'],\n                                ],\n                                value: '61',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['67'],\n                    },\n                ],\n            },\n        },\n        turtle_follow_line_until_black: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, '71'],\n                        [Lang.Blocks.turtle_color_green, '73'],\n                        [Lang.Blocks.turtle_color_blue, '75'],\n                        [Lang.Blocks.turtle_color_any, '77'],\n                    ],\n                    value: '71',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'turtle_follow_line_until_black',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.followLineUntilBlack(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.follow_red_line_until_black()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '71'],\n                                    [Lang.Blocks.turtle_color_green, '73'],\n                                    [Lang.Blocks.turtle_color_blue, '75'],\n                                    [Lang.Blocks.turtle_color_any, '77'],\n                                ],\n                                value: '71',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['71'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_green_line_until_black()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '71'],\n                                    [Lang.Blocks.turtle_color_green, '73'],\n                                    [Lang.Blocks.turtle_color_blue, '75'],\n                                    [Lang.Blocks.turtle_color_any, '77'],\n                                ],\n                                value: '71',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['73'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_blue_line_until_black()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '71'],\n                                    [Lang.Blocks.turtle_color_green, '73'],\n                                    [Lang.Blocks.turtle_color_blue, '75'],\n                                    [Lang.Blocks.turtle_color_any, '77'],\n                                ],\n                                value: '71',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['75'],\n                    },\n                    {\n                        syntax: 'Turtle.follow_any_line_until_black()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, '71'],\n                                    [Lang.Blocks.turtle_color_green, '73'],\n                                    [Lang.Blocks.turtle_color_blue, '75'],\n                                    [Lang.Blocks.turtle_color_any, '77'],\n                                ],\n                                value: '71',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['77'],\n                    },\n                ],\n            },\n        },\n        turtle_cross_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'turtle_cross_intersection',\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.crossIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.cross_forward()',\n                    },\n                ],\n            },\n        },\n        turtle_turn_at_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_left, '20'],\n                        [Lang.Blocks.turtle_right, '30'],\n                        [Lang.Blocks.turtle_back, '50'],\n                    ],\n                    value: '20',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'turtle_turn_at_intersection',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.turnAtIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.cross_left()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, '20'],\n                                    [Lang.Blocks.turtle_right, '30'],\n                                    [Lang.Blocks.turtle_back, '50'],\n                                ],\n                                value: '20',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['20'],\n                    },\n                    {\n                        syntax: 'Turtle.cross_right()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, '20'],\n                                    [Lang.Blocks.turtle_right, '30'],\n                                    [Lang.Blocks.turtle_back, '50'],\n                                ],\n                                value: '20',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['30'],\n                    },\n                    {\n                        syntax: 'Turtle.cross_uturn()',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_left, '20'],\n                                    [Lang.Blocks.turtle_right, '30'],\n                                    [Lang.Blocks.turtle_back, '50'],\n                                ],\n                                value: '20',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                        params: ['50'],\n                    },\n                ],\n            },\n        },\n        turtle_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['5', null],\n                type: 'turtle_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.set_line_speed(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'turtle_stop',\n            },\n            class: 'turtle_wheel',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.stop()',\n                    },\n                ],\n            },\n        },\n        turtle_set_head_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_color_red, 'RED'],\n                        [Lang.Blocks.turtle_color_orange, 'ORANGE'],\n                        [Lang.Blocks.turtle_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.turtle_color_green, 'GREEN'],\n                        [Lang.Blocks.turtle_color_sky_blue, 'CYAN'],\n                        [Lang.Blocks.turtle_color_blue, 'BLUE'],\n                        [Lang.Blocks.turtle_color_violet, 'VIOLET'],\n                        [Lang.Blocks.turtle_color_purple, 'MAGENTA'],\n                        [Lang.Blocks.turtle_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'turtle_set_head_led_to',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'turtle_led',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.setHeadColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.set_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_color_red, 'RED'],\n                                    [Lang.Blocks.turtle_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.turtle_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.turtle_color_green, 'GREEN'],\n                                    [Lang.Blocks.turtle_color_sky_blue, 'CYAN'],\n                                    [Lang.Blocks.turtle_color_blue, 'BLUE'],\n                                    [Lang.Blocks.turtle_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.turtle_color_purple, 'MAGENTA'],\n                                    [Lang.Blocks.turtle_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_pick_head_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'turtle_pick_head_led',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'turtle_led',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.pickHeadColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.pick_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_change_head_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'turtle_change_head_led_by_rgb',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'turtle_led',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.changeHeadRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.add_rgb(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_set_head_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'turtle_set_head_led_to_rgb',\n            },\n            paramsKeyMap: {\n                RED: 0,\n                GREEN: 1,\n                BLUE: 2,\n            },\n            class: 'turtle_led',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.setHeadRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.set_rgb(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_clear_head_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'turtle_clear_head_led',\n            },\n            class: 'turtle_led',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.clearHead(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.clear_led()',\n                    },\n                ],\n            },\n        },\n        turtle_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_sound_beep, '1'],\n                        [Lang.Blocks.turtle_sound_random_beep, '2'],\n                        [Lang.Blocks.turtle_sound_siren, '3'],\n                        [Lang.Blocks.turtle_sound_engine, '4'],\n                        [Lang.Blocks.turtle_sound_robot, '5'],\n                        [Lang.Blocks.turtle_sound_march, '6'],\n                        [Lang.Blocks.turtle_sound_birthday, '7'],\n                        [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                        [Lang.Blocks.turtle_sound_good_job, '9'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'turtle_play_sound_times',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.play_sound_beep(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['1'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_random_beep(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['2'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_siren(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['3'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_engine(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['4'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_robot(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['5'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_march(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['6'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_birthday(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['7'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_dibidibidip(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['8'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_good_job(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['9'],\n                    },\n                ],\n            },\n        },\n        turtle_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_sound_beep, '1'],\n                        [Lang.Blocks.turtle_sound_random_beep, '2'],\n                        [Lang.Blocks.turtle_sound_siren, '3'],\n                        [Lang.Blocks.turtle_sound_engine, '4'],\n                        [Lang.Blocks.turtle_sound_robot, '5'],\n                        [Lang.Blocks.turtle_sound_march, '6'],\n                        [Lang.Blocks.turtle_sound_birthday, '7'],\n                        [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                        [Lang.Blocks.turtle_sound_good_job, '9'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'turtle_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.play_sound_until_done_beep(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['1'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_until_done_random_beep(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['2'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_until_done_siren(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['3'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_until_done_engine(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['4'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_until_done_robot(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['5'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_until_done_march(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['6'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_until_done_birthday(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['7'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_until_done_dibidibidip(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['8'],\n                    },\n                    {\n                        syntax: 'Turtle.play_sound_until_done_good_job(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_sound_beep, '1'],\n                                    [Lang.Blocks.turtle_sound_random_beep, '2'],\n                                    [Lang.Blocks.turtle_sound_siren, '3'],\n                                    [Lang.Blocks.turtle_sound_engine, '4'],\n                                    [Lang.Blocks.turtle_sound_robot, '5'],\n                                    [Lang.Blocks.turtle_sound_march, '6'],\n                                    [Lang.Blocks.turtle_sound_birthday, '7'],\n                                    [Lang.Blocks.turtle_sound_dibidibidip, '8'],\n                                    [Lang.Blocks.turtle_sound_good_job, '9'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['9'],\n                    },\n                ],\n            },\n        },\n        turtle_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'turtle_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.add_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        turtle_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'turtle_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.set_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        turtle_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'turtle_clear_sound',\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.clear_sound()',\n                    },\n                ],\n            },\n        },\n        turtle_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_note_c, '4'],\n                        [Lang.Blocks.turtle_note_c_sharp, '5'],\n                        [Lang.Blocks.turtle_note_d, '6'],\n                        [Lang.Blocks.turtle_note_d_sharp, '7'],\n                        [Lang.Blocks.turtle_note_e, '8'],\n                        [Lang.Blocks.turtle_note_f, '9'],\n                        [Lang.Blocks.turtle_note_f_sharp, '10'],\n                        [Lang.Blocks.turtle_note_g, '11'],\n                        [Lang.Blocks.turtle_note_g_sharp, '12'],\n                        [Lang.Blocks.turtle_note_a, '13'],\n                        [Lang.Blocks.turtle_note_a_sharp, '14'],\n                        [Lang.Blocks.turtle_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'turtle_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.play_pitch_c(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['4'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_c_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['5'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_d(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['6'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_d_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['7'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_e(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['8'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_f(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['9'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_f_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['10'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_g(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['11'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_g_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['12'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_a(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['13'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_a_sharp(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['14'],\n                    },\n                    {\n                        syntax: 'Turtle.play_pitch_b(%2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                        params: ['15'],\n                    },\n                ],\n            },\n        },\n        turtle_play_note_for_beats: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turtle_note_c, '4'],\n                        [Lang.Blocks.turtle_note_c_sharp, '5'],\n                        [Lang.Blocks.turtle_note_d, '6'],\n                        [Lang.Blocks.turtle_note_d_sharp, '7'],\n                        [Lang.Blocks.turtle_note_e, '8'],\n                        [Lang.Blocks.turtle_note_f, '9'],\n                        [Lang.Blocks.turtle_note_f_sharp, '10'],\n                        [Lang.Blocks.turtle_note_g, '11'],\n                        [Lang.Blocks.turtle_note_g_sharp, '12'],\n                        [Lang.Blocks.turtle_note_a, '13'],\n                        [Lang.Blocks.turtle_note_a_sharp, '14'],\n                        [Lang.Blocks.turtle_note_b, '15'],\n                    ],\n                    value: '4',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'turtle_play_note_for_beats',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.play_note_c(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['4'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_c_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['5'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_d(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['6'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_d_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['7'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_e(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['8'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_f(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['9'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_f_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['10'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_g(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['11'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_g_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['12'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_a(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['13'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_a_sharp(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['14'],\n                    },\n                    {\n                        syntax: 'Turtle.play_note_b(%2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.turtle_note_c, '4'],\n                                    [Lang.Blocks.turtle_note_c_sharp, '5'],\n                                    [Lang.Blocks.turtle_note_d, '6'],\n                                    [Lang.Blocks.turtle_note_d_sharp, '7'],\n                                    [Lang.Blocks.turtle_note_e, '8'],\n                                    [Lang.Blocks.turtle_note_f, '9'],\n                                    [Lang.Blocks.turtle_note_f_sharp, '10'],\n                                    [Lang.Blocks.turtle_note_g, '11'],\n                                    [Lang.Blocks.turtle_note_g_sharp, '12'],\n                                    [Lang.Blocks.turtle_note_a, '13'],\n                                    [Lang.Blocks.turtle_note_a_sharp, '14'],\n                                    [Lang.Blocks.turtle_note_b, '15'],\n                                ],\n                                value: '4',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            { type: 'Block', accept: 'string' },\n                        ],\n                        params: ['15'],\n                    },\n                ],\n            },\n        },\n        turtle_rest_for_beats: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'turtle_rest_for_beats',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.rest(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'turtle_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        turtle_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'turtle_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'turtle_sound',\n            isNotFor: ['turtle'],\n            func(sprite, script) {\n                const robot = Entry.Turtle.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Turtle.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Turtle;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_uglybot.js",
    "content": "'use strict';\n\nEntry.UglyBot = {\n    Cmd: {\n        CMD_GOLDENKEY0: 0,\n        CMD_GOLDENKEY1: 1,\n        CMD_GOLDENKEY2: 2,\n        CMD_GOLDENKEY3: 3,\n        CMD_LENGTH: 4,\n        CMD_CHECKSUM: 5,\n        CMD_LED: 6,\n        CMD_BUZZER_TUNE: 7,\n        CMD_BUZZER_DELAY: 8,\n        CMD_MOTOR_RIGHT: 9,\n        CMD_MOTOR_LEFT: 10,\n        CMD_MOVE_LOW: 11,\n        CMD_MOVE_HIGH: 12,\n        CMD_ROT_LOW: 13,\n        CMD_ROT_HIGH: 14,\n        CMD_SERVO1: 15,\n        CMD_SERVO2: 16,\n        CMD_IRPIN: 17,\n    },\n    Sensor: {\n        ENSOR_GOLDENKEY0: 0,\n        ENSOR_GOLDENKEY1: 1,\n        ENSOR_GOLDENKEY2: 2,\n        ENSOR_GOLDENKEY3: 3,\n        ENSOR_LENGTH: 4,\n        ENSOR_CHECKSUM: 5,\n        ENSOR_EXBOARDTYPE: 6,\n        SENSOR_BUTTON: 7,\n        SENSOR_IR_LEFT: 8,\n        SENSOR_IR_MID: 9,\n        SENSOR_IR_RIGHT: 10,\n        SENSOR_ULTRASONIC: 11,\n        SENSOR_JOYSTICK_LR: 12,\n        SENSOR_JOYSTICK_TB: 13,\n        SENSOR_GYRO_LR: 14,\n        SENSOR_GYRO_TB: 15,\n        SENSOR_SOUND: 16,\n        SENSOR_PHOTO: 17,\n    },\n    setZero() {\n        Entry.hw.sendQueue.CMD = [\n            0x26,\n            0xa8,\n            0x14,\n            0xe1,\n            0x14,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n            0x00,\n        ];\n        Entry.hw.update();\n    },\n    id: '1D.3',\n    name: 'UglyBot',\n    url: 'http://www.junilab.co.kr',\n    imageName: 'uglybot.png',\n    title: {\n        en: 'UglyBot',\n        ko: '어글리봇',\n    },\n    monitorTemplate: {\n        imgPath: 'hw/uglybot.png',\n        width: 600,\n        height: 460,\n        listPorts: {\n            A6: {\n                name: '조이스틱좌우',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A7: {\n                name: '조이스틱앞뒤',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A8: {\n                name: '기울기센서좌우',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A9: {\n                name: '기울기센서앞뒤',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A10: {\n                name: '소리센서',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n            A11: {\n                name: '조도센서',\n                type: 'input',\n                pos: {\n                    x: 0,\n                    y: 0,\n                },\n            },\n        },\n        ports: {\n            A0: {\n                name: '확장보드',\n                type: 'input',\n                pos: {\n                    x: 280,\n                    y: 230,\n                },\n            },\n            A1: {\n                name: '버튼',\n                type: 'input',\n                pos: {\n                    x: 585,\n                    y: 160,\n                },\n            },\n            A2: {\n                name: '왼쪽 적외선센서',\n                type: 'input',\n                pos: {\n                    x: 200,\n                    y: 310,\n                },\n            },\n            A3: {\n                name: '중간 적외선센서',\n                type: 'input',\n                pos: {\n                    x: 200,\n                    y: 230,\n                },\n            },\n            A4: {\n                name: '오른쪽 적외선센서',\n                type: 'input',\n                pos: {\n                    x: 200,\n                    y: 160,\n                },\n            },\n            A5: {\n                name: '초음파센서',\n                type: 'input',\n                pos: {\n                    x: 20,\n                    y: 140,\n                },\n            },\n        },\n        mode: 'both',\n    },\n};\n\nEntry.UglyBot.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                uglybot_led: '%1 LED %2 %3',\n                uglybot_buzzer: '%1 음을 %2초동안 소리내기 %3',\n                uglybot_motor: '%1모터를 %2세기로 회전 %3',\n                uglybot_move: '%1(으)로 %2cm 이동 %3',\n                uglybot_rotation: '%1방향으로 %2도 회전 %3',\n                uglybot_servo: '%1번 서보모터를 %2도 회전 %3',\n                uglybot_irpin: '%1 적외선 센서 %2 %3',\n                uglybot_button: '버튼 값',\n                uglybot_ir: '%1 적외선센서 값',\n                uglybot_ultrasonic: '초음파센서 값',\n                uglybot_joystick: '%1 조이스틱 값',\n                uglybot_tilt: '%1 기울기 값',\n                uglybot_sound: '소리센서 값',\n                uglybot_illum: '조도센서 값',\n                uglybot_left: '왼쪽',\n                uglybot_mid: '중간',\n                uglybot_right: '오른쪽',\n                uglybot_on: '켜기',\n                uglybot_off: '끄기',\n                uglybot_do: '도',\n                uglybot_re: '레',\n                uglybot_mi: '미',\n                uglybot_fa: '파',\n                uglybot_sol: '솔',\n                uglybot_ra: '라',\n                uglybot_si: '시',\n                uglybot_front: '앞',\n                uglybot_back: '뒤',\n                uglybot_cc: '시계',\n                uglybot_rcc: '반시계',\n                uglybot_topbottom: '앞뒤',\n                uglybot_leftright: '좌우',\n            },\n            Blocks: {\n                uglybot_joystick_lr: '조이스틱좌우',\n                uglybot_yoystick_tb: '조이스틱앞뒤',\n                uglybot_gyro_lr: '기울기센서좌우',\n                uglybot_gyro_tb: '기울기센서앞뒤',\n                uglybot_sound2: '소리센서',\n                uglybot_photo2: '조도센서',\n                uglybot_exboard: '확장보드',\n                uglybot_button2: '버튼',\n                uglybot_irleft: '왼쪽 적외선센서',\n                uglybot_irmid: '중간 적외선센서',\n                uglybot_irright: '오른쪽 적외선센서',\n                uglybot_ultrsonic2: '초음파센서',\n            },\n        },\n        en: {\n            template: {\n                uglybot_led: '%1 LED %2 %3',\n                uglybot_buzzer: '%1 음을 %2초동안 소리내기 %3',\n                uglybot_motor: '%1모터를 %2세기로 회전 %3',\n                uglybot_move: '%1(으)로 %2cm 이동 %3',\n                uglybot_rotation: '%1(으)로 %2도 회전 %3',\n                uglybot_servo: '%1번 서보모터를 %2도 회전 %3',\n                uglybot_irpin: '%1 적외선 센서 %2 %3',\n                uglybot_button: '버튼 값',\n                uglybot_ir: '%1 적외선센서 값',\n                uglybot_ultrasonic: '초음파센서 값',\n                uglybot_joystick: '%1 조이스틱 값',\n                uglybot_tilt: '%1 기울기 값',\n                uglybot_sound: '소리센서 값',\n                uglybot_illum: '조도센서 값',\n                uglybot_left: '왼쪽',\n                uglybot_mid: '중간',\n                uglybot_right: '오른쪽',\n                uglybot_on: '켜기',\n                uglybot_off: '끄기',\n                uglybot_do: '도',\n                uglybot_re: '레',\n                uglybot_mi: '미',\n                uglybot_fa: '파',\n                uglybot_sol: '솔',\n                uglybot_ra: '라',\n                uglybot_si: '시',\n                uglybot_front: '앞',\n                uglybot_back: '뒤',\n                uglybot_cc: '시계',\n                uglybot_rcc: '반시계',\n                uglybot_topbottom: '앞뒤',\n                uglybot_leftright: '좌우',\n            },\n            Blocks: {\n                uglybot_joystick_lr: '조이스틱좌우',\n                uglybot_yoystick_tb: '조이스틱앞뒤',\n                uglybot_gyro_lr: '기울기센서좌우',\n                uglybot_gyro_tb: '기울기센서앞뒤',\n                uglybot_sound2: '소리센서',\n                uglybot_photo2: '조도센서',\n                uglybot_exboard: '확장보드',\n                uglybot_button2: '버튼',\n                uglybot_irleft: '왼쪽 적외선센서',\n                uglybot_irmid: '중간 적외선센서',\n                uglybot_irright: '오른쪽 적외선센서',\n                uglybot_ultrsonic2: '초음파센서',\n            },\n        },\n    };\n};\n\nEntry.UglyBot.blockMenuBlocks = [\n    'uglybot_led',\n    'uglybot_buzzer',\n    'uglybot_motor',\n    'uglybot_move',\n    'uglybot_rotation',\n    'uglybot_servo',\n    'uglybot_irpin',\n    'uglybot_button',\n    'uglybot_ir',\n    'uglybot_ultrasonic',\n    'uglybot_joystick',\n    'uglybot_tilt',\n    'uglybot_sound',\n    'uglybot_illum',\n];\n\nEntry.UglyBot.getBlocks = function() {\n    let noteID = 1;\n    let moveID = 1;\n    let rotID = 1;\n    let oldSensorData = [0x26, 0xa8, 0x14, 0xe1, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n    return {\n        //region UglyBot\n        uglybot_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_right, 0],\n                        [Lang.template.uglybot_left, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_on, 0],\n                        [Lang.template.uglybot_off, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_led',\n            },\n            paramsKeyMap: {\n                LED_WHAT: 0,\n                LED_ACTION: 1,\n            },\n            class: 'UglyBot_Command',\n            isNotFor: ['UglyBot'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const what = script.getNumberValue('LED_WHAT', script);\n                const act = script.getNumberValue('LED_ACTION', script);\n                if (act == 0) {\n                    cmd[Entry.UglyBot.Cmd.CMD_LED] |= 0x01 << what;\n                } else {\n                    cmd[Entry.UglyBot.Cmd.CMD_LED] &= ~(0x01 << what);\n                }\n                cmd[Entry.UglyBot.Cmd.CMD_LED] |= 0x10;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_do, 1],\n                        [Lang.template.uglybot_re, 2],\n                        [Lang.template.uglybot_mi, 3],\n                        [Lang.template.uglybot_fa, 4],\n                        [Lang.template.uglybot_sol, 5],\n                        [Lang.template.uglybot_ra, 6],\n                        [Lang.template.uglybot_si, 7],\n                    ],\n                    value: 1,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0.5', 5],\n                        ['0.8', 8],\n                        ['1', 10],\n                        ['2', 20],\n                        ['3', 30],\n                        ['4', 40],\n                        ['5', 50],\n                    ],\n                    value: 10,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_buzzer',\n            },\n            paramsKeyMap: {\n                BUZZER_NOTE: 0,\n                BUZZER_DELAY: 1,\n            },\n            class: 'UglyBot_Command',\n            isNotFor: ['UglyBot'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const note = script.getNumberValue('BUZZER_NOTE', script);\n                const delay = script.getNumberValue('BUZZER_DELAY', script);\n\n                cmd[Entry.UglyBot.Cmd.CMD_BUZZER_TUNE] = note | (noteID << 4);\n                cmd[Entry.UglyBot.Cmd.CMD_BUZZER_DELAY] = delay;\n                noteID = (noteID + 1) & 0x0f;\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_motor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_right, 0],\n                        [Lang.template.uglybot_left, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_motor',\n            },\n            paramsKeyMap: {\n                MOTOR_WHAT: 0,\n                MOTOR_SPEED: 1,\n            },\n            class: 'UglyBot_Command',\n            isNotFor: ['UglyBot'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const what = script.getNumberValue('MOTOR_WHAT', script);\n                let speed = script.getNumberValue('MOTOR_SPEED', script);\n                if (speed > 100) {\n                    speed = 100;\n                } else if (speed < -100) {\n                    speed = -100;\n                }\n                cmd[Entry.UglyBot.Cmd.CMD_MOTOR_RIGHT + what] = speed;\n                //console.log(\"%d %d\", \twhat, speed);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_move: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_front, 0],\n                        [Lang.template.uglybot_back, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_move',\n            },\n            paramsKeyMap: {\n                MOVE_DIRECTION: 0,\n                MOVE_DISTANCE: 1,\n            },\n            class: 'UglyBot_Command',\n            isNotFor: ['UglyBot'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const direction = script.getNumberValue('MOVE_DIRECTION', script);\n                let distance = script.getNumberValue('MOVE_DISTANCE', script);\n                distance = direction == 1 ? -1 * distance : distance;\n                if (distance > 1000) {\n                    distance = 1000;\n                } else if (distance < -1000) {\n                    distance = -1000;\n                }\n                cmd[Entry.UglyBot.Cmd.CMD_MOVE_LOW] = distance & 0xff;\n                cmd[Entry.UglyBot.Cmd.CMD_MOVE_HIGH] = (distance >> 8) & 0x0f;\n                cmd[Entry.UglyBot.Cmd.CMD_MOVE_HIGH] |= moveID << 4;\n                moveID = (moveID + 1) & 0x0f;\n                //console.log(\"distance:%d moveID:%d\", \tdistance, moveID);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_rotation: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_cc, 0],\n                        [Lang.template.uglybot_rcc, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_rotation',\n            },\n            paramsKeyMap: {\n                ROT_DIRECTION: 0,\n                ROT_DEGREE: 1,\n            },\n            class: 'UglyBot_Command',\n            isNotFor: ['UglyBot'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const direction = script.getNumberValue('ROT_DIRECTION', script);\n                let degree = script.getNumberValue('ROT_DEGREE', script);\n                degree = direction == 1 ? -1 * degree : degree;\n                degree = degree > 1000 ? 1000 : degree;\n                degree = degree < -1000 ? -1000 : degree;\n\n                cmd[Entry.UglyBot.Cmd.CMD_ROT_LOW] = degree & 0xff;\n                cmd[Entry.UglyBot.Cmd.CMD_ROT_HIGH] = (degree >> 8) & 0x0f;\n                cmd[Entry.UglyBot.Cmd.CMD_ROT_HIGH] |= rotID << 4;\n                rotID = (rotID + 1) & 0x0f;\n                //console.log(\"degree:%d rotID:%d\", \tdegree, rotID);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', 0],\n                        ['2', 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    value: '0',\n                    fontSize: 11,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_servo',\n            },\n            paramsKeyMap: {\n                SERVO_WHAT: 0,\n                SERVO_DEGREE: 1,\n            },\n            class: 'UglyBot_Command',\n            isNotFor: ['UglyBot'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const what = script.getNumberValue('SERVO_WHAT', script);\n                let degree = script.getNumberValue('SERVO_DEGREE', script);\n                degree = degree < -90 ? -90 : degree;\n                degree = degree > 90 ? 90 : degree;\n                cmd[Entry.UglyBot.Cmd.CMD_SERVO1 + what] = degree & 0xff;\n                //console.log(\"servo what:%d degree:%d\", \twhat, degree);\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_irpin: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_left, 0],\n                        [Lang.template.uglybot_mid, 1],\n                        [Lang.template.uglybot_right, 2],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_on, 0],\n                        [Lang.template.uglybot_off, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_irpin',\n            },\n            paramsKeyMap: {\n                IRPIN_WHAT: 0,\n                IRPIN_ACT: 1,\n            },\n            class: 'UglyBot_Command',\n            isNotFor: ['UglyBot'],\n\n            func(sprite, script) {\n                if (typeof Entry.hw.sendQueue.CMD == 'undefined') {\n                    Entry.hw.sendQueue.CMD = [\n                        0x26,\n                        0xa8,\n                        0x14,\n                        0xe1,\n                        0x14,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                        0x00,\n                    ];\n                }\n                const cmd = Entry.hw.sendQueue.CMD;\n                const what = script.getNumberValue('IRPIN_WHAT', script);\n                const act = script.getNumberValue('IRPIN_ACT', script);\n                if (act == 0) {\n                    cmd[Entry.UglyBot.Cmd.CMD_IRPIN] |= 0x01 << what;\n                } else {\n                    cmd[Entry.UglyBot.Cmd.CMD_IRPIN] &= ~(0x01 << what);\n                }\n                Entry.hw.update();\n                return script.callReturn();\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_button: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_button',\n            },\n            class: 'UglyBot_Sensor',\n            isNotFor: ['UglyBot'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                //console.log(\"%d %d\", sensorData[6], sensorData[7]);\n                return sensorData[Entry.UglyBot.Sensor.SENSOR_BUTTON];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_ir: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_left, 0],\n                        [Lang.template.uglybot_mid, 1],\n                        [Lang.template.uglybot_right, 2],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_ir',\n            },\n            paramsKeyMap: {\n                IR_POS: 0,\n            },\n            class: 'UglyBot_Sensor',\n            isNotFor: ['UglyBot'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                const pos = script.getNumberValue('IR_POS', script);\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                //console.log(\"%d %d %d\", sensorData[8], sensorData[9], sensorData[10]);\n                return sensorData[Entry.UglyBot.Sensor.SENSOR_IR_LEFT + pos];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_ultrasonic: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_ultrasonic',\n            },\n            class: 'UglyBot_Sensor',\n            isNotFor: ['UglyBot'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                //console.log(\"%d\", sensorData[11]);\n                return sensorData[Entry.UglyBot.Sensor.SENSOR_ULTRASONIC];\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_joystick: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_leftright, 0],\n                        [Lang.template.uglybot_topbottom, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_joystick',\n            },\n            paramsKeyMap: {\n                JOYSTICK_WHAT: 0,\n            },\n            class: 'UglyBot_Sensor',\n            isNotFor: ['UglyBot'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                const exBoardType = sensorData[Entry.UglyBot.Sensor.ENSOR_EXBOARDTYPE];\n                const what = script.getNumberValue('JOYSTICK_WHAT', script);\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                //console.log(\"%d %d\", sensorData[12], sensorData[13]);\n                if (exBoardType == 4) {\n                    if (what == 1) {\n                        return sensorData[Entry.UglyBot.Sensor.SENSOR_JOYSTICK_TB];\n                    } else {\n                        const aa = sensorData[Entry.UglyBot.Sensor.SENSOR_JOYSTICK_LR];\n                        return aa < 127 ? aa : aa - 256;\n                    }\n                } else {\n                    const aa = sensorData[Entry.UglyBot.Sensor.SENSOR_JOYSTICK_LR + what];\n                    return aa < 127 ? aa : aa - 256;\n                }\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_tilt: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.template.uglybot_leftright, 0],\n                        [Lang.template.uglybot_topbottom, 1],\n                    ],\n                    value: 0,\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_tilt',\n            },\n            paramsKeyMap: {\n                GYRO_WHAT: 0,\n            },\n            class: 'UglyBot_Sensor',\n            isNotFor: ['UglyBot'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                const what = script.getNumberValue('GYRO_WHAT', script);\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                //console.log(\"%d %d\", sensorData[14], sensorData[15]);\n                const aa = sensorData[Entry.UglyBot.Sensor.SENSOR_GYRO_LR + what];\n                return aa < 127 ? aa : aa - 256;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_sound',\n            },\n            class: 'UglyBot_Sensor',\n            isNotFor: ['UglyBot'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                //console.log(\"%d\", sensorData[16]);\n                const aa = sensorData[Entry.UglyBot.Sensor.SENSOR_SOUND];\n                return aa < 128 ? aa : aa - 256;\n            },\n            syntax: { js: [], py: [] },\n        },\n\n        uglybot_illum: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uglybot_illum',\n            },\n            class: 'UglyBot_Sensor',\n            isNotFor: ['UglyBot'],\n            func(sprite, script) {\n                let sensorData = Entry.hw.portData.CMD;\n                sensorData = sensorData[0] == 0x26 ? sensorData : oldSensorData;\n                oldSensorData = sensorData;\n                //console.log(\"%d\", sensorData[17]);\n                return sensorData[Entry.UglyBot.Sensor.SENSOR_PHOTO];\n            },\n            syntax: { js: [], py: [] },\n        },\n    };\n};\n\nmodule.exports = Entry.UglyBot;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_uo_albert.js",
    "content": "'use strict';\n\nfunction UoAlbertRobot(index) {\n    this.sensory = {\n        signalStrength: 0,\n        leftProximity: 0,\n        rightProximity: 0,\n        accelerationX: 0,\n        accelerationY: 0,\n        accelerationZ: 0,\n        positionX: -1,\n        positionY: -1,\n        light: 0,\n        temperature: 0,\n        touch: 0,\n        oid: -1,\n        pulseCount: 0,\n        batteryState: 2,\n        tilt: 0,\n    };\n    this.motoring = {\n        group: 'uoalbert',\n        module: 'uoalbert',\n        index,\n    };\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.motionId = 0;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.clickedId = -1;\n    this.longPressedId = -1;\n    this.longLongPressedId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.clicked = false;\n    this.longPressed = false;\n    this.longLongPressed = false;\n    this.tempo = 60;\n    this.timeouts = [];\n}\n\nUoAlbertRobot.prototype.__PORT_MAP = {\n    group: 'uoalbert',\n    module: 'uoalbert',\n    leftWheel: 0,\n    rightWheel: 0,\n    leftRgb: '0,0,0',\n    leftRed: 0,\n    leftGreen: 0,\n    leftBlue: 0,\n    rightRgb: '0,0,0',\n    rightRed: 0,\n    rightGreen: 0,\n    rightBlue: 0,\n    buzzer: 0,\n    pulse: 0,\n    pulseId: 0,\n    note: 0,\n    sound: 0,\n    soundRepeat: 1,\n    soundId: 0,\n    boardWidth: 0,\n    boardHeight: 0,\n    motionId: 0,\n    motionType: 0,\n    motionUnit: 0,\n    motionSpeed: 0,\n    motionValue: 0,\n    motionRadius: 0,\n};\n\nUoAlbertRobot.prototype.setZero = function() {\n    const portMap = this.__PORT_MAP;\n    const motoring = this.motoring;\n    for (const port in portMap) {\n        motoring[port] = portMap[port];\n    }\n    this.pulseId = 0;\n    this.soundId = 0;\n    this.motionId = 0;\n    this.wheelStateId = -1;\n    this.soundStateId = -1;\n    this.clickedId = -1;\n    this.longPressedId = -1;\n    this.longLongPressedId = -1;\n    this.blockId = 0;\n    this.motionCallback = undefined;\n    this.soundCallback = undefined;\n    this.noteBlockId = 0;\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n    this.clicked = false;\n    this.longPressed = false;\n    this.longLongPressed = false;\n    this.tempo = 60;\n    this.__removeAllTimeouts();\n};\n\nUoAlbertRobot.prototype.afterReceive = function(pd) {\n    this.sensory = pd;\n    this.handleSensory();\n};\n\nUoAlbertRobot.prototype.afterSend = function(sq) {\n    this.clicked = false;\n    this.longPressed = false;\n    this.longLongPressed = false;\n};\n\nUoAlbertRobot.prototype.setMotoring = function(motoring) {\n    this.motoring = motoring;\n};\n\nUoAlbertRobot.prototype.__setModule = function() {\n    this.motoring.group = 'uoalbert';\n    this.motoring.module = 'uoalbert';\n};\n\nUoAlbertRobot.prototype.__removeTimeout = function(id) {\n    clearTimeout(id);\n    const idx = this.timeouts.indexOf(id);\n    if (idx >= 0) {\n        this.timeouts.splice(idx, 1);\n    }\n};\n\nUoAlbertRobot.prototype.__removeAllTimeouts = function() {\n    const timeouts = this.timeouts;\n    for (const i in timeouts) {\n        clearTimeout(timeouts[i]);\n    }\n    this.timeouts = [];\n};\n\nUoAlbertRobot.prototype.__setPulse = function(pulse) {\n    this.pulseId = (this.pulseId % 255) + 1;\n    this.motoring.pulse = pulse;\n    this.motoring.pulseId = this.pulseId;\n};\n\nUoAlbertRobot.prototype.__setMotion = function(type, unit, speed, value, radius) {\n    this.motionId = (this.motionId % 255) + 1;\n    const motoring = this.motoring;\n    motoring.motionType = type;\n    motoring.motionUnit = unit;\n    motoring.motionSpeed = speed;\n    motoring.motionValue = value;\n    motoring.motionRadius = radius;\n    motoring.motionId = this.motionId;\n};\n\nUoAlbertRobot.prototype.__cancelMotion = function() {\n    this.motionCallback = undefined;\n};\n\nUoAlbertRobot.prototype.__runSound = function(sound, count) {\n    if (typeof count != 'number') {\n        count = 1;\n    }\n    if (count < 0) {\n        count = -1;\n    }\n    if (count) {\n        this.soundId = (this.soundId % 255) + 1;\n        const motoring = this.motoring;\n        motoring.sound = sound;\n        motoring.soundRepeat = count;\n        motoring.soundId = this.soundId;\n    }\n};\n\nUoAlbertRobot.prototype.__cancelSound = function() {\n    this.soundCallback = undefined;\n};\n\nUoAlbertRobot.prototype.__issueNoteBlockId = function() {\n    this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n    return this.noteBlockId;\n};\n\nUoAlbertRobot.prototype.__cancelNote = function() {\n    this.noteBlockId = 0;\n    if (this.noteTimer1 !== undefined) {\n        this.__removeTimeout(this.noteTimer1);\n    }\n    if (this.noteTimer2 !== undefined) {\n        this.__removeTimeout(this.noteTimer2);\n    }\n    this.noteTimer1 = undefined;\n    this.noteTimer2 = undefined;\n};\n\nUoAlbertRobot.prototype.handleSensory = function() {\n    const self = this;\n    const sensory = self.sensory;\n    \n    self.clicked = sensory.clicked == 1;\n    self.longPressed = sensory.longPressed == 1;\n    self.longLongPressed = sensory.longLongPressed == 1;\n\n    if (self.motionCallback) {\n        if (sensory.wheelStateId != self.wheelStateId) {\n            self.wheelStateId = sensory.wheelStateId;\n            if (sensory.wheelState == 0) {\n                self.motoring.leftWheel = 0;\n                self.motoring.rightWheel = 0;\n                var callback = self.motionCallback;\n                self.__cancelMotion();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n    if (self.soundCallback) {\n        if (sensory.soundStateId != self.soundStateId) {\n            self.soundStateId = sensory.soundStateId;\n            if (sensory.soundState == 0) {\n                var callback = self.soundCallback;\n                self.__cancelSound();\n                if (callback) {\n                    callback();\n                }\n            }\n        }\n    }\n};\n\nUoAlbertRobot.prototype.__SENSORS = {\n    SIGNAL_STRENGTH: 'signalStrength',\n    LEFT_PROXIMITY: 'leftProximity',\n    RIGHT_PROXIMITY: 'rightProximity',\n    ACCELERATION_X: 'accelerationX',\n    ACCELERATION_Y: 'accelerationY',\n    ACCELERATION_Z: 'accelerationZ',\n    POSITION_X: 'positionX',\n    POSITION_Y: 'positionY',\n    LIGHT: 'light',\n    TEMPERATURE: 'temperature',\n    TOUCH: 'touch',\n    OID: 'oid',\n    PULSE_COUNT: 'pulseCount',\n    BATTERY_STATE: 'batteryState',\n    TILT: 'tilt',\n};\n\nUoAlbertRobot.prototype.getValue = function(script) {\n    this.__setModule();\n    const dev = script.getField('DEVICE');\n\n    const sensor = this.__SENSORS[dev] || dev;\n    return this.sensory[sensor];\n};\n\nUoAlbertRobot.prototype.checkBoolean = function(script) {\n    this.__setModule();\n    var sensory = this.sensory;\n    var value = 0;\n    var dev = script.getField('DEVICE');\n    if(dev.startsWith('TILT')) {\n        if(sensory.tilt === undefined) {\n            if(sensory.accelerationZ < 2048 && sensory.accelerationX > 2048 && sensory.accelerationY > -1024 && sensory.accelerationY < 1024) value = 1;\n            else if(sensory.accelerationZ < 2048 && sensory.accelerationX < -2048 && sensory.accelerationY > -1024 && sensory.accelerationY < 1024) value = -1;\n            else if(sensory.accelerationZ < 2048 && sensory.accelerationY > 2048 && sensory.accelerationX > -1024 && sensory.accelerationX < 1024) value = 2;\n            else if(sensory.accelerationZ < 2048 && sensory.accelerationY < -2048 && sensory.accelerationX > -1024 && sensory.accelerationX < 1024) value = -2;\n            else if(sensory.accelerationZ > 3072 && sensory.accelerationX > -2048 && sensory.accelerationX < 2048 && sensory.accelerationY > -2048 && sensory.accelerationY < 2048) value = 3;\n            else if(sensory.accelerationZ < -3072 && sensory.accelerationX > -1024 && sensory.accelerationX < 1024 && sensory.accelerationY > -1024 && sensory.accelerationY < 1024) value = -3;\n            else value = 0;\n        } else {\n            value = sensory.tilt;\n        }\n        switch(dev) {\n            case 'TILT_FORWARD': return value == 1;\n            case 'TILT_BACKWARD': return value == -1;\n            case 'TILT_LEFT': return value == 2;\n            case 'TILT_RIGHT': return value == -2;\n            case 'TILT_FLIP': return value == 3;\n            case 'TILT_NOT': return value == -3;\n        }\n        return false;\n    } else {\n        switch (dev) {\n            case 'BATTERY_NORMAL': return sensory.batteryState === 2;\n            case 'BATTERY_LOW': return sensory.batteryState === 1;\n            case 'BATTERY_EMPTY': return sensory.batteryState === 0;\n        }\n        return false;\n    }\n};\n\nUoAlbertRobot.prototype.checkHandFound = function(script) {\n    this.__setModule();\n    var sensory = this.sensory;\n    return sensory.handFound === undefined ? sensory.leftProximity > 40 || sensory.rightProximity > 40 : sensory.handFound;\n};\n\nUoAlbertRobot.prototype.checkTouchState = function(script) {\n    this.__setModule();\n    const state = script.getField('STATE');\n    switch(state) {\n        case 'CLICKED': return this.clicked;\n        case 'LONG_PRESSED': return this.longPressed;\n        case 'LONG_LONG_PRESSED': return this.longLongPressed;\n    }\n    return false;\n};\n\nUoAlbertRobot.prototype.checkOid = function(script) {\n    this.__setModule();\n    var value = script.getNumberValue('VALUE');\n    return this.sensory.oid == value;\n};\n\nUoAlbertRobot.prototype.__motionUnit = function(type, unit, value, callback) {\n    const motoring = this.motoring;\n    this.__cancelMotion();\n\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    value = parseFloat(value);\n    if (value && value > 0) {\n        this.__setMotion(type, unit, 0, value, 0); // type, unit, speed, value, radius\n        this.motionCallback = callback;\n    } else {\n        this.__setMotion(0, 0, 0, 0, 0);\n        callback();\n    }\n};\n\nUoAlbertRobot.prototype.__UNITS = {\n    CM: 1,\n    DEG: 1,\n    SEC: 2,\n    PULSE: 3,\n};\n\nUoAlbertRobot.prototype.moveForwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(2, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(1, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nUoAlbertRobot.prototype.moveBackwardUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (value < 0) {\n            this.__motionUnit(1, this.__UNITS[unit], -value, () => {\n                script.isMoving = false;\n            });\n        } else {\n            this.__motionUnit(2, this.__UNITS[unit], value, () => {\n                script.isMoving = false;\n            });\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nUoAlbertRobot.prototype.turnUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const direction = script.getField('DIRECTION');\n        const value = script.getNumberValue('VALUE');\n        const unit = script.getField('UNIT');\n\n        if (direction == 'LEFT') {\n            if (value < 0) {\n                this.__motionUnit(4, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(3, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        } else {\n            if (value < 0) {\n                this.__motionUnit(3, this.__UNITS[unit], -value, () => {\n                    script.isMoving = false;\n                });\n            } else {\n                this.__motionUnit(4, this.__UNITS[unit], value, () => {\n                    script.isMoving = false;\n                });\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nUoAlbertRobot.prototype.pivotUnit = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isMoving = true;\n\n        const wheel = script.getField('WHEEL');\n        const value = script.getNumberValue('VALUE');\n        let unit = script.getField('UNIT');\n        const toward = script.getField('TOWARD');\n\n        unit = this.__UNITS[unit];\n        if (wheel == 'LEFT') {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(6, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(5, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(5, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(6, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        } else {\n            if (toward == 'FORWARD') {\n                if (value < 0) {\n                    this.__motionUnit(8, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(7, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            } else {\n                if (value < 0) {\n                    this.__motionUnit(7, unit, -value, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motionUnit(8, unit, value, () => {\n                        script.isMoving = false;\n                    });\n                }\n            }\n        }\n        return script;\n    } else if (script.isMoving) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isMoving;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nUoAlbertRobot.prototype.setWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel = leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel = rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.changeWheels = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelMotion();\n\n    let leftVelocity = script.getNumberValue('LEFT');\n    let rightVelocity = script.getNumberValue('RIGHT');\n\n    leftVelocity = parseFloat(leftVelocity);\n    rightVelocity = parseFloat(rightVelocity);\n    if (typeof leftVelocity == 'number') {\n        motoring.leftWheel =\n            motoring.leftWheel !== undefined ? motoring.leftWheel + leftVelocity : leftVelocity;\n    }\n    if (typeof rightVelocity == 'number') {\n        motoring.rightWheel =\n            motoring.rightWheel !== undefined ? motoring.rightWheel + rightVelocity : rightVelocity;\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.setWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel = velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel = velocity;\n        } else {\n            motoring.leftWheel = velocity;\n            motoring.rightWheel = velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.changeWheel = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n    this.__cancelMotion();\n\n    const wheel = script.getField('WHEEL');\n    let velocity = script.getNumberValue('VELOCITY');\n\n    velocity = parseFloat(velocity);\n    if (typeof velocity == 'number') {\n        if (wheel == 'LEFT') {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n        } else if (wheel == 'RIGHT') {\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        } else {\n            motoring.leftWheel =\n                motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n            motoring.rightWheel =\n                motoring.rightWheel != undefined ? motoring.rightWheel + velocity : velocity;\n        }\n    }\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.stop = function(script) {\n    this.__setModule();\n    this.__cancelMotion();\n\n    const motoring = this.motoring;\n    motoring.leftWheel = 0;\n    motoring.rightWheel = 0;\n    this.__setPulse(0);\n    this.__setMotion(0, 0, 0, 0, 0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.setBoardSize = function(script) {\n    const motoring = this.motoring;\n    this.__setModule();\n\n    let width = script.getNumberValue('WIDTH');\n    let height = script.getNumberValue('HEIGHT');\n\n    width = parseInt(width);\n    height = parseInt(height);\n    if(width && height && width > 0 && height > 0) {\n        motoring.boardWidth = width;\n        motoring.boardHeight = height;\n    }\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.__RGB_COLORS = {\n    RED: [255, 0, 0],\n    ORANGE: [255, 63, 0],\n    YELLOW: [255, 255, 0],\n    GREEN: [0, 255, 0],\n    SKY_BLUE: [0, 255, 255],\n    BLUE: [0, 0, 255],\n    VIOLET: [63, 0, 255],\n    PURPLE: [255, 0, 255],\n    WHITE: [255, 255, 255],\n};\n\nUoAlbertRobot.prototype.setEyeColor = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n    const color = script.getField('COLOR');\n\n    const rgb = this.__RGB_COLORS[color];\n    if (rgb) {\n        const motoring = this.motoring;\n        if (eye == 'LEFT') {\n            motoring.leftRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.leftRed = rgb[0];\n            motoring.leftGreen = rgb[1];\n            motoring.leftBlue = rgb[2];\n        } else if (eye == 'RIGHT') {\n            motoring.rightRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.rightRed = rgb[0];\n            motoring.rightGreen = rgb[1];\n            motoring.rightBlue = rgb[2];\n        } else {\n            motoring.leftRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.leftRed = rgb[0];\n            motoring.leftGreen = rgb[1];\n            motoring.leftBlue = rgb[2];\n            motoring.rightRgb = `${rgb[0]},${rgb[1]},${rgb[2]}`;\n            motoring.rightRed = rgb[0];\n            motoring.rightGreen = rgb[1];\n            motoring.rightBlue = rgb[2];\n        }\n    }\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.pickEyeColor = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n    const color = script.getField('COLOR');\n\n    const red = parseInt(color.slice(1, 3), 16);\n    const green = parseInt(color.slice(3, 5), 16);\n    const blue = parseInt(color.slice(5, 7), 16);\n\n    const motoring = this.motoring;\n    if (eye == 'LEFT') {\n        motoring.leftRgb = `${red},${green},${blue}`;\n        motoring.leftRed = red;\n        motoring.leftGreen = green;\n        motoring.leftBlue = blue;\n    } else if (eye == 'RIGHT') {\n        motoring.rightRgb = `${red},${green},${blue}`;\n        motoring.rightRed = red;\n        motoring.rightGreen = green;\n        motoring.rightBlue = blue;\n    } else {\n        motoring.leftRgb = `${red},${green},${blue}`;\n        motoring.leftRed = red;\n        motoring.leftGreen = green;\n        motoring.leftBlue = blue;\n        motoring.rightRgb = `${red},${green},${blue}`;\n        motoring.rightRed = red;\n        motoring.rightGreen = green;\n        motoring.rightBlue = blue;\n    }\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.setEyeRgb = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    const motoring = this.motoring;\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if (eye == 'LEFT') {\n        if (typeof red == 'number') {\n            motoring.leftRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue = blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n    } else if (eye == 'RIGHT') {\n        if (typeof red == 'number') {\n            motoring.rightRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.rightGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.rightBlue = blue;\n        }\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    } else {\n        if (typeof red == 'number') {\n            motoring.leftRed = red;\n            motoring.rightRed = red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen = green;\n            motoring.rightGreen = green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue = blue;\n            motoring.rightBlue = blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    }\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.changeEyeRgb = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n    let red = script.getNumberValue('RED');\n    let green = script.getNumberValue('GREEN');\n    let blue = script.getNumberValue('BLUE');\n\n    const motoring = this.motoring;\n    red = parseInt(red);\n    green = parseInt(green);\n    blue = parseInt(blue);\n    if (eye == 'LEFT') {\n        if (typeof red == 'number') {\n            motoring.leftRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue += blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n    } else if (eye == 'RIGHT') {\n        if (typeof red == 'number') {\n            motoring.rightRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.rightGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.rightBlue += blue;\n        }\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    } else {\n        if (typeof red == 'number') {\n            motoring.leftRed += red;\n            motoring.rightRed += red;\n        }\n        if (typeof green == 'number') {\n            motoring.leftGreen += green;\n            motoring.rightGreen += green;\n        }\n        if (typeof blue == 'number') {\n            motoring.leftBlue += blue;\n            motoring.rightBlue += blue;\n        }\n        motoring.leftRgb = `${motoring.leftRed},${motoring.leftGreen},${motoring.leftBlue}`;\n        motoring.rightRgb = `${motoring.rightRed},${motoring.rightGreen},${motoring.rightBlue}`;\n    }\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.clearEye = function(script) {\n    this.__setModule();\n    const eye = script.getField('EYE');\n\n    const motoring = this.motoring;\n    if (eye == 'LEFT') {\n        motoring.leftRgb = '0,0,0';\n        motoring.leftRed = 0;\n        motoring.leftGreen = 0;\n        motoring.leftBlue = 0;\n    } else if (eye == 'RIGHT') {\n        motoring.rightRgb = '0,0,0';\n        motoring.rightRed = 0;\n        motoring.rightGreen = 0;\n        motoring.rightBlue = 0;\n    } else {\n        motoring.leftRgb = '0,0,0';\n        motoring.leftRed = 0;\n        motoring.leftGreen = 0;\n        motoring.leftBlue = 0;\n        motoring.rightRgb = '0,0,0';\n        motoring.rightRed = 0;\n        motoring.rightGreen = 0;\n        motoring.rightBlue = 0;\n    }\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.__SOUNDS = {\n    BEEP: 1,\n    SIREN: 2,\n    ENGINE: 3,\n    ROBOT: 4,\n    MARCH: 5,\n    BIRTHDAY: 6,\n    DIBIDIBIDIP: 7,\n};\n\nUoAlbertRobot.prototype.playSound = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let sound = script.getField('SOUND');\n    let count = script.getNumberValue('COUNT');\n\n    sound = this.__SOUNDS[sound];\n    count = parseInt(count);\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    if (sound && count) {\n        this.__runSound(sound, count);\n    } else {\n        this.__runSound(0);\n    }\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.playSoundUntil = function(script) {\n    this.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        this.__cancelNote();\n        this.__cancelSound();\n\n        let sound = script.getField('SOUND');\n        let count = script.getNumberValue('COUNT');\n        \n        sound = this.__SOUNDS[sound];\n        count = parseInt(count);\n        this.motoring.buzzer = 0;\n        this.motoring.note = 0;\n        if (sound && count) {\n            this.__runSound(sound, count);\n            this.soundCallback = function() {\n                script.isPlaying = false;\n            };\n        } else {\n            this.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nUoAlbertRobot.prototype.setBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        this.motoring.buzzer = hz;\n    }\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.changeBuzzer = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n    let hz = script.getNumberValue('HZ');\n\n    const motoring = this.motoring;\n    hz = parseFloat(hz);\n    if (typeof hz == 'number') {\n        motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n    }\n    motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.clearSound = function(script, motoring) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    this.motoring.buzzer = 0;\n    this.motoring.note = 0;\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.__NOTES = {\n    C: 4,\n    'C#': 5,\n    Db: 5,\n    D: 6,\n    'D#': 7,\n    Eb: 7,\n    E: 8,\n    F: 9,\n    'F#': 10,\n    Gb: 10,\n    G: 11,\n    'G#': 12,\n    Ab: 12,\n    A: 13,\n    'A#': 14,\n    Bb: 14,\n    B: 15,\n    '4': 4,\n    '5': 5,\n    '6': 6,\n    '7': 7,\n    '8': 8,\n    '9': 9,\n    '10': 10,\n    '11': 11,\n    '12': 12,\n    '13': 13,\n    '14': 14,\n    '15': 15,\n};\n\nUoAlbertRobot.prototype.playNote = function(script) {\n    this.__setModule();\n    this.__cancelNote();\n    this.__cancelSound();\n\n    let note = script.getField('NOTE');\n    let octave = script.getNumberField('OCTAVE');\n\n    note = parseInt(this.__NOTES[note]);\n    octave = parseInt(octave);\n    const motoring = this.motoring;\n    motoring.buzzer = 0;\n    if (note && octave && octave > 0 && octave < 8) {\n        motoring.note = note + (octave - 1) * 12;\n    } else {\n        motoring.note = 0;\n    }\n    this.__runSound(0);\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.playNoteBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n\n        const motoring = self.motoring;\n        let note = script.getField('NOTE');\n        let octave = script.getNumberField('OCTAVE');\n        let beat = script.getNumberValue('BEAT');\n\n        note = parseInt(this.__NOTES[note]);\n        octave = parseInt(octave);\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        if (note && octave && octave > 0 && octave < 8 && beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            note += (octave - 1) * 12;\n            motoring.note = note;\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            if (timeValue > 100) {\n                self.noteTimer1 = setTimeout(() => {\n                    if (self.noteBlockId == id) {\n                        motoring.note = 0;\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, timeValue - 100);\n                self.timeouts.push(self.noteTimer1);\n            }\n            self.noteTimer2 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    motoring.note = 0;\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer2);\n            self.__runSound(0);\n        } else {\n            motoring.note = 0;\n            self.__runSound(0);\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        self.motoring.note = 0;\n        return script.callReturn();\n    }\n};\n\nUoAlbertRobot.prototype.restBeat = function(script) {\n    const self = this;\n    self.__setModule();\n    if (!script.isStart) {\n        script.isStart = true;\n        script.isPlaying = true;\n        self.__cancelNote();\n        self.__cancelSound();\n        let beat = script.getNumberValue('BEAT');\n\n        const motoring = self.motoring;\n        beat = parseFloat(beat);\n        motoring.buzzer = 0;\n        motoring.note = 0;\n        self.__runSound(0);\n        if (beat && beat > 0 && self.tempo > 0) {\n            const id = self.__issueNoteBlockId();\n            const timeValue = (beat * 60 * 1000) / self.tempo;\n            self.noteTimer1 = setTimeout(() => {\n                if (self.noteBlockId == id) {\n                    self.__cancelNote();\n                    script.isPlaying = false;\n                }\n            }, timeValue);\n            self.timeouts.push(self.noteTimer1);\n        } else {\n            script.isPlaying = false;\n        }\n        return script;\n    } else if (script.isPlaying) {\n        return script;\n    } else {\n        delete script.isStart;\n        delete script.isPlaying;\n        Entry.engine.isContinue = false;\n        return script.callReturn();\n    }\n};\n\nUoAlbertRobot.prototype.setTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo = bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nUoAlbertRobot.prototype.changeTempo = function(script) {\n    this.__setModule();\n    let bpm = script.getNumberValue('BPM');\n\n    bpm = parseFloat(bpm);\n    if (typeof bpm == 'number') {\n        this.tempo += bpm;\n        if (this.tempo < 1) {\n            this.tempo = 1;\n        }\n    }\n    return script.callReturn();\n};\n\nEntry.UoAlbert = {\n    robot: undefined,\n    getRobot() {\n        if(Entry.UoAlbert.robot == undefined) Entry.UoAlbert.robot = new UoAlbertRobot(0);\n        Entry.UoAlbert.robot.setMotoring(Entry.hw.sendQueue);\n        return Entry.UoAlbert.robot;\n    },\n    setZero() {\n        if(Entry.UoAlbert.robot) Entry.UoAlbert.robot.setZero();\n        Entry.hw.update();\n    },\n    afterReceive(pd) {\n        const robot = Entry.UoAlbert.getRobot();\n        if(robot) robot.afterReceive(pd);\n    },\n    afterSend(sq) {\n        const robot = Entry.UoAlbert.getRobot();\n        if(robot) robot.afterSend(sq);\n    },\n    id: '2.7',\n    name: 'uoalbert',\n    url: 'http://albert.school',\n    imageName: 'uoalbert.png',\n    title: {\n        en: 'UO Albert',\n        ko: 'UO 알버트',\n        jp: 'UOアルバート',\n        vn: 'UO Albert',\n    },\n    monitorTemplate: () => ({\n        imgPath: 'hw/uoalbert.png',\n        width: 300,\n        height: 434,\n        listPorts: {\n            accelerationX: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationY: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            accelerationZ: {\n                name: Lang.Blocks.ROBOID_sensor_acceleration_z,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            oid: {\n                name: Lang.Blocks.ROBOID_sensor_oid,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            positionX: {\n                name: Lang.Blocks.ROBOID_sensor_position_x,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            positionY: {\n                name: Lang.Blocks.ROBOID_sensor_position_y,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            temperature: {\n                name: Lang.Blocks.ROBOID_sensor_temperature,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            signalStrength: {\n                name: Lang.Blocks.ROBOID_sensor_signal_strength,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Blocks.ROBOID_monitor_buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: {\n                name: Lang.Blocks.ROBOID_monitor_note,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            leftProximity: {\n                name: Lang.Blocks.ROBOID_sensor_left_proximity,\n                type: 'input',\n                pos: { x: 150, y: 358 },\n            },\n            rightProximity: {\n                name: Lang.Blocks.ROBOID_sensor_right_proximity,\n                type: 'input',\n                pos: { x: 39, y: 322 },\n            },\n            touch: {\n                name: Lang.Blocks.ROBOID_sensor_touch,\n                type: 'input',\n                pos: { x: 103, y: 228 },\n            },\n            light: {\n                name: Lang.Blocks.ROBOID_sensor_light,\n                type: 'input',\n                pos: { x: 91, y: 343 },\n            },\n            leftWheel: {\n                name: Lang.Blocks.ROBOID_monitor_left_wheel,\n                type: 'output',\n                pos: { x: 208, y: 411 },\n            },\n            rightWheel: {\n                name: Lang.Blocks.ROBOID_monitor_right_wheel,\n                type: 'output',\n                pos: { x: 31, y: 349 },\n            },\n            leftRgb: {\n                name: Lang.Blocks.ROBOID_monitor_left_eye,\n                type: 'output',\n                pos: { x: 230, y: 64 },\n            },\n            rightRgb: {\n                name: Lang.Blocks.ROBOID_monitor_right_eye,\n                type: 'output',\n                pos: { x: 124, y: 44 },\n            },\n        },\n        mode: 'both',\n    }),\n};\n\nEntry.UoAlbert.setLanguage = () => ({\n    ko: {\n        template: {\n            uoalbert_value: '%1',\n            uoalbert_hand_found: '손 찾음?',\n            uoalbert_touch_state: '터치 센서를 %1 ?',\n            uoalbert_is_oid: 'OID가 %1인가?',\n            uoalbert_boolean: '%1?',\n            uoalbert_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n            uoalbert_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n            uoalbert_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n            uoalbert_pivot_around_unit_in_direction: '%1 바퀴 중심으로 %2 %3 %4 방향으로 돌기 %5',\n            uoalbert_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            uoalbert_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            uoalbert_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            uoalbert_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            uoalbert_stop: '정지하기 %1',\n            uoalbert_set_board_size: '말판 크기를 폭 %1 높이 %2(으)로 정하기 %3',\n            uoalbert_set_eye_to: '%1 눈을 %2 으로 정하기 %3',\n            uoalbert_pick_eye: '%1 눈을 %2로 정하기 %3',\n            uoalbert_change_eye_by_rgb: '%1 눈을 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n            uoalbert_set_eye_to_rgb: '%1 눈을 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n            uoalbert_clear_eye: '%1 눈 끄기 %2',\n            uoalbert_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n            uoalbert_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n            uoalbert_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            uoalbert_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            uoalbert_clear_sound: '소리 끄기 %1',\n            uoalbert_play_note: '%1 %2 음을 연주하기 %3',\n            uoalbert_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n            uoalbert_rest_for: '%1 박자 쉬기 %2',\n            uoalbert_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            uoalbert_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n        },\n        Helper: {\n            uoalbert_value: '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -8192 ~ 8191, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>터치: 터치 센서의 값 (터치하면 1, 아니면 0, 초기값: 0)<br/>OID: OID 센서의 값 (값의 범위: -1 ~ 65535, 초기값: -1)<br/>x 위치: 말판 위에서 로봇의 위치 x좌표 값 (값의 범위: -1 ~ 39999, 초기값: -1)<br/>y 위치: 말판 위에서 로봇의 위치 y좌표 값 (값의 범위: -1 ~ 39999, 초기값: -1)<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.',\n            uoalbert_hand_found: \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            uoalbert_touch_state: \"터치 센서를 클릭했으면/길게 눌렀으면/아주 길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            uoalbert_is_oid: \"OID 센서가 감지한 OID 값이 입력한 숫자와 같으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            uoalbert_boolean: \"앞으로 기울임: 앞으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집었으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않았으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            uoalbert_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            uoalbert_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            uoalbert_turn_unit_in_place: '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            uoalbert_pivot_around_unit_in_direction: '왼쪽/오른쪽 바퀴 중심으로 입력한 각도(도)/시간(초)/펄스만큼 앞쪽/뒤쪽 방향으로 회전합니다.',\n            uoalbert_change_both_wheels_by: '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            uoalbert_set_both_wheels_to: '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            uoalbert_change_wheel_by: '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            uoalbert_set_wheel_to: '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            uoalbert_stop: '양쪽 바퀴를 정지합니다.',\n            uoalbert_set_board_size: '말판의 폭과 높이를 입력한 값으로 설정합니다.',\n            uoalbert_set_eye_to: '왼쪽/오른쪽/양쪽 눈을 선택한 색깔로 켭니다.',\n            uoalbert_pick_eye: '왼쪽/오른쪽/양쪽 눈을 선택한 색깔로 켭니다.',\n            uoalbert_change_eye_by_rgb: '왼쪽/오른쪽/양쪽 눈의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            uoalbert_set_eye_to_rgb: '왼쪽/오른쪽/양쪽 눈의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            uoalbert_clear_eye: '왼쪽/오른쪽/양쪽 눈을 끕니다.',\n            uoalbert_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            uoalbert_play_sound_times_until_done: '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            uoalbert_change_buzzer_by: '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n            uoalbert_set_buzzer_to: '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n            uoalbert_clear_sound: '소리를 끕니다.',\n            uoalbert_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            uoalbert_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            uoalbert_rest_for: '입력한 박자만큼 쉽니다.',\n            uoalbert_change_tempo_by: '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            uoalbert_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n        },\n        Blocks: {\n            ROBOID_monitor_left_wheel: '왼쪽 바퀴',\n            ROBOID_monitor_right_wheel: '오른쪽 바퀴',\n            ROBOID_monitor_left_eye: '왼쪽 눈',\n            ROBOID_monitor_right_eye: '오른쪽 눈',\n            ROBOID_monitor_buzzer: '버저',\n            ROBOID_monitor_note: '음표',\n            ROBOID_sensor_signal_strength: '신호 세기',\n            ROBOID_sensor_left_proximity: '왼쪽 근접 센서',\n            ROBOID_sensor_right_proximity: '오른쪽 근접 센서',\n            ROBOID_sensor_acceleration_x: 'x축 가속도',\n            ROBOID_sensor_acceleration_y: 'y축 가속도',\n            ROBOID_sensor_acceleration_z: 'z축 가속도',\n            ROBOID_sensor_position_x: 'x 위치',\n            ROBOID_sensor_position_y: 'y 위치',\n            ROBOID_sensor_light: '밝기',\n            ROBOID_sensor_temperature: '온도',\n            ROBOID_sensor_touch: '터치',\n            ROBOID_sensor_oid: 'OID',\n            ROBOID_button_clicked: '클릭했는가',\n            ROBOID_button_long_pressed: '오래 눌렀는가(1.5초)',\n            ROBOID_button_long_long_pressed: '아주 오래 눌렀는가(3초)',\n            ROBOID_tilt_forward: '앞으로 기울임',\n            ROBOID_tilt_backward: '뒤로 기울임',\n            ROBOID_tilt_left: '왼쪽으로 기울임',\n            ROBOID_tilt_right: '오른쪽으로 기울임',\n            ROBOID_tilt_flip: '거꾸로 뒤집음',\n            ROBOID_tilt_not: '기울이지 않음',\n            ROBOID_battery_normal: '배터리 정상',\n            ROBOID_battery_low: '배터리 부족',\n            ROBOID_battery_empty: '배터리 없음',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '초',\n            ROBOID_unit_pulse: '펄스',\n            ROBOID_unit_deg: '도',\n            ROBOID_left: '왼쪽',\n            ROBOID_right: '오른쪽',\n            ROBOID_both: '양쪽',\n            ROBOID_forward: '앞쪽',\n            ROBOID_backward: '뒤쪽',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_orange: '주황색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_violet: '보라색',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_sound_beep: '삐',\n            ROBOID_sound_siren: '사이렌',\n            ROBOID_sound_engine: '엔진',\n            ROBOID_sound_robot: '로봇',\n            ROBOID_sound_dibidibidip: '디비디비딥',\n            ROBOID_sound_march: '행진',\n            ROBOID_sound_birthday: '생일',\n            ROBOID_note_c: '도',\n            ROBOID_note_c_sharp: '도♯(레♭)',\n            ROBOID_note_d: '레',\n            ROBOID_note_d_sharp: '레♯(미♭)',\n            ROBOID_note_e: '미',\n            ROBOID_note_f: '파',\n            ROBOID_note_f_sharp: '파♯(솔♭)',\n            ROBOID_note_g: '솔',\n            ROBOID_note_g_sharp: '솔♯(라♭)',\n            ROBOID_note_a: '라',\n            ROBOID_note_a_sharp: '라♯(시♭)',\n            ROBOID_note_b: '시',\n        },\n    },\n    en: {\n        template: {\n            uoalbert_value: '%1',\n            uoalbert_hand_found: 'hand found?',\n            uoalbert_touch_state: 'touch sensor %1 ?',\n            uoalbert_is_oid: 'oid %1?',\n            uoalbert_boolean: '%1?',\n            uoalbert_move_forward_unit: 'move forward %1 %2 %3',\n            uoalbert_move_backward_unit: 'move backward %1 %2 %3',\n            uoalbert_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            uoalbert_pivot_around_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n            uoalbert_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            uoalbert_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            uoalbert_change_wheel_by: 'change %1 wheel by %2 %3',\n            uoalbert_set_wheel_to: 'set %1 wheel to %2 %3',\n            uoalbert_stop: 'stop %1',\n            uoalbert_set_board_size: 'set board size to width: %1 height: %2 %3',\n            uoalbert_set_eye_to: 'set %1 eye to %2 %3',\n            uoalbert_pick_eye: 'set %1 eye to %2 %3',\n            uoalbert_change_eye_by_rgb: 'change %1 eye by r: %2 g: %3 b: %4 %5',\n            uoalbert_set_eye_to_rgb: 'set %1 eye to r: %2 g: %3 b: %4 %5',\n            uoalbert_clear_eye: 'clear %1 eye %2',\n            uoalbert_play_sound_times: 'play sound %1 %2 times %3',\n            uoalbert_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            uoalbert_change_buzzer_by: 'change buzzer by %1 %2',\n            uoalbert_set_buzzer_to: 'set buzzer to %1 %2',\n            uoalbert_clear_sound: 'clear sound %1',\n            uoalbert_play_note: 'play note %1 %2 %3',\n            uoalbert_play_note_for: 'play note %1 %2 for %3 beats %4',\n            uoalbert_rest_for: 'rest for %1 beats %2',\n            uoalbert_change_tempo_by: 'change tempo by %1 %2',\n            uoalbert_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            uoalbert_value: \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>touch: value of touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>oid: value of oid sensor (range: -1 ~ 65535, initial value: -1)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            uoalbert_hand_found: 'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            uoalbert_touch_state: 'If the touch sensor clicked/long-pressed/long-long-pressed, true, otherwise false.',\n            uoalbert_is_oid: 'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            uoalbert_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            uoalbert_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            uoalbert_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            uoalbert_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            uoalbert_pivot_around_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            uoalbert_change_both_wheels_by: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            uoalbert_set_both_wheels_to: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            uoalbert_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            uoalbert_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            uoalbert_stop: 'Stops both wheels.',\n            uoalbert_set_board_size: 'Sets the width and height of the board.',\n            uoalbert_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            uoalbert_pick_eye: 'Turns left/right/both eyes to the selected color.',\n            uoalbert_change_eye_by_rgb: 'Adds the entered values to the current R, G, B values of left/right/both eyes, respectively.',\n            uoalbert_set_eye_to_rgb: 'Sets the R, G, B values of left/right/both eyes to the entered values.',\n            uoalbert_clear_eye: 'Turns off the left/right/both eyes.',\n            uoalbert_play_sound_times: 'Plays the selected sound as many times as entered.',\n            uoalbert_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            uoalbert_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            uoalbert_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            uoalbert_clear_sound: 'Turns off sound.',\n            uoalbert_play_note: 'It sounds the selected tone and octave.',\n            uoalbert_play_note_for: 'It sounds the selected tone and octave as much as the beat you entered.',\n            uoalbert_rest_for: 'Rests as much as the beat you entered.',\n            uoalbert_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            uoalbert_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_monitor_left_eye: 'left eye',\n            ROBOID_monitor_right_eye: 'right eye',\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_left_proximity: 'left proximity',\n            ROBOID_sensor_right_proximity: 'right proximity',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_position_x: 'x position',\n            ROBOID_sensor_position_y: 'y position',\n            ROBOID_sensor_light: 'light',\n            ROBOID_sensor_temperature: 'temperature',\n            ROBOID_sensor_touch: 'touch',\n            ROBOID_sensor_oid: 'oid',\n            ROBOID_button_clicked: 'clicked',\n            ROBOID_button_long_pressed: 'long-pressed (1.5 secs)',\n            ROBOID_button_long_long_pressed: 'long-long-pressed (3 secs)',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_forward: 'forward',\n            ROBOID_backward: 'backward',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n    jp: {\n        template: {\n            uoalbert_value: '%1',\n            uoalbert_hand_found: '手を見つけたか?',\n            uoalbert_touch_state: 'タッチセンサーを %1 ?',\n            uoalbert_is_oid: 'OIDが %1ですか?',\n            uoalbert_boolean: '%1?',\n            uoalbert_move_forward_unit: '前へ%1%2移動する %3',\n            uoalbert_move_backward_unit: '後ろへ%1%2移動する %3',\n            uoalbert_turn_unit_in_place: '%1へ%2%3その場で回す %4',\n            uoalbert_pivot_around_unit_in_direction: '%1車輪を中心に%2%3%4方向に回す %5',\n            uoalbert_change_both_wheels_by: '左車輪を%1右車輪を%2ずつ変える %3',\n            uoalbert_set_both_wheels_to: '左車輪を%1右車輪を%2にする %3',\n            uoalbert_change_wheel_by: '%1車輪を%2ずつ変える %3',\n            uoalbert_set_wheel_to: '%1車輪を%2にする %3',\n            uoalbert_stop: '停止する %1',\n            uoalbert_set_board_size: 'ボード板幅を%1高さを%2にする %3',\n            uoalbert_set_eye_to: '%1眼を%2にする %3',\n            uoalbert_pick_eye: '%1眼を%2にする %3',\n            uoalbert_change_eye_by_rgb: '%1眼をR:%2G:%3B:%4ずつ変える %5',\n            uoalbert_set_eye_to_rgb: '%1眼をR:%2G:%3B:%4にする %5',\n            uoalbert_clear_eye: '%1眼を消す %2',\n            uoalbert_play_sound_times: '%1音を%2回鳴らす %3',\n            uoalbert_play_sound_times_until_done: '終わるまで%1音を%2回鳴らす %3',\n            uoalbert_change_buzzer_by: 'ブザー音を%1ずつ変える %2',\n            uoalbert_set_buzzer_to: 'ブザー音を%1にする %2',\n            uoalbert_clear_sound: '音を消す %1',\n            uoalbert_play_note: '%1%2音を鳴らす %3',\n            uoalbert_play_note_for: '%1%2音を%3拍鳴らす %4',\n            uoalbert_rest_for: '%1拍休む %2',\n            uoalbert_change_tempo_by: 'テンポを%1ずつ変える %2',\n            uoalbert_set_tempo_to: 'テンポを%1BPMにする %2',\n        },\n        Helper: {\n            uoalbert_value: \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>touch: value of touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>oid: value of oid sensor (range: -1 ~ 65535, initial value: -1)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            uoalbert_hand_found: 'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            uoalbert_touch_state: 'If the touch sensor clicked/long-pressed/long-long-pressed, true, otherwise false.',\n            uoalbert_is_oid: 'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            uoalbert_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            uoalbert_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            uoalbert_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            uoalbert_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            uoalbert_pivot_around_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            uoalbert_change_both_wheels_by: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            uoalbert_set_both_wheels_to: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            uoalbert_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            uoalbert_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            uoalbert_stop: 'Stops both wheels.',\n            uoalbert_set_board_size: 'Sets the width and height of the board.',\n            uoalbert_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            uoalbert_pick_eye: 'Turns left/right/both eyes to the selected color.',\n            uoalbert_change_eye_by_rgb: 'Adds the entered values to the current R, G, B values of left/right/both eyes, respectively.',\n            uoalbert_set_eye_to_rgb: 'Sets the R, G, B values of left/right/both eyes to the entered values.',\n            uoalbert_clear_eye: 'Turns off the left/right/both eyes.',\n            uoalbert_play_sound_times: 'Plays the selected sound as many times as entered.',\n            uoalbert_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            uoalbert_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            uoalbert_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            uoalbert_clear_sound: 'Turns off sound.',\n            uoalbert_play_note: 'It sounds the selected tone and octave.',\n            uoalbert_play_note_for: 'It sounds the selected tone and octave as much as the beat you entered.',\n            uoalbert_rest_for: 'Rests as much as the beat you entered.',\n            uoalbert_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            uoalbert_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_left_wheel: '左車輪',\n            ROBOID_monitor_right_wheel: '右車輪',\n            ROBOID_monitor_left_eye: '左眼',\n            ROBOID_monitor_right_eye: '右眼',\n            ROBOID_monitor_buzzer: 'ブザー',\n            ROBOID_monitor_note: '音符',\n            ROBOID_sensor_signal_strength: '信号強度',\n            ROBOID_sensor_left_proximity: '左近接センサー',\n            ROBOID_sensor_right_proximity: '右近接センサー',\n            ROBOID_sensor_acceleration_x: 'x軸加速度',\n            ROBOID_sensor_acceleration_y: 'y軸加速度',\n            ROBOID_sensor_acceleration_z: 'z軸加速度',\n            ROBOID_sensor_position_x: 'x位置',\n            ROBOID_sensor_position_y: 'y位置',\n            ROBOID_sensor_light: '照度',\n            ROBOID_sensor_temperature: '温度',\n            ROBOID_sensor_touch: 'タッチ',\n            ROBOID_sensor_oid: 'OID',\n            ROBOID_button_clicked: 'クリックしたか',\n            ROBOID_button_long_pressed: '長く押したか(1.5秒)',\n            ROBOID_button_long_long_pressed: '非常に長く押したか(3秒)',\n            ROBOID_tilt_forward: '前に傾けたか',\n            ROBOID_tilt_backward: '後に傾けたか',\n            ROBOID_tilt_left: '左に傾けたか',\n            ROBOID_tilt_right: '右に傾けたか',\n            ROBOID_tilt_flip: '上下裏返したか',\n            ROBOID_tilt_not: '傾けなかったか',\n            ROBOID_battery_normal: '電池が正常か',\n            ROBOID_battery_low: '電池が足りないか',\n            ROBOID_battery_empty: '電池がないか',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '秒',\n            ROBOID_unit_pulse: 'パルス',\n            ROBOID_unit_deg: '度',\n            ROBOID_left: '左',\n            ROBOID_right: '右',\n            ROBOID_both: '両',\n            ROBOID_forward: '前',\n            ROBOID_backward: '後',\n            ROBOID_color_red: '赤色',\n            ROBOID_color_orange: '橙色',\n            ROBOID_color_yellow: '黄色',\n            ROBOID_color_green: '緑色',\n            ROBOID_color_sky_blue: '水色',\n            ROBOID_color_blue: '青色',\n            ROBOID_color_violet: '青紫色',\n            ROBOID_color_purple: '紫色',\n            ROBOID_color_white: '白色',\n            ROBOID_sound_beep: 'ビープ',\n            ROBOID_sound_siren: 'サイレン',\n            ROBOID_sound_engine: 'エンジン',\n            ROBOID_sound_robot: 'ロボット',\n            ROBOID_sound_dibidibidip: 'ディバディバディップ',\n            ROBOID_sound_march: '行進',\n            ROBOID_sound_birthday: '誕生',\n            ROBOID_note_c: 'ド',\n            ROBOID_note_c_sharp: 'ド♯(レ♭)',\n            ROBOID_note_d: 'レ',\n            ROBOID_note_d_sharp: 'レ♯(ミ♭)',\n            ROBOID_note_e: 'ミ',\n            ROBOID_note_f: 'ファ',\n            ROBOID_note_f_sharp: 'ファ♯(ソ♭)',\n            ROBOID_note_g: 'ソ',\n            ROBOID_note_g_sharp: 'ソ♯(ラ♭)',\n            ROBOID_note_a: 'ラ',\n            ROBOID_note_a_sharp: 'ラ♯(シ♭)',\n            ROBOID_note_b: 'シ',\n        },\n    },\n    vn: {\n        template: {\n            uoalbert_value: '%1',\n            uoalbert_hand_found: 'hand found?',\n            uoalbert_touch_state: 'touch sensor %1 ?',\n            uoalbert_is_oid: 'oid %1?',\n            uoalbert_boolean: '%1?',\n            uoalbert_move_forward_unit: 'move forward %1 %2 %3',\n            uoalbert_move_backward_unit: 'move backward %1 %2 %3',\n            uoalbert_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            uoalbert_pivot_around_unit_in_direction: 'pivot around %1 wheel %2 %3 in %4 direction %5',\n            uoalbert_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            uoalbert_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            uoalbert_change_wheel_by: 'change %1 wheel by %2 %3',\n            uoalbert_set_wheel_to: 'set %1 wheel to %2 %3',\n            uoalbert_stop: 'stop %1',\n            uoalbert_set_board_size: 'set board size to width: %1 height: %2 %3',\n            uoalbert_set_eye_to: 'set %1 eye to %2 %3',\n            uoalbert_pick_eye: 'set %1 eye to %2 %3',\n            uoalbert_change_eye_by_rgb: 'change %1 eye by r: %2 g: %3 b: %4 %5',\n            uoalbert_set_eye_to_rgb: 'set %1 eye to r: %2 g: %3 b: %4 %5',\n            uoalbert_clear_eye: 'clear %1 eye %2',\n            uoalbert_play_sound_times: 'play sound %1 %2 times %3',\n            uoalbert_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            uoalbert_change_buzzer_by: 'change buzzer by %1 %2',\n            uoalbert_set_buzzer_to: 'set buzzer to %1 %2',\n            uoalbert_clear_sound: 'clear sound %1',\n            uoalbert_play_note: 'play note %1 %2 %3',\n            uoalbert_play_note_for: 'play note %1 %2 for %3 beats %4',\n            uoalbert_rest_for: 'rest for %1 beats %2',\n            uoalbert_change_tempo_by: 'change tempo by %1 %2',\n            uoalbert_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            uoalbert_value: \"left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -8192 to 8191, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>touch: value of touch sensor (when touched 1, otherwise 0, initial value: 0)<br/>oid: value of oid sensor (range: -1 ~ 65535, initial value: -1)<br/>x position: x-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>y position: y-coordinate value of robot's position on the board (range: -1 ~ 39999, initial value: -1)<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.\",\n            uoalbert_hand_found: 'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n            uoalbert_touch_state: 'If the touch sensor clicked/long-pressed/long-long-pressed, true, otherwise false.',\n            uoalbert_is_oid: 'If the oid value detected by the oid sensor is equal to the entered number, true, otherwise false.',\n            uoalbert_boolean: \"tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false\",\n            uoalbert_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            uoalbert_move_backward_unit: 'Moves backward for the number of cm/seconds/pulses entered.',\n            uoalbert_turn_unit_in_place: 'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            uoalbert_pivot_around_unit_in_direction: 'Pivots around the left/right wheel in the forward/backward direction for the number of degrees/seconds/pulses entered.',\n            uoalbert_change_both_wheels_by: 'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            uoalbert_set_both_wheels_to: 'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            uoalbert_change_wheel_by: 'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            uoalbert_set_wheel_to: 'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            uoalbert_stop: 'Stops both wheels.',\n            uoalbert_set_board_size: 'Sets the width and height of the board.',\n            uoalbert_set_eye_to: 'Turns left/right/both eyes to the selected color.',\n            uoalbert_pick_eye: 'Turns left/right/both eyes to the selected color.',\n            uoalbert_change_eye_by_rgb: 'Adds the entered values to the current R, G, B values of left/right/both eyes, respectively.',\n            uoalbert_set_eye_to_rgb: 'Sets the R, G, B values of left/right/both eyes to the entered values.',\n            uoalbert_clear_eye: 'Turns off the left/right/both eyes.',\n            uoalbert_play_sound_times: 'Plays the selected sound as many times as entered.',\n            uoalbert_play_sound_times_until_done: 'Plays the selected sound as many times as entered, and waits for completion.',\n            uoalbert_change_buzzer_by: 'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n            uoalbert_set_buzzer_to: 'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n            uoalbert_clear_sound: 'Turns off sound.',\n            uoalbert_play_note: 'It sounds the selected tone and octave.',\n            uoalbert_play_note_for: 'It sounds the selected tone and octave as much as the beat you entered.',\n            uoalbert_rest_for: 'Rests as much as the beat you entered.',\n            uoalbert_change_tempo_by: 'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            uoalbert_set_tempo_to: 'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_monitor_left_eye: 'left eye',\n            ROBOID_monitor_right_eye: 'right eye',\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_sensor_left_proximity: 'left proximity',\n            ROBOID_sensor_right_proximity: 'right proximity',\n            ROBOID_sensor_acceleration_x: 'x acceleration',\n            ROBOID_sensor_acceleration_y: 'y acceleration',\n            ROBOID_sensor_acceleration_z: 'z acceleration',\n            ROBOID_sensor_position_x: 'x position',\n            ROBOID_sensor_position_y: 'y position',\n            ROBOID_sensor_light: 'light',\n            ROBOID_sensor_temperature: 'temperature',\n            ROBOID_sensor_touch: 'touch',\n            ROBOID_sensor_oid: 'oid',\n            ROBOID_button_clicked: 'clicked',\n            ROBOID_button_long_pressed: 'long-pressed (1.5 secs)',\n            ROBOID_button_long_long_pressed: 'long-long-pressed (3 secs)',\n            ROBOID_tilt_forward: 'tilt forward',\n            ROBOID_tilt_backward: 'tilt backward',\n            ROBOID_tilt_left: 'tilt left',\n            ROBOID_tilt_right: 'tilt right',\n            ROBOID_tilt_flip: 'tilt flip',\n            ROBOID_tilt_not: 'not tilt',\n            ROBOID_battery_normal: 'battery normal',\n            ROBOID_battery_low: 'battery low',\n            ROBOID_battery_empty: 'battery empty',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_forward: 'forward',\n            ROBOID_backward: 'backward',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n});\n\nEntry.UoAlbert.blockMenuBlocks = [\n    'uoalbert_value',\n    'uoalbert_hand_found',\n    'uoalbert_touch_state',\n    'uoalbert_is_oid',\n    'uoalbert_boolean',\n    'uoalbert_move_forward_unit',\n    'uoalbert_move_backward_unit',\n    'uoalbert_turn_unit_in_place',\n    'uoalbert_pivot_around_unit_in_direction',\n    'uoalbert_change_both_wheels_by',\n    'uoalbert_set_both_wheels_to',\n    'uoalbert_change_wheel_by',\n    'uoalbert_set_wheel_to',\n    'uoalbert_stop',\n    'uoalbert_set_board_size',\n    'uoalbert_set_eye_to',\n    'uoalbert_pick_eye',\n    'uoalbert_change_eye_by_rgb',\n    'uoalbert_set_eye_to_rgb',\n    'uoalbert_clear_eye',\n    'uoalbert_play_sound_times',\n    'uoalbert_play_sound_times_until_done',\n    'uoalbert_change_buzzer_by',\n    'uoalbert_set_buzzer_to',\n    'uoalbert_clear_sound',\n    'uoalbert_play_note',\n    'uoalbert_play_note_for',\n    'uoalbert_rest_for',\n    'uoalbert_change_tempo_by',\n    'uoalbert_set_tempo_to',\n];\n\nEntry.UoAlbert.getBlocks = function() {\n    return {\n        uoalbert_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                        [Lang.Blocks.ROBOID_sensor_right_proximity, 'RIGHT_PROXIMITY'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                        [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                        [Lang.Blocks.ROBOID_sensor_touch, 'TOUCH'],\n                        [Lang.Blocks.ROBOID_sensor_oid, 'OID'],\n                        [Lang.Blocks.ROBOID_sensor_position_x, 'POSITION_X'],\n                        [Lang.Blocks.ROBOID_sensor_position_y, 'POSITION_Y'],\n                        [Lang.Blocks.ROBOID_sensor_light, 'LIGHT'],\n                        [Lang.Blocks.ROBOID_sensor_temperature, 'TEMPERATURE'],\n                        [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                    ],\n                    value: 'LEFT_PROXIMITY',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uoalbert_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'uoalbert_sensor',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                                    [Lang.Blocks.ROBOID_sensor_right_proximity, 'RIGHT_PROXIMITY'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_x, 'ACCELERATION_X'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_y, 'ACCELERATION_Y'],\n                                    [Lang.Blocks.ROBOID_sensor_acceleration_z, 'ACCELERATION_Z'],\n                                    [Lang.Blocks.ROBOID_sensor_touch, 'TOUCH'],\n                                    [Lang.Blocks.ROBOID_sensor_oid, 'OID'],\n                                    [Lang.Blocks.ROBOID_sensor_position_x, 'POSITION_X'],\n                                    [Lang.Blocks.ROBOID_sensor_position_y, 'POSITION_Y'],\n                                    [Lang.Blocks.ROBOID_sensor_light, 'LIGHT'],\n                                    [Lang.Blocks.ROBOID_sensor_temperature, 'TEMPERATURE'],\n                                    [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                                ],\n                                value: 'LEFT_PROXIMITY',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_hand_found: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'uoalbert_hand_found',\n            },\n            class: 'uoalbert_sensor',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.checkHandFound(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.hand_found()',\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        uoalbert_touch_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_button_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_button_long_pressed, 'LONG_PRESSED'],\n                        [Lang.Blocks.ROBOID_button_long_long_pressed, 'LONG_LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'uoalbert_touch_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'uoalbert_sensor',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.checkTouchState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.is_touch(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_button_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_button_long_pressed, 'LONG_PRESSED'],\n                                    [Lang.Blocks.ROBOID_button_long_long_pressed, 'LONG_LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_is_oid: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                ],\n                type: 'uoalbert_is_oid',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'uoalbert_sensor',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.checkOid(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.is_oid(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                        blockType: 'param',\n                    },\n                ],\n            },\n        },\n        uoalbert_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                        [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                        [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                        [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                        [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                        [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                        [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'TILT_FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uoalbert_boolean',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'uoalbert_sensor',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_tilt_forward, 'TILT_FORWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_backward, 'TILT_BACKWARD'],\n                                    [Lang.Blocks.ROBOID_tilt_left, 'TILT_LEFT'],\n                                    [Lang.Blocks.ROBOID_tilt_right, 'TILT_RIGHT'],\n                                    [Lang.Blocks.ROBOID_tilt_flip, 'TILT_FLIP'],\n                                    [Lang.Blocks.ROBOID_tilt_not, 'TILT_NOT'],\n                                    [Lang.Blocks.ROBOID_battery_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.ROBOID_battery_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.ROBOID_battery_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'TILT_FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'uoalbert_move_forward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.move_forward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['5'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'uoalbert_move_backward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.move_backward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'uoalbert_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_pivot_around_unit_in_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_backward, 'BACKWARD'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                    null,\n                ],\n                type: 'uoalbert_pivot_around_unit_in_direction',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VALUE: 1,\n                UNIT: 2,\n                TOWARD: 3,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.pivotUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.pivot(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_forward, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_backward, 'BACKWARD'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_change_both_wheels_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_change_both_wheels_by',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_set_both_wheels_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_set_both_wheels_to',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uoalbert_stop',\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.stop()',\n                    },\n                ],\n            },\n        },\n        uoalbert_set_board_size: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['108'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['76'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_set_board_size',\n            },\n            paramsKeyMap: {\n                WIDTH: 0,\n                HEIGHT: 1,\n            },\n            class: 'uoalbert_wheel',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.setBoardSize(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.set_board_size(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_set_eye_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'uoalbert_set_eye_to',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                COLOR: 1,\n            },\n            class: 'uoalbert_eye',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.setEyeColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.set_eye(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_pick_eye: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'uoalbert_pick_eye',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                COLOR: 1,\n            },\n            class: 'uoalbert_eye',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.pickEyeColor(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.pick_eye(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_change_eye_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_change_eye_by_rgb',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'uoalbert_eye',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.changeEyeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.add_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_set_eye_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_set_eye_to_rgb',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'uoalbert_eye',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.setEyeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.set_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_clear_eye: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'uoalbert_clear_eye',\n            },\n            paramsKeyMap: {\n                EYE: 0,\n            },\n            class: 'uoalbert_eye',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.clearEye(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.clear_eye(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_play_sound_times',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.play_sound(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.play_sound_until_done(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.add_buzzer(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.set_buzzer(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'uoalbert_clear_sound',\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.clear_sound()',\n                        params: [null],\n                    },\n                ],\n            },\n        },\n        uoalbert_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'uoalbert_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.play_note(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.play_note_beat(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_rest_for',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.rest_beat(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        uoalbert_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'uoalbert_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'uoalbert_sound',\n            isNotFor: ['uoalbert'],\n            func(sprite, script) {\n                const robot = Entry.UoAlbert.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'UoAlbert.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.UoAlbert;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_wearable.js",
    "content": "'use strict';\n\nEntry.Wearable = {\n    id: '4A.3',\n    name: 'wearable', // isNotFor 속성과 대소문자까지 정확하게 매치되어야 합니다.\n    url: 'http://www.robolink.co.kr/', // 생략 가능합니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    imageName: 'robolink_wearable.png', // images/hardware 폴더 내에 존재하는 이미지입니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    title: {\n        ko: '로보링크 웨어러블 키트',\n        en: 'Robolink Wearable kit',\n    },\n       \n    setZero: function() {\n        Entry.hw.update();\n    },\n};\n\n// 언어 적용\nEntry.Wearable.setLanguage = function() {\n    return {\n        ko: {\n            Blocks: {\n            turn_On:   '켜기',\n            turn_Off:  '끄기',\n            output_yaw:   '요우',\n            output_pitch: '피치',\n            output_roll:  '롤',\n            button_up: '위',\n            button_down: '아래',\n            button_left: '왼쪽',\n            button_right: '오른쪽',\n            button_joy_left: '조이스틱 왼쪽',\n            button_joy_right: '조이스틱 오른쪽',  \n            joystick_X: 'X축',\n            joystick_Y: 'Y축', \n            LED_board_main: '메인 보드',\n            LED_board_left: '왼쪽 조이스틱',\n            LED_board_right: '오른쪽 조이스틱',  \n            sound_fire_ball: '파이어 볼',\n            sound_coin: '코인',\n            sound_up1: '보너스',\n            sound_beep1: '비프 1번',\n            sound_beep2: '비프 2번',\n            sound_1: '소리 1번',\n            sound_2: '소리 2번',\n            sound_3: '소리 3번',\n            sound_charging: '충전',\n            pitch_mute: '무음',\n            pitch_C: '도',\n            pitch_CSharp: '도#',\n            pitch_D: '레',\n            pitch_DSharp: '레#',\n            pitch_E: '미',\n            pitch_F: '파',\n            pitch_FSharp: '파#',\n            pitch_G: '솔',\n            pitch_GSharp: '솔#',\n            pitch_A: '라',\n            pitch_ASharp: '라#',\n            pitch_B: '시',\n            whole_note: '온음표',\n            half_note: '2분음표',\n            quarter_note: '4분음표',\n            eighth_note: '8분음표',\n            sixteenth_note: '16분음표',\n            \n            },\n            // ko.js에 작성하던 내용\n            template: {\n                test_value:'테스트 %1',\n                attitude_angle_value:'자세 값 %1',\n                leftJoystick_value:'왼쪽 조이스틱 %1',\n                rightJoystick_value:'오른쪽 조이스틱 %1',\n                button_input:'버튼 입력 %1',\n                mic_input:'마이크 입력',\n                battery_check:'배터리 체크',\n                mainLED_control:'LED %1 번호 %2 R:%3 G:%4 B:%5 동작 %6 %7',\n                LED_control_bright:'LED %1 번호 %2 밝기 %3 동작 %4 %5', \n                LED_All_turn_off : '모든 %1 LED 전부 끄기 %2',\n                sound_effect:'버저 음향 효과 %1 %2',\n                play_pitch:'%1 옥타브 %2 을(를) %3 초 연주 %4'\n            },\n        },\n        en: {\n            Blocks: {\n                turn_On:   'ON',\n                turn_Off:  'OFF',\n                output_yaw:   'YAW',\n                output_pitch: 'PITCH',\n                output_roll:  'ROLL',\n                button_up: 'UP',\n                button_down: 'DOWN',\n                button_left: 'LEFT',\n                button_right: 'RIGHT',\n                button_joy_left: 'JOY_LEFT',\n                button_joy_right: 'JOY_RIGHT',\n                joystick_X: 'X',\n                joystick_Y: 'Y',\n                LED_board_main: 'MAIN',\n                LED_board_left: 'LEFT_JOYSTICK',\n                LED_board_right: 'RIGHT_JOYSTICK', \n                sound_fire_ball: 'FIRE_BALL',\n                sound_coin: 'COIN',\n                sound_up1: 'UP1',\n                sound_beep1: 'BEEP1',\n                sound_beep2: 'BEEP2',\n                sound_1: 'SOUND1',\n                sound_2: 'SOUND2',\n                sound_3: 'SOUND3',\n                sound_charging: 'CHARGING',\n                pitch_mute: 'MUTE',\n                pitch_C: 'C',\n                pitch_CSharp: 'C#',\n                pitch_D: 'D',\n                pitch_DSharp: 'D#',\n                pitch_E: 'E',\n                pitch_F: 'F',\n                pitch_FSharp: 'F#',\n                pitch_G: 'G',\n                pitch_GSharp: 'G#',\n                pitch_A: 'A',\n                pitch_ASharp: 'A#',\n                pitch_B: 'B',\n                whole_note: 'WHOLE_NOTE',\n                half_note: 'HELF_NOTE',\n                quarter_note: 'QUARTER_NOTE',\n                eighth_note: 'EIGHTH_NOTE',\n                sixteenth_note: 'SIXTEENTH_NOTE',    \n                                   \n            },\n            // en.js에 작성하던 내용\n            template: {\n                test_Value:'test %1',\n                attitude_angle_value:'attitude %1',\n                leftJoystick_value:'left joystick %1',\n                rightJoystick_value:'right joystick %1',\n                button_input:'button input %1',\n                mic_input:'mic input',\n                battery_check:'battery check',\n                mainLED_control:'LED %1 number %2 R:%3 G:%4 B:%5 turn %6 %7',\n                LED_control_bright:'LED %1 number %2 brightness %3 turn %4 %5',\n                LED_All_turn_off : 'all %1 LEDs clear %2',\n                sound_effect:'sound effect %1 %2',\n                play_pitch:'play %1 octave %2 for %3 second %4',\n            },\n        },\n    };\n};\n\nEntry.Wearable.blockMenuBlocks = [\n    //'test_value',\n    'mic_input',\n    'battery_check',\n    'button_input',   \n    'attitude_angle_value',\n    'leftJoystick_value',\n    'rightJoystick_value',\n    'mainLED_control',\n    'LED_control_bright',\n    'LED_All_turn_off', \n    'sound_effect',\n    'play_pitch',      \n];\n\n\n\n\n\n// 블록 생성\nEntry.Wearable.getBlocks = function() {\n    return {\n        test_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    // Dropdown 생성 기준은\n                    // [[\"key1\", \"value1\"],\n                    //  [\"key2\", \"value2\"]]\n                    options: [\n                        ['VAL1', 'VAL1'],\n                        ['VAL2', 'VAL2'],\n                        ['VAL3', 'VAL3']                        \n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['VAL1'],\n                type: 'test_value',\n            },\n            paramsKeyMap: {\n                TEST: 0,\n            },\n            class: 'input',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                const btn = script.getStringField('TEST', script);\n                return Entry.hw.portData.sensorValue.test[btn];\n\n            },\n        },\n        attitude_angle_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.output_yaw, 'yaw'],\n                        [Lang.Blocks.output_pitch, 'pitch'],\n                        [Lang.Blocks.output_roll, 'roll']                        \n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['yaw'],\n                type: 'attitude_angle_value',\n            },\n            paramsKeyMap: {\n                EULER: 0,\n            },\n            class: 'input',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                const btn = script.getStringField('EULER', script);\n\n                return Entry.hw.portData.sensorValue.euler[btn];\n            },\n        },\n        leftJoystick_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',                   \n                    options: [\n                        [Lang.Blocks.joystick_X, 'leftX'],\n                        [Lang.Blocks.joystick_Y, 'leftY'],                      \n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['leftX'],\n                type: 'leftJoystick_value',\n            },\n            paramsKeyMap: {\n                LSTICK: 0,\n            },\n            class: 'input',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                const btn = script.getStringField('LSTICK', script);\n\n                return Entry.hw.portData.sensorValue.stick[btn];\n            },\n        },\n        rightJoystick_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',                   \n                    options: [\n                        [ Lang.Blocks.joystick_X, 'rightX'],\n                        [ Lang.Blocks.joystick_Y, 'rightY'],                      \n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['rightX'],\n                type: 'rightJoystick_value',\n            },\n            paramsKeyMap: {\n                RSTICK: 0,\n            },\n            class: 'input',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                const btn = script.getStringField('RSTICK', script);\n\n                return Entry.hw.portData.sensorValue.stick[btn];\n            },\n        },\n        button_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.button_up, 'btnUp'],\n                        [Lang.Blocks.button_down, 'btnDown'],\n                        [Lang.Blocks.button_left, 'btnLeft'], \n                        [Lang.Blocks.button_right, 'btnRight'],\n                        [Lang.Blocks.button_joy_left, 'btnJoyL'],\n                        [Lang.Blocks.button_joy_right, 'btnJoyR'],                        \n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['btnUp'],\n                type: 'button_input',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n            },\n            class: 'input',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                const btn = script.getStringField('BUTTON', script);\n                if(Entry.hw.portData.sensorValue.button[btn] == 1) return true;\n                else return false;\n            },\n        },\n        mic_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            def: {\n                type: 'mic_input',\n            },           \n            class: 'input',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                return Entry.hw.portData.sensorValue.micInput;\n            },\n        },\n        battery_check: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            def: {\n                type: 'battery_check',\n            },           \n            class: 'input',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                return Entry.hw.portData.sensorValue.battery;\n            },\n        },\n        mainLED_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params:[\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.LED_board_main, 'MAIN'],\n                        [Lang.Blocks.LED_board_left, 'LEFT'],\n                        [Lang.Blocks.LED_board_right, 'RIGHT'],                                           \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turn_On, 'ON'],\n                        [Lang.Blocks.turn_Off, 'OFF']                        \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator',   img: 'block_icon/hardware_icon.svg',  size: 12 },\n            ],\n            def: {\n                params: ['MAIN', { type: 'number', params: ['0'] }, { type: 'number', params: ['0'] }, {  type: 'number', params: ['0'] }, {  type: 'number', params: ['0'] }, 'ON', null],\n                type: 'mainLED_control',\n            },\n            paramsKeyMap: {\n                BOARD: 0,\n                NUMBER: 1,\n                RED: 2,\n                GREEN: 3,\n                BLUE: 4,\n                TURN: 5,\n            },           \n            class: 'output',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                \n                var LEDNumber = [\n                    'mainLED0',\n                    'mainLED1',\n                    'mainLED2',\n                    'mainLED3',\n                    'mainLED4',\n                    'mainLED5',\n                    'mainLED6',\n                    'mainLED7',\n                    'mainLED8',\n                    'mainLED9',\n                    'mainLED10',\n                    'mainLED11',\n                    'leftLED0',\n                    'leftLED1',\n                    'leftLED2',\n                    'rightLED0',\n                    'rightLED1',\n                    'rightLED2',\n                ];\n                \n                var LEDNum = '';\n                const board = script.getStringField('BOARD', script);\n                var _num = script.getNumberValue('NUMBER');\n                var _red = script.getNumberValue('RED');\n                var _green = script.getNumberValue('GREEN');\n                var _blue = script.getNumberValue('BLUE');  \n                const _turn = script.getStringField('TURN', script); \n                \n                if(_red < 0) _red = 0; else if(_red > 255) _red = 255;\n                if(_green < 0) _green = 0; else if(_green > 255) _green = 255;\n                if(_blue < 0) _blue = 0; else if(_blue > 255) _blue = 255;\n\n                console.log(board, _num, \" R:\",_red, \"G:\", _green, \"B:\", _blue, \" TURN:\", _turn);\n                \n                if(board == 'MAIN') {\n                    if(( _num >= 0)&&(_num < 12)) {\n                        LEDNum = LEDNumber[_num];\n                    }                    \n                }\n                else if(board == 'LEFT') {\n                    if((_num >= 0)&&(_num < 12)) {\n                        LEDNum = LEDNumber[_num + 12];\n                    }\n                }\n                else if(board == 'RIGHT') {\n                    if((_num >= 0)&&(_num < 12)) {\n                        LEDNum = LEDNumber[_num + 15];\n                    }\n                }                \n                if(_turn == 'OFF') {_red = 0; _green = 0; _blue = 0;}\n                \n                Entry.hw.sendQueue[LEDNum] = [_red, _green, _blue];\n            },\n        },\n        LED_control_bright: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params:[\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.LED_board_main, 'MAIN'],\n                        [Lang.Blocks.LED_board_left, 'LEFT'],\n                        [Lang.Blocks.LED_board_right, 'RIGHT'],                                           \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },               \n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.turn_On, 'ON'],\n                        [Lang.Blocks.turn_Off, 'OFF']                        \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator',   img: 'block_icon/hardware_icon.svg',   size: 12 },\n            ],\n            def: {\n                params: ['MAIN', { type: 'number', params: ['0'] }, { type: 'number', params: ['0'] },  'ON', null],\n                type: 'LED_control_bright',\n            },\n            paramsKeyMap: {\n                BOARD: 0,\n                NUMBER: 1,\n                BRIGHT: 2,\n                TURN: 3,\n            },           \n            class: 'output',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                \n                var LEDNumber = [\n                    'mainLED0',\n                    'mainLED1',\n                    'mainLED2',\n                    'mainLED3',\n                    'mainLED4',\n                    'mainLED5',\n                    'mainLED6',\n                    'mainLED7',\n                    'mainLED8',\n                    'mainLED9',\n                    'mainLED10',\n                    'mainLED11',\n                    'leftLED0',\n                    'leftLED1',\n                    'leftLED2',\n                    'rightLED0',\n                    'rightLED1',\n                    'rightLED2',\n                ];\n                \n                var LEDNum = '';\n                const board = script.getStringField('BOARD', script);\n                var _num = script.getNumberValue('NUMBER');\n                var _bright = script.getNumberValue('BRIGHT');\n                const _turn = script.getStringField('TURN', script); \n                                \n                if(_bright < 0) _bright = 0; else if(_bright > 255) _bright = 255;    \n                console.log(board, _num, \" BRIGHTNESS:\", _bright, \" TURN:\", _turn);\n\n                if(board == 'MAIN') {\n                    if(( _num >= 0)&&(_num < 12)) {\n                        LEDNum = LEDNumber[_num];\n                    }                    \n                }\n                else if(board == 'LEFT') {\n                    if((_num >= 0)&&(_num < 12)) {\n                        LEDNum = LEDNumber[_num + 12];\n                    }\n                }\n                else if(board == 'RIGHT') {\n                    if((_num >= 0)&&(_num < 12)) {\n                        LEDNum = LEDNumber[num - 1 + 15];\n                    }\n                }                \n                if(_turn == 'OFF') {_bright = 0;}\n                \n                Entry.hw.sendQueue[LEDNum] = [_bright, _bright, _bright];\n            },\n        },\n        LED_All_turn_off: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params:[\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.LED_board_main, 'MAIN'],\n                        [Lang.Blocks.LED_board_left, 'LEFT'],\n                        [Lang.Blocks.LED_board_right, 'RIGHT'],                                           \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n               \n                { type: 'Indicator',   img: 'block_icon/hardware_icon.svg',   size: 12 },\n            ],\n            def: {\n                params: ['MAIN', null],\n                type: 'LED_All_turn_off',\n            },\n            paramsKeyMap: {\n                BOARD: 0,               \n            },           \n            class: 'output',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                \n                var LEDNumber = [\n                    'mainLED0',\n                    'mainLED1',\n                    'mainLED2',\n                    'mainLED3',\n                    'mainLED4',\n                    'mainLED5',\n                    'mainLED6',\n                    'mainLED7',\n                    'mainLED8',\n                    'mainLED9',\n                    'mainLED10',\n                    'mainLED11',\n                    'leftLED0',\n                    'leftLED1',\n                    'leftLED2',\n                    'rightLED0',\n                    'rightLED1',\n                    'rightLED2',\n                ];\n                \n                var LEDNum = '';\n                const board = script.getStringField('BOARD', script);                             \n\n                if(board == 'MAIN') {\n                                     \n                    for (var num = 0; num < 12; num++) {\n                        LEDNum = LEDNumber[num];\n                        Entry.hw.sendQueue[LEDNum] = [0, 0, 0];\n                    }\n                }\n                else if(board == 'LEFT') {\n                   \n                    for (var num = 12; num < 15; num++) {\n                        LEDNum = LEDNumber[num];\n                        Entry.hw.sendQueue[LEDNum] = [0, 0, 0];\n                    }\n\n                }\n                else if(board == 'RIGHT') {\n                    \n                    for (var num = 15; num < 18; num++) {\n                        LEDNum = LEDNumber[num];\n                        Entry.hw.sendQueue[LEDNum] = [0, 0, 0];\n                    }\n                }              \n            },\n        },\n        sound_effect: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params:[\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.sound_fire_ball, '1'],\n                        [Lang.Blocks.sound_coin, '2'],\n                        [Lang.Blocks.sound_up1, '3'],\n                        [Lang.Blocks.sound_beep1, '4'],\n                        [Lang.Blocks.sound_beep2, '5'],\n                        [Lang.Blocks.sound_1, '6'],\n                        [Lang.Blocks.sound_2, '7'],\n                        [Lang.Blocks.sound_3, '8'],\n                        [Lang.Blocks.sound_charging, '9'],                        \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator',  img: 'block_icon/hardware_icon.svg',   size: 12 },               \n            ],\n            def: {\n                params: ['1', null],\n                type: 'sound_effect',\n            },\n            paramsKeyMap: {\n                EFFECT: 0,               \n            },           \n            class: 'output',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                 const num = script.getNumberField('EFFECT', script);\n                 //Entry.hw.sendQueue['soundNumber'] = num;\n                 \n                 var exTime = new Date();\n                 var firstCheck = true;\n                 \n                 return new Promise(resolve => {\n                    \n                    var ttt = setInterval(() => {\n                        Entry.hw.sendQueue['octave'] = num;\n                        Entry.hw.sendQueue['soundNumber'] = num;\n                        var tempTime = new Date(); \n                        \n                        if((tempTime - exTime) >= 1000) firstCheck = false;\n                        \n                        if(firstCheck == false) {\n                            Entry.hw.sendQueue['octave'] = 0xFE;\n                            Entry.hw.sendQueue['soundNumber'] = 0xFE;\n                            resolve();\n                            clearInterval(ttt);\n                        }\n                    }, 50);\n                 \n                });\n            },\n        },\n        play_pitch: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params:[\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],                                               \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.pitch_mute, '0'],\n                        [Lang.Blocks.pitch_C, '1'],\n                        [Lang.Blocks.pitch_CSharp, '2'],\n                        [Lang.Blocks.pitch_D, '3'],\n                        [Lang.Blocks.pitch_DSharp, '4'],\n                        [Lang.Blocks.pitch_E, '5'],\n                        [Lang.Blocks.pitch_F, '6'],\n                        [Lang.Blocks.pitch_FSharp, '7'],\n                        [Lang.Blocks.pitch_G, '8'],\n                        [Lang.Blocks.pitch_GSharp, '9'],\n                        [Lang.Blocks.pitch_A, '10'],\n                        [Lang.Blocks.pitch_ASharp, '11'],\n                        [Lang.Blocks.pitch_B, '12'],                                                                \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.whole_note, '200'],\n                        [Lang.Blocks.half_note,  '100'],\n                        [Lang.Blocks.quarter_note, '50'],\n                        [Lang.Blocks.eighth_note,  '25'],\n                        [Lang.Blocks.sixteenth_note, '10'],                                                                 \n                    ],\n                    fontSize: 11,\n\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator',   img: 'block_icon/hardware_icon.svg',   size: 12 },     \n            ],\n            def: {\n                params: ['1', '0', '200', null],\n                type: 'play_pitch',\n            },\n            paramsKeyMap: {\n                OCTAVE: 0,\n                PITCH: 1,\n                NOTE: 2,               \n            },           \n            class: 'output',\n            isNotFor: ['wearable'],\n            func: function(sprite, script) {\n                const oct = script.getNumberField('OCTAVE', script);\n                const pitch = script.getNumberField('PITCH', script);\n                var time = script.getNumberField('NOTE', script);                \n                var octave = 0;\n                if(pitch == 0)  octave = 0;\n                else octave = ((oct - 1) * 12) + pitch;\n                \n                var exTime = new Date();\n                var firstCheck = true;\n                \n                return new Promise(resolve => {\n                    \n                    var ttt = setInterval(() => {\n                        Entry.hw.sendQueue['soundNumber'] = octave + 100;\n                        Entry.hw.sendQueue['octave'] = octave + 100;\n                        Entry.hw.sendQueue['note'] = time;     \n                        var tempTime = new Date(); \n                        \n                        if((tempTime - exTime) >= ((time * 5) * 1.3)) firstCheck = false;\n                        \n                        if(firstCheck == false) {\n                            Entry.hw.sendQueue['soundNumber'] = 0xFE;\n                            Entry.hw.sendQueue['octave'] = 0xFE;\n                            resolve();\n                            clearInterval(ttt);\n                        }\n                    }, 50);\n                 \n                });\n            },\n        },\n\n    };\n};\n\nmodule.exports = Entry.Wearable;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_whalesbot_eagle_1001.js",
    "content": "'use strict';\nimport _range from 'lodash/range';\nimport DataTable from '../../../class/DataTable';\nimport entryModuleLoader from '../../../class/entryModuleLoader';\nimport metadata from '../hardwareLite/metadata_whalesbot_drone_lite.json';\n\nEntry.WhalesbotEagle1001 = {\n    id: '62.1',\n    name: 'whalesbot_eagle_1001',\n    url: '',\n    imageName: '',\n    title: {\n        ko: 'Whalesbot Eagle 1001',\n        en: '웨일스봇 Eagle 1001',\n    },\n    simulatorPopup: null,\n    unsupportBlockExist: false,\n    setZero: function () { },\n    sendCmd(msgString) {\n        let sq = Entry.hw.sendQueue;\n        sq['cmd'] = msgString;\n        Entry.hw.update();\n        delete sq['cmd'];\n    },\n    invalidParamValue: false,\n\n    exportProject() {\n        let project = {};\n\n        project.objects = Entry.container.toJSON();\n        const objects = project.objects;\n        project.scenes = Entry.scene.toJSON();\n        project.variables = Entry.variableContainer.getVariableJSON();\n        project.messages = Entry.variableContainer.getMessageJSON();\n        project.functions = Entry.variableContainer.getFunctionJSON();\n        project.tables = DataTable.getTableJSON();\n        project.speed = Entry.FPS;\n        project.interface = Entry.captureInterfaceState();\n        project.expansionBlocks = Entry.expansionBlocks;\n        project.aiUtilizeBlocks = Entry.aiUtilizeBlocks;\n        project.hardwareLiteBlocks = Entry.hardwareLiteBlocks;\n        project.learning = Entry.aiLearning?.toJSON();\n        project.externalModules = entryModuleLoader.moduleList;\n        project.externalModulesLite = entryModuleLoader.moduleListLite;\n\n        if (!objects || !objects.length) {\n            return false;\n        }\n\n        return project;\n    }\n};\n\nEntry.WhalesbotEagle1001.setLanguage = function () {\n    return {\n        ko: {\n            template: {\n                whalesbot_eagle_1001_openning_3d_simulator: '3D 시뮬레이터를 엽니 다',\n                whalesbot_eagle_1001_clean: '삭제',\n                whalesbot_eagle_1001_restart: '재시작',\n                whalesbot_eagle_1001_get_status: '상태 가져오기',\n                whalesbot_eagle_1001_entering_pitch_mode: '준비모드 시작하기',\n                whalesbot_eagle_1001_exit_pitch_mode: '준비모드 끝내기',\n                whalesbot_eagle_1001_automatic_take_off_height: '자동 이륙 높이 %1 cm',\n                whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset: '자동 이륙 고도 %1 cm 속도 %2 X 오프셋 %3 도 Y 오프셋 %4 도 으로 이동하기',\n                whalesbot_eagle_1001_automatic_landing: '드론착륙',\n                whalesbot_eagle_1001_automatic_descent_speed_offset: '자동 낙하 속도 %1 X 오프셋 %2 도 Y 오프셋 %3 도',\n                whalesbot_eagle_1001_set_the_flight_speed: '설정된 비행 속도는 %1 cm/s',\n                whalesbot_eagle_1001_get_setting_speed: '설정 속도 가져오기',\n                whalesbot_eagle_1001_rise: '위로 %1 cm',\n                whalesbot_eagle_1001_down: '아래로 %1 cm',\n                whalesbot_eagle_1001_fly_forward: '앞으로 %1 cm',\n                whalesbot_eagle_1001_fly_backward: '뒤로 %1 cm',\n                whalesbot_eagle_1001_fly_left: '왼쪽으로 %1 cm',\n                whalesbot_eagle_1001_fly_right: '오른쪽으로 %1 cm',\n                whalesbot_eagle_1001_turn_left: '왼쪽으로 회전 %1 °',\n                whalesbot_eagle_1001_turn_right: '오른쪽으로 회전 %1 °',\n                whalesbot_eagle_1001_fly_in_the_specified_direction: '속도 %1 , 방향 %2 으로이동하기',\n                whalesbot_eagle_1001_flight_designated: '지정된 거리를 비행합니다 x %1 cm y %2 cm z%3 cm 속도 %4 cm/s',\n                whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control: '리모컨 4개 채널 설정 Pitch %1 Roll %2 Throttle %3 Yaw %4',\n                whalesbot_eagle_1001_stop_moving_and_hover: '호버링기능',\n                whalesbot_eagle_1001_hover_at_specified_altitude: '지정된 높이에 서스펜션 %1 cm',\n                whalesbot_eagle_1001_emergency_stop: '긴급정지',\n                whalesbot_eagle_1001_set_the_steering_gear: '스티어링기어 ID 설정 포트 %1 속도 %2 각도 %3',\n                whalesbot_eagle_1001_execute_script: '스크립트 실행',\n                // light & speaker blocks\n                whalesbot_eagle_1001_ls_debug_value: '센서 값 확인 %1 %2',\n                whalesbot_eagle_1001_ls_display_symbol: '도트매트릭스 %1 포트 %2',\n                whalesbot_eagle_1001_ls_off_LED: '표현스크린 닫기 포트 %1',\n                whalesbot_eagle_1001_ls_display_digital_tube: '디지털튜브 포트 %1 %2',\n                whalesbot_eagle_1001_ls_display_digital_tube_score: '디지털튜브에 점수 표시 포트 %1 %2 : %3',\n                whalesbot_eagle_1001_ls_off_digital_tube: '디지털튜브 닫기 포트 %1',\n                whalesbot_eagle_1001_ls_set_RGB: 'LED색상설정 포트 %1 색상 R %2 G %3 B %4',\n                whalesbot_eagle_1001_ls_fly_RGB: 'Led 조명인가요? %1',\n                whalesbot_eagle_1001_ls_set_DO: '전자석 포트 %1 %2',\n                whalesbot_eagle_1001_ls_execute_script: '동작 없이 스크립트 실행',\n                // sensors\n                whalesbot_eagle_1001_ss_fly_state_POS_Z: '비행 고도 cm',\n                whalesbot_eagle_1001_ss_fly_state_LASER: '동체 내부 레이저 거리 측정 cm',\n                whalesbot_eagle_1001_ss_battery_voltage: '배터리 전압 (V)',\n                whalesbot_eagle_1001_ss_fly_state_STATE_TEMP: '메인보드 온도 (°)',\n                whalesbot_eagle_1001_ss_attitude_angle: '자세각 %1 (°)',\n                whalesbot_eagle_1001_ss_flight_angular_velocity: '비행각속도 %1 cm/s',\n                whalesbot_eagle_1001_ss_flight_acceleration: '비행 가속도 %1 (1g)',\n                whalesbot_eagle_1001_ss_optical_flow: '광류 %1 (cm)',\n                whalesbot_eagle_1001_ss_get_infrared_distance: '적외선센 포트 %1 값',\n                whalesbot_eagle_1001_ss_obstacle_infrared_detected_bool: '적외선센서 포트 %1 장애물 감지',\n                whalesbot_eagle_1001_ss_obstacle_infrared_detected_string: '적외선센서 포트 %1 장애물 감지',\n                whalesbot_eagle_1001_ss_human_infrared_value_bool: '인체 감지 센서 포트 %1 사람을 감지하다',\n                whalesbot_eagle_1001_ss_human_infrared_value_string: '인체 감지 센서 포트 %1 사람을 감지하다',\n                whalesbot_eagle_1001_ss_AI: '아날로그 입력 포트 %1 값',\n                whalesbot_eagle_1001_ss_get_ultrasonic_distance: '초음파센서 포트 %1 거리 강지 cm',\n                whalesbot_eagle_1001_ss_get_ambient_light: '조도센서 입력 포트 %1 값',\n                whalesbot_eagle_1001_ss_get_temperature: '온도 센서 포트 %1 °C',\n                whalesbot_eagle_1001_ss_get_humidity: '습도 센서 포트 %1 값 %',\n                whalesbot_eagle_1001_ss_get_flame: '불꽃센서 포트 %1 값',\n                whalesbot_eagle_1001_ss_get_gesture: '동작인식 포트 %1',\n                whalesbot_eagle_1001_ss_get_tof: '레이저 거리 측정 포트 %1',\n                whalesbot_eagle_1001_ss_fly_setpoint_LASER_ENABLE: '레이저 높이 %1',\n                whalesbot_eagle_1001_ss_get_bt_remote_control: '리모콘 버튼 %1 값',\n                whalesbot_eagle_1001_ss_seconds: '현재 타이머 값',\n                whalesbot_eagle_1001_ss_resettime: '타이머 재설정',\n            },\n            Device: {\n                whalesbot_eagle_1001: 'whalesbot_eagle_1001',\n            },\n            Menus: {\n                whalesbot_eagle_1001: 'WhalesbotEagle1001',\n            },\n            Blocks: {\n                light_speaker: {\n                    electro_magnet: { absorption: '붙다', break_off: '떨어지다' },\n                },\n                sensor: {\n                    attitude_angle: { pitch: 'Pitch', roll: 'Roll', yaw: 'Yaw' },\n                    laser_height_determination: { on: 'On', off: 'Off' },\n                    remote_control_button: { key: 'Key', left_rocker_x: 'Left rocker X', left_rocker_y: 'Left rocker Y', right_rocker_x: 'Right rocker X', right_rocker_y: 'Right rocker Y' },\n                },\n                whalesbot_eagle_1001_toast_status_title: \"드론 상태\",\n                whalesbot_eagle_1001_toast_prepare_download: \"다운로드 준비...\",\n                whalesbot_eagle_1001_toast_downloading_code: \"코드 다운로드...\",\n                whalesbot_eagle_1001_toast_download_success: \"다운로드 코드가 성공했습니다\",\n                whalesbot_eagle_1001_toast_download_failed: \"다운로드 코드가 실패했습니다\",\n                whalesbot_eagle_1001_toast_clean_failed: \"깨끗한 코드가 실패했습니다\",\n                whalesbot_eagle_1001_toast_clean_success: \"깨끗한 코드 성공\",\n                whalesbot_eagle_1001_toast_unsupport_block_title: \"지원되지 않는 블록\",\n                whalesbot_eagle_1001_toast_unsupport_block_msg: \"하드웨어에서는 일부 블록이 지원되지 않습니다\"\n            }\n        },\n        en: {\n            template: {\n                whalesbot_eagle_1001_openning_3d_simulator: 'Open 3D Simulator',\n                whalesbot_eagle_1001_clean: 'Clean',\n                whalesbot_eagle_1001_restart: 'Restart',\n                whalesbot_eagle_1001_get_status: 'Get Status',\n                whalesbot_eagle_1001_entering_pitch_mode: 'Entering Pitch Mode',\n                whalesbot_eagle_1001_exit_pitch_mode: 'Exit Pitch Mode',\n                whalesbot_eagle_1001_automatic_take_off_height: 'Automatic Take Off Height %1 cm',\n                whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset: 'Automatic Take Off Altitude %1 cm, Speed %2, X offset %3 degree, Y offset %4 degree',\n                whalesbot_eagle_1001_automatic_landing: 'Automatic Landing',\n                whalesbot_eagle_1001_automatic_descent_speed_offset: 'Automatic Descent Speed %1, X offset %2 degree, Y offset %3 degree',\n                whalesbot_eagle_1001_set_the_flight_speed: 'Set The Flight Speed To %1 cm/s',\n                whalesbot_eagle_1001_get_setting_speed: 'Get Setting Speed',\n                whalesbot_eagle_1001_rise: 'Rise %1 cm',\n                whalesbot_eagle_1001_down: 'Down %1 cm',\n                whalesbot_eagle_1001_fly_forward: 'Fly Forward %1 cm',\n                whalesbot_eagle_1001_fly_backward: 'Fly Backward %1 cm',\n                whalesbot_eagle_1001_fly_left: 'Fly Left %1 cm',\n                whalesbot_eagle_1001_fly_right: 'Fly Right %1 cm',\n                whalesbot_eagle_1001_turn_left: 'Turn Left %1 °',\n                whalesbot_eagle_1001_turn_right: 'Turn Right %1 °',\n                whalesbot_eagle_1001_fly_in_the_specified_direction: 'Fly In The Specified Direction Speed %1 cm/s Direction %2 °',\n                whalesbot_eagle_1001_flight_designated: 'Flight Designated Distance X %1 cm Y %2 cm Z %3 cm Speed %4 cm/s',\n                whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control: 'Set The Four Channel Lever Quantity Of Remote Control Pitch %1° Roll %2° Throttle %3° Roll %4°',\n                whalesbot_eagle_1001_stop_moving_and_hover: 'Stop Moving And Hover',\n                whalesbot_eagle_1001_hover_at_specified_altitude: 'Hover At a Specified Altitude %1 cm',\n                whalesbot_eagle_1001_emergency_stop: 'Emergency Stop',\n                whalesbot_eagle_1001_set_the_steering_gear: 'Set The Steering Gear Port %1 Speed %2 cm/s Angle %3 °',\n                whalesbot_eagle_1001_execute_script: 'Execute Script',\n                // light & speaker blocks\n                whalesbot_eagle_1001_ls_debug_value: 'Debugging: Data %1 %2',\n                whalesbot_eagle_1001_ls_display_symbol: 'Emotion screen symbols %1 port %2',\n                whalesbot_eagle_1001_ls_off_LED: 'Clear emotion screen port %1',\n                whalesbot_eagle_1001_ls_display_digital_tube: 'Digital tube port %1 %2',\n                whalesbot_eagle_1001_ls_display_digital_tube_score: 'Digital tube score display port %1 %2 : %3',\n                whalesbot_eagle_1001_ls_off_digital_tube: 'Clear digital tube port %1',\n                whalesbot_eagle_1001_ls_set_RGB: 'Set LED lights port %1 color R %2 G %3 B %4',\n                whalesbot_eagle_1001_ls_fly_RGB: 'Airborne lighting %1',\n                whalesbot_eagle_1001_ls_set_DO: 'Electromagnet port %1 %2',\n                whalesbot_eagle_1001_ls_execute_script: 'Execute Script Without Motion',\n                // sensors\n                whalesbot_eagle_1001_ss_fly_state_POS_Z: 'Flight attitude cm',\n                whalesbot_eagle_1001_ss_fly_state_LASER: 'Laser ranging inside the fuselage cm',\n                whalesbot_eagle_1001_ss_battery_voltage: 'Battery voltage (V)',\n                whalesbot_eagle_1001_ss_fly_state_STATE_TEMP: 'Main board temperature (°C)',\n                whalesbot_eagle_1001_ss_attitude_angle: 'Attitude angle %1 (°)',\n                whalesbot_eagle_1001_ss_flight_angular_velocity: 'Flight angular velocity %1 cm/s',\n                whalesbot_eagle_1001_ss_flight_acceleration: 'Flight acceleration %1 (1g)',\n                whalesbot_eagle_1001_ss_optical_flow: 'Optical flow %1 (cm)',\n                whalesbot_eagle_1001_ss_get_infrared_distance: 'Infrared ranging sensor port %1 value',\n                whalesbot_eagle_1001_ss_obstacle_infrared_detected_bool: 'Infrared port %1 obstacle detected',\n                whalesbot_eagle_1001_ss_obstacle_infrared_detected_string: 'Infrared port %1 obstacle detected',\n                whalesbot_eagle_1001_ss_human_infrared_value_bool: 'Human infrared sensor port %1 detects a person',\n                whalesbot_eagle_1001_ss_human_infrared_value_string: 'Human infrared sensor port %1 detects a person',\n                whalesbot_eagle_1001_ss_AI: 'Analog input port %1 value',\n                whalesbot_eagle_1001_ss_get_ultrasonic_distance: 'Ultrasonic sensor port %1 detect distance cm',\n                whalesbot_eagle_1001_ss_get_ambient_light: 'Ambient light port %1 value',\n                whalesbot_eagle_1001_ss_get_temperature: 'Temperature sensor port %1 °C',\n                whalesbot_eagle_1001_ss_get_humidity: 'Humidity sensor port %1 value %',\n                whalesbot_eagle_1001_ss_get_flame: 'Flame sensor port %1 value',\n                whalesbot_eagle_1001_ss_get_gesture: 'Gesture recognition port %1',\n                whalesbot_eagle_1001_ss_get_tof: 'Laser ranging port %1',\n                whalesbot_eagle_1001_ss_fly_setpoint_LASER_ENABLE: 'Laser height determination %1',\n                whalesbot_eagle_1001_ss_get_bt_remote_control: 'Remote control button %1 value',\n                whalesbot_eagle_1001_ss_seconds: 'current timer value',\n                whalesbot_eagle_1001_ss_resettime: 'Reset timer',\n            },\n            Device: {\n                whalesbot_eagle_1001: 'whalesbot_eagle_1001',\n            },\n            Menus: {\n                whalesbot_eagle_1001: 'WhalesbotEagle1001',\n            },\n            Blocks: {\n                light_speaker: {\n                    electro_magnet: { absorption: 'Absorption', break_off: 'Break off' },\n                },\n                sensor: {\n                    attitude_angle: { pitch: 'Pitch', roll: 'Roll', yaw: 'Yaw' },\n                    laser_height_determination: { on: 'On', off: 'Off' },\n                    remote_control_button: { key: 'Key', left_rocker_x: 'Left rocker X', left_rocker_y: 'Left rocker Y', right_rocker_x: 'Right rocker X', right_rocker_y: 'Right rocker Y' },\n                },\n                whalesbot_eagle_1001_toast_status_title: \"Drone Status\",\n                whalesbot_eagle_1001_toast_prepare_download: \"Prepare Downloading...\",\n                whalesbot_eagle_1001_toast_downloading_code: \"Downloading Code...\",\n                whalesbot_eagle_1001_toast_download_success: \"Download Code Successed\",\n                whalesbot_eagle_1001_toast_download_failed: \"Download code failed\",\n                whalesbot_eagle_1001_toast_clean_failed: \"Clean code failed\",\n                whalesbot_eagle_1001_toast_clean_success: \"Clean code success\",\n                whalesbot_eagle_1001_toast_unsupport_block_title: \"Unsupport Block\",\n                whalesbot_eagle_1001_toast_unsupport_block_msg: \"There is some blocks is not supported by hardware\"\n            }\n        },\n    };\n};\n\nEntry.WhalesbotEagle1001.blockMenuBlocks = [\n    // 'whalesbot_eagle_1001_openning_3d_simulator',\n    'whalesbot_eagle_1001_entering_pitch_mode',\n    'whalesbot_eagle_1001_exit_pitch_mode',\n    'whalesbot_eagle_1001_automatic_take_off_height',\n    'whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset',\n    'whalesbot_eagle_1001_automatic_landing',\n    'whalesbot_eagle_1001_automatic_descent_speed_offset',\n    'whalesbot_eagle_1001_set_the_flight_speed',\n    'whalesbot_eagle_1001_get_setting_speed',\n    'whalesbot_eagle_1001_rise',\n    'whalesbot_eagle_1001_down',\n    'whalesbot_eagle_1001_fly_forward',\n    'whalesbot_eagle_1001_fly_backward',\n    'whalesbot_eagle_1001_fly_left',\n    'whalesbot_eagle_1001_fly_right',\n    'whalesbot_eagle_1001_turn_left',\n    'whalesbot_eagle_1001_turn_right',\n    'whalesbot_eagle_1001_fly_in_the_specified_direction',\n    'whalesbot_eagle_1001_flight_designated',\n    'whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control',\n    'whalesbot_eagle_1001_stop_moving_and_hover',\n    'whalesbot_eagle_1001_hover_at_specified_altitude',\n    'whalesbot_eagle_1001_emergency_stop',\n    'whalesbot_eagle_1001_set_the_steering_gear',\n    'whalesbot_eagle_1001_execute_script',\n    'whalesbot_eagle_1001_clean',\n    'whalesbot_eagle_1001_restart',\n    'whalesbot_eagle_1001_get_status',\n    // light & speaker blocks\n    'whalesbot_eagle_1001_ls_debug_value',\n    'whalesbot_eagle_1001_ls_display_symbol',\n    'whalesbot_eagle_1001_ls_off_LED',\n    'whalesbot_eagle_1001_ls_display_digital_tube',\n    'whalesbot_eagle_1001_ls_display_digital_tube_score',\n    'whalesbot_eagle_1001_ls_off_digital_tube',\n    'whalesbot_eagle_1001_ls_set_RGB',\n    'whalesbot_eagle_1001_ls_fly_RGB',\n    // 'whalesbot_eagle_1001_ls_set_DO',\n    // 'whalesbot_eagle_1001_ls_execute_script',\n    // sensors\n    'whalesbot_eagle_1001_ss_fly_state_POS_Z',\n    'whalesbot_eagle_1001_ss_fly_state_LASER',\n    'whalesbot_eagle_1001_ss_battery_voltage',\n    'whalesbot_eagle_1001_ss_fly_state_STATE_TEMP',\n    'whalesbot_eagle_1001_ss_attitude_angle',\n    'whalesbot_eagle_1001_ss_flight_angular_velocity',\n    'whalesbot_eagle_1001_ss_flight_acceleration',\n    'whalesbot_eagle_1001_ss_optical_flow',\n    'whalesbot_eagle_1001_ss_get_infrared_distance',\n    'whalesbot_eagle_1001_ss_obstacle_infrared_detected_bool',\n    // 'whalesbot_eagle_1001_ss_obstacle_infrared_detected_string',\n    // 'whalesbot_eagle_1001_ss_human_infrared_value_bool',\n    // 'whalesbot_eagle_1001_ss_human_infrared_value_string',\n    'whalesbot_eagle_1001_ss_AI',\n    // 'whalesbot_eagle_1001_ss_get_ultrasonic_distance',\n    'whalesbot_eagle_1001_ss_get_ambient_light',\n    // 'whalesbot_eagle_1001_ss_get_temperature',\n    // 'whalesbot_eagle_1001_ss_get_humidity',\n    // 'whalesbot_eagle_1001_ss_get_flame',\n    // 'whalesbot_eagle_1001_ss_get_gesture',\n    // 'whalesbot_eagle_1001_ss_get_tof',\n    // 'whalesbot_eagle_1001_ss_fly_setpoint_LASER_ENABLE',\n    // 'whalesbot_eagle_1001_ss_get_bt_remote_control',\n    // 'whalesbot_eagle_1001_ss_seconds',\n    // 'whalesbot_eagle_1001_ss_resettime',\n];\n\n// 블록 생성\nEntry.WhalesbotEagle1001.getBlocks = function () {\n    const blockColors = {\n        color: {\n            light_speaker: '#5b90ff',\n            sensor: '#8066f9'\n        },\n        outerLine: {\n            light_speaker: '#2b6eff',\n            sensor: '#8a6bf0'\n        },\n    }\n\n    const notificationType = {\n        \"SUCCESS\": \"success\",\n        \"UNSUPPORTED\": \"unsupported\",\n        \"ALERT\": \"alert\",\n    }\n\n    let _this = this;\n    let sourceCode;\n\n    const defaultSpeed = \"10\";\n    const defaultAltitude = \"50\";\n    const defaultOffset = \"0\";\n\n    const wbOperators = {\n        \"EQUAL\": \"==\",\n        \"NOT_EQUAL\": \"!=\",\n        \"GREATER\": \">\",\n        \"GREATER_OR_EQUAL\": \">=\",\n        \"LESS\": \"<\",\n        \"LESS_OR_EQUAL\": \"<=\",\n        \"AND\": \"&&\",\n        \"OR\": \"||\",\n    };\n\n    const wbVariables = {\n        'whalesbot_eagle_1001_get_setting_speed': 'fly_state(SETSPEED)',\n        'whalesbot_eagle_1001_ss_fly_state_POS_Z': 'fly_state(POS_Z)',\n        'whalesbot_eagle_1001_ss_fly_state_LASER': 'fly_state(LASER)',\n        'whalesbot_eagle_1001_ss_battery_voltage': 'battery()',\n        'whalesbot_eagle_1001_ss_fly_state_STATE_TEMP': 'fly_state(STATE_TEMP)',\n        'whalesbot_eagle_1001_ss_attitude_angle': 'fly_state($VALUE)',\n        'whalesbot_eagle_1001_ss_flight_angular_velocity': 'fly_state($VALUE)',\n        'whalesbot_eagle_1001_ss_flight_acceleration': 'fly_state($VALUE)',\n        'whalesbot_eagle_1001_ss_optical_flow': 'fly_state($VALUE)',\n        'whalesbot_eagle_1001_ss_get_infrared_distance': 'get_infrared_distance($VALUE)',\n        'whalesbot_eagle_1001_ss_obstacle_infrared_detected_string': 'obstacle_infrared_detected($VALUE)',\n        'whalesbot_eagle_1001_ss_obstacle_infrared_detected_bool': 'obstacle_infrared_detected($VALUE)',\n        'whalesbot_eagle_1001_ss_human_infrared_value_string': 'human_infrared_value($VALUE)',\n        'whalesbot_eagle_1001_ss_human_infrared_value_bool': 'human_infrared_value($VALUE)',\n        'whalesbot_eagle_1001_ss_AI': 'AI($VALUE)',\n        'whalesbot_eagle_1001_ss_get_ultrasonic_distance': 'get_ultrasonic_distance($VALUE)',\n        'whalesbot_eagle_1001_ss_get_ambient_light': 'get_ambient_light($VALUE)',\n        'whalesbot_eagle_1001_ss_get_temperature': 'get_temperature($VALUE)',\n        'whalesbot_eagle_1001_ss_get_humidity': 'get_humidity($VALUE)',\n        'whalesbot_eagle_1001_ss_get_flame': 'get_flame($VALUE)',\n        'whalesbot_eagle_1001_ss_get_gesture': 'get_gesture($VALUE)',\n        'whalesbot_eagle_1001_ss_get_tof': 'get_tof($VALUE)',\n        'whalesbot_eagle_1001_ss_get_bt_remote_control': 'get_bt_remote_control($VALUE)',\n        'whalesbot_eagle_1001_ss_seconds': 'seconds()',\n    }\n\n    const startBlocks = [\n        \"when_run_button_click\",\n        \"when_some_key_pressed\",\n        \"mouse_clicked\",\n        \"mouse_click_cancled\",\n        \"when_object_click\",\n        \"when_object_click_canceled\",\n        'whalesbot_eagle_1001_execute_script',\n        'whalesbot_eagle_1001_ls_debug_value',\n        'whalesbot_eagle_1001_ls_display_symbol',\n        'whalesbot_eagle_1001_ls_off_LED',\n        'whalesbot_eagle_1001_ls_display_digital_tube',\n        'whalesbot_eagle_1001_ls_display_digital_tube_score',\n        'whalesbot_eagle_1001_ls_off_digital_tube',\n        'whalesbot_eagle_1001_ls_set_RGB',\n        'whalesbot_eagle_1001_ls_fly_RGB',\n        'whalesbot_eagle_1001_ls_set_DO',\n        'whalesbot_eagle_1001_ls_execute_script',\n    ]\n\n    let globlalCVariables = {}\n\n    function _getParameter(parameter) {\n        let param = parameter.params[0] != \"\" ? parameter.params[0] : \"0\"\n        if (parameter.type != \"text\" && parameter.type != \"number\" && parameter.type != \"get_variable\") {\n            let raw_param = wbVariables[parameter.type]\n            param = raw_param.includes(\"$VALUE\") ? raw_param.replace(\"$VALUE\", parameter.params[0]) : raw_param;\n        } else if (parameter.type == \"get_variable\") {\n            param = globlalCVariables[parameter.params[0]]\n        }\n        return param\n    }\n\n    function _generateConditions(params) {\n        let left = _getParameter(params[0])\n        let operator = params[1] != undefined ? wbOperators[params[1]] : \"0\"\n        let right = _getParameter(params[2])\n        return { left, operator, right }\n    }\n\n    function generateCCode(block) {\n        switch (block.type) {\n            // LOOP\n            case 'repeat_basic':\n                let times = _getParameter(block.params[0]);\n                return `\\tfor(int i=0; i<${times}; ++i) {\\n${block.statements[0].map((generateCCode)).join('')}\\t}\\n`;\n\n            case 'repeat_inf':\n                return `\\twhile(1) {\\n${block.statements[0].map(generateCCode).join('')}\\t}\\n`;\n\n            case 'repeat_while_true':\n                let rpWhileDecision = {\n                    \"type\": block.params[0].type,\n                    \"params\": block.params[0].params,\n                };\n                let rpWhileMark = block.params[1] == 'until' ? '!' : '';\n                return `\\twhile(${rpWhileMark}(${generateCCode(rpWhileDecision)})) {\\n${block.statements[0].map(generateCCode).join('')}\\t}\\n`;\n\n            case 'wait_second':\n                let second = _getParameter(block.params[0]);\n                return `\\twait(${second});\\n`;\n\n            case 'wait_until_true':\n                let waitUntilTrueDecision = {\n                    \"type\": block.params[0].type,\n                    \"params\": block.params[0].params,\n                };\n                return `\\twhile(!(${generateCCode(waitUntilTrueDecision)})) {\\n\\t}\\n`;\n\n            case 'stop_repeat':\n                return `\\tbreak;\\n`;\n\n            // CONDITION\n            case '_if':\n                let ifDecision = {\n                    \"type\": block.params[0].type,\n                    \"params\": block.params[0].params,\n                };\n                return `\\tif(${generateCCode(ifDecision)}) {\\n${block.statements[0].map(generateCCode).join('')}\\t}\\n`;\n\n            case 'if_else':\n                let ifElseDecision = {\n                    \"type\": block.params[0].type,\n                    \"params\": block.params[0].params,\n                };\n                return `\\tif(${generateCCode(ifElseDecision)}) {\\n${block.statements[0].map(generateCCode).join('')}\\t} else {\\n${block.statements[1].map(generateCCode).join('')}\\t}\\n`;\n\n            // DECISION\n            case 'boolean_and_or':\n                let boolAndOrBasicLeftValue = generateCCode(block.params[0]);\n                let boolAndOrBasicOperator = wbOperators[block.params[1]];\n                let boolAndOrBasicRightValue = generateCCode(block.params[2]);\n                return `(${boolAndOrBasicLeftValue} ${boolAndOrBasicOperator} ${boolAndOrBasicRightValue})`;\n\n            case 'boolean_not':\n                let boolNotDecision = generateCCode(block.params[1]);\n                return `!(${boolNotDecision})`;\n\n            case 'boolean_basic_operator':\n                let boolBasicCondition = \"0\"\n                if (block.params[0].params[0] != null) {\n                    let boolBasicLeftValue = _generateConditions(block.params).left;\n                    let boolBasicOperator = _generateConditions(block.params).operator;\n                    let boolBasicRightValue = _generateConditions(block.params).right;\n                    boolBasicCondition = `(${boolBasicLeftValue} ${boolBasicOperator} ${boolBasicRightValue})`;\n                }\n                return `${boolBasicCondition}`;\n\n            // VARIABLE\n            case 'True':\n                return \"1\";\n\n            case 'False':\n                return \"0\";\n\n            case 'set_variable':\n                let variableName = globlalCVariables[block.params[0]];\n                let variableValue = _getParameter(block.params[1]);\n                return `\\t${variableName} = ${variableValue};\\n`;\n\n            case 'change_variable':\n                let changedVariableName = globlalCVariables[block.params[0]];\n                let changedVariableValue = _getParameter(block.params[1]);\n                return `\\t${changedVariableName} += ${changedVariableValue};\\n`;\n\n            // HARDWARE\n            case 'whalesbot_eagle_1001_entering_pitch_mode':\n                return '\\tfly_unlock();\\n';\n\n            case 'whalesbot_eagle_1001_exit_pitch_mode':\n                return '\\tfly_lock();\\n';\n\n            case 'whalesbot_eagle_1001_automatic_take_off_height':\n                let takeOffHeight = _getParameter(block.params[0]);\n                return `\\tfly_start(${takeOffHeight});\\n`;\n\n            case 'whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset':\n                let takeOffAltitude = _getParameter(block.params[0]) != \"\" ? _getParameter(block.params[0]) : defaultAltitude;\n                let takeOffSpeed = _getParameter(block.params[1]) != \"\" ? _getParameter(block.params[1]) : defaultSpeed;\n                let takeOffXoffset = (-10.00 <= _getParameter(block.params[2]) || _getParameter(block.params[2]) <= 10.00) ? _getParameter(block.params[2]) : defaultOffset;\n                let takeOffYoffset = (-10.00 <= _getParameter(block.params[3]) || _getParameter(block.params[3]) <= 10.00) ? _getParameter(block.params[3]) : defaultOffset;\n                return `\\tfly_start_2(${takeOffAltitude},${takeOffSpeed},${takeOffXoffset},${takeOffYoffset});\\n`\n\n            case 'whalesbot_eagle_1001_automatic_landing':\n                return `\\tfly_land();\\n`;\n\n            case 'whalesbot_eagle_1001_automatic_descent_speed_offset':\n                let automaticSpeed = _getParameter(block.params[0]) != \"\" ? _getParameter(block.params[0]) : defaultSpeed;\n                let automaticXoffset = (-10.00 <= _getParameter(block.params[1]) || _getParameter(block.params[1]) <= 10.00) ? _getParameter(block.params[1]) : defaultOffset;\n                let automaticYoffset = (-10.00 <= _getParameter(block.params[2]) || _getParameter(block.params[2]) <= 10.00) ? _getParameter(block.params[2]) : defaultOffset;\n                return `\\tfly_land_2(${automaticSpeed},${automaticXoffset},${automaticYoffset});\\n`\n\n            case 'whalesbot_eagle_1001_set_the_flight_speed':\n                let speed = _getParameter(block.params[0]);\n                return `\\tfly_setspeed(${speed});\\n`;\n\n            case 'whalesbot_eagle_1001_rise':\n                let up = _getParameter(block.params[0]);\n                return `\\tfly_moveto(UP,${up});\\n`;\n\n            case 'whalesbot_eagle_1001_down':\n                let down = _getParameter(block.params[0]);\n                return `\\tfly_moveto(DOWN,${down});\\n`;\n\n            case 'whalesbot_eagle_1001_fly_forward':\n                let front = _getParameter(block.params[0]);\n                return `\\tfly_moveto(FRONT,${front});\\n`;\n\n            case 'whalesbot_eagle_1001_fly_backward':\n                let back = _getParameter(block.params[0]);\n                return `\\tfly_moveto(BACK,${back});\\n`;\n\n            case 'whalesbot_eagle_1001_fly_left':\n                let left = _getParameter(block.params[0]);\n                return `\\tfly_moveto(LEFT,${left});\\n`;\n\n            case 'whalesbot_eagle_1001_fly_right':\n                let right = _getParameter(block.params[0]);\n                return `\\tfly_moveto(RIGHT,${right});\\n`;\n\n            case 'whalesbot_eagle_1001_turn_left':\n                let turnLeft = _getParameter(block.params[0]);\n                if (0 > turnLeft || turnLeft > 360) {\n                    turnLeft = 360\n                }\n                return `\\tfly_turn(CCW,${turnLeft});\\n`;\n\n            case 'whalesbot_eagle_1001_turn_right':\n                let turnRight = _getParameter(block.params[0]);\n                if (0 > turnRight || turnRight > 360) {\n                    turnRight = 360\n                }\n                return `\\tfly_turn(CW,${turnRight});\\n`;\n\n            case 'whalesbot_eagle_1001_fly_in_the_specified_direction':\n                let dirSpeed = _getParameter(block.params[0]);\n                let dirDirection = _getParameter(block.params[1]);\n                if (0 > dirDirection || dirDirection > 360) {\n                    dirDirection = 360\n                }\n                return `\\tfly_dir(${dirSpeed},${dirDirection});\\n`;\n\n            case 'whalesbot_eagle_1001_flight_designated':\n                let disX = _getParameter(block.params[0]);\n                let disY = _getParameter(block.params[1]);\n                let disZ = _getParameter(block.params[2]);\n                let disSpeed = _getParameter(block.params[3]);\n                return `\\tfly_move_dis(${disX},${disY},${disZ},${disSpeed});\\n`;\n\n            case 'whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control':\n                let pitch = _getParameter(block.params[0]);\n                let roll = _getParameter(block.params[1]);\n                let throttle = _getParameter(block.params[2]);\n                let yaw = _getParameter(block.params[3]);\n                return `\\tfly_move(${pitch},${roll},${throttle},${yaw});\\n`;\n\n            case 'whalesbot_eagle_1001_stop_moving_and_hover':\n                return `\\tfly_hover();\\n`;\n\n            case 'whalesbot_eagle_1001_hover_at_specified_altitude':\n                let hoverSpecifiedAltitude = (_getParameter(block.params[0]) == \"\" || _getParameter(block.params[0]) < 20) ? \"20\" : _getParameter(block.params[0]);\n                hoverSpecifiedAltitude = (_getParameter(block.params[0]) > 200) ? \"200\" : _getParameter(block.params[0]);\n                return `\\tfly_hover_laser(${hoverSpecifiedAltitude});\\n`;\n\n            case 'whalesbot_eagle_1001_emergency_stop':\n                return `\\tfly_lock();\\n`;\n\n            case 'whalesbot_eagle_1001_set_the_steering_gear':\n                let servoSpeed = _getParameter(block.params[1]);\n                let servoAngle = _getParameter(block.params[2]);\n                if (0 > servoAngle || servoAngle > 360) {\n                    servoAngle = 360\n                }\n                return `\\tSetServo(P2,${servoSpeed},${servoAngle});\\n`;\n\n            // light & speaker blocks\n            case 'whalesbot_eagle_1001_ls_debug_value':\n                let lsDebugValue1 = _getParameter(block.params[0]);\n                let lsDebugValue2 = _getParameter(block.params[1]);\n                return `\\tDebugValue(${lsDebugValue1}, ${lsDebugValue2});\\n`;\n\n            case 'whalesbot_eagle_1001_ls_display_symbol':\n                let lsDisplaySymbol = block.params[0];\n                let lsDisplaySymbolPort = block.params[1];\n                return `\\tdisplay_symbol(${lsDisplaySymbolPort}, ${lsDisplaySymbol});\\n`;\n\n            case 'whalesbot_eagle_1001_ls_off_LED':\n                let lsOffLedPort = block.params[0];\n                return `\\toff_LED(${lsOffLedPort});\\n`;\n\n            case 'whalesbot_eagle_1001_ls_display_digital_tube':\n                let lsDisplayDigitalTubePort = block.params[0];\n                let lsDisplayDigitalTubeValue = _getParameter(block.params[1]);\n                return `\\tdisplay_digital_tube(${lsDisplayDigitalTubePort}, ${lsDisplayDigitalTubeValue});\\n`;\n\n            case 'whalesbot_eagle_1001_ls_display_digital_tube_score':\n                let lsDisplayDigitalTubeScorePort = block.params[0];\n                let lsDisplayDigitalTubeScoreValue1 = _getParameter(block.params[1]);\n                let lsDisplayDigitalTubeScoreValue2 = _getParameter(block.params[2]);\n                return `\\tdisplay_digital_tube_score(${lsDisplayDigitalTubeScorePort}, ${lsDisplayDigitalTubeScoreValue1}, ${lsDisplayDigitalTubeScoreValue2});\\n`;\n\n            case 'whalesbot_eagle_1001_ls_off_digital_tube':\n                let lsOffDigitalTubePort = block.params[0];\n                return `\\toff_digital_tube(${lsOffDigitalTubePort});\\n`;\n\n            case 'whalesbot_eagle_1001_ls_set_RGB':\n                let lsSetRGBPort = block.params[0];\n                let lsSetRGBR = _getParameter(block.params[1]);\n                let lsSetRGBG = _getParameter(block.params[2]);\n                let lsSetRGBB = _getParameter(block.params[3]);\n                return `\\tset_RGB(${lsSetRGBPort}, ${lsSetRGBR}, ${lsSetRGBG}, ${lsSetRGBB});\\n`;\n\n            case 'whalesbot_eagle_1001_ls_fly_RGB':\n                let lsFlyRGB = block.params[0];\n                // let lsFlyRGBR = _getParameter(block.params[1]);\n                // let lsFlyRGBG = _getParameter(block.params[2]);\n                // let lsFlyRGBB = _getParameter(block.params[3]);\n                return `\\tfly_RGB(${lsFlyRGB});\\n`;\n\n            case 'whalesbot_eagle_1001_ls_set_DO':\n                let lsSetDOPort = block.params[0];\n                let lsSetDOValue = block.params[1];\n                return `\\tSetDO(${lsSetDOPort}, ${lsSetDOValue});\\n`;\n\n            // sensors\n            case 'whalesbot_eagle_1001_ss_fly_setpoint_LASER_ENABLE':\n                let ssFlySetpointToggle = block.params[0];\n                return `\\tfly_setpoint(LASER_ENABLE, ${ssFlySetpointToggle});\\n`;\n\n            case 'whalesbot_eagle_1001_ss_resettime':\n                return `\\tresettime();\\n`;\n\n            case 'whalesbot_eagle_1001_ss_obstacle_infrared_detected_bool':\n                let ssBbstacleInfraredDetectedBool = block.params[0];\n                return `obstacle_infrared_detected(${ssBbstacleInfraredDetectedBool})`;\n\n            default:\n                if (!startBlocks.includes(block.type)) {\n                    // console.log(\"unsupport block: \" + block.type);\n                    _this.unsupportBlockExist = true;\n                }\n                return '';\n        }\n    }\n\n    function setUpCVariables(variable) {\n        if (variable.visible) {\n            const varName = `var_${variable.name}`\n            globlalCVariables[variable.id] = varName\n            const varValue = variable.value;\n            return `float ${varName} = ${varValue};\\n`\n        }\n        return \"\"\n    }\n\n    function openedSimulatorPopup() {\n        if (_this.simulatorPopup == null) {\n            return false;\n        }\n        return !_this.simulatorPopup.closed;\n    }\n\n    function notify(type, msg) {\n        switch (type) {\n            case notificationType[\"SUCCESS\"]:\n                Entry.toast.success(\n                    Lang.Blocks.whalesbot_mc_102_toast_success_title,\n                    msg\n                );\n                break;\n            default:\n                Entry.toast.alert(\n                    Lang.Blocks.whalesbot_mc_102_toast_alert_title,\n                    msg\n                );\n        }\n    }\n\n    return {\n        whalesbot_eagle_1001_openning_3d_simulator: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_without_next',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_openning_3d_simulator',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                const width = window.innerWidth * 0.8;\n                const height = window.innerHeight * 0.8;\n                _this.simulatorPopup = window.open(\n                    metadata.simulator_url,\n                    'DroneSimulatorPopup',\n                    `width=${width},height=${height}`\n                );\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_openning_3d_simulator()'] },\n        },\n        whalesbot_eagle_1001_restart: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_without_next',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_restart',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                _this.sendCmd('restartCode');\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_restart()'] },\n        },\n        whalesbot_eagle_1001_clean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_without_next',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_clean',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                _this.sendCmd('stopCode');\n                Entry.toast.success(\n                    Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                    Lang.Blocks.whalesbot_eagle_1001_toast_clean_success\n                );\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_clean()'] },\n        },\n        whalesbot_eagle_1001_get_status: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_get_status',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                _this.sendCmd('get_status');\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_get_status()'] },\n        },\n        whalesbot_eagle_1001_entering_pitch_mode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_entering_pitch_mode',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_entering_pitch_mode\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_entering_pitch_mode()'] },\n        },\n        whalesbot_eagle_1001_exit_pitch_mode: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_without_next',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_exit_pitch_mode',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                const project = _this.exportProject();\n                const listVariables = project.variables;\n                const rawScript = project.objects[0].script;\n                const allScript = JSON.parse(rawScript);\n                const droneScript = allScript.filter((arr) => arr.length > 2);\n\n                let sourceCode = `#include \"whalesbot.h\"\\n${listVariables.map(setUpCVariables).join('')}\\nvoid user_main() {\\n`;\n                sourceCode += `${droneScript[0].map(generateCCode).join('')}}\\n\\nuser_main();`;\n\n                if (_this.unsupportBlockExist) {\n                    Entry.toast.alert(\n                        Lang.Blocks.whalesbot_eagle_1001_toast_unsupport_block_title,\n                        Lang.Blocks.whalesbot_eagle_1001_toast_unsupport_block_msg\n                    )\n                    _this.unsupportBlockExist = false;\n                    Entry.engine.toggleStop();\n                    return;\n                }\n\n                if (_this.invalidParamValue) {\n                    _this.invalidParamValue = false;\n                    return;\n                }\n\n                if (openedSimulatorPopup()) {\n                    Entry.toast.success(\n                        Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                        Lang.Blocks.whalesbot_eagle_1001_toast_download_success\n                    );\n                    return;\n                }\n\n                console.log(sourceCode);\n\n                _this.sendCmd(sourceCode);\n\n                Entry.toast.success(\n                    Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                    Lang.Blocks.whalesbot_eagle_1001_toast_prepare_download\n                );\n                setTimeout(() => {\n                    Entry.toast.success(\n                        Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                        Lang.Blocks.whalesbot_eagle_1001_toast_downloading_code\n                    );\n                    setTimeout(() => {\n                        Entry.toast.success(\n                            Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                            Lang.Blocks.whalesbot_eagle_1001_toast_download_success\n                        );\n                    }, 3000);\n                }, 4000);\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_exit_pitch_mode()'] },\n        },\n        whalesbot_eagle_1001_automatic_take_off_height: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_automatic_take_off_height',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_automatic_take_off_height\")\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_automatic_take_off_height();'] },\n        },\n        whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['100'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset',\n            },\n            paramsKeyMap: {\n                altitude: 0,\n                speed: 1,\n                x: 2,\n                y: 3,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset\")\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset();'] },\n        },\n        whalesbot_eagle_1001_automatic_landing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_automatic_landing',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_automatic_landing\")\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_automatic_landing()'] },\n        },\n        whalesbot_eagle_1001_automatic_descent_speed_offset: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_automatic_descent_speed_offset',\n            },\n            paramsKeyMap: {\n                speed: 0,\n                x: 1,\n                y: 2,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_automatic_descent_speed_offset\")\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_automatic_descent_speed_offset()'] },\n        },\n        whalesbot_eagle_1001_set_the_flight_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_set_the_flight_speed',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_set_the_flight_speed\")\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_set_the_flight_speed()'] },\n        },\n        whalesbot_eagle_1001_get_setting_speed: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_get_setting_speed',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_get_setting_speed\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_get_setting_speed()'] },\n        },\n        whalesbot_eagle_1001_rise: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_rise',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_rise\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_rise();'] },\n        },\n        whalesbot_eagle_1001_down: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_down',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_down\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_down();'] },\n        },\n        whalesbot_eagle_1001_fly_forward: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_fly_forward',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_fly_forward\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_forward();'] },\n        },\n        whalesbot_eagle_1001_fly_backward: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_fly_backward',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_fly_backward\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_backward();'] },\n        },\n        whalesbot_eagle_1001_fly_left: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_fly_left',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_fly_left\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_left();'] },\n        },\n        whalesbot_eagle_1001_fly_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_fly_right',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_fly_right\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_right();'] },\n        },\n        whalesbot_eagle_1001_turn_left: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_turn_left',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_turn_left\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_turn_left();'] },\n        },\n        whalesbot_eagle_1001_turn_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_turn_right',\n            },\n            paramsKeyMap: {\n                value: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_turn_right\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_turn_right();'] },\n        },\n        whalesbot_eagle_1001_fly_in_the_specified_direction: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['30'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['0'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_fly_in_the_specified_direction',\n            },\n            paramsKeyMap: {\n                speed: 0,\n                direction: 1,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_fly_in_the_specified_direction\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_in_the_specified_direction();'] },\n        },\n        whalesbot_eagle_1001_flight_designated: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['30'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_flight_designated',\n            },\n            paramsKeyMap: {\n                x: 0,\n                y: 1,\n                z: 2,\n                speed: 3,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_flight_designated\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_flight_designated();'] },\n        },\n        whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['50'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control',\n            },\n            paramsKeyMap: {\n                pitch: 0,\n                roll: 1,\n                throttle: 2,\n                yaw: 3,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control();'] },\n        },\n        whalesbot_eagle_1001_stop_moving_and_hover: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                params: [],\n                type: 'whalesbot_eagle_1001_stop_moving_and_hover',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_stop_moving_and_hover\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_stop_moving_and_hover();'] },\n        },\n        whalesbot_eagle_1001_hover_at_specified_altitude: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['20'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_hover_at_specified_altitude',\n            },\n            paramsKeyMap: {\n                altitude: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_hover_at_specified_altitude\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_hover_at_specified_altitude();'] },\n        },\n        whalesbot_eagle_1001_emergency_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_emergency_stop',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_emergency_stop\")\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_emergency_stop()'] },\n        },\n        whalesbot_eagle_1001_set_the_steering_gear: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P2', 'P2'],\n                    ],\n                    value: 'P2',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['40'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['90'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_set_the_steering_gear',\n            },\n            paramsKeyMap: {\n                port: 0,\n                speed: 1,\n                angle: 2,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                // console.log(\"whalesbot_eagle_1001_set_the_steering_gear\");\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_set_the_steering_gear();'] },\n        },\n        whalesbot_eagle_1001_execute_script: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_without_next',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_execute_script',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                if (openedSimulatorPopup()) {\n                    _this.simulatorPopup.postMessage({\n                        script: sourceCode\n                    }, '*');\n                    return;\n                }\n                _this.sendCmd('runCode');\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_execute_script()'] },\n        },\n\n        // light & speaker blocks\n        whalesbot_eagle_1001_ls_debug_value: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'number',\n                        params: ['1'],\n                    },\n                    {\n                        type: 'number',\n                        params: [''],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_ls_debug_value',\n            },\n            paramsKeyMap: {\n                VALUE1: 0,\n                VALUE2: 1,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var value1 = Number(script.values[0]);\n                var value2 = Number(script.values[1]);\n                if (value1 < 1 || value1 > 6) {\n                    notify(notificationType.ALERT, 'Debugging: Data [1 ~ 6] and [0 ~ 999999]')\n                    _this.invalidParamValue = true;\n                    throw new Error();\n                }\n                if (value2 < 0 || value2 > 999999) {\n                    notify(notificationType.ALERT, 'Debugging: Data [1 ~ 6] and [0 ~ 999999]')\n                    _this.invalidParamValue = true;\n                    throw new Error();\n                }\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_debug_value()'] },\n        },\n\n        whalesbot_eagle_1001_ls_display_symbol: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['?', 'LED_symbol_question_mark'], ['!', 'LED_symbol_exclamation'], ['$', 'LED_symbol_dollar'], ['¥', 'LED_symbol_RMB'],\n                        ['=', 'LED_symbol_equal'], ['+', 'LED_symbol_plus'], ['-', 'LED_symbol_minus'], ['x', 'LED_symbol_multiplied'],\n                        ['÷', 'LED_symbol_divided'], ['0', 'LED_symbol_0'], ['1', 'LED_symbol_1'], ['2', 'LED_symbol_2'],\n                        ['3', 'LED_symbol_3'], ['4', 'LED_symbol_4'], ['5', 'LED_symbol_5'], ['6', 'LED_symbol_6'],\n                        ['7', 'LED_symbol_7'], ['8', 'LED_symbol_8'], ['9', 'LED_symbol_9'], ['A', 'LED_symbol_A'],\n                        ['B', 'LED_symbol_B'], ['C', 'LED_symbol_C'], ['D', 'LED_symbol_D'], ['E', 'LED_symbol_E'],\n                        ['F', 'LED_symbol_F'], ['G', 'LED_symbol_G'], ['H', 'LED_symbol_H'], ['I', 'LED_symbol_I'],\n                        ['J', 'LED_symbol_J'], ['K', 'LED_symbol_K'], ['L', 'LED_symbol_L'], ['M', 'LED_symbol_M'],\n                        ['N', 'LED_symbol_N'], ['O', 'LED_symbol_O'], ['P', 'LED_symbol_P'], ['Q', 'LED_symbol_Q'],\n                        ['R', 'LED_symbol_R'], ['S', 'LED_symbol_S'], ['T', 'LED_symbol_T'], ['U', 'LED_symbol_U'],\n                        ['V', 'LED_symbol_V'], ['W', 'LED_symbol_W'], ['X', 'LED_symbol_X'], ['Y', 'LED_symbol_Y'],\n                        ['Z', 'LED_symbol_Z'], ['❤︎', 'LED_symbol_big_heart'], ['♥︎', 'LED_symbol_little_heart'], ['↑', 'LED_symbol_forward'],\n                        ['↓', 'LED_symbol_backward'], ['←', 'LED_symbol_turnleft'], ['→', 'LED_symbol_turnright'], ['GO', 'LED_symbol_GO'],\n                        ['⊘', 'LED_symbol_stop'],\n                    ],\n                    value: 'LED_symbol_question_mark',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ls_display_symbol',\n            },\n            paramsKeyMap: {\n                SYMBOLS: 0,\n                PORT: 1,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_display_symbol()'] },\n        },\n\n        whalesbot_eagle_1001_ls_off_LED: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ls_off_LED',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_off_LED()'] },\n        },\n\n        whalesbot_eagle_1001_ls_display_digital_tube: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: [''],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_ls_display_digital_tube',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUMBER: 1,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var number = Number(script.values[1]);\n                if (number < 0 || number > 9999) {\n                    notify(notificationType.ALERT, '0 ~ 9999')\n                    _this.invalidParamValue = true;\n                    throw new Error();\n                }\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_display_digital_tube()'] },\n        },\n\n        whalesbot_eagle_1001_ls_display_digital_tube_score: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: [''],\n                    },\n                    {\n                        type: 'number',\n                        params: [''],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_ls_display_digital_tube_score',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                NUMBER1: 1,\n                NUMBER2: 2,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var number1 = Number(script.values[1]);\n                var number2 = Number(script.values[2]);\n                if (number1 < 0 || number1 > 9999 || number2 < 0 || number2 > 9999) {\n                    notify(notificationType.ALERT, '0 ~ 9999')\n                    _this.invalidParamValue = true;\n                    throw new Error();\n                }\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_display_digital_tube_score()'] },\n        },\n\n        whalesbot_eagle_1001_ls_off_digital_tube: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ls_off_digital_tube',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_off_digital_tube()'] },\n        },\n\n        whalesbot_eagle_1001_ls_set_RGB: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'number',\n                        params: ['255'],\n                    },\n                ],\n                type: 'whalesbot_eagle_1001_ls_set_RGB',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var red = Number(script.values[1]);\n                var green = Number(script.values[2]);\n                var blue = Number(script.values[3]);\n                if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {\n                    notify(notificationType.ALERT, '0 ~ 255')\n                    _this.invalidParamValue = true;\n                    throw new Error();\n                }\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_set_RGB()'] },\n        },\n\n        whalesbot_eagle_1001_ls_fly_RGB: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['⚪', 'color_white'], ['🟡', 'color_yellow'],\n                        ['🟣', 'color_purple'], ['🟦', 'color_cyan'],\n                        ['🔴', 'color_red'], ['🟢', 'color_green'],\n                        ['🔵', 'color_blue'], ['⚫', 'color_black'],\n                    ],\n                    value: 'color_white',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ls_fly_RGB',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_fly_RGB()'] },\n        },\n\n        whalesbot_eagle_1001_ls_set_DO: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.light_speaker.electro_magnet.absorption, 'true'],\n                        [Lang.Blocks.light_speaker.electro_magnet.break_off, 'false']\n                    ],\n                    value: 'true',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ls_set_DO',\n            },\n            paramsKeyMap: {\n                PORT: 0,\n                ELECTROMAGNET: 1,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_set_DO()'] },\n        },\n\n        whalesbot_eagle_1001_ls_execute_script: {\n            color: blockColors.color.light_speaker,\n            outerLine: blockColors.outerLine.light_speaker,\n            fontColor: '#fff',\n            skeleton: 'basic_without_next',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                    defaultType: 'number',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/moving_icon.svg',\n                    size: 11,\n                },\n            ],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_ls_execute_script',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'whalesbot_eagle_1001_ls',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                const project = _this.exportProject();\n                const listVariables = project.variables;\n                const rawScript = project.objects[0].script;\n                const allScript = JSON.parse(rawScript);\n                const droneScript = allScript.filter((arr) => arr.length > 2);\n\n                let sourceCode = `#include \"whalesbot.h\"\\n${listVariables.map(setUpCVariables).join('')}\\nvoid user_main() {\\n`;\n                sourceCode += `${droneScript[0].map(generateCCode).join('')}}\\n\\nuser_main();`;\n\n                if (_this.unsupportBlockExist) {\n                    Entry.toast.alert(\n                        Lang.Blocks.whalesbot_eagle_1001_toast_unsupport_block_title,\n                        Lang.Blocks.whalesbot_eagle_1001_toast_unsupport_block_msg\n                    )\n                    _this.unsupportBlockExist = false;\n                    Entry.engine.toggleStop();\n                    return;\n                }\n\n                if (_this.invalidParamValue) {\n                    _this.invalidParamValue = false;\n                    return;\n                }\n\n                if (openedSimulatorPopup()) {\n                    Entry.toast.success(\n                        Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                        Lang.Blocks.whalesbot_eagle_1001_toast_download_success\n                    );\n                    return;\n                }\n\n                console.log(sourceCode);\n\n                _this.sendCmd(sourceCode);\n\n                Entry.toast.success(\n                    Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                    Lang.Blocks.whalesbot_eagle_1001_toast_prepare_download\n                );\n                setTimeout(() => {\n                    Entry.toast.success(\n                        Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                        Lang.Blocks.whalesbot_eagle_1001_toast_downloading_code\n                    );\n                    setTimeout(() => {\n                        Entry.toast.success(\n                            Lang.Blocks.whalesbot_eagle_1001_toast_status_title,\n                            Lang.Blocks.whalesbot_eagle_1001_toast_download_success\n                        );\n                    }, 3000);\n                }, 4000);\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ls_execute_script()'] },\n        },\n\n        // sensors\n        whalesbot_eagle_1001_ss_fly_state_POS_Z: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_ss_fly_state_POS_Z',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var posZ = Entry.hw.portData.state_position_z || '0';\n                return posZ;\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_fly_state_POS_Z()'] },\n        },\n\n        whalesbot_eagle_1001_ss_fly_state_LASER: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_ss_fly_state_LASER',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var Laser = Entry.hw.portData.LaserTof || '0';\n                return Laser;\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_fly_state_LASER()'] },\n        },\n\n        whalesbot_eagle_1001_ss_battery_voltage: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_ss_battery_voltage',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var Battery = Entry.hw.portData.Battery || '0';\n                return Battery;\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_battery_voltage()'] },\n        },\n\n        whalesbot_eagle_1001_ss_fly_state_STATE_TEMP: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_ss_fly_state_STATE_TEMP',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var state = Entry.hw.portData.SPL06_temp || '0';\n                return state;\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_fly_state_STATE_TEMP()'] },\n        },\n\n        whalesbot_eagle_1001_ss_attitude_angle: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.sensor.attitude_angle.pitch, 'STATE_PITCH'],\n                        [Lang.Blocks.sensor.attitude_angle.roll, 'STATE_ROLL'],\n                        [Lang.Blocks.sensor.attitude_angle.yaw, 'STATE_YAW'],\n                    ],\n                    value: 'STATE_PITCH',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_attitude_angle',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var state = script.values[0];\n                if (state === 'STATE_PITCH') {\n                    return Entry.hw.portData.Pitch || '0';\n                } else if (state === 'STATE_ROLL') {\n                    return Entry.hw.portData.Roll || '0';\n                } else if (state === 'STATE_YAW') {\n                    return Entry.hw.portData.Yaw || '0';\n                }\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_attitude_angle()'] },\n        },\n\n        whalesbot_eagle_1001_ss_flight_angular_velocity: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X', 'GYPO_X'], ['Y', 'GYPO_Y'], ['Z', 'GYPO_Z'],\n                    ],\n                    value: 'GYPO_X',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_flight_angular_velocity',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var state = script.values[0];\n                if (state === 'GYPO_X') {\n                    return Entry.hw.portData.Gypo_x || '0';\n                } else if (state === 'GYPO_Y') {\n                    return Entry.hw.portData.Gypo_y || '0';\n                } else if (state === 'GYPO_Z') {\n                    return Entry.hw.portData.Gypo_z || '0';\n                }\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_flight_angular_velocity()'] },\n        },\n\n        whalesbot_eagle_1001_ss_flight_acceleration: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X', 'ACC_X'], ['Y', 'ACC_Y'], ['Z', 'ACC_Z'],\n                    ],\n                    value: 'ACC_X',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_flight_acceleration',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n                var state = script.values[0];\n                if (state === 'ACC_X') {\n                    return Entry.hw.portData.ACC_x || '0';\n                } else if (state === 'ACC_Y') {\n                    return Entry.hw.portData.ACC_y || '0';\n                } else if (state === 'ACC_Z') {\n                    return Entry.hw.portData.ACC_z || '0';\n                }\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_flight_acceleration()'] },\n        },\n\n        whalesbot_eagle_1001_ss_optical_flow: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['X', 'OPX'], ['Y', 'OPY']\n                    ],\n                    value: 'OPX',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_optical_flow',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_optical_flow()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_infrared_distance: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_infrared_distance',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_infrared_distance()'] },\n        },\n\n        whalesbot_eagle_1001_ss_obstacle_infrared_detected_string: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_obstacle_infrared_detected_string',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_obstacle_infrared_detected_string()'] },\n        },\n\n        whalesbot_eagle_1001_ss_obstacle_infrared_detected_bool: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_obstacle_infrared_detected_bool',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_obstacle_infrared_detected_bool()'] },\n        },\n\n        whalesbot_eagle_1001_ss_human_infrared_value_string: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_human_infrared_value_string',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_human_infrared_value_string()'] },\n        },\n\n        whalesbot_eagle_1001_ss_human_infrared_value_bool: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_human_infrared_value_bool',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_human_infrared_value_bool()'] },\n        },\n\n        whalesbot_eagle_1001_ss_AI: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_AI',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_AI()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_ultrasonic_distance: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_ultrasonic_distance',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_ultrasonic_distance()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_ambient_light: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_ambient_light',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_ambient_light()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_temperature: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_temperature',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_temperature()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_humidity: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_humidity',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_humidity()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_flame: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_flame',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_flame()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_gesture: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_gesture',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_gesture()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_tof: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['P1', 'P1'], ['P2', 'P2']\n                    ],\n                    value: 'P1',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_tof',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_tof()'] },\n        },\n\n        whalesbot_eagle_1001_ss_fly_setpoint_LASER_ENABLE: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.sensor.laser_height_determination.on, 'true'],\n                        [Lang.Blocks.sensor.laser_height_determination.off, 'false']\n                    ],\n                    value: 'true',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_fly_setpoint_LASER_ENABLE',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_fly_setpoint_LASER_ENABLE()'] },\n        },\n\n        whalesbot_eagle_1001_ss_get_bt_remote_control: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.sensor.remote_control_button.key, 'BTKEY'],\n                        [Lang.Blocks.sensor.remote_control_button.left_rocker_x, 'BTSTICK2'],\n                        [Lang.Blocks.sensor.remote_control_button.left_rocker_y, 'BTSTICK1'],\n                        [Lang.Blocks.sensor.remote_control_button.right_rocker_x, 'BTSTICK4'],\n                        [Lang.Blocks.sensor.remote_control_button.right_rocker_y, 'BTSTICK3'],\n                    ],\n                    value: 'BTKEY',\n                    fontSize: 10,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                ],\n                type: 'whalesbot_eagle_1001_ss_get_bt_remote_control',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_get_bt_remote_control()'] },\n        },\n\n        whalesbot_eagle_1001_ss_seconds: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_ss_seconds',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_seconds()'] },\n        },\n\n        whalesbot_eagle_1001_ss_resettime: {\n            color: blockColors.color.sensor,\n            outerLine: blockColors.outerLine.sensor,\n            fontColor: '#fff',\n            skeleton: 'basic',\n            statements: [],\n            params: [],\n            events: {},\n            def: {\n                type: 'whalesbot_eagle_1001_ss_resettime',\n            },\n            paramsKeyMap: {},\n            class: 'whalesbot_eagle_1001_ss',\n            isNotFor: ['whalesbot_eagle_1001'],\n            func(sprite, script) {\n            },\n            syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_ss_resettime()'] },\n        },\n    };\n};\n\nmodule.exports = Entry.WhalesbotEagle1001;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_xbot.js",
    "content": "'use strict';\n\nEntry.Xbot = {\n    PORT_MAP: {\n        rightWheel: 0,\n        leftWheel: 0,\n        head: 90,\n        armR: 90,\n        armL: 90,\n        analogD5: 127, //D4\n        analogD6: 127, //D5\n        D4: 0,\n        D7: 0,\n        D12: 0,\n        D13: 0,\n        ledR: 0,\n        ledG: 0,\n        ledB: 0,\n        lcdNum: 0,\n        lcdTxt: '                ',\n        note: 262,\n        duration: 0,\n    },\n    setZero: function() {\n        var portMap = Entry.Xbot.PORT_MAP;\n        var sq = Entry.hw.sendQueue;\n        for (var port in portMap) {\n            sq[port] = portMap[port];\n        }\n        Entry.hw.update();\n        var Xbot = Entry.Xbot;\n        Xbot.removeAllTimeouts();\n    },\n    timeouts: [],\n    removeTimeout: function(id) {\n        clearTimeout(id);\n        var timeouts = this.timeouts;\n        var index = timeouts.indexOf(id);\n        if (index >= 0) {\n            timeouts.splice(index, 1);\n        }\n    },\n    removeAllTimeouts: function() {\n        var timeouts = this.timeouts;\n        for (var i in timeouts) {\n            clearTimeout(timeouts[i]);\n        }\n        this.timeouts = [];\n    },\n    id: '1.7',\n    name: 'xbot_epor_edge',\n    url: 'http://xbot.co.kr/',\n    imageName: 'xbot.png',\n    title: {\n        ko: '엑스봇(원터치 동글/USB)',\n        en: 'XBOT(OneTouch Dongle/USB)',\n    },\n};\n\nEntry.Xbot.setLanguage = function() {\n    return {\n        ko: {\n            template: {\n                xbot_digitalInput: '%1',\n                xbot_analogValue: '%1',\n                xbot_digitalOutput: '디지털 %1 핀, 출력 값 %2 %3',\n                xbot_analogOutput: '아날로그 %1 %2 %3',\n                xbot_servo: '서보 모터 %1 , 각도 %2 %3',\n                xbot_oneWheel: '바퀴(DC) 모터 %1 , 속도 %2 %3',\n                xbot_twoWheel: '바퀴(DC) 모터 오른쪽(2) 속도: %1 왼쪽(1) 속도: %2 %3',\n                xbot_rgb: 'RGB LED 켜기 R 값 %1 G 값 %2 B 값 %3 %4',\n                xbot_rgb_picker: 'RGB LED 색 %1 로 정하기 %2',\n                xbot_buzzer: '%1   %2 음을 %3 초 연주하기 %4',\n                xbot_lcd: 'LCD %1 번째 줄 ,  출력 값 %2 %3',\n            },\n            Blocks: {\n                XBOT_digital: '디지털',\n                XBOT_D2_digitalInput: 'D2 디지털 입력',\n                XBOT_D3_digitalInput: 'D3 디지털 입력',\n                XBOT_D11_digitalInput: 'D11 디지털 입력',\n                XBOT_analog: '아날로그',\n                XBOT_CDS: '광 센서 값',\n                XBOT_MIC: '마이크 센서 값',\n                XBOT_analog0: '아날로그 0번 핀 값',\n                XBOT_analog1: '아날로그 1번 핀 값',\n                XBOT_analog2: '아날로그 2번 핀 값',\n                XBOT_analog3: '아날로그 3번 핀 값',\n                XBOT_Value: '출력 값',\n                XBOT_pin_OutputValue: '핀, 출력 값',\n                XBOT_High: '높음',\n                XBOT_Low: '낮음',\n                XBOT_Servo: '서보 모터',\n                XBOT_Head: '머리(D8)',\n                XBOT_ArmR: '오른 팔(D9)',\n                XBOT_ArmL: '왼 팔(D10)',\n                XBOT_angle: ', 각도',\n                XBOT_DC: '바퀴(DC) 모터',\n                XBOT_rightWheel: '오른쪽',\n                XBOT_leftWheel: '왼쪽',\n                XBOT_bothWheel: '양쪽',\n                XBOT_speed: ', 속도',\n                XBOT_rightSpeed: '바퀴(DC) 모터 오른쪽(2) 속도:',\n                XBOT_leftSpeed: '왼쪽(1) 속도:',\n                XBOT_RGBLED_R: 'RGB LED 켜기 R 값',\n                XBOT_RGBLED_G: 'G 값',\n                XBOT_RGBLED_B: 'B 값',\n                XBOT_RGBLED_color: 'RGB LED 색',\n                XBOT_set: '로 정하기',\n                XBOT_c: '도',\n                XBOT_d: '레',\n                XBOT_e: '미',\n                XBOT_f: '파',\n                XBOT_g: '솔',\n                XBOT_a: '라',\n                XBOT_b: '시',\n                XBOT_melody_ms: '초 연주하기',\n                XBOT_Line: '번째 줄',\n                XBOT_outputValue: '출력 값',\n            },\n        },\n        en: {\n            template: {\n                xbot_digitalInput: '%1',\n                xbot_analogValue: '%1',\n                xbot_digitalOutput: 'Digital %1 PIN, Ouput Value %2 %3',\n                xbot_analogOutput: 'Analog %1 %2 %3',\n                xbot_servo: 'Servo Motor %1 , Angle %2 %3',\n                xbot_oneWheel: 'Wheel(DC) Motor %1 , Speed %2 %3',\n                xbot_twoWheel: 'Wheel(DC) Motor Right(2) Speed: %1 Left(1) Speed: %2 %3',\n                xbot_rgb: 'RGB LED Color from Red %1 Green %2 Blue %3 %4',\n                xbot_rgb_picker: 'RGB LED Color from %1   %2',\n                xbot_buzzer: 'play note %1   %2 for %3 sec of Melody Playing %4',\n                xbot_lcd: 'LCD %1 th Line ,  Text %2 %3',\n            },\n            Blocks: {\n                XBOT_digital: 'Digital',\n                XBOT_D2_digitalInput: 'D2 Digital Input',\n                XBOT_D3_digitalInput: 'D3 Digital Input',\n                XBOT_D11_digitalInput: 'D11 Digital Input',\n                XBOT_analog: 'Analog',\n                XBOT_CDS: 'Light Sensor Value',\n                XBOT_MIC: 'Mic Sensor Value',\n                XBOT_analog0: 'Analog PIN0 Value',\n                XBOT_analog1: 'Analog PIN1 Value',\n                XBOT_analog2: 'Analog PIN2 Value',\n                XBOT_analog3: 'Analog PIN3 Value',\n                XBOT_Value: 'Ouput Value',\n                XBOT_pin_OutputValue: 'PIN, Ouput Value',\n                XBOT_High: 'HI',\n                XBOT_Low: 'LO',\n                XBOT_Servo: 'Servo Motor',\n                XBOT_Head: 'Head(D8)',\n                XBOT_ArmR: 'Right Arm(D9)',\n                XBOT_ArmL: 'Left Arm(D10)',\n                XBOT_angle: ', Angle',\n                XBOT_DC: 'Wheel(DC) Motor',\n                XBOT_rightWheel: 'Right',\n                XBOT_leftWheel: 'Left',\n                XBOT_bothWheel: 'Both',\n                XBOT_speed: ', Speed',\n                XBOT_rightSpeed: 'Wheel(DC) Motor Right(2) Speed:',\n                XBOT_leftSpeed: 'Left(1) Speed:',\n                XBOT_RGBLED_R: 'RGB LED Color from Red',\n                XBOT_RGBLED_G: 'Green',\n                XBOT_RGBLED_B: 'Blue',\n                XBOT_RGBLED_color: 'RGB LED Color from',\n                XBOT_set: ' ',\n                XBOT_c: 'C',\n                XBOT_d: 'D',\n                XBOT_e: 'E',\n                XBOT_f: 'F',\n                XBOT_g: 'G',\n                XBOT_a: 'A',\n                XBOT_b: 'B',\n                XBOT_melody_ms: 'sec of Melody Playing',\n                XBOT_Line: 'th Line',\n                XBOT_outputValue: 'Text',\n            },\n        },\n    };\n};\n\nEntry.Xbot.blockMenuBlocks = [\n    //XBOT Blocks added\n    'xbot_analogValue',\n    'xbot_digitalInput',\n    'xbot_digitalOutput',\n    'xbot_analogOutput',\n    'xbot_rgb',\n    'xbot_rgb_picker',\n    'xbot_buzzer',\n    'xbot_servo',\n    'xbot_oneWheel',\n    'xbot_twoWheel',\n    'xbot_lcd',\n    //end of XBOT Blocks added\n];\nEntry.Xbot.getBlocks = function() {\n    return {\n        //region xbot 엑스봇\n        xbot_digitalInput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_D2_digitalInput, 'D2'],\n                        [Lang.Blocks.XBOT_D3_digitalInput, 'D3'],\n                        [Lang.Blocks.XBOT_D11_digitalInput, 'D11'],\n                    ],\n                    value: 'D2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'xbot_digitalInput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'xbot_sensor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['Xbot.digital_input(%1)'] },\n        },\n        xbot_analogValue: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_CDS, 'light'],\n                        [Lang.Blocks.XBOT_MIC, 'mic'],\n                        [Lang.Blocks.XBOT_analog0, 'adc0'],\n                        [Lang.Blocks.XBOT_analog1, 'adc1'],\n                        [Lang.Blocks.XBOT_analog2, 'adc2'],\n                        [Lang.Blocks.XBOT_analog3, 'adc3'],\n                    ],\n                    value: 'light',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'xbot_analogValue',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'xbot_sensor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var pd = Entry.hw.portData;\n                var dev = script.getField('DEVICE');\n                return pd[dev];\n            },\n            syntax: { js: [], py: ['Xbot.analog_value(%1)'] },\n        },\n        xbot_digitalOutput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['LED', 'D13'],\n                        ['D4', 'D4'],\n                        ['D7', 'D7'],\n                        ['D12 ', 'D12'],\n                    ],\n                    value: 'D13',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_High, 'HIGH'],\n                        [Lang.Blocks.XBOT_Low, 'LOW'],\n                    ],\n                    value: 'HIGH',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'xbot_digitalOutput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'xbot_sensor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getStringField('VALUE', script);\n\n                if (dev == 'D13' && value == 'HIGH') {\n                    sq.D13 = 1;\n                } else {\n                    sq.D13 = 0;\n                }\n\n                if (dev == 'D4' && value == 'HIGH') {\n                    sq.D4 = 1;\n                } else {\n                    sq.D4 = 0;\n                }\n\n                if (dev == 'D7' && value == 'HIGH') {\n                    sq.D7 = 1;\n                } else {\n                    sq.D7 = 0;\n                }\n\n                if (dev == 'D12' && value == 'HIGH') {\n                    sq.D12 = 1;\n                } else {\n                    sq.D12 = 0;\n                }\n                //sq.D13 = 1;\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Xbot.digital_output(%1, %2)'] },\n        },\n        xbot_analogOutput: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['D5', 'analogD5'],\n                        ['D6', 'analogD6'],\n                    ],\n                    value: 'analogD5',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'xbot_analogOutput',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'xbot_sensor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var dev = script.getStringField('DEVICE', script);\n                var value = script.getNumberValue('VALUE', script);\n\n                if (dev == 'analogD5') {\n                    sq.analogD5 = value;\n                } else if (dev == 'analogD6') {\n                    sq.analogD6 = value;\n                }\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Xbot.analog_output(%1, %2)'] },\n        },\n        xbot_servo: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_Head, 'head'],\n                        [Lang.Blocks.XBOT_ArmR, 'right'],\n                        [Lang.Blocks.XBOT_ArmL, 'left'],\n                    ],\n                    value: 'head',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                ],\n                type: 'xbot_servo',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'xbot_motor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var mtype = script.getStringField('DEVICE', script);\n                var angle = script.getNumberValue('VALUE', script);\n\n                if (mtype == 'head') {\n                    sq.head = angle;\n                } else if (mtype == 'right') {\n                    sq.armR = angle;\n                } else if (mtype == 'left') {\n                    sq.armL = angle;\n                }\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Xbot.servo(%1, %2)'] },\n        },\n        xbot_oneWheel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_rightWheel, 'rightWheel'],\n                        [Lang.Blocks.XBOT_leftWheel, 'leftWheel'],\n                        [Lang.Blocks.XBOT_bothWheel, 'bothWheel'],\n                    ],\n                    value: 'rightWheel',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'xbot_oneWheel',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n                VALUE: 1,\n            },\n            class: 'xbot_motor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                //console.log('xbot_move_forward_for_secs');\n                var sq = Entry.hw.sendQueue;\n                var dir = script.getStringField('DEVICE', script);\n                var speed = script.getNumberValue('VALUE', script);\n\n                if (dir == 'rightWheel') sq.rightWheel = speed;\n                else if (dir == 'leftWheel') sq.leftWheel = speed;\n                else sq.rightWheel = sq.leftWheel = speed;\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Xbot.one_wheel(%1, %2)'] },\n        },\n        xbot_twoWheel: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'xbot_twoWheel',\n            },\n            paramsKeyMap: {\n                rightWheel: 0,\n                leftWheel: 1,\n            },\n            class: 'xbot_motor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                //console.log('xbot_move_forward_for_secs');\n                var sq = Entry.hw.sendQueue;\n\n                sq.rightWheel = script.getNumberValue('rightWheel');\n                sq.leftWheel = script.getNumberValue('leftWheel');\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Xbot.two_wheel(%1, %2)'] },\n        },\n        xbot_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    null,\n                ],\n                type: 'xbot_rgb',\n            },\n            paramsKeyMap: {\n                ledR: 0,\n                ledG: 1,\n                ledB: 2,\n            },\n            class: 'xbot_rgb',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                sq.ledR = script.getNumberValue('ledR');\n                sq.ledG = script.getNumberValue('ledG');\n                sq.ledB = script.getNumberValue('ledB');\n\n                //console.log('ledR' + sq.ledR + ' ledG ' + sq.ledG +' ledB ' + sq.ledB);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Xbot.rgb(%1, %2, %3)'] },\n        },\n        xbot_rgb_picker: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'xbot_rgb_picker',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n            },\n            class: 'xbot_rgb',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var port = script.getStringField('VALUE');\n                var sq = Entry.hw.sendQueue;\n\n                sq.ledR = parseInt(parseInt(port.substr(1, 2), 16) * 0.3);\n                sq.ledG = parseInt(parseInt(port.substr(3, 2), 16) * 0.3);\n                sq.ledB = parseInt(parseInt(port.substr(5, 2), 16) * 0.3);\n\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Xbot.rgb_picker(%1)'] },\n        },\n        xbot_buzzer: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.XBOT_c, 'C'],\n                        [Lang.Blocks.XBOT_d, 'D'],\n                        [Lang.Blocks.XBOT_e, 'E'],\n                        [Lang.Blocks.XBOT_f, 'F'],\n                        [Lang.Blocks.XBOT_g, 'G'],\n                        [Lang.Blocks.XBOT_a, 'A'],\n                        [Lang.Blocks.XBOT_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '2',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'xbot_buzzer',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                VALUE: 2,\n            },\n            class: 'xbot_sensor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n\n                if (!script.isStart) {\n                    var note = script.getStringField('NOTE', script);\n                    var octave = script.getStringField('OCTAVE', script);\n                    var duration = script.getNumberValue('VALUE', script);\n                    var noteOctave = note + octave; // 'C'+ 2 = \"C2\"\n                    //console.log('xbot_buzzer noteOctave' + note + ' ' + octave + ' ' + duration);\n\n                    if (noteOctave == 'C2') sq.note = 65;\n                    else if (noteOctave == 'D2') sq.note = 73;\n                    else if (noteOctave == 'E2') sq.note = 82;\n                    else if (noteOctave == 'F2') sq.note = 87;\n                    else if (noteOctave == 'G2') sq.note = 98;\n                    else if (noteOctave == 'A2') sq.note = 110;\n                    else if (noteOctave == 'B2') sq.note = 123;\n                    else if (noteOctave == 'C3') sq.note = 131;\n                    else if (noteOctave == 'D3') sq.note = 147;\n                    else if (noteOctave == 'E3') sq.note = 165;\n                    else if (noteOctave == 'F3') sq.note = 175;\n                    else if (noteOctave == 'G3') sq.note = 196;\n                    else if (noteOctave == 'A3') sq.note = 220;\n                    else if (noteOctave == 'B3') sq.note = 247;\n                    else if (noteOctave == 'C4') sq.note = 262;\n                    else if (noteOctave == 'D4') sq.note = 294;\n                    else if (noteOctave == 'E4') sq.note = 330;\n                    else if (noteOctave == 'F4') sq.note = 349;\n                    else if (noteOctave == 'G4') sq.note = 392;\n                    else if (noteOctave == 'A4') sq.note = 440;\n                    else if (noteOctave == 'B4') sq.note = 494;\n                    else if (noteOctave == 'C5') sq.note = 523;\n                    else if (noteOctave == 'D5') sq.note = 587;\n                    else if (noteOctave == 'E5') sq.note = 659;\n                    else if (noteOctave == 'F5') sq.note = 698;\n                    else if (noteOctave == 'G5') sq.note = 784;\n                    else if (noteOctave == 'A5') sq.note = 880;\n                    else if (noteOctave == 'B5') sq.note = 988;\n                    else if (noteOctave == 'C6') sq.note = 1047;\n                    else if (noteOctave == 'D6') sq.note = 1175;\n                    else if (noteOctave == 'E6') sq.note = 1319;\n                    else if (noteOctave == 'F6') sq.note = 1397;\n                    else if (noteOctave == 'G6') sq.note = 1568;\n                    else if (noteOctave == 'A6') sq.note = 1760;\n                    else if (noteOctave == 'B6') sq.note = 1976;\n                    else if (noteOctave == 'C7') sq.note = 2093;\n                    else if (noteOctave == 'D7') sq.note = 2349;\n                    else if (noteOctave == 'E7') sq.note = 2637;\n                    else if (noteOctave == 'F7') sq.note = 2794;\n                    else if (noteOctave == 'G7') sq.note = 3136;\n                    else if (noteOctave == 'A7') sq.note = 3520;\n                    else if (noteOctave == 'B7') sq.note = 3951;\n                    else sq.note = 262;\n\n                    //sq.duration = 200;\n                    //duration *= 40; //  convert to mSec\n                    sq.duration = duration * 40;\n\n                    script.isStart = true;\n                    script.timeFlag = 1;\n\n                    var timeValue = duration * 1000;\n                    var timer = setTimeout(function() {\n                        script.timeFlag = 0;\n                        Entry.Xbot.removeTimeout(timer);\n                    }, timeValue);\n                    Entry.Xbot.timeouts.push(timer);\n                    return script;\n                } else if (script.timeFlag == 1) {\n                    return script;\n                } else {\n                    delete script.isStart;\n                    delete script.timeFlag;\n                    Entry.engine.isContinue = false;\n                    sq.duration = 0;\n                    return script.callReturn();\n                }\n            },\n            syntax: { js: [], py: ['Xbot.buzzer(%1, %2, %3)'] },\n        },\n        xbot_lcd: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['0', '0'],\n                        ['1', '1'],\n                    ],\n                    value: '0',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['Hello'],\n                    },\n                    null,\n                ],\n                type: 'xbot_lcd',\n            },\n            paramsKeyMap: {\n                LINE: 0,\n                VALUE: 1,\n            },\n            class: 'xbot_sensor',\n            isNotFor: ['xbot_epor_edge'],\n            func: function(sprite, script) {\n                var sq = Entry.hw.sendQueue;\n                var line = script.getNumberField('LINE', script);\n                var str = script.getStringValue('VALUE', script);\n\n                if (line == 0) {\n                    sq.lcdNum = 0;\n                    sq.lcdTxt = str;\n                } else if (line == 1) {\n                    sq.lcdNum = 1;\n                    sq.lcdTxt = str;\n                }\n                //console.log('ledR' + sq.ledR + ' ledG ' + sq.ledG +' ledB ' + sq.ledB);\n                return script.callReturn();\n            },\n            syntax: { js: [], py: ['Xbot.lcd(%1, %2)'] },\n        },\n        //endregion xbot 엑스봇\n    };\n};\n\nmodule.exports = Entry.Xbot;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_zerone.js",
    "content": "'use strict';\n\nEntry.Zerone = {\n    setZero() {\n        Entry.Robomation.setZero();\n    },\n    afterReceive(pd) {\n        Entry.Robomation.afterReceive(pd, false);\n    },\n    afterSend(sq) {\n        Entry.Robomation.afterSend(sq);\n    },\n    getRobot() {\n        const robot = Entry.Robomation.getRobot('zerone', 0);\n        if (robot) {\n            robot.setMotoring(Entry.hw.sendQueue);\n        }\n        return robot;\n    },\n    id: '2.F',\n    name: 'zerone',\n    url: 'http://www.toytron.co.kr',\n    imageName: 'zerone.png',\n    title: {\n        ko: '제론',\n        en: 'Zerone',\n        jp: 'ゼロン',\n        vn: 'Zerone',\n    },\n    monitorTemplate: () => ({\n        imgPath: 'hw/zerone.png',\n        width: 414,\n        height: 300,\n        listPorts: {\n            colorNumber: {\n                name: Lang.Blocks.ROBOID_sensor_color_number,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorRed: {\n                name: Lang.Blocks.ROBOID_sensor_color_r,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorGreen: {\n                name: Lang.Blocks.ROBOID_sensor_color_g,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            colorBlue: {\n                name: Lang.Blocks.ROBOID_sensor_color_b,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            button: {\n                name: Lang.Blocks.ROBOID_sensor_button,\n                type: 'input',\n                pos: { x: 0, y: 0 },\n            },\n            buzzer: {\n                name: Lang.Blocks.ROBOID_monitor_buzzer,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n            note: {\n                name: Lang.Blocks.ROBOID_monitor_note,\n                type: 'output',\n                pos: { x: 0, y: 0 },\n            },\n        },\n        ports: {\n            leftProximity: {\n                name: Lang.Blocks.ROBOID_sensor_left_proximity,\n                type: 'input',\n                pos: { x: 213, y: 115 },\n            },\n            rightProximity: {\n                name: Lang.Blocks.ROBOID_sensor_right_proximity,\n                type: 'input',\n                pos: { x: 211, y: 115 },\n            },\n            frontProximity: {\n                name: Lang.Blocks.ROBOID_sensor_front_proximity,\n                type: 'input',\n                pos: { x: 212, y: 116 },\n            },\n            rearProximity: {\n                name: Lang.Blocks.ROBOID_sensor_rear_proximity,\n                type: 'input',\n                pos: { x: 212, y: 114 },\n            },\n            floor: {\n                name: Lang.Blocks.ROBOID_sensor_floor,\n                type: 'input',\n                pos: { x: 207, y: 288 },\n            },\n            leftWheel: {\n                name: Lang.Blocks.ROBOID_monitor_left_wheel,\n                type: 'output',\n                pos: { x: 407, y: 206 },\n            },\n            rightWheel: {\n                name: Lang.Blocks.ROBOID_monitor_right_wheel,\n                type: 'output',\n                pos: { x: 7, y: 206 },\n            },\n            leftHeadRgb: {\n                name: Lang.Blocks.ROBOID_monitor_left_head_led,\n                type: 'output',\n                pos: { x: 333, y: 141 },\n            },\n            rightHeadRgb: {\n                name: Lang.Blocks.ROBOID_monitor_right_head_led,\n                type: 'output',\n                pos: { x: 71, y: 141 },\n            },\n            leftTailRgb: {\n                name: Lang.Blocks.ROBOID_monitor_left_tail_led,\n                type: 'output',\n                pos: { x: 376, y: 70 },\n            },\n            rightTailRgb: {\n                name: Lang.Blocks.ROBOID_monitor_right_tail_led,\n                type: 'output',\n                pos: { x: 37, y: 70 },\n            },\n        },\n        mode: 'both',\n    }),\n};\n\nEntry.Zerone.setLanguage = () => ({\n    ko: {\n        template: {\n            zerone_is_gesture: '제스처가 %1 인가?',\n            zerone_touching_color: '%1 에 닿았는가?',\n            zerone_is_color_pattern: '색깔 패턴이 %1 %2 인가?',\n            zerone_button_state: '버튼을 %1 ?',\n            zerone_boolean: '배터리 %1?',\n            zerone_value: '%1',\n            zerone_move_forward_unit: '앞으로 %1 %2 이동하기 %3',\n            zerone_move_backward_unit: '뒤로 %1 %2 이동하기 %3',\n            zerone_turn_unit_in_place: '%1 으로 %2 %3 제자리 돌기 %4',\n            zerone_change_both_wheels_by: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n            zerone_set_both_wheels_to: '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n            zerone_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n            zerone_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n            zerone_follow_line: '선 따라가기 %1',\n            zerone_follow_line_until: '선을 따라 %1 까지 이동하기 %2',\n            zerone_follow_line_until_intersection: '선을 따라 교차로까지 이동하기 %1',\n            zerone_cross_intersection: '교차로 건너가기 %1',\n            zerone_turn_at_intersection: '교차로에서 %1 으로 돌기 %2',\n            zerone_jump_line: '%1 선으로 건너가기 %2',\n            zerone_set_following_speed_to: '선 따라가기 속도를 %1 (으)로 정하기 %2',\n            zerone_stop: '정지하기 %1',\n            zerone_set_led_to: '%1 LED를 %2 으로 정하기 %3',\n            zerone_pick_led: '%1 LED를 %2로 정하기 %3',\n            zerone_change_led_by_rgb: '%1 LED를 R: %2 G: %3 B: %4 만큼 바꾸기 %5',\n            zerone_set_led_to_rgb: '%1 LED를 R: %2 G: %3 B: %4 (으)로 정하기 %5',\n            zerone_clear_led: '%1 LED 끄기 %2',\n            zerone_play_sound_times: '%1 소리 %2 번 재생하기 %3',\n            zerone_play_sound_times_until_done: '%1 소리 %2 번 재생하고 기다리기 %3',\n            zerone_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n            zerone_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n            zerone_clear_sound: '소리 끄기 %1',\n            zerone_play_note: '%1 %2 음을 연주하기 %3',\n            zerone_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n            zerone_rest_for: '%1 박자 쉬기 %2',\n            zerone_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n            zerone_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n        },\n        Helper: {\n            zerone_is_gesture:\n                \"선택한 제스처를 제스처 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            zerone_touching_color:\n                \"선택한 색깔을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            zerone_is_color_pattern: \"선택한 색깔 패턴을 컬러 센서가 감지하였으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            zerone_button_state: \"버튼을 클릭했으면/더블클릭했으면/길게 눌렀으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            zerone_boolean:\n                \"배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n            zerone_value:\n                '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>앞쪽 근접 센서: 앞쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>뒤쪽 근접 센서: 뒤쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>제스처: 제스처 센서가 감지한 제스처의 번호 (값의 범위: -1 ~ 6, 초기값: -1)<br/>색깔 번호: 컬러 센서가 감지한 색깔의 번호 (값의 범위: -1 ~ 6, 초기값: -1)<br/>색깔 R: 컬러 센서가 감지한 색깔의 빨간색(R) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>색깔 G: 컬러 센서가 감지한 색깔의 초록색(G) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>색깔 B: 컬러 센서가 감지한 색깔의 파란색(B) 성분 (값의 범위: 0 ~ 255, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.',\n            zerone_move_forward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 앞으로 이동합니다.',\n            zerone_move_backward_unit: '입력한 거리(cm)/시간(초)/펄스만큼 뒤로 이동합니다.',\n            zerone_turn_unit_in_place:\n                '입력한 각도(도)/시간(초)/펄스만큼 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n            zerone_change_both_wheels_by:\n                '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            zerone_set_both_wheels_to:\n                '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            zerone_change_wheel_by:\n                '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n            zerone_set_wheel_to:\n                '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n            zerone_follow_line: '하얀색 바탕 위에서 검은색 선을 따라 이동합니다.',\n            zerone_follow_line_until: '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 선택한 색깔을 컬러 센서가 감지하면 정지합니다.',\n            zerone_follow_line_until_intersection: '하얀색 바탕 위에서 검은색 선을 따라 이동하다가 검은색 교차로를 컬러 센서가 감지하면 정지합니다.',\n            zerone_cross_intersection: '검은색 교차로에서 잠시 앞으로 이동한 후 검은색 선을 찾습니다.',\n            zerone_turn_at_intersection: '검은색 교차로에서 잠시 앞으로 이동한 후 제자리에서 왼쪽/오른쪽/뒤쪽으로 회전하고 검은색 선을 찾습니다.',\n            zerone_jump_line: '제자리에서 왼쪽/오른쪽으로 90도 회전한 후 앞으로 이동하다가 컬러 센서가 검은색 선을 감지하면 원래 방향으로 다시 회전합니다.',\n            zerone_set_following_speed_to: '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n            zerone_stop: '양쪽 바퀴를 정지합니다.',\n            zerone_set_led_to: '선택한 LED를 선택한 색깔로 켭니다.',\n            zerone_pick_led: '선택한 LED를 선택한 색깔로 켭니다.',\n            zerone_change_led_by_rgb: '선택한 LED의 현재 R, G, B 값에 입력한 값을 각각 더합니다.',\n            zerone_set_led_to_rgb: '선택한 LED의 R, G, B 값을 입력한 값으로 각각 설정합니다.',\n            zerone_clear_led: '선택한 LED를 끕니다.',\n            zerone_play_sound_times: '선택한 소리를 입력한 횟수만큼 재생합니다.',\n            zerone_play_sound_times_until_done:\n                '선택한 소리를 입력한 횟수만큼 재생하고, 재생이 완료될 때까지 기다립니다.',\n            zerone_change_buzzer_by:\n                '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 첫째 자리까지 입력할 수 있습니다.',\n            zerone_set_buzzer_to:\n                '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 첫째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 소리를 끕니다.',\n            zerone_clear_sound: '소리를 끕니다.',\n            zerone_play_note: '선택한 계이름과 옥타브의 음을 계속 소리 냅니다.',\n            zerone_play_note_for: '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n            zerone_rest_for: '입력한 박자만큼 쉽니다.',\n            zerone_change_tempo_by:\n                '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n            zerone_set_tempo_to: '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: '버저',\n            ROBOID_monitor_note: '음표',\n            ROBOID_monitor_left_wheel: '왼쪽 바퀴',\n            ROBOID_monitor_right_wheel: '오른쪽 바퀴',\n            ROBOID_monitor_left_head_led: '왼쪽 앞 LED',\n            ROBOID_monitor_right_head_led: '오른쪽 앞 LED',\n            ROBOID_monitor_left_tail_led: '왼쪽 뒤 LED',\n            ROBOID_monitor_right_tail_led: '오른쪽 뒤 LED',\n            ROBOID_gesture_forward: '앞으로',\n            ROBOID_gesture_backward: '뒤로',\n            ROBOID_gesture_leftward: '왼쪽으로',\n            ROBOID_gesture_rightward: '오른쪽으로',\n            ROBOID_gesture_near: '가까이',\n            ROBOID_gesture_far: '멀리',\n            ROBOID_gesture_click: '클릭',\n            ROBOID_gesture_long_touch: '오래 터치',\n            ROBOID_color_red: '빨간색',\n            ROBOID_color_orange: '주황색',\n            ROBOID_color_yellow: '노란색',\n            ROBOID_color_green: '초록색',\n            ROBOID_color_sky_blue: '하늘색',\n            ROBOID_color_blue: '파란색',\n            ROBOID_color_violet: '보라색',\n            ROBOID_color_purple: '자주색',\n            ROBOID_color_white: '하얀색',\n            ROBOID_color_black: '검은색',\n            ROBOID_color_any: '아무 색',\n            ROBOID_clicked: '클릭했는가',\n            ROBOID_double_clicked: '더블클릭했는가',\n            ROBOID_long_pressed: '오래 눌렀는가',\n            ROBOID_battery_state_normal: '정상',\n            ROBOID_battery_state_low: '부족',\n            ROBOID_battery_state_empty: '없음',\n            ROBOID_sensor_left_proximity: '왼쪽 근접 센서',\n            ROBOID_sensor_right_proximity: '오른쪽 근접 센서',\n            ROBOID_sensor_front_proximity: '앞쪽 근접 센서',\n            ROBOID_sensor_rear_proximity: '뒤쪽 근접 센서',\n            ROBOID_sensor_gesture: '제스처',\n            ROBOID_sensor_color_number: '색깔 번호',\n            ROBOID_sensor_color_pattern: '색깔 패턴',\n            ROBOID_sensor_color_r: '색깔 R',\n            ROBOID_sensor_color_g: '색깔 G',\n            ROBOID_sensor_color_b: '색깔 B',\n            ROBOID_sensor_floor: '바닥 센서',\n            ROBOID_sensor_button: '버튼',\n            ROBOID_sensor_signal_strength: '신호 세기',\n            ROBOID_gesture: '제스처',\n            ROBOID_color: '색깔',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '초',\n            ROBOID_unit_pulse: '펄스',\n            ROBOID_unit_deg: '도',\n            ROBOID_left: '왼쪽',\n            ROBOID_right: '오른쪽',\n            ROBOID_both: '양쪽',\n            ROBOID_head: '앞쪽',\n            ROBOID_tail: '뒤쪽',\n            ROBOID_all: '모든',\n            ROBOID_led_left_head: '왼쪽 앞',\n            ROBOID_led_right_head: '오른쪽 앞',\n            ROBOID_led_left_tail: '왼쪽 뒤',\n            ROBOID_led_right_tail: '오른쪽 뒤',\n            ROBOID_sound_beep: '삐',\n            ROBOID_sound_random_beep: '무작위 삐',\n            ROBOID_sound_noise: '지지직',\n            ROBOID_sound_siren: '사이렌',\n            ROBOID_sound_engine: '엔진',\n            ROBOID_sound_chop: '쩝',\n            ROBOID_sound_robot: '로봇',\n            ROBOID_sound_dibidibidip: '디비디비딥',\n            ROBOID_sound_good_job: '잘 했어요',\n            ROBOID_sound_happy: '행복',\n            ROBOID_sound_angry: '화남',\n            ROBOID_sound_sad: '슬픔',\n            ROBOID_sound_sleep: '졸림',\n            ROBOID_sound_march: '행진',\n            ROBOID_sound_birthday: '생일',\n            ROBOID_note_c: '도',\n            ROBOID_note_c_sharp: '도♯(레♭)',\n            ROBOID_note_d: '레',\n            ROBOID_note_d_sharp: '레♯(미♭)',\n            ROBOID_note_e: '미',\n            ROBOID_note_f: '파',\n            ROBOID_note_f_sharp: '파♯(솔♭)',\n            ROBOID_note_g: '솔',\n            ROBOID_note_g_sharp: '솔♯(라♭)',\n            ROBOID_note_a: '라',\n            ROBOID_note_a_sharp: '라♯(시♭)',\n            ROBOID_note_b: '시',\n        },\n    },\n    en: {\n        template: {\n            zerone_is_gesture: 'gesture %1?',\n            zerone_touching_color: 'touching %1?',\n            zerone_is_color_pattern: 'color pattern %1 %2 ?',\n            zerone_button_state: 'button %1 ?',\n            zerone_boolean: 'battery %1?',\n            zerone_value: '%1',\n            zerone_move_forward_unit: 'move forward %1 %2 %3',\n            zerone_move_backward_unit: 'move backward %1 %2 %3',\n            zerone_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            zerone_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            zerone_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            zerone_change_wheel_by: 'change %1 wheel by %2 %3',\n            zerone_set_wheel_to: 'set %1 wheel to %2 %3',\n            zerone_follow_line: 'follow line %1',\n            zerone_follow_line_until: 'follow line until %1 %2',\n            zerone_follow_line_until_intersection: 'follow line until intersection %1',\n            zerone_cross_intersection: 'cross intersection %1',\n            zerone_turn_at_intersection: 'turn %1 at intersection %2',\n            zerone_jump_line: 'jump to %1 line %2',\n            zerone_set_following_speed_to: 'set following speed to %1 %2',\n            zerone_stop: 'stop %1',\n            zerone_set_led_to: 'set %1 led to %2 %3',\n            zerone_pick_led: 'set %1 led to %2 %3',\n            zerone_change_led_by_rgb: 'change %1 led by r: %2 g: %3 b: %4 %5',\n            zerone_set_led_to_rgb: 'set %1 led to r: %2 g: %3 b: %4 %5',\n            zerone_clear_led: 'clear %1 led %2',\n            zerone_play_sound_times: 'play sound %1 %2 times %3',\n            zerone_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            zerone_change_buzzer_by: 'change buzzer by %1 %2',\n            zerone_set_buzzer_to: 'set buzzer to %1 %2',\n            zerone_clear_sound: 'clear sound %1',\n            zerone_play_note: 'play note %1 %2 %3',\n            zerone_play_note_for: 'play note %1 %2 for %3 beats %4',\n            zerone_rest_for: 'rest for %1 beats %2',\n            zerone_change_tempo_by: 'change tempo by %1 %2',\n            zerone_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            zerone_is_gesture:\n                'If the gesture sensor detects the selected gesture, true, otherwise false.',\n            zerone_touching_color:\n                'If the color sensor detects the selected color, true, otherwise false.',\n            zerone_is_color_pattern: 'If the color sensor detects the selected color pattern, true, otherwise false.',\n            zerone_button_state: 'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            zerone_boolean:\n                'battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            zerone_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>front proximity: value of front proximity sensor (range: 0 to 255, initial value: 0)<br/>rear proximity: value of rear proximity sensor (range: 0 to 255, initial value: 0)<br/>gesture: gesture number detected by the gesture sensor (range: -1 ~ 6, initial value: -1)<br/>color number: color number detected by the color sensor (range: -1 to 6, initial value: -1)<br/>color r: red component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color g: green component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color b: blue component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.',\n            zerone_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            zerone_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            zerone_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            zerone_change_both_wheels_by:\n                'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            zerone_set_both_wheels_to:\n                'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            zerone_change_wheel_by:\n                'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            zerone_set_wheel_to:\n                'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            zerone_follow_line: 'Moves along the black line on a white background.',\n            zerone_follow_line_until: 'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            zerone_follow_line_until_intersection: 'Moves along the black line on a white background and stops when the color sensor detects the black intersection.',\n            zerone_cross_intersection: 'Moves forward for a moment at the black intersection, then finds the black line.',\n            zerone_turn_at_intersection: 'Moves forward for a moment at the black intersection, then turns left/right/back in place and finds the black line.',\n            zerone_jump_line: 'Turns left/right 90 degrees in place and moves forward. Stops when the color sensor detects the black line and turns to its original direction.',\n            zerone_set_following_speed_to: 'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            zerone_stop: 'Stops both wheels.',\n            zerone_set_led_to: 'Turns the selected LED to the selected color.',\n            zerone_pick_led: 'Turns the selected LED to the selected color.',\n            zerone_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of the selected LED, respectively.',\n            zerone_set_led_to_rgb:\n                'Sets the R, G, B values of the selected LED to the entered values.',\n            zerone_clear_led: 'Turns off the selected LED.',\n            zerone_play_sound_times: 'Plays the selected sound as many times as entered.',\n            zerone_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            zerone_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to one decimal place.',\n            zerone_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to one decimal place. Entering the number 0 turns off the buzzer sound.',\n            zerone_clear_sound: 'Turns off sound.',\n            zerone_play_note: 'It sounds the selected tone and octave.',\n            zerone_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            zerone_rest_for: 'Rests as much as the beat you entered.',\n            zerone_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            zerone_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_monitor_left_head_led: 'left head led',\n            ROBOID_monitor_right_head_led: 'right head led',\n            ROBOID_monitor_left_tail_led: 'left tail led',\n            ROBOID_monitor_right_tail_led: 'right tail led',\n            ROBOID_gesture_forward: 'forward',\n            ROBOID_gesture_backward: 'backward',\n            ROBOID_gesture_leftward: 'leftward',\n            ROBOID_gesture_rightward: 'rightward',\n            ROBOID_gesture_near: 'near',\n            ROBOID_gesture_far: 'far',\n            ROBOID_gesture_click: 'click',\n            ROBOID_gesture_long_touch: 'long touch',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_color_black: 'black',\n            ROBOID_color_any: 'any color',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_battery_state_normal: 'normal',\n            ROBOID_battery_state_low: 'low',\n            ROBOID_battery_state_empty: 'empty',\n            ROBOID_sensor_left_proximity: 'left proximity',\n            ROBOID_sensor_right_proximity: 'right proximity',\n            ROBOID_sensor_front_proximity: 'front proximity',\n            ROBOID_sensor_rear_proximity: 'rear proximity',\n            ROBOID_sensor_gesture: 'gesture',\n            ROBOID_sensor_color_number: 'color number',\n            ROBOID_sensor_color_pattern: 'color pattern',\n            ROBOID_sensor_color_r: 'color r',\n            ROBOID_sensor_color_g: 'color g',\n            ROBOID_sensor_color_b: 'color b',\n            ROBOID_sensor_floor: 'floor',\n            ROBOID_sensor_button: 'button',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_gesture: 'gesture',\n            ROBOID_color: 'color',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_head: 'head',\n            ROBOID_tail: 'tail',\n            ROBOID_all: 'all',\n            ROBOID_led_left_head: 'left head',\n            ROBOID_led_right_head: 'right head',\n            ROBOID_led_left_tail: 'left tail',\n            ROBOID_led_right_tail: 'right tail',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n    jp: {\n        template: {\n            zerone_is_gesture: 'ジェスチャーが %1 ですか?',\n            zerone_touching_color: '%1 に触れたか?',\n            zerone_is_color_pattern: '色パターンが %1 %2 ですか?',\n            zerone_button_state: 'ボタンを %1 ?',\n            zerone_boolean: '電池が%1?',\n            zerone_value: '%1',\n            zerone_move_forward_unit: '前へ%1%2動かす %3',\n            zerone_move_backward_unit: '後ろへ%1%2動かす %3',\n            zerone_turn_unit_in_place: '所定位置で%1に%2%3回す %4',\n            zerone_change_both_wheels_by: '左車輪を%1右車輪を%2ずつ変える %3',\n            zerone_set_both_wheels_to: '左車輪を%1右車輪を%2にする %3',\n            zerone_change_wheel_by: '%1車輪を%2ずつ変える %3',\n            zerone_set_wheel_to: '%1車輪を%2にする %3',\n            zerone_follow_line: '線に沿って移動する %1',\n            zerone_follow_line_until: '線に沿って %1 まで移動する %2',\n            zerone_follow_line_until_intersection: '線にそって交差点まで移動する %1',\n            zerone_cross_intersection: '交差点を渡る %1',\n            zerone_turn_at_intersection: '交差点で %1 へ回る %2',\n            zerone_jump_line: '%1 線へ渡り行く %2',\n            zerone_set_following_speed_to: '線に沿って移動する速さを %1 にする %2',\n            zerone_stop: '停止する %1',\n            zerone_set_led_to: '%1LEDを%2にする %3',\n            zerone_pick_led: '%1LEDを%2にする %3',\n            zerone_change_led_by_rgb: '%1LEDをR:%2G:%3B:%4ずつ変える %5',\n            zerone_set_led_to_rgb: '%1LEDをR:%2G:%3B:%4にする %5',\n            zerone_clear_led: '%1LEDを消す %2',\n            zerone_play_sound_times: '%1音を%2回鳴らす %3',\n            zerone_play_sound_times_until_done: '終わるまで%1音を%2回鳴らす %3',\n            zerone_change_buzzer_by: 'ブザー音を%1ずつ変える %2',\n            zerone_set_buzzer_to: 'ブザー音を%1にする %2',\n            zerone_clear_sound: '音を止める %1',\n            zerone_play_note: '%1%2音を鳴らす %3',\n            zerone_play_note_for: '%1%2音を%3拍鳴らす %4',\n            zerone_rest_for: '%1拍休む %2',\n            zerone_change_tempo_by: 'テンポを%1ずつ変える %2',\n            zerone_set_tempo_to: 'テンポを%1BPMにする %2',\n        },\n        Helper: {\n            zerone_is_gesture:\n                'If the gesture sensor detects the selected gesture, true, otherwise false.',\n            zerone_touching_color:\n                'If the color sensor detects the selected color, true, otherwise false.',\n            zerone_is_color_pattern: '選択された色パターンをカラーセンサーが感知したら「正しい」と判断して、それ以外の場合は｢正しくない｣と判断します。',\n            zerone_button_state: 'ボタンをクリックしたら、/ダブルクリックしたら、/長く押したら「正しい」と判断して、それ以外の場合は｢正しくない｣と判断します。',\n            zerone_boolean:\n                'battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            zerone_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>front proximity: value of front proximity sensor (range: 0 to 255, initial value: 0)<br/>rear proximity: value of rear proximity sensor (range: 0 to 255, initial value: 0)<br/>gesture: gesture number detected by the gesture sensor (range: -1 ~ 6, initial value: -1)<br/>color number: color number detected by the color sensor (range: -1 to 6, initial value: -1)<br/>color r: red component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color g: green component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color b: blue component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.',\n            zerone_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            zerone_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            zerone_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            zerone_change_both_wheels_by:\n                'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            zerone_set_both_wheels_to:\n                'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            zerone_change_wheel_by:\n                'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            zerone_set_wheel_to:\n                'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            zerone_follow_line: '下地が白色の上、黒色線に沿って移動します。',\n            zerone_follow_line_until: '下地が白色の上で黒の線に沿って移動している途中、選択した色をカラーセンサーが感知すると停止します。',\n            zerone_follow_line_until_intersection: '下地が白色の上で黒の線に沿って移動している途中、黒色交差点をカラーセンサーが感知すると停止します。',\n            zerone_cross_intersection: '黒色交差点でしばらく前に移動した後、黒線を探します。',\n            zerone_turn_at_intersection: '黒色交差点でしばらく前に移動した後、その場で左/右/後ろに回転して黒線を探します。',\n            zerone_jump_line: 'その場で左/右に90度回転した後、前方に移動している途中のカラーセンサーが黒線を検出すると元の方向に戻って回転します。',\n            zerone_set_following_speed_to: '線に沿って移動する速度(1〜8)を設定します。数字が大きいほど移動速度が速くなります。',\n            zerone_stop: 'Stops both wheels.',\n            zerone_set_led_to: 'Turns the selected LED to the selected color.',\n            zerone_pick_led: 'Turns the selected LED to the selected color.',\n            zerone_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of the selected LED, respectively.',\n            zerone_set_led_to_rgb:\n                'Sets the R, G, B values of the selected LED to the entered values.',\n            zerone_clear_led: 'Turns off the selected LED.',\n            zerone_play_sound_times: 'Plays the selected sound as many times as entered.',\n            zerone_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            zerone_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to one decimal place.',\n            zerone_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to one decimal place. Entering the number 0 turns off the buzzer sound.',\n            zerone_clear_sound: 'Turns off sound.',\n            zerone_play_note: 'It sounds the selected tone and octave.',\n            zerone_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            zerone_rest_for: 'Rests as much as the beat you entered.',\n            zerone_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            zerone_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'ブザー',\n            ROBOID_monitor_note: '音符',\n            ROBOID_monitor_left_wheel: '左車輪',\n            ROBOID_monitor_right_wheel: '右車輪',\n            ROBOID_monitor_left_head_led: '左前LED',\n            ROBOID_monitor_right_head_led: '右前LED',\n            ROBOID_monitor_left_tail_led: '左後LED',\n            ROBOID_monitor_right_tail_led: '右後LED',\n            ROBOID_gesture_forward: '前へ',\n            ROBOID_gesture_backward: '後ろへ',\n            ROBOID_gesture_leftward: '左へ',\n            ROBOID_gesture_rightward: '右へ',\n            ROBOID_gesture_near: '近く',\n            ROBOID_gesture_far: '遠く',\n            ROBOID_gesture_click: 'クリック',\n            ROBOID_gesture_long_touch: '長くタッチ',\n            ROBOID_color_red: '赤色',\n            ROBOID_color_orange: '橙色',\n            ROBOID_color_yellow: '黄色',\n            ROBOID_color_green: '緑色',\n            ROBOID_color_sky_blue: '水色',\n            ROBOID_color_blue: '青色',\n            ROBOID_color_violet: '青紫色',\n            ROBOID_color_purple: '紫色',\n            ROBOID_color_white: '白色',\n            ROBOID_color_black: '黒色',\n            ROBOID_color_any: '全ての色',\n            ROBOID_clicked: 'クリックしたか',\n            ROBOID_double_clicked: 'ダブルクリックしたか',\n            ROBOID_long_pressed: '長く押したか',\n            ROBOID_battery_state_normal: '正常か',\n            ROBOID_battery_state_low: '足りないか',\n            ROBOID_battery_state_empty: 'ないか',\n            ROBOID_sensor_left_proximity: '左近接センサー',\n            ROBOID_sensor_right_proximity: '右近接センサー',\n            ROBOID_sensor_front_proximity: '前近接センサー',\n            ROBOID_sensor_rear_proximity: '後近接センサー',\n            ROBOID_sensor_gesture: 'ジェスチャー',\n            ROBOID_sensor_color_number: '色番号',\n            ROBOID_sensor_color_pattern: '色パターン',\n            ROBOID_sensor_color_r: '色R',\n            ROBOID_sensor_color_g: '色G',\n            ROBOID_sensor_color_b: '色B',\n            ROBOID_sensor_floor: '床底センサー',\n            ROBOID_sensor_button: 'ボタン',\n            ROBOID_sensor_signal_strength: '信号強度',\n            ROBOID_gesture: 'ジェスチャー',\n            ROBOID_color: '色',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: '秒',\n            ROBOID_unit_pulse: 'パルス',\n            ROBOID_unit_deg: '度',\n            ROBOID_left: '左',\n            ROBOID_right: '右',\n            ROBOID_both: '両',\n            ROBOID_head: '前',\n            ROBOID_tail: '後',\n            ROBOID_all: 'すべて',\n            ROBOID_led_left_head: '左前',\n            ROBOID_led_right_head: '右前',\n            ROBOID_led_left_tail: '左後',\n            ROBOID_led_right_tail: '右後',\n            ROBOID_sound_beep: 'ビープ',\n            ROBOID_sound_random_beep: 'ランダムビープ',\n            ROBOID_sound_noise: 'ノイズ',\n            ROBOID_sound_siren: 'サイレン',\n            ROBOID_sound_engine: 'エンジン',\n            ROBOID_sound_chop: 'チョップ',\n            ROBOID_sound_robot: 'ロボット',\n            ROBOID_sound_dibidibidip: 'ディバディバディップ',\n            ROBOID_sound_good_job: 'よくやった',\n            ROBOID_sound_happy: '幸福',\n            ROBOID_sound_angry: '怒った',\n            ROBOID_sound_sad: '悲しみ',\n            ROBOID_sound_sleep: '睡眠',\n            ROBOID_sound_march: '行進',\n            ROBOID_sound_birthday: '誕生',\n            ROBOID_note_c: 'ド',\n            ROBOID_note_c_sharp: 'ド♯(レ♭)',\n            ROBOID_note_d: 'レ',\n            ROBOID_note_d_sharp: 'レ♯(ミ♭)',\n            ROBOID_note_e: 'ミ',\n            ROBOID_note_f: 'ファ',\n            ROBOID_note_f_sharp: 'ファ♯(ソ♭)',\n            ROBOID_note_g: 'ソ',\n            ROBOID_note_g_sharp: 'ソ♯(ラ♭)',\n            ROBOID_note_a: 'ラ',\n            ROBOID_note_a_sharp: 'ラ♯(シ♭)',\n            ROBOID_note_b: 'シ',\n        },\n    },\n    vn: {\n        template: {\n            zerone_is_gesture: 'gesture %1?',\n            zerone_touching_color: 'touching %1?',\n            zerone_is_color_pattern: 'color pattern %1 %2 ?',\n            zerone_button_state: 'button %1 ?',\n            zerone_boolean: 'battery %1?',\n            zerone_value: '%1',\n            zerone_move_forward_unit: 'move forward %1 %2 %3',\n            zerone_move_backward_unit: 'move backward %1 %2 %3',\n            zerone_turn_unit_in_place: 'turn %1 %2 %3 in place %4',\n            zerone_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n            zerone_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n            zerone_change_wheel_by: 'change %1 wheel by %2 %3',\n            zerone_set_wheel_to: 'set %1 wheel to %2 %3',\n            zerone_follow_line: 'follow line %1',\n            zerone_follow_line_until: 'follow line until %1 %2',\n            zerone_follow_line_until_intersection: 'follow line until intersection %1',\n            zerone_cross_intersection: 'cross intersection %1',\n            zerone_turn_at_intersection: 'turn %1 at intersection %2',\n            zerone_jump_line: 'jump to %1 line %2',\n            zerone_set_following_speed_to: 'set following speed to %1 %2',\n            zerone_stop: 'stop %1',\n            zerone_set_led_to: 'set %1 led to %2 %3',\n            zerone_pick_led: 'set %1 led to %2 %3',\n            zerone_change_led_by_rgb: 'change %1 led by r: %2 g: %3 b: %4 %5',\n            zerone_set_led_to_rgb: 'set %1 led to r: %2 g: %3 b: %4 %5',\n            zerone_clear_led: 'clear %1 led %2',\n            zerone_play_sound_times: 'play sound %1 %2 times %3',\n            zerone_play_sound_times_until_done: 'play sound %1 %2 times until done %3',\n            zerone_change_buzzer_by: 'change buzzer by %1 %2',\n            zerone_set_buzzer_to: 'set buzzer to %1 %2',\n            zerone_clear_sound: 'clear sound %1',\n            zerone_play_note: 'play note %1 %2 %3',\n            zerone_play_note_for: 'play note %1 %2 for %3 beats %4',\n            zerone_rest_for: 'rest for %1 beats %2',\n            zerone_change_tempo_by: 'change tempo by %1 %2',\n            zerone_set_tempo_to: 'set tempo to %1 bpm %2',\n        },\n        Helper: {\n            zerone_is_gesture:\n                'If the gesture sensor detects the selected gesture, true, otherwise false.',\n            zerone_touching_color:\n                'If the color sensor detects the selected color, true, otherwise false.',\n            zerone_is_color_pattern: 'If the color sensor detects the selected color pattern, true, otherwise false.',\n            zerone_button_state: 'If the button clicked/double-clicked/long-pressed, true, otherwise false.',\n            zerone_boolean:\n                'battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n            zerone_value:\n                'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>front proximity: value of front proximity sensor (range: 0 to 255, initial value: 0)<br/>rear proximity: value of rear proximity sensor (range: 0 to 255, initial value: 0)<br/>gesture: gesture number detected by the gesture sensor (range: -1 ~ 6, initial value: -1)<br/>color number: color number detected by the color sensor (range: -1 to 6, initial value: -1)<br/>color r: red component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color g: green component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>color b: blue component of color detected by the color sensor (range: 0 ~ 255, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.',\n            zerone_move_forward_unit: 'Moves forward for the number of cm/seconds/pulses entered.',\n            zerone_move_backward_unit:\n                'Moves backward for the number of cm/seconds/pulses entered.',\n            zerone_turn_unit_in_place:\n                'Turns left/right in place for the number of degrees/seconds/pulses entered.',\n            zerone_change_both_wheels_by:\n                'Adds the entered values to the current velocity values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            zerone_set_both_wheels_to:\n                'Sets the velocity of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            zerone_change_wheel_by:\n                'Adds the entered value to the current velocity value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n            zerone_set_wheel_to:\n                'Sets the velocity of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n            zerone_follow_line: 'Moves along the black line on a white background.',\n            zerone_follow_line_until: 'Moves along the black line on a white background and stops when the color sensor detects the selected color.',\n            zerone_follow_line_until_intersection: 'Moves along the black line on a white background and stops when the color sensor detects the black intersection.',\n            zerone_cross_intersection: 'Moves forward for a moment at the black intersection, then finds the black line.',\n            zerone_turn_at_intersection: 'Moves forward for a moment at the black intersection, then turns left/right/back in place and finds the black line.',\n            zerone_jump_line: 'Turns left/right 90 degrees in place and moves forward. Stops when the color sensor detects the black line and turns to its original direction.',\n            zerone_set_following_speed_to: 'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n            zerone_stop: 'Stops both wheels.',\n            zerone_set_led_to: 'Turns the selected LED to the selected color.',\n            zerone_pick_led: 'Turns the selected LED to the selected color.',\n            zerone_change_led_by_rgb:\n                'Adds the entered values to the current R, G, B values of the selected LED, respectively.',\n            zerone_set_led_to_rgb:\n                'Sets the R, G, B values of the selected LED to the entered values.',\n            zerone_clear_led: 'Turns off the selected LED.',\n            zerone_play_sound_times: 'Plays the selected sound as many times as entered.',\n            zerone_play_sound_times_until_done:\n                'Plays the selected sound as many times as entered, and waits for completion.',\n            zerone_change_buzzer_by:\n                'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to one decimal place.',\n            zerone_set_buzzer_to:\n                'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to one decimal place. Entering the number 0 turns off the buzzer sound.',\n            zerone_clear_sound: 'Turns off sound.',\n            zerone_play_note: 'It sounds the selected tone and octave.',\n            zerone_play_note_for:\n                'It sounds the selected tone and octave as much as the beat you entered.',\n            zerone_rest_for: 'Rests as much as the beat you entered.',\n            zerone_change_tempo_by:\n                'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n            zerone_set_tempo_to:\n                'Sets the playing or resting speed to the entered BPM (beats per minute).',\n        },\n        Blocks: {\n            ROBOID_monitor_buzzer: 'buzzer',\n            ROBOID_monitor_note: 'note',\n            ROBOID_monitor_left_wheel: 'left wheel',\n            ROBOID_monitor_right_wheel: 'right wheel',\n            ROBOID_monitor_left_head_led: 'left head led',\n            ROBOID_monitor_right_head_led: 'right head led',\n            ROBOID_monitor_left_tail_led: 'left tail led',\n            ROBOID_monitor_right_tail_led: 'right tail led',\n            ROBOID_gesture_forward: 'forward',\n            ROBOID_gesture_backward: 'backward',\n            ROBOID_gesture_leftward: 'leftward',\n            ROBOID_gesture_rightward: 'rightward',\n            ROBOID_gesture_near: 'near',\n            ROBOID_gesture_far: 'far',\n            ROBOID_gesture_click: 'click',\n            ROBOID_gesture_long_touch: 'long touch',\n            ROBOID_color_red: 'red',\n            ROBOID_color_orange: 'orange',\n            ROBOID_color_yellow: 'yellow',\n            ROBOID_color_green: 'green',\n            ROBOID_color_sky_blue: 'sky blue',\n            ROBOID_color_blue: 'blue',\n            ROBOID_color_violet: 'violet',\n            ROBOID_color_purple: 'purple',\n            ROBOID_color_white: 'white',\n            ROBOID_color_black: 'black',\n            ROBOID_color_any: 'any color',\n            ROBOID_clicked: 'clicked',\n            ROBOID_double_clicked: 'double-clicked',\n            ROBOID_long_pressed: 'long-pressed',\n            ROBOID_battery_state_normal: 'normal',\n            ROBOID_battery_state_low: 'low',\n            ROBOID_battery_state_empty: 'empty',\n            ROBOID_sensor_left_proximity: 'left proximity',\n            ROBOID_sensor_right_proximity: 'right proximity',\n            ROBOID_sensor_front_proximity: 'front proximity',\n            ROBOID_sensor_rear_proximity: 'rear proximity',\n            ROBOID_sensor_gesture: 'gesture',\n            ROBOID_sensor_color_number: 'color number',\n            ROBOID_sensor_color_pattern: 'color pattern',\n            ROBOID_sensor_color_r: 'color r',\n            ROBOID_sensor_color_g: 'color g',\n            ROBOID_sensor_color_b: 'color b',\n            ROBOID_sensor_floor: 'floor',\n            ROBOID_sensor_button: 'button',\n            ROBOID_sensor_signal_strength: 'signal strength',\n            ROBOID_gesture: 'gesture',\n            ROBOID_color: 'color',\n            ROBOID_unit_cm: 'cm',\n            ROBOID_unit_sec: 'seconds',\n            ROBOID_unit_pulse: 'pulses',\n            ROBOID_unit_deg: 'degrees',\n            ROBOID_left: 'left',\n            ROBOID_right: 'right',\n            ROBOID_both: 'both',\n            ROBOID_head: 'head',\n            ROBOID_tail: 'tail',\n            ROBOID_all: 'all',\n            ROBOID_led_left_head: 'left head',\n            ROBOID_led_right_head: 'right head',\n            ROBOID_led_left_tail: 'left tail',\n            ROBOID_led_right_tail: 'right tail',\n            ROBOID_sound_beep: 'beep',\n            ROBOID_sound_random_beep: 'random beep',\n            ROBOID_sound_noise: 'noise',\n            ROBOID_sound_siren: 'siren',\n            ROBOID_sound_engine: 'engine',\n            ROBOID_sound_chop: 'chop',\n            ROBOID_sound_robot: 'robot',\n            ROBOID_sound_dibidibidip: 'dibidibidip',\n            ROBOID_sound_good_job: 'good job',\n            ROBOID_sound_happy: 'happy',\n            ROBOID_sound_angry: 'angry',\n            ROBOID_sound_sad: 'sad',\n            ROBOID_sound_sleep: 'sleep',\n            ROBOID_sound_march: 'march',\n            ROBOID_sound_birthday: 'birthday',\n            ROBOID_note_c: 'C',\n            ROBOID_note_c_sharp: 'C♯(D♭)',\n            ROBOID_note_d: 'D',\n            ROBOID_note_d_sharp: 'D♯(E♭)',\n            ROBOID_note_e: 'E',\n            ROBOID_note_f: 'F',\n            ROBOID_note_f_sharp: 'F♯(G♭)',\n            ROBOID_note_g: 'G',\n            ROBOID_note_g_sharp: 'G♯(A♭)',\n            ROBOID_note_a: 'A',\n            ROBOID_note_a_sharp: 'A♯(B♭)',\n            ROBOID_note_b: 'B',\n        },\n    },\n});\n\nEntry.Zerone.blockMenuBlocks = [\n    'zerone_value',\n    'zerone_is_gesture',\n    'zerone_touching_color',\n    'zerone_is_color_pattern',\n    'zerone_button_state',\n    'zerone_boolean',\n    'zerone_move_forward_unit',\n    'zerone_move_backward_unit',\n    'zerone_turn_unit_in_place',\n    'zerone_change_both_wheels_by',\n    'zerone_set_both_wheels_to',\n    'zerone_change_wheel_by',\n    'zerone_set_wheel_to',\n    'zerone_follow_line',\n    'zerone_follow_line_until',\n    'zerone_follow_line_until_intersection',\n    'zerone_cross_intersection',\n    'zerone_turn_at_intersection',\n    'zerone_jump_line',\n    'zerone_set_following_speed_to',\n    'zerone_stop',\n    'zerone_set_led_to',\n    'zerone_pick_led',\n    'zerone_change_led_by_rgb',\n    'zerone_set_led_to_rgb',\n    'zerone_clear_led',\n    'zerone_play_sound_times',\n    'zerone_play_sound_times_until_done',\n    'zerone_change_buzzer_by',\n    'zerone_set_buzzer_to',\n    'zerone_clear_sound',\n    'zerone_play_note',\n    'zerone_play_note_for',\n    'zerone_rest_for',\n    'zerone_change_tempo_by',\n    'zerone_set_tempo_to',\n];\n\nEntry.Zerone.getBlocks = function() {\n    return {\n        zerone_value: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_string_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                        [Lang.Blocks.ROBOID_sensor_right_proximity, 'RIGHT_PROXIMITY'],\n                        [Lang.Blocks.ROBOID_sensor_front_proximity, 'FRONT_PROXIMITY'],\n                        [Lang.Blocks.ROBOID_sensor_rear_proximity, 'REAR_PROXIMITY'],\n                        [Lang.Blocks.ROBOID_sensor_gesture, 'GESTURE'],\n                        [Lang.Blocks.ROBOID_sensor_color_number, 'COLOR_NUMBER'],\n                        [Lang.Blocks.ROBOID_sensor_color_pattern, 'COLOR_PATTERN'],\n                        [Lang.Blocks.ROBOID_sensor_color_r, 'COLOR_R'],\n                        [Lang.Blocks.ROBOID_sensor_color_g, 'COLOR_G'],\n                        [Lang.Blocks.ROBOID_sensor_color_b, 'COLOR_B'],\n                        [Lang.Blocks.ROBOID_sensor_floor, 'FLOOR'],\n                        [Lang.Blocks.ROBOID_sensor_button, 'BUTTON'],\n                        [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                    ],\n                    value: 'LEFT_PROXIMITY',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_value',\n            },\n            paramsKeyMap: {\n                DEVICE: 0,\n            },\n            class: 'zerone_sensor',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                if (robot) {\n                    return robot.getValue(script);\n                }\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.sensor_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sensor_left_proximity, 'LEFT_PROXIMITY'],\n                                    [Lang.Blocks.ROBOID_sensor_right_proximity, 'RIGHT_PROXIMITY'],\n                                    [Lang.Blocks.ROBOID_sensor_front_proximity, 'FRONT_PROXIMITY'],\n                                    [Lang.Blocks.ROBOID_sensor_rear_proximity, 'REAR_PROXIMITY'],\n                                    [Lang.Blocks.ROBOID_sensor_gesture, 'GESTURE'],\n                                    [Lang.Blocks.ROBOID_sensor_color_number, 'COLOR_NUMBER'],\n                                    [Lang.Blocks.ROBOID_sensor_color_pattern, 'COLOR_PATTERN'],\n                                    [Lang.Blocks.ROBOID_sensor_color_r, 'COLOR_R'],\n                                    [Lang.Blocks.ROBOID_sensor_color_g, 'COLOR_G'],\n                                    [Lang.Blocks.ROBOID_sensor_color_b, 'COLOR_B'],\n                                    [Lang.Blocks.ROBOID_sensor_floor, 'FLOOR'],\n                                    [Lang.Blocks.ROBOID_sensor_button, 'BUTTON'],\n                                    [Lang.Blocks.ROBOID_sensor_signal_strength, 'SIGNAL_STRENGTH'],\n                                ],\n                                value: 'LEFT_PROXIMITY',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_is_gesture: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_gesture_forward, 'FORWARD'],\n                        [Lang.Blocks.ROBOID_gesture_backward, 'BACKWARD'],\n                        [Lang.Blocks.ROBOID_gesture_leftward, 'LEFTWARD'],\n                        [Lang.Blocks.ROBOID_gesture_rightward, 'RIGHTWARD'],\n                        [Lang.Blocks.ROBOID_gesture_near, 'NEAR'],\n                        [Lang.Blocks.ROBOID_gesture_far, 'FAR'],\n                        [Lang.Blocks.ROBOID_gesture_long_touch, 'LONG_TOUCH'],\n                    ],\n                    value: 'FORWARD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_is_gesture',\n            },\n            paramsKeyMap: {\n                GESTURE: 0,\n            },\n            class: 'zerone_sensor',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.checkGesture(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.is_gesture(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_gesture_forward, 'FORWARD'],\n                                    [Lang.Blocks.ROBOID_gesture_backward, 'BACKWARD'],\n                                    [Lang.Blocks.ROBOID_gesture_leftward, 'LEFTWARD'],\n                                    [Lang.Blocks.ROBOID_gesture_rightward, 'RIGHTWARD'],\n                                    [Lang.Blocks.ROBOID_gesture_near, 'NEAR'],\n                                    [Lang.Blocks.ROBOID_gesture_far, 'FAR'],\n                                    [Lang.Blocks.ROBOID_gesture_long_touch, 'LONG_TOUCH'],\n                                ],\n                                value: 'FORWARD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_touching_color: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_touching_color',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'zerone_sensor',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.checkTouchingColor(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.is_color(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_is_color_pattern: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                    ],\n                    value: 'BLACK',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'zerone_is_color_pattern',\n            },\n            paramsKeyMap: {\n                COLOR1: 0,\n                COLOR2: 1,\n            },\n            class: 'zerone_sensor',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.checkColorPattern(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.is_color_pattern(%1, %2)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                ],\n                                value: 'BLACK',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_black, 'BLACK'],\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_button_state: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                        [Lang.Blocks.ROBOID_double_clicked, 'DOUBLE_CLICKED'],\n                        [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                    ],\n                    value: 'CLICKED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_button_state',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'zerone_sensor',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.checkButtonState(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.is_button(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_clicked, 'CLICKED'],\n                                    [Lang.Blocks.ROBOID_double_clicked, 'DOUBLE_CLICKED'],\n                                    [Lang.Blocks.ROBOID_long_pressed, 'LONG_PRESSED'],\n                                ],\n                                value: 'CLICKED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_boolean: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#fff',\n            skeleton: 'basic_boolean_field',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_battery_state_normal, 'BATTERY_NORMAL'],\n                        [Lang.Blocks.ROBOID_battery_state_low, 'BATTERY_LOW'],\n                        [Lang.Blocks.ROBOID_battery_state_empty, 'BATTERY_EMPTY'],\n                    ],\n                    value: 'BATTERY_NORMAL',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            events: {},\n            def: {\n                params: [],\n                type: 'zerone_boolean',\n            },\n            paramsKeyMap: {\n                STATE: 0,\n            },\n            class: 'zerone_sensor',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.checkBoolean(script) : false;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.boolean_value(%1)',\n                        blockType: 'param',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_battery_state_normal, 'BATTERY_NORMAL'],\n                                    [Lang.Blocks.ROBOID_battery_state_low, 'BATTERY_LOW'],\n                                    [Lang.Blocks.ROBOID_battery_state_empty, 'BATTERY_EMPTY'],\n                                ],\n                                value: 'BATTERY_NORMAL',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_move_forward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'zerone_move_forward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.moveForwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.move_forward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_move_backward_unit: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'CM',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['6'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'zerone_move_backward_unit',\n            },\n            paramsKeyMap: {\n                VALUE: 0,\n                UNIT: 1,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.moveBackwardUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.move_backward(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_cm, 'CM'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'CM',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_turn_unit_in_place: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                        [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                        [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                    ],\n                    value: 'DEG',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['90'],\n                    },\n                    null,\n                    null,\n                ],\n                type: 'zerone_turn_unit_in_place',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n                VALUE: 1,\n                UNIT: 2,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.turnUnit(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.turn(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_unit_deg, 'DEG'],\n                                    [Lang.Blocks.ROBOID_unit_sec, 'SEC'],\n                                    [Lang.Blocks.ROBOID_unit_pulse, 'PULSE'],\n                                ],\n                                value: 'DEG',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_change_both_wheels_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'zerone_change_both_wheels_by',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.changeWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.add_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_set_both_wheels_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'zerone_set_both_wheels_to',\n            },\n            paramsKeyMap: {\n                LEFT: 0,\n                RIGHT: 1,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.setWheels(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.set_wheels(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_change_wheel_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'zerone_change_wheel_by',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.changeWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.add_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_set_wheel_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_both, 'BOTH'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['50'],\n                    },\n                    null,\n                ],\n                type: 'zerone_set_wheel_to',\n            },\n            paramsKeyMap: {\n                WHEEL: 0,\n                VELOCITY: 1,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.setWheel(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.set_wheel(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_both, 'BOTH'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_follow_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_follow_line',\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.followLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.follow_line()',\n                    },\n                ],\n            },\n        },\n        zerone_follow_line_until: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_any, 'ANY'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'zerone_follow_line_until',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.followLineUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.follow_line_until(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_any, 'ANY'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_follow_line_until_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_follow_line_until_intersection',\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.followLineUntilIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.follow_line_until_cross()',\n                    },\n                ],\n            },\n        },\n        zerone_cross_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_cross_intersection',\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.crossIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.cross_forward()',\n                    },\n                ],\n            },\n        },\n        zerone_turn_at_intersection: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_back, 'BACK'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'zerone_turn_at_intersection',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.turnAtIntersection(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.cross_turn(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_back, 'BACK'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_jump_line: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                    ],\n                    value: 'LEFT',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'zerone_jump_line',\n            },\n            paramsKeyMap: {\n                DIRECTION: 0,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.jumpLine(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.jump_line(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                ],\n                                value: 'LEFT',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_set_following_speed_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                        ['8', '8'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: ['4', null],\n                type: 'zerone_set_following_speed_to',\n            },\n            paramsKeyMap: {\n                SPEED: 0,\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.setLineTracerSpeed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.set_line_speed(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                    ['8', '8'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_stop',\n            },\n            class: 'zerone_wheel',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.stop(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.stop()',\n                    },\n                ],\n            },\n        },\n        zerone_set_led_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                        [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_head, 'HEAD'],\n                        [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                        [Lang.Blocks.ROBOID_all, 'ALL'],\n                    ],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_color_red, 'RED'],\n                        [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                        [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                        [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                        [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                        [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                        [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                        [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                        [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                    ],\n                    value: 'RED',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'zerone_set_led_to',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },\n            class: 'zerone_led',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.setLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.set_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                                    [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_head, 'HEAD'],\n                                    [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                                    [Lang.Blocks.ROBOID_all, 'ALL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_color_red, 'RED'],\n                                    [Lang.Blocks.ROBOID_color_orange, 'ORANGE'],\n                                    [Lang.Blocks.ROBOID_color_yellow, 'YELLOW'],\n                                    [Lang.Blocks.ROBOID_color_green, 'GREEN'],\n                                    [Lang.Blocks.ROBOID_color_sky_blue, 'SKY_BLUE'],\n                                    [Lang.Blocks.ROBOID_color_blue, 'BLUE'],\n                                    [Lang.Blocks.ROBOID_color_violet, 'VIOLET'],\n                                    [Lang.Blocks.ROBOID_color_purple, 'PURPLE'],\n                                    [Lang.Blocks.ROBOID_color_white, 'WHITE'],\n                                ],\n                                value: 'RED',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_pick_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                        [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_head, 'HEAD'],\n                        [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                        [Lang.Blocks.ROBOID_all, 'ALL'],\n                    ],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Color',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null, null],\n                type: 'zerone_pick_led',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                COLOR: 1,\n            },\n            class: 'zerone_led',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.pickLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.pick_led(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                                    [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_head, 'HEAD'],\n                                    [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                                    [Lang.Blocks.ROBOID_all, 'ALL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Color',\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_change_led_by_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                        [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_head, 'HEAD'],\n                        [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                        [Lang.Blocks.ROBOID_all, 'ALL'],\n                    ],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'zerone_change_led_by_rgb',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'zerone_led',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.changeRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.add_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                                    [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_head, 'HEAD'],\n                                    [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                                    [Lang.Blocks.ROBOID_all, 'ALL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_set_led_to_rgb: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                        [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_head, 'HEAD'],\n                        [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                        [Lang.Blocks.ROBOID_all, 'ALL'],\n                    ],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['255'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    {\n                        type: 'text',\n                        params: ['0'],\n                    },\n                    null,\n                ],\n                type: 'zerone_set_led_to_rgb',\n            },\n            paramsKeyMap: {\n                LED: 0,\n                RED: 1,\n                GREEN: 2,\n                BLUE: 3,\n            },\n            class: 'zerone_led',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.setRgb(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.set_rgb(%1, %2, %3, %4)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                                    [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_head, 'HEAD'],\n                                    [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                                    [Lang.Blocks.ROBOID_all, 'ALL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_clear_led: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                        [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                        [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                        [Lang.Blocks.ROBOID_left, 'LEFT'],\n                        [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                        [Lang.Blocks.ROBOID_head, 'HEAD'],\n                        [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                        [Lang.Blocks.ROBOID_all, 'ALL'],\n                    ],\n                    value: 'HEAD',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, null],\n                type: 'zerone_clear_led',\n            },\n            paramsKeyMap: {\n                LED: 0,\n            },\n            class: 'zerone_led',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.clearLed(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.clear_led(%1)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_led_left_head, 'LEFT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_right_head, 'RIGHT_HEAD'],\n                                    [Lang.Blocks.ROBOID_led_left_tail, 'LEFT_TAIL'],\n                                    [Lang.Blocks.ROBOID_led_right_tail, 'RIGHT_TAIL'],\n                                    [Lang.Blocks.ROBOID_left, 'LEFT'],\n                                    [Lang.Blocks.ROBOID_right, 'RIGHT'],\n                                    [Lang.Blocks.ROBOID_head, 'HEAD'],\n                                    [Lang.Blocks.ROBOID_tail, 'TAIL'],\n                                    [Lang.Blocks.ROBOID_all, 'ALL'],\n                                ],\n                                value: 'HEAD',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_play_sound_times: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'zerone_play_sound_times',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.playSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.play_sound(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_play_sound_times_until_done: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                        [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                        [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                        [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                        [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                        [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                        [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                        [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                        [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                        [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                        [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                        [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                        [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                        [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                        [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                    ],\n                    value: 'BEEP',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                    null,\n                ],\n                type: 'zerone_play_sound_times_until_done',\n            },\n            paramsKeyMap: {\n                SOUND: 0,\n                COUNT: 1,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.playSoundUntil(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.play_sound_until_done(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_sound_beep, 'BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_random_beep, 'RANDOM_BEEP'],\n                                    [Lang.Blocks.ROBOID_sound_noise, 'NOISE'],\n                                    [Lang.Blocks.ROBOID_sound_siren, 'SIREN'],\n                                    [Lang.Blocks.ROBOID_sound_engine, 'ENGINE'],\n                                    [Lang.Blocks.ROBOID_sound_chop, 'CHOP'],\n                                    [Lang.Blocks.ROBOID_sound_robot, 'ROBOT'],\n                                    [Lang.Blocks.ROBOID_sound_dibidibidip, 'DIBIDIBIDIP'],\n                                    [Lang.Blocks.ROBOID_sound_good_job, 'GOOD_JOB'],\n                                    [Lang.Blocks.ROBOID_sound_happy, 'HAPPY'],\n                                    [Lang.Blocks.ROBOID_sound_angry, 'ANGRY'],\n                                    [Lang.Blocks.ROBOID_sound_sad, 'SAD'],\n                                    [Lang.Blocks.ROBOID_sound_sleep, 'SLEEP'],\n                                    [Lang.Blocks.ROBOID_sound_march, 'MARCH'],\n                                    [Lang.Blocks.ROBOID_sound_birthday, 'BIRTHDAY'],\n                                ],\n                                value: 'BEEP',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_change_buzzer_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['10'],\n                    },\n                    null,\n                ],\n                type: 'zerone_change_buzzer_by',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.changeBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.add_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        zerone_set_buzzer_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['1000'],\n                    },\n                    null,\n                ],\n                type: 'zerone_set_buzzer_to',\n            },\n            paramsKeyMap: {\n                HZ: 0,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.setBuzzer(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.set_buzzer(%1)',\n                    },\n                ],\n            },\n        },\n        zerone_clear_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null],\n                type: 'zerone_clear_sound',\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.clearSound(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.clear_sound()',\n                        params: [null],\n                    },\n                ],\n            },\n        },\n        zerone_play_note: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [null, '4', null],\n                type: 'zerone_play_note',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.playNote(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.play_pitch(%1, %2)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_play_note_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROBOID_note_c, 'C'],\n                        [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                        [Lang.Blocks.ROBOID_note_d, 'D'],\n                        [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                        [Lang.Blocks.ROBOID_note_e, 'E'],\n                        [Lang.Blocks.ROBOID_note_f, 'F'],\n                        [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                        [Lang.Blocks.ROBOID_note_g, 'G'],\n                        [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                        [Lang.Blocks.ROBOID_note_a, 'A'],\n                        [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                        [Lang.Blocks.ROBOID_note_b, 'B'],\n                    ],\n                    value: 'C',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        ['1', '1'],\n                        ['2', '2'],\n                        ['3', '3'],\n                        ['4', '4'],\n                        ['5', '5'],\n                        ['6', '6'],\n                        ['7', '7'],\n                    ],\n                    value: '1',\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    null,\n                    '4',\n                    {\n                        type: 'text',\n                        params: ['0.5'],\n                    },\n                    null,\n                ],\n                type: 'zerone_play_note_for',\n            },\n            paramsKeyMap: {\n                NOTE: 0,\n                OCTAVE: 1,\n                BEAT: 2,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.playNoteBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.play_note(%1, %2, %3)',\n                        textParams: [\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    [Lang.Blocks.ROBOID_note_c, 'C'],\n                                    [Lang.Blocks.ROBOID_note_c_sharp, 'C#'],\n                                    [Lang.Blocks.ROBOID_note_d, 'D'],\n                                    [Lang.Blocks.ROBOID_note_d_sharp, 'D#'],\n                                    [Lang.Blocks.ROBOID_note_e, 'E'],\n                                    [Lang.Blocks.ROBOID_note_f, 'F'],\n                                    [Lang.Blocks.ROBOID_note_f_sharp, 'F#'],\n                                    [Lang.Blocks.ROBOID_note_g, 'G'],\n                                    [Lang.Blocks.ROBOID_note_g_sharp, 'G#'],\n                                    [Lang.Blocks.ROBOID_note_a, 'A'],\n                                    [Lang.Blocks.ROBOID_note_a_sharp, 'A#'],\n                                    [Lang.Blocks.ROBOID_note_b, 'B'],\n                                ],\n                                value: 'C',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringValue,\n                            },\n                            {\n                                type: 'Dropdown',\n                                options: [\n                                    ['1', '1'],\n                                    ['2', '2'],\n                                    ['3', '3'],\n                                    ['4', '4'],\n                                    ['5', '5'],\n                                    ['6', '6'],\n                                    ['7', '7'],\n                                ],\n                                value: '1',\n                                fontSize: 11,\n                                bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                converter: Entry.block.converters.returnStringOrNumberByValue,\n                            },\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_rest_for: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['0.25'],\n                    },\n                    null,\n                ],\n                type: 'zerone_rest_for',\n            },\n            paramsKeyMap: {\n                BEAT: 0,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.restBeat(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.rest(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_change_tempo_by: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['20'],\n                    },\n                    null,\n                ],\n                type: 'zerone_change_tempo_by',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.changeTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.add_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n        zerone_set_tempo_to: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            skeleton: 'basic',\n            statements: [],\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            events: {},\n            def: {\n                params: [\n                    {\n                        type: 'text',\n                        params: ['60'],\n                    },\n                    null,\n                ],\n                type: 'zerone_set_tempo_to',\n            },\n            paramsKeyMap: {\n                BPM: 0,\n            },\n            class: 'zerone_sound',\n            isNotFor: ['zerone'],\n            func(sprite, script) {\n                const robot = Entry.Zerone.getRobot();\n                return robot ? robot.setTempo(script) : script;\n            },\n            syntax: {\n                js: [],\n                py: [\n                    {\n                        syntax: 'Zerone.set_tempo(%1)',\n                        textParams: [\n                            {\n                                type: 'Block',\n                                accept: 'string',\n                            },\n                        ],\n                    },\n                ],\n            },\n        },\n    };\n};\n\nmodule.exports = Entry.Zerone;\n"
  },
  {
    "path": "src/playground/blocks/hardware/block_zumiMini.js",
    "content": "'use strict';\n\nvar firstRun = false;\nvar exCnt = 0, tempCnt = 0;\n\nEntry.ZumiMini = {\n    id: '4A.5',\n    name: 'zumi_mini', // isNotFor 속성과 대소문자까지 정확하게 매치되어야 합니다.\n    url: 'http://www.robolink.co.kr/', // 생략 가능합니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    imageName: 'robolink_zumiMini.png', // images/hardware 폴더 내에 존재하는 이미지입니다. 엔트리 사이트에서 홍보시 사용됩니다.\n    title: {\n        ko: '로보링크 주미미니',\n        en: 'Robolink zumi mini',\n    },\n\n    setZero: function() {\n\n        console.log(\"engine set Zero..\");\n        Entry.hw.sendQueue['req'] = 0x00;\n        Entry.hw.sendQueue['com'] = 0x00;\n        Entry.hw.sendQueue['speed'] = 0x00;\n        Entry.hw.sendQueue['dir'] = 0x00;\n        Entry.hw.update();\n        exCnt = tempCnt;\n        //console.log(\"exCnt:\" + exCnt);\n    },\n\n    afterReceive(pd) {\n\n        const Z_WAIT = 0;\n        const Z_SEND_PACKET = 1;\n        const Z_MOVING = 2;\n\n        const READY = 0;\n        const PROCESS = 1;\n\n        const COMMAND_MOTION_STOP = 25;\n\n        var pStep = Z_WAIT;\n        var iter = 0;\n\n        //temCnt = Entry.hw.portData.inputData.euler['ROLL'];\n        //console.log(\"exCnt: \" + exCnt);\n\n\n        if (Entry.engine.isState('run')) {\n            //console.log(\"engine running..\");\n            firstRun = false;\n            tempCnt++;\n            //console.log(\"tempCnt: \" + tempCnt);\n        }\n        else if (Entry.engine.isState('stop')) {\n            //Entry.hw.sendQueue['req'] = 0x00;\n            //Entry.hw.sendQueue['com'] = 0xF0;\n            //Entry.hw.update();\n            //console.log(\"engine stop..\");\n            if(firstRun == false)\n            {\n                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                if ((pStep == Z_WAIT) && (_stat == READY)) {\n                    pStep = Z_SEND_PACKET;\n                    console.log(\"ready start\");\n                    firstRun = true;\n                }\n                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) {\n                    pStep = Z_WAIT;    //wait until other action ends.\n                    console.log(\"not ready\");\n                }\n\n                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                    if (iter < 5) {\n                        Entry.hw.sendQueue['com'] = COMMAND_MOTION_STOP;\n                        Entry.hw.update();\n                        console.log(\"send protocol\");\n                    }\n                    else {\n                        Entry.hw.sendQueue['com'] = 0x00;\n                        Entry.hw.update();\n                    }\n                    pStep = Z_SEND_PACKET;\n                    //iter++;\n                }\n            }\n            else {\n                Entry.hw.sendQueue['com'] = 0x00;\n                Entry.hw.update();\n            }\n        }\n    }\n};\n\n// 언어 적용\nEntry.ZumiMini.setLanguage = function () {\n    return {\n        ko: {\n            Blocks: {\n                FL: '왼쪽',\n                FR: '오른쪽',\n                BL: '왼쪽',\n                BM: '가운데',\n                BR: '오른쪽',\n                COLOR: '색상',\n                AI_RED: '빨강',\n                AI_ORANGE: '주황',\n                AI_YELLOW: '노랑',\n                AI_GREEN: '녹색',\n                AI_CYAN: '청록',\n                AI_BLUE: '파랑',\n                AI_PURPLE: '보라',\n                RED: '빨강',\n                GREEN: '녹색',\n                BLUE: '파랑',\n                YELLOW: '노랑',\n                SKY_BLUE: '청록',\n                PINK: '분홍',\n                WHITE: '하양',\n                LED_NORMAL: '기본',\n                LED_BLINK: '깜빡임',\n                LED_FLICKER: '깜빡임2',\n                LED_DIMMING: '디밍',\n                LED_SUNRISE: '서서히 밝아짐',\n                LED_SUNSET: '서서히 어두워짐',\n                LED_RAINBOW: '무지개',\n                ON: '켜기',\n                OFF: '끄기',\n                CAT: '고양이얼굴',\n                HUMAN: '사람얼굴',\n                DETECT: '감지',\n                CX: 'X좌표',\n                CY: 'Y좌표',\n                ID: '번호',\n                PITCH: '피치',\n                ROLL: '롤',\n                YAW: '요우',\n                FORWARD: '전진',\n                BACKWARD: '후진',\n                RAPID: '빠르게',\n                MID: '보통',\n                SLOW: '느리게',\n                LEFT: '왼쪽',\n                RIGHT: '오른쪽',\n                CAMERA: '카메라',\n                EMOTION: '표정',\n                EMO_CHAOS: '혼란',\n                EMO_SMILE: '미소',\n                EMO_LOVE: '사랑',\n                EMO_CRASH: '안돼!',\n                EMO_SURPRISE: '놀람',\n                EMO_NICE: '신남',\n                EMO_CANTBELIEVE: '미심쩍음',\n                EMO_SLEEP: '졸림',\n                EMO_CRY: '슬픔',\n                EMO_WINK: '윙크',\n                EMO_BLINK: '깜빡깜빡',\n                EMO_SLEEPING: '잠듬',\n                SND_USER: '사용자 녹음',\n                SND_CAT: '고양이',\n                SND_SHUTTER: '셔터',\n                SND_FAIL: '실패',\n                SND_SUCCESS: '성공',\n                SND_FAIL2: '경고',\n                SND_HONK: '경적',\n                SND_HONK2: '경적2',\n                SND_SIREN: '사이렌',\n                M1: '왼쪽 모터',\n                M2: '오른쪽 모터',\n                CW: '전진방향',\n                CCW: '후진방향',\n                STOP: '멈춤',\n                RED_BTN: '빨강버튼',\n                BLUE_BTN: '파랑버튼',\n                YELLOW_BTN: '노랑버튼',\n                GREEN_BTN: '녹색버튼',\n                PRESSED: '눌렀을 때',\n                RELEASED: '눌리지 않았을 때',\n            },\n            template: {\n                go_forward:'앞으로 가기(10cm) %1',\n                go_back: '뒤로 가기(10cm) %1',\n                turn_left: '왼쪽으로 회전 %1',\n                turn_right: '오른쪽으로 회전 %1',\n                going_forward_until_sensing : '물체 감지할 때까지 앞으로 가기 %1',\n                following_line_until_sensing : '교차로 만날 때까지 선 따라가기 %1',\n                front_sensor:  '앞 센서 %1 %2',\n                bottom_sensor: '바닥 센서 %1 %2',\n                button_input: '버튼 입력 %1',\n                button_boolean_input: '%1 이 %2',\n                face_detector: 'AI 얼굴 %1 %2',\n                cat_face_detector: 'AI 고양이 얼굴 %1 %2',\n                face_boolean_detector: '%1 이 감지 되었을 때',\n                color_detector: 'AI 컬러 감지 %1 %2',\n                color_boolean_detector:'%1 이 감지되었을 때',\n                april_detector: '마커 감지 %1 %2',\n                april_boolean_detector: '마커 %1 이 감지되었을 때',\n                IMU_sensor: '자세 측정 %1 %2',\n                move_straight: '이동하기 방향 %1 속도 %2 거리 %3cm %4',\n                move_turn: '회전하기 방향 %1 속도 %2 각도 %3도 %4',\n                following_line_dist: '선 따라가기 속도 %1 거리 %2cm %3',\n                move_straight_infinite: '계속 이동하기 방향 %1 속도 %2 %3',\n                following_line_infinite: '계속 선 따라가기 속도 %1 %2',\n                motion_stop: '이동 멈추기 %1',\n                screen_toggle: '화면 바꾸기 %1 %2',\n                emotion: '표정 변화 %1 %2',\n                play_sound: '소리내기 %1 %2',\n                LED_control: 'LED 불빛 %1 효과 %2 동작 %3 %4',\n                motor_control: '모터 %1 방향 %2 속도 %3 %4',\n                power_info: '배터리 %1',\n            },\n        },\n\n        en: {\n            Blocks: {\n                FL: 'left',\n                FR: 'right',\n                BL: 'left',\n                BM: 'middle',\n                BR: 'right',\n                COLOR: 'color',\n                AI_RED: 'red',\n                AI_ORANGE: 'orange',\n                AI_YELLOW: 'yellow',\n                AI_GREEN: 'green',\n                AI_CYAN: 'cyan',\n                AI_BLUE: 'blue',\n                AI_PURPLE: 'purple',\n                RED: 'red',\n                GREEN: 'green',\n                BLUE: 'blue',\n                YELLOW: 'yellow',\n                SKY_BLUE: 'skyblue',\n                PINK: 'pink',\n                WHITE: 'white',\n                LED_NORMAL: 'normal',\n                LED_BLINK: 'blink',\n                LED_FLICKER: 'flicker',\n                LED_DIMMING: 'dimming',\n                LED_SUNRISE: 'sunrise',\n                LED_SUNSET: 'sunset',\n                LED_RAINBOW: 'rainbow',\n                ON: 'on',\n                OFF: 'off',\n                CAT: 'cat',\n                HUMAN: 'human',\n                DETECT: 'detection',\n                CX: 'X_coordinate',\n                CY: 'Y_coordinate',\n                ID: 'ID',\n                PITCH: 'pitch',\n                ROLL: 'roll',\n                YAW: 'yaw',\n                FORWARD: 'forward',\n                BACKWARD: 'backward',\n                RAPID: 'rapid',\n                MID: 'medium',\n                SLOW: 'slow',\n                LEFT: 'left',\n                RIGHT: 'right',\n                CAMERA: 'camera',\n                EMOTION: 'emotion',\n                EMO_CHAOS: 'chaos',\n                EMO_SMILE: 'smile',\n                EMO_LOVE: 'love',\n                EMO_CRASH: 'no!',\n                EMO_SURPRISE: 'surprise',\n                EMO_NICE: 'joy',\n                EMO_CANTBELIEVE: 'cant believe',\n                EMO_SLEEP: 'sleep',\n                EMO_CRY: 'cry',\n                EMO_WINK: 'wink',\n                EMO_BLINK: 'blink',\n                EMO_SLEEPING: 'sleeping',\n                SND_CAT: 'meow',\n                SND_SHUTTER: 'shutter',\n                SND_FAIL: 'fail',\n                SND_SUCCESS: 'success',\n                SND_FAIL2: 'alarm',\n                SND_HONK: 'horn',\n                SND_HONK2: 'horn2',\n                SND_SIREN: 'siren',\n                M1: 'left motor',\n                M2: 'right motor',\n                CW: 'forward',\n                CCW: 'backward',\n                STOP: 'stop',\n                RED_BTN: 'red button',\n                BLUE_BTN: 'blue button',\n                YELLOW_BTN: 'yellow button',\n                GREEN_BTN: 'green button',\n                PRESSED: 'pressed',\n                RELEASED: 'released',\n            },\n            template: {\n                go_forward:'going forward(10cm) %1',\n                go_back : 'going back(10cm) %1',\n                turn_left : 'turning left %1',\n                turn_right : 'turning right %1',\n                going_forward_until_sensing: 'going forward until sensing the object %1',\n                following_line_until_sensing: 'following the line until meet the intersection %1',\n                front_sensor: 'front sensor %1 %2',\n                bottom_sensor: 'bottom sensor %1 %2',\n                button_input: 'button input %1',\n                button_boolean_input: 'when %1 %2',\n                face_detector: 'AI face %1 %2',\n                cat_face_detector: 'AI cat face %1 %2',\n                face_boolean_detector: 'when %1 is detected',\n                color_detector: 'AI color detection %1 %2',\n                color_boolean_detector:'when %1 is detected',\n                april_detector: 'apriltag detection %1 %2',\n                april_boolean_detector: 'when apriltag %1 is detected',\n                IMU_sensor: ' inertial mesurement %1 %2',\n                move_straight: 'move direction %1 speed %2 distance %3 cm %4',\n                move_turn: 'turn %1 speed %2 degree %3 %4',\n                following_line_dist: 'line following speed %1 distance %2 %3',\n                move_straight_infinite: 'keep moving direction %1 speed %2 %3',\n                following_line_infinite: 'keep following line %1 %2',\n                motion_stop: 'stop moving %1',\n                screen_toggle: 'toggle screen %1 %2',\n                emotion: 'change emotion  %1 %2',\n                play_sound: 'play sound %1 %2',\n                LED_control: 'LED light %1 effect %2 acttion %3 %4',\n                motor_control: 'motor %1 direction %2 speed %3 %4',\n                power_info: 'battery %1',\n            },\n        },\n    };\n};\n\nEntry.ZumiMini.blockMenuBlocks = [\n\n    'motor_control',\n    'move_straight',\n    'move_straight_infinite',\n    'move_turn',\n    'motion_stop',\n\n    'going_forward_until_sensing',\n    'following_line_until_sensing',\n    'following_line_dist',\n    'following_line_infinite',\n\n    'LED_control',\n\n    'button_boolean_input',\n\n    'screen_toggle',\n    'emotion',\n\n    'face_boolean_detector',\n    'color_boolean_detector',\n    'april_boolean_detector',\n\n\n    'front_sensor',\n    'bottom_sensor',\n    'button_input',\n    'face_detector',\n    'cat_face_detector',\n    'color_detector',\n    'april_detector',\n    'power_info',\n];\n\n\nEntry.ZumiMini.getBlocks = function() {\n    return {\n        motion_stop: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                }\n            ],\n            def: {\n                type: \"motion_stop\"\n            },\n            class: \"move\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_MOTION_STOP = 25;\n\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"going turn block Start!\");\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"block skip!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_MOTION_STOP;\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"block exit!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n\n                });\n            },\n        },\n\n        move_straight: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FORWARD, 'FORWARD'],\n                        [Lang.Blocks.BACKWARD, 'BACKWARD'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RAPID, 'RAPID'],\n                        [Lang.Blocks.MID, 'MID'],\n                        [Lang.Blocks.SLOW, 'SLOW']\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                },\n            ],\n            def: {\n                params: ['FORWARD', 'MID', 10, null],\n                type: 'move_straight',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n                SPD: 1,\n                DIST: 2,\n            },\n            class: \"move\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_GO_UNTIL_DIST = 26;\n                const DIR_FORWARD = 0;\n                const DIR_BACKWARD = 1;\n                const SPEED_RAPID = 3;\n                const SPEED_MID = 2;\n                const SPEED_LOW = 1\n\n                //var exTime = new Date();\n                //var firstCheck = true;\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n\n                console.log(\"go until distance block Start!\");\n\n                var _dir = script.getStringField('DIR', script)\n                var _spd = script.getStringField('SPD', script);\n                var _dist = script.getNumberValue('DIST');\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"block skip!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_GO_UNTIL_DIST;\n\n                                        if (_dir == 'FORWARD') Entry.hw.sendQueue['dir'] = DIR_FORWARD;\n                                        else if (_dir == 'BACKWARD') Entry.hw.sendQueue['dir'] = DIR_BACKWARD;\n\n                                        if (_spd == 'RAPID') Entry.hw.sendQueue['speed'] = SPEED_RAPID;\n                                        else if (_spd == 'MID') Entry.hw.sendQueue['speed'] = SPEED_MID;\n                                        else if (_spd == 'SLOW') Entry.hw.sendQueue['speed'] = SPEED_LOW;\n\n                                      //  if (_dist < 20) _dist = 20; else if (_dist > 200) _dist = 200;\n                                        Entry.hw.sendQueue['dist'] = _dist;\n\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"block exit!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    Entry.hw.sendQueue['dir'] = 0x00;\n                                    Entry.hw.sendQueue['speed'] = 0x00;\n                                    Entry.hw.sendQueue['dist'] = 0x00;\n\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n\n                });\n            },\n        },\n\n        following_line_infinite: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RAPID, 'RAPID'],\n                        [Lang.Blocks.MID, 'MID'],\n                        [Lang.Blocks.SLOW, 'SLOW']\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['MID', null],\n                type: 'following_line_infinite',\n            },\n            paramsKeyMap: {\n                SPD: 0,\n            },\n            class: \"sense\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const COMMAND_TRACE_INFINITE = 30;\n                const SPEED_RAPID = 3;\n                const SPEED_MID = 2;\n                const SPEED_LOW = 1;\n\n                console.log(\"go move straight infinite block Start!\");\n\n                var _spd = script.getStringField('SPD', script);\n\n                Entry.hw.sendQueue['com'] = COMMAND_TRACE_INFINITE;\n\n                if (_spd == 'RAPID') Entry.hw.sendQueue['speed'] = SPEED_RAPID;\n                else if (_spd == 'MID') Entry.hw.sendQueue['speed'] = SPEED_MID;\n                else if (_spd == 'SLOW') Entry.hw.sendQueue['speed'] = SPEED_LOW;\n\n                console.log(\"send protocol!\");\n            },\n        },\n\n        move_straight_infinite: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FORWARD, 'FORWARD'],\n                        [Lang.Blocks.BACKWARD, 'BACKWARD'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RAPID, 'RAPID'],\n                        [Lang.Blocks.MID, 'MID'],\n                        [Lang.Blocks.SLOW, 'SLOW']\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['FORWARD', 'MID', null],\n                type: 'move_straight_infinite',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n                SPD: 1,\n            },\n            class: \"move\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const COMMAND_GO_INFINITE = 29;\n                const DIR_FORWARD = 0;\n                const DIR_BACKWARD = 1;\n                const SPEED_RAPID = 3;\n                const SPEED_MID = 2;\n                const SPEED_LOW = 1;\n\n                console.log(\"go move straight infinite block Start!\");\n\n                var _dir = script.getStringField('DIR', script);\n                var _spd = script.getStringField('SPD', script);\n\n                Entry.hw.sendQueue['com'] = COMMAND_GO_INFINITE;\n\n                if (_dir == 'FORWARD') Entry.hw.sendQueue['dir'] = DIR_FORWARD;\n                else if (_dir == 'BACKWARD') Entry.hw.sendQueue['dir'] = DIR_BACKWARD;\n\n                if (_spd == 'RAPID') Entry.hw.sendQueue['speed'] = SPEED_RAPID;\n                else if (_spd == 'MID') Entry.hw.sendQueue['speed'] = SPEED_MID;\n                else if (_spd == 'SLOW') Entry.hw.sendQueue['speed'] = SPEED_LOW;\n\n                console.log(\"send protocol!\");\n            },\n        },\n\n        following_line_dist: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RAPID, 'RAPID'],\n                        [Lang.Blocks.MID, 'MID'],\n                        [Lang.Blocks.SLOW, 'SLOW']\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                },\n            ],\n            def: {\n                params: ['MID', 30, null],\n                type: 'following_line_dist',\n            },\n            paramsKeyMap: {\n                SPD: 0,\n                DIST: 1,\n            },\n            class: \"sense\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_LINE_TRACE_DIST = 28;\n                const SPEED_RAPID = 3;\n                const SPEED_MID = 2;\n                const SPEED_LOW = 1\n\n                //var exTime = new Date();\n                //var firstCheck = true;\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"go following line dist block Start!\");\n\n                var _spd = script.getStringField('SPD', script);\n                var _dist = script.getNumberValue('DIST');\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"block skip!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_LINE_TRACE_DIST;\n\n                                        if (_spd == 'RAPID') Entry.hw.sendQueue['speed'] = SPEED_RAPID;\n                                        else if (_spd == 'MID') Entry.hw.sendQueue['speed'] = SPEED_MID;\n                                        else if (_spd == 'SLOW') Entry.hw.sendQueue['speed'] = SPEED_LOW;\n\n                                        if (_dist < 10) _dist = 10; else if (_dist > 200) _dist = 200;\n                                        Entry.hw.sendQueue['dist'] = _dist;\n\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"block exit!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    Entry.hw.sendQueue['dir'] = 0x00;\n                                    Entry.hw.sendQueue['speed'] = 0x00;\n                                    Entry.hw.sendQueue['dist'] = 0x00;\n\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n                });\n            },\n        },\n\n        move_turn: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.LEFT, 'LEFT'],\n                        [Lang.Blocks.RIGHT, 'RIGHT'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RAPID, 'RAPID'],\n                        [Lang.Blocks.MID, 'MID'],\n                        [Lang.Blocks.SLOW, 'SLOW']\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                },\n            ],\n            def: {\n                params: ['RIGHT', 'MID', 90, null],\n                type: 'move_turn',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n                SPD: 1,\n                DEG: 2,\n            },\n            class: \"move\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_FREE_TURN = 27;\n                const DIR_LEFT = 0;\n                const DIR_RIGHT = 1;\n                const SPEED_RAPID = 3;\n                const SPEED_MID = 2;\n                const SPEED_LOW = 1;\n\n                //var exTime = new Date();\n                //var firstCheck = true;\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"go turning block Start!\");\n\n                var _dir = script.getStringField('DIR', script)\n                var _spd = script.getStringField('SPD', script);\n                var _deg = script.getNumberValue('DEG');\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"skip block!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_FREE_TURN;\n\n                                        if (_dir == 'LEFT') Entry.hw.sendQueue['dir'] = DIR_LEFT;\n                                        else if (_dir == 'RIGHT') Entry.hw.sendQueue['dir'] = DIR_RIGHT;\n\n                                        if (_spd == 'RAPID') Entry.hw.sendQueue['speed'] = SPEED_RAPID;\n                                        else if (_spd == 'MID') Entry.hw.sendQueue['speed'] = SPEED_MID;\n                                        else if (_spd == 'SLOW') Entry.hw.sendQueue['speed'] = SPEED_LOW;\n\n                                        if (_deg < 5) _deg = 5; else if (_deg > 359) _deg = 359;\n                                        var degree = _deg * 0.5; //avoid overflow(8bit)\n\n                                        //console.log(\"degree:\", degree);\n                                        Entry.hw.sendQueue['dist'] = degree;  //따로 deg를 위한 딕셔너리는 존재하지 않는다.\n\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"exit block!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    Entry.hw.sendQueue['dir'] = 0x00;\n                                    Entry.hw.sendQueue['speed'] = 0x00;\n                                    Entry.hw.sendQueue['dist'] = 0x00;\n\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n                });\n            },\n        },\n\n        go_forward: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                }\n            ],\n            def: {\n                type: \"go_forward\"\n            },\n            class: \"base\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_GOGO = 1;\n\n                //var exTime = new Date();\n                //var firstCheck = true;\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"going forward block Start!\");\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"skip block!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_GOGO;\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"block exit!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n                });\n            },\n        },\n\n        go_back: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                }\n            ],\n            def: {\n                type: \"go_back\"\n            },\n            class: \"base\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_BACK = 4;\n\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"going back block Start!\");\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"skip block!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_BACK;\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"block exit!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n                });\n            },\n        },\n\n        turn_left: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                }\n            ],\n            def: {\n                type: \"turn_left\"\n            },\n            class: \"base\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_LEFT = 2;\n\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"turning left block Start!\");\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"skip block!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_LEFT;\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"exit block!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n\n                });\n            },\n        },\n\n        turn_right: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                }\n            ],\n            def: {\n                type: \"turn_right\"\n            },\n            class: \"base\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_RIGHT = 3;\n\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"turning right block Start!\");\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"skip block!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_RIGHT;\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"exit block!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n\n                });\n            },\n        },\n\n        going_forward_until_sensing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                }\n            ],\n            def: {\n                type: \"going_forward_until_sensing\"\n            },\n            class: \"sense\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_GOSENSOR = 100;\n\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"going forward until sensing block Start!\");\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"skip block!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_GOSENSOR;\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"block exit!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n                });\n            },\n        },\n\n        following_line_until_sensing: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                }\n            ],\n            def: {\n                type: \"following_line_until_sensing\"\n            },\n            class: \"sense\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_LINE_TRACING = 101;\n\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"following line until sensing block Start!\");\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n                        return new Promise(resolve => {\n\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"skip block!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n                                        Entry.hw.sendQueue['com'] = COMMAND_LINE_TRACING;\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"block exit!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n                        });\n\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n\n                });\n            },\n        },\n\n\n        front_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.FL, 'FL'],\n                        [Lang.Blocks.FR, 'FR'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['FL', null],\n                type: 'front_sensor',\n            },\n            paramsKeyMap: {\n                DIR: 0,\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function(sprite, script) {\n                const sen = script.getStringField('DIR', script);\n                return Entry.hw.portData.inputData.irSensor[sen];\n            },\n        },\n\n        bottom_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.BL, 'BL'],\n                        [Lang.Blocks.BM, 'BM'],\n                        [Lang.Blocks.BR, 'BR'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['BL', null],\n                type: 'bottom_sensor',\n            },\n            paramsKeyMap: {\n                B_DIR: 0,\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n                const sen = script.getStringField('B_DIR', script);\n                return Entry.hw.portData.inputData.irSensor[sen];\n            },\n        },\n\n        power_info: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                type: 'power_info',\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n                var vol = Entry.hw.portData.inputData.euler['PITCH'];\n                return vol;\n            },\n        },\n\n        button_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 12,\n                },\n            ],\n            def: {\n                type: 'button_input',\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                var bStat =  Entry.hw.portData.inputData.euler['ROLL'];\n                if(bStat == 8) bStat = 'R';\n                else if(bStat == 4) bStat = 'B';\n                else if(bStat == 2) bStat = 'G';\n                else if(bStat == 1) bStat = 'Y';\n                else bStat = 'N';\n\n                return bStat;\n            },\n        },\n\n        button_boolean_input: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RED_BTN, 'RED_BTN'],\n                        [Lang.Blocks.BLUE_BTN, 'BLUE_BTN'],\n                        [Lang.Blocks.GREEN_BTN, 'GREEN_BTN'],\n                        [Lang.Blocks.YELLOW_BTN, 'YELLOW_BTN'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.PRESSED, 'PRESS'],\n                        [Lang.Blocks.RELEASED, 'RELEASE'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['RED_BTN','PRESS'],\n                type: 'button_boolean_input',\n            },\n            paramsKeyMap: {\n                BUTTON: 0,\n                STATUS: 1,\n            },\n            class: 'boolean',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const btn = script.getStringField('BUTTON', script);\n                const stat = script.getStringField('STATUS', script);\n                var bStat = Entry.hw.portData.inputData.euler['ROLL'];\n                var result = false;\n\n                if (stat == 'PRESS')\n                {\n                    if((btn == 'RED_BTN')&&(bStat == 8)) result = true;\n                    else if((btn == 'BLUE_BTN') && (bStat == 4)) result = true;\n                    else if((btn == 'GREEN_BTN') && (bStat == 2)) result = true;\n                    else if((btn == 'YELLOW_BTN') && (bStat == 1)) result = true;\n                    else result = false;\n                }\n                else if (stat == 'RELEASE')\n                {\n                    if ((btn == 'RED_BTN') && (bStat == 8)) result = false;\n                    else if ((btn == 'BLUE_BTN') && (bStat == 4)) result = false;\n                    else if ((btn == 'GREEN_BTN') && (bStat == 2)) result = false;\n                    else if ((btn == 'YELLOW_BTN') && (bStat == 1)) result = false;\n                    else result = true;\n                }\n\n                return result;\n            },\n        },\n\n        face_detector: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.DETECT, 'DETECT'],\n                        [Lang.Blocks.CX, 'CX'],\n                        [Lang.Blocks.CY, 'CY'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['DETECT', null],\n                type: 'face_detector',\n            },\n            paramsKeyMap: {\n                PARAM: 0,\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const REQUEST_FACE_DETECTION = 0x01;\n                Entry.hw.sendQueue['req'] |= REQUEST_FACE_DETECTION;\n                const sen = script.getStringField('PARAM', script);\n                var result =  Entry.hw.portData.inputData.faceDetect[sen];\n\n                var Xg = Entry.hw.portData.inputData.faceDetect['CX'];\n                var Yg = Entry.hw.portData.inputData.faceDetect['CY'];\n\n                if (sen == 'CX') {\n                    if (result == 0x00) result = -999;\n                    else result = ((200 / 2) - Xg) + 10;\n                }\n                else if (sen == 'CY') {\n                    if (result == 0x00) result = -999;\n                    else result = ((200 / 2) - Yg) + 35;\n                }\n\n                return result;\n            },\n        },\n\n        cat_face_detector: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.DETECT, 'DETECT'],\n                        [Lang.Blocks.CX, 'CX'],\n                        [Lang.Blocks.CY, 'CY'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['DETECT', null],\n                type: 'cat_face_detector',\n            },\n            paramsKeyMap: {\n                PARAM: 0,\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const REQUEST_USER_DEFINED = 0x10;\n                Entry.hw.sendQueue['req'] |= REQUEST_USER_DEFINED;\n                const sen = script.getStringField('PARAM', script);\n                var result = Entry.hw.portData.inputData.userDefined[sen];\n\n                var Xg = Entry.hw.portData.inputData.userDefined['CX'];\n                var Yg = Entry.hw.portData.inputData.userDefined['CY'];\n\n                if (sen == 'CX') {\n                    if (result == 0x00) result = -999;\n                    else result = ((200 / 2) - Xg) + 20;\n                }\n                else if (sen == 'CY') {\n                    if (result == 0x00) result = -999;\n                    else result = ((200 / 2) - Yg) + 30;\n                }\n\n                return result;\n            },\n        },\n\n        face_boolean_detector: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.HUMAN, 'HUMAN'],\n                        [Lang.Blocks.CAT, 'CAT'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['HUMAN'],\n                type: 'face_boolean_detector',\n            },\n            paramsKeyMap: {\n                FACE: 0,\n            },\n            class: 'boolean',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                var result = false;\n\n                const REQUEST_FACE_DETECTION = 0x01;   //humanface\n                const REQUEST_USER_DEFINED = 0x10;     //catface\n\n                const sen = script.getStringField('FACE', script);\n\n                if(sen == 'HUMAN')\n                {\n                    Entry.hw.sendQueue['req'] |= REQUEST_FACE_DETECTION;\n                    var humanResult = Entry.hw.portData.inputData.faceDetect['DETECT'];\n                    if(humanResult != 0) result = true;\n                    else result = false;\n                }\n                else if(sen == 'CAT')\n                {\n                    Entry.hw.sendQueue['req'] |= REQUEST_USER_DEFINED;\n                    var catResult = Entry.hw.portData.inputData.userDefined['DETECT'];\n                    if(catResult != 0) result = true;\n                    else result = false;\n                }\n\n                return result;\n            },\n        },\n\n\n        color_detector: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.COLOR, 'COLOR'],\n                        [Lang.Blocks.CX, 'CX'],\n                        [Lang.Blocks.CY, 'CY'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['COLOR', null],\n                type: 'color_detector',\n            },\n            paramsKeyMap: {\n                PARAM: 0,\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const REQUEST_COLOR_DETECTION = 0x02;\n                Entry.hw.sendQueue['req'] |= REQUEST_COLOR_DETECTION;\n\n                const sen = script.getStringField('PARAM', script);\n                var result = Entry.hw.portData.inputData.colorDetect[sen];\n\n                if((result == 0xFE) && (sen == 'COLOR')) result = 'NONE';\n                else if ((result == 0x00) && (sen == 'COLOR')) result = 'RED';\n                else if ((result == 0x01) && (sen == 'COLOR')) result = 'ORANGE';\n                else if ((result == 0x02) && (sen == 'COLOR')) result = 'YELLOW';\n                else if ((result == 0x03) && (sen == 'COLOR')) result = 'GREEN';\n                else if ((result == 0x04) && (sen == 'COLOR')) result = 'CYAN';\n                else if ((result == 0x05) && (sen == 'COLOR')) result = 'BLUE';\n                else if ((result == 0x06) && (sen == 'COLOR')) result = 'PURPLE';\n\n                var Xg = Entry.hw.portData.inputData.colorDetect['CX'];\n                var Yg = Entry.hw.portData.inputData.colorDetect['CY'];\n\n                if (sen == 'CX') {\n                    if (result == 0xFE) result = -999;\n                    else result = ((200 / 2) - Xg) +20;\n                }\n                else if (sen == 'CY') {\n                    if (result == 0xFE) result = -999;\n                    else result = ((200 / 2) - Yg) +35;\n                }\n\n                return result;\n            },\n        },\n\n        color_boolean_detector: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.AI_RED, 'RED'],\n                        [Lang.Blocks.AI_ORANGE, 'ORANGE'],\n                        [Lang.Blocks.AI_YELLOW, 'YELLOW'],\n                        [Lang.Blocks.AI_GREEN, 'GREEN'],\n                        [Lang.Blocks.AI_CYAN, 'CYAN'],\n                        [Lang.Blocks.AI_BLUE, 'BLUE'],\n                        [Lang.Blocks.AI_PURPLE, 'PURPLE'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n            ],\n            def: {\n                params: ['RED'],\n                type: 'color_boolean_detector',\n            },\n            paramsKeyMap: {\n                PARAM: 0,\n            },\n            class: 'boolean',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                var result = false;\n\n                const REQUEST_COLOR_DETECTION = 0x02;\n                Entry.hw.sendQueue['req'] |= REQUEST_COLOR_DETECTION;\n\n                const sen = script.getStringField('PARAM', script);\n                var result = Entry.hw.portData.inputData.colorDetect['COLOR'];\n\n                //if(result == 0xFE) result = false;\n\n                if ((result == 0x00) && (sen == 'RED')) result = true;\n                else if ((result == 0x01) && (sen == 'ORANGE')) result = true;\n                else if ((result == 0x02) && (sen == 'YELLOW')) result = true;\n                else if ((result == 0x03) && (sen == 'GREEN')) result = true;\n                else if ((result == 0x04) && (sen == 'CYAN')) result = true;\n                else if ((result == 0x05) && (sen == 'BLUE')) result = true;\n                else if ((result == 0x06) && (sen == 'PURPLE')) result = true;\n                else result = false;\n\n                return result;\n            },\n        },\n\n\n        april_detector: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ID, 'ID'],\n                        [Lang.Blocks.CX, 'CX'],\n                        [Lang.Blocks.CY, 'CY'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['ID', null],\n                type: 'april_detector',\n            },\n            paramsKeyMap: {\n                A_INFO: 0,\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                var result = 0;\n\n                const REQUEST_APRIL_DETECTION = 0x04;\n                Entry.hw.sendQueue['req'] |= REQUEST_APRIL_DETECTION;\n\n                const sen = script.getStringField('A_INFO', script);\n                var result = Entry.hw.portData.inputData.aprilDetect[sen];\n\n                var Xg = Entry.hw.portData.inputData.aprilDetect['CX'];\n                var Yg = Entry.hw.portData.inputData.aprilDetect['CY'];\n\n\n                if(sen == 'ID')\n                {\n                    if(result == 0xFE) result = -1;\n                    else\n                    {\n                        if(result <11) result +=1;\n                        else if(result == 14) result = 12;\n                        else if(result == 15) result = 13;\n                        else if(result == 16) result = 14;\n                        else if(result == 18) result = 15;\n                        else if(result == 19) result = 16;\n                        else if(result == 20) result = 17;\n                    }\n                }\n                else if(sen == 'CX')\n                {\n                    if(result == 0x00) result = -999;\n                    else result = (200 / 2) - Xg;\n                }\n                else if (sen == 'CY')\n                {\n                    if (result == 0x00) result = -999;\n                    else result = (100 / 2) - Yg;\n                    //console.log(Yg, result);\n                }\n\n\n                return result;\n            },\n        },\n\n        april_boolean_detector: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_boolean_field',\n            params: [\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n            ],\n            def: {\n                params: [15],\n                type: 'april_boolean_detector',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n            },\n            class: 'boolean',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                var result = false;\n\n                const REQUEST_APRIL_DETECTION = 0x04;\n                Entry.hw.sendQueue['req'] |= REQUEST_APRIL_DETECTION;\n\n                var _num = script.getNumberValue('NUM');\n                var result = Entry.hw.portData.inputData.aprilDetect['ID'];\n\n                if(result <11) result +=1;\n                else if(result == 14) result = 12;\n                else if(result == 15) result = 13;\n                else if(result == 16) result = 14;\n                else if(result == 18) result = 15;\n                else if(result == 19) result = 16;\n                else if(result == 20) result = 17;\n\n                if(_num == result) result = true;\n                else result = false;\n\n                return result;\n            },\n        },\n\n        IMU_sensor: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic_string_field',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ROLL, 'ROLL'],\n                        [Lang.Blocks.PITCH, 'PITCH'],\n                        [Lang.Blocks.YAW, 'YAW'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['PITCH', null],\n                type: 'IMU_sensor',\n            },\n            paramsKeyMap: {\n                EULER: 0,\n            },\n            class: 'info',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const REQUEST_IMU_DETECTION = 0x08;\n                Entry.hw.sendQueue['req'] |= REQUEST_IMU_DETECTION;\n                const sen = script.getStringField('EULER', script);\n                const angle = Entry.hw.portData.inputData.euler[sen];\n                return angle;\n\n            },\n        },\n\n        screen_toggle: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CAMERA, 'CAMERA'],\n                        [Lang.Blocks.EMOTION, 'EMOTION'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['CAMERA', null],\n                type: 'screen_toggle',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'screen',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const COMMAND_SCREEN_TOGGLE = 240;\n                const SCREEN_CAMERA = 1;\n                const SCREEN_EMOTION = 2;\n\n                var _type = script.getStringField('TYPE', script);\n\n                Entry.hw.sendQueue['com'] = COMMAND_SCREEN_TOGGLE;\n\n                if (_type == 'CAMERA') Entry.hw.sendQueue['speed'] = SCREEN_CAMERA;\n                else if (_type == 'EMOTION') Entry.hw.sendQueue['speed'] = SCREEN_EMOTION;\n\n                console.log(\"send protocol!\");\n            },\n        },\n\n        emotion: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.EMO_SMILE, 'SMILE'],\n                        [Lang.Blocks.EMO_LOVE, 'LOVE'],\n                        [Lang.Blocks.EMO_SURPRISE, 'SURP'],\n                        [Lang.Blocks.EMO_NICE, 'NICE'],\n                        [Lang.Blocks.EMO_CHAOS, 'CHAOS'],\n                        [Lang.Blocks.EMO_CRASH, 'CRASH'],\n                        [Lang.Blocks.EMO_CANTBELIEVE, 'CANTBELIEVE'],\n                        [Lang.Blocks.EMO_SLEEP, 'SLEEP'],\n                        [Lang.Blocks.EMO_CRY, 'CRY'],\n                        [Lang.Blocks.EMO_WINK, 'WINK'],\n                        [Lang.Blocks.EMO_BLINK, 'BLINK'],\n                        [Lang.Blocks.EMO_SLEEPING, 'SLEEPING'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['SMILE', null],\n                type: 'emotion',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'screen',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const COMMAND_EMOTION_CHANGE = 241;\n\n                const EMO_BLINK = 3;\n                const EMO_STOP = 2;\n\n                const EMO_SMILE = 4;\n                const EMO_LOVE = 5;\n\n                const EMO_CRASH = 6;\n                const EMO_SURPRISE = 7;\n                const EMO_NICE = 8;\n                const EMO_CANTBELIEVE = 9;\n                const EMO_SLEEP = 10;\n                const EMO_CRY = 11;\n                const EMO_CHAOS = 12;\n                const EMO_SLEEPING = 13;\n                const EMO_WINK = 14;\n\n                var _type = script.getStringField('TYPE', script);\n\n                Entry.hw.sendQueue['com'] = COMMAND_EMOTION_CHANGE;\n\n                if (_type == 'SMILE') Entry.hw.sendQueue['speed'] = EMO_SMILE;\n                else if (_type == 'LOVE') Entry.hw.sendQueue['speed'] = EMO_LOVE;\n                else if (_type == 'SURP') Entry.hw.sendQueue['speed'] = EMO_SURPRISE;\n                else if (_type == 'NICE') Entry.hw.sendQueue['speed'] = EMO_NICE;\n                else if (_type == 'CHAOS') Entry.hw.sendQueue['speed'] = EMO_CHAOS;\n                else if (_type == 'CRASH') Entry.hw.sendQueue['speed'] = EMO_CRASH;\n                else if (_type == 'CANTBELIEVE') Entry.hw.sendQueue['speed'] = EMO_CANTBELIEVE;\n                else if (_type == 'SLEEP') Entry.hw.sendQueue['speed'] = EMO_SLEEP;\n                else if (_type == 'CRY') Entry.hw.sendQueue['speed'] = EMO_CRY;\n                else if (_type == 'WINK') Entry.hw.sendQueue['speed'] = EMO_WINK;\n                else if (_type == 'BLINK') Entry.hw.sendQueue['speed'] = EMO_BLINK;\n                else if (_type == 'SLEEPING') Entry.hw.sendQueue['speed'] = EMO_SLEEPING;\n\n                console.log(\"send protocol!\");\n            },\n        },\n\n        play_sound: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.SND_USER, 'USER'],\n                        [Lang.Blocks.SND_CAT, 'CAT'],\n                        [Lang.Blocks.SND_SHUTTER, 'SHUTTER'],\n                        [Lang.Blocks.SND_FAIL, 'FAIL'],\n                        [Lang.Blocks.SND_SUCCESS, 'SUCCESS'],\n                        [Lang.Blocks.SND_FAIL2, 'FAIL2'],\n                        [Lang.Blocks.SND_HONK, 'HONK'],\n                        [Lang.Blocks.SND_HONK2, 'HONK2'],\n                        [Lang.Blocks.SND_SIREN, 'SIREN'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Indicator',\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14,\n                },\n            ],\n            def: {\n                params: ['USER', null],\n                type: 'play_sound',\n            },\n            paramsKeyMap: {\n                TYPE: 0,\n            },\n            class: 'base',\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const COMMAND_PLAY_SOUND = 242;\n                const SND_USER = 0;\n                const SND_CAT = 4;\n                const SND_SHUTTER = 5;\n                const SND_FAIL = 1;\n                const SND_SUCCESS = 3;\n                const SND_FAIL2 = 2;\n                const SND_HONK = 6;\n                const SND_HONK2 = 7;\n                const SND_SIREN = 8;\n\n                var _type = script.getStringField('TYPE', script);\n\n                Entry.hw.sendQueue['com'] = COMMAND_PLAY_SOUND;\n\n                if (_type == 'USER') Entry.hw.sendQueue['speed'] = SND_USER;\n                else if (_type == 'CAT') Entry.hw.sendQueue['speed'] = SND_CAT;\n                else if (_type == 'SHUTTER') Entry.hw.sendQueue['speed'] = SND_SHUTTER;\n                else if (_type == 'FAIL') Entry.hw.sendQueue['speed'] = SND_FAIL;\n                else if (_type == 'SUCCESS') Entry.hw.sendQueue['speed'] = SND_SUCCESS;\n                else if (_type == 'FAIL2') Entry.hw.sendQueue['speed'] = SND_FAIL2;\n                else if (_type == 'HONK') Entry.hw.sendQueue['speed'] = SND_HONK;\n                else if (_type == 'HONK2') Entry.hw.sendQueue['speed'] = SND_HONK2;\n                else if (_type == 'SIREN') Entry.hw.sendQueue['speed'] = SND_SIREN;\n                console.log(\"send protocol!\");\n            },\n        },\n\n        LED_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.RED, 'RED'],\n                        [Lang.Blocks.GREEN, 'GREEN'],\n                        [Lang.Blocks.BLUE, 'BLUE'],\n                        [Lang.Blocks.YELLOW, 'YELLOW'],\n                        [Lang.Blocks.SKY_BLUE, 'SKY_BLUE'],\n                        [Lang.Blocks.PINK, 'PINK'],\n                        [Lang.Blocks.WHITE, 'WHITE'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.LED_NORMAL, 'NORMAL'],\n                        [Lang.Blocks.LED_BLINK, 'BLINK'],\n                        [Lang.Blocks.LED_DIMMING, 'DIMMING'],\n                        [Lang.Blocks.LED_SUNRISE, 'SUNRISE'],\n                        [Lang.Blocks.LED_SUNSET, 'SUNSET'],\n                        [Lang.Blocks.LED_FLICKER, 'FLICKER'],\n                        [Lang.Blocks.LED_RAINBOW, 'RAINBOW'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.ON, 'ON'],\n                        [Lang.Blocks.OFF, 'OFF'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                { type: 'Indicator', img: 'block_icon/hardware_icon.svg', size: 14 },\n            ],\n            def: {\n                params: ['WHITE', 'NORMAL', 'ON', null],\n                type: 'LED_control',\n            },\n            paramsKeyMap: {\n                COLOR: 0,\n                EFFECT: 1,\n                ACTION: 2,\n            },\n            class: \"led\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_LED_CONTROL = 31;\n\n                const LED_RED = 1;\n                const LED_BLUE = 2;\n                const LED_GREEN = 3;\n                const LED_YELLOW = 4;\n                const LED_SKY_BLUE = 5;\n                const LED_PINK = 6;\n                const LED_WHITE = 7;\n\n                const LED_NORMAL = 0;\n                const LED_BLINK = 1;\n                const LED_FLICKER = 2;\n                const LED_DIMMING = 3;\n                const LED_SUNRISE = 4;\n                const LED_SUNSET = 5;\n                const LED_RAINBOW = 6;\n\n                const LED_OFF = 0;\n                const LED_ON = 1;\n\n                //var exTime = new Date();\n                //var firstCheck = true;\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"LED block Start!\");\n\n                var _col = script.getStringField('COLOR', script);\n                var _eff = script.getStringField('EFFECT', script);\n                var _act = script.getStringField('ACTION', script);\n\n                return new Promise(resolve => {\n\n                    new Promise(resolve => {\n                        setTimeout(function () {\n                            console.log(\"exCnt: \" + exCnt + \" tempCnt:\" + tempCnt);\n                            if (exCnt == tempCnt) {\n                                _exit = true;\n\n                            }\n                            resolve();\n                        }, 200);\n                    })\n                    .then(() => {\n\n                        return new Promise(resolve => {\n                            var ttt = setInterval(() => {\n\n                                if (_exit == true) {\n                                    console.log(\"block skip!\");\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n\n                                var _stat = Entry.hw.portData.inputData['pStat'];\n\n                                if ((pStep == Z_WAIT) && (_stat == READY)) pStep = Z_SEND_PACKET;\n                                else if ((pStep == Z_WAIT) && (_stat == PROCESS)) pStep = Z_WAIT;    //wait until other action ends.\n\n                                if ((pStep == Z_SEND_PACKET) && (_stat == READY)) {    //send command until hardware start to action.\n\n                                    if (iter < 5) {\n\n                                        Entry.hw.sendQueue['com'] = COMMAND_LED_CONTROL;\n\n                                        if ((_col == 'RED') && (_act == 'ON')) Entry.hw.sendQueue['speed'] = LED_RED;\n                                        else if ((_col == 'BLUE') && (_act == 'ON')) Entry.hw.sendQueue['speed'] = LED_BLUE;\n                                        else if ((_col == 'GREEN') && (_act == 'ON')) Entry.hw.sendQueue['speed'] = LED_GREEN;\n                                        else if ((_col == 'SKY_BLUE') && (_act == 'ON')) Entry.hw.sendQueue['speed'] = LED_SKY_BLUE;\n                                        else if ((_col == 'PINK') && (_act == 'ON')) Entry.hw.sendQueue['speed'] = LED_PINK;\n                                        else if ((_col == 'YELLOW') && (_act == 'ON')) Entry.hw.sendQueue['speed'] = LED_YELLOW;\n                                        else if ((_col == 'WHITE') && (_act == 'ON')) Entry.hw.sendQueue['speed'] = LED_WHITE;\n\n                                        if (_eff == 'NORMAL') Entry.hw.sendQueue['dist'] = LED_NORMAL;\n                                        else if (_eff == 'BLINK') Entry.hw.sendQueue['dist'] = LED_BLINK;\n                                        else if (_eff == 'FLICKER') Entry.hw.sendQueue['dist'] = LED_FLICKER;\n                                        else if (_eff == 'DIMMING') Entry.hw.sendQueue['dist'] = LED_DIMMING;\n                                        else if (_eff == 'SUNRISE') Entry.hw.sendQueue['dist'] = LED_SUNRISE;\n                                        else if (_eff == 'SUNSET') Entry.hw.sendQueue['dist'] = LED_SUNSET;\n                                        else if (_eff == 'RAINBOW') Entry.hw.sendQueue['dist'] = LED_RAINBOW;\n\n                                        if (_act == 'OFF') Entry.hw.sendQueue['dir'] = LED_OFF;\n                                        else Entry.hw.sendQueue['dir'] = LED_ON;\n\n                                        console.log(\"send protocol!\");\n                                    }\n                                    else Entry.hw.sendQueue['com'] = 0x00;\n\n                                    pStep = Z_SEND_PACKET;\n                                    //iter++;\n                                }\n                                else if ((pStep == Z_SEND_PACKET) && (_stat == PROCESS)) {\n                                    pStep = Z_MOVING;\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                }\n\n                                if ((pStep == Z_MOVING) && (_stat == READY)) {\n\n                                    console.log(\"block exit!\");\n                                    Entry.hw.sendQueue['com'] = 0x00;\n                                    pStep = Z_WAIT;\n                                    resolve();\n                                    clearInterval(ttt);\n                                }\n                                else if ((pStep == Z_MOVING) && (_stat == PROCESS)) pStep = Z_MOVING;  //wait until the action ends.\n\n                            }, 50);\n\n                        });\n\n                    })\n                    .then(() => {\n                        resolve();\n                    })\n\n                });\n            },\n        },\n\n        motor_control: {\n            color: EntryStatic.colorSet.block.default.HARDWARE,\n            outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n            fontColor: '#ffffff',\n            skeleton: 'basic',\n            params: [\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.M1, 'LEFT'],\n                        [Lang.Blocks.M2, 'RIGHT'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Dropdown',\n                    options: [\n                        [Lang.Blocks.CW, 'CW'],\n                        [Lang.Blocks.CCW, 'CCW'],\n                        [Lang.Blocks.STOP, 'STOP'],\n                    ],\n                    fontSize: 11,\n                    bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                    arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                },\n                {\n                    type: 'Block',\n                    accept: 'string',\n                },\n                {\n                    type: \"Indicator\",\n                    img: 'block_icon/hardware_icon.svg',\n                    size: 14\n                },\n            ],\n            def: {\n                params: ['LEFT', 'CW', 5, null],\n                type: 'motor_control',\n            },\n            paramsKeyMap: {\n                NUM: 0,\n                DIR: 1,\n                SPD: 2,\n            },\n            class: \"move\",\n            isNotFor: ['zumi_mini'],\n            func: function (sprite, script) {\n\n                const Z_WAIT = 0;\n                const Z_SEND_PACKET = 1;\n                const Z_MOVING = 2;\n\n                const READY = 0;\n                const PROCESS = 1;\n\n                const COMMAND_MOTOR1_INFINITE = 32;\n                const COMMAND_MOTOR2_INFINITE = 33;\n                const DIR_LEFT = 1;\n                const DIR_RIGHT = 2;\n                const DIR_STOP = 3;\n\n                var pStep = Z_WAIT;\n                var iter = 0;\n                var _exit = false;\n\n                console.log(\"go motor control block Start!\");\n\n                var _num = script.getStringField('NUM', script)\n                var _dir = script.getStringField('DIR', script);\n                var _spd = script.getNumberValue('SPD');\n\n                var tSpd = Entry.hw.sendQueue['speed'];\n                var tDir = Entry.hw.sendQueue['dir'];\n\n                var ex_com = Entry.hw.sendQueue['com'];\n\n                //if ((ex_com != COMMAND_MOTOR1_INFINITE)|| (ex_com != COMMAND_MOTOR2_INFINITE)) {\n                    //tSpd = 0x00; tDir = 0x00;\n                //}\n\n                var _dirInt = 0;\n\n                if(_num == 'LEFT') {\n                    if (_dir == 'CW') _dirInt = DIR_RIGHT;\n                    else if (_dir == 'CCW') _dirInt = DIR_LEFT;\n                    else if (_dir == 'STOP') _dirInt = DIR_STOP;\n                }\n                if (_num == 'RIGHT') {\n                    if (_dir == 'CW') _dirInt = DIR_LEFT;\n                    else if (_dir == 'CCW') _dirInt = DIR_RIGHT;\n                    else if (_dir == 'STOP') _dirInt = DIR_STOP;\n                }\n\n                if (_spd < 0) _spd = 0; else if (_spd > 10) _spd = 10;\n\n                if (_num == 'LEFT') {\n                    Entry.hw.sendQueue['com'] = COMMAND_MOTOR1_INFINITE;\n\n                    tSpd = tSpd & 0b11110000;\n                    tSpd = tSpd | _spd;\n                    Entry.hw.sendQueue['speed'] = tSpd;\n\n                    tDir = tDir & 0b11110000;\n                    tDir = tDir | _dirInt;\n                    Entry.hw.sendQueue['dir'] = tDir;\n                }\n                else if (_num == 'RIGHT') {\n                    Entry.hw.sendQueue['com'] = COMMAND_MOTOR2_INFINITE;\n\n                    tSpd = tSpd & 0b00001111;\n                    tSpd = tSpd | (_spd << 4);\n                    Entry.hw.sendQueue['speed'] = tSpd;\n\n                    tDir = tDir & 0b00001111;\n                    tDir = tDir | (_dirInt << 4);\n                    Entry.hw.sendQueue['dir'] = tDir;\n                }\n\n                console.log(\"send protocol!\");\n\n            },\n        },\n\n    };\n};\n\nmodule.exports = Entry.ZumiMini;"
  },
  {
    "path": "src/playground/blocks/hardware/index.js",
    "content": "'use strict';\n\n/*\n * ex)\n * '1.1': Entry.Arduino,\n * '1.2': Entry.SensorBoard,\n * '1.3': Entry.CODEino,\n * '1.4': Entry.joystick,\n * '1.5': Entry.dplay\n * ...\n */\nEntry.HARDWARE_LIST = {};\n\n/*\n * index.js 를 제외한 해당 폴더의 모든 모듈을 import 한다.\n * 모듈은 id 가 있어야 등록된다.\n * 등록된 모듈은 Entry.HARDWARE_LIST 에 포함된다.\n * isPracticalCourse 속성값으로 교과형 하드웨어 여부를 판별하여 각 모듈리스트에 추가한다.\n */\nconst moduleListReq = require.context('.', false, /^(?!.*index.js)((.*\\.(js\\.*))[^.]*$)/im);\n\nfunction addHardwareList(module) {\n    if (typeof module.id === 'string') {\n        Entry.HARDWARE_LIST[module.id] = module;\n    } else if (module.id instanceof Array) {\n        module.id.forEach((id) => {\n            Entry.HARDWARE_LIST[id] = module;\n        });\n    }\n}\n\nfunction getHardwareModuleList() {\n    return Object.values(Entry.HARDWARE_LIST);\n}\n\nfunction getHardwareModule(hardware, callback) {\n    return new Promise((resolve) => {\n        require.ensure([], function (require) {\n            resolve(require('./' + hardware));\n        });\n    });\n}\n\nmoduleListReq.keys().forEach((fileName) => {\n    const module = moduleListReq(fileName);\n\n    if (module instanceof Array) {\n        module.forEach(addHardwareList);\n    } else {\n        addHardwareList(module);\n    }\n});\n\nmodule.exports = {\n    getHardwareModuleList,\n};\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_alux_connect_lite.js",
    "content": "'use strict';\n\nconst _throttle = require('lodash/throttle');\n\n(function() {\n    const CONNECT_INDEX = 0x32; //50\n    const RELEASE_VERSION = 17;\n    const SERIAL_INTERVAL = 32;\n    const EVENT_INTERVAL = 16;\n    const SEND_PACKET_LENGTH = 22;\n    const RECEIVED_PACKET_LENGTH = 26;\n    Entry.ProboConnectLite = new (class ProboConnectLite {\n        constructor()  {\n            this.id = '270101';\n            this.name = 'ProboConnectLite';\n            this.url = 'https://imssam.me';\n            this.imageName = 'alux_proboconnect_lite.png';\n            this.title = {\n                ko: '프로보 커넥트',\n                en: 'Probo Connect',\n            };\n            this.portData = {\n                baudRate: 115200,\n                duration: SERIAL_INTERVAL,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 128,\n                connectionType: 'bytestream',\n                constantServing: 'ReadOnly',\n            };\n\n            this.Color = {\n                Red:    { Min: 13, Max: 37 },\n                Green:  { Min: 38, Max: 62 },\n                Blue:   { Min: 63, Max: 87 },\n                Yellow: { Min: 88, Max: 112 },\n                Black:  { Min: 113, Max: 137 },\n                White:  { Min: 138, Max: 162 },\n            };\n            this.MultiSwitch = {\n                Key1: {  Min: 1, Max: 19 },\n                Key2: { Min: 26, Max: 44 },\n                Key3: { Min: 53, Max: 77 },\n                Key4: { Min: 83, Max: 101 },\n                Key5: { Min: 107, Max: 125 },\n                Key6: { Min: 139, Max: 157 },\n                Key7: { Min: 160, Max: 178 },\n                Key8: { Min: 191, Max: 209 }\n            };\n            this.Note = {\n                n32: 48,\n                n16: 96,  n16d: 144,  n16t: 64,\n                n8:  192, n8d:  288,  n8t:  128,\n                n4:  384, n4d:  576,  n4t:  256,\n                n2:  768, n2d:  1152, n2t:  512,\n                n1:  1536,\n            };\n            this.Rgb = {\n                Off: 0,\n                On: { Red: 1, Yellow: 12, Green: 23, Cyan: 34, Blue: 45, Magenta: 56, White:   67 },\n                Dimming: {\n                    Red:     90,\n                    Yellow:  91,\n                    Green:   92,\n                    Cyan:    93,\n                    Blue:    94,\n                    Magenta: 95,\n                    White:   96\n                }\n            };\n            this.Melody = [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748];\n            this.Track = [\n                [0x451F, 0x3D95, 0x36DD, 0x33C8, 0x2E22, 0x291A, 0x249E], // Start : size 7,\n                [0x228F, 0x249E, 0x291A, 0x2E22, 0x33C8, 0x36DD, 0x3D95, 0x451F], // End : size 8,\n                [0x228F, 0x1B6E, 0x1711, 0x1147 ], // LevelUp : size 4,\n                [0x1147, 0x1711, 0x1B6E, 0x228F ], // LevelDwon : size 4,\n            ];\n\n            const eventSetting = {\n                leading: true,\n                trailing: false\n            }\n            this.remoteEvent = _throttle(\n                () => {\n                    const prevFlag = this.sendFlag;\n                    try {\n                        Entry.engine.fireEvent('connectlite_event_remote_input');\n                    } catch (e) {\n                    } finally {\n                        this.sendFlag = prevFlag;\n                    }\n                },\n                EVENT_INTERVAL,\n                eventSetting\n            );\n            this.digitalEvent = _throttle(\n                () => {\n                    const prevFlag = this.sendFlag;\n                    try {\n                        Entry.engine.fireEvent('connectlite_event_digital_input');\n                    } catch (e) {\n                    } finally {\n                        this.sendFlag = prevFlag;\n                    }\n                },\n                EVENT_INTERVAL,\n                eventSetting\n            );\n\n            this.qRear = 0;\n            this.qFront = 0;\n            this.qSize = 128;\n            this.qBuffer = new Uint8Array(this.qSize + 2).fill(-1);\n            this.inputPacket = new Uint8Array(RECEIVED_PACKET_LENGTH).fill(-1);\n            this.pLength = 0; // packet length\n            this.process = false; // packet process\n\n            this.version = 0;\n            this.sendFlag = true;\n\n            this.blockMenuBlocks = [\n                //dropdown\n                'connectlite_dropdown_remote_key',\n                'connectlite_dropdown_digital_key',\n                'connectlite_dropdown_analog_key',\n                'connectlite_dropdown_setting_sensor_key',\n                'connectlite_dropdown_inNcom_sensor_key',\n                'connectlite_dropdown_sensor_color_key',\n                'connectlite_dropdown_rgb_color_key',\n                'connectlite_dropdown_sensor_angle_key',\n                'connectlite_dropdown_multikey_key',\n                'connectlite_dropdown_extension_digital_key',\n                'connectlite_dropdown_extension_analog_key',\n                'connectlite_dropdown_dc_1_all_key',\n                'connectlite_dropdown_port_1_4_key',\n                'connectlite_dropdown_on_off_key',\n                'connectlite_dropdown_velocity_key',\n                'connectlite_dropdown_servo_position_key',\n                'connectlite_dropdown_note_key',\n                'connectlite_dropdown_time_1_key',\n                'connectlite_dropdown_time_2_key',\n                'connectlite_dropdown_time_3',\n                'connectlite_dropdown_pitch_key',\n                'connectlite_dropdown_melody_key',\n\n                //event\n                'connectlite_when_press_remote_key',\n                'connectlite_when_input_digital_value',\n\n                //setting\n                'connectlite_set_sensor_setting',\n\n                //input\n                'connectlite_is_remote_key',\n                'connectlite_is_digital_value',\n                'connectlite_is_extension_digital_input',\n                'connectlite_get_analog_value',\n                'connectlite_get_extension_analog_input',\n                'connectlite_get_tri_axis_acceler_x',\n                'connectlite_get_tri_axis_acceler_y',\n                'connectlite_get_tri_axis_acceler_z',\n                'connectlite_get_value_mapping',\n                'connectlite_is_color_value',\n                'connectlite_get_color_value',\n                'connectlite_set_infinite_setting',\n                'connectlite_get_infinite_mm_diameter',\n                'connectlite_get_infinite_transform_input',\n                'connectlite_is_multi_sensor',\n                'connectlite_is_multi_switch',\n                'connectlite_set_eeprom_call',\n                'connectlite_get_eeprom_address_value',\n\n                //output\n                'connectlite_set_dc_output',\n                'connectlite_set_servo_output',\n                'connectlite_set_s_dc_output',\n                'connectlite_set_port_output',\n                'connectlite_play_melody_note_output',\n                'connectlite_play_melody_sec_output',\n                'connectlite_play_melody_output',\n                'connectlite_play_value_sec_output',\n                'connectlite_play_value_output',\n                'connectlite_play_melody_track_output',\n                'connectlite_play_melody_off',\n                'connectlite_set_rgbled_on_output',\n                'connectlite_set_rgbled_off_output',\n                'connectlite_set_rgbled_flashing_output',\n                'connectlite_set_rgbled_dimming_output',\n                'connectlite_set_fnd_output',\n                'connectlite_set_fnd_off',\n\n                //EEPROM\n                'connectlite_set_eeprom_write',\n            ];\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        connectlite_item_switch: '스위치',\n                        connectlite_item_infrared: '적외선',\n                        connectlite_item_magnetic: '자석',\n                        connectlite_item_rotation: '회전',\n                        connectlite_item_color: '컬러',\n                        connectlite_item_acceleration: '가속도',\n                        connectlite_item_ultrasonic: '초음파',\n                        connectlite_item_heart_rate: '심박',\n                        connectlite_item_illuminance: '조도',\n                        connectlite_item_temperature: '온도',\n                        connectlite_item_sound: '소리',\n                        connectlite_item_tilt: '기울기',\n                        connectlite_item_pressure: '압력',\n                        connectlite_item_multi_touch: '멀티키',\n                        connectlite_item_compass: '나침반',\n                        connectlite_item_tri_acceleration: '3가속',\n                        connectlite_item_multi_switch: '분배기',\n                        connectlite_item_infinite_rotation: '무한회전',\n                        connectlite_item_extension_input: '확장입력',\n                        connectlite_item_color_red: '빨간색',\n                        connectlite_item_color_green: '초록색',\n                        connectlite_item_color_blue: '파란색',\n                        connectlite_item_color_cyan: '청녹색',\n                        connectlite_item_color_magenta: '자홍색',\n                        connectlite_item_color_yellow: '노란색',\n                        connectlite_item_color_black: '검정색',\n                        connectlite_item_color_white: '하얀색',\n                        connectlite_item_value: '값',\n                        connectlite_item_angle: '각도',\n                        connectlite_item_absolute_angle: '절대각도',\n                        connectlite_item_number_of_rotations: '회전 수',\n                        connectlite_item_key_1: '키1',\n                        connectlite_item_key_2: '키2',\n                        connectlite_item_key_3: '키3',\n                        connectlite_item_key_4: '키4',\n                        connectlite_item_key_5: '키5',\n                        connectlite_item_key_6: '키6',\n                        connectlite_item_key_7: '키7',\n                        connectlite_item_key_8: '키8',\n                        connectlite_item_all: '모두',\n                        connectlite_item_on: '켜기',\n                        connectlite_item_off: '끄기',\n                        connectlite_item_note_whole: '온',\n                        connectlite_item_note_half: '2분',\n                        connectlite_item_note_quarter: '4분',\n                        connectlite_item_note_eighth: '8분',\n                        connectlite_item_note_sixteenth: '16분',\n                        connectlite_item_note_thirty_second: '32분',\n                        connectlite_item_pitch_do: '도',\n                        connectlite_item_pitch_do_sharp: '도#',\n                        connectlite_item_pitch_re: '레',\n                        connectlite_item_pitch_re_sharp: '레#',\n                        connectlite_item_pitch_mi: '미',\n                        connectlite_item_pitch_fa: '파',\n                        connectlite_item_pitch_fa_sharp: '파#',\n                        connectlite_item_pitch_sol: '솔',\n                        connectlite_item_pitch_sol_sharp: '솔#',\n                        connectlite_item_pitch_ra: '라',\n                        connectlite_item_pitch_ra_sharp: '라#',\n                        connectlite_item_pitch_si: '시',\n                        connectlite_item_melody_start: '시작음',\n                        connectlite_item_melody_end: '종료음',\n                        connectlite_item_melody_level_up: '레벨 업',\n                        connectlite_item_melody_level_down: '레벨 다운',\n\n                        connectlite_item_error: '오류',\n                        connectlite_item_nothing: '없음',\n\n                        connectlite_when_press_remote_key: '%1 리모컨 %2 키를 눌렀을 때',\n                        connectlite_when_input_digital_value: '%1 디지털 입력 %2 이(가) 들어왔을 때',\n\n                        connectlite_set_sensor_setting: '입력포트 %1 을(를) %2 센서로 설정 %3',\n\n                        connectlite_is_remote_key: '리모컨 입력 %1',\n                        connectlite_is_digital_value: '디지털 입력 %1',\n                        connectlite_is_extension_digital_input: '확장 디지털 입력 %1 의 %2',\n                        connectlite_get_analog_value: '아날로그 입력 %1',\n                        connectlite_get_extension_analog_input: '확장 아날로그 입력 %1 의 %2',\n                        connectlite_get_tri_axis_acceler_x: '3가속도 %1의 X축',\n                        connectlite_get_tri_axis_acceler_y: '3가속도 %1의 Y축',\n                        connectlite_get_tri_axis_acceler_z: '3가속도 %1의 Z축',\n                        connectlite_get_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환',\n                        connectlite_is_color_value: '컬러 센서 %1 이(가) %2 인가?',\n                        connectlite_get_color_value: '컬러 센서 %1 의 색상',\n                        connectlite_set_infinite_setting: '%1 센서 %2 을 %3 값으로 정하기 %4',\n                        connectlite_get_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값',\n                        connectlite_get_infinite_transform_input: '%1 센서 %2 의  %3',\n                        connectlite_is_multi_sensor: '멀티키 센서 %1의 %2',\n                        connectlite_is_multi_switch: '분배 스위치 %1의 %2',\n                        connectlite_set_eeprom_call: 'EEPROM %1 주소의 값 호출하기 %2',\n                        connectlite_get_eeprom_address_value: 'EEPROM 주소의 값',\n\n                        connectlite_set_port_output: '출력핀 %1 을(를) %2 %3',\n                        connectlite_set_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3',\n                        connectlite_set_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3',\n                        connectlite_set_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3',\n                        connectlite_play_melody_note_output: '%1 을(를) %2 음표로 연주하기 %3',\n                        connectlite_play_melody_sec_output: '%1 을(를) %2 초 동안 연주하기 %3',\n                        connectlite_play_melody_output: '%1 을(를) 연주하기 %2',\n                        connectlite_play_value_sec_output: '%1 값을(를) %2 초 동안 연주하기 %3',\n                        connectlite_play_value_output: '%1 값을(를) 연주하기 %2',\n                        connectlite_play_melody_track_output: '%1 을(를) %2초 간격으로 재생하기 %3',\n                        connectlite_play_melody_off: '멜로디 중지 %1',\n                        connectlite_set_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3',\n                        connectlite_set_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2',\n                        connectlite_set_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3',\n                        connectlite_set_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4',\n                        connectlite_set_fnd_output: 'FND를 %1 (으)로 설정 %2',\n                        connectlite_set_fnd_off: 'FND 끄기 %1',\n                        connectlite_set_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3',\n                    },\n                    Device: {\n                        probo_connect_lite: '프로보 커넥트',\n                    },\n                    Menus: {\n                        probo_connect_lite: '프로보 커넥트',\n                    },\n                },\n                en: {\n\n                    template: {\n                        connectlite_item_switch: 'Switch',\n                        connectlite_item_infrared: 'Infrared',\n                        connectlite_item_magnetic: 'Magnetic',\n                        connectlite_item_rotation: 'Rotation',\n                        connectlite_item_color: 'Color',\n                        connectlite_item_acceleration: 'Acceleration',\n                        connectlite_item_ultrasonic: 'Ultrasonic',\n                        connectlite_item_heart_rate: 'Heart Rate',\n                        connectlite_item_illuminance: 'Illuminance',\n                        connectlite_item_temperature: 'Temperature',\n                        connectlite_item_sound: 'Sound',\n                        connectlite_item_tilt: 'Tilt',\n                        connectlite_item_pressure: 'Pressure',\n                        connectlite_item_multi_touch: 'Multi Touch',\n                        connectlite_item_compass: 'Compass',\n                        connectlite_item_tri_acceleration: '3Acceleration',\n                        connectlite_item_multi_switch: 'Multi Switch',\n                        connectlite_item_infinite_rotation: 'Infinite Rotation',\n                        connectlite_item_extension_input: 'Extension Input',\n                        connectlite_item_color_red: 'Red',\n                        connectlite_item_color_green: 'Green',\n                        connectlite_item_color_blue: 'Blue',\n                        connectlite_item_color_cyan: 'Cyan',\n                        connectlite_item_color_magenta: 'Magenta',\n                        connectlite_item_color_yellow: 'Yellow',\n                        connectlite_item_color_black: 'Black',\n                        connectlite_item_color_white: 'White',\n                        connectlite_item_value: 'Value',\n                        connectlite_item_angle: 'Angle',\n                        connectlite_item_absolute_angle: 'Absolute Angle',\n                        connectlite_item_number_of_rotations: 'Number of Rotations',\n                        connectlite_item_key_1: 'Key1',\n                        connectlite_item_key_2: 'Key2',\n                        connectlite_item_key_3: 'Key3',\n                        connectlite_item_key_4: 'Key4',\n                        connectlite_item_key_5: 'Key5',\n                        connectlite_item_key_6: 'Key6',\n                        connectlite_item_key_7: 'Key7',\n                        connectlite_item_key_8: 'Key8',\n                        connectlite_item_all: 'All',\n                        connectlite_item_on: 'On',\n                        connectlite_item_off: 'Off',\n                        connectlite_item_note_whole: 'Whole',\n                        connectlite_item_note_half: 'Half',\n                        connectlite_item_note_quarter: 'Quarter',\n                        connectlite_item_note_eighth: 'Eighth',\n                        connectlite_item_note_sixteenth: 'Sixteenth',\n                        connectlite_item_note_thirty_second: 'Thirty-Second',\n                        connectlite_item_pitch_do: 'do',\n                        connectlite_item_pitch_do_sharp: 'xdo',\n                        connectlite_item_pitch_re: 're',\n                        connectlite_item_pitch_re_sharp: 'xre',\n                        connectlite_item_pitch_mi: 'mi',\n                        connectlite_item_pitch_fa: 'fa',\n                        connectlite_item_pitch_fa_sharp: 'xfa',\n                        connectlite_item_pitch_sol: 'sol',\n                        connectlite_item_pitch_sol_sharp: 'xsol',\n                        connectlite_item_pitch_ra: 'ra',\n                        connectlite_item_pitch_ra_sharp: 'xra',\n                        connectlite_item_pitch_si: 'si',\n                        connectlite_item_melody_start: 'Start',\n                        connectlite_item_melody_end: 'End',\n                        connectlite_item_melody_level_up: 'Level up',\n                        connectlite_item_melody_level_down: 'Level down',\n\n                        connectlite_item_error: 'error',\n                        connectlite_item_nothing: 'nothing',\n\n                        connectlite_when_press_remote_key: '%1 When %2 remote control key pressed',\n                        connectlite_when_input_digital_value: '%1 When %2 digital pin input',\n\n                        connectlite_set_sensor_setting: 'Set input port %1 to %2 sensor %3',\n\n                        connectlite_is_remote_key: 'Remote control %1',\n                        connectlite_is_digital_value: 'Read digital pin %1',\n                        connectlite_is_extension_digital_input: 'Extension digital input %1 to %2',\n                        connectlite_get_analog_value: 'Read analog pin %1',\n                        connectlite_get_extension_analog_input: 'Extension analog input %1 to %2',\n                        connectlite_get_tri_axis_acceler_x: '3acceleration %1 and X',\n                        connectlite_get_tri_axis_acceler_y: '3acceleration %1 and Y',\n                        connectlite_get_tri_axis_acceler_z: '3acceleration %1 and Z',\n                        connectlite_get_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5',\n                        connectlite_is_color_value: 'Is color sensor %1 %2 ?',\n                        connectlite_get_color_value: 'Color of color sensor %1',\n                        connectlite_set_infinite_setting: 'Set %1 sensor %2 to %3 value %4',\n                        connectlite_get_infinite_mm_diameter: 'The move distance(in mm) when the %1 sensor %2 is %3 mm in diameter',\n                        connectlite_get_infinite_transform_input: '%1 rotation sensor %2 to %3',\n                        connectlite_is_multi_sensor: 'Multi sensor %1 key %2',\n                        connectlite_is_multi_switch: 'A key number of the multi-switch sensor %1 = %2',\n                        connectlite_set_eeprom_call:'Calling the value of EEPROM %1 address',\n                        connectlite_get_eeprom_address_value: 'Value of EEPROM address',\n\n                        connectlite_set_dc_output: 'DC motor %1 velocity %2 %3',\n                        connectlite_set_servo_output: 'Servo motor %1 position %2 %3',\n                        connectlite_set_s_dc_output: 'Servo motor %1 speed %2 %3',\n                        connectlite_set_port_output: 'Set digital pin %1 as %2 %3',\n                        connectlite_play_melody_note_output: 'Play key %1 for %2 note %3',\n                        connectlite_play_melody_sec_output: 'Play key %1 for %2 secs %3',\n                        connectlite_play_melody_output: 'Play key %1 %2',\n                        connectlite_play_value_sec_output: 'Play value %1 for %2 secs %3',\n                        connectlite_play_value_output: 'Play value %1 %2',\n                        connectlite_play_melody_track_output: 'Play sound %1 for %2 secs %3',\n                        connectlite_play_melody_off: 'Stop tone %1',\n                        connectlite_set_rgbled_on_output: 'Turn on RGB LED %1 to %2 %3',\n                        connectlite_set_rgbled_off_output: 'Turn off RGB LED %1 %2',\n                        connectlite_set_rgbled_dimming_output: 'Dimming RGB LED %1 to %2 %3',\n                        connectlite_set_rgbled_flashing_output: 'RGB LED %1 Blinking %2 at %3 second intervals %4',\n                        connectlite_set_fnd_output: 'Set FND to %1 %2',\n                        connectlite_set_fnd_off: 'Turn off FND %1',\n                        connectlite_set_eeprom_write: 'Set EEPROM %1 address to %2 %3',\n                    },\n                    Device: {\n                        probo_connect_lite: 'Probo Connect',\n                    },\n                    Menus: {\n                        probo_connect_lite: 'Probo Connect',\n                    },\n                },\n            };\n        }\n\n        // 시작하기 및 정지하기 시 기기상태를 초기화한다.\n        setZero() {\n            this.Infinite = {\n                Buff: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Count: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Start: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                }\n            };\n            this.SensorSet = {\n                AA1: 0,\n                AA2: 0,\n                AA3: 0,\n                AA4: 0\n            };\n            this.InputData = {\n                Analog: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Digital: {\n                    A1: 0,\n                    A2: 0,\n                    A3: 0,\n                    A4: 0,\n                    FEA1: 0,\n                    FEA2: 0,\n                    FEA3: 0,\n                    FEA4: 0,\n                    REA1: 0,\n                    REA2: 0,\n                    REA3: 0,\n                    REA4: 0,\n                    BEA1: 0,\n                    BEA2: 0,\n                    BEA3: 0,\n                    BEA4: 0\n                },\n                Remote: {\n                    R_1: 0,\n                    R_2: 0,\n                    R_3: 0,\n                    R_4: 0,\n                    R_5: 0,\n                    R_6: 0,\n                    R_7: 0,\n                    R_8: 0,\n                    R_L1: 0,\n                    R_L2: 0,\n                    R_R1: 0,\n                    R_R2: 0\n                },\n                EEPROM: {\n                    EC: 0,\n                    EEPR2: 0,\n                    EEPR1: 0\n                },\n                Infinite:{\n                    ROTATION_1: 0,\n                    ROTATION_2: 0,\n                    ROTATION_3: 0,\n                    ROTATION_4: 0\n                },\n                Acceler:{\n                    AXIS_X1: 0,\n                    AXIS_X2: 0,\n                    AXIS_X3: 0,\n                    AXIS_X4: 0,\n                    AXIS_Y1: 0,\n                    AXIS_Y2: 0,\n                    AXIS_Y3: 0,\n                    AXIS_Y4: 0,\n                    AXIS_Z1: 0,\n                    AXIS_Z2: 0,\n                    AXIS_Z3: 0,\n                    AXIS_Z4: 0\n                }\n            };\n            this.RemoteData = {\n                B1: 0,\n                B2: 0,\n                B3: 0,\n                B4: 0,\n                Servo1: 0,\n                Servo2: 0,\n                Servo3: 0,\n                Servo4: 0,\n                DC1: 0,\n                DC2: 0,\n                DC3: 0,\n                DC4: 0,\n                MEL2: 0,\n                MEL1: 0,\n                FND: 100,\n                EEPR4: 0,\n                EEPR3: 0,\n                EEPR2: 0,\n                EEPR1: 0,\n                ASET2: 0,\n                ASET1: 0\n            };\n            this.EdgeFlag = {\n                FEA1: 0,\n                FEA2: 0,\n                FEA3: 0,\n                FEA4: 0,\n                REA1: 0,\n                REA2: 0,\n                REA3: 0,\n                REA4: 0,\n                BEA1: 0,\n                BEA2: 0,\n                BEA3: 0,\n                BEA4: 0\n            };\n            this.EEPROM = {\n                Buff: 0,\n                Count: 0\n            };\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            };\n        }\n\n        // 하드웨어 연결 후 초기화한다.\n        async initialHandshake() {\n            const modePacket = new Uint8Array(2).fill(0);\n            modePacket[0] = 0x63;\n            modePacket[1] = 0x36;\n\n            while(true) {\n                const response = await Entry.hwLite.serial.sendAsyncWithThrottle(modePacket);\n                if (response[0] !== CONNECT_INDEX) {\n                    modePacket[0] = 0x24;\n                    modePacket[1] = 0x42;\n                } else {\n                    this.version = (response.length === 1)\n                        ? 0\n                        : response[1];\n                    await Entry.Utils.sleep(1000);\n                    break;\n                }\n                await Entry.Utils.sleep(100);\n            }\n\n            Entry.addEventListener('run', this.handleRemoteEventInterval.bind(this));\n            Entry.addEventListener('run', this.handleDigitalEventInterval.bind(this));\n            Entry.addEventListener('beforeStop', () => {\n                if (this.remoteEventIntervalId) {\n                    clearInterval(this.remoteEventIntervalId);\n                    this.remoteEventIntervalId = null;\n                }\n                if (this.digitalEventIntervalId) {\n                    clearInterval(this.digitalEventIntervalId);\n                    this.digitalEventIntervalId = null;\n                }\n            });\n\n            this.setZero();\n\n            if (this.version === 0) {\n                const packet = await Entry.hwLite.serial.reader.read();\n                this.version = packet.value[0];\n                if (this.version !== RELEASE_VERSION) {\n                    const ko = `펌웨어를 업데이트 하세요.\\n`;\n                    const en = `(Please, Update your firmware.)\\n`;\n                    const version = ` - 현재(now): v.${this.version}\\n - 최신(latest): v.${RELEASE_VERSION}`;\n                    alert(`${ko}${en}${version}`);\n                }\n            }\n\n            return true;\n        }\n\n        handleRemoteEventInterval() {\n            if (this.remoteEventIntervalId) {\n                clearInterval(this.remoteEventIntervalId);\n            }\n            this.remoteEventIntervalId = setInterval(() => {\n                const currentState = this.remoteEvent.bind(this);\n                currentState();\n            }, EVENT_INTERVAL);\n        }\n\n        handleDigitalEventInterval() {\n            if (this.digitalEventIntervalId) {\n                clearInterval(this.digitalEventIntervalId);\n            }\n            this.digitalEventIntervalId = setInterval(() => {\n                const currentState = this.digitalEvent.bind(this);\n                currentState();\n            }, EVENT_INTERVAL);\n        }\n\n        handleLocalData(buffer) {\n            buffer.forEach(b => this.qEnqueue(b));\n\n            if (this._recoverTimeoutId) {\n                clearTimeout(this._recoverTimeoutId);\n            }\n\n            while(this.qCount() >= this.inputPacket.length) {\n                if (!this.process) {\n                    while(this.qCount() > 0) {\n                        if (this.inputPacket[0] !== 0xCD) {\n                            this.inputPacket[0] = this.qDequeue();\n                        } else if (this.inputPacket[1] !== 0xDA) {\n                            this.inputPacket[1] = this.qDequeue();\n                        } else {\n                            this.inputPacket[2] = this.qDequeue();\n                            this.pLength = this.inputPacket[2] + 3;\n                            this.process = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (this.process && (this.qCount() >= this.pLength)) {\n                    for (let i = 3; i < this.pLength; i++) {\n                        this.inputPacket[i] = this.qDequeue();\n                    }\n                    if (this.checksumHandle(this.inputPacket)) {\n                        this.processInputPacket(this.inputPacket);\n                    }\n\n                    this.inputPacket = new Uint8Array(RECEIVED_PACKET_LENGTH).fill(-1);\n                    this.process = false;\n                    this.sendFlag = true;\n                    this.pLength = 0;\n                }\n            }\n\n            if (this.sendFlag) {\n                if (this._requestTimeoutId) {\n                    clearTimeout(this._requestTimeoutId);\n                }\n                this._requestTimeoutId = setTimeout(\n                    () => {\n                        if (Entry.hwLite && Entry.hwLite.serial) {\n                            Entry.hwLite.serial.update();\n                            this.sendFlag = false;\n                            this._recoverTimeoutId = setTimeout(() => {\n                                this.sendFlag = true;\n                            }, SERIAL_INTERVAL * 3);\n                        }\n                    },\n                    SERIAL_INTERVAL\n                );\n            }\n        }\n\n        //디바이스에 값을 쓴다.\n        requestLocalData() {\n            if (this.sendFlag) {\n                return this.generateOutputPacket(this.RemoteData);\n            }\n        }\n\n        qEnqueue(data) {\n            this.qBuffer[this.qRear] = data;\n            this.qRear = (this.qRear + 1) % this.qSize\n        }\n\n        qDequeue() {\n            const data = this.qBuffer[this.qFront];\n            this.qBuffer[this.qFront] = -1;\n            this.qFront = (this.qFront + 1) % this.qSize;\n            return data;\n        }\n\n        qCount() {\n            return (this.qFront <= this.qRear)\n                ? (this.qRear - this.qFront)\n                : (this.qSize - this.qFront + this.qRear);\n        }\n\n        checksumRequest(packet) {\n            const length = packet[2] + 2;\n            let checker = 0;\n            for(let i = 3; i < length; i++) {\n                checker += packet[i];\n            }\n            return (checker & 0xFF);\n        }\n\n        checksumHandle(packet) {\n            let checker = 0;\n            const length = packet[2] + 2;\n            for(let i = 3; i < length ; i++ ) {\n                checker += packet[i];\n            }\n            return (packet[length] === (checker & 0xFF))\n        }\n\n        processInputPacket(packet) {\n            const digitalByte1 = packet[8];\n            const digitalByte2 = packet[9];\n            const remoteByte1 = packet[10];\n            const remoteByte2 = packet[11];\n            const rotationByte = packet[16];\n\n            this.InputData.Analog.AA1 = packet[4];\n            this.InputData.Analog.AA2 = packet[5];\n            this.InputData.Analog.AA3 = packet[6];\n            this.InputData.Analog.AA4 = packet[7];\n\n            this.InputData.Digital.A4 = (digitalByte1 >> 7) & 0x01;\n            this.InputData.Digital.A3 = (digitalByte1 >> 6) & 0x01;\n            this.InputData.Digital.A2 = (digitalByte1 >> 5) & 0x01;\n            this.InputData.Digital.A1 = (digitalByte1 >> 4) & 0x01;\n            this.InputData.Digital.FEA4 = (digitalByte1 >> 3) & 0x01;\n            this.InputData.Digital.FEA3 = (digitalByte1 >> 2) & 0x01;\n            this.InputData.Digital.FEA2 = (digitalByte1 >> 1) & 0x01;\n            this.InputData.Digital.FEA1 = digitalByte1 & 0x01;\n            this.InputData.Digital.REA4 = (digitalByte2 >> 7) & 0x01;\n            this.InputData.Digital.REA3 = (digitalByte2 >> 6) & 0x01;\n            this.InputData.Digital.REA2 = (digitalByte2 >> 5) & 0x01;\n            this.InputData.Digital.REA1 = (digitalByte2 >> 4) & 0x01;\n            this.InputData.Digital.BEA4 = (digitalByte2 >> 3) & 0x01;\n            this.InputData.Digital.BEA3 = (digitalByte2 >> 2) & 0x01;\n            this.InputData.Digital.BEA2 = (digitalByte2 >> 1) & 0x01;\n            this.InputData.Digital.BEA1 = digitalByte2 & 0x01;\n\n            this.InputData.Remote.R_3 = (remoteByte1 >> 7) & 0x01;\n            this.InputData.Remote.R_2 = (remoteByte1 >> 6) & 0x01;\n            this.InputData.Remote.R_4 = (remoteByte1 >> 5) & 0x01;\n            this.InputData.Remote.R_1 = (remoteByte1 >> 4) & 0x01;\n            this.InputData.Remote.R_7 = (remoteByte2 >> 7) & 0x01;\n            this.InputData.Remote.R_6 = (remoteByte2 >> 6) & 0x01;\n            this.InputData.Remote.R_8 = (remoteByte2 >> 5) & 0x01;\n            this.InputData.Remote.R_5 = (remoteByte2 >> 4) & 0x01;\n            this.InputData.Remote.R_R1 = (remoteByte2 >> 3) & 0x01;\n            this.InputData.Remote.R_L1 = (remoteByte2 >> 2) & 0x01;\n            this.InputData.Remote.R_R2 = (remoteByte2 >> 1) & 0x01;\n            this.InputData.Remote.R_L2 = remoteByte2 & 0x01;\n\n            this.InputData.EEPROM.EC = packet[13];\n            this.InputData.EEPROM.EEPR2 = packet[14];\n            this.InputData.EEPROM.EEPR1 = packet[15];\n\n            this.InputData.Infinite.ROTATION_1 = (rotationByte >> 6) & 0x0C;\n            this.InputData.Infinite.ROTATION_2 = (rotationByte >> 4) & 0x0C;\n            this.InputData.Infinite.ROTATION_3 = (rotationByte >> 2) & 0x0C;\n            this.InputData.Infinite.ROTATION_4 = rotationByte & 0x03;\n\n            this.InputData.Acceler.AXIS_X1 = packet[4];\n            this.InputData.Acceler.AXIS_X2 = packet[5];\n            this.InputData.Acceler.AXIS_X3 = packet[6];\n            this.InputData.Acceler.AXIS_X4 = packet[7];\n\n            this.InputData.Acceler.AXIS_Y1 = packet[17];\n            this.InputData.Acceler.AXIS_Y2 = packet[19];\n            this.InputData.Acceler.AXIS_Y3 = packet[21];\n            this.InputData.Acceler.AXIS_Y4 = packet[23];\n\n            this.InputData.Acceler.AXIS_Z1 = packet[18];\n            this.InputData.Acceler.AXIS_Z2 = packet[20];\n            this.InputData.Acceler.AXIS_Z3 = packet[22];\n            this.InputData.Acceler.AXIS_Z4 = packet[24];\n        }\n\n        generateOutputPacket(remoteData) {\n\n            const outputPacket = new Uint8Array(SEND_PACKET_LENGTH).fill(-1);\n\n            outputPacket[0] = 0xAD;\n            outputPacket[1] = 0xDA;\n            outputPacket[2] = outputPacket.length - 3;\n\n            outputPacket[3] = 0xF0 | (remoteData.B4 << 3) | (remoteData.B3 << 2) | (remoteData.B2 << 1) | remoteData.B1;\n\n            outputPacket[4] = remoteData.Servo1;\n            outputPacket[5] = remoteData.Servo2;\n            outputPacket[6] = remoteData.Servo3;\n            outputPacket[7] = remoteData.Servo4;\n\n            outputPacket[8] = remoteData.DC1;\n            outputPacket[9] = remoteData.DC2;\n            outputPacket[10] = remoteData.DC3;\n            outputPacket[11] = remoteData.DC4;\n\n            outputPacket[12] = remoteData.MEL2;\n            outputPacket[13] = remoteData.MEL1;\n\n            outputPacket[14] = remoteData.FND;\n\n            outputPacket[15] = remoteData.EEPR4;\n            outputPacket[16] = remoteData.EEPR3;\n            outputPacket[17] = remoteData.EEPR2;\n            outputPacket[18] = remoteData.EEPR1;\n\n            outputPacket[19] = remoteData.ASET2;\n            outputPacket[20] = remoteData.ASET1;\n\n            outputPacket[21] = this.checksumRequest(outputPacket);\n\n            return outputPacket;\n        }\n\n        getMonitorPort() {\n            return { ...this.InputData.Analog };\n        }\n\n        getRemoteKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 8) {\n                return `R_${num}`;\n            } else if (9 <= num && num <= 10) {\n                return `R_L${(num - 8)}`;\n            } else if (11 <= num && num <= 12) {\n                return `R_R${(num - 10)}`;\n            } else {\n                return data;\n            }\n        }\n\n        getDigitalKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `A${num}`;\n            } else if (5 <= num && num <= 8) {\n                return `FEA${num - 4}`;\n            } else if (9 <= num && num <= 12) {\n                return `REA${num - 8}`;\n            } else if (13 <= num && num <= 16) {\n                return `BEA${num - 12}`;\n            } else {\n                return data;\n            }\n        }\n\n        getDigitalStateValue(key) {\n            let value = false;\n            switch(key) {\n                case 'A1':\n                case 'A2':\n                case 'A3':\n                case 'A4':\n                    value = (Entry.ProboConnectLite.InputData.Digital[key] === 1);\n                    break;\n                default:\n                    if (Entry.ProboConnectLite.InputData.Digital[key] === 1) {\n                        if (Entry.ProboConnectLite.EdgeFlag[key] === 0) {\n                            Entry.ProboConnectLite.EdgeFlag[key] = 1;\n                            value = true;\n                        }\n                    } else {\n                        Entry.ProboConnectLite.EdgeFlag[key] = 0;\n                    }\n                    break;\n            }\n\n            return value;\n        }\n\n        getAnalogKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `AA${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getSettingSensorValue(key) {\n            switch (key) {\n                case '1':  // 스위치\n                case '2':  // 적외선\n                case '3':  // 자석\n                case '16': // 분배기\n                case Lang.template.connectlite_item_switch:       // 스위치\n                case Lang.template.connectlite_item_infrared:     // 적외선\n                case Lang.template.connectlite_item_magnetic:     // 자석\n                case Lang.template.connectlite_item_multi_switch: // 분배기\n                    return 1;\n                case '4': // 회전\n                case '7': // 조도\n                case '9': // 초음파\n                case Lang.template.connectlite_item_rotation:    // 회전\n                case Lang.template.connectlite_item_illuminance: // 조도\n                case Lang.template.connectlite_item_ultrasonic:  // 초음파\n                    return 2;\n                case '10': // 소리\n                case Lang.template.connectlite_item_sound: // 소리\n                    return 3;\n                case '11': // 기울기\n                case Lang.template.connectlite_item_tilt: // 기울기\n                    return 4;\n                case '12': // 압력\n                case Lang.template.connectlite_item_pressure: // 압력\n                    return 5;\n                case '8': // 심박\n                case Lang.template.connectlite_item_heart_rate: // 심박\n                    return 6;\n                case '5': // 컬러\n                case Lang.template.connectlite_item_color: // 컬러\n                    return 7;\n                case '6': // 가속도\n                case Lang.template.connectlite_item_acceleration: // 가속도\n                    return 8;\n                case '14': // 나침반\n                case '15': // 3축 가속도\n                case '17': // 확장 입력\n                case Lang.template.connectlite_item_compass:\n                case Lang.template.connectlite_item_tri_acceleration:\n                case Lang.template.connectlite_item_extension_input:\n                    return 9;\n                case '13': // 멀티터치(멀티키)\n                case Lang.template.connectlite_item_multi_touch: // 멀티터치(멀티키)\n                    return 11;\n                default:\n                    return key;\n            }\n        }\n\n        getAxisKey(data, axis) {\n            switch (data) {\n                case 'AA1':\n                case 'AA2':\n                case 'AA3':\n                case 'AA4':\n                    data = data.substr(2, 2);\n                    break;\n            }\n\n            return `AXIS_${axis}${data}`;\n        }\n\n        getMultiKeyValue(key) {\n            const num = Number(key);\n\n            if (1 <= num && num <= 8) {\n                return (num - 1);\n            } else {\n                switch (key) {\n                    case Lang.template.connectlite_item_key_1:\n                        return 0;\n                    case Lang.template.connectlite_item_key_2:\n                        return 1;\n                    case Lang.template.connectlite_item_key_3:\n                        return 2;\n                    case Lang.template.connectlite_item_key_4:\n                        return 3;\n                    case Lang.template.connectlite_item_key_5:\n                        return 4;\n                    case Lang.template.connectlite_item_key_6:\n                        return 5;\n                    case Lang.template.connectlite_item_key_7:\n                        return 6;\n                    case Lang.template.connectlite_item_key_8:\n                        return 7;\n                    default:\n                        return key;\n                }\n            }\n        }\n\n        getExtentionDigitalValue(key) {\n            const num = Number(key);\n            if (1 <= num && num <= 8) {\n                return (num - 1);\n            } else if (9 <= num && num <= 16) {\n                return (num - 9);\n            } else {\n                switch (key) {\n                    case 'EA1':\n                    case 'ET1':\n                        return 0;\n                    case 'EA2':\n                    case 'ET2':\n                        return 1;\n                    case 'EA3':\n                    case 'ET3':\n                        return 2;\n                    case 'EA4':\n                    case 'ET4':\n                        return 3;\n                    case 'EA5':\n                    case 'ET5':\n                        return 4;\n                    case 'EA6':\n                    case 'ET6':\n                        return 5;\n                    case 'EA7':\n                    case 'ET7':\n                        return 6;\n                    case 'EA8':\n                    case 'ET8':\n                        return 7;\n                    default:\n                        return key;\n                }\n            }\n        }\n\n        getExtentionAnalogKey(data) {\n            switch (data) {\n                case '1':\n                case 'EAA1':\n                    return 'Y';\n                case '2':\n                case 'EAA2':\n                    return 'Z';\n                default:\n                    return data;\n            }\n        }\n\n        getDckey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 7) {\n                return `DC${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getServoKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `Servo${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getPortKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `B${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getPortToggleValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.connectlite_item_on:\n                    return 1;\n                case '0':\n                case Lang.template.connectlite_item_off:\n                    return 0;\n                default:\n                    return key;\n            }\n        }\n\n        getSensorAngleKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.connectlite_item_value:\n                    return 'IS1';\n                case '2':\n                case Lang.template.connectlite_item_angle:\n                    return 'IS2';\n                case '3':\n                case Lang.template.connectlite_item_absolute_angle:\n                    return 'IS3';\n                case '4':\n                case Lang.template.connectlite_item_number_of_rotations:\n                    return 'IS4';\n                default:\n                    return data;\n            }\n        }\n\n        getPitchValue(pitch) {\n            // 배열의 인덱스 1번부터 음표\n            const index = (pitch % 12) + 1;\n\n            if (36 <= pitch && pitch <= 47) {\n                return Entry.ProboConnectLite.Melody[index];\n            } else if (48 <= pitch && pitch <= 59) {\n                return Entry.ProboConnectLite.Melody[index] >> 1;\n            } else if (60 <= pitch && pitch <= 71) {\n                return Entry.ProboConnectLite.Melody[index] >> 2;\n            } else if (72 <= pitch && pitch <= 83) {\n                return Entry.ProboConnectLite.Melody[index] >> 3;\n            } else {\n                return Entry.ProboConnectLite.Melody[0];\n            }\n        }\n\n        getNoteKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.connectlite_item_note_whole:\n                    return 'n1';\n                case '2':\n                case Lang.template.connectlite_item_note_half:\n                    return 'n2';\n                case '4':\n                case Lang.template.connectlite_item_note_quarter:\n                    return 'n4';\n                case '8':\n                case Lang.template.connectlite_item_note_eighth:\n                    return 'n8';\n                case '16':\n                case Lang.template.connectlite_item_note_sixteenth:\n                    return 'n16';\n                case '32':\n                case Lang.template.connectlite_item_note_thirty_second:\n                    return 'n32';\n                default:\n                    return data;\n            }\n        }\n\n        getMelodyValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.connectlite_item_melody_start:\n                    return 0;\n                case '2':\n                case Lang.template.connectlite_item_melody_end:\n                    return 1;\n                case '3':\n                case Lang.template.connectlite_item_melody_level_up:\n                    return 2;\n                case '4':\n                case Lang.template.connectlite_item_melody_level_down:\n                    return 3;\n                default:\n                    return key;\n            }\n        }\n\n        getColorSensorKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.connectlite_item_color_red:\n                    return 'Red';\n                case '2':\n                case Lang.template.connectlite_item_color_green:\n                    return 'Green';\n                case '3':\n                case Lang.template.connectlite_item_color_blue:\n                    return 'Blue';\n                case '4':\n                case Lang.template.connectlite_item_color_yellow:\n                    return 'Yellow';\n                case '5':\n                case Lang.template.connectlite_item_color_black:\n                    return 'Black';\n                case '6':\n                case Lang.template.connectlite_item_color_white:\n                    return 'White';\n                default:\n                    return data;\n            }\n        }\n\n        getRgbToggleValue(key) {\n            switch (key) {\n                case '0':\n                    return this.Rgb.Off;\n                case '1':\n                case Lang.template.technicpowerlite_item_color_red:\n                    return this.Rgb.On.Red;\n                case '2':\n                case Lang.template.technicpowerlite_item_color_green:\n                    return this.Rgb.On.Green;\n                case '3':\n                case Lang.template.technicpowerlite_item_color_blue:\n                    return this.Rgb.On.Blue;\n                case '4':\n                case Lang.template.technicpowerlite_item_color_cyan:\n                    return this.Rgb.On.Cyan;\n                case '5':\n                case Lang.template.technicpowerlite_item_color_magenta:\n                    return this.Rgb.On.Magenta;\n                case '6':\n                case Lang.template.technicpowerlite_item_color_yellow:\n                    return this.Rgb.On.Yellow;\n                case '7':\n                case Lang.template.technicpowerlite_item_color_white:\n                    return this.Rgb.On.White;\n                default:\n                    return key;\n            }\n        }\n\n        getRgbTwinkleValue(key, sec) {\n            let twinkle = 0;\n            switch (sec) {\n                case 0.05:\n                    twinkle += 1;\n                    break;\n                case 0.1:\n                    twinkle += 2;\n                    break;\n                case 0.2:\n                    twinkle += 3;\n                    break;\n                case 0.5:\n                    twinkle += 4;\n                    break;\n                case 1:\n                    twinkle += 5;\n                    break;\n            }\n\n            return this.getRgbToggleValue(key) + twinkle;\n        }\n\n        getRgbDimmingValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.technicpowerlite_item_color_red:\n                    return this.Rgb.Dimming.Red;\n                case '2':\n                case Lang.template.technicpowerlite_item_color_green:\n                    return this.Rgb.Dimming.Green;\n                case '3':\n                case Lang.template.technicpowerlite_item_color_blue:\n                    return this.Rgb.Dimming.Blue;\n                case '4':\n                case Lang.template.technicpowerlite_item_color_cyan:\n                    return this.Rgb.Dimming.Cyan;\n                case '5':\n                case Lang.template.technicpowerlite_item_color_magenta:\n                    return this.Rgb.Dimming.Magenta;\n                case '6':\n                case Lang.template.technicpowerlite_item_color_yellow:\n                    return this.Rgb.Dimming.Yellow;\n                case '7':\n                case Lang.template.technicpowerlite_item_color_white:\n                    return this.Rgb.Dimming.White;\n                default:\n                    return key;\n            }\n        }\n\n        getBlocks() {\n            return {\n                ///========================================================================================\n                /// Dropdown block\n                ///========================================================================================\n                connectlite_dropdown_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['R_1', '1'],\n                                ['R_2', '2'],\n                                ['R_3', '3'],\n                                ['R_4', '4'],\n                                ['R_5', '5'],\n                                ['R_6', '6'],\n                                ['R_7', '7'],\n                                ['R_8', '8'],\n                                ['R_L1', '9'],\n                                ['R_L2', '10'],\n                                ['R_R1', '11'],\n                                ['R_R2', '12'],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringValue('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['R_1', '1'],\n                                            ['R_2', '2'],\n                                            ['R_3', '3'],\n                                            ['R_4', '4'],\n                                            ['R_5', '5'],\n                                            ['R_6', '6'],\n                                            ['R_7', '7'],\n                                            ['R_8', '8'],\n                                            ['R_L1', '9'],\n                                            ['R_L2', '10'],\n                                            ['R_R1', '11'],\n                                            ['R_R2', '12'],\n                                        ],\n                                        value: 1,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_remote_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_digital_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['A1', '1'],\n                                ['A2', '2'],\n                                ['A3', '3'],\n                                ['A4', '4'],\n                                ['FEA1', '5'],\n                                ['FEA2', '6'],\n                                ['FEA3', '7'],\n                                ['FEA4', '8'],\n                                ['REA1', '9'],\n                                ['REA2', '10'],\n                                ['REA3', '11'],\n                                ['REA4', '12'],\n                                ['BEA1', '13'],\n                                ['BEA2', '14'],\n                                ['BEA3', '15'],\n                                ['BEA4', '16'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['A1', '1'],\n                                            ['A2', '2'],\n                                            ['A3', '3'],\n                                            ['A4', '4'],\n                                            ['FEA1', '5'],\n                                            ['FEA2', '6'],\n                                            ['FEA3', '7'],\n                                            ['FEA4', '8'],\n                                            ['REA1', '9'],\n                                            ['REA2', '10'],\n                                            ['REA3', '11'],\n                                            ['REA4', '12'],\n                                            ['BEA1', '13'],\n                                            ['BEA2', '14'],\n                                            ['BEA3', '15'],\n                                            ['BEA4', '16'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_digital_key',\n                            },\n                        ],\n                    }\n                },\n                connectlite_dropdown_analog_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['AA1', '1'],\n                                ['AA2', '2'],\n                                ['AA3', '3'],\n                                ['AA4', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['AA1', '1'],\n                                            ['AA2', '2'],\n                                            ['AA3', '3'],\n                                            ['AA4', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_analog_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_setting_sensor_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_switch, '1'],\n                                [Lang.template.connectlite_item_infrared, '2'],\n                                [Lang.template.connectlite_item_magnetic, '3'],\n                                [Lang.template.connectlite_item_rotation, '4'],\n                                [Lang.template.connectlite_item_color, '5'],\n                                [Lang.template.connectlite_item_acceleration, '6'],\n                                [Lang.template.connectlite_item_ultrasonic, '7'],\n                                [Lang.template.connectlite_item_heart_rate, '8'],\n                                [Lang.template.connectlite_item_illuminance, '9'],\n                                [Lang.template.connectlite_item_sound, '10'],\n                                [Lang.template.connectlite_item_tilt, '11'],\n                                [Lang.template.connectlite_item_pressure, '12'],\n                                [Lang.template.connectlite_item_multi_touch, '13'],\n                                [Lang.template.connectlite_item_compass, '14'],\n                                [Lang.template.connectlite_item_tri_acceleration, '15'],\n                                [Lang.template.connectlite_item_multi_switch, '16'],\n                                [Lang.template.connectlite_item_extension_input, '17'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_switch, '1'],\n                                            [Lang.template.connectlite_item_infrared, '2'],\n                                            [Lang.template.connectlite_item_magnetic, '3'],\n                                            [Lang.template.connectlite_item_rotation, '4'],\n                                            [Lang.template.connectlite_item_color, '5'],\n                                            [Lang.template.connectlite_item_acceleration, '6'],\n                                            [Lang.template.connectlite_item_ultrasonic, '7'],\n                                            [Lang.template.connectlite_item_heart_rate, '8'],\n                                            [Lang.template.connectlite_item_illuminance, '9'],\n                                            [Lang.template.connectlite_item_sound, '10'],\n                                            [Lang.template.connectlite_item_tilt, '11'],\n                                            [Lang.template.connectlite_item_pressure, '12'],\n                                            [Lang.template.connectlite_item_multi_touch, '13'],\n                                            [Lang.template.connectlite_item_compass, '14'],\n                                            [Lang.template.connectlite_item_tri_acceleration, '15'],\n                                            [Lang.template.connectlite_item_multi_switch, '16'],\n                                            [Lang.template.connectlite_item_extension_input, '17'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_setting_sensor_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_inNcom_sensor_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_infinite_rotation, '1'],\n                                [Lang.template.connectlite_item_compass, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_infinite_rotation, '1'],\n                                            [Lang.template.connectlite_item_compass, '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_inNcom_sensor_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_sensor_color_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_color_red, '1'],\n                                [Lang.template.connectlite_item_color_green, '2'],\n                                [Lang.template.connectlite_item_color_blue, '3'],\n                                [Lang.template.connectlite_item_color_yellow, '4'],\n                                [Lang.template.connectlite_item_color_black, '5'],\n                                [Lang.template.connectlite_item_color_white, '6'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_color_red, '1'],\n                                            [Lang.template.connectlite_item_color_green, '2'],\n                                            [Lang.template.connectlite_item_color_blue, '3'],\n                                            [Lang.template.connectlite_item_color_yellow, '4'],\n                                            [Lang.template.connectlite_item_color_black, '5'],\n                                            [Lang.template.connectlite_item_color_white, '6'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_sensor_color_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_rgb_color_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_color_red, '1'],\n                                [Lang.template.connectlite_item_color_green, '2'],\n                                [Lang.template.connectlite_item_color_blue, '3'],\n                                [Lang.template.connectlite_item_color_cyan, '4'],\n                                [Lang.template.connectlite_item_color_magenta, '5'],\n                                [Lang.template.connectlite_item_color_yellow, '6'],\n                                [Lang.template.connectlite_item_color_white, '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_color_red, '1'],\n                                            [Lang.template.connectlite_item_color_green, '2'],\n                                            [Lang.template.connectlite_item_color_blue, '3'],\n                                            [Lang.template.connectlite_item_color_cyan, '4'],\n                                            [Lang.template.connectlite_item_color_magenta, '5'],\n                                            [Lang.template.connectlite_item_color_yellow, '6'],\n                                            [Lang.template.connectlite_item_color_white, '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_rgb_color_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_sensor_angle_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_value, '1'],\n                                [Lang.template.connectlite_item_angle, '2'],\n                                [Lang.template.connectlite_item_absolute_angle, '3'],\n                                [Lang.template.connectlite_item_number_of_rotations, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_value, '1'],\n                                            [Lang.template.connectlite_item_angle, '2'],\n                                            [Lang.template.connectlite_item_absolute_angle, '3'],\n                                            [Lang.template.connectlite_item_number_of_rotations, '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_sensor_angle_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_multikey_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_key_1, '1'],\n                                [Lang.template.connectlite_item_key_2, '2'],\n                                [Lang.template.connectlite_item_key_3, '3'],\n                                [Lang.template.connectlite_item_key_4, '4'],\n                                [Lang.template.connectlite_item_key_5, '5'],\n                                [Lang.template.connectlite_item_key_6, '6'],\n                                [Lang.template.connectlite_item_key_7, '7'],\n                                [Lang.template.connectlite_item_key_8, '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_key_1, '1'],\n                                            [Lang.template.connectlite_item_key_2, '2'],\n                                            [Lang.template.connectlite_item_key_3, '3'],\n                                            [Lang.template.connectlite_item_key_4, '4'],\n                                            [Lang.template.connectlite_item_key_5, '5'],\n                                            [Lang.template.connectlite_item_key_6, '6'],\n                                            [Lang.template.connectlite_item_key_7, '7'],\n                                            [Lang.template.connectlite_item_key_8, '8'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_multikey_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_extension_digital_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['EA1', '1'],\n                                ['EA2', '2'],\n                                ['EA3', '3'],\n                                ['EA4', '4'],\n                                ['EA5', '5'],\n                                ['EA6', '6'],\n                                ['EA7', '7'],\n                                ['EA8', '8'],\n                                ['ET1', '9'],\n                                ['ET2', '10'],\n                                ['ET3', '11'],\n                                ['ET4', '12'],\n                                ['ET5', '13'],\n                                ['ET6', '14'],\n                                ['ET7', '15'],\n                                ['ET8', '16'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['EA1', '1'],\n                                            ['EA2', '2'],\n                                            ['EA3', '3'],\n                                            ['EA4', '4'],\n                                            ['EA5', '5'],\n                                            ['EA6', '6'],\n                                            ['EA7', '7'],\n                                            ['EA8', '8'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_extension_digital_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_extension_analog_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['EAA1', '1'],\n                                ['EAA2', '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['EAA1', '1'],\n                                            ['EAA2', '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_extension_analog_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_dc_1_all_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['1,2', '5'],\n                                ['3,4', '6'],\n                                [Lang.template.connectlite_item_all, '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['1,2', '5'],\n                                            ['3,4', '6'],\n                                            [Lang.template.connectlite_item_all, '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_dc_1_all_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_velocity_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['20', '20'],\n                                ['15', '15'],\n                                ['10', '10'],\n                                ['5', '5'],\n                                ['0', '0'],\n                                ['-5', '-5'],\n                                ['-10', '-10'],\n                                ['-15', '-15'],\n                                ['-20', '-20'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['20', '20'],\n                                            ['15', '15'],\n                                            ['10', '10'],\n                                            ['5', '5'],\n                                            ['0', '0'],\n                                            ['-5', '-5'],\n                                            ['-10', '-10'],\n                                            ['-15', '-15'],\n                                            ['-20', '-20'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_velocity_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_servo_position_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['20', '20'],\n                                ['40', '40'],\n                                ['60', '60'],\n                                ['80', '80'],\n                                ['100', '100'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['20', '20'],\n                                            ['40', '40'],\n                                            ['60', '60'],\n                                            ['80', '80'],\n                                            ['100', '100'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_servo_position_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_port_1_4_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_port_1_4_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_on_off_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_on, '1'],\n                                [Lang.template.connectlite_item_off, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    events: {},\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_on, '1'],\n                                            [Lang.template.connectlite_item_off, '0'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_on_off_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_note_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_note_whole, '1'],\n                                [Lang.template.connectlite_item_note_half, '2'],\n                                [Lang.template.connectlite_item_note_quarter, '4'],\n                                [Lang.template.connectlite_item_note_eighth, '8'],\n                                [Lang.template.connectlite_item_note_sixteenth, '16'],\n                                [Lang.template.connectlite_item_note_thirty_second, '32'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_note_whole, '1'],\n                                            [Lang.template.connectlite_item_note_half, '2'],\n                                            [Lang.template.connectlite_item_note_quarter, '4'],\n                                            [Lang.template.connectlite_item_note_eighth, '8'],\n                                            [Lang.template.connectlite_item_note_sixteenth, '16'],\n                                            [Lang.template.connectlite_item_note_thirty_second, '32'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_note_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_time_1_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.1', '0.1'],\n                                ['0.3', '0.3'],\n                                ['0.5', '0.5'],\n                                ['0.7', '0.7'],\n                                ['1', '1'],\n                                ['2', '2'],\n                            ],\n                            value: '0.5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.1', '0.1'],\n                                            ['0.3', '0.3'],\n                                            ['0.5', '0.5'],\n                                            ['0.7', '0.7'],\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                        ],\n                                        value: '0.5',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_time_1_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_time_2_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.1', '0.1'],\n                                ['0.3', '0.3'],\n                                ['0.5', '0.5'],\n                                ['0.7', '0.7'],\n                                ['1', '1'],\n                                ['2', '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.1', '0.1'],\n                                            ['0.3', '0.3'],\n                                            ['0.5', '0.5'],\n                                            ['0.7', '0.7'],\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_time_2_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_time_3: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.05', '0.05'],\n                                ['0.1', '0.1'],\n                                ['0.2', '0.2'],\n                                ['0.5', '0.5'],\n                                ['1', '1'],\n                            ],\n                            value: '0.5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.05', '0.05'],\n                                            ['0.1', '0.1'],\n                                            ['0.2', '0.2'],\n                                            ['0.5', '0.5'],\n                                            ['1', '1'],\n                                        ],\n                                        value: '0.5',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_time_3',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_pitch_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'DropdownExtra',\n                            options: [\n                                [Lang.template.connectlite_item_pitch_do + ' (36)', '36'],\n                                [Lang.template.connectlite_item_pitch_do_sharp + ' (37)', '37'],\n                                [Lang.template.connectlite_item_pitch_re + ' (38)', '38'],\n                                [Lang.template.connectlite_item_pitch_re_sharp + ' (39)', '39'],\n                                [Lang.template.connectlite_item_pitch_mi + ' (40)', '40'],\n                                [Lang.template.connectlite_item_pitch_fa + ' (41)', '41'],\n                                [Lang.template.connectlite_item_pitch_fa_sharp + ' (42)', '42'],\n                                [Lang.template.connectlite_item_pitch_sol + ' (43)', '43'],\n                                [Lang.template.connectlite_item_pitch_sol_sharp + ' (44)', '44'],\n                                [Lang.template.connectlite_item_pitch_ra + ' (45)', '45'],\n                                [Lang.template.connectlite_item_pitch_ra_sharp + ' (46)', '46'],\n                                [Lang.template.connectlite_item_pitch_si + ' (47)', '47'],\n\n                                [Lang.template.connectlite_item_pitch_do + ' (48)', '48'],\n                                [Lang.template.connectlite_item_pitch_do_sharp + ' (49)', '49'],\n                                [Lang.template.connectlite_item_pitch_re + ' (50)', '50'],\n                                [Lang.template.connectlite_item_pitch_re_sharp + ' (51)', '51'],\n                                [Lang.template.connectlite_item_pitch_mi + ' (52)', '52'],\n                                [Lang.template.connectlite_item_pitch_fa + ' (53)', '53'],\n                                [Lang.template.connectlite_item_pitch_fa_sharp + ' (54)', '54'],\n                                [Lang.template.connectlite_item_pitch_sol + ' (55)', '55'],\n                                [Lang.template.connectlite_item_pitch_sol_sharp + ' (56)', '56'],\n                                [Lang.template.connectlite_item_pitch_ra + ' (57)', '57'],\n                                [Lang.template.connectlite_item_pitch_ra_sharp + ' (58)', '58'],\n                                [Lang.template.connectlite_item_pitch_si + ' (59)', '59'],\n\n                                [Lang.template.connectlite_item_pitch_do + ' (60)', '60'],\n                                [Lang.template.connectlite_item_pitch_do_sharp + ' (61)', '61'],\n                                [Lang.template.connectlite_item_pitch_re + ' (62)', '62'],\n                                [Lang.template.connectlite_item_pitch_re_sharp + ' (63)', '63'],\n                                [Lang.template.connectlite_item_pitch_mi + ' (64)', '64'],\n                                [Lang.template.connectlite_item_pitch_fa + ' (65)', '65'],\n                                [Lang.template.connectlite_item_pitch_fa_sharp + ' (66)', '66'],\n                                [Lang.template.connectlite_item_pitch_sol + ' (67)', '67'],\n                                [Lang.template.connectlite_item_pitch_sol_sharp + ' (68)', '68'],\n                                [Lang.template.connectlite_item_pitch_ra + ' (69)', '69'],\n                                [Lang.template.connectlite_item_pitch_ra_sharp + ' (70)', '70'],\n                                [Lang.template.connectlite_item_pitch_si + ' (71)', '71'],\n\n                                [Lang.template.connectlite_item_pitch_do + ' (72)', '72'],\n                                [Lang.template.connectlite_item_pitch_do_sharp + ' (73)', '73'],\n                                [Lang.template.connectlite_item_pitch_re + ' (74)', '74'],\n                                [Lang.template.connectlite_item_pitch_re_sharp + ' (75)', '75'],\n                                [Lang.template.connectlite_item_pitch_mi + ' (76)', '76'],\n                                [Lang.template.connectlite_item_pitch_fa + ' (77)', '77'],\n                                [Lang.template.connectlite_item_pitch_fa_sharp + ' (78)', '78'],\n                                [Lang.template.connectlite_item_pitch_sol + ' (79)', '79'],\n                                [Lang.template.connectlite_item_pitch_sol_sharp + ' (80)', '80'],\n                                [Lang.template.connectlite_item_pitch_ra + ' (81)', '81'],\n                                [Lang.template.connectlite_item_pitch_ra_sharp + ' (82)', '82'],\n                                [Lang.template.connectlite_item_pitch_si + ' (83)', '83'],\n                            ],\n                            value: '60',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        const value = script.getStringField('PARAM0');\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_pitch_do + ' (36)', '36'],\n                                            [Lang.template.connectlite_item_pitch_do_sharp + ' (37)', '37'],\n                                            [Lang.template.connectlite_item_pitch_re + ' (38)', '38'],\n                                            [Lang.template.connectlite_item_pitch_re_sharp + ' (39)', '39'],\n                                            [Lang.template.connectlite_item_pitch_mi + ' (40)', '40'],\n                                            [Lang.template.connectlite_item_pitch_fa + ' (41)', '41'],\n                                            [Lang.template.connectlite_item_pitch_fa_sharp + ' (42)', '42'],\n                                            [Lang.template.connectlite_item_pitch_sol + ' (43)', '43'],\n                                            [Lang.template.connectlite_item_pitch_sol_sharp + ' (44)', '44'],\n                                            [Lang.template.connectlite_item_pitch_ra + ' (45)', '45'],\n                                            [Lang.template.connectlite_item_pitch_ra_sharp + ' (46)', '46'],\n                                            [Lang.template.connectlite_item_pitch_si + ' (47)', '47'],\n\n                                            [Lang.template.connectlite_item_pitch_do + ' (48)', '48'],\n                                            [Lang.template.connectlite_item_pitch_do_sharp + ' (49)', '49'],\n                                            [Lang.template.connectlite_item_pitch_re + ' (50)', '50'],\n                                            [Lang.template.connectlite_item_pitch_re_sharp + ' (51)', '51'],\n                                            [Lang.template.connectlite_item_pitch_mi + ' (52)', '52'],\n                                            [Lang.template.connectlite_item_pitch_fa + ' (53)', '53'],\n                                            [Lang.template.connectlite_item_pitch_fa_sharp + ' (54)', '54'],\n                                            [Lang.template.connectlite_item_pitch_sol + ' (55)', '55'],\n                                            [Lang.template.connectlite_item_pitch_sol_sharp + ' (56)', '56'],\n                                            [Lang.template.connectlite_item_pitch_ra + ' (57)', '57'],\n                                            [Lang.template.connectlite_item_pitch_ra_sharp + ' (58)', '58'],\n                                            [Lang.template.connectlite_item_pitch_si + ' (59)', '59'],\n\n                                            [Lang.template.connectlite_item_pitch_do + ' (60)', '60'],\n                                            [Lang.template.connectlite_item_pitch_do_sharp + ' (61)', '61'],\n                                            [Lang.template.connectlite_item_pitch_re + ' (62)', '62'],\n                                            [Lang.template.connectlite_item_pitch_re_sharp + ' (63)', '63'],\n                                            [Lang.template.connectlite_item_pitch_mi + ' (64)', '64'],\n                                            [Lang.template.connectlite_item_pitch_fa + ' (65)', '65'],\n                                            [Lang.template.connectlite_item_pitch_fa_sharp + ' (66)', '66'],\n                                            [Lang.template.connectlite_item_pitch_sol + ' (67)', '67'],\n                                            [Lang.template.connectlite_item_pitch_sol_sharp + ' (68)', '68'],\n                                            [Lang.template.connectlite_item_pitch_ra + ' (69)', '69'],\n                                            [Lang.template.connectlite_item_pitch_ra_sharp + ' (70)', '70'],\n                                            [Lang.template.connectlite_item_pitch_si + ' (71)', '71'],\n\n                                            [Lang.template.connectlite_item_pitch_do + ' (72)', '72'],\n                                            [Lang.template.connectlite_item_pitch_do_sharp + ' (73)', '73'],\n                                            [Lang.template.connectlite_item_pitch_re + ' (74)', '74'],\n                                            [Lang.template.connectlite_item_pitch_re_sharp + ' (75)', '75'],\n                                            [Lang.template.connectlite_item_pitch_mi + ' (76)', '76'],\n                                            [Lang.template.connectlite_item_pitch_fa + ' (77)', '77'],\n                                            [Lang.template.connectlite_item_pitch_fa_sharp + ' (78)', '78'],\n                                            [Lang.template.connectlite_item_pitch_sol + ' (79)', '79'],\n                                            [Lang.template.connectlite_item_pitch_sol_sharp + ' (80)', '80'],\n                                            [Lang.template.connectlite_item_pitch_ra + ' (81)', '81'],\n                                            [Lang.template.connectlite_item_pitch_ra_sharp + ' (82)', '82'],\n                                            [Lang.template.connectlite_item_pitch_si + ' (83)', '83'],\n                                        ],\n                                        value: '60',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_pitch_key',\n                            },\n                        ],\n                    },\n                },\n                connectlite_dropdown_melody_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.connectlite_item_melody_start, '1'],\n                                [Lang.template.connectlite_item_melody_end, '2'],\n                                [Lang.template.connectlite_item_melody_level_up, '3'],\n                                [Lang.template.connectlite_item_melody_level_down, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.connectlite_item_melody_start, '1'],\n                                            [Lang.template.connectlite_item_melody_end, '2'],\n                                            [Lang.template.connectlite_item_melody_level_up, '3'],\n                                            [Lang.template.connectlite_item_melody_level_down, '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'connectlite_dropdown_melody_key',\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Event block\n                ///========================================================================================\n                // %1 리모컨 %2 키를 눌렀을 때\n                connectlite_when_press_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: {\n                                x: 0,\n                                y: -2,\n                            },\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'connectlite_dropdown_remote_key',\n                            },\n                        ],\n                        type: 'connectlite_when_press_remote_key',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_event',\n                    isNotFor: ['ProboConnectLite'],\n                    event: 'connectlite_event_remote_input',\n                    func(sprite, script) {\n                        const key = Entry.ProboConnectLite.getRemoteKey(script.getStringValue('PARAM1'));\n                        return (Entry.ProboConnectLite.InputData.Remote[key] === 1)\n                            ? script.callReturn()\n                            : this.die();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.when_press_remote_key(%2)',\n                                blockType: 'event',\n                                passTest: true,\n                                textParams: [\n                                    undefined,\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 디지털 입력 %2 이(가) 들어왔을 때\n                connectlite_when_input_digital_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: {\n                                x: 0,\n                                y: -2,\n                            },\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'connectlite_dropdown_digital_key',\n                            },\n                        ],\n                        type: 'connectlite_when_input_digital_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_event',\n                    isNotFor: ['ProboConnectLite'],\n                    event: 'connectlite_event_digital_input',\n                    func(sprite, script) {\n                        const key = Entry.ProboConnectLite.getDigitalKey(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboConnectLite.getDigitalStateValue(key);\n                        return (value)\n                            ? script.callReturn()\n                            : this.die();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.when_input_digital_value(%2)',\n                                blockType: 'event',\n                                passTest: true,\n                                textParams: [\n                                    undefined,\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Setting Block\n                ///========================================================================================\n                // 입력포트 %1 을(를) %2 센서로 설정 %3\n                connectlite_set_sensor_setting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_setting_sensor_key',\n                            },\n                            null,\n                        ],\n                        type: 'connectlite_set_sensor_setting',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_setting',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboConnectLite.getSettingSensorValue(script.getStringValue('PARAM1'));\n                        const sensorSet = Entry.ProboConnectLite.SensorSet;\n                        sensorSet[key] = value;\n                        Entry.ProboConnectLite.RemoteData.ASET2 = ((sensorSet.AA1 << 4) | sensorSet.AA2) & 0xFF;\n                        Entry.ProboConnectLite.RemoteData.ASET1 = ((sensorSet.AA3 << 4) | sensorSet.AA4) & 0xFF;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_sensor_setting(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Input block\n                ///========================================================================================\n                // 리모컨 입력 %1\n                connectlite_is_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_remote_key',\n                            },\n                        ],\n                        type: 'connectlite_is_remote_key',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getRemoteKey(script.getStringValue('PARAM0'));\n                        return (Entry.ProboConnectLite.InputData.Remote[key] === 1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.is_remote_key(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 디지털 입력 %1\n                connectlite_is_digital_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_digital_key',\n                            },\n                        ],\n                        type: 'connectlite_is_digital_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getDigitalKey(script.getStringValue('PARAM0'));\n                        return Entry.ProboConnectLite.getDigitalStateValue(key);;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.is_digital_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 아날로그 입력 %1\n                connectlite_get_analog_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'connectlite_get_analog_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        return  (Entry.ProboConnectLite.SensorSet[key] === 5)  // 5: 압력\n                            ? 255 - Entry.ProboConnectLite.InputData.Analog[key]\n                            : Entry.ProboConnectLite.InputData.Analog[key];\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_analog_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 3가속도 %1의 X축\n                connectlite_get_tri_axis_acceler_x: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'connectlite_get_tri_axis_acceler_x',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAxisKey(script.getStringValue('PARAM0'), \"X\");\n                        const value = Entry.ProboConnectLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_tri_axis_acceler_x(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 3가속도 %1의 Y축\n                connectlite_get_tri_axis_acceler_y: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'connectlite_get_tri_axis_acceler_y',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAxisKey(script.getStringValue('PARAM0'),\"Y\");\n                        const value = Entry.ProboConnectLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_tri_axis_acceler_y(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 3가속도 %1의 Z축\n                connectlite_get_tri_axis_acceler_z: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'connectlite_get_tri_axis_acceler_z',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAxisKey(script.getStringValue('PARAM0'), \"Z\");\n                        const value = Entry.ProboConnectLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_tri_axis_acceler_z(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n\n                // %1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환\n                connectlite_get_value_mapping: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 255 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 100 ],\n                            },\n                        ],\n                        type: 'connectlite_get_value_mapping',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                        PARAM2: 2,\n                        PARAM3: 3,\n                        PARAM4: 4,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const inMin = script.getNumberValue('PARAM1');\n                        const inMax = script.getNumberValue('PARAM2');\n                        const outMin = script.getNumberValue('PARAM3');\n                        const outMax = script.getNumberValue('PARAM4');\n                        const data = (Entry.ProboConnectLite.SensorSet[key] === 5) // 5: 압력\n                            ? 255 - Entry.ProboConnectLite.InputData.Analog[key]\n                            : Entry.ProboConnectLite.InputData.Analog[key];\n                        return (data - inMin) * (outMax-outMin) / (inMax - inMin) + outMin;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_value_mapping(%1, %2, %3, %4, %5)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 컬러 센서 %1 이(가) %2 인가?\n                connectlite_is_color_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_sensor_color_key',\n                            },\n                        ],\n                        type: 'connectlite_is_color_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const key1 = Entry.ProboConnectLite.getColorSensorKey(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboConnectLite.InputData.Analog[key0];\n                        const color = Entry.ProboConnectLite.Color;\n                        return ((color[key1].Min <= value) && (value <= color[key1].Max));\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.is_color_value(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 컬러 센서 %1 의 색상\n                connectlite_get_color_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'connectlite_get_color_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboConnectLite.InputData.Analog[key0];\n                        const color = Entry.ProboConnectLite.Color;\n\n                        for (let i = 1; i < 7; i++) {\n                            const key1 =  Entry.ProboConnectLite.getColorSensorKey(i.toString());\n                            if ((color[key1].Min <= value) && (value <= color[key1].Max)) {\n                                switch (i) {\n                                    case 1:\n                                        return Lang.template.connectlite_item_color_red;\n                                    case 2:\n                                        return Lang.template.connectlite_item_color_green;\n                                    case 3:\n                                        return Lang.template.connectlite_item_color_blue;\n                                    case 4:\n                                        return Lang.template.connectlite_item_color_yellow;\n                                    case 5:\n                                        return Lang.template.connectlite_item_color_black;\n                                    case 6:\n                                        return Lang.template.connectlite_item_color_white;\n                                    default:\n                                        return Lang.template.connectlite_item_error;\n                                }\n                            }\n                        }\n\n                        return Lang.template.connectlite_item_nothing;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_color_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 을 %3 값으로 정하기 %4\n                connectlite_set_infinite_setting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        }\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            null\n                        ],\n                        type: 'connectlite_set_infinite_setting',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        let count = 0;\n                        let value = script.getNumberValue('PARAM2');\n\n                        if (value != 0) {\n                            count = Math.floor(value / 255);\n                            value = value % 255;\n                        } else {\n                            value = 0;\n                            count = 0;\n                        }\n\n                        Entry.ProboConnectLite.Infinite.Buff[key] = Entry.ProboConnectLite.InputData.Analog[key];\n                        Entry.ProboConnectLite.Infinite.Start[key] = Entry.ProboConnectLite.InputData.Analog[key] - value;\n                        Entry.ProboConnectLite.Infinite.Count[key] = count;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_infinite_setting(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 지름 %3 의 mm 값\n                connectlite_get_infinite_mm_diameter: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 53.5 ],\n                            },\n                        ],\n                        type: 'connectlite_get_infinite_mm_diameter',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        const radius = script.getNumberValue('PARAM2') / 2;\n                        const pi = 3.141592;\n                        const infinite = Entry.ProboConnectLite.Infinite;\n                        let value = Entry.ProboConnectLite.InputData.Analog[key];\n\n                        if (value < infinite.Buff[key] - 150) {\n                            infinite.Count[key]++;\n                        } else if (value > infinite.Buff[key] + 150) {\n                            infinite.Count[key]--;\n                        }\n                        infinite.Buff[key] = value;\n                        value = (infinite.Buff[key] - infinite.Start[key]) + (infinite.Count[key] * 255);\n\n                        return Number((2 * pi * radius) / 255 * value).toFixed(3);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_infinite_mm_diameter(%1, %2, %3)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 의  %3\n                connectlite_get_infinite_transform_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_sensor_angle_key',\n                            },\n                        ],\n                        type: 'connectlite_get_infinite_transform_input',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key1 = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        const key2 = Entry.ProboConnectLite.getSensorAngleKey(script.getStringValue('PARAM2'));\n                        const anlogValue = Entry.ProboConnectLite.InputData.Analog[key1];\n                        const infinite = Entry.ProboConnectLite.Infinite;\n\n                        if (anlogValue < (infinite.Buff[key1] - 150)) {\n                            infinite.Count[key1]++;\n                        } else if (anlogValue > (infinite.Buff[key1] + 150)) {\n                            infinite.Count[key1]--;\n                        }\n                        infinite.Buff[key1] = anlogValue;\n                        const value = (infinite.Buff[key1] - infinite.Start[key1]) + (infinite.Count[key1] * 255);\n\n                        switch (key2) {\n                            case 'IS1':\n                                return value;\n                            case 'IS2':\n                                return (value > 0)\n                                    ? Math.floor((value % 255) * 1.41732)\n                                    : Math.ceil((value % 255) * 1.41732)\n                            case 'IS3':\n                                return Number((360 / 255) * anlogValue).toFixed(0);\n                            case 'IS4':\n                                return (value > 0)\n                                    ? Math.floor(value / 255)\n                                    : Math.ceil(value / 255);\n                            default:\n                                return Lang.template.connectlite_item_nothing;\n\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_infinite_transform_input(%1, %2, %3)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 멀티키 센서 %1의 %2\n                connectlite_is_multi_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_multikey_key',\n                            },\n                        ],\n                        type: 'connectlite_is_multi_sensor',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboConnectLite.getMultiKeyValue(script.getStringValue('PARAM1'));\n                        return (Entry.ProboConnectLite.InputData.Analog[key] >> value) & 0x01;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.is_multi_sensor(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 분배 스위치 %1의 %2\n                connectlite_is_multi_switch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_multikey_key',\n                            },\n                        ],\n                        type: 'connectlite_is_multi_switch',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboConnectLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboConnectLite.getMultiKeyValue(script.getStringValue('PARAM1'));\n                        const analog = Entry.ProboConnectLite.InputData.Analog[key0];\n                        const multySwitch = Entry.ProboConnectLite.MultiSwitch;\n\n                        for (let i = 0; i < 8; i++) {\n                            const key = 'Key' + (i + 1).toString();\n                            if (multySwitch[key].Min <= analog && analog <= multySwitch[key].Max) {\n                                return (value === i);\n                            }\n                        }\n\n                        return false;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.is_multi_switch(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 확장 디지털 입력 %1 의 %2\n                connectlite_is_extension_digital_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_extension_digital_key',\n                            },\n                        ],\n                        type: 'connectlite_is_extension_digital_input',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAxisKey(script.getStringValue('PARAM0'), 'X');\n                        const shift = Entry.ProboConnectLite.getExtentionDigitalValue(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboConnectLite.InputData.Acceler[key];\n                        return ((value >> shift) === 1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.is_extension_digital_input(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 확장 아날로그 입력 %1 의 %2\n                connectlite_get_extension_analog_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_extension_analog_key',\n                            },\n                        ],\n                        type: 'connectlite_get_extension_analog_input',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getAxisKey(\n                            script.getStringValue('PARAM0'),\n                            Entry.ProboConnectLite.getExtentionAnalogKey(script.getStringValue('PARAM1'))\n                        );\n                        const value = Entry.ProboConnectLite.InputData.Acceler[key];\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_extension_analog_input(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM %1 주소의 값 호출하기 %2\n                connectlite_set_eeprom_call: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0']\n                            },\n                            null\n                        ],\n                        type: 'connectlite_set_eeprom_call',\n                    },\n                    paramsKeyMap: {\n                        ADDRESS: 0,\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const address = script.getNumberValue('ADDRESS', script);\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const ms = 50;\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboConnectLite.EEPROM.Count = Entry.ProboConnectLite.InputData.EEPROM.EC;\n                            Entry.ProboConnectLite.RemoteData['EEPR4'] = 0x40;\n                            Entry.ProboConnectLite.RemoteData['EEPR3'] = address;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboConnectLite.EEPROM.Buff =\n                                (Entry.ProboConnectLite.InputData.EEPROM.EEPR2 << 8) +\n                                Entry.ProboConnectLite.InputData.EEPROM.EEPR1;\n                            Entry.ProboConnectLite.RemoteData['EEPR4'] = 0;\n                            Entry.ProboConnectLite.RemoteData['EEPR3'] = 0;\n\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_eeprom_call(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM 주소의 값\n                connectlite_get_eeprom_address_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'connectlite_get_eeprom_address_value',\n                    },\n                    class: 'connectlite_input',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const count = Entry.ProboConnectLite.EEPROM.Count;\n\n                        return (Entry.ProboConnectLite.InputData.EEPROM.EC != count)\n                            ? Entry.ProboConnectLite.EEPROM.Buff\n                            : 0;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.get_eeprom_address_value',\n                                blockType: 'param',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n\n                ///========================================================================================\n                /// output block\n                ///========================================================================================\n                // DC 모터 %1 을(를) %2 속도로 회전 %3\n                connectlite_set_dc_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_dc_1_all_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_velocity_key',\n                            },\n                            null,\n                        ],\n                        type: 'connectlite_set_dc_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getDckey(script.getStringValue('PARAM0'));\n                        const value = script.getNumberValue('PARAM1');\n\n                        switch (key) {\n                            case 'DC5':\n                                Entry.ProboConnectLite.RemoteData['DC1'] = value;\n                                Entry.ProboConnectLite.RemoteData['DC2'] = value;\n                                break;\n                            case 'DC6':\n                                Entry.ProboConnectLite.RemoteData['DC3'] = value;\n                                Entry.ProboConnectLite.RemoteData['DC4'] = value;\n                                break;\n                            case 'DC7':\n                                Entry.ProboConnectLite.RemoteData['DC1'] = value;\n                                Entry.ProboConnectLite.RemoteData['DC2'] = value;\n                                Entry.ProboConnectLite.RemoteData['DC3'] = value;\n                                Entry.ProboConnectLite.RemoteData['DC4'] = value;\n                                break;\n                            default:\n                                Entry.ProboConnectLite.RemoteData[key] = value;\n                                break;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_dc_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 서보 모터 %1 의 위치를 %2 로 이동 %3\n                connectlite_set_servo_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_servo_position_key',\n                            },\n                            null,\n                        ],\n                        type: 'connectlite_set_servo_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = script.getNumberValue('PARAM1');\n                        Entry.ProboConnectLite.RemoteData[key] = Math.min(Math.max(value, 0), 100);\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_servo_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // S 모터 %1 을(를) %2 속도로 회전 %3\n                connectlite_set_s_dc_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_velocity_key',\n                            },\n                            null,\n                        ],\n                        type: 'connectlite_set_s_dc_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getServoKey(script.getStringValue('PARAM0'));\n                        const speed = script.getNumberValue('PARAM1');\n                        const value = Math.min(Math.max(speed, -20), 20) + 148;\n\n                        switch (key) {\n                            case 'Servo5':\n                                Entry.ProboConnectLite.RemoteData['Servo1'] = value;\n                                Entry.ProboConnectLite.RemoteData['Servo2'] = value;\n                                break;\n                            case 'Servo6':\n                                Entry.ProboConnectLite.RemoteData['Servo3'] = value;\n                                Entry.ProboConnectLite.RemoteData['Servo4'] = value;\n                                break;\n                            default:\n                                Entry.ProboConnectLite.RemoteData[key] = value;\n                                break;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_s_dc_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 출력핀 %1 을(를) %2 %3\n                connectlite_set_port_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_on_off_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_set_port_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getPortKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboConnectLite.getPortToggleValue(script.getStringValue('PARAM1'));\n\n                        Entry.ProboConnectLite.RemoteData[key] = value;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_port_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2 음표로 연주하기 %3\n                connectlite_play_melody_note_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_pitch_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_note_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_play_melody_note_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            const pitch = Entry.ProboConnectLite.getPitchValue(script.getNumberValue('PARAM0'));\n                            const note = Entry.ProboConnectLite.getNoteKey(script.getStringValue('PARAM1'));\n                            const ms = Entry.ProboConnectLite.Note[note];\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboConnectLite.RemoteData['MEL2'] = pitch >> 8;\n                            Entry.ProboConnectLite.RemoteData['MEL1'] = pitch;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboConnectLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboConnectLite.RemoteData['MEL1'] = 0;\n\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.play_melody_note_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2 초 동안 연주하기 %3\n                connectlite_play_melody_sec_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_pitch_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_time_1_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_play_melody_sec_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            const pitch = Entry.ProboConnectLite.getPitchValue(script.getNumberValue('PARAM0'));\n                            const sec = script.getNumberValue('PARAM1');\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboConnectLite.RemoteData['MEL2'] = pitch >> 8;\n                            Entry.ProboConnectLite.RemoteData['MEL1'] = pitch;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboConnectLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboConnectLite.RemoteData['MEL1'] = 0;\n\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.play_melody_sec_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) 연주하기 %2\n                connectlite_play_melody_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_pitch_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_play_melody_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const pitch = Entry.ProboConnectLite.getPitchValue(script.getNumberValue('PARAM0'));\n                        Entry.ProboConnectLite.RemoteData['MEL2'] = pitch >> 8;\n                        Entry.ProboConnectLite.RemoteData['MEL1'] = pitch;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.play_melody_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 값을(를) %2 초 동안 연주하기 %3\n                connectlite_play_value_sec_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 35391 ],\n                            },\n                            {\n                                type: 'connectlite_dropdown_time_1_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_play_value_sec_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const melody = script.getNumberValue('PARAM0');\n                            const sec = script.getNumberValue('PARAM1');\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboConnectLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                            Entry.ProboConnectLite.RemoteData['MEL1'] = melody & 0xff;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboConnectLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboConnectLite.RemoteData['MEL1'] = 0;\n\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.play_melody_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 1 값을(를) 연주하기 %2\n                connectlite_play_value_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 35391 ],\n                            },\n                            null\n                        ],\n                        type: 'connectlite_play_value_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const melody = script.getNumberValue('PARAM0');\n                        Entry.ProboConnectLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                        Entry.ProboConnectLite.RemoteData['MEL1'] = melody & 0xff;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.play_melody_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2초 간격으로 재생하기 %3\n                connectlite_play_melody_track_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_melody_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_time_2_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_play_melody_track_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        function getTrackStep(track,script){\n                            if(!script.isStart){\n                                script.isStart = true;\n                                script.trackStep = 0;\n                            }\n                            else {\n                                script.trackStep++;\n                            }\n                            const sec = script.getNumberValue('PARAM1');\n                            const fps = Entry.FPS || 60;\n                            const melody = Entry.ProboConnectLite.Track[track][script.trackStep];\n\n                            Entry.ProboConnectLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                            Entry.ProboConnectLite.RemoteData['MEL1'] = melody & 0xff;\n                            script.timeFlag = 1;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n                        }\n                        const TR = Entry.ProboConnectLite.getMelodyValue(\n                            script.getStringValue('PARAM0')\n                        );\n                        if (!script.isStart) {\n                            switch(TR) {\n                                case 0 :\n                                    script.maxStep = 6;\n                                    break;\n                                case 1 :\n                                    script.maxStep = 7;\n                                    break;\n                                case 2 :\n                                    script.maxStep = 3;\n                                    break;\n                                case 3 :\n                                    script.maxStep = 3;\n                                    break;\n                            }\n                            getTrackStep(TR,script);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else if (script.trackStep < script.maxStep){\n                            getTrackStep(TR,script);\n                            return script;\n                        } else {\n                            Entry.ProboConnectLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboConnectLite.RemoteData['MEL1'] = 0;\n\n                            delete script.trackStep;\n                            delete script.maxStep;\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.play_melody_track_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 멜로디 중지 %1\n                connectlite_play_melody_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                        type: 'connectlite_play_melody_off',\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        Entry.ProboConnectLite.RemoteData['MEL2'] = 0;\n                        Entry.ProboConnectLite.RemoteData['MEL1'] = 0;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.play_melody_track_output',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 을(를) %2 으로 켜기 %3\n                connectlite_set_rgbled_on_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_rgb_color_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_set_rgbled_on_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboConnectLite.getRgbToggleValue(script.getStringValue('PARAM1'));\n                        Entry.ProboConnectLite.RemoteData[key] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_rgbled_on_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 을(를) 끄기 %2\n                connectlite_set_rgbled_off_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_port_1_4_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_set_rgbled_off_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboConnectLite.getRgbToggleValue('0');\n                        Entry.ProboConnectLite.RemoteData[key] = value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_rgbled_off_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 %2 으로 %3 초 간격 %4\n                connectlite_set_rgbled_flashing_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_rgb_color_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_time_3',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_set_rgbled_flashing_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboConnectLite.getRgbTwinkleValue(\n                            script.getStringValue('PARAM1'),\n                            script.getNumberValue('PARAM2')\n                        );\n                        Entry.ProboConnectLite.RemoteData[key] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_rgbled_flashing_output(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 을(를) %2 으로 디밍 %3\n                connectlite_set_rgbled_dimming_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'connectlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'connectlite_dropdown_rgb_color_key',\n                            },\n                            null\n                        ],\n                        type: 'connectlite_set_rgbled_dimming_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboConnectLite.getServoKey(script.getStringValue('PARAM0'));\n                        const color = Entry.ProboConnectLite.getRgbDimmingValue(script.getStringValue('PARAM1'));\n                        Entry.ProboConnectLite.RemoteData[key] = color;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_rgbled_dimming_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // FND를 %1 (으)로 설정 %2\n                connectlite_set_fnd_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            null\n                        ],\n                        type: 'connectlite_set_fnd_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const value = script.getNumberValue('PARAM0');\n                        Entry.ProboConnectLite.RemoteData['FND'] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_fnd_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // FND 끄기 %1\n                connectlite_set_fnd_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                        type: 'connectlite_set_fnd_off',\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        Entry.ProboConnectLite.RemoteData['FND'] = 100;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_fnd_off',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM %1 주소에 %2 값 설정하기 %3\n                connectlite_set_eeprom_write: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 0 ]\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ]\n                            },\n                            null,\n                        ],\n                        type: 'connectlite_set_eeprom_write',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'connectlite_output',\n                    isNotFor: ['ProboConnectLite'],\n                    func: function(sprite, script) {\n                        const address = script.getNumberValue('PARAM0');\n                        const value = script.getNumberValue('PARAM1');\n\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const ms = 50;\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboConnectLite.RemoteData['EEPR4'] = 0x80;\n                            Entry.ProboConnectLite.RemoteData['EEPR3'] = address;\n                            Entry.ProboConnectLite.RemoteData['EEPR2'] = (value >> 8) & 0xff;\n                            Entry.ProboConnectLite.RemoteData['EEPR1'] = value & 0xff;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboConnectLite.RemoteData['EEPR4'] = 0x40;\n                            Entry.ProboConnectLite.RemoteData['EEPR3'] = address;\n                            Entry.ProboConnectLite.RemoteData['EEPR2'] = 0;\n                            Entry.ProboConnectLite.RemoteData['EEPR1'] = 0;\n\n                            setTimeout(function() {\n                                Entry.ProboConnectLite.RemoteData['EEPR4'] = 0;\n                                Entry.ProboConnectLite.RemoteData['EEPR3'] = 0;\n                                Entry.ProboConnectLite.RemoteData['EEPR2'] = 0;\n                                Entry.ProboConnectLite.RemoteData['EEPR1'] = 0;\n                            }, 100);\n\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboConnectLite.set_eeprom_write(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n            }; // getBlock() return;\n        }\n    })();\n})();\n\nmodule.exports = Entry.ProboConnectLite;"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_alux_nemo_lite.js",
    "content": "'use strict';\n\nconst _throttle = require('lodash/throttle');\n\n(function () {\n    const NEMOLITE_INDEX = 0x42; //66\n    const RELEASE_VERSION = 1;\n    const SERIAL_INTERVAL = 32;\n    const EVENT_INTERVAL = 16;\n    const SEND_PACKET_LENGTH = 27; // 패킷 전송전 text + checksum 길이가 더해져야 한다.\n    const RECEIVED_PACKET_LENGTH = 24;\n    Entry.ProboNemoLite = new (class ProboNemoLite {\n        //region constructor\n        constructor() {\n            this.id = '630101';\n            this.name = 'ProboNemoLite';\n            this.url = 'https://imssam.me';\n            this.imageName = 'alux_nemo_lite.png';\n            this.title = {\n                ko: '네모',\n                en: 'Nemo',\n            };\n            this.portData = {\n                baudRate: 115200,\n                duration: SERIAL_INTERVAL,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 128,\n                connectionType: 'bytestream',\n                constantServing: 'ReadOnly',\n            };\n\n            const eventSetting = {\n                leading: true,\n                trailing: false,\n            };\n            this.buttonEvent = _throttle(\n                () => {\n                    const prevFlag = this.sendFlag;\n                    try {\n                        Entry.engine.fireEvent('nemolite_event_button');\n                    } catch (e) {\n                    } finally {\n                        this.sendFlag = prevFlag;\n                    }\n                },\n                EVENT_INTERVAL,\n                eventSetting\n            );\n            this.motionEvent = _throttle(\n                () => {\n                    const prevFlag = this.sendFlag;\n                    try {\n                        Entry.engine.fireEvent('nemolite_event_motion');\n                    } catch (e) {\n                    } finally {\n                        this.sendFlag = prevFlag;\n                    }\n                },\n                EVENT_INTERVAL,\n                eventSetting\n            );\n\n            this.qRear = 0;\n            this.qFront = 0;\n            this.qSize = 128;\n            this.qBuffer = new Uint8Array(this.qSize + 2).fill(-1);\n            this.receivedPacket = new Uint8Array(RECEIVED_PACKET_LENGTH).fill(-1);\n            this.sendPacket = new Uint8Array(SEND_PACKET_LENGTH).fill(0);\n            this.textPacket = new Uint8Array(0).fill(0);\n            this.pLength = 0; // packet length\n            this.process = false; // packet process\n\n            this.version = 0;\n            this.sendFlag = true;\n\n            this.soundKeyArray = [\n                30578, 28861, 27241, 25713, 24270, 22908, 21622, 20408, 19263, 18182, 17161, 16198,\n            ];\n            this.sendIndex = {\n                cmd0: 0,\n                cmd1: 1,\n                size: 2,\n                led7x1: 3,\n                led7x2: 4,\n                led7x3: 5,\n                led7x4: 6,\n                led7x5: 7,\n                led7x6: 8,\n                led7x7: 9,\n                led7x8: 10,\n                led7x9: 11,\n                led7x10: 12,\n                led7x11: 13,\n                led7x12: 14,\n                led7x13: 15,\n                led7x14: 16,\n                ledMs0: 17,\n                ledMs1: 18,\n                ledPixel: 19,\n                ledSet: 20,\n                portSet: 21,\n                melody: 22,\n                buzzer0: 23,\n                buzzer1: 24,\n                ledRead: 25,\n                textSize: 26, // 텍스트 크기는 따로 계산하여 입력한다.\n            };\n            this.receivedIndex = {\n                cmd0: 0,\n                cmd1: 1,\n                size: 2,\n                accelAx0: 3,\n                accelAx1: 4,\n                accelAy0: 5,\n                accelAy1: 6,\n                accelAz0: 7,\n                accelAz1: 8,\n                accelALi: 9, // Linear\n                accelD: 10, // Motion\n                illuminance: 11,\n                extensionAnalog: 12,\n                extensionDigital: 13,\n                switchAnalog1: 14,\n                switchAnalog2: 15,\n                switchAnalog3: 16,\n                switchAnalog4: 17,\n                switchDigitalAB: 18,\n                switchDigitalCD: 19,\n                ledRead: 20,\n                compass: 21,\n                timeCheck: 22,\n                checksum: 23,\n            };\n\n            this.blockMenuBlocks = [\n                'nemolite_dropdown_button',\n                'nemolite_dropdown_button_now_state',\n                'nemolite_dropdown_button_state_question',\n                'nemolite_dropdown_motion',\n                'nemolite_dropdown_coordinate_acceleration',\n                'nemolite_dropdown_led_icon',\n                'nemolite_dropdown_switch',\n                'nemolite_dropdown_melody',\n                'nemolite_dropdown_keyboard',\n                'nemolite_dropdown_extension_sensor',\n                'nemolite_dropdown_sensor_mode',\n                'nemolite_dropdown_direction',\n                'nemolite_dropdown_index_0_5',\n                'nemolite_dropdown_index_1_5',\n                'nemolite_dropdown_led_columm',\n\n                'nemolite_title_namo_input',\n                'nemolite_when_button_state',\n                'nemolite_when_motion_sensing',\n                'nemolite_is_button_state',\n                'nemolite_is_motion_sensing',\n                'nemolite_is_led_state_value',\n                'nemolite_get_button_analog_value',\n                'nemolite_get_acceleration_value',\n                'nemolite_get_illuminance_value',\n                'nemolite_get_convert_value',\n\n                'nemolite_title_namo_output',\n                'nemolite_set_display_led_icon',\n                'nemolite_set_display_led_custom_columm',\n                'nemolite_set_display_led_text',\n                'nemolite_set_delete_all_led',\n                'nemolite_set_toggle_led_pixel',\n                'nemolite_set_play_melody',\n                'nemolite_set_play_melody_until_the_end',\n                'nemolite_set_play_note',\n                'nemolite_set_play_note_for_seconds',\n                'nemolite_set_stop_all_sound',\n\n                'nemolite_title_namo_extension',\n                'nemolite_ext_set_extension',\n                'nemolite_ext_set_extension_value',\n                'nemolite_ext_is_extension_state',\n                'nemolite_ext_get_extension_anlog_value',\n                'nemolite_ext_get_extension_custom_value',\n                'nemolite_ext_set_compass_value',\n                'nemolite_ext_get_compass_analog_value',\n                'nemolite_ext_get_compass_custom_value',\n                'memolite_ext_is_compass_direction',\n            ];\n        }\n        //endregion\n\n        //region setlanguage\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        nemolite_line_emtpy: ' ',\n                        nemolite_namo_input: '네모 입력',\n                        nemolite_namo_output: '네모 출력',\n                        nemolite_namo_extension: '네모 확장',\n\n                        nemolite_item_s1: 'S1',\n                        nemolite_item_s2: 'S2',\n                        nemolite_item_s3: 'S3',\n                        nemolite_item_s4: 'S4',\n                        nemolite_item_motion_1: '앞으로 기울임',\n                        nemolite_item_motion_2: '뒤로 기울임',\n                        nemolite_item_motion_3: '왼쪽으로 기울임',\n                        nemolite_item_motion_4: '오른쪽으로 기울임',\n                        nemolite_item_motion_5: '위로 놓음',\n                        nemolite_item_motion_6: '아래로 놓음',\n                        nemolite_item_motion_7: '세워 놓음',\n                        nemolite_item_motion_8: '충격 받음',\n                        nemolite_item_smile: '웃음',\n                        nemolite_item_not_much: '별로',\n                        nemolite_item_good: '좋음',\n                        nemolite_item_bad: '나쁨',\n                        nemolite_item_wink: '윙크',\n                        nemolite_item_cry: '울음',\n                        nemolite_item_absurd: '어이없음',\n                        nemolite_item_peck: '뽀뽀',\n                        nemolite_item_arrow_1: '화살표 1',\n                        nemolite_item_arrow_2: '화살표 2',\n                        nemolite_item_arrow_3: '화살표 3',\n                        nemolite_item_arrow_4: '화살표 4',\n                        nemolite_item_arrow_5: '화살표 5',\n                        nemolite_item_arrow_6: '화살표 6',\n                        nemolite_item_arrow_7: '화살표 7',\n                        nemolite_item_arrow_8: '화살표 8',\n                        nemolite_item_spade: '스페이드',\n                        nemolite_item_club: '클럽',\n                        nemolite_item_diamond: '다이아몬드',\n                        nemolite_item_heart: '하트',\n                        nemolite_item_circle: '원',\n                        nemolite_item_x: '엑스',\n                        nemolite_item_triangle: '세모',\n                        nemolite_item_square: '네모',\n                        nemolite_item_note_1: '음표 1',\n                        nemolite_item_note_2: '음표 2',\n                        nemolite_item_note_3: '음표 3',\n                        nemolite_item_dice_1: '주사위 1',\n                        nemolite_item_dice_2: '주사위 2',\n                        nemolite_item_dice_3: '주사위 3',\n                        nemolite_item_dice_4: '주사위 4',\n                        nemolite_item_dice_5: '주사위 5',\n                        nemolite_item_dice_6: '주사위 6',\n                        nemolite_item_first: '첫번째',\n                        nemolite_item_second: '두번째',\n                        nemolite_item_third: '세번째',\n                        nemolite_item_fourth: '네번째',\n                        nemolite_item_fifth: '다섯번째',\n                        nemolite_item_sixth: '여섯번째',\n                        nemolite_item_seventh: '일곱번째',\n                        nemolite_item_eighth: '여덟번째',\n                        nemolite_item_ninth: '아홉번째',\n                        nemolite_item_tenth: '열번째',\n                        nemolite_itme_eleventh: '열한번째',\n                        nemolite_item_twelfth: '열두번째',\n                        nemolite_item_thirteenth: '열세번째',\n                        nemolite_itme_fourteenth: '열네번째',\n                        nemolite_item_is_press: '눌려 있을 때',\n                        nemolite_item_is_fall: '눌렀을 때',\n                        nemolite_item_is_rise: '뗐을 때',\n                        nemolite_item_is_both: '누르거나 뗐을 때',\n                        nemolite_item_has_press: '눌려 있는가',\n                        nemolite_item_has_fall: '눌렀는가',\n                        nemolite_item_has_rise: '뗐는가',\n                        nemolite_item_has_both: '누르거나 뗐는가',\n                        nemolite_item_axis_x: 'X축',\n                        nemolite_item_axis_y: 'Y축',\n                        nemolite_item_axis_z: 'Z축',\n                        nemolite_item_linear_acceleration: '선형 가속도',\n                        nemolite_item_off_text: '끄기',\n                        nemolite_item_on_text: '켜기',\n                        nemolite_item_off_icon: '□',\n                        nemolite_item_on_icon: '■',\n                        nemolite_item_toggle: '토글',\n                        nemolite_item_do_re_mi_song: '도레미송',\n                        nemolite_item_an_island_baby: '섬집아기',\n                        nemolite_item_twinkle_twinkle_little_star: '작은별',\n                        nemolite_item_spring_in_my_hometown: '고향의 봄',\n                        nemolite_item_for_elise: '엘리제를 위하여',\n                        nemolite_item_celebrated_chop_waltz: '젓가락 행진곡',\n                        nemolite_item_happy_birthday_to_you: '생일 축하곡',\n                        nemolite_item_lc: 'C(0)',\n                        nemolite_item_lcs: 'C#(1)',\n                        nemolite_item_ld: 'D(2)',\n                        nemolite_item_lds: 'D#(3)',\n                        nemolite_item_le: 'E(4)',\n                        nemolite_item_lf: 'F(5)',\n                        nemolite_item_lfs: 'F#(6)',\n                        nemolite_item_lg: 'G(7)',\n                        nemolite_item_lgs: 'G#(8)',\n                        nemolite_item_la: 'A(9)',\n                        nemolite_item_las: 'A#(10)',\n                        nemolite_item_lb: 'B(11)',\n                        nemolite_item_mc: 'C(12)',\n                        nemolite_item_mcs: 'C#(13)',\n                        nemolite_item_md: 'D(14)',\n                        nemolite_item_mds: 'D#(15)',\n                        nemolite_item_me: 'E(16)',\n                        nemolite_item_mf: 'F(17)',\n                        nemolite_item_mfs: 'F#(18)',\n                        nemolite_item_mg: 'G(19)',\n                        nemolite_item_mgs: 'G#(20)',\n                        nemolite_item_ma: 'A(21)',\n                        nemolite_item_mas: 'A#(22)',\n                        nemolite_item_mb: 'B(23)',\n                        nemolite_item_hc: 'C(24)',\n                        nemolite_item_switch: '스위치',\n                        nemolite_item_infrared_ray: '적외선',\n                        nemolite_item_magnet: '자석',\n                        nemolite_item_rotary: '회전',\n                        nemolite_item_illuminance: '조도',\n                        nemolite_item_sound: '소리',\n                        nemolite_item_tilt: '기울기',\n                        nemolite_item_pressure: '압력',\n                        nemolite_item_heart_rate: '심박',\n                        nemolite_item_touch: '터치',\n                        nemolite_item_value: '값',\n                        nemolite_item_angle: '각도',\n                        nemolite_item_absolute_angle: '절대 각도',\n                        nemolite_item_turn_value: '회전 수',\n                        nemolite_item_east: '동쪽',\n                        nemolite_item_west: '서쪽',\n                        nemolite_item_south: '남쪽',\n                        nemolite_item_north: '북쪽',\n\n                        nemolite_event_button_state: '%1 %2 버튼을 %3',\n                        nemolite_event_motion: '%1 %2 이 감지되었을 때',\n                        nemolite_is_button_state: '%1 버튼이 %2 ?',\n                        nemolite_is_motion_sensing: '%1 이 감지되었는가?',\n                        nemolite_is_led_state_value: 'LED X: %1 Y: %2 상태값',\n                        nemolite_get_button_analog_value: '%1 버튼의 아날로그 값',\n                        nemolite_get_acceleration_value: '가속도 센서 %1 의 값',\n                        nemolite_get_illuminance_value: '조도 센서의 값',\n                        nemolite_get_convert_value: '%1 의 값 %2 ~ %3 을 %4 ~ %5 으(로) 변환',\n\n                        nemolite_set_display_led_icon: 'LED 아이콘 %1 을 %2 속도로 출력 %3',\n                        nemolite_set_display_led_custom_columm:\n                            'LED %1 열의 %2%3%4%5%6%7%8 을 %9 속도로 출력 %10',\n                        nemolite_set_display_led_text: 'LED %1 문자열을 %2 속도로 출력 %3',\n                        nemolite_set_delete_all_led: 'LED 출력 지우기 %1',\n                        nemolite_set_toggle_led_pixel: 'LED X: %1 Y: %2 %3 %4',\n                        nemolite_set_play_melody: '멜로디 %1 재생하기 %2',\n                        nemolite_set_play_melody_until_the_end: '멜로디 %1 끝까지 재생하기 %2',\n                        nemolite_set_play_note: '%1 음을 재생하기 %2',\n                        nemolite_set_play_note_for_seconds: '%1 음을 %2 초 동안 재생하기 %3',\n                        nemolite_set_stop_all_sound: '모든 소리 정지 %1',\n\n                        nemolite_ext_set_extension: '확장센서를 %1 (으)로 설정 %2',\n                        nemolite_ext_set_extension_value: '확장센서를 %1 값으로 정하기',\n                        nemolite_ext_is_extension_state: '확장센서 %1 ? %2',\n                        nemolite_ext_get_extension_anlog_value: '확장센서의 아날로그 값 %1',\n                        nemolite_ext_get_extension_custom_value: '확장센서의 %1',\n                        nemolite_ext_set_compass_value: '나침반센서를 %1 값으로 정하기',\n                        nemolite_ext_get_compass_analog_value: '나침반센서의 아날로그 값 %1',\n                        nemolite_ext_get_compass_custom_value: '나침반센서의 %1',\n                        memolite_ext_is_compass_direction: '나침반센서의 방향이 %1 인가 ?',\n                    },\n                    Device: {\n                        probo_nemolite_lite: '네모',\n                    },\n                    Menus: {\n                        probo_nemolite_lite: '네모',\n                    },\n                },\n                en: {\n                    template: {\n                        nemolite_line_emtpy: ' ',\n                        nemolite_namo_input: 'NAMO INPUT',\n                        nemolite_namo_output: 'NAMO OUTPUT',\n                        nemolite_namo_extension: 'NAMO EXTENSION',\n\n                        nemolite_item_s1: 'S1',\n                        nemolite_item_s2: 'S2',\n                        nemolite_item_s3: 'S3',\n                        nemolite_item_s4: 'S4',\n                        nemolite_item_motion_1: 'Tilting forward',\n                        nemolite_item_motion_2: 'Tilting back',\n                        nemolite_item_motion_3: 'Tilting to the left',\n                        nemolite_item_motion_4: 'Tilting to the right',\n                        nemolite_item_motion_5: 'Put it up',\n                        nemolite_item_motion_6: 'Put it down',\n                        nemolite_item_motion_7: 'Standing up',\n                        nemolite_item_motion_8: 'Impacted',\n                        nemolite_item_smile: 'Smile',\n                        nemolite_item_not_much: 'Not much',\n                        nemolite_item_good: 'Good',\n                        nemolite_item_bad: 'Bad',\n                        nemolite_item_wink: 'Wink',\n                        nemolite_item_cry: 'Cry',\n                        nemolite_item_absurd: 'Absurd',\n                        nemolite_item_peck: 'Peck',\n                        nemolite_item_arrow_1: 'Arrow 1',\n                        nemolite_item_arrow_2: 'Arrow 2',\n                        nemolite_item_arrow_3: 'Arrow 3',\n                        nemolite_item_arrow_4: 'Arrow 4',\n                        nemolite_item_arrow_5: 'Arrow 5',\n                        nemolite_item_arrow_6: 'Arrow 6',\n                        nemolite_item_arrow_7: 'Arrow 7',\n                        nemolite_item_arrow_8: 'Arrow 8',\n                        nemolite_item_spade: 'Spade',\n                        nemolite_item_club: 'Club',\n                        nemolite_item_diamond: 'Diamond',\n                        nemolite_item_heart: 'Heart',\n                        nemolite_item_circle: 'Circle',\n                        nemolite_item_x: 'X',\n                        nemolite_item_triangle: 'Triangle',\n                        nemolite_item_square: 'Square',\n                        nemolite_item_note_1: 'note 1',\n                        nemolite_item_note_2: 'note 2',\n                        nemolite_item_note_3: 'note 3',\n                        nemolite_item_dice_1: 'dice 1',\n                        nemolite_item_dice_2: 'dice 2',\n                        nemolite_item_dice_3: 'dice 3',\n                        nemolite_item_dice_4: 'dice 4',\n                        nemolite_item_dice_5: 'dice 5',\n                        nemolite_item_dice_6: 'dice 6',\n                        nemolite_item_first: 'first',\n                        nemolite_item_second: 'second',\n                        nemolite_item_third: 'third',\n                        nemolite_item_fourth: 'fourth',\n                        nemolite_item_fifth: 'fifth',\n                        nemolite_item_sixth: 'sixth',\n                        nemolite_item_seventh: 'seventh',\n                        nemolite_item_eighth: 'eighth',\n                        nemolite_item_ninth: 'ninth',\n                        nemolite_item_tenth: 'tenth',\n                        nemolite_itme_eleventh: 'eleventh',\n                        nemolite_item_twelfth: 'twelfth',\n                        nemolite_item_thirteenth: 'thirteenth',\n                        nemolite_itme_fourteenth: 'fourteenth',\n                        nemolite_item_is_press: 'is pressing',\n                        nemolite_item_is_fall: 'pressed',\n                        nemolite_item_is_rise: 'released',\n                        nemolite_item_is_both: 'pressed or released',\n                        nemolite_item_has_press: 'has be pressing',\n                        nemolite_item_has_fall: 'has pressed',\n                        nemolite_item_has_rise: 'has released',\n                        nemolite_item_has_both: 'has pressed or has released',\n                        nemolite_item_axis_x: 'X axis',\n                        nemolite_item_axis_y: 'Y axis',\n                        nemolite_item_axis_z: 'Z axis',\n                        nemolite_item_linear_acceleration: 'linear acceleration',\n                        nemolite_item_off_text: 'off',\n                        nemolite_item_on_text: 'on',\n                        nemolite_item_off_icon: '□',\n                        nemolite_item_on_icon: '■',\n                        nemolite_item_toggle: 'toggle',\n                        nemolite_item_do_re_mi_song: 'Do Re Mi Song',\n                        nemolite_item_an_island_baby: 'An Island Baby',\n                        nemolite_item_twinkle_twinkle_little_star: 'Twinkle Twinkle Little Star',\n                        nemolite_item_spring_in_my_hometown: 'Spring in My Hometwon',\n                        nemolite_item_for_elise: 'For Elise',\n                        nemolite_item_celebrated_chop_waltz: 'Celebrate Chop Waltz',\n                        nemolite_item_happy_birthday_to_you: 'Happy Birthday To You',\n                        nemolite_item_lc: 'C(0)',\n                        nemolite_item_lcs: 'C#(1)',\n                        nemolite_item_ld: 'D(2)',\n                        nemolite_item_lds: 'D#(3)',\n                        nemolite_item_le: 'E(4)',\n                        nemolite_item_lf: 'F(5)',\n                        nemolite_item_lfs: 'F#(6)',\n                        nemolite_item_lg: 'G(7)',\n                        nemolite_item_lgs: 'G#(8)',\n                        nemolite_item_la: 'A(9)',\n                        nemolite_item_las: 'A#(10)',\n                        nemolite_item_lb: 'B(11)',\n                        nemolite_item_mc: 'C(12)',\n                        nemolite_item_mcs: 'C#(13)',\n                        nemolite_item_md: 'D(14)',\n                        nemolite_item_mds: 'D#(15)',\n                        nemolite_item_me: 'E(16)',\n                        nemolite_item_mf: 'F(17)',\n                        nemolite_item_mfs: 'F#(18)',\n                        nemolite_item_mg: 'G(19)',\n                        nemolite_item_mgs: 'G#(20)',\n                        nemolite_item_ma: 'A(21)',\n                        nemolite_item_mas: 'A#(22)',\n                        nemolite_item_mb: 'B(23)',\n                        nemolite_item_hc: 'C(24)',\n                        nemolite_item_switch: 'switch',\n                        nemolite_item_infrared_ray: 'infrared ray',\n                        nemolite_item_magnet: 'magnet',\n                        nemolite_item_rotary: 'rotary',\n                        nemolite_item_illuminance: 'illuminance',\n                        nemolite_item_sound: 'sound',\n                        nemolite_item_tilt: 'tilt',\n                        nemolite_item_pressure: 'pressure',\n                        nemolite_item_heart_rate: 'heart rate',\n                        nemolite_item_touch: 'touch',\n                        nemolite_item_value: 'value',\n                        nemolite_item_angle: 'angle',\n                        nemolite_item_absolute_angle: 'absolute angle',\n                        nemolite_item_turn_value: 'rotary value',\n                        nemolite_item_east: 'East',\n                        nemolite_item_west: 'West',\n                        nemolite_item_south: 'South',\n                        nemolite_item_north: 'North',\n\n                        nemolite_event_button_state: 'When %1 button %2',\n                        nemolite_event_motion: 'When %1 motion is detected',\n                        nemolite_is_button_state: 'Is %1 button %2 ?',\n                        nemolite_is_motion_sensing: 'Is %1 motion detected',\n                        nemolite_is_led_state_value: ' LED X: %1 Y: %2 state',\n                        nemolite_get_button_analog_value: 'Analog value of %1 button',\n                        nemolite_get_acceleration_value: 'Acceleration sensor %1 value',\n                        nemolite_get_illuminance_value: 'Value of illuminance sensor',\n                        nemolite_get_convert_value:\n                            'change the value of %1 from %2 ~ %3 to %4 ~ %5',\n\n                        nemolite_set_display_led_icon: 'LED icon %1 output %2 speed %3',\n                        nemolite_set_display_led_custom_columm:\n                            'LED %1 columm %2%3%4%5%6%7%8 at %9 speed %10',\n                        nemolite_set_display_led_text: 'LED %1 string output %2 speed %3',\n                        nemolite_set_delete_all_led: 'Clear LED output %1',\n                        nemolite_set_toggle_led_pixel: 'LED X: %1 Y: %2 %3 %4',\n                        nemolite_set_play_melody: 'Play melody %1 %2',\n                        nemolite_set_play_melody_until_the_end: 'melody %1 play to the end %2',\n                        nemolite_set_play_note: 'Playing note %1 %2',\n                        nemolite_set_play_note_for_seconds: 'Play note %1 for %2 second(s) %3',\n                        nemolite_set_stop_all_sound: 'Stop all sound %1',\n\n                        nemolite_ext_set_extension: 'Extension type set %1 %2',\n                        nemolite_ext_set_extension_value: 'Extension sensor set %1 value ? %2',\n                        nemolite_ext_is_extension_state: 'Is extended sensor %1',\n                        nemolite_ext_get_extension_anlog_value: 'Value of extended sensor %1',\n                        nemolite_ext_get_extension_custom_value: 'Exansion sensor value of %1',\n                        nemolite_ext_set_compass_value: 'Compass sensor value Set %1',\n                        nemolite_ext_get_compass_analog_value: 'Value of compass sensor %1',\n                        nemolite_ext_get_compass_custom_value: 'compass sensor value of %1',\n                        memolite_ext_is_compass_direction: 'Does the rotation sensor point %1 ?',\n                    },\n                    Device: {\n                        probo_nemolite_lite: 'Nemo',\n                    },\n                    Menus: {\n                        probo_nemolite_lite: 'Nemo',\n                    },\n                },\n            };\n        }\n        //endregion\n\n        // 시작하기 및 정지하기 시 기기상태를 초기화한다.\n        //region setZero\n        setZero() {\n            this.sendPacket = new Uint8Array(SEND_PACKET_LENGTH).fill(0);\n            this.getData = {\n                accel: {\n                    x: 0,\n                    y: 0,\n                    z: 0,\n                    linear: 0,\n                },\n                motion: {\n                    front: 0,\n                    back: 0,\n                    left: 0,\n                    right: 0,\n                    up: 0,\n                    down: 0,\n                    standup: 0,\n                    impact: 0,\n                },\n                illuminance: 0,\n                extension: {\n                    analog: 0,\n                    digital: 0, // logic\n                    fall: 0, // falling edge\n                    rise: 0, // rising edge\n                    both: 0, // change edge\n                },\n                switch: {\n                    s1: {\n                        analog: 0,\n                        digital: 0,\n                        fall: 0,\n                        rise: 0,\n                        both: 0,\n                    },\n                    s2: {\n                        analog: 0,\n                        digital: 0,\n                        fall: 0,\n                        rise: 0,\n                        both: 0,\n                    },\n                    s3: {\n                        analog: 0,\n                        digital: 0,\n                        fall: 0,\n                        rise: 0,\n                        both: 0,\n                    },\n                    s4: {\n                        analog: 0,\n                        digital: 0,\n                        fall: 0,\n                        rise: 0,\n                        both: 0,\n                    },\n                },\n                ledRead: {\n                    state: 0,\n                    count: 0,\n                },\n                compass: 0,\n                timeCheck: {\n                    led: 0,\n                    sound: 0,\n                    extCount: 0,\n                },\n            };\n\n            this.setData = {\n                ledColumm: {\n                    pixel: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                    speed: 0,\n                },\n                ledPixel: {\n                    index: 0,\n                    state: 0,\n                },\n                ledIcon: {\n                    index: 0,\n                    speed: 0,\n                },\n                ledText: {\n                    text: '',\n                    speed: 0,\n                },\n                ledClear: 1,\n                extension: 0,\n                melody: {\n                    play: 1,\n                    title: 0,\n                },\n                note: {\n                    play: 1,\n                    pitch: 0,\n                },\n                ledRead: 0,\n            };\n\n            this.lastData = {\n                ledColumm: {\n                    pixel: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                    speed: 0,\n                },\n                ledIcon: {\n                    index: 0,\n                    speed: 0,\n                },\n                ledRead: {\n                    state: 0,\n                    count: 0,\n                },\n                ledText: {\n                    text: '',\n                    speed: 0,\n                },\n                timeCheck: {\n                    led: 0,\n                    sound: 0,\n                    extCount: 0,\n                },\n            };\n\n            this.state = {\n                led: 0,\n                sound: 'm'.charCodeAt(),\n                note: 0,\n                soundBlockId: 0,\n                noteBlockId: 0,\n                extCount: 0,\n            };\n\n            this.extension = {\n                bias: 0,\n                value: 0,\n                angle: 0,\n                absolutAngle: 0,\n                turnCount: 0,\n            };\n\n            this.compass = {\n                lastAnalog: 0,\n                bias: 0,\n                value: 0,\n                angle: 0,\n                absolutAngle: 0,\n                absolutTurnCount: 0,\n                turnCount: 0,\n                direction: 0,\n            };\n\n            this.setZeroFlag = true;\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n                this.state.sound = 0;\n            }\n        }\n        //endregion\n\n        // 하드웨어 연결 후 초기화한다.\n        //region initalHandshake\n        async initialHandshake() {\n            const modePacket = new Uint8Array(2).fill(0);\n            modePacket[0] = 0x63;\n            modePacket[1] = 0x36;\n\n            while (true) {\n                const response = await Entry.hwLite.serial.sendAsyncWithThrottle(modePacket);\n\n                if (response[0] !== NEMOLITE_INDEX) {\n                    modePacket[0] = 0x24;\n                    modePacket[1] = 0x42;\n                } else {\n                    this.version = response.length === 1 ? 0 : response[1];\n                    break;\n                }\n                await Entry.Utils.sleep(100);\n            }\n\n            Entry.addEventListener('run', this.handleButtonEventInterval.bind(this));\n            Entry.addEventListener('run', this.handleMotionlEventInterval.bind(this));\n            Entry.addEventListener('beforeStop', () => {\n                if (this.buttonEventIntervalId) {\n                    clearInterval(this.buttonEventIntervalId);\n                    this.buttonEventIntervalId = null;\n                }\n                if (this.motionEventIntervalId) {\n                    clearInterval(this.motionEventIntervalId);\n                    this.motionEventIntervalId = null;\n                }\n            });\n\n            this.setZero();\n\n            if (this.version === 0) {\n                const packet = await Entry.hwLite.serial.reader.read();\n                this.version = packet.value[0];\n                if (this.version !== RELEASE_VERSION) {\n                    const ko = `펌웨어를 업데이트 하세요.\\n`;\n                    const en = `(Please, Update your firmware.)\\n`;\n                    const version = ` - 현재(now): v.${this.version}\\n - 최신(latest): v.${RELEASE_VERSION}`;\n                    alert(`${ko}${en}${version}`);\n                }\n            }\n\n            return true;\n        }\n        //endregion\n\n        handleButtonEventInterval() {\n            if (this.buttonEventIntervalId) {\n                clearInterval(this.buttonEventIntervalId);\n            }\n            this.buttonEventIntervalId = setInterval(() => {\n                const currentState = this.buttonEvent.bind(this);\n                currentState();\n            }, EVENT_INTERVAL);\n        }\n\n        handleMotionlEventInterval() {\n            if (this.motionEventIntervalId) {\n                clearInterval(this.motionEventIntervalId);\n            }\n            this.motionEventIntervalId = setInterval(() => {\n                const currentState = this.motionEvent.bind(this);\n                currentState();\n            }, EVENT_INTERVAL);\n        }\n\n        // 디바이스에서 값을 읽어온다.\n        //region handleLocalData\n        handleLocalData(buffer) {\n            buffer.forEach((b) => this.qEnqueue(b));\n\n            if (this._recoverTimeoutId) {\n                clearTimeout(this._recoverTimeoutId);\n            }\n\n            while (this.qCount() >= this.receivedPacket.length) {\n                if (!this.process) {\n                    while (this.qCount() > 0) {\n                        if (this.receivedPacket[0] !== 0xcd) {\n                            this.receivedPacket[0] = this.qDequeue();\n                        } else if (this.receivedPacket[1] !== 0xda) {\n                            this.receivedPacket[1] = this.qDequeue();\n                        } else {\n                            this.receivedPacket[2] = this.qDequeue();\n                            this.pLength = this.receivedPacket[2] + 3;\n                            this.process = true;\n                            break;\n                        }\n                    }\n                }\n\n                if (this.process && this.qCount() >= this.pLength) {\n                    for (let i = 3; i < this.pLength; i++) {\n                        this.receivedPacket[i] = this.qDequeue();\n                    }\n\n                    if (\n                        this.receivedPacket[this.pLength - 1] === this.checksum(this.receivedPacket)\n                    ) {\n                        // 상태 확인 코드이므로 가장 먼저 해석\n                        this.parsingTimeCheck(this.receivedPacket);\n\n                        this.pasingAccelA(this.receivedPacket);\n                        this.pasingAccelD(this.receivedPacket);\n                        this.pasingIllumination(this.receivedPacket);\n                        this.parsingExtensionAnalog(this.receivedPacket);\n                        this.parsingExtensionDigital(this.receivedPacket);\n                        this.pasingSwitchAnalog(this.receivedPacket);\n                        this.parsingSwitchDigital(this.receivedPacket);\n                        this.parsingLedRead(this.receivedPacket);\n                        this.parsingCompass(this.receivedPacket);\n                    }\n\n                    this.receivedPacket = new Uint8Array(RECEIVED_PACKET_LENGTH).fill(-1);\n                    this.process = false;\n                    this.sendFlag = true;\n                    this.pLength = 0;\n\n                    if (this.setZeroFlag) {\n                        this.setZeroFlag = false;\n                    }\n                }\n            }\n\n            if (this.sendFlag) {\n                if (this._requestTimeoutId) {\n                    clearTimeout(this._requestTimeoutId);\n                }\n                this._requestTimeoutId = setTimeout(\n                    () => {\n                        if (Entry.hwLite && Entry.hwLite.serial) {\n                            Entry.hwLite.serial.update();\n                            this.sendFlag = false;\n                            this._recoverTimeoutId = setTimeout(() => {\n                                this.sendFlag = true;\n                            }, SERIAL_INTERVAL * 3);\n                        }\n                    },\n                    SERIAL_INTERVAL\n                );\n            }\n        } //endregion\n\n        //디바이스에 값을 쓴다.\n        //region requestLocalData\n        requestLocalData() {\n            if (this.sendFlag) {\n                const led = this.addLedClear();\n                if (!led) {\n                    this.addLedColumm();\n                    this.addLedPixel();\n                    this.addLedSet();\n                    this.addText();\n                }\n                this.addSetExtension();\n                this.addMelody();\n                this.addBuzzer();\n                this.addLedRead();\n\n                const packet = this.PreparePacket();\n                const sendSize = this.sendPacket.length;\n                const textSize = this.textPacket.length;\n\n                for (let i = 0; i < sendSize; i++) {\n                    packet[i] = this.sendPacket[i];\n                }\n                for (let i = 0; i < textSize; i++) {\n                    const index = sendSize + i;\n                    packet[index] = this.textPacket[i];\n                }\n                packet[packet.length - 1] = this.checksum(packet);\n\n                this.sendPacket = new Uint8Array(sendSize).fill(0);\n                this.textPacket = new Uint8Array(0).fill(0);\n\n                return packet;\n            }\n        } //endregion\n\n        qEnqueue(data) {\n            this.qBuffer[this.qRear] = data;\n            this.qRear = (this.qRear + 1) % this.qSize;\n        }\n\n        qDequeue() {\n            const data = this.qBuffer[this.qFront];\n            this.qBuffer[this.qFront] = -1;\n            this.qFront = (this.qFront + 1) % this.qSize;\n            return data;\n        }\n\n        qCount() {\n            return this.qFront <= this.qRear\n                ? this.qRear - this.qFront\n                : this.qSize - this.qFront + this.qRear;\n        }\n\n        checksum(packet) {\n            let checker = 0;\n            const length = packet[2] + 2;\n            for (let i = 3; i < length; i++) {\n                checker += packet[i];\n            }\n            return checker & 0xff;\n        }\n\n        getMonitorPort() {\n            const monitor = {\n                AA1: this.device.switch.s1.analog,\n                AA2: this.device.switch.s2.analog,\n                AA3: this.device.switch.s3.analog,\n                AA4: this.device.switch.s4.analog,\n            };\n\n            return { ...monitor };\n        }\n\n        pasingAccelA(buffer) {\n            for (let i = 0; i < 3; i++) {\n                const lowData = buffer[i * 2 + 3];\n                const highData = buffer[i * 2 + 4];\n                const temp =\n                    (lowData & 0x80) === 0x80\n                        ? (0x10000 - ((lowData << 8) | highData)) * -1\n                        : (lowData << 8) | highData;\n                const key = this.getAccelNameKey(i);\n                this.getData.accel[key] = temp / 10.0;\n            }\n            this.getData.accel.linear = buffer[this.receivedIndex.accelALi];\n        }\n\n        pasingAccelD(buffer) {\n            const data = buffer[this.receivedIndex.accelD];\n            for (let i = 0; i < 8; i++) {\n                const key = this.getMotionNameKey(i);\n                this.getData.motion[key] = (data >> (7 - i)) & 0x01;\n            }\n        }\n\n        pasingIllumination(buffer) {\n            this.getData.illuminance = buffer[this.receivedIndex.illuminance];\n        }\n\n        parsingExtensionAnalog(buffer) {\n            const analog = buffer[this.receivedIndex.extensionAnalog];\n\n            this.getData.extension.analog = analog;\n\n            this.extension.value = analog + this.state.extCount * 255 + this.extension.bias;\n            this.extension.angle = this.getConvertMap(this.extension.value % 255, 0, 255, 0, 360);\n            this.extension.absolutAngle = this.getConvertMap(analog, 0, 255, 0, 360);\n            this.extension.turnCount = Math.round(this.extension.value / 255);\n        }\n\n        parsingExtensionDigital(buffer) {\n            for (let i = 0; i < 4; i++) {\n                const key = this.getButtonStateKey(i);\n                this.getData.extension[key] =\n                    (buffer[this.receivedIndex.extensionDigital] >> (7 - i)) & 0x01;\n            }\n        }\n\n        pasingSwitchAnalog(buffer) {\n            for (let i = 0; i < 4; i++) {\n                const nameKey = this.getButtonNameKey(i);\n                this.getData.switch[nameKey].analog = buffer[this.receivedIndex.switchAnalog1 + i];\n            }\n        }\n\n        parsingSwitchDigital(buffer) {\n            for (let i = 0; i < 4; i++) {\n                const nameKey = this.getButtonNameKey(i);\n                const value = [\n                    (buffer[this.receivedIndex.switchDigitalAB] >> (i + 4)) & 0x01,\n                    (buffer[this.receivedIndex.switchDigitalAB] >> i) & 0x01,\n                    (buffer[this.receivedIndex.switchDigitalCD] >> (i + 4)) & 0x01,\n                    (buffer[this.receivedIndex.switchDigitalCD] >> i) & 0x01,\n                ];\n                for (let j = 0; j < 4; j++) {\n                    const stateKey = this.getButtonStateKey(j);\n                    this.getData.switch[nameKey][stateKey] = value[j];\n                }\n            }\n        }\n\n        parsingLedRead(buffer) {\n            const state = (buffer[this.receivedIndex.ledRead] >> 7) & 0x01;\n            const counter = buffer[this.receivedIndex.ledRead] & 0x7f;\n\n            if (this.lastData.ledRead.count != counter) {\n                this.getData.ledRead.state = state;\n                this.getData.ledRead.count = counter;\n\n                this.lastData.ledRead.state = state;\n                this.lastData.ledRead.count = counter;\n            }\n        }\n\n        parsingCompass(buffer) {\n            const analog = buffer[this.receivedIndex.compass];\n            this.getData.compass = analog;\n            // 회전수를 먼저 구한다.\n            if (analog < this.compass.lastAnalog - 150) {\n                this.compass.absolutTurnCount++;\n            } else if (analog > this.compass.lastAnalog + 150) {\n                this.compass.absolutTurnCount--;\n            }\n            this.compass.value = analog + this.compass.absolutTurnCount * 255 + this.compass.bias;\n            this.compass.angle = this.getConvertMap(this.compass.value % 255, 0, 255, 0, 360);\n            this.compass.absolutAngle = this.getConvertMap(analog, 0, 255, 0, 360);\n            this.compass.turnCount = Math.round(this.compass.value / 255);\n            if (35 <= analog && analog < 99) {\n                this.compass.direction = 0; // 동\n            } else if (99 <= analog && analog < 163) {\n                this.compass.direction = 2; // 남\n            } else if (163 <= analog && analog < 227) {\n                this.compass.direction = 1; // 서\n            } else {\n                // 227-34\n                this.compass.direction = 3; // 북\n            }\n\n            this.compass.lastAnalog = analog;\n        }\n\n        parsingTimeCheck(buffer) {\n            const key = ['led', 'sound', 'extCount'];\n\n            for (let i = 0; i < 3; i++) {\n                this.getData.timeCheck[key[i]] =\n                    (buffer[this.receivedIndex.timeCheck] >> (6 - i * 2)) & 0x03;\n\n                if (this.setZeroFlag) {\n                    this.lastData.timeCheck[key[i]] = this.getData.timeCheck[key[i]];\n                    if (i === 2) {\n                        this.state[key[i]] = 0;\n                    }\n                } else {\n                    if (this.getData.timeCheck[key[i]] !== this.lastData.timeCheck[key[i]]) {\n                        if (i === 2) {\n                            //+방향 일 때: 0->1->2->3->0->...\n                            //-방향 일 때: 0->3->2->1->0->...\n                            const diff =\n                                this.getData.timeCheck[key[i]] - this.lastData.timeCheck[key[i]];\n                            if (diff === 1 || diff === -3) {\n                                this.state[key[i]]++;\n                            } else if (diff === -1 || diff === 3) {\n                                this.state[key[i]]--;\n                            }\n                        } else {\n                            this.state[key[i]] = 0;\n                        }\n                        this.lastData.timeCheck[key[i]] = this.getData.timeCheck[key[i]];\n                    }\n                }\n            }\n        }\n\n        PreparePacket() {\n            const sendSize = this.sendPacket.length;\n            const textSize = this.textPacket.length;\n            const packetSize = sendSize + textSize + 1;\n\n            this.sendPacket[0] = 0xad;\n            this.sendPacket[1] = 0xda;\n            this.sendPacket[2] = packetSize - 3;\n\n            return new Uint8Array(packetSize).fill(0);\n        }\n\n        addLedColumm() {\n            if (this.state.led === 'c'.charCodeAt()) {\n                let nextPage = false;\n                this.state.led = 2;\n\n                for (let i = 0; i < 14; i++) {\n                    const index = this.sendIndex.led7x1 + i;\n                    this.sendPacket[index] = this.setData.ledColumm.pixel[i];\n                    if (index > 7 && this.sendPacket[index] > 0) {\n                        nextPage = true;\n                    }\n                }\n                this.sendPacket[this.sendIndex.ledMs0] = (this.setData.ledColumm.speed >> 8) & 0x7f;\n                this.sendPacket[this.sendIndex.ledMs1] = this.setData.ledColumm.speed & 0xff;\n\n                this.sendPacket[this.sendIndex.led7x1] |= 0x80;\n                if (nextPage) {\n                    this.sendPacket[this.sendIndex.led7x8] |= 0x80;\n                }\n\n                this.lastData.ledColumm.pixel = this.setData.ledColumm.pixel;\n                this.lastData.ledColumm.speed = this.setData.ledColumm.speed;\n            }\n        }\n\n        addLedClear() {\n            if (this.setData.ledClear === 1) {\n                this.setData.ledClear = 0;\n                this.sendPacket[this.sendIndex.led7x1] = 0x80;\n                return true;\n            } else {\n                return false;\n            }\n        }\n\n        addLedPixel() {\n            const state = this.setData.ledPixel.state;\n            if (state) {\n                const index = this.setData.ledPixel.index;\n                this.sendPacket[this.sendIndex.ledPixel] = ((state & 0x03) << 6) | (index & 0x3f);\n                this.setData.ledPixel.index = 0;\n                this.setData.ledPixel.state = 0;\n            }\n        }\n\n        addLedSet() {\n            if (this.state.led === 'i'.charCodeAt()) {\n                this.state.led = 2;\n                this.sendPacket[this.sendIndex.ledMs0] = (this.setData.ledIcon.speed >> 8) & 0xff;\n                this.sendPacket[this.sendIndex.ledMs1] = this.setData.ledIcon.speed & 0xff;\n                this.sendPacket[this.sendIndex.ledSet] = this.setData.ledIcon.index;\n                this.lastData.ledIcon.index = this.setData.ledIcon.index;\n                this.lastData.ledIcon.speed = this.setData.ledIcon.speed;\n            }\n        }\n\n        addSetExtension() {\n            this.sendPacket[this.sendIndex.portSet] = this.setData.extension;\n        }\n\n        addMelody() {\n            if (this.state.sound === 'm'.charCodeAt()) {\n                this.state.sound = 2;\n                this.sendPacket[this.sendIndex.melody] =\n                    (this.setData.melody.play << 7) | (this.setData.melody.title & 0x7f);\n            }\n        }\n\n        addBuzzer() {\n            if (this.state.note === 1) {\n                this.state.note = 2;\n                const pitch = this.setData.note.pitch;\n                if (0 <= pitch && pitch <= 47) {\n                    const n = (pitch / 12) & 0xff;\n                    const v = pitch % 12;\n                    let r = 2;\n                    for (let i = 0; i < n; i++) {\n                        r *= 2;\n                    }\n                    const hertz = this.soundKeyArray[v] / r;\n                    this.sendPacket[this.sendIndex.buzzer0] =\n                        (this.setData.note.play << 7) | ((hertz >> 8) & 0x7f);\n                    this.sendPacket[this.sendIndex.buzzer1] = hertz & 0xff;\n                }\n            }\n        }\n\n        addLedRead() {\n            this.sendPacket[this.sendIndex.ledRead] = this.setData.ledRead;\n            this.setData.ledRead = 0;\n        }\n\n        addText() {\n            if (this.state.led === 't'.charCodeAt()) {\n                this.state.led = 2;\n                const size = this.setData.ledText.text.length;\n                const text = this.setData.ledText.text;\n\n                this.textPacket = new Uint8Array(size);\n\n                for (let i = 0; i < size; i++) {\n                    this.textPacket[i] = text[i].charCodeAt();\n                }\n                this.sendPacket[this.sendIndex.textSize] = size;\n                this.sendPacket[this.sendIndex.ledMs0] = (this.setData.ledText.speed >> 8) & 0x7f;\n                this.sendPacket[this.sendIndex.ledMs1] = this.setData.ledText.speed & 0xff;\n\n                this.lastData.ledText.text = text;\n                this.lastData.ledText.speed = this.setData.ledText.speed;\n                this.setData.ledText.text = '';\n            }\n        }\n\n        getButtonNameKey(data) {\n            const key = ['s1', 's2', 's3', 's4'];\n            const num = Number(data);\n            if (0 <= num && num <= 3) {\n                return key[num];\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_s1:\n                        return key[0];\n                    case Lang.template.nemolite_item_s2:\n                        return key[1];\n                    case Lang.template.nemolite_item_s3:\n                        return key[2];\n                    case Lang.template.nemolite_item_s4:\n                        return key[3];\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getButtonStateKey(data) {\n            const key = ['digital', 'fall', 'rise', 'both'];\n            const num = Number(data);\n            if (0 <= num && num <= 3) {\n                return key[num];\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_is_press:\n                    case Lang.template.nemolite_item_has_press:\n                        return key[0];\n                    case Lang.template.nemolite_item_is_fall:\n                    case Lang.template.nemolite_item_has_fall:\n                        return key[1];\n                    case Lang.template.nemolite_item_is_rise:\n                    case Lang.template.nemolite_item_has_rise:\n                        return key[2];\n                    case Lang.template.nemolite_item_is_both:\n                    case Lang.template.nemolite_item_has_both:\n                        return key[3];\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getMotionNameKey(data) {\n            const key = ['front', 'back', 'left', 'right', 'up', 'down', 'standup', 'impact'];\n            const num = Number(data);\n            if (0 <= num && num <= 7) {\n                return key[num];\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_motion_1:\n                        return key[0];\n                    case Lang.template.nemolite_item_motion_2:\n                        return key[1];\n                    case Lang.template.nemolite_item_motion_3:\n                        return key[2];\n                    case Lang.template.nemolite_item_motion_4:\n                        return key[3];\n                    case Lang.template.nemolite_item_motion_5:\n                        return key[4];\n                    case Lang.template.nemolite_item_motion_6:\n                        return key[5];\n                    case Lang.template.nemolite_item_motion_7:\n                        return key[6];\n                    case Lang.template.nemolite_item_motion_8:\n                        return key[7];\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getAccelNameKey(data) {\n            const key = ['x', 'y', 'z', 'linear'];\n            const num = Number(data);\n            if (0 <= num && num <= 3) {\n                return key[num];\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_axis_x:\n                        return key[0];\n                    case Lang.template.nemolite_item_axis_y:\n                        return key[1];\n                    case Lang.template.nemolite_item_axis_z:\n                        return key[2];\n                    case Lang.template.nemolite_item_linear_acceleration:\n                        return key[3];\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getLedSpeedValue(data) {\n            const num = Number(data);\n            switch (num) {\n                case 0:\n                    return 0;\n                case 1:\n                    return 500;\n                case 2:\n                    return 200;\n                case 3:\n                    return 100;\n                case 4:\n                    return 50;\n                case 5:\n                    return 20;\n                default:\n                    return num < 0 ? 0 : 500;\n            }\n        }\n\n        getLedIconIndexValue(data) {\n            const num = Number(data);\n            if (0 <= num && num <= 32) {\n                return num + 1;\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_smile:\n                        return 1;\n                    case Lang.template.nemolite_item_not_much:\n                        return 2;\n                    case Lang.template.nemolite_item_good:\n                        return 3;\n                    case Lang.template.nemolite_item_bad:\n                        return 4;\n                    case Lang.template.nemolite_item_wink:\n                        return 5;\n                    case Lang.template.nemolite_item_cry:\n                        return 6;\n                    case Lang.template.nemolite_item_absurd:\n                        return 7;\n                    case Lang.template.nemolite_item_peck:\n                        return 8;\n                    case Lang.template.nemolite_item_arrow_1:\n                        return 9;\n                    case Lang.template.nemolite_item_arrow_2:\n                        return 10;\n                    case Lang.template.nemolite_item_arrow_3:\n                        return 11;\n                    case Lang.template.nemolite_item_arrow_4:\n                        return 12;\n                    case Lang.template.nemolite_item_arrow_5:\n                        return 13;\n                    case Lang.template.nemolite_item_arrow_6:\n                        return 14;\n                    case Lang.template.nemolite_item_arrow_7:\n                        return 15;\n                    case Lang.template.nemolite_item_arrow_8:\n                        return 16;\n                    case Lang.template.nemolite_item_spade:\n                        return 17;\n                    case Lang.template.nemolite_item_club:\n                        return 18;\n                    case Lang.template.nemolite_item_diamond:\n                        return 19;\n                    case Lang.template.nemolite_item_heart:\n                        return 20;\n                    case Lang.template.nemolite_item_circle:\n                        return 21;\n                    case Lang.template.nemolite_item_x:\n                        return 22;\n                    case Lang.template.nemolite_item_triangle:\n                        return 23;\n                    case Lang.template.nemolite_item_square:\n                        return 24;\n                    case Lang.template.nemolite_item_note_1:\n                        return 25;\n                    case Lang.template.nemolite_item_note_2:\n                        return 26;\n                    case Lang.template.nemolite_item_note_3:\n                        return 27;\n                    case Lang.template.nemolite_item_dice_1:\n                        return 28;\n                    case Lang.template.nemolite_item_dice_2:\n                        return 29;\n                    case Lang.template.nemolite_item_dice_3:\n                        return 30;\n                    case Lang.template.nemolite_item_dice_4:\n                        return 31;\n                    case Lang.template.nemolite_item_dice_5:\n                        return 32;\n                    case Lang.template.nemolite_item_dice_6:\n                        return 33;\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getLedColummKey(data) {\n            const num = Number(data);\n            if (0 <= num && num <= 13) {\n                return num;\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_first:\n                        return 0;\n                    case Lang.template.nemolite_item_second:\n                        return 1;\n                    case Lang.template.nemolite_item_third:\n                        return 2;\n                    case Lang.template.nemolite_item_fourth:\n                        return 3;\n                    case Lang.template.nemolite_item_fifth:\n                        return 4;\n                    case Lang.template.nemolite_item_sixth:\n                        return 5;\n                    case Lang.template.nemolite_item_seventh:\n                        return 6;\n                    case Lang.template.nemolite_item_eighth:\n                        return 7;\n                    case Lang.template.nemolite_item_ninth:\n                        return 8;\n                    case Lang.template.nemolite_item_tenth:\n                        return 9;\n                    case Lang.template.nemolite_itme_eleventh:\n                        return 10;\n                    case Lang.template.nemolite_item_twelfth:\n                        return 11;\n                    case Lang.template.nemolite_item_thirteenth:\n                        return 12;\n                    case Lang.template.nemolite_itme_fourteenth:\n                        return 13;\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getPitchKey(data) {\n            const num = Number(data);\n            if (0 <= num && num <= 32) {\n                return num + 1;\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_lc:\n                        return 0;\n                    case Lang.template.nemolite_item_lcs:\n                        return 1;\n                    case Lang.template.nemolite_item_ld:\n                        return 2;\n                    case Lang.template.nemolite_item_lds:\n                        return 3;\n                    case Lang.template.nemolite_item_le:\n                        return 4;\n                    case Lang.template.nemolite_item_lf:\n                        return 5;\n                    case Lang.template.nemolite_item_lfs:\n                        return 6;\n                    case Lang.template.nemolite_item_lg:\n                        return 7;\n                    case Lang.template.nemolite_item_lgs:\n                        return 8;\n                    case Lang.template.nemolite_item_la:\n                        return 9;\n                    case Lang.template.nemolite_item_las:\n                        return 10;\n                    case Lang.template.nemolite_item_lb:\n                        return 11;\n                    case Lang.template.nemolite_item_mc:\n                        return 12;\n                    case Lang.template.nemolite_item_mcs:\n                        return 13;\n                    case Lang.template.nemolite_item_md:\n                        return 14;\n                    case Lang.template.nemolite_item_mds:\n                        return 15;\n                    case Lang.template.nemolite_item_me:\n                        return 16;\n                    case Lang.template.nemolite_item_mf:\n                        return 17;\n                    case Lang.template.nemolite_item_mfs:\n                        return 18;\n                    case Lang.template.nemolite_item_mg:\n                        return 19;\n                    case Lang.template.nemolite_item_mgs:\n                        return 20;\n                    case Lang.template.nemolite_item_ma:\n                        return 21;\n                    case Lang.template.nemolite_item_mas:\n                        return 22;\n                    case Lang.template.nemolite_item_mb:\n                        return 23;\n                    case Lang.template.nemolite_item_hc:\n                        return 24;\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getSwitchValue(data) {\n            const num = Number(data);\n            if (0 <= num && num <= 2) {\n                return num + 1;\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_off_text:\n                    case Lang.template.nemolite_item_off_icon:\n                        return 1;\n                    case Lang.template.nemolite_item_on_text:\n                    case Lang.template.nemolite_item_on_icon:\n                        return 2;\n                    case Lang.template.nemolite_item_toggle:\n                        return 3;\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getMelodyKey(data) {\n            const num = Number(data);\n            if (0 <= num && num <= 6) {\n                return num + 1;\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_do_re_mi_song:\n                        return 1;\n                    case Lang.template.nemolite_item_an_island_baby:\n                        return 2;\n                    case Lang.template.nemolite_item_twinkle_twinkle_little_star:\n                        return 2;\n                    case Lang.template.nemolite_item_spring_in_my_hometown:\n                        return 4;\n                    case Lang.template.nemolite_item_for_elise:\n                        return 5;\n                    case Lang.template.nemolite_item_celebrated_chop_waltz:\n                        return 6;\n                    case Lang.template.nemolite_item_happy_birthday_to_you:\n                        return 7;\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getExtensionKey(data) {\n            switch (data) {\n                case '0': // 스위치\n                case '1': // 적외선\n                case '2': // 자석\n                case Lang.template.nemolite_item_switch:\n                case Lang.template.nemolite_item_infrared_ray:\n                case Lang.template.nemolite_item_magnet:\n                    return 1;\n                case '3': // 회전\n                case Lang.template.nemolite_item_rotary:\n                    return 7;\n                case '4': // 조도\n                case Lang.template.nemolite_item_illuminance:\n                    return 2;\n                case '5': // 소리\n                case Lang.template.nemolite_item_sound:\n                    return 8;\n                case '6': // 기울기\n                case Lang.template.nemolite_item_tilt:\n                    return 4;\n                case '7': // 압력\n                case Lang.template.nemolite_item_pressure:\n                    return 5;\n                case '8': // 심박\n                case Lang.template.nemolite_item_heart_rate:\n                    return 6;\n                default:\n                    return data;\n            }\n        }\n\n        getSensorModeKey(data) {\n            const key = ['value', 'angle', 'absolutAngle', 'turnCount'];\n            const num = Number(data);\n            if (0 <= num && num <= 3) {\n                return key[num];\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_value:\n                        return key[0];\n                    case Lang.template.nemolite_item_angle:\n                        return key[1];\n                    case Lang.template.nemolite_item_absolute_angle:\n                        return key[2];\n                    case Lang.template.nemolite_item_rotation_value:\n                        return key[3];\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getDirectionKey(data) {\n            const num = Number(data);\n            if (0 <= num && num <= 3) {\n                return num;\n            } else {\n                switch (data) {\n                    case Lang.template.nemolite_item_east:\n                        return 0;\n                    case Lang.template.nemolite_item_west:\n                        return 1;\n                    case Lang.template.nemolite_item_south:\n                        return 2;\n                    case Lang.template.nemolite_item_north:\n                        return 3;\n                    default:\n                        return data;\n                }\n            }\n        }\n\n        getConvertMap(value, inMin, inMax, outMin, outMax) {\n            return Math.round(((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin);\n        }\n\n        delayCallReturnUsingTime(script, ms, startCode, stopCode) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.timeFlag = 1;\n                const fps = Entry.FPS || 60;\n                const delay = (60 / fps) * ms;\n                Entry.TimeWaitManager.add(\n                    Math.random(),\n                    () => {\n                        script.timeFlag = 0;\n                    },\n                    delay\n                );\n                startCode();\n                return script;\n            } else if (script.timeFlag == 1) {\n                return script;\n            } else {\n                stopCode();\n                delete script.timeFlag;\n                delete script.isStart;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        delayCallReturnUsingFlag(script, startCode, callReturnFlag) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.timeFlag = 1;\n                startCode();\n                return script;\n            } else if (script.timeFlag == 1) {\n                if (callReturnFlag) {\n                    script.timeFlag = 2;\n                }\n                return script;\n            } else {\n                delete script.timeFlag;\n                delete script.isStart;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        getBlocks() {\n            return {\n                //========================================================================================\n                //region Dropdown block\n                //========================================================================================\n                nemolite_dropdown_button: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_s1, 0],\n                                [Lang.template.nemolite_item_s2, 1],\n                                [Lang.template.nemolite_item_s3, 2],\n                                [Lang.template.nemolite_item_s4, 3],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_s1, 0],\n                                            [Lang.template.nemolite_item_s2, 1],\n                                            [Lang.template.nemolite_item_s3, 2],\n                                            [Lang.template.nemolite_item_s4, 3],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_button',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_button_now_state: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_is_press, 0],\n                                [Lang.template.nemolite_item_is_fall, 1],\n                                [Lang.template.nemolite_item_is_rise, 2],\n                                [Lang.template.nemolite_item_is_both, 3],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_is_press, 0],\n                                            [Lang.template.nemolite_item_is_fall, 1],\n                                            [Lang.template.nemolite_item_is_rise, 2],\n                                            [Lang.template.nemolite_item_is_both, 3],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_button_now_state',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_button_state_question: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_has_press, 0],\n                                [Lang.template.nemolite_item_has_fall, 1],\n                                [Lang.template.nemolite_item_has_rise, 2],\n                                [Lang.template.nemolite_item_has_both, 3],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_has_press, 0],\n                                            [Lang.template.nemolite_item_has_fall, 1],\n                                            [Lang.template.nemolite_item_has_rise, 2],\n                                            [Lang.template.nemolite_item_has_both, 3],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_button_state_question',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_motion: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_motion_1, 0],\n                                [Lang.template.nemolite_item_motion_2, 1],\n                                [Lang.template.nemolite_item_motion_3, 2],\n                                [Lang.template.nemolite_item_motion_4, 3],\n                                [Lang.template.nemolite_item_motion_5, 4],\n                                [Lang.template.nemolite_item_motion_6, 5],\n                                [Lang.template.nemolite_item_motion_7, 6],\n                                [Lang.template.nemolite_item_motion_8, 7],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_motion_1, 0],\n                                            [Lang.template.nemolite_item_motion_2, 1],\n                                            [Lang.template.nemolite_item_motion_3, 2],\n                                            [Lang.template.nemolite_item_motion_4, 3],\n                                            [Lang.template.nemolite_item_motion_5, 4],\n                                            [Lang.template.nemolite_item_motion_6, 5],\n                                            [Lang.template.nemolite_item_motion_7, 6],\n                                            [Lang.template.nemolite_item_motion_8, 7],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_motion',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_coordinate_acceleration: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_axis_x, 0],\n                                [Lang.template.nemolite_item_axis_y, 1],\n                                [Lang.template.nemolite_item_axis_z, 2],\n                                [Lang.template.nemolite_item_linear_acceleration, 3],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_axis_x, 0],\n                                            [Lang.template.nemolite_item_axis_y, 1],\n                                            [Lang.template.nemolite_item_axis_z, 2],\n                                            [Lang.template.nemolite_item_linear_acceleration, 3],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_coordinate_acceleration',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_led_icon: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'DropdownExtra',\n                            options: [\n                                [Lang.template.nemolite_item_smile, 0],\n                                [Lang.template.nemolite_item_not_much, 1],\n                                [Lang.template.nemolite_item_good, 2],\n                                [Lang.template.nemolite_item_bad, 3],\n                                [Lang.template.nemolite_item_wink, 4],\n                                [Lang.template.nemolite_item_cry, 5],\n                                [Lang.template.nemolite_item_absurd, 6],\n                                [Lang.template.nemolite_item_peck, 7],\n                                [Lang.template.nemolite_item_arrow_1, 8],\n                                [Lang.template.nemolite_item_arrow_2, 9],\n                                [Lang.template.nemolite_item_arrow_3, 10],\n                                [Lang.template.nemolite_item_arrow_4, 11],\n                                [Lang.template.nemolite_item_arrow_5, 12],\n                                [Lang.template.nemolite_item_arrow_6, 13],\n                                [Lang.template.nemolite_item_arrow_7, 14],\n                                [Lang.template.nemolite_item_arrow_8, 15],\n                                [Lang.template.nemolite_item_spade, 16],\n                                [Lang.template.nemolite_item_club, 17],\n                                [Lang.template.nemolite_item_diamond, 18],\n                                [Lang.template.nemolite_item_heart, 19],\n                                [Lang.template.nemolite_item_circle, 20],\n                                [Lang.template.nemolite_item_x, 21],\n                                [Lang.template.nemolite_item_triangle, 22],\n                                [Lang.template.nemolite_item_square, 23],\n                                [Lang.template.nemolite_item_note_1, 24],\n                                [Lang.template.nemolite_item_note_2, 25],\n                                [Lang.template.nemolite_item_note_3, 26],\n                                [Lang.template.nemolite_item_dice_1, 27],\n                                [Lang.template.nemolite_item_dice_2, 28],\n                                [Lang.template.nemolite_item_dice_3, 29],\n                                [Lang.template.nemolite_item_dice_4, 30],\n                                [Lang.template.nemolite_item_dice_5, 31],\n                                [Lang.template.nemolite_item_dice_6, 32],\n                            ],\n                            value: 0,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_smile, 0],\n                                            [Lang.template.nemolite_item_not_much, 1],\n                                            [Lang.template.nemolite_item_good, 2],\n                                            [Lang.template.nemolite_item_bad, 3],\n                                            [Lang.template.nemolite_item_wink, 4],\n                                            [Lang.template.nemolite_item_cry, 5],\n                                            [Lang.template.nemolite_item_absurd, 6],\n                                            [Lang.template.nemolite_item_peck, 7],\n                                            [Lang.template.nemolite_item_arrow_1, 8],\n                                            [Lang.template.nemolite_item_arrow_2, 9],\n                                            [Lang.template.nemolite_item_arrow_3, 10],\n                                            [Lang.template.nemolite_item_arrow_4, 11],\n                                            [Lang.template.nemolite_item_arrow_5, 12],\n                                            [Lang.template.nemolite_item_arrow_6, 13],\n                                            [Lang.template.nemolite_item_arrow_7, 14],\n                                            [Lang.template.nemolite_item_arrow_8, 15],\n                                            [Lang.template.nemolite_item_spade, 16],\n                                            [Lang.template.nemolite_item_club, 17],\n                                            [Lang.template.nemolite_item_diamond, 18],\n                                            [Lang.template.nemolite_item_heart, 19],\n                                            [Lang.template.nemolite_item_circle, 20],\n                                            [Lang.template.nemolite_item_x, 21],\n                                            [Lang.template.nemolite_item_triangle, 22],\n                                            [Lang.template.nemolite_item_square, 23],\n                                            [Lang.template.nemolite_item_note_1, 24],\n                                            [Lang.template.nemolite_item_note_2, 25],\n                                            [Lang.template.nemolite_item_note_3, 26],\n                                            [Lang.template.nemolite_item_dice_1, 27],\n                                            [Lang.template.nemolite_item_dice_2, 28],\n                                            [Lang.template.nemolite_item_dice_3, 29],\n                                            [Lang.template.nemolite_item_dice_4, 30],\n                                            [Lang.template.nemolite_item_dice_5, 31],\n                                            [Lang.template.nemolite_item_dice_6, 32],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_led_icon',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_switch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_off_text, 0],\n                                [Lang.template.nemolite_item_on_text, 1],\n                                [Lang.template.nemolite_item_toggle, 2],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_off_text, 0],\n                                            [Lang.template.nemolite_item_on_text, 1],\n                                            [Lang.template.nemolite_item_toggle, 2],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_switch',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_melody: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_do_re_mi_song, 0],\n                                [Lang.template.nemolite_item_an_island_baby, 1],\n                                [Lang.template.nemolite_item_twinkle_twinkle_little_star, 2],\n                                [Lang.template.nemolite_item_spring_in_my_hometown, 3],\n                                [Lang.template.nemolite_item_for_elise, 4],\n                                [Lang.template.nemolite_item_celebrated_chop_waltz, 5],\n                                [Lang.template.nemolite_item_happy_birthday_to_you, 6],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_do_re_mi_song, 0],\n                                            [Lang.template.nemolite_item_an_island_baby, 1],\n                                            [\n                                                Lang.template\n                                                    .nemolite_item_twinkle_twinkle_little_star,\n                                                2,\n                                            ],\n                                            [Lang.template.nemolite_item_spring_in_my_hometown, 3],\n                                            [Lang.template.nemolite_item_for_elise, 4],\n                                            [Lang.template.nemolite_item_celebrated_chop_waltz, 5],\n                                            [Lang.template.nemolite_item_happy_birthday_to_you, 6],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_melody',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_keyboard: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'DropdownExtra',\n                            options: [\n                                [Lang.template.nemolite_item_lc, 0],\n                                [Lang.template.nemolite_item_lcs, 1],\n                                [Lang.template.nemolite_item_ld, 2],\n                                [Lang.template.nemolite_item_lds, 3],\n                                [Lang.template.nemolite_item_le, 4],\n                                [Lang.template.nemolite_item_lf, 5],\n                                [Lang.template.nemolite_item_lfs, 6],\n                                [Lang.template.nemolite_item_lg, 7],\n                                [Lang.template.nemolite_item_lgs, 8],\n                                [Lang.template.nemolite_item_la, 9],\n                                [Lang.template.nemolite_item_las, 10],\n                                [Lang.template.nemolite_item_lb, 11],\n                                [Lang.template.nemolite_item_mc, 12],\n                                [Lang.template.nemolite_item_mcs, 13],\n                                [Lang.template.nemolite_item_md, 14],\n                                [Lang.template.nemolite_item_mds, 15],\n                                [Lang.template.nemolite_item_me, 16],\n                                [Lang.template.nemolite_item_mf, 17],\n                                [Lang.template.nemolite_item_mfs, 18],\n                                [Lang.template.nemolite_item_mg, 19],\n                                [Lang.template.nemolite_item_mgs, 20],\n                                [Lang.template.nemolite_item_ma, 21],\n                                [Lang.template.nemolite_item_mas, 22],\n                                [Lang.template.nemolite_item_mb, 23],\n                                [Lang.template.nemolite_item_hc, 24],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_lc, 0],\n                                            [Lang.template.nemolite_item_lcs, 1],\n                                            [Lang.template.nemolite_item_ld, 2],\n                                            [Lang.template.nemolite_item_lds, 3],\n                                            [Lang.template.nemolite_item_le, 4],\n                                            [Lang.template.nemolite_item_lf, 5],\n                                            [Lang.template.nemolite_item_lfs, 6],\n                                            [Lang.template.nemolite_item_lg, 7],\n                                            [Lang.template.nemolite_item_lgs, 8],\n                                            [Lang.template.nemolite_item_la, 9],\n                                            [Lang.template.nemolite_item_las, 10],\n                                            [Lang.template.nemolite_item_lb, 11],\n                                            [Lang.template.nemolite_item_mc, 12],\n                                            [Lang.template.nemolite_item_mcs, 13],\n                                            [Lang.template.nemolite_item_md, 14],\n                                            [Lang.template.nemolite_item_mds, 15],\n                                            [Lang.template.nemolite_item_me, 16],\n                                            [Lang.template.nemolite_item_mf, 17],\n                                            [Lang.template.nemolite_item_mfs, 18],\n                                            [Lang.template.nemolite_item_mg, 19],\n                                            [Lang.template.nemolite_item_mgs, 20],\n                                            [Lang.template.nemolite_item_ma, 21],\n                                            [Lang.template.nemolite_item_mas, 22],\n                                            [Lang.template.nemolite_item_mb, 23],\n                                            [Lang.template.nemolite_item_hc, 24],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_keyboard',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_extension_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_switch, 0],\n                                [Lang.template.nemolite_item_infrared_ray, 1],\n                                [Lang.template.nemolite_item_magnet, 2],\n                                [Lang.template.nemolite_item_rotary, 3],\n                                [Lang.template.nemolite_item_illuminance, 4],\n                                [Lang.template.nemolite_item_sound, 5],\n                                [Lang.template.nemolite_item_tilt, 6],\n                                [Lang.template.nemolite_item_pressure, 7],\n                                [Lang.template.nemolite_item_heart_rate, 8],\n                                [Lang.template.nemolite_item_touch, 9],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_switch, 0],\n                                            [Lang.template.nemolite_item_infrared_ray, 1],\n                                            [Lang.template.nemolite_item_magnet, 2],\n                                            [Lang.template.nemolite_item_rotary, 3],\n                                            [Lang.template.nemolite_item_illuminance, 4],\n                                            [Lang.template.nemolite_item_sound, 5],\n                                            [Lang.template.nemolite_item_tilt, 6],\n                                            [Lang.template.nemolite_item_pressure, 7],\n                                            [Lang.template.nemolite_item_heart_rate, 8],\n                                            [Lang.template.nemolite_item_touch, 9],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_extension_sensor',\n                            },\n                        ],\n                    },\n                },\n\n                nemolite_dropdown_sensor_mode: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_value, 0],\n                                [Lang.template.nemolite_item_angle, 1],\n                                [Lang.template.nemolite_item_absolute_angle, 2],\n                                [Lang.template.nemolite_item_turn_value, 3],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_value, 0],\n                                            [Lang.template.nemolite_item_angle, 1],\n                                            [Lang.template.nemolite_item_absolute_angle, 2],\n                                            [Lang.template.nemolite_item_rotation_value, 3],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_sensor_mode',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_direction: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_east, 0],\n                                [Lang.template.nemolite_item_west, 1],\n                                [Lang.template.nemolite_item_south, 2],\n                                [Lang.template.nemolite_item_north, 3],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_east, 0],\n                                            [Lang.template.nemolite_item_west, 1],\n                                            [Lang.template.nemolite_item_south, 2],\n                                            [Lang.template.nemolite_item_north, 3],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_direction',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_index_0_5: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0', 0],\n                                ['1', 1],\n                                ['2', 2],\n                                ['3', 3],\n                                ['4', 4],\n                                ['5', 5],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0', 0],\n                                            ['1', 1],\n                                            ['2', 2],\n                                            ['3', 3],\n                                            ['4', 4],\n                                            ['5', 5],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_index_0_5',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_index_1_5: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', 1],\n                                ['2', 2],\n                                ['3', 3],\n                                ['4', 4],\n                                ['5', 5],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', 1],\n                                            ['2', 2],\n                                            ['3', 3],\n                                            ['4', 4],\n                                            ['5', 5],\n                                        ],\n                                        value: 1,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_index_1_5',\n                            },\n                        ],\n                    },\n                },\n                nemolite_dropdown_led_columm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.nemolite_item_first, 0],\n                                [Lang.template.nemolite_item_second, 1],\n                                [Lang.template.nemolite_item_third, 2],\n                                [Lang.template.nemolite_item_fourth, 3],\n                                [Lang.template.nemolite_item_fifth, 4],\n                                [Lang.template.nemolite_item_sixth, 5],\n                                [Lang.template.nemolite_item_seventh, 6],\n                                [Lang.template.nemolite_item_eighth, 7],\n                                [Lang.template.nemolite_item_ninth, 8],\n                                [Lang.template.nemolite_item_tenth, 9],\n                                [Lang.template.nemolite_itme_eleventh, 10],\n                                [Lang.template.nemolite_item_twelfth, 11],\n                                [Lang.template.nemolite_item_thirteenth, 12],\n                                [Lang.template.nemolite_itme_fourteenth, 13],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [],\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    events: {},\n                    func: function (sprite, script) {\n                        return script.getField('INDEX');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.nemolite_item_first, 0],\n                                            [Lang.template.nemolite_item_second, 1],\n                                            [Lang.template.nemolite_item_third, 2],\n                                            [Lang.template.nemolite_item_fourth, 3],\n                                            [Lang.template.nemolite_item_fifth, 4],\n                                            [Lang.template.nemolite_item_sixth, 5],\n                                            [Lang.template.nemolite_item_seventh, 6],\n                                            [Lang.template.nemolite_item_eighth, 7],\n                                            [Lang.template.nemolite_item_ninth, 8],\n                                            [Lang.template.nemolite_item_tenth, 9],\n                                            [Lang.template.nemolite_itme_eleventh, 10],\n                                            [Lang.template.nemolite_item_twelfth, 11],\n                                            [Lang.template.nemolite_item_thirteenth, 12],\n                                            [Lang.template.nemolite_itme_fourteenth, 13],\n                                        ],\n                                        value: 0,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'nemolite_dropdown_led_columm',\n                            },\n                        ],\n                    },\n                }, // endregion\n                //========================================================================================\n                //region Input block\n                //========================================================================================\n                nemolite_title_namo_input: {\n                    skeleton: 'basic_text',\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    template: Lang.template.title_namo_input,\n                    skeletonOptions: {\n                        box: {\n                            offsetX: 20,\n                        },\n                    },\n                    def: {\n                        type: 'nemolite_title_namo_input',\n                    },\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                },\n                // %1 %2 버튼 %3\n                nemolite_when_button_state: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    template: Lang.template.nemolite_event_button_state,\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: {\n                                x: 0,\n                                y: -2,\n                            },\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'nemolite_dropdown_button',\n                            },\n                            {\n                                type: 'nemolite_dropdown_button_now_state',\n                            },\n                        ],\n                        type: 'nemolite_when_button_state',\n                    },\n                    paramsKeyMap: {\n                        DUMMY: 0,\n                        INDEX: 1,\n                        STATE: 2,\n                    },\n                    event: 'nemolite_event_button',\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const nameKey = Entry.ProboNemoLite.getButtonNameKey(\n                            script.getStringValue('INDEX')\n                        );\n                        const stateKey = Entry.ProboNemoLite.getButtonStateKey(\n                            script.getStringValue('STATE')\n                        );\n                        const value = Entry.ProboNemoLite.getData.switch[nameKey][stateKey];\n\n                        return value === 1 ? script.callReturn() : this.die();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.when_button_state(%2, %3)',\n                                blockType: 'event',\n                                passTest: true,\n                                textParams: [\n                                    undefined,\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 %2 이 감지되었을 때\n                nemolite_when_motion_sensing: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    template: Lang.template.nemolite_event_motion,\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: {\n                                x: 0,\n                                y: -2,\n                            },\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'nemolite_dropdown_motion',\n                            },\n                        ],\n                        type: 'nemolite_when_motion_sensing',\n                    },\n                    paramsKeyMap: {\n                        DUMMY: 0,\n                        INDEX: 1,\n                    },\n                    event: 'nemolite_event_motion',\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const nameKey = Entry.ProboNemoLite.getMotionNameKey(\n                            script.getStringValue('INDEX')\n                        );\n                        const value = Entry.ProboNemoLite.getData.motion[nameKey];\n\n                        return value === 1 ? script.callReturn() : this.die();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.when_motion_sensing(%2)',\n                                blockType: 'event',\n                                passTest: true,\n                                textParams: [\n                                    undefined,\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 버튼 %2 ?\n                nemolite_is_button_state: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    template: Lang.template.nemolite_is_button_state,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_button',\n                            },\n                            {\n                                type: 'nemolite_dropdown_button_state_question',\n                            },\n                        ],\n                        type: 'nemolite_is_button_state',\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                        STATE: 1,\n                    },\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const nameKey = Entry.ProboNemoLite.getButtonNameKey(\n                            script.getStringValue('INDEX')\n                        );\n                        const stateKey = Entry.ProboNemoLite.getButtonStateKey(\n                            script.getStringValue('STATE')\n                        );\n                        const value = Entry.ProboNemoLite.getData.switch[nameKey][stateKey];\n\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.is_button_state(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 이 감지되었는가?\n                nemolite_is_motion_sensing: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    template: Lang.template.nemolite_is_motion_sensing,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_motion',\n                            },\n                        ],\n                        type: 'nemolite_is_motion_sensing',\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const nameKey = Entry.ProboNemoLite.getMotionNameKey(\n                            script.getStringValue('INDEX')\n                        );\n                        const value = Entry.ProboNemoLite.getData.motion[nameKey];\n\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.is_motion_sensing(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // LED X: %1 Y: %2 상태값\n                nemolite_is_led_state_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    template: Lang.template.nemolite_is_led_state_value,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                        ],\n                        type: 'nemolite_is_led_state_value',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                    },\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const x = script.getNumberValue('X');\n                        const y = script.getNumberValue('Y');\n                        const index = x * 7 + y + 1; // 1 ~ 49\n                        let value = false;\n                        Entry.ProboNemoLite.setData.ledRead = index;\n\n                        return Entry.ProboNemoLite.getData.ledRead.state;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.is_led_state_value(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 버튼의 아날로그 값\n                nemolite_get_button_analog_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: Lang.template.nemolite_get_button_analog_value,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_button',\n                            },\n                        ],\n                        type: 'nemolite_get_button_analog_value',\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const nameKey = Entry.ProboNemoLite.getButtonNameKey(\n                            script.getStringValue('INDEX')\n                        );\n                        const value = Entry.ProboNemoLite.getData.switch[nameKey]['analog'];\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.button_analog_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 가속도 센서 %1 의 값\n                nemolite_get_acceleration_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: Lang.template.nemolite_get_acceleration_value,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_coordinate_acceleration',\n                            },\n                        ],\n                        type: 'nemolite_get_acceleration_value',\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                    },\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const nameKey = Entry.ProboNemoLite.getAccelNameKey(\n                            script.getStringValue('INDEX')\n                        );\n                        const value = Entry.ProboNemoLite.getData.accel[nameKey];\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.acceleration_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 조도 센서의 값\n                nemolite_get_illuminance_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: Lang.template.nemolite_get_illuminance_value,\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'nemolite_get_illuminance_value',\n                    },\n                    paramsKeyMap: {},\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const illuminance = Entry.ProboNemoLite.getData.illuminance;\n                        return illuminance;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.illuminance_value()',\n                                blockType: 'param',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                // %1 의 값 %2 ~ %3 을 %4 ~ %5 으(로) 변환\n                nemolite_get_convert_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: Lang.template.nemolite_get_convert_value,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                        ],\n                        type: 'nemolite_get_convert_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                        IN_MIN: 1,\n                        IN_MAX: 2,\n                        OUT_MIN: 3,\n                        OUT_MAX: 4,\n                    },\n                    class: 'nemolite_input',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const value = script.getNumberValue('VALUE');\n                        const inMin = script.getNumberValue('IN_MIN');\n                        const inMax = script.getNumberValue('IN_MAX');\n                        const outMin = script.getNumberValue('OUT_MIN');\n                        const outMax = script.getNumberValue('OUT_MAX');\n                        return Entry.ProboNemoLite.getConvertMap(\n                            value,\n                            inMin,\n                            inMax,\n                            outMin,\n                            outMax\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.convert_value(%1, %2, %3, %4, %5)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                }, //endregion\n                //========================================================================================\n                //region Output block\n                //========================================================================================\n                nemolite_title_namo_output: {\n                    skeleton: 'basic_text',\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    template: Lang.template.title_namo_output,\n                    skeletonOptions: {\n                        box: {\n                            offsetX: 20,\n                        },\n                    },\n                    def: {\n                        type: 'nemolite_title_namo_output',\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                },\n                // LED 아이콘 %1 을 %2 속도로 출력 %3\n                nemolite_set_display_led_icon: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_display_led_icon,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_led_icon',\n                            },\n                            {\n                                type: 'nemolite_dropdown_index_0_5',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_set_display_led_icon',\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                        SPEED: 1,\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const index = Entry.ProboNemoLite.getLedIconIndexValue(\n                            script.getStringValue('INDEX')\n                        );\n                        const speed = Entry.ProboNemoLite.getLedSpeedValue(\n                            script.getStringValue('SPEED')\n                        );\n\n                        if (\n                            Entry.ProboNemoLite.state.led === 0 ||\n                            Entry.ProboNemoLite.lastData.ledIcon.index !== index ||\n                            Entry.ProboNemoLite.lastData.ledIcon.speed !== speed\n                        ) {\n                            Entry.ProboNemoLite.setData.ledIcon.index = index;\n                            Entry.ProboNemoLite.setData.ledIcon.speed = speed;\n\n                            Entry.ProboNemoLite.state.led = 'i'.charCodeAt();\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.display_led_icon(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // LED %1 줄의 %2%3%4%5%6%7%8 을 %9 속도로 출력 %10\n                nemolite_set_display_led_custom_columm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_display_led_custom_columm,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_led_columm',\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'nemolite_dropdown_index_0_5',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_set_display_led_custom_columm',\n                    },\n                    paramsKeyMap: {\n                        INDEX: 0,\n                        VALUE1: 1,\n                        VALUE2: 2,\n                        VALUE3: 3,\n                        VALUE4: 4,\n                        VALUE5: 5,\n                        VALUE6: 6,\n                        VALUE7: 7,\n                        SPEED: 8,\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const index = Entry.ProboNemoLite.getLedColummKey(\n                            script.getStringValue('INDEX')\n                        );\n                        const value = [\n                            script.getNumberValue('VALUE1'),\n                            script.getNumberValue('VALUE2'),\n                            script.getNumberValue('VALUE3'),\n                            script.getNumberValue('VALUE4'),\n                            script.getNumberValue('VALUE5'),\n                            script.getNumberValue('VALUE6'),\n                            script.getNumberValue('VALUE7'),\n                        ];\n                        const speed = Entry.ProboNemoLite.getLedSpeedValue(\n                            script.getStringValue('SPEED')\n                        );\n                        let pixel = 0;\n                        for (let i = 0; i < 7; i++) {\n                            if (value[i] > 0) {\n                                pixel |= 1 << i;\n                            } else {\n                                pixel &= ~(1 << i);\n                            }\n                        }\n\n                        if (\n                            Entry.ProboNemoLite.state.led === 0 ||\n                            Entry.ProboNemoLite.lastData.ledColumm.pixel[index] !== pixel ||\n                            Entry.ProboNemoLite.lastData.ledColumm.speed !== speed\n                        ) {\n                            Entry.ProboNemoLite.state.led = 'c'.charCodeAt();\n                            Entry.ProboNemoLite.setData.ledColumm.pixel[index] = pixel;\n                            Entry.ProboNemoLite.setData.ledColumm.speed = speed;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.display_led_custom_columm(%1, %2, %3, %4, %5, %6, %7, %8, %9)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // LED %1 문자열을 %2 속도로 출력 %3\n                nemolite_set_display_led_text: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_display_led_text,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['Hello'],\n                            },\n                            {\n                                type: 'nemolite_dropdown_index_1_5',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_set_display_led_text',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        SPEED: 1,\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const text = script.getStringValue('TEXT');\n                        const speed = Entry.ProboNemoLite.getLedSpeedValue(\n                            script.getStringValue('SPEED')\n                        );\n\n                        if (\n                            Entry.ProboNemoLite.state.led === 0 ||\n                            Entry.ProboNemoLite.lastData.ledText.text !== text ||\n                            Entry.ProboNemoLite.lastData.ledText.speed !== speed\n                        ) {\n                            Entry.ProboNemoLite.state.led = 't'.charCodeAt();\n                            Entry.ProboNemoLite.setData.ledText.text = text;\n                            Entry.ProboNemoLite.setData.ledText.speed = speed;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.display_led_text(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n\n                nemolite_set_delete_all_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_delete_all_led,\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'nemolite_set_delete_all_led',\n                    },\n                    paramsKeyMap: {},\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        Entry.ProboNemoLite.setData.ledClear = 1;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.delete_all_led()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                // LED X: %1 Y: %2 %3 %4\n                nemolite_set_toggle_led_pixel: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_toggle_led_pixel,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            {\n                                type: 'nemolite_dropdown_switch',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_set_toggle_led_pixel',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        STATE: 2,\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const x = script.getNumberValue('X');\n                        const y = script.getNumberValue('Y');\n\n                        if (0 <= x && x <= 6 && 0 <= y && y <= 6) {\n                            const index = x * 7 + y + 1; // 1 ~ 49\n                            const state = Entry.ProboNemoLite.getSwitchValue(\n                                script.getNumberValue('STATE')\n                            );\n\n                            Entry.ProboNemoLite.setData.ledPixel.state = state;\n                            Entry.ProboNemoLite.setData.ledPixel.index = index;\n                        }\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.toggle_led_pixel(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 멜로디 %1 재생하기 %2\n                nemolite_set_play_melody: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_play_melody,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_melody',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_set_play_melody',\n                    },\n                    paramsKeyMap: {\n                        TITLE: 0,\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const title = Entry.ProboNemoLite.getMelodyKey(\n                            script.getNumberValue('TITLE')\n                        );\n\n                        if (Entry.ProboNemoLite.state.sound === 0) {\n                            Entry.ProboNemoLite.state.sound = 'm'.charCodeAt();\n                            Entry.ProboNemoLite.setData.melody.play = 1;\n                            Entry.ProboNemoLite.setData.melody.title = title;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.play_melody(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // '멜로디 %1 끝까지 재생하기 %2'\n                nemolite_set_play_melody_until_the_end: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_play_melody_until_the_end,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_melody',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_set_play_melody_until_the_end',\n                    },\n                    paramsKeyMap: {\n                        TITLE: 0,\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const title = Entry.ProboNemoLite.getMelodyKey(\n                            script.getNumberValue('TITLE')\n                        );\n                        let flag = false;\n                        const startCode = function () {\n                            if (Entry.ProboNemoLite.state.sound === 0) {\n                                Entry.ProboNemoLite.state.soundBlockId = script.executor.id;\n                                Entry.ProboNemoLite.state.sound = 'm'.charCodeAt();\n                                Entry.ProboNemoLite.setData.melody.play = 1;\n                                Entry.ProboNemoLite.setData.melody.title = title;\n                            }\n                        };\n\n                        if (\n                            Entry.ProboNemoLite.state.soundBlockId === script.executor.id &&\n                            Entry.ProboNemoLite.state.sound === 0\n                        ) {\n                            flag = true;\n                        }\n\n                        return Entry.ProboNemoLite.delayCallReturnUsingFlag(\n                            script,\n                            startCode,\n                            flag\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.play_melody_until_the_end(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 음을 %2 재생하기 %3\n                nemolite_set_play_note: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_play_note,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_keyboard',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_set_play_note',\n                    },\n                    paramsKeyMap: {\n                        PITCH: 0,\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const pitch = Entry.ProboNemoLite.getPitchKey(\n                            script.getNumberValue('PITCH')\n                        );\n\n                        Entry.ProboNemoLite.state.note = 1;\n                        Entry.ProboNemoLite.setData.note.play = 1;\n                        Entry.ProboNemoLite.setData.note.pitch = pitch;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.nemolite_set_play_note(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 음을 %2 초동안 재생하기 %3\n                nemolite_set_play_note_for_seconds: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_play_note_for_seconds,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_keyboard',\n                            },\n                            {\n                                type: 'number',\n                                params: ['1'],\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_set_play_note_for_seconds',\n                    },\n                    paramsKeyMap: {\n                        PITCH: 0,\n                        TIME: 1,\n                    },\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const pitch = Entry.ProboNemoLite.getPitchKey(\n                            script.getNumberValue('PITCH')\n                        );\n                        const time = script.getNumberValue('TIME') * 1000;\n                        const startCode = function () {\n                            if (Entry.ProboNemoLite.state.note === 0) {\n                                Entry.ProboNemoLite.state.noteBlockId = script.executor.id;\n                                Entry.ProboNemoLite.state.note = 1;\n                                Entry.ProboNemoLite.setData.note.play = 1;\n                                Entry.ProboNemoLite.setData.note.pitch = pitch;\n                            }\n                        };\n                        const stopCode = function () {\n                            if (Entry.ProboNemoLite.state.noteBlockId === script.executor.id) {\n                                Entry.ProboNemoLite.state.note = 0;\n                            }\n                        };\n\n                        return Entry.ProboNemoLite.delayCallReturnUsingTime(\n                            script,\n                            time,\n                            startCode,\n                            stopCode\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.play_note_for_seconds(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 모든 소리 정지 %1\n                nemolite_set_stop_all_sound: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_set_stop_all_sound,\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'nemolite_set_stop_all_sound',\n                    },\n                    paramsKeyMap: {},\n                    class: 'nemolite_output',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        Entry.ProboNemoLite.state.sound = 'm'.charCodeAt();\n                        Entry.ProboNemoLite.setData.melody.play = 1;\n                        Entry.ProboNemoLite.setData.melody.title = 0;\n                        Entry.ProboNemoLite.state.note = 1;\n                        Entry.ProboNemoLite.setData.note.play = 0;\n                        Entry.ProboNemoLite.setData.note.pitch = 0;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.stop_all_sound()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                //endregion Output block\n                //========================================================================================\n                //region Extension block\n                //========================================================================================\n                nemolite_title_namo_extension: {\n                    skeleton: 'basic_text',\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    template: Lang.template.nemolite_namo_extension,\n                    skeletonOptions: {\n                        box: {\n                            offsetX: 20,\n                        },\n                    },\n                    def: {\n                        type: 'nemolite_title_namo_extension',\n                    },\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                },\n                nemolite_ext_set_extension: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_ext_set_extension,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_extension_sensor',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_ext_set_extension',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const type = Entry.ProboNemoLite.getExtensionKey(\n                            script.getStringValue('TYPE')\n                        );\n                        Entry.ProboNemoLite.setData.extension = type;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.set_extension(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                nemolite_ext_get_extension_anlog_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: Lang.template.nemolite_ext_get_extension_anlog_value,\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'nemolite_ext_get_extension_anlog_value',\n                    },\n                    paramsKeyMap: {},\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const value = Entry.ProboNemoLite.getData.extension.analog;\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.get_extension_anlog_value(%1)',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                nemolite_ext_set_extension_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_ext_set_extension_value,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_ext_set_extension_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const value = script.getNumberValue('VALUE');\n                        const analog = Entry.ProboNemoLite.getData.extension.analog;\n                        const count = Entry.ProboNemoLite.state.extCount;\n                        Entry.ProboNemoLite.extension.bias = value - (analog + count * 255);\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.set_extension_value(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                nemolite_ext_is_extension_state: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    template: Lang.template.nemolite_ext_is_extension_state,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_button_state_question',\n                            },\n                            null,\n                        ],\n                        type: 'nemolite_ext_is_extension_state',\n                    },\n                    paramsKeyMap: {\n                        STATE: 0,\n                    },\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const stateKey = Entry.ProboNemoLite.getButtonStateKey(\n                            script.getStringValue('STATE')\n                        );\n                        const value = Entry.ProboNemoLite.getData.extension[stateKey];\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.is_extension_state(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                nemolite_ext_get_extension_custom_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: Lang.template.nemolite_ext_get_extension_custom_value,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_sensor_mode',\n                            },\n                        ],\n                        type: 'nemolite_ext_get_extension_custom_value',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const modeKey = Entry.ProboNemoLite.getSensorModeKey(\n                            script.getStringValue('TYPE')\n                        );\n                        const value = Entry.ProboNemoLite.extension[modeKey];\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.get_extension_custom_value(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                nemolite_ext_set_compass_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    template: Lang.template.nemolite_ext_set_compass_value,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                        ],\n                        type: 'nemolite_ext_set_compass_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const value = script.getNumberValue('VALUE');\n                        const analog = Entry.ProboNemoLite.getData.compass;\n                        const count = Entry.ProboNemoLite.compass.absolutTurnCount;\n                        Entry.ProboNemoLite.compass.bias = value - (analog + count * 255);\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.set_compass_value(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                nemolite_ext_get_compass_analog_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: Lang.template.nemolite_ext_get_compass_analog_value,\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'nemolite_ext_get_compass_analog_value',\n                    },\n                    paramsKeyMap: {},\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const value = Entry.ProboNemoLite.getData.compass;\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.compass_analog_value(%1)',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                nemolite_ext_get_compass_custom_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: Lang.template.nemolite_ext_get_compass_custom_value,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_sensor_mode',\n                            },\n                        ],\n                        type: 'nemolite_ext_get_compass_custom_value',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const modeKey = Entry.ProboNemoLite.getSensorModeKey(\n                            script.getStringValue('TYPE')\n                        );\n                        const value = Entry.ProboNemoLite.compass[modeKey];\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.compass_custom_value(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                memolite_ext_is_compass_direction: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    template: Lang.template.memolite_ext_is_compass_direction,\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'nemolite_dropdown_direction',\n                            },\n                        ],\n                        type: 'memolite_ext_is_compass_direction',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'nemolite_extension',\n                    isNotFor: ['ProboNemoLite'],\n                    func: function (sprite, script) {\n                        const key = Entry.ProboNemoLite.getDirectionKey(\n                            script.getStringValue('DIRECTION')\n                        );\n                        const value = Entry.ProboNemoLite.compass.direction;\n                        return value === key;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NemoLite.is_compass_direction(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                //endregion\n            }; // getBlock() return;\n        }\n    })();\n})();\n\nmodule.exports = Entry.ProboNemoLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_alux_teachnic_normal_lite.js",
    "content": "'use strict';\n\nconst _throttle = require('lodash/throttle');\n\n(function() {\n    const TECHNIC_NORMAL_INDEX = 0x12; //18\n    const RELEASE_VERSION = 4;\n    const SERIAL_INTERVAL = 32;\n    const EVENT_INTERVAL = 16;\n    const SEND_PACKET_LENGTH = 22;\n    const RECEIVED_PACKET_LENGTH = 17;\n    Entry.ProboTechnicNormalLite = new (class ProboTechnicNormalLite  {\n        constructor()  {\n            this.id = '630301';\n            this.name = 'ProboTechnicNormalLite';\n            this.url = 'https://imssam.me';\n            this.imageName = 'alux_technic_normal_lite.png';\n            this.title = {\n                ko: '프로보 테크닉(일반)',\n                en: 'Probo Technic(Normal)',\n            };\n            this.portData = {\n                baudRate: 115200,\n                duration: this.SERIAL_INTERVAL,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 128,\n                connectionType: 'bytestream',\n                constantServing: 'ReadOnly',\n            };\n\n            this.Color = {\n                Red: {\n                    Min: 13,\n                    Max: 37\n                },\n                Green: {\n                    Min: 38,\n                    Max: 62\n                },\n                Blue: {\n                    Min: 63,\n                    Max: 87\n                },\n                Yellow: {\n                    Min: 88,\n                    Max: 112\n                },\n                Black: {\n                    Min: 113,\n                    Max: 137\n                },\n                White: {\n                    Min: 138,\n                    Max: 162\n                },\n            };\n            this.MultiSwitch = {\n                Key1: {\n                    Min: 1,\n                    Max: 19\n                },\n                Key2: {\n                    Min: 26,\n                    Max: 44\n                },\n                Key3: {\n                    Min: 53,\n                    Max: 77\n                },\n                Key4: {\n                    Min: 83,\n                    Max: 101\n                },\n                Key5: {\n                    Min: 107,\n                    Max: 125\n                },\n                Key6: {\n                    Min: 139,\n                    Max: 157\n                },\n                Key7: {\n                    Min: 160,\n                    Max: 178\n                },\n                Key8: {\n                    Min: 191,\n                    Max: 209\n                }\n            };\n            this.Note = {\n                n32:  48,   // = 1*3*4*4,\n                n16:  96,   // = 2*3*4*4,\n                n16d: 144,  // = 3*3*4*4,\n                n16t: 64,   // = 2*2*4*4,\n                n8:   192,  // = 4*3*4*4,\n                n8d:  288,  // = 6*3*4*4,\n                n8t:  128,  // = 4*2*4*4,\n                n4:   384,  // = 8*3*4*4,\n                n4d:  576,  // = 12*3*4*4,\n                n4t:  256,  // = 8*2*4*4,\n                n2:   768,  // = 16*3*4*4,\n                n2d:  1152, // = 24*3*4*4,\n                n2t:  512,  // = 16*2*4*4,\n                n1:   1536, // = 32*3*4*4\n            };\n            this.Rgb = {\n                Off: 0,\n                On: {\n                    Red :    1,\n                    Yellow:  12,\n                    Green :  23,\n                    Cyan :   34,\n                    Blue:    45,\n                    Magenta: 56,\n                    White:   67\n                },\n                Dimming: {\n                    Red:     90,\n                    Yellow:  91,\n                    Green:   92,\n                    Cyan:    93,\n                    Blue:    94,\n                    Magenta: 95,\n                    White:   96\n                }\n            };\n            this.Melody = [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748];\n            this.Track = [\n                [0x451F, 0x3D95, 0x36DD, 0x33C8, 0x2E22, 0x291A, 0x249E], // Start : size 7,\n                [0x228F, 0x249E, 0x291A, 0x2E22, 0x33C8, 0x36DD, 0x3D95, 0x451F], // End : size 8,\n                [0x228F, 0x1B6E, 0x1711, 0x1147 ], // LevelUp : size 4,\n                [0x1147, 0x1711, 0x1B6E, 0x228F ], // LevelDwon : size 4,\n            ];\n\n            const eventSetting = {\n                leading: true,\n                trailing: false\n            }\n            this.remoteEvent = _throttle(\n                () => {\n                    const prevFlag = this.sendFlag;\n                    try {\n                        Entry.engine.fireEvent('technicnormallite_event_remote_input');\n                    } catch (e) {\n                    } finally {\n                        this.sendFlag = prevFlag;\n                    }\n                },\n                EVENT_INTERVAL,\n                eventSetting\n            );\n            this.digitalEvent = _throttle(\n                () => {                    \n                    const prevFlag = this.sendFlag;\n                    try {\n                        Entry.engine.fireEvent('technicnormallite_event_digital_input');\n                    } catch (e) {\n                    } finally {\n                        this.sendFlag = prevFlag;\n                    }\n                }\n                ,\n                EVENT_INTERVAL,\n                eventSetting\n            );\n\n            this.qRear = 0;\n            this.qFront = 0;\n            this.qSize = 128;\n            this.qBuffer = new Uint8Array(this.qSize + 2).fill(-1);            \n            this.inputPacket = new Uint8Array(RECEIVED_PACKET_LENGTH).fill(-1);\n            this.pLength = 0; // packet length\n            this.process = false; // packet process\n\n            this.version = 0;\n            this.sendFlag = true;            \n\n            this.blockMenuBlocks = [\n                //dropdown\n                'technicnormallite_dropdown_remote_key',\n                'technicnormallite_dropdown_digital_key',\n                'technicnormallite_dropdown_analog_key',\n                'technicnormallite_dropdown_setting_sensor_key',\n                'technicnormallite_dropdown_inNcom_sensor_key',\n                'technicnormallite_dropdown_sensor_color_key',\n                'technicnormallite_dropdown_rgb_color_key',\n                'technicnormallite_dropdown_sensor_angle_key',\n                'technicnormallite_dropdown_multikey_key',\n                'technicnormallite_dropdown_extension_digital_key',\n                'technicnormallite_dropdown_extension_analog_key',\n                'technicnormallite_dropdown_dc_1_all_key',\n                'technicnormallite_dropdown_port_1_4_key',\n                'technicnormallite_dropdown_on_off_key',\n                'technicnormallite_dropdown_velocity_key',\n                'technicnormallite_dropdown_servo_position_key',\n                'technicnormallite_dropdown_note_key',\n                'technicnormallite_dropdown_time_1_key',\n                'technicnormallite_dropdown_time_2_key',\n                'technicnormallite_dropdown_time_3',\n                'technicnormallite_dropdown_pitch_key',\n                'technicnormallite_dropdown_melody_key',\n\n                //event\n                'technicnormallite_when_press_remote_key',\n                'technicnormallite_when_input_digital_value',\n\n                //setting\n                'technicnormallite_set_senser_setting',\n\n                //input\n                'technicnormallite_is_remote_key',\n                'technicnormallite_is_digital_value',\n                'technicnormallite_is_extension_digital_input',\n                'technicnormallite_get_analog_value',\n                'technicnormallite_get_extension_analog_input',\n                // 'technicnormallite_get_tri_axis_acceler_x', // 테크닉 에서 사용하지 않음\n                // 'technicnormallite_get_tri_axis_acceler_y', // 테크닉 에서 사용하지 않음\n                // 'technicnormallite_get_tri_axis_acceler_z', // 테크닉 에서 사용하지 않음\n                'technicnormallite_get_value_mapping',\n                'technicnormallite_is_color_value',\n                'technicnormallite_get_color_value',\n                'technicnormallite_set_infinite_setting',\n                'technicnormallite_get_infinite_mm_diameter',\n                'technicnormallite_get_infinite_transform_input',\n                // 'technicnormallite_is_multi_sensor', // 테크닉 에서 사용하지 않음\n                // 'technicnormallite_is_multi_switch', // 테크닉 에서 사용하지 않음\n                'technicnormallite_set_eeprom_call',\n                'technicnormallite_get_eeprom_address_value',\n\n                //output\n                'technicnormallite_set_dc_output',\n                'technicnormallite_set_servo_output',\n                // 'technicnormallite_set_s_dc_output', // 테크닉 에서 사용하지 않음\n                'technicnormallite_set_port_output',\n                'technicnormallite_play_melody_note_output',\n                'technicnormallite_play_melody_sec_output',\n                'technicnormallite_play_melody_output',\n                'technicnormallite_play_value_sec_output',\n                'technicnormallite_play_value_output',    \n                'technicnormallite_play_melody_track_output',\n                'technicnormallite_play_melody_off',\n                'technicnormallite_set_rgbled_on_output',\n                'technicnormallite_set_rgbled_off_output',\n                'technicnormallite_set_rgbled_flashing_output',\n                'technicnormallite_set_rgbled_dimming_output',\n                // 'technicnormallite_set_fnd_output', // 테크닉 에서 사용하지 않음\n                // 'technicnormallite_set_fnd_off',    // 테크닉 에서 사용하지 않음\n\n                //EEPROM\n                'technicnormallite_set_eeprom_write',\n            ];\n        }        \n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        technicnormallite_item_switch: '스위치',\n                        technicnormallite_item_infrared: '적외선',\n                        technicnormallite_item_magnetic: '자석',\n                        technicnormallite_item_rotation: '회전',\n                        technicnormallite_item_color: '컬러',\n                        technicnormallite_item_acceleration: '가속도',\n                        technicnormallite_item_ultrasonic: '초음파',\n                        technicnormallite_item_heart_rate: '심박',\n                        technicnormallite_item_illuminance: '조도',\n                        technicnormallite_item_temperature: '온도',\n                        technicnormallite_item_sound: '소리',\n                        technicnormallite_item_tilt: '기울기',\n                        technicnormallite_item_pressure: '압력',\n                        technicnormallite_item_multi_touch: '멀티키',\n                        technicnormallite_item_compass: '나침반',\n                        technicnormallite_item_tri_acceleration: '3가속',\n                        technicnormallite_item_multi_switch: '분배기',\n                        technicnormallite_item_infinite_rotation: '무한회전',\n                        technicnormallite_item_extension_input: '확장입력',\n                        technicnormallite_item_color_red: '빨간색',\n                        technicnormallite_item_color_green: '초록색',\n                        technicnormallite_item_color_blue: '파란색',\n                        technicnormallite_item_color_cyan: '청녹색',\n                        technicnormallite_item_color_magenta: '자홍색',\n                        technicnormallite_item_color_yellow: '노란색',\n                        technicnormallite_item_color_black: '검정색',\n                        technicnormallite_item_color_white: '하얀색',\n                        technicnormallite_item_value: '값',\n                        technicnormallite_item_angle: '각도',\n                        technicnormallite_item_absolute_angle: '절대각도',\n                        technicnormallite_item_number_of_rotations: '회전 수',\n                        technicnormallite_item_key_1: '키1',\n                        technicnormallite_item_key_2: '키2',\n                        technicnormallite_item_key_3: '키3',\n                        technicnormallite_item_key_4: '키4',\n                        technicnormallite_item_key_5: '키5',\n                        technicnormallite_item_key_6: '키6',\n                        technicnormallite_item_key_7: '키7',\n                        technicnormallite_item_key_8: '키8',\n                        technicnormallite_item_all: '모두',\n                        technicnormallite_item_on: '켜기',\n                        technicnormallite_item_off: '끄기',\n                        technicnormallite_item_note_whole: '온',\n                        technicnormallite_item_note_half: '2분',\n                        technicnormallite_item_note_quarter: '4분',\n                        technicnormallite_item_note_eighth: '8분',\n                        technicnormallite_item_note_sixteenth: '16분',\n                        technicnormallite_item_note_thirty_second: '32분',\n                        technicnormallite_item_pitch_do: '도',\n                        technicnormallite_item_pitch_do_sharp: '도#',\n                        technicnormallite_item_pitch_re: '레',\n                        technicnormallite_item_pitch_re_sharp: '레#',\n                        technicnormallite_item_pitch_mi: '미',\n                        technicnormallite_item_pitch_fa: '파',\n                        technicnormallite_item_pitch_fa_sharp: '파#',\n                        technicnormallite_item_pitch_sol: '솔',\n                        technicnormallite_item_pitch_sol_sharp: '솔#',\n                        technicnormallite_item_pitch_ra: '라',\n                        technicnormallite_item_pitch_ra_sharp: '라#',\n                        technicnormallite_item_pitch_si: '시',\n                        technicnormallite_item_melody_start: '시작음',\n                        technicnormallite_item_melody_end: '종료음',\n                        technicnormallite_item_melody_level_up: '레벨 업',\n                        technicnormallite_item_melody_level_down: '레벨 다운',\n\n                        technicnormallite_item_error: '오류',\n                        technicnormallite_item_nothing: '없음',\n        \n                        technicnormallite_when_press_remote_key: '%1 리모컨 %2 키를 눌렀을 때',\n                        technicnormallite_when_input_digital_value: '%1 디지털 입력 %2 이(가) 들어왔을 때',\n        \n                        technicnormallite_set_senser_setting: '입력포트 %1 을(를) %2 센서로 설정 %3',\n        \n                        technicnormallite_is_remote_key: '리모컨 입력 %1',\n                        technicnormallite_is_digital_value: '디지털 입력 %1',\n                        technicnormallite_is_extension_digital_input: '확장 디지털 입력 %1 의 %2',\n                        technicnormallite_get_analog_value: '아날로그 입력 %1',\n                        technicnormallite_get_extension_analog_input: '확장 아날로그 입력 %1 의 %2',\n                        technicnormallite_get_tri_axis_acceler_x: '3가속도 %1의 X축',\n                        technicnormallite_get_tri_axis_acceler_y: '3가속도 %1의 Y축',\n                        technicnormallite_get_tri_axis_acceler_z: '3가속도 %1의 Z축',\n                        technicnormallite_get_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환',\n                        technicnormallite_is_color_value: '컬러 센서 %1 이(가) %2 인가?',\n                        technicnormallite_get_color_value: '컬러 센서 %1 의 색상',\n                        technicnormallite_set_infinite_setting: '%1 센서 %2 을 %3 값으로 정하기 %4',\n                        technicnormallite_get_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값',\n                        technicnormallite_get_infinite_transform_input: '%1 센서 %2 의  %3',\n                        technicnormallite_is_multi_sensor: '멀티키 센서 %1의 %2',\n                        technicnormallite_is_multi_switch: '분배 스위치 %1의 %2',\n                        technicnormallite_set_eeprom_call: 'EEPROM %1 주소의 값 호출하기 %2',\n                        technicnormallite_get_eeprom_address_value: 'EEPROM 주소의 값',      \n        \n                        technicnormallite_set_port_output: '출력핀 %1 을(를) %2 %3',\n                        technicnormallite_set_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3',\n                        technicnormallite_set_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3',\n                        technicnormallite_set_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3',\n                        technicnormallite_play_melody_note_output: '%1 을(를) %2 음표로 연주하기 %3',\n                        technicnormallite_play_melody_sec_output: '%1 을(를) %2 초 동안 연주하기 %3',\n                        technicnormallite_play_melody_output: '%1 을(를) 연주하기 %2',\n                        technicnormallite_play_value_sec_output: '%1 값을(를) %2 초 동안 연주하기 %3',\n                        technicnormallite_play_value_output: '%1 값을(를) 연주하기 %2',\n                        technicnormallite_play_melody_track_output: '%1 을(를) %2초 간격으로 재생하기 %3',\n                        technicnormallite_play_melody_off: '멜로디 중지 %1',\n                        technicnormallite_set_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3',\n                        technicnormallite_set_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2',\n                        technicnormallite_set_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3',\n                        technicnormallite_set_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4',\n                        technicnormallite_set_fnd_output: 'FND를 %1 (으)로 설정 %2',\n                        technicnormallite_set_fnd_off: 'FND 끄기 %1',\n                        technicnormallite_set_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3',\n                    },\n                    Device: {\n                        probo_technic_normal: '프로보 테크닉(일반)',\n                    },\n                    Menus: {\n                        probo_technic_normal_lite: '프로보 테크닉(일반)',\n                    },\n                },\n                en: {\n\n                    template: {\n                        technicnormallite_item_switch: 'Switch',\n                        technicnormallite_item_infrared: 'Infrared',\n                        technicnormallite_item_magnetic: 'Magnetic',\n                        technicnormallite_item_rotation: 'Rotation',\n                        technicnormallite_item_color: 'Color',\n                        technicnormallite_item_acceleration: 'Acceleration',\n                        technicnormallite_item_ultrasonic: 'Ultrasonic',\n                        technicnormallite_item_heart_rate: 'Heart Rate',\n                        technicnormallite_item_illuminance: 'Illuminance',\n                        technicnormallite_item_temperature: 'Temperature',\n                        technicnormallite_item_sound: 'Sound',\n                        technicnormallite_item_tilt: 'Tilt',\n                        technicnormallite_item_pressure: 'Pressure',\n                        technicnormallite_item_multi_touch: 'Multi Touch',\n                        technicnormallite_item_compass: 'Compass',\n                        technicnormallite_item_tri_acceleration: '3Acceleration',\n                        technicnormallite_item_multi_switch: 'Multi Switch',\n                        technicnormallite_item_infinite_rotation: 'Infinite Rotation',\n                        technicnormallite_item_extension_input: 'Extension Input',\n                        technicnormallite_item_color_red: 'Red',\n                        technicnormallite_item_color_green: 'Green',\n                        technicnormallite_item_color_blue: 'Blue',\n                        technicnormallite_item_color_cyan: 'Cyan',\n                        technicnormallite_item_color_magenta: 'Magenta',\n                        technicnormallite_item_color_yellow: 'Yellow',\n                        technicnormallite_item_color_black: 'Black',\n                        technicnormallite_item_color_white: 'White',\n                        technicnormallite_item_value: 'Value',\n                        technicnormallite_item_angle: 'Angle',\n                        technicnormallite_item_absolute_angle: 'Absolute Angle',\n                        technicnormallite_item_number_of_rotations: 'Number of Rotations',\n                        technicnormallite_item_key_1: 'Key1',\n                        technicnormallite_item_key_2: 'Key2',\n                        technicnormallite_item_key_3: 'Key3',\n                        technicnormallite_item_key_4: 'Key4',\n                        technicnormallite_item_key_5: 'Key5',\n                        technicnormallite_item_key_6: 'Key6',\n                        technicnormallite_item_key_7: 'Key7',\n                        technicnormallite_item_key_8: 'Key8',\n                        technicnormallite_item_all: 'All',\n                        technicnormallite_item_on: 'On',\n                        technicnormallite_item_off: 'Off',\n                        technicnormallite_item_note_whole: 'Whole',\n                        technicnormallite_item_note_half: 'Half',\n                        technicnormallite_item_note_quarter: 'Quarter',\n                        technicnormallite_item_note_eighth: 'Eighth',\n                        technicnormallite_item_note_sixteenth: 'Sixteenth',\n                        technicnormallite_item_note_thirty_second: 'Thirty-Second',\n                        technicnormallite_item_pitch_do: 'do',\n                        technicnormallite_item_pitch_do_sharp: 'xdo',\n                        technicnormallite_item_pitch_re: 're',\n                        technicnormallite_item_pitch_re_sharp: 'xre',\n                        technicnormallite_item_pitch_mi: 'mi',\n                        technicnormallite_item_pitch_fa: 'fa',\n                        technicnormallite_item_pitch_fa_sharp: 'xfa',\n                        technicnormallite_item_pitch_sol: 'sol',\n                        technicnormallite_item_pitch_sol_sharp: 'xsol',\n                        technicnormallite_item_pitch_ra: 'ra',\n                        technicnormallite_item_pitch_ra_sharp: 'xra',\n                        technicnormallite_item_pitch_si: 'si',\n                        technicnormallite_item_melody_start: 'Start',\n                        technicnormallite_item_melody_end: 'End',\n                        technicnormallite_item_melody_level_up: 'Level up',\n                        technicnormallite_item_melody_level_down: 'Level down',\n                        \n                        technicnormallite_item_error: 'error',\n                        technicnormallite_item_nothing: 'nothing',\n\n                        technicnormallite_when_press_remote_key: '%1 When %2 remote control key pressed',\n                        technicnormallite_when_input_digital_value: '%1 When %2 digital pin input',\n\n                        technicnormallite_set_senser_setting: 'Set input port %1 to %2 sensor %3',\n\n                        technicnormallite_is_remote_key: 'Remote control %1',\n                        technicnormallite_is_digital_value: 'Read digital pin %1',\n                        technicnormallite_is_extension_digital_input: 'Extension digital input %1 to %2',\n                        technicnormallite_get_analog_value: 'Read analog pin %1',\n                        technicnormallite_get_extension_analog_input: 'Extension analog input %1 to %2',\n                        technicnormallite_get_tri_axis_acceler_x: '3acceleration %1 and X',\n                        technicnormallite_get_tri_axis_acceler_y: '3acceleration %1 and Y',\n                        technicnormallite_get_tri_axis_acceler_z: '3acceleration %1 and Z',\n                        technicnormallite_get_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5',\n                        technicnormallite_is_color_value: 'Is color sensor %1 %2 ?',\n                        technicnormallite_get_color_value: 'Color of color sensor %1',\n                        technicnormallite_set_infinite_setting: 'Set %1 sensor %2 to %3 value %4',\n                        technicnormallite_get_infinite_mm_diameter: 'The move distance(in mm) when the %1 sensor %2 is %3 mm in diameter',\n                        technicnormallite_get_infinite_transform_input: '%1 rotation sensor %2 to %3',\n                        technicnormallite_is_multi_sensor: 'Multi sensor %1 key %2',\n                        technicnormallite_is_multi_switch: 'A key number of the multi-switch sensor %1 = %2',\n                        technicnormallite_set_eeprom_call:'Calling the value of EEPROM %1 address',\n                        technicnormallite_get_eeprom_address_value: 'Value of EEPROM address',\n\n                        technicnormallite_set_dc_output: 'DC motor %1 velocity %2 %3',\n                        technicnormallite_set_servo_output: 'Servo motor %1 position %2 %3',\n                        technicnormallite_set_s_dc_output: 'Servo motor %1 speed %2 %3',\n                        technicnormallite_set_port_output: 'Set digital pin %1 as %2 %3',\n                        technicnormallite_play_melody_note_output: 'Play key %1 for %2 note %3',\n                        technicnormallite_play_melody_sec_output: 'Play key %1 for %2 secs %3',\n                        technicnormallite_play_melody_output: 'Play key %1 %2',\n                        technicnormallite_play_value_sec_output: 'Play value %1 for %2 secs %3',\n                        technicnormallite_play_value_output: 'Play value %1 %2',\n                        technicnormallite_play_melody_track_output: 'Play sound %1 for %2 secs %3',\n                        technicnormallite_play_melody_off: 'Stop tone %1',\n                        technicnormallite_set_rgbled_on_output: 'Turn on RGB LED %1 to %2 %3',\n                        technicnormallite_set_rgbled_off_output: 'Turn off RGB LED %1 %2',\n                        technicnormallite_set_rgbled_dimming_output: 'Dimming RGB LED %1 to %2 %3',\n                        technicnormallite_set_rgbled_flashing_output: 'RGB LED %1 Blinking %2 at %3 second intervals %4',\n                        technicnormallite_set_fnd_output: 'Set FND to %1 %2',\n                        technicnormallite_set_fnd_off: 'Turn off FND %1',\n                        technicnormallite_set_eeprom_write: 'Set EEPROM %1 address to %2 %3',\n                    },\n                    Device: {\n                        probo_technic_normal_lite: 'Probo Technic(Normal)',\n                    },\n                    Menus: {\n                        probo_technic_normal_lite: 'Probo Technic(Normal)',\n                    },\n                },\n            };\n        }\n\n        // 시작하기 및 정지하기 시 기기상태를 초기화한다.\n        setZero() {\n            this.Infinite = {\n                Buff: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Count: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Start: {                    \n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                }\n            };\n            this.SenserSet = {\n                AA1: 0,\n                AA2: 0,\n                AA3: 0,\n                AA4: 0\n            };\n            this.InputData = {\n                Analog: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Digital: {\n                    A1: 0,\n                    A2: 0,\n                    A3: 0,\n                    A4: 0,\n                    FEA1: 0,\n                    FEA2: 0,\n                    FEA3: 0,\n                    FEA4: 0,\n                    REA1: 0,\n                    REA2: 0,\n                    REA3: 0,\n                    REA4: 0,\n                    BEA1: 0,\n                    BEA2: 0,\n                    BEA3: 0,\n                    BEA4: 0\n                },\n                Remote: {\n                    R_1: 0,\n                    R_2: 0,\n                    R_3: 0,\n                    R_4: 0,\n                    R_5: 0,\n                    R_6: 0,\n                    R_7: 0,\n                    R_8: 0,\n                    R_L1: 0,\n                    R_L2: 0,\n                    R_R1: 0,\n                    R_R2: 0\n                },\n                EEPROM: {\n                    EC: 0,\n                    EEPR2: 0,\n                    EEPR1: 0\n                },\n                Infinite:{\n                    ROTATION_1: 0,\n                    ROTATION_2: 0,\n                    ROTATION_3: 0,\n                    ROTATION_4: 0\n                },\n                Acceler:{\n                    AXIS_X1: 0,\n                    AXIS_X2: 0,\n                    AXIS_X3: 0,\n                    AXIS_X4: 0,\n                    AXIS_Y1: 0,\n                    AXIS_Y2: 0,\n                    AXIS_Y3: 0,\n                    AXIS_Y4: 0,\n                    AXIS_Z1: 0,\n                    AXIS_Z2: 0,\n                    AXIS_Z3: 0,\n                    AXIS_Z4: 0\n                }\n            };\n            this.RemoteData = {\n                B1: 0,\n                B2: 0,\n                B3: 0,\n                B4: 0,\n                Servo1: 0,\n                Servo2: 0,\n                Servo3: 0,\n                Servo4: 0,\n                DC1: 0,\n                DC2: 0,\n                DC3: 0,\n                DC4: 0,\n                MEL2: 0,\n                MEL1: 0,\n                FND: 100,\n                EEPR4: 0,\n                EEPR3: 0,\n                EEPR2: 0,\n                EEPR1: 0,\n                ASET2: 0,\n                ASET1: 0\n            };\n            this.EdgeFlag = {\n                FEA1: 0,\n                FEA2: 0,\n                FEA3: 0,\n                FEA4: 0,\n                REA1: 0,\n                REA2: 0,\n                REA3: 0,\n                REA4: 0,\n                BEA1: 0,\n                BEA2: 0,\n                BEA3: 0,\n                BEA4: 0\n            };\n            this.EEPROM = {\n                Buff: 0,\n                Count: 0\n            };\n            \n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            };\n        }\n\n        // 하드웨어 연결 후 초기화한다.\n        async initialHandshake() {\n            const ko = `테크닉의 'Start' 버튼을 누른 후 확인을 클릭하세요.\\n`;\n            const en = `(Please, After pushing the 'Start' button in Technic, click 'OK'.)`;\n            alert(`${ko}${en}`);\n\n            const modePacket = new Uint8Array(2).fill(0);\n            modePacket[0] = 0x63;\n            modePacket[1] = 0x36;\n\n            while(true) {\n                const response = await Entry.hwLite.serial.sendAsyncWithThrottle(modePacket);\n\n                if (response[0] !== TECHNIC_NORMAL_INDEX) {\n                    modePacket[0] = 0x24;\n                    modePacket[1] = 0x42;\n                } else {\n                    this.version = (response.length === 1)\n                        ? RELEASE_VERSION\n                        : response[1];\n                    await Entry.Utils.sleep(1000);\n                    break;\n                }\n                await Entry.Utils.sleep(100);\n            }\n\n            Entry.addEventListener('run', this.handleRemoteEventInterval.bind(this));\n            Entry.addEventListener('run', this.handleDigitalEventInterval.bind(this));\n            Entry.addEventListener('beforeStop', () => {\n                if (this.remoteEventIntervalId) {\n                    clearInterval(this.remoteEventIntervalId);\n                    this.remoteEventIntervalId = null;\n                }\n                if (this.digitalEventIntervalId) {\n                    clearInterval(this.digitalEventIntervalId);\n                    this.digitalEventIntervalId = null;\n                }\n            });\n            this.setZero();\n\n            if (this.version === 0) {\n                const packet = await Entry.hwLite.serial.reader.read();\n                this.version = packet.value[0];\n                if (this.version !== RELEASE_VERSION) {\n                    const ko = `펌웨어를 업데이트 하세요.\\n`;\n                    const en = `(Please, Update your firmware.)\\n`;\n                    const version = ` - 현재(now): v.${this.version}\\n - 최신(latest): v.${RELEASE_VERSION}`;\n                    alert(`${ko}${en}${version}`);\n                }\n            }\n            return true;\n        }\n\n        handleRemoteEventInterval() {\n            if (this.remoteEventIntervalId) {\n                clearInterval(this.remoteEventIntervalId);\n            }\n            this.remoteEventIntervalId = setInterval(() => {\n                const currentState = this.remoteEvent.bind(this);\n                currentState();\n            }, EVENT_INTERVAL);\n        }\n\n        handleDigitalEventInterval() {            \n            if (this.digitalEventIntervalId) {\n                clearInterval(this.digitalEventIntervalId);\n            }\n            this.digitalEventIntervalId = setInterval(() => {\n                const currentState = this.digitalEvent.bind(this);\n                currentState();\n            }, EVENT_INTERVAL);\n        }\n\n        // 디바이스에서 값을 읽어온다.\n        handleLocalData(buffer) {\n            buffer.forEach(b => this.qEnqueue(b));\n\n            if (this._recoverTimeoutId) {\n                clearTimeout(this._recoverTimeoutId);\n            }\n            \n            while(this.qCount() >= this.inputPacket.length) {\n                if (!this.process) {\n                    while(this.qCount() > 0) {\n                        if (this.inputPacket[0] !== 0xCD) {\n                            this.inputPacket[0] = this.qDequeue();\n                        } else if (this.inputPacket[1] !== 0xDA) {\n                            this.inputPacket[1] = this.qDequeue();\n                        } else {\n                            this.inputPacket[2] = this.qDequeue();\n                            this.pLength = this.inputPacket[2] + 3;\n                            this.process = true;\n                            break;\n                        }\n                    }\n                }\n    \n                if (this.process && (this.qCount() >= this.pLength)) {\n                    for (let i = 3; i < this.pLength; i++) {\n                        this.inputPacket[i] = this.qDequeue();\n                    }\n                    if (this.checksumHandle(this.inputPacket)) {\n                        this.processInputPacket(this.inputPacket);\n                    }\n\n                    this.inputPacket = new Uint8Array(RECEIVED_PACKET_LENGTH).fill(-1);\n                    this.process = false;\n                    this.sendFlag = true;\n                    this.pLength = 0;\n                }\n            }\n\n            if (this.sendFlag) {\n                if (this._requestTimeoutId) {\n                    clearTimeout(this._requestTimeoutId);\n                }\n                this._requestTimeoutId = setTimeout(\n                    () => {\n                        if (Entry.hwLite && Entry.hwLite.serial) {\n                            Entry.hwLite.serial.update();\n                            this.sendFlag = false;\n                            this._recoverTimeoutId = setTimeout(() => {\n                                this.sendFlag = true;\n                            }, SERIAL_INTERVAL * 3);\n                        }\n                    },\n                    SERIAL_INTERVAL\n                );\n            };\n        }\n\n        //디바이스에 값을 쓴다.\n        requestLocalData() {\n            if (this.sendFlag) {\n                return this.generateOutputPacket(this.RemoteData);\n            }\n        }\n\n        qEnqueue(data) {\n            this.qBuffer[this.qRear] = data;\n            this.qRear = (this.qRear + 1) % this.qSize\n        }\n\n        qDequeue() {\n            const data = this.qBuffer[this.qFront];\n            this.qBuffer[this.qFront] = -1;\n            this.qFront = (this.qFront + 1) % this.qSize;\n            return data;\n        }\n\n        qCount() {\n            return (this.qFront <= this.qRear)\n                ? (this.qRear - this.qFront)\n                : (this.qSize - this.qFront + this.qRear);\n        }\n\n        checksumRequest(packet) {\n            const length = packet[2] + 2;\n            let checker = 0;\n            for(let i = 3; i < length; i++) {\n                checker += packet[i];\n            }\n            return (checker & 0xFF);\n\n        }\n        \n        checksumHandle(packet) {\n            let checker = 0;\n            const length = packet[2] + 2;\n            for(let i = 3; i < length ; i++ ) {\n                checker += packet[i];\n            }\n            return (packet[length] === (checker & 0xFF))\n        }\n\n        processInputPacket(packet) {\n            const digitalByte1 = packet[8];\n            const digitalByte2 = packet[9];\n            const remoteByte1 = packet[10];\n            const remoteByte2 = packet[11];\n            const rotationByte = packet[16];\n\n            this.InputData.Analog.AA1 = packet[4];\n            this.InputData.Analog.AA2 = packet[5];\n            this.InputData.Analog.AA3 = packet[6];\n            this.InputData.Analog.AA4 = packet[7];\n\n            this.InputData.Digital.A4 = (digitalByte1 >> 7) & 0x01;\n            this.InputData.Digital.A3 = (digitalByte1 >> 6) & 0x01;\n            this.InputData.Digital.A2 = (digitalByte1 >> 5) & 0x01;\n            this.InputData.Digital.A1 = (digitalByte1 >> 4) & 0x01;\n            this.InputData.Digital.FEA4 = (digitalByte1 >> 3) & 0x01;\n            this.InputData.Digital.FEA3 = (digitalByte1 >> 2) & 0x01;\n            this.InputData.Digital.FEA2 = (digitalByte1 >> 1) & 0x01;\n            this.InputData.Digital.FEA1 = digitalByte1 & 0x01;\n            this.InputData.Digital.REA4 = (digitalByte2 >> 7) & 0x01;\n            this.InputData.Digital.REA3 = (digitalByte2 >> 6) & 0x01;\n            this.InputData.Digital.REA2 = (digitalByte2 >> 5) & 0x01;\n            this.InputData.Digital.REA1 = (digitalByte2 >> 4) & 0x01;\n            this.InputData.Digital.BEA4 = (digitalByte2 >> 3) & 0x01;\n            this.InputData.Digital.BEA3 = (digitalByte2 >> 2) & 0x01;\n            this.InputData.Digital.BEA2 = (digitalByte2 >> 1) & 0x01;\n            this.InputData.Digital.BEA1 = digitalByte2 & 0x01;\n\n            this.InputData.Remote.R_3 = (remoteByte1 >> 7) & 0x01;\n            this.InputData.Remote.R_2 = (remoteByte1 >> 6) & 0x01;\n            this.InputData.Remote.R_4 = (remoteByte1 >> 5) & 0x01;\n            this.InputData.Remote.R_1 = (remoteByte1 >> 4) & 0x01;                    \n            this.InputData.Remote.R_7 = (remoteByte2 >> 7) & 0x01;\n            this.InputData.Remote.R_6 = (remoteByte2 >> 6) & 0x01;\n            this.InputData.Remote.R_8 = (remoteByte2 >> 5) & 0x01;\n            this.InputData.Remote.R_5 = (remoteByte2 >> 4) & 0x01;\n            this.InputData.Remote.R_R1 = (remoteByte2 >> 3) & 0x01;\n            this.InputData.Remote.R_L1 = (remoteByte2 >> 2) & 0x01;\n            this.InputData.Remote.R_R2 = (remoteByte2 >> 1) & 0x01;\n            this.InputData.Remote.R_L2 = remoteByte2 & 0x01;\n\n            this.InputData.EEPROM.EC = packet[13];\n            this.InputData.EEPROM.EEPR2 = packet[14];\n            this.InputData.EEPROM.EEPR1 = packet[15];\n\n            this.InputData.Infinite.ROTATION_1 = (rotationByte >> 6) & 0x0C;\n            this.InputData.Infinite.ROTATION_2 = (rotationByte >> 4) & 0x0C;\n            this.InputData.Infinite.ROTATION_3 = (rotationByte >> 2) & 0x0C;\n            this.InputData.Infinite.ROTATION_4 = rotationByte & 0x03;\n\n            this.InputData.Acceler.AXIS_X1 = packet[4];\n            this.InputData.Acceler.AXIS_X2 = packet[5];\n            this.InputData.Acceler.AXIS_X3 = packet[6];\n            this.InputData.Acceler.AXIS_X4 = packet[7];\n\n            this.InputData.Acceler.AXIS_Y1 = packet[17];\n            this.InputData.Acceler.AXIS_Y2 = packet[19];\n            this.InputData.Acceler.AXIS_Y3 = packet[21];\n            this.InputData.Acceler.AXIS_Y4 = packet[23];\n\n            this.InputData.Acceler.AXIS_Z1 = packet[18];\n            this.InputData.Acceler.AXIS_Z2 = packet[20];\n            this.InputData.Acceler.AXIS_Z3 = packet[22];\n            this.InputData.Acceler.AXIS_Z4 = packet[24];\n        }\n\n        generateOutputPacket(remoteData) {           \n\n            const outputPacket = new Uint8Array(SEND_PACKET_LENGTH).fill(-1);\n\n            outputPacket[0] = 0xAD;\n            outputPacket[1] = 0xDA;\n            outputPacket[2] = outputPacket.length - 3;\n\n            outputPacket[3] = 0xF0 | (remoteData.B4 << 3) | (remoteData.B3 << 2) | (remoteData.B2 << 1) | remoteData.B1;\n\n            outputPacket[4] = remoteData.Servo1;\n            outputPacket[5] = remoteData.Servo2;\n            outputPacket[6] = remoteData.Servo3;\n            outputPacket[7] = remoteData.Servo4;\n\n            outputPacket[8] = remoteData.DC1;\n            outputPacket[9] = remoteData.DC2;\n            outputPacket[10] = remoteData.DC3;\n            outputPacket[11] = remoteData.DC4;\n\n            outputPacket[12] = remoteData.MEL2;\n            outputPacket[13] = remoteData.MEL1;\n\n            outputPacket[14] = remoteData.FND; \n\n            outputPacket[15] = remoteData.EEPR4;\n            outputPacket[16] = remoteData.EEPR3;\n            outputPacket[17] = remoteData.EEPR2;\n            outputPacket[18] = remoteData.EEPR1;\n\n            outputPacket[19] = remoteData.ASET2;\n            outputPacket[20] = remoteData.ASET1;\n\n            outputPacket[21] = this.checksumRequest(outputPacket);\n\n            return outputPacket;\n        }\n        \n        getMonitorPort() {\n            return { ...this.InputData.Analog };\n        }\n\n        getRemoteKey(data) {\n            const num = Number(data);            \n            \n            if (1 <= num && num <= 8) {\n                return `R_${num}`;\n            } else if (9 <= num && num <= 10) {\n                return `R_L${(num - 8)}`;\n            } else if (11 <= num && num <= 12) {\n                return `R_R${(num - 10)}`;\n            } else {\n                return data;\n            }\n        }\n\n        getDigitalKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `A${num}`;\n            } else if (5 <= num && num <= 8) {\n                return `FEA${num - 4}`;\n            } else if (9 <= num && num <= 12) {\n                return `REA${num - 8}`;\n            } else if (13 <= num && num <= 16) {\n                return `BEA${num - 12}`;\n            } else {\n                return data;\n            }\n        }\n\n        getDigitalStateValue(key) {\n            let value = false;\n            switch(key) {\n                case 'A1':\n                case 'A2':\n                case 'A3':\n                case 'A4':\n                    value = (Entry.ProboTechnicNormalLite.InputData.Digital[key] === 1);\n                    break;\n                default:\n                    if (Entry.ProboTechnicNormalLite.InputData.Digital[key] === 1) {\n                        if (Entry.ProboTechnicNormalLite.EdgeFlag[key] === 0) {\n                            Entry.ProboTechnicNormalLite.EdgeFlag[key] = 1;\n                            value = true;\n                        }\n                    } else {\n                        Entry.ProboTechnicNormalLite.EdgeFlag[key] = 0;\n                    }\n                    break;\n            }\n\n            return value;\n        }\n\n        getAnalogKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `AA${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getSettingSensorValue(key) {\n            switch (key) {\n                case '1':  // 스위치\n                case '2':  // 적외선\n                case '3':  // 자석\n                case '16': // 분배기\n                case Lang.template.technicnormallite_item_switch:       // 스위치\n                case Lang.template.technicnormallite_item_infrared:     // 적외선\n                case Lang.template.technicnormallite_item_magnetic:     // 자석\n                case Lang.template.technicnormallite_item_multi_switch: // 분배기\n                    return 1;\n                case '4': // 회전\n                case '7': // 조도\n                case '9': // 초음파\n                case Lang.template.technicnormallite_item_rotation:    // 회전\n                case Lang.template.technicnormallite_item_illuminance: // 조도            \n                case Lang.template.technicnormallite_item_ultrasonic:  // 초음파\n                    return 2;\n                case '10': // 소리\n                case Lang.template.technicnormallite_item_sound: // 소리\n                    return 3;\n                case '11': // 기울기\n                case Lang.template.technicnormallite_item_tilt: // 기울기\n                    return 4;\n                case '12': // 압력\n                case Lang.template.technicnormallite_item_pressure: // 압력\n                    return 5;\n                case '8': // 심박\n                case Lang.template.technicnormallite_item_heart_rate: // 심박\n                    return 6;\n                case '5': // 컬러\n                case Lang.template.technicnormallite_item_color: // 컬러\n                    return 7;\n                case '6': // 가속도\n                case Lang.template.technicnormallite_item_acceleration: // 가속도\n                    return 8;\n                case '14': // 나침반\n                case '15': // 3축 가속도\n                case '17': // 확장 입력  \n                case Lang.template.technicnormallite_item_compass:\n                case Lang.template.technicnormallite_item_tri_acceleration:\n                case Lang.template.technicnormallite_item_extension_input:\n                    return 9;\n                case '13': // 멀티터치(멀티키)\n                case Lang.template.technicnormallite_item_multi_touch: // 멀티터치(멀티키)\n                    return 11;\n                default:\n                    return key;\n            }\n        }\n\n        getAxisKey(data, axis) {\n            switch (data) {\n                case 'AA1':\n                case 'AA2':\n                case 'AA3':\n                case 'AA4':\n                    data = data.substr(2, 2);\n                    break;\n            }\n\n            return `AXIS_${axis}${data}`;\n        }\n\n        getMultiKeyValue(key) {\n            const num = Number(key);\n\n            if (1 <= num && num <= 8) {\n                return (num - 1);\n            } else {\n                switch (key) {\n                    case Lang.template.technicnormallite_item_key_1:\n                        return 0;\n                    case Lang.template.technicnormallite_item_key_2:\n                        return 1;\n                    case Lang.template.technicnormallite_item_key_3:\n                        return 2;\n                    case Lang.template.technicnormallite_item_key_4:\n                        return 3;\n                    case Lang.template.technicnormallite_item_key_5:\n                        return 4;\n                    case Lang.template.technicnormallite_item_key_6:\n                        return 5;\n                    case Lang.template.technicnormallite_item_key_7:\n                        return 6;\n                    case Lang.template.technicnormallite_item_key_8:\n                        return 7;\n                    default:\n                        return key;\n                }\n            }\n        }\n\n        getExtentionDigitalValue(key) {\n            const num = Number(key);\n            if (1 <= num && num <= 8) {\n                return (num - 1);\n            } else if (9 <= num && num <= 16) {                \n                return (num - 9);\n            } else {\n                switch (key) {\n                    case 'EA1':\n                    case 'ET1':\n                        return 0;\n                    case 'EA2':\n                    case 'ET2':\n                        return 1;\n                    case 'EA3':\n                    case 'ET3':\n                        return 2;\n                    case 'EA4':\n                    case 'ET4':\n                        return 3;\n                    case 'EA5':\n                    case 'ET5':\n                        return 4;\n                    case 'EA6':\n                    case 'ET6':\n                        return 5;\n                    case 'EA7':\n                    case 'ET7':\n                        return 6;\n                    case 'EA8':\n                    case 'ET8':\n                        return 7;\n                    default:\n                        return key;\n                }\n            }\n        }\n\n        getExtentionAnalogKey(data) {\n            switch (data) {\n                case '1':\n                case 'EAA1':\n                    return 'Y';\n                case '2':\n                case 'EAA2':\n                    return 'Z';\n                default:\n                    return data;\n            }\n        }\n\n        getDckey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 7) {\n                return `DC${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getServoKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `Servo${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getPortKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `B${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getPortToggleValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.technicnormallite_item_on:\n                    return 1;\n                case '0':\n                case Lang.template.technicnormallite_item_off:\n                    return 0;\n                default:\n                    return key;\n            }\n        }\n\n        getSensorAngleKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.technicnormallite_item_value:\n                    return 'IS1';\n                case '2':\n                case Lang.template.technicnormallite_item_angle:\n                    return 'IS2';\n                case '3':\n                case Lang.template.technicnormallite_item_absolute_angle:\n                    return 'IS3';\n                case '4':\n                case Lang.template.technicnormallite_item_number_of_rotations:\n                    return 'IS4';\n                default:\n                    return data;\n            }\n        }\n\n        getPitchValue(pitch) {\n            // 배열의 인덱스 1번부터 음표\n            const index = (pitch % 12) + 1;\n\n            if (36 <= pitch && pitch <= 47) {\n                return Entry.ProboTechnicNormalLite.Melody[index];\n            } else if (48 <= pitch && pitch <= 59) {\n                return Entry.ProboTechnicNormalLite.Melody[index] >> 1;\n            } else if (60 <= pitch && pitch <= 71) {\n                return Entry.ProboTechnicNormalLite.Melody[index] >> 2;\n            } else if (72 <= pitch && pitch <= 83) {\n                return Entry.ProboTechnicNormalLite.Melody[index] >> 3;\n            } else {\n                return Entry.ProboTechnicNormalLite.Melody[0];\n            }\n        }\n\n        getNoteKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.technicnormallite_item_note_whole:\n                    return 'n1';\n                case '2':\n                case Lang.template.technicnormallite_item_note_half:\n                    return 'n2';\n                case '4':\n                case Lang.template.technicnormallite_item_note_quarter:\n                    return 'n4';\n                case '8':\n                case Lang.template.technicnormallite_item_note_eighth:\n                    return 'n8';\n                case '16':\n                case Lang.template.technicnormallite_item_note_sixteenth:\n                    return 'n16';\n                case '32':\n                case Lang.template.technicnormallite_item_note_thirty_second:\n                    return 'n32';\n                default:\n                    return data;\n            }\n        }\n\n        getMelodyValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.technicnormallite_item_melody_start:\n                    return 0;\n                case '2':\n                case Lang.template.technicnormallite_item_melody_end:\n                    return 1;\n                case '3':\n                case Lang.template.technicnormallite_item_melody_level_up:\n                    return 2;\n                case '4':\n                case Lang.template.technicnormallite_item_melody_level_down:\n                    return 3;\n                default:\n                    return key;\n            }\n        }\n\n        getColorSensorKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.technicnormallite_item_color_red:\n                    return 'Red';\n                case '2':\n                case Lang.template.technicnormallite_item_color_green:\n                    return 'Green';\n                case '3':\n                case Lang.template.technicnormallite_item_color_blue:\n                    return 'Blue';\n                case '4':\n                case Lang.template.technicnormallite_item_color_yellow:\n                    return 'Yellow';\n                case '5':\n                case Lang.template.technicnormallite_item_color_black:\n                    return 'Black';\n                case '6':\n                case Lang.template.technicnormallite_item_color_white:\n                    return 'White';\n                default:\n                    return data;\n            }\n        }\n\n        getRgbToggleValue(key) {\n            switch (key) {\n                case '0':\n                    return this.Rgb.Off;\n                case '1':\n                case Lang.template.technicnormallite_item_color_red:\n                    return this.Rgb.On.Red;\n                case '2':\n                case Lang.template.technicnormallite_item_color_green:\n                    return this.Rgb.On.Green;\n                case '3':\n                case Lang.template.technicnormallite_item_color_blue:\n                    return this.Rgb.On.Blue;\n                case '4':\n                case Lang.template.technicnormallite_item_color_cyan:\n                    return this.Rgb.On.Cyan;\n                case '5':\n                case Lang.template.technicnormallite_item_color_magenta:\n                    return this.Rgb.On.Magenta;\n                case '6':\n                case Lang.template.technicnormallite_item_color_yellow:\n                    return this.Rgb.On.Yellow;\n                case '7':\n                case Lang.template.technicnormallite_item_color_white:\n                    return this.Rgb.On.White;\n                default:\n                    return key;\n            }\n        }\n\n        getRgbTwinkleValue(key, sec) {\n            let twinkle = 0;\n            switch (sec) {\n                case 0.05:\n                    twinkle += 1;\n                    break;\n                case 0.1:\n                    twinkle += 2;\n                    break;\n                case 0.2:\n                    twinkle += 3;\n                    break;\n                case 0.5:\n                    twinkle += 4;\n                    break;\n                case 1:\n                    twinkle += 5;\n                    break;\n            }\n\n            return this.getRgbToggleValue(key) + twinkle;\n        }\n\n        getRgbDimmingValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.technicnormallite_item_color_red:\n                    return this.Rgb.Dimming.Red;\n                case '2':\n                case Lang.template.technicnormallite_item_color_green:\n                    return this.Rgb.Dimming.Green;\n                case '3':\n                case Lang.template.technicnormallite_item_color_blue:\n                    return this.Rgb.Dimming.Blue;\n                case '4':\n                case Lang.template.technicnormallite_item_color_cyan:\n                    return this.Rgb.Dimming.Cyan;        \n                case '5':\n                case Lang.template.technicnormallite_item_color_magenta:\n                    return this.Rgb.Dimming.Magenta;\n                case '6':\n                case Lang.template.technicnormallite_item_color_yellow:\n                    return this.Rgb.Dimming.Yellow;\n                case '7':\n                case Lang.template.technicnormallite_item_color_white:\n                    return this.Rgb.Dimming.White;\n                default:\n                    return key;\n            }\n        }\n\n        getBlocks() {\n            return {\n                ///========================================================================================\n                /// Dropdown block\n                ///========================================================================================\n                technicnormallite_dropdown_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['R_1', '1'],\n                                ['R_2', '2'],\n                                ['R_3', '3'],\n                                ['R_4', '4'],\n                                ['R_5', '5'],\n                                ['R_6', '6'],\n                                ['R_7', '7'],\n                                ['R_8', '8'],\n                                ['R_L1', '9'],\n                                ['R_L2', '10'],\n                                ['R_R1', '11'],\n                                ['R_R2', '12'],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringValue('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['R_1', '1'],\n                                            ['R_2', '2'],\n                                            ['R_3', '3'],\n                                            ['R_4', '4'],\n                                            ['R_5', '5'],\n                                            ['R_6', '6'],\n                                            ['R_7', '7'],\n                                            ['R_8', '8'],\n                                            ['R_L1', '9'],\n                                            ['R_L2', '10'],\n                                            ['R_R1', '11'],\n                                            ['R_R2', '12'],\n                                        ],\n                                        value: 1,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_remote_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_digital_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['A1', '1'],\n                                ['A2', '2'],\n                                ['A3', '3'],\n                                ['A4', '4'],\n                                ['FEA1', '5'],\n                                ['FEA2', '6'],\n                                ['FEA3', '7'],\n                                ['FEA4', '8'],\n                                ['REA1', '9'],\n                                ['REA2', '10'],\n                                ['REA3', '11'],\n                                ['REA4', '12'],\n                                ['BEA1', '13'],\n                                ['BEA2', '14'],\n                                ['BEA3', '15'],\n                                ['BEA4', '16'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['A1', '1'],\n                                            ['A2', '2'],\n                                            ['A3', '3'],\n                                            ['A4', '4'],\n                                            ['FEA1', '5'],\n                                            ['FEA2', '6'],\n                                            ['FEA3', '7'],\n                                            ['FEA4', '8'],\n                                            ['REA1', '9'],\n                                            ['REA2', '10'],\n                                            ['REA3', '11'],\n                                            ['REA4', '12'],\n                                            ['BEA1', '13'],\n                                            ['BEA2', '14'],\n                                            ['BEA3', '15'],\n                                            ['BEA4', '16'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_digital_key',\n                            },\n                        ],\n                    }\n                },\n                technicnormallite_dropdown_analog_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['AA1', '1'],\n                                ['AA2', '2'],\n                                ['AA3', '3'],\n                                ['AA4', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['AA1', '1'],\n                                            ['AA2', '2'],\n                                            ['AA3', '3'],\n                                            ['AA4', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_analog_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_setting_sensor_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_switch, '1'],\n                                [Lang.template.technicnormallite_item_infrared, '2'],\n                                [Lang.template.technicnormallite_item_magnetic, '3'],\n                                [Lang.template.technicnormallite_item_rotation, '4'],\n                                [Lang.template.technicnormallite_item_color, '5'],\n                                // [Lang.template.technicnormallite_item_acceleration, '6'],     // 테크닉 에서 사용하지 않음\n                                [Lang.template.technicnormallite_item_ultrasonic, '7'],\n                                [Lang.template.technicnormallite_item_heart_rate, '8'],\n                                [Lang.template.technicnormallite_item_illuminance, '9'],\n                                [Lang.template.technicnormallite_item_sound, '10'],\n                                [Lang.template.technicnormallite_item_tilt, '11'],\n                                [Lang.template.technicnormallite_item_pressure, '12'],\n                                // [Lang.template.technicnormallite_item_multi_touch, '13'],      // 테크닉 에서 사용하지 않음\n                                // [Lang.template.technicnormallite_item_compass, '14'],          // 테크닉 에서 사용하지 않음\n                                // [Lang.template.technicnormallite_item_tri_acceleration, '15'], // 테크닉 에서 사용하지 않음\n                                // [Lang.template.technicnormallite_item_multi_switch, '16'],     // 테크닉 에서 사용하지 않음\n                                // [Lang.template.technicnormallite_item_extension_input, '17'], // 테크닉 에서 사용하지 않음\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_switch, '1'],\n                                            [Lang.template.technicnormallite_item_infrared, '2'],\n                                            [Lang.template.technicnormallite_item_magnetic, '3'],\n                                            [Lang.template.technicnormallite_item_rotation, '4'],\n                                            [Lang.template.technicnormallite_item_color, '5'],\n                                            // [Lang.template.technicnormallite_item_acceleration, '6'],     // 테크닉 에서 사용하지 않음\n                                            [Lang.template.technicnormallite_item_ultrasonic, '7'],\n                                            [Lang.template.technicnormallite_item_heart_rate, '8'],\n                                            [Lang.template.technicnormallite_item_illuminance, '9'],\n                                            [Lang.template.technicnormallite_item_sound, '10'],\n                                            [Lang.template.technicnormallite_item_tilt, '11'],\n                                            [Lang.template.technicnormallite_item_pressure, '12'],\n                                            // [Lang.template.technicnormallite_item_multi_touch, '13'],      // 테크닉 에서 사용하지 않음\n                                            // [Lang.template.technicnormallite_item_compass, '14'],          // 테크닉 에서 사용하지 않음\n                                            // [Lang.template.technicnormallite_item_tri_acceleration, '15'], // 테크닉 에서 사용하지 않음\n                                            // [Lang.template.technicnormallite_item_multi_switch, '16'],     // 테크닉 에서 사용하지 않음\n                                            // [Lang.template.technicnormallite_item_extension_input, '17'], // 테크닉 에서 사용하지 않음\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_setting_sensor_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_inNcom_sensor_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_infinite_rotation, '1'],\n                                //[Lang.template.technicnormallite_item_compass, '2'], // 테크닉 에서 사용하지 않음\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_infinite_rotation, '1'],\n                                            [Lang.template.technicnormallite_item_compass, '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_inNcom_sensor_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_sensor_color_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_color_red, '1'],\n                                [Lang.template.technicnormallite_item_color_green, '2'],\n                                [Lang.template.technicnormallite_item_color_blue, '3'],\n                                [Lang.template.technicnormallite_item_color_yellow, '4'],\n                                [Lang.template.technicnormallite_item_color_black, '5'],\n                                [Lang.template.technicnormallite_item_color_white, '6'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_color_red, '1'],\n                                            [Lang.template.technicnormallite_item_color_green, '2'],\n                                            [Lang.template.technicnormallite_item_color_blue, '3'],\n                                            [Lang.template.technicnormallite_item_color_yellow, '4'],\n                                            [Lang.template.technicnormallite_item_color_black, '5'],\n                                            [Lang.template.technicnormallite_item_color_white, '6'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_sensor_color_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_rgb_color_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_color_red, '1'],\n                                [Lang.template.technicnormallite_item_color_green, '2'],\n                                [Lang.template.technicnormallite_item_color_blue, '3'],\n                                [Lang.template.technicnormallite_item_color_cyan, '4'],\n                                [Lang.template.technicnormallite_item_color_magenta, '5'],\n                                [Lang.template.technicnormallite_item_color_yellow, '6'],\n                                [Lang.template.technicnormallite_item_color_white, '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_color_red, '1'],\n                                            [Lang.template.technicnormallite_item_color_green, '2'],\n                                            [Lang.template.technicnormallite_item_color_blue, '3'],\n                                            [Lang.template.technicnormallite_item_color_cyan, '4'],\n                                            [Lang.template.technicnormallite_item_color_magenta, '5'],\n                                            [Lang.template.technicnormallite_item_color_yellow, '6'],\n                                            [Lang.template.technicnormallite_item_color_white, '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_rgb_color_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_sensor_angle_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_value, '1'],\n                                [Lang.template.technicnormallite_item_angle, '2'],\n                                [Lang.template.technicnormallite_item_absolute_angle, '3'],\n                                [Lang.template.technicnormallite_item_number_of_rotations, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_value, '1'],\n                                            [Lang.template.technicnormallite_item_angle, '2'],\n                                            [Lang.template.technicnormallite_item_absolute_angle, '3'],\n                                            [Lang.template.technicnormallite_item_number_of_rotations, '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_sensor_angle_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_multikey_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_key_1, '1'],\n                                [Lang.template.technicnormallite_item_key_2, '2'],\n                                [Lang.template.technicnormallite_item_key_3, '3'],\n                                [Lang.template.technicnormallite_item_key_4, '4'],\n                                [Lang.template.technicnormallite_item_key_5, '5'],\n                                [Lang.template.technicnormallite_item_key_6, '6'],\n                                [Lang.template.technicnormallite_item_key_7, '7'],\n                                [Lang.template.technicnormallite_item_key_8, '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_key_1, '1'],\n                                            [Lang.template.technicnormallite_item_key_2, '2'],\n                                            [Lang.template.technicnormallite_item_key_3, '3'],\n                                            [Lang.template.technicnormallite_item_key_4, '4'],\n                                            [Lang.template.technicnormallite_item_key_5, '5'],\n                                            [Lang.template.technicnormallite_item_key_6, '6'],\n                                            [Lang.template.technicnormallite_item_key_7, '7'],\n                                            [Lang.template.technicnormallite_item_key_8, '8'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_multikey_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_extension_digital_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['EA1', '1'],\n                                ['EA2', '2'],\n                                ['EA3', '3'],\n                                ['EA4', '4'],\n                                ['EA5', '5'],\n                                ['EA6', '6'],\n                                ['EA7', '7'],\n                                ['EA8', '8'],\n                                ['ET1', '9'],\n                                ['ET2', '10'],\n                                ['ET3', '11'],\n                                ['ET4', '12'],\n                                ['ET5', '13'],\n                                ['ET6', '14'],\n                                ['ET7', '15'],\n                                ['ET8', '16'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['EA1', '1'],\n                                            ['EA2', '2'],\n                                            ['EA3', '3'],\n                                            ['EA4', '4'],\n                                            ['EA5', '5'],\n                                            ['EA6', '6'],\n                                            ['EA7', '7'],\n                                            ['EA8', '8'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_extension_digital_key',\n                            },\n                        ],\n                    },\n                },                \n                technicnormallite_dropdown_extension_analog_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['EAA1', '1'],\n                                ['EAA2', '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['EAA1', '1'],\n                                            ['EAA2', '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_extension_analog_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_dc_1_all_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['1,2', '5'],\n                                ['3,4', '6'],\n                                [Lang.template.technicnormallite_item_all, '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['1,2', '5'],\n                                            ['3,4', '6'],\n                                            [Lang.template.technicnormallite_item_all, '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_dc_1_all_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_velocity_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['20', '20'],\n                                ['15', '15'],\n                                ['10', '10'],\n                                ['5', '5'],\n                                ['0', '0'],\n                                ['-5', '-5'],\n                                ['-10', '-10'],\n                                ['-15', '-15'],\n                                ['-20', '-20'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['20', '20'],\n                                            ['15', '15'],\n                                            ['10', '10'],\n                                            ['5', '5'],\n                                            ['0', '0'],\n                                            ['-5', '-5'],\n                                            ['-10', '-10'],\n                                            ['-15', '-15'],\n                                            ['-20', '-20'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_velocity_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_servo_position_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['20', '20'],\n                                ['40', '40'],\n                                ['60', '60'],\n                                ['80', '80'],\n                                ['100', '100'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },                    \n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['20', '20'],\n                                            ['40', '40'],\n                                            ['60', '60'],\n                                            ['80', '80'],\n                                            ['100', '100'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_servo_position_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_port_1_4_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_port_1_4_key',\n                            },\n                        ],\n                    },\n                },           \n                technicnormallite_dropdown_on_off_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_on, '1'],\n                                [Lang.template.technicnormallite_item_off, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    events: {},\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_on, '1'],\n                                            [Lang.template.technicnormallite_item_off, '0'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_on_off_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_note_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_note_whole, '1'],\n                                [Lang.template.technicnormallite_item_note_half, '2'],\n                                [Lang.template.technicnormallite_item_note_quarter, '4'],\n                                [Lang.template.technicnormallite_item_note_eighth, '8'],\n                                [Lang.template.technicnormallite_item_note_sixteenth, '16'],\n                                [Lang.template.technicnormallite_item_note_thirty_second, '32'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_note_whole, '1'],\n                                            [Lang.template.technicnormallite_item_note_half, '2'],\n                                            [Lang.template.technicnormallite_item_note_quarter, '4'],\n                                            [Lang.template.technicnormallite_item_note_eighth, '8'],\n                                            [Lang.template.technicnormallite_item_note_sixteenth, '16'],\n                                            [Lang.template.technicnormallite_item_note_thirty_second, '32'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_note_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_time_1_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.1', '0.1'],\n                                ['0.3', '0.3'],\n                                ['0.5', '0.5'],\n                                ['0.7', '0.7'],\n                                ['1', '1'],\n                                ['2', '2'],\n                            ],\n                            value: '0.5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.1', '0.1'],\n                                            ['0.3', '0.3'],\n                                            ['0.5', '0.5'],\n                                            ['0.7', '0.7'],\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                        ],\n                                        value: '0.5',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_time_1_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_time_2_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.1', '0.1'],\n                                ['0.3', '0.3'],\n                                ['0.5', '0.5'],\n                                ['0.7', '0.7'],\n                                ['1', '1'],\n                                ['2', '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.1', '0.1'],\n                                            ['0.3', '0.3'],\n                                            ['0.5', '0.5'],\n                                            ['0.7', '0.7'],\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_time_2_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_time_3: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.05', '0.05'],\n                                ['0.1', '0.1'],\n                                ['0.2', '0.2'],\n                                ['0.5', '0.5'],\n                                ['1', '1'],\n                            ],\n                            value: '0.5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.05', '0.05'],\n                                            ['0.1', '0.1'],\n                                            ['0.2', '0.2'],\n                                            ['0.5', '0.5'],\n                                            ['1', '1'],\n                                        ],\n                                        value: '0.5',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_time_3',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_pitch_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'DropdownExtra',\n                            options: [\n                                [Lang.template.technicnormallite_item_pitch_do + ' (36)', '36'],\n                                [Lang.template.technicnormallite_item_pitch_do_sharp + ' (37)', '37'],\n                                [Lang.template.technicnormallite_item_pitch_re + ' (38)', '38'],\n                                [Lang.template.technicnormallite_item_pitch_re_sharp + ' (39)', '39'],\n                                [Lang.template.technicnormallite_item_pitch_mi + ' (40)', '40'],\n                                [Lang.template.technicnormallite_item_pitch_fa + ' (41)', '41'],\n                                [Lang.template.technicnormallite_item_pitch_fa_sharp + ' (42)', '42'],\n                                [Lang.template.technicnormallite_item_pitch_sol + ' (43)', '43'],\n                                [Lang.template.technicnormallite_item_pitch_sol_sharp + ' (44)', '44'],\n                                [Lang.template.technicnormallite_item_pitch_ra + ' (45)', '45'],\n                                [Lang.template.technicnormallite_item_pitch_ra_sharp + ' (46)', '46'],\n                                [Lang.template.technicnormallite_item_pitch_si + ' (47)', '47'],\n        \n                                [Lang.template.technicnormallite_item_pitch_do + ' (48)', '48'],\n                                [Lang.template.technicnormallite_item_pitch_do_sharp + ' (49)', '49'],\n                                [Lang.template.technicnormallite_item_pitch_re + ' (50)', '50'],\n                                [Lang.template.technicnormallite_item_pitch_re_sharp + ' (51)', '51'],\n                                [Lang.template.technicnormallite_item_pitch_mi + ' (52)', '52'],\n                                [Lang.template.technicnormallite_item_pitch_fa + ' (53)', '53'],\n                                [Lang.template.technicnormallite_item_pitch_fa_sharp + ' (54)', '54'],\n                                [Lang.template.technicnormallite_item_pitch_sol + ' (55)', '55'],\n                                [Lang.template.technicnormallite_item_pitch_sol_sharp + ' (56)', '56'],\n                                [Lang.template.technicnormallite_item_pitch_ra + ' (57)', '57'],\n                                [Lang.template.technicnormallite_item_pitch_ra_sharp + ' (58)', '58'],\n                                [Lang.template.technicnormallite_item_pitch_si + ' (59)', '59'],\n        \n                                [Lang.template.technicnormallite_item_pitch_do + ' (60)', '60'],\n                                [Lang.template.technicnormallite_item_pitch_do_sharp + ' (61)', '61'],\n                                [Lang.template.technicnormallite_item_pitch_re + ' (62)', '62'],\n                                [Lang.template.technicnormallite_item_pitch_re_sharp + ' (63)', '63'],\n                                [Lang.template.technicnormallite_item_pitch_mi + ' (64)', '64'],\n                                [Lang.template.technicnormallite_item_pitch_fa + ' (65)', '65'],\n                                [Lang.template.technicnormallite_item_pitch_fa_sharp + ' (66)', '66'],\n                                [Lang.template.technicnormallite_item_pitch_sol + ' (67)', '67'],\n                                [Lang.template.technicnormallite_item_pitch_sol_sharp + ' (68)', '68'],\n                                [Lang.template.technicnormallite_item_pitch_ra + ' (69)', '69'],\n                                [Lang.template.technicnormallite_item_pitch_ra_sharp + ' (70)', '70'],\n                                [Lang.template.technicnormallite_item_pitch_si + ' (71)', '71'],\n        \n                                [Lang.template.technicnormallite_item_pitch_do + ' (72)', '72'],\n                                [Lang.template.technicnormallite_item_pitch_do_sharp + ' (73)', '73'],\n                                [Lang.template.technicnormallite_item_pitch_re + ' (74)', '74'],\n                                [Lang.template.technicnormallite_item_pitch_re_sharp + ' (75)', '75'],\n                                [Lang.template.technicnormallite_item_pitch_mi + ' (76)', '76'],\n                                [Lang.template.technicnormallite_item_pitch_fa + ' (77)', '77'],\n                                [Lang.template.technicnormallite_item_pitch_fa_sharp + ' (78)', '78'],\n                                [Lang.template.technicnormallite_item_pitch_sol + ' (79)', '79'],\n                                [Lang.template.technicnormallite_item_pitch_sol_sharp + ' (80)', '80'],\n                                [Lang.template.technicnormallite_item_pitch_ra + ' (81)', '81'],\n                                [Lang.template.technicnormallite_item_pitch_ra_sharp + ' (82)', '82'],\n                                [Lang.template.technicnormallite_item_pitch_si + ' (83)', '83'],\n                            ],\n                            value: '60',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        const value = script.getStringField('PARAM0');\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_pitch_do + ' (36)', '36'],\n                                            [Lang.template.technicnormallite_item_pitch_do_sharp + ' (37)', '37'],\n                                            [Lang.template.technicnormallite_item_pitch_re + ' (38)', '38'],\n                                            [Lang.template.technicnormallite_item_pitch_re_sharp + ' (39)', '39'],\n                                            [Lang.template.technicnormallite_item_pitch_mi + ' (40)', '40'],\n                                            [Lang.template.technicnormallite_item_pitch_fa + ' (41)', '41'],\n                                            [Lang.template.technicnormallite_item_pitch_fa_sharp + ' (42)', '42'],\n                                            [Lang.template.technicnormallite_item_pitch_sol + ' (43)', '43'],\n                                            [Lang.template.technicnormallite_item_pitch_sol_sharp + ' (44)', '44'],\n                                            [Lang.template.technicnormallite_item_pitch_ra + ' (45)', '45'],\n                                            [Lang.template.technicnormallite_item_pitch_ra_sharp + ' (46)', '46'],\n                                            [Lang.template.technicnormallite_item_pitch_si + ' (47)', '47'],\n                    \n                                            [Lang.template.technicnormallite_item_pitch_do + ' (48)', '48'],\n                                            [Lang.template.technicnormallite_item_pitch_do_sharp + ' (49)', '49'],\n                                            [Lang.template.technicnormallite_item_pitch_re + ' (50)', '50'],\n                                            [Lang.template.technicnormallite_item_pitch_re_sharp + ' (51)', '51'],\n                                            [Lang.template.technicnormallite_item_pitch_mi + ' (52)', '52'],\n                                            [Lang.template.technicnormallite_item_pitch_fa + ' (53)', '53'],\n                                            [Lang.template.technicnormallite_item_pitch_fa_sharp + ' (54)', '54'],\n                                            [Lang.template.technicnormallite_item_pitch_sol + ' (55)', '55'],\n                                            [Lang.template.technicnormallite_item_pitch_sol_sharp + ' (56)', '56'],\n                                            [Lang.template.technicnormallite_item_pitch_ra + ' (57)', '57'],\n                                            [Lang.template.technicnormallite_item_pitch_ra_sharp + ' (58)', '58'],\n                                            [Lang.template.technicnormallite_item_pitch_si + ' (59)', '59'],\n                    \n                                            [Lang.template.technicnormallite_item_pitch_do + ' (60)', '60'],\n                                            [Lang.template.technicnormallite_item_pitch_do_sharp + ' (61)', '61'],\n                                            [Lang.template.technicnormallite_item_pitch_re + ' (62)', '62'],\n                                            [Lang.template.technicnormallite_item_pitch_re_sharp + ' (63)', '63'],\n                                            [Lang.template.technicnormallite_item_pitch_mi + ' (64)', '64'],\n                                            [Lang.template.technicnormallite_item_pitch_fa + ' (65)', '65'],\n                                            [Lang.template.technicnormallite_item_pitch_fa_sharp + ' (66)', '66'],\n                                            [Lang.template.technicnormallite_item_pitch_sol + ' (67)', '67'],\n                                            [Lang.template.technicnormallite_item_pitch_sol_sharp + ' (68)', '68'],\n                                            [Lang.template.technicnormallite_item_pitch_ra + ' (69)', '69'],\n                                            [Lang.template.technicnormallite_item_pitch_ra_sharp + ' (70)', '70'],\n                                            [Lang.template.technicnormallite_item_pitch_si + ' (71)', '71'],\n                    \n                                            [Lang.template.technicnormallite_item_pitch_do + ' (72)', '72'],\n                                            [Lang.template.technicnormallite_item_pitch_do_sharp + ' (73)', '73'],\n                                            [Lang.template.technicnormallite_item_pitch_re + ' (74)', '74'],\n                                            [Lang.template.technicnormallite_item_pitch_re_sharp + ' (75)', '75'],\n                                            [Lang.template.technicnormallite_item_pitch_mi + ' (76)', '76'],\n                                            [Lang.template.technicnormallite_item_pitch_fa + ' (77)', '77'],\n                                            [Lang.template.technicnormallite_item_pitch_fa_sharp + ' (78)', '78'],\n                                            [Lang.template.technicnormallite_item_pitch_sol + ' (79)', '79'],\n                                            [Lang.template.technicnormallite_item_pitch_sol_sharp + ' (80)', '80'],\n                                            [Lang.template.technicnormallite_item_pitch_ra + ' (81)', '81'],\n                                            [Lang.template.technicnormallite_item_pitch_ra_sharp + ' (82)', '82'],\n                                            [Lang.template.technicnormallite_item_pitch_si + ' (83)', '83'],\n                                        ],\n                                        value: '60',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_pitch_key',\n                            },\n                        ],\n                    },\n                },\n                technicnormallite_dropdown_melody_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicnormallite_item_melody_start, '1'],\n                                [Lang.template.technicnormallite_item_melody_end, '2'],\n                                [Lang.template.technicnormallite_item_melody_level_up, '3'],\n                                [Lang.template.technicnormallite_item_melody_level_down, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicnormallite_item_melody_start, '1'],\n                                            [Lang.template.technicnormallite_item_melody_end, '2'],\n                                            [Lang.template.technicnormallite_item_melody_level_up, '3'],\n                                            [Lang.template.technicnormallite_item_melody_level_down, '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicnormallite_dropdown_melody_key',\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Event block\n                ///========================================================================================                \n                // %1 리모컨 %2 키를 눌렀을 때\n                technicnormallite_when_press_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: {\n                                x: 0,\n                                y: -2,\n                            },\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'technicnormallite_dropdown_remote_key',\n                            },\n                        ],\n                        type: 'technicnormallite_when_press_remote_key',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_event',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    event: 'technicnormallite_event_remote_input',\n                    func(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getRemoteKey(script.getStringValue('PARAM1'));\n                        return (Entry.ProboTechnicNormalLite.InputData.Remote[key] === 1)\n                            ? script.callReturn()\n                            : this.die();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.when_press_remote_key(%2)',\n                                blockType: 'event',\n                                passTest: true,\n                                textParams: [\n                                    undefined,\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 디지털 입력 %2 이(가) 들어왔을 때\n                technicnormallite_when_input_digital_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: {\n                                x: 0,\n                                y: -2,\n                            },\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'technicnormallite_dropdown_digital_key',\n                            },\n                        ],\n                        type: 'technicnormallite_when_input_digital_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_event',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    event: 'technicnormallite_event_digital_input',\n                    func(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getDigitalKey(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboTechnicNormalLite.getDigitalStateValue(key);\n                        return (value)\n                            ? script.callReturn()\n                            : this.die();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.when_input_digital_value(%2)',\n                                blockType: 'event',\n                                passTest: true,\n                                textParams: [\n                                    undefined,\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Setting Block\n                ///========================================================================================               \n                // 입력포트 %1 을(를) %2 센서로 설정 %3\n                technicnormallite_set_senser_setting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_setting_sensor_key',\n                            },\n                            null,\n                        ],\n                        type: 'technicnormallite_set_senser_setting',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_setting',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicNormalLite.getSettingSensorValue(script.getStringValue('PARAM1'));\n                        const sensorSet = Entry.ProboTechnicNormalLite.SenserSet;\n                        sensorSet[key] = value;\n                        Entry.ProboTechnicNormalLite.RemoteData.ASET2 = ((sensorSet.AA1 << 4) | sensorSet.AA2) & 0xFF;\n                        Entry.ProboTechnicNormalLite.RemoteData.ASET1 = ((sensorSet.AA3 << 4) | sensorSet.AA4) & 0xFF;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_sensor_setting(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Input block\n                ///========================================================================================\n                // 리모컨 입력 %1\n                technicnormallite_is_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_remote_key',\n                            },\n                        ],\n                        type: 'technicnormallite_is_remote_key',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getRemoteKey(script.getStringValue('PARAM0'));\n                        return (Entry.ProboTechnicNormalLite.InputData.Remote[key] === 1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.is_remote_key(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 디지털 입력 %1\n                technicnormallite_is_digital_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_digital_key',\n                            },\n                        ],\n                        type: 'technicnormallite_is_digital_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getDigitalKey(script.getStringValue('PARAM0'));\n                        return Entry.ProboTechnicNormalLite.getDigitalStateValue(key);;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.is_digital_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 아날로그 입력 %1\n                technicnormallite_get_analog_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicnormallite_get_analog_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        return  (Entry.ProboTechnicNormalLite.SenserSet[key] === 5)  // 5: 압력\n                            ? 255 - Entry.ProboTechnicNormalLite.InputData.Analog[key]\n                            : Entry.ProboTechnicNormalLite.InputData.Analog[key];\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_analog_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 3가속도 %1의 X축\n                technicnormallite_get_tri_axis_acceler_x: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicnormallite_get_tri_axis_acceler_x',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAxisKey(script.getStringValue('PARAM0'), \"X\");\n                        const value = Entry.ProboTechnicNormalLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_tri_axis_acceler_x(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },                        \n                // 3가속도 %1의 Y축\n                technicnormallite_get_tri_axis_acceler_y: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicnormallite_get_tri_axis_acceler_y',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAxisKey(script.getStringValue('PARAM0'),\"Y\");\n                        const value = Entry.ProboTechnicNormalLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_tri_axis_acceler_y(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 3가속도 %1의 Z축\n                technicnormallite_get_tri_axis_acceler_z: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicnormallite_get_tri_axis_acceler_z',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAxisKey(script.getStringValue('PARAM0'), \"Z\");\n                        const value = Entry.ProboTechnicNormalLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_tri_axis_acceler_z(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                \n                // %1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환\n                technicnormallite_get_value_mapping: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 255 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 100 ],\n                            },\n                        ],\n                        type: 'technicnormallite_get_value_mapping',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                        PARAM2: 2,\n                        PARAM3: 3,\n                        PARAM4: 4,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const inMin = script.getNumberValue('PARAM1');\n                        const inMax = script.getNumberValue('PARAM2');\n                        const outMin = script.getNumberValue('PARAM3');\n                        const outMax = script.getNumberValue('PARAM4');\n                        const data = (Entry.ProboTechnicNormalLite.SenserSet[key] === 5) // 5: 압력\n                            ? 255 - Entry.ProboTechnicNormalLite.InputData.Analog[key]\n                            : Entry.ProboTechnicNormalLite.InputData.Analog[key];\n                        return (data - inMin) * (outMax-outMin) / (inMax - inMin) + outMin;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_value_mapping(%1, %2, %3, %4, %5)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },                \n                // 컬러 센서 %1 이(가) %2 인가?\n                technicnormallite_is_color_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_sensor_color_key',\n                            },\n                        ],\n                        type: 'technicnormallite_is_color_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const key1 = Entry.ProboTechnicNormalLite.getColorSensorKey(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboTechnicNormalLite.InputData.Analog[key0];\n                        const color = Entry.ProboTechnicNormalLite.Color;\n                        return ((color[key1].Min <= value) && (value <= color[key1].Max));\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.is_color_value(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 컬러 센서 %1 의 색상\n                technicnormallite_get_color_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [                    \n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicnormallite_get_color_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicNormalLite.InputData.Analog[key0];\n                        const color = Entry.ProboTechnicNormalLite.Color;\n                        \n                        for (let i = 1; i < 7; i++) {\n                            const key1 =  Entry.ProboTechnicNormalLite.getColorSensorKey(i.toString());\n                            if ((color[key1].Min <= value) && (value <= color[key1].Max)) {\n                                switch (i) {\n                                    case 1:\n                                        return Lang.template.technicnormallite_item_color_red;\n                                    case 2:\n                                        return Lang.template.technicnormallite_item_color_green;\n                                    case 3:\n                                        return Lang.template.technicnormallite_item_color_blue;\n                                    case 4:\n                                        return Lang.template.technicnormallite_item_color_yellow;\n                                    case 5:\n                                        return Lang.template.technicnormallite_item_color_black;\n                                    case 6:\n                                        return Lang.template.technicnormallite_item_color_white;\n                                    default:\n                                        return Lang.template.technicnormallite_item_error;\n                                }\n                            }\n                        }\n\n                        return Lang.template.technicnormallite_item_nothing;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_color_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 을 %3 값으로 정하기 %4\n                technicnormallite_set_infinite_setting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        }\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_set_infinite_setting',\n                    },\n                    paramsKeyMap: {\n                        //PARAM0: 0, // 0을 쓰지 않음\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        let count = 0;\n                        let value = script.getNumberValue('PARAM2');\n                        \n                        if (value != 0) {\n                            count = Math.floor(value / 255);\n                            value = value % 255;\n                        } else {\n                            count = 0;\n                            value = 0;\n                        }\n                        \n                        Entry.ProboTechnicNormalLite.Infinite.Buff[key] = Entry.ProboTechnicNormalLite.InputData.Analog[key];\n                        Entry.ProboTechnicNormalLite.Infinite.Start[key] = Entry.ProboTechnicNormalLite.InputData.Analog[key] - value;\n                        Entry.ProboTechnicNormalLite.Infinite.Count[key] = count;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_infinite_setting(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 지름 %3 의 mm 값\n                technicnormallite_get_infinite_mm_diameter: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 53.5 ],\n                            },\n                        ],\n                        type: 'technicnormallite_get_infinite_mm_diameter',\n                    },\n                    paramsKeyMap: {\n                        //PARAM0: 0, // 0을 쓰지 않음\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        const radius = script.getNumberValue('PARAM2') / 2;\n                        const pi = 3.141592;\n                        const infinite = Entry.ProboTechnicNormalLite.Infinite;\n                        let value = Entry.ProboTechnicNormalLite.InputData.Analog[key];\n\n                        if (value < infinite.Buff[key] - 150) {\n                            infinite.Count[key]++;\n                        } else if (value > infinite.Buff[key] + 150) {\n                            infinite.Count[key]--;\n                        }                    \n                        infinite.Buff[key] = value;\n                        value = (infinite.Buff[key] - infinite.Start[key]) + (infinite.Count[key] * 255);\n\n                        return Number((2 * pi * radius) / 255 * value).toFixed(3);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_infinite_mm_diameter(%1, %2, %3)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 의  %3\n                technicnormallite_get_infinite_transform_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [                    \n                            {\n                                type: 'technicnormallite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_sensor_angle_key',\n                            },\n                        ],\n                        type: 'technicnormallite_get_infinite_transform_input',\n                    },\n                    paramsKeyMap: {\n                        //PARAM0: 0, // 0을 쓰지 않음\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key1 = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        const key2 = Entry.ProboTechnicNormalLite.getSensorAngleKey(script.getStringValue('PARAM2'));\n                        const anlogValue = Entry.ProboTechnicNormalLite.InputData.Analog[key1];\n                        const infinite = Entry.ProboTechnicNormalLite.Infinite;\n\n                        if (anlogValue < (infinite.Buff[key1] - 150)) {\n                            infinite.Count[key1]++;\n                        } else if (anlogValue > (infinite.Buff[key1] + 150)) {\n                            infinite.Count[key1]--;\n                        }\n                        infinite.Buff[key1] = anlogValue;\n                        const value = (infinite.Buff[key1] - infinite.Start[key1]) + (infinite.Count[key1] * 255);\n\n                        switch (key2) {\n                            case 'IS1':\n                                return value;\n                            case 'IS2':\n                                return (value > 0)\n                                    ? Math.floor((value % 255) * 1.41732)\n                                    : Math.ceil((value % 255) * 1.41732)\n                            case 'IS3':\n                                return Number((360 / 255) * anlogValue).toFixed(0);\n                            case 'IS4':\n                                return (value > 0)\n                                    ? Math.floor(value / 255)\n                                    : Math.ceil(value / 255);\n                            default:\n                                return Lang.template.technicnormallite_item_nothing;\n\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_infinite_transform_input(%1, %2, %3)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 멀티키 센서 %1의 %2\n                technicnormallite_is_multi_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_multikey_key',\n                            },\n                        ],\n                        type: 'technicnormallite_is_multi_sensor',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicNormalLite.getMultiKeyValue(script.getStringValue('PARAM1'));\n                        return (Entry.ProboTechnicNormalLite.InputData.Analog[key] >> value) & 0x01;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.is_multi_sensor(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 분배 스위치 %1의 %2\n                technicnormallite_is_multi_switch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_multikey_key',\n                            },\n                        ],\n                        type: 'technicnormallite_is_multi_switch',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboTechnicNormalLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicNormalLite.getMultiKeyValue(script.getStringValue('PARAM1'));\n                        const analog = Entry.ProboTechnicNormalLite.InputData.Analog[key0];\n                        const multySwitch = Entry.ProboTechnicNormalLite.MultiSwitch;\n                        \n                        for (let i = 0; i < 8; i++) {\n                            const key = 'Key' + (i + 1).toString();\n                            if (multySwitch[key].Min <= analog && analog <= multySwitch[key].Max) {\n                                return (value === i);\n                            }\n                        }\n                        \n                        return false;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.is_multi_switch(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 확장 디지털 입력 %1 의 %2\n                technicnormallite_is_extension_digital_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_extension_digital_key',\n                            },\n                        ],\n                        type: 'technicnormallite_is_extension_digital_input',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getAxisKey(script.getStringValue('PARAM0'), 'X');\n                        const shift = Entry.ProboTechnicNormalLite.getExtentionDigitalValue(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboTechnicNormalLite.InputData.Acceler[key];\n                        return ((value >> shift) === 1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.is_extension_digital_input(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },                \n                // 확장 아날로그 입력 %1 의 %2\n                technicnormallite_get_extension_analog_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicnormallite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_extension_analog_key',\n                            },\n                        ],\n                        type: 'technicnormallite_get_extension_analog_input',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {                        \n                        const key = Entry.ProboTechnicNormalLite.getAxisKey(\n                            script.getStringValue('PARAM0'),\n                            Entry.ProboTechnicNormalLite.getExtentionAnalogKey(script.getStringValue('PARAM1'))\n                        );\n                        const value = Entry.ProboTechnicNormalLite.InputData.Acceler[key];\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_extension_analog_input(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM %1 주소의 값 호출하기 %2\n                technicnormallite_set_eeprom_call: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',                    \n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0']\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_set_eeprom_call',\n                    },\n                    paramsKeyMap: {\n                        ADDRESS: 0,\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const address = script.getNumberValue('ADDRESS', script);\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const ms = 50;\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboTechnicNormalLite.EEPROM.Count = Entry.ProboTechnicNormalLite.InputData.EEPROM.EC;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR4'] = 0x40;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR3'] = address;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicNormalLite.EEPROM.Buff =\n                                (Entry.ProboTechnicNormalLite.InputData.EEPROM.EEPR2 << 8) + \n                                Entry.ProboTechnicNormalLite.InputData.EEPROM.EEPR1;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR4'] = 0;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR3'] = 0;\n\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_eeprom_call(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM 주소의 값\n                technicnormallite_get_eeprom_address_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'technicnormallite_get_eeprom_address_value',\n                    },\n                    class: 'technicnormallite_input',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const count = Entry.ProboTechnicNormalLite.EEPROM.Count;\n\n                        return (Entry.ProboTechnicNormalLite.InputData.EEPROM.EC != count)\n                            ? Entry.ProboTechnicNormalLite.EEPROM.Buff\n                            : 0;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.get_eeprom_address_value',\n                                blockType: 'param',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n                \n                ///========================================================================================\n                /// output block\n                ///========================================================================================\n                // DC 모터 %1 을(를) %2 속도로 회전 %3\n                technicnormallite_set_dc_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_dc_1_all_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_velocity_key',\n                            },\n                            null,\n                        ],\n                        type: 'technicnormallite_set_dc_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getDckey(script.getStringValue('PARAM0')); \n                        const value = script.getNumberValue('PARAM1');\n\n                        switch (key) {\n                            case 'DC5':\n                                Entry.ProboTechnicNormalLite.RemoteData['DC1'] = value;\n                                Entry.ProboTechnicNormalLite.RemoteData['DC2'] = value;\n                                break;\n                            case 'DC6':\n                                Entry.ProboTechnicNormalLite.RemoteData['DC3'] = value;\n                                Entry.ProboTechnicNormalLite.RemoteData['DC4'] = value;\n                                break;\n                            case 'DC7':\n                                Entry.ProboTechnicNormalLite.RemoteData['DC1'] = value;\n                                Entry.ProboTechnicNormalLite.RemoteData['DC2'] = value;\n                                Entry.ProboTechnicNormalLite.RemoteData['DC3'] = value;\n                                Entry.ProboTechnicNormalLite.RemoteData['DC4'] = value;\n                                break;\n                            default:\n                                Entry.ProboTechnicNormalLite.RemoteData[key] = value;\n                                break;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_dc_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 서보 모터 %1 의 위치를 %2 로 이동 %3\n                technicnormallite_set_servo_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_servo_position_key',\n                            },\n                            null,\n                        ],\n                        type: 'technicnormallite_set_servo_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = script.getNumberValue('PARAM1');\n                        Entry.ProboTechnicNormalLite.RemoteData[key] = Math.min(Math.max(value, 0), 100);\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_servo_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // S 모터 %1 을(를) %2 속도로 회전 %3\n                technicnormallite_set_s_dc_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_velocity_key',\n                            },\n                            null,\n                        ],\n                        type: 'technicnormallite_set_s_dc_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getServoKey(script.getStringValue('PARAM0'));\n                        const speed = script.getNumberValue('PARAM1');\n                        const value = Math.min(Math.max(speed, -20), 20) + 148;\n\n                        switch (key) {\n                            case 'Servo5':\n                                Entry.ProboTechnicNormalLite.RemoteData['Servo1'] = value;\n                                Entry.ProboTechnicNormalLite.RemoteData['Servo2'] = value;\n                                break;\n                            case 'Servo6':\n                                Entry.ProboTechnicNormalLite.RemoteData['Servo3'] = value;\n                                Entry.ProboTechnicNormalLite.RemoteData['Servo4'] = value;\n                                break;\n                            default:\n                                Entry.ProboTechnicNormalLite.RemoteData[key] = value;\n                                break;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_s_dc_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 출력핀 %1 을(를) %2 %3\n                technicnormallite_set_port_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_on_off_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_set_port_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getPortKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicNormalLite.getPortToggleValue(script.getStringValue('PARAM1'));\n        \n                        Entry.ProboTechnicNormalLite.RemoteData[key] = value;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_port_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2 음표로 연주하기 %3\n                technicnormallite_play_melody_note_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_pitch_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_note_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_play_melody_note_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            const pitch = Entry.ProboTechnicNormalLite.getPitchValue(script.getNumberValue('PARAM0'));\n                            const note = Entry.ProboTechnicNormalLite.getNoteKey(script.getStringValue('PARAM1'));\n                            const ms = Entry.ProboTechnicNormalLite.Note[note];\n                            const fps = Entry.FPS || 60;\n        \n                            Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = pitch >> 8;\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = pitch;        \n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = 0;\n        \n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.play_melody_note_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2 초 동안 연주하기 %3\n                technicnormallite_play_melody_sec_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_pitch_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_time_1_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_play_melody_sec_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            const pitch = Entry.ProboTechnicNormalLite.getPitchValue(script.getNumberValue('PARAM0'));\n                            const sec = script.getNumberValue('PARAM1');        \n                            const fps = Entry.FPS || 60;\n                           \n                            Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = pitch >> 8;\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = pitch;        \n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = 0;\n        \n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.play_melody_sec_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) 연주하기 %2\n                technicnormallite_play_melody_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [                \n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_pitch_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_play_melody_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const pitch = Entry.ProboTechnicNormalLite.getPitchValue(script.getNumberValue('PARAM0'));        \n                        Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = pitch >> 8;\n                        Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = pitch;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.play_melody_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 값을(를) %2 초 동안 연주하기 %3\n                technicnormallite_play_value_sec_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 35391 ],\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_time_1_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_play_value_sec_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n        \n                            const melody = script.getNumberValue('PARAM0');\n                            const sec = script.getNumberValue('PARAM1');\n                            const fps = Entry.FPS || 60;\n        \n                            Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = melody & 0xff;        \n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = 0;\n        \n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.play_melody_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 1 값을(를) 연주하기 %2\n                technicnormallite_play_value_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 35391 ],\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_play_value_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const melody = script.getNumberValue('PARAM0');\n                        Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                        Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = melody & 0xff;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.play_melody_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2초 간격으로 재생하기 %3\n                technicnormallite_play_melody_track_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_melody_key',\n                            },\n                            { \n                                type: 'technicnormallite_dropdown_time_2_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_play_melody_track_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        function getTrackStep(track,script){\n                            if(!script.isStart){\n                                script.isStart = true;\n                                script.trackStep = 0;\n                            }\n                            else {\n                                script.trackStep++;\n                            }\n                            const sec = script.getNumberValue('PARAM1');\n                            const fps = Entry.FPS || 60;\n                            const melody = Entry.ProboTechnicNormalLite.Track[track][script.trackStep];\n\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = melody & 0xff;        \n                            script.timeFlag = 1;        \n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n                        }\n                        const TR = Entry.ProboTechnicNormalLite.getMelodyValue(\n                            script.getStringValue('PARAM0')\n                        );\n                        if (!script.isStart) {\n                            switch(TR) {\n                                case 0 :\n                                    script.maxStep = 6;\n                                    break;\n                                case 1 :\n                                    script.maxStep = 7;\n                                    break;\n                                case 2 :\n                                    script.maxStep = 3;\n                                    break;\n                                case 3 :\n                                    script.maxStep = 3;\n                                    break;\n                            }\n                            getTrackStep(TR,script);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else if (script.trackStep < script.maxStep){\n                            getTrackStep(TR,script);\n                            return script;\n                        } else {\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = 0;\n        \n                            delete script.trackStep;\n                            delete script.maxStep;\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.play_melody_track_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 멜로디 중지 %1\n                technicnormallite_play_melody_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                        type: 'technicnormallite_play_melody_off',\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        Entry.ProboTechnicNormalLite.RemoteData['MEL2'] = 0;\n                        Entry.ProboTechnicNormalLite.RemoteData['MEL1'] = 0;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.play_melody_track_output',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 을(를) %2 으로 켜기 %3\n                technicnormallite_set_rgbled_on_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'technicnormallite_dropdown_rgb_color_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_set_rgbled_on_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicNormalLite.getRgbToggleValue(script.getStringValue('PARAM1'));\n                        Entry.ProboTechnicNormalLite.RemoteData[key] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_rgbled_on_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },    \n                // RGB LED %1 을(를) 끄기 %2\n                technicnormallite_set_rgbled_off_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_port_1_4_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_set_rgbled_off_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicNormalLite.getRgbToggleValue('0');\n                        Entry.ProboTechnicNormalLite.RemoteData[key] = value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_rgbled_off_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 %2 으로 %3 초 간격 %4\n                technicnormallite_set_rgbled_flashing_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_port_1_4_key',\n                            },\n                            { \n                                type: 'technicnormallite_dropdown_rgb_color_key',\n                            },\n                            { \n                                type: 'technicnormallite_dropdown_time_3',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_set_rgbled_flashing_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicNormalLite.getRgbTwinkleValue(\n                            script.getStringValue('PARAM1'),\n                            script.getNumberValue('PARAM2')\n                        );\n                        Entry.ProboTechnicNormalLite.RemoteData[key] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_rgbled_flashing_output(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 을(를) %2 으로 디밍 %3\n                technicnormallite_set_rgbled_dimming_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicnormallite_dropdown_port_1_4_key',\n                            },\n                            { \n                                type: 'technicnormallite_dropdown_rgb_color_key',\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_set_rgbled_dimming_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicNormalLite.getServoKey(script.getStringValue('PARAM0'));\n                        const color = Entry.ProboTechnicNormalLite.getRgbDimmingValue(script.getStringValue('PARAM1'));\n                        Entry.ProboTechnicNormalLite.RemoteData[key] = color;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_rgbled_dimming_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // FND를 %1 (으)로 설정 %2\n                technicnormallite_set_fnd_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            null\n                        ],\n                        type: 'technicnormallite_set_fnd_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const value = script.getNumberValue('PARAM0');\n                        Entry.ProboTechnicNormalLite.RemoteData['FND'] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_fnd_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // FND 끄기 %1\n                technicnormallite_set_fnd_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                        type: 'technicnormallite_set_fnd_off',\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        Entry.ProboTechnicNormalLite.RemoteData['FND'] = 100;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_fnd_off',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM %1 주소에 %2 값 설정하기 %3\n                technicnormallite_set_eeprom_write: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',                    \n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'number',\n                                params: [ 0 ]\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ]\n                            },\n                            null,\n                        ],\n                        type: 'technicnormallite_set_eeprom_write',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicnormallite_output',\n                    isNotFor: ['ProboTechnicNormalLite'],\n                    func: function(sprite, script) {\n                        const address = script.getNumberValue('PARAM0');\n                        const value = script.getNumberValue('PARAM1');\n\n                        if (!script.isStart) {        \n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const ms = 50;\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR4'] = 0x80;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR3'] = address;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR2'] = (value >> 8) & 0xff;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR1'] = value & 0xff;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR4'] = 0x40;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR3'] = address;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR2'] = 0;\n                            Entry.ProboTechnicNormalLite.RemoteData['EEPR1'] = 0;\n        \n                            setTimeout(function() {\n                                Entry.ProboTechnicNormalLite.RemoteData['EEPR4'] = 0;\n                                Entry.ProboTechnicNormalLite.RemoteData['EEPR3'] = 0;\n                                Entry.ProboTechnicNormalLite.RemoteData['EEPR2'] = 0;\n                                Entry.ProboTechnicNormalLite.RemoteData['EEPR1'] = 0;\n                            }, 100);\n                            \n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicNormalLite.set_eeprom_write(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n            }; // getBlock() return;\n        }\n    })();\n})();\n\nmodule.exports = Entry.ProboTechnicNormalLite;"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_alux_teachnic_power_lite.js",
    "content": "'use strict';\n\nconst _throttle = require('lodash/throttle');\n\n(function() {\n    const TECHNIC_POWER_INDEX = 0x22; //34\n    const RELEASE_VERSION = 4;\n    const SERIAL_INTERVAL = 32;\n    const EVENT_INTERVAL = 16;\n    const SEND_PACKET_LENGTH = 22;\n    const RECEIVED_PACKET_LENGTH = 17;\n    Entry.ProboTechnicPowerLite = new (class ProboTechnicPowerLite  {\n        constructor()  {\n            this.id = '630201';\n            this.name = 'ProboTechnicPowerLite';\n            this.url = 'https://imssam.me';\n            this.imageName = 'alux_technic_power_lite.png';\n            this.title = {\n                ko: '프로보 테크닉(파워)',\n                en: 'Probo Technic(Power)',\n            };\n            this.portData = {\n                baudRate: 115200,\n                duration: this.SERIAL_INTERVAL,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 128,\n                connectionType: 'bytestream',\n                constantServing: 'ReadOnly',\n            };\n\n            this.Color = {\n                Red: {\n                    Min: 13,\n                    Max: 37\n                },\n                Green: {\n                    Min: 38,\n                    Max: 62\n                },\n                Blue: {\n                    Min: 63,\n                    Max: 87\n                },\n                Yellow: {\n                    Min: 88,\n                    Max: 112\n                },\n                Black: {\n                    Min: 113,\n                    Max: 137\n                },\n                White: {\n                    Min: 138,\n                    Max: 162\n                },\n            };\n            this.MultiSwitch = {\n                Key1: {\n                    Min: 1,\n                    Max: 19\n                },\n                Key2: {\n                    Min: 26,\n                    Max: 44\n                },\n                Key3: {\n                    Min: 53,\n                    Max: 77\n                },\n                Key4: {\n                    Min: 83,\n                    Max: 101\n                },\n                Key5: {\n                    Min: 107,\n                    Max: 125\n                },\n                Key6: {\n                    Min: 139,\n                    Max: 157\n                },\n                Key7: {\n                    Min: 160,\n                    Max: 178\n                },\n                Key8: {\n                    Min: 191,\n                    Max: 209\n                }\n            };\n            this.Note = {\n                n32:  48,   // = 1*3*4*4,\n                n16:  96,   // = 2*3*4*4,\n                n16d: 144,  // = 3*3*4*4,\n                n16t: 64,   // = 2*2*4*4,\n                n8:   192,  // = 4*3*4*4,\n                n8d:  288,  // = 6*3*4*4,\n                n8t:  128,  // = 4*2*4*4,\n                n4:   384,  // = 8*3*4*4,\n                n4d:  576,  // = 12*3*4*4,\n                n4t:  256,  // = 8*2*4*4,\n                n2:   768,  // = 16*3*4*4,\n                n2d:  1152, // = 24*3*4*4,\n                n2t:  512,  // = 16*2*4*4,\n                n1:   1536, // = 32*3*4*4\n            };\n            this.Rgb = {\n                Off: 0,\n                On: {\n                    Red :    1,\n                    Yellow:  12,\n                    Green :  23,\n                    Cyan :   34,\n                    Blue:    45,\n                    Magenta: 56,\n                    White:   67\n                },\n                Dimming: {\n                    Red:     90,\n                    Yellow:  91,\n                    Green:   92,\n                    Cyan:    93,\n                    Blue:    94,\n                    Magenta: 95,\n                    White:   96\n                }\n            };\n            this.Melody = [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748];\n            this.Track = [\n                [0x451F, 0x3D95, 0x36DD, 0x33C8, 0x2E22, 0x291A, 0x249E], // Start : size 7,\n                [0x228F, 0x249E, 0x291A, 0x2E22, 0x33C8, 0x36DD, 0x3D95, 0x451F], // End : size 8,\n                [0x228F, 0x1B6E, 0x1711, 0x1147 ], // LevelUp : size 4,\n                [0x1147, 0x1711, 0x1B6E, 0x228F ], // LevelDwon : size 4,\n            ];\n\n            const eventSetting = {\n                leading: true,\n                trailing: false\n            }\n            this.remoteEvent = _throttle(\n                () => {\n                    const prevFlag = this.sendFlag;\n                    try {\n                        Entry.engine.fireEvent('technicpowerlite_event_remote_input');\n                    } catch (e) {\n                    } finally {\n                        this.sendFlag = prevFlag;\n                    }\n                },\n                EVENT_INTERVAL,\n                eventSetting\n            );\n            this.digitalEvent = _throttle(\n                () => {\n                    const prevFlag = this.sendFlag;\n                    try {\n                        Entry.engine.fireEvent('technicpowerlite_event_digital_input');\n                    } catch (e) {\n                    } finally {\n                        this.sendFlag = prevFlag;\n                    }\n                }\n                ,\n                EVENT_INTERVAL,\n                eventSetting\n            );\n\n            this.qRear = 0;\n            this.qFront = 0;\n            this.qSize = 128;\n            this.qBuffer = new Uint8Array(this.qSize + 2).fill(-1);            \n            this.inputPacket = new Uint8Array(RECEIVED_PACKET_LENGTH).fill(-1);\n            this.pLength = 0; // packet length\n            this.process = false; // packet process\n\n            this.version = 0;\n            this.sendFlag = true;            \n\n            this.blockMenuBlocks = [\n                //dropdown\n                'technicpowerlite_dropdown_remote_key',\n                'technicpowerlite_dropdown_digital_key',\n                'technicpowerlite_dropdown_analog_key',\n                'technicpowerlite_dropdown_setting_sensor_key',\n                'technicpowerlite_dropdown_inNcom_sensor_key',\n                'technicpowerlite_dropdown_sensor_color_key',\n                'technicpowerlite_dropdown_rgb_color_key',\n                'technicpowerlite_dropdown_sensor_angle_key',\n                'technicpowerlite_dropdown_multikey_key',\n                'technicpowerlite_dropdown_extension_digital_key',\n                'technicpowerlite_dropdown_extension_analog_key',\n                'technicpowerlite_dropdown_dc_1_all_key',\n                'technicpowerlite_dropdown_port_1_4_key',\n                'technicpowerlite_dropdown_on_off_key',\n                'technicpowerlite_dropdown_velocity_key',\n                'technicpowerlite_dropdown_servo_position_key',\n                'technicpowerlite_dropdown_note_key',\n                'technicpowerlite_dropdown_time_1_key',\n                'technicpowerlite_dropdown_time_2_key',\n                'technicpowerlite_dropdown_time_3',\n                'technicpowerlite_dropdown_pitch_key',\n                'technicpowerlite_dropdown_melody_key',\n\n                //event\n                'technicpowerlite_when_press_remote_key',\n                'technicpowerlite_when_input_digital_value',\n\n                //setting\n                'technicpowerlite_set_senser_setting',\n\n                //input\n                'technicpowerlite_is_remote_key',\n                'technicpowerlite_is_digital_value',\n                'technicpowerlite_is_extension_digital_input',\n                'technicpowerlite_get_analog_value',\n                'technicpowerlite_get_extension_analog_input',\n                // 'technicpowerlite_get_tri_axis_acceler_x', // 테크닉 에서 사용하지 않음\n                // 'technicpowerlite_get_tri_axis_acceler_y', // 테크닉 에서 사용하지 않음\n                // 'technicpowerlite_get_tri_axis_acceler_z', // 테크닉 에서 사용하지 않음\n                'technicpowerlite_get_value_mapping',\n                'technicpowerlite_is_color_value',\n                'technicpowerlite_get_color_value',\n                'technicpowerlite_set_infinite_setting',\n                'technicpowerlite_get_infinite_mm_diameter',\n                'technicpowerlite_get_infinite_transform_input',\n                // 'technicpowerlite_is_multi_sensor', // 테크닉 에서 사용하지 않음\n                // 'technicpowerlite_is_multi_switch', // 테크닉 에서 사용하지 않음\n                'technicpowerlite_set_eeprom_call',\n                'technicpowerlite_get_eeprom_address_value',\n\n                //output\n                'technicpowerlite_set_dc_output',\n                'technicpowerlite_set_servo_output',\n                // 'technicpowerlite_set_s_dc_output', // 테크닉 에서 사용하지 않음\n                'technicpowerlite_set_port_output',\n                'technicpowerlite_play_melody_note_output',\n                'technicpowerlite_play_melody_sec_output',\n                'technicpowerlite_play_melody_output',\n                'technicpowerlite_play_value_sec_output',\n                'technicpowerlite_play_value_output',    \n                'technicpowerlite_play_melody_track_output',\n                'technicpowerlite_play_melody_off',\n                'technicpowerlite_set_rgbled_on_output',\n                'technicpowerlite_set_rgbled_off_output',\n                'technicpowerlite_set_rgbled_flashing_output',\n                'technicpowerlite_set_rgbled_dimming_output',\n                // 'technicpowerlite_set_fnd_output', // 테크닉 에서 사용하지 않음\n                // 'technicpowerlite_set_fnd_off',    // 테크닉 에서 사용하지 않음\n\n                //EEPROM\n                'technicpowerlite_set_eeprom_write',\n            ];\n        }        \n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        technicpowerlite_item_switch: '스위치',\n                        technicpowerlite_item_infrared: '적외선',\n                        technicpowerlite_item_magnetic: '자석',\n                        technicpowerlite_item_rotation: '회전',\n                        technicpowerlite_item_color: '컬러',\n                        technicpowerlite_item_acceleration: '가속도',\n                        technicpowerlite_item_ultrasonic: '초음파',\n                        technicpowerlite_item_heart_rate: '심박',\n                        technicpowerlite_item_illuminance: '조도',\n                        technicpowerlite_item_temperature: '온도',\n                        technicpowerlite_item_sound: '소리',\n                        technicpowerlite_item_tilt: '기울기',\n                        technicpowerlite_item_pressure: '압력',\n                        technicpowerlite_item_multi_touch: '멀티키',\n                        technicpowerlite_item_compass: '나침반',\n                        technicpowerlite_item_tri_acceleration: '3가속',\n                        technicpowerlite_item_multi_switch: '분배기',\n                        technicpowerlite_item_infinite_rotation: '무한회전',\n                        technicpowerlite_item_extension_input: '확장입력',\n                        technicpowerlite_item_color_red: '빨간색',\n                        technicpowerlite_item_color_green: '초록색',\n                        technicpowerlite_item_color_blue: '파란색',\n                        technicpowerlite_item_color_cyan: '청녹색',\n                        technicpowerlite_item_color_magenta: '자홍색',\n                        technicpowerlite_item_color_yellow: '노란색',\n                        technicpowerlite_item_color_black: '검정색',\n                        technicpowerlite_item_color_white: '하얀색',\n                        technicpowerlite_item_value: '값',\n                        technicpowerlite_item_angle: '각도',\n                        technicpowerlite_item_absolute_angle: '절대각도',\n                        technicpowerlite_item_number_of_rotations: '회전 수',\n                        technicpowerlite_item_key_1: '키1',\n                        technicpowerlite_item_key_2: '키2',\n                        technicpowerlite_item_key_3: '키3',\n                        technicpowerlite_item_key_4: '키4',\n                        technicpowerlite_item_key_5: '키5',\n                        technicpowerlite_item_key_6: '키6',\n                        technicpowerlite_item_key_7: '키7',\n                        technicpowerlite_item_key_8: '키8',\n                        technicpowerlite_item_all: '모두',\n                        technicpowerlite_item_on: '켜기',\n                        technicpowerlite_item_off: '끄기',\n                        technicpowerlite_item_note_whole: '온',\n                        technicpowerlite_item_note_half: '2분',\n                        technicpowerlite_item_note_quarter: '4분',\n                        technicpowerlite_item_note_eighth: '8분',\n                        technicpowerlite_item_note_sixteenth: '16분',\n                        technicpowerlite_item_note_thirty_second: '32분',\n                        technicpowerlite_item_pitch_do: '도',\n                        technicpowerlite_item_pitch_do_sharp: '도#',\n                        technicpowerlite_item_pitch_re: '레',\n                        technicpowerlite_item_pitch_re_sharp: '레#',\n                        technicpowerlite_item_pitch_mi: '미',\n                        technicpowerlite_item_pitch_fa: '파',\n                        technicpowerlite_item_pitch_fa_sharp: '파#',\n                        technicpowerlite_item_pitch_sol: '솔',\n                        technicpowerlite_item_pitch_sol_sharp: '솔#',\n                        technicpowerlite_item_pitch_ra: '라',\n                        technicpowerlite_item_pitch_ra_sharp: '라#',\n                        technicpowerlite_item_pitch_si: '시',\n                        technicpowerlite_item_melody_start: '시작음',\n                        technicpowerlite_item_melody_end: '종료음',\n                        technicpowerlite_item_melody_level_up: '레벨 업',\n                        technicpowerlite_item_melody_level_down: '레벨 다운',\n\n                        technicpowerlite_item_error: '오류',\n                        technicpowerlite_item_nothing: '없음',\n        \n                        technicpowerlite_when_press_remote_key: '%1 리모컨 %2 키를 눌렀을 때',\n                        technicpowerlite_when_input_digital_value: '%1 디지털 입력 %2 이(가) 들어왔을 때',\n        \n                        technicpowerlite_set_senser_setting: '입력포트 %1 을(를) %2 센서로 설정 %3',\n        \n                        technicpowerlite_is_remote_key: '리모컨 입력 %1',\n                        technicpowerlite_is_digital_value: '디지털 입력 %1',\n                        technicpowerlite_is_extension_digital_input: '확장 디지털 입력 %1 의 %2',\n                        technicpowerlite_get_analog_value: '아날로그 입력 %1',\n                        technicpowerlite_get_extension_analog_input: '확장 아날로그 입력 %1 의 %2',\n                        technicpowerlite_get_tri_axis_acceler_x: '3가속도 %1의 X축',\n                        technicpowerlite_get_tri_axis_acceler_y: '3가속도 %1의 Y축',\n                        technicpowerlite_get_tri_axis_acceler_z: '3가속도 %1의 Z축',\n                        technicpowerlite_get_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환',\n                        technicpowerlite_is_color_value: '컬러 센서 %1 이(가) %2 인가?',\n                        technicpowerlite_get_color_value: '컬러 센서 %1 의 색상',\n                        technicpowerlite_set_infinite_setting: '%1 센서 %2 을 %3 값으로 정하기 %4',\n                        technicpowerlite_get_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값',\n                        technicpowerlite_get_infinite_transform_input: '%1 센서 %2 의  %3',\n                        technicpowerlite_is_multi_sensor: '멀티키 센서 %1의 %2',\n                        technicpowerlite_is_multi_switch: '분배 스위치 %1의 %2',\n                        technicpowerlite_set_eeprom_call: 'EEPROM %1 주소의 값 호출하기 %2',\n                        technicpowerlite_get_eeprom_address_value: 'EEPROM 주소의 값',      \n        \n                        technicpowerlite_set_port_output: '출력핀 %1 을(를) %2 %3',\n                        technicpowerlite_set_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3',\n                        technicpowerlite_set_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3',\n                        technicpowerlite_set_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3',\n                        technicpowerlite_play_melody_note_output: '%1 을(를) %2 음표로 연주하기 %3',\n                        technicpowerlite_play_melody_sec_output: '%1 을(를) %2 초 동안 연주하기 %3',\n                        technicpowerlite_play_melody_output: '%1 을(를) 연주하기 %2',\n                        technicpowerlite_play_value_sec_output: '%1 값을(를) %2 초 동안 연주하기 %3',\n                        technicpowerlite_play_value_output: '%1 값을(를) 연주하기 %2',\n                        technicpowerlite_play_melody_track_output: '%1 을(를) %2초 간격으로 재생하기 %3',\n                        technicpowerlite_play_melody_off: '멜로디 중지 %1',\n                        technicpowerlite_set_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3',\n                        technicpowerlite_set_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2',\n                        technicpowerlite_set_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3',\n                        technicpowerlite_set_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4',\n                        technicpowerlite_set_fnd_output: 'FND를 %1 (으)로 설정 %2',\n                        technicpowerlite_set_fnd_off: 'FND 끄기 %1',\n                        technicpowerlite_set_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3',\n                    },\n                    Device: {\n                        probo_technic_power_lite: '프로보 테크닉(파워)',\n                    },\n                    Menus: {\n                        probo_technic_power_lite: '프로보 테크닉(파워)',\n                    },\n                },\n                en: {\n\n                    template: {\n                        technicpowerlite_item_switch: 'Switch',\n                        technicpowerlite_item_infrared: 'Infrared',\n                        technicpowerlite_item_magnetic: 'Magnetic',\n                        technicpowerlite_item_rotation: 'Rotation',\n                        technicpowerlite_item_color: 'Color',\n                        technicpowerlite_item_acceleration: 'Acceleration',\n                        technicpowerlite_item_ultrasonic: 'Ultrasonic',\n                        technicpowerlite_item_heart_rate: 'Heart Rate',\n                        technicpowerlite_item_illuminance: 'Illuminance',\n                        technicpowerlite_item_temperature: 'Temperature',\n                        technicpowerlite_item_sound: 'Sound',\n                        technicpowerlite_item_tilt: 'Tilt',\n                        technicpowerlite_item_pressure: 'Pressure',\n                        technicpowerlite_item_multi_touch: 'Multi Touch',\n                        technicpowerlite_item_compass: 'Compass',\n                        technicpowerlite_item_tri_acceleration: '3Acceleration',\n                        technicpowerlite_item_multi_switch: 'Multi Switch',\n                        technicpowerlite_item_infinite_rotation: 'Infinite Rotation',\n                        technicpowerlite_item_extension_input: 'Extension Input',\n                        technicpowerlite_item_color_red: 'Red',\n                        technicpowerlite_item_color_green: 'Green',\n                        technicpowerlite_item_color_blue: 'Blue',\n                        technicpowerlite_item_color_cyan: 'Cyan',\n                        technicpowerlite_item_color_magenta: 'Magenta',\n                        technicpowerlite_item_color_yellow: 'Yellow',\n                        technicpowerlite_item_color_black: 'Black',\n                        technicpowerlite_item_color_white: 'White',\n                        technicpowerlite_item_value: 'Value',\n                        technicpowerlite_item_angle: 'Angle',\n                        technicpowerlite_item_absolute_angle: 'Absolute Angle',\n                        technicpowerlite_item_number_of_rotations: 'Number of Rotations',\n                        technicpowerlite_item_key_1: 'Key1',\n                        technicpowerlite_item_key_2: 'Key2',\n                        technicpowerlite_item_key_3: 'Key3',\n                        technicpowerlite_item_key_4: 'Key4',\n                        technicpowerlite_item_key_5: 'Key5',\n                        technicpowerlite_item_key_6: 'Key6',\n                        technicpowerlite_item_key_7: 'Key7',\n                        technicpowerlite_item_key_8: 'Key8',\n                        technicpowerlite_item_all: 'All',\n                        technicpowerlite_item_on: 'On',\n                        technicpowerlite_item_off: 'Off',\n                        technicpowerlite_item_note_whole: 'Whole',\n                        technicpowerlite_item_note_half: 'Half',\n                        technicpowerlite_item_note_quarter: 'Quarter',\n                        technicpowerlite_item_note_eighth: 'Eighth',\n                        technicpowerlite_item_note_sixteenth: 'Sixteenth',\n                        technicpowerlite_item_note_thirty_second: 'Thirty-Second',\n                        technicpowerlite_item_pitch_do: 'do',\n                        technicpowerlite_item_pitch_do_sharp: 'xdo',\n                        technicpowerlite_item_pitch_re: 're',\n                        technicpowerlite_item_pitch_re_sharp: 'xre',\n                        technicpowerlite_item_pitch_mi: 'mi',\n                        technicpowerlite_item_pitch_fa: 'fa',\n                        technicpowerlite_item_pitch_fa_sharp: 'xfa',\n                        technicpowerlite_item_pitch_sol: 'sol',\n                        technicpowerlite_item_pitch_sol_sharp: 'xsol',\n                        technicpowerlite_item_pitch_ra: 'ra',\n                        technicpowerlite_item_pitch_ra_sharp: 'xra',\n                        technicpowerlite_item_pitch_si: 'si',\n                        technicpowerlite_item_melody_start: 'Start',\n                        technicpowerlite_item_melody_end: 'End',\n                        technicpowerlite_item_melody_level_up: 'Level up',\n                        technicpowerlite_item_melody_level_down: 'Level down',\n                        \n                        technicpowerlite_item_error: 'error',\n                        technicpowerlite_item_nothing: 'nothing',\n\n                        technicpowerlite_when_press_remote_key: '%1 When %2 remote control key pressed',\n                        technicpowerlite_when_input_digital_value: '%1 When %2 digital pin input',\n\n                        technicpowerlite_set_senser_setting: 'Set input port %1 to %2 sensor %3',\n\n                        technicpowerlite_is_remote_key: 'Remote control %1',\n                        technicpowerlite_is_digital_value: 'Read digital pin %1',\n                        technicpowerlite_is_extension_digital_input: 'Extension digital input %1 to %2',\n                        technicpowerlite_get_analog_value: 'Read analog pin %1',\n                        technicpowerlite_get_extension_analog_input: 'Extension analog input %1 to %2',\n                        technicpowerlite_get_tri_axis_acceler_x: '3acceleration %1 and X',\n                        technicpowerlite_get_tri_axis_acceler_y: '3acceleration %1 and Y',\n                        technicpowerlite_get_tri_axis_acceler_z: '3acceleration %1 and Z',\n                        technicpowerlite_get_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5',\n                        technicpowerlite_is_color_value: 'Is color sensor %1 %2 ?',\n                        technicpowerlite_get_color_value: 'Color of color sensor %1',\n                        technicpowerlite_set_infinite_setting: 'Set %1 sensor %2 to %3 value %4',\n                        technicpowerlite_get_infinite_mm_diameter: 'The move distance(in mm) when the %1 sensor %2 is %3 mm in diameter',\n                        technicpowerlite_get_infinite_transform_input: '%1 rotation sensor %2 to %3',\n                        technicpowerlite_is_multi_sensor: 'Multi sensor %1 key %2',\n                        technicpowerlite_is_multi_switch: 'A key number of the multi-switch sensor %1 = %2',\n                        technicpowerlite_set_eeprom_call:'Calling the value of EEPROM %1 address',\n                        technicpowerlite_get_eeprom_address_value: 'Value of EEPROM address',\n\n                        technicpowerlite_set_dc_output: 'DC motor %1 velocity %2 %3',\n                        technicpowerlite_set_servo_output: 'Servo motor %1 position %2 %3',\n                        technicpowerlite_set_s_dc_output: 'Servo motor %1 speed %2 %3',\n                        technicpowerlite_set_port_output: 'Set digital pin %1 as %2 %3',\n                        technicpowerlite_play_melody_note_output: 'Play key %1 for %2 note %3',\n                        technicpowerlite_play_melody_sec_output: 'Play key %1 for %2 secs %3',\n                        technicpowerlite_play_melody_output: 'Play key %1 %2',\n                        technicpowerlite_play_value_sec_output: 'Play value %1 for %2 secs %3',\n                        technicpowerlite_play_value_output: 'Play value %1 %2',\n                        technicpowerlite_play_melody_track_output: 'Play sound %1 for %2 secs %3',\n                        technicpowerlite_play_melody_off: 'Stop tone %1',\n                        technicpowerlite_set_rgbled_on_output: 'Turn on RGB LED %1 to %2 %3',\n                        technicpowerlite_set_rgbled_off_output: 'Turn off RGB LED %1 %2',\n                        technicpowerlite_set_rgbled_dimming_output: 'Dimming RGB LED %1 to %2 %3',\n                        technicpowerlite_set_rgbled_flashing_output: 'RGB LED %1 Blinking %2 at %3 second intervals %4',\n                        technicpowerlite_set_fnd_output: 'Set FND to %1 %2',\n                        technicpowerlite_set_fnd_off: 'Turn off FND %1',\n                        technicpowerlite_set_eeprom_write: 'Set EEPROM %1 address to %2 %3',\n                    },\n                    Device: {\n                        probo_technic_power_lite: 'Probo Technic(Power)',\n                    },\n                    Menus: {\n                        probo_technic_power_lite: 'Probo Technic(Power)',\n                    },\n                },\n            };\n        }\n\n        // 시작하기 및 정지하기 시 기기상태를 초기화한다.\n        setZero() {\n            this.Infinite = {\n                Buff: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Count: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Start: {                    \n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                }\n            };\n            this.SenserSet = {\n                AA1: 0,\n                AA2: 0,\n                AA3: 0,\n                AA4: 0\n            };\n            this.InputData = {\n                Analog: {\n                    AA1: 0,\n                    AA2: 0,\n                    AA3: 0,\n                    AA4: 0\n                },\n                Digital: {\n                    A1: 0,\n                    A2: 0,\n                    A3: 0,\n                    A4: 0,\n                    FEA1: 0,\n                    FEA2: 0,\n                    FEA3: 0,\n                    FEA4: 0,\n                    REA1: 0,\n                    REA2: 0,\n                    REA3: 0,\n                    REA4: 0,\n                    BEA1: 0,\n                    BEA2: 0,\n                    BEA3: 0,\n                    BEA4: 0\n                },\n                Remote: {\n                    R_1: 0,\n                    R_2: 0,\n                    R_3: 0,\n                    R_4: 0,\n                    R_5: 0,\n                    R_6: 0,\n                    R_7: 0,\n                    R_8: 0,\n                    R_L1: 0,\n                    R_L2: 0,\n                    R_R1: 0,\n                    R_R2: 0\n                },\n                EEPROM: {\n                    EC: 0,\n                    EEPR2: 0,\n                    EEPR1: 0\n                },\n                Infinite:{\n                    ROTATION_1: 0,\n                    ROTATION_2: 0,\n                    ROTATION_3: 0,\n                    ROTATION_4: 0\n                },\n                Acceler:{\n                    AXIS_X1: 0,\n                    AXIS_X2: 0,\n                    AXIS_X3: 0,\n                    AXIS_X4: 0,\n                    AXIS_Y1: 0,\n                    AXIS_Y2: 0,\n                    AXIS_Y3: 0,\n                    AXIS_Y4: 0,\n                    AXIS_Z1: 0,\n                    AXIS_Z2: 0,\n                    AXIS_Z3: 0,\n                    AXIS_Z4: 0\n                }\n            };\n            this.RemoteData = {\n                B1: 0,\n                B2: 0,\n                B3: 0,\n                B4: 0,\n                Servo1: 0,\n                Servo2: 0,\n                Servo3: 0,\n                Servo4: 0,\n                DC1: 0,\n                DC2: 0,\n                DC3: 0,\n                DC4: 0,\n                MEL2: 0,\n                MEL1: 0,\n                FND: 100,\n                EEPR4: 0,\n                EEPR3: 0,\n                EEPR2: 0,\n                EEPR1: 0,\n                ASET2: 0,\n                ASET1: 0\n            };\n            this.EdgeFlag = {\n                FEA1: 0,\n                FEA2: 0,\n                FEA3: 0,\n                FEA4: 0,\n                REA1: 0,\n                REA2: 0,\n                REA3: 0,\n                REA4: 0,\n                BEA1: 0,\n                BEA2: 0,\n                BEA3: 0,\n                BEA4: 0\n            };\n            this.EEPROM = {\n                Buff: 0,\n                Count: 0\n            };\n            \n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            };\n        }\n\n        // 하드웨어 연결 후 초기화한다.\n        async initialHandshake() {\n            const ko = `테크닉의 'Start' 버튼을 누른 후 확인을 클릭하세요.\\n`;\n            const en = `(Please, After pushing the 'Start' button in Technic, click 'OK'.)`;\n            alert(`${ko}${en}`);\n\n            const modePacket = new Uint8Array(2).fill(0);\n            modePacket[0] = 0x63;\n            modePacket[1] = 0x36;\n\n            while(true) {\n                const response = await Entry.hwLite.serial.sendAsyncWithThrottle(modePacket);\n\n                if (response[0] !== TECHNIC_POWER_INDEX) {\n                    modePacket[0] = 0x24;\n                    modePacket[1] = 0x42;\n                } else {\n                    this.version = (response.length === 1)\n                        ? RELEASE_VERSION\n                        : response[1];\n                    await Entry.Utils.sleep(1000);\n                    break;\n                }\n                await Entry.Utils.sleep(100);\n            }\n\n            Entry.addEventListener('run', this.handleRemoteEventInterval.bind(this));\n            Entry.addEventListener('run', this.handleDigitalEventInterval.bind(this));\n            Entry.addEventListener('beforeStop', () => {\n                if (this.remoteEventIntervalId) {\n                    clearInterval(this.remoteEventIntervalId);\n                    this.remoteEventIntervalId = null;\n                }\n                if (this.digitalEventIntervalId) {\n                    clearInterval(this.digitalEventIntervalId);\n                    this.digitalEventIntervalId = null;\n                }\n            });\n            \n            this.setZero();\n\n            if (this.version === 0) {\n                const packet = await Entry.hwLite.serial.reader.read();\n                this.version = packet.value[0];\n                if (this.version !== RELEASE_VERSION) {\n                    const ko = `펌웨어를 업데이트 하세요.\\n`;\n                    const en = `(Please, Update your firmware.)\\n`;\n                    const version = ` - 현재(now): v.${this.version}\\n - 최신(latest): v.${RELEASE_VERSION}`;\n                    alert(`${ko}${en}${version}`);\n                }\n            }\n\n            return true;\n        }\n\n        handleRemoteEventInterval() {\n            if (this.remoteEventIntervalId) {\n                clearInterval(this.remoteEventIntervalId);\n            }\n            this.remoteEventIntervalId = setInterval(() => {\n                const currentState = this.remoteEvent.bind(this);\n                currentState();\n            }, EVENT_INTERVAL);\n        }\n\n        handleDigitalEventInterval() {\n            if (this.digitalEventIntervalId) {\n                clearInterval(this.digitalEventIntervalId);\n            }\n            this.digitalEventIntervalId = setInterval(() => {\n                const currentState = this.digitalEvent.bind(this);\n                currentState();\n            }, EVENT_INTERVAL);\n        }\n\n        // 디바이스에서 값을 읽어온다.\n        handleLocalData(buffer) {\n            buffer.forEach(b => this.qEnqueue(b));\n            \n            if (this._recoverTimeoutId) {\n                clearTimeout(this._recoverTimeoutId);\n            }\n\n            while(this.qCount() >= this.inputPacket.length) {\n                if (!this.process) {\n                    while(this.qCount() > 0) {\n                        if (this.inputPacket[0] !== 0xCD) {\n                            this.inputPacket[0] = this.qDequeue();\n                        } else if (this.inputPacket[1] !== 0xDA) {\n                            this.inputPacket[1] = this.qDequeue();\n                        } else {\n                            this.inputPacket[2] = this.qDequeue();\n                            this.pLength = this.inputPacket[2] + 3;\n                            this.process = true;\n                            break;\n                        }\n                    }\n                }\n    \n                if (this.process && (this.qCount() >= this.pLength)) {\n                    for (let i = 3; i < this.pLength; i++) {\n                        this.inputPacket[i] = this.qDequeue();\n                    }\n                    if (this.checksumHandle(this.inputPacket)) {\n                        this.processInputPacket(this.inputPacket);\n                    }\n\n                    this.inputPacket = new Uint8Array(RECEIVED_PACKET_LENGTH).fill(-1);\n                    this.process = false;\n                    this.sendFlag = true;\n                    this.pLength = 0;\n                }\n            }\n\n            if (this.sendFlag) {\n                if (this._requestTimeoutId) {\n                    clearTimeout(this._requestTimeoutId);\n                }\n                this._requestTimeoutId = setTimeout(\n                    () => {\n                        if (Entry.hwLite && Entry.hwLite.serial) {\n                            Entry.hwLite.serial.update();\n                            this.sendFlag = false;\n                            this._recoverTimeoutId = setTimeout(() => {\n                                this.sendFlag = true;\n                            }, SERIAL_INTERVAL * 3);\n                        }\n                    },\n                    SERIAL_INTERVAL\n                );\n            }\n        }\n\n        //디바이스에 값을 쓴다.\n        requestLocalData() {\n            if (this.sendFlag) {\n                return this.generateOutputPacket(this.RemoteData);\n            }\n        }\n\n        qEnqueue(data) {\n            this.qBuffer[this.qRear] = data;\n            this.qRear = (this.qRear + 1) % this.qSize\n        }\n\n        qDequeue() {\n            const data = this.qBuffer[this.qFront];\n            this.qBuffer[this.qFront] = -1;\n            this.qFront = (this.qFront + 1) % this.qSize;\n            return data;\n        }\n\n        qCount() {\n            return (this.qFront <= this.qRear)\n                ? (this.qRear - this.qFront)\n                : (this.qSize - this.qFront + this.qRear);\n        }\n\n        checksumRequest(packet) {\n            const length = packet[2] + 2;\n            let checker = 0;\n            for(let i = 3; i < length; i++) {\n                checker += packet[i];\n            }\n            return (checker & 0xFF);\n\n        }\n        \n        checksumHandle(packet) {\n            let checker = 0;\n            const length = packet[2] + 2;\n            for(let i = 3; i < length ; i++ ) {\n                checker += packet[i];\n            }\n            return (packet[length] === (checker & 0xFF))\n        }\n\n        processInputPacket(packet) {\n            const digitalByte1 = packet[8];\n            const digitalByte2 = packet[9];\n            const remoteByte1 = packet[10];\n            const remoteByte2 = packet[11];\n            const rotationByte = packet[16];\n\n            this.InputData.Analog.AA1 = packet[4];\n            this.InputData.Analog.AA2 = packet[5];\n            this.InputData.Analog.AA3 = packet[6];\n            this.InputData.Analog.AA4 = packet[7];\n\n            this.InputData.Digital.A4 = (digitalByte1 >> 7) & 0x01;\n            this.InputData.Digital.A3 = (digitalByte1 >> 6) & 0x01;\n            this.InputData.Digital.A2 = (digitalByte1 >> 5) & 0x01;\n            this.InputData.Digital.A1 = (digitalByte1 >> 4) & 0x01;\n            this.InputData.Digital.FEA4 = (digitalByte1 >> 3) & 0x01;\n            this.InputData.Digital.FEA3 = (digitalByte1 >> 2) & 0x01;\n            this.InputData.Digital.FEA2 = (digitalByte1 >> 1) & 0x01;\n            this.InputData.Digital.FEA1 = digitalByte1 & 0x01;\n            this.InputData.Digital.REA4 = (digitalByte2 >> 7) & 0x01;\n            this.InputData.Digital.REA3 = (digitalByte2 >> 6) & 0x01;\n            this.InputData.Digital.REA2 = (digitalByte2 >> 5) & 0x01;\n            this.InputData.Digital.REA1 = (digitalByte2 >> 4) & 0x01;\n            this.InputData.Digital.BEA4 = (digitalByte2 >> 3) & 0x01;\n            this.InputData.Digital.BEA3 = (digitalByte2 >> 2) & 0x01;\n            this.InputData.Digital.BEA2 = (digitalByte2 >> 1) & 0x01;\n            this.InputData.Digital.BEA1 = digitalByte2 & 0x01;\n\n            this.InputData.Remote.R_3 = (remoteByte1 >> 7) & 0x01;\n            this.InputData.Remote.R_2 = (remoteByte1 >> 6) & 0x01;\n            this.InputData.Remote.R_4 = (remoteByte1 >> 5) & 0x01;\n            this.InputData.Remote.R_1 = (remoteByte1 >> 4) & 0x01;                    \n            this.InputData.Remote.R_7 = (remoteByte2 >> 7) & 0x01;\n            this.InputData.Remote.R_6 = (remoteByte2 >> 6) & 0x01;\n            this.InputData.Remote.R_8 = (remoteByte2 >> 5) & 0x01;\n            this.InputData.Remote.R_5 = (remoteByte2 >> 4) & 0x01;\n            this.InputData.Remote.R_R1 = (remoteByte2 >> 3) & 0x01;\n            this.InputData.Remote.R_L1 = (remoteByte2 >> 2) & 0x01;\n            this.InputData.Remote.R_R2 = (remoteByte2 >> 1) & 0x01;\n            this.InputData.Remote.R_L2 = remoteByte2 & 0x01;\n\n            this.InputData.EEPROM.EC = packet[13];\n            this.InputData.EEPROM.EEPR2 = packet[14];\n            this.InputData.EEPROM.EEPR1 = packet[15];\n\n            this.InputData.Infinite.ROTATION_1 = (rotationByte >> 6) & 0x0C;\n            this.InputData.Infinite.ROTATION_2 = (rotationByte >> 4) & 0x0C;\n            this.InputData.Infinite.ROTATION_3 = (rotationByte >> 2) & 0x0C;\n            this.InputData.Infinite.ROTATION_4 = rotationByte & 0x03;\n\n            this.InputData.Acceler.AXIS_X1 = packet[4];\n            this.InputData.Acceler.AXIS_X2 = packet[5];\n            this.InputData.Acceler.AXIS_X3 = packet[6];\n            this.InputData.Acceler.AXIS_X4 = packet[7];\n\n            this.InputData.Acceler.AXIS_Y1 = packet[17];\n            this.InputData.Acceler.AXIS_Y2 = packet[19];\n            this.InputData.Acceler.AXIS_Y3 = packet[21];\n            this.InputData.Acceler.AXIS_Y4 = packet[23];\n\n            this.InputData.Acceler.AXIS_Z1 = packet[18];\n            this.InputData.Acceler.AXIS_Z2 = packet[20];\n            this.InputData.Acceler.AXIS_Z3 = packet[22];\n            this.InputData.Acceler.AXIS_Z4 = packet[24];\n        }\n\n        generateOutputPacket(remoteData) {           \n\n            const outputPacket = new Uint8Array(SEND_PACKET_LENGTH).fill(-1);\n\n            outputPacket[0] = 0xAD;\n            outputPacket[1] = 0xDA;\n            outputPacket[2] = outputPacket.length - 3;\n\n            outputPacket[3] = 0xF0 | (remoteData.B4 << 3) | (remoteData.B3 << 2) | (remoteData.B2 << 1) | remoteData.B1;\n\n            outputPacket[4] = remoteData.Servo1;\n            outputPacket[5] = remoteData.Servo2;\n            outputPacket[6] = remoteData.Servo3;\n            outputPacket[7] = remoteData.Servo4;\n\n            outputPacket[8] = remoteData.DC1;\n            outputPacket[9] = remoteData.DC2;\n            outputPacket[10] = remoteData.DC3;\n            outputPacket[11] = remoteData.DC4;\n\n            outputPacket[12] = remoteData.MEL2;\n            outputPacket[13] = remoteData.MEL1;\n\n            outputPacket[14] = remoteData.FND; \n\n            outputPacket[15] = remoteData.EEPR4;\n            outputPacket[16] = remoteData.EEPR3;\n            outputPacket[17] = remoteData.EEPR2;\n            outputPacket[18] = remoteData.EEPR1;\n\n            outputPacket[19] = remoteData.ASET2;\n            outputPacket[20] = remoteData.ASET1;\n\n            outputPacket[21] = this.checksumRequest(outputPacket);\n\n            return outputPacket;\n        }\n        \n        getMonitorPort() {\n            return { ...this.InputData.Analog };\n        }\n\n        getRemoteKey(data) {\n            const num = Number(data);            \n            \n            if (1 <= num && num <= 8) {\n                return `R_${num}`;\n            } else if (9 <= num && num <= 10) {\n                return `R_L${(num - 8)}`;\n            } else if (11 <= num && num <= 12) {\n                return `R_R${(num - 10)}`;\n            } else {\n                return data;\n            }\n        }\n\n        getDigitalKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `A${num}`;\n            } else if (5 <= num && num <= 8) {\n                return `FEA${num - 4}`;\n            } else if (9 <= num && num <= 12) {\n                return `REA${num - 8}`;\n            } else if (13 <= num && num <= 16) {\n                return `BEA${num - 12}`;\n            } else {\n                return data;\n            }\n        }\n\n        getDigitalStateValue(key) {\n            let value = false;\n            switch(key) {\n                case 'A1':\n                case 'A2':\n                case 'A3':\n                case 'A4':\n                    value = (Entry.ProboTechnicPowerLite.InputData.Digital[key] === 1);\n                    break;\n                default:\n                    if (Entry.ProboTechnicPowerLite.InputData.Digital[key] === 1) {\n                        if (Entry.ProboTechnicPowerLite.EdgeFlag[key] === 0) {\n                            Entry.ProboTechnicPowerLite.EdgeFlag[key] = 1;\n                            value = true;\n                        }\n                    } else {\n                        Entry.ProboTechnicPowerLite.EdgeFlag[key] = 0;\n                    }\n                    break;\n            }\n\n            return value;\n        }\n\n        getAnalogKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `AA${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getSettingSensorValue(key) {\n            switch (key) {\n                case '1':  // 스위치\n                case '2':  // 적외선\n                case '3':  // 자석\n                case '16': // 분배기\n                case Lang.template.technicpowerlite_item_switch:       // 스위치\n                case Lang.template.technicpowerlite_item_infrared:     // 적외선\n                case Lang.template.technicpowerlite_item_magnetic:     // 자석\n                case Lang.template.technicpowerlite_item_multi_switch: // 분배기\n                    return 1;\n                case '4': // 회전\n                case '7': // 조도\n                case '9': // 초음파\n                case Lang.template.technicpowerlite_item_rotation:    // 회전\n                case Lang.template.technicpowerlite_item_illuminance: // 조도            \n                case Lang.template.technicpowerlite_item_ultrasonic:  // 초음파\n                    return 2;\n                case '10': // 소리\n                case Lang.template.technicpowerlite_item_sound: // 소리\n                    return 3;\n                case '11': // 기울기\n                case Lang.template.technicpowerlite_item_tilt: // 기울기\n                    return 4;\n                case '12': // 압력\n                case Lang.template.technicpowerlite_item_pressure: // 압력\n                    return 5;\n                case '8': // 심박\n                case Lang.template.technicpowerlite_item_heart_rate: // 심박\n                    return 6;\n                case '5': // 컬러\n                case Lang.template.technicpowerlite_item_color: // 컬러\n                    return 7;\n                case '6': // 가속도\n                case Lang.template.technicpowerlite_item_acceleration: // 가속도\n                    return 8;\n                case '14': // 나침반\n                case '15': // 3축 가속도\n                case '17': // 확장 입력  \n                case Lang.template.technicpowerlite_item_compass:\n                case Lang.template.technicpowerlite_item_tri_acceleration:\n                case Lang.template.technicpowerlite_item_extension_input:\n                    return 9;\n                case '13': // 멀티터치(멀티키)\n                case Lang.template.technicpowerlite_item_multi_touch: // 멀티터치(멀티키)\n                    return 11;\n                default:\n                    return key;\n            }\n        }\n\n        getAxisKey(data, axis) {\n            switch (data) {\n                case 'AA1':\n                case 'AA2':\n                case 'AA3':\n                case 'AA4':\n                    data = data.substr(2, 2);\n                    break;\n            }\n\n            return `AXIS_${axis}${data}`;\n        }\n\n        getMultiKeyValue(key) {\n            const num = Number(key);\n\n            if (1 <= num && num <= 8) {\n                return (num - 1);\n            } else {\n                switch (key) {\n                    case Lang.template.technicpowerlite_item_key_1:\n                        return 0;\n                    case Lang.template.technicpowerlite_item_key_2:\n                        return 1;\n                    case Lang.template.technicpowerlite_item_key_3:\n                        return 2;\n                    case Lang.template.technicpowerlite_item_key_4:\n                        return 3;\n                    case Lang.template.technicpowerlite_item_key_5:\n                        return 4;\n                    case Lang.template.technicpowerlite_item_key_6:\n                        return 5;\n                    case Lang.template.technicpowerlite_item_key_7:\n                        return 6;\n                    case Lang.template.technicpowerlite_item_key_8:\n                        return 7;\n                    default:\n                        return key;\n                }\n            }\n        }\n\n        getExtentionDigitalValue(key) {\n            const num = Number(key);\n            if (1 <= num && num <= 8) {\n                return (num - 1);\n            } else if (9 <= num && num <= 16) {                \n                return (num - 9);\n            } else {\n                switch (key) {\n                    case 'EA1':\n                    case 'ET1':\n                        return 0;\n                    case 'EA2':\n                    case 'ET2':\n                        return 1;\n                    case 'EA3':\n                    case 'ET3':\n                        return 2;\n                    case 'EA4':\n                    case 'ET4':\n                        return 3;\n                    case 'EA5':\n                    case 'ET5':\n                        return 4;\n                    case 'EA6':\n                    case 'ET6':\n                        return 5;\n                    case 'EA7':\n                    case 'ET7':\n                        return 6;\n                    case 'EA8':\n                    case 'ET8':\n                        return 7;\n                    default:\n                        return key;\n                }\n            }\n        }\n\n        getExtentionAnalogKey(data) {\n            switch (data) {\n                case '1':\n                case 'EAA1':\n                    return 'Y';\n                case '2':\n                case 'EAA2':\n                    return 'Z';\n                default:\n                    return data;\n            }\n        }\n\n        getDckey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 7) {\n                return `DC${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getServoKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `Servo${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getPortKey(data) {\n            const num = Number(data);\n\n            if (1 <= num && num <= 4) {\n                return `B${num}`;\n            } else {\n                return data;\n            }\n        }\n\n        getPortToggleValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.technicpowerlite_item_on:\n                    return 1;\n                case '0':\n                case Lang.template.technicpowerlite_item_off:\n                    return 0;\n                default:\n                    return key;\n            }\n        }\n\n        getSensorAngleKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.technicpowerlite_item_value:\n                    return 'IS1';\n                case '2':\n                case Lang.template.technicpowerlite_item_angle:\n                    return 'IS2';\n                case '3':\n                case Lang.template.technicpowerlite_item_absolute_angle:\n                    return 'IS3';\n                case '4':\n                case Lang.template.technicpowerlite_item_number_of_rotations:\n                    return 'IS4';\n                default:\n                    return data;\n            }\n        }\n\n        getPitchValue(pitch) {\n            // 배열의 인덱스 1번부터 음표\n            const index = (pitch % 12) + 1;\n\n            if (36 <= pitch && pitch <= 47) {\n                return Entry.ProboTechnicPowerLite.Melody[index];\n            } else if (48 <= pitch && pitch <= 59) {\n                return Entry.ProboTechnicPowerLite.Melody[index] >> 1;\n            } else if (60 <= pitch && pitch <= 71) {\n                return Entry.ProboTechnicPowerLite.Melody[index] >> 2;\n            } else if (72 <= pitch && pitch <= 83) {\n                return Entry.ProboTechnicPowerLite.Melody[index] >> 3;\n            } else {\n                return Entry.ProboTechnicPowerLite.Melody[0];\n            }\n        }\n\n        getNoteKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.technicpowerlite_item_note_whole:\n                    return 'n1';\n                case '2':\n                case Lang.template.technicpowerlite_item_note_half:\n                    return 'n2';\n                case '4':\n                case Lang.template.technicpowerlite_item_note_quarter:\n                    return 'n4';\n                case '8':\n                case Lang.template.technicpowerlite_item_note_eighth:\n                    return 'n8';\n                case '16':\n                case Lang.template.technicpowerlite_item_note_sixteenth:\n                    return 'n16';\n                case '32':\n                case Lang.template.technicpowerlite_item_note_thirty_second:\n                    return 'n32';\n                default:\n                    return data;\n            }\n        }\n\n        getMelodyValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.technicpowerlite_item_melody_start:\n                    return 0;\n                case '2':\n                case Lang.template.technicpowerlite_item_melody_end:\n                    return 1;\n                case '3':\n                case Lang.template.technicpowerlite_item_melody_level_up:\n                    return 2;\n                case '4':\n                case Lang.template.technicpowerlite_item_melody_level_down:\n                    return 3;\n                default:\n                    return key;\n            }\n        }\n\n        getColorSensorKey(data) {\n            switch (data) {\n                case '1':\n                case Lang.template.technicpowerlite_item_color_red:\n                    return 'Red';\n                case '2':\n                case Lang.template.technicpowerlite_item_color_green:\n                    return 'Green';\n                case '3':\n                case Lang.template.technicpowerlite_item_color_blue:\n                    return 'Blue';\n                case '4':\n                case Lang.template.technicpowerlite_item_color_yellow:\n                    return 'Yellow';\n                case '5':\n                case Lang.template.technicpowerlite_item_color_black:\n                    return 'Black';\n                case '6':\n                case Lang.template.technicpowerlite_item_color_white:\n                    return 'White';\n                default:\n                    return data;\n            }\n        }\n\n        getRgbToggleValue(key) {\n            switch (key) {\n                case '0':\n                    return this.Rgb.Off;\n                case '1':\n                case Lang.template.technicpowerlite_item_color_red:\n                    return this.Rgb.On.Red;\n                case '2':\n                case Lang.template.technicpowerlite_item_color_green:\n                    return this.Rgb.On.Green;\n                case '3':\n                case Lang.template.technicpowerlite_item_color_blue:\n                    return this.Rgb.On.Blue;\n                case '4':\n                case Lang.template.technicpowerlite_item_color_cyan:\n                    return this.Rgb.On.Cyan;\n                case '5':\n                case Lang.template.technicpowerlite_item_color_magenta:\n                    return this.Rgb.On.Magenta;\n                case '6':\n                case Lang.template.technicpowerlite_item_color_yellow:\n                    return this.Rgb.On.Yellow;\n                case '7':\n                case Lang.template.technicpowerlite_item_color_white:\n                    return this.Rgb.On.White;\n                default:\n                    return key;\n            }\n        }\n\n        getRgbTwinkleValue(key, sec) {\n            let twinkle = 0;\n            switch (sec) {\n                case 0.05:\n                    twinkle += 1;\n                    break;\n                case 0.1:\n                    twinkle += 2;\n                    break;\n                case 0.2:\n                    twinkle += 3;\n                    break;\n                case 0.5:\n                    twinkle += 4;\n                    break;\n                case 1:\n                    twinkle += 5;\n                    break;\n            }\n\n            return this.getRgbToggleValue(key) + twinkle;\n        }\n\n        getRgbDimmingValue(key) {\n            switch (key) {\n                case '1':\n                case Lang.template.technicpowerlite_item_color_red:\n                    return this.Rgb.Dimming.Red;\n                case '2':\n                case Lang.template.technicpowerlite_item_color_green:\n                    return this.Rgb.Dimming.Green;\n                case '3':\n                case Lang.template.technicpowerlite_item_color_blue:\n                    return this.Rgb.Dimming.Blue;\n                case '4':\n                case Lang.template.technicpowerlite_item_color_cyan:\n                    return this.Rgb.Dimming.Cyan;        \n                case '5':\n                case Lang.template.technicpowerlite_item_color_magenta:\n                    return this.Rgb.Dimming.Magenta;\n                case '6':\n                case Lang.template.technicpowerlite_item_color_yellow:\n                    return this.Rgb.Dimming.Yellow;\n                case '7':\n                case Lang.template.technicpowerlite_item_color_white:\n                    return this.Rgb.Dimming.White;\n                default:\n                    return key;\n            }\n        }\n\n        getBlocks() {\n            return {\n                ///========================================================================================\n                /// Dropdown block\n                ///========================================================================================\n                technicpowerlite_dropdown_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['R_1', '1'],\n                                ['R_2', '2'],\n                                ['R_3', '3'],\n                                ['R_4', '4'],\n                                ['R_5', '5'],\n                                ['R_6', '6'],\n                                ['R_7', '7'],\n                                ['R_8', '8'],\n                                ['R_L1', '9'],\n                                ['R_L2', '10'],\n                                ['R_R1', '11'],\n                                ['R_R2', '12'],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringValue('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['R_1', '1'],\n                                            ['R_2', '2'],\n                                            ['R_3', '3'],\n                                            ['R_4', '4'],\n                                            ['R_5', '5'],\n                                            ['R_6', '6'],\n                                            ['R_7', '7'],\n                                            ['R_8', '8'],\n                                            ['R_L1', '9'],\n                                            ['R_L2', '10'],\n                                            ['R_R1', '11'],\n                                            ['R_R2', '12'],\n                                        ],\n                                        value: 1,\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_remote_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_digital_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['A1', '1'],\n                                ['A2', '2'],\n                                ['A3', '3'],\n                                ['A4', '4'],\n                                ['FEA1', '5'],\n                                ['FEA2', '6'],\n                                ['FEA3', '7'],\n                                ['FEA4', '8'],\n                                ['REA1', '9'],\n                                ['REA2', '10'],\n                                ['REA3', '11'],\n                                ['REA4', '12'],\n                                ['BEA1', '13'],\n                                ['BEA2', '14'],\n                                ['BEA3', '15'],\n                                ['BEA4', '16'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['A1', '1'],\n                                            ['A2', '2'],\n                                            ['A3', '3'],\n                                            ['A4', '4'],\n                                            ['FEA1', '5'],\n                                            ['FEA2', '6'],\n                                            ['FEA3', '7'],\n                                            ['FEA4', '8'],\n                                            ['REA1', '9'],\n                                            ['REA2', '10'],\n                                            ['REA3', '11'],\n                                            ['REA4', '12'],\n                                            ['BEA1', '13'],\n                                            ['BEA2', '14'],\n                                            ['BEA3', '15'],\n                                            ['BEA4', '16'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_digital_key',\n                            },\n                        ],\n                    }\n                },\n                technicpowerlite_dropdown_analog_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['AA1', '1'],\n                                ['AA2', '2'],\n                                ['AA3', '3'],\n                                ['AA4', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['AA1', '1'],\n                                            ['AA2', '2'],\n                                            ['AA3', '3'],\n                                            ['AA4', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_analog_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_setting_sensor_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_switch, '1'],\n                                [Lang.template.technicpowerlite_item_infrared, '2'],\n                                [Lang.template.technicpowerlite_item_magnetic, '3'],\n                                [Lang.template.technicpowerlite_item_rotation, '4'],\n                                [Lang.template.technicpowerlite_item_color, '5'],\n                                // [Lang.template.technicpowerlite_item_acceleration, '6'],     // 테크닉 에서 사용하지 않음\n                                [Lang.template.technicpowerlite_item_ultrasonic, '7'],\n                                [Lang.template.technicpowerlite_item_heart_rate, '8'],\n                                [Lang.template.technicpowerlite_item_illuminance, '9'],\n                                [Lang.template.technicpowerlite_item_sound, '10'],\n                                [Lang.template.technicpowerlite_item_tilt, '11'],\n                                [Lang.template.technicpowerlite_item_pressure, '12'],\n                                // [Lang.template.technicpowerlite_item_multi_touch, '13'],      // 테크닉 에서 사용하지 않음\n                                // [Lang.template.technicpowerlite_item_compass, '14'],          // 테크닉 에서 사용하지 않음\n                                // [Lang.template.technicpowerlite_item_tri_acceleration, '15'], // 테크닉 에서 사용하지 않음\n                                // [Lang.template.technicpowerlite_item_multi_switch, '16'],     // 테크닉 에서 사용하지 않음\n                                // [Lang.template.technicpowerlite_item_extension_input, '17'], // 테크닉 에서 사용하지 않음\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_switch, '1'],\n                                            [Lang.template.technicpowerlite_item_infrared, '2'],\n                                            [Lang.template.technicpowerlite_item_magnetic, '3'],\n                                            [Lang.template.technicpowerlite_item_rotation, '4'],\n                                            [Lang.template.technicpowerlite_item_color, '5'],\n                                            // [Lang.template.technicpowerlite_item_acceleration, '6'],     // 테크닉 에서 사용하지 않음\n                                            [Lang.template.technicpowerlite_item_ultrasonic, '7'],\n                                            [Lang.template.technicpowerlite_item_heart_rate, '8'],\n                                            [Lang.template.technicpowerlite_item_illuminance, '9'],\n                                            [Lang.template.technicpowerlite_item_sound, '10'],\n                                            [Lang.template.technicpowerlite_item_tilt, '11'],\n                                            [Lang.template.technicpowerlite_item_pressure, '12'],\n                                            // [Lang.template.technicpowerlite_item_multi_touch, '13'],      // 테크닉 에서 사용하지 않음\n                                            // [Lang.template.technicpowerlite_item_compass, '14'],          // 테크닉 에서 사용하지 않음\n                                            // [Lang.template.technicpowerlite_item_tri_acceleration, '15'], // 테크닉 에서 사용하지 않음\n                                            // [Lang.template.technicpowerlite_item_multi_switch, '16'],     // 테크닉 에서 사용하지 않음\n                                            // [Lang.template.technicpowerlite_item_extension_input, '17'], // 테크닉 에서 사용하지 않음\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_setting_sensor_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_inNcom_sensor_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_infinite_rotation, '1'],\n                                //[Lang.template.technicpowerlite_item_compass, '2'], // 테크닉 에서 사용하지 않음\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_infinite_rotation, '1'],\n                                            [Lang.template.technicpowerlite_item_compass, '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_inNcom_sensor_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_sensor_color_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_color_red, '1'],\n                                [Lang.template.technicpowerlite_item_color_green, '2'],\n                                [Lang.template.technicpowerlite_item_color_blue, '3'],\n                                [Lang.template.technicpowerlite_item_color_yellow, '4'],\n                                [Lang.template.technicpowerlite_item_color_black, '5'],\n                                [Lang.template.technicpowerlite_item_color_white, '6'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_color_red, '1'],\n                                            [Lang.template.technicpowerlite_item_color_green, '2'],\n                                            [Lang.template.technicpowerlite_item_color_blue, '3'],\n                                            [Lang.template.technicpowerlite_item_color_yellow, '4'],\n                                            [Lang.template.technicpowerlite_item_color_black, '5'],\n                                            [Lang.template.technicpowerlite_item_color_white, '6'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_sensor_color_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_rgb_color_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_color_red, '1'],\n                                [Lang.template.technicpowerlite_item_color_green, '2'],\n                                [Lang.template.technicpowerlite_item_color_blue, '3'],\n                                [Lang.template.technicpowerlite_item_color_cyan, '4'],\n                                [Lang.template.technicpowerlite_item_color_magenta, '5'],\n                                [Lang.template.technicpowerlite_item_color_yellow, '6'],\n                                [Lang.template.technicpowerlite_item_color_white, '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_color_red, '1'],\n                                            [Lang.template.technicpowerlite_item_color_green, '2'],\n                                            [Lang.template.technicpowerlite_item_color_blue, '3'],\n                                            [Lang.template.technicpowerlite_item_color_cyan, '4'],\n                                            [Lang.template.technicpowerlite_item_color_magenta, '5'],\n                                            [Lang.template.technicpowerlite_item_color_yellow, '6'],\n                                            [Lang.template.technicpowerlite_item_color_white, '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_rgb_color_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_sensor_angle_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_value, '1'],\n                                [Lang.template.technicpowerlite_item_angle, '2'],\n                                [Lang.template.technicpowerlite_item_absolute_angle, '3'],\n                                [Lang.template.technicpowerlite_item_number_of_rotations, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_value, '1'],\n                                            [Lang.template.technicpowerlite_item_angle, '2'],\n                                            [Lang.template.technicpowerlite_item_absolute_angle, '3'],\n                                            [Lang.template.technicpowerlite_item_number_of_rotations, '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_sensor_angle_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_multikey_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_key_1, '1'],\n                                [Lang.template.technicpowerlite_item_key_2, '2'],\n                                [Lang.template.technicpowerlite_item_key_3, '3'],\n                                [Lang.template.technicpowerlite_item_key_4, '4'],\n                                [Lang.template.technicpowerlite_item_key_5, '5'],\n                                [Lang.template.technicpowerlite_item_key_6, '6'],\n                                [Lang.template.technicpowerlite_item_key_7, '7'],\n                                [Lang.template.technicpowerlite_item_key_8, '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_key_1, '1'],\n                                            [Lang.template.technicpowerlite_item_key_2, '2'],\n                                            [Lang.template.technicpowerlite_item_key_3, '3'],\n                                            [Lang.template.technicpowerlite_item_key_4, '4'],\n                                            [Lang.template.technicpowerlite_item_key_5, '5'],\n                                            [Lang.template.technicpowerlite_item_key_6, '6'],\n                                            [Lang.template.technicpowerlite_item_key_7, '7'],\n                                            [Lang.template.technicpowerlite_item_key_8, '8'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_multikey_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_extension_digital_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['EA1', '1'],\n                                ['EA2', '2'],\n                                ['EA3', '3'],\n                                ['EA4', '4'],\n                                ['EA5', '5'],\n                                ['EA6', '6'],\n                                ['EA7', '7'],\n                                ['EA8', '8'],\n                                ['ET1', '9'],\n                                ['ET2', '10'],\n                                ['ET3', '11'],\n                                ['ET4', '12'],\n                                ['ET5', '13'],\n                                ['ET6', '14'],\n                                ['ET7', '15'],\n                                ['ET8', '16'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['EA1', '1'],\n                                            ['EA2', '2'],\n                                            ['EA3', '3'],\n                                            ['EA4', '4'],\n                                            ['EA5', '5'],\n                                            ['EA6', '6'],\n                                            ['EA7', '7'],\n                                            ['EA8', '8'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_extension_digital_key',\n                            },\n                        ],\n                    },\n                },                \n                technicpowerlite_dropdown_extension_analog_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['EAA1', '1'],\n                                ['EAA2', '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['EAA1', '1'],\n                                            ['EAA2', '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_extension_analog_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_dc_1_all_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['1,2', '5'],\n                                ['3,4', '6'],\n                                [Lang.template.technicpowerlite_item_all, '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['1,2', '5'],\n                                            ['3,4', '6'],\n                                            [Lang.template.technicpowerlite_item_all, '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_dc_1_all_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_velocity_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['20', '20'],\n                                ['15', '15'],\n                                ['10', '10'],\n                                ['5', '5'],\n                                ['0', '0'],\n                                ['-5', '-5'],\n                                ['-10', '-10'],\n                                ['-15', '-15'],\n                                ['-20', '-20'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['20', '20'],\n                                            ['15', '15'],\n                                            ['10', '10'],\n                                            ['5', '5'],\n                                            ['0', '0'],\n                                            ['-5', '-5'],\n                                            ['-10', '-10'],\n                                            ['-15', '-15'],\n                                            ['-20', '-20'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_velocity_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_servo_position_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['20', '20'],\n                                ['40', '40'],\n                                ['60', '60'],\n                                ['80', '80'],\n                                ['100', '100'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },                    \n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['20', '20'],\n                                            ['40', '40'],\n                                            ['60', '60'],\n                                            ['80', '80'],\n                                            ['100', '100'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_servo_position_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_port_1_4_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_port_1_4_key',\n                            },\n                        ],\n                    },\n                },           \n                technicpowerlite_dropdown_on_off_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_on, '1'],\n                                [Lang.template.technicpowerlite_item_off, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    events: {},\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_on, '1'],\n                                            [Lang.template.technicpowerlite_item_off, '0'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_on_off_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_note_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_note_whole, '1'],\n                                [Lang.template.technicpowerlite_item_note_half, '2'],\n                                [Lang.template.technicpowerlite_item_note_quarter, '4'],\n                                [Lang.template.technicpowerlite_item_note_eighth, '8'],\n                                [Lang.template.technicpowerlite_item_note_sixteenth, '16'],\n                                [Lang.template.technicpowerlite_item_note_thirty_second, '32'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_note_whole, '1'],\n                                            [Lang.template.technicpowerlite_item_note_half, '2'],\n                                            [Lang.template.technicpowerlite_item_note_quarter, '4'],\n                                            [Lang.template.technicpowerlite_item_note_eighth, '8'],\n                                            [Lang.template.technicpowerlite_item_note_sixteenth, '16'],\n                                            [Lang.template.technicpowerlite_item_note_thirty_second, '32'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_note_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_time_1_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.1', '0.1'],\n                                ['0.3', '0.3'],\n                                ['0.5', '0.5'],\n                                ['0.7', '0.7'],\n                                ['1', '1'],\n                                ['2', '2'],\n                            ],\n                            value: '0.5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.1', '0.1'],\n                                            ['0.3', '0.3'],\n                                            ['0.5', '0.5'],\n                                            ['0.7', '0.7'],\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                        ],\n                                        value: '0.5',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_time_1_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_time_2_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.1', '0.1'],\n                                ['0.3', '0.3'],\n                                ['0.5', '0.5'],\n                                ['0.7', '0.7'],\n                                ['1', '1'],\n                                ['2', '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.1', '0.1'],\n                                            ['0.3', '0.3'],\n                                            ['0.5', '0.5'],\n                                            ['0.7', '0.7'],\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_time_2_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_time_3: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0.05', '0.05'],\n                                ['0.1', '0.1'],\n                                ['0.2', '0.2'],\n                                ['0.5', '0.5'],\n                                ['1', '1'],\n                            ],\n                            value: '0.5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0.05', '0.05'],\n                                            ['0.1', '0.1'],\n                                            ['0.2', '0.2'],\n                                            ['0.5', '0.5'],\n                                            ['1', '1'],\n                                        ],\n                                        value: '0.5',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_time_3',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_pitch_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'DropdownExtra',\n                            options: [\n                                [Lang.template.technicpowerlite_item_pitch_do + ' (36)', '36'],\n                                [Lang.template.technicpowerlite_item_pitch_do_sharp + ' (37)', '37'],\n                                [Lang.template.technicpowerlite_item_pitch_re + ' (38)', '38'],\n                                [Lang.template.technicpowerlite_item_pitch_re_sharp + ' (39)', '39'],\n                                [Lang.template.technicpowerlite_item_pitch_mi + ' (40)', '40'],\n                                [Lang.template.technicpowerlite_item_pitch_fa + ' (41)', '41'],\n                                [Lang.template.technicpowerlite_item_pitch_fa_sharp + ' (42)', '42'],\n                                [Lang.template.technicpowerlite_item_pitch_sol + ' (43)', '43'],\n                                [Lang.template.technicpowerlite_item_pitch_sol_sharp + ' (44)', '44'],\n                                [Lang.template.technicpowerlite_item_pitch_ra + ' (45)', '45'],\n                                [Lang.template.technicpowerlite_item_pitch_ra_sharp + ' (46)', '46'],\n                                [Lang.template.technicpowerlite_item_pitch_si + ' (47)', '47'],\n        \n                                [Lang.template.technicpowerlite_item_pitch_do + ' (48)', '48'],\n                                [Lang.template.technicpowerlite_item_pitch_do_sharp + ' (49)', '49'],\n                                [Lang.template.technicpowerlite_item_pitch_re + ' (50)', '50'],\n                                [Lang.template.technicpowerlite_item_pitch_re_sharp + ' (51)', '51'],\n                                [Lang.template.technicpowerlite_item_pitch_mi + ' (52)', '52'],\n                                [Lang.template.technicpowerlite_item_pitch_fa + ' (53)', '53'],\n                                [Lang.template.technicpowerlite_item_pitch_fa_sharp + ' (54)', '54'],\n                                [Lang.template.technicpowerlite_item_pitch_sol + ' (55)', '55'],\n                                [Lang.template.technicpowerlite_item_pitch_sol_sharp + ' (56)', '56'],\n                                [Lang.template.technicpowerlite_item_pitch_ra + ' (57)', '57'],\n                                [Lang.template.technicpowerlite_item_pitch_ra_sharp + ' (58)', '58'],\n                                [Lang.template.technicpowerlite_item_pitch_si + ' (59)', '59'],\n        \n                                [Lang.template.technicpowerlite_item_pitch_do + ' (60)', '60'],\n                                [Lang.template.technicpowerlite_item_pitch_do_sharp + ' (61)', '61'],\n                                [Lang.template.technicpowerlite_item_pitch_re + ' (62)', '62'],\n                                [Lang.template.technicpowerlite_item_pitch_re_sharp + ' (63)', '63'],\n                                [Lang.template.technicpowerlite_item_pitch_mi + ' (64)', '64'],\n                                [Lang.template.technicpowerlite_item_pitch_fa + ' (65)', '65'],\n                                [Lang.template.technicpowerlite_item_pitch_fa_sharp + ' (66)', '66'],\n                                [Lang.template.technicpowerlite_item_pitch_sol + ' (67)', '67'],\n                                [Lang.template.technicpowerlite_item_pitch_sol_sharp + ' (68)', '68'],\n                                [Lang.template.technicpowerlite_item_pitch_ra + ' (69)', '69'],\n                                [Lang.template.technicpowerlite_item_pitch_ra_sharp + ' (70)', '70'],\n                                [Lang.template.technicpowerlite_item_pitch_si + ' (71)', '71'],\n        \n                                [Lang.template.technicpowerlite_item_pitch_do + ' (72)', '72'],\n                                [Lang.template.technicpowerlite_item_pitch_do_sharp + ' (73)', '73'],\n                                [Lang.template.technicpowerlite_item_pitch_re + ' (74)', '74'],\n                                [Lang.template.technicpowerlite_item_pitch_re_sharp + ' (75)', '75'],\n                                [Lang.template.technicpowerlite_item_pitch_mi + ' (76)', '76'],\n                                [Lang.template.technicpowerlite_item_pitch_fa + ' (77)', '77'],\n                                [Lang.template.technicpowerlite_item_pitch_fa_sharp + ' (78)', '78'],\n                                [Lang.template.technicpowerlite_item_pitch_sol + ' (79)', '79'],\n                                [Lang.template.technicpowerlite_item_pitch_sol_sharp + ' (80)', '80'],\n                                [Lang.template.technicpowerlite_item_pitch_ra + ' (81)', '81'],\n                                [Lang.template.technicpowerlite_item_pitch_ra_sharp + ' (82)', '82'],\n                                [Lang.template.technicpowerlite_item_pitch_si + ' (83)', '83'],\n                            ],\n                            value: '60',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        const value = script.getStringField('PARAM0');\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_pitch_do + ' (36)', '36'],\n                                            [Lang.template.technicpowerlite_item_pitch_do_sharp + ' (37)', '37'],\n                                            [Lang.template.technicpowerlite_item_pitch_re + ' (38)', '38'],\n                                            [Lang.template.technicpowerlite_item_pitch_re_sharp + ' (39)', '39'],\n                                            [Lang.template.technicpowerlite_item_pitch_mi + ' (40)', '40'],\n                                            [Lang.template.technicpowerlite_item_pitch_fa + ' (41)', '41'],\n                                            [Lang.template.technicpowerlite_item_pitch_fa_sharp + ' (42)', '42'],\n                                            [Lang.template.technicpowerlite_item_pitch_sol + ' (43)', '43'],\n                                            [Lang.template.technicpowerlite_item_pitch_sol_sharp + ' (44)', '44'],\n                                            [Lang.template.technicpowerlite_item_pitch_ra + ' (45)', '45'],\n                                            [Lang.template.technicpowerlite_item_pitch_ra_sharp + ' (46)', '46'],\n                                            [Lang.template.technicpowerlite_item_pitch_si + ' (47)', '47'],\n                    \n                                            [Lang.template.technicpowerlite_item_pitch_do + ' (48)', '48'],\n                                            [Lang.template.technicpowerlite_item_pitch_do_sharp + ' (49)', '49'],\n                                            [Lang.template.technicpowerlite_item_pitch_re + ' (50)', '50'],\n                                            [Lang.template.technicpowerlite_item_pitch_re_sharp + ' (51)', '51'],\n                                            [Lang.template.technicpowerlite_item_pitch_mi + ' (52)', '52'],\n                                            [Lang.template.technicpowerlite_item_pitch_fa + ' (53)', '53'],\n                                            [Lang.template.technicpowerlite_item_pitch_fa_sharp + ' (54)', '54'],\n                                            [Lang.template.technicpowerlite_item_pitch_sol + ' (55)', '55'],\n                                            [Lang.template.technicpowerlite_item_pitch_sol_sharp + ' (56)', '56'],\n                                            [Lang.template.technicpowerlite_item_pitch_ra + ' (57)', '57'],\n                                            [Lang.template.technicpowerlite_item_pitch_ra_sharp + ' (58)', '58'],\n                                            [Lang.template.technicpowerlite_item_pitch_si + ' (59)', '59'],\n                    \n                                            [Lang.template.technicpowerlite_item_pitch_do + ' (60)', '60'],\n                                            [Lang.template.technicpowerlite_item_pitch_do_sharp + ' (61)', '61'],\n                                            [Lang.template.technicpowerlite_item_pitch_re + ' (62)', '62'],\n                                            [Lang.template.technicpowerlite_item_pitch_re_sharp + ' (63)', '63'],\n                                            [Lang.template.technicpowerlite_item_pitch_mi + ' (64)', '64'],\n                                            [Lang.template.technicpowerlite_item_pitch_fa + ' (65)', '65'],\n                                            [Lang.template.technicpowerlite_item_pitch_fa_sharp + ' (66)', '66'],\n                                            [Lang.template.technicpowerlite_item_pitch_sol + ' (67)', '67'],\n                                            [Lang.template.technicpowerlite_item_pitch_sol_sharp + ' (68)', '68'],\n                                            [Lang.template.technicpowerlite_item_pitch_ra + ' (69)', '69'],\n                                            [Lang.template.technicpowerlite_item_pitch_ra_sharp + ' (70)', '70'],\n                                            [Lang.template.technicpowerlite_item_pitch_si + ' (71)', '71'],\n                    \n                                            [Lang.template.technicpowerlite_item_pitch_do + ' (72)', '72'],\n                                            [Lang.template.technicpowerlite_item_pitch_do_sharp + ' (73)', '73'],\n                                            [Lang.template.technicpowerlite_item_pitch_re + ' (74)', '74'],\n                                            [Lang.template.technicpowerlite_item_pitch_re_sharp + ' (75)', '75'],\n                                            [Lang.template.technicpowerlite_item_pitch_mi + ' (76)', '76'],\n                                            [Lang.template.technicpowerlite_item_pitch_fa + ' (77)', '77'],\n                                            [Lang.template.technicpowerlite_item_pitch_fa_sharp + ' (78)', '78'],\n                                            [Lang.template.technicpowerlite_item_pitch_sol + ' (79)', '79'],\n                                            [Lang.template.technicpowerlite_item_pitch_sol_sharp + ' (80)', '80'],\n                                            [Lang.template.technicpowerlite_item_pitch_ra + ' (81)', '81'],\n                                            [Lang.template.technicpowerlite_item_pitch_ra_sharp + ' (82)', '82'],\n                                            [Lang.template.technicpowerlite_item_pitch_si + ' (83)', '83'],\n                                        ],\n                                        value: '60',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_pitch_key',\n                            },\n                        ],\n                    },\n                },\n                technicpowerlite_dropdown_melody_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.template.technicpowerlite_item_melody_start, '1'],\n                                [Lang.template.technicpowerlite_item_melody_end, '2'],\n                                [Lang.template.technicpowerlite_item_melody_level_up, '3'],\n                                [Lang.template.technicpowerlite_item_melody_level_down, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    func: function(sprite, script) {\n                        return script.getStringField('PARAM0');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.template.technicpowerlite_item_melody_start, '1'],\n                                            [Lang.template.technicpowerlite_item_melody_end, '2'],\n                                            [Lang.template.technicpowerlite_item_melody_level_up, '3'],\n                                            [Lang.template.technicpowerlite_item_melody_level_down, '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'technicpowerlite_dropdown_melody_key',\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Event block\n                ///========================================================================================                \n                // %1 리모컨 %2 키를 눌렀을 때\n                technicpowerlite_when_press_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: {\n                                x: 0,\n                                y: -2,\n                            },\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'technicpowerlite_dropdown_remote_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_when_press_remote_key',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_event',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    event: 'technicpowerlite_event_remote_input',\n                    func(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getRemoteKey(script.getStringValue('PARAM1'));\n                        return (Entry.ProboTechnicPowerLite.InputData.Remote[key] === 1)\n                            ? script.callReturn()\n                            : this.die();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.when_press_remote_key(%2)',\n                                blockType: 'event',\n                                passTest: true,\n                                textParams: [\n                                    undefined,\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 디지털 입력 %2 이(가) 들어왔을 때\n                technicpowerlite_when_input_digital_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: {\n                                x: 0,\n                                y: -2,\n                            },\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'technicpowerlite_dropdown_digital_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_when_input_digital_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_event',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    event: 'technicpowerlite_event_digital_input',\n                    func(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getDigitalKey(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboTechnicPowerLite.getDigitalStateValue(key);\n                        return (value)\n                            ? script.callReturn()\n                            : this.die();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.when_input_digital_value(%2)',\n                                blockType: 'event',\n                                passTest: true,\n                                textParams: [\n                                    undefined,\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Setting Block\n                ///========================================================================================               \n                // 입력포트 %1 을(를) %2 센서로 설정 %3\n                technicpowerlite_set_senser_setting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_setting_sensor_key',\n                            },\n                            null,\n                        ],\n                        type: 'technicpowerlite_set_senser_setting',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_setting',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicPowerLite.getSettingSensorValue(script.getStringValue('PARAM1'));\n                        const sensorSet = Entry.ProboTechnicPowerLite.SenserSet;\n                        sensorSet[key] = value;\n                        Entry.ProboTechnicPowerLite.RemoteData.ASET2 = ((sensorSet.AA1 << 4) | sensorSet.AA2) & 0xFF;\n                        Entry.ProboTechnicPowerLite.RemoteData.ASET1 = ((sensorSet.AA3 << 4) | sensorSet.AA4) & 0xFF;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_sensor_setting(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                ///========================================================================================\n                /// Input block\n                ///========================================================================================\n                // 리모컨 입력 %1\n                technicpowerlite_is_remote_key: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_remote_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_is_remote_key',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getRemoteKey(script.getStringValue('PARAM0'));\n                        return (Entry.ProboTechnicPowerLite.InputData.Remote[key] === 1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.is_remote_key(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 디지털 입력 %1\n                technicpowerlite_is_digital_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_digital_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_is_digital_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getDigitalKey(script.getStringValue('PARAM0'));\n                        return Entry.ProboTechnicPowerLite.getDigitalStateValue(key);;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.is_digital_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 아날로그 입력 %1\n                technicpowerlite_get_analog_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_get_analog_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        return  (Entry.ProboTechnicPowerLite.SenserSet[key] === 5)  // 5: 압력\n                            ? 255 - Entry.ProboTechnicPowerLite.InputData.Analog[key]\n                            : Entry.ProboTechnicPowerLite.InputData.Analog[key];\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_analog_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 3가속도 %1의 X축\n                technicpowerlite_get_tri_axis_acceler_x: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_get_tri_axis_acceler_x',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAxisKey(script.getStringValue('PARAM0'), \"X\");\n                        const value = Entry.ProboTechnicPowerLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_tri_axis_acceler_x(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },                        \n                // 3가속도 %1의 Y축\n                technicpowerlite_get_tri_axis_acceler_y: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_get_tri_axis_acceler_y',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAxisKey(script.getStringValue('PARAM0'),\"Y\");\n                        const value = Entry.ProboTechnicPowerLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_tri_axis_acceler_y(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 3가속도 %1의 Z축\n                technicpowerlite_get_tri_axis_acceler_z: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_get_tri_axis_acceler_z',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAxisKey(script.getStringValue('PARAM0'), \"Z\");\n                        const value = Entry.ProboTechnicPowerLite.InputData.Acceler[key];\n                        return (value & 0x80)\n                            ? Number((value - 255) / 10).toFixed(1)\n                            : Number(value / 10).toFixed(1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_tri_axis_acceler_z(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                \n                // %1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환\n                technicpowerlite_get_value_mapping: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 255 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            {\n                                type: 'number',\n                                params: [ 100 ],\n                            },\n                        ],\n                        type: 'technicpowerlite_get_value_mapping',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                        PARAM2: 2,\n                        PARAM3: 3,\n                        PARAM4: 4,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const inMin = script.getNumberValue('PARAM1');\n                        const inMax = script.getNumberValue('PARAM2');\n                        const outMin = script.getNumberValue('PARAM3');\n                        const outMax = script.getNumberValue('PARAM4');\n                        const data = (Entry.ProboTechnicPowerLite.SenserSet[key] === 5) // 5: 압력\n                            ? 255 - Entry.ProboTechnicPowerLite.InputData.Analog[key]\n                            : Entry.ProboTechnicPowerLite.InputData.Analog[key];\n                        return (data - inMin) * (outMax-outMin) / (inMax - inMin) + outMin;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_value_mapping(%1, %2, %3, %4, %5)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },                \n                // 컬러 센서 %1 이(가) %2 인가?\n                technicpowerlite_is_color_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_sensor_color_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_is_color_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const key1 = Entry.ProboTechnicPowerLite.getColorSensorKey(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboTechnicPowerLite.InputData.Analog[key0];\n                        const color = Entry.ProboTechnicPowerLite.Color;\n                        return ((color[key1].Min <= value) && (value <= color[key1].Max));\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.is_color_value(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 컬러 센서 %1 의 색상\n                technicpowerlite_get_color_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [                    \n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_get_color_value',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicPowerLite.InputData.Analog[key0];\n                        const color = Entry.ProboTechnicPowerLite.Color;\n                        \n                        for (let i = 1; i < 7; i++) {\n                            const key1 =  Entry.ProboTechnicPowerLite.getColorSensorKey(i.toString());\n                            if ((color[key1].Min <= value) && (value <= color[key1].Max)) {\n                                switch (i) {\n                                    case 1:\n                                        return Lang.template.technicpowerlite_item_color_red;\n                                    case 2:\n                                        return Lang.template.technicpowerlite_item_color_green;\n                                    case 3:\n                                        return Lang.template.technicpowerlite_item_color_blue;\n                                    case 4:\n                                        return Lang.template.technicpowerlite_item_color_yellow;\n                                    case 5:\n                                        return Lang.template.technicpowerlite_item_color_black;\n                                    case 6:\n                                        return Lang.template.technicpowerlite_item_color_white;\n                                    default:\n                                        return Lang.template.technicpowerlite_item_error;\n                                }\n                            }\n                        }\n\n                        return Lang.template.technicpowerlite_item_nothing;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_color_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 을 %3 값으로 정하기 %4\n                technicpowerlite_set_infinite_setting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        }\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_set_infinite_setting',\n                    },\n                    paramsKeyMap: {\n                        //PARAM0: 0, // 0을 쓰지 않음\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        let count = 0;\n                        let value = script.getNumberValue('PARAM2');\n                        \n                        if (value != 0) {\n                            count = Math.floor(value / 255);\n                            value = value % 255;\n                        } else {\n                            count = 0;\n                            value = 0;\n                        }\n                        \n                        Entry.ProboTechnicPowerLite.Infinite.Buff[key] = Entry.ProboTechnicPowerLite.InputData.Analog[key];\n                        Entry.ProboTechnicPowerLite.Infinite.Start[key] = Entry.ProboTechnicPowerLite.InputData.Analog[key] - value;\n                        Entry.ProboTechnicPowerLite.Infinite.Count[key] = count;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_infinite_setting(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 지름 %3 의 mm 값\n                technicpowerlite_get_infinite_mm_diameter: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'number',\n                                params: [ 53.5 ],\n                            },\n                        ],\n                        type: 'technicpowerlite_get_infinite_mm_diameter',\n                    },\n                    paramsKeyMap: {\n                        //PARAM0: 0, // 0을 쓰지 않음\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        const radius = script.getNumberValue('PARAM2') / 2;\n                        const pi = 3.141592;\n                        const infinite = Entry.ProboTechnicPowerLite.Infinite;\n                        let value = Entry.ProboTechnicPowerLite.InputData.Analog[key];\n\n                        if (value < infinite.Buff[key] - 150) {\n                            infinite.Count[key]++;\n                        } else if (value > infinite.Buff[key] + 150) {\n                            infinite.Count[key]--;\n                        }                    \n                        infinite.Buff[key] = value;\n                        value = (infinite.Buff[key] - infinite.Start[key]) + (infinite.Count[key] * 255);\n\n                        return Number((2 * pi * radius) / 255 * value).toFixed(3);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_infinite_mm_diameter(%1, %2, %3)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 센서 %2 의  %3\n                technicpowerlite_get_infinite_transform_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [                    \n                            {\n                                type: 'technicpowerlite_dropdown_inNcom_sensor_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_sensor_angle_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_get_infinite_transform_input',\n                    },\n                    paramsKeyMap: {\n                        //PARAM0: 0, // 0을 쓰지 않음\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key1 = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM1'));\n                        const key2 = Entry.ProboTechnicPowerLite.getSensorAngleKey(script.getStringValue('PARAM2'));\n                        const anlogValue = Entry.ProboTechnicPowerLite.InputData.Analog[key1];\n                        const infinite = Entry.ProboTechnicPowerLite.Infinite;\n\n                        if (anlogValue < (infinite.Buff[key1] - 150)) {\n                            infinite.Count[key1]++;\n                        } else if (anlogValue > (infinite.Buff[key1] + 150)) {\n                            infinite.Count[key1]--;\n                        }\n                        infinite.Buff[key1] = anlogValue;\n                        const value = (infinite.Buff[key1] - infinite.Start[key1]) + (infinite.Count[key1] * 255);\n\n                        switch (key2) {\n                            case 'IS1':\n                                return value;\n                            case 'IS2':\n                                return (value > 0)\n                                    ? Math.floor((value % 255) * 1.41732)\n                                    : Math.ceil((value % 255) * 1.41732)\n                            case 'IS3':\n                                return Number((360 / 255) * anlogValue).toFixed(0);\n                            case 'IS4':\n                                return (value > 0)\n                                    ? Math.floor(value / 255)\n                                    : Math.ceil(value / 255);\n                            default:\n                                return Lang.template.technicpowerlite_item_nothing;\n\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_infinite_transform_input(%1, %2, %3)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 멀티키 센서 %1의 %2\n                technicpowerlite_is_multi_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_multikey_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_is_multi_sensor',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicPowerLite.getMultiKeyValue(script.getStringValue('PARAM1'));\n                        return (Entry.ProboTechnicPowerLite.InputData.Analog[key] >> value) & 0x01;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.is_multi_sensor(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 분배 스위치 %1의 %2\n                technicpowerlite_is_multi_switch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_multikey_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_is_multi_switch',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key0 = Entry.ProboTechnicPowerLite.getAnalogKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicPowerLite.getMultiKeyValue(script.getStringValue('PARAM1'));\n                        const analog = Entry.ProboTechnicPowerLite.InputData.Analog[key0];\n                        const multySwitch = Entry.ProboTechnicPowerLite.MultiSwitch;\n                        \n                        for (let i = 0; i < 8; i++) {\n                            const key = 'Key' + (i + 1).toString();\n                            if (multySwitch[key].Min <= analog && analog <= multySwitch[key].Max) {\n                                return (value === i);\n                            }\n                        }\n                        \n                        return false;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.is_multi_switch(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 확장 디지털 입력 %1 의 %2\n                technicpowerlite_is_extension_digital_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_extension_digital_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_is_extension_digital_input',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getAxisKey(script.getStringValue('PARAM0'), 'X');\n                        const shift = Entry.ProboTechnicPowerLite.getExtentionDigitalValue(script.getStringValue('PARAM1'));\n                        const value = Entry.ProboTechnicPowerLite.InputData.Acceler[key];\n                        return ((value >> shift) === 1);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.is_extension_digital_input(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },                \n                // 확장 아날로그 입력 %1 의 %2\n                technicpowerlite_get_extension_analog_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'technicpowerlite_dropdown_analog_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_extension_analog_key',\n                            },\n                        ],\n                        type: 'technicpowerlite_get_extension_analog_input',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {                        \n                        const key = Entry.ProboTechnicPowerLite.getAxisKey(\n                            script.getStringValue('PARAM0'),\n                            Entry.ProboTechnicPowerLite.getExtentionAnalogKey(script.getStringValue('PARAM1'))\n                        );\n                        const value = Entry.ProboTechnicPowerLite.InputData.Acceler[key];\n                        return value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_extension_analog_input(%1, %2)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM %1 주소의 값 호출하기 %2\n                technicpowerlite_set_eeprom_call: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',                    \n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0']\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_set_eeprom_call',\n                    },\n                    paramsKeyMap: {\n                        ADDRESS: 0,\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const address = script.getNumberValue('ADDRESS', script);\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const ms = 50;\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboTechnicPowerLite.EEPROM.Count = Entry.ProboTechnicPowerLite.InputData.EEPROM.EC;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR4'] = 0x40;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR3'] = address;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicPowerLite.EEPROM.Buff =\n                                (Entry.ProboTechnicPowerLite.InputData.EEPROM.EEPR2 << 8) + \n                                Entry.ProboTechnicPowerLite.InputData.EEPROM.EEPR1;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR4'] = 0;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR3'] = 0;\n\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_eeprom_call(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM 주소의 값\n                technicpowerlite_get_eeprom_address_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'technicpowerlite_get_eeprom_address_value',\n                    },\n                    class: 'technicpowerlite_input',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const count = Entry.ProboTechnicPowerLite.EEPROM.Count;\n\n                        return (Entry.ProboTechnicPowerLite.InputData.EEPROM.EC != count)\n                            ? Entry.ProboTechnicPowerLite.EEPROM.Buff\n                            : 0;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.get_eeprom_address_value',\n                                blockType: 'param',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n                \n                ///========================================================================================\n                /// output block\n                ///========================================================================================\n                // DC 모터 %1 을(를) %2 속도로 회전 %3\n                technicpowerlite_set_dc_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_dc_1_all_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_velocity_key',\n                            },\n                            null,\n                        ],\n                        type: 'technicpowerlite_set_dc_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getDckey(script.getStringValue('PARAM0')); \n                        const value = script.getNumberValue('PARAM1');\n\n                        switch (key) {\n                            case 'DC5':\n                                Entry.ProboTechnicPowerLite.RemoteData['DC1'] = value;\n                                Entry.ProboTechnicPowerLite.RemoteData['DC2'] = value;\n                                break;\n                            case 'DC6':\n                                Entry.ProboTechnicPowerLite.RemoteData['DC3'] = value;\n                                Entry.ProboTechnicPowerLite.RemoteData['DC4'] = value;\n                                break;\n                            case 'DC7':\n                                Entry.ProboTechnicPowerLite.RemoteData['DC1'] = value;\n                                Entry.ProboTechnicPowerLite.RemoteData['DC2'] = value;\n                                Entry.ProboTechnicPowerLite.RemoteData['DC3'] = value;\n                                Entry.ProboTechnicPowerLite.RemoteData['DC4'] = value;\n                                break;\n                            default:\n                                Entry.ProboTechnicPowerLite.RemoteData[key] = value;\n                                break;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_dc_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 서보 모터 %1 의 위치를 %2 로 이동 %3\n                technicpowerlite_set_servo_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_servo_position_key',\n                            },\n                            null,\n                        ],\n                        type: 'technicpowerlite_set_servo_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = script.getNumberValue('PARAM1');\n                        Entry.ProboTechnicPowerLite.RemoteData[key] = Math.min(Math.max(value, 0), 100);\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_servo_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // S 모터 %1 을(를) %2 속도로 회전 %3\n                technicpowerlite_set_s_dc_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_velocity_key',\n                            },\n                            null,\n                        ],\n                        type: 'technicpowerlite_set_s_dc_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getServoKey(script.getStringValue('PARAM0'));\n                        const speed = script.getNumberValue('PARAM1');\n                        const value = Math.min(Math.max(speed, -20), 20) + 148;\n\n                        switch (key) {\n                            case 'Servo5':\n                                Entry.ProboTechnicPowerLite.RemoteData['Servo1'] = value;\n                                Entry.ProboTechnicPowerLite.RemoteData['Servo2'] = value;\n                                break;\n                            case 'Servo6':\n                                Entry.ProboTechnicPowerLite.RemoteData['Servo3'] = value;\n                                Entry.ProboTechnicPowerLite.RemoteData['Servo4'] = value;\n                                break;\n                            default:\n                                Entry.ProboTechnicPowerLite.RemoteData[key] = value;\n                                break;\n                        }\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_s_dc_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 출력핀 %1 을(를) %2 %3\n                technicpowerlite_set_port_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_on_off_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_set_port_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getPortKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicPowerLite.getPortToggleValue(script.getStringValue('PARAM1'));\n        \n                        Entry.ProboTechnicPowerLite.RemoteData[key] = value;\n\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_port_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2 음표로 연주하기 %3\n                technicpowerlite_play_melody_note_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_pitch_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_note_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_play_melody_note_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            const pitch = Entry.ProboTechnicPowerLite.getPitchValue(script.getNumberValue('PARAM0'));\n                            const note = Entry.ProboTechnicPowerLite.getNoteKey(script.getStringValue('PARAM1'));\n                            const ms = Entry.ProboTechnicPowerLite.Note[note];\n                            const fps = Entry.FPS || 60;\n        \n                            Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = pitch >> 8;\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = pitch;        \n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = 0;\n        \n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.play_melody_note_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2 초 동안 연주하기 %3\n                technicpowerlite_play_melody_sec_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_pitch_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_time_1_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_play_melody_sec_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            const pitch = Entry.ProboTechnicPowerLite.getPitchValue(script.getNumberValue('PARAM0'));\n                            const sec = script.getNumberValue('PARAM1');        \n                            const fps = Entry.FPS || 60;\n                           \n                            Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = pitch >> 8;\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = pitch;        \n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = 0;\n        \n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.play_melody_sec_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) 연주하기 %2\n                technicpowerlite_play_melody_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [                \n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_pitch_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_play_melody_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const pitch = Entry.ProboTechnicPowerLite.getPitchValue(script.getNumberValue('PARAM0'));        \n                        Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = pitch >> 8;\n                        Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = pitch;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.play_melody_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 값을(를) %2 초 동안 연주하기 %3\n                technicpowerlite_play_value_sec_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 35391 ],\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_time_1_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_play_value_sec_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n        \n                            const melody = script.getNumberValue('PARAM0');\n                            const sec = script.getNumberValue('PARAM1');\n                            const fps = Entry.FPS || 60;\n        \n                            Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = melody & 0xff;        \n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = 0;\n        \n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.play_melody_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 1 값을(를) 연주하기 %2\n                technicpowerlite_play_value_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 35391 ],\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_play_value_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const melody = script.getNumberValue('PARAM0');\n                        Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                        Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = melody & 0xff;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.play_melody_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // %1 을(를) %2초 간격으로 재생하기 %3\n                technicpowerlite_play_melody_track_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_melody_key',\n                            },\n                            { \n                                type: 'technicpowerlite_dropdown_time_2_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_play_melody_track_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        function getTrackStep(track,script){\n                            if(!script.isStart){\n                                script.isStart = true;\n                                script.trackStep = 0;\n                            }\n                            else {\n                                script.trackStep++;\n                            }\n                            const sec = script.getNumberValue('PARAM1');\n                            const fps = Entry.FPS || 60;\n                            const melody = Entry.ProboTechnicPowerLite.Track[track][script.trackStep];\n\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = (melody >> 8) & 0xff;\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = melody & 0xff;        \n                            script.timeFlag = 1;        \n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * sec * 1000\n                            );\n                        }\n                        const TR = Entry.ProboTechnicPowerLite.getMelodyValue(\n                            script.getStringValue('PARAM0')\n                        );\n                        if (!script.isStart) {\n                            switch(TR) {\n                                case 0 :\n                                    script.maxStep = 6;\n                                    break;\n                                case 1 :\n                                    script.maxStep = 7;\n                                    break;\n                                case 2 :\n                                    script.maxStep = 3;\n                                    break;\n                                case 3 :\n                                    script.maxStep = 3;\n                                    break;\n                            }\n                            getTrackStep(TR,script);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else if (script.trackStep < script.maxStep){\n                            getTrackStep(TR,script);\n                            return script;\n                        } else {\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = 0;\n                            Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = 0;\n        \n                            delete script.trackStep;\n                            delete script.maxStep;\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.play_melody_track_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // 멜로디 중지 %1\n                technicpowerlite_play_melody_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [ null ],\n                        type: 'technicpowerlite_play_melody_off',\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        Entry.ProboTechnicPowerLite.RemoteData['MEL2'] = 0;\n                        Entry.ProboTechnicPowerLite.RemoteData['MEL1'] = 0;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.play_melody_track_output',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 을(를) %2 으로 켜기 %3\n                technicpowerlite_set_rgbled_on_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_port_1_4_key',\n                            },\n                            {\n                                type: 'technicpowerlite_dropdown_rgb_color_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_set_rgbled_on_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicPowerLite.getRgbToggleValue(script.getStringValue('PARAM1'));\n                        Entry.ProboTechnicPowerLite.RemoteData[key] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_rgbled_on_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },    \n                // RGB LED %1 을(를) 끄기 %2\n                technicpowerlite_set_rgbled_off_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_port_1_4_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_set_rgbled_off_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicPowerLite.getRgbToggleValue('0');\n                        Entry.ProboTechnicPowerLite.RemoteData[key] = value;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_rgbled_off_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 %2 으로 %3 초 간격 %4\n                technicpowerlite_set_rgbled_flashing_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_port_1_4_key',\n                            },\n                            { \n                                type: 'technicpowerlite_dropdown_rgb_color_key',\n                            },\n                            { \n                                type: 'technicpowerlite_dropdown_time_3',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_set_rgbled_flashing_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                        PARAM2: 2,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getServoKey(script.getStringValue('PARAM0'));\n                        const value = Entry.ProboTechnicPowerLite.getRgbTwinkleValue(\n                            script.getStringValue('PARAM1'),\n                            script.getNumberValue('PARAM2')\n                        );\n                        Entry.ProboTechnicPowerLite.RemoteData[key] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_rgbled_flashing_output(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // RGB LED %1 을(를) %2 으로 디밍 %3\n                technicpowerlite_set_rgbled_dimming_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'technicpowerlite_dropdown_port_1_4_key',\n                            },\n                            { \n                                type: 'technicpowerlite_dropdown_rgb_color_key',\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_set_rgbled_dimming_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const key = Entry.ProboTechnicPowerLite.getServoKey(script.getStringValue('PARAM0'));\n                        const color = Entry.ProboTechnicPowerLite.getRgbDimmingValue(script.getStringValue('PARAM1'));\n                        Entry.ProboTechnicPowerLite.RemoteData[key] = color;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_rgbled_dimming_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // FND를 %1 (으)로 설정 %2\n                technicpowerlite_set_fnd_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: [ 0 ],\n                            },\n                            null\n                        ],\n                        type: 'technicpowerlite_set_fnd_output',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const value = script.getNumberValue('PARAM0');\n                        Entry.ProboTechnicPowerLite.RemoteData['FND'] = value;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_fnd_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                // FND 끄기 %1\n                technicpowerlite_set_fnd_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null\n                        ],\n                        type: 'technicpowerlite_set_fnd_off',\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        Entry.ProboTechnicPowerLite.RemoteData['FND'] = 100;\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_fnd_off',\n                                textParams: [ null ],\n                            },\n                        ],\n                    },\n                },\n                // EEPROM %1 주소에 %2 값 설정하기 %3\n                technicpowerlite_set_eeprom_write: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',                    \n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            { \n                                type: 'number',\n                                params: [ 0 ]\n                            },\n                            {\n                                type: 'number',\n                                params: [ 0 ]\n                            },\n                            null,\n                        ],\n                        type: 'technicpowerlite_set_eeprom_write',\n                    },\n                    paramsKeyMap: {\n                        PARAM0: 0,\n                        PARAM1: 1,\n                    },\n                    class: 'technicpowerlite_output',\n                    isNotFor: ['ProboTechnicPowerLite'],\n                    func: function(sprite, script) {\n                        const address = script.getNumberValue('PARAM0');\n                        const value = script.getNumberValue('PARAM1');\n\n                        if (!script.isStart) {        \n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const ms = 50;\n                            const fps = Entry.FPS || 60;\n\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR4'] = 0x80;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR3'] = address;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR2'] = (value >> 8) & 0xff;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR1'] = value & 0xff;\n                            Entry.TimeWaitManager.add(\n                                script.block.id,\n                                function() {\n                                    script.timeFlag = 0;\n                                },\n                                60 / fps * ms\n                            );\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR4'] = 0x40;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR3'] = address;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR2'] = 0;\n                            Entry.ProboTechnicPowerLite.RemoteData['EEPR1'] = 0;\n        \n                            setTimeout(function() {\n                                Entry.ProboTechnicPowerLite.RemoteData['EEPR4'] = 0;\n                                Entry.ProboTechnicPowerLite.RemoteData['EEPR3'] = 0;\n                                Entry.ProboTechnicPowerLite.RemoteData['EEPR2'] = 0;\n                                Entry.ProboTechnicPowerLite.RemoteData['EEPR1'] = 0;\n                            }, 100);\n                            \n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ProboTechnicPowerLite.set_eeprom_write(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n            }; // getBlock() return;\n        }\n    })();\n})();\n\nmodule.exports = Entry.ProboTechnicPowerLite;"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_arduino_lite.js",
    "content": "'use strict';\n\n// - 라이프사이클 재점검\n// - Entry.hw 부분 Entry.hwLite로 수정\n// - portData 파라미터 확인\n// - 모니터링 로직 확인\n\nimport _range from 'lodash/range';\n\n(function() {\n    Entry.ArduinoLite = new (class ArduinoLite {\n        constructor() {\n            this.id = '010101';\n            this.name = 'ArduinoLite';\n            this.url = 'http://www.arduino.cc/';\n            this.imageName = 'arduinolite.png';\n            this.title = {\n                ko: '아두이노 우노',\n                en: 'Arduino Uno',\n            };\n            // duration도 미확인\n            this.duration = 32;\n            this.blockMenuBlocks = [\n                'arduinolite_get_number_sensor_value',\n                'arduinolite_get_digital_value',\n                'arduinolite_toggle_led',\n                'arduinolite_toggle_pwm',\n                'arduinolite_convert_scale',\n            ];\n            this.portData = {\n                baudRate: 9600,\n                duration: 32,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n            };\n            this.readablePorts = [];\n            this.remainValue = null;\n            this.setZero();\n        }\n\n        setZero() {\n            this.port = new Array(14).fill(0);\n            this.digitalValue = new Array(14).fill(0);\n            this.remoteDigitalValue = new Array(14).fill(0);\n            this.analogValue = new Array(6).fill(0);\n            this.readablePorts = _range(0, 19);\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        // 디바이스에서 값을 읽어온다.\n        handleLocalData(data) {\n            // data: Native Buffer\n            for (let i = 0; i < 32; i++) {\n                let chunk;\n                if (!this.remainValue) {\n                    chunk = data[i];\n                } else {\n                    chunk = this.remainValue;\n                    i--;\n                }\n                if (chunk >> 7) {\n                    if ((chunk >> 6) & 1) {\n                        const nextChunk = data[i + 1];\n                        if (!nextChunk && nextChunk !== 0) {\n                            this.remainValue = chunk;\n                        } else {\n                            this.remainValue = null;\n\n                            const port = (chunk >> 3) & 7;\n                            this.analogValue[port] = ((chunk & 7) << 7) + (nextChunk & 127);\n                        }\n                        i++;\n                    } else {\n                        const port = (chunk >> 2) & 15;\n                        this.digitalValue[port] = chunk & 1;\n                    }\n                }\n            }\n        }\n\n        //디바이스에 값을 쓴다.\n        requestLocalData() {\n            const queryString = [];\n            const readablePorts = this.readablePorts;\n\n            if (readablePorts) {\n                for (const i in readablePorts) {\n                    const query = (5 << 5) + (readablePorts[i] << 1);\n                    queryString.push(query);\n                }\n            }\n            const readablePortsValues = (readablePorts && Object.values(readablePorts)) || [];\n            for (let port = 0; port < 14; port++) {\n                if (readablePortsValues.indexOf(port) > -1) {\n                    continue;\n                }\n                const value = this.remoteDigitalValue[port];\n                if (value === 255 || value === 0) {\n                    const query = (7 << 5) + (port << 1) + (value == 255 ? 1 : 0);\n                    queryString.push(query);\n                } else if (value > 0 && value < 255) {\n                    let query = (6 << 5) + (port << 1) + (value >> 7);\n                    queryString.push(query);\n                    query = value & 127;\n                    queryString.push(query);\n                }\n            }\n            return queryString;\n        }\n\n        addReadablePort(port) {\n            const idx = Entry.ArduinoLite.readablePorts.indexOf(port);\n            if (idx === -1) {\n                Entry.ArduinoLite.readablePorts.push(port);\n            }\n        }\n\n        removeReadablePort(port) {\n            const idx = Entry.ArduinoLite.readablePorts.indexOf(port);\n            if (idx >= 0) {\n                Entry.ArduinoLite.readablePorts.splice(idx, 1);\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        arduinolite_text: '%1',\n                        arduinolite_get_sensor_number: '%1',\n                        arduinolite_get_port_number: '%1',\n                        arduinolite_get_pwm_port_number: '%1',\n                        arduinolite_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                        arduinolite_get_digital_value: '디지털 %1 번 센서값  ',\n                        arduinolite_toggle_led: '디지털 %1 번 핀 %2 %3',\n                        arduinolite_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                        arduinolite_convert_scale:\n                            '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                    },\n                    Device: {\n                        arduinolite: '아두이노',\n                    },\n                    Menus: {\n                        arduinolite: '아두이노',\n                    },\n                },\n                en: {\n                    template: {\n                        arduinolite_text: '%1',\n                        arduinolite_get_sensor_number: '%1',\n                        arduinolite_get_port_number: '%1',\n                        arduinolite_get_pwm_port_number: '%1',\n                        arduinolite_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                        arduinolite_get_digital_value: 'Digital %1 Sensor value  ',\n                        arduinolite_toggle_led: 'Digital %1 Pin %2 %3',\n                        arduinolite_toggle_pwm: 'Digital %1 Pin %2 %3',\n                        arduinolite_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n                    },\n                    Device: {\n                        arduinolite: 'arduinolite',\n                    },\n                    Menus: {\n                        arduinolite: 'ArduinoLite',\n                    },\n                },\n            };\n        }\n\n        getBlocks() {\n            return {\n                //region arduino 아두이노\n                arduinolite_text: {\n                    color: '#FFD974',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'TextInput',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['10'],\n                    },\n                    paramsKeyMap: {\n                        NAME: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getStringField('NAME');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'TextInput',\n                                        value: 10,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                keyOption: 'arduinolite_text',\n                            },\n                        ],\n                    },\n                },\n                arduinolite_get_sensor_number: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0', 'A0'],\n                                ['1', 'A1'],\n                                ['2', 'A2'],\n                                ['3', 'A3'],\n                                ['4', 'A4'],\n                                ['5', 'A5'],\n                            ],\n                            value: 'A0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getStringField('PORT');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0', 'A0'],\n                                            ['1', 'A1'],\n                                            ['2', 'A2'],\n                                            ['3', 'A3'],\n                                            ['4', 'A4'],\n                                            ['5', 'A5'],\n                                        ],\n                                        value: 'A0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                keyOption: 'arduinolite_get_sensor_number',\n                            },\n                        ],\n                    },\n                },\n                arduinolite_get_port_number: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0', '0'],\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                                ['8', '8'],\n                                ['9', '9'],\n                                ['10', '10'],\n                                ['11', '11'],\n                                ['12', '12'],\n                                ['13', '13'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getStringField('PORT');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['0', '0'],\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                            ['8', '8'],\n                                            ['9', '9'],\n                                            ['10', '10'],\n                                            ['11', '11'],\n                                            ['12', '12'],\n                                            ['13', '13'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    },\n                                ],\n                                keyOption: 'arduinolite_get_port_number',\n                            },\n                        ],\n                    },\n                },\n                arduinolite_get_pwm_port_number: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['3', '3'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['9', '9'],\n                                ['10', '10'],\n                                ['11', '11'],\n                            ],\n                            value: '3',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getStringField('PORT');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['3', '3'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['9', '9'],\n                                            ['10', '10'],\n                                            ['11', '11'],\n                                        ],\n                                        value: '3',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                keyOption: 'arduinolite_get_pwm_port_number',\n                            },\n                        ],\n                    },\n                },\n                arduinolite_get_number_sensor_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'arduinolite_get_sensor_number',\n                            },\n                        ],\n                        type: 'arduinolite_get_number_sensor_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'arduino_value',\n                    isNotFor: ['ArduinoLite'],\n                    func(sprite, script) {\n                        // const signal = script.getValue('VALUE', script);\n                        // return Entry.hw.getAnalogPortValue(signal[1]);\n                        return Entry.ArduinoLite.analogValue[\n                            script.getNumberValue('VALUE', script)\n                        ];\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ArduinoLite.sensor_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                arduinolite_get_digital_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'arduinolite_get_port_number',\n                            },\n                        ],\n                        type: 'arduinolite_get_digital_value',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'arduino_value',\n                    isNotFor: ['ArduinoLite'],\n                    func(sprite, script) {\n                        if (Entry.hwLite.hwModule.name === 'ArduinoExtLite') {\n                            console.log('ArduinoExtLite is not supported');\n                            // TO-DO : 아두이노 확장 웹연결 지원시 추가\n                            // return Entry.block.arduinolite_ext_get_digital.func(sprite, script);\n                        } else {\n                            const port = script.getNumberValue('PORT', script);\n                            Entry.ArduinoLite.addReadablePort(port);\n                            return Entry.ArduinoLite.digitalValue[port];\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ArduinoLite.digitalRead(%1)',\n                                blockType: 'param',\n                                replaceBlockType: 'arduinolite_ext_get_digital',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                arduinolite_toggle_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.ARDUINO_on, 'on'],\n                                [Lang.Blocks.ARDUINO_off, 'off'],\n                            ],\n                            value: 'on',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'arduinolite_get_port_number',\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'arduinolite_toggle_led',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                        OPERATOR: 1,\n                    },\n                    class: 'arduino_set',\n                    isNotFor: ['ArduinoLite'],\n                    func(sprite, script) {\n                        const port = script.getNumberValue('VALUE');\n                        const operator = script.getField('OPERATOR');\n                        const value = operator == 'on' ? 255 : 0;\n                        Entry.ArduinoLite.remoteDigitalValue[port] = value;\n                        Entry.ArduinoLite.removeReadablePort(port);\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ArduinoLite.pin_digital(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.ARDUINO_on, 'on'],\n                                            [Lang.Blocks.ARDUINO_off, 'off'],\n                                        ],\n                                        value: 'on',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                arduinolite_toggle_pwm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'arduinolite_get_pwm_port_number',\n                            },\n                            {\n                                type: 'arduinolite_text',\n                                params: ['255'],\n                            },\n                            null,\n                        ],\n                        type: 'arduinolite_toggle_pwm',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                    },\n                    class: 'arduino_set',\n                    isNotFor: ['ArduinoLite'],\n                    func(sprite, script) {\n                        const port = script.getNumberValue('PORT');\n                        let value = script.getNumberValue('VALUE');\n                        value = Math.round(value);\n                        value = Math.max(value, 0);\n                        value = Math.min(value, 255);\n                        Entry.ArduinoLite.remoteDigitalValue[port] = value;\n                        Entry.ArduinoLite.removeReadablePort(port);\n                        return script.callReturn();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ArduinoLite.set_pin_digital(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                arduinolite_convert_scale: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'arduinolite_get_number_sensor_value',\n                                params: [\n                                    {\n                                        type: 'arduinolite_get_sensor_number',\n                                        id: 'bl5e',\n                                    },\n                                ],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['1023'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                        ],\n                        type: 'arduinolite_convert_scale',\n                    },\n                    paramsKeyMap: {\n                        VALUE1: 0,\n                        VALUE2: 1,\n                        VALUE3: 2,\n                        VALUE4: 3,\n                        VALUE5: 4,\n                    },\n                    class: 'arduino',\n                    isNotFor: ['ArduinoLite'],\n                    func(sprite, script) {\n                        const value1 = script.getNumberValue('VALUE1', script);\n                        let value2 = script.getNumberValue('VALUE2', script);\n                        let value3 = script.getNumberValue('VALUE3', script);\n                        let value4 = script.getNumberValue('VALUE4', script);\n                        let value5 = script.getNumberValue('VALUE5', script);\n\n                        const stringValue4 = script.getValue('VALUE4', script);\n                        const stringValue5 = script.getValue('VALUE5', script);\n                        let isFloat = false;\n\n                        if (\n                            (Entry.Utils.isNumber(stringValue4) &&\n                                stringValue4.indexOf('.') > -1) ||\n                            (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                        ) {\n                            isFloat = true;\n                        }\n\n                        let result = value1;\n                        if (value2 > value3) {\n                            const swap = value2;\n                            value2 = value3;\n                            value3 = swap;\n                        }\n                        if (value4 > value5) {\n                            const swap = value4;\n                            value4 = value5;\n                            value5 = swap;\n                        }\n                        result -= value2;\n                        result = result * ((value5 - value4) / (value3 - value2));\n                        result += value4;\n                        result = Math.min(value5, result);\n                        result = Math.max(value4, result);\n\n                        if (isFloat) {\n                            result = Math.round(result * 100) / 100;\n                        } else {\n                            result = Math.round(result);\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'ArduinoLite.convert_scale(%1, %2, %3, %4, %5)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                //endregion arduino 아두이노\n            };\n        }\n    })();\n})();\n\nmodule.exports = Entry.ArduinoLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_choco_lite.js",
    "content": "'use strict';\nconst Buffer = require('buffer').Buffer;\n\n(function() {\n    Entry.ChocoLite = new (class ChocoLite {\n        constructor() {\n            this.id = '450101';\n            this.name = 'ChocoLite';\n            this.url = 'http://jjomulrak.com';\n            this.imageName = 'chocolite.png';\n            this.title = {\n                ko: '쪼코',\n                en: 'Choco',\n            };\n            this.duration = 32;\n            this.blockMenuBlocks = [\n                'chocolite_move_forward',\n                'chocolite_move_backward',\n                'chocolite_turn_left',\n                'chocolite_turn_right',\n                'chocolite_move_right_left',\n                'chocolite_onoff_led_rear',\n                'chocolite_set_led_color',\n                'chocolite_play_sound',\n                'chocolite_is_front_sensor',\n                'chocolite_is_bottom_sensor',\n                'chocolite_is_light_sensor',\n                'chocolite_get_front_sensor',\n                'chocolite_get_bottom_sensor',\n                'chocolite_get_light_sensor',\n            ];\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n                connectionType: 'bytestream',\n            };\n\n            // prettier-ignore\n            this.crctab16 = new Uint16Array([\n                0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF,\n                0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7,\n                0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E,\n                0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876,\n                0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD,\n                0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5,\n                0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C,\n                0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974,\n                0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB,\n                0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3,\n                0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A,\n                0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72,\n                0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9,\n                0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1,\n                0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738,\n                0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70,\n                0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7,\n                0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF,\n                0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036,\n                0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E,\n                0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5,\n                0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD,\n                0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134,\n                0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C,\n                0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3,\n                0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB,\n                0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232,\n                0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A,\n                0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1,\n                0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9,\n                0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330,\n                0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78,\n            ]);\n\n            this.SEND_PACKET = {\n                START: 0x7c,\n                END: 0x7e,\n            };\n\n            this.cmdSeq = 0;\n            this.isSendInitData = 'none';\n\n            this.sendBuffers = [];\n            this.recvBuffers = [];\n            this.executeCmd = {\n                processing: 'none',\n                cb: null,\n            };\n\n            this.sensorData = {\n                is_front_sensor: false,\n                is_bottom_sensor: false,\n                is_light_sensor: false,\n                front_sensor: 0,\n                bottom_sensor: 0,\n                light_sensor: 0,\n            };\n\n            this.sensorInit = {\n                inited: 'none',\n                sensor0: {\n                    min: 0,\n                    max: 0,\n                    threshold: 0,\n                },\n                sensor1: {\n                    min: 0,\n                    max: 0,\n                    threshold: 0,\n                },\n                sensor2: {\n                    min: 0,\n                    max: 0,\n                    threshold: 0,\n                },\n            };\n\n            this.ledStatus = [0, 0, 0]; //right, left, rear\n\n            this.setZero();\n        }\n\n        // get monitorTemplate() {\n        //     return {\n        //         imgPath: 'hw_lite/choco2.png',\n        //         width: 256,\n        //         height: 256,\n        //         listPorts: {\n        //             '2': {\n        //                 name: `${Lang.Hw.port_en} 2 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '3': {\n        //                 name: `${Lang.Hw.port_en} 3 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '4': {\n        //                 name: `${Lang.Hw.port_en} 4 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '5': {\n        //                 name: `${Lang.Hw.port_en} 5 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '6': {\n        //                 name: `${Lang.Hw.port_en} 6 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '7': {\n        //                 name: `${Lang.Hw.port_en} 7 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '8': {\n        //                 name: `${Lang.Hw.port_en} 8 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '9': {\n        //                 name: `${Lang.Hw.port_en} 9 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '10': {\n        //                 name: `${Lang.Hw.port_en} 10 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '11': {\n        //                 name: `${Lang.Hw.port_en} 11 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '12': {\n        //                 name: `${Lang.Hw.port_en} 12 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             '13': {\n        //                 name: `${Lang.Hw.port_en} 13 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             a0: {\n        //                 name: `${Lang.Hw.port_en} A0 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             a1: {\n        //                 name: `${Lang.Hw.port_en} A1 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             a2: {\n        //                 name: `${Lang.Hw.port_en} A2 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             a3: {\n        //                 name: `${Lang.Hw.port_en} A3 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             a4: {\n        //                 name: `${Lang.Hw.port_en} A4 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //             a5: {\n        //                 name: `${Lang.Hw.port_en} A5 ${Lang.Hw.port_ko}`,\n        //                 type: 'input',\n        //                 pos: { x: 0, y: 0 },\n        //             },\n        //         },\n        //         mode: 'both',\n        //     };\n        // }\n\n        // getMonitorPort() {\n        //     return {\n        //         //TODO : 통신때마다 모니터되는 포트 업데이트 하기위해 현재 포트값들 리턴\n        //     }\n        // }\n\n        setZero() {\n            this.cmdSeq = 0;\n            this.isSendInitData = 'none';\n\n            this.sendBuffers = [];\n            this.recvBuffers = [];\n            this.executeCmd = {\n                processing: 'none',\n                cb: null,\n            };\n\n            this.sensorData = {\n                is_front_sensor: false,\n                is_bottom_sensor: false,\n                is_light_sensor: false,\n                front_sensor: 0,\n                bottom_sensor: 0,\n                light_sensor: 0,\n            };\n\n            this.sensorInit = {\n                inited: 'none',\n                sensor0: {\n                    min: 0,\n                    max: 0,\n                    threshold: 0,\n                },\n                sensor1: {\n                    min: 0,\n                    max: 0,\n                    threshold: 0,\n                },\n                sensor2: {\n                    min: 0,\n                    max: 0,\n                    threshold: 0,\n                },\n            };\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        _addRecvData(value) {\n            let parsed = false;\n            let startIdx = 0;\n            this.recvBuffers = this.recvBuffers.concat(...value);\n            for (let i = 0; i < this.recvBuffers.length; i++) {\n                if (this.recvBuffers[i] === this.SEND_PACKET.END) {\n                    if (this.recvBuffers[0] === this.SEND_PACKET.START) {\n                        this._parseRecvData(this.recvBuffers.slice(startIdx, i + 1));\n                        this.recvBuffers.splice(0, i + 1);\n                        parsed = true;\n                        break;\n                    }\n                    this.recvBuffers.splice(0, i + 1);\n                    startIdx = i;\n                }\n            }\n            return parsed;\n        }\n\n        _parseRecvData(data) {\n            if (data.length > 12 && data[0] === this.SEND_PACKET.START) {\n                const idx = data.indexOf(this.SEND_PACKET.END);\n                if (idx > 0) {\n                    const decodedData = this.escapeEecode(data.slice(1, idx));\n\n                    const command = decodedData.readUInt8(0);\n                    const seqNo = decodedData.readUInt8(1);\n                    const sensor0 = decodedData.readUInt16LE(2);\n                    const sensor1 = decodedData.readUInt16LE(4);\n                    const sensor2 = decodedData.readUInt16LE(6);\n\n                    this.sensorData.front_sensor = sensor0;\n                    this.sensorData.bottom_sensor = sensor1;\n                    this.sensorData.light_sensor = sensor2;\n\n                    if (decodedData.length === 29) {\n                        this.sensorInit.inited = 'inited';\n                        this.sensorInit.sensor0.min = decodedData.readUInt16LE(9);\n                        this.sensorInit.sensor0.max = decodedData.readUInt16LE(11);\n                        this.sensorInit.sensor0.threshold = decodedData.readUInt16LE(13);\n                        this.sensorInit.sensor1.min = decodedData.readUInt16LE(15);\n                        this.sensorInit.sensor1.max = decodedData.readUInt16LE(17);\n                        this.sensorInit.sensor1.threshold = decodedData.readUInt16LE(19);\n                        this.sensorInit.sensor2.min = decodedData.readUInt16LE(21);\n                        this.sensorInit.sensor2.max = decodedData.readUInt16LE(23);\n                        this.sensorInit.sensor2.threshold = decodedData.readUInt16LE(25);\n\n                        // console.log(\n                        //     `Sensor inited`,\n                        //     `${this.sensorInit.sensor0.min},`,\n                        //     `${this.sensorInit.sensor0.max},`,\n                        //     `${this.sensorInit.sensor0.threshold}`\n                        // );\n                    }\n                    if (this.sensorInit.inited === 'inited') {\n                        if (this.sensorData.front_sensor < this.sensorInit.sensor0.min) {\n                            this.sensorData.front_sensor = this.sensorInit.sensor0.min;\n                        }\n                        if (this.sensorData.front_sensor > this.sensorInit.sensor0.max) {\n                            this.sensorData.front_sensor = this.sensorInit.sensor0.max;\n                        }\n                        if (this.sensorData.bottom_sensor < this.sensorInit.sensor1.min) {\n                            this.sensorData.bottom_sensor = this.sensorInit.sensor1.min;\n                        }\n                        if (this.sensorData.bottom_sensor > this.sensorInit.sensor1.max) {\n                            this.sensorData.bottom_sensor = this.sensorInit.sensor1.max;\n                        }\n                        if (this.sensorData.light_sensor < this.sensorInit.sensor2.min) {\n                            this.sensorData.light_sensor = this.sensorInit.sensor2.min;\n                        }\n                        if (this.sensorData.light_sensor > this.sensorInit.sensor2.max) {\n                            this.sensorData.light_sensor = this.sensorInit.sensor2.max;\n                        }\n                        this.sensorData.is_front_sensor =\n                            this.sensorData.front_sensor < this.sensorInit.sensor0.threshold;\n                        this.sensorData.is_bottom_sensor =\n                            this.sensorData.bottom_sensor > this.sensorInit.sensor1.threshold;\n                        this.sensorData.is_light_sensor =\n                            this.sensorData.light_sensor < this.sensorInit.sensor2.threshold;\n\n                        let fVal = this.sensorData.front_sensor;\n                        const fMin = this.sensorInit.sensor0.min;\n                        const fMmax = this.sensorInit.sensor0.max;\n                        fVal = ((fVal - fMin) * 100) / (fMmax - fMin);\n\n                        let bVal = this.sensorData.bottom_sensor;\n                        const bMin = this.sensorInit.sensor1.min;\n                        const bMmax = this.sensorInit.sensor1.max;\n                        bVal = ((bVal - bMin) * 100) / (bMmax - bMin);\n\n                        let lVal = this.sensorData.light_sensor;\n                        const lMin = this.sensorInit.sensor2.min;\n                        const lMmax = this.sensorInit.sensor2.max;\n                        lVal = ((lVal - lMin) * 100) / (lMmax - lMin);\n\n                        this.sensorData.front_sensor = parseInt(fVal, 10);\n                        if (this.sensorData.front_sensor < 0) {\n                            this.sensorData.front_sensor = 0;\n                        } else if (this.sensorData.front_sensor > 100) {\n                            this.sensorData.front_sensor = 100;\n                        }\n                        this.sensorData.bottom_sensor = parseInt(bVal, 10);\n                        if (this.sensorData.bottom_sensor < 0) {\n                            this.sensorData.bottom_sensor = 0;\n                        } else if (this.sensorData.bottom_sensor > 100) {\n                            this.sensorData.bottom_sensor = 100;\n                        }\n                        this.sensorData.light_sensor = parseInt(lVal, 10);\n                        if (this.sensorData.light_sensor < 0) {\n                            this.sensorData.light_sensor = 0;\n                        } else if (this.sensorData.light_sensor > 100) {\n                            this.sensorData.light_sensor = 100;\n                        }\n                    }\n\n                    // console.log(\n                    //     `command:${command}, len: ${decodedData.length}`,\n                    //     `data:${data.toString('hex')}, seqNo:${seqNo}`,\n                    //     `${sensor0},${sensor1},${sensor2}`,\n                    //     `${this.sensorData.is_front_sensor},`,\n                    //     `${this.sensorData.is_bottom_sensor},`,\n                    //     `${this.sensorData.is_light_sensor}`,\n                    //     `${this.sensorData.front_sensor},`,\n                    //     `${this.sensorData.bottom_sensor},`,\n                    //     `${this.sensorData.light_sensor}`\n                    // );\n                    if (command === 0x02 && this.executeCmd.processing === 'started') {\n                        this.executeCmd.processing = 'done';\n                        if (this.executeCmd.cb) {\n                            this.executeCmd.cb();\n                            this.executeCmd.cb = null;\n                        }\n                    }\n\n                    if (this.isSendInitData === 'sent') {\n                        this.isSendInitData = 'inited';\n                    }\n                }\n            }\n        }\n\n        // 디바이스에서 값을 읽어온다.\n        handleLocalData(data) {\n            this._addRecvData(data);\n        }\n\n        //디바이스에 값을 쓴다.\n        requestLocalData() {\n            if (this.executeCmd.processing === 'none' || this.executeCmd.processing === 'done') {\n                if (this.sendBuffers.length > 0) {\n                    const cmd = this.sendBuffers.shift();\n\n                    this.executeCmd.cb = cmd.cb;\n                    this.executeCmd.processing = 'started';\n                    return cmd.sendData;\n                }\n            }\n\n            return null;\n        }\n\n        async initialHandshake() {\n            this.recvBuffers = [];\n            const cmdReady = this.makeData({\n                type: 'ready',\n            });\n            this.sensorInit.inited = 'sent';\n            // this.sensorInit.inited 가 inited 될 때까지 기다린다.\n            while (this.sensorInit.inited === 'sent') {\n                //parsed되었는데 상태가 변경안되면.. 다시 요청을 보낸다.\n                this.log('Send Data:ready');\n                await Entry.hwLite.serial.sendAsync(cmdReady, false, (value) => {\n                    this._addRecvData(value);\n                });\n            }\n\n            this.recvBuffers = [];\n            const cmdPing = this.makeData({\n                type: 'ping2',\n            });\n            this.ledStatus = [0, 0, 0];\n            this.isSendInitData = 'sent';\n            await Entry.hwLite.serial.sendAsync(cmdPing);\n\n            while (this.isSendInitData === 'sent') {\n                // this.isSendInitData 가 inited 될 때까지 기다린다.\n                this.log('Send Data:ping2');\n                await Entry.hwLite.serial.sendAsync(cmdPing, false, (value) => {\n                    this._addRecvData(value);\n                });\n            }\n            return true;\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        chocolite_move_forward: '앞으로 %1 %2 이동 %3',\n                        chocolite_move_backward: '뒤로 %1 %2 이동 %3',\n                        chocolite_turn_left: '왼쪽으로 %1 %2 돌기 %3',\n                        chocolite_turn_right: '오른쪽으로 %1 %2 돌기 %3',\n                        chocolite_move_right_left: '오른쪽으로 %1 왼쪽으로 %2 %3 이동 %4',\n                        chocolite_onoff_led_rear: '뒤쪽 LED %1 %2',\n                        chocolite_set_led_color: '%1 LED %2 %3',\n                        chocolite_play_sound: '%1 소리내기 %2',\n                        chocolite_is_front_sensor: '전방센서',\n                        chocolite_is_bottom_sensor: '바닥센서',\n                        chocolite_is_light_sensor: '빛센서',\n                        chocolite_get_front_sensor: '전방센서',\n                        chocolite_get_bottom_sensor: '바닥센서',\n                        chocolite_get_light_sensor: '빛센서',\n                    },\n                    Blocks: {\n                        chocolite_move_step: '칸',\n                        chocolite_move_cm: 'cm',\n                        chocolite_trun_drgree: '도',\n                        chocolite_trun_round: '바퀴',\n                        chocolite_toggle_on: '켜기',\n                        chocolite_toggle_off: '끄기',\n                        chocolite_direction_right: '오른쪽',\n                        chocolite_direction_left: '왼쪽',\n                        chocolite_direction_dual: '양쪽(오른쪽,왼쪽)',\n\n                        chocolite_color_off: '끄기',\n                        chocolite_color_blue: '파란색',\n                        chocolite_color_red: '빨간색',\n                        chocolite_color_green: '초록색',\n                        chocolite_color_yellow: '노랑색',\n                        chocolite_color_pink: '분홍색',\n                        chocolite_color_bluegreen: '청록색',\n                        chocolite_color_white: '흰색',\n\n                        chocolite_sound_car: '자동차',\n                        chocolite_sound_robot: '로봇',\n                        chocolite_sound_dog: '강아지',\n                        chocolite_sound_cat: '고양이',\n                        chocolite_sound_chicken: '닭',\n                        chocolite_sound_tiger: '호랑이',\n                        chocolite_sound_lion: '사자',\n                        chocolite_sound_fart: '방귀소리',\n                        chocolite_sound_helicopter: '헬리콥터',\n                        chocolite_sound_train: '기차',\n                        chocolite_sound_frog: '개구리',\n                        chocolite_sound_jjajan: '짜잔(효과음)',\n                        chocolite_sound_sheep: '양',\n                        chocolite_sound_elephant: '코끼리',\n                        chocolite_sound_camel: '낙타',\n                        chocolite_sound_dolphin: '고래',\n                        chocolite_sound_ttiyong: '띠용(효과음)',\n                        chocolite_sound_hello_parrot: '헬로(앵무새)',\n                        chocolite_sound_hello_manga: '헬로(만화)',\n                        chocolite_sound_hello_man: '헬로(남자)',\n                        chocolite_sound_ppong: '뽕(효과음)',\n                        chocolite_sound_buzzer: '부저(효과음)',\n                        chocolite_sound_ttalilalan: '따라리라란~(효과음)',\n                        chocolite_sound_ttattattatta: '따따따따~(효과음)',\n                        chocolite_sound_laughter: '웃음소리',\n                        chocolite_sound_magic: '마술(효과음)',\n                        chocolite_sound_woodpecker: '딱따구리',\n                        chocolite_sound_bird: '새',\n                        chocolite_sound_burp: '트림',\n                        chocolite_sound_hiccup: '딸꾹질',\n                        chocolite_sound_doridori: '도리도리',\n                        chocolite_sound_firetruck: '소방차',\n                        chocolite_sound_police_car: '경찰차',\n                        chocolite_sound_applause: '박수환호',\n                        chocolite_sound_kiss: '뽀뽀',\n                        chocolite_sound_missile: '미사일',\n                        chocolite_sound_angry_duck: '화난오리',\n                        chocolite_sound_fly: '파리',\n                        chocolite_sound_ufo: 'UFO',\n                        chocolite_sound_fanfare: '팡파레',\n                        chocolite_sound_sigh: '한숨소리',\n                        chocolite_sound_alright: '올라잇~',\n                        chocolite_sound_genius: '지니어스~',\n                        chocolite_sound_no: '노우~',\n                        chocolite_sound_wow: '오우~',\n                        chocolite_sound_yahoo: '야호~',\n\n                        chocolite_sound_low_do: '낮은 도',\n                        chocolite_sound_low_dosharp: '낮은 도#',\n                        chocolite_sound_low_re: '낮은 레',\n                        chocolite_sound_low_resharp: '낮은 레#',\n                        chocolite_sound_low_mi: '낮은 미',\n                        chocolite_sound_low_fa: '낮은 파',\n                        chocolite_sound_low_fasharp: '낮은 파#',\n                        chocolite_sound_low_sol: '낮은 솔',\n                        chocolite_sound_low_solsharp: '낮은 솔#',\n                        chocolite_sound_low_ra: '낮은 라',\n                        chocolite_sound_low_rasharp: '낮은 라#',\n                        chocolite_sound_low_si: '낮은 시',\n                        chocolite_sound_do: '도',\n                        chocolite_sound_dosharp: '도#',\n                        chocolite_sound_re: '레',\n                        chocolite_sound_resharp: '레#',\n                        chocolite_sound_mi: '미',\n                        chocolite_sound_fa: '파',\n                        chocolite_sound_fasharp: '파#',\n                        chocolite_sound_sol: '솔',\n                        chocolite_sound_solsharp: '솔#',\n                        chocolite_sound_ra: '라',\n                        chocolite_sound_rasharp: '라#',\n                        chocolite_sound_si: '시',\n                        chocolite_sound_high_do: '높은 도',\n                        chocolite_sound_high_dosharp: '높은 도#',\n                        chocolite_sound_high_re: '높은 레',\n                        chocolite_sound_high_resharp: '높은 레#',\n                        chocolite_sound_high_mi: '높은 미',\n                        chocolite_sound_high_fa: '높은 파',\n                        chocolite_sound_high_fasharp: '높은 파#',\n                        chocolite_sound_high_sol: '높은 솔',\n                        chocolite_sound_high_solsharp: '높은 솔#',\n                        chocolite_sound_high_ra: '높은 라',\n                        chocolite_sound_high_rasharp: '높은 라#',\n                        chocolite_sound_high_si: '높은 시',\n                    },\n                },\n                en: {\n                    template: {\n                        chocolite_move_forward: 'move forward %1 %2 block %3',\n                        chocolite_move_backward: 'move backward %1 %2 block %3',\n                        chocolite_turn_left: '%1 %2 to the left %3',\n                        chocolite_turn_right: '%1 %2 to the right %3',\n                        chocolite_move_right_left: 'move right %1 left %2 %3 %4',\n                        chocolite_onoff_led_rear: 'Rear LED %1 %2',\n                        chocolite_set_led_color: '%1 LED %2 %3',\n                        chocolite_play_sound: 'play %1 %2',\n                        chocolite_is_front_sensor: 'front sensor',\n                        chocolite_is_bottom_sensor: 'bottom sensor',\n                        chocolite_is_light_sensor: 'light sensor',\n                        chocolite_get_front_sensor: 'front sensor',\n                        chocolite_get_bottom_sensor: 'bottom sensor',\n                        chocolite_get_light_sensor: 'light sensor',\n                    },\n                    Blocks: {\n                        chocolite_move_step: 'step',\n                        chocolite_move_cm: 'cm',\n                        chocolite_trun_drgree: 'degree',\n                        chocolite_trun_round: 'turns',\n                        chocolite_toggle_on: 'on',\n                        chocolite_toggle_off: 'off',\n                        chocolite_direction_right: 'right',\n                        chocolite_direction_left: 'left',\n                        chocolite_direction_dual: 'all(right,left)',\n\n                        chocolite_color_off: 'off',\n                        chocolite_color_blue: 'blue',\n                        chocolite_color_red: 'red',\n                        chocolite_color_green: 'green',\n                        chocolite_color_yellow: 'yellow',\n                        chocolite_color_pink: 'pink',\n                        chocolite_color_bluegreen: 'bluegreen',\n                        chocolite_color_white: 'white',\n\n                        chocolite_sound_car: 'car',\n                        chocolite_sound_robot: 'robot',\n                        chocolite_sound_dog: 'dog',\n                        chocolite_sound_cat: 'cat',\n                        chocolite_sound_chicken: 'chicken',\n                        chocolite_sound_tiger: 'tiger',\n                        chocolite_sound_lion: 'lion',\n                        chocolite_sound_fart: 'fart',\n                        chocolite_sound_helicopter: 'helicopter',\n                        chocolite_sound_train: 'train',\n                        chocolite_sound_frog: 'frog',\n                        chocolite_sound_jjajan: 'jjajan(effect)',\n                        chocolite_sound_sheep: 'sheep',\n                        chocolite_sound_elephant: 'elephant',\n                        chocolite_sound_camel: 'camel',\n                        chocolite_sound_dolphin: 'dolphin',\n                        chocolite_sound_ttiyong: 'ttiyong(effect)',\n                        chocolite_sound_hello_parrot: 'hello(parrot)',\n                        chocolite_sound_hello_manga: 'hello(manga)',\n                        chocolite_sound_hello_man: 'hello(man)',\n                        chocolite_sound_ppong: 'ppong(effect)',\n                        chocolite_sound_buzzer: 'buzzer(effect)',\n                        chocolite_sound_ttalilalan: 'ttalilalan(effect)',\n                        chocolite_sound_ttattattatta: 'ttattattatta(effect)',\n                        chocolite_sound_laughter: 'laughter',\n                        chocolite_sound_magic: 'magic(effect)',\n                        chocolite_sound_woodpecker: 'woodpecker',\n                        chocolite_sound_bird: 'bird',\n                        chocolite_sound_burp: 'burp',\n                        chocolite_sound_hiccup: 'hiccup',\n                        chocolite_sound_doridori: 'doridori',\n                        chocolite_sound_firetruck: 'fire truck',\n                        chocolite_sound_police_car: 'police car',\n                        chocolite_sound_applause: 'applause',\n                        chocolite_sound_kiss: 'kiss',\n                        chocolite_sound_missile: 'missile',\n                        chocolite_sound_angry_duck: 'angry duck',\n                        chocolite_sound_fly: 'fly',\n                        chocolite_sound_ufo: 'UFO',\n                        chocolite_sound_fanfare: 'fanfare',\n                        chocolite_sound_sigh: 'sigh',\n                        chocolite_sound_alright: 'alright',\n                        chocolite_sound_genius: 'genius',\n                        chocolite_sound_no: 'no',\n                        chocolite_sound_wow: 'wow',\n                        chocolite_sound_yahoo: 'yahoo',\n\n                        chocolite_sound_low_do: 'low do',\n                        chocolite_sound_low_dosharp: 'low do#',\n                        chocolite_sound_low_re: 'low re',\n                        chocolite_sound_low_resharp: 'low re#',\n                        chocolite_sound_low_mi: 'low mi',\n                        chocolite_sound_low_fa: 'low fa',\n                        chocolite_sound_low_fasharp: 'low fa#',\n                        chocolite_sound_low_sol: 'low sol',\n                        chocolite_sound_low_solsharp: 'low sol#',\n                        chocolite_sound_low_ra: 'low ra',\n                        chocolite_sound_low_rasharp: 'low ra#',\n                        chocolite_sound_low_si: 'low si',\n                        chocolite_sound_do: 'do',\n                        chocolite_sound_dosharp: 'do#',\n                        chocolite_sound_re: 're',\n                        chocolite_sound_resharp: 're#',\n                        chocolite_sound_mi: 'mi',\n                        chocolite_sound_fa: 'fa',\n                        chocolite_sound_fasharp: 'fa#',\n                        chocolite_sound_sol: 'sol',\n                        chocolite_sound_solsharp: 'sol#',\n                        chocolite_sound_ra: 'ra',\n                        chocolite_sound_rasharp: 'ra#',\n                        chocolite_sound_si: 'si',\n                        chocolite_sound_high_do: 'high do',\n                        chocolite_sound_high_dosharp: 'high do#',\n                        chocolite_sound_high_re: 'high re',\n                        chocolite_sound_high_resharp: 'high re#',\n                        chocolite_sound_high_mi: 'high mi',\n                        chocolite_sound_high_fa: 'high fa',\n                        chocolite_sound_high_fasharp: 'high fa#',\n                        chocolite_sound_high_sol: 'high sol',\n                        chocolite_sound_high_solsharp: 'high sol#',\n                        chocolite_sound_high_ra: 'high ra',\n                        chocolite_sound_high_rasharp: 'high ra#',\n                        chocolite_sound_high_si: 'high si',\n                    },\n                },\n            };\n        }\n\n        getBlocks() {\n            return {\n                chocolite_move_forward: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_move_step, 'step'],\n                                [Lang.Blocks.chocolite_move_cm, 'cm'],\n                            ],\n                            value: 'step',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, 'step', null],\n                        type: 'chocolite_move_forward',\n                    },\n                    paramsKeyMap: {\n                        MOVE_CNT: 0,\n                        MOVE_UNIT: 1,\n                    },\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        const moveCnt = script.getValue('MOVE_CNT');\n                        const moveUnit = script.getValue('MOVE_UNIT');\n                        if (moveCnt === 0) {\n                            return script.callReturn();\n                        }\n\n                        if (!script.is_started) {\n                            script.is_started = true;\n                            const msg = {\n                                type: 'move_forward',\n                                data: {\n                                    param1: moveCnt,\n                                    param2: moveUnit,\n                                },\n                            };\n\n                            const sendData = this.makeData(msg);\n                            script.isDone = false;\n                            this.sendBuffers.push({\n                                sendData,\n                                cb: () => {\n                                    script.isDone = true;\n                                },\n                            });\n                            return script;\n                        }\n\n                        if (script.isDone) {\n                            delete script.is_started;\n                            delete script.isDone;\n                            return script.callReturn();\n                        }\n                        return script;\n                    },\n                },\n                chocolite_move_backward: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_move_step, 'step'],\n                                [Lang.Blocks.chocolite_move_cm, 'cm'],\n                            ],\n                            value: 'step',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, 'step', null],\n                        type: 'chocolite_move_backward',\n                    },\n                    paramsKeyMap: {\n                        MOVE_CNT: 0,\n                        MOVE_UNIT: 1,\n                    },\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        const moveCnt = script.getValue('MOVE_CNT');\n                        const moveUnit = script.getValue('MOVE_UNIT');\n                        if (moveCnt === 0) {\n                            return script.callReturn();\n                        }\n\n                        if (!script.is_started) {\n                            script.is_started = true;\n                            const msg = {\n                                type: 'move_backward',\n                                data: {\n                                    param1: moveCnt,\n                                    param2: moveUnit,\n                                },\n                            };\n                            const sendData = this.makeData(msg);\n                            script.isDone = false;\n                            this.sendBuffers.push({\n                                sendData,\n                                cb: () => {\n                                    script.isDone = true;\n                                },\n                            });\n                            return script;\n                        }\n\n                        if (script.isDone) {\n                            delete script.is_started;\n                            delete script.isDone;\n                            return script.callReturn();\n                        }\n                        return script;\n                    },\n                },\n                chocolite_turn_left: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_trun_drgree, 'degree'],\n                                [Lang.Blocks.chocolite_trun_round, 'turns'],\n                            ],\n                            value: 'degree',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [90, 'degree', null],\n                        type: 'chocolite_turn_left',\n                    },\n                    paramsKeyMap: {\n                        TURN_CNT: 0,\n                        TURN_UNIT: 1,\n                    },\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        let turnCnt = script.getValue('TURN_CNT');\n                        const turnUnit = script.getValue('TURN_UNIT');\n                        if (turnCnt < 0) {\n                            turnCnt = 0;\n                        }\n                        if (turnCnt === 0) {\n                            return script.callReturn();\n                        }\n\n                        if (!script.is_started) {\n                            script.is_started = true;\n                            const msg = {\n                                type: 'turn_left',\n                                data: {\n                                    param1: turnCnt,\n                                    param2: turnUnit,\n                                },\n                            };\n                            const sendData = this.makeData(msg);\n                            script.isDone = false;\n                            this.sendBuffers.push({\n                                sendData,\n                                cb: () => {\n                                    script.isDone = true;\n                                },\n                            });\n                            return script;\n                        }\n\n                        if (script.isDone) {\n                            delete script.is_started;\n                            delete script.isDone;\n                            return script.callReturn();\n                        }\n                        return script;\n                    },\n                },\n                chocolite_turn_right: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_trun_drgree, 'degree'],\n                                [Lang.Blocks.chocolite_trun_round, 'turns'],\n                            ],\n                            value: 'degree',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [90, 'degree', null],\n                        type: 'chocolite_turn_right',\n                    },\n                    paramsKeyMap: {\n                        TURN_CNT: 0,\n                        TURN_UNIT: 1,\n                    },\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        let turnCnt = script.getValue('TURN_CNT');\n                        const turnUnit = script.getValue('TURN_UNIT');\n                        if (turnCnt < 0) {\n                            turnCnt = 0;\n                        }\n                        if (turnCnt === 0) {\n                            return script.callReturn();\n                        }\n\n                        if (!script.is_started) {\n                            script.is_started = true;\n                            const msg = {\n                                type: 'turn_right',\n                                data: {\n                                    param1: turnCnt,\n                                    param2: turnUnit,\n                                },\n                            };\n\n                            const sendData = this.makeData(msg);\n                            script.isDone = false;\n                            this.sendBuffers.push({\n                                sendData,\n                                cb: () => {\n                                    script.isDone = true;\n                                },\n                            });\n\n                            return script;\n                        }\n\n                        if (script.isDone) {\n                            delete script.is_started;\n                            delete script.isDone;\n                            return script.callReturn();\n                        }\n                        return script;\n                    },\n                },\n                chocolite_move_right_left: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_move_step, 'step'],\n                                [Lang.Blocks.chocolite_move_cm, 'cm'],\n                            ],\n                            value: 'step',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, 1, 'step', null],\n                        type: 'chocolite_move_right_left',\n                    },\n                    paramsKeyMap: {\n                        MOVE_RIGHT_CNT: 0,\n                        MOVE_LEFT_CNT: 1,\n                        MOVE_UNIT: 2,\n                    },\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        const moveRightCnt = script.getValue('MOVE_RIGHT_CNT');\n                        const moveLeftCnt = script.getValue('MOVE_LEFT_CNT');\n                        const moveUnit = script.getValue('MOVE_UNIT');\n\n                        if (!script.is_started) {\n                            script.is_started = true;\n                            const msg = {\n                                type: 'move_right_left',\n                                data: {\n                                    param1: moveRightCnt,\n                                    param2: moveLeftCnt,\n                                    param3: moveUnit,\n                                },\n                                time: Date.now(),\n                            };\n\n                            const sendData = this.makeData(msg);\n                            script.isDone = false;\n                            this.sendBuffers.push({\n                                sendData,\n                                cb: () => {\n                                    script.isDone = true;\n                                },\n                            });\n                            return script;\n                        }\n\n                        if (script.isDone) {\n                            delete script.is_started;\n                            delete script.isDone;\n                            return script.callReturn();\n                        }\n                        return script;\n                    },\n                },\n                chocolite_onoff_led_rear: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_toggle_on, 'On'],\n                                [Lang.Blocks.chocolite_toggle_off, 'Off'],\n                            ],\n                            value: 'On',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['On', null],\n                        type: 'chocolite_onoff_led_rear',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        const ledOnoff = script.getValue('VALUE');\n\n                        if (!script.is_started) {\n                            script.is_started = true;\n                            const msg = {\n                                type: 'onoff_led_rear',\n                                data: {\n                                    param1: ledOnoff,\n                                },\n                            };\n\n                            const sendData = this.makeData(msg);\n                            script.isDone = false;\n                            this.sendBuffers.push({\n                                sendData,\n                                cb: () => {\n                                    script.isDone = true;\n                                },\n                            });\n                            return script;\n                        }\n\n                        if (script.isDone) {\n                            delete script.is_started;\n                            delete script.isDone;\n                            return script.callReturn();\n                        }\n                        return script;\n                    },\n                },\n                chocolite_set_led_color: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_direction_right, 'right'],\n                                [Lang.Blocks.chocolite_direction_left, 'left'],\n                                [Lang.Blocks.chocolite_direction_dual, 'dual'],\n                            ],\n                            value: 'right',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_color_off, 0],\n                                [Lang.Blocks.chocolite_color_blue, 1],\n                                [Lang.Blocks.chocolite_color_red, 2],\n                                [Lang.Blocks.chocolite_color_green, 3],\n                                [Lang.Blocks.chocolite_color_yellow, 4],\n                                [Lang.Blocks.chocolite_color_pink, 5],\n                                [Lang.Blocks.chocolite_color_bluegreen, 6],\n                                [Lang.Blocks.chocolite_color_white, 7],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['right', 1, null],\n                        type: 'chocolite_set_led_color',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                        COLOR: 1,\n                    },\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        const ledDir = script.getValue('DIRECTION');\n                        const ledColor = script.getValue('COLOR');\n\n                        if (!script.is_started) {\n                            script.is_started = true;\n                            const msg = {\n                                type: 'set_led_color',\n                                data: {\n                                    param1: ledDir,\n                                    param2: ledColor,\n                                },\n                            };\n\n                            const sendData = this.makeData(msg);\n                            script.isDone = false;\n                            this.sendBuffers.push({\n                                sendData,\n                                cb: () => {\n                                    script.isDone = true;\n                                },\n                            });\n                            return script;\n                        }\n\n                        if (script.isDone) {\n                            delete script.is_started;\n                            delete script.isDone;\n                            return script.callReturn();\n                        }\n                        return script;\n                    },\n                },\n                chocolite_play_sound: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.chocolite_sound_car, 1],\n                                [Lang.Blocks.chocolite_sound_robot, 2],\n                                [Lang.Blocks.chocolite_sound_dog, 3],\n                                [Lang.Blocks.chocolite_sound_cat, 4],\n                                [Lang.Blocks.chocolite_sound_chicken, 5],\n                                [Lang.Blocks.chocolite_sound_tiger, 6],\n                                [Lang.Blocks.chocolite_sound_lion, 7],\n                                [Lang.Blocks.chocolite_sound_fart, 8],\n                                [Lang.Blocks.chocolite_sound_helicopter, 9],\n                                [Lang.Blocks.chocolite_sound_train, 10],\n                                [Lang.Blocks.chocolite_sound_frog, 11],\n                                [Lang.Blocks.chocolite_sound_jjajan, 12],\n                                [Lang.Blocks.chocolite_sound_sheep, 13],\n                                [Lang.Blocks.chocolite_sound_elephant, 14],\n                                [Lang.Blocks.chocolite_sound_camel, 15],\n                                [Lang.Blocks.chocolite_sound_dolphin, 16],\n                                [Lang.Blocks.chocolite_sound_ttiyong, 17],\n                                [Lang.Blocks.chocolite_sound_hello_parrot, 18],\n                                [Lang.Blocks.chocolite_sound_hello_manga, 19],\n                                [Lang.Blocks.chocolite_sound_hello_man, 20],\n                                [Lang.Blocks.chocolite_sound_ppong, 21],\n                                [Lang.Blocks.chocolite_sound_buzzer, 22],\n                                [Lang.Blocks.chocolite_sound_ttalilalan, 23],\n                                [Lang.Blocks.chocolite_sound_ttattattatta, 24],\n                                [Lang.Blocks.chocolite_sound_laughter, 25],\n                                [Lang.Blocks.chocolite_sound_magic, 26],\n                                [Lang.Blocks.chocolite_sound_woodpecker, 27],\n                                [Lang.Blocks.chocolite_sound_bird, 28],\n                                [Lang.Blocks.chocolite_sound_burp, 29],\n                                [Lang.Blocks.chocolite_sound_hiccup, 30],\n                                [Lang.Blocks.chocolite_sound_doridori, 31],\n                                [Lang.Blocks.chocolite_sound_firetruck, 32],\n                                [Lang.Blocks.chocolite_sound_police_car, 33],\n                                [Lang.Blocks.chocolite_sound_applause, 34],\n                                [Lang.Blocks.chocolite_sound_kiss, 35],\n                                [Lang.Blocks.chocolite_sound_missile, 36],\n                                [Lang.Blocks.chocolite_sound_angry_duck, 37],\n                                [Lang.Blocks.chocolite_sound_fly, 38],\n                                [Lang.Blocks.chocolite_sound_ufo, 39],\n                                [Lang.Blocks.chocolite_sound_fanfare, 40],\n                                [Lang.Blocks.chocolite_sound_sigh, 41],\n                                [Lang.Blocks.chocolite_sound_alright, 42],\n                                [Lang.Blocks.chocolite_sound_genius, 43],\n                                [Lang.Blocks.chocolite_sound_no, 44],\n                                [Lang.Blocks.chocolite_sound_wow, 45],\n                                [Lang.Blocks.chocolite_sound_yahoo, 46],\n\n                                [Lang.Blocks.chocolite_sound_low_do, 47],\n                                [Lang.Blocks.chocolite_sound_low_dosharp, 48],\n                                [Lang.Blocks.chocolite_sound_low_re, 49],\n                                [Lang.Blocks.chocolite_sound_low_resharp, 50],\n                                [Lang.Blocks.chocolite_sound_low_mi, 51],\n                                [Lang.Blocks.chocolite_sound_low_fa, 52],\n                                [Lang.Blocks.chocolite_sound_low_fasharp, 53],\n                                [Lang.Blocks.chocolite_sound_low_sol, 54],\n                                [Lang.Blocks.chocolite_sound_low_solsharp, 55],\n                                [Lang.Blocks.chocolite_sound_low_ra, 56],\n                                [Lang.Blocks.chocolite_sound_low_rasharp, 57],\n                                [Lang.Blocks.chocolite_sound_low_si, 58],\n                                [Lang.Blocks.chocolite_sound_do, 59],\n                                [Lang.Blocks.chocolite_sound_dosharp, 60],\n                                [Lang.Blocks.chocolite_sound_re, 61],\n                                [Lang.Blocks.chocolite_sound_resharp, 62],\n                                [Lang.Blocks.chocolite_sound_mi, 63],\n                                [Lang.Blocks.chocolite_sound_fa, 64],\n                                [Lang.Blocks.chocolite_sound_fasharp, 65],\n                                [Lang.Blocks.chocolite_sound_sol, 66],\n                                [Lang.Blocks.chocolite_sound_solsharp, 67],\n                                [Lang.Blocks.chocolite_sound_ra, 68],\n                                [Lang.Blocks.chocolite_sound_rasharp, 69],\n                                [Lang.Blocks.chocolite_sound_si, 70],\n                                [Lang.Blocks.chocolite_sound_high_do, 71],\n                                [Lang.Blocks.chocolite_sound_high_dosharp, 72],\n                                [Lang.Blocks.chocolite_sound_high_re, 73],\n                                [Lang.Blocks.chocolite_sound_high_resharp, 74],\n                                [Lang.Blocks.chocolite_sound_high_mi, 75],\n                                [Lang.Blocks.chocolite_sound_high_fa, 76],\n                                [Lang.Blocks.chocolite_sound_high_fasharp, 77],\n                                [Lang.Blocks.chocolite_sound_high_sol, 78],\n                                [Lang.Blocks.chocolite_sound_high_solsharp, 79],\n                                [Lang.Blocks.chocolite_sound_high_ra, 80],\n                                [Lang.Blocks.chocolite_sound_high_rasharp, 81],\n                                [Lang.Blocks.chocolite_sound_high_si, 82],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'chocolite_play_sound',\n                    },\n                    paramsKeyMap: {\n                        SOUND: 0,\n                    },\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        const sound = script.getValue('SOUND');\n\n                        if (!script.is_started) {\n                            script.is_started = true;\n                            const msg = {\n                                type: 'play_sound',\n                                data: {\n                                    param1: sound,\n                                },\n                            };\n\n                            const sendData = this.makeData(msg);\n                            script.isDone = false;\n                            this.sendBuffers.push({\n                                sendData,\n                                cb: () => {\n                                    script.isDone = true;\n                                },\n                            });\n                            return script;\n                        }\n\n                        if (script.isDone) {\n                            delete script.is_started;\n                            delete script.isDone;\n                            return script.callReturn();\n                        }\n                        return script;\n                    },\n                },\n                chocolite_is_front_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Text',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'chocolite_is_front_sensor',\n                    },\n                    paramsKeyMap: {},\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        let retVal = false;\n                        if (this.sensorData) {\n                            retVal = this.sensorData.is_front_sensor;\n                        }\n                        return retVal;\n                    },\n                },\n                chocolite_is_bottom_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Text',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'chocolite_is_bottom_sensor',\n                    },\n                    paramsKeyMap: {},\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        let retVal = false;\n                        if (this.sensorData) {\n                            retVal = this.sensorData.is_bottom_sensor;\n                        }\n                        return retVal;\n                    },\n                },\n                chocolite_is_light_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Text',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'chocolite_is_light_sensor',\n                    },\n                    paramsKeyMap: {},\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        let retVal = false;\n                        if (this.sensorData) {\n                            retVal = this.sensorData.is_light_sensor;\n                        }\n                        return retVal;\n                    },\n                },\n\n                chocolite_get_front_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Text',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'chocolite_get_front_sensor',\n                    },\n                    paramsKeyMap: {},\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        let retVal = 0;\n                        if (this.sensorData) {\n                            retVal = this.sensorData.front_sensor;\n                        }\n                        return retVal;\n                    },\n                },\n                chocolite_get_bottom_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Text',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'chocolite_get_bottom_sensor',\n                    },\n                    paramsKeyMap: {},\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        let retVal = 0;\n                        if (this.sensorData) {\n                            retVal = this.sensorData.bottom_sensor;\n                        }\n                        return retVal;\n                    },\n                },\n                chocolite_get_light_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Text',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'chocolite_get_light_sensor',\n                    },\n                    paramsKeyMap: {},\n                    class: 'chocolite_command',\n                    isNotFor: ['ChocoLite'],\n                    func: (sprite, script) => {\n                        let retVal = 0;\n                        if (this.sensorData) {\n                            retVal = this.sensorData.light_sensor;\n                        }\n                        return retVal;\n                    },\n                },\n            };\n        }\n\n        /***************************************************************************************\n         *  프로토롤 제어 함수\n         ***************************************************************************************/\n        sequenceNo() {\n            if (this.cmdSeq > 254) {\n                this.cmdSeq = 0;\n            } else {\n                this.cmdSeq++;\n            }\n            return this.cmdSeq;\n        }\n\n        calMoveVal(args) {\n            let retval = 0;\n            if (args.param2 === 'cm') {\n                retval = parseInt(args.param1 * 10, 10);\n                if (args.param1 > 0 && retval === 0) {\n                    retval = 1;\n                }\n            } else {\n                retval = args.param1 * 10;\n            }\n            retval = parseInt(retval, 10);\n            if (retval < 0) {\n                retval = 0;\n            }\n            if (retval > 990) {\n                retval = 990;\n            }\n            return retval;\n        }\n\n        calTurnVal(args) {\n            let retval = 0;\n            if (args.param2 === 'degree') {\n                retval = parseInt((args.param1 * 10) / 90, 10);\n                if (args.param1 > 0 && retval === 0) {\n                    retval = 1;\n                }\n            } else {\n                retval = args.param1 * 10 * 4;\n            }\n            retval = parseInt(retval, 10);\n            if (retval < 0) {\n                retval = 0;\n            }\n            if (retval > 990) {\n                retval = 990;\n            }\n            return retval;\n        }\n\n        calLedCol(args) {\n            let rightLed = 0;\n            let leftLed = 0;\n\n            if (args.param1 === 'right') {\n                rightLed = args.param2;\n            } else if (args.param1 === 'left') {\n                leftLed = args.param2;\n            } else if (args.param1 === 'dual') {\n                rightLed = args.param2;\n                leftLed = args.param2;\n            }\n\n            return {\n                rightLed,\n                leftLed,\n            };\n        }\n\n        /***************************************************************************************\n         *  Protocol 데이터 생성\n         ***************************************************************************************/\n        makeData(msg) {\n            const seqNo = this.sequenceNo();\n            let data = null;\n            let crc = 0;\n            let encodedCmd = [];\n\n            const type = msg.type;\n            let args = {};\n            if (msg.data) {\n                args = msg.data;\n            }\n\n            switch (type) {\n                case 'ping':\n                    data = Buffer.from([0x03, seqNo]);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'ping2':\n                    data = Buffer.from([0x13, seqNo]);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'ping3':\n                    data = Buffer.from([0x14, seqNo]);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'ping2_end':\n                    data = Buffer.from([0x17, seqNo]);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'ready':\n                    data = Buffer.from([0x04, seqNo]);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'move_forward':\n                    if (args.param2 === 'cm') {\n                        data = Buffer.from([0x19, seqNo, 0, 0, 0, 0]);\n                    } else {\n                        data = Buffer.from([0x05, seqNo, 0, 0, 0, 0]);\n                    }\n                    data.writeUInt32LE(this.calMoveVal(args), 2);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'move_backward':\n                    if (args.param2 === 'cm') {\n                        data = Buffer.from([0x1a, seqNo, 0, 0, 0, 0]);\n                    } else {\n                        data = Buffer.from([0x06, seqNo, 0, 0, 0, 0]);\n                    }\n                    data.writeUInt32LE(this.calMoveVal(args), 2);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'turn_left':\n                    data = Buffer.from([0x07, seqNo, 0, 0, 0, 0]);\n                    data.writeUInt32LE(this.calTurnVal(args), 2);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'turn_right':\n                    data = Buffer.from([0x08, seqNo, 0, 0, 0, 0]);\n                    data.writeUInt32LE(this.calTurnVal(args), 2);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n\n                case 'move_right_left': {\n                    if (args.param3 === 'cm') {\n                        data = Buffer.from([0x1b, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]);\n                    } else {\n                        data = Buffer.from([0x0d, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]);\n                    }\n                    const args1 = {\n                        param1: args.param1,\n                        param2: args.param3,\n                    };\n                    const args2 = {\n                        param1: args.param2,\n                        param2: args.param3,\n                    };\n                    data.writeUInt32LE(this.calMoveVal(args1), 2);\n                    data.writeUInt32LE(this.calMoveVal(args2), 6);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n                }\n\n                case 'onoff_led_rear': {\n                    const rearLed = args.param1 === 'On' ? 1 : 0;\n                    this.ledStatus[2] = rearLed;\n                    data = Buffer.from([\n                        0x0b,\n                        seqNo,\n                        this.ledStatus[0],\n                        this.ledStatus[1],\n                        this.ledStatus[2],\n                    ]);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n                }\n\n                case 'set_led_color': {\n                    const { rightLed, leftLed } = this.calLedCol(args);\n                    if (args.param1 === 'right') {\n                        this.ledStatus[0] = rightLed;\n                    } else if (args.param1 === 'left') {\n                        this.ledStatus[1] = leftLed;\n                    } else if (args.param1 === 'dual') {\n                        this.ledStatus[0] = rightLed;\n                        this.ledStatus[1] = leftLed;\n                    }\n                    data = Buffer.from([\n                        0x0b,\n                        seqNo,\n                        this.ledStatus[0],\n                        this.ledStatus[1],\n                        this.ledStatus[2],\n                    ]);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n                }\n\n                case 'play_sound':\n                    data = Buffer.from([0x0f, seqNo, 0, 0, 0, 0]);\n                    data.writeUInt32LE(args.param1, 2);\n                    crc = this.calCrc16(data);\n                    encodedCmd = this.escapeEncode(\n                        Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])])\n                    );\n                    break;\n            }\n\n            const cmdData = Buffer.from([0x7c, ...encodedCmd, 0x7e]);\n            //console.log(cmdData);\n            return cmdData;\n        }\n\n        /***************************************************************************************\n         *  데이터 encoding\n         ***************************************************************************************/\n        escapeEncode(data) {\n            const buffer = Buffer.alloc(data.length * 2);\n            let idx = 0;\n            for (const d of data) {\n                if (d === 0x7c) {\n                    buffer[idx] = 0x7d;\n                    buffer[idx + 1] = 0x5c;\n                    idx += 2;\n                } else if (d === 0x7d) {\n                    buffer[idx] = 0x7d;\n                    buffer[idx + 1] = 0x5d;\n                    idx += 2;\n                } else if (d === 0x7e) {\n                    buffer[idx] = 0x7d;\n                    buffer[idx + 1] = 0x5e;\n                    idx += 2;\n                } else {\n                    buffer[idx] = d;\n                    idx++;\n                }\n            }\n            return buffer.slice(0, idx);\n        }\n\n        /***************************************************************************************\n         *  데이터 decoding\n         ***************************************************************************************/\n        escapeEecode(data) {\n            const buffer = Buffer.alloc(data.length);\n            let idx = 0;\n            let i = 0;\n            while (i < data.length) {\n                if (data[i] === 0x7d) {\n                    buffer[idx++] = data[i + 1] ^ 0x20;\n                    i += 2;\n                } else {\n                    buffer[idx++] = data[i++];\n                }\n            }\n            return buffer.slice(0, idx);\n        }\n\n        /***************************************************************************************\n         *  CRC 생성\n         ***************************************************************************************/\n        calCrc16(data) {\n            let res = 0x0ffff;\n\n            for (const b of data) {\n                res = ((res >> 8) & 0x0ff) ^ this.crctab16[(res ^ b) & 0xff];\n            }\n\n            return ~res & 0x0ffff;\n        }\n\n        /***************************************************************************************\n         *  로그 출력\n         ***************************************************************************************/\n        // #region Functions for log\n\n        log(message, data = undefined) {\n            // 로그를 출력하지 않으려면 아래 주석을 활성화 할 것\n            let strInfo = '';\n            switch (typeof data) {\n                case 'object':\n                    {\n                        strInfo = ` - [ ${this.convertByteArrayToHexString(data)} ]`;\n                        console.log(`${message} - ${typeof data}${strInfo}`);\n                    }\n                    break;\n                default:\n                    {\n                        console.log(message);\n                    }\n                    break;\n            }\n        }\n\n        // 바이트 배열을 16진수 문자열로 변경\n        convertByteArrayToHexString(data) {\n            let strHexArray = '';\n            let strHex;\n\n            if (typeof data === 'object' && data.length > 1) {\n                for (let i = 0; i < data.length; i++) {\n                    strHex = data[i].toString(16).toUpperCase();\n                    strHexArray += ' ';\n                    if (strHex.length === 1) {\n                        strHexArray += '0';\n                    }\n                    strHexArray += strHex;\n                }\n                strHexArray = strHexArray.substr(1, strHexArray.length - 1);\n            } else {\n                strHexArray = data.toString();\n            }\n\n            return strHexArray;\n        }\n    })();\n})();\n\nmodule.exports = Entry.ChocoLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_cocodron_controller_Lite.js",
    "content": "//cocodron_Entrylite_wing1008\n'use strict';\n\nimport _range from 'lodash/range';\n\n(function () {\n    Entry.cocodroncontrollerLite = new (class cocodroncontrollerLite {\n        constructor() {\n            this.id = '680101';\n            this.name = 'cocodroncontrollerLite';\n            this.url = 'http://www.cocodrone.co.kr/kr/';\n            this.imageName = 'cocodroncontrollerLite.png';\n            this.title = {\n                ko: '코코드론조종기',\n                en: 'cocodron controller',\n                ja: 'ココドローン 操縦機'\n            };\n            this.duration = 32;\n            this.blockMenuBlocks = [\n                'Cocodron_Dron_Controller_connect',\n                //'Cocodron_Dron_Controller_hovering',\n                'Cocodron_Dron_Controller_mode',\n                'Cocodron_Dron_Controller_opt',\n                'Cocodron_Dron_Controller_gyroreset',\n                'Cocodron_Dron_Controller_takeoff',\n                //'Cocodron_Dron_Controller_takeoffV2',\n                'Cocodron_Dron_Controller_land',\n                'Cocodron_Dron_Controller_emergency',\n                //'Cocodron_Dron_Controller_headless',\n                'Cocodron_Dron_Controller_up',\n                'Cocodron_Dron_Controller_down',\n                'Cocodron_Dron_Controller_cw',\n                'Cocodron_Dron_Controller_ccw',\n                'Cocodron_Dron_Controller_move_drone_forward',\n                'Cocodron_Dron_Controller_move_drone_back',\n                'Cocodron_Dron_Controller_move_drone_left',\n                'Cocodron_Dron_Controller_move_drone_right',\n                'Cocodron_Dron_Controller_funled',\n                'Cocodron_Dron_Controller_flip',\n                'Cocodron_Dron_Controller_speed',\n                //'Cocodron_Dron_Controller_simultaneousOperations'\n            ];\n            this.portData = {\n                baudRate: 9600,\n                duration: 32,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: false,\n            };\n            this.readablePorts = [];\n            this.remainValue = null;\n            this.setZero();\n        }\n\n        setZero() {\n            this.port = new Array(14).fill(0);\n            this.digitalValue = new Array(14).fill(0);\n            this.remoteDigitalValue = new Array(14).fill(0);\n            this.analogValue = new Array(6).fill(0);\n            this.readablePorts = _range(0, 19);\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        handleLocalData(data) {\n            for (let i = 0; i < 32; i++) {\n                let chunk;\n                if (!this.remainValue) {\n                    chunk = data[i];\n                } else {\n                    chunk = this.remainValue;\n                    i--;\n                }\n\n                if (chunk === SOME_EXPECTED_RESPONSE) {\n                    console.log('Takeoff command acknowledged by drone.');\n                } else {\n                    console.log('Unexpected response from drone:', chunk);\n                }\n\n                if (chunk >> 7) {\n                    if ((chunk >> 6) & 1) {\n                        const nextChunk = data[i + 1];\n                        if (!nextChunk && nextChunk !== 0) {\n                            this.remainValue = chunk;\n                        } else {\n                            this.remainValue = null;\n\n                            const port = (chunk >> 3) & 7;\n                            this.analogValue[port] = ((chunk & 7) << 7) + (nextChunk & 127);\n                        }\n                        i++;\n                    } else {\n                        const port = (chunk >> 2) & 15;\n                        this.digitalValue[port] = chunk & 1;\n                    }\n                }\n            }\n        }\n\n        requestLocalData() {\n            const queryString = [];\n            const readablePorts = this.readablePorts;\n\n            const commandStr = Entry.hw.sendQueue['COMMAND'];\n            if (commandStr) {\n                for (let i = 0; i < commandStr.length; i++) {\n                    queryString.push(commandStr.charCodeAt(i));\n                }\n                delete Entry.hw.sendQueue['COMMAND'];\n            }\n\n            if (readablePorts) {\n                for (const i in readablePorts) {\n                    const query = (5 << 5) + (readablePorts[i] << 1);\n                    queryString.push(query);\n                }\n            }\n            const readablePortsValues = (readablePorts && Object.values(readablePorts)) || [];\n            for (let port = 0; port < 14; port++) {\n                if (readablePortsValues.indexOf(port) > -1) {\n                    continue;\n                }\n                const value = this.remoteDigitalValue[port];\n                if (value === 255 || value === 0) {\n                    const query = (7 << 5) + (port << 1) + (value == 255 ? 1 : 0);\n                    queryString.push(query);\n                } else if (value > 0 && value < 255) {\n                    let query = (6 << 5) + (port << 1) + (value >> 7);\n                    queryString.push(query);\n                    query = value & 127;\n                    queryString.push(query);\n                }\n            }\n            return queryString;\n        }\n\n        addReadablePort(port) {\n            const idx = Entry.ArduinoLite.readablePorts.indexOf(port);\n            if (idx === -1) {\n                Entry.ArduinoLite.readablePorts.push(port);\n            }\n        }\n\n        removeReadablePort(port) {\n            const idx = Entry.ArduinoLite.readablePorts.indexOf(port);\n            if (idx >= 0) {\n                Entry.ArduinoLite.readablePorts.splice(idx, 1);\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    Blocks: {\n                        Cocodron_Dron_Controller_mode_drone: '드론  ',\n                        Cocodron_Dron_Controller_mode_rccar: 'RC카  ',\n                        // Cocodron_Dron_Controller_altitude_up: '위쪽  ',\n                        // Cocodron_Dron_Controller_altitude_down: '아래쪽  ',\n                        // Cocodron_Dron_Controller_rotation_cw: '우회전  ',\n                        // Cocodron_Dron_Controller_rotation_ccw: '좌회전  ',\n                        // Cocodron_Dron_Controller_move_drone_left:'왼쪽  ',\n                        // Cocodron_Dron_Controller_move_drone_right:'오른쪽  ',\n                        // Cocodron_Dron_Controller_move_drone_forward:'앞쪽  ',\n                        // Cocodron_Dron_Controller_move_drone_back:'뒤쪽  ',\n                        Cocodron_Dron_Controller_flip_f: '앞으로  ',\n                        Cocodron_Dron_Controller_flip_b: '뒤로  ',\n                        Cocodron_Dron_Controller_flip_l: '왼쪽으로  ',\n                        Cocodron_Dron_Controller_flip_r: '오른쪽으로  ',\n                        Cocodron_Dron_Controller_simultaneousOperations_up: '상승  ',\n                        Cocodron_Dron_Controller_simultaneousOperations_down: '하강  ',\n                        Cocodron_Dron_Controller_simultaneousOperations_cw: '시계  ',\n                        Cocodron_Dron_Controller_simultaneousOperations_ccw: '반시계  ',\n                        Cocodron_Dron_Controller_simultaneousOperations_forward: '앞쪽  ',\n                        Cocodron_Dron_Controller_simultaneousOperations_back: '뒤쪽  ',\n                        Cocodron_Dron_Controller_simultaneousOperations_right: '오른쪽  ',\n                        Cocodron_Dron_Controller_simultaneousOperations_left: '왼쪽  ',\n                    },\n                    template: {\n                        Cocodron_Dron_Controller_connect: '바인딩  ',\n                        Cocodron_Dron_Controller_hovering: '호버링 %1 초  ',\n                        Cocodron_Dron_Controller_mode: '%1 모드  ',\n                        Cocodron_Dron_Controller_opt: '광학센서  ',\n                        Cocodron_Dron_Controller_gyroreset: '자이로 초기화  ',\n                        Cocodron_Dron_Controller_takeoff: '이륙  ',\n                        Cocodron_Dron_Controller_takeoffV2: '이륙 %1 %2',\n                        Cocodron_Dron_Controller_land: '착륙  ',\n                        Cocodron_Dron_Controller_emergency: '비상정지  ',\n                        Cocodron_Dron_Controller_headless: '헤드리스 모드  ',\n                        //Cocodron_Dron_Controller_move_drone: '%1 조이스틱을 %2 방향으로 %3 만큼 %4 ms 유지  ',\n                        Cocodron_Dron_Controller_up: '상승 %1 만큼 %2 ms 유지  ',\n                        Cocodron_Dron_Controller_down: '하강 %1 만큼 %2 ms 유지  ',\n                        Cocodron_Dron_Controller_cw: '우회전 %1 만큼 %2 ms 유지  ',\n                        Cocodron_Dron_Controller_ccw: '좌회전 %1 만큼 %2 ms 유지  ',\n                        Cocodron_Dron_Controller_move_drone_forward: '앞으로 %1 만큼 %2 ms 유지  ',\n                        Cocodron_Dron_Controller_move_drone_back: '뒤로 %1 만큼 %2 ms 유지  ',\n                        Cocodron_Dron_Controller_move_drone_left: '왼쪽으로 %1 만큼 %2 ms 유지  ',\n                        Cocodron_Dron_Controller_move_drone_right:\n                            '오른쪽으로 %1 만큼 %2 ms 유지  ',\n                        Cocodron_Dron_Controller_funled: '4색 LED 색 변경  ',\n                        Cocodron_Dron_Controller_flip: '%1 플립  ',\n                        Cocodron_Dron_Controller_speed: '속도조정 %1',\n                        Cocodron_Dron_Controller_simultaneousOperations:\n                            '%1 방향으로 %2 %3 만큼 %4 방향으로 %5 %6 이동  ',\n                    },\n                    Device: {\n                        cocodron_dron_controller: '코코드론조종기',\n                    },\n                    Menus: {\n                        cocodron_dron_controller: '코코드론조종기',\n                    },\n                    Helper: {\n                        Cocodron_Dron_Controller_connect: '바인딩  ',\n                        Cocodron_Dron_Controller_hovering: '호버링 %1 초 ',\n                        Cocodron_Dron_Controller_mode: '드론/rc카 모드변경  ',\n                        Cocodron_Dron_Controller_opt: '광학센서 on/off  ',\n                        Cocodron_Dron_Controller_gyroreset: '자이로 초기화  ',\n                        Cocodron_Dron_Controller_takeoff: '이륙  ',\n                        Cocodron_Dron_Controller_takeoffV2: '이륙 %1 %2 고도설정',\n                        Cocodron_Dron_Controller_land: '착륙  ',\n                        Cocodron_Dron_Controller_emergency: '비상정지  ',\n                        Cocodron_Dron_Controller_headless: '헤드리스 모드  ',\n                        //Cocodron_Dron_Controller_move_drone: '%1 조이스틱을 %2 방향으로 %3 만큼 %4 ms 유지  ',\n                        Cocodron_Dron_Controller_up:\n                            '상승 조종기레버를 %1만큼 이동시켜 %2ms동안 유지하여 드론이 이동  ',\n                        Cocodron_Dron_Controller_down:\n                            '하강 조종기레버를 %1만큼 이동시켜 %2ms동안 유지하여 드론이 이동  ',\n                        Cocodron_Dron_Controller_cw:\n                            '우회전 조종기레버를 %1만큼 이동시켜 %2ms동안 유지하여 드론이 이동  ',\n                        Cocodron_Dron_Controller_ccw:\n                            '좌회전 조종기레버를 %1만큼 이동시켜 %2ms동안 유지하여 드론이 이동  ',\n                        Cocodron_Dron_Controller_move_drone_forward:\n                            '앞으로 조종기레버를 %1만큼 이동시켜 %2ms동안 유지하여 드론이 이동  ',\n                        Cocodron_Dron_Controller_move_drone_back:\n                            '뒤로 조종기레버를 %1만큼 이동시켜 %2ms동안 유지하여 드론이 이동  ',\n                        Cocodron_Dron_Controller_move_drone_left:\n                            '왼쪽으로 조종기레버를 %1만큼 이동시켜 %2ms동안 유지하여 드론이 이동  ',\n                        Cocodron_Dron_Controller_move_drone_right:\n                            '오른쪽으로 조종기레버를 %1만큼 이동시켜 %2ms동안 유지하여 드론이 이동  ',\n                        Cocodron_Dron_Controller_funled: '4색 변경  ',\n                        Cocodron_Dron_Controller_flip: '플립  ',\n                        Cocodron_Dron_Controller_speed: '속도조정 ',\n                        Cocodron_Dron_Controller_simultaneousOperations: '동시비행  ',\n                    },\n                },\n                en: {\n                    template: {\n                        Cocodron_Dron_Controller_connect: 'Binding ',\n                        Cocodron_Dron_Controller_hovering: 'Hovering for %1 seconds ',\n                        Cocodron_Dron_Controller_mode: '%1 Mode ',\n                        Cocodron_Dron_Controller_opt: 'Optical Sensor ',\n                        Cocodron_Dron_Controller_gyroreset: 'Gyro Reset ',\n                        Cocodron_Dron_Controller_takeoff: 'Take Off ',\n                        Cocodron_Dron_Controller_takeoffV2: 'Take Off %1 %2 ',\n                        Cocodron_Dron_Controller_land: 'Landing ',\n                        Cocodron_Dron_Controller_emergency: 'Emergency Stop ',\n                        Cocodron_Dron_Controller_headless: 'Headless Mode ',\n                        //Cocodron_Dron_Controller_move_drone: 'Move joystick %1 in %2 direction by %3 for %4 ms',\n                        Cocodron_Dron_Controller_up: 'Ascend by %1 for %2 ms ',\n                        Cocodron_Dron_Controller_down: 'Descend by %1 for %2 ms ',\n                        Cocodron_Dron_Controller_cw: 'Rotate Clockwise by %1 for %2 ms ',\n                        Cocodron_Dron_Controller_ccw: 'Rotate Counterclockwise by %1 for %2 ms ',\n                        Cocodron_Dron_Controller_move_drone_forward: 'Move Forward by %1 for %2 ms ',\n                        Cocodron_Dron_Controller_move_drone_back: 'Move Backward by %1 for %2 ms ',\n                        Cocodron_Dron_Controller_move_drone_left: 'Move Left by %1 for %2 ms ',\n                        Cocodron_Dron_Controller_move_drone_right: 'Move Right by %1 for %2 ms ',\n                        Cocodron_Dron_Controller_funled: 'Change 4-Color LED ',\n                        Cocodron_Dron_Controller_flip: '%1 Flip ',\n                        Cocodron_Dron_Controller_speed: 'Adjust Speed %1 ',\n                        Cocodron_Dron_Controller_simultaneousOperations:\n                            'Move %1 in %2 %3 while moving %4 in %5 %6 ',\n                    },\n                    Device: {\n                        cocodron_dron_controller: 'cocodroncontroller',\n                    },\n                    Menus: {\n                        cocodron_dron_controller: 'CocodronController',\n                    },\n                },\n                ja: {\n                    template: {\n                        Cocodron_Dron_Controller_connect: 'バインディング  ',\n                        Cocodron_Dron_Controller_hovering: 'ホバーリング  %1 秒  ',\n                        Cocodron_Dron_Controller_mode: '%1 モード  ',\n                        Cocodron_Dron_Controller_opt: '光学センサー  ',\n                        Cocodron_Dron_Controller_gyroreset: 'ジャイロ初期化  ',\n                        Cocodron_Dron_Controller_takeoff: '離陸',\n                        Cocodron_Dron_Controller_takeoffV2: '離陸 %1 %2',\n                        Cocodron_Dron_Controller_land: '着陸  ',\n                        Cocodron_Dron_Controller_emergency: '緊急停止  ',\n                        Cocodron_Dron_Controller_headless: 'ヘッドレスモード  ',\n                        //Cocodron_Dron_Controller_move_drone: '%1 조이스틱을 %2 방향으로 %3 만큼 %4 ms 유지  ',\n                        Cocodron_Dron_Controller_up: '%1 上昇 %2 ms キープ  ',\n                        Cocodron_Dron_Controller_down: '%1 上昇 %2 ms キープ  ',\n                        Cocodron_Dron_Controller_cw: '%1 右回転 %2 ms キープ  ',\n                        Cocodron_Dron_Controller_ccw: '%1 左回転 %2 ms キープ  ',\n                        Cocodron_Dron_Controller_move_drone_forward: '%1 前方移動  %2 ms キープ  ',\n                        Cocodron_Dron_Controller_move_drone_back: '%1 前方移動  %2 ms キープ  ',\n                        Cocodron_Dron_Controller_move_drone_left: '%1 左移動  %2 ms キープ  ',\n                        Cocodron_Dron_Controller_move_drone_right: '%1 右移動  %2 ms キープ  ',\n                        Cocodron_Dron_Controller_funled: '4色LED カラー変更  ',\n                        Cocodron_Dron_Controller_flip: '%1 フリップ  ',\n                        Cocodron_Dron_Controller_speed: '速度調整 %1 ',\n                        Cocodron_Dron_Controller_simultaneousOperations:\n                            '%1 方向へ %2 %3  %4 方向へ %5 %6 移動  ',\n                    },\n                    Device: {\n                        cocodron_dron_controller: 'ココドローン 操縦機',\n                    },\n                    Menus: {\n                        cocodron_dron_controller: 'ココドローン 操縦機',\n                    },\n                },\n            };\n        }\n\n        initializeBlocks() {\n            Entry.hwLite\n                .connect()\n                .then(() => {\n                    if (!Entry.hwLite.serial) {\n                        console.error('Serial object is not defined. Please check the connection.');\n                        return;\n                    }\n\n                    Entry.getMainGenerator().getBlocks = this.getBlocks.bind(this);\n\n                    Entry.addEventListener('blockCompleted', () => {\n                        Entry.getMainGenerator().nextBlock();\n                    });\n                })\n                .catch((error) => {\n                    console.error('Failed to connect to hardware:', error);\n                });\n        }\n\n        getBlocks() {\n            return {\n                Cocodron_Dron_Controller_connect: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    params: [],\n                    def: { params: [], type: 'Cocodron_Dron_Controller_connect' },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'mapping_start';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_hovering: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [{ type: 'Block', accept: 'string' }],\n                    def: {\n                        params: [null],\n                        type: 'Cocodron_Dron_Controller_hovering',\n                    },\n                    paramsKeyMap: {\n                        TIME: 0,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const time = script.getField('TIME');\n\n                        return new Promise((resolve) => {\n                            setTimeout(() => {\n                                resolve(script.callReturn());\n                            }, time);\n                        });\n                    },\n                },\n                Cocodron_Dron_Controller_mode: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.Cocodron_Dron_Controller_mode_drone, 'drone'],\n                                [Lang.Blocks.Cocodron_Dron_Controller_mode_rccar, 'rccar'],\n                            ],\n                            value: 'drone',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                        type: 'Cocodron_Dron_Controller_mode',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const direction = script.getField('DIRECTION');\n                        const command = `${direction}\\r`;\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_opt: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    params: [],\n                    def: { params: [], type: 'Cocodron_Dron_Controller_opt' },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'opt';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_gyroreset: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    params: [],\n                    def: { params: [], type: 'Cocodron_Dron_Controller_gyroreset' },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'gyroreset';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_takeoff: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    params: [],\n                    def: { params: [], type: 'Cocodron_Dron_Controller_takeoff' },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'takeoff';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        console.log(`Sending command: ${command}`);\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 4500);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_takeoffV2: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_takeoffV2',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'takeoff';\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 20) {\n                            stick = 20;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            const firstCommand = `takeoff\\r`;\n                            const secondCommand = `up ${stick} ${time}\\r`;\n\n                            return new Promise((resolve) => {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(\n                                    Buffer.from(firstCommand, 'utf8'),\n                                    false\n                                );\n                                console.log('firstCommand:', firstCommand);\n                                setTimeout(() => {\n                                    Entry.hwLite.serial.sendAsyncWithThrottle(\n                                        Buffer.from(secondCommand, 'utf8'),\n                                        false\n                                    );\n                                    console.log('secondCommand:', secondCommand);\n                                    resolve(script.callReturn());\n                                }, 4000);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_land: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [],\n                    def: { params: [], type: 'Cocodron_Dron_Controller_land' },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'land';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        console.log(`Sending command: ${command}`);\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_emergency: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [],\n                    def: { params: [], type: 'Cocodron_Dron_Controller_emergency' },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'emergency';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_headless: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [],\n                    def: { params: [null], type: 'Cocodron_Dron_Controller_headless' },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'headless';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_up: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_up',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n\n                        const command = `up ${stick} ${time}\\r`;\n                        console.log('Constructed command:', command);\n\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, time + 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Cocodron_Dron_Controller_down: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_down',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n\n                        const command = `down ${stick} ${time}\\r`;\n                        console.log('Constructed command:', command);\n\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, time + 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                //드론 회전블럭 레버값 및 시간 입력코드\n                Cocodron_Dron_Controller_cw: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_cw',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n\n                        const command = `cw ${stick} ${time}\\r`;\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, time + 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Cocodron_Dron_Controller_ccw: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_ccw',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n\n                        const command = `ccw ${stick} ${time}\\r`;\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, time + 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Cocodron_Dron_Controller_move_drone_forward: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_move_drone_forward',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n                        const command = `forward ${stick} ${time}\\r`;\n                        console.log('Constructed command:', command);\n\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, time + 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Cocodron_Dron_Controller_move_drone_back: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_move_drone_back',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n                        const command = `back ${stick} ${time}\\r`;\n                        console.log('Constructed command:', command);\n\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, time + 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Cocodron_Dron_Controller_move_drone_left: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_move_drone_left',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n\n                        const command = `left ${stick} ${time}\\r`;\n                        console.log('Constructed command:', command);\n\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, time + 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Cocodron_Dron_Controller_move_drone_right: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Cocodron_Dron_Controller_move_drone_right',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script);\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < 0) {\n                            stick = 0;\n                        }\n\n                        const command = `right ${stick} ${time}\\r`;\n                        console.log('Constructed command:', command);\n\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, time + 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Cocodron_Dron_Controller_funled: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [],\n                    def: { params: [], type: 'Cocodron_Dron_Controller_funled' },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const command = 'funled';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Cocodron_Dron_Controller_flip: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.Cocodron_Dron_Controller_flip_f, 'f'],\n                                [Lang.Blocks.Cocodron_Dron_Controller_flip_b, 'b'],\n                                [Lang.Blocks.Cocodron_Dron_Controller_flip_l, 'l'],\n                                [Lang.Blocks.Cocodron_Dron_Controller_flip_r, 'r'],\n                            ],\n                            value: 'f',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                        type: 'Cocodron_Dron_Controller_flip',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const direction = script.getField('DIRECTION');\n                        const command = `flip ${direction}\\r`;\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Cocodron_Dron_Controller_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                        type: 'Cocodron_Dron_Controller_speed',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const direction = script.getField('DIRECTION');\n                        const command = `speed ${direction}\\r`;\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                //드론 원주비행(동시동작) 블록 코드, 코드개발 필요, 좌우레버 동시명령어 실행으로 원주비행_동시명령어 실행간격0.5초대기 필요\n                Cocodron_Dron_Controller_simultaneousOperations: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [\n                                    Lang.Blocks.Cocodron_Dron_Controller_simultaneousOperations_cw,\n                                    'cw',\n                                ],\n                                [\n                                    Lang.Blocks.Cocodron_Dron_Controller_simultaneousOperations_ccw,\n                                    'ccw',\n                                ],\n                                [\n                                    Lang.Blocks.Cocodron_Dron_Controller_simultaneousOperations_up,\n                                    'up',\n                                ],\n                                [\n                                    Lang.Blocks\n                                        .Cocodron_Dron_Controller_simultaneousOperations_down,\n                                    'down',\n                                ],\n                            ],\n                            value: 'cw',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [\n                                    Lang.Blocks\n                                        .Cocodron_Dron_Controller_simultaneousOperations_forward,\n                                    'forward',\n                                ],\n                                [\n                                    Lang.Blocks\n                                        .Cocodron_Dron_Controller_simultaneousOperations_back,\n                                    'back',\n                                ],\n                                [\n                                    Lang.Blocks\n                                        .Cocodron_Dron_Controller_simultaneousOperations_left,\n                                    'left',\n                                ],\n                                [\n                                    Lang.Blocks\n                                        .Cocodron_Dron_Controller_simultaneousOperations_right,\n                                    'right',\n                                ],\n                            ],\n                            value: 'forward',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [\n                            [null, null, null],\n                            [null, null, null],\n                        ],\n                        type: 'Cocodron_Dron_Controller_simultaneousOperations',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                        VALUE: 1,\n                        TIME: 1,\n                        TURN_DIRECTION: 3,\n                        TURN_VALUE: 4,\n                        TURN_TIME: 5,\n                    },\n                    class: 'cocodron',\n                    isNotFor: ['cocodroncontrollerLite'],\n                    func(sprite, script) {\n                        const direction = script.getField('DIRECTION');\n                        const value = parseInt(script.getNumberValue('VALUE', script));\n                        const time = parseInt(script.getNumberValue('TIME', script)); // ms\n                        const turnDirection = script.getField('TURN_DIRECTION');\n                        const turnValue = parseInt(script.getNumberValue('TURN_VALUE', script));\n                        const turnTime = parseInt(script.getNumberValue('TURN_TIME', script)); // ms\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            const firstCommand = `${direction} ${value} ${time}\\r`;\n                            const secondCommand = `${turnDirection} ${turnValue} ${turnTime}\\r`;\n\n                            return new Promise((resolve) => {\n                                // 첫 번째 명령 전송\n                                Entry.hwLite.serial.sendAsyncWithThrottle(\n                                    Buffer.from(firstCommand, 'utf8'),\n                                    false\n                                );\n                                console.log('First command sent:', firstCommand);\n\n                                // 지정된 time 만큼 기다린 뒤 + 0.5초 후 두 번째 명령 전송\n                                setTimeout(() => {\n                                    Entry.hwLite.serial.sendAsyncWithThrottle(\n                                        Buffer.from(secondCommand, 'utf8'),\n                                        false\n                                    );\n                                    console.log('Second command sent:', secondCommand);\n\n                                    // 두 번째 명령 실행도 끝난 뒤 스크립트 종료\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, turnTime);\n                                }, 500);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n            };\n        }\n    })();\n})();\n\nmodule.exports = Entry.cocodroncontrollerLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_codewiz_lite.js",
    "content": "'use strict';\n\n(function () {\n    Entry.CodeWizLite = new (class CodeWizLite {\n        constructor() {\n            this.id = '011201';\n            this.name = 'CodeWizLite';\n            this.url = 'https://www.codable.co.kr';\n            this.imageName = 'codewizlite.png';\n            this.title = {\n                ko: '코드위즈',\n                en: 'CodeWiz',\n            };\n            this.duration = 32;\n\n            this.portData = {\n                baudRate: 115200,\n                duration: 32,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n            };\n\n            this.receiveType = {\n                SENSOR_TYPE1: 0,\n                SENSOR_TYPE2: 1,\n                HUSKY_RESULTS: 2,\n                BOOLEAN: 3,\n                INT: 4,\n                FLOAT: 5,\n                RUN_OK: 6,\n            };\n\n            this.defaultSensorList = ['SOUND', 'LIGHT', 'DIST', 'HALL'];\n            this.defaultSensorList2 = [\n                'touchPin_13',\n                'touchPin_14',\n                'touchPin_15',\n                'touchPin_27',\n                'touchPin_32',\n                'touchPin_33',\n                'switchButton_4',\n                'switchButton_26',\n                'GYRO_X',\n                'GYRO_Y',\n                'GYRO_Z',\n                'tempSensor',\n            ];\n\n            this.isDraing = false;\n            this.isFirst = true;\n\n            this.blockMenuBlocks = [\n                'CodeWizLite_sensor_title',\n                'CodeWizLite_get_sensor',\n                'CodeWizLite_get_gyroSensor',\n                'CodeWizLite_isPushedButton',\n                'CodeWizLite_touchPin',\n\n                'CodeWizLite_buzzer_title',\n                'CodeWizLite_default_buzzer',\n\n                'CodeWizLite_neopixel_title',\n                'CodeWizLite_neopixel_init',\n                'CodeWizLite_neopixel_brightness',\n                'CodeWizLite_neopixel_setColor_one',\n                'CodeWizLite_neopixel_setColor_one2',\n                'CodeWizLite_neopixel_off_one',\n                'CodeWizLite_neopixel_setColor_all',\n                'CodeWizLite_neopixel_setColor_all2',\n                'CodeWizLite_neopixel_off_all',\n                'CodeWizLite_neopixel_OnPixelRandomColor',\n                'CodeWizLite_neopixel_fillRandom',\n                'CodeWizLite_neopixel_rotate',\n                'CodeWizLite_neopixel_shift',\n                'CodeWizLite_neopixel_gradationRGB',\n                'CodeWizLite_neopixel_gradationHSL',\n                'CodeWizLite_neopixel_wheeeeeeel',\n\n                'CodeWizLite_OLED_title',\n                'CodeWizLite_OLED_clear',\n                'CodeWizLite_OLED_mirror',\n                'CodeWizLite_OLED_setSize',\n                'CodeWizLite_OLED_setPosition',\n                'CodeWizLite_OLED_println',\n                'CodeWizLite_OLED_isCollision',\n                'CodeWizLite_OLED_specialChar',\n                'CodeWizLite_OLED_setFont',\n                'CodeWizLite_OLED_startScroll',\n                'CodeWizLite_OLED_stopScroll',\n                'CodeWizLite_OLED_drawPoint',\n                'CodeWizLite_OLED_drawLine1',\n                'CodeWizLite_OLED_drawLine2',\n                'CodeWizLite_OLED_drawLine3',\n                'CodeWizLite_OLED_drawRect',\n                'CodeWizLite_OLED_drawCircle',\n                'CodeWizLite_OLED_drawPoligon',\n                'CodeWizLite_OLED_printHG',\n\n                'CodeWizLite_DIGITAL_OUTPUT_title',\n                'CodeWizLite_DIGITAL_OUTPUT_digitalWrite',\n                'CodeWizLite_DIGITAL_OUTPUT_pwmWrite',\n\n                'CodeWizLite_OzEye_title',\n                'CodeWizLite_OzEye_initOzEye',\n                'CodeWizLite_OzEye_setModeOfOzEye',\n                'CodeWizLite_OzEye_readOzEye',\n                'CodeWizLite_OzEye_isLearnedOzEye',\n                'CodeWizLite_OzEye_isContainOzEye',\n                'CodeWizLite_OzEye_getCountLearnedOzEye',\n                'CodeWizLite_OzEye_hasTypeOzEye',\n                'CodeWizLite_OzEye_getArrowInfoOzEye',\n                'CodeWizLite_OzEye_getBoxInfoOzEye2',\n                'CodeWizLite_OzEye_getBoxInfoOzEye',\n                // 'CodeWizLite_OzEye_writeTextOzEye',\n                // 'CodeWizLite_OzEye_clearTextOzEye',\n                'CodeWizLite_OzEye_setLightLevel',\n                'CodeWizLite_OzEye_LightOff',\n\n                'CodeWizLite_HuskyLens_title',\n                'CodeWizLite_HuskyLens_initHuskyLens',\n                'CodeWizLite_HuskyLens_setModeOfHuskyLens',\n                'CodeWizLite_HuskyLens_readHuskyLens',\n                'CodeWizLite_HuskyLens_isLearnedHuskyLens',\n                'CodeWizLite_HuskyLens_isContainHuskyLens',\n                'CodeWizLite_HuskyLens_getCountLearnedHuskyLens',\n                'CodeWizLite_HuskyLens_hasTypeHuskyLens',\n                'CodeWizLite_HuskyLens_getArrowInfoHuskyLens',\n                'CodeWizLite_HuskyLens_getBoxInfoHuskyLens2',\n                'CodeWizLite_HuskyLens_getBoxInfoHuskyLens',\n                'CodeWizLite_HuskyLens_writeTextHuskyLens',\n                'CodeWizLite_HuskyLens_clearTextHuskyLens',\n\n                'CodeWizLite_Servo_title',\n                'CodeWizLite_Servo_setAngle',\n                'CodeWizLite_Servo_menuSpeed',\n                'CodeWizLite_Servo_customSpeed',\n\n                'CodeWizLite_Dc_title',\n                'CodeWizLite_Dc_setCarSpeed',\n                'CodeWizLite_Dc_setValue_Waterpump',\n\n                'CodeWizLite_DotMatrix_title',\n                'CodeWizLite_DotMatrix_init',\n                'CodeWizLite_DotMatrix_setBrightness',\n                'CodeWizLite_DotMatrix_printString',\n                'CodeWizLite_DotMatrix_setLine',\n                // 'CodeWizLite_DotMatrix_Show_Custom_Image',\n                'CodeWizLite_DotMatrix_setDot',\n                'CodeWizLite_DotMatrix_clear',\n                'CodeWizLite_DotMatrix_clearAll',\n\n                'CodeWizLite_ColorSensor_title',\n                'CodeWizLite_ColorSensor_isColor',\n                'CodeWizLite_ColorSensor_getColorValue',\n\n                'CodeWizLite_DHT_title',\n                'CodeWizLite_DHT_init',\n                'CodeWizLite_DHT_getValue',\n\n                'CodeWizLite_Joystick_title',\n                'CodeWizLite_Joystick_setPin',\n                'CodeWizLite_Joystick_readAxis',\n                'CodeWizLite_Joystick_readButton',\n\n                'CodeWizLite_etcReadSensor_title',\n                'CodeWizLite_etcReadSensor_mconRead',\n                'CodeWizLite_etcReadSensor_digitalRead',\n                'CodeWizLite_etcReadSensor_InfraredThermometerRead',\n            ];\n\n            this.sensorTypes = {\n                READ: 1,\n                WRITE: 0,\n            };\n\n            this.setZero();\n        }\n\n        __sleep(ms) {\n            return new Promise((resolve) => setTimeout(resolve, ms));\n        }\n\n        // 하드웨어 연결 후 초기화를 위한 함수입니다.\n        async initialHandshake() {\n            const runApp0 = [0xc0, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0];\n            // DTR과 RTS 설정\n            await Entry.hwLite.serial.port.setSignals({\n                dataTerminalReady: false,\n                requestToSend: true,\n            });\n            // console.log('Successfully set DTR false and RTS true.');\n            await this.__sleep(200);\n\n            await Entry.hwLite.serial.port.setSignals({\n                dataTerminalReady: true,\n                requestToSend: false,\n            });\n            // console.log('Successfully set DTR true and RTS false.');\n            await this.__sleep(800);\n\n            await Entry.hwLite.serial.port.setSignals({\n                dataTerminalReady: false,\n                requestToSend: false,\n            });\n            // console.log('Successfully set DTR false and RTS false.');\n            await this.__sleep(1000);\n\n            await Entry.hwLite.serial.sendAsync(runApp0);\n\n            return true;\n        }\n\n        // 시작하기 및 정지하기 시 기기상태를 초기화하기 위한 함수입니다.\n        setZero() {\n            this.sendBuffers = [];\n            this.recvBuffers = [];\n\n            this.sensorData = {\n                SOUND: 0,\n                LIGHT: 0,\n                DIST: 0,\n                HALL: 0,\n                touchPin_13: 0,\n                touchPin_14: 0,\n                touchPin_15: 0,\n                touchPin_27: 0,\n                touchPin_32: 0,\n                touchPin_33: 0,\n                switchButton_4: 0,\n                switchButton_26: 0,\n                tempSensor: 0.0,\n                GYRO_X: 0,\n                GYRO_Y: 0,\n                GYRO_Z: 0,\n                HUSKY_READ: {\n                    _type: 0,\n                    _count: 0,\n                    _list: [],\n                },\n            };\n\n            this.HUSKY = {\n                CENT_X: 160,\n                CENT_Y: 120,\n                getDist: function (x, y) {\n                    return Math.sqrt(Math.pow(this.CENT_X - x, 2) + Math.pow(this.CENT_Y - y, 2));\n                },\n            };\n\n            this.sendQueue = {\n                ORDER: {},\n                RESET: 1,\n            };\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                const reset = [254, 255, 3, 1, 0];\n                Entry.hwLite.serial.sendAsync(reset);\n            }\n        }\n\n        // 기기로부터 값을 읽어서 WS에 반영하는 함수입니다. (기기로부터값 읽음)\n        //this.portData.constantServing일 경우 사용합니다.\n        handleLocalData(data) {\n            const datas = this.getDataByBuffer(data);\n\n            datas.forEach((readData) => {\n                let value;\n                switch (readData[1]) {\n                    case this.receiveType.SENSOR_TYPE1: {\n                        for (let i = 1; 2 * i < readData.length; ++i) {\n                            value = (readData[i * 2] << 8) | readData[i * 2 + 1];\n                            if (i === 3) {\n                                if (value < 3000) {\n                                    Entry.CodeWizLite.sensorData.DIST = value;\n                                }\n                            } else if (i === 4) {\n                                Entry.CodeWizLite.sensorData.HALL = value - 300;\n                            } else {\n                                this.sensorData[this.defaultSensorList[i - 1]] = value;\n                            }\n                        }\n                        this.shouldUpdateSensor1 = true;\n                        return;\n                    }\n                    case this.receiveType.SENSOR_TYPE2: {\n                        let _value;\n                        for (let i = 0; i < 8; ++i) {\n                            _value = (readData[2] >> i) & 1;\n                            this.sensorData[this.defaultSensorList2[i]] = _value === 1;\n                        }\n                        for (let i = 8; i < 8 + 3; ++i) {\n                            _value = readData[i - 5];\n                            if (_value <= 180) {\n                                this.sensorData[this.defaultSensorList2[i]] = _value - 90;\n                            }\n                        }\n                        //temperature\n                        _value = (readData[6] << 8) | readData[7];\n                        _value -= 400;\n                        _value /= 10.0;\n                        if (_value < 81) {\n                            this.sensorData[this.defaultSensorList2[11]] = _value;\n                        }\n                        this.shouldUpdateSensor2 = true;\n                        return;\n                    }\n                    case this.receiveType.HUSKY_RESULTS: {\n                        Entry.CodeWizLite.sensorData.HUSKY_READ._type = readData[2];\n                        Entry.CodeWizLite.sensorData.HUSKY_READ._count = readData[3];\n                        Entry.CodeWizLite.sensorData.HUSKY_READ._list = [];\n                        for (let i = 0; i < readData[3]; ++i) {\n                            Entry.CodeWizLite.sensorData.HUSKY_READ._list.push([\n                                readData[9 * i + 4],\n                                (readData[9 * i + 5] << 8) | readData[9 * i + 6],\n                                (readData[9 * i + 7] << 8) | readData[9 * i + 8],\n                                (readData[9 * i + 9] << 8) | readData[9 * i + 10],\n                                (readData[9 * i + 11] << 8) | readData[9 * i + 12],\n                            ]);\n                        }\n                        this.shouldUpdateHusky = true;\n                        return;\n                    }\n                    case this.receiveType.RUN_OK: {\n                        // this.handler.write(this.curId, { value: 'runOK' });\n                        this.sensorData[this.curId] = { value: 'runOK' };\n\n                        return;\n                    }\n                    case this.receiveType.BOOLEAN: {\n                        // this.handler.write(this.curId, { value: readData[2] === 1 });\n                        this.sensorData[this.curId] = { value: readData[2] === 1 };\n                        return;\n                    }\n                    case this.receiveType.INT: {\n                        let _sign = readData[2] === 1;\n                        let _value = (readData[3] << 8) | readData[4];\n                        if (_sign) {\n                            _value *= -1;\n                        }\n                        // this.handler.write(this.curId, { value: _value });\n                        this.sensorData[this.curId] = { value: _value };\n                        return;\n                    }\n                    case this.receiveType.FLOAT: {\n                        let _sign = readData[2] & 0x80; // -: 1, +:0\n                        let firstData = readData[2] & 0x7f;\n                        let _value = (firstData << 8) | readData[3];\n                        if (_sign === 1) {\n                            _value *= -1;\n                        }\n                        _value /= 10;\n                        // this.handler.write(this.curId, { value: _value });\n                        this.sensorData[this.curId] = { value: _value };\n                        return;\n                    }\n                    default: {\n                        return;\n                    }\n                }\n            });\n        }\n\n        /*\n        하드웨어 기기에 전달할 데이터를 반환합니다.\n        slave 모드인 경우 duration 속성 간격으로 지속적으로 기기에 요청을 보냅니다.\n        */\n\n        //WS의 블록동작의 명령을 기기에게 쓰는 함수입니다. (기기에 값 쓰기)\n        //this.portData.constantServing일 경우 사용합니다\n        requestLocalData() {\n            if (this.sendBuffers.length > 0) {\n                const dataToSend = this.sendBuffers.shift();\n                return dataToSend;\n            }\n            return null;\n        }\n\n        getHashKey(opcode) {\n            // let key = new Date().getSeconds().toString(16);\n            // if (key.length === 1) {\n            //     key += ((Math.random() * 16) | 0).toString(16);\n            // }\n            // return Entry.generateHash(6) + opcode;\n            // Symbol을 쓰면 hw로 넘길수있나 -> 있으면 지금과 비교해서 속도는?\n            return Date.now().toString().substring(6) + opcode;\n        }\n\n        // 코드위즈에 보낼 데이터를 만드는 함수입니다.\n        sendOrder(order) {\n            Entry.CodeWizLite.intervalId = true;\n            const id = this.getHashKey(order.value.opcode);\n            this.sendQueue.ORDER[id] = order;\n            Entry.hwLite.serial.update();\n\n            let buffer = null;\n            if (this.sendQueue.ORDER) {\n                const keys = Object.keys(this.sendQueue.ORDER);\n                keys.forEach((id) => {\n                    const data = this.sendQueue.ORDER[id];\n                    if (data) {\n                        buffer = this.makeSendMessage(data.type, data.value);\n                        if (buffer?.length > 0) {\n                            this.sendBuffers.push(buffer);\n                            this.curId = id;\n                        }\n                    }\n                });\n            }\n            this.deleteOrder(id);\n\n            return id;\n        }\n\n        deleteOrder(id) {\n            Entry.CodeWizLite.sensorData[id] = { value: null };\n            delete this.sendQueue.ORDER[id];\n            Entry.hwLite.serial.update();\n        }\n\n        getOffsetX(str) {\n            return this.getByteLength(str) * 1.5 - 18;\n        }\n\n        getByteLength(s, b, i, c) {\n            if (!s) {\n                return;\n            }\n            for (b = i = 0; (c = s.charCodeAt(i++)); b += c >> 11 ? 3 : c >> 7 ? 2 : 1);\n            return b;\n        }\n\n        getMonitorPort() {\n            return { ...this.sensorData };\n        }\n\n        get monitorTemplate() {\n            return {\n                imgPath: 'hw_lite/codewizlite.png',\n                width: 200,\n                height: 200,\n\n                mode: 'both',\n            };\n        }\n\n        processData(dataArr) {\n            let retVal = [];\n            for (let i = 0; i < dataArr.length; ++i) {\n                retVal.push(...this.strToAscii('' + dataArr[i]));\n            }\n            return retVal;\n        }\n\n        strToAscii(str) {\n            if (!str) {\n                return [];\n            }\n            // let ret = [str.length];\n            let ret = [];\n            for (let i = 0; i < str.length; ++i) {\n                // ret.push(str[i].charCodeAt());\n                let c = str[i].charCodeAt();\n                if (c > 0xff) {\n                    ret.push(0x08, c >> 8, c & 0xff);\n                } else {\n                    ret.push(c);\n                }\n            }\n            ret.unshift(ret.length);\n            return ret;\n        }\n\n        makeSendMessage(type, data) {\n            if (!$.isPlainObject(data)) {\n                return null;\n            }\n            let buffer = this.addHeader(type, [data.opcode, ...this.processData(data.params)]);\n            // console.log('makeSendMessage:', buffer);\n            return buffer;\n        }\n\n        addHeader(actionType, data) {\n            return [254, 255, data.length + 2, actionType, ...data];\n        }\n\n        getDataByBuffer(buffer) {\n            this.recvBuffers.push(...buffer);\n            let datas = [];\n            let lastIdx = 0;\n            this.recvBuffers.forEach((value, idx, d) => {\n                if (value === 0xff && d[idx + 1] === 0xfe) {\n                    lastIdx = idx + 2 + d[idx + 2];\n                    datas.push(d.slice(idx + 2, lastIdx));\n                }\n            });\n            this.recvBuffers.splice(0, lastIdx);\n            return datas;\n        }\n\n        preWait() {\n            return new Promise((resolve) => {\n                let tmp = setInterval(() => {\n                    // console.log('preWait:', Entry.CodeWizLite.intervalId);\n                    if (!Entry.CodeWizLite.intervalId) {\n                        clearInterval(tmp);\n                        // Entry.CodeWizLite.preWaitResult = Entry.CodeWizLite.preWaitList.shift() || null;\n                        resolve();\n                    }\n                }, 11);\n            });\n        }\n\n        checkComplete(timeout, id) {\n            let _promise = new Promise((resolve) => {\n                timeout = timeout ?? 1000;\n                Entry.CodeWizLite.intervalId = setInterval(() => {\n                    // console.log(Entry.CodeWizLite.intervalId, 'runOK:', Entry.CodeWizLite.sensorData[id]);\n                    let ret = Entry.CodeWizLite.sensorData[id]?.value;\n                    if (ret !== undefined && ret !== null) {\n                        clearInterval(Entry.CodeWizLite.intervalId);\n                        clearTimeout(Entry.CodeWizLite.timeoutId);\n                        Entry.CodeWizLite.intervalId = null;\n                        Entry.CodeWizLite.timeoutId = null;\n                        resolve();\n                    }\n                }, 7);\n                Entry.CodeWizLite.timeoutId = setTimeout(() => {\n                    clearInterval(Entry.CodeWizLite.intervalId);\n                    // console.log(Entry.CodeWizLite.intervalId, 'timeOut');\n                    Entry.CodeWizLite.intervalId = null;\n                    Entry.CodeWizLite.timeoutId = null;\n                    // throw new Entry.Utils.AsyncError('TimeOutOccurred');\n                    resolve();\n                }, timeout);\n            });\n            return _promise;\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        CodeWizLite_sensor_title: '기본 센서',\n                        CodeWizLite_get_sensor: '%1센서 값',\n                        CodeWizLite_get_gyroSensor: '3축 센서 %1값',\n                        CodeWizLite_isPushedButton: '%1 스위치 버튼 값',\n                        CodeWizLite_touchPin: '터치핀 %1 값',\n\n                        CodeWizLite_buzzer_title: '스피커',\n                        CodeWizLite_default_buzzer:\n                            '스피커를 %1옥타브, %2음, %3분음표로 연주하기 %4',\n\n                        CodeWizLite_neopixel_title: '네오픽셀',\n                        CodeWizLite_neopixel_init: '네오픽셀 %1에 %2개로 시작설정%3',\n                        CodeWizLite_neopixel_brightness: '네오픽셀 밝기를 %1로 설정(0~255)%2',\n                        CodeWizLite_neopixel_setColor_one: '네오픽셀 %1번 LED를 %2(으)로 켜기%3',\n                        CodeWizLite_neopixel_setColor_one2:\n                            '네오픽셀 %1번 LED를 빨강%2초록%3파랑%4(으)로 켜기%5',\n                        CodeWizLite_neopixel_off_one: '네오픽셀 %1번 LED 끄기%2',\n                        CodeWizLite_neopixel_setColor_all: '네오픽셀 %1(으)로 모두 켜기%2',\n                        CodeWizLite_neopixel_setColor_all2:\n                            '네오픽셀 빨강%1초록%2파랑%3(으)로 모두 켜기%4',\n                        CodeWizLite_neopixel_off_all: '네오픽셀 모두 끄기%1',\n                        CodeWizLite_neopixel_OnPixelRandomColor:\n                            '네오픽셀 %1번 LED 무작위 색으로 켜기%2',\n                        CodeWizLite_neopixel_fillRandom: '네오픽셀 무작위 색으로 채우기%1',\n                        CodeWizLite_neopixel_rotate: '네오픽셀 LED %1으로 회전시키기%2',\n                        CodeWizLite_neopixel_shift: '네오픽셀 LED %1으로 밀기%2',\n                        CodeWizLite_neopixel_gradationRGB:\n                            '네오픽셀 %1번부터 %2번까지 RGB그라데이션(%3,%4)으로 켜기%5',\n                        CodeWizLite_neopixel_gradationHSL:\n                            '네오픽셀 %1번부터 %2번까지 HSL그라데이션(%3,%4)으로 켜기%5',\n                        CodeWizLite_neopixel_wheeeeeeel: '네오픽셀 휠%1',\n\n                        CodeWizLite_OLED_title: 'OLED',\n                        CodeWizLite_OLED_clear: 'OLED 지우기%1',\n                        CodeWizLite_OLED_mirror: 'OLED 반전 모드%1 %2',\n                        CodeWizLite_OLED_setSize: 'OLED 문자 크기를 %1(으)로 설정%2',\n                        CodeWizLite_OLED_setPosition: 'OLED 커서위치(%1,%2)(으)로 지정%3',\n                        CodeWizLite_OLED_println: 'OLED에 %1 출력%2',\n                        CodeWizLite_OLED_isCollision: 'OLED 자동 줄바꿈%1%2',\n                        CodeWizLite_OLED_specialChar: 'OLED에 기호%1 출력하기%2',\n                        CodeWizLite_OLED_setFont: 'OLED 폰트%1를 크기%2(으)로 설정%3',\n                        CodeWizLite_OLED_startScroll: 'OLED 스크롤 시키기%1 시작%2~종료%3(0~7)%4',\n                        CodeWizLite_OLED_stopScroll: 'OLED 스크롤 멈추기%1',\n                        CodeWizLite_OLED_drawPoint: 'OLED 점찍기 (%1,%2)%3%4',\n                        CodeWizLite_OLED_drawLine1: 'OLED 선 그리기 시작(%1,%2) 끝(%3,%4)%5%6',\n                        CodeWizLite_OLED_drawLine2: 'OLED 수직선 시작(%1,%2) 길이%3%4%5',\n                        CodeWizLite_OLED_drawLine3: 'OLED 수평선 시작(%1,%2) 길이%3%4%5',\n                        CodeWizLite_OLED_drawRect: 'OLED 직사각형 시작(%1,%2) 가로%3세로%4%5%6%7',\n                        CodeWizLite_OLED_drawCircle: 'OLED 원 중심(%1,%2) 반지름%3%4%5%6',\n                        CodeWizLite_OLED_drawPoligon:\n                            'OLED 삼각형 점1(%1,%2)점2(%3,%4)점3(%5,%6)%7%8%9',\n                        CodeWizLite_OLED_printHG: 'OLED에 한글포함%1 출력, 줄바꿈%2%3',\n\n                        CodeWizLite_DIGITAL_OUTPUT_title: '기본 출력',\n                        CodeWizLite_DIGITAL_OUTPUT_digitalWrite: 'PIN%1(으)로 %2내보내기%3',\n                        CodeWizLite_DIGITAL_OUTPUT_pwmWrite: 'PIN%1(으)로 PWM %2내보내기(0~1023)%3',\n\n                        CodeWizLite_OzEye_title: '오즈아이',\n                        CodeWizLite_OzEye_initOzEye: '오즈아이 시작설정%1',\n                        CodeWizLite_OzEye_setModeOfOzEye: '오즈아이 %1알고리즘으로 설정%2',\n                        CodeWizLite_OzEye_readOzEye: '오즈아이 데이터 요청시작%1',\n                        CodeWizLite_OzEye_isLearnedOzEye:\n                            '오즈아이 ID가%1인 데이터를 학습했는가?%2',\n                        CodeWizLite_OzEye_getCountLearnedOzEye: '오즈아이가 감지한 학습데이터 수%1',\n                        CodeWizLite_OzEye_isContainOzEye:\n                            '오즈아이 ID:%1로 인식한 %2데이터가 있는가?%3',\n                        CodeWizLite_OzEye_hasTypeOzEye: '오즈아이가 읽은 데이터 타입이%1인가?%2',\n                        CodeWizLite_OzEye_getArrowInfoOzEye:\n                            '오즈아이가 읽은 ID%1인 화살표정보%2%3',\n                        CodeWizLite_OzEye_getBoxInfoOzEye2: '오즈아이가 읽은 ID%1인 사각형정보%2%3',\n                        CodeWizLite_OzEye_getBoxInfoOzEye:\n                            '오즈아이가 읽은 사각형정보%1(중심좌표가 중앙에 가장 가까운 것)%2',\n                        // CodeWizLite_OzEye_writeTextOzEye: '오즈아이 (%1,%2)에 %3출력%4',\n                        // CodeWizLite_OzEye_clearTextOzEye: '오즈아이 텍스트 지우기%1',\n                        CodeWizLite_OzEye_setLightLevel:\n                            '오즈아이 라이트 밝기를 %1 단계로 설정(1~7)%2',\n                        CodeWizLite_OzEye_LightOff: '오즈아이 라이트 끄기%1',\n\n                        CodeWizLite_HuskyLens_title: '허스키렌즈',\n                        CodeWizLite_HuskyLens_initHuskyLens: '허스키렌즈 시작설정%1',\n                        CodeWizLite_HuskyLens_setModeOfHuskyLens:\n                            '허스키렌즈 %1알고리즘으로 설정%2',\n                        CodeWizLite_HuskyLens_readHuskyLens: '허스키렌즈 데이터 요청시작%1',\n                        CodeWizLite_HuskyLens_isLearnedHuskyLens:\n                            '허스키렌즈 ID가%1인 데이터를 학습했는가?%2',\n                        CodeWizLite_HuskyLens_getCountLearnedHuskyLens:\n                            '허스키렌즈가 감지한 학습데이터 수%1',\n                        CodeWizLite_HuskyLens_isContainHuskyLens:\n                            '허스키렌즈 ID:%1로 인식한 %2데이터가 있는가?%3',\n                        CodeWizLite_HuskyLens_hasTypeHuskyLens:\n                            '허스키렌즈가 읽은 데이터 타입이%1인가?%2',\n                        CodeWizLite_HuskyLens_getArrowInfoHuskyLens:\n                            '허스키렌즈가 읽은 ID%1인 화살표정보%2%3',\n                        CodeWizLite_HuskyLens_getBoxInfoHuskyLens2:\n                            '허스키렌즈가 읽은 ID%1인 사각형정보%2%3',\n                        CodeWizLite_HuskyLens_getBoxInfoHuskyLens:\n                            '허스키렌즈가 읽은 사각형정보%1(중심좌표가 중앙에 가장 가까운 것)%2',\n                        CodeWizLite_HuskyLens_writeTextHuskyLens: '허스키렌즈 (%1,%2)에 %3출력%4',\n                        CodeWizLite_HuskyLens_clearTextHuskyLens: '허스키렌즈 텍스트 지우기%1',\n\n                        CodeWizLite_Servo_title: '서보모터',\n                        CodeWizLite_Servo_setAngle: '서보모터(%1) 각도를 %2(으)로 바꾸기%3',\n                        CodeWizLite_Servo_menuSpeed: '무한회전 서보모터(%1) %2속도로 정하기%3',\n                        CodeWizLite_Servo_customSpeed:\n                            '무한회전 서보모터(%1) %2속도로 정하기(-100~100)%3',\n\n                        CodeWizLite_Dc_title: 'DC 모터',\n                        CodeWizLite_Dc_setCarSpeed:\n                            'WizCar모터에 왼쪽%1, 오른쪽%2 내보내기(-1000~1000)%3',\n                        CodeWizLite_Dc_setValue_Waterpump: '워터펌프(%1)에 %2내보내기(0~1023)%3',\n\n                        CodeWizLite_DotMatrix_title: '도트매트릭스',\n                        CodeWizLite_DotMatrix_init: '도트매트릭스 %1개 DIN%2, CS%3, CLK%4로 설정%5',\n                        CodeWizLite_DotMatrix_setBrightness:\n                            '도트매트릭스 %1번 밝기를 %2(으)로 설정%3',\n                        CodeWizLite_DotMatrix_printString: '도트매트릭스 %1번에 문자열%2 출력%3',\n                        CodeWizLite_DotMatrix_setLine: '도트매트릭스 %1번의 %2%3 %4(으)로 만들기%5',\n                        // CodeWizLite_DotMatrix_Show_Custom_Image:\n                        //     '도트매트릭스 %1번에 LED %2 켜기 %3',\n                        CodeWizLite_DotMatrix_setDot: '도트매트릭스 %1번의 %2행%3열 %4%5',\n                        CodeWizLite_DotMatrix_clear: '도트매트릭스 %1번 지우기%2',\n                        CodeWizLite_DotMatrix_clearAll: '도트매트릭스 모두 지우기%1',\n\n                        CodeWizLite_ColorSensor_title: '컬러센서',\n                        CodeWizLite_ColorSensor_isColor: 'MCON 컬러센서 감지된 색이 %1인가%2',\n                        CodeWizLite_ColorSensor_getColorValue: 'MCON 컬러센서 %1값%2',\n\n                        CodeWizLite_DHT_title: '디지털 온습도',\n                        CodeWizLite_DHT_init: '디지털 온습도 pin%1에 설정%2',\n                        CodeWizLite_DHT_getValue: '디지털 온습도 %1값%2',\n\n                        CodeWizLite_Joystick_title: '조이스틱',\n                        CodeWizLite_Joystick_setPin:\n                            '조이스틱 설정하기(X축%1, Y축%2, 버튼%3, 범위%4)%5',\n                        CodeWizLite_Joystick_readAxis: '조이스틱 %1의 값%2',\n                        CodeWizLite_Joystick_readButton: '조이스틱 버튼 값%1',\n\n                        CodeWizLite_etcReadSensor_title: '기타 입력센서',\n                        CodeWizLite_etcReadSensor_mconRead: 'MCON%1(pin%2)의 측정값%3',\n                        CodeWizLite_etcReadSensor_digitalRead: '%1(pin%2)의 측정값%3',\n                        CodeWizLite_etcReadSensor_InfraredThermometerRead:\n                            '비접촉온도센서 %1에 %2로 읽기%3',\n                    },\n\n                    Helper: {\n                        CodeWizLite_get_sensor: `주변의 소리값을 0~1023 사이 값으로 알려줍니다.\n        \n                        ▼을 클릭하여 빛, 거리, 홀, 온도를 선택하여\n                        주변의 밝기, 거리, 자성, 보드의 온도를 확인할 수 있습니다.`,\n                        CodeWizLite_get_gyroSensor: `선택된 축의 기울기를 -90~90 사이 값으로 알려줍니다.\n                        ▼을 눌러 X축, Y축, Z축을 선택할 수 있습니다.`,\n                        CodeWizLite_isPushedButton: `왼쪽/오른쪽 버튼을 누르면 “참” 으로 판단합니다.\n                        ▼을 눌러 왼쪽, 오른쪽을 선택할 수 있습니다.`,\n                        CodeWizLite_touchPin: `🐻 모양의 터치센서를 손가락으로 터치하면 “참“으로 판단합니다.\n                        ▼을 눌러 🔆,⭕, 🖐, 👊, ❌ 모양의 터치센서를 선택하면 해당 모양의 터치센서의 터치 여부도 확인할 수 있습니다.`,\n\n                        CodeWizLite_default_buzzer: `지정된 옥타브의 음을 지정된 음표로 스피커(부저)를 재생합니다.`,\n\n                        CodeWizLite_neopixel_init: `코드위즈의 네오 RGB LED 5개의 사용을 설정합니다.\n                        ▼을 눌러 SCON에 연결된 네오픽셀의 개수와 사용을 설정할 수 있습니다.`,\n                        CodeWizLite_neopixel_brightness: `밝기를 0~255 사이 값으로 지정합니다.`,\n                        CodeWizLite_neopixel_setColor_one: `입력한 번호의 LED를 선택한 색으로 켭니다.`,\n                        CodeWizLite_neopixel_setColor_one2: `입력한 번호의 LED를 빨강, 초록, 파랑에 입력된 값의 색으로 켭니다.\n                            각 값을 0~255 사이 값으로 지정합니다.`,\n                        CodeWizLite_neopixel_off_one: `입력한 번호의 LED를 끕니다.`,\n                        CodeWizLite_neopixel_setColor_all: `모든 LED를 선택한 색으로 켭니다.`,\n                        CodeWizLite_neopixel_setColor_all2: `모든 LED를 빨강, 초록, 파랑에 입력된 값의 색으로 켭니다.\n                        각 값을 0~255 사이 값으로 지정합니다.`,\n                        CodeWizLite_neopixel_off_all: `모든 LED를 끕니다.`,\n                        CodeWizLite_neopixel_OnPixelRandomColor: `입력한 번호의 LED를 무작위 색으로 켭니다.`,\n                        CodeWizLite_neopixel_fillRandom: `모든 LED를 무작위 색으로 채웁니다.`,\n                        CodeWizLite_neopixel_rotate: `모든 LED를 지정한 방향으로 회전시킵니다.\n                        방향은 ▼을 눌러 설정합니다.`,\n                        CodeWizLite_neopixel_shift: `모든 LED를 지정한 방향으로 밀어냅니다.\n                        빈자리는 기존 색으로 채워집니다.\n                        방향은 ▼을 눌러 설정합니다.`,\n                        CodeWizLite_neopixel_gradationRGB: `지정범위의 LED를 선택한 색의 그라데이션으로 채웁니다.\n                        왼쪽색부터 오른쪽색까지 RGB색표현의 그라데이션으로 채워집니다.\n                        범위는 초기화한 LED범위를 벗어날 수 없으며 서로 다른 값이여야 합니다.\n                        LED 번호가 작은 값은 왼쪽에 큰 값은 오른쪽에 위치해야합니다.`,\n                        CodeWizLite_neopixel_gradationHSL: `지정범위의 LED를 선택한 색의 그라데이션으로 채웁니다.\n                        왼쪽색부터 오른쪽색까지 HSL색표현의 그라데이션으로 채워집니다.\n                        범위는 초기화한 LED범위를 벗어날 수 없으며 서로 다른 값이여야 합니다.\n                        LED 번호가 작은 값은 왼쪽에 큰 값은 오른쪽에 위치해야합니다.`,\n                        CodeWizLite_neopixel_wheeeeeeel: `녹색, 빨강, 파랑의 세 가지색을 기준으로 섞은 색을 순환시켜 켜주는 블록입니다.\n                        이 블록을 사용해서 흐르는 듯한 네오픽셀을 표시할 수 있습니다.`,\n\n                        CodeWizLite_OLED_clear: `OLED에 표시된 내용을 지웁니다.`,\n                        CodeWizLite_OLED_mirror: `OLED에 표시할 내용의 출력 상태를 설정합니다.\n                        OFF가 기본이며, ON을 선택하면 OLED 배경에 색이 채워지고 내용이 표시됩니다.`,\n                        CodeWizLite_OLED_setSize: `글자 크기를 지정합니다.\n                        1~10 사이의 범위로 설정할 수 있습니다.`,\n                        CodeWizLite_OLED_setPosition: `글자가 출력될 위치(x좌표, y좌표)를 지정합니다.\n                        X는 0~127, Y는 0~63 사이의 범위로 설정할 수 있습니다.`,\n                        CodeWizLite_OLED_println: `입력한 내용을 OLED에 출력합니다.`,\n                        CodeWizLite_OLED_isCollision: `OLED에 출력된 내용의 줄바꿈을 설정합니다.`,\n                        CodeWizLite_OLED_specialChar: `OLED에 기호를 출력합니다.`,\n                        CodeWizLite_OLED_setFont: `글꼴과 글자 크기를 ▼ 을 눌러 설정합니다.`,\n                        CodeWizLite_OLED_startScroll: `OLED에 입력된 내용을 지정한 화살표방향으로 이동시킵니다. 시작과 종료는 y좌표를 0~7 페이지로 나눈 것으로 각 페이지는 다음과 같은 y 좌표를 가집니다.\n                        \n                        0 : y좌표 0~7\n                        1 : y좌표 8~15\n                        2 : y좌표 16~23\n                        3 : y좌표 24~31\n                        4 : y좌표 32~39\n                        5 : y좌표 40~47\n                        6 : y좌표 48~55\n                        7 : y좌표 56~63`,\n                        CodeWizLite_OLED_stopScroll: `이동을 멈춥니다.`,\n                        CodeWizLite_OLED_drawPoint: `지정된 위치 (x좌표, y좌표)에 점을 찍습니다.\n                        X는 0~127, Y는 0~63 사이의 범위로 설정할 수 있습니다.`,\n                        CodeWizLite_OLED_drawLine1: `시작 위치 (x좌표, y좌표)에서 끝 위치 (x좌표, y좌표)까지 흰색 선을 그립니다.`,\n                        CodeWizLite_OLED_drawLine2: `시작 위치 (x좌표, y좌표)에서 지정된 길이의 흰색 수직선을 그립니다.`,\n                        CodeWizLite_OLED_drawLine3: `시작 위치 (x좌표, y좌표)에서 지정된 길이의 흰색 수평선을 그립니다.`,\n                        CodeWizLite_OLED_drawRect: `시작 위치 (x좌표, y좌표)에서 지정된 가로, 세로 길이의 흰색 선 직사각형을 그립니다.\n                        ▼을 눌러 ‘비움’ 대신 ‘채움‘을 선택하면 직사각형 내부가 채워집니다.`,\n                        CodeWizLite_OLED_drawCircle: `중심(x좌표, y좌표)에서 지정된 반지름을 가지는 흰색 선 원을 그립니다.\n                        ▼을 눌러 ‘비움’ 대신 ‘채움‘을 선택하면 원 내부가 채워집니다.`,\n                        CodeWizLite_OLED_drawPoligon: `점1(x좌표, y좌표), 점2 (x좌표, y좌표), 점3 (x좌표, y좌표)을 연결하여 흰색 선 삼각형을 그립니다.\n                        ▼을 눌러 ‘비움’ 대신 ‘채움‘을 선택하면 원 내부가 채워집니다.`,\n                        CodeWizLite_OLED_printHG: `입력한 내용(한글포함)을 OLED에 출력합니다.\n                        ▼을 눌러 ‘⭕’를 선택하면 아랫줄로 커서를 이동시키고 ‘❌‘를 선택하면 마지막 글자 오른쪽으로 커서를 이동시킵니다.`,\n\n                        CodeWizLite_DIGITAL_OUTPUT_digitalWrite: `지정된 핀(터치센서 또는 SCON)에 연결된 센서로 HIGH 또는 LOW 를 내보냅니다.\n                        \n                        <현재 활용 가능한 확장도구>\n                        진동모터`,\n                        CodeWizLite_DIGITAL_OUTPUT_pwmWrite: `지정된 핀(터치센서 또는 SCON)에 연결된 센서로 입력된 값을 내보냅니다.\n                        \n                        <현재 활용 가능한 확장도구>\n                        프로펠러`,\n\n                        CodeWizLite_OzEye_initOzEye: `오즈아이 시작을 설정합니다.`,\n                        CodeWizLite_OzEye_setModeOfOzEye: `오즈아이를 선택된 알고리즘으로 설정합니다.\n        \n                        1.선 인식\n                        2.색 인식\n                        3.태그 인식\n                        4.이미지 인식\n                        5.사물 인식\n                        6.사물 추적\n                        7.선 + 태그\n                        8.얼굴 인식\n                        9.숫자 인식`,\n                        Eye_readOzEye: `오즈아이가 인식한 결과를 주기적으로 보내줍니다.`,\n                        CodeWizLite_OzEye_isLearnedOzEye: `입력한 ID 번호 데이터를 학습했다면 ‘참’으로 판단하여 알려줍니다.`,\n                        CodeWizLite_OzEye_isContainOzEye: `입력한 ID 번호의 사각형 데이터가 인식된다면 ‘참’으로 판단하여 알려줍니다.\n                            ▼을 눌러 화살표를 선택하면 화살표 데이터가 인식될 때 ‘참’으로 판단하여 알려줍니다.`,\n                        CodeWizLite_OzEye_getCountLearnedOzEye: `화면에 감지된 학습한 데이터 수를 알려줍니다.`,\n                        CodeWizLite_OzEye_hasTypeOzEye: `읽어온 데이터 타입이 선택한 타입(사각형/화살표)과 같다면 ‘참’으로 판단하여 알려줍니다.`,\n                        CodeWizLite_OzEye_getArrowInfoOzEye: `읽어온 화살표 데이터의 좌표 값을 알려줍니다. 좌표 값은 ‘시작 X좌표‘, ‘시작 Y좌표‘, ‘종료 X좌표‘, ‘종료 Y좌표‘ 중 하나를 선택합니다.\n                            대상이 없다면 -1을 반환합니다.`,\n                        CodeWizLite_OzEye_getBoxInfoOzEye2: `읽어온 사각형 데이터의 정보를 알려줍니다. 정보는 ‘중심 X좌표‘, ‘중심 Y좌표’, ‘너비‘, ‘높이’ 중 하나를 선택합니다.\n                            대상이 없다면 -1을 반환합니다.`,\n                        CodeWizLite_OzEye_getBoxInfoOzEye: `읽어온 사각형 데이터의 정보를 알려줍니다. 정보는 ‘ID’, ‘중심 X좌표‘, ‘중심 Y좌표’, ‘너비‘, ‘높이’ 중 하나를 선택합니다.\n                            대상이 없다면 -1을 반환합니다.`,\n                        // CodeWizLite_OzEye_writeTextOzEye: `오즈아이 화면의 지정된 좌표에 입력된 데이터를 출력합니다.`,\n                        // CodeWizLite_OzEye_clearTextOzEye: `오즈아이 화면에 출력되어 있는 데이터를 지웁니다.`,\n                        CodeWizLite_OzEye_setLightLevel:\n                            '오즈아이의 라이트 밝기를 1~7 단계로 설정합니다.',\n                        CodeWizLite_OzEye_LightOff: '오즈아이 라이트를 끕니다.',\n\n                        CodeWizLite_HuskyLens_initHuskyLens: `허스키렌즈 시작을 설정합니다.`,\n                        CodeWizLite_HuskyLens_setModeOfHuskyLens: `허스키렌즈를 선택된 알고리즘으로 설정합니다.\n        \n                        1.FACE_RECOGNITION\n                        2.OBJECT_TRACKING\n                        3.OBJECT_RECOGNITION\n                        4.LINE_TRACKING\n                        5.COLOR_RECOGNITION\n                        6.TAG_RECOGNITION\n                        7.OBJECT_CLASSIFICATION`,\n                        CodeWizLite_HuskyLens_readHuskyLens: `허스키렌즈가 인식한 결과를 주기적으로 보내줍니다.`,\n                        CodeWizLite_HuskyLens_isLearnedHuskyLens: `입력한 ID 번호 데이터를 학습했다면 ‘참’으로 판단하여 알려줍니다.`,\n                        CodeWizLite_HuskyLens_isContainHuskyLens: `입력한 ID 번호의 사각형 데이터가 인식된다면 ‘참’으로 판단하여 알려줍니다.\n                            ▼을 눌러 화살표를 선택하면 화살표 데이터가 인식될 때 ‘참’으로 판단하여 알려줍니다.`,\n                        CodeWizLite_HuskyLens_getCountLearnedHuskyLens: `화면에 감지된 학습한 데이터 수를 알려줍니다.`,\n                        CodeWizLite_HuskyLens_hasTypeHuskyLens: `읽어온 데이터 타입이 선택한 타입(사각형/화살표)과 같다면 ‘참’으로 판단하여 알려줍니다.`,\n                        CodeWizLite_HuskyLens_getArrowInfoHuskyLens: `읽어온 화살표 데이터의 좌표 값을 알려줍니다. 좌표 값은 ‘시작 X좌표‘, ‘시작 Y좌표‘, ‘종료 X좌표‘, ‘종료 Y좌표‘ 중 하나를 선택합니다.\n                            대상이 없다면 -1을 반환합니다.`,\n                        CodeWizLite_HuskyLens_getBoxInfoHuskyLens2: `읽어온 사각형 데이터의 정보를 알려줍니다. 정보는 ‘중심 X좌표‘, ‘중심 Y좌표’, ‘너비‘, ‘높이’ 중 하나를 선택합니다.\n                            대상이 없다면 -1을 반환합니다.`,\n                        CodeWizLite_HuskyLens_getBoxInfoHuskyLens: `읽어온 사각형 데이터의 정보를 알려줍니다. 정보는 ‘ID’, ‘중심 X좌표‘, ‘중심 Y좌표’, ‘너비‘, ‘높이’ 중 하나를 선택합니다.\n                            대상이 없다면 -1을 반환합니다.`,\n                        CodeWizLite_HuskyLens_writeTextHuskyLens: `허스키렌즈 화면의 지정된 좌표에 입력된 데이터를 출력합니다.`,\n                        CodeWizLite_HuskyLens_clearTextHuskyLens: `허스키렌즈 화면에 출력되어 있는 데이터를 지웁니다.`,\n\n                        CodeWizLite_Servo_setAngle: `선택된 커넥터(MCON/SCON)에 연결된 180도 서보모터의 각도를 입력된 각도로 회전시킵니다.(0~180)`,\n                        CodeWizLite_Servo_menuSpeed: `선택된 커넥터(MCON/SCON)에 무한회전 서보모터를 지정된 속도로 회전시킵니다.\n                        ▼을 눌러 속도를 선택합니다.(빠른/보통/느림/멈춘)`,\n                        CodeWizLite_Servo_customSpeed: `선택된 커넥터(MCON/SCON)에 무한회전 서보모터를 지정된 속도로 회전시킵니다.\n        \n                        속도 = 0 : 모터의 회전이 멈춥니다.\n                        속도 > 0 : 모터가 지정된 속도로 정방향 회전합니다.\n                        속도 < 0 : 모터가 지정된 속도로 역방향 회전합니다.`,\n\n                        CodeWizLite_Dc_setCarSpeed: `WizCar 모터에 입력한 숫자값으로 회전시킵니다.\n                        각 모터값은 -1000~-180(후진), 180~1000(전진) 사이값입니다. 바닥 상태에 따라 숫자값을 높여가면서 회전을 시켜보세요.`,\n                        CodeWizLite_Dc_setValue_Waterpump: `선택된 워터펌프를 입력한 속도로 회전시킵니다.\n                        ▼을 눌러 회전시킬 모터(MOTOR_L, MOROT_R)를 선택하고 속도는 0~1023 사이 값으로 직접 입력합니다.`,\n\n                        CodeWizLite_DotMatrix_init: `도트매트릭스가 연결된 핀을 설정합니다.\n        \n                        18, 19번 : SCON                \n                        15, 27번 : 터치센서`,\n                        CodeWizLite_DotMatrix_setBrightness: `입력된 값으로 도트매트릭스의 밝기를 설정합니다.(1~8)`,\n                        CodeWizLite_DotMatrix_printString: `입력된 문자열을 한 글자씩 출력합니다.`,\n\n                        // CodeWizLite_DotMatrix_Show_Custom_Image:\n                        //     '블록에서 선택한 LED를 선택한 밝기로 켭니다. 한번에 모든 LED를 조작할 수 있습니다.',\n\n                        CodeWizLite_DotMatrix_setLine: `지정된 행/열에 위치한 8개 LED의 ON/OFF를 각각 지정해서 제어합니다.\n        \n                        1 : ON                \n                        0 : OFF`,\n                        CodeWizLite_DotMatrix_setDot: `입력된 행,열에 위치한 LED의 ON/OFF를 지정합니다.\n        \n                        켜기 : ON\n                        끄기 : OFF`,\n                        CodeWizLite_DotMatrix_clear: `입력된 도트 매트릭스를 지웁니다.(끕니다.)`,\n                        CodeWizLite_DotMatrix_clearAll: `연결된 모든 도트 매트릭스를 지웁니다.(끕니다.)`,\n\n                        CodeWizLite_ColorSensor_isColor: `MCON에 연결된 컬러센서에 인식된 색 값이 지정된 색이라면 ‘참’으로 판단하여 알려줍니다.\n                        ▼을 빨강, 초록, 파랑, 검정, 흰색을 선택할 수 있습니다.`,\n                        CodeWizLite_ColorSensor_getColorValue: `MCON에 연결된 컬러센서에 인식된 빨강의 색상 값을 0~255 사이값으로 알려줍니다.\n                        ▼을 눌러 초록, 파랑을 선택할 수 있습니다.`,\n\n                        CodeWizLite_DHT_init: `지정한 핀으로 디지털 온습도를 설정합니다.`,\n                        CodeWizLite_DHT_getValue: `앞서 설정한 디지털 온습도에서 선택한 값을 가져옵니다.`,\n\n                        CodeWizLite_Joystick_setPin: '지정한 핀으로 조이스틱을 설정합니다.',\n                        CodeWizLite_Joystick_readAxis:\n                            '설정된 조이스틱의 지정한 축의 레버값을 읽어옵니다.',\n                        CodeWizLite_Joystick_readButton:\n                            '설정된 조이스틱의 버튼이 눌렸는지 값을 읽어옵니다.',\n\n                        CodeWizLite_etcReadSensor_mconRead: `가변저항/워터센서/토양수분센서의 측정값\n                        선택한 센서에 따라서 값이 적절히 매핑되어 반환됩니다.`,\n                        CodeWizLite_etcReadSensor_digitalRead: `버튼/포토인터럽트의 측정값\n                        해당핀의 digitalRead값을 가져옵니다.\n                        버튼의 경우 눌렸을 때 참을 반환하기 위해서 인버스를 취하고,\n                        포토인터럽트는 읽은 값 그대로 반환됩니다.\n                        `,\n                        CodeWizLite_etcReadSensor_InfraredThermometerRead: `선택된 커넥터(MCON/SCON)에 연결된 비접촉 온도 센서에 인식된 온도를 알려줍니다.\n                        ▼을 눌러 온도 단위를 선택합니다.`,\n                    },\n                },\n            };\n        }\n\n        getBlocks() {\n            return {\n                //region codeino 코드위즈\n                CodeWizLite_sensor_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_sensor_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_sensor_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_sensor_title',\n                    },\n                    class: 'CodeWizLite_default_sensor',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_get_sensor: {\n                    // Block UI : %1센서 값\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['소리', 'SOUND'],\n                                ['빛', 'LIGHT'],\n                                ['거리', 'DIST'],\n                                ['홀', 'HALL'],\n                                ['온도', 'tempSensor'],\n                            ],\n                            value: 'SOUND',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_get_sensor',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                    },\n                    isNotFor: ['CodeWizLite'],\n                    class: 'CodeWizLite_default_sensor',\n                    func: function (sprite, script) {\n                        var sensor = script.getField('SENSOR', script);\n                        var hw_sensorData = Entry.CodeWizLite.sensorData;\n                        return hw_sensorData[sensor] ?? 0;\n                    },\n                },\n                CodeWizLite_get_gyroSensor: {\n                    // Block UI : 자이로 센서 %1값\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['X', 'GYRO_X'],\n                                ['Y', 'GYRO_Y'],\n                                ['Z', 'GYRO_Z'],\n                            ],\n                            value: 'GYRO_X',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_get_gyroSensor',\n                    },\n                    paramsKeyMap: {\n                        GYRO_TYPE: 0,\n                    },\n                    isNotFor: ['CodeWizLite'],\n                    class: 'CodeWizLite_default_sensor',\n                    func: function (sprite, script) {\n                        var sensor = script.getField('GYRO_TYPE', script);\n                        var hw_sensorData = Entry.CodeWizLite.sensorData;\n                        return hw_sensorData[sensor] ?? 0;\n                    },\n                },\n                CodeWizLite_isPushedButton: {\n                    // Block UI : %1 스위치 버튼 값\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['왼쪽', 'switchButton_26'],\n                                ['오른쪽', 'switchButton_4'],\n                            ],\n                            value: 'switchButton_26',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_isPushedButton',\n                    },\n                    paramsKeyMap: {\n                        SWITCH: 0,\n                    },\n                    isNotFor: ['CodeWizLite'],\n                    class: 'CodeWizLite_default_sensor',\n                    func: function (sprite, script) {\n                        var sensor = script.getField('SWITCH', script);\n                        var hw_sensorData = Entry.CodeWizLite.sensorData;\n                        return hw_sensorData[sensor] ?? false;\n                    },\n                },\n                CodeWizLite_touchPin: {\n                    // Block UI : \"터치핀 %1 값\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['🔆(13)', 'touchPin_13'],\n                                ['⭕(14)', 'touchPin_14'],\n                                ['🖐(15)', 'touchPin_15'],\n                                ['👊(27)', 'touchPin_27'],\n                                ['🐻(32)', 'touchPin_32'],\n                                ['❌(33)', 'touchPin_33'],\n                            ],\n                            value: 'touchPin_32',\n                            fontSize: 14,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_touchPin',\n                    },\n                    paramsKeyMap: {\n                        SWITCH: 0,\n                    },\n                    isNotFor: ['CodeWizLite'],\n                    class: 'CodeWizLite_default_sensor',\n                    func: function (sprite, script) {\n                        var sensor = script.getField('SWITCH', script);\n                        var hw_sensorData = Entry.CodeWizLite.sensorData;\n                        return hw_sensorData[sensor] ?? 0;\n                    },\n                },\n                CodeWizLite_buzzer_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_buzzer_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_buzzer_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_buzzer_title',\n                    },\n                    class: 'CodeWizLite_buzzer',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_default_buzzer: {\n                    // Block UI : \"스피커를 %1옥타브, %2음, %3분음표로 연주하기%4\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['도', '0'],\n                                ['도#', '1'],\n                                ['레', '2'],\n                                ['미♭', '3'],\n                                ['미', '4'],\n                                ['파', '5'],\n                                ['파#', '6'],\n                                ['솔', '7'],\n                                ['솔#', '8'],\n                                ['라', '9'],\n                                ['시♭', '10'],\n                                ['시', '11'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['2', '2'],\n                                ['4', '4'],\n                                ['8', '8'],\n                                ['16', '16'],\n                                ['32', '32'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'CodeWizLite_default_buzzer',\n                    },\n                    paramsKeyMap: {\n                        OCTAVE: 0,\n                        NOTE: 1,\n                        BEAT: 2,\n                    },\n                    class: 'CodeWizLite_buzzer',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let octave = Number.parseInt(script.getValue('OCTAVE', script));\n                        let note = Number.parseInt(script.getValue('NOTE', script));\n                        let beat = Number.parseInt(script.getValue('BEAT', script));\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 1,\n                                params: [octave, note, beat],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n\n                        await Entry.CodeWizLite.checkComplete(1234, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                CodeWizLite_neopixel_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_neopixel_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_neopixel_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_neopixel_title',\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_neopixel_init: {\n                    // Block UI : \"네오픽셀 %1에 %2개로 시작설정%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['코드위즈', '23'],\n                                ['18', '18'],\n                                ['19', '19'],\n                            ],\n                            value: '23',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 5,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_neopixel_init',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        COUNT: 1,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _pin = script.getNumberValue('PIN', script);\n                        let _count = script.getNumberValue('COUNT', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 32,\n                                params: [_pin, _count],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_brightness: {\n                    // Block UI : \"네오픽셀 밝기를 %1로 설정(0~255)%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 22,\n                        },\n\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'CodeWizLite_neopixel_brightness',\n                    },\n                    paramsKeyMap: {\n                        BRIGHTNESS: 0,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let value = script.getNumberValue('BRIGHTNESS', script);\n                        value = Math.round(value);\n                        if (value < 0) {\n                            value = 0;\n                        } else if (value > 255) {\n                            value = 255;\n                        }\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 2,\n                                params: [value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_setColor_one: {\n                    // Block UI : \"네오픽셀 %1번 LED를 <색상표>%2(으)로 켜기%3\",\n\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', null, null],\n                        type: 'CodeWizLite_neopixel_setColor_one',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        COLOR: 1,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let num = script.getNumberValue('NUM', script) - 1;\n                        let value = script.getStringField('COLOR', script);\n\n                        let colorValue = [\n                            parseInt(value.substr(1, 2), 16),\n                            parseInt(value.substr(3, 2), 16),\n                            parseInt(value.substr(5, 2), 16),\n                        ];\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 3,\n                                params: [num, ...colorValue],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_setColor_one2: {\n                    // Block UI : \"네오픽셀 %1번 LED를 빨강%2초록%3파랑%4(으)로 켜기%5\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '255', '255', '255', null],\n                        type: 'CodeWizLite_neopixel_setColor_one2',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        R: 1,\n                        G: 2,\n                        B: 3,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let num = script.getNumberValue('NUM', script) - 1;\n                        let r = script.getNumberValue('R', script);\n                        let g = script.getNumberValue('G', script);\n                        let b = script.getNumberValue('B', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 3,\n                                params: [num, r, g, b],\n                            },\n                        };\n\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_off_one: {\n                    // Block UI : \"네오픽셀 %1번 LED 끄기%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', null],\n                        type: 'CodeWizLite_neopixel_off_one',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let num = script.getNumberValue('NUM', script) - 1;\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 4,\n                                params: [num],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_setColor_all: {\n                    // Block UI : \"네오픽셀 %1(으)로 모두 켜기%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_neopixel_setColor_all',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let value = script.getStringField('COLOR', script);\n\n                        let colorValue = [\n                            parseInt(value.substr(1, 2), 16),\n                            parseInt(value.substr(3, 2), 16),\n                            parseInt(value.substr(5, 2), 16),\n                        ];\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 5,\n                                params: [...colorValue],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_setColor_all2: {\n                    // Block UI : \"네오픽셀 빨강%1초록%2파랑%3(으)로 모두 켜기%4\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['255', '255', '255', null],\n                        type: 'CodeWizLite_neopixel_setColor_all2',\n                    },\n                    paramsKeyMap: {\n                        R: 0,\n                        G: 1,\n                        B: 2,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let r = script.getNumberValue('R', script);\n                        let g = script.getNumberValue('G', script);\n                        let b = script.getNumberValue('B', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 5,\n                                params: [r, g, b],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_off_all: {\n                    // Block UI : \"네오픽셀 모두 끄기%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_neopixel_off_all',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 6,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_OnPixelRandomColor: {\n                    // 랜덤색상 켜기 - 단일\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', null],\n                        type: 'CodeWizLite_neopixel_OnPixelRandomColor',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let num = script.getNumberValue('NUM', script) - 1;\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 3,\n                                params: [\n                                    num,\n                                    Math.floor(Math.random() * 256),\n                                    Math.floor(Math.random() * 256),\n                                    Math.floor(Math.random() * 256),\n                                ],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_fillRandom: {\n                    // 랜덤색상 켜기 - 전체\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_neopixel_fillRandom',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 43,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_rotate: {\n                    // rotate 네오픽셀\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['역방향', '0'],\n                                ['정방향', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_neopixel_rotate',\n                    },\n                    paramsKeyMap: {\n                        DIR: 0,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _dir = script.getNumberValue('DIR', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 44,\n                                params: [_dir],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_shift: {\n                    // shift 네오픽셀\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['역방향', '0'],\n                                ['정방향', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_neopixel_shift',\n                    },\n                    paramsKeyMap: {\n                        DIR: 0,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _dir = script.getNumberValue('DIR', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 45,\n                                params: [_dir],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_gradationRGB: {\n                    // RGB그라데이션\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '8', '#ff0000', '#00ff00'],\n                        type: 'CodeWizLite_neopixel_gradationRGB',\n                    },\n                    paramsKeyMap: {\n                        START: 0,\n                        END: 1,\n                        S_COLOR: 2,\n                        E_COLOR: 3,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _start = script.getNumberValue('START', script) - 1;\n                        let _end = script.getNumberValue('END', script) - 1;\n                        let _sColor = script.getStringField('S_COLOR', script);\n                        let _eColor = script.getStringField('E_COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 46,\n                                params: [_start, _end, _sColor, _eColor],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_gradationHSL: {\n                    // HSL그라데이션\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '8', '#ff0000', '#611ca1'],\n                        type: 'CodeWizLite_neopixel_gradationHSL',\n                    },\n                    paramsKeyMap: {\n                        START: 0,\n                        END: 1,\n                        S_COLOR: 2,\n                        E_COLOR: 3,\n                    },\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _start = script.getNumberValue('START', script) - 1;\n                        let _end = script.getNumberValue('END', script) - 1;\n                        let _sColor = script.getStringField('S_COLOR', script);\n                        let _eColor = script.getStringField('E_COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 47,\n                                params: [_start, _end, _sColor, _eColor],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_neopixel_wheeeeeeel: {\n                    // 휠 - 엔트리에선 느려서 활용도가 떨어질 것으로 예상해서 일단 주석\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_neopixel_wheeeeeeel',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_neopixel',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 49,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        // console.log(script.key);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                CodeWizLite_OLED_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_OLED_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_OLED_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_OLED_title',\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_OLED_clear: {\n                    // Block UI : \"OLED 지우기%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_OLED_clear',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 7,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_mirror: {\n                    // Block UI : \"OLED 반전모드%1 %2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OFF', '0'],\n                                ['ON', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OLED_mirror',\n                    },\n                    paramsKeyMap: {\n                        SWITCH: 0,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _value = script.getNumberValue('SWITCH', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 8,\n                                params: [_value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_setSize: {\n                    // Block UI : \"OLED 문자 크기를 %1(으)로 설정%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [3],\n                        type: 'CodeWizLite_OLED_setSize',\n                    },\n                    paramsKeyMap: {\n                        SIZE: 0,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _value = script.getNumberValue('SIZE', script);\n                        _value = Math.round(_value);\n                        if (_value < 1) {\n                            _value = 1;\n                        } else if (_value > 10) {\n                            _value = 10;\n                        }\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 9,\n                                params: [_value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_setPosition: {\n                    // Block UI : \"OLED 커서위치(%1,%2)(으)로 지정%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['0', '0'],\n                        type: 'CodeWizLite_OLED_setPosition',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _x = script.getNumberValue('X', script);\n                        _x = Math.round(_x);\n                        if (_x < 0) {\n                            _x = 0;\n                        } else if (_x > 255) {\n                            _x = 255;\n                        }\n\n                        let _y = script.getNumberValue('Y', script);\n                        _y = Math.round(_y);\n                        if (_y < 0) {\n                            _y = 0;\n                        } else if (_y > 255) {\n                            _y = 255;\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 10,\n                                params: [_x, _y],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_println: {\n                    // Block UI : \"OLED에 %1 출력%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['Hello, World!!'],\n                        type: 'CodeWizLite_OLED_println',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _value = script.getStringValue('TEXT');\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 11,\n                                params: [_value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_isCollision: {\n                    // Block UI : \"OLED 문자겹침 모드%1%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OFF', '0'],\n                                ['ON', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OLED_isCollision',\n                    },\n                    paramsKeyMap: {\n                        SWITCH: 0,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _value = script.getNumberValue('SWITCH', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 12,\n                                params: [_value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_specialChar: {\n                    // Block UI : \"OLED에 기호%1 출력하기%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['♥', '3'],\n                                ['◆', '4'],\n                                ['♣', '5'],\n                                ['♠', '6'],\n                                ['♬', '14'],\n                                ['▲', '30'],\n                                ['▼', '31'],\n\n                                ['😧', '1'],\n                                ['😀', '2'],\n                                ['♂', '11'],\n                                ['♀', '12'],\n                                ['↑', '24'],\n                                ['↓', '25'],\n                                ['→', '26'],\n                                ['←', '27'],\n                            ],\n                            value: '14',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OLED_specialChar',\n                    },\n                    paramsKeyMap: {\n                        CHAR: 0,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _value = script.getNumberValue('CHAR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 13,\n                                params: [_value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_setFont: {\n                    // Block UI : \"OLED 폰트%1를 크기%2(으)로 설정%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['Serif', '0'],\n                                ['Sans', '1'],\n                                ['Mono', '2'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['9', '0'],\n                                ['12', '1'],\n                                ['18', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'CodeWizLite_OLED_setFont',\n                    },\n                    paramsKeyMap: {\n                        FONT: 0,\n                        SIZE: 1,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _value = script.getNumberValue('FONT', script);\n                        let _size = script.getNumberValue('SIZE', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 14,\n                                params: [_value, _size],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_startScroll: {\n                    // Block UI : \"OLED 스크롤 시키기 옵션(%1, 범위%2~%3(0~7))%4\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['→', '0'],\n                                ['←', '1'],\n                                ['↗', '2'],\n                                ['↖', '3'],\n                            ],\n                            value: '0',\n                            fontSize: 14,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, '0', '0'],\n                        type: 'CodeWizLite_OLED_startScroll',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                        START: 1,\n                        END: 2,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _value = Number.parseInt(script.getNumberValue('DIRECTION', script));\n                        let _st = Number.parseInt(script.getNumberValue('START', script));\n                        _st = Math.round(_st);\n                        if (_st < 0) {\n                            _x = 0;\n                        } else if (_st > 7) {\n                            _st = 7;\n                        }\n                        let _ed = script.getNumberValue('END', script);\n                        _ed = Math.round(_ed);\n                        if (_ed < 0) {\n                            _ed = 0;\n                        } else if (_ed > 7) {\n                            _ed = 7;\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 15,\n                                params: [_value, _st, _ed],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_stopScroll: {\n                    // Block UI : \"OLED 스크롤 멈추기%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_OLED_stopScroll',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 16,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_drawPoint: {\n                    // Block UI : \"OLED에 점찍기 옵션((%1,%2), %3)%4\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['검은색', '0'],\n                                ['흰색', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [63, 31, null],\n                        type: 'CodeWizLite_OLED_drawPoint',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        COLOR: 2,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _x = script.getNumberValue('X', script);\n                        _x = Math.round(_x);\n                        if (_x < 0) {\n                            _x = 0;\n                        } else if (_x > 128) {\n                            _x = 128;\n                        }\n\n                        let _y = script.getNumberValue('Y', script);\n                        _y = Math.round(_y);\n                        if (_y < 0) {\n                            _y = 0;\n                        } else if (_y > 64) {\n                            _y = 64;\n                        }\n\n                        let _color = script.getNumberValue('COLOR', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 17,\n                                params: [_x, _y, _color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_drawLine1: {\n                    // Block UI : \"OLED에 선 그리기 옵션((%1,%2)~(%3,%4), %5)%6\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['검은색', '0'],\n                                ['흰색', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['0', '0', '10', '0', null],\n                        type: 'CodeWizLite_OLED_drawLine1',\n                    },\n                    paramsKeyMap: {\n                        SX: 0,\n                        SY: 1,\n                        EX: 2,\n                        EY: 3,\n                        COLOR: 4,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _sx = script.getNumberValue('SX', script);\n                        _sx = Math.round(_sx);\n                        if (_sx < 0) {\n                            _sx = 0;\n                        } else if (_sx > 128) {\n                            _sx = 128;\n                        }\n                        let _sy = script.getNumberValue('SY', script);\n                        _sy = Math.round(_sy);\n                        if (_sy < 0) {\n                            _sy = 0;\n                        } else if (_sy > 64) {\n                            _sy = 64;\n                        }\n                        let _ex = script.getNumberValue('EX', script);\n                        _ex = Math.round(_ex);\n                        if (_ex < 0) {\n                            _ex = 0;\n                        } else if (_ex > 128) {\n                            _ex = 128;\n                        }\n                        let _ey = script.getNumberValue('EY', script);\n                        _ey = Math.round(_ey);\n                        if (_ey < 0) {\n                            _ey = 0;\n                        } else if (_ey > 64) {\n                            _ey = 64;\n                        }\n                        let _color = script.getNumberValue('COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 18,\n                                params: [_sx, _sy, _ex, _ey, _color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_drawLine2: {\n                    // Block UI : \"OLED에 수직 선 그리기 옵션((%1,%2), 길이%3, %4)%5\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['검은색', '0'],\n                                ['흰색', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['0', '0', '10', null],\n                        type: 'CodeWizLite_OLED_drawLine2',\n                    },\n                    paramsKeyMap: {\n                        SX: 0,\n                        SY: 1,\n                        LEN: 2,\n                        COLOR: 3,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _sx = script.getNumberValue('SX', script);\n                        _sx = Math.round(_sx);\n                        if (_sx < 0) {\n                            _sx = 0;\n                        } else if (_sx > 128) {\n                            _sx = 128;\n                        }\n                        let _sy = script.getNumberValue('SY', script);\n                        _sy = Math.round(_sy);\n                        if (_sy < 0) {\n                            _sy = 0;\n                        } else if (_sy > 64) {\n                            _sy = 64;\n                        }\n                        let _len = script.getNumberValue('LEN', script);\n                        _len = Math.round(_len);\n                        if (_len < 0) {\n                            _len = 0;\n                        } else if (_len > 64) {\n                            _len = 64;\n                        }\n                        let _color = script.getNumberValue('COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 19,\n                                params: [_sx, _sy, _len, _color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_drawLine3: {\n                    // Block UI : \"OLED에 수평 선 그리기 옵션((%1,%2), 길이%3, %4)%5\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['검은색', '0'],\n                                ['흰색', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['0', '0', '10', null],\n                        type: 'CodeWizLite_OLED_drawLine3',\n                    },\n                    paramsKeyMap: {\n                        SX: 0,\n                        SY: 1,\n                        LEN: 2,\n                        COLOR: 3,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _sx = script.getNumberValue('SX', script);\n                        _sx = Math.round(_sx);\n                        if (_sx < 0) {\n                            _sx = 0;\n                        } else if (_sx > 128) {\n                            _sx = 128;\n                        }\n                        let _sy = script.getNumberValue('SY', script);\n                        _sy = Math.round(_sy);\n                        if (_sy < 0) {\n                            _sy = 0;\n                        } else if (_sy > 64) {\n                            _sy = 64;\n                        }\n                        let _len = script.getNumberValue('LEN', script);\n                        _len = Math.round(_len);\n                        if (_len < 0) {\n                            _len = 0;\n                        } else if (_len > 128) {\n                            _len = 128;\n                        }\n                        let _color = script.getNumberValue('COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 20,\n                                params: [_sx, _sy, _len, _color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_drawRect: {\n                    // Block UI : \"OLED에 직사각형 그리기 옵션(좌상단점(%1,%2), 가로%3, 세로%4, %5, %6)%7\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['비움', '0'],\n                                ['채움', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['검은색', '0'],\n                                ['흰색', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['0', '0', '10', '10', null, null],\n                        type: 'CodeWizLite_OLED_drawRect',\n                    },\n                    paramsKeyMap: {\n                        SX: 0,\n                        SY: 1,\n                        WIDTH: 2,\n                        HEIGHT: 3,\n                        ISFILL: 4,\n                        COLOR: 5,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _sx = script.getNumberValue('SX', script);\n                        _sx = Math.round(_sx);\n                        if (_sx < 0) {\n                            _sx = 0;\n                        } else if (_sx > 128) {\n                            _sx = 128;\n                        }\n                        let _sy = script.getNumberValue('SY', script);\n                        _sy = Math.round(_sy);\n                        if (_sy < 0) {\n                            _sy = 0;\n                        } else if (_sy > 64) {\n                            _sy = 64;\n                        }\n                        let _width = script.getNumberValue('WIDTH', script);\n                        _width = Math.round(_width);\n                        if (_width < 0) {\n                            _width = 0;\n                        } else if (_width > 128) {\n                            _width = 128;\n                        }\n                        let _height = script.getNumberValue('HEIGHT', script);\n                        _height = Math.round(_height);\n                        if (_height < 0) {\n                            _height = 0;\n                        } else if (_height > 64) {\n                            _height = 64;\n                        }\n                        let _isFill = script.getNumberValue('ISFILL', script);\n                        let _color = script.getNumberValue('COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 21,\n                                x: _sx,\n                                y: _sy,\n                                params: [_sx, _sy, _width, _height, _isFill, _color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_drawCircle: {\n                    // Block UI : \"OLED에 원 그리기 옵션(중심(%1,%2) 반지름%3, %4, %5)%6\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['비움', '0'],\n                                ['채움', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['검은색', '0'],\n                                ['흰색', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['30', '30', '10', null, null],\n                        type: 'CodeWizLite_OLED_drawCircle',\n                    },\n                    paramsKeyMap: {\n                        RX: 0,\n                        RY: 1,\n                        RAD: 2,\n                        ISFILL: 3,\n                        COLOR: 4,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _rx = script.getNumberValue('RX', script);\n                        _rx = Math.round(_rx);\n                        if (_rx < 0) {\n                            _rx = 0;\n                        } else if (_rx > 128) {\n                            _rx = 128;\n                        }\n                        let _ry = script.getNumberValue('RY', script);\n                        _ry = Math.round(_ry);\n                        if (_ry < 0) {\n                            _ry = 0;\n                        } else if (_ry > 64) {\n                            _ry = 64;\n                        }\n                        let _rad = script.getNumberValue('RAD', script);\n                        _rad = Math.round(_rad);\n                        if (_rad < 0) {\n                            _rad = 0;\n                        } else if (_rad > 255) {\n                            _rad = 255;\n                        }\n                        let _isFill = script.getNumberValue('ISFILL', script);\n                        let _color = script.getNumberValue('COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 22,\n                                params: [_rx, _ry, _rad, _isFill, _color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_drawPoligon: {\n                    // Block UI : \"OLED에 삼각형 그리기 옵션((%1,%2), (%3,%4), (%5,%6), %7, %8)%9\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['비움', '0'],\n                                ['채움', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['검은색', '0'],\n                                ['흰색', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['0', '9', '6', '9', '3', '0', null, null],\n                        type: 'CodeWizLite_OLED_drawPoligon',\n                    },\n                    paramsKeyMap: {\n                        X1: 0,\n                        Y1: 1,\n                        X2: 2,\n                        Y2: 3,\n                        X3: 4,\n                        Y3: 5,\n                        ISFILL: 6,\n                        COLOR: 7,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _x1 = script.getNumberValue('X1', script);\n                        _x1 = Math.round(_x1);\n                        if (_x1 < 0) {\n                            _x1 = 0;\n                        } else if (_x1 > 128) {\n                            _x1 = 128;\n                        }\n                        let _y1 = script.getNumberValue('Y1', script);\n                        _y1 = Math.round(_y1);\n                        if (_y1 < 0) {\n                            _y1 = 0;\n                        } else if (_y1 > 64) {\n                            _y1 = 64;\n                        }\n                        let _x2 = script.getNumberValue('X2', script);\n                        _x2 = Math.round(_x2);\n                        if (_x2 < 0) {\n                            _x2 = 0;\n                        } else if (_x2 > 128) {\n                            _x2 = 128;\n                        }\n                        let _y2 = script.getNumberValue('Y2', script);\n                        _y2 = Math.round(_y2);\n                        if (_y2 < 0) {\n                            _y2 = 0;\n                        } else if (_y2 > 64) {\n                            _y2 = 64;\n                        }\n                        let _x3 = script.getNumberValue('X3', script);\n                        _x3 = Math.round(_x3);\n                        if (_x3 < 0) {\n                            _x3 = 0;\n                        } else if (_x3 > 128) {\n                            _x3 = 128;\n                        }\n                        let _y3 = script.getNumberValue('Y3', script);\n                        _y3 = Math.round(_y3);\n                        if (_y3 < 0) {\n                            _y3 = 0;\n                        } else if (_y3 > 64) {\n                            _y3 = 64;\n                        }\n                        let _isFill = script.getNumberValue('ISFILL', script);\n                        let _color = script.getNumberValue('COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 23,\n                                params: [_x1, _y1, _x2, _y2, _x3, _y3, _isFill, _color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OLED_printHG: {\n                    // OLED 한글 출력\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['❌', '0'],\n                                ['⭕', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['코드위즈 Magic!!', null],\n                        type: 'CodeWizLite_OLED_printHG',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        isLB: 1,\n                    },\n                    class: 'CodeWizLite_OLED',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _value = script.getStringValue('TEXT');\n                        let _isLB = script.getNumberValue('isLB', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 42,\n                                params: [_value, _isLB],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_DIGITAL_OUTPUT_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(\n                                Lang.template.CodeWizLite_DIGITAL_OUTPUT_title\n                            ),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_DIGITAL_OUTPUT_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_DIGITAL_OUTPUT_title',\n                    },\n                    class: 'CodeWizLite_DIGITAL_OUTPUT',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_DIGITAL_OUTPUT_digitalWrite: {\n                    // Block UI : \"터치센서 디지털 %1(으)로 %2내보내기%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['13', '13'],\n                                ['14', '14'],\n                                ['15', '15'],\n                                ['27', '27'],\n                                ['32', '32'],\n                                ['33', '33'],\n                                ['18', '18'],\n                                ['19', '19'],\n                            ],\n                            value: '13',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['LOW', '0'],\n                                ['HIGH', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'CodeWizLite_DIGITAL_OUTPUT_digitalWrite',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    class: 'CodeWizLite_DIGITAL_OUTPUT',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _pin = script.getNumberValue('PIN', script);\n                        let _val = script.getNumberValue('VALUE', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 25,\n                                params: [_pin, _val],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_DIGITAL_OUTPUT_pwmWrite: {\n                    // Block UI : \"터치센서 PWM %1(으)로 %2내보내기(0~1023)%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['13', '13'],\n                                ['14', '14'],\n                                ['15', '15'],\n                                ['27', '27'],\n                                ['32', '32'],\n                                ['33', '33'],\n                                ['18', '18'],\n                                ['19', '19'],\n                            ],\n                            value: '13',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, '0'],\n                        type: 'CodeWizLite_DIGITAL_OUTPUT_pwmWrite',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    class: 'CodeWizLite_DIGITAL_OUTPUT',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _pin = script.getNumberValue('PIN', script);\n                        let _val = script.getNumberValue('VALUE', script);\n                        _val = Math.round(_val);\n                        if (_val < 0) {\n                            _val = 0;\n                        } else if (_val > 1023) {\n                            _val = 1023;\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 26,\n                                params: [_pin, _val],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                /////////오즈아이 시작//////////////////////////////////////////////////////////////////////////////////////////////\n\n                CodeWizLite_OzEye_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_OzEye_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_OzEye_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_OzEye_title',\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n\n                CodeWizLite_OzEye_initOzEye: {\n                    // Block UI : '오즈아이 시작설정%1',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OzEye_initOzEye',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 52,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                CodeWizLite_OzEye_setModeOfOzEye: {\n                    // Block UI : '오즈아이 %1알고리즘으로 설정%2'\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1.선 인식', '3'],\n                                ['2.색 인식', '4'],\n                                ['3.태그 인식', '5'],\n                                ['4.이미지 인식', '6'],\n                                ['5.사물 인식', '2'],\n                                ['6.사물 추적', '1'],\n                                ['7.선 + 태그', '7'],\n                                ['8.얼굴 인식', '0'],\n                                ['9.숫자 인식', '8'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OzEye_setModeOfOzEye',\n                    },\n                    paramsKeyMap: {\n                        MODE: 0,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let mode = script.getNumberValue('MODE', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 53,\n                                params: [mode],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OzEye_readOzEye: {\n                    // Block UI : \"오즈아이 데이터 요청시작%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_OzEye_readOzEye',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 54,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OzEye_isLearnedOzEye: {\n                    // Block UI : \"오즈아이 ID가%1인 데이터를 학습했는가?%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'CodeWizLite_OzEye_isLearnedOzEye',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let learnId = script.getNumberValue('ID', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 15,\n                                params: [learnId],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                        //delete Entry.CodeWizLite.sensorData[id];\n\n                        return retVal;\n                    },\n                },\n                CodeWizLite_OzEye_isContainOzEye: {\n                    // Block UI : \"오즈아이 ID:%1로 인식한 %2데이터가 있는가?%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['사각형', '42'],\n                                ['화살표', '43'],\n                            ],\n                            value: '42',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null, null],\n                        type: 'CodeWizLite_OzEye_isContainOzEye',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _learnId = script.getNumberValue('ID', script);\n                        let _type = script.getNumberValue('TYPE', script);\n                        // console.log(this.sensorData);\n                        // console.log(Entry.CodeWizLite.sensorData.HUSKY_READ);\n                        const huskyData = Entry.CodeWizLite.sensorData.HUSKY_READ;\n                        if (!huskyData._list || huskyData._list.length === 0) {\n                            return false;\n                        }\n                        if (huskyData?._type !== _type) {\n                            return false;\n                        }\n                        let _list = Entry.CodeWizLite.sensorData.HUSKY_READ._list;\n                        for (let i = 0; i < _list.length; ++i) {\n                            if (_list[i][0] === _learnId) {\n                                return true;\n                            }\n                        }\n                        return false;\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n                    //     let _learnId = script.getNumberValue('ID', script);\n                    //     let _type = script.getNumberValue('TYPE', script);\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 2,\n                    //             params: [_learnId, _type],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal;\n                    // },\n                },\n                CodeWizLite_OzEye_getCountLearnedOzEye: {\n                    // Block UI : \"오즈아이가 감지한 학습데이터 수%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OzEye_getCountLearnedOzEye',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        return Entry.CodeWizLite.sensorData.HUSKY_READ?._count ?? 0;\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 3,\n                    //             params: [],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal;\n                    // },\n                },\n                CodeWizLite_OzEye_hasTypeOzEye: {\n                    // Block UI : \"오즈아이가 읽은 데이터 타입이%1인가?%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['사각형', '42'],\n                                ['화살표', '43'],\n                            ],\n                            value: '42',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OzEye_hasTypeOzEye',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _type = script.getNumberValue('TYPE', script);\n                        return Entry.CodeWizLite.sensorData.HUSKY_READ?._type === _type;\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n                    //     let _type = script.getNumberValue('TYPE', script);\n\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 4,\n                    //             params: [_type],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal\n                    // },\n                },\n                CodeWizLite_OzEye_getArrowInfoOzEye: {\n                    // Block UI : \"오즈아이가 읽은 ID%1인 화살표정보%2%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['시작 X좌표', '1'],\n                                ['시작 Y좌표', '2'],\n                                ['종료 X좌표', '3'],\n                                ['종료 Y좌표', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'CodeWizLite_OzEye_getArrowInfoOzEye',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _id = script.getNumberValue('ID', script);\n                        let _arrowType = script.getNumberValue('TYPE', script);\n                        const huskyData = Entry.CodeWizLite.sensorData.HUSKY_READ;\n                        if (!huskyData._list || huskyData._list.length === 0) {\n                            return -1;\n                        }\n                        if (huskyData?._type !== 43) {\n                            return -1;\n                        }\n                        for (let i = 0; i < huskyData._list.length; ++i) {\n                            if (huskyData._list[i][0] === _id) {\n                                return huskyData._list[i][_arrowType];\n                            }\n                        }\n                        return -1;\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n                    //     let _arrowType = script.getNumberValue('TYPE', script);\n\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 5,\n                    //             params: [_arrowType],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal\n                    // },\n                },\n                CodeWizLite_OzEye_getBoxInfoOzEye2: {\n                    // Block UI : \"오즈아이가 읽은 ID%1인 사각형정보%2%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['중심 X좌표', '1'],\n                                ['중심 Y좌표', '2'],\n                                ['너비', '3'],\n                                ['높이', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'CodeWizLite_OzEye_getBoxInfoOzEye2',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _id = script.getNumberValue('ID', script);\n                        let _boxType = script.getNumberValue('TYPE', script);\n                        const huskyData = Entry.CodeWizLite.sensorData.HUSKY_READ;\n                        if (!huskyData._list || huskyData._list.length === 0) {\n                            return -1;\n                        }\n                        if (huskyData?._type !== 42) {\n                            return -1;\n                        }\n                        for (let i = 0; i < huskyData._list.length; ++i) {\n                            if (huskyData._list[i][0] === _id) {\n                                return huskyData._list[i][_boxType];\n                            }\n                        }\n                        return -1;\n                    },\n                },\n                CodeWizLite_OzEye_getBoxInfoOzEye: {\n                    // Block UI : \"오즈아이가 읽은 사각형정보%1(중심좌표가 중앙에 가장 가까운 것)%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['ID', '0'],\n                                ['중심 X좌표', '1'],\n                                ['중심 Y좌표', '2'],\n                                ['너비', '3'],\n                                ['높이', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OzEye_getBoxInfoOzEye',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _boxType = script.getNumberValue('TYPE', script);\n                        const huskyData = Entry.CodeWizLite.sensorData.HUSKY_READ;\n                        if (!huskyData._list || huskyData._list.length === 0) {\n                            return -1;\n                        }\n                        if (huskyData?._type !== 42 || huskyData?._count === 0) {\n                            return -1;\n                        }\n                        let curIdx = 0;\n                        let dist = Entry.CodeWizLite.HUSKY.getDist(\n                            huskyData._list[0][0],\n                            huskyData._list[0][1]\n                        );\n                        let curDist;\n                        for (let i = 1; i < huskyData._count; ++i) {\n                            curDist = Entry.CodeWizLite.HUSKY.getDist(\n                                huskyData._list[i][0],\n                                huskyData._list[i][1]\n                            );\n                            if (dist > curDist) {\n                                dist = curDist;\n                                curIdx = i;\n                            }\n                        }\n                        return huskyData._list[curIdx][_boxType];\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n                    //     let _boxType = script.getNumberValue('TYPE', script);\n\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 6,\n                    //             params: [_boxType],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal\n                    // },\n                },\n\n                //오즈아이에 텍스트 출력하기 기능 이후 적용\n                /*\n                CodeWizLite_OzEye_writeTextOzEye: {\n                    // Block UI : \"오즈아이 x:%1 y:%2에 %3출력%4\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [0, 0, 'CodeWizLite'],\n                        type: 'CodeWizLite_OzEye_writeTextOzEye',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        TEXT: 2,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _x = script.getNumberValue('X', script);\n                        let _y = script.getNumberValue('Y', script);\n                        let _text = script.getStringValue('TEXT');\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 55,\n                                params: [_x, _y, _text],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_OzEye_clearTextOzEye: {\n                    // Block UI : \"오즈아이 텍스트 지우기%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_OzEye_clearTextOzEye',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 56,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                */\n\n                CodeWizLite_OzEye_setLightLevel: {\n                    // Block UI : '오즈아이 라이트 밝기를 %1 단계로 설정(1~7)%2',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OzEye_setLightLevel',\n                    },\n                    paramsKeyMap: {\n                        Level: 0,\n                    },\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let Level = script.getNumberValue('Level', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 57,\n                                params: [Level],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                CodeWizLite_OzEye_LightOff: {\n                    // Block UI : '오즈아이 라이트 끄기%1',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_OzEye_LightOff',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_OzEye',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 58,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                //////////오즈아이 끝/////////////////////////////////////////////////////////////////////////////////////////////\n\n                CodeWizLite_HuskyLens_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_HuskyLens_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_HuskyLens_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_HuskyLens_title',\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n\n                CodeWizLite_HuskyLens_initHuskyLens: {\n                    // Block UI : '허스키렌즈 시작설정%1',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_HuskyLens_initHuskyLens',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 27,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_HuskyLens_setModeOfHuskyLens: {\n                    // Block UI : '허스키렌즈 %1알고리즘으로 설정%2'\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1.FACE_RECOGNITION', '0'],\n                                ['2.OBJECT_TRACKING', '1'],\n                                ['3.OBJECT_RECOGNITION', '2'],\n                                ['4.LINE_TRACKING', '3'],\n                                ['5.COLOR_RECOGNITION', '4'],\n                                ['6.TAG_RECOGNITION', '5'],\n                                ['7.OBJECT_CLASSIFICATION', '6'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_HuskyLens_setModeOfHuskyLens',\n                    },\n                    paramsKeyMap: {\n                        MODE: 0,\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let mode = script.getNumberValue('MODE', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 28,\n                                params: [mode],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_HuskyLens_readHuskyLens: {\n                    // Block UI : \"허스키렌즈 데이터 요청시작%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_HuskyLens_readHuskyLens',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 29,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_HuskyLens_isLearnedHuskyLens: {\n                    // Block UI : \"허스키렌즈 ID가%1인 데이터를 학습했는가?%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'CodeWizLite_HuskyLens_isLearnedHuskyLens',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let learnId = script.getNumberValue('ID', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 1,\n                                params: [learnId],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                        //delete Entry.CodeWizLite.sensorData[id];\n\n                        return retVal;\n                    },\n                },\n                CodeWizLite_HuskyLens_isContainHuskyLens: {\n                    // Block UI : \"허스키렌즈 ID:%1로 인식한 %2데이터가 있는가?%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['사각형', '42'],\n                                ['화살표', '43'],\n                            ],\n                            value: '42',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null, null],\n                        type: 'CodeWizLite_HuskyLens_isContainHuskyLens',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _learnId = script.getNumberValue('ID', script);\n                        let _type = script.getNumberValue('TYPE', script);\n                        // console.log(this.sensorData);\n                        // console.log(Entry.CodeWizLite.sensorData.HUSKY_READ);\n                        const huskyData = Entry.CodeWizLite.sensorData.HUSKY_READ;\n                        if (!huskyData._list || huskyData._list.length === 0) {\n                            return false;\n                        }\n                        if (huskyData?._type !== _type) {\n                            return false;\n                        }\n                        let _list = Entry.CodeWizLite.sensorData.HUSKY_READ._list;\n                        for (let i = 0; i < _list.length; ++i) {\n                            if (_list[i][0] === _learnId) {\n                                return true;\n                            }\n                        }\n                        return false;\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n                    //     let _learnId = script.getNumberValue('ID', script);\n                    //     let _type = script.getNumberValue('TYPE', script);\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 2,\n                    //             params: [_learnId, _type],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal;\n                    // },\n                },\n                CodeWizLite_HuskyLens_getCountLearnedHuskyLens: {\n                    // Block UI : \"허스키렌즈가 감지한 학습데이터 수%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_HuskyLens_getCountLearnedHuskyLens',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        return Entry.CodeWizLite.sensorData.HUSKY_READ?._count ?? 0;\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 3,\n                    //             params: [],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal;\n                    // },\n                },\n                CodeWizLite_HuskyLens_hasTypeHuskyLens: {\n                    // Block UI : \"허스키렌즈가 읽은 데이터 타입이%1인가?%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['사각형', '42'],\n                                ['화살표', '43'],\n                            ],\n                            value: '42',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_HuskyLens_hasTypeHuskyLens',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _type = script.getNumberValue('TYPE', script);\n                        return Entry.CodeWizLite.sensorData.HUSKY_READ?._type === _type;\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n                    //     let _type = script.getNumberValue('TYPE', script);\n\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 4,\n                    //             params: [_type],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal\n                    // },\n                },\n                CodeWizLite_HuskyLens_getArrowInfoHuskyLens: {\n                    // Block UI : \"허스키렌즈가 읽은 ID%1인 화살표정보%2%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['시작 X좌표', '1'],\n                                ['시작 Y좌표', '2'],\n                                ['종료 X좌표', '3'],\n                                ['종료 Y좌표', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'CodeWizLite_HuskyLens_getArrowInfoHuskyLens',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _id = script.getNumberValue('ID', script);\n                        let _arrowType = script.getNumberValue('TYPE', script);\n                        const huskyData = Entry.CodeWizLite.sensorData.HUSKY_READ;\n                        if (!huskyData._list || huskyData._list.length === 0) {\n                            return -1;\n                        }\n                        if (huskyData?._type !== 43) {\n                            return -1;\n                        }\n                        for (let i = 0; i < huskyData._list.length; ++i) {\n                            if (huskyData._list[i][0] === _id) {\n                                return huskyData._list[i][_arrowType];\n                            }\n                        }\n                        return -1;\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n                    //     let _arrowType = script.getNumberValue('TYPE', script);\n\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 5,\n                    //             params: [_arrowType],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal\n                    // },\n                },\n                CodeWizLite_HuskyLens_getBoxInfoHuskyLens2: {\n                    // Block UI : \"허스키렌즈가 읽은 ID%1인 사각형정보%2%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['중심 X좌표', '1'],\n                                ['중심 Y좌표', '2'],\n                                ['너비', '3'],\n                                ['높이', '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'CodeWizLite_HuskyLens_getBoxInfoHuskyLens2',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _id = script.getNumberValue('ID', script);\n                        let _boxType = script.getNumberValue('TYPE', script);\n                        const huskyData = Entry.CodeWizLite.sensorData.HUSKY_READ;\n                        if (!huskyData._list || huskyData._list.length === 0) {\n                            return -1;\n                        }\n                        if (huskyData?._type !== 42) {\n                            return -1;\n                        }\n                        for (let i = 0; i < huskyData._list.length; ++i) {\n                            if (huskyData._list[i][0] === _id) {\n                                return huskyData._list[i][_boxType];\n                            }\n                        }\n                        return -1;\n                    },\n                },\n                CodeWizLite_HuskyLens_getBoxInfoHuskyLens: {\n                    // Block UI : \"허스키렌즈가 읽은 사각형정보%1(중심좌표가 중앙에 가장 가까운 것)%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['ID', '0'],\n                                ['중심 X좌표', '1'],\n                                ['중심 Y좌표', '2'],\n                                ['너비', '3'],\n                                ['높이', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_HuskyLens_getBoxInfoHuskyLens',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    func(sprite, script) {\n                        let _boxType = script.getNumberValue('TYPE', script);\n                        const huskyData = Entry.CodeWizLite.sensorData.HUSKY_READ;\n                        if (!huskyData._list || huskyData._list.length === 0) {\n                            return -1;\n                        }\n                        if (huskyData?._type !== 42 || huskyData?._count === 0) {\n                            return -1;\n                        }\n                        let curIdx = 0;\n                        let dist = Entry.CodeWizLite.HUSKY.getDist(\n                            huskyData._list[0][0],\n                            huskyData._list[0][1]\n                        );\n                        let curDist;\n                        for (let i = 1; i < huskyData._count; ++i) {\n                            curDist = Entry.CodeWizLite.HUSKY.getDist(\n                                huskyData._list[i][0],\n                                huskyData._list[i][1]\n                            );\n                            if (dist > curDist) {\n                                dist = curDist;\n                                curIdx = i;\n                            }\n                        }\n                        return huskyData._list[curIdx][_boxType];\n                    },\n                    // async func(sprite, script) {\n                    //     if (Entry.CodeWizLite.intervalId) {\n                    //         await Entry.CodeWizLite.preWait();\n                    //     }\n                    //     let _boxType = script.getNumberValue('TYPE', script);\n\n                    //     const order = {\n                    //         type: Entry.CodeWizLite.sensorTypes.READ,\n                    //         value: {\n                    //             opcode: 6,\n                    //             params: [_boxType],\n                    //         },\n                    //     };\n                    //     const id = Entry.CodeWizLite.sendOrder(order);\n                    //     await Entry.CodeWizLite.checkComplete(1000, id);\n\n                    //     let retVal= Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                    //     //delete Entry.CodeWizLite.sensorData[id];\n                    //     return retVal\n                    // },\n                },\n                CodeWizLite_HuskyLens_writeTextHuskyLens: {\n                    // Block UI : \"허스키렌즈 x:%1 y:%2에 %3출력%4\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [0, 0, 'CodeWizLite'],\n                        type: 'CodeWizLite_HuskyLens_writeTextHuskyLens',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        TEXT: 2,\n                    },\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _x = script.getNumberValue('X', script);\n                        let _y = script.getNumberValue('Y', script);\n                        let _text = script.getStringValue('TEXT');\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 30,\n                                params: [_x, _y, _text],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_HuskyLens_clearTextHuskyLens: {\n                    // Block UI : \"허스키렌즈 텍스트 지우기%1\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_HuskyLens_clearTextHuskyLens',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_HuskyLens',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 31,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                CodeWizLite_Servo_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_Servo_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_Servo_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_Servo_title',\n                    },\n                    class: 'CodeWizLite_Servo',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_Servo_setAngle: {\n                    // Block UI : \"서보모터(%1) 각도를 %2로 바꾸기%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['SCON', '18.0'],\n                                ['MCON-18', '18.1'],\n                                ['MCON-19', '19'],\n                                ['MCON-15', '15'],\n                                ['MCON-27', '27'],\n                            ],\n                            value: '18.0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, '0'],\n                        type: 'CodeWizLite_Servo_setAngle',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    class: 'CodeWizLite_Servo',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _pin = Number.parseInt(script.getNumberValue('PIN', script));\n                        let _value = Number.parseInt(script.getNumberValue('VALUE', script));\n                        _value = Math.round(_value);\n                        if (_value < 0) {\n                            _value = 0;\n                        } else if (_value > 180) {\n                            _value = 180;\n                        }\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 33,\n                                params: [_pin, _value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_Servo_menuSpeed: {\n                    // Block UI : \"무한회전 서보모터(%1) %2속도로 정하기%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['SCON', '18.0'],\n                                ['MCON-18', '18.1'],\n                                ['MCON-19', '19'],\n                                ['MCON-15', '15'],\n                                ['MCON-27', '27'],\n                            ],\n                            value: '18.0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['빠른', '21'],\n                                ['보통', '39'],\n                                ['느린', '58'],\n                                ['멈춘', '76'],\n                            ],\n                            value: '21',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'CodeWizLite_Servo_menuSpeed',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    class: 'CodeWizLite_Servo',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _pin = Number.parseInt(script.getNumberValue('PIN', script));\n                        let _value = script.getNumberValue('VALUE', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 34,\n                                params: [_pin, _value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_Servo_customSpeed: {\n                    // Block UI : \"무한회전 서보모터(%1) %2속도로 정하기(-100~100)%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['SCON', '18.0'],\n                                ['MCON-18', '18.1'],\n                                ['MCON-19', '19'],\n                                ['MCON-15', '15'],\n                                ['MCON-27', '27'],\n                            ],\n                            value: '18.0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, '100'],\n                        type: 'CodeWizLite_Servo_customSpeed',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    class: 'CodeWizLite_Servo',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _pin = Number.parseInt(script.getNumberValue('PIN', script));\n                        let _value = Number.parseInt(script.getNumberValue('VALUE', script));\n                        if (_value < -100) {\n                            _value = -100;\n                        } else if (_value > 100) {\n                            _value = 100;\n                        }\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 35,\n                                params: [_pin, _value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                CodeWizLite_Dc_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_Dc_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_Dc_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_Dc_title',\n                    },\n                    class: 'CodeWizLite_Dc',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_Dc_setCarSpeed: {\n                    // Block UI : 'WizCar 모터에 %1,%2내보내기(-1000~1000)%3',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['600', '600'],\n                        type: 'CodeWizLite_Dc_setCarSpeed',\n                    },\n                    paramsKeyMap: {\n                        L_VALUE: 0,\n                        R_VALUE: 1,\n                    },\n                    class: 'CodeWizLite_Dc',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _lValue = Number.parseInt(script.getNumberValue('L_VALUE', script));\n                        let _rValue = Number.parseInt(script.getNumberValue('R_VALUE', script));\n                        _lValue = Math.min(Math.max(-1000, _lValue), 1000);\n                        _rValue = Math.min(Math.max(-1000, _rValue), 1000);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 51,\n                                params: [_lValue, _rValue],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_Dc_setValue_Waterpump: {\n                    // 워터펌프\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['MOTOR_L', '0'],\n                                ['MOTOR_R', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, '1023'],\n                        type: 'CodeWizLite_Dc_setValue_Waterpump',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    class: 'CodeWizLite_Dc',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _pin = script.getNumberValue('PIN', script);\n                        let _value = Number.parseInt(script.getNumberValue('VALUE', script));\n                        if (_value < 0) {\n                            _value = 0;\n                        } else if (_value > 1023) {\n                            _value = 1023;\n                        }\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 36,\n                                params: [_pin, 1, _value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_DotMatrix_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_DotMatrix_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_DotMatrix_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_DotMatrix_title',\n                    },\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_DotMatrix_init: {\n                    // Block UI : '도트매트릭스 %1개 DIN%2, CS%3, CLK%4에 시작설정%5',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['18', '18'],\n                                ['19', '19'],\n                                ['15', '15'],\n                                ['27', '27'],\n                            ],\n                            value: '18',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['18', '18'],\n                                ['19', '19'],\n                                ['15', '15'],\n                                ['27', '27'],\n                            ],\n                            value: '19',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['18', '18'],\n                                ['19', '19'],\n                                ['15', '15'],\n                                ['27', '27'],\n                            ],\n                            value: '15',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', null, null, null],\n                        type: 'CodeWizLite_DotMatrix_init',\n                    },\n                    paramsKeyMap: {\n                        COUNT: 0,\n                        PIN1: 1,\n                        PIN2: 2,\n                        PIN3: 3,\n                    },\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _count = Number.parseInt(script.getNumberValue('COUNT', script));\n                        if (_count <= 0) {\n                            return;\n                        } else if (_count > 8) {\n                            _count = 8;\n                        }\n                        let _pins = [\n                            script.getNumberValue('PIN1', script),\n                            script.getNumberValue('PIN2', script),\n                            script.getNumberValue('PIN3', script),\n                        ];\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 24,\n                                params: [_count, ..._pins],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_DotMatrix_setBrightness: {\n                    // Block UI : '도트매트릭스 %1번 밝기를 %2로 설정%3',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '8'],\n                        type: 'CodeWizLite_DotMatrix_setBrightness',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        BRIGHTNESS: 1,\n                    },\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                        if (_num < 1) {\n                            num = 1;\n                        } else if (_num > 8) {\n                            _num = 8;\n                        }\n                        let _brightness = Number.parseInt(\n                            script.getNumberValue('BRIGHTNESS', script)\n                        );\n                        if (_brightness < 1) {\n                            _brightness = 1;\n                        } else if (_brightness > 15) {\n                            _brightness = 15;\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 37,\n                                params: [_num, _brightness],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_DotMatrix_printString: {\n                    // Block UI : '도트매트릭스 %1번에 문자열%2 출력%3',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', 'HELLO'],\n                        type: 'CodeWizLite_DotMatrix_printString',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        TEXT: 1,\n                    },\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                        if (_num < 1) {\n                            num = 1;\n                        } else if (_num > 8) {\n                            _num = 8;\n                        }\n                        let _value = script.getStringValue('TEXT');\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 38,\n                                params: [_num, _value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_DotMatrix_setLine: {\n                    // Block UI : '도트매트릭스 %1번에 %2번%3 %4로 만들기%5',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['행', '1'],\n                                ['열', '0'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '2', null, '11111111'],\n                        type: 'CodeWizLite_DotMatrix_setLine',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        NUM_LINE: 1,\n                        IS_ROW: 2,\n                        VALUE: 3,\n                    },\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                        if (_num < 1) {\n                            num = 1;\n                        } else if (_num > 8) {\n                            _num = 8;\n                        }\n                        let _numLine = Number.parseInt(script.getNumberValue('NUM_LINE', script));\n                        if (_numLine < 1) {\n                            _numLine = 1;\n                        } else if (_numLine > 8) {\n                            _numLine = 8;\n                        }\n                        let _isRow = script.getNumberValue('IS_ROW', script);\n                        let _value = script.getStringValue('VALUE');\n                        const _f = (str) => {\n                            str = str.substring(0, 8);\n                            let retVal = '';\n                            for (let i = 0; i < str.length; ++i) {\n                                if (str[i] === '0' || str[i] === ' ') {\n                                    retVal += '0';\n                                } else {\n                                    retVal += '1';\n                                }\n                            }\n                            return retVal.padStart(8, '0');\n                        };\n                        _value = _f(_value);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 39,\n                                params: [_num, _numLine, _isRow, _value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                /*\n                CodeWizLite_DotMatrix_Show_Custom_Image: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            value: '1',\n                        },\n                        {\n                            type: 'Led',\n                            value: [\n                                [0, 0, 0, 0, 0],\n                                [0, 1, 1, 0, 0],\n                                [1, 1, 1, 1, 1],\n                                [1, 1, 1, 1, 1],\n                                [0, 1, 1, 1, 1],\n                            ],\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    def: {\n                        type: 'CodeWizLite_DotMatrix_Show_Custom_Image',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        VALUE: 1,\n                    },\n                    async func(sprite, script) {\n                        let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                        if (_num < 1) {\n                            num = 1;\n                        } else if (_num > 8) {\n                            _num = 8;\n                        }\n                        const value = script.getField('VALUE');\n                        const processedValue = [];\n                        for (const i in value) {\n                            processedValue[i] = value[i].join('');\n                            console.log(processedValue[i]);\n                            let _numLine = Number.parseInt(i) + 1;\n                            const order = {\n                                type: Entry.CodeWizLite.sensorTypes.WRITE,\n                                value: {\n                                    opcode: 39,\n                                    params: [_num, _numLine, 0, processedValue[i]],\n                                },\n                            };\n                            const id = Entry.CodeWizLite.sendOrder(order);\n                            await Entry.CodeWizLite.checkComplete(1000, id);\n                        }\n                        return;\n                    },\n                },\n*/\n                CodeWizLite_DotMatrix_setDot: {\n                    // Block UI : '도트매트릭스 %1번에 %2행%3열 %4%5',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['켜기', '1'],\n                                ['끄기', '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '2', '2', null],\n                        type: 'CodeWizLite_DotMatrix_setDot',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        ROW: 1,\n                        COL: 2,\n                        VALUE: 3,\n                    },\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                        if (_num < 1) {\n                            num = 1;\n                        } else if (_num > 8) {\n                            _num = 8;\n                        }\n                        let _numRow = Number.parseInt(script.getNumberValue('ROW', script));\n                        if (_numRow < 1) {\n                            _numRow = 1;\n                        } else if (_numRow > 8) {\n                            _numRow = 8;\n                        }\n                        let _numCol = Number.parseInt(script.getNumberValue('COL', script));\n                        if (_numCol < 1) {\n                            _numCol = 1;\n                        } else if (_numCol > 8) {\n                            _numCol = 8;\n                        }\n                        let _value = script.getNumberValue('VALUE', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 40,\n                                params: [_num, _numRow, _numCol, _value],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_DotMatrix_clear: {\n                    // Block UI : '도트매트릭스 %1번 지우기%2',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1'],\n                        type: 'CodeWizLite_DotMatrix_clear',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                    },\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _num = Number.parseInt(script.getNumberValue('NUM', script));\n                        if (_num < 1) {\n                            num = 1;\n                        } else if (_num > 8) {\n                            _num = 8;\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 41,\n                                params: [_num - 1],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n                CodeWizLite_DotMatrix_clearAll: {\n                    // Block UI : '도트매트릭스 모두 지우기%1',\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'CodeWizLite_DotMatrix_clearAll',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_DotMatrix',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 41,\n                                params: [-1],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        //delete Entry.CodeWizLite.sensorData[id];\n                    },\n                },\n\n                CodeWizLite_ColorSensor_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_ColorSensor_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_ColorSensor_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_ColorSensor_title',\n                    },\n                    class: 'CodeWizLite_ColorSensor',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_ColorSensor_isColor: {\n                    // Block UI : \"MCON 컬러센서 감지된 색이 %1인가%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['빨강', '0'],\n                                ['초록', '1'],\n                                ['파랑', '2'],\n                                ['검정', '3'],\n                                ['흰색', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_ColorSensor_isColor',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'CodeWizLite_ColorSensor',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _color = script.getNumberValue('COLOR', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 8,\n                                params: [_color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                        //delete Entry.CodeWizLite.sensorData[id];\n                        return retVal;\n                    },\n                },\n                CodeWizLite_ColorSensor_getColorValue: {\n                    // Block UI : \"MCON 컬러센서 %1값%2\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['빨강', '0'],\n                                ['초록', '1'],\n                                ['파랑', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_ColorSensor_getColorValue',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'CodeWizLite_ColorSensor',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _color = script.getNumberValue('COLOR', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 9,\n                                params: [_color],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                        //delete Entry.CodeWizLite.sensorData[id];\n                        return retVal;\n                    },\n                },\n\n                CodeWizLite_DHT_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_DHT_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_DHT_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_DHT_title',\n                    },\n                    class: 'CodeWizLite_DHT',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_DHT_init: {\n                    // 디지털 온습도 설정\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['13', '13'],\n                                ['14', '14'],\n                                ['15', '15'],\n                                ['27', '27'],\n                                ['32', '32'],\n                                ['33', '33'],\n                                ['18', '18'],\n                                ['19', '19'],\n                            ],\n                            value: '18',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_DHT_init',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                    },\n                    class: 'CodeWizLite_DHT',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _pin = script.getNumberValue('PIN', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 48,\n                                params: [_pin],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                    },\n                },\n                CodeWizLite_DHT_getValue: {\n                    // 디지털 온습도 값\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['℃', '0'],\n                                ['℉', '1'],\n                                ['습도', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_DHT_getValue',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'CodeWizLite_DHT',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _type = script.getNumberValue('TYPE', script);\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 12,\n                                params: [_type],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? 0.0;\n                        //delete Entry.CodeWizLite.sensorData[id];\n                        return retVal;\n                    },\n                },\n                CodeWizLite_Joystick_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX: this.getOffsetX(Lang.template.CodeWizLite_Joystick_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_Joystick_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_Joystick_title',\n                    },\n                    class: 'CodeWizLite_Joystick',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_Joystick_setPin: {\n                    // 조이스틱 설정\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['32', '32'],\n                                ['33', '33'],\n                                ['36', '36'],\n                                ['39', '39'],\n                            ],\n                            value: '36',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['32', '32'],\n                                ['33', '33'],\n                                ['36', '36'],\n                                ['39', '39'],\n                            ],\n                            value: '39',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['13', '13'],\n                                ['14', '14'],\n                                ['15', '15'],\n                                ['27', '27'],\n                                ['18', '18'],\n                                ['19', '19'],\n                            ],\n                            value: '15',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, 12],\n                        type: 'CodeWizLite_Joystick_setPin',\n                    },\n                    paramsKeyMap: {\n                        PIN_X: 0,\n                        PIN_Y: 1,\n                        PIN_B: 2,\n                        RANGE: 3,\n                    },\n                    class: 'CodeWizLite_Joystick',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        let _pinX = script.getNumberValue('PIN_X', script);\n                        let _pinY = script.getNumberValue('PIN_Y', script);\n                        let _pinB = script.getNumberValue('PIN_B', script);\n                        let _range = script.getNumberValue('RANGE', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.WRITE,\n                            value: {\n                                opcode: 50,\n                                params: [_pinX, _pinY, _pinB, _range],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                    },\n                },\n                CodeWizLite_Joystick_readAxis: {\n                    // 조이스틱 XY레버값\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['X축', '0'],\n                                ['Y축', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_Joystick_readAxis',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'CodeWizLite_Joystick',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _type = script.getNumberValue('TYPE', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 13,\n                                params: [_type],\n                            },\n                        };\n\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                        //delete Entry.CodeWizLite.sensorData[id];\n                        // console.log(_type===0?\"X:\":\"Y:\",retVal);\n                        return retVal;\n                    },\n                },\n                CodeWizLite_Joystick_readButton: {\n                    // 조이스틱 버튼값\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_Joystick_readButton',\n                    },\n                    paramsKeyMap: {},\n                    class: 'CodeWizLite_Joystick',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 14,\n                                params: [],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                        //delete Entry.CodeWizLite.sensorData[id];\n                        // console.log(\"Button:\",retVal);\n                        return retVal;\n                    },\n                },\n\n                CodeWizLite_etcReadSensor_title: {\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        box: {\n                            offsetX:\n                                5 + this.getOffsetX(Lang.template.CodeWizLite_etcReadSensor_title),\n                            offsetY: 5,\n                        },\n                    },\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.CodeWizLite_etcReadSensor_title,\n                            color: '#333333',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'CodeWizLite_etcReadSensor_title',\n                    },\n                    class: 'CodeWizLite_etcReadSensor',\n                    isNotFor: ['CodeWizLite'],\n                    events: {},\n                },\n                CodeWizLite_etcReadSensor_mconRead: {\n                    // 가변저항, 워터센서, 토양수분센서\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['가변저항', '0'],\n                                ['워터센서', '1'],\n                                ['토양수분센서', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['32', '32'],\n                                ['33', '33'],\n                                ['36', '36'],\n                                ['39', '39'],\n                            ],\n                            value: '36',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_etcReadSensor_mconRead',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                        PIN: 1,\n                    },\n                    class: 'CodeWizLite_etcReadSensor',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _type = script.getNumberValue('TYPE', script);\n                        let _pin = script.getNumberValue('PIN', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 10,\n                                params: [_type, _pin],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                        //delete Entry.CodeWizLite.sensorData[id];\n                        return retVal;\n                    },\n                },\n                CodeWizLite_etcReadSensor_digitalRead: {\n                    // 버튼, 포토인터럽트\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['버튼', '0'],\n                                ['포토인터럽트', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['13', '13'],\n                                ['14', '14'],\n                                ['15', '15'],\n                                ['27', '27'],\n                                ['32', '32'],\n                                ['33', '33'],\n                                ['18', '18'],\n                                ['19', '19'],\n                            ],\n                            value: '18',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_etcReadSensor_digitalRead',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                        PIN: 1,\n                    },\n                    class: 'CodeWizLite_etcReadSensor',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _type = script.getNumberValue('TYPE', script);\n                        let _pin = script.getNumberValue('PIN', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 11,\n                                params: [_type, _pin],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? false;\n                        //delete Entry.CodeWizLite.sensorData[id];\n                        return retVal;\n                    },\n                },\n                CodeWizLite_etcReadSensor_InfraredThermometerRead: {\n                    // Block UI : \"비접촉온도센서 %1에 %2로 읽기%3\",\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['SCON', '0'],\n                                ['MCON', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['℃', '0'],\n                                ['℉', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'CodeWizLite_etcReadSensor_InfraredThermometerRead',\n                    },\n                    paramsKeyMap: {\n                        IS_M: 0,\n                        IS_F: 1,\n                    },\n                    class: 'CodeWizLite_etcReadSensor',\n                    isNotFor: ['CodeWizLite'],\n                    async func(sprite, script) {\n                        if (Entry.CodeWizLite.intervalId) {\n                            await Entry.CodeWizLite.preWait();\n                        }\n                        let _isM = script.getNumberValue('IS_M', script);\n                        let _isF = script.getNumberValue('IS_F', script);\n\n                        const order = {\n                            type: Entry.CodeWizLite.sensorTypes.READ,\n                            value: {\n                                opcode: 8,\n                                params: [_isM, _isF],\n                            },\n                        };\n                        const id = Entry.CodeWizLite.sendOrder(order);\n                        await Entry.CodeWizLite.checkComplete(1000, id);\n\n                        let retVal = Entry.CodeWizLite.sensorData[id]?.value ?? 0;\n                        //delete Entry.CodeWizLite.sensorData[id];\n                        return retVal;\n                    },\n                },\n                //endregion CodeWiz 코드위즈\n            };\n        }\n    })();\n})();\n\nmodule.exports = Entry.CodeWizLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_hamster_lite.js",
    "content": "'use strict';\n\n(function() {\n    const COLOR_TO_RGB = [\n        [0, 0, 0],\n        [0, 0, 255],\n        [0, 255, 0],\n        [0, 255, 255],\n        [255, 0, 0],\n        [255, 0, 255],\n        [255, 255, 0],\n        [255, 255, 255],\n    ];\n\n    Entry.HamsterLite = new (class HamsterLite {\n        constructor() {\n            this.id = '020401';\n            this.url = 'http://www.robomation.net';\n            this.imageName = 'hamsterlite.png';\n            this.name = 'HamsterLite';\n            this.delimeter = '\\r';\n            this.blockMenuBlocks = [\n                'hamsterlite_hand_found',\n                'hamsterlite_boolean',\n                'hamsterlite_value',\n                'hamsterlite_move_forward_once',\n                'hamsterlite_turn_once',\n                'hamsterlite_move_forward_for_secs',\n                'hamsterlite_move_backward_for_secs',\n                'hamsterlite_turn_for_secs',\n                'hamsterlite_change_both_wheels_by',\n                'hamsterlite_set_both_wheels_to',\n                'hamsterlite_change_wheel_by',\n                'hamsterlite_set_wheel_to',\n                'hamsterlite_follow_line_using',\n                'hamsterlite_follow_line_until',\n                'hamsterlite_set_following_speed_to',\n                'hamsterlite_stop',\n                'hamsterlite_set_led_to',\n                'hamsterlite_clear_led',\n                'hamsterlite_beep',\n                'hamsterlite_change_buzzer_by',\n                'hamsterlite_set_buzzer_to',\n                'hamsterlite_clear_buzzer',\n                'hamsterlite_play_note',\n                'hamsterlite_play_note_for',\n                'hamsterlite_rest_for',\n                'hamsterlite_change_tempo_by',\n                'hamsterlite_set_tempo_to',\n                'hamsterlite_set_port_to',\n                'hamsterlite_change_output_by',\n                'hamsterlite_set_output_to',\n                'hamsterlite_gripper',\n                'hamsterlite_release_gripper',\n            ];\n            this.__SENSORS = {\n                SIGNAL_STRENGTH: 'signalStrength',\n                LEFT_PROXIMITY: 'leftProximity',\n                RIGHT_PROXIMITY: 'rightProximity',\n                LEFT_FLOOR: 'leftFloor',\n                RIGHT_FLOOR: 'rightFloor',\n                ACCELERATION_X: 'accelerationX',\n                ACCELERATION_Y: 'accelerationY',\n                ACCELERATION_Z: 'accelerationZ',\n                LIGHT: 'light',\n                TEMPERATURE: 'temperature',\n                INPUT_A: 'inputA',\n                INPUT_B: 'inputB',\n            };\n            this.__COLORS = {\n                RED: 4,\n                ORANGE: 4,\n                YELLOW: 6,\n                GREEN: 2,\n                SKY_BLUE: 3,\n                BLUE: 1,\n                VIOLET: 5,\n                PURPLE: 5,\n                WHITE: 7,\n                4: 4,\n                6: 6,\n                2: 2,\n                3: 3,\n                1: 1,\n                5: 5,\n                7: 7,\n            };\n            this.__RGB_COLORS = {\n                RED: [255, 0, 0],\n                ORANGE: [255, 63, 0],\n                YELLOW: [255, 255, 0],\n                GREEN: [0, 255, 0],\n                SKY_BLUE: [0, 255, 255],\n                BLUE: [0, 0, 255],\n                VIOLET: [63, 0, 255],\n                PURPLE: [255, 0, 255],\n                WHITE: [255, 255, 255],\n                4: [255, 0, 0],\n                6: [255, 255, 0],\n                2: [0, 255, 0],\n                3: [0, 255, 255],\n                1: [0, 0, 255],\n                5: [255, 0, 255],\n                7: [255, 255, 255],\n            };\n            this.__NOTES = {\n                C: 4,\n                'C#': 5,\n                Db: 5,\n                D: 6,\n                'D#': 7,\n                Eb: 7,\n                E: 8,\n                F: 9,\n                'F#': 10,\n                Gb: 10,\n                G: 11,\n                'G#': 12,\n                Ab: 12,\n                A: 13,\n                'A#': 14,\n                Bb: 14,\n                B: 15,\n                4: 4,\n                5: 5,\n                6: 6,\n                7: 7,\n                8: 8,\n                9: 9,\n                10: 10,\n                11: 11,\n                12: 12,\n                13: 13,\n                14: 14,\n                15: 15,\n            };\n            this.__IO_MODES = {\n                ANALOG_INPUT: 0,\n                DIGITAL_INPUT: 1,\n                DIGITAL_INPUT_PULL_UP: 2,\n                DIGITAL_INPUT_PULL_DOWN: 3,\n                VOLTAGE_INPUT: 5,\n                SERVO_OUTPUT: 8,\n                PWM_OUTPUT: 9,\n                DIGITAL_OUTPUT: 10,\n                0: 0,\n                1: 1,\n                2: 2,\n                3: 3,\n                5: 5,\n                8: 8,\n                9: 9,\n                10: 10,\n            };\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                connectionType: 'bytestream',\n                bufferSize: 65536,\n                constantServing: true,\n                writeAscii: false,\n                readAscii: true,\n                flowControl: 'hardware',\n            };\n            this.setZero();\n        }\n\n        get monitorTemplate() {\n            return {\n                imgPath: 'hw_lite/hamsterlite.png',\n                width: 256,\n                height: 256,\n                listPorts: {\n                    temperature: {\n                        name: Lang.Blocks.hamsterlite_sensor_temperature,\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    inputA: {\n                        name: Lang.Blocks.hamsterlite_sensor_input_a,\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    inputB: {\n                        name: Lang.Blocks.hamsterlite_sensor_input_b,\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    accelerationX: {\n                        name: Lang.Blocks.hamsterlite_sensor_acceleration_x,\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    accelerationY: {\n                        name: Lang.Blocks.hamsterlite_sensor_acceleration_y,\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    accelerationZ: {\n                        name: Lang.Blocks.hamsterlite_sensor_acceleration_z,\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    buzzer: {\n                        name: Lang.Hw.buzzer,\n                        type: 'output',\n                        pos: { x: 0, y: 0 },\n                    },\n                    note: { name: Lang.Hw.note, type: 'output', pos: { x: 0, y: 0 } },\n                    outputA: {\n                        name: `${Lang.Hw.output}A`,\n                        type: 'output',\n                        pos: { x: 0, y: 0 },\n                    },\n                    outputB: {\n                        name: `${Lang.Hw.output}B`,\n                        type: 'output',\n                        pos: { x: 0, y: 0 },\n                    },\n                },\n                ports: {\n                    leftProximity: {\n                        name: Lang.Blocks.hamsterlite_sensor_left_proximity,\n                        type: 'input',\n                        pos: { x: 122, y: 156 },\n                    },\n                    rightProximity: {\n                        name: Lang.Blocks.hamsterlite_sensor_right_proximity,\n                        type: 'input',\n                        pos: { x: 10, y: 108 },\n                    },\n                    leftFloor: {\n                        name: Lang.Blocks.hamsterlite_sensor_left_floor,\n                        type: 'input',\n                        pos: { x: 100, y: 234 },\n                    },\n                    rightFloor: {\n                        name: Lang.Blocks.hamsterlite_sensor_right_floor,\n                        type: 'input',\n                        pos: { x: 13, y: 180 },\n                    },\n                    light: {\n                        name: Lang.Blocks.hamsterlite_sensor_light,\n                        type: 'input',\n                        pos: { x: 56, y: 189 },\n                    },\n                    leftWheel: {\n                        name: Lang.Hw.leftWheel,\n                        type: 'output',\n                        pos: { x: 209, y: 115 },\n                    },\n                    rightWheel: {\n                        name: Lang.Hw.rightWheel,\n                        type: 'output',\n                        pos: { x: 98, y: 30 },\n                    },\n                    leftLed: {\n                        name: `${Lang.Hw.left} ${Lang.Hw.led_en}`,\n                        type: 'output',\n                        pos: { x: 87, y: 210 },\n                    },\n                    rightLed: {\n                        name: `${Lang.Hw.right} ${Lang.Hw.led_en}`,\n                        type: 'output',\n                        pos: { x: 24, y: 168 },\n                    },\n                },\n                mode: 'both',\n            };\n        }\n\n        setZero() {\n            this.sensory = {\n                signalStrength: 0,\n                leftProximity: 0,\n                rightProximity: 0,\n                leftFloor: 0,\n                rightFloor: 0,\n                accelerationX: 0,\n                accelerationY: 0,\n                accelerationZ: 0,\n                light: 0,\n                temperature: 0,\n                inputA: 0,\n                inputB: 0,\n                tilt: 0,\n                batteryState: 2,\n                lineTracerState: 0,\n                lineTracerStateId: 0,\n                batterytate: 2,\n            };\n            this.motoring = {\n                leftWheel: 0,\n                rightWheel: 0,\n                buzzer: 0,\n                outputA: 0,\n                outputB: 0,\n                topology: 0,\n                leftLed: 0,\n                rightLed: 0,\n                note: 0,\n                lineTracerMode: 0,\n                lineTracerModeId: -1,\n                lineTracerSpeed: 5,\n                ioModeA: 0,\n                ioModeB: 0,\n                configProximity: 2,\n                configGravity: 0,\n                configBandWidth: 3,\n            };\n            this.lineTracer = {\n                written: false,\n                flag: 0,\n                event: 0,\n                state: 0,\n                count: 0,\n            };\n            this.battery = {\n                state: 2,\n                data: new Array(10),\n                sum: 0.0,\n                index: 0,\n                count: 0,\n            };\n            this.lineTracerModeId = 0;\n            this.lineTracerStateId = -1;\n            this.blockId = 0;\n            this.wheelBlockId = 0;\n            this.wheelTimer = undefined;\n            this.lineTracerCallback = undefined;\n            this.boardCommand = 0;\n            this.boardState = 0;\n            this.boardCount = 0;\n            this.boardCallback = undefined;\n            this.noteBlockId = 0;\n            this.noteTimer1 = undefined;\n            this.noteTimer2 = undefined;\n            this.ioBlockId = 0;\n            this.ioTimer = undefined;\n            this.tempo = 60;\n            this.timeouts = [];\n\n            this.__removeAllTimeouts();\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        getMonitorPort() {\n            return { ...this.sensory, ...this.motoring, ...this.lineTracer };\n        }\n\n        setMotoring(motoring) {\n            this.motoring = motoring;\n        }\n\n        __removeTimeout(id) {\n            clearTimeout(id);\n            const idx = this.timeouts.indexOf(id);\n            if (idx >= 0) {\n                this.timeouts.splice(idx, 1);\n            }\n        }\n\n        __removeAllTimeouts() {\n            const timeouts = this.timeouts;\n            for (const i in timeouts) {\n                clearTimeout(timeouts[i]);\n            }\n            this.timeouts = [];\n        }\n\n        __issueWheelBlockId() {\n            this.wheelBlockId = this.blockId = (this.blockId % 65535) + 1;\n            return this.wheelBlockId;\n        }\n\n        __cancelWheel() {\n            this.wheelBlockId = 0;\n            if (this.wheelTimer !== undefined) {\n                this.__removeTimeout(this.wheelTimer);\n            }\n            this.wheelTimer = undefined;\n        }\n\n        __setLineTracerMode(mode) {\n            this.lineTracerModeId = (this.lineTracerModeId % 255) + 1;\n            this.motoring.lineTracerMode = mode;\n            this.motoring.lineTracerModeId = this.lineTracerModeId;\n        }\n\n        __cancelLineTracer() {\n            this.lineTracerCallback = undefined;\n        }\n\n        __cancelBoard() {\n            this.boardCommand = 0;\n            this.boardState = 0;\n            this.boardCount = 0;\n            this.boardCallback = undefined;\n        }\n\n        __issueNoteBlockId() {\n            this.noteBlockId = this.blockId = (this.blockId % 65535) + 1;\n            return this.noteBlockId;\n        }\n\n        __cancelNote() {\n            this.noteBlockId = 0;\n            if (this.noteTimer1 !== undefined) {\n                this.__removeTimeout(this.noteTimer1);\n            }\n            if (this.noteTimer2 !== undefined) {\n                this.__removeTimeout(this.noteTimer2);\n            }\n            this.noteTimer1 = undefined;\n            this.noteTimer2 = undefined;\n        }\n\n        __issueIoBlockId() {\n            this.ioBlockId = this.blockId = (this.blockId % 65535) + 1;\n            return this.ioBlockId;\n        }\n\n        __cancelIo() {\n            this.ioBlockId = 0;\n            if (this.ioTimer !== undefined) {\n                this.__removeTimeout(this.ioTimer);\n            }\n            this.ioTimer = undefined;\n        }\n\n        handleSensory() {\n            const self = this;\n            const sensory = self.sensory;\n            if (self.lineTracerCallback) {\n                if (sensory.lineTracerStateId != self.lineTracerStateId) {\n                    self.lineTracerStateId = sensory.lineTracerStateId;\n                    if (sensory.lineTracerState == 0x40) {\n                        self.__setLineTracerMode(0);\n                        var callback = self.lineTracerCallback;\n                        self.__cancelLineTracer();\n                        if (callback) {\n                            callback();\n                        }\n                    }\n                }\n            }\n            if (self.boardCallback) {\n                const motoring = self.motoring;\n                if (self.boardCommand == 1) {\n                    switch (self.boardState) {\n                        case 1: {\n                            if (self.boardCount < 2) {\n                                if (sensory.leftFloor < 50 && sensory.rightFloor < 50) {\n                                    self.boardCount++;\n                                } else {\n                                    self.boardCount = 0;\n                                }\n                                var diff = sensory.leftFloor - sensory.rightFloor;\n                                motoring.leftWheel = 45 + diff * 0.25;\n                                motoring.rightWheel = 45 - diff * 0.25;\n                            } else {\n                                self.boardCount = 0;\n                                self.boardState = 2;\n                            }\n                            break;\n                        }\n                        case 2: {\n                            var diff = sensory.leftFloor - sensory.rightFloor;\n                            motoring.leftWheel = 45 + diff * 0.25;\n                            motoring.rightWheel = 45 - diff * 0.25;\n                            self.boardState = 3;\n                            self.wheelTimer = setTimeout(() => {\n                                motoring.leftWheel = 0;\n                                motoring.rightWheel = 0;\n                                self.boardState = 4;\n                                if (self.wheelTimer !== undefined) {\n                                    self.__removeTimeout(self.wheelTimer);\n                                }\n                                self.wheelTimer = undefined;\n                            }, 250);\n                            self.timeouts.push(self.wheelTimer);\n                            break;\n                        }\n                        case 3: {\n                            var diff = sensory.leftFloor - sensory.rightFloor;\n                            motoring.leftWheel = 45 + diff * 0.25;\n                            motoring.rightWheel = 45 - diff * 0.25;\n                            break;\n                        }\n                        case 4: {\n                            motoring.leftWheel = 0;\n                            motoring.rightWheel = 0;\n                            var callback = self.boardCallback;\n                            self.__cancelBoard();\n                            if (callback) {\n                                callback();\n                            }\n                            break;\n                        }\n                    }\n                } else if (self.boardCommand == 2) {\n                    switch (self.boardState) {\n                        case 1: {\n                            if (self.boardCount < 2) {\n                                if (sensory.leftFloor > 50) {\n                                    self.boardCount++;\n                                }\n                            } else {\n                                self.boardCount = 0;\n                                self.boardState = 2;\n                            }\n                            break;\n                        }\n                        case 2: {\n                            if (sensory.leftFloor < 20) {\n                                self.boardState = 3;\n                            }\n                            break;\n                        }\n                        case 3: {\n                            if (self.boardCount < 2) {\n                                if (sensory.leftFloor < 20) {\n                                    self.boardCount++;\n                                }\n                            } else {\n                                self.boardCount = 0;\n                                self.boardState = 4;\n                            }\n                            break;\n                        }\n                        case 4: {\n                            if (sensory.leftFloor > 50) {\n                                self.boardState = 5;\n                            }\n                            break;\n                        }\n                        case 5: {\n                            var diff = sensory.leftFloor - sensory.rightFloor;\n                            if (diff > -15) {\n                                motoring.leftWheel = 0;\n                                motoring.rightWheel = 0;\n                                var callback = self.boardCallback;\n                                self.__cancelBoard();\n                                if (callback) {\n                                    callback();\n                                }\n                            } else {\n                                motoring.leftWheel = diff * 0.5;\n                                motoring.rightWheel = -diff * 0.5;\n                            }\n                            break;\n                        }\n                    }\n                } else if (self.boardCommand == 3) {\n                    switch (self.boardState) {\n                        case 1: {\n                            if (self.boardCount < 2) {\n                                if (sensory.rightFloor > 50) {\n                                    self.boardCount++;\n                                }\n                            } else {\n                                self.boardCount = 0;\n                                self.boardState = 2;\n                            }\n                            break;\n                        }\n                        case 2: {\n                            if (sensory.rightFloor < 20) {\n                                self.boardState = 3;\n                            }\n                            break;\n                        }\n                        case 3: {\n                            if (self.boardCount < 2) {\n                                if (sensory.rightFloor < 20) {\n                                    self.boardCount++;\n                                }\n                            } else {\n                                self.boardCount = 0;\n                                self.boardState = 4;\n                            }\n                            break;\n                        }\n                        case 4: {\n                            if (sensory.rightFloor > 50) {\n                                self.boardState = 5;\n                            }\n                            break;\n                        }\n                        case 5: {\n                            var diff = sensory.rightFloor - sensory.leftFloor;\n                            if (diff > -15) {\n                                motoring.leftWheel = 0;\n                                motoring.rightWheel = 0;\n                                var callback = self.boardCallback;\n                                self.__cancelBoard();\n                                if (callback) {\n                                    callback();\n                                }\n                            } else {\n                                motoring.leftWheel = -diff * 0.5;\n                                motoring.rightWheel = diff * 0.5;\n                            }\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        getValue(script) {\n            const dev = script.getField('DEVICE');\n\n            const sensor = this.__SENSORS[dev] || dev;\n            return this.sensory[sensor];\n        }\n\n        checkBoolean(script) {\n            const sensory = this.sensory;\n            let value = 0;\n            const dev = script.getField('DEVICE');\n\n            if (dev.startsWith('TILT')) {\n                if (\n                    sensory.accelerationZ < 8192 &&\n                    sensory.accelerationX > 8192 &&\n                    sensory.accelerationY > -4096 &&\n                    sensory.accelerationY < 4096\n                ) {\n                    value = 1;\n                } else if (\n                    sensory.accelerationZ < 8192 &&\n                    sensory.accelerationX < -8192 &&\n                    sensory.accelerationY > -4096 &&\n                    sensory.accelerationY < 4096\n                ) {\n                    value = -1;\n                } else if (\n                    sensory.accelerationZ < 8192 &&\n                    sensory.accelerationY > 8192 &&\n                    sensory.accelerationX > -4096 &&\n                    sensory.accelerationX < 4096\n                ) {\n                    value = 2;\n                } else if (\n                    sensory.accelerationZ < 8192 &&\n                    sensory.accelerationY < -8192 &&\n                    sensory.accelerationX > -4096 &&\n                    sensory.accelerationX < 4096\n                ) {\n                    value = -2;\n                } else if (\n                    sensory.accelerationZ > 12288 &&\n                    sensory.accelerationX > -8192 &&\n                    sensory.accelerationX < 8192 &&\n                    sensory.accelerationY > -8192 &&\n                    sensory.accelerationY < 8192\n                ) {\n                    value = 3;\n                } else if (\n                    sensory.accelerationZ < -12288 &&\n                    sensory.accelerationX > -4096 &&\n                    sensory.accelerationX < 4096 &&\n                    sensory.accelerationY > -4096 &&\n                    sensory.accelerationY < 4096\n                ) {\n                    value = -3;\n                } else {\n                    value = 0;\n                }\n\n                switch (dev) {\n                    case 'TILT_FORWARD':\n                        return value == 1;\n                    case 'TILT_BACKWARD':\n                        return value == -1;\n                    case 'TILT_LEFT':\n                        return value == 2;\n                    case 'TILT_RIGHT':\n                        return value == -2;\n                    case 'TILT_FLIP':\n                        return value == 3;\n                    case 'TILT_NOT':\n                        return value == -3;\n                }\n                return false;\n            } else {\n                switch (dev) {\n                    case 'BATTERY_NORMAL':\n                        return sensory.batteryState === 2;\n                    case 'BATTERY_LOW':\n                        return sensory.batteryState === 1;\n                    case 'BATTERY_EMPTY':\n                        return sensory.batteryState === 0;\n                }\n                return false;\n            }\n        }\n\n        checkHandFound(script) {\n            const sensory = this.sensory;\n            return sensory.handFound === undefined\n                ? sensory.leftProximity > 40 || sensory.rightProximity > 40\n                : sensory.handFound;\n        }\n\n        __board(leftVelocity, rightVelocity, command, callback) {\n            const motoring = this.motoring;\n            this.__cancelWheel();\n            this.__cancelLineTracer();\n\n            motoring.leftWheel = leftVelocity;\n            motoring.rightWheel = rightVelocity;\n            motoring.motion = 0;\n            this.boardCommand = command;\n            this.boardCount = 0;\n            this.boardState = 1;\n            this.boardCallback = callback;\n            this.__setLineTracerMode(0);\n        }\n\n        boardForward(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                this.__board(45, 45, 1, () => {\n                    script.isMoving = false;\n                });\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        boardTurn(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const direction = script.getField('DIRECTION');\n                if (direction == 'LEFT') {\n                    this.__board(-45, 45, 2, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__board(45, -45, 3, () => {\n                        script.isMoving = false;\n                    });\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        __motion(type, leftVelocity, rightVelocity, secs, callback) {\n            const self = this;\n            const motoring = self.motoring;\n            self.__cancelBoard();\n            self.__cancelWheel();\n            self.__cancelLineTracer();\n\n            secs = parseFloat(secs);\n            if (secs && secs > 0) {\n                const id = self.__issueWheelBlockId();\n                motoring.leftWheel = leftVelocity;\n                motoring.rightWheel = rightVelocity;\n                motoring.motion = type;\n                self.__setLineTracerMode(0);\n                self.wheelTimer = setTimeout(() => {\n                    if (self.wheelBlockId == id) {\n                        motoring.leftWheel = 0;\n                        motoring.rightWheel = 0;\n                        motoring.motion = 0;\n                        self.__cancelWheel();\n                        callback();\n                    }\n                }, secs * 1000);\n                self.timeouts.push(self.wheelTimer);\n            } else {\n                motoring.leftWheel = 0;\n                motoring.rightWheel = 0;\n                motoring.motion = 0;\n                self.__setLineTracerMode(0);\n                callback();\n            }\n        }\n\n        moveForwardSecs(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const secs = script.getNumberValue('SECS');\n                if (secs < 0) {\n                    this.__motion(2, -30, -30, -secs, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motion(1, 30, 30, secs, () => {\n                        script.isMoving = false;\n                    });\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        moveBackwardSecs(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const secs = script.getNumberValue('SECS');\n                if (secs < 0) {\n                    this.__motion(1, 30, 30, -secs, () => {\n                        script.isMoving = false;\n                    });\n                } else {\n                    this.__motion(2, -30, -30, secs, () => {\n                        script.isMoving = false;\n                    });\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        turnSecs(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const direction = script.getField('DIRECTION');\n                const secs = script.getNumberValue('SECS');\n                if (direction == 'LEFT') {\n                    if (secs < 0) {\n                        this.__motion(4, 30, -30, -secs, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(3, -30, 30, secs, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    if (secs < 0) {\n                        this.__motion(3, -30, 30, -secs, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(4, 30, -30, secs, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        __stopMotion() {\n            const motoring = this.motoring;\n            this.__cancelBoard();\n            this.__cancelWheel();\n            this.__cancelLineTracer();\n\n            motoring.leftWheel = 0;\n            motoring.rightWheel = 0;\n            motoring.motion = 0;\n            this.__setLineTracerMode(0);\n        }\n\n        moveForwardUnit(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const value = script.getNumberValue('VALUE');\n                const unit = script.getField('UNIT');\n                if (unit == 'SEC') {\n                    if (value < 0) {\n                        this.__motion(2, -30, -30, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(1, 30, 30, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    this.__stopMotion();\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        moveBackwardUnit(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const value = script.getNumberValue('VALUE');\n                const unit = script.getField('UNIT');\n                if (unit == 'SEC') {\n                    if (value < 0) {\n                        this.__motion(1, 30, 30, -value, () => {\n                            script.isMoving = false;\n                        });\n                    } else {\n                        this.__motion(2, -30, -30, value, () => {\n                            script.isMoving = false;\n                        });\n                    }\n                } else {\n                    this.__stopMotion();\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        turnUnit(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const direction = script.getField('DIRECTION');\n                const value = script.getNumberValue('VALUE');\n                const unit = script.getField('UNIT');\n                if (unit == 'SEC') {\n                    if (direction == 'LEFT') {\n                        if (value < 0) {\n                            this.__motion(4, 30, -30, -value, () => {\n                                script.isMoving = false;\n                            });\n                        } else {\n                            this.__motion(3, -30, 30, value, () => {\n                                script.isMoving = false;\n                            });\n                        }\n                    } else {\n                        if (value < 0) {\n                            this.__motion(3, -30, 30, -value, () => {\n                                script.isMoving = false;\n                            });\n                        } else {\n                            this.__motion(4, 30, -30, value, () => {\n                                script.isMoving = false;\n                            });\n                        }\n                    }\n                } else {\n                    this.__stopMotion();\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        pivotUnit(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const part = script.getField('PART');\n                const value = script.getNumberValue('VALUE');\n                const unit = script.getField('UNIT');\n                const toward = script.getField('TOWARD');\n                if (unit == 'SEC') {\n                    if (part == 'LEFT_PEN') {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(14, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(13, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(13, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(14, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    } else if (part == 'RIGHT_PEN') {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(16, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(15, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(15, 0, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(16, 0, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    } else if (part == 'LEFT_WHEEL') {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(6, 0, -30, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(5, 0, 30, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(5, 0, 30, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(6, 0, -30, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    } else {\n                        if (toward == 'FORWARD') {\n                            if (value < 0) {\n                                this.__motion(8, -30, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(7, 30, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        } else {\n                            if (value < 0) {\n                                this.__motion(7, 30, 0, -value, () => {\n                                    script.isMoving = false;\n                                });\n                            } else {\n                                this.__motion(8, -30, 0, value, () => {\n                                    script.isMoving = false;\n                                });\n                            }\n                        }\n                    }\n                } else {\n                    this.__stopMotion();\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        swingUnit(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                const part = script.getField('PART');\n                const direction = script.getField('DIRECTION');\n                const value = script.getNumberValue('VALUE');\n                const unit = script.getField('UNIT');\n                let radius = script.getNumberValue('RADIUS');\n                const toward = script.getField('TOWARD');\n                if (unit == 'SEC') {\n                    radius = parseFloat(radius);\n                    if (typeof radius == 'number' && radius >= 0) {\n                        this.motoring.radius = radius;\n                        if (part == 'LEFT_PEN') {\n                            if (direction == 'LEFT') {\n                                if (toward == 'FORWARD') {\n                                    if (value < 0) {\n                                        this.__motion(18, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(17, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                } else {\n                                    if (value < 0) {\n                                        this.__motion(17, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(18, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                }\n                            } else {\n                                if (toward == 'FORWARD') {\n                                    if (value < 0) {\n                                        this.__motion(20, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(19, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                } else {\n                                    if (value < 0) {\n                                        this.__motion(19, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(20, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                }\n                            }\n                        } else if (part == 'RIGHT_PEN') {\n                            if (direction == 'LEFT') {\n                                if (toward == 'FORWARD') {\n                                    if (value < 0) {\n                                        this.__motion(22, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(21, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                } else {\n                                    if (value < 0) {\n                                        this.__motion(21, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(22, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                }\n                            } else {\n                                if (toward == 'FORWARD') {\n                                    if (value < 0) {\n                                        this.__motion(24, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(23, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                } else {\n                                    if (value < 0) {\n                                        this.__motion(23, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(24, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                }\n                            }\n                        } else {\n                            if (direction == 'LEFT') {\n                                if (toward == 'FORWARD') {\n                                    if (value < 0) {\n                                        this.__motion(10, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(9, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                } else {\n                                    if (value < 0) {\n                                        this.__motion(9, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(10, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                }\n                            } else {\n                                if (toward == 'FORWARD') {\n                                    if (value < 0) {\n                                        this.__motion(12, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(11, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                } else {\n                                    if (value < 0) {\n                                        this.__motion(11, 0, 0, -value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    } else {\n                                        this.__motion(12, 0, 0, value, () => {\n                                            script.isMoving = false;\n                                        });\n                                    }\n                                }\n                            }\n                        }\n                    } else {\n                        this.__stopMotion();\n                        script.isMoving = false;\n                    }\n                } else {\n                    this.__stopMotion();\n                }\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setWheels(script) {\n            const motoring = this.motoring;\n\n            this.__cancelBoard();\n            this.__cancelWheel();\n            this.__cancelLineTracer();\n\n            let leftVelocity = script.getNumberValue('LEFT');\n            let rightVelocity = script.getNumberValue('RIGHT');\n\n            leftVelocity = parseFloat(leftVelocity);\n            rightVelocity = parseFloat(rightVelocity);\n            if (typeof leftVelocity == 'number') {\n                motoring.leftWheel = leftVelocity;\n            }\n            if (typeof rightVelocity == 'number') {\n                motoring.rightWheel = rightVelocity;\n            }\n            motoring.motion = 0;\n            this.__setLineTracerMode(0);\n            return script.callReturn();\n        }\n\n        changeWheels(script) {\n            const motoring = this.motoring;\n\n            this.__cancelBoard();\n            this.__cancelWheel();\n            this.__cancelLineTracer();\n\n            let leftVelocity = script.getNumberValue('LEFT');\n            let rightVelocity = script.getNumberValue('RIGHT');\n\n            leftVelocity = parseFloat(leftVelocity);\n            rightVelocity = parseFloat(rightVelocity);\n            if (typeof leftVelocity == 'number') {\n                motoring.leftWheel =\n                    motoring.leftWheel !== undefined\n                        ? motoring.leftWheel + leftVelocity\n                        : leftVelocity;\n            }\n            if (typeof rightVelocity == 'number') {\n                motoring.rightWheel =\n                    motoring.rightWheel !== undefined\n                        ? motoring.rightWheel + rightVelocity\n                        : rightVelocity;\n            }\n            motoring.motion = 0;\n            this.__setLineTracerMode(0);\n            return script.callReturn();\n        }\n\n        setWheel(script) {\n            const motoring = this.motoring;\n\n            this.__cancelBoard();\n            this.__cancelWheel();\n            this.__cancelLineTracer();\n\n            const wheel = script.getField('WHEEL');\n            let velocity = script.getNumberValue('VELOCITY');\n\n            velocity = parseFloat(velocity);\n            if (typeof velocity == 'number') {\n                if (wheel == 'LEFT') {\n                    motoring.leftWheel = velocity;\n                } else if (wheel == 'RIGHT') {\n                    motoring.rightWheel = velocity;\n                } else {\n                    motoring.leftWheel = velocity;\n                    motoring.rightWheel = velocity;\n                }\n            }\n            motoring.motion = 0;\n            this.__setLineTracerMode(0);\n            return script.callReturn();\n        }\n\n        changeWheel(script) {\n            const motoring = this.motoring;\n\n            this.__cancelBoard();\n            this.__cancelWheel();\n            this.__cancelLineTracer();\n\n            const wheel = script.getField('WHEEL');\n            let velocity = script.getNumberValue('VELOCITY');\n\n            velocity = parseFloat(velocity);\n            if (typeof velocity == 'number') {\n                if (wheel == 'LEFT') {\n                    motoring.leftWheel =\n                        motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n                } else if (wheel == 'RIGHT') {\n                    motoring.rightWheel =\n                        motoring.rightWheel != undefined\n                            ? motoring.rightWheel + velocity\n                            : velocity;\n                } else {\n                    motoring.leftWheel =\n                        motoring.leftWheel != undefined ? motoring.leftWheel + velocity : velocity;\n                    motoring.rightWheel =\n                        motoring.rightWheel != undefined\n                            ? motoring.rightWheel + velocity\n                            : velocity;\n                }\n            }\n            motoring.motion = 0;\n            this.__setLineTracerMode(0);\n            return script.callReturn();\n        }\n\n        followLine(script) {\n            this.__cancelBoard();\n            this.__cancelWheel();\n            this.__cancelLineTracer();\n\n            const color = script.getField('COLOR');\n            const sensor = script.getField('SENSOR');\n\n            let mode = 1;\n            if (sensor == 'RIGHT') {\n                mode = 2;\n            } else if (sensor == 'BOTH') {\n                mode = 3;\n            }\n            if (color == 'WHITE') {\n                mode += 7;\n            }\n\n            const motoring = this.motoring;\n            motoring.leftWheel = 0;\n            motoring.rightWheel = 0;\n            motoring.motion = 0;\n            this.__setLineTracerMode(mode);\n\n            return script.callReturn();\n        }\n\n        followLineUntil(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isMoving = true;\n                this.__cancelBoard();\n                this.__cancelWheel();\n\n                const color = script.getField('COLOR');\n                const direction = script.getField('DIRECTION');\n\n                let mode = 4;\n                if (direction == 'RIGHT') {\n                    mode = 5;\n                } else if (direction == 'FRONT') {\n                    mode = 6;\n                } else if (direction == 'REAR') {\n                    mode = 7;\n                }\n                if (color == 'WHITE') {\n                    mode += 7;\n                }\n\n                const motoring = this.motoring;\n                motoring.leftWheel = 0;\n                motoring.rightWheel = 0;\n                motoring.motion = 0;\n                this.__setLineTracerMode(mode);\n                this.lineTracerCallback = () => {\n                    script.isMoving = false;\n                };\n\n                return script;\n            } else if (script.isMoving) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isMoving;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setLineTracerSpeed(script) {\n            const speed = parseInt(script.getField('SPEED'));\n\n            if (typeof speed == 'number') {\n                this.motoring.lineTracerSpeed = speed;\n            }\n            return script.callReturn();\n        }\n\n        setLineTracerGain(script) {\n            return script.callReturn();\n        }\n\n        stop(script) {\n            this.__cancelBoard();\n            this.__cancelWheel();\n            this.__cancelLineTracer();\n\n            const motoring = this.motoring;\n            motoring.leftWheel = 0;\n            motoring.rightWheel = 0;\n            motoring.motion = 0;\n            this.__setLineTracerMode(0);\n            return script.callReturn();\n        }\n        setLed(script) {\n            const led = script.getField('LED');\n            let color = script.getField('COLOR');\n            color = parseInt(this.__COLORS[color]);\n\n            if (color && color > 0) {\n                if (led == 'LEFT') {\n                    this.motoring.leftLed = color;\n                } else if (led == 'RIGHT') {\n                    this.motoring.rightLed = color;\n                } else {\n                    this.motoring.leftLed = color;\n                    this.motoring.rightLed = color;\n                }\n            }\n\n            return script.callReturn();\n        }\n\n        pickLed(script) {\n            return script.callReturn();\n        }\n\n        clearLed(script) {\n            const led = script.getField('LED');\n\n            if (led == 'LEFT') {\n                this.motoring.leftLed = 0;\n            } else if (led == 'RIGHT') {\n                this.motoring.rightLed = 0;\n            } else {\n                this.motoring.leftLed = 0;\n                this.motoring.rightLed = 0;\n            }\n\n            return script.callReturn();\n        }\n\n        setRgb(script) {\n            return script.callReturn();\n        }\n\n        changeRgb(script) {\n            return script.callReturn();\n        }\n\n        __runBeep(count, id, callback) {\n            if (count) {\n                const self = this;\n                const motoring = self.motoring;\n                if (!motoring.buzzer) {\n                    motoring.buzzer = 440;\n                }\n                motoring.note = 0;\n                self.noteTimer1 = setTimeout(() => {\n                    if (!id || self.noteBlockId == id) {\n                        if (self.noteTimer1 !== undefined) {\n                            self.__removeTimeout(self.noteTimer1);\n                        }\n                        self.noteTimer1 = undefined;\n                    }\n                }, 100);\n                self.timeouts.push(self.noteTimer1);\n                self.noteTimer2 = setTimeout(() => {\n                    if (!id || self.noteBlockId == id) {\n                        if (self.noteTimer2 !== undefined) {\n                            self.__removeTimeout(self.noteTimer2);\n                        }\n                        self.noteTimer2 = undefined;\n                        if (count < 0) {\n                            self.__runBeep(-1, id, callback);\n                        } else if (count == 1) {\n                            self.__cancelNote();\n                            if (id && callback) {\n                                callback();\n                            }\n                        } else {\n                            self.__runBeep(count - 1, id, callback);\n                        }\n                    }\n                }, 200);\n                self.timeouts.push(self.noteTimer2);\n            }\n        }\n\n        beep(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isPlaying = true;\n                this.__cancelNote();\n                const id = this.__issueNoteBlockId();\n                this.__runBeep(1, id, () => {\n                    script.isPlaying = false;\n                });\n\n                return script;\n            } else if (script.isPlaying) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isPlaying;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        playSound(script) {\n            this.__cancelNote();\n            this.motoring.buzzer = 0;\n            this.motoring.note = 0;\n\n            const sound = script.getField('SOUND');\n            let count = script.getNumberValue('COUNT');\n\n            count = parseInt(count);\n            if (sound == 'BEEP' && count) {\n                this.__runBeep(count);\n            }\n            return script.callReturn();\n        }\n\n        playSoundUntil(script) {\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isPlaying = true;\n                this.__cancelNote();\n                this.motoring.buzzer = 0;\n                this.motoring.note = 0;\n\n                const sound = script.getField('SOUND');\n                let count = script.getNumberValue('COUNT');\n\n                count = parseInt(count);\n                if (count) {\n                    if (sound == 'BEEP') {\n                        const id = this.__issueNoteBlockId();\n                        this.__runBeep(count, id, () => {\n                            script.isPlaying = false;\n                        });\n                    }\n                } else {\n                    script.isPlaying = false;\n                }\n\n                return script;\n            } else if (script.isPlaying) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isPlaying;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setBuzzer(script) {\n            this.__cancelNote();\n            let hz = script.getNumberValue('HZ');\n\n            hz = parseFloat(hz);\n            if (typeof hz == 'number') {\n                this.motoring.buzzer = hz;\n            }\n            this.motoring.note = 0;\n            return script.callReturn();\n        }\n\n        changeBuzzer(script) {\n            this.__cancelNote();\n            let hz = script.getNumberValue('HZ');\n\n            const motoring = this.motoring;\n            hz = parseFloat(hz);\n            if (typeof hz == 'number') {\n                motoring.buzzer = motoring.buzzer != undefined ? motoring.buzzer + hz : hz;\n            }\n            motoring.note = 0;\n            return script.callReturn();\n        }\n\n        clearBuzzer(script) {\n            this.__cancelNote();\n            this.motoring.buzzer = 0;\n            this.motoring.note = 0;\n            return script.callReturn();\n        }\n\n        clearSound(script, motoring) {\n            return this.clearBuzzer(script);\n        }\n\n        playNote(script) {\n            this.__cancelNote();\n\n            let note = script.getField('NOTE');\n            let octave = script.getNumberField('OCTAVE');\n\n            note = parseInt(this.__NOTES[note]);\n            octave = parseInt(octave);\n            const motoring = this.motoring;\n            motoring.buzzer = 0;\n            if (note && octave && octave > 0 && octave < 8) {\n                motoring.note = note + (octave - 1) * 12;\n            } else {\n                motoring.note = 0;\n            }\n\n            return script.callReturn();\n        }\n\n        playNoteBeat(script) {\n            const self = this;\n\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isPlaying = true;\n                self.__cancelNote();\n\n                const motoring = self.motoring;\n                let note = script.getField('NOTE');\n                let octave = script.getNumberField('OCTAVE');\n                let beat = script.getNumberValue('BEAT');\n\n                note = parseInt(Entry.HamsterLite.__NOTES[note]);\n                octave = parseInt(octave);\n                beat = parseFloat(beat);\n                motoring.buzzer = 0;\n                if (\n                    note &&\n                    octave &&\n                    octave > 0 &&\n                    octave < 8 &&\n                    beat &&\n                    beat > 0 &&\n                    self.tempo > 0\n                ) {\n                    const id = self.__issueNoteBlockId();\n                    note += (octave - 1) * 12;\n                    motoring.note = note;\n                    const timeValue = (beat * 60 * 1000) / self.tempo;\n                    if (timeValue > 100) {\n                        self.noteTimer1 = setTimeout(() => {\n                            if (self.noteBlockId == id) {\n                                motoring.note = 0;\n                                if (self.noteTimer1 !== undefined) {\n                                    self.__removeTimeout(self.noteTimer1);\n                                }\n                                self.noteTimer1 = undefined;\n                            }\n                        }, timeValue - 100);\n                        self.timeouts.push(self.noteTimer1);\n                    }\n                    self.noteTimer2 = setTimeout(() => {\n                        if (self.noteBlockId == id) {\n                            motoring.note = 0;\n                            self.__cancelNote();\n                            script.isPlaying = false;\n                        }\n                    }, timeValue);\n                    self.timeouts.push(self.noteTimer2);\n                } else {\n                    motoring.note = 0;\n                    script.isPlaying = false;\n                }\n                return script;\n            } else if (script.isPlaying) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isPlaying;\n                Entry.engine.isContinue = false;\n                self.motoring.note = 0;\n                return script.callReturn();\n            }\n        }\n\n        restBeat(script) {\n            const self = this;\n\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isPlaying = true;\n                self.__cancelNote();\n                let beat = script.getNumberValue('BEAT');\n\n                const motoring = self.motoring;\n                beat = parseFloat(beat);\n                motoring.buzzer = 0;\n                motoring.note = 0;\n                if (beat && beat > 0 && self.tempo > 0) {\n                    const id = self.__issueNoteBlockId();\n                    const timeValue = (beat * 60 * 1000) / self.tempo;\n                    self.noteTimer1 = setTimeout(() => {\n                        if (self.noteBlockId == id) {\n                            self.__cancelNote();\n                            script.isPlaying = false;\n                        }\n                    }, timeValue);\n                    self.timeouts.push(self.noteTimer1);\n                } else {\n                    script.isPlaying = false;\n                }\n\n                return script;\n            } else if (script.isPlaying) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isPlaying;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setTempo(script) {\n            let bpm = script.getNumberValue('BPM');\n\n            bpm = parseFloat(bpm);\n            if (typeof bpm == 'number') {\n                this.tempo = bpm < 1 ? 1 : bpm;\n            }\n\n            return script.callReturn();\n        }\n\n        changeTempo(script) {\n            let bpm = script.getNumberValue('BPM');\n\n            bpm = parseFloat(bpm);\n            if (typeof bpm == 'number') {\n                this.tempo += bpm;\n                if (this.tempo < 1) {\n                    this.tempo = 1;\n                }\n            }\n\n            return script.callReturn();\n        }\n\n        setIoMode(script) {\n            this.__cancelIo();\n\n            const port = script.getField('PORT');\n            const mode = parseInt(this.__IO_MODES[script.getField('MODE')]);\n\n            const motoring = this.motoring;\n            if (typeof mode == 'number') {\n                if (port == 'A') {\n                    motoring.ioModeA = mode;\n                } else if (port == 'B') {\n                    motoring.ioModeB = mode;\n                } else {\n                    motoring.ioModeA = mode;\n                    motoring.ioModeB = mode;\n                }\n            }\n\n            return script.callReturn();\n        }\n\n        setOutput(script) {\n            this.__cancelIo();\n\n            const motoring = this.motoring;\n            const port = script.getField('PORT');\n            let value = script.getNumberValue('VALUE');\n\n            value = parseFloat(value);\n            if (typeof value == 'number') {\n                if (port == 'A') {\n                    motoring.outputA = value;\n                } else if (port == 'B') {\n                    motoring.outputB = value;\n                } else {\n                    motoring.outputA = value;\n                    motoring.outputB = value;\n                }\n            }\n\n            return script.callReturn();\n        }\n\n        changeOutput(script) {\n            this.__cancelIo();\n\n            const motoring = this.motoring;\n            const port = script.getField('PORT');\n            let value = script.getNumberValue('VALUE');\n\n            value = parseFloat(value);\n            if (typeof value == 'number') {\n                if (port == 'A') {\n                    motoring.outputA =\n                        motoring.outputA != undefined ? motoring.outputA + value : value;\n                } else if (port == 'B') {\n                    motoring.outputB =\n                        motoring.outputB != undefined ? motoring.outputB + value : value;\n                } else {\n                    motoring.outputA =\n                        motoring.outputA != undefined ? motoring.outputA + value : value;\n                    motoring.outputB =\n                        motoring.outputB != undefined ? motoring.outputB + value : value;\n                }\n            }\n\n            return script.callReturn();\n        }\n\n        gripper(script) {\n            const self = this;\n\n            if (!script.isStart) {\n                script.isStart = true;\n                script.isPlaying = true;\n                self.__cancelIo();\n\n                const id = self.__issueIoBlockId();\n                const action = script.getField('ACTION');\n\n                const motoring = self.motoring;\n                motoring.ioModeA = 10;\n                motoring.ioModeB = 10;\n                if (action == 'OPEN') {\n                    motoring.outputA = 1;\n                    motoring.outputB = 0;\n                } else {\n                    motoring.outputA = 0;\n                    motoring.outputB = 1;\n                }\n                self.ioTimer = setTimeout(() => {\n                    if (self.ioBlockId == id) {\n                        self.__cancelIo();\n                        script.isPlaying = false;\n                    }\n                }, 500);\n                self.timeouts.push(self.ioTimer);\n\n                return script;\n            } else if (script.isPlaying) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.isPlaying;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        releaseGripper(script) {\n            this.__cancelIo();\n            const motoring = this.motoring;\n            motoring.ioModeA = 10;\n            motoring.ioModeB = 10;\n            motoring.outputA = 0;\n            motoring.outputB = 0;\n            return script.callReturn();\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        hamsterlite_gripper: '집게 %1 %2',\n                        hamsterlite_release_gripper: '집게 끄기 %1',\n                        hamsterlite_boolean: '%1?',\n                        hamsterlite_play_note: '%1 %2 음을 연주하기 %3',\n                        hamsterlite_hand_found: '손 찾음?',\n                        hamsterlite_value: '%1',\n                        hamsterlite_move_forward_once: '말판 앞으로 한 칸 이동하기 %1',\n                        hamsterlite_turn_once: '말판 %1 으로 한 번 돌기 %2',\n                        hamsterlite_move_forward_for_secs: '앞으로 %1 초 이동하기 %2',\n                        hamsterlite_move_backward_for_secs: '뒤로 %1 초 이동하기 %2',\n                        hamsterlite_turn_for_secs: '%1 으로 %2 초 돌기 %3',\n                        hamsterlite_change_both_wheels_by:\n                            '왼쪽 바퀴 %1 오른쪽 바퀴 %2 만큼 바꾸기 %3',\n                        hamsterlite_set_both_wheels_to:\n                            '왼쪽 바퀴 %1 오른쪽 바퀴 %2 (으)로 정하기 %3',\n                        hamsterlite_change_wheel_by: '%1 바퀴 %2 만큼 바꾸기 %3',\n                        hamsterlite_set_wheel_to: '%1 바퀴 %2 (으)로 정하기 %3',\n                        hamsterlite_follow_line_using: '%1 선을 %2 바닥 센서로 따라가기 %3',\n                        hamsterlite_follow_line_until: '%1 선을 따라 %2 교차로까지 이동하기 %3',\n                        hamsterlite_set_following_speed_to:\n                            '선 따라가기 속도를 %1 (으)로 정하기 %2',\n                        hamsterlite_stop: '정지하기 %1',\n                        hamsterlite_set_led_to: '%1 LED를 %2 으로 정하기 %3',\n                        hamsterlite_clear_led: '%1 LED 끄기 %2',\n                        hamsterlite_beep: '삐 소리내기 %1',\n                        hamsterlite_change_buzzer_by: '버저 음을 %1 만큼 바꾸기 %2',\n                        hamsterlite_set_buzzer_to: '버저 음을 %1 (으)로 정하기 %2',\n                        hamsterlite_clear_buzzer: '버저 끄기 %1',\n                        hamsterlite_play_note_for: '%1 %2 음을 %3 박자 연주하기 %4',\n                        hamsterlite_rest_for: '%1 박자 쉬기 %2',\n                        hamsterlite_change_tempo_by: '연주 속도를 %1 만큼 바꾸기 %2',\n                        hamsterlite_set_tempo_to: '연주 속도를 %1 BPM으로 정하기 %2',\n                        hamsterlite_set_port_to: '포트 %1 를 %2 으로 정하기 %3',\n                        hamsterlite_change_output_by: '출력 %1 를 %2 만큼 바꾸기 %3',\n                        hamsterlite_set_output_to: '출력 %1 를 %2 (으)로 정하기 %3',\n                    },\n                    Helper: {\n                        hamsterlite_gripper: '집게를 열거나 닫습니다.',\n                        hamsterlite_release_gripper:\n                            '집게의 전원을 끄고 자유롭게 움직일 수 있도록 합니다.',\n                        hamsterlite_boolean:\n                            \"앞으로 기울임: 앞으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>뒤로 기울임: 뒤로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>왼쪽으로 기울임: 왼쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>오른쪽으로 기울임: 오른쪽으로 기울이면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>거꾸로 뒤집음: 거꾸로 뒤집으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>기울이지 않음: 기울이지 않으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 정상: 배터리 잔량이 충분하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 부족: 배터리 잔량이 부족하면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.<br/>배터리 없음: 배터리 잔량이 없으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n                        hamsterlite_play_note: '선택한 계이름과 옥타브의 음을 소리 냅니다.',\n                        hamsterlite_beep: '버저 소리를 짧게 냅니다.',\n                        hamsterlite_change_both_wheels_by:\n                            '왼쪽과 오른쪽 바퀴의 현재 속도 값(%)에 입력한 값을 각각 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n                        hamsterlite_change_buzzer_by:\n                            '버저 소리의 현재 음 높이(Hz)에 입력한 값을 더합니다. 소수점 둘째 자리까지 입력할 수 있습니다.',\n                        hamsterlite_change_output_by:\n                            '선택한 외부 확장 포트의 현재 출력 값에 입력한 값을 더합니다. 더한 결과는 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n                        hamsterlite_change_tempo_by:\n                            '연주하거나 쉬는 속도의 현재 BPM(분당 박자 수)에 입력한 값을 더합니다.',\n                        hamsterlite_change_wheel_by:\n                            '왼쪽/오른쪽/양쪽 바퀴의 현재 속도 값(%)에 입력한 값을 더합니다. 더한 결과가 양수 값이면 바퀴가 앞으로 회전하고, 음수 값이면 뒤로 회전합니다.',\n                        hamsterlite_clear_buzzer: '버저 소리를 끕니다.',\n                        hamsterlite_clear_led: '왼쪽/오른쪽/양쪽 LED를 끕니다.',\n                        hamsterlite_follow_line_until:\n                            '왼쪽/오른쪽/앞쪽/뒤쪽의 검은색/하얀색 선을 따라 이동하다가 교차로를 만나면 정지합니다.',\n                        hamsterlite_follow_line_using:\n                            '왼쪽/오른쪽/양쪽 바닥 센서를 사용하여 검은색/하얀색 선을 따라 이동합니다.',\n                        hamsterlite_hand_found:\n                            \"근접 센서 앞에 손 또는 물체가 있으면 '참'으로 판단하고, 아니면 '거짓'으로 판단합니다.\",\n                        hamsterlite_move_backward_for_secs: '입력한 시간(초) 동안 뒤로 이동합니다.',\n                        hamsterlite_move_forward_for_secs:\n                            '입력한 시간(초) 동안 앞으로 이동합니다.',\n                        hamsterlite_move_forward_once: '말판 위에서 한 칸 앞으로 이동합니다.',\n                        hamsterlite_play_note_for:\n                            '선택한 계이름과 옥타브의 음을 입력한 박자만큼 소리 냅니다.',\n                        hamsterlite_rest_for: '입력한 박자만큼 쉽니다.',\n                        hamsterlite_set_both_wheels_to:\n                            '왼쪽과 오른쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 각각 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n                        hamsterlite_set_buzzer_to:\n                            '버저 소리의 음 높이를 입력한 값(Hz)으로 설정합니다. 소수점 둘째 자리까지 입력할 수 있습니다. 숫자 0을 입력하면 버저 소리를 끕니다.',\n                        hamsterlite_set_following_speed_to:\n                            '선을 따라 이동하는 속도(1 ~ 8)를 설정합니다. 숫자가 클수록 이동하는 속도가 빠릅니다.',\n                        hamsterlite_set_led_to: '왼쪽/오른쪽/양쪽 LED를 선택한 색깔로 켭니다.',\n                        hamsterlite_set_output_to:\n                            '선택한 외부 확장 포트의 출력 값을 입력한 값으로 설정합니다. 입력하는 값은 외부 확장 포트의 모드에 따라 다음의 범위를 가집니다.<br/>서보 출력: 유효한 값의 범위는 1 ~ 180도, 0이면 PWM 펄스 없이 항상 0을 출력<br/>PWM 출력: 0 ~ 100%, PWM 파형에서 ON 상태의 듀티비(%)<br/>디지털 출력: 0이면 LOW, 0이 아니면 HIGH',\n                        hamsterlite_set_port_to:\n                            '선택한 외부 확장 포트의 입출력 모드를 선택한 모드로 설정합니다.',\n                        hamsterlite_set_tempo_to:\n                            '연주하거나 쉬는 속도를 입력한 BPM(분당 박자 수)으로 설정합니다.',\n                        hamsterlite_set_wheel_to:\n                            '왼쪽/오른쪽/양쪽 바퀴의 속도를 입력한 값(-100 ~ 100%)으로 설정합니다. 양수 값을 입력하면 바퀴가 앞으로 회전하고, 음수 값을 입력하면 뒤로 회전합니다. 숫자 0을 입력하면 정지합니다.',\n                        hamsterlite_stop: '양쪽 바퀴를 정지합니다.',\n                        hamsterlite_turn_for_secs:\n                            '입력한 시간(초) 동안 왼쪽/오른쪽 방향으로 제자리에서 회전합니다.',\n                        hamsterlite_turn_once:\n                            '말판 위에서 왼쪽/오른쪽 방향으로 제자리에서 90도 회전합니다.',\n                        hamsterlite_value:\n                            '왼쪽 근접 센서: 왼쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>오른쪽 근접 센서: 오른쪽 근접 센서의 값 (값의 범위: 0 ~ 255, 초기값: 0)<br/>왼쪽 바닥 센서: 왼쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>오른쪽 바닥 센서: 오른쪽 바닥 센서의 값 (값의 범위: 0 ~ 100, 초기값: 0)<br/>x축 가속도: 가속도 센서의 X축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇이 전진하는 방향이 X축의 양수 방향입니다.<br/>y축 가속도: 가속도 센서의 Y축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 왼쪽 방향이 Y축의 양수 방향입니다.<br/>z축 가속도: 가속도 센서의 Z축 값 (값의 범위: -32768 ~ 32767, 초기값: 0) 로봇의 위쪽 방향이 Z축의 양수 방향입니다.<br/>밝기: 밝기 센서의 값 (값의 범위: 0 ~ 65535, 초기값: 0) 밝을 수록 값이 커집니다.<br/>온도: 로봇 내부의 온도 값 (값의 범위: 섭씨 -40 ~ 88도, 초기값: 0)<br/>신호 세기: 블루투스 무선 통신의 신호 세기 (값의 범위: -128 ~ 0 dBm, 초기값: 0) 신호의 세기가 셀수록 값이 커집니다.<br/>입력 A: 외부 확장 포트 A로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)<br/>입력 B: 외부 확장 포트 B로 입력되는 신호의 값 (값의 범위: 아날로그 입력 0 ~ 255, 디지털 입력 0 또는 1, 초기값: 0)',\n                    },\n                    Blocks: {\n                        hamsterlite_hand_found: '손 찾음?',\n                        hamsterlite_sensor_left_proximity: '왼쪽 근접 센서',\n                        hamsterlite_sensor_right_proximity: '오른쪽 근접 센서',\n                        hamsterlite_sensor_left_floor: '왼쪽 바닥 센서',\n                        hamsterlite_sensor_right_floor: '오른쪽 바닥 센서',\n                        hamsterlite_sensor_acceleration_x: 'x축 가속도',\n                        hamsterlite_sensor_acceleration_y: 'y축 가속도',\n                        hamsterlite_sensor_acceleration_z: 'z축 가속도',\n                        hamsterlite_sensor_light: '밝기',\n                        hamsterlite_sensor_temperature: '온도',\n                        hamsterlite_sensor_signal_strength: '신호 세기',\n                        hamsterlite_sensor_input_a: '입력 A',\n                        hamsterlite_sensor_input_b: '입력 B',\n                        hamsterlite_move_forward_once: '말판 앞으로 한 칸 이동하기',\n                        hamsterlite_turn_once_1: '말판',\n                        hamsterlite_turn_once_2: '으로 한 번 돌기',\n                        hamsterlite_turn_once_left: '왼쪽',\n                        hamsterlite_turn_right: '오른쪽',\n                        hamsterlite_move_forward: '앞으로 이동하기',\n                        hamsterlite_move_backward: '뒤로 이동하기',\n                        hamsterlite_turn_around_1: '',\n                        hamsterlite_turn_around_2: '으로 돌기',\n                        hamsterlite_move_forward_for_secs_1: '앞으로',\n                        hamsterlite_move_forward_for_secs_2: '초 이동하기',\n                        hamsterlite_move_backward_for_secs_1: '뒤로',\n                        hamsterlite_move_backward_for_secs_2: '초 이동하기',\n                        hamsterlite_turn_for_secs_1: '',\n                        hamsterlite_turn_for_secs_2: '으로',\n                        hamsterlite_turn_for_secs_3: '초 돌기',\n                        hamsterlite_change_both_wheels_by_1: '왼쪽 바퀴',\n                        hamsterlite_change_both_wheels_by_2: '오른쪽 바퀴',\n                        hamsterlite_change_both_wheels_by_3: '만큼 바꾸기',\n                        hamsterlite_set_both_wheels_to_1: '왼쪽 바퀴',\n                        hamsterlite_set_both_wheels_to_2: '오른쪽 바퀴',\n                        hamsterlite_set_both_wheels_to_3: '(으)로 정하기',\n                        hamsterlite_change_wheel_by_1: '',\n                        hamsterlite_change_wheel_by_2: '바퀴',\n                        hamsterlite_change_wheel_by_3: '만큼 바꾸기',\n                        hamsterlite_left_wheel: '왼쪽',\n                        hamsterlite_right_wheel: '오른쪽',\n                        hamsterlite_both_wheels: '양쪽',\n                        hamsterlite_set_wheel_to_1: '',\n                        hamsterlite_set_wheel_to_2: '바퀴',\n                        hamsterlite_set_wheel_to_3: '(으)로 정하기',\n                        hamsterlite_follow_line_using_1: '',\n                        hamsterlite_follow_line_using_2: '선을',\n                        hamsterlite_follow_line_using_3: '바닥 센서로 따라가기',\n                        hamsterlite_left_floor_sensor: '왼쪽',\n                        hamsterlite_right_floor_sensor: '오른쪽',\n                        hamsterlite_both_floor_sensors: '양쪽',\n                        hamsterlite_follow_line_until_1: '',\n                        hamsterlite_follow_line_until_2: '선을 따라',\n                        hamsterlite_follow_line_until_3: '교차로까지 이동하기',\n                        hamsterlite_left_intersection: '왼쪽',\n                        hamsterlite_right_intersection: '오른쪽',\n                        hamsterlite_front_intersection: '앞쪽',\n                        hamsterlite_rear_intersection: '뒤쪽',\n                        hamsterlite_set_following_speed_to_1: '선 따라가기 속도를',\n                        hamsterlite_set_following_speed_to_2: '(으)로 정하기',\n                        hamsterlite_front: '앞쪽',\n                        hamsterlite_rear: '뒤쪽',\n                        hamsterlite_stop: '정지하기',\n                        hamsterlite_set_led_to_1: '',\n                        hamsterlite_set_led_to_2: 'LED를',\n                        hamsterlite_set_led_to_3: '으로 정하기',\n                        hamsterlite_left_led: '왼쪽',\n                        hamsterlite_right_led: '오른쪽',\n                        hamsterlite_both_leds: '양쪽',\n                        hamsterlite_clear_led_1: '',\n                        hamsterlite_clear_led_2: 'LED 끄기',\n                        hamsterlite_color_cyan: '하늘색',\n                        hamsterlite_color_magenta: '자주색',\n                        hamsterlite_color_black: '검은색',\n                        hamsterlite_color_white: '하얀색',\n                        hamsterlite_color_red: '빨간색',\n                        hamsterlite_color_yellow: '노란색',\n                        hamsterlite_color_green: '초록색',\n                        hamsterlite_color_blue: '파란색',\n                        hamsterlite_beep: '삐 소리내기',\n                        hamsterlite_change_buzzer_by_1: '버저 음을',\n                        hamsterlite_change_buzzer_by_2: '만큼 바꾸기',\n                        hamsterlite_set_buzzer_to_1: '버저 음을',\n                        hamsterlite_set_buzzer_to_2: '(으)로 정하기',\n                        hamsterlite_clear_buzzer: '버저 끄기',\n                        hamsterlite_play_note_for_1: '',\n                        hamsterlite_play_note_for_2: '',\n                        hamsterlite_play_note_for_3: '음을',\n                        hamsterlite_play_note_for_4: '박자 연주하기',\n                        hamsterlite_rest_for_1: '',\n                        hamsterlite_rest_for_2: '박자 쉬기',\n                        hamsterlite_change_tempo_by_1: '연주 속도를',\n                        hamsterlite_change_tempo_by_2: '만큼 바꾸기',\n                        hamsterlite_set_tempo_to_1: '연주 속도를 분당',\n                        hamsterlite_set_tempo_to_2: '박자로 정하기',\n                        hamsterlite_set_port_to_1: '포트',\n                        hamsterlite_set_port_to_2: '를',\n                        hamsterlite_set_port_to_3: '으로 정하기',\n                        hamsterlite_change_output_by_1: '출력',\n                        hamsterlite_change_output_by_2: '를',\n                        hamsterlite_change_output_by_3: '만큼 바꾸기',\n                        hamsterlite_set_output_to_1: '출력',\n                        hamsterlite_set_output_to_2: '를',\n                        hamsterlite_set_output_to_3: '(으)로 정하기',\n                        hamsterlite_port_a: 'A',\n                        hamsterlite_port_b: 'B',\n                        hamsterlite_port_ab: 'A와 B',\n                        hamsterlite_analog_input: '아날로그 입력',\n                        hamsterlite_digital_input: '디지털 입력',\n                        hamsterlite_servo_output: '서보 출력',\n                        hamsterlite_pwm_output: 'PWM 출력',\n                        hamsterlite_digital_output: '디지털 출력',\n                        hamsterlite_note_c: '도',\n                        hamsterlite_note_c_sharp: '도♯(레♭)',\n                        hamsterlite_note_d: '레',\n                        hamsterlite_note_d_sharp: '레♯(미♭)',\n                        hamsterlite_note_e: '미',\n                        hamsterlite_note_f: '파',\n                        hamsterlite_note_f_sharp: '파♯(솔♭)',\n                        hamsterlite_note_g: '솔',\n                        hamsterlite_note_g_sharp: '솔♯(라♭)',\n                        hamsterlite_note_a: '라',\n                        hamsterlite_note_a_sharp: '라♯(시♭)',\n                        hamsterlite_note_b: '시',\n                        hamsterlite_tilt_forward: '앞으로 기울임',\n                        hamsterlite_tilt_backward: '뒤로 기울임',\n                        hamsterlite_tilt_left: '왼쪽으로 기울임',\n                        hamsterlite_tilt_right: '오른쪽으로 기울임',\n                        hamsterlite_tilt_flip: '거꾸로 뒤집음',\n                        hamsterlite_tilt_not: '기울이지 않음',\n                        hamsterlite_battery_normal: '배터리 정상',\n                        hamsterlite_battery_low: '배터리 부족',\n                        hamsterlite_battery_empty: '배터리 없음',\n                        hamsterlite_open_gripper: '열기',\n                        hamsterlite_close_gripper: '닫기',\n                    },\n                },\n                en: {\n                    template: {\n                        hamsterlite_gripper: '%1 gripper %2',\n                        hamsterlite_release_gripper: 'release gripper %1',\n                        hamsterlite_boolean: '%1?',\n                        hamsterlite_play_note: 'play note %1 %2 %3',\n                        hamsterlite_hand_found: 'hand found?',\n                        hamsterlite_value: '%1',\n                        hamsterlite_move_forward_once: 'move forward once on board %1',\n                        hamsterlite_turn_once: 'turn %1 once on board %2',\n                        hamsterlite_move_forward_for_secs: 'move forward for %1 secs %2',\n                        hamsterlite_move_backward_for_secs: 'move backward for %1 secs %2',\n                        hamsterlite_turn_for_secs: 'turn %1 for %2 secs %3',\n                        hamsterlite_change_both_wheels_by: 'change wheels by left: %1 right: %2 %3',\n                        hamsterlite_set_both_wheels_to: 'set wheels to left: %1 right: %2 %3',\n                        hamsterlite_change_wheel_by: 'change %1 wheel by %2 %3',\n                        hamsterlite_set_wheel_to: 'set %1 wheel to %2 %3',\n                        hamsterlite_follow_line_using: 'follow %1 line using %2 floor sensor %3',\n                        hamsterlite_follow_line_until: 'follow %1 line until %2 intersection %3',\n                        hamsterlite_set_following_speed_to: 'set following speed to %1 %2',\n                        hamsterlite_stop: 'stop %1',\n                        hamsterlite_set_led_to: 'set %1 led to %2 %3',\n                        hamsterlite_clear_led: 'clear %1 led %2',\n                        hamsterlite_beep: 'beep %1',\n                        hamsterlite_change_buzzer_by: 'change buzzer by %1 %2',\n                        hamsterlite_set_buzzer_to: 'set buzzer to %1 %2',\n                        hamsterlite_clear_buzzer: 'clear buzzer %1',\n                        hamsterlite_play_note_for: 'play note %1 %2 for %3 beats %4',\n                        hamsterlite_rest_for: 'rest for %1 beats %2',\n                        hamsterlite_change_tempo_by: 'change tempo by %1 %2',\n                        hamsterlite_set_tempo_to: 'set tempo to %1 bpm %2',\n                        hamsterlite_set_port_to: 'set port %1 to %2 %3',\n                        hamsterlite_change_output_by: 'change output %1 by %2 %3',\n                        hamsterlite_set_output_to: 'set output %1 to %2 %3',\n                    },\n                    Helper: {\n                        hamsterlite_gripper: 'Opens or closes the gripper.',\n                        hamsterlite_release_gripper:\n                            'Turns off the gripper so that it can be moved freely.',\n                        hamsterlite_boolean:\n                            'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n                        hamsterlite_play_note: 'It sounds the selected tone and octave.',\n                        hamsterlite_beep: 'Plays beep sound.',\n                        hamsterlite_change_both_wheels_by:\n                            'Adds the entered values to the current speed values (%) of the left and right wheels respectively. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n                        hamsterlite_change_buzzer_by:\n                            'Adds the entered value to the current pitch (Hz) of the buzzer sound. You can enter up to two decimal places.',\n                        hamsterlite_change_output_by:\n                            'Adds the entered value to the current output value of the selected external port. The result will be in the following range depending on the mode of the external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n                        hamsterlite_change_tempo_by:\n                            'Adds the entered value to the current BPM (beats per minute) of the playing or resting speed.',\n                        hamsterlite_change_wheel_by:\n                            'Adds the entered value to the current speed value (%) of the left/right/both wheels. If the result is positive, the wheel rotates forward; if negative, the wheel rotates backward.',\n                        hamsterlite_clear_buzzer: 'Turns off buzzer sound.',\n                        hamsterlite_clear_led: 'Turns off the left/right/both LEDs.',\n                        hamsterlite_follow_line_until:\n                            'Moves along the black/white line on the left/right/front/back, then stops when the robot meets the intersection.',\n                        hamsterlite_follow_line_using:\n                            'Moves along the black/white line by using the left/right/both floor sensors.',\n                        hamsterlite_hand_found:\n                            'If there is a hand or object in front of the proximity sensor, true, otherwise false',\n                        hamsterlite_move_backward_for_secs:\n                            'Moves backward for the number of seconds entered.',\n                        hamsterlite_move_forward_for_secs:\n                            'Moves forward for the number of seconds entered.',\n                        hamsterlite_move_forward_once: 'Moves one space forward on the board.',\n                        hamsterlite_play_note_for:\n                            'It sounds the selected tone and octave as much as the beat you entered.',\n                        hamsterlite_rest_for: 'Rests as much as the beat you entered.',\n                        hamsterlite_set_both_wheels_to:\n                            'Sets the speed of the left and right wheels to the entered values (-100 to 100%), respectively. If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n                        hamsterlite_set_buzzer_to:\n                            'Sets the pitch of the buzzer sound to the entered value (Hz). You can enter up to two decimal places. Entering the number 0 turns off the buzzer sound.',\n                        hamsterlite_set_following_speed_to:\n                            'Sets the speed (1 to 8) to move along the line. The larger the number, the faster the movement.',\n                        hamsterlite_set_led_to: 'Turns left/right/both LEDs to the selected color.',\n                        hamsterlite_set_output_to:\n                            'Sets the output value of the selected external port to the entered value. The value has the following range according to the mode of external port.<br/>Servo output: valid range from 1 to 180 degrees; if 0, output 0 without PWM pulse<br/>PWM output: 0 to 100%, duty ratio (%) of ON state in PWM waveform<br/>Digital output: LOW when 0, otherwise HIGH',\n                        hamsterlite_set_port_to:\n                            'Sets the io mode of the selected external port to the selected mode.',\n                        hamsterlite_set_tempo_to:\n                            'Sets the playing or resting speed to the entered BPM (beats per minute).',\n                        hamsterlite_set_wheel_to:\n                            'Sets the speed of the left/right/both wheels to the entered value (-100 to 100%). If you enter a positive value, the wheel rotates forward. If you enter a negative value, the wheel rotates backward. Entering the number 0 stops it.',\n                        hamsterlite_stop: 'Stops both wheels.',\n                        hamsterlite_turn_for_secs:\n                            'Turns left/right for the number of seconds entered.',\n                        hamsterlite_turn_once: 'Turns left/right 90 degrees on the board.',\n                        hamsterlite_value:\n                            'left proximity: value of left proximity sensor (range: 0 to 255, initial value: 0)<br/>right proximity: value of right proximity sensor (range: 0 to 255, initial value: 0)<br/>left floor: value of left floor sensor (range: 0 to 100, initial value: 0)<br/>right floor: value of right floor sensor (range: 0 to 100, initial value: 0)<br/>x acceleration: x-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The direction in which the robot moves forward is the positive direction of the x axis.<br/>y acceleration: y-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The left direction of the robot is the positive direction of the y axis.<br/>z acceleration: z-axis value of acceleration sensor (range: -32768 to 32767, initial value: 0) The upward direction of the robot is the positive direction of the z axis.<br/>light: value of light sensor (range: 0 to 65535, initial value: 0) The brighter, the larger the value.<br/>temperature: temperature value inside the robot (range: -40 to 88 degrees Celsius, initial value: 0)<br/>signal strength: signal strength of Bluetooth communication (range: -128 to 0 dBm, initial value: 0) As the signal strength increases, the value increases.<br/>input A: value of signal input to external port A (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)<br/>input B: value of signal input to external port B (range: analog input 0 to 255, digital input 0 or 1, initial value: 0)',\n                    },\n                    Blocks: {\n                        hamsterlite_hand_found: 'hand found?',\n                        hamsterlite_sensor_left_proximity: 'left proximity',\n                        hamsterlite_sensor_right_proximity: 'right proximity',\n                        hamsterlite_sensor_left_floor: 'left floor',\n                        hamsterlite_sensor_right_floor: 'right floor',\n                        hamsterlite_sensor_acceleration_x: 'x acceleration',\n                        hamsterlite_sensor_acceleration_y: 'y acceleration',\n                        hamsterlite_sensor_acceleration_z: 'z acceleration',\n                        hamsterlite_sensor_light: 'light',\n                        hamsterlite_sensor_temperature: 'temperature',\n                        hamsterlite_sensor_signal_strength: 'signal strength',\n                        hamsterlite_sensor_input_a: 'input A',\n                        hamsterlite_sensor_input_b: 'input B',\n                        hamsterlite_move_forward_once: 'move forward once on board',\n                        hamsterlite_turn_once_1: 'turn',\n                        hamsterlite_turn_once_2: 'once on board',\n                        hamsterlite_turn_once_left: 'left',\n                        hamsterlite_turn_right: 'right',\n                        hamsterlite_move_forward: 'move forward',\n                        hamsterlite_move_backward: 'move backward',\n                        hamsterlite_turn_around_1: 'turn',\n                        hamsterlite_turn_around_2: '',\n                        hamsterlite_move_forward_for_secs_1: 'move forward for',\n                        hamsterlite_move_forward_for_secs_2: 'secs',\n                        hamsterlite_move_backward_for_secs_1: 'move backward',\n                        hamsterlite_move_backward_for_secs_2: 'secs',\n                        hamsterlite_turn_for_secs_1: 'turn',\n                        hamsterlite_turn_for_secs_2: 'for',\n                        hamsterlite_turn_for_secs_3: 'secs',\n                        hamsterlite_change_both_wheels_by_1: 'change wheel by left:',\n                        hamsterlite_change_both_wheels_by_2: 'right:',\n                        hamsterlite_change_both_wheels_by_3: '',\n                        hamsterlite_set_both_wheels_to_1: 'set wheel to left:',\n                        hamsterlite_set_both_wheels_to_2: 'right:',\n                        hamsterlite_set_both_wheels_to_3: '',\n                        hamsterlite_change_wheel_by_1: 'change',\n                        hamsterlite_change_wheel_by_2: 'wheel by',\n                        hamsterlite_change_wheel_by_3: '',\n                        hamsterlite_left_wheel: 'left',\n                        hamsterlite_right_wheel: 'right',\n                        hamsterlite_both_wheels: 'both',\n                        hamsterlite_set_wheel_to_1: 'set',\n                        hamsterlite_set_wheel_to_2: 'wheel to',\n                        hamsterlite_set_wheel_to_3: '',\n                        hamsterlite_follow_line_using_1: 'follow',\n                        hamsterlite_follow_line_using_2: 'line using',\n                        hamsterlite_follow_line_using_3: 'floor sensor',\n                        hamsterlite_left_floor_sensor: 'left',\n                        hamsterlite_right_floor_sensor: 'right',\n                        hamsterlite_both_floor_sensors: 'both',\n                        hamsterlite_follow_line_until_1: 'follow',\n                        hamsterlite_follow_line_until_2: 'line until',\n                        hamsterlite_follow_line_until_3: 'intersection',\n                        hamsterlite_left_intersection: 'left',\n                        hamsterlite_right_intersection: 'right',\n                        hamsterlite_front_intersection: 'front',\n                        hamsterlite_rear_intersection: 'rear',\n                        hamsterlite_set_following_speed_to_1: 'set following speed to',\n                        hamsterlite_set_following_speed_to_2: '',\n                        hamsterlite_front: 'front',\n                        hamsterlite_rear: 'rear',\n                        hamsterlite_stop: 'stop',\n                        hamsterlite_set_led_to_1: 'set',\n                        hamsterlite_set_led_to_2: 'led to',\n                        hamsterlite_set_led_to_3: '',\n                        hamsterlite_left_led: 'left',\n                        hamsterlite_right_led: 'right',\n                        hamsterlite_both_leds: 'both',\n                        hamsterlite_clear_led_1: 'clear',\n                        hamsterlite_clear_led_2: 'led',\n                        hamsterlite_color_cyan: 'sky blue',\n                        hamsterlite_color_magenta: 'purple',\n                        hamsterlite_color_black: 'black',\n                        hamsterlite_color_white: 'white',\n                        hamsterlite_color_red: 'red',\n                        hamsterlite_color_yellow: 'yellow',\n                        hamsterlite_color_green: 'green',\n                        hamsterlite_color_blue: 'blue',\n                        hamsterlite_beep: 'beep',\n                        hamsterlite_change_buzzer_by_1: 'change buzzer by',\n                        hamsterlite_change_buzzer_by_2: '',\n                        hamsterlite_set_buzzer_to_1: 'set buzzer to',\n                        hamsterlite_set_buzzer_to_2: '',\n                        hamsterlite_clear_buzzer: 'clear buzzer',\n                        hamsterlite_play_note_for_1: 'play note',\n                        hamsterlite_play_note_for_2: '',\n                        hamsterlite_play_note_for_3: 'for',\n                        hamsterlite_play_note_for_4: 'beats',\n                        hamsterlite_rest_for_1: 'rest for',\n                        hamsterlite_rest_for_2: 'beats',\n                        hamsterlite_change_tempo_by_1: 'change tempo by',\n                        hamsterlite_change_tempo_by_2: '',\n                        hamsterlite_set_tempo_to_1: 'set tempo to',\n                        hamsterlite_set_tempo_to_2: 'bpm',\n                        hamsterlite_set_port_to_1: 'set port',\n                        hamsterlite_set_port_to_2: 'to',\n                        hamsterlite_set_port_to_3: '',\n                        hamsterlite_change_output_by_1: 'change output',\n                        hamsterlite_change_output_by_2: 'by',\n                        hamsterlite_change_output_by_3: '',\n                        hamsterlite_set_output_to_1: 'set output',\n                        hamsterlite_set_output_to_2: 'to',\n                        hamsterlite_set_output_to_3: '',\n                        hamsterlite_port_a: 'A',\n                        hamsterlite_port_b: 'B',\n                        hamsterlite_port_ab: 'A and B',\n                        hamsterlite_analog_input: 'analog input',\n                        hamsterlite_digital_input: 'digital input',\n                        hamsterlite_servo_output: 'servo output',\n                        hamsterlite_pwm_output: 'pwm output',\n                        hamsterlite_digital_output: 'digital output',\n                        hamsterlite_note_c: 'C',\n                        hamsterlite_note_c_sharp: 'C♯(D♭)',\n                        hamsterlite_note_d: 'D',\n                        hamsterlite_note_d_sharp: 'D♯(E♭)',\n                        hamsterlite_note_e: 'E',\n                        hamsterlite_note_f: 'F',\n                        hamsterlite_note_f_sharp: 'F♯(G♭)',\n                        hamsterlite_note_g: 'G',\n                        hamsterlite_note_g_sharp: 'G♯(A♭)',\n                        hamsterlite_note_a: 'A',\n                        hamsterlite_note_a_sharp: 'A♯(B♭)',\n                        hamsterlite_note_b: 'B',\n                        hamsterlite_tilt_forward: 'tilt forward',\n                        hamsterlite_tilt_backward: 'tilt backward',\n                        hamsterlite_tilt_left: 'tilt left',\n                        hamsterlite_tilt_right: 'tilt right',\n                        hamsterlite_tilt_flip: 'tilt flip',\n                        hamsterlite_tilt_not: 'not tilt',\n                        hamsterlite_battery_normal: 'battery normal',\n                        hamsterlite_battery_low: 'battery low',\n                        hamsterlite_battery_empty: 'battery empty',\n                        hamsterlite_open_gripper: 'open',\n                        hamsterlite_close_gripper: 'close',\n                    },\n                },\n                jp: {\n                    template: {\n                        hamsterlite_gripper: 'グリッパを %1 %2',\n                        hamsterlite_release_gripper: 'グリッパをオフ %1',\n                        hamsterlite_boolean: '%1?',\n                        hamsterlite_play_note: '%1 %2 を演奏する %3',\n                    },\n                    Helper: {\n                        hamsterlite_gripper: 'Opens or closes the gripper.',\n                        hamsterlite_release_gripper:\n                            'Turns off the gripper so that it can be moved freely.',\n                        hamsterlite_boolean:\n                            'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n                        hamsterlite_play_note: '選択された音階（音名、オクターブ）が鳴ります。',\n                    },\n                    Blocks: {\n                        hamsterlite_note_c: 'ド',\n                        hamsterlite_note_c_sharp: 'ド♯(レ♭)',\n                        hamsterlite_note_d: 'レ',\n                        hamsterlite_note_d_sharp: 'レ♯(ミ♭)',\n                        hamsterlite_note_e: 'ミ',\n                        hamsterlite_note_f: 'ファ',\n                        hamsterlite_note_f_sharp: 'ファ♯(ソ♭)',\n                        hamsterlite_note_g: 'ソ',\n                        hamsterlite_note_g_sharp: 'ソ♯(ラ♭)',\n                        hamsterlite_note_a: 'ラ',\n                        hamsterlite_note_a_sharp: 'ラ♯(シ♭)',\n                        hamsterlite_note_b: 'シ',\n                        hamsterlite_tilt_forward: '前に傾けたか',\n                        hamsterlite_tilt_backward: '後に傾けたか',\n                        hamsterlite_tilt_left: '左に傾けたか',\n                        hamsterlite_tilt_right: '右に傾けたか',\n                        hamsterlite_tilt_flip: '上下裏返したか',\n                        hamsterlite_tilt_not: '傾けなかったか',\n                        hamsterlite_battery_normal: '電池が正常か',\n                        hamsterlite_battery_low: '電池が足りないか',\n                        hamsterlite_battery_empty: '電池がないか',\n                        hamsterlite_open_gripper: '開く',\n                        hamsterlite_close_gripper: '閉める',\n                    },\n                },\n                vn: {\n                    template: {\n                        hamsterlite_gripper: '%1 gripper %2',\n                        hamsterlite_release_gripper: 'release gripper %1',\n                        hamsterlite_boolean: '%1?',\n                        hamsterlite_play_note: 'play note %1 %2 %3',\n                    },\n                    Helper: {\n                        hamsterlite_gripper: 'Opens or closes the gripper.',\n                        hamsterlite_release_gripper:\n                            'Turns off the gripper so that it can be moved freely.',\n                        hamsterlite_boolean:\n                            'tilt forward: If tilted forward, true, otherwise false<br/>tilt backward: If tilted backward, true, otherwise false<br/>tilt left: If tilted to the left, true, otherwise false<br/>tilt right: If tilted to the right, true, otherwise false<br/>tilt flip: If upside-down, true, otherwise false<br/>not tilt: If not tilted, true, otherwise false<br/>battery normal: If the battery is enough, true, otherwise false<br/>battery low: If the battery is low, true, otherwise false<br/>battery empty: If the battery is empty, true, otherwise false',\n                        hamsterlite_play_note: 'It sounds the selected tone and octave.',\n                    },\n                    Blocks: {\n                        hamsterlite_note_c: 'C',\n                        hamsterlite_note_c_sharp: 'C♯(D♭)',\n                        hamsterlite_note_d: 'D',\n                        hamsterlite_note_d_sharp: 'D♯(E♭)',\n                        hamsterlite_note_e: 'E',\n                        hamsterlite_note_f: 'F',\n                        hamsterlite_note_f_sharp: 'F♯(G♭)',\n                        hamsterlite_note_g: 'G',\n                        hamsterlite_note_g_sharp: 'G♯(A♭)',\n                        hamsterlite_note_a: 'A',\n                        hamsterlite_note_a_sharp: 'A♯(B♭)',\n                        hamsterlite_note_b: 'B',\n                        hamsterlite_tilt_forward: 'tilt forward',\n                        hamsterlite_tilt_backward: 'tilt backward',\n                        hamsterlite_tilt_left: 'tilt left',\n                        hamsterlite_tilt_right: 'tilt right',\n                        hamsterlite_tilt_flip: 'tilt flip',\n                        hamsterlite_tilt_not: 'not tilt',\n                        hamsterlite_battery_normal: 'battery normal',\n                        hamsterlite_battery_low: 'battery low',\n                        hamsterlite_battery_empty: 'battery empty',\n                        hamsterlite_open_gripper: 'open',\n                        hamsterlite_close_gripper: 'close',\n                    },\n                },\n            };\n        }\n        getBlocks() {\n            return {\n                hamsterlite_hand_found: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'hamsterlite_hand_found',\n                    },\n                    class: 'hamsterlite_sensor',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.checkHandFound(script) || false;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.hand_found()',\n                                blockType: 'param',\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_boolean: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_tilt_forward, 'TILT_FORWARD'],\n                                [Lang.Blocks.hamsterlite_tilt_backward, 'TILT_BACKWARD'],\n                                [Lang.Blocks.hamsterlite_tilt_left, 'TILT_LEFT'],\n                                [Lang.Blocks.hamsterlite_tilt_right, 'TILT_RIGHT'],\n                                [Lang.Blocks.hamsterlite_tilt_flip, 'TILT_FLIP'],\n                                [Lang.Blocks.hamsterlite_tilt_not, 'TILT_NOT'],\n                                [Lang.Blocks.hamsterlite_battery_normal, 'BATTERY_NORMAL'],\n                                [Lang.Blocks.hamsterlite_battery_low, 'BATTERY_LOW'],\n                                [Lang.Blocks.hamsterlite_battery_empty, 'BATTERY_EMPTY'],\n                            ],\n                            value: 'TILT_FORWARD',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'hamsterlite_boolean',\n                    },\n                    paramsKeyMap: {\n                        DEVICE: 0,\n                    },\n                    class: 'hamsterlite_sensor',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.checkBoolean(script) || false;\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.boolean_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_tilt_forward, 'TILT_FORWARD'],\n                                            [\n                                                Lang.Blocks.hamsterlite_tilt_backward,\n                                                'TILT_BACKWARD',\n                                            ],\n                                            [Lang.Blocks.hamsterlite_tilt_left, 'TILT_LEFT'],\n                                            [Lang.Blocks.hamsterlite_tilt_right, 'TILT_RIGHT'],\n                                            [Lang.Blocks.hamsterlite_tilt_flip, 'TILT_FLIP'],\n                                            [Lang.Blocks.hamsterlite_tilt_not, 'TILT_NOT'],\n                                            [\n                                                Lang.Blocks.hamsterlite_battery_normal,\n                                                'BATTERY_NORMAL',\n                                            ],\n                                            [Lang.Blocks.hamsterlite_battery_low, 'BATTERY_LOW'],\n                                            [\n                                                Lang.Blocks.hamsterlite_battery_empty,\n                                                'BATTERY_EMPTY',\n                                            ],\n                                        ],\n                                        value: 'TILT_FORWARD',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_sensor_left_proximity, 'leftProximity'],\n                                [Lang.Blocks.hamsterlite_sensor_right_proximity, 'rightProximity'],\n                                [Lang.Blocks.hamsterlite_sensor_left_floor, 'leftFloor'],\n                                [Lang.Blocks.hamsterlite_sensor_right_floor, 'rightFloor'],\n                                [Lang.Blocks.hamsterlite_sensor_acceleration_x, 'accelerationX'],\n                                [Lang.Blocks.hamsterlite_sensor_acceleration_y, 'accelerationY'],\n                                [Lang.Blocks.hamsterlite_sensor_acceleration_z, 'accelerationZ'],\n                                [Lang.Blocks.hamsterlite_sensor_light, 'light'],\n                                [Lang.Blocks.hamsterlite_sensor_temperature, 'temperature'],\n                                [Lang.Blocks.hamsterlite_sensor_signal_strength, 'signalStrength'],\n                                [Lang.Blocks.hamsterlite_sensor_input_a, 'inputA'],\n                                [Lang.Blocks.hamsterlite_sensor_input_b, 'inputB'],\n                            ],\n                            value: 'leftProximity',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'hamsterlite_value',\n                    },\n                    paramsKeyMap: {\n                        DEVICE: 0,\n                    },\n                    class: 'hamsterlite_sensor',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.getValue(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.sensor_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_left_proximity,\n                                                'leftProximity',\n                                            ],\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_right_proximity,\n                                                'rightProximity',\n                                            ],\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_left_floor,\n                                                'leftFloor',\n                                            ],\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_right_floor,\n                                                'rightFloor',\n                                            ],\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_acceleration_x,\n                                                'accelerationX',\n                                            ],\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_acceleration_y,\n                                                'accelerationY',\n                                            ],\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_acceleration_z,\n                                                'accelerationZ',\n                                            ],\n                                            [Lang.Blocks.hamsterlite_sensor_light, 'light'],\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_temperature,\n                                                'temperature',\n                                            ],\n                                            [\n                                                Lang.Blocks.hamsterlite_sensor_signal_strength,\n                                                'signalStrength',\n                                            ],\n                                            [Lang.Blocks.hamsterlite_sensor_input_a, 'inputA'],\n                                            [Lang.Blocks.hamsterlite_sensor_input_b, 'inputB'],\n                                        ],\n                                        value: 'leftProximity',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_move_forward_once: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'hamsterlite_move_forward_once',\n                    },\n                    class: 'hamsterlite_board',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.boardForward(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.board_forward()',\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_turn_once: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_turn_once_left, 'LEFT'],\n                                [Lang.Blocks.hamsterlite_turn_right, 'RIGHT'],\n                            ],\n                            value: 'LEFT',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'hamsterlite_turn_once',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'hamsterlite_board',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.boardTurn(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.board_turn(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_turn_once_left, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_turn_right, 'RIGHT'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_move_forward_for_secs: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['1'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_move_forward_for_secs',\n                    },\n                    paramsKeyMap: {\n                        SECS: 0,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.moveForwardSecs(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.move_forward(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_move_backward_for_secs: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['1'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_move_backward_for_secs',\n                    },\n                    paramsKeyMap: {\n                        SECS: 0,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.moveBackwardSecs(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.move_backward(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_turn_for_secs: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_turn_once_left, 'LEFT'],\n                                [Lang.Blocks.hamsterlite_turn_right, 'RIGHT'],\n                            ],\n                            value: 'LEFT',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'text',\n                                params: ['1'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_turn_for_secs',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                        SECS: 1,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.turnSecs(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.turn(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_turn_once_left, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_turn_right, 'RIGHT'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_change_both_wheels_by: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_change_both_wheels_by',\n                    },\n                    paramsKeyMap: {\n                        LEFT: 0,\n                        RIGHT: 1,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.changeWheels(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.add_wheels(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_set_both_wheels_to: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['30'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['30'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_set_both_wheels_to',\n                    },\n                    paramsKeyMap: {\n                        LEFT: 0,\n                        RIGHT: 1,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.setWheels(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_wheels(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_change_wheel_by: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_left_wheel, 'LEFT'],\n                                [Lang.Blocks.hamsterlite_right_wheel, 'RIGHT'],\n                                [Lang.Blocks.hamsterlite_both_wheels, 'BOTH'],\n                            ],\n                            value: 'LEFT',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_change_wheel_by',\n                    },\n                    paramsKeyMap: {\n                        WHEEL: 0,\n                        VELOCITY: 1,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.changeWheel(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.add_wheel(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_wheel, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_wheel, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_wheels, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_set_wheel_to: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_left_wheel, 'LEFT'],\n                                [Lang.Blocks.hamsterlite_right_wheel, 'RIGHT'],\n                                [Lang.Blocks.hamsterlite_both_wheels, 'BOTH'],\n                            ],\n                            value: 'LEFT',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'text',\n                                params: ['30'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_set_wheel_to',\n                    },\n                    paramsKeyMap: {\n                        WHEEL: 0,\n                        VELOCITY: 1,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.setWheel(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_wheel(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_wheel, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_wheel, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_wheels, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_follow_line_using: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_color_black, 'BLACK'],\n                                [Lang.Blocks.hamsterlite_color_white, 'WHITE'],\n                            ],\n                            value: 'BLACK',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_left_floor_sensor, 'LEFT'],\n                                [Lang.Blocks.hamsterlite_right_floor_sensor, 'RIGHT'],\n                                [Lang.Blocks.hamsterlite_both_floor_sensors, 'BOTH'],\n                            ],\n                            value: 'LEFT',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'hamsterlite_follow_line_using',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                        SENSOR: 1,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.followLine(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.follow_line(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_black, 'BLACK'],\n                                            [Lang.Blocks.hamsterlite_color_white, 'WHITE'],\n                                        ],\n                                        value: 'BLACK',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_floor_sensor, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_floor_sensor, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_floor_sensors, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_follow_line_until: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_color_black, 'BLACK'],\n                                [Lang.Blocks.hamsterlite_color_white, 'WHITE'],\n                            ],\n                            value: 'BLACK',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_left_floor_sensor, 'LEFT'],\n                                [Lang.Blocks.hamsterlite_right_floor_sensor, 'RIGHT'],\n                                [Lang.Blocks.hamsterlite_front, 'FRONT'],\n                                [Lang.Blocks.hamsterlite_rear, 'REAR'],\n                            ],\n                            value: 'FRONT',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'hamsterlite_follow_line_until',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.followLineUntil(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.follow_line_until(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_black, 'BLACK'],\n                                            [Lang.Blocks.hamsterlite_color_white, 'WHITE'],\n                                        ],\n                                        value: 'BLACK',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_floor_sensor, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_floor_sensor, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_front, 'FRONT'],\n                                            [Lang.Blocks.hamsterlite_rear, 'REAR'],\n                                        ],\n                                        value: 'FRONT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_set_following_speed_to: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                                ['8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['5', null],\n                        type: 'hamsterlite_set_following_speed_to',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.setLineTracerSpeed(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_line_speed(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                            ['8', '8'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'hamsterlite_stop',\n                    },\n                    class: 'hamsterlite_wheel',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.stop(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.stop()',\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_set_led_to: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                            ],\n                            value: 'LEFT',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_color_red, '4'],\n                                [Lang.Blocks.hamsterlite_color_yellow, '6'],\n                                [Lang.Blocks.hamsterlite_color_green, '2'],\n                                [Lang.Blocks.hamsterlite_color_cyan, '3'],\n                                [Lang.Blocks.hamsterlite_color_blue, '1'],\n                                [Lang.Blocks.hamsterlite_color_magenta, '5'],\n                                [Lang.Blocks.hamsterlite_color_white, '7'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'hamsterlite_set_led_to',\n                    },\n                    paramsKeyMap: {\n                        LED: 0,\n                        COLOR: 1,\n                    },\n                    class: 'hamsterlite_led',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.setLed(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_led_red(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_red, '4'],\n                                            [Lang.Blocks.hamsterlite_color_yellow, '6'],\n                                            [Lang.Blocks.hamsterlite_color_green, '2'],\n                                            [Lang.Blocks.hamsterlite_color_cyan, '3'],\n                                            [Lang.Blocks.hamsterlite_color_blue, '1'],\n                                            [Lang.Blocks.hamsterlite_color_magenta, '5'],\n                                            [Lang.Blocks.hamsterlite_color_white, '7'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '4'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_led_yellow(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_red, '4'],\n                                            [Lang.Blocks.hamsterlite_color_yellow, '6'],\n                                            [Lang.Blocks.hamsterlite_color_green, '2'],\n                                            [Lang.Blocks.hamsterlite_color_cyan, '3'],\n                                            [Lang.Blocks.hamsterlite_color_blue, '1'],\n                                            [Lang.Blocks.hamsterlite_color_magenta, '5'],\n                                            [Lang.Blocks.hamsterlite_color_white, '7'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '6'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_led_green(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_red, '4'],\n                                            [Lang.Blocks.hamsterlite_color_yellow, '6'],\n                                            [Lang.Blocks.hamsterlite_color_green, '2'],\n                                            [Lang.Blocks.hamsterlite_color_cyan, '3'],\n                                            [Lang.Blocks.hamsterlite_color_blue, '1'],\n                                            [Lang.Blocks.hamsterlite_color_magenta, '5'],\n                                            [Lang.Blocks.hamsterlite_color_white, '7'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '2'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_led_sky_blue(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_red, '4'],\n                                            [Lang.Blocks.hamsterlite_color_yellow, '6'],\n                                            [Lang.Blocks.hamsterlite_color_green, '2'],\n                                            [Lang.Blocks.hamsterlite_color_cyan, '3'],\n                                            [Lang.Blocks.hamsterlite_color_blue, '1'],\n                                            [Lang.Blocks.hamsterlite_color_magenta, '5'],\n                                            [Lang.Blocks.hamsterlite_color_white, '7'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '3'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_led_blue(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_red, '4'],\n                                            [Lang.Blocks.hamsterlite_color_yellow, '6'],\n                                            [Lang.Blocks.hamsterlite_color_green, '2'],\n                                            [Lang.Blocks.hamsterlite_color_cyan, '3'],\n                                            [Lang.Blocks.hamsterlite_color_blue, '1'],\n                                            [Lang.Blocks.hamsterlite_color_magenta, '5'],\n                                            [Lang.Blocks.hamsterlite_color_white, '7'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '1'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_led_purple(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_red, '4'],\n                                            [Lang.Blocks.hamsterlite_color_yellow, '6'],\n                                            [Lang.Blocks.hamsterlite_color_green, '2'],\n                                            [Lang.Blocks.hamsterlite_color_cyan, '3'],\n                                            [Lang.Blocks.hamsterlite_color_blue, '1'],\n                                            [Lang.Blocks.hamsterlite_color_magenta, '5'],\n                                            [Lang.Blocks.hamsterlite_color_white, '7'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '5'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_led_white(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_color_red, '4'],\n                                            [Lang.Blocks.hamsterlite_color_yellow, '6'],\n                                            [Lang.Blocks.hamsterlite_color_green, '2'],\n                                            [Lang.Blocks.hamsterlite_color_cyan, '3'],\n                                            [Lang.Blocks.hamsterlite_color_blue, '1'],\n                                            [Lang.Blocks.hamsterlite_color_magenta, '5'],\n                                            [Lang.Blocks.hamsterlite_color_white, '7'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '7'],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_clear_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                            ],\n                            value: 'LEFT',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'hamsterlite_clear_led',\n                    },\n                    paramsKeyMap: {\n                        LED: 0,\n                    },\n                    class: 'hamsterlite_led',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.clearLed(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.clear_led(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_left_led, 'LEFT'],\n                                            [Lang.Blocks.hamsterlite_right_led, 'RIGHT'],\n                                            [Lang.Blocks.hamsterlite_both_leds, 'BOTH'],\n                                        ],\n                                        value: 'LEFT',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_beep: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'hamsterlite_beep',\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.beep(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.beep()',\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_change_buzzer_by: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_change_buzzer_by',\n                    },\n                    paramsKeyMap: {\n                        HZ: 0,\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.changeBuzzer(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.add_buzzer(%1)',\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_set_buzzer_to: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['1000'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_set_buzzer_to',\n                    },\n                    paramsKeyMap: {\n                        HZ: 0,\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.setBuzzer(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_buzzer(%1)',\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_clear_buzzer: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'hamsterlite_clear_buzzer',\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.clearBuzzer(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.clear_buzzer()',\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_play_note: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_note_c, '4'],\n                                [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                [Lang.Blocks.hamsterlite_note_d, '6'],\n                                [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                [Lang.Blocks.hamsterlite_note_e, '8'],\n                                [Lang.Blocks.hamsterlite_note_f, '9'],\n                                [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                [Lang.Blocks.hamsterlite_note_g, '11'],\n                                [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                [Lang.Blocks.hamsterlite_note_a, '13'],\n                                [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                [Lang.Blocks.hamsterlite_note_b, '15'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, '4', null],\n                        type: 'hamsterlite_play_note',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                        OCTAVE: 1,\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.playNote(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.play_pitch_c(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['4'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_c_sharp(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['5'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_d(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['6'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_d_sharp(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['7'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_e(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['8'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_f(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['9'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_f_sharp(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['10'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_g(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['11'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_g_sharp(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['12'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_a(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['13'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_a_sharp(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['14'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_pitch_b(%2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                ],\n                                params: ['15'],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_play_note_for: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_note_c, '4'],\n                                [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                [Lang.Blocks.hamsterlite_note_d, '6'],\n                                [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                [Lang.Blocks.hamsterlite_note_e, '8'],\n                                [Lang.Blocks.hamsterlite_note_f, '9'],\n                                [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                [Lang.Blocks.hamsterlite_note_g, '11'],\n                                [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                [Lang.Blocks.hamsterlite_note_a, '13'],\n                                [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                [Lang.Blocks.hamsterlite_note_b, '15'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            '4',\n                            {\n                                type: 'text',\n                                params: ['0.5'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_play_note_for',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                        OCTAVE: 1,\n                        BEAT: 2,\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.playNoteBeat(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.play_note_c(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['4'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_c_sharp(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['5'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_d(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['6'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_d_sharp(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['7'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_e(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['8'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_f(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['9'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_f_sharp(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['10'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_g(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['11'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_g_sharp(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['12'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_a(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['13'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_a_sharp(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['14'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.play_note_b(%2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_note_c, '4'],\n                                            [Lang.Blocks.hamsterlite_note_c_sharp, '5'],\n                                            [Lang.Blocks.hamsterlite_note_d, '6'],\n                                            [Lang.Blocks.hamsterlite_note_d_sharp, '7'],\n                                            [Lang.Blocks.hamsterlite_note_e, '8'],\n                                            [Lang.Blocks.hamsterlite_note_f, '9'],\n                                            [Lang.Blocks.hamsterlite_note_f_sharp, '10'],\n                                            [Lang.Blocks.hamsterlite_note_g, '11'],\n                                            [Lang.Blocks.hamsterlite_note_g_sharp, '12'],\n                                            [Lang.Blocks.hamsterlite_note_a, '13'],\n                                            [Lang.Blocks.hamsterlite_note_a_sharp, '14'],\n                                            [Lang.Blocks.hamsterlite_note_b, '15'],\n                                        ],\n                                        value: '4',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['1', '1'],\n                                            ['2', '2'],\n                                            ['3', '3'],\n                                            ['4', '4'],\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                            ['7', '7'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringOrNumberByValue,\n                                    },\n                                    { type: 'Block', accept: 'string' },\n                                ],\n                                params: ['15'],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_rest_for: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['0.25'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_rest_for',\n                    },\n                    paramsKeyMap: {\n                        BEAT: 0,\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.restBeat(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.rest(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_change_tempo_by: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['20'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_change_tempo_by',\n                    },\n                    paramsKeyMap: {\n                        BPM: 0,\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.changeTempo(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.add_tempo(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_set_tempo_to: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['60'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_set_tempo_to',\n                    },\n                    paramsKeyMap: {\n                        BPM: 0,\n                    },\n                    class: 'hamsterlite_buzzer',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.setTempo(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_tempo(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_set_port_to: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                            ],\n                            value: 'A',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_analog_input, '0'],\n                                [Lang.Blocks.hamsterlite_digital_input, '1'],\n                                [Lang.Blocks.hamsterlite_servo_output, '8'],\n                                [Lang.Blocks.hamsterlite_pwm_output, '9'],\n                                [Lang.Blocks.hamsterlite_digital_output, '10'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'hamsterlite_set_port_to',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        MODE: 1,\n                    },\n                    class: 'hamsterlite_port',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.setIoMode(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_io_mode_analog_input(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                            [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                            [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                                        ],\n                                        value: 'A',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_analog_input, '0'],\n                                            [Lang.Blocks.hamsterlite_digital_input, '1'],\n                                            [Lang.Blocks.hamsterlite_servo_output, '8'],\n                                            [Lang.Blocks.hamsterlite_pwm_output, '9'],\n                                            [Lang.Blocks.hamsterlite_digital_output, '10'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '0'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_io_mode_digital_input(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                            [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                            [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                                        ],\n                                        value: 'A',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_analog_input, '0'],\n                                            [Lang.Blocks.hamsterlite_digital_input, '1'],\n                                            [Lang.Blocks.hamsterlite_servo_output, '8'],\n                                            [Lang.Blocks.hamsterlite_pwm_output, '9'],\n                                            [Lang.Blocks.hamsterlite_digital_output, '10'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '1'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_io_mode_servo_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                            [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                            [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                                        ],\n                                        value: 'A',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_analog_input, '0'],\n                                            [Lang.Blocks.hamsterlite_digital_input, '1'],\n                                            [Lang.Blocks.hamsterlite_servo_output, '8'],\n                                            [Lang.Blocks.hamsterlite_pwm_output, '9'],\n                                            [Lang.Blocks.hamsterlite_digital_output, '10'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '8'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_io_mode_pwm_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                            [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                            [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                                        ],\n                                        value: 'A',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_analog_input, '0'],\n                                            [Lang.Blocks.hamsterlite_digital_input, '1'],\n                                            [Lang.Blocks.hamsterlite_servo_output, '8'],\n                                            [Lang.Blocks.hamsterlite_pwm_output, '9'],\n                                            [Lang.Blocks.hamsterlite_digital_output, '10'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '9'],\n                            },\n                            {\n                                syntax: 'Hamsterlite.set_io_mode_digital_output(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                            [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                            [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                                        ],\n                                        value: 'A',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_analog_input, '0'],\n                                            [Lang.Blocks.hamsterlite_digital_input, '1'],\n                                            [Lang.Blocks.hamsterlite_servo_output, '8'],\n                                            [Lang.Blocks.hamsterlite_pwm_output, '9'],\n                                            [Lang.Blocks.hamsterlite_digital_output, '10'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                                params: [null, '10'],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_change_output_by: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                            ],\n                            value: 'A',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'text',\n                                params: ['10'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_change_output_by',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                    },\n                    class: 'hamsterlite_port',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.changeOutput(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.add_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                            [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                            [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                                        ],\n                                        value: 'A',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_set_output_to: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                            ],\n                            value: 'A',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'text',\n                                params: ['100'],\n                            },\n                            null,\n                        ],\n                        type: 'hamsterlite_set_output_to',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                    },\n                    class: 'hamsterlite_port',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.setOutput(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_output(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_port_a, 'A'],\n                                            [Lang.Blocks.hamsterlite_port_b, 'B'],\n                                            [Lang.Blocks.hamsterlite_port_ab, 'AB'],\n                                        ],\n                                        value: 'A',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_gripper: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.hamsterlite_open_gripper, 'OPEN'],\n                                [Lang.Blocks.hamsterlite_close_gripper, 'CLOSE'],\n                            ],\n                            value: 'OPEN',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'hamsterlite_gripper',\n                    },\n                    paramsKeyMap: {\n                        ACTION: 0,\n                    },\n                    class: 'hamsterlite_port',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.gripper(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.set_gripper(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.hamsterlite_open_gripper, 'OPEN'],\n                                            [Lang.Blocks.hamsterlite_close_gripper, 'CLOSE'],\n                                        ],\n                                        value: 'OPEN',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                hamsterlite_release_gripper: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'hamsterlite_release_gripper',\n                    },\n                    class: 'hamsterlite_port',\n                    isNotFor: ['HamsterLite'],\n                    func(sprite, script) {\n                        return Entry.HamsterLite.releaseGripper(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'Hamsterlite.release_gripper()',\n                            },\n                        ],\n                    },\n                },\n            };\n        }\n\n        toHex(number) {\n            var value = parseInt(number);\n            if (value < 0) value += 0x100;\n\n            value = value.toString(16).toUpperCase();\n            if (value.length > 1) return value;\n            else return '0' + value;\n        }\n\n        toHex2(number) {\n            var value = parseInt(number);\n            if (value < 0) value += 0x10000;\n\n            value = value.toString(16).toUpperCase();\n            var result = '';\n            for (var i = value.length; i < 4; ++i) {\n                result += '0';\n            }\n            return result + value;\n        }\n        toHex3(number) {\n            var value = parseInt(number);\n            if (value < 0) value += 0x1000000;\n\n            value = value.toString(16).toUpperCase();\n            var result = '';\n            for (var i = value.length; i < 6; ++i) {\n                result += '0';\n            }\n            return result + value;\n        }\n        colorToRgb(color) {\n            if (color > 7) color = 7;\n            else if (color < 0) color = 0;\n            return COLOR_TO_RGB[color];\n        }\n        speedToGain(speed) {\n            if (speed > 10) speed = 10;\n            else if (speed < 1) speed = 1;\n            switch (speed) {\n                case 1:\n                case 2:\n                    return 6;\n                case 3:\n                case 4:\n                    return 5;\n                case 5:\n                case 6:\n                    return 4;\n                case 7:\n                case 8:\n                    return 3;\n                case 9:\n                case 10:\n                    return 2;\n            }\n            return 2;\n        }\n\n        requestLocalData() {\n            var motoring = this.motoring;\n            var lineTracer = this.lineTracer;\n            if (this.isHamsterS) {\n                var str = '10';\n                if (motoring.leftWheel < 0) str += this.toHex(motoring.leftWheel * 1.14 - 0.5);\n                else str += this.toHex(motoring.leftWheel * 1.14 + 0.5);\n                if (motoring.rightWheel < 0) str += this.toHex(motoring.rightWheel * 1.14 - 0.5);\n                else str += this.toHex(motoring.rightWheel * 1.14 + 0.5);\n                var tmp = this.colorToRgb(motoring.leftLed);\n                str += this.toHex(tmp[0]);\n                str += this.toHex(tmp[1]);\n                str += this.toHex(tmp[2]);\n                tmp = this.colorToRgb(motoring.rightLed);\n                str += this.toHex(tmp[0]);\n                str += this.toHex(tmp[1]);\n                str += this.toHex(tmp[2]);\n                str += '000000';\n                tmp = motoring.lineTracerMode & 0x0f;\n                if (tmp > 7) tmp++;\n                if (lineTracer.written) {\n                    lineTracer.written = false;\n                    lineTracer.count = 0;\n                    if (tmp > 0) {\n                        lineTracer.flag = (lineTracer.flag % 15) + 1;\n                        lineTracer.event = 1;\n                    } else {\n                        lineTracer.event = 0;\n                    }\n                }\n                tmp |= (lineTracer.flag & 0x0f) << 4;\n                str += this.toHex(tmp);\n                tmp = (motoring.lineTracerSpeed & 0x0f) << 4;\n                tmp |= this.speedToGain(motoring.lineTracerSpeed) & 0x0f;\n                str += this.toHex(tmp);\n                tmp = (motoring.configProximity & 0x07) << 5;\n                tmp |= (motoring.configBandWidth & 0x07) << 2;\n                tmp |= motoring.configGravity & 0x03;\n                str += this.toHex(tmp);\n                tmp = (motoring.ioModeA & 0x0f) << 4;\n                tmp |= motoring.ioModeB & 0x0f;\n                str += this.toHex(tmp);\n                str += this.toHex(motoring.outputA);\n                str += this.toHex(motoring.outputB);\n                if (motoring.note > 0) {\n                    str += '01';\n                    str += this.toHex(motoring.note);\n                } else {\n                    str += this.toHex2(motoring.buzzer * 10 + 512);\n                }\n                str += '-';\n                str += this.address;\n                str += '\\r';\n                return str;\n            } else {\n                var str = this.toHex(motoring.topology & 0x0f);\n                str += '0010';\n                str += this.toHex(motoring.leftWheel);\n                str += this.toHex(motoring.rightWheel);\n                str += this.toHex(motoring.leftLed);\n                str += this.toHex(motoring.rightLed);\n                str += this.toHex3(motoring.buzzer * 100);\n                str += this.toHex(motoring.note);\n                if (lineTracer.written) {\n                    lineTracer.written = false;\n                    if (motoring.lineTracerMode > 0) {\n                        lineTracer.flag ^= 0x80;\n                        lineTracer.event = 1;\n                    }\n                }\n                var tmp = (motoring.lineTracerMode & 0x0f) << 3;\n                tmp |= (motoring.lineTracerSpeed - 1) & 0x07;\n                tmp |= lineTracer.flag & 0x80;\n                str += this.toHex(tmp);\n                str += this.toHex(motoring.configProximity);\n                tmp = (motoring.configGravity & 0x0f) << 4;\n                tmp |= motoring.configBandWidth & 0x0f;\n                str += this.toHex(tmp);\n                tmp = (motoring.ioModeA & 0x0f) << 4;\n                tmp |= motoring.ioModeB & 0x0f;\n                str += this.toHex(tmp);\n                str += this.toHex(motoring.outputA);\n                str += this.toHex(motoring.outputB);\n                str += '000000-';\n                str += this.address;\n                str += '\\r';\n                return str;\n            }\n        }\n\n        handleLocalData(data) {\n            // data: string\n            if (data?.length != 53) {\n                return;\n            }\n\n            if (this.isHamsterS) {\n                var str = data.slice(0, 1);\n                var value = parseInt(str, 16);\n                if (value != 1) return; // invalid data\n\n                var sensory = this.sensory;\n                // left proximity\n                str = data.slice(6, 8);\n                value = parseInt(str, 16);\n                sensory.leftProximity = value;\n                // right proximity\n                str = data.slice(8, 10);\n                value = parseInt(str, 16);\n                sensory.rightProximity = value;\n                str = data.slice(38, 40);\n                var value2 = parseInt(str, 16);\n                if ((value2 & 0x01) == 0) {\n                    // flag\n                    // light\n                    str = data.slice(10, 14);\n                    value = parseInt(str, 16);\n                    sensory.light = value;\n                } else {\n                    // temperature\n                    str = data.slice(10, 12);\n                    value = parseInt(str, 16);\n                    if (value > 0x7f) value -= 0x100;\n                    value = value / 2.0 + 23;\n                    value = value.toFixed(1);\n                    sensory.temperature = value;\n                }\n                // left floor\n                str = data.slice(14, 16);\n                value = parseInt(str, 16);\n                sensory.leftFloor = value;\n                // right floor\n                str = data.slice(16, 18);\n                value = parseInt(str, 16);\n                sensory.rightFloor = value;\n                // acceleration x\n                str = data.slice(18, 22);\n                value = parseInt(str, 16);\n                if (value > 0x7fff) value -= 0x10000;\n                sensory.accelerationX = value;\n                // acceleration y\n                str = data.slice(22, 26);\n                value = parseInt(str, 16);\n                if (value > 0x7fff) value -= 0x10000;\n                sensory.accelerationY = value;\n                // acceleration z\n                str = data.slice(26, 30);\n                value = parseInt(str, 16);\n                if (value > 0x7fff) value -= 0x10000;\n                sensory.accelerationZ = value;\n                // input a\n                str = data.slice(30, 32);\n                value = parseInt(str, 16);\n                sensory.inputA = value;\n                // input b\n                str = data.slice(32, 34);\n                value = parseInt(str, 16);\n                sensory.inputB = value;\n                // signal strength\n                str = data.slice(36, 38);\n                value = parseInt(str, 16);\n                value -= 0x100;\n                sensory.signalStrength = value;\n                value = (value2 >> 6) & 0x03;\n                if ((value & 0x02) != 0) {\n                    var lineTracer = this.lineTracer;\n                    if (lineTracer.event == 1) {\n                        if (value == 0x02) {\n                            if (++lineTracer.count > 5) lineTracer.event = 2;\n                        } else {\n                            lineTracer.event = 2;\n                        }\n                    }\n                    if (lineTracer.event == 2) {\n                        if (value != lineTracer.state || lineTracer.count > 5) {\n                            lineTracer.state = value;\n                            sensory.lineTracerState = value << 5;\n                            sensory.lineTracerStateId = (sensory.lineTracerStateId % 255) + 1;\n                            if (value == 0x02) {\n                                lineTracer.event = 0;\n                                lineTracer.count = 0;\n                            }\n                        }\n                    }\n                }\n                // battery state\n                value = (value2 >> 1) & 0x03;\n                if (value == 0) value = 2;\n                else if (value >= 2) value = 0;\n                var batt = this.battery;\n                if (value != batt.state) {\n                    batt.state = value;\n                    sensory.batteryState = value;\n                }\n            } else {\n                var str = data.slice(4, 5);\n                var value = parseInt(str, 16);\n                if (value != 1) return; // invalid data\n\n                var sensory = this.sensory;\n                // signal strength\n                str = data.slice(6, 8);\n                value = parseInt(str, 16);\n                value -= 0x100;\n                sensory.signalStrength = value;\n                // left proximity\n                str = data.slice(8, 10);\n                value = parseInt(str, 16);\n                sensory.leftProximity = value;\n                // right proximity\n                str = data.slice(10, 12);\n                value = parseInt(str, 16);\n                sensory.rightProximity = value;\n                // left floor\n                str = data.slice(12, 14);\n                value = parseInt(str, 16);\n                sensory.leftFloor = value;\n                // right floor\n                str = data.slice(14, 16);\n                value = parseInt(str, 16);\n                sensory.rightFloor = value;\n                // acceleration x\n                str = data.slice(16, 20);\n                value = parseInt(str, 16);\n                if (value > 0x7fff) value -= 0x10000;\n                sensory.accelerationX = value;\n                // acceleration y\n                str = data.slice(20, 24);\n                value = parseInt(str, 16);\n                if (value > 0x7fff) value -= 0x10000;\n                sensory.accelerationY = value;\n                // acceleration z\n                str = data.slice(24, 28);\n                value = parseInt(str, 16);\n                if (value > 0x7fff) value -= 0x10000;\n                sensory.accelerationZ = value;\n                // flag\n                str = data.slice(28, 30);\n                var flag = parseInt(str, 16);\n                if (flag == 0) {\n                    // light\n                    str = data.slice(30, 34);\n                    value = parseInt(str, 16);\n                    sensory.light = value;\n                } else {\n                    // temperature\n                    str = data.slice(30, 32);\n                    value = parseInt(str, 16);\n                    if (value > 0x7f) value -= 0x100;\n                    value = value / 2.0 + 24;\n                    value = value.toFixed(1);\n                    sensory.temperature = value;\n                    // battery\n                    str = data.slice(32, 34);\n                    value = parseInt(str, 16);\n                    value = value / 100.0 + 2;\n                    var batt = this.battery;\n                    if (batt.count < 10) {\n                        ++batt.count;\n                    } else {\n                        batt.index %= 10;\n                        batt.sum -= batt.data[batt.index];\n                    }\n                    batt.sum += value;\n                    batt.data[batt.index] = value;\n                    ++batt.index;\n                    value = batt.sum / batt.count;\n                    var state = 2;\n                    if (value < 3.0) state = 0;\n                    else if (value < 3.6) state = 1;\n                    if (state != batt.state) {\n                        batt.state = state;\n                        sensory.batteryState = state;\n                    }\n                }\n                // input a\n                str = data.slice(34, 36);\n                value = parseInt(str, 16);\n                sensory.inputA = value;\n                // input b\n                str = data.slice(36, 38);\n                value = parseInt(str, 16);\n                sensory.inputB = value;\n                // line tracer state\n                str = data.slice(38, 40);\n                value = parseInt(str, 16);\n                if ((value & 0x40) != 0) {\n                    var lineTracer = this.lineTracer;\n                    if (lineTracer.event == 1) {\n                        if (value != 0x40) {\n                            lineTracer.event = 2;\n                        }\n                    }\n                    if (lineTracer.event == 2) {\n                        if (value != lineTracer.state) {\n                            lineTracer.state = value;\n                            sensory.lineTracerState = value;\n                            sensory.lineTracerStateId = (sensory.lineTracerStateId % 255) + 1;\n                            if (value == 0x40) {\n                                lineTracer.event = 0;\n                            }\n                        }\n                    }\n                }\n            }\n            this.handleSensory();\n        }\n\n        requestInitialData() {\n            return 'FF\\r';\n        }\n\n        async initialHandshake() {\n            let status = false;\n            while (true) {\n                const { value: data, done } = await Entry.hwLite.serial.reader.read();\n                if (done) {\n                    return false;\n                }\n                if (data && data.slice(0, 2) == 'FF') {\n                    var info = data.split(/[,\\n]+/);\n                    if (info && info.length >= 5) {\n                        if (info[1] == 'Hamster' && info[2] == '04' && info[4].length >= 12) {\n                            this.id = '0204' + info[3];\n                            this.address = info[4].substring(0, 12);\n                            this.isHamsterS = false;\n                            status = true;\n                            break;\n                        } else if (info[2] == '0E' && info[4].length >= 12) {\n                            this.id = '0204' + info[3];\n                            this.address = info[4].substring(0, 12);\n                            this.isHamsterS = true;\n                            status = true;\n                            break;\n                        } else {\n                            break;\n                        }\n                    }\n                } else {\n                    Entry.hwLite.serial.sendAsciiAsBuffer(this.requestInitialData());\n                }\n            }\n            return status;\n        }\n    })();\n})();\n\nmodule.exports = Entry.HamsterLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_microbit2_lite.js",
    "content": "'use strict';\n\nconst _throttle = require('lodash/throttle');\n\nconst EVENT_INTERVAL = 150;\n\n(function () {\n    Entry.Microbit2lite = new (class Microbit2Lite {\n        constructor() {\n            this.commandStatus = {};\n            this.btnEventIntervalId = -1;\n            this.retryLimitCnt = 8;\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                connectionType: 'ascii',\n            };\n            this.duration = 64;\n            this.functionKeys = {\n                LOCALDATA: 'localdata',\n                GET_ANALOG: 'get-analog',\n                GET_DIGITAL: 'get-digital',\n                SET_ANALOG: 'set-analog',\n                SET_DIGITAL: 'set-digital',\n                SET_LED: 'set-pixel',\n                GET_LED: 'get-pixel',\n                RESET: 'reset',\n                PRESET_IMAGE: 'pre-image',\n                SET_CUSTOM_IMAGE: 'custom-image',\n                SET_STRING: 'print',\n                RESET_SCREEN: 'display-clear',\n                DISPLAY_ON: 'display-on',\n                DISPLAY_OFF: 'display-off',\n                SPEAKER_ON: 'speaker-on',\n                SPEAKER_OFF: 'speaker-off',\n                PLAY_TONE: 'play-tone',\n                PLAY_SOUND: 'pre-sound',\n                PLAY_MELODY: 'pre-melody',\n                GET_BTN: 'get-btn',\n                CHANGE_TEMPO: 'change-tempo',\n                GET_LOGO: 'get-touch',\n                GET_ACC: 'get-acc',\n                GET_GESTURE: 'get-gesture',\n                GET_DIRECTION: 'direction',\n                GET_FIELD_STRENGTH: 'field-strength',\n                GET_FIELD_STRENGTH_AXIS: 'field-axis-strength',\n                GET_LIGHT_LEVEL: 'light-level',\n                GET_TEMPERATURE: 'temperature',\n                GET_SOUND_LEVEL: 'sound-level',\n                SET_RADIO: 'radio-send',\n                GET_RADIO: 'radio-receive',\n                RADIO_ON: 'radio-on',\n                RADIO_OFF: 'radio-off',\n                SETTING_RADIO: 'radio-setting',\n                SET_SERVO_MILLI: 'write-period',\n                SET_SERVO_MICRO: 'write-micro-period',\n                SET_SERVO_ANGLE: 'servo-write',\n            };\n\n            this.presetImage = [\n                // Image.HEART\n                '09090:99999:99999:09990:00900',\n                // Image.HEART_SMALL,\n                '00000:09090:09990:00900:00000',\n                // Image.HAPPY,\n                '00000:09090:00000:90009:09990',\n                // Image.SMILE,\n                '00000:00000:00000:90009:09990',\n                // Image.SAD,\n                '00000:09090:00000:09990:90009',\n                // Image.CONFUSED,\n                '00000:09090:00000:09090:90909',\n                // Image.ANGRY,\n                '90009:09090:00000:99999:90909',\n                // Image.ASLEEP,\n                '00000:99099:00000:09990:00000',\n                // Image.SURPRISED,\n                '09090:00000:00900:09090:00900',\n                // Image.SILLY,\n                '90009:00000:99999:00909:00999',\n                // Image.FABULOUS,\n                '99999:99099:00000:09090:09990',\n                // Image.MEH,\n                '09090:00000:00090:00900:09000',\n                // Image.YES,\n                '00000:00009:00090:90900:09000',\n                // Image.NO,\n                '90009:09090:00900:09090:90009',\n                // Image.CLOCK1,\n                '00090:00090:00900:00000:00000',\n                // Image.CLOCK2,\n                '00000:00990:00900:00000:00000',\n                // Image.CLOCK3,\n                '00000:00000:00999:00000:00000',\n                // Image.CLOCK4,\n                '00000:00000:00900:00990:00000',\n                // Image.CLOCK5,\n                '00000:00000:00900:00090:00090',\n                // Image.CLOCK6,\n                '00000:00000:00900:00900:00900',\n                // Image.CLOCK7,\n                '00000:00000:00900:09000:09000',\n                // Image.CLOCK8,\n                '00000:00000:00900:99000:00000',\n                // Image.CLOCK9,\n                '00000:00000:99900:00000:00000',\n                // Image.CLOCK10,\n                '00000:09900:00900:00000:00000',\n                // Image.CLOCK11,\n                '09000:09000:00900:00000:00000',\n                // Image.CLOCK12,\n                '00900:00900:00900:00000:00000',\n                // Image.ARROW_N,\n                '00900:09990:90909:00900:00900',\n                // Image.ARROW_NE,\n                '00999:00099:00909:09000:90000',\n                // Image.ARROW_E,\n                '00900:00090:99999:00090:00900',\n                // Image.ARROW_SE,\n                '90000:09000:00909:00099:00999',\n                // Image.ARROW_S,\n                '00900:00900:90909:09990:00900',\n                // Image.ARROW_SW,\n                '00009:00090:90900:99000:99900',\n                // Image.ARROW_W,\n                '00900:09000:99999:09000:00900',\n                // Image.ARROW_NW,\n                '99900:99000:90900:00090:00009',\n                // Image.TRIANGLE,\n                '00000:00900:09090:99999:00000',\n                // Image.TRIANGLE_LEFT,\n                '90000:99000:90900:90090:99999',\n                // Image.CHESSBOARD,\n                '09090:90909:09090:90909:09090',\n                // Image.DIAMOND,\n                '00900:09090:90009:09090:00900',\n                // Image.DIAMOND_SMALL,\n                '00000:00900:09090:00900:00000',\n                // Image.SQUARE,\n                '99999:90009:90009:90009:99999',\n                // Image.SQUARE_SMALL,\n                '00000:09990:09090:09990:00000',\n                // Image.RABBIT,\n                '90900:90900:99990:99090:99990',\n                // Image.COW,\n                '90009:90009:99999:09990:00900',\n                // Image.MUSIC_CROTCHET,\n                '00900:00900:00900:99900:99900',\n                // Image.MUSIC_QUAVER,\n                '00900:00990:00909:99900:99900',\n                // Image.MUSIC_QUAVERS,\n                '09999:09009:09009:99099:99099',\n                // Image.PITCHFORK,\n                '90909:90909:99999:00900:00900',\n                // Image.XMAS,\n                '00900:09990:00900:09990:99999',\n                // Image.PACMAN,\n                '099999:99090:99900:99990:09999',\n                // Image.TARGET,\n                '00900:09990:99099:09990:00900',\n                // Image.TSHIRT,\n                '99099:99999:09990:09990:09990',\n                // Image.ROLLERSKATE,\n                '00099:00099:99999:99999:09090',\n                // Image.DUCK,\n                '00990:99900:09999:09990:00000',\n                // Image.HOUSE,\n                '00900:09990:99999:09990:09090',\n                // Image.TORTOISE,\n                '00000:09990:99999:09090:00000',\n                // Image.BUTTERFLY,\n                '99099:99999:00900:99999:99099',\n                // Image.STICKFIGURE,\n                '00900:99999:00900:09090:90009',\n                // Image.GHOST,\n                '99999:90909:99999:99999:90909',\n                // Image.SWORD,\n                '00900:00900:00900:09990:00900',\n                // Image.GIRAFFE,\n                '99000:09000:09000:09990:09090',\n                // Image.SKULL,\n                '09990:90909:99999:09990:09990',\n                // Image.UMBRELLA,\n                '09990:99999:00900:90900:09900',\n                // Image.SNAKE,\n                '99000:99099:09090:09990:00000',\n            ];\n            this.id = '220301';\n            this.url = 'http://microbit.org/ko/';\n            this.imageName = 'microbit2lite.png';\n            this.supportFirmwareFlash = true;\n            this.title = {\n                en: 'Microbit V2',\n                ko: '마이크로비트 V2',\n            };\n            this.name = 'Microbit2lite';\n            this.digitalPins = [\n                ['P8', 8],\n                ['P9', 9],\n                ['P12', 12],\n                ['P13', 13],\n                ['P14', 14],\n                ['P15', 15],\n                ['P16', 16],\n            ];\n            this.analogPins = [\n                ['P0', 0],\n                ['P1', 1],\n                ['P2', 2],\n                ['P3', 3],\n                ['P4', 4],\n                ['P10', 10],\n            ];\n            this.majorPins = [\n                ['P0', 0],\n                ['P1', 1],\n                ['P2', 2],\n            ];\n            this.ledRows = [\n                [0, 0],\n                [1, 1],\n                [2, 2],\n                [3, 3],\n                [4, 4],\n            ];\n            this.defaultLed = [\n                [0, 0, 0, 0, 0],\n                [0, 9, 0, 9, 0],\n                [0, 0, 0, 0, 0],\n                [9, 0, 0, 0, 9],\n                [0, 9, 9, 9, 0],\n            ];\n            this.blockMenuBlocks = [\n                'microbit2lite_common_title',\n                'microbit2lite_get_analog',\n                'microbit2lite_set_analog',\n                'microbit2lite_get_digital',\n                'microbit2lite_set_digital',\n                'microbit2lite_screen_toggle',\n                'microbit2lite_set_led',\n                'microbit2lite_get_led',\n                'microbit2lite_show_custom_image',\n                'microbit2lite_show_string',\n                'microbit2lite_show_preset_image',\n                'microbit2lite_reset_screen',\n                'microbit2lite_radio_toggle',\n                'microbit2lite_radio_setting',\n                'microbit2lite_radio_send',\n                'microbit2lite_radio_received',\n                'microbit2lite_change_tempo',\n                'microbit2lite_set_tone',\n                'microbit2lite_play_preset_music',\n                'microbit2lite_get_btn',\n                'microbit2lite_get_acc',\n                'microbit2lite_get_gesture',\n                'microbit2lite_get_direction',\n                'microbit2lite_get_field_strength_axis',\n                'microbit2lite_get_light_level',\n                'microbit2lite_get_temperature',\n                'microbit2lite_set_servo',\n                'microbit2lite_set_pwm',\n                'microbit2lite_v2_title',\n                'microbit2lite_get_logo',\n                'microbit2lite_btn_event',\n                'microbit2lite_speaker_toggle',\n                'microbit2lite_play_sound_effect',\n                'microbit2lite_get_sound_level',\n            ];\n            this.version = '2';\n            this.firePressedBtnEventWithThrottle = _throttle(\n                (pressedBtn) => {\n                    Entry.engine.fireEventWithValue('microbit2lite_btn_pressed', pressedBtn);\n                },\n                EVENT_INTERVAL,\n                { leading: true, trailing: false }\n            );\n        }\n        _clamp(value, min, max) {\n            if (value < min) {\n                return min;\n            } else if (value > max) {\n                return max;\n            }\n            return value;\n        }\n        setZero() {\n            this.commandStatus = {};\n            return Entry.hwLite.serial.sendAsyncWithThrottle(this.functionKeys.RESET);\n        }\n\n        async initialHandshake() {\n            const defaultCMD = `${this.functionKeys.LOCALDATA}`;\n            const response = await Entry.hwLite.serial.sendAsyncWithThrottle(defaultCMD);\n            if (response && response.indexOf('localdata') > -1) {\n                const version = response.split(';')[1];\n                if (!version) {\n                    return;\n                }\n                const major = version[0];\n                if (this.version !== major) {\n                    this.version = major;\n                }\n            }\n\n            if (this.version === '2') {\n                Entry.addEventListener('run', this.handleBtnEventInterval.bind(this));\n                Entry.addEventListener('beforeStop', () => {\n                    clearInterval(this.btnEventIntervalId);\n                });\n            }\n\n            return response;\n        }\n\n        handleBtnEventInterval() {\n            this.btnEventIntervalId = setInterval(\n                this.listenBtnPressedEvent.bind(this),\n                this.duration\n            );\n        }\n\n        async listenBtnPressedEvent() {\n            if (Object.keys(this.commandStatus).length > 0) {\n                return;\n            }\n\n            const defaultCMD = `${this.functionKeys.LOCALDATA};`;\n            const response = await Entry.hwLite.serial.sendAsyncWithThrottle(defaultCMD);\n            // const response = await this.getResponseWithSync(defaultCMD);\n\n            // INFO: A,B 버튼이벤트 관련 로직\n            const pressedBtn = response.split(':btn:')[1];\n            if (pressedBtn) {\n                this.firePressedBtnEventWithThrottle(pressedBtn);\n            }\n        }\n\n        waitMilliSec(milli) {\n            this.blockReq = true;\n            setTimeout(() => {\n                this.blockReq = false;\n            }, milli);\n        }\n\n        generateCodeId(entityId, type, payload) {\n            return `${entityId}-${type}${payload ? `-${payload}` : ''}`;\n        }\n\n        getCommandType(command) {\n            if (typeof command === 'string' && command.indexOf(';') > -1) {\n                return command.split(';')[0];\n            } else {\n                console.error(\"Error: microbit's response is not variable, \", command);\n                Entry.hwLite.serial.handleConnectErrorInEngineRun();\n            }\n        }\n\n        getResponse(response) {\n            if (\n                typeof response === 'string' &&\n                response.indexOf(';') > -1 &&\n                response.indexOf('ValueError') <= -1\n            ) {\n                return response.split(';')[1];\n            } else if (response === 'command removed') {\n                console.log(\"Microbit's command removed. Too many requests\");\n            } else {\n                console.error(\"Error: microbit's response is not variable, \", response);\n                Entry.hwLite.serial.handleConnectErrorInEngineRun();\n            }\n        }\n\n        async getResponseWithSync(command) {\n            if (!Entry.engine.isState('run')) {\n                return;\n            }\n            const result = await Entry.hwLite.serial.sendAsyncWithThrottle(command);\n            if (\n                (!result || this.getCommandType(command) !== this.getCommandType(result)) &&\n                // INFO : localdata 명령어는 우선순위가 낮으므로 반복하지 않음\n                command !== `${this.functionKeys.LOCALDATA};`\n            ) {\n                if (!this.commandStatus[command]) {\n                    this.commandStatus[command] = 1;\n                    throw new Entry.Utils.AsyncError();\n                } else if (this.commandStatus[command] <= this.retryLimitCnt) {\n                    this.commandStatus[command]++;\n                    throw new Entry.Utils.AsyncError();\n                } else if (this.commandStatus[command] > this.retryLimitCnt) {\n                    delete this.commandStatus[command];\n                    return 'command removed';\n                } else {\n                    console.error('UnExpected Microbit command');\n                }\n            } else {\n                delete this.commandStatus[command];\n            }\n\n            return result;\n        }\n\n        // 언어 적용\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        microbit2lite_get_analog: '핀 %1 번 아날로그 값',\n                        microbit2lite_set_analog: '핀 %1 에 아날로그 값 %2 를 출력하기 %3',\n                        microbit2lite_get_digital: '핀 %1 번 디지털 값',\n                        microbit2lite_set_digital: '핀 %1 에 디지털 값 %2 를 출력하기 %3',\n                        microbit2lite_screen_toggle: 'LED 기능 %1 %2',\n                        microbit2lite_set_led: 'LED의 X: %1 Y: %2 를 밝기 %3 (으)로 밝히기 %4',\n                        microbit2lite_get_led: 'LED의 X: %1 Y: %2 밝기 값',\n                        microbit2lite_show_preset_image: 'LED에 %1 모양 나타내기 %2',\n                        microbit2lite_show_custom_image: 'LED %1 밝히기 %2',\n                        microbit2lite_show_string: 'LED에 %1 을(를) 나타내기 %2',\n                        microbit2lite_reset_screen: 'LED 모두 %1 %2',\n                        microbit2lite_radio_toggle: '라디오 기능 %1 %2',\n                        microbit2lite_radio_setting: '라디오 채널을 %1 (으)로 바꾸기 %2',\n                        microbit2lite_radio_send: '라디오로 %1 송신하기 %2',\n                        microbit2lite_radio_received: '라디오 수신 값',\n                        microbit2lite_speaker_toggle: '스피커 기능 %1 %2',\n                        microbit2lite_change_tempo: '연주 속도를 %1 박에 %2 BPM으로 정하기 %3',\n                        microbit2lite_set_tone: '%1 음을 %2 박만큼 연주하기 %3',\n                        microbit2lite_play_preset_music: '%1 음악을 연주하기 %2',\n                        microbit2lite_play_sound_effect: '%1 효과음을 연주하기 %2',\n                        microbit2lite_get_btn: '%1 버튼이 눌렸는가?',\n                        microbit2lite_get_logo: '로고를 터치했는가?',\n                        microbit2lite_get_gesture: '움직임이 %1 인가?',\n                        microbit2lite_get_acc: '%1 의 가속도',\n                        microbit2lite_btn_event: '%1 %2 버튼을 눌렀을 때',\n                        microbit2lite_get_direction: '나침반 방향',\n                        microbit2lite_get_field_strength_axis: '%1 의 자기장 세기 값',\n                        microbit2lite_get_light_level: '빛 센서 값',\n                        microbit2lite_get_temperature: '온도',\n                        microbit2lite_get_sound_level: '마이크 소리 크기',\n                        microbit2lite_set_servo: '핀 %1 에 서보 모터 각도를 %2 로 정하기 %3',\n                        microbit2lite_set_pwm: '핀 %1 에 서보 펄스 폭을 %2 %3초로 정하기 %4',\n                        microbit2lite_common_title: '마이크로비트 공통',\n                        microbit2lite_v2_title: '마이크로비트 V2 전용',\n                    },\n                    Blocks: {\n                        octave: '옥타브',\n                        scalar: '스칼라',\n                        xAxis: 'X축',\n                        yAxis: 'Y축',\n                        zAxis: 'Z축',\n                        up: '위',\n                        down: '아래',\n                        left: '왼쪽',\n                        right: '오른쪽',\n                        face_up: '앞면',\n                        face_down: '뒷면',\n                        freefall: '자유 낙하',\n                        '3g': '3G',\n                        '6g': '6G',\n                        '8g': '8G',\n                        shake: '흔들림',\n                        DADADADUM: '운명 교향곡',\n                        ENTERTAINER: '엔터테이너',\n                        PRELUDE: '바흐 프렐류드 1번',\n                        ODE: '합창 교향곡',\n                        NYAN: '냥캣',\n                        RINGTONE: '벨소리',\n                        FUNK: '펑크',\n                        BLUES: '블루스',\n                        BIRTHDAY: '생일 축하합니다',\n                        WEDDING: '결혼 행진곡',\n                        FUNERAL: '장례식 노래',\n                        PUNCHLINE: '펀치라인',\n                        PYTHON: '서커스',\n                        BADDY: '악당',\n                        CHASE: '추격전',\n                        BA_DING: '동전 GET',\n                        WAWAWAWAA: '실망',\n                        JUMP_UP: '위로 점프',\n                        JUMP_DOWN: '아래로 점프',\n                        POWER_UP: '켜기',\n                        POWER_DOWN: '끄기',\n                        GIGGLE: '웃음',\n                        HAPPY: '행복',\n                        HELLO: '인사',\n                        MYSTERIOUS: '신비로움',\n                        SAD: '슬픔',\n                        SLIDE: '슬라이드',\n                        SOARING: '상승',\n                        SPRING: '봄',\n                        TWINKLE: '반짝반짝',\n                        YAWN: '하품',\n                        plot: '켜기',\n                        unplot: '끄기',\n                        on: '켜기',\n                        off: '끄기',\n                        remove: '지우기',\n                        light: '밝히기',\n                        microbit_2_HEART: '하트',\n                        microbit_2_HEART_SMALL: '작은 하트',\n                        microbit_2_HAPPY: '행복',\n                        microbit_2_SMILE: '웃음',\n                        microbit_2_SAD: '슬픔',\n                        microbit_2_CONFUSED: '혼란',\n                        microbit_2_ANGRY: '화남',\n                        microbit_2_ASLEEP: '졸림',\n                        microbit_2_SURPRISED: '놀람',\n                        microbit_2_SILLY: '메롱',\n                        microbit_2_FABULOUS: '환상적인',\n                        microbit_2_MEH: '별로',\n                        microbit_2_YES: '예스',\n                        microbit_2_NO: '노',\n                        microbit_2_TRIANGLE: '삼각형',\n                        microbit_2_TRIANGLE_LEFT: '왼쪽 삼각형',\n                        microbit_2_CHESSBOARD: '체스판',\n                        microbit_2_DIAMOND: '다이아몬드',\n                        microbit_2_DIAMOND_SMALL: '작은 다이아몬드',\n                        microbit_2_SQUARE: '사각형',\n                        microbit_2_SQUARE_SMALL: '작은 사각형',\n                        microbit_2_RABBIT: '토끼',\n                        microbit_2_COW: '소',\n                        microbit_2_MUSIC_CROTCHET: '4분음표',\n                        microbit_2_MUSIC_QUAVER: '8분음표',\n                        microbit_2_MUSIC_QUAVERS: '8분음표 2개',\n                        microbit_2_PITCHFORK: '쇠스랑',\n                        microbit_2_XMAS: '크리스마스 트리',\n                        microbit_2_PACMAN: '팩맨',\n                        microbit_2_TARGET: '표적',\n                        microbit_2_TSHIRT: '티셔츠',\n                        microbit_2_ROLLERSKATE: '롤러스케이트',\n                        microbit_2_DUCK: '오리',\n                        microbit_2_HOUSE: '집',\n                        microbit_2_TORTOISE: '거북이',\n                        microbit_2_BUTTERFLY: '나비',\n                        microbit_2_STICKFIGURE: '스틱맨',\n                        microbit_2_GHOST: '유령',\n                        microbit_2_SWORD: '칼',\n                        microbit_2_GIRAFFE: '기린',\n                        microbit_2_SKULL: '해골',\n                        microbit_2_UMBRELLA: '우산',\n                        microbit_2_SNAKE: '뱀',\n                        microbit_2_CLOCK1: '1시',\n                        microbit_2_CLOCK2: '2시',\n                        microbit_2_CLOCK3: '3시',\n                        microbit_2_CLOCK4: '4시',\n                        microbit_2_CLOCK5: '5시',\n                        microbit_2_CLOCK6: '6시',\n                        microbit_2_CLOCK7: '7시',\n                        microbit_2_CLOCK8: '8시',\n                        microbit_2_CLOCK9: '9시',\n                        microbit_2_CLOCK10: '10시',\n                        microbit_2_CLOCK11: '11시',\n                        microbit_2_CLOCK12: '12시',\n                        microbit_2_ARROW_N: '북쪽',\n                        microbit_2_ARROW_NE: '북동쪽',\n                        microbit_2_ARROW_E: '동쪽',\n                        microbit_2_ARROW_SE: '남동쪽',\n                        microbit_2_ARROW_S: '남쪽',\n                        microbit_2_ARROW_SW: '남서쪽',\n                        microbit_2_ARROW_W: '서쪽',\n                        microbit_2_ARROW_NW: '북서쪽',\n                    },\n                    Helper: {\n                        microbit2lite_get_analog: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)',\n                        microbit2lite_set_analog:\n                            '선택한 핀에 입력한 아날로그 값을 출력합니다. (0 ~ 1023)',\n                        microbit2lite_get_digital: '선택한 핀의 디지털 값입니다. (0, 1)',\n                        microbit2lite_set_digital:\n                            '선택한 핀에 입력한 디지털 값을 출력합니다. (0, 1)',\n                        microbit2lite_screen_toggle: 'LED 기능을 켜거나 끕니다.',\n                        microbit2lite_set_led: 'X, Y 좌표로 선택한 LED를 선택한 밝기로 켭니다.',\n                        microbit2lite_get_led: 'X, Y 좌표로 선택한 LED의 밝기 값입니다.',\n                        microbit2lite_show_preset_image:\n                            'LED에 미리 설정되어 있는 모양을 나타냅니다.',\n                        microbit2lite_show_custom_image:\n                            '블록에서 선택한 LED를 선택한 밝기로 밝힙니다. 한 번에 모든 LED를 조작할 수 있습니다.',\n                        microbit2lite_show_string: '입력한 문자열을 LED에 차례대로 밝힙니다.',\n                        microbit2lite_reset_screen: 'LED를 모두 지우거나 밝힙니다.',\n                        microbit2lite_radio_toggle: '라디오 기능을 켜거나 끕니다.',\n                        microbit2lite_radio_setting: '라디오 채널을 입력한 숫자로 바꿉니다.',\n                        microbit2lite_radio_send: '라디오로 입력한 영문과 숫자를 송신합니다.',\n                        microbit2lite_radio_received: '라디오로 수신된 값입니다.',\n                        microbit2lite_speaker_toggle: '스피커 기능을 켜거나 끕니다.',\n                        microbit2lite_change_tempo: '연주 속도를 선택한 박자와 BPM으로 정합니다.',\n                        microbit2lite_set_tone:\n                            '선택한 음을 선택한 박만큼 연주합니다. 1~5옥타브 사이의 음계를 선택할 수 있습니다.',\n                        microbit2lite_play_preset_music: '미리 설정되어 있는 음악을 연주합니다.',\n                        microbit2lite_play_sound_effect: '미리 설정되어 있는 효과음을 연주합니다.',\n                        microbit2lite_get_btn: \"선택한 버튼이 눌렸다면 '참'으로 판단합니다.\",\n                        microbit2lite_get_logo: \"로고를 터치했다면 '참'으로 판단합니다.\",\n                        microbit2lite_get_gesture: \"선택한 움직임이 감지되면 '참'으로 판단합니다.\",\n                        microbit2lite_get_acc:\n                            '선택한 버튼이 눌리면 아래에 연결된 블록들을 실행합니다.',\n                        microbit2lite_btn_event: '%1 %2 버튼을 눌렀을 때',\n                        microbit2lite_get_direction: '나침반 방향 값입니다. (0~360) ',\n                        microbit2lite_get_field_strength_axis: '선택한 축의 자기장 세기 값입니다.',\n                        microbit2lite_get_light_level: '빛 센서의 값입니다.',\n                        microbit2lite_get_temperature: '현재 온도 값입니다. (℃)',\n                        microbit2lite_get_sound_level: '마이크 소리 크기 값입니다.',\n                        microbit2lite_set_servo:\n                            '선택한 핀에 서보 모터 각도를 입력한 값으로 정합니다.',\n                        microbit2lite_set_pwm:\n                            '선택한 핀의 서보 펄스폭을 선택한 시간으로 정합니다.',\n                    },\n                    Msgs: {\n                        microbit2lite_compatible_error:\n                            '마이크로비트 V2에서만 사용할 수 있는 블록입니다.',\n                        microbit2lite_octave: '옥타브',\n                    },\n                },\n                en: {\n                    template: {\n                        microbit2lite_get_analog: 'analog read pin %1',\n                        microbit2lite_set_analog: 'Set analog pin %1 to %2 %3',\n                        microbit2lite_get_digital: 'digital read pin %1',\n                        microbit2lite_set_digital: 'digital write pin %1 to %2 %3',\n                        microbit2lite_screen_toggle: '%1 LED screen %2',\n                        microbit2lite_set_led: 'Light X: %1 Y:%2 LED to brightness %3 %4',\n                        microbit2lite_get_led: 'brightness of X: %1 Y: %2 LED %3',\n                        microbit2lite_show_preset_image: 'Light %1 icon on LED %2',\n                        microbit2lite_show_custom_image: 'Light %1 on LED %2',\n                        microbit2lite_show_string: 'Light string %1 on LED %2',\n                        microbit2lite_reset_screen: '%1 all on LED %2',\n                        microbit2lite_radio_toggle: '%1 radio %2',\n                        microbit2lite_radio_setting: 'Change radio channel to %1 %2',\n                        microbit2lite_radio_send: 'Send %1 to radio %2',\n                        microbit2lite_radio_received: 'radio received value',\n                        microbit2lite_speaker_toggle: '%1 speaker %2',\n                        microbit2lite_change_tempo: 'Set tempo to %2 BPM per %1 beat %3',\n                        microbit2lite_set_tone: 'Play melody %1 for %2 beat %3',\n                        microbit2lite_play_preset_music: 'Play music %1 %2',\n                        microbit2lite_play_sound_effect: 'Play sound %1 %2',\n                        microbit2lite_get_btn: '%1 button pressed?',\n                        microbit2lite_get_logo: 'logo touched?',\n                        microbit2lite_get_gesture: 'Is the movement %1?',\n                        microbit2lite_get_acc: 'acceleration value of %1',\n                        microbit2lite_btn_event: '%1 When %2 button pressed',\n                        microbit2lite_get_direction: 'compass direction',\n                        microbit2lite_get_field_strength_axis:\n                            'magnetic field strength value of %1 ',\n                        microbit2lite_get_light_level: 'light sensor value',\n                        microbit2lite_get_temperature: 'temperature',\n                        microbit2lite_get_sound_level: 'microphone volume',\n                        microbit2lite_set_servo: 'Set servo pin %1 angle to %2 %3',\n                        microbit2lite_set_pwm: 'set servo pin %1 pulse to %2 %3 %4',\n                        microbit2lite_common_title: 'Common Blocks',\n                        microbit2lite_v2_title: 'v2 Only',\n                    },\n                    Blocks: {\n                        octave: 'octave',\n                        scalar: 'scalar',\n                        xAxis: 'X-axis',\n                        yAxis: 'Y-axis',\n                        zAxis: 'Z-axis',\n                        up: 'up',\n                        down: 'down',\n                        left: 'left',\n                        right: 'right',\n                        face_up: 'face up',\n                        face_down: 'face down',\n                        freefall: 'freefall',\n                        '3g': '3G',\n                        '6g': '6G',\n                        '8g': '8G',\n                        shake: 'shake',\n                        DADADADUM: 'Dadadadum',\n                        ENTERTAINER: 'Entertainer',\n                        PRELUDE: 'Prelude',\n                        ODE: 'Ode',\n                        NYAN: 'Nyan',\n                        RINGTONE: 'Ringtone',\n                        FUNK: 'Funk',\n                        BLUES: 'Blues',\n                        BIRTHDAY: 'Birthday',\n                        WEDDING: 'Wedding',\n                        FUNERAL: 'Funeral',\n                        PUNCHLINE: 'Punchline',\n                        PYTHON: 'Python',\n                        BADDY: 'Baddy',\n                        CHASE: 'Chase',\n                        BA_DING: 'Coin',\n                        WAWAWAWAA: 'Wawawawaa',\n                        JUMP_UP: 'Jump up',\n                        JUMP_DOWN: 'Jump down',\n                        POWER_UP: 'Power up',\n                        POWER_DOWN: 'Power down',\n                        GIGGLE: 'giggle',\n                        HAPPY: 'happy',\n                        HELLO: 'hello',\n                        MYSTERIOUS: 'mysterious',\n                        SAD: 'sad',\n                        SLIDE: 'slide',\n                        SOARING: 'soaring',\n                        SPRING: 'spring',\n                        TWINKLE: 'twinkle',\n                        YAWN: 'yawn',\n                        plot: 'plot',\n                        unplot: 'unplot',\n                        on: 'Turn on',\n                        off: 'Turn off',\n                        remove: 'Clear',\n                        light: 'Light',\n                        microbit_2_HEART: 'heart',\n                        microbit_2_HEART_SMALL: 'small heart',\n                        microbit_2_HAPPY: 'happy',\n                        microbit_2_SMILE: 'smile',\n                        microbit_2_SAD: 'sad',\n                        microbit_2_CONFUSED: 'confused',\n                        microbit_2_ANGRY: 'angry',\n                        microbit_2_ASLEEP: 'asleep',\n                        microbit_2_SURPRISED: 'surprised',\n                        microbit_2_SILLY: 'silly',\n                        microbit_2_FABULOUS: 'fabulous',\n                        microbit_2_MEH: 'meh',\n                        microbit_2_YES: 'yes',\n                        microbit_2_NO: 'no',\n                        microbit_2_TRIANGLE: 'triangle',\n                        microbit_2_TRIANGLE_LEFT: 'left triangle',\n                        microbit_2_CHESSBOARD: 'chessboard',\n                        microbit_2_DIAMOND: 'diamond',\n                        microbit_2_DIAMOND_SMALL: 'small diamond',\n                        microbit_2_SQUARE: 'square',\n                        microbit_2_SQUARE_SMALL: 'small square',\n                        microbit_2_RABBIT: 'rabbit',\n                        microbit_2_COW: 'cow',\n                        microbit_2_MUSIC_CROTCHET: 'crotchet',\n                        microbit_2_MUSIC_QUAVER: 'quaver',\n                        microbit_2_MUSIC_QUAVERS: 'quavers',\n                        microbit_2_PITCHFORK: 'pitchfork',\n                        microbit_2_XMAS: 'xmas',\n                        microbit_2_PACMAN: 'pacman',\n                        microbit_2_TARGET: 'target',\n                        microbit_2_TSHIRT: 'tshirt',\n                        microbit_2_ROLLERSKATE: 'rollerskate',\n                        microbit_2_DUCK: 'duck',\n                        microbit_2_HOUSE: 'house',\n                        microbit_2_TORTOISE: 'tortoise',\n                        microbit_2_BUTTERFLY: 'butterfly',\n                        microbit_2_STICKFIGURE: 'stickfigure',\n                        microbit_2_GHOST: 'ghost',\n                        microbit_2_SWORD: 'sword',\n                        microbit_2_GIRAFFE: 'giraffe',\n                        microbit_2_SKULL: 'skull',\n                        microbit_2_UMBRELLA: 'umbrella',\n                        microbit_2_SNAKE: 'snake',\n                        microbit_2_CLOCK1: \"1 o'clock\",\n                        microbit_2_CLOCK2: \"2 o'clock\",\n                        microbit_2_CLOCK3: \"3 o'clock\",\n                        microbit_2_CLOCK4: \"4 o'clock\",\n                        microbit_2_CLOCK5: \"5 o'clock\",\n                        microbit_2_CLOCK6: \"6 o'clock\",\n                        microbit_2_CLOCK7: \"7 o'clock\",\n                        microbit_2_CLOCK8: \"8 o'clock\",\n                        microbit_2_CLOCK9: \"9 o'clock\",\n                        microbit_2_CLOCK10: \"10 o'clock\",\n                        microbit_2_CLOCK11: \"11 o'clock\",\n                        microbit_2_CLOCK12: \"12 o'clock\",\n                        microbit_2_ARROW_N: 'north',\n                        microbit_2_ARROW_NE: 'northeast',\n                        microbit_2_ARROW_E: 'east',\n                        microbit_2_ARROW_SE: 'southeast',\n                        microbit_2_ARROW_S: 'south',\n                        microbit_2_ARROW_SW: 'southwest',\n                        microbit_2_ARROW_W: 'west',\n                        microbit_2_ARROW_NW: 'northwest',\n                    },\n                    Helper: {\n                        microbit2lite_get_analog:\n                            'Reads an analog signal from the pin you choose. (0 ~ 1023)',\n                        microbit2lite_set_analog:\n                            'Writes an analog signal to the pin you choose. (0 ~ 1023)',\n                        microbit2lite_get_digital:\n                            'Reads a digital signal from the pin you choose. (0 ~ 1023)',\n                        microbit2lite_set_digital:\n                            'Writes a digital signal to the pin you choose. (0 ~ 1)',\n                        microbit2lite_screen_toggle: 'Turns on or turns off the LED screen.',\n                        microbit2lite_set_led:\n                            'Lights the selected LED with X and Y coordinates to the selected brightness.',\n                        microbit2lite_get_led:\n                            'Brightness of the selected LED with X and Y coordinates',\n                        microbit2lite_show_preset_image:\n                            'Lights the selected icon on the LED screen.',\n                        microbit2lite_show_custom_image:\n                            'Lights the selected LED and brightness. You can set all the LEDs at once.',\n                        microbit2lite_show_string:\n                            'Lights the entered string in order on the LED screen.',\n                        microbit2lite_reset_screen: 'Clears or lights all LED screen.',\n                        microbit2lite_radio_toggle: 'Turns on or turns off the radio.',\n                        microbit2lite_radio_setting:\n                            'Changes the radio channel to the number entered.',\n                        microbit2lite_radio_send:\n                            'Sends the number or the string entered to the radio.',\n                        microbit2lite_radio_received: 'Value received by the radio.',\n                        microbit2lite_speaker_toggle: 'Turns on or turns off the speaker.',\n                        microbit2lite_change_tempo: 'Sets the tempo to the entered beat and BPM.',\n                        microbit2lite_set_tone:\n                            'Plays the entered melody for the entered beat. You can choose a scale between 1 and 5 octaves.',\n                        microbit2lite_play_preset_music: 'Plays preset music.',\n                        microbit2lite_play_sound_effect: 'Plays preset sound.',\n                        microbit2lite_get_btn:\n                            \"If the selected button is pressed, it is judged as 'True'.\",\n                        microbit2lite_get_logo: \"If the logo is touched, it is judged as 'True'.\",\n                        microbit2lite_get_gesture:\n                            \"When the selected movement is detected, it is judged as 'True'.\",\n                        microbit2lite_get_acc: 'The acceleration value of the selected axis.',\n                        microbit2lite_btn_event:\n                            'When the selected button is pressed, the connected blocks below will run',\n                        microbit2lite_get_direction: 'The compass direction value. (0~360)',\n                        microbit2lite_get_field_strength_axis:\n                            'The magnetic field strength value of the selected axis.',\n                        microbit2lite_get_light_level: 'The value of the light sensor.',\n                        microbit2lite_get_temperature: 'The current temperature value. (℃)',\n                        microbit2lite_get_sound_level: 'The microphone volume value.',\n                        microbit2lite_set_servo:\n                            'Sets the servo motor angle to the entered value on the selected pin.',\n                        microbit2lite_set_pwm:\n                            'Sets the servo pulse to the entered time on the selected pin.',\n                    },\n                    Msgs: {\n                        microbit2lite_compatible_error:\n                            'The corresponding block is not compatible to Microbit V1',\n                        microbit2lite_octave: 'Octave',\n                    },\n                },\n                jp: {\n                    template: {\n                        microbit2lite_get_analog: 'ピン %1 のアナログ値',\n                        microbit2lite_set_analog: 'ピン %1 にアナログ値 %2 を出力する %3',\n                        microbit2lite_get_digital: 'ピン %1 のデジタル値',\n                        microbit2lite_set_digital: 'ピン %1 に デジタル値 %2 を出力する %3',\n                        microbit2lite_screen_toggle: 'LED機能を %1 %2',\n                        microbit2lite_set_led: 'LEDの X: %1 Y: %2 を明るさ %3 にする %4',\n                        microbit2lite_get_led: 'LEDの X: %1 Y: %2 の明るさ',\n                        microbit2lite_show_preset_image: 'LEDに %1 アイコンを表示する %2',\n                        microbit2lite_show_custom_image: 'LED %1 を表示する %2',\n                        microbit2lite_show_string: 'LEDに %1 を表示する %2',\n                        microbit2lite_reset_screen: 'LEDを全部消す %1',\n                        microbit2lite_radio_toggle: 'ラジオ機能を %1 %2',\n                        microbit2lite_radio_setting: 'ラジオチャンネルを %1 に変更する %2',\n                        microbit2lite_radio_send: 'ラジオに %1 送信する %2',\n                        microbit2lite_radio_received: 'ラジオ受信値',\n                        microbit2lite_speaker_toggle: 'スピーカー機能 %1 %2',\n                        microbit2lite_change_tempo: 'テンポを %1 拍に %2 BPMにする %3',\n                        microbit2lite_set_tone: '%1 音を %2 拍演奏する %3',\n                        microbit2lite_play_preset_music: '%1 音楽を演奏する %2',\n                        microbit2lite_play_sound_effect: '%1 効果音を演奏する %2',\n                        microbit2lite_get_btn: '%1 ボタンが押したkか?',\n                        microbit2lite_get_logo: 'ロゴをタッチしたじか?',\n                        microbit2lite_get_gesture: '動きが %1 なのか?',\n                        microbit2lite_get_acc: '%1 の加速度',\n                        microbit2lite_get_direction: 'コンパス方向',\n                        microbit2lite_get_field_strength_axis: '%1 の磁場強度',\n                        microbit2lite_get_light_level: '光センサー値',\n                        microbit2lite_get_temperature: '温度値',\n                        microbit2lite_get_sound_level: 'マイク音の大きさ',\n                        microbit2lite_set_servo:\n                            'ピン %1 に サーボモーターの角度を %2 に設定する %3',\n                        microbit2lite_set_pwm: 'ピン %1 にサーボパルス幅を2にする %4',\n                        microbit2lite_common_title: 'Common Blocks',\n                        microbit2lite_v2_title: 'v2 Only',\n                    },\n                    Blocks: {\n                        octave: 'オクターブ',\n                        scalar: 'スカラー',\n                        xAxis: 'X軸',\n                        yAxis: 'Y軸',\n                        zAxis: 'Z軸',\n                        up: '上',\n                        down: '下',\n                        left: '右',\n                        right: '左',\n                        face_up: '全面',\n                        face_down: '後面',\n                        freefall: '自由落下',\n                        '3g': '3G',\n                        '6g': '6G',\n                        '8g': '8G',\n                        shake: '振れ',\n                        DADADADUM: '運命交響曲',\n                        ENTERTAINER: 'エンターネーター',\n                        PRELUDE: 'バッハ·プレリュード第1番',\n                        ODE: '合唱交響曲',\n                        NYAN: 'ニャンキャット',\n                        RINGTONE: '着信メロディ',\n                        FUNK: 'ファンク',\n                        BLUES: 'ブルース',\n                        BIRTHDAY: 'お誕生日おめでとう',\n                        WEDDING: '結婚行進曲',\n                        FUNERAL: '葬式の歌',\n                        PUNCHLINE: 'パンチライン',\n                        PYTHON: 'サーカス',\n                        BADDY: '悪党',\n                        CHASE: '追撃戦',\n                        BA_DING: 'コインGET',\n                        WAWAWAWAA: 'ガッカリ',\n                        JUMP_UP: '上にジャンプ',\n                        JUMP_DOWN: '下にジャンプ',\n                        POWER_UP: '点ける',\n                        POWER_DOWN: '消す',\n                        GIGGLE: '笑い',\n                        HAPPY: '幸せ',\n                        HELLO: '挨拶',\n                        MYSTERIOUS: '神秘的',\n                        SAD: '悲しみ',\n                        SLIDE: 'スライド',\n                        SOARING: '上昇',\n                        SPRING: '春',\n                        TWINKLE: 'キラキラ',\n                        YAWN: 'あくび',\n                        plot: 'オンにする',\n                        unplot: 'オフにする',\n                        on: 'オンにする',\n                        off: 'オフにする',\n                        microbit_2_HEART: 'ハート',\n                        microbit_2_HEART_SMALL: '小さなハート',\n                        microbit_2_HAPPY: '幸せ',\n                        microbit_2_SMILE: '笑い',\n                        microbit_2_SAD: '悲しみ',\n                        microbit_2_CONFUSED: '混乱',\n                        microbit_2_ANGRY: '怒り',\n                        microbit_2_ASLEEP: '眠気',\n                        microbit_2_SURPRISED: '驚き',\n                        microbit_2_SILLY: '間抜け',\n                        microbit_2_FABULOUS: '幻想的な',\n                        microbit_2_MEH: '別に',\n                        microbit_2_YES: 'イエス',\n                        microbit_2_NO: 'ノー',\n                        microbit_2_TRIANGLE: '三角形',\n                        microbit_2_TRIANGLE_LEFT: '左三角形',\n                        microbit_2_CHESSBOARD: 'チェスパン',\n                        microbit_2_DIAMOND: 'ダイヤモンド',\n                        microbit_2_DIAMOND_SMALL: '小さなダイヤモンド',\n                        microbit_2_SQUARE: '四角形',\n                        microbit_2_SQUARE_SMALL: '小さな四角形',\n                        microbit_2_RABBIT: 'ウサギ',\n                        microbit_2_COW: '牛',\n                        microbit_2_MUSIC_CROTCHET: '4分音符',\n                        microbit_2_MUSIC_QUAVER: '8分音符',\n                        microbit_2_MUSIC_QUAVERS: '8分音符2個',\n                        microbit_2_PITCHFORK: 'フォーク',\n                        microbit_2_XMAS: 'クリスマスツリー',\n                        microbit_2_PACMAN: 'パックマン',\n                        microbit_2_TARGET: '標的',\n                        microbit_2_TSHIRT: 'Tシャツ',\n                        microbit_2_ROLLERSKATE: 'ローラースケート',\n                        microbit_2_DUCK: 'アヒル',\n                        microbit_2_HOUSE: '家',\n                        microbit_2_TORTOISE: '亀',\n                        microbit_2_BUTTERFLY: '蝶',\n                        microbit_2_STICKFIGURE: 'スティックマン',\n                        microbit_2_GHOST: '幽霊',\n                        microbit_2_SWORD: 'ナイフ',\n                        microbit_2_GIRAFFE: 'キリン',\n                        microbit_2_SKULL: '骸骨',\n                        microbit_2_UMBRELLA: '傘',\n                        microbit_2_SNAKE: '蛇',\n                        microbit_2_CLOCK1: '1時',\n                        microbit_2_CLOCK2: '2時',\n                        microbit_2_CLOCK3: '3時',\n                        microbit_2_CLOCK4: '4時',\n                        microbit_2_CLOCK5: '5時',\n                        microbit_2_CLOCK6: '6時',\n                        microbit_2_CLOCK7: '7時',\n                        microbit_2_CLOCK8: '8時',\n                        microbit_2_CLOCK9: '9時',\n                        microbit_2_CLOCK10: '10時',\n                        microbit_2_CLOCK11: '11時',\n                        microbit_2_CLOCK12: '12時',\n                        microbit_2_ARROW_N: '北',\n                        microbit_2_ARROW_NE: '北東',\n                        microbit_2_ARROW_E: '東',\n                        microbit_2_ARROW_SE: '南東',\n                        microbit_2_ARROW_S: '南',\n                        microbit_2_ARROW_SW: '南西',\n                        microbit_2_ARROW_W: '西',\n                        microbit_2_ARROW_NW: '北西',\n                    },\n                    Helper: {\n                        microbit2lite_get_analog: '選択したピンのアナログ値です。(0 ~ 1023)',\n                        microbit2lite_set_analog:\n                            '選択したピンに入力したアナログ値を出力します。(0 ~ 1023)',\n                        microbit2lite_get_digital: '選択したピンのデジタル値です。(0, 1)',\n                        microbit2lite_set_digital:\n                            '選択したピンに入力したデジタル値を出力します。(0, 1)',\n                        microbit2lite_screen_toggle: 'LED機能をオンまたはオフにします。',\n                        microbit2lite_set_led: 'X、Y座標で選択したLEDを選択した明るさで点けます。',\n                        microbit2lite_get_led: 'X、Y座標で選択したLEDの明るさです。',\n                        microbit2lite_show_preset_image: 'LEDに先に設定されていた形で点けます。',\n                        microbit2lite_show_custom_image:\n                            'ブロックで選択したLEDを選択した明るさで点けます。 一度にすべてのLEDを操作できます。',\n                        microbit2lite_show_string: '入力した文字列をLEDに順番に表示します。',\n                        microbit2lite_reset_screen: 'LEDに表示したものをすべて消します。',\n                        microbit2lite_radio_toggle: 'ラジオ機能をオンまたはオフにします。',\n                        microbit2lite_radio_setting: 'ラジオチャンネルを入力した数字に変えます。',\n                        microbit2lite_radio_send: 'ラジオで入力した英数字を送信します。',\n                        microbit2lite_radio_received: 'ラジオで受信した値です。',\n                        microbit2lite_speaker_toggle: 'スピーカー機能をオンまたはオフにします。',\n                        microbit2lite_change_tempo: 'テンポを選択した拍子とBPMで設定します。',\n                        microbit2lite_set_tone:\n                            '選択した音を選択した拍子で演奏します。 1~5オクターブ間の音階を選べます。',\n                        microbit2lite_play_preset_music: '先に設定されていた音楽を演奏します。',\n                        microbit2lite_play_sound_effect: '先に設定されていた効果音を演奏します。',\n                        microbit2lite_get_btn: '選択したボタンが押されたら、「True」と判断します。',\n                        microbit2lite_get_logo: 'ロゴをタッチすると、「True」と判断します。',\n                        microbit2lite_get_gesture:\n                            '選択した動きを感知したら、「True」と判断します。',\n                        microbit2lite_get_acc: '選択した軸の加速度値です。',\n                        microbit2lite_get_direction: 'コンパス方向の値です。 (0~360)',\n                        microbit2lite_get_field_strength_axis: '選択した軸の磁場強度の値です。',\n                        microbit2lite_get_light_level: '光センサーの値です。',\n                        microbit2lite_get_temperature: '現在の温度です。 (℃)',\n                        microbit2lite_get_sound_level: 'マイクボリュームの値です。',\n                        microbit2lite_set_servo:\n                            '選択したピンにサーボモーターの角度を入力した値で設定します。',\n                        microbit2lite_set_pwm: '選択したピンのサーボパルス幅を選択した値にします。',\n                    },\n                    Msgs: {\n                        microbit2lite_compatible_error:\n                            '対応するブロックはMicrobitV1と互換性がありません',\n                        microbit2lite_octave: 'Octave',\n                    },\n                },\n            };\n        }\n\n        getBlocks = function () {\n            return {\n                microbit2lite_common_title: {\n                    skeleton: 'basic_text',\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.microbit2lite_common_title,\n                            color: '#333333',\n                            align: 'center',\n                        },\n                    ],\n                    def: {\n                        type: 'microbit2lite_common_title',\n                    },\n                    class: 'microbit2litePin',\n                    isNotFor: ['Microbit2lite'],\n                    events: {},\n                },\n\n                microbit2lite_get_analog: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.analogPins,\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2litePin',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_analog',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = script.getValue('VALUE');\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_ANALOG};${value}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_set_analog: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.analogPins,\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2litePin',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_set_analog',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const pin = script.getValue('PIN');\n                        const value = Math.round(\n                            this._clamp(script.getNumberValue('VALUE'), 0, 1023)\n                        );\n\n                        const parsedPayload = `${pin};${value}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_ANALOG};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_get_digital: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.digitalPins,\n                            value: 8,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2litePin',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_digital',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        const value = script.getValue('VALUE');\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_DIGITAL};${value}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_set_digital: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.digitalPins,\n                            value: 8,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [0, 0],\n                                [1, 1],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2litePin',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_set_digital',\n                    },\n                    paramsKeyMap: { PIN: 0, VALUE: 1 },\n                    func: async (sprite, script) => {\n                        const pin = script.getValue('PIN');\n                        const value = script.getValue('VALUE');\n                        const parsedPayload = `${pin};${value}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_DIGITAL};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_screen_toggle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.on, this.functionKeys.DISPLAY_ON],\n                                [Lang.Blocks.off, this.functionKeys.DISPLAY_OFF],\n                            ],\n                            value: this.functionKeys.DISPLAY_ON,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteLed',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_screen_toggle',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        const command = script.getField('VALUE');\n\n                        const response = await this.getResponseWithSync(`${command};`);\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_set_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 0,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 0,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 9,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteLed',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['9'],\n                            },\n                        ],\n                        type: 'microbit2lite_set_led',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        VALUE: 2,\n                    },\n                    func: async (sprite, script) => {\n                        const value = script.getNumberValue('VALUE');\n                        const x = script.getNumberValue('X');\n                        const y = script.getNumberValue('Y');\n                        if (x < 0 || y < 0 || x > 4 || y > 4 || value < 0 || value > 9) {\n                            return;\n                        }\n\n                        const parsedPayload = `${x};${y};${value}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_LED};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_get_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 0,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 0,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteLed',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['0'],\n                            },\n                        ],\n                        type: 'microbit2lite_get_led',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const x = script.getNumberValue('X');\n                        const y = script.getNumberValue('Y');\n                        if (x < 0 || y < 0 || x > 4 || y > 4) {\n                            return -1;\n                        }\n                        const parsedPayload = `${x};${y}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_LED};${parsedPayload}`\n                        );\n                        const parsedResponse = this.getResponse(response);\n\n                        if (parsedResponse == 0) {\n                            return 0;\n                        } else if (parsedResponse == 1) {\n                            return 1;\n                        }\n\n                        return Math.round(Math.log2(parsedResponse * 2));\n                    },\n                },\n                microbit2lite_show_preset_image: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.microbit_2_HEART, 0],\n                                [Lang.Blocks.microbit_2_HEART_SMALL, 1],\n                                [Lang.Blocks.microbit_2_HAPPY, 2],\n                                [Lang.Blocks.microbit_2_SMILE, 3],\n                                [Lang.Blocks.microbit_2_SAD, 4],\n                                [Lang.Blocks.microbit_2_CONFUSED, 5],\n                                [Lang.Blocks.microbit_2_ANGRY, 6],\n                                [Lang.Blocks.microbit_2_ASLEEP, 7],\n                                [Lang.Blocks.microbit_2_SURPRISED, 8],\n                                [Lang.Blocks.microbit_2_SILLY, 9],\n                                [Lang.Blocks.microbit_2_FABULOUS, 10],\n                                [Lang.Blocks.microbit_2_MEH, 11],\n                                [Lang.Blocks.microbit_2_YES, 12],\n                                [Lang.Blocks.microbit_2_NO, 13],\n                                [Lang.Blocks.microbit_2_TRIANGLE, 34],\n                                [Lang.Blocks.microbit_2_TRIANGLE_LEFT, 35],\n                                [Lang.Blocks.microbit_2_CHESSBOARD, 36],\n                                [Lang.Blocks.microbit_2_DIAMOND, 37],\n                                [Lang.Blocks.microbit_2_DIAMOND_SMALL, 38],\n                                [Lang.Blocks.microbit_2_SQUARE, 39],\n                                [Lang.Blocks.microbit_2_SQUARE_SMALL, 40],\n                                [Lang.Blocks.microbit_2_RABBIT, 41],\n                                [Lang.Blocks.microbit_2_COW, 42],\n                                [Lang.Blocks.microbit_2_MUSIC_CROTCHET, 43],\n                                [Lang.Blocks.microbit_2_MUSIC_QUAVER, 44],\n                                [Lang.Blocks.microbit_2_MUSIC_QUAVERS, 45],\n                                [Lang.Blocks.microbit_2_PITCHFORK, 46],\n                                [Lang.Blocks.microbit_2_XMAS, 47],\n                                [Lang.Blocks.microbit_2_PACMAN, 48],\n                                [Lang.Blocks.microbit_2_TARGET, 49],\n                                [Lang.Blocks.microbit_2_TSHIRT, 50],\n                                [Lang.Blocks.microbit_2_ROLLERSKATE, 51],\n                                [Lang.Blocks.microbit_2_DUCK, 52],\n                                [Lang.Blocks.microbit_2_HOUSE, 53],\n                                [Lang.Blocks.microbit_2_TORTOISE, 54],\n                                [Lang.Blocks.microbit_2_BUTTERFLY, 55],\n                                [Lang.Blocks.microbit_2_STICKFIGURE, 56],\n                                [Lang.Blocks.microbit_2_GHOST, 57],\n                                [Lang.Blocks.microbit_2_SWORD, 58],\n                                [Lang.Blocks.microbit_2_GIRAFFE, 59],\n                                [Lang.Blocks.microbit_2_SKULL, 60],\n                                [Lang.Blocks.microbit_2_UMBRELLA, 61],\n                                [Lang.Blocks.microbit_2_SNAKE, 62],\n                                [Lang.Blocks.microbit_2_CLOCK1, 14],\n                                [Lang.Blocks.microbit_2_CLOCK2, 15],\n                                [Lang.Blocks.microbit_2_CLOCK3, 16],\n                                [Lang.Blocks.microbit_2_CLOCK4, 17],\n                                [Lang.Blocks.microbit_2_CLOCK5, 18],\n                                [Lang.Blocks.microbit_2_CLOCK6, 19],\n                                [Lang.Blocks.microbit_2_CLOCK7, 20],\n                                [Lang.Blocks.microbit_2_CLOCK8, 21],\n                                [Lang.Blocks.microbit_2_CLOCK9, 22],\n                                [Lang.Blocks.microbit_2_CLOCK10, 23],\n                                [Lang.Blocks.microbit_2_CLOCK11, 24],\n                                [Lang.Blocks.microbit_2_CLOCK12, 25],\n                                [Lang.Blocks.microbit_2_ARROW_N, 26],\n                                [Lang.Blocks.microbit_2_ARROW_NE, 27],\n                                [Lang.Blocks.microbit_2_ARROW_E, 28],\n                                [Lang.Blocks.microbit_2_ARROW_SE, 29],\n                                [Lang.Blocks.microbit_2_ARROW_S, 30],\n                                [Lang.Blocks.microbit_2_ARROW_SW, 31],\n                                [Lang.Blocks.microbit_2_ARROW_W, 32],\n                                [Lang.Blocks.microbit_2_ARROW_NW, 33],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteLed',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_show_preset_image',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = this._clamp(script.getNumberValue('VALUE'), 0, 62);\n                        const parsedPayload = `${this.presetImage[value]}`;\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_CUSTOM_IMAGE};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_show_custom_image: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Led2',\n                            value: [\n                                [0, 0, 0, 0, 0],\n                                [0, 9, 0, 9, 0],\n                                [0, 0, 0, 0, 0],\n                                [9, 0, 0, 0, 9],\n                                [0, 9, 9, 9, 0],\n                            ],\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteLed',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_show_custom_image',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = script.getField('VALUE');\n                        const processedValue = [];\n                        for (const i in value) {\n                            processedValue[i] = value[i].join();\n                        }\n                        const parsedPayload = `${processedValue.join(':').replace(/,/gi, '')}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_CUSTOM_IMAGE};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_show_string: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteLed',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['Hello!'],\n                                accept: 'string',\n                            },\n                        ],\n                        type: 'microbit2lite_show_string',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        let payload = script.getStringValue('VALUE');\n                        payload = payload.replace(\n                            /[^A-Za-z0-9_\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\\\\\{\\}\\[\\]\\'\\\"\\;\\:\\<\\,\\>\\.\\?\\/\\s]/gim,\n                            ''\n                        );\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_STRING};${payload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_reset_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.remove, 'remove'],\n                                [Lang.Blocks.light, 'light'],\n                            ],\n                            value: 'remove',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteLed',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_reset_screen',\n                    },\n                    paramsKeyMap: { LED_STATUS: 0 },\n                    func: async (sprite, script) => {\n                        const ledStatus = script.getField('LED_STATUS');\n                        let response;\n                        if (ledStatus === 'light') {\n                            const defaultLed = '99999:99999:99999:99999:99999';\n                            response = await this.getResponseWithSync(\n                                `${this.functionKeys.SET_CUSTOM_IMAGE};${defaultLed}`\n                            );\n                        } else {\n                            response = await this.getResponseWithSync(\n                                `${this.functionKeys.RESET_SCREEN};`\n                            );\n                        }\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_radio_toggle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.on, this.functionKeys.RADIO_ON],\n                                [Lang.Blocks.off, this.functionKeys.RADIO_OFF],\n                            ],\n                            value: this.functionKeys.RADIO_ON,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteRadio',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_radio_toggle',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        const command = script.getField('VALUE');\n\n                        const response = await this.getResponseWithSync(`${command};`);\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_radio_setting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 7,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteRadio',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_radio_setting',\n                    },\n                    paramsKeyMap: { RATE: 0, CHANNEL: 1 },\n                    func: async (sprite, script) => {\n                        if (!Entry.Utils.isNumber(script.getNumberValue('CHANNEL'))) {\n                            return;\n                        }\n                        const channel = Math.round(\n                            this._clamp(script.getNumberValue('CHANNEL'), 0, 83)\n                        );\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SETTING_RADIO};${channel}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_radio_send: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteRadio',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_radio_send',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        const value = script.getStringValue('VALUE');\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_RADIO};${value}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_radio_received: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2liteRadio',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_radio_received',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_RADIO};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_change_tempo: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteSound',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['4'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['120'],\n                            },\n                        ],\n                        type: 'microbit2lite_change_tempo',\n                    },\n                    paramsKeyMap: {\n                        BEAT: 0,\n                        BPM: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const beat = Math.round(this._clamp(script.getNumberValue('BEAT'), 0, 4));\n                        const bpm = Math.round(this._clamp(script.getNumberValue('BPM'), 1, 230));\n\n                        const parsedPayload = `${beat};${bpm}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.CHANGE_TEMPO};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_set_tone: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'MusicScale',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['4', 16],\n                                ['2', 8],\n                                ['1', 4],\n                                ['1/2', 2],\n                                ['1/4', 1],\n                            ],\n                            value: 4,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteSound',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_set_tone',\n                    },\n                    paramsKeyMap: {\n                        SCALE: 0,\n                        NOTE: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const scale = script.getField('SCALE');\n                        const note = script.getField('NOTE');\n                        const parsedPayload = `${scale}:${note}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.PLAY_TONE};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_play_preset_music: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.DADADADUM, 0],\n                                [Lang.Blocks.ENTERTAINER, 1],\n                                [Lang.Blocks.PRELUDE, 2],\n                                [Lang.Blocks.ODE, 3],\n                                [Lang.Blocks.NYAN, 4],\n                                [Lang.Blocks.RINGTONE, 5],\n                                [Lang.Blocks.FUNK, 6],\n                                [Lang.Blocks.BLUES, 7],\n                                [Lang.Blocks.BIRTHDAY, 8],\n                                [Lang.Blocks.WEDDING, 9],\n                                [Lang.Blocks.FUNERAL, 10],\n                                [Lang.Blocks.PUNCHLINE, 11],\n                                [Lang.Blocks.PYTHON, 12],\n                                [Lang.Blocks.BADDY, 13],\n                                [Lang.Blocks.CHASE, 14],\n                                [Lang.Blocks.BA_DING, 15],\n                                [Lang.Blocks.WAWAWAWAA, 16],\n                                [Lang.Blocks.JUMP_UP, 17],\n                                [Lang.Blocks.JUMP_DOWN, 18],\n                                [Lang.Blocks.POWER_UP, 19],\n                                [Lang.Blocks.POWER_DOWN, 20],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteSound',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_play_preset_music',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = this._clamp(script.getNumberValue('VALUE'), 0, 20);\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.PLAY_MELODY};${value}`\n                        );\n                        this.getResponse(response);\n                        return new Promise((resolve, reject) => {\n                            this.waitMilliSec(500, resolve);\n                        });\n                    },\n                },\n\n                microbit2lite_get_btn: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['A', 'a'],\n                                ['B', 'b'],\n                                ['A+B', 'ab'],\n                            ],\n                            value: 'a',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteSensor',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_btn',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = script.getField('VALUE');\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_BTN};`\n                        );\n                        const parsedResponse = this.getResponse(response);\n\n                        if (parsedResponse == '1' && value == 'a') {\n                            return 1;\n                        } else if (parsedResponse == '2' && value == 'b') {\n                            return 1;\n                        } else if (parsedResponse == '3' && value == 'ab') {\n                            return 1;\n                        } else {\n                            return 0;\n                        }\n                    },\n                },\n                microbit2lite_btn_event: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: { x: 0, y: -2 },\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['A', '1'],\n                                ['B', '2'],\n                                ['A+B', '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        type: 'microbit2lite_btn_event',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 1,\n                    },\n                    class: 'microbit2litev2',\n                    isNotFor: ['Microbit2lite'],\n                    event: 'microbit2lite_btn_pressed',\n                    func: (sprite, script) => {\n                        return script.callReturn();\n                    },\n                },\n                microbit2lite_get_acc: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.xAxis, 'x'],\n                                [Lang.Blocks.yAxis, 'y'],\n                                [Lang.Blocks.zAxis, 'z'],\n                                [Lang.Blocks.scalar, 'mag'],\n                            ],\n                            value: 'x',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteSensor',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_acc',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const axis = script.getField('AXIS');\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_ACC};${axis}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_get_gesture: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.up, 'up'],\n                                [Lang.Blocks.down, 'down'],\n                                [Lang.Blocks.left, 'left'],\n                                [Lang.Blocks.right, 'right'],\n                                [Lang.Blocks.face_up, 'face up'],\n                                [Lang.Blocks.face_down, 'face down'],\n                                [Lang.Blocks.freefall, 'freefall'],\n                                [Lang.Blocks['3g'], '3g'],\n                                [Lang.Blocks['6g'], '6g'],\n                                [Lang.Blocks['8g'], '8g'],\n                                [Lang.Blocks['shake'], 'shake'],\n                            ],\n                            value: 'up',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteSensor',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_gesture',\n                    },\n                    paramsKeyMap: { GESTURE: 0 },\n                    func: async (sprite, script) => {\n                        const gesture = script.getField('GESTURE');\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_GESTURE};`\n                        );\n                        const parsedResponse = this.getResponse(response);\n\n                        if (gesture === parsedResponse[1]) {\n                            return true;\n                        }\n                        return false;\n                    },\n                },\n                microbit2lite_get_direction: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2liteSensor',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_direction',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_DIRECTION};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_get_field_strength_axis: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.xAxis, 'x'],\n                                [Lang.Blocks.yAxis, 'y'],\n                                [Lang.Blocks.zAxis, 'z'],\n                                [Lang.Blocks.scalar, 'mag'],\n                            ],\n                            value: 'x',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteSensor',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_field_strength_axis',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const axis = script.getField('AXIS');\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_FIELD_STRENGTH};${axis}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_get_light_level: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2liteSensor',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_light_level',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_LIGHT_LEVEL};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_get_temperature: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2liteSensor',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_temperature',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_TEMPERATURE};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n\n                microbit2lite_set_servo: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.majorPins,\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteServo',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_set_servo',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const pin = script.getValue('PIN');\n                        const value = Math.round(\n                            this._clamp(script.getNumberValue('VALUE'), 0, 180)\n                        );\n\n                        const parsedPayload = `${pin};${value}`;\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_SERVO_ANGLE};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_set_pwm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.analogPins,\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['ms', 'milli'],\n                                ['µs', 'micro'],\n                            ],\n                            value: 'milli',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2liteServo',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_set_pwm',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                        UNIT: 2,\n                    },\n                    func: async (sprite, script) => {\n                        const pin = script.getValue('PIN');\n                        const unit = script.getValue('UNIT');\n                        const value = Math.round(\n                            this._clamp(script.getNumberValue('VALUE'), 0, 1023)\n                        );\n                        const command =\n                            unit === 'milli'\n                                ? this.functionKeys.SET_SERVO_MILLI\n                                : this.functionKeys.SET_SERVO_MICRO;\n\n                        const parsedPayload = `${pin};${value}`;\n                        const response = await this.getResponseWithSync(\n                            `${command};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n\n                microbit2lite_v2_title: {\n                    skeleton: 'basic_text',\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.microbit2lite_v2_title,\n                            color: '#333333',\n                            align: 'center',\n                        },\n                    ],\n                    def: {\n                        type: 'microbit2lite_v2_title',\n                    },\n                    class: 'microbit2litev2',\n                    isNotFor: ['Microbit2lite'],\n                    events: {},\n                },\n                microbit2lite_get_logo: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2litev2',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_logo',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        if (this.version === '1') {\n                            throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                                Lang.Msgs.microbit2lite_compatible_error,\n                            ]);\n                        }\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_LOGO};`\n                        );\n                        const parsedResponse = this.getResponse(response);\n                        if (parsedResponse == '1') {\n                            return 1;\n                        } else {\n                            return 0;\n                        }\n                    },\n                },\n                microbit2lite_get_sound_level: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2litev2',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_get_sound_level',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_SOUND_LEVEL};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_speaker_toggle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.on, this.functionKeys.SPEAKER_ON],\n                                [Lang.Blocks.off, this.functionKeys.SPEAKER_OFF],\n                            ],\n                            value: this.functionKeys.SPEAKER_ON,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2litev2',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_speaker_toggle',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        if (this.version === '1') {\n                            throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                                Lang.Msgs.microbit2_compatible_error,\n                            ]);\n                        }\n                        const command = script.getField('VALUE');\n                        const response = await this.getResponseWithSync(`${command};`);\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2lite_play_sound_effect: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.GIGGLE, 21],\n                                [Lang.Blocks.HAPPY, 22],\n                                [Lang.Blocks.HELLO, 23],\n                                [Lang.Blocks.MYSTERIOUS, 24],\n                                [Lang.Blocks.SAD, 25],\n                                [Lang.Blocks.SLIDE, 26],\n                                [Lang.Blocks.SOARING, 27],\n                                [Lang.Blocks.SPRING, 28],\n                                [Lang.Blocks.TWINKLE, 29],\n                                [Lang.Blocks.YAWN, 30],\n                            ],\n                            value: 21,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2litev2',\n                    isNotFor: ['Microbit2lite'],\n                    def: {\n                        type: 'microbit2lite_play_sound_effect',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = this._clamp(script.getNumberValue('VALUE'), 21, 30);\n                        const parsedPayload = `${value}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.PLAY_SOUND};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n            };\n        };\n    })();\n})();\n\nmodule.exports = Entry.Microbit2lite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_microbit2ble_lite.js",
    "content": "'use strict';\nconst _clamp = require('lodash/clamp');\n\nconst EVENT_INTERVAL = 150;\nconst getInitialLedState = () => [\n    [false, false, false, false, false],\n    [false, false, false, false, false],\n    [false, false, false, false, false],\n    [false, false, false, false, false],\n    [false, false, false, false, false],\n];\nconst convertPresetImageToLedState = (preset) => {\n    const colums = preset.split(':');\n    const result = colums.map((row) => row.split('').map((num) => num !== '0'));\n    return result;\n};\n\n(function () {\n    Entry.Microbit2BleLite = new (class Microbit2LiteBle {\n        constructor() {\n            this.webapiType = 'ble';\n            this.supportFirmwareFlash = true;\n            this.bluetoothInfo = {\n                filters: [\n                    {\n                        namePrefix: 'BBC micro:bit',\n                    },\n                ],\n            };\n\n            this.presetImage = [\n                // Image.HEART\n                '09090:99999:99999:09990:00900',\n                // Image.HEART_SMALL,\n                '00000:09090:09990:00900:00000',\n                // Image.HAPPY,\n                '00000:09090:00000:90009:09990',\n                // Image.SMILE,\n                '00000:00000:00000:90009:09990',\n                // Image.SAD,\n                '00000:09090:00000:09990:90009',\n                // Image.CONFUSED,\n                '00000:09090:00000:09090:90909',\n                // Image.ANGRY,\n                '90009:09090:00000:99999:90909',\n                // Image.ASLEEP,\n                '00000:99099:00000:09990:00000',\n                // Image.SURPRISED,\n                '09090:00000:00900:09090:00900',\n                // Image.SILLY,\n                '90009:00000:99999:00909:00999',\n                // Image.FABULOUS,\n                '99999:99099:00000:09090:09990',\n                // Image.MEH,\n                '09090:00000:00090:00900:09000',\n                // Image.YES,\n                '00000:00009:00090:90900:09000',\n                // Image.NO,\n                '90009:09090:00900:09090:90009',\n                // Image.CLOCK1,\n                '00090:00090:00900:00000:00000',\n                // Image.CLOCK2,\n                '00000:00990:00900:00000:00000',\n                // Image.CLOCK3,\n                '00000:00000:00999:00000:00000',\n                // Image.CLOCK4,\n                '00000:00000:00900:00990:00000',\n                // Image.CLOCK5,\n                '00000:00000:00900:00090:00090',\n                // Image.CLOCK6,\n                '00000:00000:00900:00900:00900',\n                // Image.CLOCK7,\n                '00000:00000:00900:09000:09000',\n                // Image.CLOCK8,\n                '00000:00000:00900:99000:00000',\n                // Image.CLOCK9,\n                '00000:00000:99900:00000:00000',\n                // Image.CLOCK10,\n                '00000:09900:00900:00000:00000',\n                // Image.CLOCK11,\n                '09000:09000:00900:00000:00000',\n                // Image.CLOCK12,\n                '00900:00900:00900:00000:00000',\n                // Image.ARROW_N,\n                '00900:09990:90909:00900:00900',\n                // Image.ARROW_NE,\n                '00999:00099:00909:09000:90000',\n                // Image.ARROW_E,\n                '00900:00090:99999:00090:00900',\n                // Image.ARROW_SE,\n                '90000:09000:00909:00099:00999',\n                // Image.ARROW_S,\n                '00900:00900:90909:09990:00900',\n                // Image.ARROW_SW,\n                '00009:00090:90900:99000:99900',\n                // Image.ARROW_W,\n                '00900:09000:99999:09000:00900',\n                // Image.ARROW_NW,\n                '99900:99000:90900:00090:00009',\n                // Image.TRIANGLE,\n                '00000:00900:09090:99999:00000',\n                // Image.TRIANGLE_LEFT,\n                '90000:99000:90900:90090:99999',\n                // Image.CHESSBOARD,\n                '09090:90909:09090:90909:09090',\n                // Image.DIAMOND,\n                '00900:09090:90009:09090:00900',\n                // Image.DIAMOND_SMALL,\n                '00000:00900:09090:00900:00000',\n                // Image.SQUARE,\n                '99999:90009:90009:90009:99999',\n                // Image.SQUARE_SMALL,\n                '00000:09990:09090:09990:00000',\n                // Image.RABBIT,\n                '90900:90900:99990:99090:99990',\n                // Image.COW,\n                '90009:90009:99999:09990:00900',\n                // Image.MUSIC_CROTCHET,\n                '00900:00900:00900:99900:99900',\n                // Image.MUSIC_QUAVER,\n                '00900:00990:00909:99900:99900',\n                // Image.MUSIC_QUAVERS,\n                '09999:09009:09009:99099:99099',\n                // Image.PITCHFORK,\n                '90909:90909:99999:00900:00900',\n                // Image.XMAS,\n                '00900:09990:00900:09990:99999',\n                // Image.PACMAN,\n                '099999:99090:99900:99990:09999',\n                // Image.TARGET,\n                '00900:09990:99099:09990:00900',\n                // Image.TSHIRT,\n                '99099:99999:09990:09990:09990',\n                // Image.ROLLERSKATE,\n                '00099:00099:99999:99999:09090',\n                // Image.DUCK,\n                '00990:99900:09999:09990:00000',\n                // Image.HOUSE,\n                '00900:09990:99999:09990:09090',\n                // Image.TORTOISE,\n                '00000:09990:99999:09090:00000',\n                // Image.BUTTERFLY,\n                '99099:99999:00900:99999:99099',\n                // Image.STICKFIGURE,\n                '00900:99999:00900:09090:90009',\n                // Image.GHOST,\n                '99999:90909:99999:99999:90909',\n                // Image.SWORD,\n                '00900:00900:00900:09990:00900',\n                // Image.GIRAFFE,\n                '99000:09000:09000:09990:09090',\n                // Image.SKULL,\n                '09990:90909:99999:09990:09990',\n                // Image.UMBRELLA,\n                '09990:99999:00900:90900:09900',\n                // Image.SNAKE,\n                '99000:99099:09090:09990:00000',\n            ];\n            this.id = '220302';\n            this.url = 'http://microbit.org/ko/';\n            this.imageName = 'microbit2blelite.png';\n            this.title = {\n                en: 'Microbit V2',\n                ko: '마이크로비트 V2',\n            };\n            this.name = 'Microbit2BleLite';\n            this.functionKeys = {\n                LOCALDATA: 'localdata',\n                GET_ANALOG: 'get-analog',\n                GET_DIGITAL: 'get-digital',\n                SET_ANALOG: 'set-analog',\n                SET_DIGITAL: 'set-digital',\n                SET_LED: 'set-pixel',\n                GET_LED: 'get-pixel',\n                RESET: 'reset',\n                PRESET_IMAGE: 'pre-image',\n                SET_CUSTOM_IMAGE: 'custom-image',\n                SET_STRING: 'print',\n                RESET_SCREEN: 'display-clear',\n                DISPLAY_ON: 'display-on',\n                DISPLAY_OFF: 'display-off',\n                SPEAKER_ON: 'speaker-on',\n                SPEAKER_OFF: 'speaker-off',\n                PLAY_TONE: 'play-tone',\n                PLAY_SOUND: 'pre-sound',\n                PLAY_MELODY: 'pre-melody',\n                GET_BTN: 'get-btn',\n                CHANGE_TEMPO: 'change-tempo',\n                GET_LOGO: 'get-touch',\n                GET_ACC: 'get-acc',\n                GET_GESTURE: 'get-gesture',\n                GET_DIRECTION: 'direction',\n                GET_FIELD_STRENGTH: 'field-strength',\n                GET_FIELD_STRENGTH_AXIS: 'field-axis-strength',\n                GET_LIGHT_LEVEL: 'light-level',\n                GET_TEMPERATURE: 'temperature',\n                GET_SOUND_LEVEL: 'sound-level',\n                SET_RADIO: 'radio-send',\n                GET_RADIO: 'radio-receive',\n                RADIO_ON: 'radio-on',\n                RADIO_OFF: 'radio-off',\n                SETTING_RADIO: 'radio-setting',\n                SET_SERVO_MILLI: 'write-period',\n                SET_SERVO_MICRO: 'write-micro-period',\n                SET_SERVO_ANGLE: 'servo-write',\n            };\n            this.presetImage = [\n                // Image.HEART\n                '09090:99999:99999:09990:00900',\n                // Image.HEART_SMALL,\n                '00000:09090:09990:00900:00000',\n                // Image.HAPPY,\n                '00000:09090:00000:90009:09990',\n                // Image.SMILE,\n                '00000:00000:00000:90009:09990',\n                // Image.SAD,\n                '00000:09090:00000:09990:90009',\n                // Image.CONFUSED,\n                '00000:09090:00000:09090:90909',\n                // Image.ANGRY,\n                '90009:09090:00000:99999:90909',\n                // Image.ASLEEP,\n                '00000:99099:00000:09990:00000',\n                // Image.SURPRISED,\n                '09090:00000:00900:09090:00900',\n                // Image.SILLY,\n                '90009:00000:99999:00909:00999',\n                // Image.FABULOUS,\n                '99999:99099:00000:09090:09990',\n                // Image.MEH,\n                '09090:00000:00090:00900:09000',\n                // Image.YES,\n                '00000:00009:00090:90900:09000',\n                // Image.NO,\n                '90009:09090:00900:09090:90009',\n                // Image.CLOCK1,\n                '00090:00090:00900:00000:00000',\n                // Image.CLOCK2,\n                '00000:00990:00900:00000:00000',\n                // Image.CLOCK3,\n                '00000:00000:00999:00000:00000',\n                // Image.CLOCK4,\n                '00000:00000:00900:00990:00000',\n                // Image.CLOCK5,\n                '00000:00000:00900:00090:00090',\n                // Image.CLOCK6,\n                '00000:00000:00900:00900:00900',\n                // Image.CLOCK7,\n                '00000:00000:00900:09000:09000',\n                // Image.CLOCK8,\n                '00000:00000:00900:99000:00000',\n                // Image.CLOCK9,\n                '00000:00000:99900:00000:00000',\n                // Image.CLOCK10,\n                '00000:09900:00900:00000:00000',\n                // Image.CLOCK11,\n                '09000:09000:00900:00000:00000',\n                // Image.CLOCK12,\n                '00900:00900:00900:00000:00000',\n                // Image.ARROW_N,\n                '00900:09990:90909:00900:00900',\n                // Image.ARROW_NE,\n                '00999:00099:00909:09000:90000',\n                // Image.ARROW_E,\n                '00900:00090:99999:00090:00900',\n                // Image.ARROW_SE,\n                '90000:09000:00909:00099:00999',\n                // Image.ARROW_S,\n                '00900:00900:90909:09990:00900',\n                // Image.ARROW_SW,\n                '00009:00090:90900:99000:99900',\n                // Image.ARROW_W,\n                '00900:09000:99999:09000:00900',\n                // Image.ARROW_NW,\n                '99900:99000:90900:00090:00009',\n                // Image.TRIANGLE,\n                '00000:00900:09090:99999:00000',\n                // Image.TRIANGLE_LEFT,\n                '90000:99000:90900:90090:99999',\n                // Image.CHESSBOARD,\n                '09090:90909:09090:90909:09090',\n                // Image.DIAMOND,\n                '00900:09090:90009:09090:00900',\n                // Image.DIAMOND_SMALL,\n                '00000:00900:09090:00900:00000',\n                // Image.SQUARE,\n                '99999:90009:90009:90009:99999',\n                // Image.SQUARE_SMALL,\n                '00000:09990:09090:09990:00000',\n                // Image.RABBIT,\n                '90900:90900:99990:99090:99990',\n                // Image.COW,\n                '90009:90009:99999:09990:00900',\n                // Image.MUSIC_CROTCHET,\n                '00900:00900:00900:99900:99900',\n                // Image.MUSIC_QUAVER,\n                '00900:00990:00909:99900:99900',\n                // Image.MUSIC_QUAVERS,\n                '09999:09009:09009:99099:99099',\n                // Image.PITCHFORK,\n                '90909:90909:99999:00900:00900',\n                // Image.XMAS,\n                '00900:09990:00900:09990:99999',\n                // Image.PACMAN,\n                '099999:99090:99900:99990:09999',\n                // Image.TARGET,\n                '00900:09990:99099:09990:00900',\n                // Image.TSHIRT,\n                '99099:99999:09990:09990:09990',\n                // Image.ROLLERSKATE,\n                '00099:00099:99999:99999:09090',\n                // Image.DUCK,\n                '00990:99900:09999:09990:00000',\n                // Image.HOUSE,\n                '00900:09990:99999:09990:09090',\n                // Image.TORTOISE,\n                '00000:09990:99999:09090:00000',\n                // Image.BUTTERFLY,\n                '99099:99999:00900:99999:99099',\n                // Image.STICKFIGURE,\n                '00900:99999:00900:09090:90009',\n                // Image.GHOST,\n                '99999:90909:99999:99999:90909',\n                // Image.SWORD,\n                '00900:00900:00900:09990:00900',\n                // Image.GIRAFFE,\n                '99000:09000:09000:09990:09090',\n                // Image.SKULL,\n                '09990:90909:99999:09990:09990',\n                // Image.UMBRELLA,\n                '09990:99999:00900:90900:09900',\n                // Image.SNAKE,\n                '99000:99099:09090:09990:00000',\n            ];\n            this.digitalPins = [\n                ['P8', 8],\n                ['P9', 9],\n                ['P12', 12],\n                ['P13', 13],\n                ['P14', 14],\n                ['P15', 15],\n                ['P16', 16],\n            ];\n            this.analogPins = [\n                ['P0', 0],\n                ['P1', 1],\n                ['P2', 2],\n                ['P3', 3],\n                ['P4', 4],\n                ['P10', 10],\n            ];\n            this.majorPins = [\n                ['P0', 0],\n                ['P1', 1],\n                ['P2', 2],\n            ];\n            this.ledRows = [\n                [0, 0],\n                [1, 1],\n                [2, 2],\n                [3, 3],\n                [4, 4],\n            ];\n            this.blockMenuBlocks = [\n                'microbit2blelite_common_title',\n\n                // 'microbit2blelite_get_analog',\n                // 'microbit2blelite_set_analog',\n                // 'microbit2blelite_get_digital',\n                // 'microbit2blelite_set_digital',\n\n                'microbit2blelite_screen_toggle',\n                'microbit2blelite_set_led',\n                'microbit2blelite_get_led',\n                'microbit2blelite_show_custom_image',\n                'microbit2blelite_show_string',\n                'microbit2blelite_show_preset_image',\n                'microbit2blelite_reset_screen',\n\n                // 'microbit2blelite_radio_toggle',\n                // 'microbit2blelite_radio_setting',\n                // 'microbit2blelite_radio_send',\n                // 'microbit2blelite_radio_received',\n\n                // 'microbit2blelite_change_tempo',\n                // 'microbit2blelite_set_tone',\n                // 'microbit2blelite_play_preset_music',\n\n                'microbit2blelite_get_btn',\n                'microbit2blelite_get_acc',\n                // 'microbit2blelite_get_gesture',\n                // 'microbit2blelite_get_direction',\n                'microbit2blelite_get_field_strength_axis',\n                // 'microbit2blelite_get_light_level',\n                'microbit2blelite_get_temperature',\n\n                // 'microbit2blelite_set_servo',\n                // 'microbit2blelite_set_pwm',\n\n                'microbit2blelite_v2_title',\n                // 'microbit2blelite_get_logo',\n                'microbit2blelite_btn_event',\n                // 'microbit2blelite_speaker_toggle',\n                // 'microbit2blelite_play_sound_effect',\n                // 'microbit2blelite_get_sound_level',\n            ];\n            this.services = undefined;\n            this.ledState = getInitialLedState();\n            this.version = '2';\n            this.buttonState = { a: 0, b: 0 };\n        }\n        async setZero() {\n            this.ledState = getInitialLedState();\n            await this.services.LedService.writeMatrixState(this.ledState);\n        }\n\n        async initialHandshake() {\n            this.services = Entry.hwLite.bluetooth.services;\n            if (this.services.TemperatureService) {\n                await this.services.TemperatureService.setTemperaturePeriod(2000);\n            }\n            if (this.services.AccelerometerService) {\n                await this.services.AccelerometerService.setAccelerometerPeriod(640);\n            }\n            if (this.services.IoPinService) {\n                // debugger;\n                // console.log(await this.services.IoPinService.getAdConfiguration());\n            }\n            await this.setEventListener();\n        }\n\n        async setEventListener() {\n            if (!this.services) {\n                return;\n            }\n            await this.setButtonEvent();\n            //     await this.setPinDataEvent();\n        }\n\n        async setPinDataEvent() {\n            if (this.services.IoPinService) {\n                this.services.IoPinService.addEventListener('pindatachanged', (event) => {\n                    console.log(event);\n                });\n            }\n        }\n\n        pressedBothButton(fireEvent) {\n            if (this.buttonState.a + this.buttonState.b === 2) {\n                if (fireEvent) {\n                    Entry.engine.fireEventWithValue('microbit2blelite_btn_pressed', 3);\n                }\n                return true;\n            }\n            return false;\n        }\n\n        setButtonEvent() {\n            if (this.services.ButtonService) {\n                this.services.ButtonService.addEventListener('buttonastatechanged', (event) => {\n                    this.buttonState.a = event.detail;\n                    if (event.detail === 1 && !this.pressedBothButton(true)) {\n                        Entry.engine.fireEventWithValue('microbit2blelite_btn_pressed', 1);\n                    }\n                });\n                this.services.ButtonService.addEventListener('buttonbstatechanged', (event) => {\n                    this.buttonState.b = event.detail;\n                    if (event.detail === 1 && !this.pressedBothButton(true)) {\n                        Entry.engine.fireEventWithValue('microbit2blelite_btn_pressed', 2);\n                    }\n                });\n            }\n        }\n\n        // 언어 적용\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        microbit2blelite_get_analog: '핀 %1 번 아날로그 값',\n                        microbit2blelite_set_analog: '핀 %1 에 아날로그 값 %2 를 출력하기 %3',\n                        microbit2blelite_get_digital: '핀 %1 번 디지털 값',\n                        microbit2blelite_set_digital: '핀 %1 에 디지털 값 %2 를 출력하기 %3',\n                        microbit2blelite_screen_toggle: 'LED 기능 %1 %2',\n                        microbit2blelite_set_led: 'LED의 X: %1 Y: %2 를 밝기 %3 (으)로 밝히기 %4',\n                        microbit2blelite_get_led: 'LED의 X: %1 Y: %2 밝기 값',\n                        microbit2blelite_show_preset_image: 'LED에 %1 모양 나타내기 %2',\n                        microbit2blelite_show_custom_image: 'LED %1 밝히기 %2',\n                        microbit2blelite_show_string: 'LED에 %1 을(를) 나타내기 %2',\n                        microbit2blelite_reset_screen: 'LED 모두 %1 %2',\n                        microbit2blelite_radio_toggle: '라디오 기능 %1 %2',\n                        microbit2blelite_radio_setting: '라디오 채널을 %1 (으)로 바꾸기 %2',\n                        microbit2blelite_radio_send: '라디오로 %1 송신하기 %2',\n                        microbit2blelite_radio_received: '라디오 수신 값',\n                        microbit2blelite_speaker_toggle: '스피커 기능 %1 %2',\n                        microbit2blelite_change_tempo: '연주 속도를 %1 박에 %2 BPM으로 정하기 %3',\n                        microbit2blelite_set_tone: '%1 음을 %2 박만큼 연주하기 %3',\n                        microbit2blelite_play_preset_music: '%1 음악을 연주하기 %2',\n                        microbit2blelite_play_sound_effect: '%1 효과음을 연주하기 %2',\n                        microbit2blelite_get_btn: '%1 버튼이 눌렸는가?',\n                        microbit2blelite_get_logo: '로고를 터치했는가?',\n                        microbit2blelite_get_gesture: '움직임이 %1 인가?',\n                        microbit2blelite_get_acc: '%1 의 가속도',\n                        microbit2blelite_btn_event: '%1 %2 버튼을 눌렀을 때',\n                        microbit2blelite_get_direction: '나침반 방향',\n                        microbit2blelite_get_field_strength_axis: '%1 의 자기장 세기 값',\n                        microbit2blelite_get_light_level: '빛 센서 값',\n                        microbit2blelite_get_temperature: '온도',\n                        microbit2blelite_get_sound_level: '마이크 소리 크기',\n                        microbit2blelite_set_servo: '핀 %1 에 서보 모터 각도를 %2 로 정하기 %3',\n                        microbit2blelite_set_pwm: '핀 %1 에 서보 펄스 폭을 %2 %3초로 정하기 %4',\n                        microbit2blelite_common_title: '마이크로비트 공통',\n                        microbit2blelite_v2_title: '마이크로비트 V2 전용',\n                    },\n                    Blocks: {\n                        octave: '옥타브',\n                        scalar: '스칼라',\n                        xAxis: 'X축',\n                        yAxis: 'Y축',\n                        zAxis: 'Z축',\n                        up: '위',\n                        down: '아래',\n                        left: '왼쪽',\n                        right: '오른쪽',\n                        face_up: '앞면',\n                        face_down: '뒷면',\n                        freefall: '자유 낙하',\n                        '3g': '3G',\n                        '6g': '6G',\n                        '8g': '8G',\n                        shake: '흔들림',\n                        DADADADUM: '운명 교향곡',\n                        ENTERTAINER: '엔터테이너',\n                        PRELUDE: '바흐 프렐류드 1번',\n                        ODE: '합창 교향곡',\n                        NYAN: '냥캣',\n                        RINGTONE: '벨소리',\n                        FUNK: '펑크',\n                        BLUES: '블루스',\n                        BIRTHDAY: '생일 축하합니다',\n                        WEDDING: '결혼 행진곡',\n                        FUNERAL: '장례식 노래',\n                        PUNCHLINE: '펀치라인',\n                        PYTHON: '서커스',\n                        BADDY: '악당',\n                        CHASE: '추격전',\n                        BA_DING: '동전 GET',\n                        WAWAWAWAA: '실망',\n                        JUMP_UP: '위로 점프',\n                        JUMP_DOWN: '아래로 점프',\n                        POWER_UP: '켜기',\n                        POWER_DOWN: '끄기',\n                        GIGGLE: '웃음',\n                        HAPPY: '행복',\n                        HELLO: '인사',\n                        MYSTERIOUS: '신비로움',\n                        SAD: '슬픔',\n                        SLIDE: '슬라이드',\n                        SOARING: '상승',\n                        SPRING: '봄',\n                        TWINKLE: '반짝반짝',\n                        YAWN: '하품',\n                        plot: '켜기',\n                        unplot: '끄기',\n                        on: '켜기',\n                        off: '끄기',\n                        remove: '지우기',\n                        light: '밝히기',\n                        microbit_2_HEART: '하트',\n                        microbit_2_HEART_SMALL: '작은 하트',\n                        microbit_2_HAPPY: '행복',\n                        microbit_2_SMILE: '웃음',\n                        microbit_2_SAD: '슬픔',\n                        microbit_2_CONFUSED: '혼란',\n                        microbit_2_ANGRY: '화남',\n                        microbit_2_ASLEEP: '졸림',\n                        microbit_2_SURPRISED: '놀람',\n                        microbit_2_SILLY: '메롱',\n                        microbit_2_FABULOUS: '환상적인',\n                        microbit_2_MEH: '별로',\n                        microbit_2_YES: '예스',\n                        microbit_2_NO: '노',\n                        microbit_2_TRIANGLE: '삼각형',\n                        microbit_2_TRIANGLE_LEFT: '왼쪽 삼각형',\n                        microbit_2_CHESSBOARD: '체스판',\n                        microbit_2_DIAMOND: '다이아몬드',\n                        microbit_2_DIAMOND_SMALL: '작은 다이아몬드',\n                        microbit_2_SQUARE: '사각형',\n                        microbit_2_SQUARE_SMALL: '작은 사각형',\n                        microbit_2_RABBIT: '토끼',\n                        microbit_2_COW: '소',\n                        microbit_2_MUSIC_CROTCHET: '4분음표',\n                        microbit_2_MUSIC_QUAVER: '8분음표',\n                        microbit_2_MUSIC_QUAVERS: '8분음표 2개',\n                        microbit_2_PITCHFORK: '쇠스랑',\n                        microbit_2_XMAS: '크리스마스 트리',\n                        microbit_2_PACMAN: '팩맨',\n                        microbit_2_TARGET: '표적',\n                        microbit_2_TSHIRT: '티셔츠',\n                        microbit_2_ROLLERSKATE: '롤러스케이트',\n                        microbit_2_DUCK: '오리',\n                        microbit_2_HOUSE: '집',\n                        microbit_2_TORTOISE: '거북이',\n                        microbit_2_BUTTERFLY: '나비',\n                        microbit_2_STICKFIGURE: '스틱맨',\n                        microbit_2_GHOST: '유령',\n                        microbit_2_SWORD: '칼',\n                        microbit_2_GIRAFFE: '기린',\n                        microbit_2_SKULL: '해골',\n                        microbit_2_UMBRELLA: '우산',\n                        microbit_2_SNAKE: '뱀',\n                        microbit_2_CLOCK1: '1시',\n                        microbit_2_CLOCK2: '2시',\n                        microbit_2_CLOCK3: '3시',\n                        microbit_2_CLOCK4: '4시',\n                        microbit_2_CLOCK5: '5시',\n                        microbit_2_CLOCK6: '6시',\n                        microbit_2_CLOCK7: '7시',\n                        microbit_2_CLOCK8: '8시',\n                        microbit_2_CLOCK9: '9시',\n                        microbit_2_CLOCK10: '10시',\n                        microbit_2_CLOCK11: '11시',\n                        microbit_2_CLOCK12: '12시',\n                        microbit_2_ARROW_N: '북쪽',\n                        microbit_2_ARROW_NE: '북동쪽',\n                        microbit_2_ARROW_E: '동쪽',\n                        microbit_2_ARROW_SE: '남동쪽',\n                        microbit_2_ARROW_S: '남쪽',\n                        microbit_2_ARROW_SW: '남서쪽',\n                        microbit_2_ARROW_W: '서쪽',\n                        microbit_2_ARROW_NW: '북서쪽',\n                    },\n                    Helper: {\n                        microbit2blelite_get_analog: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)',\n                        microbit2blelite_set_analog:\n                            '선택한 핀에 입력한 아날로그 값을 출력합니다. (0 ~ 1023)',\n                        microbit2blelite_get_digital: '선택한 핀의 디지털 값입니다. (0, 1)',\n                        microbit2blelite_set_digital:\n                            '선택한 핀에 입력한 디지털 값을 출력합니다. (0, 1)',\n                        microbit2blelite_screen_toggle: 'LED 기능을 켜거나 끕니다.',\n                        microbit2blelite_set_led: 'X, Y 좌표로 선택한 LED를 선택한 밝기로 켭니다.',\n                        microbit2blelite_get_led: 'X, Y 좌표로 선택한 LED의 밝기 값입니다.',\n                        microbit2blelite_show_preset_image:\n                            'LED에 미리 설정되어 있는 모양을 나타냅니다.',\n                        microbit2blelite_show_custom_image:\n                            '블록에서 선택한 LED를 선택한 밝기로 밝힙니다. 한 번에 모든 LED를 조작할 수 있습니다.',\n                        microbit2blelite_show_string: '입력한 문자열을 LED에 차례대로 밝힙니다.',\n                        microbit2blelite_reset_screen: 'LED를 모두 지우거나 밝힙니다.',\n                        microbit2blelite_radio_toggle: '라디오 기능을 켜거나 끕니다.',\n                        microbit2blelite_radio_setting: '라디오 채널을 입력한 숫자로 바꿉니다.',\n                        microbit2blelite_radio_send: '라디오로 입력한 영문과 숫자를 송신합니다.',\n                        microbit2blelite_radio_received: '라디오로 수신된 값입니다.',\n                        microbit2blelite_speaker_toggle: '스피커 기능을 켜거나 끕니다.',\n                        microbit2blelite_change_tempo:\n                            '연주 속도를 선택한 박자와 BPM으로 정합니다.',\n                        microbit2blelite_set_tone:\n                            '선택한 음을 선택한 박만큼 연주합니다. 1~5옥타브 사이의 음계를 선택할 수 있습니다.',\n                        microbit2blelite_play_preset_music: '미리 설정되어 있는 음악을 연주합니다.',\n                        microbit2blelite_play_sound_effect:\n                            '미리 설정되어 있는 효과음을 연주합니다.',\n                        microbit2blelite_get_btn: \"선택한 버튼이 눌렸다면 '참'으로 판단합니다.\",\n                        microbit2blelite_get_logo: \"로고를 터치했다면 '참'으로 판단합니다.\",\n                        microbit2blelite_get_gesture:\n                            \"선택한 움직임이 감지되면 '참'으로 판단합니다.\",\n                        microbit2blelite_get_acc:\n                            '선택한 버튼이 눌리면 아래에 연결된 블록들을 실행합니다.',\n                        microbit2blelite_btn_event: '%1 %2 버튼을 눌렀을 때',\n                        microbit2blelite_get_direction: '나침반 방향 값입니다. (0~360) ',\n                        microbit2blelite_get_field_strength_axis:\n                            '선택한 축의 자기장 세기 값입니다.',\n                        microbit2blelite_get_light_level: '빛 센서의 값입니다.',\n                        microbit2blelite_get_temperature: '현재 온도 값입니다. (℃)',\n                        microbit2blelite_get_sound_level: '마이크 소리 크기 값입니다.',\n                        microbit2blelite_set_servo:\n                            '선택한 핀에 서보 모터 각도를 입력한 값으로 정합니다.',\n                        microbit2blelite_set_pwm:\n                            '선택한 핀의 서보 펄스폭을 선택한 시간으로 정합니다.',\n                    },\n                    Msgs: {\n                        microbit2blelite_compatible_error:\n                            '마이크로비트 V2에서만 사용할 수 있는 블록입니다.',\n                        microbit2blelite_octave: '옥타브',\n                    },\n                },\n                en: {\n                    template: {\n                        microbit2blelite_get_analog: 'analog read pin %1',\n                        microbit2blelite_set_analog: 'Set analog pin %1 to %2 %3',\n                        microbit2blelite_get_digital: 'digital read pin %1',\n                        microbit2blelite_set_digital: 'digital write pin %1 to %2 %3',\n                        microbit2blelite_screen_toggle: '%1 LED screen %2',\n                        microbit2blelite_set_led: 'Light X: %1 Y:%2 LED to brightness %3 %4',\n                        microbit2blelite_get_led: 'brightness of X: %1 Y: %2 LED %3',\n                        microbit2blelite_show_preset_image: 'Light %1 icon on LED %2',\n                        microbit2blelite_show_custom_image: 'Light %1 on LED %2',\n                        microbit2blelite_show_string: 'Light string %1 on LED %2',\n                        microbit2blelite_reset_screen: '%1 all on LED %2',\n                        microbit2blelite_radio_toggle: '%1 radio %2',\n                        microbit2blelite_radio_setting: 'Change radio channel to %1 %2',\n                        microbit2blelite_radio_send: 'Send %1 to radio %2',\n                        microbit2blelite_radio_received: 'radio received value',\n                        microbit2blelite_speaker_toggle: '%1 speaker %2',\n                        microbit2blelite_change_tempo: 'Set tempo to %2 BPM per %1 beat %3',\n                        microbit2blelite_set_tone: 'Play melody %1 for %2 beat %3',\n                        microbit2blelite_play_preset_music: 'Play music %1 %2',\n                        microbit2blelite_play_sound_effect: 'Play sound %1 %2',\n                        microbit2blelite_get_btn: '%1 button pressed?',\n                        microbit2blelite_get_logo: 'logo touched?',\n                        microbit2blelite_get_gesture: 'Is the movement %1?',\n                        microbit2blelite_get_acc: 'acceleration value of %1',\n                        microbit2blelite_btn_event: '%1 When %2 button pressed',\n                        microbit2blelite_get_direction: 'compass direction',\n                        microbit2blelite_get_field_strength_axis:\n                            'magnetic field strength value of %1 ',\n                        microbit2blelite_get_light_level: 'light sensor value',\n                        microbit2blelite_get_temperature: 'temperature',\n                        microbit2blelite_get_sound_level: 'microphone volume',\n                        microbit2blelite_set_servo: 'Set servo pin %1 angle to %2 %3',\n                        microbit2blelite_set_pwm: 'set servo pin %1 pulse to %2 %3 %4',\n                        microbit2blelite_common_title: 'Common Blocks',\n                        microbit2blelite_v2_title: 'v2 Only',\n                    },\n                    Blocks: {\n                        octave: 'octave',\n                        scalar: 'scalar',\n                        xAxis: 'X-axis',\n                        yAxis: 'Y-axis',\n                        zAxis: 'Z-axis',\n                        up: 'up',\n                        down: 'down',\n                        left: 'left',\n                        right: 'right',\n                        face_up: 'face up',\n                        face_down: 'face down',\n                        freefall: 'freefall',\n                        '3g': '3G',\n                        '6g': '6G',\n                        '8g': '8G',\n                        shake: 'shake',\n                        DADADADUM: 'Dadadadum',\n                        ENTERTAINER: 'Entertainer',\n                        PRELUDE: 'Prelude',\n                        ODE: 'Ode',\n                        NYAN: 'Nyan',\n                        RINGTONE: 'Ringtone',\n                        FUNK: 'Funk',\n                        BLUES: 'Blues',\n                        BIRTHDAY: 'Birthday',\n                        WEDDING: 'Wedding',\n                        FUNERAL: 'Funeral',\n                        PUNCHLINE: 'Punchline',\n                        PYTHON: 'Python',\n                        BADDY: 'Baddy',\n                        CHASE: 'Chase',\n                        BA_DING: 'Coin',\n                        WAWAWAWAA: 'Wawawawaa',\n                        JUMP_UP: 'Jump up',\n                        JUMP_DOWN: 'Jump down',\n                        POWER_UP: 'Power up',\n                        POWER_DOWN: 'Power down',\n                        GIGGLE: 'giggle',\n                        HAPPY: 'happy',\n                        HELLO: 'hello',\n                        MYSTERIOUS: 'mysterious',\n                        SAD: 'sad',\n                        SLIDE: 'slide',\n                        SOARING: 'soaring',\n                        SPRING: 'spring',\n                        TWINKLE: 'twinkle',\n                        YAWN: 'yawn',\n                        plot: 'plot',\n                        unplot: 'unplot',\n                        on: 'Turn on',\n                        off: 'Turn off',\n                        remove: 'Clear',\n                        light: 'Light',\n                        microbit_2_HEART: 'heart',\n                        microbit_2_HEART_SMALL: 'small heart',\n                        microbit_2_HAPPY: 'happy',\n                        microbit_2_SMILE: 'smile',\n                        microbit_2_SAD: 'sad',\n                        microbit_2_CONFUSED: 'confused',\n                        microbit_2_ANGRY: 'angry',\n                        microbit_2_ASLEEP: 'asleep',\n                        microbit_2_SURPRISED: 'surprised',\n                        microbit_2_SILLY: 'silly',\n                        microbit_2_FABULOUS: 'fabulous',\n                        microbit_2_MEH: 'meh',\n                        microbit_2_YES: 'yes',\n                        microbit_2_NO: 'no',\n                        microbit_2_TRIANGLE: 'triangle',\n                        microbit_2_TRIANGLE_LEFT: 'left triangle',\n                        microbit_2_CHESSBOARD: 'chessboard',\n                        microbit_2_DIAMOND: 'diamond',\n                        microbit_2_DIAMOND_SMALL: 'small diamond',\n                        microbit_2_SQUARE: 'square',\n                        microbit_2_SQUARE_SMALL: 'small square',\n                        microbit_2_RABBIT: 'rabbit',\n                        microbit_2_COW: 'cow',\n                        microbit_2_MUSIC_CROTCHET: 'crotchet',\n                        microbit_2_MUSIC_QUAVER: 'quaver',\n                        microbit_2_MUSIC_QUAVERS: 'quavers',\n                        microbit_2_PITCHFORK: 'pitchfork',\n                        microbit_2_XMAS: 'xmas',\n                        microbit_2_PACMAN: 'pacman',\n                        microbit_2_TARGET: 'target',\n                        microbit_2_TSHIRT: 'tshirt',\n                        microbit_2_ROLLERSKATE: 'rollerskate',\n                        microbit_2_DUCK: 'duck',\n                        microbit_2_HOUSE: 'house',\n                        microbit_2_TORTOISE: 'tortoise',\n                        microbit_2_BUTTERFLY: 'butterfly',\n                        microbit_2_STICKFIGURE: 'stickfigure',\n                        microbit_2_GHOST: 'ghost',\n                        microbit_2_SWORD: 'sword',\n                        microbit_2_GIRAFFE: 'giraffe',\n                        microbit_2_SKULL: 'skull',\n                        microbit_2_UMBRELLA: 'umbrella',\n                        microbit_2_SNAKE: 'snake',\n                        microbit_2_CLOCK1: \"1 o'clock\",\n                        microbit_2_CLOCK2: \"2 o'clock\",\n                        microbit_2_CLOCK3: \"3 o'clock\",\n                        microbit_2_CLOCK4: \"4 o'clock\",\n                        microbit_2_CLOCK5: \"5 o'clock\",\n                        microbit_2_CLOCK6: \"6 o'clock\",\n                        microbit_2_CLOCK7: \"7 o'clock\",\n                        microbit_2_CLOCK8: \"8 o'clock\",\n                        microbit_2_CLOCK9: \"9 o'clock\",\n                        microbit_2_CLOCK10: \"10 o'clock\",\n                        microbit_2_CLOCK11: \"11 o'clock\",\n                        microbit_2_CLOCK12: \"12 o'clock\",\n                        microbit_2_ARROW_N: 'north',\n                        microbit_2_ARROW_NE: 'northeast',\n                        microbit_2_ARROW_E: 'east',\n                        microbit_2_ARROW_SE: 'southeast',\n                        microbit_2_ARROW_S: 'south',\n                        microbit_2_ARROW_SW: 'southwest',\n                        microbit_2_ARROW_W: 'west',\n                        microbit_2_ARROW_NW: 'northwest',\n                    },\n                    Helper: {\n                        microbit2blelite_get_analog:\n                            'Reads an analog signal from the pin you choose. (0 ~ 1023)',\n                        microbit2blelite_set_analog:\n                            'Writes an analog signal to the pin you choose. (0 ~ 1023)',\n                        microbit2blelite_get_digital:\n                            'Reads a digital signal from the pin you choose. (0 ~ 1023)',\n                        microbit2blelite_set_digital:\n                            'Writes a digital signal to the pin you choose. (0 ~ 1)',\n                        microbit2blelite_screen_toggle: 'Turns on or turns off the LED screen.',\n                        microbit2blelite_set_led:\n                            'Lights the selected LED with X and Y coordinates to the selected brightness.',\n                        microbit2blelite_get_led:\n                            'Brightness of the selected LED with X and Y coordinates',\n                        microbit2blelite_show_preset_image:\n                            'Lights the selected icon on the LED screen.',\n                        microbit2blelite_show_custom_image:\n                            'Lights the selected LED and brightness. You can set all the LEDs at once.',\n                        microbit2blelite_show_string:\n                            'Lights the entered string in order on the LED screen.',\n                        microbit2blelite_reset_screen: 'Clears or lights all LED screen.',\n                        microbit2blelite_radio_toggle: 'Turns on or turns off the radio.',\n                        microbit2blelite_radio_setting:\n                            'Changes the radio channel to the number entered.',\n                        microbit2blelite_radio_send:\n                            'Sends the number or the string entered to the radio.',\n                        microbit2blelite_radio_received: 'Value received by the radio.',\n                        microbit2blelite_speaker_toggle: 'Turns on or turns off the speaker.',\n                        microbit2blelite_change_tempo:\n                            'Sets the tempo to the entered beat and BPM.',\n                        microbit2blelite_set_tone:\n                            'Plays the entered melody for the entered beat. You can choose a scale between 1 and 5 octaves.',\n                        microbit2blelite_play_preset_music: 'Plays preset music.',\n                        microbit2blelite_play_sound_effect: 'Plays preset sound.',\n                        microbit2blelite_get_btn:\n                            \"If the selected button is pressed, it is judged as 'True'.\",\n                        microbit2blelite_get_logo:\n                            \"If the logo is touched, it is judged as 'True'.\",\n                        microbit2blelite_get_gesture:\n                            \"When the selected movement is detected, it is judged as 'True'.\",\n                        microbit2blelite_get_acc: 'The acceleration value of the selected axis.',\n                        microbit2blelite_btn_event:\n                            'When the selected button is pressed, the connected blocks below will run',\n                        microbit2blelite_get_direction: 'The compass direction value. (0~360)',\n                        microbit2blelite_get_field_strength_axis:\n                            'The magnetic field strength value of the selected axis.',\n                        microbit2blelite_get_light_level: 'The value of the light sensor.',\n                        microbit2blelite_get_temperature: 'The current temperature value. (℃)',\n                        microbit2blelite_get_sound_level: 'The microphone volume value.',\n                        microbit2blelite_set_servo:\n                            'Sets the servo motor angle to the entered value on the selected pin.',\n                        microbit2blelite_set_pwm:\n                            'Sets the servo pulse to the entered time on the selected pin.',\n                    },\n                    Msgs: {\n                        microbit2blelite_compatible_error:\n                            'The corresponding block is not compatible to Microbit V1',\n                        microbit2blelite_octave: 'Octave',\n                    },\n                },\n                jp: {\n                    template: {\n                        microbit2blelite_get_analog: 'ピン %1 のアナログ値',\n                        microbit2blelite_set_analog: 'ピン %1 にアナログ値 %2 を出力する %3',\n                        microbit2blelite_get_digital: 'ピン %1 のデジタル値',\n                        microbit2blelite_set_digital: 'ピン %1 に デジタル値 %2 を出力する %3',\n                        microbit2blelite_screen_toggle: 'LED機能を %1 %2',\n                        microbit2blelite_set_led: 'LEDの X: %1 Y: %2 を明るさ %3 にする %4',\n                        microbit2blelite_get_led: 'LEDの X: %1 Y: %2 の明るさ',\n                        microbit2blelite_show_preset_image: 'LEDに %1 アイコンを表示する %2',\n                        microbit2blelite_show_custom_image: 'LED %1 を表示する %2',\n                        microbit2blelite_show_string: 'LEDに %1 を表示する %2',\n                        microbit2blelite_reset_screen: 'LEDを全部消す %1',\n                        microbit2blelite_radio_toggle: 'ラジオ機能を %1 %2',\n                        microbit2blelite_radio_setting: 'ラジオチャンネルを %1 に変更する %2',\n                        microbit2blelite_radio_send: 'ラジオに %1 送信する %2',\n                        microbit2blelite_radio_received: 'ラジオ受信値',\n                        microbit2blelite_speaker_toggle: 'スピーカー機能 %1 %2',\n                        microbit2blelite_change_tempo: 'テンポを %1 拍に %2 BPMにする %3',\n                        microbit2blelite_set_tone: '%1 音を %2 拍演奏する %3',\n                        microbit2blelite_play_preset_music: '%1 音楽を演奏する %2',\n                        microbit2blelite_play_sound_effect: '%1 効果音を演奏する %2',\n                        microbit2blelite_get_btn: '%1 ボタンが押したkか?',\n                        microbit2blelite_get_logo: 'ロゴをタッチしたじか?',\n                        microbit2blelite_get_gesture: '動きが %1 なのか?',\n                        microbit2blelite_get_acc: '%1 の加速度',\n                        microbit2blelite_get_direction: 'コンパス方向',\n                        microbit2blelite_get_field_strength_axis: '%1 の磁場強度',\n                        microbit2blelite_get_light_level: '光センサー値',\n                        microbit2blelite_get_temperature: '温度値',\n                        microbit2blelite_get_sound_level: 'マイク音の大きさ',\n                        microbit2blelite_set_servo:\n                            'ピン %1 に サーボモーターの角度を %2 に設定する %3',\n                        microbit2blelite_set_pwm: 'ピン %1 にサーボパルス幅を2にする %4',\n                        microbit2blelite_common_title: 'Common Blocks',\n                        microbit2blelite_v2_title: 'v2 Only',\n                    },\n                    Blocks: {\n                        octave: 'オクターブ',\n                        scalar: 'スカラー',\n                        xAxis: 'X軸',\n                        yAxis: 'Y軸',\n                        zAxis: 'Z軸',\n                        up: '上',\n                        down: '下',\n                        left: '右',\n                        right: '左',\n                        face_up: '全面',\n                        face_down: '後面',\n                        freefall: '自由落下',\n                        '3g': '3G',\n                        '6g': '6G',\n                        '8g': '8G',\n                        shake: '振れ',\n                        DADADADUM: '運命交響曲',\n                        ENTERTAINER: 'エンターネーター',\n                        PRELUDE: 'バッハ·プレリュード第1番',\n                        ODE: '合唱交響曲',\n                        NYAN: 'ニャンキャット',\n                        RINGTONE: '着信メロディ',\n                        FUNK: 'ファンク',\n                        BLUES: 'ブルース',\n                        BIRTHDAY: 'お誕生日おめでとう',\n                        WEDDING: '結婚行進曲',\n                        FUNERAL: '葬式の歌',\n                        PUNCHLINE: 'パンチライン',\n                        PYTHON: 'サーカス',\n                        BADDY: '悪党',\n                        CHASE: '追撃戦',\n                        BA_DING: 'コインGET',\n                        WAWAWAWAA: 'ガッカリ',\n                        JUMP_UP: '上にジャンプ',\n                        JUMP_DOWN: '下にジャンプ',\n                        POWER_UP: '点ける',\n                        POWER_DOWN: '消す',\n                        GIGGLE: '笑い',\n                        HAPPY: '幸せ',\n                        HELLO: '挨拶',\n                        MYSTERIOUS: '神秘的',\n                        SAD: '悲しみ',\n                        SLIDE: 'スライド',\n                        SOARING: '上昇',\n                        SPRING: '春',\n                        TWINKLE: 'キラキラ',\n                        YAWN: 'あくび',\n                        plot: 'オンにする',\n                        unplot: 'オフにする',\n                        on: 'オンにする',\n                        off: 'オフにする',\n                        microbit_2_HEART: 'ハート',\n                        microbit_2_HEART_SMALL: '小さなハート',\n                        microbit_2_HAPPY: '幸せ',\n                        microbit_2_SMILE: '笑い',\n                        microbit_2_SAD: '悲しみ',\n                        microbit_2_CONFUSED: '混乱',\n                        microbit_2_ANGRY: '怒り',\n                        microbit_2_ASLEEP: '眠気',\n                        microbit_2_SURPRISED: '驚き',\n                        microbit_2_SILLY: '間抜け',\n                        microbit_2_FABULOUS: '幻想的な',\n                        microbit_2_MEH: '別に',\n                        microbit_2_YES: 'イエス',\n                        microbit_2_NO: 'ノー',\n                        microbit_2_TRIANGLE: '三角形',\n                        microbit_2_TRIANGLE_LEFT: '左三角形',\n                        microbit_2_CHESSBOARD: 'チェスパン',\n                        microbit_2_DIAMOND: 'ダイヤモンド',\n                        microbit_2_DIAMOND_SMALL: '小さなダイヤモンド',\n                        microbit_2_SQUARE: '四角形',\n                        microbit_2_SQUARE_SMALL: '小さな四角形',\n                        microbit_2_RABBIT: 'ウサギ',\n                        microbit_2_COW: '牛',\n                        microbit_2_MUSIC_CROTCHET: '4分音符',\n                        microbit_2_MUSIC_QUAVER: '8分音符',\n                        microbit_2_MUSIC_QUAVERS: '8分音符2個',\n                        microbit_2_PITCHFORK: 'フォーク',\n                        microbit_2_XMAS: 'クリスマスツリー',\n                        microbit_2_PACMAN: 'パックマン',\n                        microbit_2_TARGET: '標的',\n                        microbit_2_TSHIRT: 'Tシャツ',\n                        microbit_2_ROLLERSKATE: 'ローラースケート',\n                        microbit_2_DUCK: 'アヒル',\n                        microbit_2_HOUSE: '家',\n                        microbit_2_TORTOISE: '亀',\n                        microbit_2_BUTTERFLY: '蝶',\n                        microbit_2_STICKFIGURE: 'スティックマン',\n                        microbit_2_GHOST: '幽霊',\n                        microbit_2_SWORD: 'ナイフ',\n                        microbit_2_GIRAFFE: 'キリン',\n                        microbit_2_SKULL: '骸骨',\n                        microbit_2_UMBRELLA: '傘',\n                        microbit_2_SNAKE: '蛇',\n                        microbit_2_CLOCK1: '1時',\n                        microbit_2_CLOCK2: '2時',\n                        microbit_2_CLOCK3: '3時',\n                        microbit_2_CLOCK4: '4時',\n                        microbit_2_CLOCK5: '5時',\n                        microbit_2_CLOCK6: '6時',\n                        microbit_2_CLOCK7: '7時',\n                        microbit_2_CLOCK8: '8時',\n                        microbit_2_CLOCK9: '9時',\n                        microbit_2_CLOCK10: '10時',\n                        microbit_2_CLOCK11: '11時',\n                        microbit_2_CLOCK12: '12時',\n                        microbit_2_ARROW_N: '北',\n                        microbit_2_ARROW_NE: '北東',\n                        microbit_2_ARROW_E: '東',\n                        microbit_2_ARROW_SE: '南東',\n                        microbit_2_ARROW_S: '南',\n                        microbit_2_ARROW_SW: '南西',\n                        microbit_2_ARROW_W: '西',\n                        microbit_2_ARROW_NW: '北西',\n                    },\n                    Helper: {\n                        microbit2blelite_get_analog: '選択したピンのアナログ値です。(0 ~ 1023)',\n                        microbit2blelite_set_analog:\n                            '選択したピンに入力したアナログ値を出力します。(0 ~ 1023)',\n                        microbit2blelite_get_digital: '選択したピンのデジタル値です。(0, 1)',\n                        microbit2blelite_set_digital:\n                            '選択したピンに入力したデジタル値を出力します。(0, 1)',\n                        microbit2blelite_screen_toggle: 'LED機能をオンまたはオフにします。',\n                        microbit2blelite_set_led:\n                            'X、Y座標で選択したLEDを選択した明るさで点けます。',\n                        microbit2blelite_get_led: 'X、Y座標で選択したLEDの明るさです。',\n                        microbit2blelite_show_preset_image: 'LEDに先に設定されていた形で点けます。',\n                        microbit2blelite_show_custom_image:\n                            'ブロックで選択したLEDを選択した明るさで点けます。 一度にすべてのLEDを操作できます。',\n                        microbit2blelite_show_string: '入力した文字列をLEDに順番に表示します。',\n                        microbit2blelite_reset_screen: 'LEDに表示したものをすべて消します。',\n                        microbit2blelite_radio_toggle: 'ラジオ機能をオンまたはオフにします。',\n                        microbit2blelite_radio_setting:\n                            'ラジオチャンネルを入力した数字に変えます。',\n                        microbit2blelite_radio_send: 'ラジオで入力した英数字を送信します。',\n                        microbit2blelite_radio_received: 'ラジオで受信した値です。',\n                        microbit2blelite_speaker_toggle: 'スピーカー機能をオンまたはオフにします。',\n                        microbit2blelite_change_tempo: 'テンポを選択した拍子とBPMで設定します。',\n                        microbit2blelite_set_tone:\n                            '選択した音を選択した拍子で演奏します。 1~5オクターブ間の音階を選べます。',\n                        microbit2blelite_play_preset_music: '先に設定されていた音楽を演奏します。',\n                        microbit2blelite_play_sound_effect:\n                            '先に設定されていた効果音を演奏します。',\n                        microbit2blelite_get_btn:\n                            '選択したボタンが押されたら、「True」と判断します。',\n                        microbit2blelite_get_logo: 'ロゴをタッチすると、「True」と判断します。',\n                        microbit2blelite_get_gesture:\n                            '選択した動きを感知したら、「True」と判断します。',\n                        microbit2blelite_get_acc: '選択した軸の加速度値です。',\n                        microbit2blelite_get_direction: 'コンパス方向の値です。 (0~360)',\n                        microbit2blelite_get_field_strength_axis: '選択した軸の磁場強度の値です。',\n                        microbit2blelite_get_light_level: '光センサーの値です。',\n                        microbit2blelite_get_temperature: '現在の温度です。 (℃)',\n                        microbit2blelite_get_sound_level: 'マイクボリュームの値です。',\n                        microbit2blelite_set_servo:\n                            '選択したピンにサーボモーターの角度を入力した値で設定します。',\n                        microbit2blelite_set_pwm:\n                            '選択したピンのサーボパルス幅を選択した値にします。',\n                    },\n                    Msgs: {\n                        microbit2blelite_compatible_error:\n                            '対応するブロックはMicrobitV1と互換性がありません',\n                        microbit2blelite_octave: 'Octave',\n                    },\n                },\n            };\n        }\n\n        getBlocks = function () {\n            return {\n                microbit2blelite_common_title: {\n                    skeleton: 'basic_text',\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    template: '%1',\n                    fontColor: '#333333',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.microbit2blelite_common_title,\n                            color: '#333333',\n                            align: 'center',\n                        },\n                    ],\n                    def: {\n                        type: 'microbit2blelite_common_title',\n                    },\n                    class: 'microbit2bleliteLed',\n                    isNotFor: ['Microbit2BleLite'],\n                    events: {},\n                },\n\n                microbit2blelite_get_analog: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.analogPins,\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2blelitePin',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_analog',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = script.getValue('VALUE');\n                        // const pinData = await this.services.IoPinService.readPinData();\n                        // const ad = await this.services.IoPinService.getAdConfiguration();\n                        // const config = await this.services.IoPinService.getIoConfiguration();\n\n                        // console.log(pinData);\n                        // console.log(ad);\n                        // console.log(config);\n                    },\n                },\n                microbit2blelite_set_analog: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.analogPins,\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2blelitePin',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_set_analog',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const pin = script.getValue('PIN');\n                        const value = Math.round(_clamp(script.getNumberValue('VALUE'), 0, 1023));\n\n                        const parsedPayload = `${pin};${value}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_ANALOG};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_get_digital: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.digitalPins,\n                            value: 8,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2blelitePin',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_digital',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        const value = script.getValue('VALUE');\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_DIGITAL};${value}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_set_digital: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.digitalPins,\n                            value: 8,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [0, 0],\n                                [1, 1],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2blelitePin',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_set_digital',\n                    },\n                    paramsKeyMap: { PIN: 0, VALUE: 1 },\n                    func: async (sprite, script) => {\n                        const pin = script.getValue('PIN');\n                        const value = script.getValue('VALUE');\n                        const parsedPayload = `${pin};${value}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_DIGITAL};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_screen_toggle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.on, this.functionKeys.DISPLAY_ON],\n                                [Lang.Blocks.off, this.functionKeys.DISPLAY_OFF],\n                            ],\n                            value: this.functionKeys.DISPLAY_ON,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteLed',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_screen_toggle',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        const command = script.getField('VALUE');\n                        if (command === this.functionKeys.DISPLAY_ON) {\n                            await this.services.LedService.writeMatrixState(this.ledState);\n                        } else {\n                            await this.services.LedService.writeMatrixState(getInitialLedState());\n                        }\n                    },\n                },\n                microbit2blelite_set_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 0,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 0,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 9,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteLed',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['9'],\n                            },\n                        ],\n                        type: 'microbit2blelite_set_led',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        VALUE: 2,\n                    },\n                    func: async (sprite, script) => {\n                        const value = script.getNumberValue('VALUE');\n                        const x = script.getNumberValue('X');\n                        const y = script.getNumberValue('Y');\n                        if (x < 0 || y < 0 || x > 4 || y > 4 || value < 0 || value > 9) {\n                            return;\n                        }\n                        this.ledState[y][x] = value !== 0;\n                        await this.services.LedService.writeMatrixState(this.ledState);\n                    },\n                },\n                microbit2blelite_get_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 0,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 0,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteLed',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['0'],\n                            },\n                        ],\n                        type: 'microbit2blelite_get_led',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const x = script.getNumberValue('X');\n                        const y = script.getNumberValue('Y');\n                        if (x < 0 || y < 0 || x > 4 || y > 4) {\n                            return -1;\n                        }\n\n                        // TODO: 블록스펙 변경과 함께 true, false 처리\n                        const deviceLedState = await this.services.LedService.readMatrixState();\n                        const targetLed = deviceLedState[y][x] ? 1 : 0;\n                        return targetLed;\n                    },\n                },\n                microbit2blelite_show_preset_image: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.microbit_2_HEART, 0],\n                                [Lang.Blocks.microbit_2_HEART_SMALL, 1],\n                                [Lang.Blocks.microbit_2_HAPPY, 2],\n                                [Lang.Blocks.microbit_2_SMILE, 3],\n                                [Lang.Blocks.microbit_2_SAD, 4],\n                                [Lang.Blocks.microbit_2_CONFUSED, 5],\n                                [Lang.Blocks.microbit_2_ANGRY, 6],\n                                [Lang.Blocks.microbit_2_ASLEEP, 7],\n                                [Lang.Blocks.microbit_2_SURPRISED, 8],\n                                [Lang.Blocks.microbit_2_SILLY, 9],\n                                [Lang.Blocks.microbit_2_FABULOUS, 10],\n                                [Lang.Blocks.microbit_2_MEH, 11],\n                                [Lang.Blocks.microbit_2_YES, 12],\n                                [Lang.Blocks.microbit_2_NO, 13],\n                                [Lang.Blocks.microbit_2_TRIANGLE, 34],\n                                [Lang.Blocks.microbit_2_TRIANGLE_LEFT, 35],\n                                [Lang.Blocks.microbit_2_CHESSBOARD, 36],\n                                [Lang.Blocks.microbit_2_DIAMOND, 37],\n                                [Lang.Blocks.microbit_2_DIAMOND_SMALL, 38],\n                                [Lang.Blocks.microbit_2_SQUARE, 39],\n                                [Lang.Blocks.microbit_2_SQUARE_SMALL, 40],\n                                [Lang.Blocks.microbit_2_RABBIT, 41],\n                                [Lang.Blocks.microbit_2_COW, 42],\n                                [Lang.Blocks.microbit_2_MUSIC_CROTCHET, 43],\n                                [Lang.Blocks.microbit_2_MUSIC_QUAVER, 44],\n                                [Lang.Blocks.microbit_2_MUSIC_QUAVERS, 45],\n                                [Lang.Blocks.microbit_2_PITCHFORK, 46],\n                                [Lang.Blocks.microbit_2_XMAS, 47],\n                                [Lang.Blocks.microbit_2_PACMAN, 48],\n                                [Lang.Blocks.microbit_2_TARGET, 49],\n                                [Lang.Blocks.microbit_2_TSHIRT, 50],\n                                [Lang.Blocks.microbit_2_ROLLERSKATE, 51],\n                                [Lang.Blocks.microbit_2_DUCK, 52],\n                                [Lang.Blocks.microbit_2_HOUSE, 53],\n                                [Lang.Blocks.microbit_2_TORTOISE, 54],\n                                [Lang.Blocks.microbit_2_BUTTERFLY, 55],\n                                [Lang.Blocks.microbit_2_STICKFIGURE, 56],\n                                [Lang.Blocks.microbit_2_GHOST, 57],\n                                [Lang.Blocks.microbit_2_SWORD, 58],\n                                [Lang.Blocks.microbit_2_GIRAFFE, 59],\n                                [Lang.Blocks.microbit_2_SKULL, 60],\n                                [Lang.Blocks.microbit_2_UMBRELLA, 61],\n                                [Lang.Blocks.microbit_2_SNAKE, 62],\n                                [Lang.Blocks.microbit_2_CLOCK1, 14],\n                                [Lang.Blocks.microbit_2_CLOCK2, 15],\n                                [Lang.Blocks.microbit_2_CLOCK3, 16],\n                                [Lang.Blocks.microbit_2_CLOCK4, 17],\n                                [Lang.Blocks.microbit_2_CLOCK5, 18],\n                                [Lang.Blocks.microbit_2_CLOCK6, 19],\n                                [Lang.Blocks.microbit_2_CLOCK7, 20],\n                                [Lang.Blocks.microbit_2_CLOCK8, 21],\n                                [Lang.Blocks.microbit_2_CLOCK9, 22],\n                                [Lang.Blocks.microbit_2_CLOCK10, 23],\n                                [Lang.Blocks.microbit_2_CLOCK11, 24],\n                                [Lang.Blocks.microbit_2_CLOCK12, 25],\n                                [Lang.Blocks.microbit_2_ARROW_N, 26],\n                                [Lang.Blocks.microbit_2_ARROW_NE, 27],\n                                [Lang.Blocks.microbit_2_ARROW_E, 28],\n                                [Lang.Blocks.microbit_2_ARROW_SE, 29],\n                                [Lang.Blocks.microbit_2_ARROW_S, 30],\n                                [Lang.Blocks.microbit_2_ARROW_SW, 31],\n                                [Lang.Blocks.microbit_2_ARROW_W, 32],\n                                [Lang.Blocks.microbit_2_ARROW_NW, 33],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteLed',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_show_preset_image',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = _clamp(script.getNumberValue('VALUE'), 0, 62);\n                        const presetImage = this.presetImage[value];\n                        this.ledState = convertPresetImageToLedState(presetImage);\n\n                        await this.services.LedService.writeMatrixState(this.ledState);\n                    },\n                },\n                microbit2blelite_show_custom_image: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Led2',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteLed',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_show_custom_image',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = script.getField('VALUE');\n                        const processedValue = [];\n                        for (const i in value) {\n                            processedValue[i] = value[i].join();\n                        }\n                        const parsedPayload = `${processedValue.join(':').replace(/,/gi, '')}`;\n                        this.ledState = convertPresetImageToLedState(parsedPayload);\n\n                        await this.services.LedService.writeMatrixState(this.ledState);\n                    },\n                },\n                microbit2blelite_show_string: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteLed',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['Hello!'],\n                                accept: 'string',\n                            },\n                        ],\n                        type: 'microbit2blelite_show_string',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const payload = script.getStringValue('VALUE');\n                        const text = payload.replace(\n                            /[^A-Za-z0-9_\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\\\\\{\\}\\[\\]\\'\\\"\\;\\:\\<\\,\\>\\.\\?\\/\\s]/gim,\n                            ''\n                        );\n                        await this.services.LedService.writeText(text);\n                    },\n                },\n                microbit2blelite_reset_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.remove, 'remove'],\n                                [Lang.Blocks.light, 'light'],\n                            ],\n                            value: 'remove',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteLed',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_reset_screen',\n                    },\n                    paramsKeyMap: { LED_STATUS: 0 },\n                    func: async (sprite, script) => {\n                        const ledStatus = script.getField('LED_STATUS');\n                        if (ledStatus === 'light') {\n                            const defaultLed = '99999:99999:99999:99999:99999';\n                            this.ledState = convertPresetImageToLedState(defaultLed);\n                        } else {\n                            this.ledState = getInitialLedState();\n                        }\n                        await this.services.LedService.writeMatrixState(this.ledState);\n                    },\n                },\n                microbit2blelite_radio_toggle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.on, this.functionKeys.RADIO_ON],\n                                [Lang.Blocks.off, this.functionKeys.RADIO_OFF],\n                            ],\n                            value: this.functionKeys.RADIO_ON,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteRadio',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_radio_toggle',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        const command = script.getField('VALUE');\n\n                        const response = await this.getResponseWithSync(`${command};`);\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_radio_setting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 7,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteRadio',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_radio_setting',\n                    },\n                    paramsKeyMap: { RATE: 0, CHANNEL: 1 },\n                    func: async (sprite, script) => {\n                        if (!Entry.Utils.isNumber(script.getNumberValue('CHANNEL'))) {\n                            return;\n                        }\n                        const channel = Math.round(_clamp(script.getNumberValue('CHANNEL'), 0, 83));\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SETTING_RADIO};${channel}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_radio_send: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteRadio',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_radio_send',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        const value = script.getStringValue('VALUE');\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_RADIO};${value}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_radio_received: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2bleliteRadio',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_radio_received',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_RADIO};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_change_tempo: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteSound',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['4'],\n                            },\n                            {\n                                type: 'text',\n                                params: ['120'],\n                            },\n                        ],\n                        type: 'microbit2blelite_change_tempo',\n                    },\n                    paramsKeyMap: {\n                        BEAT: 0,\n                        BPM: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const beat = Math.round(_clamp(script.getNumberValue('BEAT'), 0, 4));\n                        const bpm = Math.round(_clamp(script.getNumberValue('BPM'), 1, 230));\n\n                        const parsedPayload = `${beat};${bpm}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.CHANGE_TEMPO};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_set_tone: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'MusicScale',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['4', 16],\n                                ['2', 8],\n                                ['1', 4],\n                                ['1/2', 2],\n                                ['1/4', 1],\n                            ],\n                            value: 4,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteSound',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_set_tone',\n                    },\n                    paramsKeyMap: {\n                        SCALE: 0,\n                        NOTE: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const scale = script.getField('SCALE');\n                        const note = script.getField('NOTE');\n                        const parsedPayload = `${scale}:${note}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.PLAY_TONE};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_play_preset_music: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.DADADADUM, 0],\n                                [Lang.Blocks.ENTERTAINER, 1],\n                                [Lang.Blocks.PRELUDE, 2],\n                                [Lang.Blocks.ODE, 3],\n                                [Lang.Blocks.NYAN, 4],\n                                [Lang.Blocks.RINGTONE, 5],\n                                [Lang.Blocks.FUNK, 6],\n                                [Lang.Blocks.BLUES, 7],\n                                [Lang.Blocks.BIRTHDAY, 8],\n                                [Lang.Blocks.WEDDING, 9],\n                                [Lang.Blocks.FUNERAL, 10],\n                                [Lang.Blocks.PUNCHLINE, 11],\n                                [Lang.Blocks.PYTHON, 12],\n                                [Lang.Blocks.BADDY, 13],\n                                [Lang.Blocks.CHASE, 14],\n                                [Lang.Blocks.BA_DING, 15],\n                                [Lang.Blocks.WAWAWAWAA, 16],\n                                [Lang.Blocks.JUMP_UP, 17],\n                                [Lang.Blocks.JUMP_DOWN, 18],\n                                [Lang.Blocks.POWER_UP, 19],\n                                [Lang.Blocks.POWER_DOWN, 20],\n                            ],\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteSound',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_play_preset_music',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = _clamp(script.getNumberValue('VALUE'), 0, 20);\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.PLAY_MELODY};${value}`\n                        );\n                        this.getResponse(response);\n                        return new Promise((resolve, reject) => {\n                            this.waitMilliSec(500, resolve);\n                        });\n                    },\n                },\n\n                microbit2blelite_get_btn: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['A', 'a'],\n                                ['B', 'b'],\n                                ['A+B', 'ab'],\n                            ],\n                            value: 'a',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteSensor',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_btn',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = script.getField('VALUE');\n\n                        if (value === 'ab') {\n                            return this.pressedBothButton() ? 1 : 0;\n                        } else {\n                            return this.buttonState[value];\n                        }\n                    },\n                },\n                microbit2blelite_btn_event: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_event',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/start_icon_hardwarelite.svg',\n                            size: 14,\n                            position: { x: 0, y: -2 },\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['A', '1'],\n                                ['B', '2'],\n                                ['A+B', '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        type: 'microbit2blelite_btn_event',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 1,\n                    },\n                    class: 'microbit2blelitev2',\n                    isNotFor: ['Microbit2BleLite'],\n                    event: 'microbit2blelite_btn_pressed',\n                    func: (sprite, script) => script.callReturn(),\n                },\n                microbit2blelite_get_acc: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.xAxis, 'x'],\n                                [Lang.Blocks.yAxis, 'y'],\n                                [Lang.Blocks.zAxis, 'z'],\n                                [Lang.Blocks.scalar, 'mag'],\n                            ],\n                            value: 'x',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteSensor',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_acc',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const axis = script.getField('AXIS');\n                        // eslint-disable-next-line max-len\n                        const deviceAccData =\n                            await this.services.AccelerometerService.readAccelerometerData();\n                        if (axis === 'mag') {\n                            return deviceAccData.x + deviceAccData.y + deviceAccData.z;\n                        } else {\n                            return deviceAccData[axis];\n                        }\n                    },\n                },\n                microbit2blelite_get_gesture: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.up, 'up'],\n                                [Lang.Blocks.down, 'down'],\n                                [Lang.Blocks.left, 'left'],\n                                [Lang.Blocks.right, 'right'],\n                                [Lang.Blocks.face_up, 'face up'],\n                                [Lang.Blocks.face_down, 'face down'],\n                                [Lang.Blocks.freefall, 'freefall'],\n                                [Lang.Blocks['3g'], '3g'],\n                                [Lang.Blocks['6g'], '6g'],\n                                [Lang.Blocks['8g'], '8g'],\n                                [Lang.Blocks['shake'], 'shake'],\n                            ],\n                            value: 'up',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteSensor',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_gesture',\n                    },\n                    paramsKeyMap: { GESTURE: 0 },\n                    func: async (sprite, script) => {\n                        const gesture = script.getField('GESTURE');\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_GESTURE};`\n                        );\n                        const parsedResponse = this.getResponse(response);\n\n                        if (gesture === parsedResponse[1]) {\n                            return true;\n                        }\n                        return false;\n                    },\n                },\n                microbit2blelite_get_direction: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2bleliteSensor',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_direction',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_DIRECTION};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_get_field_strength_axis: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.xAxis, 'x'],\n                                [Lang.Blocks.yAxis, 'y'],\n                                [Lang.Blocks.zAxis, 'z'],\n                                [Lang.Blocks.scalar, 'mag'],\n                            ],\n                            value: 'x',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteSensor',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_field_strength_axis',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const axis = script.getField('AXIS');\n                        // eslint-disable-next-line max-len\n                        const deviceMagnetData =\n                            await this.services.MagnetometerService.readMagnetometerData();\n                        if (axis === 'mag') {\n                            return deviceMagnetData.x + deviceMagnetData.y + deviceMagnetData.z;\n                        } else {\n                            return deviceMagnetData[axis];\n                        }\n                    },\n                },\n                microbit2blelite_get_light_level: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2bleliteSensor',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_light_level',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_LIGHT_LEVEL};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_get_temperature: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2bleliteSensor',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_temperature',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        // eslint-disable-next-line max-len\n                        const temperature =\n                            await this.services.TemperatureService.readTemperature();\n                        return temperature;\n                    },\n                },\n\n                microbit2blelite_set_servo: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.majorPins,\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteServo',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_set_servo',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                    },\n                    func: async (sprite, script) => {\n                        const pin = script.getValue('PIN');\n                        const value = Math.round(_clamp(script.getNumberValue('VALUE'), 0, 180));\n\n                        const parsedPayload = `${pin};${value}`;\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.SET_SERVO_ANGLE};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_set_pwm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: this.analogPins,\n                            value: 0,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['ms', 'milli'],\n                                ['µs', 'micro'],\n                            ],\n                            value: 'milli',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2bleliteServo',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_set_pwm',\n                    },\n                    paramsKeyMap: {\n                        PIN: 0,\n                        VALUE: 1,\n                        UNIT: 2,\n                    },\n                    func: async (sprite, script) => {\n                        const pin = script.getValue('PIN');\n                        const unit = script.getValue('UNIT');\n                        const value = Math.round(_clamp(script.getNumberValue('VALUE'), 0, 1023));\n                        const command =\n                            unit === 'milli'\n                                ? this.functionKeys.SET_SERVO_MILLI\n                                : this.functionKeys.SET_SERVO_MICRO;\n\n                        const parsedPayload = `${pin};${value}`;\n                        const response = await this.getResponseWithSync(\n                            `${command};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n\n                microbit2blelite_v2_title: {\n                    skeleton: 'basic_text',\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#333333',\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.microbit2blelite_v2_title,\n                            color: '#333333',\n                            align: 'center',\n                        },\n                    ],\n                    def: {\n                        type: 'microbit2blelite_v2_title',\n                    },\n                    class: 'microbit2blelitev2',\n                    isNotFor: ['Microbit2BleLite'],\n                    events: {},\n                },\n                microbit2blelite_get_logo: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2blelitev2',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_logo',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        if (this.version === '1') {\n                            throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                                Lang.Msgs.microbit2blelite_compatible_error,\n                            ]);\n                        }\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_LOGO};`\n                        );\n                        const parsedResponse = this.getResponse(response);\n                        if (parsedResponse == '1') {\n                            return 1;\n                        } else {\n                            return 0;\n                        }\n                    },\n                },\n                microbit2blelite_get_sound_level: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    class: 'microbit2blelitev2',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_get_sound_level',\n                    },\n                    paramsKeyMap: {},\n                    func: async (sprite, script) => {\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.GET_SOUND_LEVEL};`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_speaker_toggle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.on, this.functionKeys.SPEAKER_ON],\n                                [Lang.Blocks.off, this.functionKeys.SPEAKER_OFF],\n                            ],\n                            value: this.functionKeys.SPEAKER_ON,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2blelitev2',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_speaker_toggle',\n                    },\n                    paramsKeyMap: { VALUE: 0 },\n                    func: async (sprite, script) => {\n                        if (this.version === '1') {\n                            throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                                Lang.Msgs.microbit2_compatible_error,\n                            ]);\n                        }\n                        const command = script.getField('VALUE');\n                        const response = await this.getResponseWithSync(`${command};`);\n                        return this.getResponse(response);\n                    },\n                },\n                microbit2blelite_play_sound_effect: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.GIGGLE, 21],\n                                [Lang.Blocks.HAPPY, 22],\n                                [Lang.Blocks.HELLO, 23],\n                                [Lang.Blocks.MYSTERIOUS, 24],\n                                [Lang.Blocks.SAD, 25],\n                                [Lang.Blocks.SLIDE, 26],\n                                [Lang.Blocks.SOARING, 27],\n                                [Lang.Blocks.SPRING, 28],\n                                [Lang.Blocks.TWINKLE, 29],\n                                [Lang.Blocks.YAWN, 30],\n                            ],\n                            value: 21,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    class: 'microbit2blelitev2',\n                    isNotFor: ['Microbit2BleLite'],\n                    def: {\n                        type: 'microbit2blelite_play_sound_effect',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func: async (sprite, script) => {\n                        const value = _clamp(script.getNumberValue('VALUE'), 21, 30);\n                        const parsedPayload = `${value}`;\n\n                        const response = await this.getResponseWithSync(\n                            `${this.functionKeys.PLAY_SOUND};${parsedPayload}`\n                        );\n                        return this.getResponse(response);\n                    },\n                },\n            };\n        };\n    })();\n})();\n\nmodule.exports = Entry.Microbit2BleLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_neo_cannon_lite.js",
    "content": "'use strict';\n\n(function () {\n    Entry.NeoCannonLite = new (class NeoCannonLite {\n        constructor() {\n            this.id = '410201';\n            this.name = 'NeoCannonLite';\n            this.url = 'http://www.neo3ds.com/';\n            this.imageName = 'neocannonlite.png';\n            this.title = {\n                ko: '네오캐논',\n                en: 'NeoCannon',\n            };\n            this.duration = 32;\n            this.blockMenuBlocks = [\n                'neocannonlite_get_vibe_value',\n                'neocannonlite_set_tone',\n                'neocannonlite_motor_state',\n                'neocannonlite_motor_state_secs',\n                'neocannonlite_motor_stop',\n                'neocannonlite_shoot_reload',\n                'neocannonlite_shoot_reload_secs',\n                'neocannonlite_shoot_catch',\n                'neocannonlite_shoot_shooting',\n                'neocannonlite_shoot_stop',\n                'neocannonlite_angle_state',\n                'neocannonlite_angle_state_secs',\n                'neocannonlite_rgb_led_select_state',\n                'neocannonlite_rgb_led_select_pwm',\n                'neocannonlite_rgb_led_color_picker',\n                'neocannonlite_rgb_led_pwm',\n                'neocannonlite_rgb_led_off',\n                'neocannonlite_neopixel_color_picker',\n                'neocannonlite_neopixel_color_picker_all_on',\n                'neocannonlite_neopixel',\n                'neocannonlite_neopixel_all_on',\n                'neocannonlite_neopixel_all_off',\n            ];\n            this.portData = {\n                baudRate: 115200,\n                duration: 32,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n            };\n            this.__toneTable = {\n                0: 0,\n                C: 1,\n                CS: 2,\n                D: 3,\n                DS: 4,\n                E: 5,\n                F: 6,\n                FS: 7,\n                G: 8,\n                GS: 9,\n                A: 10,\n                AS: 11,\n                B: 12,\n            };\n            this.__toneMap = {\n                1: [33, 65, 131, 262, 523, 1046, 2093, 4186],\n                2: [35, 69, 139, 277, 554, 1109, 2217, 4435],\n                3: [37, 73, 147, 294, 587, 1175, 2349, 4699],\n                4: [39, 78, 156, 310, 622, 1245, 2637, 4978],\n                5: [41, 82, 165, 330, 659, 1319, 2794, 5274],\n                6: [44, 87, 175, 349, 698, 1397, 2849, 5588],\n                7: [46, 92, 185, 370, 740, 1480, 2960, 5920],\n                8: [49, 98, 196, 392, 784, 1568, 3136, 6272],\n                9: [52, 104, 208, 415, 831, 1661, 3322, 6645],\n                10: [55, 110, 220, 440, 880, 1760, 3520, 7040],\n                11: [58, 117, 233, 466, 932, 1865, 3729, 7459],\n                12: [62, 123, 247, 494, 988, 1976, 3951, 7902],\n            };\n            this.setZero();\n        }\n\n        get monitorTemplate() {\n            return {\n                imgPath: 'hw_lite/neocannonlite.png',\n                width: 256,\n                height: 256,\n                listPorts: {\n                    VIBE: {\n                        name: '진동센서',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                },\n                mode: 'both',\n            };\n        }\n\n        getMonitorPort() {\n            return { ...this.sensorData };\n        }\n\n        setZero() {\n            this.txData = new Array(68).fill(0);\n\n            this.sensorData = {\n                VIBE: 0,\n            };\n            this.workerData = {\n                OCTAVE: 0,\n                NOTE: 0,\n                MOTOR: 0,\n                LED: 0,\n                SHOOT: 0,\n                D9: 0,\n                D10: 0,\n                ANGLE: 0,\n                NEOPIXEL: [\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                ],\n            };\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        getDataByBuffer(buffer) {\n            const datas = [];\n            let lastIndex = 0;\n            buffer.forEach((value, idx) => {\n                if (value == 13 && buffer[idx + 1] == 10) {\n                    datas.push(buffer.subarray(lastIndex, idx));\n                    lastIndex = idx + 2;\n                }\n            });\n            return datas;\n        }\n\n        // 디바이스에서 값을 읽어온다.\n        handleLocalData(data) {\n            const datas = this.getDataByBuffer(data);\n            const sensorData = this.sensorData;\n\n            datas.forEach((data) => {\n                if (data.length <= 4 || data[0] !== 255 || data[1] !== 7) {\n                    return;\n                }\n                const readData = data.subarray(2, data.length);\n                let checkSum;\n\n                const idx = readData[0];\n                if (idx == 1) {\n                    if (readData.length != 4) {\n                        return;\n                    }\n                    const vibeState = readData[1];\n                    const life = readData[2];\n                    checkSum = (idx + vibeState + life) & 0xff;\n                    if (checkSum != readData[3]) {\n                        return;\n                    }\n                    sensorData.VIBE = vibeState;\n                }\n            });\n            this.sensorData = sensorData;\n        }\n\n        //디바이스에 값을 쓴다.\n        requestLocalData() {\n            const workerData = this.workerData;\n            const txData = this.txData;\n            let checkSum = 0;\n            const dataLen = txData.length;\n            const pixelNum = 18;\n\n            txData[0] = 0xff;\n            txData[1] = 0x44;\n            txData[2] = 0x01;\n            txData[3] = 0x03;\n            txData[4] = workerData.OCTAVE;\n            txData[5] = workerData.NOTE;\n            txData[6] = workerData.MOTOR;\n            txData[7] = workerData.LED;\n            txData[8] = workerData.SHOOT;\n            txData[9] = workerData.D9;\n            txData[10] = workerData.D10;\n            txData[11] = workerData.ANGLE;\n            for (let i = 0; i < pixelNum; i++) {\n                txData[i * 3 + 12] = workerData.NEOPIXEL[i].RED;\n                txData[i * 3 + 13] = workerData.NEOPIXEL[i].GREEN;\n                txData[i * 3 + 14] = workerData.NEOPIXEL[i].BLUE;\n            }\n            txData[dataLen - 1] = 0xa;\n\n            for (let i = 2; i < dataLen - 2; i++) {\n                checkSum += txData[i];\n            }\n            txData[dataLen - 2] = checkSum & 255;\n\n            this.tx_data = txData;\n\n            return txData;\n        }\n\n        getVibe() {\n            return this.sensorData.VIBE;\n        }\n\n        setTone(script) {\n            if (!script.isStart) {\n                let note = script.getValue('NOTE', script);\n                if (!Entry.Utils.isNumber(note)) {\n                    note = this.__toneTable[note];\n                }\n\n                if (note < 0) {\n                    note = 0;\n                } else if (note > 12) {\n                    note = 12;\n                }\n\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration <= 0) {\n                    duration = 0;\n                    this.workerData.OCTAVE = 0;\n                    this.workerData.NOTE = 0;\n                    return script.callReturn();\n                }\n\n                let octave = script.getNumberValue('OCTAVE', script) - 1;\n\n                if (octave < 0) {\n                    octave = 0;\n                } else if (octave > 5) {\n                    octave = 5;\n                }\n\n                let value = 0;\n                if (note != 0) {\n                    value = this.__toneMap[note][octave];\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                this.workerData.OCTAVE = value >> 8;\n                this.workerData.NOTE = value & 255;\n\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, duration + 32);\n                return script;\n            } else if (script.timeFlag == 1) {\n                return script;\n            } else {\n                delete script.timeFlag;\n                delete script.isStart;\n                this.workerData.OCTAVE = 0;\n                this.workerData.NOTE = 0;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setMotor(script) {\n            const state = script.getField('STATE');\n\n            this.workerData.MOTOR = state;\n            return script.callReturn();\n        }\n\n        setMotorSecs(script) {\n            if (!script.isStart) {\n                let state = script.getField('STATE');\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration <= 0) {\n                    duration = 0;\n                    state = 0;\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                this.workerData.MOTOR = state;\n\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, duration + 32);\n\n                return script;\n            } else if (script.timeFlag == 1) {\n                return script;\n            } else {\n                delete script.timeFlag;\n                delete script.isStart;\n                this.workerData.MOTOR = 0;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setMotorStop(script) {\n            this.workerData.MOTOR = 0;\n            return script.callReturn();\n        }\n\n        setShootReload(script) {\n            this.workerData.SHOOT = 1;\n            this.workerData.D9 = 200;\n            this.workerData.D10 = 0;\n            return script.callReturn();\n        }\n\n        setShootReloadSecs(script) {\n            if (!script.isStart) {\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration <= 0) {\n                    duration = 0;\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                this.workerData.SHOOT = 1;\n                this.workerData.D9 = 200;\n                this.workerData.D10 = 0;\n\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, duration + 32);\n\n                return script;\n            } else if (script.timeFlag == 1) {\n                return script;\n            } else {\n                delete script.timeFlag;\n                delete script.isStart;\n                this.workerData.SHOOT = 0;\n                this.workerData.D9 = 0;\n                this.workerData.D10 = 0;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setShootCatch(script) {\n            this.workerData.SHOOT = 3;\n            this.workerData.D9 = 80;\n            this.workerData.D10 = 0;\n            return script.callReturn();\n        }\n\n        setShootShooting(script) {\n            if (!script.isStart) {\n                const duration = 40;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                this.workerData.SHOOT = 2;\n                this.workerData.D9 = 0;\n                this.workerData.D10 = 200;\n\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, duration + 32);\n\n                return script;\n            } else if (script.timeFlag == 1) {\n                return script;\n            } else {\n                this.workerData.SHOOT = 0;\n                this.workerData.D9 = 0;\n                this.workerData.D10 = 0;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setShootStop(script) {\n            this.workerData.SHOOT = 0;\n            this.workerData.D9 = 0;\n            this.workerData.D10 = 0;\n            return script.callReturn();\n        }\n\n        setAngle(script) {\n            const state = script.getNumberValue('STATE', script);\n            this.workerData.ANGLE = state;\n            return script.callReturn();\n        }\n\n        setAngleSecs(script) {\n            if (!script.isStart) {\n                let state = script.getNumberValue('STATE', script);\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration <= 0) {\n                    duration = 0;\n                    state = 0;\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                this.workerData.ANGLE = state;\n\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, duration + 32);\n\n                return script;\n            } else if (script.timeFlag == 1) {\n                return script;\n            } else {\n                delete script.timeFlag;\n                delete script.isStart;\n                this.workerData.ANGLE = 0;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setLed(script) {\n            const color = script.getField('COLOR');\n            const state = script.getField('STATE');\n            let power = 0;\n            if (state != null) {\n                power = state == 1 ? 255 : 0;\n            } else {\n                power = script.getNumberValue('POWER', script);\n            }\n\n            if (color == 0) {\n                this.workerData.LED = power;\n            } else if (color == 1) {\n                this.workerData.SHOOT = 4;\n                this.workerData.D9 = power;\n            } else if (color == 2) {\n                this.workerData.SHOOT = 4;\n                this.workerData.D10 = power;\n            }\n\n            return script.callReturn();\n        }\n\n        setLedPicker(script) {\n            const color = script.getStringField('COLOR');\n\n            const redPower = parseInt(color.substr(1, 2), 16);\n            const greenPower = parseInt(color.substr(3, 2), 16);\n            const bluePower = parseInt(color.substr(5, 2), 16);\n\n            this.workerData.SHOOT = 4;\n            this.workerData.LED = bluePower;\n            this.workerData.D9 = redPower;\n            this.workerData.D10 = greenPower;\n\n            return script.callReturn();\n        }\n\n        setRGBLed(script) {\n            const redPower = script.getNumberValue('RED', script);\n            const greenPower = script.getNumberValue('GREEN', script);\n            const bluePower = script.getNumberValue('BLUE', script);\n\n            this.workerData.SHOOT = 4;\n            this.workerData.LED = bluePower;\n            this.workerData.D9 = redPower;\n            this.workerData.D10 = greenPower;\n\n            return script.callReturn();\n        }\n\n        setLedOff(script) {\n            this.workerData.SHOOT = 4;\n            this.workerData.LED = 0;\n            this.workerData.D9 = 0;\n            this.workerData.D10 = 0;\n\n            return script.callReturn();\n        }\n\n        setNeopixel(script) {\n            let num = script.getNumberValue('NUM', script);\n            const redPower = script.getNumberValue('RED', script);\n            const greenPower = script.getNumberValue('GREEN', script);\n            const bluePower = script.getNumberValue('BLUE', script);\n\n            num = num % 18;\n\n            this.workerData.NEOPIXEL[num].RED = redPower;\n            this.workerData.NEOPIXEL[num].GREEN = greenPower;\n            this.workerData.NEOPIXEL[num].BLUE = bluePower;\n            return script.callReturn();\n        }\n\n        setAllNeopixel(script) {\n            const redPower = script.getNumberValue('RED', script);\n            const greenPower = script.getNumberValue('GREEN', script);\n            const bluePower = script.getNumberValue('BLUE', script);\n\n            for (let num = 0; num < 18; num++) {\n                this.workerData.NEOPIXEL[num].RED = redPower;\n                this.workerData.NEOPIXEL[num].GREEN = greenPower;\n                this.workerData.NEOPIXEL[num].BLUE = bluePower;\n            }\n\n            return script.callReturn();\n        }\n\n        setNeopixelPicker(script) {\n            let num = script.getNumberValue('NUM', script);\n            const color = script.getStringField('COLOR');\n\n            num = num % 18;\n\n            const redPower = parseInt(color.substr(1, 2), 16);\n            const greenPower = parseInt(color.substr(3, 2), 16);\n            const bluePower = parseInt(color.substr(5, 2), 16);\n\n            this.workerData.NEOPIXEL[num].RED = redPower;\n            this.workerData.NEOPIXEL[num].GREEN = greenPower;\n            this.workerData.NEOPIXEL[num].BLUE = bluePower;\n            return script.callReturn();\n        }\n\n        setAllNeopixelPicker(script) {\n            const color = script.getStringField('COLOR');\n\n            const redPower = parseInt(color.substr(1, 2), 16);\n            const greenPower = parseInt(color.substr(3, 2), 16);\n            const bluePower = parseInt(color.substr(5, 2), 16);\n\n            for (let num = 0; num < 18; num++) {\n                this.workerData.NEOPIXEL[num].RED = redPower;\n                this.workerData.NEOPIXEL[num].GREEN = greenPower;\n                this.workerData.NEOPIXEL[num].BLUE = bluePower;\n            }\n\n            return script.callReturn();\n        }\n\n        setNeopixelOff(script) {\n            for (let num = 0; num < 18; num++) {\n                this.workerData.NEOPIXEL[num].RED = 0;\n                this.workerData.NEOPIXEL[num].GREEN = 0;\n                this.workerData.NEOPIXEL[num].BLUE = 0;\n            }\n\n            return script.callReturn();\n        }\n\n        // Block\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        neocannonlite_get_vibe_value: '진동 센서 감지됨',\n                        neocannonlite_set_tone: '부저를 %1 %2 음으로 %3 초 연주하기 %4',\n                        neocannonlite_motor_state: '%1 이동하기 %2',\n                        neocannonlite_motor_state_secs: '%1 %2 초 이동하기 %3',\n                        neocannonlite_motor_stop: '정지하기 %1',\n                        neocannonlite_shoot_reload: '장전하기 %1',\n                        neocannonlite_shoot_reload_secs: '%1 초 장전하기 %2',\n                        neocannonlite_shoot_catch: '장전 풀림 방지 %1',\n                        neocannonlite_shoot_shooting: '발사하기 %1',\n                        neocannonlite_shoot_stop: '장전모터 정지 %1',\n                        neocannonlite_angle_state: '각도 %1 이동하기 %2',\n                        neocannonlite_angle_state_secs: '각도 %1 %2 초 이동하기 %3',\n                        neocannonlite_rgb_led_select_state: '%1 %2 %3',\n                        neocannonlite_rgb_led_select_pwm: '%1 %2 세기로 켜기 %3',\n                        neocannonlite_rgb_led_color_picker: 'RGB LED %1 %2',\n                        neocannonlite_rgb_led_pwm: 'RGB LED 빨강 %1 초록 %2 파랑 %3 %4',\n                        neocannonlite_rgb_led_off: 'RGB LED 끄기 %1',\n                        neocannonlite_neopixel_color_picker: '네오픽셀 %1번  %2 (으)로 켜기 %3',\n                        neocannonlite_neopixel: '네오픽셀 %1번  빨 %2 녹 %3 파 %4 (으)로 켜기 %5',\n                        neocannonlite_neopixel_color_picker_all_on:\n                            '네오픽셀 전체 %1 (으)로 켜기 %2',\n                        neocannonlite_neopixel_all_on:\n                            '네오픽셀 전체  빨 %1 녹 %2 파 %3 (으)로 켜기 %4',\n                        neocannonlite_neopixel_all_off: '네오픽셀 전체 끄기 %1',\n                    },\n                    Device: {\n                        neocannonlite: '네오캐논',\n                    },\n                    Menus: {\n                        neocannonlite: '네오캐논',\n                    },\n                },\n                en: {\n                    template: {\n                        neocannonlite_get_vibe_value: 'Detected Vibe Sensor',\n                        neocannonlite_set_tone: 'Play tone note %1 octave %2 beat %3 %4',\n                        neocannonlite_motor_state: 'Move %1 %2',\n                        neocannonlite_motor_state_secs: 'Move %1 %2 secs %3',\n                        neocannonlite_motor_stop: 'Move Stop %1',\n                        neocannonlite_shoot_reload: 'Reload %1',\n                        neocannonlite_shoot_reload_secs: 'Reload %1 secs %2',\n                        neocannonlite_shoot_catch: 'Anti-shoot %1',\n                        neocannonlite_shoot_shooting: 'Shoot %1',\n                        neocannonlite_shoot_stop: 'Stop Shooting Motor %1',\n                        neocannonlite_angle_state: 'Move Angle %1 %2',\n                        neocannonlite_angle_state_secs: 'Move Angle %1 %2 secs %3',\n                        neocannonlite_rgb_led_select_state: '%1 color %2 %3',\n                        neocannonlite_rgb_led_select_pwm: '%1 color %2 turn on pwm %3',\n                        neocannonlite_rgb_led_color_picker: 'RGB LED %1 %2',\n                        neocannonlite_rgb_led_pwm: 'RGB LED R %1 G %2 B %3 %4',\n                        neocannonlite_rgb_led_off: 'RGB LED OFF',\n                        neocannonlite_neopixel_color_picker: 'Neopixel number %1 turn on %2 %3',\n                        neocannonlite_neopixel: 'Neopixel number %1 turn on R %2 G %3 B %4 %5',\n                        neocannonlite_neopixel_color_picker_all_on: 'All Neopixel turn on %1 %2',\n                        neocannonlite_neopixel_all_on: 'All Neopixel turn on R %1 G %2 B %3 %4',\n                        neocannonlite_neopixel_all_off: 'All Neopixel turn off %1',\n                    },\n                    Device: {\n                        neocannonlite: 'neocannonlite',\n                    },\n                    Menus: {\n                        neocannonlite: 'NeoCannonLite',\n                    },\n                },\n            };\n        }\n\n        getBlocks() {\n            return {\n                neocannonlite_get_vibe_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'neocannonlite_get_vibe_value',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoCannonLiteGet',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.getVibe();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.get_vibe()',\n                                blockType: 'param',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_tone_list: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.silent, '0'],\n                                [Lang.Blocks.do_name, 'C'],\n                                [Lang.Blocks.do_sharp_name, 'CS'],\n                                [Lang.Blocks.re_name, 'D'],\n                                [Lang.Blocks.re_sharp_name, 'DS'],\n                                [Lang.Blocks.mi_name, 'E'],\n                                [Lang.Blocks.fa_name, 'F'],\n                                [Lang.Blocks.fa_sharp_name, 'FS'],\n                                [Lang.Blocks.sol_name, 'G'],\n                                [Lang.Blocks.sol_sharp_name, 'GS'],\n                                [Lang.Blocks.la_name, 'A'],\n                                [Lang.Blocks.la_sharp_name, 'AS'],\n                                [Lang.Blocks.si_name, 'B'],\n                            ],\n                            value: 'C',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getField('NOTE');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.silent, '0'],\n                                            [Lang.Blocks.do_name, 'C'],\n                                            [Lang.Blocks.do_sharp_name, 'CS'],\n                                            [Lang.Blocks.re_name, 'D'],\n                                            [Lang.Blocks.re_sharp_name, 'DS'],\n                                            [Lang.Blocks.mi_name, 'E'],\n                                            [Lang.Blocks.fa_name, 'F'],\n                                            [Lang.Blocks.fa_sharp_name, 'FS'],\n                                            [Lang.Blocks.sol_name, 'G'],\n                                            [Lang.Blocks.sol_sharp_name, 'GS'],\n                                            [Lang.Blocks.la_name, 'A'],\n                                            [Lang.Blocks.la_sharp_name, 'AS'],\n                                            [Lang.Blocks.si_name, 'B'],\n                                        ],\n                                        value: 'C',\n                                        fontSize: 11,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    },\n                                ],\n                                keyOption: 'neocannonlite_tone_list',\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_tone_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'neocannonlite_tone_list',\n                            },\n                        ],\n                        type: 'neocannonlite_tone_value',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getNumberValue('NOTE');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                keyOption: 'neocannonlite_tone_value',\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_octave_list: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        OCTAVE: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getField('OCTAVE');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                keyOption: 'neocannonlite_octave_list',\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_set_tone: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'neocannonlite_tone_list',\n                            },\n                            {\n                                type: 'neocannonlite_octave_list',\n                            },\n                            {\n                                type: 'text',\n                                params: ['1'],\n                            },\n                            null,\n                        ],\n                        type: 'neocannonlite_set_tone',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                        OCTAVE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setTone(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.tone(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_motor_state: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['앞으로', 1],\n                                ['왼쪽으로', 2],\n                                ['오른쪽으로', 3],\n                                ['뒤로', 4],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_motor_state',\n                    },\n                    paramsKeyMap: {\n                        STATE: 0,\n                    },\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setMotor(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.motor_state(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['앞으로', '1'],\n                                            ['왼쪽으로', '2'],\n                                            ['오른쪽으로', '3'],\n                                            ['뒤로', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_motor_state_secs: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['앞으로', 1],\n                                ['왼쪽으로', 2],\n                                ['오른쪽으로', 3],\n                                ['뒤로', 4],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'text',\n                                params: ['1'],\n                            },\n                        ],\n                        type: 'neocannonlite_motor_state_secs',\n                    },\n                    paramsKeyMap: {\n                        STATE: 0,\n                        DURATION: 1,\n                    },\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setMotorSecs(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.motor_state_secs(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['앞으로', '1'],\n                                            ['왼쪽으로', '2'],\n                                            ['오른쪽으로', '3'],\n                                            ['뒤로', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_motor_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_motor_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setMotorStop(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.motor_stop()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_shoot_reload: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_shoot_reload',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setShootReload(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.reload()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_shoot_reload_secs: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'text',\n                                params: ['1'],\n                            },\n                        ],\n                        type: 'neocannonlite_shoot_reload_secs',\n                    },\n                    paramsKeyMap: {\n                        DURATION: 0,\n                    },\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setShootReloadSecs(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.reload_secs(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_shoot_catch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_shoot_catch',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setShootCatch(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.shoot_catch()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_shoot_shooting: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_shoot_shooting',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setShootShooting(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.shooting()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_shoot_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_shoot_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setShootStop(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.shoot_stop()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_angle_state: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['STOP', '0'],\n                                ['UP', '1'],\n                                ['DOWN', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_angle_state',\n                    },\n                    paramsKeyMap: {\n                        STATE: 0,\n                    },\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setAngle(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.angle_state(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['STOP', '0'],\n                                            ['UP', '1'],\n                                            ['DOWN', '2'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueLowerCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_angle_state_secs: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['UP', '1'],\n                                ['DOWN', '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'text',\n                                params: ['0.1'],\n                            },\n                        ],\n                        type: 'neocannonlite_angle_state_secs',\n                    },\n                    paramsKeyMap: {\n                        STATE: 0,\n                        DURATION: 1,\n                    },\n                    class: 'NeoCannonLite',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setAngleSecs(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.angle_state_secs(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['UP', '1'],\n                                            ['DOWN', '2'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueLowerCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_rgb_led_select_state: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['BLUE', '0'],\n                                ['RED', '1'],\n                                ['GREEN', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OFF', '0'],\n                                ['ON', '1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neocannonlite_rgb_led_select_state',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                        STATE: 1,\n                    },\n                    class: 'NeoCannonLiteRGB',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setLed(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.rgb_led_select_state(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['BLUE', '0'],\n                                            ['RED', '1'],\n                                            ['GREEN', '2'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['ON', '1'],\n                                            ['OFF', '0'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_rgb_led_select_pwm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['BLUE', '0'],\n                                ['RED', '1'],\n                                ['GREEN', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neocannonlite_rgb_led_select_pwm',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                        POWER: 1,\n                    },\n                    class: 'NeoCannonLiteRGB',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setLed(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.rgb_led_select_pwm(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['BLUE', '0'],\n                                            ['RED', '1'],\n                                            ['GREEN', '2'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_rgb_led_color_picker: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['#0000FF', null],\n                        type: 'neocannonlite_rgb_led_color_picker',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'NeoCannonLiteRGB',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setLedPicker(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.rgb_led_colorpicker(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Color',\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_rgb_led_pwm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                        ],\n                        type: 'neocannonlite_rgb_led_pwm',\n                    },\n                    paramsKeyMap: {\n                        RED: 0,\n                        GREEN: 1,\n                        BLUE: 2,\n                    },\n                    class: 'NeoCannonLiteRGB',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setRGBLed(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.rgb_led_pwm(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_rgb_led_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_rgb_led_off',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoCannonLiteRGB',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setLedOff(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.rgb_led_off()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_neopixel_color_picker: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'neocannonlite_neopixel_color_picker',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        COLOR: 1,\n                    },\n                    class: 'NeoCannonLiteNeopixel',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setNeopixelPicker(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.neopixelColorPicker(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Color',\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_neopixel: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            null,\n                        ],\n                        type: 'neocannonlite_neopixel',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        RED: 1,\n                        GREEN: 2,\n                        BLUE: 3,\n                    },\n                    class: 'NeoCannonLiteNeopixel',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setNeopixel(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.neopixel(%1, %2, %3, %4)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_neopixel_color_picker_all_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neocannonlite_neopixel_color_picker_all_on',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'NeoCannonLiteNeopixel',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setAllNeopixelPicker(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.neopixelColorPickerAllOn(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Color',\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_neopixel_all_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            null,\n                        ],\n                        type: 'neocannonlite_neopixel_all_on',\n                    },\n                    paramsKeyMap: {\n                        RED: 0,\n                        GREEN: 1,\n                        BLUE: 2,\n                    },\n                    class: 'NeoCannonLiteNeopixel',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setAllNeopixel(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.neopixelAllON(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neocannonlite_neopixel_all_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neocannonlite_neopixel_all_off',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoCannonLiteNeopixel',\n                    isNotFor: ['NeoCannonLite'],\n                    func(sprite, script) {\n                        return Entry.NeoCannonLite.setNeopixelOff(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoCannonLite.neopixelAllOFF()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n            };\n        }\n    })();\n})();\n\nmodule.exports = Entry.NeoCannonLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_neo_lite.js",
    "content": "'use strict';\n(function () {\n    /*\n     엔트리에 정의된 블럭 명령어\n     엔트리에서 받을 때는 BlockTypes 로 통신하고,\n     하드웨어로 전송할 때는 Command 로 변환 후 Pdu 로 Wrapping 하여 전송한다.\n     */\n    const NeoBlockType = {\n        // MOTOR 명령어 0x1X\n        MOTOR_MOVE: 0x11,\n        MOTOR_MOVE_BOTH: 0x12,\n        MOTOR_STOP: 0x13,\n        ROBOT_MOVE: 0x14,\n        ROBOT_STOP: 0x15,\n        // SERVO 명령어 0x2X\n        SERVO_RESET: 0x21,\n        SERVO_ANGLE: 0x22,\n        SERVO_ANGLE_WAIT: 0x23,\n        SERVO_ROTATE: 0x24,\n        SERVO_STOP: 0x25,\n        // LINE_TRACER 명령어 0x3X\n        LINE_TRACER_START: 0x31,\n        LINE_CROSS_MOVE: 0x32,\n        LINE_CROSS_TURN: 0x33,\n        LINE_CHANGE_START: 0x34,\n        LINE_CHANGE_TURN: 0x35,\n        // AUTO_DRIVING 명령어 0x4X\n        AUTO_DRIVING_START: 0x41,\n        AUTO_DRIVING_SENSOR_START: 0x42,\n        AUTO_DRIVING_STOP: 0x43,\n        AUTO_PARKING_START: 0x44,\n        AUTO_DETECT_WALL_START: 0x45,\n        AUTO_DETECT_WALL_TURN: 0x46,\n        // LED 명령어 0x5X\n        LED_ON: 0x51,\n        LED_BLINK: 0x52,\n        LED_OFF: 0x53,\n        COLOR_LED_ON: 0x54,\n        COLOR_LED_OFF: 0x55,\n        COLOR_LED_ON_SENSOR: 0x56,\n        // SET_OUTPUT 명령어 0x6X\n        SET_OUTPUT: 0x61,\n        // BUZZER 명령어 0x7X\n        BUZZER_START: 0x71,\n        BUZZER_WITH_SENSOR: 0x72,\n        BUZZER_STOP: 0x73,\n        // LCD 명령어 0x8X\n        LCD_IMAGE: 0x81,\n        LCD_TEXT: 0x82,\n    };\n\n    /*\n     PDU 정의\n     */\n    const HEADER = [0xaa, 0xaa, 0xcc];\n    const IDX_LENGTH = 3;\n    const IDX_FRAME_CODE = 4;\n    const IDX_PDU_CODE = 5;\n    const IDX_ACK_NUM = 6;\n\n    const FrameCode = {\n        BASIC: 0x01,\n        CONNECTION: 0x02,\n    };\n\n    const PduConnectionCode = {\n        PAIRING_START: 0x01,\n        PAIRING_INFO: 0x03,\n        PAIRING_REMOVE: 0x06,\n        NOTIFY_LIVE: 0x07,\n    };\n\n    const PduBasicCode = {\n        SENSOR_DATA: 0x01,\n        BASIC: 0x10,\n        EXTEND_1: 0x11,\n    };\n\n    const SensorKind = {\n        CONTROLLER: 0x00,\n        ANALOG: 0x01,\n        DIGITAL: 0x02,\n        COLOR: 0x03,\n    };\n\n    const PduCode = {\n        SENSOR_DATA: 0x01,\n        CONTROLLER_COMMAND: 0x02,\n        ACTION_COMMAND: 0x03,\n        BASIC: 0x10,\n        EXTEND_1: 0x11,\n        EXTEND_2: 0x12,\n        EXTEND_3: 0x13,\n    };\n\n    const ActorKind = {\n        CONTROLLER: 0x00,\n        LED: 0x80,\n        SERVO: 0x81,\n        COLOR_LED: 0x82,\n        LCD: 0x83,\n    };\n\n    const ControllerCommand = {\n        CONTROLLER_LED: 0x01,\n        BUZZER: 0x02,\n        MOTOR: 0x03,\n        MOTOR_BOTH: 0x04,\n        ROBOT: 0x05,\n        LINE_TRACER: 0x06,\n        AUTO_DRIVING: 0x07,\n        AUTO_PARKING: 0x08,\n        AUTO_DETECT_WALL: 0x09,\n    };\n\n    const ServoCommand = {\n        STOP: 0x01,\n        RESET: 0x02,\n        ANGLE: 0x03,\n        ANGLE_WAIT: 0x04,\n        ROTATE: 0x05,\n    };\n\n    const LedCommand = {\n        OFF: 0x00,\n        ON: 0x01,\n    };\n\n    const LcdCommand = {\n        IMAGE: 0x01,\n        TEXT: 0x02,\n    };\n\n    const UnitId = {\n        CONTROLLER: 0x00,\n        CONTROLLER_IN1: 0x01,\n        CONTROLLER_IN2: 0x02,\n        CONTROLLER_IN3: 0x03,\n        SENSOR_STICK: 0x10,\n        SENSOR_STICK_IN1: 0x11,\n        IOT: 0x80,\n        CONTROLLER_OUT1: 0x81,\n        CONTROLLER_OUT2: 0x82,\n        CONTROLLER_OUT12: 0x83,\n        CONTROLLER_OUT3: 0x84,\n        CONTROLLER_OUT13: 0x85,\n        CONTROLLER_OUT23: 0x86,\n        CONTROLLER_OUT123: 0x87,\n        CONTROLLER_OUT_ALL: 0x8f,\n    };\n\n    /*\n     블럭 실행 단계\n     execute: 최초 실행\n     pending_response: 최초 실행의 response 대기중인 상태\n     set_timeout: 블럭에서 duration 필드에 의거하여 타임아웃을 설정\n     wait_timeout: timeout 대기중인 상태\n     stop: 파라미터를 0으로 바꿔서 실행\n     pending_stop: 파라미터를 0으로 바꾼 실행의 response 대기중인 상태\n     end: 실행 종료 단계\n     */\n    const ExecPhase = {\n        EXECUTE: 'execute',\n        PENDING_RESPONSE: 'pending_response',\n        SET_TIMEOUT: 'set_timeout',\n        WAIT_TIMEOUT: 'wait_timeout',\n        STOP: 'stop',\n        PENDING_STOP: 'pending_stop',\n        END: 'end',\n    };\n\n    Entry.NeoLite = new (class NeoLite {\n        constructor() {\n            this.id = '050801';\n            this.name = 'NeoLite';\n            this.url = 'http://neobot.co.kr/';\n            this.imageName = 'neo_lite.png';\n            this.portData = {\n                baudRate: 500000,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                duration: 32,\n                constantServing: true,\n            };\n            this.duration = 32;\n\n            this.sensorValues = {\n                controllerBattery: 0,\n                irCode: 0,\n                in1Kind: 0,\n                in1Values: [0, 0, 0, 0],\n                in2Kind: 0,\n                in2Values: [0, 0, 0, 0],\n                in3Kind: 0,\n                in3Values: [0, 0, 0, 0],\n                sensorStickBattery: 0,\n                in4Kind: 0,\n                in4Values: [0, 0, 0, 0],\n            }; // 센서 데이터\n\n            this.blockMenuBlocks = [\n                // robot\n                'neo_lite_robot_title',\n                'neo_lite_robot_move',\n                'neo_lite_robot_stop',\n                // auto driving\n                'neo_lite_auto_driving_title',\n                'neo_lite_auto_driving_start',\n                'neo_lite_auto_driving_sensor_start',\n                'neo_lite_auto_driving_stop',\n                // auto parking\n                // 'neo_lite_auto_parking_title',\n                // 'neo_lite_auto_parking_start',\n                // line tracer\n                // 'neo_lite_line_tracer_title',\n                'neo_lite_line_tracer_start',\n                'neo_lite_line_cross_move',\n                'neo_lite_line_cross_turn',\n                'neo_lite_line_cross_reached',\n                // motor\n                'neo_lite_motor_title',\n                'neo_lite_motor_move',\n                'neo_lite_motor_move_both',\n                'neo_lite_motor_stop',\n                // servo\n                'neo_lite_servo_title',\n                'neo_lite_servo_reset',\n                'neo_lite_servo_angle',\n                'neo_lite_servo_angle_var',\n                'neo_lite_servo_angle_wait',\n                'neo_lite_servo_rotate',\n                'neo_lite_servo_stop',\n\n                // led\n                'neo_lite_led_title',\n                'neo_lite_led_on',\n                'neo_lite_led_blink',\n                'neo_lite_led_off',\n\n                // set output\n                'neo_lite_set_output_title',\n                'neo_lite_set_output',\n\n                // color led\n                'neo_lite_color_led_title',\n                'neo_lite_color_led_on',\n                'neo_lite_color_led_off',\n                'neo_lite_color_led_on_with_sensor',\n\n                // sensor\n                'neo_lite_sensor_title',\n                'neo_lite_sensor_in',\n                'neo_lite_sensor_digital_in',\n                'neo_lite_sensor_convert',\n                'neo_lite_sensor_compare',\n                'neo_lite_sensor_between',\n                'neo_lite_sensor_digital_compare',\n                'neo_lite_sensor_color_compare',\n                'neo_lite_sensor_color_sequence_compare',\n                'neo_lite_sensor_button_pressed',\n                // buzzer\n                'neo_lite_buzzer_title',\n                'neo_lite_buzzer_start',\n                'neo_lite_buzzer_with_sensor',\n                'neo_lite_buzzer_stop',\n                // lcd\n                'neo_lite_lcd_title',\n                'neo_lite_lcd_image',\n                'neo_lite_lcd_text',\n            ];\n\n            this.executeList = [];\n            this.pendingResponseList = {};\n\n            this.isDebug = false;\n            this.isDebugSensor = false;\n            this.isDebugPdu = false;\n\n            this.seqBlockId = 0;\n\n            this.setZero();\n        }\n\n        get monitorTemplate() {\n            return {\n                imgPath: 'hw/neo.png',\n                width: 700,\n                height: 700,\n                listPorts: {\n                    IN11: { name: 'IN1 1', type: 'input', pos: { x: 0, y: 0 } },\n                    IN12: { name: 'IN1 2', type: 'input', pos: { x: 0, y: 0 } },\n                    IN13: { name: 'IN1 3', type: 'input', pos: { x: 0, y: 0 } },\n                    IN14: { name: 'IN1 4', type: 'input', pos: { x: 0, y: 0 } },\n                    IN21: { name: 'IN2 1', type: 'input', pos: { x: 0, y: 0 } },\n                    IN22: { name: 'IN2 2', type: 'input', pos: { x: 0, y: 0 } },\n                    IN23: { name: 'IN2 3', type: 'input', pos: { x: 0, y: 0 } },\n                    IN24: { name: 'IN2 4', type: 'input', pos: { x: 0, y: 0 } },\n                    IN31: { name: 'IN3 1', type: 'input', pos: { x: 0, y: 0 } },\n                    IN32: { name: 'IN3 2', type: 'input', pos: { x: 0, y: 0 } },\n                    IN33: { name: 'IN3 3', type: 'input', pos: { x: 0, y: 0 } },\n                    IN34: { name: 'IN3 4', type: 'input', pos: { x: 0, y: 0 } },\n                    IR: { name: 'IR', type: 'input', pos: { x: 0, y: 0 } },\n                    BAT: { name: 'BAT', type: 'input', pos: { x: 0, y: 0 } },\n                },\n                mode: 'both',\n            };\n        }\n\n        setZero() {\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                const blockId = this.generateBlockId();\n                const pdu = this.makePdu([\n                    FrameCode.BASIC,\n                    PduCode.CONTROLLER_COMMAND,\n                    blockId,\n                    0x04,\n                ]);\n                this.executeList = [\n                    {\n                        blockId,\n                        pdu,\n                    },\n                ];\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        /*\n        연결 후 초기에 송신할 데이터가 필요한 경우 사용합니다.\n        requestInitialData 를 사용한 경우 checkInitialData 가 필수입니다.\n        이 두 함수가 정의되어있어야 로직이 동작합니다. 필요없으면 작성하지 않아도 됩니다.\n        */\n        requestInitialData() {\n            this.logPdu('request initial data (request paring info to hw)');\n            return this.makePdu(this.getPairingInfoCmd());\n        }\n\n        validateLocalData(pdu) {\n            return true;\n        }\n\n        async initialHandshake() {\n            const initPdu = this.requestInitialData();\n            this.executeList.push({\n                blockId: 0,\n                pdu: initPdu,\n            });\n            Entry.hwLite.serial.update();\n            return true;\n        }\n\n        /**\n         * 하드웨어에서 온 데이터 처리\n         * @param {ArrayBuffer} data\n         */\n        handleLocalData(data) {\n            this.logPdu(`incoming pdu : ${this.byteArrayToHex(data)}`);\n            let validPdu = this.getValidPdu(data);\n            while (validPdu) {\n                this.onReceivePdu(validPdu);\n                if (!this.remainingPdu || this.remainingPdu.length <= 0) {\n                    break;\n                }\n                validPdu = this.getValidPdu([]);\n            }\n        }\n\n        /**\n         * remainingPdu 와 병합 처리하여 유효한 pdu 를 반환한다.\n         * 전체 길이가 짧을 경우 remainingPdu 에 저장 후 다음에 오는 패킷과 병합하여 처리함.\n         * 전체 길이가 Pdu Length 보다 길 경우 유효한 부분까지만 잘라 쓰고\n         * 나머지는 remainingPdu 에 저장 후 다음에 오는 패킷과 병합하여 처리함.\n         * @param pdu\n         * @return {null|Array} validPdu\n         */\n        getValidPdu(pdu) {\n            const mergedPdu = [];\n            if (this.remainingPdu) {\n                mergedPdu.push(...this.remainingPdu);\n                this.remainingPdu = null;\n            }\n            mergedPdu.push(...pdu);\n            this.logPdu(`merged pdu : ${this.byteArrayToHex(mergedPdu)}`);\n            if (mergedPdu.length < 4) {\n                this.remainingPdu = [...mergedPdu];\n                this.logPdu(`too short header : ${this.byteArrayToHex(mergedPdu)}`);\n                return null;\n            }\n\n            // 헤더 불일치는 버림\n            if (!this.checkHeader(mergedPdu)) {\n                this.logPdu(`incorrect header : ${this.byteArrayToHex(mergedPdu)}`);\n                return null;\n            }\n\n            // 유효 데이터 길이는 data length + header length (3) + length byte (1) + checksum byte (1)\n            const validDataLength = mergedPdu[IDX_LENGTH] + HEADER.length + 1 + 1;\n            /*\n            전체 길이가 유효 데이터 길이보다 작을 경우\n            아직 도착하지 않은 부분이 있으므로 병합을 위해 remainingPdu 에 저장\n             */\n            if (mergedPdu.length < validDataLength) {\n                this.logPdu(`too short pdu : ${this.byteArrayToHex(mergedPdu)}`);\n                this.remainingPdu = [...mergedPdu];\n                this.logPdu(`remaining pdu : ${this.byteArrayToHex(this.remainingPdu)}`);\n                return null;\n            }\n\n            /*\n            전체 길이가 유효 데이터 길이보다 클 경우\n            유효한 부분만 잘라내고 나머지는 remainingPdu 에 저장\n             */\n            if (mergedPdu.length > validDataLength) {\n                this.logPdu(`too long pdu : ${this.byteArrayToHex(mergedPdu)}`);\n                this.remainingPdu = mergedPdu.slice(validDataLength, mergedPdu.length);\n                this.logPdu(`remaining pdu : ${this.byteArrayToHex(this.remainingPdu)}`);\n            }\n\n            const validPdu = mergedPdu.slice(0, validDataLength);\n            //this.logPdu(`valid pdu : ${this.byteArrayToHex(validPdu)}`);\n\n            /*\n            유효 Pdu 의 checksum 확인\n             */\n            const dataLength = validPdu[IDX_LENGTH];\n            let checkSum = 0;\n            for (let i = 0; i < dataLength; i++) {\n                checkSum += validPdu[i + 4];\n            }\n            checkSum = checkSum & 255;\n            const pduCheckSum = validPdu[HEADER.length + 1 + dataLength];\n            if (pduCheckSum !== checkSum) {\n                this.logPdu(`checksum error : ${pduCheckSum} ${checkSum}`);\n                return null;\n            }\n\n            if (validPdu[IDX_FRAME_CODE] === 0xfe) {\n                this.logPdu('error data arrived!!');\n            }\n\n            return validPdu;\n        }\n\n        /**\n         * 유효한 pdu 수신 처리함.\n         * 센서 데이터 수신, Action Command 의 Response 만 처리함.\n         * 나머지는 NEO Platform 전용이므로 무시함.\n         * @param pdu\n         */\n        onReceivePdu(pdu) {\n            if (pdu[IDX_FRAME_CODE] === FrameCode.BASIC) {\n                if (pdu[IDX_PDU_CODE] === PduBasicCode.SENSOR_DATA) {\n                    // this.logD(this.byteArrayToHex(pdu));\n                    this.parseSensorPdu(pdu);\n                    return;\n                }\n\n                this.logD(this.byteArrayToHex(pdu));\n\n                const responseData = this.parseResponsePdu(pdu);\n\n                if (responseData && responseData.blockId) {\n                    if (this.pendingResponseList[responseData.blockId]) {\n                        delete this.pendingResponseList[responseData.blockId];\n                    }\n                }\n            }\n        }\n\n        parseSensorPdu(pdu) {\n            let body = pdu.slice(IDX_PDU_CODE + 1, pdu.length - 1);\n            this.logSensor(`sensor pdu : ${this.byteArrayToHex(body)}`);\n            while (body && body.length > 0) {\n                const sensorDataKind = body[0];\n                const unitId = body[1];\n                const valueLength = body[2];\n                const value = body.slice(3, 3 + valueLength);\n                const buffer = Buffer.from(value);\n                if (sensorDataKind === SensorKind.CONTROLLER) {\n                    if (unitId === UnitId.CONTROLLER) {\n                        this.sensorValues.irCode = buffer.readInt16LE(2);\n                        this.sensorValues.controllerBattery = buffer.readInt16LE(4);\n                    }\n                }\n                if (sensorDataKind === SensorKind.ANALOG) {\n                    const analogValue = buffer.readInt16LE(0);\n                    if (unitId === UnitId.CONTROLLER_IN1) {\n                        this.sensorValues.in1Values = [analogValue, 0, 0, 0];\n                    } else if (unitId === UnitId.CONTROLLER_IN2) {\n                        this.sensorValues.in2Values = [analogValue, 0, 0, 0];\n                    } else if (unitId === UnitId.CONTROLLER_IN3) {\n                        this.sensorValues.in3Values = [analogValue, 0, 0, 0];\n                    }\n                } else if (\n                    sensorDataKind === SensorKind.DIGITAL ||\n                    sensorDataKind === SensorKind.COLOR\n                ) {\n                    const value1 = buffer.readInt16LE(0);\n                    const value2 = buffer.readInt16LE(2);\n                    const value3 = buffer.readInt16LE(4);\n                    const value4 = buffer.readInt16LE(6);\n                    if (unitId === UnitId.CONTROLLER_IN1) {\n                        this.sensorValues.in1Values = [value1, value2, value3, value4];\n                    } else if (unitId === UnitId.CONTROLLER_IN2) {\n                        this.sensorValues.in2Values = [value1, value2, value3, value4];\n                    } else if (unitId === UnitId.CONTROLLER_IN3) {\n                        this.sensorValues.in3Values = [value1, value2, value3, value4];\n                    }\n                }\n                body = body.slice(3 + valueLength, body.length);\n            }\n            this.logSensor(`sensor data : ${JSON.stringify(this.sensorValues)}`);\n        }\n\n        parseResponsePdu(pdu) {\n            return {\n                blockId: pdu[IDX_PDU_CODE + 1],\n                result: pdu[IDX_PDU_CODE + 2],\n            };\n        }\n\n        getMonitorPort() {\n            return {\n                IN11: this.sensorValues.in1Values[0],\n                IN12: this.sensorValues.in1Values[1],\n                IN13: this.sensorValues.in1Values[2],\n                IN14: this.sensorValues.in1Values[3],\n                IN21: this.sensorValues.in2Values[0],\n                IN22: this.sensorValues.in2Values[1],\n                IN23: this.sensorValues.in2Values[2],\n                IN24: this.sensorValues.in2Values[3],\n                IN31: this.sensorValues.in3Values[0],\n                IN32: this.sensorValues.in3Values[1],\n                IN33: this.sensorValues.in3Values[2],\n                IN34: this.sensorValues.in3Values[3],\n                IR: this.sensorValues.irCode,\n                BAT: this.sensorValues.controllerBattery,\n            };\n        }\n        requestLocalData() {\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                if (this.executeList.length > 0) {\n                    const executeData = this.executeList.shift();\n                    this.logD(this.byteArrayToHex(executeData.pdu));\n                    return executeData.pdu;\n                }\n            }\n            return null;\n        }\n\n        getCheckSum(command) {\n            let checkSum = 0;\n            for (let i = 0; i < command.length; i++) {\n                checkSum += command[i];\n            }\n            return checkSum & 255;\n        }\n\n        /**\n         * pdu 길이 확인\n         * 전체 길이는 pdu[3] data length + header(3) + length byte(1) + checkSum byte(1)\n         * @param pdu\n         * @return {boolean} result\n         */\n        checkPduLength(pdu) {\n            const dataLength = pdu[IDX_LENGTH];\n            return pdu.length >= dataLength + HEADER.length + 1 + 1;\n        }\n\n        /**\n         * pdu 의 시작이 HEADER 와 일치하는지 확인\n         * @param pdu\n         * @return {boolean} result\n         */\n        checkHeader(pdu) {\n            if (pdu.length < HEADER.length) {\n                return false;\n            }\n\n            for (let i = 0; i < HEADER.length; i++) {\n                if (HEADER[i] !== pdu[i]) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        getUnitId(port) {\n            switch (port) {\n                case 'OUT1':\n                    return UnitId.CONTROLLER_OUT1;\n                case 'OUT2':\n                    return UnitId.CONTROLLER_OUT2;\n                case 'OUT3':\n                    return UnitId.CONTROLLER_OUT3;\n                case 'OUT12':\n                    return UnitId.CONTROLLER_OUT12;\n                case 'OUT123':\n                    return UnitId.CONTROLLER_OUT_ALL;\n                case 'IN1':\n                    return UnitId.CONTROLLER_IN1;\n                case 'IN2':\n                    return UnitId.CONTROLLER_IN2;\n                case 'IN3':\n                    return UnitId.CONTROLLER_IN3;\n            }\n            return UnitId.CONTROLLER;\n        }\n\n        /**\n         * 페어링 정보 요청 command (handshake 로 사용)\n         * @return {Array} Pairing Info command\n         */\n        getPairingInfoCmd() {\n            return [FrameCode.CONNECTION, PduConnectionCode.PAIRING_INFO];\n        }\n\n        makePdu(command) {\n            const pdu = [];\n            pdu.push(...HEADER);\n            pdu.push(command.length);\n            pdu.push(...command);\n            pdu.push(this.getCheckSum(command));\n            return pdu;\n        }\n\n        requestCommand(blockId, type, params) {\n            if (this.pendingResponseList[blockId]) {\n                delete this.pendingResponseList[blockId];\n            }\n            this.pendingResponseList[blockId] = 'executed';\n            const command = this.makeCommand(blockId, type, params);\n            if (!command) {\n                return;\n            }\n            const pdu = this.makePdu(command);\n            this.executeList.push({\n                blockId,\n                pdu,\n            });\n            // Entry.writePortData(pdu);\n        }\n\n        requestExtCommand(blockId, type, params) {\n            if (this.pendingResponseList[blockId]) {\n                delete this.pendingResponseList[blockId];\n            }\n            this.pendingResponseList[blockId] = 'executed';\n            const command = this.makeCommandExt(blockId, type, params);\n            if (!command) {\n                return;\n            }\n            const pdu = this.makePdu(command);\n            this.executeList.push({\n                blockId,\n                pdu,\n            });\n        }\n\n        requestExt2Command(blockId, type, params) {\n            if (this.pendingResponseList[blockId]) {\n                delete this.pendingResponseList[blockId];\n            }\n            this.pendingResponseList[blockId] = 'executed';\n            const command = this.makeCommandExt2(blockId, type, params);\n            if (!command) {\n                return;\n            }\n            const pdu = this.makePdu(command);\n            this.executeList.push({\n                blockId,\n                pdu,\n            });\n        }\n\n        generateBlockId() {\n            this.seqBlockId += 1;\n            if (this.seqBlockId > 255) {\n                this.seqBlockId = 1;\n            }\n            return this.seqBlockId;\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // robot\n                        neo_lite_robot_title: '로봇',\n                        neo_lite_robot_move: '로봇 제어하기 %1 %2 %3 %4',\n                        neo_lite_robot_stop: '로봇 멈추기 %1',\n\n                        // auto driving\n                        neo_lite_auto_driving_title: '자율주행',\n                        neo_lite_auto_driving_start: '자율주행 시작하기 %1 %2 %3',\n                        neo_lite_auto_driving_sensor_start: '%1 를 감지하여 자율주행 %2 %3',\n                        neo_lite_auto_driving_stop: '자율주행 멈추기 %1',\n\n                        // auto parking\n                        neo_lite_auto_parking_title: '자율주차 | 아이블(AiBle) 전용',\n                        neo_lite_auto_parking_start: '주차하기 %1 %2 %3',\n\n                        // line tracer\n                        neo_lite_line_tracer_title: '라인트레이서 | 아이온(AION) 전용',\n                        neo_lite_line_tracer_start: '검은색 길 따라가기 %1 %2 %3',\n                        neo_lite_line_cross_move: '%1 교차로까지 직진하기 %2',\n                        neo_lite_line_cross_turn: '방향바꾸기 %1 %2',\n                        neo_lite_line_cross_reached: '교차로에 도착하였는가?',\n\n                        // motor\n                        neo_lite_motor_title: '회전모터',\n                        neo_lite_motor_move: '회전모터 제어하기 %1 %2 %3 %4',\n                        neo_lite_motor_move_both: '회전모터 동시에 제어하기 L %1 R %2 %3',\n                        neo_lite_motor_stop: '회전모터 멈추기 %1 %2',\n\n                        // servo\n                        neo_lite_servo_title: '서보모터',\n                        neo_lite_servo_reset: '%1 서보모터 현위치를 0도로 설정하기 %2',\n                        neo_lite_servo_angle: '서보모터 각도 바꾸기 %1 %2 %3 %4',\n                        neo_lite_servo_angle_var: '서보모터 각도 바꾸기 %1 %2 %3 %4',\n                        neo_lite_servo_angle_wait: '각도 바뀔때까지 기다리기 %1 %2 %3 %4',\n                        neo_lite_servo_rotate: '서보모터 회전하기 %1 %2 %3 %4',\n                        neo_lite_servo_stop: '서보모터 멈추기 %1 %2',\n\n                        // led\n                        neo_lite_led_title: 'LED',\n                        neo_lite_led_on: 'LED 켜기 %1 %2 %3 %4',\n                        neo_lite_led_blink: 'LED 깜빡이기 %1 %2 %3 %4',\n                        neo_lite_led_off: 'LED 끄기 %1 %2',\n\n                        // set output\n                        neo_lite_set_output_title: '출력',\n                        neo_lite_set_output: '값 출력하기 %1 %2 %3 %4',\n\n                        // color led\n                        neo_lite_color_led_title: '컬러 LED',\n                        neo_lite_color_led_on: '컬러LED 켜기 %1 %2 %3 %4',\n                        neo_lite_color_led_off: '컬러LED 끄기 %1 %2',\n                        neo_lite_color_led_on_with_sensor: '컬러센서 %1 로 컬러LED %2 제어 %3',\n\n                        // sensor\n                        neo_lite_sensor_title: '센서',\n                        neo_lite_sensor_in: '%1',\n                        neo_lite_sensor_in_2: '%1',\n                        neo_lite_sensor_digital_in: '%1 의 %2',\n                        neo_lite_sensor_convert: '%1 : %2 %3 → %4 %5',\n                        neo_lite_sensor_compare: '%1 %2 %3',\n                        neo_lite_sensor_between: '%1 %2 %3 %4 %5',\n                        neo_lite_sensor_digital_compare: '%1 의 %2 %3 %4',\n                        neo_lite_sensor_color_compare: '%1 = %2',\n                        neo_lite_sensor_color_sequence_compare: '%1 = %2 %3 %4',\n                        neo_lite_sensor_button_pressed: '%1 %2',\n\n                        // buzzer\n                        neo_lite_buzzer_title: '버저',\n                        neo_lite_buzzer_start: '버저 울리기 %1 %2 %3 %4',\n                        neo_lite_buzzer_with_sensor: '센서로 버저 울리기 %1 %2',\n                        neo_lite_buzzer_stop: '버저 멈추기 %1',\n\n                        // lcd\n                        neo_lite_lcd_title: 'LCD',\n                        neo_lite_lcd_image: 'LCD에 이미지 보여주기 %1 %2 %3',\n                        neo_lite_lcd_text: 'LCD에 텍스트 보여주기 %1 %2 %3',\n\n                        // args\n                        neo_lite_arg_duration: '%1',\n                        neo_lite_arg_both_motor_speed: '%1',\n                        neo_lite_arg_servo_angle: '%1',\n                    },\n                    Blocks: {\n                        neo_lite_input_1: 'IN1',\n                        neo_lite_input_2: 'IN2',\n                        neo_lite_input_3: 'IN3',\n                        neo_lite_input_12: 'IN1&2',\n                        neo_lite_input_123: 'IN1&2&3',\n                        neo_lite_input_1_2: 'IN1&IN2',\n                        neo_lite_input_11_12: 'IN1-1&IN1-2',\n                        neo_lite_input_13_14: 'IN1-3&IN1-4',\n                        neo_lite_input_21_22: 'IN2-1&IN2-2',\n                        neo_lite_input_23_24: 'IN2-3&IN2-4',\n                        neo_lite_input_31_32: 'IN3-1&IN3-2',\n                        neo_lite_input_33_34: 'IN3-3&IN3-4',\n\n                        neo_lite_output_1: 'OUT1',\n                        neo_lite_output_2: 'OUT2',\n                        neo_lite_output_3: 'OUT3',\n                        neo_lite_output_12: 'OUT1&2',\n                        neo_lite_output_123: 'OUT1&2&3',\n\n                        neo_lite_speed_0: '0%',\n                        neo_lite_speed_5: '5%',\n                        neo_lite_speed_10: '10%',\n                        neo_lite_speed_15: '15%',\n                        neo_lite_speed_20: '20%',\n                        neo_lite_speed_25: '25%',\n                        neo_lite_speed_30: '30%',\n                        neo_lite_speed_35: '35%',\n                        neo_lite_speed_40: '40%',\n                        neo_lite_speed_45: '45%',\n                        neo_lite_speed_50: '50%',\n                        neo_lite_speed_55: '55%',\n                        neo_lite_speed_60: '60%',\n                        neo_lite_speed_65: '65%',\n                        neo_lite_speed_70: '70%',\n                        neo_lite_speed_75: '75%',\n                        neo_lite_speed_80: '80%',\n                        neo_lite_speed_85: '85%',\n                        neo_lite_speed_90: '90%',\n                        neo_lite_speed_95: '95%',\n                        neo_lite_speed_100: '100%',\n\n                        neo_lite_duration_c: '계속',\n                        neo_lite_duration_0: '0초',\n                        neo_lite_duration_1: '1초',\n                        neo_lite_duration_2: '2초',\n                        neo_lite_duration_3: '3초',\n                        neo_lite_duration_4: '4초',\n                        neo_lite_duration_5: '5초',\n                        neo_lite_duration_6: '6초',\n                        neo_lite_duration_7: '7초',\n                        neo_lite_duration_8: '8초',\n                        neo_lite_duration_9: '9초',\n\n                        neo_lite_compare_gt: '≥',\n                        neo_lite_compare_g: '>',\n                        neo_lite_compare_e: '=',\n                        neo_lite_compare_l: '<',\n                        neo_lite_compare_lt: '≤',\n\n                        neo_lite_turn_direction_l: '좌회전',\n                        neo_lite_turn_direction_r: '우회전',\n                        neo_lite_turn_direction_u: 'U턴',\n\n                        neo_lite_motor_out_l: 'L모터',\n                        neo_lite_motor_out_r: 'R모터',\n                        neo_lite_motor_out_lr: 'L/R모터',\n\n                        neo_lite_motor_speed_n100: '-100%',\n                        neo_lite_motor_speed_n95: '-95%',\n                        neo_lite_motor_speed_n90: '-90%',\n                        neo_lite_motor_speed_n85: '-85%',\n                        neo_lite_motor_speed_n80: '-80%',\n                        neo_lite_motor_speed_n75: '-75%',\n                        neo_lite_motor_speed_n70: '-70%',\n                        neo_lite_motor_speed_n65: '-65%',\n                        neo_lite_motor_speed_n60: '-60%',\n                        neo_lite_motor_speed_n55: '-55%',\n                        neo_lite_motor_speed_n50: '-50%',\n                        neo_lite_motor_speed_n45: '-45%',\n                        neo_lite_motor_speed_n40: '-40%',\n                        neo_lite_motor_speed_n35: '-35%',\n                        neo_lite_motor_speed_n30: '-30%',\n                        neo_lite_motor_speed_n25: '-25%',\n                        neo_lite_motor_speed_n20: '-20%',\n                        neo_lite_motor_speed_n15: '-15%',\n                        neo_lite_motor_speed_n10: '-10%',\n                        neo_lite_motor_speed_n5: '-5%',\n                        neo_lite_motor_speed_0: '0%',\n                        neo_lite_motor_speed_5: '5%',\n                        neo_lite_motor_speed_10: '10%',\n                        neo_lite_motor_speed_15: '15%',\n                        neo_lite_motor_speed_20: '20%',\n                        neo_lite_motor_speed_25: '25%',\n                        neo_lite_motor_speed_30: '30%',\n                        neo_lite_motor_speed_35: '35%',\n                        neo_lite_motor_speed_40: '40%',\n                        neo_lite_motor_speed_45: '45%',\n                        neo_lite_motor_speed_50: '50%',\n                        neo_lite_motor_speed_55: '55%',\n                        neo_lite_motor_speed_60: '60%',\n                        neo_lite_motor_speed_65: '65%',\n                        neo_lite_motor_speed_70: '70%',\n                        neo_lite_motor_speed_75: '75%',\n                        neo_lite_motor_speed_80: '80%',\n                        neo_lite_motor_speed_85: '85%',\n                        neo_lite_motor_speed_90: '90%',\n                        neo_lite_motor_speed_95: '95%',\n                        neo_lite_motor_speed_100: '100%',\n\n                        neo_lite_robot_direction_f: '앞으로',\n                        neo_lite_robot_direction_b: '뒤로',\n                        neo_lite_robot_direction_l: '왼쪽으로',\n                        neo_lite_robot_direction_r: '오른쪽으로',\n                        neo_lite_robot_direction_tl: '제자리왼쪽',\n                        neo_lite_robot_direction_tr: '제자리오른쪽',\n\n                        neo_lite_servo_angle_n360: '-360도',\n                        neo_lite_servo_angle_n350: '-350도',\n                        neo_lite_servo_angle_n340: '-340도',\n                        neo_lite_servo_angle_n330: '-330도',\n                        neo_lite_servo_angle_n320: '-320도',\n                        neo_lite_servo_angle_n310: '-310도',\n                        neo_lite_servo_angle_n300: '-300도',\n                        neo_lite_servo_angle_n290: '-290도',\n                        neo_lite_servo_angle_n280: '-280도',\n                        neo_lite_servo_angle_n270: '-270도',\n                        neo_lite_servo_angle_n260: '-260도',\n                        neo_lite_servo_angle_n250: '-250도',\n                        neo_lite_servo_angle_n240: '-240도',\n                        neo_lite_servo_angle_n230: '-230도',\n                        neo_lite_servo_angle_n220: '-220도',\n                        neo_lite_servo_angle_n210: '-210도',\n                        neo_lite_servo_angle_n200: '-200도',\n                        neo_lite_servo_angle_n190: '-190도',\n                        neo_lite_servo_angle_n180: '-180도',\n                        neo_lite_servo_angle_n170: '-170도',\n                        neo_lite_servo_angle_n160: '-160도',\n                        neo_lite_servo_angle_n150: '-150도',\n                        neo_lite_servo_angle_n140: '-140도',\n                        neo_lite_servo_angle_n130: '-130도',\n                        neo_lite_servo_angle_n120: '-120도',\n                        neo_lite_servo_angle_n110: '-110도',\n                        neo_lite_servo_angle_n100: '-100도',\n                        neo_lite_servo_angle_n90: '-90도',\n                        neo_lite_servo_angle_n80: '-80도',\n                        neo_lite_servo_angle_n70: '-70도',\n                        neo_lite_servo_angle_n60: '-60도',\n                        neo_lite_servo_angle_n50: '-50도',\n                        neo_lite_servo_angle_n40: '-40도',\n                        neo_lite_servo_angle_n30: '-30도',\n                        neo_lite_servo_angle_n20: '-20도',\n                        neo_lite_servo_angle_n10: '-10도',\n                        neo_lite_servo_angle_0: '0도',\n                        neo_lite_servo_angle_10: '10도',\n                        neo_lite_servo_angle_20: '20도',\n                        neo_lite_servo_angle_30: '30도',\n                        neo_lite_servo_angle_40: '40도',\n                        neo_lite_servo_angle_50: '50도',\n                        neo_lite_servo_angle_60: '60도',\n                        neo_lite_servo_angle_70: '70도',\n                        neo_lite_servo_angle_80: '80도',\n                        neo_lite_servo_angle_90: '90도',\n                        neo_lite_servo_angle_100: '100도',\n                        neo_lite_servo_angle_110: '110도',\n                        neo_lite_servo_angle_120: '120도',\n                        neo_lite_servo_angle_130: '130도',\n                        neo_lite_servo_angle_140: '140도',\n                        neo_lite_servo_angle_150: '150도',\n                        neo_lite_servo_angle_160: '160도',\n                        neo_lite_servo_angle_170: '170도',\n                        neo_lite_servo_angle_180: '180도',\n                        neo_lite_servo_angle_190: '190도',\n                        neo_lite_servo_angle_200: '200도',\n                        neo_lite_servo_angle_210: '210도',\n                        neo_lite_servo_angle_220: '220도',\n                        neo_lite_servo_angle_230: '230도',\n                        neo_lite_servo_angle_240: '240도',\n                        neo_lite_servo_angle_250: '250도',\n                        neo_lite_servo_angle_260: '260도',\n                        neo_lite_servo_angle_270: '270도',\n                        neo_lite_servo_angle_280: '280도',\n                        neo_lite_servo_angle_290: '290도',\n                        neo_lite_servo_angle_300: '300도',\n                        neo_lite_servo_angle_310: '310도',\n                        neo_lite_servo_angle_320: '320도',\n                        neo_lite_servo_angle_330: '330도',\n                        neo_lite_servo_angle_340: '340도',\n                        neo_lite_servo_angle_350: '350도',\n                        neo_lite_servo_angle_360: '360도',\n\n                        neo_lite_servo_direction_f: '앞으로',\n                        neo_lite_servo_direction_b: '뒤로',\n\n                        neo_lite_line_cross_move_1: '첫번째',\n                        neo_lite_line_cross_move_2: '두번째',\n                        neo_lite_line_cross_move_3: '세번째',\n                        neo_lite_line_cross_move_4: '네번째',\n                        neo_lite_line_cross_move_5: '다섯번째',\n                        neo_lite_line_cross_move_6: '여섯번째',\n                        neo_lite_line_cross_move_7: '일곱번째',\n                        neo_lite_line_cross_move_8: '여덟번째',\n                        neo_lite_line_cross_move_9: '아홉번째',\n                        neo_lite_line_cross_move_10: '열번째',\n\n                        neo_lite_line_cross_turn_direction_l: '좌회전',\n                        neo_lite_line_cross_turn_direction_r: '우회전',\n                        neo_lite_line_cross_turn_direction_u: 'U턴',\n\n                        neo_lite_line_cross_turn_which_next: '다음',\n                        neo_lite_line_cross_turn_which_current: '현재',\n\n                        neo_lite_auto_driving_speed_in3: 'IN3',\n\n                        neo_lite_auto_parking_which_l: '왼쪽에',\n                        neo_lite_auto_parking_which_r: '오른쪽에',\n\n                        neo_lite_auto_parking_direction_b: '후면주차',\n                        neo_lite_auto_parking_direction_s: '평행주차',\n\n                        neo_lite_led_brightness_0: '0%',\n                        neo_lite_led_brightness_5: '5%',\n                        neo_lite_led_brightness_10: '10%',\n                        neo_lite_led_brightness_15: '15%',\n                        neo_lite_led_brightness_20: '20%',\n                        neo_lite_led_brightness_25: '25%',\n                        neo_lite_led_brightness_30: '30%',\n                        neo_lite_led_brightness_35: '35%',\n                        neo_lite_led_brightness_40: '40%',\n                        neo_lite_led_brightness_45: '45%',\n                        neo_lite_led_brightness_50: '50%',\n                        neo_lite_led_brightness_55: '55%',\n                        neo_lite_led_brightness_60: '60%',\n                        neo_lite_led_brightness_65: '65%',\n                        neo_lite_led_brightness_70: '70%',\n                        neo_lite_led_brightness_75: '75%',\n                        neo_lite_led_brightness_80: '80%',\n                        neo_lite_led_brightness_85: '85%',\n                        neo_lite_led_brightness_90: '90%',\n                        neo_lite_led_brightness_95: '95%',\n                        neo_lite_led_brightness_100: '100%',\n\n                        neo_lite_led_blink_speed_1: '1단계',\n                        neo_lite_led_blink_speed_2: '2단계',\n                        neo_lite_led_blink_speed_3: '3단계',\n                        neo_lite_led_blink_speed_4: '4단계',\n                        neo_lite_led_blink_speed_5: '5단계',\n\n                        neo_lite_set_output_value_0: '0',\n                        neo_lite_set_output_value_5: '5',\n                        neo_lite_set_output_value_10: '10',\n                        neo_lite_set_output_value_15: '15',\n                        neo_lite_set_output_value_20: '20',\n                        neo_lite_set_output_value_25: '25',\n                        neo_lite_set_output_value_30: '30',\n                        neo_lite_set_output_value_35: '35',\n                        neo_lite_set_output_value_40: '40',\n                        neo_lite_set_output_value_45: '45',\n                        neo_lite_set_output_value_50: '50',\n                        neo_lite_set_output_value_55: '55',\n                        neo_lite_set_output_value_60: '60',\n                        neo_lite_set_output_value_65: '65',\n                        neo_lite_set_output_value_70: '70',\n                        neo_lite_set_output_value_75: '75',\n                        neo_lite_set_output_value_80: '80',\n                        neo_lite_set_output_value_85: '85',\n                        neo_lite_set_output_value_90: '90',\n                        neo_lite_set_output_value_95: '95',\n                        neo_lite_set_output_value_100: '100',\n                        neo_lite_set_output_value_105: '105',\n                        neo_lite_set_output_value_110: '110',\n                        neo_lite_set_output_value_115: '115',\n                        neo_lite_set_output_value_120: '120',\n                        neo_lite_set_output_value_125: '125',\n                        neo_lite_set_output_value_130: '130',\n                        neo_lite_set_output_value_135: '135',\n                        neo_lite_set_output_value_140: '140',\n                        neo_lite_set_output_value_145: '145',\n                        neo_lite_set_output_value_150: '150',\n                        neo_lite_set_output_value_155: '155',\n                        neo_lite_set_output_value_160: '160',\n                        neo_lite_set_output_value_165: '165',\n                        neo_lite_set_output_value_170: '170',\n                        neo_lite_set_output_value_175: '175',\n                        neo_lite_set_output_value_180: '180',\n                        neo_lite_set_output_value_185: '185',\n                        neo_lite_set_output_value_190: '190',\n                        neo_lite_set_output_value_195: '195',\n                        neo_lite_set_output_value_200: '200',\n                        neo_lite_set_output_value_205: '205',\n                        neo_lite_set_output_value_210: '210',\n                        neo_lite_set_output_value_215: '215',\n                        neo_lite_set_output_value_220: '220',\n                        neo_lite_set_output_value_225: '225',\n                        neo_lite_set_output_value_230: '230',\n                        neo_lite_set_output_value_235: '235',\n                        neo_lite_set_output_value_240: '240',\n                        neo_lite_set_output_value_245: '245',\n                        neo_lite_set_output_value_250: '250',\n                        neo_lite_set_output_value_255: '255',\n\n                        neo_lite_sensor_in_digital_1: '1번',\n                        neo_lite_sensor_in_digital_2: '2번',\n                        neo_lite_sensor_in_digital_3: '3번',\n                        neo_lite_sensor_in_digital_4: '4번',\n\n                        neo_lite_color_black: '검정',\n                        neo_lite_color_white: '흰색',\n                        neo_lite_color_red: '빨강',\n                        neo_lite_color_yellow: '노랑',\n                        neo_lite_color_green: '초록',\n                        neo_lite_color_blue: '파랑',\n\n                        neo_lite_button_1: '버튼1',\n                        neo_lite_button_2: '버튼2',\n                        neo_lite_button_3: '버튼3',\n                        neo_lite_button_4: '버튼4',\n\n                        neo_lite_button_on: 'ON',\n                        neo_lite_button_off: 'OFF',\n\n                        neo_lite_buzzer_octave_1: '1옥타브',\n                        neo_lite_buzzer_octave_2: '2옥타브',\n                        neo_lite_buzzer_octave_3: '3옥타브',\n                        neo_lite_buzzer_octave_4: '4옥타브',\n                        neo_lite_buzzer_octave_5: '5옥타브',\n                        neo_lite_buzzer_octave_6: '6옥타브',\n\n                        neo_lite_buzzer_do: '도',\n                        neo_lite_buzzer_do_sharp: '도#',\n                        neo_lite_buzzer_re: '레',\n                        neo_lite_buzzer_re_sharp: '레#',\n                        neo_lite_buzzer_mi: '미',\n                        neo_lite_buzzer_fa: '파',\n                        neo_lite_buzzer_fa_sharp: '파#',\n                        neo_lite_buzzer_sol: '솔',\n                        neo_lite_buzzer_sol_sharp: '솔#',\n                        neo_lite_buzzer_la: '라',\n                        neo_lite_buzzer_la_sharp: '라#',\n                        neo_lite_buzzer_ti: '시',\n\n                        neo_lite_buzzer_whole_note: '온음표',\n                        neo_lite_buzzer_half_note: '2분 음표',\n                        neo_lite_buzzer_quarter_note: '4분 음표',\n                        neo_lite_buzzer_8th_note: '8분 음표',\n\n                        neo_lite_lcd_image_1: '화남',\n                        neo_lite_lcd_image_2: '어지러움',\n                        neo_lite_lcd_image_3: '똑똑함',\n                        neo_lite_lcd_image_4: '활기참',\n                        neo_lite_lcd_image_5: '뽀뽀',\n                        neo_lite_lcd_image_6: '사랑해',\n                        neo_lite_lcd_image_7: '윙크',\n                        neo_lite_lcd_image_8: '폭풍눈물',\n                        neo_lite_lcd_image_9: '졸림',\n                        neo_lite_lcd_image_10: '미소',\n                        neo_lite_lcd_image_11: '깜찍함',\n                        neo_lite_lcd_image_12: '의심',\n                        neo_lite_lcd_image_13: '못마땅',\n                    },\n                },\n                en: {\n                    // en.js에 작성하던 내용\n                    template: {\n                        // robot\n                        neo_lite_robot_title: 'Robot',\n                        neo_lite_robot_move: 'Move robot %1 %2 %3 %4',\n                        neo_lite_robot_stop: 'Stop robot %1',\n\n                        // auto driving\n                        neo_lite_auto_driving_title: 'Self-driving',\n                        neo_lite_auto_driving_start: 'Start self-driving %1 %2 %3',\n                        neo_lite_auto_driving_sensor_start: 'Start self-driving with %1 %2 %3',\n                        neo_lite_auto_driving_stop: 'Stop self-driving %1',\n\n                        // auto parking\n                        neo_lite_auto_parking_title: 'Auto parking | AiBle-only',\n                        neo_lite_auto_parking_start: 'Start auto parking %1 %2 %3',\n\n                        // line tracer\n                        neo_lite_line_tracer_title: 'Line tracer | AION-only',\n                        neo_lite_line_tracer_start: 'Start line tracer with black line %1 %2 %3',\n                        neo_lite_line_cross_move: 'Keep moving to the %1 intersection %2',\n                        neo_lite_line_cross_turn: 'Turn %2 at the %1 intersection %3',\n                        neo_lite_line_cross_reached: 'Reached an intersection?',\n\n                        // motor\n                        neo_lite_motor_title: 'Motor',\n                        neo_lite_motor_move: 'Move motor %1 %2 %3 %4',\n                        neo_lite_motor_move_both: 'Move both motor L %1 R %2 %3',\n                        neo_lite_motor_stop: 'Stop motor %1 %2',\n\n                        // servo\n                        neo_lite_servo_title: 'Servo motor',\n                        neo_lite_servo_reset:\n                            'Reset the current position of %1 servo motor to 0 degree %2',\n                        neo_lite_servo_angle: 'Change servo angle %1 %2 %3 %4',\n                        neo_lite_servo_angle_var: 'Change servo angle %1 %2 %3 %4',\n                        neo_lite_servo_angle_wait: 'Wait to change servo angle %1 %2 %3 %4',\n                        neo_lite_servo_rotate: 'Rotate servo motor %1 %2 %3 %4',\n                        neo_lite_servo_stop: 'Stop servo motor %1 %2',\n\n                        // led\n                        neo_lite_led_title: 'LED',\n                        neo_lite_led_on: 'Turn on the LED %1 %2 %3 %4',\n                        neo_lite_led_blink: 'Blink the LED %1 %2 %3 %4',\n                        neo_lite_led_off: 'Turn off the LED %1 %2',\n\n                        // color led\n                        neo_lite_color_led_title: 'Color LED',\n                        neo_lite_color_led_on: 'Turn on the color LED %1 %2 %3 %4',\n                        neo_lite_color_led_off: 'Turn off the color LED %1 %2',\n                        neo_lite_color_led_on_with_sensor:\n                            'Turn on the color LED %2 with color sensor %1 %3',\n\n                        // set output\n                        neo_lite_set_output_title: 'Set output',\n                        neo_lite_set_output: 'Set output %1 %2 %3 %4',\n\n                        // sensor\n                        neo_lite_sensor_title: 'Sensor',\n                        neo_lite_sensor_in: '%1',\n                        neo_lite_sensor_in_2: '%1',\n                        neo_lite_sensor_digital_in: '%1 %2',\n                        neo_lite_sensor_convert: '%1 : %2 %3 → %4 %5',\n                        neo_lite_sensor_compare: '%1 %2 %3',\n                        neo_lite_sensor_between: '%1 %2 %3 %4 %5',\n                        neo_lite_sensor_digital_compare: '%1 %2 %3 %4',\n                        neo_lite_sensor_color_compare: '%1 = %2',\n                        neo_lite_sensor_color_sequence_compare: '%1 = %2 %3 %4',\n                        neo_lite_sensor_button_pressed: '%1 %2',\n\n                        // buzzer\n                        neo_lite_buzzer_title: 'Buzzer',\n                        neo_lite_buzzer_start: 'Buzzer %1 %2 %3 %4',\n                        neo_lite_buzzer_with_sensor: 'Buzzer by sensor value %1 %2',\n                        neo_lite_buzzer_stop: 'Stop the buzzer %1',\n\n                        // lcd\n                        neo_lite_lcd_title: 'LCD',\n                        neo_lite_lcd_image: 'Show image on LCD %1 %2 %3',\n                        neo_lite_lcd_text: 'Show text on LCD %1 %2 %3',\n\n                        // args\n                        neo_lite_arg_duration: '%1',\n                        neo_lite_arg_both_motor_speed: '%1',\n                        neo_lite_arg_servo_angle: '%1',\n                    },\n                    Blocks: {\n                        neo_lite_input_1: 'IN1',\n                        neo_lite_input_2: 'IN2',\n                        neo_lite_input_3: 'IN3',\n                        neo_lite_input_12: 'IN1&2',\n                        neo_lite_input_123: 'IN1&2&3',\n                        neo_lite_input_1_2: 'IN1&IN2',\n                        neo_lite_input_11_12: 'IN1-1&IN1-2',\n                        neo_lite_input_13_14: 'IN1-3&IN1-4',\n                        neo_lite_input_21_22: 'IN2-1&IN2-2',\n                        neo_lite_input_23_24: 'IN2-3&IN2-4',\n                        neo_lite_input_31_32: 'IN3-1&IN3-2',\n                        neo_lite_input_33_34: 'IN3-3&IN3-4',\n\n                        neo_lite_output_1: 'OUT1',\n                        neo_lite_output_2: 'OUT2',\n                        neo_lite_output_3: 'OUT3',\n                        neo_lite_output_12: 'OUT1&2',\n                        neo_lite_output_123: 'OUT1&2&3',\n\n                        neo_lite_speed_0: '0%',\n                        neo_lite_speed_5: '5%',\n                        neo_lite_speed_10: '10%',\n                        neo_lite_speed_15: '15%',\n                        neo_lite_speed_20: '20%',\n                        neo_lite_speed_25: '25%',\n                        neo_lite_speed_30: '30%',\n                        neo_lite_speed_35: '35%',\n                        neo_lite_speed_40: '40%',\n                        neo_lite_speed_45: '45%',\n                        neo_lite_speed_50: '50%',\n                        neo_lite_speed_55: '55%',\n                        neo_lite_speed_60: '60%',\n                        neo_lite_speed_65: '65%',\n                        neo_lite_speed_70: '70%',\n                        neo_lite_speed_75: '75%',\n                        neo_lite_speed_80: '80%',\n                        neo_lite_speed_85: '85%',\n                        neo_lite_speed_90: '90%',\n                        neo_lite_speed_95: '95%',\n                        neo_lite_speed_100: '100%',\n\n                        neo_lite_duration_c: 'constantly',\n                        neo_lite_duration_0: '0 second',\n                        neo_lite_duration_1: '1 second',\n                        neo_lite_duration_2: '2 seconds',\n                        neo_lite_duration_3: '3 seconds',\n                        neo_lite_duration_4: '4 seconds',\n                        neo_lite_duration_5: '5 seconds',\n                        neo_lite_duration_6: '6 seconds',\n                        neo_lite_duration_7: '7 seconds',\n                        neo_lite_duration_8: '8 seconds',\n                        neo_lite_duration_9: '9 seconds',\n\n                        neo_lite_compare_gt: '≥',\n                        neo_lite_compare_g: '>',\n                        neo_lite_compare_e: '=',\n                        neo_lite_compare_l: '<',\n                        neo_lite_compare_lt: '≤',\n\n                        neo_lite_turn_direction_l: 'left',\n                        neo_lite_turn_direction_r: 'right',\n                        neo_lite_turn_direction_u: 'U-turn',\n\n                        neo_lite_motor_out_l: 'left',\n                        neo_lite_motor_out_r: 'right',\n                        neo_lite_motor_out_lr: 'both',\n\n                        neo_lite_motor_speed_n100: '-100%',\n                        neo_lite_motor_speed_n95: '-95%',\n                        neo_lite_motor_speed_n90: '-90%',\n                        neo_lite_motor_speed_n85: '-85%',\n                        neo_lite_motor_speed_n80: '-80%',\n                        neo_lite_motor_speed_n75: '-75%',\n                        neo_lite_motor_speed_n70: '-70%',\n                        neo_lite_motor_speed_n65: '-65%',\n                        neo_lite_motor_speed_n60: '-60%',\n                        neo_lite_motor_speed_n55: '-55%',\n                        neo_lite_motor_speed_n50: '-50%',\n                        neo_lite_motor_speed_n45: '-45%',\n                        neo_lite_motor_speed_n40: '-40%',\n                        neo_lite_motor_speed_n35: '-35%',\n                        neo_lite_motor_speed_n30: '-30%',\n                        neo_lite_motor_speed_n25: '-25%',\n                        neo_lite_motor_speed_n20: '-20%',\n                        neo_lite_motor_speed_n15: '-15%',\n                        neo_lite_motor_speed_n10: '-10%',\n                        neo_lite_motor_speed_n5: '-5%',\n                        neo_lite_motor_speed_0: '0%',\n                        neo_lite_motor_speed_5: '5%',\n                        neo_lite_motor_speed_10: '10%',\n                        neo_lite_motor_speed_15: '15%',\n                        neo_lite_motor_speed_20: '20%',\n                        neo_lite_motor_speed_25: '25%',\n                        neo_lite_motor_speed_30: '30%',\n                        neo_lite_motor_speed_35: '35%',\n                        neo_lite_motor_speed_40: '40%',\n                        neo_lite_motor_speed_45: '45%',\n                        neo_lite_motor_speed_50: '50%',\n                        neo_lite_motor_speed_55: '55%',\n                        neo_lite_motor_speed_60: '60%',\n                        neo_lite_motor_speed_65: '65%',\n                        neo_lite_motor_speed_70: '70%',\n                        neo_lite_motor_speed_75: '75%',\n                        neo_lite_motor_speed_80: '80%',\n                        neo_lite_motor_speed_85: '85%',\n                        neo_lite_motor_speed_90: '90%',\n                        neo_lite_motor_speed_95: '95%',\n                        neo_lite_motor_speed_100: '100%',\n\n                        neo_lite_robot_direction_f: 'forward',\n                        neo_lite_robot_direction_b: 'backward',\n                        neo_lite_robot_direction_l: 'left',\n                        neo_lite_robot_direction_r: 'right',\n                        neo_lite_robot_direction_tl: 'left in place',\n                        neo_lite_robot_direction_tr: 'right in place',\n\n                        neo_lite_servo_angle_n360: '-360 degree',\n                        neo_lite_servo_angle_n350: '-350 degree',\n                        neo_lite_servo_angle_n340: '-340 degree',\n                        neo_lite_servo_angle_n330: '-330 degree',\n                        neo_lite_servo_angle_n320: '-320 degree',\n                        neo_lite_servo_angle_n310: '-310 degree',\n                        neo_lite_servo_angle_n300: '-300 degree',\n                        neo_lite_servo_angle_n290: '-290 degree',\n                        neo_lite_servo_angle_n280: '-280 degree',\n                        neo_lite_servo_angle_n270: '-270 degree',\n                        neo_lite_servo_angle_n260: '-260 degree',\n                        neo_lite_servo_angle_n250: '-250 degree',\n                        neo_lite_servo_angle_n240: '-240 degree',\n                        neo_lite_servo_angle_n230: '-230 degree',\n                        neo_lite_servo_angle_n220: '-220 degree',\n                        neo_lite_servo_angle_n210: '-210 degree',\n                        neo_lite_servo_angle_n200: '-200 degree',\n                        neo_lite_servo_angle_n190: '-190 degree',\n                        neo_lite_servo_angle_n180: '-180 degree',\n                        neo_lite_servo_angle_n170: '-170 degree',\n                        neo_lite_servo_angle_n160: '-160 degree',\n                        neo_lite_servo_angle_n150: '-150 degree',\n                        neo_lite_servo_angle_n140: '-140 degree',\n                        neo_lite_servo_angle_n130: '-130 degree',\n                        neo_lite_servo_angle_n120: '-120 degree',\n                        neo_lite_servo_angle_n110: '-110 degree',\n                        neo_lite_servo_angle_n100: '-100 degree',\n                        neo_lite_servo_angle_n90: '-90 degree',\n                        neo_lite_servo_angle_n80: '-80 degree',\n                        neo_lite_servo_angle_n70: '-70 degree',\n                        neo_lite_servo_angle_n60: '-60 degree',\n                        neo_lite_servo_angle_n50: '-50 degree',\n                        neo_lite_servo_angle_n40: '-40 degree',\n                        neo_lite_servo_angle_n30: '-30 degree',\n                        neo_lite_servo_angle_n20: '-20 degree',\n                        neo_lite_servo_angle_n10: '-10 degree',\n                        neo_lite_servo_angle_0: '0 degree',\n                        neo_lite_servo_angle_10: '10 degree',\n                        neo_lite_servo_angle_20: '20 degree',\n                        neo_lite_servo_angle_30: '30 degree',\n                        neo_lite_servo_angle_40: '40 degree',\n                        neo_lite_servo_angle_50: '50 degree',\n                        neo_lite_servo_angle_60: '60 degree',\n                        neo_lite_servo_angle_70: '70 degree',\n                        neo_lite_servo_angle_80: '80 degree',\n                        neo_lite_servo_angle_90: '90 degree',\n                        neo_lite_servo_angle_100: '100 degree',\n                        neo_lite_servo_angle_110: '110 degree',\n                        neo_lite_servo_angle_120: '120 degree',\n                        neo_lite_servo_angle_130: '130 degree',\n                        neo_lite_servo_angle_140: '140 degree',\n                        neo_lite_servo_angle_150: '150 degree',\n                        neo_lite_servo_angle_160: '160 degree',\n                        neo_lite_servo_angle_170: '170 degree',\n                        neo_lite_servo_angle_180: '180 degree',\n                        neo_lite_servo_angle_190: '190 degree',\n                        neo_lite_servo_angle_200: '200 degree',\n                        neo_lite_servo_angle_210: '210 degree',\n                        neo_lite_servo_angle_220: '220 degree',\n                        neo_lite_servo_angle_230: '230 degree',\n                        neo_lite_servo_angle_240: '240 degree',\n                        neo_lite_servo_angle_250: '250 degree',\n                        neo_lite_servo_angle_260: '260 degree',\n                        neo_lite_servo_angle_270: '270 degree',\n                        neo_lite_servo_angle_280: '280 degree',\n                        neo_lite_servo_angle_290: '290 degree',\n                        neo_lite_servo_angle_300: '300 degree',\n                        neo_lite_servo_angle_310: '310 degree',\n                        neo_lite_servo_angle_320: '320 degree',\n                        neo_lite_servo_angle_330: '330 degree',\n                        neo_lite_servo_angle_340: '340 degree',\n                        neo_lite_servo_angle_350: '350 degree',\n                        neo_lite_servo_angle_360: '360 degree',\n\n                        neo_lite_servo_direction_f: 'forward',\n                        neo_lite_servo_direction_b: 'backward',\n\n                        neo_lite_line_cross_move_1: '1st',\n                        neo_lite_line_cross_move_2: '2nd',\n                        neo_lite_line_cross_move_3: '3rd',\n                        neo_lite_line_cross_move_4: '4th',\n                        neo_lite_line_cross_move_5: '5th',\n                        neo_lite_line_cross_move_6: '6th',\n                        neo_lite_line_cross_move_7: '7th',\n                        neo_lite_line_cross_move_8: '8th',\n                        neo_lite_line_cross_move_9: '9th',\n                        neo_lite_line_cross_move_10: '10th',\n\n                        neo_lite_line_cross_turn_direction_l: 'to left',\n                        neo_lite_line_cross_turn_direction_r: 'to right',\n                        neo_lite_line_cross_turn_direction_u: 'U-turn',\n\n                        neo_lite_line_cross_turn_which_next: 'next',\n                        neo_lite_line_cross_turn_which_current: 'current',\n\n                        neo_lite_auto_driving_speed_in3: 'IN3',\n\n                        neo_lite_auto_parking_which_l: 'to left',\n                        neo_lite_auto_parking_which_r: 'to right',\n\n                        neo_lite_auto_parking_direction_b: 'rear parking',\n                        neo_lite_auto_parking_direction_s: 'parallel parking',\n\n                        neo_lite_led_brightness_0: '0%',\n                        neo_lite_led_brightness_5: '5%',\n                        neo_lite_led_brightness_10: '10%',\n                        neo_lite_led_brightness_15: '15%',\n                        neo_lite_led_brightness_20: '20%',\n                        neo_lite_led_brightness_25: '25%',\n                        neo_lite_led_brightness_30: '30%',\n                        neo_lite_led_brightness_35: '35%',\n                        neo_lite_led_brightness_40: '40%',\n                        neo_lite_led_brightness_45: '45%',\n                        neo_lite_led_brightness_50: '50%',\n                        neo_lite_led_brightness_55: '55%',\n                        neo_lite_led_brightness_60: '60%',\n                        neo_lite_led_brightness_65: '65%',\n                        neo_lite_led_brightness_70: '70%',\n                        neo_lite_led_brightness_75: '75%',\n                        neo_lite_led_brightness_80: '80%',\n                        neo_lite_led_brightness_85: '85%',\n                        neo_lite_led_brightness_90: '90%',\n                        neo_lite_led_brightness_95: '95%',\n                        neo_lite_led_brightness_100: '100%',\n\n                        neo_lite_led_blink_speed_1: 'stage 1',\n                        neo_lite_led_blink_speed_2: 'stage 2',\n                        neo_lite_led_blink_speed_3: 'stage 3',\n                        neo_lite_led_blink_speed_4: 'stage 4',\n                        neo_lite_led_blink_speed_5: 'stage 5',\n\n                        neo_lite_set_output_value_0: '0',\n                        neo_lite_set_output_value_5: '5',\n                        neo_lite_set_output_value_10: '10',\n                        neo_lite_set_output_value_15: '15',\n                        neo_lite_set_output_value_20: '20',\n                        neo_lite_set_output_value_25: '25',\n                        neo_lite_set_output_value_30: '30',\n                        neo_lite_set_output_value_35: '35',\n                        neo_lite_set_output_value_40: '40',\n                        neo_lite_set_output_value_45: '45',\n                        neo_lite_set_output_value_50: '50',\n                        neo_lite_set_output_value_55: '55',\n                        neo_lite_set_output_value_60: '60',\n                        neo_lite_set_output_value_65: '65',\n                        neo_lite_set_output_value_70: '70',\n                        neo_lite_set_output_value_75: '75',\n                        neo_lite_set_output_value_80: '80',\n                        neo_lite_set_output_value_85: '85',\n                        neo_lite_set_output_value_90: '90',\n                        neo_lite_set_output_value_95: '95',\n                        neo_lite_set_output_value_100: '100',\n                        neo_lite_set_output_value_105: '105',\n                        neo_lite_set_output_value_110: '110',\n                        neo_lite_set_output_value_115: '115',\n                        neo_lite_set_output_value_120: '120',\n                        neo_lite_set_output_value_125: '125',\n                        neo_lite_set_output_value_130: '130',\n                        neo_lite_set_output_value_135: '135',\n                        neo_lite_set_output_value_140: '140',\n                        neo_lite_set_output_value_145: '145',\n                        neo_lite_set_output_value_150: '150',\n                        neo_lite_set_output_value_155: '155',\n                        neo_lite_set_output_value_160: '160',\n                        neo_lite_set_output_value_165: '165',\n                        neo_lite_set_output_value_170: '170',\n                        neo_lite_set_output_value_175: '175',\n                        neo_lite_set_output_value_180: '180',\n                        neo_lite_set_output_value_185: '185',\n                        neo_lite_set_output_value_190: '190',\n                        neo_lite_set_output_value_195: '195',\n                        neo_lite_set_output_value_200: '200',\n                        neo_lite_set_output_value_205: '205',\n                        neo_lite_set_output_value_210: '210',\n                        neo_lite_set_output_value_215: '215',\n                        neo_lite_set_output_value_220: '220',\n                        neo_lite_set_output_value_225: '225',\n                        neo_lite_set_output_value_230: '230',\n                        neo_lite_set_output_value_235: '235',\n                        neo_lite_set_output_value_240: '240',\n                        neo_lite_set_output_value_245: '245',\n                        neo_lite_set_output_value_250: '250',\n                        neo_lite_set_output_value_255: '255',\n\n                        neo_lite_sensor_in_digital_1: '1st',\n                        neo_lite_sensor_in_digital_2: '2nd',\n                        neo_lite_sensor_in_digital_3: '3rd',\n                        neo_lite_sensor_in_digital_4: '4th',\n\n                        neo_lite_color_black: 'black',\n                        neo_lite_color_white: 'white',\n                        neo_lite_color_red: 'red',\n                        neo_lite_color_yellow: 'yellow',\n                        neo_lite_color_green: 'green',\n                        neo_lite_color_blue: 'blue',\n\n                        neo_lite_button_1: 'button 1',\n                        neo_lite_button_2: 'button 2',\n                        neo_lite_button_3: 'button 3',\n                        neo_lite_button_4: 'button 4',\n\n                        neo_lite_button_on: 'ON',\n                        neo_lite_button_off: 'OFF',\n\n                        neo_lite_buzzer_octave_1: '1 octave',\n                        neo_lite_buzzer_octave_2: '2 octave',\n                        neo_lite_buzzer_octave_3: '3 octave',\n                        neo_lite_buzzer_octave_4: '4 octave',\n                        neo_lite_buzzer_octave_5: '5 octave',\n                        neo_lite_buzzer_octave_6: '6 octave',\n\n                        neo_lite_buzzer_do: 'Do',\n                        neo_lite_buzzer_do_sharp: 'Do#',\n                        neo_lite_buzzer_re: 'Re',\n                        neo_lite_buzzer_re_sharp: 'Re#',\n                        neo_lite_buzzer_mi: 'Mi',\n                        neo_lite_buzzer_fa: 'Fa',\n                        neo_lite_buzzer_fa_sharp: 'Fa#',\n                        neo_lite_buzzer_sol: 'So',\n                        neo_lite_buzzer_sol_sharp: 'So#',\n                        neo_lite_buzzer_la: 'La',\n                        neo_lite_buzzer_la_sharp: 'La#',\n                        neo_lite_buzzer_ti: 'Si',\n\n                        neo_lite_buzzer_whole_note: 'whole note',\n                        neo_lite_buzzer_half_note: 'a half note',\n                        neo_lite_buzzer_quarter_note: 'a quarter note',\n                        neo_lite_buzzer_8th_note: 'a eighth note',\n\n                        neo_lite_lcd_image_1: 'angry',\n                        neo_lite_lcd_image_2: 'dizzy',\n                        neo_lite_lcd_image_3: 'smart',\n                        neo_lite_lcd_image_4: 'lively',\n                        neo_lite_lcd_image_5: 'kiss',\n                        neo_lite_lcd_image_6: 'lovely',\n                        neo_lite_lcd_image_7: 'wink',\n                        neo_lite_lcd_image_8: 'cry',\n                        neo_lite_lcd_image_9: 'sleepy',\n                        neo_lite_lcd_image_10: 'smiley',\n                        neo_lite_lcd_image_11: 'cute',\n                        neo_lite_lcd_image_12: 'doubt',\n                        neo_lite_lcd_image_13: 'bad',\n                    },\n                }, //\n            };\n        }\n\n        getBlocks() {\n            return {\n                /**\n                 * 로봇\n                 */\n                neo_lite_robot_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_robot_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_robot_title',\n                    },\n                    class: 'neo_lite_robot',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_robot_move: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_robot_direction_f, 1],\n                                [Lang.Blocks.neo_lite_robot_direction_b, 2],\n                                [Lang.Blocks.neo_lite_robot_direction_l, 3],\n                                [Lang.Blocks.neo_lite_robot_direction_r, 4],\n                                [Lang.Blocks.neo_lite_robot_direction_tl, 5],\n                                [Lang.Blocks.neo_lite_robot_direction_tr, 6],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_95, '95'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_85, '85'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_75, '75'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_65, '65'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_55, '55'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_45, '45'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_35, '35'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_25, '25'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_15, '15'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_5, '5'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '100',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neo_lite_arg_duration',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_robot_move',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                        SPEED: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neo_lite_robot',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const direction = script.getNumberField('DIRECTION');\n                            const speed = script.getStringField('SPEED');\n                            const duration = script.getStringValue('DURATION', script);\n                            const blockId = this.generateBlockId();\n                            if (speed.indexOf('IN') >= 0) {\n                                this.requestExtCommand(blockId, NeoBlockType.ROBOT_MOVE, [\n                                    direction,\n                                    speed,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [\n                                    direction,\n                                    speed,\n                                ]);\n                            }\n                            if (duration === 'c' || !Entry.parseNumber(duration)) {\n                                script.block_id = blockId;\n                                script.exec_phase = ExecPhase.PENDING_STOP;\n                            } else {\n                                script.exec_phase = ExecPhase.SET_TIMEOUT;\n                            }\n                        } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                            const duration = script.getStringValue('DURATION', script);\n                            const durationValue = Entry.parseNumber(duration);\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            setTimeout(() => {\n                                script.exec_phase = ExecPhase.STOP;\n                            }, durationValue * 1000);\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const direction = script.getNumberField('DIRECTION', script);\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [direction, 0]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_robot_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neo_lite_robot_stop',\n                    },\n                    paramsKeyMap: {\n                        //\n                    },\n                    class: 'neo_lite_robot',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            this.requestCommand(blockId, NeoBlockType.ROBOT_STOP, []);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n\n                /**\n                 * 자율주행\n                 */\n                neo_lite_auto_driving_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_auto_driving_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_auto_driving_title',\n                    },\n                    class: 'neo_lite_auto_driving',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_auto_driving_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_95, '95'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_85, '85'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_75, '75'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_65, '65'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_55, '55'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_45, '45'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_35, '35'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_25, '25'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_15, '15'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_5, '5'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '60',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'neo_lite_arg_duration',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_auto_driving_start',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                        DURATION: 1,\n                    },\n                    class: 'neo_lite_auto_driving',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const speed = script.getStringField('SPEED');\n                            const duration = script.getStringValue('DURATION', script);\n                            const blockId = this.generateBlockId();\n                            if (speed.indexOf('IN') >= 0) {\n                                this.requestExtCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [\n                                    speed,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [\n                                    speed,\n                                ]);\n                            }\n                            if (duration === 'c' || !Entry.parseNumber(duration)) {\n                                script.block_id = blockId;\n                                script.exec_phase = ExecPhase.PENDING_STOP;\n                            } else {\n                                script.exec_phase = ExecPhase.SET_TIMEOUT;\n                            }\n                        } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                            const duration = script.getStringValue('DURATION', script);\n                            const durationValue = Entry.parseNumber(duration);\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            setTimeout(() => {\n                                script.exec_phase = ExecPhase.STOP;\n                            }, durationValue * 1000);\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [0]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_auto_driving_sensor_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_input_1_2, 0x10],\n                                [Lang.Blocks.neo_lite_input_11_12, 0x11],\n                                [Lang.Blocks.neo_lite_input_13_14, 0x12],\n                                [Lang.Blocks.neo_lite_input_21_22, 0x13],\n                                [Lang.Blocks.neo_lite_input_23_24, 0x14],\n                                [Lang.Blocks.neo_lite_input_31_32, 0x15],\n                                [Lang.Blocks.neo_lite_input_33_34, 0x16],\n                            ],\n                            value: 0x10,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_95, '95'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_85, '85'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_75, '75'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_65, '65'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_55, '55'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_45, '45'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_35, '35'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_25, '25'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_15, '15'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_5, '5'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '60',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neo_lite_auto_driving_sensor_start',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        SPEED: 1,\n                    },\n                    class: 'neo_lite_auto_driving',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const sensor = script.getNumberField('SENSOR');\n                            const speed = script.getStringField('SPEED');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            if (speed.indexOf('IN') >= 0) {\n                                this.requestExtCommand(\n                                    blockId,\n                                    NeoBlockType.AUTO_DRIVING_SENSOR_START,\n                                    [sensor, speed]\n                                );\n                            } else {\n                                this.requestCommand(\n                                    blockId,\n                                    NeoBlockType.AUTO_DRIVING_SENSOR_START,\n                                    [sensor, speed]\n                                );\n                            }\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_auto_driving_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neo_lite_auto_driving_stop',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'neo_lite_auto_driving',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_STOP, []);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                /**\n                 * 자율주차\n                 */\n                neo_lite_auto_parking_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_auto_parking_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_auto_parking_title',\n                    },\n                    class: 'neo_lite_auto_parking',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_auto_parking_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_auto_parking_which_l, 1],\n                                [Lang.Blocks.neo_lite_auto_parking_which_r, 2],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_auto_parking_direction_b, 1],\n                                [Lang.Blocks.neo_lite_auto_parking_direction_s, 2],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neo_lite_auto_parking_start',\n                    },\n                    paramsKeyMap: {\n                        WHICH: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'neo_lite_auto_parking',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => this.runAutoParking(script),\n                },\n\n                /**\n                 * 라인트레이서\n                 */\n                neo_lite_line_tracer_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_line_tracer_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_line_tracer_title',\n                    },\n                    class: 'neo_lite_line_tracer',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_line_tracer_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_95, '95'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_85, '85'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_75, '75'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_65, '65'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_55, '55'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_45, '45'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_35, '35'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_25, '25'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_15, '15'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_5, '5'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '60',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'neo_lite_arg_duration',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_line_tracer_start',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                        DURATION: 1,\n                    },\n                    class: 'neo_lite_auto_driving',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const speed = script.getStringField('SPEED');\n                            const blockId = this.generateBlockId();\n                            const duration = script.getStringValue('DURATION', script);\n                            if (speed.indexOf('IN') >= 0) {\n                                this.requestExtCommand(blockId, NeoBlockType.LINE_TRACER_START, [\n                                    speed,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.LINE_TRACER_START, [\n                                    speed,\n                                ]);\n                            }\n                            if (duration === 'c' || !Entry.parseNumber(duration)) {\n                                script.block_id = blockId;\n                                script.exec_phase = ExecPhase.PENDING_STOP;\n                            } else {\n                                script.exec_phase = ExecPhase.SET_TIMEOUT;\n                            }\n                        } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                            const duration = script.getStringValue('DURATION', script);\n                            const durationValue = Entry.parseNumber(duration);\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            setTimeout(() => {\n                                script.exec_phase = ExecPhase.STOP;\n                            }, durationValue * 1000);\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.LINE_TRACER_START, [0]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_line_cross_move: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_line_cross_move_1, 1],\n                                [Lang.Blocks.neo_lite_line_cross_move_2, 2],\n                                [Lang.Blocks.neo_lite_line_cross_move_3, 3],\n                                [Lang.Blocks.neo_lite_line_cross_move_4, 4],\n                                [Lang.Blocks.neo_lite_line_cross_move_5, 5],\n                                [Lang.Blocks.neo_lite_line_cross_move_6, 6],\n                                [Lang.Blocks.neo_lite_line_cross_move_7, 7],\n                                [Lang.Blocks.neo_lite_line_cross_move_8, 8],\n                                [Lang.Blocks.neo_lite_line_cross_move_9, 9],\n                                [Lang.Blocks.neo_lite_line_cross_move_10, 10],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_line_cross_move',\n                    },\n                    paramsKeyMap: {\n                        COUNT: 0,\n                    },\n                    class: 'neo_lite_auto_driving',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const count = script.getStringField('COUNT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.LINE_CROSS_MOVE, [count]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_line_cross_turn: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_turn_direction_l, 30],\n                                [Lang.Blocks.neo_lite_turn_direction_r, 31],\n                            ],\n                            value: 30,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_line_cross_turn',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'neo_lite_auto_driving',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const direction = script.getStringField('DIRECTION');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.LINE_CROSS_TURN, [direction]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_line_cross_reached: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_boolean_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'neo_lite_line_cross_reached',\n                    },\n                    paramsKeyMap: {},\n                    class: 'neo_lite_auto_driving',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const sensorData = this.sensorValues;\n                        const leftValue = sensorData.in1Values[0];\n                        const rightValue = sensorData.in1Values[1];\n                        return (\n                            0 <= leftValue && leftValue <= 50 && 0 <= rightValue && rightValue <= 50\n                        );\n                    },\n                },\n\n                /**\n                 * 회전모터\n                 */\n                neo_lite_motor_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_motor_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_motor_title',\n                    },\n                    class: 'neo_lite_motor',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_motor_move: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_out_l, 1],\n                                [Lang.Blocks.neo_lite_motor_out_r, 2],\n                                [Lang.Blocks.neo_lite_motor_out_lr, 0],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_95, '95'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_85, '85'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_75, '75'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_65, '65'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_55, '55'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_45, '45'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_35, '35'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_25, '25'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_15, '15'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_5, '5'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_motor_speed_n5, '-5'],\n                                [Lang.Blocks.neo_lite_motor_speed_n10, '-10'],\n                                [Lang.Blocks.neo_lite_motor_speed_n15, '-15'],\n                                [Lang.Blocks.neo_lite_motor_speed_n20, '-20'],\n                                [Lang.Blocks.neo_lite_motor_speed_n25, '-25'],\n                                [Lang.Blocks.neo_lite_motor_speed_n30, '-30'],\n                                [Lang.Blocks.neo_lite_motor_speed_n35, '-35'],\n                                [Lang.Blocks.neo_lite_motor_speed_n40, '-40'],\n                                [Lang.Blocks.neo_lite_motor_speed_n45, '-45'],\n                                [Lang.Blocks.neo_lite_motor_speed_n50, '-50'],\n                                [Lang.Blocks.neo_lite_motor_speed_n55, '-55'],\n                                [Lang.Blocks.neo_lite_motor_speed_n60, '-60'],\n                                [Lang.Blocks.neo_lite_motor_speed_n65, '-65'],\n                                [Lang.Blocks.neo_lite_motor_speed_n70, '-70'],\n                                [Lang.Blocks.neo_lite_motor_speed_n75, '-75'],\n                                [Lang.Blocks.neo_lite_motor_speed_n80, '-80'],\n                                [Lang.Blocks.neo_lite_motor_speed_n85, '-85'],\n                                [Lang.Blocks.neo_lite_motor_speed_n90, '-90'],\n                                [Lang.Blocks.neo_lite_motor_speed_n95, '-95'],\n                                [Lang.Blocks.neo_lite_motor_speed_n100, '-100'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '100',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neo_lite_arg_duration',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_motor_move',\n                    },\n                    paramsKeyMap: {\n                        DC: 0,\n                        SPEED: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neo_lite_motor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const dc = script.getNumberField('DC');\n                            const speed = script.getStringField('SPEED');\n                            const duration = script.getStringValue('DURATION', script);\n                            const blockId = this.generateBlockId();\n                            if (speed.indexOf('IN') >= 0) {\n                                this.requestExtCommand(blockId, NeoBlockType.MOTOR_MOVE, [\n                                    dc,\n                                    speed,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, speed]);\n                            }\n                            if (duration === 'c' || !Entry.parseNumber(duration)) {\n                                script.block_id = blockId;\n                                script.exec_phase = ExecPhase.PENDING_STOP;\n                            } else {\n                                script.exec_phase = ExecPhase.SET_TIMEOUT;\n                            }\n                        } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            const duration = script.getStringValue('DURATION', script);\n                            const durationValue = Entry.parseNumber(duration);\n                            setTimeout(() => {\n                                script.exec_phase = ExecPhase.STOP;\n                            }, durationValue * 1000);\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const dc = script.getNumberField('DC', script);\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, 0]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_motor_move_both: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'neo_lite_arg_both_motor_speed',\n                            },\n                            {\n                                type: 'neo_lite_arg_both_motor_speed',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_motor_move_both',\n                    },\n                    paramsKeyMap: {\n                        SPEED_L: 0,\n                        SPEED_R: 1,\n                    },\n                    class: 'neo_lite_motor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const speedL = script.getNumberValue('SPEED_L', script);\n                            const speedR = script.getNumberValue('SPEED_R', script);\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE_BOTH, [\n                                speedL,\n                                speedR,\n                            ]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_motor_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_out_l, 1],\n                                [Lang.Blocks.neo_lite_motor_out_r, 2],\n                                [Lang.Blocks.neo_lite_motor_out_lr, 0],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_motor_stop',\n                    },\n                    paramsKeyMap: {\n                        DC: 0,\n                    },\n                    class: 'neo_lite_motor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const dc = script.getStringField('DC');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            this.requestCommand(blockId, NeoBlockType.MOTOR_STOP, [dc]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n\n                /**\n                 * 서보모터\n                 */\n                neo_lite_servo_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_servo_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_servo_title',\n                    },\n                    class: 'neo_lite_servo',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_servo_reset: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_servo_reset',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                    },\n                    class: 'neo_lite_servo',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.SERVO_RESET, [output]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_servo_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_servo_angle_360, '360'],\n                                [Lang.Blocks.neo_lite_servo_angle_350, '350'],\n                                [Lang.Blocks.neo_lite_servo_angle_340, '340'],\n                                [Lang.Blocks.neo_lite_servo_angle_330, '330'],\n                                [Lang.Blocks.neo_lite_servo_angle_320, '320'],\n                                [Lang.Blocks.neo_lite_servo_angle_310, '310'],\n                                [Lang.Blocks.neo_lite_servo_angle_300, '300'],\n                                [Lang.Blocks.neo_lite_servo_angle_290, '290'],\n                                [Lang.Blocks.neo_lite_servo_angle_280, '280'],\n                                [Lang.Blocks.neo_lite_servo_angle_270, '270'],\n                                [Lang.Blocks.neo_lite_servo_angle_260, '260'],\n                                [Lang.Blocks.neo_lite_servo_angle_250, '250'],\n                                [Lang.Blocks.neo_lite_servo_angle_240, '240'],\n                                [Lang.Blocks.neo_lite_servo_angle_230, '230'],\n                                [Lang.Blocks.neo_lite_servo_angle_220, '220'],\n                                [Lang.Blocks.neo_lite_servo_angle_210, '210'],\n                                [Lang.Blocks.neo_lite_servo_angle_200, '200'],\n                                [Lang.Blocks.neo_lite_servo_angle_190, '190'],\n                                [Lang.Blocks.neo_lite_servo_angle_180, '180'],\n                                [Lang.Blocks.neo_lite_servo_angle_170, '170'],\n                                [Lang.Blocks.neo_lite_servo_angle_160, '160'],\n                                [Lang.Blocks.neo_lite_servo_angle_150, '150'],\n                                [Lang.Blocks.neo_lite_servo_angle_140, '140'],\n                                [Lang.Blocks.neo_lite_servo_angle_130, '130'],\n                                [Lang.Blocks.neo_lite_servo_angle_120, '120'],\n                                [Lang.Blocks.neo_lite_servo_angle_110, '110'],\n                                [Lang.Blocks.neo_lite_servo_angle_100, '100'],\n                                [Lang.Blocks.neo_lite_servo_angle_90, '90'],\n                                [Lang.Blocks.neo_lite_servo_angle_80, '80'],\n                                [Lang.Blocks.neo_lite_servo_angle_70, '70'],\n                                [Lang.Blocks.neo_lite_servo_angle_60, '60'],\n                                [Lang.Blocks.neo_lite_servo_angle_50, '50'],\n                                [Lang.Blocks.neo_lite_servo_angle_40, '40'],\n                                [Lang.Blocks.neo_lite_servo_angle_30, '30'],\n                                [Lang.Blocks.neo_lite_servo_angle_20, '20'],\n                                [Lang.Blocks.neo_lite_servo_angle_10, '10'],\n                                [Lang.Blocks.neo_lite_servo_angle_0, '0'],\n                                [Lang.Blocks.neo_lite_servo_angle_n10, '-10'],\n                                [Lang.Blocks.neo_lite_servo_angle_n20, '-20'],\n                                [Lang.Blocks.neo_lite_servo_angle_n30, '-30'],\n                                [Lang.Blocks.neo_lite_servo_angle_n40, '-40'],\n                                [Lang.Blocks.neo_lite_servo_angle_n50, '-50'],\n                                [Lang.Blocks.neo_lite_servo_angle_n60, '-60'],\n                                [Lang.Blocks.neo_lite_servo_angle_n70, '-70'],\n                                [Lang.Blocks.neo_lite_servo_angle_n80, '-80'],\n                                [Lang.Blocks.neo_lite_servo_angle_n90, '-90'],\n                                [Lang.Blocks.neo_lite_servo_angle_n100, '-100'],\n                                [Lang.Blocks.neo_lite_servo_angle_n110, '-110'],\n                                [Lang.Blocks.neo_lite_servo_angle_n120, '-120'],\n                                [Lang.Blocks.neo_lite_servo_angle_n130, '-130'],\n                                [Lang.Blocks.neo_lite_servo_angle_n140, '-140'],\n                                [Lang.Blocks.neo_lite_servo_angle_n150, '-150'],\n                                [Lang.Blocks.neo_lite_servo_angle_n160, '-160'],\n                                [Lang.Blocks.neo_lite_servo_angle_n170, '-170'],\n                                [Lang.Blocks.neo_lite_servo_angle_n180, '-180'],\n                                [Lang.Blocks.neo_lite_servo_angle_n190, '-190'],\n                                [Lang.Blocks.neo_lite_servo_angle_n200, '-200'],\n                                [Lang.Blocks.neo_lite_servo_angle_n210, '-210'],\n                                [Lang.Blocks.neo_lite_servo_angle_n220, '-220'],\n                                [Lang.Blocks.neo_lite_servo_angle_n230, '-230'],\n                                [Lang.Blocks.neo_lite_servo_angle_n240, '-240'],\n                                [Lang.Blocks.neo_lite_servo_angle_n250, '-250'],\n                                [Lang.Blocks.neo_lite_servo_angle_n260, '-260'],\n                                [Lang.Blocks.neo_lite_servo_angle_n270, '-270'],\n                                [Lang.Blocks.neo_lite_servo_angle_n280, '-280'],\n                                [Lang.Blocks.neo_lite_servo_angle_n290, '-290'],\n                                [Lang.Blocks.neo_lite_servo_angle_n300, '-300'],\n                                [Lang.Blocks.neo_lite_servo_angle_n310, '-310'],\n                                [Lang.Blocks.neo_lite_servo_angle_n320, '-320'],\n                                [Lang.Blocks.neo_lite_servo_angle_n330, '-330'],\n                                [Lang.Blocks.neo_lite_servo_angle_n340, '-340'],\n                                [Lang.Blocks.neo_lite_servo_angle_n350, '-350'],\n                                [Lang.Blocks.neo_lite_servo_angle_n360, '-360'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '50',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'neo_lite_servo_angle',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        ANGLE: 1,\n                        SPEED: 2,\n                    },\n                    class: 'neo_lite_servo',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const angle = script.getStringField('ANGLE');\n                            const speed = script.getStringField('SPEED');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            const isExt2 = angle.indexOf('IN') >= 0 && speed.indexOf('IN') >= 0;\n                            if (isExt2) {\n                                this.requestExt2Command(blockId, NeoBlockType.SERVO_ANGLE, [\n                                    output,\n                                    angle,\n                                    speed,\n                                ]);\n                            } else {\n                                const isExt1 = angle.indexOf('IN') >= 0 || speed.indexOf('IN') >= 0;\n                                if (isExt1) {\n                                    this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE, [\n                                        output,\n                                        angle,\n                                        speed,\n                                    ]);\n                                } else {\n                                    this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [\n                                        output,\n                                        angle,\n                                        speed,\n                                    ]);\n                                }\n                            }\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_servo_angle_var: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '50',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'neo_lite_arg_servo_angle',\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'neo_lite_servo_angle_var',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        ANGLE: 1,\n                        SPEED: 2,\n                    },\n                    class: 'neo_lite_servo',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const angle = script.getNumberValue('ANGLE', script);\n                            const speed = script.getStringField('SPEED');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [\n                                output,\n                                angle,\n                                speed,\n                            ]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_servo_angle_wait: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_servo_angle_360, '360'],\n                                [Lang.Blocks.neo_lite_servo_angle_350, '350'],\n                                [Lang.Blocks.neo_lite_servo_angle_340, '340'],\n                                [Lang.Blocks.neo_lite_servo_angle_330, '330'],\n                                [Lang.Blocks.neo_lite_servo_angle_320, '320'],\n                                [Lang.Blocks.neo_lite_servo_angle_310, '310'],\n                                [Lang.Blocks.neo_lite_servo_angle_300, '300'],\n                                [Lang.Blocks.neo_lite_servo_angle_290, '290'],\n                                [Lang.Blocks.neo_lite_servo_angle_280, '280'],\n                                [Lang.Blocks.neo_lite_servo_angle_270, '270'],\n                                [Lang.Blocks.neo_lite_servo_angle_260, '260'],\n                                [Lang.Blocks.neo_lite_servo_angle_250, '250'],\n                                [Lang.Blocks.neo_lite_servo_angle_240, '240'],\n                                [Lang.Blocks.neo_lite_servo_angle_230, '230'],\n                                [Lang.Blocks.neo_lite_servo_angle_220, '220'],\n                                [Lang.Blocks.neo_lite_servo_angle_210, '210'],\n                                [Lang.Blocks.neo_lite_servo_angle_200, '200'],\n                                [Lang.Blocks.neo_lite_servo_angle_190, '190'],\n                                [Lang.Blocks.neo_lite_servo_angle_180, '180'],\n                                [Lang.Blocks.neo_lite_servo_angle_170, '170'],\n                                [Lang.Blocks.neo_lite_servo_angle_160, '160'],\n                                [Lang.Blocks.neo_lite_servo_angle_150, '150'],\n                                [Lang.Blocks.neo_lite_servo_angle_140, '140'],\n                                [Lang.Blocks.neo_lite_servo_angle_130, '130'],\n                                [Lang.Blocks.neo_lite_servo_angle_120, '120'],\n                                [Lang.Blocks.neo_lite_servo_angle_110, '110'],\n                                [Lang.Blocks.neo_lite_servo_angle_100, '100'],\n                                [Lang.Blocks.neo_lite_servo_angle_90, '90'],\n                                [Lang.Blocks.neo_lite_servo_angle_80, '80'],\n                                [Lang.Blocks.neo_lite_servo_angle_70, '70'],\n                                [Lang.Blocks.neo_lite_servo_angle_60, '60'],\n                                [Lang.Blocks.neo_lite_servo_angle_50, '50'],\n                                [Lang.Blocks.neo_lite_servo_angle_40, '40'],\n                                [Lang.Blocks.neo_lite_servo_angle_30, '30'],\n                                [Lang.Blocks.neo_lite_servo_angle_20, '20'],\n                                [Lang.Blocks.neo_lite_servo_angle_10, '10'],\n                                [Lang.Blocks.neo_lite_servo_angle_0, '0'],\n                                [Lang.Blocks.neo_lite_servo_angle_n10, '-10'],\n                                [Lang.Blocks.neo_lite_servo_angle_n20, '-20'],\n                                [Lang.Blocks.neo_lite_servo_angle_n30, '-30'],\n                                [Lang.Blocks.neo_lite_servo_angle_n40, '-40'],\n                                [Lang.Blocks.neo_lite_servo_angle_n50, '-50'],\n                                [Lang.Blocks.neo_lite_servo_angle_n60, '-60'],\n                                [Lang.Blocks.neo_lite_servo_angle_n70, '-70'],\n                                [Lang.Blocks.neo_lite_servo_angle_n80, '-80'],\n                                [Lang.Blocks.neo_lite_servo_angle_n90, '-90'],\n                                [Lang.Blocks.neo_lite_servo_angle_n100, '-100'],\n                                [Lang.Blocks.neo_lite_servo_angle_n110, '-110'],\n                                [Lang.Blocks.neo_lite_servo_angle_n120, '-120'],\n                                [Lang.Blocks.neo_lite_servo_angle_n130, '-130'],\n                                [Lang.Blocks.neo_lite_servo_angle_n140, '-140'],\n                                [Lang.Blocks.neo_lite_servo_angle_n150, '-150'],\n                                [Lang.Blocks.neo_lite_servo_angle_n160, '-160'],\n                                [Lang.Blocks.neo_lite_servo_angle_n170, '-170'],\n                                [Lang.Blocks.neo_lite_servo_angle_n180, '-180'],\n                                [Lang.Blocks.neo_lite_servo_angle_n190, '-190'],\n                                [Lang.Blocks.neo_lite_servo_angle_n200, '-200'],\n                                [Lang.Blocks.neo_lite_servo_angle_n210, '-210'],\n                                [Lang.Blocks.neo_lite_servo_angle_n220, '-220'],\n                                [Lang.Blocks.neo_lite_servo_angle_n230, '-230'],\n                                [Lang.Blocks.neo_lite_servo_angle_n240, '-240'],\n                                [Lang.Blocks.neo_lite_servo_angle_n250, '-250'],\n                                [Lang.Blocks.neo_lite_servo_angle_n260, '-260'],\n                                [Lang.Blocks.neo_lite_servo_angle_n270, '-270'],\n                                [Lang.Blocks.neo_lite_servo_angle_n280, '-280'],\n                                [Lang.Blocks.neo_lite_servo_angle_n290, '-290'],\n                                [Lang.Blocks.neo_lite_servo_angle_n300, '-300'],\n                                [Lang.Blocks.neo_lite_servo_angle_n310, '-310'],\n                                [Lang.Blocks.neo_lite_servo_angle_n320, '-320'],\n                                [Lang.Blocks.neo_lite_servo_angle_n330, '-330'],\n                                [Lang.Blocks.neo_lite_servo_angle_n340, '-340'],\n                                [Lang.Blocks.neo_lite_servo_angle_n350, '-350'],\n                                [Lang.Blocks.neo_lite_servo_angle_n360, '-360'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                            ],\n                            value: '50',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'neo_lite_servo_angle_wait',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        ANGLE: 1,\n                        SPEED: 2,\n                    },\n                    class: 'neo_lite_servo',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const angle = script.getStringField('ANGLE');\n                            const speed = script.getStringField('SPEED');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            const isExt2 = angle.indexOf('IN') >= 0 && speed.indexOf('IN') >= 0;\n                            if (isExt2) {\n                                this.requestExt2Command(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [\n                                    output,\n                                    angle,\n                                    speed,\n                                ]);\n                            } else {\n                                const isExt1 = angle.indexOf('IN') >= 0 || speed.indexOf('IN') >= 0;\n                                if (isExt1) {\n                                    this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [\n                                        output,\n                                        angle,\n                                        speed,\n                                    ]);\n                                } else {\n                                    this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [\n                                        output,\n                                        angle,\n                                        speed,\n                                    ]);\n                                }\n                            }\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_servo_rotate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_servo_direction_f, 1],\n                                [Lang.Blocks.neo_lite_servo_direction_b, 2],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '50',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'neo_lite_servo_rotate',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        DIRECTION: 1,\n                        SPEED: 2,\n                    },\n                    class: 'neo_lite_servo',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const direction = script.getStringField('DIRECTION');\n                            const speed = script.getStringField('SPEED');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            if (speed.indexOf('IN') >= 0) {\n                                this.requestExtCommand(blockId, NeoBlockType.SERVO_ROTATE, [\n                                    output,\n                                    direction,\n                                    speed,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.SERVO_ROTATE, [\n                                    output,\n                                    direction,\n                                    speed,\n                                ]);\n                            }\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_servo_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_servo_stop',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                    },\n                    class: 'neo_lite_servo',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.SERVO_STOP, [output]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n\n                /**\n                 * LED\n                 */\n                neo_lite_led_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_led_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_led_title',\n                    },\n                    class: 'neo_lite_led',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_led_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_led_brightness_100, '100'],\n                                [Lang.Blocks.neo_lite_led_brightness_90, '90'],\n                                [Lang.Blocks.neo_lite_led_brightness_80, '80'],\n                                [Lang.Blocks.neo_lite_led_brightness_70, '70'],\n                                [Lang.Blocks.neo_lite_led_brightness_60, '60'],\n                                [Lang.Blocks.neo_lite_led_brightness_50, '50'],\n                                [Lang.Blocks.neo_lite_led_brightness_40, '40'],\n                                [Lang.Blocks.neo_lite_led_brightness_30, '30'],\n                                [Lang.Blocks.neo_lite_led_brightness_20, '20'],\n                                [Lang.Blocks.neo_lite_led_brightness_10, '10'],\n                                [Lang.Blocks.neo_lite_led_brightness_0, '0'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '100',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neo_lite_arg_duration',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_led_on',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        BRIGHTNESS: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neo_lite_led',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const output = script.getStringField('OUTPUT');\n                            const brightness = script.getStringField('BRIGHTNESS');\n                            const duration = script.getStringValue('DURATION', script);\n                            const blockId = this.generateBlockId();\n                            if (brightness.indexOf('IN') >= 0) {\n                                this.requestExtCommand(blockId, NeoBlockType.LED_ON, [\n                                    output,\n                                    brightness,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.LED_ON, [\n                                    output,\n                                    brightness,\n                                ]);\n                            }\n                            if (duration === 'c' || !Entry.parseNumber(duration)) {\n                                script.block_id = blockId;\n                                script.exec_phase = ExecPhase.PENDING_STOP;\n                            } else {\n                                script.exec_phase = ExecPhase.SET_TIMEOUT;\n                            }\n                        } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                            const duration = script.getStringValue('DURATION', script);\n                            const durationValue = Entry.parseNumber(duration);\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            setTimeout(() => {\n                                script.exec_phase = ExecPhase.STOP;\n                            }, durationValue * 1000);\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const output = script.getStringField('OUTPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.LED_ON, [output, 0]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_led_blink: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_led_blink_speed_1, 500],\n                                [Lang.Blocks.neo_lite_led_blink_speed_2, 400],\n                                [Lang.Blocks.neo_lite_led_blink_speed_3, 300],\n                                [Lang.Blocks.neo_lite_led_blink_speed_4, 200],\n                                [Lang.Blocks.neo_lite_led_blink_speed_5, 100],\n                            ],\n                            value: 100,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neo_lite_arg_duration',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_led_blink',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        SPEED: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neo_lite_led',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const output = script.getStringField('OUTPUT');\n                            const speed = script.getStringField('SPEED');\n                            const duration = script.getStringValue('DURATION', script);\n                            const blockId = this.generateBlockId();\n                            this.requestCommand(blockId, NeoBlockType.LED_BLINK, [\n                                output,\n                                speed,\n                                100,\n                            ]);\n                            if (duration === 'c' || !Entry.parseNumber(duration)) {\n                                script.exec_phase = ExecPhase.PENDING_STOP;\n                                script.block_id = blockId;\n                            } else {\n                                script.exec_phase = ExecPhase.SET_TIMEOUT;\n                            }\n                        } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                            const duration = script.getStringValue('DURATION', script);\n                            const durationValue = Entry.parseNumber(duration);\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            setTimeout(() => {\n                                script.exec_phase = ExecPhase.STOP;\n                            }, durationValue * 1000);\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const output = script.getStringField('OUTPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.LED_BLINK, [output, 0, 0]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_led_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_led_off',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                    },\n                    class: 'neo_lite_led',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.LED_OFF, [output]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                /**\n                 * 컬러 LED\n                 */\n                neo_lite_color_led_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_color_led_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_color_led_title',\n                    },\n                    class: 'neo_lite_color_led',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_color_led_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            '#0000FF',\n                            {\n                                type: 'neo_lite_arg_duration',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_color_led_on',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        COLOR: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neo_lite_color_led',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const output = script.getStringField('OUTPUT');\n                            const color = script.getStringValue('COLOR', script);\n                            const duration = script.getStringValue('DURATION', script);\n                            const blockId = this.generateBlockId();\n                            this.requestCommand(blockId, NeoBlockType.COLOR_LED_ON, [\n                                output,\n                                color,\n                            ]);\n                            if (duration === 'c' || !Entry.parseNumber(duration)) {\n                                script.exec_phase = ExecPhase.PENDING_STOP;\n                                script.block_id = blockId;\n                            } else {\n                                script.exec_phase = ExecPhase.SET_TIMEOUT;\n                            }\n                        } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                            const duration = script.getStringValue('DURATION', script);\n                            const durationValue = Entry.parseNumber(duration);\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            setTimeout(() => {\n                                script.exec_phase = ExecPhase.STOP;\n                            }, durationValue * 1000);\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const output = script.getStringField('OUTPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.COLOR_LED_ON, [output, 0]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_color_led_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_color_led_off',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                    },\n                    class: 'neo_lite_color_led',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.COLOR_LED_OFF, [output]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_color_led_on_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neo_lite_color_led_on_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                        OUTPUT: 1,\n                    },\n                    class: 'neo_lite_color_led',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const input = script.getStringField('INPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestExtCommand(blockId, NeoBlockType.COLOR_LED_ON_SENSOR, [\n                                output,\n                                input,\n                            ]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                /**\n                 * 출력\n                 */\n                neo_lite_set_output_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_set_output_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_set_output_title',\n                    },\n                    class: 'neo_lite_set_output',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_set_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                                [Lang.Blocks.neo_lite_output_12, 'OUT12'],\n                                [Lang.Blocks.neo_lite_output_123, 'OUT123'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_set_output_value_255, '255'],\n                                [Lang.Blocks.neo_lite_set_output_value_250, '250'],\n                                [Lang.Blocks.neo_lite_set_output_value_245, '245'],\n                                [Lang.Blocks.neo_lite_set_output_value_240, '240'],\n                                [Lang.Blocks.neo_lite_set_output_value_235, '235'],\n                                [Lang.Blocks.neo_lite_set_output_value_230, '230'],\n                                [Lang.Blocks.neo_lite_set_output_value_225, '225'],\n                                [Lang.Blocks.neo_lite_set_output_value_220, '220'],\n                                [Lang.Blocks.neo_lite_set_output_value_215, '215'],\n                                [Lang.Blocks.neo_lite_set_output_value_210, '210'],\n                                [Lang.Blocks.neo_lite_set_output_value_205, '205'],\n                                [Lang.Blocks.neo_lite_set_output_value_200, '200'],\n                                [Lang.Blocks.neo_lite_set_output_value_195, '195'],\n                                [Lang.Blocks.neo_lite_set_output_value_190, '190'],\n                                [Lang.Blocks.neo_lite_set_output_value_185, '185'],\n                                [Lang.Blocks.neo_lite_set_output_value_180, '180'],\n                                [Lang.Blocks.neo_lite_set_output_value_175, '175'],\n                                [Lang.Blocks.neo_lite_set_output_value_170, '170'],\n                                [Lang.Blocks.neo_lite_set_output_value_165, '165'],\n                                [Lang.Blocks.neo_lite_set_output_value_160, '160'],\n                                [Lang.Blocks.neo_lite_set_output_value_155, '155'],\n                                [Lang.Blocks.neo_lite_set_output_value_150, '150'],\n                                [Lang.Blocks.neo_lite_set_output_value_145, '145'],\n                                [Lang.Blocks.neo_lite_set_output_value_140, '140'],\n                                [Lang.Blocks.neo_lite_set_output_value_135, '135'],\n                                [Lang.Blocks.neo_lite_set_output_value_130, '130'],\n                                [Lang.Blocks.neo_lite_set_output_value_125, '125'],\n                                [Lang.Blocks.neo_lite_set_output_value_120, '120'],\n                                [Lang.Blocks.neo_lite_set_output_value_115, '115'],\n                                [Lang.Blocks.neo_lite_set_output_value_110, '110'],\n                                [Lang.Blocks.neo_lite_set_output_value_105, '105'],\n                                [Lang.Blocks.neo_lite_set_output_value_100, '100'],\n                                [Lang.Blocks.neo_lite_set_output_value_95, '95'],\n                                [Lang.Blocks.neo_lite_set_output_value_90, '90'],\n                                [Lang.Blocks.neo_lite_set_output_value_85, '85'],\n                                [Lang.Blocks.neo_lite_set_output_value_80, '80'],\n                                [Lang.Blocks.neo_lite_set_output_value_75, '75'],\n                                [Lang.Blocks.neo_lite_set_output_value_70, '70'],\n                                [Lang.Blocks.neo_lite_set_output_value_65, '65'],\n                                [Lang.Blocks.neo_lite_set_output_value_60, '60'],\n                                [Lang.Blocks.neo_lite_set_output_value_55, '55'],\n                                [Lang.Blocks.neo_lite_set_output_value_50, '50'],\n                                [Lang.Blocks.neo_lite_set_output_value_45, '45'],\n                                [Lang.Blocks.neo_lite_set_output_value_40, '40'],\n                                [Lang.Blocks.neo_lite_set_output_value_35, '35'],\n                                [Lang.Blocks.neo_lite_set_output_value_30, '30'],\n                                [Lang.Blocks.neo_lite_set_output_value_25, '25'],\n                                [Lang.Blocks.neo_lite_set_output_value_20, '20'],\n                                [Lang.Blocks.neo_lite_set_output_value_15, '15'],\n                                [Lang.Blocks.neo_lite_set_output_value_10, '10'],\n                                [Lang.Blocks.neo_lite_set_output_value_5, '5'],\n                                [Lang.Blocks.neo_lite_set_output_value_0, '0'],\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: '100',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neo_lite_arg_duration',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_set_output',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        VALUE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neo_lite_set_output',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const output = script.getStringField('OUTPUT');\n                            const value = script.getStringField('VALUE');\n                            const duration = script.getStringValue('DURATION', script);\n                            const blockId = this.generateBlockId();\n                            if (value.indexOf('IN') >= 0) {\n                                this.requestExtCommand(blockId, NeoBlockType.SET_OUTPUT, [\n                                    output,\n                                    value,\n                                ]);\n                            } else {\n                                this.requestCommand(blockId, NeoBlockType.SET_OUTPUT, [\n                                    output,\n                                    value,\n                                ]);\n                            }\n                            if (duration === 'c' || !Entry.parseNumber(duration)) {\n                                script.exec_phase = ExecPhase.PENDING_STOP;\n                                script.block_id = blockId;\n                            } else {\n                                script.exec_phase = ExecPhase.SET_TIMEOUT;\n                            }\n                        } else if (script.exec_phase === ExecPhase.SET_TIMEOUT) {\n                            const duration = script.getStringValue('DURATION', script);\n                            const durationValue = Entry.parseNumber(duration);\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            setTimeout(() => {\n                                script.exec_phase = ExecPhase.STOP;\n                            }, durationValue * 1000);\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const output = script.getStringField('OUTPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.SET_OUTPUT, [output, 0]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                /**\n                 * 센서\n                 */\n                neo_lite_sensor_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_sensor_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_sensor_title',\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_sensor_in: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neo_lite_sensor_in',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const input = script.getStringField('INPUT');\n                        const sensorData = this.sensorValues;\n                        switch (input) {\n                            case 'IN1':\n                                return sensorData.in1Values[0];\n                            case 'IN2':\n                                return sensorData.in2Values[0];\n                            case 'IN3':\n                                return sensorData.in3Values[0];\n                        }\n                        return 0;\n                    },\n                },\n                neo_lite_sensor_in_2: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                            ],\n                            value: 'IN2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neo_lite_sensor_in_2',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const input = script.getStringField('INPUT');\n                        const sensorData = this.sensorValues;\n                        switch (input) {\n                            case 'IN1':\n                                return sensorData.in1Values[0];\n                            case 'IN2':\n                                return sensorData.in2Values[0];\n                            case 'IN3':\n                                return sensorData.in3Values[0];\n                        }\n                        return 0;\n                    },\n                },\n                neo_lite_sensor_digital_in: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_sensor_in_digital_1, 0],\n                                [Lang.Blocks.neo_lite_sensor_in_digital_2, 1],\n                                [Lang.Blocks.neo_lite_sensor_in_digital_3, 2],\n                                [Lang.Blocks.neo_lite_sensor_in_digital_4, 3],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neo_lite_sensor_digital_in',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                        INDEX: 1,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const input = script.getStringField('INPUT');\n                        const index = script.getNumberField('INDEX');\n                        const sensorData = this.sensorValues;\n                        switch (input) {\n                            case 'IN1':\n                                return sensorData.in1Values[index];\n                            case 'IN2':\n                                return sensorData.in2Values[index];\n                            case 'IN3':\n                                return sensorData.in3Values[index];\n                        }\n                        return 0;\n                    },\n                },\n                neo_lite_sensor_convert: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'neo_lite_sensor_in',\n                            },\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                        ],\n                        type: 'neo_lite_sensor_convert',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                        FROM_MIN: 1,\n                        FROM_MAX: 2,\n                        TO_MIN: 3,\n                        TO_MAX: 4,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        let value = script.getNumberValue('INPUT', script);\n                        let fromMin = script.getNumberValue('FROM_MIN', script);\n                        let fromMax = script.getNumberValue('FROM_MAX', script);\n                        let toMin = script.getNumberValue('TO_MIN', script);\n                        let toMax = script.getNumberValue('TO_MAX', script);\n\n                        if (fromMin > fromMax) {\n                            const temp = fromMin;\n                            fromMin = fromMax;\n                            fromMax = temp;\n                        }\n\n                        if (toMin > toMax) {\n                            const temp = toMin;\n                            toMin = toMax;\n                            toMax = temp;\n                        }\n\n                        value -= fromMin;\n                        value = value * ((toMax - toMin) / (fromMax - fromMin));\n                        value += toMin;\n                        value = Math.min(toMax, value);\n                        value = Math.max(toMin, value);\n\n                        return Math.round(value);\n                    },\n                },\n                neo_lite_sensor_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_compare_gt, '>='],\n                                [Lang.Blocks.neo_lite_compare_g, '>'],\n                                [Lang.Blocks.neo_lite_compare_e, '='],\n                                [Lang.Blocks.neo_lite_compare_l, '<'],\n                                [Lang.Blocks.neo_lite_compare_lt, '<='],\n                            ],\n                            value: '>',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'neo_lite_sensor_in',\n                            },\n                            null,\n                            10,\n                        ],\n                        type: 'neo_lite_sensor_compare',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                        SYMBOL: 1,\n                        VALUE: 2,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const input = script.getNumberValue('INPUT', script);\n                        const symbol = script.getStringField('SYMBOL');\n                        const value = script.getNumberValue('VALUE');\n\n                        const sensorValue = input;\n                        if (symbol === '=') {\n                            return sensorValue === value;\n                        } else if (symbol === '>') {\n                            return sensorValue > value;\n                        } else if (symbol === '<') {\n                            return sensorValue < value;\n                        } else if (symbol === '>=') {\n                            return sensorValue >= value;\n                        } else if (symbol === '<=') {\n                            return sensorValue <= value;\n                        }\n\n                        return false;\n                    },\n                },\n                neo_lite_sensor_between: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_compare_gt, '>='],\n                                [Lang.Blocks.neo_lite_compare_g, '>'],\n                                [Lang.Blocks.neo_lite_compare_e, '='],\n                                [Lang.Blocks.neo_lite_compare_l, '<'],\n                                [Lang.Blocks.neo_lite_compare_lt, '<='],\n                            ],\n                            value: '<',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_compare_gt, '>='],\n                                [Lang.Blocks.neo_lite_compare_g, '>'],\n                                [Lang.Blocks.neo_lite_compare_e, '='],\n                                [Lang.Blocks.neo_lite_compare_l, '<'],\n                                [Lang.Blocks.neo_lite_compare_lt, '<='],\n                            ],\n                            value: '<',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            10,\n                            null,\n                            {\n                                type: 'neo_lite_sensor_in',\n                            },\n                            null,\n                            30,\n                        ],\n                        type: 'neo_lite_sensor_between',\n                    },\n                    paramsKeyMap: {\n                        L_VALUE: 0,\n                        L_SYMBOL: 1,\n                        INPUT: 2,\n                        R_SYMBOL: 3,\n                        R_VALUE: 4,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const input = script.getNumberValue('INPUT', script);\n                        const lSymbol = script.getStringField('L_SYMBOL');\n                        const lValue = script.getNumberValue('L_VALUE', script);\n                        const rSymbol = script.getStringField('R_SYMBOL');\n                        const rValue = script.getNumberValue('R_VALUE', script);\n\n                        const sensorValue = input;\n                        let lResult = false;\n                        if (lSymbol === '=') {\n                            lResult = lValue === sensorValue;\n                        } else if (lSymbol === '>') {\n                            lResult = lValue > sensorValue;\n                        } else if (lSymbol === '<') {\n                            lResult = lValue < sensorValue;\n                        } else if (lSymbol === '>=') {\n                            lResult = lValue >= sensorValue;\n                        } else if (lSymbol === '<=') {\n                            lResult = lValue <= sensorValue;\n                        }\n                        let rResult = false;\n                        if (rSymbol === '=') {\n                            rResult = sensorValue === rValue;\n                        } else if (rSymbol === '>') {\n                            rResult = sensorValue > rValue;\n                        } else if (rSymbol === '<') {\n                            rResult = sensorValue < rValue;\n                        } else if (rSymbol === '>=') {\n                            rResult = sensorValue >= rValue;\n                        } else if (rSymbol === '<=') {\n                            rResult = sensorValue <= rValue;\n                        }\n                        return lResult && rResult;\n                    },\n                },\n                neo_lite_sensor_digital_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_sensor_in_digital_1, 0],\n                                [Lang.Blocks.neo_lite_sensor_in_digital_2, 1],\n                                [Lang.Blocks.neo_lite_sensor_in_digital_3, 2],\n                                [Lang.Blocks.neo_lite_sensor_in_digital_4, 3],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_compare_gt, '>='],\n                                [Lang.Blocks.neo_lite_compare_g, '>'],\n                                [Lang.Blocks.neo_lite_compare_e, '='],\n                                [Lang.Blocks.neo_lite_compare_l, '<'],\n                                [Lang.Blocks.neo_lite_compare_lt, '<='],\n                            ],\n                            value: '>',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, 10],\n                        type: 'neo_lite_sensor_digital_compare',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                        INDEX: 1,\n                        SYMBOL: 2,\n                        VALUE: 3,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const input = script.getStringField('INPUT');\n                        const index = script.getNumberField('INDEX');\n                        const sensorData = this.sensorValues;\n                        const symbol = script.getStringField('SYMBOL');\n                        const value = script.getNumberValue('VALUE', script);\n\n                        let sensorValue = 0;\n                        switch (input) {\n                            case 'IN1':\n                                sensorValue = sensorData.in1Values[index];\n                                break;\n                            case 'IN2':\n                                sensorValue = sensorData.in2Values[index];\n                                break;\n                            case 'IN3':\n                                sensorValue = sensorData.in3Values[index];\n                                break;\n                        }\n\n                        if (symbol === '=') {\n                            return sensorValue === value;\n                        } else if (symbol === '>') {\n                            return sensorValue > value;\n                        } else if (symbol === '<') {\n                            return sensorValue < value;\n                        } else if (symbol === '>=') {\n                            return sensorValue >= value;\n                        } else if (symbol === '<=') {\n                            return sensorValue <= value;\n                        }\n\n                        return false;\n                    },\n                },\n                neo_lite_sensor_color_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_color_black, 1],\n                                [Lang.Blocks.neo_lite_color_white, 2],\n                                [Lang.Blocks.neo_lite_color_red, 3],\n                                [Lang.Blocks.neo_lite_color_yellow, 4],\n                                [Lang.Blocks.neo_lite_color_green, 5],\n                                [Lang.Blocks.neo_lite_color_blue, 6],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'neo_lite_sensor_in_2',\n                            },\n                            null,\n                        ],\n                        type: 'neo_lite_sensor_color_compare',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                        COLOR: 1,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const input = script.getNumberValue('INPUT', script);\n                        const color = script.getNumberField('COLOR');\n                        const sensorValue = input;\n                        if (color === 1) {\n                            return 0 <= sensorValue && sensorValue <= 10;\n                        } else if (color === 2) {\n                            return 11 <= sensorValue && sensorValue <= 59;\n                        } else if (color === 3) {\n                            return 61 <= sensorValue && sensorValue <= 99;\n                        } else if (color === 4) {\n                            return 101 <= sensorValue && sensorValue <= 139;\n                        } else if (color === 5) {\n                            return 141 <= sensorValue && sensorValue <= 179;\n                        } else if (color === 6) {\n                            return 181 <= sensorValue && sensorValue <= 219;\n                        }\n\n                        return false;\n                    },\n                },\n                neo_lite_sensor_color_sequence_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                            ],\n                            value: 'IN2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_color_red, 3],\n                                [Lang.Blocks.neo_lite_color_yellow, 4],\n                                [Lang.Blocks.neo_lite_color_green, 5],\n                                [Lang.Blocks.neo_lite_color_blue, 6],\n                            ],\n                            value: '3',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_color_red, 3],\n                                [Lang.Blocks.neo_lite_color_yellow, 4],\n                                [Lang.Blocks.neo_lite_color_green, 5],\n                                [Lang.Blocks.neo_lite_color_blue, 6],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_color_black, 1],\n                                [Lang.Blocks.neo_lite_color_red, 3],\n                                [Lang.Blocks.neo_lite_color_yellow, 4],\n                                [Lang.Blocks.neo_lite_color_green, 5],\n                                [Lang.Blocks.neo_lite_color_blue, 6],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'neo_lite_sensor_color_sequence_compare',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                        COLOR1: 1,\n                        COLOR2: 2,\n                        COLOR3: 3,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const input = script.getStringField('INPUT');\n                        const color1 = script.getNumberField('COLOR1');\n                        const color2 = script.getNumberField('COLOR2');\n                        const color3 = script.getNumberField('COLOR3');\n                        const sensorData = this.sensorValues;\n                        let seq1 = 0;\n                        let seq2 = 0;\n                        let seq3 = 0;\n                        switch (input) {\n                            case 'IN1':\n                                seq1 = sensorData.in1Values[1];\n                                seq2 = sensorData.in1Values[2];\n                                seq3 = sensorData.in1Values[3];\n                                break;\n                            case 'IN2':\n                                seq1 = sensorData.in2Values[1];\n                                seq2 = sensorData.in2Values[2];\n                                seq3 = sensorData.in2Values[3];\n                                break;\n                            case 'IN3':\n                                seq1 = sensorData.in3Values[1];\n                                seq2 = sensorData.in3Values[2];\n                                seq3 = sensorData.in3Values[3];\n                                break;\n                        }\n                        let compare1 = false;\n                        let compare2 = false;\n                        let compare3 = false;\n\n                        if (color1 === 3) compare1 = 61 <= seq1 && seq1 <= 99;\n                        else if (color1 === 4) compare1 = 101 <= seq1 && seq1 <= 139;\n                        else if (color1 === 5) compare1 = 141 <= seq1 && seq1 <= 179;\n                        else if (color1 === 6) compare1 = 181 <= seq1 && seq1 <= 219;\n\n                        if (color2 === 3) compare2 = 61 <= seq2 && seq2 <= 99;\n                        else if (color2 === 4) compare2 = 101 <= seq2 && seq2 <= 139;\n                        else if (color2 === 5) compare2 = 141 <= seq2 && seq2 <= 179;\n                        else if (color2 === 6) compare2 = 181 <= seq2 && seq2 <= 219;\n\n                        if (color3 === 1) compare3 = 0 <= seq3 && seq3 <= 10;\n                        else if (color3 === 3) compare3 = 61 <= seq3 && seq3 <= 99;\n                        else if (color3 === 4) compare3 = 101 <= seq3 && seq3 <= 139;\n                        else if (color3 === 5) compare3 = 141 <= seq3 && seq3 <= 179;\n                        else if (color3 === 6) compare3 = 181 <= seq3 && seq3 <= 219;\n\n                        return compare1 && compare2 && compare3;\n                    },\n                },\n                neo_lite_sensor_button_pressed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#FFFFFF',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_button_1, '1'],\n                                [Lang.Blocks.neo_lite_button_2, '2'],\n                                [Lang.Blocks.neo_lite_button_3, '3'],\n                                [Lang.Blocks.neo_lite_button_4, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_button_on, 'ON'],\n                                [Lang.Blocks.neo_lite_button_off, 'OFF'],\n                            ],\n                            value: 'on',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_sensor_button_pressed',\n                    },\n                    paramsKeyMap: {\n                        BUTTON: 0,\n                        PRESSED: 1,\n                    },\n                    class: 'neo_lite_sensor',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        const button = script.getNumberField('BUTTON');\n                        const pressed = script.getStringField('PRESSED');\n                        const sensorData = this.sensorValues;\n                        const value = sensorData.IR;\n                        if (button === 1) {\n                            if (pressed === 'ON') {\n                                return value === 10;\n                            } else {\n                                return value !== 10;\n                            }\n                        } else if (button === 2) {\n                            if (pressed === 'ON') {\n                                return value === 11;\n                            } else {\n                                return value !== 11;\n                            }\n                        } else if (button === 3) {\n                            if (pressed === 'ON') {\n                                return value === 12;\n                            } else {\n                                return value !== 12;\n                            }\n                        } else if (button === 4) {\n                            if (pressed === 'ON') {\n                                return value === 13;\n                            } else {\n                                return value !== 13;\n                            }\n                        }\n                    },\n                },\n                /**\n                 * 버저\n                 */\n                neo_lite_buzzer_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_buzzer_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_buzzer_title',\n                    },\n                    class: 'neo_lite_buzzer',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_buzzer_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_buzzer_octave_1, '0'],\n                                [Lang.Blocks.neo_lite_buzzer_octave_2, '1'],\n                                [Lang.Blocks.neo_lite_buzzer_octave_3, '2'],\n                                [Lang.Blocks.neo_lite_buzzer_octave_4, '3'],\n                                [Lang.Blocks.neo_lite_buzzer_octave_5, '4'],\n                                [Lang.Blocks.neo_lite_buzzer_octave_6, '5'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_buzzer_do, '1'],\n                                [Lang.Blocks.neo_lite_buzzer_do_sharp, '2'],\n                                [Lang.Blocks.neo_lite_buzzer_re, '3'],\n                                [Lang.Blocks.neo_lite_buzzer_re_sharp, '4'],\n                                [Lang.Blocks.neo_lite_buzzer_mi, '5'],\n                                [Lang.Blocks.neo_lite_buzzer_fa, '6'],\n                                [Lang.Blocks.neo_lite_buzzer_fa_sharp, '7'],\n                                [Lang.Blocks.neo_lite_buzzer_sol, '8'],\n                                [Lang.Blocks.neo_lite_buzzer_sol_sharp, '9'],\n                                [Lang.Blocks.neo_lite_buzzer_la, '10'],\n                                [Lang.Blocks.neo_lite_buzzer_la_sharp, '11'],\n                                [Lang.Blocks.neo_lite_buzzer_ti, '12'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_buzzer_whole_note, '1'],\n                                [Lang.Blocks.neo_lite_buzzer_half_note, '2'],\n                                [Lang.Blocks.neo_lite_buzzer_quarter_note, '4'],\n                                [Lang.Blocks.neo_lite_buzzer_8th_note, '8'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'neo_lite_buzzer_start',\n                    },\n                    paramsKeyMap: {\n                        OCTAVE: 0,\n                        NOTE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neo_lite_buzzer',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            const octave = script.getNumberField('OCTAVE');\n                            const note = script.getNumberField('NOTE');\n                            const value = Math.min(note + 12 * octave, 72);\n                            const duration = script.getStringValue('DURATION', script);\n                            const blockId = this.generateBlockId();\n                            this.requestCommand(blockId, NeoBlockType.BUZZER_START, [value]);\n                            script.exec_phase = ExecPhase.WAIT_TIMEOUT;\n                            setTimeout(\n                                () => {\n                                    script.exec_phase = ExecPhase.STOP;\n                                },\n                                (1 / duration) * 2000\n                            );\n                        } else if (script.exec_phase === ExecPhase.WAIT_TIMEOUT) {\n                            return script;\n                        } else if (script.exec_phase === ExecPhase.STOP) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.BUZZER_STOP, []);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_buzzer_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_input_1, 'IN1'],\n                                [Lang.Blocks.neo_lite_input_2, 'IN2'],\n                                [Lang.Blocks.neo_lite_input_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neo_lite_buzzer_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                    },\n                    class: 'neo_lite_buzzer',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const input = script.getStringField('INPUT');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestExtCommand(blockId, NeoBlockType.BUZZER_WITH_SENSOR, [\n                                input,\n                            ]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_buzzer_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neo_lite_buzzer_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'neo_lite_buzzer',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_STOP;\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.BUZZER_STOP, []);\n                        } else if (script.exec_phase === ExecPhase.PENDING_STOP) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                /**\n                 * LCD\n                 */\n                neo_lite_lcd_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neo_lite_lcd_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neo_lite_lcd_title',\n                    },\n                    class: 'neo_lite_lcd',\n                    isNotFor: ['NeoLite'],\n                    events: {},\n                },\n                neo_lite_lcd_image: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_lcd_image_1, '1'],\n                                [Lang.Blocks.neo_lite_lcd_image_2, '2'],\n                                [Lang.Blocks.neo_lite_lcd_image_3, '3'],\n                                [Lang.Blocks.neo_lite_lcd_image_4, '4'],\n                                [Lang.Blocks.neo_lite_lcd_image_5, '5'],\n                                [Lang.Blocks.neo_lite_lcd_image_6, '6'],\n                                [Lang.Blocks.neo_lite_lcd_image_7, '7'],\n                                [Lang.Blocks.neo_lite_lcd_image_8, '8'],\n                                [Lang.Blocks.neo_lite_lcd_image_9, '9'],\n                                [Lang.Blocks.neo_lite_lcd_image_10, '10'],\n                                [Lang.Blocks.neo_lite_lcd_image_11, '11'],\n                                [Lang.Blocks.neo_lite_lcd_image_12, '12'],\n                                [Lang.Blocks.neo_lite_lcd_image_13, '13'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neo_lite_lcd_image',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        IMAGE: 1,\n                    },\n                    class: 'neo_lite_lcd',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const image = script.getStringField('IMAGE');\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.LCD_IMAGE, [output, image]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                neo_lite_lcd_text: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_output_1, 'OUT1'],\n                                [Lang.Blocks.neo_lite_output_2, 'OUT2'],\n                                [Lang.Blocks.neo_lite_output_3, 'OUT3'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, 'NEO', null],\n                        type: 'neo_lite_lcd_text',\n                    },\n                    paramsKeyMap: {\n                        OUTPUT: 0,\n                        TEXT: 1,\n                    },\n                    class: 'neo_lite_lcd',\n                    isNotFor: ['NeoLite'],\n                    func: (sprite, script) => {\n                        if (!script.exec_phase) {\n                            script.exec_phase = ExecPhase.PENDING_RESPONSE;\n                            const output = script.getStringField('OUTPUT');\n                            const text = script.getStringValue('TEXT', script);\n                            const blockId = this.generateBlockId();\n                            script.block_id = blockId;\n                            this.requestCommand(blockId, NeoBlockType.LCD_TEXT, [output, text]);\n                        } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) {\n                            if (!this.pendingResponseList[script.block_id]) {\n                                delete script.block_id;\n                                delete script.exec_phase;\n                                return script.callReturn();\n                            }\n                        }\n                        return script;\n                    },\n                },\n                /**\n                 * ARG Blocks\n                 */\n                neo_lite_arg_duration: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_duration_c, 'c'],\n                                [Lang.Blocks.neo_lite_duration_0, '0'],\n                                [Lang.Blocks.neo_lite_duration_1, '1'],\n                                [Lang.Blocks.neo_lite_duration_2, '2'],\n                                [Lang.Blocks.neo_lite_duration_3, '3'],\n                                [Lang.Blocks.neo_lite_duration_4, '4'],\n                                [Lang.Blocks.neo_lite_duration_5, '5'],\n                                [Lang.Blocks.neo_lite_duration_6, '6'],\n                                [Lang.Blocks.neo_lite_duration_7, '7'],\n                                [Lang.Blocks.neo_lite_duration_8, '8'],\n                                [Lang.Blocks.neo_lite_duration_9, '9'],\n                            ],\n                            value: 'c',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neo_lite_arg',\n                    isNotFor: ['NeoLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n                neo_lite_arg_both_motor_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_motor_speed_100, '100'],\n                                [Lang.Blocks.neo_lite_motor_speed_95, '95'],\n                                [Lang.Blocks.neo_lite_motor_speed_90, '90'],\n                                [Lang.Blocks.neo_lite_motor_speed_85, '85'],\n                                [Lang.Blocks.neo_lite_motor_speed_80, '80'],\n                                [Lang.Blocks.neo_lite_motor_speed_75, '75'],\n                                [Lang.Blocks.neo_lite_motor_speed_70, '70'],\n                                [Lang.Blocks.neo_lite_motor_speed_65, '65'],\n                                [Lang.Blocks.neo_lite_motor_speed_60, '60'],\n                                [Lang.Blocks.neo_lite_motor_speed_55, '55'],\n                                [Lang.Blocks.neo_lite_motor_speed_50, '50'],\n                                [Lang.Blocks.neo_lite_motor_speed_45, '45'],\n                                [Lang.Blocks.neo_lite_motor_speed_40, '40'],\n                                [Lang.Blocks.neo_lite_motor_speed_35, '35'],\n                                [Lang.Blocks.neo_lite_motor_speed_30, '30'],\n                                [Lang.Blocks.neo_lite_motor_speed_25, '25'],\n                                [Lang.Blocks.neo_lite_motor_speed_20, '20'],\n                                [Lang.Blocks.neo_lite_motor_speed_15, '15'],\n                                [Lang.Blocks.neo_lite_motor_speed_10, '10'],\n                                [Lang.Blocks.neo_lite_motor_speed_5, '5'],\n                                [Lang.Blocks.neo_lite_motor_speed_0, '0'],\n                                [Lang.Blocks.neo_lite_motor_speed_n5, '-5'],\n                                [Lang.Blocks.neo_lite_motor_speed_n10, '-10'],\n                                [Lang.Blocks.neo_lite_motor_speed_n15, '-15'],\n                                [Lang.Blocks.neo_lite_motor_speed_n20, '-20'],\n                                [Lang.Blocks.neo_lite_motor_speed_n25, '-25'],\n                                [Lang.Blocks.neo_lite_motor_speed_n30, '-30'],\n                                [Lang.Blocks.neo_lite_motor_speed_n35, '-35'],\n                                [Lang.Blocks.neo_lite_motor_speed_n40, '-40'],\n                                [Lang.Blocks.neo_lite_motor_speed_n45, '-45'],\n                                [Lang.Blocks.neo_lite_motor_speed_n50, '-50'],\n                                [Lang.Blocks.neo_lite_motor_speed_n55, '-55'],\n                                [Lang.Blocks.neo_lite_motor_speed_n60, '-60'],\n                                [Lang.Blocks.neo_lite_motor_speed_n65, '-65'],\n                                [Lang.Blocks.neo_lite_motor_speed_n70, '-70'],\n                                [Lang.Blocks.neo_lite_motor_speed_n75, '-75'],\n                                [Lang.Blocks.neo_lite_motor_speed_n80, '-80'],\n                                [Lang.Blocks.neo_lite_motor_speed_n85, '-85'],\n                                [Lang.Blocks.neo_lite_motor_speed_n90, '-90'],\n                                [Lang.Blocks.neo_lite_motor_speed_n95, '-95'],\n                                [Lang.Blocks.neo_lite_motor_speed_n100, '-100'],\n                            ],\n                            value: '100',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neo_lite_arg',\n                    isNotFor: ['NeoLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n                neo_lite_arg_servo_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neo_lite_servo_angle_360, '360'],\n                                [Lang.Blocks.neo_lite_servo_angle_350, '350'],\n                                [Lang.Blocks.neo_lite_servo_angle_340, '340'],\n                                [Lang.Blocks.neo_lite_servo_angle_330, '330'],\n                                [Lang.Blocks.neo_lite_servo_angle_320, '320'],\n                                [Lang.Blocks.neo_lite_servo_angle_310, '310'],\n                                [Lang.Blocks.neo_lite_servo_angle_300, '300'],\n                                [Lang.Blocks.neo_lite_servo_angle_290, '290'],\n                                [Lang.Blocks.neo_lite_servo_angle_280, '280'],\n                                [Lang.Blocks.neo_lite_servo_angle_270, '270'],\n                                [Lang.Blocks.neo_lite_servo_angle_260, '260'],\n                                [Lang.Blocks.neo_lite_servo_angle_250, '250'],\n                                [Lang.Blocks.neo_lite_servo_angle_240, '240'],\n                                [Lang.Blocks.neo_lite_servo_angle_230, '230'],\n                                [Lang.Blocks.neo_lite_servo_angle_220, '220'],\n                                [Lang.Blocks.neo_lite_servo_angle_210, '210'],\n                                [Lang.Blocks.neo_lite_servo_angle_200, '200'],\n                                [Lang.Blocks.neo_lite_servo_angle_190, '190'],\n                                [Lang.Blocks.neo_lite_servo_angle_180, '180'],\n                                [Lang.Blocks.neo_lite_servo_angle_170, '170'],\n                                [Lang.Blocks.neo_lite_servo_angle_160, '160'],\n                                [Lang.Blocks.neo_lite_servo_angle_150, '150'],\n                                [Lang.Blocks.neo_lite_servo_angle_140, '140'],\n                                [Lang.Blocks.neo_lite_servo_angle_130, '130'],\n                                [Lang.Blocks.neo_lite_servo_angle_120, '120'],\n                                [Lang.Blocks.neo_lite_servo_angle_110, '110'],\n                                [Lang.Blocks.neo_lite_servo_angle_100, '100'],\n                                [Lang.Blocks.neo_lite_servo_angle_90, '90'],\n                                [Lang.Blocks.neo_lite_servo_angle_80, '80'],\n                                [Lang.Blocks.neo_lite_servo_angle_70, '70'],\n                                [Lang.Blocks.neo_lite_servo_angle_60, '60'],\n                                [Lang.Blocks.neo_lite_servo_angle_50, '50'],\n                                [Lang.Blocks.neo_lite_servo_angle_40, '40'],\n                                [Lang.Blocks.neo_lite_servo_angle_30, '30'],\n                                [Lang.Blocks.neo_lite_servo_angle_20, '20'],\n                                [Lang.Blocks.neo_lite_servo_angle_10, '10'],\n                                [Lang.Blocks.neo_lite_servo_angle_0, '0'],\n                                [Lang.Blocks.neo_lite_servo_angle_n10, '-10'],\n                                [Lang.Blocks.neo_lite_servo_angle_n20, '-20'],\n                                [Lang.Blocks.neo_lite_servo_angle_n30, '-30'],\n                                [Lang.Blocks.neo_lite_servo_angle_n40, '-40'],\n                                [Lang.Blocks.neo_lite_servo_angle_n50, '-50'],\n                                [Lang.Blocks.neo_lite_servo_angle_n60, '-60'],\n                                [Lang.Blocks.neo_lite_servo_angle_n70, '-70'],\n                                [Lang.Blocks.neo_lite_servo_angle_n80, '-80'],\n                                [Lang.Blocks.neo_lite_servo_angle_n90, '-90'],\n                                [Lang.Blocks.neo_lite_servo_angle_n100, '-100'],\n                                [Lang.Blocks.neo_lite_servo_angle_n110, '-110'],\n                                [Lang.Blocks.neo_lite_servo_angle_n120, '-120'],\n                                [Lang.Blocks.neo_lite_servo_angle_n130, '-130'],\n                                [Lang.Blocks.neo_lite_servo_angle_n140, '-140'],\n                                [Lang.Blocks.neo_lite_servo_angle_n150, '-150'],\n                                [Lang.Blocks.neo_lite_servo_angle_n160, '-160'],\n                                [Lang.Blocks.neo_lite_servo_angle_n170, '-170'],\n                                [Lang.Blocks.neo_lite_servo_angle_n180, '-180'],\n                                [Lang.Blocks.neo_lite_servo_angle_n190, '-190'],\n                                [Lang.Blocks.neo_lite_servo_angle_n200, '-200'],\n                                [Lang.Blocks.neo_lite_servo_angle_n210, '-210'],\n                                [Lang.Blocks.neo_lite_servo_angle_n220, '-220'],\n                                [Lang.Blocks.neo_lite_servo_angle_n230, '-230'],\n                                [Lang.Blocks.neo_lite_servo_angle_n240, '-240'],\n                                [Lang.Blocks.neo_lite_servo_angle_n250, '-250'],\n                                [Lang.Blocks.neo_lite_servo_angle_n260, '-260'],\n                                [Lang.Blocks.neo_lite_servo_angle_n270, '-270'],\n                                [Lang.Blocks.neo_lite_servo_angle_n280, '-280'],\n                                [Lang.Blocks.neo_lite_servo_angle_n290, '-290'],\n                                [Lang.Blocks.neo_lite_servo_angle_n300, '-300'],\n                                [Lang.Blocks.neo_lite_servo_angle_n310, '-310'],\n                                [Lang.Blocks.neo_lite_servo_angle_n320, '-320'],\n                                [Lang.Blocks.neo_lite_servo_angle_n330, '-330'],\n                                [Lang.Blocks.neo_lite_servo_angle_n340, '-340'],\n                                [Lang.Blocks.neo_lite_servo_angle_n350, '-350'],\n                                [Lang.Blocks.neo_lite_servo_angle_n360, '-360'],\n                            ],\n                            value: '100',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neo_lite_arg',\n                    isNotFor: ['NeoLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n            };\n        }\n\n        /*\n         Functions for logging\n         */\n        logD(msg) {\n            if (this.isDebug) {\n                console.log(msg);\n            }\n        }\n\n        logPdu(msg) {\n            if (this.isDebugPdu) {\n                this.logD(msg);\n            }\n        }\n\n        logSensor(msg) {\n            if (this.isDebugSensor) {\n                this.logD(msg);\n            }\n        }\n\n        byteArrayToHex(data) {\n            let hexStr = '';\n            for (let i = 0; i < data.length; i++) {\n                hexStr += this.byteToHexString(data[i]);\n                hexStr += ' ';\n            }\n            return hexStr;\n        }\n\n        byteToHexString(byte) {\n            return `0${byte.toString(16)}`.slice(-2).toUpperCase();\n        }\n\n        getCurrentTime() {\n            const date = new Date();\n            return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()} ${date.getMilliseconds()}`;\n        }\n\n        makeCommand(blockId, type, params) {\n            //const body = [FrameCode.BASIC, PduCode.ACTION_COMMAND, PduType.REQUEST];\n            const body = [FrameCode.BASIC, PduCode.BASIC, blockId];\n            if (type === NeoBlockType.MOTOR_MOVE) {\n                const which = params[0];\n                const speed = Math.abs(params[1]);\n                const direction = params[1] < 0 ? 1 : 0;\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR);\n                const data = Buffer.from([0, 0, 0, 0, 0, 0]);\n                data.writeInt16LE(speed, 0);\n                data.writeInt16LE(which, 2);\n                data.writeInt16LE(direction, 4);\n                body.push(...data);\n            } else if (type === NeoBlockType.MOTOR_MOVE_BOTH) {\n                const speedL = params[0];\n                const speedR = params[1];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR_BOTH);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(speedL, 0);\n                data.writeInt16LE(speedR, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.ROBOT_MOVE) {\n                const robotCommand = params[0];\n                const speed = params[1];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(speed, 0);\n                data.writeInt16LE(robotCommand, 2);\n                body.push(...data);\n            } else if (\n                type === NeoBlockType.MOTOR_STOP ||\n                type === NeoBlockType.AUTO_DRIVING_STOP\n            ) {\n                const which = params[0];\n                const direction = 1;\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR);\n                const data = Buffer.from([0, 0, 0, 0, 0, 0]);\n                data.writeInt16LE(which, 2);\n                data.writeInt16LE(direction, 4);\n                body.push(...data);\n            } else if (type === NeoBlockType.ROBOT_STOP) {\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT);\n                const data = Buffer.from([0, 0, 0, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.SERVO_RESET) {\n                const output = params[0];\n                body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.RESET);\n                const data = Buffer.from([0, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.SERVO_ANGLE) {\n                const output = params[0];\n                const angle = params[1];\n                const speed = params[2];\n                body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.ANGLE);\n                const data = Buffer.from([0, 0, 0, 0, 1, 0]);\n                data.writeInt16LE(angle, 0);\n                data.writeInt16LE(speed, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.SERVO_ANGLE_WAIT) {\n                const output = params[0];\n                const angle = params[1];\n                const speed = params[2];\n                body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.ANGLE_WAIT);\n                const data = Buffer.from([0, 0, 0, 0, 1, 0]);\n                data.writeInt16LE(angle, 0);\n                data.writeInt16LE(speed, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.SERVO_ROTATE) {\n                const output = params[0];\n                const direction = params[1];\n                const speed = params[2];\n                body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.ROTATE);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(speed, 0);\n                data.writeInt16LE(direction, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.SERVO_STOP) {\n                const output = params[0];\n                body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.STOP);\n            } else if (\n                type === NeoBlockType.LINE_TRACER_START ||\n                type === NeoBlockType.AUTO_DRIVING_START ||\n                type === NeoBlockType.AUTO_DETECT_WALL_START\n            ) {\n                const speed = params[0];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT);\n                const data = Buffer.from([0, 0, 0x10, 0]);\n                data.writeInt16LE(speed, 0);\n                body.push(...data);\n            } else if (type === NeoBlockType.AUTO_DRIVING_SENSOR_START) {\n                const sensor = params[0];\n                const speed = params[1];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(speed, 0);\n                data.writeInt16LE(sensor, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.LINE_CROSS_MOVE) {\n                const count = params[0];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.LINE_TRACER);\n                const data = Buffer.from([0, 0]);\n                data.writeInt16LE(count, 0);\n                body.push(...data);\n            } else if (type === NeoBlockType.LINE_CROSS_TURN) {\n                const direction = params[0];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.LINE_TRACER);\n                const data = Buffer.from([0, 0]);\n                data.writeInt16LE(direction, 0);\n                body.push(...data);\n            } else if (type === NeoBlockType.AUTO_PARKING_START) {\n                // TODO : which 누락\n                const which = params[0];\n                const direction = params[1];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.AUTO_PARKING);\n                const data = Buffer.from([0, 0]);\n                data.writeInt16LE(direction, 0);\n                body.push(...data);\n            } else if (type === NeoBlockType.LINE_CHANGE_START) {\n                const direction = params[0];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.AUTO_DRIVING);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(60, 0);\n                data.writeInt16LE(direction, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.LINE_CHANGE_TURN) {\n                const direction = params[0];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.AUTO_DRIVING);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(60, 0);\n                data.writeInt16LE(direction, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.AUTO_DETECT_WALL_TURN) {\n                const direction = params[0];\n                body.push(\n                    UnitId.CONTROLLER,\n                    ActorKind.CONTROLLER,\n                    ControllerCommand.AUTO_DETECT_WALL\n                );\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(60, 0);\n                data.writeInt16LE(direction, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.LED_ON) {\n                const output = params[0];\n                const brightness = params[1];\n                body.push(this.getUnitId(output), ActorKind.LED, 0);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(brightness, 0);\n                body.push(...data);\n            } else if (type === NeoBlockType.LED_BLINK) {\n                const output = params[0];\n                const speed = params[1];\n                const brightness = params[2];\n                body.push(this.getUnitId(output), ActorKind.LED, 0);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(brightness, 0);\n                data.writeInt16LE(speed, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.LED_OFF) {\n                const output = params[0];\n                body.push(this.getUnitId(output), ActorKind.LED, 0);\n                const data = Buffer.from([0, 0, 0, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.COLOR_LED_ON) {\n                const output = params[0];\n                body.push(this.getUnitId(output), ActorKind.COLOR_LED, LedCommand.ON);\n                const data = Buffer.from([0, 0, 0, 0, 0, 0]);\n                const color = params[1];\n                if (color.length === 7 && color[0] === '#') {\n                    const r = color.substr(1, 2);\n                    const g = color.substr(3, 2);\n                    const b = color.substr(5, 2);\n                    data.writeInt16LE(parseInt(r, 16), 0);\n                    data.writeInt16LE(parseInt(g, 16), 2);\n                    data.writeInt16LE(parseInt(b, 16), 4);\n                }\n                body.push(...data);\n            } else if (type === NeoBlockType.COLOR_LED_OFF) {\n                const output = params[0];\n                body.push(this.getUnitId(output), ActorKind.COLOR_LED, LedCommand.OFF);\n            } else if (type === NeoBlockType.SET_OUTPUT) {\n                const output = params[0];\n                const value = params[1];\n                body.push(this.getUnitId(output), ActorKind.LED, 0);\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(value, 0);\n                body.push(...data);\n            } else if (type === NeoBlockType.BUZZER_START) {\n                const value = params[0];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.BUZZER);\n                const data = Buffer.from([0, 0]);\n                data.writeInt16LE(value, 0);\n                body.push(...data);\n            } else if (type === NeoBlockType.BUZZER_STOP) {\n                const value = params[0];\n                body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.BUZZER);\n                const data = Buffer.from([0, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.LCD_IMAGE) {\n                const output = this.getUnitId(params[0]);\n                const value = params[1];\n                body.push(output, ActorKind.LCD, LcdCommand.IMAGE);\n                const data = Buffer.from([value, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.LCD_TEXT) {\n                const output = this.getUnitId(params[0]);\n                const value = params[1];\n                body.push(output, ActorKind.LCD, LcdCommand.TEXT);\n                body.push(0); // 글씨크기 : 지금 안됨.\n                if (value.length > 0) {\n                    for (let idx = 0; idx < value.length; idx++) {\n                        body.push(value.charCodeAt(idx));\n                    }\n                }\n            }\n            return body;\n        }\n\n        makeCommandExt(blockId, type, params) {\n            const body = [FrameCode.BASIC];\n            if (type === NeoBlockType.MOTOR_MOVE) {\n                const which = params[0];\n                const unitId = this.getUnitId(params[1]);\n                body.push(\n                    PduCode.EXTEND_1,\n                    blockId,\n                    UnitId.CONTROLLER,\n                    ActorKind.CONTROLLER,\n                    ControllerCommand.MOTOR\n                );\n                const data = Buffer.from([unitId, 0, which, 0, 0, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.ROBOT_MOVE) {\n                const robotCommand = params[0];\n                const unitId = this.getUnitId(params[1]);\n                body.push(\n                    PduCode.EXTEND_1,\n                    blockId,\n                    UnitId.CONTROLLER,\n                    ActorKind.CONTROLLER,\n                    ControllerCommand.ROBOT\n                );\n                const data = Buffer.from([unitId, 0, 0, 0]);\n                data.writeInt16LE(robotCommand, 2);\n                body.push(...data);\n            } else if (\n                type === NeoBlockType.SERVO_ANGLE ||\n                type === NeoBlockType.SERVO_ANGLE_WAIT\n            ) {\n                const unitId = this.getUnitId(params[0]);\n                let angle = params[1];\n                const speed = params[2];\n                if (angle.indexOf('IN') >= 0) {\n                    angle = this.getUnitId(angle);\n                }\n                body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.SERVO, ServoCommand.ANGLE);\n                const data = Buffer.from([angle, 0, 0, 0, 1, 0]);\n                data.writeInt16LE(speed, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.SERVO_ROTATE) {\n                const unitId = this.getUnitId(params[0]);\n                const direction = params[1];\n                const inUnitId = this.getUnitId(params[2]);\n                body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.SERVO, ServoCommand.ROTATE);\n                const data = Buffer.from([inUnitId, 0, 0, 0]);\n                data.writeInt16LE(direction, 2);\n                body.push(...data);\n            } else if (\n                type === NeoBlockType.LINE_TRACER_START ||\n                type === NeoBlockType.AUTO_DRIVING_START ||\n                type === NeoBlockType.AUTO_DETECT_WALL_START\n            ) {\n                const unitId = this.getUnitId(params[0]);\n                body.push(\n                    PduCode.EXTEND_1,\n                    blockId,\n                    UnitId.CONTROLLER,\n                    ActorKind.CONTROLLER,\n                    ControllerCommand.ROBOT\n                );\n                const data = Buffer.from([unitId, 0, 0x10, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.AUTO_DRIVING_SENSOR_START) {\n                const sensor = params[0];\n                const unitId = this.getUnitId(params[1]);\n                body.push(\n                    PduCode.EXTEND_1,\n                    blockId,\n                    UnitId.CONTROLLER,\n                    ActorKind.CONTROLLER,\n                    ControllerCommand.ROBOT\n                );\n                const data = Buffer.from([0, 0, 0, 0]);\n                data.writeInt16LE(unitId, 0);\n                data.writeInt16LE(sensor, 2);\n                body.push(...data);\n            } else if (type === NeoBlockType.LED_ON) {\n                const unitId = this.getUnitId(params[0]);\n                const inUnitId = this.getUnitId(params[1]);\n                body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.LED, 0);\n                const data = Buffer.from([inUnitId, 0, 0, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.SET_OUTPUT) {\n                const unitId = this.getUnitId(params[0]);\n                const inUnitId = this.getUnitId(params[1]);\n                body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.LED, 0);\n                const data = Buffer.from([inUnitId, 0, 0, 0]);\n                body.push(...data);\n            } else if (type === NeoBlockType.BUZZER_WITH_SENSOR) {\n                const sensorUnitId = this.getUnitId(params[0]);\n                body.push(\n                    PduCode.EXTEND_1,\n                    blockId,\n                    UnitId.CONTROLLER,\n                    ActorKind.CONTROLLER,\n                    ControllerCommand.BUZZER\n                );\n                const data = Buffer.from([0, 0]);\n                data.writeInt16LE(sensorUnitId, 0);\n                body.push(...data);\n            } else if (type === NeoBlockType.COLOR_LED_ON_SENSOR) {\n                const outUnitId = this.getUnitId(params[0]);\n                const inUnitId = this.getUnitId(params[1]);\n                body.push(PduCode.EXTEND_3, blockId, outUnitId, ActorKind.COLOR_LED, LedCommand.ON);\n                const data = Buffer.from([inUnitId, 1, inUnitId, 2, inUnitId, 3]);\n                body.push(...data);\n            }\n            return body;\n        }\n\n        makeCommandExt2(blockId, type, params) {\n            const body = [FrameCode.BASIC];\n            if (type === NeoBlockType.SERVO_ANGLE || type === NeoBlockType.SERVO_ANGLE_WAIT) {\n                const unitId = this.getUnitId(params[0]);\n                const angleInUnitId = this.getUnitId(params[1]);\n                const speedInUnitId = this.getUnitId(params[2]);\n                body.push(PduCode.EXTEND_2, blockId, unitId, ActorKind.SERVO, ServoCommand.ANGLE);\n                const data = Buffer.from([angleInUnitId, 0, speedInUnitId, 0, 1, 0]);\n                body.push(...data);\n            }\n            return body;\n        }\n\n        async runAutoParking(script) {\n            const type = script.getNumberValue('DIRECTION', script);\n            const side = script.getNumberValue('WHICH', script);\n            let which = 0;\n            if (type === 1) {\n                // 후면주차\n                this.requestCommand(this.generateBlockId(), NeoBlockType.LINE_TRACER_START, [40]);\n                await Entry.Utils.sleep(2400);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                which = side === 1 ? 1 : 2;\n                this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, 30]);\n                await Entry.Utils.sleep(2000);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_MOVE, [2, 25]);\n                await Entry.Utils.sleep(2500);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                which = side === 1 ? 2 : 1;\n                this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, -30]);\n                await Entry.Utils.sleep(1300);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_MOVE, [2, 25]);\n                await Entry.Utils.sleep(1700);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            } else {\n                // 평행주차\n                this.requestCommand(this.generateBlockId(), NeoBlockType.LINE_TRACER_START, [40]);\n                await Entry.Utils.sleep(3000);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                which = side === 1 ? 1 : 2;\n                this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, 30]);\n                await Entry.Utils.sleep(2000);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_MOVE, [2, 30]);\n                await Entry.Utils.sleep(3000);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                which = side === 1 ? 1 : 2;\n                this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, -30]);\n                await Entry.Utils.sleep(1000);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                which = side === 1 ? 2 : 1;\n                this.requestCommand(this.generateBlockId(), NeoBlockType.MOTOR_MOVE, [which, 25]);\n                await Entry.Utils.sleep(1000);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_MOVE, [2, 20]);\n                await Entry.Utils.sleep(1000);\n                this.requestCommand(this.generateBlockId(), NeoBlockType.ROBOT_STOP, [0]);\n            }\n            return script.callReturn();\n        }\n    })();\n})();\n\nmodule.exports = Entry.NeoLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_neo_spider_lite.js",
    "content": "'use strict';\n\n(function() {\n    Entry.NeoSpiderLite = new (class NeoSpiderLite {\n        constructor() {\n            this.id = '410101';\n            this.name = 'NeoSpiderLite';\n            this.url = 'http://www.neo3ds.com/';\n            this.imageName = 'neospiderlite.png';\n            this.title = {\n                ko: '네오스파이더',\n                en: 'NeoSpider',\n            };\n            this.duration = 32;\n            this.blockMenuBlocks = [\n                'neospiderlite_get_analog_value',\n                'neospiderlite_get_analog_value_map',\n                'neospiderlite_get_ultrasonic_value',\n                'neospiderlite_get_motion_value',\n                'neospiderlite_get_infared_value',\n                'neospiderlite_set_servo',\n                'neospiderlite_set_servo_direction',\n                'neospiderlite_set_tone',\n                'neospiderlite_motor_state',\n                'neospiderlite_motor_state_secs',\n                'neospiderlite_motor_stop',\n                'neospiderlite_neopixel_color_picker',\n                'neospiderlite_neopixel_color_picker_all_on',\n                'neospiderlite_neopixel',\n                'neospiderlite_neopixel_all_on',\n                'neospiderlite_neopixel_all_off',\n                'neospiderlite_outer_motor',\n                'neospiderlite_outer_motor_pwm',\n            ];\n            this.portData = {\n                baudRate: 115200,\n                duration: 32,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n            };\n            this.__toneTable = {\n                '0': 0,\n                C: 1,\n                CS: 2,\n                D: 3,\n                DS: 4,\n                E: 5,\n                F: 6,\n                FS: 7,\n                G: 8,\n                GS: 9,\n                A: 10,\n                AS: 11,\n                B: 12,\n            };\n            this.__toneMap = {\n                '1': [33, 65, 131, 262, 523, 1046, 2093, 4186],\n                '2': [35, 69, 139, 277, 554, 1109, 2217, 4435],\n                '3': [37, 73, 147, 294, 587, 1175, 2349, 4699],\n                '4': [39, 78, 156, 310, 622, 1245, 2637, 4978],\n                '5': [41, 82, 165, 330, 659, 1319, 2794, 5274],\n                '6': [44, 87, 175, 349, 698, 1397, 2849, 5588],\n                '7': [46, 92, 185, 370, 740, 1480, 2960, 5920],\n                '8': [49, 98, 196, 392, 784, 1568, 3136, 6272],\n                '9': [52, 104, 208, 415, 831, 1661, 3322, 6645],\n                '10': [55, 110, 220, 440, 880, 1760, 3520, 7040],\n                '11': [58, 117, 233, 466, 932, 1865, 3729, 7459],\n                '12': [62, 123, 247, 494, 988, 1976, 3951, 7902],\n            };\n            this.setZero();\n        }\n\n        get monitorTemplate() {\n            return {\n                imgPath: 'hw_lite/neospiderlite.png',\n                width: 256,\n                height: 256,\n                listPorts: {\n                    GAS: {\n                        name: '가스/외부센서',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    CDS: {\n                        name: '조도센서',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    TMP: {\n                        name: '온도센서',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    VIBE: {\n                        name: '진동센서',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    LEFT_INFARED: {\n                        name: '적외선(좌)',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    RIGHT_INFARED: {\n                        name: '적외선(우)',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    ULTRASONIC: {\n                        name: '초음파센서',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                    MOTION: {\n                        name: '모션센서',\n                        type: 'input',\n                        pos: { x: 0, y: 0 },\n                    },\n                },\n                mode: 'both',\n            };\n        }\n\n        getMonitorPort() {\n            return { ...this.sensorData };\n        }\n\n        setZero() {\n            this.txData = new Array(36).fill(0);\n\n            this.sensorData = {\n                LEFT_INFARED: 0,\n                RIGHT_INFARED: 0,\n                MOTION: 0,\n                ULTRASONIC: 0,\n                GAS: 0,\n                CDS: 0,\n                TMP: 0,\n                VIBE: 0,\n            };\n            this.workerData = {\n                OCTAVE: 0,\n                NOTE: 0,\n                ULTRASONIC: 0,\n                MOTION: 0,\n                MOTOR: 0,\n                SERVO: 0,\n                NEOPIXEL: [\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                    { RED: 0, GREEN: 0, BLUE: 0 },\n                ],\n                OUT_MOTOR_LEFT: 0,\n                OUT_MOTOR_RIGHT: 0,\n            };\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        getDataByBuffer(buffer) {\n            const datas = [];\n            let lastIndex = 0;\n            buffer.forEach((value, idx) => {\n                if (value == 13 && buffer[idx + 1] == 10) {\n                    datas.push(buffer.subarray(lastIndex, idx));\n                    lastIndex = idx + 2;\n                }\n            });\n            return datas;\n        }\n\n        // 디바이스에서 값을 읽어온다.\n        handleLocalData(data) {\n            const datas = this.getDataByBuffer(data);\n            const sensorData = this.sensorData;\n\n            datas.forEach((data) => {\n                if (data.length <= 4 || data[0] !== 255 || data[1] !== 16) {\n                    return;\n                }\n                const readData = data.subarray(2, data.length);\n                let value;\n                let checkSum;\n                const idx = readData[0];\n                if (idx == 1) {\n                    if (readData.length != 12) {\n                        return;\n                    }\n                    const analogL0 = readData[1];\n                    const analogS0 = readData[2];\n                    const analogL1 = readData[3];\n                    const analogS1 = readData[4];\n                    const analogL2 = readData[5];\n                    const analogS2 = readData[6];\n                    const analogL3 = readData[7];\n                    const analogS3 = readData[8];\n                    const infaredLv = readData[9];\n                    const infaredRv = readData[10];\n                    checkSum =\n                        (idx +\n                            analogL0 +\n                            analogS0 +\n                            analogL1 +\n                            analogS1 +\n                            analogL2 +\n                            analogS2 +\n                            analogL3 +\n                            analogS3 +\n                            infaredLv +\n                            infaredRv) &\n                        0xff;\n                    if (checkSum != readData[11]) {\n                        return;\n                    }\n                    let tempValue = (analogL2 << 8) + analogS2;\n                    tempValue = Math.log(10240000 / tempValue - 10000);\n                    tempValue =\n                        1 /\n                        (0.001129148 +\n                            0.000234125 * tempValue +\n                            0.0000000876741 * tempValue * tempValue * tempValue);\n                    tempValue = tempValue - 273.15 - 4.0; // Downsize temperature\n                    sensorData.GAS = (analogL0 << 8) + analogS0;\n                    sensorData.CDS = (analogL1 << 8) + analogS1;\n                    sensorData.TMP = tempValue.toFixed(2);\n                    sensorData.VIBE = (analogL3 << 8) + analogS3;\n                    sensorData.LEFT_INFARED = infaredLv;\n                    sensorData.RIGHT_INFARED = infaredRv;\n                } else if (idx == 2 || idx == 3) {\n                    if (readData.length != 6) {\n                        return;\n                    }\n                    const subArray = new Uint8Array(readData.subarray(1, 5));\n                    subArray.reverse();\n                    const buffer = subArray.buffer;\n                    const view = new DataView(buffer);\n                    value = view.getFloat32(0);\n                    value = Math.round(value * 100) / 100;\n                    checkSum = (idx + value) & 0xff;\n                    if (checkSum != readData[5]) {\n                        return;\n                    }\n                    if (idx == 2) {\n                        sensorData.ULTRASONIC = value;\n                    } else {\n                        sensorData.MOTION = value;\n                    }\n                }\n            });\n            this.sensorData = sensorData;\n        }\n\n        //디바이스에 값을 쓴다.\n        requestLocalData() {\n            const workerData = this.workerData;\n            const txData = this.txData;\n            let checkSum = 0;\n            const dataLen = txData.length;\n\n            txData[0] = 0xff;\n            txData[1] = 0x24;\n            txData[2] = workerData.OCTAVE;\n            txData[3] = workerData.NOTE;\n            txData[4] = workerData.ULTRASONIC;\n            txData[5] = workerData.MOTION;\n            txData[6] = workerData.MOTOR;\n            txData[7] = workerData.SERVO;\n            txData[8] = workerData.NEOPIXEL[0].RED;\n            txData[9] = workerData.NEOPIXEL[0].GREEN;\n            txData[10] = workerData.NEOPIXEL[0].BLUE;\n            txData[11] = workerData.NEOPIXEL[1].RED;\n            txData[12] = workerData.NEOPIXEL[1].GREEN;\n            txData[13] = workerData.NEOPIXEL[1].BLUE;\n            txData[14] = workerData.NEOPIXEL[2].RED;\n            txData[15] = workerData.NEOPIXEL[2].GREEN;\n            txData[16] = workerData.NEOPIXEL[2].BLUE;\n            txData[17] = workerData.NEOPIXEL[3].RED;\n            txData[18] = workerData.NEOPIXEL[3].GREEN;\n            txData[19] = workerData.NEOPIXEL[3].BLUE;\n            txData[20] = workerData.NEOPIXEL[4].RED;\n            txData[21] = workerData.NEOPIXEL[4].GREEN;\n            txData[22] = workerData.NEOPIXEL[4].BLUE;\n            txData[23] = workerData.NEOPIXEL[5].RED;\n            txData[24] = workerData.NEOPIXEL[5].GREEN;\n            txData[25] = workerData.NEOPIXEL[5].BLUE;\n            txData[26] = workerData.NEOPIXEL[6].RED;\n            txData[27] = workerData.NEOPIXEL[6].GREEN;\n            txData[28] = workerData.NEOPIXEL[6].BLUE;\n            txData[29] = workerData.NEOPIXEL[7].RED;\n            txData[30] = workerData.NEOPIXEL[7].GREEN;\n            txData[31] = workerData.NEOPIXEL[7].BLUE;\n            txData[32] = workerData.OUT_MOTOR_LEFT;\n            txData[33] = workerData.OUT_MOTOR_RIGHT;\n            txData[35] = 0xa;\n\n            for (let i = 2; i < dataLen - 2; i++) {\n                checkSum += txData[i];\n            }\n            txData[dataLen - 2] = checkSum & 255;\n\n            this.tx_data = txData;\n\n            return txData;\n        }\n\n        getAnalogValue(script) {\n            let port = script.getValue('PORT', script);\n            port = port === 'OUTER' ? 'GAS' : port;\n            return this.sensorData[port];\n        }\n\n        getAnalogMapValue(script) {\n            let port = script.getValue('PORT', script);\n            const minValue = script.getNumberValue('MINV', script);\n            const maxValue = script.getNumberValue('MAXV', script);\n            const minTrans = script.getNumberValue('TMIN', script);\n            const maxTrans = script.getNumberValue('TMAX', script);\n\n            port = port === 'OUTER' ? 'GAS' : port;\n            let value = this.sensorData[port];\n            value = ((value - minValue) * (maxTrans - minTrans)) / maxValue - minValue + minTrans;\n\n            if (value % 1 == 0) {\n                value = Math.round(value);\n            } else {\n                value = Math.round((value * 100) / 100);\n            }\n            return value;\n        }\n\n        getUltrasonic() {\n            this.workerData.ULTRASONIC = 1;\n            return this.sensorData.ULTRASONIC || 0;\n        }\n\n        getMotion() {\n            this.workerData.MOTION = 1;\n            return this.sensorData.MOTION || 0;\n        }\n\n        getInfared(script) {\n            const port = script.getValue('PORT', script);\n            return this.sensorData[port] || 0;\n        }\n\n        setTone(script) {\n            if (!script.isStart) {\n                let note = script.getValue('NOTE', script);\n                if (!Entry.Utils.isNumber(note)) {\n                    note = this.__toneTable[note];\n                }\n\n                if (note < 0) {\n                    note = 0;\n                } else if (note > 12) {\n                    note = 12;\n                }\n\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration <= 0) {\n                    duration = 0;\n                    this.workerData.OCTAVE = 0;\n                    this.workerData.NOTE = 0;\n                    return script.callReturn();\n                }\n\n                let octave = script.getNumberValue('OCTAVE', script) - 1;\n\n                if (octave < 0) {\n                    octave = 0;\n                } else if (octave > 5) {\n                    octave = 5;\n                }\n\n                let value = 0;\n                if (note != 0) {\n                    value = this.__toneMap[note][octave];\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                this.workerData.OCTAVE = value >> 8;\n                this.workerData.NOTE = value & 255;\n\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, duration + 32);\n                return script;\n            } else if (script.timeFlag == 1) {\n                return script;\n            } else {\n                delete script.timeFlag;\n                delete script.isStart;\n                this.workerData.OCTAVE = 0;\n                this.workerData.NOTE = 0;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setServo(script) {\n            let value = script.getNumberValue('VALUE', script);\n            value = Math.min(130, value);\n            value = Math.max(50, value);\n\n            this.workerData.SERVO = value;\n            return script.callReturn();\n        }\n\n        setMotor(script) {\n            const state = script.getField('STATE');\n\n            this.workerData.MOTOR = state;\n            return script.callReturn();\n        }\n\n        setMotorSecs(script) {\n            if (!script.isStart) {\n                let state = script.getField('STATE');\n                let duration = script.getNumberValue('DURATION', script);\n\n                if (duration <= 0) {\n                    duration = 0;\n                    state = 0;\n                }\n\n                duration = duration * 1000;\n                script.isStart = true;\n                script.timeFlag = 1;\n\n                this.workerData.MOTOR = state;\n\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, duration + 32);\n\n                return script;\n            } else if (script.timeFlag == 1) {\n                return script;\n            } else {\n                delete script.timeFlag;\n                delete script.isStart;\n                this.workerData.MOTOR = 0;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setMotorStop(script) {\n            this.workerData.MOTOR = 0;\n            return script.callReturn();\n        }\n\n        setNeopixel(script) {\n            let num = script.getNumberValue('NUM', script);\n            const redPower = script.getNumberValue('RED', script);\n            const greenPower = script.getNumberValue('GREEN', script);\n            const bluePower = script.getNumberValue('BLUE', script);\n\n            num = num & 7;\n\n            this.workerData.NEOPIXEL[num].RED = redPower;\n            this.workerData.NEOPIXEL[num].GREEN = greenPower;\n            this.workerData.NEOPIXEL[num].BLUE = bluePower;\n            return script.callReturn();\n        }\n\n        setAllNeopixel(script) {\n            const redPower = script.getNumberValue('RED', script);\n            const greenPower = script.getNumberValue('GREEN', script);\n            const bluePower = script.getNumberValue('BLUE', script);\n\n            for (let num = 0; num < 8; num++) {\n                this.workerData.NEOPIXEL[num].RED = redPower;\n                this.workerData.NEOPIXEL[num].GREEN = greenPower;\n                this.workerData.NEOPIXEL[num].BLUE = bluePower;\n            }\n\n            return script.callReturn();\n        }\n\n        setNeopixelPicker(script) {\n            let num = script.getNumberValue('NUM', script);\n            const color = script.getStringField('COLOR');\n\n            num = num & 7;\n\n            const redPower = parseInt(color.substr(1, 2), 16);\n            const greenPower = parseInt(color.substr(3, 2), 16);\n            const bluePower = parseInt(color.substr(5, 2), 16);\n\n            this.workerData.NEOPIXEL[num].RED = redPower;\n            this.workerData.NEOPIXEL[num].GREEN = greenPower;\n            this.workerData.NEOPIXEL[num].BLUE = bluePower;\n            return script.callReturn();\n        }\n\n        setAllNeopixelPicker(script) {\n            const color = script.getStringField('COLOR');\n\n            const redPower = parseInt(color.substr(1, 2), 16);\n            const greenPower = parseInt(color.substr(3, 2), 16);\n            const bluePower = parseInt(color.substr(5, 2), 16);\n\n            for (let num = 0; num < 8; num++) {\n                this.workerData.NEOPIXEL[num].RED = redPower;\n                this.workerData.NEOPIXEL[num].GREEN = greenPower;\n                this.workerData.NEOPIXEL[num].BLUE = bluePower;\n            }\n\n            return script.callReturn();\n        }\n\n        setNeopixelOff(script) {\n            for (let num = 0; num < 8; num++) {\n                this.workerData.NEOPIXEL[num].RED = 0;\n                this.workerData.NEOPIXEL[num].GREEN = 0;\n                this.workerData.NEOPIXEL[num].BLUE = 0;\n            }\n\n            return script.callReturn();\n        }\n\n        setOuterMotor(script) {\n            const port = script.getNumberValue('PORT', script);\n            let state = script.getNumberValue('STATE', script);\n            state = state ? 255 : 0;\n\n            if (port == 5) {\n                this.workerData.OUT_MOTOR_LEFT = state;\n                this.workerData.OUT_MOTOR_RIGHT = 0;\n            } else if (port == 6) {\n                this.workerData.OUT_MOTOR_LEFT = 0;\n                this.workerData.OUT_MOTOR_RIGHT = state;\n            }\n\n            return script.callReturn();\n        }\n\n        setOuterMotorPWM(script) {\n            const port = script.getNumberValue('PORT', script);\n            let power = script.getNumberValue('VALUE', script);\n\n            power = Math.round(power);\n            power = Math.max(power, 0);\n            power = Math.min(power, 255);\n\n            if (port == 5) {\n                this.workerData.OUT_MOTOR_LEFT = power;\n                this.workerData.OUT_MOTOR_RIGHT = 0;\n            } else if (port == 6) {\n                this.workerData.OUT_MOTOR_LEFT = 0;\n                this.workerData.OUT_MOTOR_RIGHT = power;\n            }\n\n            return script.callReturn();\n        }\n\n        // Block\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        neospiderlite_get_analog_value: '아날로그 %1 센서값',\n                        neospiderlite_get_analog_value_map:\n                            '아날로그 %1 센서값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값',\n                        neospiderlite_get_ultrasonic_value: '초음파 센서값',\n                        neospiderlite_get_motion_value: '모션 센서 감지됨',\n                        neospiderlite_get_infared_value: '적외선센서 %1 감지됨',\n                        neospiderlite_set_tone: '부저를 %1 %2 음으로 %3 초 연주하기 %4',\n                        neospiderlite_set_servo:\n                            '머리방향 %1 의 각도로 정하기 (최소:50, 최대:130) %2',\n                        neospiderlite_set_servo_direction: '머리방향 %1 바라보기 %2',\n                        neospiderlite_motor_state: '네오스파이더 %1 이동하기 %2',\n                        neospiderlite_motor_state_secs: '네오스파이더 %1(으)로 %2초 이동하기 %3',\n                        neospiderlite_motor_stop: '네오스파이더 정지하기 %1',\n                        neospiderlite_neopixel_color_picker: 'RGB LED %1번  %2 (으)로 켜기 %3',\n                        neospiderlite_neopixel: 'RGB LED %1번  빨 %2 녹 %3 파 %4 (으)로 켜기 %5',\n                        neospiderlite_neopixel_color_picker_all_on:\n                            'RGB LED 전체 %1 (으)로 켜기 %2',\n                        neospiderlite_neopixel_all_on:\n                            'RGB LED 전체  빨 %1 녹 %2 파 %3 (으)로 켜기 %4',\n                        neospiderlite_neopixel_all_off: 'RGB LED 전체 끄기 %1',\n                        neospiderlite_outer_motor: '디지털 %1핀 %2 %3',\n                        neospiderlite_outer_motor_pwm: '디지털 %1핀 %2 (으)로 정하기 %3',\n                    },\n                    Device: {\n                        neospiderlite: '네오스파이더',\n                    },\n                    Menus: {\n                        neospiderlite: '네오스파이더',\n                    },\n                },\n                en: {\n                    template: {\n                        neospiderlite_get_analog_value: 'Analog %1 pin Sensor value',\n                        neospiderlite_get_analog_value_map:\n                            'Analog %1 value Map range %2 ~ %3 to %4 ~ %5',\n                        neospiderlite_get_ultrasonic_value: 'Ultrasonic Sensor value',\n                        neospiderlite_get_motion_value: 'Motion Sensor value',\n                        neospiderlite_get_infared_value: 'Infared ray %1 Sensor value',\n                        neospiderlite_set_tone: 'Play tone note %1 octave %2 beat %3 %4',\n                        neospiderlite_set_servo: 'Set head direction as %1 (min:50, max:130) %2',\n                        neospiderlite_set_servo_direction: 'Set head direction as %1 %2',\n                        neospiderlite_motor_state: 'Move neospider %1 %2',\n                        neospiderlite_motor_state_secs: 'Move neospider %1 %2 secs %3',\n                        neospiderlite_motor_stop: 'Neospider stop %1',\n                        neospiderlite_neopixel_color_picker: 'RGB LED number %1 turn on %2 %3',\n                        neospiderlite_neopixel: 'RGB LED number %1 turn on R %2 G %3 B %4 %5',\n                        neospiderlite_neopixel_color_picker_all_on: 'All RGB LED turn on %1 %2',\n                        neospiderlite_neopixel_all_on: 'All RGB LED turn on R %1 G %2 B %3 %4',\n                        neospiderlite_neopixel_all_off: 'All RGB LED turn off %1',\n                        neospiderlite_outer_motor: 'Digital %1 pin %2 %3',\n                        neospiderlite_outer_motor_pwm: 'Digital %1 pin %2 %3',\n                    },\n                    Device: {\n                        neospiderlite: 'neospiderlite',\n                    },\n                    Menus: {\n                        neospiderlite: 'NeoSpiderLite',\n                    },\n                },\n            };\n        }\n\n        getBlocks() {\n            return {\n                neospiderlite_get_analog_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['가스', 'GAS'],\n                                ['조도', 'CDS'],\n                                ['온도', 'TMP'],\n                                ['진동', 'VIBE'],\n                                ['외부', 'OUTER'],\n                            ],\n                            value: 'GAS',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neospiderlite_get_analog_value',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'NeoSpiderLiteGet',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.getAnalogValue(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.analogRead(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['가스', 'GAS'],\n                                            ['조도', 'CDS'],\n                                            ['온도', 'TMP'],\n                                            ['진동', 'VIBE'],\n                                            ['외부', 'OUTER'],\n                                        ],\n                                        value: 'GAS',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueLowerCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_get_analog_value_map: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['가스', 'GAS'],\n                                ['조도', 'CDS'],\n                                ['온도', 'TMP'],\n                                ['진동', 'VIBE'],\n                                ['외부', 'OUTER'],\n                            ],\n                            value: 'GAS',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['1023'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                        ],\n                        type: 'neospiderlite_get_analog_value_map',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        MINV: 1,\n                        MAXV: 2,\n                        TMIN: 3,\n                        TMAX: 4,\n                    },\n                    class: 'NeoSpiderLiteGet',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.getAnalogMapValue(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.mapAnalog(%1, %2, %3, %4, %5)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['가스', 'GAS'],\n                                            ['조도', 'CDS'],\n                                            ['온도', 'TMP'],\n                                            ['진동', 'VIBE'],\n                                            ['외부', 'OUTER'],\n                                        ],\n                                        value: 'GAS',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueLowerCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_get_ultrasonic_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'neospiderlite_get_ultrasonic_value',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoSpiderLiteGet',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.getUltrasonic();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.getUltrasonic()',\n                                blockType: 'param',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_get_motion_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'neospiderlite_get_motion_value',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoSpiderLiteGet',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.getMotion();\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.getMotionValue()',\n                                blockType: 'param',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_get_infared_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['왼쪽', 'LEFT_INFARED'],\n                                ['오른쪽', 'RIGHT_INFARED'],\n                            ],\n                            value: 'LEFT_INFARED',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neospiderlite_get_infared_value',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'NeoSpiderLiteGet',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.getInfared(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.getInfaredValue(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['왼쪽', 'LEFT_INFARED'],\n                                            ['오른쪽', 'RIGHT_INFARED'],\n                                        ],\n                                        value: 'LEFT_INFARED',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueLowerCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_tone_list: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.silent, '0'],\n                                [Lang.Blocks.do_name, 'C'],\n                                [Lang.Blocks.do_sharp_name, 'CS'],\n                                [Lang.Blocks.re_name, 'D'],\n                                [Lang.Blocks.re_sharp_name, 'DS'],\n                                [Lang.Blocks.mi_name, 'E'],\n                                [Lang.Blocks.fa_name, 'F'],\n                                [Lang.Blocks.fa_sharp_name, 'FS'],\n                                [Lang.Blocks.sol_name, 'G'],\n                                [Lang.Blocks.sol_sharp_name, 'GS'],\n                                [Lang.Blocks.la_name, 'A'],\n                                [Lang.Blocks.la_sharp_name, 'AS'],\n                                [Lang.Blocks.si_name, 'B'],\n                            ],\n                            value: 'C',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getField('NOTE');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.silent, '0'],\n                                            [Lang.Blocks.do_name, 'C'],\n                                            [Lang.Blocks.do_sharp_name, 'CS'],\n                                            [Lang.Blocks.re_name, 'D'],\n                                            [Lang.Blocks.re_sharp_name, 'DS'],\n                                            [Lang.Blocks.mi_name, 'E'],\n                                            [Lang.Blocks.fa_name, 'F'],\n                                            [Lang.Blocks.fa_sharp_name, 'FS'],\n                                            [Lang.Blocks.sol_name, 'G'],\n                                            [Lang.Blocks.sol_sharp_name, 'GS'],\n                                            [Lang.Blocks.la_name, 'A'],\n                                            [Lang.Blocks.la_sharp_name, 'AS'],\n                                            [Lang.Blocks.si_name, 'B'],\n                                        ],\n                                        value: 'C',\n                                        fontSize: 11,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    },\n                                ],\n                                keyOption: 'neospiderlite_tone_list',\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_tone_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'neospiderlite_tone_list',\n                            },\n                        ],\n                        type: 'neospiderlite_tone_value',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getNumberValue('NOTE');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                keyOption: 'neospiderlite_tone_value',\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_octave_list: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    template: '%1',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        OCTAVE: 0,\n                    },\n                    func(sprite, script) {\n                        return script.getField('OCTAVE');\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: '%1',\n                                keyOption: 'neospiderlite_octave_list',\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_set_tone: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'neospiderlite_tone_list',\n                            },\n                            {\n                                type: 'neospiderlite_octave_list',\n                            },\n                            {\n                                type: 'text',\n                                params: ['1'],\n                            },\n                            null,\n                        ],\n                        type: 'neospiderlite_set_tone',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                        OCTAVE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setTone(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.tone(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_set_servo: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [90],\n                        type: 'neospiderlite_set_servo',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setServo(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.servomotorWrite(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_set_servo_direction: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['앞', '90'],\n                                ['왼쪽', '50'],\n                                ['오른쪽', '130'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neospiderlite_set_servo_direction',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setServo(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.servomotorWrite(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_motor_state: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['앞으로', 1],\n                                ['왼쪽으로', 2],\n                                ['오른쪽으로', 3],\n                                ['뒤로', 4],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neospiderlite_motor_state',\n                    },\n                    paramsKeyMap: {\n                        STATE: 0,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setMotor(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.motorState(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['앞으로', '1'],\n                                            ['왼쪽으로', '2'],\n                                            ['오른쪽으로', '3'],\n                                            ['뒤로', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_motor_state_secs: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['앞으로', 1],\n                                ['왼쪽으로', 2],\n                                ['오른쪽으로', 3],\n                                ['뒤로', 4],\n                            ],\n                            value: 1,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'text',\n                                params: ['1'],\n                            },\n                        ],\n                        type: 'neospiderlite_motor_state_secs',\n                    },\n                    paramsKeyMap: {\n                        STATE: 0,\n                        DURATION: 1,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setMotorSecs(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.motorStateSecs(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['앞으로', '1'],\n                                            ['왼쪽으로', '2'],\n                                            ['오른쪽으로', '3'],\n                                            ['뒤로', '4'],\n                                        ],\n                                        value: '1',\n                                        fontSize: 11,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter:\n                                            Entry.block.converters.returnStringValueUpperCase,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_motor_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neospiderlite_motor_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setMotorStop(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.motorStop()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_neopixel: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            null,\n                        ],\n                        type: 'neospiderlite_neopixel',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        RED: 1,\n                        GREEN: 2,\n                        BLUE: 3,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setNeopixel(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.neopixel(%1, %2, %3, %4)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_neopixel_color_picker: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'neospiderlite_neopixel_color_picker',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                        COLOR: 1,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setNeopixelPicker(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.neopixelColorPicker(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Color',\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_neopixel_color_picker_all_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Color',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neospiderlite_neopixel_color_picker_all_on',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setAllNeopixelPicker(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.neopixelColorPickerAllOn(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Color',\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_neopixel_all_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            null,\n                        ],\n                        type: 'neospiderlite_neopixel_all_on',\n                    },\n                    paramsKeyMap: {\n                        RED: 0,\n                        GREEN: 1,\n                        BLUE: 2,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setAllNeopixel(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.neopixelAllON(%1, %2, %3)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_neopixel_all_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neospiderlite_neopixel_all_off',\n                    },\n                    paramsKeyMap: {},\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setNeopixelOff(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.neopixelAllOFF()',\n                                textParams: [],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_outer_motor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['5', '5'],\n                                ['6', '6'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['LOW', '0'],\n                                ['HIGH', '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [5, null],\n                        type: 'neospiderlite_outer_motor',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        STATE: 1,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setOuterMotor(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.outerDigitalPin(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                        ],\n                                        value: '5',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['LOW', '0'],\n                                            ['HIGH', '1'],\n                                        ],\n                                        value: '0',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n                neospiderlite_outer_motor_pwm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['5', '5'],\n                                ['6', '6'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [5, null],\n                        type: 'neospiderlite_outer_motor_pwm',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                    },\n                    class: 'NeoSpiderLite',\n                    isNotFor: ['NeoSpiderLite'],\n                    func(sprite, script) {\n                        return Entry.NeoSpiderLite.setOuterMotorPWM(script);\n                    },\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'NeoSpiderLite.outerDigitalPinPWM(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            ['5', '5'],\n                                            ['6', '6'],\n                                        ],\n                                        value: '5',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                },\n            };\n        }\n    })();\n})();\n\nmodule.exports = Entry.NeoSpiderLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_neobot_purple_lite.js",
    "content": "'use strict';\n(function() {\n    const HEADER = [0xab, 0xcd];\n    Entry.NeobotPurpleLite = new (class NeobotPurpleLite {\n        constructor() {\n            this.id = '050501';\n            this.name = 'NeobotPurpleLite';\n            this.url = 'http://neobot.co.kr/';\n            this.imageName = 'neobot_purple_lite.png';\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n            };\n            this.duration = 100;\n            this.LOCAL_MAP = ['IN1', 'IN2', 'IN3', 'IR', 'BAT'];\n            this.localBuffer = {\n                IN1: 0,\n                IN2: 0,\n                IN3: 0,\n                IR: 0,\n                BAT: 0,\n            };\n            this.remoteBuffer = {\n                OUT1: 0,\n                OUT2: 0,\n                OUT3: 0,\n                DCL: 0,\n                DCR: 0,\n                SND: 0,\n                FND: 0,\n                OPT: 0,\n            };\n            this.log_to_console = false;\n\n            this.blockMenuBlocks = [\n                // sensor\n                'neobot_purple_lite_sensor_title',\n                'neobot_purple_lite_sensor_value',\n                'neobot_purple_lite_sensor_convert_scale',\n                'neobot_purple_lite_decision_sensor_is_over',\n                'neobot_purple_lite_decision_equal_with_sensor',\n                'neobot_purple_lite_decision_sensor_angle',\n                'neobot_purple_lite_remote_button',\n\n                // led\n                'neobot_purple_lite_led_title',\n                'neobot_purple_lite_led_on',\n                'neobot_purple_lite_led_brightness_with_sensor',\n                'neobot_purple_lite_color_led_on',\n                'neobot_purple_lite_output_led_off',\n\n                // output\n                'neobot_purple_lite_output_title',\n                'neobot_purple_lite_set_output',\n\n                //  motor\n                'neobot_purple_lite_motor_title',\n                'neobot_purple_lite_robot',\n                'neobot_purple_lite_motor_start',\n                'neobot_purple_lite_motor_stop',\n\n                // servo\n                'neobot_purple_lite_servo_title',\n                'neobot_purple_lite_servo_init',\n                'neobot_purple_lite_servo_rotate',\n                'neobot_purple_lite_servo_stop',\n                'neobot_purple_lite_servo_change_degree',\n\n                // melody\n                'neobot_purple_lite_buzzer_title',\n                'neobot_purple_lite_play_note_for',\n                'neobot_purple_lite_melody_play_with_sensor',\n                'neobot_purple_lite_melody_stop',\n            ];\n\n            this.setZero();\n        }\n\n        get monitorTemplate() {\n            return {\n                imgPath: 'hw/neobot_purple.png',\n                width: 700,\n                height: 700,\n                listPorts: {\n                    IR: { name: '리모컨', type: 'input', pos: { x: 0, y: 0 } },\n                    BAT: { name: '배터리', type: 'input', pos: { x: 0, y: 0 } },\n                    SND: {\n                        name: Lang.Hw.buzzer,\n                        type: 'output',\n                        pos: { x: 0, y: 0 },\n                    },\n                    FND: { name: 'FND', type: 'output', pos: { x: 0, y: 0 } },\n                },\n                ports: {\n                    IN1: {\n                        name: 'IN1',\n                        type: 'input',\n                        pos: { x: 270, y: 200 },\n                    },\n                    IN2: {\n                        name: 'IN2',\n                        type: 'input',\n                        pos: { x: 325, y: 200 },\n                    },\n                    IN3: {\n                        name: 'IN3',\n                        type: 'input',\n                        pos: { x: 325, y: 500 },\n                    },\n                    DCL: {\n                        name: 'L-Motor',\n                        type: 'output',\n                        pos: { x: 270, y: 500 },\n                    },\n                    DCR: {\n                        name: 'R-Motor',\n                        type: 'output',\n                        pos: { x: 435, y: 500 },\n                    },\n                    OUT1: {\n                        name: 'OUT1',\n                        type: 'output',\n                        pos: { x: 380, y: 200 },\n                    },\n                    OUT2: {\n                        name: 'OUT2',\n                        type: 'output',\n                        pos: { x: 435, y: 200 },\n                    },\n                    OUT3: {\n                        name: 'OUT3',\n                        type: 'output',\n                        pos: { x: 380, y: 500 },\n                    },\n                },\n                mode: 'both',\n            };\n        }\n\n        getMonitorPort() {\n            return { ...this.localBuffer, ...this.remoteBuffer };\n        }\n\n        setZero() {\n            this.remoteBuffer = {\n                OUT1: 0,\n                OUT2: 0,\n                OUT3: 0,\n                DCL: 0,\n                DCR: 0,\n                SND: 0,\n                FND: 0,\n                OPT: 0,\n            };\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        handleLocalData(data) {\n            let validPdu = this.getValidPdu(data);\n            while (validPdu) {\n                this.onReceivePdu(validPdu);\n                if (!this.remainingPdu || this.remainingPdu.length <= 0) {\n                    break;\n                }\n                validPdu = this.getValidPdu([]);\n            }\n        }\n\n        onReceivePdu(pdu) {\n            if (pdu[0] === HEADER[0] && pdu[1] === HEADER[1]) {\n                this.localBuffer['IN1'] = pdu[2];\n                this.localBuffer['IN2'] = pdu[3];\n                this.localBuffer['IN3'] = pdu[4];\n                this.localBuffer['IR'] = pdu[5];\n                this.localBuffer['BAT'] = pdu[6];\n            }\n        }\n\n        getValidPdu(pdu) {\n            const mergedPdu = [];\n            if (this.remainingPdu) {\n                mergedPdu.push(...this.remainingPdu);\n                this.remainingPdu = null;\n            }\n            mergedPdu.push(...pdu);\n            if (mergedPdu.length < 2) {\n                this.remainingPdu = [...mergedPdu];\n                return null;\n            }\n\n            // 헤더 불일치는 버림\n            if (!this.checkHeader(mergedPdu)) {\n                return null;\n            }\n\n            // 유효 데이터 길이는 header 2 + body 5 + checksum 1 = 8\n            const validDataLength = 8;\n            /*\n            전체 길이가 유효 데이터 길이보다 작을 경우\n            아직 도착하지 않은 부분이 있으므로 병합을 위해 remainingPdu 에 저장\n             */\n            if (mergedPdu.length < validDataLength) {\n                this.remainingPdu = [...mergedPdu];\n                return null;\n            }\n\n            /*\n            전체 길이가 유효 데이터 길이보다 클 경우\n            유효한 부분만 잘라내고 나머지는 remainingPdu 에 저장\n             */\n            if (mergedPdu.length > validDataLength) {\n                this.remainingPdu = mergedPdu.slice(validDataLength, mergedPdu.length);\n            }\n\n            const validPdu = mergedPdu.slice(0, validDataLength);\n\n            /*\n            유효 Pdu 의 checksum 확인\n             */\n            const dataLength = 5;\n            let checkSum = 0;\n            for (let i = 0; i < dataLength; i++) {\n                checkSum += validPdu[i + 2];\n            }\n            checkSum = checkSum & 255;\n            const pduCheckSum = validPdu[7];\n            if (pduCheckSum !== checkSum) {\n                return null;\n            }\n\n            return validPdu;\n        }\n\n        checkHeader(pdu) {\n            if (pdu.length < HEADER.length) {\n                return false;\n            }\n\n            for (let i = 0; i < HEADER.length; i++) {\n                if (HEADER[i] !== pdu[i]) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        requestLocalData() {\n            const requestData = [];\n\n            // 시작 바이트\n            requestData.push(0xcd);\n            requestData.push(0xab);\n\n            let checksum = 0;\n            let isFnd = false;\n            Object.keys(this.remoteBuffer).forEach((key, idx) => {\n                let value = this.remoteBuffer[key];\n                if (idx === 6 && value > 0) {\n                    isFnd = true;\n                } else if (idx === 7 && isFnd) {\n                    value = value | 8;\n                }\n                requestData.push(value);\n                checksum += value;\n            });\n\n            checksum = checksum & 255;\n            //체크썸\n            requestData.push(checksum);\n            return requestData;\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // sensor\n                        neobot_purple_lite_sensor_title: '센서',\n                        neobot_purple_lite_sensor_value: '%1',\n                        neobot_purple_lite_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환',\n                        neobot_purple_lite_decision_sensor_is_over: '%1 %2 %3',\n                        neobot_purple_lite_decision_equal_with_sensor: '%1 컬러가 %2',\n                        neobot_purple_lite_decision_sensor_angle: '%1 각도 %2 %3',\n                        neobot_purple_lite_remote_button: '리모컨 버튼 %1 을 누름',\n\n                        // LED\n                        neobot_purple_lite_led_title: 'LED',\n                        neobot_purple_lite_arg_led_duration: '%1',\n                        neobot_purple_lite_led_on: 'LED 켜기   %1 %2 %3 %4',\n                        neobot_purple_lite_output_led_off: '%1 LED 끄기 %2',\n                        neobot_purple_lite_led_brightness_with_sensor: '%1 로 %2 LED 제어 %3',\n                        neobot_purple_lite_color_led_on: '%1 컬러LED 켜기   R %2 G %3 B %4 %5',\n\n                        // output\n                        neobot_purple_lite_output_title: '출력',\n                        neobot_purple_lite_set_output: '%1 에 %2 값 출력하기 %3',\n\n                        // motor\n                        neobot_purple_lite_motor_title: '회전모터',\n                        neobot_purple_lite_robot: '로봇 %1 %2',\n                        neobot_purple_lite_motor_start: '모터 회전하기   %1 %2 %3 %4 %5',\n                        neobot_purple_lite_motor_stop: '%1 모터 멈추기 %2',\n                        neobot_purple_lite_arg_motor_speed: '%1',\n                        neobot_purple_lite_arg_motor_duration: '%1',\n\n                        // melody\n                        neobot_purple_lite_buzzer_title: '버저',\n                        neobot_purple_lite_play_note_for:\n                            '버저 울리기   옥타브: %2 음: %1 길이: %3 %4',\n                        neobot_purple_lite_melody_play_with_sensor: '%1 센서로 버저 울리기 %2',\n                        neobot_purple_lite_melody_stop: '버저 멈추기 %1',\n\n                        // servo\n                        neobot_purple_lite_servo_title: '서보모터',\n                        get_servo_degree: '%1',\n                        neobot_purple_lite_servo_init: '%1 서보모터 리셋 %2',\n                        neobot_purple_lite_servo_rotate: '서보모터 회전하기   %1 %2 %3 %4',\n                        neobot_purple_lite_servo_stop: '%1 서보모터 멈추기 %2',\n                        neobot_purple_lite_servo_change_degree:\n                            '서보모터 각도 바꾸기   %2 %3 %4 %1 %5',\n                    },\n                    Blocks: {\n                        //for dropdown\n                        neobot_purple_lite_port_1: 'IN1',\n                        neobot_purple_lite_port_2: 'IN2',\n                        neobot_purple_lite_port_3: 'IN3',\n                        neobot_purple_lite_port_4: 'IN4',\n                        neobot_purple_lite_port_12: 'IN1 & IN2',\n                        neobot_purple_lite_port_bat: '배터리',\n                        neobot_purple_lite_port_remot: '리모컨',\n                        neobot_purple_lite_color_white: '흰색',\n                        neobot_purple_lite_color_red: '빨강',\n                        neobot_purple_lite_color_yellow: '노랑',\n                        neobot_purple_lite_color_green: '녹색',\n                        neobot_purple_lite_color_blue: '파랑',\n                        neobot_purple_lite_direction_forward: '앞으로',\n                        neobot_purple_lite_direction_backward: '뒤로',\n                        neobot_purple_lite_sound_silent: '무음',\n                        neobot_purple_lite_sound_do: '도',\n                        neobot_purple_lite_sound_do_shop: '도#',\n                        neobot_purple_lite_sound_re: '레',\n                        neobot_purple_lite_sound_re_shop: '레#',\n                        neobot_purple_lite_sound_mi: '미',\n                        neobot_purple_lite_sound_fa: '파',\n                        neobot_purple_lite_sound_fa_shop: '파#',\n                        neobot_purple_lite_sound_so: '솔',\n                        neobot_purple_lite_sound_so_shop: '솔#',\n                        neobot_purple_lite_sound_la: '라',\n                        neobot_purple_lite_sound_la_shop: '라#',\n                        neobot_purple_lite_sound_ti: '시',\n                        neobot_purple_lite_sound_half_note: '2분 음표',\n                        neobot_purple_lite_sound_quarter_note: '4분 음표',\n                        neobot_purple_lite_sound_eighth_note: '8분 음표',\n                        neobot_purple_lite_sound_sixteenth_note: '16분 음표',\n                        neobot_purple_lite_sensor_infrared: '적외선센서',\n                        neobot_purple_lite_sensor_light: '빛센서',\n                        neobot_purple_lite_sensor_sound: '소리센서',\n                        neobot_purple_lite_compare_symbol1: '＝',\n                        neobot_purple_lite_compare_symbol2: '＞',\n                        neobot_purple_lite_compare_symbol3: '＜',\n                        neobot_purple_lite_compare_symbol4: '≥',\n                        neobot_purple_lite_compare_symbol5: '≤',\n                        neobot_purple_lite_remote_btn_a: 'A',\n                        neobot_purple_lite_remote_btn_b: 'B',\n                        neobot_purple_lite_remote_btn_c: 'C',\n                        neobot_purple_lite_remote_btn_d: 'D',\n                        neobot_purple_lite_remote_btn_1: '1',\n                        neobot_purple_lite_remote_btn_2: '2',\n                        neobot_purple_lite_remote_btn_3: '3',\n                        neobot_purple_lite_remote_btn_4: '4',\n                        neobot_purple_lite_remote_btn_up: '▲',\n                        neobot_purple_lite_remote_btn_down: '▼',\n                        neobot_purple_lite_remote_btn_left: '◀',\n                        neobot_purple_lite_remote_btn_right: '▶',\n                        neobot_purple_lite_duration_cont: '계속',\n                        neobot_purple_lite_duration_1s: '1초',\n                        neobot_purple_lite_duration_2s: '2초',\n                        neobot_purple_lite_duration_3s: '3초',\n                        neobot_purple_lite_duration_4s: '4초',\n                        neobot_purple_lite_duration_5s: '5초',\n                        neobot_purple_lite_duration_6s: '6초',\n                        neobot_purple_lite_duration_7s: '7초',\n                        neobot_purple_lite_duration_8s: '8초',\n                        neobot_purple_lite_duration_9s: '9초',\n                        neobot_purple_lite_motor_both: '양쪽',\n                        neobot_purple_lite_motor_left: '왼쪽',\n                        neobot_purple_lite_motor_right: '오른쪽',\n                        neobot_purple_lite_motor_move_forward: '전진',\n                        neobot_purple_lite_motor_move_backward: '후진',\n                        neobot_purple_lite_motor_move_left: '좌회전',\n                        neobot_purple_lite_motor_move_right: '우회전',\n                        neobot_purple_lite_motor_move_stop: '정지',\n\n                        neobot_purple_lite_servo_dir_1: '정방향',\n                        neobot_purple_lite_servo_dir_2: '역방향',\n\n                        neobot_purple_lite_percent_10: '10%속도',\n                        neobot_purple_lite_percent_20: '20%속도',\n                        neobot_purple_lite_percent_30: '30%속도',\n                        neobot_purple_lite_percent_40: '40%속도',\n                        neobot_purple_lite_percent_50: '50%속도',\n                        neobot_purple_lite_percent_60: '60%속도',\n                        neobot_purple_lite_percent_70: '70%속도',\n                        neobot_purple_lite_percent_80: '80%속도',\n                        neobot_purple_lite_percent_90: '90%속도',\n                        neobot_purple_lite_percent_100: '100%속도',\n\n                        neobot_purple_lite_angle_0: '0도',\n                        neobot_purple_lite_angle_5: '5도',\n                        neobot_purple_lite_angle_10: '10도',\n                        neobot_purple_lite_angle_15: '15도',\n                        neobot_purple_lite_angle_20: '20도',\n                        neobot_purple_lite_angle_25: '25도',\n                        neobot_purple_lite_angle_30: '30도',\n                        neobot_purple_lite_angle_35: '35도',\n                        neobot_purple_lite_angle_40: '40도',\n                        neobot_purple_lite_angle_45: '45도',\n                        neobot_purple_lite_angle_50: '50도',\n                        neobot_purple_lite_angle_55: '55도',\n                        neobot_purple_lite_angle_60: '60도',\n                        neobot_purple_lite_angle_65: '65도',\n                        neobot_purple_lite_angle_70: '70도',\n                        neobot_purple_lite_angle_75: '75도',\n                        neobot_purple_lite_angle_80: '80도',\n                        neobot_purple_lite_angle_85: '85도',\n                        neobot_purple_lite_angle_90: '90도',\n                        neobot_purple_lite_angle_95: '95도',\n                        neobot_purple_lite_angle_100: '100도',\n                        neobot_purple_lite_angle_105: '105도',\n                        neobot_purple_lite_angle_110: '110도',\n                        neobot_purple_lite_angle_115: '115도',\n                        neobot_purple_lite_angle_120: '120도',\n                        neobot_purple_lite_angle_125: '125도',\n                        neobot_purple_lite_angle_130: '130도',\n                        neobot_purple_lite_angle_135: '135도',\n                        neobot_purple_lite_angle_140: '140도',\n                        neobot_purple_lite_angle_145: '145도',\n                        neobot_purple_lite_angle_150: '150도',\n                        neobot_purple_lite_angle_155: '155도',\n                        neobot_purple_lite_angle_160: '160도',\n                        neobot_purple_lite_angle_165: '165도',\n                        neobot_purple_lite_angle_170: '170도',\n                        neobot_purple_lite_angle_175: '175도',\n                        neobot_purple_lite_angle_180: '180도',\n\n                        neobot_purple_lite_out_all: '모든',\n                        neobot_purple_lite_direction_left: '왼쪽으로',\n                        neobot_purple_lite_direction_right: '오른쪽으로',\n                    },\n                },\n                en: {\n                    // en.js에 작성하던 내용\n                    template: {\n                        // sensor\n                        neobot_purple_lite_sensor_title: 'Sensor',\n                        neobot_purple_lite_sensor_value: '%1',\n                        neobot_purple_lite_sensor_convert_scale:\n                            \"%1 's changed value   range: %2 ~ %3 conversion: %4 ~ %5\",\n                        neobot_purple_lite_decision_sensor_is_over: '%1 %2 %3',\n                        neobot_purple_lite_decision_equal_with_sensor: \"%1 's color is %2\",\n                        neobot_purple_lite_decision_sensor_angle: '%1 angle %2 %3',\n                        neobot_purple_lite_remote_button: 'pressing button %1 of remote controller',\n\n                        // LED\n                        neobot_purple_lite_led_title: 'LED',\n                        neobot_purple_lite_arg_led_duration: '%1',\n                        neobot_purple_lite_led_on: 'Turn on the LED    %1 %2 %3 %4',\n                        neobot_purple_lite_output_led_off: 'Turn off the %1 LED %2',\n                        neobot_purple_lite_led_brightness_with_sensor:\n                            \"Control %2 LED's brightness with %1 sensor %3\",\n                        neobot_purple_lite_color_led_on:\n                            'Turn on the %1 color LED   R %2 G %3 B %4 %5',\n\n                        // output\n                        neobot_purple_lite_output_title: 'Set output',\n                        neobot_purple_lite_set_output: 'Output %2 value to %1 port %3',\n\n                        // motor\n                        neobot_purple_lite_motor_title: 'Motor',\n                        neobot_purple_lite_robot: 'Robot %1 %2',\n                        neobot_purple_lite_motor_start: 'Motor operation   %1 %2 %3 %4 %5',\n                        neobot_purple_lite_motor_stop: 'Stop the %1 motor(s) %2',\n                        neobot_purple_lite_arg_motor_speed: '%1',\n                        neobot_purple_lite_arg_motor_duration: '%1',\n\n                        // melody\n                        neobot_purple_lite_buzzer_title: 'Buzzer',\n                        neobot_purple_lite_play_note_for:\n                            'Buzzer   octave: %1 scale: %2 note: %3 %4',\n                        neobot_purple_lite_melody_play_with_sensor:\n                            'Buzzer rings by %1 sensor value %2',\n                        neobot_purple_lite_melody_stop: 'Stop the buzzer %1',\n\n                        // servo\n                        neobot_purple_lite_servo_title: 'Servo motor',\n                        neobot_purple_lite_servo_init: 'Reset the %1 servo motor %2',\n                        neobot_purple_lite_servo_rotate: 'Rotate the servo motor   %1 %2 %3 %4',\n                        neobot_purple_lite_servo_stop: 'Stop the %1 servo motor %2',\n                        neobot_purple_lite_servo_change_degree:\n                            'Change servo angle   %1 %2 %3 %4 %5',\n                    },\n                    Blocks: {\n                        //for dropdown\n                        neobot_purple_lite_port_1: 'IN1',\n                        neobot_purple_lite_port_2: 'IN2',\n                        neobot_purple_lite_port_3: 'IN3',\n                        neobot_purple_lite_port_4: 'IN4',\n                        neobot_purple_lite_port_12: 'IN1 & IN2',\n                        neobot_purple_lite_port_bat: 'battery',\n                        neobot_purple_lite_port_remot: 'remote',\n                        neobot_purple_lite_color_white: 'white',\n                        neobot_purple_lite_color_red: 'red',\n                        neobot_purple_lite_color_yellow: 'yellow',\n                        neobot_purple_lite_color_green: 'green',\n                        neobot_purple_lite_color_blue: 'blue',\n                        neobot_purple_lite_direction_forward: 'forward',\n                        neobot_purple_lite_direction_backward: 'backward',\n                        neobot_purple_lite_sound_silent: 'silent',\n                        neobot_purple_lite_sound_do: 'Do',\n                        neobot_purple_lite_sound_do_shop: 'Do#',\n                        neobot_purple_lite_sound_re: 'Re',\n                        neobot_purple_lite_sound_re_shop: 'Re#',\n                        neobot_purple_lite_sound_mi: 'Mi',\n                        neobot_purple_lite_sound_fa: 'Fa',\n                        neobot_purple_lite_sound_fa_shop: 'Fa#',\n                        neobot_purple_lite_sound_so: 'So',\n                        neobot_purple_lite_sound_so_shop: 'So#',\n                        neobot_purple_lite_sound_la: 'La',\n                        neobot_purple_lite_sound_la_shop: 'La#',\n                        neobot_purple_lite_sound_ti: 'Si',\n                        neobot_purple_lite_sound_half_note: 'a half note',\n                        neobot_purple_lite_sound_quarter_note: 'a quarter note',\n                        neobot_purple_lite_sound_eighth_note: 'a eighth note',\n                        neobot_purple_lite_sound_sixteenth_note: 'a sixteenth note',\n                        neobot_purple_lite_sensor_infrared: 'IR sensor',\n                        neobot_purple_lite_sensor_light: 'light sensor',\n                        neobot_purple_lite_sensor_sound: 'sound sensor',\n                        neobot_purple_lite_compare_symbol1: '＝',\n                        neobot_purple_lite_compare_symbol2: '＞',\n                        neobot_purple_lite_compare_symbol3: '＜',\n                        neobot_purple_lite_compare_symbol4: '≥',\n                        neobot_purple_lite_compare_symbol5: '≤',\n                        neobot_purple_lite_remote_btn_a: 'A',\n                        neobot_purple_lite_remote_btn_b: 'B',\n                        neobot_purple_lite_remote_btn_c: 'C',\n                        neobot_purple_lite_remote_btn_d: 'D',\n                        neobot_purple_lite_remote_btn_1: '1',\n                        neobot_purple_lite_remote_btn_2: '2',\n                        neobot_purple_lite_remote_btn_3: '3',\n                        neobot_purple_lite_remote_btn_4: '4',\n                        neobot_purple_lite_remote_btn_up: '▲',\n                        neobot_purple_lite_remote_btn_down: '▼',\n                        neobot_purple_lite_remote_btn_left: '◀',\n                        neobot_purple_lite_remote_btn_right: '▶',\n                        neobot_purple_lite_duration_cont: 'constantly',\n                        neobot_purple_lite_duration_1s: '1 second',\n                        neobot_purple_lite_duration_2s: '2 seconds',\n                        neobot_purple_lite_duration_3s: '3 seconds',\n                        neobot_purple_lite_duration_4s: '4 seconds',\n                        neobot_purple_lite_duration_5s: '5 seconds',\n                        neobot_purple_lite_duration_6s: '6 seconds',\n                        neobot_purple_lite_duration_7s: '7 seconds',\n                        neobot_purple_lite_duration_8s: '8 seconds',\n                        neobot_purple_lite_duration_9s: '9 seconds',\n                        neobot_purple_lite_motor_both: 'both',\n                        neobot_purple_lite_motor_left: 'left',\n                        neobot_purple_lite_motor_right: 'right',\n                        neobot_purple_lite_motor_move_forward: 'go forward',\n                        neobot_purple_lite_motor_move_backward: 'go backward',\n                        neobot_purple_lite_motor_move_left: 'turn Left',\n                        neobot_purple_lite_motor_move_right: 'turn Right',\n                        neobot_purple_lite_motor_move_stop: 'stop',\n\n                        neobot_purple_lite_servo_dir_1: 'forward',\n                        neobot_purple_lite_servo_dir_2: 'backward',\n\n                        neobot_purple_lite_percent_10: '10% speed',\n                        neobot_purple_lite_percent_20: '20% speed',\n                        neobot_purple_lite_percent_30: '30% speed',\n                        neobot_purple_lite_percent_40: '40% speed',\n                        neobot_purple_lite_percent_50: '50% speed',\n                        neobot_purple_lite_percent_60: '60% speed',\n                        neobot_purple_lite_percent_70: '70% speed',\n                        neobot_purple_lite_percent_80: '80% speed',\n                        neobot_purple_lite_percent_90: '90% speed',\n                        neobot_purple_lite_percent_100: '100% speed',\n\n                        neobot_purple_lite_angle_0: '0 degree',\n                        neobot_purple_lite_angle_5: '5 degrees',\n                        neobot_purple_lite_angle_10: '10 degrees',\n                        neobot_purple_lite_angle_15: '15 degrees',\n                        neobot_purple_lite_angle_20: '20 degrees',\n                        neobot_purple_lite_angle_25: '25 degrees',\n                        neobot_purple_lite_angle_30: '30 degrees',\n                        neobot_purple_lite_angle_35: '35 degrees',\n                        neobot_purple_lite_angle_40: '40 degrees',\n                        neobot_purple_lite_angle_45: '45 degrees',\n                        neobot_purple_lite_angle_50: '50 degrees',\n                        neobot_purple_lite_angle_55: '55 degrees',\n                        neobot_purple_lite_angle_60: '60 degrees',\n                        neobot_purple_lite_angle_65: '65 degrees',\n                        neobot_purple_lite_angle_70: '70 degrees',\n                        neobot_purple_lite_angle_75: '75 degrees',\n                        neobot_purple_lite_angle_80: '80 degrees',\n                        neobot_purple_lite_angle_85: '85 degrees',\n                        neobot_purple_lite_angle_90: '90 degrees',\n                        neobot_purple_lite_angle_95: '95 degrees',\n                        neobot_purple_lite_angle_100: '100 degrees',\n                        neobot_purple_lite_angle_105: '105 degrees',\n                        neobot_purple_lite_angle_110: '110 degrees',\n                        neobot_purple_lite_angle_115: '115 degrees',\n                        neobot_purple_lite_angle_120: '120 degrees',\n                        neobot_purple_lite_angle_125: '125 degrees',\n                        neobot_purple_lite_angle_130: '130 degrees',\n                        neobot_purple_lite_angle_135: '135 degrees',\n                        neobot_purple_lite_angle_140: '140 degrees',\n                        neobot_purple_lite_angle_145: '145 degrees',\n                        neobot_purple_lite_angle_150: '150 degrees',\n                        neobot_purple_lite_angle_155: '155 degrees',\n                        neobot_purple_lite_angle_160: '160 degrees',\n                        neobot_purple_lite_angle_165: '165 degrees',\n                        neobot_purple_lite_angle_170: '170 degrees',\n                        neobot_purple_lite_angle_175: '175 degrees',\n                        neobot_purple_lite_angle_180: '180degrees',\n\n                        neobot_purple_lite_out_all: 'ALL',\n                        neobot_purple_lite_direction_left: 'to the left',\n                        neobot_purple_lite_direction_right: 'to the right',\n                    },\n                }, //\n            };\n        }\n\n        getBlocks = function() {\n            return {\n                /*************************\n                 * class neobot_purple_lite_sensor\n                 *************************/\n                neobot_purple_lite_sensor_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_purple_lite_sensor_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_purple_lite_sensor_title',\n                    },\n                    class: 'neobot_purple_lite_sensor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    events: {},\n                },\n                neobot_purple_lite_sensor_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_purple_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_purple_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_purple_lite_port_remot, 'IR'],\n                                [Lang.Blocks.neobot_purple_lite_port_bat, 'BAT'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_purple_lite_sensor_value',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_purple_lite_sensor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT');\n                        return Entry.NeobotPurpleLite.localBuffer[port];\n                    },\n                },\n\n                neobot_purple_lite_sensor_convert_scale: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_purple_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_purple_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                        ],\n                        type: 'neobot_purple_lite_sensor_convert_scale',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        OMIN: 1,\n                        OMAX: 2,\n                        MIN: 3,\n                        MAX: 4,\n                    },\n                    class: 'neobot_purple_lite_sensor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT');\n                        let value = Entry.NeobotPurpleLite.localBuffer[port];\n                        let omin = script.getNumberValue('OMIN', script);\n                        let omax = script.getNumberValue('OMAX', script);\n                        let min = script.getNumberValue('MIN', script);\n                        let max = script.getNumberValue('MAX', script);\n\n                        if (omin > omax) {\n                            var temp = omin;\n                            omin = omax;\n                            omax = temp;\n                        }\n\n                        if (min > max) {\n                            var temp = min;\n                            min = max;\n                            max = temp;\n                        }\n\n                        value -= omin;\n                        value = value * ((max - min) / (omax - omin));\n                        value += min;\n                        value = Math.min(max, value);\n                        value = Math.max(min, value);\n\n                        return Math.round(value);\n                    },\n                },\n                neobot_purple_lite_decision_sensor_is_over: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_purple_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_purple_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_purple_lite_port_12, 'IN12'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol1, '='],\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol2, '>'],\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol3, '<'],\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol4, '>='],\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol5, '<='],\n                            ],\n                            value: '>',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 10],\n                        type: 'neobot_purple_lite_decision_sensor_is_over',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        SYMBOL: 1,\n                        VALUE: 2,\n                    },\n                    class: 'neobot_purple_lite_sensor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const symbol = script.getStringField('SYMBOL');\n                        const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                        if (sensorTemp == 'IN12') {\n                            const sensor1 = Entry.NeobotPurpleLite.localBuffer.IN1;\n                            const sensor2 = Entry.NeobotPurpleLite.localBuffer.IN2;\n                            if (symbol == '=') {\n                                return sensor1 == value && sensor2 == value;\n                            } else if (symbol == '>') {\n                                return sensor1 > value && sensor2 > value;\n                            } else if (symbol == '<') {\n                                return sensor1 < value && sensor2 < value;\n                            } else if (symbol == '>=') {\n                                return sensor1 >= value && sensor2 >= value;\n                            } else if (symbol == '<=') {\n                                return sensor1 <= value && sensor2 <= value;\n                            }\n                        } else {\n                            const sensor = Entry.NeobotPurpleLite.localBuffer[sensorTemp];\n                            if (symbol == '=') {\n                                if (sensor == value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '>') {\n                                if (sensor > value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '<') {\n                                if (sensor < value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '>=') {\n                                if (sensor >= value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '<=') {\n                                if (sensor <= value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            }\n                        }\n                        return false;\n                    },\n                },\n\n                neobot_purple_lite_decision_equal_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_purple_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_purple_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_color_white, 0],\n                                [Lang.Blocks.neobot_purple_lite_color_red, 1],\n                                [Lang.Blocks.neobot_purple_lite_color_yellow, 2],\n                                [Lang.Blocks.neobot_purple_lite_color_green, 3],\n                                [Lang.Blocks.neobot_purple_lite_color_blue, 4],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_purple_lite_decision_equal_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        COLOR: 1,\n                    },\n                    class: 'neobot_purple_lite_sensor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const sensor = Entry.NeobotPurpleLite.localBuffer[sensorTemp];\n                        const color = script.getNumberField('COLOR');\n\n                        if (sensor >= 10 && sensor <= 50) {\n                            if (color == 0) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 51 && sensor <= 90) {\n                            if (color == 1) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 91 && sensor <= 130) {\n                            if (color == 2) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 131 && sensor <= 170) {\n                            if (color == 3) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 171 && sensor <= 210) {\n                            if (color == 4) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        }\n                        return false;\n                    },\n                },\n\n                neobot_purple_lite_decision_sensor_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#FFFFFF',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_purple_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_purple_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol1, '='],\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol2, '>'],\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol3, '<'],\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol4, '>='],\n                                [Lang.Blocks.neobot_purple_lite_compare_symbol5, '<='],\n                            ],\n                            value: '>',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_angle_0, '0'],\n                                [Lang.Blocks.neobot_purple_lite_angle_10, '10'],\n                                [Lang.Blocks.neobot_purple_lite_angle_20, '20'],\n                                [Lang.Blocks.neobot_purple_lite_angle_30, '30'],\n                                [Lang.Blocks.neobot_purple_lite_angle_40, '40'],\n                                [Lang.Blocks.neobot_purple_lite_angle_50, '50'],\n                                [Lang.Blocks.neobot_purple_lite_angle_60, '60'],\n                                [Lang.Blocks.neobot_purple_lite_angle_70, '70'],\n                                [Lang.Blocks.neobot_purple_lite_angle_80, '80'],\n                                [Lang.Blocks.neobot_purple_lite_angle_90, '90'],\n                                [Lang.Blocks.neobot_purple_lite_angle_100, '100'],\n                                [Lang.Blocks.neobot_purple_lite_angle_110, '110'],\n                                [Lang.Blocks.neobot_purple_lite_angle_120, '120'],\n                                [Lang.Blocks.neobot_purple_lite_angle_130, '130'],\n                                [Lang.Blocks.neobot_purple_lite_angle_140, '140'],\n                                [Lang.Blocks.neobot_purple_lite_angle_150, '150'],\n                                [Lang.Blocks.neobot_purple_lite_angle_160, '160'],\n                                [Lang.Blocks.neobot_purple_lite_angle_170, '170'],\n                                [Lang.Blocks.neobot_purple_lite_angle_180, '180'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neobot_purple_lite_decision_sensor_angle',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        SYMBOL: 1,\n                        VALUE: 2,\n                    },\n                    class: 'neobot_purple_lite_sensor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const sensor = Entry.NeobotPurpleLite.localBuffer[sensorTemp];\n                        const symbol = script.getStringField('SYMBOL');\n                        const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                        if (symbol == '=') {\n                            if (sensor == value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '>') {\n                            if (sensor > value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '<') {\n                            if (sensor < value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '>=') {\n                            if (sensor >= value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '<=') {\n                            if (sensor <= value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        }\n                        return false;\n                    },\n                },\n                neobot_purple_lite_remote_button: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#FFFFFF',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_remote_btn_1, '10'],\n                                [Lang.Blocks.neobot_purple_lite_remote_btn_2, '11'],\n                                [Lang.Blocks.neobot_purple_lite_remote_btn_3, '12'],\n                                [Lang.Blocks.neobot_purple_lite_remote_btn_4, '13'],\n                                [Lang.Blocks.neobot_purple_lite_remote_btn_up, '1'],\n                                [Lang.Blocks.neobot_purple_lite_remote_btn_down, '2'],\n                                [Lang.Blocks.neobot_purple_lite_remote_btn_left, '3'],\n                                [Lang.Blocks.neobot_purple_lite_remote_btn_right, '4'],\n                            ],\n                            value: '10',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_purple_lite_remote_button',\n                    },\n                    paramsKeyMap: {\n                        KEY: 0,\n                    },\n                    class: 'neobot_purple_lite_sensor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const key = script.getNumberField('KEY');\n                        const value = Entry.NeobotPurpleLite.localBuffer.IR;\n                        if (key == value) {\n                            return true;\n                        } else {\n                            return false;\n                        }\n                    },\n                },\n\n                /*************************\n                 * class neobot_purple_lite_led\n                 *************************/\n                neobot_purple_lite_led_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_purple_lite_led_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_purple_lite_led_title',\n                    },\n                    class: 'neobot_purple_lite_led',\n                    isNotFor: ['NeobotPurpleLite'],\n                    events: {},\n                },\n                neobot_purple_lite_led_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['100%', '255'],\n                                ['90%', '230'],\n                                ['80%', '204'],\n                                ['70%', '179'],\n                                ['60%', '153'],\n                                ['50%', '128'],\n                                ['40%', '102'],\n                                ['30%', '77'],\n                                ['20%', '51'],\n                                ['10%', '26'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neobot_purple_lite_arg_led_duration',\n                                id: 'm311',\n                            },\n                            null,\n                        ],\n                        type: 'neobot_purple_lite_led_on',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neobot_purple_lite_led',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const value = script.getNumberField('VALUE', script);\n                            const duration = script.getStringValue('DURATION', script);\n\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print('=== neobot_purple_lite_led_on ===', 'speak');\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`brightness : ${value}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            if (\n                                duration != '계속' &&\n                                duration != 'constantly' &&\n                                Entry.parseNumber(duration) <= 0\n                            ) {\n                                return script.callReturn();\n                            }\n\n                            if (port == 'ALL') {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT1 = value;\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT2 = value;\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT3 = value;\n                            } else {\n                                Entry.NeobotPurpleLite.remoteBuffer[port] = value;\n                            }\n\n                            if (duration == '계속' || duration == 'constantly') {\n                                return script.callReturn();\n                            }\n\n                            const durationValue = Entry.parseNumber(duration);\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            setTimeout(() => {\n                                if (port == 'ALL') {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT1 = 0;\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT2 = 0;\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT3 = 0;\n                                } else {\n                                    Entry.NeobotPurpleLite.remoteBuffer[port] = 0;\n                                }\n                                if (Entry.NeobotPurpleLite.log_to_console) {\n                                    Entry.console.print('neobot_purple_lite_led_on : 0', 'speak');\n                                }\n                                script.timeFlag = 0;\n                            }, durationValue * 1000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                neobot_purple_lite_output_led_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_purple_lite_output_led_off',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_purple_lite_led',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_purple_lite_output_led_off ===',\n                                'speak'\n                            );\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT1 = 0;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT2 = 0;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT3 = 0;\n                        } else {\n                            Entry.NeobotPurpleLite.remoteBuffer[port] = 0;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_purple_lite_led_brightness_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neobot_purple_lite_led_brightness_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        IN: 0,\n                        OUT: 1,\n                    },\n                    class: 'neobot_purple_lite_led',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const inPort = script.getStringField('IN', script);\n                        const outPort = script.getStringField('OUT', script);\n                        let value = Entry.NeobotPurpleLite.localBuffer[inPort];\n\n                        // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함.\n                        value = Math.max(value, 0);\n                        value = Math.min(value, 100);\n                        value = Math.ceil((value / 100) * 255);\n\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_purple_lite_led_brightness_with_sensor ===',\n                                'speak'\n                            );\n                            Entry.console.print(`out port : ${outPort}`, 'speak');\n                            Entry.console.print(`in port : ${inPort}`, 'speak');\n                            Entry.console.print(\n                                `sensor value : ${Entry.NeobotPurpleLite.localBuffer[inPort]}`,\n                                'speak'\n                            );\n                            Entry.console.print(`output value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (outPort == 'ALL') {\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT1 = value;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT2 = value;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT3 = value;\n                        } else {\n                            Entry.NeobotPurpleLite.remoteBuffer[outPort] = value;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_purple_lite_color_led_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            null,\n                        ],\n                        type: 'neobot_purple_lite_color_led_on',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        RED: 1,\n                        GREEN: 2,\n                        BLUE: 3,\n                    },\n                    class: 'neobot_purple_lite_led',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT');\n                            let red = script.getNumberValue('RED');\n                            let green = script.getNumberValue('GREEN');\n                            let blue = script.getNumberValue('BLUE');\n\n                            let out1 = false;\n                            let out2 = false;\n                            let out3 = false;\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            } else {\n                                out1 = port == 'OUT1';\n                                out2 = port == 'OUT2';\n                                out3 = port == 'OUT3';\n                            }\n\n                            red = Math.max(red, 1);\n                            red = Math.min(red, 251);\n                            green = Math.max(green, 1);\n                            green = Math.min(green, 251);\n                            blue = Math.max(blue, 1);\n                            blue = Math.min(blue, 251);\n\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_purple_lite_color_led_on ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`red : ${red}`, 'speak');\n                                Entry.console.print(`green : ${green}`, 'speak');\n                                Entry.console.print(`blue : ${blue}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            const valRed = 252;\n                            const valGreen = 253;\n                            const valBlue = 254;\n                            const valAccept = 255;\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            if (out1) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT1 = valRed;\n                            }\n                            if (out2) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT2 = valRed;\n                            }\n                            if (out3) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT3 = valRed;\n                            }\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_purple_lite_color_led_on : ${valRed}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                // set red\n                                if (out1) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT1 = red;\n                                }\n                                if (out2) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT2 = red;\n                                }\n                                if (out3) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT3 = red;\n                                }\n                                if (Entry.NeobotPurpleLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_purple_lite_color_led_on : ${red}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    // choose green\n                                    if (out1) {\n                                        Entry.NeobotPurpleLite.remoteBuffer.OUT1 = valGreen;\n                                    }\n                                    if (out2) {\n                                        Entry.NeobotPurpleLite.remoteBuffer.OUT2 = valGreen;\n                                    }\n                                    if (out3) {\n                                        Entry.NeobotPurpleLite.remoteBuffer.OUT3 = valGreen;\n                                    }\n                                    if (Entry.NeobotPurpleLite.log_to_console) {\n                                        Entry.console.print(\n                                            `neobot_purple_lite_color_led_on : ${valGreen}`,\n                                            'speak'\n                                        );\n                                    }\n                                    setTimeout(() => {\n                                        // set green\n                                        if (out1) {\n                                            Entry.NeobotPurpleLite.remoteBuffer.OUT1 = green;\n                                        }\n                                        if (out2) {\n                                            Entry.NeobotPurpleLite.remoteBuffer.OUT2 = green;\n                                        }\n                                        if (out3) {\n                                            Entry.NeobotPurpleLite.remoteBuffer.OUT3 = green;\n                                        }\n                                        if (Entry.NeobotPurpleLite.log_to_console) {\n                                            Entry.console.print(\n                                                `neobot_purple_lite_color_led_on : ${green}`,\n                                                'speak'\n                                            );\n                                        }\n                                        setTimeout(() => {\n                                            // choose blue\n                                            if (out1) {\n                                                Entry.NeobotPurpleLite.remoteBuffer.OUT1 = valBlue;\n                                            }\n                                            if (out2) {\n                                                Entry.NeobotPurpleLite.remoteBuffer.OUT2 = valBlue;\n                                            }\n                                            if (out3) {\n                                                Entry.NeobotPurpleLite.remoteBuffer.OUT3 = valBlue;\n                                            }\n                                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                                Entry.console.print(\n                                                    `neobot_purple_lite_color_led_on : ${valBlue}`,\n                                                    'speak'\n                                                );\n                                            }\n                                            setTimeout(() => {\n                                                // set blue\n                                                if (out1) {\n                                                    Entry.NeobotPurpleLite.remoteBuffer.OUT1 = blue;\n                                                }\n                                                if (out2) {\n                                                    Entry.NeobotPurpleLite.remoteBuffer.OUT2 = blue;\n                                                }\n                                                if (out3) {\n                                                    Entry.NeobotPurpleLite.remoteBuffer.OUT3 = blue;\n                                                }\n                                                if (Entry.NeobotPurpleLite.log_to_console) {\n                                                    Entry.console.print(\n                                                        `neobot_purple_lite_color_led_on : ${blue}`,\n                                                        'speak'\n                                                    );\n                                                }\n                                                setTimeout(() => {\n                                                    // accept\n                                                    if (out1) {\n                                                        Entry.NeobotPurpleLite.remoteBuffer.OUT1 = valAccept;\n                                                    }\n                                                    if (out2) {\n                                                        Entry.NeobotPurpleLite.remoteBuffer.OUT2 = valAccept;\n                                                    }\n                                                    if (out3) {\n                                                        Entry.NeobotPurpleLite.remoteBuffer.OUT3 = valAccept;\n                                                    }\n                                                    if (Entry.NeobotPurpleLite.log_to_console) {\n                                                        Entry.console.print(\n                                                            `neobot_purple_lite_color_led_on : ${valAccept}`,\n                                                            'speak'\n                                                        );\n                                                    }\n                                                    setTimeout(() => {\n                                                        // final delay\n                                                        script.timeFlag = 0;\n                                                    }, 200);\n                                                }, 200);\n                                            }, 200);\n                                        }, 200);\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                /*************************\n                 * class neobot_purple_lite_output\n                 *************************/\n                neobot_purple_lite_output_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_purple_lite_output_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_purple_lite_output_title',\n                    },\n                    class: 'neobot_purple_lite_output',\n                    isNotFor: ['NeobotPurpleLite'],\n                    events: {},\n                },\n                neobot_purple_lite_set_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            null,\n                        ],\n                        type: 'neobot_purple_lite_set_output',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                    },\n                    class: 'neobot_purple_lite_output',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        let value = script.getNumberValue('VALUE', script);\n                        if (value < 0) {\n                            value = 0;\n                        } else if (value > 255) {\n                            value = 255;\n                        }\n\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print('=== neobot_purple_lite_set_output ===', 'speak');\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT1 = value;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT2 = value;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT3 = value;\n                        } else {\n                            Entry.NeobotPurpleLite.remoteBuffer[port] = value;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_purple_lite_motor\n                 *************************/\n                neobot_purple_lite_motor_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_purple_lite_motor_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_purple_lite_motor_title',\n                    },\n                    class: 'neobot_purple_lite_motor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    events: {},\n                },\n                neobot_purple_lite_robot: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_motor_move_forward, '1'],\n                                [Lang.Blocks.neobot_purple_lite_motor_move_backward, '2'],\n                                [Lang.Blocks.neobot_purple_lite_motor_move_left, '3'],\n                                [Lang.Blocks.neobot_purple_lite_motor_move_right, '4'],\n                                [Lang.Blocks.neobot_purple_lite_motor_move_stop, '5'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_purple_lite_robot',\n                    },\n                    paramsKeyMap: {\n                        MOVE: 0,\n                    },\n                    class: 'neobot_purple_lite_motor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const move = script.getNumberField('MOVE');\n                        let leftValue;\n                        let rightValue;\n                        switch (move) {\n                            case 1:\n                                leftValue = 0x10 + 10;\n                                rightValue = 0x10 + 10;\n                                break;\n                            case 2:\n                                leftValue = 0x20 + 10;\n                                rightValue = 0x20 + 10;\n                                break;\n                            case 3:\n                                leftValue = 0x20 + 5;\n                                rightValue = 0x10 + 5;\n                                break;\n                            case 4:\n                                leftValue = 0x10 + 5;\n                                rightValue = 0x20 + 5;\n                                break;\n                            case 5:\n                                leftValue = 0;\n                                rightValue = 0;\n                                break;\n                        }\n\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print('=== neobot_purple_lite_robot ===', 'speak');\n                            Entry.console.print(`move : ${move}`, 'speak');\n                            Entry.console.print(`left value : ${leftValue}`, 'speak');\n                            Entry.console.print(`right value : ${rightValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotPurpleLite.remoteBuffer.DCL = leftValue;\n                        Entry.NeobotPurpleLite.remoteBuffer.DCR = rightValue;\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_purple_lite_motor_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_motor_both, '1'],\n                                [Lang.Blocks.neobot_purple_lite_motor_left, '2'],\n                                [Lang.Blocks.neobot_purple_lite_motor_right, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_direction_forward, '1'],\n                                [Lang.Blocks.neobot_purple_lite_direction_backward, '2'],\n                                [Lang.Blocks.neobot_purple_lite_direction_left, '3'],\n                                [Lang.Blocks.neobot_purple_lite_direction_right, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neobot_purple_lite_arg_motor_speed',\n                                id: 'm411',\n                            },\n                            {\n                                type: 'neobot_purple_lite_arg_motor_duration',\n                                id: 'm412',\n                            },\n                            null,\n                        ],\n                        type: 'neobot_purple_lite_motor_start',\n                    },\n                    paramsKeyMap: {\n                        MOTOR: 0,\n                        DIRECTION: 1,\n                        SPEED: 2,\n                        DURATION: 3,\n                    },\n                    class: 'neobot_purple_lite_motor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const motor = script.getStringField('MOTOR', script);\n                            const direction = script.getStringField('DIRECTION', script);\n                            const speed = script.getStringValue('SPEED', script);\n                            const duration = script.getStringValue('DURATION', script);\n\n                            if (\n                                duration != '계속' &&\n                                duration != 'constantly' &&\n                                Entry.parseNumber(duration) <= 0\n                            ) {\n                                return script.callReturn();\n                            }\n\n                            let moveLeft = false;\n                            let moveRight = false;\n                            if (motor == 1) {\n                                moveLeft = true;\n                                moveRight = true;\n                            } else if (motor == 2) {\n                                moveLeft = true;\n                            } else {\n                                moveRight = true;\n                            }\n\n                            let leftDirectionValue;\n                            let rightDirectionValue;\n                            if (direction == 1) {\n                                leftDirectionValue = 0x10;\n                                rightDirectionValue = 0x10;\n                            } else if (direction == 2) {\n                                leftDirectionValue = 0x20;\n                                rightDirectionValue = 0x20;\n                            } else if (direction == 3) {\n                                leftDirectionValue = 0x20;\n                                rightDirectionValue = 0x10;\n                            } else {\n                                leftDirectionValue = 0x10;\n                                rightDirectionValue = 0x20;\n                            }\n\n                            // edited 210421, 0~100 을 0~15로 변환, 100 이상은 최대값(15)으로 처리함.\n                            let speedValue = 0;\n                            if (Entry.Utils.isNumber(speed)) {\n                                speedValue = Entry.parseNumber(speed);\n                            } else {\n                                speedValue = Entry.NeobotPurpleLite.localBuffer[speed];\n                            }\n                            speedValue = Math.max(speedValue, 0);\n                            speedValue = Math.min(speedValue, 100);\n                            speedValue = Math.ceil((speedValue / 100) * 15);\n\n                            const leftOutValue = leftDirectionValue + speedValue;\n                            const rightOutValue = rightDirectionValue + speedValue;\n\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_purple_lite_motor_start ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`motor : ${motor}`, 'speak');\n                                Entry.console.print(`direction : ${direction}`, 'speak');\n                                Entry.console.print(`speed : ${speed}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print(\n                                    `left direction value : ${leftDirectionValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print(\n                                    `right direction value : ${rightDirectionValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print(`speed value : ${speedValue}`, 'speak');\n                                Entry.console.print(`left output value : ${leftOutValue}`, 'speak');\n                                Entry.console.print(\n                                    `right output value : ${rightOutValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            if (moveLeft) {\n                                Entry.NeobotPurpleLite.remoteBuffer.DCL = leftOutValue;\n                            }\n                            if (moveRight) {\n                                Entry.NeobotPurpleLite.remoteBuffer.DCR = rightOutValue;\n                            }\n\n                            if (duration == '계속' || duration == 'constantly') {\n                                return script.callReturn();\n                            }\n\n                            const durationValue = Entry.parseNumber(duration);\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            setTimeout(() => {\n                                Entry.NeobotPurpleLite.remoteBuffer.DCL = 0;\n                                Entry.NeobotPurpleLite.remoteBuffer.DCR = 0;\n                                if (Entry.NeobotPurpleLite.log_to_console) {\n                                    Entry.console.print(\n                                        'neobot_purple_lite_motor_start : 0',\n                                        'speak'\n                                    );\n                                }\n                                script.timeFlag = 0;\n                            }, durationValue * 1000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                neobot_purple_lite_motor_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_motor_both, '1'],\n                                [Lang.Blocks.neobot_purple_lite_motor_left, '2'],\n                                [Lang.Blocks.neobot_purple_lite_motor_right, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_purple_lite_motor_stop',\n                    },\n                    paramsKeyMap: {\n                        MOTOR: 0,\n                    },\n                    class: 'neobot_purple_lite_motor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const motor = script.getNumberField('MOTOR');\n\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print('=== neobot_purple_lite_motor_stop ===', 'speak');\n                            Entry.console.print(`motor : ${motor}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (motor == 1) {\n                            Entry.NeobotPurpleLite.remoteBuffer.DCL = 0;\n                            Entry.NeobotPurpleLite.remoteBuffer.DCR = 0;\n                        } else if (motor == 2) {\n                            Entry.NeobotPurpleLite.remoteBuffer.DCL = 0;\n                        } else {\n                            Entry.NeobotPurpleLite.remoteBuffer.DCR = 0;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_purple_lite_melody\n                 *************************/\n                neobot_purple_lite_buzzer_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_purple_lite_buzzer_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_purple_lite_buzzer_title',\n                    },\n                    class: 'neobot_purple_lite_buzzer',\n                    isNotFor: ['NeobotPurpleLite'],\n                    events: {},\n                },\n                neobot_purple_lite_play_note_for: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_sound_silent, '0'],\n                                [Lang.Blocks.neobot_purple_lite_sound_do, '1'],\n                                [Lang.Blocks.neobot_purple_lite_sound_do_shop, '2'],\n                                [Lang.Blocks.neobot_purple_lite_sound_re, '3'],\n                                [Lang.Blocks.neobot_purple_lite_sound_re_shop, '4'],\n                                [Lang.Blocks.neobot_purple_lite_sound_mi, '5'],\n                                [Lang.Blocks.neobot_purple_lite_sound_fa, '6'],\n                                [Lang.Blocks.neobot_purple_lite_sound_fa_shop, '7'],\n                                [Lang.Blocks.neobot_purple_lite_sound_so, '8'],\n                                [Lang.Blocks.neobot_purple_lite_sound_so_shop, '9'],\n                                [Lang.Blocks.neobot_purple_lite_sound_la, '10'],\n                                [Lang.Blocks.neobot_purple_lite_sound_la_shop, '11'],\n                                [Lang.Blocks.neobot_purple_lite_sound_ti, '12'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                                ['6', '5'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_sound_half_note, '2'],\n                                [Lang.Blocks.neobot_purple_lite_sound_quarter_note, '4'],\n                                [Lang.Blocks.neobot_purple_lite_sound_eighth_note, '8'],\n                                [Lang.Blocks.neobot_purple_lite_sound_sixteenth_note, '16'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '2', '4', null],\n                        type: 'neobot_purple_lite_play_note_for',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                        OCTAVE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neobot_purple_lite_buzzer',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const note = script.getNumberField('NOTE', script);\n                            const octave = script.getNumberField('OCTAVE', script);\n                            const duration = script.getNumberField('DURATION', script);\n                            let value = note > 0 ? note + 12 * octave : 0;\n\n                            value = Math.min(value, 72);\n\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_purple_lite_play_note_for ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`note : ${note}`, 'speak');\n                                Entry.console.print(`octave : ${octave}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print(`value : ${value}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            Entry.NeobotPurpleLite.remoteBuffer.SND = value;\n                            setTimeout(() => {\n                                Entry.NeobotPurpleLite.remoteBuffer.SND = 0;\n                                if (Entry.NeobotPurpleLite.log_to_console) {\n                                    Entry.console.print(\n                                        'neobot_purple_lite_play_note_for : 0',\n                                        'speak'\n                                    );\n                                }\n                                script.timeFlag = 0;\n                            }, (1 / duration) * 2000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                neobot_purple_lite_melody_play_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_purple_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_purple_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_purple_lite_melody_play_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                    },\n                    class: 'neobot_purple_lite_buzzer',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const input = script.getStringField('INPUT');\n                        let value = Entry.NeobotPurpleLite.localBuffer[input];\n\n                        // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함.\n                        value = Math.max(value, 0);\n                        value = Math.min(value, 100);\n                        value = Math.ceil((value / 100) * 65);\n\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_purple_lite_melody_play_with_sensor ===',\n                                'speak'\n                            );\n                            Entry.console.print(`input : ${input}`, 'speak');\n                            Entry.console.print(`value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotPurpleLite.remoteBuffer.SND = value;\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_purple_lite_melody_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_purple_lite_melody_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'neobot_purple_lite_buzzer',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print('=== neobot_purple_lite_melody_stop ===', 'speak');\n                            Entry.console.print('value : 0', 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotPurpleLite.remoteBuffer.SND = 0;\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_purple_lite_servo\n                 *************************/\n                neobot_purple_lite_servo_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_purple_lite_servo_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_purple_lite_servo_title',\n                    },\n                    class: 'neobot_purple_lite_servo',\n                    isNotFor: ['NeobotPurpleLite'],\n                    events: {},\n                },\n                neobot_purple_lite_servo_init: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_purple_lite_servo_init',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_purple_lite_servo',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const resetValue = 186;\n                            const initValue = 1;\n\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_purple_lite_servo_init ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            let out1 = port == 'OUT1';\n                            let out2 = port == 'OUT2';\n                            let out3 = port == 'OUT3';\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            if (out1) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT1 = resetValue;\n                            }\n                            if (out2) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT2 = resetValue;\n                            }\n                            if (out3) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT3 = resetValue;\n                            }\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_purple_lite_servo_init : ${resetValue}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                if (out1) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT1 = initValue;\n                                }\n                                if (out2) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT2 = initValue;\n                                }\n                                if (out3) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT3 = initValue;\n                                }\n                                if (Entry.NeobotPurpleLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_purple_lite_servo_init : ${initValue}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    script.timeFlag = 0;\n                                }, 100);\n                            }, 200);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                neobot_purple_lite_servo_rotate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_servo_dir_1, '1'],\n                                [Lang.Blocks.neobot_purple_lite_servo_dir_2, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['0%', 0],\n                                ['10%', 10],\n                                ['20%', 20],\n                                ['30%', 30],\n                                ['40%', 40],\n                                ['50%', 50],\n                                ['60%', 60],\n                                ['70%', 70],\n                                ['80%', 80],\n                                ['90%', 90],\n                                ['100%', 100],\n                            ],\n                            value: 50,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'neobot_purple_lite_servo_rotate',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        DIRECTION: 1,\n                        SPEED: 2,\n                    },\n                    class: 'neobot_purple_lite_servo',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        const direction = script.getNumberField('DIRECTION');\n                        const speed = script.getStringField('SPEED');\n\n                        let directionValue = 192; // 정방향\n                        if (direction == 2) {\n                            directionValue = 208; // 역방향\n                        }\n                        let speedValue;\n                        if (Entry.Utils.isNumber(speed)) {\n                            speedValue = Entry.parseNumber(speed);\n                        } else {\n                            speedValue = Entry.NeobotPurpleLite.localBuffer[speed];\n                        }\n\n                        // edited 210421, 0~100 을 0~10 으로 변환\n                        speedValue = Math.max(speedValue, 0);\n                        speedValue = Math.min(speedValue, 100);\n                        speedValue = Math.ceil(speedValue / 10);\n\n                        let outValue = directionValue + speedValue;\n                        if (outValue == directionValue) {\n                            outValue = 254;\n                        } else {\n                            outValue = outValue - 1;\n                        }\n\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print('=== neobot_purple_lite_servo_rotate ===');\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`direction : ${direction}`, 'speak');\n                            Entry.console.print(`speed : ${speed}`, 'speak');\n                            Entry.console.print(`direction value : ${directionValue}`, 'speak');\n                            Entry.console.print(`speed value : ${speedValue}`, 'speak');\n                            Entry.console.print(`output value : ${outValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT1 = outValue;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT2 = outValue;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT3 = outValue;\n                        } else {\n                            Entry.NeobotPurpleLite.remoteBuffer[port] = outValue;\n                        }\n                        return script.callReturn();\n                    },\n                },\n                neobot_purple_lite_servo_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_purple_lite_servo_stop',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_purple_lite_servo',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        const outValue = 254;\n\n                        if (Entry.NeobotPurpleLite.log_to_console) {\n                            Entry.console.print('=== neobot_purple_lite_servo_stop ===', 'speak');\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`output value: ${outValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT1 = outValue;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT2 = outValue;\n                            Entry.NeobotPurpleLite.remoteBuffer.OUT3 = outValue;\n                        } else {\n                            Entry.NeobotPurpleLite.remoteBuffer[port] = outValue;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_purple_lite_servo_change_degree: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_purple_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_servo_dir_1, '1'],\n                                [Lang.Blocks.neobot_purple_lite_servo_dir_2, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['0%', 0],\n                                ['10%', 10],\n                                ['20%', 20],\n                                ['30%', 30],\n                                ['40%', 40],\n                                ['50%', 50],\n                                ['60%', 60],\n                                ['70%', 70],\n                                ['80%', 80],\n                                ['90%', 90],\n                                ['100%', 100],\n                            ],\n                            value: 50,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'get_servo_degree',\n                                id: 'm211',\n                            },\n                            null,\n                            null,\n                            null,\n                            null,\n                        ],\n                        type: 'neobot_purple_lite_servo_change_degree',\n                    },\n                    paramsKeyMap: {\n                        DEGREE: 0,\n                        PORT: 1,\n                        DIRECTION: 2,\n                        SPEED: 3,\n                    },\n                    class: 'neobot_purple_lite_servo',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const direction = script.getNumberField('DIRECTION');\n                            const speed = script.getStringValue('SPEED');\n                            const degree = script.getStringValue('DEGREE');\n\n                            let out1 = port == 'OUT1';\n                            let out2 = port == 'OUT2';\n                            let out3 = port == 'OUT3';\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            }\n\n                            let directionValue = 188;\n                            if (direction == 2) {\n                                directionValue = 189;\n                            }\n\n                            let speedValue;\n                            if (Entry.Utils.isNumber(speed)) {\n                                speedValue = Entry.parseNumber(speed);\n                            } else {\n                                speedValue = Entry.NeobotPurpleLite.localBuffer[speed];\n                            }\n\n                            // edited 210421, 0~100 을 240~250 으로 변환\n                            speedValue = Math.max(speedValue, 0);\n                            speedValue = Math.min(speedValue, 100);\n                            speedValue = Math.ceil(speedValue / 10) + 240;\n\n                            let degreeValue;\n                            if (Entry.Utils.isNumber(degree)) {\n                                degreeValue = Entry.parseNumber(degree);\n                            } else {\n                                if (degree == 'IN1' || degree == 'IN2' || degree == 'IN3') {\n                                    degreeValue = Entry.NeobotPurpleLite.localBuffer[degree];\n                                } else {\n                                    degreeValue = 0;\n                                }\n                            }\n                            // edited 210421, 별도의 변환없이 그대로 사용함\n                            degreeValue = Math.max(degreeValue, 0);\n                            degreeValue = Math.min(degreeValue, 180);\n                            degreeValue = degreeValue + 1;\n\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_purple_lite_servo_change_degree ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`direction : ${direction}`, 'speak');\n                                Entry.console.print(`speed : ${speed}`, 'speak');\n                                Entry.console.print(`degree : ${degree}`, 'speak');\n                                Entry.console.print(`directionValue : ${directionValue}`, 'speak');\n                                Entry.console.print(`speedValue : ${speedValue}`, 'speak');\n                                Entry.console.print(`degreeValue : ${degreeValue}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            // direction\n                            if (out1) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT1 = directionValue;\n                            }\n                            if (out2) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT2 = directionValue;\n                            }\n                            if (out3) {\n                                Entry.NeobotPurpleLite.remoteBuffer.OUT3 = directionValue;\n                            }\n                            if (Entry.NeobotPurpleLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_purple_lite_servo_change_degree : ${directionValue}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                // speed\n                                if (out1) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT1 = speedValue;\n                                }\n                                if (out2) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT2 = speedValue;\n                                }\n                                if (out3) {\n                                    Entry.NeobotPurpleLite.remoteBuffer.OUT3 = speedValue;\n                                }\n                                if (Entry.NeobotPurpleLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_purple_lite_servo_change_degree : ${speedValue}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    // degree\n                                    if (out1) {\n                                        Entry.NeobotPurpleLite.remoteBuffer.OUT1 = degreeValue;\n                                    }\n                                    if (out2) {\n                                        Entry.NeobotPurpleLite.remoteBuffer.OUT2 = degreeValue;\n                                    }\n                                    if (out3) {\n                                        Entry.NeobotPurpleLite.remoteBuffer.OUT3 = degreeValue;\n                                    }\n                                    if (Entry.NeobotPurpleLite.log_to_console) {\n                                        Entry.console.print(\n                                            `neobot_purple_lite_servo_change_degree : ${degreeValue}`,\n                                            'speak'\n                                        );\n                                    }\n                                    setTimeout(() => {\n                                        // final delay\n                                        script.timeFlag = 0;\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                /*****************\n                 * ARG Blocks\n                 *****************/\n                neobot_purple_lite_arg_led_duration: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_duration_cont, '계속'],\n                                [Lang.Blocks.neobot_purple_lite_duration_1s, '1'],\n                                [Lang.Blocks.neobot_purple_lite_duration_2s, '2'],\n                                [Lang.Blocks.neobot_purple_lite_duration_3s, '3'],\n                                [Lang.Blocks.neobot_purple_lite_duration_4s, '4'],\n                                [Lang.Blocks.neobot_purple_lite_duration_5s, '5'],\n                                [Lang.Blocks.neobot_purple_lite_duration_6s, '6'],\n                                [Lang.Blocks.neobot_purple_lite_duration_7s, '7'],\n                                [Lang.Blocks.neobot_purple_lite_duration_8s, '8'],\n                                [Lang.Blocks.neobot_purple_lite_duration_9s, '9'],\n                            ],\n                            value: '계속',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_purple_lite_led',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                neobot_purple_lite_arg_motor_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['100%', 100],\n                                ['90%', 90],\n                                ['80%', 80],\n                                ['70%', 70],\n                                ['60%', 60],\n                                ['50%', 50],\n                                ['40%', 40],\n                                ['30%', 30],\n                                ['20%', 20],\n                                ['10%', 10],\n                                ['0%', 0],\n                            ],\n                            value: 100,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_purple_lite_motor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                neobot_purple_lite_arg_motor_duration: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_duration_cont, '계속'],\n                                [Lang.Blocks.neobot_purple_lite_duration_1s, '1'],\n                                [Lang.Blocks.neobot_purple_lite_duration_2s, '2'],\n                                [Lang.Blocks.neobot_purple_lite_duration_3s, '3'],\n                                [Lang.Blocks.neobot_purple_lite_duration_4s, '4'],\n                                [Lang.Blocks.neobot_purple_lite_duration_5s, '5'],\n                                [Lang.Blocks.neobot_purple_lite_duration_6s, '6'],\n                                [Lang.Blocks.neobot_purple_lite_duration_7s, '7'],\n                                [Lang.Blocks.neobot_purple_lite_duration_8s, '8'],\n                                [Lang.Blocks.neobot_purple_lite_duration_9s, '9'],\n                            ],\n                            value: '계속',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_purple_lite_motor',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                get_servo_degree: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_purple_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_purple_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_purple_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_purple_lite_angle_0, '0'],\n                                [Lang.Blocks.neobot_purple_lite_angle_5, '5'],\n                                [Lang.Blocks.neobot_purple_lite_angle_10, '10'],\n                                [Lang.Blocks.neobot_purple_lite_angle_15, '15'],\n                                [Lang.Blocks.neobot_purple_lite_angle_20, '20'],\n                                [Lang.Blocks.neobot_purple_lite_angle_25, '25'],\n                                [Lang.Blocks.neobot_purple_lite_angle_30, '30'],\n                                [Lang.Blocks.neobot_purple_lite_angle_35, '35'],\n                                [Lang.Blocks.neobot_purple_lite_angle_40, '40'],\n                                [Lang.Blocks.neobot_purple_lite_angle_45, '45'],\n                                [Lang.Blocks.neobot_purple_lite_angle_50, '50'],\n                                [Lang.Blocks.neobot_purple_lite_angle_55, '55'],\n                                [Lang.Blocks.neobot_purple_lite_angle_60, '60'],\n                                [Lang.Blocks.neobot_purple_lite_angle_65, '65'],\n                                [Lang.Blocks.neobot_purple_lite_angle_70, '70'],\n                                [Lang.Blocks.neobot_purple_lite_angle_75, '75'],\n                                [Lang.Blocks.neobot_purple_lite_angle_80, '80'],\n                                [Lang.Blocks.neobot_purple_lite_angle_85, '85'],\n                                [Lang.Blocks.neobot_purple_lite_angle_90, '90'],\n                                [Lang.Blocks.neobot_purple_lite_angle_95, '95'],\n                                [Lang.Blocks.neobot_purple_lite_angle_100, '100'],\n                                [Lang.Blocks.neobot_purple_lite_angle_105, '105'],\n                                [Lang.Blocks.neobot_purple_lite_angle_110, '110'],\n                                [Lang.Blocks.neobot_purple_lite_angle_115, '115'],\n                                [Lang.Blocks.neobot_purple_lite_angle_120, '120'],\n                                [Lang.Blocks.neobot_purple_lite_angle_125, '125'],\n                                [Lang.Blocks.neobot_purple_lite_angle_130, '130'],\n                                [Lang.Blocks.neobot_purple_lite_angle_135, '135'],\n                                [Lang.Blocks.neobot_purple_lite_angle_140, '140'],\n                                [Lang.Blocks.neobot_purple_lite_angle_145, '145'],\n                                [Lang.Blocks.neobot_purple_lite_angle_150, '150'],\n                                [Lang.Blocks.neobot_purple_lite_angle_155, '155'],\n                                [Lang.Blocks.neobot_purple_lite_angle_160, '160'],\n                                [Lang.Blocks.neobot_purple_lite_angle_165, '165'],\n                                [Lang.Blocks.neobot_purple_lite_angle_170, '170'],\n                                [Lang.Blocks.neobot_purple_lite_angle_175, '175'],\n                                [Lang.Blocks.neobot_purple_lite_angle_180, '180'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_purple_lite_servo',\n                    isNotFor: ['NeobotPurpleLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n            };\n        };\n    })();\n})();\n\nmodule.exports = Entry.NeobotPurpleLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_neobot_soco_lite.js",
    "content": "'use strict';\n(function() {\n    const HEADER = [0xab, 0xcd];\n    Entry.NeobotSocoLite = new (class NeobotSocoLite {\n        constructor() {\n            this.id = '050601';\n            this.name = 'NeobotSocoLite';\n            this.url = 'http://neobot.co.kr/';\n            this.imageName = 'neobot_soco_lite.png';\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n            };\n            this.duration = 100;\n            this.LOCAL_MAP = ['IN1', 'IN2', 'IN3', 'IR', 'BAT'];\n            this.localBuffer = {\n                IN1: 0,\n                IN2: 0,\n                IN3: 0,\n                IR: 0,\n                BAT: 0,\n            };\n            this.remoteBuffer = {\n                OUT1: 0,\n                OUT2: 0,\n                OUT3: 0,\n                DCL: 0,\n                DCR: 0,\n                SND: 0,\n                FND: 0,\n                OPT: 0,\n            };\n            this.log_to_console = false;\n\n            this.blockMenuBlocks = [\n                // sensor\n                'neobot_soco_lite_sensor_title',\n                'neobot_soco_lite_sensor_value',\n                'neobot_soco_lite_sensor_convert_scale',\n                'neobot_soco_lite_decision_sensor_is_over',\n                'neobot_soco_lite_decision_equal_with_sensor',\n                'neobot_soco_lite_decision_sensor_angle',\n                'neobot_soco_lite_remote_button',\n\n                // led\n                'neobot_soco_lite_led_title',\n                'neobot_soco_lite_led_on',\n                'neobot_soco_lite_led_brightness_with_sensor',\n                'neobot_soco_lite_color_led_on',\n                'neobot_soco_lite_output_led_off',\n\n                // output\n                'neobot_soco_lite_output_title',\n                'neobot_soco_lite_set_output',\n\n                //  motor\n                'neobot_soco_lite_motor_title',\n                'neobot_soco_lite_robot',\n                'neobot_soco_lite_motor_start',\n                'neobot_soco_lite_motor_stop',\n\n                // servo\n                'neobot_soco_lite_servo_title',\n                'neobot_soco_lite_servo_init',\n                'neobot_soco_lite_servo_rotate',\n                'neobot_soco_lite_servo_stop',\n                'neobot_soco_lite_servo_change_degree',\n\n                // buzzer\n                'neobot_soco_lite_buzzer_title',\n                'neobot_soco_lite_play_note_for',\n                'neobot_soco_lite_melody_play_with_sensor',\n                'neobot_soco_lite_melody_stop',\n            ];\n\n            this.setZero();\n        }\n\n        get monitorTemplate() {\n            return {\n                imgPath: 'hw/neobot_soco.png',\n                width: 700,\n                height: 700,\n                listPorts: {\n                    IR: { name: '리모컨', type: 'input', pos: { x: 0, y: 0 } },\n                    BAT: { name: '배터리', type: 'input', pos: { x: 0, y: 0 } },\n                    SND: { name: Lang.Hw.buzzer, type: 'output', pos: { x: 0, y: 0 } },\n                    FND: { name: 'FND', type: 'output', pos: { x: 0, y: 0 } },\n                },\n                ports: {\n                    IN1: { name: 'IN1', type: 'input', pos: { x: 270, y: 200 } },\n                    IN2: { name: 'IN2', type: 'input', pos: { x: 325, y: 200 } },\n                    IN3: { name: 'IN3', type: 'input', pos: { x: 325, y: 500 } },\n                    DCL: { name: 'L-Motor', type: 'output', pos: { x: 270, y: 500 } },\n                    DCR: { name: 'R-Motor', type: 'output', pos: { x: 435, y: 500 } },\n                    OUT1: { name: 'OUT1', type: 'output', pos: { x: 380, y: 200 } },\n                    OUT2: { name: 'OUT2', type: 'output', pos: { x: 435, y: 200 } },\n                    OUT3: { name: 'OUT3', type: 'output', pos: { x: 380, y: 500 } },\n                },\n                mode: 'both',\n            };\n        }\n\n        getMonitorPort() {\n            return { ...this.localBuffer, ...this.remoteBuffer };\n        }\n\n        setZero() {\n            this.remoteBuffer = {\n                OUT1: 0,\n                OUT2: 0,\n                OUT3: 0,\n                DCL: 0,\n                DCR: 0,\n                SND: 0,\n                FND: 0,\n                OPT: 0,\n            };\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        handleLocalData(data) {\n            let validPdu = this.getValidPdu(data);\n            while (validPdu) {\n                this.onReceivePdu(validPdu);\n                if (!this.remainingPdu || this.remainingPdu.length <= 0) {\n                    break;\n                }\n                validPdu = this.getValidPdu([]);\n            }\n        }\n\n        onReceivePdu(pdu) {\n            if (pdu[0] === HEADER[0] && pdu[1] === HEADER[1]) {\n                this.localBuffer['IN1'] = pdu[2];\n                this.localBuffer['IN2'] = pdu[3];\n                this.localBuffer['IN3'] = pdu[4];\n                this.localBuffer['IR'] = pdu[5];\n                this.localBuffer['BAT'] = pdu[6];\n            }\n        }\n\n        getValidPdu(pdu) {\n            const mergedPdu = [];\n            if (this.remainingPdu) {\n                mergedPdu.push(...this.remainingPdu);\n                this.remainingPdu = null;\n            }\n            mergedPdu.push(...pdu);\n            if (mergedPdu.length < 2) {\n                this.remainingPdu = [...mergedPdu];\n                return null;\n            }\n\n            // 헤더 불일치는 버림\n            if (!this.checkHeader(mergedPdu)) {\n                return null;\n            }\n\n            // 유효 데이터 길이는 header 2 + body 5 + checksum 1 = 8\n            const validDataLength = 8;\n            /*\n            전체 길이가 유효 데이터 길이보다 작을 경우\n            아직 도착하지 않은 부분이 있으므로 병합을 위해 remainingPdu 에 저장\n             */\n            if (mergedPdu.length < validDataLength) {\n                this.remainingPdu = [...mergedPdu];\n                return null;\n            }\n\n            /*\n            전체 길이가 유효 데이터 길이보다 클 경우\n            유효한 부분만 잘라내고 나머지는 remainingPdu 에 저장\n             */\n            if (mergedPdu.length > validDataLength) {\n                this.remainingPdu = mergedPdu.slice(validDataLength, mergedPdu.length);\n            }\n\n            const validPdu = mergedPdu.slice(0, validDataLength);\n\n            /*\n            유효 Pdu 의 checksum 확인\n             */\n            const dataLength = 5;\n            let checkSum = 0;\n            for (let i = 0; i < dataLength; i++) {\n                checkSum += validPdu[i + 2];\n            }\n            checkSum = checkSum & 255;\n            const pduCheckSum = validPdu[7];\n            if (pduCheckSum !== checkSum) {\n                return null;\n            }\n\n            return validPdu;\n        }\n\n        checkHeader(pdu) {\n            if (pdu.length < HEADER.length) {\n                return false;\n            }\n\n            for (let i = 0; i < HEADER.length; i++) {\n                if (HEADER[i] !== pdu[i]) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        requestLocalData() {\n            const requestData = [];\n\n            // 시작 바이트\n            requestData.push(0xcd);\n            requestData.push(0xab);\n\n            let checksum = 0;\n            let isFnd = false;\n            Object.keys(this.remoteBuffer).forEach((key, idx) => {\n                let value = this.remoteBuffer[key];\n                if (idx === 6 && value > 0) {\n                    isFnd = true;\n                } else if (idx === 7 && isFnd) {\n                    value = value | 8;\n                }\n                requestData.push(value);\n                checksum += value;\n            });\n\n            checksum = checksum & 255;\n            //체크썸\n            requestData.push(checksum);\n            return requestData;\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // sensor\n                        neobot_soco_lite_sensor_title: '센서',\n                        neobot_soco_lite_sensor_value: '%1',\n                        neobot_soco_lite_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환',\n                        neobot_soco_lite_decision_sensor_is_over: '%1 %2 %3',\n                        neobot_soco_lite_decision_equal_with_sensor: '%1 컬러가 %2',\n                        neobot_soco_lite_decision_sensor_angle: '%1 각도 %2 %3',\n                        neobot_soco_lite_remote_button: '리모컨 버튼 %1 을 누름',\n\n                        // LED\n                        neobot_soco_lite_led_title: 'LED',\n                        neobot_soco_lite_arg_led_duration: '%1',\n                        neobot_soco_lite_led_on: 'LED 켜기   %1 %2 %3 %4',\n                        neobot_soco_lite_output_led_off: '%1 LED 끄기 %2',\n                        neobot_soco_lite_led_brightness_with_sensor: '%1 로 %2 LED 제어 %3',\n                        neobot_soco_lite_color_led_on: '%1 컬러LED 켜기   R %2 G %3 B %4 %5',\n\n                        // output\n                        neobot_soco_lite_output_title: '출력',\n                        neobot_soco_lite_set_output: '%1 에 %2 값 출력하기 %3',\n\n                        // motor\n                        neobot_soco_lite_motor_title: '회전모터',\n                        neobot_soco_lite_robot: '로봇 %1 %2',\n                        neobot_soco_lite_motor_start: '모터 회전하기   %1 %2 %3 %4 %5',\n                        neobot_soco_lite_motor_stop: '%1 모터 멈추기 %2',\n                        neobot_soco_lite_arg_motor_speed: '%1',\n                        neobot_soco_lite_arg_motor_duration: '%1',\n\n                        // melody\n                        neobot_soco_lite_buzzer_title: '버저',\n                        neobot_soco_lite_play_note_for:\n                            '버저 울리기   옥타브: %2 음: %1 길이: %3 %4',\n                        neobot_soco_lite_melody_play_with_sensor: '%1 센서로 버저 울리기 %2',\n                        neobot_soco_lite_melody_stop: '버저 멈추기 %1',\n\n                        // servo\n                        neobot_soco_lite_servo_title: '서보모터',\n                        get_servo_degree: '%1',\n                        neobot_soco_lite_servo_init: '%1 서보모터 리셋 %2',\n                        neobot_soco_lite_servo_rotate: '서보모터 회전하기   %1 %2 %3 %4',\n                        neobot_soco_lite_servo_stop: '%1 서보모터 멈추기 %2',\n                        neobot_soco_lite_servo_change_degree:\n                            '서보모터 각도 바꾸기   %2 %3 %4 %1 %5',\n                    },\n                    Blocks: {\n                        //for dropdown\n                        neobot_soco_lite_port_1: 'IN1',\n                        neobot_soco_lite_port_2: 'IN2',\n                        neobot_soco_lite_port_3: 'IN3',\n                        neobot_soco_lite_port_4: 'IN4',\n                        neobot_soco_lite_port_12: 'IN1 & IN2',\n                        neobot_soco_lite_port_bat: '배터리',\n                        neobot_soco_lite_port_remot: '리모컨',\n                        neobot_soco_lite_color_white: '흰색',\n                        neobot_soco_lite_color_red: '빨강',\n                        neobot_soco_lite_color_yellow: '노랑',\n                        neobot_soco_lite_color_green: '녹색',\n                        neobot_soco_lite_color_blue: '파랑',\n                        neobot_soco_lite_direction_forward: '앞으로',\n                        neobot_soco_lite_direction_backward: '뒤로',\n                        neobot_soco_lite_sound_silent: '무음',\n                        neobot_soco_lite_sound_do: '도',\n                        neobot_soco_lite_sound_do_shop: '도#',\n                        neobot_soco_lite_sound_re: '레',\n                        neobot_soco_lite_sound_re_shop: '레#',\n                        neobot_soco_lite_sound_mi: '미',\n                        neobot_soco_lite_sound_fa: '파',\n                        neobot_soco_lite_sound_fa_shop: '파#',\n                        neobot_soco_lite_sound_so: '솔',\n                        neobot_soco_lite_sound_so_shop: '솔#',\n                        neobot_soco_lite_sound_la: '라',\n                        neobot_soco_lite_sound_la_shop: '라#',\n                        neobot_soco_lite_sound_ti: '시',\n                        neobot_soco_lite_sound_half_note: '2분 음표',\n                        neobot_soco_lite_sound_quarter_note: '4분 음표',\n                        neobot_soco_lite_sound_eighth_note: '8분 음표',\n                        neobot_soco_lite_sound_sixteenth_note: '16분 음표',\n                        neobot_soco_lite_sensor_infrared: '적외선센서',\n                        neobot_soco_lite_sensor_light: '빛센서',\n                        neobot_soco_lite_sensor_sound: '소리센서',\n                        neobot_soco_lite_compare_symbol1: '＝',\n                        neobot_soco_lite_compare_symbol2: '＞',\n                        neobot_soco_lite_compare_symbol3: '＜',\n                        neobot_soco_lite_compare_symbol4: '≥',\n                        neobot_soco_lite_compare_symbol5: '≤',\n                        neobot_soco_lite_remote_btn_a: 'A',\n                        neobot_soco_lite_remote_btn_b: 'B',\n                        neobot_soco_lite_remote_btn_c: 'C',\n                        neobot_soco_lite_remote_btn_d: 'D',\n                        neobot_soco_lite_remote_btn_1: '1',\n                        neobot_soco_lite_remote_btn_2: '2',\n                        neobot_soco_lite_remote_btn_3: '3',\n                        neobot_soco_lite_remote_btn_4: '4',\n                        neobot_soco_lite_remote_btn_up: '▲',\n                        neobot_soco_lite_remote_btn_down: '▼',\n                        neobot_soco_lite_remote_btn_left: '◀',\n                        neobot_soco_lite_remote_btn_right: '▶',\n                        neobot_soco_lite_duration_cont: '계속',\n                        neobot_soco_lite_duration_1s: '1초',\n                        neobot_soco_lite_duration_2s: '2초',\n                        neobot_soco_lite_duration_3s: '3초',\n                        neobot_soco_lite_duration_4s: '4초',\n                        neobot_soco_lite_duration_5s: '5초',\n                        neobot_soco_lite_duration_6s: '6초',\n                        neobot_soco_lite_duration_7s: '7초',\n                        neobot_soco_lite_duration_8s: '8초',\n                        neobot_soco_lite_duration_9s: '9초',\n                        neobot_soco_lite_motor_both: '양쪽',\n                        neobot_soco_lite_motor_left: '왼쪽',\n                        neobot_soco_lite_motor_right: '오른쪽',\n                        neobot_soco_lite_motor_move_forward: '전진',\n                        neobot_soco_lite_motor_move_backward: '후진',\n                        neobot_soco_lite_motor_move_left: '좌회전',\n                        neobot_soco_lite_motor_move_right: '우회전',\n                        neobot_soco_lite_motor_move_stop: '정지',\n\n                        neobot_soco_lite_servo_dir_1: '정방향',\n                        neobot_soco_lite_servo_dir_2: '역방향',\n\n                        neobot_soco_lite_percent_10: '10%속도',\n                        neobot_soco_lite_percent_20: '20%속도',\n                        neobot_soco_lite_percent_30: '30%속도',\n                        neobot_soco_lite_percent_40: '40%속도',\n                        neobot_soco_lite_percent_50: '50%속도',\n                        neobot_soco_lite_percent_60: '60%속도',\n                        neobot_soco_lite_percent_70: '70%속도',\n                        neobot_soco_lite_percent_80: '80%속도',\n                        neobot_soco_lite_percent_90: '90%속도',\n                        neobot_soco_lite_percent_100: '100%속도',\n\n                        neobot_soco_lite_angle_0: '0도',\n                        neobot_soco_lite_angle_5: '5도',\n                        neobot_soco_lite_angle_10: '10도',\n                        neobot_soco_lite_angle_15: '15도',\n                        neobot_soco_lite_angle_20: '20도',\n                        neobot_soco_lite_angle_25: '25도',\n                        neobot_soco_lite_angle_30: '30도',\n                        neobot_soco_lite_angle_35: '35도',\n                        neobot_soco_lite_angle_40: '40도',\n                        neobot_soco_lite_angle_45: '45도',\n                        neobot_soco_lite_angle_50: '50도',\n                        neobot_soco_lite_angle_55: '55도',\n                        neobot_soco_lite_angle_60: '60도',\n                        neobot_soco_lite_angle_65: '65도',\n                        neobot_soco_lite_angle_70: '70도',\n                        neobot_soco_lite_angle_75: '75도',\n                        neobot_soco_lite_angle_80: '80도',\n                        neobot_soco_lite_angle_85: '85도',\n                        neobot_soco_lite_angle_90: '90도',\n                        neobot_soco_lite_angle_95: '95도',\n                        neobot_soco_lite_angle_100: '100도',\n                        neobot_soco_lite_angle_105: '105도',\n                        neobot_soco_lite_angle_110: '110도',\n                        neobot_soco_lite_angle_115: '115도',\n                        neobot_soco_lite_angle_120: '120도',\n                        neobot_soco_lite_angle_125: '125도',\n                        neobot_soco_lite_angle_130: '130도',\n                        neobot_soco_lite_angle_135: '135도',\n                        neobot_soco_lite_angle_140: '140도',\n                        neobot_soco_lite_angle_145: '145도',\n                        neobot_soco_lite_angle_150: '150도',\n                        neobot_soco_lite_angle_155: '155도',\n                        neobot_soco_lite_angle_160: '160도',\n                        neobot_soco_lite_angle_165: '165도',\n                        neobot_soco_lite_angle_170: '170도',\n                        neobot_soco_lite_angle_175: '175도',\n                        neobot_soco_lite_angle_180: '180도',\n\n                        neobot_soco_lite_out_all: '모든',\n                        neobot_soco_lite_direction_left: '왼쪽으로',\n                        neobot_soco_lite_direction_right: '오른쪽으로',\n                    },\n                },\n                en: {\n                    // en.js에 작성하던 내용\n                    template: {\n                        // sensor\n                        neobot_soco_lite_sensor_title: 'Sensor',\n                        neobot_soco_lite_sensor_value: '%1',\n                        neobot_soco_lite_sensor_convert_scale:\n                            \"%1 's changed value   range: %2 ~ %3 conversion: %4 ~ %5\",\n                        neobot_soco_lite_decision_sensor_is_over: '%1 %2 %3',\n                        neobot_soco_lite_decision_equal_with_sensor: \"%1 's color is %2\",\n                        neobot_soco_lite_decision_sensor_angle: '%1 angle %2 %3',\n                        neobot_soco_lite_remote_button: 'pressing button %1 of remote controller',\n\n                        // LED\n                        neobot_soco_lite_led_title: 'LED',\n                        neobot_soco_lite_arg_led_duration: '%1',\n                        neobot_soco_lite_led_on: 'Turn on the LED    %1 %2 %3 %4',\n                        neobot_soco_lite_output_led_off: 'Turn off the %1 LED %2',\n                        neobot_soco_lite_led_brightness_with_sensor:\n                            \"Control %2 LED's brightness with %1 sensor %3\",\n                        neobot_soco_lite_color_led_on:\n                            'Turn on the %1 color LED   R %2 G %3 B %4 %5',\n\n                        // output\n                        neobot_soco_lite_output_title: 'Set output',\n                        neobot_soco_lite_set_output: 'Output %2 value to %1 port %3',\n\n                        // motor\n                        neobot_soco_lite_motor_title: 'Motor',\n                        neobot_soco_lite_robot: 'Robot %1 %2',\n                        neobot_soco_lite_motor_start: 'Motor operation   %1 %2 %3 %4 %5',\n                        neobot_soco_lite_motor_stop: 'Stop the %1 motor(s) %2',\n                        neobot_soco_lite_arg_motor_speed: '%1',\n                        neobot_soco_lite_arg_motor_duration: '%1',\n\n                        // melody\n                        neobot_soco_lite_buzzer_title: 'Buzzer',\n                        neobot_soco_lite_play_note_for: 'Buzzer   octave: %1 scale: %2 note: %3 %4',\n                        neobot_soco_lite_melody_play_with_sensor:\n                            'Buzzer rings by %1 sensor value %2',\n                        neobot_soco_lite_melody_stop: 'Stop the buzzer %1',\n\n                        // servo\n                        neobot_soco_lite_servo_title: 'Servo motor',\n                        neobot_soco_lite_servo_init: 'Reset the %1 servo motor %2',\n                        neobot_soco_lite_servo_rotate: 'Rotate the servo motor   %1 %2 %3 %4',\n                        neobot_soco_lite_servo_stop: 'Stop the %1 servo motor %2',\n                        neobot_soco_lite_servo_change_degree: 'Change servo angle   %1 %2 %3 %4 %5',\n                    },\n                    Blocks: {\n                        //for dropdown\n                        neobot_soco_lite_port_1: 'IN1',\n                        neobot_soco_lite_port_2: 'IN2',\n                        neobot_soco_lite_port_3: 'IN3',\n                        neobot_soco_lite_port_4: 'IN4',\n                        neobot_soco_lite_port_12: 'IN1 & IN2',\n                        neobot_soco_lite_port_bat: 'battery',\n                        neobot_soco_lite_port_remot: 'remote',\n                        neobot_soco_lite_color_white: 'white',\n                        neobot_soco_lite_color_red: 'red',\n                        neobot_soco_lite_color_yellow: 'yellow',\n                        neobot_soco_lite_color_green: 'green',\n                        neobot_soco_lite_color_blue: 'blue',\n                        neobot_soco_lite_direction_forward: 'forward',\n                        neobot_soco_lite_direction_backward: 'backward',\n                        neobot_soco_lite_sound_silent: 'silent',\n                        neobot_soco_lite_sound_do: 'Do',\n                        neobot_soco_lite_sound_do_shop: 'Do#',\n                        neobot_soco_lite_sound_re: 'Re',\n                        neobot_soco_lite_sound_re_shop: 'Re#',\n                        neobot_soco_lite_sound_mi: 'Mi',\n                        neobot_soco_lite_sound_fa: 'Fa',\n                        neobot_soco_lite_sound_fa_shop: 'Fa#',\n                        neobot_soco_lite_sound_so: 'So',\n                        neobot_soco_lite_sound_so_shop: 'So#',\n                        neobot_soco_lite_sound_la: 'La',\n                        neobot_soco_lite_sound_la_shop: 'La#',\n                        neobot_soco_lite_sound_ti: 'Si',\n                        neobot_soco_lite_sound_half_note: 'a half note',\n                        neobot_soco_lite_sound_quarter_note: 'a quarter note',\n                        neobot_soco_lite_sound_eighth_note: 'a eighth note',\n                        neobot_soco_lite_sound_sixteenth_note: 'a sixteenth note',\n                        neobot_soco_lite_sensor_infrared: 'IR sensor',\n                        neobot_soco_lite_sensor_light: 'light sensor',\n                        neobot_soco_lite_sensor_sound: 'sound sensor',\n                        neobot_soco_lite_compare_symbol1: '＝',\n                        neobot_soco_lite_compare_symbol2: '＞',\n                        neobot_soco_lite_compare_symbol3: '＜',\n                        neobot_soco_lite_compare_symbol4: '≥',\n                        neobot_soco_lite_compare_symbol5: '≤',\n                        neobot_soco_lite_remote_btn_a: 'A',\n                        neobot_soco_lite_remote_btn_b: 'B',\n                        neobot_soco_lite_remote_btn_c: 'C',\n                        neobot_soco_lite_remote_btn_d: 'D',\n                        neobot_soco_lite_remote_btn_1: '1',\n                        neobot_soco_lite_remote_btn_2: '2',\n                        neobot_soco_lite_remote_btn_3: '3',\n                        neobot_soco_lite_remote_btn_4: '4',\n                        neobot_soco_lite_remote_btn_up: '▲',\n                        neobot_soco_lite_remote_btn_down: '▼',\n                        neobot_soco_lite_remote_btn_left: '◀',\n                        neobot_soco_lite_remote_btn_right: '▶',\n                        neobot_soco_lite_duration_cont: 'constantly',\n                        neobot_soco_lite_duration_1s: '1 second',\n                        neobot_soco_lite_duration_2s: '2 seconds',\n                        neobot_soco_lite_duration_3s: '3 seconds',\n                        neobot_soco_lite_duration_4s: '4 seconds',\n                        neobot_soco_lite_duration_5s: '5 seconds',\n                        neobot_soco_lite_duration_6s: '6 seconds',\n                        neobot_soco_lite_duration_7s: '7 seconds',\n                        neobot_soco_lite_duration_8s: '8 seconds',\n                        neobot_soco_lite_duration_9s: '9 seconds',\n                        neobot_soco_lite_motor_both: 'both',\n                        neobot_soco_lite_motor_left: 'left',\n                        neobot_soco_lite_motor_right: 'right',\n                        neobot_soco_lite_motor_move_forward: 'go forward',\n                        neobot_soco_lite_motor_move_backward: 'go backward',\n                        neobot_soco_lite_motor_move_left: 'turn Left',\n                        neobot_soco_lite_motor_move_right: 'turn Right',\n                        neobot_soco_lite_motor_move_stop: 'stop',\n\n                        neobot_soco_lite_servo_dir_1: 'forward',\n                        neobot_soco_lite_servo_dir_2: 'backward',\n\n                        neobot_soco_lite_percent_10: '10% speed',\n                        neobot_soco_lite_percent_20: '20% speed',\n                        neobot_soco_lite_percent_30: '30% speed',\n                        neobot_soco_lite_percent_40: '40% speed',\n                        neobot_soco_lite_percent_50: '50% speed',\n                        neobot_soco_lite_percent_60: '60% speed',\n                        neobot_soco_lite_percent_70: '70% speed',\n                        neobot_soco_lite_percent_80: '80% speed',\n                        neobot_soco_lite_percent_90: '90% speed',\n                        neobot_soco_lite_percent_100: '100% speed',\n\n                        neobot_soco_lite_angle_0: '0 degree',\n                        neobot_soco_lite_angle_5: '5 degrees',\n                        neobot_soco_lite_angle_10: '10 degrees',\n                        neobot_soco_lite_angle_15: '15 degrees',\n                        neobot_soco_lite_angle_20: '20 degrees',\n                        neobot_soco_lite_angle_25: '25 degrees',\n                        neobot_soco_lite_angle_30: '30 degrees',\n                        neobot_soco_lite_angle_35: '35 degrees',\n                        neobot_soco_lite_angle_40: '40 degrees',\n                        neobot_soco_lite_angle_45: '45 degrees',\n                        neobot_soco_lite_angle_50: '50 degrees',\n                        neobot_soco_lite_angle_55: '55 degrees',\n                        neobot_soco_lite_angle_60: '60 degrees',\n                        neobot_soco_lite_angle_65: '65 degrees',\n                        neobot_soco_lite_angle_70: '70 degrees',\n                        neobot_soco_lite_angle_75: '75 degrees',\n                        neobot_soco_lite_angle_80: '80 degrees',\n                        neobot_soco_lite_angle_85: '85 degrees',\n                        neobot_soco_lite_angle_90: '90 degrees',\n                        neobot_soco_lite_angle_95: '95 degrees',\n                        neobot_soco_lite_angle_100: '100 degrees',\n                        neobot_soco_lite_angle_105: '105 degrees',\n                        neobot_soco_lite_angle_110: '110 degrees',\n                        neobot_soco_lite_angle_115: '115 degrees',\n                        neobot_soco_lite_angle_120: '120 degrees',\n                        neobot_soco_lite_angle_125: '125 degrees',\n                        neobot_soco_lite_angle_130: '130 degrees',\n                        neobot_soco_lite_angle_135: '135 degrees',\n                        neobot_soco_lite_angle_140: '140 degrees',\n                        neobot_soco_lite_angle_145: '145 degrees',\n                        neobot_soco_lite_angle_150: '150 degrees',\n                        neobot_soco_lite_angle_155: '155 degrees',\n                        neobot_soco_lite_angle_160: '160 degrees',\n                        neobot_soco_lite_angle_165: '165 degrees',\n                        neobot_soco_lite_angle_170: '170 degrees',\n                        neobot_soco_lite_angle_175: '175 degrees',\n                        neobot_soco_lite_angle_180: '180degrees',\n\n                        neobot_soco_lite_out_all: 'ALL',\n                        neobot_soco_lite_direction_left: 'to the left',\n                        neobot_soco_lite_direction_right: 'to the right',\n                    },\n                }, //\n            };\n        }\n\n        getBlocks = function() {\n            return {\n                /*************************\n                 * class neobot_soco_lite_sensor\n                 *************************/\n                neobot_soco_lite_sensor_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_soco_lite_sensor_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_soco_lite_sensor_title',\n                    },\n                    class: 'neobot_soco_lite_sensor',\n                    isNotFor: ['NeobotSocoLite'],\n                    events: {},\n                },\n                neobot_soco_lite_sensor_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_soco_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_soco_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_soco_lite_port_remot, 'IR'],\n                                [Lang.Blocks.neobot_soco_lite_port_bat, 'BAT'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_soco_lite_sensor_value',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_soco_lite_sensor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT');\n                        return Entry.NeobotSocoLite.localBuffer[port];\n                    },\n                },\n\n                neobot_soco_lite_sensor_convert_scale: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_soco_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_soco_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                        ],\n                        type: 'neobot_soco_lite_sensor_convert_scale',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        OMIN: 1,\n                        OMAX: 2,\n                        MIN: 3,\n                        MAX: 4,\n                    },\n                    class: 'neobot_soco_lite_sensor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT');\n                        let value = Entry.NeobotSocoLite.localBuffer[port];\n                        let omin = script.getNumberValue('OMIN', script);\n                        let omax = script.getNumberValue('OMAX', script);\n                        let min = script.getNumberValue('MIN', script);\n                        let max = script.getNumberValue('MAX', script);\n\n                        if (omin > omax) {\n                            var temp = omin;\n                            omin = omax;\n                            omax = temp;\n                        }\n\n                        if (min > max) {\n                            var temp = min;\n                            min = max;\n                            max = temp;\n                        }\n\n                        value -= omin;\n                        value = value * ((max - min) / (omax - omin));\n                        value += min;\n                        value = Math.min(max, value);\n                        value = Math.max(min, value);\n\n                        return Math.round(value);\n                    },\n                },\n                neobot_soco_lite_decision_sensor_is_over: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_soco_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_soco_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_soco_lite_port_12, 'IN12'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol1, '='],\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol2, '>'],\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol3, '<'],\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol4, '>='],\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol5, '<='],\n                            ],\n                            value: '>',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 10],\n                        type: 'neobot_soco_lite_decision_sensor_is_over',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        SYMBOL: 1,\n                        VALUE: 2,\n                    },\n                    class: 'neobot_soco_lite_sensor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const symbol = script.getStringField('SYMBOL');\n                        const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                        if (sensorTemp == 'IN12') {\n                            const sensor1 = Entry.NeobotSocoLite.localBuffer.IN1;\n                            const sensor2 = Entry.NeobotSocoLite.localBuffer.IN2;\n                            if (symbol == '=') {\n                                return sensor1 == value && sensor2 == value;\n                            } else if (symbol == '>') {\n                                return sensor1 > value && sensor2 > value;\n                            } else if (symbol == '<') {\n                                return sensor1 < value && sensor2 < value;\n                            } else if (symbol == '>=') {\n                                return sensor1 >= value && sensor2 >= value;\n                            } else if (symbol == '<=') {\n                                return sensor1 <= value && sensor2 <= value;\n                            }\n                        } else {\n                            const sensor = Entry.NeobotSocoLite.localBuffer[sensorTemp];\n                            if (symbol == '=') {\n                                if (sensor == value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '>') {\n                                if (sensor > value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '<') {\n                                if (sensor < value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '>=') {\n                                if (sensor >= value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '<=') {\n                                if (sensor <= value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            }\n                        }\n                        return false;\n                    },\n                },\n\n                neobot_soco_lite_decision_equal_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_soco_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_soco_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_color_white, 0],\n                                [Lang.Blocks.neobot_soco_lite_color_red, 1],\n                                [Lang.Blocks.neobot_soco_lite_color_yellow, 2],\n                                [Lang.Blocks.neobot_soco_lite_color_green, 3],\n                                [Lang.Blocks.neobot_soco_lite_color_blue, 4],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_soco_lite_decision_equal_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        COLOR: 1,\n                    },\n                    class: 'neobot_soco_lite_sensor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const sensor = Entry.NeobotSocoLite.localBuffer[sensorTemp];\n                        const color = script.getNumberField('COLOR');\n\n                        if (sensor >= 10 && sensor <= 50) {\n                            if (color == 0) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 51 && sensor <= 90) {\n                            if (color == 1) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 91 && sensor <= 130) {\n                            if (color == 2) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 131 && sensor <= 170) {\n                            if (color == 3) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 171 && sensor <= 210) {\n                            if (color == 4) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        }\n                        return false;\n                    },\n                },\n\n                neobot_soco_lite_decision_sensor_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#FFFFFF',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_soco_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_soco_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol1, '='],\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol2, '>'],\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol3, '<'],\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol4, '>='],\n                                [Lang.Blocks.neobot_soco_lite_compare_symbol5, '<='],\n                            ],\n                            value: '>',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_angle_0, '0'],\n                                [Lang.Blocks.neobot_soco_lite_angle_10, '10'],\n                                [Lang.Blocks.neobot_soco_lite_angle_20, '20'],\n                                [Lang.Blocks.neobot_soco_lite_angle_30, '30'],\n                                [Lang.Blocks.neobot_soco_lite_angle_40, '40'],\n                                [Lang.Blocks.neobot_soco_lite_angle_50, '50'],\n                                [Lang.Blocks.neobot_soco_lite_angle_60, '60'],\n                                [Lang.Blocks.neobot_soco_lite_angle_70, '70'],\n                                [Lang.Blocks.neobot_soco_lite_angle_80, '80'],\n                                [Lang.Blocks.neobot_soco_lite_angle_90, '90'],\n                                [Lang.Blocks.neobot_soco_lite_angle_100, '100'],\n                                [Lang.Blocks.neobot_soco_lite_angle_110, '110'],\n                                [Lang.Blocks.neobot_soco_lite_angle_120, '120'],\n                                [Lang.Blocks.neobot_soco_lite_angle_130, '130'],\n                                [Lang.Blocks.neobot_soco_lite_angle_140, '140'],\n                                [Lang.Blocks.neobot_soco_lite_angle_150, '150'],\n                                [Lang.Blocks.neobot_soco_lite_angle_160, '160'],\n                                [Lang.Blocks.neobot_soco_lite_angle_170, '170'],\n                                [Lang.Blocks.neobot_soco_lite_angle_180, '180'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neobot_soco_lite_decision_sensor_angle',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        SYMBOL: 1,\n                        VALUE: 2,\n                    },\n                    class: 'neobot_soco_lite_sensor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const sensor = Entry.NeobotSocoLite.localBuffer[sensorTemp];\n                        const symbol = script.getStringField('SYMBOL');\n                        const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                        if (symbol == '=') {\n                            if (sensor == value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '>') {\n                            if (sensor > value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '<') {\n                            if (sensor < value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '>=') {\n                            if (sensor >= value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '<=') {\n                            if (sensor <= value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        }\n                        return false;\n                    },\n                },\n\n                neobot_soco_lite_remote_button: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#FFFFFF',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_remote_btn_1, '10'],\n                                [Lang.Blocks.neobot_soco_lite_remote_btn_2, '11'],\n                                [Lang.Blocks.neobot_soco_lite_remote_btn_3, '12'],\n                                [Lang.Blocks.neobot_soco_lite_remote_btn_4, '13'],\n                                [Lang.Blocks.neobot_soco_lite_remote_btn_up, '1'],\n                                [Lang.Blocks.neobot_soco_lite_remote_btn_down, '2'],\n                                [Lang.Blocks.neobot_soco_lite_remote_btn_left, '3'],\n                                [Lang.Blocks.neobot_soco_lite_remote_btn_right, '4'],\n                            ],\n                            value: '10',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_soco_lite_remote_button',\n                    },\n                    paramsKeyMap: {\n                        KEY: 0,\n                    },\n                    class: 'neobot_soco_lite_sensor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const key = script.getNumberField('KEY');\n                        const value = Entry.NeobotSocoLite.localBuffer.IR;\n                        if (key == value) {\n                            return true;\n                        } else {\n                            return false;\n                        }\n                    },\n                },\n\n                /*************************\n                 * class neobot_soco_lite_led\n                 *************************/\n                neobot_soco_lite_led_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_soco_lite_led_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_soco_lite_led_title',\n                    },\n                    class: 'neobot_soco_lite_led',\n                    isNotFor: ['NeobotSocoLite'],\n                    events: {},\n                },\n                neobot_soco_lite_led_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['100%', '255'],\n                                ['90%', '230'],\n                                ['80%', '204'],\n                                ['70%', '179'],\n                                ['60%', '153'],\n                                ['50%', '128'],\n                                ['40%', '102'],\n                                ['30%', '77'],\n                                ['20%', '51'],\n                                ['10%', '26'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neobot_soco_lite_arg_led_duration',\n                                id: 'm311',\n                            },\n                            null,\n                        ],\n                        type: 'neobot_soco_lite_led_on',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neobot_soco_lite_led',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const value = script.getNumberField('VALUE', script);\n                            const duration = script.getStringValue('DURATION', script);\n\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print('=== neobot_soco_lite_led_on ===', 'speak');\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`brightness : ${value}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            if (\n                                duration != '계속' &&\n                                duration != 'constantly' &&\n                                Entry.parseNumber(duration) <= 0\n                            ) {\n                                return script.callReturn();\n                            }\n\n                            if (port == 'ALL') {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT1 = value;\n                                Entry.NeobotSocoLite.remoteBuffer.OUT2 = value;\n                                Entry.NeobotSocoLite.remoteBuffer.OUT3 = value;\n                            } else {\n                                Entry.NeobotSocoLite.remoteBuffer[port] = value;\n                            }\n\n                            if (duration == '계속' || duration == 'constantly') {\n                                return script.callReturn();\n                            }\n\n                            const durationValue = Entry.parseNumber(duration);\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            setTimeout(() => {\n                                if (port == 'ALL') {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT1 = 0;\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT2 = 0;\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT3 = 0;\n                                } else {\n                                    Entry.NeobotSocoLite.remoteBuffer[port] = 0;\n                                }\n                                if (Entry.NeobotSocoLite.log_to_console) {\n                                    Entry.console.print('neobot_soco_lite_led_on : 0', 'speak');\n                                }\n                                script.timeFlag = 0;\n                            }, durationValue * 1000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                neobot_soco_lite_output_led_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_soco_lite_output_led_off',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_soco_lite_led',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print('=== neobot_soco_lite_output_led_off ===', 'speak');\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotSocoLite.remoteBuffer.OUT1 = 0;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT2 = 0;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT3 = 0;\n                        } else {\n                            Entry.NeobotSocoLite.remoteBuffer[port] = 0;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_soco_lite_led_brightness_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neobot_soco_lite_led_brightness_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        IN: 0,\n                        OUT: 1,\n                    },\n                    class: 'neobot_soco_lite_led',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const inPort = script.getStringField('IN', script);\n                        const outPort = script.getStringField('OUT', script);\n                        let value = Entry.NeobotSocoLite.localBuffer[inPort];\n\n                        // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함.\n                        value = Math.max(value, 0);\n                        value = Math.min(value, 100);\n                        value = Math.ceil((value / 100) * 255);\n\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_soco_lite_led_brightness_with_sensor ===',\n                                'speak'\n                            );\n                            Entry.console.print(`out port : ${outPort}`, 'speak');\n                            Entry.console.print(`in port : ${inPort}`, 'speak');\n                            Entry.console.print(\n                                `sensor value : ${Entry.NeobotSocoLite.localBuffer[inPort]}`,\n                                'speak'\n                            );\n                            Entry.console.print(`output value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (outPort == 'ALL') {\n                            Entry.NeobotSocoLite.remoteBuffer.OUT1 = value;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT2 = value;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT3 = value;\n                        } else {\n                            Entry.NeobotSocoLite.remoteBuffer[outPort] = value;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_soco_lite_color_led_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            null,\n                        ],\n                        type: 'neobot_soco_lite_color_led_on',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        RED: 1,\n                        GREEN: 2,\n                        BLUE: 3,\n                    },\n                    class: 'neobot_soco_lite_led',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT');\n                            let red = script.getNumberValue('RED');\n                            let green = script.getNumberValue('GREEN');\n                            let blue = script.getNumberValue('BLUE');\n\n                            let out1 = false;\n                            let out2 = false;\n                            let out3 = false;\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            } else {\n                                out1 = port == 'OUT1';\n                                out2 = port == 'OUT2';\n                                out3 = port == 'OUT3';\n                            }\n\n                            red = Math.max(red, 1);\n                            red = Math.min(red, 251);\n                            green = Math.max(green, 1);\n                            green = Math.min(green, 251);\n                            blue = Math.max(blue, 1);\n                            blue = Math.min(blue, 251);\n\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_soco_lite_color_led_on ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`red : ${red}`, 'speak');\n                                Entry.console.print(`green : ${green}`, 'speak');\n                                Entry.console.print(`blue : ${blue}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            const valRed = 252;\n                            const valGreen = 253;\n                            const valBlue = 254;\n                            const valAccept = 255;\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            if (out1) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT1 = valRed;\n                            }\n                            if (out2) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT2 = valRed;\n                            }\n                            if (out3) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT3 = valRed;\n                            }\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_soco_lite_color_led_on : ${valRed}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                // set red\n                                if (out1) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT1 = red;\n                                }\n                                if (out2) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT2 = red;\n                                }\n                                if (out3) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT3 = red;\n                                }\n                                if (Entry.NeobotSocoLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_soco_lite_color_led_on : ${red}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    // choose green\n                                    if (out1) {\n                                        Entry.NeobotSocoLite.remoteBuffer.OUT1 = valGreen;\n                                    }\n                                    if (out2) {\n                                        Entry.NeobotSocoLite.remoteBuffer.OUT2 = valGreen;\n                                    }\n                                    if (out3) {\n                                        Entry.NeobotSocoLite.remoteBuffer.OUT3 = valGreen;\n                                    }\n                                    if (Entry.NeobotSocoLite.log_to_console) {\n                                        Entry.console.print(\n                                            `neobot_soco_lite_color_led_on : ${valGreen}`,\n                                            'speak'\n                                        );\n                                    }\n                                    setTimeout(() => {\n                                        // set green\n                                        if (out1) {\n                                            Entry.NeobotSocoLite.remoteBuffer.OUT1 = green;\n                                        }\n                                        if (out2) {\n                                            Entry.NeobotSocoLite.remoteBuffer.OUT2 = green;\n                                        }\n                                        if (out3) {\n                                            Entry.NeobotSocoLite.remoteBuffer.OUT3 = green;\n                                        }\n                                        if (Entry.NeobotSocoLite.log_to_console) {\n                                            Entry.console.print(\n                                                `neobot_soco_lite_color_led_on : ${green}`,\n                                                'speak'\n                                            );\n                                        }\n                                        setTimeout(() => {\n                                            // choose blue\n                                            if (out1) {\n                                                Entry.NeobotSocoLite.remoteBuffer.OUT1 = valBlue;\n                                            }\n                                            if (out2) {\n                                                Entry.NeobotSocoLite.remoteBuffer.OUT2 = valBlue;\n                                            }\n                                            if (out3) {\n                                                Entry.NeobotSocoLite.remoteBuffer.OUT3 = valBlue;\n                                            }\n                                            if (Entry.NeobotSocoLite.log_to_console) {\n                                                Entry.console.print(\n                                                    `neobot_soco_lite_color_led_on : ${valBlue}`,\n                                                    'speak'\n                                                );\n                                            }\n                                            setTimeout(() => {\n                                                // set blue\n                                                if (out1) {\n                                                    Entry.NeobotSocoLite.remoteBuffer.OUT1 = blue;\n                                                }\n                                                if (out2) {\n                                                    Entry.NeobotSocoLite.remoteBuffer.OUT2 = blue;\n                                                }\n                                                if (out3) {\n                                                    Entry.NeobotSocoLite.remoteBuffer.OUT3 = blue;\n                                                }\n                                                if (Entry.NeobotSocoLite.log_to_console) {\n                                                    Entry.console.print(\n                                                        `neobot_soco_lite_color_led_on : ${blue}`,\n                                                        'speak'\n                                                    );\n                                                }\n                                                setTimeout(() => {\n                                                    // accept\n                                                    if (out1) {\n                                                        Entry.NeobotSocoLite.remoteBuffer.OUT1 = valAccept;\n                                                    }\n                                                    if (out2) {\n                                                        Entry.NeobotSocoLite.remoteBuffer.OUT2 = valAccept;\n                                                    }\n                                                    if (out3) {\n                                                        Entry.NeobotSocoLite.remoteBuffer.OUT3 = valAccept;\n                                                    }\n                                                    if (Entry.NeobotSocoLite.log_to_console) {\n                                                        Entry.console.print(\n                                                            `neobot_soco_lite_color_led_on : ${valAccept}`,\n                                                            'speak'\n                                                        );\n                                                    }\n                                                    setTimeout(() => {\n                                                        // final delay\n                                                        script.timeFlag = 0;\n                                                    }, 200);\n                                                }, 200);\n                                            }, 200);\n                                        }, 200);\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                /*************************\n                 * class neobot_soco_lite_output\n                 *************************/\n                neobot_soco_lite_output_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_soco_lite_output_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_soco_lite_output_title',\n                    },\n                    class: 'neobot_soco_lite_output',\n                    isNotFor: ['NeobotSocoLite'],\n                    events: {},\n                },\n                neobot_soco_lite_set_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            null,\n                        ],\n                        type: 'neobot_soco_lite_set_output',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                    },\n                    class: 'neobot_soco_lite_output',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        let value = script.getNumberValue('VALUE', script);\n                        if (value < 0) {\n                            value = 0;\n                        } else if (value > 255) {\n                            value = 255;\n                        }\n\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print('=== neobot_soco_lite_set_output ===', 'speak');\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotSocoLite.remoteBuffer.OUT1 = value;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT2 = value;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT3 = value;\n                        } else {\n                            Entry.NeobotSocoLite.remoteBuffer[port] = value;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_soco_lite_motor\n                 *************************/\n                neobot_soco_lite_motor_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_soco_lite_motor_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_soco_lite_motor_title',\n                    },\n                    class: 'neobot_soco_lite_motor',\n                    isNotFor: ['NeobotSocoLite'],\n                    events: {},\n                },\n                neobot_soco_lite_robot: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_motor_move_forward, '1'],\n                                [Lang.Blocks.neobot_soco_lite_motor_move_backward, '2'],\n                                [Lang.Blocks.neobot_soco_lite_motor_move_left, '3'],\n                                [Lang.Blocks.neobot_soco_lite_motor_move_right, '4'],\n                                [Lang.Blocks.neobot_soco_lite_motor_move_stop, '5'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_soco_lite_robot',\n                    },\n                    paramsKeyMap: {\n                        MOVE: 0,\n                    },\n                    class: 'neobot_soco_lite_motor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const move = script.getNumberField('MOVE');\n                        let leftValue;\n                        let rightValue;\n                        switch (move) {\n                            case 1:\n                                leftValue = 0x10 + 10;\n                                rightValue = 0x10 + 10;\n                                break;\n                            case 2:\n                                leftValue = 0x20 + 10;\n                                rightValue = 0x20 + 10;\n                                break;\n                            case 3:\n                                leftValue = 0x20 + 5;\n                                rightValue = 0x10 + 5;\n                                break;\n                            case 4:\n                                leftValue = 0x10 + 5;\n                                rightValue = 0x20 + 5;\n                                break;\n                            case 5:\n                                leftValue = 0;\n                                rightValue = 0;\n                                break;\n                        }\n\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print('=== neobot_soco_lite_robot ===', 'speak');\n                            Entry.console.print(`move : ${move}`, 'speak');\n                            Entry.console.print(`left value : ${leftValue}`, 'speak');\n                            Entry.console.print(`right value : ${rightValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotSocoLite.remoteBuffer.DCL = leftValue;\n                        Entry.NeobotSocoLite.remoteBuffer.DCR = rightValue;\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_soco_lite_motor_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_motor_both, '1'],\n                                [Lang.Blocks.neobot_soco_lite_motor_left, '2'],\n                                [Lang.Blocks.neobot_soco_lite_motor_right, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_direction_forward, '1'],\n                                [Lang.Blocks.neobot_soco_lite_direction_backward, '2'],\n                                [Lang.Blocks.neobot_soco_lite_direction_left, '3'],\n                                [Lang.Blocks.neobot_soco_lite_direction_right, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neobot_soco_lite_arg_motor_speed',\n                                id: 'm411',\n                            },\n                            {\n                                type: 'neobot_soco_lite_arg_motor_duration',\n                                id: 'm412',\n                            },\n                            null,\n                        ],\n                        type: 'neobot_soco_lite_motor_start',\n                    },\n                    paramsKeyMap: {\n                        MOTOR: 0,\n                        DIRECTION: 1,\n                        SPEED: 2,\n                        DURATION: 3,\n                    },\n                    class: 'neobot_soco_lite_motor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const motor = script.getStringField('MOTOR', script);\n                            const direction = script.getStringField('DIRECTION', script);\n                            const speed = script.getStringValue('SPEED', script);\n                            const duration = script.getStringValue('DURATION', script);\n\n                            if (\n                                duration != '계속' &&\n                                duration != 'constantly' &&\n                                Entry.parseNumber(duration) <= 0\n                            ) {\n                                return script.callReturn();\n                            }\n\n                            let moveLeft = false;\n                            let moveRight = false;\n                            if (motor == 1) {\n                                moveLeft = true;\n                                moveRight = true;\n                            } else if (motor == 2) {\n                                moveLeft = true;\n                            } else {\n                                moveRight = true;\n                            }\n\n                            let leftDirectionValue;\n                            let rightDirectionValue;\n                            if (direction == 1) {\n                                leftDirectionValue = 0x10;\n                                rightDirectionValue = 0x10;\n                            } else if (direction == 2) {\n                                leftDirectionValue = 0x20;\n                                rightDirectionValue = 0x20;\n                            } else if (direction == 3) {\n                                leftDirectionValue = 0x20;\n                                rightDirectionValue = 0x10;\n                            } else {\n                                leftDirectionValue = 0x10;\n                                rightDirectionValue = 0x20;\n                            }\n\n                            // edited 210421, 0~100 을 0~15로 변환, 100 이상은 최대값(15)으로 처리함.\n                            let speedValue = 0;\n                            if (Entry.Utils.isNumber(speed)) {\n                                speedValue = Entry.parseNumber(speed);\n                            } else {\n                                speedValue = Entry.NeobotSocoLite.localBuffer[speed];\n                            }\n                            speedValue = Math.max(speedValue, 0);\n                            speedValue = Math.min(speedValue, 100);\n                            speedValue = Math.ceil((speedValue / 100) * 15);\n\n                            const leftOutValue = leftDirectionValue + speedValue;\n                            const rightOutValue = rightDirectionValue + speedValue;\n\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_soco_lite_motor_start ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`motor : ${motor}`, 'speak');\n                                Entry.console.print(`direction : ${direction}`, 'speak');\n                                Entry.console.print(`speed : ${speed}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print(\n                                    `left direction value : ${leftDirectionValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print(\n                                    `right direction value : ${rightDirectionValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print(`speed value : ${speedValue}`, 'speak');\n                                Entry.console.print(`left output value : ${leftOutValue}`, 'speak');\n                                Entry.console.print(\n                                    `right output value : ${rightOutValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            if (moveLeft) {\n                                Entry.NeobotSocoLite.remoteBuffer.DCL = leftOutValue;\n                            }\n                            if (moveRight) {\n                                Entry.NeobotSocoLite.remoteBuffer.DCR = rightOutValue;\n                            }\n\n                            if (duration == '계속' || duration == 'constantly') {\n                                return script.callReturn();\n                            }\n\n                            const durationValue = Entry.parseNumber(duration);\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            setTimeout(() => {\n                                Entry.NeobotSocoLite.remoteBuffer.DCL = 0;\n                                Entry.NeobotSocoLite.remoteBuffer.DCR = 0;\n                                if (Entry.NeobotSocoLite.log_to_console) {\n                                    Entry.console.print(\n                                        'neobot_soco_lite_motor_start : 0',\n                                        'speak'\n                                    );\n                                }\n                                script.timeFlag = 0;\n                            }, durationValue * 1000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                neobot_soco_lite_motor_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_motor_both, '1'],\n                                [Lang.Blocks.neobot_soco_lite_motor_left, '2'],\n                                [Lang.Blocks.neobot_soco_lite_motor_right, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_soco_lite_motor_stop',\n                    },\n                    paramsKeyMap: {\n                        MOTOR: 0,\n                    },\n                    class: 'neobot_soco_lite_motor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const motor = script.getNumberField('MOTOR');\n\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print('=== neobot_soco_lite_motor_stop ===', 'speak');\n                            Entry.console.print(`motor : ${motor}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (motor == 1) {\n                            Entry.NeobotSocoLite.remoteBuffer.DCL = 0;\n                            Entry.NeobotSocoLite.remoteBuffer.DCR = 0;\n                        } else if (motor == 2) {\n                            Entry.NeobotSocoLite.remoteBuffer.DCL = 0;\n                        } else {\n                            Entry.NeobotSocoLite.remoteBuffer.DCR = 0;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_soco_lite_melody\n                 *************************/\n                neobot_soco_lite_buzzer_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_soco_lite_buzzer_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_soco_lite_buzzer_title',\n                    },\n                    class: 'neobot_soco_lite_melody',\n                    isNotFor: ['NeobotSocoLite'],\n                    events: {},\n                },\n                neobot_soco_lite_play_note_for: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_sound_silent, '0'],\n                                [Lang.Blocks.neobot_soco_lite_sound_do, '1'],\n                                [Lang.Blocks.neobot_soco_lite_sound_do_shop, '2'],\n                                [Lang.Blocks.neobot_soco_lite_sound_re, '3'],\n                                [Lang.Blocks.neobot_soco_lite_sound_re_shop, '4'],\n                                [Lang.Blocks.neobot_soco_lite_sound_mi, '5'],\n                                [Lang.Blocks.neobot_soco_lite_sound_fa, '6'],\n                                [Lang.Blocks.neobot_soco_lite_sound_fa_shop, '7'],\n                                [Lang.Blocks.neobot_soco_lite_sound_so, '8'],\n                                [Lang.Blocks.neobot_soco_lite_sound_so_shop, '9'],\n                                [Lang.Blocks.neobot_soco_lite_sound_la, '10'],\n                                [Lang.Blocks.neobot_soco_lite_sound_la_shop, '11'],\n                                [Lang.Blocks.neobot_soco_lite_sound_ti, '12'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                                ['6', '5'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_sound_half_note, '2'],\n                                [Lang.Blocks.neobot_soco_lite_sound_quarter_note, '4'],\n                                [Lang.Blocks.neobot_soco_lite_sound_eighth_note, '8'],\n                                [Lang.Blocks.neobot_soco_lite_sound_sixteenth_note, '16'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '2', '4', null],\n                        type: 'neobot_soco_lite_play_note_for',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                        OCTAVE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neobot_soco_lite_melody',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const note = script.getNumberField('NOTE', script);\n                            const octave = script.getNumberField('OCTAVE', script);\n                            const duration = script.getNumberField('DURATION', script);\n                            let value = note > 0 ? note + 12 * octave : 0;\n\n                            value = Math.min(value, 72);\n\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_soco_lite_play_note_for ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`note : ${note}`, 'speak');\n                                Entry.console.print(`octave : ${octave}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print(`value : ${value}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            Entry.NeobotSocoLite.remoteBuffer.SND = value;\n                            setTimeout(() => {\n                                Entry.NeobotSocoLite.remoteBuffer.SND = 0;\n                                if (Entry.NeobotSocoLite.log_to_console) {\n                                    Entry.console.print(\n                                        'neobot_soco_lite_play_note_for : 0',\n                                        'speak'\n                                    );\n                                }\n                                script.timeFlag = 0;\n                            }, (1 / duration) * 2000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                neobot_soco_lite_melody_play_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_soco_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_soco_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_soco_lite_melody_play_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                    },\n                    class: 'neobot_soco_lite_melody',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const input = script.getStringField('INPUT');\n                        let value = Entry.NeobotSocoLite.localBuffer[input];\n\n                        // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함.\n                        value = Math.max(value, 0);\n                        value = Math.min(value, 100);\n                        value = Math.ceil((value / 100) * 65);\n\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_soco_lite_melody_play_with_sensor ===',\n                                'speak'\n                            );\n                            Entry.console.print(`input : ${input}`, 'speak');\n                            Entry.console.print(`value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotSocoLite.remoteBuffer.SND = value;\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_soco_lite_melody_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_soco_lite_melody_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'neobot_soco_lite_melody',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print('=== neobot_soco_lite_melody_stop ===', 'speak');\n                            Entry.console.print('value : 0', 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotSocoLite.remoteBuffer.SND = 0;\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_soco_lite_servo\n                 *************************/\n                neobot_soco_lite_servo_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_soco_lite_servo_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_soco_lite_servo_title',\n                    },\n                    class: 'neobot_soco_lite_servo',\n                    isNotFor: ['NeobotSocoLite'],\n                    events: {},\n                },\n                neobot_soco_lite_servo_init: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_soco_lite_servo_init',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_soco_lite_servo',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const resetValue = 186;\n                            const initValue = 1;\n\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print('=== neobot_soco_lite_servo_init ===', 'speak');\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            let out1 = port == 'OUT1';\n                            let out2 = port == 'OUT2';\n                            let out3 = port == 'OUT3';\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            if (out1) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT1 = resetValue;\n                            }\n                            if (out2) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT2 = resetValue;\n                            }\n                            if (out3) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT3 = resetValue;\n                            }\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_soco_lite_servo_init : ${resetValue}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                if (out1) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT1 = initValue;\n                                }\n                                if (out2) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT2 = initValue;\n                                }\n                                if (out3) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT3 = initValue;\n                                }\n                                if (Entry.NeobotSocoLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_soco_lite_servo_init : ${initValue}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    script.timeFlag = 0;\n                                }, 100);\n                            }, 200);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                neobot_soco_lite_servo_rotate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_servo_dir_1, '1'],\n                                [Lang.Blocks.neobot_soco_lite_servo_dir_2, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['0%', 0],\n                                ['10%', 10],\n                                ['20%', 20],\n                                ['30%', 30],\n                                ['40%', 40],\n                                ['50%', 50],\n                                ['60%', 60],\n                                ['70%', 70],\n                                ['80%', 80],\n                                ['90%', 90],\n                                ['100%', 100],\n                            ],\n                            value: 50,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'neobot_soco_lite_servo_rotate',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        DIRECTION: 1,\n                        SPEED: 2,\n                    },\n                    class: 'neobot_soco_lite_servo',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        const direction = script.getNumberField('DIRECTION');\n                        const speed = script.getStringField('SPEED');\n\n                        let directionValue = 192; // 정방향\n                        if (direction == 2) {\n                            directionValue = 208; // 역방향\n                        }\n                        let speedValue;\n                        if (Entry.Utils.isNumber(speed)) {\n                            speedValue = Entry.parseNumber(speed);\n                        } else {\n                            speedValue = Entry.NeobotSocoLite.localBuffer[speed];\n                        }\n\n                        // edited 210421, 0~100 을 0~10 으로 변환\n                        speedValue = Math.max(speedValue, 0);\n                        speedValue = Math.min(speedValue, 100);\n                        speedValue = Math.ceil(speedValue / 10);\n\n                        let outValue = directionValue + speedValue;\n                        if (outValue == directionValue) {\n                            outValue = 254;\n                        } else {\n                            outValue = outValue - 1;\n                        }\n\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print('=== neobot_soco_lite_servo_rotate ===');\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`direction : ${direction}`, 'speak');\n                            Entry.console.print(`speed : ${speed}`, 'speak');\n                            Entry.console.print(`direction value : ${directionValue}`, 'speak');\n                            Entry.console.print(`speed value : ${speedValue}`, 'speak');\n                            Entry.console.print(`output value : ${outValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotSocoLite.remoteBuffer.OUT1 = outValue;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT2 = outValue;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT3 = outValue;\n                        } else {\n                            Entry.NeobotSocoLite.remoteBuffer[port] = outValue;\n                        }\n                        return script.callReturn();\n                    },\n                },\n                neobot_soco_lite_servo_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_soco_lite_servo_stop',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_soco_lite_servo',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        const outValue = 254;\n\n                        if (Entry.NeobotSocoLite.log_to_console) {\n                            Entry.console.print('=== neobot_soco_lite_servo_stop ===', 'speak');\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`output value: ${outValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotSocoLite.remoteBuffer.OUT1 = outValue;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT2 = outValue;\n                            Entry.NeobotSocoLite.remoteBuffer.OUT3 = outValue;\n                        } else {\n                            Entry.NeobotSocoLite.remoteBuffer[port] = outValue;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                neobot_soco_lite_servo_change_degree: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_soco_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_servo_dir_1, '1'],\n                                [Lang.Blocks.neobot_soco_lite_servo_dir_2, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['0%', 0],\n                                ['10%', 10],\n                                ['20%', 20],\n                                ['30%', 30],\n                                ['40%', 40],\n                                ['50%', 50],\n                                ['60%', 60],\n                                ['70%', 70],\n                                ['80%', 80],\n                                ['90%', 90],\n                                ['100%', 100],\n                            ],\n                            value: 50,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'get_servo_degree',\n                                id: 'm211',\n                            },\n                            null,\n                            null,\n                            null,\n                            null,\n                        ],\n                        type: 'neobot_soco_lite_servo_change_degree',\n                    },\n                    paramsKeyMap: {\n                        DEGREE: 0,\n                        PORT: 1,\n                        DIRECTION: 2,\n                        SPEED: 3,\n                    },\n                    class: 'neobot_soco_lite_servo',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const direction = script.getNumberField('DIRECTION');\n                            const speed = script.getStringValue('SPEED');\n                            const degree = script.getStringValue('DEGREE');\n\n                            let out1 = port == 'OUT1';\n                            let out2 = port == 'OUT2';\n                            let out3 = port == 'OUT3';\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            }\n\n                            let directionValue = 188;\n                            if (direction == 2) {\n                                directionValue = 189;\n                            }\n\n                            let speedValue;\n                            if (Entry.Utils.isNumber(speed)) {\n                                speedValue = Entry.parseNumber(speed);\n                            } else {\n                                speedValue = Entry.NeobotSocoLite.localBuffer[speed];\n                            }\n\n                            // edited 210421, 0~100 을 240~250 으로 변환\n                            speedValue = Math.max(speedValue, 0);\n                            speedValue = Math.min(speedValue, 100);\n                            speedValue = Math.ceil(speedValue / 10) + 240;\n\n                            let degreeValue;\n                            if (Entry.Utils.isNumber(degree)) {\n                                degreeValue = Entry.parseNumber(degree);\n                            } else {\n                                if (degree == 'IN1' || degree == 'IN2' || degree == 'IN3') {\n                                    degreeValue = Entry.NeobotSocoLite.localBuffer[degree];\n                                } else {\n                                    degreeValue = 0;\n                                }\n                            }\n                            // edited 210421, 별도의 변환없이 그대로 사용함\n                            degreeValue = Math.max(degreeValue, 0);\n                            degreeValue = Math.min(degreeValue, 180);\n                            degreeValue = degreeValue + 1;\n\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_soco_lite_servo_change_degree ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`direction : ${direction}`, 'speak');\n                                Entry.console.print(`speed : ${speed}`, 'speak');\n                                Entry.console.print(`degree : ${degree}`, 'speak');\n                                Entry.console.print(`directionValue : ${directionValue}`, 'speak');\n                                Entry.console.print(`speedValue : ${speedValue}`, 'speak');\n                                Entry.console.print(`degreeValue : ${degreeValue}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            // direction\n                            if (out1) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT1 = directionValue;\n                            }\n                            if (out2) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT2 = directionValue;\n                            }\n                            if (out3) {\n                                Entry.NeobotSocoLite.remoteBuffer.OUT3 = directionValue;\n                            }\n                            if (Entry.NeobotSocoLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_soco_lite_servo_change_degree : ${directionValue}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                // speed\n                                if (out1) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT1 = speedValue;\n                                }\n                                if (out2) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT2 = speedValue;\n                                }\n                                if (out3) {\n                                    Entry.NeobotSocoLite.remoteBuffer.OUT3 = speedValue;\n                                }\n                                if (Entry.NeobotSocoLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_soco_lite_servo_change_degree : ${speedValue}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    // degree\n                                    if (out1) {\n                                        Entry.NeobotSocoLite.remoteBuffer.OUT1 = degreeValue;\n                                    }\n                                    if (out2) {\n                                        Entry.NeobotSocoLite.remoteBuffer.OUT2 = degreeValue;\n                                    }\n                                    if (out3) {\n                                        Entry.NeobotSocoLite.remoteBuffer.OUT3 = degreeValue;\n                                    }\n                                    if (Entry.NeobotSocoLite.log_to_console) {\n                                        Entry.console.print(\n                                            `neobot_soco_lite_servo_change_degree : ${degreeValue}`,\n                                            'speak'\n                                        );\n                                    }\n                                    setTimeout(() => {\n                                        // final delay\n                                        script.timeFlag = 0;\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                /*****************\n                 * ARG Blocks\n                 *****************/\n                neobot_soco_lite_arg_led_duration: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_duration_cont, '계속'],\n                                [Lang.Blocks.neobot_soco_lite_duration_1s, '1'],\n                                [Lang.Blocks.neobot_soco_lite_duration_2s, '2'],\n                                [Lang.Blocks.neobot_soco_lite_duration_3s, '3'],\n                                [Lang.Blocks.neobot_soco_lite_duration_4s, '4'],\n                                [Lang.Blocks.neobot_soco_lite_duration_5s, '5'],\n                                [Lang.Blocks.neobot_soco_lite_duration_6s, '6'],\n                                [Lang.Blocks.neobot_soco_lite_duration_7s, '7'],\n                                [Lang.Blocks.neobot_soco_lite_duration_8s, '8'],\n                                [Lang.Blocks.neobot_soco_lite_duration_9s, '9'],\n                            ],\n                            value: '계속',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_soco_lite_led',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                neobot_soco_lite_arg_motor_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['100%', 100],\n                                ['90%', 90],\n                                ['80%', 80],\n                                ['70%', 70],\n                                ['60%', 60],\n                                ['50%', 50],\n                                ['40%', 40],\n                                ['30%', 30],\n                                ['20%', 20],\n                                ['10%', 10],\n                                ['0%', 0],\n                            ],\n                            value: 100,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_soco_lite_motor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                neobot_soco_lite_arg_motor_duration: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_duration_cont, '계속'],\n                                [Lang.Blocks.neobot_soco_lite_duration_1s, '1'],\n                                [Lang.Blocks.neobot_soco_lite_duration_2s, '2'],\n                                [Lang.Blocks.neobot_soco_lite_duration_3s, '3'],\n                                [Lang.Blocks.neobot_soco_lite_duration_4s, '4'],\n                                [Lang.Blocks.neobot_soco_lite_duration_5s, '5'],\n                                [Lang.Blocks.neobot_soco_lite_duration_6s, '6'],\n                                [Lang.Blocks.neobot_soco_lite_duration_7s, '7'],\n                                [Lang.Blocks.neobot_soco_lite_duration_8s, '8'],\n                                [Lang.Blocks.neobot_soco_lite_duration_9s, '9'],\n                            ],\n                            value: '계속',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_soco_lite_motor',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                get_servo_degree: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_soco_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_soco_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_soco_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_soco_lite_angle_0, '0'],\n                                [Lang.Blocks.neobot_soco_lite_angle_5, '5'],\n                                [Lang.Blocks.neobot_soco_lite_angle_10, '10'],\n                                [Lang.Blocks.neobot_soco_lite_angle_15, '15'],\n                                [Lang.Blocks.neobot_soco_lite_angle_20, '20'],\n                                [Lang.Blocks.neobot_soco_lite_angle_25, '25'],\n                                [Lang.Blocks.neobot_soco_lite_angle_30, '30'],\n                                [Lang.Blocks.neobot_soco_lite_angle_35, '35'],\n                                [Lang.Blocks.neobot_soco_lite_angle_40, '40'],\n                                [Lang.Blocks.neobot_soco_lite_angle_45, '45'],\n                                [Lang.Blocks.neobot_soco_lite_angle_50, '50'],\n                                [Lang.Blocks.neobot_soco_lite_angle_55, '55'],\n                                [Lang.Blocks.neobot_soco_lite_angle_60, '60'],\n                                [Lang.Blocks.neobot_soco_lite_angle_65, '65'],\n                                [Lang.Blocks.neobot_soco_lite_angle_70, '70'],\n                                [Lang.Blocks.neobot_soco_lite_angle_75, '75'],\n                                [Lang.Blocks.neobot_soco_lite_angle_80, '80'],\n                                [Lang.Blocks.neobot_soco_lite_angle_85, '85'],\n                                [Lang.Blocks.neobot_soco_lite_angle_90, '90'],\n                                [Lang.Blocks.neobot_soco_lite_angle_95, '95'],\n                                [Lang.Blocks.neobot_soco_lite_angle_100, '100'],\n                                [Lang.Blocks.neobot_soco_lite_angle_105, '105'],\n                                [Lang.Blocks.neobot_soco_lite_angle_110, '110'],\n                                [Lang.Blocks.neobot_soco_lite_angle_115, '115'],\n                                [Lang.Blocks.neobot_soco_lite_angle_120, '120'],\n                                [Lang.Blocks.neobot_soco_lite_angle_125, '125'],\n                                [Lang.Blocks.neobot_soco_lite_angle_130, '130'],\n                                [Lang.Blocks.neobot_soco_lite_angle_135, '135'],\n                                [Lang.Blocks.neobot_soco_lite_angle_140, '140'],\n                                [Lang.Blocks.neobot_soco_lite_angle_145, '145'],\n                                [Lang.Blocks.neobot_soco_lite_angle_150, '150'],\n                                [Lang.Blocks.neobot_soco_lite_angle_155, '155'],\n                                [Lang.Blocks.neobot_soco_lite_angle_160, '160'],\n                                [Lang.Blocks.neobot_soco_lite_angle_165, '165'],\n                                [Lang.Blocks.neobot_soco_lite_angle_170, '170'],\n                                [Lang.Blocks.neobot_soco_lite_angle_175, '175'],\n                                [Lang.Blocks.neobot_soco_lite_angle_180, '180'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_soco_lite_servo',\n                    isNotFor: ['NeobotSocoLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n            };\n        };\n    })();\n})();\n\nmodule.exports = Entry.NeobotSocoLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_neobot_thinkcar_lite.js",
    "content": "'use strict';\n(function() {\n    const HEADER = [0xab, 0xcd];\n\n    Entry.NeobotThinkCarLite = new (class NeobotThinkCarLite {\n        constructor() {\n            this.id = '050701';\n            this.name = 'NeobotThinkCarLite';\n            this.url = 'http://neobot.co.kr/';\n            this.imageName = 'neobot_thinkcar_lite.png';\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n            };\n            this.duration = 100;\n            this.LOCAL_MAP = ['IN1', 'IN2', 'IN3', 'IR', 'BAT'];\n            this.localBuffer = {\n                IN1: 0,\n                IN2: 0,\n                IN3: 0,\n                IR: 0,\n                BAT: 0,\n            };\n            this.remoteBuffer = {\n                OUT1: 0,\n                OUT2: 0,\n                OUT3: 0,\n                DCL: 0,\n                DCR: 0,\n                SND: 0,\n                FND: 0,\n                OPT: 0,\n            };\n            this.log_to_console = false;\n\n            this.blockMenuBlocks = [\n                // think car\n                'neobot_think_car_lite_auto_driving_title',\n                'neobot_think_car_lite_line_tracer_start',\n                // 'neobot_think_car_lite_line_tracer_change_speed',\n                'neobot_think_car_lite_reverse_parking_start',\n                'neobot_think_car_lite_line_change',\n                'neobot_think_car_lite_driving_stop',\n\n                // sensor\n                'neobot_think_car_lite_sensor_title',\n                'neobot_think_car_lite_sensor_value',\n                'neobot_think_car_lite_sensor_convert_scale',\n                'neobot_think_car_lite_decision_sensor_is_over',\n                'neobot_think_car_lite_decision_equal_with_sensor',\n                'neobot_think_car_lite_decision_sensor_angle',\n                'neobot_think_car_lite_remote_button',\n\n                // led\n                'neobot_think_car_lite_led_title',\n                'neobot_think_car_lite_led_on',\n                'neobot_think_car_lite_led_brightness_with_sensor',\n                'neobot_think_car_lite_color_led_on',\n                'neobot_think_car_lite_output_led_off',\n\n                // output\n                'neobot_think_car_lite_output_title',\n                'neobot_think_car_lite_set_output',\n\n                //  motor\n                'neobot_think_car_lite_motor_title',\n                'neobot_think_car_lite_robot',\n                'neobot_think_car_lite_motor_start',\n                'neobot_think_car_lite_motor_stop',\n\n                // servo\n                'neobot_think_car_lite_servo_title',\n                'neobot_think_car_lite_servo_init',\n                'neobot_think_car_lite_servo_rotate',\n                'neobot_think_car_lite_servo_stop',\n                'neobot_think_car_lite_servo_change_degree',\n\n                // melody\n                'neobot_think_car_lite_buzzer_title',\n                'neobot_think_car_lite_play_note_for',\n                'neobot_think_car_lite_melody_play_with_sensor',\n                'neobot_think_car_lite_melody_stop',\n            ];\n\n            this.setZero();\n        }\n\n        get monitorTemplate() {\n            return {\n                imgPath: 'hw/neobot_thinkcar.png',\n                width: 700,\n                height: 700,\n                listPorts: {\n                    IR: { name: 'IR', type: 'input', pos: { x: 0, y: 0 } },\n                    BAT: { name: 'BAT', type: 'input', pos: { x: 0, y: 0 } },\n                    SND: { name: 'SND', type: 'output', pos: { x: 0, y: 0 } },\n                    FND: { name: 'FND', type: 'output', pos: { x: 0, y: 0 } },\n                },\n                ports: {\n                    IN1: { name: 'IN1', type: 'input', pos: { x: 270, y: 200 } },\n                    IN2: { name: 'IN2', type: 'input', pos: { x: 325, y: 200 } },\n                    IN3: { name: 'IN3', type: 'input', pos: { x: 325, y: 500 } },\n                    DCL: { name: 'L-Motor', type: 'output', pos: { x: 270, y: 500 } },\n                    DCR: { name: 'R-Motor', type: 'output', pos: { x: 435, y: 500 } },\n                    OUT1: { name: 'OUT1', type: 'output', pos: { x: 380, y: 200 } },\n                    OUT2: { name: 'OUT2', type: 'output', pos: { x: 435, y: 200 } },\n                    OUT3: { name: 'OUT3', type: 'output', pos: { x: 380, y: 500 } },\n                },\n                mode: 'both',\n            };\n        }\n\n        getMonitorPort() {\n            return { ...this.localBuffer, ...this.remoteBuffer };\n        }\n\n        setZero() {\n            this.remoteBuffer = {\n                OUT1: 0,\n                OUT2: 0,\n                OUT3: 0,\n                DCL: 0,\n                DCR: 0,\n                SND: 0,\n                FND: 0,\n                OPT: 0,\n            };\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        handleLocalData(data) {\n            let validPdu = this.getValidPdu(data);\n            while (validPdu) {\n                this.onReceivePdu(validPdu);\n                if (!this.remainingPdu || this.remainingPdu.length <= 0) {\n                    break;\n                }\n                validPdu = this.getValidPdu([]);\n            }\n        }\n\n        onReceivePdu(pdu) {\n            if (pdu[0] === HEADER[0] && pdu[1] === HEADER[1]) {\n                this.localBuffer['IN1'] = pdu[2];\n                this.localBuffer['IN2'] = pdu[3];\n                this.localBuffer['IN3'] = pdu[4];\n                this.localBuffer['IR'] = pdu[5];\n                this.localBuffer['BAT'] = pdu[6];\n            }\n        }\n\n        getValidPdu(pdu) {\n            const mergedPdu = [];\n            if (this.remainingPdu) {\n                mergedPdu.push(...this.remainingPdu);\n                this.remainingPdu = null;\n            }\n            mergedPdu.push(...pdu);\n            if (mergedPdu.length < 2) {\n                this.remainingPdu = [...mergedPdu];\n                return null;\n            }\n\n            // 헤더 불일치는 버림\n            if (!this.checkHeader(mergedPdu)) {\n                return null;\n            }\n\n            // 유효 데이터 길이는 header 2 + body 5 + checksum 1 = 8\n            const validDataLength = 8;\n            /*\n            전체 길이가 유효 데이터 길이보다 작을 경우\n            아직 도착하지 않은 부분이 있으므로 병합을 위해 remainingPdu 에 저장\n             */\n            if (mergedPdu.length < validDataLength) {\n                this.remainingPdu = [...mergedPdu];\n                return null;\n            }\n\n            /*\n            전체 길이가 유효 데이터 길이보다 클 경우\n            유효한 부분만 잘라내고 나머지는 remainingPdu 에 저장\n             */\n            if (mergedPdu.length > validDataLength) {\n                this.remainingPdu = mergedPdu.slice(validDataLength, mergedPdu.length);\n            }\n\n            const validPdu = mergedPdu.slice(0, validDataLength);\n\n            /*\n            유효 Pdu 의 checksum 확인\n             */\n            const dataLength = 5;\n            let checkSum = 0;\n            for (let i = 0; i < dataLength; i++) {\n                checkSum += validPdu[i + 2];\n            }\n            checkSum = checkSum & 255;\n            const pduCheckSum = validPdu[7];\n            if (pduCheckSum !== checkSum) {\n                return null;\n            }\n\n            return validPdu;\n        }\n\n        checkHeader(pdu) {\n            if (pdu.length < HEADER.length) {\n                return false;\n            }\n\n            for (let i = 0; i < HEADER.length; i++) {\n                if (HEADER[i] !== pdu[i]) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        requestLocalData() {\n            const requestData = [];\n\n            // 시작 바이트\n            requestData.push(0xcd);\n            requestData.push(0xab);\n\n            let checksum = 0;\n            let isFnd = false;\n            Object.keys(this.remoteBuffer).forEach((key, idx) => {\n                let value = this.remoteBuffer[key];\n                if (idx === 6 && value > 0) {\n                    isFnd = true;\n                } else if (idx === 7 && isFnd) {\n                    value = value | 8;\n                }\n                requestData.push(value);\n                checksum += value;\n            });\n\n            checksum = checksum & 255;\n            //체크썸\n            requestData.push(checksum);\n            return requestData;\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // think car\n                        neobot_think_car_lite_auto_driving_title: '자율주행',\n                        neobot_think_car_lite_line_tracer_start:\n                            '차로를 유지하며 속도 %1 으로 자율주행 %2',\n                        // neobot_think_car_lite_line_tracer_change_speed: '자율주행 속도 변경 %1 %2',\n                        neobot_think_car_lite_reverse_parking_start: '%1 표지판에서 후면 주차 %2',\n                        neobot_think_car_lite_line_change:\n                            '1차로 %1 2차로 %2 표지판에서 차로 변경 %3',\n                        neobot_think_car_lite_driving_stop: '자율주행 중지 %1',\n\n                        // sensor\n                        neobot_think_car_lite_sensor_title: '센서',\n                        neobot_think_car_lite_sensor_value: '%1',\n                        neobot_think_car_lite_sensor_convert_scale:\n                            '%1 %2 ~ %3 를 %4 ~ %5 으로 변환',\n                        neobot_think_car_lite_decision_sensor_is_over: '%1 %2 %3',\n                        neobot_think_car_lite_decision_equal_with_sensor: '%1 컬러가 %2',\n                        neobot_think_car_lite_decision_sensor_angle: '%1 각도 %2 %3',\n                        neobot_think_car_lite_remote_button: '리모컨 버튼 %1 을 누름',\n\n                        // LED\n                        neobot_think_car_lite_led_title: 'LED',\n                        neobot_think_car_lite_arg_led_duration: '%1',\n                        neobot_think_car_lite_led_on: 'LED 켜기   %1 %2 %3 %4',\n                        neobot_think_car_lite_output_led_off: '%1 LED 끄기 %2',\n                        neobot_think_car_lite_led_brightness_with_sensor: '%1 로 %2 LED 제어 %3',\n                        neobot_think_car_lite_color_led_on: '%1 컬러LED 켜기   R %2 G %3 B %4 %5',\n\n                        // output\n                        neobot_think_car_lite_output_title: '출력',\n                        neobot_think_car_lite_set_output: '%1 에 %2 값 출력하기 %3',\n\n                        // motor\n                        neobot_think_car_lite_motor_title: '회전모터',\n                        neobot_think_car_lite_robot: '로봇 %1 %2',\n                        neobot_think_car_lite_motor_start: '모터 회전하기   %1 %2 %3 %4 %5',\n                        neobot_think_car_lite_motor_stop: '%1 모터 멈추기 %2',\n                        neobot_think_car_lite_arg_motor_speed: '%1',\n                        neobot_think_car_lite_arg_motor_duration: '%1',\n\n                        // melody\n                        neobot_think_car_lite_buzzer_title: '버저',\n                        neobot_think_car_lite_play_note_for:\n                            '버저 울리기   옥타브: %2 음: %1 길이: %3 %4',\n                        neobot_think_car_lite_melody_play_with_sensor: '%1 센서로 버저 울리기 %2',\n                        neobot_think_car_lite_melody_stop: '버저 멈추기 %1',\n\n                        // servo\n                        neobot_think_car_lite_servo_title: '서보모터',\n                        get_servo_degree: '%1',\n                        neobot_think_car_lite_servo_init: '%1 서보모터 리셋 %2',\n                        neobot_think_car_lite_servo_rotate: '서보모터 회전하기   %1 %2 %3 %4',\n                        neobot_think_car_lite_servo_stop: '%1 서보모터 멈추기 %2',\n                        neobot_think_car_lite_servo_change_degree:\n                            '서보모터 각도 바꾸기   %2 %3 %4 %1 %5',\n                    },\n                    Blocks: {\n                        //for dropdown\n                        neobot_think_car_lite_port_1: 'IN1',\n                        neobot_think_car_lite_port_2: 'IN2',\n                        neobot_think_car_lite_port_3: 'IN3',\n                        neobot_think_car_lite_port_4: 'IN4',\n                        neobot_think_car_lite_port_12: 'IN1 & IN2',\n                        neobot_think_car_lite_port_bat: '배터리',\n                        neobot_think_car_lite_port_remot: '리모컨',\n                        neobot_think_car_lite_color_white: '흰색',\n                        neobot_think_car_lite_color_red: '빨강',\n                        neobot_think_car_lite_color_yellow: '노랑',\n                        neobot_think_car_lite_color_green: '녹색',\n                        neobot_think_car_lite_color_blue: '파랑',\n                        neobot_think_car_lite_direction_forward: '앞으로',\n                        neobot_think_car_lite_direction_backward: '뒤로',\n                        neobot_think_car_lite_sound_silent: '무음',\n                        neobot_think_car_lite_sound_do: '도',\n                        neobot_think_car_lite_sound_do_shop: '도#',\n                        neobot_think_car_lite_sound_re: '레',\n                        neobot_think_car_lite_sound_re_shop: '레#',\n                        neobot_think_car_lite_sound_mi: '미',\n                        neobot_think_car_lite_sound_fa: '파',\n                        neobot_think_car_lite_sound_fa_shop: '파#',\n                        neobot_think_car_lite_sound_so: '솔',\n                        neobot_think_car_lite_sound_so_shop: '솔#',\n                        neobot_think_car_lite_sound_la: '라',\n                        neobot_think_car_lite_sound_la_shop: '라#',\n                        neobot_think_car_lite_sound_ti: '시',\n                        neobot_think_car_lite_sound_half_note: '2분 음표',\n                        neobot_think_car_lite_sound_quarter_note: '4분 음표',\n                        neobot_think_car_lite_sound_eighth_note: '8분 음표',\n                        neobot_think_car_lite_sound_sixteenth_note: '16분 음표',\n                        neobot_think_car_lite_sensor_infrared: '적외선센서',\n                        neobot_think_car_lite_sensor_light: '빛센서',\n                        neobot_think_car_lite_sensor_sound: '소리센서',\n                        neobot_think_car_lite_compare_symbol1: '＝',\n                        neobot_think_car_lite_compare_symbol2: '＞',\n                        neobot_think_car_lite_compare_symbol3: '＜',\n                        neobot_think_car_lite_compare_symbol4: '≥',\n                        neobot_think_car_lite_compare_symbol5: '≤',\n                        neobot_think_car_lite_remote_btn_a: 'A',\n                        neobot_think_car_lite_remote_btn_b: 'B',\n                        neobot_think_car_lite_remote_btn_c: 'C',\n                        neobot_think_car_lite_remote_btn_d: 'D',\n                        neobot_think_car_lite_remote_btn_1: '1',\n                        neobot_think_car_lite_remote_btn_2: '2',\n                        neobot_think_car_lite_remote_btn_3: '3',\n                        neobot_think_car_lite_remote_btn_4: '4',\n                        neobot_think_car_lite_remote_btn_up: '▲',\n                        neobot_think_car_lite_remote_btn_down: '▼',\n                        neobot_think_car_lite_remote_btn_left: '◀',\n                        neobot_think_car_lite_remote_btn_right: '▶',\n                        neobot_think_car_lite_duration_cont: '계속',\n                        neobot_think_car_lite_duration_1s: '1초',\n                        neobot_think_car_lite_duration_2s: '2초',\n                        neobot_think_car_lite_duration_3s: '3초',\n                        neobot_think_car_lite_duration_4s: '4초',\n                        neobot_think_car_lite_duration_5s: '5초',\n                        neobot_think_car_lite_duration_6s: '6초',\n                        neobot_think_car_lite_duration_7s: '7초',\n                        neobot_think_car_lite_duration_8s: '8초',\n                        neobot_think_car_lite_duration_9s: '9초',\n                        neobot_think_car_lite_motor_both: '양쪽',\n                        neobot_think_car_lite_motor_left: '왼쪽',\n                        neobot_think_car_lite_motor_right: '오른쪽',\n                        neobot_think_car_lite_motor_move_forward: '전진',\n                        neobot_think_car_lite_motor_move_backward: '후진',\n                        neobot_think_car_lite_motor_move_left: '좌회전',\n                        neobot_think_car_lite_motor_move_right: '우회전',\n                        neobot_think_car_lite_motor_move_stop: '정지',\n\n                        neobot_think_car_lite_servo_dir_1: '정방향',\n                        neobot_think_car_lite_servo_dir_2: '역방향',\n\n                        neobot_think_car_lite_percent_10: '10%속도',\n                        neobot_think_car_lite_percent_20: '20%속도',\n                        neobot_think_car_lite_percent_30: '30%속도',\n                        neobot_think_car_lite_percent_40: '40%속도',\n                        neobot_think_car_lite_percent_50: '50%속도',\n                        neobot_think_car_lite_percent_60: '60%속도',\n                        neobot_think_car_lite_percent_70: '70%속도',\n                        neobot_think_car_lite_percent_80: '80%속도',\n                        neobot_think_car_lite_percent_90: '90%속도',\n                        neobot_think_car_lite_percent_100: '100%속도',\n\n                        neobot_think_car_lite_angle_0: '0도',\n                        neobot_think_car_lite_angle_5: '5도',\n                        neobot_think_car_lite_angle_10: '10도',\n                        neobot_think_car_lite_angle_15: '15도',\n                        neobot_think_car_lite_angle_20: '20도',\n                        neobot_think_car_lite_angle_25: '25도',\n                        neobot_think_car_lite_angle_30: '30도',\n                        neobot_think_car_lite_angle_35: '35도',\n                        neobot_think_car_lite_angle_40: '40도',\n                        neobot_think_car_lite_angle_45: '45도',\n                        neobot_think_car_lite_angle_50: '50도',\n                        neobot_think_car_lite_angle_55: '55도',\n                        neobot_think_car_lite_angle_60: '60도',\n                        neobot_think_car_lite_angle_65: '65도',\n                        neobot_think_car_lite_angle_70: '70도',\n                        neobot_think_car_lite_angle_75: '75도',\n                        neobot_think_car_lite_angle_80: '80도',\n                        neobot_think_car_lite_angle_85: '85도',\n                        neobot_think_car_lite_angle_90: '90도',\n                        neobot_think_car_lite_angle_95: '95도',\n                        neobot_think_car_lite_angle_100: '100도',\n                        neobot_think_car_lite_angle_105: '105도',\n                        neobot_think_car_lite_angle_110: '110도',\n                        neobot_think_car_lite_angle_115: '115도',\n                        neobot_think_car_lite_angle_120: '120도',\n                        neobot_think_car_lite_angle_125: '125도',\n                        neobot_think_car_lite_angle_130: '130도',\n                        neobot_think_car_lite_angle_135: '135도',\n                        neobot_think_car_lite_angle_140: '140도',\n                        neobot_think_car_lite_angle_145: '145도',\n                        neobot_think_car_lite_angle_150: '150도',\n                        neobot_think_car_lite_angle_155: '155도',\n                        neobot_think_car_lite_angle_160: '160도',\n                        neobot_think_car_lite_angle_165: '165도',\n                        neobot_think_car_lite_angle_170: '170도',\n                        neobot_think_car_lite_angle_175: '175도',\n                        neobot_think_car_lite_angle_180: '180도',\n\n                        neobot_think_car_lite_out_all: '모든',\n                        neobot_think_car_lite_direction_left: '왼쪽으로',\n                        neobot_think_car_lite_direction_right: '오른쪽으로',\n\n                        neobot_think_car_lite_color_sign_red: '빨간색',\n                        neobot_think_car_lite_color_sign_yellow: '노란색',\n                        neobot_think_car_lite_color_sign_green: '녹색',\n                        neobot_think_car_lite_color_sign_blue: '파란색',\n                    },\n                },\n                en: {\n                    // en.js에 작성하던 내용\n                    template: {\n                        // think car\n                        neobot_think_car_lite_auto_driving_title: 'Self-driving',\n                        neobot_think_car_lite_line_tracer_start:\n                            'Start self-driving at %1 speed while keeping lanes %2',\n                        // neobot_think_car_lite_line_tracer_change_speed: 'Change the speed of self-driving %1 %2',\n                        neobot_think_car_lite_reverse_parking_start:\n                            'Start reverse parking at %1 sign %2',\n                        neobot_think_car_lite_line_change:\n                            'Change the lane from primary %1 sign to secondary %2 sign %3',\n                        neobot_think_car_lite_driving_stop: 'Stop self-driving %1',\n\n                        // sensor\n                        neobot_think_car_lite_sensor_title: 'Sensor',\n                        neobot_think_car_lite_sensor_value: '%1',\n                        neobot_think_car_lite_sensor_convert_scale:\n                            \"%1 's changed value   range: %2 ~ %3 conversion: %4 ~ %5\",\n                        neobot_think_car_lite_decision_sensor_is_over: '%1 %2 %3',\n                        neobot_think_car_lite_decision_equal_with_sensor: \"%1 's color is %2\",\n                        neobot_think_car_lite_decision_sensor_angle: '%1 angle %2 %3',\n                        neobot_think_car_lite_remote_button:\n                            'pressing button %1 of remote controller',\n\n                        // LED\n                        neobot_think_car_lite_led_title: 'LED',\n                        neobot_think_car_lite_arg_led_duration: '%1',\n                        neobot_think_car_lite_led_on: 'Turn on the LED    %1 %2 %3 %4',\n                        neobot_think_car_lite_output_led_off: 'Turn off the %1 LED %2',\n                        neobot_think_car_lite_led_brightness_with_sensor:\n                            \"Control %2 LED's brightness with %1 sensor %3\",\n                        neobot_think_car_lite_color_led_on:\n                            'Turn on the %1 color LED   R %2 G %3 B %4 %5',\n\n                        // output\n                        neobot_think_car_lite_output_title: 'Set output',\n                        neobot_think_car_lite_set_output: 'Output %2 value to %1 port %3',\n\n                        // motor\n                        neobot_think_car_lite_motor_title: 'Motor',\n                        neobot_think_car_lite_robot: 'Robot %1 %2',\n                        neobot_think_car_lite_motor_start: 'Motor operation   %1 %2 %3 %4 %5',\n                        neobot_think_car_lite_motor_stop: 'Stop the %1 motor(s) %2',\n                        neobot_think_car_lite_arg_motor_speed: '%1',\n                        neobot_think_car_lite_arg_motor_duration: '%1',\n\n                        // buzzer\n                        neobot_think_car_lite_buzzer_title: 'Buzzer',\n                        neobot_think_car_lite_play_note_for:\n                            'Buzzer   octave: %1 scale: %2 note: %3 %4',\n                        neobot_think_car_lite_melody_play_with_sensor:\n                            'Buzzer rings by %1 sensor value %2',\n                        neobot_think_car_lite_melody_stop: 'Stop the buzzer %1',\n\n                        // servo\n                        neobot_think_car_lite_servo_title: 'Servo motor',\n                        get_servo_degree: '%1',\n                        neobot_think_car_lite_servo_init: 'Reset the %1 servo motor %2',\n                        neobot_think_car_lite_servo_rotate: 'Rotate the servo motor   %1 %2 %3 %4',\n                        neobot_think_car_lite_servo_stop: 'Stop the %1 servo motor %2',\n                        neobot_think_car_lite_servo_change_degree:\n                            'Change servo angle   %1 %2 %3 %4 %5',\n                    },\n                    Blocks: {\n                        //for dropdown\n                        neobot_think_car_lite_port_1: 'IN1',\n                        neobot_think_car_lite_port_2: 'IN2',\n                        neobot_think_car_lite_port_3: 'IN3',\n                        neobot_think_car_lite_port_4: 'IN4',\n                        neobot_think_car_lite_port_12: 'IN1 & IN2',\n                        neobot_think_car_lite_port_bat: 'battery',\n                        neobot_think_car_lite_port_remot: 'remote',\n                        neobot_think_car_lite_color_white: 'white',\n                        neobot_think_car_lite_color_red: 'red',\n                        neobot_think_car_lite_color_yellow: 'yellow',\n                        neobot_think_car_lite_color_green: 'green',\n                        neobot_think_car_lite_color_blue: 'blue',\n                        neobot_think_car_lite_direction_forward: 'forward',\n                        neobot_think_car_lite_direction_backward: 'backward',\n                        neobot_think_car_lite_sound_silent: 'silent',\n                        neobot_think_car_lite_sound_do: 'Do',\n                        neobot_think_car_lite_sound_do_shop: 'Do#',\n                        neobot_think_car_lite_sound_re: 'Re',\n                        neobot_think_car_lite_sound_re_shop: 'Re#',\n                        neobot_think_car_lite_sound_mi: 'Mi',\n                        neobot_think_car_lite_sound_fa: 'Fa',\n                        neobot_think_car_lite_sound_fa_shop: 'Fa#',\n                        neobot_think_car_lite_sound_so: 'So',\n                        neobot_think_car_lite_sound_so_shop: 'So#',\n                        neobot_think_car_lite_sound_la: 'La',\n                        neobot_think_car_lite_sound_la_shop: 'La#',\n                        neobot_think_car_lite_sound_ti: 'Si',\n                        neobot_think_car_lite_sound_half_note: 'a half note',\n                        neobot_think_car_lite_sound_quarter_note: 'a quarter note',\n                        neobot_think_car_lite_sound_eighth_note: 'a eighth note',\n                        neobot_think_car_lite_sound_sixteenth_note: 'a sixteenth note',\n                        neobot_think_car_lite_sensor_infrared: 'IR sensor',\n                        neobot_think_car_lite_sensor_light: 'light sensor',\n                        neobot_think_car_lite_sensor_sound: 'sound sensor',\n                        neobot_think_car_lite_compare_symbol1: '＝',\n                        neobot_think_car_lite_compare_symbol2: '＞',\n                        neobot_think_car_lite_compare_symbol3: '＜',\n                        neobot_think_car_lite_compare_symbol4: '≥',\n                        neobot_think_car_lite_compare_symbol5: '≤',\n                        neobot_think_car_lite_remote_btn_a: 'A',\n                        neobot_think_car_lite_remote_btn_b: 'B',\n                        neobot_think_car_lite_remote_btn_c: 'C',\n                        neobot_think_car_lite_remote_btn_d: 'D',\n                        neobot_think_car_lite_remote_btn_1: '1',\n                        neobot_think_car_lite_remote_btn_2: '2',\n                        neobot_think_car_lite_remote_btn_3: '3',\n                        neobot_think_car_lite_remote_btn_4: '4',\n                        neobot_think_car_lite_remote_btn_up: '▲',\n                        neobot_think_car_lite_remote_btn_down: '▼',\n                        neobot_think_car_lite_remote_btn_left: '◀',\n                        neobot_think_car_lite_remote_btn_right: '▶',\n                        neobot_think_car_lite_duration_cont: 'constantly',\n                        neobot_think_car_lite_duration_1s: '1 second',\n                        neobot_think_car_lite_duration_2s: '2 seconds',\n                        neobot_think_car_lite_duration_3s: '3 seconds',\n                        neobot_think_car_lite_duration_4s: '4 seconds',\n                        neobot_think_car_lite_duration_5s: '5 seconds',\n                        neobot_think_car_lite_duration_6s: '6 seconds',\n                        neobot_think_car_lite_duration_7s: '7 seconds',\n                        neobot_think_car_lite_duration_8s: '8 seconds',\n                        neobot_think_car_lite_duration_9s: '9 seconds',\n                        neobot_think_car_lite_motor_both: 'both',\n                        neobot_think_car_lite_motor_left: 'left',\n                        neobot_think_car_lite_motor_right: 'right',\n                        neobot_think_car_lite_motor_move_forward: 'go forward',\n                        neobot_think_car_lite_motor_move_backward: 'go backward',\n                        neobot_think_car_lite_motor_move_left: 'turn Left',\n                        neobot_think_car_lite_motor_move_right: 'turn Right',\n                        neobot_think_car_lite_motor_move_stop: 'stop',\n\n                        neobot_think_car_lite_servo_dir_1: 'forward',\n                        neobot_think_car_lite_servo_dir_2: 'backward',\n\n                        neobot_think_car_lite_percent_10: '10% speed',\n                        neobot_think_car_lite_percent_20: '20% speed',\n                        neobot_think_car_lite_percent_30: '30% speed',\n                        neobot_think_car_lite_percent_40: '40% speed',\n                        neobot_think_car_lite_percent_50: '50% speed',\n                        neobot_think_car_lite_percent_60: '60% speed',\n                        neobot_think_car_lite_percent_70: '70% speed',\n                        neobot_think_car_lite_percent_80: '80% speed',\n                        neobot_think_car_lite_percent_90: '90% speed',\n                        neobot_think_car_lite_percent_100: '100% speed',\n\n                        neobot_think_car_lite_angle_0: '0 degree',\n                        neobot_think_car_lite_angle_5: '5 degrees',\n                        neobot_think_car_lite_angle_10: '10 degrees',\n                        neobot_think_car_lite_angle_15: '15 degrees',\n                        neobot_think_car_lite_angle_20: '20 degrees',\n                        neobot_think_car_lite_angle_25: '25 degrees',\n                        neobot_think_car_lite_angle_30: '30 degrees',\n                        neobot_think_car_lite_angle_35: '35 degrees',\n                        neobot_think_car_lite_angle_40: '40 degrees',\n                        neobot_think_car_lite_angle_45: '45 degrees',\n                        neobot_think_car_lite_angle_50: '50 degrees',\n                        neobot_think_car_lite_angle_55: '55 degrees',\n                        neobot_think_car_lite_angle_60: '60 degrees',\n                        neobot_think_car_lite_angle_65: '65 degrees',\n                        neobot_think_car_lite_angle_70: '70 degrees',\n                        neobot_think_car_lite_angle_75: '75 degrees',\n                        neobot_think_car_lite_angle_80: '80 degrees',\n                        neobot_think_car_lite_angle_85: '85 degrees',\n                        neobot_think_car_lite_angle_90: '90 degrees',\n                        neobot_think_car_lite_angle_95: '95 degrees',\n                        neobot_think_car_lite_angle_100: '100 degrees',\n                        neobot_think_car_lite_angle_105: '105 degrees',\n                        neobot_think_car_lite_angle_110: '110 degrees',\n                        neobot_think_car_lite_angle_115: '115 degrees',\n                        neobot_think_car_lite_angle_120: '120 degrees',\n                        neobot_think_car_lite_angle_125: '125 degrees',\n                        neobot_think_car_lite_angle_130: '130 degrees',\n                        neobot_think_car_lite_angle_135: '135 degrees',\n                        neobot_think_car_lite_angle_140: '140 degrees',\n                        neobot_think_car_lite_angle_145: '145 degrees',\n                        neobot_think_car_lite_angle_150: '150 degrees',\n                        neobot_think_car_lite_angle_155: '155 degrees',\n                        neobot_think_car_lite_angle_160: '160 degrees',\n                        neobot_think_car_lite_angle_165: '165 degrees',\n                        neobot_think_car_lite_angle_170: '170 degrees',\n                        neobot_think_car_lite_angle_175: '175 degrees',\n                        neobot_think_car_lite_angle_180: '180degrees',\n\n                        neobot_think_car_lite_out_all: 'ALL',\n                        neobot_think_car_lite_direction_left: 'to the left',\n                        neobot_think_car_lite_direction_right: 'to the right',\n\n                        neobot_think_car_lite_color_sign_red: 'red',\n                        neobot_think_car_lite_color_sign_yellow: 'yellow',\n                        neobot_think_car_lite_color_sign_green: 'green',\n                        neobot_think_car_lite_color_sign_blue: 'blue',\n                    },\n                }, //\n            };\n        }\n\n        getBlocks = function() {\n            return {\n                neobot_think_car_lite_auto_driving_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_think_car_lite_auto_driving_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_think_car_lite_auto_driving_title',\n                    },\n                    class: 'neobot_think_car_lite_operation',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    events: {},\n                },\n                neobot_think_car_lite_line_tracer_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['10%', 10],\n                                ['20%', 20],\n                                ['30%', 30],\n                                ['40%', 40],\n                                ['50%', 50],\n                                ['60%', 60],\n                                ['70%', 70],\n                                ['80%', 80],\n                                ['90%', 90],\n                                ['100%', 100],\n                            ],\n                            value: 60,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_line_tracer_start',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                    },\n                    class: 'neobot_think_car_lite_operation',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const speed = script.getNumberField('SPEED');\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const out3Value = 221;\n                            const buzzerValue = 72;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = out3Value;\n                            Entry.NeobotThinkCarLite.remoteBuffer.SND = buzzerValue;\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_line_tracer_start ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`out3 : ${out3Value}`, 'speak');\n                                Entry.console.print(`buzzer : ${buzzerValue}`, 'speak');\n                            }\n\n                            setTimeout(() => {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = speed;\n                                Entry.NeobotThinkCarLite.remoteBuffer.SND = 0;\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(`out1 : ${speed}`, 'speak');\n                                    Entry.console.print('buzzer : 0', 'speak');\n                                    Entry.console.print('==========================', 'speak');\n                                }\n                                script.timeFlag = 0;\n                            }, 300);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n                neobot_think_car_lite_reverse_parking_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_red, 80],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_yellow, 120],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_green, 160],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_blue, 200],\n                            ],\n                            value: 160,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_reverse_parking_start',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'neobot_think_car_lite_operation',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const out3Value = 228;\n                            const buzzerValue = 72;\n                            const colorValue = script.getNumberField('COLOR');\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = out3Value;\n                            Entry.NeobotThinkCarLite.remoteBuffer.SND = buzzerValue;\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_reverse_parking_start ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`out3 : ${out3Value}`, 'speak');\n                                Entry.console.print(`buzzer : ${buzzerValue}`, 'speak');\n                            }\n\n                            setTimeout(() => {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = colorValue;\n                                Entry.NeobotThinkCarLite.remoteBuffer.SND = 0;\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(`out1 : ${colorValue}`, 'speak');\n                                    Entry.console.print('buzzer : 0', 'speak');\n                                    Entry.console.print('==========================', 'speak');\n                                }\n\n                                script.timeFlag = 0;\n                            }, 300);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n                neobot_think_car_lite_line_change: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_red, 80],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_yellow, 120],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_green, 160],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_blue, 200],\n                            ],\n                            value: 200,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_red, 80],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_yellow, 120],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_green, 160],\n                                [Lang.Blocks.neobot_think_car_lite_color_sign_blue, 200],\n                            ],\n                            value: 160,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neobot_think_car_lite_line_change',\n                    },\n                    paramsKeyMap: {\n                        FROM_COLOR: 0,\n                        TO_COLOR: 1,\n                    },\n                    class: 'neobot_think_car_lite_operation',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const out3Value = 223;\n                            const buzzerValue = 72;\n                            const fromColorValue = script.getNumberField('FROM_COLOR');\n                            const toColorValue = script.getNumberField('TO_COLOR');\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = out3Value;\n                            Entry.NeobotThinkCarLite.remoteBuffer.SND = buzzerValue;\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_line_change ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`out3 : ${out3Value}`, 'speak');\n                                Entry.console.print(`buzzer : ${buzzerValue}`, 'speak');\n                            }\n\n                            setTimeout(() => {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = fromColorValue;\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = toColorValue;\n                                Entry.NeobotThinkCarLite.remoteBuffer.SND = 0;\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(`out1 : ${fromColorValue}`, 'speak');\n                                    Entry.console.print(`out2 : ${toColorValue}`, 'speak');\n                                    Entry.console.print('buzzer : 0', 'speak');\n                                    Entry.console.print('==========================', 'speak');\n                                }\n\n                                script.timeFlag = 0;\n                            }, 300);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n                neobot_think_car_lite_driving_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_think_car_lite_driving_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'neobot_think_car_lite_operation',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            const out3Value = 248;\n                            const buzzerValue = 72;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = out3Value;\n                            Entry.NeobotThinkCarLite.remoteBuffer.SND = buzzerValue;\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_driving_stop ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`out3 : ${out3Value}`, 'speak');\n                                Entry.console.print(`buzzer : ${buzzerValue}`, 'speak');\n                            }\n                            setTimeout(() => {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = 0;\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = 0;\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = 0;\n                                Entry.NeobotThinkCarLite.remoteBuffer.SND = 0;\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print('out1 : 0', 'speak');\n                                    Entry.console.print('out2 : 0', 'speak');\n                                    Entry.console.print('out3 : 0', 'speak');\n                                    Entry.console.print('buzzer : 0', 'speak');\n                                    Entry.console.print('==========================', 'speak');\n                                }\n                                script.timeFlag = 0;\n                            }, 300);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n                /*neobot_think_car_lite_line_tracer_change_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0%', 0],\n                                ['10%', 10],\n                                ['20%', 20],\n                                ['30%', 30],\n                                ['40%', 40],\n                                ['50%', 50],\n                                ['60%', 60],\n                                ['70%', 70],\n                                ['80%', 80],\n                                ['90%', 90],\n                                ['100%', 100],\n                            ],\n                            value: 50,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                        ],\n                        type: 'neobot_think_car_lite_line_tracer_change_speed',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                    },\n                    class: 'neobot_think_car_lite_operation',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func: function(sprite, script) {\n                        const speed = script.getStringField('SPEED');\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_think_car_lite_line_tracer_change_speed ===',\n                                'speak');\n                            Entry.console.print('out1 : ' + speed, 'speak');\n                            Entry.console.print('==========================',\n                                'speak');\n                        }\n                        Entry.NeobotThinkCarLite.remoteBuffer['OUT1'] = speed;\n                    },\n                },*/\n                /*************************\n                 * class neobot_think_car_lite_sensor\n                 *************************/\n                neobot_think_car_lite_sensor_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_think_car_lite_sensor_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_think_car_lite_sensor_title',\n                    },\n                    class: 'neobot_think_car_lite_sensor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    events: {},\n                },\n                neobot_think_car_lite_sensor_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_think_car_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_think_car_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_think_car_lite_port_remot, 'IR'],\n                                [Lang.Blocks.neobot_think_car_lite_port_bat, 'BAT'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_think_car_lite_sensor_value',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_think_car_lite_sensor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT');\n                        return Entry.NeobotThinkCarLite.localBuffer[port];\n                    },\n                },\n                neobot_think_car_lite_sensor_convert_scale: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_think_car_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_think_car_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                        ],\n                        type: 'neobot_think_car_lite_sensor_convert_scale',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        OMIN: 1,\n                        OMAX: 2,\n                        MIN: 3,\n                        MAX: 4,\n                    },\n                    class: 'neobot_think_car_lite_sensor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT');\n                        let value = Entry.NeobotThinkCarLite.localBuffer[port];\n                        let omin = script.getNumberValue('OMIN', script);\n                        let omax = script.getNumberValue('OMAX', script);\n                        let min = script.getNumberValue('MIN', script);\n                        let max = script.getNumberValue('MAX', script);\n\n                        if (omin > omax) {\n                            var temp = omin;\n                            omin = omax;\n                            omax = temp;\n                        }\n\n                        if (min > max) {\n                            var temp = min;\n                            min = max;\n                            max = temp;\n                        }\n\n                        value -= omin;\n                        value = value * ((max - min) / (omax - omin));\n                        value += min;\n                        value = Math.min(max, value);\n                        value = Math.max(min, value);\n\n                        return Math.round(value);\n                    },\n                },\n                neobot_think_car_lite_decision_sensor_is_over: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_think_car_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_think_car_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_think_car_lite_port_12, 'IN12'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol1, '='],\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol2, '>'],\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol3, '<'],\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol4, '>='],\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol5, '<='],\n                            ],\n                            value: '>',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 10],\n                        type: 'neobot_think_car_lite_decision_sensor_is_over',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        SYMBOL: 1,\n                        VALUE: 2,\n                    },\n                    class: 'neobot_think_car_lite_sensor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const symbol = script.getStringField('SYMBOL');\n                        const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                        if (sensorTemp == 'IN12') {\n                            const sensor1 = Entry.NeobotThinkCarLite.localBuffer.IN1;\n                            const sensor2 = Entry.NeobotThinkCarLite.localBuffer.IN2;\n                            if (symbol == '=') {\n                                return sensor1 == value && sensor2 == value;\n                            } else if (symbol == '>') {\n                                return sensor1 > value && sensor2 > value;\n                            } else if (symbol == '<') {\n                                return sensor1 < value && sensor2 < value;\n                            } else if (symbol == '>=') {\n                                return sensor1 >= value && sensor2 >= value;\n                            } else if (symbol == '<=') {\n                                return sensor1 <= value && sensor2 <= value;\n                            }\n                        } else {\n                            const sensor = Entry.NeobotThinkCarLite.localBuffer[sensorTemp];\n                            if (symbol == '=') {\n                                if (sensor == value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '>') {\n                                if (sensor > value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '<') {\n                                if (sensor < value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '>=') {\n                                if (sensor >= value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            } else if (symbol == '<=') {\n                                if (sensor <= value) {\n                                    return true;\n                                } else {\n                                    return false;\n                                }\n                            }\n                        }\n                        return false;\n                    },\n                },\n                neobot_think_car_lite_decision_equal_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_think_car_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_think_car_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_color_white, 0],\n                                [Lang.Blocks.neobot_think_car_lite_color_red, 1],\n                                [Lang.Blocks.neobot_think_car_lite_color_yellow, 2],\n                                [Lang.Blocks.neobot_think_car_lite_color_green, 3],\n                                [Lang.Blocks.neobot_think_car_lite_color_blue, 4],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_decision_equal_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        COLOR: 1,\n                    },\n                    class: 'neobot_think_car_lite_sensor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const sensor = Entry.NeobotThinkCarLite.localBuffer[sensorTemp];\n                        const color = script.getNumberField('COLOR');\n\n                        if (sensor >= 10 && sensor <= 50) {\n                            if (color == 0) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 51 && sensor <= 90) {\n                            if (color == 1) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 91 && sensor <= 130) {\n                            if (color == 2) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 131 && sensor <= 170) {\n                            if (color == 3) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (sensor >= 171 && sensor <= 210) {\n                            if (color == 4) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        }\n                        return false;\n                    },\n                },\n                neobot_think_car_lite_decision_sensor_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#FFFFFF',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_think_car_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_think_car_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol1, '='],\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol2, '>'],\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol3, '<'],\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol4, '>='],\n                                [Lang.Blocks.neobot_think_car_lite_compare_symbol5, '<='],\n                            ],\n                            value: '>',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_angle_0, '0'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_10, '10'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_20, '20'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_30, '30'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_40, '40'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_50, '50'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_60, '60'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_70, '70'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_80, '80'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_90, '90'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_100, '100'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_110, '110'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_120, '120'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_130, '130'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_140, '140'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_150, '150'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_160, '160'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_170, '170'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_180, '180'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neobot_think_car_lite_decision_sensor_angle',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                        SYMBOL: 1,\n                        VALUE: 2,\n                    },\n                    class: 'neobot_think_car_lite_sensor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const sensorTemp = script.getStringField('SENSOR');\n                        const sensor = Entry.NeobotThinkCarLite.localBuffer[sensorTemp];\n                        const symbol = script.getStringField('SYMBOL');\n                        const value = Entry.parseNumber(script.getStringValue('VALUE'));\n\n                        if (symbol == '=') {\n                            if (sensor == value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '>') {\n                            if (sensor > value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '<') {\n                            if (sensor < value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '>=') {\n                            if (sensor >= value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        } else if (symbol == '<=') {\n                            if (sensor <= value) {\n                                return true;\n                            } else {\n                                return false;\n                            }\n                        }\n                        return false;\n                    },\n                },\n                neobot_think_car_lite_remote_button: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#FFFFFF',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_remote_btn_1, '10'],\n                                [Lang.Blocks.neobot_think_car_lite_remote_btn_2, '11'],\n                                [Lang.Blocks.neobot_think_car_lite_remote_btn_3, '12'],\n                                [Lang.Blocks.neobot_think_car_lite_remote_btn_4, '13'],\n                                [Lang.Blocks.neobot_think_car_lite_remote_btn_up, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_remote_btn_down, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_remote_btn_left, '3'],\n                                [Lang.Blocks.neobot_think_car_lite_remote_btn_right, '4'],\n                            ],\n                            value: '10',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_think_car_lite_remote_button',\n                    },\n                    paramsKeyMap: {\n                        KEY: 0,\n                    },\n                    class: 'neobot_think_car_lite_sensor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const key = script.getNumberField('KEY');\n                        const value = Entry.NeobotThinkCarLite.localBuffer.IR;\n                        if (key == value) {\n                            return true;\n                        } else {\n                            return false;\n                        }\n                    },\n                },\n\n                /*************************\n                 * class neobot_think_car_lite_led\n                 *************************/\n                neobot_think_car_lite_led_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_think_car_lite_led_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_think_car_lite_led_title',\n                    },\n                    class: 'neobot_think_car_lite_led',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    events: {},\n                },\n                neobot_think_car_lite_led_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['100%', '255'],\n                                ['90%', '230'],\n                                ['80%', '204'],\n                                ['70%', '179'],\n                                ['60%', '153'],\n                                ['50%', '128'],\n                                ['40%', '102'],\n                                ['30%', '77'],\n                                ['20%', '51'],\n                                ['10%', '26'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neobot_think_car_lite_arg_led_duration',\n                                id: 'm311',\n                            },\n                            null,\n                        ],\n                        type: 'neobot_think_car_lite_led_on',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neobot_think_car_lite_led',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const value = script.getNumberField('VALUE', script);\n                            const duration = script.getStringValue('DURATION', script);\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_led_on ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`brightness : ${value}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            if (\n                                duration != '계속' &&\n                                duration != 'constantly' &&\n                                Entry.parseNumber(duration) <= 0\n                            ) {\n                                return script.callReturn();\n                            }\n\n                            if (port == 'ALL') {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = value;\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = value;\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = value;\n                            } else {\n                                Entry.NeobotThinkCarLite.remoteBuffer[port] = value;\n                            }\n\n                            if (duration == '계속' || duration == 'constantly') {\n                                return script.callReturn();\n                            }\n\n                            const durationValue = Entry.parseNumber(duration);\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            setTimeout(() => {\n                                if (port == 'ALL') {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = 0;\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = 0;\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = 0;\n                                } else {\n                                    Entry.NeobotThinkCarLite.remoteBuffer[port] = 0;\n                                }\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(\n                                        'neobot_think_car_lite_led_on : 0',\n                                        'speak'\n                                    );\n                                }\n                                script.timeFlag = 0;\n                            }, durationValue * 1000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n                neobot_think_car_lite_output_led_off: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_output_led_off',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_think_car_lite_led',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_think_car_lite_output_led_off ===',\n                                'speak'\n                            );\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = 0;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = 0;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = 0;\n                        } else {\n                            Entry.NeobotThinkCarLite.remoteBuffer[port] = 0;\n                        }\n                        return script.callReturn();\n                    },\n                },\n                neobot_think_car_lite_led_brightness_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'neobot_think_car_lite_led_brightness_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        IN: 0,\n                        OUT: 1,\n                    },\n                    class: 'neobot_think_car_lite_led',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const inPort = script.getStringField('IN', script);\n                        const outPort = script.getStringField('OUT', script);\n                        let value = Entry.NeobotThinkCarLite.localBuffer[inPort];\n\n                        // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함.\n                        value = Math.max(value, 0);\n                        value = Math.min(value, 100);\n                        value = Math.ceil((value / 100) * 255);\n\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_think_car_lite_led_brightness_with_sensor ===',\n                                'speak'\n                            );\n                            Entry.console.print(`out port : ${outPort}`, 'speak');\n                            Entry.console.print(`in port : ${inPort}`, 'speak');\n                            Entry.console.print(\n                                `sensor value : ${Entry.NeobotThinkCarLite.localBuffer[inPort]}`,\n                                'speak'\n                            );\n                            Entry.console.print(`output value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (outPort == 'ALL') {\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = value;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = value;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = value;\n                        } else {\n                            Entry.NeobotThinkCarLite.remoteBuffer[outPort] = value;\n                        }\n                        return script.callReturn();\n                    },\n                },\n                neobot_think_car_lite_color_led_on: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            null,\n                        ],\n                        type: 'neobot_think_car_lite_color_led_on',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        RED: 1,\n                        GREEN: 2,\n                        BLUE: 3,\n                    },\n                    class: 'neobot_think_car_lite_led',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT');\n                            let red = script.getNumberValue('RED');\n                            let green = script.getNumberValue('GREEN');\n                            let blue = script.getNumberValue('BLUE');\n\n                            let out1 = false;\n                            let out2 = false;\n                            let out3 = false;\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            } else {\n                                out1 = port == 'OUT1';\n                                out2 = port == 'OUT2';\n                                out3 = port == 'OUT3';\n                            }\n\n                            red = Math.max(red, 1);\n                            red = Math.min(red, 251);\n                            green = Math.max(green, 1);\n                            green = Math.min(green, 251);\n                            blue = Math.max(blue, 1);\n                            blue = Math.min(blue, 251);\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_color_led_on ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`red : ${red}`, 'speak');\n                                Entry.console.print(`green : ${green}`, 'speak');\n                                Entry.console.print(`blue : ${blue}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            const valRed = 252;\n                            const valGreen = 253;\n                            const valBlue = 254;\n                            const valAccept = 255;\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            if (out1) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = valRed;\n                            }\n                            if (out2) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = valRed;\n                            }\n                            if (out3) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = valRed;\n                            }\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_think_car_lite_color_led_on : ${valRed}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                // set red\n                                if (out1) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = red;\n                                }\n                                if (out2) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = red;\n                                }\n                                if (out3) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = red;\n                                }\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_think_car_lite_color_led_on : ${red}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    // choose green\n                                    if (out1) {\n                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = valGreen;\n                                    }\n                                    if (out2) {\n                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = valGreen;\n                                    }\n                                    if (out3) {\n                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = valGreen;\n                                    }\n                                    if (Entry.NeobotThinkCarLite.log_to_console) {\n                                        Entry.console.print(\n                                            `neobot_think_car_lite_color_led_on : ${valGreen}`,\n                                            'speak'\n                                        );\n                                    }\n                                    setTimeout(() => {\n                                        // set green\n                                        if (out1) {\n                                            Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = green;\n                                        }\n                                        if (out2) {\n                                            Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = green;\n                                        }\n                                        if (out3) {\n                                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = green;\n                                        }\n                                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                                            Entry.console.print(\n                                                `neobot_think_car_lite_color_led_on : ${green}`,\n                                                'speak'\n                                            );\n                                        }\n                                        setTimeout(() => {\n                                            // choose blue\n                                            if (out1) {\n                                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = valBlue;\n                                            }\n                                            if (out2) {\n                                                Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = valBlue;\n                                            }\n                                            if (out3) {\n                                                Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = valBlue;\n                                            }\n                                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                                Entry.console.print(\n                                                    `neobot_think_car_lite_color_led_on : ${valBlue}`,\n                                                    'speak'\n                                                );\n                                            }\n                                            setTimeout(() => {\n                                                // set blue\n                                                if (out1) {\n                                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = blue;\n                                                }\n                                                if (out2) {\n                                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = blue;\n                                                }\n                                                if (out3) {\n                                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = blue;\n                                                }\n                                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                                    Entry.console.print(\n                                                        `neobot_think_car_lite_color_led_on : ${blue}`,\n                                                        'speak'\n                                                    );\n                                                }\n                                                setTimeout(() => {\n                                                    // accept\n                                                    if (out1) {\n                                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = valAccept;\n                                                    }\n                                                    if (out2) {\n                                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = valAccept;\n                                                    }\n                                                    if (out3) {\n                                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = valAccept;\n                                                    }\n                                                    if (Entry.NeobotThinkCarLite.log_to_console) {\n                                                        Entry.console.print(\n                                                            `neobot_think_car_lite_color_led_on : ${valAccept}`,\n                                                            'speak'\n                                                        );\n                                                    }\n                                                    setTimeout(() => {\n                                                        // final delay\n                                                        script.timeFlag = 0;\n                                                    }, 200);\n                                                }, 200);\n                                            }, 200);\n                                        }, 200);\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                /*************************\n                 * class neobot_think_car_lite_output\n                 *************************/\n                neobot_think_car_lite_output_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_think_car_lite_output_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_think_car_lite_output_title',\n                    },\n                    class: 'neobot_think_car_lite_output',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    events: {},\n                },\n                neobot_think_car_lite_set_output: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            null,\n                        ],\n                        type: 'neobot_think_car_lite_set_output',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                    },\n                    class: 'neobot_think_car_lite_output',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        let value = script.getNumberValue('VALUE', script);\n                        if (value < 0) {\n                            value = 0;\n                        } else if (value > 255) {\n                            value = 255;\n                        }\n\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_think_car_lite_set_output ===',\n                                'speak'\n                            );\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = value;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = value;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = value;\n                        } else {\n                            Entry.NeobotThinkCarLite.remoteBuffer[port] = value;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_think_car_lite_motor\n                 *************************/\n                neobot_think_car_lite_motor_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_think_car_lite_motor_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_think_car_lite_motor_title',\n                    },\n                    class: 'neobot_think_car_lite_motor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    events: {},\n                },\n                neobot_think_car_lite_robot: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_motor_move_forward, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_motor_move_backward, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_motor_move_left, '3'],\n                                [Lang.Blocks.neobot_think_car_lite_motor_move_right, '4'],\n                                [Lang.Blocks.neobot_think_car_lite_motor_move_stop, '5'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_robot',\n                    },\n                    paramsKeyMap: {\n                        MOVE: 0,\n                    },\n                    class: 'neobot_think_car_lite_motor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const move = script.getNumberField('MOVE');\n                        let leftValue;\n                        let rightValue;\n                        switch (move) {\n                            case 1:\n                                leftValue = 0x10 + 10;\n                                rightValue = 0x10 + 10;\n                                break;\n                            case 2:\n                                leftValue = 0x20 + 10;\n                                rightValue = 0x20 + 10;\n                                break;\n                            case 3:\n                                leftValue = 0x20 + 5;\n                                rightValue = 0x10 + 5;\n                                break;\n                            case 4:\n                                leftValue = 0x10 + 5;\n                                rightValue = 0x20 + 5;\n                                break;\n                            case 5:\n                                leftValue = 0;\n                                rightValue = 0;\n                                break;\n                        }\n\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print('=== neobot_think_car_lite_robot ===', 'speak');\n                            Entry.console.print(`move : ${move}`, 'speak');\n                            Entry.console.print(`left value : ${leftValue}`, 'speak');\n                            Entry.console.print(`right value : ${rightValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotThinkCarLite.remoteBuffer.DCL = leftValue;\n                        Entry.NeobotThinkCarLite.remoteBuffer.DCR = rightValue;\n                        return script.callReturn();\n                    },\n                },\n                neobot_think_car_lite_motor_start: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_motor_both, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_motor_left, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_motor_right, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_direction_forward, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_direction_backward, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_direction_left, '3'],\n                                [Lang.Blocks.neobot_think_car_lite_direction_right, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                            {\n                                type: 'neobot_think_car_lite_arg_motor_speed',\n                                id: 'm411',\n                            },\n                            {\n                                type: 'neobot_think_car_lite_arg_motor_duration',\n                                id: 'm412',\n                            },\n                            null,\n                        ],\n                        type: 'neobot_think_car_lite_motor_start',\n                    },\n                    paramsKeyMap: {\n                        MOTOR: 0,\n                        DIRECTION: 1,\n                        SPEED: 2,\n                        DURATION: 3,\n                    },\n                    class: 'neobot_think_car_lite_motor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const motor = script.getStringField('MOTOR', script);\n                            const direction = script.getStringField('DIRECTION', script);\n                            const speed = script.getStringValue('SPEED', script);\n                            const duration = script.getStringValue('DURATION', script);\n\n                            if (\n                                duration != '계속' &&\n                                duration != 'constantly' &&\n                                Entry.parseNumber(duration) <= 0\n                            ) {\n                                return script.callReturn();\n                            }\n\n                            let moveLeft = false;\n                            let moveRight = false;\n                            if (motor == 1) {\n                                moveLeft = true;\n                                moveRight = true;\n                            } else if (motor == 2) {\n                                moveLeft = true;\n                            } else {\n                                moveRight = true;\n                            }\n\n                            let leftDirectionValue;\n                            let rightDirectionValue;\n                            if (direction == 1) {\n                                leftDirectionValue = 0x10;\n                                rightDirectionValue = 0x10;\n                            } else if (direction == 2) {\n                                leftDirectionValue = 0x20;\n                                rightDirectionValue = 0x20;\n                            } else if (direction == 3) {\n                                leftDirectionValue = 0x20;\n                                rightDirectionValue = 0x10;\n                            } else {\n                                leftDirectionValue = 0x10;\n                                rightDirectionValue = 0x20;\n                            }\n\n                            // edited 210421, 0~100 을 0~15로 변환, 100 이상은 최대값(15)으로 처리함.\n                            let speedValue = 0;\n                            if (Entry.Utils.isNumber(speed)) {\n                                speedValue = Entry.parseNumber(speed);\n                            } else {\n                                speedValue = Entry.NeobotThinkCarLite.localBuffer[speed];\n                            }\n                            speedValue = Math.max(speedValue, 0);\n                            speedValue = Math.min(speedValue, 100);\n                            speedValue = Math.ceil((speedValue / 100) * 15);\n\n                            const leftOutValue = leftDirectionValue + speedValue;\n                            const rightOutValue = rightDirectionValue + speedValue;\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_motor_start ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`motor : ${motor}`, 'speak');\n                                Entry.console.print(`direction : ${direction}`, 'speak');\n                                Entry.console.print(`speed : ${speed}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print(\n                                    `left direction value : ${leftDirectionValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print(\n                                    `right direction value : ${rightDirectionValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print(`speed value : ${speedValue}`, 'speak');\n                                Entry.console.print(`left output value : ${leftOutValue}`, 'speak');\n                                Entry.console.print(\n                                    `right output value : ${rightOutValue}`,\n                                    'speak'\n                                );\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            if (moveLeft) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.DCL = leftOutValue;\n                            }\n                            if (moveRight) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.DCR = rightOutValue;\n                            }\n\n                            if (duration == '계속' || duration == 'constantly') {\n                                return script.callReturn();\n                            }\n\n                            const durationValue = Entry.parseNumber(duration);\n                            script.isStart = true;\n                            script.timeFlag = 1;\n                            setTimeout(() => {\n                                Entry.NeobotThinkCarLite.remoteBuffer.DCL = 0;\n                                Entry.NeobotThinkCarLite.remoteBuffer.DCR = 0;\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(\n                                        'neobot_think_car_lite_motor_start : 0',\n                                        'speak'\n                                    );\n                                }\n                                script.timeFlag = 0;\n                            }, durationValue * 1000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n                neobot_think_car_lite_motor_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_motor_both, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_motor_left, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_motor_right, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_motor_stop',\n                    },\n                    paramsKeyMap: {\n                        MOTOR: 0,\n                    },\n                    class: 'neobot_think_car_lite_motor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const motor = script.getNumberField('MOTOR');\n\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_think_car_lite_motor_stop ===',\n                                'speak'\n                            );\n                            Entry.console.print(`motor : ${motor}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (motor == 1) {\n                            Entry.NeobotThinkCarLite.remoteBuffer.DCL = 0;\n                            Entry.NeobotThinkCarLite.remoteBuffer.DCR = 0;\n                        } else if (motor == 2) {\n                            Entry.NeobotThinkCarLite.remoteBuffer.DCL = 0;\n                        } else {\n                            Entry.NeobotThinkCarLite.remoteBuffer.DCR = 0;\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_think_car_lite_melody\n                 *************************/\n                neobot_think_car_lite_buzzer_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_think_car_lite_buzzer_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_think_car_lite_buzzer_title',\n                    },\n                    class: 'neobot_think_car_lite_melody',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    events: {},\n                },\n                neobot_think_car_lite_play_note_for: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_sound_silent, '0'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_do, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_do_shop, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_re, '3'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_re_shop, '4'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_mi, '5'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_fa, '6'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_fa_shop, '7'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_so, '8'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_so_shop, '9'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_la, '10'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_la_shop, '11'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_ti, '12'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                                ['6', '5'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_sound_half_note, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_quarter_note, '4'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_eighth_note, '8'],\n                                [Lang.Blocks.neobot_think_car_lite_sound_sixteenth_note, '16'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '2', '4', null],\n                        type: 'neobot_think_car_lite_play_note_for',\n                    },\n                    paramsKeyMap: {\n                        NOTE: 0,\n                        OCTAVE: 1,\n                        DURATION: 2,\n                    },\n                    class: 'neobot_think_car_lite_melody',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const note = script.getNumberField('NOTE', script);\n                            const octave = script.getNumberField('OCTAVE', script);\n                            const duration = script.getNumberField('DURATION', script);\n                            let value = note > 0 ? note + 12 * octave : 0;\n\n                            value = Math.min(value, 72);\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_play_note_for ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`note : ${note}`, 'speak');\n                                Entry.console.print(`octave : ${octave}`, 'speak');\n                                Entry.console.print(`duration : ${duration}`, 'speak');\n                                Entry.console.print(`value : ${value}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            Entry.NeobotThinkCarLite.remoteBuffer.SND = value;\n                            setTimeout(() => {\n                                Entry.NeobotThinkCarLite.remoteBuffer.SND = 0;\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(\n                                        'neobot_think_car_lite_play_note_for : 0',\n                                        'speak'\n                                    );\n                                }\n                                script.timeFlag = 0;\n                            }, (1 / duration) * 2000);\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n                neobot_think_car_lite_melody_play_with_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_think_car_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_think_car_lite_port_3, 'IN3'],\n                            ],\n                            value: 'IN1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_melody_play_with_sensor',\n                    },\n                    paramsKeyMap: {\n                        INPUT: 0,\n                    },\n                    class: 'neobot_think_car_lite_melody',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const input = script.getStringField('INPUT');\n                        let value = Entry.NeobotThinkCarLite.localBuffer[input];\n\n                        // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함.\n                        value = Math.max(value, 0);\n                        value = Math.min(value, 100);\n                        value = Math.ceil((value / 100) * 65);\n\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_think_car_lite_melody_play_with_sensor ===',\n                                'speak'\n                            );\n                            Entry.console.print(`input : ${input}`, 'speak');\n                            Entry.console.print(`value : ${value}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotThinkCarLite.remoteBuffer.SND = value;\n                        return script.callReturn();\n                    },\n                },\n                neobot_think_car_lite_melody_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'neobot_think_car_lite_melody_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'neobot_think_car_lite_melody',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_think_car_lite_melody_stop ===',\n                                'speak'\n                            );\n                            Entry.console.print('value : 0', 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        Entry.NeobotThinkCarLite.remoteBuffer.SND = 0;\n                        return script.callReturn();\n                    },\n                },\n\n                /*************************\n                 * class neobot_think_car_lite_servo\n                 *************************/\n                neobot_think_car_lite_servo_title: {\n                    color: EntryStatic.colorSet.common.TRANSPARENT,\n                    fontColor: '#191970',\n                    skeleton: 'basic_text',\n                    skeletonOptions: {\n                        contentPos: {\n                            x: 5,\n                        },\n                    },\n                    params: [\n                        {\n                            type: 'Text',\n                            text: Lang.template.neobot_think_car_lite_servo_title,\n                            color: '#191970',\n                            align: 'left',\n                        },\n                    ],\n                    def: {\n                        type: 'neobot_think_car_lite_servo_title',\n                    },\n                    class: 'neobot_think_car_lite_servo',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    events: {},\n                },\n                neobot_think_car_lite_servo_init: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_servo_init',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_think_car_lite_servo',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const resetValue = 186;\n                            const initValue = 1;\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_servo_init ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            let out1 = port == 'OUT1';\n                            let out2 = port == 'OUT2';\n                            let out3 = port == 'OUT3';\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            if (out1) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = resetValue;\n                            }\n                            if (out2) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = resetValue;\n                            }\n                            if (out3) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = resetValue;\n                            }\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_think_car_lite_servo_init : ${resetValue}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                if (out1) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = initValue;\n                                }\n                                if (out2) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = initValue;\n                                }\n                                if (out3) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = initValue;\n                                }\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_think_car_lite_servo_init : ${initValue}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    script.timeFlag = 0;\n                                }, 100);\n                            }, 200);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n                neobot_think_car_lite_servo_rotate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_servo_dir_1, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_servo_dir_2, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['0%', 0],\n                                ['10%', 10],\n                                ['20%', 20],\n                                ['30%', 30],\n                                ['40%', 40],\n                                ['50%', 50],\n                                ['60%', 60],\n                                ['70%', 70],\n                                ['80%', 80],\n                                ['90%', 90],\n                                ['100%', 100],\n                            ],\n                            value: 50,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'neobot_think_car_lite_servo_rotate',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        DIRECTION: 1,\n                        SPEED: 2,\n                    },\n                    class: 'neobot_think_car_lite_servo',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        const direction = script.getNumberField('DIRECTION');\n                        const speed = script.getStringField('SPEED');\n\n                        let directionValue = 192; // 정방향\n                        if (direction == 2) {\n                            directionValue = 208; // 역방향\n                        }\n                        let speedValue;\n                        if (Entry.Utils.isNumber(speed)) {\n                            speedValue = Entry.parseNumber(speed);\n                        } else {\n                            speedValue = Entry.NeobotThinkCarLite.localBuffer[speed];\n                        }\n\n                        // edited 210421, 0~100 을 0~10 으로 변환\n                        speedValue = Math.max(speedValue, 0);\n                        speedValue = Math.min(speedValue, 100);\n                        speedValue = Math.ceil(speedValue / 10);\n\n                        let outValue = directionValue + speedValue;\n                        if (outValue == directionValue) {\n                            outValue = 254;\n                        } else {\n                            outValue = outValue - 1;\n                        }\n\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print('=== neobot_think_car_lite_servo_rotate ===');\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`direction : ${direction}`, 'speak');\n                            Entry.console.print(`speed : ${speed}`, 'speak');\n                            Entry.console.print(`direction value : ${directionValue}`, 'speak');\n                            Entry.console.print(`speed value : ${speedValue}`, 'speak');\n                            Entry.console.print(`output value : ${outValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = outValue;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = outValue;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = outValue;\n                        } else {\n                            Entry.NeobotThinkCarLite.remoteBuffer[port] = outValue;\n                        }\n                        return script.callReturn();\n                    },\n                },\n                neobot_think_car_lite_servo_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'neobot_think_car_lite_servo_stop',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'neobot_think_car_lite_servo',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        const port = script.getStringField('PORT', script);\n                        const outValue = 254;\n\n                        if (Entry.NeobotThinkCarLite.log_to_console) {\n                            Entry.console.print(\n                                '=== neobot_think_car_lite_servo_stop ===',\n                                'speak'\n                            );\n                            Entry.console.print(`port : ${port}`, 'speak');\n                            Entry.console.print(`output value: ${outValue}`, 'speak');\n                            Entry.console.print('==========================', 'speak');\n                        }\n\n                        if (port == 'ALL') {\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = outValue;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = outValue;\n                            Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = outValue;\n                        } else {\n                            Entry.NeobotThinkCarLite.remoteBuffer[port] = outValue;\n                        }\n                        return script.callReturn();\n                    },\n                },\n                neobot_think_car_lite_servo_change_degree: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['OUT1', 'OUT1'],\n                                ['OUT2', 'OUT2'],\n                                ['OUT3', 'OUT3'],\n                                [Lang.Blocks.neobot_think_car_lite_out_all, 'ALL'],\n                            ],\n                            value: 'OUT1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_servo_dir_1, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_servo_dir_2, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['0%', 0],\n                                ['10%', 10],\n                                ['20%', 20],\n                                ['30%', 30],\n                                ['40%', 40],\n                                ['50%', 50],\n                                ['60%', 60],\n                                ['70%', 70],\n                                ['80%', 80],\n                                ['90%', 90],\n                                ['100%', 100],\n                            ],\n                            value: 50,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'get_servo_degree',\n                                id: 'm211',\n                            },\n                            null,\n                            null,\n                            null,\n                            null,\n                        ],\n                        type: 'neobot_think_car_lite_servo_change_degree',\n                    },\n                    paramsKeyMap: {\n                        DEGREE: 0,\n                        PORT: 1,\n                        DIRECTION: 2,\n                        SPEED: 3,\n                    },\n                    class: 'neobot_think_car_lite_servo',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        if (!script.isStart) {\n                            const port = script.getStringField('PORT', script);\n                            const direction = script.getNumberField('DIRECTION');\n                            const speed = script.getStringValue('SPEED');\n                            const degree = script.getStringValue('DEGREE');\n\n                            let out1 = port == 'OUT1';\n                            let out2 = port == 'OUT2';\n                            let out3 = port == 'OUT3';\n                            if (port == 'ALL') {\n                                out1 = true;\n                                out2 = true;\n                                out3 = true;\n                            }\n\n                            let directionValue = 188;\n                            if (direction == 2) {\n                                directionValue = 189;\n                            }\n\n                            let speedValue;\n                            if (Entry.Utils.isNumber(speed)) {\n                                speedValue = Entry.parseNumber(speed);\n                            } else {\n                                speedValue = Entry.NeobotThinkCarLite.localBuffer[speed];\n                            }\n\n                            // edited 210421, 0~100 을 240~250 으로 변환\n                            speedValue = Math.max(speedValue, 0);\n                            speedValue = Math.min(speedValue, 100);\n                            speedValue = Math.ceil(speedValue / 10) + 240;\n\n                            let degreeValue;\n                            if (Entry.Utils.isNumber(degree)) {\n                                degreeValue = Entry.parseNumber(degree);\n                            } else {\n                                if (degree == 'IN1' || degree == 'IN2' || degree == 'IN3') {\n                                    degreeValue = Entry.NeobotThinkCarLite.localBuffer[degree];\n                                } else {\n                                    degreeValue = 0;\n                                }\n                            }\n                            // edited 210421, 별도의 변환없이 그대로 사용함\n                            degreeValue = Math.max(degreeValue, 0);\n                            degreeValue = Math.min(degreeValue, 180);\n                            degreeValue = degreeValue + 1;\n\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    '=== neobot_think_car_lite_servo_change_degree ===',\n                                    'speak'\n                                );\n                                Entry.console.print(`port : ${port}`, 'speak');\n                                Entry.console.print(`direction : ${direction}`, 'speak');\n                                Entry.console.print(`speed : ${speed}`, 'speak');\n                                Entry.console.print(`degree : ${degree}`, 'speak');\n                                Entry.console.print(`directionValue : ${directionValue}`, 'speak');\n                                Entry.console.print(`speedValue : ${speedValue}`, 'speak');\n                                Entry.console.print(`degreeValue : ${degreeValue}`, 'speak');\n                                Entry.console.print('==========================', 'speak');\n                            }\n\n                            script.isStart = true;\n                            script.timeFlag = 1;\n\n                            // direction\n                            if (out1) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = directionValue;\n                            }\n                            if (out2) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = directionValue;\n                            }\n                            if (out3) {\n                                Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = directionValue;\n                            }\n                            if (Entry.NeobotThinkCarLite.log_to_console) {\n                                Entry.console.print(\n                                    `neobot_think_car_lite_servo_change_degree : ${directionValue}`,\n                                    'speak'\n                                );\n                            }\n                            setTimeout(() => {\n                                // speed\n                                if (out1) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = speedValue;\n                                }\n                                if (out2) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = speedValue;\n                                }\n                                if (out3) {\n                                    Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = speedValue;\n                                }\n                                if (Entry.NeobotThinkCarLite.log_to_console) {\n                                    Entry.console.print(\n                                        `neobot_think_car_lite_servo_change_degree : ${speedValue}`,\n                                        'speak'\n                                    );\n                                }\n                                setTimeout(() => {\n                                    // degree\n                                    if (out1) {\n                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT1 = degreeValue;\n                                    }\n                                    if (out2) {\n                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT2 = degreeValue;\n                                    }\n                                    if (out3) {\n                                        Entry.NeobotThinkCarLite.remoteBuffer.OUT3 = degreeValue;\n                                    }\n                                    if (Entry.NeobotThinkCarLite.log_to_console) {\n                                        Entry.console.print(\n                                            `neobot_think_car_lite_servo_change_degree : ${degreeValue}`,\n                                            'speak'\n                                        );\n                                    }\n                                    setTimeout(() => {\n                                        // final delay\n                                        script.timeFlag = 0;\n                                    }, 200);\n                                }, 200);\n                            }, 200);\n\n                            return script;\n                        } else if (script.timeFlag == 1) {\n                            return script;\n                        } else {\n                            delete script.timeFlag;\n                            delete script.isStart;\n                            Entry.engine.isContinue = false;\n                            return script.callReturn();\n                        }\n                    },\n                },\n\n                /*****************\n                 * ARG Blocks\n                 *****************/\n                neobot_think_car_lite_arg_led_duration: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_duration_cont, '계속'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_1s, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_2s, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_3s, '3'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_4s, '4'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_5s, '5'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_6s, '6'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_7s, '7'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_8s, '8'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_9s, '9'],\n                            ],\n                            value: '계속',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_think_car_lite_led',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                neobot_think_car_lite_arg_motor_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['IN1', 'IN1'],\n                                ['IN2', 'IN2'],\n                                ['IN3', 'IN3'],\n                                ['100%', 100],\n                                ['90%', 90],\n                                ['80%', 80],\n                                ['70%', 70],\n                                ['60%', 60],\n                                ['50%', 50],\n                                ['40%', 40],\n                                ['30%', 30],\n                                ['20%', 20],\n                                ['10%', 10],\n                                ['0%', 0],\n                            ],\n                            value: 100,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_think_car_lite_motor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                neobot_think_car_lite_arg_motor_duration: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_duration_cont, '계속'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_1s, '1'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_2s, '2'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_3s, '3'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_4s, '4'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_5s, '5'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_6s, '6'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_7s, '7'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_8s, '8'],\n                                [Lang.Blocks.neobot_think_car_lite_duration_9s, '9'],\n                            ],\n                            value: '계속',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_think_car_lite_motor',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n\n                get_servo_degree: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.neobot_think_car_lite_port_1, 'IN1'],\n                                [Lang.Blocks.neobot_think_car_lite_port_2, 'IN2'],\n                                [Lang.Blocks.neobot_think_car_lite_port_3, 'IN3'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_0, '0'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_5, '5'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_10, '10'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_15, '15'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_20, '20'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_25, '25'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_30, '30'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_35, '35'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_40, '40'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_45, '45'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_50, '50'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_55, '55'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_60, '60'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_65, '65'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_70, '70'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_75, '75'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_80, '80'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_85, '85'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_90, '90'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_95, '95'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_100, '100'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_105, '105'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_110, '110'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_115, '115'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_120, '120'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_125, '125'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_130, '130'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_135, '135'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_140, '140'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_145, '145'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_150, '150'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_155, '155'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_160, '160'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_165, '165'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_170, '170'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_175, '175'],\n                                [Lang.Blocks.neobot_think_car_lite_angle_180, '180'],\n                            ],\n                            value: '90',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'neobot_think_car_lite_servo',\n                    isNotFor: ['NeobotThinkCarLite'],\n                    func(sprite, script) {\n                        return script.getStringField('VALUE');\n                    },\n                },\n            };\n        };\n    })();\n})();\n\nmodule.exports = Entry.NeobotThinkCarLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_robolink_ZumiMini_lite.js",
    "content": "'use strict';\n\nconst CommandType = {\n    COMMAND_NONE: 0,\n    COMMAND_GOGO: 1,\n    COMMAND_LEFT: 2,\n    COMMAND_RIGHT: 3,\n    COMMAND_GOBACK: 4,\n    COMMAND_WAIT: 5,\n    COMMAND_WAIT1: 6,\n    COMMAND_SPEAK: 7,\n    COMMAND_HUMAN: 8,\n    COMMAND_HAND: 9,\n    COMMAND_LED: 10,\n\n    COMMAND_COLOR_RED: 19,\n    COMMAND_COLOR_GREEN: 20,\n    COMMAND_CARD_NUM1: 21,\n    COMMAND_CARD_NUM2: 22,\n    COMMAND_CARD_NUM3: 23,\n    COMMAND_MOTION_STOP: 25,\n\n    COMMAND_GO_UNTIL_DIST: 26,\n    COMMAND_FREE_TURN: 27,\n    COMMAND_LINE_TRACE_DIST: 28,\n    COMMAND_GO_INFINITE: 29,\n    COMMAND_TRACE_INFINITE: 30,\n\n    COMMAND_LED_CONTROL: 31,\n    COMMAND_MOTOR1_INFINITE: 32,\n    COMMAND_MOTOR2_INFINITE: 33,\n    COMMAND_LED_INFINITE: 34,\n\n    COMMAND_CONTROL_MODE1: 35,\n\n    COMMAND_LINE_LEFT: 39,\n    COMMAND_LINE_RIGHT: 40,\n\n    COMMAND_MOTOR_TIME: 41,\n\n    COMMAND_QUICK_GOGO: 50,\n    COMMAND_QUICK_GOBACK: 51,\n    COMMAND_QUICK_LEFT: 52,\n    COMMAND_QUICK_RIGHT: 53,\n\n    COMMAND_FREE_TURN_PYTHON: 70,\n\n    COMMAND_GOSENSOR: 100,\n    COMMAND_LINE_TRACING: 101,\n    COMMAND_COLOR_TRACKING: 102,\n\n    COMMAND_ROBOT_LINE: 103,\n    COMMAND_ROBOT_AVOIDANCE: 104,\n    COMMAND_ROBOT_FOLLOWER: 105,\n    COMMAND_ROBOT_CLIFF: 106,\n\n    COMMAND_SET_IR_THREADHOLD: 150,\n    COMMAND_SET_MOTOR_DEGREE: 151,\n\n    COMMAND_CONTROL_LED: 200,\n    COMMAND_PATTERN_LED: 201,\n\n    COMMAND_COLOR_TRACKING2: 211,\n    COMMAND_COLOR_TRACKING3: 212,\n\n    COMMAND_TEXT_INPUT: 230,\n    COMMAND_TEXT_SET: 231,\n    COMMAND_TEXT_ADD: 232,\n\n    COMMAND_SCREEN_TOGGLE: 240,\n    COMMAND_EMOTION_CHANGE: 241,\n    COMMAND_PLAY_SOUND: 242,\n\n    COMMAND_MOTOR_CALIBRATION_READ: 245,\n    COMMAND_MOTOR_CALIBRATION_START: 247,\n};\n\nconst CommandType_DATA_LENGTH = {\n    COMMAND_NONE: 0,\n    COMMAND_GOGO: 1,\n    COMMAND_LEFT: 1,\n    COMMAND_RIGHT: 1,\n    COMMAND_GOBACK: 1,\n    COMMAND_WAIT: 4,\n    COMMAND_WAIT1: 5,\n    COMMAND_SPEAK: 8,\n    COMMAND_HUMAN: 4,\n    COMMAND_HAND: 9,\n    COMMAND_LED: 3,\n\n    COMMAND_COLOR_RED: 19,\n    COMMAND_COLOR_GREEN: 20,\n    COMMAND_CARD_NUM1: 21,\n    COMMAND_CARD_NUM2: 22,\n    COMMAND_CARD_NUM3: 23,\n    COMMAND_MOTION_STOP: 0,\n\n    COMMAND_GO_UNTIL_DIST: 3,\n    COMMAND_FREE_TURN: 27,\n    COMMAND_LINE_TRACE_DIST: 2,\n    COMMAND_GO_INFINITE: 3,\n    COMMAND_TRACE_INFINITE: 1,\n\n    COMMAND_LED_CONTROL: 3,\n    COMMAND_MOTOR1_INFINITE: 3,\n    COMMAND_MOTOR2_INFINITE: 3,\n    COMMAND_LED_INFINITE: 34,\n\n    COMMAND_CONTROL_MODE1: 35,\n\n    COMMAND_LINE_LEFT: 39,\n    COMMAND_LINE_RIGHT: 40,\n\n    COMMAND_MOTOR_TIME: 41,\n\n    COMMAND_QUICK_GOGO: 1,\n    COMMAND_QUICK_GOBACK: 1,\n    COMMAND_QUICK_LEFT: 1,\n    COMMAND_QUICK_RIGHT: 1,\n\n    COMMAND_FREE_TURN_PYTHON: 4,\n\n    COMMAND_GOSENSOR: 3,\n    COMMAND_LINE_TRACING: 5,\n    COMMAND_COLOR_TRACKING: 102,\n\n    COMMAND_ROBOT_LINE: 103,\n    COMMAND_ROBOT_AVOIDANCE: 104,\n    COMMAND_ROBOT_FOLLOWER: 105,\n    COMMAND_ROBOT_CLIFF: 106,\n\n    COMMAND_SET_IR_THREADHOLD: 150,\n    COMMAND_SET_MOTOR_DEGREE: 151,\n\n    COMMAND_CONTROL_LED: 200,\n    COMMAND_PATTERN_LED: 3,\n\n    COMMAND_COLOR_TRACKING2: 211,\n    COMMAND_COLOR_TRACKING3: 212,\n\n    COMMAND_TEXT_INPUT: 1,\n    COMMAND_TEXT_SET: 5,\n    COMMAND_TEXT_ADD: 1,\n\n    COMMAND_SCREEN_TOGGLE: 1,\n    COMMAND_EMOTION_CHANGE: 1,\n    COMMAND_PLAY_SOUND: 1,\n};\n\n\nconst RequestType = {\n    REQUEST_ENTRY_FACE_DETECT: 0x01,\n    REQUEST_ENTRY_COLOR_DETECT: 0x02,\n    REQUEST_ENTRY_APRIL_DETECT: 0x04,\n    REQUEST_ENTRY_CAT_DETECT: 0x10,\n};\n\nconst PacketIndex = {\n    DATA_COM: 2,\n    DATA_INFO: 2,\n    DATA_REQ: 3,\n    DATA_PSTAT: 4,\n    DATA_SEN_FR: 5,\n    DATA_SEN_FL: 6,\n    DATA_SEN_BR: 7,\n    DATA_SEN_BC: 8,\n    DATA_SEN_BL: 9,\n\n    DATA_DETECT_FACE: 10,\n    DATA_DETECT_FACE_X: 11,\n    DATA_DETECT_FACE_Y: 12,\n\n    DATA_DETECT_COLOR: 13,\n    DATA_DETECT_COLOR_X: 14,\n    DATA_DETECT_COLOR_Y: 15,\n\n    DATA_DETECT_MARKER: 16,\n    DATA_DETECT_MARKER_X: 17,\n    DATA_DETECT_MARKER_Y: 18,\n\n    DATA_BTN_INPUT: 19,\n    DATA_BATTERY: 20,\n\n    DATA_DETECT_CAT: 23,\n    DATA_DETECT_CAT_X: 24,\n    DATA_DETECT_CAT_Y: 25\n};\n\n(function() {\n    Entry.ZumiMiniLite = new (class ZumiMiniLite {\n        constructor() {\n            this.id = '4A0501';\n            this.name = 'ZumiMiniLite';\n            this.url = 'http://www.robolink.co.kr/';\n            this.imageName = 'robolink_ZumiMini_lite.png';\n            this.title = {\n                ko: '로보링크 주미 미니',\n                en: 'Robolink zumi mini',\n            };\n\n            this.duration = 50;\n\n            this.blockMenuBlocks = [\n                'zumiMiniLite_motor_control',\n                'zumiMiniLite_move_straight',\n                'zumiMiniLite_move_straight_infinite',\n                'zumiMiniLite_move_turn',\n                'zumiMiniLite_motion_stop',\n\n                'zumiMiniLite_going_forward_until_sensing',\n                'zumiMiniLite_following_line_until_sensing',\n                'zumiMiniLite_following_line_dist',\n                'zumiMiniLite_following_line_infinite',\n\n                'zumiMiniLite_LED_control',\n                'zumiMiniLite_button_boolean_input',\n\n                'zumiMiniLite_screen_toggle',\n                'zumiMiniLite_emotion',\n\n                'zumiMiniLite_face_boolean_detector',\n                'zumiMiniLite_color_boolean_detector',\n                'zumiMiniLite_april_boolean_detector',\n\n                'zumiMiniLite_front_sensor',\n                'zumiMiniLite_bottom_sensor',\n                'zumiMiniLite_button_input',\n                'zumiMiniLite_face_detector',\n                'zumiMiniLite_cat_face_detector',\n                'zumiMiniLite_color_detector',\n                'zumiMiniLite_april_detector',\n                'zumiMiniLite_power_info'\n            ];\n\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                //connectionType: 'bytestream',\n                bufferSize: 1024,\n                constantServing: true,\n                connectionType: 'bytestream',\n            };\n\n            this.StateLoading = {\n                Ready: 0x00,\n                Receiving: 0x01,\n                Loaded: 0x02,\n                Failure: 0x03\n            };\n\n            this.Section = {\n                Start: 0x00,\n                Header:0x01,\n                Data: 0x02,\n                End: 0x03\n            };\n\n            this.PACKET_DATA_LENGTH = 24;\n            this.PACKET_START_BYTE1 = 0x24;\n            this.PACKET_START_BYTE2 = 0x52;\n            this.HEADER_LENGTH = 2;\n\n            this.receiverState = this.StateLoading.Ready;\n            this.receiverSection = this.Section.Start;\n            this.receiverIndex = 0;\n            this.receiverBuffer = [];\n            this.receiverData = [];\n            this.receiverMessage = null;\n            this.receiverSectionOld = this.Section.End;\n\n            this.reqINFO = 0;\n            this.reqREQ = 0;\n            this.reqPSTAT = 0;\n            this.btn = 0;\n            this.battery = 0;\n\n            this.senFL = 0;\n            this.senFR = 0;\n            this.senBL = 0;\n            this.senBC = 0;\n            this.senBR = 0;\n\n            this.zumiFaceDetected = false;\n            this.zumiFaceCenter = [0, 0];\n            this.zumiColorDetected = 0;\n            this.zumiColorCenter = [0, 0];\n            this.zumiMarkerDetected = 0;\n            this.zumiMarkerCenter = [0, 0];\n            this.zumiCatDetected = 0;\n            this.zumiCatCenter = [0, 0];\n\n            this.current_request = 0;\n            this.sendBuffers = [];\n\n            this.tSpd = 0;\n            this.tDir = 0;\n            this.motorTrigger = false;\n\n            this.setZero();\n        }\n\n        // get monitorTemplate() {\n        //     return {\n        //     };\n        // }\n        // getMonitorPort() {\n        //     return {\n        //     }\n        // }\n\n        setZero() {\n            this.current_request = 0;\n\n            this.sendBuffers = [];\n\n            this.motorTrigger = false;\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n        async initialHandshake() {\n            //console.log(\"initialHandshake\");\n            const runApp0 = [0x24, 0x52, 0x19, 0x00]; //stop\n            await Entry.hwLite.serial.sendAsync(runApp0);\n\n            return true;\n        }\n\n\n        handleLocalData(data) {\n            if (!this.bufferHandler) {\n                this.bufferHandler = [];\n            }\n\n            for (const byte of data) {\n                this.bufferHandler.push(byte);\n            }\n\n            while (this.bufferHandler.length > 0) {\n                const byte = this.bufferHandler.shift();\n                const stateLoading = this._processReceiverByte(byte);\n                if (stateLoading === this.StateLoading.Loaded) {\n                    this._updateDataStore(this.receiverData);\n                    this._resetReceiverState();\n                    continue;\n                }\n                if (stateLoading === this.StateLoading.Failure) {\n                    this._resetReceiverState();\n                }\n            }\n        }\n\n        requestLocalData() {\n            const dataToSend = Entry.ZumiMiniLite.sendBuffers;\n\n            if(Entry.ZumiMiniLite.sendBuffers.length === 0)\n            {\n                if(this.motorTrigger == true)\n                {\n                    const sendACK= [0x24,0x52,CommandType.COMMAND_MOTOR1_INFINITE,this.current_request,this.tSpd,0x00,this.tDir]; //motor infinite\n                    return sendACK;\n                }\n                else\n                {\n                    const sendACK= [0x24,0x52,0x00,this.current_request,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF]; //stop\n                    return sendACK;\n                }\n            }\n            else\n            {\n                if((dataToSend[2] == CommandType.COMMAND_MOTOR1_INFINITE) || (dataToSend[2] == CommandType.COMMAND_MOTOR2_INFINITE))\n                {\n                   this.motorTrigger = true;\n                }\n                else\n                {\n                    this.motorTrigger = false;\n                }\n            }\n\n            Entry.ZumiMiniLite.sendBuffers = [];\n            return dataToSend;\n        }\n\n        // requestLocalData() {\n        //     const dataToSend = Entry.ZumiMiniLite.sendBuffers;\n        //     if(Entry.ZumiMiniLite.sendBuffers.length === 0)\n        //     {\n        //        // console.log(\"null data\");\n        //         const sendACK= [0x24,0x52,0x00,this.current_request,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF]; //stop\n        //         return sendACK;\n        //     }\n        //     Entry.ZumiMiniLite.sendBuffers = [];\n        //     return dataToSend;\n        // }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        zumiMiniLite_go_forward: '앞으로 가기(10cm) %1',\n                        zumiMiniLite_go_back: '뒤로 가기(10cm) %1',\n                        zumiMiniLite_turn_left: '왼쪽으로 회전 %1',\n                        zumiMiniLite_turn_right: '오른쪽으로 회전 %1',\n                        zumiMiniLite_going_forward_until_sensing: '물체 감지할 때까지 앞으로 가기 %1',\n                        zumiMiniLite_following_line_until_sensing: '교차로 만날 때까지 선 따라가기 %1',\n                        zumiMiniLite_front_sensor: '앞 센서 %1 %2',\n                        zumiMiniLite_bottom_sensor: '바닥 센서 %1 %2',\n                        zumiMiniLite_button_input: '버튼 입력 %1',\n                        zumiMiniLite_button_boolean_input: '%1 이 %2',\n                        zumiMiniLite_face_detector: 'AI 얼굴 %1 %2',\n                        zumiMiniLite_cat_face_detector: 'AI 고양이 얼굴 %1 %2',\n                        zumiMiniLite_face_boolean_detector: '%1 이 감지 되었을 때',\n                        zumiMiniLite_color_detector: 'AI 컬러 감지 %1 %2',\n                        zumiMiniLite_color_boolean_detector: '%1 이 감지되었을 때',\n                        zumiMiniLite_april_detector: '마커 감지 %1 %2',\n                        zumiMiniLite_april_boolean_detector: '마커 %1 이 감지되었을 때',\n                        zumiMiniLite_IMU_sensor: '자세 측정 %1 %2',\n                        zumiMiniLite_move_straight: '이동하기 방향 %1 속도 %2 거리 %3cm %4',\n                        zumiMiniLite_move_turn: '회전하기 방향 %1 속도 %2 각도 %3도 %4',\n                        zumiMiniLite_following_line_dist: '선 따라가기 속도 %1 거리 %2cm %3',\n                        zumiMiniLite_move_straight_infinite: '계속 이동하기 방향 %1 속도 %2 %3',\n                        zumiMiniLite_following_line_infinite: '계속 선 따라가기 속도 %1 %2',\n                        zumiMiniLite_motion_stop: '이동 멈추기 %1',\n                        zumiMiniLite_screen_toggle: '화면 바꾸기 %1 %2',\n                        zumiMiniLite_emotion: '표정 변화 %1 %2',\n                        zumiMiniLite_play_sound: '소리내기 %1 %2',\n                        zumiMiniLite_LED_control: 'LED 불빛 %1 효과 %2 동작 %3 %4',\n                        zumiMiniLite_motor_control: '모터 %1 방향 %2 속도 %3 %4',\n                        zumiMiniLite_power_info: '배터리 %1',\n                    },\n                    Blocks: {\n                        zumiMiniLite_fl: '왼쪽',\n                        zumiMiniLite_fr: '오른쪽',\n                        zumiMiniLite_bl: '왼쪽',\n                        zumiMiniLite_bm: '가운데',\n                        zumiMiniLite_br: '오른쪽',\n                        zumiMiniLite_color: '색상',\n                        zumiMiniLite_ai_red: '빨강',\n                        zumiMiniLite_ai_orange: '주황',\n                        zumiMiniLite_ai_yellow: '노랑',\n                        zumiMiniLite_ai_green: '녹색',\n                        zumiMiniLite_ai_cyan: '청록',\n                        zumiMiniLite_ai_blue: '파랑',\n                        zumiMiniLite_ai_purple: '보라',\n                        zumiMiniLite_red: '빨강',\n                        zumiMiniLite_green: '녹색',\n                        zumiMiniLite_blue: '파랑',\n                        zumiMiniLite_yellow: '노랑',\n                        zumiMiniLite_sky_blue: '청록',\n                        zumiMiniLite_pink: '분홍',\n                        zumiMiniLite_white: '하양',\n                        zumiMiniLite_led_normal: '기본',\n                        zumiMiniLite_led_blink: '깜빡임',\n                        zumiMiniLite_led_flicker: '깜빡임2',\n                        zumiMiniLite_led_dimming: '디밍',\n                        zumiMiniLite_led_sunrise: '서서히 밝아짐',\n                        zumiMiniLite_led_sunset: '서서히 어두워짐',\n                        zumiMiniLite_led_rainbow: '무지개',\n                        zumiMiniLite_on: '켜기',\n                        zumiMiniLite_off: '끄기',\n                        zumiMiniLite_cat: '고양이얼굴',\n                        zumiMiniLite_human: '사람얼굴',\n                        zumiMiniLite_detect: '감지',\n                        zumiMiniLite_cx: 'x좌표',\n                        zumiMiniLite_cy: 'y좌표',\n                        zumiMiniLite_id: '번호',\n                        zumiMiniLite_pitch: '피치',\n                        zumiMiniLite_roll: '롤',\n                        zumiMiniLite_yaw: '요우',\n                        zumiMiniLite_forward: '전진',\n                        zumiMiniLite_backward: '후진',\n                        zumiMiniLite_rapid: '빠르게',\n                        zumiMiniLite_mid: '보통',\n                        zumiMiniLite_slow: '느리게',\n                        zumiMiniLite_left: '왼쪽',\n                        zumiMiniLite_right: '오른쪽',\n                        zumiMiniLite_camera: '카메라',\n                        zumiMiniLite_emotion: '표정',\n                        zumiMiniLite_emo_chaos: '혼란',\n                        zumiMiniLite_emo_smile: '미소',\n                        zumiMiniLite_emo_love: '사랑',\n                        zumiMiniLite_emo_crash: '안돼!',\n                        zumiMiniLite_emo_surprise: '놀람',\n                        zumiMiniLite_emo_nice: '신남',\n                        zumiMiniLite_emo_cantbelieve: '미심쩍음',\n                        zumiMiniLite_emo_sleep: '졸림',\n                        zumiMiniLite_emo_cry: '슬픔',\n                        zumiMiniLite_emo_wink: '윙크',\n                        zumiMiniLite_emo_blink: '깜빡깜빡',\n                        zumiMiniLite_emo_sleeping: '잠듬',\n                        zumiMiniLite_snd_user: '사용자 녹음',\n                        zumiMiniLite_snd_cat: '고양이',\n                        zumiMiniLite_snd_shutter: '셔터',\n                        zumiMiniLite_snd_fail: '실패',\n                        zumiMiniLite_snd_success: '성공',\n                        zumiMiniLite_snd_fail2: '경고',\n                        zumiMiniLite_snd_honk: '경적',\n                        zumiMiniLite_snd_honk2: '경적2',\n                        zumiMiniLite_snd_siren: '사이렌',\n                        zumiMiniLite_m1: '왼쪽 모터',\n                        zumiMiniLite_m2: '오른쪽 모터',\n                        zumiMiniLite_cw: '전진방향',\n                        zumiMiniLite_ccw: '후진방향',\n                        zumiMiniLite_stop: '멈춤',\n                        zumiMiniLite_red_btn: '빨강버튼',\n                        zumiMiniLite_blue_btn: '파랑버튼',\n                        zumiMiniLite_yellow_btn: '노랑버튼',\n                        zumiMiniLite_green_btn: '녹색버튼',\n                        zumiMiniLite_pressed: '눌렀을 때',\n                        zumiMiniLite_released: '눌리지 않았을 때',\n                    }\n                },\n                en: {\n                    template: {\n                        zumiMiniLite_go_forward: 'going forward(10cm) %1',\n                        zumiMiniLite_go_back: 'going back(10cm) %1',\n                        zumiMiniLite_turn_left: 'turning left %1',\n                        zumiMiniLite_turn_right: 'turning right %1',\n                        zumiMiniLite_going_forward_until_sensing: 'going forward until sensing the object %1',\n                        zumiMiniLite_following_line_until_sensing: 'following the line until meet the intersection %1',\n                        zumiMiniLite_front_sensor: 'front sensor %1 %2',\n                        zumiMiniLite_bottom_sensor: 'bottom sensor %1 %2',\n                        zumiMiniLite_button_inpput: 'button input %1',\n                        zumiMiniLite_button_boolean_input: 'when %1 %2',\n                        zumiMiniLite_face_detector: 'AI face %1 %2',\n                        zumiMiniLite_cat_face_detector: 'AI cat face %1 %2',\n                        zumiMiniLite_face_boolean_detector: 'when %1 is detected',\n                        zumiMiniLite_color_detector: 'AI color detection %1 %2',\n                        zumiMiniLite_color_boolean_detector: 'when %1 is detected',\n                        zumiMiniLite_april_detector: 'apriltag detection %1 %2',\n                        zumiMiniLite_april_boolean_detector: 'when apriltag %1 is detected',\n                        zumiMiniLite_IMU_sensor: ' inertial mesurement %1 %2',\n                        zumiMiniLite_move_straight: 'move direction %1 speed %2 distance %3 cm %4',\n                        zumiMiniLite_move_turn: 'turn %1 speed %2 degree %3 %4',\n                        zumiMiniLite_following_line_dist: 'line following speed %1 distance %2 %3',\n                        zumiMiniLite_move_straight_infinite: 'keep moving direction %1 speed %2 %3',\n                        zumiMiniLite_following_line_infinite: 'keep following line %1 %2',\n                        zumiMiniLite_motion_stop: 'stop moving %1',\n                        zumiMiniLite_screen_toggle: 'toggle screen %1 %2',\n                        zumiMiniLite_emotion: 'change emotion %1 %2',\n                        zumiMiniLite_play_sound: 'play sound %1 %2',\n                        zumiMiniLite_LED_control: 'LED light %1 effect %2 acttion %3 %4',\n                        zumiMiniLite_motor_control: 'motor %1 direction %2 speed %3 %4',\n                        zumiMiniLite_power_info: 'battery %1',\n                    },\n                    Blocks: {\n                        zumiMiniLite_fl: 'left',\n                        zumiMiniLite_fr: 'right',\n                        zumiMiniLite_bl: 'left',\n                        zumiMiniLite_bm: 'middle',\n                        zumiMiniLite_br: 'right',\n                        zumiMiniLite_color: 'color',\n                        zumiMiniLite_ai_red: 'red',\n                        zumiMiniLite_ai_orange: 'orange',\n                        zumiMiniLite_ai_yellow: 'yellow',\n                        zumiMiniLite_ai_green: 'green',\n                        zumiMiniLite_ai_cyan: 'cyan',\n                        zumiMiniLite_ai_blue: 'blue',\n                        zumiMiniLite_ai_purple: 'purple',\n                        zumiMiniLite_red: 'red',\n                        zumiMiniLite_green: 'green',\n                        zumiMiniLite_blue: 'blue',\n                        zumiMiniLite_yellow: 'yellow',\n                        zumiMiniLite_sky_blue: 'skyblue',\n                        zumiMiniLite_pink: 'pink',\n                        zumiMiniLite_white: 'white',\n                        zumiMiniLite_led_normal: 'normal',\n                        zumiMiniLite_led_blink: 'blink',\n                        zumiMiniLite_led_flicker: 'flicker',\n                        zumiMiniLite_led_dimming: 'dimming',\n                        zumiMiniLite_led_sunrise: 'sunrise',\n                        zumiMiniLite_led_sunset: 'sunset',\n                        zumiMiniLite_led_rainbow: 'rainbow',\n                        zumiMiniLite_on: 'on',\n                        zumiMiniLite_off: 'off',\n                        zumiMiniLite_cat: 'cat',\n                        zumiMiniLite_human: 'human',\n                        zumiMiniLite_detect: 'detection',\n                        zumiMiniLite_cx: 'x_coordinate',\n                        zumiMiniLite_cy: 'y_coordinate',\n                        zumiMiniLite_id: 'id',\n                        zumiMiniLite_pitch: 'pitch',\n                        zumiMiniLite_roll: 'roll',\n                        zumiMiniLite_yaw: 'yaw',\n                        zumiMiniLite_forward: 'forward',\n                        zumiMiniLite_backward: 'backward',\n                        zumiMiniLite_rapid: 'rapid',\n                        zumiMiniLite_mid: 'medium',\n                        zumiMiniLite_slow: 'slow',\n                        zumiMiniLite_left: 'left',\n                        zumiMiniLite_right: 'right',\n                        zumiMiniLite_camera: 'camera',\n                        zumiMiniLite_emotion: 'emotion',\n                        zumiMiniLite_emo_chaos: 'chaos',\n                        zumiMiniLite_emo_smile: 'smile',\n                        zumiMiniLite_emo_love: 'love',\n                        zumiMiniLite_emo_crash: 'no!',\n                        zumiMiniLite_emo_surprise: 'surprise',\n                        zumiMiniLite_emo_nice: 'joy',\n                        zumiMiniLite_emo_cantbelieve: 'cant believe',\n                        zumiMiniLite_emo_sleep: 'sleep',\n                        zumiMiniLite_emo_cry: 'cry',\n                        zumiMiniLite_emo_wink: 'wink',\n                        zumiMiniLite_emo_blink: 'blink',\n                        zumiMiniLite_emo_sleeping: 'sleeping',\n                        zumiMiniLite_snd_cat: 'meow',\n                        zumiMiniLite_snd_shutter: 'shutter',\n                        zumiMiniLite_snd_fail: 'fail',\n                        zumiMiniLite_snd_success: 'success',\n                        zumiMiniLite_snd_fail2: 'alarm',\n                        zumiMiniLite_snd_honk: 'horn',\n                        zumiMiniLite_snd_honk2: 'horn2',\n                        zumiMiniLite_snd_siren: 'siren',\n                        zumiMiniLite_m1: 'left motor',\n                        zumiMiniLite_m2: 'right motor',\n                        zumiMiniLite_cw: 'forward',\n                        zumiMiniLite_ccw: 'backward',\n                        zumiMiniLite_stop: 'stop',\n                        zumiMiniLite_red_btn: 'red button',\n                        zumiMiniLite_blue_btn: 'blue button',\n                        zumiMiniLite_yellow_btn: 'yellow button',\n                        zumiMiniLite_green_btn: 'green button',\n                        zumiMiniLite_pressed: 'pressed',\n                        zumiMiniLite_released: 'released',\n                    }\n                },\n            };\n        }\n\n        getBlocks() {\n            return {\n\n                zumiMiniLite_motor_control: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_m1, 'LEFT'],\n                                [Lang.Blocks.zumiMiniLite_m2, 'RIGHT'],\n                            ],\n                            value: 'LEFT',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_cw, 'CW'],\n                                [Lang.Blocks.zumiMiniLite_ccw, 'CCW'],\n                                [Lang.Blocks.zumiMiniLite_stop, 'STOP'],\n                            ],\n                            value: 'CW',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            value: '5',//\n                        },\n                        {\n                            type: \"Indicator\",\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14\n                        },\n                    ],\n                    def: {\n                        params: ['LEFT', 'CW', 5, null],\n                        type: 'zumiMiniLite_motor_control',\n                    },\n                    paramsKeyMap: {\n                        SEL: 0,\n                        DIR: 1,\n                        SPD: 2,\n                    },\n                    class: \"zumiMiniLite_move\",\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const DIR_LEFT = 1;\n                        const DIR_RIGHT = 2;\n                        const DIR_STOP = 3;\n\n                        const _sel = script.getValue('SEL');\n                        const _dir = script.getValue('DIR');\n                        const _spd = script.getValue('SPD');\n\n                        var _dirInt = 0;\n\n                        if(_sel == 'LEFT') {\n                            if (_dir == 'CW') _dirInt = DIR_RIGHT;\n                            else if (_dir == 'CCW') _dirInt = DIR_LEFT;\n                            else if (_dir == 'STOP') _dirInt = DIR_STOP;\n                        }\n                        if (_sel == 'RIGHT') {\n                            if (_dir == 'CW') _dirInt = DIR_LEFT;\n                            else if (_dir == 'CCW') _dirInt = DIR_RIGHT;\n                            else if (_dir == 'STOP') _dirInt = DIR_STOP;\n                        }\n\n                        if (_spd < 0) _spd = 0;\n                        else if (_spd > 10) _spd = 10;\n\n                        if (_sel == 'LEFT') {\n                            Entry.ZumiMiniLite.tSpd = Entry.ZumiMiniLite.tSpd & 0b11110000;\n                            Entry.ZumiMiniLite.tSpd = Entry.ZumiMiniLite.tSpd | _spd;\n                            Entry.ZumiMiniLite.tDir = Entry.ZumiMiniLite.tDir & 0b11110000;\n                            Entry.ZumiMiniLite.tDir = Entry.ZumiMiniLite.tDir | _dirInt;\n\n                            Entry.ZumiMiniLite.sendCommand(\n                            CommandType.COMMAND_MOTOR1_INFINITE,\n                            Entry.ZumiMiniLite.tSpd,\n                            Entry.ZumiMiniLite.tSpd,\n                            Entry.ZumiMiniLite.tDir\n                            );\n                        }\n\n                        else if (_sel == 'RIGHT') {\n                            Entry.ZumiMiniLite.tSpd = Entry.ZumiMiniLite.tSpd & 0b00001111;\n                            Entry.ZumiMiniLite.tSpd = Entry.ZumiMiniLite.tSpd | (_spd << 4);\n                            Entry.ZumiMiniLite.tDir = Entry.ZumiMiniLite.tDir & 0b00001111;\n                            Entry.ZumiMiniLite.tDir = Entry.ZumiMiniLite.tDir | (_dirInt << 4);\n\n                           Entry.ZumiMiniLite.sendCommand(\n                            CommandType.COMMAND_MOTOR2_INFINITE,\n                            Entry.ZumiMiniLite.tSpd,\n                            Entry.ZumiMiniLite.tSpd,\n                            Entry.ZumiMiniLite.tDir\n                           );\n                        }\n\n                        return script.callReturn();\n                    },\n                },\n\n                zumiMiniLite_move_straight: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_forward, 'FORWARD'],\n                                [Lang.Blocks.zumiMiniLite_backward, 'BACKWARD'],\n                            ],\n                            value: 'FORWARD',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_rapid, 'RAPID'],\n                                [Lang.Blocks.zumiMiniLite_mid, 'MID'],\n                                [Lang.Blocks.zumiMiniLite_slow, 'SLOW']\n                            ],\n                            value: 'MID',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            value: '10',//\n                        },\n                        {\n                            type: \"Indicator\",\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14\n                        },\n                    ],\n                    def: {\n                        params: ['FORWARD', 'MID', 10, null],\n                        type: 'zumiMiniLite_move_straight',\n                    },\n                    paramsKeyMap: {\n                        DIR: 0,\n                        SPD: 1,\n                        DIST: 2,\n                    },\n                    class: \"zumiMiniLite_move\",\n                    isNotFor: ['ZumiMiniLite'],\n                    async func(sprite, script) {\n\n                        const DIR_FORWARD = 0;\n                        const DIR_BACKWARD = 1;\n                        const SPEED_RAPID = 3;\n\n                        const SPEED_MID = 2;\n                        const SPEED_LOW = 1;\n\n                        const _dir = script.getStringField('DIR', script)\n                        const _spd = script.getStringField('SPD', script);\n                        const _dist = script.getNumberValue('DIST');\n\n                        let _dirV = (_dir === 'FORWARD') ? DIR_FORWARD : DIR_BACKWARD;\n                        let _spdV = (_spd === 'RAPID') ? SPEED_RAPID : (_spd === 'MID') ? SPEED_MID : SPEED_LOW;\n                        let _distV = parseInt(_dist);\n\n                        await Entry.ZumiMiniLite.runCommandBlock(() => {\n                            Entry.ZumiMiniLite.sendCommand(\n                                CommandType.COMMAND_GO_UNTIL_DIST,\n                                _spdV,\n                                _distV,\n                                _dirV\n                            );\n                        });\n                    },\n                },\n\n                zumiMiniLite_move_straight_infinite: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_forward, 'FORWARD'],\n                                [Lang.Blocks.zumiMiniLite_backward, 'BACKWARD'],\n                            ],\n                            value: 'FORWARD',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_rapid, 'RAPID'],\n                                [Lang.Blocks.zumiMiniLite_mid, 'MID'],\n                                [Lang.Blocks.zumiMiniLite_slow, 'SLOW']\n                            ],\n                            value: 'MID',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: \"Indicator\",\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['FORWARD', 'MID', null],\n                        type: 'zumiMiniLite_move_straight_infinite',\n                    },\n                    paramsKeyMap: {\n                        DIR: 0,\n                        SPD: 1,\n                    },\n                    class: \"zumiMiniLite_move\",\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n                        const DIR_FORWARD = 0;\n                        const DIR_BACKWARD = 1;\n\n                        const SPEED_RAPID = 3;\n                        const SPEED_MID = 2;\n                        const SPEED_LOW = 1;\n\n                        const _dir = script.getStringField('DIR', script)\n                        const _spd = script.getStringField('SPD', script);\n\n                        let _dirV = (_dir === 'FORWARD') ? DIR_FORWARD : DIR_BACKWARD;\n                        let _spdV = (_spd === 'RAPID') ? SPEED_RAPID : (_spd === 'MID') ? SPEED_MID : SPEED_LOW;\n\n                        Entry.ZumiMiniLite.sendCommand(\n                            CommandType.COMMAND_GO_INFINITE,\n                            _spdV,\n                            0,\n                            _dirV\n                        );\n                    },\n                },\n\n                zumiMiniLite_move_turn: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_left, 'LEFT'],\n                                [Lang.Blocks.zumiMiniLite_right, 'RIGHT'],\n                            ],\n                            value: 'RIGHT',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.RAPID, 'RAPID'],\n                                [Lang.Blocks.MID, 'MID'],\n                                [Lang.Blocks.SLOW, 'SLOW']\n                            ],\n                            value: 'MID',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            value: '90',//\n                        },\n                        {\n                            type: \"Indicator\",\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14\n                        },\n                    ],\n                    def: {\n                        params: ['RIGHT', 'MID', 90, null],\n                        type: 'zumiMiniLite_move_turn',\n                    },\n                    paramsKeyMap: {\n                        DIR: 0,\n                        SPD: 1,\n                        DEG: 2,\n                    },\n                    class: \"zumiMiniLite_move\",\n                    isNotFor: ['ZumiMiniLite'],\n                    async func(sprite, script) {\n\n                        const DIR_LEFT = 0;\n                        const DIR_RIGHT = 1;\n                        const SPEED_RAPID = 3;\n                        const SPEED_MID = 2;\n                        const SPEED_LOW = 1;\n\n                        const _dir = script.getStringField('DIR', script)\n                        const _spd = script.getStringField('SPD', script);\n                        const _deg = script.getNumberValue('DEG');\n\n                        let _dirV = (_dir === 'LEFT') ? DIR_LEFT : DIR_RIGHT;\n                        let _spdV = (_spd === 'RAPID') ? SPEED_RAPID : (_spd === 'MID') ? SPEED_MID : SPEED_LOW;\n                        let _degV = parseFloat(_deg);\n                        if (_degV < 5) _degV = 5; else if (_degV > 359) _degV = 359;\n                        var _degree = _degV * 0.5;\n\n                        await Entry.ZumiMiniLite.runCommandBlock(() => {\n                            Entry.ZumiMiniLite.sendCommand(\n                                CommandType.COMMAND_FREE_TURN,\n                                _spdV,\n                                _degree,\n                                _dirV\n                            );\n                        });\n                    },\n                },\n\n                zumiMiniLite_motion_stop: {\n                        color: EntryStatic.colorSet.block.default.HARDWARE,\n                        outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                        fontColor: '#ffffff',\n                        skeleton: 'basic',\n                        statements: [],//\n                        params: [\n                            {\n                                type: \"Indicator\",\n                                img: 'block_icon/hardwarelite_icon.svg',\n                                size: 14,\n                            }\n                        ],\n                        def: {\n                            type: \"zumiMiniLite_motion_stop\"\n                        },\n                        class: \"zumiMiniLite_move\",\n                        isNotFor: ['ZumiMiniLite'],\n                        async func(sprite, script) {\n\n                            await Entry.ZumiMiniLite.runCommandBlock(() => {\n                                Entry.ZumiMiniLite.sendCommand(\n                                    CommandType.COMMAND_MOTION_STOP\n                                );\n                            });\n\n                        },\n                },\n\n                zumiMiniLite_going_forward_until_sensing: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: \"Indicator\",\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14\n                        }\n                    ],\n                    def: {\n                        type: \"zumiMiniLite_going_forward_until_sensing\"\n                    },\n                    class: \"zumiMiniLite_sense\",\n                    isNotFor: ['ZumiMiniLite'],\n                    async func(sprite, script) {\n\n                        await Entry.ZumiMiniLite.runCommandBlock(() => {\n                            Entry.ZumiMiniLite.sendCommand(\n                                CommandType.COMMAND_GOSENSOR\n                            );\n                        });\n\n                    },\n                },\n\n                // -- line\n                zumiMiniLite_following_line_until_sensing: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    params: [\n                        {\n                            type: \"Indicator\",\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        }\n                    ],\n                    def: {\n                        type: \"zumiMiniLite_following_line_until_sensing\"\n                    },\n                    class: \"zumiMiniLite_sense\",\n                    isNotFor: ['ZumiMiniLite'],\n                    async func(sprite, script) {\n\n                        await Entry.ZumiMiniLite.runCommandBlock(() => {\n                            Entry.ZumiMiniLite.sendCommand(\n                                CommandType.COMMAND_LINE_TRACING,\n                                0,\n                                0,\n                                0,\n                                0x8B,\n                                0x3A\n                            );\n                        });\n\n                    },\n                },\n\n                zumiMiniLite_following_line_dist: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_rapid, 'RAPID'],\n                                [Lang.Blocks.zumiMiniLite_mid, 'MID'],\n                                [Lang.Blocks.zumiMiniLite_slow, 'SLOW']\n                            ],\n                            value: 'MID',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            value: '30',//\n                        },\n                        {\n                            type: \"Indicator\",\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14\n                        },\n                    ],\n                    def: {\n                        params: ['MID', 30, null],\n                        type: 'zumiMiniLite_following_line_dist',\n                    },\n                    paramsKeyMap: {\n                        SPD: 0,\n                        DIST: 1,\n                    },\n                    class: \"zumiMiniLite_sense\",\n                    isNotFor: ['ZumiMiniLite'],\n                    async func(sprite, script) {\n\n                        const SPEED_RAPID = 3;\n                        const SPEED_MID = 2;\n                        const SPEED_LOW = 1;\n\n                        const _spd = script.getStringField('SPD', script);\n                        const _dist = script.getNumberValue('DIST');\n\n                        let _spdV = (_spd === 'RAPID') ? SPEED_RAPID : (_spd === 'MID') ? SPEED_MID : SPEED_LOW;\n                        let _distV = parseInt(_dist);\n                        if (_dist < 10) _distV = 10;\n                        else if (_dist > 200) _distV = 200;\n\n                        await Entry.ZumiMiniLite.runCommandBlock(() => {\n                            Entry.ZumiMiniLite.sendCommand(\n                                CommandType.COMMAND_LINE_TRACE_DIST,\n                                _spdV,\n                                _distV\n                            );\n                        });\n\n                    },\n                },\n\n                zumiMiniLite_following_line_infinite: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_rapid, 'RAPID'],\n                                [Lang.Blocks.zumiMiniLite_mid, 'MID'],\n                                [Lang.Blocks.zumiMiniLite_slow, 'SLOW']\n                            ],\n                            value: 'MID',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: \"Indicator\",\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['MID', null],\n                        type: 'zumiMiniLite_following_line_infinite',\n                    },\n                    paramsKeyMap: {\n                        SPD: 0,\n                    },\n                    class: \"zumiMiniLite_sense\",\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const SPEED_RAPID = 3;\n                        const SPEED_MID = 2;\n                        const SPEED_LOW = 1;\n\n                        const _spd = script.getStringField('SPD', script);\n\n                        let _spdV = (_spd === 'RAPID') ? SPEED_RAPID : (_spd === 'MID') ? SPEED_MID : SPEED_LOW;\n\n                        Entry.ZumiMiniLite.sendCommand(\n                            CommandType.COMMAND_TRACE_INFINITE,\n                            _spdV\n                        );\n\n                    },\n                },\n//-----------------------------------------------------------------------------------//\n                zumiMiniLite_LED_control: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',//\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_red, 'RED'],\n                                [Lang.Blocks.zumiMiniLite_green, 'GREEN'],\n                                [Lang.Blocks.zumiMiniLite_blue, 'BLUE'],\n                                [Lang.Blocks.zumiMiniLite_yellow, 'YELLOW'],\n                                [Lang.Blocks.zumiMiniLite_sky_blue, 'SKY_BLUE'],\n                                [Lang.Blocks.zumiMiniLite_pink, 'PINK'],\n                                [Lang.Blocks.zumiMiniLite_white, 'WHITE'],\n                            ],\n                            value: 'WHITE',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_led_normal, 'NORMAL'],\n                                [Lang.Blocks.zumiMiniLite_led_blink, 'BLINK'],\n                                [Lang.Blocks.zumiMiniLite_led_dimming, 'DIMMING'],\n                                [Lang.Blocks.zumiMiniLite_led_sunrise, 'SUNRISE'],\n                                [Lang.Blocks.zumiMiniLite_led_sunset, 'SUNSET'],\n                                [Lang.Blocks.zumiMiniLite_led_flicker, 'FLICKER'],\n                                [Lang.Blocks.zumiMiniLite_led_rainbow, 'RAINBOW'],\n                            ],\n                            value: 'NORMAL',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.ON, 'ON'],\n                                [Lang.Blocks.OFF, 'OFF'],\n                            ],\n                            value: 'ON',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['WHITE', 'NORMAL', 'ON', null],\n                        type: 'zumiMiniLite_LED_control',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                        EFFECT: 1,\n                        ACTION: 2,\n                    },\n                    class: 'zumiMiniLite_led',\n                    isNotFor: ['ZumiMiniLite'],\n                    async func(sprite, script) {\n\n                        const _col = script.getValue('COLOR');\n                        const _eff = script.getValue('EFFECT');\n                        const _act = script.getValue('ACTION');\n\n                        const LED_RED = 1;\n                        const LED_BLUE = 2;\n                        const LED_GREEN = 3;\n                        const LED_YELLOW = 4;\n                        const LED_SKY_BLUE = 5;\n                        const LED_PINK = 6;\n                        const LED_WHITE = 7;\n\n                        const LED_NORMAL = 0;\n                        const LED_BLINK = 1;\n                        const LED_FLICKER = 2;\n                        const LED_DIMMING = 3;\n                        const LED_SUNRISE = 4;\n                        const LED_SUNSET = 5;\n                        const LED_RAINBOW = 6;\n\n                        let _colorSend = 0;\n                        let _effectSend = 0;\n                        let _actSend = 0;\n\n                        if ((_col == 'RED') && (_act == 'ON')) _colorSend = LED_RED;\n                        else if ((_col == 'BLUE') && (_act == 'ON')) _colorSend = LED_BLUE;\n                        else if ((_col == 'GREEN') && (_act == 'ON')) _colorSend = LED_GREEN;\n                        else if ((_col == 'SKY_BLUE') && (_act == 'ON')) _colorSend = LED_SKY_BLUE;\n                        else if ((_col == 'PINK') && (_act == 'ON')) _colorSend = LED_PINK;\n                        else if ((_col == 'YELLOW') && (_act == 'ON')) _colorSend = LED_YELLOW;\n                        else if ((_col == 'WHITE') && (_act == 'ON')) _colorSend = LED_WHITE;\n\n                        if (_eff == 'NORMAL') _effectSend = LED_NORMAL;\n                        else if (_eff == 'BLINK') _effectSend = LED_BLINK;\n                        else if (_eff == 'FLICKER') _effectSend = LED_FLICKER;\n                        else if (_eff == 'DIMMING') _effectSend = LED_DIMMING;\n                        else if (_eff == 'SUNRISE') _effectSend = LED_SUNRISE;\n                        else if (_eff == 'SUNSET') _effectSend = LED_SUNSET;\n                        else if (_eff == 'RAINBOW') _effectSend = LED_RAINBOW;\n\n                        if(_act == 'ON') _actSend = 1;\n                        else if(_act == 'OFF') _actSend = 0;\n\n                        await Entry.ZumiMiniLite.runCommandBlock(() => {\n                        Entry.ZumiMiniLite.sendCommand(\n                            CommandType.COMMAND_LED_CONTROL,\n                            _colorSend,\n                            _effectSend,\n                            _actSend\n                        );\n                        });\n\n                        return script.callReturn();\n                    },\n                    //syntax: { js: [], py: ['Sensorboard.led(%1, %2)'] },\n                },\n\n                zumiMiniLite_button_boolean_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_red_btn, 'RED_BTN'],\n                                [Lang.Blocks.zumiMiniLite_blue_btn, 'BLUE_BTN'],\n                                [Lang.Blocks.zumiMiniLite_green_btn, 'GREEN_BTN'],\n                                [Lang.Blocks.zumiMiniLite_yellow_btn, 'YELLOW_BTN'],\n                            ],\n                            value: 'RED_BTN',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_pressed, 'PRESS'],\n                                [Lang.Blocks.zumiMiniLite_released, 'RELEASE'],\n                            ],\n                            value: 'PRESS',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: ['RED_BTN','PRESS'],\n                        type: 'zumiMiniLite_button_boolean_input',\n                    },\n                    paramsKeyMap: {\n                        BUTTON: 0,\n                        STATUS: 1,\n                    },\n                    class: 'zumiMiniLite_boolean',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        var result = false;\n\n                        const _btn = script.getValue('BUTTON');\n                        const _stat = script.getValue('STATUS');\n                        var bStat = Entry.ZumiMiniLite.btn;\n\n                        if (_stat == 'PRESS')\n                        {\n                            if((_btn == 'RED_BTN')&&(bStat == 8)) result = true;\n                            else if((_btn == 'BLUE_BTN') && (bStat == 4)) result = true;\n                            else if((_btn == 'GREEN_BTN') && (bStat == 2)) result = true;\n                            else if((_btn == 'YELLOW_BTN') && (bStat == 1)) result = true;\n                            else result = false;\n                        }\n                        else if (_stat == 'RELEASE')\n                        {\n                            if ((_btn == 'RED_BTN') && (bStat == 8)) result = false;\n                            else if ((_btn == 'BLUE_BTN') && (bStat == 4)) result = false;\n                            else if ((_btn == 'GREEN_BTN') && (bStat == 2)) result = false;\n                            else if ((_btn == 'YELLOW_BTN') && (bStat == 1)) result = false;\n                            else result = true;\n                        }\n\n                        return result;\n                    },\n                },\n//-----------------------------------------------------------------------------------//\n                zumiMiniLite_screen_toggle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_camera, 'CAMERA'],\n                                [Lang.Blocks.zumiMiniLite_emotion, 'EMOTION'],\n                            ],\n                            value: 'CAMERA',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['CAMERA', null],\n                        type: 'zumiMiniLite_screen_toggle',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'zumiMiniLite_screen',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const SCREEN_CAMERA = 1;\n                        const SCREEN_EMOTION = 2;\n\n                        const _type = script.getStringField('TYPE', script)\n\n                        let _typeV = (_type === 'CAMERA') ? SCREEN_CAMERA : SCREEN_EMOTION;\n\n                            Entry.ZumiMiniLite.sendCommand(\n                                CommandType.COMMAND_SCREEN_TOGGLE,\n                                _typeV\n                            );\n                    },\n                },\n\n                zumiMiniLite_emotion: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_emo_smile, 'SMILE'],\n                                [Lang.Blocks.zumiMiniLite_emo_love, 'LOVE'],\n                                [Lang.Blocks.zumiMiniLite_emo_surprise, 'SURP'],\n                                [Lang.Blocks.zumiMiniLite_emo_nice, 'NICE'],\n                                [Lang.Blocks.zumiMiniLite_emo_chaos, 'CHAOS'],\n                                [Lang.Blocks.zumiMiniLite_emo_crash, 'CRASH'],\n                                [Lang.Blocks.zumiMiniLite_emo_cantbelieve, 'CANTBELIEVE'],\n                                [Lang.Blocks.zumiMiniLite_emo_sleep, 'SLEEP'],\n                                [Lang.Blocks.zumiMiniLite_emo_cry, 'CRY'],\n                                [Lang.Blocks.zumiMiniLite_emo_wink, 'WINK'],\n                                [Lang.Blocks.zumiMiniLite_emo_blink, 'BLINK'],\n                                [Lang.Blocks.zumiMiniLite_emo_sleeping, 'SLEEPING'],\n                            ],\n                            value: 'SMILE',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['SMILE', null],\n                        type: 'zumiMiniLite_emotion',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'zumiMiniLite_screen',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const EMO_BLINK = 3;\n                        const EMO_STOP = 2;\n\n                        const EMO_SMILE = 4;\n                        const EMO_LOVE = 5;\n\n                        const EMO_CRASH = 6;\n                        const EMO_SURPRISE = 7;\n                        const EMO_NICE = 8;\n                        const EMO_CANTBELIEVE = 9;\n                        const EMO_SLEEP = 10;\n                        const EMO_CRY = 11;\n                        const EMO_CHAOS = 12;\n                        const EMO_SLEEPING = 13;\n                        const EMO_WINK = 14;\n\n                        const _type = script.getStringField('TYPE', script)\n                        let _typeV = 0;\n\n                        if (_type == 'SMILE') _typeV = EMO_SMILE;\n                        else if (_type == 'LOVE') _typeV = EMO_LOVE;\n                        else if (_type == 'SURP') _typeV = EMO_SURPRISE;\n                        else if (_type == 'NICE') _typeV = EMO_NICE;\n                        else if (_type == 'CHAOS') _typeV = EMO_CHAOS;\n                        else if (_type == 'CRASH') _typeV = EMO_CRASH;\n                        else if (_type == 'CANTBELIEVE') _typeV = EMO_CANTBELIEVE;\n                        else if (_type == 'SLEEP') _typeV = EMO_SLEEP;\n                        else if (_type == 'CRY') _typeV = EMO_CRY;\n                        else if (_type == 'WINK') _typeV = EMO_WINK;\n                        else if (_type == 'BLINK') _typeV = EMO_BLINK;\n                        else if (_type == 'SLEEPING') _typeV = EMO_SLEEPING;\n\n                            Entry.ZumiMiniLite.sendCommand(\n                                CommandType.COMMAND_EMOTION_CHANGE,\n                                _typeV\n                            );\n                    },\n                },\n\n//-----------------------------------------------------------------------------------//\n                // AI 인식 판단\n                zumiMiniLite_face_boolean_detector: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_human, 'HUMAN'],\n                                [Lang.Blocks.zumiMiniLite_cat, 'CAT'],\n                            ],\n                            value: 'HUMAN',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: ['HUMAN'],\n                        type: 'zumiMiniLite_face_boolean_detector',\n                    },\n                    paramsKeyMap: {\n                        FACE: 0,\n                    },\n                    class: 'zumiMiniLite_boolean',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        var result = false;\n\n                        const sel_detect = script.getValue('FACE');\n\n                        if(sel_detect == 'HUMAN')\n                        {\n                            Entry.ZumiMiniLite.current_request |= RequestType.REQUEST_ENTRY_FACE_DETECT;\n\n                            if(Entry.ZumiMiniLite.zumiFaceDetected != 0) result = true;\n                            else result = false;\n                        }\n                        else if(sel_detect == 'CAT')\n                        {\n                            Entry.ZumiMiniLite.current_request |= RequestType.REQUEST_ENTRY_CAT_DETECT;\n\n                            if(Entry.ZumiMiniLite.zumiCatDetected != 0) result = true;\n                            else result = false;\n                        }\n\n                        // Entry.ZumiMiniLite.sendCommand(\n                        //     CommandType.COMMAND_NONE\n                        // );\n\n                        return result;\n                    },\n                },\n\n                zumiMiniLite_color_boolean_detector: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_ai_red, 'RED'],\n                                [Lang.Blocks.zumiMiniLite_ai_orange, 'ORANGE'],\n                                [Lang.Blocks.zumiMiniLite_ai_yellow, 'YELLOW'],\n                                [Lang.Blocks.zumiMiniLite_ai_green, 'GREEN'],\n                                [Lang.Blocks.zumiMiniLite_ai_cyan, 'CYAN'],\n                                [Lang.Blocks.zumiMiniLite_ai_blue, 'BLUE'],\n                                [Lang.Blocks.zumiMiniLite_ai_purple, 'PURPLE'],\n                            ],\n                            value: 'RED',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: ['RED'],\n                        type: 'zumiMiniLite_color_boolean_detector',\n                    },\n                    paramsKeyMap: {\n                        PARAM: 0,\n                    },\n                    class: 'zumiMiniLite_boolean',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const sen = script.getValue('PARAM');\n                        Entry.ZumiMiniLite.current_request |= RequestType.REQUEST_ENTRY_COLOR_DETECT;\n\n                        // Entry.ZumiMiniLite.sendCommand(\n                        //     CommandType.COMMAND_NONE\n                        // );\n\n                        var result = Entry.ZumiMiniLite.zumiColorDetected;\n\n                        if ((result == 0x00) && (sen == 'RED')) result = true;\n                        else if ((result == 0x01) && (sen == 'ORANGE')) result = true;\n                        else if ((result == 0x02) && (sen == 'YELLOW')) result = true;\n                        else if ((result == 0x03) && (sen == 'GREEN')) result = true;\n                        else if ((result == 0x04) && (sen == 'CYAN')) result = true;\n                        else if ((result == 0x05) && (sen == 'BLUE')) result = true;\n                        else if ((result == 0x06) && (sen == 'PURPLE')) result = true;\n                        else result = false;\n\n                        return result;\n                    },\n                },\n\n                zumiMiniLite_april_boolean_detector: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            value: '15',//\n                        },\n                    ],\n                    def: {\n                        params: [15],\n                        type: 'zumiMiniLite_april_boolean_detector',\n                    },\n                    paramsKeyMap: {\n                        NUM: 0,\n                    },\n                    class: 'zumiMiniLite_boolean',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const _num = script.getValue('NUM');\n                        Entry.ZumiMiniLite.current_request |= RequestType.REQUEST_ENTRY_APRIL_DETECT;\n\n                        // Entry.ZumiMiniLite.sendCommand(\n                        //     CommandType.COMMAND_NONE\n                        // );\n\n                        var result = Entry.ZumiMiniLite.zumiMarkerDetected;\n\n                        if(result <11) result +=1;\n                        else if(result == 14) result = 12;\n                        else if(result == 15) result = 13;\n                        else if(result == 16) result = 14;\n                        else if(result == 18) result = 15;\n                        else if(result == 19) result = 16;\n                        else if(result == 20) result = 17;\n\n                        if(_num == result) result = true;\n                        else result = false;\n\n                        return result;\n                    },\n                },\n//-----------------------------------------------------------------------------------//\n\n                zumiMiniLite_front_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',//\n                    skeleton: 'basic_string_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_fl, 'FL'],\n                                [Lang.Blocks.zumiMiniLite_fr, 'FR'],\n                            ],\n                            value: 'FL',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['FL', null],\n                        type: 'zumiMiniLite_front_sensor',\n                    },\n                    paramsKeyMap: {\n                        DIR: 0,\n                    },\n                    class: 'info',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n                        const _dir = script.getValue('DIR');\n                        if(_dir == 'FL') return Entry.ZumiMiniLite.senFL;\n                        else return Entry.ZumiMiniLite.senFR;\n                    },\n                },\n                zumiMiniLite_bottom_sensor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',//\n                    skeleton: 'basic_string_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_bl, 'BL'],\n                                [Lang.Blocks.zumiMiniLite_bm, 'BM'],\n                                [Lang.Blocks.zumiMiniLite_br, 'BR'],\n                            ],\n                            value: 'BL',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['BL', null],\n                        type: 'zumiMiniLite_bottom_sensor',\n                    },\n                    paramsKeyMap: {\n                        DIR: 0,\n                    },\n                    class: 'info',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n                        const _dir = script.getValue('DIR');\n                        if(_dir == 'BL') return Entry.ZumiMiniLite.senBL;\n                        else if(_dir == 'BR') return Entry.ZumiMiniLite.senBR;\n                        else return Entry.ZumiMiniLite.senBC;\n                    },\n                },\n                zumiMiniLite_button_input: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    def: {\n                        type: 'zumiMiniLite_button_input',\n                    },\n                    class: 'info',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        var bStat = Entry.ZumiMiniLite.btn;\n                        if(bStat == 8) bStat = 'R';\n                        else if(bStat == 4) bStat = 'B';\n                        else if(bStat == 2) bStat = 'G';\n                        else if(bStat == 1) bStat = 'Y';\n                        else bStat = 'N';\n\n                        return bStat;\n                    },\n                },\n                zumiMiniLite_power_info: {\n                color: EntryStatic.colorSet.block.default.HARDWARE,\n                outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                fontColor: '#ffffff',\n                skeleton: 'basic_string_field',\n                statements: [],//\n                params: [\n                    {\n                        type: 'Indicator',\n                        img: 'block_icon/hardwarelite_icon.svg',\n                        size: 12,\n                    },\n                ],\n                def: {\n                    type: 'zumiMiniLite_power_info',\n                },\n                class: 'info',\n                isNotFor: ['ZumiMiniLite'],\n                func(sprite, script) {\n                    return Entry.ZumiMiniLite.battery;\n                },\n                },\n\n                zumiMiniLite_face_detector: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_detect, 'DETECT'],\n                                [Lang.Blocks.zumiMiniLite_cx, 'CX'],\n                                [Lang.Blocks.zumiMiniLite_cy, 'CY'],\n                            ],\n                            value: 'DETECT',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['DETECT', null],\n                        type: 'zumiMiniLite_face_detector',\n                    },\n                    paramsKeyMap: {\n                        PARAM: 0,\n                    },\n                    class: 'info',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const sel_detect = script.getValue('PARAM');\n\n                        Entry.ZumiMiniLite.current_request |= RequestType.REQUEST_ENTRY_FACE_DETECT;\n\n                        // Entry.ZumiMiniLite.sendCommand(\n                        //     CommandType.COMMAND_NONE\n                        // );\n\n                        if(Entry.ZumiMiniLite.zumiFaceDetected == 0x00)\n                        {\n                            if(sel_detect == 'DETECT') return false;\n                            else if(sel_detect == 'CX') return parseInt(-999);\n                            else if(sel_detect == 'CY') return parseInt(-999);\n                        }\n                        else\n                        {\n                            if(sel_detect == 'DETECT')  return true;\n\n                            else if(sel_detect == 'CX')\n                            {\n                                var Xg = Entry.ZumiMiniLite.zumiFaceCenter[0];\n                                return ((200 / 2) - Xg) + 10;\n                            }\n                            else if(sel_detect == 'CY')\n                            {\n                                var Yg = Entry.ZumiMiniLite.zumiFaceCenter[1];\n                                return  ((200 / 2) - Yg) + 35;\n                            }\n                        }\n                    },\n                },\n                zumiMiniLite_cat_face_detector: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_detect, 'DETECT'],\n                                [Lang.Blocks.zumiMiniLite_cx, 'CX'],\n                                [Lang.Blocks.zumiMiniLite_cy, 'CY'],\n                            ],\n                            value: 'DETECT',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['DETECT', null],\n                        type: 'zumiMiniLite_cat_face_detector',\n                    },\n                    paramsKeyMap: {\n                        PARAM: 0,\n                    },\n                    class: 'info',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const sel_detect = script.getValue('PARAM');\n                        Entry.ZumiMiniLite.current_request |= RequestType.REQUEST_ENTRY_CAT_DETECT;\n\n                        // Entry.ZumiMiniLite.sendCommand(\n                        //     CommandType.COMMAND_NONE\n                        // );\n\n                        if(Entry.ZumiMiniLite.zumiCatDetected == 0x00)\n                        {\n                            if(sel_detect == 'DETECT') return false;\n                            else if(sel_detect == 'CX') return parseInt(-999);\n                            else if(sel_detect == 'CY') return parseInt(-999);\n                        }\n                        else\n                        {\n                            if(sel_detect == 'DETECT')  return true;\n\n                            else if(sel_detect == 'CX')\n                            {\n                                var Xg = Entry.ZumiMiniLite.zumiCatCenter[0];\n                                return ((200 / 2) - Xg) + 20;\n                            }\n                            else if(sel_detect == 'CY')\n                            {\n                                var Yg = Entry.ZumiMiniLite.zumiCatCenter[1];\n                                return  ((200 / 2) - Yg) + 30;\n                            }\n                        }\n                    },\n                },\n                zumiMiniLite_color_detector: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_color, 'COLOR'],\n                                [Lang.Blocks.zumiMiniLite_cx, 'CX'],\n                                [Lang.Blocks.zumiMiniLite_cy, 'CY'],\n                            ],\n                            value: 'COLOR',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['COLOR', null],\n                        type: 'zumiMiniLite_color_detector',\n                    },\n                    paramsKeyMap: {\n                        PARAM: 0,\n                    },\n                    class: 'info',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const sen = script.getValue('PARAM');\n                        Entry.ZumiMiniLite.current_request |= RequestType.REQUEST_ENTRY_COLOR_DETECT;\n\n                        // Entry.ZumiMiniLite.sendCommand(\n                        //     CommandType.COMMAND_NONE\n                        // );\n\n                        var result = Entry.ZumiMiniLite.zumiColorDetected;\n\n                        if((result == 0xFE) && (sen == 'COLOR')) result = 'NONE';\n                        else if ((result == 0x00) && (sen == 'COLOR')) result = 'RED';\n                        else if ((result == 0x01) && (sen == 'COLOR')) result = 'ORANGE';\n                        else if ((result == 0x02) && (sen == 'COLOR')) result = 'YELLOW';\n                        else if ((result == 0x03) && (sen == 'COLOR')) result = 'GREEN';\n                        else if ((result == 0x04) && (sen == 'COLOR')) result = 'CYAN';\n                        else if ((result == 0x05) && (sen == 'COLOR')) result = 'BLUE';\n                        else if ((result == 0x06) && (sen == 'COLOR')) result = 'PURPLE';\n\n                        var Xg = Entry.ZumiMiniLite.zumiColorCenter[0];\n                        var Yg = Entry.ZumiMiniLite.zumiColorCenter[1];\n\n                        if (sen == 'CX') {\n                            if (result == 0xFE) result = -999;\n                            else result = ((200 / 2) - Xg) +20;\n                        }\n                        else if (sen == 'CY') {\n                            if (result == 0xFE) result = -999;\n                            else result = ((200 / 2) - Yg) +35;\n                        }\n\n                        return result;\n                    },\n                },\n                zumiMiniLite_april_detector: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#ffffff',\n                    skeleton: 'basic_string_field',\n                    statements: [],//\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.zumiMiniLite_id, 'ID'],\n                                [Lang.Blocks.zumiMiniLite_cx, 'CX'],\n                                [Lang.Blocks.zumiMiniLite_cy, 'CY'],\n                            ],\n                            value: 'ID',//\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 14,\n                        },\n                    ],\n                    def: {\n                        params: ['ID', null],\n                        type: 'zumiMiniLite_april_detector',\n                    },\n                    paramsKeyMap: {\n                        PARAM: 0,\n                    },\n                    class: 'info',\n                    isNotFor: ['ZumiMiniLite'],\n                    func(sprite, script) {\n\n                        const sen = script.getValue('PARAM');\n\n                        Entry.ZumiMiniLite.current_request |= RequestType.REQUEST_ENTRY_APRIL_DETECT;\n\n                        // Entry.ZumiMiniLite.sendCommand(\n                        //     CommandType.COMMAND_NONE\n                        // );\n\n                        var result = Entry.ZumiMiniLite.zumiMarkerDetected;\n                        var Xg = Entry.ZumiMiniLite.zumiMarkerCenter[0];\n                        var Yg = Entry.ZumiMiniLite.zumiMarkerCenter[1];\n\n\n                        if(sen == 'ID')\n                        {\n                            if(result == 0xFE) result = -1;\n                            else\n                            {\n                                if(result <11) result +=1;\n                                else if(result == 14) result = 12;\n                                else if(result == 15) result = 13;\n                                else if(result == 16) result = 14;\n                                else if(result == 18) result = 15;\n                                else if(result == 19) result = 16;\n                                else if(result == 20) result = 17;\n                            }\n                        }\n                        else if(sen == 'CX')\n                        {\n                            if(result == 0xFE) result = -999;\n                            else result = (200 / 2) - Xg;\n                        }\n                        else if (sen == 'CY')\n                        {\n                            if (result == 0xFE) result = -999;\n                            else result = (100 / 2) - Yg;\n                        }\n\n                        return result;\n                    },\n                },\n            };\n        }\n        /***************************************************************************************\n         *  프로토롤 제어 함수 (데이터 송신)\n        ***************************************************************************************/\n        makeData(msg){\n            console.log(msg);\n        }\n\n        sendCommand(commandType, ...params) {\n\n            const commandName = Object.keys(CommandType).find(key => CommandType[key] === commandType);\n            if (!commandName) {\n                console.error(`Unknown commandType: ${commandType}`);\n                return;\n            }\n            //console.log(commandName);\n\n            const paramLength = CommandType_DATA_LENGTH[commandName] || 0;\n\n            const payloadBytes = new Uint8Array(1 + paramLength);\n\n            payloadBytes[0] = commandType;\n\n            for (let i = 0; i < params.length && i < paramLength; i++) {\n                payloadBytes[i + 1] = params[i] & 0xFF;\n            }\n\n            Entry.ZumiMiniLite.transferData(payloadBytes);\n        }\n\n        transferData(payloadBytes) {\n\n            const HEADER1 = 0x24; // '$'\n            const HEADER2 = 0x52; // 'R'\n\n            const fullMessageLength = 4 + payloadBytes.length-1;\n\n            const dataArray = new Uint8Array(fullMessageLength);\n            let index = 0;\n\n            dataArray[index++] = HEADER1;\n            dataArray[index++] = HEADER2;\n            dataArray[index++] = payloadBytes[0];\n            dataArray[index++] = Entry.ZumiMiniLite.current_request;\n\n            dataArray.set(payloadBytes.slice(1), index);\n\n            Entry.ZumiMiniLite.sendBuffers = [];\n            Entry.ZumiMiniLite.sendBuffers.push(...dataArray);\n        }\n\n        /***************************************************************************************\n         *  데이터 수신\n        ***************************************************************************************/\n        _updateDataStore(dataArray) {\n\n            const offset = this.HEADER_LENGTH;\n\n            this.reqINFO = dataArray[PacketIndex.DATA_INFO - offset];\n            this.reqREQ = dataArray[PacketIndex.DATA_REQ - offset];\n            this.reqPSTAT = dataArray[PacketIndex.DATA_PSTAT - offset];\n            this.btn = dataArray[PacketIndex.DATA_BTN_INPUT - offset];\n            this.battery = dataArray[PacketIndex.DATA_BATTERY - offset];\n\n            this.senFR = dataArray[PacketIndex.DATA_SEN_FR - offset];\n            this.senFL = dataArray[PacketIndex.DATA_SEN_FL - offset];\n            this.senBR = dataArray[PacketIndex.DATA_SEN_BR - offset];\n            this.senBC = dataArray[PacketIndex.DATA_SEN_BC - offset];\n            this.senBL = dataArray[PacketIndex.DATA_SEN_BL - offset];\n\n            this.zumiFaceDetected = dataArray[PacketIndex.DATA_DETECT_FACE - offset] === 1;\n            this.zumiFaceCenter[0] = dataArray[PacketIndex.DATA_DETECT_FACE_X - offset];\n            this.zumiFaceCenter[1] = dataArray[PacketIndex.DATA_DETECT_FACE_Y - offset];\n\n            this.zumiColorDetected = dataArray[PacketIndex.DATA_DETECT_COLOR - offset];\n            this.zumiColorCenter[0] = dataArray[PacketIndex.DATA_DETECT_COLOR_X - offset];\n            this.zumiColorCenter[1] = dataArray[PacketIndex.DATA_DETECT_COLOR_Y - offset];\n\n            this.zumiMarkerDetected = dataArray[PacketIndex.DATA_DETECT_MARKER - offset];\n            this.zumiMarkerCenter[0] = dataArray[PacketIndex.DATA_DETECT_MARKER_X - offset];\n            this.zumiMarkerCenter[1] = dataArray[PacketIndex.DATA_DETECT_MARKER_Y - offset];\n\n            this.zumiCatDetected = dataArray[PacketIndex.DATA_DETECT_CAT - offset] === 1;\n            this.zumiCatCenter[0] = dataArray[PacketIndex.DATA_DETECT_CAT_X - offset];\n            this.zumiCatCenter[1] = dataArray[PacketIndex.DATA_DETECT_CAT_Y - offset];\n        }\n\n        _processReceiverByte(data) {\n            if (this.receiverState === this.StateLoading.Failure) {\n                this.receiverState = this.StateLoading.Ready;\n            }\n\n            if (this.receiverState === this.StateLoading.Ready) {\n                this.receiverSection = this.Section.Start;\n                this.receiverIndex = 0;\n            }\n\n            else if (this.receiverState === this.StateLoading.Loaded){\n                return this.receiverState;\n            }\n\n            if (this.receiverSection !== this.receiverSectionOld) {\n                this.receiverIndex = 0;\n                this.receiverSectionOld = this.receiverSection;\n            }\n\n            if (this.receiverSection === this.Section.Start) {\n                if (this.receiverIndex === 0) {\n                    if (data === this.PACKET_START_BYTE1) {\n                        this.receiverState = this.StateLoading.Receiving;\n                    } else {\n                        this.receiverState = this.StateLoading.Failure;\n                        this.receiverMessage = \"Error: Invalid Start Byte 1\";\n                        console.log(receiverMessage);\n                        return this.receiverState;\n                    }\n                } else if (this.receiverIndex === 1) {\n                    if (data === this.PACKET_START_BYTE2) {\n                        this.receiverSection = this.Section.Data;\n                        this.receiverBuffer = [];\n                    } else {\n                        this.receiverState = this.StateLoading.Failure;\n                        this.receiverMessage = \"Error: Invalid Start Byte 2\";\n                        console.log(receiverMessage);\n                        return this.receiverState;\n                    }\n                }\n            }\n\n            else if (this.receiverSection === this.Section.Data) {\n                this.receiverBuffer.push(data);\n                if (this.receiverIndex === (this.PACKET_DATA_LENGTH - 1)) {\n                    this.receiverSection = this.Section.End;\n                }\n            }\n\n            else if (this.receiverSection === this.Section.End) {\n                if (this.receiverIndex === 1) {\n                    this.receiverData = [...this.receiverBuffer];\n                    this.receiverState = this.StateLoading.Loaded;\n                    this.receiverMessage = \"Success: Receive complete\";\n\n                    return this.receiverState;\n                }\n            }\n\n            if (this.receiverState === this.StateLoading.Receiving) {\n                this.receiverIndex++;\n            }\n\n            return this.receiverState;\n        }\n\n        _resetReceiverState() {\n            this.receiverState = this.StateLoading.Ready;\n            this.receiverSection = this.Section.Start;\n            this.receiverIndex = 0;\n            this.receiverBuffer = []; // 수신 버퍼 클리어\n            this.receiverMessage = null;\n        }\n\n        runCommandBlock = async function(sendCommandFunc) {\n            const STATUS_WAIT = 0;\n            const STATUS_SENDING = 1;\n            const STATUS_MOVING = 2;\n            const HW_READY = 0;\n            const HW_PROCESSING = 1;\n            var exCnt = 1, tempCnt = 0;\n\n            let currentStep = STATUS_WAIT;\n            let iter = 0;\n            let shouldExitBlock = false;\n\n            await new Promise(resolve => {\n                setTimeout(() => {\n                    if (exCnt === tempCnt) {\n                        shouldExitBlock = true;\n                       // console.log(\" Block Skip Condition Met\");\n                    }\n                    else\n                    {\n                       // console.log(\" not Block Skip Condition\");\n                    }\n                    resolve();\n                }, 200);\n            });\n\n            await new Promise(resolve => {\n                const pollingInterval = setInterval(() => {\n                    if (shouldExitBlock) {\n                        clearInterval(pollingInterval);\n                        return resolve();\n                    }\n\n                    const hardwareStatus = Entry.ZumiMiniLite.reqPSTAT;\n\n                    if((currentStep == STATUS_WAIT) && (hardwareStatus === HW_READY))\n                        {\n                            currentStep = STATUS_SENDING;\n                        }\n                    else if ((currentStep == STATUS_WAIT) && (hardwareStatus == HW_PROCESSING))\n                        {\n                            currentStep = STATUS_WAIT;\n                        }\n\n                    switch (currentStep) {\n                        // case STATUS_WAIT:\n                        //     if (hardwareStatus === HW_READY) currentStep = STATUS_SENDING;\n                        //     break;\n\n                        case STATUS_SENDING:\n\n                            if (hardwareStatus === HW_READY)\n                            {\n                                if (iter < 5) {\n                                    sendCommandFunc();  // ← 여기만 명령 함수 주입\n                                    iter++;\n                                }\n                                else {\n                                    Entry.ZumiMiniLite.sendBuffers = [];\n                                    clearInterval(pollingInterval);\n                                    return resolve();\n                                }\n                            }\n                            else if (hardwareStatus === HW_PROCESSING)\n                            {\n                                currentStep = STATUS_MOVING;\n                                Entry.ZumiMiniLite.sendBuffers = [];\n                            }\n                            break;\n\n                        case STATUS_MOVING:\n                            if (hardwareStatus === HW_READY) {\n                                clearInterval(pollingInterval);\n                                return resolve();\n                            }\n                            break;\n                    }\n                }, 50);//650\n            });\n        };\n\n    })();\n})();\n\nmodule.exports = Entry.ZumiMiniLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_robotis_kkokdu_lite.js",
    "content": "'use strict';\n\nconst INST_NONE = 0;\nconst INST_READ = 2;\nconst INST_WRITE = 3;\nconst INST_DXL_REGWRITE = 4;\nconst INST_DXL_ACTION = 5;\nconst INST_DXL_SYNCWRITE = 0x83;\nconst INST_BYPASS_READ = 0xa2;\nconst INST_BYPASS_WRITE = 0xa3;\n\nconst INST_STATUS = 0x55;\n\nconst PACKET_STATE_IDLE = 0;\nconst PACKET_STATE_RESERVED = 1;\nconst PACKET_STATE_ID = 2;\nconst PACKET_STATE_LENGTH_L = 3;\nconst PACKET_STATE_LENGTH_H = 4;\nconst PACKET_STATE_DATA = 5;\nconst PACKET_STATE_CRC_L = 6;\nconst PACKET_STATE_CRC_H = 7;\n\nconst DEFAULT_DELAY = 50;\n\nconst rxPacket = {\n    header: [0, 0, 0],\n    reserved: 0,\n    id: 0,\n    cmd: 0,\n    error: 0,\n    type: 0,\n    index: 0,\n    packetLength: 0,\n    paramLength: 0,\n    crc: 0,\n    crcReceived: 0,\n    checksum: 0,\n    checksumReceived: 0,\n    data: [],\n};\n\nconst addrMap = [\n    [0, 4, 302],\n    [4, 1, 42],\n    [5, 1, 44],\n    [6, 1, 45],\n    [7, 1, 47],\n    [8, 1, 50],\n    [9, 1, 51],\n    [10, 1, 52],\n    [11, 1, 68],\n    [12, 2, 70],\n    [14, 2, 72],\n    [16, 2, 74],\n    [18, 2, 76],\n    [20, 2, 78],\n    [22, 2, 80],\n    [24, 2, 82],\n    [26, 2, 84],\n    [28, 1, 86],\n    [29, 1, 87],\n    [30, 2, 88],\n    [32, 2, 90],\n    [34, 1, 112],\n    [35, 1, 118],\n    [36, 1, 119],\n    [37, 1, 122],\n    [38, 1, 123],\n    [39, 1, 124],\n    [40, 1, 125],\n    [41, 1, 160],\n    [42, 1, 220],\n    [43, 2, 360],\n    [45, 2, 362],\n    [47, 2, 364],\n    [49, 2, 366],\n    [51, 2, 368],\n    [53, 2, 370],\n    [55, 1, 372],\n    [56, 1, 373],\n    [57, 1, 374],\n    [58, 1, 375],\n    [59, 1, 376],\n    [60, 1, 377],\n    [61, 1, 378],\n    [62, 1, 379],\n    [63, 1, 380],\n    [64, 1, 381],\n    [65, 1, 382],\n    [66, 1, 383],\n    [67, 1, 500],\n    [68, 1, 501],\n    [69, 8, 502],\n    [77, 1, 700],\n    [78, 1, 810],\n    [79, 1, 2134],\n    [80, 1, 5015],\n    [81, 1, 5030],\n    [82, 1, 5031],\n    [83, 1, 5040],\n];\n\nconst addrMap2 = [\n    [153, 1, 4000],\n    [154, 2, 4003],\n    [156, 1, 4005],\n    [157, 1, 4006],\n    [158, 2, 4009],\n    [160, 2, 4011],\n    [162, 2, 4013],\n    [164, 2, 4015],\n    [166, 2, 4017],\n    [168, 2, 4019],\n    [170, 2, 4021],\n    [172, 2, 4023],\n    [174, 2, 4025],\n    [176, 2, 4027],\n    [178, 1, 4031],\n    [179, 1, 4032],\n    [180, 1, 4033],\n    [181, 2, 4036],\n    [183, 2, 4038],\n    [185, 2, 4040],\n    [187, 2, 4042],\n    [189, 2, 4044],\n    [191, 2, 4046],\n    [193, 2, 4048],\n    [195, 2, 4050],\n];\n\nconst crcTable = [\n    0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039,\n    0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,\n    0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9,\n    0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,\n    0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099,\n    0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,\n    0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea,\n    0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,\n    0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179,\n    0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,\n    0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309,\n    0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,\n    0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359,\n    0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,\n    0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9,\n    0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,\n    0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9,\n    0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,\n    0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, 0x0246, 0x024c, 0x8249,\n    0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,\n    0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219,\n    0x0208, 0x820d, 0x8207, 0x0202,\n];\n\nconst rb100_last_valid_value = [];\nlet bg_color = 0;\nlet beat_per_minute = 75;\nlet camera_id_for_use = 0;\n\n(function () {\n    Entry.RobotisKkokduLite = new (class RobotisKkokduLite {\n        constructor() {\n            this.id = '070701';\n            this.url = 'http://www.robotis.com';\n            this.imageName = 'robotis_kkokdu_lite.png';\n            this.name = 'RobotisKkokduLite';\n            this.blockMenuBlocks = [\n                // 다이나믹셀 제어\n                'robotis_kkokdu_lite_dxl_set_mode',\n                'robotis_kkokdu_lite_dxl_set_position',\n                'robotis_kkokdu_lite_dxl_set_rotate',\n                'robotis_kkokdu_lite_dxl_set_multiturn_round',\n\n                // 값 블록\n                'robotis_kkokdu_lite_cm_ir_value',\n                'robotis_kkokdu_lite_cm_ir_compare',\n                'robotis_kkokdu_lite_detectFrontObj',\n                'robotis_kkokdu_lite_cm_btn_value',\n                'robotis_kkokdu_lite_cm_joystick_value',\n                'robotis_kkokdu_lite_mic',\n                'robotis_kkokdu_lite_detectSound_compare',\n                'robotis_kkokdu_lite_imu',\n                'robotis_kkokdu_lite_roll_pitch',\n\n                // 음계\n                'robotis_kkokdu_lite_buzzer_index',\n\n                // LCD 제어\n                'robotis_kkokdu_lite_rgee_screen',\n                'robotis_kkokdu_lite_rgee_anim_screen',\n                'robotis_kkokdu_lite_icon',\n                'robotis_kkokdu_lite_LCDBright',\n                'robotis_kkokdu_lite_LCDColor',\n\n                // LED 제어\n                'robotis_kkokdu_lite_led_brightness',\n                'robotis_kkokdu_lite_led_pattern',\n\n\n                // 소리\n                'robotis_kkokdu_lite_Hello',\n                'robotis_kkokdu_lite_effectSound',\n                'robotis_kkokdu_lite_record',\n                'robotis_kkokdu_lite_playRecord',\n\n                // 다른 로봇 LCD 화면 제어\n                'robotis_kkokdu_lite_rla_screen',\n                'robotis_kkokdu_lite_rla_anim_screen',\n                'robotis_kkokdu_lite_kkokdu_screen',\n                'robotis_kkokdu_lite_kkokdu_anim_screen',\n\n                // 모션 제어\n                'robotis_kkokdu_lite_motion',\n                'robotis_kkokdu_lite_motion_other',\n                'robotis_kkokdu_lite_motion_custom',\n                'robotis_kkokdu_lite_dxl_control',\n                'robotis_kkokdu_lite_dxl_position_time',\n\n                // 텍스트 출력\n                'robotis_kkokdu_lite_text_screen',\n            ];\n            this.portData = {\n                baudRate: 57600,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                connectionType: 'bytestream',\n                bufferSize: 128,\n                constantServing: true,\n            };\n            this.duration = 15;\n            this.setZero();\n\n            this.timeouts = [];\n\n            this.robotisBuffer = []; // buffer to transmit to H/W\n            this.receiveBuffer = []; // buffer to receive from H/W\n            this.dataBuffer = []; // saved control table value buffer\n\n            this.packetReceiveState = 0;\n            this.headerCount = 0;\n\n            this.dxlPositions = [];\n\n            this.pirPir = [];\n            this.pirTemperature = [];\n            this.pirHumidity = [];\n            this.pirBrightness = [];\n            this.distanceDistance = [];\n            this.distanceButton = [];\n            this.distanceBrightness = [];\n        }\n\n        setZero() {\n            this.timeouts = [];\n            this.__removeAllTimeouts();\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 7]); // App Coding 모드\n            this.robotisBuffer.push([INST_WRITE, 40, 2, 0]); // LED 끄기\n            this.robotisBuffer.push([INST_WRITE, 66, 2, 0]); // 모션 종료\n            this.robotisBuffer.push([INST_WRITE, 710, 2, 0]); // 바퀴 정지\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 20]); // App Coding 모드\n            this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기\n            camera_id_for_use = 0;\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        __removeTimeout(id) {\n            clearTimeout(id);\n            const idx = this.timeouts.indexOf(id);\n            if (idx >= 0) {\n                this.timeouts.splice(idx, 1);\n            }\n        }\n\n        __removeAllTimeouts() {\n            const timeouts = this.timeouts;\n            for (const i in timeouts) {\n                clearTimeout(timeouts[i]);\n            }\n            this.timeouts = [];\n        }\n\n        getMonitorPort() {\n            return { ...this.sensory, ...this.motoring, ...this.lineTracer };\n        }\n\n        writePacket(id, address, length, value) {\n            if (length > 256) {\n                console.log(`######### invalid length: ${length}`);\n                return null;\n            }\n            console.log('######### writePacket');\n            const packet = [];\n            let i = 0;\n            packet.push(0xff);\n            packet.push(0xff);\n            packet.push(0xfd);\n            packet.push(0x00);\n            packet.push(id);\n            packet.push(length + 5);\n            packet.push(0x00);\n            packet.push(INST_WRITE);\n            packet.push(this.getLowByte(address));\n            packet.push(this.getHighByte(address));\n            switch (length) {\n                case 1:\n                    packet.push(this.getLowByte(value));\n                    break;\n                case 2:\n                    packet.push(this.getLowByte(value));\n                    packet.push(this.getHighByte(value));\n                    break;\n                case 4:\n                    packet.push(this.getLowByte(this.getLowWord(value)));\n                    packet.push(this.getHighByte(this.getLowWord(value)));\n                    packet.push(this.getLowByte(this.getHighWord(value)));\n                    packet.push(this.getHighByte(this.getHighWord(value)));\n                    break;\n                default:\n                    for (i = 0; i < length; i++) {\n                        if (typeof value[i] == 'number') {\n                            packet.push(value[i]);\n                        } else if (typeof value[i] == 'string') {\n                            packet.push(value[i].charCodeAt(0));\n                        }\n                    }\n                    break;\n            }\n            const crc = this.updateCRC(0, packet, packet.length);\n            packet.push(this.getLowByte(crc));\n            packet.push(this.getHighByte(crc));\n            return packet;\n        }\n\n        registWritePacket(id, address, length, value) {\n            if (length > 256) {\n                console.log(`######### invalid length: ${length}`);\n                return null;\n            }\n            console.log('######### registWritePacket');\n            const packet = [];\n            let i = 0;\n            packet.push(0xff);\n            packet.push(0xff);\n            packet.push(0xfd);\n            packet.push(0x00);\n            packet.push(id);\n            packet.push(length + 5);\n            packet.push(0x00);\n            packet.push(INST_DXL_REGWRITE);\n            packet.push(this.getLowByte(address));\n            packet.push(this.getHighByte(address));\n            switch (length) {\n                case 1:\n                    packet.push(this.getLowByte(value));\n                    break;\n                case 2:\n                    packet.push(this.getLowByte(value));\n                    packet.push(this.getHighByte(value));\n                    break;\n                case 4:\n                    packet.push(this.getLowByte(this.getLowWord(value)));\n                    packet.push(this.getHighByte(this.getLowWord(value)));\n                    packet.push(this.getLowByte(this.getHighWord(value)));\n                    packet.push(this.getHighByte(this.getHighWord(value)));\n                    break;\n                default:\n                    for (i = 0; i < length; i++) {\n                        if (typeof value[i] == 'number') {\n                            packet.push(value[i]);\n                        } else if (typeof value[i] == 'string') {\n                            packet.push(value[i].charCodeAt(0));\n                        }\n                    }\n                    break;\n            }\n            const crc = this.updateCRC(0, packet, packet.length);\n            packet.push(this.getLowByte(crc));\n            packet.push(this.getHighByte(crc));\n            return packet;\n        }\n\n        actionPacket(id) {\n            console.log('######### actionPacket');\n            const packet = [];\n            packet.push(0xff);\n            packet.push(0xff);\n            packet.push(0xfd);\n            packet.push(0x00);\n            packet.push(id);\n            packet.push(0x03);\n            packet.push(0x00);\n            packet.push(INST_DXL_ACTION);\n            const crc = this.updateCRC(0, packet, packet.length);\n            packet.push(this.getLowByte(crc));\n            packet.push(this.getHighByte(crc));\n            return packet;\n        }\n\n        makeWord(a, b) {\n            return (a & 0xff) | ((b & 0xff) << 8);\n        }\n\n        getLowByte(a) {\n            return a & 0xff;\n        }\n\n        getHighByte(a) {\n            return (a >> 8) & 0xff;\n        }\n\n        getLowWord(a) {\n            return a & 0xffff;\n        }\n\n        getHighWord(a) {\n            return (a >> 16) & 0xffff;\n        }\n\n        updateCRC(crcAccum, dataBlkPtr, dataBlkSize) {\n            let i = 0;\n            let j = 0;\n            let crc = crcAccum;\n\n            for (j = 0; j < dataBlkSize; j++) {\n                i = ((crc >> 8) ^ dataBlkPtr[j]) & 0xff;\n                crc = (crc << 8) ^ crcTable[i];\n            }\n\n            return crc;\n        }\n\n        makeWord(a, b) {\n            return (a & 0xff) | ((b & 0xff) << 8);\n        }\n\n        getLowByte(a) {\n            return a & 0xff;\n        }\n\n        getHighByte(a) {\n            return (a >> 8) & 0xff;\n        }\n\n        getLowWord(a) {\n            return a & 0xffff;\n        }\n\n        getHighWord(a) {\n            return (a >> 16) & 0xffff;\n        }\n\n        updateCRC(crcAccum, dataBlkPtr, dataBlkSize) {\n            let i = 0;\n            let j = 0;\n            let crc = crcAccum;\n\n            for (j = 0; j < dataBlkSize; j++) {\n                i = ((crc >> 8) ^ dataBlkPtr[j]) & 0xff;\n                crc = (crc << 8) ^ crcTable[i];\n            }\n\n            return crc;\n        }\n\n        removeStuffing(buffer, length) {\n            let i = 0;\n            let stuffLength = 0;\n            let index = 0;\n\n            for (i = 0; i < length; i++) {\n                if (i >= 2) {\n                    if (buffer[i - 2] == 0xff && buffer[i - 1] == 0xff && buffer[i] == 0xfd) {\n                        i++;\n                        stuffLength++;\n                    }\n                }\n                buffer[index++] = buffer[i];\n            }\n\n            return stuffLength;\n        }\n\n        postCallReturn(script, data, ms) {\n            /*\n            if (data == null) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            } else if (data.length == 0) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n            */\n            if (!script.isStart) {\n                script.isStart = true;\n                script.timeFlag = 1;\n                for (let i = 0; i < data.length; i++) {\n                    this.robotisBuffer.push(data[i]);\n                }\n                //delay ms\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, ms);\n                return script;\n            } else if (script.timeFlag) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.timeFlag;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // DXL 제어\n                        robotis_kkokdu_lite_dxl_set_mode: \"%1 모터 %2 모드로 설정 %3\",\n                        robotis_kkokdu_lite_dxl_each_control: \"%1 모터 %2°로 %3 초 동안 움직이기 %4\",\n                        robotis_kkokdu_lite_dxl_set_position: \"%1 모터 %2 속도로 %3° 위치로 회전 %4\",\n                        robotis_kkokdu_lite_dxl_set_rotate: \"%1 모터 %2 속도로 %3 으로 %4 %5\",\n                        robotis_kkokdu_lite_dxl_set_multiturn_round:\n                            '%1 모터 %2 속도로 %3 바퀴 %4으로 회전 %5',\n\n                        // 값 블록\n                        robotis_kkokdu_lite_cm_ir_value: '%1 번 IR 센서 값',\n                        robotis_kkokdu_lite_cm_ir_compare: '%1 번 IR 센서 값이 %2  %3이면',\n                        robotis_kkokdu_lite_detectFrontObj: '앞에 물체가 있으면',\n                        robotis_kkokdu_lite_cm_btn_value: '%1 버튼이 %2 이면',\n                        robotis_kkokdu_lite_cm_joystick_value:\n                            '조이스틱 위치가 %1 이면',\n                        robotis_kkokdu_lite_mic: '마이크 음량(dB)',\n                        robotis_kkokdu_lite_detectSound_compare: '소리가 %1에서 나면',\n                        robotis_kkokdu_lite_imu: '%1축의 %2 값',\n                        robotis_kkokdu_lite_roll_pitch: '제어기 각도 %1 값',\n\n                        // 음계\n                        robotis_kkokdu_lite_buzzer_index: '제어기 음계값 %1 을(를) %2 옥타브로 %3 초 동안 %4 %5',\n\n                        // LCD 제어\n                        robotis_kkokdu_lite_rla_screen: '제어기 화면 배경을 알라 %1 (으)로 선택 %2',\n                        robotis_kkokdu_lite_rla_anim_screen:\n                            '제어기 화면 애니메이션을 알라 %1 (으)로 선택 %2',\n                        robotis_kkokdu_lite_icon:\n                            \"제어기 화면에 %1 출력하기 %5\",\n                        robotis_kkokdu_lite_LCDBright: '제어기 화면 밝기를 %1 (으)로 정하기 %2',\n                        robotis_kkokdu_lite_LCDColor: '제어기 화면 색상을 %1 (으)로 정하기 %2',\n\n                        // LED 제어\n                        robotis_kkokdu_lite_led_brightness: '제어기 %1 LED 밝기를 %2(으)로 정하기 %3',\n                        robotis_kkokdu_lite_led_pattern: '제어기 %1 LED %2 %3',\n\n                        // 소리\n                        robotis_kkokdu_lite_Hello: '%1 말하기 %2',\n                        robotis_kkokdu_lite_effectSound: '효과음 %1 재생하기 %2',\n                        robotis_kkokdu_lite_record: '%1 번 방에 녹음하기 %2',\n                        robotis_kkokdu_lite_playRecord: '%1 번 방 소리 재생하기 %2',\n\n                        // 다른 로봇 LCD 제어\n                        robotis_kkokdu_lite_rgee_screen: '제어기 화면 배경을 알쥐 %1 (으)로 선택 %2',\n                        robotis_kkokdu_lite_rgee_anim_screen:\n                            '제어기 화면 애니메이션을 알쥐 %1 (으)로 선택 %2',\n                        robotis_kkokdu_lite_kkokdu_screen: '제어기 화면 배경을 꼭두 %1 (으)로 선택 %2',\n                        robotis_kkokdu_lite_kkokdu_anim_screen:\n                            '제어기 화면 애니메이션을 꼭두 %1 (으)로 선택 %2',\n                        robotis_kkokdu_lite_text_screen:\n                            '제어기 화면에 %1을(를) (%2, %3)위치에 %4 로 %5(으)로 출력하기 %6',\n\n\n                        // 모션 & DXL 제어\n                        robotis_kkokdu_lite_motion: \"휴머노이드 이동 모션 %1 실행 %2\",\n                        robotis_kkokdu_lite_motion_other: \"휴머노이드 기타 모션 %1 실행 %2\",\n                        robotis_kkokdu_lite_motion_custom: \"휴머노이드 커스텀 모션 %1 실행 %2\",\n                        robotis_kkokdu_lite_dxl_control: \"1번 모터 %1° 2번 모터 %2° 3번 모터 %3° 4번 모터 %4° 5번 모터 %5° 6번 모터 %6° 7번 모터 %7° 8번 모터 %8° %9초 동안 움직이기 %10\",\n                        robotis_kkokdu_lite_dxl_position_time: \"%1 모터 %2° %3 초 동안 움직이기 %4\",\n                    },\n                    Helper: {\n                        // DXL 제어\n                        robotis_kkokdu_lite_dxl_set_mode: \"지정한 ID의 모터의 동작모드를 설정\",\n                        robotis_kkokdu_lite_dxl_set_position: \"지정한 ID의 모터가 지정한 속도로 지정한 각도로 움직이도록 설정\",\n                        robotis_kkokdu_lite_dxl_set_rotate: \"지정한 ID의 모터의 회전 속도와 방향을 설정\",\n                        robotis_kkokdu_lite_dxl_set_multiturn_round:\n                            '지정한 ID의 모터가 지정한 속도와 방향으로 지정한 바퀴만큼 회전',\n\n                        // 값 블록\n                        robotis_kkokdu_lite_cm_ir_value:\n                            '지정한 번호의 IR 센서 값(범위: 0 ~ 400)',\n                        robotis_kkokdu_lite_cm_ir_compare:\n                            \"지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_kkokdu_lite_detectFrontObj:\n                            \"지정한 센서 앞에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_kkokdu_lite_cm_btn_value:\n                            \"지정한 버튼이 눌렸다가 해제되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_kkokdu_lite_cm_joystick_value:\n                            \"조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다..\",\n                        robotis_kkokdu_lite_mic:\n                            '마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.',\n                        robotis_kkokdu_lite_detectSound_compare:\n                            \"소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_kkokdu_lite_imu:\n                            '지정한 축의 지정한 가속도센서/자이로센서의 값\\n범위: -100 ~ 100',\n                        robotis_kkokdu_lite_roll_pitch:\n                            'roll/pitch 값\\nroll: -180° ~ 180°, pitch: -90° ~ 90°',\n\n                        // 소리\n                        robotis_kkokdu_lite_buzzer_index: '지정한 음계, 옥타브, 시간만큼 연주하기',\n\n                        // LCD 제어\n                        robotis_kkokdu_lite_rgee_screen: '제어기 화면배경을 알쥐의 지정한 표정으로 설정',\n                        robotis_kkokdu_lite_rgee_anim_screen:\n                            '제어기 화면 애니메이션을 알쥐의 지정한 표정으로 설정',\n                        robotis_kkokdu_lite_icon:\n                            '화면 중앙에 지정한 아이콘을 표시',\n                        robotis_kkokdu_lite_LCDBright: '화면 밝기를 설정\\n밝기범위: 1% ~ 100%',\n                        robotis_kkokdu_lite_LCDColor: '화면 색상을 설정',\n\n                        // LED 제어\n                        robotis_kkokdu_lite_led_brightness: '제어기의 지정한 LED의 밝기를 설정정',\n                        robotis_kkokdu_lite_led_pattern: '제어기의 LED의 깜박임 패턴 설정',\n\n                        // 소리\n                        robotis_kkokdu_lite_Hello: '지정한 문장을 말하기',\n                        robotis_kkokdu_lite_effectSound: '지정한 효과음 재생하기',\n                        robotis_kkokdu_lite_record: '제어기의 지정한 번호에 녹음하기',\n                        robotis_kkokdu_lite_playRecord: '제어기의 지정한 번호의 녹음음성 재생하기기',\n\n                        // 다른 로봇 LCD 제어\n                        robotis_kkokdu_lite_rla_screen: '제어기 화면배경을 알라의 지정한 표정으로 설정',\n                        robotis_kkokdu_lite_rla_anim_screen:\n                            '제어기 화면 애니메이션을 알라의 지정한 표정으로 설정',\n                        robotis_kkokdu_lite_kkokdu_screen: '제어기 화면배경을 꼭두의 지정한 표정으로 설정',\n                        robotis_kkokdu_lite_kkokdu_anim_screen:\n                            '제어기 화면 애니메이션을 꼭두두의 지정한 표정으로 설정',\n                        robotis_kkokdu_lite_text_screen:\n                            '화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n\n                        // 모션 제어\n                        robotis_kkokdu_lite_motion: \"지정한 이동 모션 실행\",\n                        robotis_kkokdu_lite_motion_other: \"지정한 기타 모션 실행\",\n                        robotis_kkokdu_lite_motion_custom: \"지정한 번호의 모션 실행\",\n                        robotis_kkokdu_lite_dxl_control: \"1 ~ 8번 관절을 각각 지정한 위치로 지정한 시간내에 이동\",\n                        robotis_kkokdu_lite_dxl_position_time: \"지정한 관절을 지정한 시간동안 지정한 위치로 이동\",\n                    },\n                    Blocks: {\n                        robotis_white: \"흰색\",\n                        robotis_gray: \"회색\",\n                        robotis_darkgray: \"진회색\",\n                        robotis_black: \"검정\",\n                        robotis_purple: \"보라\",\n                        robotis_pink: \"분홍색\",\n                        robotis_red: \"빨강\",\n                        robotis_orange: \"주황\",\n                        robotis_brown: \"갈색\",\n                        robotis_yellow: \"노랑\",\n                        robotis_green: \"초록\",\n                        robotis_blue: \"파랑\",\n                        robotis_lightblue: \"연파랑\",\n                        robotis_darkblue: \"남색\",\n                        robotis_left: \"왼쪽\",\n                        robotis_center: \"중앙\",\n                        robotis_right: \"오른쪽\",\n                        robotis_both: \"양쪽\",\n                        robotis_korean1: \"안녕하세요\",\n                        robotis_korean2: \"반가워요\",\n                        robotis_korean3: \"알겠어요\",\n                        robotis_korean4: \"아니에요\",\n                        robotis_korean5: \"모르겠어요\",\n                        robotis_korean6: \"좋아요\",\n                        robotis_korean7: \"싫어요\",\n                        robotis_korean8: \"이름을말하세요\",\n                        robotis_korean9: \"무엇을도와줄까?\",\n                        robotis_korean10: \"잘했어\",\n                        robotis_korean11: \"괜찮아\",\n                        robotis_korean12: \"다시해보자\",\n                        robotis_korean13: \"고마워\",\n                        robotis_korean14: \"다시말해줄래?\",\n                        robotis_korean15: \"최고야!\",\n                        robotis_korean16: \"신나요\",\n                        robotis_korean17: \"즐거워요\",\n                        robotis_korean18: \"미안해요\",\n                        robotis_korean19: \"화나요\",\n                        robotis_korean20: \"부끄러워요\",\n                        robotis_korean21: \"무서워요\",\n                        robotis_korean22: \"속상해요\",\n                        robotis_korean23: \"사랑해요\",\n                        robotis_korean24: \"예뻐요\",\n                        robotis_korean25: \"신기해요\",\n                        robotis_korean26: \"초조해요\",\n                        robotis_korean27: \"앞으로가자\",\n                        robotis_korean28: \"뒤로가자\",\n                        robotis_korean29: \"일어나자\",\n                        robotis_korean30: \"넘어졌네?\",\n                        robotis_korean31: \"오예\",\n                        robotis_korean32: \"아싸\",\n                        robotis_korean33: \"어머\",\n                        robotis_korean34: \"이런\",\n                        robotis_korean35: \"오호\",\n                        robotis_korean36: \"하하하\",\n                        robotis_korean37: \"호호호\",\n                        robotis_korean38: \"졸려\",\n                        robotis_korean39: \"자장가를들려줘\",\n                        robotis_korean40: \"안녕\",\n                        robotis_korean41: \"배고프다\",\n                        robotis_korean42: \"도토리땡긴다\",\n                        robotis_korean43: \"아.씻고싶어\",\n                        robotis_korean44: \"비누목욕시간이야\",\n                        robotis_korean45: \"심심한데\",\n                        robotis_korean46: \"간식먹을까\",\n                        robotis_korean47: \"아파요\",\n                        robotis_korean48: \"약은없나요?\",\n                        robotis_korean49: \"어디로가야하지?\",\n                        robotis_korean50: \"와아도착이다\",\n                        robotis_korean51: \"왼쪽으로가자\",\n                        robotis_korean52: \"오른쪽으로가자\",\n                        robotis_korean53: \"깜짝이야\",\n                        robotis_korean54: \"찾았다\",\n                        robotis_korean55: \"여긴없네\",\n                        robotis_korean56: \"혹시나불렀어?\",\n                        robotis_korean57: \"내려주세요\",\n                        robotis_korean58: \"앗\",\n                        robotis_korean59: \"힝\",\n                        robotis_korean60: \"이익\",\n                        robotis_dog: \"개\",\n                        robotis_frog: \"개구리\",\n                        robotis_cat: \"고양이\",\n                        robotis_chicken: \"닭\",\n                        robotis_tiger: \"호랑이\",\n                        robotis_mouse: \"쥐\",\n                        robotis_ambul: \"앰뷸런스\",\n                        robotis_Horn: \"경적(빵빵)\",\n                        robotis_siren: \"사이렌(경찰차)\",\n                        robotis_whistle: \"호루라기\",\n                        robotis_gun: \"총소리\",\n                        robotis_clap: \"박수소리\",\n                        robotis_melody1: \"멜로디1\",\n                        robotis_melody2: \"멜로디2\",\n                        robotis_melody3: \"멜로디3\",\n                        robotis_melody4: \"멜로디4\",\n                        robotis_forward: \"앞으로\",\n                        robotis_backward: \"뒤로\",\n                        robotis_acceleration: \"가속도\",\n                        robotis_gyro: \"자이로\",\n                        robotis_run: \"실행\",\n                        robotis_cancel: \"취소\",\n                        robotis_push: \"눌림\",\n                        robotis_notPush: \"안눌림\",\n                        robotis_play: \"연주\",\n                        robotis_rest: \"쉼표\",\n                        robotis_face01: \"와하하\",\n                        robotis_face02: \"싱글벙글\",\n                        robotis_face03: \"큭큭큭\",\n                        robotis_face04: \"냠냠\",\n                        robotis_face05: \"겁먹음\",\n                        robotis_face06: \"답답\",\n                        robotis_face07: \"갸우뚱\",\n                        robotis_face08: \"어벙벙\",\n                        robotis_face09: \"고함\",\n                        robotis_face10: \"화남\",\n                        robotis_face11: \"킁킁(왼쪽)\",\n                        robotis_face12: \"킁킁(오른쪽)\",\n                        robotis_face13: \"킁킁(아래)\",\n                        robotis_face14: \"안심\",\n                        robotis_face15: \"기절\",\n                        robotis_face16: \"헤롱헤롱\",\n                        robotis_face17: \"하품\",\n                        robotis_face18: \"졸림\",\n                        robotis_face19: \"잠듦\",\n                        robotis_face20: \"마음앓이\",\n                        robotis_face21: \"폭풍눈물\",\n                        robotis_face22: \"목욕\",\n                        robotis_face23: \"햐트뿅뿅\",\n\n                        robotis_car_anim01: \"기본 표정\",\n                        robotis_car_anim02: \"감동\",\n                        robotis_car_anim03: \"미소\",\n                        robotis_car_anim04: \"웃음\",\n                        robotis_car_anim05: \"기쁨\",\n                        robotis_car_anim06: \"행복\",\n                        robotis_car_anim07: \"자신감\",\n                        robotis_car_anim08: \"화남\",\n                        robotis_car_anim09: \"우울\",\n                        robotis_car_anim10: \"슬픔\",\n                        robotis_car_anim11: \"고통\",\n                        robotis_car_anim12: \"기절\",\n                        robotis_car_anim13: \"공포\",\n                        robotis_car_anim14: \"하품\",\n                        robotis_car_anim15: \"졸림\",\n                        robotis_car_anim16: \"오른쪽보기\",\n                        robotis_car_anim17: \"왼쪽보기\",\n                        robotis_car_anim18: \"앞쪽보기\",\n                        robotis_car_anim19: \"깜짝놀람\",\n\n                        robotis_flashing1: \"점멸1\",\n                        robotis_flashing2: \"점멸2\",\n                        robotis_flashing3: \"점멸3\",\n                        robotis_flashing4: \"점멸4\",\n                        robotis_flashing5: \"점멸5\",\n                        robotis_flashing6: \"점멸6\",\n                        robotis_flashing7: \"점멸7\",\n                        robotis_flashing8: \"점멸8\",\n                        robotis_flashing9: \"점멸9\",\n                        robotis_moveF: \"전진\",\n                        robotis_moveB: \"후진\",\n                        robotis_moveL: \"좌회전\",\n                        robotis_moveR: \"우회전\",\n                        robotis_moveU: 'U턴',\n                        robotis_moveL_in_place: '제자리 좌회전',\n                        robotis_moveR_in_place: '제자리 우회전',\n                        robotis_moveU_in_place: '제자리 U턴',\n                        robotis_moveRG1: \"일어서기\",\n                        robotis_moveRG2: \"앉기\",\n                        robotis_moveRG3: \"발버둥\",\n                        robotis_moveRG4: \"발들기\",\n                        robotis_stMotion1: \"기본자세\",\n                        robotis_stMotion2: \"전진\",\n                        robotis_stMotion3: \"우전진\",\n                        robotis_stMotion4: \"좌전진\",\n                        robotis_stMotion5: \"후진\",\n                        robotis_stMotion6: \"오른쪽으로\",\n                        robotis_stMotion7: \"왼쪽으로\",\n                        robotis_stMotion8: \"우회전\",\n                        robotis_stMotion9: \"좌회전\",\n                        robotis_spMotion1: \"오른손 들기\",\n                        robotis_spMotion2: \"오른손 내리기\",\n                        robotis_spMotion3: \"왼손 들기\",\n                        robotis_spMotion4: \"왼손 내리기\",\n                        robotis_spMotion5: \"양손 들기\",\n                        robotis_spMotion6: \"양손 내리기\",\n                        robotis_spMotion7: \"뒤로 넘어지기\",\n                        robotis_spMotion8: \"앞으로 넘어지기\",\n                        robotis_spMotion9: \"앞으로 일어서기\",\n                        robotis_spMotion10: \"뒤로 일어서기\",\n                        robotis_spMotion11: \"방어\",\n                        robotis_spMotion12: \"공격1\",\n                        robotis_spMotion13: \"공격2\",\n                        robotis_spMotion14: \"공격3\",\n                        robotis_spMotion15: \"공격4\",\n                        robotis_screen1: \"가위\",\n                        robotis_screen2: \"바위\",\n                        robotis_screen3: \"보\",\n                        robotis_clockwise: \"시계방향\",\n                        robotis_counterclockwise: \"반시계방향\",\n                        robotis_up: \"들기\",\n                        robotis_down: \"내리기\",\n                        robotis_screen_text_font_small: \"작은 폰트\",\n                        robotis_screen_text_font_big: \"큰 폰트\",\n                        robotis_sensing_temperature: \"온도센서\",\n                        robotis_sensing_humidity: \"습도센서\",\n                        robotis_sensing_brightness: \"밝기센서\",\n                        robotis_sensing_motion: \"움직임센서\",\n                        robotis_sensing_button: \"버튼센서\",\n                        robotis_sensing_distance: \"거리센서\",\n                        robotis_sensing_ir_left: \"왼쪽 적외선센서\",\n                        robotis_sensing_ir_right: \"오른쪽 적외선센서\",\n                        robotis_stage_1: \"1단계\",\n                        robotis_stage_2: \"2단계\",\n                        robotis_stage_3: \"3단계\",\n                    },\n                },\n                en: {\n                    template: {\n                        // DXL 제어\n                        robotis_kkokdu_lite_dxl_set_mode: \"Set ID %1 motor as %2 mode %3\",\n                        robotis_kkokdu_lite_dxl_set_position: \"Rotate ID %1 motor to angle %3° at speed %2 %4\",\n                        robotis_kkokdu_lite_dxl_set_rotate: \"%4 ID %1 motor %3 at speed %2 %4\",\n                        robotis_kkokdu_lite_dxl_set_multiturn_round:\n                            'Rotate ID %1 motor %3 times %4 at speed %2 %5',\n\n                        // Value Blocks\n                        robotis_kkokdu_lite_cm_ir_value: 'IR sensor value of No. %1',\n                        robotis_kkokdu_lite_cm_ir_compare: 'If the IR sensor value of No. %1 is %2 %3',\n                        robotis_kkokdu_lite_detectFrontObj: 'If there is an object in front',\n                        robotis_kkokdu_lite_cm_btn_value: 'If button %1 is %2',\n                        robotis_kkokdu_lite_cm_joystick_value: 'If joystick is at %1',\n                        robotis_kkokdu_lite_mic: 'Microphone volume (dB)',\n                        robotis_kkokdu_lite_detectSound_compare: 'If the sound comes from %1',\n                        robotis_kkokdu_lite_imu: '%2 value of %1 axis',\n                        robotis_kkokdu_lite_roll_pitch: 'Controller angle %1 value',\n\n                        // Musical Scale\n                        robotis_kkokdu_lite_buzzer_index: 'Play note %1 on controller in octave %2 for %3 seconds %4 %5',\n\n                        // LCD Control\n                        robotis_kkokdu_lite_rgee_screen: 'Set controller screen background to R-Gee %1 %2',\n                        robotis_kkokdu_lite_rgee_anim_screen: 'Set controller screen animation to R-Gee %1 %2',\n                        robotis_kkokdu_lite_icon: 'Display %1 on controller screen %5',\n                        robotis_kkokdu_lite_LCDBright: 'Set controller screen brightness to %1 %2',\n                        robotis_kkokdu_lite_LCDColor: 'Set controller screen color to %1 %2',\n\n                        // LED Control\n                        robotis_kkokdu_lite_led_brightness: 'Set controller LED %1 brightness to %2 %3',\n                        robotis_kkokdu_lite_led_pattern: 'Controller LED %1 %2 %3',\n\n                        // Sound\n                        robotis_kkokdu_lite_Hello: 'Say \"%1\" %2',\n                        robotis_kkokdu_lite_effectSound: 'Play sound effect %1 %2',\n                        robotis_kkokdu_lite_record: 'Record in slot %1 %2',\n                        robotis_kkokdu_lite_playRecord: 'Play sound from slot %1 %2',\n\n                        // Other Robot LCD Control\n                        robotis_kkokdu_lite_rla_screen: 'Set controller screen background to Kodala %1 %2',\n                        robotis_kkokdu_lite_rla_anim_screen: 'Set controller screen animation to Kodala %1 %2',\n                        robotis_kkokdu_lite_kkokdu_screen: 'Set controller screen background to TIG %1 %2',\n                        robotis_kkokdu_lite_kkokdu_anim_screen: 'Set controller screen animation to TIG %1 %2',\n                        robotis_kkokdu_lite_text_screen: 'Display \"%1\" on screen at (%2, %3) with font %4 and color %5 %6',\n                        \n                        // Motion & DXL Control\n                        robotis_kkokdu_lite_motion: \"Execute humanoid movement motion %1 %2\",\n                        robotis_kkokdu_lite_motion_other: \"Execute humanoid other motion %1 %2\",\n                        robotis_kkokdu_lite_motion_custom: \"Execute humanoid custom motion %1 %2\",\n                        robotis_kkokdu_lite_dxl_control: \"Move motor 1 to %1°, motor 2 to %2°, motor 3 to %3°, motor 4 to %4°, motor 5 to %5°, motor 6 to %6°, motor 7 to %7°, motor 8 to %8° over %9 seconds %10\",\n                        robotis_kkokdu_lite_dxl_position_time: \"Move motor %1 to %2° over %3 seconds %4\",\n\n                    },\n                    Helper: {\n                        // DXL 제어\n                        robotis_kkokdu_lite_dxl_set_mode: \"Set the operating mode of the motor with the specified ID\",\n                        robotis_kkokdu_lite_dxl_set_position: \"Set the motor with the specified ID to move to the specified angle at the specified speed\",\n                        robotis_kkokdu_lite_dxl_set_rotate: \"Set the rotation speed and direction of the motor with the specified ID\",\n                        robotis_kkokdu_lite_dxl_set_multiturn_round:\n                            'Set the motor with the specified ID to rotate the specified number of turns at the specified speed and direction',\n\n                        // Value blocks\n                        robotis_kkokdu_lite_cm_ir_value: 'IR sensor value of the specified number (Range: 0 ~ 400)',\n                        robotis_kkokdu_lite_cm_ir_compare: \"Returns 'true' if the comparison of the IR sensor value of the specified number and the given value is correct; otherwise returns 'false'.\",\n                        robotis_kkokdu_lite_detectFrontObj: \"Returns 'true' if an object is detected in front of the specified sensor; otherwise returns 'false'.\",\n                        robotis_kkokdu_lite_cm_btn_value: \"Returns 'true' if the specified button was pressed and released; otherwise returns 'false'.\",\n                        robotis_kkokdu_lite_cm_joystick_value: \"Returns 'true' if the joystick position matches the specified state; otherwise returns 'false'.\",\n                        robotis_kkokdu_lite_mic: 'Displays the intensity of sound detected by the microphone in decibels (dB).',\n                        robotis_kkokdu_lite_detectSound_compare: \"Returns 'true' if the direction of the sound matches the specified direction; otherwise returns 'false'.\",\n                        robotis_kkokdu_lite_imu: 'Value of the specified axis of the accelerometer/gyroscope sensor\\nRange: -100 ~ 100',\n                        robotis_kkokdu_lite_roll_pitch: 'Roll/pitch values\\nRoll: -180° ~ 180°, Pitch: -90° ~ 90°',\n\n                        // Sound\n                        robotis_kkokdu_lite_buzzer_index: 'Play the specified scale, octave, and duration',\n\n                        // LCD control\n                        robotis_kkokdu_lite_rgee_screen: 'Set the controller screen background to the specified R-Gee expression',\n                        robotis_kkokdu_lite_rgee_anim_screen: 'Set the controller screen animation to the specified R-Gee expression',\n                        robotis_kkokdu_lite_icon: 'Display the specified icon at the center of the screen',\n                        robotis_kkokdu_lite_LCDBright: 'Set the screen brightness\\nBrightness range: 1% ~ 100%',\n                        robotis_kkokdu_lite_LCDColor: 'Set the screen color',\n\n                        // LED control\n                        robotis_kkokdu_lite_led_brightness: 'Set the brightness of the specified LED on the controller',\n                        robotis_kkokdu_lite_led_pattern: 'Set the blinking pattern of the LED on the controller',\n\n                        // Sound\n                        robotis_kkokdu_lite_Hello: 'Speak the specified sentence',\n                        robotis_kkokdu_lite_effectSound: 'Play the specified sound effect',\n                        robotis_kkokdu_lite_record: 'Record on the specified number of the controller',\n                        robotis_kkokdu_lite_playRecord: 'Play the recorded voice of the specified number on the controller',\n\n                        // Other robot LCD control\n                        robotis_kkokdu_lite_rla_screen: 'Set the controller screen background to the specified expression of R-LA',\n                        robotis_kkokdu_lite_rla_anim_screen: 'Set the controller screen animation to the specified expression of R-LA',\n                        robotis_kkokdu_lite_kkokdu_screen: 'Set the controller screen background to the specified expression of Kkokdu',\n                        robotis_kkokdu_lite_kkokdu_anim_screen: 'Set the controller screen animation to the specified expression of Kkokdu',\n                        robotis_kkokdu_lite_text_screen: 'Set the location, font size, and color of the specified phrase to be displayed on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n                    \n                \n                        // Motion & DXL control\n                        robotis_kkokdu_lite_motion: \"Execute specified movement motion\",\n                        robotis_kkokdu_lite_motion_other: \"Execute specified other motion\",\n                        robotis_kkokdu_lite_motion_custom: \"Execute motion with specified number\",\n                        robotis_kkokdu_lite_dxl_control: \"Move joints 1 to 8 to specified positions within specified time\",\n                        robotis_kkokdu_lite_dxl_position_time: \"Move specified joint to specified position over specified time\",\n\n                    },\n\n                    Blocks: {\n                        robotis_white: 'White',\n                        robotis_gray: 'Gray',\n                        robotis_darkgray: 'Darkgray',\n                        robotis_black: 'Black',\n                        robotis_purple: 'Purple',\n                        robotis_pink: 'Pink',\n                        robotis_red: 'Red',\n                        robotis_orange: 'Orange',\n                        robotis_brown: 'Brown',\n                        robotis_yellow: 'Yellow',\n                        robotis_green: 'Green',\n                        robotis_blue: 'Blue',\n                        robotis_lightblue: 'Lightblue',\n                        robotis_darkblue: 'Darkblue',\n                        robotis_brown: 'Brown',\n                        robotis_left: 'Left',\n                        robotis_center: 'Center',\n                        robotis_right: 'Right',\n                        robotis_both: 'Both',\n\n                        robotis_rla: 'R-GEE',\n                        robotis_rla: 'KODALA',\n                        robotis_kkokdu: 'TIG',\n\n                        robotis_korean1: 'Hello!',\n                        robotis_korean2: 'Great to see you.',\n                        robotis_korean3: 'Okay ~',\n                        robotis_korean4: 'No!',\n                        robotis_korean5: \"I don't know.\",\n                        robotis_korean6: 'I like it.',\n                        robotis_korean7: \"I don't like it.\",\n                        robotis_korean8: 'What is your name? ',\n                        robotis_korean9: 'How can I help you? ',\n                        robotis_korean10: 'Great job! ',\n                        robotis_korean11: \"It's alright.\",\n                        robotis_korean12: \"Let's do it again! \",\n                        robotis_korean13: 'Thank you! ',\n                        robotis_korean14: 'Can you say that one more time?',\n                        robotis_korean15: 'Awesome!',\n                        robotis_korean16: \"I'm excited! \",\n                        robotis_korean17: \"I'm having a great time! \",\n                        robotis_korean18: \"I'm sorry.\",\n                        robotis_korean19: \"I'm angry! \",\n                        robotis_korean20: \"I'm embarassed.\",\n                        robotis_korean21: \"I'm scared.\",\n                        robotis_korean22: \"I'm upset.\",\n                        robotis_korean23: 'I love you.',\n                        robotis_korean24: 'Very pretty! ',\n                        robotis_korean25: 'Interesting.',\n                        robotis_korean26: \"I'm nervous.\",\n                        robotis_korean27: \"Let's move forward! \",\n                        robotis_korean28: \"Let's move backward! \",\n                        robotis_korean29: \"Let's stand up! \",\n                        robotis_korean30: 'Did you fall down? ',\n                        robotis_korean31: 'Oh Yeah~',\n                        robotis_korean32: 'Sweet! ',\n                        robotis_korean33: 'Oh no',\n                        robotis_korean34: 'My My ',\n                        robotis_korean35: 'Whoo hoo! ',\n                        robotis_korean36: 'Ha Ha Ha',\n                        robotis_korean37: 'Ho Ho Ho ',\n                        robotis_korean38: \"I'm sleepy.\",\n                        robotis_korean39: 'Sing me a bedtime song! ',\n                        robotis_korean40: 'Hello!',\n                        robotis_korean41: \"I'm hungry.\",\n                        robotis_korean42: \"I'm craving an acorn! \",\n                        robotis_korean43: 'I want to take a bath! ',\n                        robotis_korean44: 'Time for a bath! ',\n                        robotis_korean45: \"I'm bored. \",\n                        robotis_korean46: 'Do you want a snack? ',\n                        robotis_korean47: \"I'm sick.\",\n                        robotis_korean48: 'Do you have any medicine? ',\n                        robotis_korean49: 'Where do we have to go? ',\n                        robotis_korean50: \"We're here! \",\n                        robotis_korean51: \"Let's go to the left side! \",\n                        robotis_korean52: \"Let's go to the right side! \",\n                        robotis_korean53: 'Oh my, you scared me! ',\n                        robotis_korean54: 'Found you! ',\n                        robotis_korean55: \"There's nothing here. \",\n                        robotis_korean56: 'Did you call me?',\n                        robotis_korean57: 'Please let me down. ',\n                        robotis_korean58: 'Oops! ',\n                        robotis_korean59: 'Hmmph! ',\n                        robotis_korean60: 'Eek! ',\n                        robotis_dog: 'Dog',\n                        robotis_frog: 'Frog',\n                        robotis_cat: 'Cat',\n                        robotis_chicken: 'Rooster',\n                        robotis_tiger: 'Tiger',\n                        robotis_mouse: 'Mouse',\n                        robotis_whistle: 'Whistle',\n                        robotis_ambul: 'Ambulance',\n                        robotis_Horn: 'CarHorn',\n                        robotis_siren: 'Siren',\n                        robotis_gun: 'Gunshot',\n                        robotis_clap: 'Clap',\n                        robotis_melody1: 'Melody1',\n                        robotis_melody2: 'Melody2',\n                        robotis_melody3: 'Melody3',\n                        robotis_melody4: 'Melody4',\n                        robotis_forward: 'Forward',\n                        robotis_backward: 'Backward',\n                        robotis_acceleration: 'acceleration',\n                        robotis_gyro: 'gyro',\n                        robotis_run: 'Run',\n                        robotis_cancel: 'Cancel',\n                        robotis_push: 'Pressed',\n                        robotis_notPush: 'Unpressed',\n                        robotis_play: 'Play',\n                        robotis_rest: 'Rest',\n                        robotis_face01: 'Haha',\n                        robotis_face02: 'Smile',\n                        robotis_face03: 'Laugh',\n                        robotis_face04: 'Yum Yum',\n                        robotis_face05: 'Scared',\n                        robotis_face06: 'Uncomfortable',\n                        robotis_face07: 'Confused',\n                        robotis_face08: 'Dazed',\n                        robotis_face09: 'Yell',\n                        robotis_face10: 'Angry',\n                        robotis_face11: 'Sniff (Left)',\n                        robotis_face12: 'Sniff (Right)',\n                        robotis_face13: 'Sniff (Down)',\n                        robotis_face14: 'Whew',\n                        robotis_face15: 'Faint',\n                        robotis_face16: 'Dizzy',\n                        robotis_face17: 'Yawn',\n                        robotis_face18: 'Sleepy',\n                        robotis_face19: 'Sleep',\n                        robotis_face20: 'Sad',\n                        robotis_face21: 'Cry',\n                        robotis_face22: 'Bath',\n                        robotis_face23: 'Heart-Eyes',\n\n                        robotis_car_anim01: \"Default\",\n                        robotis_car_anim02: \"Touched\",\n                        robotis_car_anim03: \"Smile\",\n                        robotis_car_anim04: \"Laugh\",\n                        robotis_car_anim05: \"Joy\",\n                        robotis_car_anim06: \"Happiness\",\n                        robotis_car_anim07: \"Confidence\",\n                        robotis_car_anim08: \"Anger\",\n                        robotis_car_anim09: \"Depressed\",\n                        robotis_car_anim10: \"Sadness\",\n                        robotis_car_anim11: \"Pain\",\n                        robotis_car_anim12: \"Fainting\",\n                        robotis_car_anim13: \"Fear\",\n                        robotis_car_anim14: \"Yawn\",\n                        robotis_car_anim15: \"Sleepy\",\n                        robotis_car_anim16: \"Looking Right\",\n                        robotis_car_anim17: \"Looking Left\",\n                        robotis_car_anim18: \"Looking Forward\",\n                        robotis_car_anim19: \"Surprised\",\n\n\n                        robotis_flashing1: \"Flashing1\",\n                        robotis_flashing2: \"Flashing2\",\n                        robotis_flashing3: \"Flashing3\",\n                        robotis_flashing4: \"Flashing4\",\n                        robotis_flashing5: \"Flashing5\",\n                        robotis_flashing6: \"Flashing6\",\n                        robotis_flashing7: \"Flashing7\",\n                        robotis_flashing8: \"Flashing8\",\n                        robotis_flashing9: \"Flashing9\",\n\n\n\n                        robotis_moveF: 'Forward',\n                        robotis_moveB: 'Backward',\n                        robotis_moveL: 'LeftTurn',\n                        robotis_moveR: 'RightTurn',\n                        robotis_moveU: 'U-turn',\n                        robotis_moveL_in_place: 'Turn left in place',\n                        robotis_moveR_in_place: 'Trun right in place',\n                        robotis_moveU_in_place: 'U-turn in place',\n                        robotis_moveRG1: 'Stand',\n                        robotis_moveRG2: 'Sit',\n                        robotis_moveRG3: 'Struggle',\n                        robotis_moveRG4: 'RaiseFeet',\n                        robotis_fast: 'Fast',\n                        robotis_normal: 'Normal',\n                        robotis_slow: 'Slow',\n                        robotis_stop: 'Stop',\n                        robotis_roll: 'Left-right rotate angle (roll)',\n                        robotis_pitch: 'Forward-backward rotate angle (pitch)',\n                        robotis_stMotion1: 'Standard',\n                        robotis_stMotion2: 'Forward',\n                        robotis_stMotion3: 'TurnRight',\n                        robotis_stMotion4: 'TurnLeft',\n                        robotis_stMotion5: 'Backward',\n                        robotis_stMotion6: 'ToRight',\n                        robotis_stMotion7: 'ToLeft',\n                        robotis_stMotion8: 'TurnAroundRight',\n                        robotis_stMotion9: 'TurnAroundLeft',\n                        robotis_spMotion1: 'RightHandUp',\n                        robotis_spMotion2: 'RightHandDown',\n                        robotis_spMotion3: 'LeftHandUp',\n                        robotis_spMotion4: 'LeftHandDown',\n                        robotis_spMotion5: 'BothHandsUp',\n                        robotis_spMotion6: 'BothHandsDown',\n                        robotis_spMotion7: 'FallBackward',\n                        robotis_spMotion8: 'FallForward',\n                        robotis_spMotion9: 'StandForward',\n                        robotis_spMotion10: 'StandBackward',\n                        robotis_spMotion11: 'Defence',\n                        robotis_spMotion12: 'Offense1',\n                        robotis_spMotion13: 'Offense2',\n                        robotis_spMotion14: 'Offense3',\n                        robotis_spMotion15: 'Offense4',\n                        robotis_screen1: 'Sissor',\n                        robotis_screen2: 'Rock',\n                        robotis_screen3: 'Paper',\n                        robotis_clockwise: \"clockwise\",\n                        robotis_counterclockwise: \"counterclockwise\",\n                        robotis_up: \"up\",\n                        robotis_down: \"down\",\n                        robotis_screen_text_font_small: \"Small font\",\n                        robotis_screen_text_font_big: \"Big font\",\n                        robotis_stage_1: \"Stage 1\",\n                        robotis_stage_2: \"Stage 2\",\n                        robotis_stage_3: \"Stage 3\",\n                    },\n                },\n            };\n        }\n        getBlocks() {\n            return {\n                robotis_kkokdu_lite_dxl_set_mode: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_mode_joint, '3'],\n                                [Lang.Blocks.robotis_dxl_mode_wheel, '1'],\n                                [Lang.Blocks.robotis_dxl_mode_multi_turn, '4'],\n                            ],\n                            value: '3',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', null, null],\n                        type: 'robotis_kkokdu_lite_dxl_set_mode',\n                    },\n                    paramsKeyMap: {\n                        DXL_ID: 0,\n                        DXL_MODE: 1,\n                    },\n                    class: 'robotis_kkokdu_lite_dxl',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let dxl_id = script.getNumberValue('DXL_ID', script);\n                        let dxl_mode = script.getField('DXL_MODE', script);\n\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                        let data_address = 0;\n                        let data_length = 0;\n                        let data_value = 0;\n\n                        data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[0];\n                        data_length = Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[1];\n\n                        data_value = dxl_mode;\n\n                        let data_sendqueue = [\n                            [\n                                data_instruction,\n                                Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0],\n                                Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1],\n                                dxl_id,\n                                0,\n                            ],\n                            [data_instruction, data_address, data_length, dxl_id, data_value],\n                            [\n                                data_instruction,\n                                Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0],\n                                Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1],\n                                dxl_id,\n                                1,\n                            ],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite..set_dxl_mode(%1, %2)'],\n                    },\n                },\n                robotis_kkokdu_lite_dxl_set_position: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '50', '0', null],\n                        type: 'robotis_kkokdu_lite_dxl_set_position',\n                    },\n                    paramsKeyMap: {\n                        DXL_ID: 0,\n                        DXL_SPEED: 1,\n                        DXL_ANGLE: 2,\n                    },\n                    class: 'robotis_kkokdu_lite_dxl',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let dxl_id = script.getNumberValue('DXL_ID', script);\n                        let dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                        let dxl_angle = script.getNumberValue('DXL_ANGLE', script);\n\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                        let data_address = 0;\n                        let data_length = 0;\n                        let data_buf = [];\n\n                        data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0];\n                        data_length =\n                            Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] +\n                            Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1];\n\n                        if (dxl_speed < 0) {\n                            dxl_speed = 0;\n                        } else if (dxl_speed > 100) {\n                            dxl_speed = 100;\n                        }\n\n                        data_buf.push((dxl_speed * 10) % 256);\n                        data_buf.push(Math.floor((dxl_speed * 10) / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n\n                        if (dxl_angle < -179) {\n                            dxl_angle = -179;\n                        } else if (dxl_angle > 180) {\n                            dxl_angle = 180;\n                        }\n\n                        dxl_angle = 180 - dxl_angle;\n\n                        data_buf.push(Math.floor((dxl_angle * 4096) / 360) % 256);\n                        data_buf.push(Math.floor((dxl_angle * 4096) / 360 / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, dxl_id, data_buf],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite..set_dxl_position(%1, %2, %3)'],\n                    },\n                },\n                robotis_kkokdu_lite_dxl_set_rotate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_rotate_cw, '1'],\n                                [Lang.Blocks.robotis_dxl_rotate_ccw, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_move_rotate, '1'],\n                                [Lang.Blocks.robotis_dxl_move_stop, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '50', null, null, null],\n                        type: 'robotis_kkokdu_lite_dxl_set_rotate',\n                    },\n                    paramsKeyMap: {\n                        DXL_ID: 0,\n                        DXL_SPEED: 1,\n                        DXL_DIRECTION: 2,\n                        DXL_MOVE: 3,\n                    },\n                    class: 'robotis_kkokdu_lite_dxl',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let dxl_id = script.getNumberValue('DXL_ID', script);\n                        let dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                        let dxl_direction = script.getNumberValue('DXL_DIRECTION', script);\n                        let dxl_move = script.getNumberValue('DXL_MOVE', script);\n\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                        let data_address = 0;\n                        let data_length = 0;\n                        let data_value = 0;\n\n                        data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[0];\n                        data_length = Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[1];\n\n                        if (dxl_speed < 0) {\n                            dxl_speed = 0;\n                        } else if (dxl_speed > 100) {\n                            dxl_speed = 100;\n                        }\n\n                        data_value = dxl_speed * 10;\n\n                        // cw일 경우 음수처리\n                        if (dxl_direction == 1) {\n                            data_value = -data_value;\n                        }\n\n                        // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대\n                        if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) {\n                            data_value = -data_value;\n                        }\n\n                        data_value = data_value * dxl_move;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, dxl_id, data_value],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite..set_dxl_rotate(%1, %2, %3, %4)'],\n                    },\n                },\n                robotis_kkokdu_lite_dxl_set_multiturn_round: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_rotate_cw, '1'],\n                                [Lang.Blocks.robotis_dxl_rotate_ccw, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['1', '50', '1', null, null],\n                        type: 'robotis_kkokdu_lite_dxl_set_multiturn_round',\n                    },\n                    paramsKeyMap: {\n                        DXL_ID: 0,\n                        DXL_SPEED: 1,\n                        DXL_ROUND: 2,\n                        DXL_DIRECTION: 3,\n                    },\n                    class: 'robotis_kkokdu_lite_dxl',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let dxl_id = script.getNumberValue('DXL_ID', script);\n                        let dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                        let dxl_round = script.getNumberValue('DXL_ROUND', script);\n                        let dxl_direction = script.getNumberValue('DXL_DIRECTION', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address_1 = 0;\n                        let data_length_1 = 0;\n                        let data_value_1 = 0;\n                        let data_address_2 = 0;\n                        let data_length_2 = 0;\n                        let data_value_2 = 0;\n                        let data_address_3 = 0;\n                        let data_length_3 = 0;\n                        let data_value_3 = 0;\n\n                        let data_sendqueue = [];\n                        let result = undefined;\n\n                        if (dxl_id == 0 || dxl_speed == 0 || dxl_round == 0) {\n                            return;\n                        }\n\n                        data_address_1 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[0];\n                        data_length_1 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[1];\n\n                        data_address_2 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[0];\n                        data_length_2 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[1];\n\n                        if (dxl_speed < 0) {\n                            dxl_speed = 0;\n                        } else if (dxl_speed > 100) {\n                            dxl_speed = 100;\n                        }\n\n                        data_value_2 = dxl_speed * 10;\n\n                        data_address_3 =\n                            Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[0];\n                        data_length_3 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[1];\n\n                        if (dxl_round < 0) {\n                            dxl_round = 0;\n                        } else if (dxl_round > 100) {\n                            dxl_round = 100;\n                        }\n\n                        // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대\n                        if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) {\n                            dxl_round = -dxl_round;\n                        }\n\n                        data_value_3 = dxl_round * 4096;\n\n                        if (dxl_direction == 1) {\n                            data_value_3 = -data_value_3;\n                        }\n\n                        data_sendqueue = [\n                            [data_instruction, data_address_1, data_length_1, dxl_id],\n                            [data_instruction, data_address_2, data_length_2, data_value_2],\n                            [data_instruction, data_address_3, data_length_3, data_value_3],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.set_dxl_multiturn_round(%1, %2, %3, %4)'],\n                    },\n                },\n\n                robotis_kkokdu_lite_cm_ir_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '360'],\n                                ['2', '362'],\n                                ['3', '364'],\n                                ['4', '366'],\n                                ['5', '368'],\n                                ['6', '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_cm_ir_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        const scope = script.executor.scope;\n\n                        const data_default_address = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisKkokduLite.dataBuffer[data_default_address];\n                        if (result == undefined) {\n                            result = rb100_last_valid_value[data_default_address];\n                        } else {\n                            rb100_last_valid_value[data_default_address] = result;\n                        }\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return Math.round(result % 65536);\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.ir_value(%1)'],\n                    },\n                },\n                robotis_kkokdu_lite_cm_ir_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '360'],\n                                ['2', '362'],\n                                ['3', '364'],\n                                ['4', '366'],\n                                ['5', '368'],\n                                ['6', '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['>', '0'],\n                                ['<', '1'],\n                                ['=', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 200],\n                        type: 'robotis_kkokdu_lite_cm_ir_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                        COMPARE_OP: 1,\n                        COMPARE_VAL: 2,\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = script.getNumberValue('COMPARE_VAL');\n                        let compareOP = script.getNumberValue('COMPARE_OP');\n\n                        let result = Entry.RobotisKkokduLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        result = Math.round(result % 65536);\n\n                        switch (compareOP) {\n                            case 0:\n                                return result > compareValue;\n                            case 1:\n                                return result < compareValue;\n                            default:\n                                return false;\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.ir_compare(%1)'],\n                    },\n                },\n                robotis_kkokdu_lite_detectFrontObj: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n\n                        ],\n                        type: 'robotis_kkokdu_lite_detectFrontObj',\n                    },\n                    paramsKeyMap: {\n\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let ir_1 = 0;\n                        let ir_2 = 0;\n\n\n\n                        ir_1 = Entry.RobotisKkokduLite.dataBuffer[360];\n                        ir_2 = Entry.RobotisKkokduLite.dataBuffer[362];\n                        if (ir_1 == undefined) {\n                            ir_1 = 0;\n                        }\n                        if (ir_2 == undefined) {\n                            ir_2 = 0;\n                        }\n                        return ir_1 > 100 || ir_2 > 100;\n\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.detectFrontObj()'],\n                    },\n                },\n                robotis_kkokdu_lite_cm_btn_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_run, '45'],\n                                [Lang.Blocks.robotis_cancel, '42'],\n                            ],\n                            value: '45',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_push, '1'],\n                                [Lang.Blocks.robotis_notPush, '0'],\n\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_cm_btn_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = 1;\n\n                        let result = Entry.RobotisKkokduLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.btn_value(%1)'],\n                    },\n                },\n                robotis_kkokdu_lite_cm_joystick_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_center, '0'],\n                                ['←', '1'],\n                                ['→', '2'],\n                                ['↑', '3'],\n                                ['↓', '4'],\n                                ['↖', '5'],\n                                ['↗', '6'],\n                                ['↙', '7'],\n                                ['↘', '8'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_cm_joystick_value',\n                    },\n                    paramsKeyMap: {\n                        COMPARE_VAL: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 50;\n                        let compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                        let result = Entry.RobotisKkokduLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.joystick_value()'],\n                    },\n                },\n                robotis_kkokdu_lite_mic: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_mic',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    async func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 119;\n\n                        let result = Entry.RobotisKkokduLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.mic()'],\n                    },\n                },\n                robotis_kkokdu_lite_detectSound_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_right, '255'],\n                                [Lang.Blocks.robotis_center, '0'],\n                                [Lang.Blocks.robotis_left, '1'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_detectSound_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 5031;\n                        let compareValue = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisKkokduLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.detectSound_compare(%1)'],\n                    },\n                },\n                robotis_kkokdu_lite_imu: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['x', '78'], //72\n                                ['y', '80'], //74\n                                ['z', '82'], //76\n                            ],\n                            value: '78',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_acceleration, '0'], //72\n                                [Lang.Blocks.robotis_gyro, '6'], //74\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_kkokdu_lite_imu',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                        MODE: 1,\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address =\n                            script.getField('AXIS', script) - script.getField('MODE', script);\n\n                        let result = Entry.RobotisKkokduLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.imu()'],\n                    },\n                },\n                robotis_kkokdu_lite_roll_pitch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_roll, '70'], //72\n                                [Lang.Blocks.robotis_pitch, '88'], //74\n                            ],\n                            value: '70',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_roll_pitch',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_value',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('AXIS');\n\n                        let result = Entry.RobotisKkokduLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.roll_pitch(%1)'],\n                    },\n                },\n\n\n                robotis_kkokdu_lite_buzzer_index: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.General.note_c + '', '1'],\n                                [Lang.General.note_c + '#', '2'],\n                                [Lang.General.note_d + '', '3'],\n                                [Lang.General.note_d + '#', '4'],\n                                [Lang.General.note_e + '', '5'],\n                                [Lang.General.note_f + '', '6'],\n                                [Lang.General.note_f + '#', '7'],\n                                [Lang.General.note_g + '', '8'],\n                                [Lang.General.note_g + '#', '9'],\n                                [Lang.General.note_a + '', '10'],\n                                [Lang.General.note_a + '#', '11'],\n                                [Lang.General.note_b + '', '12'],\n                            ],\n                            value: '11',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_play, '1'],\n                                [Lang.Blocks.robotis_rest, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 1, null, null],\n                        type: 'robotis_kkokdu_lite_buzzer_index',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_INDEX: 0,\n                        CM_BUZZER_OCTAV: 1,\n                        CM_BUZZER_DELAY: 2,\n                        CM_BUZZER_PLAY: 3\n                    },\n                    class: 'robotis_kkokdu_lite_sound',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                        let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                        let cmBuzzerTime = script.getNumberValue('CM_BUZZER_DELAY', script);\n                        let cmBuzzerPlay = script.getNumberValue('CM_BUZZER_PLAY', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 0;\n                        let data_value = 0;\n                        let interval = 0;\n                        let data_buf = [];\n\n                        cmBuzzerTime = Math.round(cmBuzzerTime * 1000);\n\n                        data_address = 740;\n                        // data_value_1 = cmBuzzerTime * 10;\n                        // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n\n                        if (cmBuzzerTime < 0) {\n                            cmBuzzerTime = 0;\n                        }\n                        if (cmBuzzerTime > 50000) {\n                            cmBuzzerTime = 50000;\n                        }\n\n                        data_buf.push(cmBuzzerTime % 256);\n                        data_buf.push(Math.floor(cmBuzzerTime / 256));\n\n                        data_value = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n                        data_buf.push(Math.floor(data_value));\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [[data_instruction, data_address, 3, data_buf]];\n\n                        if (cmBuzzerPlay == '2') {\n                            data_sendqueue = [];\n                        }\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.buzzer_index(%1, %2, %3)'],\n                    },\n                },\n\n\n                robotis_kkokdu_lite_rgee_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_face01, '2817'],\n                                [Lang.Blocks.robotis_face02, '2818'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face03, '2819'],\n                                [Lang.Blocks.robotis_face04, '2820'],\n                                [Lang.Blocks.robotis_face05, '2821'],\n\n                                [Lang.Blocks.robotis_face06, '2822'],\n                                [Lang.Blocks.robotis_face07, '2823'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face08, '2824'],\n                                [Lang.Blocks.robotis_face09, '2825'],\n                                [Lang.Blocks.robotis_face10, '2826'],\n\n                                [Lang.Blocks.robotis_face11, '2827'],\n                                [Lang.Blocks.robotis_face12, '2828'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face13, '2829'],\n\n                                [Lang.Blocks.robotis_face14, '2830'],\n                                [Lang.Blocks.robotis_face15, '2831'],\n                                [Lang.Blocks.robotis_face16, '2832'],\n                                [Lang.Blocks.robotis_face17, '2833'],\n                                [Lang.Blocks.robotis_face18, '2834'],\n\n                                [Lang.Blocks.robotis_face19, '2835'],\n                                [Lang.Blocks.robotis_face20, '2836'],\n                                [Lang.Blocks.robotis_face21, '2837'],\n                                [Lang.Blocks.robotis_face22, '2838'],\n                                [Lang.Blocks.robotis_face23, '2839'],\n                            ],\n                            value: '2817',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_kkokdu_lite_rgee_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.rgee_screen(%1)'] },\n                },\n\n                robotis_kkokdu_lite_rgee_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_face01, '30748'],\n                                [Lang.Blocks.robotis_face02, '30749'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face03, '30750'],\n                                [Lang.Blocks.robotis_face04, '30756'],\n                                [Lang.Blocks.robotis_face05, '30754'],\n\n                                [Lang.Blocks.robotis_face06, '30741'],\n                                [Lang.Blocks.robotis_face07, '30747'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face08, '30738'],\n                                [Lang.Blocks.robotis_face09, '30740'],\n                                [Lang.Blocks.robotis_face10, '30739'],\n\n                                [Lang.Blocks.robotis_face11, '30733'],\n                                [Lang.Blocks.robotis_face12, '30734'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face13, '30732'],\n\n                                [Lang.Blocks.robotis_face14, '30757'],\n                                [Lang.Blocks.robotis_face15, '30736'],\n                                [Lang.Blocks.robotis_face16, '30731'],\n                                [Lang.Blocks.robotis_face17, '30742'],\n                                [Lang.Blocks.robotis_face18, '30743'],\n\n                                [Lang.Blocks.robotis_face19, '30744'],\n                                [Lang.Blocks.robotis_face20, '30751'],\n                                [Lang.Blocks.robotis_face21, '30752'],\n                                [Lang.Blocks.robotis_face22, '30755'],\n                                [Lang.Blocks.robotis_face23, '30758'],\n                            ],\n                            value: '30748',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_kkokdu_lite_rgee_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.rgee_animation_screen(%1)'] },\n                },\n\n\n\n\n                robotis_kkokdu_lite_icon: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_screen1, '11545'],\n                                [Lang.Blocks.robotis_screen2, '11546'],\n                                [Lang.Blocks.robotis_screen3, '11547'],\n                                ['0', '11283'],\n                                ['1', '11284'],\n                                ['2', '11285'],\n                                ['3', '11286'],\n                                ['4', '11287'],\n                                ['5', '11288'],\n                                ['6', '11289'],\n                                ['7', '11290'],\n                                ['8', '11291'],\n                                ['9', '11292'],\n                                ['10', '11293'],\n                            ],\n                            value: '11545',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_kkokdu_lite_icon',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.icon_screen(%1,%2,%3,%4)'],\n                    },\n                },\n\n\n                robotis_kkokdu_lite_LCDBright: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [10],\n                        type: 'robotis_kkokdu_lite_LCDBright',\n                    },\n                    paramsKeyMap: {\n                        BRIGHT: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let bright = script.getNumberValue('BRIGHT', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 180;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        bright = Math.min(Math.max(bright, 0), 100);\n\n                        data_value = bright;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.LCDBright(%1)'],\n                    },\n                },\n                robotis_kkokdu_lite_LCDColor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '224',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_LCDColor',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let color = script.getNumberValue('COLOR', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = color;\n                        bg_color = color;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.LCDColor(%1)'],\n                    },\n                },\n\n                robotis_kkokdu_lite_led_brightness: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '2'],\n                                [Lang.Blocks.robotis_both, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: [100]\n                            }\n                        ],\n                        type: 'robotis_kkokdu_lite_led_brightness',\n                    },\n                    paramsKeyMap: {\n                        RB_LED: 0,\n                        BRIGHT: 1,\n                    },\n                    class: 'robotis_kkokdu_lite_led',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmLed = script.getNumberValue('RB_LED', script);\n                        let bright = script.getNumberValue('BRIGHT', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 0;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        if (bright < 0) {\n                            bright = 0;\n                        } else if (bright > 100) {\n                            bright = 100\n                        }\n                        data_value = 100 + bright;\n\n                        if (cmLed == 1) {\n                            data_address = 40;\n                            data_length = 1;\n                        } else if (cmLed == 2) {\n                            data_address = 41;\n                            data_length = 1;\n                        } else if (cmLed == 3) {\n                            data_address = 40;\n                            data_length = 2;\n                            data_value = data_value * 257\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.led_brightness(%1, %2)'] },\n                },\n                robotis_kkokdu_lite_led_pattern: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_flashing1, '11'],\n                                [Lang.Blocks.robotis_flashing2, '12'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing3, '13'],\n\n                                [Lang.Blocks.robotis_flashing4, '21'],\n                                [Lang.Blocks.robotis_flashing5, '22'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing6, '23'],\n\n                                [Lang.Blocks.robotis_flashing7, '31'],\n                                [Lang.Blocks.robotis_flashing8, '32'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing9, '33'],\n\n                            ],\n                            value: '11',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_common_on, '1'],\n                                [Lang.Blocks.robotis_common_off, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'robotis_kkokdu_lite_led_pattern',\n                    },\n                    paramsKeyMap: {\n                        RB_LED: 0,\n                        VALUE: 1,\n                    },\n                    class: 'robotis_kkokdu_lite_led',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmLed = script.getNumberValue('RB_LED', script);\n                        let value = script.getNumberValue('VALUE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 40;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = value * cmLed;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.led_pattern(%1, %2)'] },\n                },\n\n\n\n                robotis_kkokdu_lite_Hello: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_korean1, '0'],\n                                [Lang.Blocks.robotis_korean2, '1'],\n                                [Lang.Blocks.robotis_korean3, '2'],\n                                [Lang.Blocks.robotis_korean4, '3'],\n                                [Lang.Blocks.robotis_korean5, '4'],\n                                [Lang.Blocks.robotis_korean6, '5'],\n                                [Lang.Blocks.robotis_korean7, '6'],\n                                [Lang.Blocks.robotis_korean8, '7'],\n                                [Lang.Blocks.robotis_korean9, '8'],\n                                [Lang.Blocks.robotis_korean10, '9'],\n                                [Lang.Blocks.robotis_korean11, '10'],\n                                [Lang.Blocks.robotis_korean12, '11'],\n                                [Lang.Blocks.robotis_korean13, '12'],\n                                [Lang.Blocks.robotis_korean14, '13'],\n                                [Lang.Blocks.robotis_korean15, '14'],\n                                [Lang.Blocks.robotis_korean16, '15'],\n                                [Lang.Blocks.robotis_korean17, '16'],\n                                [Lang.Blocks.robotis_korean18, '17'],\n                                [Lang.Blocks.robotis_korean19, '18'],\n                                [Lang.Blocks.robotis_korean20, '19'],\n                                [Lang.Blocks.robotis_korean21, '20'],\n                                [Lang.Blocks.robotis_korean22, '21'],\n                                [Lang.Blocks.robotis_korean23, '22'],\n                                [Lang.Blocks.robotis_korean24, '23'],\n                                [Lang.Blocks.robotis_korean25, '24'],\n                                [Lang.Blocks.robotis_korean26, '25'],\n                                [Lang.Blocks.robotis_korean27, '26'],\n                                [Lang.Blocks.robotis_korean28, '27'],\n                                [Lang.Blocks.robotis_korean29, '28'],\n                                [Lang.Blocks.robotis_korean30, '29'],\n                                [Lang.Blocks.robotis_korean31, '30'],\n                                [Lang.Blocks.robotis_korean32, '31'],\n                                [Lang.Blocks.robotis_korean33, '32'],\n                                [Lang.Blocks.robotis_korean34, '33'],\n                                [Lang.Blocks.robotis_korean35, '34'],\n                                [Lang.Blocks.robotis_korean36, '35'],\n                                [Lang.Blocks.robotis_korean37, '36'],\n                                [Lang.Blocks.robotis_korean38, '37'],\n                                [Lang.Blocks.robotis_korean39, '38'],\n                                [Lang.Blocks.robotis_korean40, '39'],\n                                [Lang.Blocks.robotis_korean41, '40'],\n                                [Lang.Blocks.robotis_korean42, '41'],\n                                [Lang.Blocks.robotis_korean43, '42'],\n                                [Lang.Blocks.robotis_korean44, '43'],\n                                [Lang.Blocks.robotis_korean45, '44'],\n                                [Lang.Blocks.robotis_korean46, '45'],\n                                [Lang.Blocks.robotis_korean47, '46'],\n                                [Lang.Blocks.robotis_korean48, '47'],\n                                [Lang.Blocks.robotis_korean49, '48'],\n                                [Lang.Blocks.robotis_korean50, '49'],\n                                [Lang.Blocks.robotis_korean51, '50'],\n                                [Lang.Blocks.robotis_korean52, '51'],\n                                [Lang.Blocks.robotis_korean53, '52'],\n                                [Lang.Blocks.robotis_korean54, '53'],\n                                [Lang.Blocks.robotis_korean55, '54'],\n                                [Lang.Blocks.robotis_korean56, '55'],\n                                [Lang.Blocks.robotis_korean57, '56'],\n                                [Lang.Blocks.robotis_korean58, '57'],\n                                [Lang.Blocks.robotis_korean59, '58'],\n                                [Lang.Blocks.robotis_korean60, '59'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_Hello',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_sound',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = 25601 + Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n\n                        if (cmHello == '38' || cmHello == '55') {\n                            extraTime = 2000;\n                        }\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            2000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.speak(%1)'],\n                    },\n                },\n                robotis_kkokdu_lite_effectSound: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dog, '0'],\n                                [Lang.Blocks.robotis_frog, '1'],\n                                [Lang.Blocks.robotis_cat, '2'],\n                                [Lang.Blocks.robotis_chicken, '7'],\n                                [Lang.Blocks.robotis_tiger, '19'],\n                                [Lang.Blocks.robotis_mouse, '17'],\n\n                                [Lang.Blocks.robotis_ambul, '773'],\n                                [Lang.Blocks.robotis_Horn, '781'],\n                                [Lang.Blocks.robotis_siren, '774'],\n                                [Lang.Blocks.robotis_whistle, '274'],\n                                [Lang.Blocks.robotis_gun, '775'],\n                                [Lang.Blocks.robotis_clap, '260'],\n\n                                [Lang.Blocks.robotis_melody1, '786'],\n                                [Lang.Blocks.robotis_melody2, '787'],\n                                [Lang.Blocks.robotis_melody3, '788'],\n                                [Lang.Blocks.robotis_melody4, '789'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_effectSound',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_sound',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n                        if (\n                            cmHello == '272' ||\n                            cmHello == '786' ||\n                            cmHello == '787' ||\n                            cmHello == '788' ||\n                            cmHello == '789'\n                        ) {\n                            //오리\n                            extraTime = 0;\n                            if (cmHello == '788' || cmHello == '789') {\n                                extraTime += 500;\n                            }\n                        }\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            3000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.effect_sound(%1)'],\n                    },\n                },\n                robotis_kkokdu_lite_record: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_record',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_sound',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 115;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.record(%1)'],\n                    },\n                },\n                robotis_kkokdu_lite_playRecord: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_kkokdu_lite_playRecord',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_sound',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 116;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.playRecord(%1)'],\n                    },\n                },\n\n\n\n\n                robotis_kkokdu_lite_rla_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '3329'],\n                                [Lang.Blocks.robotis_car_anim02, '3330'],\n                                [Lang.Blocks.robotis_car_anim03, '3331'],\n                                [Lang.Blocks.robotis_car_anim04, '3332'],\n                                [Lang.Blocks.robotis_car_anim05, '3333'],\n\n                                [Lang.Blocks.robotis_car_anim06, '3334'],\n                                [Lang.Blocks.robotis_car_anim07, '3335'],\n                                [Lang.Blocks.robotis_car_anim08, '3336'],\n                                [Lang.Blocks.robotis_car_anim09, '3337'],\n                                [Lang.Blocks.robotis_car_anim10, '3338'],\n\n                                [Lang.Blocks.robotis_car_anim11, '3339'],\n                                [Lang.Blocks.robotis_car_anim12, '3340'],\n                                [Lang.Blocks.robotis_car_anim13, '3341'],\n                                [Lang.Blocks.robotis_car_anim14, '3342'],\n                                [Lang.Blocks.robotis_car_anim15, '3343'],\n\n                                [Lang.Blocks.robotis_car_anim16, '3344'],\n                                [Lang.Blocks.robotis_car_anim17, '3345'],\n                                [Lang.Blocks.robotis_car_anim18, '3346'],\n                                [Lang.Blocks.robotis_car_anim19, '3347'],\n                            ],\n                            value: '3329',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_kkokdu_lite_rla_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.rla_screen(%1)'] },\n                },\n\n                robotis_kkokdu_lite_rla_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '30978'],\n                                [Lang.Blocks.robotis_car_anim02, '30981'],\n                                [Lang.Blocks.robotis_car_anim03, '30982'],\n                                [Lang.Blocks.robotis_car_anim04, '30983'],\n                                [Lang.Blocks.robotis_car_anim05, '30984'],\n\n                                [Lang.Blocks.robotis_car_anim06, '30985'],\n                                [Lang.Blocks.robotis_car_anim07, '30986'],\n                                [Lang.Blocks.robotis_car_anim08, '30987'],\n                                [Lang.Blocks.robotis_car_anim09, '30988'],\n                                [Lang.Blocks.robotis_car_anim10, '30989'],\n\n                                [Lang.Blocks.robotis_car_anim11, '30990'],\n                                [Lang.Blocks.robotis_car_anim12, '30991'],\n                                [Lang.Blocks.robotis_car_anim13, '30992'],\n                                [Lang.Blocks.robotis_car_anim14, '30993'],\n                                [Lang.Blocks.robotis_car_anim15, '30994'],\n\n                                [Lang.Blocks.robotis_car_anim16, '30995'],\n                                [Lang.Blocks.robotis_car_anim17, '30996'],\n                                [Lang.Blocks.robotis_car_anim18, '30997'],\n                                [Lang.Blocks.robotis_car_anim19, '30998'],\n                            ],\n                            value: '30978',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_kkokdu_lite_rla_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.rla_animation_screen(%1)'] },\n                },\n\n                robotis_kkokdu_lite_kkokdu_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '3585'],\n                                [Lang.Blocks.robotis_car_anim02, '3586'],\n                                [Lang.Blocks.robotis_car_anim03, '3587'],\n                                [Lang.Blocks.robotis_car_anim04, '3588'],\n                                [Lang.Blocks.robotis_car_anim05, '3589'],\n\n                                [Lang.Blocks.robotis_car_anim06, '3590'],\n                                [Lang.Blocks.robotis_car_anim07, '3591'],\n                                [Lang.Blocks.robotis_car_anim08, '3592'],\n                                [Lang.Blocks.robotis_car_anim09, '3593'],\n                                [Lang.Blocks.robotis_car_anim10, '3594'],\n\n                                [Lang.Blocks.robotis_car_anim11, '3595'],\n                                [Lang.Blocks.robotis_car_anim12, '3596'],\n                                [Lang.Blocks.robotis_car_anim13, '3597'],\n                                [Lang.Blocks.robotis_car_anim14, '3598'],\n                                [Lang.Blocks.robotis_car_anim15, '3599'],\n\n                                [Lang.Blocks.robotis_car_anim16, '3600'],\n                                [Lang.Blocks.robotis_car_anim17, '3601'],\n                                [Lang.Blocks.robotis_car_anim18, '3602'],\n                                [Lang.Blocks.robotis_car_anim19, '3603'],\n                            ],\n                            value: '3585',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_kkokdu_lite_kkokdu_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.kkokdu_screen(%1)'] },\n                },\n\n                robotis_kkokdu_lite_kkokdu_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '31234'],\n                                [Lang.Blocks.robotis_car_anim02, '31237'],\n                                [Lang.Blocks.robotis_car_anim03, '31238'],\n                                [Lang.Blocks.robotis_car_anim04, '31239'],\n                                [Lang.Blocks.robotis_car_anim05, '31240'],\n\n                                [Lang.Blocks.robotis_car_anim06, '31241'],\n                                [Lang.Blocks.robotis_car_anim07, '31242'],\n                                [Lang.Blocks.robotis_car_anim08, '31243'],\n                                [Lang.Blocks.robotis_car_anim09, '31244'],\n                                [Lang.Blocks.robotis_car_anim10, '31245'],\n\n                                [Lang.Blocks.robotis_car_anim11, '31246'],\n                                [Lang.Blocks.robotis_car_anim12, '31247'],\n                                [Lang.Blocks.robotis_car_anim13, '31248'],\n                                [Lang.Blocks.robotis_car_anim14, '31249'],\n                                [Lang.Blocks.robotis_car_anim15, '31250'],\n\n                                [Lang.Blocks.robotis_car_anim16, '31251'],\n                                [Lang.Blocks.robotis_car_anim17, '31252'],\n                                [Lang.Blocks.robotis_car_anim18, '31253'],\n                                [Lang.Blocks.robotis_car_anim19, '31254'],\n                            ],\n                            value: '31234',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_kkokdu_lite_kkokdu_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.kkokdu_animation_screen(%1)'] },\n                },\n                robotis_kkokdu_lite_text_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_screen_text_font_small, '0'],\n                                [Lang.Blocks.robotis_screen_text_font_big, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            ' ',\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'robotis_kkokdu_lite_text_screen',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        X: 1,\n                        Y: 2,\n                        FONT: 3,\n                        COLOR: 4,\n                    },\n                    class: 'robotis_kkokdu_lite_lcd',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let text = script.getStringValue('TEXT', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let font = script.getNumberValue('FONT', script);\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 900;\n                        let data_length = 2;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        let encoder = new TextEncoder('utf-8');\n                        let byteArray = encoder.encode(text);\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(font);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(color);\n                        data_buf.push(byteArray.length);\n                        for (i = 0; i < byteArray.length; i++) {\n                            data_buf.push(byteArray[i]);\n                        }\n\n                        data_length = 9 + byteArray.length;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['KkokduLite.text_screen(%1,%2,%3,%4,%5)'],\n                    },\n                },\n                robotis_kkokdu_lite_motion: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_stMotion1, '1'],\n                                [Lang.Blocks.robotis_stMotion2, '25'],\n                                [Lang.Blocks.robotis_stMotion3, '46'],\n                                [Lang.Blocks.robotis_stMotion4, '47'],\n                                [Lang.Blocks.robotis_stMotion5, '37'], //Lang.Blocks.robotis_common_green_color\n                                [Lang.Blocks.robotis_stMotion6, '38'],\n                                [Lang.Blocks.robotis_stMotion7, '39'],\n                                [Lang.Blocks.robotis_stMotion8, '41'],\n                                [Lang.Blocks.robotis_stMotion9, '40'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                        ],\n                        type: 'robotis_kkokdu_lite_motion',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_move',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func: function (sprite, script) {\n                        // instruction / address / length / value / default length\n                        var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                        var data_address = 0;\n                        var data_length = 0;\n                        var data_value = 0;\n                        var extraTime = 0;\n\n                        data_address =\n                            Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[0];\n                        data_length = Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[1];\n                        data_value = script.getField('VALUE', script);\n\n\n                        console.log(\"motion send\");\n                        var data_sendqueue = [\n                            [data_instruction, data_address, data_length, 0],\n                            [data_instruction, data_address, data_length, data_value]\n                        ];\n\n                        switch (data_value) {\n                            case '1':\n                                extraTime = 100;\n                                break;\n                            case '25':\n                            case '46':\n                            case '47':\n                                extraTime = 3000;\n                                break;\n                            case '37':\n                                extraTime = 3000;\n                                break;\n                            case '38':\n                                extraTime = 1000;\n                                break;\n                            case '39':\n                                extraTime = 1000;\n                                break;\n                            case '40':\n                                extraTime = 2300;\n                                break;\n                            case '41':\n                                extraTime = 2300;\n                                break;\n\n\n                        }\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + extraTime + 300\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.run_motion(%1)'] },\n                },\n                robotis_kkokdu_lite_motion_other: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_spMotion1, '26'],\n                                [Lang.Blocks.robotis_spMotion2, '27'],\n                                [Lang.Blocks.robotis_spMotion3, '28'],\n                                [Lang.Blocks.robotis_spMotion4, '29'],\n                                [Lang.Blocks.robotis_spMotion5, '30'], //Lang.Blocks.robotis_common_green_color\n                                [Lang.Blocks.robotis_spMotion6, '31'],\n                                [Lang.Blocks.robotis_spMotion7, '32'],\n                                [Lang.Blocks.robotis_spMotion8, '33'],\n                                [Lang.Blocks.robotis_spMotion9, '48'],\n                                [Lang.Blocks.robotis_spMotion10, '35'],\n                                [Lang.Blocks.robotis_spMotion11, '36'],\n                                [Lang.Blocks.robotis_spMotion12, '42'],\n                                [Lang.Blocks.robotis_spMotion13, '43'],\n                                [Lang.Blocks.robotis_spMotion14, '44'],\n                                [Lang.Blocks.robotis_spMotion15, '45'],\n                            ],\n                            value: '26',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                        ],\n                        type: 'robotis_kkokdu_lite_motion_other',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_move',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func: function (sprite, script) {\n                        // instruction / address / length / value / default length\n                        var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                        var data_address = 0;\n                        var data_length = 0;\n                        var data_value = 0;\n                        var extraTime = 0;\n\n                        data_address =\n                            Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[0];\n                        data_length = Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[1];\n                        data_value = script.getField('VALUE', script);\n\n\n                        console.log(\"motion send\");\n                        var data_sendqueue = [\n                            [data_instruction, data_address, data_length, 0],\n                            [data_instruction, data_address, data_length, data_value]\n                        ];\n\n                        switch (data_value) {\n                            case '26':\n                                extraTime = 800;\n                                break;\n                            case '27':\n                                extraTime = 1000;\n                                break;\n                            case '28':\n                                extraTime = 800;\n                                break;\n                            case '29':\n                                extraTime = 1000;\n                                break;\n                            case '30':\n                                extraTime = 800;\n                                break;\n                            case '31':\n                                extraTime = 1000;\n                                break;\n                            case '32':\n                                extraTime = 5800;\n                                break;\n                            case '33':\n                                extraTime = 3800;\n                                break;\n                            case '34':\n                                extraTime = 8400;\n                                break;\n                            case '35':\n                                extraTime = 4000;\n                                break;\n                            case '36':\n                                extraTime = 300;\n                                break;\n                            case '42':\n                                extraTime = 600;\n                                break;\n                            case '43':\n                                extraTime = 800;\n                                break;\n                            case '44':\n                                extraTime = 800;\n                                break;\n                            case '45':\n                                extraTime = 1000;\n                                break;\n                            case '48':\n                                extraTime = 12400;\n                                break;\n                        }\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + extraTime + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.run_motion_other(%1)'] },\n                },\n\n\n                robotis_kkokdu_lite_motion_custom: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['1'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_kkokdu_lite_motion_custom',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_kkokdu_lite_move',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func: function (sprite, script) {\n                        // instruction / address / length / value / default length\n                        var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                        var data_address = 0;\n                        var data_length = 0;\n                        var data_value = 0;\n                        var extraTime = 0;\n\n                        data_address =\n                            Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[0];\n                        data_length = Entry.Robotis_rb.CONTROL_TABLE.CM_MOTION[1];\n                        data_value = script.getNumberValue('VALUE', script);\n\n                        var data_sendqueue = [\n                            [data_instruction, data_address, data_length, 0],\n                            [data_instruction, data_address, data_length, data_value]\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.run_motion_custom(%1)'] },\n                },\n                robotis_kkokdu_lite_dxl_control: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['1'],\n                            },\n                        ],\n                        type: 'robotis_kkokdu_lite_dxl_control',\n                    },\n\n                    paramsKeyMap: {\n                        ANGLE1: 0,\n                        ANGLE2: 1,\n                        ANGLE3: 2,\n                        ANGLE4: 3,\n\n                        ANGLE5: 4,\n                        ANGLE6: 5,\n                        ANGLE7: 6,\n                        ANGLE8: 7,\n                        TIME: 8\n                    },\n                    class: 'robotis_kkokdu_lite_move',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(entity, script) {\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE;\n                        let data_address = 19;\n                        let data_length = 1;\n                        let data_value = 1;\n                        let move_time = script.getNumberValue('TIME', script) * 1000;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_DXL_REGWRITE, 64, 1, 1, [1]],\n                            [INST_DXL_REGWRITE, 64, 1, 2, [1]],\n                            [INST_DXL_REGWRITE, 64, 1, 3, [1]],\n                            [INST_DXL_REGWRITE, 64, 1, 4, [1]],\n                            [INST_DXL_REGWRITE, 64, 1, 5, [1]],\n                            [INST_DXL_REGWRITE, 64, 1, 6, [1]],\n                            [INST_DXL_REGWRITE, 64, 1, 7, [1]],\n                            [INST_DXL_REGWRITE, 64, 1, 8, [1]],\n                            [INST_DXL_ACTION, 0, 0, 0xFE],\n                        ]\n\n                        let keyWord = 'ANGLE';\n                        for (let i = 1; i < 9; i++) {\n                            keyWord = 'ANGLE' + i;\n                            let value = script.getNumberValue('ANGLE' + i, script);\n\n                            let engValue = 2048;\n                            engValue = Math.floor(2048 - Math.round(value * 4096) / 360);\n\n                            let velocity = 0;\n\n                            let data_buf = [];\n\n                            if (move_time == 0) {\n                                velocity = 0;\n                            } else {\n                                velocity = Math.round(Math.floor(60 * Math.abs(value - Entry.RobotisKkokduLite.dxlPositions[i]) * 1000 / 4096 / move_time) / 0.229);\n                            }\n\n                            Entry.RobotisKkokduLite.dxlPositions[i] = value;\n\n                            data_buf.push(Entry.RobotisKkokduLite.getLowByte(Entry.RobotisKkokduLite.getLowWord(velocity)));\n                            data_buf.push(Entry.RobotisKkokduLite.getHighByte(Entry.RobotisKkokduLite.getLowWord(velocity)));\n                            data_buf.push(Entry.RobotisKkokduLite.getLowByte(Entry.RobotisKkokduLite.getHighWord(velocity)));\n                            data_buf.push(Entry.RobotisKkokduLite.getHighByte(Entry.RobotisKkokduLite.getHighWord(velocity)));\n                            data_buf.push(Entry.RobotisKkokduLite.getLowByte(Entry.RobotisKkokduLite.getLowWord(engValue)));\n                            data_buf.push(Entry.RobotisKkokduLite.getHighByte(Entry.RobotisKkokduLite.getLowWord(engValue)));\n                            data_buf.push(Entry.RobotisKkokduLite.getLowByte(Entry.RobotisKkokduLite.getHighWord(engValue)));\n                            data_buf.push(Entry.RobotisKkokduLite.getHighByte(Entry.RobotisKkokduLite.getHighWord(engValue)));\n\n                            data_sendqueue.push([INST_DXL_REGWRITE, 112, 8, i, data_buf]);\n                        }\n\n                        data_sendqueue.push([INST_DXL_ACTION, 0, 0, 0xFE]);\n\n                        for (let j = 1; j < 9; j++) {\n                            data_sendqueue.push([INST_DXL_REGWRITE, 112, 4, j, [0]]);\n                        }\n                        data_sendqueue.push([INST_DXL_ACTION, 0, 0, 0xFE]);\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            move_time + DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.dxl_control(%1, %2, %3, %4, %5, %6, %7, %8, %9)'] },\n                },\n\n                robotis_kkokdu_lite_dxl_position_time: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [\"1\", '1'],\n                                [\"2\", '2'],\n                                [\"3\", '3'],\n                                [\"4\", '4'],\n                                [\"5\", '5'],\n                                [\"6\", '6'],\n                                [\"7\", '7'],\n                                [\"8\", '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            1,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['1'],\n                            },\n                        ],\n                        type: 'robotis_kkokdu_lite_dxl_position_time',\n                    },\n\n                    paramsKeyMap: {\n                        DXLNUM: 0,\n                        ANGLE: 1,\n                        TIME: 2,\n                    },\n                    class: 'robotis_kkokdu_lite_move',\n                    isNotFor: ['RobotisKkokduLite'],\n                    func(entity, script) {\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                        let data_address = 0;\n                        let data_length = 0;\n\n                        data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0];\n                        data_length =\n                            Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] +\n                            Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1];\n\n                        let dxlID = script.getField('DXLNUM', script);\n                        let angle = script.getNumberValue('ANGLE', script);\n                        let time = script.getNumberValue('TIME', script) * 1000;\n                        let data_buf = [];\n\n                        let engValue = 2048;\n                        engValue = Math.floor(2048 - Math.round(angle * 4096) / 360);\n                        let velocity = 0;\n\n                        if (time == 0) {\n                            velocity = 0;\n                        } else {\n                            velocity = Math.round(\n                                Math.floor(\n                                    (60 *\n                                        Math.abs(\n                                            engValue - Entry.RobotisKkokduLite.dxlPositions[dxlID]\n                                        ) *\n                                        1000) /\n                                        4096 /\n                                        time\n                                ) / 0.229\n                            );\n                        }\n\n                        data_buf.push(velocity % 256);\n                        data_buf.push(Math.floor(velocity / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n\n                        data_buf.push(engValue % 256);\n                        data_buf.push(Math.floor(engValue / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, dxlID, data_buf],\n                        ];\n\n                        return Entry.RobotisKkokduLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            time + DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['KkokduLite.dxl_each_control(%1, %2, %3)'] },\n                },\n\n                //////////////////////////////////////////////////////////////////////////////////////////////////////////\n            };\n        }\n\n        requestLocalData() {\n            let packets = [];\n            while (this.robotisBuffer.length > 0) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n                let packet = null;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        packet = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        packet = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                    case INST_DXL_REGWRITE:\n                        id = value;\n                        packet = this.registWritePacket(id, address, length, dataBuffer);\n                        break;\n                    case INST_DXL_ACTION:\n                        id = value;\n                        packet = this.actionPacket(id);\n                        break;\n                }\n\n                if (packet !== null && Array.isArray(packet)) {\n                    packets.push(...packet);\n                }\n            }\n            return packets;\n        }\n\n        handleLocalData(data) {\n            let stuffLength = 0;\n            //console.log(`length: ${data.length}`);\n            for (let i = 0; i < data.length; i++) {\n                //this.receiveBuffer.push(data[i]);\n                const dataIn = data[i];\n\n                switch (this.packetReceiveState) {\n                    case PACKET_STATE_IDLE:\n                        if (this.headerCount >= 2) {\n                            rxPacket.header[2] = dataIn;\n\n                            if (\n                                rxPacket.header[0] == 0xff &&\n                                rxPacket.header[1] == 0xff &&\n                                rxPacket.header[2] == 0xfd\n                            ) {\n                                this.headerCount = 0;\n                                this.packetReceiveState = PACKET_STATE_RESERVED;\n                            } else {\n                                rxPacket.header[0] = rxPacket.header[1];\n                                rxPacket.header[1] = rxPacket.header[2];\n                                rxPacket.header[2] = 0;\n                            }\n                        } else {\n                            rxPacket.header[this.headerCount] = dataIn;\n                            this.headerCount++;\n                        }\n                        break;\n\n                    case PACKET_STATE_RESERVED:\n                        if (dataIn == 0xfd) {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        } else {\n                            rxPacket.reserved = dataIn;\n                            this.packetReceiveState = PACKET_STATE_ID;\n                        }\n                        break;\n\n                    case PACKET_STATE_ID:\n                        rxPacket.id = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_L;\n                        break;\n\n                    case PACKET_STATE_LENGTH_L:\n                        rxPacket.packetLength = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_H;\n                        break;\n\n                    case PACKET_STATE_LENGTH_H:\n                        rxPacket.packetLength |= dataIn << 8;\n                        if (rxPacket.packetLength < 1000) {\n                            this.packetReceiveState = PACKET_STATE_DATA;\n                        } else {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        }\n                        rxPacket.index = 0;\n                        break;\n\n                    case PACKET_STATE_DATA:\n                        rxPacket.data[rxPacket.index] = dataIn;\n                        rxPacket.index++;\n\n                        if (rxPacket.index >= rxPacket.packetLength - 2) {\n                            this.packetReceiveState = PACKET_STATE_CRC_L;\n                        }\n                        break;\n\n                    case PACKET_STATE_CRC_L:\n                        rxPacket.crcReceived = dataIn;\n                        this.packetReceiveState = PACKET_STATE_CRC_H;\n                        break;\n\n                    case PACKET_STATE_CRC_H:\n                        rxPacket.crcReceived |= dataIn << 8;\n\n                        stuffLength = this.removeStuffing(rxPacket.data, rxPacket.packetLength);\n                        rxPacket.packetLength -= stuffLength;\n\n                        rxPacket.cmd = rxPacket.data[0];\n                        rxPacket.error = rxPacket.data[1];\n\n                        if (rxPacket.cmd == INST_STATUS) {\n                            //console.log(`rx length: ${rxPacket.packetLength}`);\n                            if (rxPacket.packetLength >= 147) {\n                                let tempValue = 0;\n                                for (let i = 0; i < addrMap.length; i++) {\n                                    switch (addrMap[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n\n                                const dxlPositionStartAddr =\n                                    addrMap[addrMap.length - 1][0] + addrMap[addrMap.length - 1][1];\n\n                                // DXL Position\n                                for (let i = 0; i < 20; i++) {\n                                    const currentId =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i];\n                                    const currentPos =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 1] +\n                                        (rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 2] << 8);\n                                    if (currentId != 0xff && currentPos != 0xffff) {\n                                        this.dxlPositions[currentId] = currentPos;\n                                    }\n                                }\n\n                                const lineCategoryStartAddr = dxlPositionStartAddr + 3 * 20;\n                                // line category\n                                this.dataBuffer[5201] = rxPacket.data[2 + lineCategoryStartAddr];\n\n                                const sensorStartAddr = lineCategoryStartAddr + 1;\n\n                                // 온습도+조도+동작감지센서값\n                                this.pirPir[0] = rxPacket.data[2 + sensorStartAddr];\n                                this.pirTemperature[0] = rxPacket.data[2 + sensorStartAddr + 1];\n                                this.pirHumidity[0] = rxPacket.data[2 + sensorStartAddr + 2];\n                                this.pirBrightness[0] = rxPacket.data[2 + sensorStartAddr + 3];\n\n                                // 거리+버튼+조도센서값\n                                this.distanceDistance[0] =\n                                    rxPacket.data[2 + sensorStartAddr + 4] +\n                                    (rxPacket.data[2 + sensorStartAddr + 5] << 8);\n                                this.distanceButton[0] = rxPacket.data[2 + sensorStartAddr + 6];\n                                this.distanceBrightness[0] = rxPacket.data[2 + sensorStartAddr + 7];\n\n                                for (let i = 0; i < addrMap2.length; i++) {\n                                    switch (addrMap2[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap2[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n                            }\n                        }\n\n                        this.packetReceiveState = PACKET_STATE_IDLE;\n                        break;\n\n                    default:\n                    // code block\n                }\n            }\n        }\n\n        requestInitialData() {\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 20]);\n            this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기\n            this.robotisBuffer.push([INST_WRITE, 20, 1, 0]); // bypass port를 BLE로 설정\n            this.robotisBuffer.push([INST_WRITE, 23, 1, 1]); // auto report 기능 켜기\n            this.robotisBuffer.push([INST_WRITE, 4250, 1, 1]); // ai_camera 텍스트 지우기\n            this.robotisBuffer.push([INST_WRITE, 722, 1, 0]); // dxl 토크 끄기\n            //this.robotisBuffer.push([INST_WRITE, 63, 1, 1]); // 부저음 시간 설정\n            //this.robotisBuffer.push([INST_WRITE, 60, 1, 70]); // 부저음 발생\n            this.robotisBuffer.push([INST_WRITE, 113, 2, 1040]); // \"띵\" 효과음 발생\n            /*\n            //const ping = [0xff, 0xff, 0xfd, 0x00, 0xc8, 0x03, 0x00, 0x01, 0x3b, 0xfa];\n            // run entry mode\n            const packet = [\n                0xff, 0xff, 0xfd, 0x00, 0xc8, 0x07, 0x00, 0x03, 0x15, 0x00, 0x14, 0x00, 0xc1, 0xb3,\n            ];\n            return packet;\n            */\n        }\n\n        async initialHandshake() {\n            const status = true;\n            let sendBuffer = null;\n            this.requestInitialData();\n            while (this.robotisBuffer.length) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        sendBuffer = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        sendBuffer = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n                Entry.hwLite.serial.sendAsciiAsBuffer(sendBuffer);\n                if (instruction == INST_WRITE && address == 2100 && length == 1 && value == 1) {\n                    this.robotisBuffer = [];\n                }\n            }\n            return status;\n        }\n    })();\n})();\n\nmodule.exports = Entry.RobotisKkokduLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_robotis_koalabot_lite.js",
    "content": "'use strict';\n\nconst INST_NONE = 0;\nconst INST_READ = 2;\nconst INST_WRITE = 3;\nconst INST_DXL_SYNCWRITE = 4;\nconst INST_DXL_REGWRITE = 5;\nconst INST_DXL_ACTION = 6;\nconst INST_BYPASS_READ = 0xa2;\nconst INST_BYPASS_WRITE = 0xa3;\n\nconst INST_STATUS = 0x55;\n\nconst PACKET_STATE_IDLE = 0;\nconst PACKET_STATE_RESERVED = 1;\nconst PACKET_STATE_ID = 2;\nconst PACKET_STATE_LENGTH_L = 3;\nconst PACKET_STATE_LENGTH_H = 4;\nconst PACKET_STATE_DATA = 5;\nconst PACKET_STATE_CRC_L = 6;\nconst PACKET_STATE_CRC_H = 7;\n\nconst DEFAULT_DELAY = 50;\n\nconst rxPacket = {\n    header: [0, 0, 0],\n    reserved: 0,\n    id: 0,\n    cmd: 0,\n    error: 0,\n    type: 0,\n    index: 0,\n    packetLength: 0,\n    paramLength: 0,\n    crc: 0,\n    crcReceived: 0,\n    checksum: 0,\n    checksumReceived: 0,\n    data: [],\n};\n\nconst addrMap = [\n    [0, 4, 302],\n    [4, 1, 42],\n    [5, 1, 44],\n    [6, 1, 45],\n    [7, 1, 47],\n    [8, 1, 50],\n    [9, 1, 51],\n    [10, 1, 52],\n    [11, 1, 68],\n    [12, 2, 70],\n    [14, 2, 72],\n    [16, 2, 74],\n    [18, 2, 76],\n    [20, 2, 78],\n    [22, 2, 80],\n    [24, 2, 82],\n    [26, 2, 84],\n    [28, 1, 86],\n    [29, 1, 87],\n    [30, 2, 88],\n    [32, 2, 90],\n    [34, 1, 112],\n    [35, 1, 118],\n    [36, 1, 119],\n    [37, 1, 122],\n    [38, 1, 123],\n    [39, 1, 124],\n    [40, 1, 125],\n    [41, 1, 160],\n    [42, 1, 220],\n    [43, 2, 360],\n    [45, 2, 362],\n    [47, 2, 364],\n    [49, 2, 366],\n    [51, 2, 368],\n    [53, 2, 370],\n    [55, 1, 372],\n    [56, 1, 373],\n    [57, 1, 374],\n    [58, 1, 375],\n    [59, 1, 376],\n    [60, 1, 377],\n    [61, 1, 378],\n    [62, 1, 379],\n    [63, 1, 380],\n    [64, 1, 381],\n    [65, 1, 382],\n    [66, 1, 383],\n    [67, 1, 500],\n    [68, 1, 501],\n    [69, 8, 502],\n    [77, 1, 700],\n    [78, 1, 810],\n    [79, 1, 2134],\n    [80, 1, 5015],\n    [81, 1, 5030],\n    [82, 1, 5031],\n    [83, 1, 5040],\n];\n\nconst addrMap2 = [\n    [153, 1, 4000],\n    [154, 2, 4003],\n    [156, 1, 4005],\n    [157, 1, 4006],\n    [158, 2, 4009],\n    [160, 2, 4011],\n    [162, 2, 4013],\n    [164, 2, 4015],\n    [166, 2, 4017],\n    [168, 2, 4019],\n    [170, 2, 4021],\n    [172, 2, 4023],\n    [174, 2, 4025],\n    [176, 2, 4027],\n    [178, 1, 4031],\n    [179, 1, 4032],\n    [180, 1, 4033],\n    [181, 2, 4036],\n    [183, 2, 4038],\n    [185, 2, 4040],\n    [187, 2, 4042],\n    [189, 2, 4044],\n    [191, 2, 4046],\n    [193, 2, 4048],\n    [195, 2, 4050],\n];\n\nconst crcTable = [\n    0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039,\n    0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,\n    0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9,\n    0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,\n    0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099,\n    0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,\n    0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea,\n    0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,\n    0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179,\n    0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,\n    0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309,\n    0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,\n    0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359,\n    0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,\n    0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9,\n    0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,\n    0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9,\n    0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,\n    0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, 0x0246, 0x024c, 0x8249,\n    0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,\n    0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219,\n    0x0208, 0x820d, 0x8207, 0x0202,\n];\n\nconst rb100_last_valid_value = [];\nlet bg_color = 0;\nlet beat_per_minute = 75;\nlet camera_id_for_use = 0;\n\n(function () {\n    Entry.RobotisKoalabotLite = new (class RobotisKoalabotLite {\n        constructor() {\n            this.id = '070C01';\n            this.url = 'http://www.robotis.com';\n            this.imageName = 'robotis_koalabot_lite.png';\n            this.name = 'RobotisKoalabotLite';\n            this.blockMenuBlocks = [\n                // 주행 제어\n                'robotis_koalabot_lite_drive_simple',\n                'robotis_koalabot_lite_drive_advanced',\n                'robotis_koalabot_lite_drive_seperate',\n                'robotis_koalabot_lite_drive_angle',\n                'robotis_koalabot_lite_go_distance',\n                'robotis_koalabot_lite_turn_angle',\n                'robotis_koalabot_lite_follow_line',\n                'robotis_koalabot_lite_stop_at_cross',\n                'robotis_koalabot_lite_turn_at_line',\n                'robotis_koalabot_lite_drive_stop',\n\n                // 값 블록\n                'robotis_koalabot_lite_cm_ir_value',\n                'robotis_koalabot_lite_cm_ir_compare',\n                'robotis_koalabot_lite_detectFrontObj',\n                'robotis_koalabot_lite_cm_btn_value',\n                'robotis_koalabot_lite_cm_joystick_value',\n                'robotis_koalabot_lite_mic',\n                'robotis_koalabot_lite_detectSound_compare',\n                'robotis_koalabot_lite_imu',\n                'robotis_koalabot_lite_roll_pitch',\n                'robotis_koalabot_lite_distance_value',\n                'robotis_koalabot_lite_distance_compare',\n                'robotis_koalabot_lite_dxl_value',\n                'robotis_koalabot_lite_line_cross_compare',\n\n                // 소리\n                'robotis_koalabot_lite_scale_simple',\n                'robotis_koalabot_lite_scale_advanced',\n                'robotis_koalabot_lite_rest_simple',\n                'robotis_koalabot_lite_rest_advanced',\n                'robotis_koalabot_lite_beat_per_minute',\n                'robotis_koalabot_lite_Hello',\n                'robotis_koalabot_lite_effectSound',\n                'robotis_koalabot_lite_record',\n                'robotis_koalabot_lite_playRecord',\n\n                // LCD 제어\n                'robotis_koalabot_lite_screen',\n                'robotis_koalabot_lite_anim_screen',\n                'robotis_koalabot_lite_icon_screen_food_plant',\n                'robotis_koalabot_lite_icon_screen_animal_human',\n                'robotis_koalabot_lite_icon_screen_object_tool',\n                'robotis_koalabot_lite_icon_screen_vehicle_number',\n                'robotis_koalabot_lite_icon_screen_game_character',\n                'robotis_koalabot_lite_text_screen',\n                'robotis_koalabot_lite_text_screen_redraw',\n                'robotis_koalabot_lite_pixel',\n                'robotis_koalabot_lite_LCDColor',\n                'robotis_koalabot_lite_LCDBright',\n\n                // LED 제어\n                'robotis_koalabot_lite_cm_led',\n                'robotis_koalabot_lite_cm_led_pattern',\n\n                // AI 카메라 값 블록\n                'robotis_koalabot_lite_ai_camera_connection_status',\n                'robotis_koalabot_lite_ai_camera_if_detected',\n\n                'robotis_koalabot_lite_ai_camera_block_value_closest_to_center',\n                'robotis_koalabot_lite_ai_camera_arrow_value_closest_to_center',\n                'robotis_koalabot_lite_ai_camera_number_of_learned_id',\n                'robotis_koalabot_lite_ai_camera_block_value_of_id',\n                'robotis_koalabot_lite_ai_camera_arrow_value_of_id',\n\n                'robotis_koalabot_lite_ai_camera_if_learned_id',\n                'robotis_koalabot_lite_ai_camera_if_detected_id_type',\n\n                // AI Camera 제어\n                'robotis_koalabot_lite_ai_camera_set_mode',\n                'robotis_koalabot_lite_ai_camera_print_custom_text',\n                'robotis_koalabot_lite_ai_camera_clear_custom_text',\n            ];\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                connectionType: 'bytestream',\n                bufferSize: 128,\n                constantServing: true,\n            };\n            this.duration = 15;\n            this.setZero();\n\n            this.timeouts = [];\n\n            this.robotisBuffer = []; // buffer to transmit to H/W\n            this.receiveBuffer = []; // buffer to receive from H/W\n            this.dataBuffer = []; // saved control table value buffer\n\n            this.packetReceiveState = 0;\n            this.headerCount = 0;\n\n            this.dxlPositions = [];\n\n            this.pirPir = [];\n            this.pirTemperature = [];\n            this.pirHumidity = [];\n            this.pirBrightness = [];\n            this.distanceDistance = [];\n            this.distanceButton = [];\n            this.distanceBrightness = [];\n        }\n\n        setZero() {\n            this.timeouts = [];\n            this.__removeAllTimeouts();\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 2100, 1, 2]); // 값 2는 코알라 얼굴이 뜨도록(펌웨어는 v1.15.4부터)\n            camera_id_for_use = 0;\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        __removeTimeout(id) {\n            clearTimeout(id);\n            const idx = this.timeouts.indexOf(id);\n            if (idx >= 0) {\n                this.timeouts.splice(idx, 1);\n            }\n        }\n\n        __removeAllTimeouts() {\n            const timeouts = this.timeouts;\n            for (const i in timeouts) {\n                clearTimeout(timeouts[i]);\n            }\n            this.timeouts = [];\n        }\n\n        getMonitorPort() {\n            return { ...this.sensory, ...this.motoring, ...this.lineTracer };\n        }\n\n        writePacket(id, address, length, value) {\n            if (length > 256) {\n                console.log(`######### invalid length: ${length}`);\n                return null;\n            }\n            console.log('######### writePacket');\n            const packet = [];\n            let i = 0;\n            packet.push(0xff);\n            packet.push(0xff);\n            packet.push(0xfd);\n            packet.push(0x00);\n            packet.push(id);\n            packet.push(length + 5);\n            packet.push(0x00);\n            packet.push(INST_WRITE);\n            packet.push(this.getLowByte(address));\n            packet.push(this.getHighByte(address));\n            switch (length) {\n                case 1:\n                    packet.push(this.getLowByte(value));\n                    break;\n                case 2:\n                    packet.push(this.getLowByte(value));\n                    packet.push(this.getHighByte(value));\n                    break;\n                case 4:\n                    packet.push(this.getLowByte(this.getLowWord(value)));\n                    packet.push(this.getHighByte(this.getLowWord(value)));\n                    packet.push(this.getLowByte(this.getHighWord(value)));\n                    packet.push(this.getHighByte(this.getHighWord(value)));\n                    break;\n                default:\n                    for (i = 0; i < length; i++) {\n                        if (typeof value[i] == 'number') {\n                            packet.push(value[i]);\n                        } else if (typeof value[i] == 'string') {\n                            packet.push(value[i].charCodeAt(0));\n                        }\n                    }\n                    break;\n            }\n            const crc = this.updateCRC(0, packet, packet.length);\n            packet.push(this.getLowByte(crc));\n            packet.push(this.getHighByte(crc));\n            return packet;\n        }\n\n        makeWord(a, b) {\n            return (a & 0xff) | ((b & 0xff) << 8);\n        }\n\n        getLowByte(a) {\n            return a & 0xff;\n        }\n\n        getHighByte(a) {\n            return (a >> 8) & 0xff;\n        }\n\n        getLowWord(a) {\n            return a & 0xffff;\n        }\n\n        getHighWord(a) {\n            return (a >> 16) & 0xffff;\n        }\n\n        updateCRC(crcAccum, dataBlkPtr, dataBlkSize) {\n            let i = 0;\n            let j = 0;\n            let crc = crcAccum;\n\n            for (j = 0; j < dataBlkSize; j++) {\n                i = ((crc >> 8) ^ dataBlkPtr[j]) & 0xff;\n                crc = (crc << 8) ^ crcTable[i];\n            }\n\n            return crc;\n        }\n\n        removeStuffing(buffer, length) {\n            let i = 0;\n            let stuffLength = 0;\n            let index = 0;\n\n            for (i = 0; i < length; i++) {\n                if (i >= 2) {\n                    if (buffer[i - 2] == 0xff && buffer[i - 1] == 0xff && buffer[i] == 0xfd) {\n                        i++;\n                        stuffLength++;\n                    }\n                }\n                buffer[index++] = buffer[i];\n            }\n\n            return stuffLength;\n        }\n\n        postCallReturn(script, data, ms) {\n            /*\n            if (data == null) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            } else if (data.length == 0) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n            */\n            if (!script.isStart) {\n                script.isStart = true;\n                script.timeFlag = 1;\n                for (let i = 0; i < data.length; i++) {\n                    this.robotisBuffer.push(data[i]);\n                }\n                //delay ms\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, ms);\n                return script;\n            } else if (script.timeFlag) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.timeFlag;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // 주행 제어\n                        robotis_koalabot_lite_drive_simple: '속도 %1 (으)로 %2 하기 %3',\n                        robotis_koalabot_lite_drive_advanced:\n                            '왼쪽바퀴 %1 속도로 %2, 오른쪽바퀴 %3 속도로 %4 %5',\n                        robotis_koalabot_lite_drive_seperate:\n                            '%1 바퀴 %2 속도로 %3 으로 회전하기 %4',\n                        robotis_koalabot_lite_drive_angle:\n                            '양쪽 바퀴 %1 도만큼 %2 으로 회전하기 %3',\n                        robotis_koalabot_lite_go_distance: '%1 cm %2 하기 %3',\n                        robotis_koalabot_lite_turn_angle: '로봇 %1 도 %2 하기%3',\n                        robotis_koalabot_lite_follow_line: '%1 속도로 라인 따라가기 %2',\n                        robotis_koalabot_lite_stop_at_cross: '교차로 %1 에서 멈추기 %2',\n                        robotis_koalabot_lite_turn_at_line: '교차로에서 %1 하고 멈추기 %2',\n                        robotis_koalabot_lite_drive_stop: '정지하기 %1',\n\n                        // 값 블록\n                        robotis_koalabot_lite_cm_ir_value: '%1 적외선센서 값',\n                        robotis_koalabot_lite_cm_ir_compare: '%1 적외선센서 값이 %2 보다 %3',\n                        robotis_koalabot_lite_detectFrontObj: '%1의 앞에 물체가 있으면',\n                        robotis_koalabot_lite_cm_btn_value: '로봇의 %1 버튼을 눌렀을 때',\n                        robotis_koalabot_lite_cm_joystick_value:\n                            '로봇의 노랑 조이스틱 위치가 %1 이면',\n                        robotis_koalabot_lite_mic: '소리의 크기(dB)',\n                        robotis_koalabot_lite_detectSound_compare: '소리가 로봇의 %1에서 들리면',\n                        robotis_koalabot_lite_imu: '%1축의 %2 값',\n                        robotis_koalabot_lite_roll_pitch: '로봇의 %1 값',\n                        robotis_koalabot_lite_distance_value: '%1 값',\n                        robotis_koalabot_lite_distance_compare: '%1 값이 %2보다 %3',\n                        robotis_koalabot_lite_line_cross_compare: '교차로 모양이 %1이면',\n                        robotis_koalabot_lite_dxl_value: '%1의 각도값',\n\n                        // 소리\n                        robotis_koalabot_lite_scale_simple: '옥타브%1 로 %2 음을 %3로 연주하기 %4',\n                        robotis_koalabot_lite_scale_advanced:\n                            '옥타브%1 로 %2 음을 %3박자 연주하기 %4',\n                        robotis_koalabot_lite_rest_simple: '%1 %2',\n                        robotis_koalabot_lite_rest_advanced: '쉼표 %1 박자 %2',\n                        robotis_koalabot_lite_beat_per_minute: '연주 빠르기를 %1 (으)로 정하기 %2',\n                        robotis_koalabot_lite_Hello: '로봇 %1 말하기 %2',\n                        robotis_koalabot_lite_effectSound: '효과음 %1 재생하기 %2',\n                        robotis_koalabot_lite_record: '소리 %1번에 녹음하기 %2',\n                        robotis_koalabot_lite_playRecord: '소리 %1번을 재생하기 %2',\n\n                        // LCD 제어\n                        robotis_koalabot_lite_screen: '화면 표정을 %1 %2 (으)로 정하기 %3',\n                        robotis_koalabot_lite_anim_screen:\n                            '화면 애니메이션을 %1 %2 (으)로 정하기 %3',\n                        robotis_koalabot_lite_icon_screen_food_plant:\n                            '화면에 [음식/식물]중 %1 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_koalabot_lite_icon_screen_animal_human:\n                            '화면에 [동물/사람]중 %1 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_koalabot_lite_icon_screen_object_tool:\n                            '화면에 [물건/도구]중 %1 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_koalabot_lite_icon_screen_vehicle_number:\n                            '화면에 [탈것/숫자]중 %1 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_koalabot_lite_icon_screen_game_character:\n                            '화면에 [게임/캐릭터]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_koalabot_lite_text_screen:\n                            '화면에 %1 (%2, %3)위치에 %4 로 %5으로 표시 %6',\n                        robotis_koalabot_lite_text_screen_redraw:\n                            '화면에 %1 (%2, %3)위치에 %4으로 새로 표시 %5',\n                        robotis_koalabot_lite_pixel: '화면 (%1, %2)위치에 %3 색 점 표시 %4',\n                        robotis_koalabot_lite_LCDBright: '화면 밝기를 %1 (으)로 정하기 %2',\n                        robotis_koalabot_lite_LCDColor: '화면 색상을 %1 (으)로 정하기 %2',\n\n                        // LED 제어\n                        robotis_koalabot_lite_cm_led: '로봇 %1 LED %2 %3',\n                        robotis_koalabot_lite_cm_led_pattern: 'LED %1 %2로 깜박이기 %3',\n\n                        // AI Camera 값 블록\n                        robotis_koalabot_lite_ai_camera_connection_status: 'AI 카메라 %1이면',\n                        robotis_koalabot_lite_ai_camera_if_detected: 'AI 카메라 %1 이/가 표시되면',\n\n                        robotis_koalabot_lite_ai_camera_block_value_closest_to_center:\n                            'AI 카메라 화면 중앙과 가장 가까운 사각형의 %1',\n                        robotis_koalabot_lite_ai_camera_arrow_value_closest_to_center:\n                            'AI 카메라 화면 중앙과 가장 가까운 화살표의 %1',\n                        robotis_koalabot_lite_ai_camera_number_of_learned_id:\n                            'AI 카메라 학습한 ID의 갯수',\n                        robotis_koalabot_lite_ai_camera_block_value_of_id:\n                            'AI 카메라 감지된 ID가 %1인 사각형의 %2',\n                        robotis_koalabot_lite_ai_camera_arrow_value_of_id:\n                            'AI 카메라 감지된 ID가 %1인 화살표의 %2',\n\n                        robotis_koalabot_lite_ai_camera_if_learned_id:\n                            'AI 카메라 ID가 %1인 데이터를 학습하였으면',\n                        robotis_koalabot_lite_ai_camera_if_detected_id_type:\n                            'AI 카메라 ID가 %1인 %2데이터를 인식하였으면',\n\n                        // AI 카메라 제어\n                        robotis_koalabot_lite_ai_camera_set_mode:\n                            'AI 카메라 모드를 %1(으)로 설정 %2',\n                        robotis_koalabot_lite_ai_camera_print_custom_text:\n                            'AI 카메라 화면 위치 (%1,%2)에 %3를 보여주기%4',\n                        robotis_koalabot_lite_ai_camera_clear_custom_text:\n                            'AI 카메라 화면의 글 지우기 %1',\n                    },\n                    Helper: {\n                        // 주행 제어\n                        robotis_koalabot_lite_drive_simple:\n                            '코알라봇을 지정한 속도와 방향으로 주행\\n속도범위: -100 ~ 100\\n속도단위: %',\n                        robotis_koalabot_lite_drive_advanced:\n                            '코알라봇의 좌,우 바퀴를 각각 지정한 속도와 방향으로 회전\\n속도범위: -100 ~ 100\\n속도단위: %',\n                        robotis_koalabot_lite_drive_seperate:\n                            '코알라봇의 지정한 바퀴를 지정한 속도와 방향으로 회전\\n속도범위: -100 ~ 100\\n속도단위: %',\n                        robotis_koalabot_lite_drive_angle:\n                            '코알라봇의 지정한 바퀴를 지정한 방향과 지정한 각도만큼 회전\\n각도범위: -5760 ~ 5760\\n각도단위: 도',\n                        robotis_koalabot_lite_go_distance:\n                            '지정거리만큼 앞 또는 뒤로 이동\\n거리범위: -1000 ~ 1000\\n거리단위: mm',\n                        robotis_koalabot_lite_turn_angle:\n                            '지정한 각도와 방향으로 제자리회전\\n각도범위: -360 ~ 360\\n각도단위: 도',\n                        robotis_koalabot_lite_follow_line:\n                            '지정한 수준의 속도로 라인 따라가기 시작',\n                        robotis_koalabot_lite_stop_at_cross: '지정한 교차로에서 멈추기',\n                        robotis_koalabot_lite_turn_at_line: '교차로에서 지정한 회전을 하고 멈추기',\n                        robotis_koalabot_lite_drive_stop: '코알라봇 정지하기',\n\n                        // 값 블록\n                        robotis_koalabot_lite_cm_ir_value:\n                            '지정한 번호의 IR 센서 값(범위: 0 ~ 200)',\n                        robotis_koalabot_lite_cm_ir_compare:\n                            \"지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_koalabot_lite_detectFrontObj:\n                            \"지정한 센서 앞에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_koalabot_lite_cm_btn_value:\n                            \"지정한 버튼이 눌렸다가 해제되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_koalabot_lite_cm_joystick_value:\n                            \"조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다..\",\n                        robotis_koalabot_lite_mic:\n                            '마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.',\n                        robotis_koalabot_lite_detectSound_compare:\n                            \"소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_koalabot_lite_imu:\n                            '지정한 축의 지정한 가속도센서/자이로센서의 값\\n범위: -100 ~ 100',\n                        robotis_koalabot_lite_roll_pitch:\n                            'roll/pitch 값\\nroll: -180° ~ 180°, pitch: -90° ~ 90°',\n                        robotis_koalabot_lite_distance_value:\n                            '지정한 센서값\\n거리범위: 0 ~ 1000mm\\n밝기범위: 0 ~ 100%\\n버튼센서: 0(눌리지 않음) / 1(눌림)',\n                        robotis_koalabot_lite_distance_compare:\n                            \"지정한 센서값의 지정한 수식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_koalabot_lite_line_cross_compare:\n                            \"지정한 교차로 모양이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_koalabot_lite_dxl_value:\n                            '지정한 모터의 위치 각도값\\n범위: -180° ~ 180°',\n\n                        // 소리\n                        robotis_koalabot_lite_scale_simple: '지정한 옥타브, 음계, 음표로 연주하기',\n                        robotis_koalabot_lite_scale_advanced:\n                            '지정한 옥타브, 음계, 박자로 연주하기',\n                        robotis_koalabot_lite_rest_simple: '지정한 쉼표 쉬기',\n                        robotis_koalabot_lite_rest_advanced: '지정한 박자 쉬기',\n                        robotis_koalabot_lite_beat_per_minute:\n                            '연주 빠르기를 지정하기 (BPM)\\n범위: 10 ~ 600',\n                        robotis_koalabot_lite_Hello: '로봇이 지정한 말소리를 재생하기',\n                        robotis_koalabot_lite_effectSound: '로봇이 지정한 효과음을 재생하기',\n                        robotis_koalabot_lite_record: '지정번호 보관함에 녹음하여 저장하기',\n                        robotis_koalabot_lite_playRecord: '지정번호 보관함의 녹음음성을 재생하기',\n\n                        // LCD 제어\n                        robotis_koalabot_lite_screen: '제어기 화면배경의 캐릭터와 표정을 설정',\n                        robotis_koalabot_lite_anim_screen:\n                            '제어기 화면 애니메이션의 캐릭터와 표정을 설정',\n                        robotis_koalabot_lite_icon_screen_food_plant:\n                            '화면에 [음식/식물]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_koalabot_lite_icon_screen_animal_human:\n                            '화면에 [동물/사람]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_koalabot_lite_icon_screen_object_tool:\n                            '화면에 [물건/도구]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_koalabot_lite_icon_screen_vehicle_number:\n                            '화면에 [탈것/숫자]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_koalabot_lite_icon_screen_game_character:\n                            '화면에 [게임/캐릭터]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_koalabot_lite_text_screen:\n                            '화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n                        robotis_koalabot_lite_text_screen_redraw:\n                            '화면에 지정한 문구를 새롭게(문구의 배경 지움) 표시할 위치와 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_koalabot_lite_pixel:\n                            '화면에 표시할 점의 위치와 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n                        robotis_koalabot_lite_LCDBright: '화면 밝기를 설정\\n밝기범위: 1% ~ 100%',\n                        robotis_koalabot_lite_LCDColor: '화면 색상을 설정',\n\n                        // LED 제어\n                        robotis_koalabot_lite_cm_led: '제어기의 지정한 LED를 켜거나 끄기',\n                        robotis_koalabot_lite_cm_led_pattern: '제어기의 LED의 깜박임 패턴 설정',\n\n                        // AI Camera 값 블록\n                        robotis_koalabot_lite_ai_camera_connection_status:\n                            \"AI 카메라가 연결된 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_koalabot_lite_ai_camera_if_detected:\n                            \"AI 카메라의 LCD화면에 선택한 기호(사각형/화살표)가 표시되면 '참', 아니면 '거짓'으로 판단합니다.\",\n\n                        robotis_koalabot_lite_ai_camera_block_value_closest_to_center:\n                            'AI 카메라 화면 중앙과 가장 가까운 사각형의 X좌표/Y좌표/너비/높이/학습ID',\n                        robotis_koalabot_lite_ai_camera_arrow_value_closest_to_center:\n                            'AI 카메라 화면 중앙과 가장 가까운 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표/학습ID',\n                        robotis_koalabot_lite_ai_camera_number_of_learned_id:\n                            'AI 카메라가 학습한 ID의 갯수',\n                        robotis_koalabot_lite_ai_camera_block_value_of_id:\n                            'AI 카메라가 감지한 사각형중 지정한 ID의 사각형의 X좌표/Y좌표/너비/높이',\n                        robotis_koalabot_lite_ai_camera_arrow_value_of_id:\n                            'AI 카메라가 감지한 화살표중 지정한 ID의 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표',\n\n                        robotis_koalabot_lite_ai_camera_if_learned_id:\n                            \"AI 카메라가 지정한 ID인 데이터를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_koalabot_lite_ai_camera_if_detected_id_type:\n                            \"AI 카메라가 지정한 ID인 지정한 데이터(사각형/화살표)를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.\",\n\n                        // AI 카메라 제어\n                        robotis_koalabot_lite_ai_camera_set_mode: 'AI 카메라의 모드를 설정',\n                        robotis_koalabot_lite_ai_camera_print_custom_text:\n                            'AI 카메라 화면의 지정한 위치에 지정한 문구 출력\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n                        robotis_koalabot_lite_ai_camera_clear_custom_text:\n                            'AI 카메라 화면에 표시한 모든 문구 지우기',\n                    },\n                    Blocks: {\n                        robotis_red: '빨강',\n                        robotis_orange: '주황',\n                        robotis_yellow: '노랑',\n                        robotis_green: '초록',\n                        robotis_blue: '파랑',\n                        robotis_brown: '갈색',\n                        robotis_black: '검정',\n                        robotis_white: '흰색',\n                        robotis_left: '왼쪽',\n                        robotis_center: '중앙',\n                        robotis_right: '오른쪽',\n                        robotis_both: '양쪽',\n                        robotis_rgee: '알쥐',\n                        robotis_rla: '알라',\n                        robotis_kkokdu: '꼭두',\n                        robotis_korean1: '안녕하세요',\n                        robotis_korean2: '반가워요',\n                        robotis_korean3: '알겠어요',\n                        robotis_korean4: '아니에요',\n                        robotis_korean5: '모르겠어요',\n                        robotis_korean6: '좋아요',\n                        robotis_korean7: '싫어요',\n                        robotis_korean8: '이름을말하세요',\n                        robotis_korean9: '무엇을도와줄까?',\n                        robotis_korean10: '잘했어',\n                        robotis_korean11: '괜찮아',\n                        robotis_korean12: '다시해보자',\n                        robotis_korean13: '고마워',\n                        robotis_korean14: '다시말해줄래?',\n                        robotis_korean15: '최고야!',\n                        robotis_korean16: '신나요',\n                        robotis_korean17: '즐거워요',\n                        robotis_korean18: '미안해요',\n                        robotis_korean19: '화나요',\n                        robotis_korean20: '부끄러워요',\n                        robotis_korean21: '무서워요',\n                        robotis_korean22: '속상해요',\n                        robotis_korean23: '사랑해요',\n                        robotis_korean24: '예뻐요',\n                        robotis_korean25: '신기해요',\n                        robotis_korean26: '초조해요',\n                        robotis_korean27: '앞으로가자',\n                        robotis_korean28: '뒤로가자',\n                        robotis_korean29: '일어나자',\n                        robotis_korean30: '넘어졌네?',\n                        robotis_korean31: '오예',\n                        robotis_korean32: '아싸',\n                        robotis_korean33: '어머',\n                        robotis_korean34: '이런',\n                        robotis_korean35: '오호',\n                        robotis_korean36: '하하하',\n                        robotis_korean37: '호호호',\n                        robotis_korean38: '졸려',\n                        robotis_korean39: '자장가를들려줘',\n                        robotis_korean40: '안녕',\n                        robotis_korean41: '배고프다',\n                        robotis_korean42: '도토리땡긴다',\n                        robotis_korean43: '아.씻고싶어',\n                        robotis_korean44: '비누목욕시간이야',\n                        robotis_korean45: '심심한데',\n                        robotis_korean46: '간식먹을까',\n                        robotis_korean47: '아파요',\n                        robotis_korean48: '약은없나요?',\n                        robotis_korean49: '어디로가야하지?',\n                        robotis_korean50: '와아도착이다',\n                        robotis_korean51: '왼쪽으로가자',\n                        robotis_korean52: '오른쪽으로가자',\n                        robotis_korean53: '깜짝이야',\n                        robotis_korean54: '찾았다',\n                        robotis_korean55: '여긴없네',\n                        robotis_korean56: '혹시나불렀어?',\n                        robotis_korean57: '내려주세요',\n                        robotis_korean58: '앗',\n                        robotis_korean59: '힝',\n                        robotis_korean60: '이익',\n                        robotis_dog: '개',\n                        robotis_frog: '개구리',\n                        robotis_cat: '고양이',\n                        robotis_chicken: '닭',\n                        robotis_tiger: '호랑이',\n                        robotis_mouse: '쥐',\n                        robotis_ambul: '앰뷸런스',\n                        robotis_Horn: '경적(빵빵)',\n                        robotis_siren: '사이렌(경찰차)',\n                        robotis_whistle: '호루라기',\n                        robotis_gun: '총소리',\n                        robotis_clap: '박수소리',\n                        robotis_melody1: '멜로디1',\n                        robotis_melody2: '멜로디2',\n                        robotis_melody3: '멜로디3',\n                        robotis_melody4: '멜로디4',\n                        robotis_forward: '앞으로',\n                        robotis_backward: '뒤로',\n                        robotis_acceleration: '가속도',\n                        robotis_gyro: '자이로',\n                        robotis_run: '실행',\n                        robotis_cancel: '취소',\n                        robotis_push: '눌림',\n                        robotis_notPush: '안눌림',\n                        robotis_play: '연주',\n                        robotis_rest: '쉼표',\n                        robotis_face01: '와하하',\n                        robotis_face02: '싱글벙글',\n                        robotis_face03: '큭큭큭',\n                        robotis_face04: '냠냠',\n                        robotis_face05: '겁먹음',\n                        robotis_face06: '답답',\n                        robotis_face07: '갸우뚱',\n                        robotis_face08: '어벙벙',\n                        robotis_face09: '고함',\n                        robotis_face10: '화남',\n                        robotis_face11: '킁킁(왼쪽)',\n                        robotis_face12: '킁킁(오른쪽)',\n                        robotis_face13: '킁킁(아래)',\n                        robotis_face14: '안심',\n                        robotis_face15: '기절',\n                        robotis_face16: '헤롱헤롱',\n                        robotis_face17: '하품',\n                        robotis_face18: '졸림',\n                        robotis_face19: '잠듦',\n                        robotis_face20: '마음앓이',\n                        robotis_face21: '폭풍눈물',\n                        robotis_face22: '목욕',\n                        robotis_face23: '햐트뿅뿅',\n\n                        robotis_pattern1: '패턴1',\n                        robotis_pattern2: '패턴2',\n                        robotis_pattern3: '패턴3',\n                        robotis_moveF: '전진',\n                        robotis_moveB: '후진',\n                        robotis_moveL: '좌회전',\n                        robotis_moveR: '우회전',\n                        robotis_moveU: 'U턴',\n                        robotis_moveL_in_place: '제자리 좌회전',\n                        robotis_moveR_in_place: '제자리 우회전',\n                        robotis_moveU_in_place: '제자리 U턴',\n                        robotis_moveRG1: '일어서기',\n                        robotis_moveRG2: '앉기',\n                        robotis_moveRG3: '발버둥',\n                        robotis_moveRG4: '발들기',\n                        robotis_fast: '빠른',\n                        robotis_normal: '보통',\n                        robotis_slow: '느린',\n                        robotis_stop: '정지',\n                        robotis_roll: '좌우 회전각 (roll)',\n                        robotis_pitch: '앞뒤 회전각 (pitch)',\n                        robotis_direction_forward: '전진방향',\n                        robotis_direction_backward: '후진방향',\n                        robotis_stMotion1: '기본자세',\n                        robotis_stMotion2: '전진',\n                        robotis_stMotion3: '우전진',\n                        robotis_stMotion4: '좌전진',\n                        robotis_stMotion5: '후진',\n                        robotis_stMotion6: '오른쪽으로',\n                        robotis_stMotion7: '왼쪽으로',\n                        robotis_stMotion8: '우회전',\n                        robotis_stMotion9: '좌회전',\n                        robotis_spMotion1: '오른손 들기',\n                        robotis_spMotion2: '오른손 내리기',\n                        robotis_spMotion3: '왼손 들기',\n                        robotis_spMotion4: '왼손 내리기',\n                        robotis_spMotion5: '양손 들기',\n                        robotis_spMotion6: '양손 내리기',\n                        robotis_spMotion7: '뒤로 넘어지기',\n                        robotis_spMotion8: '앞으로 넘어지기',\n                        robotis_spMotion9: '앞으로 일어서기',\n                        robotis_spMotion10: '뒤로 일어서기',\n                        robotis_spMotion11: '방어',\n                        robotis_spMotion12: '공격1',\n                        robotis_spMotion13: '공격2',\n                        robotis_spMotion14: '공격3',\n                        robotis_spMotion15: '공격4',\n                        robotis_screen1: '가위',\n                        robotis_screen2: '바위',\n                        robotis_screen3: '보',\n                        robotis_icon_food_plant_1: '우유',\n                        robotis_icon_food_plant_2: '나무',\n                        robotis_icon_food_plant_3: '스프',\n                        robotis_icon_food_plant_4: '케익',\n                        robotis_icon_food_plant_5: '물',\n                        robotis_icon_food_plant_6: '주스',\n                        robotis_icon_food_plant_7: '당근',\n                        robotis_icon_food_plant_8: '사과',\n                        robotis_icon_food_plant_9: '오렌지',\n                        robotis_icon_food_plant_10: '고기',\n                        robotis_icon_food_plant_11: '화분',\n                        robotis_icon_food_plant_12: '장미',\n                        robotis_icon_food_plant_13: '포도',\n                        robotis_icon_food_plant_14: '감자',\n                        robotis_icon_food_plant_15: '사탕',\n                        robotis_icon_food_plant_16: '치즈',\n                        robotis_icon_food_plant_17: '식빵',\n                        robotis_icon_food_plant_18: '꽃들',\n                        robotis_icon_food_plant_19: '커피',\n                        robotis_icon_food_plant_20: '튤립',\n                        robotis_icon_food_plant_21: '바나나',\n                        robotis_icon_food_plant_22: '과일들',\n                        robotis_icon_food_plant_23: '햄버거',\n                        robotis_icon_food_plant_24: '피자',\n                        robotis_icon_animal_human_1: '시바견',\n                        robotis_icon_animal_human_2: '강아지',\n                        robotis_icon_animal_human_3: '곰',\n                        robotis_icon_animal_human_4: '새',\n                        robotis_icon_animal_human_5: '오리',\n                        robotis_icon_animal_human_6: '사자',\n                        robotis_icon_animal_human_7: '호랑이',\n                        robotis_icon_animal_human_8: '말',\n                        robotis_icon_animal_human_9: '양',\n                        robotis_icon_animal_human_10: '상어1(왼쪽)',\n                        robotis_icon_animal_human_11: '상어1(오른쪽)',\n                        robotis_icon_animal_human_12: '상어2(왼쪽)',\n                        robotis_icon_animal_human_13: '상어2(오른쪽)',\n                        robotis_icon_animal_human_14: '물고기1',\n                        robotis_icon_animal_human_15: '물고기2',\n                        robotis_icon_animal_human_16: '물고기3',\n                        robotis_icon_animal_human_17: '문어',\n                        robotis_icon_animal_human_18: '원숭이',\n                        robotis_icon_animal_human_19: '닭',\n                        robotis_icon_animal_human_20: '돼지',\n                        robotis_icon_animal_human_21: '사람(살찐)',\n                        robotis_icon_animal_human_22: '사람(수영복)',\n                        robotis_icon_animal_human_23: '아기',\n                        robotis_icon_animal_human_24: '사람(달리는)',\n                        robotis_icon_animal_human_25: '사람(노래하는)',\n                        robotis_icon_animal_human_26: '사람(앉은)',\n                        robotis_icon_animal_human_27: '사람(화난)',\n                        robotis_icon_animal_human_28: '사람(만세)',\n                        robotis_icon_animal_human_29: '왕',\n                        robotis_icon_animal_human_30: '왕자',\n                        robotis_icon_animal_human_31: '공주',\n                        robotis_icon_animal_human_32: '요리사',\n                        robotis_icon_animal_human_33: '의사',\n                        robotis_icon_animal_human_34: '간호사',\n                        robotis_icon_object_tool_1: '가방',\n                        robotis_icon_object_tool_2: '상자',\n                        robotis_icon_object_tool_3: '머그컵',\n                        robotis_icon_object_tool_4: '모자(중절모)',\n                        robotis_icon_object_tool_5: '모자(캡모자)',\n                        robotis_icon_object_tool_6: '열쇠',\n                        robotis_icon_object_tool_7: '장난감',\n                        robotis_icon_object_tool_8: '책',\n                        robotis_icon_object_tool_9: '곰인형',\n                        robotis_icon_object_tool_10: '드럼',\n                        robotis_icon_object_tool_11: '메모장',\n                        robotis_icon_object_tool_12: '볼펜',\n                        robotis_icon_object_tool_13: '책상',\n                        robotis_icon_object_tool_14: '테이블',\n                        robotis_icon_object_tool_15: '의자',\n                        robotis_icon_object_tool_16: '침대',\n                        robotis_icon_object_tool_17: '텐트',\n                        robotis_icon_object_tool_18: '접시',\n                        robotis_icon_object_tool_19: '축구공',\n                        robotis_icon_object_tool_20: '종',\n                        robotis_icon_object_tool_21: '손목시계',\n                        robotis_icon_object_tool_22: '신발',\n                        robotis_icon_object_tool_23: '전등',\n                        robotis_icon_object_tool_24: '라디오',\n                        robotis_icon_object_tool_25: '지폐',\n                        robotis_icon_object_tool_26: '자',\n                        robotis_icon_object_tool_27: '카메라',\n                        robotis_icon_object_tool_28: '스푼',\n                        robotis_icon_object_tool_29: '건반',\n                        robotis_icon_object_tool_30: '달력',\n                        robotis_icon_object_tool_31: '칼',\n                        robotis_icon_object_tool_32: '풍선',\n                        robotis_icon_object_tool_33: '물통',\n                        robotis_icon_object_tool_34: '나무막대(세로)',\n                        robotis_icon_object_tool_35: '나무막대(가로)',\n                        robotis_icon_object_tool_36: '낚시바늘',\n                        robotis_icon_vehicle_number_1: '자동차',\n                        robotis_icon_vehicle_number_2: '버스',\n                        robotis_icon_vehicle_number_3: '트럭',\n                        robotis_icon_vehicle_number_4: '지프',\n                        robotis_icon_vehicle_number_5: '자전거',\n                        robotis_icon_vehicle_number_6: '전철',\n                        robotis_icon_vehicle_number_7: '기차',\n                        robotis_icon_vehicle_number_8: '비행기',\n                        robotis_icon_vehicle_number_9: '전투기(세로)',\n                        robotis_icon_vehicle_number_10: '전투기(가로)',\n                        robotis_icon_vehicle_number_11: '로켓',\n                        robotis_icon_vehicle_number_12: '어선',\n                        robotis_icon_vehicle_number_13: '여객선',\n                        robotis_icon_vehicle_number_14: '잠수함(왼쪽)',\n                        robotis_icon_vehicle_number_15: '잠수함(오른쪽)',\n                        robotis_icon_vehicle_number_16: '비행기(왼쪽)',\n                        robotis_icon_vehicle_number_17: '비행기(오른쪽)',\n                        robotis_icon_vehicle_number_18: '비행기(윗쪽)',\n                        robotis_icon_vehicle_number_19: '우주선(왼쪽)',\n                        robotis_icon_vehicle_number_20: '우주선(오른쪽)',\n                        robotis_icon_vehicle_number_21: '우주선(윗쪽)',\n                        robotis_icon_vehicle_number_22: '주사위(1)',\n                        robotis_icon_vehicle_number_23: '주사위(2)',\n                        robotis_icon_vehicle_number_24: '주사위(3)',\n                        robotis_icon_vehicle_number_25: '주사위(4)',\n                        robotis_icon_vehicle_number_26: '주사위(5)',\n                        robotis_icon_vehicle_number_27: '주사위(6)',\n                        robotis_icon_vehicle_number_28: '0',\n                        robotis_icon_vehicle_number_29: '1',\n                        robotis_icon_vehicle_number_30: '2',\n                        robotis_icon_vehicle_number_31: '3',\n                        robotis_icon_vehicle_number_32: '4',\n                        robotis_icon_vehicle_number_33: '5',\n                        robotis_icon_vehicle_number_34: '6',\n                        robotis_icon_vehicle_number_35: '7',\n                        robotis_icon_vehicle_number_36: '8',\n                        robotis_icon_vehicle_number_37: '9',\n                        robotis_icon_vehicle_number_38: '10',\n                        robotis_icon_game_character_1: '알쥐(정면)',\n                        robotis_icon_game_character_2: '알쥐(왼쪽)',\n                        robotis_icon_game_character_3: '알쥐(오른쪽)',\n                        robotis_icon_game_character_4: '알라(정면)',\n                        robotis_icon_game_character_5: '알라(왼쪽))',\n                        robotis_icon_game_character_6: '알라(오른쪽)',\n                        robotis_icon_game_character_7: '유령',\n                        robotis_icon_game_character_8: '괴물',\n                        robotis_icon_game_character_9: '바이러스',\n                        robotis_icon_game_character_10: '세균',\n                        robotis_icon_game_character_11: '나는 알쥐(왼쪽)',\n                        robotis_icon_game_character_12: '나는 알쥐(오른쪽)',\n                        robotis_icon_game_character_13: '나는 알쥐(정면)',\n                        robotis_icon_game_character_14: '메달',\n                        robotis_icon_game_character_15: '돈(G)',\n                        robotis_icon_game_character_16: '돈($)',\n                        robotis_icon_game_character_17: '하트',\n                        robotis_icon_game_character_18: '폭탄',\n                        robotis_icon_game_character_19: '불',\n                        robotis_icon_game_character_20: '구름1',\n                        robotis_icon_game_character_21: '구름2',\n                        robotis_icon_game_character_22: '포탄1',\n                        robotis_icon_game_character_23: '포탄2',\n                        robotis_icon_game_character_24: '대포(수평)',\n                        robotis_icon_game_character_25: '대포(수직)',\n                        robotis_icon_game_character_26: '레이저(수직)',\n                        robotis_icon_game_character_27: '게이저(수평)',\n                        robotis_icon_game_character_28: '화살(수평)',\n                        robotis_icon_game_character_29: '화살(수직)',\n                        robotis_icon_game_character_30: '미사일(U)',\n                        robotis_icon_game_character_31: '미사일(D)',\n                        robotis_icon_game_character_32: '미사일(L)',\n                        robotis_icon_game_character_33: '미사일(R)',\n                        robotis_icon_game_character_34: '낙하산',\n                        robotis_icon_game_character_35: '폭발1',\n                        robotis_icon_game_character_36: '폭발2',\n                        robotis_icon_game_character_37: '조준경',\n                        robotis_icon_game_character_38: '가위',\n                        robotis_icon_game_character_39: '바위',\n                        robotis_icon_game_character_40: '보',\n                        robotis_icon_game_character_41: '걷는 사람1',\n                        robotis_icon_game_character_42: '걷는 사람2',\n                        robotis_icon_game_character_43: '뛰는 사람1',\n                        robotis_icon_game_character_44: '뛰는 사람2',\n                        robotis_speed_fast: '빠른 속도',\n                        robotis_speed_midium: '중간 속도',\n                        robotis_speed_slow: '느린 속도',\n                        robotis_clockwise: '시계방향',\n                        robotis_counterclockwise: '반시계방향',\n                        robotis_up: '들기',\n                        robotis_down: '내리기',\n                        robotis_if_greater: '크면',\n                        robotis_if_smaller: '작으면',\n                        robotis_if_equal: '같으면',\n                        robotis_front_right: '앞 오른쪽',\n                        robotis_front_left: '앞 왼쪽',\n                        robotis_bottom_right: '아래 오른쪽',\n                        robotis_bottom_left: '아래 왼쪽',\n                        robotis_side_right: '우측',\n                        robotis_side_left: '좌측',\n                        robotis_front_ir_sensor: '적외선센서',\n                        robotis_distance_sensor: '거리센서',\n                        robotis_front: '앞',\n                        robotis_right: '오른쪽',\n                        robotis_left_wheel: '왼쪽바퀴',\n                        robotis_right_wheel: '오른쪽바퀴',\n                        // https://namu.wiki/w/%EC%9D%8C%ED%91%9C\n                        robotis_beat_sound_8th_note: '8분음표 (♪)',\n                        robotis_beat_sound_dotted_8th_note: '점8분음표 (♪.)',\n                        robotis_beat_sound_quarter_note: '4분음표 (♩)',\n                        robotis_beat_sound_dotted_quarter_note: '점4분음표 (♩.)',\n                        robotis_beat_sound_half_note: '2분음표 (𝅗𝅥)',\n                        robotis_beat_sound_dotted_half_note: '점2분음표 (𝅗𝅥.)',\n                        robotis_beat_sound_whole_note: '온음표 (𝅝)',\n                        robotis_beat_sound_dotted_note: '점온음표 (𝅝.)',\n                        robotis_beat_rest_8th_note: '8분쉼표 (𝄾)',\n                        robotis_beat_rest_dotted_8th_note: '점8분쉼표 (𝄾.)',\n                        robotis_beat_rest_quarter_note: '4분쉼표 (𝄽)',\n                        robotis_beat_rest_dotted_quarter_note: '점4분쉼표 (𝄽.)',\n                        robotis_beat_rest_half_note: '2분쉼표 (𝄼)',\n                        robotis_beat_rest_dotted_half_note: '점2분쉼표 (𝄼˙)',\n                        robotis_beat_rest_whole_note: '온쉼표 (𝄻)',\n                        robotis_beat_rest_dotted_note: '점온쉼표 (𝄻˙)',\n                        robotis_line_cross_type_0: '|',\n                        robotis_line_cross_type_1: ' (공백)',\n                        robotis_line_cross_type_5: '🞣',\n                        robotis_line_cross_type_6: '⏉',\n                        robotis_line_cross_type_7: '⊣',\n                        robotis_line_cross_type_8: '⊢',\n                        robotis_line_cross_type_9: '⏋',\n                        robotis_line_cross_type_10: '⎾',\n                        robotis_line_cross_type_11: '¦',\n                        robotis_line_cross_type_12: '︙',\n\n                        robotis_connected: '연결',\n                        robotis_disconnected: '없음',\n                        robotis_ai_camera_mode_face_recognition: '얼굴인식',\n                        robotis_ai_camera_mode_object_tracking: '물체추적',\n                        robotis_ai_camera_mode_object_recognition: '물체인식',\n                        robotis_ai_camera_mode_line_tracking: '라인인식',\n                        robotis_ai_camera_mode_color_recognition: '색상인식',\n                        robotis_ai_camera_mode_tag_recognition: '태그인식',\n                        robotis_ai_camera_mode_object_classification: '물체분류',\n                        robotis_ai_camera_block: '사각형',\n                        robotis_ai_camera_arrow: '화살표',\n                        robotis_ai_camera_center_block_center_x: '중심 X좌표',\n                        robotis_ai_camera_center_block_center_y: '중심 Y좌표',\n                        robotis_ai_camera_center_block_width: '너비',\n                        robotis_ai_camera_center_block_height: '높이',\n                        robotis_ai_camera_center_leared_id: '학습ID',\n                        robotis_ai_camera_center_arrow_origin_x: '시작점 X좌표',\n                        robotis_ai_camera_center_arrow_origin_y: '시작점 Y좌표',\n                        robotis_ai_camera_center_arrow_target_x: '끝점 X좌표',\n                        robotis_ai_camera_center_arrow_target_y: '끝점 Y좌표',\n                    },\n                },\n                en: {\n                    template: {\n                        // 주행 제어\n                        robotis_koalabot_lite_drive_simple: 'Move %2 with velocity %1 %3',\n                        robotis_koalabot_lite_drive_advanced:\n                            'Left wheel %2 with velocity %1, right wheel %4 with velocity %3 %5',\n                        robotis_koalabot_lite_drive_seperate:\n                            '%1 wheel rotate %3 with velocity %2 %4',\n                        robotis_koalabot_lite_drive_angle: 'Both wheels rotate %1 degree %2 %3',\n                        robotis_koalabot_lite_go_distance: 'Moves %2 %1 cm %3',\n                        robotis_koalabot_lite_turn_angle: 'Rotates %1 degree(s) %2 in place %3',\n                        robotis_koalabot_lite_follow_line: 'Follow line with %1 speed %2',\n                        robotis_koalabot_lite_stop_at_cross: 'Stop at cross %1 %2',\n                        robotis_koalabot_lite_turn_at_line: '%1 at cross and stop %2',\n                        robotis_koalabot_lite_drive_stop: 'Stop %1',\n\n                        // 값 블록\n                        robotis_koalabot_lite_cm_ir_value: 'Value of %1 IR Sensor',\n                        robotis_koalabot_lite_cm_ir_compare:\n                            'If the number %1 IR sensor value is %3 than %2',\n                        robotis_koalabot_lite_detectFrontObj:\n                            'If there is an object in front of %1',\n                        robotis_koalabot_lite_cm_btn_value: \"When the robot's %1 button is pressed\",\n                        robotis_koalabot_lite_cm_joystick_value:\n                            \"If the robot's yellow joystick position is %1\",\n                        robotis_koalabot_lite_mic: 'MIC volume(dB)',\n                        robotis_koalabot_lite_detectSound_compare:\n                            'If sound is detected from %1 of the robot',\n                        robotis_koalabot_lite_imu: \"%1 axis' %2 value\",\n                        robotis_koalabot_lite_roll_pitch: '%1 value of the controller',\n                        robotis_koalabot_lite_distance_value: '%1 value',\n                        robotis_koalabot_lite_distance_compare: 'If %1 value is %3 than %2',\n                        robotis_koalabot_lite_line_cross_compare: 'If the type of cross is %1',\n                        robotis_koalabot_lite_dxl_value: 'The angle of ID %1',\n\n                        // 소리\n                        robotis_koalabot_lite_scale_simple:\n                            'Play the note %2 as %3 in octave %1 %4',\n                        robotis_koalabot_lite_scale_advanced:\n                            'Play the note %2 in octave %1 for %3 beat %4',\n                        robotis_koalabot_lite_rest_simple: '%1 %2',\n                        robotis_koalabot_lite_rest_advanced: 'Rest %1 beat %2',\n                        robotis_koalabot_lite_beat_per_minute: 'Set playing speed to %1 %2',\n                        robotis_koalabot_lite_Hello: 'Robot speaks %1 %2',\n                        robotis_koalabot_lite_effectSound: 'Play sound effect %1 %2',\n                        robotis_koalabot_lite_record: 'Record to sound slot %1 %2',\n                        robotis_koalabot_lite_playRecord: 'Play sound from slot %1 %2',\n\n                        // LCD 제어\n                        robotis_koalabot_lite_screen: 'Set screen expression to %1 %2 %3',\n                        robotis_koalabot_lite_anim_screen: 'Set screen animation to %1 %2 %3',\n                        robotis_koalabot_lite_icon_screen_food_plant:\n                            'Display %1 from [Food/Plants] at position (%2, %3) in size %4 %5',\n                        robotis_koalabot_lite_icon_screen_animal_human:\n                            'Display %1 from [Animal/Human] at position (%2, %3) in size %4 %5',\n                        robotis_koalabot_lite_icon_screen_object_tool:\n                            'Display %1 from [Object/Tool] at position (%2, %3) in size %4 %5',\n                        robotis_koalabot_lite_icon_screen_vehicle_number:\n                            'Display %1 from [Vehicle/Number] at position (%2, %3) in size %4 %5',\n                        robotis_koalabot_lite_icon_screen_game_character:\n                            'Display %1 from [Game/Character] at position (%2, %3) in size %4 %5',\n                        robotis_koalabot_lite_text_screen:\n                            'Display %1 in %5 in %4 at (%2, %3) on the screen %6',\n                        robotis_koalabot_lite_text_screen_redraw:\n                            'Newly display %1 in %4 at (%2, %3) %5',\n                        robotis_koalabot_lite_pixel: 'Display %3 colored dot at (%1, %2) %4',\n                        robotis_koalabot_lite_LCDBright: 'Set screen brightness as %1 %2',\n                        robotis_koalabot_lite_LCDColor: 'Set screen color as %1 %2',\n\n                        // LED 제어\n                        robotis_koalabot_lite_cm_led: \"%2 the robot's %1 LED %3\",\n                        robotis_koalabot_lite_cm_led_pattern: 'LED %1 blinks at a %2 speed %3',\n\n                        // AI Camera 값 블록\n                        robotis_koalabot_lite_ai_camera_connection_status: 'AI Camera: If %1',\n                        robotis_koalabot_lite_ai_camera_if_detected:\n                            'AI Camera: If %1 is displayed',\n\n                        robotis_koalabot_lite_ai_camera_block_value_closest_to_center:\n                            'AI Camera: %1 of the rectangle closest to the center of the screen',\n                        robotis_koalabot_lite_ai_camera_arrow_value_closest_to_center:\n                            'AI Camera: %1 of the arrow closest to the center of the screen',\n                        robotis_koalabot_lite_ai_camera_number_of_learned_id:\n                            'AI Camera: the number of learned ID',\n                        robotis_koalabot_lite_ai_camera_block_value_of_id:\n                            'AI Camera: %2 of rectangle with detected ID %1',\n                        robotis_koalabot_lite_ai_camera_arrow_value_of_id:\n                            'AI Camera: %2 of arrow with detected ID %1',\n\n                        robotis_koalabot_lite_ai_camera_if_learned_id:\n                            'AI Camera: If learned data with ID %1',\n                        robotis_koalabot_lite_ai_camera_if_detected_id_type:\n                            'AI Camera: If learned %2 data with ID %1',\n\n                        // AI 카메라 제어\n                        robotis_koalabot_lite_ai_camera_set_mode: 'AI Camera: Set mode to %1 %2',\n                        robotis_koalabot_lite_ai_camera_print_custom_text:\n                            'AI Camera: Display %3 at screen position (%1, %2) %4',\n                        robotis_koalabot_lite_ai_camera_clear_custom_text:\n                            'AI Camera: Clear screen text %1',\n                    },\n                    Blocks: {\n                        // Driving Control\n                        robotis_koalabot_lite_drive_simple:\n                            'Drive the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %',\n                        robotis_koalabot_lite_drive_advanced:\n                            'Rotate the left and right wheels of the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %',\n                        robotis_koalabot_lite_drive_seperate:\n                            'Rotate the specified wheel of the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %',\n                        robotis_koalabot_lite_drive_angle:\n                            'Rotate the two wheels of the robot in the specified direction and by the specified angle\\nAngle range: -5760 ~ 5760\\nAngle unit: degrees',\n                        robotis_koalabot_lite_go_distance:\n                            'Move forward or backward by the specified distance\\nDistance range: -1000 ~ 1000\\nDistance unit: mm',\n                        robotis_koalabot_lite_turn_angle:\n                            'Rotate in place by the specified angle and direction\\nAngle range: -360 ~ 360\\nAngle unit: degrees',\n                        robotis_koalabot_lite_follow_line:\n                            'Start following the line at the specified speed',\n                        robotis_koalabot_lite_stop_at_cross: 'Stop at the specified intersection',\n                        robotis_koalabot_lite_turn_at_line:\n                            'Make the specified turn at the intersection and stop',\n                        robotis_koalabot_lite_drive_stop: 'Stop the robot',\n\n                        // Value Blocks\n                        robotis_koalabot_lite_cm_ir_value:\n                            'IR sensor value of the specified number (range: 0 ~ 200)',\n                        robotis_koalabot_lite_cm_ir_compare:\n                            \"If the IR sensor value of the specified number matches the specified value, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_detectFrontObj:\n                            \"If an object is detected in front of the specified sensor, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_cm_btn_value:\n                            \"If the specified button is clicked, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_cm_joystick_value:\n                            \"If the joystick position is in the specified state, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_mic:\n                            'Displays the intensity of the sound detected by the microphone in decibels (dB).',\n                        robotis_koalabot_lite_detectSound_compare:\n                            \"If the direction of the sound matches the specified direction, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_imu:\n                            'Value of the specified accelerometer/gyro sensor on the specified axis\\nRange: -100 ~ 100',\n                        robotis_koalabot_lite_roll_pitch:\n                            'roll/pitch value\\nroll: -180° ~ 180°, pitch: -90° ~ 90°',\n                        robotis_koalabot_lite_distance_value:\n                            'Value of the specified sensor\\nDistance range: 0 ~ 1000mm\\nIlluminance range: 0 ~ 100%\\nButton sensor: 0 (not pressed) / 1 (pressed)',\n                        robotis_koalabot_lite_distance_compare:\n                            \"If the specified equation of the specified sensor value is correct, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_line_cross_compare:\n                            \"If the specified intersection shape is correct, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_dxl_value:\n                            'Position angle value of the specified motor\\nRange: -180° ~ 180°',\n\n                        // Sound\n                        robotis_koalabot_lite_scale_simple:\n                            'Play with the specified octave, scale, and note',\n                        robotis_koalabot_lite_scale_advanced:\n                            'Play with the specified octave, scale, and beat',\n                        robotis_koalabot_lite_rest_simple: 'Rest for the specified rest note',\n                        robotis_koalabot_lite_rest_advanced: 'Rest for the specified beat',\n                        robotis_koalabot_lite_beat_per_minute:\n                            'Set the playing speed (BPM)\\nRange: 10 ~ 600',\n                        robotis_koalabot_lite_Hello: 'Play the specified voice of the robot',\n                        robotis_koalabot_lite_effectSound:\n                            'Play the specified sound effect of the robot',\n                        robotis_koalabot_lite_record:\n                            'Record and save to the specified number storage',\n                        robotis_koalabot_lite_playRecord:\n                            'Play the recorded voice in the specified number storage',\n\n                        // LCD Control\n                        robotis_koalabot_lite_screen:\n                            'Set the character and expression of the controller screen background',\n                        robotis_koalabot_lite_anim_screen:\n                            'Set the character and expression of the controller screen animation',\n                        robotis_koalabot_lite_icon_screen_food_plant:\n                            'Set the position and size of a specific icon in [food/plant] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_koalabot_lite_icon_screen_animal_human:\n                            'Set the position and size of a specific icon in [animal/human] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_koalabot_lite_icon_screen_object_tool:\n                            'Set the position and size of a specific icon in [object/tool] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_koalabot_lite_icon_screen_vehicle_number:\n                            'Set the position and size of a specific icon in [vehicle/number] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_koalabot_lite_icon_screen_game_character:\n                            'Set the position and size of a specific icon in [game/character] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_koalabot_lite_text_screen:\n                            'Set the position, font size, and color of the specified text on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n                        robotis_koalabot_lite_text_screen_redraw:\n                            'Set the position and color of the specified text to be newly displayed (clearing the background of the text) on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_koalabot_lite_pixel:\n                            'Set the position and color of the dot to be displayed on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n                        robotis_koalabot_lite_LCDBright:\n                            'Set the screen brightness\\nBrightness range: 0% ~ 100%',\n                        robotis_koalabot_lite_LCDColor: 'Set the screen color',\n\n                        // LED Control\n                        robotis_koalabot_lite_cm_led:\n                            'Turn the specified LED of the controller on or off',\n                        robotis_koalabot_lite_cm_led_pattern:\n                            'Set the blinking pattern of LEDs of the controller',\n\n                        // AI Camera Value Blocks\n                        robotis_koalabot_lite_ai_camera_connection_status:\n                            \"If the AI camera is connected, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_ai_camera_if_detected:\n                            \"If the selected symbol (rectangle/arrow) is displayed on the LCD screen of the AI camera, it is determined as 'true'; otherwise, 'false'.\",\n\n                        robotis_koalabot_lite_ai_camera_block_value_closest_to_center:\n                            'X coordinate/Y coordinate/width/height/learning ID of the rectangle closest to the center of the AI camera screen',\n                        robotis_koalabot_lite_ai_camera_arrow_value_closest_to_center:\n                            'Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate/learning ID of the arrow closest to the center of the AI camera screen',\n                        robotis_koalabot_lite_ai_camera_number_of_learned_id:\n                            'Number of IDs learned by the AI camera',\n                        robotis_koalabot_lite_ai_camera_block_value_of_id:\n                            'X coordinate/Y coordinate/width/height of the rectangle with the specified ID detected by the AI camera',\n                        robotis_koalabot_lite_ai_camera_arrow_value_of_id:\n                            'Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate of the arrow with the specified ID detected by the AI camera',\n\n                        robotis_koalabot_lite_ai_camera_if_learned_id:\n                            \"If the AI camera has learned data with the specified ID, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_koalabot_lite_ai_camera_if_detected_id_type:\n                            \"If the AI camera has learned the specified data (rectangle/arrow) with the specified ID, it is determined as 'true'; otherwise, 'false'.\",\n\n                        // AI Camera Control\n                        robotis_koalabot_lite_ai_camera_set_mode: 'Set the mode of the AI camera',\n                        robotis_koalabot_lite_ai_camera_print_custom_text:\n                            'Print the specified text at the specified position on the AI camera screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n                        robotis_koalabot_lite_ai_camera_clear_custom_text:\n                            'Clear all texts displayed on the AI camera screen',\n                    },\n\n                    Blocks: {\n                        robotis_red: 'Red',\n                        robotis_orange: 'Orange',\n                        robotis_yellow: 'Yellow',\n                        robotis_green: 'Green',\n                        robotis_blue: 'Blue',\n                        robotis_brown: 'Brown',\n                        robotis_black: 'Black',\n                        robotis_white: 'White',\n                        robotis_left: 'Left',\n                        robotis_center: 'Center',\n                        robotis_right: 'Right',\n                        robotis_both: 'Both',\n                        robotis_rgee: 'R-GEE',\n                        robotis_rla: 'KODALA',\n                        robotis_kkokdu: 'TIG',\n                        robotis_korean1: 'Hello!',\n                        robotis_korean2: 'Great to see you.',\n                        robotis_korean3: 'Okay ~',\n                        robotis_korean4: 'No!',\n                        robotis_korean5: \"I don't know.\",\n                        robotis_korean6: 'I like it.',\n                        robotis_korean7: \"I don't like it.\",\n                        robotis_korean8: 'What is your name? ',\n                        robotis_korean9: 'How can I help you? ',\n                        robotis_korean10: 'Great job! ',\n                        robotis_korean11: \"It's alright.\",\n                        robotis_korean12: \"Let's do it again! \",\n                        robotis_korean13: 'Thank you! ',\n                        robotis_korean14: 'Can you say that one more time?',\n                        robotis_korean15: 'Awesome!',\n                        robotis_korean16: \"I'm excited! \",\n                        robotis_korean17: \"I'm having a great time! \",\n                        robotis_korean18: \"I'm sorry.\",\n                        robotis_korean19: \"I'm angry! \",\n                        robotis_korean20: \"I'm embarassed.\",\n                        robotis_korean21: \"I'm scared.\",\n                        robotis_korean22: \"I'm upset.\",\n                        robotis_korean23: 'I love you.',\n                        robotis_korean24: 'Very pretty! ',\n                        robotis_korean25: 'Interesting.',\n                        robotis_korean26: \"I'm nervous.\",\n                        robotis_korean27: \"Let's move forward! \",\n                        robotis_korean28: \"Let's move backward! \",\n                        robotis_korean29: \"Let's stand up! \",\n                        robotis_korean30: 'Did you fall down? ',\n                        robotis_korean31: 'Oh Yeah~',\n                        robotis_korean32: 'Sweet! ',\n                        robotis_korean33: 'Oh no',\n                        robotis_korean34: 'My My ',\n                        robotis_korean35: 'Whoo hoo! ',\n                        robotis_korean36: 'Ha Ha Ha',\n                        robotis_korean37: 'Ho Ho Ho ',\n                        robotis_korean38: \"I'm sleepy.\",\n                        robotis_korean39: 'Sing me a bedtime song! ',\n                        robotis_korean40: 'Hello!',\n                        robotis_korean41: \"I'm hungry.\",\n                        robotis_korean42: \"I'm craving an acorn! \",\n                        robotis_korean43: 'I want to take a bath! ',\n                        robotis_korean44: 'Time for a bath! ',\n                        robotis_korean45: \"I'm bored. \",\n                        robotis_korean46: 'Do you want a snack? ',\n                        robotis_korean47: \"I'm sick.\",\n                        robotis_korean48: 'Do you have any medicine? ',\n                        robotis_korean49: 'Where do we have to go? ',\n                        robotis_korean50: \"We're here! \",\n                        robotis_korean51: \"Let's go to the left side! \",\n                        robotis_korean52: \"Let's go to the right side! \",\n                        robotis_korean53: 'Oh my, you scared me! ',\n                        robotis_korean54: 'Found you! ',\n                        robotis_korean55: \"There's nothing here. \",\n                        robotis_korean56: 'Did you call me?',\n                        robotis_korean57: 'Please let me down. ',\n                        robotis_korean58: 'Oops! ',\n                        robotis_korean59: 'Hmmph! ',\n                        robotis_korean60: 'Eek! ',\n                        robotis_dog: 'Dog',\n                        robotis_frog: 'Frog',\n                        robotis_cat: 'Cat',\n                        robotis_chicken: 'Rooster',\n                        robotis_tiger: 'Tiger',\n                        robotis_mouse: 'Mouse',\n                        robotis_whistle: 'Whistle',\n                        robotis_ambul: 'Ambulance',\n                        robotis_Horn: 'CarHorn',\n                        robotis_siren: 'Siren',\n                        robotis_gun: 'Gunshot',\n                        robotis_clap: 'Clap',\n                        robotis_melody1: 'Melody1',\n                        robotis_melody2: 'Melody2',\n                        robotis_melody3: 'Melody3',\n                        robotis_melody4: 'Melody4',\n                        robotis_forward: 'Forward',\n                        robotis_backward: 'Backward',\n                        robotis_acceleration: 'acceleration',\n                        robotis_gyro: 'gyro',\n                        robotis_run: 'Run',\n                        robotis_cancel: 'Cancel',\n                        robotis_push: 'Pressed',\n                        robotis_notPush: 'Unpressed',\n                        robotis_play: 'Play',\n                        robotis_rest: 'Rest',\n                        robotis_face01: 'Haha',\n                        robotis_face02: 'Smile',\n                        robotis_face03: 'Laugh',\n                        robotis_face04: 'Yum Yum',\n                        robotis_face05: 'Scared',\n                        robotis_face06: 'Uncomfortable',\n                        robotis_face07: 'Confused',\n                        robotis_face08: 'Dazed',\n                        robotis_face09: 'Yell',\n                        robotis_face10: 'Angry',\n                        robotis_face11: 'Sniff (Left)',\n                        robotis_face12: 'Sniff (Right)',\n                        robotis_face13: 'Sniff (Down)',\n                        robotis_face14: 'Whew',\n                        robotis_face15: 'Faint',\n                        robotis_face16: 'Dizzy',\n                        robotis_face17: 'Yawn',\n                        robotis_face18: 'Sleepy',\n                        robotis_face19: 'Sleep',\n                        robotis_face20: 'Sad',\n                        robotis_face21: 'Cry',\n                        robotis_face22: 'Bath',\n                        robotis_face23: 'Heart-Eyes',\n\n                        robotis_pattern1: 'Pattern1',\n                        robotis_pattern2: 'Pattern2',\n                        robotis_pattern3: 'Pattern3',\n                        robotis_moveF: 'Forward',\n                        robotis_moveB: 'Backward',\n                        robotis_moveL: 'LeftTurn',\n                        robotis_moveR: 'RightTurn',\n                        robotis_moveU: 'U-turn',\n                        robotis_moveL_in_place: 'Turn left in place',\n                        robotis_moveR_in_place: 'Trun right in place',\n                        robotis_moveU_in_place: 'U-turn in place',\n                        robotis_moveRG1: 'Stand',\n                        robotis_moveRG2: 'Sit',\n                        robotis_moveRG3: 'Struggle',\n                        robotis_moveRG4: 'RaiseFeet',\n                        robotis_fast: 'Fast',\n                        robotis_normal: 'Normal',\n                        robotis_slow: 'Slow',\n                        robotis_stop: 'Stop',\n                        robotis_roll: 'Left-right rotate angle (roll)',\n                        robotis_pitch: 'Forward-backward rotate angle (pitch)',\n                        robotis_direction_forward: 'Forward',\n                        robotis_direction_backward: 'Backward',\n                        robotis_stMotion1: 'Standard',\n                        robotis_stMotion2: 'Forward',\n                        robotis_stMotion3: 'TurnRight',\n                        robotis_stMotion4: 'TurnLeft',\n                        robotis_stMotion5: 'Backward',\n                        robotis_stMotion6: 'ToRight',\n                        robotis_stMotion7: 'ToLeft',\n                        robotis_stMotion8: 'TurnAroundRight',\n                        robotis_stMotion9: 'TurnAroundLeft',\n                        robotis_spMotion1: 'RightHandUp',\n                        robotis_spMotion2: 'RightHandDown',\n                        robotis_spMotion3: 'LeftHandUp',\n                        robotis_spMotion4: 'LeftHandDown',\n                        robotis_spMotion5: 'BothHandsUp',\n                        robotis_spMotion6: 'BothHandsDown',\n                        robotis_spMotion7: 'FallBackward',\n                        robotis_spMotion8: 'FallForward',\n                        robotis_spMotion9: 'StandForward',\n                        robotis_spMotion10: 'StandBackward',\n                        robotis_spMotion11: 'Defence',\n                        robotis_spMotion12: 'Offense1',\n                        robotis_spMotion13: 'Offense2',\n                        robotis_spMotion14: 'Offense3',\n                        robotis_spMotion15: 'Offense4',\n                        robotis_screen1: 'Sissor',\n                        robotis_screen2: 'Rock',\n                        robotis_screen3: 'Paper',\n                        robotis_icon_food_plant_1: 'Milk',\n                        robotis_icon_food_plant_2: 'Tree',\n                        robotis_icon_food_plant_3: 'Soup',\n                        robotis_icon_food_plant_4: 'Cake',\n                        robotis_icon_food_plant_5: 'Water',\n                        robotis_icon_food_plant_6: 'Juice',\n                        robotis_icon_food_plant_7: 'Carrot',\n                        robotis_icon_food_plant_8: 'Apple',\n                        robotis_icon_food_plant_9: 'Orange',\n                        robotis_icon_food_plant_10: 'Meat',\n                        robotis_icon_food_plant_11: 'Flowerpot',\n                        robotis_icon_food_plant_12: 'Rose',\n                        robotis_icon_food_plant_13: 'Grape',\n                        robotis_icon_food_plant_14: 'Potato',\n                        robotis_icon_food_plant_15: 'Candy',\n                        robotis_icon_food_plant_16: 'Cheese',\n                        robotis_icon_food_plant_17: 'Bread',\n                        robotis_icon_food_plant_18: 'Flowers',\n                        robotis_icon_food_plant_19: 'Coffee',\n                        robotis_icon_food_plant_20: 'Tulip',\n                        robotis_icon_food_plant_21: 'Banana',\n                        robotis_icon_food_plant_22: 'Fruits',\n                        robotis_icon_food_plant_23: 'Hamburger',\n                        robotis_icon_food_plant_24: 'Pizza',\n                        robotis_icon_animal_human_1: 'Shiba Dog',\n                        robotis_icon_animal_human_2: 'Puppy',\n                        robotis_icon_animal_human_3: 'Bear',\n                        robotis_icon_animal_human_4: 'Bird',\n                        robotis_icon_animal_human_5: 'Duck',\n                        robotis_icon_animal_human_6: 'Lion',\n                        robotis_icon_animal_human_7: 'Tiger',\n                        robotis_icon_animal_human_8: 'Horse',\n                        robotis_icon_animal_human_9: 'Sheep',\n                        robotis_icon_animal_human_10: 'Shark 1 (Left)',\n                        robotis_icon_animal_human_11: 'Shark 1 (Right)',\n                        robotis_icon_animal_human_12: 'Shark 2 (Left)',\n                        robotis_icon_animal_human_13: 'Shark 2 (Right)',\n                        robotis_icon_animal_human_14: 'Fish 1',\n                        robotis_icon_animal_human_15: 'Fish 2',\n                        robotis_icon_animal_human_16: 'Fish 3',\n                        robotis_icon_animal_human_17: 'Octopus',\n                        robotis_icon_animal_human_18: 'Monkey',\n                        robotis_icon_animal_human_19: 'Chicken',\n                        robotis_icon_animal_human_20: 'Pig',\n                        robotis_icon_animal_human_21: 'Person (Chubby)',\n                        robotis_icon_animal_human_22: 'Person (Swimsuit)',\n                        robotis_icon_animal_human_23: 'Baby',\n                        robotis_icon_animal_human_24: 'Person (Running)',\n                        robotis_icon_animal_human_25: 'Person (Singing)',\n                        robotis_icon_animal_human_26: 'Person (Sitting)',\n                        robotis_icon_animal_human_27: 'Person (Angry)',\n                        robotis_icon_animal_human_28: 'Person (Cheering)',\n                        robotis_icon_animal_human_29: 'King',\n                        robotis_icon_animal_human_30: 'Prince',\n                        robotis_icon_animal_human_31: 'Princess',\n                        robotis_icon_animal_human_32: 'Chef',\n                        robotis_icon_animal_human_33: 'Doctor',\n                        robotis_icon_animal_human_34: 'Nurse',\n                        robotis_icon_object_tool_1: 'Bag',\n                        robotis_icon_object_tool_2: 'Box',\n                        robotis_icon_object_tool_3: 'Mug',\n                        robotis_icon_object_tool_4: 'Hat (Fedora)',\n                        robotis_icon_object_tool_5: 'Hat (Cap)',\n                        robotis_icon_object_tool_6: 'Key',\n                        robotis_icon_object_tool_7: 'Toy',\n                        robotis_icon_object_tool_8: 'Book',\n                        robotis_icon_object_tool_9: 'Teddy Bear',\n                        robotis_icon_object_tool_10: 'Drum',\n                        robotis_icon_object_tool_11: 'Notebook',\n                        robotis_icon_object_tool_12: 'Pen',\n                        robotis_icon_object_tool_13: 'Desk',\n                        robotis_icon_object_tool_14: 'Table',\n                        robotis_icon_object_tool_15: 'Chair',\n                        robotis_icon_object_tool_16: 'Bed',\n                        robotis_icon_object_tool_17: 'Tent',\n                        robotis_icon_object_tool_18: 'Plate',\n                        robotis_icon_object_tool_19: 'Soccer Ball',\n                        robotis_icon_object_tool_20: 'Bell',\n                        robotis_icon_object_tool_21: 'Watch',\n                        robotis_icon_object_tool_22: 'Shoes',\n                        robotis_icon_object_tool_23: 'Lamp',\n                        robotis_icon_object_tool_24: 'Radio',\n                        robotis_icon_object_tool_25: 'Banknote',\n                        robotis_icon_object_tool_26: 'Ruler',\n                        robotis_icon_object_tool_27: 'Camera',\n                        robotis_icon_object_tool_28: 'Spoon',\n                        robotis_icon_object_tool_29: 'Keyboard',\n                        robotis_icon_object_tool_30: 'Calendar',\n                        robotis_icon_object_tool_31: 'Knife',\n                        robotis_icon_object_tool_32: 'Balloon',\n                        robotis_icon_object_tool_33: 'Water Bottle',\n                        robotis_icon_object_tool_34: 'Wooden Stick (Horizontal)',\n                        robotis_icon_object_tool_35: 'Wooden Stick (Vertical)',\n                        robotis_icon_object_tool_36: 'Fishing Hook',\n                        robotis_icon_vehicle_number_1: 'Car',\n                        robotis_icon_vehicle_number_2: 'Bus',\n                        robotis_icon_vehicle_number_3: 'Truck',\n                        robotis_icon_vehicle_number_4: 'Jeep',\n                        robotis_icon_vehicle_number_5: 'Bicycle',\n                        robotis_icon_vehicle_number_6: 'Subway',\n                        robotis_icon_vehicle_number_7: 'Train',\n                        robotis_icon_vehicle_number_8: 'Airplane',\n                        robotis_icon_vehicle_number_9: 'Fighter Jet (Vertical)',\n                        robotis_icon_vehicle_number_10: 'Fighter Jet (Horizontal)',\n                        robotis_icon_vehicle_number_11: 'Rocket',\n                        robotis_icon_vehicle_number_12: 'Fishing Boat',\n                        robotis_icon_vehicle_number_13: 'Passenger Ship',\n                        robotis_icon_vehicle_number_14: 'Submarine (Left)',\n                        robotis_icon_vehicle_number_15: 'Submarine (Right)',\n                        robotis_icon_vehicle_number_16: 'Airplane (Left)',\n                        robotis_icon_vehicle_number_17: 'Airplane (Right)',\n                        robotis_icon_vehicle_number_18: 'Airplane (Top)',\n                        robotis_icon_vehicle_number_19: 'Spaceship (Left)',\n                        robotis_icon_vehicle_number_20: 'Spaceship (Right)',\n                        robotis_icon_vehicle_number_21: 'Spaceship (Top)',\n                        robotis_icon_vehicle_number_22: 'Dice (1)',\n                        robotis_icon_vehicle_number_23: 'Dice (2)',\n                        robotis_icon_vehicle_number_24: 'Dice (3)',\n                        robotis_icon_vehicle_number_25: 'Dice (4)',\n                        robotis_icon_vehicle_number_26: 'Dice (5)',\n                        robotis_icon_vehicle_number_27: 'Dice (6)',\n                        robotis_icon_vehicle_number_28: '0',\n                        robotis_icon_vehicle_number_29: '1',\n                        robotis_icon_vehicle_number_30: '2',\n                        robotis_icon_vehicle_number_31: '3',\n                        robotis_icon_vehicle_number_32: '4',\n                        robotis_icon_vehicle_number_33: '5',\n                        robotis_icon_vehicle_number_34: '6',\n                        robotis_icon_vehicle_number_35: '7',\n                        robotis_icon_vehicle_number_36: '8',\n                        robotis_icon_vehicle_number_37: '9',\n                        robotis_icon_vehicle_number_38: '10',\n                        robotis_icon_game_character_1: 'R-GEE(F)',\n                        robotis_icon_game_character_2: 'R-GEE(L)',\n                        robotis_icon_game_character_3: 'R-GEE(R)',\n                        robotis_icon_game_character_4: 'KODALA(F)',\n                        robotis_icon_game_character_5: 'KODALA(L))',\n                        robotis_icon_game_character_6: 'KODALA(R)',\n                        robotis_icon_game_character_7: 'Ghost',\n                        robotis_icon_game_character_8: 'Monster',\n                        robotis_icon_game_character_9: 'Virus',\n                        robotis_icon_game_character_10: 'Bacteria',\n                        robotis_icon_game_character_11: 'Flying R-GEE (L)',\n                        robotis_icon_game_character_12: 'Flying R-GEE (R)',\n                        robotis_icon_game_character_13: 'Flying R-GEE (F)',\n                        robotis_icon_game_character_14: 'Medal',\n                        robotis_icon_game_character_15: 'Money (G)',\n                        robotis_icon_game_character_16: 'Money ($)',\n                        robotis_icon_game_character_17: 'Heart',\n                        robotis_icon_game_character_18: 'Bomb',\n                        robotis_icon_game_character_19: 'Fire',\n                        robotis_icon_game_character_20: 'Cloud 1',\n                        robotis_icon_game_character_21: 'Cloud 2',\n                        robotis_icon_game_character_22: 'Shell 1',\n                        robotis_icon_game_character_23: 'Shell 2',\n                        robotis_icon_game_character_24: 'Cannon (Horizontal)',\n                        robotis_icon_game_character_25: 'Cannon (Vertical)',\n                        robotis_icon_game_character_26: 'Laser (Vertical)',\n                        robotis_icon_game_character_27: 'Laser (Horizontal)',\n                        robotis_icon_game_character_28: 'Arrow (Horizontal)',\n                        robotis_icon_game_character_29: 'Arrow (Vertical)',\n                        robotis_icon_game_character_30: 'Missile (Up)',\n                        robotis_icon_game_character_31: 'Missile (Down)',\n                        robotis_icon_game_character_32: 'Missile (Left)',\n                        robotis_icon_game_character_33: 'Missile (Right)',\n                        robotis_icon_game_character_34: 'Parachute',\n                        robotis_icon_game_character_35: 'Explosion 1',\n                        robotis_icon_game_character_36: 'Explosion 2',\n                        robotis_icon_game_character_37: 'Scope',\n                        robotis_icon_game_character_38: 'Scissors',\n                        robotis_icon_game_character_39: 'Rock',\n                        robotis_icon_game_character_40: 'Paper',\n                        robotis_icon_game_character_41: 'Walking Person 1',\n                        robotis_icon_game_character_42: 'Walking Person 2',\n                        robotis_icon_game_character_43: 'Running Person 1',\n                        robotis_icon_game_character_44: 'Running Person 2',  \n                        robotis_speed_fast: 'Fast Speed',\n                        robotis_speed_midium: 'Medium Speed',\n                        robotis_speed_slow: 'Slow Speed',\n                        robotis_clockwise: 'Clockwise',\n                        robotis_counterclockwise: 'Counterclockwise',\n                        robotis_up: 'Lift',\n                        robotis_down: 'Lower',\n                        robotis_if_greater: 'If Greater',\n                        robotis_if_smaller: 'If Smaller',\n                        robotis_if_equal: 'If Equal',\n                        robotis_front_right: 'Front Right',\n                        robotis_front_left: 'Front Left',\n                        robotis_bottom_right: 'Bottom Right',\n                        robotis_bottom_left: 'Bottom Left',\n                        robotis_side_right: 'Right Edge',\n                        robotis_side_left: 'Left Edge',\n                        robotis_front_ir_sensor: 'Infrared Sensor',\n                        robotis_distance_sensor: 'Distance Sensor',\n                        robotis_front: 'Front',\n                        robotis_right: 'Right',\n                        robotis_left_wheel: 'Left Wheel',\n                        robotis_right_wheel: 'Right Wheel',\n                        robotis_beat_sound_8th_note: 'Eighth Note (♪)',\n                        robotis_beat_sound_dotted_8th_note: 'Dotted Eighth Note (♪.)',\n                        robotis_beat_sound_quarter_note: 'Quarter Note (♩)',\n                        robotis_beat_sound_dotted_quarter_note: 'Dotted Quarter Note (♩.)',\n                        robotis_beat_sound_half_note: 'Half Note (𝅗𝅥)',\n                        robotis_beat_sound_dotted_half_note: 'Dotted Half Note (𝅗𝅥.)',\n                        robotis_beat_sound_whole_note: 'Whole Note (𝅝)',\n                        robotis_beat_sound_dotted_note: 'Dotted Whole Note (𝅝.)',\n                        robotis_beat_rest_8th_note: 'Eighth Rest (𝄾)',\n                        robotis_beat_rest_dotted_8th_note: 'Dotted Eighth Rest (𝄾.)',\n                        robotis_beat_rest_quarter_note: 'Quarter Rest (𝄽)',\n                        robotis_beat_rest_dotted_quarter_note: 'Dotted Quarter Rest (𝄽.)',\n                        robotis_beat_rest_half_note: 'Half Rest (𝄼)',\n                        robotis_beat_rest_dotted_half_note: 'Dotted Half Rest (𝄼˙)',\n                        robotis_beat_rest_whole_note: 'Whole Rest (𝄻)',\n                        robotis_beat_rest_dotted_note: 'Dotted Whole Rest (𝄻˙)',\n                        robotis_line_cross_type_0: '|',\n                        robotis_line_cross_type_1: ' (Blank)',\n                        robotis_line_cross_type_5: '🞣',\n                        robotis_line_cross_type_6: '⏉',\n                        robotis_line_cross_type_7: '⊣',\n                        robotis_line_cross_type_8: '⊢',\n                        robotis_line_cross_type_9: '⏋',\n                        robotis_line_cross_type_10: '⎾',\n                        robotis_line_cross_type_11: '¦',\n                        robotis_line_cross_type_12: '︙',\n                        robotis_connected: 'Connected',\n                        robotis_disconnected: 'Not connected',\n                        robotis_ai_camera_mode_face_recognition: 'Face Recognition',\n                        robotis_ai_camera_mode_object_tracking: 'Object Tracking',\n                        robotis_ai_camera_mode_object_recognition: 'Object Recognition',\n                        robotis_ai_camera_mode_line_tracking: 'Line Tracking',\n                        robotis_ai_camera_mode_color_recognition: 'Color Recognition',\n                        robotis_ai_camera_mode_tag_recognition: 'Tag Recognition',\n                        robotis_ai_camera_mode_object_classification: 'Object Classification',\n                        robotis_ai_camera_block: 'Block',\n                        robotis_ai_camera_arrow: 'Arrow',\n                        robotis_ai_camera_center_block_center_x: 'Center X Coordinate',\n                        robotis_ai_camera_center_block_center_y: 'Center Y Coordinate',\n                        robotis_ai_camera_center_block_width: 'Width',\n                        robotis_ai_camera_center_block_height: 'Height',\n                        robotis_ai_camera_center_leared_id: 'Learned ID',\n                        robotis_ai_camera_center_arrow_origin_x: 'Start X Coordinate',\n                        robotis_ai_camera_center_arrow_origin_y: 'Start Y Coordinate',\n                        robotis_ai_camera_center_arrow_target_x: 'End X Coordinate',\n                        robotis_ai_camera_center_arrow_target_y: 'End Y Coordinate',\n                    },\n                },\n            };\n        }\n        getBlocks() {\n            return {\n                robotis_koalabot_lite_drive_simple: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '2'],\n                                [Lang.Blocks.robotis_moveL_in_place, '3'],\n                                [Lang.Blocks.robotis_moveR_in_place, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [5, null, null],\n                        type: 'robotis_koalabot_lite_drive_simple',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        const speed = script.getNumberValue('SPEED', script);\n                        const direction = script.getField('DIRECTION', script);\n\n                        const data_instruction = INST_WRITE;\n                        const data_address = 710;\n                        const data_length = 2;\n                        let data_value = 0;\n\n                        switch (direction) {\n                            case '1':\n                                data_value = speed * 256 + speed;\n                                break;\n                            case '2':\n                                data_value = (256 - speed) * 256 + (256 - speed);\n                                break;\n                            case '3':\n                                data_value = speed * 256 + (256 - speed);\n                                break;\n                            case '4':\n                                data_value = (256 - speed) * 256 + speed;\n                                break;\n                            default:\n                                data_value = 0;\n                                break;\n                        }\n\n                        const data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.go_simple(%1, %2)'],\n                    },\n                },\n                robotis_koalabot_lite_drive_advanced: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['5'],\n                            },\n                            null,\n                            {\n                                type: 'number',\n                                params: ['5'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_drive_advanced',\n                    },\n                    paramsKeyMap: {\n                        LEFT_SPEED: 0,\n                        LEFT_DIRECTION: 1,\n                        RIGHT_SPEED: 2,\n                        RIGHT_DIRECTION: 3,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let leftSpeed = script.getNumberValue('LEFT_SPEED', script);\n                        const leftDirection = script.getField('LEFT_DIRECTION', script);\n                        let rightSpeed = script.getNumberValue('RIGHT_SPEED', script);\n                        const rightDirection = script.getField('RIGHT_DIRECTION', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        if (leftSpeed < -100) {\n                            leftSpeed = -100;\n                        } else if (leftSpeed > 100) {\n                            leftSpeed = 100;\n                        }\n\n                        if (rightSpeed < -100) {\n                            rightSpeed = -100;\n                        } else if (rightSpeed > 100) {\n                            rightSpeed = 100;\n                        }\n\n                        if (leftDirection == '2') {\n                            leftSpeed = -leftSpeed;\n                        }\n                        if (rightDirection == '2') {\n                            rightSpeed = -rightSpeed;\n                        }\n\n                        if (leftSpeed < 0) {\n                            leftSpeed = 256 + leftSpeed;\n                        }\n                        if (rightSpeed < 0) {\n                            rightSpeed = 256 + rightSpeed;\n                        }\n\n                        data_value = leftSpeed + rightSpeed * 256;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.go_advanced(%1, %2)'],\n                    },\n                },\n                robotis_koalabot_lite_drive_seperate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '0'],\n                                [Lang.Blocks.robotis_both, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_direction_forward, '1'],\n                                [Lang.Blocks.robotis_direction_backward, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['5'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_drive_seperate',\n                    },\n                    paramsKeyMap: {\n                        WHEEL_SIDE: 0,\n                        WHEEL_SPEED: 1,\n                        WHEEL_DIRECTION: 2,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let wheelSide = script.getNumberValue('WHEEL_SIDE', script);\n                        let wheelSpeed = script.getNumberValue('WHEEL_SPEED', script);\n                        let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n\n                        let leftSpeed = 0;\n                        let rightSpeed = 0;\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        if (wheelSpeed < -100) {\n                            wheelSpeed = -100;\n                        } else if (wheelSpeed > 100) {\n                            wheelSpeed = 100;\n                        }\n\n                        wheelSpeed = (wheelSpeed + 256) % 256;\n                        if (wheelDirection == '2') {\n                            wheelSpeed = (256 - wheelSpeed) % 256;\n                        }\n\n                        if (wheelSide == 1) {\n                            leftSpeed = wheelSpeed;\n                            rightSpeed = 127; // 속도제어 안함\n                        } else if (wheelSide == 0) {\n                            leftSpeed = 127; // 속도제어 안함\n                            rightSpeed = wheelSpeed;\n                        } else {\n                            leftSpeed = wheelSpeed;\n                            rightSpeed = wheelSpeed;\n                        }\n\n                        data_value = leftSpeed + rightSpeed * 256;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            25 //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.go_seperate(%1, %2)'],\n                    },\n                },\n                robotis_koalabot_lite_drive_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_direction_forward, '1'],\n                                [Lang.Blocks.robotis_direction_backward, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['180'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_drive_angle',\n                    },\n                    paramsKeyMap: {\n                        WHEEL_ANGLE: 0,\n                        WHEEL_DIRECTION: 1,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let wheelAngle = script.getNumberValue('WHEEL_ANGLE', script);\n                        let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n\n                        const data_instruction = INST_WRITE;\n                        let data_address = 580;\n                        let data_length = 8;\n                        let angleValue = 0;\n                        let data_buf_left = [];\n                        let data_buf_right = [];\n                        let i = 0;\n                        let speed = 50;\n\n                        if (wheelDirection == '2') {\n                            wheelAngle = -wheelAngle;\n                        }\n\n                        wheelAngle = Math.round((wheelAngle * 4096) / 360);\n\n                        if (wheelAngle > 65535) {\n                            wheelAngle = 65535;\n                        } else if (wheelAngle < -65535) {\n                            wheelAngle = -65535;\n                        }\n\n                        angleValue = wheelAngle;\n                        if (wheelAngle < 0) {\n                            angleValue = 65536 + angleValue;\n                        }\n                        data_buf_left.push(35);\n                        data_buf_left.push(0);\n                        data_buf_left.push(speed % 256);\n                        data_buf_left.push(Math.floor(speed / 256));\n                        data_buf_left.push(angleValue % 256);\n                        data_buf_left.push(Math.floor(angleValue / 256) % 256);\n                        if (wheelAngle >= 0) {\n                            data_buf_left.push(0);\n                            data_buf_left.push(0);\n                        } else {\n                            data_buf_left.push(0xff);\n                            data_buf_left.push(0xff);\n                        }\n\n                        data_buf_right.push(36);\n                        data_buf_right.push(0);\n                        data_buf_right.push(speed % 256);\n                        data_buf_right.push(Math.floor(speed / 256));\n                        data_buf_right.push(angleValue % 256);\n                        data_buf_right.push(Math.floor(angleValue / 256) % 256);\n                        if (wheelAngle >= 0) {\n                            data_buf_right.push(0);\n                            data_buf_right.push(0);\n                        } else {\n                            data_buf_right.push(0xff);\n                            data_buf_right.push(0xff);\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf_left],\n                            [data_instruction, data_address, data_length, data_buf_right],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.go_angle(%1, %2)'],\n                    },\n                },\n                robotis_koalabot_lite_go_distance: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '-1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['5'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_go_distance',\n                    },\n\n                    paramsKeyMap: {\n                        DISTANCE: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(entity, script) {\n                        let distance = script.getNumberValue('DISTANCE', script);\n                        let direction = script.getField('DIRECTION', script);\n\n                        if (distance > 1000) {\n                            distance = 1000;\n                        } else if (distance < -1000) {\n                            distance = -1000;\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 270;\n                        let data_length = 4;\n                        let data_value = Math.floor(10 * distance * direction);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        data_sendqueue.push([data_instruction, 66, 2, 50491]);\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 150 * Math.abs(distance) + 1200\n                            //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Koalabot.go_distance(%1)'] },\n                },\n\n                robotis_koalabot_lite_turn_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveL_in_place, '1'],\n                                [Lang.Blocks.robotis_moveR_in_place, '-1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['90'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_turn_angle',\n                    },\n\n                    paramsKeyMap: {\n                        ANGLE: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(entity, script) {\n                        let angle = script.getNumberValue('ANGLE', script);\n                        let direction = script.getNumberValue('DIRECTION', script);\n\n                        angle *= direction;\n\n                        if (angle > 360) {\n                            angle = 360;\n                        } else if (angle < -360) {\n                            angle = -360;\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 270;\n                        let data_length = 4;\n                        let data_value = Math.floor(angle);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        data_sendqueue.push([data_instruction, 66, 2, 50492]);\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + Math.abs(angle) * 16 + 1500\n                            //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Koalabot.turn_angle(%1)'] },\n                },\n                robotis_koalabot_lite_follow_line: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_slow, '1'],\n                                [Lang.Blocks.robotis_normal, '2'],\n                                [Lang.Blocks.robotis_fast, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_follow_line',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let speed_level = script.getNumberValue('SPEED', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 5200;\n                        let data_length = 1;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, speed_level],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.follow_line(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_stop_at_cross: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_line_cross_type_5, '5'],\n                                [Lang.Blocks.robotis_line_cross_type_6, '6'],\n                                [Lang.Blocks.robotis_line_cross_type_7, '7'],\n                                [Lang.Blocks.robotis_line_cross_type_8, '8'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_stop_at_cross',\n                    },\n                    paramsKeyMap: {\n                        CROSS: 0,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    async func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cross_type = script.getNumberValue('CROSS', script);\n                        let data_address = 5201;\n\n                        // max 10 seconds\n                        for (let i = 0; i < 100; i++) {\n                            await Entry.Utils.sleep(100);\n                            if (Entry.RobotisKoalabotLite.dataBuffer[data_address] == cross_type) {\n                                break;\n                            }\n                            if (Entry.engine.isState('stop') == true) {\n                                break;\n                            }\n                        }\n\n                        let data_sendqueue = [[INST_WRITE, 5200, 1, 0]];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.stop_at_cross(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_turn_at_line: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveL_in_place, '0'],\n                                [Lang.Blocks.robotis_moveR_in_place, '1'],\n                                [Lang.Blocks.robotis_moveU_in_place, '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_turn_at_line',\n                    },\n                    paramsKeyMap: {\n                        TURN_TYPE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let turn_type = script.getNumberValue('TURN_TYPE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 66;\n                        let data_length = 2;\n                        let extra_delay = 0;\n\n                        switch (turn_type) {\n                            case 0:\n                            case 1:\n                                extra_delay = 2000;\n                                break;\n\n                            case 2:\n                                extra_delay = 3500;\n                                break;\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, 50045 + turn_type],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + extra_delay\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.turn_at_line(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_drive_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_drive_stop',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'robotis_koalabot_lite_move',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        let data_sendqueue = [\n                            [data_instruction, 5200, 1, 0],\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.stop(%1, %2)'],\n                    },\n                },\n\n                robotis_koalabot_lite_cm_ir_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_front_right, '360'],\n                                [Lang.Blocks.robotis_front_left, '362'],\n                                [Lang.Blocks.robotis_bottom_right, '364'],\n                                [Lang.Blocks.robotis_bottom_left, '366'],\n                                [Lang.Blocks.robotis_side_right, '368'],\n                                [Lang.Blocks.robotis_side_left, '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_cm_ir_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        const scope = script.executor.scope;\n\n                        const data_default_address = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_default_address];\n                        if (result == undefined) {\n                            result = rb100_last_valid_value[data_default_address];\n                        } else {\n                            rb100_last_valid_value[data_default_address] = result;\n                        }\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return Math.round((result % 65536) / 2);\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ir_value(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_cm_ir_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_front_right, '360'],\n                                [Lang.Blocks.robotis_front_left, '362'],\n                                [Lang.Blocks.robotis_bottom_right, '364'],\n                                [Lang.Blocks.robotis_bottom_left, '366'],\n                                [Lang.Blocks.robotis_side_right, '368'],\n                                [Lang.Blocks.robotis_side_left, '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_if_greater, '0'],\n                                [Lang.Blocks.robotis_if_smaller, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, 50, null],\n                        type: 'robotis_koalabot_lite_cm_ir_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                        COMPARE_VAL: 1,\n                        COMPARE_OP: 2,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = script.getNumberValue('COMPARE_VAL');\n                        let compareOP = script.getNumberValue('COMPARE_OP');\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        result = Math.round((result % 65536) / 2);\n\n                        switch (compareOP) {\n                            case 0:\n                                return result > compareValue;\n                            case 1:\n                                return result < compareValue;\n                            default:\n                                return false;\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ir_compare(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_detectFrontObj: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_front_ir_sensor, '0'],\n                                [Lang.Blocks.robotis_distance_sensor, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_detectFrontObj',\n                    },\n                    paramsKeyMap: {\n                        SENSOR: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let sensorType = script.getNumberValue('SENSOR');\n                        let ir_1 = 0;\n                        let ir_2 = 0;\n\n                        if (sensorType == 0) {\n                            ir_1 = Entry.RobotisKoalabotLite.dataBuffer[360];\n                            ir_2 = Entry.RobotisKoalabotLite.dataBuffer[362];\n                            if (ir_1 == undefined) {\n                                ir_1 = 0;\n                            }\n                            if (ir_2 == undefined) {\n                                ir_2 = 0;\n                            }\n                            return ir_1 > 100 || ir_2 > 100;\n                        } else if (sensorType == 1) {\n                            result = Entry.RobotisKoalabotLite.distanceDistance[0];\n                            if (result == undefined) {\n                                return false;\n                            } else {\n                                return result < 200;\n                            }\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.detectFrontObj()'],\n                    },\n                },\n                robotis_koalabot_lite_cm_btn_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_blue, '47'],\n                                [Lang.Blocks.robotis_red, '44'],\n                            ],\n                            value: '47',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_cm_btn_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = 1;\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.btn_value(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_cm_joystick_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_center, '0'],\n                                ['←', '1'],\n                                ['→', '2'],\n                                ['↑', '3'],\n                                ['↓', '4'],\n                                ['↖', '5'],\n                                ['↗', '6'],\n                                ['↙', '7'],\n                                ['↘', '8'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_cm_joystick_value',\n                    },\n                    paramsKeyMap: {\n                        COMPARE_VAL: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 50;\n                        let compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.joystick_value()'],\n                    },\n                },\n                robotis_koalabot_lite_mic: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_mic',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    async func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 119;\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.mic()'],\n                    },\n                },\n                robotis_koalabot_lite_detectSound_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_center, '0'],\n                                [Lang.Blocks.robotis_right, '255'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_detectSound_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 5031;\n                        let compareValue = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.detectSound_compare(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_imu: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['x', '78'], //72\n                                ['y', '80'], //74\n                                ['z', '82'], //76\n                            ],\n                            value: '78',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_acceleration, '0'], //72\n                                [Lang.Blocks.robotis_gyro, '6'], //74\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_imu',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                        MODE: 1,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address =\n                            script.getField('AXIS', script) - script.getField('MODE', script);\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.imu()'],\n                    },\n                },\n                robotis_koalabot_lite_roll_pitch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_roll, '70'], //72\n                                [Lang.Blocks.robotis_pitch, '88'], //74\n                            ],\n                            value: '70',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_roll_pitch',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('AXIS');\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.roll_pitch(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_distance_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_sensing_distance, '25'],\n                                [Lang.Blocks.robotis_sensing_button, '24'],\n                                [Lang.Blocks.robotis_sensing_brightness, '30'],\n                            ],\n                            value: '25',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_distance_value',\n                    },\n                    paramsKeyMap: {\n                        ADDR: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('ADDR');\n\n                        let result = 0;\n\n                        switch (data_address) {\n                            case 25:\n                                result = Entry.RobotisKoalabotLite.distanceDistance[0];\n                                break;\n\n                            case 24:\n                                result = Entry.RobotisKoalabotLite.distanceButton[0];\n                                break;\n\n                            case 30:\n                                result = Entry.RobotisKoalabotLite.distanceBrightness[0];\n                                break;\n                        }\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        if (data_address == 25) {\n                            if (result > 1000) result = 1000;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.distance_value(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_distance_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_sensing_distance, '25'],\n                                [Lang.Blocks.robotis_sensing_button, '24'],\n                                [Lang.Blocks.robotis_sensing_brightness, '30'],\n                            ],\n                            value: '25',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            value: '',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_if_greater, '0'],\n                                [Lang.Blocks.robotis_if_smaller, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_distance_compare',\n                    },\n                    paramsKeyMap: {\n                        ADDR: 0,\n                        COMPARE_VAL: 1,\n                        COMPARE_OP: 2,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        let data_address = script.getNumberValue('ADDR');\n                        let compareValue = script.getNumberValue('COMPARE_VAL');\n                        let compareOP = script.getNumberValue('COMPARE_OP');\n\n                        let result = 0;\n\n                        switch (data_address) {\n                            case 25:\n                                result = Entry.RobotisKoalabotLite.distanceDistance[0];\n                                break;\n\n                            case 24:\n                                result = Entry.RobotisKoalabotLite.distanceButton[0];\n                                break;\n\n                            case 30:\n                                result = Entry.RobotisKoalabotLite.distanceBrightness[0];\n                                break;\n                        }\n\n                        if (typeof result == 'undefined') {\n                            return false;\n                        }\n\n                        if (data_address == 25) {\n                            if (result > 1000) result = 1000;\n                        }\n\n                        switch (compareOP) {\n                            case 0:\n                                return result > compareValue;\n                            case 1:\n                                return result < compareValue;\n                            case 2:\n                                return result == compareValue;\n                            default:\n                                return false;\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.distance_compare(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_dxl_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left_wheel, '36'],\n                                [Lang.Blocks.robotis_right_wheel, '35'],\n                            ],\n                            value: '36',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_value_angle, '1'],\n                                [Lang.Blocks.robotis_dxl_value_velocity, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [36, null],\n                        type: 'robotis_koalabot_lite_dxl_value',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        let dxl_id = script.getNumberValue('ID');\n                        //var data_type = script.getNumberValue('TYPE');\n\n                        let result = Entry.RobotisKoalabotLite.dxlPositions[dxl_id];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        result = 180 - Math.round((result * 360) / 4096);\n                        while (result < -180) {\n                            result += 360;\n                        }\n                        while (result > 180) {\n                            result -= 360;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.get_dxl_value(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_line_cross_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_line_cross_type_5, '5'],\n                                [Lang.Blocks.robotis_line_cross_type_6, '6'],\n                                [Lang.Blocks.robotis_line_cross_type_7, '7'],\n                                [Lang.Blocks.robotis_line_cross_type_8, '8'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_line_cross_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 5201;\n                        let compareValue = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.line_cross_compare(%1)'],\n                    },\n                },\n\n                robotis_koalabot_lite_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_rla, '2'],\n                                [Lang.Blocks.robotis_rgee, '0'],\n                                [Lang.Blocks.robotis_kkokdu, '3'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '2817'],\n                                [Lang.Blocks.robotis_car_anim02, '2818'],\n                                [Lang.Blocks.robotis_car_anim03, '2819'],\n                                [Lang.Blocks.robotis_car_anim04, '2820'],\n                                [Lang.Blocks.robotis_car_anim05, '2821'],\n\n                                [Lang.Blocks.robotis_car_anim06, '2822'],\n                                //[Lang.Blocks.robotis_car_anim07, '2823'],\n                                [Lang.Blocks.robotis_car_anim08, '2824'],\n                                [Lang.Blocks.robotis_car_anim09, '2825'],\n                                [Lang.Blocks.robotis_car_anim10, '2826'],\n\n                                [Lang.Blocks.robotis_car_anim11, '2827'],\n                                [Lang.Blocks.robotis_car_anim12, '2828'],\n                                //[Lang.Blocks.robotis_car_anim13, '2829'],\n                                [Lang.Blocks.robotis_car_anim14, '2830'],\n                                [Lang.Blocks.robotis_car_anim15, '2831'],\n\n                                [Lang.Blocks.robotis_car_anim16, '2832'],\n                                [Lang.Blocks.robotis_car_anim17, '2833'],\n                                [Lang.Blocks.robotis_car_anim18, '2834'],\n                                [Lang.Blocks.robotis_car_anim19, '2835'],\n                            ],\n                            value: '2817',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_screen',\n                    },\n                    paramsKeyMap: {\n                        ROBOT_TYPE: 0,\n                        BACKGROUND: 1,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let robotType = script.getNumberValue('ROBOT_TYPE', script);\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue + robotType * 256;\n\n                        if (robotType == 0) {\n                            switch (screenValue) {\n                                case 2817:\n                                    data_value = 2841;\n                                    break;\n\n                                case 2818:\n                                    data_value = 2842;\n                                    break;\n\n                                case 2819:\n                                    data_value = 2820;\n                                    break;\n\n                                case 2820:\n                                    data_value = 2817;\n                                    break;\n\n                                case 2821:\n                                    data_value = 2819;\n                                    break;\n\n                                case 2822:\n                                    data_value = 2818;\n                                    break;\n\n                                //case 2823:\n                                //    break;\n\n                                case 2824:\n                                    data_value = 2826;\n                                    break;\n\n                                case 2825:\n                                    data_value = 2836;\n                                    break;\n\n                                case 2826:\n                                    data_value = 2837;\n                                    break;\n\n                                case 2827:\n                                    data_value = 2843;\n                                    break;\n\n                                case 2828:\n                                    data_value = 2831;\n                                    break;\n\n                                //case 2829:\n                                //    break;\n\n                                case 2830:\n                                    data_value = 2833;\n                                    break;\n\n                                case 2831:\n                                    data_value = 2834;\n                                    break;\n\n                                case 2832:\n                                    data_value = 2828;\n                                    break;\n\n                                case 2833:\n                                    data_value = 2827;\n                                    break;\n\n                                case 2834:\n                                    data_value = 2829;\n                                    break;\n\n                                case 2835:\n                                    data_value = 2840;\n                                    break;\n\n                                default:\n                                    data_value = 2841;\n                                    break;\n                            }\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['Koalabot.screen(%1)'] },\n                },\n\n                robotis_koalabot_lite_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_rla, '0'],\n                                [Lang.Blocks.robotis_rgee, '-1'],\n                                [Lang.Blocks.robotis_kkokdu, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '30978'],\n                                [Lang.Blocks.robotis_car_anim02, '30981'],\n                                //[Lang.Blocks.robotis_car_anim03, '30982'],\n                                [Lang.Blocks.robotis_car_anim04, '30983'],\n                                [Lang.Blocks.robotis_car_anim05, '30984'],\n\n                                [Lang.Blocks.robotis_car_anim06, '30985'],\n                                [Lang.Blocks.robotis_car_anim07, '30986'],\n                                [Lang.Blocks.robotis_car_anim08, '30987'],\n                                [Lang.Blocks.robotis_car_anim09, '30988'],\n                                [Lang.Blocks.robotis_car_anim10, '30989'],\n\n                                [Lang.Blocks.robotis_car_anim11, '30990'],\n                                [Lang.Blocks.robotis_car_anim12, '30991'],\n                                //[Lang.Blocks.robotis_car_anim13, '30992'],\n                                [Lang.Blocks.robotis_car_anim14, '30993'],\n                                [Lang.Blocks.robotis_car_anim15, '30994'],\n\n                                [Lang.Blocks.robotis_car_anim16, '30995'],\n                                [Lang.Blocks.robotis_car_anim17, '30996'],\n                                [Lang.Blocks.robotis_car_anim18, '30997'],\n                                [Lang.Blocks.robotis_car_anim19, '30998'],\n                            ],\n                            value: '30978',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        ROBOT_TYPE: 0,\n                        BACKGROUND: 1,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let robotType = script.getNumberValue('ROBOT_TYPE', script);\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        if (robotType >= 0) {\n                            data_value += 256 * robotType;\n                        } else {\n                            switch (screenValue) {\n                                case 30978:\n                                    data_value = 30724;\n                                    break;\n\n                                case 30981:\n                                    data_value = 30761;\n                                    break;\n\n                                //case 30982:\n                                //    break;\n\n                                case 30983:\n                                    data_value = 30748;\n                                    break;\n\n                                case 30984:\n                                    data_value = 30750;\n                                    break;\n\n                                case 30985:\n                                    data_value = 30749;\n                                    break;\n\n                                //case 30986:\n                                //    break;\n\n                                case 30987:\n                                    data_value = 30739;\n                                    break;\n\n                                case 30988:\n                                    data_value = 30751;\n                                    break;\n\n                                case 30989:\n                                    data_value = 30752;\n                                    break;\n\n                                case 30990:\n                                    data_value = 30762;\n                                    break;\n\n                                case 30991:\n                                    data_value = 30736;\n                                    break;\n\n                                //case 30992:\n                                //    break;\n\n                                case 30993:\n                                    data_value = 30742;\n                                    break;\n\n                                case 30994:\n                                    data_value = 30743;\n                                    break;\n\n                                case 30995:\n                                    data_value = 30734;\n                                    break;\n\n                                case 30996:\n                                    data_value = 30733;\n                                    break;\n\n                                case 30997:\n                                    data_value = 30732;\n                                    break;\n\n                                case 30998:\n                                    data_value = 30760;\n                                    break;\n\n                                default:\n                                    data_value = 30724;\n                                    break;\n                            }\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['Koalabot.animation_screen(%1)'] },\n                },\n                robotis_koalabot_lite_icon_screen_food_plant: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_food_plant_1, '10496'],\n                                [Lang.Blocks.robotis_icon_food_plant_2, '10497'],\n                                [Lang.Blocks.robotis_icon_food_plant_3, '10498'],\n                                [Lang.Blocks.robotis_icon_food_plant_4, '10499'],\n                                [Lang.Blocks.robotis_icon_food_plant_5, '10500'],\n                                [Lang.Blocks.robotis_icon_food_plant_6, '10501'],\n                                [Lang.Blocks.robotis_icon_food_plant_7, '10502'],\n                                [Lang.Blocks.robotis_icon_food_plant_8, '10503'],\n                                [Lang.Blocks.robotis_icon_food_plant_9, '10504'],\n                                [Lang.Blocks.robotis_icon_food_plant_10, '10505'],\n                                [Lang.Blocks.robotis_icon_food_plant_11, '10506'],\n                                [Lang.Blocks.robotis_icon_food_plant_12, '10507'],\n                                [Lang.Blocks.robotis_icon_food_plant_13, '10508'],\n                                [Lang.Blocks.robotis_icon_food_plant_14, '10509'],\n                                [Lang.Blocks.robotis_icon_food_plant_15, '10510'],\n                                [Lang.Blocks.robotis_icon_food_plant_16, '10511'],\n                                [Lang.Blocks.robotis_icon_food_plant_17, '10512'],\n                                [Lang.Blocks.robotis_icon_food_plant_18, '10513'],\n                                [Lang.Blocks.robotis_icon_food_plant_19, '10514'],\n                                [Lang.Blocks.robotis_icon_food_plant_20, '10515'],\n                                [Lang.Blocks.robotis_icon_food_plant_21, '10516'],\n                                [Lang.Blocks.robotis_icon_food_plant_22, '10517'],\n                                [Lang.Blocks.robotis_icon_food_plant_23, '10518'],\n                                [Lang.Blocks.robotis_icon_food_plant_24, '10519'],\n                            ],\n                            value: '10496',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_icon_screen_food_plant',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.icon_screen_food_and_plant(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_koalabot_lite_icon_screen_animal_human: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_animal_human_1, '10752'],\n                                [Lang.Blocks.robotis_icon_animal_human_2, '10753'],\n                                [Lang.Blocks.robotis_icon_animal_human_3, '10754'],\n                                [Lang.Blocks.robotis_icon_animal_human_4, '10755'],\n                                [Lang.Blocks.robotis_icon_animal_human_5, '10756'],\n                                [Lang.Blocks.robotis_icon_animal_human_6, '10757'],\n                                [Lang.Blocks.robotis_icon_animal_human_7, '10758'],\n                                [Lang.Blocks.robotis_icon_animal_human_8, '10759'],\n                                [Lang.Blocks.robotis_icon_animal_human_9, '10760'],\n                                [Lang.Blocks.robotis_icon_animal_human_10, '11787'],\n                                [Lang.Blocks.robotis_icon_animal_human_11, '11788'],\n                                [Lang.Blocks.robotis_icon_animal_human_12, '11789'],\n                                [Lang.Blocks.robotis_icon_animal_human_13, '11790'],\n                                [Lang.Blocks.robotis_icon_animal_human_14, '11805'],\n                                [Lang.Blocks.robotis_icon_animal_human_15, '11806'],\n                                [Lang.Blocks.robotis_icon_animal_human_16, '11807'],\n                                [Lang.Blocks.robotis_icon_animal_human_17, '11808'],\n                                [Lang.Blocks.robotis_icon_animal_human_18, '10761'],\n                                [Lang.Blocks.robotis_icon_animal_human_19, '10762'],\n                                [Lang.Blocks.robotis_icon_animal_human_20, '10763'],\n                                [Lang.Blocks.robotis_icon_animal_human_21, '10764'],\n                                [Lang.Blocks.robotis_icon_animal_human_22, '10765'],\n                                [Lang.Blocks.robotis_icon_animal_human_23, '10766'],\n                                [Lang.Blocks.robotis_icon_animal_human_24, '10767'],\n                                [Lang.Blocks.robotis_icon_animal_human_25, '10768'],\n                                [Lang.Blocks.robotis_icon_animal_human_26, '10769'],\n                                [Lang.Blocks.robotis_icon_animal_human_27, '10770'],\n                                [Lang.Blocks.robotis_icon_animal_human_28, '10771'],\n                                [Lang.Blocks.robotis_icon_animal_human_29, '10772'],\n                                [Lang.Blocks.robotis_icon_animal_human_30, '10773'],\n                                [Lang.Blocks.robotis_icon_animal_human_31, '10774'],\n                                [Lang.Blocks.robotis_icon_animal_human_32, '10775'],\n                                [Lang.Blocks.robotis_icon_animal_human_33, '10776'],\n                                [Lang.Blocks.robotis_icon_animal_human_34, '10777'],\n                            ],\n                            value: '10752',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_icon_screen_animal_human',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.icon_screen_animal_and_human(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_koalabot_lite_icon_screen_object_tool: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_object_tool_1, '11008'],\n                                [Lang.Blocks.robotis_icon_object_tool_2, '11009'],\n                                [Lang.Blocks.robotis_icon_object_tool_3, '11010'],\n                                [Lang.Blocks.robotis_icon_object_tool_4, '11011'],\n                                [Lang.Blocks.robotis_icon_object_tool_5, '11012'],\n                                [Lang.Blocks.robotis_icon_object_tool_6, '11013'],\n                                [Lang.Blocks.robotis_icon_object_tool_7, '11014'],\n                                [Lang.Blocks.robotis_icon_object_tool_8, '11015'],\n                                [Lang.Blocks.robotis_icon_object_tool_9, '11016'],\n                                [Lang.Blocks.robotis_icon_object_tool_10, '11017'],\n                                [Lang.Blocks.robotis_icon_object_tool_11, '11018'],\n                                [Lang.Blocks.robotis_icon_object_tool_12, '11019'],\n                                [Lang.Blocks.robotis_icon_object_tool_13, '11020'],\n                                [Lang.Blocks.robotis_icon_object_tool_14, '11021'],\n                                [Lang.Blocks.robotis_icon_object_tool_15, '11022'],\n                                [Lang.Blocks.robotis_icon_object_tool_16, '11023'],\n                                [Lang.Blocks.robotis_icon_object_tool_17, '11024'],\n                                [Lang.Blocks.robotis_icon_object_tool_18, '11025'],\n                                [Lang.Blocks.robotis_icon_object_tool_19, '11026'],\n                                [Lang.Blocks.robotis_icon_object_tool_20, '11027'],\n                                [Lang.Blocks.robotis_icon_object_tool_21, '11028'],\n                                [Lang.Blocks.robotis_icon_object_tool_22, '11029'],\n                                [Lang.Blocks.robotis_icon_object_tool_23, '11030'],\n                                [Lang.Blocks.robotis_icon_object_tool_24, '11031'],\n                                [Lang.Blocks.robotis_icon_object_tool_25, '11032'],\n                                [Lang.Blocks.robotis_icon_object_tool_26, '11033'],\n                                [Lang.Blocks.robotis_icon_object_tool_27, '11034'],\n                                [Lang.Blocks.robotis_icon_object_tool_28, '11035'],\n                                [Lang.Blocks.robotis_icon_object_tool_29, '11036'],\n                                [Lang.Blocks.robotis_icon_object_tool_30, '11037'],\n                                [Lang.Blocks.robotis_icon_object_tool_31, '11038'],\n                                [Lang.Blocks.robotis_icon_object_tool_32, '11039'],\n                                [Lang.Blocks.robotis_icon_object_tool_33, '11040'],\n                                [Lang.Blocks.robotis_icon_object_tool_34, '11801'],\n                                [Lang.Blocks.robotis_icon_object_tool_35, '11802'],\n                                [Lang.Blocks.robotis_icon_object_tool_36, '11809'],\n                            ],\n                            value: '11008',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_icon_screen_object_tool',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.icon_screen_object_and_tool(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_koalabot_lite_icon_screen_vehicle_number: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_vehicle_number_1, '11264'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_2, '11265'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_3, '11266'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_4, '11267'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_5, '11268'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_6, '11269'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_7, '11270'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_8, '11271'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_9, '11272'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_10, '11273'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_11, '11274'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_12, '11275'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_13, '11276'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_14, '11776'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_15, '11777'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_16, '11778'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_17, '11779'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_18, '11780'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_19, '11781'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_20, '11782'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_21, '11783'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_22, '11277'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_23, '11278'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_24, '11279'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_25, '11280'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_26, '11281'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_27, '11282'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_28, '11283'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_29, '11284'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_30, '11285'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_31, '11286'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_32, '11287'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_33, '11288'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_34, '11289'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_35, '11290'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_36, '11291'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_37, '11292'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_38, '11293'],\n                            ],\n                            value: '11264',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_icon_screen_vehicle_number',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.icon_screen_vehicle_and_number(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_koalabot_lite_icon_screen_game_character: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_game_character_1, '11520'], // 알쥐(정면)\n                                [Lang.Blocks.robotis_icon_game_character_2, '11521'], // 알쥐(왼쪽)\n                                [Lang.Blocks.robotis_icon_game_character_3, '11522'], // 알쥐(오른쪽)\n                                [Lang.Blocks.robotis_icon_game_character_4, '11523'], // 알라(정면)\n                                [Lang.Blocks.robotis_icon_game_character_5, '11524'], // 알라(왼쪽)\n                                [Lang.Blocks.robotis_icon_game_character_6, '11525'], // 알라(오른쪽)\n                                [Lang.Blocks.robotis_icon_game_character_7, '11526'], // 유령\n                                [Lang.Blocks.robotis_icon_game_character_8, '11527'], // 괴물\n                                [Lang.Blocks.robotis_icon_game_character_9, '11528'], // 바이러스\n                                [Lang.Blocks.robotis_icon_game_character_10, '11529'], // 세균\n                                [Lang.Blocks.robotis_icon_game_character_11, '11784'], // 나는 알쥐(L)\n                                [Lang.Blocks.robotis_icon_game_character_12, '11785'], // 나는 알쥐(R)\n                                [Lang.Blocks.robotis_icon_game_character_13, '11786'], // 나는 알쥐(U)\n                                [Lang.Blocks.robotis_icon_game_character_14, '11530'], // 메달\n                                [Lang.Blocks.robotis_icon_game_character_15, '11531'], // 돈(G)\n                                [Lang.Blocks.robotis_icon_game_character_16, '11532'], // 돈($)\n                                [Lang.Blocks.robotis_icon_game_character_17, '11533'], // 하트\n                                [Lang.Blocks.robotis_icon_game_character_18, '11534'], // 포탄\n                                [Lang.Blocks.robotis_icon_game_character_19, '11535'], // 불\n                                [Lang.Blocks.robotis_icon_game_character_20, '11803'], // 구름1\n                                [Lang.Blocks.robotis_icon_game_character_21, '11804'], // 구름2\n                                [Lang.Blocks.robotis_icon_game_character_22, '11536'], // 포탄1\n                                [Lang.Blocks.robotis_icon_game_character_23, '11791'], // 포탄2\n                                [Lang.Blocks.robotis_icon_game_character_24, '11537'], // 대포(수평)\n                                [Lang.Blocks.robotis_icon_game_character_25, '11538'], // 대포(수직)\n                                [Lang.Blocks.robotis_icon_game_character_27, '11540'], // 레이저(수평)\n                                [Lang.Blocks.robotis_icon_game_character_26, '11539'], // 레이저(수직)\n                                [Lang.Blocks.robotis_icon_game_character_28, '11541'], // 화살(수평)\n                                [Lang.Blocks.robotis_icon_game_character_29, '11542'], // 화살(수직)\n                                [Lang.Blocks.robotis_icon_game_character_30, '11792'], // 미사일(U)\n                                [Lang.Blocks.robotis_icon_game_character_31, '11793'], // 미사일(D)\n                                [Lang.Blocks.robotis_icon_game_character_32, '11794'], // 미사일(L)\n                                [Lang.Blocks.robotis_icon_game_character_33, '11795'], // 미사일(R)\n                                [Lang.Blocks.robotis_icon_game_character_34, '11796'], // 낙하산\n                                [Lang.Blocks.robotis_icon_game_character_35, '11543'], // 폭발1\n                                [Lang.Blocks.robotis_icon_game_character_36, '11544'], // 폭발2\n                                [Lang.Blocks.robotis_icon_game_character_37, '11810'], // 조준경\n                                [Lang.Blocks.robotis_icon_game_character_38, '11545'], // 가위\n                                [Lang.Blocks.robotis_icon_game_character_39, '11546'], // 바위\n                                [Lang.Blocks.robotis_icon_game_character_40, '11547'], // 보\n                                [Lang.Blocks.robotis_icon_game_character_41, '11797'], // 걷는 사람1\n                                [Lang.Blocks.robotis_icon_game_character_42, '11798'], // 걷는 사람2\n                                [Lang.Blocks.robotis_icon_game_character_43, '11799'], // 뛰는 사람1\n                                [Lang.Blocks.robotis_icon_game_character_44, '11800'], // 뛰는 사람2\n                            ],\n                            value: '11520',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_icon_screen_game_character',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabotlite.icon_screen_game_and_character(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_koalabot_lite_text_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_screen_text_font_small, '0'],\n                                [Lang.Blocks.robotis_screen_text_font_big, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            ' ',\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_text_screen',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        X: 1,\n                        Y: 2,\n                        FONT: 3,\n                        COLOR: 4,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let text = script.getStringValue('TEXT', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let font = script.getNumberValue('FONT', script);\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 900;\n                        let data_length = 2;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        let encoder = new TextEncoder('utf-8');\n                        let byteArray = encoder.encode(text);\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(font);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(color);\n                        data_buf.push(byteArray.length);\n                        for (i = 0; i < byteArray.length; i++) {\n                            data_buf.push(byteArray[i]);\n                        }\n\n                        data_length = 9 + byteArray.length;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.text_screen(%1,%2,%3,%4,%5)'],\n                    },\n                },\n                robotis_koalabot_lite_pixel: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_pixel',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        COLOR: 2,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 130;\n                        let data_length = 11;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(color);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 161, 2, 1 * 256 + 8],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.pixel(%1,%2,%3)'],\n                    },\n                },\n                robotis_koalabot_lite_text_screen_redraw: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            ' ',\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_koalabot_lite_text_screen_redraw',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        X: 1,\n                        Y: 2,\n                        COLOR: 3,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let text = script.getStringValue('TEXT', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let font = 0;\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        let encoder = new TextEncoder('utf-8');\n                        let byteArray = encoder.encode(text);\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(font);\n                        data_buf.push(1);\n                        data_buf.push(bg_color);\n                        data_buf.push(color);\n                        data_buf.push(byteArray.length);\n                        for (i = 0; i < byteArray.length; i++) {\n                            data_buf.push(byteArray[i]);\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 900;\n                        let data_length = 9 + byteArray.length;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.text_screen_redraw(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_koalabot_lite_LCDBright: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [50],\n                        type: 'robotis_koalabot_lite_LCDBright',\n                    },\n                    paramsKeyMap: {\n                        BRIGHT: 0,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let bright = script.getNumberValue('BRIGHT', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 180;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        bright = Math.min(Math.max(bright, 0), 100);\n\n                        data_value = bright;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.LCDBright(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_LCDColor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '224',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_LCDColor',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'robotis_koalabot_lite_lcd',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let color = script.getNumberValue('COLOR', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = color;\n                        bg_color = color;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.LCDColor(%1)'],\n                    },\n                },\n\n                robotis_koalabot_lite_cm_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '2'],\n                                [Lang.Blocks.robotis_both, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_common_on, '1'],\n                                [Lang.Blocks.robotis_common_off, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'robotis_koalabot_lite_cm_led',\n                    },\n                    paramsKeyMap: {\n                        RB_LED: 0,\n                        VALUE: 1,\n                    },\n                    class: 'robotis_koalabot_lite_led',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmLed = script.getField('RB_LED', script);\n                        let value = script.getField('VALUE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 40;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        if (cmLed == 1) {\n                            data_value = 200 * value;\n                        } else if (cmLed == 2) {\n                            data_address = 41;\n                            data_value = 200 * value;\n                        } else if (cmLed == 3) {\n                            data_address = 40;\n                            data_length = 2;\n                            data_value = 200 * 257 * value;\n                        } else {\n                            data_value = value * cmLed;\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Koalabot.led(%1, %2)'] },\n                },\n                robotis_koalabot_lite_cm_led_pattern: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_pattern1, '11'],\n                                [Lang.Blocks.robotis_pattern2, '21'],\n                                [Lang.Blocks.robotis_pattern3, '31'],\n                            ],\n                            value: '11',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_speed_fast, '0'],\n                                [Lang.Blocks.robotis_speed_midium, '1'],\n                                [Lang.Blocks.robotis_speed_slow, '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'robotis_koalabot_lite_cm_led_pattern',\n                    },\n                    paramsKeyMap: {\n                        PATTERN: 0,\n                        SPEED: 1,\n                    },\n                    class: 'robotis_koalabot_lite_led',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let pattern = script.getNumberValue('PATTERN', script);\n                        let speed = script.getNumberValue('SPEED', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 40;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = pattern + speed;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Koalabot.led_pattern(%1, %2)'] },\n                },\n\n                robotis_koalabot_lite_scale_simple: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.General.note_c + '', '1'],\n                                [Lang.General.note_c + '#', '2'],\n                                [Lang.General.note_d + '', '3'],\n                                [Lang.General.note_d + '#', '4'],\n                                [Lang.General.note_e + '', '5'],\n                                [Lang.General.note_f + '', '6'],\n                                [Lang.General.note_f + '#', '7'],\n                                [Lang.General.note_g + '', '8'],\n                                [Lang.General.note_g + '#', '9'],\n                                [Lang.General.note_a + '', '10'],\n                                [Lang.General.note_a + '#', '11'],\n                                [Lang.General.note_b + '', '12'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_beat_sound_8th_note, '3'],\n                                [Lang.Blocks.robotis_beat_sound_dotted_8th_note, '4'],\n                                [Lang.Blocks.robotis_beat_sound_quarter_note, '5'],\n                                [Lang.Blocks.robotis_beat_sound_dotted_quarter_note, '6'],\n                                [Lang.Blocks.robotis_beat_sound_half_note, '7'],\n                                [Lang.Blocks.robotis_beat_sound_dotted_half_note, '8'],\n                                [Lang.Blocks.robotis_beat_sound_whole_note, '9'],\n                                [Lang.Blocks.robotis_beat_sound_dotted_note, '10'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'robotis_koalabot_lite_scale_simple',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_OCTAV: 0,\n                        CM_BUZZER_INDEX: 1,\n                        CM_BUZZER_NOTE: 2,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                        let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                        let cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script);\n                        let cmBuzzerTime = 0;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 0;\n                        let data_value = 0;\n                        let interval = 0;\n                        let data_buf = [];\n\n                        switch (cmBuzzerNote) {\n                            case 3:\n                                cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute / 2);\n                                break;\n\n                            case 4:\n                                cmBuzzerTime = Math.round(\n                                    ((60 * 1000) / beat_per_minute / 2) * 1.5\n                                );\n                                break;\n\n                            case 5:\n                                cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute);\n                                break;\n\n                            case 6:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 1.5);\n                                break;\n\n                            case 7:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 2);\n                                break;\n\n                            case 8:\n                                cmBuzzerTime = Math.round(\n                                    ((60 * 1000) / beat_per_minute) * 2 * 1.5\n                                );\n                                break;\n\n                            case 9:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 4);\n                                break;\n\n                            case 10:\n                                cmBuzzerTime = Math.round(\n                                    ((60 * 1000) / beat_per_minute) * 4 * 1.5\n                                );\n                                break;\n                        }\n\n                        data_address = 740;\n                        // data_value_1 = cmBuzzerTime * 10;\n                        // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                        data_value = cmBuzzerTime;\n                        if (data_value < 0) {\n                            data_value = 0;\n                        }\n                        if (data_value > 50000) {\n                            data_value = 50000;\n                        }\n\n                        data_buf.push(data_value % 256);\n                        data_buf.push(Math.floor(data_value / 256));\n\n                        data_value = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n                        data_buf.push(Math.floor(data_value));\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [[data_instruction, data_address, 3, data_buf]];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.scale_simple(%1, %2, %3)'],\n                    },\n                },\n                robotis_koalabot_lite_scale_advanced: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.General.note_c + '', '1'],\n                                [Lang.General.note_c + '#', '2'],\n                                [Lang.General.note_d + '', '3'],\n                                [Lang.General.note_d + '#', '4'],\n                                [Lang.General.note_e + '', '5'],\n                                [Lang.General.note_f + '', '6'],\n                                [Lang.General.note_f + '#', '7'],\n                                [Lang.General.note_g + '', '8'],\n                                [Lang.General.note_g + '#', '9'],\n                                [Lang.General.note_a + '', '10'],\n                                [Lang.General.note_a + '#', '11'],\n                                [Lang.General.note_b + '', '12'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 1, null],\n                        type: 'robotis_koalabot_lite_scale_advanced',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_OCTAV: 0,\n                        CM_BUZZER_INDEX: 1,\n                        CM_BUZZER_BEAT: 2,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                        let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                        let cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script);\n                        let cmBuzzerTime = 0;\n\n                        cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address_1 = 0;\n                        let data_length_1 = 0;\n                        let data_value_1 = 0;\n                        let data_address_2 = 0;\n                        let data_length_2 = 0;\n                        let data_value_2 = 0;\n                        let interval = 0;\n\n                        cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * cmBuzzerBeat);\n\n                        data_address_1 = 740;\n                        data_length_1 = 2;\n                        // data_value_1 = cmBuzzerTime * 10;\n                        // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                        data_value_1 = cmBuzzerTime;\n                        if (data_value_1 < 0) {\n                            data_value_1 = 0;\n                        }\n                        if (data_value_1 > 50000) {\n                            data_value_1 = 50000;\n                        }\n\n                        data_address_2 = 742;\n                        data_length_2 = 1;\n                        data_value_2 = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [\n                            [data_instruction, data_address_1, data_length_1, data_value_1],\n                            [data_instruction, data_address_2, data_length_2, data_value_2],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.scale_advanced(%1, %2, %3)'],\n                    },\n                },\n                robotis_koalabot_lite_rest_simple: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_beat_rest_8th_note, '3'],\n                                [Lang.Blocks.robotis_beat_rest_quarter_note, '5'],\n                                [Lang.Blocks.robotis_beat_rest_half_note, '7'],\n                                [Lang.Blocks.robotis_beat_rest_whole_note, '9'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_rest_simple',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_NOTE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script);\n                        let cmBuzzerTime = 0;\n\n                        let interval = 0;\n\n                        switch (cmBuzzerNote) {\n                            case 3:\n                                cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute / 2);\n                                break;\n\n                            case 5:\n                                cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute);\n                                break;\n\n                            case 7:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 2);\n                                break;\n\n                            case 9:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 4);\n                                break;\n                        }\n\n                        let data_sendqueue = [];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.rest_simple(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_rest_advanced: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'robotis_koalabot_lite_rest_advanced',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_BEAT: 0,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script);\n                        let cmBuzzerTime = 0;\n\n                        let interval = 0;\n\n                        cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100);\n\n                        cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * cmBuzzerBeat);\n\n                        let data_sendqueue = [];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.rest_advanced(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_beat_per_minute: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [75, null],\n                        type: 'robotis_koalabot_lite_beat_per_minute',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_BPM: 0,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerBpm = script.getNumberValue('CM_BUZZER_BPM', script);\n\n                        beat_per_minute = Math.min(Math.max(cmBuzzerBpm, 10), 600);\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(script, data_sendqueue, 0);\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.set_bpm(%1)'],\n                    },\n                },\n\n                robotis_koalabot_lite_Hello: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_korean1, '0'],\n                                [Lang.Blocks.robotis_korean2, '1'],\n                                [Lang.Blocks.robotis_korean3, '2'],\n                                [Lang.Blocks.robotis_korean4, '3'],\n                                [Lang.Blocks.robotis_korean5, '4'],\n                                [Lang.Blocks.robotis_korean6, '5'],\n                                [Lang.Blocks.robotis_korean7, '6'],\n                                [Lang.Blocks.robotis_korean8, '7'],\n                                [Lang.Blocks.robotis_korean9, '8'],\n                                [Lang.Blocks.robotis_korean10, '9'],\n                                [Lang.Blocks.robotis_korean11, '10'],\n                                [Lang.Blocks.robotis_korean12, '11'],\n                                [Lang.Blocks.robotis_korean13, '12'],\n                                [Lang.Blocks.robotis_korean14, '13'],\n                                [Lang.Blocks.robotis_korean15, '14'],\n                                [Lang.Blocks.robotis_korean16, '15'],\n                                [Lang.Blocks.robotis_korean17, '16'],\n                                [Lang.Blocks.robotis_korean18, '17'],\n                                [Lang.Blocks.robotis_korean19, '18'],\n                                [Lang.Blocks.robotis_korean20, '19'],\n                                [Lang.Blocks.robotis_korean21, '20'],\n                                [Lang.Blocks.robotis_korean22, '21'],\n                                [Lang.Blocks.robotis_korean23, '22'],\n                                [Lang.Blocks.robotis_korean24, '23'],\n                                [Lang.Blocks.robotis_korean25, '24'],\n                                [Lang.Blocks.robotis_korean26, '25'],\n                                [Lang.Blocks.robotis_korean27, '26'],\n                                [Lang.Blocks.robotis_korean28, '27'],\n                                [Lang.Blocks.robotis_korean29, '28'],\n                                [Lang.Blocks.robotis_korean30, '29'],\n                                [Lang.Blocks.robotis_korean31, '30'],\n                                [Lang.Blocks.robotis_korean32, '31'],\n                                [Lang.Blocks.robotis_korean33, '32'],\n                                [Lang.Blocks.robotis_korean34, '33'],\n                                [Lang.Blocks.robotis_korean35, '34'],\n                                [Lang.Blocks.robotis_korean36, '35'],\n                                [Lang.Blocks.robotis_korean37, '36'],\n                                [Lang.Blocks.robotis_korean38, '37'],\n                                [Lang.Blocks.robotis_korean39, '38'],\n                                [Lang.Blocks.robotis_korean40, '39'],\n                                [Lang.Blocks.robotis_korean41, '40'],\n                                [Lang.Blocks.robotis_korean42, '41'],\n                                [Lang.Blocks.robotis_korean43, '42'],\n                                [Lang.Blocks.robotis_korean44, '43'],\n                                [Lang.Blocks.robotis_korean45, '44'],\n                                [Lang.Blocks.robotis_korean46, '45'],\n                                [Lang.Blocks.robotis_korean47, '46'],\n                                [Lang.Blocks.robotis_korean48, '47'],\n                                [Lang.Blocks.robotis_korean49, '48'],\n                                [Lang.Blocks.robotis_korean50, '49'],\n                                [Lang.Blocks.robotis_korean51, '50'],\n                                [Lang.Blocks.robotis_korean52, '51'],\n                                [Lang.Blocks.robotis_korean53, '52'],\n                                [Lang.Blocks.robotis_korean54, '53'],\n                                [Lang.Blocks.robotis_korean55, '54'],\n                                [Lang.Blocks.robotis_korean56, '55'],\n                                [Lang.Blocks.robotis_korean57, '56'],\n                                [Lang.Blocks.robotis_korean58, '57'],\n                                [Lang.Blocks.robotis_korean59, '58'],\n                                [Lang.Blocks.robotis_korean60, '59'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_Hello',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = 25601 + Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n\n                        if (cmHello == '38' || cmHello == '55') {\n                            extraTime = 2000;\n                        }\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            2000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.speak(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_effectSound: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dog, '0'],\n                                [Lang.Blocks.robotis_frog, '1'],\n                                [Lang.Blocks.robotis_cat, '2'],\n                                [Lang.Blocks.robotis_chicken, '7'],\n                                [Lang.Blocks.robotis_tiger, '19'],\n                                [Lang.Blocks.robotis_mouse, '17'],\n\n                                [Lang.Blocks.robotis_ambul, '773'],\n                                [Lang.Blocks.robotis_Horn, '781'],\n                                [Lang.Blocks.robotis_siren, '774'],\n                                [Lang.Blocks.robotis_whistle, '274'],\n                                [Lang.Blocks.robotis_gun, '775'],\n                                [Lang.Blocks.robotis_clap, '260'],\n\n                                [Lang.Blocks.robotis_melody1, '786'],\n                                [Lang.Blocks.robotis_melody2, '787'],\n                                [Lang.Blocks.robotis_melody3, '788'],\n                                [Lang.Blocks.robotis_melody4, '789'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_effectSound',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n                        if (\n                            cmHello == '272' ||\n                            cmHello == '786' ||\n                            cmHello == '787' ||\n                            cmHello == '788' ||\n                            cmHello == '789'\n                        ) {\n                            //오리\n                            extraTime = 0;\n                            if (cmHello == '788' || cmHello == '789') {\n                                extraTime += 500;\n                            }\n                        }\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            3000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.effect_sound(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_record: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_record',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 115;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.record(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_playRecord: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_playRecord',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_koalabot_lite_sound',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 116;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.playRecord(%1)'],\n                    },\n                },\n\n                robotis_koalabot_lite_ai_camera_block_value_closest_to_center: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_width, '2'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_height, '3'],\n                                [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_ai_camera_block_value_closest_to_center',\n                    },\n                    paramsKeyMap: {\n                        DATA_TYPE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_ai_camera_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4009;\n                        let data_type = script.getNumberValue('DATA_TYPE');\n                        data_address += data_type * 2;\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_block_value_closest_to_center(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_arrow_value_closest_to_center: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'],\n                                [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_ai_camera_arrow_value_closest_to_center',\n                    },\n                    paramsKeyMap: {\n                        DATA_TYPE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_ai_camera_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4019;\n                        let data_type = script.getNumberValue('DATA_TYPE');\n                        data_address += data_type * 2;\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_arrow_value_closest_to_center(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_number_of_learned_id: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'robotis_koalabot_lite_ai_camera_number_of_learned_id',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_koalabot_lite_ai_camera_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4003;\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_number_of_learned_id()'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_block_value_of_id: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                                ['8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_width, '2'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_height, '3'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_ai_camera_block_value_of_id',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'robotis_koalabot_lite_ai_camera_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4029; // ID_FOR_USE\n                        let data_length = 2;\n                        let data_value = script.getNumberValue('ID');\n\n                        if (data_value != camera_id_for_use) {\n                            let data_sendqueue = [\n                                [data_instruction, data_address, data_length, data_value],\n                            ];\n\n                            Entry.RobotisKoalabotLite.postCallReturn(\n                                script,\n                                data_sendqueue,\n                                DEFAULT_DELAY\n                            );\n                            camera_id_for_use = data_value;\n                        }\n\n                        data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER\n\n                        data_address += script.getNumberValue('TYPE') * 2;\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_block_value_of_id(%1, %2)'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_arrow_value_of_id: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                                ['8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_koalabot_lite_ai_camera_arrow_value_of_id',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'robotis_koalabot_lite_ai_camera_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4029; // ID_FOR_USE\n                        let data_length = 2;\n                        let data_value = script.getNumberValue('ID');\n\n                        if (data_value != camera_id_for_use) {\n                            let data_sendqueue = [\n                                [data_instruction, data_address, data_length, data_value],\n                            ];\n\n                            Entry.RobotisKoalabotLite.postCallReturn(\n                                script,\n                                data_sendqueue,\n                                DEFAULT_DELAY\n                            );\n                            camera_id_for_use = data_value;\n                        }\n\n                        data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN\n\n                        data_address += script.getNumberValue('TYPE') * 2;\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_arrow_value_of_id(%1, %2)'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_connection_status: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_connected, '1'],\n                                [Lang.Blocks.robotis_disconnected, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_ai_camera_connection_status',\n                    },\n                    paramsKeyMap: {\n                        STATUS: 0,\n                    },\n                    class: 'robotis_koalabot_lite_ai_camera_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4000;\n                        let compareValue = script.getNumberValue('STATUS');\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_connection_status(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_if_detected: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_block, '0'],\n                                [Lang.Blocks.robotis_ai_camera_arrow, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_ai_camera_if_detected',\n                    },\n                    paramsKeyMap: {\n                        DETECT_TYPE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_ai_camera_value',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4005; // block\n                        let detect_type = script.getNumberValue('DETECT_TYPE');\n\n                        if (detect_type == 1) {\n                            data_address = 4006;\n                        } // arrow\n\n                        let result = Entry.RobotisKoalabotLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == 1;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_if_detected(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_set_mode: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_mode_face_recognition, '0'],\n                                [Lang.Blocks.robotis_ai_camera_mode_object_tracking, '1'],\n                                [Lang.Blocks.robotis_ai_camera_mode_object_recognition, '2'],\n                                [Lang.Blocks.robotis_ai_camera_mode_line_tracking, '3'],\n                                [Lang.Blocks.robotis_ai_camera_mode_color_recognition, '4'],\n                                [Lang.Blocks.robotis_ai_camera_mode_tag_recognition, '5'],\n                                [Lang.Blocks.robotis_ai_camera_mode_object_classification, '6'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_koalabot_lite_ai_camera_set_mode',\n                    },\n                    paramsKeyMap: {\n                        AI_CAMERA_MODE: 0,\n                    },\n                    class: 'robotis_koalabot_lite_ai_camera_set',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let ai_camera_mode = script.getField('AI_CAMERA_MODE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4001;\n                        let data_length = 1;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, ai_camera_mode],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.set_ai_camera_mode(%1)'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_print_custom_text: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            'Hello!',\n                        ],\n                        type: 'robotis_koalabot_lite_ai_camera_print_custom_text',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        TEXT: 2,\n                    },\n                    class: 'robotis_koalabot_lite_ai_camera_set',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let text = script.getStringValue('TEXT', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        // Encode the text as UTF-8\n                        let encoder = new TextEncoder();\n                        let utf8Array = encoder.encode(text);\n        \n                        // utf8Array is now a Uint8Array containing the UTF-8 bytes of the text\n                        let text_len = utf8Array.length;\n\n                        if (text_len > 45) text_len = 45;\n\n                        if (x < -160) {\n                            x = 160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = 120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (x < 0) {\n                            x = 65536 + x;\n                        }\n                        if (y < 0) {\n                            y = 65536 + y;\n                        }\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        for (i = 0; i < text_len; i++) {\n                            data_buf.push(utf8Array[i]);\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4200;\n                        let data_length = 6 + text_len;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                        ];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_print_custom_text(%1,%2,%3)'],\n                    },\n                },\n                robotis_koalabot_lite_ai_camera_clear_custom_text: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'robotis_koalabot_lite_ai_camera_clear_custom_text',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_koalabot_lite_ai_camera_set',\n                    isNotFor: ['RobotisKoalabotLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4250;\n                        let data_length = 1;\n\n                        let data_sendqueue = [[data_instruction, data_address, data_length, 1]];\n\n                        return Entry.RobotisKoalabotLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Koalabot.ai_camera_clear_custom_text()'],\n                    },\n                },\n            };\n        }\n\n        requestLocalData() {\n            let packets = [];\n            while (this.robotisBuffer.length > 0) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n                let packet = null;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        packet = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        packet = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n\n                if (packet !== null && Array.isArray(packet)) {\n                    packets.push(...packet);\n                }\n            }\n            return packets;\n        }\n\n        handleLocalData(data) {\n            let stuffLength = 0;\n            //console.log(`length: ${data.length}`);\n            for (let i = 0; i < data.length; i++) {\n                //this.receiveBuffer.push(data[i]);\n                const dataIn = data[i];\n\n                switch (this.packetReceiveState) {\n                    case PACKET_STATE_IDLE:\n                        if (this.headerCount >= 2) {\n                            rxPacket.header[2] = dataIn;\n\n                            if (\n                                rxPacket.header[0] == 0xff &&\n                                rxPacket.header[1] == 0xff &&\n                                rxPacket.header[2] == 0xfd\n                            ) {\n                                this.headerCount = 0;\n                                this.packetReceiveState = PACKET_STATE_RESERVED;\n                            } else {\n                                rxPacket.header[0] = rxPacket.header[1];\n                                rxPacket.header[1] = rxPacket.header[2];\n                                rxPacket.header[2] = 0;\n                            }\n                        } else {\n                            rxPacket.header[this.headerCount] = dataIn;\n                            this.headerCount++;\n                        }\n                        break;\n\n                    case PACKET_STATE_RESERVED:\n                        if (dataIn == 0xfd) {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        } else {\n                            rxPacket.reserved = dataIn;\n                            this.packetReceiveState = PACKET_STATE_ID;\n                        }\n                        break;\n\n                    case PACKET_STATE_ID:\n                        rxPacket.id = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_L;\n                        break;\n\n                    case PACKET_STATE_LENGTH_L:\n                        rxPacket.packetLength = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_H;\n                        break;\n\n                    case PACKET_STATE_LENGTH_H:\n                        rxPacket.packetLength |= dataIn << 8;\n                        if (rxPacket.packetLength < 1000) {\n                            this.packetReceiveState = PACKET_STATE_DATA;\n                        } else {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        }\n                        rxPacket.index = 0;\n                        break;\n\n                    case PACKET_STATE_DATA:\n                        rxPacket.data[rxPacket.index] = dataIn;\n                        rxPacket.index++;\n\n                        if (rxPacket.index >= rxPacket.packetLength - 2) {\n                            this.packetReceiveState = PACKET_STATE_CRC_L;\n                        }\n                        break;\n\n                    case PACKET_STATE_CRC_L:\n                        rxPacket.crcReceived = dataIn;\n                        this.packetReceiveState = PACKET_STATE_CRC_H;\n                        break;\n\n                    case PACKET_STATE_CRC_H:\n                        rxPacket.crcReceived |= dataIn << 8;\n\n                        stuffLength = this.removeStuffing(rxPacket.data, rxPacket.packetLength);\n                        rxPacket.packetLength -= stuffLength;\n\n                        rxPacket.cmd = rxPacket.data[0];\n                        rxPacket.error = rxPacket.data[1];\n\n                        if (rxPacket.cmd == INST_STATUS) {\n                            //console.log(`rx length: ${rxPacket.packetLength}`);\n                            if (rxPacket.packetLength >= 147) {\n                                let tempValue = 0;\n                                for (let i = 0; i < addrMap.length; i++) {\n                                    switch (addrMap[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n\n                                const dxlPositionStartAddr =\n                                    addrMap[addrMap.length - 1][0] + addrMap[addrMap.length - 1][1];\n\n                                // DXL Position\n                                for (let i = 0; i < 20; i++) {\n                                    const currentId =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i];\n                                    const currentPos =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 1] +\n                                        (rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 2] << 8);\n                                    if (currentId != 0xff && currentPos != 0xffff) {\n                                        this.dxlPositions[currentId] = currentPos;\n                                    }\n                                }\n\n                                const lineCategoryStartAddr = dxlPositionStartAddr + 3 * 20;\n                                // line category\n                                this.dataBuffer[5201] = rxPacket.data[2 + lineCategoryStartAddr];\n\n                                const sensorStartAddr = lineCategoryStartAddr + 1;\n\n                                // 온습도+조도+동작감지센서값\n                                this.pirPir[0] = rxPacket.data[2 + sensorStartAddr];\n                                this.pirTemperature[0] = rxPacket.data[2 + sensorStartAddr + 1];\n                                this.pirHumidity[0] = rxPacket.data[2 + sensorStartAddr + 2];\n                                this.pirBrightness[0] = rxPacket.data[2 + sensorStartAddr + 3];\n\n                                // 거리+버튼+조도센서값\n                                this.distanceDistance[0] =\n                                    rxPacket.data[2 + sensorStartAddr + 4] +\n                                    (rxPacket.data[2 + sensorStartAddr + 5] << 8);\n                                this.distanceButton[0] = rxPacket.data[2 + sensorStartAddr + 6];\n                                this.distanceBrightness[0] = rxPacket.data[2 + sensorStartAddr + 7];\n\n                                for (let i = 0; i < addrMap2.length; i++) {\n                                    switch (addrMap2[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap2[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n                            }\n                        }\n\n                        this.packetReceiveState = PACKET_STATE_IDLE;\n                        break;\n\n                    default:\n                    // code block\n                }\n            }\n        }\n\n        requestInitialData() {\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 1010, 2, 0xABC2]); // 아래 20번 모드 진입후 코알라 얼굴로 변경준비\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 20]);\n            this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기\n            this.robotisBuffer.push([INST_WRITE, 20, 1, 0]); // bypass port를 BLE로 설정\n            this.robotisBuffer.push([INST_WRITE, 23, 1, 1]); // auto report 기능 켜기\n            this.robotisBuffer.push([INST_WRITE, 4250, 1, 1]); // ai_camera 텍스트 지우기\n            this.robotisBuffer.push([INST_WRITE, 722, 1, 0]); // dxl 토크 끄기\n            //this.robotisBuffer.push([INST_WRITE, 63, 1, 1]); // 부저음 시간 설정\n            //this.robotisBuffer.push([INST_WRITE, 60, 1, 70]); // 부저음 발생\n            this.robotisBuffer.push([INST_WRITE, 113, 2, 1040]); // \"띵\" 효과음 발생\n            /*\n            //const ping = [0xff, 0xff, 0xfd, 0x00, 0xc8, 0x03, 0x00, 0x01, 0x3b, 0xfa];\n            // run entry mode\n            const packet = [\n                0xff, 0xff, 0xfd, 0x00, 0xc8, 0x07, 0x00, 0x03, 0x15, 0x00, 0x14, 0x00, 0xc1, 0xb3,\n            ];\n            return packet;\n            */\n        }\n\n        async initialHandshake() {\n            const status = true;\n            let sendBuffer = null;\n            this.requestInitialData();\n            while (this.robotisBuffer.length) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        sendBuffer = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        sendBuffer = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n                Entry.hwLite.serial.sendAsciiAsBuffer(sendBuffer);\n                if (instruction == INST_WRITE && address == 2100 && length == 1 && value == 1) {\n                    this.robotisBuffer = [];\n                }\n            }\n            return status;\n        }\n    })();\n})();\n\nmodule.exports = Entry.RobotisKoalabotLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_robotis_rgee_lite.js",
    "content": "'use strict';\n\nconst INST_NONE = 0;\nconst INST_READ = 2;\nconst INST_WRITE = 3;\nconst INST_DXL_SYNCWRITE = 4;\nconst INST_DXL_REGWRITE = 5;\nconst INST_DXL_ACTION = 6;\nconst INST_BYPASS_READ = 0xa2;\nconst INST_BYPASS_WRITE = 0xa3;\n\nconst INST_STATUS = 0x55;\n\nconst PACKET_STATE_IDLE = 0;\nconst PACKET_STATE_RESERVED = 1;\nconst PACKET_STATE_ID = 2;\nconst PACKET_STATE_LENGTH_L = 3;\nconst PACKET_STATE_LENGTH_H = 4;\nconst PACKET_STATE_DATA = 5;\nconst PACKET_STATE_CRC_L = 6;\nconst PACKET_STATE_CRC_H = 7;\n\nconst DEFAULT_DELAY = 50;\n\nconst rxPacket = {\n    header: [0, 0, 0],\n    reserved: 0,\n    id: 0,\n    cmd: 0,\n    error: 0,\n    type: 0,\n    index: 0,\n    packetLength: 0,\n    paramLength: 0,\n    crc: 0,\n    crcReceived: 0,\n    checksum: 0,\n    checksumReceived: 0,\n    data: [],\n};\n\nconst addrMap = [\n    [0, 4, 302],\n    [4, 1, 42],\n    [5, 1, 44],\n    [6, 1, 45],\n    [7, 1, 47],\n    [8, 1, 50],\n    [9, 1, 51],\n    [10, 1, 52],\n    [11, 1, 68],\n    [12, 2, 70],\n    [14, 2, 72],\n    [16, 2, 74],\n    [18, 2, 76],\n    [20, 2, 78],\n    [22, 2, 80],\n    [24, 2, 82],\n    [26, 2, 84],\n    [28, 1, 86],\n    [29, 1, 87],\n    [30, 2, 88],\n    [32, 2, 90],\n    [34, 1, 112],\n    [35, 1, 118],\n    [36, 1, 119],\n    [37, 1, 122],\n    [38, 1, 123],\n    [39, 1, 124],\n    [40, 1, 125],\n    [41, 1, 160],\n    [42, 1, 220],\n    [43, 2, 360],\n    [45, 2, 362],\n    [47, 2, 364],\n    [49, 2, 366],\n    [51, 2, 368],\n    [53, 2, 370],\n    [55, 1, 372],\n    [56, 1, 373],\n    [57, 1, 374],\n    [58, 1, 375],\n    [59, 1, 376],\n    [60, 1, 377],\n    [61, 1, 378],\n    [62, 1, 379],\n    [63, 1, 380],\n    [64, 1, 381],\n    [65, 1, 382],\n    [66, 1, 383],\n    [67, 1, 500],\n    [68, 1, 501],\n    [69, 8, 502],\n    [77, 1, 700],\n    [78, 1, 810],\n    [79, 1, 2134],\n    [80, 1, 5015],\n    [81, 1, 5030],\n    [82, 1, 5031],\n    [83, 1, 5040],\n];\n\nconst addrMap2 = [\n    [153, 1, 4000],\n    [154, 2, 4003],\n    [156, 1, 4005],\n    [157, 1, 4006],\n    [158, 2, 4009],\n    [160, 2, 4011],\n    [162, 2, 4013],\n    [164, 2, 4015],\n    [166, 2, 4017],\n    [168, 2, 4019],\n    [170, 2, 4021],\n    [172, 2, 4023],\n    [174, 2, 4025],\n    [176, 2, 4027],\n    [178, 1, 4031],\n    [179, 1, 4032],\n    [180, 1, 4033],\n    [181, 2, 4036],\n    [183, 2, 4038],\n    [185, 2, 4040],\n    [187, 2, 4042],\n    [189, 2, 4044],\n    [191, 2, 4046],\n    [193, 2, 4048],\n    [195, 2, 4050],\n];\n\nconst crcTable = [\n    0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039,\n    0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,\n    0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9,\n    0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,\n    0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099,\n    0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,\n    0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea,\n    0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,\n    0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179,\n    0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,\n    0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309,\n    0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,\n    0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359,\n    0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,\n    0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9,\n    0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,\n    0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9,\n    0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,\n    0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, 0x0246, 0x024c, 0x8249,\n    0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,\n    0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219,\n    0x0208, 0x820d, 0x8207, 0x0202,\n];\n\nconst rb100_last_valid_value = [];\nlet bg_color = 0;\nlet beat_per_minute = 75;\nlet camera_id_for_use = 0;\n\n(function () {\n    Entry.RobotisRgeeLite = new (class RobotisRgeeLite {\n        constructor() {\n            this.id = '070501';\n            this.url = 'http://www.robotis.com';\n            this.imageName = 'robotis_rgee_lite.png';\n            this.name = 'RobotisRgeeLite';\n            this.blockMenuBlocks = [\n                // 값 블록\n                'robotis_rgee_lite_cm_ir_value',\n                'robotis_rgee_lite_cm_ir_compare',\n                'robotis_rgee_lite_detectFrontObj',\n                'robotis_rgee_lite_cm_btn_value',\n                'robotis_rgee_lite_cm_joystick_value',\n                'robotis_rgee_lite_mic',\n                'robotis_rgee_lite_detectSound_compare',\n                'robotis_rgee_lite_imu',\n                'robotis_rgee_lite_roll_pitch',\n\n                // 음계\n                'robotis_rgee_lite_buzzer_index',\n\n                // LCD 제어\n                'robotis_rgee_lite_rgee_screen',\n                'robotis_rgee_lite_rgee_anim_screen',\n                'robotis_rgee_lite_icon',\n                'robotis_rgee_lite_LCDBright',\n                'robotis_rgee_lite_LCDColor',\n\n                // LED 제어\n                'robotis_rgee_lite_led_brightness',\n                'robotis_rgee_lite_led_pattern',\n\n\n                // 소리\n                'robotis_rgee_lite_Hello',\n                'robotis_rgee_lite_effectSound',\n                'robotis_rgee_lite_record',\n                'robotis_rgee_lite_playRecord',\n\n                // 다른 로봇 LCD 화면 제어\n                'robotis_rgee_lite_rla_screen',\n                'robotis_rgee_lite_rla_anim_screen',\n                'robotis_rgee_lite_kkokdu_screen',\n                'robotis_rgee_lite_kkokdu_anim_screen',\n                'robotis_rgee_lite_text_screen',\n                \n                // 주행 제어\n                'robotis_rgee_lite_drive_simple',\n                'robotis_rgee_lite_drive_stop',\n                'robotis_rgee_lite_motion',\n                'robotis_rgee_lite_follow_line',\n                'robotis_rgee_lite_stop_follow_line',\n            ];\n            this.portData = {\n                baudRate: 57600,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                connectionType: 'bytestream',\n                bufferSize: 128,\n                constantServing: true,\n            };\n            this.duration = 15;\n            this.setZero();\n\n            this.timeouts = [];\n\n            this.robotisBuffer = []; // buffer to transmit to H/W\n            this.receiveBuffer = []; // buffer to receive from H/W\n            this.dataBuffer = []; // saved control table value buffer\n\n            this.packetReceiveState = 0;\n            this.headerCount = 0;\n\n            this.dxlPositions = [];\n\n            this.pirPir = [];\n            this.pirTemperature = [];\n            this.pirHumidity = [];\n            this.pirBrightness = [];\n            this.distanceDistance = [];\n            this.distanceButton = [];\n            this.distanceBrightness = [];\n        }\n\n        setZero() {\n            this.timeouts = [];\n            this.__removeAllTimeouts();\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 7]); // App Coding 모드\n            this.robotisBuffer.push([INST_WRITE, 40, 2, 0]); // LED 끄기\n            this.robotisBuffer.push([INST_WRITE, 66, 2, 0]); // 모션 종료\n            this.robotisBuffer.push([INST_WRITE, 710, 2, 0]); // 바퀴 정지\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 20]); // App Coding 모드\n            this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기\n            camera_id_for_use = 0;\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        __removeTimeout(id) {\n            clearTimeout(id);\n            const idx = this.timeouts.indexOf(id);\n            if (idx >= 0) {\n                this.timeouts.splice(idx, 1);\n            }\n        }\n\n        __removeAllTimeouts() {\n            const timeouts = this.timeouts;\n            for (const i in timeouts) {\n                clearTimeout(timeouts[i]);\n            }\n            this.timeouts = [];\n        }\n\n        getMonitorPort() {\n            return { ...this.sensory, ...this.motoring, ...this.lineTracer };\n        }\n\n        writePacket(id, address, length, value) {\n            if (length > 256) {\n                console.log(`######### invalid length: ${length}`);\n                return null;\n            }\n            console.log('######### writePacket');\n            const packet = [];\n            let i = 0;\n            packet.push(0xff);\n            packet.push(0xff);\n            packet.push(0xfd);\n            packet.push(0x00);\n            packet.push(id);\n            packet.push(length + 5);\n            packet.push(0x00);\n            packet.push(INST_WRITE);\n            packet.push(this.getLowByte(address));\n            packet.push(this.getHighByte(address));\n            switch (length) {\n                case 1:\n                    packet.push(this.getLowByte(value));\n                    break;\n                case 2:\n                    packet.push(this.getLowByte(value));\n                    packet.push(this.getHighByte(value));\n                    break;\n                case 4:\n                    packet.push(this.getLowByte(this.getLowWord(value)));\n                    packet.push(this.getHighByte(this.getLowWord(value)));\n                    packet.push(this.getLowByte(this.getHighWord(value)));\n                    packet.push(this.getHighByte(this.getHighWord(value)));\n                    break;\n                default:\n                    for (i = 0; i < length; i++) {\n                        if (typeof value[i] == 'number') {\n                            packet.push(value[i]);\n                        } else if (typeof value[i] == 'string') {\n                            packet.push(value[i].charCodeAt(0));\n                        }\n                    }\n                    break;\n            }\n            const crc = this.updateCRC(0, packet, packet.length);\n            packet.push(this.getLowByte(crc));\n            packet.push(this.getHighByte(crc));\n            return packet;\n        }\n\n        makeWord(a, b) {\n            return (a & 0xff) | ((b & 0xff) << 8);\n        }\n\n        getLowByte(a) {\n            return a & 0xff;\n        }\n\n        getHighByte(a) {\n            return (a >> 8) & 0xff;\n        }\n\n        getLowWord(a) {\n            return a & 0xffff;\n        }\n\n        getHighWord(a) {\n            return (a >> 16) & 0xffff;\n        }\n\n        updateCRC(crcAccum, dataBlkPtr, dataBlkSize) {\n            let i = 0;\n            let j = 0;\n            let crc = crcAccum;\n\n            for (j = 0; j < dataBlkSize; j++) {\n                i = ((crc >> 8) ^ dataBlkPtr[j]) & 0xff;\n                crc = (crc << 8) ^ crcTable[i];\n            }\n\n            return crc;\n        }\n\n        removeStuffing(buffer, length) {\n            let i = 0;\n            let stuffLength = 0;\n            let index = 0;\n\n            for (i = 0; i < length; i++) {\n                if (i >= 2) {\n                    if (buffer[i - 2] == 0xff && buffer[i - 1] == 0xff && buffer[i] == 0xfd) {\n                        i++;\n                        stuffLength++;\n                    }\n                }\n                buffer[index++] = buffer[i];\n            }\n\n            return stuffLength;\n        }\n\n        postCallReturn(script, data, ms) {\n            /*\n            if (data == null) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            } else if (data.length == 0) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n            */\n            if (!script.isStart) {\n                script.isStart = true;\n                script.timeFlag = 1;\n                for (let i = 0; i < data.length; i++) {\n                    this.robotisBuffer.push(data[i]);\n                }\n                //delay ms\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, ms);\n                return script;\n            } else if (script.timeFlag) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.timeFlag;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // 값 블록\n                        robotis_rgee_lite_cm_ir_value: '%1 번 IR 센서 값',\n                        robotis_rgee_lite_cm_ir_compare: '%1 번 IR 센서 값이 %2  %3이면',\n                        robotis_rgee_lite_detectFrontObj: '앞에 물체가 있으면',\n                        robotis_rgee_lite_cm_btn_value: '%1 버튼이 %2 이면',\n                        robotis_rgee_lite_cm_joystick_value:\n                            '조이스틱 위치가 %1 이면',\n                        robotis_rgee_lite_mic: '마이크 음량(dB)',\n                        robotis_rgee_lite_detectSound_compare: '소리가 %1에서 나면',\n                        robotis_rgee_lite_imu: '%1축의 %2 값',\n                        robotis_rgee_lite_roll_pitch: '제어기 각도 %1 값',\n\n                        // 음계\n                        robotis_rgee_lite_buzzer_index: '제어기 음계값 %1 을(를) %2 옥타브로 %3 초 동안 %4 %5',\n\n                        // LCD 제어\n                        robotis_rgee_lite_rgee_screen: '제어기 화면 배경을 알쥐 %1 (으)로 선택 %2',\n                        robotis_rgee_lite_rgee_anim_screen:\n                            '제어기 화면 애니메이션을 알쥐 %1 (으)로 선택 %2',\n                        robotis_rgee_lite_icon: \n                            \"제어기 화면에 %1 출력하기 %5\",\n                        robotis_rgee_lite_LCDBright: '제어기 화면 밝기를 %1 (으)로 정하기 %2',\n                        robotis_rgee_lite_LCDColor: '제어기 화면 색상을 %1 (으)로 정하기 %2',\n\n                        // LED 제어\n                        robotis_rgee_lite_led_brightness: '제어기 %1 LED 밝기를 %2(으)로 정하기 %3',\n                        robotis_rgee_lite_led_pattern: '제어기 %1 LED %2 %3',\n                        \n                        // 소리\n                        robotis_rgee_lite_Hello: '%1 말하기 %2',\n                        robotis_rgee_lite_effectSound: '효과음 %1 재생하기 %2',\n                        robotis_rgee_lite_record: '%1 번 방에 녹음하기 %2',\n                        robotis_rgee_lite_playRecord: '%1 번 방 소리 재생하기 %2',\n\n                        // 다른 로봇 LCD 제어\n                        robotis_rgee_lite_rla_screen: '제어기 화면 배경을 알라 %1 (으)로 선택 %2',\n                        robotis_rgee_lite_rla_anim_screen:\n                            '제어기 화면 애니메이션을 알라 %1 (으)로 선택 %2',\n                        robotis_rgee_lite_kkokdu_screen: '제어기 화면 배경을 꼭두 %1 (으)로 선택 %2',\n                        robotis_rgee_lite_kkokdu_anim_screen:\n                            '제어기 화면 애니메이션을 꼭두 %1 (으)로 선택 %2',\n                        robotis_rgee_lite_text_screen:\n                            '제어기 화면에 %1을(를) (%2, %3)위치에 %4 로 %5(으)로 출력하기 %6',\n\n                            \n                        // 주행 제어\n                        robotis_rgee_lite_drive_simple: '알쥐 %1 속도로 %2 하기 %3',\n                        robotis_rgee_lite_drive_stop: '알쥐 정지하기 %1',\n                        robotis_rgee_lite_motion: '알쥐 %1 %2',\n                        robotis_rgee_lite_follow_line: '%1 속도로 라인 따라가기 %2',\n                        robotis_rgee_lite_stop_follow_line: '라인 따라가기 종료 %1',\n                    },\n                    Helper: {\n                        // 값 블록\n                        robotis_rgee_lite_cm_ir_value:\n                            '지정한 번호의 IR 센서 값(범위: 0 ~ 400)',\n                        robotis_rgee_lite_cm_ir_compare:\n                            \"지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_rgee_lite_detectFrontObj:\n                            \"지정한 센서 앞에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_rgee_lite_cm_btn_value:\n                            \"지정한 버튼이 눌렸다가 해제되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_rgee_lite_cm_joystick_value:\n                            \"조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다..\",\n                        robotis_rgee_lite_mic:\n                            '마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.',\n                        robotis_rgee_lite_detectSound_compare:\n                            \"소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_rgee_lite_imu:\n                            '지정한 축의 지정한 가속도센서/자이로센서의 값\\n범위: -100 ~ 100',\n                        robotis_rgee_lite_roll_pitch:\n                            'roll/pitch 값\\nroll: -180° ~ 180°, pitch: -90° ~ 90°',\n\n                        // 소리\n                        robotis_rgee_lite_buzzer_index: '지정한 음계, 옥타브, 시간만큼 연주하기',\n\n                        // LCD 제어\n                        robotis_rgee_lite_rgee_screen: '제어기 화면배경을 알쥐의 지정한 표정으로 설정',\n                        robotis_rgee_lite_rgee_anim_screen:\n                            '제어기 화면 애니메이션을 알쥐의 지정한 표정으로 설정',\n                        robotis_rgee_lite_icon:\n                            '화면 중앙에 지정한 아이콘을 표시',\n                        robotis_rgee_lite_LCDBright: '화면 밝기를 설정\\n밝기범위: 1% ~ 100%',\n                        robotis_rgee_lite_LCDColor: '화면 색상을 설정',\n\n                        // LED 제어\n                        robotis_rgee_lite_led_brightness: '제어기의 지정한 LED의 밝기를 설정정',\n                        robotis_rgee_lite_led_pattern: '제어기의 LED의 깜박임 패턴 설정',\n\n                        // 소리\n                        robotis_rgee_lite_Hello: '지정한 문장을 말하기',\n                        robotis_rgee_lite_effectSound: '지정한 효과음 재생하기',\n                        robotis_rgee_lite_record: '제어기의 지정한 번호에 녹음하기',\n                        robotis_rgee_lite_playRecord: '제어기의 지정한 번호의 녹음음성 재생하기기',\n\n                        // 다른 로봇 LCD 제어\n                        robotis_rgee_lite_rla_screen: '제어기 화면배경을 알라의 지정한 표정으로 설정',\n                        robotis_rgee_lite_rla_anim_screen:\n                            '제어기 화면 애니메이션을 알라의 지정한 표정으로 설정',\n                        robotis_rgee_lite_kkokdu_screen: '제어기 화면배경을 꼭두의 지정한 표정으로 설정',\n                        robotis_rgee_lite_kkokdu_anim_screen:\n                            '제어기 화면 애니메이션을 꼭두두의 지정한 표정으로 설정',\n                        robotis_rgee_lite_text_screen:\n                            '화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n                            \n                        // 주행 제어\n                        robotis_rgee_lite_drive_simple: '알쥐를 지정한 속도와 방향으로 주행',\n                        robotis_rgee_lite_drive_stop: '알쥐 정지하기',\n                        robotis_rgee_lite_motion: '알쥐 지정한 동작을 하기',\n                        robotis_rgee_lite_follow_line: '지정한 속도로 라인 따라가기',\n                        robotis_rgee_lite_stop_follow_line: '라인 따라가기 종료',\n\n                    },\n                    Blocks: {\n                        robotis_white: \"흰색\",\n                        robotis_gray: \"회색\",\n                        robotis_darkgray: \"진회색\",\n                        robotis_black: \"검정\",\n                        robotis_purple: \"보라\",\n                        robotis_pink: \"분홍색\",\n                        robotis_red: \"빨강\",\n                        robotis_orange: \"주황\",\n                        robotis_brown: \"갈색\",\n                        robotis_yellow: \"노랑\",\n                        robotis_green: \"초록\",\n                        robotis_blue: \"파랑\",\n                        robotis_lightblue: \"연파랑\",\n                        robotis_darkblue: \"남색\",\n                        robotis_left: \"왼쪽\",\n                        robotis_center: \"중앙\",\n                        robotis_right: \"오른쪽\",\n                        robotis_both: \"양쪽\",\n                        robotis_korean1: \"안녕하세요\",\n                        robotis_korean2: \"반가워요\",\n                        robotis_korean3: \"알겠어요\",\n                        robotis_korean4: \"아니에요\",\n                        robotis_korean5: \"모르겠어요\",\n                        robotis_korean6: \"좋아요\",\n                        robotis_korean7: \"싫어요\",\n                        robotis_korean8: \"이름을말하세요\",\n                        robotis_korean9: \"무엇을도와줄까?\",\n                        robotis_korean10: \"잘했어\",\n                        robotis_korean11: \"괜찮아\",\n                        robotis_korean12: \"다시해보자\",\n                        robotis_korean13: \"고마워\",\n                        robotis_korean14: \"다시말해줄래?\",\n                        robotis_korean15: \"최고야!\",\n                        robotis_korean16: \"신나요\",\n                        robotis_korean17: \"즐거워요\",\n                        robotis_korean18: \"미안해요\",\n                        robotis_korean19: \"화나요\",\n                        robotis_korean20: \"부끄러워요\",\n                        robotis_korean21: \"무서워요\",\n                        robotis_korean22: \"속상해요\",\n                        robotis_korean23: \"사랑해요\",\n                        robotis_korean24: \"예뻐요\",\n                        robotis_korean25: \"신기해요\",\n                        robotis_korean26: \"초조해요\",\n                        robotis_korean27: \"앞으로가자\",\n                        robotis_korean28: \"뒤로가자\",\n                        robotis_korean29: \"일어나자\",\n                        robotis_korean30: \"넘어졌네?\",\n                        robotis_korean31: \"오예\",\n                        robotis_korean32: \"아싸\",\n                        robotis_korean33: \"어머\",\n                        robotis_korean34: \"이런\",\n                        robotis_korean35: \"오호\",\n                        robotis_korean36: \"하하하\",\n                        robotis_korean37: \"호호호\",\n                        robotis_korean38: \"졸려\",\n                        robotis_korean39: \"자장가를들려줘\",\n                        robotis_korean40: \"안녕\",\n                        robotis_korean41: \"배고프다\",\n                        robotis_korean42: \"도토리땡긴다\",\n                        robotis_korean43: \"아.씻고싶어\",\n                        robotis_korean44: \"비누목욕시간이야\",\n                        robotis_korean45: \"심심한데\",\n                        robotis_korean46: \"간식먹을까\",\n                        robotis_korean47: \"아파요\",\n                        robotis_korean48: \"약은없나요?\",\n                        robotis_korean49: \"어디로가야하지?\",\n                        robotis_korean50: \"와아도착이다\",\n                        robotis_korean51: \"왼쪽으로가자\",\n                        robotis_korean52: \"오른쪽으로가자\",\n                        robotis_korean53: \"깜짝이야\",\n                        robotis_korean54: \"찾았다\",\n                        robotis_korean55: \"여긴없네\",\n                        robotis_korean56: \"혹시나불렀어?\",\n                        robotis_korean57: \"내려주세요\",\n                        robotis_korean58: \"앗\",\n                        robotis_korean59: \"힝\",\n                        robotis_korean60: \"이익\",\n                        robotis_dog: \"개\",\n                        robotis_frog: \"개구리\",\n                        robotis_cat: \"고양이\",\n                        robotis_chicken: \"닭\",\n                        robotis_tiger: \"호랑이\",\n                        robotis_mouse: \"쥐\",\n                        robotis_ambul: \"앰뷸런스\",\n                        robotis_Horn: \"경적(빵빵)\",\n                        robotis_siren: \"사이렌(경찰차)\",\n                        robotis_whistle: \"호루라기\",\n                        robotis_gun: \"총소리\",\n                        robotis_clap: \"박수소리\",\n                        robotis_melody1: \"멜로디1\",\n                        robotis_melody2: \"멜로디2\",\n                        robotis_melody3: \"멜로디3\",\n                        robotis_melody4: \"멜로디4\",\n                        robotis_forward: \"앞으로\",\n                        robotis_backward: \"뒤로\",\n                        robotis_acceleration: \"가속도\",\n                        robotis_gyro: \"자이로\",\n                        robotis_run: \"실행\",\n                        robotis_cancel: \"취소\",\n                        robotis_push: \"눌림\",\n                        robotis_notPush: \"안눌림\",\n                        robotis_play: \"연주\",\n                        robotis_rest: \"쉼표\",\n                        robotis_face01: \"와하하\",\n                        robotis_face02: \"싱글벙글\",\n                        robotis_face03: \"큭큭큭\",\n                        robotis_face04: \"냠냠\",\n                        robotis_face05: \"겁먹음\",\n                        robotis_face06: \"답답\",\n                        robotis_face07: \"갸우뚱\",\n                        robotis_face08: \"어벙벙\",\n                        robotis_face09: \"고함\",\n                        robotis_face10: \"화남\",\n                        robotis_face11: \"킁킁(왼쪽)\",\n                        robotis_face12: \"킁킁(오른쪽)\",\n                        robotis_face13: \"킁킁(아래)\",\n                        robotis_face14: \"안심\",\n                        robotis_face15: \"기절\",\n                        robotis_face16: \"헤롱헤롱\",\n                        robotis_face17: \"하품\",\n                        robotis_face18: \"졸림\",\n                        robotis_face19: \"잠듦\",\n                        robotis_face20: \"마음앓이\",\n                        robotis_face21: \"폭풍눈물\",\n                        robotis_face22: \"목욕\",\n                        robotis_face23: \"햐트뿅뿅\",\n        \n                        robotis_car_anim01: \"기본 표정\",\n                        robotis_car_anim02: \"감동\",\n                        robotis_car_anim03: \"미소\",\n                        robotis_car_anim04: \"웃음\",\n                        robotis_car_anim05: \"기쁨\",\n                        robotis_car_anim06: \"행복\",\n                        robotis_car_anim07: \"자신감\",\n                        robotis_car_anim08: \"화남\",\n                        robotis_car_anim09: \"우울\",\n                        robotis_car_anim10: \"슬픔\",\n                        robotis_car_anim11: \"고통\",\n                        robotis_car_anim12: \"기절\",\n                        robotis_car_anim13: \"공포\",\n                        robotis_car_anim14: \"하품\",\n                        robotis_car_anim15: \"졸림\",\n                        robotis_car_anim16: \"오른쪽보기\",\n                        robotis_car_anim17: \"왼쪽보기\",\n                        robotis_car_anim18: \"앞쪽보기\",\n                        robotis_car_anim19: \"깜짝놀람\",\n        \n                        robotis_flashing1: \"점멸1\",\n                        robotis_flashing2: \"점멸2\",\n                        robotis_flashing3: \"점멸3\",\n                        robotis_flashing4: \"점멸4\",\n                        robotis_flashing5: \"점멸5\",\n                        robotis_flashing6: \"점멸6\",\n                        robotis_flashing7: \"점멸7\",\n                        robotis_flashing8: \"점멸8\",\n                        robotis_flashing9: \"점멸9\",\n                        robotis_moveF: \"전진\",\n                        robotis_moveB: \"후진\",\n                        robotis_moveL: \"좌회전\",\n                        robotis_moveR: \"우회전\",\n                        robotis_moveU: 'U턴',\n                        robotis_moveL_in_place: '제자리 좌회전',\n                        robotis_moveR_in_place: '제자리 우회전',\n                        robotis_moveU_in_place: '제자리 U턴',\n                        robotis_moveRG1: \"일어서기\",\n                        robotis_moveRG2: \"앉기\",\n                        robotis_moveRG3: \"발버둥\",\n                        robotis_moveRG4: \"발들기\",\n                        robotis_stMotion1: \"기본자세\",\n                        robotis_stMotion2: \"전진\",\n                        robotis_stMotion3: \"우전진\",\n                        robotis_stMotion4: \"좌전진\",\n                        robotis_stMotion5: \"후진\",\n                        robotis_stMotion6: \"오른쪽으로\",\n                        robotis_stMotion7: \"왼쪽으로\",\n                        robotis_stMotion8: \"우회전\",\n                        robotis_stMotion9: \"좌회전\",\n                        robotis_spMotion1: \"오른손 들기\",\n                        robotis_spMotion2: \"오른손 내리기\",\n                        robotis_spMotion3: \"왼손 들기\",\n                        robotis_spMotion4: \"왼손 내리기\",\n                        robotis_spMotion5: \"양손 들기\",\n                        robotis_spMotion6: \"양손 내리기\",\n                        robotis_spMotion7: \"뒤로 넘어지기\",\n                        robotis_spMotion8: \"앞으로 넘어지기\",\n                        robotis_spMotion9: \"앞으로 일어서기\",\n                        robotis_spMotion10: \"뒤로 일어서기\",\n                        robotis_spMotion11: \"방어\",\n                        robotis_spMotion12: \"공격1\",\n                        robotis_spMotion13: \"공격2\",\n                        robotis_spMotion14: \"공격3\",\n                        robotis_spMotion15: \"공격4\",\n                        robotis_screen1: \"가위\",\n                        robotis_screen2: \"바위\",\n                        robotis_screen3: \"보\",\n                        robotis_screen_text_font_small: \"작은 폰트\",\n                        robotis_screen_text_font_big: \"큰 폰트\",\n                        robotis_sensing_temperature: \"온도센서\",\n                        robotis_sensing_humidity: \"습도센서\",\n                        robotis_sensing_brightness: \"밝기센서\",\n                        robotis_sensing_motion: \"움직임센서\",\n                        robotis_sensing_button: \"버튼센서\",\n                        robotis_sensing_distance: \"거리센서\",\n                        robotis_sensing_ir_left: \"왼쪽 적외선센서\",\n                        robotis_sensing_ir_right: \"오른쪽 적외선센서\",\n                    },\n                },\n                en: {\n                    template: {                        \n                        // Value Blocks\n                        robotis_rgee_lite_cm_ir_value: 'IR sensor value of No. %1',\n                        robotis_rgee_lite_cm_ir_compare: 'If the IR sensor value of No. %1 is %2 %3',\n                        robotis_rgee_lite_detectFrontObj: 'If there is an object in front',\n                        robotis_rgee_lite_cm_btn_value: 'If button %1 is %2',\n                        robotis_rgee_lite_cm_joystick_value: 'If joystick is at %1',\n                        robotis_rgee_lite_mic: 'Microphone volume (dB)',\n                        robotis_rgee_lite_detectSound_compare: 'If the sound comes from %1',\n                        robotis_rgee_lite_imu: '%2 value of %1 axis',\n                        robotis_rgee_lite_roll_pitch: 'Controller angle %1 value',\n\n                        // Musical Scale\n                        robotis_rgee_lite_buzzer_index: 'Play note %1 on controller in octave %2 for %3 seconds %4 %5',\n\n                        // LCD Control\n                        robotis_rgee_lite_rgee_screen: 'Set controller screen background to R-Gee %1 %2',\n                        robotis_rgee_lite_rgee_anim_screen: 'Set controller screen animation to R-Gee %1 %2',\n                        robotis_rgee_lite_icon: 'Display %1 on controller screen %5',\n                        robotis_rgee_lite_LCDBright: 'Set controller screen brightness to %1 %2',\n                        robotis_rgee_lite_LCDColor: 'Set controller screen color to %1 %2',\n\n                        // LED Control\n                        robotis_rgee_lite_led_brightness: 'Set controller LED %1 brightness to %2 %3',\n                        robotis_rgee_lite_led_pattern: 'Controller LED %1 %2 %3',\n\n                        // Sound\n                        robotis_rgee_lite_Hello: 'Say \"%1\" %2',\n                        robotis_rgee_lite_effectSound: 'Play sound effect %1 %2',\n                        robotis_rgee_lite_record: 'Record in slot %1 %2',\n                        robotis_rgee_lite_playRecord: 'Play sound from slot %1 %2',\n\n                        // Other Robot LCD Control\n                        robotis_rgee_lite_rla_screen: 'Set controller screen background to Kodala %1 %2',\n                        robotis_rgee_lite_rla_anim_screen: 'Set controller screen animation to Kodala %1 %2',\n                        robotis_rgee_lite_kkokdu_screen: 'Set controller screen background to TIG %1 %2',\n                        robotis_rgee_lite_kkokdu_anim_screen: 'Set controller screen animation to TIG %1 %2',\n                        robotis_rgee_lite_text_screen: 'Display \"%1\" on screen at (%2, %3) with font %4 and color %5 %6',\n\n                        // Driving Control\n                        robotis_rgee_lite_drive_simple: 'Move R-Gee at speed %1 in direction %2 %3',\n                        robotis_rgee_lite_drive_stop: 'Stop R-Gee %1',\n                        robotis_rgee_lite_motion: 'R-Gee %1 %2',\n                        robotis_rgee_lite_follow_line: 'Follow line at speed %1 %2',\n                        robotis_rgee_lite_stop_follow_line: 'Stop following line %1',\n                    },\n                    Helper: {\n                        // Value blocks\n                        robotis_rgee_lite_cm_ir_value: 'IR sensor value of the specified number (Range: 0 ~ 400)',\n                        robotis_rgee_lite_cm_ir_compare: \"Returns 'true' if the comparison of the IR sensor value of the specified number and the given value is correct; otherwise returns 'false'.\",\n                        robotis_rgee_lite_detectFrontObj: \"Returns 'true' if an object is detected in front of the specified sensor; otherwise returns 'false'.\",\n                        robotis_rgee_lite_cm_btn_value: \"Returns 'true' if the specified button was pressed and released; otherwise returns 'false'.\",\n                        robotis_rgee_lite_cm_joystick_value: \"Returns 'true' if the joystick position matches the specified state; otherwise returns 'false'.\",\n                        robotis_rgee_lite_mic: 'Displays the intensity of sound detected by the microphone in decibels (dB).',\n                        robotis_rgee_lite_detectSound_compare: \"Returns 'true' if the direction of the sound matches the specified direction; otherwise returns 'false'.\",\n                        robotis_rgee_lite_imu: 'Value of the specified axis of the accelerometer/gyroscope sensor\\nRange: -100 ~ 100',\n                        robotis_rgee_lite_roll_pitch: 'Roll/pitch values\\nRoll: -180° ~ 180°, Pitch: -90° ~ 90°',\n\n                        // Sound\n                        robotis_rgee_lite_buzzer_index: 'Play the specified scale, octave, and duration',\n\n                        // LCD control\n                        robotis_rgee_lite_rgee_screen: 'Set the controller screen background to the specified R-Gee expression',\n                        robotis_rgee_lite_rgee_anim_screen: 'Set the controller screen animation to the specified R-Gee expression',\n                        robotis_rgee_lite_icon: 'Display the specified icon at the center of the screen',\n                        robotis_rgee_lite_LCDBright: 'Set the screen brightness\\nBrightness range: 1% ~ 100%',\n                        robotis_rgee_lite_LCDColor: 'Set the screen color',\n\n                        // LED control\n                        robotis_rgee_lite_led_brightness: 'Set the brightness of the specified LED on the controller',\n                        robotis_rgee_lite_led_pattern: 'Set the blinking pattern of the LED on the controller',\n\n                        // Sound\n                        robotis_rgee_lite_Hello: 'Speak the specified sentence',\n                        robotis_rgee_lite_effectSound: 'Play the specified sound effect',\n                        robotis_rgee_lite_record: 'Record on the specified number of the controller',\n                        robotis_rgee_lite_playRecord: 'Play the recorded voice of the specified number on the controller',\n\n                        // Other robot LCD control\n                        robotis_rgee_lite_rla_screen: 'Set the controller screen background to the specified expression of R-LA',\n                        robotis_rgee_lite_rla_anim_screen: 'Set the controller screen animation to the specified expression of R-LA',\n                        robotis_rgee_lite_kkokdu_screen: 'Set the controller screen background to the specified expression of Kkokdu',\n                        robotis_rgee_lite_kkokdu_anim_screen: 'Set the controller screen animation to the specified expression of Kkokdu',\n                        robotis_rgee_lite_text_screen: 'Set the location, font size, and color of the specified phrase to be displayed on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n\n                        // Driving control (duplicate entries for R-Gee)\n                        robotis_rgee_lite_drive_simple: 'Drive R-Gee at the specified speed and direction',\n                        robotis_rgee_lite_drive_stop: 'Stop R-Gee',\n                        robotis_rgee_lite_motion: 'Make R-Gee perform the specified motion',\n                        robotis_rgee_lite_follow_line: 'Start following the line at the specified speed',\n                        robotis_rgee_lite_stop_follow_line: 'Stop following the line'\n                    },\n\n                    Blocks: {\n                        robotis_white: 'White',\n                        robotis_gray: 'Gray',\n                        robotis_darkgray: 'Darkgray',\n                        robotis_black: 'Black',\n                        robotis_purple: 'Purple',\n                        robotis_pink: 'Pink',\n                        robotis_red: 'Red',\n                        robotis_orange: 'Orange',\n                        robotis_brown: 'Brown',\n                        robotis_yellow: 'Yellow',\n                        robotis_green: 'Green',\n                        robotis_blue: 'Blue',\n                        robotis_lightblue: 'Lightblue',\n                        robotis_darkblue: 'Darkblue',\n                        robotis_brown: 'Brown',\n                        robotis_left: 'Left',\n                        robotis_center: 'Center',\n                        robotis_right: 'Right',\n                        robotis_both: 'Both',\n\n                        robotis_rgee: 'R-GEE',\n                        robotis_rla: 'KODALA',\n                        robotis_kkokdu: 'TIG',\n                        \n                        robotis_korean1: 'Hello!',\n                        robotis_korean2: 'Great to see you.',\n                        robotis_korean3: 'Okay ~',\n                        robotis_korean4: 'No!',\n                        robotis_korean5: \"I don't know.\",\n                        robotis_korean6: 'I like it.',\n                        robotis_korean7: \"I don't like it.\",\n                        robotis_korean8: 'What is your name? ',\n                        robotis_korean9: 'How can I help you? ',\n                        robotis_korean10: 'Great job! ',\n                        robotis_korean11: \"It's alright.\",\n                        robotis_korean12: \"Let's do it again! \",\n                        robotis_korean13: 'Thank you! ',\n                        robotis_korean14: 'Can you say that one more time?',\n                        robotis_korean15: 'Awesome!',\n                        robotis_korean16: \"I'm excited! \",\n                        robotis_korean17: \"I'm having a great time! \",\n                        robotis_korean18: \"I'm sorry.\",\n                        robotis_korean19: \"I'm angry! \",\n                        robotis_korean20: \"I'm embarassed.\",\n                        robotis_korean21: \"I'm scared.\",\n                        robotis_korean22: \"I'm upset.\",\n                        robotis_korean23: 'I love you.',\n                        robotis_korean24: 'Very pretty! ',\n                        robotis_korean25: 'Interesting.',\n                        robotis_korean26: \"I'm nervous.\",\n                        robotis_korean27: \"Let's move forward! \",\n                        robotis_korean28: \"Let's move backward! \",\n                        robotis_korean29: \"Let's stand up! \",\n                        robotis_korean30: 'Did you fall down? ',\n                        robotis_korean31: 'Oh Yeah~',\n                        robotis_korean32: 'Sweet! ',\n                        robotis_korean33: 'Oh no',\n                        robotis_korean34: 'My My ',\n                        robotis_korean35: 'Whoo hoo! ',\n                        robotis_korean36: 'Ha Ha Ha',\n                        robotis_korean37: 'Ho Ho Ho ',\n                        robotis_korean38: \"I'm sleepy.\",\n                        robotis_korean39: 'Sing me a bedtime song! ',\n                        robotis_korean40: 'Hello!',\n                        robotis_korean41: \"I'm hungry.\",\n                        robotis_korean42: \"I'm craving an acorn! \",\n                        robotis_korean43: 'I want to take a bath! ',\n                        robotis_korean44: 'Time for a bath! ',\n                        robotis_korean45: \"I'm bored. \",\n                        robotis_korean46: 'Do you want a snack? ',\n                        robotis_korean47: \"I'm sick.\",\n                        robotis_korean48: 'Do you have any medicine? ',\n                        robotis_korean49: 'Where do we have to go? ',\n                        robotis_korean50: \"We're here! \",\n                        robotis_korean51: \"Let's go to the left side! \",\n                        robotis_korean52: \"Let's go to the right side! \",\n                        robotis_korean53: 'Oh my, you scared me! ',\n                        robotis_korean54: 'Found you! ',\n                        robotis_korean55: \"There's nothing here. \",\n                        robotis_korean56: 'Did you call me?',\n                        robotis_korean57: 'Please let me down. ',\n                        robotis_korean58: 'Oops! ',\n                        robotis_korean59: 'Hmmph! ',\n                        robotis_korean60: 'Eek! ',\n                        robotis_dog: 'Dog',\n                        robotis_frog: 'Frog',\n                        robotis_cat: 'Cat',\n                        robotis_chicken: 'Rooster',\n                        robotis_tiger: 'Tiger',\n                        robotis_mouse: 'Mouse',\n                        robotis_whistle: 'Whistle',\n                        robotis_ambul: 'Ambulance',\n                        robotis_Horn: 'CarHorn',\n                        robotis_siren: 'Siren',\n                        robotis_gun: 'Gunshot',\n                        robotis_clap: 'Clap',\n                        robotis_melody1: 'Melody1',\n                        robotis_melody2: 'Melody2',\n                        robotis_melody3: 'Melody3',\n                        robotis_melody4: 'Melody4',\n                        robotis_forward: 'Forward',\n                        robotis_backward: 'Backward',\n                        robotis_acceleration: 'acceleration',\n                        robotis_gyro: 'gyro',\n                        robotis_run: 'Run',\n                        robotis_cancel: 'Cancel',\n                        robotis_push: 'Pressed',\n                        robotis_notPush: 'Unpressed',\n                        robotis_play: 'Play',\n                        robotis_rest: 'Rest',\n                        robotis_face01: 'Haha',\n                        robotis_face02: 'Smile',\n                        robotis_face03: 'Laugh',\n                        robotis_face04: 'Yum Yum',\n                        robotis_face05: 'Scared',\n                        robotis_face06: 'Uncomfortable',\n                        robotis_face07: 'Confused',\n                        robotis_face08: 'Dazed',\n                        robotis_face09: 'Yell',\n                        robotis_face10: 'Angry',\n                        robotis_face11: 'Sniff (Left)',\n                        robotis_face12: 'Sniff (Right)',\n                        robotis_face13: 'Sniff (Down)',\n                        robotis_face14: 'Whew',\n                        robotis_face15: 'Faint',\n                        robotis_face16: 'Dizzy',\n                        robotis_face17: 'Yawn',\n                        robotis_face18: 'Sleepy',\n                        robotis_face19: 'Sleep',\n                        robotis_face20: 'Sad',\n                        robotis_face21: 'Cry',\n                        robotis_face22: 'Bath',\n                        robotis_face23: 'Heart-Eyes',\n                                \n                        robotis_car_anim01: \"Default\",\n                        robotis_car_anim02: \"Touched\",\n                        robotis_car_anim03: \"Smile\",\n                        robotis_car_anim04: \"Laugh\",\n                        robotis_car_anim05: \"Joy\",\n                        robotis_car_anim06: \"Happiness\",\n                        robotis_car_anim07: \"Confidence\",\n                        robotis_car_anim08: \"Anger\",\n                        robotis_car_anim09: \"Depressed\",\n                        robotis_car_anim10: \"Sadness\",\n                        robotis_car_anim11: \"Pain\",\n                        robotis_car_anim12: \"Fainting\",\n                        robotis_car_anim13: \"Fear\",\n                        robotis_car_anim14: \"Yawn\",\n                        robotis_car_anim15: \"Sleepy\",\n                        robotis_car_anim16: \"Looking Right\",\n                        robotis_car_anim17: \"Looking Left\",\n                        robotis_car_anim18: \"Looking Forward\",\n                        robotis_car_anim19: \"Surprised\",\n\n        \n                        robotis_flashing1: \"Flashing1\",\n                        robotis_flashing2: \"Flashing2\",\n                        robotis_flashing3: \"Flashing3\",\n                        robotis_flashing4: \"Flashing4\",\n                        robotis_flashing5: \"Flashing5\",\n                        robotis_flashing6: \"Flashing6\",\n                        robotis_flashing7: \"Flashing7\",\n                        robotis_flashing8: \"Flashing8\",\n                        robotis_flashing9: \"Flashing9\",\n\n\n\n                        robotis_moveF: 'Forward',\n                        robotis_moveB: 'Backward',\n                        robotis_moveL: 'LeftTurn',\n                        robotis_moveR: 'RightTurn',\n                        robotis_moveU: 'U-turn',\n                        robotis_moveL_in_place: 'Turn left in place',\n                        robotis_moveR_in_place: 'Trun right in place',\n                        robotis_moveU_in_place: 'U-turn in place',\n                        robotis_moveRG1: 'Stand',\n                        robotis_moveRG2: 'Sit',\n                        robotis_moveRG3: 'Struggle',\n                        robotis_moveRG4: 'RaiseFeet',\n                        robotis_fast: 'Fast',\n                        robotis_normal: 'Normal',\n                        robotis_slow: 'Slow',\n                        robotis_stop: 'Stop',\n                        robotis_roll: 'Left-right rotate angle (roll)',\n                        robotis_pitch: 'Forward-backward rotate angle (pitch)',\n                        robotis_stMotion1: 'Standard',\n                        robotis_stMotion2: 'Forward',\n                        robotis_stMotion3: 'TurnRight',\n                        robotis_stMotion4: 'TurnLeft',\n                        robotis_stMotion5: 'Backward',\n                        robotis_stMotion6: 'ToRight',\n                        robotis_stMotion7: 'ToLeft',\n                        robotis_stMotion8: 'TurnAroundRight',\n                        robotis_stMotion9: 'TurnAroundLeft',\n                        robotis_spMotion1: 'RightHandUp',\n                        robotis_spMotion2: 'RightHandDown',\n                        robotis_spMotion3: 'LeftHandUp',\n                        robotis_spMotion4: 'LeftHandDown',\n                        robotis_spMotion5: 'BothHandsUp',\n                        robotis_spMotion6: 'BothHandsDown',\n                        robotis_spMotion7: 'FallBackward',\n                        robotis_spMotion8: 'FallForward',\n                        robotis_spMotion9: 'StandForward',\n                        robotis_spMotion10: 'StandBackward',\n                        robotis_spMotion11: 'Defence',\n                        robotis_spMotion12: 'Offense1',\n                        robotis_spMotion13: 'Offense2',\n                        robotis_spMotion14: 'Offense3',\n                        robotis_spMotion15: 'Offense4',\n                        robotis_screen1: 'Sissor',\n                        robotis_screen2: 'Rock',\n                        robotis_screen3: 'Paper',\n                        robotis_screen_text_font_small: \"Small font\",\n                        robotis_screen_text_font_big: \"Big font\",\n                    },\n                },\n            };\n        }\n        getBlocks() {\n            return {\n                robotis_rgee_lite_cm_ir_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '360'],\n                                ['2', '362'],\n                                ['3', '364'],\n                                ['4', '366'],\n                                ['5', '368'],\n                                ['6', '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_cm_ir_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        const scope = script.executor.scope;\n\n                        const data_default_address = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisRgeeLite.dataBuffer[data_default_address];\n                        if (result == undefined) {\n                            result = rb100_last_valid_value[data_default_address];\n                        } else {\n                            rb100_last_valid_value[data_default_address] = result;\n                        }\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return Math.round(result % 65536);\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.ir_value(%1)'],\n                    },\n                },\n                robotis_rgee_lite_cm_ir_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '360'],\n                                ['2', '362'],\n                                ['3', '364'],\n                                ['4', '366'],\n                                ['5', '368'],\n                                ['6', '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['>', '0'],\n                                ['<', '1'],\n                                ['=', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 200],\n                        type: 'robotis_rgee_lite_cm_ir_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                        COMPARE_OP: 1,\n                        COMPARE_VAL: 2,\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = script.getNumberValue('COMPARE_VAL');\n                        let compareOP = script.getNumberValue('COMPARE_OP');\n\n                        let result = Entry.RobotisRgeeLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        result = Math.round(result % 65536);\n\n                        switch (compareOP) {\n                            case 0:\n                                return result > compareValue;\n                            case 1:\n                                return result < compareValue;\n                            default:\n                                return false;\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.ir_compare(%1)'],\n                    },\n                },\n                robotis_rgee_lite_detectFrontObj: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n\n                        ],\n                        type: 'robotis_rgee_lite_detectFrontObj',\n                    },\n                    paramsKeyMap: {\n\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let ir_1 = 0;\n                        let ir_2 = 0;\n\n                        \n                            \n                        ir_1 = Entry.RobotisRgeeLite.dataBuffer[360];\n                        ir_2 = Entry.RobotisRgeeLite.dataBuffer[362];\n                        if (ir_1 == undefined) {\n                            ir_1 = 0;\n                        }\n                        if (ir_2 == undefined) {\n                            ir_2 = 0;\n                        }\n                        return ir_1 > 100 || ir_2 > 100;\n                            \n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.detectFrontObj()'],\n                    },\n                },\n                robotis_rgee_lite_cm_btn_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_run, '45'],\n                                [Lang.Blocks.robotis_cancel, '42'],\n                            ],\n                            value: '45',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_push, '1'],\n                                [Lang.Blocks.robotis_notPush, '0'],\n        \n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_cm_btn_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = 1;\n\n                        let result = Entry.RobotisRgeeLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.btn_value(%1)'],\n                    },\n                },\n                robotis_rgee_lite_cm_joystick_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_center, '0'],\n                                ['←', '1'],\n                                ['→', '2'],\n                                ['↑', '3'],\n                                ['↓', '4'],\n                                ['↖', '5'],\n                                ['↗', '6'],\n                                ['↙', '7'],\n                                ['↘', '8'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_cm_joystick_value',\n                    },\n                    paramsKeyMap: {\n                        COMPARE_VAL: 0,\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 50;\n                        let compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                        let result = Entry.RobotisRgeeLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.joystick_value()'],\n                    },\n                },\n                robotis_rgee_lite_mic: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_mic',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    async func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 119;\n\n                        let result = Entry.RobotisRgeeLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.mic()'],\n                    },\n                },\n                robotis_rgee_lite_detectSound_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_right, '255'],\n                                [Lang.Blocks.robotis_center, '0'],\n                                [Lang.Blocks.robotis_left, '1'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_detectSound_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 5031;\n                        let compareValue = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisRgeeLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.detectSound_compare(%1)'],\n                    },\n                },\n                robotis_rgee_lite_imu: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['x', '78'], //72\n                                ['y', '80'], //74\n                                ['z', '82'], //76\n                            ],\n                            value: '78',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_acceleration, '0'], //72\n                                [Lang.Blocks.robotis_gyro, '6'], //74\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rgee_lite_imu',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                        MODE: 1,\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address =\n                            script.getField('AXIS', script) - script.getField('MODE', script);\n\n                        let result = Entry.RobotisRgeeLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.imu()'],\n                    },\n                },\n                robotis_rgee_lite_roll_pitch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_roll, '70'], //72\n                                [Lang.Blocks.robotis_pitch, '88'], //74\n                            ],\n                            value: '70',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_roll_pitch',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    class: 'robotis_rgee_lite_value',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('AXIS');\n\n                        let result = Entry.RobotisRgeeLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.roll_pitch(%1)'],\n                    },\n                },\n\n                \n                robotis_rgee_lite_buzzer_index: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.General.note_c + '', '1'],\n                                [Lang.General.note_c + '#', '2'],\n                                [Lang.General.note_d + '', '3'],\n                                [Lang.General.note_d + '#', '4'],\n                                [Lang.General.note_e + '', '5'],\n                                [Lang.General.note_f + '', '6'],\n                                [Lang.General.note_f + '#', '7'],\n                                [Lang.General.note_g + '', '8'],\n                                [Lang.General.note_g + '#', '9'],\n                                [Lang.General.note_a + '', '10'],\n                                [Lang.General.note_a + '#', '11'],\n                                [Lang.General.note_b + '', '12'],\n                            ],\n                            value: '11',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_play, '1'],\n                                [Lang.Blocks.robotis_rest, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 1, null, null],\n                        type: 'robotis_rgee_lite_buzzer_index',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_INDEX: 0,\n                        CM_BUZZER_OCTAV: 1,\n                        CM_BUZZER_DELAY: 2,\n                        CM_BUZZER_PLAY: 3\n                    },\n                    class: 'robotis_rgee_lite_sound',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                        let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                        let cmBuzzerTime = script.getNumberValue('CM_BUZZER_DELAY', script);\n                        let cmBuzzerPlay = script.getNumberValue('CM_BUZZER_PLAY', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 0;\n                        let data_value = 0;\n                        let interval = 0;\n                        let data_buf = [];\n\n                        cmBuzzerTime = Math.round(cmBuzzerTime * 1000);\n\n                        data_address = 740;\n                        // data_value_1 = cmBuzzerTime * 10;\n                        // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n\n                        if (cmBuzzerTime < 0) {\n                            cmBuzzerTime = 0;\n                        }\n                        if (cmBuzzerTime > 50000) {\n                            cmBuzzerTime = 50000;\n                        }\n\n                        data_buf.push(cmBuzzerTime % 256);\n                        data_buf.push(Math.floor(cmBuzzerTime / 256));\n\n                        data_value = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n                        data_buf.push(Math.floor(data_value));\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [[data_instruction, data_address, 3, data_buf]];\n\n                        if(cmBuzzerPlay == '2') {\n                            data_sendqueue = [];\n                        }\n                        \n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.buzzer_index(%1, %2, %3)'],\n                    },\n                },\n\n\n                robotis_rgee_lite_rgee_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_face01, '2817'],\n                                [Lang.Blocks.robotis_face02, '2818'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face03, '2819'],\n                                [Lang.Blocks.robotis_face04, '2820'],\n                                [Lang.Blocks.robotis_face05, '2821'],\n        \n                                [Lang.Blocks.robotis_face06, '2822'],\n                                [Lang.Blocks.robotis_face07, '2823'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face08, '2824'],\n                                [Lang.Blocks.robotis_face09, '2825'],\n                                [Lang.Blocks.robotis_face10, '2826'],\n        \n                                [Lang.Blocks.robotis_face11, '2827'],\n                                [Lang.Blocks.robotis_face12, '2828'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face13, '2829'],\n                                \n                                [Lang.Blocks.robotis_face14, '2830'],\n                                [Lang.Blocks.robotis_face15, '2831'],\n                                [Lang.Blocks.robotis_face16, '2832'],\n                                [Lang.Blocks.robotis_face17, '2833'],\n                                [Lang.Blocks.robotis_face18, '2834'],\n        \n                                [Lang.Blocks.robotis_face19, '2835'],\n                                [Lang.Blocks.robotis_face20, '2836'],\n                                [Lang.Blocks.robotis_face21, '2837'],\n                                [Lang.Blocks.robotis_face22, '2838'],\n                                [Lang.Blocks.robotis_face23, '2839'],\n                            ],\n                            value: '2817',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rgee_lite_rgee_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['RgeeLite.rgee_screen(%1)'] },\n                },\n\n                robotis_rgee_lite_rgee_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_face01, '30748'],\n                                [Lang.Blocks.robotis_face02, '30749'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face03, '30750'],\n                                [Lang.Blocks.robotis_face04, '30756'],\n                                [Lang.Blocks.robotis_face05, '30754'],\n        \n                                [Lang.Blocks.robotis_face06, '30741'],\n                                [Lang.Blocks.robotis_face07, '30747'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face08, '30738'],\n                                [Lang.Blocks.robotis_face09, '30740'],\n                                [Lang.Blocks.robotis_face10, '30739'],\n        \n                                [Lang.Blocks.robotis_face11, '30733'],\n                                [Lang.Blocks.robotis_face12, '30734'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face13, '30732'],\n                                \n                                [Lang.Blocks.robotis_face14, '30757'],\n                                [Lang.Blocks.robotis_face15, '30736'],\n                                [Lang.Blocks.robotis_face16, '30731'],\n                                [Lang.Blocks.robotis_face17, '30742'],\n                                [Lang.Blocks.robotis_face18, '30743'],\n        \n                                [Lang.Blocks.robotis_face19, '30744'],\n                                [Lang.Blocks.robotis_face20, '30751'],\n                                [Lang.Blocks.robotis_face21, '30752'],\n                                [Lang.Blocks.robotis_face22, '30755'],\n                                [Lang.Blocks.robotis_face23, '30758'],\n                            ],\n                            value: '30748',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rgee_lite_rgee_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['RgeeLite.rgee_animation_screen(%1)'] },\n                },\n\n\n\n\n                robotis_rgee_lite_icon: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_screen1, '11545'],\n                                        [Lang.Blocks.robotis_screen2, '11546'],\n                                [Lang.Blocks.robotis_screen3, '11547'],\n                                ['0', '11283'],\n                                ['1', '11284'],\n                                ['2', '11285'],\n                                ['3', '11286'],\n                                ['4', '11287'],\n                                ['5', '11288'],\n                                ['6', '11289'],\n                                ['7', '11290'],\n                                ['8', '11291'],\n                                ['9', '11292'],\n                                ['10', '11293'],\n                            ],\n                            value: '11545',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_rgee_lite_icon',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.icon_screen(%1,%2,%3,%4)'],\n                    },\n                },\n\n\n                robotis_rgee_lite_LCDBright: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [10],\n                        type: 'robotis_rgee_lite_LCDBright',\n                    },\n                    paramsKeyMap: {\n                        BRIGHT: 0,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let bright = script.getNumberValue('BRIGHT', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 180;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        bright = Math.min(Math.max(bright, 0), 100);\n\n                        data_value = bright;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.LCDBright(%1)'],\n                    },\n                },\n                robotis_rgee_lite_LCDColor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '224',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_LCDColor',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let color = script.getNumberValue('COLOR', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = color;\n                        bg_color = color;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.LCDColor(%1)'],\n                    },\n                },\n\n                robotis_rgee_lite_led_brightness: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '2'],\n                                [Lang.Blocks.robotis_both, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null, \n                            {\n                                type: 'number',\n                                params: [100]\n                            }\n                        ],\n                        type: 'robotis_rgee_lite_led_brightness',\n                    },\n                    paramsKeyMap: {\n                        RB_LED: 0,\n                        BRIGHT: 1,\n                    },\n                    class: 'robotis_rgee_lite_led',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmLed = script.getNumberValue('RB_LED', script);\n                        let bright = script.getNumberValue('BRIGHT', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 0;\n                        let data_length = 1;\n                        let data_value = 0;\n                        \n                        if(bright < 0){ \n                            bright = 0;\n                        } else if(bright > 100) {\n                            bright = 100\n                        }\n                        data_value = 100+bright;\n\n                        if (cmLed == 1) {\n                            data_address = 40;\n                            data_length = 1;\n                        } else if (cmLed == 2) {\n                            data_address = 41;\n                            data_length = 1;\n                        } else if (cmLed == 3) {\n                            data_address = 40;\n                            data_length = 2;\n                            data_value = data_value * 257\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['RgeeLite.led_brightness(%1, %2)'] },\n                },\n                robotis_rgee_lite_led_pattern: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_flashing1, '11'],\n                                [Lang.Blocks.robotis_flashing2, '12'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing3, '13'],\n        \n                                [Lang.Blocks.robotis_flashing4, '21'],\n                                [Lang.Blocks.robotis_flashing5, '22'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing6, '23'],\n        \n                                [Lang.Blocks.robotis_flashing7, '31'],\n                                [Lang.Blocks.robotis_flashing8, '32'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing9, '33'],\n        \n                            ],\n                            value: '11',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_common_on, '1'],\n                                [Lang.Blocks.robotis_common_off, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'robotis_rgee_lite_led_pattern',\n                    },\n                    paramsKeyMap: {\n                        RB_LED: 0,\n                        VALUE: 1,\n                    },\n                    class: 'robotis_rgee_lite_led',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmLed = script.getNumberValue('RB_LED', script);\n                        let value = script.getNumberValue('VALUE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 40;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = value * cmLed;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['RgeeLite.led_pattern(%1, %2)'] },\n                },\n\n                \n\n                robotis_rgee_lite_Hello: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_korean1, '0'],\n                                [Lang.Blocks.robotis_korean2, '1'],\n                                [Lang.Blocks.robotis_korean3, '2'],\n                                [Lang.Blocks.robotis_korean4, '3'],\n                                [Lang.Blocks.robotis_korean5, '4'],\n                                [Lang.Blocks.robotis_korean6, '5'],\n                                [Lang.Blocks.robotis_korean7, '6'],\n                                [Lang.Blocks.robotis_korean8, '7'],\n                                [Lang.Blocks.robotis_korean9, '8'],\n                                [Lang.Blocks.robotis_korean10, '9'],\n                                [Lang.Blocks.robotis_korean11, '10'],\n                                [Lang.Blocks.robotis_korean12, '11'],\n                                [Lang.Blocks.robotis_korean13, '12'],\n                                [Lang.Blocks.robotis_korean14, '13'],\n                                [Lang.Blocks.robotis_korean15, '14'],\n                                [Lang.Blocks.robotis_korean16, '15'],\n                                [Lang.Blocks.robotis_korean17, '16'],\n                                [Lang.Blocks.robotis_korean18, '17'],\n                                [Lang.Blocks.robotis_korean19, '18'],\n                                [Lang.Blocks.robotis_korean20, '19'],\n                                [Lang.Blocks.robotis_korean21, '20'],\n                                [Lang.Blocks.robotis_korean22, '21'],\n                                [Lang.Blocks.robotis_korean23, '22'],\n                                [Lang.Blocks.robotis_korean24, '23'],\n                                [Lang.Blocks.robotis_korean25, '24'],\n                                [Lang.Blocks.robotis_korean26, '25'],\n                                [Lang.Blocks.robotis_korean27, '26'],\n                                [Lang.Blocks.robotis_korean28, '27'],\n                                [Lang.Blocks.robotis_korean29, '28'],\n                                [Lang.Blocks.robotis_korean30, '29'],\n                                [Lang.Blocks.robotis_korean31, '30'],\n                                [Lang.Blocks.robotis_korean32, '31'],\n                                [Lang.Blocks.robotis_korean33, '32'],\n                                [Lang.Blocks.robotis_korean34, '33'],\n                                [Lang.Blocks.robotis_korean35, '34'],\n                                [Lang.Blocks.robotis_korean36, '35'],\n                                [Lang.Blocks.robotis_korean37, '36'],\n                                [Lang.Blocks.robotis_korean38, '37'],\n                                [Lang.Blocks.robotis_korean39, '38'],\n                                [Lang.Blocks.robotis_korean40, '39'],\n                                [Lang.Blocks.robotis_korean41, '40'],\n                                [Lang.Blocks.robotis_korean42, '41'],\n                                [Lang.Blocks.robotis_korean43, '42'],\n                                [Lang.Blocks.robotis_korean44, '43'],\n                                [Lang.Blocks.robotis_korean45, '44'],\n                                [Lang.Blocks.robotis_korean46, '45'],\n                                [Lang.Blocks.robotis_korean47, '46'],\n                                [Lang.Blocks.robotis_korean48, '47'],\n                                [Lang.Blocks.robotis_korean49, '48'],\n                                [Lang.Blocks.robotis_korean50, '49'],\n                                [Lang.Blocks.robotis_korean51, '50'],\n                                [Lang.Blocks.robotis_korean52, '51'],\n                                [Lang.Blocks.robotis_korean53, '52'],\n                                [Lang.Blocks.robotis_korean54, '53'],\n                                [Lang.Blocks.robotis_korean55, '54'],\n                                [Lang.Blocks.robotis_korean56, '55'],\n                                [Lang.Blocks.robotis_korean57, '56'],\n                                [Lang.Blocks.robotis_korean58, '57'],\n                                [Lang.Blocks.robotis_korean59, '58'],\n                                [Lang.Blocks.robotis_korean60, '59'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_Hello',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_rgee_lite_sound',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = 25601 + Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n\n                        if (cmHello == '38' || cmHello == '55') {\n                            extraTime = 2000;\n                        }\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            2000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.speak(%1)'],\n                    },\n                },\n                robotis_rgee_lite_effectSound: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dog, '0'],\n                                [Lang.Blocks.robotis_frog, '1'],\n                                [Lang.Blocks.robotis_cat, '2'],\n                                [Lang.Blocks.robotis_chicken, '7'],\n                                [Lang.Blocks.robotis_tiger, '19'],\n                                [Lang.Blocks.robotis_mouse, '17'],\n\n                                [Lang.Blocks.robotis_ambul, '773'],\n                                [Lang.Blocks.robotis_Horn, '781'],\n                                [Lang.Blocks.robotis_siren, '774'],\n                                [Lang.Blocks.robotis_whistle, '274'],\n                                [Lang.Blocks.robotis_gun, '775'],\n                                [Lang.Blocks.robotis_clap, '260'],\n\n                                [Lang.Blocks.robotis_melody1, '786'],\n                                [Lang.Blocks.robotis_melody2, '787'],\n                                [Lang.Blocks.robotis_melody3, '788'],\n                                [Lang.Blocks.robotis_melody4, '789'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_effectSound',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_rgee_lite_sound',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n                        if (\n                            cmHello == '272' ||\n                            cmHello == '786' ||\n                            cmHello == '787' ||\n                            cmHello == '788' ||\n                            cmHello == '789'\n                        ) {\n                            //오리\n                            extraTime = 0;\n                            if (cmHello == '788' || cmHello == '789') {\n                                extraTime += 500;\n                            }\n                        }\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            3000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.effect_sound(%1)'],\n                    },\n                },\n                robotis_rgee_lite_record: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_record',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_rgee_lite_sound',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 115;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.record(%1)'],\n                    },\n                },\n                robotis_rgee_lite_playRecord: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_playRecord',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_rgee_lite_sound',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 116;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.playRecord(%1)'],\n                    },\n                },\n\n\n\n                \n                robotis_rgee_lite_rla_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '3329'],\n                                [Lang.Blocks.robotis_car_anim02, '3330'],\n                                [Lang.Blocks.robotis_car_anim03, '3331'],\n                                [Lang.Blocks.robotis_car_anim04, '3332'],\n                                [Lang.Blocks.robotis_car_anim05, '3333'],\n        \n                                [Lang.Blocks.robotis_car_anim06, '3334'],\n                                [Lang.Blocks.robotis_car_anim07, '3335'], \n                                [Lang.Blocks.robotis_car_anim08, '3336'],\n                                [Lang.Blocks.robotis_car_anim09, '3337'],\n                                [Lang.Blocks.robotis_car_anim10, '3338'],\n        \n                                [Lang.Blocks.robotis_car_anim11, '3339'],\n                                [Lang.Blocks.robotis_car_anim12, '3340'], \n                                [Lang.Blocks.robotis_car_anim13, '3341'],\n                                [Lang.Blocks.robotis_car_anim14, '3342'],\n                                [Lang.Blocks.robotis_car_anim15, '3343'],\n        \n                                [Lang.Blocks.robotis_car_anim16, '3344'],\n                                [Lang.Blocks.robotis_car_anim17, '3345'], \n                                [Lang.Blocks.robotis_car_anim18, '3346'],\n                                [Lang.Blocks.robotis_car_anim19, '3347'],\n                            ],\n                            value: '3329',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rgee_lite_rla_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['RgeeLite.rla_screen(%1)'] },\n                },\n\n                robotis_rgee_lite_rla_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '30978'],\n                                [Lang.Blocks.robotis_car_anim02, '30981'],\n                                [Lang.Blocks.robotis_car_anim03, '30982'],\n                                [Lang.Blocks.robotis_car_anim04, '30983'],\n                                [Lang.Blocks.robotis_car_anim05, '30984'],\n        \n                                [Lang.Blocks.robotis_car_anim06, '30985'],\n                                [Lang.Blocks.robotis_car_anim07, '30986'], \n                                [Lang.Blocks.robotis_car_anim08, '30987'],\n                                [Lang.Blocks.robotis_car_anim09, '30988'],\n                                [Lang.Blocks.robotis_car_anim10, '30989'],\n        \n                                [Lang.Blocks.robotis_car_anim11, '30990'],\n                                [Lang.Blocks.robotis_car_anim12, '30991'], \n                                [Lang.Blocks.robotis_car_anim13, '30992'],\n                                [Lang.Blocks.robotis_car_anim14, '30993'],\n                                [Lang.Blocks.robotis_car_anim15, '30994'],\n        \n                                [Lang.Blocks.robotis_car_anim16, '30995'],\n                                [Lang.Blocks.robotis_car_anim17, '30996'], \n                                [Lang.Blocks.robotis_car_anim18, '30997'],\n                                [Lang.Blocks.robotis_car_anim19, '30998'],\n                            ],\n                            value: '30978',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rgee_lite_rla_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['RgeeLite.rla_animation_screen(%1)'] },\n                },\n                \n                robotis_rgee_lite_kkokdu_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '3585'],\n                                [Lang.Blocks.robotis_car_anim02, '3586'],\n                                [Lang.Blocks.robotis_car_anim03, '3587'],\n                                [Lang.Blocks.robotis_car_anim04, '3588'],\n                                [Lang.Blocks.robotis_car_anim05, '3589'],\n        \n                                [Lang.Blocks.robotis_car_anim06, '3590'],\n                                [Lang.Blocks.robotis_car_anim07, '3591'], \n                                [Lang.Blocks.robotis_car_anim08, '3592'],\n                                [Lang.Blocks.robotis_car_anim09, '3593'],\n                                [Lang.Blocks.robotis_car_anim10, '3594'],\n        \n                                [Lang.Blocks.robotis_car_anim11, '3595'],\n                                [Lang.Blocks.robotis_car_anim12, '3596'], \n                                [Lang.Blocks.robotis_car_anim13, '3597'],\n                                [Lang.Blocks.robotis_car_anim14, '3598'],\n                                [Lang.Blocks.robotis_car_anim15, '3599'],\n        \n                                [Lang.Blocks.robotis_car_anim16, '3600'],\n                                [Lang.Blocks.robotis_car_anim17, '3601'], \n                                [Lang.Blocks.robotis_car_anim18, '3602'],\n                                [Lang.Blocks.robotis_car_anim19, '3603'],\n                            ],\n                            value: '3585',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rgee_lite_kkokdu_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['RgeeLite.kkokdu_screen(%1)'] },\n                },\n\n                robotis_rgee_lite_kkokdu_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '31234'],\n                                [Lang.Blocks.robotis_car_anim02, '31237'],\n                                [Lang.Blocks.robotis_car_anim03, '31238'],\n                                [Lang.Blocks.robotis_car_anim04, '31239'],\n                                [Lang.Blocks.robotis_car_anim05, '31240'],\n        \n                                [Lang.Blocks.robotis_car_anim06, '31241'],\n                                [Lang.Blocks.robotis_car_anim07, '31242'], \n                                [Lang.Blocks.robotis_car_anim08, '31243'],\n                                [Lang.Blocks.robotis_car_anim09, '31244'],\n                                [Lang.Blocks.robotis_car_anim10, '31245'],\n        \n                                [Lang.Blocks.robotis_car_anim11, '31246'],\n                                [Lang.Blocks.robotis_car_anim12, '31247'], \n                                [Lang.Blocks.robotis_car_anim13, '31248'],\n                                [Lang.Blocks.robotis_car_anim14, '31249'],\n                                [Lang.Blocks.robotis_car_anim15, '31250'],\n        \n                                [Lang.Blocks.robotis_car_anim16, '31251'],\n                                [Lang.Blocks.robotis_car_anim17, '31252'], \n                                [Lang.Blocks.robotis_car_anim18, '31253'],\n                                [Lang.Blocks.robotis_car_anim19, '31254'],\n                            ],\n                            value: '31234',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rgee_lite_kkokdu_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['RgeeLite.kkokdu_animation_screen(%1)'] },\n                },\n                robotis_rgee_lite_text_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_screen_text_font_small, '0'],\n                                [Lang.Blocks.robotis_screen_text_font_big, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            ' ',\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'robotis_rgee_lite_text_screen',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        X: 1,\n                        Y: 2,\n                        FONT: 3,\n                        COLOR: 4,\n                    },\n                    class: 'robotis_rgee_lite_lcd',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let text = script.getStringValue('TEXT', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let font = script.getNumberValue('FONT', script);\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 900;\n                        let data_length = 2;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        let encoder = new TextEncoder('utf-8');\n                        let byteArray = encoder.encode(text);\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(font);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(color);\n                        data_buf.push(byteArray.length);\n                        for (i = 0; i < byteArray.length; i++) {\n                            data_buf.push(byteArray[i]);\n                        }\n\n                        data_length = 9 + byteArray.length;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.text_screen(%1,%2,%3,%4,%5)'],\n                    },\n                },\n\n\n                \n                robotis_rgee_lite_drive_simple: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '2'],\n                                [Lang.Blocks.robotis_moveL, '3'],\n                                [Lang.Blocks.robotis_moveR, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [10, null, null],\n                        type: 'robotis_rgee_lite_drive_simple',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_rgee_lite_move',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        const speed = script.getNumberValue('SPEED', script);\n                        const direction = script.getField('DIRECTION', script);\n\n                        const data_instruction = INST_WRITE;\n                        const data_address = 710;\n                        const data_length = 2;\n                        let data_value = 0;\n\n                        switch (direction) {\n                            case '1':\n                                data_value = speed * 256 + speed;\n                                break;\n                            case '2':\n                                data_value = (256 - speed) * 256 + (256 - speed);\n                                break;\n                            case '3':\n                                data_value = speed * 256 + (256 - speed);\n                                break;\n                            case '4':\n                                data_value = (256 - speed) * 256 + speed;\n                                break;\n                            default:\n                                data_value = 0;\n                                break;\n                        }\n\n                        const data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.go_simple(%1, %2)'],\n                    },\n                },\n                \n                robotis_rgee_lite_drive_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_drive_stop',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'robotis_rgee_lite_move',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        let data_sendqueue = [\n                            [data_instruction, 5200, 1, 0],\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.stop(%1, %2)'],\n                    },\n                },\n                robotis_rgee_lite_motion: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveRG1, '50007'],\n                                [Lang.Blocks.robotis_moveRG2, '50008'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_moveRG3, '50071'],\n                                [Lang.Blocks.robotis_moveRG4, '50072'],\n                            ],\n                            value: '50007',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_motion',\n                    },\n                    paramsKeyMap: {\n                        MotionNumber: 0,\n                    },\n                    class: 'robotis_rgee_lite_move',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        const data_instruction = INST_WRITE;\n                        const data_address = 66;\n                        const data_length = 2;\n                        let data_value = script.getField('MotionNumber', script);\n\n                        const data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            data_value > 50070 ? 2000 : 1000 \n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.run_motion(%1)'],\n                    },\n                },\n                robotis_rgee_lite_follow_line: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1단계', '1'],\n                                ['2단계', '2'],\n                                ['3단계', '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rgee_lite_follow_line',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                    },\n                    class: 'robotis_rgee_lite_move',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let speed_level = script.getNumberValue('SPEED', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 5200;\n                        let data_length = 1;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, speed_level],\n                        ];\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.follow_line(%1)'],\n                    },\n                },\n\n                robotis_rgee_lite_stop_follow_line: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rgee_lite_stop_follow_line',\n                    },\n                    paramsKeyMap: {\n                    },\n                    class: 'robotis_rgee_lite_move',\n                    isNotFor: ['RobotisRgeeLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        let data_sendqueue = [\n                            [data_instruction, 5200, 1, 0],\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRgeeLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RgeeLite.stop_follow_line()'],\n                    },\n                },\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////\n            };\n        }\n\n        requestLocalData() {\n            let packets = [];\n            while (this.robotisBuffer.length > 0) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n                let packet = null;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        packet = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        packet = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n\n                if (packet !== null && Array.isArray(packet)) {\n                    packets.push(...packet);\n                }\n            }\n            return packets;\n        }\n\n        handleLocalData(data) {\n            let stuffLength = 0;\n            //console.log(`length: ${data.length}`);\n            for (let i = 0; i < data.length; i++) {\n                //this.receiveBuffer.push(data[i]);\n                const dataIn = data[i];\n\n                switch (this.packetReceiveState) {\n                    case PACKET_STATE_IDLE:\n                        if (this.headerCount >= 2) {\n                            rxPacket.header[2] = dataIn;\n\n                            if (\n                                rxPacket.header[0] == 0xff &&\n                                rxPacket.header[1] == 0xff &&\n                                rxPacket.header[2] == 0xfd\n                            ) {\n                                this.headerCount = 0;\n                                this.packetReceiveState = PACKET_STATE_RESERVED;\n                            } else {\n                                rxPacket.header[0] = rxPacket.header[1];\n                                rxPacket.header[1] = rxPacket.header[2];\n                                rxPacket.header[2] = 0;\n                            }\n                        } else {\n                            rxPacket.header[this.headerCount] = dataIn;\n                            this.headerCount++;\n                        }\n                        break;\n\n                    case PACKET_STATE_RESERVED:\n                        if (dataIn == 0xfd) {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        } else {\n                            rxPacket.reserved = dataIn;\n                            this.packetReceiveState = PACKET_STATE_ID;\n                        }\n                        break;\n\n                    case PACKET_STATE_ID:\n                        rxPacket.id = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_L;\n                        break;\n\n                    case PACKET_STATE_LENGTH_L:\n                        rxPacket.packetLength = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_H;\n                        break;\n\n                    case PACKET_STATE_LENGTH_H:\n                        rxPacket.packetLength |= dataIn << 8;\n                        if (rxPacket.packetLength < 1000) {\n                            this.packetReceiveState = PACKET_STATE_DATA;\n                        } else {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        }\n                        rxPacket.index = 0;\n                        break;\n\n                    case PACKET_STATE_DATA:\n                        rxPacket.data[rxPacket.index] = dataIn;\n                        rxPacket.index++;\n\n                        if (rxPacket.index >= rxPacket.packetLength - 2) {\n                            this.packetReceiveState = PACKET_STATE_CRC_L;\n                        }\n                        break;\n\n                    case PACKET_STATE_CRC_L:\n                        rxPacket.crcReceived = dataIn;\n                        this.packetReceiveState = PACKET_STATE_CRC_H;\n                        break;\n\n                    case PACKET_STATE_CRC_H:\n                        rxPacket.crcReceived |= dataIn << 8;\n\n                        stuffLength = this.removeStuffing(rxPacket.data, rxPacket.packetLength);\n                        rxPacket.packetLength -= stuffLength;\n\n                        rxPacket.cmd = rxPacket.data[0];\n                        rxPacket.error = rxPacket.data[1];\n\n                        if (rxPacket.cmd == INST_STATUS) {\n                            //console.log(`rx length: ${rxPacket.packetLength}`);\n                            if (rxPacket.packetLength >= 147) {\n                                let tempValue = 0;\n                                for (let i = 0; i < addrMap.length; i++) {\n                                    switch (addrMap[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n\n                                const dxlPositionStartAddr =\n                                    addrMap[addrMap.length - 1][0] + addrMap[addrMap.length - 1][1];\n\n                                // DXL Position\n                                for (let i = 0; i < 20; i++) {\n                                    const currentId =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i];\n                                    const currentPos =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 1] +\n                                        (rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 2] << 8);\n                                    if (currentId != 0xff && currentPos != 0xffff) {\n                                        this.dxlPositions[currentId] = currentPos;\n                                    }\n                                }\n\n                                const lineCategoryStartAddr = dxlPositionStartAddr + 3 * 20;\n                                // line category\n                                this.dataBuffer[5201] = rxPacket.data[2 + lineCategoryStartAddr];\n\n                                const sensorStartAddr = lineCategoryStartAddr + 1;\n\n                                // 온습도+조도+동작감지센서값\n                                this.pirPir[0] = rxPacket.data[2 + sensorStartAddr];\n                                this.pirTemperature[0] = rxPacket.data[2 + sensorStartAddr + 1];\n                                this.pirHumidity[0] = rxPacket.data[2 + sensorStartAddr + 2];\n                                this.pirBrightness[0] = rxPacket.data[2 + sensorStartAddr + 3];\n\n                                // 거리+버튼+조도센서값\n                                this.distanceDistance[0] =\n                                    rxPacket.data[2 + sensorStartAddr + 4] +\n                                    (rxPacket.data[2 + sensorStartAddr + 5] << 8);\n                                this.distanceButton[0] = rxPacket.data[2 + sensorStartAddr + 6];\n                                this.distanceBrightness[0] = rxPacket.data[2 + sensorStartAddr + 7];\n\n                                for (let i = 0; i < addrMap2.length; i++) {\n                                    switch (addrMap2[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap2[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n                            }\n                        }\n\n                        this.packetReceiveState = PACKET_STATE_IDLE;\n                        break;\n\n                    default:\n                    // code block\n                }\n            }\n        }\n\n        requestInitialData() {\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 20]);\n            this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기\n            this.robotisBuffer.push([INST_WRITE, 20, 1, 0]); // bypass port를 BLE로 설정\n            this.robotisBuffer.push([INST_WRITE, 23, 1, 1]); // auto report 기능 켜기\n            this.robotisBuffer.push([INST_WRITE, 4250, 1, 1]); // ai_camera 텍스트 지우기\n            this.robotisBuffer.push([INST_WRITE, 722, 1, 0]); // dxl 토크 끄기\n            //this.robotisBuffer.push([INST_WRITE, 63, 1, 1]); // 부저음 시간 설정\n            //this.robotisBuffer.push([INST_WRITE, 60, 1, 70]); // 부저음 발생\n            this.robotisBuffer.push([INST_WRITE, 113, 2, 1040]); // \"띵\" 효과음 발생\n            /*\n            //const ping = [0xff, 0xff, 0xfd, 0x00, 0xc8, 0x03, 0x00, 0x01, 0x3b, 0xfa];\n            // run entry mode\n            const packet = [\n                0xff, 0xff, 0xfd, 0x00, 0xc8, 0x07, 0x00, 0x03, 0x15, 0x00, 0x14, 0x00, 0xc1, 0xb3,\n            ];\n            return packet;\n            */\n        }\n\n        async initialHandshake() {\n            const status = true;\n            let sendBuffer = null;\n            this.requestInitialData();\n            while (this.robotisBuffer.length) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        sendBuffer = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        sendBuffer = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n                Entry.hwLite.serial.sendAsciiAsBuffer(sendBuffer);\n                if (instruction == INST_WRITE && address == 2100 && length == 1 && value == 1) {\n                    this.robotisBuffer = [];\n                }\n            }\n            return status;\n        }\n    })();\n})();\n\nmodule.exports = Entry.RobotisRgeeLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_robotis_rla_lite.js",
    "content": "'use strict';\n\nconst INST_NONE = 0;\nconst INST_READ = 2;\nconst INST_WRITE = 3;\nconst INST_DXL_SYNCWRITE = 4;\nconst INST_DXL_REGWRITE = 5;\nconst INST_DXL_ACTION = 6;\nconst INST_BYPASS_READ = 0xa2;\nconst INST_BYPASS_WRITE = 0xa3;\n\nconst INST_STATUS = 0x55;\n\nconst PACKET_STATE_IDLE = 0;\nconst PACKET_STATE_RESERVED = 1;\nconst PACKET_STATE_ID = 2;\nconst PACKET_STATE_LENGTH_L = 3;\nconst PACKET_STATE_LENGTH_H = 4;\nconst PACKET_STATE_DATA = 5;\nconst PACKET_STATE_CRC_L = 6;\nconst PACKET_STATE_CRC_H = 7;\n\nconst DEFAULT_DELAY = 50;\n\nconst rxPacket = {\n    header: [0, 0, 0],\n    reserved: 0,\n    id: 0,\n    cmd: 0,\n    error: 0,\n    type: 0,\n    index: 0,\n    packetLength: 0,\n    paramLength: 0,\n    crc: 0,\n    crcReceived: 0,\n    checksum: 0,\n    checksumReceived: 0,\n    data: [],\n};\n\nconst addrMap = [\n    [0, 4, 302],\n    [4, 1, 42],\n    [5, 1, 44],\n    [6, 1, 45],\n    [7, 1, 47],\n    [8, 1, 50],\n    [9, 1, 51],\n    [10, 1, 52],\n    [11, 1, 68],\n    [12, 2, 70],\n    [14, 2, 72],\n    [16, 2, 74],\n    [18, 2, 76],\n    [20, 2, 78],\n    [22, 2, 80],\n    [24, 2, 82],\n    [26, 2, 84],\n    [28, 1, 86],\n    [29, 1, 87],\n    [30, 2, 88],\n    [32, 2, 90],\n    [34, 1, 112],\n    [35, 1, 118],\n    [36, 1, 119],\n    [37, 1, 122],\n    [38, 1, 123],\n    [39, 1, 124],\n    [40, 1, 125],\n    [41, 1, 160],\n    [42, 1, 220],\n    [43, 2, 360],\n    [45, 2, 362],\n    [47, 2, 364],\n    [49, 2, 366],\n    [51, 2, 368],\n    [53, 2, 370],\n    [55, 1, 372],\n    [56, 1, 373],\n    [57, 1, 374],\n    [58, 1, 375],\n    [59, 1, 376],\n    [60, 1, 377],\n    [61, 1, 378],\n    [62, 1, 379],\n    [63, 1, 380],\n    [64, 1, 381],\n    [65, 1, 382],\n    [66, 1, 383],\n    [67, 1, 500],\n    [68, 1, 501],\n    [69, 8, 502],\n    [77, 1, 700],\n    [78, 1, 810],\n    [79, 1, 2134],\n    [80, 1, 5015],\n    [81, 1, 5030],\n    [82, 1, 5031],\n    [83, 1, 5040],\n];\n\nconst addrMap2 = [\n    [153, 1, 4000],\n    [154, 2, 4003],\n    [156, 1, 4005],\n    [157, 1, 4006],\n    [158, 2, 4009],\n    [160, 2, 4011],\n    [162, 2, 4013],\n    [164, 2, 4015],\n    [166, 2, 4017],\n    [168, 2, 4019],\n    [170, 2, 4021],\n    [172, 2, 4023],\n    [174, 2, 4025],\n    [176, 2, 4027],\n    [178, 1, 4031],\n    [179, 1, 4032],\n    [180, 1, 4033],\n    [181, 2, 4036],\n    [183, 2, 4038],\n    [185, 2, 4040],\n    [187, 2, 4042],\n    [189, 2, 4044],\n    [191, 2, 4046],\n    [193, 2, 4048],\n    [195, 2, 4050],\n];\n\nconst crcTable = [\n    0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039,\n    0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,\n    0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9,\n    0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,\n    0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099,\n    0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,\n    0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea,\n    0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,\n    0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179,\n    0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,\n    0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309,\n    0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,\n    0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359,\n    0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,\n    0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9,\n    0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,\n    0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9,\n    0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,\n    0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, 0x0246, 0x024c, 0x8249,\n    0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,\n    0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219,\n    0x0208, 0x820d, 0x8207, 0x0202,\n];\n\nconst rb100_last_valid_value = [];\nlet bg_color = 0;\nlet beat_per_minute = 75;\nlet camera_id_for_use = 0;\n\n(function () {\n    Entry.RobotisRlaLite = new (class RobotisRlaLite {\n        constructor() {\n            this.id = '070901';\n            this.url = 'http://www.robotis.com';\n            this.imageName = 'robotis_rla_lite.png';\n            this.name = 'RobotisRlaLite';\n            this.blockMenuBlocks = [\n                // 값 블록\n                'robotis_rla_lite_cm_ir_value',\n                'robotis_rla_lite_cm_ir_compare',\n                'robotis_rla_lite_detectFrontObj',\n                'robotis_rla_lite_cm_btn_value',\n                'robotis_rla_lite_cm_joystick_value',\n                'robotis_rla_lite_mic',\n                'robotis_rla_lite_detectSound_compare',\n                'robotis_rla_lite_imu',\n                'robotis_rla_lite_roll_pitch',\n\n                // 음계\n                'robotis_rla_lite_buzzer_index',\n\n                // LCD 제어\n                'robotis_rla_lite_rgee_screen',\n                'robotis_rla_lite_rgee_anim_screen',\n                'robotis_rla_lite_icon',\n                'robotis_rla_lite_LCDBright',\n                'robotis_rla_lite_LCDColor',\n\n                // LED 제어\n                'robotis_rla_lite_led_brightness',\n                'robotis_rla_lite_led_pattern',\n\n\n                // 소리\n                'robotis_rla_lite_Hello',\n                'robotis_rla_lite_effectSound',\n                'robotis_rla_lite_record',\n                'robotis_rla_lite_playRecord',\n\n                // 다른 로봇 LCD 화면 제어\n                'robotis_rla_lite_rla_screen',\n                'robotis_rla_lite_rla_anim_screen',\n                'robotis_rla_lite_kkokdu_screen',\n                'robotis_rla_lite_kkokdu_anim_screen',\n                \n                // 주행 제어\n                'robotis_rla_lite_drive_simple',\n                'robotis_rla_lite_drive_stop',\n                'robotis_rla_lite_wheel_rotate',\n                'robotis_rla_lite_wheel_stop',\n                'robotis_rla_lite_go_distance',\n                'robotis_rla_lite_turn_angle',\n                'robotis_rla_lite_motion',\n\n                // 텍스트 출력\n                'robotis_rla_lite_text_screen',\n                \n                // 라인 따라가기\n                'robotis_rla_lite_follow_line',\n                'robotis_rla_lite_stop_follow_line',\n            ];\n            this.portData = {\n                baudRate: 57600,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                connectionType: 'bytestream',\n                bufferSize: 128,\n                constantServing: true,\n            };\n            this.duration = 15;\n            this.setZero();\n\n            this.timeouts = [];\n\n            this.robotisBuffer = []; // buffer to transmit to H/W\n            this.receiveBuffer = []; // buffer to receive from H/W\n            this.dataBuffer = []; // saved control table value buffer\n\n            this.packetReceiveState = 0;\n            this.headerCount = 0;\n\n            this.dxlPositions = [];\n\n            this.pirPir = [];\n            this.pirTemperature = [];\n            this.pirHumidity = [];\n            this.pirBrightness = [];\n            this.distanceDistance = [];\n            this.distanceButton = [];\n            this.distanceBrightness = [];\n        }\n\n        setZero() {\n            this.timeouts = [];\n            this.__removeAllTimeouts();\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 7]); // App Coding 모드\n            this.robotisBuffer.push([INST_WRITE, 40, 2, 0]); // LED 끄기\n            this.robotisBuffer.push([INST_WRITE, 66, 2, 0]); // 모션 종료\n            this.robotisBuffer.push([INST_WRITE, 710, 2, 0]); // 바퀴 정지\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 20]); // App Coding 모드\n            this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기\n            camera_id_for_use = 0;\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        __removeTimeout(id) {\n            clearTimeout(id);\n            const idx = this.timeouts.indexOf(id);\n            if (idx >= 0) {\n                this.timeouts.splice(idx, 1);\n            }\n        }\n\n        __removeAllTimeouts() {\n            const timeouts = this.timeouts;\n            for (const i in timeouts) {\n                clearTimeout(timeouts[i]);\n            }\n            this.timeouts = [];\n        }\n\n        getMonitorPort() {\n            return { ...this.sensory, ...this.motoring, ...this.lineTracer };\n        }\n\n        writePacket(id, address, length, value) {\n            if (length > 256) {\n                console.log(`######### invalid length: ${length}`);\n                return null;\n            }\n            console.log('######### writePacket');\n            const packet = [];\n            let i = 0;\n            packet.push(0xff);\n            packet.push(0xff);\n            packet.push(0xfd);\n            packet.push(0x00);\n            packet.push(id);\n            packet.push(length + 5);\n            packet.push(0x00);\n            packet.push(INST_WRITE);\n            packet.push(this.getLowByte(address));\n            packet.push(this.getHighByte(address));\n            switch (length) {\n                case 1:\n                    packet.push(this.getLowByte(value));\n                    break;\n                case 2:\n                    packet.push(this.getLowByte(value));\n                    packet.push(this.getHighByte(value));\n                    break;\n                case 4:\n                    packet.push(this.getLowByte(this.getLowWord(value)));\n                    packet.push(this.getHighByte(this.getLowWord(value)));\n                    packet.push(this.getLowByte(this.getHighWord(value)));\n                    packet.push(this.getHighByte(this.getHighWord(value)));\n                    break;\n                default:\n                    for (i = 0; i < length; i++) {\n                        if (typeof value[i] == 'number') {\n                            packet.push(value[i]);\n                        } else if (typeof value[i] == 'string') {\n                            packet.push(value[i].charCodeAt(0));\n                        }\n                    }\n                    break;\n            }\n            const crc = this.updateCRC(0, packet, packet.length);\n            packet.push(this.getLowByte(crc));\n            packet.push(this.getHighByte(crc));\n            return packet;\n        }\n\n        makeWord(a, b) {\n            return (a & 0xff) | ((b & 0xff) << 8);\n        }\n\n        getLowByte(a) {\n            return a & 0xff;\n        }\n\n        getHighByte(a) {\n            return (a >> 8) & 0xff;\n        }\n\n        getLowWord(a) {\n            return a & 0xffff;\n        }\n\n        getHighWord(a) {\n            return (a >> 16) & 0xffff;\n        }\n\n        updateCRC(crcAccum, dataBlkPtr, dataBlkSize) {\n            let i = 0;\n            let j = 0;\n            let crc = crcAccum;\n\n            for (j = 0; j < dataBlkSize; j++) {\n                i = ((crc >> 8) ^ dataBlkPtr[j]) & 0xff;\n                crc = (crc << 8) ^ crcTable[i];\n            }\n\n            return crc;\n        }\n\n        removeStuffing(buffer, length) {\n            let i = 0;\n            let stuffLength = 0;\n            let index = 0;\n\n            for (i = 0; i < length; i++) {\n                if (i >= 2) {\n                    if (buffer[i - 2] == 0xff && buffer[i - 1] == 0xff && buffer[i] == 0xfd) {\n                        i++;\n                        stuffLength++;\n                    }\n                }\n                buffer[index++] = buffer[i];\n            }\n\n            return stuffLength;\n        }\n\n        postCallReturn(script, data, ms) {\n            /*\n            if (data == null) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            } else if (data.length == 0) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n            */\n            if (!script.isStart) {\n                script.isStart = true;\n                script.timeFlag = 1;\n                for (let i = 0; i < data.length; i++) {\n                    this.robotisBuffer.push(data[i]);\n                }\n                //delay ms\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, ms);\n                return script;\n            } else if (script.timeFlag) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.timeFlag;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // 값 블록\n                        robotis_rla_lite_cm_ir_value: '%1 번 IR 센서 값',\n                        robotis_rla_lite_cm_ir_compare: '%1 번 IR 센서 값이 %2  %3이면',\n                        robotis_rla_lite_detectFrontObj: '앞에 물체가 있으면',\n                        robotis_rla_lite_cm_btn_value: '%1 버튼이 %2 이면',\n                        robotis_rla_lite_cm_joystick_value:\n                            '조이스틱 위치가 %1 이면',\n                        robotis_rla_lite_mic: '마이크 음량(dB)',\n                        robotis_rla_lite_detectSound_compare: '소리가 %1에서 나면',\n                        robotis_rla_lite_imu: '%1축의 %2 값',\n                        robotis_rla_lite_roll_pitch: '제어기 각도 %1 값',\n\n                        // 음계\n                        robotis_rla_lite_buzzer_index: '제어기 음계값 %1 을(를) %2 옥타브로 %3 초 동안 %4 %5',\n\n                        // LCD 제어\n                        robotis_rla_lite_rla_screen: '제어기 화면 배경을 알라 %1 (으)로 선택 %2',\n                        robotis_rla_lite_rla_anim_screen:\n                            '제어기 화면 애니메이션을 알라 %1 (으)로 선택 %2',\n                        robotis_rla_lite_icon: \n                            \"제어기 화면에 %1 출력하기 %5\",\n                        robotis_rla_lite_LCDBright: '제어기 화면 밝기를 %1 (으)로 정하기 %2',\n                        robotis_rla_lite_LCDColor: '제어기 화면 색상을 %1 (으)로 정하기 %2',\n\n                        // LED 제어\n                        robotis_rla_lite_led_brightness: '제어기 %1 LED 밝기를 %2(으)로 정하기 %3',\n                        robotis_rla_lite_led_pattern: '제어기 %1 LED %2 %3',\n                        \n                        // 소리\n                        robotis_rla_lite_Hello: '%1 말하기 %2',\n                        robotis_rla_lite_effectSound: '효과음 %1 재생하기 %2',\n                        robotis_rla_lite_record: '%1 번 방에 녹음하기 %2',\n                        robotis_rla_lite_playRecord: '%1 번 방 소리 재생하기 %2',\n\n                        // 다른 로봇 LCD 제어\n                        robotis_rla_lite_rgee_screen: '제어기 화면 배경을 알쥐 %1 (으)로 선택 %2',\n                        robotis_rla_lite_rgee_anim_screen:\n                            '제어기 화면 애니메이션을 알쥐 %1 (으)로 선택 %2',\n                        robotis_rla_lite_kkokdu_screen: '제어기 화면 배경을 꼭두 %1 (으)로 선택 %2',\n                        robotis_rla_lite_kkokdu_anim_screen:\n                            '제어기 화면 애니메이션을 꼭두 %1 (으)로 선택 %2',\n                        robotis_rla_lite_text_screen:\n                            '제어기 화면에 %1을(를) (%2, %3)위치에 %4 로 %5(으)로 출력하기 %6',\n\n                            \n                        // 주행 제어\n                        robotis_rla_lite_drive_simple: '알라 %1 속도로 %2 하기 %3',\n                        robotis_rla_lite_drive_stop: '알라 정지하기 %1',\n                        robotis_rla_lite_wheel_rotate:\n                            '%1 모터 %2의 속도로 %3 회전하기 %4',\n                        robotis_rla_lite_wheel_stop:\n                            '%1 모터 정지하기 %2',\n                        robotis_rla_lite_go_distance: '알라 로봇 %1 cm %2 하기 %3',\n                        robotis_rla_lite_turn_angle: '알라 로봇 제자리 %1 도 회전하기%3',\n                        robotis_rla_lite_motion: '알라 로봇 펜 %1 %2',\n\n                        // 라인 따라가기기\n                        robotis_rla_lite_follow_line: '%1 속도로 라인 따라가기 %2',\n                        robotis_rla_lite_stop_follow_line: '라인 따라가기 종료 %1',\n                    },\n                    Helper: {\n                        // 값 블록\n                        robotis_rla_lite_cm_ir_value:\n                            '지정한 번호의 IR 센서 값(범위: 0 ~ 400)',\n                        robotis_rla_lite_cm_ir_compare:\n                            \"지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_rla_lite_detectFrontObj:\n                            \"지정한 센서 앞에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_rla_lite_cm_btn_value:\n                            \"지정한 버튼이 눌렸다가 해제되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_rla_lite_cm_joystick_value:\n                            \"조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다..\",\n                        robotis_rla_lite_mic:\n                            '마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.',\n                        robotis_rla_lite_detectSound_compare:\n                            \"소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_rla_lite_imu:\n                            '지정한 축의 지정한 가속도센서/자이로센서의 값\\n범위: -100 ~ 100',\n                        robotis_rla_lite_roll_pitch:\n                            'roll/pitch 값\\nroll: -180° ~ 180°, pitch: -90° ~ 90°',\n\n                        // 소리\n                        robotis_rla_lite_buzzer_index: '지정한 음계, 옥타브, 시간만큼 연주하기',\n\n                        // LCD 제어\n                        robotis_rla_lite_rgee_screen: '제어기 화면배경을 알쥐의 지정한 표정으로 설정',\n                        robotis_rla_lite_rgee_anim_screen:\n                            '제어기 화면 애니메이션을 알쥐의 지정한 표정으로 설정',\n                        robotis_rla_lite_icon:\n                            '화면 중앙에 지정한 아이콘을 표시',\n                        robotis_rla_lite_LCDBright: '화면 밝기를 설정\\n밝기범위: 1% ~ 100%',\n                        robotis_rla_lite_LCDColor: '화면 색상을 설정',\n\n                        // LED 제어\n                        robotis_rla_lite_led_brightness: '제어기의 지정한 LED의 밝기를 설정정',\n                        robotis_rla_lite_led_pattern: '제어기의 LED의 깜박임 패턴 설정',\n\n                        // 소리\n                        robotis_rla_lite_Hello: '지정한 문장을 말하기',\n                        robotis_rla_lite_effectSound: '지정한 효과음 재생하기',\n                        robotis_rla_lite_record: '제어기의 지정한 번호에 녹음하기',\n                        robotis_rla_lite_playRecord: '제어기의 지정한 번호의 녹음음성 재생하기기',\n\n                        // 다른 로봇 LCD 제어\n                        robotis_rla_lite_rla_screen: '제어기 화면배경을 알라의 지정한 표정으로 설정',\n                        robotis_rla_lite_rla_anim_screen:\n                            '제어기 화면 애니메이션을 알라의 지정한 표정으로 설정',\n                        robotis_rla_lite_kkokdu_screen: '제어기 화면배경을 꼭두의 지정한 표정으로 설정',\n                        robotis_rla_lite_kkokdu_anim_screen:\n                            '제어기 화면 애니메이션을 꼭두두의 지정한 표정으로 설정',\n                        robotis_rla_lite_text_screen:\n                            '화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n                            \n                        // 주행 제어\n                        robotis_rla_lite_drive_simple: '알라를 지정한 속도와 방향으로 주행',\n                        robotis_rla_lite_drive_stop: '알라 정지하기',\n                        robotis_rla_lite_wheel_rotate: '알라의 지정한 바퀴를 지정한 속도와 방향으로 회전',\n                        robotis_rla_lite_wheel_stop: '알라의 지정한 바퀴를 정지',\n                        robotis_rla_lite_go_distance: '알라 지정한 거리만큼 주행',\n                        robotis_rla_lite_turn_angle: '알라 지정한 각도만큼 제자리 회전',\n                        robotis_rla_lite_motion: '알라 지정한 동작을 하기',\n\n                        // 라인 따라가기\n                        robotis_rla_lite_follow_line: '지정한 속도로 라인 따라가기',\n                        robotis_rla_lite_stop_follow_line: '라인 따라가기 종료',\n\n                    },\n                    Blocks: {\n                        robotis_white: \"흰색\",\n                        robotis_gray: \"회색\",\n                        robotis_darkgray: \"진회색\",\n                        robotis_black: \"검정\",\n                        robotis_purple: \"보라\",\n                        robotis_pink: \"분홍색\",\n                        robotis_red: \"빨강\",\n                        robotis_orange: \"주황\",\n                        robotis_brown: \"갈색\",\n                        robotis_yellow: \"노랑\",\n                        robotis_green: \"초록\",\n                        robotis_blue: \"파랑\",\n                        robotis_lightblue: \"연파랑\",\n                        robotis_darkblue: \"남색\",\n                        robotis_left: \"왼쪽\",\n                        robotis_center: \"중앙\",\n                        robotis_right: \"오른쪽\",\n                        robotis_both: \"양쪽\",\n                        robotis_korean1: \"안녕하세요\",\n                        robotis_korean2: \"반가워요\",\n                        robotis_korean3: \"알겠어요\",\n                        robotis_korean4: \"아니에요\",\n                        robotis_korean5: \"모르겠어요\",\n                        robotis_korean6: \"좋아요\",\n                        robotis_korean7: \"싫어요\",\n                        robotis_korean8: \"이름을말하세요\",\n                        robotis_korean9: \"무엇을도와줄까?\",\n                        robotis_korean10: \"잘했어\",\n                        robotis_korean11: \"괜찮아\",\n                        robotis_korean12: \"다시해보자\",\n                        robotis_korean13: \"고마워\",\n                        robotis_korean14: \"다시말해줄래?\",\n                        robotis_korean15: \"최고야!\",\n                        robotis_korean16: \"신나요\",\n                        robotis_korean17: \"즐거워요\",\n                        robotis_korean18: \"미안해요\",\n                        robotis_korean19: \"화나요\",\n                        robotis_korean20: \"부끄러워요\",\n                        robotis_korean21: \"무서워요\",\n                        robotis_korean22: \"속상해요\",\n                        robotis_korean23: \"사랑해요\",\n                        robotis_korean24: \"예뻐요\",\n                        robotis_korean25: \"신기해요\",\n                        robotis_korean26: \"초조해요\",\n                        robotis_korean27: \"앞으로가자\",\n                        robotis_korean28: \"뒤로가자\",\n                        robotis_korean29: \"일어나자\",\n                        robotis_korean30: \"넘어졌네?\",\n                        robotis_korean31: \"오예\",\n                        robotis_korean32: \"아싸\",\n                        robotis_korean33: \"어머\",\n                        robotis_korean34: \"이런\",\n                        robotis_korean35: \"오호\",\n                        robotis_korean36: \"하하하\",\n                        robotis_korean37: \"호호호\",\n                        robotis_korean38: \"졸려\",\n                        robotis_korean39: \"자장가를들려줘\",\n                        robotis_korean40: \"안녕\",\n                        robotis_korean41: \"배고프다\",\n                        robotis_korean42: \"도토리땡긴다\",\n                        robotis_korean43: \"아.씻고싶어\",\n                        robotis_korean44: \"비누목욕시간이야\",\n                        robotis_korean45: \"심심한데\",\n                        robotis_korean46: \"간식먹을까\",\n                        robotis_korean47: \"아파요\",\n                        robotis_korean48: \"약은없나요?\",\n                        robotis_korean49: \"어디로가야하지?\",\n                        robotis_korean50: \"와아도착이다\",\n                        robotis_korean51: \"왼쪽으로가자\",\n                        robotis_korean52: \"오른쪽으로가자\",\n                        robotis_korean53: \"깜짝이야\",\n                        robotis_korean54: \"찾았다\",\n                        robotis_korean55: \"여긴없네\",\n                        robotis_korean56: \"혹시나불렀어?\",\n                        robotis_korean57: \"내려주세요\",\n                        robotis_korean58: \"앗\",\n                        robotis_korean59: \"힝\",\n                        robotis_korean60: \"이익\",\n                        robotis_dog: \"개\",\n                        robotis_frog: \"개구리\",\n                        robotis_cat: \"고양이\",\n                        robotis_chicken: \"닭\",\n                        robotis_tiger: \"호랑이\",\n                        robotis_mouse: \"쥐\",\n                        robotis_ambul: \"앰뷸런스\",\n                        robotis_Horn: \"경적(빵빵)\",\n                        robotis_siren: \"사이렌(경찰차)\",\n                        robotis_whistle: \"호루라기\",\n                        robotis_gun: \"총소리\",\n                        robotis_clap: \"박수소리\",\n                        robotis_melody1: \"멜로디1\",\n                        robotis_melody2: \"멜로디2\",\n                        robotis_melody3: \"멜로디3\",\n                        robotis_melody4: \"멜로디4\",\n                        robotis_forward: \"앞으로\",\n                        robotis_backward: \"뒤로\",\n                        robotis_acceleration: \"가속도\",\n                        robotis_gyro: \"자이로\",\n                        robotis_run: \"실행\",\n                        robotis_cancel: \"취소\",\n                        robotis_push: \"눌림\",\n                        robotis_notPush: \"안눌림\",\n                        robotis_play: \"연주\",\n                        robotis_rest: \"쉼표\",\n                        robotis_face01: \"와하하\",\n                        robotis_face02: \"싱글벙글\",\n                        robotis_face03: \"큭큭큭\",\n                        robotis_face04: \"냠냠\",\n                        robotis_face05: \"겁먹음\",\n                        robotis_face06: \"답답\",\n                        robotis_face07: \"갸우뚱\",\n                        robotis_face08: \"어벙벙\",\n                        robotis_face09: \"고함\",\n                        robotis_face10: \"화남\",\n                        robotis_face11: \"킁킁(왼쪽)\",\n                        robotis_face12: \"킁킁(오른쪽)\",\n                        robotis_face13: \"킁킁(아래)\",\n                        robotis_face14: \"안심\",\n                        robotis_face15: \"기절\",\n                        robotis_face16: \"헤롱헤롱\",\n                        robotis_face17: \"하품\",\n                        robotis_face18: \"졸림\",\n                        robotis_face19: \"잠듦\",\n                        robotis_face20: \"마음앓이\",\n                        robotis_face21: \"폭풍눈물\",\n                        robotis_face22: \"목욕\",\n                        robotis_face23: \"햐트뿅뿅\",\n        \n                        robotis_car_anim01: \"기본 표정\",\n                        robotis_car_anim02: \"감동\",\n                        robotis_car_anim03: \"미소\",\n                        robotis_car_anim04: \"웃음\",\n                        robotis_car_anim05: \"기쁨\",\n                        robotis_car_anim06: \"행복\",\n                        robotis_car_anim07: \"자신감\",\n                        robotis_car_anim08: \"화남\",\n                        robotis_car_anim09: \"우울\",\n                        robotis_car_anim10: \"슬픔\",\n                        robotis_car_anim11: \"고통\",\n                        robotis_car_anim12: \"기절\",\n                        robotis_car_anim13: \"공포\",\n                        robotis_car_anim14: \"하품\",\n                        robotis_car_anim15: \"졸림\",\n                        robotis_car_anim16: \"오른쪽보기\",\n                        robotis_car_anim17: \"왼쪽보기\",\n                        robotis_car_anim18: \"앞쪽보기\",\n                        robotis_car_anim19: \"깜짝놀람\",\n        \n                        robotis_flashing1: \"점멸1\",\n                        robotis_flashing2: \"점멸2\",\n                        robotis_flashing3: \"점멸3\",\n                        robotis_flashing4: \"점멸4\",\n                        robotis_flashing5: \"점멸5\",\n                        robotis_flashing6: \"점멸6\",\n                        robotis_flashing7: \"점멸7\",\n                        robotis_flashing8: \"점멸8\",\n                        robotis_flashing9: \"점멸9\",\n                        robotis_moveF: \"전진\",\n                        robotis_moveB: \"후진\",\n                        robotis_moveL: \"좌회전\",\n                        robotis_moveR: \"우회전\",\n                        robotis_moveU: 'U턴',\n                        robotis_moveL_in_place: '제자리 좌회전',\n                        robotis_moveR_in_place: '제자리 우회전',\n                        robotis_moveU_in_place: '제자리 U턴',\n                        robotis_moveRG1: \"일어서기\",\n                        robotis_moveRG2: \"앉기\",\n                        robotis_moveRG3: \"발버둥\",\n                        robotis_moveRG4: \"발들기\",\n                        robotis_stMotion1: \"기본자세\",\n                        robotis_stMotion2: \"전진\",\n                        robotis_stMotion3: \"우전진\",\n                        robotis_stMotion4: \"좌전진\",\n                        robotis_stMotion5: \"후진\",\n                        robotis_stMotion6: \"오른쪽으로\",\n                        robotis_stMotion7: \"왼쪽으로\",\n                        robotis_stMotion8: \"우회전\",\n                        robotis_stMotion9: \"좌회전\",\n                        robotis_spMotion1: \"오른손 들기\",\n                        robotis_spMotion2: \"오른손 내리기\",\n                        robotis_spMotion3: \"왼손 들기\",\n                        robotis_spMotion4: \"왼손 내리기\",\n                        robotis_spMotion5: \"양손 들기\",\n                        robotis_spMotion6: \"양손 내리기\",\n                        robotis_spMotion7: \"뒤로 넘어지기\",\n                        robotis_spMotion8: \"앞으로 넘어지기\",\n                        robotis_spMotion9: \"앞으로 일어서기\",\n                        robotis_spMotion10: \"뒤로 일어서기\",\n                        robotis_spMotion11: \"방어\",\n                        robotis_spMotion12: \"공격1\",\n                        robotis_spMotion13: \"공격2\",\n                        robotis_spMotion14: \"공격3\",\n                        robotis_spMotion15: \"공격4\",\n                        robotis_screen1: \"가위\",\n                        robotis_screen2: \"바위\",\n                        robotis_screen3: \"보\",\n                        robotis_clockwise: \"시계방향\",\n                        robotis_counterclockwise: \"반시계방향\",\n                        robotis_up: \"들기\",\n                        robotis_down: \"내리기\",\n                        robotis_screen_text_font_small: \"작은 폰트\",\n                        robotis_screen_text_font_big: \"큰 폰트\",\n                        robotis_sensing_temperature: \"온도센서\",\n                        robotis_sensing_humidity: \"습도센서\",\n                        robotis_sensing_brightness: \"밝기센서\",\n                        robotis_sensing_motion: \"움직임센서\",\n                        robotis_sensing_button: \"버튼센서\",\n                        robotis_sensing_distance: \"거리센서\",\n                        robotis_sensing_ir_left: \"왼쪽 적외선센서\",\n                        robotis_sensing_ir_right: \"오른쪽 적외선센서\",\n                        robotis_stage_1: \"1단계\",\n                        robotis_stage_2: \"2단계\",\n                        robotis_stage_3: \"3단계\",\n                    },\n                },\n                en: {\n                    template: {                        \n                        // Value Blocks\n                        robotis_rla_lite_cm_ir_value: 'IR sensor value of No. %1',\n                        robotis_rla_lite_cm_ir_compare: 'If the IR sensor value of No. %1 is %2 %3',\n                        robotis_rla_lite_detectFrontObj: 'If there is an object in front',\n                        robotis_rla_lite_cm_btn_value: 'If button %1 is %2',\n                        robotis_rla_lite_cm_joystick_value: 'If joystick is at %1',\n                        robotis_rla_lite_mic: 'Microphone volume (dB)',\n                        robotis_rla_lite_detectSound_compare: 'If the sound comes from %1',\n                        robotis_rla_lite_imu: '%2 value of %1 axis',\n                        robotis_rla_lite_roll_pitch: 'Controller angle %1 value',\n\n                        // Musical Scale\n                        robotis_rla_lite_buzzer_index: 'Play note %1 on controller in octave %2 for %3 seconds %4 %5',\n\n                        // LCD Control\n                        robotis_rla_lite_rgee_screen: 'Set controller screen background to R-Gee %1 %2',\n                        robotis_rla_lite_rgee_anim_screen: 'Set controller screen animation to R-Gee %1 %2',\n                        robotis_rla_lite_icon: 'Display %1 on controller screen %5',\n                        robotis_rla_lite_LCDBright: 'Set controller screen brightness to %1 %2',\n                        robotis_rla_lite_LCDColor: 'Set controller screen color to %1 %2',\n\n                        // LED Control\n                        robotis_rla_lite_led_brightness: 'Set controller LED %1 brightness to %2 %3',\n                        robotis_rla_lite_led_pattern: 'Controller LED %1 %2 %3',\n\n                        // Sound\n                        robotis_rla_lite_Hello: 'Say \"%1\" %2',\n                        robotis_rla_lite_effectSound: 'Play sound effect %1 %2',\n                        robotis_rla_lite_record: 'Record in slot %1 %2',\n                        robotis_rla_lite_playRecord: 'Play sound from slot %1 %2',\n\n                        // Other Robot LCD Control\n                        robotis_rla_lite_rla_screen: 'Set controller screen background to Kodala %1 %2',\n                        robotis_rla_lite_rla_anim_screen: 'Set controller screen animation to Kodala %1 %2',\n                        robotis_rla_lite_kkokdu_screen: 'Set controller screen background to TIG %1 %2',\n                        robotis_rla_lite_kkokdu_anim_screen: 'Set controller screen animation to TIG %1 %2',\n                        robotis_rla_lite_text_screen: 'Display \"%1\" on screen at (%2, %3) with font %4 and color %5 %6',\n\n                        // Driving Control\n                        robotis_rla_lite_drive_simple: 'Move Kodala at speed %1 in direction %2 %3',\n                        robotis_rla_lite_drive_stop: 'Stop Kodala %1',\n                        robotis_rla_lite_wheel_rotate:\n                            'Rotate motor %1 at speed %2 in %3 direction %4',\n                        robotis_rla_lite_wheel_stop:\n                            'Stop motor %1 %2',\n                        robotis_rla_lite_go_distance: 'Move Kodala robot %1 cm in %2 direction %3',\n                        robotis_rla_lite_turn_angle: 'Rotate Kodala robot in place by %1 degrees %3',\n                        robotis_rla_lite_motion: 'Kodala %1 %2',\n\n                        // Line following\n                        robotis_rla_lite_follow_line: 'Follow line at speed %1 %2',\n                        robotis_rla_lite_stop_follow_line: 'Stop following line %1',\n                    },\n                    Helper: {\n                        // Value blocks\n                        robotis_rla_lite_cm_ir_value: 'IR sensor value of the specified number (Range: 0 ~ 400)',\n                        robotis_rla_lite_cm_ir_compare: \"Returns 'true' if the comparison of the IR sensor value of the specified number and the given value is correct; otherwise returns 'false'.\",\n                        robotis_rla_lite_detectFrontObj: \"Returns 'true' if an object is detected in front of the specified sensor; otherwise returns 'false'.\",\n                        robotis_rla_lite_cm_btn_value: \"Returns 'true' if the specified button was pressed and released; otherwise returns 'false'.\",\n                        robotis_rla_lite_cm_joystick_value: \"Returns 'true' if the joystick position matches the specified state; otherwise returns 'false'.\",\n                        robotis_rla_lite_mic: 'Displays the intensity of sound detected by the microphone in decibels (dB).',\n                        robotis_rla_lite_detectSound_compare: \"Returns 'true' if the direction of the sound matches the specified direction; otherwise returns 'false'.\",\n                        robotis_rla_lite_imu: 'Value of the specified axis of the accelerometer/gyroscope sensor\\nRange: -100 ~ 100',\n                        robotis_rla_lite_roll_pitch: 'Roll/pitch values\\nRoll: -180° ~ 180°, Pitch: -90° ~ 90°',\n\n                        // Sound\n                        robotis_rla_lite_buzzer_index: 'Play the specified scale, octave, and duration',\n\n                        // LCD control\n                        robotis_rla_lite_rgee_screen: 'Set the controller screen background to the specified R-Gee expression',\n                        robotis_rla_lite_rgee_anim_screen: 'Set the controller screen animation to the specified R-Gee expression',\n                        robotis_rla_lite_icon: 'Display the specified icon at the center of the screen',\n                        robotis_rla_lite_LCDBright: 'Set the screen brightness\\nBrightness range: 1% ~ 100%',\n                        robotis_rla_lite_LCDColor: 'Set the screen color',\n\n                        // LED control\n                        robotis_rla_lite_led_brightness: 'Set the brightness of the specified LED on the controller',\n                        robotis_rla_lite_led_pattern: 'Set the blinking pattern of the LED on the controller',\n\n                        // Sound\n                        robotis_rla_lite_Hello: 'Speak the specified sentence',\n                        robotis_rla_lite_effectSound: 'Play the specified sound effect',\n                        robotis_rla_lite_record: 'Record on the specified number of the controller',\n                        robotis_rla_lite_playRecord: 'Play the recorded voice of the specified number on the controller',\n\n                        // Other robot LCD control\n                        robotis_rla_lite_rla_screen: 'Set the controller screen background to the specified expression of Kodala',\n                        robotis_rla_lite_rla_anim_screen: 'Set the controller screen animation to the specified expression of Kodala',\n                        robotis_rla_lite_kkokdu_screen: 'Set the controller screen background to the specified expression of Kkokdu',\n                        robotis_rla_lite_kkokdu_anim_screen: 'Set the controller screen animation to the specified expression of Kkokdu',\n                        robotis_rla_lite_text_screen: 'Set the location, font size, and color of the specified phrase to be displayed on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n\n                        // Driving control (duplicate entries for R-Gee)\n                        robotis_rla_lite_drive_simple: 'Drive Kodala at the specified speed and direction',\n                        robotis_rla_lite_drive_stop: 'Stop Kodala',\n                        robotis_rla_lite_wheel_rotate: 'Rotate the specified wheel of Kodala at the given speed and direction',\n                        robotis_rla_lite_wheel_stop: 'Stop the specified wheel of Kodala',\n                        robotis_rla_lite_go_distance: 'Move Kodala forward/backward by the specified distance',\n                        robotis_rla_lite_turn_angle: 'Rotate Kodala in place by the specified angle',\n                        robotis_rla_lite_motion: 'Make Kodala perform the specified motion',\n                        robotis_rla_lite_follow_line: 'Start following the line at the specified speed',\n                        robotis_rla_lite_stop_follow_line: 'Stop following the line'\n                    },\n\n                    Blocks: {\n                        robotis_white: 'White',\n                        robotis_gray: 'Gray',\n                        robotis_darkgray: 'Darkgray',\n                        robotis_black: 'Black',\n                        robotis_purple: 'Purple',\n                        robotis_pink: 'Pink',\n                        robotis_red: 'Red',\n                        robotis_orange: 'Orange',\n                        robotis_brown: 'Brown',\n                        robotis_yellow: 'Yellow',\n                        robotis_green: 'Green',\n                        robotis_blue: 'Blue',\n                        robotis_lightblue: 'Lightblue',\n                        robotis_darkblue: 'Darkblue',\n                        robotis_brown: 'Brown',\n                        robotis_left: 'Left',\n                        robotis_center: 'Center',\n                        robotis_right: 'Right',\n                        robotis_both: 'Both',\n\n                        robotis_rla: 'R-GEE',\n                        robotis_rla: 'KODALA',\n                        robotis_kkokdu: 'TIG',\n                        \n                        robotis_korean1: 'Hello!',\n                        robotis_korean2: 'Great to see you.',\n                        robotis_korean3: 'Okay ~',\n                        robotis_korean4: 'No!',\n                        robotis_korean5: \"I don't know.\",\n                        robotis_korean6: 'I like it.',\n                        robotis_korean7: \"I don't like it.\",\n                        robotis_korean8: 'What is your name? ',\n                        robotis_korean9: 'How can I help you? ',\n                        robotis_korean10: 'Great job! ',\n                        robotis_korean11: \"It's alright.\",\n                        robotis_korean12: \"Let's do it again! \",\n                        robotis_korean13: 'Thank you! ',\n                        robotis_korean14: 'Can you say that one more time?',\n                        robotis_korean15: 'Awesome!',\n                        robotis_korean16: \"I'm excited! \",\n                        robotis_korean17: \"I'm having a great time! \",\n                        robotis_korean18: \"I'm sorry.\",\n                        robotis_korean19: \"I'm angry! \",\n                        robotis_korean20: \"I'm embarassed.\",\n                        robotis_korean21: \"I'm scared.\",\n                        robotis_korean22: \"I'm upset.\",\n                        robotis_korean23: 'I love you.',\n                        robotis_korean24: 'Very pretty! ',\n                        robotis_korean25: 'Interesting.',\n                        robotis_korean26: \"I'm nervous.\",\n                        robotis_korean27: \"Let's move forward! \",\n                        robotis_korean28: \"Let's move backward! \",\n                        robotis_korean29: \"Let's stand up! \",\n                        robotis_korean30: 'Did you fall down? ',\n                        robotis_korean31: 'Oh Yeah~',\n                        robotis_korean32: 'Sweet! ',\n                        robotis_korean33: 'Oh no',\n                        robotis_korean34: 'My My ',\n                        robotis_korean35: 'Whoo hoo! ',\n                        robotis_korean36: 'Ha Ha Ha',\n                        robotis_korean37: 'Ho Ho Ho ',\n                        robotis_korean38: \"I'm sleepy.\",\n                        robotis_korean39: 'Sing me a bedtime song! ',\n                        robotis_korean40: 'Hello!',\n                        robotis_korean41: \"I'm hungry.\",\n                        robotis_korean42: \"I'm craving an acorn! \",\n                        robotis_korean43: 'I want to take a bath! ',\n                        robotis_korean44: 'Time for a bath! ',\n                        robotis_korean45: \"I'm bored. \",\n                        robotis_korean46: 'Do you want a snack? ',\n                        robotis_korean47: \"I'm sick.\",\n                        robotis_korean48: 'Do you have any medicine? ',\n                        robotis_korean49: 'Where do we have to go? ',\n                        robotis_korean50: \"We're here! \",\n                        robotis_korean51: \"Let's go to the left side! \",\n                        robotis_korean52: \"Let's go to the right side! \",\n                        robotis_korean53: 'Oh my, you scared me! ',\n                        robotis_korean54: 'Found you! ',\n                        robotis_korean55: \"There's nothing here. \",\n                        robotis_korean56: 'Did you call me?',\n                        robotis_korean57: 'Please let me down. ',\n                        robotis_korean58: 'Oops! ',\n                        robotis_korean59: 'Hmmph! ',\n                        robotis_korean60: 'Eek! ',\n                        robotis_dog: 'Dog',\n                        robotis_frog: 'Frog',\n                        robotis_cat: 'Cat',\n                        robotis_chicken: 'Rooster',\n                        robotis_tiger: 'Tiger',\n                        robotis_mouse: 'Mouse',\n                        robotis_whistle: 'Whistle',\n                        robotis_ambul: 'Ambulance',\n                        robotis_Horn: 'CarHorn',\n                        robotis_siren: 'Siren',\n                        robotis_gun: 'Gunshot',\n                        robotis_clap: 'Clap',\n                        robotis_melody1: 'Melody1',\n                        robotis_melody2: 'Melody2',\n                        robotis_melody3: 'Melody3',\n                        robotis_melody4: 'Melody4',\n                        robotis_forward: 'Forward',\n                        robotis_backward: 'Backward',\n                        robotis_acceleration: 'acceleration',\n                        robotis_gyro: 'gyro',\n                        robotis_run: 'Run',\n                        robotis_cancel: 'Cancel',\n                        robotis_push: 'Pressed',\n                        robotis_notPush: 'Unpressed',\n                        robotis_play: 'Play',\n                        robotis_rest: 'Rest',\n                        robotis_face01: 'Haha',\n                        robotis_face02: 'Smile',\n                        robotis_face03: 'Laugh',\n                        robotis_face04: 'Yum Yum',\n                        robotis_face05: 'Scared',\n                        robotis_face06: 'Uncomfortable',\n                        robotis_face07: 'Confused',\n                        robotis_face08: 'Dazed',\n                        robotis_face09: 'Yell',\n                        robotis_face10: 'Angry',\n                        robotis_face11: 'Sniff (Left)',\n                        robotis_face12: 'Sniff (Right)',\n                        robotis_face13: 'Sniff (Down)',\n                        robotis_face14: 'Whew',\n                        robotis_face15: 'Faint',\n                        robotis_face16: 'Dizzy',\n                        robotis_face17: 'Yawn',\n                        robotis_face18: 'Sleepy',\n                        robotis_face19: 'Sleep',\n                        robotis_face20: 'Sad',\n                        robotis_face21: 'Cry',\n                        robotis_face22: 'Bath',\n                        robotis_face23: 'Heart-Eyes',\n                                \n                        robotis_car_anim01: \"Default\",\n                        robotis_car_anim02: \"Touched\",\n                        robotis_car_anim03: \"Smile\",\n                        robotis_car_anim04: \"Laugh\",\n                        robotis_car_anim05: \"Joy\",\n                        robotis_car_anim06: \"Happiness\",\n                        robotis_car_anim07: \"Confidence\",\n                        robotis_car_anim08: \"Anger\",\n                        robotis_car_anim09: \"Depressed\",\n                        robotis_car_anim10: \"Sadness\",\n                        robotis_car_anim11: \"Pain\",\n                        robotis_car_anim12: \"Fainting\",\n                        robotis_car_anim13: \"Fear\",\n                        robotis_car_anim14: \"Yawn\",\n                        robotis_car_anim15: \"Sleepy\",\n                        robotis_car_anim16: \"Looking Right\",\n                        robotis_car_anim17: \"Looking Left\",\n                        robotis_car_anim18: \"Looking Forward\",\n                        robotis_car_anim19: \"Surprised\",\n\n        \n                        robotis_flashing1: \"Flashing1\",\n                        robotis_flashing2: \"Flashing2\",\n                        robotis_flashing3: \"Flashing3\",\n                        robotis_flashing4: \"Flashing4\",\n                        robotis_flashing5: \"Flashing5\",\n                        robotis_flashing6: \"Flashing6\",\n                        robotis_flashing7: \"Flashing7\",\n                        robotis_flashing8: \"Flashing8\",\n                        robotis_flashing9: \"Flashing9\",\n\n\n\n                        robotis_moveF: 'Forward',\n                        robotis_moveB: 'Backward',\n                        robotis_moveL: 'LeftTurn',\n                        robotis_moveR: 'RightTurn',\n                        robotis_moveU: 'U-turn',\n                        robotis_moveL_in_place: 'Turn left in place',\n                        robotis_moveR_in_place: 'Trun right in place',\n                        robotis_moveU_in_place: 'U-turn in place',\n                        robotis_moveRG1: 'Stand',\n                        robotis_moveRG2: 'Sit',\n                        robotis_moveRG3: 'Struggle',\n                        robotis_moveRG4: 'RaiseFeet',\n                        robotis_fast: 'Fast',\n                        robotis_normal: 'Normal',\n                        robotis_slow: 'Slow',\n                        robotis_stop: 'Stop',\n                        robotis_roll: 'Left-right rotate angle (roll)',\n                        robotis_pitch: 'Forward-backward rotate angle (pitch)',\n                        robotis_stMotion1: 'Standard',\n                        robotis_stMotion2: 'Forward',\n                        robotis_stMotion3: 'TurnRight',\n                        robotis_stMotion4: 'TurnLeft',\n                        robotis_stMotion5: 'Backward',\n                        robotis_stMotion6: 'ToRight',\n                        robotis_stMotion7: 'ToLeft',\n                        robotis_stMotion8: 'TurnAroundRight',\n                        robotis_stMotion9: 'TurnAroundLeft',\n                        robotis_spMotion1: 'RightHandUp',\n                        robotis_spMotion2: 'RightHandDown',\n                        robotis_spMotion3: 'LeftHandUp',\n                        robotis_spMotion4: 'LeftHandDown',\n                        robotis_spMotion5: 'BothHandsUp',\n                        robotis_spMotion6: 'BothHandsDown',\n                        robotis_spMotion7: 'FallBackward',\n                        robotis_spMotion8: 'FallForward',\n                        robotis_spMotion9: 'StandForward',\n                        robotis_spMotion10: 'StandBackward',\n                        robotis_spMotion11: 'Defence',\n                        robotis_spMotion12: 'Offense1',\n                        robotis_spMotion13: 'Offense2',\n                        robotis_spMotion14: 'Offense3',\n                        robotis_spMotion15: 'Offense4',\n                        robotis_screen1: 'Sissor',\n                        robotis_screen2: 'Rock',\n                        robotis_screen3: 'Paper',\n                        robotis_clockwise: \"clockwise\",\n                        robotis_counterclockwise: \"counterclockwise\",\n                        robotis_up: \"up\",\n                        robotis_down: \"down\",\n                        robotis_screen_text_font_small: \"Small font\",\n                        robotis_screen_text_font_big: \"Big font\",\n                        robotis_stage_1: \"Stage 1\",\n                        robotis_stage_2: \"Stage 2\",\n                        robotis_stage_3: \"Stage 3\",\n                    },\n                },\n            };\n        }\n        getBlocks() {\n            return {\n                robotis_rla_lite_cm_ir_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '360'],\n                                ['2', '362'],\n                                ['3', '364'],\n                                ['4', '366'],\n                                ['5', '368'],\n                                ['6', '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_cm_ir_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        const scope = script.executor.scope;\n\n                        const data_default_address = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisRlaLite.dataBuffer[data_default_address];\n                        if (result == undefined) {\n                            result = rb100_last_valid_value[data_default_address];\n                        } else {\n                            rb100_last_valid_value[data_default_address] = result;\n                        }\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return Math.round(result % 65536);\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.ir_value(%1)'],\n                    },\n                },\n                robotis_rla_lite_cm_ir_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '360'],\n                                ['2', '362'],\n                                ['3', '364'],\n                                ['4', '366'],\n                                ['5', '368'],\n                                ['6', '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['>', '0'],\n                                ['<', '1'],\n                                ['=', '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 200],\n                        type: 'robotis_rla_lite_cm_ir_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                        COMPARE_OP: 1,\n                        COMPARE_VAL: 2,\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = script.getNumberValue('COMPARE_VAL');\n                        let compareOP = script.getNumberValue('COMPARE_OP');\n\n                        let result = Entry.RobotisRlaLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        result = Math.round(result % 65536);\n\n                        switch (compareOP) {\n                            case 0:\n                                return result > compareValue;\n                            case 1:\n                                return result < compareValue;\n                            default:\n                                return false;\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.ir_compare(%1)'],\n                    },\n                },\n                robotis_rla_lite_detectFrontObj: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n\n                        ],\n                        type: 'robotis_rla_lite_detectFrontObj',\n                    },\n                    paramsKeyMap: {\n\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let ir_1 = 0;\n                        let ir_2 = 0;\n\n                        \n                            \n                        ir_1 = Entry.RobotisRlaLite.dataBuffer[360];\n                        ir_2 = Entry.RobotisRlaLite.dataBuffer[362];\n                        if (ir_1 == undefined) {\n                            ir_1 = 0;\n                        }\n                        if (ir_2 == undefined) {\n                            ir_2 = 0;\n                        }\n                        return ir_1 > 100 || ir_2 > 100;\n                            \n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.detectFrontObj()'],\n                    },\n                },\n                robotis_rla_lite_cm_btn_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_run, '45'],\n                                [Lang.Blocks.robotis_cancel, '42'],\n                            ],\n                            value: '45',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_push, '1'],\n                                [Lang.Blocks.robotis_notPush, '0'],\n        \n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_cm_btn_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = 1;\n\n                        let result = Entry.RobotisRlaLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.btn_value(%1)'],\n                    },\n                },\n                robotis_rla_lite_cm_joystick_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_center, '0'],\n                                ['←', '1'],\n                                ['→', '2'],\n                                ['↑', '3'],\n                                ['↓', '4'],\n                                ['↖', '5'],\n                                ['↗', '6'],\n                                ['↙', '7'],\n                                ['↘', '8'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_cm_joystick_value',\n                    },\n                    paramsKeyMap: {\n                        COMPARE_VAL: 0,\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 50;\n                        let compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                        let result = Entry.RobotisRlaLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.joystick_value()'],\n                    },\n                },\n                robotis_rla_lite_mic: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_mic',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    async func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 119;\n\n                        let result = Entry.RobotisRlaLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.mic()'],\n                    },\n                },\n                robotis_rla_lite_detectSound_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_right, '255'],\n                                [Lang.Blocks.robotis_center, '0'],\n                                [Lang.Blocks.robotis_left, '1'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_detectSound_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 5031;\n                        let compareValue = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisRlaLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.detectSound_compare(%1)'],\n                    },\n                },\n                robotis_rla_lite_imu: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['x', '78'], //72\n                                ['y', '80'], //74\n                                ['z', '82'], //76\n                            ],\n                            value: '78',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_acceleration, '0'], //72\n                                [Lang.Blocks.robotis_gyro, '6'], //74\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rla_lite_imu',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                        MODE: 1,\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address =\n                            script.getField('AXIS', script) - script.getField('MODE', script);\n\n                        let result = Entry.RobotisRlaLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.imu()'],\n                    },\n                },\n                robotis_rla_lite_roll_pitch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_roll, '70'], //72\n                                [Lang.Blocks.robotis_pitch, '88'], //74\n                            ],\n                            value: '70',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_roll_pitch',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    class: 'robotis_rla_lite_value',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('AXIS');\n\n                        let result = Entry.RobotisRlaLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.roll_pitch(%1)'],\n                    },\n                },\n\n                \n                robotis_rla_lite_buzzer_index: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.General.note_c + '', '1'],\n                                [Lang.General.note_c + '#', '2'],\n                                [Lang.General.note_d + '', '3'],\n                                [Lang.General.note_d + '#', '4'],\n                                [Lang.General.note_e + '', '5'],\n                                [Lang.General.note_f + '', '6'],\n                                [Lang.General.note_f + '#', '7'],\n                                [Lang.General.note_g + '', '8'],\n                                [Lang.General.note_g + '#', '9'],\n                                [Lang.General.note_a + '', '10'],\n                                [Lang.General.note_a + '#', '11'],\n                                [Lang.General.note_b + '', '12'],\n                            ],\n                            value: '11',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_play, '1'],\n                                [Lang.Blocks.robotis_rest, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 1, null, null],\n                        type: 'robotis_rla_lite_buzzer_index',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_INDEX: 0,\n                        CM_BUZZER_OCTAV: 1,\n                        CM_BUZZER_DELAY: 2,\n                        CM_BUZZER_PLAY: 3\n                    },\n                    class: 'robotis_rla_lite_sound',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                        let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                        let cmBuzzerTime = script.getNumberValue('CM_BUZZER_DELAY', script);\n                        let cmBuzzerPlay = script.getNumberValue('CM_BUZZER_PLAY', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 0;\n                        let data_value = 0;\n                        let interval = 0;\n                        let data_buf = [];\n\n                        cmBuzzerTime = Math.round(cmBuzzerTime * 1000);\n\n                        data_address = 740;\n                        // data_value_1 = cmBuzzerTime * 10;\n                        // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n\n                        if (cmBuzzerTime < 0) {\n                            cmBuzzerTime = 0;\n                        }\n                        if (cmBuzzerTime > 50000) {\n                            cmBuzzerTime = 50000;\n                        }\n\n                        data_buf.push(cmBuzzerTime % 256);\n                        data_buf.push(Math.floor(cmBuzzerTime / 256));\n\n                        data_value = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n                        data_buf.push(Math.floor(data_value));\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [[data_instruction, data_address, 3, data_buf]];\n\n                        if(cmBuzzerPlay == '2') {\n                            data_sendqueue = [];\n                        }\n                        \n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.buzzer_index(%1, %2, %3)'],\n                    },\n                },\n\n\n                robotis_rla_lite_rgee_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_face01, '2817'],\n                                [Lang.Blocks.robotis_face02, '2818'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face03, '2819'],\n                                [Lang.Blocks.robotis_face04, '2820'],\n                                [Lang.Blocks.robotis_face05, '2821'],\n        \n                                [Lang.Blocks.robotis_face06, '2822'],\n                                [Lang.Blocks.robotis_face07, '2823'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face08, '2824'],\n                                [Lang.Blocks.robotis_face09, '2825'],\n                                [Lang.Blocks.robotis_face10, '2826'],\n        \n                                [Lang.Blocks.robotis_face11, '2827'],\n                                [Lang.Blocks.robotis_face12, '2828'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face13, '2829'],\n                                \n                                [Lang.Blocks.robotis_face14, '2830'],\n                                [Lang.Blocks.robotis_face15, '2831'],\n                                [Lang.Blocks.robotis_face16, '2832'],\n                                [Lang.Blocks.robotis_face17, '2833'],\n                                [Lang.Blocks.robotis_face18, '2834'],\n        \n                                [Lang.Blocks.robotis_face19, '2835'],\n                                [Lang.Blocks.robotis_face20, '2836'],\n                                [Lang.Blocks.robotis_face21, '2837'],\n                                [Lang.Blocks.robotis_face22, '2838'],\n                                [Lang.Blocks.robotis_face23, '2839'],\n                            ],\n                            value: '2817',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rla_lite_rgee_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.rgee_screen(%1)'] },\n                },\n\n                robotis_rla_lite_rgee_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_face01, '30748'],\n                                [Lang.Blocks.robotis_face02, '30749'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face03, '30750'],\n                                [Lang.Blocks.robotis_face04, '30756'],\n                                [Lang.Blocks.robotis_face05, '30754'],\n        \n                                [Lang.Blocks.robotis_face06, '30741'],\n                                [Lang.Blocks.robotis_face07, '30747'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face08, '30738'],\n                                [Lang.Blocks.robotis_face09, '30740'],\n                                [Lang.Blocks.robotis_face10, '30739'],\n        \n                                [Lang.Blocks.robotis_face11, '30733'],\n                                [Lang.Blocks.robotis_face12, '30734'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_face13, '30732'],\n                                \n                                [Lang.Blocks.robotis_face14, '30757'],\n                                [Lang.Blocks.robotis_face15, '30736'],\n                                [Lang.Blocks.robotis_face16, '30731'],\n                                [Lang.Blocks.robotis_face17, '30742'],\n                                [Lang.Blocks.robotis_face18, '30743'],\n        \n                                [Lang.Blocks.robotis_face19, '30744'],\n                                [Lang.Blocks.robotis_face20, '30751'],\n                                [Lang.Blocks.robotis_face21, '30752'],\n                                [Lang.Blocks.robotis_face22, '30755'],\n                                [Lang.Blocks.robotis_face23, '30758'],\n                            ],\n                            value: '30748',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rla_lite_rgee_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.rgee_animation_screen(%1)'] },\n                },\n\n\n\n\n                robotis_rla_lite_icon: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_screen1, '11545'],\n                                        [Lang.Blocks.robotis_screen2, '11546'],\n                                [Lang.Blocks.robotis_screen3, '11547'],\n                                ['0', '11283'],\n                                ['1', '11284'],\n                                ['2', '11285'],\n                                ['3', '11286'],\n                                ['4', '11287'],\n                                ['5', '11288'],\n                                ['6', '11289'],\n                                ['7', '11290'],\n                                ['8', '11291'],\n                                ['9', '11292'],\n                                ['10', '11293'],\n                            ],\n                            value: '11545',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_rla_lite_icon',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.icon_screen(%1,%2,%3,%4)'],\n                    },\n                },\n\n\n                robotis_rla_lite_LCDBright: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [10],\n                        type: 'robotis_rla_lite_LCDBright',\n                    },\n                    paramsKeyMap: {\n                        BRIGHT: 0,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let bright = script.getNumberValue('BRIGHT', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 180;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        bright = Math.min(Math.max(bright, 0), 100);\n\n                        data_value = bright;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.LCDBright(%1)'],\n                    },\n                },\n                robotis_rla_lite_LCDColor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '224',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_LCDColor',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let color = script.getNumberValue('COLOR', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = color;\n                        bg_color = color;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.LCDColor(%1)'],\n                    },\n                },\n\n                robotis_rla_lite_led_brightness: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '2'],\n                                [Lang.Blocks.robotis_both, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null, \n                            {\n                                type: 'number',\n                                params: [100]\n                            }\n                        ],\n                        type: 'robotis_rla_lite_led_brightness',\n                    },\n                    paramsKeyMap: {\n                        RB_LED: 0,\n                        BRIGHT: 1,\n                    },\n                    class: 'robotis_rla_lite_led',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmLed = script.getNumberValue('RB_LED', script);\n                        let bright = script.getNumberValue('BRIGHT', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 0;\n                        let data_length = 1;\n                        let data_value = 0;\n                        \n                        if(bright < 0){ \n                            bright = 0;\n                        } else if(bright > 100) {\n                            bright = 100\n                        }\n                        data_value = 100+bright;\n\n                        if (cmLed == 1) {\n                            data_address = 40;\n                            data_length = 1;\n                        } else if (cmLed == 2) {\n                            data_address = 41;\n                            data_length = 1;\n                        } else if (cmLed == 3) {\n                            data_address = 40;\n                            data_length = 2;\n                            data_value = data_value * 257\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.led_brightness(%1, %2)'] },\n                },\n                robotis_rla_lite_led_pattern: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_flashing1, '11'],\n                                [Lang.Blocks.robotis_flashing2, '12'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing3, '13'],\n        \n                                [Lang.Blocks.robotis_flashing4, '21'],\n                                [Lang.Blocks.robotis_flashing5, '22'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing6, '23'],\n        \n                                [Lang.Blocks.robotis_flashing7, '31'],\n                                [Lang.Blocks.robotis_flashing8, '32'], //Lang.Blocks.robotis_robotis_common_green_color\n                                [Lang.Blocks.robotis_flashing9, '33'],\n        \n                            ],\n                            value: '11',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_common_on, '1'],\n                                [Lang.Blocks.robotis_common_off, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'robotis_rla_lite_led_pattern',\n                    },\n                    paramsKeyMap: {\n                        RB_LED: 0,\n                        VALUE: 1,\n                    },\n                    class: 'robotis_rla_lite_led',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmLed = script.getNumberValue('RB_LED', script);\n                        let value = script.getNumberValue('VALUE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 40;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = value * cmLed;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.led_pattern(%1, %2)'] },\n                },\n\n                \n\n                robotis_rla_lite_Hello: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_korean1, '0'],\n                                [Lang.Blocks.robotis_korean2, '1'],\n                                [Lang.Blocks.robotis_korean3, '2'],\n                                [Lang.Blocks.robotis_korean4, '3'],\n                                [Lang.Blocks.robotis_korean5, '4'],\n                                [Lang.Blocks.robotis_korean6, '5'],\n                                [Lang.Blocks.robotis_korean7, '6'],\n                                [Lang.Blocks.robotis_korean8, '7'],\n                                [Lang.Blocks.robotis_korean9, '8'],\n                                [Lang.Blocks.robotis_korean10, '9'],\n                                [Lang.Blocks.robotis_korean11, '10'],\n                                [Lang.Blocks.robotis_korean12, '11'],\n                                [Lang.Blocks.robotis_korean13, '12'],\n                                [Lang.Blocks.robotis_korean14, '13'],\n                                [Lang.Blocks.robotis_korean15, '14'],\n                                [Lang.Blocks.robotis_korean16, '15'],\n                                [Lang.Blocks.robotis_korean17, '16'],\n                                [Lang.Blocks.robotis_korean18, '17'],\n                                [Lang.Blocks.robotis_korean19, '18'],\n                                [Lang.Blocks.robotis_korean20, '19'],\n                                [Lang.Blocks.robotis_korean21, '20'],\n                                [Lang.Blocks.robotis_korean22, '21'],\n                                [Lang.Blocks.robotis_korean23, '22'],\n                                [Lang.Blocks.robotis_korean24, '23'],\n                                [Lang.Blocks.robotis_korean25, '24'],\n                                [Lang.Blocks.robotis_korean26, '25'],\n                                [Lang.Blocks.robotis_korean27, '26'],\n                                [Lang.Blocks.robotis_korean28, '27'],\n                                [Lang.Blocks.robotis_korean29, '28'],\n                                [Lang.Blocks.robotis_korean30, '29'],\n                                [Lang.Blocks.robotis_korean31, '30'],\n                                [Lang.Blocks.robotis_korean32, '31'],\n                                [Lang.Blocks.robotis_korean33, '32'],\n                                [Lang.Blocks.robotis_korean34, '33'],\n                                [Lang.Blocks.robotis_korean35, '34'],\n                                [Lang.Blocks.robotis_korean36, '35'],\n                                [Lang.Blocks.robotis_korean37, '36'],\n                                [Lang.Blocks.robotis_korean38, '37'],\n                                [Lang.Blocks.robotis_korean39, '38'],\n                                [Lang.Blocks.robotis_korean40, '39'],\n                                [Lang.Blocks.robotis_korean41, '40'],\n                                [Lang.Blocks.robotis_korean42, '41'],\n                                [Lang.Blocks.robotis_korean43, '42'],\n                                [Lang.Blocks.robotis_korean44, '43'],\n                                [Lang.Blocks.robotis_korean45, '44'],\n                                [Lang.Blocks.robotis_korean46, '45'],\n                                [Lang.Blocks.robotis_korean47, '46'],\n                                [Lang.Blocks.robotis_korean48, '47'],\n                                [Lang.Blocks.robotis_korean49, '48'],\n                                [Lang.Blocks.robotis_korean50, '49'],\n                                [Lang.Blocks.robotis_korean51, '50'],\n                                [Lang.Blocks.robotis_korean52, '51'],\n                                [Lang.Blocks.robotis_korean53, '52'],\n                                [Lang.Blocks.robotis_korean54, '53'],\n                                [Lang.Blocks.robotis_korean55, '54'],\n                                [Lang.Blocks.robotis_korean56, '55'],\n                                [Lang.Blocks.robotis_korean57, '56'],\n                                [Lang.Blocks.robotis_korean58, '57'],\n                                [Lang.Blocks.robotis_korean59, '58'],\n                                [Lang.Blocks.robotis_korean60, '59'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_Hello',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_rla_lite_sound',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = 25601 + Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n\n                        if (cmHello == '38' || cmHello == '55') {\n                            extraTime = 2000;\n                        }\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            2000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.speak(%1)'],\n                    },\n                },\n                robotis_rla_lite_effectSound: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dog, '0'],\n                                [Lang.Blocks.robotis_frog, '1'],\n                                [Lang.Blocks.robotis_cat, '2'],\n                                [Lang.Blocks.robotis_chicken, '7'],\n                                [Lang.Blocks.robotis_tiger, '19'],\n                                [Lang.Blocks.robotis_mouse, '17'],\n\n                                [Lang.Blocks.robotis_ambul, '773'],\n                                [Lang.Blocks.robotis_Horn, '781'],\n                                [Lang.Blocks.robotis_siren, '774'],\n                                [Lang.Blocks.robotis_whistle, '274'],\n                                [Lang.Blocks.robotis_gun, '775'],\n                                [Lang.Blocks.robotis_clap, '260'],\n\n                                [Lang.Blocks.robotis_melody1, '786'],\n                                [Lang.Blocks.robotis_melody2, '787'],\n                                [Lang.Blocks.robotis_melody3, '788'],\n                                [Lang.Blocks.robotis_melody4, '789'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_effectSound',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_rla_lite_sound',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n                        if (\n                            cmHello == '272' ||\n                            cmHello == '786' ||\n                            cmHello == '787' ||\n                            cmHello == '788' ||\n                            cmHello == '789'\n                        ) {\n                            //오리\n                            extraTime = 0;\n                            if (cmHello == '788' || cmHello == '789') {\n                                extraTime += 500;\n                            }\n                        }\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            3000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.effect_sound(%1)'],\n                    },\n                },\n                robotis_rla_lite_record: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_record',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_rla_lite_sound',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 115;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.record(%1)'],\n                    },\n                },\n                robotis_rla_lite_playRecord: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_playRecord',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_rla_lite_sound',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 116;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.playRecord(%1)'],\n                    },\n                },\n\n\n\n                \n                robotis_rla_lite_rla_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '3329'],\n                                [Lang.Blocks.robotis_car_anim02, '3330'],\n                                [Lang.Blocks.robotis_car_anim03, '3331'],\n                                [Lang.Blocks.robotis_car_anim04, '3332'],\n                                [Lang.Blocks.robotis_car_anim05, '3333'],\n        \n                                [Lang.Blocks.robotis_car_anim06, '3334'],\n                                [Lang.Blocks.robotis_car_anim07, '3335'], \n                                [Lang.Blocks.robotis_car_anim08, '3336'],\n                                [Lang.Blocks.robotis_car_anim09, '3337'],\n                                [Lang.Blocks.robotis_car_anim10, '3338'],\n        \n                                [Lang.Blocks.robotis_car_anim11, '3339'],\n                                [Lang.Blocks.robotis_car_anim12, '3340'], \n                                [Lang.Blocks.robotis_car_anim13, '3341'],\n                                [Lang.Blocks.robotis_car_anim14, '3342'],\n                                [Lang.Blocks.robotis_car_anim15, '3343'],\n        \n                                [Lang.Blocks.robotis_car_anim16, '3344'],\n                                [Lang.Blocks.robotis_car_anim17, '3345'], \n                                [Lang.Blocks.robotis_car_anim18, '3346'],\n                                [Lang.Blocks.robotis_car_anim19, '3347'],\n                            ],\n                            value: '3329',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rla_lite_rla_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.rla_screen(%1)'] },\n                },\n\n                robotis_rla_lite_rla_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '30978'],\n                                [Lang.Blocks.robotis_car_anim02, '30981'],\n                                [Lang.Blocks.robotis_car_anim03, '30982'],\n                                [Lang.Blocks.robotis_car_anim04, '30983'],\n                                [Lang.Blocks.robotis_car_anim05, '30984'],\n        \n                                [Lang.Blocks.robotis_car_anim06, '30985'],\n                                [Lang.Blocks.robotis_car_anim07, '30986'], \n                                [Lang.Blocks.robotis_car_anim08, '30987'],\n                                [Lang.Blocks.robotis_car_anim09, '30988'],\n                                [Lang.Blocks.robotis_car_anim10, '30989'],\n        \n                                [Lang.Blocks.robotis_car_anim11, '30990'],\n                                [Lang.Blocks.robotis_car_anim12, '30991'], \n                                [Lang.Blocks.robotis_car_anim13, '30992'],\n                                [Lang.Blocks.robotis_car_anim14, '30993'],\n                                [Lang.Blocks.robotis_car_anim15, '30994'],\n        \n                                [Lang.Blocks.robotis_car_anim16, '30995'],\n                                [Lang.Blocks.robotis_car_anim17, '30996'], \n                                [Lang.Blocks.robotis_car_anim18, '30997'],\n                                [Lang.Blocks.robotis_car_anim19, '30998'],\n                            ],\n                            value: '30978',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rla_lite_rla_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.rla_animation_screen(%1)'] },\n                },\n                \n                robotis_rla_lite_kkokdu_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '3585'],\n                                [Lang.Blocks.robotis_car_anim02, '3586'],\n                                [Lang.Blocks.robotis_car_anim03, '3587'],\n                                [Lang.Blocks.robotis_car_anim04, '3588'],\n                                [Lang.Blocks.robotis_car_anim05, '3589'],\n        \n                                [Lang.Blocks.robotis_car_anim06, '3590'],\n                                [Lang.Blocks.robotis_car_anim07, '3591'], \n                                [Lang.Blocks.robotis_car_anim08, '3592'],\n                                [Lang.Blocks.robotis_car_anim09, '3593'],\n                                [Lang.Blocks.robotis_car_anim10, '3594'],\n        \n                                [Lang.Blocks.robotis_car_anim11, '3595'],\n                                [Lang.Blocks.robotis_car_anim12, '3596'], \n                                [Lang.Blocks.robotis_car_anim13, '3597'],\n                                [Lang.Blocks.robotis_car_anim14, '3598'],\n                                [Lang.Blocks.robotis_car_anim15, '3599'],\n        \n                                [Lang.Blocks.robotis_car_anim16, '3600'],\n                                [Lang.Blocks.robotis_car_anim17, '3601'], \n                                [Lang.Blocks.robotis_car_anim18, '3602'],\n                                [Lang.Blocks.robotis_car_anim19, '3603'],\n                            ],\n                            value: '3585',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rla_lite_kkokdu_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.kkokdu_screen(%1)'] },\n                },\n\n                robotis_rla_lite_kkokdu_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '31234'],\n                                [Lang.Blocks.robotis_car_anim02, '31237'],\n                                [Lang.Blocks.robotis_car_anim03, '31238'],\n                                [Lang.Blocks.robotis_car_anim04, '31239'],\n                                [Lang.Blocks.robotis_car_anim05, '31240'],\n        \n                                [Lang.Blocks.robotis_car_anim06, '31241'],\n                                [Lang.Blocks.robotis_car_anim07, '31242'], \n                                [Lang.Blocks.robotis_car_anim08, '31243'],\n                                [Lang.Blocks.robotis_car_anim09, '31244'],\n                                [Lang.Blocks.robotis_car_anim10, '31245'],\n        \n                                [Lang.Blocks.robotis_car_anim11, '31246'],\n                                [Lang.Blocks.robotis_car_anim12, '31247'], \n                                [Lang.Blocks.robotis_car_anim13, '31248'],\n                                [Lang.Blocks.robotis_car_anim14, '31249'],\n                                [Lang.Blocks.robotis_car_anim15, '31250'],\n        \n                                [Lang.Blocks.robotis_car_anim16, '31251'],\n                                [Lang.Blocks.robotis_car_anim17, '31252'], \n                                [Lang.Blocks.robotis_car_anim18, '31253'],\n                                [Lang.Blocks.robotis_car_anim19, '31254'],\n                            ],\n                            value: '31234',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rla_lite_kkokdu_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        BACKGROUND: 0,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.kkokdu_animation_screen(%1)'] },\n                },\n                robotis_rla_lite_text_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_screen_text_font_small, '0'],\n                                [Lang.Blocks.robotis_screen_text_font_big, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            ' ',\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'robotis_rla_lite_text_screen',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        X: 1,\n                        Y: 2,\n                        FONT: 3,\n                        COLOR: 4,\n                    },\n                    class: 'robotis_rla_lite_lcd',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let text = script.getStringValue('TEXT', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let font = script.getNumberValue('FONT', script);\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 900;\n                        let data_length = 2;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        let encoder = new TextEncoder('utf-8');\n                        let byteArray = encoder.encode(text);\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(font);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(color);\n                        data_buf.push(byteArray.length);\n                        for (i = 0; i < byteArray.length; i++) {\n                            data_buf.push(byteArray[i]);\n                        }\n\n                        data_length = 9 + byteArray.length;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.text_screen(%1,%2,%3,%4,%5)'],\n                    },\n                },\n\n\n                \n                robotis_rla_lite_drive_simple: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '2'],\n                                [Lang.Blocks.robotis_moveL, '3'],\n                                [Lang.Blocks.robotis_moveR, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [10, null, null],\n                        type: 'robotis_rla_lite_drive_simple',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        const speed = script.getNumberValue('SPEED', script);\n                        const direction = script.getField('DIRECTION', script);\n\n                        const data_instruction = INST_WRITE;\n                        const data_address = 710;\n                        const data_length = 2;\n                        let data_value = 0;\n\n                        switch (direction) {\n                            case '1':\n                                data_value = speed * 256 + speed;\n                                break;\n                            case '2':\n                                data_value = (256 - speed) * 256 + (256 - speed);\n                                break;\n                            case '3':\n                                data_value = speed * 256 + (256 - speed);\n                                break;\n                            case '4':\n                                data_value = (256 - speed) * 256 + speed;\n                                break;\n                            default:\n                                data_value = 0;\n                                break;\n                        }\n\n                        const data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.go_simple(%1, %2)'],\n                    },\n                },\n                \n                robotis_rla_lite_drive_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_drive_stop',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        let data_sendqueue = [\n                            [data_instruction, 5200, 1, 0],\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.stop(%1, %2)'],\n                    },\n                },\n                robotis_rla_lite_motion: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_up, '50007'],\n                                [Lang.Blocks.robotis_down, '50008'], //Lang.Blocks.robotis_robotis_common_green_color\n                            ],\n                            value: '50007',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_motion',\n                    },\n                    paramsKeyMap: {\n                        MotionNumber: 0,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        const data_instruction = INST_WRITE;\n                        const data_address = 66;\n                        const data_length = 2;\n                        let data_value = script.getField('MotionNumber', script);\n\n                        const data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            data_value > 50070 ? 2000 : 1000 \n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.run_motion(%1)'],\n                    },\n                },\n                robotis_rla_lite_wheel_rotate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_clockwise, '1'],\n                                [Lang.Blocks.robotis_counterclockwise, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_rla_lite_wheel_rotate',\n                    },\n                    paramsKeyMap: {\n                        WHEEL_SIDE: 0,\n                        WHEEL_SPEED: 1,\n                        WHEEL_DIRECTION: 2,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let wheelSide = script.getNumberValue('WHEEL_SIDE', script);\n                        let wheelSpeed = script.getNumberValue('WHEEL_SPEED', script);\n                        let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n\n                        let leftSpeed = 0;\n                        let rightSpeed = 0;\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        if (wheelSpeed < -100) {\n                            wheelSpeed = -100;\n                        } else if (wheelSpeed > 100) {\n                            wheelSpeed = 100;\n                        }\n                        if (wheelSide == 1) {\n                            wheelSpeed = wheelSpeed * (-1);\n                        }\n\n                        wheelSpeed = (wheelSpeed + 256) % 256;\n                        if (wheelDirection == '2') {\n                            wheelSpeed = (256 - wheelSpeed) % 256;\n                        }\n\n                        if (wheelSide == 1) {\n                            leftSpeed = wheelSpeed;\n                            rightSpeed = 127; // 속도제어 안함\n                        } else if (wheelSide == 0) {\n                            leftSpeed = 127; // 속도제어 안함\n                            rightSpeed = wheelSpeed;\n                        }\n\n                        data_value = leftSpeed + rightSpeed * 256;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            25 //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.go_seperate(%1, %2)'],\n                    },\n                },\n                robotis_rla_lite_wheel_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'robotis_rla_lite_wheel_stop',\n                    },\n                    paramsKeyMap: {\n                        WHEEL_SIDE: 0,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let wheelSide = script.getNumberValue('WHEEL_SIDE', script);\n\n                        let leftSpeed = 0;\n                        let rightSpeed = 0;\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        if (wheelSide == 1) {\n                            leftSpeed = 0;\n                            rightSpeed = 127; // 속도제어 안함\n                        } else if (wheelSide == 0) {\n                            leftSpeed = 127; // 속도제어 안함\n                            rightSpeed = 0;\n                        }\n\n                        data_value = leftSpeed + rightSpeed * 256;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            25 //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.stop_seperate(%1)'],\n                    },\n                },\n                robotis_rla_lite_go_distance: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '-1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['10'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_rla_lite_go_distance',\n                    },\n\n                    paramsKeyMap: {\n                        DISTANCE: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(entity, script) {\n                        let distance = script.getNumberValue('DISTANCE', script);\n                        let direction = script.getField('DIRECTION', script);\n\n                        if (distance > 1000) {\n                            distance = 1000;\n                        } else if (distance < -1000) {\n                            distance = -1000;\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 270;\n                        let data_length = 4;\n                        let data_value = Math.floor(10 * distance * direction);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        data_sendqueue.push([data_instruction, 66, 2, 50491]);\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 150 * Math.abs(distance) + 1200\n                            //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.go_distance(%1)'] },\n                },\n\n                robotis_rla_lite_turn_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveL_in_place, '1'],\n                                [Lang.Blocks.robotis_moveR_in_place, '-1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['90'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_rla_lite_turn_angle',\n                    },\n\n                    paramsKeyMap: {\n                        ANGLE: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(entity, script) {\n                        let angle = script.getNumberValue('ANGLE', script);\n                        let direction = script.getNumberValue('DIRECTION', script);\n\n                        angle *= direction;\n\n                        if (angle > 360) {\n                            angle = 360;\n                        } else if (angle < -360) {\n                            angle = -360;\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 270;\n                        let data_length = 4;\n                        let data_value = Math.floor(angle);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        data_sendqueue.push([data_instruction, 66, 2, 50492]);\n\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + Math.abs(angle) * 16 + 1500\n                            //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['RlaLite.turn_angle(%1)'] },\n                },\n\n                \n                robotis_rla_lite_follow_line: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_stage_1, '1'],\n                                [Lang.Blocks.robotis_stage_2, '2'],\n                                [Lang.Blocks.robotis_stage_3, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_rla_lite_follow_line',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let speed_level = script.getNumberValue('SPEED', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 5200;\n                        let data_length = 1;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, speed_level],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.follow_line(%1)'],\n                    },\n                },\n\n                robotis_rla_lite_stop_follow_line: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_rla_lite_stop_follow_line',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'robotis_rla_lite_move',\n                    isNotFor: ['RobotisRlaLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        let data_sendqueue = [\n                            [data_instruction, 5200, 1, 0],\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRlaLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['RlaLite.stop_follow_line()'],\n                    },\n                },\n\n//////////////////////////////////////////////////////////////////////////////////////////////////////////\n            };\n        }\n\n        requestLocalData() {\n            let packets = [];\n            while (this.robotisBuffer.length > 0) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n                let packet = null;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        packet = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        packet = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n\n                if (packet !== null && Array.isArray(packet)) {\n                    packets.push(...packet);\n                }\n            }\n            return packets;\n        }\n\n        handleLocalData(data) {\n            let stuffLength = 0;\n            //console.log(`length: ${data.length}`);\n            for (let i = 0; i < data.length; i++) {\n                //this.receiveBuffer.push(data[i]);\n                const dataIn = data[i];\n\n                switch (this.packetReceiveState) {\n                    case PACKET_STATE_IDLE:\n                        if (this.headerCount >= 2) {\n                            rxPacket.header[2] = dataIn;\n\n                            if (\n                                rxPacket.header[0] == 0xff &&\n                                rxPacket.header[1] == 0xff &&\n                                rxPacket.header[2] == 0xfd\n                            ) {\n                                this.headerCount = 0;\n                                this.packetReceiveState = PACKET_STATE_RESERVED;\n                            } else {\n                                rxPacket.header[0] = rxPacket.header[1];\n                                rxPacket.header[1] = rxPacket.header[2];\n                                rxPacket.header[2] = 0;\n                            }\n                        } else {\n                            rxPacket.header[this.headerCount] = dataIn;\n                            this.headerCount++;\n                        }\n                        break;\n\n                    case PACKET_STATE_RESERVED:\n                        if (dataIn == 0xfd) {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        } else {\n                            rxPacket.reserved = dataIn;\n                            this.packetReceiveState = PACKET_STATE_ID;\n                        }\n                        break;\n\n                    case PACKET_STATE_ID:\n                        rxPacket.id = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_L;\n                        break;\n\n                    case PACKET_STATE_LENGTH_L:\n                        rxPacket.packetLength = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_H;\n                        break;\n\n                    case PACKET_STATE_LENGTH_H:\n                        rxPacket.packetLength |= dataIn << 8;\n                        if (rxPacket.packetLength < 1000) {\n                            this.packetReceiveState = PACKET_STATE_DATA;\n                        } else {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        }\n                        rxPacket.index = 0;\n                        break;\n\n                    case PACKET_STATE_DATA:\n                        rxPacket.data[rxPacket.index] = dataIn;\n                        rxPacket.index++;\n\n                        if (rxPacket.index >= rxPacket.packetLength - 2) {\n                            this.packetReceiveState = PACKET_STATE_CRC_L;\n                        }\n                        break;\n\n                    case PACKET_STATE_CRC_L:\n                        rxPacket.crcReceived = dataIn;\n                        this.packetReceiveState = PACKET_STATE_CRC_H;\n                        break;\n\n                    case PACKET_STATE_CRC_H:\n                        rxPacket.crcReceived |= dataIn << 8;\n\n                        stuffLength = this.removeStuffing(rxPacket.data, rxPacket.packetLength);\n                        rxPacket.packetLength -= stuffLength;\n\n                        rxPacket.cmd = rxPacket.data[0];\n                        rxPacket.error = rxPacket.data[1];\n\n                        if (rxPacket.cmd == INST_STATUS) {\n                            //console.log(`rx length: ${rxPacket.packetLength}`);\n                            if (rxPacket.packetLength >= 147) {\n                                let tempValue = 0;\n                                for (let i = 0; i < addrMap.length; i++) {\n                                    switch (addrMap[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n\n                                const dxlPositionStartAddr =\n                                    addrMap[addrMap.length - 1][0] + addrMap[addrMap.length - 1][1];\n\n                                // DXL Position\n                                for (let i = 0; i < 20; i++) {\n                                    const currentId =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i];\n                                    const currentPos =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 1] +\n                                        (rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 2] << 8);\n                                    if (currentId != 0xff && currentPos != 0xffff) {\n                                        this.dxlPositions[currentId] = currentPos;\n                                    }\n                                }\n\n                                const lineCategoryStartAddr = dxlPositionStartAddr + 3 * 20;\n                                // line category\n                                this.dataBuffer[5201] = rxPacket.data[2 + lineCategoryStartAddr];\n\n                                const sensorStartAddr = lineCategoryStartAddr + 1;\n\n                                // 온습도+조도+동작감지센서값\n                                this.pirPir[0] = rxPacket.data[2 + sensorStartAddr];\n                                this.pirTemperature[0] = rxPacket.data[2 + sensorStartAddr + 1];\n                                this.pirHumidity[0] = rxPacket.data[2 + sensorStartAddr + 2];\n                                this.pirBrightness[0] = rxPacket.data[2 + sensorStartAddr + 3];\n\n                                // 거리+버튼+조도센서값\n                                this.distanceDistance[0] =\n                                    rxPacket.data[2 + sensorStartAddr + 4] +\n                                    (rxPacket.data[2 + sensorStartAddr + 5] << 8);\n                                this.distanceButton[0] = rxPacket.data[2 + sensorStartAddr + 6];\n                                this.distanceBrightness[0] = rxPacket.data[2 + sensorStartAddr + 7];\n\n                                for (let i = 0; i < addrMap2.length; i++) {\n                                    switch (addrMap2[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap2[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n                            }\n                        }\n\n                        this.packetReceiveState = PACKET_STATE_IDLE;\n                        break;\n\n                    default:\n                    // code block\n                }\n            }\n        }\n\n        requestInitialData() {\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 20]);\n            this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기\n            this.robotisBuffer.push([INST_WRITE, 20, 1, 0]); // bypass port를 BLE로 설정\n            this.robotisBuffer.push([INST_WRITE, 23, 1, 1]); // auto report 기능 켜기\n            this.robotisBuffer.push([INST_WRITE, 4250, 1, 1]); // ai_camera 텍스트 지우기\n            this.robotisBuffer.push([INST_WRITE, 722, 1, 0]); // dxl 토크 끄기\n            //this.robotisBuffer.push([INST_WRITE, 63, 1, 1]); // 부저음 시간 설정\n            //this.robotisBuffer.push([INST_WRITE, 60, 1, 70]); // 부저음 발생\n            this.robotisBuffer.push([INST_WRITE, 113, 2, 1040]); // \"띵\" 효과음 발생\n            /*\n            //const ping = [0xff, 0xff, 0xfd, 0x00, 0xc8, 0x03, 0x00, 0x01, 0x3b, 0xfa];\n            // run entry mode\n            const packet = [\n                0xff, 0xff, 0xfd, 0x00, 0xc8, 0x07, 0x00, 0x03, 0x15, 0x00, 0x14, 0x00, 0xc1, 0xb3,\n            ];\n            return packet;\n            */\n        }\n\n        async initialHandshake() {\n            const status = true;\n            let sendBuffer = null;\n            this.requestInitialData();\n            while (this.robotisBuffer.length) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        sendBuffer = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        sendBuffer = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n                Entry.hwLite.serial.sendAsciiAsBuffer(sendBuffer);\n                if (instruction == INST_WRITE && address == 2100 && length == 1 && value == 1) {\n                    this.robotisBuffer = [];\n                }\n            }\n            return status;\n        }\n    })();\n})();\n\nmodule.exports = Entry.RobotisRlaLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js",
    "content": "'use strict';\n\nconst INST_NONE = 0;\nconst INST_READ = 2;\nconst INST_WRITE = 3;\nconst INST_DXL_SYNCWRITE = 4;\nconst INST_DXL_REGWRITE = 5;\nconst INST_DXL_ACTION = 6;\nconst INST_BYPASS_READ = 0xa2;\nconst INST_BYPASS_WRITE = 0xa3;\n\nconst INST_STATUS = 0x55;\n\nconst PACKET_STATE_IDLE = 0;\nconst PACKET_STATE_RESERVED = 1;\nconst PACKET_STATE_ID = 2;\nconst PACKET_STATE_LENGTH_L = 3;\nconst PACKET_STATE_LENGTH_H = 4;\nconst PACKET_STATE_DATA = 5;\nconst PACKET_STATE_CRC_L = 6;\nconst PACKET_STATE_CRC_H = 7;\n\nconst DEFAULT_DELAY = 50;\n\nconst rxPacket = {\n    header: [0, 0, 0],\n    reserved: 0,\n    id: 0,\n    cmd: 0,\n    error: 0,\n    type: 0,\n    index: 0,\n    packetLength: 0,\n    paramLength: 0,\n    crc: 0,\n    crcReceived: 0,\n    checksum: 0,\n    checksumReceived: 0,\n    data: [],\n};\n\nconst addrMap = [\n    [0, 4, 302],\n    [4, 1, 42],\n    [5, 1, 44],\n    [6, 1, 45],\n    [7, 1, 47],\n    [8, 1, 50],\n    [9, 1, 51],\n    [10, 1, 52],\n    [11, 1, 68],\n    [12, 2, 70],\n    [14, 2, 72],\n    [16, 2, 74],\n    [18, 2, 76],\n    [20, 2, 78],\n    [22, 2, 80],\n    [24, 2, 82],\n    [26, 2, 84],\n    [28, 1, 86],\n    [29, 1, 87],\n    [30, 2, 88],\n    [32, 2, 90],\n    [34, 1, 112],\n    [35, 1, 118],\n    [36, 1, 119],\n    [37, 1, 122],\n    [38, 1, 123],\n    [39, 1, 124],\n    [40, 1, 125],\n    [41, 1, 160],\n    [42, 1, 220],\n    [43, 2, 360],\n    [45, 2, 362],\n    [47, 2, 364],\n    [49, 2, 366],\n    [51, 2, 368],\n    [53, 2, 370],\n    [55, 1, 372],\n    [56, 1, 373],\n    [57, 1, 374],\n    [58, 1, 375],\n    [59, 1, 376],\n    [60, 1, 377],\n    [61, 1, 378],\n    [62, 1, 379],\n    [63, 1, 380],\n    [64, 1, 381],\n    [65, 1, 382],\n    [66, 1, 383],\n    [67, 1, 500],\n    [68, 1, 501],\n    [69, 8, 502],\n    [77, 1, 700],\n    [78, 1, 810],\n    [79, 1, 2134],\n    [80, 1, 5015],\n    [81, 1, 5030],\n    [82, 1, 5031],\n    [83, 1, 5040],\n];\n\nconst addrMap2 = [\n    [153, 1, 4000],\n    [154, 2, 4003],\n    [156, 1, 4005],\n    [157, 1, 4006],\n    [158, 2, 4009],\n    [160, 2, 4011],\n    [162, 2, 4013],\n    [164, 2, 4015],\n    [166, 2, 4017],\n    [168, 2, 4019],\n    [170, 2, 4021],\n    [172, 2, 4023],\n    [174, 2, 4025],\n    [176, 2, 4027],\n    [178, 1, 4031],\n    [179, 1, 4032],\n    [180, 1, 4033],\n    [181, 2, 4036],\n    [183, 2, 4038],\n    [185, 2, 4040],\n    [187, 2, 4042],\n    [189, 2, 4044],\n    [191, 2, 4046],\n    [193, 2, 4048],\n    [195, 2, 4050],\n];\n\nconst crcTable = [\n    0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039,\n    0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,\n    0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9,\n    0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,\n    0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099,\n    0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,\n    0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea,\n    0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,\n    0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179,\n    0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,\n    0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309,\n    0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,\n    0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359,\n    0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,\n    0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9,\n    0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,\n    0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9,\n    0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,\n    0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, 0x0246, 0x024c, 0x8249,\n    0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,\n    0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219,\n    0x0208, 0x820d, 0x8207, 0x0202,\n];\n\nconst rb100_last_valid_value = [];\nlet bg_color = 0;\nlet beat_per_minute = 75;\nlet camera_id_for_use = 0;\n\n(function () {\n    Entry.RobotisRobotaiLite = new (class RobotisRobotaiLite {\n        constructor() {\n            this.id = '070B01';\n            this.url = 'http://www.robotis.com';\n            this.imageName = 'robotis_robotai_lite.png';\n            this.name = 'RobotisRobotaiLite';\n            this.blockMenuBlocks = [\n                // 주행 제어\n                'robotis_robotai_lite_drive_simple',\n                'robotis_robotai_lite_drive_advanced',\n                'robotis_robotai_lite_drive_seperate',\n                'robotis_robotai_lite_drive_angle',\n                'robotis_robotai_lite_go_distance',\n                'robotis_robotai_lite_turn_angle',\n                'robotis_robotai_lite_follow_line',\n                'robotis_robotai_lite_stop_at_cross',\n                'robotis_robotai_lite_turn_at_line',\n                'robotis_robotai_lite_drive_stop',\n\n                'robotis_robotai_lite_securitybot_init',\n                'robotis_robotai_lite_securitybot_hi',\n                'robotis_robotai_lite_securitybot_alert',\n\n                'robotis_robotai_lite_petbot_happy',\n                'robotis_robotai_lite_petbot_sad',\n\n                'robotis_robotai_lite_farmbot_init',\n                'robotis_robotai_lite_farmbot_seek',\n                'robotis_robotai_lite_farmbot_plant_type',\n                'robotis_robotai_lite_farmbot_harvest_or_not_and_go',\n\n                // 값 블록\n                'robotis_robotai_lite_cm_ir_value',\n                'robotis_robotai_lite_detectFrontObj',\n                'robotis_robotai_lite_cm_ir_compare',\n                'robotis_robotai_lite_cm_btn_value',\n                'robotis_robotai_lite_cm_joystick_value',\n                'robotis_robotai_lite_mic',\n                'robotis_robotai_lite_detectSound_compare',\n                'robotis_robotai_lite_imu',\n                'robotis_robotai_lite_roll_pitch',\n                'robotis_robotai_lite_environment_value',\n                'robotis_robotai_lite_line_cross_compare',\n                //'robotis_robotai_lite_distance_compare',\n                'robotis_robotai_lite_environment_compare',\n                'robotis_robotai_lite_dxl_value',\n\n                // 소리\n                'robotis_robotai_lite_scale_simple',\n                'robotis_robotai_lite_scale_advanced',\n                'robotis_robotai_lite_rest_simple',\n                'robotis_robotai_lite_rest_advanced',\n                'robotis_robotai_lite_beat_per_minute',\n                'robotis_robotai_lite_Hello',\n                'robotis_robotai_lite_effectSound',\n                'robotis_robotai_lite_record',\n                'robotis_robotai_lite_playRecord',\n\n                // LCD 제어\n                'robotis_robotai_lite_screen',\n                'robotis_robotai_lite_anim_screen',\n                'robotis_robotai_lite_icon_screen_food_plant',\n                'robotis_robotai_lite_icon_screen_animal_human',\n                'robotis_robotai_lite_icon_screen_object_tool',\n                'robotis_robotai_lite_icon_screen_vehicle_number',\n                'robotis_robotai_lite_icon_screen_game_character',\n                'robotis_robotai_lite_text_screen',\n                'robotis_robotai_lite_text_screen_redraw',\n                'robotis_robotai_lite_pixel',\n                'robotis_robotai_lite_LCDColor',\n                'robotis_robotai_lite_LCD_Flash',\n                'robotis_robotai_lite_LCDBright',\n\n                // LED 제어\n                'robotis_robotai_lite_cm_led',\n                'robotis_robotai_lite_cm_led_pattern',\n\n                // 다이나믹셀 제어\n                'robotis_robotai_lite_dxl_set_mode',\n                'robotis_robotai_lite_dxl_each_control',\n                'robotis_robotai_lite_dxl_set_position',\n                'robotis_robotai_lite_dxl_set_rotate',\n                'robotis_robotai_lite_dxl_set_multiturn_round',\n\n                // 인공지능 카메라 값 블록\n                'robotis_robotai_lite_ai_camera_connection_status',\n                'robotis_robotai_lite_ai_camera_if_detected',\n\n                'robotis_robotai_lite_ai_camera_block_value_closest_to_center',\n                'robotis_robotai_lite_ai_camera_arrow_value_closest_to_center',\n                'robotis_robotai_lite_ai_camera_number_of_learned_id',\n                'robotis_robotai_lite_ai_camera_block_value_of_id',\n                'robotis_robotai_lite_ai_camera_arrow_value_of_id',\n\n                'robotis_robotai_lite_ai_camera_if_learned_id',\n                'robotis_robotai_lite_ai_camera_if_detected_id_type',\n\n                // AI Camera 제어\n                'robotis_robotai_lite_ai_camera_set_mode',\n                'robotis_robotai_lite_ai_camera_print_custom_text',\n                'robotis_robotai_lite_ai_camera_clear_custom_text',\n            ];\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                connectionType: 'bytestream',\n                bufferSize: 128,\n                constantServing: true,\n            };\n            this.duration = 15;\n            this.setZero();\n\n            this.timeouts = [];\n\n            this.robotisBuffer = []; // buffer to transmit to H/W\n            this.receiveBuffer = []; // buffer to receive from H/W\n            this.dataBuffer = []; // saved control table value buffer\n\n            this.packetReceiveState = 0;\n            this.headerCount = 0;\n\n            this.dxlPositions = [];\n\n            this.pirPir = [];\n            this.pirTemperature = [];\n            this.pirHumidity = [];\n            this.pirBrightness = [];\n            this.distanceDistance = [];\n            this.distanceButton = [];\n            this.distanceBrightness = [];\n        }\n\n        setZero() {\n            this.timeouts = [];\n            this.__removeAllTimeouts();\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 2100, 1, 1]); // 값 1은 꼭두 얼굴이 뜨도록 (펌웨어는 v1.15.4부터)\n            camera_id_for_use = 0;\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        __removeTimeout(id) {\n            clearTimeout(id);\n            const idx = this.timeouts.indexOf(id);\n            if (idx >= 0) {\n                this.timeouts.splice(idx, 1);\n            }\n        }\n\n        __removeAllTimeouts() {\n            const timeouts = this.timeouts;\n            for (const i in timeouts) {\n                clearTimeout(timeouts[i]);\n            }\n            this.timeouts = [];\n        }\n\n        getMonitorPort() {\n            return { ...this.sensory, ...this.motoring, ...this.lineTracer };\n        }\n\n        writePacket(id, address, length, value) {\n            if (length > 256) {\n                console.log(`######### invalid length: ${length}`);\n                return null;\n            }\n            console.log('######### writePacket');\n            const packet = [];\n            let i = 0;\n            packet.push(0xff);\n            packet.push(0xff);\n            packet.push(0xfd);\n            packet.push(0x00);\n            packet.push(id);\n            packet.push(length + 5);\n            packet.push(0x00);\n            packet.push(INST_WRITE);\n            packet.push(this.getLowByte(address));\n            packet.push(this.getHighByte(address));\n            switch (length) {\n                case 1:\n                    packet.push(this.getLowByte(value));\n                    break;\n                case 2:\n                    packet.push(this.getLowByte(value));\n                    packet.push(this.getHighByte(value));\n                    break;\n                case 4:\n                    packet.push(this.getLowByte(this.getLowWord(value)));\n                    packet.push(this.getHighByte(this.getLowWord(value)));\n                    packet.push(this.getLowByte(this.getHighWord(value)));\n                    packet.push(this.getHighByte(this.getHighWord(value)));\n                    break;\n                default:\n                    for (i = 0; i < length; i++) {\n                        if (typeof value[i] == 'number') {\n                            packet.push(value[i]);\n                        } else if (typeof value[i] == 'string') {\n                            packet.push(value[i].charCodeAt(0));\n                        }\n                    }\n                    break;\n            }\n            const crc = this.updateCRC(0, packet, packet.length);\n            packet.push(this.getLowByte(crc));\n            packet.push(this.getHighByte(crc));\n            return packet;\n        }\n\n        makeWord(a, b) {\n            return (a & 0xff) | ((b & 0xff) << 8);\n        }\n\n        getLowByte(a) {\n            return a & 0xff;\n        }\n\n        getHighByte(a) {\n            return (a >> 8) & 0xff;\n        }\n\n        getLowWord(a) {\n            return a & 0xffff;\n        }\n\n        getHighWord(a) {\n            return (a >> 16) & 0xffff;\n        }\n\n        updateCRC(crcAccum, dataBlkPtr, dataBlkSize) {\n            let i = 0;\n            let j = 0;\n            let crc = crcAccum;\n\n            for (j = 0; j < dataBlkSize; j++) {\n                i = ((crc >> 8) ^ dataBlkPtr[j]) & 0xff;\n                crc = (crc << 8) ^ crcTable[i];\n            }\n\n            return crc;\n        }\n\n        removeStuffing(buffer, length) {\n            let i = 0;\n            let stuffLength = 0;\n            let index = 0;\n\n            for (i = 0; i < length; i++) {\n                if (i >= 2) {\n                    if (buffer[i - 2] == 0xff && buffer[i - 1] == 0xff && buffer[i] == 0xfd) {\n                        i++;\n                        stuffLength++;\n                    }\n                }\n                buffer[index++] = buffer[i];\n            }\n\n            return stuffLength;\n        }\n\n        postCallReturn(script, data, ms) {\n            /*\n            if (data == null) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            } else if (data.length == 0) {\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n            */\n            if (!script.isStart) {\n                script.isStart = true;\n                script.timeFlag = 1;\n                for (let i = 0; i < data.length; i++) {\n                    this.robotisBuffer.push(data[i]);\n                }\n                //delay ms\n                setTimeout(() => {\n                    script.timeFlag = 0;\n                }, ms);\n                return script;\n            } else if (script.timeFlag) {\n                return script;\n            } else {\n                delete script.isStart;\n                delete script.timeFlag;\n                Entry.engine.isContinue = false;\n                return script.callReturn();\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        // 주행 제어\n                        robotis_robotai_lite_drive_simple: '속도 %1 (으)로 %2 하기 %3',\n                        robotis_robotai_lite_drive_advanced:\n                            '왼쪽바퀴 %1 속도로 %2 하기, 오른쪽바퀴 %3 속도로 %4 하기 %5',\n                        robotis_robotai_lite_drive_seperate:\n                            '%1 바퀴 %2 속도로 %3 으로 회전하기 %4',\n                        robotis_robotai_lite_drive_angle: '%1 바퀴 %2 도만큼 %3 으로 회전하기 %4',\n                        robotis_robotai_lite_go_distance: '%1 cm %2 하기 %3',\n                        robotis_robotai_lite_turn_angle: '%1 도 %2 하기%3',\n                        robotis_robotai_lite_follow_line: '%1 속도로 라인 따라가기 %2',\n                        robotis_robotai_lite_stop_at_cross: '교차로 %1 에서 멈추기 %2',\n                        robotis_robotai_lite_turn_at_line: '교차로에서 %1 하고 멈추기 %2',\n                        robotis_robotai_lite_drive_stop: '정지하기 %1',\n\n                        robotis_robotai_lite_securitybot_init: '보안 로봇 초기화 %1',\n                        robotis_robotai_lite_securitybot_hi: '보안 로봇 긍정적 행동하기 %1',\n                        robotis_robotai_lite_securitybot_alert: '보안 로봇 부정적 행동하기 %1',\n\n                        robotis_robotai_lite_petbot_happy: '반려 로봇 행복한 행동하기 %1',\n                        robotis_robotai_lite_petbot_sad: '반려 로봇 화난 행동하기 %1',\n\n                        robotis_robotai_lite_farmbot_init: '스마트팜 로봇 초기화 %1',\n                        robotis_robotai_lite_farmbot_seek: '농작물 찾기 %1',\n                        robotis_robotai_lite_farmbot_plant_type: '%1 농작물이면',\n                        robotis_robotai_lite_farmbot_harvest_or_not_and_go: '농작물 %1 돌아가기 %2',\n\n                        // 값 블록\n                        robotis_robotai_lite_cm_ir_value: '%1 적외선센서 값',\n                        robotis_robotai_lite_cm_ir_compare: '%1 적외선센서 값이 %2 보다 %3',\n                        robotis_robotai_lite_detectFrontObj: '적외선센서의 %1에 물체가 있으면',\n                        robotis_robotai_lite_cm_btn_value: '제어기의 %1 버튼을 클릭했을때',\n                        robotis_robotai_lite_cm_joystick_value:\n                            '제어기의 노랑 조이스틱 위치가 %1 이면',\n                        robotis_robotai_lite_mic: '소리의 크기(dB)',\n                        robotis_robotai_lite_detectSound_compare: '소리가 제어기의 %1에서 들리면',\n                        robotis_robotai_lite_imu: '%1축의 %2 값',\n                        robotis_robotai_lite_roll_pitch: '제어기의 %1 값',\n                        robotis_robotai_lite_line_cross_compare: '교차로 모양이 %1이면',\n                        robotis_robotai_lite_environment_value: '%1 값',\n                        robotis_robotai_lite_environment_compare: '%1 값이 %2보다 %3',\n                        robotis_robotai_lite_dxl_value: '%1의 각도값',\n\n                        // 소리\n                        robotis_robotai_lite_scale_simple: '옥타브%1 로 %2 음을 %3로 연주하기 %4',\n                        robotis_robotai_lite_scale_advanced:\n                            '옥타브%1 로 %2 음을 %3박자 연주하기 %4',\n                        robotis_robotai_lite_rest_simple: '%1 %2',\n                        robotis_robotai_lite_rest_advanced: '쉼표 %1 박자 %2',\n                        robotis_robotai_lite_beat_per_minute: '연주 빠르기를 %1 (으)로 정하기 %2',\n                        robotis_robotai_lite_Hello: '로봇 %1 말하기 %2',\n                        robotis_robotai_lite_effectSound: '효과음 %1 재생하기 %2',\n                        robotis_robotai_lite_record: '소리 %1번에 녹음하기 %2',\n                        robotis_robotai_lite_playRecord: '소리 %1번을 재생하기 %2',\n\n                        // LCD 제어\n                        robotis_robotai_lite_screen: '화면을 %1 %2 (으)로 정하기 %3',\n                        robotis_robotai_lite_anim_screen:\n                            '화면 애니메이션을 %1 %2 (으)로 정하기 %3',\n                        robotis_robotai_lite_icon_screen_food_plant:\n                            '화면에 [음식/식물]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_robotai_lite_icon_screen_animal_human:\n                            '화면에 [동물/사람]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_robotai_lite_icon_screen_object_tool:\n                            '화면에 [물건/도구]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_robotai_lite_icon_screen_vehicle_number:\n                            '화면에 [탈것/숫자]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_robotai_lite_icon_screen_game_character:\n                            '화면에 [게임/캐릭터]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5',\n                        robotis_robotai_lite_text_screen:\n                            '화면에 %1를 (%2, %3)위치에 %4 로 %5으로 표시 %6',\n                        robotis_robotai_lite_pixel: '화면 (%1, %2)위치에 %3 색 점 표시 %4',\n                        robotis_robotai_lite_text_screen_redraw:\n                            '화면에 %1를 (%2, %3)위치에 %4으로 새로 표시 %5',\n                        robotis_robotai_lite_LCDColor: '화면 색상을 %1 (으)로 정하기 %2',\n                        robotis_robotai_lite_LCD_Flash:\n                            '화면을 %1과 %2으로 %3초 간격으로 깜박이기 %4',\n                        robotis_robotai_lite_LCDBright: '화면 밝기를 %1 (으)로 정하기 %2',\n\n                        // LED 제어\n                        robotis_robotai_lite_cm_led: '로봇 %1 LED %2 %3',\n                        robotis_robotai_lite_cm_led_pattern: 'LED %1 %2로 깜박이기 %3',\n\n                        // DXL 제어\n                        robotis_robotai_lite_dxl_set_mode: '%1 모터 %2 모드로 설정 %3',\n                        robotis_robotai_lite_dxl_each_control:\n                            '%1 모터 %2°로 %3 초 동안 움직이기 %4',\n                        robotis_robotai_lite_dxl_set_position:\n                            '%1 모터 %2 속도로 %3° 위치로 회전 %4',\n                        robotis_robotai_lite_dxl_set_rotate: '%1 모터 %2 속도로 %3 으로 %4 %5',\n                        robotis_robotai_lite_dxl_set_multiturn_round:\n                            '%1 모터 %2 속도로 %3 바퀴 %4으로 회전 %5',\n\n                        // ai_camera 값 블록\n                        robotis_robotai_lite_ai_camera_connection_status:\n                            '인공지능 카메라가 %1이면',\n                        robotis_robotai_lite_ai_camera_if_detected:\n                            '인공지능 카메라에 %1 이/가 표시되면',\n\n                        robotis_robotai_lite_ai_camera_block_value_closest_to_center:\n                            '인공지능 카메라가 인식한 %1의 %2',\n                        robotis_robotai_lite_ai_camera_arrow_value_closest_to_center:\n                            '인공지능 카메라가 인식한 화살표의 %1',\n                        robotis_robotai_lite_ai_camera_number_of_learned_id:\n                            '인공지능 카메라가 학습한 클래스의 갯수',\n                        robotis_robotai_lite_ai_camera_block_value_of_id:\n                            '인공지능 카메라가 감지한 클래스가 %1인 %2의 %3',\n                        robotis_robotai_lite_ai_camera_arrow_value_of_id:\n                            '인공지능 카메라가 감지한 클래스가 %1인 화살표의 %2',\n\n                        robotis_robotai_lite_ai_camera_if_learned_id:\n                            '인공지능 카메라가 클래스가 %1인 데이터를 학습하였으면',\n                        robotis_robotai_lite_ai_camera_if_detected_id_type:\n                            '인공지능 카메라가 클래스가 %1인 %2데이터를 인식하였으면',\n\n                        // 인공지능 카메라 제어\n                        robotis_robotai_lite_ai_camera_set_mode:\n                            '인공지능 카메라의 작동 방식을 %1(으)로 설정 %2',\n                        robotis_robotai_lite_ai_camera_print_custom_text:\n                            '인공지능 카메라의 화면 위치 (%1,%2)에 %3를 보여주기%4',\n                        robotis_robotai_lite_ai_camera_clear_custom_text:\n                            '인공지능 카메라의 화면의 글 지우기 %1',\n                    },\n                    Helper: {\n                        // 주행 제어\n                        robotis_robotai_lite_drive_simple:\n                            '로봇아이를 지정한 속도와 방향으로 주행\\n속도범위: -100 ~ 100\\n속도단위: %',\n                        robotis_robotai_lite_drive_advanced:\n                            '로봇아이의 좌,우 바퀴를 각각 지정한 속도와 방향으로 회전\\n속도범위: -100 ~ 100\\n속도단위: %',\n                        robotis_robotai_lite_drive_seperate:\n                            '로봇아이의 지정한 바퀴를 지정한 속도와 방향으로 회전\\n속도범위: -100 ~ 100\\n속도단위: %',\n                        robotis_robotai_lite_drive_angle:\n                            '로봇아이의 지정한 바퀴를 지정한 방향과 지정한 각도만큼 회전\\n각도범위: -5760 ~ 5760\\n각도단위: 도',\n                        robotis_robotai_lite_go_distance:\n                            '지정거리만큼 앞 또는 뒤로 이동\\n거리범위: -1000 ~ 1000\\n거리단위: mm',\n                        robotis_robotai_lite_turn_angle:\n                            '지정한 각도와 방향으로 제자리회전\\n각도범위: -360 ~ 360\\n각도단위: 도',\n                        robotis_robotai_lite_follow_line: '지정한 수준의 속도로 라인 따라가기 시작',\n                        robotis_robotai_lite_stop_at_cross: '지정한 교차로에서 멈추기',\n                        robotis_robotai_lite_turn_at_line: '교차로에서 지정한 회전을 하고 멈추기',\n                        robotis_robotai_lite_drive_stop: '로봇아이 정지하기',\n\n                        robotis_robotai_lite_securitybot_init:\n                            '보안 로봇을 초기화합니다. 두 모터를 관절모드로 설정하고 카메라를 얼굴 인식모드로 설정합니다.',\n                        robotis_robotai_lite_securitybot_hi:\n                            '보안 로봇이 \"사용자를 확인하였습니다.\" 문구를 화면에 표시하고 팔을 위아래로 흔듭니다.',\n                        robotis_robotai_lite_securitybot_alert:\n                            '보안 로봇이 \"사용자가 아닙니다.\" 문구를 화면에 표시하고 몸을 좌우로 흔듭니다.',\n\n                        robotis_robotai_lite_petbot_happy:\n                            '반려 로봇이 웃는 표정을 하고 \"즐거워요\" 라고 말을 하면서 제자리에서 한바퀴 회전합니다.',\n                        robotis_robotai_lite_petbot_sad:\n                            '반려 로봇이 화난 표정을 하고 \"무서워요\" 라고 말을 하면서 뒤로 5cm 후진합니다.',\n\n                        robotis_robotai_lite_farmbot_init:\n                            '스마트팜 로봇을 초기화 합니다. 1번 모터를 시작위치로 이동시키고 카메라를 색상인식모드로 설정합니다.',\n                        robotis_robotai_lite_farmbot_seek: '농작물을 발견하면 가까이로 이동합니다.',\n                        robotis_robotai_lite_farmbot_plant_type: '농작물의 유형을 판단합니다.',\n                        robotis_robotai_lite_farmbot_harvest_or_not_and_go:\n                            '농작물을 수확하거나 수확하지 않습니다. 그 이후 우측으로 회전합니다.',\n\n                        // 값 블록\n                        robotis_robotai_lite_cm_ir_value: '지정한 번호의 IR 센서 값(범위: 0 ~ 200)',\n                        robotis_robotai_lite_cm_ir_compare:\n                            \"지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_detectFrontObj:\n                            \"지정한 방향의 적외선센서에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_cm_btn_value:\n                            \"지정한 버튼이 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_cm_joystick_value:\n                            \"조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_mic:\n                            '마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.',\n                        robotis_robotai_lite_detectSound_compare:\n                            \"소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_imu:\n                            '지정한 축의 지정한 가속도센서/자이로센서의 값\\n범위: -100 ~ 100',\n                        robotis_robotai_lite_roll_pitch:\n                            'roll/pitch 값\\nroll: -180° ~ 180°, pitch: -90° ~ 90°',\n                        robotis_robotai_lite_environment_value:\n                            '지정한 센서값\\n움직임센서: 0(움직임 없음) / 1(움직임 있음)\\n밝기범위: 0 ~ 100%\\n온도범위: -25°C ~ 85°C',\n                        robotis_robotai_lite_environment_compare:\n                            \"지정한 센서값의 지정한 수식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_line_cross_compare:\n                            \"지정한 교차로 모양이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_dxl_value:\n                            '지정한 모터의 위치 각도값\\n범위: -180° ~ 180°',\n\n                        // 소리\n                        robotis_robotai_lite_scale_simple: '지정한 옥타브, 음계, 음표로 연주하기',\n                        robotis_robotai_lite_scale_advanced: '지정한 옥타브, 음계, 박자로 연주하기',\n                        robotis_robotai_lite_rest_simple: '지정한 쉼표 쉬기',\n                        robotis_robotai_lite_rest_advanced: '지정한 박자 쉬기',\n                        robotis_robotai_lite_beat_per_minute:\n                            '연주 빠르기를 지정하기 (BPM)\\n범위: 10 ~ 600',\n                        robotis_robotai_lite_Hello: '로봇이 지정한 말소리를 재생하기',\n                        robotis_robotai_lite_effectSound: '로봇이 지정한 효과음을 재생하기',\n                        robotis_robotai_lite_record: '지정번호 보관함에 녹음하여 저장하기',\n                        robotis_robotai_lite_playRecord: '지정번호 보관함의 녹음음성을 재생하기',\n\n                        // LCD 제어\n                        robotis_robotai_lite_screen: '제어기 화면배경의 캐릭터와 표정을 설정',\n                        robotis_robotai_lite_anim_screen:\n                            '제어기 화면 애니메이션의 캐릭터와 표정을 설정',\n                        robotis_robotai_lite_icon_screen_food_plant:\n                            '화면에 [음식/식물]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_robotai_lite_icon_screen_animal_human:\n                            '화면에 [동물/사람]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_robotai_lite_icon_screen_object_tool:\n                            '화면에 [물건/도구]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_robotai_lite_icon_screen_vehicle_number:\n                            '화면에 [탈것/숫자]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_robotai_lite_icon_screen_game_character:\n                            '화면에 [게임/캐릭터]중 특정 아이콘을 표시할 위치와 크기를 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_robotai_lite_text_screen:\n                            '화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n                        robotis_robotai_lite_text_screen_redraw:\n                            '화면에 지정한 문구를 새롭게(문구의 배경 지움) 표시할 위치와 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120\\n크기: 0 ~ 200',\n                        robotis_robotai_lite_pixel:\n                            '화면에 표시할 점의 위치와 색상을 설정\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n                        robotis_robotai_lite_LCDBright: '화면 밝기를 설정\\n밝기범위: 1% ~ 100%',\n                        robotis_robotai_lite_LCDColor: '화면 색상을 설정',\n                        robotis_robotai_lite_LCD_Flash: '화면이 깜박이는 2가지 색상과 간격을 지정',\n\n                        // LED 제어\n                        robotis_robotai_lite_cm_led: '제어기의 지정한 LED를 켜거나 끄기',\n                        robotis_robotai_lite_cm_led_pattern: '제어기의 LED의 깜박임 패턴 설정',\n\n                        // DXL 제어\n                        robotis_robotai_lite_dxl_set_mode: '지정한 ID의 모터의 동작모드를 설정',\n                        robotis_robotai_lite_dxl_each_control:\n                            '지정한 ID의 모터가 지정한 각도로 지정한 시간(초)동안 움직이도록 설정',\n                        robotis_robotai_lite_dxl_set_position:\n                            '지정한 ID의 모터가 지정한 속도로 지정한 각도로 움직이도록 설정',\n                        robotis_robotai_lite_dxl_set_rotate:\n                            '지정한 ID의 모터의 회전 속도와 방향을 설정',\n                        robotis_robotai_lite_dxl_set_multiturn_round:\n                            '지정한 ID의 모터가 지정한 속도와 방향으로 지정한 바퀴만큼 회전',\n\n                        // AI Camera 값 블록\n                        robotis_robotai_lite_ai_camera_connection_status:\n                            \"인공지능 카메라가 연결된 상태이면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_ai_camera_if_detected:\n                            \"인공지능 카메라의 LCD화면에 선택한 기호(사각형/화살표)가 표시되면 '참', 아니면 '거짓'으로 판단합니다.\",\n\n                        robotis_robotai_lite_ai_camera_block_value_closest_to_center:\n                            '인공지능 카메라 화면 중앙과 가장 가까운 사각형의 X좌표/Y좌표/너비/높이/클래스',\n                        robotis_robotai_lite_ai_camera_arrow_value_closest_to_center:\n                            '인공지능 카메라 화면 중앙과 가장 가까운 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표/클래스',\n                        robotis_robotai_lite_ai_camera_number_of_learned_id:\n                            '인공지능 카메라가 학습한 번호의 갯수',\n                        robotis_robotai_lite_ai_camera_block_value_of_id:\n                            '인공지능 카메라가 감지한 사각형중 지정한 번호의 사각형의 X좌표/Y좌표/너비/높이',\n                        robotis_robotai_lite_ai_camera_arrow_value_of_id:\n                            '인공지능 카메라가 감지한 화살표중 지정한 번호의 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표',\n\n                        robotis_robotai_lite_ai_camera_if_learned_id:\n                            \"인공지능 카메라가 지정한 번호인 데이터를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.\",\n                        robotis_robotai_lite_ai_camera_if_detected_id_type:\n                            \"인공지능 카메라가 지정한 번호인 지정한 데이터(사각형/화살표)를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.\",\n\n                        // 인공지능 카메라 제어\n                        robotis_robotai_lite_ai_camera_set_mode: '인공지능 카메라의 모드를 설정',\n                        robotis_robotai_lite_ai_camera_print_custom_text:\n                            '인공지능 카메라 화면의 지정한 위치에 지정한 문구 출력\\nX좌표: -160 ~ 160\\nY좌표: -120 ~ 120',\n                        robotis_robotai_lite_ai_camera_clear_custom_text:\n                            '인공지능 카메라 화면에 표시한 모든 문구 지우기',\n                    },\n                    Blocks: {\n                        robotis_red: '빨강',\n                        robotis_orange: '주황',\n                        robotis_yellow: '노랑',\n                        robotis_green: '초록',\n                        robotis_blue: '파랑',\n                        robotis_brown: '갈색',\n                        robotis_black: '검정',\n                        robotis_white: '흰색',\n                        robotis_left: '왼쪽',\n                        robotis_center: '중앙',\n                        robotis_right: '오른쪽',\n                        robotis_both: '양쪽',\n                        robotis_rgee: '알쥐',\n                        robotis_rla: '알라',\n                        robotis_kkokdu: '꼭두',\n                        robotis_korean1: '안녕하세요',\n                        robotis_korean2: '반가워요',\n                        robotis_korean3: '알겠어요',\n                        robotis_korean4: '아니에요',\n                        robotis_korean5: '모르겠어요',\n                        robotis_korean6: '좋아요',\n                        robotis_korean7: '싫어요',\n                        robotis_korean8: '이름을말하세요',\n                        robotis_korean9: '무엇을도와줄까?',\n                        robotis_korean10: '잘했어',\n                        robotis_korean11: '괜찮아',\n                        robotis_korean12: '다시해보자',\n                        robotis_korean13: '고마워',\n                        robotis_korean14: '다시말해줄래?',\n                        robotis_korean15: '최고야!',\n                        robotis_korean16: '신나요',\n                        robotis_korean17: '즐거워요',\n                        robotis_korean18: '미안해요',\n                        robotis_korean19: '화나요',\n                        robotis_korean20: '부끄러워요',\n                        robotis_korean21: '무서워요',\n                        robotis_korean22: '속상해요',\n                        robotis_korean23: '사랑해요',\n                        robotis_korean24: '예뻐요',\n                        robotis_korean25: '신기해요',\n                        robotis_korean26: '초조해요',\n                        robotis_korean27: '앞으로가자',\n                        robotis_korean28: '뒤로가자',\n                        robotis_korean29: '일어나자',\n                        robotis_korean30: '넘어졌네?',\n                        robotis_korean31: '오예',\n                        robotis_korean32: '아싸',\n                        robotis_korean33: '어머',\n                        robotis_korean34: '이런',\n                        robotis_korean35: '오호',\n                        robotis_korean36: '하하하',\n                        robotis_korean37: '호호호',\n                        robotis_korean38: '졸려',\n                        robotis_korean39: '자장가를들려줘',\n                        robotis_korean40: '안녕',\n                        robotis_korean41: '배고프다',\n                        robotis_korean42: '도토리땡긴다',\n                        robotis_korean43: '아.씻고싶어',\n                        robotis_korean44: '비누목욕시간이야',\n                        robotis_korean45: '심심한데',\n                        robotis_korean46: '간식먹을까',\n                        robotis_korean47: '아파요',\n                        robotis_korean48: '약은없나요?',\n                        robotis_korean49: '어디로가야하지?',\n                        robotis_korean50: '와아도착이다',\n                        robotis_korean51: '왼쪽으로가자',\n                        robotis_korean52: '오른쪽으로가자',\n                        robotis_korean53: '깜짝이야',\n                        robotis_korean54: '찾았다',\n                        robotis_korean55: '여긴없네',\n                        robotis_korean56: '혹시나불렀어?',\n                        robotis_korean57: '내려주세요',\n                        robotis_korean58: '앗',\n                        robotis_korean59: '힝',\n                        robotis_korean60: '이익',\n                        robotis_dog: '개',\n                        robotis_frog: '개구리',\n                        robotis_cat: '고양이',\n                        robotis_chicken: '닭',\n                        robotis_tiger: '호랑이',\n                        robotis_mouse: '쥐',\n                        robotis_ambul: '앰뷸런스',\n                        robotis_Horn: '경적(빵빵)',\n                        robotis_siren: '사이렌(경찰차)',\n                        robotis_whistle: '호루라기',\n                        robotis_gun: '총소리',\n                        robotis_clap: '박수소리',\n                        robotis_melody1: '멜로디1',\n                        robotis_melody2: '멜로디2',\n                        robotis_melody3: '멜로디3',\n                        robotis_melody4: '멜로디4',\n                        robotis_forward: '앞으로',\n                        robotis_backward: '뒤로',\n                        robotis_acceleration: '가속도',\n                        robotis_gyro: '자이로',\n                        robotis_run: '실행',\n                        robotis_cancel: '취소',\n                        robotis_push: '눌림',\n                        robotis_notPush: '안눌림',\n                        robotis_play: '연주',\n                        robotis_rest: '쉼표',\n                        robotis_face01: '와하하',\n                        robotis_face02: '싱글벙글',\n                        robotis_face03: '큭큭큭',\n                        robotis_face04: '냠냠',\n                        robotis_face05: '겁먹음',\n                        robotis_face06: '답답',\n                        robotis_face07: '갸우뚱',\n                        robotis_face08: '어벙벙',\n                        robotis_face09: '고함',\n                        robotis_face10: '화남',\n                        robotis_face11: '킁킁(왼쪽)',\n                        robotis_face12: '킁킁(오른쪽)',\n                        robotis_face13: '킁킁(아래)',\n                        robotis_face14: '안심',\n                        robotis_face15: '기절',\n                        robotis_face16: '헤롱헤롱',\n                        robotis_face17: '하품',\n                        robotis_face18: '졸림',\n                        robotis_face19: '잠듦',\n                        robotis_face20: '마음앓이',\n                        robotis_face21: '폭풍눈물',\n                        robotis_face22: '목욕',\n                        robotis_face23: '햐트뿅뿅',\n\n                        robotis_flashing1: '깜박임1',\n                        robotis_flashing2: '깜박임2',\n                        robotis_flashing3: '깜박임3',\n                        robotis_flashing4: '깜박임4',\n                        robotis_flashing5: '깜박임5',\n                        robotis_flashing6: '깜박임6',\n                        robotis_flashing7: '깜박임7',\n                        robotis_flashing8: '깜박임8',\n                        robotis_flashing9: '깜박임9',\n                        robotis_moveF: '전진',\n                        robotis_moveB: '후진',\n                        robotis_moveL: '좌회전',\n                        robotis_moveR: '우회전',\n                        robotis_moveU: 'U턴',\n                        robotis_moveL_in_place: '제자리 좌회전',\n                        robotis_moveR_in_place: '제자리 우회전',\n                        robotis_moveU_in_place: '제자리 U턴',\n                        robotis_moveRG1: '일어서기',\n                        robotis_moveRG2: '앉기',\n                        robotis_moveRG3: '발버둥',\n                        robotis_moveRG4: '발들기',\n                        robotis_fast: '빠른',\n                        robotis_normal: '보통',\n                        robotis_slow: '느린',\n                        robotis_stop: '정지',\n                        robotis_roll: '좌우 회전각 (roll)',\n                        robotis_pitch: '앞뒤 회전각 (pitch)',\n                        robotis_direction_forward: '전진방향',\n                        robotis_direction_backward: '후진방향',\n                        robotis_stMotion1: '기본 자세',\n                        robotis_stMotion2: '전진',\n                        robotis_stMotion3: '우전진',\n                        robotis_stMotion4: '좌전진',\n                        robotis_stMotion5: '후진',\n                        robotis_stMotion6: '오른쪽으로',\n                        robotis_stMotion7: '왼쪽으로',\n                        robotis_stMotion8: '우회전',\n                        robotis_stMotion9: '좌회전',\n                        robotis_spMotion1: '오른손 들기',\n                        robotis_spMotion2: '오른손 내리기',\n                        robotis_spMotion3: '왼손 들기',\n                        robotis_spMotion4: '왼손 내리기',\n                        robotis_spMotion5: '양손 들기',\n                        robotis_spMotion6: '양손 내리기',\n                        robotis_spMotion7: '뒤로 넘어지기',\n                        robotis_spMotion8: '앞으로 넘어지기',\n                        robotis_spMotion9: '앞으로 일어서기',\n                        robotis_spMotion10: '뒤로 일어서기',\n                        robotis_spMotion11: '방어',\n                        robotis_spMotion12: '공격1',\n                        robotis_spMotion13: '공격2',\n                        robotis_spMotion14: '공격3',\n                        robotis_spMotion15: '공격4',\n                        robotis_screen1: '가위',\n                        robotis_screen2: '바위',\n                        robotis_screen3: '보',\n                        robotis_icon_food_plant_1: '우유',\n                        robotis_icon_food_plant_2: '나무',\n                        robotis_icon_food_plant_3: '스프',\n                        robotis_icon_food_plant_4: '케익',\n                        robotis_icon_food_plant_5: '물',\n                        robotis_icon_food_plant_6: '주스',\n                        robotis_icon_food_plant_7: '당근',\n                        robotis_icon_food_plant_8: '사과',\n                        robotis_icon_food_plant_9: '오렌지',\n                        robotis_icon_food_plant_10: '고기',\n                        robotis_icon_food_plant_11: '화분',\n                        robotis_icon_food_plant_12: '장미',\n                        robotis_icon_food_plant_13: '포도',\n                        robotis_icon_food_plant_14: '감자',\n                        robotis_icon_food_plant_15: '사탕',\n                        robotis_icon_food_plant_16: '치즈',\n                        robotis_icon_food_plant_17: '식빵',\n                        robotis_icon_food_plant_18: '꽃들',\n                        robotis_icon_food_plant_19: '커피',\n                        robotis_icon_food_plant_20: '튤립',\n                        robotis_icon_food_plant_21: '바나나',\n                        robotis_icon_food_plant_22: '과일들',\n                        robotis_icon_food_plant_23: '햄버거',\n                        robotis_icon_food_plant_24: '피자',\n                        robotis_icon_animal_human_1: '시바견',\n                        robotis_icon_animal_human_2: '강아지',\n                        robotis_icon_animal_human_3: '곰',\n                        robotis_icon_animal_human_4: '새',\n                        robotis_icon_animal_human_5: '오리',\n                        robotis_icon_animal_human_6: '사자',\n                        robotis_icon_animal_human_7: '호랑이',\n                        robotis_icon_animal_human_8: '말',\n                        robotis_icon_animal_human_9: '양',\n                        robotis_icon_animal_human_10: '상어1(왼쪽)',\n                        robotis_icon_animal_human_11: '상어1(오른쪽)',\n                        robotis_icon_animal_human_12: '상어2(왼쪽)',\n                        robotis_icon_animal_human_13: '상어2(오른쪽)',\n                        robotis_icon_animal_human_14: '물고기1',\n                        robotis_icon_animal_human_15: '물고기2',\n                        robotis_icon_animal_human_16: '물고기3',\n                        robotis_icon_animal_human_17: '문어',\n                        robotis_icon_animal_human_18: '원숭이',\n                        robotis_icon_animal_human_19: '닭',\n                        robotis_icon_animal_human_20: '돼지',\n                        robotis_icon_animal_human_21: '사람(살찐)',\n                        robotis_icon_animal_human_22: '사람(수영복)',\n                        robotis_icon_animal_human_23: '아기',\n                        robotis_icon_animal_human_24: '사람(달리는)',\n                        robotis_icon_animal_human_25: '사람(노래하는)',\n                        robotis_icon_animal_human_26: '사람(앉은)',\n                        robotis_icon_animal_human_27: '사람(화난)',\n                        robotis_icon_animal_human_28: '사람(만세)',\n                        robotis_icon_animal_human_29: '왕',\n                        robotis_icon_animal_human_30: '왕자',\n                        robotis_icon_animal_human_31: '공주',\n                        robotis_icon_animal_human_32: '요리사',\n                        robotis_icon_animal_human_33: '의사',\n                        robotis_icon_animal_human_34: '간호사',\n                        robotis_icon_object_tool_1: '가방',\n                        robotis_icon_object_tool_2: '상자',\n                        robotis_icon_object_tool_3: '머그컵',\n                        robotis_icon_object_tool_4: '모자(중절모)',\n                        robotis_icon_object_tool_5: '모자(캡모자)',\n                        robotis_icon_object_tool_6: '열쇠',\n                        robotis_icon_object_tool_7: '장난감',\n                        robotis_icon_object_tool_8: '책',\n                        robotis_icon_object_tool_9: '곰인형',\n                        robotis_icon_object_tool_10: '드럼',\n                        robotis_icon_object_tool_11: '메모장',\n                        robotis_icon_object_tool_12: '볼펜',\n                        robotis_icon_object_tool_13: '책상',\n                        robotis_icon_object_tool_14: '테이블',\n                        robotis_icon_object_tool_15: '의자',\n                        robotis_icon_object_tool_16: '침대',\n                        robotis_icon_object_tool_17: '텐트',\n                        robotis_icon_object_tool_18: '접시',\n                        robotis_icon_object_tool_19: '축구공',\n                        robotis_icon_object_tool_20: '종',\n                        robotis_icon_object_tool_21: '손목시계',\n                        robotis_icon_object_tool_22: '신발',\n                        robotis_icon_object_tool_23: '전등',\n                        robotis_icon_object_tool_24: '라디오',\n                        robotis_icon_object_tool_25: '지폐',\n                        robotis_icon_object_tool_26: '자',\n                        robotis_icon_object_tool_27: '카메라',\n                        robotis_icon_object_tool_28: '스푼',\n                        robotis_icon_object_tool_29: '건반',\n                        robotis_icon_object_tool_30: '달력',\n                        robotis_icon_object_tool_31: '칼',\n                        robotis_icon_object_tool_32: '풍선',\n                        robotis_icon_object_tool_33: '물통',\n                        robotis_icon_object_tool_34: '나무막대(세로)',\n                        robotis_icon_object_tool_35: '나무막대(가로)',\n                        robotis_icon_object_tool_36: '낚시바늘',\n                        robotis_icon_vehicle_number_1: '자동차',\n                        robotis_icon_vehicle_number_2: '버스',\n                        robotis_icon_vehicle_number_3: '트럭',\n                        robotis_icon_vehicle_number_4: '지프',\n                        robotis_icon_vehicle_number_5: '자전거',\n                        robotis_icon_vehicle_number_6: '전철',\n                        robotis_icon_vehicle_number_7: '기차',\n                        robotis_icon_vehicle_number_8: '비행기',\n                        robotis_icon_vehicle_number_9: '전투기(세로)',\n                        robotis_icon_vehicle_number_10: '전투기(가로)',\n                        robotis_icon_vehicle_number_11: '로켓',\n                        robotis_icon_vehicle_number_12: '어선',\n                        robotis_icon_vehicle_number_13: '여객선',\n                        robotis_icon_vehicle_number_14: '잠수함(왼쪽)',\n                        robotis_icon_vehicle_number_15: '잠수함(오른쪽)',\n                        robotis_icon_vehicle_number_16: '비행기(왼쪽)',\n                        robotis_icon_vehicle_number_17: '비행기(오른쪽)',\n                        robotis_icon_vehicle_number_18: '비행기(윗쪽)',\n                        robotis_icon_vehicle_number_19: '우주선(왼쪽)',\n                        robotis_icon_vehicle_number_20: '우주선(오른쪽)',\n                        robotis_icon_vehicle_number_21: '우주선(윗쪽)',\n                        robotis_icon_vehicle_number_22: '주사위(1)',\n                        robotis_icon_vehicle_number_23: '주사위(2)',\n                        robotis_icon_vehicle_number_24: '주사위(3)',\n                        robotis_icon_vehicle_number_25: '주사위(4)',\n                        robotis_icon_vehicle_number_26: '주사위(5)',\n                        robotis_icon_vehicle_number_27: '주사위(6)',\n                        robotis_icon_vehicle_number_28: '0',\n                        robotis_icon_vehicle_number_29: '1',\n                        robotis_icon_vehicle_number_30: '2',\n                        robotis_icon_vehicle_number_31: '3',\n                        robotis_icon_vehicle_number_32: '4',\n                        robotis_icon_vehicle_number_33: '5',\n                        robotis_icon_vehicle_number_34: '6',\n                        robotis_icon_vehicle_number_35: '7',\n                        robotis_icon_vehicle_number_36: '8',\n                        robotis_icon_vehicle_number_37: '9',\n                        robotis_icon_vehicle_number_38: '10',\n                        robotis_icon_game_character_1: '알쥐(정면)',\n                        robotis_icon_game_character_2: '알쥐(왼쪽)',\n                        robotis_icon_game_character_3: '알쥐(오른쪽)',\n                        robotis_icon_game_character_4: '알라(정면)',\n                        robotis_icon_game_character_5: '알라(왼쪽))',\n                        robotis_icon_game_character_6: '알라(오른쪽)',\n                        robotis_icon_game_character_7: '유령',\n                        robotis_icon_game_character_8: '괴물',\n                        robotis_icon_game_character_9: '바이러스',\n                        robotis_icon_game_character_10: '세균',\n                        robotis_icon_game_character_11: '나는 알쥐(왼쪽)',\n                        robotis_icon_game_character_12: '나는 알쥐(오른쪽)',\n                        robotis_icon_game_character_13: '나는 알쥐(정면)',\n                        robotis_icon_game_character_14: '메달',\n                        robotis_icon_game_character_15: '돈(G)',\n                        robotis_icon_game_character_16: '돈($)',\n                        robotis_icon_game_character_17: '하트',\n                        robotis_icon_game_character_18: '폭탄',\n                        robotis_icon_game_character_19: '불',\n                        robotis_icon_game_character_20: '구름1',\n                        robotis_icon_game_character_21: '구름2',\n                        robotis_icon_game_character_22: '포탄1',\n                        robotis_icon_game_character_23: '포탄2',\n                        robotis_icon_game_character_24: '대포(수평)',\n                        robotis_icon_game_character_25: '대포(수직)',\n                        robotis_icon_game_character_26: '레이저(수직)',\n                        robotis_icon_game_character_27: '게이저(수평)',\n                        robotis_icon_game_character_28: '화살(수평)',\n                        robotis_icon_game_character_29: '화살(수직)',\n                        robotis_icon_game_character_30: '미사일(U)',\n                        robotis_icon_game_character_31: '미사일(D)',\n                        robotis_icon_game_character_32: '미사일(L)',\n                        robotis_icon_game_character_33: '미사일(R)',\n                        robotis_icon_game_character_34: '낙하산',\n                        robotis_icon_game_character_35: '폭발1',\n                        robotis_icon_game_character_36: '폭발2',\n                        robotis_icon_game_character_37: '조준경',\n                        robotis_icon_game_character_38: '가위',\n                        robotis_icon_game_character_39: '바위',\n                        robotis_icon_game_character_40: '보',\n                        robotis_icon_game_character_41: '걷는 사람1',\n                        robotis_icon_game_character_42: '걷는 사람2',\n                        robotis_icon_game_character_43: '뛰는 사람1',\n                        robotis_icon_game_character_44: '뛰는 사람2',\n                        robotis_speed_fast: '빠른 속도',\n                        robotis_speed_midium: '중간 속도',\n                        robotis_speed_slow: '느린 속도',\n                        robotis_clockwise: '시계방향',\n                        robotis_counterclockwise: '반시계방향',\n                        robotis_up: '들기',\n                        robotis_down: '내리기',\n                        robotis_if_greater: '크면',\n                        robotis_if_smaller: '작으면',\n                        robotis_if_equal: '같으면',\n                        robotis_front_right: '앞 오른쪽',\n                        robotis_front_left: '앞 왼쪽',\n                        robotis_bottom_right: '아래 오른쪽',\n                        robotis_bottom_left: '아래 왼쪽',\n                        robotis_side_right: '우측',\n                        robotis_side_left: '좌측',\n                        robotis_front_ir_sensor: '적외선센서',\n                        robotis_distance_sensor: '거리센서',\n                        robotis_front: '앞',\n                        robotis_right: '오른쪽',\n                        robotis_left_wheel: '왼쪽바퀴(52)',\n                        robotis_right_wheel: '오른쪽바퀴(51)',\n                        // https://namu.wiki/w/%EC%9D%8C%ED%91%9C\n                        robotis_beat_sound_8th_note: '8분음표 (♪)',\n                        robotis_beat_sound_dotted_8th_note: '점8분음표 (♪.)',\n                        robotis_beat_sound_quarter_note: '4분음표 (♩)',\n                        robotis_beat_sound_dotted_quarter_note: '점4분음표 (♩.)',\n                        robotis_beat_sound_half_note: '2분음표 (𝅗𝅥)',\n                        robotis_beat_sound_dotted_half_note: '점2분음표 (𝅗𝅥.)',\n                        robotis_beat_sound_whole_note: '온음표 (𝅝)',\n                        robotis_beat_sound_dotted_note: '점온음표 (𝅝.)',\n                        robotis_beat_rest_8th_note: '8분쉼표 (𝄾)',\n                        robotis_beat_rest_dotted_8th_note: '점8분쉼표 (𝄾.)',\n                        robotis_beat_rest_quarter_note: '4분쉼표 (𝄽)',\n                        robotis_beat_rest_dotted_quarter_note: '점4분쉼표 (𝄽.)',\n                        robotis_beat_rest_half_note: '2분쉼표 (𝄼)',\n                        robotis_beat_rest_dotted_half_note: '점2분쉼표 (𝄼˙)',\n                        robotis_beat_rest_whole_note: '온쉼표 (𝄻)',\n                        robotis_beat_rest_dotted_note: '점온쉼표 (𝄻˙)',\n                        robotis_line_cross_type_0: '|',\n                        robotis_line_cross_type_1: ' (공백)',\n                        robotis_line_cross_type_5: '🞣',\n                        robotis_line_cross_type_6: '⏉',\n                        robotis_line_cross_type_7: '⊣',\n                        robotis_line_cross_type_8: '⊢',\n                        robotis_line_cross_type_9: '⏋',\n                        robotis_line_cross_type_10: '⎾',\n                        robotis_line_cross_type_11: '¦',\n                        robotis_line_cross_type_12: '︙',\n\n                        robotis_dxl_mode_joint: '관절',\n                        robotis_dxl_mode_wheel: '바퀴',\n                        robotis_dxl_mode_multi_turn: '여러바퀴회전',\n                        robotis_dxl_move_rotate: '회전',\n                        robotis_dxl_move_stop: '정지',\n                        robotis_dxl_rotate_cw: '시계방향',\n                        robotis_dxl_rotate_ccw: '반시계방향',\n                        robotis_dxl_value_angle: '각도',\n                        robotis_dxl_value_velocity: '속도',\n                        robotis_dxl_value_moving: '움직임',\n\n                        robotis_connected: '연결',\n                        robotis_disconnected: '없음',\n                        robotis_ai_camera_mode_face_recognition: '얼굴 인식',\n                        robotis_ai_camera_mode_line_tracking: '라인 인식',\n                        robotis_ai_camera_mode_color_recognition: '색상 인식',\n                        robotis_ai_camera_mode_tag_recognition: '태그 인식',\n                        robotis_ai_camera_mode_object_classification: '사물 분류',\n                        robotis_ai_camera_mode_expression_recognition: '표정 인식',\n                        robotis_ai_camera_target_face: '얼굴',\n                        robotis_ai_camera_target_expression: '표정',\n                        robotis_ai_camera_target_object: '사물',\n                        robotis_ai_camera_target_color: '색상',\n                        robotis_ai_camera_target_tag: '태그',\n                        robotis_ai_camera_target_qr: 'QR코드',\n                        robotis_ai_camera_target_block: '사각형',\n                        robotis_ai_camera_target_arrow: '화살표',\n                        robotis_ai_camera_center_block_center_x: '중심 X좌표',\n                        robotis_ai_camera_center_block_center_y: '중심 Y좌표',\n                        robotis_ai_camera_center_block_width: '너비',\n                        robotis_ai_camera_center_block_height: '높이',\n                        robotis_ai_camera_center_leared_id: '클래스',\n                        robotis_ai_camera_center_arrow_origin_x: '시작점 X좌표',\n                        robotis_ai_camera_center_arrow_origin_y: '시작점 Y좌표',\n                        robotis_ai_camera_center_arrow_target_x: '끝점 X좌표',\n                        robotis_ai_camera_center_arrow_target_y: '끝점 Y좌표',\n\n                        robotis_plant_ripe: '빨간색',\n                        robotis_plant_unripe: '초록색',\n                        robotis_harvest: '수확하고',\n                        robotis_not_harvest: '수확하지 않고',\n                    },\n                },\n                en: {\n                    template: {\n                        // 주행 제어\n                        robotis_robotai_lite_drive_simple: 'Move %2 with velocity %1 %3',\n                        robotis_robotai_lite_drive_advanced:\n                            'Left wheel %2 with velocity %1, right wheel %4 with velocity %3 %5',\n                        robotis_robotai_lite_drive_seperate:\n                            '%1 wheel rotate %3 with velocity %2 %4',\n                        robotis_robotai_lite_drive_angle: 'Rotate %1 wheel %2 degree %3 %4',\n                        robotis_robotai_lite_go_distance: 'Moves %2 %1 cm %3',\n                        robotis_robotai_lite_turn_angle: 'Rotates %1 degree(s) %2 in place %3',\n                        robotis_robotai_lite_follow_line: 'Follow line with %1 speed %2',\n                        robotis_robotai_lite_stop_at_cross: 'Stop at cross %1 %2',\n                        robotis_robotai_lite_turn_at_line: '%1 at cross and stop %2',\n                        robotis_robotai_lite_drive_stop: 'Stop %1',\n\n                        robotis_robotai_lite_securitybot_init: 'Security robot init %1',\n                        robotis_robotai_lite_securitybot_hi: 'Security robot shake up and down %1',\n                        robotis_robotai_lite_securitybot_alert:\n                            'Security robot shake left and right %1',\n\n                        robotis_robotai_lite_petbot_happy: 'Petbot laugh %1',\n                        robotis_robotai_lite_petbot_sad: 'Petbot angry %1',\n\n                        robotis_robotai_lite_farmbot_init: 'SmartFarm Robot init %1',\n                        robotis_robotai_lite_farmbot_seek: 'Look for plant %1',\n                        robotis_robotai_lite_farmbot_plant_type: 'If it is %1 plant',\n                        robotis_robotai_lite_farmbot_harvest_or_not_and_go:\n                            '%1 the plant and go back %2',\n\n                        // 값 블록\n                        robotis_robotai_lite_cm_ir_value: 'Value of %1 IR Sensor',\n                        robotis_robotai_lite_cm_ir_compare:\n                            'If the number %1 IR sensor value is %3 than %2',\n                        robotis_robotai_lite_detectFrontObj: 'If %1 IR sensor detected an object',\n                        robotis_robotai_lite_cm_btn_value:\n                            \"When the controller's %1 button is clicked\",\n                        robotis_robotai_lite_cm_joystick_value:\n                            \"If the controller's yellow joystick position is %1\",\n                        robotis_robotai_lite_mic: 'MIC volume(dB)',\n                        robotis_robotai_lite_detectSound_compare:\n                            'If sound is detected from %1 of the robot',\n                        robotis_robotai_lite_imu: \"%1 axis' %2 value\",\n                        robotis_robotai_lite_roll_pitch: '%1 value of the controller',\n                        robotis_robotai_lite_environment_value: '%1 value',\n                        robotis_robotai_lite_environment_compare: 'If %1 value is %3 than %2',\n                        robotis_robotai_lite_line_cross_compare: 'If the type of cross is %1',\n                        robotis_robotai_lite_dxl_value: 'The angle of ID %1',\n\n                        // 소리\n                        robotis_robotai_lite_scale_simple: 'Play the note %2 as %3 in octave %1 %4',\n                        robotis_robotai_lite_scale_advanced:\n                            'Play the note %2 in octave %1 for %3 beat %4',\n                        robotis_robotai_lite_rest_simple: '%1 %2',\n                        robotis_robotai_lite_rest_advanced: 'Rest %1 beat %2',\n                        robotis_robotai_lite_beat_per_minute: 'Set playing speed to %1 %2',\n                        robotis_robotai_lite_Hello: 'Robot speaks %1 %2',\n                        robotis_robotai_lite_effectSound: 'Play sound effect %1 %2',\n                        robotis_robotai_lite_record: 'Record to sound slot %1 %2',\n                        robotis_robotai_lite_playRecord: 'Play sound from slot %1 %2',\n\n                        // LCD 제어\n                        robotis_robotai_lite_screen: 'Set screen expression to %1 %2 %3',\n                        robotis_robotai_lite_anim_screen: 'Set screen animation to %1 %2 %3',\n                        robotis_robotai_lite_icon_screen_food_plant:\n                            'Display %1 from [Food/Plants] at position (%2, %3) in size %4 %5',\n                        robotis_robotai_lite_icon_screen_animal_human:\n                            'Display %1 from [Animal/Human] at position (%2, %3) in size %4 %5',\n                        robotis_robotai_lite_icon_screen_object_tool:\n                            'Display %1 from [Object/Tool] at position (%2, %3) in size %4 %5',\n                        robotis_robotai_lite_icon_screen_vehicle_number:\n                            'Display %1 from [Vehicle/Number] at position (%2, %3) in size %4 %5',\n                        robotis_robotai_lite_icon_screen_game_character:\n                            'Display %1 from [Game/Character] at position (%2, %3) in size %4 %5',\n                        robotis_robotai_lite_text_screen:\n                            'Display %1 in %5 in %4 at (%2, %3) on the screen %6',\n                        robotis_robotai_lite_text_screen_redraw:\n                            'Newly display %1 in %4 at (%2, %3) %5',\n                        robotis_robotai_lite_pixel: 'Display %3 colored dot at (%1, %2) %4',\n                        robotis_robotai_lite_LCDColor: 'Set screen color as %1 %2',\n                        robotis_robotai_lite_LCD_Flash:\n                            'Blink the screen with %1 and %2 at intervals of %3 seconds %4',\n                        robotis_robotai_lite_LCDBright: 'Set screen brightness as %1 %2',\n\n                        // LED 제어\n                        robotis_robotai_lite_cm_led: \"%2 the robot's %1 LED %3\",\n                        robotis_robotai_lite_cm_led_pattern: 'LED %1 blinks at a %2 speed %3',\n\n                        // DXL 제어\n                        robotis_robotai_lite_dxl_set_mode: 'Set ID %1 motor as %2 mode %3',\n                        robotis_robotai_lite_dxl_each_control: 'Move %1th motor %2° for %3 second',\n                        robotis_robotai_lite_dxl_set_position:\n                            'Rotate ID %1 motor to angle %3° at speed %2 %4',\n                        robotis_robotai_lite_dxl_set_rotate: '%4 ID %1 motor %3 at speed %2 %4',\n                        robotis_robotai_lite_dxl_set_multiturn_round:\n                            'Rotate ID %1 motor %3 times %4 at speed %2 %5',\n\n                        // AI Camera 값 블록\n                        robotis_robotai_lite_ai_camera_connection_status: 'AI Camera: If %1',\n                        robotis_robotai_lite_ai_camera_if_detected: 'AI Camera: If %1 is displayed',\n\n                        robotis_robotai_lite_ai_camera_block_value_closest_to_center:\n                            'AI Camera: %2 of the %1 closest to the center of the screen',\n                        robotis_robotai_lite_ai_camera_arrow_value_closest_to_center:\n                            'AI Camera: %1 of the arrow closest to the center of the screen',\n                        robotis_robotai_lite_ai_camera_number_of_learned_id:\n                            'AI Camera: the number of learned ID',\n                        robotis_robotai_lite_ai_camera_block_value_of_id:\n                            'AI Camera: %3 of %2 with detected ID %1',\n                        robotis_robotai_lite_ai_camera_arrow_value_of_id:\n                            'AI Camera: %2 of arrow with detected ID %1',\n\n                        robotis_robotai_lite_ai_camera_if_learned_id:\n                            'AI Camera: If learned data with ID %1',\n                        robotis_robotai_lite_ai_camera_if_detected_id_type:\n                            'AI Camera: If learned %2 data with ID %1',\n\n                        // 인공지능 카메라 제어\n                        robotis_robotai_lite_ai_camera_set_mode: 'AI Camera: Set mode to %1 %2',\n                        robotis_robotai_lite_ai_camera_print_custom_text:\n                            'AI Camera: Display %3 at screen position (%1, %2) %4',\n                        robotis_robotai_lite_ai_camera_clear_custom_text:\n                            'AI Camera: Clear screen text %1',\n                    },\n                    Blocks: {\n                        // 주행 제어\n                        robotis_robotai_lite_drive_simple:\n                            'Drive the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %',\n                        robotis_robotai_lite_drive_advanced:\n                            'Rotate the left and right wheels of the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %',\n                        robotis_robotai_lite_drive_seperate:\n                            'Rotate the specified wheel of the robot at the specified speed and direction\\nSpeed range: -100 ~ 100\\nSpeed unit: %',\n                        robotis_robotai_lite_drive_angle:\n                            'Rotate the specified wheel of the robot in the specified direction and by the specified angle\\nAngle range: -5760 ~ 5760\\nAngle unit: degrees',\n                        robotis_robotai_lite_go_distance:\n                            'Move forward or backward by the specified distance\\nDistance range: -1000 ~ 1000\\nDistance unit: mm',\n                        robotis_robotai_lite_turn_angle:\n                            'Rotate in place by the specified angle and direction\\nAngle range: -360 ~ 360\\nAngle unit: degrees',\n                        robotis_robotai_lite_follow_line:\n                            'Start following the line at the specified speed',\n                        robotis_robotai_lite_stop_at_cross: 'Stop at the specified intersection',\n                        robotis_robotai_lite_turn_at_line:\n                            'Make the specified turn at the intersection and stop',\n                        robotis_robotai_lite_drive_stop: 'Stop the robot',\n\n                        robotis_robotai_lite_securitybot_init:\n                            'Initializes the security robot. Sets both motors to joint mode and the camera to face recognition mode.',\n                        robotis_robotai_lite_securitybot_hi:\n                            'The security robot displays the message \"User identified\" on the screen and waves its arms up and down.',\n                        robotis_robotai_lite_securitybot_alert:\n                            'The security robot displays the message \"Not a user\" on the screen and shakes its body from side to side.',\n\n                        robotis_robotai_lite_petbot_happy:\n                            'The pet robot makes a smiling face, says \"I’m happy,\" and spins around in place.',\n                        robotis_robotai_lite_petbot_sad:\n                            'The pet robot makes an angry face, says \"I’m scared,\" and moves 5cm backward.',\n\n                        robotis_robotai_lite_farmbot_init:\n                            'Initializes the smart farm robot. Moves motor 1 to the starting position and sets the camera to color recognition mode.',\n                        robotis_robotai_lite_farmbot_seek: 'Moves closer when it detects crops.',\n                        robotis_robotai_lite_farmbot_plant_type: 'Identifies the type of crop.',\n                        robotis_robotai_lite_farmbot_harvest_or_not_and_go:\n                            'Decides whether to harvest the crop or not, then rotates to the right.',\n\n                        // 값 블록\n                        robotis_robotai_lite_cm_ir_value:\n                            'IR sensor value of the specified number (range: 0 ~ 200)',\n                        robotis_robotai_lite_cm_ir_compare:\n                            \"If the IR sensor value of the specified number matches the specified value, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_robotai_lite_detectFrontObj:\n                            \"It returns 'true' if an object is detected by the infrared sensor in the specified direction; otherwise, it returns 'false'.\",\n                        robotis_robotai_lite_cm_btn_value:\n                            \"If the specified button is clicked, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_robotai_lite_cm_joystick_value:\n                            \"If the joystick position is in the specified state, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_robotai_lite_mic:\n                            'Displays the intensity of the sound detected by the microphone in decibels (dB).',\n                        robotis_robotai_lite_detectSound_compare:\n                            \"If the direction of the sound matches the specified direction, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_robotai_lite_imu:\n                            'Value of the specified accelerometer/gyro sensor on the specified axis\\nRange: -100 ~ 100',\n                        robotis_robotai_lite_roll_pitch:\n                            'roll/pitch value\\nroll: -180° ~ 180°, pitch: -90° ~ 90°',\n                        robotis_robotai_lite_environment_value:\n                            'Value of the specified sensor\\nMotion sensor: 0 (no movement) / 1 (movement)\\nBrightness range: 0 ~ 100%\\nTemperature range: -25°C ~ 85°C',\n                        robotis_robotai_lite_environment_compare:\n                            \"If the specified equation of the specified sensor value is correct, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_robotai_lite_line_cross_compare:\n                            \"If the specified intersection shape is correct, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_robotai_lite_dxl_value:\n                            'Position angle value of the specified motor\\nRange: -180° ~ 180°',\n\n                        // 소리\n                        robotis_robotai_lite_scale_simple:\n                            'Play with the specified octave, scale, and note',\n                        robotis_robotai_lite_scale_advanced:\n                            'Play with the specified octave, scale, and beat',\n                        robotis_robotai_lite_rest_simple: 'Rest for the specified rest note',\n                        robotis_robotai_lite_rest_advanced: 'Rest for the specified beat',\n                        robotis_robotai_lite_beat_per_minute:\n                            'Set the playing speed (BPM)\\nRange: 10 ~ 600',\n                        robotis_robotai_lite_Hello: 'Play the specified voice of the robot',\n                        robotis_robotai_lite_effectSound:\n                            'Play the specified sound effect of the robot',\n                        robotis_robotai_lite_record:\n                            'Record and save to the specified number storage',\n                        robotis_robotai_lite_playRecord:\n                            'Play the recorded voice in the specified number storage',\n\n                        // LCD 제어\n                        robotis_robotai_lite_screen:\n                            'Set the character and expression of the controller screen background',\n                        robotis_robotai_lite_anim_screen:\n                            'Set the character and expression of the controller screen animation',\n                        robotis_robotai_lite_icon_screen_food_plant:\n                            'Set the position and size of a specific icon in [food/plant] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_robotai_lite_icon_screen_animal_human:\n                            'Set the position and size of a specific icon in [animal/human] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_robotai_lite_icon_screen_object_tool:\n                            'Set the position and size of a specific icon in [object/tool] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_robotai_lite_icon_screen_vehicle_number:\n                            'Set the position and size of a specific icon in [vehicle/number] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_robotai_lite_icon_screen_game_character:\n                            'Set the position and size of a specific icon in [game/character] on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_robotai_lite_text_screen:\n                            'Set the position, font size, and color of the specified text on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n                        robotis_robotai_lite_text_screen_redraw:\n                            'Set the position and color of the specified text to be newly displayed (clearing the background of the text) on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120\\nSize: 0 ~ 200',\n                        robotis_robotai_lite_pixel:\n                            'Set the position and color of the dot to be displayed on the screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n                        robotis_robotai_lite_LCDBright:\n                            'Set the screen brightness\\nBrightness range: 0% ~ 100%',\n                        robotis_robotai_lite_LCDColor: 'Set the screen color',\n                        robotis_robotai_lite_LCD_Flash:\n                            'Specify two colors and the interval for the screen to blink.',\n\n                        // LED 제어\n                        robotis_robotai_lite_cm_led:\n                            'Turn the specified LED of the controller on or off',\n                        robotis_robotai_lite_cm_led_pattern:\n                            'Set the blinking pattern of LEDs of the controller',\n\n                        // DXL 제어\n                        robotis_robotai_lite_dxl_set_mode:\n                            'Set the operating mode of the motor with the specified ID',\n                        robotis_robotai_lite_dxl_each_control:\n                            'Set the motor with the specified ID to move to the specified angle for the specified time (seconds)',\n                        robotis_robotai_lite_dxl_set_position:\n                            'Set the motor with the specified ID to move to the specified angle at the specified speed',\n                        robotis_robotai_lite_dxl_set_rotate:\n                            'Set the rotation speed and direction of the motor with the specified ID',\n                        robotis_robotai_lite_dxl_set_multiturn_round:\n                            'Set the motor with the specified ID to rotate the specified number of turns at the specified speed and direction',\n\n                        // AI Camera 값 블록\n                        robotis_robotai_lite_ai_camera_connection_status:\n                            \"If the AI camera is connected, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_robotai_lite_ai_camera_if_detected:\n                            \"If the selected symbol (rectangle/arrow) is displayed on the LCD screen of the AI camera, it is determined as 'true'; otherwise, 'false'.\",\n\n                        robotis_robotai_lite_ai_camera_block_value_closest_to_center:\n                            'X coordinate/Y coordinate/width/height/learning ID of the rectangle closest to the center of the AI camera screen',\n                        robotis_robotai_lite_ai_camera_arrow_value_closest_to_center:\n                            'Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate/learning ID of the arrow closest to the center of the AI camera screen',\n                        robotis_robotai_lite_ai_camera_number_of_learned_id:\n                            'Number of IDs learned by the AI camera',\n                        robotis_robotai_lite_ai_camera_block_value_of_id:\n                            'X coordinate/Y coordinate/width/height of the rectangle with the specified ID detected by the AI camera',\n                        robotis_robotai_lite_ai_camera_arrow_value_of_id:\n                            'Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate of the arrow with the specified ID detected by the AI camera',\n\n                        robotis_robotai_lite_ai_camera_if_learned_id:\n                            \"If the AI camera has learned the data of the specified ID, it is determined as 'true'; otherwise, 'false'.\",\n                        robotis_robotai_lite_ai_camera_if_detected_id_type:\n                            \"If the AI camera has learned the specified data (rectangle/arrow) of the specified ID, it is determined as 'true'; otherwise, 'false'.\",\n\n                        // 인공지능 카메라 제어\n                        robotis_robotai_lite_ai_camera_set_mode: 'Set the mode of the AI camera',\n                        robotis_robotai_lite_ai_camera_print_custom_text:\n                            'Print the specified text at the specified position on the AI camera screen\\nX coordinate: -160 ~ 160\\nY coordinate: -120 ~ 120',\n                        robotis_robotai_lite_ai_camera_clear_custom_text:\n                            'Clear all the text displayed on the AI camera screen',\n                    },\n\n                    Blocks: {\n                        robotis_red: 'Red',\n                        robotis_orange: 'Orange',\n                        robotis_yellow: 'Yellow',\n                        robotis_green: 'Green',\n                        robotis_blue: 'Blue',\n                        robotis_brown: 'Brown',\n                        robotis_black: 'Black',\n                        robotis_white: 'White',\n                        robotis_left: 'Left',\n                        robotis_center: 'Center',\n                        robotis_right: 'Right',\n                        robotis_both: 'Both',\n                        robotis_rgee: 'R-GEE',\n                        robotis_rla: 'KODALA',\n                        robotis_kkokdu: 'TIG',\n                        robotis_korean1: 'Hello!',\n                        robotis_korean2: 'Great to see you.',\n                        robotis_korean3: 'Okay ~',\n                        robotis_korean4: 'No!',\n                        robotis_korean5: \"I don't know.\",\n                        robotis_korean6: 'I like it.',\n                        robotis_korean7: \"I don't like it.\",\n                        robotis_korean8: 'What is your name? ',\n                        robotis_korean9: 'How can I help you? ',\n                        robotis_korean10: 'Great job! ',\n                        robotis_korean11: \"It's alright.\",\n                        robotis_korean12: \"Let's do it again! \",\n                        robotis_korean13: 'Thank you! ',\n                        robotis_korean14: 'Can you say that one more time?',\n                        robotis_korean15: 'Awesome!',\n                        robotis_korean16: \"I'm excited! \",\n                        robotis_korean17: \"I'm having a great time! \",\n                        robotis_korean18: \"I'm sorry.\",\n                        robotis_korean19: \"I'm angry! \",\n                        robotis_korean20: \"I'm embarassed.\",\n                        robotis_korean21: \"I'm scared.\",\n                        robotis_korean22: \"I'm upset.\",\n                        robotis_korean23: 'I love you.',\n                        robotis_korean24: 'Very pretty! ',\n                        robotis_korean25: 'Interesting.',\n                        robotis_korean26: \"I'm nervous.\",\n                        robotis_korean27: \"Let's move forward! \",\n                        robotis_korean28: \"Let's move backward! \",\n                        robotis_korean29: \"Let's stand up! \",\n                        robotis_korean30: 'Did you fall down? ',\n                        robotis_korean31: 'Oh Yeah~',\n                        robotis_korean32: 'Sweet! ',\n                        robotis_korean33: 'Oh no',\n                        robotis_korean34: 'My My ',\n                        robotis_korean35: 'Whoo hoo! ',\n                        robotis_korean36: 'Ha Ha Ha',\n                        robotis_korean37: 'Ho Ho Ho ',\n                        robotis_korean38: \"I'm sleepy.\",\n                        robotis_korean39: 'Sing me a bedtime song! ',\n                        robotis_korean40: 'Hello!',\n                        robotis_korean41: \"I'm hungry.\",\n                        robotis_korean42: \"I'm craving an acorn! \",\n                        robotis_korean43: 'I want to take a bath! ',\n                        robotis_korean44: 'Time for a bath! ',\n                        robotis_korean45: \"I'm bored. \",\n                        robotis_korean46: 'Do you want a snack? ',\n                        robotis_korean47: \"I'm sick.\",\n                        robotis_korean48: 'Do you have any medicine? ',\n                        robotis_korean49: 'Where do we have to go? ',\n                        robotis_korean50: \"We're here! \",\n                        robotis_korean51: \"Let's go to the left side! \",\n                        robotis_korean52: \"Let's go to the right side! \",\n                        robotis_korean53: 'Oh my, you scared me! ',\n                        robotis_korean54: 'Found you! ',\n                        robotis_korean55: \"There's nothing here. \",\n                        robotis_korean56: 'Did you call me?',\n                        robotis_korean57: 'Please let me down. ',\n                        robotis_korean58: 'Oops! ',\n                        robotis_korean59: 'Hmmph! ',\n                        robotis_korean60: 'Eek! ',\n                        robotis_dog: 'Dog',\n                        robotis_frog: 'Frog',\n                        robotis_cat: 'Cat',\n                        robotis_chicken: 'Rooster',\n                        robotis_tiger: 'Tiger',\n                        robotis_mouse: 'Mouse',\n                        robotis_ambul: 'Ambulance',\n                        robotis_Horn: 'CarHorn',\n                        robotis_siren: 'Siren',\n                        robotis_whistle: 'Whistle',\n                        robotis_gun: 'Gunshot',\n                        robotis_clap: 'Clap',\n                        robotis_melody1: 'Melody1',\n                        robotis_melody2: 'Melody2',\n                        robotis_melody3: 'Melody3',\n                        robotis_melody4: 'Melody4',\n                        robotis_forward: 'Forward',\n                        robotis_backward: 'Backward',\n                        robotis_acceleration: 'acceleration',\n                        robotis_gyro: 'gyro',\n                        robotis_run: 'Run',\n                        robotis_cancel: 'Cancel',\n                        robotis_push: 'Pressed',\n                        robotis_notPush: 'Unpressed',\n                        robotis_play: 'Play',\n                        robotis_rest: 'Rest',\n                        robotis_face01: 'Haha',\n                        robotis_face02: 'Smile',\n                        robotis_face03: 'Laugh',\n                        robotis_face04: 'Yum Yum',\n                        robotis_face05: 'Scared',\n                        robotis_face06: 'Uncomfortable',\n                        robotis_face07: 'Confused',\n                        robotis_face08: 'Dazed',\n                        robotis_face09: 'Yell',\n                        robotis_face10: 'Angry',\n                        robotis_face11: 'Sniff (Left)',\n                        robotis_face12: 'Sniff (Right)',\n                        robotis_face13: 'Sniff (Down)',\n                        robotis_face14: 'Whew',\n                        robotis_face15: 'Faint',\n                        robotis_face16: 'Dizzy',\n                        robotis_face17: 'Yawn',\n                        robotis_face18: 'Sleepy',\n                        robotis_face19: 'Sleep',\n                        robotis_face20: 'Sad',\n                        robotis_face21: 'Cry',\n                        robotis_face22: 'Bath',\n                        robotis_face23: 'Heart-Eyes',\n                        robotis_flashing1: 'Flashing1',\n                        robotis_flashing2: 'Flashing2',\n                        robotis_flashing3: 'Flashing3',\n                        robotis_flashing4: 'Flashing4',\n                        robotis_flashing5: 'Flashing5',\n                        robotis_flashing6: 'Flashing6',\n                        robotis_flashing7: 'Flashing7',\n                        robotis_flashing8: 'Flashing8',\n                        robotis_flashing9: 'Flashing9',\n                        robotis_moveF: 'Forward',\n                        robotis_moveB: 'Backward',\n                        robotis_moveL: 'LeftTurn',\n                        robotis_moveR: 'RightTurn',\n                        robotis_moveU: 'U-turn',\n                        robotis_moveL_in_place: 'Turn left in place',\n                        robotis_moveR_in_place: 'Trun right in place',\n                        robotis_moveU_in_place: 'U-turn in place',\n                        robotis_moveRG1: 'Stand',\n                        robotis_moveRG2: 'Sit',\n                        robotis_moveRG3: 'Struggle',\n                        robotis_moveRG4: 'RaiseFeet',\n                        robotis_fast: 'Fast',\n                        robotis_normal: 'Normal',\n                        robotis_slow: 'Slow',\n                        robotis_stop: 'Stop',\n                        robotis_roll: 'Left-right rotate angle (roll)',\n                        robotis_pitch: 'Forward-backward rotate angle (pitch)',\n                        robotis_direction_forward: 'Forward',\n                        robotis_direction_backward: 'Backward',\n                        robotis_stMotion1: 'Standard',\n                        robotis_stMotion2: 'Forward',\n                        robotis_stMotion3: 'TurnRight',\n                        robotis_stMotion4: 'TurnLeft',\n                        robotis_stMotion5: 'Backward',\n                        robotis_stMotion6: 'ToRight',\n                        robotis_stMotion7: 'ToLeft',\n                        robotis_stMotion8: 'TurnAroundRight',\n                        robotis_stMotion9: 'TurnAroundLeft',\n                        robotis_spMotion1: 'RightHandUp',\n                        robotis_spMotion2: 'RightHandDown',\n                        robotis_spMotion3: 'LeftHandUp',\n                        robotis_spMotion4: 'LeftHandDown',\n                        robotis_spMotion5: 'BothHandsUp',\n                        robotis_spMotion6: 'BothHandsDown',\n                        robotis_spMotion7: 'FallBackward',\n                        robotis_spMotion8: 'FallForward',\n                        robotis_spMotion9: 'StandForward',\n                        robotis_spMotion10: 'StandBackward',\n                        robotis_spMotion11: 'Defence',\n                        robotis_spMotion12: 'Offense1',\n                        robotis_spMotion13: 'Offense2',\n                        robotis_spMotion14: 'Offense3',\n                        robotis_spMotion15: 'Offense4',\n                        robotis_screen1: 'Sissor',\n                        robotis_screen2: 'Rock',\n                        robotis_screen3: 'Paper',\n                        robotis_dxl_mode_joint: 'Joint',\n                        robotis_dxl_mode_wheel: 'Wheel',\n                        robotis_dxl_mode_multi_turn: 'Multi-turn',\n                        robotis_dxl_move_rotate: 'Rotate',\n                        robotis_dxl_move_stop: 'Stop',\n                        robotis_dxl_rotate_cw: 'clockwise',\n                        robotis_dxl_rotate_ccw: 'counter clockwise',\n                        robotis_dxl_value_angle: 'angle',\n                        robotis_dxl_value_velocity: 'velocity',\n                        robotis_dxl_value_moving: 'moving',\n                        robotis_icon_food_plant_1: 'Milk',\n                        robotis_icon_food_plant_2: 'Tree',\n                        robotis_icon_food_plant_3: 'Soup',\n                        robotis_icon_food_plant_4: 'Cake',\n                        robotis_icon_food_plant_5: 'Water',\n                        robotis_icon_food_plant_6: 'Juice',\n                        robotis_icon_food_plant_7: 'Carrot',\n                        robotis_icon_food_plant_8: 'Apple',\n                        robotis_icon_food_plant_9: 'Orange',\n                        robotis_icon_food_plant_10: 'Meat',\n                        robotis_icon_food_plant_11: 'Flowerpot',\n                        robotis_icon_food_plant_12: 'Rose',\n                        robotis_icon_food_plant_13: 'Grape',\n                        robotis_icon_food_plant_14: 'Potato',\n                        robotis_icon_food_plant_15: 'Candy',\n                        robotis_icon_food_plant_16: 'Cheese',\n                        robotis_icon_food_plant_17: 'Bread',\n                        robotis_icon_food_plant_18: 'Flowers',\n                        robotis_icon_food_plant_19: 'Coffee',\n                        robotis_icon_food_plant_20: 'Tulip',\n                        robotis_icon_food_plant_21: 'Banana',\n                        robotis_icon_food_plant_22: 'Fruits',\n                        robotis_icon_food_plant_23: 'Hamburger',\n                        robotis_icon_food_plant_24: 'Pizza',\n                        robotis_icon_animal_human_1: 'Shiba Dog',\n                        robotis_icon_animal_human_2: 'Puppy',\n                        robotis_icon_animal_human_3: 'Bear',\n                        robotis_icon_animal_human_4: 'Bird',\n                        robotis_icon_animal_human_5: 'Duck',\n                        robotis_icon_animal_human_6: 'Lion',\n                        robotis_icon_animal_human_7: 'Tiger',\n                        robotis_icon_animal_human_8: 'Horse',\n                        robotis_icon_animal_human_9: 'Sheep',\n                        robotis_icon_animal_human_10: 'Shark 1 (Left)',\n                        robotis_icon_animal_human_11: 'Shark 1 (Right)',\n                        robotis_icon_animal_human_12: 'Shark 2 (Left)',\n                        robotis_icon_animal_human_13: 'Shark 2 (Right)',\n                        robotis_icon_animal_human_14: 'Fish 1',\n                        robotis_icon_animal_human_15: 'Fish 2',\n                        robotis_icon_animal_human_16: 'Fish 3',\n                        robotis_icon_animal_human_17: 'Octopus',\n                        robotis_icon_animal_human_18: 'Monkey',\n                        robotis_icon_animal_human_19: 'Chicken',\n                        robotis_icon_animal_human_20: 'Pig',\n                        robotis_icon_animal_human_21: 'Person (Chubby)',\n                        robotis_icon_animal_human_22: 'Person (Swimsuit)',\n                        robotis_icon_animal_human_23: 'Baby',\n                        robotis_icon_animal_human_24: 'Person (Running)',\n                        robotis_icon_animal_human_25: 'Person (Singing)',\n                        robotis_icon_animal_human_26: 'Person (Sitting)',\n                        robotis_icon_animal_human_27: 'Person (Angry)',\n                        robotis_icon_animal_human_28: 'Person (Cheering)',\n                        robotis_icon_animal_human_29: 'King',\n                        robotis_icon_animal_human_30: 'Prince',\n                        robotis_icon_animal_human_31: 'Princess',\n                        robotis_icon_animal_human_32: 'Chef',\n                        robotis_icon_animal_human_33: 'Doctor',\n                        robotis_icon_animal_human_34: 'Nurse',\n                        robotis_icon_object_tool_1: 'Bag',\n                        robotis_icon_object_tool_2: 'Box',\n                        robotis_icon_object_tool_3: 'Mug',\n                        robotis_icon_object_tool_4: 'Hat (Fedora)',\n                        robotis_icon_object_tool_5: 'Hat (Cap)',\n                        robotis_icon_object_tool_6: 'Key',\n                        robotis_icon_object_tool_7: 'Toy',\n                        robotis_icon_object_tool_8: 'Book',\n                        robotis_icon_object_tool_9: 'Teddy Bear',\n                        robotis_icon_object_tool_10: 'Drum',\n                        robotis_icon_object_tool_11: 'Notebook',\n                        robotis_icon_object_tool_12: 'Pen',\n                        robotis_icon_object_tool_13: 'Desk',\n                        robotis_icon_object_tool_14: 'Table',\n                        robotis_icon_object_tool_15: 'Chair',\n                        robotis_icon_object_tool_16: 'Bed',\n                        robotis_icon_object_tool_17: 'Tent',\n                        robotis_icon_object_tool_18: 'Plate',\n                        robotis_icon_object_tool_19: 'Soccer Ball',\n                        robotis_icon_object_tool_20: 'Bell',\n                        robotis_icon_object_tool_21: 'Watch',\n                        robotis_icon_object_tool_22: 'Shoes',\n                        robotis_icon_object_tool_23: 'Lamp',\n                        robotis_icon_object_tool_24: 'Radio',\n                        robotis_icon_object_tool_25: 'Banknote',\n                        robotis_icon_object_tool_26: 'Ruler',\n                        robotis_icon_object_tool_27: 'Camera',\n                        robotis_icon_object_tool_28: 'Spoon',\n                        robotis_icon_object_tool_29: 'Keyboard',\n                        robotis_icon_object_tool_30: 'Calendar',\n                        robotis_icon_object_tool_31: 'Knife',\n                        robotis_icon_object_tool_32: 'Balloon',\n                        robotis_icon_object_tool_33: 'Water Bottle',\n                        robotis_icon_object_tool_34: 'Wooden Stick (Horizontal)',\n                        robotis_icon_object_tool_35: 'Wooden Stick (Vertical)',\n                        robotis_icon_object_tool_36: 'Fishing Hook',\n                        robotis_icon_vehicle_number_1: 'Car',\n                        robotis_icon_vehicle_number_2: 'Bus',\n                        robotis_icon_vehicle_number_3: 'Truck',\n                        robotis_icon_vehicle_number_4: 'Jeep',\n                        robotis_icon_vehicle_number_5: 'Bicycle',\n                        robotis_icon_vehicle_number_6: 'Subway',\n                        robotis_icon_vehicle_number_7: 'Train',\n                        robotis_icon_vehicle_number_8: 'Airplane',\n                        robotis_icon_vehicle_number_9: 'Fighter Jet (Vertical)',\n                        robotis_icon_vehicle_number_10: 'Fighter Jet (Horizontal)',\n                        robotis_icon_vehicle_number_11: 'Rocket',\n                        robotis_icon_vehicle_number_12: 'Fishing Boat',\n                        robotis_icon_vehicle_number_13: 'Passenger Ship',\n                        robotis_icon_vehicle_number_14: 'Submarine (Left)',\n                        robotis_icon_vehicle_number_15: 'Submarine (Right)',\n                        robotis_icon_vehicle_number_16: 'Airplane (Left)',\n                        robotis_icon_vehicle_number_17: 'Airplane (Right)',\n                        robotis_icon_vehicle_number_18: 'Airplane (Top)',\n                        robotis_icon_vehicle_number_19: 'Spaceship (Left)',\n                        robotis_icon_vehicle_number_20: 'Spaceship (Right)',\n                        robotis_icon_vehicle_number_21: 'Spaceship (Top)',\n                        robotis_icon_vehicle_number_22: 'Dice (1)',\n                        robotis_icon_vehicle_number_23: 'Dice (2)',\n                        robotis_icon_vehicle_number_24: 'Dice (3)',\n                        robotis_icon_vehicle_number_25: 'Dice (4)',\n                        robotis_icon_vehicle_number_26: 'Dice (5)',\n                        robotis_icon_vehicle_number_27: 'Dice (6)',\n                        robotis_icon_vehicle_number_28: '0',\n                        robotis_icon_vehicle_number_29: '1',\n                        robotis_icon_vehicle_number_30: '2',\n                        robotis_icon_vehicle_number_31: '3',\n                        robotis_icon_vehicle_number_32: '4',\n                        robotis_icon_vehicle_number_33: '5',\n                        robotis_icon_vehicle_number_34: '6',\n                        robotis_icon_vehicle_number_35: '7',\n                        robotis_icon_vehicle_number_36: '8',\n                        robotis_icon_vehicle_number_37: '9',\n                        robotis_icon_vehicle_number_38: '10',\n                        robotis_icon_game_character_1: 'R-GEE(F)',\n                        robotis_icon_game_character_2: 'R-GEE(L)',\n                        robotis_icon_game_character_3: 'R-GEE(R)',\n                        robotis_icon_game_character_4: 'KODALA(F)',\n                        robotis_icon_game_character_5: 'KODALA(L))',\n                        robotis_icon_game_character_6: 'KODALA(R)',\n                        robotis_icon_game_character_7: 'Ghost',\n                        robotis_icon_game_character_8: 'Monster',\n                        robotis_icon_game_character_9: 'Virus',\n                        robotis_icon_game_character_10: 'Bacteria',\n                        robotis_icon_game_character_11: 'Flying R-GEE (L)',\n                        robotis_icon_game_character_12: 'Flying R-GEE (R)',\n                        robotis_icon_game_character_13: 'Flying R-GEE (F)',\n                        robotis_icon_game_character_14: 'Medal',\n                        robotis_icon_game_character_15: 'Money (G)',\n                        robotis_icon_game_character_16: 'Money ($)',\n                        robotis_icon_game_character_17: 'Heart',\n                        robotis_icon_game_character_18: 'Bomb',\n                        robotis_icon_game_character_19: 'Fire',\n                        robotis_icon_game_character_20: 'Cloud 1',\n                        robotis_icon_game_character_21: 'Cloud 2',\n                        robotis_icon_game_character_22: 'Shell 1',\n                        robotis_icon_game_character_23: 'Shell 2',\n                        robotis_icon_game_character_24: 'Cannon (Horizontal)',\n                        robotis_icon_game_character_25: 'Cannon (Vertical)',\n                        robotis_icon_game_character_26: 'Laser (Vertical)',\n                        robotis_icon_game_character_27: 'Laser (Horizontal)',\n                        robotis_icon_game_character_28: 'Arrow (Horizontal)',\n                        robotis_icon_game_character_29: 'Arrow (Vertical)',\n                        robotis_icon_game_character_30: 'Missile (Up)',\n                        robotis_icon_game_character_31: 'Missile (Down)',\n                        robotis_icon_game_character_32: 'Missile (Left)',\n                        robotis_icon_game_character_33: 'Missile (Right)',\n                        robotis_icon_game_character_34: 'Parachute',\n                        robotis_icon_game_character_35: 'Explosion 1',\n                        robotis_icon_game_character_36: 'Explosion 2',\n                        robotis_icon_game_character_37: 'Scope',\n                        robotis_icon_game_character_38: 'Scissors',\n                        robotis_icon_game_character_39: 'Rock',\n                        robotis_icon_game_character_40: 'Paper',\n                        robotis_icon_game_character_41: 'Walking Person 1',\n                        robotis_icon_game_character_42: 'Walking Person 2',\n                        robotis_icon_game_character_43: 'Running Person 1',\n                        robotis_icon_game_character_44: 'Running Person 2',                        \n                        robotis_speed_fast: 'Fast Speed',\n                        robotis_speed_midium: 'Medium Speed',\n                        robotis_speed_slow: 'Slow Speed',\n                        robotis_clockwise: 'Clockwise',\n                        robotis_counterclockwise: 'Counterclockwise',\n                        robotis_up: 'Lift',\n                        robotis_down: 'Lower',\n                        robotis_if_greater: 'If Greater',\n                        robotis_if_smaller: 'If Smaller',\n                        robotis_if_equal: 'If Equal',\n                        robotis_front_right: 'Front Right',\n                        robotis_front_left: 'Front Left',\n                        robotis_bottom_right: 'Bottom Right',\n                        robotis_bottom_left: 'Bottom Left',\n                        robotis_side_right: 'Right Edge',\n                        robotis_side_left: 'Left Edge',\n                        robotis_front_ir_sensor: 'Infrared Sensor',\n                        robotis_distance_sensor: 'Distance Sensor',\n                        robotis_front: 'Front',\n                        robotis_right: 'Right',\n                        robotis_left_wheel: 'Left Wheel',\n                        robotis_right_wheel: 'Right Wheel',\n                        robotis_beat_sound_8th_note: 'Eighth Note (♪)',\n                        robotis_beat_sound_dotted_8th_note: 'Dotted Eighth Note (♪.)',\n                        robotis_beat_sound_quarter_note: 'Quarter Note (♩)',\n                        robotis_beat_sound_dotted_quarter_note: 'Dotted Quarter Note (♩.)',\n                        robotis_beat_sound_half_note: 'Half Note (𝅗𝅥)',\n                        robotis_beat_sound_dotted_half_note: 'Dotted Half Note (𝅗𝅥.)',\n                        robotis_beat_sound_whole_note: 'Whole Note (𝅝)',\n                        robotis_beat_sound_dotted_note: 'Dotted Whole Note (𝅝.)',\n                        robotis_beat_rest_8th_note: 'Eighth Rest (𝄾)',\n                        robotis_beat_rest_dotted_8th_note: 'Dotted Eighth Rest (𝄾.)',\n                        robotis_beat_rest_quarter_note: 'Quarter Rest (𝄽)',\n                        robotis_beat_rest_dotted_quarter_note: 'Dotted Quarter Rest (𝄽.)',\n                        robotis_beat_rest_half_note: 'Half Rest (𝄼)',\n                        robotis_beat_rest_dotted_half_note: 'Dotted Half Rest (𝄼˙)',\n                        robotis_beat_rest_whole_note: 'Whole Rest (𝄻)',\n                        robotis_beat_rest_dotted_note: 'Dotted Whole Rest (𝄻˙)',\n                        robotis_line_cross_type_0: '|',\n                        robotis_line_cross_type_1: ' (Blank)',\n                        robotis_line_cross_type_5: '🞣',\n                        robotis_line_cross_type_6: '⏉',\n                        robotis_line_cross_type_7: '⊣',\n                        robotis_line_cross_type_8: '⊢',\n                        robotis_line_cross_type_9: '⏋',\n                        robotis_line_cross_type_10: '⎾',\n                        robotis_line_cross_type_11: '¦',\n                        robotis_line_cross_type_12: '︙',\n                        robotis_connected: 'Connected',\n                        robotis_disconnected: 'Not connected',\n                        robotis_ai_camera_mode_face_recognition: 'Face recognition',\n                        robotis_ai_camera_mode_object_tracking: 'Object tracking',\n                        robotis_ai_camera_mode_object_recognition: 'Object recognition',\n                        robotis_ai_camera_mode_line_recognition: 'Line tracking',\n                        robotis_ai_camera_mode_color_recognition: 'Color recognition',\n                        robotis_ai_camera_mode_tag_recognition: 'Tag recognition',\n                        robotis_ai_camera_mode_object_classification: 'Object classification',\n                        robotis_ai_camera_mode_expression_recognition: 'Expression recognition',\n                        robotis_ai_camera_target_face: 'Face',\n                        robotis_ai_camera_target_expression: 'Expression',\n                        robotis_ai_camera_target_object: 'Object',\n                        robotis_ai_camera_target_color: 'Color',\n                        robotis_ai_camera_target_tag: 'Tag',\n                        robotis_ai_camera_target_qr: 'QR',\n                        robotis_ai_camera_target_block: 'Rectangle',\n                        robotis_ai_camera_target_arrow: 'Arrow',\n                        robotis_ai_camera_center_block_center_x: 'Center X',\n                        robotis_ai_camera_center_block_center_y: 'Center Y',\n                        robotis_ai_camera_center_block_width: 'Width',\n                        robotis_ai_camera_center_block_height: 'Height',\n                        robotis_ai_camera_center_leared_id: 'Learned ID',\n                        robotis_ai_camera_center_arrow_origin_x: 'Origin X',\n                        robotis_ai_camera_center_arrow_origin_y: 'Origin Y',\n                        robotis_ai_camera_center_arrow_target_x: 'Target X',\n                        robotis_ai_camera_center_arrow_target_y: 'Target Y',\n\n                        robotis_plant_ripe: 'ripe in red',\n                        robotis_plant_unripe: 'green and unripe',\n                        robotis_harvest: 'Harvest',\n                        robotis_not_harvest: 'Skip harvesting',\n                    },\n                },\n            };\n        }\n        getBlocks() {\n            return {\n                robotis_robotai_lite_drive_simple: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '2'],\n                                [Lang.Blocks.robotis_moveL_in_place, '3'],\n                                [Lang.Blocks.robotis_moveR_in_place, '4'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [5, null, null],\n                        type: 'robotis_robotai_lite_drive_simple',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        const speed = script.getNumberValue('SPEED', script);\n                        const direction = script.getField('DIRECTION', script);\n\n                        const data_instruction = INST_WRITE;\n                        const data_address = 710;\n                        const data_length = 2;\n                        let data_value = 0;\n\n                        switch (direction) {\n                            case '1':\n                                data_value = speed * 256 + speed;\n                                break;\n                            case '2':\n                                data_value = (256 - speed) * 256 + (256 - speed);\n                                break;\n                            case '3':\n                                data_value = speed * 256 + (256 - speed);\n                                break;\n                            case '4':\n                                data_value = (256 - speed) * 256 + speed;\n                                break;\n                            default:\n                                data_value = 0;\n                                break;\n                        }\n\n                        const data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.go_simple(%1, %2)'],\n                    },\n                },\n                robotis_robotai_lite_drive_advanced: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['5'],\n                            },\n                            null,\n                            {\n                                type: 'number',\n                                params: ['5'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_drive_advanced',\n                    },\n                    paramsKeyMap: {\n                        LEFT_SPEED: 0,\n                        LEFT_DIRECTION: 1,\n                        RIGHT_SPEED: 2,\n                        RIGHT_DIRECTION: 3,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let leftSpeed = script.getNumberValue('LEFT_SPEED', script);\n                        const leftDirection = script.getField('LEFT_DIRECTION', script);\n                        let rightSpeed = script.getNumberValue('RIGHT_SPEED', script);\n                        const rightDirection = script.getField('RIGHT_DIRECTION', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        if (leftSpeed < -100) {\n                            leftSpeed = -100;\n                        } else if (leftSpeed > 100) {\n                            leftSpeed = 100;\n                        }\n\n                        if (rightSpeed < -100) {\n                            rightSpeed = -100;\n                        } else if (rightSpeed > 100) {\n                            rightSpeed = 100;\n                        }\n\n                        if (leftDirection == '2') {\n                            leftSpeed = -leftSpeed;\n                        }\n                        if (rightDirection == '2') {\n                            rightSpeed = -rightSpeed;\n                        }\n\n                        if (leftSpeed < 0) {\n                            leftSpeed = 256 + leftSpeed;\n                        }\n                        if (rightSpeed < 0) {\n                            rightSpeed = 256 + rightSpeed;\n                        }\n\n                        data_value = leftSpeed + rightSpeed * 256;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.go_advanced(%1, %2)'],\n                    },\n                },\n                robotis_robotai_lite_drive_seperate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '0'],\n                                [Lang.Blocks.robotis_both, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_direction_forward, '1'],\n                                [Lang.Blocks.robotis_direction_backward, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['5'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_drive_seperate',\n                    },\n                    paramsKeyMap: {\n                        WHEEL_SIDE: 0,\n                        WHEEL_SPEED: 1,\n                        WHEEL_DIRECTION: 2,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let wheelSide = script.getNumberValue('WHEEL_SIDE', script);\n                        let wheelSpeed = script.getNumberValue('WHEEL_SPEED', script);\n                        let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n\n                        let leftSpeed = 0;\n                        let rightSpeed = 0;\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        if (wheelSpeed < -100) {\n                            wheelSpeed = -100;\n                        } else if (wheelSpeed > 100) {\n                            wheelSpeed = 100;\n                        }\n\n                        wheelSpeed = (wheelSpeed + 256) % 256;\n                        if (wheelDirection == '2') {\n                            wheelSpeed = (256 - wheelSpeed) % 256;\n                        }\n\n                        if (wheelSide == 1) {\n                            leftSpeed = wheelSpeed;\n                            rightSpeed = 127; // 속도제어 안함\n                        } else if (wheelSide == 0) {\n                            leftSpeed = 127; // 속도제어 안함\n                            rightSpeed = wheelSpeed;\n                        } else {\n                            leftSpeed = wheelSpeed;\n                            rightSpeed = wheelSpeed;\n                        }\n\n                        data_value = leftSpeed + rightSpeed * 256;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            25 //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.go_seperate(%1, %2)'],\n                    },\n                },\n                robotis_robotai_lite_drive_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_direction_forward, '1'],\n                                [Lang.Blocks.robotis_direction_backward, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['15'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_drive_angle',\n                    },\n                    paramsKeyMap: {\n                        WHEEL_SIDE: 0,\n                        WHEEL_ANGLE: 1,\n                        WHEEL_DIRECTION: 2,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let wheelSide = script.getNumberValue('WHEEL_SIDE', script);\n                        let wheelAngle = script.getNumberValue('WHEEL_ANGLE', script);\n                        let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script);\n\n                        const data_instruction = INST_WRITE;\n                        let data_address = 580;\n                        let data_length = 8;\n                        let angleValue = 0;\n                        let id = 51 + wheelSide;\n                        let data_buf = [];\n                        let i = 0;\n                        let speed = 150;\n\n                        if (wheelDirection == '2') {\n                            wheelAngle = -wheelAngle;\n                        }\n\n                        wheelAngle = Math.round((wheelAngle * 4096) / 360);\n\n                        if (wheelAngle > 65535) {\n                            wheelAngle = 65535;\n                        } else if (wheelAngle < -65535) {\n                            wheelAngle = -65535;\n                        }\n\n                        angleValue = wheelAngle;\n                        if (wheelAngle < 0) {\n                            angleValue = 65536 + angleValue;\n                        }\n\n                        data_buf.push(id);\n                        data_buf.push(0);\n                        data_buf.push(speed % 256);\n                        data_buf.push(Math.floor(speed / 256));\n                        data_buf.push(angleValue % 256);\n                        data_buf.push(Math.floor(angleValue / 256) % 256);\n                        if (wheelAngle >= 0) {\n                            data_buf.push(0);\n                            data_buf.push(0);\n                        } else {\n                            data_buf.push(0xff);\n                            data_buf.push(0xff);\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.go_angle(%1, %2)'],\n                    },\n                },\n                robotis_robotai_lite_go_distance: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveF, '1'],\n                                [Lang.Blocks.robotis_moveB, '-1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['5'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_go_distance',\n                    },\n\n                    paramsKeyMap: {\n                        DISTANCE: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(entity, script) {\n                        let distance = script.getNumberValue('DISTANCE', script);\n                        let direction = script.getField('DIRECTION', script);\n\n                        if (distance > 1000) {\n                            distance = 1000;\n                        } else if (distance < -1000) {\n                            distance = -1000;\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 270;\n                        let data_length = 4;\n                        let data_value = Math.floor(10 * distance * direction);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        data_sendqueue.push([data_instruction, 66, 2, 50491]);\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 150 * Math.abs(distance) + 1200\n                            //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Robotailite.dxl_each_control(%1)'] },\n                },\n\n                robotis_robotai_lite_turn_angle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveL_in_place, '1'],\n                                [Lang.Blocks.robotis_moveR_in_place, '-1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['90'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_turn_angle',\n                    },\n\n                    paramsKeyMap: {\n                        ANGLE: 0,\n                        DIRECTION: 1,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(entity, script) {\n                        let angle = script.getNumberValue('ANGLE', script);\n                        let direction = script.getNumberValue('DIRECTION', script);\n\n                        angle *= direction;\n\n                        if (angle > 720) {\n                            angle = 720;\n                        } else if (angle < -720) {\n                            angle = -720;\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 270;\n                        let data_length = 4;\n                        let data_value = Math.floor(angle);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        data_sendqueue.push([data_instruction, 66, 2, 50492]);\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + Math.abs(angle) * 16 + 1500\n                            //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Robotailite.dxl_each_control(%1)'] },\n                },\n                robotis_robotai_lite_follow_line: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_slow, '1'],\n                                [Lang.Blocks.robotis_normal, '2'],\n                                [Lang.Blocks.robotis_fast, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_follow_line',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let speed_level = script.getNumberValue('SPEED', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 5200;\n                        let data_length = 1;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, speed_level],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.follow_line(%1)'],\n                    },\n                },\n                robotis_robotai_lite_stop_at_cross: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_line_cross_type_5, '5'],\n                                [Lang.Blocks.robotis_line_cross_type_6, '6'],\n                                [Lang.Blocks.robotis_line_cross_type_7, '7'],\n                                [Lang.Blocks.robotis_line_cross_type_8, '8'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_stop_at_cross',\n                    },\n                    paramsKeyMap: {\n                        CROSS: 0,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    async func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cross_type = script.getNumberValue('CROSS', script);\n                        let data_address = 5201;\n\n                        // max 10 seconds\n                        for (let i = 0; i < 100; i++) {\n                            await Entry.Utils.sleep(100);\n                            if (Entry.RobotisRobotaiLite.dataBuffer[data_address] == cross_type) {\n                                break;\n                            }\n                            if (Entry.engine.isState('stop') == true) {\n                                break;\n                            }\n                        }\n\n                        let data_sendqueue = [[INST_WRITE, 5200, 1, 0]];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.stop_at_cross(%1)'],\n                    },\n                },\n                robotis_robotai_lite_turn_at_line: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_moveL_in_place, '0'],\n                                [Lang.Blocks.robotis_moveR_in_place, '1'],\n                                [Lang.Blocks.robotis_moveU_in_place, '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_turn_at_line',\n                    },\n                    paramsKeyMap: {\n                        TURN_TYPE: 0,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let turn_type = script.getNumberValue('TURN_TYPE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 66;\n                        let data_length = 2;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, 50045 + turn_type],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.turn_at_line(%1)'],\n                    },\n                },\n                robotis_robotai_lite_drive_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_drive_stop',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'robotis_robotai_lite_move',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 710;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        let data_sendqueue = [\n                            [data_instruction, 5200, 1, 0],\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.stop(%1, %2)'],\n                    },\n                },\n                robotis_robotai_lite_securitybot_init: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_securitybot_init',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_sendqueue = [[INST_WRITE, 2110, 1, 1]];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            1100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.securitybot_init()'],\n                    },\n                },\n                robotis_robotai_lite_securitybot_hi: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_securitybot_hi',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_sendqueue = [[INST_WRITE, 2111, 1, 1]];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            3000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.securitybot_hi()'],\n                    },\n                },\n                robotis_robotai_lite_securitybot_alert: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_securitybot_alert',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_sendqueue = [[INST_WRITE, 2112, 1, 1]];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            3000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.securitybot_alert()'],\n                    },\n                },\n                robotis_robotai_lite_petbot_happy: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_petbot_happy',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_sendqueue = [[INST_WRITE, 2121, 1, 1]];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            7100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.petbot_happy()'],\n                    },\n                },\n                robotis_robotai_lite_petbot_sad: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_petbot_sad',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_sendqueue = [[INST_WRITE, 2122, 1, 1]];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            2500\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.petbot_sad()'],\n                    },\n                },\n\n                robotis_robotai_lite_farmbot_init: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_farmbot_init',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let data_sendqueue = [[INST_WRITE, 2130, 1, 1]];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            3000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotis.farmbot_init()'],\n                    },\n                },\n                robotis_robotai_lite_farmbot_seek: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_farmbot_seek',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_sendqueue = [[INST_WRITE, 2131, 1, 1]];\n                        return Entry.RobotisRobotaiLite.postCallReturn(script, data_sendqueue, 200);\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotis.farmbot_seek()'],\n                    },\n                },\n                robotis_robotai_lite_farmbot_plant_type: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_plant_ripe, '1'],\n                                [Lang.Blocks.robotis_plant_unripe, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_farmbot_plant_type',\n                    },\n                    paramsKeyMap: {\n                        TYPE: 0,\n                    },\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let compareValue = script.getNumberValue('TYPE');\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[2134];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotis.farmbot_is_type(%1)'],\n                    },\n                },\n                robotis_robotai_lite_farmbot_harvest_or_not_and_go: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_harvest, '1'],\n                                [Lang.Blocks.robotis_not_harvest, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_farmbot_harvest_or_not_and_go',\n                    },\n                    paramsKeyMap: {\n                        ACTION: 0,\n                    },\n                    class: 'robotis_robotai_lite_special',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let action = script.getNumberValue('ACTION', script);\n                        let address = 2132;\n                        let wait_time = 6000;\n\n                        switch (action) {\n                            case 1:\n                                address = 2132;\n                                wait_time = 6500;\n                                break;\n\n                            case 2:\n                                address = 2133;\n                                wait_time = 2100;\n                                break;\n                        }\n\n                        let data_sendqueue = [[INST_WRITE, address, 1, 1]];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            wait_time\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotis.farmbot_harvest_or_not_and_go(%1)'],\n                    },\n                },\n\n                robotis_robotai_lite_cm_ir_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_front_right, '360'],\n                                [Lang.Blocks.robotis_front_left, '362'],\n                                [Lang.Blocks.robotis_bottom_right, '364'],\n                                [Lang.Blocks.robotis_bottom_left, '366'],\n                                [Lang.Blocks.robotis_side_right, '368'],\n                                [Lang.Blocks.robotis_side_left, '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_cm_ir_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        const scope = script.executor.scope;\n\n                        const data_default_address = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_default_address];\n                        if (result == undefined) {\n                            result = rb100_last_valid_value[data_default_address];\n                        } else {\n                            rb100_last_valid_value[data_default_address] = result;\n                        }\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return Math.round((result % 65536) / 2);\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ir_value(%1)'],\n                    },\n                },\n                robotis_robotai_lite_cm_ir_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_front_right, '360'],\n                                [Lang.Blocks.robotis_front_left, '362'],\n                                [Lang.Blocks.robotis_bottom_right, '364'],\n                                [Lang.Blocks.robotis_bottom_left, '366'],\n                                [Lang.Blocks.robotis_side_right, '368'],\n                                [Lang.Blocks.robotis_side_left, '370'],\n                            ],\n                            value: '360',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_if_greater, '0'],\n                                [Lang.Blocks.robotis_if_smaller, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, 50, null],\n                        type: 'robotis_robotai_lite_cm_ir_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                        COMPARE_VAL: 1,\n                        COMPARE_OP: 2,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = script.getNumberValue('COMPARE_VAL');\n                        let compareOP = script.getNumberValue('COMPARE_OP');\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        result = Math.round((result % 65536) / 2);\n\n                        switch (compareOP) {\n                            case 0:\n                                return result > compareValue;\n                            case 1:\n                                return result < compareValue;\n                            default:\n                                return false;\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ir_compare(%1)'],\n                    },\n                },\n                robotis_robotai_lite_detectFrontObj: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_front, '0'],\n                                [Lang.Blocks.robotis_right, '1'],\n                                [Lang.Blocks.robotis_left, '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_detectFrontObj',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let direction = script.getNumberValue('DIRECTION');\n                        let ir_1 = 0;\n                        let ir_2 = 0;\n\n                        if (direction == 0) {\n                            ir_1 = Entry.RobotisRobotaiLite.dataBuffer[360];\n                            ir_2 = Entry.RobotisRobotaiLite.dataBuffer[362];\n                            if (ir_1 == undefined) {\n                                ir_1 = 0;\n                            }\n                            if (ir_2 == undefined) {\n                                ir_2 = 0;\n                            }\n                            return ir_1 > 100 || ir_2 > 100;\n                        } else if (direction == 1) {\n                            ir_1 = Entry.RobotisRobotaiLite.dataBuffer[368];\n                            if (ir_1 == undefined) {\n                                ir_1 = 0;\n                            }\n                            return ir_1 > 100;\n                        } else if (direction == 2) {\n                            ir_1 = Entry.RobotisRobotaiLite.dataBuffer[370];\n                            if (ir_1 == undefined) {\n                                ir_1 = 0;\n                            }\n                            return ir_1 > 100;\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.detectFrontObj()'],\n                    },\n                },\n                robotis_robotai_lite_cm_btn_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_blue, '47'],\n                                [Lang.Blocks.robotis_red, '44'],\n                            ],\n                            value: '47',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_cm_btn_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('VALUE');\n                        let compareValue = 1;\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.btn_value(%1)'],\n                    },\n                },\n                robotis_robotai_lite_cm_joystick_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_center, '0'],\n                                ['←', '1'],\n                                ['→', '2'],\n                                ['↑', '3'],\n                                ['↓', '4'],\n                                ['↖', '5'],\n                                ['↗', '6'],\n                                ['↙', '7'],\n                                ['↘', '8'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_cm_joystick_value',\n                    },\n                    paramsKeyMap: {\n                        COMPARE_VAL: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 50;\n                        let compareValue = script.getNumberValue('COMPARE_VAL', script);\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.joystick_value()'],\n                    },\n                },\n                robotis_robotai_lite_mic: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_mic',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    async func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 119;\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.mic()'],\n                    },\n                },\n                robotis_robotai_lite_detectSound_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_center, '0'],\n                                [Lang.Blocks.robotis_right, '255'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_detectSound_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 5031;\n                        let compareValue = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.detectSound_compare(%1)'],\n                    },\n                },\n                robotis_robotai_lite_imu: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['x', '78'], //72\n                                ['y', '80'], //74\n                                ['z', '82'], //76\n                            ],\n                            value: '78',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_acceleration, '0'], //72\n                                [Lang.Blocks.robotis_gyro, '6'], //74\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_imu',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                        MODE: 1,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address =\n                            script.getField('AXIS', script) - script.getField('MODE', script);\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.imu()'],\n                    },\n                },\n                robotis_robotai_lite_roll_pitch: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_roll, '70'], //72\n                                [Lang.Blocks.robotis_pitch, '88'], //74\n                            ],\n                            value: '70',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_roll_pitch',\n                    },\n                    paramsKeyMap: {\n                        AXIS: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('AXIS');\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.roll_pitch(%1)'],\n                    },\n                },\n                robotis_robotai_lite_environment_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_sensing_temperature, '28'],\n                                [Lang.Blocks.robotis_sensing_humidity, '29'],\n                                [Lang.Blocks.robotis_sensing_brightness, '30'],\n                                [Lang.Blocks.robotis_sensing_motion, '27'],\n                            ],\n                            value: '28',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_environment_value',\n                    },\n                    paramsKeyMap: {\n                        ADDR: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = script.getNumberValue('ADDR');\n\n                        let result = 0;\n\n                        switch (data_address) {\n                            case 28:\n                                result = Entry.RobotisRobotaiLite.pirTemperature[0];\n                                break;\n\n                            case 29:\n                                result = Entry.RobotisRobotaiLite.pirHumidity[0];\n                                break;\n\n                            case 30:\n                                result = Entry.RobotisRobotaiLite.pirBrightness[0];\n                                break;\n\n                            case 27:\n                                result = Entry.RobotisRobotaiLite.pirPir[0];\n                                break;\n                        }\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        } else {\n                            // temperature\n                            if (data_address == 28) {\n                                result = result % 256;\n                                if (result > 128) {\n                                    result = result - 256;\n                                }\n                            }\n                        }\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.environment_value(%1)'],\n                    },\n                },\n                robotis_robotai_lite_environment_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_sensing_temperature, '28'],\n                                [Lang.Blocks.robotis_sensing_humidity, '29'],\n                                [Lang.Blocks.robotis_sensing_brightness, '30'],\n                                [Lang.Blocks.robotis_sensing_motion, '27'],\n                            ],\n                            value: '28',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            value: '',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_if_greater, '0'],\n                                [Lang.Blocks.robotis_if_smaller, '1'],\n                                [Lang.Blocks.robotis_if_equal, '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: [0],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_environment_compare',\n                    },\n                    paramsKeyMap: {\n                        ADDR: 0,\n                        COMPARE_VAL: 1,\n                        COMPARE_OP: 2,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        let data_address = script.getNumberValue('ADDR');\n                        let compareValue = script.getNumberValue('COMPARE_VAL');\n                        let compareOP = script.getNumberValue('COMPARE_OP');\n\n                        let result = 0;\n\n                        switch (data_address) {\n                            case 28:\n                                result = Entry.RobotisRobotaiLite.pirTemperature[0];\n                                break;\n\n                            case 29:\n                                result = Entry.RobotisRobotaiLite.pirHumidity[0];\n                                break;\n\n                            case 30:\n                                result = Entry.RobotisRobotaiLite.pirBrightness[0];\n                                break;\n\n                            case 27:\n                                result = Entry.RobotisRobotaiLite.pirPir[0];\n                                break;\n                        }\n\n                        if (typeof result == 'undefined') {\n                            return false;\n                        }\n\n                        switch (compareOP) {\n                            case 0:\n                                return result > compareValue;\n                            case 1:\n                                return result < compareValue;\n                            case 2:\n                                return result == compareValue;\n                            default:\n                                return false;\n                        }\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.environment_compare(%1)'],\n                    },\n                },\n                robotis_robotai_lite_dxl_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left_wheel, '52'],\n                                [Lang.Blocks.robotis_right_wheel, '51'],\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '52',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_value_angle, '1'],\n                                [Lang.Blocks.robotis_dxl_value_velocity, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [52, null],\n                        type: 'robotis_robotai_lite_dxl_value',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        let dxl_id = script.getNumberValue('ID');\n                        //var data_type = script.getNumberValue('TYPE');\n\n                        let result = Entry.RobotisRobotaiLite.dxlPositions[dxl_id];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n                        result = 180 - Math.round((result * 360) / 4096);\n                        while (result < -180) {\n                            result += 360;\n                        }\n                        while (result > 180) {\n                            result -= 360;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.get_dxl_value(%1)'],\n                    },\n                },\n                robotis_robotai_lite_line_cross_compare: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_line_cross_type_5, '5'],\n                                [Lang.Blocks.robotis_line_cross_type_6, '6'],\n                                [Lang.Blocks.robotis_line_cross_type_7, '7'],\n                                [Lang.Blocks.robotis_line_cross_type_8, '8'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_line_cross_compare',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'robotis_robotai_lite_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 5201;\n                        let compareValue = script.getNumberValue('VALUE');\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.line_cross_compare(%1)'],\n                    },\n                },\n\n                robotis_robotai_lite_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_kkokdu, '3'],\n                                [Lang.Blocks.robotis_rla, '2'],\n                                [Lang.Blocks.robotis_rgee, '0'],\n                            ],\n                            value: '3',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '2817'],\n                                [Lang.Blocks.robotis_car_anim02, '2818'],\n                                [Lang.Blocks.robotis_car_anim03, '2819'],\n                                [Lang.Blocks.robotis_car_anim04, '2820'],\n                                [Lang.Blocks.robotis_car_anim05, '2821'],\n\n                                [Lang.Blocks.robotis_car_anim06, '2822'],\n                                //[Lang.Blocks.robotis_car_anim07, '2823'],\n                                [Lang.Blocks.robotis_car_anim08, '2824'],\n                                [Lang.Blocks.robotis_car_anim09, '2825'],\n                                [Lang.Blocks.robotis_car_anim10, '2826'],\n\n                                [Lang.Blocks.robotis_car_anim11, '2827'],\n                                [Lang.Blocks.robotis_car_anim12, '2828'],\n                                //[Lang.Blocks.robotis_car_anim13, '2829'],\n                                [Lang.Blocks.robotis_car_anim14, '2830'],\n                                [Lang.Blocks.robotis_car_anim15, '2831'],\n\n                                [Lang.Blocks.robotis_car_anim16, '2832'],\n                                [Lang.Blocks.robotis_car_anim17, '2833'],\n                                [Lang.Blocks.robotis_car_anim18, '2834'],\n                                [Lang.Blocks.robotis_car_anim19, '2835'],\n                            ],\n                            value: '2817',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_screen',\n                    },\n                    paramsKeyMap: {\n                        ROBOT_TYPE: 0,\n                        BACKGROUND: 1,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let robotType = script.getNumberValue('ROBOT_TYPE', script);\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue + robotType * 256;\n\n                        if (robotType == 0) {\n                            switch (screenValue) {\n                                case 2817:\n                                    data_value = 2841;\n                                    break;\n\n                                case 2818:\n                                    data_value = 2842;\n                                    break;\n\n                                case 2819:\n                                    data_value = 2820;\n                                    break;\n\n                                case 2820:\n                                    data_value = 2817;\n                                    break;\n\n                                case 2821:\n                                    data_value = 2819;\n                                    break;\n\n                                case 2822:\n                                    data_value = 2818;\n                                    break;\n\n                                //case 2823:\n                                //    break;\n\n                                case 2824:\n                                    data_value = 2826;\n                                    break;\n\n                                case 2825:\n                                    data_value = 2836;\n                                    break;\n\n                                case 2826:\n                                    data_value = 2837;\n                                    break;\n\n                                case 2827:\n                                    data_value = 2843;\n                                    break;\n\n                                case 2828:\n                                    data_value = 2831;\n                                    break;\n\n                                //case 2829:\n                                //    break;\n\n                                case 2830:\n                                    data_value = 2833;\n                                    break;\n\n                                case 2831:\n                                    data_value = 2834;\n                                    break;\n\n                                case 2832:\n                                    data_value = 2828;\n                                    break;\n\n                                case 2833:\n                                    data_value = 2827;\n                                    break;\n\n                                case 2834:\n                                    data_value = 2829;\n                                    break;\n\n                                case 2835:\n                                    data_value = 2840;\n                                    break;\n\n                                default:\n                                    data_value = 2841;\n                                    break;\n                            }\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: { js: [], py: ['Robotailite.screen(%1)'] },\n                },\n\n                robotis_robotai_lite_anim_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_kkokdu, '1'],\n                                [Lang.Blocks.robotis_rla, '0'],\n                                [Lang.Blocks.robotis_rgee, '-1'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_car_anim01, '30978'],\n                                [Lang.Blocks.robotis_car_anim02, '30981'],\n                                //[Lang.Blocks.robotis_car_anim03, '30982'],\n                                [Lang.Blocks.robotis_car_anim04, '30983'],\n                                [Lang.Blocks.robotis_car_anim05, '30984'],\n\n                                [Lang.Blocks.robotis_car_anim06, '30985'],\n                                [Lang.Blocks.robotis_car_anim07, '30986'],\n                                [Lang.Blocks.robotis_car_anim08, '30987'],\n                                [Lang.Blocks.robotis_car_anim09, '30988'],\n                                [Lang.Blocks.robotis_car_anim10, '30989'],\n\n                                [Lang.Blocks.robotis_car_anim11, '30990'],\n                                [Lang.Blocks.robotis_car_anim12, '30991'],\n                                //[Lang.Blocks.robotis_car_anim13, '30992'],\n                                [Lang.Blocks.robotis_car_anim14, '30993'],\n                                [Lang.Blocks.robotis_car_anim15, '30994'],\n\n                                [Lang.Blocks.robotis_car_anim16, '30995'],\n                                [Lang.Blocks.robotis_car_anim17, '30996'],\n                                [Lang.Blocks.robotis_car_anim18, '30997'],\n                                [Lang.Blocks.robotis_car_anim19, '30998'],\n                            ],\n                            value: '30978',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_anim_screen',\n                    },\n                    paramsKeyMap: {\n                        ROBOT_TYPE: 0,\n                        BACKGROUND: 1,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let robotType = script.getNumberValue('ROBOT_TYPE', script);\n                        let screenValue = script.getNumberValue('BACKGROUND', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = screenValue;\n\n                        if (robotType >= 0) {\n                            data_value += 256 * robotType;\n                        } else {\n                            switch (screenValue) {\n                                case 30978:\n                                    data_value = 30724;\n                                    break;\n\n                                case 30981:\n                                    data_value = 30761;\n                                    break;\n\n                                //case 30982:\n                                //    break;\n\n                                case 30983:\n                                    data_value = 30748;\n                                    break;\n\n                                case 30984:\n                                    data_value = 30750;\n                                    break;\n\n                                case 30985:\n                                    data_value = 30749;\n                                    break;\n\n                                //case 30986:\n                                //    break;\n\n                                case 30987:\n                                    data_value = 30739;\n                                    break;\n\n                                case 30988:\n                                    data_value = 30751;\n                                    break;\n\n                                case 30989:\n                                    data_value = 30752;\n                                    break;\n\n                                case 30990:\n                                    data_value = 30762;\n                                    break;\n\n                                case 30991:\n                                    data_value = 30736;\n                                    break;\n\n                                //case 30992:\n                                //    break;\n\n                                case 30993:\n                                    data_value = 30742;\n                                    break;\n\n                                case 30994:\n                                    data_value = 30743;\n                                    break;\n\n                                case 30995:\n                                    data_value = 30734;\n                                    break;\n\n                                case 30996:\n                                    data_value = 30733;\n                                    break;\n\n                                case 30997:\n                                    data_value = 30732;\n                                    break;\n\n                                case 30998:\n                                    data_value = 30760;\n                                    break;\n\n                                default:\n                                    data_value = 30724;\n                                    break;\n                            }\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY //+ 1000\n                        );\n                    },\n                    syntax: { js: [], py: ['Robotailite.animation_screen(%1)'] },\n                },\n                robotis_robotai_lite_icon_screen_food_plant: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_food_plant_1, '10496'],\n                                [Lang.Blocks.robotis_icon_food_plant_2, '10497'],\n                                [Lang.Blocks.robotis_icon_food_plant_3, '10498'],\n                                [Lang.Blocks.robotis_icon_food_plant_4, '10499'],\n                                [Lang.Blocks.robotis_icon_food_plant_5, '10500'],\n                                [Lang.Blocks.robotis_icon_food_plant_6, '10501'],\n                                [Lang.Blocks.robotis_icon_food_plant_7, '10502'],\n                                [Lang.Blocks.robotis_icon_food_plant_8, '10503'],\n                                [Lang.Blocks.robotis_icon_food_plant_9, '10504'],\n                                [Lang.Blocks.robotis_icon_food_plant_10, '10505'],\n                                [Lang.Blocks.robotis_icon_food_plant_11, '10506'],\n                                [Lang.Blocks.robotis_icon_food_plant_12, '10507'],\n                                [Lang.Blocks.robotis_icon_food_plant_13, '10508'],\n                                [Lang.Blocks.robotis_icon_food_plant_14, '10509'],\n                                [Lang.Blocks.robotis_icon_food_plant_15, '10510'],\n                                [Lang.Blocks.robotis_icon_food_plant_16, '10511'],\n                                [Lang.Blocks.robotis_icon_food_plant_17, '10512'],\n                                [Lang.Blocks.robotis_icon_food_plant_18, '10513'],\n                                [Lang.Blocks.robotis_icon_food_plant_19, '10514'],\n                                [Lang.Blocks.robotis_icon_food_plant_20, '10515'],\n                                [Lang.Blocks.robotis_icon_food_plant_21, '10516'],\n                                [Lang.Blocks.robotis_icon_food_plant_22, '10517'],\n                                [Lang.Blocks.robotis_icon_food_plant_23, '10518'],\n                                [Lang.Blocks.robotis_icon_food_plant_24, '10519'],\n                            ],\n                            value: '10496',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_icon_screen_food_plant',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.icon_screen_food_and_plant(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_robotai_lite_icon_screen_animal_human: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_animal_human_1, '10752'],\n                                [Lang.Blocks.robotis_icon_animal_human_2, '10753'],\n                                [Lang.Blocks.robotis_icon_animal_human_3, '10754'],\n                                [Lang.Blocks.robotis_icon_animal_human_4, '10755'],\n                                [Lang.Blocks.robotis_icon_animal_human_5, '10756'],\n                                [Lang.Blocks.robotis_icon_animal_human_6, '10757'],\n                                [Lang.Blocks.robotis_icon_animal_human_7, '10758'],\n                                [Lang.Blocks.robotis_icon_animal_human_8, '10759'],\n                                [Lang.Blocks.robotis_icon_animal_human_9, '10760'],\n                                [Lang.Blocks.robotis_icon_animal_human_10, '11787'],\n                                [Lang.Blocks.robotis_icon_animal_human_11, '11788'],\n                                [Lang.Blocks.robotis_icon_animal_human_12, '11789'],\n                                [Lang.Blocks.robotis_icon_animal_human_13, '11790'],\n                                [Lang.Blocks.robotis_icon_animal_human_14, '11805'],\n                                [Lang.Blocks.robotis_icon_animal_human_15, '11806'],\n                                [Lang.Blocks.robotis_icon_animal_human_16, '11807'],\n                                [Lang.Blocks.robotis_icon_animal_human_17, '11808'],\n                                [Lang.Blocks.robotis_icon_animal_human_18, '10761'],\n                                [Lang.Blocks.robotis_icon_animal_human_19, '10762'],\n                                [Lang.Blocks.robotis_icon_animal_human_20, '10763'],\n                                [Lang.Blocks.robotis_icon_animal_human_21, '10764'],\n                                [Lang.Blocks.robotis_icon_animal_human_22, '10765'],\n                                [Lang.Blocks.robotis_icon_animal_human_23, '10766'],\n                                [Lang.Blocks.robotis_icon_animal_human_24, '10767'],\n                                [Lang.Blocks.robotis_icon_animal_human_25, '10768'],\n                                [Lang.Blocks.robotis_icon_animal_human_26, '10769'],\n                                [Lang.Blocks.robotis_icon_animal_human_27, '10770'],\n                                [Lang.Blocks.robotis_icon_animal_human_28, '10771'],\n                                [Lang.Blocks.robotis_icon_animal_human_29, '10772'],\n                                [Lang.Blocks.robotis_icon_animal_human_30, '10773'],\n                                [Lang.Blocks.robotis_icon_animal_human_31, '10774'],\n                                [Lang.Blocks.robotis_icon_animal_human_32, '10775'],\n                                [Lang.Blocks.robotis_icon_animal_human_33, '10776'],\n                                [Lang.Blocks.robotis_icon_animal_human_34, '10777'],\n                            ],\n                            value: '10752',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_icon_screen_animal_human',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.icon_screen_animal_and_human(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_robotai_lite_icon_screen_object_tool: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_object_tool_1, '11008'],\n                                [Lang.Blocks.robotis_icon_object_tool_2, '11009'],\n                                [Lang.Blocks.robotis_icon_object_tool_3, '11010'],\n                                [Lang.Blocks.robotis_icon_object_tool_4, '11011'],\n                                [Lang.Blocks.robotis_icon_object_tool_5, '11012'],\n                                [Lang.Blocks.robotis_icon_object_tool_6, '11013'],\n                                [Lang.Blocks.robotis_icon_object_tool_7, '11014'],\n                                [Lang.Blocks.robotis_icon_object_tool_8, '11015'],\n                                [Lang.Blocks.robotis_icon_object_tool_9, '11016'],\n                                [Lang.Blocks.robotis_icon_object_tool_10, '11017'],\n                                [Lang.Blocks.robotis_icon_object_tool_11, '11018'],\n                                [Lang.Blocks.robotis_icon_object_tool_12, '11019'],\n                                [Lang.Blocks.robotis_icon_object_tool_13, '11020'],\n                                [Lang.Blocks.robotis_icon_object_tool_14, '11021'],\n                                [Lang.Blocks.robotis_icon_object_tool_15, '11022'],\n                                [Lang.Blocks.robotis_icon_object_tool_16, '11023'],\n                                [Lang.Blocks.robotis_icon_object_tool_17, '11024'],\n                                [Lang.Blocks.robotis_icon_object_tool_18, '11025'],\n                                [Lang.Blocks.robotis_icon_object_tool_19, '11026'],\n                                [Lang.Blocks.robotis_icon_object_tool_20, '11027'],\n                                [Lang.Blocks.robotis_icon_object_tool_21, '11028'],\n                                [Lang.Blocks.robotis_icon_object_tool_22, '11029'],\n                                [Lang.Blocks.robotis_icon_object_tool_23, '11030'],\n                                [Lang.Blocks.robotis_icon_object_tool_24, '11031'],\n                                [Lang.Blocks.robotis_icon_object_tool_25, '11032'],\n                                [Lang.Blocks.robotis_icon_object_tool_26, '11033'],\n                                [Lang.Blocks.robotis_icon_object_tool_27, '11034'],\n                                [Lang.Blocks.robotis_icon_object_tool_28, '11035'],\n                                [Lang.Blocks.robotis_icon_object_tool_29, '11036'],\n                                [Lang.Blocks.robotis_icon_object_tool_30, '11037'],\n                                [Lang.Blocks.robotis_icon_object_tool_31, '11038'],\n                                [Lang.Blocks.robotis_icon_object_tool_32, '11039'],\n                                [Lang.Blocks.robotis_icon_object_tool_33, '11040'],\n                                [Lang.Blocks.robotis_icon_object_tool_34, '11801'],\n                                [Lang.Blocks.robotis_icon_object_tool_35, '11802'],\n                                [Lang.Blocks.robotis_icon_object_tool_36, '11809'],\n                            ],\n                            value: '11008',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_icon_screen_object_tool',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.icon_screen_object_and_tool(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_robotai_lite_icon_screen_vehicle_number: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_vehicle_number_1, '11264'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_2, '11265'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_3, '11266'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_4, '11267'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_5, '11268'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_6, '11269'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_7, '11270'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_8, '11271'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_9, '11272'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_10, '11273'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_11, '11274'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_12, '11275'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_13, '11276'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_14, '11776'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_15, '11777'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_16, '11778'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_17, '11779'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_18, '11780'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_19, '11781'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_20, '11782'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_21, '11783'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_22, '11277'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_23, '11278'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_24, '11279'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_25, '11280'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_26, '11281'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_27, '11282'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_28, '11283'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_29, '11284'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_30, '11285'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_31, '11286'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_32, '11287'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_33, '11288'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_34, '11289'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_35, '11290'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_36, '11291'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_37, '11292'],\n                                [Lang.Blocks.robotis_icon_vehicle_number_38, '11293'],\n                            ],\n                            value: '11264',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_icon_screen_vehicle_number',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.icon_screen_vehicle_and_number(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_robotai_lite_icon_screen_game_character: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_icon_game_character_1, '11520'], // 알쥐(정면)\n                                [Lang.Blocks.robotis_icon_game_character_2, '11521'], // 알쥐(왼쪽)\n                                [Lang.Blocks.robotis_icon_game_character_3, '11522'], // 알쥐(오른쪽)\n                                [Lang.Blocks.robotis_icon_game_character_4, '11523'], // 알라(정면)\n                                [Lang.Blocks.robotis_icon_game_character_5, '11524'], // 알라(왼쪽)\n                                [Lang.Blocks.robotis_icon_game_character_6, '11525'], // 알라(오른쪽)\n                                [Lang.Blocks.robotis_icon_game_character_7, '11526'], // 유령\n                                [Lang.Blocks.robotis_icon_game_character_8, '11527'], // 괴물\n                                [Lang.Blocks.robotis_icon_game_character_9, '11528'], // 바이러스\n                                [Lang.Blocks.robotis_icon_game_character_10, '11529'], // 세균\n                                [Lang.Blocks.robotis_icon_game_character_11, '11784'], // 나는 알쥐(L)\n                                [Lang.Blocks.robotis_icon_game_character_12, '11785'], // 나는 알쥐(R)\n                                [Lang.Blocks.robotis_icon_game_character_13, '11786'], // 나는 알쥐(U)\n                                [Lang.Blocks.robotis_icon_game_character_14, '11530'], // 메달\n                                [Lang.Blocks.robotis_icon_game_character_15, '11531'], // 돈(G)\n                                [Lang.Blocks.robotis_icon_game_character_16, '11532'], // 돈($)\n                                [Lang.Blocks.robotis_icon_game_character_17, '11533'], // 하트\n                                [Lang.Blocks.robotis_icon_game_character_18, '11534'], // 포탄\n                                [Lang.Blocks.robotis_icon_game_character_19, '11535'], // 불\n                                [Lang.Blocks.robotis_icon_game_character_20, '11803'], // 구름1\n                                [Lang.Blocks.robotis_icon_game_character_21, '11804'], // 구름2\n                                [Lang.Blocks.robotis_icon_game_character_22, '11536'], // 포탄1\n                                [Lang.Blocks.robotis_icon_game_character_23, '11791'], // 포탄2\n                                [Lang.Blocks.robotis_icon_game_character_24, '11537'], // 대포(수평)\n                                [Lang.Blocks.robotis_icon_game_character_25, '11538'], // 대포(수직)\n                                [Lang.Blocks.robotis_icon_game_character_27, '11540'], // 레이저(수평)\n                                [Lang.Blocks.robotis_icon_game_character_26, '11539'], // 레이저(수직)\n                                [Lang.Blocks.robotis_icon_game_character_28, '11541'], // 화살(수평)\n                                [Lang.Blocks.robotis_icon_game_character_29, '11542'], // 화살(수직)\n                                [Lang.Blocks.robotis_icon_game_character_30, '11792'], // 미사일(U)\n                                [Lang.Blocks.robotis_icon_game_character_31, '11793'], // 미사일(D)\n                                [Lang.Blocks.robotis_icon_game_character_32, '11794'], // 미사일(L)\n                                [Lang.Blocks.robotis_icon_game_character_33, '11795'], // 미사일(R)\n                                [Lang.Blocks.robotis_icon_game_character_34, '11796'], // 낙하산\n                                [Lang.Blocks.robotis_icon_game_character_35, '11543'], // 폭발1\n                                [Lang.Blocks.robotis_icon_game_character_36, '11544'], // 폭발2\n                                [Lang.Blocks.robotis_icon_game_character_37, '11810'], // 조준경\n                                [Lang.Blocks.robotis_icon_game_character_38, '11545'], // 가위\n                                [Lang.Blocks.robotis_icon_game_character_39, '11546'], // 바위\n                                [Lang.Blocks.robotis_icon_game_character_40, '11547'], // 보\n                                [Lang.Blocks.robotis_icon_game_character_41, '11797'], // 걷는 사람1\n                                [Lang.Blocks.robotis_icon_game_character_42, '11798'], // 걷는 사람2\n                                [Lang.Blocks.robotis_icon_game_character_43, '11799'], // 뛰는 사람1\n                                [Lang.Blocks.robotis_icon_game_character_44, '11800'], // 뛰는 사람2\n                            ],\n                            value: '11520',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            50,\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_icon_screen_game_character',\n                    },\n                    paramsKeyMap: {\n                        ICON: 0,\n                        X: 1,\n                        Y: 2,\n                        SIZE: 3,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let iconNum = script.getField('ICON', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let size = script.getNumberValue('SIZE', script) * 2;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 166;\n                        let data_length = 2;\n                        let data_value = 10496;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (size < 0) {\n                            size = 0;\n                        } else if (size > 400) {\n                            size = 400;\n                        }\n\n                        data_value = iconNum;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 130, 2, x],\n                            [INST_WRITE, 132, 2, y],\n                            [INST_WRITE, 149, 2, size],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.icon_screen_game_and_character(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_robotai_lite_text_screen: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_screen_text_font_small, '0'],\n                                [Lang.Blocks.robotis_screen_text_font_big, '1'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            ' ',\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_text_screen',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        X: 1,\n                        Y: 2,\n                        FONT: 3,\n                        COLOR: 4,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let text = script.getStringValue('TEXT', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let font = script.getNumberValue('FONT', script);\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 900;\n                        let data_length = 2;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        let encoder = new TextEncoder('utf-8');\n                        let byteArray = encoder.encode(text);\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(font);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(color);\n                        data_buf.push(byteArray.length);\n                        for (i = 0; i < byteArray.length; i++) {\n                            data_buf.push(byteArray[i]);\n                        }\n\n                        data_length = 9 + byteArray.length;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 200\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.text_screen(%1,%2,%3,%4,%5)'],\n                    },\n                },\n                robotis_robotai_lite_pixel: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_pixel',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        COLOR: 2,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 130;\n                        let data_length = 11;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        data_buf.push(color);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 161, 2, 1 * 256 + 8],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.pixel(%1,%2,%3)'],\n                    },\n                },\n                robotis_robotai_lite_text_screen_redraw: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            ' ',\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            null,\n                        ],\n                        type: 'robotis_robotai_lite_text_screen_redraw',\n                    },\n                    paramsKeyMap: {\n                        TEXT: 0,\n                        X: 1,\n                        Y: 2,\n                        COLOR: 3,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let text = script.getStringValue('TEXT', script);\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let font = 0;\n                        let color = script.getNumberValue('COLOR', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        if (x < -160) {\n                            x = -160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = -120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        let encoder = new TextEncoder('utf-8');\n                        let byteArray = encoder.encode(text);\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(font);\n                        data_buf.push(1);\n                        data_buf.push(bg_color);\n                        data_buf.push(color);\n                        data_buf.push(byteArray.length);\n                        for (i = 0; i < byteArray.length; i++) {\n                            data_buf.push(byteArray[i]);\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 900;\n                        let data_length = 9 + byteArray.length;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.text_screen_redraw(%1,%2,%3,%4)'],\n                    },\n                },\n                robotis_robotai_lite_LCDBright: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [50],\n                        type: 'robotis_robotai_lite_LCDBright',\n                    },\n                    paramsKeyMap: {\n                        BRIGHT: 0,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let bright = script.getNumberValue('BRIGHT', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 180;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        bright = Math.min(Math.max(bright, 0), 100);\n\n                        data_value = bright;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.LCDBright(%1)'],\n                    },\n                },\n                robotis_robotai_lite_LCDColor: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '224',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_LCDColor',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let color = script.getNumberValue('COLOR', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 163;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = color;\n                        bg_color = color;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 163, 2, 2817],\n                            [data_instruction, data_address, data_length, data_value],\n                            [INST_WRITE, 162, 1, 1],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.LCDColor(%1)'],\n                    },\n                },\n                robotis_robotai_lite_LCD_Flash: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '224',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_red, '224'],\n                                [Lang.Blocks.robotis_orange, '244'],\n                                [Lang.Blocks.robotis_yellow, '252'],\n                                [Lang.Blocks.robotis_green, '28'],\n                                [Lang.Blocks.robotis_blue, '3'],\n                                [Lang.Blocks.robotis_darkblue, '2'],\n                                [Lang.Blocks.robotis_purple, '130'],\n                                [Lang.Blocks.robotis_brown, '173'],\n                                [Lang.Blocks.robotis_black, '0'],\n                                [Lang.Blocks.robotis_white, '255'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [0.3, '3'],\n                                [0.4, '4'],\n                                [0.5, '5'],\n                                [0.6, '6'],\n                                [0.7, '7'],\n                                [0.8, '8'],\n                                [0.9, '9'],\n                                [1.0, '10'],\n                                [1.1, '11'],\n                                [1.2, '12'],\n                                [1.3, '13'],\n                                [1.4, '14'],\n                                [1.5, '15'],\n                                [1.6, '16'],\n                                [1.7, '17'],\n                                [1.8, '18'],\n                                [1.9, '19'],\n                                [2.0, '20'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_LCD_Flash',\n                    },\n                    paramsKeyMap: {\n                        COLOR_ON: 0,\n                        COLOR_OFF: 1,\n                        PERIOD: 2,\n                    },\n                    class: 'robotis_robotai_lite_lcd',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        const color_on = script.getNumberValue('COLOR_ON', script);\n                        const color_off = script.getNumberValue('COLOR_OFF', script);\n                        const period = script.getNumberValue('PERIOD', script);\n                        const colors = color_on + (color_off << 8);\n\n                        // 0x8000: use flashing mode,\n                        // (period << 8): on time (0.1 sec)\n                        // period: off time (0.1 sec)\n                        const time_parameter = 0x8000 + (period << 8) + period;\n\n                        let data_sendqueue = [\n                            [INST_WRITE, 158, 2, colors],\n                            [INST_WRITE, 163, 2, time_parameter],\n                        ];\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY + 100\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.LCD_Flash(%1, %2, %3)'],\n                    },\n                },\n\n                robotis_robotai_lite_cm_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left, '1'],\n                                [Lang.Blocks.robotis_right, '2'],\n                                [Lang.Blocks.robotis_both, '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_common_on, '1'],\n                                [Lang.Blocks.robotis_common_off, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'robotis_robotai_lite_cm_led',\n                    },\n                    paramsKeyMap: {\n                        RB_LED: 0,\n                        VALUE: 1,\n                    },\n                    class: 'robotis_robotai_lite_led',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmLed = script.getField('RB_LED', script);\n                        let value = script.getField('VALUE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 40;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        if (cmLed == 1) {\n                            data_value = 200 * value;\n                        } else if (cmLed == 2) {\n                            data_address = 41;\n                            data_value = 200 * value;\n                        } else if (cmLed == 3) {\n                            data_address = 40;\n                            data_length = 2;\n                            data_value = 200 * 257 * value;\n                        } else {\n                            data_value = value * cmLed;\n                        }\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Robotailite.led(%1, %2)'] },\n                },\n                robotis_robotai_lite_cm_led_pattern: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_pattern1, '11'],\n                                [Lang.Blocks.robotis_pattern2, '21'],\n                                [Lang.Blocks.robotis_pattern3, '31'],\n                            ],\n                            value: '11',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_speed_fast, '0'],\n                                [Lang.Blocks.robotis_speed_midium, '1'],\n                                [Lang.Blocks.robotis_speed_slow, '2'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'robotis_robotai_lite_cm_led_pattern',\n                    },\n                    paramsKeyMap: {\n                        PATTERN: 0,\n                        SPEED: 1,\n                    },\n                    class: 'robotis_robotai_lite_led',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let pattern = script.getNumberValue('PATTERN', script);\n                        let speed = script.getNumberValue('SPEED', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 40;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = pattern + speed;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Robotailite.led_pattern(%1, %2)'] },\n                },\n\n                robotis_robotai_lite_dxl_set_mode: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left_wheel, '52'],\n                                [Lang.Blocks.robotis_right_wheel, '51'],\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '52',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_mode_joint, '3'],\n                                [Lang.Blocks.robotis_dxl_mode_wheel, '1'],\n                                [Lang.Blocks.robotis_dxl_mode_multi_turn, '4'],\n                            ],\n                            value: '3',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['52', null, null],\n                        type: 'robotis_robotai_lite_dxl_set_mode',\n                    },\n                    paramsKeyMap: {\n                        DXL_ID: 0,\n                        DXL_MODE: 1,\n                    },\n                    class: 'robotis_robotai_lite_dxl',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let dxl_id = script.getNumberValue('DXL_ID', script);\n                        let dxl_mode = script.getField('DXL_MODE', script);\n\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                        let data_address = 0;\n                        let data_length = 0;\n                        let data_value = 0;\n\n                        data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[0];\n                        data_length = Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[1];\n\n                        data_value = dxl_mode;\n\n                        let data_sendqueue = [\n                            [\n                                data_instruction,\n                                Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0],\n                                Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1],\n                                dxl_id,\n                                0,\n                            ],\n                            [data_instruction, data_address, data_length, dxl_id, data_value],\n                            [\n                                data_instruction,\n                                Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0],\n                                Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1],\n                                dxl_id,\n                                1,\n                            ],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.set_dxl_mode(%1, %2)'],\n                    },\n                },\n                robotis_robotai_lite_dxl_each_control: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left_wheel, '52'],\n                                [Lang.Blocks.robotis_right_wheel, '51'],\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '52',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            '52',\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['1'],\n                            },\n                        ],\n                        type: 'robotis_robotai_lite_dxl_each_control',\n                    },\n\n                    paramsKeyMap: {\n                        DXLNUM: 0,\n                        ANGLE: 1,\n                        TIME: 2,\n                    },\n                    class: 'robotis_robotai_lite_dxl',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(entity, script) {\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                        let data_address = 0;\n                        let data_length = 0;\n\n                        data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0];\n                        data_length =\n                            Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] +\n                            Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1];\n\n                        let dxlID = script.getField('DXLNUM', script);\n                        let angle = script.getNumberValue('ANGLE', script);\n                        let time = script.getNumberValue('TIME', script) * 1000;\n                        let data_buf = [];\n\n                        let engValue = 2048;\n                        engValue = Math.floor(2048 - Math.round(angle * 4096) / 360);\n                        let velocity = 0;\n\n                        if (time == 0) {\n                            velocity = 0;\n                        } else {\n                            velocity = Math.round(\n                                Math.floor(\n                                    (60 *\n                                        Math.abs(\n                                            engValue - Entry.RobotisRobotaiLite.dxlPositions[dxlID]\n                                        ) *\n                                        1000) /\n                                        4096 /\n                                        time\n                                ) / 0.229\n                            );\n                        }\n\n                        data_buf.push(velocity % 256);\n                        data_buf.push(Math.floor(velocity / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n\n                        data_buf.push(engValue % 256);\n                        data_buf.push(Math.floor(engValue / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, dxlID, data_buf],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            time + DEFAULT_DELAY\n                            //DEFAULT_DELAY\n                        );\n                    },\n                    syntax: { js: [], py: ['Robotailite.dxl_each_control(%1,%2,%3)'] },\n                },\n                robotis_robotai_lite_dxl_set_position: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left_wheel, '52'],\n                                [Lang.Blocks.robotis_right_wheel, '51'],\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '52',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['52', '50', '0', null],\n                        type: 'robotis_robotai_lite_dxl_set_position',\n                    },\n                    paramsKeyMap: {\n                        DXL_ID: 0,\n                        DXL_SPEED: 1,\n                        DXL_ANGLE: 2,\n                    },\n                    class: 'robotis_robotai_lite_dxl',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let dxl_id = script.getNumberValue('DXL_ID', script);\n                        let dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                        let dxl_angle = script.getNumberValue('DXL_ANGLE', script);\n\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                        let data_address = 0;\n                        let data_length = 0;\n                        let data_buf = [];\n\n                        data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0];\n                        data_length =\n                            Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] +\n                            Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1];\n\n                        if (dxl_speed < 0) {\n                            dxl_speed = 0;\n                        } else if (dxl_speed > 100) {\n                            dxl_speed = 100;\n                        }\n\n                        data_buf.push((dxl_speed * 10) % 256);\n                        data_buf.push(Math.floor((dxl_speed * 10) / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n\n                        if (dxl_angle < -179) {\n                            dxl_angle = -179;\n                        } else if (dxl_angle > 180) {\n                            dxl_angle = 180;\n                        }\n\n                        dxl_angle = 180 - dxl_angle;\n\n                        data_buf.push(Math.floor((dxl_angle * 4096) / 360) % 256);\n                        data_buf.push(Math.floor((dxl_angle * 4096) / 360 / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, dxl_id, data_buf],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.set_dxl_position(%1, %2, %3)'],\n                    },\n                },\n                robotis_robotai_lite_dxl_set_rotate: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left_wheel, '52'],\n                                [Lang.Blocks.robotis_right_wheel, '51'],\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '52',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_rotate_cw, '1'],\n                                [Lang.Blocks.robotis_dxl_rotate_ccw, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_move_rotate, '1'],\n                                [Lang.Blocks.robotis_dxl_move_stop, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['52', '50', null, null, null],\n                        type: 'robotis_robotai_lite_dxl_set_rotate',\n                    },\n                    paramsKeyMap: {\n                        DXL_ID: 0,\n                        DXL_SPEED: 1,\n                        DXL_DIRECTION: 2,\n                        DXL_MOVE: 3,\n                    },\n                    class: 'robotis_robotai_lite_dxl',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let dxl_id = script.getNumberValue('DXL_ID', script);\n                        let dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                        let dxl_direction = script.getNumberValue('DXL_DIRECTION', script);\n                        let dxl_move = script.getNumberValue('DXL_MOVE', script);\n\n                        let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE;\n                        let data_address = 0;\n                        let data_length = 0;\n                        let data_value = 0;\n\n                        data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[0];\n                        data_length = Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[1];\n\n                        if (dxl_speed < 0) {\n                            dxl_speed = 0;\n                        } else if (dxl_speed > 100) {\n                            dxl_speed = 100;\n                        }\n\n                        data_value = dxl_speed * 10;\n\n                        // cw일 경우 음수처리\n                        if (dxl_direction == 1) {\n                            data_value = -data_value;\n                        }\n\n                        // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대\n                        if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) {\n                            data_value = -data_value;\n                        }\n\n                        data_value = data_value * dxl_move;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, dxl_id, data_value],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.set_dxl_rotate(%1, %2, %3, %4)'],\n                    },\n                },\n                robotis_robotai_lite_dxl_set_multiturn_round: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_left_wheel, '52'],\n                                [Lang.Blocks.robotis_right_wheel, '51'],\n                                ['ID 1', '1'],\n                                ['ID 2', '2'],\n                                ['ID 3', '3'],\n                                ['ID 4', '4'],\n                                ['ID 5', '5'],\n                                ['ID 6', '6'],\n                                ['ID 7', '7'],\n                                ['ID 8', '8'],\n                            ],\n                            value: '52',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dxl_rotate_cw, '1'],\n                                [Lang.Blocks.robotis_dxl_rotate_ccw, '2'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: ['52', '50', '1', null, null],\n                        type: 'robotis_robotai_lite_dxl_set_multiturn_round',\n                    },\n                    paramsKeyMap: {\n                        DXL_ID: 0,\n                        DXL_SPEED: 1,\n                        DXL_ROUND: 2,\n                        DXL_DIRECTION: 3,\n                    },\n                    class: 'robotis_robotai_lite_dxl',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let dxl_id = script.getNumberValue('DXL_ID', script);\n                        let dxl_speed = script.getNumberValue('DXL_SPEED', script);\n                        let dxl_round = script.getNumberValue('DXL_ROUND', script);\n                        let dxl_direction = script.getNumberValue('DXL_DIRECTION', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address_1 = 0;\n                        let data_length_1 = 0;\n                        let data_value_1 = 0;\n                        let data_address_2 = 0;\n                        let data_length_2 = 0;\n                        let data_value_2 = 0;\n                        let data_address_3 = 0;\n                        let data_length_3 = 0;\n                        let data_value_3 = 0;\n\n                        let data_sendqueue = [];\n                        let result = undefined;\n\n                        if (dxl_id == 0 || dxl_speed == 0 || dxl_round == 0) {\n                            return;\n                        }\n\n                        data_address_1 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[0];\n                        data_length_1 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[1];\n\n                        data_address_2 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[0];\n                        data_length_2 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[1];\n\n                        if (dxl_speed < 0) {\n                            dxl_speed = 0;\n                        } else if (dxl_speed > 100) {\n                            dxl_speed = 100;\n                        }\n\n                        data_value_2 = dxl_speed * 10;\n\n                        data_address_3 =\n                            Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[0];\n                        data_length_3 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[1];\n\n                        if (dxl_round < 0) {\n                            dxl_round = 0;\n                        } else if (dxl_round > 100) {\n                            dxl_round = 100;\n                        }\n\n                        // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대\n                        if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) {\n                            dxl_round = -dxl_round;\n                        }\n\n                        data_value_3 = dxl_round * 4096;\n\n                        if (dxl_direction == 1) {\n                            data_value_3 = -data_value_3;\n                        }\n\n                        data_sendqueue = [\n                            [data_instruction, data_address_1, data_length_1, dxl_id],\n                            [data_instruction, data_address_2, data_length_2, data_value_2],\n                            [data_instruction, data_address_3, data_length_3, data_value_3],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.set_dxl_multiturn_round(%1, %2, %3, %4)'],\n                    },\n                },\n\n                robotis_robotai_lite_scale_simple: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.General.note_c + '', '1'],\n                                [Lang.General.note_c + '#', '2'],\n                                [Lang.General.note_d + '', '3'],\n                                [Lang.General.note_d + '#', '4'],\n                                [Lang.General.note_e + '', '5'],\n                                [Lang.General.note_f + '', '6'],\n                                [Lang.General.note_f + '#', '7'],\n                                [Lang.General.note_g + '', '8'],\n                                [Lang.General.note_g + '#', '9'],\n                                [Lang.General.note_a + '', '10'],\n                                [Lang.General.note_a + '#', '11'],\n                                [Lang.General.note_b + '', '12'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_beat_sound_8th_note, '3'],\n                                [Lang.Blocks.robotis_beat_sound_dotted_8th_note, '4'],\n                                [Lang.Blocks.robotis_beat_sound_quarter_note, '5'],\n                                [Lang.Blocks.robotis_beat_sound_dotted_quarter_note, '6'],\n                                [Lang.Blocks.robotis_beat_sound_half_note, '7'],\n                                [Lang.Blocks.robotis_beat_sound_dotted_half_note, '8'],\n                                [Lang.Blocks.robotis_beat_sound_whole_note, '9'],\n                                [Lang.Blocks.robotis_beat_sound_dotted_note, '10'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null, null],\n                        type: 'robotis_robotai_lite_scale_simple',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_OCTAV: 0,\n                        CM_BUZZER_INDEX: 1,\n                        CM_BUZZER_NOTE: 2,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                        let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                        let cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script);\n                        let cmBuzzerTime = 0;\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 0;\n                        let data_value = 0;\n                        let interval = 0;\n                        let data_buf = [];\n\n                        switch (cmBuzzerNote) {\n                            case 3:\n                                cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute / 2);\n                                break;\n\n                            case 4:\n                                cmBuzzerTime = Math.round(\n                                    ((60 * 1000) / beat_per_minute / 2) * 1.5\n                                );\n                                break;\n\n                            case 5:\n                                cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute);\n                                break;\n\n                            case 6:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 1.5);\n                                break;\n\n                            case 7:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 2);\n                                break;\n\n                            case 8:\n                                cmBuzzerTime = Math.round(\n                                    ((60 * 1000) / beat_per_minute) * 2 * 1.5\n                                );\n                                break;\n\n                            case 9:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 4);\n                                break;\n\n                            case 10:\n                                cmBuzzerTime = Math.round(\n                                    ((60 * 1000) / beat_per_minute) * 4 * 1.5\n                                );\n                                break;\n                        }\n\n                        data_address = 740;\n                        // data_value_1 = cmBuzzerTime * 10;\n                        // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                        data_value = cmBuzzerTime;\n                        if (data_value < 0) {\n                            data_value = 0;\n                        }\n                        if (data_value > 50000) {\n                            data_value = 50000;\n                        }\n\n                        data_buf.push(data_value % 256);\n                        data_buf.push(Math.floor(data_value / 256));\n\n                        data_value = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n                        data_buf.push(Math.floor(data_value));\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [[data_instruction, data_address, 3, data_buf]];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.scale_simple(%1, %2, %3)'],\n                    },\n                },\n                robotis_robotai_lite_scale_advanced: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                            ],\n                            value: '4',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.General.note_c + '', '1'],\n                                [Lang.General.note_c + '#', '2'],\n                                [Lang.General.note_d + '', '3'],\n                                [Lang.General.note_d + '#', '4'],\n                                [Lang.General.note_e + '', '5'],\n                                [Lang.General.note_f + '', '6'],\n                                [Lang.General.note_f + '#', '7'],\n                                [Lang.General.note_g + '', '8'],\n                                [Lang.General.note_g + '#', '9'],\n                                [Lang.General.note_a + '', '10'],\n                                [Lang.General.note_a + '#', '11'],\n                                [Lang.General.note_b + '', '12'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, 1, null],\n                        type: 'robotis_robotai_lite_scale_advanced',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_OCTAV: 0,\n                        CM_BUZZER_INDEX: 1,\n                        CM_BUZZER_BEAT: 2,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script);\n                        let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script);\n                        let cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script);\n                        let cmBuzzerTime = 0;\n\n                        cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address_1 = 0;\n                        let data_length_1 = 0;\n                        let data_value_1 = 0;\n                        let data_address_2 = 0;\n                        let data_length_2 = 0;\n                        let data_value_2 = 0;\n                        let interval = 0;\n\n                        cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * cmBuzzerBeat);\n\n                        data_address_1 = 740;\n                        data_length_1 = 2;\n                        // data_value_1 = cmBuzzerTime * 10;\n                        // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력  - console.log(parseInt(0.59 * 10)); max 는 5초\n                        data_value_1 = cmBuzzerTime;\n                        if (data_value_1 < 0) {\n                            data_value_1 = 0;\n                        }\n                        if (data_value_1 > 50000) {\n                            data_value_1 = 50000;\n                        }\n\n                        data_address_2 = 742;\n                        data_length_2 = 1;\n                        data_value_2 = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12;\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [\n                            [data_instruction, data_address_1, data_length_1, data_value_1],\n                            [data_instruction, data_address_2, data_length_2, data_value_2],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.scale_advanced(%1, %2, %3)'],\n                    },\n                },\n                robotis_robotai_lite_rest_simple: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_beat_rest_8th_note, '3'],\n                                [Lang.Blocks.robotis_beat_rest_quarter_note, '5'],\n                                [Lang.Blocks.robotis_beat_rest_half_note, '7'],\n                                [Lang.Blocks.robotis_beat_rest_whole_note, '9'],\n                            ],\n                            value: '5',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_rest_simple',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_NOTE: 0,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script);\n                        let cmBuzzerTime = 0;\n\n                        let interval = 0;\n\n                        switch (cmBuzzerNote) {\n                            case 3:\n                                cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute / 2);\n                                break;\n\n                            case 5:\n                                cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute);\n                                break;\n\n                            case 7:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 2);\n                                break;\n\n                            case 9:\n                                cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 4);\n                                break;\n                        }\n\n                        let data_sendqueue = [];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.rest_simple(%1)'],\n                    },\n                },\n                robotis_robotai_lite_rest_advanced: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [1, null],\n                        type: 'robotis_robotai_lite_rest_advanced',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_BEAT: 0,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script);\n                        let cmBuzzerTime = 0;\n\n                        let interval = 0;\n\n                        cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100);\n\n                        cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * cmBuzzerBeat);\n\n                        let data_sendqueue = [];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            cmBuzzerTime + interval\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.rest_advanced(%1)'],\n                    },\n                },\n                robotis_robotai_lite_beat_per_minute: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [75, null],\n                        type: 'robotis_robotai_lite_beat_per_minute',\n                    },\n                    paramsKeyMap: {\n                        CM_BUZZER_BPM: 0,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmBuzzerBpm = script.getNumberValue('CM_BUZZER_BPM', script);\n\n                        beat_per_minute = Math.min(Math.max(cmBuzzerBpm, 10), 600);\n\n                        // console.log(\"buzzer send\");\n                        let data_sendqueue = [];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(script, data_sendqueue, 0);\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.set_bpm(%1)'],\n                    },\n                },\n\n                robotis_robotai_lite_Hello: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_korean1, '0'],\n                                [Lang.Blocks.robotis_korean2, '1'],\n                                [Lang.Blocks.robotis_korean3, '2'],\n                                [Lang.Blocks.robotis_korean4, '3'],\n                                [Lang.Blocks.robotis_korean5, '4'],\n                                [Lang.Blocks.robotis_korean6, '5'],\n                                [Lang.Blocks.robotis_korean7, '6'],\n                                [Lang.Blocks.robotis_korean8, '7'],\n                                [Lang.Blocks.robotis_korean9, '8'],\n                                [Lang.Blocks.robotis_korean10, '9'],\n                                [Lang.Blocks.robotis_korean11, '10'],\n                                [Lang.Blocks.robotis_korean12, '11'],\n                                [Lang.Blocks.robotis_korean13, '12'],\n                                [Lang.Blocks.robotis_korean14, '13'],\n                                [Lang.Blocks.robotis_korean15, '14'],\n                                [Lang.Blocks.robotis_korean16, '15'],\n                                [Lang.Blocks.robotis_korean17, '16'],\n                                [Lang.Blocks.robotis_korean18, '17'],\n                                [Lang.Blocks.robotis_korean19, '18'],\n                                [Lang.Blocks.robotis_korean20, '19'],\n                                [Lang.Blocks.robotis_korean21, '20'],\n                                [Lang.Blocks.robotis_korean22, '21'],\n                                [Lang.Blocks.robotis_korean23, '22'],\n                                [Lang.Blocks.robotis_korean24, '23'],\n                                [Lang.Blocks.robotis_korean25, '24'],\n                                [Lang.Blocks.robotis_korean26, '25'],\n                                [Lang.Blocks.robotis_korean27, '26'],\n                                [Lang.Blocks.robotis_korean28, '27'],\n                                [Lang.Blocks.robotis_korean29, '28'],\n                                [Lang.Blocks.robotis_korean30, '29'],\n                                [Lang.Blocks.robotis_korean31, '30'],\n                                [Lang.Blocks.robotis_korean32, '31'],\n                                [Lang.Blocks.robotis_korean33, '32'],\n                                [Lang.Blocks.robotis_korean34, '33'],\n                                [Lang.Blocks.robotis_korean35, '34'],\n                                [Lang.Blocks.robotis_korean36, '35'],\n                                [Lang.Blocks.robotis_korean37, '36'],\n                                [Lang.Blocks.robotis_korean38, '37'],\n                                [Lang.Blocks.robotis_korean39, '38'],\n                                [Lang.Blocks.robotis_korean40, '39'],\n                                [Lang.Blocks.robotis_korean41, '40'],\n                                [Lang.Blocks.robotis_korean42, '41'],\n                                [Lang.Blocks.robotis_korean43, '42'],\n                                [Lang.Blocks.robotis_korean44, '43'],\n                                [Lang.Blocks.robotis_korean45, '44'],\n                                [Lang.Blocks.robotis_korean46, '45'],\n                                [Lang.Blocks.robotis_korean47, '46'],\n                                [Lang.Blocks.robotis_korean48, '47'],\n                                [Lang.Blocks.robotis_korean49, '48'],\n                                [Lang.Blocks.robotis_korean50, '49'],\n                                [Lang.Blocks.robotis_korean51, '50'],\n                                [Lang.Blocks.robotis_korean52, '51'],\n                                [Lang.Blocks.robotis_korean53, '52'],\n                                [Lang.Blocks.robotis_korean54, '53'],\n                                [Lang.Blocks.robotis_korean55, '54'],\n                                [Lang.Blocks.robotis_korean56, '55'],\n                                [Lang.Blocks.robotis_korean57, '56'],\n                                [Lang.Blocks.robotis_korean58, '57'],\n                                [Lang.Blocks.robotis_korean59, '58'],\n                                [Lang.Blocks.robotis_korean60, '59'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_Hello',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = 25601 + Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n\n                        if (cmHello == '38' || cmHello == '55') {\n                            extraTime = 2000;\n                        }\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            2000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.speak(%1)'],\n                    },\n                },\n                robotis_robotai_lite_effectSound: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_dog, '0'],\n                                [Lang.Blocks.robotis_frog, '1'],\n                                [Lang.Blocks.robotis_cat, '2'],\n                                [Lang.Blocks.robotis_chicken, '7'],\n                                [Lang.Blocks.robotis_tiger, '19'],\n                                [Lang.Blocks.robotis_mouse, '17'],\n\n                                [Lang.Blocks.robotis_ambul, '773'],\n                                [Lang.Blocks.robotis_Horn, '781'],\n                                [Lang.Blocks.robotis_siren, '774'],\n                                [Lang.Blocks.robotis_whistle, '274'],\n                                [Lang.Blocks.robotis_gun, '775'],\n                                [Lang.Blocks.robotis_clap, '260'],\n\n                                [Lang.Blocks.robotis_melody1, '786'],\n                                [Lang.Blocks.robotis_melody2, '787'],\n                                [Lang.Blocks.robotis_melody3, '788'],\n                                [Lang.Blocks.robotis_melody4, '789'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_effectSound',\n                    },\n                    paramsKeyMap: {\n                        HELLO: 0,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let cmHello = script.getField('HELLO', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 110;\n                        let data_length = 2;\n                        let data_value = 0;\n\n                        data_value = Number(cmHello);\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                            [data_instruction, 0, 2, 0],\n                        ];\n\n                        let extraTime = 0;\n                        if (\n                            cmHello == '272' ||\n                            cmHello == '786' ||\n                            cmHello == '787' ||\n                            cmHello == '788' ||\n                            cmHello == '789'\n                        ) {\n                            //오리\n                            extraTime = 0;\n                            if (cmHello == '788' || cmHello == '789') {\n                                extraTime += 500;\n                            }\n                        }\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            3000 + extraTime\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.effect_sound(%1)'],\n                    },\n                },\n                robotis_robotai_lite_record: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_record',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 115;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.record(%1)'],\n                    },\n                },\n                robotis_robotai_lite_playRecord: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '0'],\n                                ['2', '1'],\n                                ['3', '2'],\n                                ['4', '3'],\n                                ['5', '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_playRecord',\n                    },\n                    paramsKeyMap: {\n                        ROOM: 0,\n                    },\n                    class: 'robotis_robotai_lite_sound',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let roomNum = script.getField('ROOM', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 116;\n                        let data_length = 1;\n                        let data_value = 0;\n\n                        data_value = roomNum;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_value],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            6000\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.playRecord(%1)'],\n                    },\n                },\n\n                robotis_robotai_lite_ai_camera_block_value_closest_to_center: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_target_face, '0'],\n                                [Lang.Blocks.robotis_ai_camera_target_expression, '1'],\n                                [Lang.Blocks.robotis_ai_camera_target_object, '2'],\n                                [Lang.Blocks.robotis_ai_camera_target_color, '3'],\n                                [Lang.Blocks.robotis_ai_camera_target_tag, '4'],\n                                [Lang.Blocks.robotis_ai_camera_target_qr, '5'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_width, '2'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_height, '3'],\n                                [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_ai_camera_block_value_closest_to_center',\n                    },\n                    paramsKeyMap: {\n                        TARGET: 0,\n                        DATA_TYPE: 1,\n                    },\n                    class: 'robotis_robotai_lite_ai_camera_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4009;\n                        let data_type = script.getNumberValue('DATA_TYPE');\n                        data_address += data_type * 2;\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_block_value_closest_to_center(%1)'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'],\n                                [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_ai_camera_arrow_value_closest_to_center',\n                    },\n                    paramsKeyMap: {\n                        DATA_TYPE: 0,\n                    },\n                    class: 'robotis_robotai_lite_ai_camera_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4019;\n                        let data_type = script.getNumberValue('DATA_TYPE');\n                        data_address += data_type * 2;\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_arrow_value_closest_to_center(%1)'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_number_of_learned_id: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'robotis_robotai_lite_ai_camera_number_of_learned_id',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_ai_camera_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4003;\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_number_of_learned_id()'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_block_value_of_id: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                                ['8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_target_face, '0'],\n                                [Lang.Blocks.robotis_ai_camera_target_expression, '1'],\n                                [Lang.Blocks.robotis_ai_camera_target_object, '2'],\n                                [Lang.Blocks.robotis_ai_camera_target_color, '3'],\n                                [Lang.Blocks.robotis_ai_camera_target_tag, '4'],\n                                [Lang.Blocks.robotis_ai_camera_target_qr, '5'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_width, '2'],\n                                [Lang.Blocks.robotis_ai_camera_center_block_height, '3'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'robotis_robotai_lite_ai_camera_block_value_of_id',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TARGET: 1,\n                        TYPE: 2,\n                    },\n                    class: 'robotis_robotai_lite_ai_camera_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4029; // ID_FOR_USE\n                        let data_length = 2;\n                        let data_value = script.getNumberValue('ID');\n\n                        if (data_value != camera_id_for_use) {\n                            let data_sendqueue = [\n                                [data_instruction, data_address, data_length, data_value],\n                            ];\n\n                            Entry.RobotisRobotaiLite.postCallReturn(\n                                script,\n                                data_sendqueue,\n                                DEFAULT_DELAY\n                            );\n                            camera_id_for_use = data_value;\n                        }\n\n                        data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER\n\n                        data_address += script.getNumberValue('TYPE') * 2;\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_block_value_of_id(%1, %2)'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_arrow_value_of_id: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                                ['8', '8'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'],\n                                [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null],\n                        type: 'robotis_robotai_lite_ai_camera_arrow_value_of_id',\n                    },\n                    paramsKeyMap: {\n                        ID: 0,\n                        TYPE: 1,\n                    },\n                    class: 'robotis_robotai_lite_ai_camera_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n\n                        // instruction / address / length / value / default length\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4029; // ID_FOR_USE\n                        let data_length = 2;\n                        let data_value = script.getNumberValue('ID');\n\n                        if (data_value != camera_id_for_use) {\n                            let data_sendqueue = [\n                                [data_instruction, data_address, data_length, data_value],\n                            ];\n\n                            Entry.RobotisRobotaiLite.postCallReturn(\n                                script,\n                                data_sendqueue,\n                                DEFAULT_DELAY\n                            );\n                            camera_id_for_use = data_value;\n                        }\n\n                        data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN\n\n                        data_address += script.getNumberValue('TYPE') * 2;\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (typeof result == 'undefined') {\n                            return 0;\n                        }\n\n                        return result;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_arrow_value_of_id(%1, %2)'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_connection_status: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_connected, '1'],\n                                [Lang.Blocks.robotis_disconnected, '0'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_ai_camera_connection_status',\n                    },\n                    paramsKeyMap: {\n                        STATUS: 0,\n                    },\n                    class: 'robotis_robotai_lite_ai_camera_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4000;\n                        let compareValue = script.getNumberValue('STATUS');\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == compareValue;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_connection_status(%1)'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_if_detected: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_target_face, '0'],\n                                [Lang.Blocks.robotis_ai_camera_target_expression, '1'],\n                                [Lang.Blocks.robotis_ai_camera_target_object, '2'],\n                                [Lang.Blocks.robotis_ai_camera_target_color, '3'],\n                                [Lang.Blocks.robotis_ai_camera_target_tag, '4'],\n                                [Lang.Blocks.robotis_ai_camera_target_qr, '5'],\n                                [Lang.Blocks.robotis_ai_camera_target_arrow, '6'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_ai_camera_if_detected',\n                    },\n                    paramsKeyMap: {\n                        DETECT_TYPE: 0,\n                    },\n                    class: 'robotis_robotai_lite_ai_camera_value',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        let scope = script.executor.scope;\n                        let data_address = 4005; // block\n                        let detect_type = script.getNumberValue('DETECT_TYPE');\n\n                        if (detect_type == 6) {\n                            data_address = 4006;\n                        } // arrow\n\n                        let result = Entry.RobotisRobotaiLite.dataBuffer[data_address];\n\n                        if (result == undefined) {\n                            return false;\n                        }\n\n                        return result == 1;\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_if_detected(%1)'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_set_mode: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.robotis_ai_camera_mode_face_recognition, '0'],\n                                [Lang.Blocks.robotis_ai_camera_mode_expression_recognition, '9'],\n                                [Lang.Blocks.robotis_ai_camera_mode_line_tracking, '3'],\n                                [Lang.Blocks.robotis_ai_camera_mode_color_recognition, '4'],\n                                [Lang.Blocks.robotis_ai_camera_mode_tag_recognition, '5'],\n                                [Lang.Blocks.robotis_ai_camera_mode_object_classification, '6'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'robotis_robotai_lite_ai_camera_set_mode',\n                    },\n                    paramsKeyMap: {\n                        AI_CAMERA_MODE: 0,\n                    },\n                    class: 'robotis_robotai_lite_ai_camera_set',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let ai_camera_mode = script.getField('AI_CAMERA_MODE', script);\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4001;\n                        let data_length = 1;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, ai_camera_mode],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.set_ai_camera_mode(%1)'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_print_custom_text: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            'Hello!',\n                        ],\n                        type: 'robotis_robotai_lite_ai_camera_print_custom_text',\n                    },\n                    paramsKeyMap: {\n                        X: 0,\n                        Y: 1,\n                        TEXT: 2,\n                    },\n                    class: 'robotis_robotai_lite_ai_camera_set',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n                        let x = script.getNumberValue('X', script);\n                        let y = script.getNumberValue('Y', script);\n                        let text = script.getStringValue('TEXT', script);\n                        let data_buf = [];\n                        let i = 0;\n\n                        // Encode the text as UTF-8\n                        let encoder = new TextEncoder();\n                        let utf8Array = encoder.encode(text);\n\n                        // utf8Array is now a Uint8Array containing the UTF-8 bytes of the text\n                        let text_len = utf8Array.length;\n\n                        if (text_len > 45) text_len = 45;\n\n                        if (x < -160) {\n                            x = 160;\n                        } else if (x > 160) {\n                            x = 160;\n                        }\n\n                        if (y < -120) {\n                            y = 120;\n                        } else if (y > 120) {\n                            y = 120;\n                        }\n\n                        if (x < 0) {\n                            x = 65536 + x;\n                        }\n                        if (y < 0) {\n                            y = 65536 + y;\n                        }\n\n                        data_buf.push(x % 256);\n                        data_buf.push(Math.floor(x / 256));\n                        data_buf.push(y % 256);\n                        data_buf.push(Math.floor(y / 256));\n                        data_buf.push(0);\n                        data_buf.push(0);\n                        for (i = 0; i < text_len; i++) {\n                            data_buf.push(utf8Array[i]);\n                        }\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4200;\n                        let data_length = 6 + text_len;\n\n                        let data_sendqueue = [\n                            [data_instruction, data_address, data_length, data_buf],\n                        ];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_print_custom_text(%1,%2,%3)'],\n                    },\n                },\n                robotis_robotai_lite_ai_camera_clear_custom_text: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardware_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'robotis_robotai_lite_ai_camera_clear_custom_text',\n                    },\n                    paramsKeyMap: {},\n                    class: 'robotis_robotai_lite_ai_camera_set',\n                    isNotFor: ['RobotisRobotaiLite'],\n                    func(sprite, script) {\n                        // instruction / address / length / value / default length\n\n                        let data_instruction = INST_WRITE;\n                        let data_address = 4250;\n                        let data_length = 1;\n\n                        let data_sendqueue = [[data_instruction, data_address, data_length, 1]];\n\n                        return Entry.RobotisRobotaiLite.postCallReturn(\n                            script,\n                            data_sendqueue,\n                            DEFAULT_DELAY\n                        );\n                    },\n                    syntax: {\n                        js: [],\n                        py: ['Robotailite.ai_camera_clear_custom_text()'],\n                    },\n                },\n            };\n        }\n\n        requestLocalData() {\n            let packets = [];\n            while (this.robotisBuffer.length > 0) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n                let packet = null;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        packet = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        packet = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n                \n                if (packet !== null && Array.isArray(packet)) {\n                    packets.push(...packet);\n                }\n            }\n            return packets;\n        }\n\n        handleLocalData(data) {\n            let stuffLength = 0;\n            //console.log(`length: ${data.length}`);\n            for (let i = 0; i < data.length; i++) {\n                //this.receiveBuffer.push(data[i]);\n                const dataIn = data[i];\n\n                switch (this.packetReceiveState) {\n                    case PACKET_STATE_IDLE:\n                        if (this.headerCount >= 2) {\n                            rxPacket.header[2] = dataIn;\n\n                            if (\n                                rxPacket.header[0] == 0xff &&\n                                rxPacket.header[1] == 0xff &&\n                                rxPacket.header[2] == 0xfd\n                            ) {\n                                this.headerCount = 0;\n                                this.packetReceiveState = PACKET_STATE_RESERVED;\n                            } else {\n                                rxPacket.header[0] = rxPacket.header[1];\n                                rxPacket.header[1] = rxPacket.header[2];\n                                rxPacket.header[2] = 0;\n                            }\n                        } else {\n                            rxPacket.header[this.headerCount] = dataIn;\n                            this.headerCount++;\n                        }\n                        break;\n\n                    case PACKET_STATE_RESERVED:\n                        if (dataIn == 0xfd) {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        } else {\n                            rxPacket.reserved = dataIn;\n                            this.packetReceiveState = PACKET_STATE_ID;\n                        }\n                        break;\n\n                    case PACKET_STATE_ID:\n                        rxPacket.id = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_L;\n                        break;\n\n                    case PACKET_STATE_LENGTH_L:\n                        rxPacket.packetLength = dataIn;\n                        this.packetReceiveState = PACKET_STATE_LENGTH_H;\n                        break;\n\n                    case PACKET_STATE_LENGTH_H:\n                        rxPacket.packetLength |= dataIn << 8;\n                        if (rxPacket.packetLength < 1000) {\n                            this.packetReceiveState = PACKET_STATE_DATA;\n                        } else {\n                            this.packetReceiveState = PACKET_STATE_IDLE;\n                        }\n                        rxPacket.index = 0;\n                        break;\n\n                    case PACKET_STATE_DATA:\n                        rxPacket.data[rxPacket.index] = dataIn;\n                        rxPacket.index++;\n\n                        if (rxPacket.index >= rxPacket.packetLength - 2) {\n                            this.packetReceiveState = PACKET_STATE_CRC_L;\n                        }\n                        break;\n\n                    case PACKET_STATE_CRC_L:\n                        rxPacket.crcReceived = dataIn;\n                        this.packetReceiveState = PACKET_STATE_CRC_H;\n                        break;\n\n                    case PACKET_STATE_CRC_H:\n                        rxPacket.crcReceived |= dataIn << 8;\n\n                        stuffLength = this.removeStuffing(rxPacket.data, rxPacket.packetLength);\n                        rxPacket.packetLength -= stuffLength;\n\n                        rxPacket.cmd = rxPacket.data[0];\n                        rxPacket.error = rxPacket.data[1];\n\n                        if (rxPacket.cmd == INST_STATUS) {\n                            //console.log(`rx length: ${rxPacket.packetLength}`);\n                            if (rxPacket.packetLength >= 147) {\n                                let tempValue = 0;\n                                for (let i = 0; i < addrMap.length; i++) {\n                                    switch (addrMap[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap[i][2]] =\n                                                rxPacket.data[2 + addrMap[i][0]] +\n                                                (rxPacket.data[2 + addrMap[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n\n                                const dxlPositionStartAddr =\n                                    addrMap[addrMap.length - 1][0] + addrMap[addrMap.length - 1][1];\n\n                                // DXL Position\n                                for (let i = 0; i < 20; i++) {\n                                    const currentId =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i];\n                                    const currentPos =\n                                        rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 1] +\n                                        (rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 2] << 8);\n                                    if (currentId != 0xff && currentPos != 0xffff) {\n                                        this.dxlPositions[currentId] = currentPos;\n                                    }\n                                }\n\n                                const lineCategoryStartAddr = dxlPositionStartAddr + 3 * 20;\n                                // line category\n                                this.dataBuffer[5201] = rxPacket.data[2 + lineCategoryStartAddr];\n\n                                const sensorStartAddr = lineCategoryStartAddr + 1;\n\n                                // 온습도+조도+동작감지센서값\n                                this.pirPir[0] = rxPacket.data[2 + sensorStartAddr];\n                                this.pirTemperature[0] = rxPacket.data[2 + sensorStartAddr + 1];\n                                this.pirHumidity[0] = rxPacket.data[2 + sensorStartAddr + 2];\n                                this.pirBrightness[0] = rxPacket.data[2 + sensorStartAddr + 3];\n\n                                // 거리+버튼+조도센서값\n                                this.distanceDistance[0] =\n                                    rxPacket.data[2 + sensorStartAddr + 4] +\n                                    (rxPacket.data[2 + sensorStartAddr + 5] << 8);\n                                this.distanceButton[0] = rxPacket.data[2 + sensorStartAddr + 6];\n                                this.distanceBrightness[0] = rxPacket.data[2 + sensorStartAddr + 7];\n\n                                for (let i = 0; i < addrMap2.length; i++) {\n                                    switch (addrMap2[i][1]) {\n                                        case 1:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]];\n                                            break;\n\n                                        case 2:\n                                            tempValue =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8);\n                                            if (tempValue >= 32768) {\n                                                tempValue = tempValue - 65536;\n                                            }\n                                            this.dataBuffer[addrMap2[i][2]] = tempValue;\n                                            break;\n\n                                        case 4:\n                                            this.dataBuffer[addrMap2[i][2]] =\n                                                rxPacket.data[2 + addrMap2[i][0]] +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 1] << 8) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 2] << 16) +\n                                                (rxPacket.data[2 + addrMap2[i][0] + 3] << 24);\n                                            break;\n                                    }\n                                }\n                            }\n                        }\n\n                        this.packetReceiveState = PACKET_STATE_IDLE;\n                        break;\n\n                    default:\n                    // code block\n                }\n            }\n        }\n\n        requestInitialData() {\n            this.robotisBuffer = [];\n            this.robotisBuffer.push([INST_WRITE, 1010, 2, 0xABC1]); // 아래 20번 모드 진입후 꼭두 얼굴로 변경준비\n            this.robotisBuffer.push([INST_WRITE, 21, 2, 20]);\n            this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기\n            this.robotisBuffer.push([INST_WRITE, 20, 1, 0]); // bypass port를 BLE로 설정\n            this.robotisBuffer.push([INST_WRITE, 23, 1, 1]); // auto report 기능 켜기\n            this.robotisBuffer.push([INST_WRITE, 4250, 1, 1]); // ai_camera 텍스트 지우기\n            this.robotisBuffer.push([INST_WRITE, 722, 1, 0]); // dxl 토크 끄기\n            //this.robotisBuffer.push([INST_WRITE, 63, 1, 1]); // 부저음 시간 설정\n            //this.robotisBuffer.push([INST_WRITE, 60, 1, 70]); // 부저음 발생\n            this.robotisBuffer.push([INST_WRITE, 113, 2, 1040]); // \"띵\" 효과음 발생\n            /*\n            //const ping = [0xff, 0xff, 0xfd, 0x00, 0xc8, 0x03, 0x00, 0x01, 0x3b, 0xfa];\n            // run entry mode\n            const packet = [\n                0xff, 0xff, 0xfd, 0x00, 0xc8, 0x07, 0x00, 0x03, 0x15, 0x00, 0x14, 0x00, 0xc1, 0xb3,\n            ];\n            return packet;\n            */\n        }\n\n        async initialHandshake() {\n            const status = true;\n            let sendBuffer = null;\n            this.requestInitialData();\n            while (this.robotisBuffer.length) {\n                const data = this.robotisBuffer.shift();\n                const instruction = data[0];\n                const address = data[1];\n                const length = data[2];\n                const value = data[3];\n                const dataBuffer = data[4];\n                let id = 0;\n\n                switch (instruction) {\n                    case INST_WRITE:\n                        id = 200;\n                        sendBuffer = this.writePacket(id, address, length, value);\n                        break;\n                    case INST_BYPASS_WRITE:\n                        id = value;\n                        sendBuffer = this.writePacket(id, address, length, dataBuffer);\n                        break;\n                }\n                Entry.hwLite.serial.sendAsciiAsBuffer(sendBuffer);\n                if (instruction == INST_WRITE && address == 2100 && length == 1 && value == 1) {\n                    this.robotisBuffer = [];\n                }\n            }\n            return status;\n        }\n    })();\n})();\n\nmodule.exports = Entry.RobotisRobotaiLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_sensorboard_lite.js",
    "content": "'use strict';\n\nimport _range from 'lodash/range';\n\n(function() {\n    Entry.SensorboardLite = new (class SensorboardLite {\n        constructor() {\n            this.id = '010201';\n            this.name = 'SensorboardLite';\n            this.url = 'http://www.neweducation.co.kr/';\n            this.imageName = 'sensorboardlite.png';\n            this.title = {\n                ko: 'E-센서보드',\n                en: 'E-Sensorboard',\n            };\n            this.duration = 32;\n            this.blockMenuBlocks = [\n                'sensorboardlite_get_named_sensor_value',\n                'sensorboardlite_is_button_pressed',\n                'sensorboardlite_led',\n                'sensorboardlite_get_number_sensor_value',\n                'sensorboardlite_get_digital_value',\n                'sensorboardlite_toggle_digital',\n                'sensorboardlite_toggle_pwm',\n                'sensorboardlite_convert_scale',\n            ];\n            this.portData = {\n                baudRate: 57600,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: true,\n            };\n            this.readablePorts = [];\n            this.remainValue = null;\n            this.setZero();\n        }\n        setZero() {\n            this.port = new Array(12).fill(0);\n            this.digitalValue = new Array(12).fill(0);\n            this.remoteDigitalValue = new Array(12).fill(0);\n            this.analogValue = new Array(6).fill(0);\n            this.readablePorts = _range(0, 19);\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        handleLocalData(data) {\n            for (let i = 0; i < 32; i++) {\n                let chunk;\n                if (!this.remainValue) {\n                    chunk = data[i];\n                } else {\n                    chunk = this.remainValue;\n                    i--;\n                }\n                if (chunk >> 7) {\n                    if ((chunk >> 6) & 1) {\n                        const nextChunk = data[i + 1];\n                        if (!nextChunk && nextChunk !== 0) {\n                            this.remainValue = chunk;\n                        } else {\n                            this.remainValue = null;\n\n                            const port = (chunk >> 3) & 7;\n                            this.analogValue[port] = ((chunk & 7) << 7) + (nextChunk & 127);\n                        }\n                        i++;\n                    } else {\n                        const port = (chunk >> 2) & 15;\n                        this.digitalValue[port] = chunk & 1;\n                    }\n                }\n            }\n        }\n\n        requestLocalData() {\n            const queryString = [];\n            const readablePorts = this.readablePorts;\n\n            if (readablePorts) {\n                for (const i in readablePorts) {\n                    const query = (5 << 5) + (readablePorts[i] << 1);\n                    queryString.push(query);\n                }\n            }\n            const readablePortsValues = (readablePorts && Object.values(readablePorts)) || [];\n            for (let port = 0; port < 12; port++) {\n                if (readablePortsValues.indexOf(port) > -1) {\n                    continue;\n                }\n                const value = this.remoteDigitalValue[port];\n                if (value === 255 || value === 0) {\n                    const query = (7 << 5) + (port << 1) + (value == 255 ? 1 : 0);\n                    queryString.push(query);\n                } else if (value > 0 && value < 255) {\n                    let query = (6 << 5) + (port << 1) + (value >> 7);\n                    queryString.push(query);\n                    query = value & 127;\n                    queryString.push(query);\n                }\n            }\n            return queryString;\n        }\n\n        addReadablePort(port) {\n            const idx = Entry.SensorboardLite.readablePorts.indexOf(port);\n            if (idx === -1) {\n                Entry.SensorboardLite.readablePorts.push(port);\n            }\n        }\n\n        removeReadablePort(port) {\n            const idx = Entry.SensorboardLite.readablePorts.indexOf(port);\n            if (idx >= 0) {\n                Entry.SensorboardLite.readablePorts.splice(idx, 1);\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        sensorboardlite_get_number_sensor_value: '아날로그 %1 번 센서값  ',\n                        sensorboardlite_get_digital_value: '디지털 %1 번 센서값  ',\n                        sensorboardlite_toggle_digital: '디지털 %1 번 핀 %2 %3',\n                        sensorboardlite_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3',\n                        sensorboardlite_convert_scale:\n                            '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값  ',\n                        sensorboardlite_get_named_sensor_value: '%1  센서값',\n                        sensorboardlite_is_button_pressed: '%1  버튼을 눌렀는가?',\n                        sensorboardlite_led: '%1  LED %2   %3',\n                    },\n                },\n                en: {\n                    template: {\n                        sensorboardlite_get_number_sensor_value: 'Analog %1 Sensor value  ',\n                        sensorboardlite_get_digital_value: 'Digital %1 Sensor value  ',\n                        sensorboardlite_toggle_digital: 'Digital %1 Pin %2 %3',\n                        sensorboardlite_toggle_pwm: 'Digital %1 Pin %2 %3',\n                        sensorboardlite_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5  ',\n                        sensorboardlite_get_named_sensor_value: '%1  Sensor value',\n                        sensorboardlite_is_button_pressed: 'Pressed %1 button?',\n                        sensorboardlite_led: '%1  LED %2   %3',\n                    },\n                },\n            };\n        }\n\n        // TODO : block_arduino_lite.js와 공통블럭 상속하도록 변경\n        getBlocks() {\n            return {\n                sensorboardlite_get_named_sensor_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['소리', '0'],\n                                ['빛 감지', '1'],\n                                ['슬라이더', '2'],\n                                ['온도', '3'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'sensorboardlite_get_named_sensor_value',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'sensorBoard',\n                    isNotFor: ['SensorboardLite'],\n                    func(sprite, script) {\n                        return Entry.SensorboardLite.analogValue[script.getField('PORT', script)];\n                    },\n                    syntax: { js: [], py: ['Sensorboard.sensor_value(%1)'] },\n                },\n                sensorboardlite_is_button_pressed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['빨간', '8'],\n                                ['파란', '9'],\n                                ['노랑', '10'],\n                                ['초록', '11'],\n                            ],\n                            value: '8',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null],\n                        type: 'sensorboardlite_is_button_pressed',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'sensorBoard',\n                    isNotFor: ['SensorboardLite'],\n                    func(sprite, script) {\n                        const port = script.getNumberValue('PORT', script);\n                        Entry.SensorboardLite.addReadablePort(port);\n                        return Entry.SensorboardLite.digitalValue[port];\n                    },\n                    syntax: { js: [], py: ['Sensorboard.is_button_pressed(%1)'] },\n                },\n                sensorboardlite_led: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['빨간', '2'],\n                                ['초록', '3'],\n                                ['파란', '4'],\n                                ['노랑', '5'],\n                            ],\n                            value: '2',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['켜기', '255'],\n                                ['끄기', '0'],\n                            ],\n                            value: '255',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [null, null, null],\n                        type: 'sensorboardlite_led',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        OPERATOR: 1,\n                    },\n                    class: 'sensorBoard',\n                    isNotFor: ['SensorboardLite'],\n                    func(sprite, script) {\n                        const port = script.getNumberValue('PORT');\n                        const operator = script.getNumberField('OPERATOR');\n                        Entry.SensorboardLite.remoteDigitalValue[port] = operator;\n                        Entry.SensorboardLite.removeReadablePort(port);\n                        return script.callReturn();\n                    },\n                    syntax: { js: [], py: ['Sensorboard.led(%1, %2)'] },\n                },\n                sensorboardlite_get_number_sensor_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    isNotFor: ['SensorboardLite'],\n                    def: {\n                        type: 'sensorboardlite_get_number_sensor_value',\n                    },\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0', '0'],\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    class: 'arduino_value',\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'SensorBoard.get_number_sensor_value(%1)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    func(sprite, script) {\n                        return Entry.SensorboardLite.analogValue[\n                            script.getNumberValue('VALUE', script)\n                        ];\n                    },\n                },\n                sensorboardlite_get_digital_value: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    parent: 'arduino_get_digital_value',\n                    skeleton: 'basic_boolean_field',\n                    isNotFor: ['SensorboardLite'],\n                    def: {\n                        type: 'sensorboardlite_get_digital_value',\n                    },\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0', '0'],\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                                ['8', '8'],\n                                ['9', '9'],\n                                ['10', '10'],\n                                ['11', '11'],\n                                ['12', '12'],\n                                ['13', '13'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    class: 'arduino_value',\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'SensorBoard.get_digital_value(%1)',\n                                blockType: 'param',\n                                replaceBlockType: 'arduino_ext_get_digital',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    func(sprite, script) {\n                        const port = script.getNumberValue('PORT', script);\n                        Entry.SensorboardLite.addReadablePort(port);\n                        return Entry.SensorboardLite.digitalValue[port];\n                    },\n                },\n                sensorboardlite_toggle_digital: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    isNotFor: ['SensorboardLite'],\n                    def: {\n                        type: 'sensorboardlite_toggle_digital',\n                    },\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['0', '0'],\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                                ['4', '4'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['7', '7'],\n                                ['8', '8'],\n                                ['9', '9'],\n                                ['10', '10'],\n                                ['11', '11'],\n                                ['12', '12'],\n                                ['13', '13'],\n                            ],\n                            value: '0',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['켜기', 255],\n                                ['끄기', 0],\n                            ],\n                            value: 255,\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    class: 'arduino_set',\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'SensorBoard.toggle_led(%1)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Dropdown',\n                                        options: [\n                                            [Lang.Blocks.ARDUINO_on, 'on'],\n                                            [Lang.Blocks.ARDUINO_off, 'off'],\n                                        ],\n                                        value: 'on',\n                                        fontSize: 11,\n                                        bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                                        arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                                        converter: Entry.block.converters.returnStringValue,\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                        OPERATOR: 1,\n                    },\n                    func(sprite, script) {\n                        const port = script.getNumberValue('VALUE');\n                        const operator = script.getField('OPERATOR');\n                        Entry.SensorboardLite.remoteDigitalValue[port] = operator;\n                        Entry.SensorboardLite.removeReadablePort(port);\n                        return script.callReturn();\n                    },\n                },\n                sensorboardlite_toggle_pwm: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    isNotFor: ['SensorboardLite'],\n                    skeleton: 'basic',\n                    def: {\n                        type: 'sensorboardlite_toggle_pwm',\n                    },\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['3', '3'],\n                                ['5', '5'],\n                                ['6', '6'],\n                                ['9', '9'],\n                                ['10', '10'],\n                                ['11', '11'],\n                            ],\n                            value: '3',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                            value: 255,\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/hardwarelite_icon.svg',\n                            size: 12,\n                        },\n                    ],\n                    class: 'arduino_set',\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'SensorBoard.toggle_pwm(%1, %2)',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        VALUE: 1,\n                    },\n                    func(sprite, script) {\n                        const port = script.getNumberValue('PORT');\n                        let value = script.getNumberValue('VALUE');\n                        value = Math.round(value);\n                        value = Math.max(value, 0);\n                        value = Math.min(value, 255);\n                        Entry.SensorboardLite.remoteDigitalValue[port] = value;\n                        Entry.SensorboardLite.removeReadablePort(port);\n                        return script.callReturn();\n                    },\n                },\n                sensorboardlite_convert_scale: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic_string_field',\n                    isNotFor: ['SensorboardLite'],\n                    def: {\n                        params: [\n                            {\n                                type: 'arduino_get_number_sensor_value',\n                                params: [\n                                    {\n                                        type: 'arduino_get_sensor_number',\n                                        id: 'bl5e',\n                                    },\n                                ],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['1023'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                        ],\n                        type: 'sensorboardlite_convert_scale',\n                    },\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    class: 'arduino',\n                    syntax: {\n                        js: [],\n                        py: [\n                            {\n                                syntax: 'SensorBoard.convert_scale(%1, %2, %3, %4, %5)',\n                                blockType: 'param',\n                                textParams: [\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                    {\n                                        type: 'Block',\n                                        accept: 'string',\n                                    },\n                                ],\n                            },\n                        ],\n                    },\n                    paramsKeyMap: {\n                        VALUE1: 0,\n                        VALUE2: 1,\n                        VALUE3: 2,\n                        VALUE4: 3,\n                        VALUE5: 4,\n                    },\n                    func(sprite, script) {\n                        const value1 = script.getNumberValue('VALUE1', script);\n                        let value2 = script.getNumberValue('VALUE2', script);\n                        let value3 = script.getNumberValue('VALUE3', script);\n                        let value4 = script.getNumberValue('VALUE4', script);\n                        let value5 = script.getNumberValue('VALUE5', script);\n\n                        const stringValue4 = script.getValue('VALUE4', script);\n                        const stringValue5 = script.getValue('VALUE5', script);\n                        let isFloat = false;\n\n                        if (\n                            (Entry.Utils.isNumber(stringValue4) &&\n                                stringValue4.indexOf('.') > -1) ||\n                            (Entry.Utils.isNumber(stringValue5) && stringValue5.indexOf('.') > -1)\n                        ) {\n                            isFloat = true;\n                        }\n\n                        let result = value1;\n                        if (value2 > value3) {\n                            const swap = value2;\n                            value2 = value3;\n                            value3 = swap;\n                        }\n                        if (value4 > value5) {\n                            const swap = value4;\n                            value4 = value5;\n                            value5 = swap;\n                        }\n                        result -= value2;\n                        result = result * ((value5 - value4) / (value3 - value2));\n                        result += value4;\n                        result = Math.min(value5, result);\n                        result = Math.max(value4, result);\n\n                        if (isFloat) {\n                            result = Math.round(result * 100) / 100;\n                        } else {\n                            result = Math.round(result);\n                        }\n\n                        return result;\n                    },\n                },\n            };\n        }\n    })();\n})();\n\nmodule.exports = Entry.SensorboardLite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_whalesbot_drone_lite.js",
    "content": "'use strict';\n\n// - 라이프사이클 재점검\n// - Entry.hw 부분 Entry.hwLite로 수정\n// - portData 파라미터 확인\n// - 모니터링 로직 확인\n\nimport _range from 'lodash/range';\nimport DataTable from '../../../class/DataTable';\nimport entryModuleLoader from '../../../class/entryModuleLoader';\nimport metadata from './metadata_whalesbot_drone_lite.json';\n\n(function () {\n    Entry.WhalesbotDroneLite = new (class WhalesbotDroneLite {\n        constructor() {\n            this.id = '620101';\n            this.name = 'WhalesbotDroneLite';\n            this.url = 'https://gaion-edu.kr/';\n            this.imageName = 'whalesbotlite.png';\n            this.title = {\n                ko: 'Whalesbot Eagle1001',\n                en: 'Whalesbot Eagle1001',\n            };\n            // duration도 미확인\n            this.duration = 32;\n            this.blockMenuBlocks = [\n                // 'whalesbot_eagle_1001_lite_openning_3d_simulator',\n                'whalesbot_eagle_1001_lite_entering_pitch_mode',\n                'whalesbot_eagle_1001_lite_exit_pitch_mode',\n                'whalesbot_eagle_1001_lite_automatic_take_off_height',\n                'whalesbot_eagle_1001_lite_automatic_take_off_altitude_speed_offset',\n                'whalesbot_eagle_1001_lite_automatic_landing',\n                'whalesbot_eagle_1001_lite_automatic_descent_speed_offset',\n                'whalesbot_eagle_1001_lite_set_the_flight_speed',\n                'whalesbot_eagle_1001_lite_get_setting_speed',\n                'whalesbot_eagle_1001_lite_rise',\n                'whalesbot_eagle_1001_lite_down',\n                'whalesbot_eagle_1001_lite_fly_forward',\n                'whalesbot_eagle_1001_lite_fly_backward',\n                'whalesbot_eagle_1001_lite_fly_left',\n                'whalesbot_eagle_1001_lite_fly_right',\n                'whalesbot_eagle_1001_lite_turn_left',\n                'whalesbot_eagle_1001_lite_turn_right',\n                'whalesbot_eagle_1001_lite_fly_in_the_specified_direction',\n                'whalesbot_eagle_1001_lite_flight_designated',\n                'whalesbot_eagle_1001_lite_set_the_four_channel_lever_quantity_of_remote_control',\n                'whalesbot_eagle_1001_lite_stop_moving_and_hover',\n                'whalesbot_eagle_1001_lite_hover_at_specified_altitude',\n                'whalesbot_eagle_1001_lite_emergency_stop',\n                'whalesbot_eagle_1001_lite_set_the_steering_gear',\n                // 'whalesbot_eagle_1001_lite_execute_script',\n                'whalesbot_eagle_1001_lite_clean',\n                'whalesbot_eagle_1001_lite_restart',\n                'whalesbot_eagle_1001_lite_get_status',\n                // light & speaker blocks\n                'whalesbot_eagle_1001_lite_ls_debug_value',\n                'whalesbot_eagle_1001_lite_ls_display_symbol',\n                'whalesbot_eagle_1001_lite_ls_off_LED',\n                'whalesbot_eagle_1001_lite_ls_display_digital_tube',\n                'whalesbot_eagle_1001_lite_ls_display_digital_tube_score',\n                'whalesbot_eagle_1001_lite_ls_off_digital_tube',\n                'whalesbot_eagle_1001_lite_ls_set_RGB',\n                'whalesbot_eagle_1001_lite_ls_fly_RGB',\n                // 'whalesbot_eagle_1001_lite_ls_set_DO',\n                // 'whalesbot_eagle_1001_lite_ls_execute_script',\n                // sensors\n                'whalesbot_eagle_1001_lite_ss_fly_state_POS_Z',\n                'whalesbot_eagle_1001_lite_ss_fly_state_LASER',\n                'whalesbot_eagle_1001_lite_ss_battery_voltage',\n                'whalesbot_eagle_1001_lite_ss_fly_state_STATE_TEMP',\n                'whalesbot_eagle_1001_lite_ss_attitude_angle',\n                'whalesbot_eagle_1001_lite_ss_flight_angular_velocity',\n                'whalesbot_eagle_1001_lite_ss_flight_acceleration',\n                'whalesbot_eagle_1001_lite_ss_optical_flow',\n                'whalesbot_eagle_1001_lite_ss_get_infrared_distance',\n                'whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_bool',\n                // 'whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_string',\n                // 'whalesbot_eagle_1001_lite_ss_human_infrared_value_bool',\n                // 'whalesbot_eagle_1001_lite_ss_human_infrared_value_string',\n                'whalesbot_eagle_1001_lite_ss_AI',\n                // 'whalesbot_eagle_1001_lite_ss_get_ultrasonic_distance',\n                'whalesbot_eagle_1001_lite_ss_get_ambient_light',\n                // 'whalesbot_eagle_1001_lite_ss_get_temperature',\n                // 'whalesbot_eagle_1001_lite_ss_get_humidity',\n                // 'whalesbot_eagle_1001_lite_ss_get_flame',\n                // 'whalesbot_eagle_1001_lite_ss_get_gesture',\n                // 'whalesbot_eagle_1001_lite_ss_get_tof',\n                // 'whalesbot_eagle_1001_lite_ss_fly_setpoint_LASER_ENABLE',\n                // 'whalesbot_eagle_1001_lite_ss_get_bt_remote_control',\n                // 'whalesbot_eagle_1001_lite_ss_seconds',\n                // 'whalesbot_eagle_1001_lite_ss_resettime',\n            ];\n            this.portData = {\n                baudRate: 115200,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 255,\n                constantServing: 'ReadOnly',\n                connectionType: 'bytestream',\n            };\n            this.readablePorts = [];\n            this.remainValue = null;\n            this.decoder = new TextDecoder();\n            this.nowdwpack = 0;\n            this.BT_INDEX_CMD_SEND = 2;\n            this.BT_INDEX_DATA_SEND = 3;\n            this.packlen = 128;\n            this.DATASENDLEN = 154;\n            this.BT_INDEX_SENDCHECKSUM = this.DATASENDLEN - 1;\n            this.DATAREVLEN = 160;\n            this.BT_INDEX_REVCHECKSUM = this.DATAREVLEN - 1;\n            this.BT_INDEX_CMD_REV = 8;\n            this.BT_INDEX_DATA_REV = 9\n            this.BT_CMD_GETFLYSTATE1 = 0x50;\n            this.isDroneConnection = false;\n            this.countDroneConnectionAttempt = 0;\n            this.IsPicocStop = false;\n            this.revtmp = Buffer.alloc(this.DATAREVLEN);\n            this.revtemplength = 0;\n            this.revtmpdata = Buffer.alloc(this.DATAREVLEN);\n            this.revdata = Buffer.alloc(this.DATAREVLEN);\n            this.BT_CMD_DOWNLOAD = 0x62;\n            this.BT_CMD_DOWNLOAD_END = 0x64;\n            this.BT_CMD_PICOCSTOP = 0x68;\n            this.isDownloadDone = false;\n            this.isGetFlyState = false;\n            this.cmdType = {\n                'Download': 1,\n                'Stop': 2,\n            }\n            this.runCode = [\n                0x77, 0x78, 0x66, 0x1, 0x2, 0x2, 0x3, 0x3, 0x4, 0x4, 0x5, 0x5,\n                0x6, 0x6, 0x7, 0x7, 0x8, 0x8, 0x9, 0x9, 0xa, 0xa, 0xb, 0xb, 0xc, 0xc,\n                0xd, 0xd, 0xe, 0xe, 0xf, 0xf, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13,\n                0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18,\n                0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e,\n                0x1f, 0x1f, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24,\n                0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a,\n                0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f, 0x30, 0x30,\n                0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36,\n                0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c,\n                0x3d, 0x3d, 0x3e, 0x3e, 0x3f, 0x3f, 0x40, 0x40, 0x41, 0x41, 0x42, 0x42,\n                0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x48, 0x48,\n                0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x0, 0x56\n            ];\n\n            this.getStateCode = [\n                0x77, 0x78, 0x50, 0x1, 0x2, 0x2, 0x3, 0x3, 0x4, 0x4, 0x5, 0x5, 0x6, 0x6, 0x7, 0x7, 0x8, 0x8, 0x9, 0x9,\n                0xa, 0xa, 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xe, 0xe, 0xf, 0xf, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12\n                , 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a\n                , 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22\n                , 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a\n                , 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32\n                , 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a, 0x3a\n                , 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3e, 0x3e, 0x3f, 0x3f, 0x40, 0x40, 0x41, 0x41, 0x42, 0x42\n                , 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49, 0x4a, 0x4a\n                , 0x4b, 0x4b, 0x0, 0x6c\n            ];\n\n            this.stopCode = [\n                0x77, 0x78, 0x68, 0x1, 0x2, 0x2, 0x3, 0x3, 0x4, 0x4, 0x5, 0x5,\n                0x6, 0x6, 0x7, 0x7, 0x8, 0x8, 0x9, 0x9, 0xa, 0xa, 0xb, 0xb, 0xc,\n                0xc, 0xd, 0xd, 0xe, 0xe, 0xf, 0xf, 0x10, 0x10, 0x11, 0x11, 0x12,\n                0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17,\n                0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d,\n                0x1d, 0x1e, 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22,\n                0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,\n                0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d,\n                0x2e, 0x2e, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33,\n                0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38,\n                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3e,\n                0x3e, 0x3f, 0x3f, 0x40, 0x40, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43,\n                0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x48, 0x48, 0x49,\n                0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x0, 0x54\n            ];\n            this.simulatorPopup = null;\n            this.setZero();\n            this.unsupportBlockExist = false;\n            this.getStateTimeSleep = 500;\n            this.lock = false;\n            this.sensor = {\n                ACC_x: 0.0,\n                ACC_y: 0.0,\n                ACC_z: 0.0,\n                Gypo_x: 0.0,\n                Gypo_y: 0.0,\n                Gypo_z: 0.0,\n                SPL06_temp: 0.0,\n                SPL06_Press: 0.0,\n                SPL06_asl: 0.0,\n                Pitch: 0.0,\n                Roll: 0.0,\n                Yaw: 0.0,\n                Battery: 0.0,\n                LaserTof: 0.0,\n                GL_X: 0.0,\n                GL_Y: 0.0,\n                timertick: 0.0,\n                M1: 0,\n                M2: 0,\n                M3: 0,\n                M4: 0,\n                Debug_0: 0.0,\n                Debug_1: 0.0,\n                Debug_2: 0.0,\n                Debug_3: 0.0,\n                Debug_4: 0.0,\n                Debug_5: 0.0,\n                FusedHeight: 0.0,\n                VER: 100,\n                TYPE: \"TYPE_EG_DUMMY\",\n                ErrFly: 0,\n                asl_dis: 0.0,\n                startBaroAsl: 0.0,\n                LineNo: 0,\n                LineError: 0,\n                ErrorCode: 0,\n                state_position_x: 0.0,\n                state_position_y: 0.0,\n                state_position_z: 0.0,\n                state_velocity_x: 0.0,\n                state_velocity_y: 0.0,\n                state_velocity_z: 0.0,\n                btkey: 0,\n                btstick1: 0,\n                btstick2: 0,\n                btstick3: 0,\n                btstick4: 0,\n                btstick5: 0\n            };\n            this.BIT0 = 0x01;\n            this.BIT1 = 0x02;\n            this.BIT2 = 0x04;\n            this.BIT3 = 0x08;\n            this.BIT4 = 0x10;\n            this.BIT5 = 0x20;\n            this.BIT6 = 0x40;\n            this.BIT7 = 0x80;\n\n            this.simulatorUrl = metadata.simulator_url;\n            this.currentProcess = '';\n            this.received_data = [];\n        }\n\n        setZero() {\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        // 디바이스에서 값을 읽어온다.\n        async handleLocalData(data) {\n            if (this.currentProcess == 'pingControl') {\n                const CMD_PING_REV_SIZE = 3;\n                const revtemp = Buffer.alloc(CMD_PING_REV_SIZE);\n                for (let i = 0; i < data.length; i++) {\n                    revtemp[i] = data[i];\n                }\n                if (revtemp.length == CMD_PING_REV_SIZE) {\n                    if (revtemp[0] == 0x77 && revtemp[1] == 0x78 && revtemp[2] == 0x80) {\n                        this.sp.close();\n                        this.currentProcess = 'getStatus';\n                    }\n                }\n            }\n\n            if (this.currentProcess == 'getStatus') {\n                for (let i = 0; i < data.length; i++) {\n                    this.received_data.push(data[i]);\n                }\n                console.log('data.length: ', data.length);\n                if (this.received_data.length >= this.DATAREVLEN) {\n                    let revtmp = Buffer.from(this.received_data.slice(0, this.DATAREVLEN));\n                    this.received_data = this.received_data.slice(this.DATAREVLEN);\n                    // const hexStringX = Array.from(revtmp)\n                    //     .map(byte => `0x${byte.toString(16).padStart(2, '0')}`)\n                    //     .join(',');\n                    // console.log(`revtmp (hex): ${hexStringX}`);\n                    // let revtmp = Buffer.alloc(this.DATAREVLEN);\n                    // for (let i = 0; i < this.received_data.length; i++) {\n                    //     revtmp[i] = this.received_data[i];\n                    // }\n                    // revtmp = [0x77,0x78,0x0,0x0,0x63,0x5e,0x62,0x62,0x50,0xc3,0xd,0x3d,0xbc,0x39,0x6b,0xe0,0x3c,0xa6,0xb8,0x7f,0x3f,0x12,0xf0,0xa1,0xbd,0xac,0xe5,0x56,0x3e,0x48,0x62,0x0,0xbf,0x7b,0x87,0x23,0x42,0xe6,0xa9,0x7b,0x44,0x70,0xb,0xac,0x45,0xe6,0x2b,0x8b,0x3f,0x4f,0x3f,0xc1,0x3f,0x26,0xab,0x5d,0xc2,0x7a,0xe9,0x66,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x71,0x3d,0x21,0x43,0x0,0x0,0x0,0x0,0xba,0x5d,0x4c,0x3f,0x22,0xc,0x8e,0x38,0x74,0xb7,0x8e,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0xbf,0xa2,0xbc,0x6b,0x0,0x0,0x1,0x0,0x0,0x0,0x0,0x70,0xb,0xac,0x45,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0x49,0x5a,0x3f,0x1e,0x63,0x6,0x3e,0x4e,0x24,0x92,0x3c,0x4b,0x0,0xfd]\n                    if (revtmp[0] == 0x77 && revtmp[1] == 0x78) {\n                        // console.log(revtmp[this.BT_INDEX_REVCHECKSUM], this.btremotecalchecksum(revtmp));\n                        if (revtmp[this.BT_INDEX_REVCHECKSUM] == this.btremotecalchecksum(revtmp)) {\n                            for (let i = 0; i < revtmp.length; i++) {\n                                this.revdata[i] = revtmp[i];\n                            }\n                            this.makerevcmd();\n                            this.revcount = this.revcount + 1;\n                            if (this.isConnectEagle == false) {\n                                this.isConnectEagle = true;\n                                this.reverrcount = 0;\n                            }\n                        } else {\n                            this.reverrcount = this.reverrcount + 1;\n                            setTimeout(() => { }, 500);\n                        }\n                    } else {\n                        this.reverrcount = this.reverrcount + 1;\n                    }\n                    this.currentProcess = '';\n                }\n            }\n        }\n\n        retHex(bytes) {\n            const l = Array.from(bytes).map(byte => '0x' + byte.toString(16).padStart(1, '0'));\n            return l;\n        }\n\n        convertToBufferArray(input) {\n            const hexArray = input.split(',');\n            const byteArray = hexArray.map(hex => parseInt(hex, 16));\n            const buffer = Buffer.from(byteArray);\n            return buffer;\n        }\n\n        //디바이스에 값을 쓴다.\n        requestLocalData() {\n            // return this.getStateCode;\n            return null;\n            // return this.stopCode;\n        }\n\n        makerevcmd() {\n            this.IsRevPID = false; // 指示是否进行读取PID操作\n            this.IsSetPID = false; // 指示是否进行设置PID操作\n            this.IsDownload = false; // 指示是否进行下载操作\n            this.IsPicocRun = false; // 指示飞飞控上的解释器是否开始运行脚本\n            this.IsPicocStop = false; // 指示飞飞控上的解释器是否停止运行\n            this.IsAutoDownload = false; // 指示飞飞控是否强制自动降落\n            this.nowdwpack = 0;\n            this.dwmsg = '';\n            this.IsNewDataRevForLog = false;\n            this.revcount = 0;\n            this.sendcount = 0;\n            this.sensor = {};\n            this.TYPE_EG101 = 1;\n            this.TYPE_EG102 = 2;\n            if (this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_GETFLYSTATE1) {\n                // const hexStringX = Array.from(this.revdata)\n                //     .map(byte => `0x${byte.toString(16).padStart(2, '0')}`)\n                //     .join(',');\n                // console.log(`revtmp (hex): ${hexStringX}`);\n\n                this.sensor.btkey = parseInt(this.revdata[2] + this.revdata[3] * 256, 10);\n                this.sensor.btstick1 = parseInt(this.revdata[4], 10);\n                this.sensor.btstick2 = parseInt(this.revdata[5], 10);\n                this.sensor.btstick3 = parseInt(this.revdata[6], 10);\n                this.sensor.btstick4 = parseInt(this.revdata[7], 10);\n\n                this.sensor.ACC_x = this.byte2float(this.BT_INDEX_DATA_REV + 0 * 4);\n                this.sensor.ACC_y = this.byte2float(this.BT_INDEX_DATA_REV + 1 * 4);\n                this.sensor.ACC_z = this.byte2float(this.BT_INDEX_DATA_REV + 2 * 4);\n                this.sensor.Gypo_x = this.byte2float(this.BT_INDEX_DATA_REV + 3 * 4);\n                this.sensor.Gypo_y = this.byte2float(this.BT_INDEX_DATA_REV + 4 * 4);\n                this.sensor.Gypo_z = this.byte2float(this.BT_INDEX_DATA_REV + 5 * 4);\n                this.sensor.SPL06_temp = this.byte2float(this.BT_INDEX_DATA_REV + 6 * 4);\n                this.sensor.SPL06_Press = this.byte2float(this.BT_INDEX_DATA_REV + 7 * 4);\n                this.sensor.SPL06_asl = this.byte2float(this.BT_INDEX_DATA_REV + 8 * 4);\n                this.sensor.Pitch = this.byte2float(this.BT_INDEX_DATA_REV + 9 * 4);\n                this.sensor.Roll = this.byte2float(this.BT_INDEX_DATA_REV + 10 * 4);\n                this.sensor.Yaw = this.byte2float(this.BT_INDEX_DATA_REV + 11 * 4);\n                this.sensor.Battery = this.byte2float(this.BT_INDEX_DATA_REV + 12 * 4);\n\n                this.sensor.LaserTof = this.byte2float(this.BT_INDEX_DATA_REV + 13 * 4);\n                this.sensor.GL_X = this.byte2float(this.BT_INDEX_DATA_REV + 14 * 4);\n                this.sensor.GL_Y = this.byte2float(this.BT_INDEX_DATA_REV + 15 * 4);\n                this.sensor.timertick = this.byte2float(this.BT_INDEX_DATA_REV + 16 * 4);\n                this.sensor.M1 = parseInt(this.revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 0], 10);\n                this.sensor.M2 = parseInt(this.revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 1], 10);\n                this.sensor.M3 = parseInt(this.revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 2], 10);\n                this.sensor.M4 = parseInt(this.revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 3], 10);\n\n                this.sensor.state_velocity_x = this.byte2float(this.BT_INDEX_DATA_REV + 18 * 4);\n                this.sensor.state_velocity_y = this.byte2float(this.BT_INDEX_DATA_REV + 19 * 4);\n                this.sensor.state_velocity_z = this.byte2float(this.BT_INDEX_DATA_REV + 20 * 4);\n\n                this.sensor.Debug_0 = this.byte2float(this.BT_INDEX_DATA_REV + 21 * 4);\n                this.sensor.Debug_1 = this.byte2float(this.BT_INDEX_DATA_REV + 22 * 4);\n                this.sensor.Debug_2 = this.byte2float(this.BT_INDEX_DATA_REV + 23 * 4);\n                this.sensor.Debug_3 = this.byte2float(this.BT_INDEX_DATA_REV + 24 * 4);\n                this.sensor.Debug_4 = this.byte2float(this.BT_INDEX_DATA_REV + 25 * 4);\n                this.sensor.Debug_5 = this.byte2float(this.BT_INDEX_DATA_REV + 26 * 4);\n                this.sensor.FusedHeight = this.byte2float(this.BT_INDEX_DATA_REV + 27 * 4);\n\n                this.sensor.VER = parseInt(this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 0], 10);\n                this.sensor.ErrFly = parseInt(this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 1], 10);\n                // 飞机种类\n                if (this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 3] == 1) {\n                    this.sensor.TYPE = this.TYPE_EG101;\n                } else if (this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 3] == 2) {\n                    this.sensor.TYPE = this.TYPE_EG102;\n                } else if (this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 3] == 3) {\n                    this.sensor.TYPE = this.TYPE_FPV101;\n                } else {\n                    this.sensor.TYPE = `${this.TYPE_EGXXX}${this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 3]}`;\n                }\n\n                this.sensor.asl_dis = this.byte2float(this.BT_INDEX_DATA_REV + 29 * 4);\n                this.sensor.startBaroAsl = this.byte2float(this.BT_INDEX_DATA_REV + 30 * 4);\n                this.sensor.LineNo = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 31 * 4), 10);\n                this.sensor.LineError = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 32 * 4), 10);\n                this.sensor.ErrorCode = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 33 * 4), 10);\n                this.sensor.state_position_x = this.byte2float(this.BT_INDEX_DATA_REV + 34 * 4);\n                this.sensor.state_position_y = this.byte2float(this.BT_INDEX_DATA_REV + 35 * 4);\n                this.sensor.state_position_z = this.byte2float(this.BT_INDEX_DATA_REV + 36 * 4);\n\n                console.log('this.sensor', this.sensor);\n            } else if (this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_GETFLYSTATE_SCRATCH) {\n                // const hexStringX = Array.from(this.revdata)\n                //     .map(byte => `0x${byte.toString(16).padStart(2, '0')}`)\n                //     .join(',');\n                // console.log(`revtmp (hex): ${hexStringX}`);\n\n                this.sensor.btkey = parseInt(this.revdata[2] + this.revdata[3] * 256, 10);\n                this.sensor.btstick1 = parseInt(this.revdata[4], 10);\n                this.sensor.btstick2 = parseInt(this.revdata[5], 10);\n                this.sensor.btstick3 = parseInt(this.revdata[6], 10);\n                this.sensor.btstick4 = parseInt(this.revdata[7], 10);\n\n                if (this.revdata[this.BT_INDEX_DATA_REV + 0 * 4] == 0x77) { //蓝牙名称有效\n                    const bytename = new Uint8Array(14);\n                    for (let i = 0; i < 14; i++) {\n                        if (this.revdata[this.BT_INDEX_DATA_REV + 0 * 4 + i] == '\\0') { //避免\\0干扰上位机解析\n                            break;\n                        }\n                        bytename[i] = this.revdata[this.BT_INDEX_DATA_REV + 0 * 4 + i];\n                    }\n                    this.sensor.BTname = String.fromCharCode(...bytename);\n                }\n                this.sensor.FlyTime_h = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 4 * 4), 10);\n                this.sensor.FlyTime_m = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 5 * 4), 10);\n                this.sensor.SPL06_temp = this.byte2float(this.BT_INDEX_DATA_REV + 6 * 4);\n                this.sensor.FlyTime_s = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 7 * 4), 10);\n                this.sensor.SPL06_asl = this.byte2float(this.BT_INDEX_DATA_REV + 8 * 4);\n                this.sensor.Pitch = this.byte2float(this.BT_INDEX_DATA_REV + 9 * 4);\n                this.sensor.Roll = this.byte2float(this.BT_INDEX_DATA_REV + 10 * 4);\n                this.sensor.Yaw = this.byte2float(this.BT_INDEX_DATA_REV + 11 * 4);\n                this.sensor.Battery = this.byte2float(this.BT_INDEX_DATA_REV + 12 * 4);\n\n                this.sensor.Debug_0 = this.byte2float(this.BT_INDEX_DATA_REV + 21 * 4);\n                this.sensor.Debug_1 = this.byte2float(this.BT_INDEX_DATA_REV + 22 * 4);\n                this.sensor.Debug_2 = this.byte2float(this.BT_INDEX_DATA_REV + 23 * 4);\n                this.sensor.Debug_3 = this.byte2float(this.BT_INDEX_DATA_REV + 24 * 4);\n                this.sensor.Debug_4 = this.byte2float(this.BT_INDEX_DATA_REV + 25 * 4);\n                this.sensor.Debug_5 = this.byte2float(this.BT_INDEX_DATA_REV + 26 * 4);\n                this.sensor.FusedHeight = this.byte2float(this.BT_INDEX_DATA_REV + 27 * 4);\n\n                this.sensor.VER = parseInt(this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 0], 10);\n                this.sensor.ErrFly = parseInt(this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 1], 10);\n                //飞机种类\n                if (this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 3] == 1) {\n                    this.sensor.TYPE = this.TYPE_EG101;\n                } else if (this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 3] == 2) {\n                    this.sensor.TYPE = this.TYPE_EG102;\n                } else if (this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 3] == 3) {\n                    this.sensor.TYPE = this.TYPE_FPV101;\n                } else {\n                    this.sensor.TYPE = `${this.TYPE_EGXXX}${this.revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 3]}`;\n                }\n\n                this.sensor.LineNo = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 31 * 4), 10);\n                this.sensor.LineError = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 32 * 4), 10);\n                this.sensor.ErrorCode = parseInt(this.byte2float(this.BT_INDEX_DATA_REV + 33 * 4), 10);\n                this.sensor.state_position_x = this.byte2float(this.BT_INDEX_DATA_REV + 34 * 4);\n                this.sensor.state_position_y = this.byte2float(this.BT_INDEX_DATA_REV + 35 * 4);\n                this.sensor.state_position_z = this.byte2float(this.BT_INDEX_DATA_REV + 36 * 4);\n            } else if (this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_DOWNLOAD\n                || this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_DOWNLOAD_END) {\n                // const hexStringX = Array.from(this.revdata)\n                //     .map(byte => `0x${byte.toString(16).padStart(2, '0')}`)\n                //     .join(',');\n                // console.log(`revtmp (hex): ${hexStringX}`);\n\n                let isrevsame = true;\n                for (let i = 0; i < this.packlen; i++) {  //(int i = 0; i < packlen; i++)\n                    if (this.senddata[i + this.BT_INDEX_CMD_SEND] != this.revdata[i + this.BT_INDEX_CMD_REV]) {\n                        isrevsame = false;\n                        break;\n                    }\n                }\n                if (isrevsame == true) {\n                    this.nowdwpack = this.nowdwpack + 1;\n                }\n                if (this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_DOWNLOAD_END) {\n                    // 已经超过下载文件长度，可以停止下载\n                    this.IsDownload = false;\n                    this.dwmsg = 'download success';\n                    this.IsPicocStop = true;\n                } else if (this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_PICOCRUN) {\n                    this.IsPicocRun = false;\n                } else if (this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_PICOCSTOP) {\n                    this.IsPicocStop = false;\n                } else if (this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_AUTOLAND) {\n                    this.IsAutoDownload = false;\n                }\n                // 指示新的数据收到\n                this.IsNewDataRevForLog = true;\n            }\n        }\n\n        resetSensor() {\n            this.sensor.Pitch = 0;\n            this.sensor.Roll = 0;\n            this.sensor.Yaw = 0;\n            this.sensor.state_position_x = 0.0;\n            this.sensor.state_position_y = 0.0;\n            this.sensor.state_position_z = 0.0;\n            this.sensor.state_velocity_x = 0.0;\n            this.sensor.state_velocity_y = 0.0;\n            this.sensor.state_velocity_z = 0.0;\n        }\n\n        makesendcmd() {\n            this.IsRevPID = false;\n            this.IsSetPID = false;\n            this.IsDownload = false;\n            this.IsPicocRun = false;\n            this.IsPicocStop = false;\n            this.IsAutoDownload = false;\n            this.nowdwpack = 0;\n            this.dwmsg = '';\n            this.IsNewDataRevForLog = false;\n            if (this.IsDownload == true) {\n                this.resetSensor();\n                this.senddata[this.BT_INDEX_CMD_SEND] = this.BT_CMD_DOWNLOAD;\n                this.senddata[this.BT_INDEX_DATA_SEND] = this.nowdwpack & 0x000000ff;\n                this.senddata[this.BT_INDEX_DATA_SEND + 1] = parseInt(((this.nowdwpack & 0x0000ff00) / 256), 10);\n                if ((this.nowdwpack * this.packlen) > this.Picocode.length) {\n                    this.senddata[this.BT_INDEX_CMD_SEND] = this.BT_CMD_DOWNLOAD_END;\n                }\n                for (let i = 0; i < this.packlen; i++) {\n                    if (i + (this.nowdwpack * this.packlen) >= this.Picocode.length) {\n                        this.senddata[this.BT_INDEX_DATA_SEND + 2 + i] = 0xff;\n                    } else {\n                        this.senddata[this.BT_INDEX_DATA_SEND + 2 + i] = this.Picocode[i + (this.nowdwpack * this.packlen)];\n                    }\n                    this.dwmsg = `正在下载: ${this.nowdwpack * this.packlen} / ${this.Picocode.length}`;\n                    //PrintLog(5, dwmsg)\n                    console.log(this.dwmsg);\n                }\n            } else if (this.IsPicocRun == true) {\n                this.senddata[this.BT_INDEX_CMD_SEND] = this.BT_CMD_PICOCRUN;\n            } else if (this.IsPicocStop == true) {\n                this.senddata[this.BT_INDEX_CMD_SEND] = this.BT_CMD_PICOCSTOP;\n                this.IsPicocStop = false;\n            } else if (this.IsAutoDownload == true) {\n                this.senddata[this.BT_INDEX_CMD_SEND] = this.BT_CMD_AUTOLAND;\n            } else {\n                // if (this.sensor.VER >= 109 && this.sensor.VER <= 200) {\n                //     this.senddata[this.BT_INDEX_CMD_SEND] = this.BT_CMD_GETFLYSTATE_SCRATCH;\n                // } else {\n                //     this.senddata[this.BT_INDEX_CMD_SEND] = this.BT_CMD_GETFLYSTATE1;\n                // }\n                this.senddata[this.BT_INDEX_CMD_SEND] = this.BT_CMD_GETFLYSTATE1;\n                for (let i = this.BT_INDEX_DATA_SEND; i < this.BT_INDEX_SENDCHECKSUM - 1; i++) {\n                    // this.senddata[i] = parseInt((i / 2), 10) & 0x000000ff;\n                    this.senddata[i] = Math.floor(i / 2) & 0xFF;\n                }\n            }\n        }\n\n        btremotecalchecksum(data) {\n            let sum = 0;\n            const codelen = data.byteLength - 1;\n            for (let i = 2; i < codelen; i++) {\n                sum = sum + data[i];\n            }\n            sum = (sum & 0xff);\n            sum = (~sum) & 0xff;\n            return +sum;\n        }\n\n        sleep(time = 300) {\n            return new Promise(resolve => setTimeout(resolve, time));\n        }\n\n        async handleClean() {\n            let i = 0;\n            while (i < 2) {\n                await Entry.hwLite.serial.writer.write(Buffer.from(this.stopCode));\n                await this.sleep();\n                i++;\n            }\n        }\n\n        async downloadCode(sourceCode) {\n            // console.log(\"Send chunk 0\");\n            let byteCode = this.generateBytesCode(this.cmdType.Download, sourceCode, 0);\n            await Entry.hwLite.serial.writer.write(byteCode);\n\n            await this.sleep();\n            await Entry.hwLite.serial.writer.write(Buffer.from(this.getStateCode));\n            let i = 0;\n\n            await this.sleep();\n\n            while (true) {\n                // console.log(\"Send chunk \", i);\n                byteCode = this.generateBytesCode(this.cmdType.Download, sourceCode, i);\n                await Entry.hwLite.serial.writer.write(byteCode);\n                await this.sleep();\n                if (this.isLatestChunk(byteCode)) {\n                    // console.log(\"Latest chunk sent!\");\n                    this.revdata = [];\n                    break;\n                }\n                i++;\n            }\n        }\n\n        async handleGetStatus() {\n            this.currentProcess = 'getStatus';\n            await Entry.hwLite.serial.writer.write(Buffer.from(this.getStateCode));\n            await this.sleep();\n        }\n\n        async handleRestart() {\n            await Entry.hwLite.serial.writer.write(Buffer.from(this.getStateCode));\n            await this.sleep();\n        }\n\n        async handleRun() {\n            await Entry.hwLite.serial.writer.write(Buffer.from(this.runCode));\n            await this.sleep();\n        }\n\n        async sendPacket(packet, hex = true, callback = null) {\n            if (hex) {\n                await Entry.hwLite.serial.writer.write(Buffer.from(packet))\n            } else {\n                // console.log(this.retHex(packet).join(\",\"))\n                await Entry.hwLite.serial.writer.write(packet)\n            }\n            await new Promise(resolve => setTimeout(resolve, 250));\n        }\n\n        isLatestChunk(chunkData) {\n            if (chunkData[this.BT_INDEX_CMD_SEND] == 0x64) {\n                for (let i = 0; i <= chunkData.length - 1; i++) {\n                    if (chunkData[i] == 0xff\n                        && chunkData[i + 1] == 0x42\n                        && chunkData[i + 2] == 0x43\n                        && chunkData[i + 3] == 0x43\n                        && chunkData[i + 4] == 0x44\n                        && chunkData[i + 5] == 0x44\n                    ) {\n                        return true;\n                    }\n                }\n            }\n\n            return false;\n        }\n\n        generateBytesCode(type, Picocode = \"\", nowdwpack = 0) {\n            let ret = Buffer.alloc(this.DATASENDLEN);\n\n            ret[0] = 0x77;\n            ret[1] = 0x78;\n\n            ret[this.BT_INDEX_CMD_SEND] = this.BT_CMD_GETFLYSTATE1;\n            for (let i = this.BT_INDEX_DATA_SEND; i < this.BT_INDEX_SENDCHECKSUM - 1; i++) {\n                ret[i] = (Math.floor(i / 2)) & 0x000000ff;\n            }\n\n            if (type == this.cmdType.Download) {\n                ret[this.BT_INDEX_CMD_SEND] = this.BT_CMD_DOWNLOAD;\n                ret[this.BT_INDEX_DATA_SEND] = nowdwpack & 0x000000ff;\n                ret[this.BT_INDEX_DATA_SEND + 1] = ((nowdwpack & 0x0000ff00) / 256) | 0;\n\n                if (nowdwpack * this.packlen > Picocode.length) {\n                    ret[this.BT_INDEX_CMD_SEND] = this.BT_CMD_DOWNLOAD_END;\n                }\n\n                for (let i = 0; i < this.packlen; i++) {\n                    if (i + nowdwpack * this.packlen >= Picocode.length) {\n                        ret[this.BT_INDEX_DATA_SEND + 2 + i] = 0xff;\n                    } else {\n                        ret[this.BT_INDEX_DATA_SEND + 2 + i] = Picocode.charCodeAt(i + nowdwpack * this.packlen);\n                    }\n                }\n            } else if (type == this.cmdType.Stop) {\n                ret[this.BT_INDEX_CMD_SEND] = this.BT_CMD_PICOCSTOP\n            }\n\n            ret[this.BT_INDEX_SENDCHECKSUM] = this.calChecksum(ret);\n            // console.log(ret[this.BT_INDEX_SENDCHECKSUM]);\n            return ret;\n        }\n\n        calChecksum(data) {\n            let sum = 0;\n            const codelen = data.byteLength - 1;\n            for (let i = 2; i < codelen; i++) {\n                sum = sum + data[i];\n            }\n            sum = (sum & 0xff);\n            sum = (~sum) & 0xff;\n            return +sum;\n        }\n\n        VERSTR() {\n            return (this.sensor.TYPE).toString() + \"_\" + parseInt(this.sensor.VER).toString()\n\n        }\n        Errcode2Msg(ErrorCode) {\n            if (ErrorCode == 0) {\n                return \"No Error\"\n            }\n            if (ErrorCode == 1) {\n                return \"can't assign to this\"\n            }\n            if (ErrorCode == 2) {\n                return \"NULL pointer dereference\"\n            }\n            if (ErrorCode == 3) {\n                return \"first argument to '?' should be a number\"\n            }\n            if (ErrorCode == 4) {\n                return \"can't get the address of this\"\n            }\n            if (ErrorCode == 5) {\n                return \"invalid operation\"\n            }\n            if (ErrorCode == 6) {\n                return \"invalid use of a NULL pointer\"\n            }\n            if (ErrorCode == 7) {\n                return \"not supported\"\n            }\n            if (ErrorCode == 8) {\n                return \"invalid expression\"\n            }\n            if (ErrorCode == 9) {\n                return \"array index must be an integer\"\n            }\n            if (ErrorCode == 10) {\n                return \"this Target is not an array\"\n            }\n            if (ErrorCode == 11) {\n                return \"need an structure or union member\"\n            }\n            if (ErrorCode == 12) {\n                return \"struct or union error\"\n            }\n            if (ErrorCode == 13) {\n                return \"doesn't have a member\"\n            }\n            if (ErrorCode == 14) {\n                return \"operator not expected here\"\n            }\n            if (ErrorCode == 15) {\n                return \"brackets not closed\"\n            }\n            if (ErrorCode == 16) {\n                return \"identifier not expected here\"\n            }\n            if (ErrorCode == 17) {\n                return \"macro arguments missing\"\n            }\n            if (ErrorCode == 18) {\n                return \"expression expected\"\n            }\n            if (ErrorCode == 19) {\n                return \"a void value isn't much use here\"\n            }\n            if (ErrorCode == 20) {\n                return \"value not expected here\"\n            }\n            if (ErrorCode == 21) {\n                return \"type not expected here\"\n            }\n            if (ErrorCode == 22) {\n                return \"brackets not closed\"\n            }\n            if (ErrorCode == 23) {\n                return \"ExpressionParseMacroCall out of memory\"\n            }\n            if (ErrorCode == 24) {\n                return \"too many arguments\"\n            }\n            if (ErrorCode == 25) {\n                return \"comma expected\"\n            }\n            if (ErrorCode == 26) {\n                return \"bad argument\"\n            }\n            if (ErrorCode == 27) {\n                return \"not enough arguments\"\n            }\n            if (ErrorCode == 28) {\n                return \"Macro undefined\"\n            }\n            if (ErrorCode == 29) {\n                return \"function - can't call\"\n            }\n            if (ErrorCode == 30) {\n                return \"ExpressionParseFunctionCall out of memory\"\n            }\n            if (ErrorCode == 31) {\n                return \"too many arguments\"\n            }\n            if (ErrorCode == 32) {\n                return \"comma expected\"\n            }\n            if (ErrorCode == 33) {\n                return \"bad argument\"\n            }\n            if (ErrorCode == 34) {\n                return \"not enough arguments\"\n            }\n            if (ErrorCode == 35) {\n                return \"undefined Fun name\"\n            }\n            if (ErrorCode == 36) {\n                return \"function body expected\"\n            }\n            if (ErrorCode == 37) {\n                return \"no value returned from a function returning\"\n            }\n            if (ErrorCode == 38) {\n                return \"couldn't find goto label\"\n            }\n            if (ErrorCode == 39) {\n                return \"expression expected\"\n            }\n            if (ErrorCode == 40) {\n                return \"integer value expected instead\"\n            }\n            if (ErrorCode == 41) {\n                return \"identifier expected\"\n            }\n            if (ErrorCode == 42) {\n                return \"undefined Identifier\"\n            }\n            if (ErrorCode == 43) {\n                return \"value expected\"\n            }\n            if (ErrorCode == 44) {\n                return \"#else without #if\"\n            }\n            if (ErrorCode == 45) {\n                return \"#endif without #if\"\n            }\n            if (ErrorCode == 46) {\n                return \"nested function definitions are not allowed\"\n            }\n            if (ErrorCode == 47) {\n                return \"too many parameters\"\n            }\n            if (ErrorCode == 48) {\n                return \"comma expected\"\n            }\n            if (ErrorCode == 49) {\n                return \"bad parameter\"\n            }\n            if (ErrorCode == 50) {\n                return \"main() should return an int or void\"\n            }\n            if (ErrorCode == 51) {\n                return \"bad parameters to main()\"\n            }\n            if (ErrorCode == 52) {\n                return \"bad function definition\"\n            }\n            if (ErrorCode == 53) {\n                return \"function definition expected\"\n            }\n            if (ErrorCode == 54) {\n                return \"Identifier is already defined\"\n            }\n            if (ErrorCode == 55) {\n                return \"} expected\"\n            }\n            if (ErrorCode == 56) {\n                return \"can't define a void variable\"\n            }\n            if (ErrorCode == 57) {\n                return \"close bracket expected\"\n            }\n            if (ErrorCode == 58) {\n                return \"Macro is already defined\"\n            }\n            if (ErrorCode == 59) {\n                return \"'(' expected\"\n            }\n            if (ErrorCode == 60) {\n                return \"statement expected\"\n            }\n            if (ErrorCode == 61) {\n                return \"';' expected\"\n            }\n            if (ErrorCode == 62) {\n                return \"')' expected\"\n            }\n            if (ErrorCode == 63) {\n                return \"'while' expected\"\n            }\n            if (ErrorCode == 64) {\n                return \"'{' expected\"\n            }\n            if (ErrorCode == 65) {\n                return \"filename.h expected\"\n            }\n            if (ErrorCode == 66) {\n                return \"'' expected\"\n            }\n            if (ErrorCode == 67) {\n                return \"value required in return\"\n            }\n            if (ErrorCode == 68) {\n                return \"value in return from a void function\"\n            }\n            if (ErrorCode == 69) {\n                return \"PicocParse out of memory\"\n            }\n            if (ErrorCode == 70) {\n                return \"parse error\"\n            }\n            if (ErrorCode == 71) {\n                return \"AssignFail\"\n            }\n            if (ErrorCode == 72) {\n                return \"TableSetIdentifier out of memory\"\n            }\n            if (ErrorCode == 73) {\n                return \"data type is already defined\"\n            }\n            if (ErrorCode == 74) {\n                return \"structure isn't defined\"\n            }\n            if (ErrorCode == 75) {\n                return \"struct/union definitions can only be globals\"\n            }\n            if (ErrorCode == 76) {\n                return \"invalid type in struct\"\n            }\n            if (ErrorCode == 77) {\n                return \"member already defined\"\n            }\n            if (ErrorCode == 78) {\n                return \"semicolon expected\"\n            }\n            if (ErrorCode == 79) {\n                return \"enum isn't defined\"\n            }\n            if (ErrorCode == 80) {\n                return \"enum definitions can only be globals\"\n            }\n            if (ErrorCode == 81) {\n                return \"bad type declaration\"\n            }\n            if (ErrorCode == 82) {\n                return \"']' expected\"\n            }\n            if (ErrorCode == 83) {\n                return \"Variable out of memory\"\n            }\n            if (ErrorCode == 84) {\n                return \"stack underrun\"\n            }\n            if (ErrorCode == 85) {\n                return \"VariableStack out of memory\"\n            }\n            if (ErrorCode == 86) {\n                return \"stack is empty - can't go back\"\n            }\n            return \"\"\n        }\n\n        ErrFly2String(ErrFly) {\n            let msg = \"\"\n            const ERR_NONE = 0\n            const ERR_LOWBATT = this.BIT0\n            const ERR_CODE = this.BIT1\n            const ERR_TEMP = this.BIT3\n            const ERR_SENSORS = this.BIT4\n            const ERR_LOADER = this.BIT5\n            const ERR_ANGLE = this.BIT6\n            if (ErrFly == ERR_NONE) {\n                msg = msg + \"NO_Error\"\n\n            }\n            if (ErrFly & ERR_LOWBATT == ERR_LOWBATT) {\n                msg = \"Low_Battery\" + \" \"\n            }\n            if (ErrFly & ERR_CODE == ERR_CODE) {\n                msg = msg + \"Code_Error\" + \" \"\n            }\n            if (ErrFly & ERR_TEMP == ERR_TEMP) {\n                msg = msg + \"motherboard_temperature_is_too_high\" + \" \"\n            }\n            if (ErrFly & ERR_SENSORS == ERR_SENSORS) {\n                msg = msg + \"Sensor_Error\" + \" \"\n            }\n            if (ErrFly & ERR_LOADER == ERR_LOADER) {\n                msg = msg + \"Excessive_load\" + \" \"\n            }\n            if (ErrFly & ERR_ANGLE == ERR_ANGLE) {\n                msg = msg + \"Excessive_inclination_angle\" + \" \"\n            }\n            return msg\n\n        }\n        Sensor2String() {\n            let SPLIT_STRING = \"------------------------------------\\n\"\n            let msg = \"STATE_PITCH=    \" + (Math.round(this.sensor.Pitch, 3)).toString() + \"\\n\"\n            msg = msg + \"STATE_ROLL=    \" + (Math.round(this.sensor.Roll, 3)).toString() + \"\\n\"\n            msg = msg + \"STATE_YAW=    \" + (Math.round(this.sensor.Yaw, 3)).toString() + \"\\n\"\n            msg = msg + SPLIT_STRING\n\n            msg = msg + \"STATE_TEMP=    \" + (Math.round(this.sensor.SPL06_temp, 3)).toString() + \"\\n\"\n\n            msg = msg + \"FusedHeight=    \" + (Math.round(this.sensor.FusedHeight, 3)).toString() + \"\\n\"\n\n            msg = msg + \"BATTERY=    \" + (Math.round(this.sensor.Battery, 3)).toString() + \"\\n\"\n\n            msg = msg + \"VER=    \" + this.VERSTR() + \"\\n\"\n            msg = msg + SPLIT_STRING\n            msg = msg + \"FLY_ERR=    \" + this.ErrFly2String(parseInt(this.sensor.ErrFly)) + \"\\n\"\n            msg = msg + \"LINE_NO=    \" + (this.sensor.LineNo) + \"\\n\"\n            msg = msg + \"ERROR_NO=    \" + (this.sensor.LineError) + \"\\n\"\n            msg = msg + \"ERROR_MSG=    \" + this.Errcode2Msg(this.sensor.ErrorCode) + \"\\n\"\n\n            msg = msg + \"DEBUG1=    \" + (Math.round(this.sensor.Debug_0, 6)).toString() + \"\\n\"\n            msg = msg + \"DEBUG2=    \" + (Math.round(this.sensor.Debug_1, 6)).toString() + \"\\n\"\n            msg = msg + \"DEBUG3=    \" + (Math.round(this.sensor.Debug_2, 6)).toString() + \"\\n\"\n            msg = msg + \"DEBUG4=    \" + (Math.round(this.sensor.Debug_3, 6)).toString() + \"\\n\"\n            msg = msg + \"DEBUG5=    \" + (Math.round(this.sensor.Debug_4, 6)).toString() + \"\\n\"\n            msg = msg + \"DEBUG6=    \" + (Math.round(this.sensor.Debug_5, 6)).toString() + \"\\n\"\n            return msg\n        }\n\n        byte2float(offset) {\n            let buffer = new ArrayBuffer(4);\n            let view = new DataView(buffer);\n\n            view.setUint8(3, this.revdata[offset + 0]);\n            view.setUint8(2, this.revdata[offset + 1]);\n            view.setUint8(1, this.revdata[offset + 2]);\n            view.setUint8(0, this.revdata[offset + 3]);\n\n            return view.getFloat32(0, false);\n        }\n\n\n        getInjectStatus(revtmp) {\n            let revdata = Buffer.alloc(this.DATAREVLEN);\n            if (revtmp.byteLength == this.DATAREVLEN) {\n                if (revtmp[0] == 0x77 && revtmp[1] == 0x78) {\n                    if (revtmp[this.BT_INDEX_REVCHECKSUM] == this.calChecksum(revtmp)) {\n                        for (let i = 0; i < revtmp.length; i++) {\n                            revdata[i] = revtmp[i];\n                        }\n                    }\n                }\n            }\n\n            if (revdata[this.BT_INDEX_CMD_REV] === this.BT_CMD_DOWNLOAD || revdata[this.BT_INDEX_CMD_REV] === this.BT_CMD_DOWNLOAD_END) {\n                let isrevsame = true;\n                for (let i = 0; i < this.packlen; i++) {\n                    if (revtmp !== revdata[i + this.BT_INDEX_CMD_REV]) {\n                        isrevsame = false;\n                        break;\n                    }\n                }\n                if (isrevsame === true) {\n                    this.nowdwpack = this.nowdwpack + 1;\n                }\n                if (revdata[this.BT_INDEX_CMD_REV] === this.BT_CMD_DOWNLOAD_END) {\n                    // IsDownload = false;\n                    // console.log(\"download success\");\n                    return true\n                }\n            }\n            else if (this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_GETFLYSTATE1) {\n                this.sensor.btkey = parseInt(revdata[2] + revdata[3] * 256)\n                this.sensor.btstick1 = parseInt(revdata[4])\n                this.sensor.btstick2 = parseInt(revdata[5])\n                this.sensor.btstick3 = parseInt(revdata[6])\n                this.sensor.btstick4 = parseInt(revdata[7])\n                this.sensor.ACC_x = this.byte2float(this.BT_INDEX_DATA_REV + 0 * 4)\n                this.sensor.ACC_y = this.byte2float(this.BT_INDEX_DATA_REV + 1 * 4)\n                this.sensor.ACC_z = this.byte2float(this.BT_INDEX_DATA_REV + 2 * 4)\n                this.sensor.Gypo_x = this.byte2float(this.BT_INDEX_DATA_REV + 3 * 4)\n                this.sensor.Gypo_y = this.byte2float(this.BT_INDEX_DATA_REV + 4 * 4)\n                this.sensor.Gypo_z = this.byte2float(this.BT_INDEX_DATA_REV + 5 * 4)\n                this.sensor.SPL06_temp = this.byte2float(this.BT_INDEX_DATA_REV + 6 * 4)\n                this.sensor.SPL06_Press = this.byte2float(this.BT_INDEX_DATA_REV + 7 * 4)\n                this.sensor.SPL06_asl = this.byte2float(this.BT_INDEX_DATA_REV + 8 * 4)\n                this.sensor.Pitch = this.byte2float(this.BT_INDEX_DATA_REV + 9 * 4)\n                this.sensor.Roll = this.byte2float(this.BT_INDEX_DATA_REV + 10 * 4)\n                this.sensor.Yaw = this.byte2float(this.BT_INDEX_DATA_REV + 11 * 4)\n                this.sensor.Battery = this.byte2float(this.BT_INDEX_DATA_REV + 12 * 4)\n                this.sensor.LaserTof = this.byte2float(this.BT_INDEX_DATA_REV + 13 * 4)\n                this.sensor.GL_X = this.byte2float(this.BT_INDEX_DATA_REV + 14 * 4)\n                this.sensor.GL_Y = this.byte2float(this.BT_INDEX_DATA_REV + 15 * 4)\n                this.sensor.timertick = this.byte2float(this.BT_INDEX_DATA_REV + 16 * 4)\n                this.sensor.M1 = parseInt(revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 0])\n                this.sensor.M2 = parseInt(revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 1])\n                this.sensor.M3 = parseInt(revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 2])\n                this.sensor.M4 = parseInt(revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 3])\n\n                this.sensor.state_velocity_x = this.byte2float(this.BT_INDEX_DATA_REV + 18 * 4)\n                this.sensor.state_velocity_y = this.byte2float(this.BT_INDEX_DATA_REV + 19 * 4)\n                this.sensor.state_velocity_z = this.byte2float(this.BT_INDEX_DATA_REV + 20 * 4)\n\n                this.sensor.Debug_0 = this.byte2float(this.BT_INDEX_DATA_REV + 21 * 4)\n                this.sensor.Debug_1 = this.byte2float(this.BT_INDEX_DATA_REV + 22 * 4)\n                this.sensor.Debug_2 = this.byte2float(this.BT_INDEX_DATA_REV + 23 * 4)\n                this.sensor.Debug_3 = this.byte2float(this.BT_INDEX_DATA_REV + 24 * 4)\n                this.sensor.Debug_4 = this.byte2float(this.BT_INDEX_DATA_REV + 25 * 4)\n                this.sensor.Debug_5 = this.byte2float(this.BT_INDEX_DATA_REV + 26 * 4)\n                this.sensor.FusedHeight = this.byte2float(this.BT_INDEX_DATA_REV + 27 * 4)\n\n                this.sensor.VER = parseInt(revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 0])\n                this.sensor.ErrFly = parseInt(revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 1])\n                let msg = this.Sensor2String();\n                // console.log(msg);\n            }\n\n            return false;\n        }\n\n        exportProject() {\n            let project = {};\n\n            project.objects = Entry.container.toJSON();\n            const objects = project.objects;\n            project.scenes = Entry.scene.toJSON();\n            project.variables = Entry.variableContainer.getVariableJSON();\n            project.messages = Entry.variableContainer.getMessageJSON();\n            project.functions = Entry.variableContainer.getFunctionJSON();\n            project.tables = DataTable.getTableJSON();\n            project.speed = Entry.FPS;\n            project.interface = Entry.captureInterfaceState();\n            project.expansionBlocks = Entry.expansionBlocks;\n            project.aiUtilizeBlocks = Entry.aiUtilizeBlocks;\n            project.hardwareLiteBlocks = Entry.hardwareLiteBlocks;\n            project.learning = Entry.aiLearning?.toJSON();\n            project.externalModules = entryModuleLoader.moduleList;\n            project.externalModulesLite = entryModuleLoader.moduleListLite;\n\n            if (!objects || !objects.length) {\n                return false;\n            }\n\n            return project;\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    template: {\n                        whalesbot_eagle_1001_lite_openning_3d_simulator: '3D 시뮬레이터를 엽니 다',\n                        whalesbot_eagle_1001_lite_clean: '삭제',\n                        whalesbot_eagle_1001_lite_restart: '재시작',\n                        whalesbot_eagle_1001_lite_get_status: '상태 가져오기',\n                        whalesbot_eagle_1001_lite_entering_pitch_mode: '준비모드 시작하기',\n                        whalesbot_eagle_1001_lite_exit_pitch_mode: '준비모드 끝내기',\n                        whalesbot_eagle_1001_lite_automatic_take_off_height: '자동 이륙 높이 %1 cm',\n                        whalesbot_eagle_1001_lite_automatic_take_off_altitude_speed_offset: '자동 이륙 고도 %1 cm 속도 %2 X 오프셋 %3 도 Y 오프셋 %4 도 으로 이동하기',\n                        whalesbot_eagle_1001_lite_automatic_landing: '드론착륙',\n                        whalesbot_eagle_1001_lite_automatic_descent_speed_offset: '자동 낙하 속도 %1 X 오프셋 %2 도 Y 오프셋 %3 도',\n                        whalesbot_eagle_1001_lite_set_the_flight_speed: '설정된 비행 속도는 %1 cm/s',\n                        whalesbot_eagle_1001_lite_get_setting_speed: '설정 속도 가져오기',\n                        whalesbot_eagle_1001_lite_rise: '위로 %1 cm',\n                        whalesbot_eagle_1001_lite_down: '아래로 %1 cm',\n                        whalesbot_eagle_1001_lite_fly_forward: '앞으로 %1 cm',\n                        whalesbot_eagle_1001_lite_fly_backward: '뒤로 %1 cm',\n                        whalesbot_eagle_1001_lite_fly_left: '왼쪽으로 %1 cm',\n                        whalesbot_eagle_1001_lite_fly_right: '오른쪽으로 %1 cm',\n                        whalesbot_eagle_1001_lite_turn_left: '왼쪽으로 회전 %1 °',\n                        whalesbot_eagle_1001_lite_turn_right: '오른쪽으로 회전 %1 °',\n                        whalesbot_eagle_1001_lite_fly_in_the_specified_direction: '속도 %1 , 방향 %2 으로이동하기',\n                        whalesbot_eagle_1001_lite_flight_designated: '지정된 거리를 비행합니다 x %1 cm y %2 cm z%3 cm 속도 %4 cm/s',\n                        whalesbot_eagle_1001_lite_set_the_four_channel_lever_quantity_of_remote_control: '리모컨 4개 채널 설정 Pitch %1 Roll %2 Throttle %3 Yaw %4',\n                        whalesbot_eagle_1001_lite_stop_moving_and_hover: '호버링기능',\n                        whalesbot_eagle_1001_lite_hover_at_specified_altitude: '지정된 높이에 서스펜션 %1 cm',\n                        whalesbot_eagle_1001_lite_emergency_stop: '긴급정지',\n                        whalesbot_eagle_1001_lite_set_the_steering_gear: '스티어링기어 ID 설정 포트 %1 속도 %2 각도 %3',\n                        whalesbot_eagle_1001_lite_execute_script: '스크립트 실행',\n                        // light & speaker blocks\n                        whalesbot_eagle_1001_lite_ls_debug_value: '센서 값 확인 %1 %2',\n                        whalesbot_eagle_1001_lite_ls_display_symbol: '도트매트릭스 %1 포트 %2',\n                        whalesbot_eagle_1001_lite_ls_off_LED: '표현스크린 닫기 포트 %1',\n                        whalesbot_eagle_1001_lite_ls_display_digital_tube: '디지털튜브 포트 %1 %2',\n                        whalesbot_eagle_1001_lite_ls_display_digital_tube_score: '디지털튜브에 점수 표시 포트 %1 %2 : %3',\n                        whalesbot_eagle_1001_lite_ls_off_digital_tube: '디지털튜브 닫기 포트 %1',\n                        whalesbot_eagle_1001_lite_ls_set_RGB: 'LED색상설정 포트 %1 색상 R %2 G %3 B %4',\n                        whalesbot_eagle_1001_lite_ls_fly_RGB: 'Led 조명인가요? %1',\n                        whalesbot_eagle_1001_lite_ls_set_DO: '전자석 포트 %1 %2',\n                        whalesbot_eagle_1001_lite_ls_execute_script: '동작 없이 스크립트 실행',\n                        // sensors\n                        whalesbot_eagle_1001_lite_ss_fly_state_POS_Z: '비행 고도 cm',\n                        whalesbot_eagle_1001_lite_ss_fly_state_LASER: '동체 내부 레이저 거리 측정 cm',\n                        whalesbot_eagle_1001_lite_ss_battery_voltage: '배터리 전압 (V)',\n                        whalesbot_eagle_1001_lite_ss_fly_state_STATE_TEMP: '메인보드 온도 (°)',\n                        whalesbot_eagle_1001_lite_ss_attitude_angle: '자세각 %1 (°)',\n                        whalesbot_eagle_1001_lite_ss_flight_angular_velocity: '비행각속도 %1 cm/s',\n                        whalesbot_eagle_1001_lite_ss_flight_acceleration: '비행 가속도 %1 (1g)',\n                        whalesbot_eagle_1001_lite_ss_optical_flow: '광류 %1 (cm)',\n                        whalesbot_eagle_1001_lite_ss_get_infrared_distance: '적외선센 포트 %1 값',\n                        whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_bool: '적외선센서 포트 %1 장애물 감지',\n                        whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_string: '적외선센서 포트 %1 장애물 감지',\n                        whalesbot_eagle_1001_lite_ss_human_infrared_value_bool: '인체 감지 센서 포트 %1 사람을 감지하다',\n                        whalesbot_eagle_1001_lite_ss_human_infrared_value_string: '인체 감지 센서 포트 %1 사람을 감지하다',\n                        whalesbot_eagle_1001_lite_ss_AI: '아날로그 입력 포트 %1 값',\n                        whalesbot_eagle_1001_lite_ss_get_ultrasonic_distance: '초음파센서 포트 %1 거리 강지 cm',\n                        whalesbot_eagle_1001_lite_ss_get_ambient_light: '조도센서 입력 포트 %1 값',\n                        whalesbot_eagle_1001_lite_ss_get_temperature: '온도 센서 포트 %1 °C',\n                        whalesbot_eagle_1001_lite_ss_get_humidity: '습도 센서 포트 %1 값 %',\n                        whalesbot_eagle_1001_lite_ss_get_flame: '불꽃센서 포트 %1 값',\n                        whalesbot_eagle_1001_lite_ss_get_gesture: '동작인식 포트 %1',\n                        whalesbot_eagle_1001_lite_ss_get_tof: '레이저 거리 측정 포트 %1',\n                        whalesbot_eagle_1001_lite_ss_fly_setpoint_LASER_ENABLE: '레이저 높이 %1',\n                        whalesbot_eagle_1001_lite_ss_get_bt_remote_control: '리모콘 버튼 %1 값',\n                        whalesbot_eagle_1001_lite_ss_seconds: '현재 타이머 값',\n                        whalesbot_eagle_1001_lite_ss_resettime: '타이머 재설정',\n                    },\n                    Device: {\n                        whalesbot_eagle_1001_lite_lite: 'whalesbot_eagle_1001_lite_lite',\n                    },\n                    Menus: {\n                        whalesbot_eagle_1001_lite_lite: 'WhalesbotEagle1001Lite',\n                    },\n                    Blocks: {\n                        light_speaker: {\n                            electro_magnet: { absorption: '붙다', break_off: '떨어지다' },\n                        },\n                        sensor: {\n                            attitude_angle: { pitch: 'Pitch', roll: 'Roll', yaw: 'Yaw' },\n                            laser_height_determination: { on: 'On', off: 'Off' },\n                            remote_control_button: { key: 'Key', left_rocker_x: 'Left rocker X', left_rocker_y: 'Left rocker Y', right_rocker_x: 'Right rocker X', right_rocker_y: 'Right rocker Y' },\n                        },\n                        whalesbot_eagle_1001_lite_toast_status_title: \"드론 상태\",\n                        whalesbot_eagle_1001_lite_toast_prepare_download: \"다운로드 준비...\",\n                        whalesbot_eagle_1001_lite_toast_downloading_code: \"코드 다운로드...\",\n                        whalesbot_eagle_1001_lite_toast_download_success: \"다운로드 코드가 성공했습니다\",\n                        whalesbot_eagle_1001_lite_toast_download_failed: \"다운로드 코드가 실패했습니다\",\n                        whalesbot_eagle_1001_lite_toast_clean_failed: \"깨끗한 코드가 실패했습니다\",\n                        whalesbot_eagle_1001_lite_toast_clean_success: \"깨끗한 코드 성공\",\n                        whalesbot_eagle_1001_lite_toast_unsupport_block_title: \"지원되지 않는 블록\",\n                        whalesbot_eagle_1001_lite_toast_unsupport_block_msg: \"하드웨어에서는 일부 블록이 지원되지 않습니다\"\n                    }\n                },\n                en: {\n                    template: {\n                        whalesbot_eagle_1001_lite_openning_3d_simulator: 'Open 3D Simulator',\n                        whalesbot_eagle_1001_lite_clean: 'Clean',\n                        whalesbot_eagle_1001_lite_restart: 'Restart',\n                        whalesbot_eagle_1001_lite_get_status: 'Get Status',\n                        whalesbot_eagle_1001_lite_entering_pitch_mode: 'Entering Pitch Mode',\n                        whalesbot_eagle_1001_lite_exit_pitch_mode: 'Exit Pitch Mode',\n                        whalesbot_eagle_1001_lite_automatic_take_off_height: 'Automatic Take Off Height %1 cm',\n                        whalesbot_eagle_1001_lite_automatic_take_off_altitude_speed_offset: 'Automatic Take Off Altitude %1 cm, Speed %2, X offset %3 degree, Y offset %4 degree',\n                        whalesbot_eagle_1001_lite_automatic_landing: 'Automatic Landing',\n                        whalesbot_eagle_1001_lite_automatic_descent_speed_offset: 'Automatic Descent Speed %1, X offset %2 degree, Y offset %3 degree',\n                        whalesbot_eagle_1001_lite_set_the_flight_speed: 'Set The Flight Speed To %1 cm/s',\n                        whalesbot_eagle_1001_lite_get_setting_speed: 'Get Setting Speed',\n                        whalesbot_eagle_1001_lite_rise: 'Rise %1 cm',\n                        whalesbot_eagle_1001_lite_down: 'Down %1 cm',\n                        whalesbot_eagle_1001_lite_fly_forward: 'Fly Forward %1 cm',\n                        whalesbot_eagle_1001_lite_fly_backward: 'Fly Backward %1 cm',\n                        whalesbot_eagle_1001_lite_fly_left: 'Fly Left %1 cm',\n                        whalesbot_eagle_1001_lite_fly_right: 'Fly Right %1 cm',\n                        whalesbot_eagle_1001_lite_turn_left: 'Turn Left %1 °',\n                        whalesbot_eagle_1001_lite_turn_right: 'Turn Right %1 °',\n                        whalesbot_eagle_1001_lite_fly_in_the_specified_direction: 'Fly In The Specified Direction Speed %1 cm/s Direction %2 °',\n                        whalesbot_eagle_1001_lite_flight_designated: 'Flight Designated Distance X %1 cm Y %2 cm Z %3 cm Speed %4 cm/s',\n                        whalesbot_eagle_1001_lite_set_the_four_channel_lever_quantity_of_remote_control: 'Set The Four Channel Lever Quantity Of Remote Control Pitch %1° Roll %2° Throttle %3° Roll %4°',\n                        whalesbot_eagle_1001_lite_stop_moving_and_hover: 'Stop Moving And Hover',\n                        whalesbot_eagle_1001_lite_hover_at_specified_altitude: 'Hover At a Specified Altitude %1 cm',\n                        whalesbot_eagle_1001_lite_emergency_stop: 'Emergency Stop',\n                        whalesbot_eagle_1001_lite_set_the_steering_gear: 'Set The Steering Gear Port %1 Speed %2 cm/s Angle %3 °',\n                        whalesbot_eagle_1001_lite_execute_script: 'Execute Script',\n                        // light & speaker blocks\n                        whalesbot_eagle_1001_lite_ls_debug_value: 'Debugging: Data %1 %2',\n                        whalesbot_eagle_1001_lite_ls_display_symbol: 'Emotion screen symbols %1 port %2',\n                        whalesbot_eagle_1001_lite_ls_off_LED: 'Clear emotion screen port %1',\n                        whalesbot_eagle_1001_lite_ls_display_digital_tube: 'Digital tube port %1 %2',\n                        whalesbot_eagle_1001_lite_ls_display_digital_tube_score: 'Digital tube score display port %1 %2 : %3',\n                        whalesbot_eagle_1001_lite_ls_off_digital_tube: 'Clear digital tube port %1',\n                        whalesbot_eagle_1001_lite_ls_set_RGB: 'Set LED lights port %1 color R %2 G %3 B %4',\n                        whalesbot_eagle_1001_lite_ls_fly_RGB: 'Airborne lighting %1',\n                        whalesbot_eagle_1001_lite_ls_set_DO: 'Electromagnet port %1 %2',\n                        whalesbot_eagle_1001_lite_ls_execute_script: 'Execute Script Without Motion',\n                        // sensors\n                        whalesbot_eagle_1001_lite_ss_fly_state_POS_Z: 'Flight attitude cm',\n                        whalesbot_eagle_1001_lite_ss_fly_state_LASER: 'Laser ranging inside the fuselage cm',\n                        whalesbot_eagle_1001_lite_ss_battery_voltage: 'Battery voltage (V)',\n                        whalesbot_eagle_1001_lite_ss_fly_state_STATE_TEMP: 'Main board temperature (°C)',\n                        whalesbot_eagle_1001_lite_ss_attitude_angle: 'Attitude angle %1 (°)',\n                        whalesbot_eagle_1001_lite_ss_flight_angular_velocity: 'Flight angular velocity %1 cm/s',\n                        whalesbot_eagle_1001_lite_ss_flight_acceleration: 'Flight acceleration %1 (1g)',\n                        whalesbot_eagle_1001_lite_ss_optical_flow: 'Optical flow %1 (cm)',\n                        whalesbot_eagle_1001_lite_ss_get_infrared_distance: 'Infrared ranging sensor port %1 value',\n                        whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_bool: 'Infrared port %1 obstacle detected',\n                        whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_string: 'Infrared port %1 obstacle detected',\n                        whalesbot_eagle_1001_lite_ss_human_infrared_value_bool: 'Human infrared sensor port %1 detects a person',\n                        whalesbot_eagle_1001_lite_ss_human_infrared_value_string: 'Human infrared sensor port %1 detects a person',\n                        whalesbot_eagle_1001_lite_ss_AI: 'Analog input port %1 value',\n                        whalesbot_eagle_1001_lite_ss_get_ultrasonic_distance: 'Ultrasonic sensor port %1 detect distance cm',\n                        whalesbot_eagle_1001_lite_ss_get_ambient_light: 'Ambient light port %1 value',\n                        whalesbot_eagle_1001_lite_ss_get_temperature: 'Temperature sensor port %1 °C',\n                        whalesbot_eagle_1001_lite_ss_get_humidity: 'Humidity sensor port %1 value %',\n                        whalesbot_eagle_1001_lite_ss_get_flame: 'Flame sensor port %1 value',\n                        whalesbot_eagle_1001_lite_ss_get_gesture: 'Gesture recognition port %1',\n                        whalesbot_eagle_1001_lite_ss_get_tof: 'Laser ranging port %1',\n                        whalesbot_eagle_1001_lite_ss_fly_setpoint_LASER_ENABLE: 'Laser height determination %1',\n                        whalesbot_eagle_1001_lite_ss_get_bt_remote_control: 'Remote control button %1 value',\n                        whalesbot_eagle_1001_lite_ss_seconds: 'current timer value',\n                        whalesbot_eagle_1001_lite_ss_resettime: 'Reset timer',\n                    },\n                    Device: {\n                        whalesbot_eagle_1001_lite_lite: 'whalesbot_eagle_1001_lite_lite',\n                    },\n                    Menus: {\n                        whalesbot_eagle_1001_lite_lite: 'WhalesbotEagle1001Lite',\n                    },\n                    Blocks: {\n                        light_speaker: {\n                            electro_magnet: { absorption: 'Absorption', break_off: 'Break off' },\n                        },\n                        sensor: {\n                            attitude_angle: { pitch: 'Pitch', roll: 'Roll', yaw: 'Yaw' },\n                            laser_height_determination: { on: 'On', off: 'Off' },\n                            remote_control_button: { key: 'Key', left_rocker_x: 'Left rocker X', left_rocker_y: 'Left rocker Y', right_rocker_x: 'Right rocker X', right_rocker_y: 'Right rocker Y' },\n                        },\n                        whalesbot_eagle_1001_lite_toast_status_title: \"Drone Status\",\n                        whalesbot_eagle_1001_lite_toast_prepare_download: \"Prepare Downloading...\",\n                        whalesbot_eagle_1001_lite_toast_downloading_code: \"Downloading Code...\",\n                        whalesbot_eagle_1001_lite_toast_download_success: \"Download Code Successed\",\n                        whalesbot_eagle_1001_lite_toast_download_failed: \"Download code failed\",\n                        whalesbot_eagle_1001_lite_toast_clean_failed: \"Clean code failed\",\n                        whalesbot_eagle_1001_lite_toast_clean_success: \"Clean code success\",\n                        whalesbot_eagle_1001_lite_toast_unsupport_block_title: \"Unsupport Block\",\n                        whalesbot_eagle_1001_lite_toast_unsupport_block_msg: \"There is some blocks is not supported by hardware\"\n                    }\n                },\n            };\n        }\n\n        getBlocks() {\n            const blockColors = {\n                color: {\n                    light_speaker: '#5b90ff',\n                    sensor: '#8066f9'\n                },\n                outerLine: {\n                    light_speaker: '#2b6eff',\n                    sensor: '#8a6bf0'\n                },\n            }\n\n            const notificationType = {\n                \"SUCCESS\": \"success\",\n                \"UNSUPPORTED\": \"unsupported\",\n                \"ALERT\": \"alert\",\n            }\n\n            let cFunctions = [];\n            let _this = this;\n            let sourceCode;\n\n            const defaultSpeed = \"10\";\n            const defaultAltitude = \"50\";\n            const defaultOffset = \"0\";\n\n            const wbOperators = {\n                \"EQUAL\": \"==\",\n                \"NOT_EQUAL\": \"!=\",\n                \"GREATER\": \">\",\n                \"GREATER_OR_EQUAL\": \">=\",\n                \"LESS\": \"<\",\n                \"LESS_OR_EQUAL\": \"<=\",\n                \"AND\": \"&&\",\n                \"OR\": \"||\",\n            };\n\n            const wbVariables = {\n                'whalesbot_eagle_1001_lite_get_setting_speed': 'fly_state(SETSPEED)',\n                'whalesbot_eagle_1001_lite_ss_fly_state_POS_Z': 'fly_state(POS_Z)',\n                'whalesbot_eagle_1001_lite_ss_fly_state_LASER': 'fly_state(LASER)',\n                'whalesbot_eagle_1001_lite_ss_battery_voltage': 'battery()',\n                'whalesbot_eagle_1001_lite_ss_fly_state_STATE_TEMP': 'fly_state(STATE_TEMP)',\n                'whalesbot_eagle_1001_lite_ss_attitude_angle': 'fly_state($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_flight_angular_velocity': 'fly_state($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_flight_acceleration': 'fly_state($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_optical_flow': 'fly_state($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_infrared_distance': 'get_infrared_distance($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_string': 'obstacle_infrared_detected($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_bool': 'obstacle_infrared_detected($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_human_infrared_value_string': 'human_infrared_value($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_human_infrared_value_bool': 'human_infrared_value($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_AI': 'AI($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_ultrasonic_distance': 'get_ultrasonic_distance($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_ambient_light': 'get_ambient_light($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_temperature': 'get_temperature($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_humidity': 'get_humidity($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_flame': 'get_flame($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_gesture': 'get_gesture($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_tof': 'get_tof($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_get_bt_remote_control': 'get_bt_remote_control($VALUE)',\n                'whalesbot_eagle_1001_lite_ss_seconds': 'seconds()',\n            }\n\n            const startBlocks = [\n                \"when_run_button_click\",\n                \"when_some_key_pressed\",\n                \"mouse_clicked\",\n                \"mouse_click_cancled\",\n                \"when_object_click\",\n                \"when_object_click_canceled\",\n                'whalesbot_eagle_1001_lite_execute_script',\n                'whalesbot_eagle_1001_lite_ls_debug_value',\n                'whalesbot_eagle_1001_lite_ls_display_symbol',\n                'whalesbot_eagle_1001_lite_ls_off_LED',\n                'whalesbot_eagle_1001_lite_ls_display_digital_tube',\n                'whalesbot_eagle_1001_lite_ls_display_digital_tube_score',\n                'whalesbot_eagle_1001_lite_ls_off_digital_tube',\n                'whalesbot_eagle_1001_lite_ls_set_RGB',\n                'whalesbot_eagle_1001_lite_ls_fly_RGB',\n                'whalesbot_eagle_1001_lite_ls_set_DO',\n                // 'whalesbot_eagle_1001_lite_ls_execute_script',\n            ]\n\n            let globlalCVariables = {}\n\n            function _getParameter(parameter) {\n                let param = parameter.params[0] != \"\" ? parameter.params[0] : \"0\"\n                if (parameter.type != \"text\" && parameter.type != \"number\" && parameter.type != \"get_variable\") {\n                    let raw_param = wbVariables[parameter.type]\n                    param = raw_param.includes(\"$VALUE\") ? raw_param.replace(\"$VALUE\", parameter.params[0]) : raw_param;\n                } else if (parameter.type == \"get_variable\") {\n                    param = globlalCVariables[parameter.params[0]]\n                }\n                return param\n            }\n\n            function _generateConditions(params) {\n                let left = _getParameter(params[0])\n                let operator = params[1] != undefined ? wbOperators[params[1]] : \"0\"\n                let right = _getParameter(params[2])\n                return { left, operator, right }\n            }\n\n            function generateCCode(block) {\n                switch (block.type) {\n                    // LOOP\n                    case 'repeat_basic':\n                        let times = _getParameter(block.params[0]);\n                        return `\\tfor(int i=0; i<${times}; ++i) {\\n${block.statements[0].map((generateCCode)).join('')}\\t}\\n`;\n\n                    case 'repeat_inf':\n                        return `\\twhile(1) {\\n${block.statements[0].map(generateCCode).join('')}\\t}\\n`;\n\n                    case 'repeat_while_true':\n                        let rpWhileDecision = {\n                            \"type\": block.params[0].type,\n                            \"params\": block.params[0].params,\n                        };\n                        let rpWhileMark = block.params[1] == 'until' ? '!' : '';\n                        return `\\twhile(${rpWhileMark}(${generateCCode(rpWhileDecision)})) {\\n${block.statements[0].map(generateCCode).join('')}\\t}\\n`;\n\n                    case 'wait_second':\n                        let second = _getParameter(block.params[0]);\n                        return `\\twait(${second});\\n`;\n\n                    case 'wait_until_true':\n                        let waitUntilTrueDecision = {\n                            \"type\": block.params[0].type,\n                            \"params\": block.params[0].params,\n                        };\n                        return `\\twhile(!(${generateCCode(waitUntilTrueDecision)})) {\\n\\t}\\n`;\n\n                    case 'stop_repeat':\n                        return `\\tbreak;\\n`;\n\n                    // CONDITION\n                    case '_if':\n                        let ifDecision = {\n                            \"type\": block.params[0].type,\n                            \"params\": block.params[0].params,\n                        };\n                        return `\\tif(${generateCCode(ifDecision)}) {\\n${block.statements[0].map(generateCCode).join('')}\\t}\\n`;\n\n                    case 'if_else':\n                        let ifElseDecision = {\n                            \"type\": block.params[0].type,\n                            \"params\": block.params[0].params,\n                        };\n                        return `\\tif(${generateCCode(ifElseDecision)}) {\\n${block.statements[0].map(generateCCode).join('')}\\t} else {\\n${block.statements[1].map(generateCCode).join('')}\\t}\\n`;\n\n                    // DECISION\n                    case 'boolean_and_or':\n                        let boolAndOrBasicLeftValue = generateCCode(block.params[0]);\n                        let boolAndOrBasicOperator = wbOperators[block.params[1]];\n                        let boolAndOrBasicRightValue = generateCCode(block.params[2]);\n                        return `(${boolAndOrBasicLeftValue} ${boolAndOrBasicOperator} ${boolAndOrBasicRightValue})`;\n\n                    case 'boolean_not':\n                        let boolNotDecision = generateCCode(block.params[1]);\n                        return `!(${boolNotDecision})`;\n\n                    case 'boolean_basic_operator':\n                        let boolBasicCondition = \"0\"\n                        if (block.params[0].params[0] != null) {\n                            let boolBasicLeftValue = _generateConditions(block.params).left;\n                            let boolBasicOperator = _generateConditions(block.params).operator;\n                            let boolBasicRightValue = _generateConditions(block.params).right;\n                            boolBasicCondition = `(${boolBasicLeftValue} ${boolBasicOperator} ${boolBasicRightValue})`;\n                        }\n                        return `${boolBasicCondition}`;\n\n                    // VARIABLE\n                    case 'True':\n                        return \"1\";\n\n                    case 'False':\n                        return \"0\";\n\n                    case 'set_variable':\n                        let variableName = globlalCVariables[block.params[0]];\n                        let variableValue = _getParameter(block.params[1]);\n                        return `\\t${variableName} = ${variableValue};\\n`;\n\n                    case 'change_variable':\n                        let changedVariableName = globlalCVariables[block.params[0]];\n                        let changedVariableValue = _getParameter(block.params[1]);\n                        return `\\t${changedVariableName} += ${changedVariableValue};\\n`;\n\n                    // HARDWARE\n                    case 'whalesbot_eagle_1001_lite_entering_pitch_mode':\n                        return '\\tfly_unlock();\\n';\n\n                    case 'whalesbot_eagle_1001_lite_exit_pitch_mode':\n                        return '\\tfly_lock();\\n';\n\n                    case 'whalesbot_eagle_1001_lite_automatic_take_off_height':\n                        let takeOffHeight = _getParameter(block.params[0]);\n                        return `\\tfly_start(${takeOffHeight});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_automatic_take_off_altitude_speed_offset':\n                        let takeOffAltitude = _getParameter(block.params[0]) != \"\" ? _getParameter(block.params[0]) : defaultAltitude;\n                        let takeOffSpeed = _getParameter(block.params[1]) != \"\" ? _getParameter(block.params[1]) : defaultSpeed;\n                        let takeOffXoffset = (-10.00 <= _getParameter(block.params[2]) || _getParameter(block.params[2]) <= 10.00) ? _getParameter(block.params[2]) : defaultOffset;\n                        let takeOffYoffset = (-10.00 <= _getParameter(block.params[3]) || _getParameter(block.params[3]) <= 10.00) ? _getParameter(block.params[3]) : defaultOffset;\n                        return `\\tfly_start_2(${takeOffAltitude},${takeOffSpeed},${takeOffXoffset},${takeOffYoffset});\\n`\n\n                    case 'whalesbot_eagle_1001_lite_automatic_landing':\n                        return `\\tfly_land();\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_automatic_descent_speed_offset':\n                        let automaticSpeed = _getParameter(block.params[0]) != \"\" ? _getParameter(block.params[0]) : defaultSpeed;\n                        let automaticXoffset = (-10.00 <= _getParameter(block.params[1]) || _getParameter(block.params[1]) <= 10.00) ? _getParameter(block.params[1]) : defaultOffset;\n                        let automaticYoffset = (-10.00 <= _getParameter(block.params[2]) || _getParameter(block.params[2]) <= 10.00) ? _getParameter(block.params[2]) : defaultOffset;\n                        return `\\tfly_land_2(${automaticSpeed},${automaticXoffset},${automaticYoffset});\\n`\n\n                    case 'whalesbot_eagle_1001_lite_set_the_flight_speed':\n                        let speed = _getParameter(block.params[0]);\n                        return `\\tfly_setspeed(${speed});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_rise':\n                        let up = _getParameter(block.params[0]);\n                        return `\\tfly_moveto(UP,${up});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_down':\n                        let down = _getParameter(block.params[0]);\n                        return `\\tfly_moveto(DOWN,${down});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_fly_forward':\n                        let front = _getParameter(block.params[0]);\n                        return `\\tfly_moveto(FRONT,${front});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_fly_backward':\n                        let back = _getParameter(block.params[0]);\n                        return `\\tfly_moveto(BACK,${back});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_fly_left':\n                        let left = _getParameter(block.params[0]);\n                        return `\\tfly_moveto(LEFT,${left});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_fly_right':\n                        let right = _getParameter(block.params[0]);\n                        return `\\tfly_moveto(RIGHT,${right});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_turn_left':\n                        let turnLeft = _getParameter(block.params[0]);\n                        if (0 > turnLeft || turnLeft > 360) {\n                            turnLeft = 360\n                        }\n                        return `\\tfly_turn(CCW,${turnLeft});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_turn_right':\n                        let turnRight = _getParameter(block.params[0]);\n                        if (0 > turnRight || turnRight > 360) {\n                            turnRight = 360\n                        }\n                        return `\\tfly_turn(CW,${turnRight});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_fly_in_the_specified_direction':\n                        let dirSpeed = _getParameter(block.params[0]);\n                        let dirDirection = _getParameter(block.params[1]);\n                        if (0 > dirDirection || dirDirection > 360) {\n                            dirDirection = 360\n                        }\n                        return `\\tfly_dir(${dirSpeed},${dirDirection});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_flight_designated':\n                        let disX = _getParameter(block.params[0]);\n                        let disY = _getParameter(block.params[1]);\n                        let disZ = _getParameter(block.params[2]);\n                        let disSpeed = _getParameter(block.params[3]);\n                        return `\\tfly_move_dis(${disX},${disY},${disZ},${disSpeed});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_set_the_four_channel_lever_quantity_of_remote_control':\n                        let pitch = _getParameter(block.params[0]);\n                        let roll = _getParameter(block.params[1]);\n                        let throttle = _getParameter(block.params[2]);\n                        let yaw = _getParameter(block.params[3]);\n                        return `\\tfly_move(${pitch},${roll},${throttle},${yaw});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_stop_moving_and_hover':\n                        return `\\tfly_hover();\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_hover_at_specified_altitude':\n                        let hoverSpecifiedAltitude = (_getParameter(block.params[0]) == \"\" || _getParameter(block.params[0]) < 20) ? \"20\" : _getParameter(block.params[0]);\n                        hoverSpecifiedAltitude = (_getParameter(block.params[0]) > 200) ? \"200\" : _getParameter(block.params[0]);\n                        return `\\tfly_hover_laser(${hoverSpecifiedAltitude});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_emergency_stop':\n                        return `\\tfly_lock();\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_set_the_steering_gear':\n                        let servoSpeed = _getParameter(block.params[1]);\n                        let servoAngle = _getParameter(block.params[2]);\n                        if (0 > servoAngle || servoAngle > 360) {\n                            servoAngle = 360\n                        }\n                        return `\\tSetServo(P2,${servoSpeed},${servoAngle});\\n`;\n\n                    // light & speaker blocks\n                    case 'whalesbot_eagle_1001_lite_ls_debug_value':\n                        let lsDebugValue1 = _getParameter(block.params[0]);\n                        let lsDebugValue2 = _getParameter(block.params[1]);\n                        return `\\tDebugValue(${lsDebugValue1}, ${lsDebugValue2});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ls_display_symbol':\n                        let lsDisplaySymbol = block.params[0];\n                        let lsDisplaySymbolPort = block.params[1];\n                        return `\\tdisplay_symbol(${lsDisplaySymbolPort}, ${lsDisplaySymbol});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ls_off_LED':\n                        let lsOffLedPort = block.params[0];\n                        return `\\toff_LED(${lsOffLedPort});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ls_display_digital_tube':\n                        let lsDisplayDigitalTubePort = block.params[0];\n                        let lsDisplayDigitalTubeValue = _getParameter(block.params[1]);\n                        return `\\tdisplay_digital_tube(${lsDisplayDigitalTubePort}, ${lsDisplayDigitalTubeValue});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ls_display_digital_tube_score':\n                        let lsDisplayDigitalTubeScorePort = block.params[0];\n                        let lsDisplayDigitalTubeScoreValue1 = _getParameter(block.params[1]);\n                        let lsDisplayDigitalTubeScoreValue2 = _getParameter(block.params[2]);\n                        return `\\tdisplay_digital_tube_score(${lsDisplayDigitalTubeScorePort}, ${lsDisplayDigitalTubeScoreValue1}, ${lsDisplayDigitalTubeScoreValue2});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ls_off_digital_tube':\n                        let lsOffDigitalTubePort = block.params[0];\n                        return `\\toff_digital_tube(${lsOffDigitalTubePort});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ls_set_RGB':\n                        let lsSetRGBPort = block.params[0];\n                        let lsSetRGBR = _getParameter(block.params[1]);\n                        let lsSetRGBG = _getParameter(block.params[2]);\n                        let lsSetRGBB = _getParameter(block.params[3]);\n                        return `\\tset_RGB(${lsSetRGBPort}, ${lsSetRGBR}, ${lsSetRGBG}, ${lsSetRGBB});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ls_fly_RGB':\n                        let lsFlyRGB = block.params[0];\n                        // let lsFlyRGBR = _getParameter(block.params[1]);\n                        // let lsFlyRGBG = _getParameter(block.params[2]);\n                        // let lsFlyRGBB = _getParameter(block.params[3]);\n                        return `\\tfly_RGB(${lsFlyRGB});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ls_set_DO':\n                        let lsSetDOPort = block.params[0];\n                        let lsSetDOValue = block.params[1];\n                        return `\\tSetDO(${lsSetDOPort}, ${lsSetDOValue});\\n`;\n\n                    // sensors\n                    case 'whalesbot_eagle_1001_lite_ss_fly_setpoint_LASER_ENABLE':\n                        let ssFlySetpointToggle = block.params[0];\n                        return `\\tfly_setpoint(LASER_ENABLE, ${ssFlySetpointToggle});\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ss_resettime':\n                        return `\\tresettime();\\n`;\n\n                    case 'whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_bool':\n                        let ssBbstacleInfraredDetectedBool = block.params[0];\n                        return `obstacle_infrared_detected(${ssBbstacleInfraredDetectedBool})`;\n\n                    default:\n                        if (!startBlocks.includes(block.type)) {\n                            _this.unsupportBlockExist = true;\n                        }\n                        return '';\n                }\n            }\n\n            function setUpCVariables(variable) {\n                if (variable.visible) {\n                    const varName = `var_${variable.name}`\n                    globlalCVariables[variable.id] = varName\n                    const varValue = variable.value;\n                    return `float ${varName} = ${varValue};\\n`\n                }\n                return \"\"\n            }\n\n            function openedSimulatorPopup() {\n                if (_this.simulatorPopup == null) {\n                    return false;\n                }\n                return !_this.simulatorPopup.closed;\n            }\n\n            function notify(type, msg) {\n                switch (type) {\n                    case notificationType[\"SUCCESS\"]:\n                        Entry.toast.success(\n                            Lang.Blocks.whalesbot_mc_102_toast_success_title,\n                            msg\n                        );\n                        break;\n                    default:\n                        Entry.toast.alert(\n                            Lang.Blocks.whalesbot_mc_102_toast_alert_title,\n                            msg\n                        );\n                }\n            }\n\n            return {\n                whalesbot_eagle_1001_lite_openning_3d_simulator: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_without_next',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_openning_3d_simulator',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const width = window.innerWidth * 0.8;\n                        const height = window.innerHeight * 0.8;\n                        _this.simulatorPopup = window.open(\n                            metadata.simulator_url,\n                            'DroneSimulatorPopup',\n                            `width=${width},height=${height}`\n                        );\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_openning_3d_simulator()'] },\n                },\n                whalesbot_eagle_1001_lite_restart: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_without_next',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/moving_icon.svg',\n                            size: 11,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_restart',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        await _this.sendPacket(_this.getStateCode);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_restart()'] },\n                },\n                whalesbot_eagle_1001_lite_clean: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_without_next',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/moving_icon.svg',\n                            size: 11,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_clean',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        await _this.sendPacket(_this.stopCode);\n                        await _this.sendPacket(_this.stopCode);\n                        Entry.toast.success(Lang.Blocks.whalesbot_eagle_1001_lite_toast_status_title,\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_clean_success);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_clean()'] },\n                },\n                whalesbot_eagle_1001_lite_get_status: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/moving_icon.svg',\n                            size: 11,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_get_status',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        await _this.handleGetStatus();\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_get_status()'] },\n                },\n                whalesbot_eagle_1001_lite_entering_pitch_mode: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_entering_pitch_mode',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        await _this.sendPacket(_this.getStateCode);\n                        await _this.sendPacket(_this.getStateCode);\n                        cFunctions.push(`fly_unlock();`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_entering_pitch_mode()'] },\n                },\n                whalesbot_eagle_1001_lite_exit_pitch_mode: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_without_next',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_exit_pitch_mode',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        const project = _this.exportProject();\n                        const listVariables = project.variables;\n                        const rawScript = project.objects[0].script;\n                        const allScript = JSON.parse(rawScript);\n                        const droneScript = allScript.filter((arr) => arr.length > 2);\n\n                        sourceCode = `#include \"whalesbot.h\"\\n${listVariables.map(setUpCVariables).join('')}\\nvoid user_main() {\\n`;\n                        sourceCode += `${droneScript[0].map(generateCCode).join('')}}\\n\\nuser_main();`;\n\n                        if (_this.unsupportBlockExist) {\n                            Entry.toast.alert(\n                                Lang.Blocks.whalesbot_eagle_1001_lite_toast_unsupport_block_title,\n                                Lang.Blocks.whalesbot_eagle_1001_lite_toast_unsupport_block_msg\n                            )\n                            _this.unsupportBlockExist = false;\n                            Entry.engine.toggleStop();\n                            return;\n                        }\n                        console.log(sourceCode)\n\n                        Entry.toast.success(\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_status_title,\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_prepare_download\n                        );\n                        await _this.handleClean();\n                        await _this.sleep(3000);\n                        Entry.toast.success(\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_status_title,\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_downloading_code\n                        );\n                        await _this.downloadCode(sourceCode);\n                        await _this.sleep(4000);\n                        Entry.toast.success(\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_status_title,\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_download_success\n                        );\n                        await _this.handleRun();\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_exit_pitch_mode()'] },\n                },\n                whalesbot_eagle_1001_lite_automatic_take_off_height: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_automatic_take_off_height',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        cFunctions.push(`fly_start(${script.getValue('VALUE')})`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_automatic_take_off_height();'] },\n                },\n                whalesbot_eagle_1001_lite_automatic_take_off_altitude_speed_offset: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['100'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_automatic_take_off_altitude_speed_offset',\n                    },\n                    paramsKeyMap: {\n                        altitude: 0,\n                        speed: 1,\n                        x: 2,\n                        y: 3,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        cFunctions.push(`fly_start(${script.getValue('VALUE')})`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_automatic_take_off_altitude_speed_offset();'] },\n                },\n                whalesbot_eagle_1001_lite_automatic_landing: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_automatic_landing',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        cFunctions.push(`fly_land();`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_automatic_landing()'] },\n                },\n                whalesbot_eagle_1001_lite_automatic_descent_speed_offset: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_automatic_descent_speed_offset',\n                    },\n                    paramsKeyMap: {\n                        speed: 0,\n                        x: 1,\n                        y: 2,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        cFunctions.push(`fly_land_2();`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_automatic_descent_speed_offset()'] },\n                },\n                whalesbot_eagle_1001_lite_set_the_flight_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_set_the_flight_speed',\n                    },\n                    paramsKeyMap: {\n                        SPEED: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        const speed = script.getValue('SPEED');\n                        cFunctions.push(`fly_setspeed(${speed});`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_set_the_flight_speed()'] },\n                },\n                whalesbot_eagle_1001_lite_get_setting_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_get_setting_speed',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        cFunctions.push(`fly_state(SETSPEED);`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_get_setting_speed()'] },\n                },\n                whalesbot_eagle_1001_lite_rise: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_rise',\n                    },\n                    paramsKeyMap: {\n                        value: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const value = script.getValue('value');\n                        cFunctions.push(`fly_moveto(UP,${value})`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_rise();'] },\n                },\n                whalesbot_eagle_1001_lite_down: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_down',\n                    },\n                    paramsKeyMap: {\n                        value: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const value = script.getValue('value');\n                        cFunctions.push(`fly_moveto(DOWN,${value})`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_down();'] },\n                },\n                whalesbot_eagle_1001_lite_fly_forward: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_fly_forward',\n                    },\n                    paramsKeyMap: {\n                        value: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const value = script.getValue('value');\n                        cFunctions.push(`fly_moveto(FRONT,${value})`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_fly_forward();'] },\n                },\n                whalesbot_eagle_1001_lite_fly_backward: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_fly_backward',\n                    },\n                    paramsKeyMap: {\n                        value: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const value = script.getValue('value');\n                        cFunctions.push(`fly_moveto(BACK,${value})`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_fly_backward();'] },\n                },\n                whalesbot_eagle_1001_lite_fly_left: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_fly_left',\n                    },\n                    paramsKeyMap: {\n                        value: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const value = script.getValue('value');\n                        cFunctions.push(`fly_moveto(LEFT,${value});`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_fly_left();'] },\n                },\n                whalesbot_eagle_1001_lite_fly_right: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_fly_right',\n                    },\n                    paramsKeyMap: {\n                        value: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const value = script.getValue('value');\n                        cFunctions.push(`fly_moveto(RIGHT,${value});`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_fly_right();'] },\n                },\n                whalesbot_eagle_1001_lite_turn_left: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['90'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_turn_left',\n                    },\n                    paramsKeyMap: {\n                        value: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const value = script.getValue('value');\n                        if (value < 0 && value > 360) {\n                            value = 360\n                        }\n                        cFunctions.push(`fly_turn(CCW,${value});`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_turn_left();'] },\n                },\n                whalesbot_eagle_1001_lite_turn_right: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['90'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_turn_right',\n                    },\n                    paramsKeyMap: {\n                        value: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const value = script.getValue('value');\n                        if (value < 0 && value > 360) {\n                            value = 360\n                        }\n                        cFunctions.push(`fly_turn(CW,${value});`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_turn_right();'] },\n                },\n                whalesbot_eagle_1001_lite_fly_in_the_specified_direction: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['30'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['0'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_fly_in_the_specified_direction',\n                    },\n                    paramsKeyMap: {\n                        speed: 0,\n                        direction: 1,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const speed = script.getValue('speed');\n                        const direction = script.getValue('direction');\n                        if (direction < 0 && direction > 360) {\n                            direction = 360\n                        }\n                        cFunctions.push(`fly_dir(${speed},${direction});`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_fly_in_the_specified_direction();'] },\n                },\n                whalesbot_eagle_1001_lite_flight_designated: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['30'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_flight_designated',\n                    },\n                    paramsKeyMap: {\n                        x: 0,\n                        y: 1,\n                        z: 2,\n                        speed: 3,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const x = script.getValue('x');\n                        const y = script.getValue('y');\n                        const z = script.getValue('z');\n                        const speed = script.getValue('speed');\n                        cFunctions.push(`fly_move_dis(${x},${y},${z},${speed})`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_flight_designated();'] },\n                },\n                whalesbot_eagle_1001_lite_set_the_four_channel_lever_quantity_of_remote_control: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['50'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_set_the_four_channel_lever_quantity_of_remote_control',\n                    },\n                    paramsKeyMap: {\n                        pitch: 0,\n                        roll: 1,\n                        throttle: 2,\n                        yaw: 3,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const pitch = script.getValue('pitch');\n                        const roll = script.getValue('roll');\n                        const throttle = script.getValue('throttle');\n                        const yaw = script.getValue('yaw');\n                        cFunctions.push(`fly_move(${pitch},${roll},${throttle},${yaw});`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_set_the_four_channel_lever_quantity_of_remote_control();'] },\n                },\n                whalesbot_eagle_1001_lite_stop_moving_and_hover: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        params: [],\n                        type: 'whalesbot_eagle_1001_lite_stop_moving_and_hover',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        cFunctions.push(`fly_hover();`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_stop_moving_and_hover();'] },\n                },\n                whalesbot_eagle_1001_lite_hover_at_specified_altitude: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['20'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_hover_at_specified_altitude',\n                    },\n                    paramsKeyMap: {\n                        altitude: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        cFunctions.push(`fly_hover_laser();`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_hover_at_specified_altitude();'] },\n                },\n                whalesbot_eagle_1001_lite_emergency_stop: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_emergency_stop',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    async func(sprite, script) {\n                        cFunctions.push(`fly_lock();`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_emergency_stop()'] },\n                },\n                whalesbot_eagle_1001_lite_set_the_steering_gear: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P2', 'P2'],\n                            ],\n                            value: 'P2',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['40'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['90'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_set_the_steering_gear',\n                    },\n                    paramsKeyMap: {\n                        port: 0,\n                        speed: 1,\n                        angle: 2,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_lite',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const speed = script.getValue('speed');\n                        const angle = script.getValue('angle');\n                        cFunctions.push(`SetServo(P2,${speed},${angle});`);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_set_the_steering_gear();'] },\n                },\n                // whalesbot_eagle_1001_lite_execute_script: {\n                //     color: EntryStatic.colorSet.block.default.HARDWARE,\n                //     outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                //     fontColor: '#fff',\n                //     skeleton: 'basic_without_next',\n                //     statements: [],\n                //     params: [\n                //         {\n                //             type: 'Block',\n                //             accept: 'string',\n                //             defaultType: 'number',\n                //         },\n                //         {\n                //             type: 'Indicator',\n                //             img: 'block_icon/moving_icon.svg',\n                //             size: 11,\n                //         },\n                //     ],\n                //     events: {},\n                //     def: {\n                //         type: 'whalesbot_eagle_1001_lite_execute_script',\n                //     },\n                //     paramsKeyMap: {\n                //         VALUE: 0,\n                //     },\n                //     class: 'whalesbot_eagle_1001_lite_lite',\n                //     isNotFor: ['WhalesbotDroneLite'],\n                //     async func(sprite, script) {\n                //         if (openedSimulatorPopup()) {\n                //             _this.simulatorPopup.postMessage({\n                //                 function: \"enteringPitchMode\",\n                //                 args: [],\n                //                 script: sourceCode\n                //             }, '*');\n                //             return;\n                //         }\n                //         await _this.sendPacket(_this.runCode);\n                //     },\n                //     syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_execute_script()'] },\n                // },\n\n                // light & speaker blocks\n                whalesbot_eagle_1001_lite_ls_debug_value: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            {\n                                type: 'number',\n                                params: ['1'],\n                            },\n                            {\n                                type: 'number',\n                                params: [''],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_debug_value',\n                    },\n                    paramsKeyMap: {\n                        VALUE1: 0,\n                        VALUE2: 1,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        var value1 = Number(script.values[0]);\n                        var value2 = Number(script.values[1]);\n                        if (value1 < 1 || value1 > 6) {\n                            notify(notificationType.ALERT, 'Debugging: Data [1 ~ 6] and [0 ~ 999999]')\n                            _this.invalidParamValue = true;\n                            throw new Error();\n                        }\n                        if (value2 < 0 || value2 > 999999) {\n                            notify(notificationType.ALERT, 'Debugging: Data [1 ~ 6] and [0 ~ 999999]')\n                            _this.invalidParamValue = true;\n                            throw new Error();\n                        }\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_debug_value()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_display_symbol: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['?', 'LED_symbol_question_mark'], ['!', 'LED_symbol_exclamation'], ['$', 'LED_symbol_dollar'], ['¥', 'LED_symbol_RMB'],\n                                ['=', 'LED_symbol_equal'], ['+', 'LED_symbol_plus'], ['-', 'LED_symbol_minus'], ['x', 'LED_symbol_multiplied'],\n                                ['÷', 'LED_symbol_divided'], ['0', 'LED_symbol_0'], ['1', 'LED_symbol_1'], ['2', 'LED_symbol_2'],\n                                ['3', 'LED_symbol_3'], ['4', 'LED_symbol_4'], ['5', 'LED_symbol_5'], ['6', 'LED_symbol_6'],\n                                ['7', 'LED_symbol_7'], ['8', 'LED_symbol_8'], ['9', 'LED_symbol_9'], ['A', 'LED_symbol_A'],\n                                ['B', 'LED_symbol_B'], ['C', 'LED_symbol_C'], ['D', 'LED_symbol_D'], ['E', 'LED_symbol_E'],\n                                ['F', 'LED_symbol_F'], ['G', 'LED_symbol_G'], ['H', 'LED_symbol_H'], ['I', 'LED_symbol_I'],\n                                ['J', 'LED_symbol_J'], ['K', 'LED_symbol_K'], ['L', 'LED_symbol_L'], ['M', 'LED_symbol_M'],\n                                ['N', 'LED_symbol_N'], ['O', 'LED_symbol_O'], ['P', 'LED_symbol_P'], ['Q', 'LED_symbol_Q'],\n                                ['R', 'LED_symbol_R'], ['S', 'LED_symbol_S'], ['T', 'LED_symbol_T'], ['U', 'LED_symbol_U'],\n                                ['V', 'LED_symbol_V'], ['W', 'LED_symbol_W'], ['X', 'LED_symbol_X'], ['Y', 'LED_symbol_Y'],\n                                ['Z', 'LED_symbol_Z'], ['❤︎', 'LED_symbol_big_heart'], ['♥︎', 'LED_symbol_little_heart'], ['↑', 'LED_symbol_forward'],\n                                ['↓', 'LED_symbol_backward'], ['←', 'LED_symbol_turnleft'], ['→', 'LED_symbol_turnright'], ['GO', 'LED_symbol_GO'],\n                                ['⊘', 'LED_symbol_stop'],\n                            ],\n                            value: 'LED_symbol_question_mark',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_display_symbol',\n                    },\n                    paramsKeyMap: {\n                        SYMBOLS: 0,\n                        PORT: 1,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_display_symbol()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_off_LED: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_off_LED',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_off_LED()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_display_digital_tube: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: [''],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_display_digital_tube',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        NUMBER: 1,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        var number = Number(script.values[1]);\n                        if (number < 0 || number > 9999) {\n                            notify(notificationType.ALERT, '0 ~ 9999')\n                            _this.invalidParamValue = true;\n                            throw new Error();\n                        }\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_display_digital_tube()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_display_digital_tube_score: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: [''],\n                            },\n                            {\n                                type: 'number',\n                                params: [''],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_display_digital_tube_score',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        NUMBER1: 1,\n                        NUMBER2: 2,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        var number1 = Number(script.values[1]);\n                        var number2 = Number(script.values[2]);\n                        if (number1 < 0 || number1 > 9999 || number2 < 0 || number2 > 9999) {\n                            notify(notificationType.ALERT, '0 ~ 9999')\n                            _this.invalidParamValue = true;\n                            throw new Error();\n                        }\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_display_digital_tube_score()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_off_digital_tube: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_off_digital_tube',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_off_digital_tube()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_set_RGB: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                            {\n                                type: 'number',\n                                params: ['255'],\n                            },\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_set_RGB',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        RED: 1,\n                        GREEN: 2,\n                        BLUE: 3,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        var red = Number(script.values[1]);\n                        var green = Number(script.values[2]);\n                        var blue = Number(script.values[3]);\n                        if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {\n                            notify(notificationType.ALERT, '0 ~ 255')\n                            _this.invalidParamValue = true;\n                            throw new Error();\n                        }\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_set_RGB()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_fly_RGB: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['⚪', 'color_white'], ['🟡', 'color_yellow'],\n                                ['🟣', 'color_purple'], ['🟦', 'color_cyan'],\n                                ['🔴', 'color_red'], ['🟢', 'color_green'],\n                                ['🔵', 'color_blue'], ['⚫', 'color_black'],\n                            ],\n                            value: 'color_white',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_fly_RGB',\n                    },\n                    paramsKeyMap: {\n                        COLOR: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_fly_RGB()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_set_DO: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.light_speaker.electro_magnet.absorption, 'true'],\n                                [Lang.Blocks.light_speaker.electro_magnet.break_off, 'false']\n                            ],\n                            value: 'true',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ls_set_DO',\n                    },\n                    paramsKeyMap: {\n                        PORT: 0,\n                        ELECTROMAGNET: 1,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_set_DO()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ls_execute_script: {\n                    color: blockColors.color.light_speaker,\n                    outerLine: blockColors.outerLine.light_speaker,\n                    fontColor: '#fff',\n                    skeleton: 'basic_without_next',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Block',\n                            accept: 'string',\n                            defaultType: 'number',\n                        },\n                        {\n                            type: 'Indicator',\n                            img: 'block_icon/moving_icon.svg',\n                            size: 11,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_ls_execute_script',\n                    },\n                    paramsKeyMap: {\n                        VALUE: 0,\n                    },\n                    class: 'whalesbot_eagle_1001_lite_ls',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        const project = _this.exportProject();\n                        const listVariables = project.variables;\n                        const rawScript = project.objects[0].script;\n                        const allScript = JSON.parse(rawScript);\n                        const droneScript = allScript.filter((arr) => arr.length > 2);\n\n                        let sourceCode = `#include \"whalesbot.h\"\\n${listVariables.map(setUpCVariables).join('')}\\nvoid user_main() {\\n`;\n                        sourceCode += `${droneScript[0].map(generateCCode).join('')}}\\n\\nuser_main();`;\n\n                        if (_this.unsupportBlockExist) {\n                            Entry.toast.alert(\n                                Lang.Blocks.whalesbot_eagle_1001_lite_toast_unsupport_block_title,\n                                Lang.Blocks.whalesbot_eagle_1001_lite_toast_unsupport_block_msg\n                            )\n                            _this.unsupportBlockExist = false;\n                            Entry.engine.toggleStop();\n                            return;\n                        }\n\n                        if (_this.invalidParamValue) {\n                            _this.invalidParamValue = false;\n                            return;\n                        }\n\n                        if (openedSimulatorPopup()) {\n                            Entry.toast.success(\n                                Lang.Blocks.whalesbot_eagle_1001_lite_toast_status_title,\n                                Lang.Blocks.whalesbot_eagle_1001_lite_toast_download_success\n                            );\n                            return;\n                        }\n\n                        console.log(sourceCode);\n\n                        _this.sendCmd(sourceCode);\n\n                        Entry.toast.success(\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_status_title,\n                            Lang.Blocks.whalesbot_eagle_1001_lite_toast_prepare_download\n                        );\n                        setTimeout(() => {\n                            Entry.toast.success(\n                                Lang.Blocks.whalesbot_eagle_1001_lite_toast_status_title,\n                                Lang.Blocks.whalesbot_eagle_1001_lite_toast_downloading_code\n                            );\n                            setTimeout(() => {\n                                Entry.toast.success(\n                                    Lang.Blocks.whalesbot_eagle_1001_lite_toast_status_title,\n                                    Lang.Blocks.whalesbot_eagle_1001_lite_toast_download_success\n                                );\n                            }, 3000);\n                        }, 4000);\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ls_execute_script()'] },\n                },\n\n                // sensors\n                whalesbot_eagle_1001_lite_ss_fly_state_POS_Z: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_ss_fly_state_POS_Z',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        _this.sleep();\n                        return _this.sensor.state_position_z || '0';\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_fly_state_POS_Z()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_fly_state_LASER: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_ss_fly_state_LASER',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        _this.sleep();\n                        return _this.sensor.LaserTof || '0';\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_fly_state_LASER()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_battery_voltage: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_ss_battery_voltage',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        _this.sleep();\n                        return _this.sensor.Battery || '0';\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_battery_voltage()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_fly_state_STATE_TEMP: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_ss_fly_state_STATE_TEMP',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        _this.sleep();\n                        return _this.sensor.SPL06_temp || '0';\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_fly_state_STATE_TEMP()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_attitude_angle: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.sensor.attitude_angle.pitch, 'STATE_PITCH'],\n                                [Lang.Blocks.sensor.attitude_angle.roll, 'STATE_ROLL'],\n                                [Lang.Blocks.sensor.attitude_angle.yaw, 'STATE_YAW'],\n                            ],\n                            value: 'STATE_PITCH',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_attitude_angle',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        var state = script.values[0];\n                        if (state === 'STATE_PITCH') {\n                            _this.sleep();\n                            return _this.sensor.Pitch || '0';\n                        } else if (state === 'STATE_ROLL') {\n                            _this.sleep();\n                            return _this.sensor.Roll || '0';\n                        } else if (state === 'STATE_YAW') {\n                            _this.sleep();\n                            return _this.sensor.Yaw || '0';\n                        }\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_attitude_angle()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_flight_angular_velocity: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['X', 'GYPO_X'], ['Y', 'GYPO_Y'], ['Z', 'GYPO_Z'],\n                            ],\n                            value: 'GYPO_X',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_flight_angular_velocity',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        var state = script.values[0];\n                        if (state === 'GYPO_X') {\n                            _this.sleep();\n                            return _this.sensor.Gypo_x || '0';\n                        } else if (state === 'GYPO_Y') {\n                            _this.sleep();\n                            return _this.sensor.Gypo_y || '0';\n                        } else if (state === 'GYPO_Z') {\n                            _this.sleep();\n                            return _this.sensor.Gypo_z || '0';\n                        }\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_flight_angular_velocity()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_flight_acceleration: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['X', 'ACC_X'], ['Y', 'ACC_Y'], ['Z', 'ACC_Z'],\n                            ],\n                            value: 'ACC_X',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_flight_acceleration',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                        var state = script.values[0];\n                        if (state === 'ACC_X') {\n                            _this.sleep();\n                            return _this.sensor.ACC_x || '0';\n                        } else if (state === 'ACC_Y') {\n                            _this.sleep();\n                            return _this.sensor.ACC_y || '0';\n                        } else if (state === 'ACC_Z') {\n                            _this.sleep();\n                            return _this.sensor.ACC_z || '0';\n                        }\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_flight_acceleration()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_optical_flow: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['X', 'OPX'], ['Y', 'OPY']\n                            ],\n                            value: 'OPX',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_optical_flow',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_optical_flow()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_infrared_distance: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_infrared_distance',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_infrared_distance()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_string: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_string',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_string()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_bool: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_bool',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_obstacle_infrared_detected_bool()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_human_infrared_value_string: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_human_infrared_value_string',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_human_infrared_value_string()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_human_infrared_value_bool: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_boolean_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_human_infrared_value_bool',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_human_infrared_value_bool()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_AI: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_AI',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_AI()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_ultrasonic_distance: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_ultrasonic_distance',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_ultrasonic_distance()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_ambient_light: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_ambient_light',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_ambient_light()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_temperature: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_temperature',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_temperature()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_humidity: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_humidity',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_humidity()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_flame: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_flame',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_flame()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_gesture: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_gesture',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_gesture()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_tof: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['P1', 'P1'], ['P2', 'P2']\n                            ],\n                            value: 'P1',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_tof',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_tof()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_fly_setpoint_LASER_ENABLE: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.sensor.laser_height_determination.on, 'true'],\n                                [Lang.Blocks.sensor.laser_height_determination.off, 'false']\n                            ],\n                            value: 'true',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_fly_setpoint_LASER_ENABLE',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_fly_setpoint_LASER_ENABLE()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_get_bt_remote_control: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.sensor.remote_control_button.key, 'BTKEY'],\n                                [Lang.Blocks.sensor.remote_control_button.left_rocker_x, 'BTSTICK2'],\n                                [Lang.Blocks.sensor.remote_control_button.left_rocker_y, 'BTSTICK1'],\n                                [Lang.Blocks.sensor.remote_control_button.right_rocker_x, 'BTSTICK4'],\n                                [Lang.Blocks.sensor.remote_control_button.right_rocker_y, 'BTSTICK3'],\n                            ],\n                            value: 'BTKEY',\n                            fontSize: 10,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    events: {},\n                    def: {\n                        params: [\n                            null,\n                        ],\n                        type: 'whalesbot_eagle_1001_lite_ss_get_bt_remote_control',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_get_bt_remote_control()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_seconds: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic_string_field',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_ss_seconds',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_seconds()'] },\n                },\n\n                whalesbot_eagle_1001_lite_ss_resettime: {\n                    color: blockColors.color.sensor,\n                    outerLine: blockColors.outerLine.sensor,\n                    fontColor: '#fff',\n                    skeleton: 'basic',\n                    statements: [],\n                    params: [],\n                    events: {},\n                    def: {\n                        type: 'whalesbot_eagle_1001_lite_ss_resettime',\n                    },\n                    paramsKeyMap: {},\n                    class: 'whalesbot_eagle_1001_lite_ss',\n                    isNotFor: ['WhalesbotDroneLite'],\n                    func(sprite, script) {\n                    },\n                    syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_lite_ss_resettime()'] },\n                },\n            };\n        }\n    })();\n})();\n\nmodule.exports = Entry.WhalesbotDroneLite;"
  },
  {
    "path": "src/playground/blocks/hardwareLite/block_wizwing_controller_lite.js",
    "content": "'use strict';\n\nimport _range from 'lodash/range';\n\n(function () {\n    Entry.wizwingcontrollerlite = new (class wizwingcontrollerlite {\n        constructor() {\n            this.id = '69.1';\n            this.name = 'wizwingcontrollerlite';\n            this.url = 'http://www.wizwing.co.kr/';\n            this.imageName = 'wizwingcontrollerlite.png';\n            this.title = {\n                ko: '위즈윙 코딩드론 R4 조종기',\n                en: 'wizwing coding drone R4 controller',\n            };\n            this.duration = 32;\n            this.blockMenuBlocks = [\n                'Wizwing_Drone_Controller_connect',\n                'Wizwing_Drone_Controller_takeoff',\n                'Wizwing_Drone_Controller_land',\n                'Wizwing_Drone_Controller_throttle',\n                'Wizwing_Drone_Controller_elevator',\n                'Wizwing_Drone_Controller_aileron',\n                'Wizwing_Drone_Controller_rudder',\n                'Wizwing_Drone_Controller_funled',\n                'Wizwing_Drone_Controller_flip',\n                'Wizwing_Drone_Controller_speed',\n                'Wizwing_Drone_Controller_emergency',\n                'Wizwing_Drone_Controller_opt',\n                'Wizwing_Drone_Controller_gyroreset',\n                'Wizwing_Drone_Controller_headless',\n                'Wizwing_Drone_Controller_diagonal',\n                'Wizwing_Drone_Controller_circularflight',\n                'Wizwing_Drone_Controller_photoflight',\n            ];\n            this.portData = {\n                baudRate: 9600,\n                duration: 32,\n                dataBits: 8,\n                parity: 'none',\n                stopBits: 1,\n                bufferSize: 512,\n                constantServing: false,\n            };\n            this.readablePorts = [];\n            this.remainValue = null;\n            this.setZero();\n        }\n\n        setZero() {\n            this.port = new Array(14).fill(0);\n            this.digitalValue = new Array(14).fill(0);\n            this.remoteDigitalValue = new Array(14).fill(0);\n            this.analogValue = new Array(6).fill(0);\n            this.readablePorts = _range(0, 19);\n\n            if (Entry.hwLite && Entry.hwLite.serial) {\n                Entry.hwLite.serial.update();\n            }\n        }\n\n        handleLocalData(data) {\n            for (let i = 0; i < 32; i++) {\n                let chunk;\n                if (!this.remainValue) {\n                    chunk = data[i];\n                } else {\n                    chunk = this.remainValue;\n                    i--;\n                }\n\n                if (chunk === SOME_EXPECTED_RESPONSE) {\n                    console.log('Takeoff command acknowledged by drone.');\n                } else {\n                    console.log('Unexpected response from drone:', chunk);\n                }\n\n                if (chunk >> 7) {\n                    if ((chunk >> 6) & 1) {\n                        const nextChunk = data[i + 1];\n                        if (!nextChunk && nextChunk !== 0) {\n                            this.remainValue = chunk;\n                        } else {\n                            this.remainValue = null;\n\n                            const port = (chunk >> 3) & 7;\n                            this.analogValue[port] = ((chunk & 7) << 7) + (nextChunk & 127);\n                        }\n                        i++;\n                    } else {\n                        const port = (chunk >> 2) & 15;\n                        this.digitalValue[port] = chunk & 1;\n                    }\n                }\n            }\n        }\n\n        requestLocalData() {\n            const queryString = [];\n            const readablePorts = this.readablePorts;\n\n            const commandStr = Entry.hw.sendQueue['COMMAND'];\n            if (commandStr) {\n                for (let i = 0; i < commandStr.length; i++) {\n                    queryString.push(commandStr.charCodeAt(i));\n                }\n                delete Entry.hw.sendQueue['COMMAND'];\n            }\n\n            if (readablePorts) {\n                for (const i in readablePorts) {\n                    const query = (5 << 5) + (readablePorts[i] << 1);\n                    queryString.push(query);\n                }\n            }\n            const readablePortsValues = (readablePorts && Object.values(readablePorts)) || [];\n            for (let port = 0; port < 14; port++) {\n                if (readablePortsValues.indexOf(port) > -1) {\n                    continue;\n                }\n                const value = this.remoteDigitalValue[port];\n                if (value === 255 || value === 0) {\n                    const query = (7 << 5) + (port << 1) + (value == 255 ? 1 : 0);\n                    queryString.push(query);\n                } else if (value > 0 && value < 255) {\n                    let query = (6 << 5) + (port << 1) + (value >> 7);\n                    queryString.push(query);\n                    query = value & 127;\n                    queryString.push(query);\n                }\n            }\n            return queryString;\n        }\n\n        addReadablePort(port) {\n            const idx = Entry.ArduinoLite.readablePorts.indexOf(port);\n            if (idx === -1) {\n                Entry.ArduinoLite.readablePorts.push(port);\n            }\n        }\n\n        removeReadablePort(port) {\n            const idx = Entry.ArduinoLite.readablePorts.indexOf(port);\n            if (idx >= 0) {\n                Entry.ArduinoLite.readablePorts.splice(idx, 1);\n            }\n        }\n\n        setLanguage() {\n            return {\n                ko: {\n                    Blocks: {\n                        Wizwing_Drone_Controller_flip_f: '앞으로  ',\n                        Wizwing_Drone_Controller_flip_b: '뒤로  ',\n                        Wizwing_Drone_Controller_flip_l: '왼쪽으로  ',\n                        Wizwing_Drone_Controller_flip_r: '오른쪽으로  ',\n                    },\n                    template: {\n                        Wizwing_Drone_Controller_connect: '페어링(바인딩)  ',\n                        Wizwing_Drone_Controller_takeoff: '자동이륙  ',\n                        Wizwing_Drone_Controller_land: '자동착륙  ',\n                        Wizwing_Drone_Controller_throttle: '스로틀 %1만큼 %2ms  ',\n                        Wizwing_Drone_Controller_elevator: '엘리베이터 %1만큼 %2ms  ',\n                        Wizwing_Drone_Controller_aileron: '에일러론 %1만큼 %2ms  ',\n                        Wizwing_Drone_Controller_rudder: '러더 %1만큼 %2 ms  ',\n                        Wizwing_Drone_Controller_funled: '7색 LED 색 변경  ',\n                        Wizwing_Drone_Controller_flip: '360도회전 %1  ',\n                        Wizwing_Drone_Controller_speed: '속도조절 %1 단 ',\n                        Wizwing_Drone_Controller_emergency: '모터긴급정지  ',\n                        Wizwing_Drone_Controller_opt: '비전센서 on/off  ',\n                        Wizwing_Drone_Controller_gyroreset: '자이로 초기화  ',\n                        Wizwing_Drone_Controller_headless: '헤드리스 모드 on/off  ',\n                        Wizwing_Drone_Controller_diagonal: '엘리베이터%1 에일러론%2 %3ms   ',\n                        Wizwing_Drone_Controller_circularflight: '엘리베이터%1 러더%2 %3ms   ',\n                        Wizwing_Drone_Controller_photoflight: '에일러론%1 러더%2 %3ms   ',\n                    },\n                    Device: {\n                        Wizwing_Drone_Controller: '위즈윙 코딩드론 R4 조종기',\n                    },\n                    Menus: {\n                        Wizwing_Drone_Controller: '위즈윙 코딩드론 R4 조종기',\n                    },\n                    Helper: {\n                        Wizwing_Drone_Controller_connect: '페어링(바인딩)  ',\n                        Wizwing_Drone_Controller_takeoff: '자동 이륙  ',\n                        Wizwing_Drone_Controller_land: '자동 착륙  ',\n                        Wizwing_Drone_Controller_throttle: '드론이 상승/ 하강합니다  ',\n                        Wizwing_Drone_Controller_elevator: '드론이 앞/뒤로 이동합니다  ',\n                        Wizwing_Drone_Controller_aileron: '드론이 좌/우로 이동합니다  ',\n                        Wizwing_Drone_Controller_rudder: '드론이 좌/우로 회전합니다.  ',\n                        Wizwing_Drone_Controller_funled: '7색 LED 색 변경  ',\n                        Wizwing_Drone_Controller_flip: '360도회전 %1   ',\n                        Wizwing_Drone_Controller_speed: '속도 %1 단 ',\n                        Wizwing_Drone_Controller_emergency: '모터긴급정지  ',\n                        Wizwing_Drone_Controller_opt: '비전센서 on/off  ',\n                        Wizwing_Drone_Controller_gyroreset: '자이로 초기화  ',\n                        Wizwing_Drone_Controller_headless: '헤드리스 모드  ',\n                        Wizwing_Drone_Controller_diagonal: '대각선으로 이동  ',\n                        Wizwing_Drone_Controller_circularflight: '선회비행  ',\n                        Wizwing_Drone_Controller_photoflight: '촬영비행  ',\n                    },\n                },\n                en: {\n                    template: {\n                        Wizwing_Drone_Controller_connect: 'Fairing(Binding)',\n                        Wizwing_Drone_Controller_takeoff: 'Auto Takeoff ',\n                        Wizwing_Drone_Controller_land: 'Auto Landing ',\n                        Wizwing_Drone_Controller_throttle: 'thottle %1 time %2ms  ',\n                        Wizwing_Drone_Controller_elevator: 'elevator %1 time %2ms  ',\n                        Wizwing_Drone_Controller_aileron: 'aileron %1 time %2ms  ',\n                        Wizwing_Drone_Controller_rudder: 'rudder %1 time %2ms  ',\n                        Wizwing_Drone_Controller_funled: '7-color LED color change  ',\n                        Wizwing_Drone_Controller_flip: '%1  360 flip  ',\n                        Wizwing_Drone_Controller_speed: 'Speed adjustment %1',\n                        Wizwing_Drone_Controller_emergency: 'Emergency Stop ',\n                        Wizwing_Drone_Controller_opt: 'vision sensor on/off  ',\n                        Wizwing_Drone_Controller_gyroreset: 'Gyro Reset ',\n                        Wizwing_Drone_Controller_headless: 'Headless Mode ',\n                        Wizwing_Drone_Controller_diagonal: 'diagonal Mode ',\n                        Wizwing_Drone_Controller_circularflight: 'circularflight Mode ',\n                        Wizwing_Drone_Controller_photoflight: 'photoflight Mode ',\n                    },\n                    Device: {\n                        Wizwing_Drone_Controller: 'wizwingdroncontroller',\n                    },\n                    Menus: {\n                        Wizwing_Drone_Controller: 'WizwingDronController',\n                    },\n                },\n            };\n        }\n\n        initializeBlocks() {\n            Entry.hwLite\n                .connect()\n                .then(() => {\n                    if (!Entry.hwLite.serial) {\n                        console.error('Serial object is not defined. Please check the connection.');\n                        return;\n                    }\n\n                    Entry.getMainGenerator().getBlocks = this.getBlocks.bind(this);\n\n                    Entry.addEventListener('blockCompleted', () => {\n                        Entry.getMainGenerator().nextBlock();\n                    });\n                })\n                .catch((error) => {\n                    console.error('Failed to connect to hardware:', error);\n                });\n        }\n\n        getBlocks() {\n            return {\n                Wizwing_Drone_Controller_connect: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    params: [],\n                    def: { params: [], type: 'Wizwing_Drone_Controller_connect' },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const command = 'mapping_start';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Wizwing_Drone_Controller_takeoff: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    params: [],\n                    def: { params: [], type: 'Wizwing_Drone_Controller_takeoff' },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const command = 'takeoff';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        console.log(`Sending command: ${command}`);\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 4000);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Wizwing_Drone_Controller_land: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [],\n                    def: { params: [], type: 'Wizwing_Drone_Controller_land' },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const command = 'land';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        console.log(`Sending command: ${command}`);\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 3000);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Wizwing_Drone_Controller_throttle: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Wizwing_Drone_Controller_throttle',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script) * 5;\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < -500) {\n                            stick = -500;\n                        }\n\n                        if (stick >= 0) {\n                            const command1 = `up ${stick} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer = Buffer.from(command1, 'utf8');\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else {\n                            stick = stick * -1;\n                            const command2 = `down ${stick} ${time}\\r`;\n                            console.log('Constructed command:', command2);\n                            const commandBuffer = Buffer.from(command2, 'utf8');\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command2);\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        }\n\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_elevator: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Wizwing_Drone_Controller_elevator',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script) * 5;\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < -500) {\n                            stick = -500;\n                        }\n\n                        if (stick >= 0) {\n                            const command1 = `forward ${stick} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer = Buffer.from(command1, 'utf8');\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else {\n                            stick = stick * -1;\n                            const command2 = `back ${stick} ${time}\\r`;\n                            console.log('Constructed command:', command2);\n                            const commandBuffer = Buffer.from(command2, 'utf8');\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command2);\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        }\n\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_aileron: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Wizwing_Drone_Controller_aileron',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script) * 5;\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < -500) {\n                            stick = -500;\n                        }\n\n                        if (stick >= 0) {\n                            const command1 = `right ${stick} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer = Buffer.from(command1, 'utf8');\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else {\n                            stick = stick * -1;\n                            const command2 = `left ${stick} ${time}\\r`;\n                            console.log('Constructed command:', command2);\n                            const commandBuffer = Buffer.from(command2, 'utf8');\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command2);\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        }\n\n                        return script.callReturn();\n                    },\n                },\n                Wizwing_Drone_Controller_rudder: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null],\n                        type: 'Wizwing_Drone_Controller_rudder',\n                    },\n                    paramsKeyMap: {\n                        STICK: 0,\n                        TIME: 1,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        let stick = script.getNumberValue('STICK', script) * 5;\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick > 500) {\n                            stick = 500;\n                        } else if (stick < -500) {\n                            stick = -500;\n                        }\n\n                        if (stick >= 0) {\n                            const command1 = `cw ${stick} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer = Buffer.from(command1, 'utf8');\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else {\n                            stick = stick * -1;\n                            const command2 = `ccw ${stick} ${time}\\r`;\n                            console.log('Constructed command:', command2);\n                            const commandBuffer = Buffer.from(command2, 'utf8');\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command2);\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        }\n\n                        return script.callReturn();\n                    },\n                },\n                Wizwing_Drone_Controller_funled: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [],\n                    def: { params: [], type: 'Wizwing_Drone_Controller_funled' },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const command = 'funled';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_flip: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                [Lang.Blocks.Wizwing_Drone_Controller_flip_f, 'f'],\n                                [Lang.Blocks.Wizwing_Drone_Controller_flip_b, 'b'],\n                                [Lang.Blocks.Wizwing_Drone_Controller_flip_l, 'l'],\n                                [Lang.Blocks.Wizwing_Drone_Controller_flip_r, 'r'],\n                            ],\n                            value: 'f',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                        type: 'Wizwing_Drone_Controller_flip',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const direction = script.getField('DIRECTION');\n                        const command = `flip ${direction}\\r`;\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 4100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_speed: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [\n                        {\n                            type: 'Dropdown',\n                            options: [\n                                ['1', '1'],\n                                ['2', '2'],\n                                ['3', '3'],\n                            ],\n                            value: '1',\n                            fontSize: 11,\n                            bgColor: EntryStatic.colorSet.block.darken.HARDWARE,\n                            arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,\n                        },\n                    ],\n                    def: {\n                        params: [null],\n                        type: 'Wizwing_Drone_Controller_speed',\n                    },\n                    paramsKeyMap: {\n                        DIRECTION: 0,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const direction = script.getField('DIRECTION');\n                        const command = `speed ${direction}\\r`;\n                        const commandBuffer = Buffer.from(command, 'utf8');\n\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Wizwing_Drone_Controller_emergency: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [],\n                    def: { params: [], type: 'Wizwing_Drone_Controller_emergency' },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const command = 'emergency';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n                Wizwing_Drone_Controller_opt: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    params: [],\n                    def: { params: [], type: 'Wizwing_Drone_Controller_opt' },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const command = 'opt';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_gyroreset: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    params: [],\n                    def: { params: [], type: 'Wizwing_Drone_Controller_gyroreset' },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const command = 'gyroreset';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_headless: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    params: [],\n                    def: { params: [null], type: 'Wizwing_Drone_Controller_headless' },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        const command = 'headless';\n                        const commandBuffer = Buffer.from(\n                            encodeURIComponent(command) + '\\r',\n                            'utf8'\n                        );\n                        if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                            Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer, false);\n                            console.log('Command sent using sendAsyncWithThrottle:', command);\n                            return new Promise((resolve) => {\n                                setTimeout(() => {\n                                    resolve(script.callReturn());\n                                }, 1100);\n                            });\n                        } else {\n                            console.log('Serial writer not found.');\n                        }\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_diagonal: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null, null],\n                        type: 'Wizwing_Drone_Controller_diagonal',\n                    },\n                    paramsKeyMap: {\n                        STICK1: 0,\n                        STICK2: 1,\n                        TIME: 2,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        let stick1 = script.getNumberValue('STICK1', script) * 5;\n                        let stick2 = script.getNumberValue('STICK2', script) * 5;\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick1 > 500) {\n                            stick1 = 500;\n                        } else if (stick1 < -500) {\n                            stick1 = -500;\n                        }\n\n                        if (stick2 > 500) {\n                            stick2 = 500;\n                        } else if (stick2 < -500) {\n                            stick2 = -500;\n                        }\n\n                        if (stick1 >= 0 && stick2 >= 0) {\n                            const command1 = `forward ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `right ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else if (stick1 >= 0 && stick2 < 0) {\n                            stick2 = stick2 * -1;\n\n                            const command1 = `forward ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `left ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else if (stick1 < 0 && stick2 >= 0) {\n                            stick1 = stick1 * -1;\n                            const command1 = `back ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `right ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else {\n                            stick1 = stick1 * -1;\n                            stick2 = stick2 * -1;\n                            const command1 = `back ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `left ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        }\n\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_circularflight: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null, null],\n                        type: 'Wizwing_Drone_Controller_circularflight',\n                    },\n                    paramsKeyMap: {\n                        STICK1: 0,\n                        STICK2: 1,\n                        TIME: 2,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        let stick1 = script.getNumberValue('STICK1', script) * 5;\n                        let stick2 = script.getNumberValue('STICK2', script) * 5;\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick1 > 500) {\n                            stick1 = 500;\n                        } else if (stick1 < -500) {\n                            stick1 = -500;\n                        }\n\n                        if (stick2 > 500) {\n                            stick2 = 500;\n                        } else if (stick2 < -500) {\n                            stick2 = -500;\n                        }\n\n                        if (stick1 >= 0 && stick2 >= 0) {\n                            const command1 = `forward ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `cw ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else if (stick1 >= 0 && stick2 < 0) {\n                            stick2 = stick2 * -1;\n\n                            const command1 = `forward ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `ccw ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else if (stick1 < 0 && stick2 >= 0) {\n                            stick1 = stick1 * -1;\n                            const command1 = `back ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `cw ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else {\n                            stick1 = stick1 * -1;\n                            stick2 = stick2 * -1;\n                            const command1 = `back ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `ccw ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        }\n\n                        return script.callReturn();\n                    },\n                },\n\n                Wizwing_Drone_Controller_photoflight: {\n                    color: EntryStatic.colorSet.block.default.HARDWARE,\n                    outerLine: EntryStatic.colorSet.block.darken.HARDWARE,\n                    skeleton: 'basic',\n                    fontColor: '#fff',\n                    statements: [],\n                    params: [\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                        { type: 'Block', accept: 'string' },\n                    ],\n                    def: {\n                        params: [null, null, null],\n                        type: 'Wizwing_Drone_Controller_photoflight',\n                    },\n                    paramsKeyMap: {\n                        STICK1: 0,\n                        STICK2: 1,\n                        TIME: 2,\n                    },\n                    class: 'wizwing',\n                    isNotFor: ['wizwingcontrollerlite'],\n                    func(sprite, script) {\n                        let stick1 = script.getNumberValue('STICK1', script) * 5;\n                        let stick2 = script.getNumberValue('STICK2', script) * 5;\n                        let time = script.getNumberValue('TIME', script);\n\n                        if (stick1 > 500) {\n                            stick1 = 500;\n                        } else if (stick1 < -500) {\n                            stick1 = -500;\n                        }\n\n                        if (stick2 > 500) {\n                            stick2 = 500;\n                        } else if (stick2 < -500) {\n                            stick2 = -500;\n                        }\n\n                        if (stick1 >= 0 && stick2 >= 0) {\n                            const command1 = `right ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `cw ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else if (stick1 >= 0 && stick2 < 0) {\n                            stick2 = stick2 * -1;\n\n                            const command1 = `right ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `ccw ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else if (stick1 < 0 && stick2 >= 0) {\n                            stick1 = stick1 * -1;\n                            const command1 = `left ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `cw ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        } else {\n                            stick1 = stick1 * -1;\n                            stick2 = stick2 * -1;\n                            const command1 = `left ${stick1} ${time}\\r`;\n                            console.log('Constructed command:', command1);\n                            const commandBuffer1 = Buffer.from(command1, 'utf8');\n\n                            const command11 = `ccw ${stick2} ${time}\\r`;\n                            console.log('Constructed command:', command11);\n                            const commandBuffer11 = Buffer.from(command11, 'utf8');\n\n                            if (Entry.hwLite && Entry.hwLite.serial && Entry.hwLite.serial.writer) {\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer1, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command1);\n\n                                Entry.hwLite.serial.sendAsyncWithThrottle(commandBuffer11, false);\n                                console.log('Command sent using sendAsyncWithThrottle:', command11);\n\n                                return new Promise((resolve) => {\n                                    setTimeout(() => {\n                                        resolve(script.callReturn());\n                                    }, time + 1100);\n                                });\n                            } else {\n                                console.log('Serial writer not found.');\n                            }\n                        }\n\n                        return script.callReturn();\n                    },\n                },\n            };\n        }\n    })();\n})();\n\nmodule.exports = Entry.wizwingcontrollerlite;\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/index.js",
    "content": "'use strict';\n\nEntry.HARDWARE_LITE_LIST = {};\n\nconst moduleListReq = require.context('.', false, /^(?!.*index.js)((.*_lite\\.(js))*$)/im);\nconst metaDataListReq = require.context('.', false, /^(?!.*index.js)((.*_lite\\.(json))*$)/im);\n\nfunction addHardwareLiteList(module) {\n    if (typeof module.id === 'string') {\n        Entry.HARDWARE_LITE_LIST[module.id] = module;\n    } else if (module.id instanceof Array) {\n        module.id.forEach((id) => {\n            Entry.HARDWARE_LITE_LIST[id] = module;\n        });\n    }\n}\n\nfunction initHardwareLiteList() {\n    moduleListReq.keys().forEach((fileName) => {\n        const module = moduleListReq(fileName);\n\n        if (module instanceof Array) {\n            module.forEach(addHardwareLiteList);\n        } else {\n            addHardwareLiteList(module);\n        }\n    });\n\n    metaDataListReq.keys().forEach((fileName) => {\n        const metaData = metaDataListReq(fileName);\n        // const moduleId = `${metaData.moduleId.substring(0, 2).replace(/(^0+)/, \"\")}.${metaData.moduleId.substring(2, 4).replace(/(^0+)/, \"\")}`;\n        const moduleId = metaData.moduleId;\n\n        if (Entry.HARDWARE_LITE_LIST[moduleId]) {\n            Entry.HARDWARE_LITE_LIST[moduleId].title = { ko: metaData.title };\n            Entry.HARDWARE_LITE_LIST[moduleId].description = metaData.description;\n            Entry.HARDWARE_LITE_LIST[moduleId].linkBox = {\n                desc: '고객센터',\n                url: Entry.HARDWARE_LITE_LIST[moduleId].url,\n            };\n        } else {\n            console.error(`Error, HardwareLiteID ${moduleId} not contain module`);\n        }\n    });\n}\n\nfunction getHardwareLiteModuleList() {\n    return Object.values(Entry.HARDWARE_LITE_LIST);\n}\n\ninitHardwareLiteList();\n\nmodule.exports = {\n    getHardwareLiteModuleList,\n};\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_alux_connect_lite.json",
    "content": "{\n    \"name\": \"ProboConnectLite\",\n    \"version\": \"1.0.1\",\n    \"type\": \"hardware\",\n    \"title\": \"프로보 커넥트\",\n    \"description\": \"에이럭스\",\n    \"imageName\": \"alux_proboconnect_lite.png\",\n    \"moduleId\": \"270101\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_alux_nemo_lite.json",
    "content": "{\n    \"name\": \"ProboNemoLite\",\n    \"version\": \"1.0.1\",\n    \"type\": \"hardware\",\n    \"title\": \"네모\",\n    \"description\": \"에이럭스\",\n    \"imageName\": \"alux_nemo_lite.png\",\n    \"moduleId\": \"630101\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_alux_teachnic_normal_lite.json",
    "content": "{\n    \"name\": \"ProboTechnicNormalLite\",\n    \"version\": \"1.0.1\",\n    \"type\": \"hardware\",\n    \"title\": \"프로보 테크닉(일반)\",\n    \"description\": \"에이럭스\",\n    \"imageName\": \"alux_technic_normal_lite.png\",\n    \"moduleId\": \"630301\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_alux_teachnic_power_lite.json",
    "content": "{\n    \"name\": \"ProboTechnicPowerLite\",\n    \"version\": \"1.0.1\",\n    \"type\": \"hardware\",\n    \"title\": \"프로보 테크닉(파워)\",\n    \"description\": \"에이럭스\",\n    \"imageName\": \"alux_technic_power_lite.png\",\n    \"moduleId\": \"630201\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_arduino_lite.json",
    "content": "{\n    \"name\": \"ArduinoLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"아두이노 우노\",\n    \"description\": \"Arduino\",\n    \"imageName\": \"arduinolite\",\n    \"moduleId\": \"010101\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_choco_lite.json",
    "content": "{\n    \"name\": \"ChocoLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"쪼코\",\n    \"description\": \"씨앤알테크\",\n    \"imageName\": \"choco\",\n    \"moduleId\": \"450101\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_cocodron_controller_Lite.json",
    "content": "{\n    \"name\": \"cocodroncontrollerLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"코코드론조종기\",\n    \"description\": \"cocodron\",\n    \"imageName\": \"cocodroncontrollerLite\",\n    \"moduleId\": \"680101\"\n}"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_codewiz_lite.json",
    "content": "{\n    \"name\": \"CodeWizLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"코드위즈\",\n    \"description\": \"Codewiz\",\n    \"imageName\": \"codewizlite.png\",\n    \"moduleId\": \"011201\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_hamster_lite.json",
    "content": "{\n    \"name\": \"HamsterLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"햄스터\",\n    \"description\": \"로보메이션\",\n    \"imageName\": \"hamsterLite\",\n    \"moduleId\": \"020401\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_microbit2_lite.json",
    "content": "{\n    \"name\": \"Microbit2lite\",\n    \"version\": \"2\",\n    \"type\": \"hardware\",\n    \"title\": \"마이크로비트\",\n    \"description\": \"Micro:bit Educational Foundation\",\n    \"imageName\": \"microbit2lite.png\",\n    \"moduleId\": \"220301\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_microbit2ble_lite.json",
    "content": "{\n    \"name\": \"Microbit2BleLite\",\n    \"version\": \"2\",\n    \"title\": \"마이크로비트 블루투스(BLE) 연결\",\n    \"description\": \"Micro:bit Educational Foundation\",\n    \"imageName\": \"microbit2blelite.png\",\n    \"moduleId\": \"220302\",\n    \"connectionType\": \"ble\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_neo_cannon_lite.json",
    "content": "{\n    \"name\": \"NeoCannonLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"robot\",\n    \"title\": \"네오캐논\",\n    \"description\": \"NeoCannon\",\n    \"imageName\": \"neocannonlite\",\n    \"moduleId\": \"410201\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_neo_lite.json",
    "content": "{\n    \"name\": \"NeoLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"네오(NEO)\",\n    \"description\": \"네오피아\",\n    \"imageName\": \"neo\",\n    \"moduleId\": \"050801\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_neo_spider_lite.json",
    "content": "{\n    \"name\": \"NeoSpiderLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"robot\",\n    \"title\": \"네오스파이더\",\n    \"description\": \"NeoSpider\",\n    \"imageName\": \"neospiderlite\",\n    \"moduleId\": \"410101\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_neobot_purple_lite.json",
    "content": "{\n    \"name\": \"NeobotPurpleLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"NEW 네오봇\",\n    \"description\": \"네오피아\",\n    \"imageName\": \"neobot_purple_lite\",\n    \"moduleId\": \"050501\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_neobot_soco_lite.json",
    "content": "{\n    \"name\": \"NeobotSocoLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"네오쏘코(SoCo)\",\n    \"description\": \"네오피아\",\n    \"imageName\": \"neobot_soco_lite\",\n    \"moduleId\": \"050601\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_neobot_thinkcar_lite.json",
    "content": "{\n    \"name\": \"NeobotThinkCarLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"네오씽카(ThinkCar)\",\n    \"description\": \"네오피아\",\n    \"imageName\": \"neobot_thinkcar_lite\",\n    \"moduleId\": \"050701\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_robolink_ZumiMini_lite.json",
    "content": "{\n    \"name\": \"ZumiMiniLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"주미 미니\",\n    \"description\": \"로보링크\",\n    \"imageName\": \"robolink_ZumiMini_lite.png\",\n    \"moduleId\": \"4A0501\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_robotis_kkokdu_lite.json",
    "content": "{\n    \"name\": \"RobotisKkokduLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"로보티즈 꼭두\",\n    \"description\": \"로보티즈\",\n    \"imageName\": \"robotis_kkokdu_lite\",\n    \"moduleId\": \"070701\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_robotis_koalabot_lite.json",
    "content": "{\n    \"name\": \"RobotisKoalabotLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"코알라봇\",\n    \"description\": \"로보티즈\",\n    \"imageName\": \"robotis_koalabot_lite\",\n    \"moduleId\": \"070C01\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_robotis_rgee_lite.json",
    "content": "{\n    \"name\": \"RobotisRgeeLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"로보티즈 알쥐\",\n    \"description\": \"로보티즈\",\n    \"imageName\": \"robotis_rgee_lite\",\n    \"moduleId\": \"070501\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_robotis_rla_lite.json",
    "content": "{\n    \"name\": \"RobotisRgeeLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"로보티즈 알라\",\n    \"description\": \"로보티즈\",\n    \"imageName\": \"robotis_rla_lite\",\n    \"moduleId\": \"070901\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_robotis_robotai_lite.json",
    "content": "{\n    \"name\": \"RobotisRobotaiLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"로봇아이(AI)\",\n    \"description\": \"로보티즈\",\n    \"imageName\": \"robotis_robotai_lite\",\n    \"moduleId\": \"070B01\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_sensorboard_lite.json",
    "content": "{\n    \"name\": \"SensorboardLite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"E-센서보드 (유선연결)\",\n    \"description\": \"새로운교육\",\n    \"imageName\": \"sensorboardlite\",\n    \"moduleId\": \"010201\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_whalesbot_drone_lite.json",
    "content": "{\n    \"name\": \"WhalesbotDrone\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"고래봇 드론\",\n    \"description\": \"Whalesbot\",\n    \"imageName\": \"whalesbot_drone\",\n    \"moduleId\": \"620101\"\n}\n"
  },
  {
    "path": "src/playground/blocks/hardwareLite/metadata_wizwing_controller_lite.json",
    "content": "{\n    \"name\": \"wizwingcontrollerlite\",\n    \"version\": \"1.0.0\",\n    \"type\": \"hardware\",\n    \"title\": \"위즈윙 코딩드론 R4 조종기\",\n    \"description\": \"wizwing\",\n    \"imageName\": \"wizwingcontrollerlite\",\n    \"moduleId\": \"69.1\"\n}\n"
  },
  {
    "path": "src/playground/blocks/index.js",
    "content": "'use strict';\n\nconst hardware = require('./hardware/index');\nconst hardwareLite = require('./hardwareLite/index');\nconst _union = require('lodash/union');\nconst _flatten = require('lodash/flatten');\n\nconst basicBlockList = [\n    require('./block_start'),\n    require('./block_flow'),\n    require('./block_moving'),\n    require('./block_looks'),\n    require('./block_brush'),\n    require('./block_text'),\n    require('./block_sound'),\n    require('./block_judgement'),\n    require('./block_calc'),\n    require('./block_variable'),\n    require('./block_func'),\n    require('./block_analysis'),\n];\n\nconst destroyBlockList = [];\n\nfunction getBlockObject(items) {\n    const blockObject = {};\n    items.forEach((item) => {\n        try {\n            if ('getBlocks' in item) {\n                Object.assign(blockObject, item.getBlocks());\n            }\n            if ('destroy' in item) {\n                destroyBlockList.push(item.destroy);\n            }\n        } catch (err) {\n            console.log(err, item);\n        }\n    });\n    return blockObject;\n}\n\nfunction getHardwareBlockObject(items) {\n    const blockObject = {};\n    items.forEach((item) => {\n        // 일반모드, 교과블록 미포함 하드웨어 > 일반블록만 출력\n        // 일반모드, 교과블록 포함 하드웨어 > 일반블록만 출력\n        // 교과모드, 교과블록 미포함 하드웨어 > 일반블록만 출력\n        // 교과모드, 교과블록 포함 하드웨어 > 교과블록만 출력\n        try {\n            if (item.hasPracticalCourse && EntryStatic.isPracticalCourse) {\n                Object.assign(\n                    blockObject,\n                    'getPracticalBlocks' in item ? item.getPracticalBlocks() : {}\n                );\n                EntryStatic.hwMiniSupportList.push(item.name);\n            } else {\n                Object.assign(blockObject, 'getBlocks' in item ? item.getBlocks() : {});\n            }\n        } catch (err) {\n            console.log(err, item);\n        }\n    });\n    return blockObject;\n}\n\n/**\n * 하드웨어 블록을 EntryStatic 에 등록한다.\n * 하드웨어 블록에만 사용하는 이유는,\n * 기존 블록은 legacy 블록이 존재하기 때문에 전부 등록하면 안되기 때문이다.\n * 또한 값블록으로서만 사용하는 블록이 블록메뉴에 따로 나타나게 될 수 있다.\n *\n * @param {Object} hardwareModules\n * @return {void}\n */\nfunction registerHardwareBlockToStatic(hardwareModules) {\n    // TODO : getHardwareBlockObject과의 병합 고려\n    hardwareModules.forEach((hardware) => {\n        try {\n            if (hardware.hasPracticalCourse && EntryStatic.isPracticalCourse) {\n                if (hardware.practicalBlockMenuBlocks) {\n                    for (const category in hardware.practicalBlockMenuBlocks) {\n                        EntryStatic.DynamicPracticalHardwareBlocks[category] = _union(\n                            hardware.practicalBlockMenuBlocks[category],\n                            EntryStatic.DynamicPracticalHardwareBlocks[category]\n                        );\n                    }\n                }\n            } else {\n                EntryStatic.DynamicHardwareBlocks = _union(\n                    hardware.blockMenuBlocks || [],\n                    EntryStatic.DynamicHardwareBlocks || []\n                );\n            }\n        } catch (err) {\n            console.log(err, hardware);\n        }\n    });\n}\n\nmodule.exports = {\n    getBlocks() {\n        const hardwareModules = hardware.getHardwareModuleList();\n        const hardwareLiteModules = hardwareLite.getHardwareLiteModuleList();\n        registerHardwareBlockToStatic(hardwareModules);\n        registerHardwareBlockToStatic(hardwareLiteModules);\n        const basicAndExpansionBlockObjectList = getBlockObject(basicBlockList);\n        const hardwareBlockObjectList = getHardwareBlockObject(hardwareModules);\n        const hardwareLiteBlockObjectList = getHardwareBlockObject(hardwareLiteModules);\n        return Object.assign(\n            {},\n            basicAndExpansionBlockObjectList,\n            hardwareBlockObjectList,\n            hardwareLiteBlockObjectList\n        );\n    },\n    destroyBlockList,\n};\n"
  },
  {
    "path": "src/playground/blocks/inputs/keyboard.js",
    "content": "export const keyInputList = [\n    [Lang.Blocks.START_press_some_key_back_space, '8'],\n    ['Tab', '9'],\n    [Lang.Blocks.START_press_some_key_enter, '13'],\n    ['Shift', '16'],\n    ['Ctrl', '17'],\n    ['Alt', '18'],\n    ['Esc', '27'],\n    [Lang.Blocks.START_press_some_key_space, '32'],\n    [Lang.Blocks.START_press_some_key_left, '37'],\n    [Lang.Blocks.START_press_some_key_up, '38'],\n    [Lang.Blocks.START_press_some_key_right, '39'],\n    [Lang.Blocks.START_press_some_key_down, '40'],\n    ['0', '48'],\n    ['1', '49'],\n    ['2', '50'],\n    ['3', '51'],\n    ['4', '52'],\n    ['5', '53'],\n    ['6', '54'],\n    ['7', '55'],\n    ['8', '56'],\n    ['9', '57'],\n    ['a', '65'],\n    ['b', '66'],\n    ['c', '67'],\n    ['d', '68'],\n    ['e', '69'],\n    ['f', '70'],\n    ['g', '71'],\n    ['h', '72'],\n    ['i', '73'],\n    ['j', '74'],\n    ['k', '75'],\n    ['l', '76'],\n    ['m', '77'],\n    ['n', '78'],\n    ['o', '79'],\n    ['p', '80'],\n    ['q', '81'],\n    ['r', '82'],\n    ['s', '83'],\n    ['t', '84'],\n    ['u', '85'],\n    ['v', '86'],\n    ['w', '87'],\n    ['x', '88'],\n    ['y', '89'],\n    ['z', '90'],\n    [';', '186'],\n    ['=', '187'],\n    [',', '188'],\n    ['-', '189'],\n    ['.', '190'],\n    ['/', '191'],\n    ['~', '192'],\n    ['[', '219'],\n    [Lang.Blocks.START_press_some_key_back_slash, '220'],\n    [']', '221'],\n    [\"'\", '222'],\n];\n"
  },
  {
    "path": "src/playground/board.js",
    "content": "import debounce from 'lodash/debounce';\nimport _get from 'lodash/get';\n\nEntry.Board = class Board {\n    constructor(option) {\n        Entry.Model(this, false);\n        this.scale = option.scale || 1;\n        this.readOnly = option.readOnly === undefined ? false : option.readOnly;\n        this.changeEvent = new Entry.Event(this);\n\n        this.createView(option);\n        this.updateOffset();\n\n        this.scroller = new Entry.Scroller(this, true, true);\n\n        this._magnetMap = {};\n\n        Entry.ANIMATION_DURATION = 200;\n        Entry.BOARD_PADDING = 100;\n\n        this._initContextOptions();\n        Entry.Utils.disableContextmenu(this.svgDom);\n\n        this._addControl();\n        this._bindEvent();\n        this.observe(this, 'handleVisibleComment', ['isVisibleComment'], false);\n        Entry.addEventListener('fontLoaded', this.reDraw.bind(this));\n        if (!Entry.codeChangedEvent) {\n            Entry.codeChangedEvent = new Entry.Event(window);\n        }\n\n        const updateObjectBlockCount = () => {\n            this.updateObjectBlockCount(Entry.container.selectedObject);\n        };\n        Entry.codeChangedEvent.attach(this, updateObjectBlockCount);\n        Entry.addEventListener('loadComplete', updateObjectBlockCount);\n\n        Entry.Utils.setSVGDom(this.svgDom);\n    }\n\n    static get OPTION_PASTE() {\n        return 0;\n    }\n    static get OPTION_ALIGN() {\n        return 1;\n    }\n    static get OPTION_CLEAR() {\n        return 2;\n    }\n    static get OPTION_DOWNLOAD() {\n        return 3;\n    }\n    static get ADD_COMMENT() {\n        return 4;\n    }\n    static get VISIBLE_COMMENT() {\n        return 5;\n    }\n    static get DRAG_RADIUS() {\n        return 5;\n    }\n    static get FIRST_DRAG_RADIUS() {\n        return 10;\n    }\n\n    schema = {\n        code: null,\n        dragBlock: null,\n        magnetedBlockView: null,\n        selectedBlockView: null,\n        isVisibleComment: true,\n    };\n\n    createView(option) {\n        let dom = option.dom;\n        if (typeof dom === 'string') {\n            dom = $(`#${dom}`);\n        } else {\n            dom = $(dom);\n        }\n\n        if (dom.prop('tagName') !== 'DIV') {\n            return console.error('Dom is not div element');\n        }\n\n        this.view = dom;\n        this._svgId = `play${new Date().getTime()}`;\n\n        this.workspace = option.workspace;\n\n        this._activatedBlockView = null;\n\n        this.wrapper = Entry.Dom('div', {\n            parent: dom,\n            class: 'entryBoardWrapper',\n        });\n\n        this.svgDom = Entry.Dom(\n            $(\n                `<svg id=\"${this._svgId}\" class=\"entryBoard\" width=\"100%\" height=\"100%\"` +\n                    `version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"></svg>`\n            ),\n            { parent: this.wrapper }\n        );\n\n        this.visible = true;\n        this.svg = Entry.SVG(this._svgId);\n        $(window).scroll(this.updateOffset.bind(this));\n\n        this.svgGroup = this.svg.elem('g');\n        this.svgGroup.attr('transform', `scale(${this.scale})`);\n        this.svgObjectTitle = this.svgGroup.elem('g');\n        this.svgObjectTitle.board = this;\n        this.svgObjectTitle.attr({\n            class: 'svgObjectTitle',\n        });\n\n        this.svgObjectBlockCount = this.svgGroup.elem('g');\n        this.svgObjectBlockCount.board = this;\n        this.svgObjectBlockCount.attr({\n            class: 'svgObjectBlockCount',\n        });\n\n        this.svgThreadGroup = this.svgGroup.elem('g');\n        this.svgThreadGroup.board = this;\n\n        this.svgBlockGroup = this.svgGroup.elem('g');\n        this.svgBlockGroup.board = this;\n\n        this.svgCommentGroup = this.svgGroup.elem('g');\n        this.svgCommentGroup.board = this;\n\n        if (option.isOverlay) {\n            this.wrapper.addClass('entryOverlayBoard');\n            this.generateButtons();\n            this.suffix = 'overlayBoard';\n        } else {\n            this.suffix = 'board';\n        }\n\n        Entry.Utils.addFilters(this.svg, this.suffix);\n        this.pattern = Entry.Utils.addBlockPattern(this.svg, this.suffix).pattern;\n    }\n\n    changeCode(code, shouldNotCreateView, cb) {\n        if (this.code && this.codeListener) {\n            this.codeListener.destroy();\n        }\n\n        this.set({ code });\n\n        const that = this;\n        if (code && !shouldNotCreateView) {\n            this.codeListener = this.code.changeEvent.attach(this, () => {\n                that.changeEvent.notify();\n            });\n            this.svgCommentGroup.remove();\n            this.svgBlockGroup.remove();\n            this.svgThreadGroup.remove();\n            code.createView(this);\n            if (code.isAllThreadsInOrigin()) {\n                this.alignThreads();\n            }\n            cb && cb();\n        }\n        this.scroller.resizeScrollBar();\n    }\n\n    bindCodeView(codeView) {\n        this.svgCommentGroup.remove();\n        this.svgBlockGroup.remove();\n        this.svgThreadGroup.remove();\n        this.svgCommentGroup = codeView.svgCommentGroup;\n        this.svgBlockGroup = codeView.svgBlockGroup;\n        this.svgThreadGroup = codeView.svgThreadGroup;\n        this.svgGroup.appendChild(this.svgThreadGroup);\n        this.svgGroup.appendChild(this.svgBlockGroup);\n        this.svgGroup.appendChild(this.svgCommentGroup);\n    }\n\n    setMagnetedBlock(block, magnetType) {\n        if (this.magnetedBlockView === block) {\n            return;\n        }\n\n        this.magnetedBlockView && this.magnetedBlockView.set({ magneting: false });\n        this.set({ magnetedBlockView: block });\n        if (block) {\n            block.set({ magneting: magnetType });\n            block.dominate();\n        }\n    }\n\n    getCode() {\n        return this.code;\n    }\n\n    findById(id) {\n        return this.code.findById(id);\n    }\n\n    _addControl() {\n        const dom = this.svgDom;\n        const that = this;\n        dom.mousedown(function () {\n            that.onMouseDown(...arguments);\n        });\n        dom.bind('touchstart', function () {\n            that.onMouseDown(...arguments);\n        });\n        dom.on('wheel', function () {\n            that.mouseWheel(...arguments);\n        });\n\n        const scroller = that.scroller;\n        if (scroller) {\n            dom.mouseenter(() => {\n                scroller.setOpacity(0.8);\n            });\n            dom.mouseleave(() => {\n                scroller.setOpacity(0);\n            });\n        }\n\n        Entry.Utils.bindBlockViewHoverEvent(this, dom);\n    }\n\n    removeControl(eventType) {\n        this.svgDom.off(eventType);\n    }\n\n    onMouseDown(e) {\n        if (this.workspace.getMode() == Entry.Workspace.MODE_VIMBOARD) {\n            return;\n        }\n\n        if (e.stopPropagation) {\n            e.stopPropagation();\n        }\n        if (e.preventDefault) {\n            e.preventDefault();\n        }\n        if (e.which == 2) {\n            console.log('mouse wheel click disabled');\n            return;\n        }\n\n        if (this.workingEvent) {\n            return;\n        }\n\n        this.workingEvent = true;\n\n        if (Entry.isMobile()) {\n            this.scroller.setOpacity(0.8);\n        }\n        const board = this;\n        let longPressTimer = null;\n        let dragMode = Entry.DRAG_MODE_NONE;\n        if (e.button === 0 || (e.originalEvent && e.originalEvent.touches)) {\n            const eventType = e.type;\n            const mouseEvent = Entry.Utils.convertMouseEvent(e);\n            if (Entry.documentMousedown) {\n                Entry.documentMousedown.notify(mouseEvent);\n            }\n            dragMode = Entry.DRAG_MODE_MOUSEDOWN;\n            const doc = $(document);\n\n            this.mouseDownCoordinate = {\n                x: mouseEvent.pageX,\n                y: mouseEvent.pageY,\n            };\n\n            doc.bind('mousemove.entryBoard', onMouseMove);\n            doc.bind('mouseup.entryBoard', onMouseUp);\n            doc.bind('touchmove.entryBoard', onMouseMove);\n            doc.bind('touchend.entryBoard', onMouseUp);\n            this.dragInstance = new Entry.DragInstance({\n                startX: mouseEvent.pageX,\n                startY: mouseEvent.pageY,\n                offsetX: mouseEvent.pageX,\n                offsetY: mouseEvent.pageY,\n            });\n\n            if (eventType === 'touchstart' || Entry.isMobile()) {\n                longPressTimer = setTimeout(() => {\n                    if (longPressTimer) {\n                        longPressTimer = null;\n                        onMouseUp();\n                        board._rightClick(e);\n                    }\n                }, 1000);\n            }\n        } else if (Entry.Utils.isRightButton(e)) {\n            this._rightClick(e);\n        }\n\n        function onMouseMove(e) {\n            if (e.stopPropagation) {\n                e.stopPropagation();\n            }\n            if (e.preventDefault) {\n                e.preventDefault();\n            }\n\n            const mouseEvent = Entry.Utils.convertMouseEvent(e);\n\n            const mouseDownCoordinate = board.mouseDownCoordinate;\n            const pageX = mouseEvent.pageX;\n            const pageY = mouseEvent.pageY;\n            const diff = Math.sqrt(\n                Math.pow(pageX - mouseDownCoordinate.x, 2) +\n                    Math.pow(pageY - mouseDownCoordinate.y, 2)\n            );\n\n            if (\n                (dragMode === Entry.DRAG_MODE_DRAG && diff > Entry.Board.DRAG_RADIUS) ||\n                (dragMode === Entry.DRAG_MODE_MOUSEDOWN && diff > Entry.Board.FIRST_DRAG_RADIUS)\n            ) {\n                dragMode = Entry.DRAG_MODE_DRAG;\n                if (longPressTimer) {\n                    clearTimeout(longPressTimer);\n                    longPressTimer = null;\n                }\n\n                const dragInstance = board.dragInstance;\n                board.scroller.scroll(pageX - dragInstance.offsetX, pageY - dragInstance.offsetY);\n                dragInstance.set({ offsetX: pageX, offsetY: pageY });\n            }\n        }\n\n        function onMouseUp() {\n            if (longPressTimer) {\n                clearTimeout(longPressTimer);\n                longPressTimer = null;\n            }\n            if (Entry.isMobile()) {\n                board.scroller.setOpacity(0);\n            }\n            $(document).unbind('.entryBoard');\n            delete board.workingEvent;\n            delete board.mouseDownCoordinate;\n            delete board.dragInstance;\n        }\n    }\n\n    mouseWheel(e) {\n        e = e.originalEvent;\n        e.preventDefault();\n        const disposeEvent = Entry.disposeEvent;\n        if (disposeEvent) {\n            disposeEvent.notify(e);\n        }\n\n        this.scroller.scroll(e.wheelDeltaX || -e.deltaX, e.wheelDeltaY || -e.deltaY);\n    }\n\n    setSelectedBlock(blockView) {\n        const old = this.selectedBlockView;\n\n        if (old) {\n            old.removeSelected();\n        }\n\n        if (blockView instanceof Entry.BlockView) {\n            blockView.addSelected();\n        } else {\n            blockView = null;\n        }\n\n        this.set({ selectedBlockView: blockView });\n    }\n\n    hide() {\n        this.wrapper.addClass('entryRemove');\n        this.visible = false;\n    }\n\n    show() {\n        this.wrapper.removeClass('entryRemove');\n        this.visible = true;\n    }\n\n    initCommentSchema() {\n        const blockMap = this.code._blockMap;\n        const keys = Object.keys(blockMap) || [];\n\n        keys.forEach((id) => {\n            const comment = blockMap[id];\n            if (comment instanceof Entry.Comment) {\n                comment.initSchema();\n            }\n        });\n    }\n\n    alignThreads(reDraw) {\n        const threads = this.code.getThreads();\n        if (!threads.length) {\n            return;\n        }\n\n        this.initCommentSchema();\n\n        const verticalGap = 15;\n        let acculmulatedTop = 15;\n        let columWidth = 0;\n        const limitTopPosition = this.svgDom.height() - 30;\n        let left = 50;\n\n        threads.forEach((thread) => {\n            const block = thread.getFirstBlock();\n            if (!block) {\n                return;\n            }\n            if (!this.isVisibleComment && block instanceof Entry.Comment) {\n                return;\n            }\n            reDraw && thread.view.reDraw();\n            const blockView = block.view;\n            if (!blockView.movable) {\n                return;\n            }\n            const bBox = blockView.svgGroup.getBBox();\n            let top = acculmulatedTop + verticalGap;\n            if (top > limitTopPosition) {\n                left = left + columWidth + 10;\n                columWidth = 0;\n                acculmulatedTop = 15;\n            }\n            columWidth = Math.max(columWidth, bBox.width * this.scale);\n            top = acculmulatedTop + verticalGap;\n            if (block instanceof Entry.Block) {\n                blockView.moveTo(left, top, false);\n            } else {\n                blockView.moveTo(left / this.scale, top / this.scale, false);\n            }\n            acculmulatedTop = top + bBox.height * this.scale;\n        });\n        this.scroller.resizeScrollBar();\n    }\n\n    clear() {\n        this.svgCommentGroup.remove();\n        this.svgBlockGroup.remove();\n        this.svgThreadGroup.remove();\n        this.clearObjectTitle();\n        this.clearObjectBlockCount();\n    }\n\n    updateOffset() {\n        this._offset = this.svg.getBoundingClientRect();\n        const w = $(window);\n        const scrollTop = w.scrollTop();\n        const scrollLeft = w.scrollLeft();\n        const offset = this._offset;\n\n        this.relativeOffset = {\n            top: offset.top - scrollTop,\n            left: offset.left - scrollLeft,\n        };\n\n        const svgDom = this.svgDom;\n        if (svgDom) {\n            this._svgDomRect = {\n                width: svgDom.width(),\n                height: svgDom.height(),\n            };\n        }\n\n        if (this.btnWrapper) {\n            this.btnWrapper.attr({\n                transform: `translate(${offset.width / 2 - 65},${offset.height - 200})`,\n            });\n        }\n    }\n\n    generateButtons() {\n        this.btnWrapper = this.svg.elem('g');\n        const btnWrapper = this.btnWrapper;\n\n        const BLUE_CLASS = 'entryFunctionButtonText';\n        const WHITE_CLASS = 'entryFunctionButton';\n\n        const saveButton = btnWrapper.elem('rect', {\n            x: 74,\n            y: 12,\n            width: 64,\n            height: 32,\n            rx: 4,\n            ry: 4,\n            class: BLUE_CLASS,\n        });\n        this.saveButton = saveButton;\n\n        const cancelButton = btnWrapper.elem('rect', {\n            x: 0,\n            y: 12,\n            width: 64,\n            height: 32,\n            rx: 4,\n            ry: 4,\n            class: 'entryFunctionButtonBorder',\n        });\n\n        const saveText = btnWrapper.elem('text', {\n            x: 106,\n            y: 33,\n            class: WHITE_CLASS,\n        });\n        saveText.textContent = Lang.Buttons.save;\n\n        const cancelText = btnWrapper.elem('text', {\n            x: 32,\n            y: 33,\n            class: BLUE_CLASS,\n        });\n        cancelText.textContent = Lang.Buttons.cancel;\n\n        const saveFunc = this.save.bind(this);\n        const cancelFunc = this.cancelEdit.bind(this);\n        this.cancelButton = cancelButton;\n\n        $(saveButton).bind('mousedown touchstart', saveFunc);\n        $(saveText).bind('mousedown touchstart', saveFunc);\n        $(cancelButton).bind('mousedown touchstart', cancelFunc);\n        $(cancelText).bind('mousedown touchstart', cancelFunc);\n    }\n\n    cancelEdit() {\n        Entry.disposeEvent.notify();\n        Entry.do('funcEditEnd', 'cancel');\n    }\n\n    save() {\n        Entry.disposeEvent.notify();\n        Entry.do('funcEditEnd', 'save');\n    }\n\n    generateCodeMagnetMap() {\n        const code = this.code;\n        const dragBlock = this.dragBlock;\n        if (!(code && dragBlock)) {\n            return;\n        }\n\n        //reset magnetMap\n        this._magnetMap = {};\n\n        for (const targetType in dragBlock.magnet) {\n            if (\n                targetType === 'next' &&\n                dragBlock.thread && // 파이썬 변환 후 basic skeleton 블록이 필드에 있는 경우 제외\n                dragBlock.block.getLastBlock().view.magnet.next === undefined\n            ) {\n                continue;\n            }\n\n            const metaData = this._getCodeBlocks(code, targetType).sort(\n                (a, b) => a.point - b.point\n            );\n\n            metaData.unshift({ point: -Number.MAX_VALUE, blocks: [] });\n\n            for (let i = 1; i < metaData.length; i++) {\n                const pointData = metaData[i];\n                let includeData = pointData;\n                const block = pointData.startBlock;\n                if (block) {\n                    const limit = pointData.endPoint;\n                    let index = i;\n                    while (limit > includeData.point) {\n                        includeData.blocks.push(block);\n                        index++;\n                        includeData = metaData[index];\n                        if (!includeData) {\n                            break;\n                        }\n                    }\n                    delete pointData.startBlock;\n                }\n                pointData.endPoint = Number.MAX_VALUE;\n                metaData[i - 1].endPoint = pointData.point;\n            }\n\n            this._magnetMap[targetType] = metaData;\n        }\n    }\n\n    _getCodeBlocks(code, targetType) {\n        let func;\n        switch (targetType) {\n            case 'previous':\n                func = this._getNextMagnets;\n                break;\n            case 'next':\n                func = this._getPreviousMagnets;\n                break;\n            case 'string':\n            case 'boolean':\n                func = this._getFieldMagnets;\n                break;\n            case 'param':\n                func = this._getOutputMagnets;\n                break;\n            default:\n                return [];\n        }\n\n        return code\n            .getThreads()\n            .reduce(\n                (blocks, thread) =>\n                    blocks.concat(func.call(this, thread, thread.view.zIndex, null, targetType)),\n                []\n            );\n    }\n\n    _getNextMagnets(thread, zIndex, offset, targetType) {\n        offset = offset ? offset : { x: 0, y: 0 };\n        const blocks = thread.getBlocks();\n        let statementBlocks = [];\n        const metaData = [];\n        let cursorX = offset.x;\n        let cursorY = offset.y;\n\n        for (let i = 0; i < blocks.length; i++) {\n            const block = blocks[i];\n            const blockView = block.view;\n            blockView.zIndex = zIndex;\n            if (blockView.dragInstance) {\n                break;\n            }\n\n            cursorY += blockView.y / this.scale;\n            cursorX += blockView.x;\n            let endPoint = cursorY + 1;\n            if (blockView.magnet.next) {\n                endPoint += blockView.height;\n                metaData.push({\n                    point: cursorY,\n                    endPoint,\n                    startBlock: block,\n                    blocks: [],\n                });\n                metaData.push({\n                    point: endPoint,\n                    blocks: [],\n                });\n                blockView.absX = cursorX;\n            }\n            if (block.statements) {\n                zIndex += 0.01;\n                for (let j = 0; j < block.statements.length; j++) {\n                    const thread = block.statements[j];\n                    const statement = block.view._statements[j];\n                    statement.zIndex = zIndex;\n                    statement.absX = cursorX + statement.x * this.scale;\n                    metaData.push({\n                        point: statement.y + cursorY - 30,\n                        endPoint: statement.y + cursorY,\n                        startBlock: statement,\n                        blocks: [],\n                    });\n                    metaData.push({\n                        point: statement.y + cursorY + statement.height,\n                        blocks: [],\n                    });\n                    zIndex += 0.01;\n                    statementBlocks = statementBlocks.concat(\n                        this._getNextMagnets(\n                            thread,\n                            zIndex,\n                            {\n                                x: statement.x * this.scale + cursorX,\n                                y: statement.y + cursorY,\n                            },\n                            targetType\n                        )\n                    );\n                }\n            }\n            if (blockView.magnet.next) {\n                cursorY += blockView.magnet.next.y;\n                cursorX += blockView.magnet.next.x * this.scale;\n            }\n        }\n        return statementBlocks.concat(metaData);\n    }\n\n    _getPreviousMagnets(thread, zIndex, offset) {\n        offset = offset ? offset : { x: 0, y: 0 };\n        const blocks = thread.getBlocks();\n        const metaData = [];\n        let cursorX = offset.x;\n        let cursorY = offset.y;\n\n        const block = blocks[0];\n        const blockView = block.view;\n        blockView.zIndex = zIndex;\n        if (blockView.dragInstance) {\n            return [];\n        }\n        cursorY += blockView.y / this.scale - 15;\n        cursorX += blockView.x;\n        let endPoint = cursorY + 1;\n        if (blockView.magnet.previous) {\n            endPoint += blockView.height;\n            metaData.push({\n                point: cursorY,\n                endPoint,\n                startBlock: block,\n                blocks: [],\n            });\n            metaData.push({\n                point: endPoint,\n                blocks: [],\n            });\n            blockView.absX = cursorX;\n            return metaData;\n        }\n        return [];\n    }\n\n    _getFieldMagnets(thread, zIndex, offset, targetType) {\n        offset = offset ? offset : { x: 0, y: 0 };\n        const blocks = thread.getBlocks();\n        let statementBlocks = [];\n        let metaData = [];\n        let cursorX = offset.x;\n        let cursorY = offset.y;\n        for (let i = 0; i < blocks.length; i++) {\n            const block = blocks[i];\n            if (block instanceof Entry.Comment) {\n                break;\n            }\n            if (!block.assemble) {\n                break;\n            }\n            const blockView = block.view;\n            if (blockView.dragInstance) {\n                break;\n            }\n            blockView.zIndex = zIndex;\n            cursorY += blockView.y / this.scale;\n            cursorX += blockView.x;\n            metaData = metaData.concat(\n                this._getFieldBlockMetaData(blockView, cursorX, cursorY, zIndex, targetType)\n            );\n            if (block.statements) {\n                zIndex += 0.01;\n            }\n            for (let j = 0; j < block.statements.length; j++) {\n                const thread = block.statements[j];\n                const statement = block.view._statements[j];\n                statementBlocks = statementBlocks.concat(\n                    this._getFieldMagnets(\n                        thread,\n                        zIndex,\n                        {\n                            x: statement.x * this.scale + cursorX,\n                            y: statement.y + cursorY,\n                        },\n                        targetType\n                    )\n                );\n            }\n            if (blockView.magnet.next) {\n                cursorY += blockView.magnet.next.y;\n                cursorX += blockView.magnet.next.x * this.scale;\n            }\n        }\n        return statementBlocks.concat(metaData);\n    }\n\n    _getFieldBlockMetaData(blockView, cursorX, cursorY, zIndex, targetType) {\n        const contents = blockView._contents;\n        let metaData = [];\n        cursorY += blockView.contentPos.y;\n        for (let i = 0; i < contents.length; i++) {\n            const content = contents[i];\n            if (!(content instanceof Entry.FieldBlock)) {\n                continue;\n            }\n            const contentBlock = content._valueBlock;\n            if (contentBlock.view.dragInstance) {\n                continue;\n            }\n            const startX = cursorX + content.box.x * this.scale;\n            const startY = cursorY + content.box.y + (blockView.contentHeight % 1000) * -0.5;\n            const endY = cursorY + content.box.y + content.box.height;\n            if (content.acceptType !== targetType && content.acceptType !== 'boolean') {\n                if (targetType === 'boolean') {\n                    const contentBlockView = contentBlock.view;\n                    metaData = metaData.concat(\n                        this._getFieldBlockMetaData(\n                            contentBlockView,\n                            startX + contentBlockView.contentPos.x * this.scale,\n                            startY + contentBlockView.contentPos.y,\n                            zIndex,\n                            targetType\n                        )\n                    );\n                }\n                continue;\n            }\n            if (content.acceptType === targetType) {\n                metaData.push({\n                    point: startY,\n                    endPoint: endY,\n                    startBlock: contentBlock,\n                    blocks: [],\n                });\n                metaData.push({\n                    point: endY,\n                    blocks: [],\n                });\n            }\n            const contentBlockView = contentBlock.view;\n            contentBlockView.absX = startX;\n            contentBlockView.zIndex = zIndex;\n            metaData = metaData.concat(\n                this._getFieldBlockMetaData(\n                    contentBlockView,\n                    startX + contentBlockView.contentPos.x * this.scale,\n                    startY + contentBlockView.contentPos.y,\n                    zIndex + 0.01,\n                    targetType\n                )\n            );\n        }\n        return metaData;\n    }\n\n    _getOutputMagnets(thread, zIndex, offset, targetType) {\n        offset = offset ? offset : { x: 0, y: 0 };\n        const blocks = thread.getBlocks();\n        let statementBlocks = [];\n        let metaData = [];\n        let cursorX = offset.x;\n        let cursorY = offset.y;\n        for (let i = 0; i < blocks.length; i++) {\n            const block = blocks[i];\n            const blockView = block.view;\n            if (blockView instanceof Entry.Comment) {\n                continue;\n            }\n            if (blockView.dragInstance) {\n                break;\n            }\n            blockView.zIndex = zIndex;\n            cursorY += blockView.y / this.scale;\n            cursorX += blockView.x;\n            metaData = metaData.concat(\n                this._getOutputMetaData(blockView, cursorX, cursorY, zIndex, targetType)\n            );\n            if (block.statements) {\n                zIndex += 0.01;\n            }\n            for (let j = 0; j < block.statements.length; j++) {\n                const thread = block.statements[j];\n                const statement = block.view._statements[j];\n                statementBlocks = statementBlocks.concat(\n                    this._getOutputMagnets(\n                        thread,\n                        zIndex,\n                        {\n                            x: statement.x * this.scale + cursorX,\n                            y: statement.y + cursorY,\n                        },\n                        targetType\n                    )\n                );\n            }\n            if (blockView.magnet.next) {\n                cursorY += blockView.magnet.next.y;\n                cursorX += blockView.magnet.next.x * this.scale;\n            }\n        }\n        return statementBlocks.concat(metaData);\n    }\n\n    _getOutputMetaData(blockView, cursorX, cursorY, zIndex, targetType) {\n        const contents = blockView._contents;\n        let metaData = [];\n        cursorX += blockView.contentPos.x * this.scale;\n        cursorY += blockView.contentPos.y;\n        for (let i = 0; i < contents.length; i++) {\n            const content = contents[i];\n            const contentScaleX = content.box.x * this.scale;\n            const startX = cursorX + contentScaleX;\n            const startY = cursorY - 24;\n            const endY = cursorY;\n            if (content instanceof Entry.FieldBlock) {\n                if (content.acceptType === targetType) {\n                    metaData.push({\n                        point: startY,\n                        endPoint: endY,\n                        startBlock: content,\n                        blocks: [],\n                    });\n                    metaData.push({\n                        point: endY,\n                        blocks: [],\n                    });\n                    content.absX = startX;\n                    content.zIndex = zIndex;\n                    content.width = 20;\n                }\n\n                const contentBlock = content._valueBlock;\n                if (contentBlock) {\n                    metaData = metaData.concat(\n                        this._getOutputMetaData(\n                            contentBlock.view,\n                            startX,\n                            cursorY + content.box.y,\n                            zIndex + 0.01,\n                            targetType\n                        )\n                    );\n                }\n                continue;\n            } else if (content instanceof Entry.FieldOutput) {\n                if (content.acceptType !== targetType) {\n                    continue;\n                }\n                metaData.push({\n                    point: startY,\n                    endPoint: endY,\n                    startBlock: content,\n                    blocks: [],\n                });\n                metaData.push({\n                    point: endY,\n                    blocks: [],\n                });\n                content.absX = startX;\n                content.zIndex = zIndex;\n                content.width = 20;\n                const contentBlock = content._valueBlock;\n                if (!contentBlock) {\n                    continue;\n                }\n                if (contentBlock.view.dragInstance) {\n                    continue;\n                }\n                const contentBlockView = contentBlock.view;\n                metaData = metaData.concat(\n                    this._getOutputMetaData(\n                        contentBlockView,\n                        cursorX + contentScaleX,\n                        cursorY + content.box.y,\n                        zIndex + 0.01,\n                        targetType\n                    )\n                );\n            }\n        }\n        return metaData;\n    }\n\n    getNearestMagnet(x, y, targetType) {\n        const targetArray = this._magnetMap[targetType];\n        if (!targetArray || targetArray.length === 0) {\n            return;\n        }\n\n        let minIndex = 0;\n        let maxIndex = targetArray.length - 1;\n        let index;\n        let pointData;\n        let result = null;\n        const searchValue = targetType === 'previous' ? y - 15 : y;\n        const leftOffset = ['previous', 'next'].indexOf(targetType) > -1 ? 20 : 0;\n        while (minIndex <= maxIndex) {\n            index = ((minIndex + maxIndex) / 2) | 0;\n            pointData = targetArray[index];\n            if (searchValue < pointData.point) {\n                maxIndex = index - 1;\n            } else if (searchValue > pointData.endPoint) {\n                minIndex = index + 1;\n            } else {\n                const blocks = pointData.blocks;\n                for (let i = 0; i < blocks.length; i++) {\n                    const blockView = blocks[i].view;\n                    const minX = blockView.absX / this.scale - leftOffset;\n                    const maxX = blockView.width + minX;\n                    if (minX < x && x < maxX) {\n                        const resultBlock = pointData.blocks[i];\n                        if (!result || result.view.zIndex < resultBlock.view.zIndex) {\n                            result = pointData.blocks[i];\n                        }\n                    }\n                }\n                return result;\n            }\n        }\n        return null;\n    }\n\n    dominate(thread) {\n        if (!thread) {\n            return;\n        }\n\n        const code = this.code;\n        // currently top of dom\n        // no need to dominate again\n        if (!_shouldDominate(thread.view.zIndex, code.getMaxZIndex())) {\n            return;\n        }\n\n        const block = thread.getFirstBlock();\n        if (!block) {\n            return;\n        }\n\n        //udpate zIndex data first\n        code.dominate(thread);\n        //udpate visual things next frame\n        requestAnimationFrame(() => {\n            const svgGroup = _.result(block && block.view, 'svgGroup');\n            if (this.svgBlockGroup && svgGroup) {\n                this.svgBlockGroup.appendChild(svgGroup);\n            }\n        });\n\n        function _shouldDominate(zIndex, max) {\n            return zIndex + 1 < max || !zIndex || !max;\n        }\n    }\n\n    enablePattern() {\n        this.pattern.removeAttribute('style');\n    }\n\n    disablePattern() {\n        this.pattern.attr({ style: 'display: none' });\n    }\n\n    _removeActivated() {\n        if (!this._activatedBlockView) {\n            return;\n        }\n\n        this._activatedBlockView.removeActivated();\n        this._activatedBlockView = null;\n    }\n\n    activateBlock(block) {\n        const view = block.view;\n        const { x: blockX, y: blockY } = view.getAbsoluteCoordinate();\n\n        const { width, height } = this.getSvgDomRect();\n        this.scroller.scroll(width / 2 - blockX, height / 2 - blockY - 100);\n\n        view.addActivated();\n\n        this._activatedBlockView = view;\n    }\n\n    reDraw() {\n        this.code && this.code.view && this.code.view.reDraw();\n    }\n\n    separate(block, count, index) {\n        if (typeof block === 'string') {\n            block = this.findById(block);\n        }\n        if (block.view) {\n            block.view._toGlobalCoordinate();\n        }\n        if (block.getBlockType() === 'output') {\n            if (!count) {\n                return;\n            }\n            const prevOutputBlock = block.getPrevOutputBlock();\n            let nextOutputBlock = block;\n            for (let i = 0; i < count; i++) {\n                nextOutputBlock = nextOutputBlock.getOutputBlock();\n            }\n\n            block.separate(count, index);\n            if (prevOutputBlock && nextOutputBlock) {\n                nextOutputBlock.separate();\n                nextOutputBlock.doInsert(prevOutputBlock.view._contents[1]);\n            }\n        } else {\n            let nextBlock;\n            let backupPos;\n            const prevBlock = block.getPrevBlock();\n            if (\n                !prevBlock &&\n                block.thread instanceof Entry.Thread &&\n                block.thread.parent instanceof Entry.Code\n            ) {\n                nextBlock = block.thread.getBlock(block.thread.indexOf(block) + count);\n\n                if (nextBlock) {\n                    backupPos = nextBlock.view.getAbsoluteCoordinate();\n                }\n            }\n            block.separate(count, index);\n            if (prevBlock && prevBlock.getNextBlock()) {\n                prevBlock.getNextBlock().view.bindPrev();\n            } else if (nextBlock) {\n                nextBlock.view._toGlobalCoordinate();\n                nextBlock.moveTo(backupPos.x, backupPos.y);\n            }\n        }\n    }\n\n    insert(block, pointer, count) {\n        // pointer can be target\n        if (typeof block === 'string') {\n            block = this.findById(block);\n        }\n\n        let targetBlock;\n\n        if (pointer.length === 3) {\n            // for global\n            this.separate(block, count, pointer[2]);\n            block.moveTo(pointer[0], pointer[1]);\n        } else if (pointer.length === 4 && pointer[3] == -1) {\n            // insert on top\n            pointer[3] = 0;\n            targetBlock = this.code.getByPointer(pointer);\n            this.separate(block, count, pointer[2]);\n            block = block.getLastBlock();\n\n            targetBlock.view.bindPrev(block);\n            targetBlock.doInsert(block);\n        } else {\n            this.separate(block, count);\n            let targetObj;\n            if (pointer instanceof Array) {\n                targetObj = this.code.getByPointer(pointer);\n            } else {\n                targetObj = pointer;\n            }\n            if (targetObj instanceof Entry.Block) {\n                if (block.getBlockType() === 'basic') {\n                    block.view.bindPrev(targetObj);\n                }\n                block.doInsert(targetObj);\n            } else if (targetObj instanceof Entry.FieldStatement) {\n                block.view.bindPrev(targetObj);\n                targetObj.insertTopBlock(block);\n            } else if (targetObj instanceof Entry.Thread) {\n                targetObj = targetObj.view.getParent();\n                block.view.bindPrev(targetObj);\n                targetObj.insertTopBlock(block);\n            } else {\n                block.doInsert(targetObj);\n            }\n        }\n    }\n\n    adjustThreadsPosition() {\n        const code = this.code;\n        if (!code) {\n            return;\n        }\n        if (!code.view) {\n            return;\n        }\n\n        let threads = code.getThreads();\n        if (!threads || threads.length === 0) {\n            return;\n        }\n\n        threads = threads.sort((a, b) => a.getFirstBlock().view.x - b.getFirstBlock().view.x);\n\n        let block = threads[0].getFirstBlock();\n        if (block) {\n            block = block.view;\n            const { x, y } = block.getAbsoluteCoordinate();\n            this.scroller.scroll(50 - x, 30 - y, true);\n        }\n    }\n\n    _initContextOptions() {\n        const that = this;\n        const { options = {} } = Entry;\n        this._contextOptions = [\n            {\n                activated: true,\n                option: {\n                    text: Lang.Blocks.Paste_blocks,\n                    enable: !!Entry.clipboard && !this.readOnly,\n                    callback() {\n                        if (Entry.clipboard.type === 'comment') {\n                            Entry.do('createComment', Entry.clipboard, that);\n                        } else {\n                            Entry.do('addThread', Entry.clipboard)\n                                .value.getFirstBlock()\n                                .copyToClipboard();\n                        }\n                    },\n                },\n            },\n            {\n                activated: true,\n                option: {\n                    text: Lang.Blocks.tidy_up_block,\n                    enable: !this.readOnly,\n                    callback() {\n                        that.alignThreads();\n                    },\n                },\n            },\n            {\n                activated: true,\n                option: {\n                    text: Lang.Blocks.Clear_all_blocks,\n                    enable: !this.readOnly,\n                    callback() {\n                        Entry.do('destroyThreads');\n                    },\n                },\n            },\n            {\n                activated:\n                    Entry.blockSaveImageEnable &&\n                    Entry.type === 'workspace' &&\n                    Entry.Utils.isChrome() &&\n                    !Entry.isMobile(),\n                option: {\n                    text: Lang.Menus.save_as_image_all,\n                    enable: !this.readOnly,\n                    async callback() {\n                        const threads = that.code.getThreads();\n                        const promises = threads.map((thread) => {\n                            const topBlock = thread.getFirstBlock();\n                            if (!topBlock) {\n                                return;\n                            }\n                            return topBlock.view.getDataUrl();\n                        });\n\n                        const images = await Promise.all(promises);\n                        Entry.dispatchEvent('saveBlockImages', {\n                            images,\n                        });\n                    },\n                },\n            },\n            {\n                activated: !options.commentDisable,\n                option: {\n                    text: Lang.Blocks.add_comment,\n                    enable: !this.readOnly,\n                    callback: () => {\n                        const { left: x, top: y } = that.offset();\n                        Entry.do(\n                            'createComment',\n                            {\n                                id: Entry.Utils.generateId(),\n                                x: (Entry.ContextMenu.mouseCoordinate.x - x) / that.scale,\n                                y: (Entry.ContextMenu.mouseCoordinate.y - y) / that.scale,\n                            },\n                            that\n                        );\n                    },\n                },\n            },\n            {\n                activated: !options.commentDisable,\n                option: {\n                    text: Lang.Blocks.hide_all_comment,\n                    enable: !this.readOnly,\n                    callback() {\n                        that.isVisibleComment\n                            ? Entry.do('hideAllComment', that)\n                            : Entry.do('showAllComment', that);\n                    },\n                },\n            },\n        ];\n    }\n\n    activateContextOption(option) {\n        this._contextOptions[option].activated = true;\n    }\n\n    deActivateContextOption(option) {\n        this._contextOptions[option].activated = false;\n    }\n\n    _bindEvent() {\n        let evt = Entry.documentMousedown;\n        if (evt) {\n            evt.attach(this, this.setSelectedBlock);\n            evt.attach(this, this._removeActivated);\n        }\n\n        evt = Entry.windowResized;\n        if (evt) {\n            evt.attach(this, debounce(this.updateOffset, 200));\n        }\n    }\n\n    offset() {\n        if (!this._offset || (this._offset.top === 0 && this._offset.left === 0)) {\n            this.updateOffset();\n            return this._offset;\n        }\n        return this._offset;\n    }\n\n    _rightClick(e) {\n        delete this.workingEvent;\n        const disposeEvent = Entry.disposeEvent;\n        disposeEvent && disposeEvent.notify(e);\n        if (!this.visible) {\n            return;\n        }\n\n        const contextOptions = this._contextOptions;\n        contextOptions[Entry.Board.OPTION_PASTE].option.enable = !!Entry.clipboard;\n        contextOptions[Entry.Board.OPTION_DOWNLOAD].option.enable =\n            this.code.getThreads().length !== 0;\n        contextOptions[Entry.Board.VISIBLE_COMMENT].option.text = this.isVisibleComment\n            ? Lang.Blocks.hide_all_comment\n            : Lang.Blocks.show_all_comment;\n\n        const { clientX: x, clientY: y } = Entry.Utils.convertMouseEvent(e);\n        Entry.ContextMenu.show(\n            contextOptions.reduce((options, { activated, option }) => {\n                if (activated) {\n                    options.push(option);\n                }\n                return options;\n            }, []),\n            null,\n            { x, y }\n        );\n    }\n\n    handleVisibleComment() {\n        if (this.isVisibleComment) {\n            this.view.removeClass('invisibleComment');\n        } else {\n            this.view.addClass('invisibleComment');\n        }\n        Entry.dispatchEvent('commentVisibleChanged');\n    }\n\n    getDom(query) {\n        query = query.concat();\n        const key = query.shift();\n        if (key === 'trashcan') {\n            return this.workspace.trashcan.svgGroup;\n        } else if (key === 'coord') {\n            return {\n                getBoundingClientRect: function () {\n                    const halfWidth = 20;\n                    const boardOffset = this.relativeOffset;\n                    return {\n                        top: query[1] + boardOffset.top - halfWidth,\n                        left: query[0] + boardOffset.left - halfWidth,\n                        width: 2 * halfWidth,\n                        height: 2 * halfWidth,\n                    };\n                }.bind(this),\n            };\n        } else if (key === 'cancelEditButton') {\n            return this.cancelButton;\n        } else if (key === 'saveButton') {\n            return this.saveButton;\n        } else if (key instanceof Array) {\n            const targetObj = this.code.getByPointer(key);\n            if (targetObj.getDom) {\n                return targetObj.getDom(query);\n            } else {\n                return targetObj.svgGroup;\n            }\n        }\n    }\n\n    findBlock(block) {\n        if (typeof block === 'string') {\n            return this.findById(block);\n        } else if (block && block.id) {\n            return this.findById(block.id) || block;\n        } else if (block instanceof Array) {\n            return this.code.getByPointer(block);\n        }\n        return block;\n    }\n\n    scrollToPointer(pointer) {\n        const obj = this.code.getByPointer(pointer);\n        let pos;\n        if (obj instanceof Entry.Block) {\n            pos = obj.view.getAbsoluteCoordinate();\n            obj.view.dominate();\n        } else if (obj instanceof Entry.Thread) {\n            pos = obj.view.requestAbsoluteCoordinate();\n        } else if (obj.getAbsolutePosFromBoard) {\n            pos = obj.getAbsolutePosFromBoard();\n        }\n\n        let newX = 0;\n        let newY = 0;\n        const offset = this._offset;\n        const width = offset.width;\n        const height = offset.height;\n\n        if (pos.x > width - 200) {\n            newX = width - 200 - pos.x;\n        } else if (pos.x < 100) {\n            newX = 100 - pos.x;\n        }\n\n        if (pos.y > height - 200) {\n            newY = height - 200 - pos.y;\n        } else if (pos.y < 100) {\n            newY = 100 - pos.y;\n        }\n\n        this.scroller.scroll(newX, newY, true);\n        return [newX, newY];\n    }\n\n    getSvgDomRect() {\n        if (!this._svgDomRect) {\n            this.updateOffset();\n        }\n        return this._svgDomRect;\n    }\n\n    setScale(scale = 1) {\n        this.scale = scale;\n        this.svgGroup.attr('transform', `scale(${scale})`);\n        this.adjustThreadsPosition();\n    }\n\n    updateObjectTitle(object) {\n        if (!object) {\n            this.clearObjectTitle();\n            return;\n        }\n\n        if (!this.svgObjectTitle.thumbnail) {\n            const thumbnail = this.svgObjectTitle.elem('g');\n            const rect = thumbnail.elem('rect');\n            rect.attr({\n                x: 14,\n                y: 12,\n                rx: 2,\n                ry: 2,\n                width: 24,\n                height: 24,\n                fill: 'none',\n                stroke: '#e2e2e2',\n                strokeWidth: '1',\n            });\n            const image = thumbnail.elem('image');\n            image.addClass('entryBoardObjectThumbnail');\n            image.attr({\n                x: 17,\n                y: 15,\n                width: 18,\n                height: 18,\n                href: object.thumbUrl,\n            });\n            this.svgObjectTitle.frame = rect;\n            this.svgObjectTitle.thumbnail = image;\n        }\n\n        if (!this.svgObjectTitle.name) {\n            const name = this.svgObjectTitle.elem('g');\n            const nameText = name.elem('text');\n            nameText.addClass('entryBoardObjectName');\n            nameText.attr({ x: 44, y: 26, fill: '#6b6b6b' });\n            nameText.style.font = \"12px NanumGothicBold, 'Nanum Gothic'\";\n            nameText.textContent = object.name;\n            this.svgObjectTitle.name = nameText;\n        }\n\n        this.svgObjectTitle.thumbnail.attr({ href: object.thumbUrl });\n        this.svgObjectTitle.name.textContent = object.name;\n        this.updateObjectBlockCount(object);\n    }\n\n    async updateObjectBlockCount(object) {\n        if (this.suffix !== 'board' || !object) {\n            this.clearObjectBlockCount();\n            return;\n        }\n\n        if (!this.svgObjectBlockCount.rect) {\n            const rect = this.svgObjectBlockCount.elem('rect');\n            rect.attr({\n                rx: 10,\n                ry: 10,\n                height: 20,\n                fill: '#ffffff',\n                stroke: '#d6e9f4',\n                strokeWidth: '1',\n            });\n            this.svgObjectBlockCount.rect = rect;\n        }\n\n        if (!this.svgObjectBlockCount.countText) {\n            const countText = this.svgObjectBlockCount.elem('text');\n            countText.style.font = \"12px NanumGothic, 'Nanum Gothic'\";\n            countText.attr({\n                fill: '#6b6b6b',\n            });\n            this.svgObjectBlockCount.countText = countText;\n        }\n\n        const nameWidth =\n            Math.round(this.svgObjectTitle?.name?.getBoundingClientRect().width || 0) / this.scale;\n        const x = nameWidth + 8;\n        this.svgObjectBlockCount.countText.attr({\n            x: 44 + x + 8,\n            y: 26,\n        });\n        requestAnimationFrame(() => {\n            if (!this.svgObjectBlockCount.countText) {\n                return;\n            }\n            const rectWidth =\n                this.svgObjectBlockCount.countText.getBoundingClientRect().width / this.scale;\n            this.svgObjectBlockCount.rect.attr({\n                width: rectWidth + 16,\n                x: 44 + x,\n                y: 12,\n            });\n        });\n        const blocks = await Entry.Utils.getObjectsBlocksForEventThread(object);\n        const count = _get(blocks, 'length', 0);\n\n        let langText = Lang.Workspace.use_blocks_project;\n        if (count === 1) {\n            langText = Lang.Workspace.use_block_project;\n        }\n        if (this.svgObjectBlockCount.countText) {\n            this.svgObjectBlockCount.countText.textContent = Entry.Utils.stringFormat(\n                langText,\n                Entry.Utils.shortenNumber(count)\n            );\n        }\n    }\n\n    clearObjectTitle() {\n        if (!this.svgObjectTitle) {\n            return;\n        }\n\n        this.svgObjectTitle.frame?.remove();\n        this.svgObjectTitle.thumbnail?.remove();\n        this.svgObjectTitle.name?.remove();\n        delete this.svgObjectTitle.frame;\n        delete this.svgObjectTitle.thumbnail;\n        delete this.svgObjectTitle.name;\n    }\n\n    clearObjectBlockCount() {\n        if (!this.svgObjectBlockCount) {\n            return;\n        }\n\n        this.svgObjectBlockCount.rect?.remove();\n        this.svgObjectBlockCount.countText?.remove();\n        delete this.svgObjectBlockCount.rect;\n        delete this.svgObjectBlockCount.countText;\n    }\n};\n"
  },
  {
    "path": "src/playground/code.js",
    "content": "'use strict';\n\nimport _find from 'lodash/find';\nimport _includes from 'lodash/includes';\n\nEntry.STATEMENT = 0;\nEntry.PARAM = -1;\nEntry.Code = class Code {\n    schema = {\n        view: null,\n        board: null,\n    };\n\n    constructor(code, object) {\n        Entry.Model(this, false);\n        this.id = Entry.generateHash();\n        if (object) {\n            this.object = object;\n        }\n\n        this._data = new Entry.Collection();\n\n        this._eventMap = {};\n        this._blockMap = {};\n\n        this.executors = [];\n        this.watchEvent = new Entry.Event(this);\n        this.executeEndEvent = new Entry.Event(this);\n        this.changeEvent = new Entry.Event(this);\n        this.changeEvent.attach(this, this._handleChange);\n\n        this._maxZIndex = 0;\n\n        this.load(code);\n    }\n\n    load(code) {\n        if (Entry.engine && Entry.engine.isState('run')) {\n            return;\n        }\n\n        this.clear();\n\n        const parseCode = Array.isArray(code) ? code : JSON.parse(code);\n        parseCode.forEach((t) => {\n            if (Array.isArray(t) && t.length > 1 && t?.[0].type === 'function_create') {\n                if (!t[0].statements) {\n                    t[0].statements = [];\n                }\n                t[0].statements.push(t.splice(1, t.length));\n            }\n\n            const thread = new Entry.Thread(t, this);\n            if (thread.hasData()) {\n                this._data.push(thread);\n            }\n        });\n\n        return this;\n    }\n\n    clear(isNotForce = false) {\n        for (let i = this._data.length - 1; i >= 0; i--) {\n            this._data[i].destroy(false, isNotForce);\n        }\n\n        this.clearExecutors();\n    }\n\n    createView(board) {\n        if (this.view === null) {\n            this.set({\n                view: new Entry.CodeView(this, board),\n                board,\n            });\n        } else {\n            this.set({ board });\n            board.bindCodeView(this.view);\n        }\n    }\n\n    destroyView() {\n        if (!this.view) {\n            return;\n        }\n        this.view.destroy();\n        this.set({ view: null });\n    }\n\n    recreateView() {\n        if (!this.view) {\n            return;\n        }\n        this.destroyView();\n        this.set({\n            view: new Entry.CodeView(this, this.board),\n            board: this.board,\n        });\n    }\n\n    registerEvent(block, eventType) {\n        const eventMap = this._eventMap;\n        if (!eventMap[eventType]) {\n            eventMap[eventType] = [];\n        }\n\n        eventMap[eventType].push(block);\n    }\n\n    unregisterEvent(block, eventType) {\n        const blocks = this._eventMap[eventType];\n        if (_.isEmpty(blocks)) {\n            return;\n        }\n\n        const index = blocks.indexOf(block);\n        if (index < 0) {\n            return;\n        }\n        blocks.splice(index, 1);\n    }\n\n    raiseEvent(eventType, entity, value) {\n        const blocks = this._eventMap[eventType];\n        if (blocks === undefined) {\n            return;\n        }\n\n        const executors = [];\n\n        for (let i = 0; i < blocks.length; i++) {\n            const block = blocks[i];\n            const pointer = block.pointer();\n            if (pointer[3] !== 0 || pointer.length !== 4) {\n                continue;\n            }\n            if (value === undefined || block.params.indexOf(value) > -1) {\n                const executor = new Entry.Executor(blocks[i], entity, this);\n                this.executors.push(executor);\n                executors.push(executor);\n            }\n        }\n        return executors;\n    }\n\n    getEventMap(eventType) {\n        return this._eventMap[eventType];\n    }\n\n    map(func) {\n        this._data.map(func);\n    }\n\n    tick() {\n        if (Entry.isTurbo && !this.isUpdateTime) {\n            this.isUpdateTime = performance.now();\n        }\n        const executors = this.executors;\n        const watchEvent = this.watchEvent;\n        const shouldNotifyWatch = watchEvent.hasListeners();\n        let result;\n        let executedBlocks = [];\n        const loopExecutor = [];\n\n        const _executeEvent = _.partial(Entry.dispatchEvent, 'blockExecute');\n        const _executeEndEvent = _.partial(Entry.dispatchEvent, 'blockExecuteEnd');\n\n        for (let i = 0; i < executors.length; i++) {\n            const executor = executors[i];\n            if (executor.isPause()) {\n                continue;\n            } else if (!executor.isEnd()) {\n                const { view } = executor.scope.block || {};\n                _executeEvent(view);\n                result = executor.execute(true);\n                if (executor.isLooped) {\n                    loopExecutor.push(executor);\n                }\n                if (shouldNotifyWatch) {\n                    const { blocks } = result;\n                    executedBlocks = executedBlocks.concat(blocks);\n                }\n            } else if (executor.isEnd()) {\n                _executeEndEvent(this.board);\n                executors.splice(i--, 1);\n                if (_.isEmpty(executors)) {\n                    this.executeEndEvent.notify();\n                }\n            }\n        }\n\n        if (Entry.isTurbo) {\n            for (let i = 0; i < loopExecutor.length; i++) {\n                const executor = loopExecutor[i];\n                if (executor.isPause()) {\n                    continue;\n                } else if (!executor.isEnd()) {\n                    const { view } = executor.scope.block || {};\n                    _executeEvent(view);\n                    result = executor.execute(true);\n                    if (shouldNotifyWatch) {\n                        const { blocks } = result;\n                        executedBlocks = executedBlocks.concat(blocks);\n                    }\n                } else if (executor.isEnd()) {\n                    _executeEndEvent(this.board);\n                    loopExecutor.splice(i--, 1);\n                    if (_.isEmpty(loopExecutor)) {\n                        this.executeEndEvent.notify();\n                    }\n                }\n\n                if (\n                    i === loopExecutor.length - 1 &&\n                    Entry.tickTime > performance.now() - this.isUpdateTime\n                ) {\n                    i = -1;\n                }\n            }\n        }\n\n        this.isUpdateTime = 0;\n        shouldNotifyWatch && watchEvent.notify(executedBlocks);\n        if (result && result.promises) {\n            Entry.engine.addPromiseExecutor(result.promises);\n        }\n    }\n\n    removeExecutor(executor) {\n        const index = this.executors.indexOf(executor);\n        if (index > -1) {\n            this.executors.splice(index, 1);\n        }\n    }\n\n    clearExecutors() {\n        this.executors.forEach((e) => e.end());\n        Entry.dispatchEvent('blockExecuteEnd');\n        this.executors = [];\n    }\n\n    clearExecutorsByEntity(entity) {\n        this.executors.forEach((executor) => {\n            if (executor.entity === entity) {\n                executor.end();\n            }\n        });\n    }\n\n    addExecutor(executor) {\n        this.executors.push(executor);\n    }\n\n    createThread(blocks, index) {\n        if (!Array.isArray(blocks)) {\n            return console.error('blocks must be array');\n        }\n\n        const thread = new Entry.Thread(blocks, this);\n        if (index === undefined || index === null) {\n            this._data.push(thread);\n        } else {\n            this._data.insert(thread, index);\n        }\n\n        this.changeEvent.notify();\n        return thread;\n    }\n\n    getThreadIndex(thread) {\n        return this._data.indexOf(thread);\n    }\n\n    getThreadCount() {\n        return this._data.length;\n    }\n\n    cloneThread(thread, mode) {\n        const newThread = thread.clone(this, mode);\n        this._data.push(newThread);\n        return newThread;\n    }\n\n    destroyThread(thread) {\n        const data = this._data;\n        const index = data.indexOf(thread);\n        // case of statement thread\n        if (~index) {\n            data.splice(index, 1);\n        }\n    }\n\n    pushBackThread(thread) {\n        this._data.splice(this.getThreadIndex(thread), 1);\n        this._data.push(thread);\n    }\n\n    doDestroyThread = this.destroyThread;\n\n    getThread(index) {\n        return this._data[index];\n    }\n\n    getThreads() {\n        return this._data.slice();\n    }\n\n    getThreadsByCategory(categoryName) {\n        if (!categoryName) {\n            return [];\n        }\n\n        return this.getThreads().filter(\n            (t) => _.result(t.getFirstBlock(), 'category') === categoryName\n        );\n    }\n\n    toJSON(excludeData, option) {\n        const params = [false, undefined, excludeData, option];\n        return this.getThreads().map((t) => t.toJSON(...params));\n    }\n\n    countBlock() {\n        return this.getThreads().reduce((cnt, thread) => cnt + thread.countBlock(), 0);\n    }\n\n    moveBy(x, y) {\n        this.getThreads().forEach((thread) => {\n            const { view = {} } = thread.getFirstBlock() || {};\n            if (view && view.display) {\n                view.moveBy(x, y, false);\n            }\n        });\n        const { board } = this;\n        if (board instanceof Entry.BlockMenu) {\n            board.updateSplitters(y);\n        }\n    }\n\n    stringify(excludeData) {\n        return JSON.stringify(this.toJSON(excludeData));\n    }\n\n    dominate(thread) {\n        thread.view.setZIndex(this._maxZIndex++);\n    }\n\n    getMaxZIndex() {\n        return this._maxZIndex;\n    }\n\n    indexOf(thread) {\n        return this._data.indexOf(thread);\n    }\n\n    _handleChange() {\n        const board = _.result(this.view, 'board');\n        const event = Entry.creationChangedEvent;\n        if (board && event && board.constructor !== Entry.BlockMenu) {\n            event.notify();\n            if (Entry.codeChangedEvent) {\n                Entry.codeChangedEvent.notify();\n            }\n        }\n    }\n\n    hasBlockType(type) {\n        return this.getThreads().some((thread) => thread.hasBlockType(type));\n    }\n\n    findById(id) {\n        return this._blockMap[id];\n    }\n\n    findByType(type) {\n        const id = Object.keys(this._blockMap).find((id) => {\n            const block = this._blockMap[id];\n            return block.type === type;\n        });\n        return this._blockMap[id];\n    }\n\n    findByParamId(paramId) {\n        return _find(this._blockMap, (block) => _includes(block?.params || [], paramId));\n    }\n\n    registerBlock(block) {\n        this._blockMap[block.id] = block;\n    }\n\n    unregisterBlock({ id }) {\n        delete this._blockMap[id];\n    }\n\n    getByPointer([, , ...pointer]) {\n        const thread = this._data[pointer.shift()];\n        let block = thread.getBlock(pointer.shift());\n        while (pointer.length) {\n            if (!(block instanceof Entry.Block)) {\n                if (!block || !block.getValueBlock) {\n                    console.error(\"can't get valueBlock\", block);\n                    return block;\n                }\n                block = block.getValueBlock();\n            }\n            const type = pointer.shift();\n            const index = pointer.shift();\n            if (type > -1) {\n                const statement = block.statements[type];\n                if (index === undefined) {\n                    return statement;\n                } else {\n                    block = statement.getBlock(index);\n                }\n            } else if (type === -1) {\n                block = block.view.getParam(index);\n            }\n        }\n        return block;\n    }\n\n    getTargetByPointer([, , ...pointer]) {\n        const thread = this._data[pointer.shift()];\n        let block;\n\n        if (pointer.length === 1) {\n            block = thread.getBlock(pointer.shift() - 1);\n        } else {\n            block = thread.getBlock(pointer.shift());\n            while (pointer.length) {\n                if (!(block instanceof Entry.Block)) {\n                    block = block.getValueBlock();\n                }\n                const type = pointer.shift();\n                const index = pointer.shift();\n                if (type > -1) {\n                    const statement = block.statements[type];\n                    if (!pointer.length) {\n                        if (index === 0) {\n                            block = statement.view.getParent();\n                        } else if (index === undefined) {\n                            block = statement;\n                        } else {\n                            block = statement.getBlock(index - 1);\n                        }\n                    } else {\n                        if (index < 0) {\n                            block = statement;\n                        } else {\n                            block = statement.getBlock(index);\n                        }\n                    }\n                } else if (type === -1) {\n                    block = block.view.getParam(index);\n                }\n            }\n        }\n        return block;\n    }\n\n    getBlockList(excludePrimitive, type) {\n        return _.chain(this.getThreads())\n            .map((t) => t.getBlockList(excludePrimitive, type))\n            .flatten(true)\n            .value();\n    }\n\n    getBlockListForEventThread(excludePrimitive, type) {\n        return _.chain(this.getThreads())\n            .map((t) => {\n                if (t._event) {\n                    return t.getBlockList(excludePrimitive, type);\n                }\n                return [];\n            })\n            .flatten(true)\n            .value();\n    }\n\n    removeBlocksByType(type) {\n        this.getBlockList(false, type).forEach((b) => b.doDestroy());\n    }\n\n    isAllThreadsInOrigin() {\n        return this.getThreads().every((thread) => thread.isInOrigin());\n    }\n\n    destroy() {\n        this.clear();\n        this.destroyView();\n    }\n\n    static waitPauseState = async () => {\n        while (Entry.engine.isState('pause')) {\n            await Entry.Utils.sleep(100);\n        }\n    };\n\n    static funcAsyncExecute = async (funcCode, funcExecutor, _promises = []) => {\n        await Promise.all(_promises);\n        if (Entry.engine.isState('pause')) {\n            await this.waitPauseState();\n            return this.funcAsyncExecute(funcCode, funcExecutor, _promises);\n        } else if (!Entry.engine.isState('run')) {\n            funcCode.removeExecutor(funcExecutor);\n            return Entry.STATIC.BREAK;\n        }\n\n        return new Promise((resolve, reject) => {\n            requestAnimationFrame(async () => {\n                const result = funcExecutor.execute();\n                const { promises = [] } = result || {};\n\n                if (!funcExecutor.isEnd()) {\n                    if (promises.length) {\n                        try {\n                            return resolve(\n                                await this.funcAsyncExecute(funcCode, funcExecutor, promises)\n                            );\n                        } catch (e) {\n                            return reject(e);\n                        }\n                    } else {\n                        funcCode.callStackLength--;\n                        funcCode.removeExecutor(funcExecutor);\n                        return resolve(Entry.STATIC.CONTINUE);\n                    }\n                }\n                return resolve();\n            });\n        });\n    };\n\n    static getAsyncParamsData = async (scope) => {\n        const values = scope.getParams();\n        const isPromise = values.some((value) => value instanceof Promise);\n        if (!isPromise) {\n            scope.values = values;\n        } else {\n            scope.values = await Promise.all(values);\n        }\n        return scope.getValue('VALUE', scope);\n    };\n\n    static funcValueAsyncExecute = async (funcCode, funcExecutor, _promises = []) => {\n        await Promise.all(_promises);\n        if (Entry.engine.isState('pause')) {\n            await this.waitPauseState();\n            return this.funcValueAsyncExecute(funcCode, funcExecutor, _promises);\n        } else if (!Entry.engine.isState('run')) {\n            funcCode.removeExecutor(funcExecutor);\n            return await this.getAsyncParamsData(funcExecutor.result);\n        }\n\n        return new Promise((resolve, reject) => {\n            requestAnimationFrame(async () => {\n                try {\n                    const result = funcExecutor.execute();\n                    const { promises = [] } = result || {};\n\n                    if (!funcExecutor.isEnd()) {\n                        if (promises.length) {\n                            try {\n                                return resolve(\n                                    await this.funcValueAsyncExecute(\n                                        funcCode,\n                                        funcExecutor,\n                                        promises\n                                    )\n                                );\n                            } catch (e) {\n                                return reject(e);\n                            }\n                        } else {\n                            funcCode.callStackLength--;\n                            funcCode.removeExecutor(funcExecutor);\n                        }\n                    }\n                    resolve(await this.getAsyncParamsData(funcExecutor.result));\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        });\n    };\n\n    static funcRestExecute = async (funcCode, funcExecutor) => {\n        if (!Entry.engine.isState('run')) {\n            funcCode.removeExecutor(funcExecutor);\n            return await this.getAsyncParamsData(funcExecutor.result);\n        }\n\n        return new Promise((resolve, reject) => {\n            requestAnimationFrame(async () => {\n                try {\n                    const result = funcExecutor.execute();\n                    const { promises = [] } = result || {};\n                    if (!funcExecutor.isEnd()) {\n                        if (promises.length) {\n                            try {\n                                return resolve(\n                                    await this.funcValueAsyncExecute(\n                                        funcCode,\n                                        funcExecutor,\n                                        promises\n                                    )\n                                );\n                            } catch (e) {\n                                return reject(e);\n                            }\n                        } else {\n                            return resolve(await this.funcRestExecute(funcCode, funcExecutor));\n                        }\n                    }\n                    resolve(await this.getAsyncParamsData(funcExecutor.result));\n                    funcCode.removeExecutor(funcExecutor);\n                } catch (e) {\n                    reject(e);\n                }\n            });\n        });\n    };\n};\n"
  },
  {
    "path": "src/playground/code_view.js",
    "content": "/*\n *\n */\n'use strict';\n\n/*\n *\n */\nEntry.CodeView = function(code, board) {\n    Entry.Model(this, false);\n\n    this.code = code;\n    this.set({ board: board });\n\n    this.svgThreadGroup = board.svgGroup.elem('g');\n    this.svgThreadGroup.attr({\n        class: 'svgThreadGroup',\n    });\n\n    this.svgThreadGroup.board = board;\n\n    this.svgBlockGroup = board.svgGroup.elem('g');\n    this.svgBlockGroup.attr({\n        class: 'svgBlockGroup',\n    });\n    this.svgBlockGroup.board = board;\n\n    this.svgCommentGroup = board.svgGroup.elem('g');\n    this.svgCommentGroup.attr({\n        class: 'svgCommentGroup',\n    });\n    this.svgCommentGroup.board = board;\n\n    board.bindCodeView(this);\n\n    this.code._data.getAll().forEach(function(thread) {\n        thread.createView(board);\n    });\n    code.observe(this, '_setBoard', ['board']);\n};\n\n(function(p) {\n    p.schema = {\n        board: null,\n        scrollX: 0,\n        scrollY: 0,\n    };\n\n    p._setBoard = function() {\n        this.set({ board: this.code.board });\n    };\n\n    p.reDraw = function() {\n        this.code.map(\n            function(thread) {\n                if (thread.view) thread.view.reDraw();\n                else thread.createView(this.board);\n            }.bind(this)\n        );\n    };\n\n    p.destroy = function() {\n        this.code.map(function(thread) {\n            thread.destroyView();\n        });\n    };\n})(Entry.CodeView.prototype);\n"
  },
  {
    "path": "src/playground/comment.js",
    "content": "Entry.Comment = class Comment {\n    dragMode = Entry.DRAG_MODE_NONE;\n    offsetX = 50;\n    offsetY = 10;\n    schema = {\n        id: null,\n        x: 0,\n        y: 0,\n        moveX: 0,\n        moveY: 0,\n        parentWidth: 0,\n        parentHeight: 0,\n        width: 160,\n        height: 160,\n        value: '',\n        readOnly: false,\n        visible: true,\n        display: true,\n        movable: true,\n        isOpened: true,\n        deletable: Entry.Block.DELETABLE_TRUE,\n    };\n\n    constructor(schema, board, block) {\n        Entry.Model(this, false);\n\n        if (schema) {\n            this.set(schema);\n        }\n        this.generateId(schema);\n        this._block = block;\n        if (block) {\n            this.createComment(board, schema);\n        }\n        this.magnet = {};\n    }\n\n    get block() {\n        return this._block;\n    }\n\n    get board() {\n        return this._board;\n    }\n\n    get blockView() {\n        return this._blockView;\n    }\n\n    get view() {\n        return this;\n    }\n\n    get defaultLineLength() {\n        return 40;\n    }\n\n    get titleHeight() {\n        return 22;\n    }\n\n    get scale() {\n        return this.board.scale || 1;\n    }\n\n    get fontSize() {\n        return this.scale * 10;\n    }\n\n    get value() {\n        return this.value;\n    }\n\n    get thread() {\n        return this._thread || (this.block && this.block.thread);\n    }\n\n    get code() {\n        if (this.board && this.board.getCode) {\n            return this.board.getCode();\n        }\n        if (this.thread && this.thread.getCode) {\n            return this.thread.getCode();\n        }\n    }\n\n    get textAreaPath() {\n        let d = '';\n        let { width, height } = this;\n        width = Math.max(width, 100);\n        height = Math.max(height, 100);\n\n        for (let y = 14; y < height - this.titleHeight - 4; y += 16) {\n            d += `M6,${y} H${width - 12} `;\n        }\n        return d;\n    }\n\n    get titleAreaPath() {\n        let d = '';\n        d = `M0 4 C 0 2 2 0 4 0 H${this.width - 4}`;\n        d += ` C ${this.width - 2} 0 ${this.width} 2 ${this.width} 4 `;\n        if (this.isOpened) {\n            d += `V22 H0 V4`;\n        } else if (this.block) {\n            d = 'M0 11 C 0 5 5 0 11 0 C 17 0 22 5 22 11 ';\n            d += 'C 22 17 17 22 11 22 C 5 22 0 17 0 11';\n        } else {\n            d += `V18 C ${this.width} 20 ${this.width - 2} 22 ${this.width - 4} 22 H4`;\n            d += `C 2 22 0 20 0 18 V4`;\n        }\n        return d;\n    }\n\n    get titleTextAreaPath() {\n        return `M22,14 H${this.width - 22}`;\n    }\n\n    generateId(schema = {}) {\n        const id = schema.id || Entry.Utils.generateId();\n        this.set({ id });\n    }\n\n    createComment(board, schema) {\n        if (board) {\n            this._board = board;\n        }\n        const { view } = this.block || {};\n        this._blockView = view;\n        const { svgGroup, pathGroup, svgCommentGroup } = this.blockView || {};\n        this.pathGroup = pathGroup;\n        this.parentGroup = svgGroup;\n\n        if (this.block && svgCommentGroup) {\n            this.svgGroup = svgCommentGroup.prepend('g');\n        } else if (this.board.svgCommentGroup) {\n            this.svgGroup = this.board.svgCommentGroup.elem('g');\n        } else {\n            return;\n        }\n        this.mouseDown = this.mouseDown.bind(this);\n        this.mouseMove = this.mouseMove.bind(this);\n        this.mouseUp = this.mouseUp.bind(this);\n        this.resizeMouseDown = this.resizeMouseDown.bind(this);\n        this.resizeMouseMove = this.resizeMouseMove.bind(this);\n        this.resizeMouseUp = this.resizeMouseUp.bind(this);\n        this.toggleMouseDown = this.toggleMouseDown.bind(this);\n        this.toggleMouseUp = this.toggleMouseUp.bind(this);\n\n        this.startRender();\n        this.initParentSize();\n        if (schema) {\n            this.initSchema(schema);\n        }\n        this.setFrame();\n        this.addControl();\n        this.setPosition();\n        this.code && this.code.registerBlock(this);\n        this.setObservers();\n    }\n\n    startRender() {\n        if (this.block) {\n            this._line = this.svgGroup.elem('line');\n        }\n\n        this._contentGroup = this.svgGroup.elem('g');\n        this._comment = this._contentGroup.elem('rect');\n        this._path = this._contentGroup.elem('defs').elem('path');\n        this._text = this._contentGroup.elem('text');\n        this._textPath = this._text.elem('textPath');\n        this._resizeArrow = this._contentGroup.elem('image');\n        this._resizeArea = this._contentGroup.elem('rect');\n\n        this._title = this.svgGroup.elem('path');\n        this._titleGroup = this.svgGroup.elem('g');\n        this._toggleArrow = this._titleGroup.elem('image');\n        this._titlePath = this._titleGroup.elem('defs').elem('path');\n        this._titleText = this._titleGroup.elem('text');\n        this._titleTextPath = this._titleText.elem('textPath');\n\n        this._commentIcon = this.svgGroup.elem('image');\n        this._toggleArea = this.svgGroup.elem('rect');\n\n        this.canRender = true;\n    }\n\n    initSchema(schema = {}) {\n        const { titleHeight, defaultLineLength } = this;\n        const x = this.parentWidth + defaultLineLength;\n        const y = this.parentHeight / 2 - titleHeight / 2;\n\n        schema.x = schema.x || x;\n        schema.y = schema.y || y;\n        schema.width = schema.width || 160;\n        schema.height = schema.height || 160;\n        this.set(schema);\n    }\n\n    initParentSize() {\n        if (!this.pathGroup) {\n            return;\n        }\n        const parentWidth = this.pathGroup.getBBox().width;\n        const { topFieldHeight, height } = this._blockView;\n        const parentHeight = topFieldHeight || height;\n\n        this.set({\n            parentWidth,\n            parentHeight,\n        });\n    }\n\n    setFrame() {\n        this._comment.attr({\n            stroke: '#EDA913',\n            fill: '#FFDA85',\n            rx: '4',\n        });\n\n        this._title.attr({\n            stroke: '#EDA913',\n            fill: '#FBB315',\n        });\n\n        if (this.block) {\n            this._line.attr({\n                style: 'stroke:#eda913;stroke-width:2',\n            });\n        }\n\n        this._path.attr({\n            id: `${this.id}c`,\n            stroke: 'red',\n        });\n\n        this._titlePath.attr({\n            id: `${this.id}t`,\n        });\n\n        this._text.attr({\n            'font-size': 10,\n        });\n\n        this._titleText.attr({\n            'font-size': 10,\n            fill: 'white',\n            'font-weight': 'bold',\n            class: 'invisible',\n        });\n\n        this._textPath.attr({\n            href: `#${this.id}c`,\n        });\n\n        this._titleTextPath.attr({\n            href: `#${this.id}t`,\n        });\n\n        const path = `${Entry.mediaFilePath}block_icon/comment/`;\n\n        this._resizeArea.attr({\n            width: 20,\n            height: 20,\n            fill: 'transparent',\n            class: 'entry-comment-resize-arrow',\n        });\n\n        this._resizeArrow.attr({\n            width: 8,\n            height: 8,\n            href: `${path}resize_arrow.svg`,\n        });\n\n        this._toggleArea.attr({\n            y: this.y,\n            width: 20,\n            height: this.titleHeight,\n            fill: 'transparent',\n            class: 'entry-comment-toggle-arrow',\n        });\n\n        this._toggleArrow.attr({\n            width: 8,\n            height: 5,\n            href: `${path}toggle_open_arrow.svg`,\n        });\n\n        this._commentIcon.attr({\n            width: 12,\n            height: 12,\n            href: `${path}comment_icon.svg`,\n        });\n    }\n\n    setPosition() {\n        if (!this.visible) {\n            return;\n        }\n        const { x, y } = this;\n        let width = Math.max(this.width, 100);\n        let rx = 4;\n        const height = Math.max(this.height, 100);\n        if (!this.isOpened && this.block) {\n            width = 22;\n            rx = 11;\n        }\n\n        this._title.attr({\n            transform: `translate(${x}, ${y})`,\n            d: this.titleAreaPath,\n        });\n\n        this._comment.attr({\n            x,\n            y,\n            width,\n            height,\n        });\n\n        if (this.block) {\n            this._line.attr({\n                x1: this.parentWidth,\n                y1: this.parentHeight / 2,\n                x2: x + width / 2,\n                y2: y + this.titleHeight / 2,\n            });\n        }\n\n        this._path.attr({\n            transform: `translate(${x}, ${y + this.titleHeight})`,\n            d: this.textAreaPath,\n        });\n\n        this._titlePath.attr({\n            transform: `translate(${x}, ${y})`,\n            d: this.titleTextAreaPath,\n        });\n\n        this._resizeArea.attr({\n            x: x + width - 20,\n            y: y + height - 20,\n        });\n\n        this._resizeArrow.attr({\n            x: x + width - 14,\n            y: y + height - 14,\n        });\n\n        this._toggleArea.attr({\n            y,\n            x: x + width - 20,\n            height: this.titleHeight,\n        });\n\n        this._toggleArrow.attr({\n            x: x + width - 16,\n            y: y + 8,\n        });\n\n        this._commentIcon.attr({\n            x: x + 5,\n            y: y + 5,\n        });\n    }\n\n    setObservers() {\n        this._observers = [];\n        this._observers.push(this.observe(this, 'updateOpacity', ['visible'], false));\n        this._observers.push(this.observe(this, 'toggleContent', ['isOpened']));\n        this._observers.push(this.observe(this, 'setValue', ['value']));\n        this._observers.push(\n            this.observe(this, 'setPosition', [\n                'x',\n                'y',\n                'width',\n                'height',\n                'parentWidth',\n                'parentHeight',\n                'isOpened',\n            ])\n        );\n    }\n\n    updatePos() {\n        this.set({\n            x: this.moveX,\n            y: this.moveY,\n        });\n    }\n\n    updateParentPos() {\n        if (this.pathGroup) {\n            const { width: parentWidth } = this.pathGroup.getBBox();\n            const { topFieldHeight, height } = this._blockView;\n            const parentHeight = topFieldHeight || height;\n            const { parentWidth: beforeParentWidth, parentHeight: beforeParentHeight } = this;\n            const defferenceWidth = parentWidth - beforeParentWidth;\n            const defferenceHeight = parentHeight - beforeParentHeight;\n\n            if (defferenceWidth || defferenceHeight) {\n                let { x, y } = this;\n                x += defferenceWidth;\n                y += defferenceHeight;\n\n                this.set({\n                    x,\n                    y,\n                    parentWidth,\n                    parentHeight,\n                });\n            }\n        }\n    }\n\n    moveTo(x, y) {\n        if (!this.display) {\n            this.set({ x: -99999, y: -99999 });\n        } else {\n            this.set({ x, y });\n        }\n    }\n\n    moveBy(x, y) {\n        return this.moveTo(this.x + x / this.scale, this.y + y / this.scale);\n    }\n\n    resize(x, y) {\n        this.set({\n            width: this.width + x,\n            height: this.height + y,\n        });\n    }\n\n    setDragInstance(e) {\n        const mouseEvent = Entry.Utils.convertMouseEvent(e);\n        const matrix = this.svgGroup.getCTM();\n        const { x, y } = Entry.GlobalSvg.getRelativePoint(matrix);\n        const { left: startX, top: startY } = (this.pathGroup &&\n            this.pathGroup.getBoundingClientRect()) || { left: x, top: y };\n        this.mouseDownCoordinate = {\n            x: mouseEvent.pageX,\n            y: mouseEvent.pageY,\n            parentX: x,\n            parentY: y,\n        };\n        this.dragInstance = new Entry.DragInstance({\n            startX,\n            startY,\n            offsetX: mouseEvent.pageX,\n            offsetY: mouseEvent.pageY,\n            mode: true,\n        });\n    }\n\n    bindDomEvent(mouseMove, mouseUp) {\n        document.addEventListener('mousemove', mouseMove);\n        document.addEventListener('touchmove', mouseMove);\n        document.addEventListener('mouseup', mouseUp);\n        document.addEventListener('touchend', mouseUp);\n    }\n\n    removeDomEvent(mouseMove, mouseUp) {\n        document.removeEventListener('mousemove', mouseMove);\n        document.removeEventListener('touchmove', mouseMove);\n        document.removeEventListener('mouseup', mouseUp);\n        document.removeEventListener('touchend', mouseUp);\n    }\n\n    getMouseMoveDiff(mouseEvent) {\n        return Math.sqrt(\n            Math.pow(mouseEvent.pageX - this.mouseDownCoordinate.x, 2) +\n                Math.pow(mouseEvent.pageY - this.mouseDownCoordinate.y, 2)\n        );\n    }\n\n    mouseDown(e) {\n        e.stopPropagation();\n        e.preventDefault();\n        this.longPressTimer = null;\n        if (this.board.workingEvent) {\n            return;\n        }\n        this.board.workingEvent = true;\n\n        if ((e.button === 0 || e.type === 'touchstart') && !this.board.readOnly) {\n            this.setDragInstance(e);\n            this.dragMode = Entry.DRAG_MODE_MOUSEDOWN;\n            this.bindDomEvent(this.mouseMove, this.mouseUp);\n            const eventType = e.type;\n            this.board.set({ dragBlock: this });\n\n            if (eventType === 'touchstart' || Entry.isMobile()) {\n                this.longPressTimer = setTimeout(() => {\n                    if (this.longPressTimer) {\n                        this.longPressTimer = null;\n                        this.rightClick(e);\n                        this.mouseUp(e);\n                    }\n                }, 700);\n            }\n        } else if (Entry.Utils.isRightButton(e)) {\n            this.rightClick(e);\n        }\n    }\n\n    rightClick(e) {\n        const disposeEvent = Entry.disposeEvent;\n        if (disposeEvent) {\n            disposeEvent.notify(e);\n        }\n        delete this.board.workingEvent;\n        this.dragMode = Entry.DRAG_MODE_NONE;\n\n        const { clientX: x, clientY: y } = Entry.Utils.convertMouseEvent(e);\n\n        const board = this.board;\n        return Entry.ContextMenu.show(_getOptions(this), null, { x, y });\n\n        function _getOptions(comment) {\n            const readOnly = comment.readOnly;\n\n            const copyAndPaste = {\n                text: Lang.Blocks.copy_paste_comment,\n                enable: !readOnly,\n                callback() {\n                    Entry.do('cloneComment', comment.copy(), board);\n                },\n            };\n\n            const copy = {\n                text: Lang.Blocks.copy_comment,\n                enable: !readOnly,\n                callback() {\n                    comment.copyToClipboard();\n                },\n            };\n\n            const remove = {\n                text: Lang.Blocks.delete_comment,\n                enable: !readOnly,\n                callback() {\n                    Entry.do('removeComment', comment);\n                },\n            };\n\n            const toggle = {\n                text: comment.isOpened ? Lang.Blocks.fold_comment : Lang.Blocks.open_comment,\n                enable: !readOnly,\n                callback() {\n                    Entry.do('toggleComment', comment);\n                },\n            };\n\n            const separate = {\n                text: Lang.Blocks.separate_comment,\n                enable: !!comment.block,\n                callback() {\n                    Entry.do('separateComment', comment);\n                },\n            };\n\n            const options = [copyAndPaste, copy, remove, toggle, separate];\n\n            return options;\n        }\n    }\n\n    mouseMove(e) {\n        e.stopPropagation();\n        const mouseEvent = Entry.Utils.convertMouseEvent(e);\n        if (\n            this.dragMode === Entry.DRAG_MODE_DRAG ||\n            this.getMouseMoveDiff(mouseEvent) > Entry.BlockView.DRAG_RADIUS\n        ) {\n            if (this.longPressTimer) {\n                clearTimeout(this.longPressTimer);\n                this.longPressTimer = null;\n            }\n            if (this.isEditing) {\n                this.destroyTextArea();\n            }\n            const workspaceMode = this.board.workspace.getMode();\n            if (this.dragMode !== Entry.DRAG_MODE_DRAG) {\n                this.set({\n                    moveX: this.x,\n                    moveY: this.y,\n                });\n                this.dragMode = Entry.DRAG_MODE_DRAG;\n                Entry.GlobalSvg.setComment(this, workspaceMode);\n                this.visible && this.set({ visible: false });\n                this.generateCommentableBlocks();\n            }\n\n            this.set({\n                moveX: this.moveX + (mouseEvent.pageX - this.dragInstance.offsetX) / this.scale,\n                moveY: this.moveY + (mouseEvent.pageY - this.dragInstance.offsetY) / this.scale,\n            });\n\n            this.checkConnectableBlock();\n            this.dragInstance.set({\n                offsetX: mouseEvent.pageX,\n                offsetY: mouseEvent.pageY,\n            });\n            Entry.GlobalSvg.commentPosition(this.dragInstance);\n        }\n    }\n\n    mouseUp(e) {\n        e.stopPropagation();\n        if (this.longPressTimer) {\n            clearTimeout(this.longPressTimer);\n            this.longPressTimer = null;\n        }\n\n        if (!this.isEditing && this.isOpened && this.dragMode === Entry.DRAG_MODE_MOUSEDOWN) {\n            this.renderTextArea();\n        } else if (this.dragMode === Entry.DRAG_MODE_DRAG) {\n            this.destroyTextArea();\n            Entry.do('moveComment', this);\n            if (this.connectableBlockView) {\n                Entry.do('connectComment', this.toJSON(), this.connectableBlockView.block).isPass(\n                    true,\n                    true\n                );\n                this.removeSelected();\n            }\n        }\n        if (this.board) {\n            this.board.set({ dragBlock: null });\n            delete this.board.workingEvent;\n        }\n\n        this.removeMoveSetting(this.mouseMove, this.mouseUp);\n    }\n\n    removeMoveSetting(mouseMove, mouseUp) {\n        const dragMode = this.dragMode;\n        this.dragMode = Entry.DRAG_MODE_NONE;\n        this.board.set({ dragBlock: null });\n        delete this.connectableBlocks;\n        this.set({ visible: true });\n        this.setPosition();\n        this.removeDomEvent(mouseMove, mouseUp);\n        const gs = Entry.GlobalSvg;\n        const gsRet = gs.terminateDrag(this);\n        if (gsRet === gs.REMOVE && dragMode === Entry.DRAG_MODE_DRAG) {\n            Entry.do('removeComment', this).isPass(true, true);\n        }\n        Entry.GlobalSvg.remove();\n        delete this.mouseDownCoordinate;\n        delete this.dragInstance;\n    }\n\n    addControl() {\n        const bindEvent = (dom, func) => {\n            dom.addEventListener('mousedown', func);\n            dom.addEventListener('touchstart', func, false);\n        };\n        bindEvent(this._contentGroup, this.mouseDown);\n        bindEvent(this._title, this.mouseDown);\n        bindEvent(this._titleGroup, this.mouseDown);\n        bindEvent(this._resizeArea, this.resizeMouseDown);\n        bindEvent(this._toggleArea, this.toggleMouseDown);\n    }\n\n    updateOpacity() {\n        this.visible\n            ? Entry.Utils.removeClass(this.svgGroup, 'invisible')\n            : Entry.Utils.addClass(this.svgGroup, 'invisible');\n    }\n\n    isReadOnly() {\n        return this.readOnly;\n    }\n\n    getBoard() {\n        return this.board;\n    }\n\n    getAbsoluteCoordinate(dragMode = this.dragMode) {\n        const scale = this.scale;\n        let pos = null;\n        let parentX = 0;\n        let parentY = 0;\n        let x = this.moveX || this.x;\n        let y = this.moveY || this.y;\n        if (this.mouseDownCoordinate) {\n            parentX = this.mouseDownCoordinate.parentX;\n            parentY = this.mouseDownCoordinate.parentY;\n        }\n        if (this.blockView && dragMode !== Entry.DRAG_MODE_DRAG) {\n            x += this.blockView.getAbsoluteCoordinate().x;\n            y += this.blockView.getAbsoluteCoordinate().y;\n        }\n        pos = {\n            x,\n            y,\n            scaleX: x + parentX / scale,\n            scaleY: y + parentY / scale,\n        };\n        return pos;\n    }\n\n    renderTextArea() {\n        this.isEditing = true;\n        const { top, left } = this._comment.getBoundingClientRect();\n        const scrollTop = document.documentElement.scrollTop;\n        this.event = Entry.disposeEvent.attach(this, () => {\n            this._textPath.textContent = this.value;\n            this.destroyTextArea();\n        });\n        this.textArea = Entry.Dom('textarea', {\n            class: 'entry-widget-textarea',\n            parent: $('body'),\n        });\n        this.bindDomEventTextArea();\n        this.textArea.val(this.value);\n        this.textArea.css({\n            left: left - (1 - this.scale) * 0.2 + 2,\n            top: this.titleHeight * this.scale + top + 1 + scrollTop,\n            'font-size': `${this.fontSize}px`,\n            width: (this.width - 16) * this.scale,\n            height: (this.height - this.titleHeight - 10) * this.scale,\n            border: `${this.scale}px solid transparent`,\n            'border-radius': `0 0 ${4 * this.scale}px ${4 * this.scale}px`,\n            padding: `${2 * this.scale}px ${4 * this.scale}px`,\n        });\n        const length = this.value.length;\n        this.textArea.focus &&\n            this.textArea.focus() &&\n            this.textArea[0].setSelectionRange(length, length);\n    }\n\n    bindDomEventTextArea() {\n        this.textArea.on('mousedown', (e) => {\n            e.stopPropagation();\n        });\n        const exitKeys = [13, 27];\n        this.textArea.on('keypress', (e) => {\n            if (_.includes(exitKeys, e.keyCode || e.which)) {\n                e.preventDefault();\n            }\n        });\n        this.textArea.on('keyup', (e) => {\n            if (_.includes(exitKeys, e.keyCode || e.which)) {\n                this.destroyTextArea();\n                this.isEditing = false;\n            }\n        });\n        this.textArea.one('blur', () => {\n            this.destroyTextArea();\n            this.isEditing = false;\n        });\n    }\n\n    destroyTextArea() {\n        this.isEditing = false;\n\n        this.event && this.event.destroy();\n        delete this.event;\n\n        if (this.textArea) {\n            this.textArea.remove();\n            const value = this.textArea.val();\n            if (this.value !== value) {\n                Entry.do('writeComment', this, value);\n            }\n            delete this.textArea;\n        }\n\n        Entry.Utils.blur();\n    }\n\n    writeComment(value) {\n        this.set({ value });\n    }\n\n    setValue() {\n        this._textPath.textContent = this.value;\n        this._titleTextPath.textContent = this.value;\n    }\n\n    resizeMouseDown(e) {\n        e.stopPropagation();\n        e.preventDefault();\n        if (Entry.documentMousedown) {\n            Entry.documentMousedown.notify(e);\n        }\n\n        if ((e.button === 0 || e.type === 'touchstart') && !this.board.readOnly) {\n            this.setDragInstance(e);\n            this.dragMode = Entry.DRAG_MODE_MOUSEDOWN;\n            this.bindDomEvent(this.resizeMouseMove, this.resizeMouseUp);\n        } else if (Entry.Utils.isRightButton(e)) {\n            this.rightClick(e);\n        }\n    }\n\n    resizeMouseMove(e) {\n        e.stopPropagation();\n\n        const mouseEvent = Entry.Utils.convertMouseEvent(e);\n        if (\n            this.dragMode === Entry.DRAG_MODE_DRAG ||\n            this.getMouseMoveDiff(mouseEvent) > Entry.BlockView.DRAG_RADIUS\n        ) {\n            if (this.dragMode !== Entry.DRAG_MODE_DRAG) {\n                this.dragMode = Entry.DRAG_MODE_DRAG;\n            }\n            this.resize(\n                (mouseEvent.pageX - this.dragInstance.offsetX) / this.scale,\n                (mouseEvent.pageY - this.dragInstance.offsetY) / this.scale\n            );\n\n            this.dragInstance.set({\n                offsetX: mouseEvent.pageX,\n                offsetY: mouseEvent.pageY,\n            });\n        }\n    }\n\n    resizeMouseUp(e) {\n        e.stopPropagation();\n\n        this.set({\n            width: Number(this._comment.getAttribute('width')),\n            height: Number(this._comment.getAttribute('height')),\n        });\n\n        this.removeMoveSetting(this.resizeMouseMove, this.resizeMouseUp);\n    }\n\n    toggleMouseDown(e) {\n        e.stopPropagation();\n        e.preventDefault();\n        if (Entry.documentMousedown) {\n            Entry.documentMousedown.notify(e);\n        }\n\n        if ((e.button === 0 || e.type === 'touchstart') && !this.board.readOnly) {\n            this.setDragInstance(e);\n            this.dragMode = Entry.DRAG_MODE_MOUSEDOWN;\n            this.bindDomEvent(this.mouseMove, this.toggleMouseUp);\n        } else if (Entry.Utils.isRightButton(e)) {\n            this.rightClick(e);\n        }\n    }\n\n    toggleMouseUp(e) {\n        e.stopPropagation();\n\n        if (this.dragMode === Entry.DRAG_MODE_MOUSEDOWN) {\n            Entry.do('toggleComment', this);\n        } else {\n            Entry.do('moveComment', this);\n        }\n        this.removeMoveSetting(this.mouseMove, this.toggleMouseUp);\n    }\n\n    toggleContent() {\n        const path = `${Entry.mediaFilePath}block_icon/comment/`;\n        let fileName;\n        if (this.isOpened) {\n            Entry.Utils.removeClass(this._contentGroup, 'invisible');\n            Entry.Utils.addClass(this._titleText, 'invisible');\n            Entry.Utils.removeClass(this._titleGroup, 'invisible');\n            fileName = 'toggle_open_arrow.svg';\n        } else {\n            if (this._block) {\n                Entry.Utils.addClass(this._titleGroup, 'invisible');\n            }\n            Entry.Utils.addClass(this._contentGroup, 'invisible');\n            Entry.Utils.removeClass(this._titleText, 'invisible');\n            fileName = 'toggle_close_arrow.svg';\n            this.destroyTextArea();\n        }\n        this._toggleArrow.attr({\n            href: path + fileName,\n        });\n    }\n\n    setThread(thread) {\n        this._thread = thread;\n    }\n\n    getThread() {\n        let thread;\n        if (this.block) {\n            thread = this.block.getThread();\n        } else {\n            thread = this.thread;\n        }\n        return thread;\n    }\n\n    copy() {\n        const cloned = this.toJSON(true);\n        const { x, y } = this.getAbsoluteCoordinate();\n        cloned.x = x + 15;\n        cloned.y = y + 15;\n        cloned.id = Entry.Utils.generateId();\n        cloned.type = 'comment';\n\n        return cloned;\n    }\n\n    copyToClipboard() {\n        Entry.clipboard = this.copy();\n    }\n\n    connectToBlock(block) {\n        const data = this.toJSON();\n        const board = this.board;\n        delete data.x;\n        delete data.y;\n        delete data.visible;\n        this.destroy();\n        block.connectComment(new Entry.Comment(data, board, block));\n    }\n\n    separateFromBlock() {\n        const data = this.toJSON();\n        const { x, y } = this.getAbsoluteCoordinate();\n        const board = this.board;\n        data.x = x;\n        data.y = y;\n        this.destroy();\n        const comment = new Entry.Comment(data, board);\n        this.board.code.createThread([comment], 0);\n    }\n\n    destroy() {\n        if (this.board) {\n            this.destroyView();\n            this._destroyObservers();\n            this.code.unregisterBlock(this);\n        }\n        if (this.block) {\n            this.block.disconnectComment();\n        } else {\n            this.code.destroyThread(this.thread);\n        }\n    }\n\n    destroyView() {\n        this.removeControl();\n        this.svgGroup && this.svgGroup.remove();\n        delete this.svgGroup;\n    }\n\n    getBlocksInThreads(threads) {\n        let blockMap = [];\n        for (const thread of threads) {\n            const blocks = thread.getBlocks();\n            for (const block of blocks) {\n                let blocksInStatement = [];\n                if (block.statements) {\n                    blocksInStatement = this.getBlocksInThreads(block.statements);\n                }\n                blockMap = [block, ...blocksInStatement, ...blockMap];\n            }\n        }\n        return blockMap;\n    }\n\n    generateCommentableBlocks() {\n        this.connectableBlocks = [];\n        this.connectableBlockCoordinate = null;\n        if (this.block) {\n            return;\n        }\n\n        const threads = (this.code && this.code.getThreads()) || [];\n        const blockMap = this.getBlocksInThreads(threads);\n        for (const index in blockMap) {\n            const block = blockMap[index];\n            if (block instanceof Entry.Block && !block.comment && block.isCommentable()) {\n                const coordinate = block.view.getAbsoluteCoordinate();\n                const { width, height, topFieldHeight } = block.view;\n                this.connectableBlocks.push({\n                    id: block.id,\n                    x1: coordinate.scaleX,\n                    y1: coordinate.scaleY,\n                    x2: coordinate.scaleX + width,\n                    y2: coordinate.scaleY + (topFieldHeight || height),\n                });\n            }\n        }\n    }\n\n    checkConnectableBlock() {\n        if (this.block) {\n            return;\n        }\n        if (\n            this.connectableBlockCoordinate &&\n            this.isOnConnectableBlock(this.connectableBlockCoordinate)\n        ) {\n            return;\n        }\n        this.removeSelected();\n        for (const coordinate of this.connectableBlocks) {\n            if (this.isOnConnectableBlock(coordinate)) {\n                this.connectableBlockView = this.code.findById(coordinate.id).view;\n                this.board.setSelectedBlock(this.connectableBlockView);\n                this.connectableBlockCoordinate = coordinate;\n                return;\n            }\n        }\n    }\n\n    removeSelected() {\n        if (this.connectableBlockView) {\n            this.connectableBlockView.removeSelected();\n            this.connectableBlockView = null;\n        }\n        this.connectableBlockCoordinate = null;\n    }\n\n    isOnConnectableBlock(coordinate) {\n        const { x1, y1, x2, y2 } = coordinate;\n        const { moveX: x, moveY: y } = this;\n        return x1 <= x && x < x2 && y1 <= y && y < y2;\n    }\n\n    isInOrigin() {\n        return false;\n    }\n\n    reDraw() {}\n\n    _destroyObservers() {\n        const observers = this._observers;\n        while (observers.length) {\n            observers.pop().destroy();\n        }\n    }\n\n    removeControl() {\n        const destroyEvent = (dom, func) => {\n            dom.removeEventListener('mousedown', func);\n            dom.removeEventListener('ontouchstart', func);\n        };\n        destroyEvent(this._contentGroup, this.mouseDown);\n        destroyEvent(this._title, this.mouseDown);\n        destroyEvent(this._resizeArea, this.resizeMouseDown);\n        destroyEvent(this._toggleArea, this.toggleMouseDown);\n    }\n\n    isDeletable() {\n        return this.deletable;\n    }\n\n    getCode() {\n        return this.code;\n    }\n\n    toJSON() {\n        const json = this._toJSON();\n        json.type = 'comment';\n        delete json.parentWidth;\n        delete json.parentHeight;\n        delete json.moveX;\n        delete json.moveY;\n        return json;\n    }\n};\n"
  },
  {
    "path": "src/playground/connection_ripple.js",
    "content": "'use strict';\n\nEntry.ConnectionRipple = {};\n\n(function(cr) {\n    cr.createDom = function(blockView) {\n        if (this.svgDom) return;\n\n        var svgGroup = blockView.getBoard().svgGroup;\n        this._ripple = svgGroup.elem('circle', {\n            cx: 0,\n            cy: 0,\n            r: 0,\n            stroke: '#888',\n            'stroke-width': 10,\n        });\n    };\n\n    cr.setView = function(blockView) {\n        if (!this._ripple) this.createDom(blockView);\n        var ripple = this._ripple;\n        var svgGroup = blockView.getBoard().svgGroup;\n        ripple.remove();\n\n        var pos = blockView.getAbsoluteCoordinate();\n        ripple.attr({ cx: pos.scaleX, cy: pos.scaleY });\n\n        svgGroup.appendChild(ripple);\n        ripple._startTime = new Date();\n        return this;\n    };\n\n    cr.dispose = function() {\n        var that = this;\n        var ripple = this._ripple;\n        var ms = new Date() - ripple._startTime;\n        var percent = ms / 150;\n        if (percent > 1) ripple.remove();\n        else {\n            ripple.attr({\n                r: percent * 25,\n                opacity: 1 - percent,\n            });\n            window.setTimeout(function() {\n                that.dispose();\n            }, 10);\n        }\n    };\n})(Entry.ConnectionRipple);\n"
  },
  {
    "path": "src/playground/executors.js",
    "content": "/*\n *\n */\n'use strict';\n\nclass Executor {\n    constructor(block, entity, code) {\n        this.scope = new Entry.Scope(block, this);\n        this.isUpdateTime = 0;\n        this.entity = entity;\n        this.code = code;\n        this._callStack = [];\n        this.register = {};\n        this.paused = false;\n        this.parentExecutor = null;\n        this.valueMap = {};\n        this.valueState = {};\n        this.id = Entry.Utils.generateId();\n    }\n\n    execute(isFromOrigin) {\n        if (Entry.isTurbo && !this.isUpdateTime) {\n            this.isUpdateTime = performance.now();\n        }\n        if (this.isEnd()) {\n            return;\n        }\n\n        const executedBlocks = [];\n        const promises = [];\n        if (isFromOrigin) {\n            Entry.callStackLength = 0;\n        }\n\n        const entity = this.entity;\n        const isOffline = window.location.href.indexOf('file://') === 0;\n        while (true) {\n            let returnVal = null;\n            executedBlocks.push(this.scope.block);\n            try {\n                const schema = this.scope.block.getSchema();\n                if (schema.class === 'ai_learning' && isOffline) {\n                    throw new Entry.Utils.OfflineError();\n                }\n                if (schema && Entry.skeleton[schema.skeleton].executable) {\n                    Entry.dispatchEvent('blockExecute', this.scope.block && this.scope.block.view);\n                    returnVal = this.scope.run(entity);\n                    this.scope.key = Entry.generateHash();\n                }\n            } catch (e) {\n                if (e.name === 'AsyncError') {\n                    returnVal = Entry.STATIC.BREAK;\n                } else if (e.name === 'IncompatibleError') {\n                    Entry.Utils.stopProjectWithToast(this.scope, 'IncompatibleError', e);\n                } else if (e.name === 'OfflineError') {\n                    Entry.Utils.stopProjectWithToast(this.scope, 'OfflineError', e);\n                } else if (this.isFuncExecutor) {\n                    Entry.Utils.stopProjectWithToast(this.parentScope, undefined, e);\n                } else if (e.name === 'RangeError') {\n                    Entry.toast.alert(\n                        Lang.Workspace.RecursiveCallWarningTitle,\n                        Lang.Workspace.RecursiveCallWarningContent\n                    );\n                    Entry.Utils.stopProjectWithToast(this.scope, undefined, e);\n                } else {\n                    Entry.Utils.stopProjectWithToast(this.scope, undefined, e);\n                }\n            }\n\n            //executor can be ended after block function call\n            if (this.isEnd()) {\n                return executedBlocks;\n            }\n\n            if (returnVal instanceof Promise) {\n                promises.push(returnVal);\n                this.paused = true;\n                returnVal\n                    .then((returnVal) => {\n                        this.valueMap = {};\n                        this.valueState = {};\n                        this.paused = false;\n                        if (returnVal === Entry.STATIC.CONTINUE || returnVal === this.scope) {\n                            return;\n                        }\n                        if (this.scope.block && Entry.engine.isState('run')) {\n                            this.scope = new Entry.Scope(this.scope.block.getNextBlock(), this);\n                        }\n                        if (this.scope.block === null && this._callStack.length) {\n                            const oldScope = this.scope;\n                            this.scope = this._callStack.pop();\n                            if (this.scope.isLooped !== oldScope.isLooped) {\n                                this.isLooped = true;\n                            }\n                        }\n                    })\n                    .catch((e) => {\n                        this.paused = false;\n                        if (e.name === 'AsyncError') {\n                            returnVal = Entry.STATIC.BREAK;\n                        } else if (e.name === 'IncompatibleError') {\n                            Entry.Utils.stopProjectWithToast(this.scope, 'IncompatibleError', e);\n                        } else if (this.isFuncExecutor) {\n                            //function executor\n                            Entry.Utils.stopProjectWithToast(this.parentScope, undefined, e);\n                        } else if (e.name === 'RangeError') {\n                            Entry.toast.alert(\n                                Lang.Workspace.RecursiveCallWarningTitle,\n                                Lang.Workspace.RecursiveCallWarningContent\n                            );\n                            Entry.Utils.stopProjectWithToast(this.scope, undefined, e);\n                        } else {\n                            Entry.Utils.stopProjectWithToast(this.scope, undefined, e);\n                        }\n                    });\n                break;\n            } else if (\n                returnVal === undefined ||\n                returnVal === null ||\n                returnVal === Entry.STATIC.PASS\n            ) {\n                this.scope = new Entry.Scope(this.scope.block.getNextBlock(), this);\n                this.valueMap = {};\n                this.valueState = {};\n                if (this.scope.block === null) {\n                    if (this._callStack.length) {\n                        const oldScope = this.scope;\n                        this.scope = this._callStack.pop();\n                        if (this.scope.isLooped !== oldScope.isLooped) {\n                            this.isLooped = true;\n                            break;\n                        }\n                    } else {\n                        break;\n                    }\n                }\n            } else if (returnVal === Entry.STATIC.CONTINUE) {\n                this.valueMap = {};\n                this.valueState = {};\n            } else if (returnVal === this.scope) {\n                this.valueMap = {};\n                this.valueState = {};\n                break;\n            } else if (returnVal === Entry.STATIC.BREAK) {\n                break;\n            }\n        }\n        return { promises, blocks: executedBlocks };\n    }\n\n    checkExecutorError(error) {\n        if (error.name === 'AsyncError') {\n            return Entry.STATIC.BREAK;\n        } else if (this.isFuncExecutor) {\n            throw error;\n        } else {\n            Entry.Utils.stopProjectWithToast(this.scope, undefined, error);\n        }\n    }\n\n    checkExecutorResult(returnVal) {\n        if (returnVal === undefined || returnVal === null || returnVal === Entry.STATIC.PASS) {\n            this.scope = new Entry.Scope(this.scope.block.getNextBlock(), this);\n            this.valueMap = {};\n            this.valueState = {};\n            if (this.scope.block === null) {\n                if (this._callStack.length) {\n                    const oldScope = this.scope;\n                    this.scope = this._callStack.pop();\n                    if (this.scope.isLooped !== oldScope.isLooped) {\n                        this.isLooped = true;\n                        return true;\n                    }\n                } else {\n                    return true;\n                }\n            }\n        } else if (returnVal === Entry.STATIC.CONTINUE) {\n            this.valueMap = {};\n            this.valueState = {};\n        } else if (returnVal === this.scope) {\n            this.valueMap = {};\n            this.valueState = {};\n            return true;\n        } else if (returnVal === Entry.STATIC.BREAK) {\n            return true;\n        }\n    }\n\n    stepInto(thread) {\n        if (!(thread instanceof Entry.Thread)) {\n            console.error('Must step in to thread');\n        }\n\n        const block = thread.getFirstBlock();\n        if (!block) {\n            return Entry.STATIC.BREAK;\n        }\n\n        this._callStack.push(this.scope);\n\n        this.scope = new Entry.Scope(block, this);\n        return Entry.STATIC.CONTINUE;\n    }\n\n    break() {\n        if (this._callStack.length) {\n            this.scope = this._callStack.pop();\n        }\n        return Entry.STATIC.PASS;\n    }\n\n    breakLoop() {\n        if (this._callStack.length) {\n            this.scope = this._callStack.pop();\n        }\n        while (this._callStack.length) {\n            const schema = Entry.block[this.scope.block.type];\n            if (schema.class === 'repeat') {\n                break;\n            }\n            this.scope = this._callStack.pop();\n        }\n        return Entry.STATIC.PASS;\n    }\n\n    continueLoop() {\n        if (this._callStack.length) {\n            this.scope = this._callStack.pop();\n        } else {\n            return Entry.STATIC.PASS;\n        }\n        while (this._callStack.length) {\n            const schema = Entry.block[this.scope.block.type];\n            if (schema.class === 'repeat') {\n                break;\n            }\n            this.scope = this._callStack.pop();\n        }\n        return Entry.STATIC.BREAK;\n    }\n\n    end() {\n        Entry.dispatchEvent('blockExecuteEnd', this.scope.block && this.scope.block.view);\n        this.scope.block = null;\n    }\n\n    isPause() {\n        return this.paused;\n    }\n\n    isEnd() {\n        return this.scope.block === null;\n    }\n}\n\nEntry.Executor = Executor;\n"
  },
  {
    "path": "src/playground/executors2.js",
    "content": "/*\n *\n */\n'use strict';\nclass Executor {\n    constructor(block, entity, code) {\n        this.scope = new Entry.Scope(block, this);\n        this.isUpdateTime = 0;\n        this.entity = entity;\n        this.code = code;\n        this._callStack = [];\n        this.register = {};\n        this.paused = false;\n        this.parentExecutor = null;\n        this.valueMap = {};\n        this.valueState = {};\n        this.id = Entry.Utils.generateId();\n    }\n\n    execute(isFromOrigin) {\n        if (Entry.isTurbo && !this.isUpdateTime) {\n            this.isUpdateTime = performance.now();\n        }\n        if (this.isEnd()) {\n            return;\n        }\n\n        const executedBlocks = [];\n        if (isFromOrigin) {\n            Entry.callStackLength = 0;\n        }\n\n        const entity = this.entity;\n\n        while (true) {\n            let returnVal = null;\n            executedBlocks.push(this.scope.block);\n\n            try {\n                const schema = this.scope.block.getSchema();\n                if (schema && Entry.skeleton[schema.skeleton].executable) {\n                    Entry.dispatchEvent('blockExecute', this.scope.block && this.scope.block.view);\n                    returnVal = this.scope.run(entity);\n                    this.scope.key = Entry.generateHash();\n                }\n            } catch (e) {\n                returnVal = this.checkExecutorError(e);\n            }\n\n            //executor can be ended after block function call\n            if (this.isEnd()) {\n                return executedBlocks;\n            }\n\n            if (returnVal instanceof Promise) {\n                this.paused = true;\n                returnVal\n                    .then((result) => {\n                        this.checkExecutorResult(result);\n                        this.paused = false;\n                    })\n                    .catch((e) => {\n                        this.paused = false;\n                        this.checkExecutorError(e);\n                    });\n                break;\n            }\n            const isBreak = this.checkExecutorResult(returnVal);\n            if (isBreak) {\n                break;\n            }\n        }\n        return executedBlocks;\n    }\n\n    checkExecutorError(error) {\n        if (error.name === 'AsyncError') {\n            return Entry.STATIC.BREAK;\n        } else if (this.isFuncExecutor) {\n            throw error;\n        } else {\n            Entry.Utils.stopProjectWithToast(this.scope, undefined, error);\n        }\n    }\n\n    checkExecutorResult(returnVal) {\n        if (returnVal === undefined || returnVal === null || returnVal === Entry.STATIC.PASS) {\n            this.scope = new Entry.Scope(this.scope.block.getNextBlock(), this);\n            this.valueMap = {};\n            this.valueState = {};\n            if (this.scope.block === null) {\n                if (this._callStack.length) {\n                    const oldScope = this.scope;\n                    this.scope = this._callStack.pop();\n                    if (this.scope.isLooped !== oldScope.isLooped) {\n                        this.isLooped = true;\n                        return true;\n                    }\n                } else {\n                    return true;\n                }\n            }\n        } else if (returnVal === Entry.STATIC.CONTINUE) {\n            this.valueMap = {};\n            this.valueState = {};\n        } else if (returnVal === this.scope) {\n            this.valueMap = {};\n            this.valueState = {};\n            return true;\n        } else if (returnVal === Entry.STATIC.BREAK) {\n            return true;\n        }\n    }\n\n    stepInto(thread) {\n        if (!(thread instanceof Entry.Thread)) {\n            console.error('Must step in to thread');\n        }\n\n        const block = thread.getFirstBlock();\n        if (!block) {\n            return Entry.STATIC.BREAK;\n        }\n\n        this._callStack.push(this.scope);\n\n        this.scope = new Entry.Scope(block, this);\n        return Entry.STATIC.CONTINUE;\n    }\n\n    break() {\n        if (this._callStack.length) {\n            this.scope = this._callStack.pop();\n        }\n        return Entry.STATIC.PASS;\n    }\n\n    breakLoop() {\n        if (this._callStack.length) {\n            this.scope = this._callStack.pop();\n        }\n        while (this._callStack.length) {\n            const schema = Entry.block[this.scope.block.type];\n            if (schema.class === 'repeat') {\n                break;\n            }\n            this.scope = this._callStack.pop();\n        }\n        return Entry.STATIC.PASS;\n    }\n\n    end() {\n        Entry.dispatchEvent('blockExecuteEnd', this.scope.block && this.scope.block.view);\n        this.scope.block = null;\n    }\n\n    isPause() {\n        return this.paused;\n    }\n\n    isEnd() {\n        return this.scope.block === null;\n    }\n}\n\nEntry.Executor = Executor;\n"
  },
  {
    "path": "src/playground/extension/extension.js",
    "content": "/*\n *\n */\n\"use strict\";\n\n/*\n *\n */\nEntry.BlockExtension = function(content, blockView) {\n};\n\n(function(p) {\n})(Entry.BlockExtension.prototype);\n"
  },
  {
    "path": "src/playground/extension/guide.js",
    "content": "'use strict';\n\nconst TRANSFORM = 'transform';\n\nEntry.ExtGuide = class ExtGuide {\n    constructor(content, blockView, mode) {\n        this.blockView = blockView;\n        this.block = blockView.block;\n        this.model = content.model ? content.model : [];\n\n        this.render();\n    }\n\n    render() {\n        if (!this.model) {\n            return;\n        }\n\n        const board = this.blockView.getBoard();\n        this.svgGroup = this.blockView.svgGroup.elem('g', {\n            class: 'extension guideGroup',\n        });\n        this.blockView.guideSvgGroup = this.svgGroup;\n        $(this.svgGroup).bind('mousedown touchstart', (e) => {\n            e.stopPropagation && e.stopPropagation();\n            e.preventDefault && e.preventDefault();\n        });\n\n        const block = this.block;\n        const code = block.getCode();\n\n        //move blocks off the screen\n        //in order to prevent magneting for some reasons\n        this.model[0].x = -99999;\n        this.model[0].y = -99999;\n\n        const thread = code.createThread(this.model);\n        !thread.view && thread.createView(board);\n        const cloned = thread.getFirstBlock().view.clone();\n        cloned.removeAttribute(TRANSFORM);\n        this.svgGroup.appendChild(cloned);\n        this.updatePos();\n        this.block.getThread().view.setHasGuide(true);\n        thread.destroy(false);\n    }\n\n    updatePos() {\n        this.svgGroup.attr(TRANSFORM, this._getTransform());\n    }\n\n    _getTransform() {\n        return 'translate(0,%y)'.replace('%y', this.blockView.magnet.next.y);\n    }\n};\n"
  },
  {
    "path": "src/playground/extension/side_tag.js",
    "content": "/*\n *\n */\n'use strict';\n\n/*\n *\n */\nEntry.ExtSideTag = class ExtSideTag {\n    constructor(content, blockView, mode) {\n        this.blockView = blockView;\n        this.color = content.color ? content.color : '#EBC576';\n        this.text = content.text ? content.text : '';\n        this.height = content.height ? Number(content.height) : Number(content.count) * 31;\n\n        this.render();\n        this.updatePos();\n    }\n\n    render() {\n        this.svgGroup = this.blockView.svgGroup.elem('g');\n        $(this.svgGroup).bind('mousedown touchstart', (e) => {\n            if (e.stopPropagation) {\n                e.stopPropagation();\n            }\n            if (e.preventDefault) {\n                e.preventDefault();\n            }\n        });\n        this.path = this.svgGroup.elem('path').attr({\n            d: `m0,2 h-9 v${this.height - 4} h9`,\n            stroke: this.color,\n            fill: 'transparent',\n            'stroke-width': '3',\n        });\n        this.textElement = this.svgGroup.elem('text').attr({\n            style: 'white-space: pre;',\n            'font-size': '10px',\n            'font-family': EntryStatic.fontFamily || 'NanumGothic',\n            class: 'dragNone',\n            fill: '#000000',\n        });\n        const textArray = this.text.split('\\n');\n        this.tspans = textArray.map((t) => {\n            const tspan = this.textElement.elem('tspan').attr({\n                dy: '1.2em',\n                x: '0',\n                class: 'extension sideTagTspan',\n            });\n            tspan.textContent = t;\n            return tspan;\n        });\n    }\n\n    updatePos() {\n        const pointer = this.blockView.block.pointer();\n        this.positionX = -(pointer.length - 2) * 8;\n        this.svgGroup.attr('transform', `translate(${this.positionX},0)`);\n        this.textElement.attr({\n            y: this.height / 2 - 12 * (this.tspans.length - 1) - 2,\n        });\n        const bBox = this.textElement.getBoundingClientRect();\n\n        this.tspans.map((tspan) => {\n            tspan.attr({ x: -bBox.width - 14 });\n        });\n    }\n};\n"
  },
  {
    "path": "src/playground/field/angle.js",
    "content": "/*\n */\n'use strict';\n\nimport { Angle } from '@entrylabs/tool';\n\nEntry.FieldAngle = class FieldAngle extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index);\n\n        this.X_PADDING = 8;\n        this.TEXT_Y_PADDING = 4;\n\n        this._block = blockView.block;\n        this._blockView = blockView;\n        this.box = new Entry.BoxModel();\n        this.svgGroup = null;\n        this.position = content.position;\n        this._contents = content;\n        this._index = index;\n\n        const value = this.getValue();\n        this.setValue(FieldAngle._refineDegree(value !== undefined ? value : '90'));\n\n        this._CONTENT_HEIGHT = this.getContentHeight();\n        this.renderStart();\n    }\n\n    renderStart() {\n        if (this.svgGroup) {\n            $(this.svgGroup).remove();\n        }\n\n        this.svgGroup = this._blockView.contentSvgGroup.elem('g', {\n            class: 'entry-input-field',\n        });\n\n        this.textElement = this.svgGroup.elem('text', {\n            x: this.X_PADDING / 2,\n            y: this.TEXT_Y_PADDING,\n            'font-size': '11px',\n            'font-family': EntryStatic.fontFamily || 'NanumGothic',\n        });\n\n        this._setTextValue();\n\n        const width = this.getTextWidth();\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n\n        this._header = this.svgGroup.elem('rect', {\n            x: 0,\n            y: (_.result(this.position, 'y') || 0) - CONTENT_HEIGHT / 2,\n            rx: 3,\n            ry: 3,\n            width: width,\n            height: CONTENT_HEIGHT,\n            fill: '#fff',\n            'fill-opacity': 0.4,\n        });\n\n        this.svgGroup.appendChild(this.textElement);\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x: 0,\n            y: 0,\n            width: width,\n            height: CONTENT_HEIGHT,\n        });\n    }\n\n    renderOptions() {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-widget-angle',\n            parent: $('body'),\n        });\n\n        this.angleWidget = new Angle({\n            data: {\n                angle: this.getValue(),\n                positionDom: this.svgGroup,\n                onOutsideClick: (angle) => {\n                    if (this.angleWidget) {\n                        this._applyValue(FieldAngle._refineDegree(angle));\n                        this._setTextValue();\n                        this.destroyOption();\n                    }\n                },\n            },\n            container: this.optionGroup[0],\n        })\n            .on('click', (eventName, value) => {\n                let nextValue = 0;\n                switch (eventName) {\n                    case 'buttonPressed': {\n                        nextValue = this._getNextValue(value);\n                        break;\n                    }\n                    case 'backButtonPressed': {\n                        nextValue = this._getSubstringValue();\n                        break;\n                    }\n                }\n                this._applyValue(nextValue);\n            })\n            .on('change', (value) => {\n                this._applyValue(String(value));\n            });\n\n        this.optionGroup.focus();\n        this.optionGroup.select();\n        this.optionDomCreated();\n    }\n\n    /**\n     * 기존 값의 뒤에 새 값을 추가한다. 내부에서 모든 숫자는 문자열이다.\n     * 규칙은 아래와 같다.\n     *\n     * - 마이너스 입력은 현재 값이 0 인 경우만 가능\n     * - . 은 값에서 유일하게 하나만 허용한다.\n     * - 현재 값이 0 혹은 -0 인 경우 0은 입력할 수 없다. 다른 숫자는 입력할 수 있다.\n     *\n     * @param value 이번에 입력된 값\n     * @return {string} 규칙에 맞추어 정제된 값\n     * @private\n     */\n    _getNextValue(value) {\n        let returnValue = String(this.getValue());\n\n        if (!FieldAngle._isValidInputValue(value)) {\n            return returnValue;\n        }\n\n        switch (value) {\n            case '-':\n                if (returnValue === '0') {\n                    return '-';\n                }\n                return returnValue;\n            case '.':\n                if (/\\./.test(returnValue) || returnValue === '-') {\n                    return returnValue;\n                }\n                break;\n            case '0':\n                if (returnValue.startsWith('0') || returnValue.startsWith('-0')) {\n                    return returnValue;\n                }\n                break;\n            default:\n                if (returnValue === '0') {\n                    return value;\n                }\n                break;\n        }\n\n        returnValue += value;\n        return returnValue;\n    }\n\n    /**\n     * 현재 값 블록에서 마지막 숫자를 삭제한 값을 반환한다.\n     * 0 인 경우는 0 을 반환, - 인 경우는 0 을 반환한다.\n     * @returns {string} 마지막 위치가 삭제된 블록 값\n     * @private\n     */\n    _getSubstringValue() {\n        let returnValue = String(this.getValue());\n        if (returnValue.length === 1) {\n            return '0';\n        } else {\n            return returnValue.slice(0, returnValue.length - 1);\n        }\n    }\n\n    _applyValue(value) {\n        let rangedValue = value;\n        if (Entry.Utils.isNumber(value) && value.lastIndexOf('.') !== value.length - 1) {\n            rangedValue = String(rangedValue % 360);\n        }\n\n        this.setValue(rangedValue);\n        this.textElement.textContent = this.getValue();\n\n        if (this.angleWidget) {\n            this.angleWidget.data = {\n                angle: FieldAngle._refineDegree(value),\n            };\n        }\n\n        this.resize();\n    }\n\n    resize() {\n        const obj = { width: this.getTextWidth() };\n\n        this._header.attr(obj);\n        if (this.optionGroup) {\n            this.optionGroup.css(obj);\n        }\n\n        this.box.set(obj);\n        this._blockView.dAlignContent();\n    }\n\n    getTextWidth() {\n        if (!this.textElement) return this.X_PADDING;\n        return this.getTextBBox().width + this.X_PADDING;\n    }\n\n    getText() {\n        const value = this.getValue();\n        const reg = /&value/gm;\n        if (reg.test(value)) return value.replace(reg, '');\n        return value + '\\u00B0';\n    }\n\n    destroyOption() {\n        if (this.angleWidget) {\n            this.angleWidget.isShow && this.angleWidget.hide();\n            this.angleWidget.remove();\n            this.angleWidget = null;\n        }\n        if (this.optionGroup) {\n            this.optionGroup.remove();\n        }\n\n        super.destroyOption();\n    }\n\n    _setTextValue() {\n        this.textElement.textContent = this._convert(this.getText(), this.getValue());\n    }\n\n    static _refineDegree(value) {\n        const reg = /&value/gm;\n        if (reg.test(value)) return value;\n\n        let refinedDegree = String(value).match(/[\\d|\\-|.|\\+]+/g)[0] || 0;\n        if (refinedDegree > 360) {\n            refinedDegree %= 360;\n        } else if (refinedDegree < 0) {\n            refinedDegree = refinedDegree % 360;\n        }\n        refinedDegree = String(refinedDegree);\n\n        if (refinedDegree.lastIndexOf('.') === refinedDegree.length - 1) {\n            return refinedDegree.slice(0, refinedDegree.length - 1);\n        }\n\n        return refinedDegree;\n    }\n\n    static _isValidInputValue(value) {\n        return Entry.Utils.isNumber(value) || value === '-' || value === '.';\n    }\n};\n"
  },
  {
    "path": "src/playground/field/block.js",
    "content": "'use strict';\n\nEntry.FieldBlock = class FieldBlock extends Entry.Field {\n    constructor(content, blockView, index, mode, contentIndex) {\n        super(content, blockView, index, mode, contentIndex);\n        Entry.Model(this, false);\n        this._blockView = blockView;\n        this._block = blockView.block;\n        this._valueBlock = null;\n        this._oldPrimitiveValue = null;\n\n        this.box = new Entry.BoxModel();\n        this.changeEvent = new Entry.Event(this);\n\n        this._index = index;\n        this.contentIndex = contentIndex;\n        this._content = content;\n\n        this.acceptType = content.accept;\n        this.defaultType = content.defaultType;\n        this._restoreCurrent = content.restore;\n\n        this.view = this;\n\n        this.svgGroup = null;\n\n        this._position = content.position;\n\n        this.observe(this, '_updateBG', ['magneting'], false);\n\n        this.renderStart(this.getBoard(), mode);\n\n        this.schema = {\n            magneting: false,\n        };\n        this.calcHeight = this.calcWH;\n        this.doSeparate = this.separate;\n    }\n\n    getBoard() {\n        return _.result(this._blockView, 'getBoard');\n    }\n\n    getBlockType = () => 'field';\n\n    getBlockList(excludePrimitive, type) {\n        const { value } = this;\n        try {\n            return _.chain(value.getBlockList(excludePrimitive, type))\n                .flatten()\n                .compact()\n                .value();\n        } catch (e) {\n            console.log(e);\n            return [];\n        }\n    }\n\n    stringify(excludeData, isNew) {\n        try {\n            return JSON.stringify(this.toJSON(isNew, undefined, excludeData));\n        } catch (e) {\n            console.error(e);\n            return '';\n        }\n    }\n\n    toJSON(isNew, index, excludeData, option) {\n        try {\n            const { value } = this;\n            return [value.toJSON(isNew, excludeData, option)];\n        } catch (e) {\n            console.error(e);\n            return [];\n        }\n    }\n\n    renderStart(board, mode, renderMode, isReDraw) {\n        if (!this.svgGroup) {\n            this.svgGroup = this._blockView.contentSvgGroup.elem('g');\n        }\n\n        this.renderMode = !_.isUndefined(mode) ? mode : this._blockView.renderMode;\n\n        this.view = this;\n        this._nextGroup = this.svgGroup;\n\n        this.updateValueBlock(this.getValue());\n\n        const valueBlockView = this._valueBlock.view;\n        valueBlockView.renderByMode(this.renderMode, isReDraw);\n\n        if (this.getBoard().constructor !== Entry.Board) {\n            valueBlockView.removeControl();\n        }\n\n        this.box.observe(this._blockView, 'dAlignContent', ['width', 'height'], false);\n    }\n\n    align(x, y, animate = true) {\n        const svgGroup = this.svgGroup;\n        if (this._position) {\n            if (this._position.x) {\n                x = this._position.x;\n            }\n            if (this._position.y) {\n                y = this._position.y;\n            }\n        }\n\n        const blockView = _.result(this._valueBlock, 'view');\n\n        if (y === 0 && blockView) {\n            y = blockView.height * -0.5;\n        } else if (y > 0) {\n            y = y - 10;\n        }\n\n        if (!(x || y)) {\n            svgGroup.removeAttr('transform');\n        } else {\n            const transform = `translate(${x},${y})`;\n            if (animate) {\n                svgGroup.animate(\n                    {\n                        transform,\n                    },\n                    300,\n                    mina.easeinout\n                );\n            } else {\n                svgGroup.attr({\n                    transform,\n                });\n            }\n        }\n\n        x = Math.round(x * 100) / 100;\n        y = Math.round(y * 100) / 100;\n\n        const box = this.box;\n        if (box.x === x && box.y === y) {\n            return;\n        }\n\n        box.set({ x, y });\n    }\n\n    calcWH() {\n        const block = this._valueBlock;\n        const box = this.box;\n        const oldWidth = box.width;\n        const oldHeight = box.height;\n        let newWidth;\n        let newHeight;\n        const blockView = block && block.view;\n        if (blockView) {\n            newWidth = blockView.width;\n            newHeight = blockView.height;\n        } else {\n            newWidth = 15;\n            newHeight = 20;\n        }\n\n        if (newWidth !== oldWidth) {\n            box.set({ width: newWidth });\n        }\n\n        if (newHeight !== oldHeight) {\n            box.set({ height: newHeight });\n        }\n    }\n\n    destroy() {\n        _.result(this._valueBlock, 'destroyView');\n    }\n\n    inspectBlock() {\n        let blockType = null;\n        if (this._originBlock) {\n            blockType = this._originBlock.type;\n            delete this._originBlock;\n        } else if (this._content.blockType) {\n            blockType = this._content.blockType;\n        } else if (this._content.defaultType) {\n            blockType = this._content.defaultType;\n        } else {\n            switch (this.acceptType.toLowerCase()) {\n                case 'boolean':\n                    blockType = 'True';\n                    break;\n                case 'string':\n                    blockType = 'text';\n                    break;\n                case 'number':\n                    blockType = 'number';\n                    break;\n                case 'param':\n                default:\n                    blockType = 'function_field_label';\n                    break;\n            }\n        }\n\n        return this._createBlockByType(blockType);\n    }\n\n    _setValueBlock(block) {\n        if (this._restoreCurrent) {\n            this._originBlock = this._valueBlock;\n        }\n\n        block = block || this.inspectBlock();\n\n        this._valueBlock = block;\n        this.setValue(block);\n\n        block.setThread(this);\n        this.view.setParent(this);\n\n        return this._valueBlock;\n    }\n\n    getValueBlock() {\n        return this._valueBlock;\n    }\n\n    updateValueBlock(block) {\n        if (!(block instanceof Entry.Block)) {\n            block = undefined;\n        }\n\n        block = this._ensureBlock(block);\n\n        if (block && block === this._valueBlock) {\n            return this.calcWH();\n        }\n\n        this._destroyObservers();\n\n        const { view } = this._setValueBlock(block);\n        view.bindPrev(this);\n        this._blockView.alignContent();\n        this._posObserver = view.observe(this, 'updateValueBlock', ['x', 'y'], false);\n        this._sizeObserver = view.observe(this, 'calcWH', ['width', 'height']);\n    }\n\n    _destroyObservers() {\n        const _destroyFunc = _.partial(_.result, _, 'destroy');\n        _destroyFunc(this._sizeObserver);\n        _destroyFunc(this._posObserver);\n    }\n\n    getPrevBlock(block) {\n        if (this._valueBlock === block) {\n            return this;\n        } else {\n            return null;\n        }\n    }\n\n    getNextBlock() {\n        return null;\n    }\n\n    requestAbsoluteCoordinate(blockView) {\n        const board = this.getBoard();\n        const { scale = 1 } = board || {};\n        var blockView = this._blockView;\n        const contentPos = blockView.contentPos;\n        const pos = blockView.getAbsoluteCoordinate();\n        pos.x += (this.box.x + contentPos.x) * scale;\n        pos.y += this.box.y + contentPos.y;\n        return pos;\n    }\n\n    requestPartHeight(blockView, forAll) {\n        return blockView ? (blockView.magnet.next ? blockView.magnet.next.y : blockView.height) : 0;\n    }\n\n    getCount() {\n        return 0;\n    }\n\n    dominate() {\n        this._blockView.dominate();\n    }\n\n    isGlobal() {\n        return false;\n    }\n\n    separate(block) {\n        this.getCode().createThread([block]);\n        this.calcWH();\n        this.changeEvent.notify();\n    }\n\n    getCode() {\n        return this._block.thread.getCode();\n    }\n\n    cut(block) {\n        if (this._valueBlock === block) {\n            return [block];\n        }\n        return null;\n    }\n\n    replace(block) {\n        if (typeof block === 'string') {\n            block = this._createBlockByType(block);\n        }\n\n        const valueBlock = this._valueBlock;\n\n        if (Entry.block[valueBlock.type].isPrimitive) {\n            valueBlock.doNotSplice = true;\n            this._oldPrimitiveValue = valueBlock.getParam(0);\n            valueBlock.destroy();\n        } else if (this.acceptType === 'param') {\n            this._destroyObservers();\n            valueBlock.view._toGlobalCoordinate();\n            block.getTerminateOutputBlock().view._contents[1].replace(valueBlock);\n        } else {\n            this._destroyObservers();\n            valueBlock.view._toGlobalCoordinate();\n\n            Entry.do('separateBlockByCommand', valueBlock).isPass(true);\n            const board = this.getBoard();\n            const { scale = 1 } = board || {};\n            valueBlock.view.bumpAway(30 * scale, 150);\n        }\n        this.updateValueBlock(block);\n        block.view._toLocalCoordinate(this);\n        this.calcWH();\n        this.changeEvent.notify();\n    }\n\n    setParent(parent) {\n        this._parent = parent;\n    }\n\n    getParent() {\n        return this._parent;\n    }\n\n    get parent() {\n        return this._parent;\n    }\n\n    _createBlockByType(blockType) {\n        const board = this._blockView.getBoard();\n        const selected = _.result(board.workspace, 'selectedBlockView');\n        let isFromUserAction = false;\n        if (selected) {\n            isFromUserAction = !!_.result(selected, 'dragInstance');\n        }\n\n        const block = new Entry.Block(\n            {\n                type: blockType,\n                defaultType: this.defaultType,\n                params: [isFromUserAction ? undefined : this._oldPrimitiveValue],\n                copyable: blockType !== 'function_field_label',\n            },\n            this\n        );\n\n        block.createView(board, this.renderMode);\n\n        delete this._oldPrimitiveValue;\n        return block;\n    }\n\n    _updateBG() {\n        if (this.magneting) {\n            this._bg = this.svgGroup.elem('path', {\n                d: 'm 8,12 l -4,0 -2,-2 0,-3 3,0 1,-1 0,-12 -1,-1 -3,0 0,-3 2,-2 l 4,0 z',\n                fill: '#fff',\n                stroke: '#fff',\n                'fill-opacity': 0.7,\n                transform: 'translate(0,12)',\n            });\n        } else {\n            _.result(this._bg, 'remove');\n            delete this._bg;\n        }\n    }\n\n    getThread() {\n        return this;\n    }\n\n    getParentThread() {\n        return this._block.getThread();\n    }\n\n    pointer(pointer = []) {\n        return this._block.pointer([Entry.PARAM, this._index, ...pointer]);\n    }\n\n    targetPointer(pointer = []) {\n        const _pointer = this._block.pointer([Entry.PARAM, this._index, ...pointer]);\n        return _pointer;\n    }\n\n    isParamBlockType() {\n        return true;\n    }\n\n    //check block schema and view\n    _ensureBlock(block) {\n        if (!block) {\n            return;\n        }\n\n        if (block.constructor !== Entry.Block) {\n            block = new Entry.Block(block, this._block.thread);\n        }\n\n        //if block schema is not present\n        //and can't load schema, then destroy and return undefined\n        if (!block.getSchema()) {\n            this._destroyObservers();\n            block.destroy();\n            return;\n        }\n\n        block.defaultType = this.defaultType;\n\n        if (!block.view) {\n            block.setThread(this);\n            block.createView(this.getBoard(), this.renderMode);\n            this.view.setParent(this);\n        }\n\n        return block;\n    }\n\n    getFields() {\n        if (!this._blockView) {\n            return [];\n        }\n        return this._blockView.getFields();\n    }\n};\n"
  },
  {
    "path": "src/playground/field/color.js",
    "content": "/*\n */\n'use strict';\n\nimport { ColorPicker } from '@entrylabs/tool';\nimport Extension from '../../extensions/extension';\n\n/*\n *\n */\nEntry.FieldColor = class FieldColor extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index);\n        this._block = blockView.block;\n        this._blockView = blockView;\n        const board = blockView.getBoard();\n        this.box = new Entry.BoxModel();\n        this.svgGroup = null;\n        this._contents = content;\n        this._index = index;\n        this._position = content.position;\n        this._fontSize = content.fontSize || blockView.getSkeleton().fontSize || 10;\n        this._color =\n            content.color ||\n            this._block.getSchema().fontColor ||\n            blockView.getSkeleton().color ||\n            'black';\n        this.key = content.key;\n        this.setValue(this.getValue() || '#FF0000');\n        this._CONTENT_HEIGHT = this.getContentHeight();\n        this._CONTENT_WIDTH = this.getContentWidth();\n\n        this.renderStart();\n        this.dropper = Extension.getExtension('Dropper');\n    }\n\n    renderStart() {\n        if (this.svgGroup) {\n            $(this.svgGroup).remove();\n        }\n        const { contentSvgGroup, renderMode } = this._blockView;\n        this.svgGroup = contentSvgGroup.elem('g', {\n            class: 'entry-field-color',\n        });\n\n        let x, y, WIDTH, HEIGHT;\n\n        if (renderMode === Entry.BlockView.RENDER_MODE_TEXT) {\n            const rect = this.svgGroup.elem('rect', {\n                x: 0,\n                rx: 3,\n                ry: 3,\n                fill: '#fff',\n                'fill-opacity': 0.4,\n            });\n\n            this.textElement = this.svgGroup.elem('text').attr({\n                style: 'white-space: pre;',\n                'font-size': `${this._fontSize}px`,\n                'font-family': EntryStatic.fontFamily || 'NanumGothic',\n                class: 'dragNone',\n                fill: this._color,\n            });\n\n            this.textElement.textContent = this._convert(this.getValue(), this.getValue());\n            const bBox = this.textElement.getBoundingClientRect();\n            WIDTH = bBox.width + 12;\n            HEIGHT = bBox.height;\n            rect.attr({\n                y: -HEIGHT / 2,\n                width: WIDTH,\n                height: HEIGHT,\n            });\n            this.textElement.attr({\n                x: 6,\n                y: bBox.height * 0.25,\n            });\n        } else {\n            HEIGHT = this._CONTENT_HEIGHT;\n            WIDTH = this._CONTENT_WIDTH;\n            const position = this._position;\n            if (position) {\n                x = position.x || 0;\n                y = position.y || 0;\n            } else {\n                x = 0;\n                y = -HEIGHT / 2;\n            }\n\n            this._header = this.svgGroup.elem('rect', {\n                x,\n                y,\n                rx: 2,\n                ry: 2,\n                width: 20, //WIDTH,\n                height: 20, //HEIGHT,\n                fill: this.getValue(),\n                stroke: '#fff',\n                'stroke-width': '1',\n            });\n        }\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x,\n            y,\n            width: WIDTH,\n            height: HEIGHT,\n        });\n    }\n\n    _attachDisposeEvent(func) {\n        let action = func;\n        if (!action) {\n            action = (skipCommand) => {\n                // this.applyValue(this.colorPicker.getData('color'));\n                this.destroyOption(skipCommand);\n                this._selectBlockView();\n            };\n        }\n        this.disposeEvent = Entry.disposeEvent.attach(this, action);\n    }\n\n    spoidClick = _.debounce(() => {\n        this.isRunSpoid = true;\n        this.colorPicker.data = {\n            activeSpoid: true,\n        };\n        const { canvas } = Entry.stage.canvas || {};\n        this.dropper\n            .show({\n                target: canvas,\n            })\n            .once('pick', (color) => {\n                const data = { activeSpoid: false };\n                if (color) {\n                    this.applyValue(color);\n                    data.color = color;\n                }\n                this.colorPicker.setData(data);\n                delete this.isRunSpoid;\n            });\n    });\n\n    renderOptions() {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-color-picker',\n            parent: $('body'),\n        });\n        this.colorPicker = new ColorPicker({\n            data: {\n                eventTypes: ['mousedown', 'touchstart', 'wheel'],\n                color: this.getValue(),\n                canTransparent: false,\n                canSpoide: true,\n                positionDom: this.svgGroup,\n                // boundrayDom: this.boundrayDom,\n                onOutsideClick: (color) => {\n                    if (this.isRunSpoid) {\n                        return;\n                    }\n                    if (this.colorPicker) {\n                        this.colorPicker.hide();\n                        color && this.applyValue(color);\n                    }\n                    this._attachDisposeEvent();\n                },\n                onSpoidClick: this.spoidClick,\n            },\n            container: this.optionGroup[0],\n        }).on('change', (color) => {\n            if (color) {\n                this.colorPicker.setData({ color });\n                this.applyValue(color);\n            }\n        });\n\n        this.optionDomCreated();\n    }\n\n    applyValue(value) {\n        if (this.value == value) {\n            return;\n        }\n\n        this.setValue(value);\n\n        if (this._header) {\n            this._header.attr({ fill: value });\n        } else if (this.textElement) {\n            value = this.getValue();\n            this.textElement.textContent = this._convert(value, value);\n        }\n    }\n\n    destroyOption() {\n        if (this.colorPicker) {\n            this.colorPicker.isShow && this.colorPicker.hide();\n            this.colorPicker.remove();\n            this.colorPicker = null;\n        }\n        if (this.optionGroup) {\n            this.optionGroup.remove();\n        }\n        super.destroyOption();\n    }\n\n    getContentWidth() {\n        return 22;\n    }\n};\n"
  },
  {
    "path": "src/playground/field/dropdown.js",
    "content": "'use strict';\n\nimport { Dropdown } from '@entrylabs/tool';\n\nEntry.FieldDropdown = class FieldDropdown extends Entry.Field {\n    constructor(content, blockView, index, renderMode, i, isDynamic) {\n        super();\n        if (isDynamic) {\n            return;\n        }\n        this._block = blockView.block;\n        this._blockView = blockView;\n\n        this.box = new Entry.BoxModel();\n\n        this.svgGroup = null;\n\n        this._contents = content;\n        this._noArrow = content.noArrow;\n\n        const { bgColor, textColor } = content;\n        let { arrowColor } = content;\n        const { deletable, emphasized } = this._block;\n\n        if (deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN || emphasized) {\n            arrowColor = blockView._fillColor;\n        }\n\n        this._arrowColor = arrowColor;\n        this._textColor = textColor || '#FFFFFF';\n        this._bgColor = bgColor;\n        this._index = index;\n        this.setValue(this.getValue());\n\n        this._CONTENT_HEIGHT = this.getContentHeight(content.dropdownHeight);\n\n        this._font_size = this.getFontSize(content.fontSize);\n\n        this._ROUND = content.roundValue || 2;\n\n        this.renderStart();\n    }\n\n    renderStart() {\n        const blockView = this._blockView;\n        const that = this;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        const arrowInfo = this.getArrow();\n\n        if (!this.svgGroup) {\n            this.svgGroup = blockView.contentSvgGroup.elem('g', {\n                class: 'entry-field-dropdown',\n            });\n        }\n\n        if (!this._header) {\n            const rectInfo = {\n                height: CONTENT_HEIGHT,\n                y: -CONTENT_HEIGHT / 2,\n                rx: that._ROUND,\n                ry: that._ROUND,\n            };\n\n            if (this._bgColor) {\n                rectInfo.fill = this._bgColor;\n            } else {\n                rectInfo.fill = '#fff';\n                rectInfo['fill-opacity'] = 0.4;\n            }\n\n            this._header = this.svgGroup.elem('rect', rectInfo);\n        }\n\n        if (!this.textElement) {\n            this.textElement = this.svgGroup.elem('text', {\n                x: 5,\n                style: 'white-space: pre;',\n                fill: this._textColor,\n                'font-size': `${+that._font_size}px`,\n                'font-weight': 'bold',\n                'font-family': EntryStatic.fontFamily || 'NanumGothic',\n            });\n        }\n\n        if (!this._noArrow && !this._arrow) {\n            this._arrow = this.svgGroup.elem('path', {\n                d: `M 5.79 0.818\n                L 3.339 3.8\n                a 0.5 0.5 0 0 1 -0.772 0\n                L 0.114 0.818\n                A 0.5 0.5 0 0 1 0.5 0\n                h 4.904\n                a 0.5 0.5 0 0 1 0.387 0.818\n                z\n                `,\n                fill: arrowInfo.color,\n                stroke: arrowInfo.color,\n            });\n        }\n        let promise;\n        if (this instanceof Entry.FieldDropdownDynamic) {\n            promise = this._updateValue();\n            if (promise instanceof Promise) {\n                promise.then(() => {\n                    this._updateTextRender();\n                });\n            }\n        }\n        this._updateTextRender();\n        return promise;\n    }\n\n    resize() {\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const board = this._blockView.getBoard() || {};\n        const { scale = 1 } = board || {};\n        let width = this.textElement.getBoundingClientRect().width / scale + X_PADDING;\n        if (!this._noArrow) {\n            const arrowInfo = this.getArrow();\n            this._arrow.attr({\n                transform: `translate(${width - arrowInfo.width - 5},${-arrowInfo.height / 2})`,\n            });\n        } else {\n            width -= X_PADDING_SUBT;\n        }\n\n        this._header.attr({\n            width,\n        });\n\n        this.box.set({ width });\n        this._block.view?.dAlignContent();\n    }\n\n    _attachDisposeEvent(func) {\n        let action = func;\n        if (!action) {\n            action = (skipCommand) => {\n                this.destroyOption(skipCommand);\n                this._selectBlockView();\n            };\n        }\n        this.disposeEvent = Entry.disposeEvent.attach(this, action);\n    }\n\n    renderOptions() {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-widget-dropdown',\n            parent: $('body'),\n        });\n        const { options = [] } = this._contents;\n        const convertedOptions = options.map(([key, value]) => {\n            return [this._convert(key, value), value];\n        });\n        this.dropdownWidget = new Dropdown({\n            type: 'dropdownWidget',\n            data: {\n                eventTypes: ['mousedown', 'touchstart', 'wheel'],\n                items: convertedOptions,\n                positionDom: this.svgGroup,\n                onOutsideClick: () => {\n                    this.destroyOption();\n                },\n            },\n            container: this.optionGroup[0],\n        }).on('select', (item) => {\n            this.applyValue(item[1]);\n            this.destroyOption();\n            const { view = {} } = this._block.getThread();\n            if (view.reDraw) {\n                view.reDraw();\n            } else {\n                this._block.view.reDraw();\n            }\n        });\n        this.optionDomCreated();\n    }\n\n    applyValue(value) {\n        if (this.value != value) {\n            this.setValue(value);\n        }\n        this._setTextValue();\n        this.resize();\n    }\n\n    getTextByValue(value) {\n        const reg = /&value/gm;\n        if (reg.test(value)) {\n            return value.replace(reg, '');\n        }\n\n        if ((!value && typeof value !== 'number') || value === 'null') {\n            return Lang.Blocks.no_target;\n        }\n\n        const matched = _.find(this._contents.options, ([, cValue]) => {\n            return cValue == value;\n        });\n\n        if (matched) {\n            return _.head(matched);\n        }\n\n        //no match found\n        //check should return value as it is\n        if (this._shouldReturnValue(value)) {\n            return value;\n        }\n        return Lang.Blocks.no_target;\n    }\n\n    getContentHeight(height) {\n        return height || this._blockView.getSkeleton().dropdownHeight || 20;\n    }\n\n    getArrow() {\n        return {\n            color: this._arrowColor || this._blockView._schema.color,\n            points: '0,0 6.4,0 3.2,4.2',\n            height: 4.2,\n            width: 6.4,\n        };\n    }\n\n    _setTextValue() {\n        const textValue = this.getTextByValue(this.getValue());\n        const newValue = this._convert(textValue, this.getValue());\n        if (this.getTextValue() !== newValue) {\n            this.textElement.textContent = newValue;\n        }\n    }\n\n    _updateTextRender() {\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        const arrowInfo = this.getArrow();\n        this._setTextValue();\n\n        const bBox = this.getTextBBox();\n\n        this.textElement.attr({\n            y: bBox.height * 0.27,\n        });\n\n        let width = bBox.width + X_PADDING;\n\n        if (this._noArrow) {\n            width -= X_PADDING_SUBT;\n        }\n\n        this._header.attr({ width });\n\n        if (!this._noArrow) {\n            this._arrow.attr({\n                transform: `translate(${width - arrowInfo.width - 5},${-arrowInfo.height / 2})`,\n            });\n        }\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x: 0,\n            y: 0,\n            width,\n            height: CONTENT_HEIGHT,\n        });\n    }\n\n    getTextValue() {\n        return this.textElement.textContent;\n    }\n\n    destroyOption() {\n        if (this.dropdownWidget) {\n            this.dropdownWidget.isShow && this.dropdownWidget.hide();\n            this.dropdownWidget.remove();\n            this.dropdownWidget = null;\n        }\n        if (this.optionGroup) {\n            this.optionGroup.remove();\n        }\n        super.destroyOption();\n    }\n};\n"
  },
  {
    "path": "src/playground/field/dropdownDynamic.js",
    "content": "/*\n */\n'use strict';\nimport { Dropdown } from '@entrylabs/tool';\nimport _cloneDeep from 'lodash/cloneDeep';\n/*\n *\n */\nEntry.FieldDropdownDynamic = class FieldDropdownDynamic extends Entry.FieldDropdown {\n    constructor(content, blockView, index) {\n        super(content, blockView, index, null, null, true);\n        this._block = blockView.block;\n        this._blockView = blockView;\n\n        const box = new Entry.BoxModel();\n        this.box = box;\n\n        this.svgGroup = null;\n\n        this._contents = content;\n\n        if (content.needDeepCopy) {\n            this._contents = _cloneDeep(content);\n        }\n\n        this._index = index;\n\n        let { bgColor, textColor, arrowColor } = content;\n        if (\n            this._block.deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN ||\n            this._block.emphasized\n        ) {\n            arrowColor = blockView._fillColor;\n        }\n\n        this._arrowColor = arrowColor;\n        this._textColor = textColor || '#FFFFFF';\n        this._bgColor = bgColor;\n\n        const menuName = this._contents.menuName;\n        if (_.isFunction(menuName)) {\n            this._menuGenerator = menuName;\n        } else {\n            this._menuName = menuName;\n        }\n\n        this._CONTENT_HEIGHT = this.getContentHeight(content.dropdownHeight);\n        this._font_size = this.getFontSize(content.fontSize);\n\n        this._ROUND = content.roundValue || 3;\n        this.initialize(blockView);\n    }\n\n    initialize(blockView) {\n        const promise = this.renderStart(blockView);\n        if (\n            blockView &&\n            blockView.getBoard() &&\n            blockView.getBoard().workspace &&\n            blockView.getBoard().workspace.changeEvent\n        ) {\n            blockView.getBoard().workspace.changeEvent.attach(this, () => {\n                this._updateValue(true);\n            });\n        }\n        if (promise instanceof Promise) {\n            promise.then(() => {\n                blockView.alignContent(false);\n            });\n        }\n    }\n\n    _isBlockInBoardWhenFunctionEdit() {\n        const view = this._block.getView() || { _board: {} };\n        return view._board.suffix === 'board' && Entry.Func.isEdit;\n    }\n\n    getTextByValue(value) {\n        if (this._isBlockInBoardWhenFunctionEdit()) {\n            return this.textElement.textContent;\n        }\n\n        return super.getTextByValue(value);\n    }\n\n    updateValue(reDraw) {\n        return this._updateValue(reDraw);\n    }\n\n    async _updateValue(reDraw) {\n        const object = this._block.getCode().object;\n        let options = [];\n        if (Entry.container) {\n            if (this._menuName) {\n                options = await Entry.container.getDropdownList(this._menuName, object);\n            } else {\n                options = await this._menuGenerator(this._block);\n                if (options.length === 0) {\n                    options = [[Lang.Blocks.no_target, 'null']];\n                }\n            }\n        }\n\n        this._contents.options = options;\n        this._updateOptions();\n\n        if (reDraw && this._menuName === 'variables' && !this._isBlockInBoardWhenFunctionEdit()) {\n            this.value = undefined;\n        }\n        this.applyValue(this.getOptionCheckedValue(), reDraw);\n    }\n\n    getTargetValue(key, useParent = false) {\n        if (!key) {\n            return;\n        }\n        const block = useParent ? this._block.thread._block : this._block;\n        const { _schema, params: values = [] } = block || {};\n        const { params = [] } = _schema || {};\n        const idx = params.findIndex(({ dropdownSync }) => dropdownSync === key);\n        return values[idx || 0];\n    }\n\n    getOptionCheckedValue() {\n        const { options = [], defaultValue } = this._contents;\n        let value = this.getValue();\n\n        if (this._blockView.isInBlockMenu || !value || value == 'null') {\n            value = options.length !== 0 && options[0] ? options[0][1] : null;\n        }\n        const matched = _.find(options, ([, cValue]) => cValue === value);\n        if (!matched && defaultValue) {\n            if (_.isFunction(defaultValue)) {\n                return defaultValue(value, options);\n            }\n            return defaultValue;\n        }\n        return value;\n    }\n\n    renderOptions() {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-widget-dropdown',\n            parent: $('body'),\n        });\n        const { options = [] } = this._contents;\n        const convertedOptions = options.map(([key, value]) => [this._convert(key, value), value]);\n        this.dropdownWidget = new Dropdown({\n            data: {\n                eventTypes: ['mousedown', 'touchstart', 'wheel'],\n                items: convertedOptions,\n                positionDom: this.svgGroup,\n                onOutsideClick: () => {\n                    this.destroyOption();\n                },\n            },\n            container: this.optionGroup[0],\n        }).on('select', (item) => {\n            this.applyValue(item[1]);\n            this.destroyOption();\n            const { view = {} } = this._block.getThread();\n            if (view.reDraw) {\n                view.reDraw();\n            } else {\n                this._block.view.reDraw();\n            }\n        });\n        this.optionDomCreated();\n    }\n};\n"
  },
  {
    "path": "src/playground/field/dropdownExtra.js",
    "content": "'use strict';\n\nimport { DropdownExtra } from '@entrylabs/tool';\n\nEntry.FieldDropdownExtra = class FieldDropdownExtra extends Entry.Field {\n    constructor(content, blockView, index, renderMode, i, isDynamic) {\n        super();\n        if (isDynamic) {\n            return;\n        }\n        this._block = blockView.block;\n        this._blockView = blockView;\n\n        this.box = new Entry.BoxModel();\n\n        this.svgGroup = null;\n\n        this._contents = content;\n        this._noArrow = content.noArrow;\n\n        const { bgColor, textColor } = content;\n        let { arrowColor } = content;\n        const { deletable, emphasized } = this._block;\n\n        if (deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN || emphasized) {\n            arrowColor = blockView._fillColor;\n        }\n\n        this._arrowColor = arrowColor;\n        this._textColor = textColor || '#FFFFFF';\n        this._bgColor = bgColor;\n        this._index = index;\n        this.setValue(this.getValue());\n\n        this._CONTENT_HEIGHT = this.getContentHeight(content.dropdownHeight);\n\n        this._font_size = this.getFontSize(content.fontSize);\n\n        this._ROUND = content.roundValue || 2;\n\n        this.renderStart();\n    }\n\n    renderStart() {\n        const blockView = this._blockView;\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const that = this;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        const arrowInfo = this.getArrow();\n\n        if (!this.svgGroup) {\n            this.svgGroup = blockView.contentSvgGroup.elem('g', {\n                class: 'entry-field-dropdown',\n            });\n        }\n\n        if (!this._header) {\n            const rectInfo = {\n                height: CONTENT_HEIGHT,\n                y: -CONTENT_HEIGHT / 2,\n                rx: that._ROUND,\n                ry: that._ROUND,\n            };\n\n            if (this._bgColor) {\n                rectInfo.fill = this._bgColor;\n            } else {\n                rectInfo.fill = '#fff';\n                rectInfo['fill-opacity'] = 0.4;\n            }\n\n            this._header = this.svgGroup.elem('rect', rectInfo);\n        }\n\n        if (!this.textElement) {\n            this.textElement = this.svgGroup.elem('text', {\n                x: 5,\n                style: 'white-space: pre;',\n                fill: this._textColor,\n                'font-size': `${+that._font_size}px`,\n                'font-weight': 'bold',\n                'font-family': EntryStatic.fontFamily || 'NanumGothic',\n            });\n        }\n\n        if (!this._noArrow && !this._arrow) {\n            this._arrow = this.svgGroup.elem('path', {\n                d: `M 5.79 0.818\n                L 3.339 3.8\n                a 0.5 0.5 0 0 1 -0.772 0\n                L 0.114 0.818\n                A 0.5 0.5 0 0 1 0.5 0\n                h 4.904\n                a 0.5 0.5 0 0 1 0.387 0.818\n                z\n                `,\n                fill: arrowInfo.color,\n                stroke: arrowInfo.color,\n            });\n        }\n\n        this._setTextValue();\n\n        const bBox = this.getTextBBox();\n\n        this.textElement.attr({\n            y: bBox.height * 0.27,\n        });\n\n        let width = bBox.width + X_PADDING;\n\n        if (this._noArrow) {\n            width -= X_PADDING_SUBT;\n        }\n\n        this._header.attr({ width });\n\n        if (!this._noArrow) {\n            this._arrow.attr({\n                transform: `translate(${width - arrowInfo.width - 5},${-arrowInfo.height / 2})`,\n            });\n        }\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x: 0,\n            y: 0,\n            width,\n            height: CONTENT_HEIGHT,\n        });\n    }\n\n    resize() {\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const board = this._blockView.getBoard() || {};\n        const { scale = 1 } = board || {};\n        let width = this.textElement.getBoundingClientRect().width / scale + X_PADDING;\n        if (!this._noArrow) {\n            const arrowInfo = this.getArrow();\n            this._arrow.attr({\n                transform: `translate(${width - arrowInfo.width - 5},${-arrowInfo.height / 2})`,\n            });\n        } else {\n            width -= X_PADDING_SUBT;\n        }\n\n        this._header.attr({\n            width,\n        });\n\n        this.box.set({ width });\n        this._block.view.dAlignContent();\n    }\n\n    _attachDisposeEvent(func) {\n        let action = func;\n        if (!action) {\n            action = (skipCommand) => {\n                this.destroyOption(skipCommand);\n                this._selectBlockView();\n            };\n        }\n        this.disposeEvent = Entry.disposeEvent.attach(this, action);\n    }\n\n    renderOptions() {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-widget-dropdown-extra',\n            parent: $('body'),\n        });\n        const { options = [] } = this._contents;\n        const convertedOptions = options.map(([key, value]) => [this._convert(key, value), value]);\n        this.dropdownWidget = new DropdownExtra({\n            type: 'dropdownExtraWidget',\n            data: {\n                eventTypes: ['mousedown', 'touchstart', 'wheel'],\n                items: convertedOptions,\n                positionDom: this.svgGroup,\n                onOutsideClick: () => {\n                    this.destroyOption();\n                },\n            },\n            container: this.optionGroup[0],\n        }).on('select', (item) => {\n            this.applyValue(item[1]);\n            this.destroyOption();\n            const { view = {} } = this._block.getThread();\n            if (view.reDraw) {\n                view.reDraw();\n            } else {\n                this._block.view.reDraw();\n            }\n        });\n        this.optionDomCreated();\n    }\n\n    applyValue(value) {\n        if (this.value != value) {\n            this.setValue(value);\n        }\n        this._setTextValue();\n        this.resize();\n    }\n\n    getTextByValue(value) {\n        const reg = /&value/gm;\n        if (reg.test(value)) {\n            return value.replace(reg, '');\n        }\n\n        if ((!value && typeof value !== 'number') || value === 'null') {\n            return Lang.Blocks.no_target;\n        }\n\n        const matched = _.find(this._contents.options, ([, cValue]) => cValue == value);\n\n        if (matched) {\n            return _.head(matched);\n        }\n\n        //no match found\n        //check should return value as it is\n        if (this._shouldReturnValue(value)) {\n            return value;\n        }\n        return Lang.Blocks.no_target;\n    }\n\n    getContentHeight(height) {\n        return height || this._blockView.getSkeleton().dropdownHeight || 20;\n    }\n\n    getArrow() {\n        return {\n            color: this._arrowColor || this._blockView._schema.color,\n            points: '0,0 6.4,0 3.2,4.2',\n            height: 4.2,\n            width: 6.4,\n        };\n    }\n\n    _setTextValue() {\n        const textValue = this.getTextByValue(this.getValue());\n        const newValue = this._convert(textValue, this.getValue());\n        if (this.getTextValue() !== newValue) {\n            this.textElement.textContent = newValue;\n        }\n    }\n\n    getTextValue() {\n        return this.textElement.textContent;\n    }\n\n    destroyOption() {\n        if (this.dropdownWidget) {\n            this.dropdownWidget.isShow && this.dropdownWidget.hide();\n            this.dropdownWidget.remove();\n            this.dropdownWidget = null;\n        }\n        if (this.optionGroup) {\n            this.optionGroup.remove();\n        }\n        super.destroyOption();\n    }\n};\n"
  },
  {
    "path": "src/playground/field/field.js",
    "content": "/*\n *\n */\n'use strict';\n\nconst _cache = new Map();\nlet invisibleCanvas = undefined;\nlet invisibleContext = undefined;\n/*\n *\n */\nEntry.Field = class Field {\n    constructor(content, blockView, index) {\n        this.TEXT_LIMIT_LENGTH = 20;\n\n        this._blockView = blockView;\n        this._contents = content;\n        this._index = index;\n    }\n\n    destroy() {\n        const svgGroup = this.svgGroup;\n        if (svgGroup) {\n            svgGroup._isBinded = false;\n            $(svgGroup).off('.fieldBindEvent');\n        }\n        this.destroyOption(true);\n    }\n\n    command(forceCommand) {\n        const startValue = this._startValue;\n        if (\n            !this._blockView.isInBlockMenu &&\n            !_.isUndefined(startValue) &&\n            (forceCommand || startValue !== this.getValue())\n        ) {\n            Entry.do(\n                'setFieldValue',\n                this.pointer(),\n                this._nextValue || this.getValue(),\n                this._code\n            );\n            delete this._nextValue;\n            delete this._code;\n        }\n        delete this._startValue;\n    }\n\n    destroyOption(skipCommand, forceCommand) {\n        const _destroyFunc = _.partial(_.result, _, 'destroy');\n        const _removeFunc = _.partial(_.result, _, 'remove');\n\n        _destroyFunc(this.documentDownEvent);\n        delete this.documentDownEvent;\n\n        _destroyFunc(this.disposeEvent);\n        delete this.documentDownEvent;\n\n        _removeFunc(this.optionGroup);\n        delete this.optionGroup;\n\n        delete this._neighborFields;\n\n        _cache.clear();\n        invisibleCanvas = undefined;\n        invisibleContext = undefined;\n\n        this.isEditing() && Entry.Utils.blur();\n        this._isEditing = false;\n\n        skipCommand !== true && this.command(forceCommand);\n    }\n\n    _attachDisposeEvent(func) {\n        const defaultFunc = (skipCommand) => {\n            this.destroyOption(skipCommand);\n        };\n\n        func = func || defaultFunc;\n        this.disposeEvent = Entry.disposeEvent.attach(this, func);\n    }\n\n    align(x, y, animate = true) {\n        const svgGroup = this.svgGroup;\n        if (this._position) {\n            if (this._position.x) {\n                x = this._position.x;\n            }\n            if (this._position.y) {\n                y = this._position.y;\n            }\n        }\n\n        const transform = `translate(${x},${y})`;\n\n        if (animate) {\n            svgGroup.animate(\n                {\n                    transform,\n                },\n                300,\n                mina.easeinout\n            );\n        } else {\n            svgGroup.attr({\n                transform,\n            });\n        }\n\n        this.box.set({ x, y });\n    }\n\n    //get absolute position of field from parent board\n    getAbsolutePosFromBoard() {\n        const blockView = this._block.view;\n        const contentPos = blockView.getContentPos();\n        const absPos = blockView.getAbsoluteCoordinate();\n\n        return {\n            x: absPos.x + this.box.x + contentPos.x,\n            y: absPos.y + this.box.y + contentPos.y,\n        };\n    }\n\n    //get absolute position of field from parent document\n    getAbsolutePosFromDocument() {\n        const blockView = this._block.view;\n        const board = blockView.getBoard();\n        const { scale = 1 } = board || {};\n        const contentPos = blockView.getContentPos();\n        const absPos = blockView.getAbsoluteCoordinate();\n        const offset = blockView.getBoard().svgDom.offset();\n        return {\n            x: absPos.x + this.box.x + contentPos.x * scale + offset.left,\n            y: absPos.y + this.box.y + contentPos.y + offset.top - $(window).scrollTop(),\n        };\n    }\n\n    //get relative position of field from blockView origin\n    getRelativePos() {\n        const contentPos = this._block.view.getContentPos();\n        const { x, y } = this.box;\n\n        return {\n            x: x + contentPos.x,\n            y: y + contentPos.y,\n        };\n    }\n\n    truncate() {\n        const value = String(this._convert(this.getValue()));\n        const limit = this.TEXT_LIMIT_LENGTH;\n        let ret = value.substring(0, limit);\n        if (value.length > limit) {\n            ret += '...';\n        }\n        return ret;\n    }\n\n    appendSvgOptionGroup() {\n        return this._block.view.getBoard().svgGroup.elem('g');\n    }\n\n    getValue() {\n        let data = this._block.params[this._index];\n\n        const contents = this._contents;\n\n        if (contents && !_.isEmpty(contents.reference)) {\n            const reference = contents.reference.concat();\n            if (reference[0][0] === '%') {\n                data = this._block.params[parseInt(reference.shift().substr(1)) - 1];\n            }\n            if (!data) {\n                return data;\n            }\n\n            return data.getDataByPointer(reference);\n        } else {\n            return data;\n        }\n    }\n\n    setValue(value, reDraw) {\n        if (this.value === value) {\n            return;\n        }\n\n        this.value = value;\n\n        const contents = this._contents;\n\n        if (contents && !_.isEmpty(contents.reference)) {\n            const ref = contents.reference.concat();\n            const index = ref.pop();\n            let targetBlock = this._block.params[this._index];\n            if (ref.length && ref[0][0] === '%') {\n                targetBlock = this._block.params[parseInt(ref.shift().substr(1)) - 1];\n            }\n            if (ref.length) {\n                targetBlock = targetBlock.getDataByPointer(ref);\n            }\n            targetBlock.params[index] = value;\n        } else {\n            this._block.params[this._index] = value;\n        }\n\n        if (reDraw) {\n            this._blockView.reDraw();\n        }\n    }\n\n    _isEditable() {\n        if (Entry.ContextMenu.visible || this._blockView.getBoard().readOnly) {\n            return false;\n        }\n        const dragMode = this._block.view.dragMode;\n        if (dragMode == Entry.DRAG_MODE_DRAG) {\n            return false;\n        }\n        const blockView = this._block.view;\n        const board = blockView.getBoard();\n        if (board.disableMouseEvent === true) {\n            return false;\n        }\n\n        const selectedBlockView = board.workspace.selectedBlockView;\n\n        if (!selectedBlockView || board != selectedBlockView.getBoard()) {\n            return false;\n        }\n\n        if (selectedBlockView.isVerticalMove) {\n            return false;\n        }\n\n        const root = blockView.getSvgRoot();\n\n        return root == selectedBlockView.svgGroup || $(root).has($(blockView.svgGroup));\n    }\n\n    _selectBlockView() {\n        const blockView = this._block.view;\n        blockView.getBoard().setSelectedBlock(blockView);\n    }\n\n    _bindRenderOptions() {\n        if (this.svgGroup._isBinded) {\n            return;\n        }\n\n        this.svgGroup._isBinded = true;\n        $(this.svgGroup)\n            .off('mouseup.fieldBindEvent touchend.fieldBindEvent')\n            .on('mouseup.fieldBindEvent touchend.fieldBindEvent', (e) => {\n                if (this._isEditable()) {\n                    this._code = this.getCode();\n                    this.destroyOption();\n                    this._startValue = this.getValue();\n                    this.renderOptions();\n                    this._isEditing = true;\n                }\n            });\n    }\n\n    pointer(pointer = []) {\n        return this._block.pointer([Entry.PARAM, this._index, ...pointer]);\n    }\n\n    getFontSize(size) {\n        return size || this._blockView.getSkeleton().fontSize || 10;\n    }\n\n    getContentHeight() {\n        return 20;\n    }\n\n    _getRenderMode() {\n        const mode = this._blockView.renderMode;\n        return mode !== undefined ? mode : Entry.BlockView.RENDER_MODE_BLOCK;\n    }\n\n    _convert(key, value) {\n        value = value !== undefined ? value : this.getValue();\n        const reg = /&value/gm;\n        if (reg.test(value)) {\n            return value.replace(reg, '');\n        } else if (this._contents.converter) {\n            return this._contents.converter(key, value);\n        } else {\n            return key;\n        }\n    }\n\n    _updateOptions() {\n        const block = Entry.block[this._blockView.type];\n        if (!block) {\n            return;\n        }\n\n        const syntaxes = block.syntax;\n\n        for (const key in syntaxes) {\n            const syntax = syntaxes[key];\n            if (!syntax) {\n                continue;\n            }\n            if (syntax.length === 0) {\n                continue;\n            }\n\n            for (const i in syntax) {\n                const textParams = syntax[i].textParams;\n                if (!textParams) {\n                    continue;\n                }\n\n                textParams[this._index].options = this._contents.options;\n            }\n        }\n    }\n\n    _shouldReturnValue(value) {\n        const obj = this._block.getCode().object;\n        return value === '?' || !obj || obj.constructor !== Entry.EntryObject;\n    }\n\n    isEditing(value) {\n        return !!this._isEditing;\n    }\n\n    getDom(query) {\n        if (_.isEmpty(query)) {\n            return this.svgGroup;\n        }\n\n        query = [...query];\n\n        const key = query.shift();\n        if (key === 'option') {\n            return this.optionGroup;\n        }\n\n        //default return value\n        return this.svgGroup;\n    }\n\n    optionDomCreated() {\n        this._blockView.getBoard().workspace.widgetUpdateEvent.notify();\n    }\n\n    fixNextValue(value) {\n        this._nextValue = value;\n    }\n\n    getFieldRawType() {\n        if (this instanceof Entry.FieldTextInput) {\n            return 'textInput';\n        } else if (this instanceof Entry.FieldDropdown) {\n            return 'dropdown';\n        } else if (this instanceof Entry.FieldDropdownDynamic) {\n            return 'dropdownDynamic';\n        } else if (this instanceof Entry.FieldDropdownExtra) {\n            return 'dropdownExtra';\n        } else if (this instanceof Entry.FieldKeyboard) {\n            return 'keyboard';\n        } else if (this instanceof Entry.FieldDynamicText) {\n            return 'dynamicText';\n        }\n        // 마이크로비트 전용\n        else if (this instanceof Entry.FieldLed) {\n            return 'led';\n        } else if (this instanceof Entry.FieldLed2) {\n            return 'led2';\n        } else if (this instanceof Entry.FieldMusicScale) {\n            return 'musicScale';\n        }\n    }\n\n    getTextValueByValue(value) {\n        switch (this.getFieldRawType()) {\n            case 'keyboard':\n                return Entry.getKeyCodeMap()[value];\n            case 'dropdown':\n            case 'dropdownDynamic':\n                return _.chain(this._contents.options)\n                    .find(([, optionValue]) => optionValue === value)\n                    .head()\n                    .value();\n            case 'textInput':\n                return value;\n        }\n    }\n\n    getBoard() {\n        return _.result(this._blockView, 'getBoard');\n    }\n\n    getCode() {\n        return _.result(this.getBoard(), 'code');\n    }\n\n    getTextValue() {\n        return this.getValue();\n    }\n\n    getFontFamily() {\n        return window.loadFontFamily || EntryStatic.fontFamily || 'NanumGothic';\n    }\n\n    getIndex() {\n        return this._index;\n    }\n\n    getTextBBox() {\n        if (!invisibleContext) {\n            invisibleCanvas = Entry.Dom($('<canvas id=\"invisibleCanvas\"></canvas>'))[0];\n            invisibleContext = invisibleCanvas.getContext('2d');\n        }\n\n        const value = this.getTextValue();\n\n        if (!value) {\n            return { width: 0, height: 0 };\n        }\n\n        const fontSize = this._font_size || '';\n        const key = `${value}&&${fontSize}`;\n        let bBox = _cache.get(key);\n\n        if (bBox) {\n            return bBox;\n        }\n\n        const board = this._blockView.getBoard();\n        const { scale = 1 } = board;\n        invisibleContext.font = `${fontSize}px ${this.getFontFamily()}`;\n        const heightLetter = EntryStatic.heightLetter || 'M';\n        bBox = {\n            width: Math.round(invisibleContext.measureText(value).width * 100) / 100,\n            height: Math.round(invisibleContext.measureText(heightLetter).width * 100) / 100,\n        };\n\n        if (fontSize && window.fontLoaded && bBox.width && bBox.height) {\n            _cache.set(key, bBox);\n        }\n        return bBox;\n    }\n};\n"
  },
  {
    "path": "src/playground/field/image.js",
    "content": "Entry.FieldImage = class FieldImage extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index);\n        this._block = blockView.block;\n        this._blockView = blockView;\n        this._content = content;\n\n        const box = new Entry.BoxModel();\n        this.box = box;\n\n        if (Entry.Utils.isNumber(content.size)) {\n            this._width = content.size;\n            this._height = content.size;\n        } else {\n            const sizeSet = content.size || {};\n            this._width = sizeSet.width || 0;\n            this._height = sizeSet.height || 0;\n        }\n\n        this._highlightColor = content.highlightColor || '#F59900';\n        this._position = content.position;\n\n        this.svgGroup = null;\n        this._path = null;\n        this._imgElement = null;\n        this._index = index;\n\n        this.setValue(null);\n        this.renderStart();\n    }\n\n    renderStart() {\n        const img = this._content.img;\n\n        this._imgUrl =\n            this._block.deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN\n                ? img.replace('.png', '_un.png')\n                : img;\n\n        const options = {\n            href: this._imgUrl,\n            x: 0,\n            y: this._height * -0.5,\n            width: this._width,\n            height: this._height,\n        };\n\n        if (!this._imgElement) {\n            this.svgGroup = this._imgElement = this._blockView.contentSvgGroup.elem(\n                'image',\n                options\n            );\n        } else {\n            this._imgElement.attr(options);\n        }\n\n        this.box.set({\n            x: this._width,\n            y: 0,\n            width: this._width,\n            height: this._height,\n        });\n    }\n};\n"
  },
  {
    "path": "src/playground/field/indicator.js",
    "content": "Entry.FieldIndicator = class FieldIndicator extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index);\n        this._block = blockView.block;\n        this._blockView = blockView;\n\n        const box = new Entry.BoxModel();\n        this.box = box;\n\n        this._size = content.size;\n        if (content.img) {\n            if (this._block.deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN) {\n                this._imgUrl = content.img.replace('.png', '_un.png');\n            } else {\n                this._imgUrl = content.img;\n            }\n        } else if (content.color) {\n            this._color = content.color;\n        }\n\n        this._boxMultiplier = content.boxMultiplier || 2;\n        this._highlightColor = content.highlightColor || '#F59900';\n        this._position = content.position;\n\n        this._index = index;\n        this.svgGroup = null;\n        this._imgElement = null;\n        this.setValue(null);\n\n        this.renderStart();\n    }\n\n    renderStart() {\n        let options;\n        if (!this._imgElement) {\n            this.svgGroup = this._imgElement = this._blockView.contentSvgGroup.elem('image');\n        }\n\n        if (this._imgUrl) {\n            options = {\n                href: Entry.mediaFilePath + this._imgUrl,\n                x: this._position ? this._size * -1 : 0,\n                y: this._size * -1,\n                width: this._size * 2,\n                height: this._size * 2,\n            };\n            this._imgElement.attr(options);\n\n            if (this._block.emphasized && this._imgUrl.lastIndexOf('_un.png') === -1) {\n                this._imgUrl = this._imgUrl.replace('.png', '_un.png');\n            }\n        }\n\n        this.box.set({\n            width: this._size * this._boxMultiplier + (this._position ? -this._size : 0),\n            height: this._size * this._boxMultiplier,\n        });\n    }\n\n    enableHighlight() {\n        return;\n        const pathLen = this._path.getTotalLength();\n        const path = this._path;\n        this._path.attr({\n            stroke: this._highlightColor,\n            strokeWidth: 2,\n            'stroke-linecap': 'round',\n            'stroke-dasharray': `${pathLen} ${pathLen}`,\n            'stroke-dashoffset': pathLen,\n        });\n        setInterval(\n            () => {\n                path.attr({ 'stroke-dashoffset': pathLen }).animate(\n                    { 'stroke-dashoffset': 0 },\n                    300\n                );\n            },\n            1400,\n            mina.easeout\n        );\n        setTimeout(() => {\n            setInterval(\n                () => {\n                    path.animate({ 'stroke-dashoffset': -pathLen }, 300);\n                },\n                1400,\n                mina.easeout\n            );\n        }, 500);\n    }\n};\n"
  },
  {
    "path": "src/playground/field/keyboardInput.js",
    "content": "/*\n */\n'use strict';\n\nimport { Dropdown } from '@entrylabs/tool';\nimport EntryEvent from '@entrylabs/event';\n\nEntry.FieldKeyboard = class FieldDropdown extends Entry.Field {\n    constructor(content, blockView, index, renderMode, i, isDynamic) {\n        super();\n        if (isDynamic) {\n            return;\n        }\n        this._block = blockView.block;\n        this._blockView = blockView;\n\n        this.box = new Entry.BoxModel();\n\n        this.svgGroup = null;\n\n        this._contents = content;\n        this._noArrow = content.noArrow;\n\n        const { bgColor, textColor } = content;\n        let { arrowColor } = content;\n        const { deletable, emphasized } = this._block;\n\n        if (deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN || emphasized) {\n            arrowColor = blockView._fillColor;\n        }\n\n        this._arrowColor = arrowColor;\n        this._textColor = textColor || '#FFFFFF';\n        this._bgColor = bgColor;\n        this._index = index;\n        this.setValue(this.getValue());\n\n        this._CONTENT_HEIGHT = this.getContentHeight(content.dropdownHeight);\n\n        this._font_size = this.getFontSize(content.fontSize);\n\n        this._ROUND = content.roundValue || 2;\n\n        this.renderStart();\n    }\n\n    renderStart() {\n        const blockView = this._blockView;\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const that = this;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        const arrowInfo = this.getArrow();\n\n        if (!this.svgGroup) {\n            this.svgGroup = blockView.contentSvgGroup.elem('g', {\n                class: 'entry-field-dropdown',\n            });\n        }\n\n        if (!this._header) {\n            const rectInfo = {\n                height: CONTENT_HEIGHT,\n                y: -CONTENT_HEIGHT / 2,\n                rx: that._ROUND,\n                ry: that._ROUND,\n            };\n\n            if (this._bgColor) {\n                rectInfo.fill = this._bgColor;\n            } else {\n                rectInfo.fill = '#fff';\n                rectInfo['fill-opacity'] = 0.4;\n            }\n\n            this._header = this.svgGroup.elem('rect', rectInfo);\n        }\n\n        if (!this.textElement) {\n            this.textElement = this.svgGroup.elem('text', {\n                x: 5,\n                style: 'white-space: pre;',\n                fill: this._textColor,\n                'font-size': `${+that._font_size}px`,\n                'font-weight': 'bold',\n                'font-family': EntryStatic.fontFamily || 'NanumGothic',\n            });\n        }\n\n        if (!this._noArrow && !this._arrow) {\n            this._arrow = this.svgGroup.elem('path', {\n                d: `M 5.79 0.818\n                L 3.339 3.8\n                a 0.5 0.5 0 0 1 -0.772 0\n                L 0.114 0.818\n                A 0.5 0.5 0 0 1 0.5 0\n                h 4.904\n                a 0.5 0.5 0 0 1 0.387 0.818\n                z\n                `,\n                fill: arrowInfo.color,\n                stroke: arrowInfo.color,\n            });\n        }\n\n        if (this instanceof Entry.FieldDropdownDynamic) {\n            this._updateValue();\n        }\n\n        this._setTextValue();\n\n        const bBox = this.getTextBBox();\n\n        this.textElement.attr({\n            y: bBox.height * 0.27,\n        });\n\n        let width = bBox.width + X_PADDING;\n\n        if (this._noArrow) {\n            width -= X_PADDING_SUBT;\n        }\n\n        this._header.attr({ width });\n\n        if (!this._noArrow) {\n            this._arrow.attr({\n                transform: `translate(${width - arrowInfo.width - 5},${-arrowInfo.height / 2})`,\n            });\n        }\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x: 0,\n            y: 0,\n            width,\n            height: CONTENT_HEIGHT,\n        });\n\n        this.keyboardEvent = new EntryEvent(document);\n    }\n\n    resize() {\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const board = this._blockView.getBoard() || {};\n        const { scale = 1 } = board || {};\n        let width = this.textElement.getBoundingClientRect().width / scale + X_PADDING;\n        if (!this._noArrow) {\n            const arrowInfo = this.getArrow();\n            this._arrow.attr({\n                transform: `translate(${width - arrowInfo.width - 5},${-arrowInfo.height / 2})`,\n            });\n        } else {\n            width -= X_PADDING_SUBT;\n        }\n\n        this._header.attr({\n            width,\n        });\n\n        this.box.set({ width });\n        this._block.view.dAlignContent();\n    }\n\n    _attachDisposeEvent(func) {\n        let action = func;\n        if (!action) {\n            action = (skipCommand) => {\n                this.destroyOption(skipCommand);\n                this._selectBlockView();\n            };\n        }\n        this.disposeEvent = Entry.disposeEvent.attach(this, action);\n    }\n\n    renderOptions() {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-widget-dropdown',\n            parent: $('body'),\n        });\n        const { options = [] } = this._contents;\n        const convertedOptions = options.map(([key, value]) => [this._convert(key, value), value]);\n        this.dropdownWidget = new Dropdown({\n            data: {\n                eventTypes: ['mousedown', 'touchstart', 'wheel'],\n                items: convertedOptions,\n                positionDom: this.svgGroup,\n                onOutsideClick: () => {\n                    this.destroyOption();\n                },\n            },\n            container: this.optionGroup[0],\n        }).on('select', (item) => {\n            this.applyValue(item[1]);\n            this.destroyOption();\n            $(this._blockView.contentSvgGroup).trigger('optionChanged', {\n                block: this._block,\n                value: this.getValue(),\n            });\n        });\n        this.optionDomCreated();\n        this.keyboardEvent.on('keyup.keyboard', this.keyboardControl);\n    }\n\n    keyboardControl = (e) => {\n        e?.stopPropagation();\n        e?.preventDefault();\n        let value = Entry.Utils.inputToKeycode(e);\n        if (!value) {\n            return;\n        }\n\n        const text = Entry.getKeyCodeMap()[value];\n        if (text !== undefined) {\n            this.destroyOption();\n            this.applyValue(value, false, true);\n        }\n    };\n\n    applyValue(value, skipCommand, forceCommand) {\n        this.setValue(String(value));\n        this._setTextValue();\n        this.resize();\n        this.destroyOption(skipCommand, forceCommand);\n    }\n\n    getTextByValue(value) {\n        const reg = /&value/gm;\n        if (reg.test(value)) {\n            return value.replace(reg, '');\n        }\n\n        if ((!value && typeof value !== 'number') || value === 'null') {\n            return Lang.Blocks.no_target;\n        }\n\n        const matched = _.find(this._contents.options, ([, cValue]) => cValue == value);\n\n        if (matched) {\n            return _.head(matched);\n        }\n\n        //no match found\n        //check should return value as it is\n        if (this._shouldReturnValue(value)) {\n            return value;\n        }\n        return Lang.Blocks.no_target;\n    }\n\n    getContentHeight(height) {\n        return height || this._blockView.getSkeleton().dropdownHeight || 20;\n    }\n\n    getArrow() {\n        return {\n            color: this._arrowColor || this._blockView._schema.color,\n            points: '0,0 6.4,0 3.2,4.2',\n            height: 4.2,\n            width: 6.4,\n        };\n    }\n\n    _setTextValue() {\n        const textValue = this.getTextByValue(this.getValue());\n        const newValue = this._convert(textValue, this.getValue());\n        if (this.getTextValue() !== newValue) {\n            this.textElement.textContent = newValue;\n        }\n    }\n\n    getTextValue() {\n        return this.textElement.textContent;\n    }\n\n    destroyOption() {\n        if (this.keyboardEvent) {\n            this.keyboardEvent.off('keyboard');\n        }\n        if (this.dropdownWidget) {\n            this.dropdownWidget.isShow && this.dropdownWidget.hide();\n            this.dropdownWidget.remove();\n            this.dropdownWidget = null;\n        }\n        if (this.optionGroup) {\n            this.optionGroup.remove();\n        }\n        super.destroyOption();\n    }\n};\n"
  },
  {
    "path": "src/playground/field/led.js",
    "content": "/*\n */\n'use strict';\n\nimport { LedPicker } from '@entrylabs/tool';\n\n/*\n *\n */\nEntry.FieldLed = class FieldLed extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index);\n        this._block = blockView.block;\n        this._blockView = blockView;\n        const board = blockView.getBoard();\n        this.box = new Entry.BoxModel();\n        this.svgGroup = null;\n        this._contents = content;\n        this._index = index;\n        this._position = content.position;\n        this._fontSize = content.fontSize || blockView.getSkeleton().fontSize || 10;\n        this._color =\n            content.color ||\n            this._block.getSchema().fontColor ||\n            blockView.getSkeleton().color ||\n            'black';\n        this.key = content.key;\n        this.setValue(\n            this.getValue() || [\n                [0, 0, 0, 0, 0],\n                [0, 1, 0, 1, 0],\n                [0, 0, 0, 0, 0],\n                [1, 0, 0, 0, 1],\n                [0, 1, 1, 1, 0],\n            ]\n        );\n        /*\n\n        */\n        this._CONTENT_HEIGHT = 20;\n        this._CONTENT_WIDTH = this.getContentWidth();\n\n        this.renderStart();\n    }\n\n    renderLed() {\n        const ledStatus = this.getValue();\n        const ledDist = 3;\n        const ledOffset = 0.5;\n        const currentStatus = ledStatus.params || ledStatus;\n        currentStatus.map((leds, x_pos) => {\n            return leds.map((led, y_pos) => {\n                if (this._rect[`${x_pos}`][`${y_pos}`]) {\n                    this._rect[`${x_pos}`][`${y_pos}`].remove();\n                }\n\n                return (this._rect[`${x_pos}`][`${y_pos}`] = this.svgGroup.elem('rect', {\n                    x: y_pos * ledDist + 4,\n                    y: x_pos * ledDist - 8 + ledOffset,\n                    width: ledDist - ledOffset,\n                    height: ledDist - ledOffset,\n                    rx: 0.5,\n                    ry: 0.5,\n                    fill: currentStatus[x_pos][y_pos] ? '#ffffff' : '#00b6b1',\n                }));\n            });\n        });\n    }\n\n    renderStart() {\n        const blockView = this._blockView;\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const that = this;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        const arrowInfo = this.getArrow();\n\n        if (this.svgGroup) {\n            $(this.svgGroup).remove();\n        }\n        const { contentSvgGroup, renderMode } = this._blockView;\n        this.svgGroup = contentSvgGroup.elem('g', {\n            class: 'entry-field-microbit-led',\n        });\n\n        let x, y, WIDTH, HEIGHT;\n\n        HEIGHT = this._CONTENT_HEIGHT;\n        WIDTH = this._CONTENT_WIDTH + 10;\n        const position = this._position;\n        if (position) {\n            x = position.x || 0;\n            y = position.y || 0;\n        } else {\n            x = 0;\n            y = -HEIGHT / 2;\n        }\n        this._header = this.svgGroup.elem('rect', {\n            x,\n            y,\n            width: 35, //WIDTH,\n            height: 20, //HEIGHT,\n\n            rx: 2,\n            ry: 2,\n\n            fill: '#008380',\n        });\n\n        this._rect = [[], [], [], [], []];\n        this.renderLed();\n        this._arrow = this.svgGroup.elem('path', {\n            d: `M 30.79 -1.182\n            L 28.339 1.8\n            a 0.5 0.5 0 0 1 -0.772 0\n            L 25.114 -1.182\n            A 0.5 0.5 0 0 1 25.5 -2\n            h 4.904\n            a 0.5 0.5 0 0 1 0.387 0.818\n            z\n            `,\n            fill: arrowInfo.color,\n            stroke: arrowInfo.color,\n        });\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x,\n            y,\n            width: WIDTH,\n            height: HEIGHT,\n        });\n    }\n\n    getArrow() {\n        return {\n            color: '#ffffff',\n            points: '0,0 6.4,0 3.2,4.2',\n            height: 4.2,\n            width: 6.4,\n        };\n    }\n\n    _attachDisposeEvent(func) {\n        let action = func;\n        if (!action) {\n            action = (skipCommand) => {\n                this.destroyOption(skipCommand);\n                this._selectBlockView();\n            };\n        }\n        this.disposeEvent = Entry.disposeEvent.attach(this, action);\n    }\n\n    renderOptions() {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-field-microbit-led',\n            parent: $('body'),\n        });\n        this.ledPicker = new LedPicker({\n            data: {\n                eventTypes: ['mousedown', 'touchstart'],\n                ledStatus: this.getValue(),\n                canTransparent: false,\n                positionDom: this.svgGroup,\n                onOutsideClick: (ledMatrix) => {\n                    if (this.ledPicker) {\n                        this.ledPicker.hide();\n                        ledMatrix && this.applyValue(ledMatrix);\n                    }\n                    this._attachDisposeEvent();\n                },\n                withLevel: false,\n                maxBrightness: this._contents.maxBrightness,\n                defaultStatus: this._contents.defaultStatus,\n            },\n            container: this.optionGroup[0],\n        }).on('change', (value) => {\n            if (value) {\n                this.applyValue(value);\n            }\n        });\n\n        this.optionDomCreated();\n    }\n\n    applyValue(value) {\n        this.setValue(value);\n        this.renderLed();\n    }\n\n    destroyOption() {\n        if (this.ledPicker) {\n            this.ledPicker.isShow && this.ledPicker.hide();\n            this.ledPicker.remove();\n            this.ledPicker = null;\n        }\n        if (this.optionGroup) {\n            this.optionGroup.remove();\n        }\n        super.destroyOption();\n    }\n\n    getContentWidth() {\n        return 22;\n    }\n};\n"
  },
  {
    "path": "src/playground/field/led2.js",
    "content": "/*\n */\n'use strict';\n\nimport { LedPicker } from '@entrylabs/tool';\n\n/*\n *\n */\nconst DEFAULT_LED_SIZE = 5;\n\nEntry.FieldLed2 = class FieldLed2 extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index);\n        this.props = { content, blockView, index };\n        this._block = blockView.block;\n        this._blockView = blockView;\n        const board = blockView.getBoard();\n        this.box = new Entry.BoxModel();\n        this.svgGroup = null;\n        this._contents = content;\n        this._index = index;\n        this._position = content.position;\n        this._fontSize = content.fontSize || blockView.getSkeleton().fontSize || 10;\n        this._color =\n            content.color ||\n            this._block.getSchema().fontColor ||\n            blockView.getSkeleton().color ||\n            'black';\n        this.key = content.key;\n        this.setValue(\n            this.getValue() || [\n                [0, 0, 0, 0, 0],\n                [0, 9, 0, 9, 0],\n                [0, 0, 0, 0, 0],\n                [9, 0, 0, 0, 9],\n                [0, 9, 9, 9, 0],\n            ]\n        );\n        this.ledSize = this.getValue().length || DEFAULT_LED_SIZE;\n        /*\n\n        */\n        this._CONTENT_HEIGHT = 20;\n        this._CONTENT_WIDTH = this.getContentWidth();\n\n        this.renderStart();\n    }\n\n    renderLed() {\n        const ledStatus = this.getValue();\n        const ledDist = 3 * (DEFAULT_LED_SIZE / this.ledSize);\n        const ledOffset = 0.5 * (DEFAULT_LED_SIZE / this.ledSize);\n        const currentStatus = ledStatus.params || ledStatus;\n        currentStatus.map((leds, x_pos) => {\n            return leds.map((led, y_pos) => {\n                if (this._rect[`${x_pos}`][`${y_pos}`]) {\n                    this._rect[`${x_pos}`][`${y_pos}`].remove();\n                }\n                return (this._rect[`${x_pos}`][`${y_pos}`] = this.svgGroup.elem('rect', {\n                    x: y_pos * ledDist + 4,\n                    y: x_pos * ledDist - 8 + ledOffset,\n                    width: ledDist - ledOffset,\n                    height: ledDist - ledOffset,\n                    rx: 0.5,\n                    ry: 0.5,\n                    fill: currentStatus[x_pos][y_pos] ? '#ffffff' : '#00b6b1',\n                }));\n            });\n        });\n    }\n\n    renderStart() {\n        const blockView = this._blockView;\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const that = this;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        const arrowInfo = this.getArrow();\n\n        if (this.svgGroup) {\n            $(this.svgGroup).remove();\n        }\n        const { contentSvgGroup, renderMode } = this._blockView;\n        this.svgGroup = contentSvgGroup.elem('g', {\n            class: 'entry-field-microbit-led',\n        });\n\n        let x, y, WIDTH, HEIGHT;\n\n        HEIGHT = this._CONTENT_HEIGHT;\n        WIDTH = this._CONTENT_WIDTH + 10;\n        const position = this._position;\n        if (position) {\n            x = position.x || 0;\n            y = position.y || 0;\n        } else {\n            x = 0;\n            y = -HEIGHT / 2;\n        }\n        this._header = this.svgGroup.elem('rect', {\n            x,\n            y,\n            width: 35, //WIDTH,\n            height: 20, //HEIGHT,\n\n            rx: 2,\n            ry: 2,\n\n            fill: '#008380',\n        });\n\n        this._rect = Array.from({ length: this.ledSize }, () => []);\n        this.renderLed();\n        this._arrow = this.svgGroup.elem('path', {\n            d: `M 30.79 -1.182\n            L 28.339 1.8\n            a 0.5 0.5 0 0 1 -0.772 0\n            L 25.114 -1.182\n            A 0.5 0.5 0 0 1 25.5 -2\n            h 4.904\n            a 0.5 0.5 0 0 1 0.387 0.818\n            z\n            `,\n            fill: arrowInfo.color,\n            stroke: arrowInfo.color,\n        });\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x,\n            y,\n            width: WIDTH,\n            height: HEIGHT,\n        });\n    }\n\n    getArrow() {\n        return {\n            color: '#ffffff',\n            points: '0,0 6.4,0 3.2,4.2',\n            height: 4.2,\n            width: 6.4,\n        };\n    }\n\n    _attachDisposeEvent(func) {\n        let action = func;\n        if (!action) {\n            action = (skipCommand) => {\n                this.destroyOption(skipCommand);\n                this._selectBlockView();\n            };\n        }\n        this.disposeEvent = Entry.disposeEvent.attach(this, action);\n    }\n\n    renderOptions() {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-field-microbit-led',\n            parent: $('body'),\n        });\n        this.ledPicker = new LedPicker({\n            data: {\n                eventTypes: ['mousedown', 'touchstart'],\n                ledStatus: this.getValue(),\n                canTransparent: false,\n                positionDom: this.svgGroup,\n                onOutsideClick: (ledMatrix) => {\n                    if (this.ledPicker) {\n                        this.ledPicker.hide();\n                        ledMatrix && this.applyValue(ledMatrix);\n                    }\n                    this._attachDisposeEvent();\n                },\n                withLevel: true,\n            },\n            container: this.optionGroup[0],\n        }).on('change', (value) => {\n            if (value) {\n                this.applyValue(value);\n            }\n        });\n\n        this.optionDomCreated();\n    }\n\n    applyValue(value) {\n        this.setValue(value);\n        this.renderLed();\n    }\n\n    destroyOption() {\n        if (this.ledPicker) {\n            this.ledPicker.isShow && this.ledPicker.hide();\n            this.ledPicker.remove();\n            this.ledPicker = null;\n        }\n        if (this.optionGroup) {\n            this.optionGroup.remove();\n        }\n        super.destroyOption();\n    }\n\n    getContentWidth() {\n        return 22;\n    }\n};\n"
  },
  {
    "path": "src/playground/field/lineBreak.js",
    "content": "Entry.FieldLineBreak = class FieldLineBreak extends Entry.Field {\n    constructor(content, blockView, index) {\n        super();\n        this._block = blockView.block;\n        this._blockView = blockView;\n        this._index = index;\n\n        const box = new Entry.BoxModel();\n        this.box = box;\n\n        this.setValue(null);\n        this.renderStart();\n    }\n    renderStart() {\n        return;\n    }\n\n    align(targetStatementIndex) {\n        const blockView = this._blockView;\n\n        if (blockView._statements.length === 0) {\n            return;\n        }\n\n        this.box.set({\n            y:\n                (blockView._statements[targetStatementIndex].height || 20) +\n                Math.max(blockView.contentHeight % 1000, 30),\n        });\n    }\n};\n"
  },
  {
    "path": "src/playground/field/musicScale.js",
    "content": "import { MusicScale } from '@entrylabs/tool';\n\nEntry.FieldMusicScale = class FieldMusicScale extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index);\n        this._block = blockView.block;\n        this._blockView = blockView;\n\n        this.box = new Entry.BoxModel();\n\n        this.svgGroup = null;\n\n        this._contents = content;\n        this._noArrow = content.noArrow;\n\n        const { bgColor, textColor } = content;\n        let { arrowColor } = content;\n        const { deletable, emphasized } = this._block;\n\n        if (deletable === Entry.Block.DELETABLE_FALSE_LIGHTEN || emphasized) {\n            arrowColor = blockView._fillColor;\n        }\n\n        this._arrowColor = arrowColor;\n        this._textColor = textColor || '#FFFFFF';\n        this._bgColor = bgColor;\n        this._index = index;\n        this.setValue(this.getValue() || 'C1');\n\n        this._CONTENT_HEIGHT = this.getContentHeight(content.dropdownHeight);\n\n        this._font_size = this.getFontSize(content.fontSize);\n\n        this._ROUND = content.roundValue || 2;\n\n        this.renderStart();\n    }\n\n    renderStart() {\n        const blockView = this._blockView;\n        const that = this;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        const arrowInfo = this.getArrow();\n\n        if (!this.svgGroup) {\n            this.svgGroup = blockView.contentSvgGroup.elem('g', {\n                class: 'entry-field-music-scale',\n            });\n        }\n\n        if (!this._header) {\n            let x, y, WIDTH, HEIGHT;\n\n            HEIGHT = this._CONTENT_HEIGHT;\n            WIDTH = this._CONTENT_WIDTH + 10;\n            const position = this._position;\n            if (position) {\n                x = position.x || 0;\n                y = position.y || 0;\n            } else {\n                x = 0;\n                y = -HEIGHT / 2;\n            }\n            this._header = this.svgGroup.elem('rect', {\n                x,\n                y,\n                width: 35, //WIDTH,\n                height: 20, //HEIGHT,\n\n                rx: 2,\n                ry: 2,\n\n                fill: '#008380',\n            });\n        }\n\n        if (!this.textElement) {\n            this.textElement = this.svgGroup.elem('text', {\n                x: 5,\n                style: 'white-space: pre;',\n                fill: this._textColor,\n                'font-size': `${+that._font_size}px`,\n                'font-weight': 'bold',\n                'font-family': EntryStatic.fontFamily || 'NanumGothic',\n            });\n        }\n\n        if (!this._noArrow && !this._arrow) {\n            this._arrow = this.svgGroup.elem('path', {\n                d: `M 5.79 0.818\n                L 3.339 3.8\n                a 0.5 0.5 0 0 1 -0.772 0\n                L 0.114 0.818\n                A 0.5 0.5 0 0 1 0.5 0\n                h 4.904\n                a 0.5 0.5 0 0 1 0.387 0.818\n                z\n                `,\n                fill: arrowInfo.color,\n                stroke: arrowInfo.color,\n            });\n        }\n        this._updateTextRender();\n    }\n\n    resize() {\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const board = this._blockView.getBoard() || {};\n        const { scale = 1 } = board || {};\n        let width = this.textElement.getBoundingClientRect().width / scale + X_PADDING;\n        if (!this._noArrow) {\n            const arrowInfo = this.getArrow();\n            this._arrow.attr({\n                transform: `translate(${width - arrowInfo.width - 5},${-arrowInfo.height / 2})`,\n            });\n        } else {\n            width -= X_PADDING_SUBT;\n        }\n\n        this._header.attr({\n            width,\n        });\n\n        this.box.set({ width });\n        this._block.view?.dAlignContent();\n    }\n\n    _attachDisposeEvent(func) {\n        let action = func;\n        if (!action) {\n            action = (skipCommand) => {\n                this.destroyOption(skipCommand);\n                this._selectBlockView();\n            };\n        }\n        this.disposeEvent = Entry.disposeEvent.attach(this, action);\n    }\n\n    getArrow() {\n        return {\n            color: this._arrowColor || '#ffffff',\n            points: '0,0 6.4,0 3.2,4.2',\n            height: 4.2,\n            width: 6.4,\n        };\n    }\n\n    renderOptions(neighborFields) {\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-widget-music-scale',\n            parent: $('body'),\n        });\n        const currentValue = this.getValue();\n        const scale = currentValue.substr(0, currentValue.length - 1);\n        const octave = currentValue[currentValue.length - 1];\n        this.optionWidget = new MusicScale({\n            type: 'musicScaleWidget',\n            data: {\n                eventTypes: ['mousedown', 'touchstart', 'wheel'],\n                positionDom: this.svgGroup,\n                onOutsideClick: () => {\n                    this.destroyOption();\n                },\n                scale: scale || 'C',\n                octave: octave || 1,\n            },\n            container: this.optionGroup[0],\n        }).on('click', (eventName, value) => {\n            let prevValue = String(this.getValue());\n            switch (eventName) {\n                case 'changedValue':\n                    if (prevValue === '0' && _.includes(['0', '.'], value) === false) {\n                        prevValue = '';\n                    }\n                    this.applyValue(value);\n                    break;\n            }\n        });\n    }\n\n    getContentHeight(height) {\n        return height || this._blockView.getSkeleton().dropdownHeight || 20;\n    }\n\n    applyValue(value) {\n        if (this.value != value) {\n            this.setValue(value);\n        }\n        this._setTextValue();\n        this.resize();\n    }\n\n    destroyOption(skipCommand, forceCommand) {\n        if (this.optionWidget) {\n            this.optionWidget.isShow && this.optionWidget.hide();\n            this.optionWidget.remove();\n            delete this.optionWidget;\n        }\n        if (this.optionGroup) {\n            this.optionGroup.remove();\n        }\n\n        super.destroyOption();\n    }\n\n    getTextWidth() {\n        return Math.max(this.getTextBBox().width, 7);\n    }\n\n    _updateTextRender() {\n        const X_PADDING = 20;\n        const X_PADDING_SUBT = 10;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        const arrowInfo = this.getArrow();\n        this._setTextValue();\n\n        const bBox = this.getTextBBox();\n\n        this.textElement.attr({\n            y: bBox.height * 0.27,\n        });\n\n        let width = bBox.width + X_PADDING;\n\n        if (this._noArrow) {\n            width -= X_PADDING_SUBT;\n        }\n\n        this._header.attr({ width });\n\n        if (!this._noArrow) {\n            this._arrow.attr({\n                transform: `translate(${width - arrowInfo.width - 5},${-arrowInfo.height / 2})`,\n            });\n        }\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x: 0,\n            y: 0,\n            width,\n            height: CONTENT_HEIGHT,\n        });\n    }\n\n    _setTextValue() {\n        const textValue = this.getValue();\n        const newValue = this._convert(textValue, this.getValue());\n        if (this.getTextValue() !== newValue) {\n            const scale = newValue.substr(0, newValue.length - 1);\n            const octave = newValue[newValue.length - 1];\n            this.textElement.textContent = `${octave} ${Lang.Blocks.octave} ${scale}`;\n        }\n    }\n\n    getTextValue() {\n        return this.textElement.textContent;\n    }\n};\n"
  },
  {
    "path": "src/playground/field/output.js",
    "content": "/*\n */\n'use strict';\n/*\n *\n */\nEntry.FieldOutput = class FieldOutput extends Entry.Field {\n    schema = {\n        magneting: false,\n    };\n    constructor(content, blockView, index, mode, contentIndex) {\n        super(content, blockView, index);\n        Entry.Model(this, false);\n\n        this._blockView = blockView;\n        this._block = blockView.block;\n        this._valueBlock = null;\n\n        this.box = new Entry.BoxModel();\n        this.changeEvent = new Entry.Event(this);\n\n        this._index = index;\n        this.contentIndex = contentIndex;\n        this._content = content;\n\n        this.acceptType = content.accept;\n\n        this.view = this;\n\n        this.svgGroup = null;\n\n        this._position = content.position;\n\n        this.box.observe(blockView, 'dAlignContent', ['width', 'height']);\n        this.observe(this, '_updateBG', ['magneting'], false);\n\n        this.renderStart(blockView.getBoard(), mode);\n        this.isParamBlockType = _.constant(true);\n        this.calcHeight = this.calcWH;\n    }\n\n    renderStart(board, mode) {\n        if (!this.svgGroup) {\n            this.svgGroup = this._blockView.contentSvgGroup.elem('g');\n        }\n\n        this.view = this;\n        this._nextGroup = this.svgGroup;\n\n        const block = this.getValue();\n        if (block && !block.view) {\n            block.setThread(this);\n            block.createView(board, mode);\n        }\n\n        this._updateValueBlock(block);\n        this._valueBlock && this._valueBlock.view._startContentRender(this.renderMode);\n\n        if (this._blockView.getBoard().constructor == Entry.BlockMenu && this._valueBlock) {\n            this._valueBlock.view.removeControl();\n        }\n    }\n\n    align(x, y, animate) {\n        animate = animate === undefined ? true : animate;\n        const svgGroup = this.svgGroup;\n        if (this._position) {\n            if (this._position.x) {\n                x = this._position.x;\n            }\n            if (this._position.y) {\n                y = this._position.y;\n            }\n        }\n\n        const block = this._valueBlock;\n\n        if (block && block.view) {\n            y = block.view.height * -0.5;\n        }\n\n        const transform = `translate(${x},${y})`;\n\n        if (animate) {\n            svgGroup.animate(\n                {\n                    transform,\n                },\n                300,\n                mina.easeinout\n            );\n        } else {\n            svgGroup.attr({\n                transform,\n            });\n        }\n\n        if (this.box.x !== x || this.box.y !== y) {\n            this.box.set({ x, y });\n        }\n    }\n\n    calcWH() {\n        const block = this._valueBlock;\n        const blockView = block && block.view;\n\n        if (block && blockView) {\n            if (this.box.width !== blockView.width || this.box.height !== blockView.height) {\n                this.box.set({\n                    width: blockView.width,\n                    height: blockView.height,\n                });\n            }\n        } else {\n            this.box.set({\n                width: 0,\n                height: 20,\n            });\n        }\n    }\n\n    destroy() {\n        this._valueBlock && this._valueBlock.destroyView();\n    }\n\n    _inspectBlock() {}\n\n    _setValueBlock(block) {\n        if (block != this._valueBlock || !this._valueBlock) {\n            this._valueBlock = block;\n            this.setValue(block);\n\n            block && block.setThread(this);\n            return this._valueBlock;\n        }\n    }\n\n    spliceBlock() {\n        this._updateValueBlock();\n    }\n\n    _updateValueBlock(block) {\n        if (!(block instanceof Entry.Block)) {\n            block = undefined;\n        }\n\n        if (block && block === this._valueBlock) {\n            this.calcWH();\n            return;\n        }\n\n        this._sizeObserver && this._sizeObserver.destroy();\n        this._posObserver && this._posObserver.destroy();\n\n        block = this._setValueBlock(block);\n        if (block) {\n            const view = block.view;\n            view.bindPrev();\n            this._posObserver = view.observe(this, '_updateValueBlock', ['x', 'y'], false);\n            this._sizeObserver = view.observe(this, 'calcWH', ['width', 'height']);\n        } else {\n            this.calcWH();\n        }\n\n        this._blockView.dAlignContent();\n    }\n\n    getPrevBlock(block) {\n        if (this._valueBlock === block) {\n            return this;\n        } else {\n            return null;\n        }\n    }\n\n    getNextBlock() {\n        return null;\n    }\n\n    requestAbsoluteCoordinate(blockView) {\n        const board = this.getBoard();\n        const { scale = 1 } = board || {};\n        var blockView = this._blockView;\n        const contentPos = blockView.contentPos;\n        const pos = blockView.getAbsoluteCoordinate();\n        pos.x += (this.box.x + contentPos.x) * scale;\n        pos.y += this.box.y + contentPos.y;\n        return pos;\n    }\n\n    dominate() {\n        this._blockView.dominate();\n    }\n\n    isGlobal() {\n        return false;\n    }\n\n    separate(block) {\n        this.getCode().createThread([block]);\n        this._updateValueBlock(null);\n        this.changeEvent.notify();\n    }\n\n    getCode() {\n        return this._block.thread.getCode();\n    }\n\n    cut(block) {\n        if (this._valueBlock === block) {\n            delete this._valueBlock;\n            return [block];\n        } else {\n            return null;\n        }\n    }\n\n    _updateBG() {\n        if (this.magneting) {\n            this._bg = this.svgGroup.elem('path', {\n                d: 'm -4,-12 h 3 l 2,2 0,3 3,0 1,1 0,12 -1,1 -3,0 0,3 -2,2 h -3 ',\n                fill: '#fff',\n                stroke: '#fff',\n                'fill-opacity': 0.7,\n                transform: `translate(0,${this._valueBlock ? 12 : 0})`,\n            });\n        } else {\n            if (this._bg) {\n                this._bg.remove();\n                delete this._bg;\n            }\n        }\n    }\n\n    replace(block) {\n        const valueBlock = this._valueBlock;\n        if (valueBlock) {\n            valueBlock.view._toGlobalCoordinate();\n            block.getTerminateOutputBlock().view._contents[1].replace(valueBlock);\n        }\n        this._updateValueBlock(block);\n        block.view._toLocalCoordinate(this);\n        this.calcWH();\n    }\n\n    setParent(parent) {\n        this._parent = parent;\n    }\n\n    getParent() {\n        return this._parent;\n    }\n\n    getThread() {\n        return this;\n    }\n\n    getValueBlock() {\n        return this._valueBlock;\n    }\n\n    pointer(pointer) {\n        pointer = pointer || [];\n        pointer.unshift(this._index);\n        pointer.unshift(Entry.PARAM);\n        return this._block.pointer(pointer);\n    }\n};\n"
  },
  {
    "path": "src/playground/field/statement.js",
    "content": "/*\n */\n'use strict';\n\n/*\n *\n */\nEntry.FieldStatement = function(content, blockView, index) {\n    Entry.Model(this, false);\n\n    this._blockView = blockView;\n    this.block = blockView.block;\n\n    this.view = this;\n\n    this._index = index;\n\n    this.acceptType = content.accept;\n\n    this.svgGroup = null;\n    this.commentGroup = null;\n    this.statementSvgGroup = null;\n    this.statementCommentGroup = null;\n    this._thread = null;\n\n    this._position = content.position;\n\n    this._events = [];\n\n    this.observe(blockView, 'alignContent', ['height'], false);\n    this.observe(this, '_updateBG', ['magneting'], false);\n\n    this.renderStart(blockView.getBoard());\n};\n\n(function(p) {\n    p.schema = {\n        x: 0,\n        y: 0,\n        width: 100,\n        height: 31,\n        magneting: false,\n    };\n\n    p.magnet = { next: { x: 0, y: 0 } };\n\n    p.renderStart = function(board) {\n        this.svgGroup = this._blockView.statementSvgGroup.elem('g');\n        this.statementSvgGroup = this.svgGroup.elem('g');\n        this._nextGroup = this.statementSvgGroup;\n        if (this._blockView.statementCommentGroup) {\n            this.commentGroup = this._blockView.statementCommentGroup.elem('g');\n            this.statementCommentGroup = this.commentGroup.elem('g');\n            this._nextCommentGroup = this.statementCommentGroup;\n        }\n        this._initThread(board);\n        this._board = board;\n    };\n\n    p._initThread = function(board) {\n        const thread = this.getValue();\n        this._thread = thread;\n        thread.createView(board);\n        thread.view.setParent(this);\n        const firstBlock = thread.getFirstBlock();\n        if (firstBlock) {\n            firstBlock.view._toLocalCoordinate(this);\n            this.firstBlock = firstBlock;\n        }\n\n        const event = thread.changeEvent;\n\n        const calcEvent = event.attach(this, this.calcHeight);\n        const checkTopEvent = event.attach(this, this.checkTopBlock);\n\n        this._events.push(calcEvent);\n        this._events.push(checkTopEvent);\n\n        this.calcHeight();\n    };\n\n    p.align = function(x, y, animate) {\n        animate = animate === undefined ? true : animate;\n        const svgGroup = this.svgGroup;\n        const commentGroup = this.commentGroup;\n        if (this._position) {\n            if (this._position.x) {\n                x = this._position.x;\n            }\n            if (this._position.y) {\n                y = this._position.y;\n            }\n        }\n\n        const transform = `translate(${x},${y})`;\n\n        if (this.x !== x || this.y !== y) {\n            this.set({ x, y });\n        }\n\n        if (animate) {\n            svgGroup.animate(\n                {\n                    transform,\n                },\n                300,\n                mina.easeinout\n            );\n            if (commentGroup) {\n                commentGroup.animate(\n                    {\n                        transform,\n                    },\n                    300,\n                    mina.easeinout\n                );\n            }\n        } else {\n            svgGroup.attr({\n                transform,\n            });\n            if (commentGroup) {\n                commentGroup.attr({\n                    transform,\n                });\n            }\n        }\n    };\n\n    p.calcHeight = function() {\n        const height = this._thread.view.requestPartHeight(null);\n        if (this.height === height) {\n            return;\n        }\n        this.set({ height });\n    };\n\n    p.getValue = function() {\n        return this.block.statements[this._index];\n    };\n\n    p.requestAbsoluteCoordinate = function() {\n        const { scale = 1 } = this._board || {};\n        const pos = this._blockView.getAbsoluteCoordinate();\n        pos.x += this.x * scale;\n        pos.y += this.y * scale;\n        return pos;\n    };\n\n    p.dominate = function() {\n        this._blockView.dominate();\n    };\n\n    p.destroy = function() {\n        while (this._events.length) {\n            this._events.pop().destroy();\n        }\n    };\n\n    p._updateBG = function() {\n        const dragBlock = this._board.dragBlock;\n        if (!dragBlock || !dragBlock.dragInstance) {\n            return;\n        }\n\n        const blockView = this;\n        const magneting = blockView.magneting;\n        const { scale = 1 } = this._board || {};\n\n        if (magneting) {\n            const shadow = dragBlock.getShadow();\n            const pos = this.requestAbsoluteCoordinate();\n            const transform = `translate(${pos.x / scale}, ${pos.y / scale})`;\n            $(shadow).attr({\n                transform,\n                display: 'block',\n            });\n            this._clonedShadow = shadow;\n\n            if (blockView.background) {\n                blockView.background.remove();\n                blockView.nextBackground.remove();\n                delete blockView.background;\n                delete blockView.nextBackground;\n            }\n            const height = dragBlock.getBelowHeight();\n\n            this.statementSvgGroup.attr({\n                transform: `translate(0,${height})`,\n            });\n            this.statementCommentGroup.attr({\n                transform: `translate(0,${height})`,\n            });\n\n            this.set({ height: this.height + height });\n        } else {\n            if (this._clonedShadow) {\n                this._clonedShadow.attr({ display: 'none' });\n                delete this._clonedShadow;\n            }\n\n            const height = blockView.originalHeight;\n            if (height !== undefined) {\n                if (blockView.background) {\n                    blockView.background.remove();\n                    blockView.nextBackground.remove();\n                    delete blockView.background;\n                    delete blockView.nextBackground;\n                }\n                delete blockView.originalHeight;\n            }\n            this.statementSvgGroup.attr({\n                transform: 'translate(0,0)',\n            });\n            this.statementCommentGroup.attr({\n                transform: 'translate(0,0)',\n            });\n            this.calcHeight();\n        }\n        const changeEvent = blockView.block.thread.changeEvent;\n        if (changeEvent) {\n            changeEvent.notify();\n        }\n    };\n\n    p.insertTopBlock = function(newBlock) {\n        if (this._posObserver) {\n            this._posObserver.destroy();\n        }\n\n        const block = this.firstBlock;\n        this.firstBlock = newBlock;\n        if (newBlock) {\n            newBlock.doInsert(this._thread);\n        }\n        return block;\n    };\n\n    p.getNextBlock = function() {\n        return this.firstBlock;\n    };\n\n    p.checkTopBlock = function() {\n        const firstBlock = this._thread.getFirstBlock();\n        if (firstBlock && this.firstBlock !== firstBlock) {\n            this.firstBlock = firstBlock;\n            firstBlock.view.bindPrev(this);\n            firstBlock._updatePos();\n        } else if (!firstBlock) {\n            this.firstBlock = null;\n        }\n    };\n\n    p.pointer = function(pointer) {\n        pointer = pointer || [];\n        pointer.unshift(this._index);\n        return this.block.pointer(pointer);\n    };\n\n    p.isParamBlockType = function() {\n        return false;\n    };\n})(Entry.FieldStatement.prototype);\n"
  },
  {
    "path": "src/playground/field/text.js",
    "content": "Entry.FieldText = class FieldText extends Entry.Field {\n    constructor({ fontSize, align = 'left', text, color }, blockView, index) {\n        super();\n        this._block = blockView.block;\n        this._blockView = blockView;\n        this._index = index;\n\n        this.box = new Entry.BoxModel();\n\n        this._font_size = fontSize || blockView.getSkeleton().fontSize || 12;\n        this._color =\n            color || this._block.getSchema().fontColor || blockView.getSkeleton().color || 'white';\n        this._align = align;\n        this._text = this.getValue() || text;\n        this.setValue(null);\n\n        this.textElement = null;\n\n        this.renderStart();\n    }\n    renderStart() {\n        const { contentSvgGroup } = this._blockView;\n\n        if (!this.textElement) {\n            this.svgGroup = this.textElement = contentSvgGroup.elem('text').attr({\n                style: 'white-space: pre;',\n                'font-size': `${this._font_size}px`,\n                'font-weight': 'bold',\n                'font-family': EntryStatic.fontFamily || 'NanumGothic',\n                class: 'dragNone',\n                fill: this._color,\n            });\n        }\n\n        const old = this.textElement.textContent;\n        // this._text = this._text.replace(/(\\r\\n|\\n|\\r)/gm, ' ');\n        const text = this._text || '';\n        if (old !== text.replace(/(\\r\\n|\\n|\\r)/gm, '')) {\n            const textList = this._text.split(/\\r\\n|\\n|\\r/gm);\n            textList.forEach((text, i) => {\n                this.textElement.elem('tspan').attr({\n                    dy: `${i ? 14 : 0}px`,\n                }).textContent = text;\n            });\n            // this.textElement.textContent = this._text;\n        }\n\n        const { width, height } = this.getTextBBox();\n        const x = this._align == 'center' ? -width / 2 : 0;\n        const offsetY = EntryStatic.fontOffsetY || 0;\n        this.textElement.attr({\n            x,\n            y: height * 0.5 + offsetY,\n        });\n\n        if (this.textElement.childElementCount > 1) {\n            const { childNodes } = this.textElement;\n            for (let i = 0; i < childNodes.length; i++) {\n                childNodes[i].attr({\n                    x,\n                });\n            }\n        }\n\n        this.box.set({\n            x: 0,\n            y: 0,\n            width,\n            height,\n        });\n    }\n\n    getTextValue() {\n        return this._text;\n    }\n};\n"
  },
  {
    "path": "src/playground/field/textDynamic.js",
    "content": "\nEntry.FieldTextDynamic = class FieldTextDynamic extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index, null, null, true);\n        const { fontSize, align = 'left', text, color, setValue } = content;\n        this._block = blockView.block;\n        this._blockView = blockView;\n        this._index = index;\n\n        this.box = new Entry.BoxModel();\n\n        this._font_size = fontSize || blockView.getSkeleton().fontSize || 12;\n        this._color =\n            color || this._block.getSchema().fontColor || blockView.getSkeleton().color || 'white';\n        this._align = align;\n        this._text = this.getValue() || text;\n\n        this.textElement = null;\n        this.setGenerateValue = setValue;\n        this.renderStart(blockView);\n\n    }\n\n    async _updateValue() {\n        if(!this.setGenerateValue) {\n            return ;\n        }\n        const value = await this.setGenerateValue();\n        this._text = value;\n        const reDraw = this.value !== value;\n        if (reDraw) {\n            this.value = undefined;\n        }\n       \n        this.setValue(value, reDraw);\n    }\n\n    renderStart() {\n        const { contentSvgGroup } = this._blockView;\n        this._updateValue();\n        if (!this.textElement) {\n            this.svgGroup = this.textElement = contentSvgGroup.elem('text').attr({\n                style: 'white-space: pre;',\n                'font-size': `${this._font_size}px`,\n                'font-weight': 'bold',\n                'font-family': EntryStatic.fontFamily || 'NanumGothic',\n                class: 'dragNone',\n                fill: this._color,\n            });\n        }\n\n        const old = this.textElement.textContent;\n        // this._text = this._text.replace(/(\\r\\n|\\n|\\r)/gm, ' ');\n        const text = this._text || '';\n        if (old !== text.replace(/(\\r\\n|\\n|\\r)/gm, '')) {\n            const textList = this._text.split(/\\r\\n|\\n|\\r/gm);\n            textList.forEach((text, i) => {\n                this.textElement.elem('tspan').attr({\n                    dy: `${i ? 14 : 0}px`,\n                }).textContent = text;\n            });\n            this.textElement.textContent = this._text;\n        }\n\n        const { width, height } = this.getTextBBox();\n        const x = this._align == 'center' ? -width / 2 : 0;\n        const offsetY = EntryStatic.fontOffsetY || 0;\n        this.textElement.attr({\n            x,\n            y: height * 0.5 + offsetY,\n        });\n\n        if (this.textElement.childElementCount > 1) {\n            const { childNodes } = this.textElement;\n            for (let i = 0; i < childNodes.length; i++) {\n                childNodes[i].attr({\n                    x,\n                });\n            }\n        }\n\n        this.box.set({\n            x: 0,\n            y: 0,\n            width,\n            height,\n        });\n    }\n\n    getTextValue() {\n        return this._text;\n    }\n};\n"
  },
  {
    "path": "src/playground/field/textInput.js",
    "content": "'use strict';\n\nimport { Angle, Number } from '@entrylabs/tool';\n\nEntry.FieldTextInput = class FieldTextInput extends Entry.Field {\n    constructor(content, blockView, index) {\n        super(content, blockView, index);\n        const { data = {} } = blockView;\n        const { type = 'text' } = data;\n        this.type = type;\n        this.TEXT_Y_PADDING = 3;\n\n        this._blockView = blockView;\n        this.board = this._blockView.getBoard();\n        this._block = blockView.block;\n\n        this.box = new Entry.BoxModel();\n\n        this.svgGroup = null;\n        this.optionWidget = null;\n        this.optionInput = null;\n\n        this.position = content.position;\n        this._contents = content;\n        this._isClearBG = content.clearBG || false;\n        this._index = index;\n        this._CONTENT_HEIGHT = this.getContentHeight();\n        this._font_size = content.fontSize || 10;\n        this._neighborFields = null;\n\n        this.renderStart();\n    }\n\n    // 기본 모드의 keyEvent(tab) 용\n    _focusNeighbor(direction) {\n        const fields = this.getNeighborFields();\n\n        let idx = fields.indexOf(this);\n        if (direction === 'prev') {\n            idx--;\n        } else {\n            idx++;\n        }\n        const field = fields[idx];\n\n        //no field to focus\n        if (!field) {\n            return;\n        }\n\n        this.board.setSelectedBlock(field._blockView);\n        this.destroyOption(undefined, true);\n        field.renderOptions(fields);\n    }\n\n    renderStart() {\n        const blockView = this._blockView;\n\n        if (!this.svgGroup) {\n            this.svgGroup = blockView.contentSvgGroup.elem('g');\n        }\n\n        if (!this.textElement) {\n            this.textElement = this.svgGroup.elem('text', {\n                x: 0,\n                y: this.TEXT_Y_PADDING,\n                fill: this._contents.color || 'black',\n                'font-size': `${this._font_size}px`,\n                'font-weight': 'bold',\n                'font-family': EntryStatic.fontFamily || 'NanumGothic',\n            });\n        }\n\n        this.svgGroup.attr({ class: 'entry-input-field' });\n\n        this._setConvertedValue();\n\n        const width = this.getTextWidth();\n        let y = this.position && this.position.y ? this.position.y : 0;\n        const CONTENT_HEIGHT = this._CONTENT_HEIGHT;\n        y -= CONTENT_HEIGHT / 2;\n        if (!this._header) {\n            this._header = this.svgGroup.elem('rect', {\n                width,\n                x: 0,\n                y,\n                height: CONTENT_HEIGHT,\n                rx: 0,\n                ry: 3,\n                fill: '#fff',\n                'fill-opacity': 0,\n            });\n        } else {\n            this._header.setAttribute('width', width);\n        }\n\n        if (this._isClearBG) {\n            $(this._header).css({ stroke: 'none' });\n        }\n\n        this.svgGroup.appendChild(this.textElement);\n\n        this._bindRenderOptions();\n\n        this.box.set({\n            x: 0,\n            y: 0,\n            width,\n            height: CONTENT_HEIGHT,\n        });\n    }\n\n    renderOptions(neighborFields) {\n        const { _block = {} } = this;\n        const { defaultType = 'text' } = _block;\n        if (neighborFields) {\n            this._neighborFields = neighborFields;\n        }\n\n        this.optionGroup = Entry.Dom('div', {\n            class: 'entry-widget-parent',\n            parent: $('body'),\n        });\n\n        if (Entry.isMobile()) {\n            if (defaultType === 'number') {\n                this.optionWidget = this._getNumberOptionWidget();\n            } else if (defaultType === 'angle') {\n                this.optionWidget = this._getAngleOptionWidget();\n            } else {\n                this.optionInput = this._getInputFieldOption();\n                this._attachDisposeEvent();\n            }\n        } else {\n            if (defaultType === 'angle') {\n                this.optionInput = this._getInputFieldOption();\n                this.optionWidget = this._getAngleOptionWidget(this.optionInput[0]);\n            } else {\n                this.optionInput = this._getInputFieldOption();\n                this._attachDisposeEvent();\n            }\n        }\n\n        this._setTextValue();\n        this.optionDomCreated();\n    }\n\n    _getNumberOptionWidget() {\n        return new Number({\n            type: 'numberWidget',\n            data: {\n                eventTypes: ['mousedown', 'touchstart', 'wheel'],\n                positionDom: this.svgGroup,\n                onOutsideClick: () => {\n                    this.destroyOption(undefined, true);\n                },\n            },\n            container: this.optionGroup[0],\n        }).on('click', (eventName, value) => {\n            let prevValue = String(this.getValue());\n            switch (eventName) {\n                case 'buttonPressed':\n                    if (prevValue === '0' && _.includes(['0', '.'], value) === false) {\n                        prevValue = '';\n                    }\n                    this.applyValue(prevValue + value);\n                    break;\n                case 'backButtonPressed': {\n                    const nextValue = prevValue.substring(0, prevValue.length - 1);\n                    this.applyValue(_.isEmpty(nextValue) ? 0 : nextValue);\n                    break;\n                }\n            }\n        });\n    }\n\n    /**\n     *\n     * @param {Array} excludeDom outside 로 판단하지 않을 dom target list\n     * @returns {EntryTool} Angle Widget\n     * @private\n     */\n    _getAngleOptionWidget(...excludeDom) {\n        return new Angle({\n            type: 'angleWidget',\n            data: {\n                eventTypes: ['mousedown', 'touchstart', 'wheel'],\n                angle: this.getValue(),\n                outsideExcludeDom: excludeDom,\n                positionDom: this.svgGroup,\n                onOutsideClick: (angle) => {\n                    this.applyValue(FieldTextInput._refineDegree(angle));\n                    this.destroyOption();\n                },\n            },\n            container: this.optionGroup[0],\n        })\n            .on('click', (eventName, value) => {\n                let nextValue = 0;\n                switch (eventName) {\n                    case 'buttonPressed': {\n                        nextValue = this._getNextValue(value);\n                        break;\n                    }\n                    case 'backButtonPressed': {\n                        nextValue = this._getSubstringValue();\n                        break;\n                    }\n                }\n                this.applyValue(nextValue);\n            })\n            .on('change', (value) => {\n                this.applyValue(String(value));\n            });\n    }\n\n    _getInputFieldOption() {\n        const inputField = Entry.Dom('input', {\n            class: 'entry-widget-input-field',\n            parent: $('body'),\n        });\n\n        inputField.val(this.getValue());\n\n        inputField.on('mousedown', (e) => {\n            e.stopPropagation();\n        });\n\n        inputField.on('keyup', (e) => {\n            this.applyValue(inputField[0].value, true);\n            if (_.includes([13, 27], e.keyCode || e.which)) {\n                this.destroyOption(undefined, true);\n            }\n        });\n\n        inputField.on('keydown', (e) => {\n            const keyCode = e.keyCode || e.which;\n\n            if (keyCode === 9) {\n                e.preventDefault();\n                this._focusNeighbor(e.shiftKey ? 'prev' : 'next');\n            }\n        });\n\n        inputField.on('blur', (e) => {\n            const isOptionGroupVisible = !!this.optionGroup.get(0).style.display;\n            if (!isOptionGroupVisible) {\n                this.destroyOption(undefined, true);\n            }\n        });\n\n        const { scale = 1 } = this.board;\n        this._font_size = 10 * scale;\n        const { x, y } = this.getAbsolutePosFromDocument();\n        const height = (this._CONTENT_HEIGHT - 4) * scale;\n        inputField.css({\n            height,\n            left: x + 1,\n            top: y + (scale - 1) * 4 + 2 * scale - 1 * (scale / 2) - this.box.height / 2,\n            width: this.box.width * scale,\n            'font-size': `${this._font_size}px`,\n            'background-color': EntryStatic.colorSet.block.lighten.CALC,\n        });\n\n        inputField.focus && inputField.focus();\n\n        inputField[0].setSelectionRange(0, inputField[0].value.length, 'backward');\n        return inputField;\n    }\n\n    applyValue(value, isNotUpdate) {\n        let result = value;\n\n        if (this.optionWidget) {\n            switch (this.optionWidget.type) {\n                case 'angleWidget':\n                    this.optionWidget.data = {\n                        angle: FieldTextInput._refineDegree(value),\n                    };\n                    if (\n                        Entry.Utils.isNumber(value) &&\n                        value.lastIndexOf('.') !== value.length - 1\n                    ) {\n                        result = String(result % 360);\n                    }\n                    break;\n            }\n        }\n        if (this.optionInput && !isNotUpdate) {\n            this.optionInput.val(result);\n        }\n\n        if (this._block?.data?.type === 'function_field_label') {\n            const reg = /(%\\d)/im;\n            if (result && reg.test(result)) {\n                result = result.replace(/%(\\d)/gi, '$1');\n            }\n        }\n        this.setValue(result);\n        this._setTextValue();\n        this.resize();\n    }\n\n    resize() {\n        const { scale = 1 } = this.board;\n        const size = { width: this.getTextWidth() };\n        const scaleSize = { width: this.getTextWidth() / scale };\n        this._header.attr(scaleSize);\n        this.box.set(scaleSize);\n        this.optionInput && this.optionInput.css(size);\n        this._blockView.dAlignContent();\n    }\n\n    destroyOption(skipCommand, forceCommand) {\n        this._setConvertedValue();\n\n        if (this.optionWidget) {\n            this.optionWidget.isShow && this.optionWidget.hide();\n            this.optionWidget.remove();\n            delete this.optionWidget;\n        }\n\n        if (this.optionInput) {\n            this.optionInput.remove();\n            delete this.optionInput;\n        }\n\n        const reg = /(%\\d)/im;\n        if (this.value && reg.test(this.value)) {\n            this.applyValue(this.value.replace(/%(\\d)/gi, '$1'));\n        }\n\n        super.destroyOption(skipCommand, forceCommand);\n    }\n\n    getTextWidth() {\n        return Math.max(this.getTextBBox().width, 7);\n    }\n\n    _setTextValue() {\n        const value = this.getValue();\n        if (this.textElement.textContent !== value) {\n            this.textElement.textContent = value;\n        }\n    }\n\n    _setConvertedValue() {\n        const { _block = {} } = this;\n        const { defaultType = 'text' } = _block;\n        let value = this._convert(this.getValue(), this.getValue());\n\n        if (defaultType === 'angle') {\n            value += '°';\n        }\n\n        if (this.textElement.textContent !== value) {\n            this.textElement.textContent = value;\n        }\n    }\n\n    getNeighborFields() {\n        if (!this._neighborFields) {\n            const FIELD_TEXT_INPUT = Entry.FieldTextInput;\n            this._neighborFields = this._block\n                .getRootBlock()\n                .getThread()\n                .view.getFields()\n                .filter((f) => f instanceof FIELD_TEXT_INPUT);\n        }\n\n        return this._neighborFields;\n    }\n\n    /**\n     * 기존 값의 뒤에 새 값을 추가한다. 내부에서 모든 숫자는 문자열이다.\n     * 규칙은 아래와 같다.\n     *\n     * - 마이너스 입력은 현재 값이 0 인 경우만 가능\n     * - . 은 값에서 유일하게 하나만 허용한다.\n     * - 현재 값이 0 혹은 -0 인 경우 0은 입력할 수 없다. 다른 숫자는 입력할 수 있다.\n     *\n     * @param value 이번에 입력된 값\n     * @return {string} 규칙에 맞추어 정제된 값\n     * @private\n     */\n    _getNextValue(value) {\n        let returnValue = String(this.getValue());\n        returnValue = returnValue.replace('°', '');\n\n        if (!FieldTextInput._isValidInputValue(value)) {\n            return returnValue;\n        }\n\n        switch (value) {\n            case '-':\n                if (returnValue === '0') {\n                    return '-';\n                }\n                return returnValue;\n            case '.':\n                if (/\\./.test(returnValue) || returnValue === '-') {\n                    return returnValue;\n                }\n                break;\n            case '0':\n                if (returnValue.startsWith('0') || returnValue.startsWith('-0')) {\n                    return returnValue;\n                }\n                break;\n            default:\n                if (returnValue === '0') {\n                    return value;\n                }\n                break;\n        }\n\n        returnValue += value;\n        return returnValue;\n    }\n\n    /**\n     * 현재 값 블록에서 마지막 숫자를 삭제한 값을 반환한다.\n     * 0 인 경우는 0 을 반환, - 인 경우는 0 을 반환한다.\n     * @returns {string} 마지막 위치가 삭제된 블록 값\n     * @private\n     */\n    _getSubstringValue() {\n        const returnValue = String(this.getValue());\n        if (returnValue.length === 1) {\n            return '0';\n        } else {\n            return returnValue.slice(0, returnValue.length - 1);\n        }\n    }\n\n    static _refineDegree(value) {\n        const reg = /&value/gm;\n        if (reg.test(value)) {\n            return value;\n        }\n\n        const numberOnlyValue = String(value).match(/[\\d|\\-|.|\\+]+/g);\n        let refinedDegree = (numberOnlyValue && numberOnlyValue[0]) || '0';\n        if (refinedDegree > 360) {\n            refinedDegree %= 360;\n        } else if (refinedDegree < 0) {\n            refinedDegree = refinedDegree % 360;\n        }\n        refinedDegree = String(refinedDegree);\n\n        if (refinedDegree.lastIndexOf('.') === refinedDegree.length - 1) {\n            return refinedDegree.slice(0, refinedDegree.length - 1);\n        }\n\n        return refinedDegree;\n    }\n\n    static _isValidInputValue(value) {\n        return Entry.Utils.isNumber(value) || value === '-' || value === '.';\n    }\n};\n"
  },
  {
    "path": "src/playground/globalSvg.js",
    "content": "'use strict';\n\nclass GlobalSvg {\n    DONE = 0;\n    _inited = false;\n    REMOVE = 1;\n    RETURN = 2;\n    scale = 1;\n\n    createDom() {\n        if (this.inited) {\n            return;\n        }\n\n        //document attached element not removed by angular\n        $('#globalSvgSurface').remove();\n        $('#globalSvg').remove();\n\n        const body = $('body');\n        this._container = Entry.Dom('div', {\n            classes: ['globalSvgSurface', 'entryRemove'],\n            id: 'globalSvgSurface',\n            parent: body,\n        });\n\n        this.svgDom = Entry.Dom(\n            $(\n                '<svg id=\"globalSvg\" width=\"1\" height=\"1\"' +\n                    'version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"></svg>'\n            ),\n            { parent: this._container }\n        );\n\n        this.svg = Entry.SVG('globalSvg');\n        this.svgPoint = this.svg.createSVGPoint();\n        this.left = 0;\n        this.top = 0;\n        this._inited = true;\n    }\n\n    setView(view, mode) {\n        if (view == this._view) {\n            return;\n        }\n        const data = view.block || view;\n        if (data.isReadOnly() || !view.movable) {\n            return;\n        }\n        this._view = view;\n        this._mode = mode;\n        this.isFromBlockMenu = view.dragInstance && view.dragInstance.isNew;\n        view.set({ visible: false });\n        this.draw();\n        this.show();\n        this.align();\n        this.position();\n        return true;\n    }\n\n    getView() {\n        return this._view;\n    }\n\n    get canAddStorageBlock() {\n        const { block = {} } = this._view || {};\n        const { copyable } = block;\n        return !this.isFromBlockMenu && copyable;\n    }\n\n    setComment(view, mode) {\n        if (view == this._view || view.readOnly || !view.movable) {\n            return;\n        }\n\n        view._path.attr({\n            id: `${view.id}C`,\n            stroke: 'red',\n        });\n\n        view._titlePath.attr({\n            id: `${view.id}T`,\n        });\n\n        view._textPath.attr({\n            href: `#${view.id}C`,\n        });\n\n        view._titleTextPath.attr({\n            href: `#${view.id}T`,\n        });\n        this._view = view;\n        this._mode = mode;\n        this.originalX = view.x;\n        this.originalY = view.y;\n        this.draw();\n        this.show();\n        this.align();\n        this.commentPosition();\n    }\n\n    draw() {\n        const blockView = this._view;\n        if (this._svg) {\n            this.remove();\n        }\n        const isVimMode = this._mode == Entry.Workspace.MODE_VIMBOARD;\n        const bBox = blockView.svgGroup.getBBox();\n        const { width, height } = bBox;\n        this.svgDom.attr({\n            width: `${Math.round(bBox.width + 4)}px`,\n            height: `${Math.round(bBox.height + 4)}px`,\n        });\n        this.xScaleDiff = (width * (this.scale - 1)) / (this.scale * 2);\n        this.yscaleDiff = (height * (this.scale - 1)) / (this.scale * 2);\n\n        this.svgGroup = Entry.SVG.createElement(blockView.svgGroup.cloneNode(true), { opacity: 1 });\n        this.svg.appendChild(this.svgGroup);\n        if (blockView.svgCommentGroup) {\n            this.svgCommentGroup = Entry.SVG.createElement(\n                blockView.svgCommentGroup.cloneNode(true),\n                {\n                    opacity: 1,\n                }\n            );\n            this.svg.appendChild(this.svgCommentGroup);\n        }\n        //TODO selectAll function replace\n        if (isVimMode) {\n            const $svg = $(this.svgGroup);\n            const $svgComment = $(this.svgCommentGroup);\n\n            $svg.find('g').css({ filter: 'none' });\n            $svgComment.find('g').css({ filter: 'none' });\n\n            $svg.find('path, rect, polygon').velocity(\n                {\n                    opacity: 0,\n                },\n                {\n                    duration: 500,\n                }\n            );\n            $svgComment.find('path, rect, polygon').velocity(\n                {\n                    opacity: 0,\n                },\n                {\n                    duration: 500,\n                }\n            );\n\n            $svg.find('text').velocity(\n                {\n                    fill: '#000000',\n                },\n                {\n                    duration: 530,\n                }\n            );\n            $svgComment.find('text').velocity(\n                {\n                    fill: '#000000',\n                },\n                {\n                    duration: 530,\n                }\n            );\n        }\n    }\n\n    remove() {\n        if (!this.svgGroup) {\n            return;\n        }\n        this.svgGroup.remove();\n        delete this.svgGroup;\n        if (this.svgCommentGroup) {\n            this.svgCommentGroup.remove();\n            delete this.svgCommentGroup;\n        }\n        delete this._view;\n        delete this._offsetX;\n        delete this._offsetY;\n        delete this._startX;\n        delete this._startY;\n        this.hide();\n    }\n\n    align() {\n        let offsetX = 0;\n        let offsetY = 0;\n        if (this._view.getSkeleton) {\n            offsetX = this._view.getSkeleton().box(this._view).offsetX || 0;\n            offsetY = this._view.getSkeleton().box(this._view).offsetY || 0;\n        }\n        offsetX *= -1;\n        offsetX += 1;\n        offsetY *= -1;\n        offsetY += 1;\n        this._offsetX = offsetX;\n        this._offsetY = offsetY;\n        const transform = `translate(${offsetX}, ${offsetY})`;\n        this.svgGroup.attr({ transform });\n        if (this.svgCommentGroup) {\n            this.svgCommentGroup.attr({ transform });\n        }\n    }\n\n    show() {\n        this.isShow = true;\n        this._container.removeClass('entryRemove');\n    }\n\n    hide() {\n        this.isShow = false;\n        this._container.addClass('entryRemove');\n    }\n\n    position(value) {\n        const blockView = this._view;\n        if (!blockView) {\n            return;\n        }\n        const pos = blockView.getAbsoluteCoordinate();\n        const offset = blockView.getBoard().offset();\n        if (value) {\n            this.left += value.left / this.scale;\n            this.top += value.top / this.scale;\n        } else {\n            this.left = pos.scaleX + (offset.left / this.scale - this._offsetX);\n            this.top = pos.scaleY + (offset.top / this.scale - this._offsetY);\n        }\n        this._applyDomPos(this.left, this.top);\n    }\n\n    commentPosition({ startX = 0, startY = 0 } = {}) {\n        const view = this._view;\n        if (!view) {\n            return;\n        }\n        const pos = view.getAbsoluteCoordinate();\n        const offset = view.board.offset();\n        this.left = pos.scaleX + (offset.left / this.scale - this._offsetX) - this.originalX;\n        this.top = pos.scaleY + (offset.top / this.scale - this._offsetY) - this.originalY;\n        const [line] = this.svgGroup.getElementsByTagName('line');\n        if (line) {\n            line.setAttribute('x1', startX / this.scale - this.left + view.parentWidth);\n            line.setAttribute('y1', startY / this.scale - this.top + view.parentHeight / 2);\n        }\n        this._applyDomPos(this.left, this.top);\n    }\n\n    adjust(adjustX, adjustY) {\n        const left = this.left + (adjustX || 0);\n        const top = this.top + (adjustY || 0);\n        if (left === this.left && top === this.top) {\n            return;\n        }\n\n        this.left = left;\n        this.top = top;\n        this._applyDomPos(this.left, this.top);\n    }\n\n    _applyDomPos(left, top) {\n        this.svgDom.css({\n            transform: `scale(${this.scale}) translate3d(${left + this.xScaleDiff}px,${top +\n                this.yscaleDiff}px, 0px)`,\n        });\n    }\n\n    terminateDrag(blockView) {\n        const mousePos = Entry.mouseCoordinate;\n        const board = blockView.getBoard();\n        const blockMenu = board.workspace.blockMenu;\n        const bLeft = blockMenu.offset().left;\n        const bTop = blockMenu.offset().top;\n        const bWidth = blockMenu.visible ? blockMenu.blockMenuContainer.width() : 0;\n\n        let backPackWidth = 0;\n        const windowWidth = window.innerWidth;\n        const backPackMode = Entry.playground.backPack.isShow;\n        if (backPackMode) {\n            backPackWidth = 135;\n        }\n\n        if (\n            mousePos.y > board.offset().top - 20 &&\n            mousePos.x > bLeft + bWidth &&\n            mousePos.x < windowWidth - backPackWidth\n        ) {\n            return this.DONE;\n        } else if (\n            mousePos.y > bTop &&\n            mousePos.x > bLeft &&\n            mousePos.x <= bLeft + bWidth &&\n            blockMenu.visible\n        ) {\n            if (blockView.block && !blockView.block.isDeletable()) {\n                return this.RETURN;\n            } else {\n                return this.REMOVE;\n            }\n        } else {\n            return this.RETURN;\n        }\n    }\n\n    addControl(...args) {\n        this.onMouseDown(...args);\n    }\n\n    onMouseDown(e) {\n        this._startY = e.pageY;\n        const that = this;\n        e.stopPropagation();\n        e.preventDefault();\n        if (e.which == 2) {\n            console.log('mouse wheel click disabled');\n            return;\n        }\n        const $doc = $(document);\n        $doc.bind('mousemove.block', onMouseMove);\n        $doc.bind('mouseup.block', onMouseUp);\n        $doc.bind('touchmove.block', onMouseMove);\n        $doc.bind('touchend.block', onMouseUp);\n        this._startX = e.pageX;\n        this._startY = e.pageY;\n\n        function onMouseMove(e) {\n            const newX = e.pageX;\n            const newY = e.pageY;\n            const dX = newX - that._startX;\n            const dY = newY - that._startY;\n            const newLeft = that.left + dX;\n            const newTop = that.top + dY;\n            that._applyDomPos(newLeft, newTop);\n            that._startX = newX;\n            that._startY = newY;\n            that.left = newLeft;\n            that.top = newTop;\n        }\n\n        function onMouseUp(e) {\n            if (e.which == 2) {\n                console.log('mouse wheel click disabled');\n                return;\n            }\n            $(document).unbind('.block');\n        }\n    }\n\n    setScale(scale = 1) {\n        this.scale = scale;\n    }\n\n    getRelativePoint(matrix) {\n        return this.svgPoint.matrixTransform(matrix);\n    }\n}\n\nEntry.GlobalSvg = new GlobalSvg();\n"
  },
  {
    "path": "src/playground/mutator.js",
    "content": "/*\n *\n */\n'use strict';\n\n/*\n *\n */\nEntry.Mutator = function() {};\n\n(function(m) {\n    m.mutate = function(blockType, schemaDiff, changeData) {\n        var blockSchema = Entry.block[blockType];\n        if (blockSchema.changeEvent === undefined) blockSchema.changeEvent = new Entry.Event();\n        if (blockSchema.paramsBackupEvent === undefined)\n            blockSchema.paramsBackupEvent = new Entry.Event();\n        if (blockSchema.destroyParamsBackupEvent === undefined)\n            blockSchema.destroyParamsBackupEvent = new Entry.Event();\n\n        //statements params template\n        if (schemaDiff.template) {\n            blockSchema.template = schemaDiff.template;\n        }\n        if (schemaDiff.params) {\n            blockSchema.params = schemaDiff.params;\n        }\n\n        blockSchema.changeEvent.notify(1, changeData);\n    };\n})(Entry.Mutator);\n\n(function(p) {})(Entry.Mutator.prototype);\n"
  },
  {
    "path": "src/playground/renderView.js",
    "content": "'use strict';\n\nEntry.RenderView = class RenderView {\n    schema = {\n        code: null,\n        dragBlock: null,\n        closeBlock: null,\n        selectedBlockView: null,\n    };\n\n    constructor(dom, align, scale, parserType) {\n        this._align = align || 'CENTER';\n\n        if (typeof dom === 'string') {\n            dom = $(`#${dom}`);\n        } else {\n            dom = $(dom);\n        }\n\n        if (dom.prop('tagName') !== 'DIV') {\n            return console.error('Dom is not div element');\n        }\n\n        this.view = dom;\n        this.viewOnly = true;\n        this.suffix = 'renderView';\n        this._scale = scale === undefined ? 1 : scale;\n\n        this._parserType = parserType;\n\n        this.visible = true;\n        this.disableMouseEvent = true;\n        this._svgId = `renderView_${new Date().getTime()}`;\n        this._generateView();\n\n        this.offset = this.svgDom.offset();\n        this._minBlockOffsetX = 0;\n        this._setSize();\n\n        this.svg = Entry.SVG(this._svgId, this.svgDom[0]);\n        Entry.Utils.addFilters(this.svg, this.suffix, true);\n\n        if (this.svg) {\n            this.svgGroup = this.svg.elem('g');\n\n            this.svgThreadGroup = this.svgGroup.elem('g');\n            this.svgThreadGroup.board = this;\n\n            this.svgBlockGroup = this.svgGroup.elem('g');\n            this.svgBlockGroup.board = this;\n\n            this.svgCommentGroup = this.svgGroup.elem('g');\n            this.svgCommentGroup.board = this;\n        }\n    }\n\n    _generateView() {\n        const parent = this.view;\n\n        this.renderViewContainer = Entry.Dom('div', {\n            class: 'renderViewContainer',\n            parent,\n        });\n\n        this.svgDom = Entry.Dom(\n            $(\n                `<svg id=\"${\n                    this._svgId\n                }\" class=\"renderView\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"></svg>`\n            ),\n            { parent: this.renderViewContainer }\n        );\n    }\n\n    changeCode(code, resizeImmediately) {\n        if (!(code instanceof Entry.Code)) {\n            return console.error('You must inject code instance');\n        }\n        this.code = code;\n\n        if (!this.svg) {\n            this.svg = Entry.SVG(this._svgId, this.svgDom[0]);\n            this.svgGroup = this.svg.elem('g');\n\n            this.svgThreadGroup = this.svgGroup.elem('g');\n            this.svgThreadGroup.board = this;\n\n            this.svgBlockGroup = this.svgGroup.elem('g');\n            this.svgBlockGroup.board = this;\n\n            this.svgCommentGroup = this.svgGroup.elem('g');\n            this.svgCommentGroup.board = this;\n        }\n\n        code.createView(this);\n        this.align();\n        this.resize(resizeImmediately);\n    }\n\n    align() {\n        const threads = this.code.getThreads();\n        if (!threads || threads.length === 0) {\n            return;\n        }\n        const vPadding = 15;\n        let marginFromTop = 0;\n        const hPadding = this._getHorizontalPadding();\n\n        for (let i = 0, len = threads.length; i < len; i++) {\n            const thread = threads[i];\n            const block = thread.getFirstBlock();\n            const blockView = block.view;\n\n            const height = blockView.svgGroup.getBBox().height;\n            let xPos = 0;\n            const extensions = $(blockView.svgGroup).find('.extension');\n            if (extensions) {\n                for (let j = 0; j < extensions.length; j++) {\n                    const ext = extensions[j];\n                    const currentXpos = parseFloat(ext.getAttribute('x'));\n                    xPos = Math.min(xPos, currentXpos);\n                }\n            }\n            this._minBlockOffsetX = Math.min(this._minBlockOffsetX, blockView.offsetX);\n            blockView.moveTo(\n                hPadding - xPos - blockView.offsetX,\n                marginFromTop - blockView.offsetY,\n                false\n            );\n            marginFromTop += height + vPadding;\n        }\n        this._setSize();\n    }\n\n    hide() {\n        this.view.addClass('entryRemove');\n    }\n\n    show() {\n        this.view.removeClass('entryRemove');\n    }\n\n    _setSize() {\n        if (this.svgDom) {\n            this._svgWidth = this.svgDom.width();\n            this.offset = this.svgDom.offset();\n        }\n        if (this.svgGroup) {\n            this._bBox = this.svgGroup.getBBox();\n        }\n    }\n\n    bindCodeView(codeView) {\n        this.svgBlockGroup.remove();\n        this.svgThreadGroup.remove();\n        this.svgBlockGroup = codeView.svgBlockGroup;\n        this.svgThreadGroup = codeView.svgThreadGroup;\n        this.svgCommentGroup = codeView.svgCommentGroup;\n        this.svgGroup.appendChild(this.svgThreadGroup);\n        this.svgGroup.appendChild(this.svgBlockGroup);\n        this.svgGroup.appendChild(this.svgCommentGroup);\n    }\n\n    resize(isImmediate) {\n        if (!this.svg || !this._bBox) {\n            return;\n        }\n\n        if (isImmediate) {\n            run.call(this);\n        } else {\n            setTimeout(\n                function() {\n                    run.call(this);\n                }.bind(this),\n                0\n            );\n        }\n\n        function run() {\n            this._setSize();\n            const width = Math.round(this._bBox.width);\n            const height = Math.round(this._bBox.height);\n            //svg is not on the screen\n            if (width === 0 || height === 0) {\n                return;\n            }\n\n            $(this.svg).css({\n                width: width + this._getHorizontalPadding() - this._minBlockOffsetX + 5,\n                height: height + 5,\n            });\n\n            //double check\n            setTimeout(\n                function() {\n                    const bBox = this.svgGroup.getBBox();\n                    if (Math.round(bBox.width) !== width || Math.round(bBox.height) !== height) {\n                        this.resize();\n                    }\n                }.bind(this),\n                1000\n            );\n        }\n    }\n\n    setDomSize(isImmediate) {\n        if (this.svgBlockGroup) {\n            this.svgBlockGroup.attr('transform', 'scale(1)');\n        }\n        this.code.view.reDraw();\n        this.align();\n        this.resize(isImmediate);\n        if (this._scale !== 1) {\n            window.setTimeout(\n                function() {\n                    this.svgBlockGroup.attr(\n                        'transform',\n                        'scale(%scale)'.replace('%scale', this._scale)\n                    );\n                    this.align();\n                    this.resize();\n                }.bind(this),\n                0\n            );\n        }\n    }\n\n    _getHorizontalPadding() {\n        const marginMap = {\n            LEFT: 20,\n            LEFT_MOST: 0,\n        };\n        const ret = marginMap[this._align];\n\n        return ret !== undefined ? ret : this.svgDom.width() / 2;\n    }\n\n    getBlockSyntax(block, renderMode) {\n        let syntax = null;\n        if (renderMode === 2) {\n            if (!this._parser) {\n                this._parser = new Entry.Parser(null, null);\n            }\n            this._parser.setParser(1, this._parserType);\n            if (this._parser._execParser) {\n                syntax = this._parser._execParser.searchSyntax(block);\n            }\n        }\n\n        return syntax;\n    }\n\n    setParserType(parserType) {\n        this._parserType = parserType;\n    }\n};\n"
  },
  {
    "path": "src/playground/scope.js",
    "content": "'use strict';\n\nclass Scope {\n    constructor(block, executor) {\n        this.block = block;\n        this.type = block ? block.type : null; //legacy\n        this.executor = executor;\n        this.entity = executor.entity;\n    }\n\n    callReturn() {\n        return undefined;\n    }\n\n    getParam(index) {\n        const param = this.block.params[index];\n        if (param instanceof Entry.Block) {\n            const newScope = new Entry.Scope(param, this.executor);\n            const result = newScope.run(this.entity, true);\n            return result;\n        } else {\n            return this.filterReservedKeywords(param);\n        }\n    }\n\n    // 클래스 레벨에서 한 번만 생성\n    static _reservedKeywords = new Set(['__proto__']);\n\n    filterReservedKeywords(param) {\n        return Scope._reservedKeywords.has(param) ? '' : param;\n    }\n\n    getParams() {\n        return this.block.params.map((param) => {\n            if (param instanceof Entry.Block) {\n                const fieldBlock = param;\n                const newScope = new Entry.Scope(fieldBlock, this.executor);\n                return newScope.run(this.entity, true);\n            } else {\n                return this.filterReservedKeywords(param);\n            }\n        });\n    }\n\n    _setBlockState(fieldBlock, valueState) {\n        const newScope = new Entry.Scope(fieldBlock, this.executor);\n        const result = Entry.block[fieldBlock.type].func.call(newScope, this.entity, newScope);\n        const blockId = fieldBlock.data.id;\n\n        if (result instanceof Promise) {\n            if (valueState[blockId].state === 'pending') {\n                throw new Entry.Utils.AsyncError();\n            }\n            valueState[blockId].state = 'pending';\n            result.then((value) => {\n                valueState[blockId].state = 'complete';\n                valueState[blockId].value = value;\n            });\n        } else {\n            valueState[blockId].state = 'complete';\n            valueState[blockId].value = result;\n        }\n    }\n\n    _setChildBlockState(fieldBlocks, currentBlockId) {\n        const valueState = this.executor.valueState || {};\n\n        let hasPending = false;\n        if (valueState[currentBlockId].state === 'wait') {\n            fieldBlocks.forEach((fieldBlock) => {\n                const blockId = fieldBlock.data.id;\n                valueState[blockId] = valueState[blockId] || { state: 'wait' };\n                if (valueState[blockId].state === 'wait') {\n                    this._setBlockState(fieldBlock, valueState);\n                }\n                hasPending = hasPending || valueState[blockId].state === 'pending';\n            });\n        }\n\n        if (hasPending && valueState[currentBlockId].state === 'wait') {\n            valueState[currentBlockId].state = 'pending';\n            throw new Entry.Utils.AsyncError();\n        }\n    }\n\n    getValues(keys, scope) {\n        return keys.map((key) => this.values[this._getParamIndex(key, scope)]);\n    }\n\n    getValue(key, scope) {\n        return this.values[this._getParamIndex(key, scope)];\n    }\n\n    /**\n     * 일반 getValue 값을 가져오기 전,\n     * 현 Scope 상태에서의 executor.valueMap 을 세팅한다.\n     * 이 로직은 Promise.all[] 과 유사하며, 모든 값이 준비될 때까지 Scope 를 멈춘다.\n     * @param{Array} fieldBlocks getValue 에 의한 호출의 경우 1, getValues 의 경우 1 이상\n     */\n    _setExecutorValueMap(fieldBlocks) {\n        const executorValueMap = this.executor.valueMap;\n\n        fieldBlocks.forEach((block) => {\n            const blockId = block.data.id;\n\n            if (executorValueMap[blockId] === 'isPending') {\n                throw new Entry.Utils.AsyncError();\n            } else if (\n                executorValueMap[blockId] &&\n                executorValueMap[blockId].name === 'IncompatibleError'\n            ) {\n                throw executorValueMap[blockId];\n            } else if (executorValueMap[blockId] !== undefined) {\n                return executorValueMap[blockId];\n            }\n\n            const newScope = new Entry.Scope(block, this.executor);\n            const result = Entry.block[block.type].func.call(newScope, this.entity, newScope);\n\n            if (result instanceof Promise) {\n                executorValueMap[blockId] = 'isPending';\n                result.then((value) => {\n                    executorValueMap[blockId] = value;\n                });\n                throw new Entry.Utils.AsyncError();\n            } else {\n                executorValueMap[blockId] = result;\n            }\n        });\n    }\n\n    getStringValue(key, scope) {\n        return String(this.getValue(key, scope));\n    }\n\n    getNumberValue(key, scope) {\n        return parseFloat(this.getValue(key, scope)) || 0;\n    }\n\n    getBooleanValue(key, scope) {\n        let value = this.getValue(key, scope);\n        if (value === undefined) {\n            return false;\n        }\n        value = Number(value);\n        return isNaN(value) ? true : value; // handle \"0\" or \"0.00\"\n    }\n\n    getField(key) {\n        return this.filterReservedKeywords(this.block.params[this._getParamIndex(key)]);\n    }\n\n    getStringField(key) {\n        return String(this.getField(key));\n    }\n\n    getNumberField(key) {\n        return Number(this.getField(key));\n    }\n\n    getStatement(key, scope) {\n        return this.executor.stepInto(this.block.statements[this._getStatementIndex(key, scope)]);\n    }\n\n    _getParamIndex(key) {\n        if (!this._schema) {\n            this._schema = Entry.block[this.type];\n        }\n        return this._schema.paramsKeyMap[key];\n    }\n\n    _getStatementIndex(key) {\n        if (!this._schema) {\n            this._schema = Entry.block[this.type];\n        }\n        return this._schema.statementsKeyMap[key];\n    }\n\n    die() {\n        this.block = null;\n        return Entry.STATIC.BREAK;\n    }\n\n    run(entity, isValue) {\n        const schema = this.block.getSchema();\n        if (this.isCondition) {\n            return schema.func.call(this, entity, this);\n        }\n        const values = this.getParams();\n        const isPromise = values.some((value) => value instanceof Promise);\n        if (!schema.func) {\n            return;\n        }\n\n        if (!isPromise) {\n            this.values = values;\n            return schema.func.call(this, entity, this);\n        } else {\n            return Promise.all(values).then(async (values) => {\n                if (Entry.engine.state !== 'stop' && this.block) {\n                    this.values = values;\n                    return await schema.func.call(this, entity, this);\n                }\n            });\n        }\n    }\n}\n\nEntry.Scope = Scope;\n"
  },
  {
    "path": "src/playground/scroll.js",
    "content": "import debounce from 'lodash/debounce';\n\nEntry.Scroller = class Scroller {\n    get SCROLL_WIDTH() {\n        return 8;\n    }\n    get RADIUS() {\n        return 2.5;\n    }\n    get MARGIN() {\n        return 40;\n    }\n    constructor(board, horizontal, vertical) {\n        this._horizontal = horizontal === undefined ? true : horizontal;\n        this._vertical = vertical === undefined ? true : vertical;\n\n        this.board = board;\n        this.canRAF = true;\n\n        this.svgGroup = null;\n\n        this.hWidth = 0;\n        this.hX = 0;\n        this.hRatio = 0;\n        this.vWidth = 0;\n        this.vY = 0;\n        this.vRatio = 0;\n        this._visible = true;\n        this._opacity = -1;\n\n        this.createScrollBar();\n        this.setOpacity(0);\n\n        this._bindEvent();\n\n        this._scrollCommand = debounce(Entry.do, 200);\n    }\n\n    onMouseMove = (e) => {\n        console.log('onMouseMove');\n        e.stopPropagation();\n        e.preventDefault();\n\n        if (window.TouchEvent && e instanceof window.TouchEvent) {\n            e = e.changedTouches[0];\n        }\n        const dragInstance = this.dragInstance;\n        if (this.scrollType === 'horizontal') {\n            this.scroll((-e.pageX + dragInstance.offsetX) / this.hRatio, 0);\n        } else {\n            this.scroll(0, (-e.pageY + dragInstance.offsetY) / this.vRatio);\n        }\n        dragInstance.set({\n            offsetX: e.pageX,\n            offsetY: e.pageY,\n        });\n    };\n\n    onMouseUp = (e) => {\n        if (e.which == 2) {\n            console.log('mouse wheel click disabled');\n            return;\n        }\n        console.log('onMouseUp');\n        this.removeEventListener(document, ['mousemove', 'touchmove'], this.onMouseMove);\n        this.removeEventListener(document, ['mouseup', 'touchend'], this.onMouseUp);\n        delete this.dragInstance;\n        delete this.scrollType;\n    };\n\n    onMouseDown = (e) => {\n        if (e.which == 2) {\n            console.log('mouse wheel click disabled');\n            return;\n        }\n        console.log('onMouseDown', e.button, e);\n        if (e.button === 0 || e instanceof window.TouchEvent) {\n            console.log('go into add event');\n            this.scrollType = e.target.type;\n            if (Entry.documentMousedown) {\n                Entry.documentMousedown.notify(e);\n            }\n            this.addEventListener(document, ['mousemove', 'touchmove'], this.onMouseMove, {\n                passive: false,\n            });\n            this.addEventListener(document, ['mouseup', 'touchend'], this.onMouseUp);\n            this.dragInstance = new Entry.DragInstance({\n                startX: e.pageX,\n                startY: e.pageY,\n                offsetX: e.pageX,\n                offsetY: e.pageY,\n            });\n        }\n        e.stopPropagation();\n    };\n\n    addEventListener(dom, event = [], func, option) {\n        event.forEach((e) => {\n            dom.addEventListener(e, func, option);\n        });\n    }\n    removeEventListener(dom, event = [], func) {\n        event.forEach((e) => {\n            dom.removeEventListener(e, func);\n        });\n    }\n\n    createScrollBar() {\n        const r = this.RADIUS;\n        const { common = {} } = EntryStatic.colorSet || {};\n        this.svgGroup = this.board.svg.elem('g').attr({ class: 'boardScrollbar' });\n\n        if (this._horizontal) {\n            this.hScrollbar = this.svgGroup.elem('rect', {\n                height: this.SCROLL_WIDTH,\n                rx: r,\n                ry: r,\n                fill: common.SCROLL_BAR || '#aac5d5',\n                class: 'scrollbar horizontal',\n            });\n            this.hScrollbar.type = 'horizontal';\n            this.addEventListener(this.hScrollbar, ['touchstart', 'mousedown'], this.onMouseDown);\n        }\n\n        if (this._vertical) {\n            this.vScrollbar = this.svgGroup.elem('rect', {\n                width: this.SCROLL_WIDTH,\n                rx: r,\n                ry: r,\n                fill: common.SCROLL_BAR || '#aac5d5',\n                class: 'scrollbar vertical',\n            });\n            this.vScrollbar.type = 'vertical';\n            this.addEventListener(this.vScrollbar, ['touchstart', 'mousedown'], this.onMouseDown);\n        }\n    }\n\n    updateScrollBar(dx, dy) {\n        if (this._horizontal) {\n            this.hX -= dx * this.hRatio;\n            this.hScrollbar.attr({\n                x: this.hX || 0,\n            });\n        }\n\n        if (this._vertical) {\n            this.vY -= dy * this.vRatio;\n            this.vScrollbar.attr({\n                y: this.vY,\n            });\n        }\n    }\n\n    scroll(x, y, skipCommand) {\n        if (!this.board.code) {\n            return;\n        }\n\n        const board = this.board;\n        const svgRect = board.getSvgDomRect();\n        const clientRect = board.svgBlockGroup.getBoundingClientRect();\n        const bBox = {\n            x: clientRect.left - this.board.offset().left,\n            y: clientRect.top - this.board.offset().top,\n            width: clientRect.width,\n            height: clientRect.height,\n        };\n\n        const sWidth = svgRect.width;\n        const sHeight = svgRect.height;\n\n        if (bBox.width && bBox.height) {\n            if (sWidth / 2 > bBox.width) {\n                x = Math.max(-bBox.x + 1, x);\n                x = Math.min(sWidth - bBox.width - bBox.x - 1, x);\n            } else {\n                x = Math.max(sWidth / 2 - bBox.x - bBox.width, x);\n                x = Math.min(sWidth / 2 - bBox.x, x);\n            }\n            if (sHeight / 2 > bBox.height) {\n                y = Math.max(-bBox.y + 1, y);\n                y = Math.min(sHeight - bBox.height - bBox.y - 1, y);\n            } else {\n                y = Math.max(sHeight / 2 - bBox.y - bBox.height, y);\n                y = Math.min(sHeight / 2 - bBox.y, y);\n            }\n        }\n\n        this._scroll(x, y);\n        if (skipCommand !== true) {\n            if (!this._diffs) {\n                this._diffs = [0, 0];\n            }\n\n            this._diffs[0] += x;\n            this._diffs[1] += y;\n\n            this._scrollCommand('scrollBoard', this._diffs[0], this._diffs[1], true);\n        }\n\n        this.canRAF = true;\n    }\n\n    _scroll(x, y) {\n        this.board.code.moveBy(x, y);\n        this.updateScrollBar(x, y);\n    }\n\n    setVisible(visible) {\n        if (visible == this.isVisible()) {\n            return;\n        }\n        this._visible = visible;\n        this.svgGroup.attr({\n            display: visible === true ? 'block' : 'none',\n        });\n    }\n\n    isVisible() {\n        return this._visible;\n    }\n\n    setOpacity(value) {\n        if (this._opacity == value) {\n            return;\n        }\n        this.hScrollbar.attr({ opacity: value });\n        this.vScrollbar.attr({ opacity: value });\n\n        this._opacity = value;\n    }\n\n    resizeScrollBar() {\n        if (!this._visible) {\n            return;\n        }\n\n        const board = this.board;\n        const offset = board.offset();\n        const svgRect = board.getSvgDomRect();\n        const bRect = board.svgBlockGroup.getBoundingClientRect();\n        const width = svgRect.width;\n        const height = svgRect.height;\n        const bBox = {\n            x: bRect.left - offset.left,\n            y: bRect.top - offset.top,\n            width: bRect.width,\n            height: bRect.height,\n        };\n\n        // hScroll\n        if (this._horizontal) {\n            const sWidth = svgRect.width;\n            const marginSWitdh = svgRect.width - this.MARGIN;\n            let limit = sWidth;\n            let ratio = 0.6;\n            let hWidth = 0;\n            if (sWidth / 2 > bBox.width) {\n                limit = sWidth - bBox.width;\n                ratio = Math.min(limit / marginSWitdh, ratio);\n                hWidth = marginSWitdh * ratio;\n                this.hRatio = (marginSWitdh - hWidth) / limit;\n                this.hX = marginSWitdh + this.MARGIN / 2 - hWidth - bBox.x * this.hRatio;\n            } else {\n                limit = bBox.width;\n                ratio = Math.min(marginSWitdh / limit, ratio);\n                hWidth = marginSWitdh * ratio;\n                this.hRatio = (marginSWitdh - hWidth) / limit;\n                this.hX = (sWidth / 2 - bBox.x) * this.hRatio + this.MARGIN / 2;\n            }\n            this.hScrollbar.attr({\n                width: hWidth,\n                x: this.hX,\n                y: height - 2 * this.SCROLL_WIDTH,\n            });\n        }\n\n        // vScroll\n        if (this._vertical) {\n            const sHeight = svgRect.height;\n            const marginSHeight = svgRect.height - this.MARGIN;\n            let limit = height;\n            let ratio = 0.6;\n            let vHeight = 0;\n            if (sHeight / 2 > bBox.height) {\n                limit = sHeight - bBox.height;\n                ratio = Math.min(limit / marginSHeight, ratio);\n                vHeight = marginSHeight * ratio;\n                this.vRatio = (marginSHeight - vHeight) / limit;\n                this.vY = marginSHeight + this.MARGIN / 2 - vHeight - bBox.y * this.vRatio;\n            } else {\n                limit = bBox.height;\n                ratio = Math.min(marginSHeight / limit, ratio);\n                vHeight = marginSHeight * ratio;\n                this.vRatio = (marginSHeight - vHeight) / limit;\n                this.vY = (sHeight / 2 - bBox.y) * this.vRatio + this.MARGIN / 2;\n            }\n\n            this.vScrollbar.attr({\n                height: vHeight,\n                y: this.vY,\n                x: width - 2 * this.SCROLL_WIDTH,\n            });\n        }\n    }\n\n    _bindEvent() {\n        const dResizeScrollBar = debounce(this.resizeScrollBar, 250);\n        this.board.changeEvent.attach(this, dResizeScrollBar);\n        if (Entry.windowResized) {\n            Entry.windowResized.attach(this, dResizeScrollBar);\n        }\n    }\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic.ts",
    "content": "Entry.skeleton.basic = {\n    executable: true,\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(28, height + 2);\n        width = Math.max(0, width + 6 - height / 2);\n        const halfHeight = height / 2;\n        return `M 0 0\n        l 6 6\n        l 6 -6\n        h ${width}\n        a ${halfHeight} ${halfHeight} 0 0 1 0 ${height}\n        h -${width}\n        l -6 6\n        l -6 -6\n        z`;\n    },\n    box(blockView) {\n        const width = blockView ? blockView.contentWidth : 150;\n        const height = blockView ? blockView.contentHeight : 28;\n        return {\n            offsetX: -8,\n            offsetY: 0,\n            width: width + 30,\n            height: Math.max(28, height + 2),\n            marginBottom: 0,\n        };\n    },\n    magnets(blockView) {\n        // apply scale required.\n        const height = blockView ? Math.max(blockView.height, 28) : 28;\n        return {\n            previous: { x: 0, y: 0 },\n            next: { x: 0, y: height + blockView.offsetY },\n        };\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight, 28);\n        return { x: 14, y: height / 2 };\n    },\n};\n\nEntry.skeleton.basic_without_next = {\n    executable: true,\n    outerLine: '#13bf68',\n    box: Entry.skeleton.basic.box,\n    contentPos: Entry.skeleton.basic.contentPos,\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(28, height + 2);\n        width = Math.max(0, width + 6 - height / 2);\n        const halfHeight = height / 2;\n\n        return `m 0 0\n        l 6 6\n        l 6 -6\n        h ${width}\n        a ${halfHeight} ${halfHeight} 0 0 1 0 ${height}\n        H 0\n        z`;\n    },\n    magnets() {\n        return {\n            previous: { x: 0, y: 0 },\n        };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_boolean_field.ts",
    "content": "Entry.skeleton.basic_boolean_field = {\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(20, height);\n        width = Math.max(0, width - height + 19);\n        const halfHeight = height / 2;\n        const x = height * 0.4;\n\n        return `m ${halfHeight} 0\n                l -${x} ${halfHeight}\n                l ${x} ${halfHeight}\n                h ${width}\n                l ${x} -${halfHeight}\n                l -${x} -${halfHeight}\n                z`;\n    },\n    color: '#FFF',\n    outerLine: '#1b3ad8',\n    fontSize: 10,\n    box(blockView) {\n        const width = blockView ? blockView.contentWidth : 5;\n        const height = blockView ? blockView.contentHeight : 18;\n        return {\n            offsetX: 0,\n            offsetY: 0,\n            width: width + 19,\n            height: Math.max(height, 20),\n            marginBottom: 0,\n        };\n    },\n    magnets() {\n        return {\n            boolean: {},\n        };\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight, 20);\n        return { x: 10, y: height / 2 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_button.ts",
    "content": "Entry.skeleton.basic_button = {\n    path() {\n        return `m 6 0\n            h 150\n            a 6 6 0 0 1 6 6\n            v 28\n            a 6 6 0 0 1 -6 6\n            h -150\n            a 6 6 0 0 1 -6 -6\n            v -28\n            a 6 6 0 0 1 6 -6\n            z`;\n    },\n    box() {\n        return {\n            offsetX: -5,\n            offsetY: 0,\n            width: 162,\n            height: 40,\n            marginBottom: 3,\n        };\n    },\n    contentPos() {\n        // apply scale required.\n        return { x: 81, y: 20 };\n    },\n    movable: false,\n    readOnly: true,\n    nextShadow: true,\n    fontSize: 14,\n    classes: ['basicButtonView'],\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_button_disabled.ts",
    "content": "Entry.skeleton.basic_button_disabled = {\n    path() {\n        return `m 6 0\n            h 150\n            a 6 6 0 0 1 6 6\n            v 28\n            a 6 6 0 0 1 -6 6\n            h -150\n            a 6 6 0 0 1 -6 -6\n            v -28\n            a 6 6 0 0 1 6 -6\n            z`;\n    },\n    box() {\n        return {\n            offsetX: -5,\n            offsetY: 0,\n            width: 162,\n            height: 40,\n            marginBottom: 3,\n        };\n    },\n    contentPos() {\n        // apply scale required.\n        return { x: 81, y: 20 };\n    },\n    movable: false,\n    readOnly: true,\n    nextShadow: true,\n    fontSize: 14,\n    classes: ['basicButtonDisabledView'],\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_create.ts",
    "content": "Entry.skeleton.basic_create = {\n    executable: true,\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(28, height);\n        width = Math.max(0, width + 4);\n        let statementHeight = blockView._statements[0] ? blockView._statements[0].height : 20;\n        statementHeight = Math.max(statementHeight, 20);\n        const bw = width - 20;\n        const halfHeight = height / 2;\n\n        return `m 0 0\n        V 1\n        h ${width}\n        a ${halfHeight} ${halfHeight} 0 0 1 0 ${height}\n        H 26\n        l -6 6\n        l -6 -6\n        v ${statementHeight}\n        l 6 6\n        l 6 -6\n        h ${bw}\n        a 7.5 7.5 0 0 1 0 15\n        H 0\n        z`;\n    },\n    magnets(blockView) {\n        return {};\n    },\n    box(blockView) {\n        const width = blockView ? blockView.contentWidth : 150;\n        const height = blockView ? blockView.contentHeight : 28;\n        return {\n            offsetX: -8,\n            offsetY: 0,\n            width: width + 30,\n            height: Math.max(30, height + 2),\n            marginBottom: 0,\n        };\n    },\n    statementPos(blockView) {\n        const height1 = Math.max(30, (blockView.contentHeight % 1000000) + 2) + 1;\n        return [{ x: 14, y: height1 - 3 }];\n    },\n    contentPos(blockView) {\n        const height = Math.max(blockView.contentHeight % 1000000, 28);\n        return { x: 14, y: height / 2 + 1 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_create_value.ts",
    "content": "import _take from 'lodash/take';\nimport _takeRight from 'lodash/takeRight';\n\nconst getFirstBoxWidth = (blockView: any): number => {\n    const contents = _take(blockView._contents, 3);\n    return contents.reduce<number>((acc, content: any) => acc + content.box.width, 20);\n};\n\nconst getSecondBoxWidth = (blockView: any): number => {\n    const contents = _takeRight(blockView._contents, 3);\n    return contents.reduce<number>((acc, content: any) => acc + content.box.width, 20);\n};\n\nEntry.skeleton.basic_create_value = {\n    executable: true,\n    path(blockView) {\n        let height = blockView.contentHeight % 1000000;\n        height = Math.max(30, height + 2);\n        const statements = blockView._statements;\n        let statementHeight = statements[0] ? statements[0].height : 20;\n        const halfHeight = height / 2;\n\n        statementHeight = Math.max(statementHeight, 20);\n\n        return `M 0 0                \n                V 1\n                h ${getFirstBoxWidth(blockView)}\n                a 14 14 0 0 1 0 28\n                H 26\n                l -6 6\n                l -6 -6\n                v ${statementHeight}\n                l 6 6\n                l 6 -6\n                h ${getSecondBoxWidth(blockView) - 15}\n                a ${halfHeight} ${halfHeight} 0 0 1 0 ${height}\n                H 0\n                z`;\n    },\n    magnets(blockView) {\n        return {};\n    },\n    box(blockView) {\n        const width = blockView ? blockView.contentWidth : 150;\n        const height = blockView ? blockView.height : 28;\n        return {\n            offsetX: -8,\n            offsetY: 0,\n            width: width + 30,\n            height: Math.max(30, height),\n            marginBottom: 0,\n        };\n    },\n    statementPos(blockView) {\n        const height1 = Math.max(30, (blockView.contentHeight % 1000000) + 2) + 1;\n        return [{ x: 14, y: height1 - 3 }];\n    },\n    contentPos(blockView) {\n        const height = Math.max(blockView.contentHeight % 1000000, 28);\n        return { x: 14, y: height / 2 + 1 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_define.ts",
    "content": "Entry.skeleton.basic_define = {\n    executable: true,\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(30, height + 2);\n        width = Math.max(0, width + 9 - height / 2);\n        let statementHeight = blockView._statements[0] ? blockView._statements[0].height : 30;\n        statementHeight = Math.max(statementHeight, 20);\n        return (\n            'm -8,0 l 16,0 h %w a %h,%h 0 0,1 0,%wh H 24 l -8,8 -8,-8 h -0.4 v' +\n            '%sh h 0.4 l 8,8 8,-8 h %bw a 8,8 0 0,1 0,16 H -8 z'\n        )\n            .replace(/%wh/gi, height)\n            .replace(/%w/gi, width)\n            .replace(/%h/gi, (height / 2) as any) // TODO blockView 인터페이스 완성시 삭제\n            .replace(/%bw/gi, (width - 8) as any)\n            .replace(/%sh/gi, statementHeight + 1);\n    },\n    magnets() {\n        return {};\n    },\n    box(blockView) {\n        const contentWidth = blockView.contentWidth;\n        const contentHeight = Math.max(blockView.contentHeight, 25);\n        return {\n            offsetX: 0,\n            offsetY: 0,\n            width: contentWidth,\n            height: contentHeight + 46,\n            marginBottom: 0,\n        };\n    },\n    statementPos(blockView) {\n        const height = Math.max(30, blockView.contentHeight + 2);\n        return [\n            {\n                x: 16,\n                y: height,\n            },\n        ];\n    },\n    contentPos() {\n        // apply scale required.\n        return { x: 14, y: 15 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_double_loop.ts",
    "content": "Entry.skeleton.basic_double_loop = {\n    executable: true,\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height1 = blockView.contentHeight % 1000000;\n        height1 = Math.max(30, height1 + 2);\n        width = Math.max(0, width + 2 - height1 / 2);\n        const statements = blockView._statements;\n        let statementHeight1 = statements[0] ? statements[0].height : 20;\n        let statementHeight2 = statements[1] ? statements[1].height : 20;\n        const bw = width - 8;\n\n        statementHeight1 = Math.max(statementHeight1, 20);\n        statementHeight2 = Math.max(statementHeight2, 20);\n\n        return `m 0 0\n        l 6 6\n        l 6 -6\n        h ${width}\n        a 14 14 0 0 1 0 28\n        H 26\n        l -6 6\n        l -6 -6\n        v ${statementHeight1}\n        l 6 6\n        l 6 -6\n        h ${bw - 6}\n        a 14 14 0 0 1 0 28\n        H 26\n        l -6 6\n        l -6 -6\n        v ${statementHeight2}\n        l 6 6\n        l 6 -6\n        h ${bw}\n        a 7.5 7.5 0 0 1 0 15\n        H 12\n        l -6 6\n        l -6 -6\n        z`;\n    },\n    magnets(blockView) {\n        const contentHeight1 = Math.max((blockView.contentHeight % 1000000) + 2, 30);\n        const contentHeight2 = Math.max(Math.floor(blockView.contentHeight / 1000000) + 2, 30);\n        let statementHeight1 = blockView._statements[0] ? blockView._statements[0].height : 20;\n        let statementHeight2 = blockView._statements[1] ? blockView._statements[1].height : 20;\n        statementHeight1 = Math.max(statementHeight1, 20);\n        statementHeight2 = Math.max(statementHeight2, 20);\n        return {\n            previous: { x: 0, y: 0 },\n            next: {\n                x: 0,\n                y:\n                    statementHeight1 +\n                    statementHeight2 +\n                    contentHeight1 +\n                    contentHeight2 +\n                    11 +\n                    blockView.offsetY,\n            },\n        };\n    },\n    box(blockView) {\n        const contentWidth = blockView.contentWidth;\n        const contentHeight1 = Math.max(Math.floor(blockView.contentHeight / 1000000) + 2, 30);\n        const contentHeight2 = Math.max((blockView.contentHeight % 1000000) + 2, 30);\n        let statementHeight1 = blockView._statements[0]\n            ? blockView._statements[0].height % 1000000\n            : 20;\n        let statementHeight2 = blockView._statements[1] ? blockView._statements[1].height : 20;\n        statementHeight1 = Math.max(statementHeight1, 20);\n        statementHeight2 = Math.max(statementHeight2, 20);\n        return {\n            offsetX: -8,\n            offsetY: 0,\n            width: contentWidth + 30,\n            height: contentHeight1 + contentHeight2 + statementHeight1 + statementHeight2 + 17,\n            marginBottom: 0,\n            topFieldHeight: contentHeight1,\n        };\n    },\n    statementPos(blockView) {\n        const statementHeight1 = blockView._statements[0]\n            ? blockView._statements[0].height % 1000000\n            : 20;\n        const height1 = Math.max(30, (blockView.contentHeight % 1000000) + 2) + 1;\n        const height2 =\n            height1 +\n            Math.max(statementHeight1, 20) +\n            Math.max(Math.floor(blockView.contentHeight / 1000000) + 2, 30) +\n            1;\n\n        return [{ x: 14, y: height1 - 3 }, { x: 14, y: height2 - 6 }];\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight % 1000000, 28);\n        return { x: 14, y: height / 2 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_event.ts",
    "content": "Entry.skeleton.basic_event = {\n    executable: true,\n    path(blockView) {\n        let width = blockView.contentWidth + 20;\n        width = Math.max(0, width);\n        width -= 30;\n\n        return `m 24 34\n        h ${width}\n        a 14 14 0 0 0 0 -28\n        H 30\n        A 17 17 0 0 0 18 1\n        C 8.611 1 1 8.611 1 18\n        c 0 7.2 4.5 13.5 11 16\n        l 6 6\n        l 6 -6\n        z`;\n    },\n    box(blockView) {\n        return {\n            topFieldHeight: 40,\n            offsetX: 0,\n            offsetY: -2,\n            width: blockView.contentWidth + 30,\n            height: 30,\n            marginBottom: 0,\n        };\n    },\n    magnets(blockView) {\n        // apply scale required.\n        const height = blockView ? Math.max(blockView.height + blockView.offsetY + 7, 30) : 30;\n        return {\n            next: { x: 12, y: height - 1 },\n        };\n    },\n    contentPos() {\n        // apply scale required.\n        return { x: 18, y: 20 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_loop.ts",
    "content": "Entry.skeleton.basic_loop = {\n    executable: true,\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(28, height);\n        width = Math.max(0, width + 6 - height / 2);\n        let statementHeight = blockView._statements[0] ? blockView._statements[0].height : 20;\n        statementHeight = Math.max(statementHeight, 20);\n        const bw = width - 8;\n        const halfHeight = height / 2;\n\n        return `m 0 0\n        l 6 6\n        l 6 -6\n        h ${width}\n        a ${halfHeight} ${halfHeight} 0 0 1 0 ${height}\n        H 26\n        l -6 6\n        l -6 -6\n        v ${statementHeight}\n        l 6 6\n        l 6 -6\n        h ${bw}\n        a 7.5 7.5 0 0 1 0 15\n        H 12\n        l -6 6\n        l -6 -6\n        z`;\n    },\n    magnets(blockView) {\n        const contentHeight = Math.max(blockView.contentHeight + 2, 28);\n        let statementHeight = blockView._statements[0] ? blockView._statements[0].height : 20;\n        statementHeight = Math.max(statementHeight, 20);\n        return {\n            previous: { x: 0, y: 0 },\n            next: { x: 0, y: statementHeight + contentHeight + 15 + blockView.offsetY },\n        };\n    },\n    box(blockView) {\n        const contentWidth = blockView.contentWidth;\n        const contentHeight = Math.max(blockView.contentHeight + 2, 28);\n        let statementHeight = blockView._statements[0] ? blockView._statements[0].height : 20;\n        statementHeight = Math.max(statementHeight, 20);\n        return {\n            topFieldHeight: contentHeight,\n            offsetX: -8,\n            offsetY: 0,\n            width: contentWidth + 30,\n            height: contentHeight + statementHeight + 17,\n            marginBottom: 0,\n        };\n    },\n    statementPos(blockView) {\n        const height = Math.max(30, blockView.contentHeight + 2);\n        return [{ x: 14, y: height - 2 }];\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight, 28);\n        return { x: 14, y: height / 2 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_param.ts",
    "content": "Entry.skeleton.basic_param = {\n    path(blockView) {\n        let width = blockView.contentWidth;\n        const output = blockView._contents[blockView._contents.length - 1];\n        if (output) {\n            width -= output.box.width + Entry.BlockView.PARAM_SPACE - 2;\n        }\n        width = Math.max(0, width);\n        return `m 2 0\n                h ${width + 11}\n                a 3 3 0 0 1 3 3\n                h 2.2\n                a 2 2 0 0 1 2 2\n                v 12\n                a 2 2 0 0 1 -2 2\n                h -2.2\n                a 3 3 0 0 1 -3 3\n                H 3\n                a 3 3 0 0 1 -3 -3\n                h 2\n                a 2 2 0 0 0 2 -2\n                V 5\n                a 2 2 0 0 0 -2 -2\n                H 0\n                a 3 3 0 0 1 3 -3\n                z`;\n    },\n    box(blockView) {\n        const width = blockView ? blockView.contentWidth : 5;\n        return {\n            offsetX: -8,\n            offsetY: 0,\n            width: width + 11,\n            height: 22,\n            marginBottom: 0,\n        };\n    },\n    magnets() {\n        return {\n            param: {},\n        };\n    },\n    contentPos() {\n        return { x: 11, y: 11 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_string_field.ts",
    "content": "Entry.skeleton.basic_string_field = {\n    path(blockView) {\n        let width =\n            blockView.contentWidth < 10 ? blockView.contentWidth : blockView.contentWidth + 2;\n        let height = blockView.contentHeight;\n        height = Math.max(20, height);\n        width = Math.max(0, width - height + 12);\n        const halfHeight = height / 2;\n\n        return `m ${halfHeight} 0\n                h ${width}\n                a ${halfHeight} ${halfHeight} 0 1 1 0 ${height}\n                H ${halfHeight}\n                a ${halfHeight} ${halfHeight} 0 0 1 0 -${height}\n                z`;\n    },\n    color: '#FFF',\n    outerLine: '#FF9C00',\n    fontSize: 10,\n    box(blockView) {\n        const width = blockView ? blockView.contentWidth : 5;\n        const height = blockView ? blockView.contentHeight : 0;\n        return {\n            offsetX: -8,\n            offsetY: 0,\n            width: width + 15,\n            height: Math.max(height, 20),\n            marginBottom: 0,\n        };\n    },\n    magnets() {\n        return {\n            string: {},\n        };\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight, 20);\n        return { x: 7, y: height / 2 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_text.ts",
    "content": "import _get from 'lodash/get';\n\nEntry.skeleton.basic_text = {\n    path(blockView) {\n        const paramText = _get(blockView, ['_schema', 'params', '0', 'text'], '').match(/[\\r\\n]/g);\n        const textLines = paramText ? paramText.length + 1 : 1;\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(18, height + 2) * textLines;\n        width = Math.max(0, width - height + 12);\n        const halfHeight = height / 2;\n        return (\n            `m ${halfHeight},0 h ${width} a ${halfHeight},${halfHeight} 0 1,1 0,${height}` +\n            `H ${halfHeight} A ${halfHeight},${halfHeight} 0 1,1 ${halfHeight},0 z`\n        );\n    },\n    box(blockView) {\n        const paramText = _get(blockView, ['_schema', 'params', '0', 'text'], '').match(/[\\r\\n]/g);\n        const textLines = paramText ? paramText.length + 1 : 1;\n        const width = blockView ? blockView.contentWidth : 5;\n        const height = (blockView ? blockView.contentHeight : 18) * textLines;\n        const { skeletonOptions = {} } = blockView._schema;\n        const { box = {} } = skeletonOptions;\n        return Object.assign(\n            {\n                offsetX: 0,\n                offsetY: 0,\n                width: width + 12,\n                height: Math.max(height + 2, 18),\n                marginBottom: 0,\n            },\n            box\n        );\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight, 16);\n        const width = Math.max(blockView.contentWidth, 16);\n\n        const { skeletonOptions = {} } = blockView._schema;\n        const { contentPos = {} } = skeletonOptions;\n\n        return Object.assign({ x: width / 2 + 5, y: height / 2 + 1 }, contentPos);\n    },\n    movable: false,\n    readOnly: true,\n    nextShadow: false,\n    classes: ['basicText'],\n};\n"
  },
  {
    "path": "src/playground/skeleton/basic/basic_text_light.ts",
    "content": "import _get from 'lodash/get';\n\n/**\n * line entry 의 hardware font-light-weight noti 를 위해 만든 스켈레톤\n */\nEntry.skeleton.basic_text_light = {\n    path(blockView) {\n        const paramText = _get(blockView, ['_schema', 'params', '0', 'text'], '').match(/[\\r\\n]/g);\n        const textLines = paramText ? paramText.length + 1 : 1;\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(18, height + 2) * textLines;\n        width = Math.max(0, width - height + 12);\n        const halfHeight = height / 2;\n        return (\n            `m ${halfHeight},0 h ${width} a ${halfHeight},${halfHeight} 0 1,1 0,${height}` +\n            `H ${halfHeight} A ${halfHeight},${halfHeight} 0 1,1 ${halfHeight},0 z`\n        );\n    },\n    box(blockView) {\n        const paramText = _get(blockView, ['_schema', 'params', '0', 'text'], '').match(/[\\r\\n]/g);\n        const textLines = paramText ? paramText.length + 1 : 1;\n        const width = blockView ? blockView.contentWidth : 5;\n        const height = (blockView ? blockView.contentHeight : 18) * textLines;\n        const { skeletonOptions = {} } = blockView._schema;\n        const { box = {} } = skeletonOptions;\n        return Object.assign(\n            {\n                offsetX: 0,\n                offsetY: 0,\n                width: width + 12,\n                height: Math.max(height + 2, 18),\n                marginBottom: 0,\n            },\n            box\n        );\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight, 16);\n        const width = Math.max(blockView.contentWidth, 16);\n        return { x: width / 2 + 5, y: height / 2 + 1 };\n    },\n    movable: false,\n    readOnly: true,\n    nextShadow: false,\n    classes: ['basicTextLight'],\n};\n"
  },
  {
    "path": "src/playground/skeleton/clickable_text.ts",
    "content": "Entry.skeleton.clickable_text = {\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(18, height + 2);\n        width = Math.max(0, width - height + 12);\n        const halfHeight = height / 2;\n        return (\n            `m ${halfHeight},0 h ${width} a ${halfHeight},${halfHeight} 0 1,1 0,${height}` +\n            `H ${halfHeight} A ${halfHeight},${halfHeight} 0 1,1 ${halfHeight},0 z`\n        );\n    },\n    box(blockView) {\n        const width = blockView ? blockView.contentWidth : 5;\n        const height = blockView ? blockView.contentHeight : 18;\n        const { skeletonOptions = {} } = blockView._schema;\n        const { box = {} } = skeletonOptions;\n        return Object.assign(\n            {\n                offsetX: 0,\n                offsetY: 0,\n                width: width + 12,\n                height: Math.max(height + 2, 18),\n                marginBottom: 0,\n            },\n            box\n        );\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight, 16);\n        const width = Math.max(blockView.contentWidth, 16);\n        return { x: width / 2 + 5, y: height / 2 + 1 };\n    },\n    movable: false,\n    readOnly: true,\n    nextShadow: false,\n    classes: ['clickableText'],\n};\n"
  },
  {
    "path": "src/playground/skeleton/comment.ts",
    "content": "Entry.skeleton.comment = {\n    executable: false,\n    path(blockView) {\n        let width = blockView.contentWidth;\n        let height = blockView.contentHeight;\n        height = Math.max(30, height + 2);\n        width = Math.max(0, width + 9 - height / 2);\n        const halfHeight = height / 2;\n\n        return (\n            `m -8,0 l 8,8 8,-8 h ${width} a ${halfHeight},${halfHeight} 0 0,1 0,${height}` +\n            `h -${width} l -8,8 -8,-8 v -${height} z`\n        );\n    },\n    box(blockView) {\n        const width = blockView ? blockView.contentWidth : 150;\n        const height = blockView ? blockView.contentHeight : 28;\n        return {\n            offsetX: -8,\n            offsetY: 0,\n            width: width + 30,\n            height: Math.max(30, height + 2),\n            marginBottom: 0,\n        };\n    },\n    magnets(blockView) {\n        // apply scale required.\n        const height = blockView ? Math.max(blockView.height, 30) : 30;\n        return {\n            previous: { x: 0, y: 0 },\n            next: { x: 0, y: height + 1 + blockView.offsetY },\n        };\n    },\n    contentPos(blockView) {\n        // apply scale required.\n        const height = Math.max(blockView.contentHeight, 28);\n        return { x: 14, y: height / 2 + 1 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/index.ts",
    "content": "Entry.skeleton = {};\n\n// index.js 를 제외한 playground/skeleton 디렉토리 하위의 모든 js 를 불러옴\n// https://webpack.js.org/guides/dependency-management/#requirecontext\nconst context = require.context('.', true, /^(?!.*index.[jt]s)(.*\\.[jt]s$)/im);\ncontext.keys().forEach(context);\n"
  },
  {
    "path": "src/playground/skeleton/pebble/pebble_basic.ts",
    "content": "Entry.skeleton.pebble_basic = {\n    executable: true,\n    fontSize: 15,\n    morph: ['prev', 'next'],\n    path() {\n        return (\n            'm 0,9 a 9,9 0 0,0 9,-9 h 28 ' +\n            'q 25,0 25,25' +\n            'q 0,25 -25,25' +\n            'h -28 a 9,9 0 0,1 -18,0 h -28 ' +\n            'q -25,0 -25,-25' +\n            'q 0,-25 25,-25' +\n            'h 28 a 9,9 0 0,0 9,9 z'\n        );\n    },\n    magnets(blockView) {\n        // apply scale required.\n        const height = blockView ? Math.max(blockView.height, 51) : 51;\n        return {\n            previous: { x: 0, y: 0 },\n            next: { x: 0, y: height + blockView.offsetY },\n        };\n    },\n    box() {\n        return {\n            offsetX: -62,\n            offsetY: 0,\n            width: 124,\n            height: 50,\n            marginBottom: 0,\n        };\n    },\n    contentPos() {\n        // apply scale required.\n        return { x: -46, y: 25 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/pebble/pebble_event.ts",
    "content": "Entry.skeleton.pebble_event = {\n    executable: true,\n    path() {\n        return 'm 0,0 a 25,25 0 0,1 9,48.3 a 9,9 0 0,1 -18,0 a 25,25 0 0,1 9,-48.3 z';\n    },\n    box() {\n        return {\n            offsetX: -25,\n            offsetY: 0,\n            width: 50,\n            height: 48.3,\n            marginBottom: 0,\n        };\n    },\n    magnets(blockView) {\n        // apply scale required.\n        const height = blockView ? Math.max(blockView.height, 49.3) : 49.3;\n        return {\n            next: { x: 0, y: height + blockView.offsetY },\n        };\n    },\n    contentPos() {\n        // apply scale required.\n        return { x: 0, y: 25 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skeleton/pebble/pebble_loop.ts",
    "content": "Entry.skeleton.pebble_loop = {\n    executable: true,\n    fontSize: 16,\n    dropdownHeight: 23,\n    path(blockView) {\n        const contentWidth = 124;\n        const statementHeight = Math.max(\n            blockView._statements[0] ? blockView._statements[0].height : 50,\n            50\n        );\n        return (\n            (\n                'M 0,9 a 9,9 0 0,0 9,-9 h %cw q 25,0 25,25 v' +\n                '%ch q 0,25 -25,25 h -%cw a 9,9 0 0,1 -18,0 ' +\n                'h -%cw q -25,0 -25,-25 v -%ch q 0,-25 25,-25 h %cw a 9,9 0 0,0 9,9 ' +\n                'M 0,49 a 9,9 0 0,1 -9,-9 h -28 a 25,25 0 0,0 -25,25 v' +\n                '%cih a 25,25 0 0,0 25,25 h 28 a 9,9 0 0,0 18,0 ' +\n                'h 28 a 25,25 0 0,0 25,-25 v -%cih a 25,25 0 0,0 -25,-25 h -28 a 9,9 0 0,1 -9,9 z'\n            )\n                // TODO blockView 인터페이스 완성시 삭제\n                .replace(/%cw/gi, (contentWidth / 2 - 21) as any)\n                .replace(/%ch/gi, (statementHeight + 4) as any)\n                .replace(/%cih/gi, (statementHeight - 50) as any)\n        );\n    },\n    magnets(blockView) {\n        const contentHeight = Math.max(blockView.contentHeight + 2, 41);\n        let statementHeight = blockView._statements[0] ? blockView._statements[0].height : 20;\n        statementHeight = Math.max(statementHeight, 51);\n        return {\n            previous: { x: 0, y: 0 },\n            next: { x: 0, y: statementHeight + contentHeight + 13 + blockView.offsetY },\n        };\n    },\n    box(blockView) {\n        const contentWidth = blockView.contentWidth;\n        const contentHeight = Math.max(blockView.contentHeight + 2, 41);\n        let statementHeight = blockView._statements[0] ? blockView._statements[0].height : 20;\n        statementHeight = Math.max(statementHeight, 51);\n        return {\n            topFieldHeight: contentHeight,\n            offsetX: -(contentWidth / 2 + 13),\n            offsetY: 0,\n            width: contentWidth + 30,\n            height: contentHeight + statementHeight + 13,\n            marginBottom: 0,\n        };\n    },\n    statementPos(blockView) {\n        const height = Math.max(39, blockView.contentHeight + 2) + 1.5;\n        return [{ x: 0, y: height }];\n    },\n    contentPos() {\n        // apply scale required.\n        return { x: -46, y: 25 };\n    },\n};\n"
  },
  {
    "path": "src/playground/skinner.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.skinContainer = {\n    _skins: {},\n};\n\n(function(p) {\n    p.skinSchema = {\n        type: '',\n        condition: [],\n    };\n\n    p.loadSkins = function(skins) {\n        skins.map(this.addSkin.bind(this));\n    };\n\n    p.addSkin = function(skin) {\n        var blockSkin = function() {};\n        var blockPrototype = Entry.block[skin.type];\n        blockSkin.prototype = blockPrototype;\n        blockSkin = new blockSkin();\n\n        for (var key in skin) blockSkin[key] = skin[key];\n\n        if (!this._skins[skin.type]) this._skins[skin.type] = [];\n\n        this._skins[skin.type].push(blockSkin);\n    };\n\n    p.getSkin = function(block) {\n        if (this._skins[block.type]) {\n            var candidates = this._skins[block.type];\n            for (var i = 0; i < candidates.length; i++) {\n                var candidate = candidates[i];\n                if (!candidate.conditions || !candidate.conditions.length)\n                    return candidate;\n                for (var j = 0; j < candidate.conditions.length; j++) {\n                    var condition = candidate.conditions[j];\n                    if (\n                        block.getDataByPointer(condition.pointer) !==\n                        condition.value\n                    )\n                        // here\n                        break;\n                    if (j === candidate.conditions.length - 1) return candidate;\n                }\n            }\n        }\n\n        return Entry.block[block.type];\n    };\n})(Entry.skinContainer);\n"
  },
  {
    "path": "src/playground/thread.js",
    "content": "'use strict';\n\nEntry.Thread = class Thread {\n    constructor(thread, code, parent) {\n        this.id = Entry.generateHash();\n        this._data = new Entry.Collection();\n        this._code = code;\n        this.changeEvent = new Entry.Event(this);\n        this.changeEvent.attach(this, this.handleChange);\n        this._event = null;\n        this.parent = parent ? parent : code;\n\n        this.load(thread);\n    }\n\n    getId() {\n        return this.id;\n    }\n\n    load(thread = [], mode) {\n        if (!(thread instanceof Array)) {\n            return console.error('thread must be array');\n        }\n\n        for (let i = 0; i < thread.length; i++) {\n            const block = thread[i];\n            if (block instanceof Entry.Block || block instanceof Entry.Comment || block.isDummy) {\n                block.setThread(this);\n                this._data.push(block);\n            } else if (block.type === 'comment') {\n                const commment = new Entry.Comment(block);\n                commment.setThread(this);\n                this._data.push(commment);\n            } else {\n                this._data.push(new Entry.Block(block, this));\n            }\n        }\n\n        const codeView = this._code.view;\n        if (codeView) {\n            this.createView(codeView.board, mode);\n        }\n        this.resetEvent();\n        return this;\n    }\n\n    registerEvent(block, eventType) {\n        this._event = eventType;\n        this._code.registerEvent(block, eventType);\n    }\n\n    unregisterEvent(block, eventType) {\n        this._code.unregisterEvent(block, eventType);\n    }\n\n    createView(board, mode) {\n        if (!this.view) {\n            this.view = new Entry.ThreadView(this, board);\n        }\n        this.getBlocks().forEach((b) => {\n            let view;\n            if (b.createView) {\n                view = b.createView(board, mode);\n            } else if (b.createComment) {\n                view = b.createComment(board);\n            }\n            return view;\n        });\n    }\n\n    destroyView() {\n        this.view = null;\n        this._data.map((b) => b.destroyView());\n    }\n\n    separate(block, count, index) {\n        if (!this._data.has(block.id)) {\n            return;\n        }\n\n        this._code.createThread(this._data.splice(this._data.indexOf(block), count), index);\n        this.resetEvent();\n        this.changeEvent.notify();\n    }\n\n    cut(block) {\n        const splicedData = this._data.splice(this._data.indexOf(block));\n        this.resetEvent();\n        this.changeEvent.notify();\n        return splicedData;\n    }\n\n    insertByBlock(block, newBlocks) {\n        const index = block ? this._data.indexOf(block) : -1;\n        for (let i = 0; i < newBlocks.length; i++) {\n            newBlocks[i].setThread(this);\n        }\n        this._data.splice(...[index + 1, 0].concat(newBlocks));\n        this.resetEvent();\n        this.changeEvent.notify();\n    }\n\n    insertToTop(newBlock) {\n        newBlock.setThread(this);\n        this._data.unshift.apply(this._data, [newBlock]);\n        this.resetEvent();\n        this.changeEvent.notify();\n    }\n\n    clone(code, mode) {\n        const newThread = new Entry.Thread([], code || this._code);\n        return newThread.load(\n            this.getBlocks().reduce((acc, block) => [...acc, block.clone(newThread)], []),\n            mode\n        );\n    }\n\n    toJSON(isNew, index = 0, excludeData, option) {\n        if (index instanceof Entry.Block) {\n            index = this.indexOf(index);\n        }\n\n        const array = [];\n        const data = this._data;\n        for (index; index < data.length; index++) {\n            const block = data[index];\n            if (block instanceof Entry.Block) {\n                array.push(block.toJSON(isNew, excludeData, option));\n            } else if (block instanceof Entry.Comment) {\n                array.push(block.toJSON());\n            }\n        }\n        return array;\n    }\n\n    destroy(animate, isNotForce) {\n        if (this.view) {\n            this.view.destroy(animate);\n        }\n\n        this.getBlocks()\n            .reverse()\n            .forEach((block) => block.destroy(animate, null, isNotForce));\n\n        if (!this._data.length) {\n            this._code.destroyThread(this, false);\n        }\n    }\n\n    getBlock(index) {\n        return this._data[index];\n    }\n\n    getBlocks() {\n        return this._data.map(_.identity);\n    }\n\n    countBlock() {\n        return this.getBlocks().reduce((count, block) => {\n            if (!block.type) {\n                return count;\n            }\n\n            count++;\n\n            return (block.statements || []).reduce(\n                (count, statement) => (count += statement.countBlock()),\n                count\n            );\n        }, 0);\n    }\n\n    handleChange() {\n        if (this._data.length === 0) {\n            this.destroy();\n        }\n    }\n\n    getCode() {\n        return this._code;\n    }\n\n    setCode(code) {\n        this._code = code;\n    }\n\n    spliceBlock(block) {\n        this._data.remove(block);\n        this.resetEvent();\n        this.changeEvent.notify();\n    }\n\n    getFirstBlock() {\n        return this._data[0];\n    }\n\n    getPrevBlock(block) {\n        return this._data.at(this._data.indexOf(block) - 1);\n    }\n\n    getNextBlock(block) {\n        return this._data.at(this._data.indexOf(block) + 1);\n    }\n\n    getLastBlock() {\n        return this._data.at(this._data.length - 1);\n    }\n\n    getRootBlock() {\n        return this._data.at(0);\n    }\n\n    hasBlockType(type) {\n        for (let i = 0; i < this._data.length; i++) {\n            if (inspectBlock(this._data[i])) {\n                return true;\n            }\n        }\n        return false;\n\n        function inspectBlock(block) {\n            if (Array.isArray(type) && type.includes(block.type)) {\n                return true;\n            } else if (type === block.type) {\n                return true;\n            }\n\n            const params = block.params || [];\n            for (let k = 0; k < params.length; k++) {\n                const param = params[k];\n                if (param && param.constructor == Entry.Block) {\n                    if (inspectBlock(param)) {\n                        return true;\n                    }\n                }\n            }\n            const statements = block.statements;\n            if (statements) {\n                for (let j = 0; j < statements.length; j++) {\n                    if (statements[j].hasBlockType(type)) {\n                        return true;\n                    }\n                }\n            }\n            return false;\n        }\n    }\n\n    getCount(startBlock) {\n        let result = this._data.length;\n        if (startBlock) {\n            result -= this._data.indexOf(startBlock);\n        }\n        return result;\n    }\n\n    indexOf(block) {\n        return this._data.indexOf(block);\n    }\n\n    pointer(pointer = [], block) {\n        if (block) {\n            pointer.unshift(this.indexOf(block));\n        }\n\n        const parent = this.parent;\n\n        if (parent instanceof Entry.Block) {\n            pointer.unshift(parent.indexOfStatements(this));\n        }\n\n        if (this._code === parent) {\n            const { x, y } = this._data[0];\n            return [x, y, this._code.indexOf(this), ...pointer];\n        }\n\n        return parent.pointer(pointer);\n    }\n\n    getBlockIndex(block) {\n        return this.getBlocks().indexOf(block);\n    }\n\n    getBlockList(excludePrimitive, type, index) {\n        return _.chain(this._data)\n            .map((block) => {\n                if (block.constructor !== Entry.Block) {\n                    return;\n                }\n                if (Array.isArray(type)) {\n                    return type.reduce(\n                        (acc, type) => acc.concat(block.getBlockList(excludePrimitive, type)),\n                        []\n                    );\n                } else {\n                    return block.getBlockList(excludePrimitive, type);\n                }\n            })\n            .flatten()\n            .compact()\n            .value();\n    }\n\n    stringify(excludeData, isNew, index) {\n        return JSON.stringify(this.toJSON(isNew, index, excludeData));\n    }\n\n    isInOrigin() {\n        const block = this.getFirstBlock();\n        return block && block.isInOrigin();\n    }\n\n    getDom(query) {\n        const view = this.view;\n\n        if (_.isEmpty(query)) {\n            return view.svgGroup;\n        }\n\n        query = [...query];\n\n        const key = query.shift();\n        if (key === 'magnet') {\n            return view.getMagnet('next');\n        }\n    }\n\n    isParamBlockType() {\n        return false;\n    }\n\n    isGlobal() {\n        return this._code === this.parent;\n    }\n\n    hasData() {\n        return Boolean(this._data.length);\n    }\n\n    resetEvent() {\n        const block = this.getFirstBlock();\n        if (block && this._event !== block?._schema?.event) {\n            this._event = block?._schema?.event;\n        }\n    }\n};\n"
  },
  {
    "path": "src/playground/thread_view.js",
    "content": "'use strict';\n\nEntry.ThreadView = class ThreadView {\n    schema = {\n        height: 0,\n        zIndex: 0,\n    };\n\n    constructor(thread, board) {\n        Entry.Model(this, false);\n\n        this.thread = thread;\n\n        this.svgGroup = board.svgThreadGroup.elem('g');\n\n        this.board = board;\n\n        this.parent = board; // statement\n\n        this._hasGuide = false;\n    }\n\n    destroy() {\n        this.svgGroup.remove();\n    }\n\n    setParent(parent) {\n        this.parent = parent;\n    }\n\n    getParent() {\n        return this.parent;\n    }\n\n    renderText() {\n        const blocks = this.thread.getBlocks();\n        for (let i = 0; i < blocks.length; i++) {\n            blocks[i].view.renderText();\n        }\n    }\n\n    renderBlock() {\n        const blocks = this.thread.getBlocks();\n        for (let i = 0; i < blocks.length; i++) {\n            blocks[i].view.renderBlock();\n        }\n    }\n\n    requestAbsoluteCoordinate(blockView) {\n        const board = this.board;\n        const { scale = 1 } = board || {};\n        const blocks = this.thread.getBlocks();\n        let block = blocks.shift();\n        let pos = {\n            x: 0,\n            y: 0,\n        };\n        const parent = this.parent;\n        if (\n            !(parent instanceof Entry.Board || parent instanceof Entry.BlockMenu) &&\n            parent.requestAbsoluteCoordinate\n        ) {\n            pos = parent.requestAbsoluteCoordinate();\n        }\n\n        while (block && block.view !== blockView && block.view) {\n            const prevBlockView = block.view;\n            pos.x += prevBlockView.x + prevBlockView.magnet.next.x * scale;\n            pos.y += prevBlockView.y + prevBlockView.magnet.next.y * scale;\n            block = blocks.shift();\n        }\n        return pos;\n    }\n\n    requestPartHeight(blockView) {\n        const blocks = this.thread.getBlocks();\n        let block = blocks.pop();\n        let height = 0;\n        if (blockView) {\n            height = blockView.magnet.next ? blockView.magnet.next.y : blockView.height;\n        }\n        while (block && block.view !== blockView && block.view) {\n            const prevBlockView = block.view;\n            if (prevBlockView.magnet.next) {\n                height += prevBlockView.magnet.next.y;\n            } else {\n                height += prevBlockView.height;\n            }\n            if (prevBlockView.dragMode === Entry.DRAG_MODE_DRAG) {\n                height = 0;\n            }\n            block = blocks.pop();\n        }\n        return height;\n    }\n\n    getMagnet() {\n        return {\n            getBoundingClientRect: function() {\n                const halfWidth = 20;\n                const coord = this.parent.requestAbsoluteCoordinate();\n                const boardOffset = this.board.relativeOffset;\n                return {\n                    top: coord.y + boardOffset.top - halfWidth,\n                    left: coord.x + boardOffset.left - halfWidth,\n                    width: 2 * halfWidth,\n                    height: 2 * halfWidth,\n                };\n            }.bind(this),\n        };\n    }\n\n    dominate() {\n        !this._hasGuide && this.parent.dominate(this.thread);\n    }\n\n    isGlobal() {\n        return this.parent instanceof Entry.Board;\n    }\n\n    reDraw() {\n        const blocks = this.thread._data;\n\n        for (let i = blocks.length - 1; i >= 0; i--) {\n            const b = blocks[i];\n            if (b.view) {\n                b.view.reDraw();\n            } else {\n                b.createView(this.thread._code.view.board);\n            }\n        }\n    }\n\n    setZIndex(zIndex) {\n        this.set({ zIndex });\n    }\n\n    setHasGuide(bool) {\n        this._hasGuide = bool;\n    }\n\n    getFields() {\n        const BLOCK = Entry.Block;\n\n        return this.thread.getBlocks().reduce(function(fields, block) {\n            if (!(block instanceof BLOCK)) {\n                return fields;\n            }\n\n            return fields.concat(block.view.getFields());\n        }, []);\n    }\n};\n"
  },
  {
    "path": "src/playground/toast.js",
    "content": "export default class Toast {\n    static instance;\n    constructor(board) {\n        if (Toast.instance) {\n            return Toast.instance;\n        }\n        this.board = board;\n        this.$boardView = $(board.view);\n        this.generateView();\n        Toast.instance = this;\n    }\n\n    generateView() {\n        const template = `\n            <div class=\"entryMobileToast hideToast\">\n                <div class=\"content\"/>\n            </div>\n        `;\n        this.$view = $('<div class=\"entryMobileToastWrapper\">').append(template);\n        this.$toast = this.$view.find('.entryMobileToast');\n        this.$content = this.$view.find('.content');\n        if (!this.$boardView.has(this.$view).length) {\n            this.$boardView.append(this.$view);\n        }\n    }\n\n    show(message) {\n        this.$content.text(message);\n        this.$toast.removeClass('fadeToast');\n        $(this.$toast).width();\n        this.$toast.addClass('fadeToast');\n        this.removeToast(this);\n    }\n\n    // 애니메이션 Debounce 처리\n    removeToast = _.debounce((toast) => {\n        toast.$toast.removeClass('fadeToast');\n    }, 3000);\n\n    destroy() {\n        this.removeToast.cancel();\n        delete this.$boardView;\n        delete this.board;\n        delete this.$view;\n        delete this.$toast;\n        delete this.$content;\n        delete Toast.instance;\n    }\n}\n"
  },
  {
    "path": "src/playground/trashcan.js",
    "content": "'use strict';\nEntry.FieldTrashcan = class FieldTrashcan {\n    constructor(board) {\n        if (board) {\n            this.setBoard(board);\n        }\n        this.dragBlock = null;\n        this.dragBlockObserver = null;\n        this.isOver = false;\n        if (Entry.windowResized) {\n            Entry.windowResized.attach(this, this.setPosition);\n        }\n    }\n\n    _generateView() {\n        this.svgGroup = this.board.svg.elem('g');\n        this.renderStart();\n        this._addControl();\n    }\n\n    renderStart() {\n        const path = `${Entry.mediaFilePath}delete_`;\n        this.svgGroup.elem('image', {\n            href: `${path}body.svg`,\n            y: 19,\n            width: 61,\n            height: 70,\n        });\n        this.trashcanTop = this.svgGroup.elem('image', {\n            href: `${path}cover.svg`,\n            width: 60,\n            height: 27,\n        });\n    }\n\n    _addControl() {\n        $(this.svgGroup).bind('mousedown', function(e) {\n            if (Entry.Utils.isRightButton(e)) {\n                e.stopPropagation();\n                $('#entryWorkspaceBoard').css('background', 'white');\n            }\n        });\n    }\n\n    updateDragBlock() {\n        const block = this.board.dragBlock;\n        const observer = this.dragBlockObserver;\n\n        if (observer) {\n            observer.destroy();\n            this.dragBlockObserver = null;\n        }\n\n        if (block) {\n            if (block instanceof Entry.Comment) {\n                this.dragBlockObserver = block.observe(this, 'checkBlock', ['moveX', 'moveY']);\n            } else {\n                this.dragBlockObserver = block.observe(this, 'checkBlock', ['x', 'y']);\n            }\n        } else {\n            if (this.isOver && this.dragBlock) {\n                if (this.dragBlock instanceof Entry.BlockView) {\n                    const prevBlock = this.dragBlock.block.getPrevBlock();\n                    if (!prevBlock) {\n                        const script = this.dragBlock.block.getCode();\n                        Entry.do('destroyThread', this.dragBlock.block.thread, 'trashcan').isPass(\n                            true,\n                            true\n                        );\n                        Entry.Utils.playSound('entryDelete');\n                        script?.changeEvent?.notify();\n                    }\n                } else if (this.dragBlock instanceof Entry.Comment) {\n                    Entry.do('removeComment', this.dragBlock).isPass(true, true);\n                }\n            }\n            this.tAnimation(false);\n        }\n        this.dragBlock = block;\n    }\n\n    checkBlock() {\n        const dragBlock = this.dragBlock;\n        if (!dragBlock || (dragBlock.block && !dragBlock.block.isDeletable())) {\n            return;\n        }\n\n        const boardOffset = this.board.offset();\n        const position = this.getPosition();\n        const trashcanX = position.x + boardOffset.left;\n        const trashcanY = position.y + boardOffset.top;\n\n        let mouseX;\n        let mouseY;\n        const instance = dragBlock.dragInstance;\n        if (instance) {\n            mouseX = instance.offsetX;\n            mouseY = instance.offsetY;\n        }\n        const isOver = mouseX >= trashcanX && mouseY >= trashcanY;\n        this.tAnimation(isOver);\n    }\n\n    align() {\n        const position = this.getPosition();\n        const transform = `translate(${position.x},${position.y})`;\n\n        this.svgGroup.attr({\n            transform,\n        });\n    }\n\n    setPosition() {\n        if (!this.board) {\n            return;\n        }\n        const svgDom = this.board.svgDom;\n        this._x = svgDom.width() - 83.5;\n        this._y = svgDom.height() - 110;\n        this.align();\n    }\n\n    getPosition() {\n        return {\n            x: this._x,\n            y: this._y,\n        };\n    }\n\n    tAnimation(isOver) {\n        if (isOver === this.isOver) {\n            return;\n        }\n\n        isOver = isOver === undefined ? true : isOver;\n        const trashTop = this.trashcanTop;\n        if (isOver) {\n            $(trashTop).attr('transform', 'translate(20, -25) rotate(30)');\n            // $(trashTop).attr('class', 'trashcanOpen');\n        } else {\n            $(trashTop).attr('transform', 'translate(0, 0) rotate(0)');\n            // $(trashTop).attr('class', 'trashcanClose');\n        }\n\n        this.isOver = isOver;\n    }\n\n    setBoard(board) {\n        if (this._dragBlockObserver) {\n            this._dragBlockObserver.destroy();\n        }\n        this.board = board;\n        if (!this.svgGroup) {\n            this._generateView();\n        }\n\n        //control z-index\n        const svg = board.svg;\n        const firstChild = svg.firstChild;\n        if (firstChild) {\n            svg.insertBefore(this.svgGroup, firstChild);\n        } else {\n            svg.appendChild(this.svgGroup);\n        }\n\n        this._dragBlockObserver = board.observe(this, 'updateDragBlock', ['dragBlock']);\n        this.svgGroup.attr({\n            filter: `url(#entryTrashcanFilter_${board.suffix})`,\n        });\n        this.setPosition();\n    }\n};\n"
  },
  {
    "path": "src/playground/vim.js",
    "content": "import debounce from 'lodash/debounce';\n\nclass Vim {\n    static MAZE_MODE = 1;\n    static WORKSPACE_MODE = 2;\n\n    static TEXT_TYPE_JS = 0;\n    static TEXT_TYPE_PY = 1;\n\n    static PARSER_TYPE_JS_TO_BLOCK = 0;\n    static PARSER_TYPE_PY_TO_BLOCK = 1;\n    static PARSER_TYPE_BLOCK_TO_JS = 2;\n    static PARSER_TYPE_BLOCK_TO_PY = 3;\n\n    static INEDITABLE_LINE_PY = 3;\n\n    static PYTHON_IMPORT_ENTRY = 'import Entry';\n    static PYTHON_IMPORT_HW = '';\n\n    constructor(dom) {\n        if (typeof dom === 'string') {\n            dom = $(`#${dom}`);\n        } else {\n            dom = $(dom);\n        }\n\n        if (dom.prop('tagName') !== 'DIV') {\n            return console.error('Dom is not div element');\n        }\n\n        this._parentView = dom;\n        this.createDom(dom);\n\n        this._parser = new Entry.Parser(null, null, this.codeMirror);\n\n        Entry.addEventListener('hwChanged', (e) => {\n            if (Entry.hw.hwModule) {\n                let name = Entry.hw.hwModule.name;\n                name = name[0].toUpperCase() + name.slice(1);\n                if (name === 'ArduinoExt') {\n                    name = 'Arduino';\n                }\n                Vim.PYTHON_IMPORT_HW = `\\nimport ${name}\\n`;\n                Vim.INEDITABLE_LINE_PY = 4;\n            } else {\n                Vim.PYTHON_IMPORT_HW = '';\n                Vim.INEDITABLE_LINE_PY = 3;\n            }\n        });\n    }\n\n    createDom(dom) {\n        const parent = dom;\n\n        this.view = Entry.Dom('div', {\n            parent,\n            class: 'entryVimBoard',\n        });\n\n        this.codeMirror = CodeMirror(this.view[0], {\n            lineNumbers: true,\n            value: '',\n            mode: { name: 'javascript', globalVars: true },\n            theme: 'default',\n            indentUnit: 4,\n            indentWithTabs: true,\n            styleActiveLine: true,\n            extraKeys: {\n                'Ctrl-Space': 'autocomplete',\n                Tab(cm) {\n                    const spaces = Array(cm.getOption('indentUnit') + 1).join(' ');\n                    cm.replaceSelection(spaces);\n                },\n            },\n            //gutters: [\"CodeMirror-linenumbers\", \"breakpoints\"],\n            lint: true,\n            viewportMargin: 10,\n        });\n\n        const dShowHint = debounce(() => {\n            if (Entry.isTextMode) {\n                this.codeMirror.showHint({\n                    completeSingle: false,\n                    globalScope: this.#getAssistScope(),\n                });\n            }\n        }, 250);\n\n        this.codeMirror.on('keydown', (cm, event) => {\n            if (Entry && Entry.keyPressed) {\n                Entry.keyPressed.notify(event, true);\n            }\n            if (event.key.length === 1) {\n                dShowHint();\n            }\n        });\n\n        const dClear = debounce(() => {\n            const input =\n                this.codeMirror.display && this.codeMirror.display.input\n                    ? this.codeMirror.display.input\n                    : undefined;\n            if (input && input.composing) {\n                input.poll();\n                input.composing.range.clear();\n                input.composing = null;\n            }\n        }, 250);\n\n        this.codeMirror.on('keyup', (cm, event) => {\n            //i.e composition bug\n            dClear();\n\n            if (event.key === 'Backspace') {\n                dShowHint();\n            }\n        });\n\n        this.doc = this.codeMirror.getDoc();\n\n        const target = this.view[0];\n        target.removeEventListener('dragEnd', this.#handleDragEnd);\n        target.removeEventListener('dragOver', this.#handleDragOver);\n        target.addEventListener('dragEnd', this.#handleDragEnd);\n        target.addEventListener('dragOver', this.#handleDragOver);\n    }\n\n    hide() {\n        this.view.addClass('entryRemove');\n        this.view.remove();\n    }\n\n    show() {\n        this.view.removeClass('entryRemove');\n        this._parentView.append(this.view);\n    }\n\n    clearText() {\n        this.codeMirror.setValue('');\n    }\n\n    textToCode(textType) {\n        const type = textType;\n        if (type === Vim.TEXT_TYPE_JS) {\n            this._parserType = Vim.PARSER_TYPE_JS_TO_BLOCK;\n            this._parser.setParser(this._mode, this._parserType, this.codeMirror);\n        } else if (type === Vim.TEXT_TYPE_PY) {\n            this._parserType = Vim.PARSER_TYPE_PY_TO_BLOCK;\n            this._parser.setParser(this._mode, this._parserType, this.codeMirror);\n        }\n\n        let textCode = this.codeMirror.getValue();\n        const cursor = this.doc.getCursor();\n        textCode = textCode.replace(/\\t/gm, '    ');\n        this.codeMirror.setValue(textCode);\n        this.doc.setCursor(cursor);\n        return this._parser.parse(textCode);\n    }\n\n    codeToText(code, mode) {\n        let doc;\n        let textCode;\n        let codeDescription;\n        if (mode) {\n            this._mode = mode.runType;\n        }\n\n        const textType = mode.textType;\n        this._oldParserType = mode.textType;\n\n        if (textType === Vim.TEXT_TYPE_JS) {\n            this._parserType = Vim.PARSER_TYPE_BLOCK_TO_JS;\n            if (this._oldParserType !== this._parserType) {\n                this._parser.setParser(this._mode, this._parserType, this.codeMirror);\n            }\n            this._oldParserType = this._parserType;\n        } else if (textType === Vim.TEXT_TYPE_PY) {\n            this._parserType = Vim.PARSER_TYPE_BLOCK_TO_PY;\n            if (this._oldParserType !== this._parserType) {\n                this._parser.setParser(this._mode, this._parserType, this.codeMirror);\n            }\n            this._oldParserType = this._parserType;\n        }\n\n        if (Entry.playground) {\n            this._currentObject = Entry.playground.object;\n        }\n\n        this._parser._hasDeclaration = false;\n\n        if (textType === Vim.TEXT_TYPE_PY) {\n            if (this._currentObject) {\n                codeDescription = `# ${this._currentObject.name}${Lang.TextCoding.python_code}`;\n                textCode = this._parser.parse(code, Entry.Parser.PARSE_GENERAL);\n\n                if (textType === Vim.TEXT_TYPE_PY) {\n                    textCode = codeDescription\n                        .concat('\\n\\n')\n                        .concat(Vim.PYTHON_IMPORT_ENTRY)\n                        .concat(Vim.PYTHON_IMPORT_HW)\n                        .concat('\\n\\n')\n                        .concat(textCode);\n                }\n                this.codeMirror.setValue(textCode);\n                if (textType === Vim.TEXT_TYPE_PY) {\n                    this.codeMirror\n                        .getDoc()\n                        .markText(\n                            { line: 0, ch: 0 },\n                            { line: Vim.INEDITABLE_LINE_PY, ch: 0 },\n                            { readOnly: true, inclusiveLeft: true }\n                        );\n                }\n\n                doc = this.codeMirror.getDoc();\n                doc.setCursor({ line: doc.lastLine() - 1 });\n            } else {\n                this.clearText();\n            }\n        } else if (textType === Vim.TEXT_TYPE_JS) {\n            textCode = this._parser.parse(code, Entry.Parser.PARSE_GENERAL);\n            this.codeMirror.setValue(textCode);\n            doc = this.codeMirror.getDoc();\n            doc.setCursor({ line: doc.lastLine() - 1 });\n        }\n\n        if (Entry.isTextMode) {\n            this._parser._onRunError = false;\n        }\n    }\n\n    getCodeToText(code, parseType) {\n        this.#setParserUsingOldTextType();\n\n        return parseType\n            ? this._parser.parse(code, parseType)\n            : this._parser.parse(code, Entry.Parser.PARSE_SYNTAX);\n    }\n\n    setParserAvailableCode(blockMenuCode, boardCode) {\n        this._parser.setAvailableCode(blockMenuCode, boardCode);\n    }\n\n    getBlockSyntax(datum) {\n        let syntax = null;\n        this.#setParserUsingOldTextType();\n\n        if (this._parser._execParser) {\n            syntax = this._parser._execParser.searchSyntax(datum);\n        }\n\n        return syntax;\n    }\n\n    #getAssistScope() {\n        const execParser = this._parser._execParser;\n        if (execParser && execParser.getAssistScope) {\n            return execParser.getAssistScope();\n        }\n    }\n\n    #setParserUsingOldTextType() {\n        const textType = this.workspace.oldTextType;\n\n        if (textType === Vim.TEXT_TYPE_JS) {\n            this._parserType = Vim.PARSER_TYPE_BLOCK_TO_JS;\n            this._parser.setParser(this._mode, this._parserType, this.codeMirror);\n        } else if (textType === Vim.TEXT_TYPE_PY) {\n            this._parserType = Vim.PARSER_TYPE_BLOCK_TO_PY;\n            this._parser.setParser(this._mode, this._parserType, this.codeMirror);\n        }\n    }\n\n    #handleDragEnd = (e) => {\n        const block = e.block;\n\n        if (!block) {\n            return;\n        }\n\n        const codeMirror = this.codeMirror;\n        const textCode = this.getCodeToText(block, Entry.Parser.PARSE_BLOCK);\n\n        codeMirror.display.dragFunctions.leave(e);\n        codeMirror.display.scroller.dispatchEvent(Entry.Utils.createMouseEvent('mousedown', e));\n\n        const testArr = textCode.split('\\n');\n        const max = testArr.length - 1;\n        let statementCursorLine = this.doc.getCursor().line;\n        testArr.forEach((text, i) => {\n            if (i !== max) {\n                text += '\\n';\n            }\n            codeMirror.replaceSelection(text);\n        });\n\n        //set cursor for statement block\n        if (block.statements && block.statements.length) {\n            statementCursorLine++;\n            codeMirror.setCursor(statementCursorLine);\n            if (codeMirror.getLine(statementCursorLine)) {\n                codeMirror.replaceSelection('\\n');\n                codeMirror.setCursor(statementCursorLine);\n            }\n            CodeMirror.commands.indentAuto(codeMirror);\n        }\n\n        codeMirror.display.scroller.dispatchEvent(Entry.Utils.createMouseEvent('mouseup', e));\n    };\n\n    #handleDragOver = (e) => {\n        this.codeMirror.display.dragFunctions.over(e);\n    };\n}\n\nEntry.Vim = Vim;\n"
  },
  {
    "path": "src/playground/workspace.js",
    "content": "import { Destroyer } from '../util/destroyer/Destroyer';\nimport debounce from 'lodash/debounce';\n\nEntry.Workspace = class Workspace {\n    schema = {\n        selectedBlockView: null,\n        selectedBoard: null,\n    };\n\n    constructor(options) {\n        Entry.Model(this, false);\n        this._destroyer = this._destroyer || new Destroyer();\n        this._destroyer.destroy();\n        this.scale = 1;\n        this.dSetMode = debounce(this.setMode, 200);\n        this.dReDraw = debounce(this.reDraw, 150);\n\n        this.observe(this, '_handleChangeBoard', ['selectedBoard'], false);\n        this.trashcan = new Entry.FieldTrashcan();\n        this.zoomController = new Entry.ZoomController();\n\n        this.readOnly = options.readOnly === undefined ? false : options.readOnly;\n\n        this.blockViewMouseUpEvent = new Entry.Event(this);\n        this.widgetUpdateEvent = new Entry.Event(this);\n        this.reDrawEvent = new Entry.Event(this);\n        this._blockViewMouseUpEvent = null;\n        this.widgetUpdateEveryTime = false;\n        this._hoverBlockView = null;\n\n        let option = options.blockMenu;\n        if (option) {\n            this.blockMenu = new Entry.BlockMenu(\n                option.dom,\n                option.align,\n                option.categoryData,\n                option.scroll\n            );\n            this._destroyer.add(this.blockMenu);\n            this.blockMenu.workspace = this;\n            this.blockMenu.observe(this, '_setSelectedBlockView', ['selectedBlockView'], false);\n        }\n\n        option = options.board;\n        if (option) {\n            option.workspace = this;\n            option.readOnly = this.readOnly;\n            this.board = new Entry.Board(option);\n            this.board.observe(this, '_setSelectedBlockView', ['selectedBlockView'], false);\n            this.set({ selectedBoard: this.board });\n\n            if (this.blockMenu) {\n                this.blockMenu.enableTrashcan();\n            }\n        }\n\n        option = options.vimBoard;\n        if (option) {\n            this.vimBoard = new Entry.Vim(option.dom);\n            this.vimBoard.workspace = this;\n        }\n\n        if (this.board && this.vimBoard) {\n            this.vimBoard.hide();\n        }\n\n        Entry.GlobalSvg.createDom();\n\n        this.mode = Entry.Workspace.MODE_BOARD;\n\n        this.attachKeyboardCapture();\n\n        // view state change event\n        this.changeEvent = new Entry.Event(this);\n\n        Entry.commander.setCurrentEditor('board', this.board);\n\n        if (options.textType !== undefined) {\n            this.textType = options.textType;\n        } else {\n            this.textType = Entry.Vim.TEXT_TYPE_PY;\n        }\n\n        this.oldMode = Entry.Workspace.MODE_BOARD;\n        this.mode = Entry.Workspace.MODE_BOARD;\n    }\n\n    getBoard() {\n        return this.board;\n    }\n\n    getSelectedBoard() {\n        return this.selectedBoard;\n    }\n\n    getBlockMenu() {\n        return this.blockMenu;\n    }\n\n    getVimBoard() {\n        return this.vimBoard;\n    }\n\n    getMode() {\n        return this.mode;\n    }\n\n    setMode(mode, message, isForce) {\n        if (\n            Entry.options &&\n            !Entry.options.textCodingEnable &&\n            Entry.Workspace.MODE_VIMBOARD === mode.boardType\n        ) {\n            return;\n        }\n\n        Entry.disposeEvent.notify();\n\n        const playground = Entry.playground;\n\n        if (!isForce && !checkObjectAndAlert(playground && playground.object)) {\n            return false;\n        } // change mode fail\n\n        if (Entry.Utils.isNumber(mode)) {\n            this.mode = mode;\n        } else {\n            this.mode = mode.boardType;\n            this.runType = mode.runType;\n            this.textType = mode.textType;\n        }\n\n        this.mode = Number(this.mode);\n        if (this.oldMode === this.mode) {\n            return;\n        }\n        Entry.variableContainer.updateList();\n\n        const VIM = Entry.Vim;\n        const WORKSPACE = Entry.Workspace;\n        const blockMenu = this.blockMenu;\n        const Util = Entry.TextCodingUtil;\n        const dispatchChangeBoardEvent = () => {\n            this.oldMode = this.mode;\n            Entry.isTextMode = this.mode === WORKSPACE.MODE_VIMBOARD;\n\n            blockMenu.align();\n            Entry.dispatchEvent('workspaceChangeMode');\n            this.changeEvent.notify(message);\n            Entry.dispatchEvent('cancelBlockMenuDynamic');\n        };\n\n        const changeToPythonMode = () => {\n            try {\n                this.board && this.board.hide();\n                this.overlayBoard && this.overlayBoard.hide();\n                this.set({ selectedBoard: this.vimBoard });\n                this.vimBoard.show();\n                blockMenu.banClass('functionInit', true);\n                this.codeToText(this.board.code, mode);\n                this.oldTextType = this.textType;\n                this.board.clear();\n            } catch (e) {\n                this.vimBoard.hide();\n                this.board.show();\n                blockMenu.unbanClass('functionInit');\n                this.set({ selectedBoard: this.board });\n                this.mode = WORKSPACE.MODE_BOARD;\n                mode.boardType = WORKSPACE.MODE_BOARD;\n                if (this.oldTextType === VIM.TEXT_TYPE_JS) {\n                    mode.runType = VIM.MAZE_MODE;\n                } else if (this.oldTextType === VIM.TEXT_TYPE_PY) {\n                    mode.runType = VIM.WORKSPACE_MODE;\n                }\n                e.block && Entry.getMainWS() && Entry.getMainWS().board.activateBlock(e.block);\n            } finally {\n                this.oldMode = 1;\n                this.mode = 1;\n            }\n        };\n\n        switch (this.mode) {\n            case WORKSPACE.MODE_VIMBOARD: {\n                const alertMessage =\n                    Util.validateVariableAndListToPython() ||\n                    Util.validateFunctionToPython() ||\n                    Util.hasNotSupportedBlocks();\n\n                const invalidEditorModeErrorMessage = Util.canConvertTextModeForOverlayMode(\n                    Entry.Workspace.MODE_VIMBOARD\n                );\n                if (invalidEditorModeErrorMessage) {\n                    Entry.modal.alert(invalidEditorModeErrorMessage);\n                    return;\n                }\n\n                if (alertMessage) {\n                    if (alertMessage.type === 'warning') {\n                        Entry.modal.confirm(alertMessage.message).then((result) => {\n                            if (result) {\n                                Entry.variableContainer.removeNotPythonSupportedFunction();\n                                Entry.expansion?.banExpansionBlocks(Entry.expansionBlocks);\n                                Entry.aiUtilize?.banAIUtilizeBlocks(Entry.aiUtilizeBlocks);\n                                Entry.hwLite?.banClassAllHardwareLite();\n                                Entry.playground?.dataTable?.removeAllBlocks();\n                                Entry.aiLearning?.removeAllBlocks();\n                                Util.removeNotSupportedBlock();\n                                Entry.playground.blockMenu.banClass('python_disable');\n                                // 블럭 삭제되고 처리\n                                requestAnimationFrame(() => {\n                                    changeToPythonMode();\n                                    dispatchChangeBoardEvent();\n                                });\n                            } else {\n                                const mode = {};\n                                mode.boardType = WORKSPACE.MODE_BOARD;\n                                mode.textType = -1;\n                                Entry.getMainWS().setMode(mode);\n                                dispatchChangeBoardEvent();\n                            }\n                        });\n                    } else if (alertMessage.type === 'error') {\n                        Entry.modal.alert(alertMessage.message);\n\n                        const mode = {};\n                        mode.boardType = WORKSPACE.MODE_BOARD;\n                        mode.textType = -1;\n                        Entry.getMainWS().setMode(mode);\n                        dispatchChangeBoardEvent();\n                        break;\n                    }\n                } else {\n                    changeToPythonMode();\n                    dispatchChangeBoardEvent();\n                }\n                break;\n            }\n            case WORKSPACE.MODE_BOARD:\n                try {\n                    this.board.show();\n                    blockMenu.unbanClass('functionInit', true);\n                    Entry.playground.blockMenu.unbanClass('python_disable');\n                    this.set({ selectedBoard: this.board });\n                    this.textToCode(this.oldMode, this.oldTextType);\n                    if (this.overlayBoard) {\n                        this.overlayBoard.hide();\n                    }\n                    this.oldTextType = this.textType;\n                    this.vimBoard && this.vimBoard.hide();\n                } catch (e) {\n                    if (this.board && this.board.code) {\n                        this.board.code.clear();\n                    }\n                    if (this.board) {\n                        this.board.hide();\n                    }\n                    this.set({ selectedBoard: this.vimBoard });\n                    blockMenu.banClass('functionInit');\n\n                    this.mode = WORKSPACE.MODE_VIMBOARD;\n\n                    if (this.oldTextType === VIM.TEXT_TYPE_JS) {\n                        this.boardType = WORKSPACE.MODE_VIMBOARD;\n                        this.textType = VIM.TEXT_TYPE_JS;\n                        this.runType = VIM.MAZE_MODE;\n                    } else if (this.oldTextType === VIM.TEXT_TYPE_PY) {\n                        this.boardType = WORKSPACE.MODE_VIMBOARD;\n                        this.textType = VIM.TEXT_TYPE_PY;\n                        this.runType = VIM.WORKSPACE_MODE;\n                    }\n                }\n                Entry.commander.setCurrentEditor('board', this.board);\n                dispatchChangeBoardEvent();\n                break;\n\n            case WORKSPACE.MODE_OVERLAYBOARD:\n                if (this.oldMode === WORKSPACE.MODE_VIMBOARD) {\n                    this.overlayModefrom = WORKSPACE.MODE_VIMBOARD;\n                } else if (this.oldMode === WORKSPACE.MODE_BOARD) {\n                    this.overlayModefrom = WORKSPACE.MODE_BOARD;\n                }\n\n                if (!this.overlayBoard) {\n                    this.initOverlayBoard();\n                }\n                this.overlayBoard.show();\n                this.set({ selectedBoard: this.overlayBoard });\n                Entry.commander.setCurrentEditor('board', this.overlayBoard);\n                dispatchChangeBoardEvent();\n                break;\n        }\n\n        function checkObjectAndAlert(object, message) {\n            if (Entry.type === 'workspace' && !object) {\n                Entry.modal.alert(message || Lang.Workspace.object_not_exist_error);\n                return false;\n            }\n            return true;\n        }\n    }\n\n    changeBoardCode(code, cb) {\n        this._syncTextCode();\n        const isVim = this.mode === Entry.Workspace.MODE_VIMBOARD;\n        this.board.changeCode(code, isVim, cb);\n        if (isVim) {\n            const mode = {};\n            mode.textType = this.textType;\n            mode.boardType = this.boardType;\n            mode.runType = this.runType;\n            this.codeToText(this.board.code, mode);\n        }\n    }\n\n    changeOverlayBoardCode(code) {\n        if (this.overlayBoard) {\n            this.overlayBoard.changeCode(code);\n        }\n    }\n\n    changeBlockMenuCode(code) {\n        this.blockMenu.changeCode(code);\n    }\n\n    textToCode(mode, oldTextType) {\n        if (!this.vimBoard || mode !== Entry.Workspace.MODE_VIMBOARD) {\n            return;\n        }\n\n        const changedCode = this.vimBoard.textToCode(oldTextType);\n\n        const board = this.board;\n        const code = board.code;\n        if (!code) {\n            return;\n        }\n\n        code.load(changedCode);\n        this.changeBoardCode(code);\n        setTimeout(() => {\n            if (code.view) {\n                code.view.reDraw();\n                this.board.alignThreads();\n            }\n        }, 0);\n    }\n\n    codeToText(code, mode) {\n        if (!this.vimBoard) {\n            return;\n        }\n\n        code = code || this.board.code;\n        mode = mode || {\n            textType: this.textType,\n            boardType: this.boardType,\n            runType: this.runType,\n        };\n\n        return this.vimBoard.codeToText(code, mode);\n    }\n\n    getCodeToText(code) {\n        if (!this.vimBoard) {\n            return;\n        }\n\n        return this.vimBoard.getCodeToText(code);\n    }\n\n    _setSelectedBlockView() {\n        const view = 'selectedBlockView';\n        const blockView =\n            this.board[view] ||\n            this.blockMenu[view] ||\n            (this.overlayBoard ? this.overlayBoard[view] : null);\n\n        this._unbindBlockViewMouseUpEvent();\n\n        this.set({ selectedBlockView: blockView });\n\n        if (!blockView) {\n            return;\n        }\n\n        this.setHoverBlockView();\n        this._blockViewMouseUpEvent = blockView.mouseUpEvent.attach(this, () => {\n            this.blockViewMouseUpEvent.notify(blockView);\n        });\n    }\n\n    initOverlayBoard() {\n        this.overlayBoard = new Entry.Board({\n            dom: this.board.view,\n            workspace: this,\n            isOverlay: true,\n            scale: this.scale,\n        });\n        this.overlayBoard.changeCode(new Entry.Code([]));\n        this.overlayBoard.workspace = this;\n        this.overlayBoard.observe(this, '_setSelectedBlockView', ['selectedBlockView'], false);\n    }\n\n    _keyboardControl(e, isForce) {\n        if (Entry.Loader && !Entry.Loader.isLoaded()) {\n            return;\n        }\n        const keyCode = e.keyCode || e.which;\n        const ctrlKey = e.ctrlKey;\n        const shiftKey = e.shiftKey;\n        const altKey = e.altKey;\n        const playground = Entry.playground;\n        const object = playground && playground.object ? playground.object : undefined;\n\n        if (Entry.Utils.isInInput(e) && !isForce) {\n            return;\n        }\n\n        const isVimMode = this._isVimMode();\n\n        const blockView = this.selectedBlockView;\n        const board = this.selectedBoard;\n        const isBoardReadOnly = board.readOnly;\n        let checkKeyCodes;\n\n        if (ctrlKey) {\n            checkKeyCodes = [219, 221];\n\n            if (checkKeyCodes.indexOf(keyCode) > -1) {\n                if (!checkObjectAndAlert(object)) {\n                    return;\n                }\n            }\n\n            const mainWorksapceMode = Entry.playground.mainWorkspace.getMode();\n            const playgroundMode = Entry.playground.getViewMode();\n            const isBlockCodeView =\n                (mainWorksapceMode === Entry.Workspace.MODE_OVERLAYBOARD ||\n                    mainWorksapceMode === Entry.Workspace.MODE_BOARD) &&\n                (playgroundMode === 'code' || playgroundMode === 'variable');\n            switch (keyCode) {\n                case 86: //paste\n                    if (\n                        !isBoardReadOnly &&\n                        board &&\n                        board instanceof Entry.Board &&\n                        Entry.clipboard &&\n                        isBlockCodeView\n                    ) {\n                        Entry.do('addThread', Entry.clipboard)\n                            .value.getFirstBlock()\n                            .copyToClipboard();\n                    }\n                    break;\n                case 219: {\n                    //setMode(block) for textcoding ( ctrl + [ )\n                    if (\n                        !Entry.options.textCodingEnable ||\n                        Entry.playground.getViewMode() === 'picture'\n                    ) {\n                        return;\n                    }\n                    const oldMode = Entry.getMainWS().oldMode;\n                    if (oldMode === Entry.Workspace.MODE_OVERLAYBOARD) {\n                        return;\n                    }\n\n                    this.dSetMode({\n                        boardType: Entry.Workspace.MODE_BOARD,\n                        textType: -1,\n                    });\n                    e.preventDefault();\n                    break;\n                }\n                case 221: {\n                    //setMode(python) for textcoding ( ctrl + ] )\n                    if (\n                        !Entry.options.textCodingEnable ||\n                        Entry.playground.getViewMode() === 'picture'\n                    ) {\n                        return;\n                    }\n\n                    const message = Entry.TextCodingUtil.canConvertTextModeForOverlayMode(\n                        Entry.Workspace.MODE_VIMBOARD\n                    );\n                    if (message) {\n                        Entry.modal.alert(message);\n                        return;\n                    }\n\n                    this.dSetMode({\n                        boardType: Entry.Workspace.MODE_VIMBOARD,\n                        textType: Entry.Vim.TEXT_TYPE_PY,\n                        runType: Entry.Vim.WORKSPACE_MODE,\n                    });\n                    e.preventDefault();\n                    break;\n                }\n                case 67:\n                    if (\n                        blockView &&\n                        !blockView.isInBlockMenu &&\n                        blockView.block.isDeletable() &&\n                        blockView.block.isCopyable()\n                    ) {\n                        blockView.block.copyToClipboard();\n                    }\n                    break;\n                case 88:\n                    if (\n                        !isBoardReadOnly &&\n                        blockView &&\n                        !blockView.isInBlockMenu &&\n                        blockView.block.isDeletable()\n                    ) {\n                        (function (block) {\n                            block.copyToClipboard();\n                            Entry.do('destroyBlockBelow', block);\n                            blockView.getBoard().setSelectedBlock(null);\n                        })(blockView.block);\n                    }\n                    break;\n            }\n        } else if (altKey) {\n            checkKeyCodes = [49, 50, 51, 52, 219, 221];\n\n            if (checkKeyCodes.indexOf(keyCode) > -1) {\n                if (!checkObjectAndAlert(object)) {\n                    return;\n                }\n            }\n\n            switch (keyCode) {\n                case 49:\n                    playground.changeViewMode('code');\n                    e.preventDefault();\n                    break;\n                case 50:\n                    playground.changeViewMode('picture');\n                    e.preventDefault();\n                    break;\n                case 51:\n                    playground.changeViewMode('sound');\n                    e.preventDefault();\n                    break;\n                case 52:\n                    playground.toggleOnVariableView();\n                    playground.changeViewMode('variable');\n                    e.preventDefault();\n                    break;\n                case 219:\n                    if (Entry.container) {\n                        e.preventDefault();\n                        Entry.container.selectNeighborObject('prev');\n                    }\n                    break;\n                case 221:\n                    if (Entry.container) {\n                        e.preventDefault();\n                        Entry.container.selectNeighborObject('next');\n                    }\n                    break;\n            }\n        } else if (shiftKey) {\n            switch (keyCode) {\n                case 9:\n                    if (isVimMode) {\n                        CodeMirror.commands.indentLess(this.vimBoard.codeMirror);\n                        e.preventDefault();\n                    }\n                    break;\n            }\n        } else {\n            switch (keyCode) {\n                case 9:\n                    if (isVimMode) {\n                        CodeMirror.commands.indentMore(this.vimBoard.codeMirror);\n                        e.preventDefault();\n                    }\n                    break;\n                case 8:\n                case 46:\n                    if (\n                        !isBoardReadOnly &&\n                        blockView &&\n                        !blockView.isInBlockMenu &&\n                        blockView.block.isDeletable() &&\n                        !blockView.isFieldEditing()\n                    ) {\n                        if (Entry.engine.isState('stop')) {\n                            Entry.do('destroyBlock', blockView.block);\n                            this.board.set({ selectedBlockView: null });\n                            e.preventDefault();\n                        }\n                    }\n                    break;\n            }\n        }\n\n        //delay for fields value applied\n        setTimeout(() => {\n            Entry.disposeEvent && Entry.disposeEvent.notify(e);\n        }, 0);\n\n        function checkObjectAndAlert(object, message) {\n            if (!object) {\n                message = message || Lang.Workspace.object_not_exist_error;\n                Entry.modal.alert(message);\n                return false;\n            }\n            return true;\n        }\n    }\n\n    _handleChangeBoard() {\n        const board = this.selectedBoard;\n        if (!board) {\n            return;\n        }\n        if (board.constructor === Entry.Board) {\n            this.zoomController.setBoard(board);\n            this.trashcan.setBoard(board);\n        }\n    }\n\n    _syncTextCode() {\n        if (\n            this.mode !== Entry.Workspace.MODE_VIMBOARD ||\n            (Entry.engine && Entry.engine.isState('run'))\n        ) {\n            return;\n        }\n\n        const changedCode = this.vimBoard.textToCode(this.textType);\n\n        const board = this.board;\n        const code = board.code;\n        if (code) {\n            code.load(changedCode);\n        }\n\n        const event = Entry.creationChangedEvent;\n        event && event.notify(true);\n    }\n\n    addVimBoard(dom) {\n        if (this.vimBoard) {\n            return;\n        }\n        this.vimBoard = new Entry.Vim(dom);\n        this.vimBoard.workspace = this;\n        this.vimBoard.hide();\n    }\n\n    getParserType() {\n        return this.vimBoard._parserType;\n    }\n\n    getBlockViewRenderMode() {\n        switch (this.mode) {\n            case Entry.Workspace.MODE_BOARD:\n            case Entry.Workspace.MODE_OVERLAYBOARD:\n                return Entry.BlockView.RENDER_MODE_BLOCK;\n            case Entry.Workspace.MODE_VIMBOARD:\n                return Entry.BlockView.RENDER_MODE_TEXT;\n        }\n    }\n\n    _isVimMode() {\n        return this.oldMode === Entry.Workspace.MODE_VIMBOARD;\n    }\n\n    isVimMode = this._isVimMode;\n\n    attachKeyboardCapture() {\n        if (Entry.keyPressed) {\n            this._keyboardEvent && this.detachKeyboardCapture();\n            this._keyboardEvent = Entry.keyPressed.attach(this, this._keyboardControl);\n        }\n    }\n\n    detachKeyboardCapture() {\n        if (Entry.keyPressed && this._keyboardEvent) {\n            this._keyboardEvent.destroy();\n            delete this._keyboardEvent;\n        }\n    }\n\n    _unbindBlockViewMouseUpEvent() {\n        if (this._blockViewMouseUpEvent) {\n            this._blockViewMouseUpEvent.destroy();\n            this._blockViewMouseUpEvent = null;\n        }\n    }\n\n    setWidgetUpdateEveryTime(val) {\n        this.widgetUpdateEveryTime = !!val;\n    }\n\n    syncCode() {\n        switch (this.mode) {\n            case Entry.Workspace.MODE_VIMBOARD:\n                this._syncTextCode();\n                break;\n        }\n    }\n\n    setHoverBlockView(blockView) {\n        const oldBlockView = this._hoverBlockView;\n        oldBlockView && oldBlockView.resetBackgroundPath();\n\n        this._hoverBlockView = blockView;\n        blockView && blockView.setBackgroundPath();\n    }\n\n    reDraw() {\n        const blockMenu = this.blockMenu;\n        const board = this.board;\n        const overlayBoard = this.overlayBoard;\n\n        blockMenu && blockMenu.reDraw();\n        board && board.reDraw();\n        overlayBoard && overlayBoard.reDraw();\n\n        if (blockMenu || board || overlayBoard) {\n            this.reDrawEvent.notify();\n        }\n    }\n\n    getCurrentBoard() {\n        const { MODE_BOARD, MODE_VIMBOARD, MODE_OVERLAYBOARD } = Entry.Workspace;\n\n        switch (this.mode) {\n            case MODE_BOARD:\n                return this.getBoard();\n            case MODE_VIMBOARD:\n                return this.getVimBoard();\n            case MODE_OVERLAYBOARD:\n                return this.overlayBoard;\n        }\n    }\n\n    setScale(scale = 1) {\n        this.scale = scale;\n        this.board.setScale(scale);\n        Entry.GlobalSvg.setScale(scale);\n        if (this.overlayBoard) {\n            this.overlayBoard.setScale(scale);\n        }\n    }\n\n    destroy() {\n        this._destroyer.destroy();\n    }\n};\n\nEntry.Workspace.MODE_BOARD = 0;\nEntry.Workspace.MODE_VIMBOARD = 1;\nEntry.Workspace.MODE_OVERLAYBOARD = 2;\n"
  },
  {
    "path": "src/playground/zoom_controller.js",
    "content": "import Toast from './toast';\n\nEntry.ZoomController = class ZoomController {\n    constructor(board) {\n        this.boardMap = new Map();\n        if (board) {\n            this.setBoard(board);\n        }\n        if (Entry.windowResized) {\n            Entry.windowResized.attach(this, this.setPosition);\n        }\n    }\n\n    get CONTROLLER_WIDTH() {\n        return 128;\n    }\n\n    get CONTROLLER_HEIGHT() {\n        return 38;\n    }\n\n    get ZOOM_RANGE() {\n        return [0.6, 0.8, 1, 1.3, 1.6, 2];\n    }\n\n    get ZOOM_MODE() {\n        return {\n            RESET: 0,\n            OUT: 1,\n            IN: 2,\n        };\n    }\n\n    get view() {\n        return this.svgGroup;\n    }\n\n    ZOOM_LEVEL = 2;\n\n    generateView() {\n        const zoomGroup = {\n            svgZoom: this.nowBoard.svg.elem('g'),\n        };\n        this.renderStart(zoomGroup);\n        this.addControl(zoomGroup);\n        zoomGroup.toast = new Toast(this.nowBoard);\n        return zoomGroup;\n    }\n\n    renderStart(zoomGroup) {\n        const {\n            btn_zoom_bg = `${Entry.mediaFilePath}btn_zoom_bg.svg`,\n            btn_zoom_out = `${Entry.mediaFilePath}btn_zoom_out.svg`,\n            btn_zoom_reset = `${Entry.mediaFilePath}btn_zoom_reset.svg`,\n            btn_zoom_in = `${Entry.mediaFilePath}btn_zoom_in.svg`,\n        } = EntryStatic.images || {};\n        const isSafari = Entry.getBrowserType().indexOf('Safari') >= 0;\n        const shadowFilter = isSafari ? 'none' : 'url(#entryButtonShadowFilter)';\n        zoomGroup.svgZoom.elem('image', {\n            href: btn_zoom_bg,\n            width: this.CONTROLLER_WIDTH,\n            height: this.CONTROLLER_HEIGHT,\n        });\n        zoomGroup.zoomOut = zoomGroup.svgZoom.elem('image', {\n            href: btn_zoom_out,\n            x: 4,\n            y: 3,\n            width: 32,\n            height: 32,\n            filter: shadowFilter,\n            style: 'cursor: default; cursor: -moz-zoom-out; cursor: -webkit-zoom-out; cursor: -ms-zoom-out; cursor: -o-zoom-out;',\n        });\n        zoomGroup.zoomReset = zoomGroup.svgZoom.elem('image', {\n            id: 'zoom_reset',\n            href: btn_zoom_reset,\n            x: 44,\n            y: 3,\n            width: 40,\n            height: 32,\n            filter: shadowFilter,\n            style: 'cursor: pointer;',\n        });\n        zoomGroup.zoomIn = zoomGroup.svgZoom.elem('image', {\n            href: btn_zoom_in,\n            x: 92,\n            y: 3,\n            width: 32,\n            height: 32,\n            filter: shadowFilter,\n            style: 'cursor: default; cursor: -moz-zoom-in; cursor: -webkit-zoom-in; cursor: -ms-zoom-in; cursor: -o-zoom-in;',\n        });\n    }\n\n    addControl(zoomGroup) {\n        if (this.nowBoard) {\n            $(zoomGroup.svgZoom).bind('mousedown touchstart', (e) => {\n                e.stopImmediatePropagation();\n            });\n            $(zoomGroup.zoomOut).bind('mousedown touchstart', (e) => {\n                this.zoomChange(this.ZOOM_MODE.OUT);\n            });\n            $(zoomGroup.zoomReset).bind('mousedown touchstart', (e) => {\n                this.zoomChange(this.ZOOM_MODE.RESET);\n            });\n            $(zoomGroup.zoomIn).bind('mousedown touchstart', (e) => {\n                this.zoomChange(this.ZOOM_MODE.IN);\n            });\n        }\n    }\n\n    zoomChange(mode) {\n        switch (mode) {\n            case this.ZOOM_MODE.OUT:\n                if (this.ZOOM_LEVEL > 0) {\n                    this.ZOOM_LEVEL -= 1;\n                    this.setScale(this.ZOOM_RANGE[this.ZOOM_LEVEL]);\n                }\n                break;\n            case this.ZOOM_MODE.IN:\n                if (this.ZOOM_LEVEL < this.ZOOM_RANGE.length - 1) {\n                    this.ZOOM_LEVEL += 1;\n                    this.setScale(this.ZOOM_RANGE[this.ZOOM_LEVEL]);\n                }\n                break;\n            case this.ZOOM_MODE.RESET:\n            default:\n                const resetIndex = this.ZOOM_RANGE.indexOf(1);\n                if (this.ZOOM_LEVEL !== resetIndex) {\n                    this.ZOOM_LEVEL = 2;\n                    this.setScale(this.ZOOM_RANGE[this.ZOOM_LEVEL]);\n                }\n                break;\n        }\n    }\n\n    setScale(scale = 1) {\n        const zoomGroup = this.boardMap.get(this.nowBoard);\n        const { workspace } = this.nowBoard;\n        workspace.setScale(scale);\n        zoomGroup.toast.show(`${scale * 100}%`);\n        const { scroller } = this.nowBoard;\n        scroller.resizeScrollBar && scroller.resizeScrollBar.call(scroller);\n    }\n\n    setPosition() {\n        if (!this.nowBoard) {\n            return;\n        }\n        var svgDom = this.nowBoard.svgDom;\n        this.x = svgDom.width() - (this.CONTROLLER_WIDTH + 22.5);\n        this.y = 8;\n        this.align();\n    }\n\n    getPosition() {\n        return {\n            x: this.x,\n            y: this.y,\n        };\n    }\n\n    align() {\n        var position = this.getPosition();\n        this.boardMap.forEach((zoomGroup) => {\n            zoomGroup.svgZoom.attr({\n                transform: `translate(${position.x}, ${position.y})`,\n            });\n        });\n    }\n\n    setBoard(board) {\n        this.nowBoard = board;\n        const zoomGroup = this.boardMap.get(board);\n        if (!zoomGroup) {\n            this.boardMap.set(board, this.generateView());\n        }\n        this.setPosition();\n    }\n\n    destroy() {\n        this.boardMap.forEach((zoomGroup) => {\n            if (zoomGroup.toast) {\n                zoomGroup.toast.destroy();\n            }\n        });\n        delete this.nowBoard;\n        delete this.boardMap;\n    }\n};\n"
  },
  {
    "path": "src/textcoding/ast/jsAstGenerator.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.JsAstGenerator = function() {};\n\n(function(p) {\n    p.generate = function(code) {\n        return arcon.parse(code);\n    };\n})(Entry.JsAstGenerator.prototype);\n"
  },
  {
    "path": "src/textcoding/ast/pyAstGenerator.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.PyAstGenerator = function() {};\n\n(function(p) {\n    p.generate = function(code) {\n        var filbertParse = filbert.parse;\n        var locations = true;\n        var ranges = true;\n        var options = { locations: locations, ranges: ranges };\n        try {\n            var astTree = filbertParse(code, options);\n            return astTree;\n        } catch (error) {\n            var msgTokens = error.message.split(\"'\");\n            var title = Entry.TextCodingError.TITLE_SYNTAX;\n            console.log('msgTokens', msgTokens);\n\n            var message, subject;\n            if (error.expectedType && error.tokType) {\n                if (error.tokType === 'eof' || error.tokType === 'newline')\n                    message =\n                        Lang.TextCoding.message_conv_is_expect1 +\n                        this.getTokenLang(error.expectedType) +\n                        Lang.TextCoding.message_conv_is_expect2;\n                else\n                    message = Lang.TextCoding.message_conv_instead\n                        .replace('%1', this.getTokenLang(error.tokType))\n                        .replace('%2', this.getTokenLang(error.expectedType));\n                subject = Entry.TextCodingError.SUBJECT_SYNTAX_TOKEN;\n            } else if (error.tokType) {\n                if (error.tokType === 'eof' || error.tokType === 'newline')\n                    message =\n                        Entry.TextCodingError.MESSAGE_SYNTAX_UNEXPECTED_TOKEN;\n                else\n                    message =\n                        Lang.TextCoding.message_conv_is_wrong1 +\n                        this.getTokenLang(error.tokType) +\n                        Lang.TextCoding.message_conv_is_wrong2;\n                subject = Entry.TextCodingError.SUBJECT_SYNTAX_TOKEN;\n            } else if (msgTokens[0].trim() == 'Unexpected token') {\n                message = Entry.TextCodingError.MESSAGE_SYNTAX_UNEXPECTED_TOKEN;\n                subject = Entry.TextCodingError.SUBJECT_SYNTAX_TOKEN;\n            } else if (msgTokens[0].trim() == 'Unexpected character') {\n                message =\n                    Entry.TextCodingError.MESSAGE_SYNTAX_UNEXPECTED_CHARACTER;\n                subject = Entry.TextCodingError.SUBJECT_SYNTAX_CHARACTER;\n            } else if (msgTokens[0].trim() == 'Reserved variable word') {\n                message = Entry.TextCodingError.MESSAGE_SYNTAX_RESERVED_TOKEN;\n                subject = Entry.TextCodingError.SUBJECT_CONV_VARIABLE;\n            } else if (msgTokens[0].trim() == 'Reserved list word') {\n                message =\n                    Entry.TextCodingError.MESSAGE_SYNTAX_RESERVED_TOKEN_LIST;\n                subject = Entry.TextCodingError.SUBJECT_CONV_LIST;\n            } else if (msgTokens[0].trim() == 'Unexpected indent') {\n                message =\n                    Entry.TextCodingError.MESSAGE_SYNTAX_UNEXPECTED_CHARACTER;\n                subject = Entry.TextCodingError.SUBJECT_SYNTAX_INDENT;\n            } else {\n                message = Entry.TextCodingError.MESSAGE_SYNTAX_DEFAULT;\n                subject = Entry.TextCodingError.SUBJECT_SYNTAX_DEFAULT;\n            }\n\n            if (msgTokens[1]) var keyword = msgTokens[1];\n\n            error.title = Lang.TextCoding[title] || title;\n            error.message = Lang.TextCoding[message] || message;\n            error.keyword = keyword || '';\n            error.subject = Lang.TextCoding[subject] || subject;\n\n            throw error;\n        }\n    };\n\n    p.getTokenLang = function(token) {\n        if (Array.isArray(token)) {\n            var tokens = token.map(this._getTokenLang);\n            var lastToken = tokens.pop();\n            return (\n                tokens.join(', ') + Lang.TextCoding.message_conv_or + lastToken\n            );\n        } else return this._getTokenLang(token);\n    };\n\n    p._getTokenLang = function(token) {\n        return Lang.TextCoding[token] || '\"' + token + '\"';\n    };\n})(Entry.PyAstGenerator.prototype);\n"
  },
  {
    "path": "src/textcoding/data_processing/map.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.Map = function() {\n    var map = {};\n    map.repo = {};\n    this._map = map;\n};\n\n(function(p) {\n    p.getKey = function(id) {\n        return id;\n    };\n\n    p.put = function(id, value) {\n        var key = this.getKey(id);\n        this._map.repo[key] = value;\n    };\n\n    p.contains = function(id) {\n        var key = this.getKey(id);\n        if (this._map.repo[key]) {\n            return true;\n        } else {\n            return false;\n        }\n    };\n\n    p.get = function(id) {\n        var key = this.getKey(id);\n        if (this._map.repo[key]) {\n            return this._map.repo[key];\n        }\n        return null;\n    };\n\n    p.remove = function(id) {\n        var key = this.getKey(id);\n        if (this.contains(id)) {\n            this._map.repo[key] = undefined;\n        }\n    };\n\n    p.clear = function() {\n        this._map.repo = {};\n    };\n\n    p.toString = function() {\n        return this._map.repo;\n    };\n})(Entry.Map.prototype);\n"
  },
  {
    "path": "src/textcoding/data_processing/queue.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.Queue = function() {\n    this.head = null;\n    this.tail = null;\n};\n\nfunction Node(data) {\n    this.data = data;\n    this.next = null;\n}\n\n(function(p) {\n    p.enqueue = function(data) {\n        var newNode = new Node(data);\n\n        if (this.head === null) {\n            this.head = newNode;\n            this.tail = newNode;\n        } else {\n            this.tail.next = newNode;\n            this.tail = newNode;\n        }\n    };\n\n    p.dequeue = function() {\n        var newNode;\n        if (this.head !== null) {\n            newNode = this.head.data;\n            this.head = this.head.next;\n        }\n        return newNode;\n    };\n\n    p.clear = function() {\n        while (this.dequeue()) {}\n    };\n\n    p.toString = function() {\n        var curr = this.head;\n        var items = [];\n        while (curr) {\n            items.push(curr.data);\n            curr = curr.next;\n        }\n\n        return items.toString();\n    };\n})(Entry.Queue.prototype);\n"
  },
  {
    "path": "src/textcoding/error/textCodingError.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.TextCodingError = {};\n\n(function(tce) {\n    tce.TITLE_SYNTAX = 'title_syntax';\n    tce.TITLE_CONVERTING = 'title_converting';\n\n    tce.MESSAGE_SYNTAX_DEFAULT = 'message_syntax_default';\n    tce.MESSAGE_SYNTAX_UNEXPECTED_TOKEN = 'message_syntax_unexpected_token';\n    tce.MESSAGE_SYNTAX_UNEXPECTED_CHARACTER = 'message_syntax_unexpected_character';\n    tce.MESSAGE_SYNTAX_UNEXPECTED_INDENT = 'message_syntax_unexpected_indent';\n    tce.MESSAGE_SYNTAX_RESERVED_TOKEN = 'message_syntax_reserved_token';\n    tce.MESSAGE_SYNTAX_RESERVED_TOKEN_LIST = 'message_syntax_reserved_token_list';\n\n    tce.MESSAGE_CONV_DEFAULT = 'message_conv_default';\n    tce.MESSAGE_CONV_NO_SUPPORT = 'message_conv_no_support';\n    tce.MESSAGE_CONV_NO_VARIABLE = 'message_conv_no_variable';\n    tce.MESSAGE_CONV_NO_LIST = 'message_conv_no_list';\n    tce.MESSAGE_CONV_NO_OBJECT = 'message_conv_no_object';\n    tce.MESSAGE_CONV_NO_FUNCTION = 'message_conv_no_function';\n    tce.MESSAGE_CONV_NO_ENTRY_EVENT_FUNCTION = 'message_conv_no_entry_event_function';\n\n    tce.SUBJECT_SYNTAX_DEFAULT = 'subject_syntax_default';\n    tce.SUBJECT_SYNTAX_TOKEN = 'subject_syntax_token';\n    tce.SUBJECT_SYNTAX_CHARACTER = 'subject_syntax_character';\n    tce.SUBJECT_SYNTAX_INDENT = 'subject_syntax_indent';\n\n    tce.SUBJECT_CONV_DEFAULT = 'subject_conv_default';\n    tce.SUBJECT_CONV_GENERAL = 'subject_conv_general';\n    tce.SUBJECT_CONV_VARIABLE = 'subject_conv_variable';\n    tce.SUBJECT_CONV_LIST = 'subject_conv_list';\n    tce.SUBJECT_CONV_OBJECT = 'subject_conv_object';\n    tce.SUBJECT_CONV_FUNCTION = 'subject_conv_function';\n\n    //No Converting Message\n    tce.ALERT_VARIABLE_EMPTY_TEXT_ADD_CHANGE = 'alert_variable_empty_text_add_change';\n    tce.ALERT_LIST_EMPTY_TEXT_ADD_CHANGE = 'alert_list_empty_text_add_change';\n    tce.ALERT_LIST_CONTAINS_EXCEED_LENGTH_VALUE = 'alert_list_contains_exceed_length_value';\n    tce.ALERT_FUNCTION_NAME_EMPTY_TEXT_ADD_CHANGE = 'alert_function_name_empty_text_add_change';\n    tce.ALERT_VARIABLE_EMPTY_TEXT = 'alert_variable_empty_text';\n    tce.ALERT_LIST_EMPTY_TEXT = 'alert_list_empty_text';\n    tce.ALERT_FUNCTION_NAME_FIELD_MULTI = 'alert_function_name_field_multi';\n    tce.ALERT_FUNCTION_NAME_DISORDER = 'alert_function_name_disorder';\n    tce.ALERT_FUNCTION_HAS_BOOLEAN = 'alert_function_has_boolean';\n    tce.ALERT_FUNCTION_EDITOR = 'alert_function_editor';\n    tce.ALERT_FUNCTION_NO_SUPPORT = 'alert_function_no_support';\n    tce.ALERT_LIST_NO_SUPPORT = 'alert_list_no_support';\n    tce.ALERT_VARIABLE_NO_SUPPORT = 'alert_variable_no_support';\n    tce.ALERT_SIGNAL_NO_SUPPORT = 'alert_signal_no_support';\n    tce.ALERT_LEGACY_NO_SUPPORT = 'alert_legacy_no_support';\n    tce.ALERT_NO_SAVE_ON_ERROR = 'alert_no_save_on_error';\n    tce.ALERT_API_NO_SUPPORT = 'alert_api_no_support';\n\n    const error = {};\n\n    tce.error = function(title, message, keyword, line, subject) {\n        console.log('error control', title, message, keyword, line);\n        const errorInfo = this.getErrorInfo(title, message, keyword, line, subject);\n        error.title = errorInfo.title;\n        error.message = errorInfo.message;\n        error.line = line;\n        throw error;\n    };\n\n    tce.getErrorInfo = function(title, message, keyword, line, subject) {\n        const info = {};\n        info.title = Lang.TextCoding[title];\n        var message = Lang.TextCoding[message];\n\n        let contents;\n        if (keyword) {\n            var kw = `'${keyword}' `;\n        } else {\n            var kw = '';\n        }\n\n        if (subject) {\n            var sj = Lang.TextCoding[subject];\n        } else {\n            var sj = Lang.TextCoding[this.SUBJECT_CONV_GENERAL];\n        }\n\n        if (typeof line === 'object') {\n            line = line.start.line + 2;\n        }\n\n        contents = `[${sj}]` + ` ${kw} : ${message} ` + `(line ${line})`;\n\n        info.message = contents;\n\n        return info;\n    };\n})(Entry.TextCodingError);\n"
  },
  {
    "path": "src/textcoding/hint/python.js",
    "content": "/*\n *\n */\n'use strict';\n\n// CodeMirror, copyright (c) by Marijn Haverbeke and others\n// Distributed under an MIT license: http://codemirror.net/LICENSE\n//\nEntry.PyHint = function(syntax) {\n    this.setSyntax(syntax);\n    this.lastHW = null;\n\n    this._blockMenu = Entry.getMainWS().blockMenu;\n\n    CodeMirror.registerHelper('hint', 'python', this.pythonHint.bind(this));\n\n    var hwFunc = function(e) {\n        if (Entry.hw.hwModule) {\n            var name = Entry.hw.hwModule.name;\n            name = name[0].toUpperCase() + name.slice(1);\n            if (name === 'ArduinoExt') this.addScope('Arduino', 'Ext');\n            else this.addScope(name);\n            this.lastHW = name;\n        } else {\n            this.removeScope(this.lastHW);\n            this.lastHW = null;\n        }\n    }.bind(this);\n\n    Entry.addEventListener('hwChanged', hwFunc);\n\n    if (Entry.hw.hwModule) hwFunc();\n};\n\n(function(p) {\n    p.pythonHint = function(editor) {\n        var cur = editor.getCursor(),\n            tokens = editor.getLineTokens(cur.line);\n        var lastToken = tokens.pop();\n        var result = [],\n            menuResult = [];\n\n        while (lastToken && cur.ch <= lastToken.start) lastToken = tokens.pop();\n\n        if (!lastToken) return null;\n\n        var searchString;\n        var start = lastToken.start;\n        var hintFunc = this.hintFunc;\n        var syntax = this.syntax;\n\n        switch (lastToken.type) {\n            case 'builtin':\n                if (\n                    tokens[tokens.length - 2] &&\n                    tokens[tokens.length - 2].string === 'def'\n                )\n                    searchString = null;\n                else searchString = lastToken.string;\n            case 'def':\n                if (!searchString) {\n                    var defToken = tokens[tokens.length - 2];\n                    if (defToken) {\n                        searchString = 'def ' + lastToken.string;\n                        start = defToken.start;\n                    }\n                }\n            case 'keyword':\n                if (!searchString) searchString = lastToken.string;\n            case 'variable':\n                if (!searchString) searchString = lastToken.string;\n                result = this.fuzzySearch(\n                    this.getScope('_global'),\n                    searchString\n                );\n                result = result.map(function(key) {\n                    var localSyntax = syntax;\n                    var displayText = key.split('#')[0];\n                    displayText = displayText.split('\\n').join(' ');\n                    displayText = displayText.replace(/%\\d+/gi, '');\n                    displayText = displayText.replace(/\\$\\d+/gi, '');\n                    var localKey;\n                    if (key.indexOf('.') > -1) {\n                        key = key.split('.');\n                        localSyntax = syntax[key[0]];\n                        localKey = key.shift();\n                        key = key.join('.');\n                    }\n                    if (localSyntax[key].key)\n                        menuResult.push(this.getMenuElement(localSyntax[key]));\n                    return {\n                        displayText: displayText,\n                        hint: hintFunc,\n                        syntax: localSyntax[key],\n                        localKey: localKey,\n                    };\n                }, this);\n                break;\n            case 'property':\n                var variableToken = tokens[tokens.length - 2];\n                if (!variableToken) break;\n                var searchResult;\n                var searchScope = this.getScope(variableToken.string);\n                if (searchScope.length)\n                    searchResult = this.fuzzySearch(\n                        searchScope,\n                        lastToken.string\n                    );\n                else if (\n                    Entry.variableContainer.getListByName(variableToken.string)\n                ) {\n                    searchResult = this.fuzzySearch(\n                        this.getScope('%2'),\n                        lastToken.string\n                    );\n                    variableToken.string = '%2';\n                } else searchResult = [];\n                result = searchResult.map(function(key) {\n                    var displayText = key.split('#')[0];\n                    displayText = displayText.split('\\n')[0];\n                    return {\n                        displayText: displayText,\n                        hint: hintFunc,\n                        syntax: syntax[variableToken.string][key],\n                    };\n                });\n                var scope = this.syntax[variableToken.string];\n                menuResult = searchResult.map(function(key) {\n                    return this.getMenuElement(scope[key]);\n                }, this);\n                break;\n            default:\n                break;\n        }\n\n        if (menuResult.length) this._blockMenu._setDynamic(menuResult);\n        else this._blockMenu._cancelDynamic();\n        return {\n            list: result, // for optimize\n            from: CodeMirror.Pos(cur.line, start),\n            to: CodeMirror.Pos(cur.line, lastToken.end),\n        };\n    };\n\n    p.addScope = function(name, extName) {\n        if (this.syntax[name] && !this.scope[name]) {\n            var syntax = this.syntax;\n            if (name === 'Chocopi') {\n                for (var key in this.syntax) {\n                    if (\n                        syntax[key].syntax &&\n                        key.indexOf('%') < 0 &&\n                        syntax[key].key.indexOf('function_field') < 0\n                    ) {\n                        if (key.substr(0, 6) === 'def on')\n                            this.scope._global.push(key);\n                    }\n                }\n            }\n            syntax = this.syntax[name];\n            var keys = Object.keys(syntax);\n            keys = keys.filter(function(k) {\n                var blockSyntax = Entry.block[syntax[k].key];\n                if (\n                    name === 'Arduino' &&\n                    (extName === 'Ext') !==\n                        (blockSyntax.class &&\n                            blockSyntax.class.indexOf('Ext') > 0)\n                )\n                    return false;\n                return k.indexOf('#') < 0 && !blockSyntax.deprecated;\n            });\n            this.scope[name] = keys;\n            this.scope._global.unshift(name);\n            keys = keys.map(function(k) {\n                return name + '.' + k;\n            });\n            this.scope._global = this.scope._global.concat(keys);\n        }\n    };\n\n    p.removeScope = function(name) {\n        if (this.scope[name]) {\n            var syntax = this.syntax[name];\n            var keys = Object.keys(syntax);\n            keys = keys.filter(function(k) {\n                return (\n                    k.indexOf('#') < 0 && !Entry.block[syntax[k].key].deprecated\n                );\n            });\n            keys = keys.map(function(k) {\n                return name + '.' + k;\n            });\n\n            this.scope._global.splice(this.scope._global.indexOf(name), 1);\n            while (keys.length) {\n                var key = keys.pop();\n                this.scope._global.splice(this.scope._global.indexOf(key), 1);\n            }\n            delete this.scope[name];\n        }\n    };\n\n    p.getScope = function(name) {\n        if (this.scope[name]) return this.scope[name];\n        else return [];\n    };\n\n    p.fuzzySearch = function(arr, start, options) {\n        options = options || {};\n        options.escapeLetter = '#';\n        var result = Entry.Utils.fuzzy.filter(start, arr, options).slice(0, 20);\n        result = result.map(function(o) {\n            return o.original;\n        });\n        return result;\n    };\n\n    p.hintFunc = function(cm, self, data) {\n        var text;\n        var syntax = data.syntax;\n        var ch = self.from.ch;\n        if (!syntax.syntax) {\n            text = data.displayText + '.';\n            ch += text.length;\n        } else {\n            text = syntax.syntax;\n            if (data.localKey) {\n                text = data.localKey + '.' + text;\n            }\n            text = text.split('.');\n            if (text.length > 1) text.shift();\n            text = text.join('.');\n            if (text.indexOf('%') > -1) {\n                ch += text.indexOf('%');\n                text = text.replace(/%\\d+/gi, '');\n            } else {\n                ch += text.length;\n            }\n            text = text.replace(/\\$\\d+/gi, '');\n        }\n        if (text.indexOf('\\n') > -1) {\n            text = text.split('\\n').join('\\n' + '\\t'.repeat(self.from.ch));\n        }\n        if (text.indexOf(':') > -1) {\n            var cur = cm.getCursor(),\n                tokens = cm.getLineTokens(cur.line);\n            var newStart = tokens.shift();\n            while (tokens.length) {\n                if (newStart.type === 'keyword') break;\n                newStart = tokens.shift();\n            }\n            ch -= self.from.ch - newStart.start;\n            self.from.ch = newStart.start;\n        }\n\n        cm.replaceRange(text, self.from, self.to);\n        cm.setCursor({ line: self.from.line, ch: ch });\n        Entry.helper.renderBlock(data.syntax.key);\n    };\n\n    p.setSyntax = function(syntax) {\n        this.syntax = syntax;\n        this.scope = {};\n        this.scope._global = [];\n        this.scope._list = [];\n        for (var key in syntax) {\n            if (\n                syntax[key].syntax &&\n                key.indexOf('%') < 0 &&\n                syntax[key].key.indexOf('function_field') < 0\n            ) {\n                if (key.substr(0, 6) === 'def on') continue;\n                this.scope._global.push(key);\n            } else if (key.substr(0, 2) === 'if') this.scope._global.push(key);\n            else if (key.substr(0, 5) === 'while') this.scope._global.push(key);\n        }\n        this.addScope('Entry');\n        this.addScope('random');\n        this.addScope('math');\n        this.addScope('%2', '_list');\n\n        if (this.lastHW) this.addScope(this.lastHW);\n    };\n\n    p.getMenuElement = function(blockSyntax) {\n        var blockType = blockSyntax.key;\n        if (\n            blockSyntax.isDefault &&\n            Entry.playground.mainWorkspace.blockMenu.getThreadByBlockKey(\n                blockType\n            )\n        ) {\n            return blockType;\n        } else {\n            var params = [];\n            if (blockSyntax.params) params = params.concat(blockSyntax.params);\n            return [\n                blockSyntax.syntax,\n                {\n                    type: blockType,\n                    params: params,\n                },\n            ];\n        }\n    };\n})(Entry.PyHint.prototype);\n"
  },
  {
    "path": "src/textcoding/parser/core/block/blockToJs.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.BlockToJsParser = function(syntax, parentParser) {\n    this._type = 'BlockToJsParser';\n    this.syntax = syntax;\n\n    this._parentParser = parentParser;\n\n    this._iterVariableCount = 0;\n    this._iterVariableChunk = ['i', 'j', 'k'];\n};\n\n(function(p) {\n    p.Code = function(code, parseMode) {\n        this._parseMode = parseMode;\n        /*if (code instanceof Entry.Thread)\n            return this.Thread(code);*/\n        if (code instanceof Entry.Block) return this.Block(code);\n\n        var textCode = '',\n            threads = code._data;\n\n        for (var i = 0; i < threads.length; i++) {\n            var thread = threads[i];\n            textCode += this.Thread(thread);\n        }\n\n        return textCode.trim();\n    };\n\n    p.Thread = function(thread) {\n        if (thread instanceof Entry.Block) return this.Block(thread);\n        var code = '',\n            blocks = thread.getBlocks();\n\n        for (var i = 0; i < blocks.length; i++) {\n            var block = blocks[i];\n            if (i != blocks.length - 1) {\n                var block = this.Block(block);\n                if (this._parseMode == Entry.Parser.PARSE_GENERAL) {\n                    code += block + '\\n';\n                } else if (this._parseMode == Entry.Parser.PARSE_SYNTAX) {\n                    code = block + '\\n';\n                }\n            } else {\n                var block = this.Block(block);\n                if (this._parseMode == Entry.Parser.PARSE_GENERAL) {\n                    code += block;\n                } else if (this._parseMode == Entry.Parser.PARSE_SYNTAX) {\n                    code = block;\n                }\n            }\n        }\n        return code + '\\n';\n    };\n\n    p.Block = function(block) {\n        if (block._schema.syntax.js) var syntax = block._schema.syntax.js;\n        else var syntax = block._schema.syntax;\n\n        if (!syntax) return '';\n        var syntaxType = syntax[0];\n        var block = this[syntaxType](block);\n        return block;\n    };\n\n    p.Program = function(block) {\n        return '';\n    };\n\n    p.Scope = function(block) {\n        var notParenthesis = false;\n        var result = '';\n        var paramReg = /(%.)/im;\n        if (block._schema.syntax.js) {\n            var syntax = block._schema.syntax.js.concat();\n            notParenthesis = true;\n        } else {\n            var syntax = block._schema.syntax.concat();\n        }\n\n        syntax.shift();\n        var syntaxTokens = syntax[0].split(paramReg);\n\n        var schemaParams = block._schema.params;\n        var dataParams = block.data.params;\n\n        for (var i = 0; i < syntaxTokens.length; i++) {\n            var syntaxToken = syntaxTokens[i];\n            if (syntaxToken.length === 0 || syntaxToken === 'Scope') continue;\n            if (syntaxToken === 'Judge') {\n                notParenthesis = true;\n                continue;\n            }\n            if (paramReg.test(syntaxToken)) {\n                var paramIndex = syntaxToken.split('%')[1];\n                var index = parseInt(paramIndex) - 1;\n                if (schemaParams[index]) {\n                    if (schemaParams[index].type == 'Image') {\n                        index++;\n                    } else if (schemaParams[index].type == 'Block') {\n                        var param = this.Block(dataParams[index]);\n                        result += param;\n                    } else {\n                        result += this[schemaParams[index].type](\n                            dataParams[index],\n                            schemaParams[index]\n                        );\n                    }\n                }\n            } else {\n                result += syntaxToken;\n            }\n        }\n\n        if (result.charAt(result.length - 1) == '#') {\n            notParenthesis = true;\n            result = result.substring(0, result.length - 1);\n            result = result.trim();\n        }\n\n        if (!notParenthesis) result += '();';\n\n        result = Entry.TextCodingUtil.jsAdjustSyntax(block, result);\n\n        return result;\n\n        //return syntax.splice(1, syntax.length - 1).join(\".\") + \"();\\n\";\n    };\n\n    p.BasicFunction = function(block) {\n        var statementCode = this.Thread(block.statements[0]);\n        var code =\n            'function promise() {\\n' + this.indent(statementCode).trim() + '}';\n        return code;\n    };\n\n    p.BasicIteration = function(block) {\n        var iterateNumber = block.params[0];\n        var iterVariable = this.publishIterateVariable();\n        var statementCode = this.Thread(block.statements[0]);\n        this.unpublishIterateVariable();\n        var code =\n            'for (var ' +\n            iterVariable +\n            ' = 0; ' +\n            iterVariable +\n            ' < ' +\n            iterateNumber +\n            '; ' +\n            iterVariable +\n            '++) {\\n' +\n            this.indent(statementCode) +\n            '}';\n        return code;\n    };\n\n    p.BasicIf = function(block) {\n        var code;\n        if (block.data.statements.length == 2) {\n            var statementCode1 = this.Thread(block.statements[0]);\n            var statementCode2 = this.Thread(block.statements[1]);\n            var syntax = block._schema.syntax.concat();\n\n            var paramBlock = block.data.params[0];\n\n            if (paramBlock && paramBlock.data.type == 'True') {\n                var param = syntax[1];\n            } else {\n                if (paramBlock === undefined) var param = syntax[1];\n                else var param = this.Block(paramBlock);\n            }\n\n            code =\n                'if (' +\n                param +\n                ') {\\n' +\n                this.indent(statementCode1) +\n                '}\\n' +\n                'else {\\n' +\n                this.indent(statementCode2) +\n                '}\\n';\n        } else {\n            var statementCode1 = this.Thread(block.statements[0]);\n            var syntax = block._schema.syntax.concat();\n\n            var paramBlock = block.data.params[0];\n\n            if (paramBlock && paramBlock.data.type == 'True') {\n                var param = syntax[1];\n            } else {\n                if (paramBlock === undefined) var param = syntax[1];\n                else var param = this.Block(paramBlock);\n            }\n\n            code =\n                'if (' + param + ') {\\n' + this.indent(statementCode1) + '}\\n';\n        }\n\n        return code;\n    };\n\n    p.BasicWhile = function(block) {\n        var statementCode = this.Thread(block.statements[0]);\n        var syntax = block._schema.syntax.concat();\n        var code =\n            'while (' +\n            syntax[1] +\n            ') {\\n' +\n            this.indent(statementCode) +\n            '}\\n';\n        return code;\n    };\n\n    p.indent = function(textCode) {\n        var result = '';\n        var indentedCode = textCode.split('\\n');\n\n        for (var i in indentedCode) {\n            var item = indentedCode[i];\n\n            if (item.length == 0) continue;\n\n            result += '\\t' + item + '\\n';\n        }\n\n        return result;\n    };\n\n    // iterate variable\n    p.publishIterateVariable = function() {\n        var iterVariable = '';\n        var iterVariableCount = this._iterVariableCount;\n        do {\n            var chunk = this._iterVariableChunk[iterVariableCount % 3];\n            iterVariable = chunk + iterVariable;\n            iterVariableCount = parseInt(iterVariableCount / 3) - 1;\n            if (iterVariableCount === 0)\n                iterVariable = this._iterVariableChunk[0] + iterVariable;\n        } while (iterVariableCount > 0);\n        this._iterVariableCount++;\n        return iterVariable;\n    };\n\n    p.unpublishIterateVariable = function() {\n        if (this._iterVariableCount) this._iterVariableCount--;\n    };\n\n    p.Dropdown = function(dataParam) {\n        var value = dataParam;\n        if (value == 'OBSTACLE') value = 'stone';\n        else if (value == 'ITEM') value = value.toLowerCase();\n        else if (value == 'WALL') value = value.toLowerCase();\n\n        var result = \"'\" + value + \"'\";\n\n        return result;\n    };\n\n    p.TextInput = function(dataParam) {\n        var result = dataParam;\n\n        return result;\n    };\n\n    p.DropdownDynamic = function(dataParam, schemaParam) {\n        var object = Entry.playground.object;\n\n        if (dataParam == 'null') {\n            dataParam = 'none';\n        } else {\n            dataParam = Entry.TextCodingUtil.dropdownDynamicValueConvertor(\n                dataParam,\n                schemaParam\n            );\n        }\n\n        return dataParam;\n    };\n\n    p.searchSyntax = function(datum) {\n        if (datum instanceof Entry.BlockView) datum = datum.block;\n        return this._parentParser.parse(datum, Entry.Parser.PARSE_SYNTAX);\n    };\n\n    p.getAssistScope = function() {\n        if (this._assist) return this._assist;\n\n        var assist = {};\n        for (var key in this.syntax.Scope) {\n            if (key.indexOf('%') < 0)\n                assist[key + '();\\n'] = this.syntax.Scope[key];\n        }\n        this._assist = assist;\n        return assist;\n    };\n})(Entry.BlockToJsParser.prototype);\n"
  },
  {
    "path": "src/textcoding/parser/core/block/blockToPy.js",
    "content": "/*\n *\n */\n'use strict';\n\nimport _includes from 'lodash/includes';\n\nEntry.BlockToPyParser = class {\n    constructor() {\n        this._type = 'BlockToPyParser';\n        this._funcParamMap = new Entry.Map();\n        this.funcDefMap = {};\n\n        this.globalCommentList = [];\n\n        this._variableDeclaration = null;\n        this._listDeclaration = null;\n        this._forIdCharIndex = 0;\n    }\n\n    Code(code, parseMode) {\n        this._parseMode = parseMode;\n        if (!code) {\n            return;\n        }\n        if (code instanceof Entry.Thread) {\n            return this.Thread(code);\n        }\n        if (code instanceof Entry.Block) {\n            return this.Block(code);\n        }\n\n        const resultTextCode = [];\n        const threads = code.getThreads();\n\n        for (let i = 0; i < threads.length; i++) {\n            this._forIdCharIndex = 0;\n            const thread = threads[i];\n\n            if (thread) {\n                resultTextCode.push(this.Thread(thread));\n            }\n        }\n\n        return resultTextCode.join('\\n').trim();\n    }\n\n    Thread(thread) {\n        if (thread instanceof Entry.Block) {\n            return this.Block(thread);\n        }\n        const blocks = thread.getBlocks();\n\n        if (blocks.length === 0) {\n            return '';\n        }\n\n        if (blocks[0] instanceof Entry.Comment) {\n            this.Comment(blocks[0]);\n        } else if (this._parseMode === Entry.Parser.PARSE_SYNTAX) {\n            return blocks.map((block) => `${this.Block(block)}\\n`).trim();\n        } else if (this._parseMode === Entry.Parser.PARSE_GENERAL) {\n            let rootResult = '';\n            let contentResult = '';\n\n            blocks.forEach((block, index) => {\n                try {\n                    if (index === 0 && Entry.TextCodingUtil.isEventBlock(block)) {\n                        rootResult = `${this.Block(block)}\\n`;\n                    } else {\n                        contentResult += `${this.Block(block)}\\n`;\n                    }\n                } catch (e) {\n                    Entry.toast.alert(\n                        Lang.TextCoding.title_converting,\n                        Lang.TextCoding.alert_legacy_no_support\n                    );\n                }\n            });\n\n            if (rootResult !== '') {\n                contentResult = Entry.TextCodingUtil.indent(contentResult);\n            }\n\n            return `${(rootResult + contentResult).trim()}\\n`;\n        }\n    }\n\n    Block(block) {\n        if (!block || !(block instanceof Entry.Block)) {\n            return '';\n        }\n        !block._schema && block.loadSchema();\n\n        const results = [];\n        const syntaxObj = this.searchSyntax(block);\n        let syntax;\n\n        if (syntaxObj) {\n            syntax = syntaxObj.syntax;\n        }\n\n        // User Function\n        if (this.isFunc(block)) {\n            if (!this.funcDefMap[block.data.type]) {\n                this._rootFuncId = block.data.type;\n                this.funcDefMap[block.data.type] = this.makeFuncDef(block, this._hasRootFunc);\n                this._hasRootFunc = false;\n            }\n            if (this.isRegisteredFunc(block)) {\n                syntax = this.makeFuncSyntax(block);\n            }\n            if (this._parseMode === Entry.Parser.PARSE_SYNTAX) {\n                return syntax;\n            }\n        } else if (this.isFuncStmtParam(block)) {\n            const type = block.data.type;\n            results.push(this._funcParamMap.get(type) || type);\n        }\n\n        if (!syntax && !this.isFuncStmtParam(block)) {\n            const error = new Error();\n            error.block = block;\n            throw error;\n        }\n\n        const _blockTokens = syntax.split(/[\\r\\n]/);\n        const _blockParamRegex = /%\\d/gim;\n        const _blockStatementRegex = /\\$\\d/gim;\n\n        let isFirstCommentToken = true;\n\n        _blockTokens.forEach((token) => {\n            let tokenProcessed = token;\n            // 이재원 #7994 관련하여 만약 token (text input) 에 시작하는 템플릿이 괄호라면,\n            // 그리고 하나의 Param만 가지고 있는 경우를 regex check 후에 slice해서 사용.\n            if (_blockTokens.length == 1 && /^\\(%[\\d ]+\\)/gim.test(tokenProcessed)) {\n                tokenProcessed = tokenProcessed.slice(1, -1);\n            }\n            const paramsTemplate = tokenProcessed.match(_blockParamRegex);\n            const statements = tokenProcessed.match(_blockStatementRegex);\n            let resultTextCode = '';\n\n            // %1 과 같은 템플릿 값이 있는 경우\n            if (paramsTemplate) {\n                const paramsValue = [];\n                paramsTemplate.forEach((template) => {\n                    const [, index] = template.split('%');\n\n                    if (index) {\n                        paramsValue[index] = this._getParamsValue(index, block);\n                    }\n                });\n\n                resultTextCode += tokenProcessed.replace(\n                    /%(\\d)/gim,\n                    (_, groupMatch) => paramsValue[groupMatch]\n                );\n            }\n\n            // $1 과 같이 statement 를 포함하는 경우\n            if (statements) {\n                statements.forEach((value) => {\n                    const [, index] = value.split('$');\n                    const statementTextCodes = [];\n                    const thread = block.statements[index - 1];\n                    thread.getBlocks().forEach((block) => {\n                        if (this.getFuncInfo(block)) {\n                            statementTextCodes.push(this.makeFuncDef(block, true));\n                        } else {\n                            statementTextCodes.push(this.Block(block));\n                        }\n                    });\n                    resultTextCode += Entry.TextCodingUtil.indent(\n                        statementTextCodes.join('\\n').concat('\\n')\n                    );\n                });\n            }\n\n            // 일반 블록 처리\n            if (!statements && !paramsTemplate) {\n                resultTextCode += tokenProcessed;\n            }\n\n            // 특수 블록 처리\n            // TODO 이와 같은 처리는 블록에 정보가 있고, 정보에 따라 처리해야 한다.\n            if (syntaxObj) {\n                switch (syntaxObj.key) {\n                    case 'repeat_while_true':\n                        resultTextCode = Entry.TextCodingUtil.assembleRepeatWhileTrueBlock(\n                            block,\n                            resultTextCode\n                        );\n                        break;\n                    case 'repeat_basic': {\n                        const forStmtTokens = resultTextCode.split(' ');\n\n                        if (_includes(forStmtTokens, 'for', 'i', 'in')) {\n                            forStmtTokens[1] = Entry.TextCodingUtil.generateForStmtIndex(\n                                this._forIdCharIndex++\n                            );\n                            resultTextCode = forStmtTokens.join(' ');\n                        }\n                        break;\n                    }\n                    case 'substring': {\n                        // \"안녕 엔트리\"[1:5] -> \"안녕 엔트리\", [1:5]\n                        const tokens = resultTextCode.split(/(?=\\[)/);\n                        if (tokens.length === 2 && Entry.Utils.isNumber(tokens[0])) {\n                            tokens[0] = `\"${tokens[0]}\"`;\n                        }\n                        resultTextCode = tokens.join('');\n                        break;\n                    }\n                }\n            }\n\n            // 코멘트 처리\n            const commentValue = block.getCommentValue();\n            if (isFirstCommentToken && !statements && commentValue !== undefined) {\n                // '' 도 표기한다.\n                resultTextCode += ` # ${commentValue}`;\n                isFirstCommentToken = !isFirstCommentToken;\n            }\n\n            results.push(resultTextCode);\n        });\n\n        return results.join('\\n');\n    }\n\n    Comment(comment) {\n        this.globalCommentList.push(`# ${comment.value}`);\n    }\n\n    /**\n     * 해당 block 의 template parameter 의 실제 값을 가져온다.\n     * @param templateIndex index 번호 (%2 라면 2)\n     * @param block 추출할 블록\n     * @returns {string} 블록의 결과값\n     * @private\n     */\n    _getParamsValue(templateIndex, block) {\n        const index = Number(templateIndex) - 1;\n        const schemaParams = block._schema.params;\n        const dataParams = block.data.params;\n\n        let result = '';\n        const syntaxObj = this.searchSyntax(block);\n        const textParams = syntaxObj.textParams && syntaxObj.textParams;\n\n        if (schemaParams[index]) {\n            switch (schemaParams[index].type) {\n                case 'Indicator': {\n                    break;\n                }\n                case 'Block': {\n                    let param = this.Block(dataParams[index]).trim();\n                    const funcParam = this._funcParamMap.get(param);\n                    const textParam = textParams && textParams[index];\n\n                    if (funcParam) {\n                        param = funcParam;\n                    } else {\n                        const funcParamTokens = param.split('_');\n                        const prefix = funcParamTokens[0];\n                        if (funcParamTokens.length === 2) {\n                            if (prefix === 'stringParam') {\n                                param = 'string_param';\n                            } else if (prefix === 'booleanParam') {\n                                param = 'boolean_param';\n                            }\n                        }\n                    }\n\n                    if (textParam && textParam.paramType === 'index') {\n                        if (Entry.Utils.isNumber(param)) {\n                            param = param - 1;\n                        } else {\n                            const tokens = param.split('+');\n                            if (tokens[tokens.length - 1] === ' 1)') {\n                                delete tokens[tokens.length - 1];\n                                param = tokens.join('+');\n                                param = param.substring(1, param.length - 2);\n                            } else {\n                                param += ' - 1';\n                            }\n                        }\n                    }\n\n                    if (textParam && textParam.paramType === 'integer') {\n                        if (Entry.Utils.isNumber(param) && Entry.isFloat(param)) {\n                            result = result.replace('randint', 'uniform');\n                        }\n                    }\n\n                    result += param;\n                    break;\n                }\n                default: {\n                    const textParam = textParams && textParams[index];\n\n                    let param;\n                    if (textParam && textParam.type) {\n                        param = this[`Field${textParam.type}`](dataParams[index], textParam);\n                    } else {\n                        param = this[`Field${schemaParams[index].type}`](\n                            dataParams[index],\n                            textParam\n                        );\n                    }\n                    const isTypeNumber = Entry.Utils.isNumber(param);\n\n                    // 필드 블록이 아닌 블록에 내재된 파라미터 처리\n                    if (\n                        !Entry.Utils.isNumber(param) &&\n                        (block.type === 'when_some_key_pressed' ||\n                            block.type === 'is_press_some_key')\n                    ) {\n                        if (\n                            !Entry.KeyboardCode.map[\n                                typeof param === 'string' ? param.toLowerCase() : param\n                            ]\n                        ) {\n                            Entry.toast.alert(Lang.Msgs.warn, Lang.Msgs.parameter_can_not_space);\n                            throw Error('');\n                        }\n\n                        result += `\"${param}\"`;\n                    } else if (\n                        !isTypeNumber &&\n                        Entry.Utils.isNumber(param) &&\n                        (block.type === 'number' || block.type === 'string')\n                    ) {\n                        result += `\"${param}\"`;\n                    } else {\n                        result += param;\n                    }\n\n                    break;\n                }\n            }\n        }\n        return result;\n    }\n\n    searchSyntax(datum) {\n        let schema;\n        let appliedParams;\n        if (datum instanceof Entry.BlockView) {\n            schema = datum.block._schema;\n            appliedParams = datum.block.data.params;\n        } else if (datum instanceof Entry.Block) {\n            schema = datum._schema;\n            appliedParams = datum.params;\n        } else {\n            schema = datum;\n        }\n\n        if (schema && schema.syntax && schema.syntax.py && schema.syntax.py.length > 0) {\n            const syntaxes = schema.syntax.py.concat();\n            while (syntaxes.length) {\n                let isFail = false;\n                const syntax = syntaxes.shift();\n                if (typeof syntax === 'string') {\n                    return { syntax, template: syntax };\n                }\n\n                if (syntax.params) {\n                    for (let i = 0; i < syntax.params.length; i++) {\n                        if (syntax.params[i] && syntax.params[i] !== appliedParams[i]) {\n                            isFail = true;\n                            break;\n                        }\n                    }\n                }\n                if (!syntax.template) {\n                    syntax.template = syntax.syntax;\n                }\n                if (isFail) {\n                    continue;\n                }\n                return syntax;\n            }\n        }\n        return null;\n    }\n\n    FieldAngle(dataParam, textParam) {\n        if (textParam && textParam.converter) {\n            dataParam = textParam.converter(dataParam);\n        }\n\n        return dataParam;\n    }\n\n    FieldColor(dataParam, textParam) {\n        if (textParam && textParam.converter) {\n            dataParam = textParam.converter(null, dataParam);\n        }\n        return dataParam;\n    }\n\n    FieldDropdown(dataParam, textParam) {\n        if (typeof dataParam === 'object') {\n            return 'None'.replace(/\\\"/gm, '');\n        }\n\n        if (textParam && textParam.converter && textParam.options) {\n            const options = textParam.options;\n            for (const i in options) {\n                const key = options[i][0];\n                const value = options[i][1];\n                if (dataParam == value) {\n                    return (dataParam = textParam.converter(key, value));\n                }\n            }\n            dataParam = textParam.converter(dataParam, dataParam);\n        }\n\n        return dataParam;\n    }\n\n    FieldDropdownDynamic(dataParam, textParam) {\n        if (typeof dataParam === 'object') {\n            return 'None'.replace(/\\\"/gm, '');\n        }\n\n        if (textParam && textParam.converter && textParam.options) {\n            const options = textParam.options;\n            for (const i in options) {\n                let key = options[i][0];\n                const value = options[i][1];\n                if (dataParam == value) {\n                    const name = Entry.TextCodingUtil.dropdownDynamicIdToNameConvertor(\n                        value,\n                        textParam.menuName\n                    );\n                    if (name) {\n                        key = name;\n                    }\n                    return (dataParam = textParam.converter(key, value));\n                }\n            }\n            const value = Entry.TextCodingUtil.dropdownDynamicIdToNameConvertor(\n                dataParam,\n                textParam.menuName\n            );\n            if (value) {\n                dataParam = textParam.converter(value, value);\n            } else {\n                dataParam = textParam.converter(dataParam, dataParam);\n            }\n\n            const reg = /None/;\n            if (reg.test(dataParam)) {\n                dataParam = dataParam.replace(/\\\"/gm, '');\n            }\n        }\n\n        return dataParam;\n    }\n\n    FieldImage(dataParam, textParam) {\n        if (textParam && textParam.converter) {\n            dataParam = textParam.converter(null, dataParam);\n        }\n\n        return dataParam;\n    }\n\n    FieldIndicator(dataParam, textParam) {\n        return dataParam;\n    }\n\n    FieldKeyboard(dataParam, textParam) {\n        const reg = /None/;\n        if (reg.test(dataParam)) {\n            return dataParam.replace(/\\\"/gm, '');\n        }\n\n        const map = Entry.KeyboardCode.map;\n        for (const key in map) {\n            const value = map[key];\n            if (value == dataParam) {\n                dataParam = key;\n                break;\n            }\n        }\n\n        if (textParam && textParam.converter) {\n            dataParam = textParam.converter(dataParam, null);\n        }\n\n        dataParam = dataParam.toLowerCase();\n        return dataParam;\n    }\n\n    FieldOutput(dataParam, textParam) {\n        return dataParam;\n    }\n\n    FieldText(dataParam, textParam) {\n        if (textParam && textParam.converter) {\n            dataParam = textParam.converter(null, dataParam);\n        }\n\n        return dataParam;\n    }\n\n    FieldTextInput(dataParam, textParam) {\n        if (typeof dataParam !== 'number') {\n            dataParam = dataParam.replace('\\t', '    ');\n            const spaces = dataParam.split(/ /);\n\n            if (dataParam.length == spaces.length - 1) {\n                dataParam = '\"()\"'.replace('()', dataParam);\n            }\n        }\n\n        if (textParam && textParam.converter) {\n            dataParam = textParam.converter(null, dataParam);\n        }\n\n        return dataParam;\n    }\n\n    FieldNumber(dataParam, textParam) {\n        if (textParam && textParam.converter) {\n            dataParam = textParam.converter(null, dataParam);\n        }\n\n        return dataParam;\n    }\n\n    isFunc(block) {\n        if (!block || !block.data || !block.data.type) {\n            return false;\n        }\n\n        const tokens = block.data.type.split('_');\n        const prefix = tokens[0];\n\n        return prefix === 'func';\n    }\n\n    /**\n     * 워크스페이스에 실제로 등록되어있는 함수인지 확인한다.\n     * @param block\n     * @returns {boolean}\n     */\n    isRegisteredFunc(block) {\n        const tokens = block.data.type.split('_');\n        const funcId = tokens[1];\n        return !!Entry.variableContainer.functions_[funcId];\n    }\n\n    isFuncStmtParam(block) {\n        if (!block || !block.data || !block.data.type) {\n            return false;\n        }\n        const blockType = block.data.type;\n        const tokens = blockType.split('_');\n        const prefix = tokens[0];\n\n        return prefix === 'stringParam' || prefix === 'booleanParam';\n    }\n\n    /**\n     * functionTemplate 에서 파이선에서 표기될 함수를 만들어낸다.\n     * ex) 함수 %1 %2 %3 + %3 이 Indicator 인 경우 => 함수(%1, %2)\n     * @param funcBlock{Block} 함수 블록\n     * @return {string} 파이선 함수 호출 syntax\n     */\n    makeFuncSyntax(funcBlock) {\n        let schemaTemplate = '';\n\n        if (funcBlock) {\n            if (funcBlock._schema) {\n                if (funcBlock._schema.template) {\n                    schemaTemplate = funcBlock._schema.template.trim();\n                }\n            } else if (this._hasRootFunc) {\n                const rootFunc = Entry.block[this._rootFuncId];\n                schemaTemplate = rootFunc.block.template;\n            }\n        }\n\n        const templateParams = schemaTemplate.trim().match(/%\\d/gim);\n        templateParams.pop(); // pop() 이유는 맨 마지막 템플릿은 Indicator 로 판단할 것이기 때문이다.\n\n        return Entry.TextCodingUtil.getFunctionNameFromTemplate(schemaTemplate)\n            .trim()\n            .concat(`(${templateParams.join(',')})`);\n    }\n\n    makeFuncDef(funcBlock, isExpression) {\n        if (!this.isRegisteredFunc(funcBlock)) {\n            return;\n        }\n\n        let result = '';\n        const func = this.getFuncInfo(funcBlock);\n\n        if (func) {\n            result += func.name;\n        } else {\n            return;\n        }\n\n        let paramResult = '';\n        if (func.params && func.params.length !== 0) {\n            paramResult = func.params.join(', ').trim();\n        }\n        result = result.concat('(').concat(paramResult).concat(')');\n\n        if (isExpression) {\n            // 선언된 함수 사용하는 블록의 경우\n            const expBlockComment = funcBlock.getCommentValue();\n            if (expBlockComment || expBlockComment === '') {\n                result += ` # ${expBlockComment}`;\n            }\n            return result;\n        } else {\n            // 함수 선언 중인 경우\n            this._hasRootFunc = true;\n\n            result = `def ${result}`;\n            result = result.concat(':');\n            if (func.comment || func.comment === '') {\n                result += ` # ${func.comment}`;\n            }\n            result += '\\n';\n\n            if (func.statements && func.statements.length) {\n                let stmtResult = '';\n                for (const s in func.statements) {\n                    const block = func.statements[s];\n\n                    if (this.getFuncInfo(block)) {\n                        stmtResult += this.makeFuncDef(block, true).concat('\\n');\n                    } else {\n                        stmtResult += this.Block(block).concat('\\n');\n                    }\n                }\n                result += Entry.TextCodingUtil.indent(stmtResult).concat('\\n');\n            }\n\n            return result.trim();\n        }\n    }\n\n    getFuncInfo(funcBlock) {\n        const result = {};\n        const funcId = funcBlock.getFuncId();\n\n        const func = funcId && Entry.variableContainer.getFunction(funcId);\n        if (!func) {\n            return null;\n        }\n\n        const funcName = Entry.TextCodingUtil.getFunctionNameFromTemplate(func.block.template);\n\n        Entry.TextCodingUtil.initQueue();\n\n        const funcContents = func.content.getEventMap('funcDef')[0].getThread().getBlocks();\n        const statements = func.content.getEventMap('funcDef')[0].getStatements().getBlocks();\n        statements.forEach((value) => funcContents.push(value));\n        const defBlock = funcContents.shift();\n\n        const funcComment = defBlock.getCommentValue();\n\n        Entry.TextCodingUtil.gatherFuncDefParam(defBlock.getParam(0));\n\n        const that = this;\n        const funcParams = [];\n\n        if (!this._hasRootFunc) {\n            const funcDefParams = [];\n            let param;\n            while ((param = Entry.TextCodingUtil._funcParamQ.dequeue())) {\n                funcDefParams.push(param);\n            }\n\n            funcDefParams.forEach((value, index) => {\n                if (/(string|boolean)Param/.test(value)) {\n                    index += 1;\n                    const name = `param${index}`;\n                    funcParams.push(name);\n                    that._funcParamMap.put(value, name);\n                }\n            });\n        } else {\n            funcBlock.params\n                .filter((p) => p instanceof Entry.Block)\n                .forEach((p) => {\n                    let paramText = that.Block(p);\n                    if (!paramText) {\n                        return;\n                    }\n                    paramText = that._funcParamMap.get(paramText) || paramText;\n                    funcParams.push(paramText);\n                });\n        }\n\n        Entry.TextCodingUtil.clearQueue();\n\n        if (funcName) {\n            result.name = funcName;\n        }\n        if (funcComment || funcComment === '') {\n            result.comment = funcComment;\n        }\n        if (funcParams.length !== 0) {\n            result.params = funcParams;\n        }\n        if (funcContents.length !== 0) {\n            result.statements = funcContents;\n        }\n\n        return result;\n    }\n};\n"
  },
  {
    "path": "src/textcoding/parser/core/text/jsToBlock.js",
    "content": "/*\n *\n */\n\"use strict\";\n\nEntry.JsToBlockParser = function(syntax, parentParser) {\n    this._type =\"JsToBlockParser\";\n    this.syntax = syntax;\n\n    this.scopeChain = [];\n    this.scope = null;\n\n    this._blockCount = 0;\n    this._blockInfo = {};\n    this._parentParser = parentParser;\n};\n\n(function(p){\n    p.Program = function(astArr) {\n        var code = [];\n        var thread = [];\n\n        thread.push({\n            type: this.syntax.Program\n        });\n\n        for(var index in astArr) {\n            var node = astArr[index];\n            if(node.type != 'Program') return;\n\n            //block statement\n            var separatedBlocks = this.initScope(node);\n            var blocks = this.BlockStatement(node);\n\n            for(var i in blocks) {\n                var block = blocks[i];\n\n                thread.push(block);\n            }\n\n            this.unloadScope();\n            if(thread.length != 0)\n                code.push(thread);\n        }\n        return code;\n    };\n\n    p.Identifier = function(node) {\n        return node.name;\n    };\n\n    p.Literal = function(node, type) {\n        if(node.value === true)\n            return {type:'True'};\n        else if(node.value === false)\n            return {type:'False'};\n\n        if(type == \"ai_distance_value\")\n            return node.value;\n        else if(type == \"ai_boolean_object\")\n            return node.value;\n        else\n            return {type: 'text', params: [node.value] };\n    };\n\n    // Statement\n    p.ExpressionStatement = function(node) {\n        var expression = node.expression;\n        return this[expression.type](expression);\n    };\n\n    p.ForStatement = function(node) {\n        var init = node.init,\n            test = node.test,\n            update = node.update,\n            body = node.body;\n\n        var contents = \"\";\n\n        var blockType = this.syntax.ForStatement;\n\n        if (!blockType) {\n            body = this[body.type](body);\n\n            var startVal = init.declarations[0].init.value;\n            var test = test;\n            var op = test.operator;\n            var endVal = test.right.value;\n            var updateOp = update.operator;\n\n            var res = 0;\n            if(!(updateOp == '++')){\n                var temp = startVal;\n                var startVal = endVal;\n                var endVal = temp;\n            }\n\n            switch (op) {\n                case '<':\n                    res = endVal - startVal;\n                break;\n\n                case '<=':\n                    res = ((endVal+1) - startVal);\n                break;\n\n                case '>':\n                    res =  startVal - endVal;\n                break;\n\n                case '>=':\n                    res = ((startVal+ 1) - endVal);\n                break;\n            }\n\n            return this.BasicIteration(node, res, body);\n        } else {\n            throw {\n                message : '지원하지 않는 표현식 입니다.',\n                node : node\n            };\n        }\n    };\n\n    p.BlockStatement = function(node) {\n        var blocks = [];\n        var body = node.body;\n\n        for (var i = 0; i < body.length; i++) {\n            var bodyData = body[i];\n            var block = this[bodyData.type](bodyData);\n\n            if(!Entry.TextCodingUtil.hasBlockInfo(bodyData, this._blockInfo))\n                this._blockCount++;\n\n            Entry.TextCodingUtil.updateBlockInfo(bodyData, this._blockInfo);\n\n            if(!block) continue;\n            else if (block.type === undefined) {\n                throw {\n                    title : '블록변환 오류',\n                    message : '지원하지 않는 블록입니다.',\n                    node : bodyData,\n                    blockCount : this._blockCount\n                };\n            } else if (Entry.TextCodingUtil.isParamBlock(block)) {\n            } else if (block) {\n                blocks.push(block);\n            }\n        }\n\n        return blocks;\n    };\n\n    p.EmptyStatement = function(node) {\n        throw {\n            message : 'empty는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.DebuggerStatement = function(node) {\n        throw {\n            message : 'debugger는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.WithStatement = function(node) {\n        var object = node.object,\n            body = node.body;\n\n        throw {\n            message : 'with는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    //control flow\n    p.ReturnStaement = function(node) {\n        var args = node.arguments;\n\n        throw {\n            message : 'return은 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.LabeledStatement = function(node) {\n        var label = node.label,\n            body = node.body;\n\n        throw {\n            message : 'label은 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.BreakStatement = function(node) {\n        var label = node.label;\n\n        throw {\n            message : 'break는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.ContinueStatement = function(node) {\n        var label = node.label;\n\n        throw {\n            message : 'continue는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.IfStatement = function(node) {\n        var test = node.test,\n            consequent = node.consequent,\n            alternate  = node.alternate;\n\n        var blockType = this.syntax.BasicIf;\n        if (blockType) {\n            return this.BasicIf(node);\n        } else {\n            throw {\n                message : 'if는 지원하지 않는 표현식 입니다.',\n                node : node\n            };\n        }\n\n    };\n\n    p.SwitchStatement = function(node) {\n        var discriminant = node.discriminant,\n            cases = node.cases;\n\n        throw {\n            message : 'switch는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.SwitchCase = function(node) {\n        var test = node.test,\n            consequent = node.consequent;\n\n        throw {\n            message : 'switch ~ case는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    //throwstatement\n\n    p.ThrowStatement = function(node) {\n        var args = node.arguments;\n\n        throw {\n            message : 'throw는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.TryStatement = function(node) {\n        var block = node.block,\n            handler = node.handler,\n            finalizer = node.finalizer;\n\n        throw {\n            message : 'try는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.CatchClause = function(node) {\n        var param = node.param,\n            body = node.body;\n\n        throw {\n            message : 'catch는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.WhileStatement = function(node) {\n        var test = node.test,\n            body = node.body;\n        var blockType = this.syntax.WhileStatement;\n        body = this[body.type](body);\n\n        if (!blockType) {\n            return this.BasicWhile(node, body);\n        } else {\n\n            throw {\n                message : 'while은 지원하지 않는 표현식 입니다.',\n                node : node\n            };\n        }\n    };\n\n    p.DoWhileStatement = function(node) {\n        var body = node.body,\n            test = node.test;\n\n        throw {\n            message : 'do ~ while은 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n\n    p.ForInStatement = function(node) {\n        var left = node.left,\n            right = node.right,\n            body = node.body;\n\n        throw {\n            message : 'for ~ in은 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    //Declaration\n\n    p.FunctionDeclaration = function(node) {\n        var id = node.id;\n\n        var blockType = this.syntax.FunctionDeclaration;\n\n        if (!blockType) {\n            return null;\n        } else {\n            throw {\n                message : 'function은 지원하지 않는 표현식 입니다.',\n                node : node\n            };\n        }\n    };\n\n    p.VariableDeclaration = function(node) {\n        var declaration = node.declarations,\n            kind = node.kind;\n\n        throw {\n            message : 'var은 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    // Expression\n    p.ThisExpression = function(node) {\n        return this.scope.this;\n    };\n\n    p.ArrayExpression = function(node) {\n        var elements = node.elements;\n\n        throw {\n            message : 'array는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.ObjectExpression = function(node) {\n        var property = node.property;\n\n        throw {\n            message : 'object는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.Property = function(node) {\n        var key = node.key,\n            value = node.value,\n            kind = node.kind;\n\n        throw {\n            message : 'init, get, set은 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.FunctionExpression = function(node) {\n        throw {\n            message : 'function은 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n    // unary expression\n\n    p.UnaryExpression = function(node) {\n        var operator = node.operator,\n            prefix = node.prefix,\n            args  = node.argument;\n\n        throw {\n            message : operator + '은(는) 지원하지 않는 명령어 입니다.',\n            node : node\n        };\n    };\n\n    p.UnaryOperator = function(){\n        return  [\"-\" , \"+\" , \"!\" , \"~\" , \"typeof\" , \"void\" , \"delete\"];\n    };\n\n    p.updateOperator = function() {\n        return [\"++\" , \"--\"];\n    };\n\n    //Binary expression\n    p.BinaryOperator = function() {\n        return [\n            \"==\" , \"!=\" , \"===\" , \"!==\",\n            \"<\" , \"<=\" , \">\" , \">=\",\n            \"<<\" , \">>\" , \">>>\",\n            \"+\" , \"-\" , \"*\" , \"/\" , \"%\",\n            \",\" , \"^\" , \"&\" , \"in\",\n            \"instanceof\"\n        ];\n    };\n\n    p.AssignmentExpression = function(node) {\n        var operator = node.operator,\n            left = node.left,\n            right = node.right;\n\n        throw {\n            message : operator + '은(는) 지원하지 않는 명령어 입니다.',\n            node : node\n        };\n    };\n\n    p.AssignmentOperator = function() {\n        return [\n            \"=\" , \"+=\" , \"-=\" , \"*=\" , \"/=\" , \"%=\",\n            \"<<=\" , \">>=\" , \">>>=\",\n            \",=\" , \"^=\" , \"&=\"\n        ];\n    };\n\n    p.BinaryExpression = function(node) {\n        var result = {};\n        var structure = {};\n        var operator = String(node.operator);\n        var nodeLeftName = node.left.name;\n\n        switch(operator){\n            case \"==\":\n                if(nodeLeftName == \"object_up\" || nodeLeftName == \"object_right\" || nodeLeftName == \"object_down\")\n                    var type = \"ai_boolean_object\";\n                else if(nodeLeftName == \"radar_up\" || nodeLeftName == \"radar_right\" || nodeLeftName == \"radar_down\")\n                    var type = \"ai_boolean_distance\";\n                else\n                    var type = null;\n                break;\n            case \"<\":\n                var type = \"ai_boolean_distance\";\n                break;\n            case \"<=\":\n                var type = \"ai_boolean_distance\";\n                break;\n            case \">\":\n                var type = \"ai_boolean_distance\";\n                break;\n            case \">=\":\n                var type = \"ai_boolean_distance\";\n                break;\n\n            default:\n                operator = operator;\n        }\n\n        if(type) {\n            var params = [];\n            var left = node.left;\n\n            if(left.type == \"Literal\" || left.type == \"Identifier\") {\n                var args = [];\n                args.push(left);\n                var paramsMeta = Entry.block[type].params;\n\n                for(var p in paramsMeta) {\n                    var paramType = paramsMeta[p].type;\n                    if(paramType == \"Indicator\") {\n                        var pendingArg = {raw: null, type: \"Literal\", value: null};\n                        if(p < args.length)\n                            args.splice(p, 0, pendingArg);\n                    }\n                    else if(paramType == \"Text\") {\n                        var pendingArg = {raw: \"\", type: \"Literal\", value: \"\"};\n                        if(p < args.length)\n                            args.splice(p, 0, pendingArg);\n                    }\n                }\n\n                for(var i in args) {\n                    var argument = args[i];\n\n                    var param = this[argument.type](argument);\n                    param = Entry.TextCodingUtil.radarVariableConvertor(param);\n\n                    if(param && param != null)\n                        params.push(param);\n                }\n            } else {\n                param = this[left.type](left);\n                param = Entry.TextCodingUtil.radarVariableConvertor(param);\n                if(param)\n                    params.push(param);\n            }\n\n            operator = String(node.operator);\n            if(operator) {\n                operator = Entry.TextCodingUtil.jTobBinaryOperatorConvertor(operator);\n                param = operator;\n                if(param)\n                    params.push(param);\n\n                structure.operator = operator;\n            }\n\n            var right = node.right;\n\n            if(right.type == \"Literal\" || right.type == \"Identifier\") {\n                var args = [];\n                args.push(right);\n                var paramsMeta = Entry.block[type].params;\n\n                for(var p in paramsMeta) {\n                    var paramType = paramsMeta[p].type;\n                    if(paramType == \"Indicator\") {\n                        var pendingArg = {raw: null, type: \"Literal\", value: null};\n                        if(p < args.length)\n                            args.splice(p, 0, pendingArg);\n                    }\n                    else if(paramType == \"Text\") {\n                        var pendingArg = {raw: \"\", type: \"Literal\", value: \"\"};\n                        if(p < args.length)\n                            args.splice(p, 0, pendingArg);\n                    }\n                }\n\n                for(var i in args) {\n                    var argument = args[i];\n                    var param = this[argument.type](argument);\n\n                    if(typeof param == \"string\") {\n                        var nameTokens = param.split(\"_\");\n\n                        if(nameTokens[0] == 'radar') {\n                            var result = {};\n                            result.type = \"ai_distance_value\";\n                            result.params = [];\n                            result.params.push(nameTokens[1].toUpperCase());\n                            param = result;\n                        }\n                    }\n\n                    if(param && param != null) {\n                        if(type == \"ai_boolean_object\") {\n                            param = param.params[0];\n                            params.splice(1, 1);\n                        }\n\n                        param = Entry.TextCodingUtil.tTobDropdownValueConvertor(param);\n                        params.push(param);\n\n                        if(params[2] && params[2].type != \"text\" && params[2].type != \"ai_distance_value\") {\n                           throw {\n                                message : '지원하지 않는 표현식 입니다.',\n                                node : node.test\n                            };\n                        }\n                    }\n                }\n            } else {\n                param = this[right.type](right);\n                if(type == \"ai_boolean_object\") {\n                    param = param.params[0];\n                    params.splice(1, 1);\n                }\n\n                if(param)\n                    params.push(param);\n            }\n\n            structure.type = type;\n            structure.params = params;\n        } else {\n            throw {\n                message : '지원하지 않는 표현식 입니다.',\n                node : node.test\n            };\n        }\n\n        result = structure;\n\n        return result;\n    };\n\n    p.LogicalExpression = function(node) {\n        var result;\n        var structure = {};\n\n        var operator = String(node.operator);\n\n        switch(operator){\n            case '&&':\n                var type = \"ai_boolean_and\";\n                break;\n            default:\n                var type = \"ai_boolean_and\";\n                break;\n        }\n\n        var params = [];\n        var left = node.left;\n\n        if(left.type == \"Literal\" || left.type == \"Identifier\") {\n            var args = [];\n            args.push(left);\n            var paramsMeta = Entry.block[type].params;\n\n            for(var p in paramsMeta) {\n                var paramType = paramsMeta[p].type;\n                if(paramType == \"Indicator\") {\n                    var pendingArg = {raw: null, type: \"Literal\", value: null};\n                    if(p < args.length)\n                        args.splice(p, 0, pendingArg);\n                }\n                else if(paramType == \"Text\") {\n                    var pendingArg = {raw: \"\", type: \"Literal\", value: \"\"};\n                    if(p < args.length)\n                        args.splice(p, 0, pendingArg);\n                }\n            }\n\n            for(var i in args) {\n                var argument = args[i];\n                var param = this[argument.type](argument);\n                if(param && param != null)\n                    params.push(param);\n            }\n        } else {\n            param = this[left.type](left);\n            if(param)\n                params.push(param);\n        }\n\n        operator = String(node.operator);\n        if(operator) {\n            operator = Entry.TextCodingUtil.logicalExpressionConvert(operator);\n            param = operator;\n            params.push(param);\n        }\n\n        var right = node.right;\n\n        if(right.type == \"Literal\" || right.type == \"Identifier\") {\n            var args = [];\n            args.push(right);\n            var paramsMeta = Entry.block[type].params;\n            //var paramsDefMeta = Entry.block[type].def.params;\n\n            for(var p in paramsMeta) {\n                var paramType = paramsMeta[p].type;\n                if(paramType == \"Indicator\") {\n                    var pendingArg = {raw: null, type: \"Literal\", value: null};\n                    if(p < args.length)\n                        args.splice(p, 0, pendingArg);\n                }\n                else if(paramType == \"Text\") {\n                    var pendingArg = {raw: \"\", type: \"Literal\", value: \"\"};\n                    if(p < args.length)\n                        args.splice(p, 0, pendingArg);\n                }\n            }\n\n            for(var i in args) {\n                var argument = args[i];\n                var param = this[argument.type](argument);\n\n                if(param && param != null)\n                    params.push(param);\n            }\n\n            if(params[0].type != \"True\" &&\n                params[0].type != \"ai_boolean_distance\" &&\n                params[0].type != \"ai_boolean_object\" &&\n                params[0].type != \"ai_boolean_and\" &&\n                params[0].type != \"ai_distance_value\")\n            {\n                throw {\n                    message : '지원하지 않는 명렁어 입니다.',\n                    node : node\n                }\n            }\n\n            if(params[2].type != \"True\" &&\n                params[2].type != \"ai_boolean_distance\" &&\n                params[2].type != \"ai_boolean_object\" &&\n                params[2].type != \"ai_boolean_and\" &&\n                params[2].type != \"ai_distance_value\")\n            {\n                throw {\n                    message : '지원하지 않는 명렁어 입니다.',\n                    node : node\n                }\n            }\n        } else {\n            param = this[right.type](right);\n            if(param)\n                params.push(param);\n        }\n\n        structure.type = type;\n        structure.params = params;\n\n        result = structure;\n        return result;\n    };\n\n    p.LogicalOperator = function() {\n        return [\"||\" , \"&&\"];\n    };\n\n    p.MemberExpression = function(node) {\n        var object = node.object,\n            property = node.property,\n            computed = node.computed;\n\n        object = this[object.type](object);\n\n        property = this[property.type](property, object);\n\n        if(!(Object(object) === object && Object.getPrototypeOf(object) === Object.prototype)) {\n            throw {\n                message : object + '은(는) 잘못된 멤버 변수입니다.',\n                node : node\n            };\n        }\n\n        var blockType = property;\n        if(!blockType) {\n            throw {\n                message : property + '이(가) 존재하지 않습니다.',\n                node : node\n            };\n        }\n        return blockType;\n    };\n\n    p.ConditionalExpression = function(node) {\n        var test = node.test,\n            alternate = node.alternate,\n            consequent = node.consequent;\n\n        throw {\n            message : '지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.UpdateExpression = function(node) {\n        var operator = node.operator,\n            args = node.argument,\n            prefix = node.prefix;\n\n        throw {\n            message : operator + '은(는) 지원하지 않는 명렁어 입니다.',\n            node : node\n        };\n    };\n\n    p.CallExpression = function(node) {\n        var callee = node.callee,\n            args = node.arguments;\n        var params = [];\n        var blockType = this[callee.type](callee);\n\n        var type = this.syntax.Scope[blockType];\n        var block = Entry.block[type];\n        var blockParams = block.params;\n\n        for(var i = 0; i < args.length; i++) {\n            var arg = args[i];\n            var value = this[arg.type](arg, type);\n            var paramType = blockParams[i].type;\n\n            if (paramType == \"Dropdown\") {\n                params.push(value);\n            } else if (paramType === 'Block') {\n                var paramBlock;\n                if (typeof value == 'string') {\n                    paramBlock = {type: 'text', params:[value]};\n                } else if (typeof value == 'number') {\n                    paramBlock = {type: 'number', params:[value]};\n                } else {\n                    paramBlock = value;\n                }\n                params.push(paramBlock);\n            } else {\n                params.push(value);\n            }\n\n            if (value.type !== paramType && this._parentParser) {\n                var title = Lang.Msgs.warn;\n                //lineNubmer start from 0\n                var lineNumber = this._parentParser\n                                    .getLineNumber(node.start, node.end)\n                                    .from.line + 1;\n                var content = Lang.TextCoding.warn_unnecessary_arguments;\n                content = content\n                    .replace('&(calleeName)', callee.name)\n                    .replace('&(lineNumber)', lineNumber);\n                Entry.toast.warning(title, content);\n            }\n        }\n\n        return {\n            type: type,\n            params: params\n        };\n    };\n\n    p.NewExpression = function(node) {\n        throw {\n            message : 'new는 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    p.SequenceExpression = function(node) {\n        var expressions = node.expressions;\n\n        throw {\n            message : 'SequenceExpression 지원하지 않는 표현식 입니다.',\n            node : node\n        };\n    };\n\n    // scope method\n    p.initScope = function(node) {\n        if (this.scope === null) {\n            var scoper = function() {};\n            scoper.prototype = this.syntax.Scope;\n            this.scope = new scoper();\n        } else {\n            var scoper = function() {};\n            scoper.prototype = this.scope;\n            this.scope = new scoper();\n        }\n\n        this.scopeChain.push(this.scope);\n        return this.scanDefinition(node);\n    };\n\n    p.unloadScope = function() {\n        this.scopeChain.pop();\n        if (this.scopeChain.length)\n            this.scope = this.scopeChain[this.scopeChain.length - 1];\n        else\n            this.scope = null;\n    };\n\n    p.scanDefinition = function(node) {\n        var body = node.body;\n        var separatedBlocks = [];\n        for (var i = 0; i < body.length; i++) {\n            var childNode = body[i];\n            if (childNode.type === \"FunctionDeclaration\") {\n                this.scope[childNode.id.name] = this.scope.promise;\n                if (this.syntax.BasicFunction) {\n                    var childBody = childNode.body;\n                    separatedBlocks.push([{\n                        type: this.syntax.BasicFunction,\n                        statements: [this[childBody.type](childBody)]\n                    }]);\n                }\n            }\n        }\n        return separatedBlocks;\n    };\n\n    p.BasicFunction = function(node, body) {\n        return null;\n    };\n\n    // custom node parser\n    p.BasicIteration = function(node, iterCount, body) {\n        if(iterCount > 10) {\n            throw {\n                message : '반복 숫자값이 10을 넘으면 안됩니다.',\n                node : node.test\n            };\n        }\n\n        var blockType = this.syntax.BasicIteration;\n        if (!blockType)\n            throw {\n                message : '지원하지 않는 표현식 입니다.',\n                node : node\n            };\n        return {\n            params: [iterCount],\n            type: blockType,\n            statements: [body]\n        };\n    };\n\n    p.BasicWhile = function(node, body) {\n        var raw = node.test.raw;\n        if (this.syntax.BasicWhile[raw]) {\n            return {\n                type: this.syntax.BasicWhile[raw],\n                statements: [body]\n            }\n        } else {\n            throw {\n                message : '지원하지 않는 표현식 입니다.',\n                node : node.test\n            };\n        }\n    };\n\n    p.BasicIf = function(node) {\n        var result = {};\n        result.params = [];\n        result.statements = [];\n        var type;\n        var stmtCons = [];\n        var stmtAlt = [];\n        var params = [];\n        var cons = node.consequent;\n        if(cons)\n            var consequent = this[cons.type](cons);\n\n        var alt = node.alternate;\n        if(alt)\n            var alternate = this[alt.type](alt);\n\n        try{\n            var test = '';\n            if(node.test.operator)\n                var operator = (node.test.operator === '===') ? '==' : node.test.operator;\n            else\n                var operator = null;\n\n            if(node.test.left && node.test.right)\n                var testCondition = node.test.left.name + node.test.right.value;\n            else\n                var testCondition = null;\n\n            if(testCondition == \"frontwall\" && (operator == \"==\")) {\n                test = \"front == \\'wall\\'\";\n                type = this.syntax.BasicIf[test];\n            } else if(testCondition == \"fronthump\" && (operator == \"==\")) {\n                test = \"front == \\'hump\\'\";\n                type = this.syntax.BasicIf[test];\n            } else if(testCondition == \"frontstone\" && (operator == \"==\")) {\n                test = \"front == \\'stone\\'\";\n                type = this.syntax.BasicIf[test];\n            } else if(testCondition == \"frontbee\" && (operator == \"==\")) {\n                test = \"front == \\'bee\\'\";\n                type = this.syntax.BasicIf[test];\n            } else {\n                if(node.test.value || (node.test.left && node.test.right)) {\n                    type = \"ai_if_else\";\n                    var callExData = this[node.test.type](node.test, this.syntax.Scope);\n                    var value = callExData.params[2];\n                    params.push(callExData);\n                } else {\n                    throw {\n                        message : '지원하지 않는 표현식 입니다.',\n                        node : node.test\n                    };\n                }\n            }\n\n            if (type) {\n                if(consequent && consequent.length != 0){\n                    stmtCons = consequent;\n                    result.statements.push(stmtCons);\n                }\n\n                if(alternate && alternate.length != 0) {\n                    stmtAlt = alternate;\n                    result.statements.push(stmtAlt);\n                }\n\n                if(type)\n                    result.type = type;\n                if(params && params.length != 0)\n                    result.params = params;\n\n                return result;\n            } else {\n                if(consequent && consequent.length != 0)\n                    stmtCons = consequent;\n\n                if(alternate && alternate.length != 0)\n                    stmtAlt = alternate;\n\n                if(type)\n                    result.type = type;\n                if(params && params.length != 0)\n                    result.params = params;\n\n                result.statements = [stmtCons, stmtAlt];\n\n                return result;\n                //throw new Error();\n            }\n        } catch (e) {\n            throw {\n                message : '지원하지 않는 표현식 입니다.',\n                node : node.test\n            };\n        }\n    };\n\n    p.searchSyntax = function(datum) { return null; };\n})(Entry.JsToBlockParser.prototype);\n"
  },
  {
    "path": "src/textcoding/parser/core/text/pyToBlock.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.PyToBlockParser = class {\n    constructor(blockSyntax) {\n        this._type = 'PyToBlockParser';\n        this.dic = blockSyntax['#dic'];\n        this.blockSyntax = blockSyntax;\n\n        this._funcParamMap = {};\n        this._funcMap = {};\n\n        this._isInFuncDef = false;\n\n        this.util = Entry.TextCodingUtil;\n\n        this.binaryOperator = {\n            '==': 'EQUAL',\n            '!=': 'NOT_EQUAL',\n            '>': 'GREATER',\n            '<': 'LESS',\n            '>=': 'GREATER_OR_EQUAL',\n            '<=': 'LESS_OR_EQUAL',\n        };\n\n        this.arithmeticOperator = {\n            '+': 'PLUS',\n            '-': 'MINUS',\n            '*': 'MULTI',\n            '/': 'DIVIDE',\n        };\n\n        this.divideOperator = {\n            '//': 'QUOTIENT',\n            '%': 'MOD',\n        };\n\n        this.logicalOperator = {\n            '&&': 'AND',\n            '||': 'OR',\n        };\n    }\n\n    Programs(astArr) {\n        try {\n            return this.processPrograms(astArr);\n        } catch (error) {\n            throw error;\n        }\n    }\n\n    raiseError({ title = '', message = '', line }) {\n        throw { title, message, line };\n    }\n\n    processPrograms(astArr) {\n        this.createFunctionMap();\n        this._funcParamMap = {};\n        this._isInFuncDef = false;\n        const ws = Entry.playground.mainWorkspace;\n        if (ws && !ws.board.code) {\n            return [];\n        }\n        this.object = ws ? ws.board.code.object : Entry.playground.object;\n\n        let result;\n        if (!astArr[0]) {\n            return [];\n        }\n        const astArrBody = astArr[0].body;\n        const hasVariable =\n            astArrBody &&\n            astArrBody[0] &&\n            astArrBody[0].type === 'ExpressionStatement' &&\n            astArrBody[0].expression.type === 'AssignmentExpression';\n\n        if (hasVariable) {\n            const variableArr = this.getVariables(astArr[0]);\n            astArr.splice(0, 1);\n            const contentArr = astArr.map(this.Node, this);\n\n            result = variableArr.concat(contentArr);\n        } else {\n            result = astArr.map(this.Node, this);\n        }\n\n        return result.filter((t) => t.length > 0);\n    }\n\n    Program(component) {\n        const thread = component.body.map((n) => {\n            const result = this.Node(n);\n            this.assert(typeof result === 'object', '', n, 'NO_SUPPORT', 'GENERAL');\n            return result;\n        }, this);\n        if (thread[0].constructor === Array) {\n            return thread[0];\n        } else {\n            return thread;\n        }\n    }\n\n    ExpressionStatement(component) {\n        const expression = component.expression;\n        const result = this.Node(expression);\n        if (expression.comment) {\n            result.comment = expression.comment;\n        }\n\n        return result;\n    }\n\n    CallExpression(component) {\n        const callee = component.callee;\n        const args = component.arguments;\n        let obj = this.Node(callee);\n        if (obj.type && component.callee.type === 'Identifier') {\n            // Duplicate name with variable\n            obj = callee.name;\n        }\n\n        if (typeof obj === 'string' && callee.type === 'MemberExpression') {\n            if (this[obj]) {\n                return this[obj](component);\n            } else {\n                this.raiseError({\n                    message: Lang.TextCoding.message_conv_undefined_function,\n                    line: callee.loc,\n                });\n            }\n        }\n\n        if (callee.type === 'Identifier') {\n            // global function\n            if (this._funcMap[obj]) {\n                const funcType = this._funcMap[obj][args.length];\n                obj = { type: `func_${funcType}` };\n            } else if (this[obj]) {\n                // special block like len\n                return this[obj](component);\n            } else {\n                const blockInfo = this.blockSyntax[obj];\n                this.assert(blockInfo && blockInfo.key, '', callee, 'NO_FUNCTION', 'GENERAL');\n                obj = this.Block({}, blockInfo);\n            }\n        }\n\n        if (obj.preParams) {\n            component.arguments = obj.preParams.concat(component.arguments);\n            delete obj.preParams;\n        }\n\n        if (component.arguments) {\n            obj.params = this.Arguments(obj.type, component.arguments, obj.params);\n        }\n\n        if (obj.type === 'is_press_some_key') {\n            if (!component.arguments[0]) {\n                throw new Error(`keyboard input is empty`);\n            }\n            const value = component.arguments[0].value;\n            if (!Entry.KeyboardCode.map[typeof value === 'string' ? value.toLowerCase() : value]) {\n                throw new Error(`${value} is not supported key name`);\n            }\n            obj.params = [\n                `${\n                    Entry.KeyboardCode.map[typeof value === 'string' ? value.toLowerCase() : value]\n                }`,\n            ];\n        }\n\n        return obj;\n    }\n\n    Identifier(component) {\n        const name = component.name;\n\n        if (this._isInFuncDef && this._funcParamMap[name]) {\n            return {\n                type: `stringParam_${this._funcParamMap[name]}`,\n            };\n        }\n\n        const variable = Entry.variableContainer.getVariableByName(name);\n        if (variable) {\n            return {\n                type: 'get_variable',\n                params: [variable.id_],\n            };\n        }\n\n        const list = Entry.variableContainer.getListByName(name);\n        if (list) {\n            return {\n                type: 'get_list',\n                params: [list.id_],\n            };\n        }\n        return name;\n    }\n\n    VariableDeclaration(component) {\n        const results = component.declarations.map(this.Node, this);\n\n        return results;\n    }\n\n    VariableDeclarator(component) {\n        if (component.init && component.init.arguments) {\n            return component.init.arguments.map(this.Node, this);\n        } else {\n            return [];\n        }\n    }\n\n    AssignmentExpression(component) {\n        const lefts = Array.isArray(component.left) ? component.left : [component.left];\n        const results = [];\n\n        for (const i in lefts) {\n            const result = { params: [] };\n            const left = lefts[i];\n            let leftVar;\n            switch (left.type) {\n                case 'MemberExpression':\n                    result.type = 'change_value_list_index';\n                    const leftName = left.object.name;\n                    if (leftName === 'self') {\n                        result.type = 'set_variable';\n                        leftVar = Entry.variableContainer.getVariableByName(\n                            left.property.name,\n                            true,\n                            this.object.id\n                        );\n                        if (!leftVar) {\n                            Entry.variableContainer.addVariable({\n                                variableType: 'variable',\n                                name: left.property.name,\n                                visible: true,\n                                object: this.object.id,\n                                value: 0,\n                            });\n\n                            leftVar = Entry.variableContainer.getVariableByName(\n                                left.property.name,\n                                true,\n                                this.object.id\n                            );\n                        }\n\n                        result.params.push(leftVar.id_);\n                    } else {\n                        leftVar = Entry.variableContainer.getListByName(leftName);\n                        this.assert(leftVar, leftName, left.object, 'NO_LIST', 'LIST');\n                        result.params.push(leftVar.id_);\n                        result.params.push(this.ListIndex(this.Node(left.property.arguments[1])));\n                    }\n                    break;\n                case 'Identifier':\n                    result.type = 'set_variable';\n                    leftVar = Entry.variableContainer.getVariableByName(left.name, false);\n                    if (!leftVar) {\n                        Entry.variableContainer.addVariable({\n                            variableType: 'variable',\n                            name: left.name,\n                            visible: true,\n                            value: 0,\n                        });\n                        leftVar = Entry.variableContainer.getVariableByName(left.name, false);\n                    }\n                    result.params.push(leftVar.id_);\n                    break;\n                default:\n                    this.assert(false, 'error', left, 'NO_SUPPORT', 'GENERAL');\n            }\n\n            let rightHand = this.Node(component.right);\n\n            switch (component.operator) {\n                case '=':\n                    break;\n                case '+=':\n                    if (result.type === 'set_variable') {\n                        result.type = 'change_variable';\n                        break;\n                    }\n                case '-=':\n                case '/=':\n                case '*=':\n                default:\n                    const operator = this.arithmeticOperator[component.operator[0]];\n                    if (operator) {\n                        let getBlock;\n                        if (result.type === 'set_variable') {\n                            getBlock = {\n                                type: 'get_variable',\n                                params: [leftVar.id_],\n                            };\n                        } else {\n                            getBlock = {\n                                type: 'value_of_index_from_list',\n                                params: [\n                                    undefined,\n                                    leftVar.id_,\n                                    undefined,\n                                    this.ListIndex(this.Node(component.left.property.arguments[1])), // do not change this\n                                ],\n                            };\n                        }\n                        rightHand = {\n                            type: 'calc_basic',\n                            params: [getBlock, operator, rightHand],\n                        };\n                    }\n            }\n            result.params.push(rightHand);\n            results.push(result);\n        }\n\n        return results;\n    }\n\n    Literal(component, paramSchema, paramDef) {\n        const value = component.value;\n        switch (typeof value) {\n            case 'boolean':\n                return { type: value ? 'True' : 'False' };\n            default:\n        }\n        const paramType = paramSchema ? paramSchema.type : 'Block';\n        switch (paramType) {\n            case 'DropdownDynamic':\n                return this.DropdownDynamic(value, paramSchema);\n            case 'Block':\n                if (paramDef && paramDef.type) {\n                    // process primitive block\n                    return {\n                        type: paramDef.type,\n                        params: this.Arguments(paramDef.type, [component]),\n                    };\n                }\n                return {\n                    type: 'number',\n                    params: [this.getValue(component)],\n                };\n            default:\n                return this.getValue(component);\n        }\n    }\n\n    MemberExpression(component) {\n        let obj;\n        const result = {};\n        if (component.object.name === 'self') {\n            // local variable\n            let localVar = Entry.variableContainer.getVariableByName(\n                component.property.name,\n                true,\n                this.object.id\n            );\n            if (localVar) {\n                return {\n                    type: 'get_variable',\n                    params: [localVar.id_],\n                };\n            }\n            localVar = Entry.variableContainer.getListByName(\n                component.property.name,\n                true,\n                this.object.id\n            );\n            if (localVar) {\n                return {\n                    type: 'get_list',\n                    params: [localVar.id_],\n                };\n            }\n            this.assert(localVar, 'variable not exist', component);\n        } else if (component.object.type === 'Literal') {\n            // string member\n            obj = '%2';\n            result.preParams = [component.object];\n        } else {\n            obj = this.Node(component.object);\n        }\n\n        if (typeof obj === 'object') {\n            // list member\n            if (obj.type === 'get_list') {\n                result.preParams = [obj.params[0]];\n            } else {\n                result.preParams = [component.object];\n            }\n            obj = '%2';\n        }\n        const property = component.property;\n        let blockInfo;\n\n        if (property.type === 'CallExpression') {\n            return this.SubscriptIndex(component);\n        } else if (property.name === '_pySlice') {\n            blockInfo = this.blockSyntax['%2[%4:%6]'];\n        } else {\n            const rawSyntax = `${obj}.${property.name}`;\n            if (this.blockSyntax[obj] && this.blockSyntax[obj][property.name]) {\n                if (this[rawSyntax]) {\n                    return rawSyntax;\n                }\n                blockInfo = this.blockSyntax[obj][property.name];\n            } else {\n                return rawSyntax;\n            } // block syntax not exist. pass to special\n        }\n\n        this.Block(result, blockInfo);\n\n        return result;\n    }\n\n    WhileStatement(component) {\n        const comment = component.body.comment;\n        const blocks = component.body.body;\n        const obj = {\n            statements: [this.setParams(blocks)],\n        };\n        const test = component.test;\n        if (test.raw === 'True') {\n            obj.type = 'repeat_inf';\n        } else {\n            obj.type = 'repeat_while_true';\n            if (test.type === 'UnaryExpression' && test.operator === '!') {\n                obj.params = [this.Node(component.test.argument), 'until'];\n            } else {\n                obj.params = [this.Node(component.test), 'while'];\n            }\n        }\n        if (comment) {\n            obj.comment = comment;\n        }\n\n        return obj;\n    }\n\n    BlockStatement(component) {\n        let db = component.body.map(this.Node, this);\n\n        if (db.constructor == Array && db[0].length) {\n            if (db.length > 0) {\n                db[db.length - 1][0].params.push(db[0][0][0]);\n            }\n\n            db = db[db.length - 1][0];\n        }\n\n        return db;\n    }\n\n    IfStatement(component) {\n        let alternate;\n        let blocks;\n\n        const tempAlt = component.alternate;\n        const isForState =\n            tempAlt &&\n            tempAlt.body &&\n            tempAlt.body[0] &&\n            'type' in tempAlt.body[0] &&\n            tempAlt.body[0].type === 'ForInStatement';\n\n        if (isForState) {\n            alternate = component.alternate.body.map(this.Node, this);\n            component.consequent.body[0].body.body.shift();\n\n            blocks = component.consequent.body[0].body.body;\n            alternate[0].statements.push(this.setParams(blocks));\n        } else if (!('alternate' in component) || !component.alternate) {\n            alternate = {\n                type: '_if',\n                statements: [this.setParams(component.consequent.body)],\n                params: [this.Node(component.test)],\n            };\n        } else {\n            const consequent = component.consequent\n                ? component.consequent.body\n                      .map(this.Node, this)\n                      .map((b) => (Array.isArray(b) ? b[0] : b))\n                : [];\n            const alternates = component.alternate\n                ? component.alternate.body\n                      .map(this.Node, this)\n                      .map((b) => (Array.isArray(b) ? b[0] : b))\n                : [];\n            alternate = {\n                type: 'if_else',\n                statements: [consequent, alternates],\n                params: [this.Node(component.test)],\n            };\n        }\n\n        if (component.consequent.comment) {\n            alternate.comment = component.consequent.comment;\n        }\n\n        return alternate;\n    }\n\n    ForStatement(component) {\n        const body = component.body.body;\n        return this.Node(body[body.length - 1]);\n    }\n\n    ForInStatement(component) {\n        // let  expression = component.body.body[0] && 'expression' in component.body.body[0] ?\n        //                     this.Node(component.body.body[0].expression) : null;\n        const result = {\n            type: 'repeat_basic',\n            params: [],\n            statements: [],\n        };\n\n        if (component.body.comment) {\n            result.comment = component.body.comment;\n        }\n\n        return result;\n    }\n\n    BreakStatement(component) {\n        return {\n            type: this.blockSyntax.break.key,\n        };\n    }\n\n    UnaryExpression(component) {\n        switch (component.operator) {\n            case '!':\n                return {\n                    type: 'boolean_not',\n                    params: [undefined, this.Node(component.argument)],\n                };\n            case '-':\n            case '+':\n                const result = this.Node(component.argument);\n                if (result.type === 'number') {\n                    result.params = [component.operator + result.params[0]];\n                    return result;\n                } else {\n                    return {\n                        type: 'calc_basic',\n                        params: [\n                            {\n                                type: 'number',\n                                params: [`${component.operator}1`],\n                            },\n                            'MULTI',\n                            result,\n                        ],\n                    };\n                }\n            default:\n                throw new Error(`Unary operator ${component.operator} is not supported`);\n        }\n    }\n\n    LogicalExpression(component) {\n        return {\n            type: 'boolean_and_or',\n            params: [\n                this.Node(component.left),\n                this.logicalOperator[component.operator],\n                this.Node(component.right),\n            ],\n        };\n    }\n\n    BinaryExpression(component) {\n        let operator = component.operator;\n        let blockType;\n        if (this.binaryOperator[operator]) {\n            blockType = 'boolean_basic_operator';\n            operator = this.binaryOperator[operator];\n        } else if (this.arithmeticOperator[operator]) {\n            // nt11576 이슈 9429, 파이썬 변환시 Number add 와 String concat parsing 버그 수정\n            if (\n                typeof component.left.value === 'string' ||\n                typeof component.right.value === 'string'\n            ) {\n                return {\n                    type: 'combine_something',\n                    params: [\n                        undefined,\n                        this.Node(component.left),\n                        undefined,\n                        this.Node(component.right),\n                        undefined,\n                    ],\n                };\n            } else {\n                blockType = 'calc_basic';\n                operator = this.arithmeticOperator[operator];\n            }\n        } else if (this.divideOperator[operator]) {\n            return {\n                type: 'quotient_and_mod',\n                params: [\n                    undefined,\n                    this.Node(component.left),\n                    undefined,\n                    this.Node(component.right),\n                    undefined,\n                    this.divideOperator[operator],\n                ],\n            };\n        } else if (operator === '**') {\n            this.assert(\n                component.right.value === 2,\n                component.right.value,\n                component,\n                'DEFAULT',\n                'DEFAULT'\n            );\n            return {\n                type: 'calc_operation',\n                params: [undefined, this.Node(component.left), undefined, 'square'],\n            };\n        } else {\n            throw new Error(`Not supported operator ${component.operator}`);\n        }\n        return {\n            type: blockType,\n            params: [this.Node(component.left), operator, this.Node(component.right)],\n        };\n    }\n\n    // UpdateExpression(component) {};\n\n    FunctionDeclaration(component) {\n        const startBlock = {};\n\n        const funcName = component.id.name;\n        this.assert(!this._isInFuncDef, funcName, component, 'NO_ENTRY_EVENT_FUNCTION', 'FUNCTION');\n\n        this._isInFuncDef = true;\n        this.assert(component.body.body[0], funcName, component, 'NO_OBJECT', 'OBJECT');\n\n        if (funcName === 'when_press_key') {\n            if (!component.arguments || !component.arguments[0]) {\n                throw new Error(`keyboard input is empty`);\n                // startBlock.params = [null, null];\n            } else {\n                const value = component.arguments[0].name;\n                if (\n                    !Entry.KeyboardCode.map[typeof value === 'string' ? value.toLowerCase() : value]\n                ) {\n                    throw new Error(`${value} is not supported key name`);\n                }\n                startBlock.params = [\n                    null,\n                    `${\n                        Entry.KeyboardCode.map[\n                            typeof value === 'string' ? value.toLowerCase() : value\n                        ]\n                    }`,\n                ];\n            }\n        }\n\n        if (funcName === 'when_get_signal') {\n            if (!component.arguments || !component.arguments[0]) {\n                startBlock.params = [null, null];\n            } else {\n                startBlock.params = [null, this.getMessage(component.arguments[0].name)];\n            }\n        }\n\n        const blockStatement = component.body.body[0].argument.callee.object.body;\n        const comment = blockStatement.comment;\n        const blocks = blockStatement.body;\n        const blockInfo = this.blockSyntax[`def ${funcName}`];\n\n        if (blockInfo) {\n            // event block\n            startBlock.type = blockInfo.key;\n            if (comment) {\n                startBlock.comment = comment;\n            }\n\n            const definedBlocks = this.setParams(blocks);\n            definedBlocks.unshift(startBlock);\n\n            this._isInFuncDef = false;\n            return definedBlocks;\n        } else {\n            this.createFunction(component, funcName, blocks);\n            this._isInFuncDef = false;\n            return [];\n        }\n    }\n\n    FunctionExpression(component) {\n        return this.Node(component.body);\n    }\n\n    ReturnStatement(component) {\n        return component.argument.arguments.map(this.Node, this);\n    }\n\n    // ThisExpression(component) {};\n\n    NewExpression(component) {\n        return this.Node(component.callee);\n    }\n\n    SubscriptIndex(component) {\n        const obj = this.Node(component.object);\n        let blockInfo;\n\n        if (obj.type === 'get_list') {\n            // string\n            blockInfo = this.blockSyntax['%2[%4]'];\n        } else {\n            // var, list\n            blockInfo = this.blockSyntax['%2[%4]#char_at'];\n        }\n        const result = this.Block({}, blockInfo);\n        result.params = this.Arguments(result.type, component.property.arguments);\n        return result;\n    }\n\n    Comment(component) {\n        return {\n            type: 'comment',\n            value: component.value,\n        };\n    }\n\n    /**\n     * util Function\n     */\n\n    Arguments(blockType, args, defaultParams) {\n        let defParams;\n        let sortedArgs;\n        let blockSchema;\n        blockSchema = Entry.block[blockType];\n        if ((blockType && blockType.substr(0, 5) === 'func_') || !blockSchema) {\n            // function block, etc\n            sortedArgs = args;\n        } else {\n            const syntax = this.PySyntax(blockSchema, defaultParams);\n            const indexes = syntax.match(/%\\d+/g, '');\n            if (!indexes) {\n                return defaultParams || [];\n            }\n            sortedArgs = defaultParams || [];\n\n            for (let i = 0; i < indexes.length; i++) {\n                const idx = parseInt(indexes[i].substring(1)) - 1;\n                sortedArgs[idx] = args[i];\n            }\n            defParams =\n                blockSchema.def && blockSchema.def.params ? blockSchema.def.params : undefined;\n        }\n        let results = sortedArgs.map((arg, index) => {\n            if (arg && arg.type) {\n                const paramSchema = blockSchema ? blockSchema.params[index] : null;\n                let param = this.Node(\n                    arg,\n                    arg.type === 'Literal' ? paramSchema : undefined,\n                    arg.type === 'Literal' && defParams ? defParams[index] : undefined\n                );\n                this.assert(\n                    !(typeof param === 'string' && arg.type === 'Identifier'),\n                    param,\n                    arg,\n                    'NO_VARIABLE',\n                    'VARIABLE'\n                );\n\n                if (paramSchema.type !== 'Block' && param && param.params) {\n                    // for list and variable dropdown\n                    param = param.params[0];\n                } else if (paramSchema.type === 'Block' && paramSchema.isListIndex) {\n                    param = this.ListIndex(param);\n                }\n\n                return param;\n            } else {\n                return arg;\n            } // default params\n        }, this);\n\n        const codeMap = this.CodeMap(blockType);\n        if (codeMap) {\n            results = results.map((arg, index) => {\n                if (codeMap[index] && arg) {\n                    return codeMap[index][this.toLowerCase(arg)] || arg;\n                } else {\n                    return arg;\n                }\n            }, this);\n        }\n\n        return results;\n    }\n\n    getValue(component) {\n        let value;\n        if (component.type === 'Literal') {\n            value = component.raw;\n            if (value === 'None') {\n                return;\n            } else if (component.value === undefined) {\n                value = 0;\n            } else if (!component.value) {\n                value = component.value;\n            } else if (component.value.constructor === String) {\n                if (component.raw.includes('\"') || component.raw.includes(\"'\")) {\n                    value = component.raw.substr(1, component.raw.length - 2);\n                } else {\n                    value = component.raw;\n                }\n            } else if (component.value.constructor === Number) {\n                value = component.value;\n            }\n\n            return value;\n        } else {\n            value = this.Node(component);\n            return value.params && value.params[0] ? value.params[0] : null;\n        }\n    }\n\n    getMessage(name) {\n        if (!name) {\n            return;\n        }\n        name = name.replace(/_space_/gi, ' ');\n\n        let objects = Entry.variableContainer.messages_.filter((obj) => obj.name === name);\n\n        if (objects.length <= 0) {\n            Entry.variableContainer.addMessage({\n                name,\n            });\n            objects = Entry.variableContainer.messages_.filter((obj) => obj.name === name);\n        }\n\n        let object;\n        if (objects && objects.length > 0) {\n            object = objects[0].id;\n        } else {\n            object = name;\n        }\n\n        return object;\n    }\n\n    DropdownDynamic(value, paramSchema) {\n        if (_.isFunction(paramSchema.menuName)) {\n            return value;\n        }\n        let object;\n        let objects;\n        switch (paramSchema.menuName) {\n            case 'sprites':\n\n            case 'spritesWithMouse':\n                objects = Entry.container.objects_.filter((obj) => obj.name === value);\n\n                if (objects && objects.length > 0) {\n                    object = objects[0].id;\n                } else {\n                    object = value;\n                }\n\n                return object;\n\n            case 'spritesWithSelf':\n                if (!value) {\n                    object = 'None';\n                } else if (value == 'self') {\n                    object = value;\n                } else {\n                    objects = Entry.container.objects_.filter((obj) => obj.name === value);\n\n                    object = objects[0].id;\n                }\n\n                return object;\n            case 'collision':\n                objects = Entry.container.objects_.filter((obj) => obj.name === value);\n\n                if (objects && objects.length > 0) {\n                    object = objects[0].id;\n                } else {\n                    object = value;\n                }\n\n                return object;\n\n            case 'pictures':\n                const picture = this.object.getPicture(value);\n                return picture ? picture.id : undefined;\n            case 'messages':\n                return this.getMessage(value);\n            case 'variables':\n                if (!value) {\n                    return;\n                }\n                value = value.split('.');\n                let variable;\n                if (value.length > 1) {\n                    // self variable\n                    variable = Entry.variableContainer.getVariableByName(\n                        value[1],\n                        true,\n                        this.object.id\n                    );\n                } else {\n                    variable = Entry.variableContainer.getVariableByName(\n                        value[0],\n                        false,\n                        this.object.id\n                    );\n                }\n                return variable ? variable.id_ : undefined;\n            case 'lists':\n                if (!value) {\n                    return;\n                }\n                value = value.split('.');\n                let list;\n                if (value.length > 1) {\n                    // self variable\n                    list = Entry.variableContainer.getListByName(value[1], true, this.object.id);\n                } else {\n                    list = Entry.variableContainer.getListByName(value[0], false, this.object.id);\n                }\n                return list ? list.id_ : undefined;\n            case 'scenes':\n                const scenes = Entry.scene.scenes_.filter((s) => s.name === value);\n                return scenes[0] ? scenes[0].id : undefined;\n            case 'sounds':\n                if (!value) {\n                    return undefined;\n                }\n                const sound = this.object.getSound(value);\n                return sound ? sound.id : undefined;\n            case 'clone':\n            case 'textBoxWithSelf':\n                let object;\n\n                if (!value) {\n                    object = null;\n                } else if (value == 'self') {\n                    object = value;\n                } else {\n                    const objects = Entry.container.objects_.filter((obj) => obj.name === value);\n\n                    object = objects[0] ? objects[0].id : null;\n                }\n\n                return object;\n            case 'fonts':\n                return EntryStatic.fonts.find(({ family }) => family === value).family;\n            case 'objectSequence':\n            case 'blockCount':\n                return value;\n        }\n    }\n\n    Node(nodeType, node) {\n        let hasType = false;\n        if (typeof nodeType === 'string' && nodeType !== node.type) {\n            this.assert(\n                false,\n                node.name || node.value || node.operator,\n                node,\n                'NO_SUPPORT',\n                'GENERAL'\n            );\n        } else if (typeof nodeType === 'string') {\n            hasType = true;\n        }\n\n        const args = Array.prototype.slice.call(arguments);\n        if (hasType) {\n            args.shift();\n        }\n\n        node = args[0];\n\n        if (!this[node.type]) {\n            throw new Error(`${node.type} is not supported`);\n        }\n        return this[node.type].apply(this, args);\n    }\n\n    PySyntax(blockSchema, defaultParams) {\n        if (defaultParams) {\n            const syntaxes = blockSchema.syntax.py.filter((s) => {\n                if (!s.params) {\n                    return false;\n                }\n                let isSame = true;\n                s.params.map((p, index) => {\n                    if (p != defaultParams[index]) {\n                        isSame = false;\n                    }\n                });\n                return isSame;\n            });\n            if (syntaxes.length) {\n                return syntaxes[0].syntax;\n            }\n        }\n        const syntaxObj = blockSchema.syntax.py[0];\n        return syntaxObj.syntax || syntaxObj;\n    }\n\n    CodeMap(blockType) {\n        for (const objName in Entry.CodeMap) {\n            if (Entry.CodeMap[objName] && Entry.CodeMap[objName][blockType]) {\n                return Entry.CodeMap[objName][blockType];\n            }\n        }\n    }\n\n    Block(result, blockInfo) {\n        result.type = blockInfo.key;\n\n        if (blockInfo.params) {\n            result.params = blockInfo.params.concat();\n        }\n        return result;\n    }\n\n    ListIndex(param) {\n        if (this.isParamPrimitive(param)) {\n            // literal\n            param.params = [Number(param.params[0]) + 1];\n        } else if (\n            param.type === 'calc_basic' && // x - 1\n            param.params[1] === 'MINUS' &&\n            this.isParamPrimitive(param.params[2]) &&\n            `${param.params[2].params[0]}` === '1'\n        ) {\n            param = param.params[0];\n        } else {\n            param = {\n                type: 'calc_basic',\n                params: [\n                    param,\n                    'PLUS',\n                    {\n                        type: 'text',\n                        params: ['1'],\n                    },\n                ],\n            };\n        }\n        return param;\n    }\n\n    isParamPrimitive(param) {\n        return param && (param.type === 'number' || param.type === 'text');\n    }\n\n    assert(data, keyword, errorNode, message, subject) {\n        if (data) {\n            return;\n        }\n        Entry.TextCodingError.error(\n            Entry.TextCodingError.TITLE_CONVERTING,\n            Entry.TextCodingError[`MESSAGE_CONV_${message || 'NO_SUPPORT'}`],\n            keyword,\n            errorNode.loc,\n            Entry.TextCodingError[`SUBJECT_CONV_${subject || 'GENERAL'}`]\n        );\n    }\n\n    setParams(params) {\n        const definedBlocks = params.length\n            ? params.map(function(n) {\n                  const result = this.Node(n);\n                  this.assert(typeof result === 'object', '', n, 'NO_SUPPORT', 'GENERAL');\n                  return result;\n              }, this)\n            : [];\n\n        let results = [];\n        for (let i = 0; i < definedBlocks.length; i++) {\n            const db = definedBlocks[i];\n\n            if (Array.isArray(db)) {\n                results = results.concat(db);\n            } else {\n                results.push(db);\n            }\n        }\n\n        return results.filter((b) => b.constructor === Object);\n    }\n\n    getVariables(program) {\n        const nodes = program.body;\n\n        nodes.map(function(n) {\n            n = n.expression;\n            let left = n.left;\n            const right = n.right;\n            let name;\n            let type = 'variables_';\n            const id = Entry.generateHash();\n            let value;\n            let array;\n\n            if (n.operator != '=') {\n                return;\n            }\n\n            if (right.type === 'NewExpression' && right.callee.property.name == 'list') {\n                type = 'lists_';\n                let temp = right.arguments.map(this.Node, this);\n\n                temp = temp.map((m) => {\n                    if (m.constructor === Object && 'params' in m) {\n                        return {\n                            data:\n                                typeof m.params[0] === 'string'\n                                    ? m.params[0].replace(/\\\\\\\"/gi, '\"')\n                                    : m.params[0],\n                        };\n                    } else {\n                        return { data: m };\n                    }\n                });\n\n                array = temp;\n            } else {\n                value = this.getValue(right);\n            }\n\n            const functionType = `add${type[0].toUpperCase()}${type.slice(1, type.length - 2)}`;\n\n            if (!Array.isArray(left)) {\n                left = [left];\n            }\n\n            for (const key in left) {\n                let object = false;\n                const l = left[key];\n\n                const obj = {\n                    variableType: 'variable',\n                    name: '',\n                    visible: true,\n                    object: {},\n                    value: '',\n                };\n                if (array) {\n                    obj.array = array;\n                }\n                if (value) {\n                    obj.value = value;\n                }\n\n                if ('name' in l) {\n                    name = l.name;\n                } else {\n                    object = this.object;\n                    name = l.property.name;\n                    object = object.id;\n                }\n\n                const existVar = this.variableExist(name, type);\n\n                if (existVar) {\n                    if (type == 'lists_') {\n                        existVar.array_ = obj.array;\n                        return;\n                    }\n                    existVar.value_ = this.getValue(right);\n                    return;\n                } else {\n                    obj.variableType = type.slice(0, length - 2);\n                    obj.name = name;\n                    obj.object = object;\n                    Entry.variableContainer[functionType](obj);\n                }\n            }\n        }, this);\n\n        return [];\n    }\n\n    variableExist(name, type) {\n        let variables_ = Entry.variableContainer[type];\n        variables_ = variables_.map((v) => v.name_);\n\n        if (variables_.indexOf(name) > -1) {\n            return Entry.variableContainer[type][variables_.indexOf(name)];\n        }\n        return false;\n    }\n\n    /**\n     * Special Blocks\n     */\n\n    len(component) {\n        const param = this.Node(component.arguments[0]);\n        this.assert(\n            !(typeof param === 'string' && component.arguments[0].type === 'Identifier'),\n            param,\n            component.arguments[0],\n            'NO_VARIABLE',\n            'VARIABLE'\n        );\n\n        if (param.type === 'get_list') {\n            // string len\n            return {\n                type: 'length_of_list',\n                params: [undefined, param.params[0]],\n            };\n        } else {\n            // array len\n            return {\n                type: 'length_of_string',\n                params: [undefined, param],\n            };\n        }\n    }\n\n    ['Hamster.note'](component) {\n        let blockInfo;\n        if (component.arguments.length > 2) {\n            blockInfo = this.blockSyntax.Hamster.note;\n        } else {\n            blockInfo = this.blockSyntax.Hamster['note#0'];\n            component.arguments.shift();\n        }\n        const obj = this.Block({}, blockInfo);\n        obj.params = this.Arguments(blockInfo.key, component.arguments);\n        if (component.arguments.length > 2) {\n            obj.params[0] =\n                Entry.CodeMap.Hamster.hamster_play_note_for[0][this.toLowerCase(obj.params[0])];\n        }\n        return obj;\n    }\n\n    ['Hamster.line_tracer_mode'](component) {\n        return this.Special(component, 'Hamster', 'line_tracer_mode');\n    }\n\n    ['Hamster.io_mode_a'](component) {\n        return this.Special(component, 'Hamster', 'io_mode_a');\n    }\n\n    ['Hamster.io_mode_b'](component) {\n        return this.Special(component, 'Hamster', 'io_mode_b');\n    }\n\n    ['Hamster.io_modes'](component) {\n        return this.Special(component, 'Hamster', 'io_modes');\n    }\n\n    ['Hamster.leds'](component) {\n        return this.Special(component, 'Hamster', 'leds');\n    }\n\n    ['Hamster.left_led'](component) {\n        return this.Special(component, 'Hamster', 'left_led');\n    }\n\n    ['Hamster.right_led'](component) {\n        return this.Special(component, 'Hamster', 'right_led');\n    }\n\n    ['__pythonRuntime.ops.in'](component) {\n        // \"10 in list\"\n        return {\n            type: 'is_included_in_list',\n            params: this.Arguments('is_included_in_list', component.arguments),\n        };\n    }\n\n    Special(component, name, key) {\n        const result = {};\n        let param = this.Node(component.arguments[0]);\n        if (this.isParamPrimitive(param)) {\n            param = param.params[0];\n        }\n        const blockInfo = this.blockSyntax[name][`${key}(${param})`];\n\n        this.Block(result, blockInfo);\n        return result;\n    }\n\n    createFunctionMap() {\n        this._funcMap = {};\n        const functions = Entry.variableContainer.functions_;\n        for (const key in functions) {\n            const funcSchema = Entry.block[`func_${key}`];\n            const funcName = funcSchema.template\n                .trim()\n                .split(' ')[0]\n                .trim();\n            if (!this._funcMap[funcName]) {\n                this._funcMap[funcName] = {};\n            }\n            this._funcMap[funcName][funcSchema.params.length - 1] = key;\n        }\n    }\n\n    createFunction(component, funcName, blocks) {\n        const params = component.arguments ? component.arguments.map(this.Node, this) : [];\n        const functions = Entry.variableContainer.functions_;\n\n        let funcId = Entry.generateHash();\n        for (const key in functions) {\n            const funcSchema = Entry.block[`func_${key}`];\n            if (\n                funcSchema.params.length === params.length + 1 &&\n                funcSchema.template\n                    .trim()\n                    .split(' ')[0]\n                    .trim() === funcName\n            ) {\n                funcId = key;\n                break;\n            }\n        }\n\n        //함수 선언 블록 내 값블록\n        let funcParamPointer = {\n            type: 'function_field_label',\n            params: [funcName],\n        };\n        //함수 선언 블록\n        const funcDeclarationContent = {\n            type: 'function_create',\n            params: [funcParamPointer],\n        };\n        const func = {\n            id: funcId,\n            content: [[funcDeclarationContent]],\n        };\n\n        // 함수 선언 블록에 달린 코멘트 처리\n        const comment = component.body.body[0].argument.callee.object.body.comment;\n        if (comment) {\n            funcDeclarationContent.comment = comment;\n        }\n\n        if (!this._funcMap[funcName]) {\n            this._funcMap[funcName] = {};\n        }\n        this._funcMap[funcName][params.length] = func.id;\n\n        while (params.length) {\n            // generate param\n            const param = params.shift();\n            let paramId = Entry.Func.requestParamBlock('string');\n            const newFuncParam = {\n                type: 'function_field_string',\n                params: [\n                    {\n                        type: paramId,\n                    },\n                ],\n            };\n            paramId = paramId.split('_')[1];\n            this._funcParamMap[param] = paramId;\n            funcParamPointer.params.push(newFuncParam);\n            funcParamPointer = newFuncParam;\n        }\n\n        const definedBlocks = this.setParams(blocks); // function content\n        this._funcParamMap = {};\n\n        func.content[0] = func.content[0].concat(definedBlocks);\n\n        func.content = JSON.stringify(func.content);\n        if (functions[funcId]) {\n            const targetFunc = functions[funcId];\n            targetFunc.content = new Entry.Code(func.content);\n            targetFunc.generateBlock(true);\n            Entry.Func.generateWsBlock(targetFunc);\n        } else {\n            Entry.variableContainer.setFunctions([func]);\n        }\n    }\n\n    /**\n     * Not Supported\n     */\n\n    ClassDeclaration(component) {\n        const funcName = this.Node(component.id);\n        this.assert(false, funcName, component, 'NO_OBJECT', 'OBJECT');\n    }\n\n    // RegExp(component) {};\n\n    // Function(component) {};\n\n    // EmptyStatement(component) {};\n\n    // DebuggerStatement(component) {};\n\n    // WithStatement(component) {};\n\n    // LabeledStatement(component) {};\n\n    // ContinueStatement(component) {};\n\n    // SwitchStatement(component) {};\n\n    // SwitchCase(component) {};\n\n    // ThrowStatement(component) {};\n\n    // TryStatement(component) {};\n\n    // CatchClause(component) {};\n\n    // DoWhileStatement(component) {\n    //     return component.body.map(this.Node,  this);\n    // };\n\n    // ArrayExpression(component) {};\n\n    // ObjectExpression(component) {};\n\n    // Property(component) {};\n\n    // ConditionalExpression(component) {};\n\n    // SequenceExpression(component) {};\n\n    searchSyntax(datum) {\n        //legacy\n        let schema;\n        let appliedParams;\n        let doNotCheckParams = false;\n\n        if (datum instanceof Entry.BlockView) {\n            schema = datum.block._schema;\n            appliedParams = datum.block.data.params;\n        } else if (datum instanceof Entry.Block) {\n            schema = datum._schema;\n            appliedParams = datum.params;\n        } else {\n            schema = datum;\n            doNotCheckParams = true;\n        }\n\n        if (schema && schema.syntax) {\n            const syntaxes = schema.syntax.py.concat();\n            while (syntaxes.length) {\n                let isFail = false;\n                const syntax = syntaxes.shift();\n                if (typeof syntax === 'string') {\n                    return { syntax, template: syntax };\n                }\n                if (syntax.params) {\n                    for (let i = 0; i < syntax.params.length; i++) {\n                        if (\n                            doNotCheckParams !== true &&\n                            syntax.params[i] &&\n                            syntax.params[i] !== appliedParams[i]\n                        ) {\n                            isFail = true;\n                            break;\n                        }\n                    }\n                }\n                if (!syntax.template) {\n                    syntax.template = syntax.syntax;\n                }\n                if (isFail) {\n                    continue;\n                }\n                return syntax;\n            }\n        }\n        return null;\n    }\n\n    toLowerCase(data) {\n        if (data && data.toLowerCase) {\n            return data.toLowerCase();\n        } else {\n            return data;\n        }\n    }\n};\n"
  },
  {
    "path": "src/textcoding/parser.js",
    "content": "/*\n *\n */\n'use strict';\n\nrequire('./util/console');\nrequire('./parser/core/text/pyToBlock');\nrequire('./parser/core/text/jsToBlock');\nrequire('./parser/core/block/blockToPy');\nrequire('./parser/core/block/blockToJs');\n\nEntry.Parser = function(mode, type, cm, syntax) {\n    this._mode = mode; // maze ai workspace\n    this.syntax = {}; //for maze\n    this.codeMirror = cm;\n\n    this._lang = syntax;\n    this._type = type;\n    this.availableCode = [];\n    this._syntax_cache = {};\n    this._pyThreadCount = 1;\n    this._pyBlockCount = {};\n\n    Entry.Parser.PARSE_GENERAL = 1;\n    Entry.Parser.PARSE_SYNTAX = 2;\n    Entry.Parser.PARSE_VARIABLE = 3;\n    Entry.Parser.PARSE_BLOCK = 4;\n\n    this._onError = false;\n    this._onRunError = false;\n\n    if (Entry.type === 'workspace') {\n        this._console = new Entry.Console();\n\n        const hwFunc = function() {\n            const _mode = this._mode;\n            if (_mode === null) {\n                return;\n            }\n            this.setAvailableCode();\n\n            delete this._syntax_cache[_mode];\n            this.syntax = this.mappingSyntax(_mode);\n            this._pyHinter && this._pyHinter.setSyntax(this.syntax);\n        }.bind(this);\n\n        //after hw code generated update syntax for this\n        //and update python hinter syntax\n        Entry.addEventListener('hwCodeGenerated', hwFunc);\n    }\n};\n\n(function(p) {\n    const SYNTAX_MAP = {\n        'Hamster.LINE_TRACER_MODE_OFF': '0',\n        'Hamster.LINE_TRACER_MODE_BLACK_LEFT_SENSOR': '1',\n        'Hamster.LINE_TRACER_MODE_BLACK_RIGHT_SENSOR': '2',\n        'Hamster.LINE_TRACER_MODE_BLACK_BOTH_SENSORS': '3',\n        'Hamster.LINE_TRACER_MODE_BLACK_TURN_LEFT': '4',\n        'Hamster.LINE_TRACER_MODE_BLACK_TURN_RIGHT': '5',\n        'Hamster.LINE_TRACER_MODE_BLACK_MOVE_FORWARD': '6',\n        'Hamster.LINE_TRACER_MODE_BLACK_UTURN': '7',\n        'Hamster.LINE_TRACER_MODE_WHITE_LEFT_SENSOR': '8',\n        'Hamster.LINE_TRACER_MODE_WHITE_RIGHT_SENSOR': '9',\n        'Hamster.LINE_TRACER_MODE_WHITE_BOTH_SENSORS': '10',\n        'Hamster.LINE_TRACER_MODE_WHITE_TURN_LEFT': '11',\n        'Hamster.LINE_TRACER_MODE_WHITE_TURN_RIGHT': '12',\n        'Hamster.LINE_TRACER_MODE_WHITE_MOVE_FORWARD': '13',\n        'Hamster.LINE_TRACER_MODE_WHITE_UTURN': '14',\n\n        'Hamster.LED_OFF': '0',\n        'Hamster.LED_BLUE': '1',\n        'Hamster.LED_GREEN': '2',\n        'Hamster.LED_CYAN': '3',\n        'Hamster.LED_RED': '4',\n        'Hamster.LED_MAGENTA': '5',\n        'Hamster.LED_YELLOW': '6',\n        'Hamster.LED_WHITE': '7',\n\n        'Hamster.IO_MODE_ANALOG_INPUT': '0',\n        'Hamster.IO_MODE_DIGITAL_INPUT': '1',\n        'Hamster.IO_MODE_SERVO_OUTPUT': '8',\n        'Hamster.IO_MODE_PWM_OUTPUT': '9',\n        'Hamster.IO_MODE_DIGITAL_OUTPUT': '10',\n    };\n\n    p.setParser = function(mode, type, cm) {\n        if (this._mode === mode && this._type === type) {\n            return;\n        }\n\n        this._mode = mode;\n        this._type = type;\n        this._cm = cm;\n\n        this.syntax = this.mappingSyntax(mode);\n\n        switch (type) {\n            case Entry.Vim.PARSER_TYPE_JS_TO_BLOCK:\n                this._execParser = new Entry.JsToBlockParser(this.syntax, this);\n                this._execParserType = Entry.Vim.PARSER_TYPE_JS_TO_BLOCK;\n                break;\n            case Entry.Vim.PARSER_TYPE_PY_TO_BLOCK:\n                this._execParser = new Entry.PyToBlockParser(this.syntax);\n                this._execParserType = Entry.Vim.PARSER_TYPE_PY_TO_BLOCK;\n                break;\n            case Entry.Vim.PARSER_TYPE_BLOCK_TO_JS:\n                this._execParser = new Entry.BlockToJsParser(this.syntax, this);\n                this._execParserType = Entry.Vim.PARSER_TYPE_BLOCK_TO_JS;\n                break;\n            case Entry.Vim.PARSER_TYPE_BLOCK_TO_PY:\n                this._execParser = new Entry.BlockToPyParser(this.syntax);\n                cm && cm.setOption('mode', { name: 'python', globalVars: true });\n                this._execParserType = Entry.Vim.PARSER_TYPE_BLOCK_TO_PY;\n                break;\n        }\n    };\n\n    p.parse = function(code, parseMode) {\n        const type = this._type;\n        let result = '';\n\n        switch (type) {\n            case Entry.Vim.PARSER_TYPE_JS_TO_BLOCK:\n                try {\n                    const threads = [];\n                    threads.push(code);\n                    const astArray = [];\n\n                    for (const index in threads) {\n                        let thread = threads[index];\n                        thread = thread.trim();\n                        const ast = acorn.parse(thread);\n                        astArray.push(ast);\n                    }\n\n                    result = this._execParser.Program(astArray);\n                } catch (error) {\n                    if (this.codeMirror) {\n                        let annotation;\n                        if (error instanceof SyntaxError) {\n                            annotation = {\n                                from: { line: error.loc.line - 1, ch: 0 },\n                                to: { line: error.loc.line - 1, ch: error.loc.column },\n                            };\n                            error.message = '문법(Syntax) 오류입니다.';\n                            error.type = 1;\n                        } else {\n                            const { node = {} } = error || {};\n                            const { start = 0, end = 0 } = node;\n                            annotation = this.getLineNumber(start, end);\n                            annotation.message = error.message;\n                            annotation.severity = 'converting error';\n                            error.type = 2;\n                        }\n\n                        this.codeMirror.markText(annotation.from, annotation.to, {\n                            className: 'CodeMirror-lint-mark-error',\n                            __annotation: annotation,\n                            clearOnEnter: true,\n                        });\n\n                        let errorTitle;\n                        if (error.title) {\n                            errorTitle = error.title;\n                        } else {\n                            errorTitle = '문법 오류';\n                        }\n\n                        let errorMsg;\n                        if (error.type == 2 && error.message) {\n                            errorMsg = error.message;\n                        } else if (error.type == 2 && !error.message) {\n                            errorMsg = '자바스크립트 코드를 확인해주세요.';\n                        } else if (error.type == 1) {\n                            errorMsg = '자바스크립트 문법을 확인해주세요.';\n                        }\n\n                        Entry.toast.alert(errorTitle, errorMsg);\n\n                        const mode = {};\n                        mode.boardType = Entry.Workspace.MODE_BOARD;\n                        mode.textType = Entry.Vim.TEXT_TYPE_JS;\n                        mode.runType = Entry.Vim.MAZE_MODE;\n                        Ntry.dispatchEvent('textError', mode);\n                        throw error;\n                    }\n                    result = [];\n                }\n                break;\n            case Entry.Vim.PARSER_TYPE_PY_TO_BLOCK:\n                try {\n                    this._pyBlockCount = {};\n                    this._pyThreadCount = 1;\n\n                    const pyAstGenerator = new Entry.PyAstGenerator();\n                    const threads = this.makeThreads(code);\n\n                    const astArray = [];\n                    let threadCount = 0;\n                    let ast;\n                    for (let index = 0; index < threads.length; index++) {\n                        let thread = threads[index];\n                        if (thread.length === 0) {\n                            continue;\n                        }\n                        thread = thread.replace(/\\t/gm, '    ');\n                        ast = pyAstGenerator.generate(thread);\n                        if (!ast) {\n                            continue;\n                        }\n                        this._pyThreadCount = threadCount++;\n                        this._pyBlockCount[threadCount] = thread.split('\\n').length - 1;\n                        if (ast.body.length !== 0) {\n                            astArray.push(ast);\n                        }\n                    }\n                    result = this._execParser.Programs(astArray);\n                    this._onError = false;\n                    break;\n                } catch (error) {\n                    this._onError = true;\n                    result = [];\n\n                    let annotation;\n                    if (this.codeMirror) {\n                        let err;\n                        if (error instanceof SyntaxError) {\n                            err = this.findSyntaxError(error);\n                            if (err) {\n                                annotation = {\n                                    from: { line: err.from.line - 1, ch: err.from.ch },\n                                    to: { line: err.to.line - 1, ch: err.to.ch },\n                                };\n                            }\n\n                            error.type = 'syntax';\n                        } else {\n                            err = error.line;\n                            if (err) {\n                                // 3 == 최초주석 및 import 구문\n                                annotation = {\n                                    from: { line: err.start.line + 3, ch: err.start.column },\n                                    to: { line: err.end.line + 3, ch: err.end.column },\n                                };\n                            }\n\n                            error.type = 'converting';\n                        }\n\n                        if (annotation) {\n                            const option = {\n                                className: 'CodeMirror-lint-mark-error',\n                                __annotation: annotation,\n                                clearOnEnter: true,\n                                inclusiveLeft: true,\n                                inclusiveRight: true,\n                                clearWhenEmpty: false,\n                            };\n\n                            this._marker = this.codeMirror.markText(\n                                annotation.from,\n                                annotation.to,\n                                option\n                            );\n                        }\n\n                        let title = '';\n                        let message = '';\n                        if (error.type === 'syntax') {\n                            title = error.title;\n                            message = this.makeSyntaxErrorDisplay(\n                                error.subject,\n                                error.keyword,\n                                error.message,\n                                err.from.line\n                            );\n                        } else if (error.type === 'converting') {\n                            title = error.title;\n                            message = error.message;\n                        }\n\n                        Entry.toast.alert(title, message);\n                        throw error;\n                    }\n                }\n\n                break;\n\n            case Entry.Vim.PARSER_TYPE_BLOCK_TO_JS:\n                var textCode = this._execParser.Code(code, parseMode);\n                result = textCode;\n                break;\n            case Entry.Vim.PARSER_TYPE_BLOCK_TO_PY: {\n                try {\n                    Entry.getMainWS().blockMenu.renderText();\n                    result = '';\n                    let funcKeysBackup;\n\n                    if (\n                        parseMode === Entry.Parser.PARSE_BLOCK &&\n                        code.type.substr(0, 5) === 'func_'\n                    ) {\n                        funcKeysBackup = Object.keys(this._execParser.funcDefMap);\n                    }\n\n                    const textCode = this._execParser.Code(code, parseMode);\n                    if (!this._pyHinter) {\n                        this._pyHinter = new Entry.PyHint(this.syntax);\n                    }\n\n                    if (!this._hasDeclaration) {\n                        this.initDeclaration();\n                    }\n\n                    if (parseMode === Entry.Parser.PARSE_GENERAL) {\n                        if (this.py_variableDeclaration) {\n                            result += this.py_variableDeclaration;\n                        }\n\n                        if (this.py_listDeclaration) {\n                            result += this.py_listDeclaration;\n                        }\n\n                        if (this.py_variableDeclaration || this.py_listDeclaration) {\n                            result += '\\n';\n                        }\n\n                        // Global Comment Append\n                        const globalCommentList = this._execParser.globalCommentList;\n                        if (globalCommentList.length > 0) {\n                            result += `${globalCommentList.join('\\n')}\\n\\n`;\n                        }\n\n                        // function Declaration\n                        const funcDefMap = this._execParser.funcDefMap;\n                        let fd = '';\n                        for (const funcKey in funcDefMap) {\n                            fd += `${funcDefMap[funcKey]}\\n\\n`;\n                        }\n\n                        result += fd;\n                    } else if (parseMode === Entry.Parser.PARSE_BLOCK) {\n                        if (funcKeysBackup && funcKeysBackup.indexOf(code.type) < 0) {\n                            result += `${this._execParser.funcDefMap[code.type]}\\n\\n`;\n                        }\n                    }\n                    if (textCode) {\n                        result += textCode.trim();\n                    }\n\n                    result = result.replace(/\\t/g, '    ');\n                    if (this._hasDeclaration) {\n                        this.removeDeclaration();\n                    }\n                } catch (e) {\n                    console.error(e);\n                    if (e.block) {\n                        Entry.toast.alert(\n                            Lang.TextCoding.title_converting,\n                            Lang.TextCoding.alert_legacy_no_support\n                        );\n                    }\n                    throw e;\n                }\n\n                break;\n            }\n        }\n\n        return result;\n    };\n\n    p.getLineNumber = function(start, end) {\n        const value = this.codeMirror.getValue();\n        const lines = {\n            from: {},\n            to: {},\n        };\n\n        const startline = value.substring(0, start).split(/\\n/gi);\n        lines.from.line = startline.length - 1;\n        lines.from.ch = startline[startline.length - 1].length;\n\n        const endline = value.substring(0, end).split(/\\n/gi);\n        lines.to.line = endline.length - 1;\n        lines.to.ch = endline[endline.length - 1].length;\n\n        return lines;\n    };\n\n    p.mappingSyntax = function(mode) {\n        const that = this;\n        if (this._syntax_cache[mode]) {\n            return this._syntax_cache[mode];\n        }\n\n        const types = Object.keys(Entry.block);\n        const availables = this.setAvailableCode();\n        const syntax = {};\n        if (mode === Entry.Vim.WORKSPACE_MODE) {\n            syntax['#dic'] = {};\n        }\n\n        for (let i = 0; i < types.length; i++) {\n            const type = types[i];\n            //if (Entry.type !== 'invisible' && (availables && (availables.indexOf(type) < 0)))\n            //continue;\n\n            if (mode === Entry.Vim.MAZE_MODE && availables && availables.indexOf(type) < 0) {\n                continue;\n            }\n\n            const block = Entry.block[type];\n\n            if (mode === Entry.Vim.MAZE_MODE) {\n                const syntaxArray = block.syntax;\n                if (!syntaxArray) {\n                    continue;\n                }\n\n                if (block.syntax.py) {\n                    continue;\n                }\n\n                let syntaxTemp = syntax;\n\n                for (let j = 0; j < syntaxArray.length; j++) {\n                    var key = syntaxArray[j];\n                    if (j === syntaxArray.length - 2 && typeof syntaxArray[j + 1] === 'function') {\n                        syntaxTemp[key] = syntaxArray[j + 1];\n                        break;\n                    }\n                    if (!syntaxTemp[key]) {\n                        syntaxTemp[key] = {};\n                    }\n                    if (j === syntaxArray.length - 1) {\n                        syntaxTemp[key] = type;\n                    } else {\n                        syntaxTemp = syntaxTemp[key];\n                    }\n                }\n            } else if (mode === Entry.Vim.WORKSPACE_MODE) {\n                var key = type;\n                const pySyntax = block.syntax && block.syntax.py;\n\n                if (!pySyntax) {\n                    continue;\n                }\n\n                pySyntax.map((s, i) => {\n                    let result;\n                    let tokens;\n\n                    if (typeof s === 'string') {\n                        result = {};\n                        tokens = s;\n                        result.key = key;\n                        result.syntax = s;\n                        result.template = s;\n                    } else {\n                        result = s;\n                        tokens = s.syntax;\n                        s.key = key;\n                        if (!s.template) {\n                            result.template = s.syntax;\n                        }\n                        if (s.dic) {\n                            syntax['#dic'][s.dic] = key;\n                        }\n                    }\n                    if (i === 0) {\n                        result.isDefault = true;\n                    }\n                    if (!tokens) {\n                        return;\n                    }\n                    tokens = tokens.split('(');\n\n                    if (/%/.test(tokens[1])) {\n                        if (tokens[0].length) {\n                            tokens = tokens[0];\n                        } else {\n                            tokens = tokens.join('(');\n                        }\n                    } else {\n                        tokens = tokens.join('(');\n                    }\n\n                    tokens = tokens.replace(/\\(\\):?/, '');\n\n                    if (s.keyOption) {\n                        tokens += `#${s.keyOption}`;\n                    }\n\n                    tokens = tokens.split('.');\n\n                    const newTokens = [];\n                    newTokens.push(tokens.shift());\n                    const restToken = tokens.join('.');\n                    if (restToken !== '') {\n                        newTokens.push(restToken);\n                    }\n                    tokens = newTokens;\n\n                    let syntaxPointer = syntax;\n                    for (var i = 0; i < tokens.length; i++) {\n                        const syntaxKey = tokens[i];\n                        if (i === tokens.length - 1) {\n                            syntaxPointer[syntaxKey] = result;\n                            const anotherKey = that._getAnotherSyntaxKey(syntaxKey);\n                            if (anotherKey) {\n                                syntaxPointer[anotherKey] = result;\n                            }\n                            break;\n                        }\n                        if (!syntaxPointer[syntaxKey]) {\n                            syntaxPointer[syntaxKey] = {};\n                        }\n                        syntaxPointer = syntaxPointer[syntaxKey];\n                    }\n                });\n            }\n        }\n        this._syntax_cache[mode] = syntax;\n        return syntax;\n    };\n\n    p.setAvailableCode = function() {\n        const WS = Entry.getMainWS();\n        if (!WS) {\n            return;\n        }\n\n        const blockMenu = WS.blockMenu;\n        const board = WS.board;\n        const container = Entry.conatainer;\n\n        let blocks = [];\n\n        if (blockMenu && blockMenu.code) {\n            blocks = blocks.concat(blockMenu.code.getBlockList());\n        }\n\n        if (container) {\n            blocks = blocks.concat(container.getBlockList());\n        } else if (!container && board && board.code) {\n            blocks = blocks.concat(board.code.getBlockList());\n        }\n\n        blocks = blocks.map((b) => b.type);\n        blocks = blocks.filter((b, index) => blocks.indexOf(b) === index);\n\n        this.availableCode = blocks;\n\n        return blocks;\n    };\n\n    p.findSyntaxError = function(error, threadCount) {\n        const loc = error.loc;\n        loc.line = loc.line + 2;\n        return {\n            from: { line: loc.line, ch: loc.column },\n            to: { line: loc.line, ch: loc.column + error.tokLen },\n        };\n    };\n\n    p.makeThreads = function(text) {\n        const textArr = text.split('\\n');\n        const threads = [];\n\n        let optText = '';\n        let onEntryEvent = false;\n\n        let startLine = 0;\n\n        // # 엔트리봇 ~ import Entry 제외\n        for (let i = 4; i < textArr.length; i++) {\n            const textLine = `${textArr[i]}\\n`;\n\n            if (textLine.trim().startsWith('#')) {\n                threads.push(`${textLine.trim()}\\n`);\n            } else if (Entry.TextCodingUtil.isEntryEventFuncByFullText(textLine.trim())) {\n                if (optText.length !== 0) {\n                    threads.push(makeLine(optText));\n                    startLine = i - 2;\n                }\n\n                optText = '';\n                optText += textLine;\n                onEntryEvent = true;\n            } else {\n                if (textLine.length === 1 && !onEntryEvent) {\n                    //empty line\n                    threads.push(makeLine(optText));\n                    startLine = i - 2;\n                    optText = '';\n                } else if (textLine.length !== 1 && textLine.charAt(0) !== ' ' && onEntryEvent) {\n                    //general line\n                    threads.push(makeLine(optText));\n                    startLine = i - 2;\n                    optText = '';\n                    onEntryEvent = false;\n                }\n                optText += textLine;\n            }\n        }\n\n        threads.push(makeLine(optText));\n        function makeLine(text) {\n            return new Array(startLine + 1).join('\\n') + text;\n        }\n        return threads;\n    };\n\n    p.makeSyntaxErrorDisplay = function(subject, keyword, message, line) {\n        let kw;\n        if (keyword) {\n            kw = `'${keyword}' `;\n        } else {\n            kw = '';\n        }\n\n        return `[${subject}]` + ` ${kw} : ${message} ` + `(line ${line})`;\n    };\n\n    p.initDeclaration = function() {\n        this.py_variableDeclaration = Entry.TextCodingUtil.generateVariablesDeclaration();\n        this.py_listDeclaration = Entry.TextCodingUtil.generateListsDeclaration();\n        this._hasDeclaration = true;\n    };\n\n    p.removeDeclaration = function() {\n        this.py_variableDeclaration = null;\n        this.py_listDeclaration = null;\n    };\n\n    p._getAnotherSyntaxKey = function(syntax) {\n        let replaced = false;\n        for (const key in SYNTAX_MAP) {\n            if (syntax.indexOf(key) > -1) {\n                replaced = true;\n                syntax = syntax.replace(new RegExp(key, 'gm'), SYNTAX_MAP[key]);\n            }\n        }\n\n        if (replaced) {\n            return syntax;\n        }\n    };\n})(Entry.Parser.prototype);\n"
  },
  {
    "path": "src/textcoding/static/codeMap.js",
    "content": "'use strict';\n\nEntry.CodeMap = {};\n\n(function (cc) {\n    cc.Entry = {\n        start_neighbor_scene: [\n            {\n                다음: 'next',\n                이전: 'prev',\n            },\n        ],\n        stop_object: [\n            {\n                thisOnly: 'self',\n                thisThread: 'this',\n                otherThread: 'others',\n                self: 'thisOnly',\n                this: 'thisThread',\n                others: 'otherThread',\n                모든: 'all',\n                자신: 'thisOnly',\n                이: 'thisThread',\n                '자신의 다른': 'otherThread',\n            },\n        ],\n        change_to_next_shape: [\n            {\n                prev: 'prev',\n                pre: 'prev',\n                다음: 'next',\n                이전: 'prev',\n            },\n        ],\n        add_effect_amount: [\n            {\n                색깔: 'color',\n                밝기: 'brightness',\n                투명도: 'transparency',\n            },\n        ],\n        change_effect_amount: [\n            {\n                색깔: 'color',\n                밝기: 'brightness',\n                투명도: 'transparency',\n            },\n        ],\n        change_object_index: [\n            {\n                front: 'FRONT',\n                forward: 'FORWARD',\n                backward: 'BACKWARD',\n                back: 'BACK',\n                '맨 앞': 'FRONT',\n                앞: 'FORWARD',\n                뒤: 'BACKWARD',\n                '맨 뒤': 'BACK',\n            },\n        ],\n        set_color: [\n            {\n                red: '#FF0000',\n                orange: '#FF9966',\n                yellow: '#FFFF66',\n                green: '#009900',\n                blue: '#3333FF',\n                navy: '#000099',\n                purple: '#993399',\n                black: '#000000',\n                white: '#FFFFFF',\n                brown: '#990000',\n            },\n        ],\n        set_text_color: [\n            {\n                red: '#FF0000',\n                orange: '#FF9966',\n                yellow: '#FFFF66',\n                green: '#009900',\n                blue: '#3333FF',\n                navy: '#000099',\n                purple: '#993399',\n                black: '#000000',\n                white: '#FFFFFF',\n                brown: '#990000',\n            },\n        ],\n        reach_something: [\n            null,\n            {\n                mouse: 'mouse_pointer',\n                wall: 'edge',\n                wall_up: 'edge_up',\n                wall_down: 'edge_down',\n                wall_right: 'edge_right',\n                wall_left: 'edge_left',\n                mouse_pointer: 'mouse',\n                edge: 'wall',\n                edge_up: 'wall_up',\n                edge_down: 'wall_down',\n                edge_right: 'wall_right',\n                edge_left: 'wall_left',\n                마우스포인터: 'mouse',\n            },\n            null,\n        ],\n        create_clone: [\n            {\n                자신: 'self',\n                self: 'self',\n            },\n        ],\n        text_read: [\n            {\n                자신: 'self',\n                self: 'self',\n            },\n        ],\n        locate: [\n            {\n                mouse: 'mouse_pointer',\n                mouse_pointer: 'mouse',\n                마우스포인터: 'mouse',\n            },\n        ],\n        locate_object_time: [\n            null,\n            {\n                mouse: 'mouse_pointer',\n                mouse_pointer: 'mouse',\n                마우스포인터: 'mouse',\n            },\n        ],\n        see_angle_object: [\n            {\n                mouse: 'mouse_pointer',\n                mouse_pointer: 'mouse',\n                마우스포인터: 'mouse',\n            },\n        ],\n        coordinate_mouse: [\n            null,\n            {\n                X: 'x',\n                Y: 'y',\n            },\n            null,\n        ],\n        coordinate_object: [\n            null,\n            {\n                자신: 'self',\n                self: 'self',\n            },\n            null,\n            {\n                크기: 'size',\n                방향: 'rotation',\n                '이동 방향': 'direction',\n                '모양 번호': 'picture_index',\n                '모양 이름': 'picture_name',\n                picture_index: 'shape_number',\n                picture_name: 'shape_name',\n                shape_number: 'picture_index',\n                shape_name: 'picture_name',\n            },\n        ],\n        choose_project_timer_action: [\n            null,\n            {\n                start: 'START',\n                stop: 'STOP',\n                reset: 'RESET',\n            },\n        ],\n        set_visible_project_timer: [\n            null,\n            {\n                show: 'SHOW',\n                hide: 'HIDE',\n            },\n        ],\n        get_date: [\n            null,\n            {\n                year: 'YEAR',\n                month: 'MONTH',\n                day: 'DAY',\n                hour: 'HOUR',\n                minute: 'MINUTE',\n                second: 'SECOND',\n            },\n        ],\n        distance_something: [\n            null,\n            {\n                mouse: 'mouse_pointer',\n                mouse_pointer: 'mouse',\n                마우스포인터: 'mouse',\n            },\n        ],\n        set_visible_answer: [\n            {\n                show: 'SHOW',\n                hide: 'HIDE',\n            },\n        ],\n        text_change_font: [\n            EntryStatic.fonts.reduce(\n                (obj, { family }) => ({\n                    ...obj,\n                    [family.toLowerCase()]: family,\n                }),\n                {}\n            ),\n        ],\n        get_block_count: [\n            {\n                자신: 'self',\n                self: 'self',\n            },\n        ],\n    };\n\n    cc.Arduino = {\n        arduino_ext_analog_list: [\n            {\n                a0: '0',\n                a1: '1',\n                a2: '2',\n                a3: '3',\n                a4: '4',\n                a5: '5',\n            },\n        ],\n        arduino_get_digital_toggle: [\n            {\n                on: 'high',\n                off: 'low',\n                high: 'on',\n                low: 'off',\n                HIGH: 'on',\n                LOW: 'off',\n            },\n        ],\n    };\n\n    cc.Hamster = {\n        hamster_play_note_for: [\n            {\n                4: 'hamster.note_c',\n                5: 'hamster.note_c_sharp',\n                6: 'hamster.note_d',\n                7: 'hamster.note_e_flat',\n                8: 'hamster.note_e',\n                9: 'hamster.note_f',\n                10: 'hamster.note_f_sharp',\n                11: 'hamster.note_g',\n                12: 'hamster.note_g_sharp',\n                13: 'hamster.note_a',\n                14: 'hamster.note_b_flat',\n                15: 'hamster.note_b',\n                'hamster.note_c': 4,\n                'hamster.note_c_sharp': 5,\n                'hamster.note_d_flat': 5,\n                'hamster.note_d': 6,\n                'hamster.note_e_flat': 7,\n                'hamster.note_d_sharp': 7,\n                'hamster.note_e': 8,\n                'hamster.note_f': 9,\n                'hamster.note_f_sharp': 10,\n                'hamster.note_g_flat': 10,\n                'hamster.note_g': 11,\n                'hamster.note_g_sharp': 12,\n                'hamster.note_a_flat': 12,\n                'hamster.note_a': 13,\n                'hamster.note_b_flat': 14,\n                'hamster.note_a_sharp': 14,\n                'hamster.note_b': 15,\n            },\n            null,\n            null,\n        ],\n    };\n\n    cc.Turtle = {\n        touching_colors: {\n            1: 'turtle.color_black',\n            2: 'turtle.color_red',\n            3: 'turtle.color_orange',\n            4: 'turtle.color_yellow',\n            5: 'turtle.color_green',\n            6: 'turtle.color_cyan',\n            7: 'turtle.color_blue',\n            8: 'turtle.color_magenta',\n            9: 'turtle.color_white',\n            'turtle.color_black': 1,\n            'turtle.color_red': 2,\n            'turtle.color_orange': 3,\n            'turtle.color_yellow': 4,\n            'turtle.color_green': 5,\n            'turtle.color_cyan': 6,\n            'turtle.color_sky_blue': 6,\n            'turtle.color_blue': 7,\n            'turtle.color_magenta': 8,\n            'turtle.color_purple': 8,\n            'turtle.color_white': 9,\n        },\n        pattern_colors: {\n            1: 'turtle.color_red',\n            3: 'turtle.color_yellow',\n            4: 'turtle.color_green',\n            5: 'turtle.color_cyan',\n            6: 'turtle.color_blue',\n            7: 'turtle.color_magenta',\n            'turtle.color_red': 1,\n            'turtle.color_yellow': 3,\n            'turtle.color_green': 4,\n            'turtle.color_cyan': 5,\n            'turtle.color_sky_blue': 5,\n            'turtle.color_blue': 6,\n            'turtle.color_magenta': 7,\n            'turtle.color_purple': 7,\n        },\n        units: {\n            CM: 'turtle.unit_cm',\n            DEG: 'turtle.unit_deg',\n            SEC: 'turtle.unit_sec',\n            PULSE: 'turtle.unit_pulse',\n            'turtle.unit_cm': 'CM',\n            'turtle.unit_deg': 'DEG',\n            'turtle.unit_sec': 'SEC',\n            'turtle.unit_pulse': 'PULSE',\n        },\n        head_tail: {\n            HEAD: 'turtle.head',\n            TAIL: 'turtle.tail',\n            'turtle.head': 'HEAD',\n            'turtle.tail': 'TAIL',\n        },\n        line_colors: {\n            10: 'turtle.color_black',\n            11: 'turtle.color_red',\n            13: 'turtle.color_green',\n            15: 'turtle.color_blue',\n            17: 'turtle.color_any',\n            'turtle.color_black': 10,\n            'turtle.color_red': 11,\n            'turtle.color_green': 13,\n            'turtle.color_blue': 15,\n            'turtle.color_any': 17,\n        },\n        target_colors: {\n            61: 'turtle.color_red',\n            62: 'turtle.color_yellow',\n            63: 'turtle.color_green',\n            64: 'turtle.color_cyan',\n            65: 'turtle.color_blue',\n            66: 'turtle.color_magenta',\n            67: 'turtle.color_any',\n            'turtle.color_red': 61,\n            'turtle.color_yellow': 62,\n            'turtle.color_green': 63,\n            'turtle.color_cyan': 64,\n            'turtle.color_sky_blue': 64,\n            'turtle.color_blue': 65,\n            'turtle.color_magenta': 66,\n            'turtle.color_purple': 66,\n            'turtle.color_any': 67,\n        },\n        color_lines: {\n            71: 'turtle.color_red',\n            73: 'turtle.color_green',\n            75: 'turtle.color_blue',\n            77: 'turtle.color_any',\n            'turtle.color_red': 71,\n            'turtle.color_green': 73,\n            'turtle.color_blue': 75,\n            'turtle.color_any': 77,\n        },\n        led_colors: {\n            RED: 'turtle.color_red',\n            ORANGE: 'turtle.color_orange',\n            YELLOW: 'turtle.color_yellow',\n            GREEN: 'turtle.color_green',\n            CYAN: 'turtle.color_cyan',\n            BLUE: 'turtle.color_blue',\n            VIOLET: 'turtle.color_violet',\n            MAGENTA: 'turtle.color_magenta',\n            WHITE: 'turtle.color_white',\n            'turtle.color_red': 'RED',\n            'turtle.color_orange': 'ORANGE',\n            'turtle.color_yellow': 'YELLOW',\n            'turtle.color_green': 'GREEN',\n            'turtle.color_cyan': 'CYAN',\n            'turtle.color_sky_blue': 'CYAN',\n            'turtle.color_blue': 'BLUE',\n            'turtle.color_violet': 'VIOLET',\n            'turtle.color_magenta': 'MAGENTA',\n            'turtle.color_purple': 'MAGENTA',\n            'turtle.color_white': 'WHITE',\n        },\n        sounds: {\n            1: 'turtle.sound_beep',\n            2: 'turtle.sound_random',\n            3: 'turtle.sound_siren',\n            4: 'turtle.sound_engine',\n            5: 'turtle.sound_robot',\n            6: 'turtle.sound_march',\n            7: 'turtle.sound_birthday',\n            8: 'turtle.sound_dibidibidip',\n            9: 'turtle.sound_good_job',\n            'turtle.sound_beep': 1,\n            'turtle.sound_random': 2,\n            'turtle.sound_siren': 3,\n            'turtle.sound_engine': 4,\n            'turtle.sound_robot': 5,\n            'turtle.sound_march': 6,\n            'turtle.sound_birthday': 7,\n            'turtle.sound_dibidibidip': 8,\n            'turtle.sound_good_job': 9,\n        },\n        notes: {\n            4: 'turtle.note_c',\n            5: 'turtle.note_c_sharp',\n            6: 'turtle.note_d',\n            7: 'turtle.note_e_flat',\n            8: 'turtle.note_e',\n            9: 'turtle.note_f',\n            10: 'turtle.note_f_sharp',\n            11: 'turtle.note_g',\n            12: 'turtle.note_g_sharp',\n            13: 'turtle.note_a',\n            14: 'turtle.note_b_flat',\n            15: 'turtle.note_b',\n            'turtle.note_c': 4,\n            'turtle.note_c_sharp': 5,\n            'turtle.note_d_flat': 5,\n            'turtle.note_d': 6,\n            'turtle.note_e_flat': 7,\n            'turtle.note_d_sharp': 7,\n            'turtle.note_e': 8,\n            'turtle.note_f': 9,\n            'turtle.note_f_sharp': 10,\n            'turtle.note_g_flat': 10,\n            'turtle.note_g': 11,\n            'turtle.note_g_sharp': 12,\n            'turtle.note_a_flat': 12,\n            'turtle.note_a': 13,\n            'turtle.note_b_flat': 14,\n            'turtle.note_a_sharp': 14,\n            'turtle.note_b': 15,\n        },\n    };\n})(Entry.CodeMap);\n"
  },
  {
    "path": "src/textcoding/static/keyboardCode.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.KeyboardCode = {};\n\n(function(kc) {\n    kc.map = {\n        backspace: 8,\n        'back-space': 8,\n        tab: 9,\n        enter: 13,\n        shift: 16,\n        ctrl: 17,\n        alt: 18,\n        pausebreak: 19,\n        capslock: 20,\n        esc: 27,\n        space: 32,\n        pageup: 33,\n        pagedown: 34,\n        end: 35,\n        home: 36,\n        left: 37,\n        up: 38,\n        right: 39,\n        down: 40,\n        insert: 45,\n        delete: 46,\n        '0': 48,\n        '1': 49,\n        '2': 50,\n        '3': 51,\n        '4': 52,\n        '5': 53,\n        '6': 54,\n        '7': 55,\n        '8': 56,\n        '9': 57,\n        a: 65,\n        b: 66,\n        c: 67,\n        d: 68,\n        e: 69,\n        f: 70,\n        g: 71,\n        h: 72,\n        i: 73,\n        j: 74,\n        k: 75,\n        l: 76,\n        m: 77,\n        n: 78,\n        o: 79,\n        p: 80,\n        q: 81,\n        r: 82,\n        s: 83,\n        t: 84,\n        u: 85,\n        v: 86,\n        w: 87,\n        x: 88,\n        y: 89,\n        z: 90,\n        windows: 91,\n        rightclick: 93,\n        numpad0: 96,\n        numpad1: 97,\n        numpad2: 98,\n        numpad3: 99,\n        numpad4: 100,\n        numpad5: 101,\n        numpad6: 102,\n        numpad7: 103,\n        numpad8: 104,\n        numpad9: 105,\n        'numpad*': 106,\n        'numpad+': 107,\n        'numpad-': 109,\n        'numpad.': 110,\n        'numpad/': 111,\n        f1: 112,\n        f2: 113,\n        f3: 114,\n        f4: 115,\n        f5: 116,\n        f6: 117,\n        f7: 118,\n        f8: 119,\n        f9: 120,\n        f10: 121,\n        f11: 122,\n        f12: 123,\n        numlock: 144,\n        scrolllock: 145,\n        mycomputer: 182,\n        mycalculator: 183,\n        ';': 186,\n        '=': 187,\n        ',': 188,\n        '-': 189,\n        '.': 190,\n        '/': 191,\n        '~': 192,\n        '[': 219,\n        '\\\\': 220,\n        ']': 221,\n        \"'\": 222,\n        backslash: 220,\n\n        // legacy keyinput support\n        '13': 13,\n        '16': 16,\n        '17': 17,\n        '18': 18,\n        '19': 19,\n        '20': 20,\n        '27': 27,\n        '32': 32,\n        '33': 33,\n        '34': 34,\n        '35': 35,\n        '36': 36,\n        '37': 37,\n        '38': 38,\n        '39': 39,\n        '40': 40,\n        '45': 45,\n        '46': 46,\n        '48': 48,\n        '49': 49,\n        '50': 50,\n        '51': 51,\n        '52': 52,\n        '53': 53,\n        '54': 54,\n        '55': 55,\n        '56': 56,\n        '57': 57,\n        '65': 65,\n        '66': 66,\n        '67': 67,\n        '68': 68,\n        '69': 69,\n        '70': 70,\n        '71': 71,\n        '72': 72,\n        '73': 73,\n        '74': 74,\n        '75': 75,\n        '76': 76,\n        '77': 77,\n        '78': 78,\n        '79': 79,\n        '80': 80,\n        '81': 81,\n        '82': 82,\n        '83': 83,\n        '84': 84,\n        '85': 85,\n        '86': 86,\n        '87': 87,\n        '88': 88,\n        '89': 89,\n        '90': 90,\n        '96': 96,\n        '97': 97,\n        '98': 98,\n        '99': 99,\n        '100': 100,\n        '101': 101,\n        '102': 102,\n        '103': 103,\n        '104': 104,\n        '105': 105,\n        '186': 186,\n        '187': 187,\n        '188': 188,\n        '189': 189,\n        '190': 190,\n        '191': 191,\n        '192': 192,\n        '219': 219,\n        '220': 220,\n        '221': 221,\n        '222': 222,\n    };\n\n    kc.codeToKeyCode = {\n        ArrowLeft: 37,\n        ArrowUp: 38,\n        ArrowRight: 39,\n        ArrowDown: 40,\n        Space: 32,\n        Control: 17,\n        ControlLeft: 17,\n        ControlRight: 17,\n        Shift: 16,\n        ShiftLeft: 16,\n        ShiftRight: 16,\n        Alt: 18,\n        AltLeft: 18,\n        AltRight: 18,\n        Tab: 9,\n        Escape: 27,\n        Backspace: 8,\n        Enter: 13,\n        KeyA: 65,\n        KeyB: 66,\n        KeyC: 67,\n        KeyD: 68,\n        KeyE: 69,\n        KeyF: 70,\n        KeyG: 71,\n        KeyH: 72,\n        KeyI: 73,\n        KeyJ: 74,\n        KeyK: 75,\n        KeyL: 76,\n        KeyM: 77,\n        KeyN: 78,\n        KeyO: 79,\n        KeyP: 80,\n        KeyQ: 81,\n        KeyR: 82,\n        KeyS: 83,\n        KeyT: 84,\n        KeyU: 85,\n        KeyV: 86,\n        KeyW: 87,\n        KeyX: 88,\n        KeyY: 89,\n        KeyZ: 90,\n        0: 48,\n        1: 49,\n        2: 50,\n        3: 51,\n        4: 52,\n        5: 53,\n        6: 54,\n        7: 55,\n        8: 56,\n        9: 57,\n        // for ie\n        Left: 37,\n        Up: 38,\n        Right: 39,\n        Down: 40,\n        Spacebar: 32,\n        a: 65,\n        b: 66,\n        c: 67,\n        d: 68,\n        e: 69,\n        f: 70,\n        g: 71,\n        h: 72,\n        i: 73,\n        j: 74,\n        k: 75,\n        l: 76,\n        m: 77,\n        n: 78,\n        o: 79,\n        p: 80,\n        q: 81,\n        r: 82,\n        s: 83,\n        t: 84,\n        u: 85,\n        v: 86,\n        w: 87,\n        x: 88,\n        y: 89,\n        z: 90,\n        // SpecialChar\n        ';': 186,\n        Semicolon: 186,\n        '=': 187,\n        Equal: 187,\n        ',': 188,\n        Comma: 188,\n        '-': 189,\n        Minus: 189,\n        '.': 190,\n        Period: 190,\n        '/': 191,\n        Slash: 191,\n        '`': 192,\n        Backquote: 192,\n        '[': 219,\n        BracketLeft: 219,\n        '\\\\': 220,\n        Backslash: 220,\n        ']': 221,\n        BracketRight: 221,\n        \"'\": 222,\n        Quote: 222,\n        Help: 45,\n        Insert: 45,\n        Delete: 46,\n        Home: 36,\n        End: 35,\n        PageUp: 33,\n        PageDown: 34,\n    };\n    /*kc.keyCodeToChar = {\n        8:\"backspace\",9:\"tab\",13:\"enter\",16:\"shift\",17:\"ctrl\",18:\"alt\",\n        19:\"pausebreak\",20:\"capslock\",27:\"esc\",32:\"space\",33:\"pageup\",\n        34:\"pagedown\",35:\"end\",36:\"home\",37:\"left\",38:\"up\",39:\"right\",\n        40:\"down\",45:\"insert\",46:\"delete\",48:\"0\",49:\"1\",50:\"2\",51:\"3\",\n        52:\"4\",53:\"5\",54:\"6\",55:\"7\",56:\"8\",57:\"9\",65:\"a\",66:\"b\",67:\"c\",\n        68:\"d\",69:\"e\",70:\"f\",71:\"g\",72:\"h\",73:\"i\",74:\"j\",75:\"k\",76:\"l\",\n        77:\"m\",78:\"n\",79:\"o\",80:\"p\",81:\"q\",82:\"r\",83:\"s\",84:\"t\",85:\"u\",\n        86:\"v\",87:\"w\",88:\"x\",89:\"y\",90:\"z\",91:\"windows\",93:\"right\",\n        96:\"numpad0\",97:\"numpad1\",98:\"numpad2\",99:\"numpad3\",\n        100:\"numpad4\",101:\"numpad5\",102:\"numpad6\",103:\"numpad7\",\n        104:\"numpad8\",105:\"numpad9\",106:\"numpad*\",107:\"numpad+\",\n        109:\"numpad-\",110:\"numpad.\",111:\"numpad/\",112:\"f1\",113:\"f2\",\n        114:\"f3\",115:\"f4\",116:\"f5\",117:\"f6\",118:\"f7\",119:\"f8\",120:\"f9\",\n        121:\"f10\",122:\"f11\",123:\"f12\",144:\"numlock\",145:\"scrolllock\",\n        182:\"mycomputer\",183:\"mycalculator\",186:\";\",187:\"=\",188:\",\",\n        189:\"-\",190:\".\",191:\"/\",192:\"`\",219:\"[\",220:\"\\\\\",221:\"]\",222:\"'\"\n    };\n    kc.keyCharToCode = {\n        \"backspace\":8,\"tab\":9,\"enter\":13,\"shift\":16,\"ctrl\":17,\"alt\":18,\n        \"pausebreak\":19,\"capslock\":20,\"esc\":27,\"space\":32,\"pageup\":33,\n        \"pagedown\":34,\"end\":35,\"home\":36,\"left\":37,\"up\":38,\"right\":39,\n        \"down\":40,\"insert\":45,\"delete\":46,\"0\":48,\"1\":49,\"2\":50,\"3\":51,\n        \"4\":52,\"5\":53,\"6\":54,\"7\":55,\"8\":56,\"9\":57,\"a\":65,\"b\":66,\"c\":67,\"d\":68,\n        \"e\":69,\"f\":70,\"g\":71,\"h\":72,\"i\":73,\"j\":74,\"k\":75,\"l\":76,\"m\":77,\"n\":78,\n        \"o\":79,\"p\":80,\"q\":81,\"r\":82,\"s\":83,\"t\":84,\"u\":85,\"v\":86,\"w\":87,\"x\":88,\n        \"y\":89,\"z\":90,\"windows\":91,\"rightclick\":93,\"numpad0\":96,\"numpad1\":97,\n        \"numpad2\":98,\"numpad3\":99,\"numpad4\":100,\"numpad5\":101,\"numpad6\":102,\n        \"numpad7\":103,\"numpad8\":104,\"numpad9\":105,\"numpad*\":106,\"numpad+\":107,\n        \"numpad-\":109,\"numpad.\":110,\"numpad/\":111,\"f1\":112,\"f2\":113,\"f3\":114,\n        \"f4\":115,\"f5\":116,\"f6\":117,\"f7\":118,\"f8\":119,\"f9\":120,\"f10\":121,\"f11\":122,\n        \"f12\":123,\"numlock\":144,\"scrolllock\":145,\"mycomputer\":182,\"mycalculator\":183,\n        \";\":186,\"=\":187,\",\":188,\"-\":189,\".\":190,\"/\":191,\"`\":192,\"[\":219,\"\\\\\":220,\"]\":221,\n        \"'\":222\n    };*/\n})(Entry.KeyboardCode);\n"
  },
  {
    "path": "src/textcoding/util/console.js",
    "content": "/*\n *\n */\n'use strict';\n\nEntry.Console = function() {\n    if (!Entry.propertyPanel) return;\n    this.createView();\n    Entry.propertyPanel.addMode('console', this);\n    Entry.console = this;\n\n    this._isEditing = false;\n    this._inputData = null;\n};\n\n(function(p) {\n    p.createView = function() {\n        this.view = Entry.Dom('div', {\n            id: 'entryConsole',\n        });\n\n        this.codeMirror = CodeMirror(this.view[0], {\n            readOnly: 'nocursor',\n            lineNumbers: false,\n            lineWrapping: true,\n            value: '',\n            mode: {},\n            theme: 'default',\n            styleActiveLine: false,\n            //gutters: [\"CodeMirror-lint-markers\"],\n            lint: false,\n        });\n        this._doc = this.codeMirror.getDoc();\n\n        this.codeMirror.on(\n            'beforeChange',\n            function(cm, change) {\n                if (!this._isEditing) change.cancel();\n                else if (change.origin === '+delete' && change.to.ch === 0) {\n                    change.cancel();\n                }\n            }.bind(this)\n        );\n\n        this.codeMirror.on(\n            'keyup',\n            function(cm, event) {\n                if (this._isEditing && event.keyCode === 13) {\n                    this.endInput();\n                }\n            }.bind(this)\n        );\n\n        this.codeMirror.on('cursorActivity', function(cm, event) {\n            cm.execCommand('goDocEnd');\n        });\n\n        Entry.addEventListener('stop', this.clear.bind(this));\n\n        this.clear();\n    };\n\n    p.getView = function() {\n        return this.view;\n    };\n\n    p.clear = function() {\n        this.setEditing(true);\n        this.codeMirror.setValue('Entry Console \\n');\n        this.codeMirror.execCommand('goDocEnd');\n        this.setEditing(false);\n    };\n\n    p.print = function(message, mode) {\n        if (!this.visible) return;\n\n        if (mode !== 'ask') {\n            this._doc.cm.options.readOnly = 'nocursor';\n        }\n        this.setEditing(true);\n        this.codeMirror.execCommand('goDocEnd');\n        var cursor = this._doc.getCursor();\n        var pos = {\n            line: cursor.line,\n            ch: 0,\n        };\n        this._doc.replaceRange(message + '\\n', pos);\n        this._doc.addLineClass(cursor.line, 'text', mode);\n        if (mode === 'speak') this.setEditing(false);\n        this.codeMirror.execCommand('goDocEnd');\n        if (mode === 'ask') {\n            this._doc.cm.options.readOnly = false;\n            this._doc.addLineClass(cursor.line + 1, 'text', 'answer');\n            this.codeMirror.focus();\n        }\n    };\n\n    p.endInput = function() {\n        var cursor = this._doc.getCursor();\n        var lineInfo = this.codeMirror.lineInfo(cursor.line);\n        if (lineInfo.textClass === 'answer') {\n            this._inputData = lineInfo.text;\n            var pos = {\n                line: cursor.line,\n                ch: lineInfo.text.length,\n            };\n            this._doc.replaceRange('\\n', pos);\n        } else this._inputData = this._doc.getLine(cursor.line - 1);\n        Entry.container.setInputValue(this._inputData);\n        this.setEditing(false);\n    };\n\n    p.stopInput = function(inputValue) {\n        this.setEditing(false);\n    };\n\n    p.setEditing = function(set) {\n        if (this._isEditing === set) return;\n        this._isEditing = set;\n    };\n})(Entry.Console.prototype);\n"
  },
  {
    "path": "src/textcoding/util/textCodingUtil.js",
    "content": "'use strict';\n\nclass TextCodingUtil {\n    // Entry 에서 사용 중\n    canUsePythonVariables(variables) {\n        return variables.every((variable) => {\n            const target = variable.variableType === 'variable' ? 'v' : 'l';\n            return !Entry.TextCodingUtil.validateName(variable.name, target);\n        });\n    }\n\n    // Entry 에서 사용 중\n    canUsePythonFunctions(functions) {\n        return functions.every(({ content }) => {\n            const code = new Entry.Code(content);\n            const funcSchemaBlock = code.getEventMap('funcDef')[0];\n            // const funcSchemaBlock = targets[targetKey].content.getEventMap('funcDef')[0];\n            const functionBlock = funcSchemaBlock && funcSchemaBlock.params[0];\n            const { params } = functionBlock;\n            const [functionName, parameterBlock] = params;\n\n            const errorMessage = this.getFunctionToPythonErrorMessage(\n                functionBlock,\n                functionName,\n                parameterBlock\n            );\n\n            return !errorMessage;\n        });\n    }\n\n    initQueue() {\n        this._funcParamQ = new Entry.Queue();\n        this._funcNameQ = new Entry.Queue();\n    }\n\n    clearQueue() {\n        this._funcParamQ.clear();\n        this._funcNameQ.clear();\n    }\n\n    indent(textCode) {\n        let result = '\\t';\n        const indentedCodeArr = textCode.split('\\n');\n        indentedCodeArr.pop();\n        result += indentedCodeArr.join('\\n\\t');\n        result = `\\t${result.trim()}`; //.concat('\\n');\n\n        return result;\n    }\n\n    isNumeric(value) {\n        const stringValue = String(Math.abs(value));\n        return !!(stringValue.match(/^-?\\d+$|^-\\d+$/) || stringValue.match(/^-?\\d+\\.\\d+$/));\n    }\n\n    isBinaryOperator(value) {\n        return ['==', '>', '<', '>=', '>=', '<=', '+', '-', '*', '/'].indexOf(value) > -1;\n    }\n\n    logicalExpressionConvert(operator) {\n        let result;\n        switch (operator) {\n            case '&&': {\n                result = null;\n                break;\n            }\n            case '||': {\n                result = null;\n                break;\n            }\n            default: {\n                result = operator;\n            }\n        }\n        return result;\n    }\n\n    dropdownDynamicIdToNameConvertor(id, menuName) {\n        let result;\n\n        switch (menuName) {\n            case 'variables': {\n                const entryVariables = Entry.variableContainer.variables_;\n                for (const varKey in entryVariables) {\n                    const entryVariable = entryVariables[varKey];\n                    if (entryVariable.id_ === id) {\n                        if (entryVariable.object_) {\n                            result = `self.${entryVariable.name_}`;\n                        } else {\n                            result = entryVariable.name_;\n                        }\n                        break;\n                    }\n                }\n                break;\n            }\n            case 'lists': {\n                const entryLists = Entry.variableContainer.lists_;\n                for (const listKey in entryLists) {\n                    const entryList = entryLists[listKey];\n                    if (entryList.id_ === id) {\n                        if (entryList.object_) {\n                            result = `self.${entryList.name_}`;\n                        } else {\n                            result = entryList.name_;\n                        }\n                        break;\n                    }\n                }\n                break;\n            }\n            case 'messages': {\n                const entryMessages = Entry.variableContainer.messages_;\n                for (const messageKey in entryMessages) {\n                    const entryList = entryMessages[messageKey];\n                    if (entryList.id === id) {\n                        result = entryList.name;\n                        break;\n                    }\n                }\n                break;\n            }\n            case 'pictures': {\n                const objects = Entry.container.getAllObjects();\n                for (const objKey in objects) {\n                    const object = objects[objKey];\n                    const pictures = object.pictures;\n                    for (const picKey in pictures) {\n                        const picture = pictures[picKey];\n                        if (picture.id === id) {\n                            result = picture.name;\n                            return result;\n                        }\n                    }\n                }\n                break;\n            }\n            case 'sounds': {\n                const objects = Entry.container.getAllObjects();\n                for (const objKey in objects) {\n                    const object = objects[objKey];\n                    const sounds = object.sounds;\n                    for (const soundKey in sounds) {\n                        const sound = sounds[soundKey];\n                        if (sound.id === id) {\n                            result = sound.name;\n                            return result;\n                        }\n                    }\n                }\n                break;\n            }\n            case 'scenes': {\n                const scenes = Entry.scene.getScenes();\n                for (const sceneKey in scenes) {\n                    const scene = scenes[sceneKey];\n                    if (scene.id === id) {\n                        result = scene.name;\n                        break;\n                    }\n                }\n                break;\n            }\n            case 'clone':\n            case 'textBoxWithSelf': {\n                if (id === 'self') {\n                    result = id;\n                } else {\n                    const objects = Entry.container.objects_.filter((obj) => obj.id === id);\n                    result = objects[0] ? objects[0].name : null;\n                }\n                break;\n            }\n        }\n\n        return result;\n    }\n\n    isEventBlock(block) {\n        const blockType = block.data.type;\n        return (\n            blockType == 'when_run_button_click' ||\n            blockType == 'when_some_key_pressed' ||\n            blockType == 'mouse_clicked' ||\n            blockType == 'mouse_click_cancled' ||\n            blockType == 'when_object_click' ||\n            blockType == 'when_object_click_canceled' ||\n            blockType == 'when_message_cast' ||\n            blockType == 'when_scene_start' ||\n            blockType == 'when_clone_start'\n        );\n    }\n\n    isEntryEventFuncByFullText(text) {\n        const index = text.indexOf('(');\n        const name = text.substring(0, index);\n\n        return (\n            name == 'def when_start' ||\n            name == 'def when_press_key' ||\n            name == 'def when_click_mouse_on' ||\n            name == 'def when_click_mouse_off' ||\n            name == 'def when_click_object_on' ||\n            name == 'def when_click_object_off' ||\n            name == 'def when_get_signal' ||\n            name == 'def when_start_scene' ||\n            name == 'def when_make_clone' ||\n            name == 'def entry_event_start' ||\n            name == 'def entry_event_key' ||\n            name == 'def entry_event_mouse_down' ||\n            name == 'def entry_event_mouse_up' ||\n            name == 'def entry_event_object_down' ||\n            name == 'def entry_event_object_up' ||\n            name == 'def entry_event_signal' ||\n            name == 'def entry_event_scene_start' ||\n            name == 'def entry_event_clone_create'\n        );\n    }\n\n    searchFuncDefParam(block) {\n        if (block.data.type == 'function_field_label') {\n            const name = block.data.params[0];\n            this._funcNameQ.enqueue(name);\n        }\n\n        if (block && block.data && block.data.params && block.data.params[1]) {\n            if (\n                block.data.type == 'function_field_string' ||\n                block.data.type == 'function_field_boolean'\n            ) {\n                const param = block.data.params[0].data.type;\n                this._funcParamQ.enqueue(param);\n            }\n\n            return this.searchFuncDefParam(block.data.params[1]);\n        } else {\n            return block;\n        }\n    }\n\n    gatherFuncDefParam(block) {\n        let result;\n        if (block && block.data) {\n            if (block.data.params[0]) {\n                if (block.data.params[0].data) {\n                    const param = block.data.params[0].data.type;\n                    if (\n                        block.data.type == 'function_field_string' ||\n                        block.data.type == 'function_field_boolean'\n                    ) {\n                        this._funcParamQ.enqueue(param);\n                    }\n                } else if (block.data.type == 'function_field_label') {\n                    const name = block.data.params[0];\n                    this._funcNameQ.enqueue(name);\n                }\n            }\n            if (block.data.params[1]) {\n                result = this.searchFuncDefParam(block.data.params[1]);\n\n                if (result.data.params[0].data) {\n                    const param = result.data.params[0].data.type;\n\n                    if (\n                        result.data.type == 'function_field_string' ||\n                        result.data.type == 'function_field_boolean'\n                    ) {\n                        this._funcParamQ.enqueue(param);\n                    }\n                }\n\n                if (result.data.params[1]) {\n                    if (result.data.params[1].data.params[0].data) {\n                        const param = result.data.params[1].data.params[0].data.type;\n\n                        if (\n                            result.data.params[1].data.type == 'function_field_string' ||\n                            result.data.params[1].data.type == 'function_field_boolean'\n                        ) {\n                            this._funcParamQ.enqueue(param);\n                        }\n                    }\n                }\n            }\n        }\n\n        return result;\n    }\n\n    isParamBlock(block) {\n        const type = block.type;\n        return (\n            type == 'ai_boolean_distance' ||\n            type == 'ai_distance_value' ||\n            type == 'ai_boolean_object' ||\n            type == 'ai_boolean_and'\n        );\n    }\n\n    hasBlockInfo(data, blockInfo) {\n        let result = false;\n        for (const key in blockInfo) {\n            const info = blockInfo[key];\n            if (key == data.type) {\n                for (const j in info) {\n                    const loc = info[j];\n                    if (loc.start == data.start && loc.end == data.end) {\n                        result = true;\n                        break;\n                    }\n                }\n            }\n        }\n\n        return result;\n    }\n\n    updateBlockInfo(data, blockInfo) {\n        const infoArr = blockInfo[data.type];\n        if (infoArr && Array.isArray(infoArr) && infoArr.legnth != 0) {\n            for (const i in infoArr) {\n                const info = infoArr[i];\n                if (info.start == data.start && info.end == data.end) {\n                    break;\n                } else {\n                    var loc = {};\n                    loc.start = data.start;\n                    loc.end = data.end;\n\n                    infoArr.push(loc);\n                }\n            }\n        } else {\n            blockInfo[data.type] = [];\n\n            var loc = {};\n            loc.start = data.start;\n            loc.end = data.end;\n\n            blockInfo[data.type].push(loc);\n        }\n    }\n\n    assembleRepeatWhileTrueBlock(block, syntax) {\n        let result = '';\n        if (block.data.type === 'repeat_while_true') {\n            const blockToken = syntax.split(/(?=:)|[ ]/gi); // space 로 split 하되, : 도 자르지만 토큰에 포함\n            let lastIndex = blockToken.length - 2;\n            const option = blockToken[lastIndex];\n\n            if (option == 'until') {\n                const condition = 'not';\n                blockToken.splice(1, 0, condition);\n                lastIndex += 1;\n                blockToken.splice(lastIndex, 1);\n                result = blockToken.join(' ').replace(/[ ]+:/, ':');\n            } else if (option == 'while') {\n                blockToken.splice(lastIndex, 1);\n                result = blockToken.join(' ').replace(/[ ]+:/, ':');\n            } else {\n                result = syntax;\n            }\n        } else {\n            result = syntax;\n        }\n\n        return result;\n    }\n\n    jsAdjustSyntax(block, syntax) {\n        let result = '';\n        if (block.data.type == 'ai_boolean_distance') {\n            var tokens = syntax.split(' ');\n            var firstParam = tokens[0].split('_');\n            var value = firstParam[1];\n            firstParam[1] = firstParam[1].substring(1, firstParam[1].length - 1);\n            firstParam[1] = firstParam[1].toLowerCase();\n            firstParam = firstParam.join('_');\n            var secondParam = tokens[1];\n            secondParam = this.bTojBinaryOperatorConvertor(secondParam);\n            var thirdParam = tokens[2];\n\n            result = `${firstParam} ${secondParam} ${thirdParam}`;\n        } else if (block.data.type == 'ai_boolean_object') {\n            var tokens = syntax.split(' ');\n            var firstParam = tokens[0].split('_');\n            var value = firstParam[1];\n            firstParam[1] = firstParam[1].substring(1, firstParam[1].length - 1);\n            firstParam[1] = firstParam[1].toLowerCase();\n            firstParam = firstParam.join('_');\n            var secondParam = tokens[1];\n            var thirdParam = tokens[2];\n\n            result = `${firstParam} ${secondParam} ${thirdParam}`;\n        } else if (block.data.type == 'ai_distance_value') {\n            var tokens = syntax.split(' ');\n            var firstParam = tokens[0].split('_');\n            var value = firstParam[1];\n            firstParam[1] = firstParam[1].substring(1, firstParam[1].length - 1);\n            firstParam[1] = firstParam[1].toLowerCase();\n            firstParam = firstParam.join('_');\n\n            result = firstParam;\n        } else {\n            result = syntax;\n        }\n\n        return result;\n    }\n\n    bTojBinaryOperatorConvertor(operator) {\n        let result;\n        switch (operator) {\n            case \"'BIGGER'\":\n                result = '>';\n                break;\n            case \"'BIGGER_EQUAL'\":\n                result = '>=';\n                break;\n            case \"'EQUAL'\":\n                result = '==';\n                break;\n            case \"'SMALLER'\":\n                result = '<';\n                break;\n            case \"'SMALLER_EQUAL'\":\n                result = '<=';\n                break;\n        }\n\n        return result;\n    }\n\n    jTobBinaryOperatorConvertor(operator) {\n        let result;\n        switch (operator) {\n            case '>':\n                result = 'BIGGER';\n                break;\n            case '>=':\n                result = 'BIGGER_EQUAL';\n                break;\n            case '==':\n                result = 'EQUAL';\n                break;\n            case '<':\n                result = 'SMALLER';\n                break;\n            case '<=':\n                result = 'SMALLER_EQUAL';\n                break;\n        }\n\n        return result;\n    }\n\n    radarVariableConvertor(variable) {\n        const items = variable.split('_');\n        return items[1].toUpperCase();\n    }\n\n    tTobDropdownValueConvertor(value) {\n        let result;\n        if (value == 'stone') {\n            result = 'OBSTACLE';\n        } else if (value == 'wall') {\n            result = value.toUpperCase();\n        } else if (value == 'item') {\n            result = value.toUpperCase();\n        } else {\n            result = value;\n        }\n\n        return result;\n    }\n\n    canConvertTextModeForOverlayMode(convertingMode) {\n        let message;\n        const oldMode = Entry.getMainWS().oldMode;\n\n        if (\n            oldMode == Entry.Workspace.MODE_OVERLAYBOARD &&\n            convertingMode == Entry.Workspace.MODE_VIMBOARD\n        ) {\n            message = Lang.TextCoding[Entry.TextCodingError.ALERT_FUNCTION_EDITOR];\n            return message;\n        }\n\n        return message;\n    }\n\n    /**\n     * TODO 18년 9월자 배포(10/4) 일 임시 코드입니다. 차후 수정 필수입니다.\n     * https://oss.navercorp.com/entry/Entry/issues/9155 링크 참조\n     * @returns {{message: string, type: string} || undefined}\n     */\n    hasNotSupportedBlocks() {\n        const vc = Entry.variableContainer;\n        if (!vc) {\n            return;\n        }\n\n        const activatedExpansionBlocks = Entry.expansionBlocks;\n        const activatedUtilizeBlock = Entry.aiUtilizeBlocks;\n        const tables = Entry.playground.dataTable ? Entry.playground.dataTable.tables : [];\n        const functions = Entry.variableContainer.functions_;\n        const isNotPythonSupportFunciton = Object.keys(functions).some(\n            (key) => functions[key].useLocalVariables || functions[key].type === 'value'\n        );\n        const isNotSupportedUsed = this.getNotSupportedBlocks().some((name) =>\n            Entry.Utils.isUsedBlockType(name)\n        );\n        if (\n            activatedExpansionBlocks.length > 0 ||\n            activatedUtilizeBlock.length > 0 ||\n            Entry.aiLearning?.isLoaded ||\n            isNotPythonSupportFunciton ||\n            tables.length > 0 ||\n            isNotSupportedUsed\n        ) {\n            return {\n                message: Lang.TextCoding[Entry.TextCodingError.ALERT_API_NO_SUPPORT],\n                type: 'warning',\n            };\n        }\n    }\n\n    getNotSupportedBlocks() {\n        if (EntryStatic.pythonDisabled) {\n            return EntryStatic.pythonDisabled;\n        }\n        EntryStatic.pythonDisabled = Object.keys(Entry.block).filter(\n            (key) => Entry.block[key]?.isNotFor?.indexOf('python_disable') >= 0\n        );\n        return EntryStatic.pythonDisabled;\n    }\n\n    removeNotSupportedBlock(names = []) {\n        this.getNotSupportedBlocks().forEach((blockType) => {\n            Entry.Utils.removeBlockByType(blockType);\n        });\n    }\n\n    /**\n     * 현재 코드 내 변수, 리스트에 대해 공백/특수문자/예약어/숫자시작 여부를 검사한다.\n     * @return {Object} 에러오브젝트\n     */\n    validateVariableAndListToPython() {\n        const vc = Entry.variableContainer;\n        if (!vc) {\n            return;\n        }\n        return (\n            this.validateVariable(vc.variables_ || [], 'v') ||\n            this.validateList(vc.lists_ || [], 'l')\n        );\n    }\n\n    validateVariable(variables, errorSuffix) {\n        for (let i = 0; i < variables.length; i++) {\n            const errorMessage = this.validateName(variables[i].name_, errorSuffix);\n            if (errorMessage) {\n                return errorMessage;\n            }\n        }\n    }\n\n    validateList(targets, errorSuffix) {\n        let errorMessage = undefined;\n\n        for (let i = 0; i < targets.length; i++) {\n            const list = targets[i];\n\n            errorMessage = this.validateName(list.name_, errorSuffix);\n            // 객체별 내부값 검사 후 문제가 없으면 리스트명에 대한 검사\n            for (let j = 0; j < list.getArray().length; j++) {\n                if (errorMessage) {\n                    break;\n                }\n                const elem = list.getArray()[j];\n                errorMessage = this.validateTargetNotExceedMaxNumber(elem.data);\n            }\n\n            if (errorMessage) {\n                return errorMessage;\n            }\n        }\n    }\n\n    /**\n     * 현재 코드 내 함수에 대해 공백/특수문자/예약어/숫자시작 여부 외에,\n     * 함수명 필드 시작여부 / 함수명 다중 사용여부 / boolean 타입 필드 사용여부를 검사한다.\n     * boolean 은 구조상 파이선으로 변환하면 일반필드가 되어버린다.\n     * @return {Object} 에러 / 경고 오브젝트\n     */\n    validateFunctionToPython() {\n        const vc = Entry.variableContainer;\n        if (!vc) {\n            return;\n        }\n\n        const targets = vc.functions_ || {};\n\n        for (const targetKey in targets) {\n            const funcSchemaBlock = targets[targetKey].content.getEventMap('funcDef')[0];\n            const functionBlock = funcSchemaBlock && funcSchemaBlock.params[0];\n            const { params } = functionBlock;\n            const [functionName, parameterBlock] = params;\n            const result = this.getFunctionToPythonErrorMessage(\n                functionBlock,\n                functionName,\n                parameterBlock\n            );\n\n            if (result) {\n                return result;\n            }\n        }\n        return false;\n    }\n\n    returnErrorResult = (errorMessage) => this._generateErrorObject(errorMessage, 'error');\n\n    getFunctionToPythonErrorMessage(functionBlock, functionName, parameterBlock) {\n        const {\n            ALERT_FUNCTION_NAME_DISORDER,\n            ALERT_FUNCTION_NAME_FIELD_MULTI,\n            ALERT_FUNCTION_HAS_BOOLEAN,\n        } = Entry.TextCodingError;\n        const DISORDER = Lang.TextCoding[ALERT_FUNCTION_NAME_DISORDER];\n        const FIELD_MULTI = Lang.TextCoding[ALERT_FUNCTION_NAME_FIELD_MULTI];\n        const HAS_BOOLEAN = Lang.TextCoding[ALERT_FUNCTION_HAS_BOOLEAN];\n        if (!functionBlock) {\n            return;\n        }\n\n        // 함수의 첫 값이 함수명필드여야 한다.\n        if (functionBlock.type !== 'function_field_label') {\n            return this.returnErrorResult(DISORDER);\n        }\n\n        // 함수명의 특수문자, 예약어, 숫자로 시작됨 여부 검사\n        // 공백검사는 하지 않는다. 공백은 __ 로 치환되기 때문이다.\n        const errorMessageObject =\n            this.validateNameNotStartWithNumber(functionName, 'f') ||\n            this.validateNameNotStartWithSpecials(functionName, 'f') ||\n            this.validateNameIsReservedKeyword(functionName, 'f');\n\n        if (errorMessageObject) {\n            return errorMessageObject;\n        }\n\n        // 함수명 필드는 여러개 등장할 수 없다.\n        if (this.hasFunctionFieldLabel(parameterBlock)) {\n            return this.returnErrorResult(FIELD_MULTI);\n        }\n\n        // 'warning' 함수인자에 boolean 타입이 있는 경우 변환시 일반 필드화가 된다.\n        if (this.hasFunctionBooleanField(parameterBlock)) {\n            return this._generateErrorObject(HAS_BOOLEAN, 'warning');\n        }\n    }\n\n    hasFunctionFieldLabel(fBlock) {\n        if (!fBlock || !fBlock.data) {\n            return;\n        }\n        if (fBlock.data.type == 'function_field_label') {\n            return true;\n        }\n\n        const params = fBlock.data.params;\n        if (params[0]) {\n            var type = params[0].data.type;\n            if (type == 'function_field_label') {\n                return true;\n            }\n            if (params[0].data.params) {\n                if (this.hasFunctionFieldLabel(params[0])) {\n                    return true;\n                }\n            }\n        }\n\n        if (params[1]) {\n            var type = params[1].data.type;\n            if (type == 'function_field_label') {\n                return true;\n            }\n            if (params[1].data.params) {\n                if (this.hasFunctionFieldLabel(params[1])) {\n                    return true;\n                }\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * 함수 인자에 판단형 파라미터가 존재하는지 찾는다.\n     * 이 함수는 재귀로 동작한다.\n     * @param fBlock 함수명이 포함되지 않은 functionBlock 목록\n     * @returns {Boolean} 판단형 파라미터가 존재하는 경우 true, 존재하지 않는 경우 false\n     */\n    hasFunctionBooleanField(fBlock) {\n        if (!fBlock || !fBlock.data) {\n            return false;\n        }\n        const { data } = fBlock;\n        return (\n            data.type === 'function_field_boolean' || this.hasFunctionBooleanField(data.params[1])\n        );\n    }\n\n    /**\n     * 예약어 사용여부, 공백 사용여부, 숫자로 시작여부, 특수문자 사용 여부를 검사한다.\n     * @param target{string} 검사할 name\n     * @param errorSuffix{string} l = 리스트, v = 변수, f = 함수\n     * @return {Object || undefined} 에러메세지를 반환하거나 아무것도 반환하지 않는다\n     * @property message{string} 에러메세지\n     * @property type{string} 'error' 고정. 타입이 에러인 메세지 반환\n     */\n    validateName(target, errorSuffix) {\n        //이름엔 공백이 포함될 수 없다.\n        //이름 맨앞에 _ 를 제외한 특수문자가 올 수 없다.\n        //변수명은 예약어가 될 수 없다.\n        const errorMessage = this.validateNameIncludeSpace(target, errorSuffix);\n        if (errorMessage) {\n            return this._generateErrorObject(errorMessage, 'error');\n        }\n\n        //이름 맨앞에 숫자가 올 수 없다.\n        const errorObject =\n            this.validateNameNotStartWithNumber(target, errorSuffix) ||\n            this.validateNameNotStartWithSpecials(target, errorSuffix) ||\n            this.validateNameIsReservedKeyword(target, errorSuffix);\n\n        if (errorObject) {\n            return errorObject;\n        }\n    }\n\n    /**\n     * target 값의 길이가 15가 넘어갔는지 검사한다.\n     * target 이 문자인 경우는 true 를 반환한다. #10921\n     * @param target {string | number}\n     * @return {Object|undefined}\n     */\n    validateTargetNotExceedMaxNumber(target) {\n        const convertedNumber = Number(target);\n        let isValid;\n\n        if (typeof target === 'string') {\n            // 검사를 넘어가는 경우는,\n            // 숫자 변환 불가능한 문자거나, 앞이 0으로 시작되는 문자거나, 숫자변환 가능하고 0으로 시작되지 않고 길이 15 이하\n            isValid = isNaN(convertedNumber) || target[0] === '0' || target.length <= 15;\n        } else {\n            // number 라고 가정한 경우 15자리 수 이하여야 한다.\n            isValid = Math.ceil(Math.log10(target + 1)) <= 15;\n        }\n\n        if (!isValid) {\n            return this._generateErrorObject(\n                Lang.TextCoding[Entry.TextCodingError.ALERT_LIST_CONTAINS_EXCEED_LENGTH_VALUE],\n                'error'\n            );\n        }\n    }\n\n    /**\n     * 공백이 들었는지 검사한다. 외부에서 사용하고 있어서 리턴타입을 변경하지 않았다.\n     * @param name 타겟\n     * @param type variable|v|list|l|function|f 이에 맞춰서 에러메세지가 변경된다.\n     * @return {string|undefined} 에러메세지\n     */\n    validateNameIncludeSpace(name, type) {\n        if (!/ /.test(name)) {\n            return;\n        }\n\n        if (type === 'variable' || type === 'v') {\n            return Lang.TextCoding[Entry.TextCodingError.ALERT_VARIABLE_EMPTY_TEXT_ADD_CHANGE];\n        } else if (type === 'list' || type === 'l') {\n            return Lang.TextCoding[Entry.TextCodingError.ALERT_LIST_EMPTY_TEXT_ADD_CHANGE];\n        } else if (type === 'function' || type === 'f') {\n            return Lang.TextCoding[Entry.TextCodingError.ALERT_FUNCTION_NAME_EMPTY_TEXT_ADD_CHANGE];\n        }\n    }\n\n    /**\n     * 이름이 숫자로 시작하는지 검사. 숫자로 시작하는 경우 에러 메세지를 반환한다.\n     * @param name 타겟\n     * @param errorSuffix v|l|f 이에 맞춰서 에러메세지가 변경된다.\n     * @return {{message: string, type: string} | undefined} 에러메세지\n     */\n    validateNameNotStartWithNumber(name, errorSuffix) {\n        //이름 맨앞에 숫자가 올 수 없다.\n        const regExp = /^[0-9]$/g;\n        if (regExp.test(name[0])) {\n            return this._generateErrorObject(\n                Lang.Menus[`textcoding_numberError_${errorSuffix}`],\n                'error'\n            );\n        }\n    }\n\n    /**\n     * 이름이 _ 를 제외한 특수문자로 시작하는지 검사. 해당하는 경우 에러 메세지를 반환한다.\n     * @param name 타겟\n     * @param errorSuffix v|l|f 이에 맞춰서 에러메세지가 변경된다.\n     * @return {{message: string, type: string} | undefined} 에러메세지\n     */\n    validateNameNotStartWithSpecials(name, errorSuffix) {\n        const regExp = /[\\{\\}\\[\\]\\/?.,;:|\\)*~`!^\\-+<>@\\#$%&\\\\\\=\\(\\'\\\"]/gi;\n        if (regExp.test(name)) {\n            return this._generateErrorObject(\n                Lang.Menus[`textcoding_specialCharError_${errorSuffix}`],\n                'error'\n            );\n        }\n    }\n\n    validateNameIsReservedKeyword(name, errorSuffix) {\n        const keywords = [\n            'and',\n            'assert',\n            'break',\n            'class',\n            'continue',\n            'def',\n            'del',\n            'elif',\n            'else',\n            'except',\n            'exec',\n            'finally',\n            'for',\n            'from',\n            'global',\n            'if',\n            'import',\n            'in',\n            'is',\n            'lambda',\n            'not',\n            'or',\n            'pass',\n            'print',\n            'raise',\n            'return',\n            'try',\n            'while',\n            'with',\n            'yield',\n            'None',\n        ];\n\n        //변수명은 예약어가 될 수 없다.\n        if (keywords.includes(name)) {\n            return this._generateErrorObject(\n                Lang.Menus[`textcoding_bookedError_1${errorSuffix}`] +\n                    name +\n                    Lang.Menus[`textcoding_bookedError_2${errorSuffix}`],\n                'error'\n            );\n        }\n    }\n\n    /**\n     * 에러메세지를 만든다. 단순히 오브젝트를 지정하는 것 말고는 하지 않는다.\n     * @param message{string} 에러메세지\n     * @param type{string} error | warning warning 인 경우는 변환은 성공하나, 알림이 발생한다.\n     * @return {{message: string, type: string}}\n     * @private\n     */\n    _generateErrorObject(message, type) {\n        return {\n            message,\n            type,\n        };\n    }\n\n    generateVariablesDeclaration() {\n        let result = '';\n        const currentObject = Entry.playground.object;\n        const vc = Entry.variableContainer;\n        if (!vc) {\n            return;\n        }\n        //inspect variables\n        const targets = vc.variables_ || [];\n\n        for (let i = targets.length - 1; i >= 0; i--) {\n            const v = targets[i];\n            let name = v.name_;\n            let value = v.value_;\n\n            if (v.object_) {\n                if (v.object_ == currentObject.id) {\n                    name = `self.${name}`;\n                } else {\n                    continue;\n                }\n            }\n\n            if (typeof value === 'string') {\n                value = '\"()\"'.replace('()', value);\n            }\n\n            result += `${name} = ${value}\\n`;\n        }\n\n        return result;\n    }\n\n    generateListsDeclaration() {\n        let result = '';\n        const currentObject = Entry.playground.object;\n        const vc = Entry.variableContainer;\n        if (!vc) {\n            return;\n        }\n\n        //inspect lists\n        const targets = vc.lists_ || [];\n\n        for (let i = targets.length - 1; i >= 0; i--) {\n            const l = targets[i];\n            let name = l.name_;\n            let value = '';\n            const lArray = l.array_;\n            if (l.object_) {\n                if (l.object_ == currentObject.id) {\n                    name = `self.${name}`;\n                } else {\n                    continue;\n                }\n            }\n\n            for (const va in lArray) {\n                const vItem = lArray[va];\n                let data = vItem.data;\n\n                if (isNaN(data) || (data.length > 1 && String(data)[0] === '0')) {\n                    data = `\"${data.replace(/\"/gi, '\\\\\"')}\"`;\n                }\n\n                if (typeof data === 'number' || (data.trim && data.trim().length > 0)) {\n                    value += data;\n                }\n\n                if (va != lArray.length - 1) {\n                    value += ', ';\n                }\n            }\n\n            result += `${name} = [${value}]` + `\\n`;\n        }\n\n        return result;\n    }\n\n    generateForStmtIndex(index, str) {\n        str = str || '';\n        const ref = ['i', 'j', 'k'];\n        const quotient = Math.floor(index / 3);\n        const remainder = index % 3;\n\n        str = ref[remainder] + str;\n\n        if (quotient) {\n            return this.generateForStmtIndex(quotient - 1, str);\n        } else {\n            return str;\n        }\n    }\n\n    /**\n     * 함수명 템플릿에서 함수명을 추출한다.\n     * 함수명은 아래의 규칙을 따른다.\n     * - 공백은 __로 치환된다.\n     * - 함수명이 '' 인 경우는 '함수' 로 대체된다.\n     * @param template{string} 함수명 템플릿\n     * @return {string} 치환된 함수\n     */\n    getFunctionNameFromTemplate(template) {\n        if (!template) {\n            return Lang.Workspace.func;\n        }\n\n        const trimmedFunctionName = template.split(/%\\d/)[0].trim();\n        if (trimmedFunctionName === '') {\n            return Lang.Workspace.func;\n        }\n\n        return trimmedFunctionName.replace(/ /gi, '__');\n    }\n}\n\nEntry.TextCodingUtil = {};\nEntry.TextCodingUtil = new TextCodingUtil();\n"
  },
  {
    "path": "src/theme/old.js",
    "content": "'use strict';\n\n/**\n * 기존 색상 팔레트\n */\nmodule.exports = {\n    arrow: {\n        default: {\n            DEFAULT: '#FFFFFF',\n            START: '#2F975A',\n            FLOW: '#3A71BC',\n            MOVING: '#8641B6',\n            LOOKS: '#D8234E',\n            TEXT: '#DC9C32',\n            SOUND: '#83A617',\n            JUDGE: '#89A1F7',\n            CALC: '#E8B349',\n            VARIABLE: '#CE38CE',\n            HARDWARE: '#097E84',\n            EXPANSION: '#FF8888',\n        },\n    },\n    block: {\n        default: {\n            START: '#3BBD70',\n            FLOW: '#498DEB',\n            MOVING: '#A751E3',\n            LOOKS: '#EC4466',\n            BRUSH: '#FF9E20',\n            SOUNDS: '#A4D01D',\n            HARDWARE: '#00979D',\n            CALC: '#FFD974',\n            VARIABLE: '#E457DC',\n            FUNCTION: '#CC7337',\n            JUDGE: '#AEB8FF',\n            TEXT: '#FFCA36',\n            EXPANSION: '#FF8888',\n        },\n        lighten: {\n            //NOTE not have boolean, extension block color\n            START: '#53E68E',\n            FLOW: '#4ADAFB',\n            MOVING: '#CA7DFF',\n            LOOKS: '#FF7792',\n            BRUSH: '#FF9831',\n            SOUND: '#9FEC35',\n            HARDWARE: '#65E3E0',\n            CALC: '#FFDE82',\n            VARIABLE: '#FAA0F7',\n            FUNC: '#F3853B',\n            TEXT: '#FF9354',\n        },\n        darken: {\n            START: '#13BF68',\n            FLOW: '#08ACDD',\n            MOVING: '#B13EFE',\n            LOOKS: '#EE3157',\n            BRUSH: '#FC5E01',\n            SOUND: '#6EBC02',\n            HARDWARE: '#04B5B0',\n            CALC: '#FF9C00',\n            VARIABLE: '#EC52E7',\n            FUNC: '#C85404',\n            JUDGE: '#6173F5',\n            TEXT: '#E43500',\n            EXPANSION: '#EF6D6D',\n        },\n        emphasize: {\n            '#3BBD70': '#5BC982',\n            '#498DEB': '#62A5F4',\n            '#A751E3': '#C08FF7',\n            '#EC4466': '#F46487',\n            '#FF9E20': '#FFB05A',\n            '#A4D01D': '#C4DD31',\n            '#00979D': '#09BAB5',\n            '#FFD974': '#FCDA90',\n            '#E457DC': '#F279F2',\n            '#CC7337': '#DD884E',\n            '#AEB8FF': '#C0CBFF',\n            '#FFCA36': '#F2C670',\n        },\n        common: {\n            WHITE: '#FFFFFF',\n            DARK: '#000000'\n        }\n    },\n};"
  },
  {
    "path": "src/theme/standard.js",
    "content": "'use strict';\n\n/**\n * static.js 의 default colorSet 과 동일합니다.\n * 정확한 기획스펙이 없는 상태에서 page reload 없이 ws 만 재로딩 하는 경우\n * 다른 theme -> 초기 theme 로 돌아갈때 필요할 수 있어서 만들어둔 테마입니다.\n */\nmodule.exports = {\n    arrow: {\n        default: {\n            DEFAULT: '#FFFFFF',\n            START: '#FFFFFF',\n            FLOW: '#3A71BC',\n            MOVING: '#8641B6',\n            LOOKS: '#FFFFFF',\n            TEXT: '#DC9C32',\n            SOUND: '#83A617',\n            JUDGE: '#89A1F7',\n            CALC: '#E8B349',\n            VARIABLE: '#CE38CE',\n            HARDWARE: '#097E84',\n            EXPANSION: '#FF8888',\n        },\n    },\n    block: {\n        default: {\n            START: '#10D35E',\n            FLOW: '#31C1EC',\n            MOVING: '#BF63FF',\n            LOOKS: '#FF5174',\n            BRUSH: '#FC7E01',\n            SOUND: '#82D214',\n            HARDWARE: '#00CFCA',\n            CALC: '#FEB71A',\n            VARIABLE: '#F57DF1',\n            FUNC: '#DE6E22',\n            JUDGE: '#7E8EFE',\n            TEXT: '#FC5D01',\n            EXPANSION: '#FF8888',\n        },\n        lighten: {\n            //NOTE not have boolean, extension block color\n            START: '#53E68E',\n            FLOW: '#4ADAFB',\n            MOVING: '#CA7DFF',\n            LOOKS: '#FF7792',\n            BRUSH: '#FF9831',\n            SOUND: '#9FEC35',\n            HARDWARE: '#65E3E0',\n            CALC: '#FFDE82',\n            VARIABLE: '#FAA0F7',\n            FUNC: '#F3853B',\n            TEXT: '#FF9354',\n        },\n        darken: {\n            START: '#13BF68',\n            FLOW: '#08ACDD',\n            MOVING: '#B13EFE',\n            LOOKS: '#EE3157',\n            BRUSH: '#FC5E01',\n            SOUND: '#6EBC02',\n            HARDWARE: '#04B5B0',\n            CALC: '#FF9C00',\n            VARIABLE: '#EC52E7',\n            FUNC: '#C85404',\n            JUDGE: '#1B3AD8',\n            TEXT: '#E43500',\n            EXPANSION: '#EF6D6D',\n        },\n        emphasize: {\n            '#10D35E': '#5BC982',\n            '#31C1EC': '#62A5F4',\n            '#BF63FF': '#C08FF7',\n            '#FF5174': '#F46487',\n            '#FC7E01': '#FFB05A',\n            '#82D214': '#C4DD31',\n            '#00CFCA': '#09BAB5',\n            '#FEB71A': '#FCDA90',\n            '#F57DF1': '#F279F2',\n            '#DE6E22': '#DD884E',\n            '#7E8EFE': '#C0CBFF',\n            '#FC5D01': '#F2C670',\n        },\n    },\n    common: {\n        WHITE: '#FFFFFF',\n        DARK: '#000000'\n    }\n};"
  },
  {
    "path": "src/util/audioSocket.js",
    "content": "import audioUtils from './audioUtils';\nimport io from 'socket.io-client';\n\nconst GATEWAY_CONNECT_TIMEOUT = 5000;\n\nconst DEFAULT_ADDR = {\n    hostname: window.origin,\n    path: '/vc',\n};\n\nexport function voiceApiConnect(addr = DEFAULT_ADDR, language = 'Kor', cb) {\n    return new Promise((resolve, reject) => {\n        const client = io(addr.hostname, {\n            path: addr.path,\n            query: `language=${language}`,\n            secure: true,\n            reconnect: true,\n            rejectUnauthorized: false,\n            timeout: GATEWAY_CONNECT_TIMEOUT,\n            transports: ['websocket', 'polling'],\n        });\n\n        client.on('open', () => {\n            console.log('NSASR Voice Server Connected');\n            resolve(client);\n        });\n\n        client.on('connect', () => {\n            console.log('socket connected');\n        });\n\n        client.on('disconnect', () => {\n            console.log('closed');\n            Entry.engine.hideAllAudioPanel();\n            audioUtils.isRecording = false;\n        });\n\n        let isFirst = true;\n        client.on('connect_error', (error) => {\n            if (isFirst) {\n                isFirst = false;\n                client.io.opts.transports = ['polling', 'websocket'];\n            } else {\n                console.error('connect_error', error);\n                Entry.engine.hideAllAudioPanel();\n                audioUtils.isRecording = false;\n                reject(error);\n            }\n        });\n        client.on('connect_timeout', (timeout) => {\n            console.error('connect_timeout', timeout);\n            Entry.engine.hideAllAudioPanel();\n            audioUtils.isRecording = false;\n            reject(timeout);\n        });\n        client.on('error', (error) => {\n            console.error('error', error);\n            Entry.engine.hideAllAudioPanel();\n            audioUtils.isRecording = false;\n            reject(error);\n        });\n    });\n}\n"
  },
  {
    "path": "src/util/audioUtils.js",
    "content": "/**\n * 언더바가 붙은 함수 및 변수를 외부에서 쓰지 마세요\n * @author extracold1209, wodnjs6512\n */\n\nconst { voiceApiConnect } = require('./audioSocket');\nconst toWav = require('audiobuffer-to-wav');\n\nconst STATUS_CODE = {\n    CONNECTED: 'CONNECTED',\n    NOT_RECOGNIZED: 'NOT_RECOGNIZED',\n    START_RECOGNIZE: 'START_RECOGNIZE',\n    END_POINT_DETECTED: 'END_POINT_DETECTED',\n};\n\nconst getVoiceServerAddress = () => ({\n    hostname: Entry.baseUrl,\n    path: '/vc',\n});\n\nconst DESIRED_SAMPLE_RATE = 16000;\n\nclass AudioUtils {\n    isTimedRecord = false;\n    timedResult = [];\n    stopCallback = null;\n\n    get currentVolume() {\n        return this._currentVolume;\n    }\n\n    constructor() {\n        this.isInitialized = false; // 유저 인풋 연결 확인\n        this.isRecording = false;\n        this._userMediaStream = undefined;\n        this._mediaRecorder = undefined;\n        this._currentVolume = -1;\n        this._audioChunks = [];\n        this.result = null;\n        this.startedRecording = false;\n        this.audioInputList = [];\n    }\n\n    async getMediaStream() {\n        try {\n            return await navigator.mediaDevices.getUserMedia({\n                audio: {\n                    autoGainControl: true,\n                    noiseSuppression: true,\n                    echoCancellation: true,\n                },\n            });\n        } catch (err) {\n            // is MIC present in browser\n            this.isRecording = false;\n            this.stopRecord();\n            throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                Lang.Workspace.check_microphone_error,\n            ]);\n        }\n    }\n\n    incompatBrowserChecker() {\n        // IE/safari CHECKER\n        if (!this.isAudioSupport) {\n            this.isAudioSupport = this._isBrowserSupportAudio(); // 브라우저 지원 확인\n            if (!this.isAudioSupport) {\n                this.isRecording = false;\n                this.stopRecord();\n                throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                    Lang.Workspace.check_microphone_error,\n                ]);\n            }\n        }\n    }\n\n    async initialize() {\n        if (this.isInitialized) {\n            return;\n        }\n        this.incompatBrowserChecker();\n        const mediaStream = await this.getMediaStream();\n        try {\n            Entry.addEventListener('beforeStop', () => {\n                this.improperStop();\n            });\n\n            const inputList = await navigator.mediaDevices.enumerateDevices();\n            this.audioInputList = inputList\n                .filter((input) => input.kind === 'audioinput')\n                .map((item) => [item.label, item.deviceId]);\n\n            if (!window.AudioContext) {\n                if (window.webkitAudioContext) {\n                    window.AudioContext = window.webkitAudioContext;\n                }\n            }\n            const audioContext = new window.AudioContext();\n            const streamSrc = audioContext.createMediaStreamSource(mediaStream);\n            const analyserNode = audioContext.createAnalyser();\n            // const reducerNode = new window.audio.NoiseReducer(0.5, 5);\n            const gainNode = audioContext.createGain();\n            gainNode.gain.value = 1.8;\n\n            const highpassFilter = audioContext.createBiquadFilter();\n            highpassFilter.type = 'highpass';\n            highpassFilter.frequency.value = 150;\n            highpassFilter.Q.value = 1;\n            highpassFilter.detune.value = 1;\n\n            analyserNode.fftSize = 4096;\n            analyserNode.smoothingTimeConstant = 0.0;\n            analyserNode.minDecibels = -80;\n            analyserNode.maxDecibels = -40;\n\n            const scriptNode = audioContext.createScriptProcessor(512, 1, 1);\n            const streamDest = audioContext.createMediaStreamDestination();\n            const mediaRecorder = new MediaRecorder(streamDest.stream);\n            // 순서대로 노드 커넥션을 맺는다.\n            this._connectNodes(streamSrc, analyserNode, scriptNode, streamDest);\n            scriptNode.onaudioprocess = this._handleScriptProcess(analyserNode);\n\n            this._audioContext = audioContext;\n            this._userMediaStream = mediaStream;\n            this._mediaRecorder = mediaRecorder;\n\n            // 음성 인식 api 를 사용하기 위함\n            // 음성 인식은 websocket 을 통해서 WAV로 전송하게 되어있음.\n            // 첫번째 파라미터는 프로토콜을 제외한 hostname+port 조합\n            // ex)'localhost:4001'\n            this.isInitialized = true;\n            return;\n        } catch (e) {\n            console.error('error occurred while init audio input', e);\n            this.isInitialized = false;\n            return;\n        }\n    }\n\n    improperStop() {\n        this.stopRecord();\n        if (this.resolveFunc) {\n            this.resolveFunc('');\n        }\n    }\n\n    startRecord(recordMilliSecond, language) {\n        return new Promise(async (resolve, reject) => {\n            this.resolveFunc = resolve;\n            if (!this.isInitialized) {\n                console.log('audio not initialized');\n                resolve(0);\n                return;\n            }\n            // this.isRecording = true;\n            if (this._audioContext.state === 'suspended') {\n                this.isInitialized = false;\n                await this.initialize();\n            }\n\n            try {\n                this._socketClient = await voiceApiConnect(\n                    getVoiceServerAddress(),\n                    language,\n                    (data) => {\n                        this.result = data;\n                    }\n                );\n            } catch (err) {\n                console.log(err);\n            }\n\n            this._audioChunks = [];\n\n            this._stopMediaRecorder();\n            this._mediaRecorder.start();\n            this.startedRecording = true;\n            Entry.engine.toggleAudioShadePanel();\n            this._socketClient.on('disconnect', () => {\n                resolve('-');\n            });\n            this._socketClient.on('message', (e) => {\n                switch (e) {\n                    case STATUS_CODE.CONNECTED:\n                        break;\n                    case STATUS_CODE.END_POINT_DETECTED:\n                        Entry.dispatchEvent('audioRecordProcessing');\n                        if (this.startedRecording) {\n                            Entry.engine.toggleAudioProgressPanel();\n                        }\n                        this.startedRecording = false;\n                        break;\n                    case STATUS_CODE.NOT_RECOGNIZED:\n                        this.stopCallback = null;\n                        resolve('-');\n                        this.stopRecord();\n                        break;\n                    default: {\n                        const parsed = JSON.parse(e);\n                        const isArray = Array.isArray(parsed);\n                        if (isArray) {\n                            this.stopCallback = null;\n                            resolve(parsed[0]);\n                            this.stopRecord();\n                        } else {\n                            resolve('-');\n                        }\n                        break;\n                    }\n                }\n            });\n            this._properStopCall = setTimeout(this.stopRecord, recordMilliSecond);\n            this.stopCallback = () => {\n                resolve(0);\n            };\n        });\n    }\n\n    startTimedRecord(recordMilliSecond, language) {\n        return new Promise(async (resolve, reject) => {\n            this.isTimedRecord = true;\n            this.timedResult = [];\n            this.resolveFunc = resolve;\n            if (!this.isInitialized) {\n                console.log('audio not initialized');\n                resolve(0);\n                return;\n            }\n            // this.isRecording = true;\n            if (this._audioContext.state === 'suspended') {\n                this.isInitialized = false;\n                await this.initialize();\n            }\n\n            try {\n                this._socketClient = await voiceApiConnect(\n                    getVoiceServerAddress(),\n                    language,\n                    (data) => {\n                        this.result = data;\n                    }\n                );\n            } catch (err) {\n                console.log(err);\n            }\n\n            this._audioChunks = [];\n\n            this._stopMediaRecorder();\n            this._mediaRecorder.start();\n            this.startedRecording = true;\n            Entry.engine.toggleAudioShadePanel();\n\n            this._properStopCall = setTimeout(async () => {\n                try {\n                    this.isTimedRecord = false;\n                    Entry.dispatchEvent('audioRecordProcessing');\n                    if (this.startedRecording) {\n                        Entry.engine.toggleAudioProgressPanel();\n                    }\n                    this.startedRecording = false;\n                    const result = await this.sendBuffer(this.timedResult, language);\n                    this.stopRecord();\n                    resolve(result);\n                } catch (e) {\n                    resolve(0);\n                }\n            }, recordMilliSecond);\n\n            this.stopCallback = () => {\n                resolve(0);\n            };\n        });\n    }\n\n    async sendBuffer(buffers, language) {\n        return new Promise(async (resolve, reject) => {\n            this._socketClient.on('disconnect', () => {\n                resolve('-');\n            });\n            this._socketClient.on('message', (e) => {\n                switch (e) {\n                    case STATUS_CODE.CONNECTED:\n                        break;\n                    case STATUS_CODE.END_POINT_DETECTED:\n                        break;\n                    case STATUS_CODE.NOT_RECOGNIZED:\n                        this.stopCallback = null;\n                        resolve('-');\n                        this.stopRecord();\n                        break;\n                    default: {\n                        const parsed = JSON.parse(e);\n                        const isArray = Array.isArray(parsed);\n                        if (isArray) {\n                            this.stopCallback = null;\n                            resolve(parsed[0]);\n                            this.stopRecord();\n                        } else {\n                            resolve('-');\n                        }\n                        break;\n                    }\n                }\n            });\n\n            if (this._socketClient && this._socketClient.readyState === this._socketClient.OPEN) {\n                // socket.io로 서버 전송\n                buffers.forEach((buffer) => {\n                    this._socketClient.send(toWav(buffer));\n                });\n            }\n        });\n    }\n\n    _stopMediaRecorder() {\n        if (this._mediaRecorder.state == 'recording' || this._mediaRecorder.state === 'paused') {\n            this._mediaRecorder.stop();\n        }\n    }\n\n    /**\n     * 녹음을 종료한다.\n     */\n    stopRecord() {\n        if (this._socketClient) {\n            this._socketClient.disconnect();\n        }\n        if (!this.isInitialized || !this.isRecording) {\n            return;\n        }\n        Entry.dispatchEvent('audioRecordProcessing');\n        if (this.startedRecording) {\n            Entry.engine.toggleAudioProgressPanel();\n        }\n        this.startedRecording = false;\n\n        this._mediaRecorder.onstop = null;\n\n        this._stopMediaRecorder();\n        this._audioContext.suspend();\n        this?.stream?.getTracks().forEach((track) => {\n            track.stop();\n        });\n        clearTimeout(this._properStopCall);\n        if (this.stopCallback) {\n            this.stopCallback();\n        }\n        // this.isRecording = false;\n    }\n\n    isAudioConnected() {\n        if (!this._isBrowserSupportAudio() || !this.isInitialized || !this._userMediaStream) {\n            return false;\n        }\n        const tracks = this._userMediaStream.getAudioTracks();\n        return tracks && tracks.some((track) => track.readyState === 'live');\n    }\n\n    _connectNodes(...connectableNodes) {\n        for (let i = 0; i < connectableNodes.length - 1; i++) {\n            if (connectableNodes[i].connect) {\n                connectableNodes[i].connect(connectableNodes[i + 1]);\n            } else {\n                throw new Error('you can not connect node');\n            }\n        }\n    }\n\n    _isBrowserSupportAudio() {\n        if (\n            !navigator.mediaDevices ||\n            !navigator.mediaDevices.getUserMedia ||\n            !window.MediaRecorder\n        ) {\n            return false;\n        }\n        return true;\n    }\n\n    _handleScriptProcess = (analyserNode) => (audioProcessingEvent) => {\n        const array = new Uint8Array(analyserNode.frequencyBinCount);\n        analyserNode.getByteFrequencyData(array);\n\n        // 현재 input 의 볼륨세기\n        this._currentVolume = array.reduce((total, data) => total + data, 0) / array.length;\n\n        // 볼륨 변형 없이 그대로 통과\n        const { inputBuffer, outputBuffer } = audioProcessingEvent;\n        for (let channel = 0; channel < outputBuffer.numberOfChannels; channel++) {\n            const inputData = inputBuffer.getChannelData(channel);\n            const outputData = outputBuffer.getChannelData(channel);\n            for (let sample = 0; sample < inputBuffer.length; sample++) {\n                outputData[sample] = inputData[sample];\n            }\n        }\n        if (!this.isRecording) {\n            return;\n        }\n\n        ///// RESAMPLE\n        // offline context 로 44100hz 에서 16000hz로 resample\n        const offlineCtx = new OfflineAudioContext(\n            outputBuffer.numberOfChannels,\n            outputBuffer.duration * DESIRED_SAMPLE_RATE,\n            DESIRED_SAMPLE_RATE\n        );\n        const cloneBuffer = offlineCtx.createBuffer(\n            outputBuffer.numberOfChannels,\n            outputBuffer.length,\n            outputBuffer.sampleRate\n        );\n        // Copy the source data into the offline AudioBuffer\n        for (let channel = 0; channel < outputBuffer.numberOfChannels; channel++) {\n            cloneBuffer.copyToChannel(outputBuffer.getChannelData(channel), channel);\n        }\n        // Play it from the beginning.\n        const source = offlineCtx.createBufferSource();\n        source.buffer = cloneBuffer;\n        source.connect(offlineCtx.destination);\n        offlineCtx.oncomplete = (e) => {\n            if (!this.isRecording) {\n                return;\n            }\n\n            if (this.isTimedRecord) {\n                this.timedResult.push(e.renderedBuffer);\n            } else if (\n                this._socketClient &&\n                this._socketClient.readyState === this._socketClient.OPEN\n            ) {\n                // socket.io로 서버 전송\n                this._socketClient.send(toWav(e.renderedBuffer));\n            }\n        };\n        offlineCtx.startRendering();\n        source.start(0);\n    };\n}\n\n//Entry 네임스페이스에는 존재하지 않으므로 외부에서 사용할 수 없다.\nexport default new AudioUtils();\n"
  },
  {
    "path": "src/util/binPacking.js",
    "content": "import _cloneDeep from 'lodash/cloneDeep';\n\nclass BinPacking {\n    constructor(width, height) {\n        this.MAX_WIDTH = width;\n        this.MAX_HEIGHT = height;\n        this.itemList = new Map();\n        this.spaceList = new Set();\n        this.spaceList.add({ x: 0, y: 0, w: width, h: height });\n    }\n\n    reset() {\n        this.spaceList = new Set();\n        this.spaceList.add({ x: 0, y: 0, w: this.MAX_WIDTH, h: this.MAX_HEIGHT });\n    }\n\n    isIntersect(r1, r2) {\n        if (r1.x >= r2.x + r2.w) {\n            return false;\n        }\n        if (r1.x + r1.w <= r2.x) {\n            return false;\n        }\n        if (r1.y >= r2.y + r2.h) {\n            return false;\n        }\n        if (r1.y + r1.h <= r2.y) {\n            return false;\n        }\n        return true;\n    }\n\n    isInclude(r1, r2) {\n        if (\n            r2.x >= r1.x &&\n            r2.x + r2.w <= r1.x + r1.w &&\n            r2.y >= r1.y &&\n            r2.y + r2.h <= r1.y + r1.h\n        ) {\n            return true;\n        }\n        return false;\n    }\n\n    getIntersection(r1, r2) {\n        const rect = {};\n        rect.x = Math.max(r1.x, r2.x);\n        rect.y = Math.max(r1.y, r2.y);\n        rect.w = Math.min(r1.x + r1.w, r2.x + r2.w) - rect.x;\n        rect.h = Math.min(r1.y + r1.h, r2.y + r2.h) - rect.y;\n        return rect;\n    }\n\n    check(item) {\n        let isFound = false;\n\n        let findSpace;\n        for (const space of this.spaceList) {\n            findSpace = space;\n            if (item.x || item.y) {\n                const { x = 0, y = 0, w, h } = item;\n                if (x >= space.x && y >= space.y && w <= space.w && h <= space.h) {\n                    isFound = true;\n                    break;\n                }\n            } else if (item.w <= space.w && item.h <= space.h) {\n                isFound = true;\n                break;\n            }\n        }\n\n        if (!item.x && !item.y) {\n            item.x = findSpace.x;\n            item.y = findSpace.y;\n        }\n        if (isFound) {\n            const newList = new Set();\n            for (const sp of this.spaceList) {\n                if (this.isInclude(item, sp)) {\n                    this.spaceList.delete(sp);\n                    continue;\n                }\n                if (this.isIntersect(item, sp)) {\n                    const rt = {\n                        x: sp.x,\n                        y: sp.y,\n                        w: sp.w,\n                        h: item.y - sp.y,\n                    };\n                    const rb = {\n                        x: sp.x,\n                        y: item.y + item.h,\n                        w: sp.w,\n                        h: sp.y + sp.h - (item.y + item.h),\n                    };\n                    const rl = {\n                        x: sp.x,\n                        y: sp.y,\n                        w: item.x - sp.x,\n                        h: sp.h,\n                    };\n                    const rr = {\n                        x: item.x + item.w,\n                        y: sp.y,\n                        w: sp.x + sp.w - (item.x + item.w),\n                        h: sp.h,\n                    };\n\n                    if (rt.w > 0 && rt.h > 0) {\n                        newList.add(rt);\n                    }\n                    if (rl.w > 0 && rl.h > 0) {\n                        newList.add(rl);\n                    }\n                    if (rb.w > 0 && rb.h > 0) {\n                        newList.add(rb);\n                    }\n                    if (rr.w > 0 && rr.h > 0) {\n                        newList.add(rr);\n                    }\n\n                    this.spaceList.delete(sp);\n                    continue;\n                }\n            }\n\n            //remove invalidate spaces\n            for (const s1 of this.spaceList) {\n                for (const s2 of newList) {\n                    if (s1 != s2 && this.isInclude(s1, s2)) {\n                        newList.delete(s2);\n                        continue;\n                    }\n                }\n            }\n\n            for (const s1 of newList) {\n                for (const s2 of newList) {\n                    if (s1 != s2 && this.isInclude(s1, s2)) {\n                        newList.delete(s2);\n                        continue;\n                    }\n                }\n            }\n\n            if (newList.size) {\n                for (const list of newList) {\n                    this.spaceList.add(list);\n                }\n            }\n            this.spaceList = new Set(\n                [...this.spaceList].sort((a, b) => {\n                    if (a.x < b.x) {\n                        return -1;\n                    } else if (a.x == b.x && a.y < b.y) {\n                        return -1;\n                    } else {\n                        return 1;\n                    }\n                })\n            );\n        } else {\n            item.x = Math.floor(Math.random() * (this.MAX_WIDTH - 30));\n            item.y = Math.floor(Math.random() * (this.MAX_HEIGHT - 30));\n        }\n\n        return item;\n    }\n\n    add(id, x = 0, y = 0, w = 100, h = 100) {\n        this.reset();\n        for (const [id, item] of this.itemList) {\n            this.check(_cloneDeep(item));\n        }\n        const item = this.check({ x, y, w, h });\n        this.itemList.set(id, item);\n        return item;\n    }\n\n    replace(id, x = 0, y = 0, width, height) {\n        const item = this.itemList.get(id) || {};\n        item.x = x + 230;\n        item.y = y + 105;\n        item.w = width;\n        item.h = height;\n    }\n\n    remove(id) {\n        this.itemList.delete(id);\n    }\n}\n\nexport default BinPacking;\n"
  },
  {
    "path": "src/util/block_driver.js",
    "content": "'use strict';\n\nEntry.BlockDriver = class BlockDriver {\n    convert() {\n        const time = new Date();\n        for (const blockType in Entry.block) {\n            if (typeof Entry.block[blockType] === 'function') {\n                this._convertBlock(blockType);\n            }\n        }\n        console.log(new Date().getTime() - time.getTime());\n    }\n\n    _convertBlock(blockType) {\n        const blocklyInfo = Blockly.Blocks[blockType];\n        const blockInfo = EntryStatic.blockInfo[blockType];\n        let className;\n        let isNotFor;\n        if (blockInfo) {\n            className = blockInfo.class;\n            isNotFor = blockInfo.isNotFor;\n\n            //add block definition by xml to json\n            let xml = blockInfo.xml;\n            if (xml) {\n                xml = $.parseXML(xml);\n                const child = xml.childNodes[0];\n                var def = generateBlockDef(child);\n            }\n        }\n        const mockup = new Entry.BlockMockup(blocklyInfo, def, blockType);\n\n        const blockObject = mockup.toJSON();\n        blockObject.class = className;\n        blockObject.isNotFor = isNotFor;\n\n        if (_.isEmpty(blockObject.paramsKeyMap)) {\n            delete blockObject.paramsKeyMap;\n        }\n        if (_.isEmpty(blockObject.statementsKeyMap)) {\n            delete blockObject.statementsKeyMap;\n        }\n\n        blockObject.func = Entry.block[blockType];\n\n        const PRIMITIVES = [\n            'NUMBER',\n            'TRUE',\n            'FALSE',\n            'TEXT',\n            'FUNCTION_PARAM_BOOLEAN',\n            'FUNCTION_PARAM_STRING',\n            'TRUE_UN',\n        ];\n\n        if (PRIMITIVES.indexOf(blockType.toUpperCase()) > -1) {\n            blockObject.isPrimitive = true;\n        }\n        Entry.block[blockType] = blockObject;\n\n        function generateBlockDef(block) {\n            const def = {\n                type: block.getAttribute('type'),\n                index: {},\n            };\n\n            const children = $(block).children();\n            if (!children) {\n                return def;\n            }\n            for (let i = 0; i < children.length; i++) {\n                const child = children[i];\n                const tagName = child.tagName;\n                const subChild = $(child).children()[0];\n                const key = child.getAttribute('name');\n                if (tagName === 'value') {\n                    if (subChild.nodeName == 'block') {\n                        if (!def.params) {\n                            def.params = [];\n                        }\n                        def.params.push(generateBlockDef(subChild));\n                        def.index[key] = def.params.length - 1;\n                    }\n                } else if (tagName === 'field') {\n                    if (!def.params) {\n                        def.params = [];\n                    }\n                    def.params.push(child.textContent);\n                    def.index[key] = def.params.length - 1;\n                }\n            }\n            return def;\n        }\n    }\n};\n\nEntry.BlockMockup = class BlockMockup {\n    constructor(blocklyInfo, def, blockType) {\n        this.templates = [];\n        this.params = [];\n        this.statements = [];\n        this.color = '';\n        this.isPrev = false;\n        this.isNext = false;\n        this.output = false;\n        this.fieldCount = 0;\n        this.events = {};\n        this.def = def || {};\n        this.paramsKeyMap = {};\n        this.statementsKeyMap = {};\n        this.definition = {\n            params: [],\n            type: this.def.type,\n        };\n\n        this.simulate(blocklyInfo);\n        this.def = this.definition;\n    }\n\n    simulate(blocklyInfo) {\n        if (blocklyInfo.sensorList) {\n            this.sensorList = blocklyInfo.sensorList;\n        }\n        if (blocklyInfo.portList) {\n            this.portList = blocklyInfo.portList;\n        }\n        blocklyInfo.init.call(this);\n        if (blocklyInfo.whenAdd) {\n            if (!this.events.blockViewAdd) {\n                this.events.blockViewAdd = [];\n            }\n            this.events.blockViewAdd.push(blocklyInfo.whenAdd);\n        }\n\n        if (blocklyInfo.whenRemove) {\n            if (!this.events.blockViewDestroy) {\n                this.events.blockViewDestroy = [];\n            }\n            this.events.blockViewDestroy.push(blocklyInfo.whenRemove);\n        }\n    }\n\n    toJSON() {\n        let skeleton = '';\n        if (this.output) {\n            if (this.output === 'Boolean') {\n                skeleton = 'basic_boolean_field';\n            } else {\n                skeleton = 'basic_string_field';\n            }\n        } else if (!this.isPrev && this.isNext) {\n            skeleton = 'basic_event';\n        } else if (this.statements.length == 1) {\n            skeleton = 'basic_loop';\n        } else if (this.statements.length == 2) {\n            skeleton = 'basic_double_loop';\n        } else if (this.isPrev && this.isNext) {\n            skeleton = 'basic';\n        } else if (this.isPrev && !this.isNext) {\n            skeleton = 'basic_without_next';\n        }\n\n        const def = this.def;\n        removeIndex(def);\n\n        function removeIndex(def) {\n            if (!def) {\n                return;\n            }\n            const params = def.params;\n            if (!params) {\n                return;\n            }\n            for (let i = 0; i < params.length; i++) {\n                const param = params[i];\n                if (!param) {\n                    continue;\n                }\n                delete param.index;\n                removeIndex(param);\n            }\n        }\n\n        const reg = /dummy_/im;\n        for (var key in this.paramsKeyMap) {\n            if (reg.test(key)) {\n                delete this.paramsKeyMap[key];\n            }\n        }\n\n        for (key in this.statementsKeyMap) {\n            if (reg.test(key)) {\n                delete this.statementsKeyMap[key];\n            }\n        }\n\n        return {\n            color: this.color,\n            skeleton,\n            statements: this.statements,\n            template: this.templates.filter((p) => typeof p === 'string').join(' '),\n            params: this.params,\n            events: this.events,\n            def: this.def,\n            paramsKeyMap: this.paramsKeyMap,\n            statementsKeyMap: this.statementsKeyMap,\n        };\n    }\n\n    appendDummyInput() {\n        return this;\n    }\n\n    appendValueInput(key) {\n        // field block\n        if (this.def && this.def.index) {\n            if (this.def.index[key] !== undefined) {\n                this.definition.params.push(this.def.params[this.def.index[key]]);\n            } else {\n                this.definition.params.push(null);\n            }\n        }\n        this.params.push({\n            type: 'Block',\n            accept: 'string',\n        });\n\n        this._addToParamsKeyMap(key);\n        this.templates.push(this.getFieldCount());\n        return this;\n    }\n\n    appendStatementInput(key) {\n        const statement = {\n            accept: 'basic',\n        };\n        this._addToStatementsKeyMap(key);\n        this.statements.push(statement);\n    }\n\n    setCheck(accept) {\n        //add value\n        const params = this.params;\n        if (accept === 'Boolean') {\n            params[params.length - 1].accept = 'boolean';\n        }\n    }\n\n    appendField(field, opt) {\n        if (!field) {\n            return this;\n        }\n        if (typeof field === 'string' && field.length > 0) {\n            if (opt) {\n                field = {\n                    type: 'Text',\n                    text: field,\n                    color: opt,\n                };\n                this.params.push(field);\n                this._addToParamsKeyMap();\n                this.templates.push(this.getFieldCount());\n                if (this.def && this.def.index && this.def.index[opt] !== undefined) {\n                    this.definition.params.push(this.def.params[this.def.index[opt]]);\n                } else {\n                    this.definition.params.push(undefined);\n                }\n            } else {\n                this.templates.push(field);\n            }\n        } else {\n            if (field.constructor == Blockly.FieldIcon) {\n                if (field.type === 'start') {\n                    this.params.push({\n                        type: 'Indicator',\n                        img: field.src_,\n                        size: 17,\n                        position: {\n                            x: 0,\n                            y: -2,\n                        },\n                    });\n                } else {\n                    this.params.push({\n                        type: 'Indicator',\n                        img: field.src_,\n                        size: 12,\n                    });\n                }\n                this._addToParamsKeyMap();\n                this.templates.push(this.getFieldCount());\n                if (this.definition) {\n                    this.definition.params.push(null);\n                }\n            } else if (field.constructor == Blockly.FieldDropdown) {\n                this.params.push({\n                    type: 'Dropdown',\n                    options: field.menuGenerator_,\n                    value: field.menuGenerator_[0][1],\n                    fontSize: 11,\n                });\n                this._addToParamsKeyMap(opt);\n\n                this.templates.push(this.getFieldCount());\n                if (this.def && this.def.index && this.def.index[opt] !== undefined) {\n                    this.definition.params.push(this.def.params[this.def.index[opt]]);\n                } else {\n                    this.definition.params.push(undefined);\n                }\n            } else if (field.constructor == Blockly.FieldDropdownDynamic) {\n                this.params.push({\n                    type: 'DropdownDynamic',\n                    value: null,\n                    menuName: field.menuName_,\n                    fontSize: 11,\n                });\n                this.templates.push(this.getFieldCount());\n                if (this.def && this.def.index && this.def.index[opt] !== undefined) {\n                    this.definition.params.push(this.def.params[this.def.index[opt]]);\n                } else {\n                    this.definition.params.push(undefined);\n                }\n                this._addToParamsKeyMap(opt);\n            } else if (field.constructor == Blockly.FieldTextInput) {\n                this.params.push({\n                    type: 'TextInput',\n                    value: 10,\n                });\n                this.templates.push(this.getFieldCount());\n                this._addToParamsKeyMap(opt);\n            } else if (field.constructor == Blockly.FieldAngle) {\n                this.params.push({\n                    type: 'Angle',\n                });\n                this.templates.push(this.getFieldCount());\n                if (this.def && this.def.index && this.def.index[opt] !== undefined) {\n                    this.definition.params.push(this.def.params[this.def.index[opt]]);\n                } else {\n                    this.definition.params.push(null);\n                }\n                this._addToParamsKeyMap(opt);\n            } else if (field.constructor == Blockly.FieldKeydownInput) {\n                this.params.push({\n                    type: 'Keyboard',\n                    value: 81,\n                });\n                this.templates.push(this.getFieldCount());\n                if (this.def.index[opt] !== undefined) {\n                    this.definition.params.push(this.def.params[this.def.index[opt]]);\n                } else {\n                    this.definition.params.push(undefined);\n                }\n                this._addToParamsKeyMap(opt);\n            } else if (field.constructor == Blockly.FieldColour) {\n                this.params.push({\n                    type: 'Color',\n                });\n                this.templates.push(this.getFieldCount());\n                this._addToParamsKeyMap(opt);\n            } else {\n                console.log('else', field);\n                //console.log('else', field);\n            }\n        }\n        return this;\n    }\n\n    setColour(color) {\n        this.color = color;\n    }\n\n    setInputsInline() {}\n\n    setOutput(bool, type) {\n        if (!bool) {\n            return;\n        }\n        this.output = type;\n    }\n\n    setPreviousStatement(bool) {\n        this.isPrev = bool;\n    }\n\n    setNextStatement(bool) {\n        this.isNext = bool;\n    }\n\n    setEditable(bool) {\n        // Not implemented\n    }\n\n    getFieldCount() {\n        this.fieldCount++;\n        return `%${this.fieldCount}`;\n    }\n\n    _addToParamsKeyMap(key) {\n        key = key ? key : `dummy_${Entry.Utils.generateId()}`;\n        const map = this.paramsKeyMap;\n        map[key] = Object.keys(map).length;\n    }\n\n    _addToStatementsKeyMap(key) {\n        key = key ? key : `dummy_${Entry.Utils.generateId()}`;\n        const map = this.statementsKeyMap;\n        map[key] = Object.keys(map).length;\n    }\n};\n"
  },
  {
    "path": "src/util/common.js",
    "content": "import fetch from 'isomorphic-fetch';\nimport _isNaN from 'lodash/isNaN';\nimport _toNumber from 'lodash/toNumber';\nimport _isNumber from 'lodash/isNumber';\nimport _cuid from 'cuid';\nimport _uid from 'uid';\n\nconst _memoize = require('lodash/memoize');\nconst _assign = require('lodash/assign');\n\nconst Common = {\n    toQueryString: (obj) =>\n        encodeURI(\n            Object.keys(obj)\n                .map((k) => `${k}=${obj[k]}`)\n                .join('&')\n        ),\n    callApi: _memoize(async (key, opt, header) => {\n        const options = _assign(\n            {\n                method: 'GET',\n                headers: {\n                    Accept: 'application/json',\n                    'Content-Type': 'application/json',\n                    ...header,\n                },\n            },\n            opt\n        );\n        if (typeof options.data !== 'string') {\n            options.body = JSON.stringify(options.data);\n        }\n        const queryString = options.params ? `?${Common.toQueryString(options.params)}` : '';\n        const fetchPromise = fetch(`${Entry.baseUrl || ''}${options.url}${queryString}`, options);\n        const timeoutPromise = new Promise((_, reject) =>\n            setTimeout(() => reject(new Error('Request timeout')), 3000)\n        );\n        try {\n            const response = await Promise.race([fetchPromise, timeoutPromise]);\n            if (response.status >= 400) {\n                Common.callApi.cache = new _memoize.Cache();\n                throw new Error(response);\n            }\n            const data = await response.json();\n            return { data };\n        } catch (error) {\n            Common.callApi.cache = new _memoize.Cache();\n            throw error;\n        }\n    }),\n    toNumber: (str) => {\n        if (typeof str === 'number') {\n            return str;\n        }\n        if (Array.isArray(str)) {\n            return str.map((x) => Common.toNumber(x));\n        }\n        if (!_isNaN(parseInt(str, 10)) && !_isNaN(_toNumber(str))) {\n            return _toNumber(str);\n        }\n        return str;\n    },\n    generateId() {\n        return _uid(8) + _cuid();\n    },\n};\n\nmodule.exports = Common;\n"
  },
  {
    "path": "src/util/contextmenu.js",
    "content": "'use strict';\n\nimport { ContextMenu } from '@entrylabs/tool';\nimport DomUtils from './domUtils';\n\nEntry.ContextMenu = {};\n\n(function(ctx) {\n    const ATTR_KEY = 'data-option-index';\n\n    ctx.visible = false;\n    ctx._hideEvent = null;\n\n    ctx.createDom = function() {\n        this.dom = Entry.Dom('div', {\n            id: 'entry-contextmenu',\n            parent: $('body'),\n        });\n\n        _bindEvent.call(this);\n    };\n\n    ctx.show = function(options, className, coordinate) {\n        if (!options.length) {\n            return;\n        }\n\n        this._options = options;\n\n        this.createDom();\n\n        if (this._hideEvent) {\n            this._hideEvent.destroy();\n        }\n\n        if (className !== undefined) {\n            this._className = className;\n            this.dom.addClass(className);\n        }\n\n        this._hideEvent = Entry.documentMousedown.attach(this, this.hide);\n        this.mouseCoordinate = coordinate || Entry.mouseCoordinate;\n        this.contextMenu = new ContextMenu({\n            type: 'contextMenu',\n            data: {\n                items: options,\n                coordinate: this.mouseCoordinate,\n                onOutsideClick: () => {\n                    this.hide();\n                },\n            },\n            container: this.dom[0],\n        });\n\n        this.visible = true;\n    };\n\n    ctx.position = function(pos) {\n        const dom = this.dom;\n        dom.css({\n            left: 0,\n            top: 0,\n        });\n        const width = dom.width();\n        const height = dom.height();\n\n        const win = $(window);\n        const winWidth = win.width();\n        const winHeight = win.height();\n\n        if (pos.x + width > winWidth) {\n            pos.x -= width + 3;\n        }\n        if (pos.y + height > winHeight) {\n            pos.y -= height;\n        }\n\n        dom.css({\n            left: pos.x,\n            top: pos.y,\n        });\n    };\n\n    ctx.hide = function() {\n        this.visible = false;\n        const dom = this.dom;\n        if (!dom) {\n            return;\n        }\n        dom.addClass('entryRemove');\n\n        if (this._className) {\n            dom.removeClass(this._className);\n            delete this._className;\n        }\n        if (this._hideEvent) {\n            this._hideEvent.destroy();\n            this._hideEvent = null;\n        }\n        if (this.contextMenu) {\n            this.contextMenu.isShow && this.contextMenu.hide();\n            this.contextMenu.remove();\n            this.contextMenu = null;\n        }\n    };\n\n    ctx.onContextmenu = function(target, callback) {\n        const longPressEvent = (e) => {\n            const startEvent = Entry.Utils.convertMouseEvent(e);\n            this.coordi = {\n                x: startEvent.clientX,\n                y: startEvent.clientY,\n            };\n\n            if (this.longTouchEvent) {\n                clearTimeout(this.longTouchEvent);\n                this.longTouchEvent = null;\n            }\n\n            this.longTouchEvent = setTimeout(() => {\n                callback(this.coordi);\n                this.longTouchEvent = undefined;\n            }, 900);\n        };\n\n        DomUtils.addEventListenerMultiple(\n            target,\n            'touchstart touchmove touchend mousemove mouseup mousedown',\n            (e) => {\n                switch (e.type) {\n                    case 'touchstart': {\n                        longPressEvent(e);\n                        break;\n                    }\n                    case 'mousemove':\n                    case 'touchmove': {\n                        const startEvent = Entry.Utils.convertMouseEvent(e);\n                        if (!this.coordi) {\n                            return;\n                        }\n                        const diff = Math.sqrt(\n                            Math.pow(startEvent.pageX - this.coordi.x, 2) +\n                                Math.pow(startEvent.pageY - this.coordi.y, 2)\n                        );\n\n                        if (diff > 5 && this.longTouchEvent) {\n                            clearTimeout(this.longTouchEvent);\n                            this.longTouchEvent = undefined;\n                        }\n                        break;\n                    }\n                    case 'mouseup':\n                    case 'touchend':\n                        // e.stopPropagation();\n                        if (this.longTouchEvent) {\n                            clearTimeout(this.longTouchEvent);\n                            this.longTouchEvent = undefined;\n                        }\n                        break;\n                    case 'mousedown':\n                        if (Entry.Utils.isRightButton(e)) {\n                            e.stopPropagation();\n\n                            this.coordi = {\n                                x: e.clientX,\n                                y: e.clientY,\n                            };\n\n                            clearTimeout(this.longTouchEvent);\n                            this.longTouchEvent = undefined;\n                            callback(this.coordi);\n                        }\n\n                        if (Entry.isMobile()) {\n                            longPressEvent(e);\n                        }\n                        break;\n                }\n            }\n        );\n    };\n\n    function _bindEvent() {\n        const that = this;\n        this.dom.on('mousedown touchstart', (e) => {\n            e.stopPropagation();\n        });\n\n        //event delegation\n        this.dom.on('mousedown touchstart', 'li', function(e) {\n            e.stopPropagation();\n            const options = that._options;\n\n            if (_.isEmpty(options)) {\n                return that.hide();\n            }\n\n            const { enable, callback } = options[this.getAttribute(ATTR_KEY)];\n\n            if (enable && callback) {\n                e.preventDefault();\n                that.hide();\n                callback(e);\n            }\n        });\n\n        Entry.Utils.disableContextmenu(this.dom);\n    }\n})(Entry.ContextMenu);\n"
  },
  {
    "path": "src/util/curtain.js",
    "content": "'use strict';\n\nEntry.Curtain = {};\n\n(function() {\n    this._visible = false;\n    this._doms = null;\n    this._targetDom = null;\n\n    this.init = function(isCloseable) {\n        this._createDom(isCloseable);\n    };\n\n    this._createDom = function(isCloseable) {\n        var $body = $('body');\n        var option = {\n            parent: $body,\n            class: 'entryCurtainElem entryRemove',\n        };\n\n        this._doms = {\n            top: Entry.Dom('div', option),\n            right: Entry.Dom('div', option),\n            bottom: Entry.Dom('div', option),\n            left: Entry.Dom('div', option),\n        };\n\n        if (isCloseable) {\n            this._closeBtn = Entry.Dom('button', {\n                parent: $body,\n                class: 'entryCurtainCloseBtn entryRemove',\n            });\n\n            this._closeBtn.on(\n                'click',\n                function() {\n                    this._closeBtn.off('click');\n                    entrylms.emit('ExitStudy');\n                }.bind(this)\n            );\n        }\n\n        for (var key in this._doms) {\n            var dom = this._doms[key];\n            dom.addClass(key);\n            dom.bind('mousedown', function(e) {\n                e.stopPropagation();\n                Entry.disposeEvent.notify(undefined, true);\n            });\n        }\n    };\n\n    this.show = function(datum) {\n        !this._doms && this._createDom();\n\n        if (datum instanceof Array) datum = Entry.getDom(datum);\n\n        datum = $(datum);\n        this._targetDom = datum;\n\n        this.align();\n\n        for (var key in this._doms) this._doms[key].removeClass('entryRemove');\n        this._closeBtn && this._closeBtn.removeClass('entryRemove');\n        this._visible = true;\n    };\n\n    this.align = function() {\n        var dom = this._targetDom;\n        if (!dom) return;\n        var $win = $(window);\n        var bodyRect = $('body')[0].getBoundingClientRect();\n        var bodyWidth = bodyRect.width;\n        var bodyHeight = bodyRect.height;\n\n        var winWidth = $win.width();\n        var winHeight = $win.height();\n\n        if (winWidth < Math.round(bodyWidth)) bodyWidth = winWidth;\n\n        if (winHeight < Math.round(bodyHeight)) bodyHeight = winHeight;\n\n        var doms = this._doms;\n\n        if (!dom.get(0)) return;\n\n        var rect = dom.get(0).getBoundingClientRect();\n\n        var topPos = Math.round(rect.top);\n        var rightPos = Math.round(rect.right);\n        var bottom = Math.round(rect.bottom);\n\n        doms.top.css({\n            height: topPos,\n        });\n        doms.left.css({\n            top: topPos,\n            right: bodyWidth - rightPos + rect.width,\n            bottom: Math.round(bodyHeight - bottom),\n        });\n        var leftLect = doms.left[0].getBoundingClientRect();\n        var bottomTop =\n            doms.top[0].getBoundingClientRect().height + leftLect.height;\n        doms.bottom.css({\n            top: bottomTop || bottom,\n            right: bodyWidth - rightPos,\n        });\n        doms.right.css({\n            top: topPos,\n            left: doms.bottom[0].getBoundingClientRect().width || rightPos,\n        });\n    };\n\n    this.hide = function() {\n        if (!this._doms) return;\n\n        for (var key in this._doms) this._doms[key].addClass('entryRemove');\n        this._closeBtn && this._closeBtn.addClass('entryRemove');\n        this._visible = false;\n        this._targetDom = null;\n    };\n\n    this.isVisible = function() {\n        return this._visible;\n    };\n\n    this.setVisible = function(value) {\n        this._visible = value;\n    };\n}.bind(Entry.Curtain)());\n"
  },
  {
    "path": "src/util/dataSource.ts",
    "content": "class DataStore<K, V> {\n    private dataMap: Map<K, V[]>;\n\n    constructor() {\n        this.dataMap = new Map<K, V[]>();\n    }\n\n    // 데이터 추가 메서드\n    add(key: K, value: V): void {\n        if (!this.dataMap.has(key)) {\n            this.dataMap.set(key, []);\n        }\n        this.dataMap.get(key)!.push(value); // \"!\"는 값이 null 또는 undefined가 아님을 나타냅니다.\n    }\n\n    // 특정 키에 대한 모든 데이터 가져오기\n    getAll(key: K): V[] {\n        return this.dataMap.get(key) || [];\n    }\n\n    // 특정 키를 제외한 모든 데이터 가져오기\n    getAllExcept(excludedKey: K): V[] {\n        let allData: V[] = [];\n        for (const [key, values] of this.dataMap.entries()) {\n            if (key !== excludedKey) {\n                allData = allData.concat(values);\n            }\n        }\n        return allData;\n    }\n\n    // 모든 키와 데이터 가져오기\n    getAllData(): [K, V[]][] {\n        return Array.from(this.dataMap.entries());\n    }\n\n    getAllValues(): V[] {\n        let allValues: V[] = [];\n        for (const values of this.dataMap.values()) {\n            allValues = allValues.concat(values);\n        }\n        return allValues;\n    }\n\n    // 특정 키의 데이터 삭제하기\n    delete(key: K): void {\n        this.dataMap.delete(key);\n    }\n\n    deleteItemByKeyAndValue(key: K, value: V): boolean {\n        const valuesForKey = this.dataMap.get(key);\n        if (!valuesForKey) {\n            return false;\n        }\n\n        const index = valuesForKey.indexOf(value);\n        if (index === -1) {\n            return false;\n        }\n\n        valuesForKey.splice(index, 1);\n\n        if (valuesForKey.length === 0) {\n            this.dataMap.delete(key);\n        }\n\n        return true;\n    }\n\n    // 모든 데이터 삭제하기\n    clear(): void {\n        this.dataMap.clear();\n    }\n}\n\nexport default DataStore;\n"
  },
  {
    "path": "src/util/destroyer/Destroyer.ts",
    "content": "export interface IDestroyer {\n    destroy(): void;\n}\n\nexport class Destroyer implements IDestroyer {\n    private _items: IDestroyer[] = [];\n\n    add(item: IDestroyer): void {\n        if (item == this) {\n            throw new Error(\"Can't add self.\");\n        }\n        this._items.push(item);\n    }\n\n    remove(item: IDestroyer): void {\n        const i = this._items.indexOf(item);\n        if (i == -1) {\n            return;\n        }\n        this._items.splice(i, 1);\n    }\n\n    destroy() {\n        const LEN = this._items.length;\n        for (let i = 0; i < LEN; i++) {\n            this._items[i].destroy();\n        }\n        this._items = [];\n    }\n}\n"
  },
  {
    "path": "src/util/domUtils.js",
    "content": "export default class {\n    /**\n     * 여러개의 이벤트를 바인딩한다.\n     * @param {HTMLElement} target\n     * @param {Array<string> | string} eventTypes string 인 경우 space split\n     * @param {function} eventHandler\n     * @param {AddEventListenerOptions?} option\n     */\n    static addEventListenerMultiple(target, eventTypes, eventHandler, option) {\n        if (!(target instanceof HTMLElement)) {\n            return;\n        }\n\n        if (typeof eventTypes === 'string') {\n            eventTypes.split(' ').forEach((eventType) => target.addEventListener(eventType, eventHandler, option));\n        } else if (eventTypes instanceof Array) {\n            eventTypes.forEach((eventType) => target.addEventListener(eventType, eventHandler, option));\n        }\n    }\n}\n"
  },
  {
    "path": "src/util/eventHandler.js",
    "content": "/**\n * Add event listener\n * @param {!string} eventName\n * @param {function} fn\n */\nEntry.addEventListener = function (eventName, fn) {\n    if (!this.events_) {\n        this.events_ = {};\n    }\n\n    if (!this.events_[eventName]) {\n        this.events_[eventName] = [];\n    }\n    if (fn instanceof Function) {\n        this.events_[eventName].push(fn);\n    }\n\n    return true;\n};\n\n/**\n * Dispatch event\n * @param {!string} eventName\n * @param {*} args\n */\nEntry.dispatchEvent = function (eventName, ...args) {\n    if (!this.events_) {\n        this.events_ = {};\n        return;\n    }\n\n    const events = this.events_[eventName];\n    if (_.isEmpty(events)) {\n        return;\n    }\n\n    events.forEach((func) => func.apply(window, args));\n};\n\n/**\n * Remove event listener\n * @param {!string} eventName\n * @param {function} fn\n */\nEntry.removeEventListener = function (eventName, fn) {\n    const events = this.events_[eventName];\n    if (_.isEmpty(events)) {\n        return;\n    }\n    this.events_[eventName] = events.filter((a) => fn !== a);\n};\n\n/**\n * Remove event listener\n * @param {!string} eventName\n */\nEntry.removeAllEventListener = function (eventName) {\n    if (!this.events_ || !this.events_[eventName]) {\n        return;\n    }\n    delete this.events_[eventName];\n};\n"
  },
  {
    "path": "src/util/extrablockUtils.js",
    "content": "const banAllBlocks = (playground, type) => {\n    const { mainWorkspace } = playground;\n    if (!mainWorkspace) {\n        return;\n    }\n\n    const blockMenu = _.result(mainWorkspace, 'blockMenu');\n    if (!blockMenu) {\n        return;\n    }\n\n    Object.values(type).forEach((block) => {\n        if (!block) {\n            console.log(type, block);\n            return;\n        }\n        blockMenu.banClass(block.name, true);\n        blockMenu.banClass(`${block.name}_legacy`, true);\n        blockMenu.banClass(`${block.name.toLowerCase()}`, true);\n    });\n};\n\nconst banBlocks = (blockNames = [], typedList, callback) => {\n    if (!blockNames.length) {\n        return;\n    }\n\n    const extraBlocks = Object.keys(typedList);\n    const extraBlockTypes = blockNames.filter((x) => extraBlocks.includes(x));\n    if (!extraBlockTypes.length) {\n        console.warn('not exist extra block', extraBlockTypes);\n        return;\n    }\n    const currentObjectId = Entry.playground.object.id;\n    Entry.do('selectObject', currentObjectId);\n    extraBlockTypes.forEach((type) => {\n        if (isActive(type, typedList)) {\n            const blocks = typedList[type].getBlocks();\n            Object.keys(blocks).forEach((blockType) => {\n                Entry.Utils.removeBlockByType(blockType);\n            });\n        }\n    });\n    Entry.do('selectObject', currentObjectId).isPass(true);\n    callback(extraBlockTypes);\n};\n\nconst isActive = (name, typedList) => {\n    const activeList = typedList[name];\n    if (!activeList) {\n        console.warn('not exist extra block', activeList);\n        return;\n    }\n    const blocks = activeList.getBlocks();\n    return Object.keys(blocks).some((blockName) => Entry.Utils.isUsedBlockType(blockName));\n};\n\nconst getExtras = (blockList, categoryFlag) => {\n    let resultList = [];\n    blockList.forEach((block) => {\n        const { _schema = {} } = block || {};\n        const { isFor, isNotFor = [] } = _schema;\n        const [key] = isNotFor;\n        if (key && isFor && isFor.indexOf(categoryFlag) >= 0) {\n            resultList = _.union(resultList, [key]);\n        }\n    });\n    return resultList;\n};\n\nmodule.exports = {\n    isActive,\n    banAllBlocks,\n    banBlocks,\n    getExtras,\n};\n"
  },
  {
    "path": "src/util/functions/showConsoleBanner.ts",
    "content": "/* eslint-disable max-len */\nexport default () => {\n    const green = 'color:#48D57C;font-weight:bold;';\n    const blue = 'color:#6B8DF5;font-weight:bold;';\n    const purple = 'color:#7B46E6;font-weight:bold;';\n    const yellow = 'color:#F5CE10;font-weight:bold;';\n    const red = 'color:#EF583C;font-weight:bold;';\n    const black = 'color:black;font-weight:bold;';\n\n    function isUA(userAgent: string) {\n        return navigator.userAgent.toLowerCase().indexOf(userAgent) > -1;\n    }\n\n    if (typeof console === 'object' && console.log && typeof console.log === 'function') {\n        if (isUA('chrome') && !isUA('edge')) {\n            const bannerText = `\n%c███████╗%c███╗   ██╗%c████████╗%c██████╗ %c██╗   ██╗ %c\n%c██╔════╝%c████╗  ██║%c╚══██╔══╝%c██╔══██╗%c╚██╗ ██╔╝ %c   _     \n%c█████╗  %c██╔██╗ ██║%c   ██║   %c██████╔╝%c ╚████╔╝  %c  |_|___ \n%c██╔══╝  %c██║╚██╗██║%c   ██║   %c██╔══██╗%c  ╚██╔╝   %c  | |_ -|\n%c███████╗%c██║ ╚████║%c   ██║   %c██║  ██║%c   ██║    %c _| |___|\n%c╚══════╝%c╚═╝  ╚═══╝%c   ╚═╝   %c╚═╝  ╚═╝%c   ╚═╝    %c|___|`;\n\n            console.log(\n                bannerText,\n                green,\n                blue,\n                purple,\n                yellow,\n                red,\n                black,\n                green,\n                blue,\n                purple,\n                yellow,\n                red,\n                black,\n                green,\n                blue,\n                purple,\n                yellow,\n                red,\n                black,\n                green,\n                blue,\n                purple,\n                yellow,\n                red,\n                black,\n                green,\n                blue,\n                purple,\n                yellow,\n                red,\n                black,\n                green,\n                blue,\n                purple,\n                yellow,\n                red,\n                black\n            );\n        } else {\n            console.log(`\n███████╗███╗   ██╗████████╗██████╗ ██╗   ██╗\n██╔════╝████╗  ██║╚══██╔══╝██╔══██╗╚██╗ ██╔╝    _\n█████╗  ██╔██╗ ██║   ██║   ██████╔╝ ╚████╔╝    |_|___\n██╔══╝  ██║╚██╗██║   ██║   ██╔══██╗  ╚██╔╝     | |_ -|\n███████╗██║ ╚████║   ██║   ██║  ██║   ██║     _| |___|\n╚══════╝╚═╝  ╚═══╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝    |___|`);\n        }\n    }\n};\n"
  },
  {
    "path": "src/util/fuzzy.js",
    "content": "'use strict';\n\n/*\n * Fuzzy\n * https://github.com/myork/fuzzy\n *\n * Copyright (c) 2012 Matt York\n * Licensed under the MIT license.\n */\n\n(function(u) {\n    var fuzzy = {};\n\n    u.fuzzy = fuzzy;\n\n    // Return all elements of `array` that have a fuzzy\n    // match against `pattern`.\n    fuzzy.simpleFilter = function(pattern, array) {\n        return array.filter(function(string) {\n            return fuzzy.test(pattern, string);\n        });\n    };\n\n    // Does `pattern` fuzzy match `string`?\n    fuzzy.test = function(pattern, string) {\n        return fuzzy.match(pattern, string) !== null;\n    };\n\n    // If `pattern` matches `string`, wrap each matching character\n    // in `opts.pre` and `opts.post`. If no match, return null\n    fuzzy.match = function(pattern, string, opts) {\n        opts = opts || {};\n        var patternIdx = 0,\n            result = [],\n            len = string.length,\n            totalScore = 0,\n            currScore = 0,\n            // prefix\n            pre = opts.pre || '',\n            // suffix\n            post = opts.post || '',\n            // String to compare against. This might be a lowercase version of the\n            // raw string\n            compareString =\n                (opts.caseSensitive && string) || string.toLowerCase(),\n            ch,\n            compareChar;\n\n        pattern = (opts.caseSensitive && pattern) || pattern.toLowerCase();\n\n        // For each character in the string, either add it to the result\n        // or wrap in template if it's the next string in the pattern\n        for (var idx = 0; idx < len; idx++) {\n            ch = string[idx];\n            if (compareString[idx] === opts.escapeLetter) {\n                break;\n            }\n            if (compareString[idx] === pattern[patternIdx]) {\n                ch = pre + ch + post;\n                patternIdx += 1;\n\n                // consecutive characters should increase the score more than linearly\n                currScore += 1 + currScore;\n            } else {\n                currScore = 0;\n            }\n            totalScore += currScore;\n            result[result.length] = ch;\n        }\n\n        // return rendered string if we have a match for every char\n        if (patternIdx === pattern.length) {\n            return { rendered: result.join(''), score: totalScore };\n        }\n\n        return null;\n    };\n\n    // The normal entry point. Filters `arr` for matches against `pattern`.\n    // It returns an array with matching values of the type:\n    //\n    //     [{\n    //         string:   '<b>lah' // The rendered string\n    //       , index:    2        // The index of the element in `arr`\n    //       , original: 'blah'   // The original element in `arr`\n    //     }]\n    //\n    // `opts` is an optional argument bag. Details:\n    //\n    //    opts = {\n    //        // string to put before a matching character\n    //        pre:     '<b>'\n    //\n    //        // string to put after matching character\n    //      , post:    '</b>'\n    //\n    //        // Optional function. Input is an entry in the given arr`,\n    //        // output should be the string to test `pattern` against.\n    //        // In this example, if `arr = [{crying: 'koala'}]` we would return\n    //        // 'koala'.\n    //      , extract: function(arg) { return arg.crying; }\n    //    }\n    fuzzy.filter = function(pattern, arr, opts) {\n        opts = opts || {};\n        return (\n            arr\n                .reduce(function(prev, element, idx, arr) {\n                    var str = element;\n                    if (opts.extract) {\n                        str = opts.extract(element);\n                    }\n                    var rendered = fuzzy.match(pattern, str, opts);\n                    if (rendered != null) {\n                        prev[prev.length] = {\n                            string: rendered.rendered,\n                            score: rendered.score,\n                            index: idx,\n                            original: element,\n                        };\n                    }\n                    return prev;\n                }, [])\n\n                // Sort by score. Browsers are inconsistent wrt stable/unstable\n                // sorting, so force stable by using the index in the case of tie.\n                // See http://ofb.net/~sethml/is-sort-stable.html\n                .sort(function(a, b) {\n                    var compare = b.score - a.score;\n                    if (compare) return compare;\n                    return a.index - b.index;\n                })\n        );\n    };\n})(Entry.Utils);\n"
  },
  {
    "path": "src/util/hardwareUtils.ts",
    "content": "export const stringToUint8Array = (e: string): Uint8Array => {\n    let t = e.length;\n    let n = new Uint8Array(t);\n    for (let i = 0; i < t; ++i) n[i] = 255 & e.charCodeAt(i);\n    return n;\n};\n"
  },
  {
    "path": "src/util/htmlElementPatcher.js",
    "content": "//add methods to HTMLElement prototype\n((p) => {\n    p.hasClass = function(className) {\n        return $(this).hasClass(className);\n    };\n\n    p.addClass = function(...classes) {\n        return _.head($(this).addClass(classes.filter(_.identity).join(' ')));\n    };\n\n    p.removeClass = function(...classes) {\n        return _.head($(this).removeClass(classes.join(' ')));\n    };\n\n    p.text = function(str) {\n        if (str) {\n            this.textContent = str;\n        }\n        return this;\n    };\n\n    p.bindOnClick = function(func) {\n        $(this).on('click tab', function(e) {\n            if (this.disabled) {\n                return;\n            }\n            func.call(this, e);\n        });\n        return this;\n    };\n\n    p.unBindOnClick = function() {\n        $(this).off('click tab');\n        return this;\n    };\n\n    p.appendTo = function(parent) {\n        if (parent) {\n            parent.appendChild(this);\n        }\n        return this;\n    };\n})(HTMLElement.prototype);\n"
  },
  {
    "path": "src/util/init.js",
    "content": "'use strict';\n\nimport { Destroyer } from './destroyer/Destroyer';\nimport { GEHelper } from '../graphicEngine/GEHelper';\nimport Expansion from '../class/Expansion';\nimport EntryBlockHelper from '../class/helper';\nimport AIUtilize from '../class/AIUtilize';\nimport AILearning from '../class/AILearning';\nimport Extension from '../extensions/extension';\nimport CloudVariable from '../extensions/CloudVariable';\nimport DataSource from '../util/dataSource';\n\nimport './utils';\n\n/**\n * Initialize method with options.\n * @param {HTMLElement} container for entry workspace or others.\n * @param {Object} options for initialize.\n */\nEntry.init = function (container, options) {\n    Entry.assert(typeof options === 'object', 'Init option is not object');\n    Entry.assert(!!container, 'root container must be provided');\n\n    this.events_ = {};\n    this.interfaceState = {\n        menuWidth: 264,\n    };\n\n    Entry.Utils.bindGlobalEvent([\n        'resize',\n        'mousedown',\n        'mousemove',\n        'keydown',\n        'keyup',\n        'dispose',\n    ]);\n\n    this.options = options;\n    this.parseOptions(options);\n    setDefaultPathsFromOptions(options);\n    this.cloudVariable = CloudVariable.getInstance();\n\n    if (this.type === 'workspace' && this.isPhone()) {\n        this.type = 'phone';\n    }\n    this.initialize_();\n    this.initSoundQueue_();\n    /** @type {!Element} */\n    this.view_ = container;\n    $(this.view_).addClass('entry');\n    if (this.type === 'minimize') {\n        $(this.view_).addClass(this.type);\n    }\n    // if (this.device === 'tablet') $(this.view_).addClass('tablet');\n\n    Entry.initFonts(options.fonts);\n    setDefaultTheme(options);\n\n    Entry.paintMode = options.paintMode || 'entry-paint';\n    container && this.createDom(container, this.type);\n    this.loadInterfaceState();\n    this.overridePrototype();\n    this.maxCloneLimit = 360;\n    this.cloudSavable = true;\n    this.startTime = new Date().getTime();\n\n    document.onkeydown = function (e) {\n        Entry.dispatchEvent('keyPressed', e);\n    };\n    document.onkeyup = function (e) {\n        Entry.dispatchEvent('keyUpped', e);\n    };\n    window.onresize = function (e) {\n        Entry.dispatchEvent('windowResized', e);\n    };\n    window.onbeforeunload = this.beforeUnload;\n\n    Entry.addEventListener('saveWorkspace', () => {\n        Entry.addActivity('save');\n    });\n\n    Entry.addEventListener('showBlockHelper', () => {\n        Entry.propertyPanel.select('helper');\n    });\n\n    // if (Entry.getBrowserType().substr(0, 2) === 'IE' && !window.flashaudio) {\n    //     createjs.FlashAudioPlugin.swfPath = `${this.mediaFilePath}media/`;\n    //     createjs.Sound.registerPlugins([createjs.FlashAudioPlugin]);\n    //     window.flashaudio = true;\n    // } else {\n    //     createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.HTMLAudioPlugin]);\n    // }\n    createjs.Sound.registerPlugins([createjs.WebAudioPlugin, createjs.HTMLAudioPlugin]);\n\n    Entry.loadAudio_(\n        [\n            `${Entry.mediaFilePath}sounds/click.mp3`,\n            `${Entry.mediaFilePath}sounds/click.wav`,\n            `${Entry.mediaFilePath}sounds/click.ogg`,\n        ],\n        'entryMagneting'\n    );\n    Entry.loadAudio_(\n        [\n            `${Entry.mediaFilePath}sounds/delete.mp3`,\n            `${Entry.mediaFilePath}sounds/delete.ogg`,\n            `${Entry.mediaFilePath}sounds/delete.wav`,\n        ],\n        'entryDelete'\n    );\n\n    createjs.Sound.stop();\n    BigNumber.config({ ERRORS: false });\n};\n\nconst setDefaultPathsFromOptions = function (options) {\n    const {\n        libDir = '/lib',\n        entryDir = '/@entrylabs/entry',\n        defaultDir = '',\n        soundDir = '',\n        blockInjectDir = '',\n        baseUrl = location.origin || 'https://playentry.org',\n        offlineModulePath,\n    } = options;\n\n    Entry.mediaFilePath = `${libDir}${entryDir}/images/`;\n    Entry.painterBaseUrl = `${libDir}/literallycanvas-mobile/lib/img`;\n    Entry.defaultPath = defaultDir;\n    Entry.soundPath = soundDir;\n    Entry.blockInjectPath = blockInjectDir;\n    Entry.offlineModulePath = offlineModulePath;\n    Entry.baseUrl = baseUrl.replace(/\\/$/, '');\n    Entry.moduleBaseUrl = `${Entry.baseUrl}/modules/`;\n    Entry.moduleliteBaseUrl = `${Entry.baseUrl}/moduleslite/`;\n};\n\nconst setDefaultTheme = function (options) {\n    const { theme = 'default' } = options;\n    if (theme !== 'default') {\n        try {\n            EntryStatic.colorSet = require(`../theme/${theme}`);\n            require('../playground/block_entry').assignBlocks();\n        } catch (e) {\n            console.log('not exist theme!', e);\n        }\n    }\n};\n\nEntry.changeContainer = function (container) {\n    container.appendChild(this.view_);\n};\n\nEntry.loadAudio_ = function (filenames, name) {\n    if (!window.Audio || !filenames.length) {\n        // No browser support for Audio.\n        return;\n    }\n\n    for (let i = 0; i < filenames.length; i++) {\n        const filename = filenames[i];\n        Entry.soundQueue.loadFile({\n            id: name,\n            src: filename,\n            type: createjs.LoadQueue.SOUND,\n        });\n        break;\n    }\n};\n\n/**\n * Initialize function for Entry.\n * @private\n */\nEntry.initialize_ = function () {\n    /** @type {Destroyer} */\n    this._destroyer = this._destroyer || new Destroyer();\n    this._destroyer.destroy();\n\n    GEHelper.INIT(this.options.useWebGL);\n    this.stage = new Entry.Stage();\n    this._destroyer.add(this.stage);\n\n    if (Entry.engine && Entry.engine.projectTimer) {\n        Entry.engine.clearTimer();\n    }\n\n    this.engine = new Entry.Engine();\n    this._destroyer.add(this.engine);\n\n    if (this.type !== 'minimize') {\n        this.propertyPanel = new Entry.PropertyPanel();\n    }\n\n    this.container = new Entry.Container();\n    this._destroyer.add(this.container);\n\n    this.helper = new EntryBlockHelper();\n    this.youtube = new Entry.Youtube();\n    this.modal = new Entry.Modal();\n    // this.tvCast = new Entry.TvCast();\n    // this.doneProject = new Entry.DoneProject();\n\n    this.variableContainer = new Entry.VariableContainer();\n\n    if (this.type === 'workspace' || this.type === 'phone' || this.type === 'playground') {\n        this.stateManager = new Entry.StateManager();\n    }\n    this.commander = new Entry.Commander(this.type, this.doNotSkipAny);\n\n    this.scene = new Entry.Scene();\n    this._destroyer.add(this.scene);\n\n    this.playground = new Entry.Playground();\n    this._destroyer.add(this.playground);\n\n    this.blockCountViewer = new Entry.BlockCountViewer(this.playground);\n    this._destroyer.add(this.blockCountViewer);\n\n    if (this.options.expansionDisable === false || this.options.expansionDisable === undefined) {\n        this.expansion = new Expansion(this.playground);\n        this._destroyer.add(this.expansion);\n        this.expansion.init();\n    }\n\n    if (this.options.aiUtilizeDisable === false || this.options.aiUtilizeDisable === undefined) {\n        this.aiUtilize = new AIUtilize(this.playground);\n        this._destroyer.add(this.aiUtilize);\n        this.aiLearning = new AILearning(this.playground, this.aiLearningEnable);\n        this._destroyer.add(this.aiLearning);\n        this.aiUtilize.init();\n        this.aiLearning.init();\n    }\n\n    this.intro = new Entry.Intro();\n\n    this.toast = new Entry.Toast();\n\n    if (this.hw) {\n        this.hw.closeConnection();\n    }\n    this.hw = new Entry.HW();\n\n    this.hwLite = new Entry.HWLite(this.playground);\n\n    if (Entry.enableActivityLogging) {\n        this.reporter = new Entry.Reporter(false);\n    } else if (this.type === 'workspace' || this.type === 'phone') {\n        this.reporter = new Entry.Reporter(true);\n    }\n};\n\nEntry.disposeContainer = function () {\n    this._destroyer = this._destroyer || new Destroyer();\n    this._destroyer.destroy();\n    while (this.view_.firstChild) {\n        this.view_.removeChild(this.view_.firstChild);\n    }\n};\n\nEntry.initSoundQueue_ = function () {\n    Entry.soundQueue = new createjs.LoadQueue();\n    Entry.soundQueue.installPlugin(createjs.Sound);\n    Entry.soundInstances = new DataSource();\n    Entry.bgmInstances = new DataSource();\n    Entry.soundQueue.urls = new Set();\n    Entry.soundQueue.total = 0;\n    Entry.soundQueue.loadCallback = (src) => {\n        if (!Entry.soundQueue.urls.has(src)) {\n            return;\n        }\n        Entry.soundQueue.total = Math.max(Entry.soundQueue.total, Entry.soundQueue.urls.size);\n        Entry.soundQueue.urls.delete(src);\n        const now = Entry.soundQueue.urls.size;\n        if (!Entry.soundQueue.loadComplete && now < 1) {\n            Entry.soundQueue.loadComplete = true;\n            Entry.dispatchEvent('soundLoaded');\n        }\n    };\n    Entry.soundQueue.on('fileload', (event) => {\n        Entry.soundQueue.loadCallback(event.item.src);\n    });\n    Entry.soundQueue.on('error', (event) => {\n        console.error('load sound, error', event);\n        Entry.soundQueue.loadCallback(event.data.src);\n    });\n};\n/**\n * Initialize html DOM view for entry.\n * This work differently with initialize option.\n * @param {HTMLElement} container for entry workspace or others.\n * @param {string} type for create dom by type.\n */\nEntry.createDom = function (container, type) {\n    const textCanvasContainer = Entry.createElement('div', 'textCanvasContainer');\n    textCanvasContainer.style.display = 'none';\n    container.appendChild(textCanvasContainer);\n\n    switch (type) {\n        case 'minimize': {\n            const canvas = _createCanvasElement(['entryCanvasWorkspace', 'minimize']);\n            const canvasWrapper = Entry.createElement('div', 'entryCanvasWrapper');\n            canvasWrapper.appendChild(canvas);\n            container.appendChild(canvasWrapper);\n\n            this.canvas_ = canvas;\n            this.stage.initStage(this.canvas_);\n\n            const engineView = Entry.createElement('div');\n            container.appendChild(engineView);\n            this.engineView = engineView;\n            this.engine.generateView(this.engineView, type);\n            Entry.addEventListener('dispatchEventDidTogglePause', () =>\n                Entry.engine.view_.classList.toggle('paused')\n            );\n            break;\n        }\n        case 'phone': {\n            this.stateManagerView = Entry.createElement('div');\n            this.stateManager.generateView(this.stateManagerView, type);\n\n            const engineView = Entry.createElement('div');\n            container.appendChild(engineView);\n            this.engineView = engineView;\n            this.engine.generateView(this.engineView, type);\n\n            const canvas = _createCanvasElement('entryCanvasPhone');\n\n            engineView.insertBefore(canvas, this.engine.footerView_);\n            this.canvas_ = canvas;\n            this.stage.initStage(this.canvas_);\n\n            const containerView = Entry.createElement('div');\n            container.appendChild(containerView);\n            this.containerView = containerView;\n            this.container.generateView(this.containerView);\n\n            const playgroundView = Entry.createElement('div');\n            container.appendChild(playgroundView);\n            this.playgroundView = playgroundView;\n            this.playground.generateView(this.playgroundView, type);\n            break;\n        }\n        case 'playground': {\n            const playgroundView = Entry.createElement('div');\n            container.appendChild(playgroundView);\n            this.playgroundView = playgroundView;\n            this.playground.generateView(this.playgroundView, type);\n            break;\n        }\n        case 'invisible': {\n            // 아무런 뷰도 그리지 않는다.\n            break;\n        }\n        case 'workspace':\n        default: {\n            Entry.documentMousedown.attach(this, this.cancelObjectEdit);\n\n            const topFloatingView = Entry.createElement('div');\n            topFloatingView.addClass('entryTopFloatingView');\n            container.appendChild(topFloatingView);\n\n            const sceneView = Entry.createElement('div');\n            topFloatingView.appendChild(sceneView);\n            this.sceneView = sceneView;\n            this.scene.generateView(this.sceneView, type);\n\n            const blockCountViewerView = Entry.createElement('div');\n            blockCountViewerView.addClass('entryBlockCountView');\n            topFloatingView.appendChild(blockCountViewerView);\n            this.blockCountViewerView = blockCountViewerView;\n            this.blockCountViewer.generateView(this.blockCountViewerView, type);\n\n            const stateManagerView = Entry.createElement('div');\n            this.sceneView.appendChild(stateManagerView);\n            this.stateManagerView = stateManagerView;\n            this.stateManager.generateView(this.stateManagerView, type);\n\n            const engineContainer = Entry.createElement('div');\n            engineContainer.classList.add('engineContainer');\n            container.appendChild(engineContainer);\n            const engineView = Entry.createElement('div');\n            engineContainer.appendChild(engineView);\n            this.engineContainer = engineContainer;\n            this.engineView = engineView;\n            this.engine.generateView(this.engineView, type);\n\n            const canvas = _createCanvasElement('entryCanvasWorkspace');\n            this.engine.mouseView.after(canvas);\n\n            canvas.addEventListener('mousewheel', (evt) => {\n                const mousePosition = Entry.stage.mouseCoordinate;\n                const tempList = Entry.variableContainer.getListById(mousePosition);\n                const wheelDirection = evt.wheelDelta > 0;\n\n                for (let i = 0; i < tempList.length; i++) {\n                    const list = tempList[i];\n                    if (wheelDirection) {\n                        if (list.scrollButton_.y >= 46) {\n                            list.scrollButton_.y -= 25;\n                        } else {\n                            list.scrollButton_.y = 25;\n                        }\n                    } else {\n                        list.scrollButton_.y += 25;\n                    }\n                    list.updateView();\n                }\n            });\n\n            this.canvas_ = canvas;\n            this.extension = new Extension();\n            this.stage.initStage(this.canvas_);\n\n            const containerView = Entry.createElement('div');\n            this.propertyPanel.generateView(engineContainer, type);\n            this.containerView = containerView;\n            this.container.generateView(this.containerView);\n            this.propertyPanel.addMode('object', this.container);\n\n            this.helper.generateView(this.containerView, type);\n            this.propertyPanel.addMode('helper', this.helper);\n\n            const introView = Entry.createElement('div');\n            container.appendChild(introView);\n            this.introView = introView;\n            this.intro.generateView(this.introView, type);\n\n            const playgroundView = Entry.createElement('div');\n            container.appendChild(playgroundView);\n            this.playgroundView = playgroundView;\n            this.playground.generateView(this.playgroundView, type);\n\n            this.propertyPanel.select('object');\n            this.helper.bindWorkspace(this.playground.mainWorkspace);\n        }\n    }\n};\n\n/**\n * @param className {string|string[]}\n * @private\n */\nconst _createCanvasElement = (className) => {\n    const canvas = Entry.createElement('canvas');\n    canvas.id = 'entryCanvas';\n    canvas.width = 640;\n    canvas.height = 360;\n\n    if (Array.isArray(className)) {\n        canvas.className = className.join(' ');\n    } else {\n        canvas.addClass(className);\n    }\n\n    return canvas;\n};\n\nEntry.start = function () {\n    if (Entry.type === 'invisible') {\n        return;\n    }\n    /** @type {number} */\n    if (!this.FPS) {\n        this.FPS = 60;\n    }\n    Entry.assert(typeof this.FPS === 'number', 'FPS must be number');\n    Entry.engine.start(this.FPS);\n};\n\nEntry.stop = function () {\n    if (Entry.type === 'invisible') {\n        return;\n    }\n    this.FPS = null;\n    Entry?.engine?.stop();\n};\n\n/**\n * Parse init options\n * @param {!object} options for parse\n */\nEntry.parseOptions = function (options) {\n    /** @type {string} */\n    this.type = options.type || this.type;\n\n    this.hashId = options.hashId || this.hashId;\n\n    if (options.device) {\n        this.device = options.device;\n    }\n\n    this.projectSaveable = options.projectsaveable;\n    if (this.projectSaveable === undefined) {\n        this.projectSaveable = true;\n    }\n\n    this.objectAddable = options.objectaddable;\n    if (this.objectAddable === undefined) {\n        this.objectAddable = true;\n    }\n\n    this.objectEditable = options.objectEditable;\n    if (this.objectEditable === undefined) {\n        this.objectEditable = true;\n    }\n    if (!this.objectEditable) {\n        this.objectAddable = false;\n    }\n\n    this.objectDeletable = options.objectdeletable;\n    if (this.objectDeletable === undefined) {\n        this.objectDeletable = true;\n    }\n\n    this.soundEditable = options.soundeditable;\n    if (this.soundEditable === undefined) {\n        this.soundEditable = true;\n    }\n\n    this.pictureEditable = options.pictureeditable;\n    if (this.pictureEditable === undefined) {\n        this.pictureEditable = true;\n    }\n\n    this.sceneEditable = options.sceneEditable;\n    if (this.sceneEditable === undefined) {\n        this.sceneEditable = true;\n    }\n\n    this.functionEnable = options.functionEnable;\n    if (this.functionEnable === undefined) {\n        this.functionEnable = true;\n    }\n\n    this.messageEnable = options.messageEnable;\n    if (this.messageEnable === undefined) {\n        this.messageEnable = true;\n    }\n\n    this.variableEnable = options.variableEnable;\n    if (this.variableEnable === undefined) {\n        this.variableEnable = true;\n    }\n\n    this.aiLearningEnable = options.aiLearningEnable;\n    if (this.aiLearningEnable === undefined) {\n        this.aiLearningEnable = true;\n    }\n\n    this.hardwareEnable = options.hardwareEnable;\n    if (this.hardwareEnable === undefined) {\n        this.hardwareEnable = true;\n    }\n\n    this.listEnable = options.listEnable;\n    if (this.listEnable === undefined) {\n        this.listEnable = true;\n    }\n\n    this.doCommandAll = options.doCommandAll;\n    if (this.doCommandAll === undefined) {\n        this.doCommandAll = false;\n    }\n\n    this.backpackDisable = options.backpackDisable;\n    if (this.backpackDisable === undefined) {\n        this.backpackDisable = false;\n    }\n\n    this.exportObjectEnable = options.exportObjectEnable;\n    if (this.exportObjectEnable === undefined) {\n        this.exportObjectEnable = true;\n    }\n\n    this.iframeDomAccess = options.iframeDomAccess;\n    if (this.iframeDomAccess === undefined) {\n        //direct, message, none\n        this.iframeDomAccess = 'direct';\n    }\n\n    this.blockSaveImageEnable = options.blockSaveImageEnable;\n    if (this.blockSaveImageEnable === undefined) {\n        this.blockSaveImageEnable = true;\n    }\n\n    this.hasVariableManager = options.hasvariablemanager;\n    if (!(this.variableEnable || this.messageEnable || this.listEnable || this.functionEnable)) {\n        this.hasVariableManager = false;\n    } else if (this.hasVariableManager === undefined) {\n        this.hasVariableManager = true;\n    }\n\n    this.readOnly = options.readOnly || false;\n    if (this.readOnly) {\n        this.soundEditable = false;\n        this.sceneEditable = false;\n        this.objectAddable = false;\n    }\n\n    if (options.isForLecture) {\n        this.isForLecture = options.isForLecture;\n    }\n    if (options.textCodingEnable) {\n        this.textCodingEnable = options.textCodingEnable;\n    }\n    if (options.isStartOnLoaded) {\n        this.isStartOnLoaded = options.isStartOnLoaded;\n    }\n    this.fullScreenEnable = options.fullScreenEnable;\n    if (this.fullScreenEnable === undefined) {\n        this.fullScreenEnable = true;\n    }\n    if (options.aiAssistantEnable) {\n        this.aiAssistantEnable = options.aiAssistantEnable;\n    }\n    this.modalContainer = options.modalContainer || $('body')[0];\n};\n\nEntry.initFonts = function (fonts) {\n    this.fonts = fonts;\n    if (!fonts) {\n        this.fonts = [];\n    }\n};\n\nEntry.reloadOption = function (options) {\n    this.options = options;\n    this.parseOptions(options);\n    this.playground.applyTabOption();\n    this.variableContainer.applyOption();\n    this.engine.applyOption();\n    this.commander.applyOption();\n};\n\nEntry.Utils.initEntryEvent_ = function () {\n    if (!Entry.events_) {\n        Entry.events_ = [];\n    }\n};\n\nEntry.getSoundPath = (sound) =>\n    sound.fileurl ||\n    `${Entry.defaultPath}/uploads/${sound.filename.substring(0, 2)}/${sound.filename.substring(\n        2,\n        4\n    )}/${Entry.soundPath}${sound.filename}${sound.ext || '.mp3'}`;\n\n/**\n * initialize sound\n * @param {object} sound\n */\nEntry.initSound = function (sound) {\n    if (!sound || !sound.duration || sound.duration == 0) {\n        return;\n    }\n    sound.path =\n        sound.fileurl ||\n        `${Entry.defaultPath}/uploads/${sound.filename.substring(0, 2)}/${sound.filename.substring(\n            2,\n            4\n        )}/${Entry.soundPath}${sound.filename}${sound.ext || '.mp3'}`;\n    Entry.soundQueue.urls.add(sound.path);\n    Entry.soundQueue.loadFile({\n        id: sound.id,\n        src: sound.path,\n        type: createjs.LoadQueue.SOUND,\n    });\n    setTimeout(() => {\n        Entry.soundQueue.loadCallback(sound.path);\n    }, 3000);\n};\n\nEntry.loadAllBlocks = function (options = {}) {\n    if (options.aiUtilizeDisable === false || options.aiUtilizeDisable === undefined) {\n        this.aiUtilize = new AIUtilize();\n        this.aiLearning = new AILearning();\n        this.aiUtilize.init();\n        this.aiLearning.init();\n    }\n\n    if (options.expansionDisable === false || options.expansionDisable === undefined) {\n        this.expansion = new Expansion(this.playground);\n        this.expansion.init();\n    }\n};\n"
  },
  {
    "path": "src/util/loader.js",
    "content": "'use strict';\n\nEntry.Loader = {\n    queueCount: 0,\n    totalCount: 0,\n    loaded: false,\n};\n\nEntry.Loader.addQueue = function(type) {\n    if (!this.queueCount) Entry.dispatchEvent('loadStart');\n    this.queueCount++;\n    this.totalCount++;\n};\n\nEntry.Loader.removeQueue = function(type) {\n    this.queueCount--;\n    if (!this.queueCount) {\n        this.totalCount = 0;\n        this.handleLoad();\n    }\n};\n\nEntry.Loader.getLoadedPercent = function() {\n    if (this.totalCount === 0) return 1;\n    else return this.queueCount / this.totalCount;\n};\n\nEntry.Loader.isLoaded = function() {\n    return !this.queueCount && !this.totalCount;\n};\n\nEntry.Loader.handleLoad = function() {\n    if (this.loaded) return;\n    this.loaded = true;\n    Entry.dispatchEvent('loadComplete');\n};\n"
  },
  {
    "path": "src/util/location.js",
    "content": "'use strict';\n\nfunction getInitialData() {\n    let locationObj = {};\n    locationObj.initialData = [Lang.Blocks.location_entire, 'all'];\n    locationObj.ko = {\n        'Seoul': {\n            'lang': Lang.Blocks.location_seoul,\n            'sub': [\n                [Lang.Blocks.location_seoul_jongno_gu, 'jongno_gu'],\n                [Lang.Blocks.location_seoul_jung_gu, 'jung_gu'],\n                [Lang.Blocks.location_seoul_yongsan_gu, 'yongsan_gu'],\n                [Lang.Blocks.location_seoul_seongdong_gu, 'seongdong_gu'],\n                [Lang.Blocks.location_seoul_gwangjin_gu, 'gwangjin_gu'],\n                [Lang.Blocks.location_seoul_dongdaemun_gu, 'dongdaemun_gu'],\n                [Lang.Blocks.location_seoul_jungnang_gu, 'jungnang_gu'],\n                [Lang.Blocks.location_seoul_seongbuk_gu, 'seongbuk_gu'],\n                [Lang.Blocks.location_seoul_gangbuk_gu, 'gangbuk_gu'],\n                [Lang.Blocks.location_seoul_dobong_gu, 'dobong_gu'],\n                [Lang.Blocks.location_seoul_nowon_gu, 'nowon_gu'],\n                [Lang.Blocks.location_seoul_eunpyeong_gu, 'eunpyeong_gu'],\n                [Lang.Blocks.location_seoul_seodaemun_gu, 'seodaemun_gu'],\n                [Lang.Blocks.location_seoul_mapo_gu, 'mapo_gu'],\n                [Lang.Blocks.location_seoul_yangcheon_gu, 'yangcheon_gu'],\n                [Lang.Blocks.location_seoul_gangseo_gu, 'gangseo_gu'],\n                [Lang.Blocks.location_seoul_guro_gu, 'guro_gu'],\n                [Lang.Blocks.location_seoul_geumcheon_gu, 'geumcheon_gu'],\n                [Lang.Blocks.location_seoul_yeongdeungpo_gu, 'yeongdeungpo_gu'],\n                [Lang.Blocks.location_seoul_dongjak_gu, 'dongjak_gu'],\n                [Lang.Blocks.location_seoul_gwanak_gu, 'gwanak_gu'],\n                [Lang.Blocks.location_seoul_seocho_gu, 'seocho_gu'],\n                [Lang.Blocks.location_seoul_gangnam_gu, 'gangnam_gu'],\n                [Lang.Blocks.location_seoul_songpa_gu, 'songpa_gu'],\n                [Lang.Blocks.location_seoul_gangdong_gu, 'gangdong_gu'],\n            ],\n        },\n        'Gangwon': {\n            'lang': Lang.Blocks.location_gangwon,\n            'sub': [\n                [Lang.Blocks.location_gangwon_chuncheon, 'chuncheon'],\n                [Lang.Blocks.location_gangwon_wonju, 'wonju'],\n                [Lang.Blocks.location_gangwon_gangneung_si, 'gangneung_si'],\n                [Lang.Blocks.location_gangwon_donghae, 'donghae'],\n                [Lang.Blocks.location_gangwon_taebaek_si, 'taebaek_si'],\n                [Lang.Blocks.location_gangwon_sokcho, 'sokcho'],\n                [Lang.Blocks.location_gangwon_samcheok_si, 'samcheok_si'],\n                [Lang.Blocks.location_gangwon_hongcheon, 'hongcheon'],\n                [Lang.Blocks.location_gangwon_hoengseong_gun, 'hoengseong_gun'],\n                [Lang.Blocks.location_gangwon_yeongwol_gun, 'yeongwol_gun'],\n                [Lang.Blocks.location_gangwon_pyeongchang, 'pyeongchang'],\n                [Lang.Blocks.location_gangwon_jeongseon, 'jeongseon'],\n                [Lang.Blocks.location_gangwon_cheolwon, 'cheolwon'],\n                [Lang.Blocks.location_gangwon_hwacheon, 'hwacheon'],\n                [Lang.Blocks.location_gangwon_yanggu, 'yanggu'],\n                [Lang.Blocks.location_gangwon_inje, 'inje'],\n                [Lang.Blocks.location_gangwon_goseong, 'goseong'],\n                [Lang.Blocks.location_gangwon_yangyang, 'yangyang'],\n            ],\n        },\n        'Gyeonggi-do': {\n            'lang': Lang.Blocks.location_gyeonggi,\n            'sub': [\n                [Lang.Blocks.location_gyeonggi_suwon_si, 'suwon_si'],\n                [Lang.Blocks.location_gyeonggi_seongnam, 'seongnam'],\n                [Lang.Blocks.location_gyeonggi_uijeongbu, 'uijeongbu'],\n                [Lang.Blocks.location_gyeonggi_anyang_si, 'anyang_si'],\n                [Lang.Blocks.location_gyeonggi_bucheon_si, 'bucheon_si'],\n                [Lang.Blocks.location_gyeonggi_gwangmyeong_si, 'gwangmyeong_si'],\n                [Lang.Blocks.location_gyeonggi_pyeongtaek_si, 'pyeongtaek_si'],\n                [Lang.Blocks.location_gyeonggi_dongducheon_si, 'dongducheon_si'],\n                [Lang.Blocks.location_gyeonggi_ansan_si, 'ansan_si'],\n                [Lang.Blocks.location_gyeonggi_goyang_si, 'goyang_si'],\n                [Lang.Blocks.location_gyeonggi_gwacheon_si, 'gwacheon_si'],\n                [Lang.Blocks.location_gyeonggi_guri, 'guri'],\n                [Lang.Blocks.location_gyeonggi_namyangju_si, 'namyangju_si'],\n                [Lang.Blocks.location_gyeonggi_osan, 'osan'],\n                [Lang.Blocks.location_gyeonggi_siheung, 'siheung'],\n                [Lang.Blocks.location_gyeonggi_gunpo_si, 'gunpo_si'],\n                [Lang.Blocks.location_gyeonggi_uiwang_si, 'uiwang_si'],\n                [Lang.Blocks.location_gyeonggi_hanam, 'hanam'],\n                [Lang.Blocks.location_gyeonggi_yongin_si, 'yongin_si'],\n                [Lang.Blocks.location_gyeonggi_paju, 'paju'],\n                [Lang.Blocks.location_gyeonggi_icheon, 'icheon'],\n                [Lang.Blocks.location_gyeonggi_anseong_si, 'anseong_si'],\n                [Lang.Blocks.location_gyeonggi_gimpo, 'gimpo'],\n                [Lang.Blocks.location_gyeonggi_hwaseong_si, 'hwaseong_si'],\n                [Lang.Blocks.location_gyeonggi_gwangju, 'gwangju'],\n                [Lang.Blocks.location_gyeonggi_yangju_si, 'yangju_si'],\n                [Lang.Blocks.location_gyeonggi_pocheon, 'pocheon'],\n                [Lang.Blocks.location_gyeonggi_yeoju, 'yeoju'],\n                [Lang.Blocks.location_gyeonggi_yeoncheon_gun, 'yeoncheon_gun'],\n                [Lang.Blocks.location_gyeonggi_gapyeong_gun, 'gapyeong_gun'],\n                [Lang.Blocks.location_gyeonggi_yangpyeong, 'yangpyeong'],\n            ],\n        },\n        'Gyeongsangnam-do': {\n            'lang': Lang.Blocks.location_gyeongsangnam,\n            'sub': [\n                [Lang.Blocks.location_gyeongsangnam_changwon_si, 'changwon_si'],\n                [Lang.Blocks.location_gyeongsangnam_jinju, 'jinju'],\n                [Lang.Blocks.location_gyeongsangnam_tongyeong_si, 'tongyeong_si'],\n                [Lang.Blocks.location_gyeongsangnam_sacheon_si, 'sacheon_si'],\n                [Lang.Blocks.location_gyeongsangnam_gimhae_si, 'gimhae_si'],\n                [Lang.Blocks.location_gyeongsangnam_miryang_si, 'miryang_si'],\n                [Lang.Blocks.location_gyeongsangnam_geoje_si, 'geoje_si'],\n                [Lang.Blocks.location_gyeongsangnam_yangsan_si, 'yangsan_si'],\n                [Lang.Blocks.location_gyeongsangnam_uiryeong, 'uiryeong'],\n                [Lang.Blocks.location_gyeongsangnam_haman, 'haman'],\n                [Lang.Blocks.location_gyeongsangnam_changnyeong, 'changnyeong'],\n                [Lang.Blocks.location_gyeongsangnam_goseong, 'goseong'],\n                [Lang.Blocks.location_gyeongsangnam_namhae, 'namhae'],\n                [Lang.Blocks.location_gyeongsangnam_hadong, 'hadong'],\n                [Lang.Blocks.location_gyeongsangnam_sancheong, 'sancheong'],\n                [Lang.Blocks.location_gyeongsangnam_hamyang, 'hamyang'],\n                [Lang.Blocks.location_gyeongsangnam_geochang, 'geochang'],\n                [Lang.Blocks.location_gyeongsangnam_hapcheon, 'hapcheon'],\n            ],\n        },\n        'Gyeongsangbuk-do': {\n            'lang': Lang.Blocks.location_gyeongsangbuk,\n            'sub': [\n                [Lang.Blocks.location_gyeongsangbuk_pohang_si, 'pohang_si'],\n                [Lang.Blocks.location_gyeongsangbuk_gyeongju_si, 'gyeongju_si'],\n                [Lang.Blocks.location_gyeongsangbuk_gimcheon_si, 'gimcheon_si'],\n                [Lang.Blocks.location_gyeongsangbuk_andong_si, 'andong_si'],\n                [Lang.Blocks.location_gyeongsangbuk_gumi_si, 'gumi_si'],\n                [Lang.Blocks.location_gyeongsangbuk_yeongju_si, 'yeongju_si'],\n                [Lang.Blocks.location_gyeongsangbuk_yeongcheon_si, 'yeongcheon_si'],\n                [Lang.Blocks.location_gyeongsangbuk_sangju_si, 'sangju_si'],\n                [Lang.Blocks.location_gyeongsangbuk_mungyeong_si, 'mungyeong_si'],\n                [Lang.Blocks.location_gyeongsangbuk_gyeongsan_si, 'gyeongsan_si'],\n                [Lang.Blocks.location_gyeongsangbuk_uiseong, 'uiseong'],\n                [Lang.Blocks.location_gyeongsangbuk_cheongsong, 'cheongsong'],\n                [Lang.Blocks.location_gyeongsangbuk_goryong, 'goryong'],\n                [Lang.Blocks.location_gyeongsangbuk_yeongdeok, 'yeongdeok'],\n                [Lang.Blocks.location_gyeongsangbuk_cheongdo, 'cheongdo'],\n                [Lang.Blocks.location_gyeongsangbuk_golyeong, 'golyeong'],\n                [Lang.Blocks.location_gyeongsangbuk_seongju, 'seongju'],\n                [Lang.Blocks.location_gyeongsangbuk_chilgok, 'chilgok'],\n                [Lang.Blocks.location_gyeongsangbuk_yecheon, 'yecheon'],\n                [Lang.Blocks.location_gyeongsangbuk_bonghwa, 'bonghwa'],\n                [Lang.Blocks.location_gyeongsangbuk_uljin, 'uljin'],\n                [Lang.Blocks.location_gyeongsangbuk_ulleung, 'ulleung'],\n            ],\n        },\n        'Gwangju': {\n            'lang': Lang.Blocks.location_gwangju,\n            'sub': [\n                [Lang.Blocks.location_gwangju_dong_gu, 'dong_gu'],\n                [Lang.Blocks.location_gwangju_seo_gu, 'seo_gu'],\n                [Lang.Blocks.location_gwangju_nam_gu, 'nam_gu'],\n                [Lang.Blocks.location_gwangju_buk_gu, 'buk_gu'],\n                [Lang.Blocks.location_gwangju_gwangsan_gu, 'gwangsan_gu'],\n            ],\n        },\n        'Daegu': {\n            'lang': Lang.Blocks.location_daegu,\n            'sub': [\n                [Lang.Blocks.location_daegu_jung_gu, 'jung_gu'],\n                [Lang.Blocks.location_daegu_dong_gu, 'dong_gu'],\n                [Lang.Blocks.location_daegu_seo_gu, 'seo_gu'],\n                [Lang.Blocks.location_daegu_nam_gu, 'nam_gu'],\n                [Lang.Blocks.location_daegu_buk_gu, 'buk_gu'],\n                [Lang.Blocks.location_daegu_suseong_gu, 'suseong_gu'],\n                [Lang.Blocks.location_daegu_dalseo_gu, 'dalseo_gu'],\n                [Lang.Blocks.location_daegu_dalseong, 'dalseong'],\n                [Lang.Blocks.location_daegu_gunwi, 'gunwi'],\n            ],\n        },\n        'Daejeon': {\n            'lang': Lang.Blocks.location_daejeon,\n            'sub': [\n                [Lang.Blocks.location_daejeon_dong_gu, 'dong_gu'],\n                [Lang.Blocks.location_daejeon_jung_gu, 'jung_gu'],\n                [Lang.Blocks.location_daejeon_seo_gu, 'seo_gu'],\n                [Lang.Blocks.location_daejeon_yuseong_gu, 'yuseong_gu'],\n                [Lang.Blocks.location_daejeon_daedeok_gu, 'daedeok_gu'],\n            ],\n        },\n        'Busan': {\n            'lang': Lang.Blocks.location_busan,\n            'sub': [\n                [Lang.Blocks.location_busan_jung_gu, 'jung_gu'],\n                [Lang.Blocks.location_busan_seo_gu, 'seo_gu'],\n                [Lang.Blocks.location_busan_dong_gu, 'dong_gu'],\n                [Lang.Blocks.location_busan_yeongdo_gu, 'yeongdo_gu'],\n                [Lang.Blocks.location_busan_busanjin_gu, 'busanjin_gu'],\n                [Lang.Blocks.location_busan_dongnae_gu, 'dongnae_gu'],\n                [Lang.Blocks.location_busan_nam_gu, 'nam_gu'],\n                [Lang.Blocks.location_busan_buk_gu, 'buk_gu'],\n                [Lang.Blocks.location_busan_haeundae_gu, 'haeundae_gu'],\n                [Lang.Blocks.location_busan_saha_gu, 'saha_gu'],\n                [Lang.Blocks.location_busan_geumjeong_gu, 'geumjeong_gu'],\n                [Lang.Blocks.location_busan_gangseo_gu, 'gangseo_gu'],\n                [Lang.Blocks.location_busan_yeonje, 'yeonje'],\n                [Lang.Blocks.location_busan_suyeong_gu, 'suyeong_gu'],\n                [Lang.Blocks.location_busan_sasang_gu, 'sasang_gu'],\n                [Lang.Blocks.location_busan_gijang, 'gijang'],\n            ],\n        },\n        'Sejong': {\n            'lang': Lang.Blocks.location_sejong,\n            'sub': [],\n        },\n        'Ulsan': {\n            'lang': Lang.Blocks.location_ulsan,\n            'sub': [\n                [Lang.Blocks.location_ulsan_jung_gu, 'jung_gu'],\n                [Lang.Blocks.location_ulsan_nam_gu, 'nam_gu'],\n                [Lang.Blocks.location_ulsan_dong_gu, 'dong_gu'],\n                [Lang.Blocks.location_ulsan_buk_gu, 'buk_gu'],\n                [Lang.Blocks.location_ulsan_ulju, 'ulju'],\n            ],\n        },\n        'Incheon': {\n            'lang': Lang.Blocks.location_incheon,\n            'sub': [\n                [Lang.Blocks.location_incheon_jung_gu, 'jung_gu'],\n                [Lang.Blocks.location_incheon_dong_gu, 'dong_gu'],\n                [Lang.Blocks.location_incheon_nam_gu, 'nam_gu'],\n                [Lang.Blocks.location_incheon_yeonsu_gu, 'yeonsu_gu'],\n                [Lang.Blocks.location_incheon_namdong_gu, 'namdong_gu'],\n                [Lang.Blocks.location_incheon_bupyeong_gu, 'bupyeong_gu'],\n                [Lang.Blocks.location_incheon_gyeyang_gu, 'gyeyang_gu'],\n                [Lang.Blocks.location_incheon_seo_gu, 'seo_gu'],\n                [Lang.Blocks.location_incheon_ganghwa, 'ganghwa'],\n                [Lang.Blocks.location_incheon_ongjin_gun, 'ongjin_gun'],\n            ],\n        },\n        'Jeollanam-do': {\n            'lang': Lang.Blocks.location_jeollanam,\n            'sub': [\n                [Lang.Blocks.location_jeollanam_mokpo, 'mokpo'],\n                [Lang.Blocks.location_jeollanam_yosu, 'yosu'],\n                [Lang.Blocks.location_jeollanam_suncheon_si, 'suncheon_si'],\n                [Lang.Blocks.location_jeollanam_naju, 'naju'],\n                [Lang.Blocks.location_jeollanam_gwangyang_si, 'gwangyang_si'],\n                [Lang.Blocks.location_jeollanam_damyang, 'damyang'],\n                [Lang.Blocks.location_jeollanam_gokseong, 'gokseong'],\n                [Lang.Blocks.location_jeollanam_gurye, 'gurye'],\n                [Lang.Blocks.location_jeollanam_goheung, 'goheung'],\n                [Lang.Blocks.location_jeollanam_boseong, 'boseong'],\n                [Lang.Blocks.location_jeollanam_hwasun, 'hwasun'],\n                [Lang.Blocks.location_jeollanam_jangheung, 'jangheung'],\n                [Lang.Blocks.location_jeollanam_gangjin, 'gangjin'],\n                [Lang.Blocks.location_jeollanam_haenam, 'haenam'],\n                [Lang.Blocks.location_jeollanam_yeongam, 'yeongam'],\n                [Lang.Blocks.location_jeollanam_jindo, 'jindo'],\n                [Lang.Blocks.location_jeollanam_muan, 'muan'],\n                [Lang.Blocks.location_jeollanam_hampyeong, 'hampyeong'],\n                [Lang.Blocks.location_jeollanam_yeonggwang, 'yeonggwang'],\n                [Lang.Blocks.location_jeollanam_jangseong, 'jangseong'],\n                [Lang.Blocks.location_jeollanam_wando, 'wando'],\n                [Lang.Blocks.location_jeollanam_sinan, 'sinan'],\n\n            ],\n        },\n        'Jeollabuk-do': {\n            'lang': Lang.Blocks.location_jeollabuk,\n            'sub': [\n                [Lang.Blocks.location_jeollabuk_jeonju, 'jeonju'],\n                [Lang.Blocks.location_jeollabuk_gunsan_si, 'gunsan_si'],\n                [Lang.Blocks.location_jeollabuk_iksan, 'iksan'],\n                [Lang.Blocks.location_jeollabuk_jeongeup, 'jeongeup'],\n                [Lang.Blocks.location_jeollabuk_namwon, 'namwon'],\n                [Lang.Blocks.location_jeollabuk_gimje_si, 'gimje_si'],\n                [Lang.Blocks.location_jeollabuk_wanju, 'wanju'],\n                [Lang.Blocks.location_jeollabuk_jinan, 'jinan'],\n                [Lang.Blocks.location_jeollabuk_muju, 'muju'],\n                [Lang.Blocks.location_jeollabuk_jangsu, 'jangsu'],\n                [Lang.Blocks.location_jeollabuk_imsil, 'imsil'],\n                [Lang.Blocks.location_jeollabuk_sunchang, 'sunchang'],\n                [Lang.Blocks.location_jeollabuk_gochang, 'gochang'],\n                [Lang.Blocks.location_jeollabuk_buan, 'buan'],\n            ],\n        },\n        'Jeju': {\n            'lang': Lang.Blocks.location_jeju,\n            'sub': [\n                [Lang.Blocks.location_jeju_jeju_si, 'jeju_si'],\n                [Lang.Blocks.location_jeju_seogwipo, 'seogwipo'],\n            ],\n        },\n        'Chungcheongnam-do': {\n            'lang': Lang.Blocks.location_chungcheongnam,\n            'sub': [\n                [Lang.Blocks.location_chungcheongnam_cheonan, 'cheonan'],\n                [Lang.Blocks.location_chungcheongnam_gongju, 'gongju'],\n                [Lang.Blocks.location_chungcheongnam_boryeong, 'boryeong'],\n                [Lang.Blocks.location_chungcheongnam_asan, 'asan'],\n                [Lang.Blocks.location_chungcheongnam_seosan, 'seosan'],\n                [Lang.Blocks.location_chungcheongnam_nonsan, 'nonsan'],\n                [Lang.Blocks.location_chungcheongnam_gyeryong, 'gyeryong'],\n                [Lang.Blocks.location_chungcheongnam_dangjin, 'dangjin'],\n                [Lang.Blocks.location_chungcheongnam_geumsan, 'geumsan'],\n                [Lang.Blocks.location_chungcheongnam_buyeo, 'buyeo'],\n                [Lang.Blocks.location_chungcheongnam_seocheon, 'seocheon'],\n                [Lang.Blocks.location_chungcheongnam_cheongyang, 'cheongyang'],\n                [Lang.Blocks.location_chungcheongnam_hongseong, 'hongseong'],\n                [Lang.Blocks.location_chungcheongnam_yesan, 'yesan'],\n                [Lang.Blocks.location_chungcheongnam_taean, 'taean'],\n            ],\n        },\n        'Chungcheongbuk-do': {\n            'lang': Lang.Blocks.location_chungcheongbuk,\n            'sub': [\n                [Lang.Blocks.location_chungcheongbuk_cheongju, 'cheongju'],\n                [Lang.Blocks.location_chungcheongbuk_chungju, 'chungju'],\n                [Lang.Blocks.location_chungcheongbuk_jecheon, 'jecheon'],\n                [Lang.Blocks.location_chungcheongbuk_boeun, 'boeun'],\n                [Lang.Blocks.location_chungcheongbuk_okcheon, 'okcheon'],\n                [Lang.Blocks.location_chungcheongbuk_yeongdong, 'yeongdong'],\n                [Lang.Blocks.location_chungcheongbuk_jeungpyeong, 'jeungpyeong'],\n                [Lang.Blocks.location_chungcheongbuk_jincheon, 'jincheon'],\n                [Lang.Blocks.location_chungcheongbuk_goesan, 'goesan'],\n                [Lang.Blocks.location_chungcheongbuk_eumseong, 'eumseong'],\n                [Lang.Blocks.location_chungcheongbuk_danyang, 'danyang'],\n            ],\n        },\n    };\n    return locationObj;\n}\n\nexports.locationData = getInitialData();\n//도 및 광역시\nexports.getStateOptions = function() {\n    const locationObj = getInitialData();\n    return Object.keys(locationObj.ko).map((k) => [locationObj.ko[k].lang, k]);\n};\n\n//시군구\nexports.getCityOptions = function(state) {\n    const locationObj = getInitialData();\n    const init = [locationObj.initialData];\n    if (locationObj.ko[state]) {\n\n        return [...init, ...locationObj.ko[state].sub];\n    }\n    return [...init, ...locationObj.ko.Seoul.sub];\n};\n"
  },
  {
    "path": "src/util/mediaPipeUtils.ts",
    "content": "import singleInstance from '../core/singleInstance';\nimport { GEHelper } from '../graphicEngine/GEHelper';\nimport {\n    FilesetResolver,\n    DrawingUtils,\n    GestureRecognizer,\n    GestureRecognizerResult,\n    PoseLandmarker,\n    PoseLandmarkerResult,\n    ObjectDetector,\n    ObjectDetectorResult,\n    Detection,\n} from '@mediapipe/tasks-vision';\nimport { UAParser } from 'ua-parser-js';\nimport _clamp from 'lodash/clamp';\nimport _get from 'lodash/get';\nimport VideoMotionWorker from './workers/newmotion.worker.ts';\n\nexport const getInputList = async () => {\n    if (navigator.mediaDevices) {\n        return (await navigator.mediaDevices.enumerateDevices()) || [];\n    }\n    return [];\n};\n\nconst parser = new UAParser();\n\nexport const flipState = {\n    NORMAL: 0,\n    HORIZONTAL: 1,\n    VERTICAL: 2,\n    BOTH: 3,\n};\ntype FLIP_NORMAL = 0;\ntype FLIP_HORIZONTAL = 1;\ntype FLIP_VERTICAL = 2;\ntype FLIP_BOTH = 3;\ntype TFlipState = FLIP_NORMAL | FLIP_HORIZONTAL | FLIP_VERTICAL | FLIP_BOTH;\n\ntype TGestureRecognitionOption = {\n    isDrawDetectedHand?: boolean;\n};\n\ntype MotionElement = {\n    total: number;\n    direction: {\n        x: number;\n        y: number;\n    };\n};\n\ntype Pixel = {\n    r: number;\n    g: number;\n    b: number;\n    rDiff: number;\n    gDiff: number;\n    bDiff: number;\n};\n\ntype TNames = {\n    [key: string]: string;\n};\n\nconst flipActions = {\n    [flipState.NORMAL]: {\n        [flipState.HORIZONTAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.hFlipVideoElement(videos);\n        },\n        [flipState.VERTICAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.vFlipVideoElement(videos);\n        },\n        [flipState.BOTH]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.hFlipVideoElement(videos);\n            GEHelper.vFlipVideoElement(videos);\n        },\n    },\n    [flipState.HORIZONTAL]: {\n        [flipState.NORMAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.hFlipVideoElement(videos);\n        },\n        [flipState.VERTICAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.hFlipVideoElement(videos);\n            GEHelper.vFlipVideoElement(videos);\n        },\n        [flipState.BOTH]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.vFlipVideoElement(videos);\n        },\n    },\n    [flipState.VERTICAL]: {\n        [flipState.NORMAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.vFlipVideoElement(videos);\n        },\n        [flipState.HORIZONTAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.hFlipVideoElement(videos);\n            GEHelper.vFlipVideoElement(videos);\n        },\n        [flipState.BOTH]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.hFlipVideoElement(videos);\n        },\n    },\n    [flipState.BOTH]: {\n        [flipState.NORMAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.hFlipVideoElement(videos);\n            GEHelper.vFlipVideoElement(videos);\n        },\n        [flipState.HORIZONTAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.vFlipVideoElement(videos);\n        },\n        [flipState.VERTICAL]: (videos: PIXI.Sprite[] | createjs.Bitmap[]) => {\n            GEHelper.hFlipVideoElement(videos);\n        },\n    },\n};\n\nconst colors = [\n    'rgb(66, 133, 244)',\n    'rgb(36, 193, 224)',\n    'rgb(52, 168, 83)',\n    'rgb(161, 66, 244)',\n    'rgb(244, 57, 160)',\n    'rgb(234, 67, 53)',\n    'rgb(250, 123, 23)',\n    'rgb(252, 201, 52)',\n];\n\nclass MediaPipeUtils {\n    public isInitialized: boolean = false;\n    public videoInputList: string[][] = [];\n    public canvasVideo: PIXI.Sprite | createjs.Bitmap;\n    public video: HTMLVideoElement;\n    public videoCanvas: HTMLCanvasElement;\n    public videoCanvasCtx: CanvasRenderingContext2D;\n    public motionCanvas: HTMLCanvasElement;\n    public motionOffscreenCanvas: HTMLCanvasElement;\n    public canWorker: boolean = true;\n    public flipState: TFlipState = 0;\n    private VIDEO_WIDTH: number = 640;\n    private VIDEO_HEIGHT: number = 360;\n    private STAGE_WIDTH: number = 480;\n    private STAGE_HEIGHT: number = 260;\n    private SAMPLE_SIZE: number = 15;\n    private stream: MediaStream;\n    private lastVideoTime: number = -1;\n    private sourceTarget: number;\n\n    public countDetectedHand: number;\n    public isPrevHandDetected: boolean = false;\n    public isRunningHandGesture: boolean = false;\n    public isDrawDetectedHand: boolean = false;\n    private isInitGestureRecognition: boolean = false;\n    private gestureRecognizerVideoCanvas: HTMLCanvasElement;\n    private gestureRecognizerVideoCanvasCtx: CanvasRenderingContext2D;\n    private gestureRecognizerCanvasOverlay: PIXI.Sprite | createjs.Bitmap;\n    private gestureRecognizerOffscreenCanvas: OffscreenCanvas;\n    private gestureRecognizerWorker: Worker;\n    private alreadyInitGestureRecognizerOffscreenCanvas: boolean = false;\n    private gestureRecognizerDrawingUtils: DrawingUtils;\n    private prevGestureRecognizerResult: GestureRecognizerResult;\n    private gestureRecognizer: GestureRecognizer;\n\n    public countDetectedPose: number;\n    public isPrevPoseLandmarker: boolean = false;\n    public isRunningPoseLandmarker: boolean = false;\n    public isDrawDetectedPoseLandmarker: boolean = false;\n    private isInitPoseLandmarker: boolean = false;\n    private poseLandmarkerVideoCanvas: HTMLCanvasElement;\n    private poseLandmarkerVideoCanvasCtx: CanvasRenderingContext2D;\n    private poseLandmarkerCanvasOverlay: PIXI.Sprite | createjs.Bitmap;\n    private poseLandmarkerOffscreenCanvas: OffscreenCanvas;\n    private poseLandmarkerWorker: Worker;\n    private alreadyInitPoseLandmarkerOffscreenCanvas: boolean = false;\n    private poseLandmarkerDrawingUtils: DrawingUtils;\n    private prevPoseLandmarkerResult: PoseLandmarkerResult;\n    private poseLandmarker: PoseLandmarker;\n\n    public countDetectedFace: number;\n    public isPrevFaceLandmarker: boolean = false;\n    public isRunWorkerFaceLandmarker: boolean = false;\n    public isRunningFaceLandmarker: boolean = false;\n    public isDrawDetectedFaceLandmarker: boolean = false;\n    private isInitFaceLandmarker: boolean = false;\n    private faceLandmarkerVideoCanvas: HTMLCanvasElement;\n    private faceLandmarkerCanvasOverlay: PIXI.Sprite | createjs.Bitmap;\n    private faceLandmarkerOffscreenCanvas: OffscreenCanvas;\n    private faceLandmarkerWorker: Worker;\n    private alreadyInitFaceLandmarkerOffscreenCanvas: boolean = false;\n    private prevFaceLandmarkerResult: any;\n\n    public countDetectedObject: number;\n    public isPrevObjectDetector: boolean = false;\n    public isRunningObjectDetector: boolean = false;\n    public isDrawDetectedObjectDetector: boolean = false;\n    private isInitObjectDetector: boolean = false;\n    private objectDetectorVideoCanvas: HTMLCanvasElement;\n    private objectDetectorVideoCanvasCtx: CanvasRenderingContext2D;\n    private objectDetectorCanvasOverlay: PIXI.Sprite | createjs.Bitmap;\n    private objectDetectorOffscreenCanvas: OffscreenCanvas;\n    private objectDetectorWorker: Worker;\n    private alreadyInitObjectDetectorOffscreenCanvas: boolean = false;\n    private prevObjectDetectorResult: ObjectDetectorResult;\n    private objectDetector: ObjectDetector;\n\n    public totalMotions: MotionElement = { total: 0, direction: { x: 0, y: 0 } };\n    public motions: Pixel[][] = [\n        ...Array(Math.ceil(this.STAGE_HEIGHT / this.SAMPLE_SIZE)),\n    ].map((e) => Array(this.STAGE_WIDTH / this.SAMPLE_SIZE));\n    public motionWorker: Worker = new VideoMotionWorker();\n\n    constructor() {\n        const uaResult = parser.getResult();\n        if (uaResult.browser.name === 'Safari' || uaResult.os.name === 'iOS') {\n            this.canWorker = false;\n        }\n    }\n\n    get isRunning() {\n        return Boolean(this.video.srcObject);\n    }\n\n    get allCanvases(): PIXI.Sprite[] | createjs.Bitmap[] {\n        return [\n            this.canvasVideo,\n            this.gestureRecognizerCanvasOverlay,\n            this.poseLandmarkerCanvasOverlay,\n            this.faceLandmarkerCanvasOverlay,\n            this.objectDetectorCanvasOverlay,\n        ] as PIXI.Sprite[] | createjs.Bitmap[];\n    }\n\n    get overlayCanvases(): PIXI.Sprite[] | createjs.Bitmap[] {\n        return [\n            this.gestureRecognizerCanvasOverlay,\n            this.poseLandmarkerCanvasOverlay,\n            this.faceLandmarkerCanvasOverlay,\n            this.objectDetectorCanvasOverlay,\n        ] as PIXI.Sprite[] | createjs.Bitmap[];\n    }\n\n    changeCanWorker(canWorker: boolean) {\n        this.canWorker = canWorker;\n    }\n\n    async initialize() {\n        if (this.isInitialized) {\n            return;\n        }\n        await this.checkPermission();\n        const inputList = await getInputList();\n        this.videoInputList = inputList\n            .filter((input) => input.kind === 'videoinput' && input.deviceId)\n            .map((item) => [item.label, item.deviceId]);\n\n        await this.compatabilityChecker();\n        this.motionCanvas = document.createElement('canvas');\n        this.motionCanvas.width = this.VIDEO_WIDTH;\n        this.motionCanvas.height = this.VIDEO_HEIGHT;\n        const video = document.createElement('video');\n        video.id = 'webCamElement';\n        video.autoplay = true;\n        video.width = this.VIDEO_WIDTH;\n        video.height = this.VIDEO_HEIGHT;\n        this.canvasVideo = GEHelper.getVideoElement(video);\n        GEHelper.hFlipVideoElement(this.allCanvases as PIXI.Sprite[] | createjs.Bitmap[]);\n        this.video = video;\n        Entry.addEventListener('beforeStop', this.reset.bind(this));\n        this.isInitialized = true;\n        this.initMotionWorkerEvent();\n    }\n\n    sleep(ms?: number) {\n        return new Promise((resolve) => {\n            if (ms) {\n                setTimeout(resolve, ms);\n            } else {\n                requestAnimationFrame(resolve);\n            }\n        });\n    }\n\n    initMotionWorkerEvent() {\n        this.motionWorker.onmessage = ({ data }) => {\n            if (data.action === 'init_complete') {\n                this.motionDetect();\n            } else if (data.action === 'next_detect_motion') {\n                this.totalMotions = data.result;\n                setTimeout(this.motionDetect.bind(this), 100);\n            }\n        };\n    }\n\n    cameraOnOff(mode: String) {\n        if (mode === 'on') {\n            this.turnOnWebcam();\n        } else {\n            this.turnOffWebcam();\n        }\n    }\n\n    async changeSource(target: number) {\n        const inputSource = this.videoInputList[target];\n        if (!inputSource) {\n            return;\n        }\n        this.sourceTarget = target;\n        try {\n            this.stream = await this.getVideoStream(inputSource[1]);\n            this.video.srcObject = this.stream;\n            this.video.width = this.VIDEO_WIDTH;\n            this.video.height = this.VIDEO_HEIGHT;\n            this.video.style.transform = 'scaleX(-1)';\n        } catch (err) {\n            console.log(err);\n        }\n    }\n\n    setFlipState(state: TFlipState) {\n        if (!this.canvasVideo) {\n            return;\n        }\n        this.setForceFlipState(this.flipState, state);\n    }\n\n    setForceFlipState(prevState: TFlipState, nextState: TFlipState) {\n        const action = flipActions[prevState][nextState];\n        if (action) {\n            action(this.allCanvases);\n        }\n        this.flipState = nextState;\n    }\n\n    initFlipStateCanvas(canvas: PIXI.Sprite | createjs.Bitmap) {\n        if (this.flipState === 0) {\n            GEHelper.hFlipVideoElement(canvas);\n        } else if (this.flipState === 2) {\n            GEHelper.vFlipVideoElement(canvas);\n            GEHelper.hFlipVideoElement(canvas);\n        } else if (this.flipState === 3) {\n            GEHelper.vFlipVideoElement(canvas);\n        }\n    }\n\n    setOpacityCamera(opacity: number) {\n        GEHelper.setVideoAlpha(this.canvasVideo, opacity);\n    }\n\n    turnOffWebcam() {\n        if (this.video.srcObject) {\n            const stream: MediaStream = this.video.srcObject as MediaStream;\n            stream.getTracks().forEach((track) => {\n                track.stop();\n            });\n            window.requestAnimationFrame(() => {\n                this.video.srcObject = null;\n                this.stream = undefined;\n            });\n        }\n\n        GEHelper.turnOffWebcam(this.canvasVideo);\n        this.overlayCanvases.forEach((canvas: PIXI.Sprite | createjs.Bitmap) => {\n            if (canvas) {\n                GEHelper.turnOffOverlay(canvas);\n            }\n        });\n        this.setForceFlipState(this.flipState, 0);\n    }\n\n    async getVideoStream(source: string) {\n        const isMobile = typeof window.orientation !== 'undefined';\n        const isPortrait = isMobile && window.screen.orientation.type.includes('portrait');\n        const width = isPortrait ? this.VIDEO_HEIGHT : this.VIDEO_WIDTH;\n        const height = isPortrait ? this.VIDEO_WIDTH : this.VIDEO_HEIGHT;\n        return await navigator.mediaDevices.getUserMedia({\n            video: {\n                deviceId: { exact: source },\n                width,\n                height,\n            },\n        });\n    }\n\n    registerRotateEvent = () => {\n        const isMobile = typeof window.orientation !== 'undefined';\n        const reloadVideo = async () => {\n            if (this.video.srcObject) {\n                const stream: MediaStream = this.video.srcObject as MediaStream;\n                stream.getTracks().forEach((track) => {\n                    track.stop();\n                });\n            }\n\n            const target = this.sourceTarget || 0;\n            const stream = await this.getVideoStream(this.videoInputList[target][1]);\n            this.video.srcObject = stream;\n            this.stream = stream;\n        };\n        if (isMobile && !window.screen.orientation.onchange) {\n            window.screen.orientation.onchange = reloadVideo;\n        }\n    }\n\n    async turnOnWebcam() {\n        let stream;\n        try {\n            const target = this.sourceTarget || 0;\n            stream = await this.getVideoStream(this.videoInputList[target][1]);\n        } catch (err) {\n            throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                Lang.Workspace.check_webcam_error,\n            ]);\n        }\n        this.video.srcObject = stream;\n        this.stream = stream;\n        try {\n            await this.video.play();\n            this.registerRotateEvent();\n        } catch {}\n        GEHelper.drawVideoElement(this.canvasVideo);\n        this.overlayCanvases.forEach((canvas: PIXI.Sprite | createjs.Bitmap) => {\n            if (canvas) {\n                GEHelper.drawOverlayElement(canvas);\n            }\n        });\n        this.motionWorker.postMessage({\n            action: 'init',\n            width: this.VIDEO_WIDTH,\n            height: this.VIDEO_HEIGHT,\n        });\n    }\n\n    async checkPermission() {\n        if (navigator.permissions) {\n            const permission = await navigator.permissions.query({ name: 'camera' });\n            if (permission.state !== 'granted') {\n                await navigator.mediaDevices.getUserMedia({ video: true });\n            }\n        } else {\n            await navigator.mediaDevices.getUserMedia({ video: true });\n        }\n    }\n\n    async compatabilityChecker() {\n        if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n            throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                Lang.Workspace.check_browser_error_video,\n            ]);\n        }\n        if (!this.stream && this.videoInputList.length == 0) {\n            throw new Entry.Utils.IncompatibleError('IncompatibleError', [\n                Lang.Workspace.check_webcam_error,\n            ]);\n        }\n    }\n\n    isFlipState(type: string) {\n        if (type === 'horizontal') {\n            return this.flipState === flipState.BOTH || this.flipState === flipState.HORIZONTAL;\n        } else if (type === 'vertical') {\n            return this.flipState === flipState.BOTH || this.flipState === flipState.VERTICAL;\n        }\n    }\n\n    motionDetect(sprite?: any): Promise<MotionElement> {\n        return new Promise(async (resolve, reject) => {\n            try {\n                if (!this.motionCanvas || !this.isRunning) {\n                    resolve(undefined);\n                    return;\n                }\n                if (this.video.readyState < 2) {\n                    await this.sleep();\n                    resolve(this.motionDetect(sprite));\n                    return;\n                }\n\n                const id = Entry.generateHash();\n                if (sprite) {\n                    const returnMessage = ({ data }: MessageEvent) => {\n                        if (data.action === 'sprite_return' && data.id === id) {\n                            this.motionWorker.removeEventListener('message', returnMessage);\n                            resolve(data.result);\n                        }\n                    };\n                    this.motionWorker.addEventListener('message', returnMessage);\n                }\n                const { STAGE_WIDTH: width, STAGE_HEIGHT: height, SAMPLE_SIZE: sampleSize } = this;\n                const [minX, maxX] = [0, width];\n                const [minY, maxY] = [0, height];\n                const imageBitmap = await createImageBitmap(this.video);\n                this.motionWorker.postMessage({\n                    sprite: sprite && {\n                        x: sprite.x,\n                        y: sprite.y,\n                        width: sprite.width,\n                        height: sprite.height,\n                        scaleX: sprite.scaleX,\n                        scaleY: sprite.scaleY,\n                    },\n                    action: 'motion',\n                    range: {\n                        minX,\n                        maxX,\n                        minY,\n                        maxY,\n                    },\n                    imageBitmap,\n                    flipState: this.flipState,\n                    id,\n                });\n\n                if (!sprite) {\n                    resolve(undefined);\n                }\n            } catch (e) {\n                console.error(e);\n                reject(e);\n            }\n        });\n    }\n\n    getYX(a: number) {\n        return Math.max(1, Math.min(10, 10 * (1 - (a - -0.15) / 0.25) + (1 - (0.1 - a) / 0.25)));\n    }\n\n    async sendImageBitmapForGesture() {\n        if (!this.isRunningHandGesture) {\n            return;\n        }\n        if (this.video.readyState < 2) {\n            await this.sleep();\n            this.sendImageBitmapForGesture();\n            return;\n        }\n        this.gestureRecognizerWorker.postMessage({\n            action: 'gesture_recognizer',\n            imageBitmap: await createImageBitmap(this.video),\n            flipState: this.flipState,\n        });\n    }\n\n    async sendImageBitmapForPoseLandmarker() {\n        if (!this.isRunningPoseLandmarker) {\n            return;\n        }\n        if (this.video.readyState < 2) {\n            await this.sleep();\n            this.sendImageBitmapForPoseLandmarker();\n            return;\n        }\n        this.poseLandmarkerWorker.postMessage({\n            action: 'pose_landmarker',\n            imageBitmap: await createImageBitmap(this.video),\n            flipState: this.flipState,\n        });\n    }\n\n    async sendImageBitmapForFaceLandmarker() {\n        if (!this.isRunningFaceLandmarker) {\n            return;\n        }\n        if (this.video.readyState < 2) {\n            await this.sleep();\n            this.sendImageBitmapForFaceLandmarker();\n            return;\n        }\n        this.faceLandmarkerWorker.postMessage({\n            action: 'face_landmarker',\n            imageBitmap: await createImageBitmap(this.video),\n            flipState: this.flipState,\n        });\n    }\n\n    async sendImageBitmapForObjectDetector() {\n        if (!this.isRunningObjectDetector) {\n            return;\n        }\n        if (this.video.readyState < 2) {\n            await this.sleep();\n            this.sendImageBitmapForObjectDetector();\n            return;\n        }\n        this.objectDetectorWorker.postMessage({\n            action: 'object_detector',\n            imageBitmap: await createImageBitmap(this.video),\n            flipState: this.flipState,\n        });\n    }\n\n    initGestureRecognitionWorkerEvent() {\n        this.gestureRecognizerWorker.addEventListener('message', ({ data }) => {\n            if (!this.isRunningHandGesture) {\n                return;\n            }\n            if (['next_gesture_recognizer'].includes(data.action)) {\n                if (GEHelper.isWebGL) {\n                    (this.gestureRecognizerCanvasOverlay as PIXI.Sprite).texture.update();\n                }\n                this.sendImageBitmapForGesture();\n            } else if (data.action === 'start_gesture_recognizer') {\n                this.isPrevHandDetected = true;\n                Entry.engine.fireEvent('when_hand_detection');\n            } else if (data.action === 'stop_gesture_recognizer') {\n                this.countDetectedHand = 0;\n                this.isPrevHandDetected = false;\n            } else if (data.action === 'count_detected_hand_gesture_recognizer') {\n                this.countDetectedHand = data.count;\n            } else if (data.action === 'gesture_recognizer_data') {\n                this.prevGestureRecognizerResult = data.gestureRecognizerResult;\n            }\n        });\n    }\n\n    initPoseLandmarkerWorkerEvent() {\n        this.poseLandmarkerWorker.addEventListener('message', ({ data }) => {\n            if (!this.isRunningPoseLandmarker) {\n                return;\n            }\n            if (['next_pose_landmarker'].includes(data.action)) {\n                if (GEHelper.isWebGL) {\n                    (this.poseLandmarkerCanvasOverlay as PIXI.Sprite).texture.update();\n                }\n                this.sendImageBitmapForPoseLandmarker();\n            } else if (data.action === 'start_pose_landmarker') {\n                this.isPrevPoseLandmarker = true;\n                Entry.engine.fireEvent('when_pose_landmarker');\n            } else if (data.action === 'stop_pose_landmarker') {\n                this.countDetectedPose = 0;\n                this.isPrevPoseLandmarker = false;\n            } else if (data.action === 'count_detected_pose_landmarker') {\n                this.countDetectedPose = data.count;\n            } else if (data.action === 'pose_landmarker_data') {\n                this.prevPoseLandmarkerResult = data.poseLandmarkerResult;\n            }\n        });\n    }\n\n    initFaceLandmarkerWorkerEvent() {\n        this.faceLandmarkerWorker.addEventListener('message', ({ data }) => {\n            if (!this.isRunningFaceLandmarker) {\n                return;\n            }\n            if (['next_face_landmarker'].includes(data.action)) {\n                if (GEHelper.isWebGL) {\n                    (this.faceLandmarkerCanvasOverlay as PIXI.Sprite).texture.update();\n                }\n                this.sendImageBitmapForFaceLandmarker();\n            } else if (data.action === 'run_start_face_landmarker') {\n                this.isRunWorkerFaceLandmarker = true;\n            } else if (data.action === 'run_stop_face_landmarker') {\n                this.isRunWorkerFaceLandmarker = false;\n            } else if (data.action === 'start_face_landmarker') {\n                this.isPrevFaceLandmarker = true;\n                Entry.engine.fireEvent('when_face_landmarker');\n            } else if (data.action === 'stop_face_landmarker') {\n                this.countDetectedFace = 0;\n                this.isPrevFaceLandmarker = false;\n            } else if (data.action === 'count_detected_face_landmarker') {\n                this.countDetectedFace = data.count;\n            } else if (data.action === 'face_landmarker_data') {\n                this.prevFaceLandmarkerResult = data.faceLandmarkerResult;\n            }\n        });\n    }\n\n    initObjectDetectorWorkerEvent() {\n        this.objectDetectorWorker.addEventListener('message', ({ data }) => {\n            if (!this.isRunningObjectDetector) {\n                return;\n            }\n            if (['next_object_detector'].includes(data.action)) {\n                if (GEHelper.isWebGL) {\n                    (this.objectDetectorCanvasOverlay as PIXI.Sprite).texture.update();\n                }\n                this.sendImageBitmapForObjectDetector();\n            } else if (data.action === 'start_object_detector') {\n                this.isPrevObjectDetector = true;\n                Entry.engine.fireEvent('when_object_detector');\n            } else if (data.action === 'stop_object_detector') {\n                this.countDetectedObject = 0;\n                this.isPrevObjectDetector = false;\n            } else if (data.action === 'count_detected_object_detector') {\n                this.countDetectedObject = data.count;\n            } else if (data.action === 'object_detector_data') {\n                this.prevObjectDetectorResult = data.objectDetectorResult;\n            }\n        });\n    }\n\n    initHandGestureRecognition() {\n        this.isInitGestureRecognition = true;\n        this.gestureRecognizerVideoCanvas = document.createElement('canvas');\n        this.gestureRecognizerVideoCanvas.width = this.VIDEO_WIDTH;\n        this.gestureRecognizerVideoCanvas.height = this.VIDEO_HEIGHT;\n        this.gestureRecognizerCanvasOverlay = GEHelper.getOverlayElement(\n            this.gestureRecognizerVideoCanvas\n        );\n        GEHelper.drawOverlayElement(this.gestureRecognizerCanvasOverlay);\n        this.initFlipStateCanvas(this.gestureRecognizerCanvasOverlay);\n        if (this.canWorker) {\n            // eslint-disable-next-line max-len\n            this.gestureRecognizerOffscreenCanvas = this.gestureRecognizerVideoCanvas.transferControlToOffscreen();\n            this.gestureRecognizerWorker = new Worker(\n                `${Entry.Utils.getEntryjsPath()}/extern/gesture-recognition.worker.js`\n            );\n            this.initGestureRecognitionWorkerEvent();\n        } else {\n            this.gestureRecognizerVideoCanvasCtx = this.gestureRecognizerVideoCanvas.getContext(\n                '2d'\n            );\n            this.gestureRecognizerVideoCanvasCtx.font = '20px Arial';\n            this.gestureRecognizerDrawingUtils = new DrawingUtils(\n                this.gestureRecognizerVideoCanvasCtx\n            );\n        }\n    }\n\n    initPoseLandmarker() {\n        this.isInitPoseLandmarker = true;\n        this.poseLandmarkerVideoCanvas = document.createElement('canvas');\n        this.poseLandmarkerVideoCanvas.width = this.VIDEO_WIDTH;\n        this.poseLandmarkerVideoCanvas.height = this.VIDEO_HEIGHT;\n        this.poseLandmarkerCanvasOverlay = GEHelper.getOverlayElement(\n            this.poseLandmarkerVideoCanvas\n        );\n        GEHelper.drawOverlayElement(this.poseLandmarkerCanvasOverlay);\n        this.initFlipStateCanvas(this.poseLandmarkerCanvasOverlay);\n        if (this.canWorker) {\n            // eslint-disable-next-line max-len\n            this.poseLandmarkerOffscreenCanvas = this.poseLandmarkerVideoCanvas.transferControlToOffscreen();\n            this.poseLandmarkerWorker = new Worker(\n                `${Entry.Utils.getEntryjsPath()}/extern/pose-landmarker.worker.js`\n            );\n            this.initPoseLandmarkerWorkerEvent();\n        } else {\n            this.poseLandmarkerVideoCanvasCtx = this.poseLandmarkerVideoCanvas.getContext('2d');\n            this.poseLandmarkerVideoCanvasCtx.font = '20px Arial';\n            this.poseLandmarkerDrawingUtils = new DrawingUtils(this.poseLandmarkerVideoCanvasCtx);\n        }\n    }\n\n    initFaceLandmarker() {\n        this.isInitFaceLandmarker = true;\n        this.faceLandmarkerVideoCanvas = document.createElement('canvas');\n        this.faceLandmarkerVideoCanvas.width = this.VIDEO_WIDTH;\n        this.faceLandmarkerVideoCanvas.height = this.VIDEO_HEIGHT;\n        this.faceLandmarkerCanvasOverlay = GEHelper.getOverlayElement(\n            this.faceLandmarkerVideoCanvas\n        );\n        GEHelper.drawOverlayElement(this.faceLandmarkerCanvasOverlay);\n        this.initFlipStateCanvas(this.faceLandmarkerCanvasOverlay);\n        // eslint-disable-next-line max-len\n        this.faceLandmarkerOffscreenCanvas = this.faceLandmarkerVideoCanvas.transferControlToOffscreen();\n        this.faceLandmarkerWorker = new Worker(\n            `${Entry.Utils.getEntryjsPath()}/extern/face-landmarker.worker.js`\n        );\n        this.initFaceLandmarkerWorkerEvent();\n    }\n\n    initObjectDetector() {\n        this.isInitObjectDetector = true;\n        this.objectDetectorVideoCanvas = document.createElement('canvas');\n        this.objectDetectorVideoCanvas.width = this.VIDEO_WIDTH;\n        this.objectDetectorVideoCanvas.height = this.VIDEO_HEIGHT;\n        this.objectDetectorCanvasOverlay = GEHelper.getOverlayElement(\n            this.objectDetectorVideoCanvas\n        );\n        GEHelper.drawOverlayElement(this.objectDetectorCanvasOverlay);\n        this.initFlipStateCanvas(this.objectDetectorCanvasOverlay);\n        if (this.canWorker) {\n            // eslint-disable-next-line max-len\n            this.objectDetectorOffscreenCanvas = this.objectDetectorVideoCanvas.transferControlToOffscreen();\n            this.objectDetectorWorker = new Worker(\n                `${Entry.Utils.getEntryjsPath()}/extern/object-detector.worker.js`\n            );\n            this.initObjectDetectorWorkerEvent();\n        } else {\n            this.objectDetectorVideoCanvasCtx = this.objectDetectorVideoCanvas.getContext('2d');\n            this.objectDetectorVideoCanvasCtx.font = '20px Arial';\n        }\n    }\n\n    async startHandGestureRecognition() {\n        try {\n            if (!this.stream) {\n                await this.turnOnWebcam();\n            }\n            if (!this.isInitGestureRecognition) {\n                this.initHandGestureRecognition();\n            }\n            this.isRunningHandGesture = true;\n\n            if (this.canWorker) {\n                if (!this.alreadyInitGestureRecognizerOffscreenCanvas) {\n                    this.gestureRecognizerWorker.postMessage(\n                        {\n                            action: 'gesture_recognizer_init',\n                            canvas: this.gestureRecognizerOffscreenCanvas,\n                            lang: {\n                                leftHand: Lang.Blocks.left_hand,\n                                rightHand: Lang.Blocks.right_hand,\n                            },\n                            option: {\n                                isDrawDetectedHand: this.isDrawDetectedHand,\n                            },\n                        },\n                        [this.gestureRecognizerOffscreenCanvas]\n                    );\n                    this.alreadyInitGestureRecognizerOffscreenCanvas = true;\n                } else {\n                    this.gestureRecognizerWorker.postMessage({\n                        action: 'gesture_recognizer_restart',\n                    });\n                    this.sendImageBitmapForGesture();\n                }\n            } else {\n                await this.initPredictHandGesture();\n                this.predictHandGesture();\n            }\n        } catch (e) {\n            console.error(e);\n        }\n    }\n\n    async startPoseLandmarker() {\n        try {\n            if (!this.stream) {\n                await this.turnOnWebcam();\n            }\n            if (!this.isInitPoseLandmarker) {\n                this.initPoseLandmarker();\n            }\n            this.isRunningPoseLandmarker = true;\n\n            if (this.canWorker) {\n                if (!this.alreadyInitPoseLandmarkerOffscreenCanvas) {\n                    this.poseLandmarkerWorker.postMessage(\n                        {\n                            action: 'pose_landmarker_init',\n                            canvas: this.poseLandmarkerOffscreenCanvas,\n                            lang: {\n                                person: Lang.video_object_params.person,\n                            },\n                            option: {\n                                isDrawDetectedPoseLandmarker: this.isDrawDetectedPoseLandmarker,\n                            },\n                        },\n                        [this.poseLandmarkerOffscreenCanvas]\n                    );\n                    this.alreadyInitPoseLandmarkerOffscreenCanvas = true;\n                } else {\n                    this.poseLandmarkerWorker.postMessage({\n                        action: 'pose_landmarker_restart',\n                    });\n                    this.sendImageBitmapForPoseLandmarker();\n                }\n            } else {\n                await this.initPredictPoseLandmarker();\n                this.predictPoseLandmarker();\n            }\n        } catch (e) {\n            console.error(e);\n        }\n    }\n\n    async startFaceLandmarker() {\n        try {\n            if (!this.stream) {\n                await this.turnOnWebcam();\n            }\n            if (!this.isInitFaceLandmarker) {\n                this.initFaceLandmarker();\n            }\n            this.isRunningFaceLandmarker = true;\n\n            if (!this.alreadyInitFaceLandmarkerOffscreenCanvas) {\n                const uaResult = parser.getResult();\n                this.faceLandmarkerWorker.postMessage(\n                    {\n                        action: 'face_landmarker_init',\n                        canvas: this.faceLandmarkerOffscreenCanvas,\n                        isSafari: uaResult.browser.name === 'Safari' || uaResult.os.name === 'iOS',\n                        lang: {\n                            face: Lang.Blocks.video_face,\n                        },\n                        option: {\n                            isDrawDetectedFaceLandmarker: this.isDrawDetectedFaceLandmarker,\n                        },\n                    },\n                    [this.faceLandmarkerOffscreenCanvas]\n                );\n                this.alreadyInitFaceLandmarkerOffscreenCanvas = true;\n            } else if (!this.isRunWorkerFaceLandmarker) {\n                this.faceLandmarkerWorker.postMessage({\n                    action: 'face_landmarker_restart',\n                });\n                this.sendImageBitmapForFaceLandmarker();\n            }\n        } catch (e) {\n            console.error(e);\n        }\n    }\n\n    async startObjectDetector() {\n        try {\n            if (!this.stream) {\n                await this.turnOnWebcam();\n            }\n            if (!this.isInitObjectDetector) {\n                this.initObjectDetector();\n            }\n            this.isRunningObjectDetector = true;\n\n            if (this.canWorker) {\n                if (!this.alreadyInitObjectDetectorOffscreenCanvas) {\n                    this.objectDetectorWorker.postMessage(\n                        {\n                            action: 'object_detector_init',\n                            canvas: this.objectDetectorOffscreenCanvas,\n                            lang: {\n                                objectNameList: Lang.video_object_params,\n                            },\n                            option: {\n                                isDrawDetectedObjectDetector: this.isDrawDetectedObjectDetector,\n                            },\n                        },\n                        [this.objectDetectorOffscreenCanvas]\n                    );\n                    this.alreadyInitObjectDetectorOffscreenCanvas = true;\n                } else {\n                    this.objectDetectorWorker.postMessage({\n                        action: 'object_detector_restart',\n                    });\n                    this.sendImageBitmapForObjectDetector();\n                }\n            } else {\n                await this.initPredictObjectDetector();\n                this.predictObjectDetector();\n            }\n        } catch (e) {\n            console.error(e);\n        }\n    }\n\n    changeDrawDetectedHand(isDrawDetectedHand: boolean) {\n        this.isDrawDetectedHand = isDrawDetectedHand;\n        this.updateHandGestureRecognition();\n    }\n\n    changeDrawDetectedPoseLandmarker(isDrawDetectedPoseLandmarker: boolean) {\n        this.isDrawDetectedPoseLandmarker = isDrawDetectedPoseLandmarker;\n        this.updatePoseLandmarker();\n    }\n\n    changeDrawDetectedFaceLandmarker(isDrawDetectedFaceLandmarker: boolean) {\n        this.isDrawDetectedFaceLandmarker = isDrawDetectedFaceLandmarker;\n        this.updateFaceLandmarker();\n    }\n\n    changeDrawDetectedObjectDetector(isDrawDetectedObjectDetector: boolean) {\n        this.isDrawDetectedObjectDetector = isDrawDetectedObjectDetector;\n        this.updateObjectDetector();\n    }\n\n    updateHandGestureRecognition() {\n        if (this.canWorker) {\n            this.gestureRecognizerWorker.postMessage({\n                action: 'gesture_recognizer_change_option',\n                option: {\n                    isDrawDetectedHand: this.isDrawDetectedHand,\n                },\n            });\n        }\n    }\n\n    updatePoseLandmarker() {\n        if (this.canWorker) {\n            this.poseLandmarkerWorker.postMessage({\n                action: 'pose_landmarker_change_option',\n                option: {\n                    isDrawDetectedPoseLandmarker: this.isDrawDetectedPoseLandmarker,\n                },\n            });\n        }\n    }\n\n    updateFaceLandmarker() {\n        this.faceLandmarkerWorker.postMessage({\n            action: 'face_landmarker_change_option',\n            option: {\n                isDrawDetectedFaceLandmarker: this.isDrawDetectedFaceLandmarker,\n            },\n        });\n    }\n\n    updateObjectDetector() {\n        if (this.canWorker) {\n            this.objectDetectorWorker.postMessage({\n                action: 'object_detector_change_option',\n                option: {\n                    isDrawDetectedObjectDetector: this.isDrawDetectedObjectDetector,\n                },\n            });\n        }\n    }\n\n    async stopHandGestureRecognition() {\n        if (this.canWorker) {\n            this.gestureRecognizerWorker.postMessage({\n                action: 'clear_gesture_recognizer',\n            });\n        } else {\n            this.gestureRecognizerVideoCanvasCtx.clearRect(\n                0,\n                0,\n                this.video.width,\n                this.video.height\n            );\n            if (GEHelper.isWebGL) {\n                (this.gestureRecognizerCanvasOverlay as PIXI.Sprite).texture.update();\n            }\n        }\n        this.isRunningHandGesture = false;\n        this.isPrevHandDetected = false;\n        this.countDetectedHand = 0;\n    }\n\n    async stopPoseLandmarker() {\n        if (this.canWorker) {\n            this.poseLandmarkerWorker.postMessage({\n                action: 'clear_pose_landmarker',\n            });\n        } else {\n            this.poseLandmarkerVideoCanvasCtx.clearRect(0, 0, this.video.width, this.video.height);\n            if (GEHelper.isWebGL) {\n                (this.poseLandmarkerCanvasOverlay as PIXI.Sprite).texture.update();\n            }\n        }\n        this.isRunningPoseLandmarker = false;\n        this.isPrevPoseLandmarker = false;\n        this.countDetectedPose = 0;\n    }\n\n    async stopFaceLandmarker() {\n        this.faceLandmarkerWorker.postMessage({\n            action: 'clear_face_landmarker',\n        });\n        this.isRunningFaceLandmarker = false;\n        this.isPrevFaceLandmarker = false;\n        this.isRunWorkerFaceLandmarker = false;\n        this.countDetectedFace = 0;\n    }\n\n    async stopObjectDetector() {\n        if (this.canWorker) {\n            this.objectDetectorWorker.postMessage({\n                action: 'clear_object_detector',\n            });\n        } else {\n            this.objectDetectorVideoCanvasCtx.clearRect(0, 0, this.video.width, this.video.height);\n            if (GEHelper.isWebGL) {\n                (this.objectDetectorCanvasOverlay as PIXI.Sprite).texture.update();\n            }\n        }\n        this.isRunningObjectDetector = false;\n        this.isPrevObjectDetector = false;\n        this.countDetectedObject = 0;\n    }\n\n    async initPredictHandGesture() {\n        const vision = await FilesetResolver.forVisionTasks(\n            `${Entry.Utils.getEntryjsPath()}/extern/wasm`\n        );\n        this.gestureRecognizer = await GestureRecognizer.createFromOptions(vision, {\n            baseOptions: {\n                // eslint-disable-next-line max-len\n                modelAssetPath: `${Entry.Utils.getEntryjsPath()}/extern/model/gesture_recognizer.task`,\n                delegate: 'GPU',\n            },\n            runningMode: 'VIDEO',\n            numHands: 2,\n        });\n    }\n\n    async initPredictPoseLandmarker() {\n        const vision = await FilesetResolver.forVisionTasks(\n            `${Entry.Utils.getEntryjsPath()}/extern/wasm`\n        );\n        this.poseLandmarker = await PoseLandmarker.createFromOptions(vision, {\n            baseOptions: {\n                // eslint-disable-next-line max-len\n                modelAssetPath: `${Entry.Utils.getEntryjsPath()}/extern/model/pose_landmarker_lite.task`,\n                delegate: 'GPU',\n            },\n            runningMode: 'VIDEO',\n            numPoses: 4,\n        });\n    }\n\n    async initPredictObjectDetector() {\n        const vision = await FilesetResolver.forVisionTasks(\n            `${Entry.Utils.getEntryjsPath()}/extern/wasm`\n        );\n        this.objectDetector = await ObjectDetector.createFromOptions(vision, {\n            baseOptions: {\n                // eslint-disable-next-line max-len\n                modelAssetPath: `${Entry.Utils.getEntryjsPath()}/extern/model/object_detector_lite.tflite`,\n                delegate: 'GPU',\n            },\n            runningMode: 'VIDEO',\n            scoreThreshold: 0.5,\n            maxResults: 8,\n        });\n    }\n\n    contextFlip = (context, axis) => {\n        if (this.flipState === 0) {\n            context.scale(-1, 1);\n            return {\n                x: -axis.x * 640,\n                y: axis.y * 360 - 20,\n            };\n        } else if (this.flipState === 1) {\n            context.scale(1, 1);\n            return {\n                x: axis.x * 640,\n                y: axis.y * 360 - 20,\n            };\n        } else if (this.flipState === 2) {\n            context.scale(-1, -1);\n            return {\n                x: -axis.x * 640,\n                y: -axis.y * 360 + 20,\n            };\n        } else if (this.flipState === 3) {\n            context.scale(1, -1);\n            return {\n                x: axis.x * 640,\n                y: -axis.y * 360 + 20,\n            };\n        }\n    };\n\n    async predictHandGesture() {\n        try {\n            let results;\n\n            if (!this.gestureRecognizerVideoCanvasCtx || this.isRunningHandGesture === false) {\n                return;\n            }\n            if (this.video.readyState < 2) {\n                await this.sleep();\n                this.predictHandGesture();\n                return;\n            }\n            if (this.video.currentTime !== this.lastVideoTime) {\n                this.lastVideoTime = this.video.currentTime;\n                const startTimeMs = Date.now();\n                results = this.gestureRecognizer.recognizeForVideo(this.video, startTimeMs);\n            } else {\n                return;\n            }\n            this.gestureRecognizerVideoCanvasCtx.save();\n            this.gestureRecognizerVideoCanvasCtx.clearRect(\n                0,\n                0,\n                this.video.width,\n                this.video.height\n            );\n\n            const { landmarks, handednesses } = results;\n            this.prevGestureRecognizerResult = results;\n            if (landmarks.length) {\n                if (!this.isPrevHandDetected) {\n                    this.isPrevHandDetected = true;\n                    Entry.engine.fireEvent('when_hand_detection');\n                }\n                if (landmarks.length !== this.countDetectedHand) {\n                    this.countDetectedHand = landmarks.length;\n                }\n                if (!this.isDrawDetectedHand) {\n                    return;\n                }\n\n                landmarks.forEach((landmark, i) => {\n                    let connectColor;\n                    let landmarkColor;\n                    const [handedness] = handednesses[i];\n                    const mark12 = landmark[12];\n                    const { x, y } = this.contextFlip(this.gestureRecognizerVideoCanvasCtx, mark12);\n                    if (handedness.categoryName === 'Left') {\n                        this.gestureRecognizerVideoCanvasCtx.fillStyle = '#FF0000';\n                        this.gestureRecognizerVideoCanvasCtx.fillText(\n                            `${i + 1}-${Lang.Blocks.right_hand}`,\n                            x,\n                            y\n                        );\n                        connectColor = '#FF0000';\n                        landmarkColor = '#00FF00';\n                    } else {\n                        this.gestureRecognizerVideoCanvasCtx.fillStyle = '#00FF00';\n                        this.gestureRecognizerVideoCanvasCtx.fillText(\n                            `${i + 1}-${Lang.Blocks.left_hand}`,\n                            x,\n                            y\n                        );\n                        connectColor = '#00FF00';\n                        landmarkColor = '#FF0000';\n                    }\n                    this.contextFlip(this.gestureRecognizerVideoCanvasCtx, mark12);\n                    this.gestureRecognizerDrawingUtils.drawConnectors(\n                        landmark,\n                        GestureRecognizer.HAND_CONNECTIONS,\n                        {\n                            color: connectColor,\n                            lineWidth: 4,\n                        }\n                    );\n                    this.gestureRecognizerDrawingUtils.drawLandmarks(landmark, {\n                        color: connectColor,\n                        lineWidth: 4,\n                        fillColor: landmarkColor,\n                        radius: (e) => this.getYX(e.from!.z || 0),\n                    });\n                });\n            } else {\n                this.isPrevHandDetected = false;\n                this.countDetectedHand = 0;\n            }\n        } finally {\n            if (GEHelper.isWebGL) {\n                (this.gestureRecognizerCanvasOverlay as PIXI.Sprite).texture.update();\n            }\n            this.gestureRecognizerVideoCanvasCtx.restore();\n            if (this.isRunningHandGesture === true) {\n                window.requestAnimationFrame(this.predictHandGesture.bind(this));\n            }\n        }\n    }\n\n    async predictPoseLandmarker() {\n        try {\n            let results;\n\n            if (!this.poseLandmarkerVideoCanvasCtx || this.isRunningPoseLandmarker === false) {\n                return;\n            }\n            if (this.video.readyState < 2) {\n                await this.sleep();\n                this.predictPoseLandmarker();\n                return;\n            }\n            if (this.video.currentTime !== this.lastVideoTime) {\n                this.lastVideoTime = this.video.currentTime;\n                const startTimeMs = performance.now();\n                results = await this.poseLandmarker.detectForVideo(this.video, startTimeMs);\n            } else {\n                return;\n            }\n            this.poseLandmarkerVideoCanvasCtx.save();\n            this.poseLandmarkerVideoCanvasCtx.clearRect(0, 0, this.video.width, this.video.height);\n\n            const { landmarks } = results;\n            this.prevPoseLandmarkerResult = results;\n            if (landmarks.length) {\n                if (!this.isPrevPoseLandmarker) {\n                    this.isPrevPoseLandmarker = true;\n                    Entry.engine.fireEvent('when_pose_landmarker');\n                }\n                if (landmarks.length !== this.countDetectedPose) {\n                    this.countDetectedPose = landmarks.length;\n                }\n                if (!this.isDrawDetectedPoseLandmarker) {\n                    return;\n                }\n\n                landmarks.forEach((landmark, i) => {\n                    const mark7 = landmark[7];\n                    this.poseLandmarkerVideoCanvasCtx.scale(-1, 1);\n                    this.poseLandmarkerVideoCanvasCtx.fillStyle = '#FF0000';\n                    this.poseLandmarkerVideoCanvasCtx.fillText(\n                        `${i + 1}-${Lang.video_object_params.person}`,\n                        -mark7.x * 640,\n                        mark7.y * 360 - 20\n                    );\n                    this.poseLandmarkerVideoCanvasCtx.scale(-1, 1);\n                    this.poseLandmarkerDrawingUtils.drawLandmarks(landmark, {\n                        radius: (data) => DrawingUtils.lerp(data.from!.z, -0.15, 0.1, 5, 1),\n                    });\n                    this.poseLandmarkerDrawingUtils.drawConnectors(\n                        landmark,\n                        PoseLandmarker.POSE_CONNECTIONS\n                    );\n                });\n            } else {\n                this.isPrevPoseLandmarker = false;\n                this.countDetectedPose = 0;\n            }\n        } catch (e) {\n            console.error(e);\n        } finally {\n            if (GEHelper.isWebGL) {\n                (this.poseLandmarkerCanvasOverlay as PIXI.Sprite).texture.update();\n            }\n            this.poseLandmarkerVideoCanvasCtx.restore();\n            if (this.isRunningPoseLandmarker === true) {\n                window.requestAnimationFrame(this.predictPoseLandmarker.bind(this));\n            }\n        }\n    }\n\n    async predictObjectDetector() {\n        try {\n            let results;\n\n            if (!this.objectDetectorVideoCanvasCtx || this.isRunningObjectDetector === false) {\n                return;\n            }\n            if (this.video.readyState < 2) {\n                await this.sleep();\n                this.predictObjectDetector();\n                return;\n            }\n            if (this.video.currentTime !== this.lastVideoTime) {\n                this.lastVideoTime = this.video.currentTime;\n                const startTimeMs = performance.now();\n                results = await this.objectDetector.detectForVideo(this.video, startTimeMs);\n            } else {\n                return;\n            }\n            this.objectDetectorVideoCanvasCtx.save();\n            this.objectDetectorVideoCanvasCtx.clearRect(0, 0, this.video.width, this.video.height);\n\n            const { detections } = results;\n            this.prevObjectDetectorResult = results;\n            if (detections.length) {\n                if (!this.isPrevObjectDetector) {\n                    this.isPrevObjectDetector = true;\n                    Entry.engine.fireEvent('when_face_landmarker');\n                }\n                if (detections.length !== this.countDetectedObject) {\n                    this.countDetectedObject = detections.length;\n                }\n                if (!this.isDrawDetectedObjectDetector) {\n                    return;\n                }\n                detections.forEach((detect, i) => {\n                    this.drawObjectDetections(detect, i);\n                });\n            } else {\n                this.isPrevObjectDetector = false;\n                this.countDetectedObject = 0;\n            }\n        } catch (e) {\n            console.error(e);\n        } finally {\n            if (GEHelper.isWebGL) {\n                (this.objectDetectorCanvasOverlay as PIXI.Sprite).texture.update();\n            }\n            this.objectDetectorVideoCanvasCtx.restore();\n            if (this.isRunningObjectDetector === true) {\n                window.requestAnimationFrame(this.predictObjectDetector.bind(this));\n            }\n        }\n    }\n\n    objectContextFlip(context, axis) {\n        if (this.flipState === 0) {\n            context.scale(-1, 1);\n            return {\n                x: -axis.x - axis.offsetX,\n                y: axis.y - axis.offsetY,\n            };\n        } else if (this.flipState === 1) {\n            context.scale(1, 1);\n            return {\n                x: axis.x + 3,\n                y: axis.y - axis.offsetY,\n            };\n        } else if (this.flipState === 2) {\n            context.scale(-1, -1);\n            return {\n                x: -axis.x - axis.offsetX,\n                y: -(axis.y - axis.offsetY - 6),\n            };\n        } else if (this.flipState === 3) {\n            context.scale(1, -1);\n            return {\n                x: axis.x + 3,\n                y: -(axis.y - axis.offsetY - 6),\n            };\n        }\n    }\n\n    drawObjectDetections(detect: Detection, i: number) {\n        try {\n            const { boundingBox, categories } = detect;\n            const [category] = categories;\n            const displayName = category.displayName || category.categoryName;\n            const text = Lang.video_object_params[displayName] || displayName;\n\n            const x = boundingBox.originX;\n            const y = boundingBox.originY;\n            const w = boundingBox.width;\n            const h = boundingBox.height;\n            const e = (this.VIDEO_WIDTH / 600) * 4;\n            const measureText = this.objectDetectorVideoCanvasCtx.measureText(text);\n            const l = measureText.width + 6;\n            const measureSize =\n                measureText.fontBoundingBoxAscent + measureText.fontBoundingBoxDescent + 2 * e;\n            const m = x + w - l;\n            this.objectDetectorVideoCanvasCtx.strokeStyle = colors[i];\n            this.objectDetectorVideoCanvasCtx.beginPath();\n            this.objectDetectorVideoCanvasCtx.moveTo(x, y);\n            this.objectDetectorVideoCanvasCtx.lineTo(x + w, y);\n            this.objectDetectorVideoCanvasCtx.lineTo(x + w, y + h);\n            this.objectDetectorVideoCanvasCtx.lineTo(x, y + h);\n            this.objectDetectorVideoCanvasCtx.lineTo(x, y);\n            this.objectDetectorVideoCanvasCtx.stroke();\n            this.objectDetectorVideoCanvasCtx.fillStyle = colors[i];\n            this.objectDetectorVideoCanvasCtx.fillRect(m, y, l, measureSize);\n            const { x: axisX, y: axisY } = this.objectContextFlip(\n                this.objectDetectorVideoCanvasCtx,\n                {\n                    offsetX: l - 3,\n                    offsetY: 3 * e,\n                    x: m,\n                    y: y + measureSize,\n                }\n            );\n            this.objectDetectorVideoCanvasCtx.fillStyle = 'white';\n            this.objectDetectorVideoCanvasCtx.fillText(text, axisX, axisY);\n            this.objectContextFlip(this.objectDetectorVideoCanvasCtx, {\n                offsetX: 0,\n                offsetY: 0,\n                x: 0,\n                y: 0,\n            });\n        } catch (e) {\n            console.error(e.stack);\n        }\n    }\n\n    getFlipDirectionToSign() {\n        if (this.flipState === 0) {\n            return {\n                x: 1,\n                y: 1,\n            };\n        } else if (this.flipState === 1) {\n            return {\n                x: -1,\n                y: 1,\n            };\n        } else if (this.flipState === 2) {\n            return {\n                x: 1,\n                y: -1,\n            };\n        } else if (this.flipState === 3) {\n            return {\n                x: -1,\n                y: -1,\n            };\n        }\n    }\n\n    getHandPointAxis(hand: number, handPoint: number) {\n        if (!this.prevGestureRecognizerResult) {\n            return;\n        }\n        const { landmarks } = this.prevGestureRecognizerResult;\n        if (!landmarks.length) {\n            return;\n        }\n        const landmark = landmarks[hand];\n        const pointAxis = landmark[handPoint];\n        const sign = this.getFlipDirectionToSign();\n        return {\n            x: (-pointAxis.x * this.STAGE_WIDTH + this.STAGE_WIDTH / 2) * sign.x,\n            y: (-pointAxis.y * this.STAGE_HEIGHT + this.STAGE_HEIGHT / 2) * sign.y,\n            z: pointAxis.z,\n        };\n    }\n\n    getPosePointAxis(pose: number, posePoint: number) {\n        if (!this.prevPoseLandmarkerResult) {\n            return;\n        }\n        const { landmarks } = this.prevPoseLandmarkerResult;\n        if (!landmarks.length) {\n            return;\n        }\n        const landmark = landmarks[pose];\n        const pointAxis = landmark[posePoint];\n        const sign = this.getFlipDirectionToSign();\n        return {\n            x: (-pointAxis.x * this.STAGE_WIDTH + this.STAGE_WIDTH / 2) * sign.x,\n            y: (-pointAxis.y * this.STAGE_HEIGHT + this.STAGE_HEIGHT / 2) * sign.y,\n            z: pointAxis.z,\n        };\n    }\n\n    getFacePointAxis(faceNum: number, facePoint: number) {\n        if (!this.prevFaceLandmarkerResult) {\n            return;\n        }\n        const { face = [] } = this.prevFaceLandmarkerResult;\n        if (!face.length) {\n            return;\n        }\n        const meshRaw = _get(face, `${faceNum}.meshRaw`);\n        if (!meshRaw) {\n            return;\n        }\n        const pointAxis = meshRaw[facePoint];\n        const sign = this.getFlipDirectionToSign();\n        return {\n            x: (-pointAxis[0] * this.STAGE_WIDTH + this.STAGE_WIDTH / 2) * sign.x,\n            y: (-pointAxis[1] * this.STAGE_HEIGHT + this.STAGE_HEIGHT / 2) * sign.y,\n            z: pointAxis[2],\n        };\n    }\n\n    getFaceGender(faceNum: number) {\n        if (!this.prevFaceLandmarkerResult) {\n            return;\n        }\n        const { face = [] } = this.prevFaceLandmarkerResult;\n        if (!face.length) {\n            return;\n        }\n        return _get(face, `${faceNum}.gender`);\n    }\n\n    getFaceAge(faceNum: number) {\n        if (!this.prevFaceLandmarkerResult) {\n            return;\n        }\n        const { face = [] } = this.prevFaceLandmarkerResult;\n        if (!face.length) {\n            return;\n        }\n        return Math.round(_get(face, `${faceNum}.age`, 0));\n    }\n\n    getFaceEmotion(faceNum: number) {\n        if (!this.prevFaceLandmarkerResult) {\n            return;\n        }\n        const { face = [] } = this.prevFaceLandmarkerResult;\n        if (!face.length) {\n            return;\n        }\n        return _get(face, `${faceNum}.emotion.0.emotion`);\n    }\n\n    getObjectPointAxis(face: number, facePoint: number) {\n        if (!this.prevObjectDetectorResult) {\n            return;\n        }\n        const { detections } = this.prevObjectDetectorResult;\n        if (!detections.length) {\n            return;\n        }\n        const detect = detections[face];\n        return detect.boundingBox;\n    }\n\n    getHandedness(hand: number) {\n        if (!this.prevGestureRecognizerResult) {\n            return;\n        }\n        const { handednesses } = this.prevGestureRecognizerResult;\n        if (!handednesses.length) {\n            return;\n        }\n        return handednesses[hand][0];\n    }\n\n    getGesture(hand: number) {\n        if (!this.prevGestureRecognizerResult) {\n            return;\n        }\n        const { gestures } = this.prevGestureRecognizerResult;\n        if (!gestures.length) {\n            return;\n        }\n        return gestures[hand][0];\n    }\n\n    reset() {\n        if (this.isInitGestureRecognition) {\n            this.changeDrawDetectedHand(false);\n            this.stopHandGestureRecognition();\n            this.prevGestureRecognizerResult = undefined;\n        }\n        if (this.isInitPoseLandmarker) {\n            this.changeDrawDetectedPoseLandmarker(false);\n            this.stopPoseLandmarker();\n            this.prevPoseLandmarkerResult = undefined;\n        }\n        if (this.isInitFaceLandmarker) {\n            this.changeDrawDetectedFaceLandmarker(false);\n            this.stopFaceLandmarker();\n            this.prevFaceLandmarkerResult = undefined;\n        }\n        if (this.isInitObjectDetector) {\n            this.changeDrawDetectedObjectDetector(false);\n            this.stopObjectDetector();\n            this.prevObjectDetectorResult = undefined;\n        }\n        GEHelper.setVideoAlpha(this.canvasVideo, 50);\n        this.turnOffWebcam();\n    }\n\n    destroy() {\n        this.isInitialized = false;\n    }\n}\n\nexport default singleInstance(MediaPipeUtils);\n"
  },
  {
    "path": "src/util/modal.js",
    "content": "Entry.Modal = class EntryModal {\n    #modal = null;\n    #isLmsModal = false;\n\n    get modal() {\n        if (!this.#modal) {\n            if (window.EntryModal) {\n                this.#modal = window.EntryModal;\n            } else {\n                this.#modal = entrylms;\n                this.#isLmsModal = true;\n            }\n        }\n        return this.#modal;\n    }\n\n    alert(content, title, options) {\n        if (this.#isLmsModal) {\n            return new Promise((resolve) => {\n                this.modal.alert(content, title, options).on('hide', (result) => resolve(result));\n            });\n        }\n        return this.modal.alert(content, title, options);\n    }\n\n    confirm(content, title, options) {\n        return this.modal.confirm(content, title, options);\n    }\n};\n"
  },
  {
    "path": "src/util/restrictor.js",
    "content": "'use strict';\n\nEntry.Restrictor = class Restrictor {\n    constructor(controller) {\n        this._controller = controller;\n        this.startEvent = new Entry.Event(this);\n        this.endEvent = new Entry.Event(this);\n\n        Entry.Curtain.init(controller && controller.isRestrictorCloseable);\n\n        this.currentTooltip = null;\n    }\n    restrict(data, toolTipRender) {\n        this._data = data;\n        Entry.expectedAction = data.content.concat();\n        this.toolTipRender = toolTipRender;\n\n        this.end();\n\n        const log = data.content.concat();\n        const commandType = log.shift();\n        const command = Entry.Command[commandType];\n\n        let domQuery = command.dom;\n        this.startEvent.notify();\n        if (domQuery instanceof Array) {\n            domQuery = this.processDomQuery(domQuery);\n        }\n\n        if (!data.tooltip) {\n            data.tooltip = {\n                title: '액션',\n                content: '지시 사항을 따르시오',\n            };\n        }\n\n        if (command.restrict) {\n            this.currentTooltip = command.restrict(\n                data,\n                domQuery,\n                this.restrictEnd.bind(this),\n                this\n            );\n            return;\n        } else {\n            this.currentTooltip = new Entry.Tooltip(\n                [\n                    {\n                        title: data.tooltip.title,\n                        content: data.tooltip.content,\n                        target: domQuery,\n                    },\n                ],\n                {\n                    restrict: true,\n                    dimmed: true,\n                    callBack: this.restrictEnd.bind(this),\n                }\n            );\n            window.setTimeout(this.align.bind(this));\n        }\n\n        if (data.skip) {\n            return this.end();\n        }\n    }\n\n    end() {\n        if (this.currentTooltip) {\n            this.currentTooltip.dispose();\n            this.currentTooltip = null;\n        }\n    }\n\n    restrictEnd() {\n        this.endEvent.notify();\n    }\n\n    align() {\n        if (this.currentTooltip) {\n            this.currentTooltip.alignTooltips();\n        }\n    }\n\n    processDomQuery(domQuery, log) {\n        log = log || this._data.content;\n        log = log.concat();\n        log.shift();\n        if (domQuery instanceof Array) {\n            domQuery = domQuery.map((q) => {\n                if (q[0] === '&') {\n                    return log[Number(q.substr(1))][1];\n                } else {\n                    return q;\n                }\n            });\n        }\n        return domQuery;\n    }\n\n    renderTooltip() {\n        if (this.currentTooltip) {\n            this.currentTooltip.render();\n        }\n    }\n\n    fadeOutTooltip() {\n        if (this.currentTooltip) {\n            this.currentTooltip.fadeOut();\n        }\n    }\n\n    fadeInTooltip() {\n        if (this.currentTooltip) {\n            this.currentTooltip.fadeIn();\n        }\n    }\n\n    isTooltipFaded() {\n        if (this.currentTooltip) {\n            return this.currentTooltip.isFaded();\n        }\n        return false;\n    }\n\n    requestNextData() {\n        if (this._controller) {\n            return this._controller.requestNextData();\n        }\n    }\n};\n"
  },
  {
    "path": "src/util/scheduler.js",
    "content": "export class Scheduler {\n    /**\n     * Runs a generator function concurrently\n     * It's a naive implementation that uses setTimeout().\n     * @param {() => Generator} callback Generator function to schedule\n     */\n    run(callback) {\n        this.cancel();\n\n        // get generator by calling generator function\n        const generator = callback();\n\n        const runGenerator = () => {\n            // 10ms budget for running task\n            const deadline = performance.now() + 10;\n            // start iteration\n            while (true) {\n                // we get result object for each yield and return\n                const result = generator.next();\n                if (result.done) {\n                    // we reached return - no more work to do\n                    break;\n                } else if (performance.now() >= deadline) {\n                    // we reached deadline - now it's time to schedule the next task\n                    // and stop the current one\n                    this.timeoutId = setTimeout(runGenerator);\n                    break;\n                }\n            }\n        };\n        // start the generator iteration task\n        runGenerator();\n    }\n\n    /**\n     * Cancels currently running generator.\n     */\n    cancel() {\n        if (this.timeoutId !== undefined) {\n            // cancel scheduled task\n            clearTimeout(this.timeoutId);\n            this.timeoutId = undefined;\n        }\n    }\n}\n"
  },
  {
    "path": "src/util/static.js",
    "content": "'use strict';\n\nconst Entry = require('../entry');\n\nEntry.STATIC = {\n    /* data type */\n    OBJECT: 0,\n    ENTITY: 1,\n    SPRITE: 2,\n    SOUND: 3,\n    VARIABLE: 4,\n    FUNCTION: 5,\n    SCENE: 6,\n    MESSAGE: 7,\n    BLOCK_MODEL: 8,\n    BLOCK_RENDER_MODEL: 9,\n    BOX_MODEL: 10,\n    THREAD_MODEL: 11,\n    DRAG_INSTANCE: 12,\n\n    /* block state */\n    BLOCK_STATIC: 0,\n    BLOCK_MOVE: 1,\n    BLOCK_FOLLOW: 2,\n\n    /* execute return state */\n    RETURN: 0,\n    CONTINUE: 1,\n    BREAK: 2,\n    PASS: 3,\n\n    //if command type number > 500\n    //undo redo not working for usual workspace\n    //but recorded and validated in guide\n\n    COMMAND_TYPES_ALWAYS: {\n        sceneAdd: 1,\n        sceneRemove: 2,\n        sceneRename: 3,\n        sceneSort: 4,\n        sceneSelect: 5,\n\n        addThread: 101,\n        destroyThread: 102,\n        destroyBlock: 103,\n        recoverBlock: 104,\n        insertBlock: 105,\n        separateBlock: 106,\n        moveBlock: 107,\n        cloneBlock: 108,\n        uncloneBlock: 109,\n        scrollBoard: 110,\n        setFieldValue: 111,\n        selectBlockMenu: 112,\n        destroyBlockBelow: 113,\n        destroyThreads: 114,\n        addThreads: 115,\n        recoverBlockBelow: 116,\n        addThreadFromBlockMenu: 117,\n        insertBlockFromBlockMenu: 118,\n        moveBlockFromBlockMenu: 119,\n        separateBlockForDestroy: 120,\n        moveBlockForDestroy: 121,\n        insertBlockFromBlockMenuFollowSeparate: 122,\n        insertBlockFollowSeparate: 123,\n        separateBlockByCommand: 124,\n\n        selectObject: 201,\n        objectEditButtonClick: 202,\n        objectAddPicture: 203,\n        objectRemovePicture: 204,\n        objectAddSound: 205,\n        objectRemoveSound: 206,\n        objectNameEdit: 207,\n        addObject: 208,\n        removeObject: 209,\n        objectUpdatePosX: 211,\n        objectUpdatePosY: 212,\n        objectUpdateSize: 213,\n        objectUpdateRotationValue: 214,\n        objectUpdateDirectionValue: 215,\n        objectUpdateRotateMethod: 216,\n        entitySetModel: 217,\n        objectAddExpansionBlocks: 218,\n        objectRemoveExpansionBlocks: 219,\n        objectReorder: 220,\n\n        objectAddAIUtilizeBlocks: 221,\n        objectRemoveAIUtilizeBlocks: 222,\n\n        objectAddHardwareLiteBlocks: 223,\n        objectRemoveHardwareLiteBlocks: 224,\n\n        do: 301,\n        undo: 302,\n        redo: 303,\n\n        editPicture: 401,\n        uneditPicture: 402,\n        processPicture: 403,\n        unprocessPicture: 404,\n        editText: 405,\n\n        variableContainerAddMessage: 807,\n        variableContainerRemoveMessage: 808,\n\n        funcEditStart: 1001,\n        funcEditEnd: 1002,\n        funcRemove: 1003,\n        funcCreate: 1004,\n        funcChangeType: 1005,\n        funcLocalVarChangeLength: 1006,\n        toggleFuncUseLocalVariables: 1007,\n        insertFuncLocalVariable: 1008,\n        removeFuncLocalVariableByIndex: 1009,\n\n        createComment: 1201,\n        removeComment: 1202,\n        showAllComment: 1203,\n        hideAllComment: 1204,\n        moveComment: 1205,\n        toggleComment: 1206,\n        cloneComment: 1207,\n        uncloneComment: 1208,\n        separateComment: 1209,\n        connectComment: 1210,\n        writeComment: 1211,\n\n        dataTableAddSource: 1301,\n        dataTableRemoveSource: 1302,\n        //TODO commands development\n    },\n\n    COMMAND_TYPES_NOT_ALWAYS: {\n        addObjectButtonClick: 210,\n\n        toggleRun: 501,\n        toggleStop: 502,\n\n        containerSelectObject: 601,\n\n        playgroundChangeViewMode: 701,\n        playgroundClickAddPicture: 702,\n        playgroundClickAddSound: 703,\n        playgroundClickAddPictureCancel: 704,\n        playgroundClickAddSoundCancel: 705,\n        playgroundClickAddTable: 706,\n        playgroundClickAddTableCancel: 707,\n\n        variableContainerSelectFilter: 801,\n        variableContainerClickVariableAddButton: 802,\n        variableContainerAddVariable: 803,\n        variableContainerRemoveVariable: 804,\n        variableAddSetName: 805,\n        messageSetName: 806,\n        variableAddSetScope: 809,\n        variableAddSetCloud: 810,\n        variableSetVisibility: 811,\n        variableSetDefaultValue: 812,\n        variableSetSlidable: 813,\n        variableSetMinValue: 814,\n        variableSetMaxValue: 815,\n        variableContainerClickListAddButton: 816,\n        variableContainerAddList: 817,\n        variableContainerRemoveList: 818,\n        listAddSetName: 819,\n        listAddSetScope: 820,\n        listAddSetCloud: 821,\n        listSetVisibility: 822,\n        listChangeLength: 823,\n        listSetDefaultValue: 824,\n        setMessageEditable: 825,\n        setVariableEditable: 826,\n        setListEditable: 827,\n        variableSetName: 828,\n        listSetName: 829,\n        variableContainerClickMessageAddButton: 830,\n\n        dismissModal: 900,\n\n        playgroundClickAddExpansionBlock: 1101,\n        playgroundClickAddExpansionBlockCancel: 1102,\n\n        playgroundClickAddAIUtilizeBlock: 1103,\n        playgroundClickAddAIUtilizeBlockCancel: 1104,\n\n        playgroundClickAddHardwareLiteBlock: 1105,\n        playgroundClickAddHardwareLiteBlockCancel: 1106,\n    },\n\n    COMMAND_TYPES_CHANGE_CHECK: {\n        variableContainerAddVariable: 803,\n        variableContainerAddMessage: 807,\n        variableContainerAddList: 817,\n    },\n\n    RECORDABLE: {\n        SUPPORT: 1,\n        SKIP: 2,\n        ABANDON: 3,\n    },\n\n    get COMMAND_TYPES() {\n        return Object.assign(\n            {},\n            Entry.STATIC.COMMAND_TYPES_ALWAYS,\n            Entry.STATIC.COMMAND_TYPES_NOT_ALWAYS\n        );\n    },\n\n    getCommandName(commandType) {\n        return _.findKey(Entry.STATIC.COMMAND_TYPES, _.partial(_.isEqual, commandType));\n    },\n};\n"
  },
  {
    "path": "src/util/tooltip.js",
    "content": "import debounce from 'lodash/debounce';\n\nEntry.Tooltip = function(data, opts) {\n    this.init(data, opts);\n};\n\n(function(p) {\n    p.usedClasses = 'up down left right edge_up edge_down edge_left edge_right';\n\n    p.init = function(data, opts) {\n        if (this._rendered) {\n            this.dispose();\n        }\n\n        this.data = Array.isArray(data) ? data : [data];\n        this.opts = opts ||\n            this.opts || {\n                dimmed: true,\n                restirct: false,\n            };\n        this._rendered = false;\n        this._noDispose = !!this.opts.noDispose;\n        this._faded = false;\n        this._tooltips = [];\n        this._indicators = [];\n\n        if (data.length > 1 || opts.indicator) {\n            this.isIndicator = true;\n        }\n\n        if (opts.render !== false) {\n            this.render();\n        }\n\n        this._resizeEventFunc = debounce(this.alignTooltips.bind(this, 200));\n\n        Entry.addEventListener('windowResized', this._resizeEventFunc);\n    };\n\n    p.render = function() {\n        if (this._rendered) {\n            return;\n        }\n        this.fadeIn();\n\n        this._convertDoms();\n\n        if (this.opts.dimmed) {\n            this.renderBG();\n        }\n\n        const datum = this.data[0].targetDom;\n        if (datum && typeof datum !== 'string' && datum.length) {\n            this.opts.restrict && this.opts.dimmed && Entry.Curtain.show(datum.get(0));\n            this.renderTooltips();\n            this._rendered = true;\n            if (this.opts.restrict) {\n                this.restrictAction();\n            }\n        }\n    };\n\n    p._convertDoms = function() {\n        this.data.map((d) => {\n            let findedDom = d.target;\n            if (d.target instanceof Array) {\n                findedDom = Entry.getDom(d.target);\n            }\n            const targetDom = $(findedDom);\n            if (targetDom.length) {\n                d.targetDom = targetDom;\n            }\n        });\n    };\n\n    p.renderBG = function() {\n        if (this.opts.restrict) {\n            this._bg = Entry.Dom('div', {\n                classes: [],\n                parent: $(document.body),\n            });\n        } else {\n            this._bg = Entry.Dom('div', {\n                classes: ['entryDimmed', 'entryTooltipBG'],\n                parent: $(document.body),\n            });\n\n            this._bg.bindOnClick(this.dispose.bind(this));\n        }\n    };\n\n    p.renderTooltips = function() {\n        this.data.forEach(this._renderTooltip.bind(this));\n    };\n\n    p.alignTooltips = function() {\n        if (!this._rendered) {\n            return;\n        }\n\n        this.data.map(this._alignTooltip.bind(this));\n        this.opts.dimmed && Entry.Curtain.align();\n    };\n\n    p._renderTooltip = function(data) {\n        if (!data.content) {\n            return;\n        }\n        const tooltipWrapper = Entry.Dom('div', {\n            classes: ['entryTooltipWrapper'],\n            parent: $(document.body),\n        });\n        const tooltipDom = Entry.Dom('div', {\n            classes: ['entryTooltip', data.direction, data.style],\n            parent: tooltipWrapper,\n        });\n\n        if (this.isIndicator) {\n            data.indicator = this.renderIndicator();\n        }\n\n        tooltipDom.bind('mousedown', (e) => {\n            e.stopPropagation();\n            setTimeout(() => Entry.disposeEvent.notify(undefined, true), 150);\n        });\n        tooltipDom.bind('mouseup', (e) => {\n            e.stopPropagation();\n        });\n\n        tooltipDom.html(data.content);\n        this._tooltips.push(tooltipWrapper);\n        data.wrapper = tooltipWrapper;\n        data.dom = tooltipDom;\n        this._alignTooltip(data);\n    };\n\n    p._alignTooltip = function(data) {\n        let rect;\n        if (data.targetDom instanceof $) {\n            rect = data.targetDom.get(0).getBoundingClientRect();\n        } else {\n            rect = data.targetDom.getBoundingClientRect();\n        }\n        const tooltipRect = data.dom[0].getBoundingClientRect();\n\n        const { clientWidth, clientHeight } = document.body;\n\n        if (this.isIndicator) {\n            data.indicator.css({\n                left: rect.left + rect.width / 2,\n                top: rect.top + rect.height / 2,\n            });\n        }\n\n        if (tooltipRect.width > 450) {\n            data.dom.addClass('shrink');\n        } else {\n            data.dom.removeClass('shrink');\n        }\n\n        let direction = data.direction;\n\n        if (!direction) {\n            let margin = rect.left - tooltipRect.width;\n            let newMargin = clientWidth - rect.left - rect.width - tooltipRect.width;\n            direction = 'left';\n            if (margin < newMargin) {\n                margin = newMargin;\n                direction = 'right';\n            }\n            newMargin = rect.top - tooltipRect.height;\n            if (margin < newMargin) {\n                margin = newMargin;\n                direction = 'up';\n            }\n            newMargin = clientHeight - rect.top - rect.height - tooltipRect.height;\n            if (margin < newMargin) {\n                margin = newMargin;\n                direction = 'down';\n            }\n        }\n        data.dom.removeClass(this.usedClasses).addClass(direction);\n\n        const pos = { top: rect.top, left: rect.left };\n        let edgeStyle;\n        switch (direction) {\n            case 'down':\n                pos.top += rect.height;\n            case 'up':\n                pos.left += rect.width / 2;\n                if (pos.left < tooltipRect.width / 2) {\n                    edgeStyle = 'edge_left';\n                }\n                if (clientWidth - pos.left < tooltipRect.width / 2) {\n                    edgeStyle = 'edge_right';\n                }\n                break;\n            case 'right':\n                pos.left += rect.width;\n            case 'left':\n                pos.top += rect.height / 2;\n                if (pos.top < tooltipRect.height / 2) {\n                    edgeStyle = 'edge_up';\n                }\n                if (clientHeight - pos.top < tooltipRect.height / 2) {\n                    edgeStyle = 'edge_down';\n                }\n                break;\n            default:\n                break;\n        }\n        if (edgeStyle) {\n            data.dom.addClass(edgeStyle);\n        }\n\n        data.wrapper.css(pos);\n    };\n\n    p.renderIndicator = function(left, top) {\n        const indicator = Entry.Dom('div', {\n            classes: ['entryTooltipIndicator'],\n            parent: $(document.body),\n        });\n        indicator.html('<div></div><div></div><div></div>');\n        this._indicators.push(indicator);\n        return indicator;\n    };\n\n    p.dispose = function(e) {\n        // click event object when call from restrict\n        if (this._bg) {\n            this._bg.remove();\n        }\n        if (this.opts.restrict) {\n            Entry.Utils.allowAction();\n            this.opts.dimmed && Entry.Curtain.hide();\n        }\n        while (this._tooltips.length) {\n            this._tooltips.pop().remove();\n        }\n        while (this._indicators.length) {\n            this._indicators.pop().remove();\n        }\n        if (this.opts.callBack) {\n            this.opts.callBack.call(this, e);\n        }\n        Entry.removeEventListener('windowResized', this._resizeEventFunc);\n    };\n\n    p.restrictAction = function() {\n        const doms = this.data.map((d) => d.targetDom);\n        if (this._noDispose && this.opts.callBack) {\n            this.opts.callBack.call(this);\n        }\n        Entry.Utils.restrictAction(doms, this.dispose.bind(this), this._noDispose);\n    };\n\n    p.fadeOut = function() {\n        $(document.body).addClass('hideTooltip');\n        this._faded = true;\n    };\n\n    p.fadeIn = function() {\n        $(document.body).removeClass('hideTooltip');\n        this._faded = false;\n    };\n\n    p.isFaded = function() {\n        return this._faded;\n    };\n})(Entry.Tooltip.prototype);\n"
  },
  {
    "path": "src/util/tvCast.js",
    "content": "Entry.TvCast = class TvCast {\n    constructor(tvCast) {\n        this.generateView(tvCast);\n    }\n    init(tvCastHash) {\n        this.tvCastHash = tvCastHash;\n    }\n\n    generateView(tvCastHash) {\n        const movieContainer = Entry.createElement('div');\n        movieContainer.addClass('entryContainerMovieWorkspace');\n        movieContainer.addClass('entryRemove');\n\n        const iframe = Entry.createElement('iframe');\n        iframe.setAttribute('id', 'tvCastIframe');\n        iframe.setAttribute('allowfullscreen', '');\n        iframe.setAttribute('frameborder', 0);\n        iframe.setAttribute('src', tvCastHash);\n        this.movieFrame = iframe;\n\n        movieContainer.appendChild(this.movieFrame);\n        this.movieContainer = movieContainer;\n    }\n\n    getView() {\n        return this.movieContainer;\n    }\n\n    resize() {\n        const iframe = document.getElementById('tvCastIframe');\n        const w = this.movieContainer.offsetWidth;\n        iframe.width = `${w}px`;\n        iframe.height = `${(w * 9) / 16}px`;\n    }\n};\n"
  },
  {
    "path": "src/util/utils.js",
    "content": "'use strict';\n\nimport { GEHelper } from '../graphicEngine/GEHelper';\nimport _uniq from 'lodash/uniq';\nimport _intersection from 'lodash/intersection';\nimport _clamp from 'lodash/clamp';\nimport _round from 'lodash/round';\nimport _throttle from 'lodash/throttle';\nimport FontFaceOnload from 'fontfaceonload';\nimport DataTable from '../class/DataTable';\nimport entryModuleLoader from '../class/entryModuleLoader';\nimport { bignumber, chain } from 'mathjs';\nimport { Scheduler } from './scheduler';\nimport { UAParser } from 'ua-parser-js';\n\nEntry.Utils = {};\n\nEntry.TEXT_ALIGN_CENTER = 0;\n\nEntry.TEXT_ALIGN_LEFT = 1;\n\nEntry.TEXT_ALIGN_RIGHT = 2;\n\nEntry.TEXT_ALIGNS = ['center', 'left', 'right'];\n\nEntry.clipboard = null;\n\nEntry.CANVAS_MIN_WIDTH = 162;\nEntry.CANVAS_DEFAULT_WIDTH = 324;\nEntry.CANVAS_MAX_WIDTH = 640;\n\n/**\n * Load project\n * @param {*} project\n */\nEntry.loadProject = function (project) {\n    Entry.isLoadProject = false;\n    if (!project) {\n        project = Entry.getStartProject(Entry.mediaFilePath);\n    }\n    if (this.type === 'workspace') {\n        Entry.stateManager.startIgnore();\n    }\n    Entry.projectId = project._id;\n    Entry.variableContainer?.setVariables(Entry.Utils.combineCloudVariable(project), {\n        aiUtilizeBlocks: project.aiUtilizeBlocks,\n    });\n    Entry.variableContainer.setMessages(project.messages);\n    Entry.variableContainer.setFunctions(project.functions);\n    DataTable?.setTables(project.tables);\n    Entry.aiLearning?.load(project.learning);\n    Entry.scene.addScenes(project.scenes);\n    Entry.stage.initObjectContainers();\n    Entry.container.setObjects(project.objects);\n    Entry.FPS = project.speed ? project.speed : 60;\n    GEHelper.Ticker.setFPS(Entry.FPS);\n    Entry.aiUtilizeBlocks = project?.aiUtilizeBlocks || [];\n    if (Entry.aiUtilizeBlocks.length > 0) {\n        for (const type in Entry.ALL_AI_UTILIZE_BLOCK_LIST) {\n            if (Entry.aiUtilizeBlocks.indexOf(type) > -1) {\n                Entry.AI_UTILIZE_BLOCK[type].init();\n                if (Entry.type === 'workspace' || Entry.type === 'playground') {\n                    Entry.playground.blockMenu.unbanClass(type);\n                }\n            }\n        }\n    }\n\n    Entry.expansionBlocks = project.expansionBlocks || [];\n    if (Entry.expansionBlocks.length > 0) {\n        for (const type in Entry.EXPANSION_BLOCK_LIST) {\n            if (Entry.expansionBlocks.indexOf(type) > -1) {\n                Entry.EXPANSION_BLOCK[type].init();\n                if (Entry.type === 'workspace' || Entry.type === 'playground') {\n                    Entry.playground.blockMenu.unbanClass(type);\n                }\n            }\n        }\n    }\n\n    Entry.hardwareLiteBlocks = project.hardwareLiteBlocks || [];\n    if (Entry.hardwareLiteBlocks.length > 0) {\n        for (const type in Entry.HARDWARE_LITE_LIST) {\n            if (Entry.hardwareLiteBlocks.indexOf(type) > -1) {\n                const module = Entry.HARDWARE_LITE_LIST[type];\n                Entry.playground.addHardwareLiteModule(module);\n            }\n        }\n    }\n\n    if (!Entry.engine.projectTimer) {\n        Entry.variableContainer.generateTimer();\n    }\n\n    if (Object.keys(Entry.container.inputValue).length === 0) {\n        Entry.variableContainer.generateAnswer();\n    }\n    Entry.start();\n    if (this.options.programmingMode) {\n        let mode = this.options.programmingMode;\n        if (Entry.Utils.isNumber(mode)) {\n            const pMode = mode;\n            mode = {};\n\n            this.mode = mode;\n            if (pMode == 0) {\n                mode.boardType = Entry.Workspace.MODE_BOARD;\n                mode.textType = -1;\n            } else if (pMode == 1) {\n                // Python in Text Coding\n                mode.boardType = Entry.Workspace.MODE_VIMBOARD;\n                mode.textType = Entry.Vim.TEXT_TYPE_PY;\n                mode.runType = Entry.Vim.WORKSPACE_MODE;\n            } else if (pMode == 2) {\n                // Javascript in Text Coding\n                mode.boardType = Entry.Workspace.MODE_VIMBOARD;\n                mode.textType = Entry.Vim.TEXT_TYPE_JS;\n                mode.runType = Entry.Vim.MAZE_MODE;\n            }\n            Entry.getMainWS().setMode(mode);\n        }\n    }\n\n    Entry.Loader.isLoaded() && Entry.Loader.handleLoad();\n\n    if (this.type == 'workspace') {\n        Entry.stateManager.endIgnore();\n    }\n\n    if (project.interface && Entry.options.loadInterface) {\n        Entry.loadInterfaceState(project.interface);\n    }\n\n    try {\n        if (window.parent && window.parent.childIframeLoaded) {\n            window.parent.childIframeLoaded();\n        }\n    } catch (e) {}\n    Entry.isLoadProject = true;\n    return project;\n};\n\nEntry.clearProject = function () {\n    try {\n        Entry.stop();\n        Entry.projectId = null;\n        Entry.variableContainer.clear();\n        Entry.container.clear();\n        Entry.scene.clear();\n        Entry.stateManager?.clear();\n        DataTable?.clear();\n        GEHelper.resManager.clearProject();\n        Entry.Loader && (Entry.Loader.loaded = false);\n\n        if (Entry.type !== 'invisible') {\n            Entry.playground && Entry.playground.changeViewMode('code');\n        }\n    } catch (e) {\n        console.warn('clearProject fail', e);\n    }\n};\n\n/**\n * Export project\n * @param {?Project} project\n */\nEntry.exportProject = function (project) {\n    if (!project) {\n        project = {};\n    }\n\n    if (!Entry.engine.isState('stop')) {\n        Entry.engine.toggleStop();\n    }\n    project.objects = Entry.container.toJSON();\n    const objects = project.objects;\n    project.scenes = Entry.scene.toJSON();\n    project.variables = Entry.variableContainer.getVariableJSON();\n    project.messages = Entry.variableContainer.getMessageJSON();\n    project.functions = Entry.variableContainer.getFunctionJSON();\n    project.tables = DataTable.getTableJSON();\n    project.speed = Entry.FPS;\n    project.interface = Entry.captureInterfaceState();\n    project.expansionBlocks = Entry.expansionBlocks;\n    project.aiUtilizeBlocks = Entry.aiUtilizeBlocks;\n    project.hardwareLiteBlocks = Entry.hardwareLiteBlocks;\n    project.learning = Entry.aiLearning?.toJSON();\n    project.externalModules = entryModuleLoader.moduleList;\n    project.externalModulesLite = entryModuleLoader.moduleListLite;\n\n    if (!objects || !objects.length) {\n        return false;\n    }\n\n    return project;\n};\n\n/**\n * inject blocks to Entry menu.\n * Available block is different by object type.\n * @param {!string} objectType\n * @param {!xml} XML\n */\nEntry.setBlock = function (objectType, XML) {\n    Entry.playground.setMenuBlock(objectType, XML);\n};\n\n/**\n * This method is called when window closed;\n * @param {event} e\n */\nEntry.beforeUnload = function (e) {\n    Entry.dispatchEvent('EntryBeforeUnload');\n    Entry.hw.closeConnection();\n    if (Entry.type === 'workspace') {\n        if (localStorage && Entry.interfaceState) {\n            localStorage.setItem(\n                'workspace-interface',\n                JSON.stringify(Entry.captureInterfaceState())\n            );\n        }\n        if (!Entry.stateManager.isSaved()) {\n            return Lang.Workspace.project_changed;\n        }\n    }\n};\n\nEntry.captureInterfaceState = function () {\n    const interfaceState = JSON.parse(JSON.stringify(Entry.interfaceState));\n    const playground = Entry.playground;\n    if (Entry.type === 'workspace' && playground && playground.object) {\n        interfaceState.object = playground.object.id;\n    }\n\n    return interfaceState;\n};\n\n/**\n * load interface state by localstorage\n */\nEntry.loadInterfaceState = function (interfaceState) {\n    if (Entry.type === 'workspace') {\n        if (interfaceState) {\n            Entry.container.selectObject(interfaceState.object, true);\n        } else if (localStorage && localStorage.getItem('workspace-interface')) {\n            const interfaceModel = localStorage.getItem('workspace-interface');\n            interfaceState = JSON.parse(interfaceModel);\n        } else {\n            interfaceState = {\n                menuWidth: 280,\n                canvasWidth: 480,\n            };\n        }\n        this.resizeElement(interfaceState);\n    }\n};\n\n/**\n * @return {Number} return up time time stamp\n */\nEntry.getUpTime = function () {\n    return new Date().getTime() - this.startTime;\n};\n\n/**\n * @param {String} activityType\n */\nEntry.addActivity = function (activityType) {\n    if (Entry.stateManager) {\n        Entry.stateManager.addActivity(activityType);\n    }\n};\n\nEntry.startActivityLogging = function () {\n    if (Entry.reporter) {\n        Entry.reporter.start(\n            Entry.projectId,\n            window.user ? window.user._id : null,\n            Entry.startTime\n        );\n    }\n};\n\n/**\n * return activity log\n * @return {object}\n */\nEntry.getActivityLog = function () {\n    const log = {};\n    if (Entry.stateManager) {\n        log.activityLog = Entry.stateManager.activityLog_;\n    }\n    return log;\n};\n//block drag mode for Entry.BlockView\nEntry.DRAG_MODE_NONE = 0;\nEntry.DRAG_MODE_MOUSEDOWN = 1;\nEntry.DRAG_MODE_DRAG = 2;\n\nEntry.cancelObjectEdit = function ({ target, type }) {\n    const object = Entry.playground.object;\n    if (!object) {\n        return;\n    }\n    const objectView = object.view_;\n    const isCurrent = $(objectView).find(target).length !== 0;\n    const tagName = target.tagName.toUpperCase();\n    if (!object.isEditing || (tagName === 'INPUT' && isCurrent) || type === 'touchstart') {\n        return;\n    }\n    object.editObjectValues(false);\n};\n\nEntry.getMainWS = function () {\n    let ret;\n    if (Entry.mainWorkspace) {\n        ret = Entry.mainWorkspace;\n    } else if (Entry.playground && Entry.playground.mainWorkspace) {\n        ret = Entry.playground.mainWorkspace;\n    }\n    return ret;\n};\n\nEntry.getDom = function (query) {\n    if (!query) {\n        return this.view_;\n    }\n\n    query = JSON.parse(JSON.stringify(query));\n    if (query.length > 1) {\n        const key = query.shift();\n        return this[key].getDom(query);\n    } else {\n    }\n};\n\nfunction toggleEngineContainer(isVisible) {\n    const splitterSelector = '.entryObjectSelectedImgWorkspace';\n    $(Entry.engineContainer)\n        .css('padding', isVisible ? '' : '0')\n        .children(`:not(${splitterSelector})`)\n        .toggleClass('entryRemove', !isVisible);\n}\n\n/**\n * Resize element's size.\n * @param {!json} interfaceModel\n */\nEntry.resizeElement = function (interfaceModel) {\n    // 워크 스페이스에 style width / height 값을 임시로 막음.\n    // return;\n    const mainWorkspace = Entry.getMainWS();\n    if (!mainWorkspace) {\n        return;\n    }\n\n    if (!interfaceModel) {\n        interfaceModel = this.interfaceState;\n    }\n\n    if (Entry.type === 'workspace') {\n        const interfaceState = this.interfaceState;\n        if (!interfaceModel.canvasWidth && interfaceState.canvasWidth) {\n            interfaceModel.canvasWidth = interfaceState.canvasWidth;\n        }\n\n        if (Entry.engine.speedPanelOn) {\n            Entry.engine.toggleSpeedPanel();\n        }\n\n        let isEngineContainerVisible = true;\n        let canvasSize = interfaceModel.canvasWidth;\n        if (!canvasSize) {\n            canvasSize = Entry.CANVAS_MIN_WIDTH;\n        } else if (canvasSize < Entry.CANVAS_MIN_WIDTH) {\n            canvasSize = 16;\n            isEngineContainerVisible = false;\n        } else if (canvasSize < Entry.CANVAS_DEFAULT_WIDTH) {\n            canvasSize = Entry.CANVAS_DEFAULT_WIDTH;\n        } else if (canvasSize > Entry.CANVAS_MAX_WIDTH) {\n            canvasSize = Entry.CANVAS_MAX_WIDTH;\n        }\n        interfaceModel.canvasWidth = canvasSize;\n\n        const engineContainer = Entry.engine.view_.parentElement;\n        engineContainer.style.width = `${canvasSize}px`;\n        Entry.engine.view_.style.width = `${canvasSize - 24}px`;\n        Entry.stage.canvas.canvas.style.width = `${canvasSize - 26}px`;\n\n        toggleEngineContainer(isEngineContainerVisible);\n\n        const blockMenu = mainWorkspace.blockMenu;\n        const adjust = blockMenu.hasCategory() ? -64 : 0;\n\n        this.interfaceState = interfaceModel;\n    }\n\n    Entry.windowResized.notify();\n};\n\n/**\n * override native prototype to add useful method.\n */\nEntry.overridePrototype = function () {\n    /** modulo include negative number */\n    Number.prototype.mod = function (n) {\n        try {\n            // 음수 보정을 위해서 존재하는 기능\n            // INFO : https://stackoverflow.com/questions/4467539/javascript-modulo-gives-a-negative-result-for-negative-numbers\n            const left = bignumber(this);\n            const right = bignumber(n);\n            return chain(left).mod(right).add(right).mod(right).value.toNumber();\n        } catch (e) {\n            return ((this % n) + n) % n;\n        }\n    };\n\n    //polyfill\n    if (!String.prototype.repeat) {\n        String.prototype.repeat = function (count) {\n            'use strict';\n            if (this == null) {\n                throw new TypeError(`can't convert ${this} to object`);\n            }\n            let str = `${this}`;\n            count = +count;\n            if (count != count) {\n                count = 0;\n            }\n            if (count < 0) {\n                throw new RangeError('repeat count must be non-negative');\n            }\n            if (count == Infinity) {\n                throw new RangeError('repeat count must be less than infinity');\n            }\n            count = Math.floor(count);\n            if (str.length == 0 || count == 0) {\n                return '';\n            }\n            // Ensuring count is a 31-bit integer allows us to heavily optimize the\n            // main part. But anyway, most current (August 2014) browsers can't handle\n            // strings 1 << 28 chars or longer, so:\n            if (str.length * count >= 1 << 28) {\n                throw new RangeError('repeat count must not overflow maximum string size');\n            }\n            let rpt = '';\n            for (;;) {\n                if ((count & 1) == 1) {\n                    rpt += str;\n                }\n                count >>>= 1;\n                if (count == 0) {\n                    break;\n                }\n                str += str;\n            }\n            // Could we try:\n            // return Array(count + 1).join(this);\n            return rpt;\n        };\n    }\n};\n\n// INFO: 기존에 사용하던 isNaN에는 숫자 체크의 문자가 있을수 있기때문에 regex로 체크하는 로직으로 변경\n// isNaN 문제는 https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/isNaN\n// 에서 확인.\nEntry.Utils.isNumber = function (num) {\n    if (typeof num === 'number') {\n        return true;\n    }\n    const reg = /^-?\\d+\\.?\\d*$/;\n    if (typeof num === 'string' && reg.test(num)) {\n        return true;\n    }\n    return false;\n};\n\nEntry.Utils.generateId = function () {\n    return `0000${((Math.random() * Math.pow(36, 4)) << 0).toString(36)}`.substr(-4);\n};\n\nEntry.Utils.randomColor = function () {\n    const letters = '0123456789ABCDEF';\n    let color = '#';\n    for (var i = 0; i < 6; i++) {\n        color += letters[Math.floor(Math.random() * 16)];\n    }\n    return color;\n};\n\nEntry.Utils.isPointInMatrix = function (matrix, point, offset) {\n    offset = offset === undefined ? 0 : offset;\n    const x = matrix.offsetX ? matrix.x + matrix.offsetX : matrix.x;\n    const y = matrix.offsetY ? matrix.y + matrix.offsety : matrix.y;\n    return (\n        x - offset <= point.x &&\n        x + matrix.width + offset >= point.x &&\n        y - offset <= point.y &&\n        y + matrix.height + offset >= point.y\n    );\n};\n\nEntry.Utils.colorDarken = function (color, factor) {\n    let r;\n    let g;\n    let b;\n    if (color.length === 7) {\n        r = parseInt(color.substr(1, 2), 16);\n        g = parseInt(color.substr(3, 2), 16);\n        b = parseInt(color.substr(5, 2), 16);\n    } else {\n        r = parseInt(color.substr(1, 2), 16);\n        g = parseInt(color.substr(2, 2), 16);\n        b = parseInt(color.substr(3, 2), 16);\n    }\n\n    factor = factor === undefined ? 0.7 : factor;\n    r = inspect(Math.floor(r * factor).toString(16));\n    g = inspect(Math.floor(g * factor).toString(16));\n    b = inspect(Math.floor(b * factor).toString(16));\n\n    function inspect(val) {\n        if (val.length != 2) {\n            val = `0${val}`;\n        }\n        return val;\n    }\n\n    return `#${r}${g}${b}`;\n};\n\nEntry.Utils.colorLighten = function (color, amount) {\n    function clamp01(val) {\n        return Math.min(1, Math.max(0, val));\n    }\n\n    amount = amount === 0 ? 0 : amount || 20;\n    const hsl = Entry.Utils.hexToHsl(color);\n    hsl.l += amount / 100;\n    hsl.l = clamp01(hsl.l);\n    return Entry.Utils.hslToHex(hsl);\n};\n\nEntry.Utils.getEmphasizeColor = function (color) {\n    return EntryStatic.colorSet.block.emphasize[color] || color;\n};\n\n// Take input from [0, n] and return it as [0, 1]\nEntry.Utils.bound01 = function (n, max) {\n    function isOnePointZero(n) {\n        return typeof n === 'string' && n.indexOf('.') != -1 && parseFloat(n) === 1;\n    }\n\n    function isPercentage(n) {\n        return typeof n === 'string' && n.indexOf('%') != -1;\n    }\n\n    if (isOnePointZero(n)) {\n        n = '100%';\n    }\n\n    const processPercent = isPercentage(n);\n    n = Math.min(max, Math.max(0, parseFloat(n)));\n\n    // Automatically convert percentage into number\n    if (processPercent) {\n        n = parseInt(n * max, 10) / 100;\n    }\n\n    // Handle floating point rounding errors\n    if (Math.abs(n - max) < 0.000001) {\n        return 1;\n    }\n\n    // Convert into [0, 1] range if it isn't already\n    return (n % max) / parseFloat(max);\n};\n\n// `rgbToHsl`\n// Converts an RGB color value to HSL.\n// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n// *Returns:* { h, s, l } in [0,1]\nEntry.Utils.hexToHsl = function (color) {\n    let r;\n    let g;\n    let b;\n    if (color.length === 7) {\n        r = parseInt(color.substr(1, 2), 16);\n        g = parseInt(color.substr(3, 2), 16);\n        b = parseInt(color.substr(5, 2), 16);\n    } else {\n        r = parseInt(color.substr(1, 2), 16);\n        g = parseInt(color.substr(2, 2), 16);\n        b = parseInt(color.substr(3, 2), 16);\n    }\n\n    r = Entry.Utils.bound01(r, 255);\n    g = Entry.Utils.bound01(g, 255);\n    b = Entry.Utils.bound01(b, 255);\n\n    const max = Math.max(r, g, b);\n    const min = Math.min(r, g, b);\n    let h;\n    let s;\n    const l = (max + min) / 2;\n\n    if (max == min) {\n        h = s = 0; // achromatic\n    } else {\n        const d = max - min;\n        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n        switch (max) {\n            case r:\n                h = (g - b) / d + (g < b ? 6 : 0);\n                break;\n            case g:\n                h = (b - r) / d + 2;\n                break;\n            case b:\n                h = (r - g) / d + 4;\n                break;\n        }\n\n        h /= 6;\n    }\n\n    const hsl = { h, s, l };\n    return { h: hsl.h * 360, s: hsl.s, l: hsl.l };\n};\n\n// `hslToRgb`\n// Converts an HSL color value to RGB.\n// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n// *Returns:* { r, g, b } in the set [0, 255]\nEntry.Utils.hslToHex = function (color) {\n    let r;\n    let g;\n    let b;\n\n    const h = Entry.Utils.bound01(color.h, 360);\n    const s = Entry.Utils.bound01(color.s, 1);\n    const l = Entry.Utils.bound01(color.l, 1);\n\n    function hue2rgb(p, q, t) {\n        if (t < 0) {\n            t += 1;\n        }\n        if (t > 1) {\n            t -= 1;\n        }\n        if (t < 1 / 6) {\n            return p + (q - p) * 6 * t;\n        }\n        if (t < 1 / 2) {\n            return q;\n        }\n        if (t < 2 / 3) {\n            return p + (q - p) * (2 / 3 - t) * 6;\n        }\n        return p;\n    }\n\n    function pad2(c) {\n        return c.length == 1 ? `0${c}` : `${c}`;\n    }\n\n    if (s === 0) {\n        r = g = b = l; // achromatic\n    } else {\n        const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n        const p = 2 * l - q;\n        r = hue2rgb(p, q, h + 1 / 3);\n        g = hue2rgb(p, q, h);\n        b = hue2rgb(p, q, h - 1 / 3);\n    }\n\n    const rgb = { r: r * 255, g: g * 255, b: b * 255 };\n\n    const hex = [\n        pad2(Math.round(rgb.r).toString(16)),\n        pad2(Math.round(rgb.g).toString(16)),\n        pad2(Math.round(rgb.b).toString(16)),\n    ];\n\n    return `#${hex.join('')}`;\n};\n\nEntry.Utils.setSVGDom = function (SVGDom) {\n    Entry.Utils.SVGDom = SVGDom;\n};\n\nEntry.Utils.bindIOSDeviceWatch = function () {\n    const Agent = Entry.Utils.mobileAgentParser();\n    if (Agent.apple.device) {\n        let lastHeight = window.innerHeight || document.documentElement.clientHeight;\n        let lastSVGDomHeight = 0;\n        if (Entry.Utils.SVGDom) {\n            lastSVGDomHeight = Entry.Utils.SVGDom.height();\n        }\n\n        setInterval(() => {\n            const nowHeight = window.innerHeight || document.documentElement.clientHeight;\n            let SVGDomCheck = false;\n            if (Entry.Utils.SVGDom) {\n                const nowSVGDomHeight = Entry.Utils.SVGDom.height();\n                SVGDomCheck = lastSVGDomHeight != nowSVGDomHeight;\n                lastSVGDomHeight = nowSVGDomHeight;\n            }\n            if (lastHeight != nowHeight || SVGDomCheck) {\n                Entry.windowResized.notify();\n            }\n            lastHeight = nowHeight;\n        }, 1000);\n\n        $(window).on('orientationchange', () => {\n            Entry.windowResized.notify();\n        });\n\n        window.addEventListener('pagehide', Entry.beforeUnload);\n    }\n};\n\nfunction addEntryEvent(dom, event, func) {\n    if (dom && event) {\n        dom.on(event, func);\n    }\n}\n\nfunction removeEntryEvent(dom, event, func) {\n    if (dom && event) {\n        dom.off(event, func);\n    }\n}\n\nEntry.Utils.bindGlobalEvent = function (options) {\n    const doc = $(document);\n    let parentDoc;\n    if (window.parent !== window.self) {\n        try {\n            parentDoc = $(window.parent.document);\n        } catch (e) {}\n    }\n    if (options === undefined) {\n        options = ['resize', 'mousedown', 'mousemove', 'keydown', 'keyup', 'dispose'];\n    }\n\n    if (options.indexOf('resize') > -1) {\n        if (Entry.windowReszied) {\n            removeEntryEvent($(window), 'resize');\n            if (parentDoc) {\n                removeEntryEvent($(window.parent), 'resize');\n            }\n            Entry.windowReszied.clear();\n        }\n        Entry.windowResized = new Entry.Event(window);\n        const func = (e) => {\n            Entry.windowResized.notify(e);\n        };\n        addEntryEvent($(window), 'resize', func);\n        if (parentDoc) {\n            addEntryEvent($(window.parent), 'resize', func);\n        }\n        Entry.Utils.bindIOSDeviceWatch();\n    }\n\n    if (options.indexOf('mousedown') > -1) {\n        if (Entry.documentMousedown) {\n            removeEntryEvent(doc, 'mousedown');\n            removeEntryEvent(parentDoc, 'mousedown');\n            Entry.documentMousedown.clear();\n        }\n        Entry.documentMousedown = new Entry.Event(window);\n        const func = (e) => {\n            const selectedBlock = document.querySelector('.block.selected');\n            if (selectedBlock) {\n                selectedBlock.classList.remove('selected');\n            }\n        };\n        addEntryEvent(doc, 'mousedown', func);\n        addEntryEvent(parentDoc, 'mousedown', func);\n    }\n\n    if (options.indexOf('mousemove') > -1) {\n        if (Entry.documentMousemove) {\n            removeEntryEvent(doc, 'touchmove mousemove');\n            removeEntryEvent(parentDoc, 'touchmove mousemove');\n            Entry.documentMousemove.clear();\n        }\n\n        Entry.mouseCoordinate = {};\n        Entry.documentMousemove = new Entry.Event(window);\n        const func = (e) => {\n            if (e.originalEvent && e.originalEvent.touches) {\n                e = e.originalEvent.touches[0];\n            }\n            Entry.documentMousemove.notify(e);\n            Entry.mouseCoordinate.x = e.clientX;\n            Entry.mouseCoordinate.y = e.clientY;\n        };\n        addEntryEvent(doc, 'touchmove mousemove', func);\n        addEntryEvent(parentDoc, 'touchmove mousemove', func);\n    }\n\n    if (options.indexOf('keydown') > -1) {\n        if (Entry.keyPressed) {\n            removeEntryEvent(doc, 'keydown');\n            removeEntryEvent(parentDoc, 'keydown');\n            Entry.keyPressed.clear();\n        }\n        Entry.pressedKeys = [];\n        Entry.keyPressed = new Entry.Event(window);\n        const func = (e) => {\n            const keyCode = Entry.Utils.inputToKeycode(e);\n            if (!keyCode) {\n                return;\n            }\n            if (Entry.pressedKeys.indexOf(keyCode) < 0) {\n                Entry.pressedKeys.push(keyCode);\n            }\n            Entry.keyPressed.notify(e);\n        };\n        addEntryEvent(doc, 'keydown', func);\n        addEntryEvent(parentDoc, 'keydown', func);\n    }\n\n    if (options.indexOf('keyup') > -1) {\n        if (Entry.keyUpped) {\n            removeEntryEvent(doc, 'keyup');\n            removeEntryEvent(parentDoc, 'keyup');\n            Entry.keyUpped.clear();\n        }\n        Entry.keyUpped = new Entry.Event(window);\n        const func = (e) => {\n            const keyCode = Entry.Utils.inputToKeycode(e);\n            if (!keyCode) {\n                return;\n            }\n            const index = Entry.pressedKeys.indexOf(keyCode);\n            if (index > -1) {\n                Entry.pressedKeys.splice(index, 1);\n            }\n            Entry.keyUpped.notify(e);\n        };\n        addEntryEvent(doc, 'keyup', func);\n        addEntryEvent(parentDoc, 'keyup', func);\n    }\n\n    if (options.indexOf('dispose') > -1) {\n        if (Entry.disposeEvent) {\n            Entry.disposeEvent.clear();\n        }\n        Entry.disposeEvent = new Entry.Event(window);\n        if (Entry.documentMousedown) {\n            Entry.documentMousedown.attach(this, (e) => {\n                Entry.disposeEvent.notify(e);\n            });\n        }\n    }\n};\nEntry.Utils.inputToKeycode = (e) => {\n    //https://riptutorial.com/jquery/example/21119/originalevent\n    const event = e.originalEvent || e;\n    let keyCode = event.code == undefined ? event.key : event.code;\n    if (!keyCode) {\n        return null;\n    }\n    keyCode = keyCode.replace('Digit', '');\n    keyCode = keyCode.replace('Numpad', '');\n    if (keyCode.indexOf('Shift') > -1) {\n        keyCode = keyCode.replace('Left', '');\n        keyCode = keyCode.replace('Right', '');\n    }\n    return Entry.KeyboardCode.codeToKeyCode[keyCode];\n};\n\nEntry.Utils.makeActivityReporter = function () {\n    Entry.activityReporter = new Entry.ActivityReporter();\n    if (Entry.commander) {\n        Entry.commander.addReporter(Entry.activityReporter);\n    }\n    return Entry.activityReporter;\n};\n\n/**\n * Raise error when assert condition fail.\n * @param {!boolean} condition assert condition.\n * @param {?string} message assert message will be shown when assert fail.\n */\nEntry.assert = function (condition, message) {\n    if (!condition) {\n        throw Error(message || 'Assert failed');\n    }\n};\n\n/**\n * Parse Text to Xml\n * @param {!string} xmlText\n * @param {xml} doc\n */\nEntry.parseTexttoXML = function (xmlText) {\n    let doc;\n    if (window.ActiveXObject) {\n        doc = new ActiveXObject('Microsoft.XMLDOM');\n        doc.async = 'false';\n        doc.loadXML(xmlText);\n    } else {\n        const parser = new DOMParser();\n        doc = parser.parseFromString(xmlText, 'text/xml');\n    }\n    return doc;\n};\n\n/**\n * Create html element with some method\n */\nEntry.createElement = function (type, elementId) {\n    const element = type instanceof HTMLElement ? type : document.createElement(type);\n    if (elementId) {\n        element.id = elementId;\n    }\n\n    return element;\n};\n\n/**\n * Generate random hash\n * @return {string}\n */\nEntry.generateHash = function (length = 4) {\n    return Math.random().toString(36).substr(2, length);\n};\n\n/**\n * Add two number properly.\n *\n * @return {number}\n *\n * @param {!number} a\n * @param {!number} b\n */\nEntry.addTwoNumber = function (a, b) {\n    if (!Entry.Utils.isNumber(a) || !Entry.Utils.isNumber(b)) {\n        return a + b;\n    }\n    a += '';\n    b += '';\n\n    const indexA = a.indexOf('.');\n    const indexB = b.indexOf('.');\n    let fixedA = 0;\n    let fixedB = 0;\n    if (indexA > 0) {\n        fixedA = a.length - indexA - 1;\n    }\n\n    if (indexB > 0) {\n        fixedB = b.length - indexB - 1;\n    }\n\n    if (fixedA > 0 || fixedB > 0) {\n        if (fixedA >= fixedB) {\n            return (parseFloat(a) + parseFloat(b)).toFixed(fixedA);\n        } else {\n            return (parseFloat(a) + parseFloat(b)).toFixed(fixedB);\n        }\n    } else {\n        return parseInt(a) + parseInt(b);\n    }\n};\n\n/*\n * HTML hex colour code to RGB colour value\n */\nEntry.hex2rgb = function (hexstr) {\n    let hex = hexstr[0] === '#' ? hexstr : `#${hexstr}`;\n    if (hex.length === 4) {\n        hex = `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`;\n    }\n    if (!/^#[0-9a-f]{6}?$/i.test(hex)) {\n        hex = '#000000';\n    }\n    const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n    return result\n        ? {\n              r: parseInt(result[1], 16),\n              g: parseInt(result[2], 16),\n              b: parseInt(result[3], 16),\n          }\n        : null;\n};\n\n/*\n * RGB colour value to HTML hex colour code\n */\nEntry.rgb2hex = function (r, g, b) {\n    return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;\n};\n\n/**\n *\n * @param {number} r - 0~255 integer\n * @param {number} g - 0~255 integer\n * @param {number} b - 0~255 integer\n * @return {number} 0~0xffffff integer\n */\nEntry.rgb2Number = function (r, g, b) {\n    return (r << 16) + (g << 8) + Number(b);\n};\n\n/*\n * Generate random rgb color object\n */\nEntry.generateRgb = function () {\n    return {\n        r: Math.floor(Math.random() * 256),\n        g: Math.floor(Math.random() * 256),\n        b: Math.floor(Math.random() * 256),\n    };\n};\n\n/*\n * Adjustment input value by max and min value\n * @param {!Number} value, min, max\n */\nEntry.adjustValueWithMaxMin = function (input, min, max) {\n    if (input > max) {\n        return max;\n    } else if (input < min) {\n        return min;\n    } else {\n        return input;\n    }\n};\n\n/*\n * Inspect input value exists already in an array\n * @param {String} targetValue\n * @param {String} identifier\n * @param {Array} arr\n * @return {boolean} return true when target value exists already\n */\nEntry.isExist = function (targetValue, identifier, arr) {\n    return !!_.find(arr, { [identifier]: targetValue });\n};\n\nEntry.getColourCodes = function () {\n    return [\n        'transparent',\n        '#660000',\n        '#663300',\n        '#996633',\n        '#003300',\n        '#003333',\n        '#003399',\n        '#000066',\n        '#330066',\n        '#660066',\n        '#FFFFFF',\n        '#990000',\n        '#993300',\n        '#CC9900',\n        '#006600',\n        '#336666',\n        '#0033FF',\n        '#000099',\n        '#660099',\n        '#990066',\n        '#000000',\n        '#CC0000',\n        '#CC3300',\n        '#FFCC00',\n        '#009900',\n        '#006666',\n        '#0066FF',\n        '#0000CC',\n        '#663399',\n        '#CC0099',\n        '#333333',\n        '#FF0000',\n        '#FF3300',\n        '#FFFF00',\n        '#00CC00',\n        '#009999',\n        '#0099FF',\n        '#0000FF',\n        '#9900CC',\n        '#FF0099',\n        '#666666',\n        '#CC3333',\n        '#FF6600',\n        '#FFFF33',\n        '#00FF00',\n        '#00CCCC',\n        '#00CCFF',\n        '#3366FF',\n        '#9933FF',\n        '#FF00FF',\n        '#999999',\n        '#FF6666',\n        '#FF6633',\n        '#FFFF66',\n        '#66FF66',\n        '#66CCCC',\n        '#00FFFF',\n        '#3399FF',\n        '#9966FF',\n        '#FF66FF',\n        '#BBBBBB',\n        '#FF9999',\n        '#FF9966',\n        '#FFFF99',\n        '#99FF99',\n        '#66FFCC',\n        '#99FFFF',\n        '#66CCff',\n        '#9999FF',\n        '#FF99FF',\n        '#CCCCCC',\n        '#FFCCCC',\n        '#FFCC99',\n        '#FFFFCC',\n        '#CCFFCC',\n        '#99FFCC',\n        '#CCFFFF',\n        '#99CCFF',\n        '#CCCCFF',\n        '#FFCCFF',\n    ];\n};\n\n/*\n * Replacement for element.remove() method\n * @param {Element} targetElement\n * @return {boolean} return true when target element remove or not\n */\nEntry.removeElement = function (element) {\n    if (element && element.parentNode) {\n        element.parentNode.removeChild(element);\n    }\n};\n\n/*\n * parse string to number\n * @param {String||Number} value\n * @return {Boolean||Number} arr\n */\nEntry.parseNumber = function (value) {\n    if (typeof value === 'string') {\n        if (\n            (Entry.Utils.isNumber(value) && value[0] === '0') ||\n            (value[0] === '0' && value[1].toLowerCase() === 'x')\n        ) {\n            return value;\n        } else if (Entry.Utils.isNumber(value)) {\n            return Number(value);\n        }\n    } else if (typeof value === 'number' && Entry.Utils.isNumber(value)) {\n        return value;\n    }\n\n    return false;\n};\n\n/**\n * count length of string.\n * Hanguel character is count to two.\n * @param {!String} dataString\n * @return {Number}\n */\nEntry.countStringLength = function (dataString) {\n    let p;\n    let len = 0;\n    for (p = 0; p < dataString.length; p++) {\n        if (dataString.charCodeAt(p) > 255) {\n            len += 2;\n        } else {\n            len++;\n        }\n    }\n    return len;\n};\n\n/**\n * count length of string.\n * Hanguel character is count to two.\n * @param {!String} dataString\n * @param {!Number} stringLength\n * @return {String}\n */\nEntry.cutStringByLength = function (dataString, stringLength) {\n    let p;\n    let len = 0;\n    for (p = 0; len < stringLength && p < dataString.length; p++) {\n        if (dataString.charCodeAt(p) > 255) {\n            len += 2;\n        } else {\n            len++;\n        }\n    }\n    return dataString.substr(0, p);\n};\n\n/**\n * check to element is are parent child.\n * @param {Element} parent\n * @param {Element} child\n * @return {Boolean}\n */\nEntry.isChild = function (parent, child) {\n    if (!child) {\n        while (child.parentNode) {\n            if ((child = child.parentNode) == parent) {\n                return true;\n            }\n        }\n    }\n    return false;\n};\n\n/**\n * @param {Element} child\n */\nEntry.launchFullScreen = function (element) {\n    if (element.requestFullscreen) {\n        element.requestFullscreen();\n    } else if (element.mozRequestFulScreen) {\n        element.mozRequestFulScreen();\n    } else if (element.webkitRequestFullscreen) {\n        element.webkitRequestFullscreen();\n    } else if (element.msRequestFullScreen) {\n        element.msRequestFullScreen();\n    }\n};\n\nEntry.exitFullScreen = function () {\n    if (document.exitFullScreen) {\n        document.exitFullScreen();\n    } else if (document.mozCancelFullScreen) {\n        document.mozCancelFullScreen();\n    } else if (document.webkitExitFullscreen) {\n        document.webkitExitFullscreen();\n    }\n};\n\nEntry.isPhone = function () {\n    return false;\n    //if (window.screen.availWidth > 480)\n    //return false;\n    //else\n    //return true;\n};\n\nEntry.getKeyCodeMap = function () {\n    return {\n        8: 'backspace',\n        9: 'tab',\n        13: Lang.Blocks.START_press_some_key_enter,\n        16: 'shift',\n        17: 'ctrl',\n        18: 'alt',\n        27: 'esc',\n        32: Lang.Blocks.START_press_some_key_space,\n        37: Lang.Blocks.START_press_some_key_left,\n        38: Lang.Blocks.START_press_some_key_up,\n        39: Lang.Blocks.START_press_some_key_right,\n        40: Lang.Blocks.START_press_some_key_down,\n        48: '0',\n        49: '1',\n        50: '2',\n        51: '3',\n        52: '4',\n        53: '5',\n        54: '6',\n        55: '7',\n        56: '8',\n        57: '9',\n        65: 'a',\n        66: 'b',\n        67: 'c',\n        68: 'd',\n        69: 'e',\n        70: 'f',\n        71: 'g',\n        72: 'h',\n        73: 'i',\n        74: 'j',\n        75: 'k',\n        76: 'l',\n        77: 'm',\n        78: 'n',\n        79: 'o',\n        80: 'p',\n        81: 'q',\n        82: 'r',\n        83: 's',\n        84: 't',\n        85: 'u',\n        86: 'v',\n        87: 'w',\n        88: 'x',\n        89: 'y',\n        90: 'z',\n        //special Characters\n        186: ';',\n        187: '=',\n        188: ',',\n        189: '-',\n        190: '.',\n        191: '/',\n        192: '~',\n        219: '[',\n        220: 'Backslash',\n        221: ']',\n        222: \"'\",\n        // #2590 이슈 처리에 의해 주석처리\n        // '45': 'Help',\n        // '45': 'Insert',\n        // '46': 'Delete',\n        // '36': 'Home',\n        // '35': 'End',\n        // '33': 'PageUp',\n        // '34': 'PageDown',\n    };\n};\n\nEntry.checkCollisionRect = function (rectA, rectB) {\n    return !(\n        rectA.y + rectA.height < rectB.y ||\n        rectA.y > rectB.y + rectB.height ||\n        rectA.x + rectA.width < rectB.x ||\n        rectA.x > rectB.x + rectB.width\n    );\n};\n\nEntry.bindAnimationCallback = function (element, func) {\n    element.addEventListener('webkitAnimationEnd', func, false);\n    element.addEventListener('animationend', func, false);\n    element.addEventListener('oanimationend', func, false);\n};\n\nEntry.cloneSimpleObject = function (object) {\n    return _.clone(object);\n};\n\nEntry.computeInputWidth = (function () {\n    let elem;\n    const _cache = {};\n    return function (value) {\n        // eslint-disable-next-line no-param-reassign\n        value = value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n\n        const cached = _cache[value];\n        if (cached) {\n            return cached;\n        } else {\n            elem = elem || document.getElementById('entryInputForComputeWidth');\n            if (!elem) {\n                elem = document.createElement('span');\n                elem.setAttribute('id', 'entryInputForComputeWidth');\n                elem.className = 'elem-element';\n                document.body.appendChild(elem);\n            }\n\n            elem.textContent = value;\n            const ret = `${Number(elem.offsetWidth + 10)}px`;\n\n            if (window.fontLoaded) {\n                _cache[value] = ret;\n            }\n            return ret;\n        }\n    };\n})();\n\nEntry.isArrowOrBackspace = function (keyCode) {\n    return !!~['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Backspace'].indexOf(keyCode);\n};\n\nEntry.hexStringToBin = function (hexString) {\n    const bytes = [];\n    let str;\n\n    for (let i = 0; i < hexString.length - 1; i += 2) {\n        bytes.push(parseInt(hexString.substr(i, 2), 16));\n    }\n\n    str = String.fromCharCode(...bytes);\n    return str;\n};\n\n//maybe deprecated\nEntry.findObjsByKey = function (arr, keyName, key) {\n    const result = [];\n    for (let i = 0; i < arr.length; i++) {\n        if (arr[i][keyName] == key) {\n            result.push(arr[i]);\n        }\n    }\n    return result;\n};\n\nEntry.factorial = _.memoize((n) => {\n    if (n === 0 || n == 1) {\n        return 1;\n    }\n    return Entry.factorial(n - 1) * n;\n});\n\nEntry.getListRealIndex = function (index, list) {\n    if (!Entry.Utils.isNumber(index)) {\n        switch (index) {\n            case 'FIRST':\n                index = 1;\n                break;\n            case 'LAST':\n                index = list.getArray().length;\n                break;\n            case 'RANDOM':\n                index = Math.floor(Math.random() * list.getArray().length) + 1;\n                break;\n        }\n    }\n    return index;\n};\n\nEntry.toRadian = function (angle) {\n    return (angle * Math.PI) / 180;\n};\n\nEntry.toDegrees = function (radians) {\n    return (radians * 180) / Math.PI;\n};\n\nconst SQRT3 = Math.sqrt(3);\n\nconst TRIG_VALUES = {\n    sin: {\n        0: 0,\n        30: 0.5,\n        45: Math.SQRT2 / 2,\n        60: SQRT3 / 2,\n        90: 1,\n        120: SQRT3 / 2,\n        135: Math.SQRT2 / 2,\n        150: 0.5,\n        180: 0,\n        210: -0.5,\n        225: -Math.SQRT2 / 2,\n        240: -SQRT3 / 2,\n        270: -1,\n        300: -SQRT3 / 2,\n        315: -Math.SQRT2 / 2,\n        330: -0.5,\n        360: 0,\n    },\n    cos: {\n        0: 1,\n        30: SQRT3 / 2,\n        45: Math.SQRT2 / 2,\n        60: 0.5,\n        90: 0,\n        120: -0.5,\n        135: -Math.SQRT2 / 2,\n        150: -SQRT3 / 2,\n        180: -1,\n        210: -SQRT3 / 2,\n        225: -Math.SQRT2 / 2,\n        240: -0.5,\n        270: 0,\n        300: 0.5,\n        315: Math.SQRT2 / 2,\n        330: SQRT3 / 2,\n        360: 1,\n    },\n    tan: {\n        0: 0,\n        30: SQRT3 / 3,\n        45: 1,\n        60: SQRT3,\n        90: Infinity,\n        120: -SQRT3,\n        135: -1,\n        150: -SQRT3 / 3,\n        180: 0,\n        210: SQRT3 / 3,\n        225: 1,\n        240: SQRT3,\n        270: -Infinity,\n        300: -SQRT3,\n        315: -1,\n        330: -SQRT3 / 3,\n        360: 0,\n    },\n};\n\nEntry.preciseTrig = (degrees, operator) => {\n    const angle = degrees % 360;\n\n    if (\n        TRIG_VALUES[operator] &&\n        Object.prototype.hasOwnProperty.call(TRIG_VALUES[operator], angle)\n    ) {\n        return TRIG_VALUES[operator][angle];\n    }\n\n    return Math[operator](Entry.toRadian(angle));\n};\n\nEntry.getPicturesJSON = function (pictures = [], isClone) {\n    return pictures.reduce((acc, p) => {\n        const o = {};\n        o._id = p._id;\n        o.id = isClone ? Entry.generateHash() : p.id;\n        o.dimension = p.dimension;\n        o.filename = p.filename;\n        o.fileurl = p.fileurl;\n        o.thumbUrl = p.thumbUrl;\n        o.name = p.name;\n        o.scale = p.scale;\n        o.imageType = p.imageType || 'png';\n        acc.push(o);\n        return acc;\n    }, []);\n};\n\nEntry.getSoundsJSON = function (sounds = [], isClone) {\n    return sounds.reduce((acc, s) => {\n        const o = {};\n        o._id = s._id;\n        o.duration = s.duration;\n        o.ext = s.ext;\n        o.id = isClone ? Entry.generateHash() : s.id;\n        o.filename = s.filename;\n        o.fileurl = s.fileurl;\n        o.name = s.name;\n        acc.push(o);\n        return acc;\n    }, []);\n};\n\nEntry.cutDecimal = function (number) {\n    return Math.round(number * 100) / 100;\n};\n\nEntry.getBrowserType = function () {\n    if (Entry.userAgent) {\n        return Entry.userAgent;\n    }\n    const ua = navigator.userAgent;\n    let tem;\n    let M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) || [];\n    if (/trident/i.test(M[1])) {\n        tem = /\\brv[ :]+(\\d+)/g.exec(ua) || [];\n        return `IE ${tem[1] || ''}`;\n    }\n    if (M[1] === 'Chrome') {\n        tem = ua.match(/\\b(OPR|Edge)\\/(\\d+)/);\n        if (tem != null) {\n            return tem.slice(1).join(' ').replace('OPR', 'Opera');\n        }\n    }\n    M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];\n    if ((tem = ua.match(/version\\/(\\d+)/i)) != null) {\n        M.splice(1, 1, tem[1]);\n    }\n    const uaResult = M.join(' ');\n    Entry.userAgent = uaResult;\n    return uaResult;\n};\n\nEntry.setBasicBrush = function (sprite) {\n    const isWebGL = GEHelper.isWebGL;\n    const brush = GEHelper.brushHelper.newBrush();\n    if (sprite.brush) {\n        const parentBrush = sprite.brush;\n        brush.thickness = parentBrush.thickness;\n        brush.rgb = parentBrush.rgb;\n        brush.opacity = parentBrush.opacity;\n        brush.setStrokeStyle(brush.thickness);\n\n        const rgb = brush.rgb;\n        const opacity = 1 - brush.opacity / 100;\n\n        if (isWebGL) {\n            brush.beginStrokeFast(Entry.rgb2Number(rgb.r, rgb.g, rgb.b), opacity);\n        } else {\n            brush.beginStroke(`rgba(${rgb.r},${rgb.g},${rgb.b},${opacity})`);\n        }\n    } else {\n        brush.thickness = 1;\n        brush.rgb = Entry.hex2rgb('#ff0000');\n        brush.opacity = 0;\n        brush.setStrokeStyle(1);\n        if (isWebGL) {\n            brush.beginStrokeFast(0xff0000, 1);\n        } else {\n            brush.beginStroke('rgba(255,0,0,1)');\n        }\n    }\n\n    brush.entity = sprite;\n    const shape = GEHelper.brushHelper.newShape(brush);\n\n    shape.entity = sprite;\n    const selectedObjectContainer = Entry.stage.selectedObjectContainer;\n    selectedObjectContainer.addChildAt(shape, selectedObjectContainer.getChildIndex(sprite.object));\n\n    sprite.brush = brush;\n\n    sprite.shapes.push(shape);\n};\n\nEntry.setCloneBrush = function (sprite, parentBrush) {\n    const isWebGL = GEHelper.isWebGL;\n    const brush = GEHelper.brushHelper.newBrush();\n    brush.thickness = parentBrush.thickness;\n    brush.rgb = parentBrush.rgb;\n    brush.opacity = parentBrush.opacity;\n    brush.setStrokeStyle(brush.thickness);\n\n    const rgb = brush.rgb;\n    const opacity = 1 - brush.opacity / 100;\n    if (isWebGL) {\n        brush.beginStrokeFast(Entry.rgb2Number(rgb.r, rgb.g, rgb.b), opacity);\n    } else {\n        brush.beginStroke(`rgba(${rgb.r},${rgb.g},${rgb.b},${opacity})`);\n    }\n\n    const shape = GEHelper.brushHelper.newShape(brush);\n    shape.entity = sprite;\n    const selectedObjectContainer = Entry.stage.selectedObjectContainer;\n    selectedObjectContainer.addChildAt(shape, selectedObjectContainer.getChildIndex(sprite.object));\n\n    brush.stop = parentBrush.stop;\n\n    sprite.brush = brush;\n\n    sprite.shapes.push(shape);\n};\n\nEntry.setBasicPaint = function (sprite) {\n    const isWebGL = GEHelper.isWebGL;\n    const paint = GEHelper.brushHelper.newPaint();\n    const shape = GEHelper.brushHelper.newShape(paint);\n    paint.entity = sprite;\n    paint.opacity = 0;\n    paint.rgb = Entry.hex2rgb('#ff0000');\n    if (isWebGL) {\n        paint.beginFillFast(0xff0000, 1);\n    } else {\n        paint.beginFill('rgba(255,0,0,1)');\n    }\n    shape.entity = sprite;\n    const selectedObjectContainer = Entry.stage.selectedObjectContainer;\n    selectedObjectContainer.addChildAt(shape, selectedObjectContainer.getChildIndex(sprite.object));\n    sprite.paint = paint;\n    sprite.paintShapes.push(shape);\n};\n\nEntry.isFloat = function (num) {\n    return /\\d+\\.{1}\\d+$/.test(num);\n};\n\nEntry.isInteger = function (value) {\n    return isFinite(value) && Math.floor(value) == value;\n};\n\nEntry.getStringIndex = function (str) {\n    if (!str) {\n        return '';\n    }\n    const result = {\n        string: str,\n        index: 1,\n    };\n    let idx = 0;\n    const num = [];\n    const len = str.length;\n    for (let i = len - 1; i > 0; --i) {\n        const ch = str.charAt(i);\n        if (Entry.Utils.isNumber(ch)) {\n            num.unshift(ch);\n            idx = i;\n        } else {\n            break;\n        }\n    }\n\n    if (idx > 0) {\n        result.string = str.substring(0, idx);\n        result.index = parseInt(num.join('')) + 1;\n    }\n\n    return result;\n};\n\nEntry.getOrderedName = function (str, objects, field) {\n    if (!str) {\n        return 'untitled';\n    }\n    if (!objects || objects.length === 0) {\n        return str;\n    }\n    if (!field) {\n        field = 'name';\n    }\n\n    const maxNumber = Entry.getOrderedNameNumber(str, objects, field);\n    const source = Entry.getStringIndex(str);\n    if (maxNumber > 0) {\n        return source.string + maxNumber;\n    }\n    return str;\n};\n\nEntry.getOrderedNameNumber = function (str, objects, field) {\n    const source = Entry.getStringIndex(str);\n    let maxNumber = 0;\n    for (let i = 0, len = objects.length; i < len; i++) {\n        const target = Entry.getStringIndex(objects[i][field]);\n        if (source.string === target.string && target.index > maxNumber) {\n            maxNumber = target.index;\n        }\n    }\n    return maxNumber;\n};\n\nEntry.changeXmlHashId = function (xmlBlock) {\n    const reg = /function_field/;\n    if (reg.test(xmlBlock.getAttribute('type'))) {\n        const mutations = xmlBlock.getElementsByTagName('mutation');\n        for (let i = 0, len = mutations.length; i < len; i++) {\n            mutations[i].setAttribute('hashid', Entry.generateHash());\n        }\n    }\n    return xmlBlock;\n};\n\nEntry.getMaxFloatPoint = function (numbers) {\n    let max = 0;\n    for (let i = 0, len = numbers.length; i < len; i++) {\n        const n = String(numbers[i]);\n        const idx = n.indexOf('.');\n        if (idx !== -1) {\n            const tmp = n.length - (idx + 1);\n            if (tmp > max) {\n                max = tmp;\n            }\n        }\n    }\n    return Math.min(max, 20);\n};\n\nEntry.convertToRoundedDecimals = function (value, decimals) {\n    if (!Entry.Utils.isNumber(value) || !this.isFloat(value)) {\n        return value;\n    } else {\n        return Number(`${Math.round(`${value}e${decimals}`)}e-${decimals}`);\n    }\n};\n\nEntry.attachEventListener = function (elem, eventType, func) {\n    setTimeout(() => {\n        elem.addEventListener(eventType, func);\n    }, 0);\n};\n\nEntry.deAttachEventListener = function (elem, eventType, func) {\n    elem.removeEventListener(eventType, func);\n};\n\nEntry.isEmpty = _.isEmpty;\n\nEntry.Utils.disableContextmenu = function (node) {\n    if (!node) {\n        return;\n    }\n\n    $(node).on('contextmenu', this.contextPreventFunction);\n};\n\nEntry.Utils.contextPreventFunction = function (e) {\n    e.stopPropagation();\n    e.preventDefault();\n    return false;\n};\n\nEntry.Utils.enableContextmenu = function (node) {\n    if (!node) {\n        return;\n    }\n\n    $(node).off('contextmenu', this.contextPreventFunction);\n};\n\nEntry.Utils.isRightButton = function (e) {\n    return e.button == 2 || e.ctrlKey;\n};\n\nEntry.Utils.isTouchEvent = function ({ type }) {\n    return type.toLowerCase().includes('touch');\n};\n\nEntry.Utils.inherit = function (parent, child) {\n    function F() {}\n\n    F.prototype = parent.prototype;\n    child.prototype = new F();\n    return child;\n};\n\nEntry.bindAnimationCallbackOnce = function ($elem, func) {\n    $elem.one('webkitAnimationEnd animationendo animationend', func);\n};\n\nEntry.Utils.isInInput = function ({ target: { type } }) {\n    return type === 'textarea' || type === 'text' || type === 'number';\n};\n\nEntry.Utils.addFilters = function (boardSvgDom, suffix, isOnlyBlock) {\n    const defs = boardSvgDom.elem('defs');\n\n    //trashcan filter\n    const trashCanFilter = defs.elem('filter', {\n        id: `entryTrashcanFilter_${suffix}`,\n    });\n    trashCanFilter.elem('feGaussianBlur', {\n        in: 'SourceAlpha',\n        stdDeviation: 2,\n        result: 'blur',\n    });\n    trashCanFilter.elem('feOffset', {\n        in: 'blur',\n        dx: 1,\n        dy: 1,\n        result: 'offsetBlur',\n    });\n    trashCanFilter.elem('feColorMatrix', {\n        id: 'recolor',\n        in: 'offsetBlur',\n        type: 'matrix',\n        values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0',\n        result: 'colorMatrix',\n    });\n    const feMerge = trashCanFilter.elem('feMerge');\n    feMerge.elem('feMergeNode', {\n        in: 'colorMatrix',\n    });\n    feMerge.elem(\n        'feMergeNode',\n        {\n            in: 'SourceGraphic',\n        },\n        feMerge\n    );\n\n    const blockSelectFilter = defs.elem('filter', {\n        id: `entryBlockSelectFilter_${suffix}`,\n    });\n    blockSelectFilter.elem('feGaussianBlur', {\n        id: 'blur',\n        in: 'SourceGraphic',\n        stdDeviation: '1',\n        result: 'blur',\n    });\n    const fct = blockSelectFilter.elem('feComponentTransfer', {\n        in: 'blur',\n        result: 'component',\n    });\n    fct.elem('feFuncA', {\n        id: 'contour',\n        type: 'table',\n        tableValues: '0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1',\n    });\n    blockSelectFilter.elem('feColorMatrix', {\n        id: 'recolor',\n        in: 'component',\n        type: 'matrix',\n        values: '0 0 0 0 1 0 0 0 0 0.902 0 0 0 0 0 0 0 0 1 0',\n        result: 'colorMatrix',\n    });\n    const fm = blockSelectFilter.elem('feMerge');\n    fm.elem('feMergeNode', {\n        in: 'colorMatrix',\n    });\n    fm.elem('feMergeNode', {\n        in: 'SourceGraphic',\n    });\n\n    const blockHighlightFilter = defs.elem('filter', {\n        id: `entryBlockHighlightFilter_${suffix}`,\n    });\n    blockHighlightFilter.elem('feOffset', {\n        result: 'offOut',\n        in: 'SourceGraphic',\n        dx: 0,\n        dy: 0,\n    });\n    blockHighlightFilter.elem('feColorMatrix', {\n        result: 'matrixOut',\n        in: 'offOut',\n        type: 'matrix',\n        values: '1.3 0 0 0 0 0 1.3 0 0 0 0 0 1.3 0 0 0 0 0 1 0',\n    });\n\n    defs.elem('filter', {\n        id: `entryBlockDarkenFilter_${suffix}`,\n    }).elem('feColorMatrix', {\n        type: 'matrix',\n        values: '.45 0 0 0 0 0 .45 0 0 0 0 0 .45 0 0 0 0 0 1 0',\n    });\n\n    if (!isOnlyBlock) {\n        const buttonShadow = defs.elem('filter', {\n            id: 'entryButtonShadowFilter',\n        });\n        buttonShadow.elem('feOffset', {\n            result: 'offOut',\n            in: 'SourceGraphic',\n            dx: 1,\n            dy: 1,\n        });\n        buttonShadow.elem('feColorMatrix', {\n            result: 'matrixOut',\n            in: 'offOut',\n            type: 'matrix',\n            values: '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0',\n        });\n        buttonShadow.elem('feGaussianBlur', {\n            result: 'blurOut',\n            in: 'matrixOut',\n            stdDeviation: '1',\n        });\n        buttonShadow.elem('feBlend', {\n            in: 'SourceGraphic',\n            in2: 'blurOut',\n            mode: 'normal',\n        });\n    }\n};\n\nEntry.Utils.addBlockPattern = function (boardSvgDom, suffix) {\n    const pattern = boardSvgDom.elem('pattern', {\n        id: `blockHoverPattern_${suffix}`,\n        class: 'blockHoverPattern',\n        patternUnits: 'userSpaceOnUse',\n        patternTransform: 'translate(12, 0)',\n        x: 0,\n        y: 0,\n        width: 48,\n        height: 28,\n        style: 'display: none',\n    });\n\n    const imagePath = `${Entry.mediaFilePath}block_pattern_(order).svg`;\n    const order = '(order)';\n    for (let i = 1; i < 5; i++) {\n        pattern.elem('image', {\n            class: `pattern${i}`,\n            href: imagePath.replace(order, i),\n            x: 0,\n            y: 0,\n            width: 48,\n            height: 28,\n        });\n    }\n\n    return { pattern };\n};\n\nfunction handleOptionalBlocksActive(item) {\n    const { expansionBlocks = [], aiUtilizeBlocks = [] } = item;\n    if (expansionBlocks.length > 0) {\n        Entry.expansion.addExpansionBlocks(expansionBlocks);\n    }\n    if (aiUtilizeBlocks.length > 0) {\n        Entry.aiUtilize.addAIUtilizeBlocks(aiUtilizeBlocks);\n    }\n}\n\nEntry.Utils.addNewBlock = function (item) {\n    const {\n        script,\n        functions,\n        messages,\n        variables,\n        learning = {},\n        tables = [],\n        expansionBlocks = [],\n        aiUtilizeBlocks = [],\n    } = item;\n    const parseScript = JSON.parse(script);\n    if (!parseScript) {\n        return;\n    }\n\n    if (\n        Entry.getMainWS().mode === Entry.Workspace.MODE_VIMBOARD &&\n        (!Entry.TextCodingUtil.canUsePythonVariables(variables) ||\n            !Entry.TextCodingUtil.canUsePythonFunctions(functions))\n    ) {\n        return Entry.modal.alert(Lang.Menus.object_import_syntax_error);\n    }\n\n    const objectIdMap = {};\n    variables.forEach((variable) => {\n        const { object } = variable;\n        if (object) {\n            variable.object = _.get(Entry, ['container', 'selectedObject', 'id'], '');\n        }\n    });\n    DataTable.setTables(tables);\n    if (!Entry.options.aiUtilizeDisable) {\n        Entry.aiLearning.load(learning);\n    }\n    handleOptionalBlocksActive(item);\n\n    Entry.variableContainer.appendMessages(messages);\n    Entry.variableContainer.appendVariables(variables);\n    Entry.variableContainer.appendFunctions(functions);\n    if (!Entry.container || !Entry.container.isSceneObjectsExist()) {\n        if (Entry.toast && !(this.objectAlert && Entry.toast.isOpen(this.objectAlert))) {\n            this.objectAlert = Entry.toast.alert(\n                Lang.Workspace.add_object_alert,\n                Lang.Workspace.add_object_alert_msg\n            );\n        }\n        return;\n    }\n    Entry.do(\n        'addThread',\n        parseScript.map((block) => {\n            block.id = Entry.generateHash();\n            return block;\n        })\n    );\n};\n\nEntry.Utils.addNewObject = function (sprite) {\n    if (sprite) {\n        const {\n            objects,\n            functions,\n            messages,\n            variables,\n            tables = [],\n            expansionBlocks = [],\n            aiUtilizeBlocks = [],\n        } = sprite;\n\n        if (\n            Entry.getMainWS().mode === Entry.Workspace.MODE_VIMBOARD &&\n            (!Entry.TextCodingUtil.canUsePythonVariables(variables) ||\n                !Entry.TextCodingUtil.canUsePythonFunctions(functions))\n        ) {\n            return Entry.modal.alert(Lang.Menus.object_import_syntax_error);\n        }\n        const objectIdMap = {};\n        DataTable.setTables(tables);\n        handleOptionalBlocksActive(sprite);\n        variables.forEach((variable) => {\n            const { object } = variable;\n            if (object) {\n                const id = variable.id;\n                const idMap = objectIdMap[object];\n                variable.id = Entry.generateHash();\n                if (!idMap) {\n                    variable.object = Entry.generateHash();\n                    objectIdMap[object] = {\n                        objectId: variable.object,\n                        variableOriginId: [id],\n                        variableId: [variable.id],\n                    };\n                } else {\n                    variable.object = idMap.objectId;\n                    idMap.variableOriginId.push(id);\n                    idMap.variableId.push(variable.id);\n                }\n            }\n        });\n        Entry.variableContainer.appendMessages(messages);\n        Entry.variableContainer.appendVariables(variables);\n        Entry.variableContainer.appendFunctions(functions);\n\n        objects.forEach((object) => {\n            const idMap = objectIdMap[object.id];\n            if (idMap) {\n                let script = object.script;\n                idMap.variableOriginId.forEach((id, idx) => {\n                    const regex = new RegExp(id, 'gi');\n                    script = script.replace(regex, idMap.variableId[idx]);\n                });\n                object.script = script;\n                object.id = idMap.objectId;\n            } else if (Entry.container.getObject(object.id)) {\n                object.id = Entry.generateHash();\n            }\n            if (!object.objectType) {\n                object.objectType = 'sprite';\n            }\n            Entry.container.addObject(object, 0);\n        });\n    }\n};\n\nEntry.Utils.COLLISION = {\n    NONE: 0,\n    UP: 1,\n    RIGHT: 2,\n    LEFT: 3,\n    DOWN: 4,\n};\n\nEntry.Utils.createMouseEvent = function (type, event) {\n    const e = document.createEvent('MouseEvent');\n    e.initMouseEvent(\n        type,\n        true,\n        true,\n        window,\n        0,\n        0,\n        0,\n        event.clientX,\n        event.clientY,\n        false,\n        false,\n        false,\n        false,\n        0,\n        null\n    );\n    return e;\n};\n\nEntry.Utils.stopProjectWithToast = _throttle(\n    async (scope, message, error) => {\n        let block = scope.block;\n        message = message || 'Runtime Error';\n        const toast = error.toast;\n        const engine = Entry.engine;\n\n        if (engine && engine.isState('run')) {\n            await engine.toggleStop();\n        }\n        if (Entry.type === 'workspace') {\n            if (scope.block && 'funcBlock' in scope.block) {\n                block = scope.block.funcBlock;\n            } else if (scope.funcExecutor) {\n                block = scope.funcExecutor.scope.block;\n                Entry.Func.edit(scope.type);\n            }\n\n            if (block) {\n                const id = block.getCode().object && block.getCode().object.id;\n                if (id) {\n                    Entry.container.selectObject(block.getCode().object.id, true);\n                }\n                const view = block.view;\n                view && view.getBoard().activateBlock(block);\n            }\n        }\n\n        if (message === 'IncompatibleError' && Entry.toast) {\n            Entry.toast.alert(\n                Lang.Msgs.warn,\n                toast || [Lang.Workspace.check_runtime_error, Lang.Workspace.check_browser_error],\n                true\n            );\n            Entry.engine.hideAllAudioPanel();\n        }\n        if (message === 'OfflineError' && Entry.toast) {\n            Entry.toast.alert(\n                Lang.Msgs.warn,\n                toast || [\n                    Lang.Workspace.check_runtime_error,\n                    Lang.Workspace.offline_not_compatible_error,\n                ],\n                true\n            );\n        } else if (Entry.toast) {\n            Entry.toast.alert(Lang.Msgs.warn, Lang.Workspace.check_runtime_error, true);\n        }\n\n        if (error) {\n            const newError = new Error(`${message}: ${error.message}`);\n            newError.stack = error.stack;\n            throw newError;\n        }\n\n        throw new Error(message);\n    },\n    300,\n    { trailing: false }\n);\n\nEntry.Utils.AsyncError = function (message) {\n    this.name = 'AsyncError';\n    this.message = message || 'Waiting for callback';\n};\n\nEntry.Utils.AsyncError.prototype = new Error();\nEntry.Utils.AsyncError.prototype.constructor = Entry.Utils.AsyncError;\n\nEntry.Utils.IncompatibleError = function (message, toast) {\n    this.name = 'IncompatibleError';\n    this.message = message || 'IncompatibleError';\n    this.toast = toast || null;\n};\nEntry.Utils.IncompatibleError.prototype = new Error();\nEntry.Utils.IncompatibleError.prototype.constructor = Entry.Utils.IncompatibleError;\n\nEntry.Utils.OfflineError = function (message, toast) {\n    this.name = 'OfflineError';\n    this.message = message || 'OfflineError';\n    this.toast = toast || null;\n};\nEntry.Utils.OfflineError.prototype = new Error();\nEntry.Utils.OfflineError.prototype.constructor = Entry.Utils.OfflineError;\n\nEntry.Utils.isChrome = function () {\n    return /chrom(e|ium)/.test(navigator.userAgent.toLowerCase());\n};\n\nEntry.Utils.getUsedFonts = function (project) {\n    if (!project) {\n        return;\n    }\n    const getFamily = (x) =>\n        x.entity.font\n            .split(' ')\n            .filter((t) => t.indexOf('bold') < 0 && t.indexOf('italic') < 0 && t.indexOf('px') < 0)\n            .join(' ');\n    return _uniq(project.objects.filter((x) => x.objectType === 'textBox').map(getFamily));\n};\n\nEntry.Utils.waitForWebfonts = function (fonts, callback) {\n    return Promise.all(\n        fonts.map(\n            (font) =>\n                new Promise((resolve) => {\n                    FontFaceOnload(font, {\n                        success() {\n                            resolve();\n                        },\n                        error() {\n                            console.log('fail', font);\n                            resolve();\n                        },\n                        timeout: 5000,\n                    });\n                })\n        )\n    ).then(() => {\n        console.log('font loaded');\n        callback && callback();\n    });\n};\n\nwindow.requestAnimFrame = (function () {\n    return (\n        window.requestAnimationFrame ||\n        window.webkitRequestAnimationFrame ||\n        window.mozRequestAnimationFrame ||\n        function (callback) {\n            window.setTimeout(callback, 1000 / 60);\n        }\n    );\n})();\n\nEntry.isMobile = function () {\n    if (Entry.device) {\n        return Entry.device === 'tablet';\n    }\n\n    const platform = window.platform;\n    const ret =\n        platform && platform.type && (platform.type === 'tablet' || platform.type === 'mobile');\n\n    if (ret) {\n        Entry.device = 'tablet';\n        return true;\n    } else {\n        Entry.device = 'desktop';\n        return false;\n    }\n};\n\nEntry.Utils.mobileAgentParser = function (userAgent) {\n    const applePhone = /iPhone/i;\n    const appleIpod = /iPod/i;\n    const appleTablet = /iPad/i;\n    const androidPhone = /(?=.*\\bAndroid\\b)(?=.*\\bMobile\\b)/i; // Match 'Android' AND 'Mobile'\n    const androidTablet = /Android/i;\n    const amazonPhone = /(?=.*\\bAndroid\\b)(?=.*\\bSD4930UR\\b)/i;\n    const amazonTablet =\n        // eslint-disable-next-line max-len\n        /(?=.*\\bAndroid\\b)(?=.*\\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\\b)/i;\n    const windowsPhone = /Windows Phone/i;\n    const windowsTablet = /(?=.*\\bWindows\\b)(?=.*\\bARM\\b)/i; // Match 'Windows' AND 'ARM'\n    const otherBlackberry = /BlackBerry/i;\n    const otherBlackberry10 = /BB10/i;\n    const otherOpera = /Opera Mini/i;\n    const otherChrome = /(CriOS|Chrome)(?=.*\\bMobile\\b)/i;\n    const otherFirefox = /(?=.*\\bFirefox\\b)(?=.*\\bMobile\\b)/i; // Match 'Firefox' AND 'Mobile'\n    const sevenInch = new RegExp(\n        '(?:' + // Non-capturing group\n            'Nexus 7' + // Nexus 7\n            '|' + // OR\n            'BNTV250' + // B&N Nook Tablet 7 inch\n            '|' + // OR\n            'Kindle Fire' + // Kindle Fire\n            '|' + // OR\n            'Silk' + // Kindle Fire, Silk Accelerated\n            '|' + // OR\n            'GT-P1000' + // Galaxy Tab 7 inch\n            ')', // End non-capturing group\n\n        'i'\n    ); // Case-insensitive matching\n\n    const match = function (regex, userAgent) {\n        return regex.test(userAgent);\n    };\n\n    let ua = userAgent || navigator.userAgent;\n\n    // Facebook mobile app's integrated browser adds a bunch of strings that\n    // match everything. Strip it out if it exists.\n    let tmp = ua.split('[FBAN');\n    if (typeof tmp[1] !== 'undefined') {\n        ua = tmp[0];\n    }\n\n    // Twitter mobile app's integrated browser on iPad adds a \"Twitter for\n    // iPhone\" string. Same probable happens on other tablet platforms.\n    // This will confuse detection so strip it out if it exists.\n    tmp = ua.split('Twitter');\n    if (typeof tmp[1] !== 'undefined') {\n        ua = tmp[0];\n    }\n\n    this.apple = {\n        phone: match(applePhone, ua),\n        ipod: match(appleIpod, ua),\n        tablet: !match(applePhone, ua) && match(appleTablet, ua),\n        device: match(applePhone, ua) || match(appleIpod, ua) || match(appleTablet, ua),\n    };\n    this.amazon = {\n        phone: match(amazonPhone, ua),\n        tablet: !match(amazonPhone, ua) && match(amazonTablet, ua),\n        device: match(amazonPhone, ua) || match(amazonTablet, ua),\n    };\n    this.android = {\n        phone: match(amazonPhone, ua) || match(androidPhone, ua),\n        tablet:\n            !match(amazonPhone, ua) &&\n            !match(androidPhone, ua) &&\n            (match(amazonTablet, ua) || match(androidTablet, ua)),\n        device:\n            match(amazonPhone, ua) ||\n            match(amazonTablet, ua) ||\n            match(androidPhone, ua) ||\n            match(androidTablet, ua),\n    };\n    this.windows = {\n        phone: match(windowsPhone, ua),\n        tablet: match(windowsTablet, ua),\n        device: match(windowsPhone, ua) || match(windowsTablet, ua),\n    };\n    this.other = {\n        blackberry: match(otherBlackberry, ua),\n        blackberry10: match(otherBlackberry10, ua),\n        opera: match(otherOpera, ua),\n        firefox: match(otherFirefox, ua),\n        chrome: match(otherChrome, ua),\n        device:\n            match(otherBlackberry, ua) ||\n            match(otherBlackberry10, ua) ||\n            match(otherOpera, ua) ||\n            match(otherFirefox, ua) ||\n            match(otherChrome, ua),\n    };\n    this.seven_inch = match(sevenInch, ua);\n    this.any =\n        this.apple.device ||\n        this.android.device ||\n        this.windows.device ||\n        this.other.device ||\n        this.seven_inch;\n\n    // excludes 'other' devices and ipods, targeting touchscreen phones\n    this.phone = this.apple.phone || this.android.phone || this.windows.phone;\n\n    // excludes 7 inch devices, classifying as phone or tablet is left to the user\n    this.tablet = this.apple.tablet || this.android.tablet || this.windows.tablet;\n\n    return this;\n};\n\nEntry.Utils.convertMouseEvent = function (e) {\n    if (e.originalEvent && e.originalEvent.touches) {\n        return e.originalEvent.touches[0];\n    } else if (e.changedTouches) {\n        return e.changedTouches[0];\n    } else {\n        return e;\n    }\n};\n\nEntry.Utils.hasSpecialCharacter = function (str) {\n    const reg = /!|@|#|\\$|%|\\^|&|\\*|\\(|\\)|\\+|=|-|\\[|\\]|\\\\|\\'|;|,|\\.|\\/|{|}|\\||\\\"|:|<|>|\\?/g;\n    return reg.test(str);\n};\n\nEntry.Utils.getBlockCategory = (function () {\n    const map = {};\n    let allBlocks;\n    return function (blockType) {\n        if (!blockType) {\n            return;\n        }\n\n        if (map[blockType]) {\n            return map[blockType];\n        }\n\n        if (!allBlocks) {\n            allBlocks = EntryStatic.getAllBlocks();\n        }\n\n        for (let i = 0; i < allBlocks.length; i++) {\n            const data = allBlocks[i];\n            const category = data.category;\n            if (data.blocks.indexOf(blockType) > -1) {\n                map[blockType] = category;\n                return category;\n            }\n        }\n    };\n})();\n\nEntry.Utils.getUniqObjectsBlocks = function (objects) {\n    const _typePicker = _.partial(_.result, _, 'type');\n\n    return _.chain(objects || Entry.container.objects_)\n        .map(({ script }) => {\n            if (!(script instanceof Entry.Code)) {\n                script = new Entry.Code(script);\n            }\n            return script.getBlockList().map(_typePicker);\n        })\n        .flatten()\n        .uniq()\n        .value();\n};\n\nEntry.Utils.getObjectsBlocks = function (objects) {\n    const _typePicker = _.partial(_.result, _, 'type');\n    return _.chain(objects || Entry.container.objects_)\n        .map(({ script }) => {\n            if (!(script instanceof Entry.Code)) {\n                script = new Entry.Code(script);\n            }\n            return script.getBlockList(true).map(_typePicker);\n        })\n        .flatten()\n        .value();\n};\n\nconst scheduler = new Scheduler();\n\nEntry.Utils.getObjectsBlocksBySceneId = _.memoize((sceneId) => {\n    if (!sceneId) {\n        return [];\n    }\n    const _typePicker = _.partial(_.result, _, 'type');\n    const job = new Promise((resolve) => {\n        scheduler.run(function* () {\n            const result = [];\n            const codes = Entry.container.objects_;\n            for (const code of codes) {\n                if (code?.scene?.id !== sceneId) {\n                    continue;\n                }\n                let script = code.script;\n                if (!(script instanceof Entry.Code)) {\n                    script = new Entry.Code(script);\n                }\n                result.push(script.getBlockListForEventThread(true).map(_typePicker));\n                yield;\n            }\n            resolve(_.flatten(result));\n        });\n    });\n    return job;\n});\n\nEntry.Utils.getObjectsBlocksForEventThread = _.memoize((object) => {\n    const nowScheduler = new Scheduler();\n    const _typePicker = _.partial(_.result, _, 'type');\n    const job = new Promise((resolve) => {\n        nowScheduler.run(function* () {\n            const result = [];\n            try {\n                let codes;\n                if (object) {\n                    codes = [object];\n                } else {\n                    codes = Entry.container.objects_;\n                }\n                for (const code of codes) {\n                    let script = code.script;\n                    if (!(script instanceof Entry.Code)) {\n                        script = new Entry.Code(script);\n                    }\n                    result.push(script.getBlockListForEventThread(true).map(_typePicker));\n                    yield;\n                }\n                resolve(_.flatten(result));\n            } catch (e) {\n                console.warn('blockCount : ', e);\n                resolve(_.flatten(result));\n            }\n        });\n    });\n    return job;\n});\n\nEntry.Utils.clearObjectsBlocksForEventThread = () => {\n    Entry.Utils.getObjectsBlocksForEventThread.cache = new _.memoize.Cache();\n    Entry.Utils.getObjectsBlocksBySceneId.cache = new _.memoize.Cache();\n};\n\nEntry.Utils.makeCategoryDataByBlocks = function (blockArr) {\n    if (!blockArr) {\n        return;\n    }\n    const that = this;\n\n    const data = EntryStatic.getAllBlocks();\n    const categoryIndexMap = {};\n    for (let i = 0; i < data.length; i++) {\n        const datum = data[i];\n        datum.blocks = [];\n        categoryIndexMap[datum.category] = i;\n    }\n\n    blockArr.forEach((b) => {\n        const category = that.getBlockCategory(b);\n        const index = categoryIndexMap[category];\n        if (index === undefined) {\n            return;\n        }\n        data[index].blocks.push(b);\n    });\n\n    const allBlocks = EntryStatic.getAllBlocks();\n    return allBlocks\n        .map((block) => {\n            const { category, blocks } = block;\n            if (category === 'func') {\n                return { blocks: [] };\n            }\n            return {\n                category,\n                blocks: _intersection(blockArr, blocks),\n            };\n        })\n        .filter(({ blocks }) => blocks.length);\n};\n\nEntry.Utils.blur = function () {\n    const elem = document.activeElement;\n    elem && elem.blur && elem.blur();\n};\n\nEntry.Utils.getWindow = function (hashId) {\n    if (!hashId) {\n        return;\n    }\n    for (let i = 0; i < window.frames.length; i++) {\n        const frame = window.frames[i];\n        if (frame.Entry && frame.Entry.hashId === hashId) {\n            return frame;\n        }\n    }\n};\n\nEntry.Utils.restrictAction = function (exceptions = [], callback, noDispose) {\n    const that = this;\n    exceptions = exceptions.map(_.head);\n\n    const handler = function (e) {\n        e = e || window.event;\n        const target = e.target || e.srcElement;\n        if (!that.isRightButton(e)) {\n            for (let i = 0; i < exceptions.length; i++) {\n                const exception = exceptions[i];\n                if (exception === target || $.contains(exception, target)) {\n                    if (!noDispose) {\n                        callback(e);\n                    } else {\n                        target.focus && target.focus();\n                    }\n                    return;\n                }\n            }\n        }\n\n        if (!e.preventDefault) {\n            //IE quirks\n            e.returnValue = false;\n            e.cancelBubble = true;\n        }\n        e.preventDefault();\n        e.stopPropagation();\n    };\n\n    this._restrictHandler = handler;\n\n    const entryDom = Entry.getDom();\n    Entry.Utils.disableContextmenu(entryDom);\n    if (entryDom.addEventListener) {\n        entryDom.addEventListener('click', handler, true);\n        entryDom.addEventListener('mousedown', handler, true);\n        entryDom.addEventListener('mouseup', handler, true);\n        entryDom.addEventListener('touchstart', handler, true);\n    } else {\n        entryDom.attachEvent('onclick', handler);\n        entryDom.attachEvent('onmousedown', handler);\n        entryDom.attachEvent('onmouseup', handler);\n        entryDom.attachEvent('ontouchstart', handler);\n    }\n};\n\nEntry.Utils.allowAction = function () {\n    const entryDom = Entry.getDom();\n    Entry.Utils.enableContextmenu(entryDom);\n    if (this._restrictHandler) {\n        if (entryDom.addEventListener) {\n            entryDom.removeEventListener('click', this._restrictHandler, true);\n            entryDom.removeEventListener('mousedown', this._restrictHandler, true);\n            entryDom.removeEventListener('mouseup', this._restrictHandler, true);\n            entryDom.removeEventListener('touchstart', this._restrictHandler, true);\n        } else {\n            entryDom.detachEvent('onclick', this._restrictHandler);\n            entryDom.detachEvent('onmousedown', this._restrictHandler);\n            entryDom.detachEvent('onmouseup', this._restrictHandler);\n            entryDom.detachEvent('ontouchstart', this._restrictHandler);\n        }\n        delete this._restrictHandler;\n    }\n};\n\nEntry.Utils.glideBlock = function (svgGroup, x, y, callback) {\n    const rect = svgGroup.getBoundingClientRect();\n    const svgDom = Entry.Dom(\n        $(\n            '<svg id=\"globalSvg\" width=\"10\" height=\"10\"' +\n                'version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"></svg>'\n        ),\n        { parent: $(document.body) }\n    );\n    svgGroup = $(svgGroup.cloneNode(true));\n    svgGroup.attr({ transform: 'translate(8,0)' });\n    svgDom.append(svgGroup);\n    svgDom.css({\n        top: rect.top,\n        left: rect.left,\n    });\n    svgDom.velocity(\n        {\n            top: y,\n            left: x - 8,\n        },\n        {\n            duration: 1200,\n            complete() {\n                setTimeout(() => {\n                    svgDom.remove();\n                    callback();\n                }, 500);\n            },\n            easing: 'ease-in-out',\n        }\n    );\n};\n\nEntry.Utils.getScrollPos = function () {\n    return {\n        left: window.pageXOffset || document.documentElement.scrollLeft,\n        top: window.pageYOffset || document.documentElement.scrollTop,\n    };\n};\n\nEntry.Utils.isPointInRect = ({ x, y }, { top, bottom, left, right }) =>\n    _.inRange(x, left, right) && _.inRange(y, top, bottom);\n\nEntry.Utils.getBoundingClientRectMemo = _.memoize((target, offset = {}) => {\n    const rect = target.getBoundingClientRect();\n    const result = {\n        top: rect.top,\n        bottom: rect.bottom,\n        left: rect.left,\n        right: rect.right,\n    };\n    Object.keys(offset).forEach((key) => {\n        result[key] += offset[key];\n    });\n    return result;\n});\n\nEntry.Utils.clearClientRectMemo = () => {\n    Entry.Utils.getBoundingClientRectMemo.cache = new _.memoize.Cache();\n};\n\nEntry.Utils.getPosition = (event) => {\n    const position = {\n        x: 0,\n        y: 0,\n    };\n    if (event.touches && event.touches[0]) {\n        const touch = event.touches[0];\n        position.x = touch.pageX;\n        position.y = touch.pageY;\n    } else {\n        position.x = event.pageX;\n        position.y = event.pageY;\n    }\n    return position;\n};\n\nEntry.Utils.copy = function (target) {\n    return JSON.parse(JSON.stringify(target));\n};\n\n//helper function for development and debug\nEntry.Utils.getAllObjectsBlockList = function () {\n    return Entry.container.objects_.reduce(\n        (prev, { script }) => prev.concat(script.getBlockList()),\n        []\n    );\n};\n\nEntry.Utils.toFixed = function (value, len) {\n    const length = len || 1;\n    const powValue = Math.pow(10, length);\n\n    let retValue = Math.round(value * powValue) / powValue;\n\n    if (Entry.isFloat(retValue)) {\n        return String(retValue);\n    } else {\n        retValue += '.';\n        for (let i = 0; i < length; i++) {\n            retValue += '0';\n        }\n        return retValue;\n    }\n};\n\nEntry.Utils.setVolume = function (volume) {\n    this._volume = _clamp(volume, 0, 1);\n\n    Entry.soundInstances\n        .getAllValues()\n        .filter(({ soundType }) => !soundType)\n        .forEach((instance) => {\n            instance.volume = this._volume;\n        });\n};\n\nEntry.Utils.getVolume = function () {\n    if (this._volume || this._volume === 0) {\n        return this._volume;\n    }\n    return 1;\n};\n\nEntry.Utils.playBGM = function (id, option = {}) {\n    const instance = createjs.Sound.play(id, Object.assign({ volume: 1 }, option));\n    return instance;\n};\n\nEntry.Utils.addBGMInstances = function (instance, sprite = 'global') {\n    Entry.bgmInstances.add(sprite, instance);\n    instance.on('complete', () => {\n        Entry.bgmInstances.deleteItemByKeyAndValue(sprite, instance);\n    });\n};\n\nEntry.Utils.forceStopBGM = function () {\n    _.each([...Entry.bgmInstances.getAllValues()], (instance) => {\n        instance?.dispatchEvent?.('complete');\n        instance?.stop?.();\n    });\n    Entry.bgmInstances.clear();\n};\n\nEntry.Utils.forceStopSounds = function () {\n    _.each([...Entry.soundInstances.getAllValues()], (instance) => {\n        instance?.dispatchEvent?.('complete');\n        instance?.stop?.();\n    });\n    Entry.soundInstances.clear();\n};\n\nEntry.Utils.playSound = function (id, option = {}) {\n    const instance = createjs.Sound.play(id, Object.assign({ volume: this._volume }, option));\n    if (instance.sourceNode?.playbackRate) {\n        instance.sourceNode.playbackRate.value = Entry.playbackRateValue;\n    }\n    return instance;\n};\n\nEntry.Utils.addSoundInstances = function (instance, sprite = 'global') {\n    Entry.soundInstances.add(sprite, instance);\n    instance.on('complete', () => {\n        Entry.soundInstances.deleteItemByKeyAndValue(sprite, instance);\n    });\n};\n\nEntry.Utils.pauseSoundInstances = function () {\n    Entry.soundInstances.getAllValues().forEach((instance) => {\n        instance.paused = true;\n    });\n    Entry.bgmInstances.getAllValues().forEach((instance) => {\n        instance.paused = true;\n    });\n};\n\nEntry.Utils.recoverSoundInstances = function () {\n    Entry.soundInstances.getAllValues().forEach((instance) => {\n        instance.paused = false;\n        if (instance.sourceNode?.playbackRate) {\n            instance.sourceNode.playbackRate.value = Entry.playbackRateValue;\n        }\n    });\n    Entry.bgmInstances.getAllValues().forEach((instance) => {\n        instance.paused = false;\n    });\n};\n\nEntry.Utils.hasClass = (elem, name) => ` ${elem.getAttribute('class')} `.indexOf(` ${name} `) >= 0;\n\nEntry.Utils.addClass = (elem, name) => {\n    if (!Entry.Utils.hasClass(elem, name)) {\n        elem.setAttribute('class', (elem.getAttribute('class') ? `${elem.className} ` : '') + name);\n    }\n};\n\nEntry.Utils.toggleClass = (elem, name, force) => {\n    if (force || (typeof force === 'undefined' && !Entry.Utils.hasClass(elem, name))) {\n        Entry.Utils.addClass(elem, name);\n    } else {\n        Entry.Utils.removeClass(elem, name);\n    }\n};\n\nEntry.Utils.removeClass = (elem, name) => {\n    let set = ` ${elem.getAttribute('class')} `;\n\n    while (set.indexOf(` ${name} `) >= 0) {\n        set = set.replace(` ${name} `, ' ');\n    }\n\n    const result = typeof set.trim === 'function' ? set.trim() : set.replace(/^\\s+|\\s+$/g, '');\n    elem.setAttribute('class', result);\n};\n\nEntry.Utils.bindBlockViewHoverEvent = function (board, dom) {\n    if (Entry.isMobile()) {\n        return;\n    }\n\n    dom.on('mouseenter mouseleave', 'path', function ({ type }) {\n        if (this.getAttribute('class') !== 'blockPath') {\n            return;\n        }\n        const block = board.code.findById(this.getAttribute('blockId'));\n        if (!block) {\n            return;\n        }\n        const blockView = block.view;\n\n        if (!blockView._mouseEnable) {\n            return;\n        }\n\n        blockView.setHoverBlockView({\n            that: blockView,\n            blockView: type === 'mouseenter' ? blockView : undefined,\n        });\n    });\n};\n\nEntry.Utils.bindBlockExecuteFocusEvents = function () {\n    Entry.addEventListener('blockExecute', (view) => {\n        if (!view) {\n            return;\n        }\n        this.focusBlockView(view.getBoard(), view);\n    });\n\n    Entry.addEventListener('blockExecuteEnd', this.focusBlockView);\n};\n\nEntry.Utils.focusBlockView = (() => {\n    let _last;\n\n    function _getAllElem(elem) {\n        return $(elem).find('*:not(g)');\n    }\n\n    return (board, blockView) => {\n        const { svgGroup, suffix } = board || Entry.getMainWS().board || {};\n\n        if (!svgGroup || !suffix || (_last && _last === blockView)) {\n            return;\n        }\n\n        if (blockView) {\n            //darken all\n            _getAllElem(svgGroup).attr('filter', `url(#entryBlockDarkenFilter_${suffix})`);\n\n            //brighten only block\n            const { _path, contentSvgGroup } = blockView;\n            $(_path).removeAttr('filter');\n            $(contentSvgGroup).find('*:not(g)').removeAttr('filter');\n        } else {\n            //brighten all\n            _getAllElem(svgGroup).removeAttr('filter');\n        }\n\n        _last = blockView;\n    };\n})();\n\nEntry.Utils.isDomActive = function (dom) {\n    return !!(dom && document.activeElement === dom);\n};\n\nEntry.Utils.when = function (predicate, fn) {\n    return function (...args) {\n        if (predicate.apply(this, args)) {\n            return fn && fn.apply(this, args);\n        }\n    };\n};\n\nEntry.Utils.whenEnter = function (fn) {\n    return Entry.Utils.when(({ keyCode, repeat }) => keyCode === 13 && !repeat, fn);\n};\n\nEntry.Utils.blurWhenEnter = Entry.Utils.whenEnter(function () {\n    this.blur();\n});\n\nEntry.Utils.whenWithTimeout = function (predicate, fn, time = 200) {\n    return function (...args) {\n        if (this._timer) {\n            clearTimeout(this._timer);\n            delete this._timer;\n        }\n        this._timer = setTimeout(() => {\n            if (predicate.apply(this, args)) {\n                return fn.apply(this, args);\n            }\n        }, time);\n    };\n};\n\nEntry.Utils.setBlurredTimer = function (func) {\n    return Entry.Utils.whenWithTimeout(function () {\n        if (this._focused) {\n            this._focused = false;\n            return true;\n        }\n        return false;\n    }, func);\n};\n\nEntry.Utils.setFocused = function () {\n    if (this._timer) {\n        clearTimeout(this._timer);\n        delete this._timer;\n    }\n    this._focused = true;\n};\n\nEntry.Utils.focusIfNotActive = function (dom) {\n    if (Array.isArray(dom)) {\n        dom = Entry.getDom(dom);\n    }\n    if (!dom) {\n        return;\n    }\n    if (!Entry.Utils.isDomActive(dom)) {\n        dom.focus && dom.focus();\n    }\n};\n\n// 터치와 마우스의 이벤트를 맞춰주는 함수\nEntry.Utils.getMouseEvent = function (event) {\n    let mouseEvent;\n    if (event.originalEvent && event.originalEvent.touches) {\n        mouseEvent = event.originalEvent.touches[0];\n    } else if (event.touches) {\n        mouseEvent = event.touches[0];\n    } else {\n        mouseEvent = event;\n    }\n    return mouseEvent;\n};\n\nEntry.Utils.removeBlockByType = function (blockType, callback) {\n    const objects = Entry.container.getAllObjects();\n    objects.forEach(({ id, script }) => {\n        Entry.do('selectObject', id).isPass(true);\n        script.getBlockList(false, blockType).forEach((b, index) => {\n            Entry.do('destroyBlock', b).isPass(true);\n        });\n    });\n    Entry.variableContainer.removeBlocksInFunctionByType(blockType);\n\n    if (callback) {\n        callback();\n    }\n};\n\nEntry.Utils.removeBlockByType2 = function (blockType, callback) {\n    Entry.variableContainer.removeBlocksInFunctionByType(blockType);\n    const objects = Entry.container.getAllObjects();\n    objects.forEach(({ id, script }) => {\n        script.getBlockList(false, blockType).forEach((block, index) => {\n            block.destroy();\n        });\n    });\n\n    if (callback) {\n        callback();\n    }\n};\n\nEntry.Utils.sleep = (time = 0) =>\n    new Promise((resolve) => {\n        setTimeout(resolve, time);\n    });\n\nEntry.Utils.runAsync = async (func) => {\n    await Entry.Utils.sleep();\n    await func();\n};\n\nEntry.Utils.runAsyncCurry =\n    (func, time = 0) =>\n    async (...args) => {\n        await Entry.Utils.sleep(time);\n        await func(...args);\n    };\n\nEntry.Utils.removeBlockByTypeAsync = async (blockType, callback) => {\n    Entry.dispatchEvent('removeFunctionsStart');\n    await Entry.variableContainer.removeBlocksInFunctionByTypeAsync(blockType);\n    const objects = Entry.container.getAllObjects();\n    await Promise.all(\n        objects.map(async ({ script }) => {\n            await Promise.all(\n                script.getBlockList(false, blockType).map(\n                    Entry.Utils.runAsyncCurry(async (block) => {\n                        block.destroy();\n                    })\n                )\n            );\n        })\n    );\n    Entry.dispatchEvent('removeFunctionsEnd');\n    if (callback) {\n        callback();\n    }\n};\n\nEntry.Utils.isUsedBlockType = function (blockType) {\n    const objects = Entry.container.getAllObjects();\n    const usedInObject = objects.some(\n        ({ script }) => !!script.getBlockList(false, blockType).length\n    );\n    if (usedInObject) {\n        return true;\n    }\n    return Entry.variableContainer.isUsedBlockTypeInFunction(blockType);\n};\n\nEntry.Utils.combineCloudVariable = ({ variables, cloudVariable }) => {\n    let items;\n    if (typeof cloudVariable === 'string') {\n        try {\n            items = JSON.parse(cloudVariable);\n        } catch (e) {}\n    }\n    if (!Array.isArray(items)) {\n        return variables;\n    }\n    return variables.map((variable) => {\n        const cloud = items.find(({ id }) => id === variable.id);\n        if (cloud) {\n            return { ...variable, ...cloud };\n        }\n        return variable;\n    });\n};\n\nEntry.Utils.asyncAnimationFrame = (func) => {\n    let captureTimeout = false;\n\n    const asyncFunc = () => {\n        if (!Entry.engine.isState('run')) {\n            return;\n        }\n        if (func instanceof Promise) {\n            func().then(() => {\n                captureTimeout = requestAnimationFrame(asyncFunc);\n            });\n        } else if (func instanceof Function) {\n            func();\n            captureTimeout = requestAnimationFrame(asyncFunc);\n        }\n    };\n\n    captureTimeout = requestAnimationFrame(asyncFunc);\n    return () => {\n        cancelAnimationFrame(captureTimeout);\n    };\n};\n\nEntry.Utils.stringFormat = (text, ...args) => {\n    if (!text) {\n        return text;\n    }\n    let result = text;\n    for (let i = 0; i < args.length; i++) {\n        const regexp = new RegExp(`\\\\{${i}\\\\}`, 'gi');\n        result = result.replace(regexp, args[i]);\n    }\n    return result;\n};\n\nEntry.Utils.shortenNumber = (num = 0) => {\n    if (num >= 1000000000) {\n        return `${_round(num / 1000000000, 1)}B`;\n    }\n    if (num >= 1000000) {\n        return `${_round(num / 1000000, 1)}M`;\n    }\n    if (num >= 100000) {\n        return `${_round(num / 1000, 1)}K`;\n    }\n    return num;\n};\n\nEntry.Utils.doCodeChange = () => {\n    if (Entry.codeChangedEvent) {\n        Entry.Utils.clearObjectsBlocksForEventThread();\n        Entry.codeChangedEvent.notify();\n    }\n};\n\nEntry.Utils.extractTextFromHTML = (htmlString) => {\n    const parser = new DOMParser();\n    const dom = parser.parseFromString(htmlString, 'text/html');\n    return dom.body.textContent || '';\n};\n\nEntry.Utils.getEntryjsPath = () =>\n    window.navigator.userAgent.indexOf('Electron') > -1\n        ? `file://${window.getEntryjsPath()}`\n        : `${window.location.origin}/lib/entry-js`;\n\nEntry.Utils.getDeviceType = (target) => {\n    const parser = new UAParser();\n    const result = parser.getResult();\n    return result.device.type;\n};\n\nEntry.Utils.cellToRowCol = (cell) => {\n    let col = 0;\n    let i = 0;\n    while (i < cell.length && isNaN(cell[i])) {\n        col = col * 26 + (cell.charCodeAt(i) - 'A'.charCodeAt(0) + 1);\n        i++;\n    }\n\n    const row = parseInt(cell.slice(i), 10) - 1;\n    return { col, row };\n};\n"
  },
  {
    "path": "src/util/virtualScroll.js",
    "content": "'use strict';\n\nEntry.VirtualScroll = class VirtualScroll {\n    constructor(dom = document.body, option = {}) {\n        const { itemHeight, dataWrapper, data, groupSize } = option;\n        this.dom = dom;\n        this.parentDom = dom.parentElement;\n        this._currGroup = -1;\n        this.scrollTop = 0;\n        this.data = data || [];\n        this.eventData = [];\n        this._groupSize = groupSize;\n        this._itemHeight = itemHeight || 0;\n        this.dataWrapper = dataWrapper;\n        this.scroll = this.scroll.bind(this);\n        this.parentDom.addEventListener('scroll', _.throttle(this.scroll, 16));\n    }\n\n    get groupSize() {\n        if (this._groupSize) {\n            return this._groupSize;\n        }\n        if (this._itemHeight) {\n            this._groupSize = parseInt((this.height / this._itemHeight) * 1.5, 10);\n            return this._groupSize;\n        }\n        const itemMinHeight = 15;\n        return Math.max(this.height / itemMinHeight, 1);\n    }\n\n    get itemHeight() {\n        if (!this._itemHeight && this.data.length) {\n            const dom = this.convertElement(this.wrap([this.data[0]]));\n            this.dom.appendChild(dom);\n            this._itemHeight = dom.offsetHeight;\n            $(dom).remove();\n        }\n        return this._itemHeight || this.height;\n    }\n\n    get currGroup() {\n        return parseInt(this.parentDom.scrollTop / this.groupHeight, 10);\n    }\n\n    get groupHeight() {\n        return this.itemHeight * this.groupSize;\n    }\n\n    get beforeHeight() {\n        return Math.max((this.currGroup - 1) * this.groupHeight, 0);\n    }\n\n    get afterHeight() {\n        const dataLength = this.data.length;\n        const shownDataCount = Math.min((this.currGroup + 2) * this.groupSize, dataLength);\n        return (dataLength - shownDataCount) * this.itemHeight;\n    }\n\n    get height() {\n        return this.dom.offsetHeight || 1;\n    }\n\n    show() {\n        const beforeSpace = /* html */ `<div style='height:${this.beforeHeight}px'></div>`;\n        const afterSpace = /* html */ `<div style='height:${this.afterHeight}px'></div>`;\n        const data = this.getData(this.currGroup);\n\n        $(this.dom).empty();\n        this.dom.innerHTML = this.combineItems(beforeSpace, this.wrap(data), afterSpace);\n    }\n\n    scroll() {\n        if (this.currGroup === this._currGroup) {\n            return;\n        }\n        this._currGroup = this.currGroup;\n        this.show();\n    }\n\n    wrap(data) {\n        if (!this.dataWrapper) {\n            return data;\n        }\n        return this.dataWrapper.replace(/\\{(\\d+)\\}/g, this.arrayToString(data));\n    }\n\n    arrayToString(arr) {\n        let st = '';\n        arr.forEach((item) => {\n            st += item;\n        });\n        return st;\n    }\n\n    getData(currGroup = -1) {\n        if (currGroup === -1) {\n            return this.data;\n        }\n        const startIndex = Math.max((currGroup - 1) * this.groupSize, 0);\n        const endIndex = (currGroup + 2) * this.groupSize;\n        return this.data.slice(startIndex, endIndex);\n    }\n\n    combineItems(...items) {\n        let htmlText = '';\n        items.forEach((item) => {\n            if (item instanceof Array) {\n                item.forEach((html) => {\n                    htmlText += html;\n                });\n            } else if (typeof item === 'string') {\n                htmlText += item;\n            }\n        });\n        return htmlText;\n    }\n\n    convertElement(html) {\n        const wrapper = document.createElement('div');\n        wrapper.innerHTML = html;\n        return wrapper.children[0];\n    }\n\n    append(item) {\n        this.data.push(item);\n    }\n\n    remove(index = this.data.length - 1) {\n        this.data.splice(index, 1);\n    }\n\n    assignData(data) {\n        delete this.data;\n        this.data = data;\n    }\n};\n"
  },
  {
    "path": "src/util/workers/newmotion.worker.ts",
    "content": "import { clamp } from 'lodash';\n\nconst ctx: Worker = self as any;\n\ntype FLIP_NORMAL = 0;\ntype FLIP_HORIZONTAL = 1;\ntype FLIP_VERTICAL = 2;\ntype FLIP_BOTH = 3;\ntype TFlipState = FLIP_NORMAL | FLIP_HORIZONTAL | FLIP_VERTICAL | FLIP_BOTH;\n\ntype Pixel = {\n    r: number;\n    g: number;\n    b: number;\n    rDiff: number;\n    gDiff: number;\n    bDiff: number;\n};\n\ntype ImageRange = {\n    minX: number;\n    maxX: number;\n    minY: number;\n    maxY: number;\n};\n\ntype TMessageData = {\n    id: string;\n    action: string;\n    width?: number;\n    height?: number;\n    range?: ImageRange;\n    imageBitmap?: ImageBitmap;\n    flipState?: TFlipState;\n    sprite?: any;\n};\n\nlet motions: Pixel[][];\n\nlet wasmInstance;\nlet motionCanvas: OffscreenCanvas;\nlet motionCanvasCtx: OffscreenCanvasRenderingContext2D;\nlet detector;\n\nconst _SAMPLE_SIZE: number = 15;\nconst _BOUNDARY_OFFSET: number = 4;\nconst _SAME_COORDINATE_COMPENSATION: number = 10;\n\nconst dimension = {\n    height: 0,\n    width: 0,\n};\n\nconst flipState = {\n    NORMAL: 0,\n    HORIZONTAL: 1,\n    VERTICAL: 2,\n    BOTH: 3,\n};\n\nctx.onmessage = async function(e: { data: TMessageData }) {\n    const { action } = e.data;\n    switch (action) {\n        case 'init':\n            init(e.data);\n            break;\n        case 'motion':\n            calcMotion(e.data);\n            break;\n        default:\n            break;\n    }\n};\n\nfunction isFlipState(nowFlipState: TFlipState, type: string) {\n    if (type === 'horizontal') {\n        return nowFlipState === flipState.BOTH || nowFlipState === flipState.HORIZONTAL;\n    } else if (type === 'vertical') {\n        return nowFlipState === flipState.BOTH || nowFlipState === flipState.VERTICAL;\n    }\n}\n\nasync function init(data: TMessageData) {\n    motionCanvas = new OffscreenCanvas(data.width, data.height);\n    motionCanvasCtx = motionCanvas.getContext('2d');\n    dimension.width = data.width;\n    dimension.height = data.height;\n    motions = [...Array(Math.ceil(dimension.height / _SAMPLE_SIZE))].map((e) =>\n        Array(Math.ceil(dimension.width / _SAMPLE_SIZE))\n    );\n    ctx.postMessage({ action: 'init_complete' });\n}\n\nfunction calcMotion(data: TMessageData) {\n    try {\n        motionCanvasCtx.drawImage(data.imageBitmap, 0, 0);\n        const imageData = motionCanvasCtx.getImageData(\n            0,\n            0,\n            motionCanvas.width,\n            motionCanvas.height\n        ).data;\n        const id = data.id;\n        const sprite = data.sprite;\n        const flipState = data.flipState;\n        let { minX, maxX, minY, maxY } = data.range;\n\n        if (sprite) {\n            const { x, y, width, height, scaleX, scaleY } = sprite;\n            minX = motionCanvas.width / 2 + x - (width * scaleX) / 2;\n            maxX = motionCanvas.width / 2 + x + (width * scaleX) / 2;\n            minY = motionCanvas.height / 2 - y - (height * scaleY) / 2;\n            maxY = motionCanvas.height / 2 - y + (height * scaleY) / 2;\n            if (!isFlipState(flipState, 'horizontal')) {\n                const tempMinX = minX;\n                minX = motionCanvas.width - maxX;\n                maxX = motionCanvas.width - tempMinX;\n            }\n            if (isFlipState(flipState, 'vertical')) {\n                const tempMinY = minY;\n                minY = motionCanvas.height - maxY;\n                maxY = motionCanvas.height - tempMinY;\n            }\n            minX = Math.floor(minX / _SAMPLE_SIZE) * _SAMPLE_SIZE;\n            maxX = Math.floor(maxX / _SAMPLE_SIZE) * _SAMPLE_SIZE;\n            minY = Math.floor(minY / _SAMPLE_SIZE) * _SAMPLE_SIZE;\n            maxY = Math.floor(maxY / _SAMPLE_SIZE) * _SAMPLE_SIZE;\n        }\n\n        if (minX > maxX) {\n            const temp = minX;\n            minX = maxX;\n            maxX = temp;\n        }\n        if (minY > maxY) {\n            const temp = minY;\n            minY = maxY;\n            maxY = temp;\n        }\n\n        let areaMotion = 0;\n        let totalMotionDirectionX = 0;\n        let totalMotionDirectionY = 0;\n        for (let y = minY; y < maxY; y += _SAMPLE_SIZE) {\n            for (let x = minX; x < maxX; x += _SAMPLE_SIZE) {\n                const pos = (x + y * dimension.width) * 4;\n                const r = imageData[pos];\n                const g = imageData[pos + 1];\n                const b = imageData[pos + 2];\n                // const a = imageData[pos + 3];\n                const xLength = motions[0].length;\n                const yLength = motions.length;\n\n                const yIndex = y / _SAMPLE_SIZE;\n                const xIndex = x / _SAMPLE_SIZE;\n                if (yIndex > yLength - 1 || xIndex > xLength - 1 || xIndex < 0 || yIndex < 0) {\n                    continue;\n                }\n                const currentPos = motions[yIndex][xIndex] || { r: 0, g: 0, b: 0 };\n                const rDiff = Math.abs(currentPos.r - r);\n                const gDiff = Math.abs(currentPos.g - g);\n                const bDiff = Math.abs(currentPos.b - b);\n                const areaMotionScore = rDiff + gDiff + bDiff / (_SAMPLE_SIZE * _SAMPLE_SIZE);\n\n                const mostSimilar = { x: 0, y: 0, diff: 99999999 };\n\n                /**\n                 * 주변 픽셀 검사로 방향 체크, 가장 값이 비슷한 픽셀 위치로 이동했다 가정\n                 * */\n                // clamp를 통해서 out of bounds 검사\n                const minScanY = clamp(yIndex - _BOUNDARY_OFFSET, 0, yLength - 1);\n                const maxScanY = clamp(yIndex + _BOUNDARY_OFFSET, 0, yLength - 1);\n                const minScanX = clamp(xIndex - _BOUNDARY_OFFSET, 0, xLength - 1);\n                const maxScanX = clamp(xIndex + _BOUNDARY_OFFSET, 0, xLength - 1);\n                for (let scopeY = minScanY; scopeY <= maxScanY; scopeY++) {\n                    for (let scopeX = minScanX; scopeX <= maxScanX; scopeX++) {\n                        const valuesNearPos = motions[scopeY][scopeX] || {\n                            r: 0,\n                            g: 0,\n                            b: 0,\n                        };\n                        const rDiffScope = Math.abs(valuesNearPos.r - r);\n                        const gDiffScope = Math.abs(valuesNearPos.g - g);\n                        const bDiffScope = Math.abs(valuesNearPos.b - b);\n                        let diff = rDiffScope + gDiffScope + bDiffScope;\n                        // 같은 포지션에 있는 픽셀에 대해서 이동하지 않았다는 전제로 가중치를 추가\n                        if (yIndex === scopeY && xIndex === scopeX) {\n                            diff = diff - _SAME_COORDINATE_COMPENSATION;\n                        }\n                        if (diff < mostSimilar.diff) {\n                            mostSimilar.x = scopeX;\n                            mostSimilar.y = scopeY;\n                            mostSimilar.diff = diff;\n                        }\n                    }\n                }\n\n                // 이미지 픽셀값 노이즈로 인한 부분들은 수용하지 않는다.\n                if (mostSimilar.x > 1) {\n                    totalMotionDirectionX += mostSimilar.x - xIndex;\n                }\n                if (mostSimilar.y > 1) {\n                    totalMotionDirectionY += mostSimilar.y - yIndex;\n                }\n                areaMotion += areaMotionScore;\n\n                motions[yIndex][xIndex] = {\n                    r,\n                    g,\n                    b,\n                    rDiff,\n                    gDiff,\n                    bDiff,\n                };\n            }\n        }\n        const result = {\n            total: areaMotion,\n            direction: {\n                x: totalMotionDirectionX,\n                y: totalMotionDirectionY,\n            },\n        };\n        if (sprite) {\n            ctx.postMessage({ id, action: 'sprite_return', result });\n        } else {\n            ctx.postMessage({ id, action: 'next_detect_motion', result });\n        }\n    } catch (e) {\n        console.error(e);\n    }\n}\n"
  },
  {
    "path": "src/util/youtube.js",
    "content": "Entry.Youtube = class Youtube {\n    constructor(youtube) {\n        this.generateView(youtube);\n    }\n    init(youtube) {\n        this.youtubeHash = youtube;\n        this.generateView();\n    }\n\n    generateView(youtubeHash) {\n        const movieContainer = Entry.createElement('div');\n        movieContainer.addClass('entryContainerMovieWorkspace');\n        movieContainer.addClass('entryRemove');\n\n        this.movieContainer = movieContainer;\n\n        const url = 'https://www.youtube.com/embed/';\n        const iframe = Entry.createElement('iframe');\n        iframe.setAttribute('id', 'youtubeIframe');\n        iframe.setAttribute('allowfullscreen', '');\n        iframe.setAttribute('frameborder', 0);\n        iframe.setAttribute('src', url + youtubeHash);\n        this.movieFrame = iframe;\n\n        this.movieContainer.appendChild(iframe);\n    }\n\n    getView() {\n        return this.movieContainer;\n    }\n\n    resize() {\n        const container = document.getElementsByClassName('propertyContent')[0];\n        const iframe = document.getElementById('youtubeIframe');\n        const w = container.offsetWidth;\n        iframe.width = `${w}px`;\n        iframe.height = `${(w * 9) / 16}px`;\n    }\n};\n"
  },
  {
    "path": "test/class/container.spec.js",
    "content": "test('Container 샘플 테스트', async () => {\n    // global.Entry = {};\n    // const Container = await import('../../src/class/container');\n    // expect(typeof Entry.Container).toEqual('function');\n});\n"
  },
  {
    "path": "test/entry/entry.js",
    "content": "describe('Entry', function(){\n    it('exist', function(){\n        assert.equal(typeof Entry, \"object\");\n    })\n});\n"
  },
  {
    "path": "test/textcoding/block.js",
    "content": "describe('EntryPython', function(){\n    var allCategories = EntryStatic.getAllBlocks();\n\n    Entry.init(null, {type: \"invisible\"});\n\n    Entry.loadProject(Entry.getStartProject());\n    Entry.playground.object = Entry.container.objects_[0];\n\n    //Entry.variableContainer.addVariable({\"name\": \"testVar\"})\n\n    function pairConvertTest(blockType) {\n        it (blockType, function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            var parser = new Entry.Parser(Entry.Vim.WORKSPACE_MODE);\n            var syntax = parser.mappingSyntax(Entry.Vim.WORKSPACE_MODE);\n            var blockToPyParser = new Entry.BlockToPyParser(syntax);\n            var pyToBlockParser = new Entry.PyToBlockParser(syntax);\n            blockToPyParser._parseMode = Entry.Parser.PARSE_GENERAL;\n            var options = { locations: true, ranges: true };\n            var code = {\n                registerEvent: function() {},\n                registerBlock: function() {}\n            };\n\n            var blockSchema = Entry.block[blockType];\n            var pythonOutput = blockToPyParser.Thread(new Entry.Thread([blockSchema.def], code));\n            var blockOutput = pyToBlockParser.processPrograms([filbert.parse(pythonOutput, options)]);\n\n            blockToPyParser = new Entry.BlockToPyParser(syntax);\n            blockToPyParser._parseMode = Entry.Parser.PARSE_GENERAL;\n\n            var secondPythonOutput = blockToPyParser.Thread(new Entry.Thread(blockOutput[0], code));\n            if (pythonOutput !== secondPythonOutput)\n                console.log(\n                    pythonOutput,\n                    secondPythonOutput,\n                    blockOutput\n                );\n\n            assert.equal(pythonOutput, secondPythonOutput);\n            Entry.clearProject();\n        });\n    }\n\n    describe('should convert block', function(){\n        for (var i = 0; i < allCategories.length; i++) {\n            var blocks = allCategories[i].blocks;\n            for (var j = 0; j < blocks.length; j++) {\n                var blockType = blocks[j];\n                var blockSchema = Entry.block[blockType];\n\n                if (blockSchema &&\n                    blockSchema.syntax &&\n                    blockSchema.syntax.py &&\n                    blockSchema.def) {\n                    if (i === 11 &&\n                        [\"arduino\", \"ArduinoExt\", \"hamster\"].indexOf(blockSchema.isNotFor[0]) < 0)\n                        continue;\n                    if (blockSchema.syntax.py[0] &&\n                        blockSchema.syntax.py[0].passTest)\n                        continue;\n                    pairConvertTest(blockType);\n                }\n            }\n        }\n    });\n\n    describe('should convert block', function(){\n        it (\"move direction\", function() {\n            assert.ok(Test.pythonToBlock(\n                \"Entry.move_to_direction(10)\",\n                [[{\n                    type: \"move_direction\",\n                    params: [{\n                        params: [\"10\"]\n                    }]\n                }]]\n            ));\n        });\n    });\n\n    describe('should convert block', function() {\n        it(\"move_x\" , function() {\n            assert.ok(Test.pythonToBlock(\n                \"Entry.add_x(10)\" ,\n                [[{\n                    \"type\": \"move_x\",\n                    \"params\": [{\n                        params : [\"10\"]\n                    }]\n                }]]\n            ));\n        });\n    });\n\n    describe('minus / plus test', function() {\n        it(\"move_x\" , function() {\n            assert.ok(Test.pythonToBlock(\n                \"Entry.add_x(-10)\" ,\n                [[{\n                    \"type\": \"move_x\",\n                    \"params\": [{\n                        params : [\"-10\"]\n                    }]\n                }]]\n            ));\n        });\n    });\n\n    describe('String merge and add block test', function() { // variable add ,\n        it(\"calc_basic\" , function() {\n            assert.ok(Test.pythonToBlock(\n                \"('안녕' + '하세요')\",\n                [[{\n                    \"type\": \"calc_basic\",\n                    \"params\": [\n                        {\n                            params : [\"안녕\"]\n                        },\n                        \"PLUS\",\n                        {\n                            params : [\"하세요\"]\n                        }\n                    ]\n                }]]\n            ));\n        });\n\n    });\n\n    describe('convert float and integer block test', function() { // variable add ,\n        it(\"calc_basic\" , function() {\n            assert.ok(Test.pythonToBlock(\n                \"('10.12345' - '10.0003')\",\n                [[{\n                    \"type\": \"calc_basic\",\n                    \"params\": [\n                        {\n                            params : [\"10.12345\"]\n                        },\n                        \"MINUS\",\n                        {\n                            params : [\"10.0003\"]\n                        }\n                    ]\n                }]]\n            ));\n        });\n\n        it(\"quotient_and_mod\" , function() {\n            assert.ok(Test.pythonToBlock(\n                \"(11.0002 // 10.0003)\",\n                [[{\n                    \"type\": \"quotient_and_mod\",\n                    \"params\": [\n                        null,\n                        {\n                            params : [\"11.0002\"]\n                        },\n                        null,\n                        {\n                            params : [\"10.0003\"]\n                        }\n                    ]\n                }]]\n            ));\n        });\n\n        it(\"Minus action use variable\" , function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"abcd\" , \"value\" : \"11.0002\"\n            });\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수2\", \"id\": \"abce\" , \"value\" : \"10.0003\"\n            });\n            assert.ok(Test.pythonToBlock(\n                \"(테스트변수1 - 테스트변수2)\",\n                [[{\n                    \"type\": \"calc_basic\",\n                    \"params\": [\n                        {\n                            type: \"get_variable\",\n                            params: [\n                                \"abcd\"\n                            ]\n                        },\n                        \"MINUS\",\n                        {\n                            type: \"get_variable\",\n                            params: [\n                                \"abce\"\n                            ]\n                        }\n                    ]\n                }]]\n            ));\n            Entry.clearProject();\n        });\n    });\n\n    describe('should convert block', function(){\n        it (\"get_variable\", function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"asdf\"\n            })\n\n\n            assert.ok(Test.pythonToBlock(\n                \"테스트변수1\",\n                [[{\n                    type: \"get_variable\",\n                    params: [\n                        \"asdf\"\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n        });\n    });\n\n    describe('parameter process test' , function() {\n\n        it(\"dialog block test\", function() { // (테스트변수)를 말하기 블록\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"asdf\"\n            })\n\n            assert.ok(Test.pythonToBlock(\n                \"Entry.print(테스트변수1)\",\n                [[{\n                    type: \"dialog\",\n                    params: [\n                        {\n                            type: \"get_variable\",\n                            params: [\n                                \"asdf\"\n                            ]\n                        }\n                    ]\n                }]]\n            ));\n            Entry.clearProject();\n        });\n\n\n\n        it(\"dialog time block test\", function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"asdf\"\n            })\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수2\", \"id\": \"asde\"\n            })\n\n            assert.ok(Test.pythonToBlock(\n                \"Entry.print_for_sec(테스트변수1 , 테스트변수2)\",\n                [[{\n                    type: \"dialog_time\",\n                    params: [\n                        {\n                            type: \"get_variable\",\n                            params: [\n                                \"asdf\"\n                            ]\n                        },\n                        {\n                            type: \"get_variable\",\n                            params: [\n                                \"asde\"\n                            ]\n                        }\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n        });\n\n\n        it(\"while not block test\", function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"asdf\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수2\", \"id\": \"asde\"\n            });\n\n\n            assert.ok(Test.pythonToBlock(\n                \"while not (테스트변수1 == 테스트변수2):\",\n                [[{\n                    type : \"repeat_while_true\",\n                    params : [\n                        {\n                            \"type\" : \"boolean_basic_operator\",\n                            \"params\" : [\n                                {\n                                    \"type\": \"get_variable\",\n                                    \"params\" : [\n                                        \"asdf\"\n                                    ]\n                                },\n                                \"EQUAL\",\n                                {\n                                    \"type\": \"get_variable\",\n                                    \"params\" : [\n                                        \"asde\"\n                                    ]\n                                }\n                            ]\n                        }\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n        });\n\n        it(\"set x, y block test\", function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"asdf\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수2\", \"id\": \"asde\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수3\", \"id\": \"asdh\"\n            });\n\n            assert.ok(Test.pythonToBlock(\n                \"Entry.set_xy_for_sec(테스트변수2, 테스트변수3, 테스트변수1)\",\n                [[{\n                    type : \"locate_xy_time\",\n                    params : [\n                        {\n                            type: \"get_variable\",\n                            params : ['asdf']\n                        },\n                        {\n                            type: \"get_variable\",\n                            params : ['asde']\n                        },\n                        {\n                            type: \"get_variable\",\n                            params : ['asdh']\n                        }\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n        });\n\n        it(\"add_brush_size block test\", function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"asdf\"\n            });\n\n            assert.ok(Test.pythonToBlock(\n                \"Entry.add_brush_size(테스트변수1)\",\n                [[{\n                    type : \"change_thickness\",\n                    params : [\n                        {\n                            type: \"get_variable\",\n                            params : ['asdf']\n                        }\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n        });\n\n        it(\"play_sound_from_to block test\", function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"asdf\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수2\", \"id\": \"abce\"\n            });\n\n            assert.ok(Test.pythonToBlock(\n                \"Entry.play_sound_from_to('강아지 짖는소리', 테스트변수1, 테스트변수2)\",\n                [[{\n                    type : \"sound_from_to\",\n                    params : [\n                        {\n                            type: \"get_sounds\",\n                            params : ['8el5']\n                        },\n                        {\n                            type: \"get_variable\",\n                            params : ['asdf']\n                        },\n                        {\n                            type: \"get_variable\",\n                            params : ['abce']\n                        }\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n        });\n    })\n\n\n    describe('list index change block is ', function(){\n        it(\"value_of_index_from_list block\", function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addList({\n                \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n            });\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수\", \"id\": \"asde\"\n            });\n\n\n            assert.ok(Test.pythonToBlock(\n                \"테스트리스트[테스트변수-1]\",\n                [[{\n                    type : \"value_of_index_from_list\",\n                    params : [\n                        null,\n                        'asdf',\n                        null,\n                       {\n                            type: \"get_variable\",\n                            params : ['asde']\n                        }\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n\n        });\n\n        it(\"remove_value_from_list block\", function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addList({\n                \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수\", \"id\": \"asde\"\n            });\n\n            assert.ok(Test.pythonToBlock(\n                \"테스트리스트.pop(테스트변수-1)\",\n                [[{\n                    type : \"remove_value_from_list\",\n                    params : [\n                       {\n                            type: \"get_variable\",\n                            params: ['asde']\n                       },\n                       'asdf'\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n\n        });\n\n        it(\"insert_value_to_list block\", function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addList({\n                \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수\", \"id\": \"asde\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수2\", \"id\": \"asdz\"\n            });\n\n\n            assert.ok(Test.pythonToBlock(\n                \"테스트리스트.insert(테스트변수2-1 , 테스트변수)\",\n                [[{\n                    type : \"insert_value_to_list\",\n                    params : [\n                       {\n                            type: \"get_variable\",\n                            params: ['asde']\n                       },\n                       'asdf',\n                       {\n                            type: \"get_variable\",\n                            params: ['asdz']\n                       }\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n\n        });\n\n        it(\"change_value_list_index block\", function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addList({\n                \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수\", \"id\": \"asde\"\n            });\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수2\", \"id\": \"asdz\"\n            });\n\n\n            assert.ok(Test.pythonToBlock(\n                \"테스트리스트 = []\\n\\n테스트리스트[테스트변수2-1] = 테스트변수\",\n                [[{\n                    type : \"change_value_list_index\",\n                    params : [\n                       'asdf',\n                       {\n                            type: \"get_variable\",\n                            params: ['asdz']\n                       },\n                       {\n                            type: \"get_variable\",\n                            params: ['asde']\n                       }\n                    ]\n                }]]\n            ));\n\n            Entry.clearProject();\n        });\n\n    });\n\n    describe('declare', function(){\n\n        it(\"variable\" , function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            var resultBlock = Test.parsePython(\"test = 2\");\n            var variable = Entry.variableContainer.variables_[0];\n\n            assert.ok(variable);\n            assert.equal(variable.name_ , 'test');\n            assert.equal(variable.value_ , '2');\n\n            Entry.clearProject();\n\n        });\n\n        it(\"list\" , function() {\n\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            var resultBlock = Test.parsePython(\"test = ['2']\");\n            var list = Entry.variableContainer.lists_[0];\n\n            assert.ok(list);\n            assert.equal(list.name_ , 'test');\n            assert.equal(list.array_[0].data , '2');\n\n            Entry.clearProject();\n\n        });\n\n    });\n\n    describe('parse', function(){\n\n        it(\"sound\" , function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            assert.ok(Test.pythonToBlock(\n                \"Entry.play_sound('강아지 짖는소리')\",\n                [[{\n                    type : \"sound_something_with_block\",\n                    params : [\n                       {\n                            type: \"get_sounds\",\n                            params: ['8el5']\n                       },\n                       null\n                    ]\n                }]]\n            ));\n            Entry.clearProject();\n        });\n\n        it(\"picture\" , function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            assert.ok(Test.pythonToBlock(\n                \"Entry.change_shape('엔트리봇_걷기2')\",\n                [[{\n                    type : \"change_to_some_shape\",\n                    params : [\n                       {\n                            type: \"get_pictures\",\n                            params: [\"4t48\"]\n                       },\n                       null\n                    ]\n                }]]\n            ));\n            Entry.clearProject();\n        });\n\n        it(\"object\" , function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            assert.ok(Test.pythonToBlock(\n                'Entry.make_clone_of(\"엔트리봇\")',\n                [[{\n                    type : \"create_clone\",\n                    params : [\n                        \"7y0y\"\n                    ]\n                }]]\n            ));\n            Entry.clearProject();\n        });\n    });\n\n    describe('create ' , function() {\n        it('local variable' , function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"abcd\" , object_ : \"7y0y\"\n\n            });\n\n\n            assert.ok(Test.pythonToBlock(\n                \"테스트변수1\",\n                [[{\n                    type : 'get_variable',\n                    params : [ 'abcd' ]\n                }]]\n            ));\n\n            Entry.clearProject();\n        })\n    });\n\n    describe('call' , function() {\n        describe('variable' , function() {\n            it('ask_and_wait method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                Entry.variableContainer.addVariable({\n                    \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"abcd\"\n                });\n\n                assert.ok(Test.pythonToBlock(\n                    'Entry.input(테스트변수1)',\n                    [[{\n                        \"type\" : \"ask_and_wait\",\n                        \"params\" : [\n                            {\n                                type : 'get_variable',\n                                params : [\"abcd\"]\n                            }\n                        ]\n                    }]]\n                ));\n\n                Entry.clearProject();\n            });\n\n            it('show_variable method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                Entry.variableContainer.addVariable({\n                    \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"abcd\"\n                });\n\n                assert.ok(Test.pythonToBlock(\n                    'Entry.show_variable(\"테스트변수1\")',\n                    [[{\n                        \"type\" : \"show_variable\",\n                        \"params\" : [\n                            \"abcd\"\n                        ]\n                    }]]\n                ));\n\n                Entry.clearProject();\n\n            });\n\n            it('hide_variable method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                Entry.variableContainer.addVariable({\n                    \"type\": \"variable\", \"name\": \"테스트변수1\", \"id\": \"abcd\"\n                });\n\n                assert.ok(Test.pythonToBlock(\n                    \"Entry.hide_variable('테스트변수1')\",\n                    [[{\n                        type : 'hide_variable',\n                        params: [\n                            'abcd'\n                        ]\n                    }]]\n                ));\n\n                Entry.clearProject();\n\n            });\n\n            it('change_variable method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n                Entry.variableContainer.addVariable({\n                    \"type\": \"variable\", \"name\": \"test\", \"id\": \"abcd\"\n                });\n                var resultBlock = Test.parsePython(\"test=0\\n\\ntest += 10\");\n\n                assert.ok(Test.pythonToBlock(\n                    \"test=0\\n\\ntest += 10\",\n                    [\n                       [\n                          {\n                             \"type\":\"change_variable\",\n                             \"params\":[\n                                \"abcd\",\n                                {\n                                   \"type\":\"number\",\n                                   \"params\":[\n                                      \"10\"\n                                   ]\n                                }\n                             ]\n                          }\n                       ]\n                    ]\n                ));\n                Entry.clearProject();\n            })\n\n            it('char_at method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n                Entry.variableContainer.addVariable({\n                    \"type\": \"variable\", \"name\": \"test\", \"id\": \"abcd\"\n                });\n                assert.ok(Test.pythonToBlock(\n                    \"test=\\\"asdf\\\"\\n\\ntest[0]\",\n                    [\n                       [\n                          {\n                             \"type\":\"char_at\",\n                             \"params\":[\n                                 undefined,\n                                 {\n                                    type: \"get_variable\",\n                                    params: [ \"abcd\" ]\n                                 },\n                                 undefined,\n                                 {\n                                    type: \"number\",\n                                    params: [ 1 ]\n                                 }\n                             ]\n                          }\n                       ]\n                    ]\n                ));\n                Entry.clearProject();\n            })\n\n            it('char_at answer method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n                assert.ok(Test.pythonToBlock(\n                    \"Entry.answer()[0]\",\n                    [\n                       [\n                          {\n                             \"type\":\"char_at\",\n                             \"params\":[\n                                 undefined,\n                                 {\n                                    type: \"get_canvas_input_value\"\n                                 },\n                                 undefined,\n                                 {\n                                    type: \"number\",\n                                    params: [ 1 ]\n                                 }\n                             ]\n                          }\n                       ]\n                    ]\n                ));\n                Entry.clearProject();\n            })\n        });\n\n        describe('list method' , function() {\n            it('show_list method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                Entry.variableContainer.addList({\n                    \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n                });\n\n                assert.ok(Test.pythonToBlock(\n                    \"Entry.show_list('테스트리스트')\",\n                    [[{\n                        type: 'show_list',\n                        params : ['asdf']\n                    }]]\n                ));\n                Entry.clearProject();\n            });\n\n            it('hide_list method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                Entry.variableContainer.addList({\n                    \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n                });\n\n                assert.ok(Test.pythonToBlock(\n                    \"Entry.hide_list('테스트리스트')\",\n                    [[{\n                        type: 'hide_list',\n                        params : ['asdf']\n                    }]]\n                ));\n                Entry.clearProject();\n            });\n\n            it('add_value_to_list method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                Entry.variableContainer.addList({\n                    \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n                });\n\n                assert.ok(Test.pythonToBlock(\n                    \"테스트리스트.append('10')\",\n                    [[{\n                        type: \"add_value_to_list\",\n                        params : [\n                            {\n                                type : \"text\",\n                                params : [\"10\"]\n                            },\n                            \"asdf\"\n                        ]\n                    }]]\n                ));\n                Entry.clearProject();\n            });\n\n            it('is_included_in_list method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                Entry.variableContainer.addList({\n                    \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n                });\n\n\n                assert.ok(Test.pythonToBlock(\n                    \"'10' in 테스트리스트\",\n                    [[{\n                        type : \"is_included_in_list\",\n                        params : [\n                            null ,\n                            \"asdf\",\n                            null,\n                            {\n                                type : 'text',\n                                params : ['10']\n                            }\n                        ]\n                    }]]\n                ));\n                Entry.clearProject();\n\n            });\n\n            it('length_of_list method' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                Entry.variableContainer.addList({\n                    \"type\": \"list\", \"name\": \"테스트리스트\", \"id\": \"asdf\"\n                });\n\n\n                assert.ok(Test.pythonToBlock(\n                    \"len(테스트리스트)\",\n                    [[{\n                        type : \"length_of_list\",\n                        params : [\n                            null ,\n                            \"asdf\"\n                        ]\n                    }]]\n                ));\n                Entry.clearProject();\n            })\n        });\n\n        describe('recursive', function(){\n            it('add block',function(){\n\n                assert.ok(Test.pythonToBlock(\n                    \"((('10'+'10') + '10')+'10')\",\n                    [[{\n                        \"type\" : \"calc_basic\",\n                        \"params\" : [\n                            {\n                                \"type\" : \"calc_basic\",\n                                \"params\" : [\n                                    {\n                                        \"type\" : \"calc_basic\",\n                                        \"params\" : [\n                                            {\n                                                \"type\" : \"number\",\n                                                \"params\" : [\"10\"]\n                                            },\n                                            \"PLUS\",\n                                            {\n                                                \"type\" : \"number\",\n                                                \"params\" : [\"10\"]\n                                            }\n\n                                        ]\n                                    },\n                                    \"PLUS\",\n                                    {\n                                        \"type\": \"number\",\n                                        \"params\": [\"10\"]\n                                    }\n\n                                ]\n                            },\n                            \"PLUS\",\n                            {\n                                \"type\": \"number\",\n                                \"params\" : [\"10\"]\n                            }\n                        ]\n                    }]]\n                ));\n            });\n\n            it('minus block',function(){\n                assert.ok(Test.pythonToBlock(\n                    \"((('10'-'10') - '10')-'10')\",\n                    [[{\n                        \"type\" : \"calc_basic\",\n                        \"params\" : [\n                            {\n                                \"type\" : \"calc_basic\",\n                                \"params\" : [\n                                    {\n                                        \"type\" : \"calc_basic\",\n                                        \"params\" : [\n                                            {\n                                                \"type\" : \"number\",\n                                                \"params\" : [\"10\"]\n                                            },\n                                            \"MINUS\",\n                                            {\n                                                \"type\" : \"number\",\n                                                \"params\" : [\"10\"]\n                                            }\n\n                                        ]\n                                    },\n                                    \"MINUS\",\n                                    {\n                                        \"type\": \"number\",\n                                        \"params\": [\"10\"]\n                                    }\n\n                                ]\n                            },\n                            \"MINUS\",\n                            {\n                                \"type\": \"number\",\n                                \"params\" : [\"10\"]\n                            }\n                        ]\n                    }]]\n                ));\n            })\n\n\n            it('calc_operation block',function(){\n                assert.ok(Test.pythonToBlock(\n                    \"((('10'**2)**2)**2)\",\n                    [[{\n                        \"type\" : \"calc_operation\",\n                        \"params\" : [\n                            null,\n                            {\n                                type: \"calc_operation\",\n                                params: [\n                                    null,\n                                    {\n                                        type: 'calc_operation',\n                                        params : [\n                                            null,\n                                            {\n                                                \"type\": \"number\",\n                                                \"params\" : [ \"10\" ]\n                                            },\n                                            null,\n                                            null\n                                        ]\n                                    },\n                                    null,\n                                    null\n                                ]\n                            },\n                            null,\n                            null\n                        ]\n                    }]]\n                ));\n            })\n        });\n\n        describe('about function python mode' , function() {\n            it('define' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n                Test.parsePython(\"def 함수(param1, param2):\\n    Entry.move_to_direction(10)\");\n                var functions = Entry.variableContainer.functions_;\n                var functionKey = Object.keys(functions)[0];\n                var func = functions[functionKey];\n\n                assert.equal(func.description.trim().substr(0, 2) , '함수');\n                assert.equal(func.content._data[0]._data[1].data.type , 'move_direction');\n                assert.equal(func.content._data[0]._data[1].data.params[0].data.params[0] , '10');\n\n                Entry.clearProject();\n            });\n\n            it('params convert' , function(){\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n\n                var resultBlock = Test.parsePython(\"def 함수(param1, param2):\\n    Entry.move_to_direction(10)\\n\\n함수(10,True)\");\n                var functions = Entry.variableContainer.functions_;\n                var functionKey = Object.keys(functions)[0];\n                var func = functions[functionKey];\n\n                assert.ok(Test.objectSimilarCheck(resultBlock[0][0],\n                    {\n                        \"type\": 'func_' + functionKey,\n                        \"params\" : [\n                            {\n                                \"type\" : 'number',\n                                \"params\" : [\"10\"]\n                            },\n                            {\n                                \"type\" : \"True\"\n                            }\n                        ]\n                    }\n                ));\n                Entry.clearProject();\n            });\n\n            it('params' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n                var resultBlock = Test.parsePython(\"def 함수(param1):\\n    함수(param1)\\n함수(10)\");\n                var functions = Entry.variableContainer.functions_;\n                var functionKey = Object.keys(functions)[0];\n                var func = functions[functionKey];\n                var functionContent = func.content.toJSON();\n\n                assert.equal(functionContent[0][0].params[0].params[1].params[0].type , functionContent[0][1].params[0].type);\n\n                Entry.clearProject();\n            })\n\n            it('recursive' , function() {\n                Entry.loadProject(Entry.getStartProject());\n                Entry.playground.object = Entry.container.objects_[0];\n                var resultBlock = Test.parsePython(\"def 함수(param1):\\n    함수(param1)\\n함수(10)\");\n                var functions = Entry.variableContainer.functions_;\n                var functionKey = Object.keys(functions)[0];\n                var func = functions[functionKey];\n                var functionData = func.content._data[0];\n                var functionDefineParam = functionData._data[1].data.type;\n\n                assert.ok(functionDefineParam.indexOf('func_') > -1);\n\n\n            })\n        })\n    });\n\n    describe('indent' , function(){\n        it('block' , function(){\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n            var resultBlock = Test.parsePython(\"while True:\\n    if True:\\n    Entry.move_to_direction(0)\");\n\n            assert.ok(Test.pythonToBlock(\n                \"while True:\\n    if True:\\n    Entry.move_to_direction(0)\",\n                [[{\n                    \"statements\":[\n                       [\n                          {\n                             \"statements\":[\n\n                             ],\n                             \"type\":\"_if\",\n                             \"params\":[\n                                {\n                                   \"type\":\"True\"\n                                }\n                             ]\n                          },\n                          {\n                             \"type\":\"move_direction\",\n                             \"params\":[\n                                {\n                                   \"type\":\"number\",\n                                   \"params\":[\n                                      \"0\"\n                                   ]\n                                },\n                                null\n                             ]\n                          }\n                       ]\n                    ],\n                    \"type\":\"repeat_inf\"\n                }]]\n            ));\n            Entry.clearProject();\n\n\n        })\n    });\n\n    describe('check' , function(){\n        it('hardware block' , function() {\n            // var resultBlock = Test.parsePython(\"Hamster.left_led(Hamster.LED_RED)\");\n\n            assert.ok(Test.pythonToBlock('Hamster.io_modes(Hamster.IO_MODE_DIGITAL_INPUT)',\n                [[{\n                    \"type\":\"hamster_set_port_to\",\n                    \"params\":[\"AB\",\"1\",null]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.io_modes(Hamster.IO_MODE_SERVO_OUTPUT)',\n                [[{\n                    \"type\":\"hamster_set_port_to\",\n                    \"params\":[\"AB\",\"8\",null]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.io_modes(Hamster.IO_MODE_PWM_OUTPUT)',\n                [[{\n                    \"type\":\"hamster_set_port_to\",\n                    \"params\":[\"AB\",\"9\",null]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.io_modes(Hamster.IO_MODE_DIGITAL_OUTPUT)',\n                [[{\n                    \"type\":\"hamster_set_port_to\",\n                    \"params\":[\"AB\",\"10\",null]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.note(0,0.25)',\n                [[{\n                    \"type\":\"hamster_rest_for\",\n                    \"params\":[\n                            {\n                                \"type\":\"text\",\n                                \"params\":[\"0.25\"]\n                            },\n                                null\n                        ]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.note(HAMSTER.NOTE_C, 4, 0.5)',\n                [[{\n                    \"type\":\"hamster_play_note_for\",\n                    \"params\":[\n                            4,\n                            \"4\",\n                            {\n                                \"type\":\"text\",\"params\":[\"0.5\"]\n                            }\n                            ,null\n                        ]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.left_led(Hamster.LED_RED)',\n                [[{\n                    \"type\":\"hamster_set_led_to\",\n                    \"params\": [\n                            \"LEFT\",\n                            \"4\",\n                            null\n                        ]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.left_led(Hamster.LED_YELLOW)',\n                [[{\n                    \"type\":\"hamster_set_led_to\",\n                    \"params\": [\n                            \"LEFT\",\n                            \"6\",\n                            null\n                        ]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.line_tracer_mode(Hamster.LINE_TRACER_MODE_BLACK_LEFT_SENSOR)',\n                [[{\n                    \"type\":\"hamster_follow_line_using\",\n                    \"params\":[\n                        \"BLACK\",\n                        \"LEFT\",\n                        null\n                    ]\n                }]]\n            ));\n\n            assert.ok(Test.pythonToBlock('Hamster.line_tracer_mode(Hamster.LINE_TRACER_MODE_BLACK_TURN_LEFT)',\n                [[{\n                    \"type\":\"hamster_follow_line_until\",\n                    \"params\":[\n                        \"BLACK\",\n                        \"LEFT\",\n                        null\n                    ]\n                }]]\n            ));\n        });\n    });\n\n    describe('def' , function() {\n        it('when_start_click block' , function() {\n\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            assert.ok(Test.pythonToBlock('def when_start():\\n    Entry.move_to_direction(10)',\n                [\n                   [\n                      {\n                         \"type\":\"when_run_button_click\"\n                      },\n                      {\n                         \"type\":\"move_direction\",\n                         \"params\":[\n                            {\n                               \"type\":\"number\",\n                               \"params\":[\n                                  \"10\"\n                               ]\n                            },\n                            null\n                         ]\n                      }\n                   ]\n                ]\n            ));\n        });\n\n        it('repeat basic block' , function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n            // var resultBlock = Test.parsePython(\"def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\");\n\n            assert.ok(Test.pythonToBlock(\n                \"def when_start():\\n    for i in range(10):\\n        Entry.move_to_direction(10)\",\n                [\n                   [\n                      {\n                         \"type\":\"when_run_button_click\"\n                      },\n                      {\n                         \"type\":\"repeat_basic\",\n                         \"params\":[\n                            {\n                               \"type\":\"number\",\n                               \"params\":[\n                                  \"10\"\n                               ]\n                            }\n                         ],\n                         \"statements\":[\n                            [\n                               {\n                                  \"type\":\"move_direction\",\n                                  \"params\":[\n                                     {\n                                        \"type\":\"number\",\n                                        \"params\":[\n                                           \"10\"\n                                        ]\n                                     },\n                                     null\n                                  ]\n                               }\n                            ]\n                         ]\n                      }\n                   ]\n                ]\n            ));\n        });\n\n        it('if else block' , function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n            var resultBlock = Test.parsePython(\"def when_start():\\n    if (True and True):\\n        Entry.add_x(10)\\n    else:\\n        Entry.bounce_on_edge()\");\n\n            assert.ok(Test.parsePython(\n                \"def when_start():\\n    if (True and True):\\n        Entry.add_x(10)\\n    else:\\n        Entry.bounce_on_edge()\" ,\n                [\n                   [\n                      {\n                         \"type\":\"when_run_button_click\",\n                         \"params\":[\n                            null\n                         ],\n                         \"contents\":[\n                            {\n                               \"type\":\"if_else\",\n                               \"params\":[\n                                  {\n                                     \"type\":\"boolean_and\",\n                                     \"params\":[\n                                        {\n                                           \"type\":\"True\"\n                                        },\n                                        null,\n                                        {\n                                           \"type\":\"True\"\n                                        }\n                                     ]\n                                  }\n                               ],\n                               \"statements\":[\n                                  [\n                                     {\n                                        \"type\":\"move_x\",\n                                        \"params\":[\n                                           {\n                                              \"type\":\"number\",\n                                              \"params\":[\n                                                 \"10\"\n                                              ]\n                                           },\n                                           null\n                                        ]\n                                     }\n                                  ],\n                                  [\n                                     {\n                                        \"type\":\"bounce_wall\",\n                                        \"params\":[\n                                           null\n                                        ]\n                                     }\n                                  ]\n                               ]\n                            }\n                         ]\n                      },\n                      {\n                         \"type\":\"if_else\",\n                         \"params\":[\n                            {\n                               \"type\":\"boolean_and\",\n                               \"params\":[\n                                  {\n                                     \"type\":\"True\"\n                                  },\n                                  null,\n                                  {\n                                     \"type\":\"True\"\n                                  }\n                               ]\n                            }\n                         ],\n                         \"statements\":[\n                            [\n                               {\n                                  \"type\":\"move_x\",\n                                  \"params\":[\n                                     {\n                                        \"type\":\"number\",\n                                        \"params\":[\n                                           \"10\"\n                                        ]\n                                     },\n                                     null\n                                  ]\n                               }\n                            ],\n                            [\n                               {\n                                  \"type\":\"bounce_wall\",\n                                  \"params\":[\n                                     null\n                                  ]\n                               }\n                            ]\n                         ]\n                      }\n                   ]\n                ]\n                ));\n        });\n        it('while block ' , function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n            var resultBlock = Test.parsePython(\"def when_start():\\n    while True:\\n        for i in range(10):\\n            Entry.move_to_direction(10)\");\n\n            assert.ok(Test.pythonToBlock(\n                \"def when_start():\\n    while True:\\n        for i in range(10):\\n            Entry.move_to_direction(10)\" ,\n                [\n                   [\n                      {\n                         \"type\":\"when_run_button_click\"\n                      },\n                      {\n                         \"type\":\"repeat_inf\",\n                         \"statements\":[\n                            [\n                               {\n                                  \"statements\":[\n                                     [\n                                        {\n                                           \"type\":\"move_direction\",\n                                           \"params\":[\n                                              {\n                                                 \"type\":\"number\",\n                                                 \"params\":[\n                                                    \"10\"\n                                                 ]\n                                              },\n                                              null\n                                           ]\n                                        }\n                                     ]\n                                  ],\n                                  \"params\":[\n                                     {\n                                        \"type\":\"number\",\n                                        \"params\":[\n                                           \"10\"\n                                        ]\n                                     }\n                                  ],\n                                  \"type\":\"repeat_basic\"\n                               }\n                            ]\n                         ]\n                      }\n                   ]\n                ]\n            ));\n        });\n\n        it('Do while block ' , function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            var resultBlock = Test.parsePython(\"def when_start():\\n    while not (10 > 10):\\n       Entry.move_to_direction(10)\");\n\n            assert.ok(Test.pythonToBlock(\n                \"def when_start():\\n    while not (10 > 10):\\n        Entry.move_to_direction(10)\" ,\n                [\n                   [\n                        {\n                         \"type\":\"when_run_button_click\"\n                        },\n                        {\n                         \"type\":\"repeat_while_true\",\n                         \"params\":[\n                            {\n                               \"type\":\"boolean_basic_operator\",\n                               \"params\":[\n                                  {\n                                     \"type\":\"number\",\n                                     \"params\":[\n                                        \"10\"\n                                     ]\n                                  },\n                                  \"GREATER\",\n                                  {\n                                     \"type\":\"number\",\n                                     \"params\":[\n                                        \"10\"\n                                     ]\n                                  }\n                               ]\n                            }\n                        ],\n                        \"statements\":[\n                            [\n                               {\n                                  \"type\":\"move_direction\",\n                                  \"params\":[\n                                     {\n                                        \"type\":\"number\",\n                                        \"params\":[\n                                           \"10\"\n                                        ]\n                                     }\n                                  ]\n                               }\n                            ]\n                        ]\n                    }\n                ]\n            ]\n        ));\n    });\n\n\n        it('set variable block ' , function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            Entry.variableContainer.addVariable({\n                \"type\": \"variable\", \"name\": \"test\", \"id\": \"abcd\"\n            });\n\n            var resultBlock = Test.parsePython(\"test = 0\\n\\ndef when_start():\\n    test = 22\");\n\n            assert.ok(Test.pythonToBlock(\n                \"def when_start():\\n    test = 22\" ,\n                [\n                   [\n                      {\n                         \"type\":\"when_run_button_click\"\n                      },\n                      {\n                         \"type\":\"set_variable\",\n                         \"params\":[\n                            \"abcd\",\n                            {\n                               \"type\":\"number\",\n                               \"params\":[\n                                  \"22\"\n                               ]\n                            }\n                         ]\n                      }\n                   ]\n                ]\n            ));\n        });\n\n        it('when press key ' , function() {\n            Entry.loadProject(Entry.getStartProject());\n            Entry.playground.object = Entry.container.objects_[0];\n\n            var resultBlock = Test.parsePython('def when_press_key(space):');\n\n            assert.ok(Test.pythonToBlock(\n                'def when_press_key(space):',\n               [\n                   [\n                      {\n                         \"type\":\"when_some_key_pressed\",\n                         \"params\":[\n                            null,\n                            32\n                         ]\n                      }\n                   ]\n                ]\n            ));\n        });\n\n    });\n});\n"
  },
  {
    "path": "test_util/helper.js",
    "content": "\"use strict\";\n\nvar Test = {};\n\nTest.randomString = function() {\n    return Math.random().toString(36).substring(\n        Math.floor(Math.random()*13 + 2)\n    );\n};\n\nTest.randomNumber = function() {\n    return Math.floor(Math.random() * 100);\n};\n\nTest.parsePython = function(textCode) {\n    textCode = \"# object code\\n\\nimport Entry\\n\\n\" + textCode;\n    var parser = new Entry.Parser();\n    parser.setParser(Entry.Vim.WORKSPACE_MODE, Entry.Vim.PARSER_TYPE_PY_TO_BLOCK);\n\n    var blockOutput = parser.parse(textCode);\n\n    return blockOutput;\n};\n\n\nTest.pythonToBlock = function(textCode, block) {\n    var blockOutput = this.parsePython(textCode);\n    var result = Test.objectSimilarCheck(block, blockOutput);\n    if (!result){\n        console.log(JSON.stringify(blockOutput));\n    }\n    return result;\n}\n\nTest.objectSimilarCheck = function(obj, targetObj) {\n    for (var key in obj) {\n        var value = obj[key];\n        switch (typeof value) {\n            case \"object\":\n            case \"array\":\n                if (!obj || !targetObj)\n                    return false;\n                var testResult = this.objectSimilarCheck(obj[key], targetObj[key]);\n                if (!testResult)\n                    return false;\n                break;\n            case \"string\":\n            case \"number\":\n                if (value + \"\" !== targetObj[key] + \"\")\n                    return false;\n                break;\n            default:\n                if (value !== targetObj[key])\n                    return false;\n                break;\n        }\n    }\n    return true;\n};\n\n\nwindow.Test = Test;\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"sourceMap\": true,\n        \"noImplicitAny\": true,\n        \"module\": \"esnext\",\n        \"target\": \"es5\",\n        \"downlevelIteration\": true,\n        \"moduleResolution\": \"node\",\n        \"lib\": [\"es6\", \"dom\", \"webworker\"],\n        \"allowJs\": true,\n        \"baseUrl\": \"./\",\n        \"typeRoots\": [\"./types\", \"./node_modules/@types\"],\n        \"allowSyntheticDefaultImports\": true\n    },\n    \"include\": [\n        \"src/**/*.ts\",\n        \"./types/**/*\"\n    ]\n}\n"
  },
  {
    "path": "types/entry.d.ts",
    "content": "/// <reference path=\"./index.d.ts\" />\n\nimport { ISkeleton, EntryBlock, UnknownAny } from './index';\n\ndeclare interface EntryOptions {\n    hardwareEnable?: boolean;\n    mediaFilePath?: string;\n    moduleBaseUrl?: string;\n    moduleliteBaseUrl?: string;\n    dataTableDisable?: boolean;\n    offlineModulePath?: string;\n}\n\n/**\n * 엔트리 실제 인스턴스에 대한 정의\n */\nexport declare interface IEntry extends EntryOptions {\n    soundQueue: any;\n    Func: any;\n    externalModulesLite: any;\n    loadAudio_: (filename: string[], name: string) => void;\n    loadLiteTestModule: (file: file, name: string) => Promise<void>;\n    loadLiteTestModuleUploader: () => void;\n    HWLite: typeof import('../src/class/hw_lite').default;\n    HW: typeof import('../src/class/hw').default;\n    Intro: typeof import('../src/class/intro').default;\n    PropertyPanel: typeof import('../src/class/property_panel').default;\n    Pdf: typeof import('../src/class/pdf').default;\n    BlockMenu: typeof import('../src/playground/block_menu').default;\n    Dom: typeof import('../src/core/dom').default;\n    Dialog: typeof import('../src/class/dialog').default;\n    popupHelper: typeof import('../src/class/popup_helper').default;\n    moduleManager: typeof import('../src/class/entryModuleLoader').default;\n    Model: (target: any, isSeal: boolean) => void;\n    BlockView: any;\n    SVG: any;\n    Event: any;\n    Code: any;\n    BlockMenuScroller: any;\n\n    // 엔트리 내 클래스들\n    skeleton: { [name: string]: ISkeleton };\n    options: EntryOptions;\n    engine: any;\n    toast: IEntry.WorkspaceToast;\n    playground: IEntry.Playground;\n    workspace: any;\n    console: any;\n    propertyPanel: import('../src/class/property_panel').default;\n    container: IEntry.Container;\n    stage: IEntry.Stage;\n    Utils: any;\n    GlobalSvg: any;\n    Workspace: any;\n    DragInstance: any;\n\n    // 엔트리에서 네임스페이스에 할당되어있는 특정 객체들\n    HARDWARE_LIST: { [hardwareName: string]: any };\n    HARDWARE_LITE_LIST: { [hardwareName: string]: any };\n    KeyboardCode: {\n        map: { [keyname: string]: number };\n        codeToKeyCode: { [keyname: string]: number };\n    };\n    events_: any;\n    requestUpdate: boolean;\n    TEXT_ALIGNS: string[];\n    TEXT_ALIGN_LEFT: number;\n    TEXT_ALIGN_CENTER: number;\n    TEXT_ALIGN_RIGHT: number;\n    block: {\n        [blockName: string]: EntryBlock;\n        changeBlockText: (key: string, text: string) => void;\n        changeBlockEvent: (key: string, event: string, callback: Function) => void;\n    };\n    hwLite: typeof import('../src/class/hw_lite').default;\n    hw: import('../src/class/hw').default; // HW instance\n    interfaceState: { [key: string]: any };\n    modal: any; // @entrylabs/modal\n\n    // 엔트리 전역에 할당된 이벤트 객체\n    disposeEvent: any;\n    documentMousemove: any;\n    keyPressed: any;\n    windowResized: any;\n    documentMousedown: any;\n\n    // 엔트리 전역에 할당된 상수\n    DRAG_MODE_DRAG: 2; // utils.js\n    DRAG_MODE_NONE: 0;\n    DRAG_MODE_MOUSEDOWN: 1;\n    type: 'workspace' | string;\n\n    // 엔트리에서 네임스페이스에 할당되어있는 특정 함수들\n    addEventListener(type: string, listener: () => void): void;\n    removeEventListener(eventName: string, listener: () => void): void;\n    dispatchEvent(eventName: string, ...args: any): void;\n    getMainWS(): UnknownAny | undefined;\n    isMobile(): boolean;\n    assert(predicate: any, message: string): void;\n    resizeElement(interfaceModel?: any): void;\n    loadExternalModules(project: any): Promise<void>;\n    loadLiteExternalModules: (project?: any) => Promise<void>;\n    bindAnimationCallbackOnce(element: any, func: () => void): void;\n    createElement<K extends keyof HTMLElementTagNameMap>(\n        type: HTMLElement | K,\n        elementId?: string\n    ): HTMLElementTagNameMap[K];\n    do(commandName: string, ...args: any[]): any;\n\n    expansionBlocks: any;\n    aiUtilizeBlocks: any;\n    hardwareLiteBlocks: any;\n    generateHash: () => string;\n\n    canvas_: HTMLCanvasElement;\n    CANVAS_MIN_WIDTH: 162;\n    CANVAS_DEFAULT_WIDTH: 324;\n    CANVAS_MAX_WIDTH: 640;\n}\n\ndeclare type IHardwareType = 'serial' | 'bluetooth' | 'hid' | 'ble';\ndeclare type IHardwareControlType = 'slave' | 'master';\n\ndeclare interface IHardwareModuleConfig {\n    type: IHardwareType;\n    control: IHardwareControlType;\n    duration: number;\n    baudRate: number;\n    commType: 'ascii' | 'utf8' | 'utf16le' | 'ucs2' | 'base64' | 'binary' | 'hex' | undefined;\n    firmwarecheck?: boolean;\n\n    vendor: string | string[] | { [key in 'win32' | 'darwin']: string | string[] };\n    pnpId: string | string[];\n    comName: string;\n\n    lostTimer?: number;\n    flowControl?: 'hardware' | 'software';\n    byteDelimiter?: number[];\n    delimiter?: string;\n\n    advertise?: number;\n    softwareReset?: boolean;\n    stream?: 'string';\n}\n\ndeclare var Entry: IEntry;\n"
  },
  {
    "path": "types/index.d.ts",
    "content": "// TODO 이 아래 타입들이 붙어있으면 그냥 아직 몰라서 붙인 타입입니다. 수정이 필요합니다.\ndeclare type UnknownAny = any;\ndeclare type UnknownFunction = (...args: any[]) => any;\n\ndeclare type Point = {\n    x: number;\n    y: number;\n};\n\nexport declare interface ISkeleton {\n    executable?: boolean;\n    fontSize?: number;\n    movable?: boolean;\n    readOnly?: boolean;\n    nextShadow?: boolean;\n    classes?: string[];\n    color?: string;\n    outerLine?: string;\n    morph?: ['prev', 'next']; // for pebble\n    dropdownHeight?: number; // for pebble\n    path: (blockView: any) => string; // svg path string\n    box: (blockView: any) => {\n        offsetX: number;\n        offsetY: number;\n        width: number;\n        height: number;\n        marginBottom: number;\n        topFieldHeight?: number;\n    };\n    contentPos: (blockView: any) => Point;\n    magnets?: (blockView: any) => {\n        next?: Point;\n        previous?: Point;\n        boolean?: {};\n        string?: {};\n        param?: {};\n    };\n    statementPos?: (blockView: any) => Point[];\n}\n\nexport declare interface MediaUtilsInterface {\n    initialize(list?: string[][]): void;\n\n    reset(): void;\n\n    destroy(): void;\n\n    compatabilityChecker(): void; // throws error if failed\n}\n\ndeclare interface EntryDomOptions {\n    id?: string;\n    class?: string;\n    classes?: string[];\n    text?: string;\n    src?: string;\n    href?: string;\n    parent?: EntryDom;\n}\n\nexport declare interface EntryDom extends JQuery {\n    innerHTML?: string;\n    textContent?: string;\n    bindOnClick?: (e: any) => this;\n}\n\nexport declare type EntryDomConstructor = (\n    tag: string | HTMLElement | JQuery,\n    options?: EntryDomOptions\n) => EntryDom;\n\nexport interface HardwareMessageData extends HardwareModuleId {\n    [key: string]: any;\n}\n\ninterface HardwareModuleId {\n    company: string;\n    model: string;\n}\n\nexport type WebSocketMessage = {\n    data: string;\n    mode: number;\n    type: 'utf8';\n};\n\ndeclare module SerialPort {}\n\nexport declare module IEntry {\n    export interface Container {\n        resizeEvent: any; // Entry.Event\n        splitterEnable?: boolean;\n\n        getAllObjects(): UnknownAny[];\n    }\n\n    export interface Playground {\n        object?: UnknownAny;\n        setMenu?: UnknownFunction;\n        resizing: boolean;\n        checkVariables: () => void;\n        hideTabs: () => void;\n        showTabs: () => void;\n    }\n\n    export interface Stage {\n        loadDialog(dialog: any): void;\n\n        unloadDialog(dialog: any): void;\n\n        canvas: any;\n        _app: any;\n    }\n\n    /**\n     * 과거 엔트리 토스트\n     */\n    type WSToastFunction = (title: string, message: string, isNotAutoDispose?: boolean) => void;\n\n    export interface WorkspaceToast {\n        alert: WSToastFunction;\n        warning: WSToastFunction;\n        success: WSToastFunction;\n        isOpen: (target?: any) => boolean;\n    }\n\n    export interface Intro {\n        modes: any;\n        selected: any;\n\n        generateView(introView: any): void;\n\n        setView(view: any): void;\n\n        removeView(): void;\n    }\n\n    // Entry namespace 에 필요한 객체가 있으면 추가해주세요.\n}\n\nexport declare type EntryBlock = {\n    color: string;\n    outerLine?: string;\n    skeleton: string;\n    statements?: any[];\n    template?: string;\n    params: { [key: string]: any };\n    defs?: any; // legacy\n    def: { type: string } & { [key: string]: any };\n    paramsKeyMap?: { [key: string]: number };\n    class: string;\n    isFor?: string[];\n    isNotFor?: string[];\n    events: { [key: string]: any };\n    type?: string;\n    category?: string;\n    pyHelpDef?: {\n        params: string[];\n        type: string;\n    };\n    func?: Function;\n    syntax?: {\n        js?: any[];\n        py: any[];\n    };\n};\n\n// expansion blocks 의 스키마를 따름\nexport declare interface EntryBlockModule {\n    name: string;\n    title: { [key: string]: string };\n    description?: string;\n    getBlocks: () => { [blockName: string]: EntryBlock };\n}\n\nexport declare interface EntryHardwareBlockModule extends EntryBlockModule {\n    // 홍보용\n    imageName: string;\n    url: string;\n\n    // 모듈 정의용\n    id: string | string[];\n    monitorTemplate?: UnknownAny;\n    communicationType?: string;\n    sendMessage?: (hw: import('../src/class/hw').default) => void;\n    hasPracticalCourse?: boolean;\n\n    // 필수 함수 목록\n    setZero: () => void;\n    blockMenuBlocks: string[];\n    setLanguage: () => {\n        [langType: string]: { [type: string]: { [templateName: string]: string } };\n    };\n\n    //TODO afterSend, dataHandler 의 목적이 모호하므로 추후 개선 필요\n    afterReceive?: (portData: HardwareMessageData) => void; // 데이터 수신 이후\n    afterSend?: (sendQueue: HardwareMessageData) => void; // 데이서 송신 이후\n    dataHandler?: (data: HardwareMessageData) => void;\n}\n\nexport declare interface EntryHWLiteBaseModule extends EntryBlockModule {\n    getMonitorPort(): Object;\n    duration: number;\n    // 홍보용\n    imageName: string;\n    url: string;\n\n    // 모듈 정의용\n    id: string;\n    monitorTemplate?: UnknownAny;\n    portData?: HWLiteSerialInfo;\n    bluetoothInfo?: HWLiteBluetoothInfo;\n    type?: 'master' | 'slave';\n    delimeter?: string | number;\n    webapiType?: 'ble' | 'usb' | 'serial';\n    supportFirmwareFlash?: boolean;\n    customPrompt?: {\n        title: string;\n        description: string;\n        defaultValue?: string;\n        negativeButtonText: string;\n        positiveButtonText: string;\n    };\n\n    // 필수 함수 목록\n    setZero: () => void;\n    blockMenuBlocks: string[];\n    setLanguage: () => {\n        [langType: string]: { [type: string]: { [templateName: string]: string } };\n    };\n    handleLocalData: (value: any) => void;\n    initialHandshake: () => any;\n    requestLocalData: () => string;\n}\n\nexport declare interface HWLiteSerialInfo {\n    baudRate: number;\n    dataBits: number;\n    parity: 'none' | 'even' | 'odd';\n    stopBits: 1 | 2;\n    bufferSize: number;\n    connectionType?: 'bytestream' | 'ascii';\n    constantServing?: boolean | 'ReadOnly';\n    constantRead?: boolean;\n    writeAscii?: boolean;\n    readAscii?: boolean;\n    flowControl?: 'hardware';\n}\n\nexport declare interface HWLiteBluetoothInfo {\n    filters: BluetoothLEScanFilter[];\n    optionalServices: string[];\n}\n\nexport declare type HWLiteStatus =\n    | 'disconnected'\n    | 'connected'\n    | 'willDisconnect'\n    | 'connectFailed';\n"
  },
  {
    "path": "types/window.d.ts",
    "content": "import { IEntry } from './entry';\n\ndeclare global {\n    interface Window {\n        entrylms: any;\n        Lang: any;\n        popupHelper?: import('../src/class/popup_helper').default;\n        EntryStatic: any;\n        ImageCapture: any;\n        sendSync: any | undefined;\n        Entry: IEntry;\n    }\n    var entrylms: any;\n    var Lang: any;\n    var EntryStatic: any;\n    var ImageCapture: any;\n    var sendSync: any | undefined;\n    var Entry: IEntry;\n}\n\ndeclare var Lang: any;\ndeclare var entrylms: any;\ndeclare var EntryStatic: any;\ndeclare var ImageCapture: any;\n\ndeclare module '*.worker.ts' {\n    var value: new () => Worker;\n    export = value;\n}\n\ndeclare module '@egjs/*' {\n    const value: any;\n    export default value;\n}\n"
  },
  {
    "path": "webpack.config.js",
    "content": "const { merge } = require('webpack-merge');\nconst common = require('./webpack_config/common');\n\nlet conf;\n\nswitch (process.env.NODE_ENV) {\n    case 'lint':\n        // common config 을 가지지 않는다.\n        return require('./webpack_config/lint');\n    case 'production':\n        conf = require('./webpack_config/prod');\n        break;\n    case 'serve':\n    case 'serve-mini':\n        conf = require('./webpack_config/serve');\n        break;\n    case 'development':\n    default:\n        conf = require('./webpack_config/dev');\n        break;\n}\n\nmodule.exports = merge(common, conf);\n"
  },
  {
    "path": "webpack_config/common.js",
    "content": "/*eslint-env node*/\n\nconst path = require('path');\nconst autoprefixer = require('autoprefixer');\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst CleanWebpackPlugin = require('clean-webpack-plugin');\nconst { WebpackManifestPlugin } = require('webpack-manifest-plugin');\nconst webpack = require('webpack');\nconst CopyPlugin = require('copy-webpack-plugin');\n\nmodule.exports = {\n    entry: {\n        entry: './src/entry.js',\n    },\n    output: {\n        path: path.resolve('./dist'),\n        publicPath: '/dist/',\n        filename: '[name].js',\n    },\n    resolve: {\n        fallback: {\n            fs: false,\n            path: false,\n            crypto: false,\n            buffer: false,\n            perf_hooks: false,\n            buffer: require.resolve('buffer/'),\n        },\n        extensions: ['.ts', '.tsx', '.js', '.json'],\n        mainFields: ['jsnext:main', 'browser', 'main'],\n    },\n    module: {\n        rules: [\n            {\n                test: /\\.worker\\.ts$/,\n                use: {\n                    loader: 'worker-loader',\n                    options: {\n                        inline: 'no-fallback',\n                    },\n                },\n            },\n            {\n                test: /\\.js$/,\n                use: [\n                    {\n                        loader: 'webpack-strip-block',\n                        options: {\n                            start: 'IGNORE_WEBPACK:START',\n                            end: 'IGNORE_WEBPACK:END',\n                        },\n                    },\n                    {\n                        loader: 'babel-loader',\n                        options: {\n                            configFile: path.resolve(__dirname, '..', '.babelrc'),\n                        },\n                    },\n                ],\n            },\n            {\n                test: /\\.(ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|cur)(\\?v=[0-9]\\.[0-9]\\.[0-9])?$/,\n                type: 'asset',\n                parser: {\n                    dataUrlCondition: {\n                        maxSize: 10000, // 10kb\n                    },\n                },\n                generator: {\n                    filename: '[hash][ext]',\n                },\n            },\n            {\n                test: /\\.tsx?$/,\n                loader: 'ts-loader',\n                exclude: /node_modules/,\n                options: { transpileOnly: true },\n            },\n            {\n                test: /\\.(css|less)$/,\n                use: [\n                    {\n                        loader: MiniCssExtractPlugin.loader,\n                        options: {\n                            publicPath: '../',\n                        },\n                    },\n                    {\n                        loader: 'css-loader',\n                        options: {\n                            url: false,\n                            sourceMap: false,\n                        },\n                    },\n                    {\n                        loader: require.resolve('postcss-loader'),\n                        options: {\n                            ident: 'postcss',\n                            plugins: () => [\n                                require('postcss-flexbugs-fixes'),\n                                require('cssnano')({ preset: 'default' }),\n                                autoprefixer({\n                                    overrideBrowserslist: [\n                                        '>1%',\n                                        'last 4 versions',\n                                        'Firefox ESR',\n                                        'not ie < 9', // React doesn't support IE8 anyway\n                                    ],\n                                    flexbox: 'no-2009',\n                                    remove: false,\n                                }),\n                            ],\n                        },\n                    },\n                    {\n                        loader: 'less-loader',\n                        options: {\n                            sourceMap: false,\n                        },\n                    },\n                ],\n            },\n        ],\n    },\n    externals: {\n        react: 'React',\n        'react-dom': 'ReactDOM',\n        '@entrylabs/tool': 'EntryTool',\n        'entry-paint': 'EntryPaint',\n        '@entrylabs/sound-editor': 'EntrySoundEditor',\n        '@entrylabs/legacy-video': 'EntryVideoLegacy',\n    },\n    plugins: [\n        new CleanWebpackPlugin(['dist'], {\n            root: path.join(__dirname, '..'),\n        }),\n        new WebpackManifestPlugin(),\n        new webpack.ProvidePlugin({\n            Buffer: ['buffer', 'Buffer'],\n        }),\n        new MiniCssExtractPlugin({\n            filename: '[name].css',\n            chunkFilename: '[id].css',\n        }),\n        new CopyPlugin({\n            patterns: [\n                {\n                    from: path.join(\n                        __dirname,\n                        '..',\n                        'node_modules',\n                        'khaiii',\n                        'dist',\n                        'libkhaiii.wasm'\n                    ),\n                    to: path.join(__dirname, '..', 'dist', 'libkhaiii.wasm'),\n                    toType: 'file',\n                },\n            ],\n        }),\n    ],\n};\n"
  },
  {
    "path": "webpack_config/dev.js",
    "content": "const webpack = require('webpack');\n\nmodule.exports = {\n    mode: 'development',\n    module: {\n        rules: [],\n    },\n    devtool: 'cheap-source-map',\n    plugins: [\n        // new webpack.ProgressPlugin({\n        //     activeModules: true, // display the current module\n        // }),\n    ],\n    // stats: {\n    //     logging: 'verbose',\n    // },\n    // infrastructureLogging: {\n    //     level: 'verbose',\n    // },\n    // parallelism: 1,\n};\n"
  },
  {
    "path": "webpack_config/lint.js",
    "content": "'use strict';\n\nconst path = require('path');\nconst ExtractTextPlugin = require('extract-text-webpack-plugin');\nconst autoprefixer = require('autoprefixer');\n\nmodule.exports = {\n    mode: 'development',\n    entry: {\n        entry: './src/entry.js',\n    },\n    output: {\n        path: path.resolve('./dist'),\n        publicPath: '/dist/',\n        filename: '[name].js',\n    },\n    module: {\n        rules: [\n            {\n                enforce: 'pre',\n                test: /\\.js$/,\n                exclude: /node_modules/,\n                loader: 'eslint-loader',\n            },\n            {\n                test: /\\.(ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot|cur)(\\?v=[0-9]\\.[0-9]\\.[0-9])?$/,\n                loader: 'url-loader',\n                options: {\n                    name: '[hash].[ext]',\n                    limit: 10000,\n                },\n            },\n            {\n                test: /\\.(css|less)$/,\n                use: ExtractTextPlugin.extract({\n                    fallback: 'style-loader',\n                    use: [\n                        {\n                            loader: 'css-loader',\n                            options: {\n                                url: false,\n                                sourceMap: false,\n                            },\n                        },\n                        {\n                            loader: require.resolve('postcss-loader'),\n                            options: {\n                                ident: 'postcss',\n                                plugins: () => [\n                                    require('postcss-flexbugs-fixes'),\n                                    require('cssnano')({ preset: 'default' }),\n                                    autoprefixer({\n                                        overrideBrowserslist: [\n                                            '>1%',\n                                            'last 4 versions',\n                                            'Firefox ESR',\n                                            'not ie < 9', // React doesn't support IE8 anyway\n                                        ],\n                                        flexbox: 'no-2009',\n                                        remove: false,\n                                    }),\n                                ],\n                            },\n                        },\n                        {\n                            loader: 'less-loader',\n                            options: {\n                                sourceMap: false,\n                            },\n                        },\n                    ],\n                }),\n            },\n        ],\n    },\n    plugins: [\n        new ExtractTextPlugin({\n            filename: 'entry.css',\n        }),\n    ],\n};\n"
  },
  {
    "path": "webpack_config/prod.js",
    "content": "'use strict';\n\nconst MiniCssExtractPlugin = require('mini-css-extract-plugin');\nconst TerserPlugin = require('terser-webpack-plugin');\n\nmodule.exports = {\n    entry: {\n        'entry.min': './src/entry.js',\n    },\n    mode: 'production',\n    output: {\n        chunkFilename: '[name].[contenthash].js',\n        filename: '[name].js',\n    },\n    module: {\n        rules: [],\n    },\n    plugins: [\n        new MiniCssExtractPlugin({\n            filename: '[name].css',\n            chunkFilename: '[name][contenthash].css',\n        }),\n    ],\n    optimization: {\n        minimize: true,\n        minimizer: [\n            new TerserPlugin({\n                include: /\\.min\\.js$/,\n                parallel: true,\n                terserOptions: {\n                    ecma: 5,\n                },\n            }),\n        ],\n    },\n};\n"
  },
  {
    "path": "webpack_config/serve.js",
    "content": "'use strict';\n\nconst path = require('path');\nconst HtmlWebpackPlugin = require('html-webpack-plugin');\n\nconst isWebGLEnabled = process.argv.some(\n    (arg) => arg.startsWith('--webgl') && arg.split('=')[1] === 'true'\n);\nconst templateName = (() => {\n    if (process.env.NODE_ENV === 'serve') {\n        return isWebGLEnabled ? 'example_webgl.ejs' : 'example.ejs';\n    } else {\n        return 'example_mini.ejs';\n    }\n})();\nconst template = path.resolve('example', templateName);\nconst devServerPort = 8080;\n\nmodule.exports = {\n    mode: 'development',\n    module: {\n        rules: [],\n    },\n    plugins: [\n        new HtmlWebpackPlugin({\n            template,\n            title: 'Entry Example',\n            filename: path.resolve('dist', 'index.html'),\n            inject: false,\n            hash: true,\n        }),\n    ],\n    devServer: {\n        static: {\n            directory: path.join(__dirname, '../'),\n        },\n        port: devServerPort,\n        historyApiFallback: true,\n        devMiddleware: {\n            publicPath: '/',\n        },\n        proxy: {\n            '/lib/entry-js': {\n                target: `http://localhost:${devServerPort}`,\n                pathRewrite: { '^/lib/entry-js': '' },\n            },\n            '/dist': {\n                target: `http://localhost:${devServerPort}`,\n                pathRewrite: { '^/dist': '' },\n            },\n        },\n    },\n    devtool: 'source-map',\n};\n"
  },
  {
    "path": "weights/age_gender_model-weights_manifest.json",
    "content": "[{\"weights\":[{\"name\":\"entry_flow/conv_in/filters\",\"shape\":[3,3,3,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005431825039433498,\"min\":-0.7441600304023892}},{\"name\":\"entry_flow/conv_in/bias\",\"shape\":[32],\"dtype\":\"float32\"},{\"name\":\"entry_flow/reduction_block_0/separable_conv0/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005691980614381678,\"min\":-0.6090419257388395}},{\"name\":\"entry_flow/reduction_block_0/separable_conv0/pointwise_filter\",\"shape\":[1,1,32,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.009089225881239947,\"min\":-1.1179747833925135}},{\"name\":\"entry_flow/reduction_block_0/separable_conv0/bias\",\"shape\":[64],\"dtype\":\"float32\"},{\"name\":\"entry_flow/reduction_block_0/separable_conv1/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00683894624897078,\"min\":-0.8138346036275228}},{\"name\":\"entry_flow/reduction_block_0/separable_conv1/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.011632566358528886,\"min\":-1.3028474321552352}},{\"name\":\"entry_flow/reduction_block_0/separable_conv1/bias\",\"shape\":[64],\"dtype\":\"float32\"},{\"name\":\"entry_flow/reduction_block_0/expansion_conv/filters\",\"shape\":[1,1,32,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010254812240600587,\"min\":-0.9229331016540528}},{\"name\":\"entry_flow/reduction_block_0/expansion_conv/bias\",\"shape\":[64],\"dtype\":\"float32\"},{\"name\":\"entry_flow/reduction_block_1/separable_conv0/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0052509616403018725,\"min\":-0.6406173201168285}},{\"name\":\"entry_flow/reduction_block_1/separable_conv0/pointwise_filter\",\"shape\":[1,1,64,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010788509424994973,\"min\":-1.4564487723743214}},{\"name\":\"entry_flow/reduction_block_1/separable_conv0/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"entry_flow/reduction_block_1/separable_conv1/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00553213918910307,\"min\":-0.7025816770160899}},{\"name\":\"entry_flow/reduction_block_1/separable_conv1/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.013602388606351965,\"min\":-1.6186842441558837}},{\"name\":\"entry_flow/reduction_block_1/separable_conv1/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"entry_flow/reduction_block_1/expansion_conv/filters\",\"shape\":[1,1,64,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.007571851038465313,\"min\":-1.158493208885193}},{\"name\":\"entry_flow/reduction_block_1/expansion_conv/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"middle_flow/main_block_0/separable_conv0/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005766328409606335,\"min\":-0.6688940955143349}},{\"name\":\"middle_flow/main_block_0/separable_conv0/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.012136116214826995,\"min\":-1.5776951079275094}},{\"name\":\"middle_flow/main_block_0/separable_conv0/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"middle_flow/main_block_0/separable_conv1/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004314773222979377,\"min\":-0.5652352922102984}},{\"name\":\"middle_flow/main_block_0/separable_conv1/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.01107162026798024,\"min\":-1.2400214700137868}},{\"name\":\"middle_flow/main_block_0/separable_conv1/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"middle_flow/main_block_0/separable_conv2/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0036451735917259667,\"min\":-0.4848080876995536}},{\"name\":\"middle_flow/main_block_0/separable_conv2/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.008791744942758598,\"min\":-1.134135097615859}},{\"name\":\"middle_flow/main_block_0/separable_conv2/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"middle_flow/main_block_1/separable_conv0/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004915751896652521,\"min\":-0.6095532351849126}},{\"name\":\"middle_flow/main_block_1/separable_conv0/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010868691463096469,\"min\":-1.3368490499608656}},{\"name\":\"middle_flow/main_block_1/separable_conv0/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"middle_flow/main_block_1/separable_conv1/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005010117269029804,\"min\":-0.6012140722835765}},{\"name\":\"middle_flow/main_block_1/separable_conv1/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010311148213405235,\"min\":-1.3816938605963016}},{\"name\":\"middle_flow/main_block_1/separable_conv1/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"middle_flow/main_block_1/separable_conv2/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004911523706772748,\"min\":-0.7367285560159123}},{\"name\":\"middle_flow/main_block_1/separable_conv2/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.008976466047997568,\"min\":-1.2207993825276693}},{\"name\":\"middle_flow/main_block_1/separable_conv2/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"exit_flow/reduction_block/separable_conv0/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005074804436926748,\"min\":-0.7104726211697447}},{\"name\":\"exit_flow/reduction_block/separable_conv0/pointwise_filter\",\"shape\":[1,1,128,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.011453078307357489,\"min\":-1.4545409450344011}},{\"name\":\"exit_flow/reduction_block/separable_conv0/bias\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"exit_flow/reduction_block/separable_conv1/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.007741751390344957,\"min\":-1.1380374543807086}},{\"name\":\"exit_flow/reduction_block/separable_conv1/pointwise_filter\",\"shape\":[1,1,256,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.011347713189966538,\"min\":-1.497898141075583}},{\"name\":\"exit_flow/reduction_block/separable_conv1/bias\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"exit_flow/reduction_block/expansion_conv/filters\",\"shape\":[1,1,128,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006717281014311547,\"min\":-0.8329428457746318}},{\"name\":\"exit_flow/reduction_block/expansion_conv/bias\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"exit_flow/separable_conv/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0027201742518181892,\"min\":-0.3237007359663645}},{\"name\":\"exit_flow/separable_conv/pointwise_filter\",\"shape\":[1,1,256,512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010076364348916447,\"min\":-1.330080094056971}},{\"name\":\"exit_flow/separable_conv/bias\",\"shape\":[512],\"dtype\":\"float32\"},{\"name\":\"fc/age/weights\",\"shape\":[512,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.008674054987290326,\"min\":-1.2664120281443876}},{\"name\":\"fc/age/bias\",\"shape\":[1],\"dtype\":\"float32\"},{\"name\":\"fc/gender/weights\",\"shape\":[512,2],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0029948226377075793,\"min\":-0.34140978069866407}},{\"name\":\"fc/gender/bias\",\"shape\":[2],\"dtype\":\"float32\"}],\"paths\":[\"age_gender_model-shard1\"]}]"
  },
  {
    "path": "weights/face_expression_model-weights_manifest.json",
    "content": "[{\"weights\":[{\"name\":\"dense0/conv0/filters\",\"shape\":[3,3,3,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0057930146946626555,\"min\":-0.7125408074435067}},{\"name\":\"dense0/conv0/bias\",\"shape\":[32],\"dtype\":\"float32\"},{\"name\":\"dense0/conv1/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006473719839956246,\"min\":-0.6408982641556684}},{\"name\":\"dense0/conv1/pointwise_filter\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010509579321917366,\"min\":-1.408283629136927}},{\"name\":\"dense0/conv1/bias\",\"shape\":[32],\"dtype\":\"float32\"},{\"name\":\"dense0/conv2/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005666389652326995,\"min\":-0.7252978754978554}},{\"name\":\"dense0/conv2/pointwise_filter\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010316079270605948,\"min\":-1.1760330368490781}},{\"name\":\"dense0/conv2/bias\",\"shape\":[32],\"dtype\":\"float32\"},{\"name\":\"dense0/conv3/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0063220320963392074,\"min\":-0.853474333005793}},{\"name\":\"dense0/conv3/pointwise_filter\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010322785377502442,\"min\":-1.4658355236053466}},{\"name\":\"dense0/conv3/bias\",\"shape\":[32],\"dtype\":\"float32\"},{\"name\":\"dense1/conv0/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0042531527724920535,\"min\":-0.5741756242864272}},{\"name\":\"dense1/conv0/pointwise_filter\",\"shape\":[1,1,32,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010653339647779278,\"min\":-1.1825207009035}},{\"name\":\"dense1/conv0/bias\",\"shape\":[64],\"dtype\":\"float32\"},{\"name\":\"dense1/conv1/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005166931012097527,\"min\":-0.6355325144879957}},{\"name\":\"dense1/conv1/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.011478300188101974,\"min\":-1.3888743227603388}},{\"name\":\"dense1/conv1/bias\",\"shape\":[64],\"dtype\":\"float32\"},{\"name\":\"dense1/conv2/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006144821410085641,\"min\":-0.8479853545918185}},{\"name\":\"dense1/conv2/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010541967317169788,\"min\":-1.3809977185492421}},{\"name\":\"dense1/conv2/bias\",\"shape\":[64],\"dtype\":\"float32\"},{\"name\":\"dense1/conv3/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005769844849904378,\"min\":-0.686611537138621}},{\"name\":\"dense1/conv3/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010939095534530341,\"min\":-1.2689350820055196}},{\"name\":\"dense1/conv3/bias\",\"shape\":[64],\"dtype\":\"float32\"},{\"name\":\"dense2/conv0/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0037769308277204924,\"min\":-0.40790852939381317}},{\"name\":\"dense2/conv0/pointwise_filter\",\"shape\":[1,1,64,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.01188667194516051,\"min\":-1.4382873053644218}},{\"name\":\"dense2/conv0/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"dense2/conv1/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006497045825509464,\"min\":-0.8381189114907208}},{\"name\":\"dense2/conv1/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.011632198913424622,\"min\":-1.3377028750438316}},{\"name\":\"dense2/conv1/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"dense2/conv2/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005947182225246056,\"min\":-0.7969224181829715}},{\"name\":\"dense2/conv2/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.011436844339557722,\"min\":-1.4524792311238306}},{\"name\":\"dense2/conv2/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"dense2/conv3/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006665432686899222,\"min\":-0.8998334127313949}},{\"name\":\"dense2/conv3/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.01283421422920975,\"min\":-1.642779421338848}},{\"name\":\"dense2/conv3/bias\",\"shape\":[128],\"dtype\":\"float32\"},{\"name\":\"dense3/conv0/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004711699953266218,\"min\":-0.6737730933170692}},{\"name\":\"dense3/conv0/pointwise_filter\",\"shape\":[1,1,128,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010955964817720302,\"min\":-1.3914075318504784}},{\"name\":\"dense3/conv0/bias\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"dense3/conv1/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00554193468654857,\"min\":-0.7149095745647656}},{\"name\":\"dense3/conv1/pointwise_filter\",\"shape\":[1,1,256,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.016790372250126858,\"min\":-2.484975093018775}},{\"name\":\"dense3/conv1/bias\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"dense3/conv2/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006361540626077091,\"min\":-0.8142772001378676}},{\"name\":\"dense3/conv2/pointwise_filter\",\"shape\":[1,1,256,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.01777329678628959,\"min\":-1.7062364914838006}},{\"name\":\"dense3/conv2/bias\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"dense3/conv3/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006900275922289082,\"min\":-0.8625344902861353}},{\"name\":\"dense3/conv3/pointwise_filter\",\"shape\":[1,1,256,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.015449936717164282,\"min\":-1.9003422162112067}},{\"name\":\"dense3/conv3/bias\",\"shape\":[256],\"dtype\":\"float32\"},{\"name\":\"fc/weights\",\"shape\":[256,7],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004834276554631252,\"min\":-0.7203072066400565}},{\"name\":\"fc/bias\",\"shape\":[7],\"dtype\":\"float32\"}],\"paths\":[\"face_expression_model-shard1\"]}]"
  },
  {
    "path": "weights/face_landmark_68_model-weights_manifest.json",
    "content": "[{\"weights\":[{\"name\":\"dense0/conv0/filters\",\"shape\":[3,3,3,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004853619781194949,\"min\":-0.5872879935245888}},{\"name\":\"dense0/conv0/bias\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004396426443960153,\"min\":-0.7298067896973853}},{\"name\":\"dense0/conv1/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00635151559231328,\"min\":-0.5589333721235686}},{\"name\":\"dense0/conv1/pointwise_filter\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.009354315552057004,\"min\":-1.2628325995276957}},{\"name\":\"dense0/conv1/bias\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0029380727048013726,\"min\":-0.5846764682554731}},{\"name\":\"dense0/conv2/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0049374802439820535,\"min\":-0.6171850304977566}},{\"name\":\"dense0/conv2/pointwise_filter\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.009941946758943446,\"min\":-1.3421628124573652}},{\"name\":\"dense0/conv2/bias\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0030300481062309416,\"min\":-0.5272283704841838}},{\"name\":\"dense0/conv3/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005672684837790097,\"min\":-0.7431217137505026}},{\"name\":\"dense0/conv3/pointwise_filter\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010712201455060173,\"min\":-1.5639814124387852}},{\"name\":\"dense0/conv3/bias\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0030966934035806097,\"min\":-0.3839899820439956}},{\"name\":\"dense1/conv0/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0039155554537679636,\"min\":-0.48161332081345953}},{\"name\":\"dense1/conv0/pointwise_filter\",\"shape\":[1,1,32,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.01023082966898002,\"min\":-1.094698774580862}},{\"name\":\"dense1/conv0/bias\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0027264176630506327,\"min\":-0.3871513081531898}},{\"name\":\"dense1/conv1/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004583378632863362,\"min\":-0.5454220573107401}},{\"name\":\"dense1/conv1/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00915846403907327,\"min\":-1.117332612766939}},{\"name\":\"dense1/conv1/bias\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.003091680419211294,\"min\":-0.5966943209077797}},{\"name\":\"dense1/conv2/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005407439727409214,\"min\":-0.708374604290607}},{\"name\":\"dense1/conv2/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00946493943532308,\"min\":-1.2399070660273235}},{\"name\":\"dense1/conv2/bias\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004409168514550901,\"min\":-0.9788354102303}},{\"name\":\"dense1/conv3/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004478132958505668,\"min\":-0.6493292789833219}},{\"name\":\"dense1/conv3/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.011063695888893277,\"min\":-1.2501976354449402}},{\"name\":\"dense1/conv3/bias\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.003909627596537272,\"min\":-0.6646366914113363}},{\"name\":\"dense2/conv0/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.003213915404151468,\"min\":-0.3374611174359041}},{\"name\":\"dense2/conv0/pointwise_filter\",\"shape\":[1,1,64,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010917326048308728,\"min\":-1.4520043644250609}},{\"name\":\"dense2/conv0/bias\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.002800439152063108,\"min\":-0.38085972468058266}},{\"name\":\"dense2/conv1/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0050568851770139206,\"min\":-0.6927932692509071}},{\"name\":\"dense2/conv1/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.01074961213504567,\"min\":-1.3222022926106174}},{\"name\":\"dense2/conv1/bias\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0030654204242369708,\"min\":-0.5487102559384177}},{\"name\":\"dense2/conv2/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00591809165244009,\"min\":-0.917304206128214}},{\"name\":\"dense2/conv2/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.01092823346455892,\"min\":-1.366029183069865}},{\"name\":\"dense2/conv2/bias\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.002681120470458386,\"min\":-0.36463238398234055}},{\"name\":\"dense2/conv3/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0048311497650894465,\"min\":-0.5797379718107336}},{\"name\":\"dense2/conv3/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.011227761062921263,\"min\":-1.4483811771168429}},{\"name\":\"dense2/conv3/bias\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0034643323982463162,\"min\":-0.3360402426298927}},{\"name\":\"dense3/conv0/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.003394978887894574,\"min\":-0.49227193874471326}},{\"name\":\"dense3/conv0/pointwise_filter\",\"shape\":[1,1,128,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010051267287310432,\"min\":-1.2765109454884247}},{\"name\":\"dense3/conv0/bias\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.003142924752889895,\"min\":-0.4588670139219247}},{\"name\":\"dense3/conv1/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00448304671867221,\"min\":-0.5872791201460595}},{\"name\":\"dense3/conv1/pointwise_filter\",\"shape\":[1,1,256,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.016063522357566685,\"min\":-2.3613377865623026}},{\"name\":\"dense3/conv1/bias\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00287135781026354,\"min\":-0.47664539650374765}},{\"name\":\"dense3/conv2/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006002906724518421,\"min\":-0.7923836876364315}},{\"name\":\"dense3/conv2/pointwise_filter\",\"shape\":[1,1,256,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.017087187019048954,\"min\":-1.6061955797906016}},{\"name\":\"dense3/conv2/bias\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.003124481205846749,\"min\":-0.46242321846531886}},{\"name\":\"dense3/conv3/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006576311588287353,\"min\":-1.0193282961845398}},{\"name\":\"dense3/conv3/pointwise_filter\",\"shape\":[1,1,256,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.015590153955945782,\"min\":-1.99553970636106}},{\"name\":\"dense3/conv3/bias\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004453541601405424,\"min\":-0.6546706154065973}},{\"name\":\"fc/weights\",\"shape\":[256,136],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.010417488509533453,\"min\":-1.500118345372817}},{\"name\":\"fc/bias\",\"shape\":[136],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0025084222648658005,\"min\":0.07683877646923065}}],\"paths\":[\"face_landmark_68_model-shard1\"]}]"
  },
  {
    "path": "weights/face_landmark_68_tiny_model-weights_manifest.json",
    "content": "[{\"weights\":[{\"name\":\"dense0/conv0/filters\",\"shape\":[3,3,3,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.008194216092427571,\"min\":-0.9423348506291708}},{\"name\":\"dense0/conv0/bias\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006839508168837603,\"min\":-0.8412595047670252}},{\"name\":\"dense0/conv1/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.009194007106855804,\"min\":-1.2779669878529567}},{\"name\":\"dense0/conv1/pointwise_filter\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0036026100317637128,\"min\":-0.3170296827952067}},{\"name\":\"dense0/conv1/bias\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.000740380117706224,\"min\":-0.06367269012273527}},{\"name\":\"dense0/conv2/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":1,\"min\":0}},{\"name\":\"dense0/conv2/pointwise_filter\",\"shape\":[1,1,32,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":1,\"min\":0}},{\"name\":\"dense0/conv2/bias\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0037702228508743585,\"min\":-0.6220867703942692}},{\"name\":\"dense1/conv0/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0033707996209462483,\"min\":-0.421349952618281}},{\"name\":\"dense1/conv0/pointwise_filter\",\"shape\":[1,1,32,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.014611541991140328,\"min\":-1.8556658328748217}},{\"name\":\"dense1/conv0/bias\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.002832523046755323,\"min\":-0.30307996600281956}},{\"name\":\"dense1/conv1/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006593170586754294,\"min\":-0.6329443763284123}},{\"name\":\"dense1/conv1/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.012215249211180444,\"min\":-1.6001976466646382}},{\"name\":\"dense1/conv1/bias\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.002384825547536214,\"min\":-0.3028728445370992}},{\"name\":\"dense1/conv2/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005859645441466687,\"min\":-0.7617539073906693}},{\"name\":\"dense1/conv2/pointwise_filter\",\"shape\":[1,1,64,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.013121426806730382,\"min\":-1.7845140457153321}},{\"name\":\"dense1/conv2/bias\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0032247188044529336,\"min\":-0.46435950784122243}},{\"name\":\"dense2/conv0/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.002659512618008782,\"min\":-0.32977956463308894}},{\"name\":\"dense2/conv0/pointwise_filter\",\"shape\":[1,1,64,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.015499923743453681,\"min\":-1.9839902391620712}},{\"name\":\"dense2/conv0/bias\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0032450980999890497,\"min\":-0.522460794098237}},{\"name\":\"dense2/conv1/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005911862382701799,\"min\":-0.792189559282041}},{\"name\":\"dense2/conv1/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.021025861478319356,\"min\":-2.2077154552235325}},{\"name\":\"dense2/conv1/bias\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.00349616945958605,\"min\":-0.46149436866535865}},{\"name\":\"dense2/conv2/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.008104994250278847,\"min\":-1.013124281284856}},{\"name\":\"dense2/conv2/pointwise_filter\",\"shape\":[1,1,128,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.029337059282789044,\"min\":-3.5791212325002633}},{\"name\":\"dense2/conv2/bias\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0038808938334969913,\"min\":-0.4230174278511721}},{\"name\":\"fc/weights\",\"shape\":[128,136],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.014016061670639936,\"min\":-1.8921683255363912}},{\"name\":\"fc/bias\",\"shape\":[136],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0029505149698724935,\"min\":0.088760145008564}}],\"paths\":[\"face_landmark_68_tiny_model-shard1\"]}]"
  },
  {
    "path": "weights/tiny_face_detector_model-weights_manifest.json",
    "content": "[{\"weights\":[{\"name\":\"conv0/filters\",\"shape\":[3,3,3,16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.009007044399485869,\"min\":-1.2069439495311063}},{\"name\":\"conv0/bias\",\"shape\":[16],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.005263455241334205,\"min\":-0.9211046672334858}},{\"name\":\"conv1/depthwise_filter\",\"shape\":[3,3,16,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.004001977630690033,\"min\":-0.5042491814669441}},{\"name\":\"conv1/pointwise_filter\",\"shape\":[1,1,16,32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.013836609615999109,\"min\":-1.411334180831909}},{\"name\":\"conv1/bias\",\"shape\":[32],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0015159862590771096,\"min\":-0.30926119685173037}},{\"name\":\"conv2/depthwise_filter\",\"shape\":[3,3,32,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.002666276225856706,\"min\":-0.317286870876948}},{\"name\":\"conv2/pointwise_filter\",\"shape\":[1,1,32,64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.015265831292844286,\"min\":-1.6792414422128714}},{\"name\":\"conv2/bias\",\"shape\":[64],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0020280554598453,\"min\":-0.37113414915168985}},{\"name\":\"conv3/depthwise_filter\",\"shape\":[3,3,64,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006100742489683862,\"min\":-0.8907084034938438}},{\"name\":\"conv3/pointwise_filter\",\"shape\":[1,1,64,128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.016276211832083907,\"min\":-2.0508026908425725}},{\"name\":\"conv3/bias\",\"shape\":[128],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.003394414279975143,\"min\":-0.7637432129944072}},{\"name\":\"conv4/depthwise_filter\",\"shape\":[3,3,128,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.006716050119961009,\"min\":-0.8059260143953211}},{\"name\":\"conv4/pointwise_filter\",\"shape\":[1,1,128,256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.021875603993733724,\"min\":-2.8875797271728514}},{\"name\":\"conv4/bias\",\"shape\":[256],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.0041141652009066415,\"min\":-0.8187188749804216}},{\"name\":\"conv5/depthwise_filter\",\"shape\":[3,3,256,1],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.008423839597141042,\"min\":-0.9013508368940915}},{\"name\":\"conv5/pointwise_filter\",\"shape\":[1,1,256,512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.030007277283014035,\"min\":-3.8709387695088107}},{\"name\":\"conv5/bias\",\"shape\":[512],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.008402082966823203,\"min\":-1.4871686851277068}},{\"name\":\"conv8/filters\",\"shape\":[1,1,512,25],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.028336129469030042,\"min\":-4.675461362389957}},{\"name\":\"conv8/bias\",\"shape\":[25],\"dtype\":\"float32\",\"quantization\":{\"dtype\":\"uint8\",\"scale\":0.002268134028303857,\"min\":-0.41053225912299807}}],\"paths\":[\"tiny_face_detector_model-shard1\"]}]"
  }
]